diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX
index 49c0513..f54273e 100644
--- a/Documentation/00-INDEX
+++ b/Documentation/00-INDEX
@@ -270,8 +270,6 @@ preempt-locking.txt
 	- info on locking under a preemptive kernel.
 printk-formats.txt
 	- how to get printk format specifiers right
-prio_tree.txt
-	- info on radix-priority-search-tree use for indexing vmas.
 ramoops.txt
 	- documentation of the ramoops oops/panic logging module.
 rbtree.txt
diff --git a/Documentation/ABI/obsolete/proc-pid-oom_adj b/Documentation/ABI/obsolete/proc-pid-oom_adj
deleted file mode 100644
index 9a3cb88..0000000
--- a/Documentation/ABI/obsolete/proc-pid-oom_adj
+++ /dev/null
@@ -1,22 +0,0 @@
-What:	/proc/<pid>/oom_adj
-When:	August 2012
-Why:	/proc/<pid>/oom_adj allows userspace to influence the oom killer's
-	badness heuristic used to determine which task to kill when the kernel
-	is out of memory.
-
-	The badness heuristic has since been rewritten since the introduction of
-	this tunable such that its meaning is deprecated.  The value was
-	implemented as a bitshift on a score generated by the badness()
-	function that did not have any precise units of measure.  With the
-	rewrite, the score is given as a proportion of available memory to the
-	task allocating pages, so using a bitshift which grows the score
-	exponentially is, thus, impossible to tune with fine granularity.
-
-	A much more powerful interface, /proc/<pid>/oom_score_adj, was
-	introduced with the oom killer rewrite that allows users to increase or
-	decrease the badness score linearly.  This interface will replace
-	/proc/<pid>/oom_adj.
-
-	A warning will be emitted to the kernel log if an application uses this
-	deprecated interface.  After it is printed once, future warnings will be
-	suppressed until the kernel is rebooted.
diff --git a/Documentation/ABI/testing/ima_policy b/Documentation/ABI/testing/ima_policy
index 6cd6dae..9869466 100644
--- a/Documentation/ABI/testing/ima_policy
+++ b/Documentation/ABI/testing/ima_policy
@@ -12,11 +12,14 @@ Description:
 		then closing the file.  The new policy takes effect after
 		the file ima/policy is closed.
 
+		IMA appraisal, if configured, uses these file measurements
+		for local measurement appraisal.
+
 		rule format: action [condition ...]
 
-		action: measure | dont_measure
+		action: measure | dont_measure | appraise | dont_appraise | audit
 		condition:= base | lsm
-			base:	[[func=] [mask=] [fsmagic=] [uid=]]
+			base:	[[func=] [mask=] [fsmagic=] [uid=] [fowner]]
 			lsm:	[[subj_user=] [subj_role=] [subj_type=]
 				 [obj_user=] [obj_role=] [obj_type=]]
 
@@ -24,36 +27,50 @@ Description:
 			mask:= [MAY_READ] [MAY_WRITE] [MAY_APPEND] [MAY_EXEC]
 			fsmagic:= hex value
 			uid:= decimal value
+			fowner:=decimal value
 		lsm:  	are LSM specific
 
 		default policy:
 			# PROC_SUPER_MAGIC
 			dont_measure fsmagic=0x9fa0
+			dont_appraise fsmagic=0x9fa0
 			# SYSFS_MAGIC
 			dont_measure fsmagic=0x62656572
+			dont_appraise fsmagic=0x62656572
 			# DEBUGFS_MAGIC
 			dont_measure fsmagic=0x64626720
+			dont_appraise fsmagic=0x64626720
 			# TMPFS_MAGIC
 			dont_measure fsmagic=0x01021994
+			dont_appraise fsmagic=0x01021994
+			# RAMFS_MAGIC
+			dont_measure fsmagic=0x858458f6
+			dont_appraise fsmagic=0x858458f6
 			# SECURITYFS_MAGIC
 			dont_measure fsmagic=0x73636673
+			dont_appraise fsmagic=0x73636673
 
 			measure func=BPRM_CHECK
 			measure func=FILE_MMAP mask=MAY_EXEC
 			measure func=FILE_CHECK mask=MAY_READ uid=0
+			appraise fowner=0
 
 		The default policy measures all executables in bprm_check,
 		all files mmapped executable in file_mmap, and all files
-		open for read by root in do_filp_open.
+		open for read by root in do_filp_open.  The default appraisal
+		policy appraises all files owned by root.
 
 		Examples of LSM specific definitions:
 
 		SELinux:
 			# SELINUX_MAGIC
-			dont_measure fsmagic=0xF97CFF8C
+			dont_measure fsmagic=0xf97cff8c
+			dont_appraise fsmagic=0xf97cff8c
 
 			dont_measure obj_type=var_log_t
+			dont_appraise obj_type=var_log_t
 			dont_measure obj_type=auditd_log_t
+			dont_appraise obj_type=auditd_log_t
 			measure subj_user=system_u func=FILE_CHECK mask=MAY_READ
 			measure subj_role=system_r func=FILE_CHECK mask=MAY_READ
 
diff --git a/Documentation/ABI/testing/sysfs-block b/Documentation/ABI/testing/sysfs-block
index c1eb41c..279da08 100644
--- a/Documentation/ABI/testing/sysfs-block
+++ b/Documentation/ABI/testing/sysfs-block
@@ -206,3 +206,17 @@ Description:
 		when a discarded area is read the discard_zeroes_data
 		parameter will be set to one. Otherwise it will be 0 and
 		the result of reading a discarded area is undefined.
+
+What:		/sys/block/<disk>/queue/write_same_max_bytes
+Date:		January 2012
+Contact:	Martin K. Petersen <martin.petersen@oracle.com>
+Description:
+		Some devices support a write same operation in which a
+		single data block can be written to a range of several
+		contiguous blocks on storage. This can be used to wipe
+		areas on disk or to initialize drives in a RAID
+		configuration. write_same_max_bytes indicates how many
+		bytes can be written in a single write same command. If
+		write_same_max_bytes is 0, write same is not supported
+		by the device.
+
diff --git a/Documentation/ABI/testing/sysfs-bus-usb b/Documentation/ABI/testing/sysfs-bus-usb
index 5f75f8f..b6fbe51 100644
--- a/Documentation/ABI/testing/sysfs-bus-usb
+++ b/Documentation/ABI/testing/sysfs-bus-usb
@@ -220,3 +220,10 @@ Description:
 		If the device doesn't support LTM, the file will read "no".
 		The file will be present for all speeds of USB devices, and will
 		always read "no" for USB 1.1 and USB 2.0 devices.
+
+What:		/sys/bus/usb/devices/.../(hub interface)/portX
+Date:		August 2012
+Contact:	Lan Tianyu <tianyu.lan@intel.com>
+Description:
+		The /sys/bus/usb/devices/.../(hub interface)/portX
+		is usb port device's sysfs directory.
diff --git a/Documentation/ABI/testing/sysfs-class-extcon b/Documentation/ABI/testing/sysfs-class-extcon
index 20ab361..57a7262 100644
--- a/Documentation/ABI/testing/sysfs-class-extcon
+++ b/Documentation/ABI/testing/sysfs-class-extcon
@@ -13,7 +13,7 @@ Description:
 		accessory cables have such capability. For example,
 		the 30-pin port of Nuri board (/arch/arm/mach-exynos)
 		may have both HDMI and Charger attached, or analog audio,
-		video, and USB cables attached simulteneously.
+		video, and USB cables attached simultaneously.
 
 		If there are cables mutually exclusive with each other,
 		such binary relations may be expressed with extcon_dev's
@@ -35,7 +35,7 @@ Description:
 		The /sys/class/extcon/.../state shows and stores the cable
 		attach/detach information of the corresponding extcon object.
 		If the extcon object has an optional callback "show_state"
-		defined, the showing function is overriden with the optional
+		defined, the showing function is overridden with the optional
 		callback.
 
 		If the default callback for showing function is used, the
@@ -46,19 +46,19 @@ Description:
 		TA=1
 		EAR_JACK=0
 		#
-		In this example, the extcon device have USB_OTG and TA
+		In this example, the extcon device has USB_OTG and TA
 		cables attached and HDMI and EAR_JACK cables detached.
 
 		In order to update the state of an extcon device, enter a hex
-		state number starting with 0x.
-		 echo 0xHEX > state
+		state number starting with 0x:
+		# echo 0xHEX > state
 
-		This updates the whole state of the extcon dev.
+		This updates the whole state of the extcon device.
 		Inputs of all the methods are required to meet the
-		mutually_exclusive contidions if they exist.
+		mutually_exclusive conditions if they exist.
 
 		It is recommended to use this "global" state interface if
-		you need to enter the value atomically. The later state
+		you need to set the value atomically. The later state
 		interface associated with each cable cannot update
 		multiple cable states of an extcon device simultaneously.
 
@@ -73,7 +73,7 @@ What:		/sys/class/extcon/.../cable.x/state
 Date:		February 2012
 Contact:	MyungJoo Ham <myungjoo.ham@samsung.com>
 Description:
-		The /sys/class/extcon/.../cable.x/name shows and stores the
+		The /sys/class/extcon/.../cable.x/state shows and stores the
 		state of cable "x" (integer between 0 and 31) of an extcon
 		device. The state value is either 0 (detached) or 1
 		(attached).
@@ -83,8 +83,8 @@ Date:		December 2011
 Contact:	MyungJoo Ham <myungjoo.ham@samsung.com>
 Description:
 		Shows the relations of mutually exclusiveness. For example,
-		if the mutually_exclusive array of extcon_dev is
-		{0x3, 0x5, 0xC, 0x0}, the, the output is:
+		if the mutually_exclusive array of extcon device is
+		{0x3, 0x5, 0xC, 0x0}, then the output is:
 		# ls mutually_exclusive/
 		0x3
 		0x5
diff --git a/Documentation/ABI/testing/sysfs-class-regulator b/Documentation/ABI/testing/sysfs-class-regulator
index e091fa8..bc578bc 100644
--- a/Documentation/ABI/testing/sysfs-class-regulator
+++ b/Documentation/ABI/testing/sysfs-class-regulator
@@ -349,3 +349,24 @@ Description:
 
 		This will be one of the same strings reported by
 		the "state" attribute.
+
+What:		/sys/class/regulator/.../bypass
+Date:		September 2012
+KernelVersion:	3.7
+Contact:	Mark Brown <broonie@opensource.wolfsonmicro.com>
+Description:
+		Some regulator directories will contain a field called
+		bypass.  This indicates if the device is in bypass mode.
+
+		This will be one of the following strings:
+
+		'enabled'
+		'disabled'
+		'unknown'
+
+		'enabled' means the regulator is in bypass mode.
+
+		'disabled' means that the regulator is regulating.
+
+		'unknown' means software cannot determine the state, or
+		the reported state is invalid.
diff --git a/Documentation/ABI/testing/sysfs-devices-system-cpu b/Documentation/ABI/testing/sysfs-devices-system-cpu
index 5dab364..6943133 100644
--- a/Documentation/ABI/testing/sysfs-devices-system-cpu
+++ b/Documentation/ABI/testing/sysfs-devices-system-cpu
@@ -176,3 +176,14 @@ Description:	Disable L3 cache indices
 		All AMD processors with L3 caches provide this functionality.
 		For details, see BKDGs at
 		http://developer.amd.com/documentation/guides/Pages/default.aspx
+
+
+What:		/sys/devices/system/cpu/cpufreq/boost
+Date:		August 2012
+Contact:	Linux kernel mailing list <linux-kernel@vger.kernel.org>
+Description:	Processor frequency boosting control
+
+		This switch controls the boost setting for the whole system.
+		Boosting allows the CPU and the firmware to run at a frequency
+		beyound it's nominal limit.
+		More details can be found in Documentation/cpu-freq/boost.txt
diff --git a/Documentation/ABI/testing/sysfs-driver-ppi b/Documentation/ABI/testing/sysfs-driver-ppi
new file mode 100644
index 0000000..97a003e
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-driver-ppi
@@ -0,0 +1,70 @@
+What:		/sys/devices/pnp0/<bus-num>/ppi/
+Date:		August 2012
+Kernel Version:	3.6
+Contact:	xiaoyan.zhang@intel.com
+Description:
+		This folder includes the attributes related with PPI (Physical
+		Presence Interface). Only if TPM is supported by BIOS, this
+		folder makes sence. The folder path can be got by command
+		'find /sys/ -name 'pcrs''. For the detail information of PPI,
+		please refer to the PPI specification from
+		http://www.trustedcomputinggroup.org/
+
+What:		/sys/devices/pnp0/<bus-num>/ppi/version
+Date:		August 2012
+Contact:	xiaoyan.zhang@intel.com
+Description:
+		This attribute shows the version of the PPI supported by the
+		platform.
+		This file is readonly.
+
+What:		/sys/devices/pnp0/<bus-num>/ppi/request
+Date:		August 2012
+Contact:	xiaoyan.zhang@intel.com
+Description:
+		This attribute shows the request for an operation to be
+		executed in the pre-OS environment. It is the only input from
+		the OS to the pre-OS environment. The request should be an
+		integer value range from 1 to 160, and 0 means no request.
+		This file can be read and written.
+
+What:		/sys/devices/pnp0/00:<bus-num>/ppi/response
+Date:		August 2012
+Contact:	xiaoyan.zhang@intel.com
+Description:
+		This attribute shows the response to the most recent operation
+		request it acted upon. The format is "<request> <response num>
+		: <response description>".
+		This file is readonly.
+
+What:		/sys/devices/pnp0/<bus-num>/ppi/transition_action
+Date:		August 2012
+Contact:	xiaoyan.zhang@intel.com
+Description:
+		This attribute shows the platform-specific action that should
+		take place in order to transition to the BIOS for execution of
+		a requested operation. The format is "<action num>: <action
+		description>".
+		This file is readonly.
+
+What:		/sys/devices/pnp0/<bus-num>/ppi/tcg_operations
+Date:		August 2012
+Contact:	xiaoyan.zhang@intel.com
+Description:
+		This attribute shows whether it is allowed to request an
+		operation to be executed in the pre-OS environment by the BIOS
+		for the requests defined by TCG, i.e. requests from 1 to 22.
+		The format is "<request> <status num>: <status description>".
+		This attribute is only supported by PPI version 1.2+.
+		This file is readonly.
+
+What:		/sys/devices/pnp0/<bus-num>/ppi/vs_operations
+Date:		August 2012
+Contact:	xiaoyan.zhang@intel.com
+Description:
+		This attribute shows whether it is allowed to request an
+		operation to be executed in the pre-OS environment by the BIOS
+		for the verdor specific requests, i.e. requests from 128 to
+		255. The format is same with tcg_operations. This attribute
+		is also only supported by PPI version 1.2+.
+		This file is readonly.
diff --git a/Documentation/ABI/testing/sysfs-driver-wacom b/Documentation/ABI/testing/sysfs-driver-wacom
index 8d55a83..7fc7810 100644
--- a/Documentation/ABI/testing/sysfs-driver-wacom
+++ b/Documentation/ABI/testing/sysfs-driver-wacom
@@ -1,3 +1,16 @@
+WWhat:		/sys/class/hidraw/hidraw*/device/oled*_img
+Date:		June 2012
+Contact:	linux-bluetooth@vger.kernel.org
+Description:
+		The /sys/class/hidraw/hidraw*/device/oled*_img files control
+		OLED mocro displays on Intuos4 Wireless tablet. Accepted image
+		has to contain 256 bytes (64x32 px 1 bit colour). The format
+		is the same as PBM image 62x32px without header (64 bits per
+		horizontal line, 32 lines). An example of setting OLED No. 0:
+		dd bs=256 count=1 if=img_file of=[path to oled0_img]/oled0_img
+		The attribute is read only and no local copy of the image is
+		stored.
+
 What:		/sys/class/hidraw/hidraw*/device/speed
 Date:		April 2010
 Kernel Version:	2.6.35
diff --git a/Documentation/ABI/testing/sysfs-fs-ext4 b/Documentation/ABI/testing/sysfs-fs-ext4
index f22ac08..c631253 100644
--- a/Documentation/ABI/testing/sysfs-fs-ext4
+++ b/Documentation/ABI/testing/sysfs-fs-ext4
@@ -96,3 +96,16 @@ Contact:	"Theodore Ts'o" <tytso@mit.edu>
 Description:
 		The maximum number of megabytes the writeback code will
 		try to write out before move on to another inode.
+
+What:		/sys/fs/ext4/<disk>/extent_max_zeroout_kb
+Date:		August 2012
+Contact:	"Theodore Ts'o" <tytso@mit.edu>
+Description:
+		The maximum number of kilobytes which will be zeroed
+		out in preference to creating a new uninitialized
+		extent when manipulating an inode's extent tree.  Note
+		that using a larger value will increase the
+		variability of time necessary to complete a random
+		write operation (since a 4k random write might turn
+		into a much larger write due to the zeroout
+		operation).
diff --git a/Documentation/ABI/testing/sysfs-ptp b/Documentation/ABI/testing/sysfs-ptp
index d40d2b5..05aeedf 100644
--- a/Documentation/ABI/testing/sysfs-ptp
+++ b/Documentation/ABI/testing/sysfs-ptp
@@ -19,7 +19,11 @@ Date:		September 2010
 Contact:	Richard Cochran <richardcochran@gmail.com>
 Description:
 		This file contains the name of the PTP hardware clock
-		as a human readable string.
+		as a human readable string. The purpose of this
+		attribute is to provide the user with a "friendly
+		name" and to help distinguish PHY based devices from
+		MAC based ones. The string does not necessarily have
+		to be any kind of unique id.
 
 What:		/sys/class/ptp/ptpN/max_adjustment
 Date:		September 2010
diff --git a/Documentation/ABI/testing/sysfs-tty b/Documentation/ABI/testing/sysfs-tty
index b138b66..0c43015 100644
--- a/Documentation/ABI/testing/sysfs-tty
+++ b/Documentation/ABI/testing/sysfs-tty
@@ -17,3 +17,12 @@ Description:
 		 device, like 'tty1'.
 		 The file supports poll() to detect virtual
 		 console switches.
+
+What:		/sys/class/tty/ttyS0/uartclk
+Date:		Sep 2012
+Contact:	Tomas Hlavacek <tmshlvck@gmail.com>
+Description:
+		 Shows the current uartclk value associated with the
+		 UART port in serial_core, that is bound to TTY like ttyS0.
+		 uartclk = 16 * baud_base
+
diff --git a/Documentation/CodingStyle b/Documentation/CodingStyle
index cb9258b..495e5ba 100644
--- a/Documentation/CodingStyle
+++ b/Documentation/CodingStyle
@@ -454,6 +454,16 @@ The preferred style for long (multi-line) comments is:
 	 * with beginning and ending almost-blank lines.
 	 */
 
+For files in net/ and drivers/net/ the preferred style for long (multi-line)
+comments is a little different.
+
+	/* The preferred comment style for files in net/ and drivers/net
+	 * looks like this.
+	 *
+	 * It is nearly the same as the generally preferred comment style,
+	 * but there is no initial almost-blank line.
+	 */
+
 It's also important to comment data, whether they are basic types or derived
 types.  To this end, use just one data declaration per line (no commas for
 multiple data declarations).  This leaves you room for a small comment on each
diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl
index 196b8b9..b030052 100644
--- a/Documentation/DocBook/drm.tmpl
+++ b/Documentation/DocBook/drm.tmpl
@@ -6,11 +6,36 @@
   <bookinfo>
     <title>Linux DRM Developer's Guide</title>
 
+    <authorgroup>
+      <author>
+	<firstname>Jesse</firstname>
+	<surname>Barnes</surname>
+	<contrib>Initial version</contrib>
+	<affiliation>
+	  <orgname>Intel Corporation</orgname>
+	  <address>
+	    <email>jesse.barnes@intel.com</email>
+	  </address>
+	</affiliation>
+      </author>
+      <author>
+	<firstname>Laurent</firstname>
+	<surname>Pinchart</surname>
+	<contrib>Driver internals</contrib>
+	<affiliation>
+	  <orgname>Ideas on board SPRL</orgname>
+	  <address>
+	    <email>laurent.pinchart@ideasonboard.com</email>
+	  </address>
+	</affiliation>
+      </author>
+    </authorgroup>
+
     <copyright>
       <year>2008-2009</year>
-      <holder>
-	Intel Corporation (Jesse Barnes &lt;jesse.barnes@intel.com&gt;)
-      </holder>
+      <year>2012</year>
+      <holder>Intel Corporation</holder>
+      <holder>Laurent Pinchart</holder>
     </copyright>
 
     <legalnotice>
@@ -20,6 +45,17 @@
 	the kernel source COPYING file.
       </para>
     </legalnotice>
+
+    <revhistory>
+      <!-- Put document revisions here, newest first. -->
+      <revision>
+	<revnumber>1.0</revnumber>
+	<date>2012-07-13</date>
+	<authorinitials>LP</authorinitials>
+	<revremark>Added extensive documentation about driver internals.
+	</revremark>
+      </revision>
+    </revhistory>
   </bookinfo>
 
 <toc></toc>
@@ -72,342 +108,361 @@
       submission &amp; fencing, suspend/resume support, and DMA
       services.
     </para>
-    <para>
-      The core of every DRM driver is struct drm_driver.  Drivers
-      typically statically initialize a drm_driver structure,
-      then pass it to drm_init() at load time.
-    </para>
 
   <!-- Internals: driver init -->
 
   <sect1>
-    <title>Driver initialization</title>
-    <para>
-      Before calling the DRM initialization routines, the driver must
-      first create and fill out a struct drm_driver structure.
-    </para>
-    <programlisting>
-      static struct drm_driver driver = {
-	/* Don't use MTRRs here; the Xserver or userspace app should
-	 * deal with them for Intel hardware.
-	 */
-	.driver_features =
-	    DRIVER_USE_AGP | DRIVER_REQUIRE_AGP |
-	    DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_MODESET,
-	.load = i915_driver_load,
-	.unload = i915_driver_unload,
-	.firstopen = i915_driver_firstopen,
-	.lastclose = i915_driver_lastclose,
-	.preclose = i915_driver_preclose,
-	.save = i915_save,
-	.restore = i915_restore,
-	.device_is_agp = i915_driver_device_is_agp,
-	.get_vblank_counter = i915_get_vblank_counter,
-	.enable_vblank = i915_enable_vblank,
-	.disable_vblank = i915_disable_vblank,
-	.irq_preinstall = i915_driver_irq_preinstall,
-	.irq_postinstall = i915_driver_irq_postinstall,
-	.irq_uninstall = i915_driver_irq_uninstall,
-	.irq_handler = i915_driver_irq_handler,
-	.reclaim_buffers = drm_core_reclaim_buffers,
-	.get_map_ofs = drm_core_get_map_ofs,
-	.get_reg_ofs = drm_core_get_reg_ofs,
-	.fb_probe = intelfb_probe,
-	.fb_remove = intelfb_remove,
-	.fb_resize = intelfb_resize,
-	.master_create = i915_master_create,
-	.master_destroy = i915_master_destroy,
-#if defined(CONFIG_DEBUG_FS)
-	.debugfs_init = i915_debugfs_init,
-	.debugfs_cleanup = i915_debugfs_cleanup,
-#endif
-	.gem_init_object = i915_gem_init_object,
-	.gem_free_object = i915_gem_free_object,
-	.gem_vm_ops = &amp;i915_gem_vm_ops,
-	.ioctls = i915_ioctls,
-	.fops = {
-		.owner = THIS_MODULE,
-		.open = drm_open,
-		.release = drm_release,
-		.ioctl = drm_ioctl,
-		.mmap = drm_mmap,
-		.poll = drm_poll,
-		.fasync = drm_fasync,
-#ifdef CONFIG_COMPAT
-		.compat_ioctl = i915_compat_ioctl,
-#endif
-		.llseek = noop_llseek,
-		},
-	.pci_driver = {
-		.name = DRIVER_NAME,
-		.id_table = pciidlist,
-		.probe = probe,
-		.remove = __devexit_p(drm_cleanup_pci),
-		},
-	.name = DRIVER_NAME,
-	.desc = DRIVER_DESC,
-	.date = DRIVER_DATE,
-	.major = DRIVER_MAJOR,
-	.minor = DRIVER_MINOR,
-	.patchlevel = DRIVER_PATCHLEVEL,
-      };
-    </programlisting>
-    <para>
-      In the example above, taken from the i915 DRM driver, the driver
-      sets several flags indicating what core features it supports;
-      we go over the individual callbacks in later sections.  Since
-      flags indicate which features your driver supports to the DRM
-      core, you need to set most of them prior to calling drm_init().  Some,
-      like DRIVER_MODESET can be set later based on user supplied parameters,
-      but that's the exception rather than the rule.
-    </para>
-    <variablelist>
-      <title>Driver flags</title>
-      <varlistentry>
-	<term>DRIVER_USE_AGP</term>
-	<listitem><para>
-	    Driver uses AGP interface
-	</para></listitem>
-      </varlistentry>
-      <varlistentry>
-	<term>DRIVER_REQUIRE_AGP</term>
-	<listitem><para>
-	    Driver needs AGP interface to function.
-	</para></listitem>
-      </varlistentry>
-      <varlistentry>
-	<term>DRIVER_USE_MTRR</term>
-	<listitem>
-	  <para>
-	    Driver uses MTRR interface for mapping memory.  Deprecated.
-	  </para>
-	</listitem>
-      </varlistentry>
-      <varlistentry>
-	<term>DRIVER_PCI_DMA</term>
-	<listitem><para>
-	    Driver is capable of PCI DMA.  Deprecated.
-	</para></listitem>
-      </varlistentry>
-      <varlistentry>
-	<term>DRIVER_SG</term>
-	<listitem><para>
-	    Driver can perform scatter/gather DMA.  Deprecated.
-	</para></listitem>
-      </varlistentry>
-      <varlistentry>
-	<term>DRIVER_HAVE_DMA</term>
-	<listitem><para>Driver supports DMA.  Deprecated.</para></listitem>
-      </varlistentry>
-      <varlistentry>
-	<term>DRIVER_HAVE_IRQ</term><term>DRIVER_IRQ_SHARED</term>
-	<listitem>
-	  <para>
-	    DRIVER_HAVE_IRQ indicates whether the driver has an IRQ
-	    handler.  DRIVER_IRQ_SHARED indicates whether the device &amp;
-	    handler support shared IRQs (note that this is required of
-	    PCI drivers).
-	  </para>
-	</listitem>
-      </varlistentry>
-      <varlistentry>
-	<term>DRIVER_DMA_QUEUE</term>
-	<listitem>
-	  <para>
-	    Should be set if the driver queues DMA requests and completes them
-	    asynchronously.  Deprecated.
-	  </para>
-	</listitem>
-      </varlistentry>
-      <varlistentry>
-	<term>DRIVER_FB_DMA</term>
-	<listitem>
-	  <para>
-	    Driver supports DMA to/from the framebuffer.  Deprecated.
-	  </para>
-	</listitem>
-      </varlistentry>
-      <varlistentry>
-	<term>DRIVER_MODESET</term>
-	<listitem>
-	  <para>
-	    Driver supports mode setting interfaces.
-	  </para>
-	</listitem>
-      </varlistentry>
-    </variablelist>
-    <para>
-      In this specific case, the driver requires AGP and supports
-      IRQs.  DMA, as discussed later, is handled by device-specific ioctls
-      in this case.  It also supports the kernel mode setting APIs, though
-      unlike in the actual i915 driver source, this example unconditionally
-      exports KMS capability.
+    <title>Driver Initialization</title>
+    <para>
+      At the core of every DRM driver is a <structname>drm_driver</structname>
+      structure. Drivers typically statically initialize a drm_driver structure,
+      and then pass it to one of the <function>drm_*_init()</function> functions
+      to register it with the DRM subsystem.
     </para>
-  </sect1>
-
-  <!-- Internals: driver load -->
-
-  <sect1>
-    <title>Driver load</title>
-    <para>
-      In the previous section, we saw what a typical drm_driver
-      structure might look like.  One of the more important fields in
-      the structure is the hook for the load function.
-    </para>
-    <programlisting>
-      static struct drm_driver driver = {
-      	...
-      	.load = i915_driver_load,
-        ...
-      };
-    </programlisting>
-    <para>
-      The load function has many responsibilities: allocating a driver
-      private structure, specifying supported performance counters,
-      configuring the device (e.g. mapping registers &amp; command
-      buffers), initializing the memory manager, and setting up the
-      initial output configuration.
-    </para>
-    <para>
-      If compatibility is a concern (e.g. with drivers converted over
-      to the new interfaces from the old ones), care must be taken to
-      prevent device initialization and control that is incompatible with
-      currently active userspace drivers.  For instance, if user
-      level mode setting drivers are in use, it would be problematic
-      to perform output discovery &amp; configuration at load time.
-      Likewise, if user-level drivers unaware of memory management are
-      in use, memory management and command buffer setup may need to
-      be omitted.  These requirements are driver-specific, and care
-      needs to be taken to keep both old and new applications and
-      libraries working.  The i915 driver supports the "modeset"
-      module parameter to control whether advanced features are
-      enabled at load time or in legacy fashion.
+    <para>
+      The <structname>drm_driver</structname> structure contains static
+      information that describes the driver and features it supports, and
+      pointers to methods that the DRM core will call to implement the DRM API.
+      We will first go through the <structname>drm_driver</structname> static
+      information fields, and will then describe individual operations in
+      details as they get used in later sections.
     </para>
-
     <sect2>
-      <title>Driver private &amp; performance counters</title>
-      <para>
-	The driver private hangs off the main drm_device structure and
-	can be used for tracking various device-specific bits of
-	information, like register offsets, command buffer status,
-	register state for suspend/resume, etc.  At load time, a
-	driver may simply allocate one and set drm_device.dev_priv
-	appropriately; it should be freed and drm_device.dev_priv set
-	to NULL when the driver is unloaded.
-      </para>
+      <title>Driver Information</title>
+      <sect3>
+        <title>Driver Features</title>
+        <para>
+          Drivers inform the DRM core about their requirements and supported
+          features by setting appropriate flags in the
+          <structfield>driver_features</structfield> field. Since those flags
+          influence the DRM core behaviour since registration time, most of them
+          must be set to registering the <structname>drm_driver</structname>
+          instance.
+        </para>
+        <synopsis>u32 driver_features;</synopsis>
+        <variablelist>
+          <title>Driver Feature Flags</title>
+          <varlistentry>
+            <term>DRIVER_USE_AGP</term>
+            <listitem><para>
+              Driver uses AGP interface, the DRM core will manage AGP resources.
+            </para></listitem>
+          </varlistentry>
+          <varlistentry>
+            <term>DRIVER_REQUIRE_AGP</term>
+            <listitem><para>
+              Driver needs AGP interface to function. AGP initialization failure
+              will become a fatal error.
+            </para></listitem>
+          </varlistentry>
+          <varlistentry>
+            <term>DRIVER_USE_MTRR</term>
+            <listitem><para>
+              Driver uses MTRR interface for mapping memory, the DRM core will
+              manage MTRR resources. Deprecated.
+            </para></listitem>
+          </varlistentry>
+          <varlistentry>
+            <term>DRIVER_PCI_DMA</term>
+            <listitem><para>
+              Driver is capable of PCI DMA, mapping of PCI DMA buffers to
+              userspace will be enabled. Deprecated.
+            </para></listitem>
+          </varlistentry>
+          <varlistentry>
+            <term>DRIVER_SG</term>
+            <listitem><para>
+              Driver can perform scatter/gather DMA, allocation and mapping of
+              scatter/gather buffers will be enabled. Deprecated.
+            </para></listitem>
+          </varlistentry>
+          <varlistentry>
+            <term>DRIVER_HAVE_DMA</term>
+            <listitem><para>
+              Driver supports DMA, the userspace DMA API will be supported.
+              Deprecated.
+            </para></listitem>
+          </varlistentry>
+          <varlistentry>
+            <term>DRIVER_HAVE_IRQ</term><term>DRIVER_IRQ_SHARED</term>
+            <listitem><para>
+              DRIVER_HAVE_IRQ indicates whether the driver has an IRQ handler. The
+              DRM core will automatically register an interrupt handler when the
+              flag is set. DRIVER_IRQ_SHARED indicates whether the device &amp;
+              handler support shared IRQs (note that this is required of PCI
+              drivers).
+            </para></listitem>
+          </varlistentry>
+          <varlistentry>
+            <term>DRIVER_IRQ_VBL</term>
+            <listitem><para>Unused. Deprecated.</para></listitem>
+          </varlistentry>
+          <varlistentry>
+            <term>DRIVER_DMA_QUEUE</term>
+            <listitem><para>
+              Should be set if the driver queues DMA requests and completes them
+              asynchronously.  Deprecated.
+            </para></listitem>
+          </varlistentry>
+          <varlistentry>
+            <term>DRIVER_FB_DMA</term>
+            <listitem><para>
+              Driver supports DMA to/from the framebuffer, mapping of frambuffer
+              DMA buffers to userspace will be supported. Deprecated.
+            </para></listitem>
+          </varlistentry>
+          <varlistentry>
+            <term>DRIVER_IRQ_VBL2</term>
+            <listitem><para>Unused. Deprecated.</para></listitem>
+          </varlistentry>
+          <varlistentry>
+            <term>DRIVER_GEM</term>
+            <listitem><para>
+              Driver use the GEM memory manager.
+            </para></listitem>
+          </varlistentry>
+          <varlistentry>
+            <term>DRIVER_MODESET</term>
+            <listitem><para>
+              Driver supports mode setting interfaces (KMS).
+            </para></listitem>
+          </varlistentry>
+          <varlistentry>
+            <term>DRIVER_PRIME</term>
+            <listitem><para>
+              Driver implements DRM PRIME buffer sharing.
+            </para></listitem>
+          </varlistentry>
+        </variablelist>
+      </sect3>
+      <sect3>
+        <title>Major, Minor and Patchlevel</title>
+        <synopsis>int major;
+int minor;
+int patchlevel;</synopsis>
+        <para>
+          The DRM core identifies driver versions by a major, minor and patch
+          level triplet. The information is printed to the kernel log at
+          initialization time and passed to userspace through the
+          DRM_IOCTL_VERSION ioctl.
+        </para>
+        <para>
+          The major and minor numbers are also used to verify the requested driver
+          API version passed to DRM_IOCTL_SET_VERSION. When the driver API changes
+          between minor versions, applications can call DRM_IOCTL_SET_VERSION to
+          select a specific version of the API. If the requested major isn't equal
+          to the driver major, or the requested minor is larger than the driver
+          minor, the DRM_IOCTL_SET_VERSION call will return an error. Otherwise
+          the driver's set_version() method will be called with the requested
+          version.
+        </para>
+      </sect3>
+      <sect3>
+        <title>Name, Description and Date</title>
+        <synopsis>char *name;
+char *desc;
+char *date;</synopsis>
+        <para>
+          The driver name is printed to the kernel log at initialization time,
+          used for IRQ registration and passed to userspace through
+          DRM_IOCTL_VERSION.
+        </para>
+        <para>
+          The driver description is a purely informative string passed to
+          userspace through the DRM_IOCTL_VERSION ioctl and otherwise unused by
+          the kernel.
+        </para>
+        <para>
+          The driver date, formatted as YYYYMMDD, is meant to identify the date of
+          the latest modification to the driver. However, as most drivers fail to
+          update it, its value is mostly useless. The DRM core prints it to the
+          kernel log at initialization time and passes it to userspace through the
+          DRM_IOCTL_VERSION ioctl.
+        </para>
+      </sect3>
+    </sect2>
+    <sect2>
+      <title>Driver Load</title>
       <para>
-	The DRM supports several counters which may be used for rough
-	performance characterization.  Note that the DRM stat counter
-	system is not often used by applications, and supporting
-	additional counters is completely optional.
+        The <methodname>load</methodname> method is the driver and device
+        initialization entry point. The method is responsible for allocating and
+        initializing driver private data, specifying supported performance
+        counters, performing resource allocation and mapping (e.g. acquiring
+        clocks, mapping registers or allocating command buffers), initializing
+        the memory manager (<xref linkend="drm-memory-management"/>), installing
+        the IRQ handler (<xref linkend="drm-irq-registration"/>), setting up
+        vertical blanking handling (<xref linkend="drm-vertical-blank"/>), mode
+	setting (<xref linkend="drm-mode-setting"/>) and initial output
+	configuration (<xref linkend="drm-kms-init"/>).
       </para>
+      <note><para>
+        If compatibility is a concern (e.g. with drivers converted over from
+        User Mode Setting to Kernel Mode Setting), care must be taken to prevent
+        device initialization and control that is incompatible with currently
+        active userspace drivers. For instance, if user level mode setting
+        drivers are in use, it would be problematic to perform output discovery
+        &amp; configuration at load time. Likewise, if user-level drivers
+        unaware of memory management are in use, memory management and command
+        buffer setup may need to be omitted. These requirements are
+        driver-specific, and care needs to be taken to keep both old and new
+        applications and libraries working.
+      </para></note>
+      <synopsis>int (*load) (struct drm_device *, unsigned long flags);</synopsis>
       <para>
-	These interfaces are deprecated and should not be used.  If performance
-	monitoring is desired, the developer should investigate and
-	potentially enhance the kernel perf and tracing infrastructure to export
-	GPU related performance information for consumption by performance
-	monitoring tools and applications.
+        The method takes two arguments, a pointer to the newly created
+	<structname>drm_device</structname> and flags. The flags are used to
+	pass the <structfield>driver_data</structfield> field of the device id
+	corresponding to the device passed to <function>drm_*_init()</function>.
+	Only PCI devices currently use this, USB and platform DRM drivers have
+	their <methodname>load</methodname> method called with flags to 0.
       </para>
+      <sect3>
+        <title>Driver Private &amp; Performance Counters</title>
+        <para>
+          The driver private hangs off the main
+          <structname>drm_device</structname> structure and can be used for
+          tracking various device-specific bits of information, like register
+          offsets, command buffer status, register state for suspend/resume, etc.
+          At load time, a driver may simply allocate one and set
+          <structname>drm_device</structname>.<structfield>dev_priv</structfield>
+          appropriately; it should be freed and
+          <structname>drm_device</structname>.<structfield>dev_priv</structfield>
+          set to NULL when the driver is unloaded.
+        </para>
+        <para>
+          DRM supports several counters which were used for rough performance
+          characterization. This stat counter system is deprecated and should not
+          be used. If performance monitoring is desired, the developer should
+          investigate and potentially enhance the kernel perf and tracing
+          infrastructure to export GPU related performance information for
+          consumption by performance monitoring tools and applications.
+        </para>
+      </sect3>
+      <sect3 id="drm-irq-registration">
+        <title>IRQ Registration</title>
+        <para>
+          The DRM core tries to facilitate IRQ handler registration and
+          unregistration by providing <function>drm_irq_install</function> and
+          <function>drm_irq_uninstall</function> functions. Those functions only
+          support a single interrupt per device.
+        </para>
+  <!--!Fdrivers/char/drm/drm_irq.c drm_irq_install-->
+        <para>
+          Both functions get the device IRQ by calling
+          <function>drm_dev_to_irq</function>. This inline function will call a
+          bus-specific operation to retrieve the IRQ number. For platform devices,
+          <function>platform_get_irq</function>(..., 0) is used to retrieve the
+          IRQ number.
+        </para>
+        <para>
+          <function>drm_irq_install</function> starts by calling the
+          <methodname>irq_preinstall</methodname> driver operation. The operation
+          is optional and must make sure that the interrupt will not get fired by
+          clearing all pending interrupt flags or disabling the interrupt.
+        </para>
+        <para>
+          The IRQ will then be requested by a call to
+          <function>request_irq</function>. If the DRIVER_IRQ_SHARED driver
+          feature flag is set, a shared (IRQF_SHARED) IRQ handler will be
+          requested.
+        </para>
+        <para>
+          The IRQ handler function must be provided as the mandatory irq_handler
+          driver operation. It will get passed directly to
+          <function>request_irq</function> and thus has the same prototype as all
+          IRQ handlers. It will get called with a pointer to the DRM device as the
+          second argument.
+        </para>
+        <para>
+          Finally the function calls the optional
+          <methodname>irq_postinstall</methodname> driver operation. The operation
+          usually enables interrupts (excluding the vblank interrupt, which is
+          enabled separately), but drivers may choose to enable/disable interrupts
+          at a different time.
+        </para>
+        <para>
+          <function>drm_irq_uninstall</function> is similarly used to uninstall an
+          IRQ handler. It starts by waking up all processes waiting on a vblank
+          interrupt to make sure they don't hang, and then calls the optional
+          <methodname>irq_uninstall</methodname> driver operation. The operation
+          must disable all hardware interrupts. Finally the function frees the IRQ
+          by calling <function>free_irq</function>.
+        </para>
+      </sect3>
+      <sect3>
+        <title>Memory Manager Initialization</title>
+        <para>
+          Every DRM driver requires a memory manager which must be initialized at
+          load time. DRM currently contains two memory managers, the Translation
+          Table Manager (TTM) and the Graphics Execution Manager (GEM).
+          This document describes the use of the GEM memory manager only. See
+          <xref linkend="drm-memory-management"/> for details.
+        </para>
+      </sect3>
+      <sect3>
+        <title>Miscellaneous Device Configuration</title>
+        <para>
+          Another task that may be necessary for PCI devices during configuration
+          is mapping the video BIOS. On many devices, the VBIOS describes device
+          configuration, LCD panel timings (if any), and contains flags indicating
+          device state. Mapping the BIOS can be done using the pci_map_rom() call,
+          a convenience function that takes care of mapping the actual ROM,
+          whether it has been shadowed into memory (typically at address 0xc0000)
+          or exists on the PCI device in the ROM BAR. Note that after the ROM has
+          been mapped and any necessary information has been extracted, it should
+          be unmapped; on many devices, the ROM address decoder is shared with
+          other BARs, so leaving it mapped could cause undesired behaviour like
+          hangs or memory corruption.
+  <!--!Fdrivers/pci/rom.c pci_map_rom-->
+        </para>
+      </sect3>
     </sect2>
+  </sect1>
 
-    <sect2>
-      <title>Configuring the device</title>
-      <para>
-	Obviously, device configuration is device-specific.
-	However, there are several common operations: finding a
-	device's PCI resources, mapping them, and potentially setting
-	up an IRQ handler.
-      </para>
-      <para>
-	Finding &amp; mapping resources is fairly straightforward.  The
-	DRM wrapper functions, drm_get_resource_start() and
-	drm_get_resource_len(), may be used to find BARs on the given
-	drm_device struct.  Once those values have been retrieved, the
-	driver load function can call drm_addmap() to create a new
-	mapping for the BAR in question.  Note that you probably want a
-	drm_local_map_t in your driver private structure to track any
-	mappings you create.
-<!-- !Fdrivers/gpu/drm/drm_bufs.c drm_get_resource_* -->
-<!-- !Finclude/drm/drmP.h drm_local_map_t -->
-      </para>
-      <para>
-	if compatibility with other operating systems isn't a concern
-	(DRM drivers can run under various BSD variants and OpenSolaris),
-	native Linux calls may be used for the above, e.g. pci_resource_*
-	and iomap*/iounmap.  See the Linux device driver book for more
-	info.
-      </para>
-      <para>
-	Once you have a register map, you may use the DRM_READn() and
-	DRM_WRITEn() macros to access the registers on your device, or
-	use driver-specific versions to offset into your MMIO space
-	relative to a driver-specific base pointer (see I915_READ for
-	an example).
-      </para>
-      <para>
-	If your device supports interrupt generation, you may want to
-	set up an interrupt handler when the driver is loaded.  This
-	is done using the drm_irq_install() function.  If your device
-	supports vertical blank interrupts, it should call
-	drm_vblank_init() to initialize the core vblank handling code before
-	enabling interrupts on your device.  This ensures the vblank related
-	structures are allocated and allows the core to handle vblank events.
-      </para>
-<!--!Fdrivers/char/drm/drm_irq.c drm_irq_install-->
-      <para>
-	Once your interrupt handler is registered (it uses your
-	drm_driver.irq_handler as the actual interrupt handling
-	function), you can safely enable interrupts on your device,
-	assuming any other state your interrupt handler uses is also
-	initialized.
-      </para>
-      <para>
-	Another task that may be necessary during configuration is
-	mapping the video BIOS.  On many devices, the VBIOS describes
-	device configuration, LCD panel timings (if any), and contains
-	flags indicating device state.  Mapping the BIOS can be done
-	using the pci_map_rom() call, a convenience function that
-	takes care of mapping the actual ROM, whether it has been
-	shadowed into memory (typically at address 0xc0000) or exists
-	on the PCI device in the ROM BAR.  Note that after the ROM
-	has been mapped and any necessary information has been extracted,
-	it should be unmapped; on many devices, the ROM address decoder is
-	shared with other BARs, so leaving it mapped could cause
-	undesired behavior like hangs or memory corruption.
-<!--!Fdrivers/pci/rom.c pci_map_rom-->
-      </para>
-    </sect2>
+  <!-- Internals: memory management -->
 
+  <sect1 id="drm-memory-management">
+    <title>Memory management</title>
+    <para>
+      Modern Linux systems require large amount of graphics memory to store
+      frame buffers, textures, vertices and other graphics-related data. Given
+      the very dynamic nature of many of that data, managing graphics memory
+      efficiently is thus crucial for the graphics stack and plays a central
+      role in the DRM infrastructure.
+    </para>
+    <para>
+      The DRM core includes two memory managers, namely Translation Table Maps
+      (TTM) and Graphics Execution Manager (GEM). TTM was the first DRM memory
+      manager to be developed and tried to be a one-size-fits-them all
+      solution. It provides a single userspace API to accomodate the need of
+      all hardware, supporting both Unified Memory Architecture (UMA) devices
+      and devices with dedicated video RAM (i.e. most discrete video cards).
+      This resulted in a large, complex piece of code that turned out to be
+      hard to use for driver development.
+    </para>
+    <para>
+      GEM started as an Intel-sponsored project in reaction to TTM's
+      complexity. Its design philosophy is completely different: instead of
+      providing a solution to every graphics memory-related problems, GEM
+      identified common code between drivers and created a support library to
+      share it. GEM has simpler initialization and execution requirements than
+      TTM, but has no video RAM management capabitilies and is thus limited to
+      UMA devices.
+    </para>
     <sect2>
-      <title>Memory manager initialization</title>
-      <para>
-	In order to allocate command buffers, cursor memory, scanout
-	buffers, etc., as well as support the latest features provided
-	by packages like Mesa and the X.Org X server, your driver
-	should support a memory manager.
-      </para>
+      <title>The Translation Table Manager (TTM)</title>
       <para>
-	If your driver supports memory management (it should!), you
-	need to set that up at load time as well.  How you initialize
-	it depends on which memory manager you're using: TTM or GEM.
+	TTM design background and information belongs here.
       </para>
       <sect3>
 	<title>TTM initialization</title>
-	<para>
-	  TTM (for Translation Table Manager) manages video memory and
-	  aperture space for graphics devices. TTM supports both UMA devices
-	  and devices with dedicated video RAM (VRAM), i.e. most discrete
-	  graphics devices.  If your device has dedicated RAM, supporting
-	  TTM is desirable.  TTM also integrates tightly with your
-	  driver-specific buffer execution function.  See the radeon
-	  driver for examples.
-	</para>
-	<para>
-	  The core TTM structure is the ttm_bo_driver struct.  It contains
-	  several fields with function pointers for initializing the TTM,
-	  allocating and freeing memory, waiting for command completion
-	  and fence synchronization, and memory migration.  See the
-	  radeon_ttm.c file for an example of usage.
+        <warning><para>This section is outdated.</para></warning>
+        <para>
+          Drivers wishing to support TTM must fill out a drm_bo_driver
+          structure. The structure contains several fields with function
+          pointers for initializing the TTM, allocating and freeing memory,
+          waiting for command completion and fence synchronization, and memory
+          migration. See the radeon_ttm.c file for an example of usage.
 	</para>
 	<para>
 	  The ttm_global_reference structure is made up of several fields:
@@ -445,82 +500,1081 @@
 	  count for the TTM, which will call your initialization function.
 	</para>
       </sect3>
+    </sect2>
+    <sect2 id="drm-gem">
+      <title>The Graphics Execution Manager (GEM)</title>
+      <para>
+        The GEM design approach has resulted in a memory manager that doesn't
+        provide full coverage of all (or even all common) use cases in its
+        userspace or kernel API. GEM exposes a set of standard memory-related
+        operations to userspace and a set of helper functions to drivers, and let
+        drivers implement hardware-specific operations with their own private API.
+      </para>
+      <para>
+        The GEM userspace API is described in the
+        <ulink url="http://lwn.net/Articles/283798/"><citetitle>GEM - the Graphics
+        Execution Manager</citetitle></ulink> article on LWN. While slightly
+        outdated, the document provides a good overview of the GEM API principles.
+        Buffer allocation and read and write operations, described as part of the
+        common GEM API, are currently implemented using driver-specific ioctls.
+      </para>
+      <para>
+        GEM is data-agnostic. It manages abstract buffer objects without knowing
+        what individual buffers contain. APIs that require knowledge of buffer
+        contents or purpose, such as buffer allocation or synchronization
+        primitives, are thus outside of the scope of GEM and must be implemented
+        using driver-specific ioctls.
+      </para>
+      <para>
+	On a fundamental level, GEM involves several operations:
+	<itemizedlist>
+	  <listitem>Memory allocation and freeing</listitem>
+	  <listitem>Command execution</listitem>
+	  <listitem>Aperture management at command execution time</listitem>
+	</itemizedlist>
+	Buffer object allocation is relatively straightforward and largely
+        provided by Linux's shmem layer, which provides memory to back each
+        object.
+      </para>
+      <para>
+        Device-specific operations, such as command execution, pinning, buffer
+	read &amp; write, mapping, and domain ownership transfers are left to
+        driver-specific ioctls.
+      </para>
+      <sect3>
+        <title>GEM Initialization</title>
+        <para>
+          Drivers that use GEM must set the DRIVER_GEM bit in the struct
+          <structname>drm_driver</structname>
+          <structfield>driver_features</structfield> field. The DRM core will
+          then automatically initialize the GEM core before calling the
+          <methodname>load</methodname> operation. Behind the scene, this will
+          create a DRM Memory Manager object which provides an address space
+          pool for object allocation.
+        </para>
+        <para>
+          In a KMS configuration, drivers need to allocate and initialize a
+          command ring buffer following core GEM initialization if required by
+          the hardware. UMA devices usually have what is called a "stolen"
+          memory region, which provides space for the initial framebuffer and
+          large, contiguous memory regions required by the device. This space is
+          typically not managed by GEM, and must be initialized separately into
+          its own DRM MM object.
+        </para>
+      </sect3>
       <sect3>
-	<title>GEM initialization</title>
-	<para>
-	  GEM is an alternative to TTM, designed specifically for UMA
-	  devices.  It has simpler initialization and execution requirements
-	  than TTM, but has no VRAM management capability.  Core GEM
-	  is initialized by calling drm_mm_init() to create
-	  a GTT DRM MM object, which provides an address space pool for
-	  object allocation.  In a KMS configuration, the driver
-	  needs to allocate and initialize a command ring buffer following
-	  core GEM initialization.  A UMA device usually has what is called a
-	  "stolen" memory region, which provides space for the initial
-	  framebuffer and large, contiguous memory regions required by the
-	  device.  This space is not typically managed by GEM, and it must
-	  be initialized separately into its own DRM MM object.
-	</para>
-	<para>
-	  Initialization is driver-specific. In the case of Intel
-	  integrated graphics chips like 965GM, GEM initialization can
-	  be done by calling the internal GEM init function,
-	  i915_gem_do_init().  Since the 965GM is a UMA device
-	  (i.e. it doesn't have dedicated VRAM), GEM manages
-	  making regular RAM available for GPU operations.  Memory set
-	  aside by the BIOS (called "stolen" memory by the i915
-	  driver) is managed by the DRM memrange allocator; the
-	  rest of the aperture is managed by GEM.
-	  <programlisting>
-	    /* Basic memrange allocator for stolen space (aka vram) */
-	    drm_memrange_init(&amp;dev_priv->vram, 0, prealloc_size);
-	    /* Let GEM Manage from end of prealloc space to end of aperture */
-	    i915_gem_do_init(dev, prealloc_size, agp_size);
-	  </programlisting>
-<!--!Edrivers/char/drm/drm_memrange.c-->
-	</para>
-	<para>
-	  Once the memory manager has been set up, we may allocate the
-	  command buffer.  In the i915 case, this is also done with a
-	  GEM function, i915_gem_init_ringbuffer().
-	</para>
+        <title>GEM Objects Creation</title>
+        <para>
+          GEM splits creation of GEM objects and allocation of the memory that
+          backs them in two distinct operations.
+        </para>
+        <para>
+          GEM objects are represented by an instance of struct
+          <structname>drm_gem_object</structname>. Drivers usually need to extend
+          GEM objects with private information and thus create a driver-specific
+          GEM object structure type that embeds an instance of struct
+          <structname>drm_gem_object</structname>.
+        </para>
+        <para>
+          To create a GEM object, a driver allocates memory for an instance of its
+          specific GEM object type and initializes the embedded struct
+          <structname>drm_gem_object</structname> with a call to
+          <function>drm_gem_object_init</function>. The function takes a pointer to
+          the DRM device, a pointer to the GEM object and the buffer object size
+          in bytes.
+        </para>
+        <para>
+          GEM uses shmem to allocate anonymous pageable memory.
+          <function>drm_gem_object_init</function> will create an shmfs file of
+          the requested size and store it into the struct
+          <structname>drm_gem_object</structname> <structfield>filp</structfield>
+          field. The memory is used as either main storage for the object when the
+          graphics hardware uses system memory directly or as a backing store
+          otherwise.
+        </para>
+        <para>
+          Drivers are responsible for the actual physical pages allocation by
+          calling <function>shmem_read_mapping_page_gfp</function> for each page.
+          Note that they can decide to allocate pages when initializing the GEM
+          object, or to delay allocation until the memory is needed (for instance
+          when a page fault occurs as a result of a userspace memory access or
+          when the driver needs to start a DMA transfer involving the memory).
+        </para>
+        <para>
+          Anonymous pageable memory allocation is not always desired, for instance
+          when the hardware requires physically contiguous system memory as is
+          often the case in embedded devices. Drivers can create GEM objects with
+          no shmfs backing (called private GEM objects) by initializing them with
+          a call to <function>drm_gem_private_object_init</function> instead of
+          <function>drm_gem_object_init</function>. Storage for private GEM
+          objects must be managed by drivers.
+        </para>
+        <para>
+          Drivers that do not need to extend GEM objects with private information
+          can call the <function>drm_gem_object_alloc</function> function to
+          allocate and initialize a struct <structname>drm_gem_object</structname>
+          instance. The GEM core will call the optional driver
+          <methodname>gem_init_object</methodname> operation after initializing
+          the GEM object with <function>drm_gem_object_init</function>.
+          <synopsis>int (*gem_init_object) (struct drm_gem_object *obj);</synopsis>
+        </para>
+        <para>
+          No alloc-and-init function exists for private GEM objects.
+        </para>
+      </sect3>
+      <sect3>
+        <title>GEM Objects Lifetime</title>
+        <para>
+          All GEM objects are reference-counted by the GEM core. References can be
+          acquired and release by <function>calling drm_gem_object_reference</function>
+          and <function>drm_gem_object_unreference</function> respectively. The
+          caller must hold the <structname>drm_device</structname>
+          <structfield>struct_mutex</structfield> lock. As a convenience, GEM
+          provides the <function>drm_gem_object_reference_unlocked</function> and
+          <function>drm_gem_object_unreference_unlocked</function> functions that
+          can be called without holding the lock.
+        </para>
+        <para>
+          When the last reference to a GEM object is released the GEM core calls
+          the <structname>drm_driver</structname>
+          <methodname>gem_free_object</methodname> operation. That operation is
+          mandatory for GEM-enabled drivers and must free the GEM object and all
+          associated resources.
+        </para>
+        <para>
+          <synopsis>void (*gem_free_object) (struct drm_gem_object *obj);</synopsis>
+          Drivers are responsible for freeing all GEM object resources, including
+          the resources created by the GEM core. If an mmap offset has been
+          created for the object (in which case
+          <structname>drm_gem_object</structname>::<structfield>map_list</structfield>::<structfield>map</structfield>
+          is not NULL) it must be freed by a call to
+          <function>drm_gem_free_mmap_offset</function>. The shmfs backing store
+          must be released by calling <function>drm_gem_object_release</function>
+          (that function can safely be called if no shmfs backing store has been
+          created).
+        </para>
+      </sect3>
+      <sect3>
+        <title>GEM Objects Naming</title>
+        <para>
+          Communication between userspace and the kernel refers to GEM objects
+          using local handles, global names or, more recently, file descriptors.
+          All of those are 32-bit integer values; the usual Linux kernel limits
+          apply to the file descriptors.
+        </para>
+        <para>
+          GEM handles are local to a DRM file. Applications get a handle to a GEM
+          object through a driver-specific ioctl, and can use that handle to refer
+          to the GEM object in other standard or driver-specific ioctls. Closing a
+          DRM file handle frees all its GEM handles and dereferences the
+          associated GEM objects.
+        </para>
+        <para>
+          To create a handle for a GEM object drivers call
+          <function>drm_gem_handle_create</function>. The function takes a pointer
+          to the DRM file and the GEM object and returns a locally unique handle.
+          When the handle is no longer needed drivers delete it with a call to
+          <function>drm_gem_handle_delete</function>. Finally the GEM object
+          associated with a handle can be retrieved by a call to
+          <function>drm_gem_object_lookup</function>.
+        </para>
+        <para>
+          Handles don't take ownership of GEM objects, they only take a reference
+          to the object that will be dropped when the handle is destroyed. To
+          avoid leaking GEM objects, drivers must make sure they drop the
+          reference(s) they own (such as the initial reference taken at object
+          creation time) as appropriate, without any special consideration for the
+          handle. For example, in the particular case of combined GEM object and
+          handle creation in the implementation of the
+          <methodname>dumb_create</methodname> operation, drivers must drop the
+          initial reference to the GEM object before returning the handle.
+        </para>
+        <para>
+          GEM names are similar in purpose to handles but are not local to DRM
+          files. They can be passed between processes to reference a GEM object
+          globally. Names can't be used directly to refer to objects in the DRM
+          API, applications must convert handles to names and names to handles
+          using the DRM_IOCTL_GEM_FLINK and DRM_IOCTL_GEM_OPEN ioctls
+          respectively. The conversion is handled by the DRM core without any
+          driver-specific support.
+        </para>
+        <para>
+          Similar to global names, GEM file descriptors are also used to share GEM
+          objects across processes. They offer additional security: as file
+          descriptors must be explictly sent over UNIX domain sockets to be shared
+          between applications, they can't be guessed like the globally unique GEM
+          names.
+        </para>
+        <para>
+          Drivers that support GEM file descriptors, also known as the DRM PRIME
+          API, must set the DRIVER_PRIME bit in the struct
+          <structname>drm_driver</structname>
+          <structfield>driver_features</structfield> field, and implement the
+          <methodname>prime_handle_to_fd</methodname> and
+          <methodname>prime_fd_to_handle</methodname> operations.
+        </para>
+        <para>
+          <synopsis>int (*prime_handle_to_fd)(struct drm_device *dev,
+                            struct drm_file *file_priv, uint32_t handle,
+                            uint32_t flags, int *prime_fd);
+  int (*prime_fd_to_handle)(struct drm_device *dev,
+                            struct drm_file *file_priv, int prime_fd,
+                            uint32_t *handle);</synopsis>
+          Those two operations convert a handle to a PRIME file descriptor and
+          vice versa. Drivers must use the kernel dma-buf buffer sharing framework
+          to manage the PRIME file descriptors.
+        </para>
+        <para>
+          While non-GEM drivers must implement the operations themselves, GEM
+          drivers must use the <function>drm_gem_prime_handle_to_fd</function>
+          and <function>drm_gem_prime_fd_to_handle</function> helper functions.
+          Those helpers rely on the driver
+          <methodname>gem_prime_export</methodname> and
+          <methodname>gem_prime_import</methodname> operations to create a dma-buf
+          instance from a GEM object (dma-buf exporter role) and to create a GEM
+          object from a dma-buf instance (dma-buf importer role).
+        </para>
+        <para>
+          <synopsis>struct dma_buf * (*gem_prime_export)(struct drm_device *dev,
+                                       struct drm_gem_object *obj,
+                                       int flags);
+  struct drm_gem_object * (*gem_prime_import)(struct drm_device *dev,
+                                              struct dma_buf *dma_buf);</synopsis>
+          These two operations are mandatory for GEM drivers that support DRM
+          PRIME.
+        </para>
+      </sect3>
+      <sect3 id="drm-gem-objects-mapping">
+        <title>GEM Objects Mapping</title>
+        <para>
+          Because mapping operations are fairly heavyweight GEM favours
+          read/write-like access to buffers, implemented through driver-specific
+          ioctls, over mapping buffers to userspace. However, when random access
+          to the buffer is needed (to perform software rendering for instance),
+          direct access to the object can be more efficient.
+        </para>
+        <para>
+          The mmap system call can't be used directly to map GEM objects, as they
+          don't have their own file handle. Two alternative methods currently
+          co-exist to map GEM objects to userspace. The first method uses a
+          driver-specific ioctl to perform the mapping operation, calling
+          <function>do_mmap</function> under the hood. This is often considered
+          dubious, seems to be discouraged for new GEM-enabled drivers, and will
+          thus not be described here.
+        </para>
+        <para>
+          The second method uses the mmap system call on the DRM file handle.
+          <synopsis>void *mmap(void *addr, size_t length, int prot, int flags, int fd,
+             off_t offset);</synopsis>
+          DRM identifies the GEM object to be mapped by a fake offset passed
+          through the mmap offset argument. Prior to being mapped, a GEM object
+          must thus be associated with a fake offset. To do so, drivers must call
+          <function>drm_gem_create_mmap_offset</function> on the object. The
+          function allocates a fake offset range from a pool and stores the
+          offset divided by PAGE_SIZE in
+          <literal>obj-&gt;map_list.hash.key</literal>. Care must be taken not to
+          call <function>drm_gem_create_mmap_offset</function> if a fake offset
+          has already been allocated for the object. This can be tested by
+          <literal>obj-&gt;map_list.map</literal> being non-NULL.
+        </para>
+        <para>
+          Once allocated, the fake offset value
+          (<literal>obj-&gt;map_list.hash.key &lt;&lt; PAGE_SHIFT</literal>)
+          must be passed to the application in a driver-specific way and can then
+          be used as the mmap offset argument.
+        </para>
+        <para>
+          The GEM core provides a helper method <function>drm_gem_mmap</function>
+          to handle object mapping. The method can be set directly as the mmap
+          file operation handler. It will look up the GEM object based on the
+          offset value and set the VMA operations to the
+          <structname>drm_driver</structname> <structfield>gem_vm_ops</structfield>
+          field. Note that <function>drm_gem_mmap</function> doesn't map memory to
+          userspace, but relies on the driver-provided fault handler to map pages
+          individually.
+        </para>
+        <para>
+          To use <function>drm_gem_mmap</function>, drivers must fill the struct
+          <structname>drm_driver</structname> <structfield>gem_vm_ops</structfield>
+          field with a pointer to VM operations.
+        </para>
+        <para>
+          <synopsis>struct vm_operations_struct *gem_vm_ops
+
+  struct vm_operations_struct {
+          void (*open)(struct vm_area_struct * area);
+          void (*close)(struct vm_area_struct * area);
+          int (*fault)(struct vm_area_struct *vma, struct vm_fault *vmf);
+  };</synopsis>
+        </para>
+        <para>
+          The <methodname>open</methodname> and <methodname>close</methodname>
+          operations must update the GEM object reference count. Drivers can use
+          the <function>drm_gem_vm_open</function> and
+          <function>drm_gem_vm_close</function> helper functions directly as open
+          and close handlers.
+        </para>
+        <para>
+          The fault operation handler is responsible for mapping individual pages
+          to userspace when a page fault occurs. Depending on the memory
+          allocation scheme, drivers can allocate pages at fault time, or can
+          decide to allocate memory for the GEM object at the time the object is
+          created.
+        </para>
+        <para>
+          Drivers that want to map the GEM object upfront instead of handling page
+          faults can implement their own mmap file operation handler.
+        </para>
+      </sect3>
+      <sect3>
+        <title>Dumb GEM Objects</title>
+        <para>
+          The GEM API doesn't standardize GEM objects creation and leaves it to
+          driver-specific ioctls. While not an issue for full-fledged graphics
+          stacks that include device-specific userspace components (in libdrm for
+          instance), this limit makes DRM-based early boot graphics unnecessarily
+          complex.
+        </para>
+        <para>
+          Dumb GEM objects partly alleviate the problem by providing a standard
+          API to create dumb buffers suitable for scanout, which can then be used
+          to create KMS frame buffers.
+        </para>
+        <para>
+          To support dumb GEM objects drivers must implement the
+          <methodname>dumb_create</methodname>,
+          <methodname>dumb_destroy</methodname> and
+          <methodname>dumb_map_offset</methodname> operations.
+        </para>
+        <itemizedlist>
+          <listitem>
+            <synopsis>int (*dumb_create)(struct drm_file *file_priv, struct drm_device *dev,
+                     struct drm_mode_create_dumb *args);</synopsis>
+            <para>
+              The <methodname>dumb_create</methodname> operation creates a GEM
+              object suitable for scanout based on the width, height and depth
+              from the struct <structname>drm_mode_create_dumb</structname>
+              argument. It fills the argument's <structfield>handle</structfield>,
+              <structfield>pitch</structfield> and <structfield>size</structfield>
+              fields with a handle for the newly created GEM object and its line
+              pitch and size in bytes.
+            </para>
+          </listitem>
+          <listitem>
+            <synopsis>int (*dumb_destroy)(struct drm_file *file_priv, struct drm_device *dev,
+                      uint32_t handle);</synopsis>
+            <para>
+              The <methodname>dumb_destroy</methodname> operation destroys a dumb
+              GEM object created by <methodname>dumb_create</methodname>.
+            </para>
+          </listitem>
+          <listitem>
+            <synopsis>int (*dumb_map_offset)(struct drm_file *file_priv, struct drm_device *dev,
+                         uint32_t handle, uint64_t *offset);</synopsis>
+            <para>
+              The <methodname>dumb_map_offset</methodname> operation associates an
+              mmap fake offset with the GEM object given by the handle and returns
+              it. Drivers must use the
+              <function>drm_gem_create_mmap_offset</function> function to
+              associate the fake offset as described in
+              <xref linkend="drm-gem-objects-mapping"/>.
+            </para>
+          </listitem>
+        </itemizedlist>
+      </sect3>
+      <sect3>
+        <title>Memory Coherency</title>
+        <para>
+          When mapped to the device or used in a command buffer, backing pages
+          for an object are flushed to memory and marked write combined so as to
+          be coherent with the GPU. Likewise, if the CPU accesses an object
+          after the GPU has finished rendering to the object, then the object
+          must be made coherent with the CPU's view of memory, usually involving
+          GPU cache flushing of various kinds. This core CPU&lt;-&gt;GPU
+          coherency management is provided by a device-specific ioctl, which
+          evaluates an object's current domain and performs any necessary
+          flushing or synchronization to put the object into the desired
+          coherency domain (note that the object may be busy, i.e. an active
+          render target; in that case, setting the domain blocks the client and
+          waits for rendering to complete before performing any necessary
+          flushing operations).
+        </para>
+      </sect3>
+      <sect3>
+        <title>Command Execution</title>
+        <para>
+	  Perhaps the most important GEM function for GPU devices is providing a
+          command execution interface to clients. Client programs construct
+          command buffers containing references to previously allocated memory
+          objects, and then submit them to GEM. At that point, GEM takes care to
+          bind all the objects into the GTT, execute the buffer, and provide
+          necessary synchronization between clients accessing the same buffers.
+          This often involves evicting some objects from the GTT and re-binding
+          others (a fairly expensive operation), and providing relocation
+          support which hides fixed GTT offsets from clients. Clients must take
+          care not to submit command buffers that reference more objects than
+          can fit in the GTT; otherwise, GEM will reject them and no rendering
+          will occur. Similarly, if several objects in the buffer require fence
+          registers to be allocated for correct rendering (e.g. 2D blits on
+          pre-965 chips), care must be taken not to require more fence registers
+          than are available to the client. Such resource management should be
+          abstracted from the client in libdrm.
+        </para>
       </sect3>
     </sect2>
+  </sect1>
+
+  <!-- Internals: mode setting -->
 
+  <sect1 id="drm-mode-setting">
+    <title>Mode Setting</title>
+    <para>
+      Drivers must initialize the mode setting core by calling
+      <function>drm_mode_config_init</function> on the DRM device. The function
+      initializes the <structname>drm_device</structname>
+      <structfield>mode_config</structfield> field and never fails. Once done,
+      mode configuration must be setup by initializing the following fields.
+    </para>
+    <itemizedlist>
+      <listitem>
+        <synopsis>int min_width, min_height;
+int max_width, max_height;</synopsis>
+        <para>
+	  Minimum and maximum width and height of the frame buffers in pixel
+	  units.
+	</para>
+      </listitem>
+      <listitem>
+        <synopsis>struct drm_mode_config_funcs *funcs;</synopsis>
+	<para>Mode setting functions.</para>
+      </listitem>
+    </itemizedlist>
     <sect2>
-      <title>Output configuration</title>
+      <title>Frame Buffer Creation</title>
+      <synopsis>struct drm_framebuffer *(*fb_create)(struct drm_device *dev,
+				     struct drm_file *file_priv,
+				     struct drm_mode_fb_cmd2 *mode_cmd);</synopsis>
       <para>
-	The final initialization task is output configuration.  This involves:
-	<itemizedlist>
-	  <listitem>
-	    Finding and initializing the CRTCs, encoders, and connectors
-	    for the device.
-	  </listitem>
-	  <listitem>
-	    Creating an initial configuration.
-	  </listitem>
-	  <listitem>
-	    Registering a framebuffer console driver.
-	  </listitem>
-	</itemizedlist>
+        Frame buffers are abstract memory objects that provide a source of
+        pixels to scanout to a CRTC. Applications explicitly request the
+        creation of frame buffers through the DRM_IOCTL_MODE_ADDFB(2) ioctls and
+        receive an opaque handle that can be passed to the KMS CRTC control,
+        plane configuration and page flip functions.
+      </para>
+      <para>
+        Frame buffers rely on the underneath memory manager for low-level memory
+        operations. When creating a frame buffer applications pass a memory
+        handle (or a list of memory handles for multi-planar formats) through
+        the <parameter>drm_mode_fb_cmd2</parameter> argument. This document
+        assumes that the driver uses GEM, those handles thus reference GEM
+        objects.
+      </para>
+      <para>
+        Drivers must first validate the requested frame buffer parameters passed
+        through the mode_cmd argument. In particular this is where invalid
+        sizes, pixel formats or pitches can be caught.
+      </para>
+      <para>
+        If the parameters are deemed valid, drivers then create, initialize and
+        return an instance of struct <structname>drm_framebuffer</structname>.
+        If desired the instance can be embedded in a larger driver-specific
+        structure. The new instance is initialized with a call to
+        <function>drm_framebuffer_init</function> which takes a pointer to DRM
+        frame buffer operations (struct
+        <structname>drm_framebuffer_funcs</structname>). Frame buffer operations are
+        <itemizedlist>
+          <listitem>
+            <synopsis>int (*create_handle)(struct drm_framebuffer *fb,
+		     struct drm_file *file_priv, unsigned int *handle);</synopsis>
+            <para>
+              Create a handle to the frame buffer underlying memory object. If
+              the frame buffer uses a multi-plane format, the handle will
+              reference the memory object associated with the first plane.
+            </para>
+            <para>
+              Drivers call <function>drm_gem_handle_create</function> to create
+              the handle.
+            </para>
+          </listitem>
+          <listitem>
+            <synopsis>void (*destroy)(struct drm_framebuffer *framebuffer);</synopsis>
+            <para>
+              Destroy the frame buffer object and frees all associated
+              resources. Drivers must call
+              <function>drm_framebuffer_cleanup</function> to free resources
+              allocated by the DRM core for the frame buffer object, and must
+              make sure to unreference all memory objects associated with the
+              frame buffer. Handles created by the
+              <methodname>create_handle</methodname> operation are released by
+              the DRM core.
+            </para>
+          </listitem>
+          <listitem>
+            <synopsis>int (*dirty)(struct drm_framebuffer *framebuffer,
+	     struct drm_file *file_priv, unsigned flags, unsigned color,
+	     struct drm_clip_rect *clips, unsigned num_clips);</synopsis>
+            <para>
+              This optional operation notifies the driver that a region of the
+              frame buffer has changed in response to a DRM_IOCTL_MODE_DIRTYFB
+              ioctl call.
+            </para>
+          </listitem>
+        </itemizedlist>
+      </para>
+      <para>
+        After initializing the <structname>drm_framebuffer</structname>
+        instance drivers must fill its <structfield>width</structfield>,
+        <structfield>height</structfield>, <structfield>pitches</structfield>,
+        <structfield>offsets</structfield>, <structfield>depth</structfield>,
+        <structfield>bits_per_pixel</structfield> and
+        <structfield>pixel_format</structfield> fields from the values passed
+        through the <parameter>drm_mode_fb_cmd2</parameter> argument. They
+        should call the <function>drm_helper_mode_fill_fb_struct</function>
+        helper function to do so.
+      </para>
+    </sect2>
+    <sect2>
+      <title>Output Polling</title>
+      <synopsis>void (*output_poll_changed)(struct drm_device *dev);</synopsis>
+      <para>
+        This operation notifies the driver that the status of one or more
+        connectors has changed. Drivers that use the fb helper can just call the
+        <function>drm_fb_helper_hotplug_event</function> function to handle this
+        operation.
+      </para>
+    </sect2>
+  </sect1>
+
+  <!-- Internals: kms initialization and cleanup -->
+
+  <sect1 id="drm-kms-init">
+    <title>KMS Initialization and Cleanup</title>
+    <para>
+      A KMS device is abstracted and exposed as a set of planes, CRTCs, encoders
+      and connectors. KMS drivers must thus create and initialize all those
+      objects at load time after initializing mode setting.
+    </para>
+    <sect2>
+      <title>CRTCs (struct <structname>drm_crtc</structname>)</title>
+      <para>
+        A CRTC is an abstraction representing a part of the chip that contains a
+	pointer to a scanout buffer. Therefore, the number of CRTCs available
+	determines how many independent scanout buffers can be active at any
+	given time. The CRTC structure contains several fields to support this:
+	a pointer to some video memory (abstracted as a frame buffer object), a
+	display mode, and an (x, y) offset into the video memory to support
+	panning or configurations where one piece of video memory spans multiple
+	CRTCs.
       </para>
       <sect3>
-	<title>Output discovery and initialization</title>
-	<para>
-	  Several core functions exist to create CRTCs, encoders, and
-	  connectors, namely: drm_crtc_init(), drm_connector_init(), and
-	  drm_encoder_init(), along with several "helper" functions to
-	  perform common tasks.
-	</para>
-	<para>
-	  Connectors should be registered with sysfs once they've been
-	  detected and initialized, using the
-	  drm_sysfs_connector_add() function.  Likewise, when they're
-	  removed from the system, they should be destroyed with
-	  drm_sysfs_connector_remove().
-	</para>
-	<programlisting>
-<![CDATA[
+        <title>CRTC Initialization</title>
+        <para>
+          A KMS device must create and register at least one struct
+          <structname>drm_crtc</structname> instance. The instance is allocated
+          and zeroed by the driver, possibly as part of a larger structure, and
+          registered with a call to <function>drm_crtc_init</function> with a
+          pointer to CRTC functions.
+        </para>
+      </sect3>
+      <sect3>
+        <title>CRTC Operations</title>
+        <sect4>
+          <title>Set Configuration</title>
+          <synopsis>int (*set_config)(struct drm_mode_set *set);</synopsis>
+          <para>
+            Apply a new CRTC configuration to the device. The configuration
+            specifies a CRTC, a frame buffer to scan out from, a (x,y) position in
+            the frame buffer, a display mode and an array of connectors to drive
+            with the CRTC if possible.
+          </para>
+          <para>
+            If the frame buffer specified in the configuration is NULL, the driver
+            must detach all encoders connected to the CRTC and all connectors
+            attached to those encoders and disable them.
+          </para>
+          <para>
+            This operation is called with the mode config lock held.
+          </para>
+          <note><para>
+            FIXME: How should set_config interact with DPMS? If the CRTC is
+            suspended, should it be resumed?
+          </para></note>
+        </sect4>
+        <sect4>
+          <title>Page Flipping</title>
+          <synopsis>int (*page_flip)(struct drm_crtc *crtc, struct drm_framebuffer *fb,
+                   struct drm_pending_vblank_event *event);</synopsis>
+          <para>
+            Schedule a page flip to the given frame buffer for the CRTC. This
+            operation is called with the mode config mutex held.
+          </para>
+          <para>
+            Page flipping is a synchronization mechanism that replaces the frame
+            buffer being scanned out by the CRTC with a new frame buffer during
+            vertical blanking, avoiding tearing. When an application requests a page
+            flip the DRM core verifies that the new frame buffer is large enough to
+            be scanned out by  the CRTC in the currently configured mode and then
+            calls the CRTC <methodname>page_flip</methodname> operation with a
+            pointer to the new frame buffer.
+          </para>
+          <para>
+            The <methodname>page_flip</methodname> operation schedules a page flip.
+            Once any pending rendering targetting the new frame buffer has
+            completed, the CRTC will be reprogrammed to display that frame buffer
+            after the next vertical refresh. The operation must return immediately
+            without waiting for rendering or page flip to complete and must block
+            any new rendering to the frame buffer until the page flip completes.
+          </para>
+          <para>
+            If a page flip is already pending, the
+            <methodname>page_flip</methodname> operation must return
+            -<errorname>EBUSY</errorname>.
+          </para>
+          <para>
+            To synchronize page flip to vertical blanking the driver will likely
+            need to enable vertical blanking interrupts. It should call
+            <function>drm_vblank_get</function> for that purpose, and call
+            <function>drm_vblank_put</function> after the page flip completes.
+          </para>
+          <para>
+            If the application has requested to be notified when page flip completes
+            the <methodname>page_flip</methodname> operation will be called with a
+            non-NULL <parameter>event</parameter> argument pointing to a
+            <structname>drm_pending_vblank_event</structname> instance. Upon page
+            flip completion the driver must fill the
+            <parameter>event</parameter>::<structfield>event</structfield>
+            <structfield>sequence</structfield>, <structfield>tv_sec</structfield>
+            and <structfield>tv_usec</structfield> fields with the associated
+            vertical blanking count and timestamp, add the event to the
+            <parameter>drm_file</parameter> list of events to be signaled, and wake
+            up any waiting process. This can be performed with
+            <programlisting><![CDATA[
+            struct timeval now;
+
+            event->event.sequence = drm_vblank_count_and_time(..., &now);
+            event->event.tv_sec = now.tv_sec;
+            event->event.tv_usec = now.tv_usec;
+
+            spin_lock_irqsave(&dev->event_lock, flags);
+            list_add_tail(&event->base.link, &event->base.file_priv->event_list);
+            wake_up_interruptible(&event->base.file_priv->event_wait);
+            spin_unlock_irqrestore(&dev->event_lock, flags);
+            ]]></programlisting>
+          </para>
+          <note><para>
+            FIXME: Could drivers that don't need to wait for rendering to complete
+            just add the event to <literal>dev-&gt;vblank_event_list</literal> and
+            let the DRM core handle everything, as for "normal" vertical blanking
+            events?
+          </para></note>
+          <para>
+            While waiting for the page flip to complete, the
+            <literal>event-&gt;base.link</literal> list head can be used freely by
+            the driver to store the pending event in a driver-specific list.
+          </para>
+          <para>
+            If the file handle is closed before the event is signaled, drivers must
+            take care to destroy the event in their
+            <methodname>preclose</methodname> operation (and, if needed, call
+            <function>drm_vblank_put</function>).
+          </para>
+        </sect4>
+        <sect4>
+          <title>Miscellaneous</title>
+          <itemizedlist>
+            <listitem>
+              <synopsis>void (*gamma_set)(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b,
+                        uint32_t start, uint32_t size);</synopsis>
+              <para>
+                Apply a gamma table to the device. The operation is optional.
+              </para>
+            </listitem>
+            <listitem>
+              <synopsis>void (*destroy)(struct drm_crtc *crtc);</synopsis>
+              <para>
+                Destroy the CRTC when not needed anymore. See
+                <xref linkend="drm-kms-init"/>.
+              </para>
+            </listitem>
+          </itemizedlist>
+        </sect4>
+      </sect3>
+    </sect2>
+    <sect2>
+      <title>Planes (struct <structname>drm_plane</structname>)</title>
+      <para>
+        A plane represents an image source that can be blended with or overlayed
+	on top of a CRTC during the scanout process. Planes are associated with
+	a frame buffer to crop a portion of the image memory (source) and
+	optionally scale it to a destination size. The result is then blended
+	with or overlayed on top of a CRTC.
+      </para>
+      <sect3>
+        <title>Plane Initialization</title>
+        <para>
+          Planes are optional. To create a plane, a KMS drivers allocates and
+          zeroes an instances of struct <structname>drm_plane</structname>
+          (possibly as part of a larger structure) and registers it with a call
+          to <function>drm_plane_init</function>. The function takes a bitmask
+          of the CRTCs that can be associated with the plane, a pointer to the
+          plane functions and a list of format supported formats.
+        </para>
+      </sect3>
+      <sect3>
+        <title>Plane Operations</title>
+        <itemizedlist>
+          <listitem>
+            <synopsis>int (*update_plane)(struct drm_plane *plane, struct drm_crtc *crtc,
+                        struct drm_framebuffer *fb, int crtc_x, int crtc_y,
+                        unsigned int crtc_w, unsigned int crtc_h,
+                        uint32_t src_x, uint32_t src_y,
+                        uint32_t src_w, uint32_t src_h);</synopsis>
+            <para>
+              Enable and configure the plane to use the given CRTC and frame buffer.
+            </para>
+            <para>
+              The source rectangle in frame buffer memory coordinates is given by
+              the <parameter>src_x</parameter>, <parameter>src_y</parameter>,
+              <parameter>src_w</parameter> and <parameter>src_h</parameter>
+              parameters (as 16.16 fixed point values). Devices that don't support
+              subpixel plane coordinates can ignore the fractional part.
+            </para>
+            <para>
+              The destination rectangle in CRTC coordinates is given by the
+              <parameter>crtc_x</parameter>, <parameter>crtc_y</parameter>,
+              <parameter>crtc_w</parameter> and <parameter>crtc_h</parameter>
+              parameters (as integer values). Devices scale the source rectangle to
+              the destination rectangle. If scaling is not supported, and the source
+              rectangle size doesn't match the destination rectangle size, the
+              driver must return a -<errorname>EINVAL</errorname> error.
+            </para>
+          </listitem>
+          <listitem>
+            <synopsis>int (*disable_plane)(struct drm_plane *plane);</synopsis>
+            <para>
+              Disable the plane. The DRM core calls this method in response to a
+              DRM_IOCTL_MODE_SETPLANE ioctl call with the frame buffer ID set to 0.
+              Disabled planes must not be processed by the CRTC.
+            </para>
+          </listitem>
+          <listitem>
+            <synopsis>void (*destroy)(struct drm_plane *plane);</synopsis>
+            <para>
+              Destroy the plane when not needed anymore. See
+              <xref linkend="drm-kms-init"/>.
+            </para>
+          </listitem>
+        </itemizedlist>
+      </sect3>
+    </sect2>
+    <sect2>
+      <title>Encoders (struct <structname>drm_encoder</structname>)</title>
+      <para>
+        An encoder takes pixel data from a CRTC and converts it to a format
+	suitable for any attached connectors. On some devices, it may be
+	possible to have a CRTC send data to more than one encoder. In that
+	case, both encoders would receive data from the same scanout buffer,
+	resulting in a "cloned" display configuration across the connectors
+	attached to each encoder.
+      </para>
+      <sect3>
+        <title>Encoder Initialization</title>
+        <para>
+          As for CRTCs, a KMS driver must create, initialize and register at
+          least one struct <structname>drm_encoder</structname> instance. The
+          instance is allocated and zeroed by the driver, possibly as part of a
+          larger structure.
+        </para>
+        <para>
+          Drivers must initialize the struct <structname>drm_encoder</structname>
+          <structfield>possible_crtcs</structfield> and
+          <structfield>possible_clones</structfield> fields before registering the
+          encoder. Both fields are bitmasks of respectively the CRTCs that the
+          encoder can be connected to, and sibling encoders candidate for cloning.
+        </para>
+        <para>
+          After being initialized, the encoder must be registered with a call to
+          <function>drm_encoder_init</function>. The function takes a pointer to
+          the encoder functions and an encoder type. Supported types are
+          <itemizedlist>
+            <listitem>
+              DRM_MODE_ENCODER_DAC for VGA and analog on DVI-I/DVI-A
+              </listitem>
+            <listitem>
+              DRM_MODE_ENCODER_TMDS for DVI, HDMI and (embedded) DisplayPort
+            </listitem>
+            <listitem>
+              DRM_MODE_ENCODER_LVDS for display panels
+            </listitem>
+            <listitem>
+              DRM_MODE_ENCODER_TVDAC for TV output (Composite, S-Video, Component,
+              SCART)
+            </listitem>
+            <listitem>
+              DRM_MODE_ENCODER_VIRTUAL for virtual machine displays
+            </listitem>
+          </itemizedlist>
+        </para>
+        <para>
+          Encoders must be attached to a CRTC to be used. DRM drivers leave
+          encoders unattached at initialization time. Applications (or the fbdev
+          compatibility layer when implemented) are responsible for attaching the
+          encoders they want to use to a CRTC.
+        </para>
+      </sect3>
+      <sect3>
+        <title>Encoder Operations</title>
+        <itemizedlist>
+          <listitem>
+            <synopsis>void (*destroy)(struct drm_encoder *encoder);</synopsis>
+            <para>
+              Called to destroy the encoder when not needed anymore. See
+              <xref linkend="drm-kms-init"/>.
+            </para>
+          </listitem>
+        </itemizedlist>
+      </sect3>
+    </sect2>
+    <sect2>
+      <title>Connectors (struct <structname>drm_connector</structname>)</title>
+      <para>
+        A connector is the final destination for pixel data on a device, and
+	usually connects directly to an external display device like a monitor
+	or laptop panel. A connector can only be attached to one encoder at a
+	time. The connector is also the structure where information about the
+	attached display is kept, so it contains fields for display data, EDID
+	data, DPMS &amp; connection status, and information about modes
+	supported on the attached displays.
+      </para>
+      <sect3>
+        <title>Connector Initialization</title>
+        <para>
+          Finally a KMS driver must create, initialize, register and attach at
+          least one struct <structname>drm_connector</structname> instance. The
+          instance is created as other KMS objects and initialized by setting the
+          following fields.
+        </para>
+        <variablelist>
+          <varlistentry>
+            <term><structfield>interlace_allowed</structfield></term>
+            <listitem><para>
+              Whether the connector can handle interlaced modes.
+            </para></listitem>
+          </varlistentry>
+          <varlistentry>
+            <term><structfield>doublescan_allowed</structfield></term>
+            <listitem><para>
+              Whether the connector can handle doublescan.
+            </para></listitem>
+          </varlistentry>
+          <varlistentry>
+            <term><structfield>display_info
+            </structfield></term>
+            <listitem><para>
+              Display information is filled from EDID information when a display
+              is detected. For non hot-pluggable displays such as flat panels in
+              embedded systems, the driver should initialize the
+              <structfield>display_info</structfield>.<structfield>width_mm</structfield>
+              and
+              <structfield>display_info</structfield>.<structfield>height_mm</structfield>
+              fields with the physical size of the display.
+            </para></listitem>
+          </varlistentry>
+          <varlistentry>
+            <term id="drm-kms-connector-polled"><structfield>polled</structfield></term>
+            <listitem><para>
+              Connector polling mode, a combination of
+              <variablelist>
+                <varlistentry>
+                  <term>DRM_CONNECTOR_POLL_HPD</term>
+                  <listitem><para>
+                    The connector generates hotplug events and doesn't need to be
+                    periodically polled. The CONNECT and DISCONNECT flags must not
+                    be set together with the HPD flag.
+                  </para></listitem>
+                </varlistentry>
+                <varlistentry>
+                  <term>DRM_CONNECTOR_POLL_CONNECT</term>
+                  <listitem><para>
+                    Periodically poll the connector for connection.
+                  </para></listitem>
+                </varlistentry>
+                <varlistentry>
+                  <term>DRM_CONNECTOR_POLL_DISCONNECT</term>
+                  <listitem><para>
+                    Periodically poll the connector for disconnection.
+                  </para></listitem>
+                </varlistentry>
+              </variablelist>
+              Set to 0 for connectors that don't support connection status
+              discovery.
+            </para></listitem>
+          </varlistentry>
+        </variablelist>
+        <para>
+          The connector is then registered with a call to
+          <function>drm_connector_init</function> with a pointer to the connector
+          functions and a connector type, and exposed through sysfs with a call to
+          <function>drm_sysfs_connector_add</function>.
+        </para>
+        <para>
+          Supported connector types are
+          <itemizedlist>
+            <listitem>DRM_MODE_CONNECTOR_VGA</listitem>
+            <listitem>DRM_MODE_CONNECTOR_DVII</listitem>
+            <listitem>DRM_MODE_CONNECTOR_DVID</listitem>
+            <listitem>DRM_MODE_CONNECTOR_DVIA</listitem>
+            <listitem>DRM_MODE_CONNECTOR_Composite</listitem>
+            <listitem>DRM_MODE_CONNECTOR_SVIDEO</listitem>
+            <listitem>DRM_MODE_CONNECTOR_LVDS</listitem>
+            <listitem>DRM_MODE_CONNECTOR_Component</listitem>
+            <listitem>DRM_MODE_CONNECTOR_9PinDIN</listitem>
+            <listitem>DRM_MODE_CONNECTOR_DisplayPort</listitem>
+            <listitem>DRM_MODE_CONNECTOR_HDMIA</listitem>
+            <listitem>DRM_MODE_CONNECTOR_HDMIB</listitem>
+            <listitem>DRM_MODE_CONNECTOR_TV</listitem>
+            <listitem>DRM_MODE_CONNECTOR_eDP</listitem>
+            <listitem>DRM_MODE_CONNECTOR_VIRTUAL</listitem>
+          </itemizedlist>
+        </para>
+        <para>
+          Connectors must be attached to an encoder to be used. For devices that
+          map connectors to encoders 1:1, the connector should be attached at
+          initialization time with a call to
+          <function>drm_mode_connector_attach_encoder</function>. The driver must
+          also set the <structname>drm_connector</structname>
+          <structfield>encoder</structfield> field to point to the attached
+          encoder.
+        </para>
+        <para>
+          Finally, drivers must initialize the connectors state change detection
+          with a call to <function>drm_kms_helper_poll_init</function>. If at
+          least one connector is pollable but can't generate hotplug interrupts
+          (indicated by the DRM_CONNECTOR_POLL_CONNECT and
+          DRM_CONNECTOR_POLL_DISCONNECT connector flags), a delayed work will
+          automatically be queued to periodically poll for changes. Connectors
+          that can generate hotplug interrupts must be marked with the
+          DRM_CONNECTOR_POLL_HPD flag instead, and their interrupt handler must
+          call <function>drm_helper_hpd_irq_event</function>. The function will
+          queue a delayed work to check the state of all connectors, but no
+          periodic polling will be done.
+        </para>
+      </sect3>
+      <sect3>
+        <title>Connector Operations</title>
+        <note><para>
+          Unless otherwise state, all operations are mandatory.
+        </para></note>
+        <sect4>
+          <title>DPMS</title>
+          <synopsis>void (*dpms)(struct drm_connector *connector, int mode);</synopsis>
+          <para>
+            The DPMS operation sets the power state of a connector. The mode
+            argument is one of
+            <itemizedlist>
+              <listitem><para>DRM_MODE_DPMS_ON</para></listitem>
+              <listitem><para>DRM_MODE_DPMS_STANDBY</para></listitem>
+              <listitem><para>DRM_MODE_DPMS_SUSPEND</para></listitem>
+              <listitem><para>DRM_MODE_DPMS_OFF</para></listitem>
+            </itemizedlist>
+          </para>
+          <para>
+            In all but DPMS_ON mode the encoder to which the connector is attached
+            should put the display in low-power mode by driving its signals
+            appropriately. If more than one connector is attached to the encoder
+            care should be taken not to change the power state of other displays as
+            a side effect. Low-power mode should be propagated to the encoders and
+            CRTCs when all related connectors are put in low-power mode.
+          </para>
+        </sect4>
+        <sect4>
+          <title>Modes</title>
+          <synopsis>int (*fill_modes)(struct drm_connector *connector, uint32_t max_width,
+                      uint32_t max_height);</synopsis>
+          <para>
+            Fill the mode list with all supported modes for the connector. If the
+            <parameter>max_width</parameter> and <parameter>max_height</parameter>
+            arguments are non-zero, the implementation must ignore all modes wider
+            than <parameter>max_width</parameter> or higher than
+            <parameter>max_height</parameter>.
+          </para>
+          <para>
+            The connector must also fill in this operation its
+            <structfield>display_info</structfield>
+            <structfield>width_mm</structfield> and
+            <structfield>height_mm</structfield> fields with the connected display
+            physical size in millimeters. The fields should be set to 0 if the value
+            isn't known or is not applicable (for instance for projector devices).
+          </para>
+        </sect4>
+        <sect4>
+          <title>Connection Status</title>
+          <para>
+            The connection status is updated through polling or hotplug events when
+            supported (see <xref linkend="drm-kms-connector-polled"/>). The status
+            value is reported to userspace through ioctls and must not be used
+            inside the driver, as it only gets initialized by a call to
+            <function>drm_mode_getconnector</function> from userspace.
+          </para>
+          <synopsis>enum drm_connector_status (*detect)(struct drm_connector *connector,
+                                        bool force);</synopsis>
+          <para>
+            Check to see if anything is attached to the connector. The
+            <parameter>force</parameter> parameter is set to false whilst polling or
+            to true when checking the connector due to user request.
+            <parameter>force</parameter> can be used by the driver to avoid
+            expensive, destructive operations during automated probing.
+          </para>
+          <para>
+            Return connector_status_connected if something is connected to the
+            connector, connector_status_disconnected if nothing is connected and
+            connector_status_unknown if the connection state isn't known.
+          </para>
+          <para>
+            Drivers should only return connector_status_connected if the connection
+            status has really been probed as connected. Connectors that can't detect
+            the connection status, or failed connection status probes, should return
+            connector_status_unknown.
+          </para>
+        </sect4>
+        <sect4>
+          <title>Miscellaneous</title>
+          <itemizedlist>
+            <listitem>
+              <synopsis>void (*destroy)(struct drm_connector *connector);</synopsis>
+              <para>
+                Destroy the connector when not needed anymore. See
+                <xref linkend="drm-kms-init"/>.
+              </para>
+            </listitem>
+          </itemizedlist>
+        </sect4>
+      </sect3>
+    </sect2>
+    <sect2>
+      <title>Cleanup</title>
+      <para>
+        The DRM core manages its objects' lifetime. When an object is not needed
+	anymore the core calls its destroy function, which must clean up and
+	free every resource allocated for the object. Every
+	<function>drm_*_init</function> call must be matched with a
+	corresponding <function>drm_*_cleanup</function> call to cleanup CRTCs
+	(<function>drm_crtc_cleanup</function>), planes
+	(<function>drm_plane_cleanup</function>), encoders
+	(<function>drm_encoder_cleanup</function>) and connectors
+	(<function>drm_connector_cleanup</function>). Furthermore, connectors
+	that have been added to sysfs must be removed by a call to
+	<function>drm_sysfs_connector_remove</function> before calling
+	<function>drm_connector_cleanup</function>.
+      </para>
+      <para>
+        Connectors state change detection must be cleanup up with a call to
+	<function>drm_kms_helper_poll_fini</function>.
+      </para>
+    </sect2>
+    <sect2>
+      <title>Output discovery and initialization example</title>
+      <programlisting><![CDATA[
 void intel_crt_init(struct drm_device *dev)
 {
 	struct drm_connector *connector;
@@ -556,252 +1610,741 @@ void intel_crt_init(struct drm_device *dev)
 	drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs);
 
 	drm_sysfs_connector_add(connector);
-}
-]]>
-	</programlisting>
-	<para>
-	  In the example above (again, taken from the i915 driver), a
-	  CRT connector and encoder combination is created.  A device-specific
-	  i2c bus is also created for fetching EDID data and
-	  performing monitor detection.  Once the process is complete,
-	  the new connector is registered with sysfs to make its
-	  properties available to applications.
-	</para>
-	<sect4>
-	  <title>Helper functions and core functions</title>
-	  <para>
-	    Since many PC-class graphics devices have similar display output
-	    designs, the DRM provides a set of helper functions to make
-	    output management easier.  The core helper routines handle
-	    encoder re-routing and the disabling of unused functions following
-	    mode setting.  Using the helpers is optional, but recommended for
-	    devices with PC-style architectures (i.e. a set of display planes
-	    for feeding pixels to encoders which are in turn routed to
-	    connectors).  Devices with more complex requirements needing
-	    finer grained management may opt to use the core callbacks
-	    directly.
-	  </para>
-	  <para>
-	    [Insert typical diagram here.]  [Insert OMAP style config here.]
-	  </para>
-	</sect4>
-	<para>
-	  Each encoder object needs to provide:
-	  <itemizedlist>
-	    <listitem>
-	      A DPMS (basically on/off) function.
-	    </listitem>
-	    <listitem>
-	      A mode-fixup function (for converting requested modes into
-	      native hardware timings).
-	    </listitem>
-	    <listitem>
-	      Functions (prepare, set, and commit) for use by the core DRM
-	      helper functions.
-	    </listitem>
-	  </itemizedlist>
-	  Connector helpers need to provide functions (mode-fetch, validity,
-	  and encoder-matching) for returning an ideal encoder for a given
-	  connector.  The core connector functions include a DPMS callback,
-	  save/restore routines (deprecated), detection, mode probing,
-	  property handling, and cleanup functions.
-	</para>
-<!--!Edrivers/char/drm/drm_crtc.h-->
-<!--!Edrivers/char/drm/drm_crtc.c-->
-<!--!Edrivers/char/drm/drm_crtc_helper.c-->
-      </sect3>
+}]]></programlisting>
+      <para>
+        In the example above (taken from the i915 driver), a CRTC, connector and
+        encoder combination is created. A device-specific i2c bus is also
+        created for fetching EDID data and performing monitor detection. Once
+        the process is complete, the new connector is registered with sysfs to
+        make its properties available to applications.
+      </para>
     </sect2>
   </sect1>
 
-  <!-- Internals: vblank handling -->
+  <!-- Internals: mid-layer helper functions -->
 
   <sect1>
-    <title>VBlank event handling</title>
+    <title>Mid-layer Helper Functions</title>
     <para>
-      The DRM core exposes two vertical blank related ioctls:
-      <variablelist>
-        <varlistentry>
-          <term>DRM_IOCTL_WAIT_VBLANK</term>
-          <listitem>
-            <para>
-              This takes a struct drm_wait_vblank structure as its argument,
-              and it is used to block or request a signal when a specified
-              vblank event occurs.
-            </para>
-          </listitem>
-        </varlistentry>
-        <varlistentry>
-          <term>DRM_IOCTL_MODESET_CTL</term>
-          <listitem>
-            <para>
-              This should be called by application level drivers before and
-              after mode setting, since on many devices the vertical blank
-              counter is reset at that time.  Internally, the DRM snapshots
-              the last vblank count when the ioctl is called with the
-              _DRM_PRE_MODESET command, so that the counter won't go backwards
-              (which is dealt with when _DRM_POST_MODESET is used).
-            </para>
-          </listitem>
-        </varlistentry>
-      </variablelist>
-<!--!Edrivers/char/drm/drm_irq.c-->
+      The CRTC, encoder and connector functions provided by the drivers
+      implement the DRM API. They're called by the DRM core and ioctl handlers
+      to handle device state changes and configuration request. As implementing
+      those functions often requires logic not specific to drivers, mid-layer
+      helper functions are available to avoid duplicating boilerplate code.
+    </para>
+    <para>
+      The DRM core contains one mid-layer implementation. The mid-layer provides
+      implementations of several CRTC, encoder and connector functions (called
+      from the top of the mid-layer) that pre-process requests and call
+      lower-level functions provided by the driver (at the bottom of the
+      mid-layer). For instance, the
+      <function>drm_crtc_helper_set_config</function> function can be used to
+      fill the struct <structname>drm_crtc_funcs</structname>
+      <structfield>set_config</structfield> field. When called, it will split
+      the <methodname>set_config</methodname> operation in smaller, simpler
+      operations and call the driver to handle them.
     </para>
     <para>
-      To support the functions above, the DRM core provides several
-      helper functions for tracking vertical blank counters, and
-      requires drivers to provide several callbacks:
-      get_vblank_counter(), enable_vblank() and disable_vblank().  The
-      core uses get_vblank_counter() to keep the counter accurate
-      across interrupt disable periods.  It should return the current
-      vertical blank event count, which is often tracked in a device
-      register.  The enable and disable vblank callbacks should enable
-      and disable vertical blank interrupts, respectively.  In the
-      absence of DRM clients waiting on vblank events, the core DRM
-      code uses the disable_vblank() function to disable
-      interrupts, which saves power.  They are re-enabled again when
-      a client calls the vblank wait ioctl above.
+      To use the mid-layer, drivers call <function>drm_crtc_helper_add</function>,
+      <function>drm_encoder_helper_add</function> and
+      <function>drm_connector_helper_add</function> functions to install their
+      mid-layer bottom operations handlers, and fill the
+      <structname>drm_crtc_funcs</structname>,
+      <structname>drm_encoder_funcs</structname> and
+      <structname>drm_connector_funcs</structname> structures with pointers to
+      the mid-layer top API functions. Installing the mid-layer bottom operation
+      handlers is best done right after registering the corresponding KMS object.
     </para>
     <para>
-      A device that doesn't provide a count register may simply use an
-      internal atomic counter incremented on every vertical blank
-      interrupt (and then treat the enable_vblank() and disable_vblank()
-      callbacks as no-ops).
+      The mid-layer is not split between CRTC, encoder and connector operations.
+      To use it, a driver must provide bottom functions for all of the three KMS
+      entities.
     </para>
+    <sect2>
+      <title>Helper Functions</title>
+      <itemizedlist>
+        <listitem>
+          <synopsis>int drm_crtc_helper_set_config(struct drm_mode_set *set);</synopsis>
+          <para>
+            The <function>drm_crtc_helper_set_config</function> helper function
+            is a CRTC <methodname>set_config</methodname> implementation. It
+            first tries to locate the best encoder for each connector by calling
+            the connector <methodname>best_encoder</methodname> helper
+            operation.
+          </para>
+          <para>
+            After locating the appropriate encoders, the helper function will
+            call the <methodname>mode_fixup</methodname> encoder and CRTC helper
+            operations to adjust the requested mode, or reject it completely in
+            which case an error will be returned to the application. If the new
+            configuration after mode adjustment is identical to the current
+            configuration the helper function will return without performing any
+            other operation.
+          </para>
+          <para>
+            If the adjusted mode is identical to the current mode but changes to
+            the frame buffer need to be applied, the
+            <function>drm_crtc_helper_set_config</function> function will call
+            the CRTC <methodname>mode_set_base</methodname> helper operation. If
+            the adjusted mode differs from the current mode, or if the
+            <methodname>mode_set_base</methodname> helper operation is not
+            provided, the helper function performs a full mode set sequence by
+            calling the <methodname>prepare</methodname>,
+            <methodname>mode_set</methodname> and
+            <methodname>commit</methodname> CRTC and encoder helper operations,
+            in that order.
+          </para>
+        </listitem>
+        <listitem>
+          <synopsis>void drm_helper_connector_dpms(struct drm_connector *connector, int mode);</synopsis>
+          <para>
+            The <function>drm_helper_connector_dpms</function> helper function
+            is a connector <methodname>dpms</methodname> implementation that
+            tracks power state of connectors. To use the function, drivers must
+            provide <methodname>dpms</methodname> helper operations for CRTCs
+            and encoders to apply the DPMS state to the device.
+          </para>
+          <para>
+            The mid-layer doesn't track the power state of CRTCs and encoders.
+            The <methodname>dpms</methodname> helper operations can thus be
+            called with a mode identical to the currently active mode.
+          </para>
+        </listitem>
+        <listitem>
+          <synopsis>int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
+                                            uint32_t maxX, uint32_t maxY);</synopsis>
+          <para>
+            The <function>drm_helper_probe_single_connector_modes</function> helper
+            function is a connector <methodname>fill_modes</methodname>
+            implementation that updates the connection status for the connector
+            and then retrieves a list of modes by calling the connector
+            <methodname>get_modes</methodname> helper operation.
+          </para>
+          <para>
+            The function filters out modes larger than
+            <parameter>max_width</parameter> and <parameter>max_height</parameter>
+            if specified. It then calls the connector
+            <methodname>mode_valid</methodname> helper operation for  each mode in
+            the probed list to check whether the mode is valid for the connector.
+          </para>
+        </listitem>
+      </itemizedlist>
+    </sect2>
+    <sect2>
+      <title>CRTC Helper Operations</title>
+      <itemizedlist>
+        <listitem id="drm-helper-crtc-mode-fixup">
+          <synopsis>bool (*mode_fixup)(struct drm_crtc *crtc,
+                       const struct drm_display_mode *mode,
+                       struct drm_display_mode *adjusted_mode);</synopsis>
+          <para>
+            Let CRTCs adjust the requested mode or reject it completely. This
+            operation returns true if the mode is accepted (possibly after being
+            adjusted) or false if it is rejected.
+          </para>
+          <para>
+            The <methodname>mode_fixup</methodname> operation should reject the
+            mode if it can't reasonably use it. The definition of "reasonable"
+            is currently fuzzy in this context. One possible behaviour would be
+            to set the adjusted mode to the panel timings when a fixed-mode
+            panel is used with hardware capable of scaling. Another behaviour
+            would be to accept any input mode and adjust it to the closest mode
+            supported by the hardware (FIXME: This needs to be clarified).
+          </para>
+        </listitem>
+        <listitem>
+          <synopsis>int (*mode_set_base)(struct drm_crtc *crtc, int x, int y,
+                     struct drm_framebuffer *old_fb)</synopsis>
+          <para>
+            Move the CRTC on the current frame buffer (stored in
+            <literal>crtc-&gt;fb</literal>) to position (x,y). Any of the frame
+            buffer, x position or y position may have been modified.
+          </para>
+          <para>
+            This helper operation is optional. If not provided, the
+            <function>drm_crtc_helper_set_config</function> function will fall
+            back to the <methodname>mode_set</methodname> helper operation.
+          </para>
+          <note><para>
+            FIXME: Why are x and y passed as arguments, as they can be accessed
+            through <literal>crtc-&gt;x</literal> and
+            <literal>crtc-&gt;y</literal>?
+          </para></note>
+        </listitem>
+        <listitem>
+          <synopsis>void (*prepare)(struct drm_crtc *crtc);</synopsis>
+          <para>
+            Prepare the CRTC for mode setting. This operation is called after
+            validating the requested mode. Drivers use it to perform
+            device-specific operations required before setting the new mode.
+          </para>
+        </listitem>
+        <listitem>
+          <synopsis>int (*mode_set)(struct drm_crtc *crtc, struct drm_display_mode *mode,
+                struct drm_display_mode *adjusted_mode, int x, int y,
+                struct drm_framebuffer *old_fb);</synopsis>
+          <para>
+            Set a new mode, position and frame buffer. Depending on the device
+            requirements, the mode can be stored internally by the driver and
+            applied in the <methodname>commit</methodname> operation, or
+            programmed to the hardware immediately.
+          </para>
+          <para>
+            The <methodname>mode_set</methodname> operation returns 0 on success
+	    or a negative error code if an error occurs.
+          </para>
+        </listitem>
+        <listitem>
+          <synopsis>void (*commit)(struct drm_crtc *crtc);</synopsis>
+          <para>
+            Commit a mode. This operation is called after setting the new mode.
+            Upon return the device must use the new mode and be fully
+            operational.
+          </para>
+        </listitem>
+      </itemizedlist>
+    </sect2>
+    <sect2>
+      <title>Encoder Helper Operations</title>
+      <itemizedlist>
+        <listitem>
+          <synopsis>bool (*mode_fixup)(struct drm_encoder *encoder,
+                       const struct drm_display_mode *mode,
+                       struct drm_display_mode *adjusted_mode);</synopsis>
+          <note><para>
+            FIXME: The mode argument be const, but the i915 driver modifies
+            mode-&gt;clock in <function>intel_dp_mode_fixup</function>.
+          </para></note>
+          <para>
+            Let encoders adjust the requested mode or reject it completely. This
+            operation returns true if the mode is accepted (possibly after being
+            adjusted) or false if it is rejected. See the
+            <link linkend="drm-helper-crtc-mode-fixup">mode_fixup CRTC helper
+            operation</link> for an explanation of the allowed adjustments.
+          </para>
+        </listitem>
+        <listitem>
+          <synopsis>void (*prepare)(struct drm_encoder *encoder);</synopsis>
+          <para>
+            Prepare the encoder for mode setting. This operation is called after
+            validating the requested mode. Drivers use it to perform
+            device-specific operations required before setting the new mode.
+          </para>
+        </listitem>
+        <listitem>
+          <synopsis>void (*mode_set)(struct drm_encoder *encoder,
+                 struct drm_display_mode *mode,
+                 struct drm_display_mode *adjusted_mode);</synopsis>
+          <para>
+            Set a new mode. Depending on the device requirements, the mode can
+            be stored internally by the driver and applied in the
+            <methodname>commit</methodname> operation, or programmed to the
+            hardware immediately.
+          </para>
+        </listitem>
+        <listitem>
+          <synopsis>void (*commit)(struct drm_encoder *encoder);</synopsis>
+          <para>
+            Commit a mode. This operation is called after setting the new mode.
+            Upon return the device must use the new mode and be fully
+            operational.
+          </para>
+        </listitem>
+      </itemizedlist>
+    </sect2>
+    <sect2>
+      <title>Connector Helper Operations</title>
+      <itemizedlist>
+        <listitem>
+          <synopsis>struct drm_encoder *(*best_encoder)(struct drm_connector *connector);</synopsis>
+          <para>
+            Return a pointer to the best encoder for the connecter. Device that
+            map connectors to encoders 1:1 simply return the pointer to the
+            associated encoder. This operation is mandatory.
+          </para>
+        </listitem>
+        <listitem>
+          <synopsis>int (*get_modes)(struct drm_connector *connector);</synopsis>
+          <para>
+            Fill the connector's <structfield>probed_modes</structfield> list
+            by parsing EDID data with <function>drm_add_edid_modes</function> or
+            calling <function>drm_mode_probed_add</function> directly for every
+            supported mode and return the number of modes it has detected. This
+            operation is mandatory.
+          </para>
+          <para>
+            When adding modes manually the driver creates each mode with a call to
+            <function>drm_mode_create</function> and must fill the following fields.
+            <itemizedlist>
+              <listitem>
+                <synopsis>__u32 type;</synopsis>
+                <para>
+                  Mode type bitmask, a combination of
+                  <variablelist>
+                    <varlistentry>
+                      <term>DRM_MODE_TYPE_BUILTIN</term>
+                      <listitem><para>not used?</para></listitem>
+                    </varlistentry>
+                    <varlistentry>
+                      <term>DRM_MODE_TYPE_CLOCK_C</term>
+                      <listitem><para>not used?</para></listitem>
+                    </varlistentry>
+                    <varlistentry>
+                      <term>DRM_MODE_TYPE_CRTC_C</term>
+                      <listitem><para>not used?</para></listitem>
+                    </varlistentry>
+                    <varlistentry>
+                      <term>
+        DRM_MODE_TYPE_PREFERRED - The preferred mode for the connector
+                      </term>
+                      <listitem>
+                        <para>not used?</para>
+                      </listitem>
+                    </varlistentry>
+                    <varlistentry>
+                      <term>DRM_MODE_TYPE_DEFAULT</term>
+                      <listitem><para>not used?</para></listitem>
+                    </varlistentry>
+                    <varlistentry>
+                      <term>DRM_MODE_TYPE_USERDEF</term>
+                      <listitem><para>not used?</para></listitem>
+                    </varlistentry>
+                    <varlistentry>
+                      <term>DRM_MODE_TYPE_DRIVER</term>
+                      <listitem>
+                        <para>
+                          The mode has been created by the driver (as opposed to
+                          to user-created modes).
+                        </para>
+                      </listitem>
+                    </varlistentry>
+                  </variablelist>
+                  Drivers must set the DRM_MODE_TYPE_DRIVER bit for all modes they
+                  create, and set the DRM_MODE_TYPE_PREFERRED bit for the preferred
+                  mode.
+                </para>
+              </listitem>
+              <listitem>
+                <synopsis>__u32 clock;</synopsis>
+                <para>Pixel clock frequency in kHz unit</para>
+              </listitem>
+              <listitem>
+                <synopsis>__u16 hdisplay, hsync_start, hsync_end, htotal;
+    __u16 vdisplay, vsync_start, vsync_end, vtotal;</synopsis>
+                <para>Horizontal and vertical timing information</para>
+                <screen><![CDATA[
+             Active                 Front           Sync           Back
+             Region                 Porch                          Porch
+    <-----------------------><----------------><-------------><-------------->
+
+      //////////////////////|
+     ////////////////////// |
+    //////////////////////  |..................               ................
+                                               _______________
+
+    <----- [hv]display ----->
+    <------------- [hv]sync_start ------------>
+    <--------------------- [hv]sync_end --------------------->
+    <-------------------------------- [hv]total ----------------------------->
+]]></screen>
+              </listitem>
+              <listitem>
+                <synopsis>__u16 hskew;
+    __u16 vscan;</synopsis>
+                <para>Unknown</para>
+              </listitem>
+              <listitem>
+                <synopsis>__u32 flags;</synopsis>
+                <para>
+                  Mode flags, a combination of
+                  <variablelist>
+                    <varlistentry>
+                      <term>DRM_MODE_FLAG_PHSYNC</term>
+                      <listitem><para>
+                        Horizontal sync is active high
+                      </para></listitem>
+                    </varlistentry>
+                    <varlistentry>
+                      <term>DRM_MODE_FLAG_NHSYNC</term>
+                      <listitem><para>
+                        Horizontal sync is active low
+                      </para></listitem>
+                    </varlistentry>
+                    <varlistentry>
+                      <term>DRM_MODE_FLAG_PVSYNC</term>
+                      <listitem><para>
+                        Vertical sync is active high
+                      </para></listitem>
+                    </varlistentry>
+                    <varlistentry>
+                      <term>DRM_MODE_FLAG_NVSYNC</term>
+                      <listitem><para>
+                        Vertical sync is active low
+                      </para></listitem>
+                    </varlistentry>
+                    <varlistentry>
+                      <term>DRM_MODE_FLAG_INTERLACE</term>
+                      <listitem><para>
+                        Mode is interlaced
+                      </para></listitem>
+                    </varlistentry>
+                    <varlistentry>
+                      <term>DRM_MODE_FLAG_DBLSCAN</term>
+                      <listitem><para>
+                        Mode uses doublescan
+                      </para></listitem>
+                    </varlistentry>
+                    <varlistentry>
+                      <term>DRM_MODE_FLAG_CSYNC</term>
+                      <listitem><para>
+                        Mode uses composite sync
+                      </para></listitem>
+                    </varlistentry>
+                    <varlistentry>
+                      <term>DRM_MODE_FLAG_PCSYNC</term>
+                      <listitem><para>
+                        Composite sync is active high
+                      </para></listitem>
+                    </varlistentry>
+                    <varlistentry>
+                      <term>DRM_MODE_FLAG_NCSYNC</term>
+                      <listitem><para>
+                        Composite sync is active low
+                      </para></listitem>
+                    </varlistentry>
+                    <varlistentry>
+                      <term>DRM_MODE_FLAG_HSKEW</term>
+                      <listitem><para>
+                        hskew provided (not used?)
+                      </para></listitem>
+                    </varlistentry>
+                    <varlistentry>
+                      <term>DRM_MODE_FLAG_BCAST</term>
+                      <listitem><para>
+                        not used?
+                      </para></listitem>
+                    </varlistentry>
+                    <varlistentry>
+                      <term>DRM_MODE_FLAG_PIXMUX</term>
+                      <listitem><para>
+                        not used?
+                      </para></listitem>
+                    </varlistentry>
+                    <varlistentry>
+                      <term>DRM_MODE_FLAG_DBLCLK</term>
+                      <listitem><para>
+                        not used?
+                      </para></listitem>
+                    </varlistentry>
+                    <varlistentry>
+                      <term>DRM_MODE_FLAG_CLKDIV2</term>
+                      <listitem><para>
+                        ?
+                      </para></listitem>
+                    </varlistentry>
+                  </variablelist>
+                </para>
+                <para>
+                  Note that modes marked with the INTERLACE or DBLSCAN flags will be
+                  filtered out by
+                  <function>drm_helper_probe_single_connector_modes</function> if
+                  the connector's <structfield>interlace_allowed</structfield> or
+                  <structfield>doublescan_allowed</structfield> field is set to 0.
+                </para>
+              </listitem>
+              <listitem>
+                <synopsis>char name[DRM_DISPLAY_MODE_LEN];</synopsis>
+                <para>
+                  Mode name. The driver must call
+                  <function>drm_mode_set_name</function> to fill the mode name from
+                  <structfield>hdisplay</structfield>,
+                  <structfield>vdisplay</structfield> and interlace flag after
+                  filling the corresponding fields.
+                </para>
+              </listitem>
+            </itemizedlist>
+          </para>
+          <para>
+            The <structfield>vrefresh</structfield> value is computed by
+            <function>drm_helper_probe_single_connector_modes</function>.
+          </para>
+          <para>
+            When parsing EDID data, <function>drm_add_edid_modes</function> fill the
+            connector <structfield>display_info</structfield>
+            <structfield>width_mm</structfield> and
+            <structfield>height_mm</structfield> fields. When creating modes
+            manually the <methodname>get_modes</methodname> helper operation must
+            set the <structfield>display_info</structfield>
+            <structfield>width_mm</structfield> and
+            <structfield>height_mm</structfield> fields if they haven't been set
+            already (for instance at initilization time when a fixed-size panel is
+            attached to the connector). The mode <structfield>width_mm</structfield>
+            and <structfield>height_mm</structfield> fields are only used internally
+            during EDID parsing and should not be set when creating modes manually.
+          </para>
+        </listitem>
+        <listitem>
+          <synopsis>int (*mode_valid)(struct drm_connector *connector,
+		  struct drm_display_mode *mode);</synopsis>
+          <para>
+            Verify whether a mode is valid for the connector. Return MODE_OK for
+            supported modes and one of the enum drm_mode_status values (MODE_*)
+            for unsupported modes. This operation is mandatory.
+          </para>
+          <para>
+            As the mode rejection reason is currently not used beside for
+            immediately removing the unsupported mode, an implementation can
+            return MODE_BAD regardless of the exact reason why the mode is not
+            valid.
+          </para>
+          <note><para>
+            Note that the <methodname>mode_valid</methodname> helper operation is
+            only called for modes detected by the device, and
+            <emphasis>not</emphasis> for modes set by the user through the CRTC
+            <methodname>set_config</methodname> operation.
+          </para></note>
+        </listitem>
+      </itemizedlist>
+    </sect2>
   </sect1>
 
-  <sect1>
-    <title>Memory management</title>
+  <!-- Internals: vertical blanking -->
+
+  <sect1 id="drm-vertical-blank">
+    <title>Vertical Blanking</title>
+    <para>
+      Vertical blanking plays a major role in graphics rendering. To achieve
+      tear-free display, users must synchronize page flips and/or rendering to
+      vertical blanking. The DRM API offers ioctls to perform page flips
+      synchronized to vertical blanking and wait for vertical blanking.
+    </para>
+    <para>
+      The DRM core handles most of the vertical blanking management logic, which
+      involves filtering out spurious interrupts, keeping race-free blanking
+      counters, coping with counter wrap-around and resets and keeping use
+      counts. It relies on the driver to generate vertical blanking interrupts
+      and optionally provide a hardware vertical blanking counter. Drivers must
+      implement the following operations.
+    </para>
+    <itemizedlist>
+      <listitem>
+        <synopsis>int (*enable_vblank) (struct drm_device *dev, int crtc);
+void (*disable_vblank) (struct drm_device *dev, int crtc);</synopsis>
+        <para>
+	  Enable or disable vertical blanking interrupts for the given CRTC.
+	</para>
+      </listitem>
+      <listitem>
+        <synopsis>u32 (*get_vblank_counter) (struct drm_device *dev, int crtc);</synopsis>
+        <para>
+	  Retrieve the value of the vertical blanking counter for the given
+	  CRTC. If the hardware maintains a vertical blanking counter its value
+	  should be returned. Otherwise drivers can use the
+	  <function>drm_vblank_count</function> helper function to handle this
+	  operation.
+	</para>
+      </listitem>
+    </itemizedlist>
     <para>
-      The memory manager lies at the heart of many DRM operations; it
-      is required to support advanced client features like OpenGL
-      pbuffers.  The DRM currently contains two memory managers: TTM
-      and GEM.
+      Drivers must initialize the vertical blanking handling core with a call to
+      <function>drm_vblank_init</function> in their
+      <methodname>load</methodname> operation. The function will set the struct
+      <structname>drm_device</structname>
+      <structfield>vblank_disable_allowed</structfield> field to 0. This will
+      keep vertical blanking interrupts enabled permanently until the first mode
+      set operation, where <structfield>vblank_disable_allowed</structfield> is
+      set to 1. The reason behind this is not clear. Drivers can set the field
+      to 1 after <function>calling drm_vblank_init</function> to make vertical
+      blanking interrupts dynamically managed from the beginning.
     </para>
+    <para>
+      Vertical blanking interrupts can be enabled by the DRM core or by drivers
+      themselves (for instance to handle page flipping operations). The DRM core
+      maintains a vertical blanking use count to ensure that the interrupts are
+      not disabled while a user still needs them. To increment the use count,
+      drivers call <function>drm_vblank_get</function>. Upon return vertical
+      blanking interrupts are guaranteed to be enabled.
+    </para>
+    <para>
+      To decrement the use count drivers call
+      <function>drm_vblank_put</function>. Only when the use count drops to zero
+      will the DRM core disable the vertical blanking interrupts after a delay
+      by scheduling a timer. The delay is accessible through the vblankoffdelay
+      module parameter or the <varname>drm_vblank_offdelay</varname> global
+      variable and expressed in milliseconds. Its default value is 5000 ms.
+    </para>
+    <para>
+      When a vertical blanking interrupt occurs drivers only need to call the
+      <function>drm_handle_vblank</function> function to account for the
+      interrupt.
+    </para>
+    <para>
+      Resources allocated by <function>drm_vblank_init</function> must be freed
+      with a call to <function>drm_vblank_cleanup</function> in the driver
+      <methodname>unload</methodname> operation handler.
+    </para>
+  </sect1>
+
+  <!-- Internals: open/close, file operations and ioctls -->
 
+  <sect1>
+    <title>Open/Close, File Operations and IOCTLs</title>
     <sect2>
-      <title>The Translation Table Manager (TTM)</title>
+      <title>Open and Close</title>
+      <synopsis>int (*firstopen) (struct drm_device *);
+void (*lastclose) (struct drm_device *);
+int (*open) (struct drm_device *, struct drm_file *);
+void (*preclose) (struct drm_device *, struct drm_file *);
+void (*postclose) (struct drm_device *, struct drm_file *);</synopsis>
+      <abstract>Open and close handlers. None of those methods are mandatory.
+      </abstract>
       <para>
-	TTM was developed by Tungsten Graphics, primarily by Thomas
-	Hellström, and is intended to be a flexible, high performance
-	graphics memory manager.
+        The <methodname>firstopen</methodname> method is called by the DRM core
+	when an application opens a device that has no other opened file handle.
+	Similarly the <methodname>lastclose</methodname> method is called when
+	the last application holding a file handle opened on the device closes
+	it. Both methods are mostly used for UMS (User Mode Setting) drivers to
+	acquire and release device resources which should be done in the
+	<methodname>load</methodname> and <methodname>unload</methodname>
+	methods for KMS drivers.
       </para>
       <para>
-	Drivers wishing to support TTM must fill out a drm_bo_driver
-	structure.
+        Note that the <methodname>lastclose</methodname> method is also called
+	at module unload time or, for hot-pluggable devices, when the device is
+	unplugged. The <methodname>firstopen</methodname> and
+	<methodname>lastclose</methodname> calls can thus be unbalanced.
       </para>
       <para>
-	TTM design background and information belongs here.
+        The <methodname>open</methodname> method is called every time the device
+	is opened by an application. Drivers can allocate per-file private data
+	in this method and store them in the struct
+	<structname>drm_file</structname> <structfield>driver_priv</structfield>
+	field. Note that the <methodname>open</methodname> method is called
+	before <methodname>firstopen</methodname>.
+      </para>
+      <para>
+        The close operation is split into <methodname>preclose</methodname> and
+	<methodname>postclose</methodname> methods. Drivers must stop and
+	cleanup all per-file operations in the <methodname>preclose</methodname>
+	method. For instance pending vertical blanking and page flip events must
+	be cancelled. No per-file operation is allowed on the file handle after
+	returning from the <methodname>preclose</methodname> method.
+      </para>
+      <para>
+        Finally the <methodname>postclose</methodname> method is called as the
+	last step of the close operation, right before calling the
+	<methodname>lastclose</methodname> method if no other open file handle
+	exists for the device. Drivers that have allocated per-file private data
+	in the <methodname>open</methodname> method should free it here.
+      </para>
+      <para>
+        The <methodname>lastclose</methodname> method should restore CRTC and
+	plane properties to default value, so that a subsequent open of the
+	device will not inherit state from the previous user.
       </para>
     </sect2>
-
     <sect2>
-      <title>The Graphics Execution Manager (GEM)</title>
+      <title>File Operations</title>
+      <synopsis>const struct file_operations *fops</synopsis>
+      <abstract>File operations for the DRM device node.</abstract>
       <para>
-	GEM is an Intel project, authored by Eric Anholt and Keith
-	Packard.  It provides simpler interfaces than TTM, and is well
-	suited for UMA devices.
+        Drivers must define the file operations structure that forms the DRM
+	userspace API entry point, even though most of those operations are
+	implemented in the DRM core. The <methodname>open</methodname>,
+	<methodname>release</methodname> and <methodname>ioctl</methodname>
+	operations are handled by
+	<programlisting>
+	.owner = THIS_MODULE,
+	.open = drm_open,
+	.release = drm_release,
+	.unlocked_ioctl = drm_ioctl,
+  #ifdef CONFIG_COMPAT
+	.compat_ioctl = drm_compat_ioctl,
+  #endif
+        </programlisting>
       </para>
       <para>
-	GEM-enabled drivers must provide gem_init_object() and
-	gem_free_object() callbacks to support the core memory
-	allocation routines.  They should also provide several driver-specific
-	ioctls to support command execution, pinning, buffer
-	read &amp; write, mapping, and domain ownership transfers.
+        Drivers that implement private ioctls that requires 32/64bit
+	compatibility support must provide their own
+	<methodname>compat_ioctl</methodname> handler that processes private
+	ioctls and calls <function>drm_compat_ioctl</function> for core ioctls.
       </para>
       <para>
-	On a fundamental level, GEM involves several operations:
-	<itemizedlist>
-	  <listitem>Memory allocation and freeing</listitem>
-	  <listitem>Command execution</listitem>
-	  <listitem>Aperture management at command execution time</listitem>
-	</itemizedlist>
-	Buffer object allocation is relatively
-	straightforward and largely provided by Linux's shmem layer, which
-	provides memory to back each object.  When mapped into the GTT
-	or used in a command buffer, the backing pages for an object are
-	flushed to memory and marked write combined so as to be coherent
-	with the GPU.  Likewise, if the CPU accesses an object after the GPU
-	has finished rendering to the object, then the object must be made
-	coherent with the CPU's view
-	of memory, usually involving GPU cache flushing of various kinds.
-	This core CPU&lt;-&gt;GPU coherency management is provided by a
-	device-specific ioctl, which evaluates an object's current domain and
-	performs any necessary flushing or synchronization to put the object
-	into the desired coherency domain (note that the object may be busy,
-	i.e. an active render target; in that case, setting the domain
-	blocks the client and waits for rendering to complete before
-	performing any necessary flushing operations).
-      </para>
-      <para>
-	Perhaps the most important GEM function is providing a command
-	execution interface to clients.  Client programs construct command
-	buffers containing references to previously allocated memory objects,
-	and then submit them to GEM.  At that point, GEM takes care to bind
-	all the objects into the GTT, execute the buffer, and provide
-	necessary synchronization between clients accessing the same buffers.
-	This often involves evicting some objects from the GTT and re-binding
-	others (a fairly expensive operation), and providing relocation
-	support which hides fixed GTT offsets from clients.  Clients must
-	take care not to submit command buffers that reference more objects
-	than can fit in the GTT; otherwise, GEM will reject them and no rendering
-	will occur.  Similarly, if several objects in the buffer require
-	fence registers to be allocated for correct rendering (e.g. 2D blits
-	on pre-965 chips), care must be taken not to require more fence
-	registers than are available to the client.  Such resource management
-	should be abstracted from the client in libdrm.
+        The <methodname>read</methodname> and <methodname>poll</methodname>
+	operations provide support for reading DRM events and polling them. They
+	are implemented by
+	<programlisting>
+	.poll = drm_poll,
+	.read = drm_read,
+	.fasync = drm_fasync,
+	.llseek = no_llseek,
+	</programlisting>
+      </para>
+      <para>
+        The memory mapping implementation varies depending on how the driver
+	manages memory. Pre-GEM drivers will use <function>drm_mmap</function>,
+	while GEM-aware drivers will use <function>drm_gem_mmap</function>. See
+	<xref linkend="drm-gem"/>.
+	<programlisting>
+	.mmap = drm_gem_mmap,
+	</programlisting>
+      </para>
+      <para>
+        No other file operation is supported by the DRM API.
+      </para>
+    </sect2>
+    <sect2>
+      <title>IOCTLs</title>
+      <synopsis>struct drm_ioctl_desc *ioctls;
+int num_ioctls;</synopsis>
+      <abstract>Driver-specific ioctls descriptors table.</abstract>
+      <para>
+        Driver-specific ioctls numbers start at DRM_COMMAND_BASE. The ioctls
+	descriptors table is indexed by the ioctl number offset from the base
+	value. Drivers can use the DRM_IOCTL_DEF_DRV() macro to initialize the
+	table entries.
+      </para>
+      <para>
+        <programlisting>DRM_IOCTL_DEF_DRV(ioctl, func, flags)</programlisting>
+	<para>
+	  <parameter>ioctl</parameter> is the ioctl name. Drivers must define
+	  the DRM_##ioctl and DRM_IOCTL_##ioctl macros to the ioctl number
+	  offset from DRM_COMMAND_BASE and the ioctl number respectively. The
+	  first macro is private to the device while the second must be exposed
+	  to userspace in a public header.
+	</para>
+	<para>
+	  <parameter>func</parameter> is a pointer to the ioctl handler function
+	  compatible with the <type>drm_ioctl_t</type> type.
+	  <programlisting>typedef int drm_ioctl_t(struct drm_device *dev, void *data,
+		struct drm_file *file_priv);</programlisting>
+	</para>
+	<para>
+	  <parameter>flags</parameter> is a bitmask combination of the following
+	  values. It restricts how the ioctl is allowed to be called.
+	  <itemizedlist>
+	    <listitem><para>
+	      DRM_AUTH - Only authenticated callers allowed
+	    </para></listitem>
+	    <listitem><para>
+	      DRM_MASTER - The ioctl can only be called on the master file
+	      handle
+	    </para></listitem>
+            <listitem><para>
+	      DRM_ROOT_ONLY - Only callers with the SYSADMIN capability allowed
+	    </para></listitem>
+            <listitem><para>
+	      DRM_CONTROL_ALLOW - The ioctl can only be called on a control
+	      device
+	    </para></listitem>
+            <listitem><para>
+	      DRM_UNLOCKED - The ioctl handler will be called without locking
+	      the DRM global mutex
+	    </para></listitem>
+	  </itemizedlist>
+	</para>
       </para>
     </sect2>
-
-  </sect1>
-
-  <!-- Output management -->
-  <sect1>
-    <title>Output management</title>
-    <para>
-      At the core of the DRM output management code is a set of
-      structures representing CRTCs, encoders, and connectors.
-    </para>
-    <para>
-      A CRTC is an abstraction representing a part of the chip that
-      contains a pointer to a scanout buffer.  Therefore, the number
-      of CRTCs available determines how many independent scanout
-      buffers can be active at any given time.  The CRTC structure
-      contains several fields to support this: a pointer to some video
-      memory, a display mode, and an (x, y) offset into the video
-      memory to support panning or configurations where one piece of
-      video memory spans multiple CRTCs.
-    </para>
-    <para>
-      An encoder takes pixel data from a CRTC and converts it to a
-      format suitable for any attached connectors.  On some devices,
-      it may be possible to have a CRTC send data to more than one
-      encoder.  In that case, both encoders would receive data from
-      the same scanout buffer, resulting in a "cloned" display
-      configuration across the connectors attached to each encoder.
-    </para>
-    <para>
-      A connector is the final destination for pixel data on a device,
-      and usually connects directly to an external display device like
-      a monitor or laptop panel.  A connector can only be attached to
-      one encoder at a time.  The connector is also the structure
-      where information about the attached display is kept, so it
-      contains fields for display data, EDID data, DPMS &amp;
-      connection status, and information about modes supported on the
-      attached displays.
-    </para>
-<!--!Edrivers/char/drm/drm_crtc.c-->
-  </sect1>
-
-  <sect1>
-    <title>Framebuffer management</title>
-    <para>
-      Clients need to provide a framebuffer object which provides a source
-      of pixels for a CRTC to deliver to the encoder(s) and ultimately the
-      connector(s). A framebuffer is fundamentally a driver-specific memory
-      object, made into an opaque handle by the DRM's addfb() function.
-      Once a framebuffer has been created this way, it may be passed to the
-      KMS mode setting routines for use in a completed configuration.
-    </para>
   </sect1>
 
   <sect1>
@@ -812,15 +2355,24 @@ void intel_crt_init(struct drm_device *dev)
     </para>
   </sect1>
 
+  <!-- Internals: suspend/resume -->
+
   <sect1>
-    <title>Suspend/resume</title>
+    <title>Suspend/Resume</title>
+    <para>
+      The DRM core provides some suspend/resume code, but drivers wanting full
+      suspend/resume support should provide save() and restore() functions.
+      These are called at suspend, hibernate, or resume time, and should perform
+      any state save or restore required by your device across suspend or
+      hibernate states.
+    </para>
+    <synopsis>int (*suspend) (struct drm_device *, pm_message_t state);
+int (*resume) (struct drm_device *);</synopsis>
     <para>
-      The DRM core provides some suspend/resume code, but drivers
-      wanting full suspend/resume support should provide save() and
-      restore() functions.  These are called at suspend,
-      hibernate, or resume time, and should perform any state save or
-      restore required by your device across suspend or hibernate
-      states.
+      Those are legacy suspend and resume methods. New driver should use the
+      power management interface provided by their bus type (usually through
+      the struct <structname>device_driver</structname> dev_pm_ops) and set
+      these methods to NULL.
     </para>
   </sect1>
 
@@ -833,6 +2385,35 @@ void intel_crt_init(struct drm_device *dev)
   </sect1>
   </chapter>
 
+<!-- TODO
+
+- Add a glossary
+- Document the struct_mutex catch-all lock
+- Document connector properties
+
+- Why is the load method optional?
+- What are drivers supposed to set the initial display state to, and how?
+  Connector's DPMS states are not initialized and are thus equal to
+  DRM_MODE_DPMS_ON. The fbcon compatibility layer calls
+  drm_helper_disable_unused_functions(), which disables unused encoders and
+  CRTCs, but doesn't touch the connectors' DPMS state, and
+  drm_helper_connector_dpms() in reaction to fbdev blanking events. Do drivers
+  that don't implement (or just don't use) fbcon compatibility need to call
+  those functions themselves?
+- KMS drivers must call drm_vblank_pre_modeset() and drm_vblank_post_modeset()
+  around mode setting. Should this be done in the DRM core?
+- vblank_disable_allowed is set to 1 in the first drm_vblank_post_modeset()
+  call and never set back to 0. It seems to be safe to permanently set it to 1
+  in drm_vblank_init() for KMS driver, and it might be safe for UMS drivers as
+  well. This should be investigated.
+- crtc and connector .save and .restore operations are only used internally in
+  drivers, should they be removed from the core?
+- encoder mid-layer .save and .restore operations are only used internally in
+  drivers, should they be removed from the core?
+- encoder mid-layer .detect operation is only used internally in drivers,
+  should it be removed from the core?
+-->
+
   <!-- External interfaces -->
 
   <chapter id="drmExternals">
@@ -853,6 +2434,42 @@ void intel_crt_init(struct drm_device *dev)
       Cover generic ioctls and sysfs layout here.  We only need high-level
       info, since man pages should cover the rest.
     </para>
+
+  <!-- External: vblank handling -->
+
+    <sect1>
+      <title>VBlank event handling</title>
+      <para>
+        The DRM core exposes two vertical blank related ioctls:
+        <variablelist>
+          <varlistentry>
+            <term>DRM_IOCTL_WAIT_VBLANK</term>
+            <listitem>
+              <para>
+                This takes a struct drm_wait_vblank structure as its argument,
+                and it is used to block or request a signal when a specified
+                vblank event occurs.
+              </para>
+            </listitem>
+          </varlistentry>
+          <varlistentry>
+            <term>DRM_IOCTL_MODESET_CTL</term>
+            <listitem>
+              <para>
+                This should be called by application level drivers before and
+                after mode setting, since on many devices the vertical blank
+                counter is reset at that time.  Internally, the DRM snapshots
+                the last vblank count when the ioctl is called with the
+                _DRM_PRE_MODESET command, so that the counter won't go backwards
+                (which is dealt with when _DRM_POST_MODESET is used).
+              </para>
+            </listitem>
+          </varlistentry>
+        </variablelist>
+<!--!Edrivers/char/drm/drm_irq.c-->
+      </para>
+    </sect1>
+
   </chapter>
 
   <!-- API reference -->
diff --git a/Documentation/DocBook/media/Makefile b/Documentation/DocBook/media/Makefile
index 3625209..9b7e4c5 100644
--- a/Documentation/DocBook/media/Makefile
+++ b/Documentation/DocBook/media/Makefile
@@ -300,7 +300,7 @@ $(MEDIA_OBJ_DIR)/media-entities.tmpl: $(MEDIA_OBJ_DIR)/v4l2.xml
 	@(								\
 	for ident in $(IOCTLS) ; do					\
 	  entity=`echo $$ident | tr _ -` ;				\
-	  id=`grep "<refname>$$ident" $(MEDIA_OBJ_DIR)/vidioc-*.xml | sed -r s,"^.*/(.*).xml.*","\1",` ; \
+	  id=`grep "<refname>$$ident" $(MEDIA_OBJ_DIR)/vidioc-*.xml $(MEDIA_OBJ_DIR)/media-ioc-*.xml | sed -r s,"^.*/(.*).xml.*","\1",` ; \
 	  echo "<!ENTITY $$entity \"<link"				\
 	    "linkend='$$id'><constant>$$ident</constant></link>\">"	\
 	  >>$@ ;							\
diff --git a/Documentation/DocBook/media/dvb/audio.xml b/Documentation/DocBook/media/dvb/audio.xml
index d643862..a7ea56c 100644
--- a/Documentation/DocBook/media/dvb/audio.xml
+++ b/Documentation/DocBook/media/dvb/audio.xml
@@ -1,12 +1,16 @@
 <title>DVB Audio Device</title>
 <para>The DVB audio device controls the MPEG2 audio decoder of the DVB hardware. It
 can be accessed through <emphasis role="tt">/dev/dvb/adapter0/audio0</emphasis>. Data types and and
-ioctl definitions can be accessed by including <emphasis role="tt">linux/dvb/video.h</emphasis> in your
+ioctl definitions can be accessed by including <emphasis role="tt">linux/dvb/audio.h</emphasis> in your
 application.
 </para>
 <para>Please note that some DVB cards don&#8217;t have their own MPEG decoder, which results in
 the omission of the audio and video device.
 </para>
+<para>
+These ioctls were also used by V4L2 to control MPEG decoders implemented in V4L2. The use
+of these ioctls for that purpose has been made obsolete and proper V4L2 ioctls or controls
+have been created to replace that functionality.</para>
 
 <section id="audio_data_types">
 <title>Audio Data Types</title>
@@ -558,6 +562,8 @@ role="subsection"><title>AUDIO_SELECT_SOURCE</title>
 role="subsection"><title>AUDIO_SET_MUTE</title>
 <para>DESCRIPTION
 </para>
+<para>This ioctl is for DVB devices only. To control a V4L2 decoder use the V4L2
+&VIDIOC-DECODER-CMD; with the <constant>V4L2_DEC_CMD_START_MUTE_AUDIO</constant> flag instead.</para>
 <informaltable><tgroup cols="1"><tbody><row><entry
  align="char">
 <para>This ioctl call asks the audio device to mute the stream that is currently being
@@ -730,6 +736,8 @@ role="subsection"><title>AUDIO_SET_BYPASS_MODE</title>
 role="subsection"><title>AUDIO_CHANNEL_SELECT</title>
 <para>DESCRIPTION
 </para>
+<para>This ioctl is for DVB devices only. To control a V4L2 decoder use the V4L2
+<constant>V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK</constant> control instead.</para>
 <informaltable><tgroup cols="1"><tbody><row><entry
  align="char">
 <para>This ioctl call asks the Audio Device to select the requested channel if possible.</para>
@@ -772,6 +780,109 @@ role="subsection"><title>AUDIO_CHANNEL_SELECT</title>
  </row></tbody></tgroup></informaltable>
 &return-value-dvb;
 
+</section><section id="AUDIO_BILINGUAL_CHANNEL_SELECT"
+role="subsection"><title>AUDIO_BILINGUAL_CHANNEL_SELECT</title>
+<para>DESCRIPTION
+</para>
+<para>This ioctl is obsolete. Do not use in new drivers. It has been replaced by
+the V4L2 <constant>V4L2_CID_MPEG_AUDIO_DEC_MULTILINGUAL_PLAYBACK</constant> control
+for MPEG decoders controlled through V4L2.</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>This ioctl call asks the Audio Device to select the requested channel for bilingual streams if possible.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>SYNOPSIS
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>int ioctl(int fd, int request =
+ AUDIO_BILINGUAL_CHANNEL_SELECT, audio_channel_select_t);</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>PARAMETERS
+</para>
+<informaltable><tgroup cols="2"><tbody><row><entry
+ align="char">
+<para>int fd</para>
+</entry><entry
+ align="char">
+<para>File descriptor returned by a previous call to open().</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>int request</para>
+</entry><entry
+ align="char">
+<para>Equals AUDIO_BILINGUAL_CHANNEL_SELECT for this
+ command.</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>audio_channel_select_t
+ch</para>
+</entry><entry
+ align="char">
+<para>Select the output format of the audio (mono left/right,
+ stereo).</para>
+</entry>
+ </row>
+</tbody></tgroup></informaltable>
+&return-value-dvb;
+
+</section><section id="AUDIO_GET_PTS"
+role="subsection"><title>AUDIO_GET_PTS</title>
+<para>DESCRIPTION
+</para>
+<para>This ioctl is obsolete. Do not use in new drivers. If you need this functionality,
+then please contact the linux-media mailing list (&v4l-ml;).</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>This ioctl call asks the Audio Device to return the current PTS timestamp.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>SYNOPSIS
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>int ioctl(int fd, int request =
+ AUDIO_GET_PTS, __u64 *pts);</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>PARAMETERS
+</para>
+<informaltable><tgroup cols="2"><tbody><row><entry
+ align="char">
+<para>int fd</para>
+</entry><entry
+ align="char">
+<para>File descriptor returned by a previous call to open().</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>int request</para>
+</entry><entry
+ align="char">
+<para>Equals AUDIO_GET_PTS for this
+ command.</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>__u64 *pts
+</para>
+</entry><entry
+ align="char">
+<para>Returns the 33-bit timestamp as defined in ITU T-REC-H.222.0 / ISO/IEC 13818-1.
+</para>
+<para>
+The PTS should belong to the currently played
+frame if possible, but may also be a value close to it
+like the PTS of the last decoded frame or the last PTS
+extracted by the PES parser.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+&return-value-dvb;
+
 </section><section id="AUDIO_GET_STATUS"
 role="subsection"><title>AUDIO_GET_STATUS</title>
 <para>DESCRIPTION
diff --git a/Documentation/DocBook/media/dvb/ca.xml b/Documentation/DocBook/media/dvb/ca.xml
index 5c4adb4..85eaf4f 100644
--- a/Documentation/DocBook/media/dvb/ca.xml
+++ b/Documentation/DocBook/media/dvb/ca.xml
@@ -226,4 +226,357 @@ typedef struct ca_pid {
 </entry>
  </row></tbody></tgroup></informaltable>
  </section>
+
+<section id="CA_RESET"
+role="subsection"><title>CA_RESET</title>
+<para>DESCRIPTION
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>This ioctl is undocumented. Documentation is welcome.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>SYNOPSIS
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>int ioctl(fd, int request = CA_RESET);
+</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>PARAMETERS
+</para>
+<informaltable><tgroup cols="2"><tbody><row><entry
+ align="char">
+<para>int fd</para>
+</entry><entry
+ align="char">
+<para>File descriptor returned by a previous call to open().</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>int request</para>
+</entry><entry
+ align="char">
+<para>Equals CA_RESET for this command.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+&return-value-dvb;
+</section>
+
+<section id="CA_GET_CAP"
+role="subsection"><title>CA_GET_CAP</title>
+<para>DESCRIPTION
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>This ioctl is undocumented. Documentation is welcome.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>SYNOPSIS
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>int ioctl(fd, int request = CA_GET_CAP,
+ ca_caps_t *);</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>PARAMETERS
+</para>
+<informaltable><tgroup cols="2"><tbody><row><entry
+ align="char">
+<para>int fd</para>
+</entry><entry
+ align="char">
+<para>File descriptor returned by a previous call to open().</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>int request</para>
+</entry><entry
+ align="char">
+<para>Equals CA_GET_CAP for this command.</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>ca_caps_t *
+</para>
+</entry><entry
+ align="char">
+<para>Undocumented.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+&return-value-dvb;
+</section>
+
+<section id="CA_GET_SLOT_INFO"
+role="subsection"><title>CA_GET_SLOT_INFO</title>
+<para>DESCRIPTION
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>This ioctl is undocumented. Documentation is welcome.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>SYNOPSIS
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>int ioctl(fd, int request = CA_GET_SLOT_INFO,
+ ca_slot_info_t *);</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>PARAMETERS
+</para>
+<informaltable><tgroup cols="2"><tbody><row><entry
+ align="char">
+<para>int fd</para>
+</entry><entry
+ align="char">
+<para>File descriptor returned by a previous call to open().</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>int request</para>
+</entry><entry
+ align="char">
+<para>Equals CA_GET_SLOT_INFO for this command.</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>ca_slot_info_t *
+</para>
+</entry><entry
+ align="char">
+<para>Undocumented.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+&return-value-dvb;
+</section>
+
+<section id="CA_GET_DESCR_INFO"
+role="subsection"><title>CA_GET_DESCR_INFO</title>
+<para>DESCRIPTION
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>This ioctl is undocumented. Documentation is welcome.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>SYNOPSIS
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>int ioctl(fd, int request = CA_GET_DESCR_INFO,
+ ca_descr_info_t *);</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>PARAMETERS
+</para>
+<informaltable><tgroup cols="2"><tbody><row><entry
+ align="char">
+<para>int fd</para>
+</entry><entry
+ align="char">
+<para>File descriptor returned by a previous call to open().</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>int request</para>
+</entry><entry
+ align="char">
+<para>Equals CA_GET_DESCR_INFO for this command.</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>ca_descr_info_t *
+</para>
+</entry><entry
+ align="char">
+<para>Undocumented.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+&return-value-dvb;
+</section>
+
+<section id="CA_GET_MSG"
+role="subsection"><title>CA_GET_MSG</title>
+<para>DESCRIPTION
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>This ioctl is undocumented. Documentation is welcome.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>SYNOPSIS
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>int ioctl(fd, int request = CA_GET_MSG,
+ ca_msg_t *);</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>PARAMETERS
+</para>
+<informaltable><tgroup cols="2"><tbody><row><entry
+ align="char">
+<para>int fd</para>
+</entry><entry
+ align="char">
+<para>File descriptor returned by a previous call to open().</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>int request</para>
+</entry><entry
+ align="char">
+<para>Equals CA_GET_MSG for this command.</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>ca_msg_t *
+</para>
+</entry><entry
+ align="char">
+<para>Undocumented.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+&return-value-dvb;
+</section>
+
+<section id="CA_SEND_MSG"
+role="subsection"><title>CA_SEND_MSG</title>
+<para>DESCRIPTION
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>This ioctl is undocumented. Documentation is welcome.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>SYNOPSIS
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>int ioctl(fd, int request = CA_SEND_MSG,
+ ca_msg_t *);</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>PARAMETERS
+</para>
+<informaltable><tgroup cols="2"><tbody><row><entry
+ align="char">
+<para>int fd</para>
+</entry><entry
+ align="char">
+<para>File descriptor returned by a previous call to open().</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>int request</para>
+</entry><entry
+ align="char">
+<para>Equals CA_SEND_MSG for this command.</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>ca_msg_t *
+</para>
+</entry><entry
+ align="char">
+<para>Undocumented.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+&return-value-dvb;
+</section>
+
+<section id="CA_SET_DESCR"
+role="subsection"><title>CA_SET_DESCR</title>
+<para>DESCRIPTION
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>This ioctl is undocumented. Documentation is welcome.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>SYNOPSIS
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>int ioctl(fd, int request = CA_SET_DESCR,
+ ca_descr_t *);</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>PARAMETERS
+</para>
+<informaltable><tgroup cols="2"><tbody><row><entry
+ align="char">
+<para>int fd</para>
+</entry><entry
+ align="char">
+<para>File descriptor returned by a previous call to open().</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>int request</para>
+</entry><entry
+ align="char">
+<para>Equals CA_SET_DESCR for this command.</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>ca_descr_t *
+</para>
+</entry><entry
+ align="char">
+<para>Undocumented.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+&return-value-dvb;
+</section>
+
+<section id="CA_SET_PID"
+role="subsection"><title>CA_SET_PID</title>
+<para>DESCRIPTION
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>This ioctl is undocumented. Documentation is welcome.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>SYNOPSIS
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>int ioctl(fd, int request = CA_SET_PID,
+ ca_pid_t *);</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>PARAMETERS
+</para>
+<informaltable><tgroup cols="2"><tbody><row><entry
+ align="char">
+<para>int fd</para>
+</entry><entry
+ align="char">
+<para>File descriptor returned by a previous call to open().</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>int request</para>
+</entry><entry
+ align="char">
+<para>Equals CA_SET_PID for this command.</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>ca_pid_t *
+</para>
+</entry><entry
+ align="char">
+<para>Undocumented.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+&return-value-dvb;
+</section>
+
 </section>
diff --git a/Documentation/DocBook/media/dvb/demux.xml b/Documentation/DocBook/media/dvb/demux.xml
index 37c1790..86de89c 100644
--- a/Documentation/DocBook/media/dvb/demux.xml
+++ b/Documentation/DocBook/media/dvb/demux.xml
@@ -899,4 +899,232 @@ typedef enum {
 <para>Invalid stc number.</para>
 </entry>
  </row></tbody></tgroup></informaltable>
- </section></section>
+ </section>
+
+<section id="DMX_GET_PES_PIDS"
+role="subsection"><title>DMX_GET_PES_PIDS</title>
+<para>DESCRIPTION
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>This ioctl is undocumented. Documentation is welcome.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>SYNOPSIS
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>int ioctl(fd, int request = DMX_GET_PES_PIDS,
+ __u16[5]);</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>PARAMETERS
+</para>
+<informaltable><tgroup cols="2"><tbody><row><entry
+ align="char">
+<para>int fd</para>
+</entry><entry
+ align="char">
+<para>File descriptor returned by a previous call to open().</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>int request</para>
+</entry><entry
+ align="char">
+<para>Equals DMX_GET_PES_PIDS for this command.</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>__u16[5]
+</para>
+</entry><entry
+ align="char">
+<para>Undocumented.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+&return-value-dvb;
+</section>
+
+<section id="DMX_GET_CAPS"
+role="subsection"><title>DMX_GET_CAPS</title>
+<para>DESCRIPTION
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>This ioctl is undocumented. Documentation is welcome.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>SYNOPSIS
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>int ioctl(fd, int request = DMX_GET_CAPS,
+ dmx_caps_t *);</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>PARAMETERS
+</para>
+<informaltable><tgroup cols="2"><tbody><row><entry
+ align="char">
+<para>int fd</para>
+</entry><entry
+ align="char">
+<para>File descriptor returned by a previous call to open().</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>int request</para>
+</entry><entry
+ align="char">
+<para>Equals DMX_GET_CAPS for this command.</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>dmx_caps_t *
+</para>
+</entry><entry
+ align="char">
+<para>Undocumented.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+&return-value-dvb;
+</section>
+
+<section id="DMX_SET_SOURCE"
+role="subsection"><title>DMX_SET_SOURCE</title>
+<para>DESCRIPTION
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>This ioctl is undocumented. Documentation is welcome.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>SYNOPSIS
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>int ioctl(fd, int request = DMX_SET_SOURCE,
+ dmx_source_t *);</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>PARAMETERS
+</para>
+<informaltable><tgroup cols="2"><tbody><row><entry
+ align="char">
+<para>int fd</para>
+</entry><entry
+ align="char">
+<para>File descriptor returned by a previous call to open().</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>int request</para>
+</entry><entry
+ align="char">
+<para>Equals DMX_SET_SOURCE for this command.</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>dmx_source_t *
+</para>
+</entry><entry
+ align="char">
+<para>Undocumented.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+&return-value-dvb;
+</section>
+
+<section id="DMX_ADD_PID"
+role="subsection"><title>DMX_ADD_PID</title>
+<para>DESCRIPTION
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>This ioctl is undocumented. Documentation is welcome.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>SYNOPSIS
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>int ioctl(fd, int request = DMX_ADD_PID,
+ __u16 *);</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>PARAMETERS
+</para>
+<informaltable><tgroup cols="2"><tbody><row><entry
+ align="char">
+<para>int fd</para>
+</entry><entry
+ align="char">
+<para>File descriptor returned by a previous call to open().</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>int request</para>
+</entry><entry
+ align="char">
+<para>Equals DMX_ADD_PID for this command.</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>__u16 *
+</para>
+</entry><entry
+ align="char">
+<para>Undocumented.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+&return-value-dvb;
+</section>
+
+<section id="DMX_REMOVE_PID"
+role="subsection"><title>DMX_REMOVE_PID</title>
+<para>DESCRIPTION
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>This ioctl is undocumented. Documentation is welcome.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>SYNOPSIS
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>int ioctl(fd, int request = DMX_REMOVE_PID,
+ __u16 *);</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>PARAMETERS
+</para>
+<informaltable><tgroup cols="2"><tbody><row><entry
+ align="char">
+<para>int fd</para>
+</entry><entry
+ align="char">
+<para>File descriptor returned by a previous call to open().</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>int request</para>
+</entry><entry
+ align="char">
+<para>Equals DMX_REMOVE_PID for this command.</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>__u16 *
+</para>
+</entry><entry
+ align="char">
+<para>Undocumented.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+&return-value-dvb;
+</section>
+
+
+</section>
diff --git a/Documentation/DocBook/media/dvb/dvbapi.xml b/Documentation/DocBook/media/dvb/dvbapi.xml
index 2ab6ddc..757488b 100644
--- a/Documentation/DocBook/media/dvb/dvbapi.xml
+++ b/Documentation/DocBook/media/dvb/dvbapi.xml
@@ -28,7 +28,7 @@
 	<holder>Convergence GmbH</holder>
 </copyright>
 <copyright>
-	<year>2009-2011</year>
+	<year>2009-2012</year>
 	<holder>Mauro Carvalho Chehab</holder>
 </copyright>
 
@@ -84,7 +84,7 @@ Added ISDB-T test originally written by Patrick Boettcher
 
 
 <title>LINUX DVB API</title>
-<subtitle>Version 5.2</subtitle>
+<subtitle>Version 5.8</subtitle>
 <!-- ADD THE CHAPTERS HERE -->
   <chapter id="dvb_introdution">
     &sub-intro;
diff --git a/Documentation/DocBook/media/dvb/dvbproperty.xml b/Documentation/DocBook/media/dvb/dvbproperty.xml
index e633c09..3eebdac 100644
--- a/Documentation/DocBook/media/dvb/dvbproperty.xml
+++ b/Documentation/DocBook/media/dvb/dvbproperty.xml
@@ -194,6 +194,7 @@ get/set up to 64 properties. The actual meaning of each property is described on
 	APSK_16,
 	APSK_32,
 	DQPSK,
+	QAM_4_NR,
  } fe_modulation_t;
 </programlisting>
 	</section>
@@ -265,6 +266,7 @@ typedef enum fe_code_rate {
 	FEC_AUTO,
 	FEC_3_5,
 	FEC_9_10,
+	FEC_2_5,
 } fe_code_rate_t;
 	</programlisting>
 	<para>which correspond to error correction rates of 1/2, 2/3, etc.,
@@ -351,7 +353,7 @@ typedef enum fe_delivery_system {
 	SYS_ISDBC,
 	SYS_ATSC,
 	SYS_ATSCMH,
-	SYS_DMBTH,
+	SYS_DTMB,
 	SYS_CMMB,
 	SYS_DAB,
 	SYS_DVBT2,
@@ -567,28 +569,33 @@ typedef enum fe_delivery_system {
 			<title><constant>DTV_ATSCMH_RS_FRAME_MODE</constant></title>
 			<para>RS frame mode.</para>
 			<para>Possible values are:</para>
+		  <para id="atscmh-rs-frame-mode">
 <programlisting>
 typedef enum atscmh_rs_frame_mode {
 	ATSCMH_RSFRAME_PRI_ONLY  = 0,
 	ATSCMH_RSFRAME_PRI_SEC   = 1,
 } atscmh_rs_frame_mode_t;
 </programlisting>
+		  </para>
 		</section>
 		<section id="DTV-ATSCMH-RS-FRAME-ENSEMBLE">
 			<title><constant>DTV_ATSCMH_RS_FRAME_ENSEMBLE</constant></title>
 			<para>RS frame ensemble.</para>
 			<para>Possible values are:</para>
+		  <para id="atscmh-rs-frame-ensemble">
 <programlisting>
 typedef enum atscmh_rs_frame_ensemble {
 	ATSCMH_RSFRAME_ENS_PRI   = 0,
 	ATSCMH_RSFRAME_ENS_SEC   = 1,
 } atscmh_rs_frame_ensemble_t;
 </programlisting>
+		  </para>
 		</section>
 		<section id="DTV-ATSCMH-RS-CODE-MODE-PRI">
 			<title><constant>DTV_ATSCMH_RS_CODE_MODE_PRI</constant></title>
 			<para>RS code mode (primary).</para>
 			<para>Possible values are:</para>
+		  <para id="atscmh-rs-code-mode">
 <programlisting>
 typedef enum atscmh_rs_code_mode {
 	ATSCMH_RSCODE_211_187    = 0,
@@ -596,6 +603,7 @@ typedef enum atscmh_rs_code_mode {
 	ATSCMH_RSCODE_235_187    = 2,
 } atscmh_rs_code_mode_t;
 </programlisting>
+		  </para>
 		</section>
 		<section id="DTV-ATSCMH-RS-CODE-MODE-SEC">
 			<title><constant>DTV_ATSCMH_RS_CODE_MODE_SEC</constant></title>
@@ -613,23 +621,27 @@ typedef enum atscmh_rs_code_mode {
 			<title><constant>DTV_ATSCMH_SCCC_BLOCK_MODE</constant></title>
 			<para>Series Concatenated Convolutional Code Block Mode.</para>
 			<para>Possible values are:</para>
+		  <para id="atscmh-sccc-block-mode">
 <programlisting>
 typedef enum atscmh_sccc_block_mode {
 	ATSCMH_SCCC_BLK_SEP      = 0,
 	ATSCMH_SCCC_BLK_COMB     = 1,
 } atscmh_sccc_block_mode_t;
 </programlisting>
+		  </para>
 		</section>
 		<section id="DTV-ATSCMH-SCCC-CODE-MODE-A">
 			<title><constant>DTV_ATSCMH_SCCC_CODE_MODE_A</constant></title>
 			<para>Series Concatenated Convolutional Code Rate.</para>
 			<para>Possible values are:</para>
+		  <para id="atscmh-sccc-code-mode">
 <programlisting>
 typedef enum atscmh_sccc_code_mode {
 	ATSCMH_SCCC_CODE_HLF     = 0,
 	ATSCMH_SCCC_CODE_QTR     = 1,
 } atscmh_sccc_code_mode_t;
 </programlisting>
+		  </para>
 		</section>
 		<section id="DTV-ATSCMH-SCCC-CODE-MODE-B">
 			<title><constant>DTV_ATSCMH_SCCC_CODE_MODE_B</constant></title>
@@ -725,6 +737,9 @@ typedef enum fe_guard_interval {
 	GUARD_INTERVAL_1_128,
 	GUARD_INTERVAL_19_128,
 	GUARD_INTERVAL_19_256,
+	GUARD_INTERVAL_PN420,
+	GUARD_INTERVAL_PN595,
+	GUARD_INTERVAL_PN945,
 } fe_guard_interval_t;
 </programlisting>
 
@@ -733,6 +748,7 @@ typedef enum fe_guard_interval {
 			try to find the correct guard interval (if capable) and will use TMCC to fill
 			in the missing parameters.</para>
 		<para>2) Intervals 1/128, 19/128 and 19/256 are used only for DVB-T2 at present</para>
+		<para>3) DTMB specifies PN420, PN595 and PN945.</para>
 	</section>
 	<section id="DTV-TRANSMISSION-MODE">
 		<title><constant>DTV_TRANSMISSION_MODE</constant></title>
@@ -749,6 +765,8 @@ typedef enum fe_transmit_mode {
 	TRANSMISSION_MODE_1K,
 	TRANSMISSION_MODE_16K,
 	TRANSMISSION_MODE_32K,
+	TRANSMISSION_MODE_C1,
+	TRANSMISSION_MODE_C3780,
 } fe_transmit_mode_t;
 </programlisting>
 		<para>Notes:</para>
@@ -760,6 +778,7 @@ typedef enum fe_transmit_mode {
 			use TMCC to fill in the missing parameters.</para>
 		<para>3) DVB-T specifies 2K and 8K as valid sizes.</para>
 		<para>4) DVB-T2 specifies 1K, 2K, 4K, 8K, 16K and 32K.</para>
+		<para>5) DTMB specifies C1 and C3780.</para>
 	</section>
 	<section id="DTV-HIERARCHY">
 	<title><constant>DTV_HIERARCHY</constant></title>
@@ -774,17 +793,28 @@ typedef enum fe_hierarchy {
  } fe_hierarchy_t;
 	</programlisting>
 	</section>
-	<section id="DTV-ISDBS-TS-ID">
-	<title><constant>DTV_ISDBS_TS_ID</constant></title>
-	<para>Currently unused.</para>
+	<section id="DTV-STREAM-ID">
+	<title><constant>DTV_STREAM_ID</constant></title>
+	<para>DVB-S2, DVB-T2 and ISDB-S support the transmission of several
+	      streams on a single transport stream.
+	      This property enables the DVB driver to handle substream filtering,
+	      when supported by the hardware.
+	      By default, substream filtering is disabled.
+	</para><para>
+	      For DVB-S2 and DVB-T2, the valid substream id range is from 0 to 255.
+	</para><para>
+	      For ISDB, the valid substream id range is from 1 to 65535.
+	</para><para>
+	      To disable it, you should use the special macro NO_STREAM_ID_FILTER.
+	</para><para>
+	      Note: any value outside the id range also disables filtering.
+	</para>
 	</section>
-	<section id="DTV-DVBT2-PLP-ID">
-		<title><constant>DTV_DVBT2_PLP_ID</constant></title>
-		<para>DVB-T2 supports Physical Layer Pipes (PLP) to allow transmission of
-			many data types via a single multiplex. The API will soon support this
-			at which point this section will be expanded.</para>
+	<section id="DTV-DVBT2-PLP-ID-LEGACY">
+		<title><constant>DTV_DVBT2_PLP_ID_LEGACY</constant></title>
+		<para>Obsolete, replaced with DTV_STREAM_ID.</para>
 	</section>
-	<section id="DTV_ENUM_DELSYS">
+	<section id="DTV-ENUM-DELSYS">
 		<title><constant>DTV_ENUM_DELSYS</constant></title>
 		<para>A Multi standard frontend needs to advertise the delivery systems provided.
 			Applications need to enumerate the provided delivery systems, before using
@@ -796,6 +826,18 @@ typedef enum fe_hierarchy {
 			FE_GET_INFO. In the case of a legacy frontend, the result is just the same
 			as with FE_GET_INFO, but in a more structured format </para>
 	</section>
+	<section id="DTV-INTERLEAVING">
+	<title><constant>DTV_INTERLEAVING</constant></title>
+	<para id="fe-interleaving">Interleaving mode</para>
+	<programlisting>
+enum fe_interleaving {
+	INTERLEAVING_NONE,
+	INTERLEAVING_AUTO,
+	INTERLEAVING_240,
+	INTERLEAVING_720,
+};
+	</programlisting>
+	</section>
 </section>
 	<section id="frontend-property-terrestrial-systems">
 	<title>Properties used on terrestrial delivery systems</title>
@@ -838,7 +880,7 @@ typedef enum fe_hierarchy {
 			<listitem><para><link linkend="DTV-GUARD-INTERVAL"><constant>DTV_GUARD_INTERVAL</constant></link></para></listitem>
 			<listitem><para><link linkend="DTV-TRANSMISSION-MODE"><constant>DTV_TRANSMISSION_MODE</constant></link></para></listitem>
 			<listitem><para><link linkend="DTV-HIERARCHY"><constant>DTV_HIERARCHY</constant></link></para></listitem>
-			<listitem><para><link linkend="DTV-DVBT2-PLP-ID"><constant>DTV_DVBT2_PLP_ID</constant></link></para></listitem>
+			<listitem><para><link linkend="DTV-STREAM-ID"><constant>DTV_STREAM_ID</constant></link></para></listitem>
 		</itemizedlist>
 		</section>
 		<section id="isdbt">
@@ -925,13 +967,31 @@ typedef enum fe_hierarchy {
 				<listitem><para><link linkend="DTV-ATSCMH-PRC"><constant>DTV_ATSCMH_PRC</constant></link></para></listitem>
 				<listitem><para><link linkend="DTV-ATSCMH-RS-FRAME-MODE"><constant>DTV_ATSCMH_RS_FRAME_MODE</constant></link></para></listitem>
 				<listitem><para><link linkend="DTV-ATSCMH-RS-FRAME-ENSEMBLE"><constant>DTV_ATSCMH_RS_FRAME_ENSEMBLE</constant></link></para></listitem>
-				<listitem><para><link linkend="DTV-ATSCMH-CODE-MODE-PRI"><constant>DTV_ATSCMH_CODE_MODE_PRI</constant></link></para></listitem>
-				<listitem><para><link linkend="DTV-ATSCMH-CODE-MODE-SEC"><constant>DTV_ATSCMH_CODE_MODE_SEC</constant></link></para></listitem>
+				<listitem><para><link linkend="DTV-ATSCMH-RS-CODE-MODE-PRI"><constant>DTV_ATSCMH_RS_CODE_MODE_PRI</constant></link></para></listitem>
+				<listitem><para><link linkend="DTV-ATSCMH-RS-CODE-MODE-SEC"><constant>DTV_ATSCMH_RS_CODE_MODE_SEC</constant></link></para></listitem>
 				<listitem><para><link linkend="DTV-ATSCMH-SCCC-BLOCK-MODE"><constant>DTV_ATSCMH_SCCC_BLOCK_MODE</constant></link></para></listitem>
-				<listitem><para><link linkend="DTV-ATSCMH-SCCC-CODE_MODE-A"><constant>DTV_ATSCMH_SCCC_CODE_MODE_A</constant></link></para></listitem>
-				<listitem><para><link linkend="DTV-ATSCMH-SCCC-CODE_MODE-B"><constant>DTV_ATSCMH_SCCC_CODE_MODE_B</constant></link></para></listitem>
-				<listitem><para><link linkend="DTV-ATSCMH-SCCC-CODE_MODE-C"><constant>DTV_ATSCMH_SCCC_CODE_MODE_C</constant></link></para></listitem>
-				<listitem><para><link linkend="DTV-ATSCMH-SCCC-CODE_MODE-D"><constant>DTV_ATSCMH_SCCC_CODE_MODE_D</constant></link></para></listitem>
+				<listitem><para><link linkend="DTV-ATSCMH-SCCC-CODE-MODE-A"><constant>DTV_ATSCMH_SCCC_CODE_MODE_A</constant></link></para></listitem>
+				<listitem><para><link linkend="DTV-ATSCMH-SCCC-CODE-MODE-B"><constant>DTV_ATSCMH_SCCC_CODE_MODE_B</constant></link></para></listitem>
+				<listitem><para><link linkend="DTV-ATSCMH-SCCC-CODE-MODE-C"><constant>DTV_ATSCMH_SCCC_CODE_MODE_C</constant></link></para></listitem>
+				<listitem><para><link linkend="DTV-ATSCMH-SCCC-CODE-MODE-D"><constant>DTV_ATSCMH_SCCC_CODE_MODE_D</constant></link></para></listitem>
+			</itemizedlist>
+		</section>
+		<section id="dtmb-params">
+			<title>DTMB delivery system</title>
+			<para>The following parameters are valid for DTMB:</para>
+			<itemizedlist mark='opencircle'>
+				<listitem><para><link linkend="DTV-API-VERSION"><constant>DTV_API_VERSION</constant></link></para></listitem>
+				<listitem><para><link linkend="DTV-DELIVERY-SYSTEM"><constant>DTV_DELIVERY_SYSTEM</constant></link></para></listitem>
+				<listitem><para><link linkend="DTV-TUNE"><constant>DTV_TUNE</constant></link></para></listitem>
+				<listitem><para><link linkend="DTV-CLEAR"><constant>DTV_CLEAR</constant></link></para></listitem>
+				<listitem><para><link linkend="DTV-FREQUENCY"><constant>DTV_FREQUENCY</constant></link></para></listitem>
+				<listitem><para><link linkend="DTV-MODULATION"><constant>DTV_MODULATION</constant></link></para></listitem>
+				<listitem><para><link linkend="DTV-BANDWIDTH-HZ"><constant>DTV_BANDWIDTH_HZ</constant></link></para></listitem>
+				<listitem><para><link linkend="DTV-INVERSION"><constant>DTV_INVERSION</constant></link></para></listitem>
+				<listitem><para><link linkend="DTV-INNER-FEC"><constant>DTV_INNER_FEC</constant></link></para></listitem>
+				<listitem><para><link linkend="DTV-GUARD-INTERVAL"><constant>DTV_GUARD_INTERVAL</constant></link></para></listitem>
+				<listitem><para><link linkend="DTV-TRANSMISSION-MODE"><constant>DTV_TRANSMISSION_MODE</constant></link></para></listitem>
+				<listitem><para><link linkend="DTV-INTERLEAVING"><constant>DTV_INTERLEAVING</constant></link></para></listitem>
 			</itemizedlist>
 		</section>
 	</section>
@@ -999,6 +1059,7 @@ typedef enum fe_hierarchy {
 			<listitem><para><link linkend="DTV-MODULATION"><constant>DTV_MODULATION</constant></link></para></listitem>
 			<listitem><para><link linkend="DTV-PILOT"><constant>DTV_PILOT</constant></link></para></listitem>
 			<listitem><para><link linkend="DTV-ROLLOFF"><constant>DTV_ROLLOFF</constant></link></para></listitem>
+			<listitem><para><link linkend="DTV-STREAM-ID"><constant>DTV_STREAM_ID</constant></link></para></listitem>
 		</itemizedlist>
 	</section>
 	<section id="turbo-params">
@@ -1021,7 +1082,7 @@ typedef enum fe_hierarchy {
 			<listitem><para><link linkend="DTV-SYMBOL-RATE"><constant>DTV_SYMBOL_RATE</constant></link></para></listitem>
 			<listitem><para><link linkend="DTV-INNER-FEC"><constant>DTV_INNER_FEC</constant></link></para></listitem>
 			<listitem><para><link linkend="DTV-VOLTAGE"><constant>DTV_VOLTAGE</constant></link></para></listitem>
-			<listitem><para><link linkend="DTV-ISDBS-TS-ID"><constant>DTV_ISDBS_TS_ID</constant></link></para></listitem>
+			<listitem><para><link linkend="DTV-STREAM-ID"><constant>DTV_STREAM_ID</constant></link></para></listitem>
 		</itemizedlist>
 	</section>
 	</section>
diff --git a/Documentation/DocBook/media/dvb/frontend.xml b/Documentation/DocBook/media/dvb/frontend.xml
index aeaed59..426c252 100644
--- a/Documentation/DocBook/media/dvb/frontend.xml
+++ b/Documentation/DocBook/media/dvb/frontend.xml
@@ -66,7 +66,7 @@ supported via the new <link linkend="FE_GET_SET_PROPERTY">FE_GET_PROPERTY/FE_GET
 
 <para>The usage of this field is deprecated, as it doesn't report all supported standards, and
 will provide an incomplete information for frontends that support multiple delivery systems.
-Please use <link linkend="DTV_ENUM_DELSYS">DTV_ENUM_DELSYS</link> instead.</para>
+Please use <link linkend="DTV-ENUM-DELSYS">DTV_ENUM_DELSYS</link> instead.</para>
 </section>
 
 <section id="fe-caps-t">
@@ -101,6 +101,7 @@ a specific frontend type.</para>
 	FE_CAN_8VSB                   = 0x200000,
 	FE_CAN_16VSB                  = 0x400000,
 	FE_HAS_EXTENDED_CAPS          = 0x800000,
+	FE_CAN_MULTISTREAM            = 0x4000000,
 	FE_CAN_TURBO_FEC              = 0x8000000,
 	FE_CAN_2G_MODULATION          = 0x10000000,
 	FE_NEEDS_BENDING              = 0x20000000,
@@ -207,18 +208,44 @@ spec.</para>
 <para>Several functions of the frontend device use the fe_status data type defined
 by</para>
 <programlisting>
- typedef enum fe_status {
-	 FE_HAS_SIGNAL     = 0x01,   /&#x22C6;  found something above the noise level &#x22C6;/
-	 FE_HAS_CARRIER    = 0x02,   /&#x22C6;  found a DVB signal  &#x22C6;/
-	 FE_HAS_VITERBI    = 0x04,   /&#x22C6;  FEC is stable  &#x22C6;/
-	 FE_HAS_SYNC       = 0x08,   /&#x22C6;  found sync bytes  &#x22C6;/
-	 FE_HAS_LOCK       = 0x10,   /&#x22C6;  everything's working... &#x22C6;/
-	 FE_TIMEDOUT       = 0x20,   /&#x22C6;  no lock within the last ~2 seconds &#x22C6;/
-	 FE_REINIT         = 0x40    /&#x22C6;  frontend was reinitialized,  &#x22C6;/
- } fe_status_t;                      /&#x22C6;  application is recommned to reset &#x22C6;/
+typedef enum fe_status {
+	FE_HAS_SIGNAL		= 0x01,
+	FE_HAS_CARRIER		= 0x02,
+	FE_HAS_VITERBI		= 0x04,
+	FE_HAS_SYNC		= 0x08,
+	FE_HAS_LOCK		= 0x10,
+	FE_TIMEDOUT		= 0x20,
+	FE_REINIT		= 0x40,
+} fe_status_t;
 </programlisting>
-<para>to indicate the current state and/or state changes of the frontend hardware.
-</para>
+<para>to indicate the current state and/or state changes of the frontend hardware:
+</para>
+
+<informaltable><tgroup cols="2"><tbody>
+<row>
+<entry align="char">FE_HAS_SIGNAL</entry>
+<entry align="char">The frontend has found something above the noise level</entry>
+</row><row>
+<entry align="char">FE_HAS_CARRIER</entry>
+<entry align="char">The frontend has found a DVB signal</entry>
+</row><row>
+<entry align="char">FE_HAS_VITERBI</entry>
+<entry align="char">The frontend FEC code is stable</entry>
+</row><row>
+<entry align="char">FE_HAS_SYNC</entry>
+<entry align="char">Syncronization bytes was found</entry>
+</row><row>
+<entry align="char">FE_HAS_LOCK</entry>
+<entry align="char">The DVB were locked and everything is working</entry>
+</row><row>
+<entry align="char">FE_TIMEDOUT</entry>
+<entry align="char">no lock within the last about 2 seconds</entry>
+</row><row>
+<entry align="char">FE_REINIT</entry>
+<entry align="char">The frontend was reinitialized, application is
+recommended to reset DiSEqC, tone and parameters</entry>
+</row>
+</tbody></tgroup></informaltable>
 
 </section>
 
@@ -238,7 +265,7 @@ and to add newer delivery systems.</para>
 <constant>FE_GET_PROPERTY/FE_SET_PROPERTY</constant></link> instead, in
 order to be able to support the newer System Delivery like  DVB-S2, DVB-T2,
 DVB-C2, ISDB, etc.</para>
-<para>All kinds of parameters are combined as an union in the FrontendParameters structure:</para>
+<para>All kinds of parameters are combined as an union in the FrontendParameters structure:
 <programlisting>
 struct dvb_frontend_parameters {
 	uint32_t frequency;     /&#x22C6; (absolute) frequency in Hz for QAM/OFDM &#x22C6;/
@@ -251,12 +278,13 @@ struct dvb_frontend_parameters {
 		struct dvb_vsb_parameters  vsb;
 	} u;
 };
-</programlisting>
+</programlisting></para>
 <para>In the case of QPSK frontends the <constant>frequency</constant> field specifies the intermediate
 frequency, i.e. the offset which is effectively added to the local oscillator frequency (LOF) of
 the LNB. The intermediate frequency has to be specified in units of kHz. For QAM and
 OFDM frontends the <constant>frequency</constant> specifies the absolute frequency and is given in Hz.
 </para>
+
 <section id="dvb-qpsk-parameters">
 <title>QPSK parameters</title>
 <para>For satellite QPSK frontends you have to use the <constant>dvb_qpsk_parameters</constant> structure:</para>
@@ -321,8 +349,8 @@ itself.
 <section id="fe-code-rate-t">
 <title>frontend code rate</title>
 <para>The possible values for the <constant>fec_inner</constant> field used on
-<link refend="dvb-qpsk-parameters"><constant>struct dvb_qpsk_parameters</constant></link> and
-<link refend="dvb-qam-parameters"><constant>struct dvb_qam_parameters</constant></link> are:
+<link linkend="dvb-qpsk-parameters"><constant>struct dvb_qpsk_parameters</constant></link> and
+<link linkend="dvb-qam-parameters"><constant>struct dvb_qam_parameters</constant></link> are:
 </para>
 <programlisting>
 typedef enum fe_code_rate {
@@ -347,9 +375,9 @@ detection.
 <section id="fe-modulation-t">
 <title>frontend modulation type for QAM, OFDM and VSB</title>
 <para>For cable and terrestrial frontends, e. g. for
-<link refend="dvb-qam-parameters"><constant>struct dvb_qpsk_parameters</constant></link>,
-<link refend="dvb-ofdm-parameters"><constant>struct dvb_qam_parameters</constant></link> and
-<link refend="dvb-vsb-parameters"><constant>struct dvb_qam_parameters</constant></link>,
+<link linkend="dvb-qam-parameters"><constant>struct dvb_qpsk_parameters</constant></link>,
+<link linkend="dvb-ofdm-parameters"><constant>struct dvb_qam_parameters</constant></link> and
+<link linkend="dvb-vsb-parameters"><constant>struct dvb_qam_parameters</constant></link>,
 it needs to specify the quadrature modulation mode which can be one of the following:
 </para>
 <programlisting>
@@ -370,8 +398,8 @@ it needs to specify the quadrature modulation mode which can be one of the follo
  } fe_modulation_t;
 </programlisting>
 </section>
-<para>Finally, there are several more parameters for OFDM:
-</para>
+<section>
+<title>More OFDM parameters</title>
 <section id="fe-transmit-mode-t">
 <title>Number of carriers per channel</title>
 <programlisting>
@@ -427,6 +455,7 @@ typedef enum fe_hierarchy {
  } fe_hierarchy_t;
 </programlisting>
 </section>
+</section>
 
 </section>
 
diff --git a/Documentation/DocBook/media/dvb/intro.xml b/Documentation/DocBook/media/dvb/intro.xml
index 170064a..2048b53 100644
--- a/Documentation/DocBook/media/dvb/intro.xml
+++ b/Documentation/DocBook/media/dvb/intro.xml
@@ -205,7 +205,7 @@ a partial path like:</para>
 additional include file <emphasis
 role="tt">linux/dvb/version.h</emphasis> exists, which defines the
 constant <emphasis role="tt">DVB_API_VERSION</emphasis>. This document
-describes <emphasis role="tt">DVB_API_VERSION 5.4</emphasis>.
+describes <emphasis role="tt">DVB_API_VERSION 5.8</emphasis>.
 </para>
 
 </section>
diff --git a/Documentation/DocBook/media/dvb/kdapi.xml b/Documentation/DocBook/media/dvb/kdapi.xml
index 6c67481..6c11ec5 100644
--- a/Documentation/DocBook/media/dvb/kdapi.xml
+++ b/Documentation/DocBook/media/dvb/kdapi.xml
@@ -2,7 +2,7 @@
 <para>The kernel demux API defines a driver-internal interface for registering low-level,
 hardware specific driver to a hardware independent demux layer. It is only of interest for
 DVB device driver writers. The header file for this API is named <emphasis role="tt">demux.h</emphasis> and located in
-<emphasis role="tt">drivers/media/dvb/dvb-core</emphasis>.
+<emphasis role="tt">drivers/media/dvb-core</emphasis>.
 </para>
 <para>Maintainer note: This section must be reviewed. It is probably out of date.
 </para>
diff --git a/Documentation/DocBook/media/dvb/net.xml b/Documentation/DocBook/media/dvb/net.xml
index 67d37e5..a193e86 100644
--- a/Documentation/DocBook/media/dvb/net.xml
+++ b/Documentation/DocBook/media/dvb/net.xml
@@ -26,4 +26,131 @@ struct dvb_net_if {
 <title>DVB net Function Calls</title>
 <para>To be written&#x2026;
 </para>
+
+<section id="NET_ADD_IF"
+role="subsection"><title>NET_ADD_IF</title>
+<para>DESCRIPTION
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>This ioctl is undocumented. Documentation is welcome.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>SYNOPSIS
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>int ioctl(fd, int request = NET_ADD_IF,
+ struct dvb_net_if *if);</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>PARAMETERS
+</para>
+<informaltable><tgroup cols="2"><tbody><row><entry
+ align="char">
+<para>int fd</para>
+</entry><entry
+ align="char">
+<para>File descriptor returned by a previous call to open().</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>int request</para>
+</entry><entry
+ align="char">
+<para>Equals NET_ADD_IF for this command.</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>struct dvb_net_if *if
+</para>
+</entry><entry
+ align="char">
+<para>Undocumented.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+&return-value-dvb;
+</section>
+
+<section id="NET_REMOVE_IF"
+role="subsection"><title>NET_REMOVE_IF</title>
+<para>DESCRIPTION
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>This ioctl is undocumented. Documentation is welcome.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>SYNOPSIS
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>int ioctl(fd, int request = NET_REMOVE_IF);
+</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>PARAMETERS
+</para>
+<informaltable><tgroup cols="2"><tbody><row><entry
+ align="char">
+<para>int fd</para>
+</entry><entry
+ align="char">
+<para>File descriptor returned by a previous call to open().</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>int request</para>
+</entry><entry
+ align="char">
+<para>Equals NET_REMOVE_IF for this command.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+&return-value-dvb;
+</section>
+
+<section id="NET_GET_IF"
+role="subsection"><title>NET_GET_IF</title>
+<para>DESCRIPTION
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>This ioctl is undocumented. Documentation is welcome.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>SYNOPSIS
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>int ioctl(fd, int request = NET_GET_IF,
+ struct dvb_net_if *if);</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>PARAMETERS
+</para>
+<informaltable><tgroup cols="2"><tbody><row><entry
+ align="char">
+<para>int fd</para>
+</entry><entry
+ align="char">
+<para>File descriptor returned by a previous call to open().</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>int request</para>
+</entry><entry
+ align="char">
+<para>Equals NET_GET_IF for this command.</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>struct dvb_net_if *if
+</para>
+</entry><entry
+ align="char">
+<para>Undocumented.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+&return-value-dvb;
+</section>
 </section>
diff --git a/Documentation/DocBook/media/dvb/video.xml b/Documentation/DocBook/media/dvb/video.xml
index 25fb823..3ea1ca7 100644
--- a/Documentation/DocBook/media/dvb/video.xml
+++ b/Documentation/DocBook/media/dvb/video.xml
@@ -15,6 +15,10 @@ the audio and video device as well as the video4linux device.
 <para>The ioctls that deal with SPUs (sub picture units) and navigation packets are only
 supported on some MPEG decoders made for DVD playback.
 </para>
+<para>
+These ioctls were also used by V4L2 to control MPEG decoders implemented in V4L2. The use
+of these ioctls for that purpose has been made obsolete and proper V4L2 ioctls or controls
+have been created to replace that functionality.</para>
 <section id="video_types">
 <title>Video Data Types</title>
 
@@ -55,7 +59,7 @@ typedef enum {
 </section>
 
 <section id="video-stream-source-t">
-<title>video stream source</title>
+<title>video_stream_source_t</title>
 <para>The video stream source is set through the VIDEO_SELECT_SOURCE call and can take
 the following values, depending on whether we are replaying from an internal (demuxer) or
 external (user write) source.
@@ -76,7 +80,7 @@ call.
 </section>
 
 <section id="video-play-state-t">
-<title>video play state</title>
+<title>video_play_state_t</title>
 <para>The following values can be returned by the VIDEO_GET_STATUS call representing the
 state of video playback.
 </para>
@@ -90,9 +94,9 @@ typedef enum {
 </section>
 
 <section id="video-command">
+<title>struct video_command</title>
 <para>The structure must be zeroed before use by the application
 This ensures it can be extended safely in the future.</para>
-<title>struct video-command</title>
 <programlisting>
 struct video_command {
 	__u32 cmd;
@@ -121,7 +125,7 @@ struct video_command {
 </section>
 
 <section id="video-size-t">
-<title>struct video_size-t</title>
+<title>video_size_t</title>
 <programlisting>
 typedef struct {
 	int w;
@@ -217,7 +221,7 @@ bits set according to the hardwares capabilities.
 </section>
 
 <section id="video-system">
-<title>video system</title>
+<title>video_system_t</title>
 <para>A call to VIDEO_SET_SYSTEM sets the desired video system for TV output. The
 following system types can be set:
 </para>
@@ -263,7 +267,7 @@ call expects the following format for that information:
 
 </section>
 <section id="video-spu">
-<title>video SPU</title>
+<title>struct video_spu</title>
 <para>Calling VIDEO_SET_SPU deactivates or activates SPU decoding, according to the
 following format:
 </para>
@@ -277,12 +281,12 @@ following format:
 
 </section>
 <section id="video-spu-palette">
-<title>video SPU palette</title>
+<title>struct video_spu_palette</title>
 <para>The following structure is used to set the SPU palette by calling VIDEO_SPU_PALETTE:
 </para>
 <programlisting>
  typedef
- struct video_spu_palette{
+ struct video_spu_palette {
 	 int length;
 	 uint8_t &#x22C6;palette;
  } video_spu_palette_t;
@@ -290,13 +294,13 @@ following format:
 
 </section>
 <section id="video-navi-pack">
-<title>video NAVI pack</title>
+<title>struct video_navi_pack</title>
 <para>In order to get the navigational data the following structure has to be passed to the ioctl
 VIDEO_GET_NAVI:
 </para>
 <programlisting>
  typedef
- struct video_navi_pack{
+ struct video_navi_pack {
 	 int length;         /&#x22C6; 0 ... 1024 &#x22C6;/
 	 uint8_t data[1024];
  } video_navi_pack_t;
@@ -305,7 +309,7 @@ VIDEO_GET_NAVI:
 
 
 <section id="video-attributes-t">
-<title>video attributes</title>
+<title>video_attributes_t</title>
 <para>The following attributes can be set by a call to VIDEO_SET_ATTRIBUTES:
 </para>
 <programlisting>
@@ -541,6 +545,8 @@ VIDEO_GET_NAVI:
 role="subsection"><title>VIDEO_STOP</title>
 <para>DESCRIPTION
 </para>
+<para>This ioctl is for DVB devices only. To control a V4L2 decoder use the V4L2
+&VIDIOC-DECODER-CMD; instead.</para>
 <informaltable><tgroup cols="1"><tbody><row><entry
  align="char">
 <para>This ioctl call asks the Video Device to stop playing the current stream.
@@ -598,6 +604,8 @@ role="subsection"><title>VIDEO_STOP</title>
 role="subsection"><title>VIDEO_PLAY</title>
 <para>DESCRIPTION
 </para>
+<para>This ioctl is for DVB devices only. To control a V4L2 decoder use the V4L2
+&VIDIOC-DECODER-CMD; instead.</para>
 <informaltable><tgroup cols="1"><tbody><row><entry
  align="char">
 <para>This ioctl call asks the Video Device to start playing a video stream from the
@@ -634,6 +642,8 @@ role="subsection"><title>VIDEO_PLAY</title>
 role="subsection"><title>VIDEO_FREEZE</title>
 <para>DESCRIPTION
 </para>
+<para>This ioctl is for DVB devices only. To control a V4L2 decoder use the V4L2
+&VIDIOC-DECODER-CMD; instead.</para>
 <informaltable><tgroup cols="1"><tbody><row><entry
  align="char">
 <para>This ioctl call suspends the live video stream being played. Decoding
@@ -674,6 +684,8 @@ role="subsection"><title>VIDEO_FREEZE</title>
 role="subsection"><title>VIDEO_CONTINUE</title>
 <para>DESCRIPTION
 </para>
+<para>This ioctl is for DVB devices only. To control a V4L2 decoder use the V4L2
+&VIDIOC-DECODER-CMD; instead.</para>
 <informaltable><tgroup cols="1"><tbody><row><entry
  align="char">
 <para>This ioctl call restarts decoding and playing processes of the video stream
@@ -710,6 +722,9 @@ role="subsection"><title>VIDEO_CONTINUE</title>
 role="subsection"><title>VIDEO_SELECT_SOURCE</title>
 <para>DESCRIPTION
 </para>
+<para>This ioctl is for DVB devices only. This ioctl was also supported by the
+V4L2 ivtv driver, but that has been replaced by the ivtv-specific
+<constant>IVTV_IOC_PASSTHROUGH_MODE</constant> ioctl.</para>
 <informaltable><tgroup cols="1"><tbody><row><entry
  align="char">
 <para>This ioctl call informs the video device which source shall be used for the input
@@ -845,10 +860,160 @@ role="subsection"><title>VIDEO_GET_STATUS</title>
  </row></tbody></tgroup></informaltable>
 &return-value-dvb;
 
+</section><section id="VIDEO_GET_FRAME_COUNT"
+role="subsection"><title>VIDEO_GET_FRAME_COUNT</title>
+<para>DESCRIPTION
+</para>
+<para>This ioctl is obsolete. Do not use in new drivers. For V4L2 decoders this
+ioctl has been replaced by the <constant>V4L2_CID_MPEG_VIDEO_DEC_FRAME</constant> control.</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>This ioctl call asks the Video Device to return the number of displayed frames
+since the decoder was started.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>SYNOPSIS
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>int ioctl(int fd, int request =
+ VIDEO_GET_FRAME_COUNT, __u64 *pts);</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>PARAMETERS
+</para>
+<informaltable><tgroup cols="2"><tbody><row><entry
+ align="char">
+<para>int fd</para>
+</entry><entry
+ align="char">
+<para>File descriptor returned by a previous call to open().</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>int request</para>
+</entry><entry
+ align="char">
+<para>Equals VIDEO_GET_FRAME_COUNT for this
+ command.</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>__u64 *pts
+</para>
+</entry><entry
+ align="char">
+<para>Returns the number of frames displayed since the decoder was started.
+</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+&return-value-dvb;
+
+</section><section id="VIDEO_GET_PTS"
+role="subsection"><title>VIDEO_GET_PTS</title>
+<para>DESCRIPTION
+</para>
+<para>This ioctl is obsolete. Do not use in new drivers. For V4L2 decoders this
+ioctl has been replaced by the <constant>V4L2_CID_MPEG_VIDEO_DEC_PTS</constant> control.</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>This ioctl call asks the Video Device to return the current PTS timestamp.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>SYNOPSIS
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>int ioctl(int fd, int request =
+ VIDEO_GET_PTS, __u64 *pts);</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>PARAMETERS
+</para>
+<informaltable><tgroup cols="2"><tbody><row><entry
+ align="char">
+<para>int fd</para>
+</entry><entry
+ align="char">
+<para>File descriptor returned by a previous call to open().</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>int request</para>
+</entry><entry
+ align="char">
+<para>Equals VIDEO_GET_PTS for this
+ command.</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>__u64 *pts
+</para>
+</entry><entry
+ align="char">
+<para>Returns the 33-bit timestamp as defined in ITU T-REC-H.222.0 / ISO/IEC 13818-1.
+</para>
+<para>
+The PTS should belong to the currently played
+frame if possible, but may also be a value close to it
+like the PTS of the last decoded frame or the last PTS
+extracted by the PES parser.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+&return-value-dvb;
+
+</section><section id="VIDEO_GET_FRAME_RATE"
+role="subsection"><title>VIDEO_GET_FRAME_RATE</title>
+<para>DESCRIPTION
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>This ioctl call asks the Video Device to return the current framerate.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>SYNOPSIS
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>int ioctl(int fd, int request =
+ VIDEO_GET_FRAME_RATE, unsigned int *rate);</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>PARAMETERS
+</para>
+<informaltable><tgroup cols="2"><tbody><row><entry
+ align="char">
+<para>int fd</para>
+</entry><entry
+ align="char">
+<para>File descriptor returned by a previous call to open().</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>int request</para>
+</entry><entry
+ align="char">
+<para>Equals VIDEO_GET_FRAME_RATE for this
+ command.</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>unsigned int *rate
+</para>
+</entry><entry
+ align="char">
+<para>Returns the framerate in number of frames per 1000 seconds.
+</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+&return-value-dvb;
+
 </section><section id="VIDEO_GET_EVENT"
 role="subsection"><title>VIDEO_GET_EVENT</title>
 <para>DESCRIPTION
 </para>
+<para>This ioctl is for DVB devices only. To get events from a V4L2 decoder use the V4L2
+&VIDIOC-DQEVENT; ioctl instead.</para>
 <informaltable><tgroup cols="1"><tbody><row><entry
  align="char">
 <para>This ioctl call returns an event of type video_event if available. If an event is
@@ -914,6 +1079,152 @@ role="subsection"><title>VIDEO_GET_EVENT</title>
 </entry>
  </row></tbody></tgroup></informaltable>
 
+</section><section id="VIDEO_COMMAND"
+role="subsection"><title>VIDEO_COMMAND</title>
+<para>DESCRIPTION
+</para>
+<para>This ioctl is obsolete. Do not use in new drivers. For V4L2 decoders this
+ioctl has been replaced by the &VIDIOC-DECODER-CMD; ioctl.</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>This ioctl commands the decoder. The <constant>video_command</constant> struct
+is a subset of the <constant>v4l2_decoder_cmd</constant> struct, so refer to the
+&VIDIOC-DECODER-CMD; documentation for more information.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>SYNOPSIS
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>int ioctl(int fd, int request =
+ VIDEO_COMMAND, struct video_command *cmd);</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>PARAMETERS
+</para>
+<informaltable><tgroup cols="2"><tbody><row><entry
+ align="char">
+<para>int fd</para>
+</entry><entry
+ align="char">
+<para>File descriptor returned by a previous call to open().</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>int request</para>
+</entry><entry
+ align="char">
+<para>Equals VIDEO_COMMAND for this
+ command.</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>struct video_command *cmd
+</para>
+</entry><entry
+ align="char">
+<para>Commands the decoder.
+</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+&return-value-dvb;
+
+</section><section id="VIDEO_TRY_COMMAND"
+role="subsection"><title>VIDEO_TRY_COMMAND</title>
+<para>DESCRIPTION
+</para>
+<para>This ioctl is obsolete. Do not use in new drivers. For V4L2 decoders this
+ioctl has been replaced by the &VIDIOC-TRY-DECODER-CMD; ioctl.</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>This ioctl tries a decoder command. The <constant>video_command</constant> struct
+is a subset of the <constant>v4l2_decoder_cmd</constant> struct, so refer to the
+&VIDIOC-TRY-DECODER-CMD; documentation for more information.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>SYNOPSIS
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>int ioctl(int fd, int request =
+ VIDEO_TRY_COMMAND, struct video_command *cmd);</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>PARAMETERS
+</para>
+<informaltable><tgroup cols="2"><tbody><row><entry
+ align="char">
+<para>int fd</para>
+</entry><entry
+ align="char">
+<para>File descriptor returned by a previous call to open().</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>int request</para>
+</entry><entry
+ align="char">
+<para>Equals VIDEO_TRY_COMMAND for this
+ command.</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>struct video_command *cmd
+</para>
+</entry><entry
+ align="char">
+<para>Try a decoder command.
+</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+&return-value-dvb;
+
+</section><section id="VIDEO_GET_SIZE"
+role="subsection"><title>VIDEO_GET_SIZE</title>
+<para>DESCRIPTION
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>This ioctl returns the size and aspect ratio.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>SYNOPSIS
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>int ioctl(int fd, int request =
+ VIDEO_GET_SIZE, video_size_t *size);</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>PARAMETERS
+</para>
+<informaltable><tgroup cols="2"><tbody><row><entry
+ align="char">
+<para>int fd</para>
+</entry><entry
+ align="char">
+<para>File descriptor returned by a previous call to open().</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>int request</para>
+</entry><entry
+ align="char">
+<para>Equals VIDEO_GET_SIZE for this
+ command.</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>video_size_t *size
+</para>
+</entry><entry
+ align="char">
+<para>Returns the size and aspect ratio.
+</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+&return-value-dvb;
+
 </section><section id="VIDEO_SET_DISPLAY_FORMAT"
 role="subsection"><title>VIDEO_SET_DISPLAY_FORMAT</title>
 <para>DESCRIPTION
diff --git a/Documentation/DocBook/media/v4l/biblio.xml b/Documentation/DocBook/media/v4l/biblio.xml
index 1078e45..d2eb79e 100644
--- a/Documentation/DocBook/media/v4l/biblio.xml
+++ b/Documentation/DocBook/media/v4l/biblio.xml
@@ -178,23 +178,23 @@ Signal - NTSC for Studio Applications"</title>
 1125-Line High-Definition Production"</title>
     </biblioentry>
 
-    <biblioentry id="en50067">
-      <abbrev>EN&nbsp;50067</abbrev>
+    <biblioentry id="iec62106">
+      <abbrev>IEC&nbsp;62106</abbrev>
       <authorgroup>
-	<corpauthor>European Committee for Electrotechnical Standardization
-(<ulink url="http://www.cenelec.eu">http://www.cenelec.eu</ulink>)</corpauthor>
+	<corpauthor>International Electrotechnical Commission
+(<ulink url="http://www.iec.ch">http://www.iec.ch</ulink>)</corpauthor>
       </authorgroup>
       <title>Specification of the radio data system (RDS) for VHF/FM sound broadcasting
 in the frequency range from 87,5 to 108,0 MHz</title>
     </biblioentry>
 
     <biblioentry id="nrsc4">
-      <abbrev>NRSC-4</abbrev>
+      <abbrev>NRSC-4-B</abbrev>
       <authorgroup>
 	<corpauthor>National Radio Systems Committee
 (<ulink url="http://www.nrscstandards.org">http://www.nrscstandards.org</ulink>)</corpauthor>
       </authorgroup>
-      <title>NRSC-4: United States RBDS Standard</title>
+      <title>NRSC-4-B: United States RBDS Standard</title>
     </biblioentry>
 
     <biblioentry id="iso12232">
@@ -226,4 +226,44 @@ in the frequency range from 87,5 to 108,0 MHz</title>
       <title>VESA and Industry Standards and Guidelines for Computer Display Monitor Timing (DMT)</title>
     </biblioentry>
 
+    <biblioentry id="vesaedid">
+      <abbrev>EDID</abbrev>
+      <authorgroup>
+	<corpauthor>Video Electronics Standards Association
+(<ulink url="http://www.vesa.org">http://www.vesa.org</ulink>)</corpauthor>
+      </authorgroup>
+      <title>VESA Enhanced Extended Display Identification Data Standard</title>
+      <subtitle>Release A, Revision 2</subtitle>
+    </biblioentry>
+
+    <biblioentry id="hdcp">
+      <abbrev>HDCP</abbrev>
+      <authorgroup>
+	<corpauthor>Digital Content Protection LLC
+(<ulink url="http://www.digital-cp.com">http://www.digital-cp.com</ulink>)</corpauthor>
+      </authorgroup>
+      <title>High-bandwidth Digital Content Protection System</title>
+      <subtitle>Revision 1.3</subtitle>
+    </biblioentry>
+
+    <biblioentry id="hdmi">
+      <abbrev>HDMI</abbrev>
+      <authorgroup>
+	<corpauthor>HDMI Licensing LLC
+(<ulink url="http://www.hdmi.org">http://www.hdmi.org</ulink>)</corpauthor>
+      </authorgroup>
+      <title>High-Definition Multimedia Interface</title>
+      <subtitle>Specification Version 1.4a</subtitle>
+    </biblioentry>
+
+    <biblioentry id="dp">
+      <abbrev>DP</abbrev>
+      <authorgroup>
+	<corpauthor>Video Electronics Standards Association
+(<ulink url="http://www.vesa.org">http://www.vesa.org</ulink>)</corpauthor>
+      </authorgroup>
+      <title>VESA DisplayPort Standard</title>
+      <subtitle>Version 1, Revision 2</subtitle>
+    </biblioentry>
+
   </bibliography>
diff --git a/Documentation/DocBook/media/v4l/compat.xml b/Documentation/DocBook/media/v4l/compat.xml
index faa0fd1..98e8d08 100644
--- a/Documentation/DocBook/media/v4l/compat.xml
+++ b/Documentation/DocBook/media/v4l/compat.xml
@@ -2468,21 +2468,9 @@ that used it. It was originally scheduled for removal in 2.6.35.
 	  <structfield>reserved2</structfield> and removed
 	  <constant>V4L2_BUF_FLAG_INPUT</constant>.</para>
 	</listitem>
-      </orderedlist>
-    </section>
-
-    <section>
-      <title>V4L2 in Linux 3.6</title>
-      <orderedlist>
         <listitem>
 	  <para>Added V4L2_CAP_VIDEO_M2M and V4L2_CAP_VIDEO_M2M_MPLANE capabilities.</para>
         </listitem>
-      </orderedlist>
-    </section>
-
-    <section>
-      <title>V4L2 in Linux 3.6</title>
-      <orderedlist>
         <listitem>
 	  <para>Added support for frequency band enumerations: &VIDIOC-ENUM-FREQ-BANDS;.</para>
         </listitem>
@@ -2615,10 +2603,6 @@ ioctls.</para>
 	  and &VIDIOC-SUBDEV-S-SELECTION; ioctls.</para>
         </listitem>
         <listitem>
-	  <para><link linkend="v4l2-auto-focus-area"><constant>
-	  V4L2_CID_AUTO_FOCUS_AREA</constant></link> control.</para>
-        </listitem>
-        <listitem>
 	  <para>Support for frequency band enumeration: &VIDIOC-ENUM-FREQ-BANDS; ioctl.</para>
         </listitem>
       </itemizedlist>
diff --git a/Documentation/DocBook/media/v4l/controls.xml b/Documentation/DocBook/media/v4l/controls.xml
index b0964fb..272a5f7 100644
--- a/Documentation/DocBook/media/v4l/controls.xml
+++ b/Documentation/DocBook/media/v4l/controls.xml
@@ -3505,7 +3505,7 @@ This encodes up to 31 pre-defined programme types.</entry>
 	  </row>
 	  <row><entry spanname="descr">Sets the Programme Service name (PS_NAME) for transmission.
 It is intended for static display on a receiver. It is the primary aid to listeners in programme service
-identification and selection.  In Annex E of <xref linkend="en50067" />, the RDS specification,
+identification and selection.  In Annex E of <xref linkend="iec62106" />, the RDS specification,
 there is a full description of the correct character encoding for Programme Service name strings.
 Also from RDS specification, PS is usually a single eight character text. However, it is also possible
 to find receivers which can scroll strings sized as 8 x N characters. So, this control must be configured
@@ -3519,7 +3519,7 @@ with steps of 8 characters. The result is it must always contain a string with s
 what is being broadcasted. RDS Radio Text can be applied when broadcaster wishes to transmit longer PS names,
 programme-related information or any other text. In these cases, RadioText should be used in addition to
 <constant>V4L2_CID_RDS_TX_PS_NAME</constant>. The encoding for Radio Text strings is also fully described
-in Annex E of <xref linkend="en50067" />. The length of Radio Text strings depends on which RDS Block is being
+in Annex E of <xref linkend="iec62106" />. The length of Radio Text strings depends on which RDS Block is being
 used to transmit it, either 32 (2A block) or 64 (2B block).  However, it is also possible
 to find receivers which can scroll strings sized as 32 x N or 64 x N characters. So, this control must be configured
 with steps of 32 or 64 characters. The result is it must always contain a string with size multiple of 32 or 64. </entry>
@@ -3650,7 +3650,7 @@ manually or automatically if set to zero. Unit, range and step are driver-specif
       </table>
 
 <para>For more details about RDS specification, refer to
-<xref linkend="en50067" /> document, from CENELEC.</para>
+<xref linkend="iec62106" /> document, from CENELEC.</para>
     </section>
 
     <section id="flash-controls">
@@ -3717,232 +3717,231 @@ interface and may change in the future.</para>
 	    use case involving camera or individually.
 	  </para>
 
-	</section>
 
+          <table pgwide="1" frame="none" id="flash-control-id">
+          <title>Flash Control IDs</title>
+    
+          <tgroup cols="4">
+    	<colspec colname="c1" colwidth="1*" />
+    	<colspec colname="c2" colwidth="6*" />
+    	<colspec colname="c3" colwidth="2*" />
+    	<colspec colname="c4" colwidth="6*" />
+    	<spanspec namest="c1" nameend="c2" spanname="id" />
+    	<spanspec namest="c2" nameend="c4" spanname="descr" />
+    	<thead>
+    	  <row>
+    	    <entry spanname="id" align="left">ID</entry>
+    	    <entry align="left">Type</entry>
+    	  </row><row rowsep="1"><entry spanname="descr" align="left">Description</entry>
+    	  </row>
+    	</thead>
+    	<tbody valign="top">
+    	  <row><entry></entry></row>
+    	  <row>
+    	    <entry spanname="id"><constant>V4L2_CID_FLASH_CLASS</constant></entry>
+    	    <entry>class</entry>
+    	  </row>
+    	  <row>
+    	    <entry spanname="descr">The FLASH class descriptor.</entry>
+    	  </row>
+    	  <row>
+    	    <entry spanname="id"><constant>V4L2_CID_FLASH_LED_MODE</constant></entry>
+    	    <entry>menu</entry>
+    	  </row>
+    	  <row id="v4l2-flash-led-mode">
+    	    <entry spanname="descr">Defines the mode of the flash LED,
+    	    the high-power white LED attached to the flash controller.
+    	    Setting this control may not be possible in presence of
+    	    some faults. See V4L2_CID_FLASH_FAULT.</entry>
+    	  </row>
+    	  <row>
+    	    <entrytbl spanname="descr" cols="2">
+    	      <tbody valign="top">
+    		<row>
+    		  <entry><constant>V4L2_FLASH_LED_MODE_NONE</constant></entry>
+    		  <entry>Off.</entry>
+    		</row>
+    		<row>
+    		  <entry><constant>V4L2_FLASH_LED_MODE_FLASH</constant></entry>
+    		  <entry>Flash mode.</entry>
+    		</row>
+    		<row>
+    		  <entry><constant>V4L2_FLASH_LED_MODE_TORCH</constant></entry>
+    		  <entry>Torch mode. See V4L2_CID_FLASH_TORCH_INTENSITY.</entry>
+    		</row>
+    	      </tbody>
+    	    </entrytbl>
+    	  </row>
+    	  <row>
+    	    <entry spanname="id"><constant>V4L2_CID_FLASH_STROBE_SOURCE</constant></entry>
+    	    <entry>menu</entry>
+    	  </row>
+    	  <row id="v4l2-flash-strobe-source"><entry
+    	  spanname="descr">Defines the source of the flash LED
+    	  strobe.</entry>
+    	  </row>
+    	  <row>
+    	    <entrytbl spanname="descr" cols="2">
+    	      <tbody valign="top">
+    		<row>
+    		  <entry><constant>V4L2_FLASH_STROBE_SOURCE_SOFTWARE</constant></entry>
+    		  <entry>The flash strobe is triggered by using
+    		  the V4L2_CID_FLASH_STROBE control.</entry>
+    		</row>
+    		<row>
+    		  <entry><constant>V4L2_FLASH_STROBE_SOURCE_EXTERNAL</constant></entry>
+    		  <entry>The flash strobe is triggered by an
+    		  external source. Typically this is a sensor,
+    		  which makes it possible to synchronises the
+    		  flash strobe start to exposure start.</entry>
+    		</row>
+    	      </tbody>
+    	    </entrytbl>
+    	  </row>
+    	  <row>
+    	    <entry spanname="id"><constant>V4L2_CID_FLASH_STROBE</constant></entry>
+    	    <entry>button</entry>
+    	  </row>
+    	  <row>
+    	    <entry spanname="descr">Strobe flash. Valid when
+    	    V4L2_CID_FLASH_LED_MODE is set to
+    	    V4L2_FLASH_LED_MODE_FLASH and V4L2_CID_FLASH_STROBE_SOURCE
+    	    is set to V4L2_FLASH_STROBE_SOURCE_SOFTWARE. Setting this
+    	    control may not be possible in presence of some faults.
+    	    See V4L2_CID_FLASH_FAULT.</entry>
+    	  </row>
+    	  <row>
+    	    <entry spanname="id"><constant>V4L2_CID_FLASH_STROBE_STOP</constant></entry>
+    	    <entry>button</entry>
+    	  </row>
+    	  <row><entry spanname="descr">Stop flash strobe immediately.</entry>
+    	  </row>
+    	  <row>
+    	    <entry spanname="id"><constant>V4L2_CID_FLASH_STROBE_STATUS</constant></entry>
+    	    <entry>boolean</entry>
+    	  </row>
+    	  <row>
+    	    <entry spanname="descr">Strobe status: whether the flash
+    	    is strobing at the moment or not. This is a read-only
+    	    control.</entry>
+    	  </row>
+    	  <row>
+    	    <entry spanname="id"><constant>V4L2_CID_FLASH_TIMEOUT</constant></entry>
+    	    <entry>integer</entry>
+    	  </row>
+    	  <row>
+    	    <entry spanname="descr">Hardware timeout for flash. The
+    	    flash strobe is stopped after this period of time has
+    	    passed from the start of the strobe.</entry>
+    	  </row>
+    	  <row>
+    	    <entry spanname="id"><constant>V4L2_CID_FLASH_INTENSITY</constant></entry>
+    	    <entry>integer</entry>
+    	  </row>
+    	  <row>
+    	    <entry spanname="descr">Intensity of the flash strobe when
+    	    the flash LED is in flash mode
+    	    (V4L2_FLASH_LED_MODE_FLASH). The unit should be milliamps
+    	    (mA) if possible.</entry>
+    	  </row>
+    	  <row>
+    	    <entry spanname="id"><constant>V4L2_CID_FLASH_TORCH_INTENSITY</constant></entry>
+    	    <entry>integer</entry>
+    	  </row>
+    	  <row>
+    	    <entry spanname="descr">Intensity of the flash LED in
+    	    torch mode (V4L2_FLASH_LED_MODE_TORCH). The unit should be
+    	    milliamps (mA) if possible. Setting this control may not
+    	    be possible in presence of some faults. See
+    	    V4L2_CID_FLASH_FAULT.</entry>
+    	  </row>
+    	  <row>
+    	    <entry spanname="id"><constant>V4L2_CID_FLASH_INDICATOR_INTENSITY</constant></entry>
+    	    <entry>integer</entry>
+    	  </row>
+    	  <row>
+    	    <entry spanname="descr">Intensity of the indicator LED.
+    	    The indicator LED may be fully independent of the flash
+    	    LED. The unit should be microamps (uA) if possible.</entry>
+    	  </row>
+    	  <row>
+    	    <entry spanname="id"><constant>V4L2_CID_FLASH_FAULT</constant></entry>
+    	    <entry>bitmask</entry>
+    	  </row>
+    	  <row>
+    	    <entry spanname="descr">Faults related to the flash. The
+    	    faults tell about specific problems in the flash chip
+    	    itself or the LEDs attached to it. Faults may prevent
+    	    further use of some of the flash controls. In particular,
+    	    V4L2_CID_FLASH_LED_MODE is set to V4L2_FLASH_LED_MODE_NONE
+    	    if the fault affects the flash LED. Exactly which faults
+    	    have such an effect is chip dependent. Reading the faults
+    	    resets the control and returns the chip to a usable state
+    	    if possible.</entry>
+    	  </row>
+    	  <row>
+    	    <entrytbl spanname="descr" cols="2">
+    	      <tbody valign="top">
+    		<row>
+    		  <entry><constant>V4L2_FLASH_FAULT_OVER_VOLTAGE</constant></entry>
+    		  <entry>Flash controller voltage to the flash LED
+    		  has exceeded the limit specific to the flash
+    		  controller.</entry>
+    		</row>
+    		<row>
+    		  <entry><constant>V4L2_FLASH_FAULT_TIMEOUT</constant></entry>
+    		  <entry>The flash strobe was still on when
+    		  the timeout set by the user ---
+    		  V4L2_CID_FLASH_TIMEOUT control --- has expired.
+    		  Not all flash controllers may set this in all
+    		  such conditions.</entry>
+    		</row>
+    		<row>
+    		  <entry><constant>V4L2_FLASH_FAULT_OVER_TEMPERATURE</constant></entry>
+    		  <entry>The flash controller has overheated.</entry>
+    		</row>
+    		<row>
+    		  <entry><constant>V4L2_FLASH_FAULT_SHORT_CIRCUIT</constant></entry>
+    		  <entry>The short circuit protection of the flash
+    		  controller has been triggered.</entry>
+    		</row>
+    		<row>
+    		  <entry><constant>V4L2_FLASH_FAULT_OVER_CURRENT</constant></entry>
+    		  <entry>Current in the LED power supply has exceeded the limit
+    		  specific to the flash controller.</entry>
+    		</row>
+    		<row>
+    		  <entry><constant>V4L2_FLASH_FAULT_INDICATOR</constant></entry>
+    		  <entry>The flash controller has detected a short or open
+    		  circuit condition on the indicator LED.</entry>
+    		</row>
+    	      </tbody>
+    	    </entrytbl>
+    	  </row>
+    	  <row>
+    	    <entry spanname="id"><constant>V4L2_CID_FLASH_CHARGE</constant></entry>
+    	    <entry>boolean</entry>
+    	  </row>
+    	  <row><entry spanname="descr">Enable or disable charging of the xenon
+    	  flash capacitor.</entry>
+    	  </row>
+    	  <row>
+    	    <entry spanname="id"><constant>V4L2_CID_FLASH_READY</constant></entry>
+    	    <entry>boolean</entry>
+    	  </row>
+    	  <row>
+    	    <entry spanname="descr">Is the flash ready to strobe?
+    	    Xenon flashes require their capacitors charged before
+    	    strobing. LED flashes often require a cooldown period
+    	    after strobe during which another strobe will not be
+    	    possible. This is a read-only control.</entry>
+    	  </row>
+    	  <row><entry></entry></row>
+    	</tbody>
+          </tgroup>
+          </table>
+	</section>
       </section>
-
-      <table pgwide="1" frame="none" id="flash-control-id">
-      <title>Flash Control IDs</title>
-
-      <tgroup cols="4">
-	<colspec colname="c1" colwidth="1*" />
-	<colspec colname="c2" colwidth="6*" />
-	<colspec colname="c3" colwidth="2*" />
-	<colspec colname="c4" colwidth="6*" />
-	<spanspec namest="c1" nameend="c2" spanname="id" />
-	<spanspec namest="c2" nameend="c4" spanname="descr" />
-	<thead>
-	  <row>
-	    <entry spanname="id" align="left">ID</entry>
-	    <entry align="left">Type</entry>
-	  </row><row rowsep="1"><entry spanname="descr" align="left">Description</entry>
-	  </row>
-	</thead>
-	<tbody valign="top">
-	  <row><entry></entry></row>
-	  <row>
-	    <entry spanname="id"><constant>V4L2_CID_FLASH_CLASS</constant></entry>
-	    <entry>class</entry>
-	  </row>
-	  <row>
-	    <entry spanname="descr">The FLASH class descriptor.</entry>
-	  </row>
-	  <row>
-	    <entry spanname="id"><constant>V4L2_CID_FLASH_LED_MODE</constant></entry>
-	    <entry>menu</entry>
-	  </row>
-	  <row id="v4l2-flash-led-mode">
-	    <entry spanname="descr">Defines the mode of the flash LED,
-	    the high-power white LED attached to the flash controller.
-	    Setting this control may not be possible in presence of
-	    some faults. See V4L2_CID_FLASH_FAULT.</entry>
-	  </row>
-	  <row>
-	    <entrytbl spanname="descr" cols="2">
-	      <tbody valign="top">
-		<row>
-		  <entry><constant>V4L2_FLASH_LED_MODE_NONE</constant></entry>
-		  <entry>Off.</entry>
-		</row>
-		<row>
-		  <entry><constant>V4L2_FLASH_LED_MODE_FLASH</constant></entry>
-		  <entry>Flash mode.</entry>
-		</row>
-		<row>
-		  <entry><constant>V4L2_FLASH_LED_MODE_TORCH</constant></entry>
-		  <entry>Torch mode. See V4L2_CID_FLASH_TORCH_INTENSITY.</entry>
-		</row>
-	      </tbody>
-	    </entrytbl>
-	  </row>
-	  <row>
-	    <entry spanname="id"><constant>V4L2_CID_FLASH_STROBE_SOURCE</constant></entry>
-	    <entry>menu</entry>
-	  </row>
-	  <row id="v4l2-flash-strobe-source"><entry
-	  spanname="descr">Defines the source of the flash LED
-	  strobe.</entry>
-	  </row>
-	  <row>
-	    <entrytbl spanname="descr" cols="2">
-	      <tbody valign="top">
-		<row>
-		  <entry><constant>V4L2_FLASH_STROBE_SOURCE_SOFTWARE</constant></entry>
-		  <entry>The flash strobe is triggered by using
-		  the V4L2_CID_FLASH_STROBE control.</entry>
-		</row>
-		<row>
-		  <entry><constant>V4L2_FLASH_STROBE_SOURCE_EXTERNAL</constant></entry>
-		  <entry>The flash strobe is triggered by an
-		  external source. Typically this is a sensor,
-		  which makes it possible to synchronises the
-		  flash strobe start to exposure start.</entry>
-		</row>
-	      </tbody>
-	    </entrytbl>
-	  </row>
-	  <row>
-	    <entry spanname="id"><constant>V4L2_CID_FLASH_STROBE</constant></entry>
-	    <entry>button</entry>
-	  </row>
-	  <row>
-	    <entry spanname="descr">Strobe flash. Valid when
-	    V4L2_CID_FLASH_LED_MODE is set to
-	    V4L2_FLASH_LED_MODE_FLASH and V4L2_CID_FLASH_STROBE_SOURCE
-	    is set to V4L2_FLASH_STROBE_SOURCE_SOFTWARE. Setting this
-	    control may not be possible in presence of some faults.
-	    See V4L2_CID_FLASH_FAULT.</entry>
-	  </row>
-	  <row>
-	    <entry spanname="id"><constant>V4L2_CID_FLASH_STROBE_STOP</constant></entry>
-	    <entry>button</entry>
-	  </row>
-	  <row><entry spanname="descr">Stop flash strobe immediately.</entry>
-	  </row>
-	  <row>
-	    <entry spanname="id"><constant>V4L2_CID_FLASH_STROBE_STATUS</constant></entry>
-	    <entry>boolean</entry>
-	  </row>
-	  <row>
-	    <entry spanname="descr">Strobe status: whether the flash
-	    is strobing at the moment or not. This is a read-only
-	    control.</entry>
-	  </row>
-	  <row>
-	    <entry spanname="id"><constant>V4L2_CID_FLASH_TIMEOUT</constant></entry>
-	    <entry>integer</entry>
-	  </row>
-	  <row>
-	    <entry spanname="descr">Hardware timeout for flash. The
-	    flash strobe is stopped after this period of time has
-	    passed from the start of the strobe.</entry>
-	  </row>
-	  <row>
-	    <entry spanname="id"><constant>V4L2_CID_FLASH_INTENSITY</constant></entry>
-	    <entry>integer</entry>
-	  </row>
-	  <row>
-	    <entry spanname="descr">Intensity of the flash strobe when
-	    the flash LED is in flash mode
-	    (V4L2_FLASH_LED_MODE_FLASH). The unit should be milliamps
-	    (mA) if possible.</entry>
-	  </row>
-	  <row>
-	    <entry spanname="id"><constant>V4L2_CID_FLASH_TORCH_INTENSITY</constant></entry>
-	    <entry>integer</entry>
-	  </row>
-	  <row>
-	    <entry spanname="descr">Intensity of the flash LED in
-	    torch mode (V4L2_FLASH_LED_MODE_TORCH). The unit should be
-	    milliamps (mA) if possible. Setting this control may not
-	    be possible in presence of some faults. See
-	    V4L2_CID_FLASH_FAULT.</entry>
-	  </row>
-	  <row>
-	    <entry spanname="id"><constant>V4L2_CID_FLASH_INDICATOR_INTENSITY</constant></entry>
-	    <entry>integer</entry>
-	  </row>
-	  <row>
-	    <entry spanname="descr">Intensity of the indicator LED.
-	    The indicator LED may be fully independent of the flash
-	    LED. The unit should be microamps (uA) if possible.</entry>
-	  </row>
-	  <row>
-	    <entry spanname="id"><constant>V4L2_CID_FLASH_FAULT</constant></entry>
-	    <entry>bitmask</entry>
-	  </row>
-	  <row>
-	    <entry spanname="descr">Faults related to the flash. The
-	    faults tell about specific problems in the flash chip
-	    itself or the LEDs attached to it. Faults may prevent
-	    further use of some of the flash controls. In particular,
-	    V4L2_CID_FLASH_LED_MODE is set to V4L2_FLASH_LED_MODE_NONE
-	    if the fault affects the flash LED. Exactly which faults
-	    have such an effect is chip dependent. Reading the faults
-	    resets the control and returns the chip to a usable state
-	    if possible.</entry>
-	  </row>
-	  <row>
-	    <entrytbl spanname="descr" cols="2">
-	      <tbody valign="top">
-		<row>
-		  <entry><constant>V4L2_FLASH_FAULT_OVER_VOLTAGE</constant></entry>
-		  <entry>Flash controller voltage to the flash LED
-		  has exceeded the limit specific to the flash
-		  controller.</entry>
-		</row>
-		<row>
-		  <entry><constant>V4L2_FLASH_FAULT_TIMEOUT</constant></entry>
-		  <entry>The flash strobe was still on when
-		  the timeout set by the user ---
-		  V4L2_CID_FLASH_TIMEOUT control --- has expired.
-		  Not all flash controllers may set this in all
-		  such conditions.</entry>
-		</row>
-		<row>
-		  <entry><constant>V4L2_FLASH_FAULT_OVER_TEMPERATURE</constant></entry>
-		  <entry>The flash controller has overheated.</entry>
-		</row>
-		<row>
-		  <entry><constant>V4L2_FLASH_FAULT_SHORT_CIRCUIT</constant></entry>
-		  <entry>The short circuit protection of the flash
-		  controller has been triggered.</entry>
-		</row>
-		<row>
-		  <entry><constant>V4L2_FLASH_FAULT_OVER_CURRENT</constant></entry>
-		  <entry>Current in the LED power supply has exceeded the limit
-		  specific to the flash controller.</entry>
-		</row>
-		<row>
-		  <entry><constant>V4L2_FLASH_FAULT_INDICATOR</constant></entry>
-		  <entry>The flash controller has detected a short or open
-		  circuit condition on the indicator LED.</entry>
-		</row>
-	      </tbody>
-	    </entrytbl>
-	  </row>
-	  <row>
-	    <entry spanname="id"><constant>V4L2_CID_FLASH_CHARGE</constant></entry>
-	    <entry>boolean</entry>
-	  </row>
-	  <row><entry spanname="descr">Enable or disable charging of the xenon
-	  flash capacitor.</entry>
-	  </row>
-	  <row>
-	    <entry spanname="id"><constant>V4L2_CID_FLASH_READY</constant></entry>
-	    <entry>boolean</entry>
-	  </row>
-	  <row>
-	    <entry spanname="descr">Is the flash ready to strobe?
-	    Xenon flashes require their capacitors charged before
-	    strobing. LED flashes often require a cooldown period
-	    after strobe during which another strobe will not be
-	    possible. This is a read-only control.</entry>
-	  </row>
-	  <row><entry></entry></row>
-	</tbody>
-      </tgroup>
-      </table>
     </section>
 
     <section id="jpeg-controls">
@@ -4274,4 +4273,165 @@ interface and may change in the future.</para>
       </table>
 
     </section>
+
+    <section id="dv-controls">
+      <title>Digital Video Control Reference</title>
+
+      <note>
+	<title>Experimental</title>
+
+	<para>This is an <link
+	linkend="experimental">experimental</link> interface and may
+	change in the future.</para>
+      </note>
+
+      <para>
+	The Digital Video control class is intended to control receivers
+	and transmitters for <ulink url="http://en.wikipedia.org/wiki/Vga">VGA</ulink>,
+	<ulink url="http://en.wikipedia.org/wiki/Digital_Visual_Interface">DVI</ulink>
+	(Digital Visual Interface), HDMI (<xref linkend="hdmi" />) and DisplayPort (<xref linkend="dp" />).
+	These controls are generally expected to be private to the receiver or transmitter
+	subdevice that implements them, so they are only exposed on the
+	<filename>/dev/v4l-subdev*</filename> device node.
+      </para>
+
+      <para>Note that these devices can have multiple input or output pads which are
+      hooked up to e.g. HDMI connectors. Even though the subdevice will receive or
+      transmit video from/to only one of those pads, the other pads can still be
+      active when it comes to EDID (Extended Display Identification Data,
+      <xref linkend="vesaedid" />) and HDCP (High-bandwidth Digital Content
+      Protection System, <xref linkend="hdcp" />) processing, allowing the device
+      to do the fairly slow EDID/HDCP handling in advance. This allows for quick
+      switching between connectors.</para>
+
+      <para>These pads appear in several of the controls in this section as
+      bitmasks, one bit for each pad. Bit 0 corresponds to pad 0, bit 1 to pad 1,
+      etc. The maximum value of the control is the set of valid pads.</para>
+
+      <table pgwide="1" frame="none" id="dv-control-id">
+      <title>Digital Video Control IDs</title>
+
+      <tgroup cols="4">
+	<colspec colname="c1" colwidth="1*" />
+	<colspec colname="c2" colwidth="6*" />
+	<colspec colname="c3" colwidth="2*" />
+	<colspec colname="c4" colwidth="6*" />
+	<spanspec namest="c1" nameend="c2" spanname="id" />
+	<spanspec namest="c2" nameend="c4" spanname="descr" />
+	<thead>
+	  <row>
+	    <entry spanname="id" align="left">ID</entry>
+	    <entry align="left">Type</entry>
+	  </row><row rowsep="1"><entry spanname="descr" align="left">Description</entry>
+	  </row>
+	</thead>
+	<tbody valign="top">
+	  <row><entry></entry></row>
+	  <row>
+	    <entry spanname="id"><constant>V4L2_CID_DV_CLASS</constant></entry>
+	    <entry>class</entry>
+	  </row>
+	  <row>
+	    <entry spanname="descr">The Digital Video class descriptor.</entry>
+	  </row>
+	  <row>
+	    <entry spanname="id"><constant>V4L2_CID_DV_TX_HOTPLUG</constant></entry>
+	    <entry>bitmask</entry>
+	  </row>
+	  <row>
+	    <entry spanname="descr">Many connectors have a hotplug pin which is high
+	    if EDID information is available from the source. This control shows the
+	    state of the hotplug pin as seen by the transmitter.
+	    Each bit corresponds to an output pad on the transmitter. If an output pad
+	    does not have an associated hotplug pin, then the bit for that pad will be 0.
+	    This read-only control is applicable to DVI-D, HDMI and DisplayPort connectors.
+	    </entry>
+	  </row>
+	  <row>
+	    <entry spanname="id"><constant>V4L2_CID_DV_TX_RXSENSE</constant></entry>
+	    <entry>bitmask</entry>
+	  </row>
+	  <row>
+	    <entry spanname="descr">Rx Sense is the detection of pull-ups on the TMDS
+            clock lines. This normally means that the sink has left/entered standby (i.e.
+	    the transmitter can sense that the receiver is ready to receive video).
+	    Each bit corresponds to an output pad on the transmitter. If an output pad
+	    does not have an associated Rx Sense, then the bit for that pad will be 0.
+	    This read-only control is applicable to DVI-D and HDMI devices.
+	    </entry>
+	  </row>
+	  <row>
+	    <entry spanname="id"><constant>V4L2_CID_DV_TX_EDID_PRESENT</constant></entry>
+	    <entry>bitmask</entry>
+	  </row>
+	  <row>
+	    <entry spanname="descr">When the transmitter sees the hotplug signal from the
+	    receiver it will attempt to read the EDID. If set, then the transmitter has read
+	    at least the first block (= 128 bytes).
+	    Each bit corresponds to an output pad on the transmitter. If an output pad
+	    does not support EDIDs, then the bit for that pad will be 0.
+	    This read-only control is applicable to VGA, DVI-A/D, HDMI and DisplayPort connectors.
+	    </entry>
+	  </row>
+	  <row>
+	    <entry spanname="id"><constant>V4L2_CID_DV_TX_MODE</constant></entry>
+	    <entry id="v4l2-dv-tx-mode">enum v4l2_dv_tx_mode</entry>
+	  </row>
+	  <row>
+	    <entry spanname="descr">HDMI transmitters can transmit in DVI-D mode (just video)
+	    or in HDMI mode (video + audio + auxiliary data). This control selects which mode
+	    to use: V4L2_DV_TX_MODE_DVI_D or V4L2_DV_TX_MODE_HDMI.
+	    This control is applicable to HDMI connectors.
+	    </entry>
+	  </row>
+	  <row>
+	    <entry spanname="id"><constant>V4L2_CID_DV_TX_RGB_RANGE</constant></entry>
+	    <entry id="v4l2-dv-rgb-range">enum v4l2_dv_rgb_range</entry>
+	  </row>
+	  <row>
+	    <entry spanname="descr">Select the quantization range for RGB output. V4L2_DV_RANGE_AUTO
+	    follows the RGB quantization range specified in the standard for the video interface
+	    (ie. <xref linkend="cea861" /> for HDMI). V4L2_DV_RANGE_LIMITED and V4L2_DV_RANGE_FULL override the standard
+	    to be compatible with sinks that have not implemented the standard correctly
+	    (unfortunately quite common for HDMI and DVI-D). Full range allows all possible values to be
+	    used whereas limited range sets the range to (16 &lt;&lt; (N-8)) - (235 &lt;&lt; (N-8))
+	    where N is the number of bits per component.
+	    This control is applicable to VGA, DVI-A/D, HDMI and DisplayPort connectors.
+	    </entry>
+	  </row>
+	  <row>
+	    <entry spanname="id"><constant>V4L2_CID_DV_RX_POWER_PRESENT</constant></entry>
+	    <entry>bitmask</entry>
+	  </row>
+	  <row>
+	    <entry spanname="descr">Detects whether the receiver receives power from the source
+	    (e.g. HDMI carries 5V on one of the pins). This is often used to power an eeprom
+	    which contains EDID information, such that the source can read the EDID even if
+	    the sink is in standby/power off.
+	    Each bit corresponds to an input pad on the transmitter. If an input pad
+	    cannot detect whether power is present, then the bit for that pad will be 0.
+	    This read-only control is applicable to DVI-D, HDMI and DisplayPort connectors.
+	    </entry>
+	  </row>
+	  <row>
+	    <entry spanname="id"><constant>V4L2_CID_DV_RX_RGB_RANGE</constant></entry>
+	    <entry>enum v4l2_dv_rgb_range</entry>
+	  </row>
+	  <row>
+	    <entry spanname="descr">Select the quantization range for RGB input. V4L2_DV_RANGE_AUTO
+	    follows the RGB quantization range specified in the standard for the video interface
+	    (ie. <xref linkend="cea861" /> for HDMI). V4L2_DV_RANGE_LIMITED and V4L2_DV_RANGE_FULL override the standard
+	    to be compatible with sources that have not implemented the standard correctly
+	    (unfortunately quite common for HDMI and DVI-D). Full range allows all possible values to be
+	    used whereas limited range sets the range to (16 &lt;&lt; (N-8)) - (235 &lt;&lt; (N-8))
+	    where N is the number of bits per component.
+	    This control is applicable to VGA, DVI-A/D, HDMI and DisplayPort connectors.
+	    </entry>
+	  </row>
+	  <row><entry></entry></row>
+	</tbody>
+      </tgroup>
+      </table>
+
+    </section>
 </section>
diff --git a/Documentation/DocBook/media/v4l/dev-rds.xml b/Documentation/DocBook/media/v4l/dev-rds.xml
index 38883a4..be2f337 100644
--- a/Documentation/DocBook/media/v4l/dev-rds.xml
+++ b/Documentation/DocBook/media/v4l/dev-rds.xml
@@ -6,7 +6,7 @@ information, on an inaudible audio subcarrier of a radio program. This
 interface is aimed at devices capable of receiving and/or transmitting RDS
 information.</para>
 
-      <para>For more information see the core RDS standard <xref linkend="en50067" />
+      <para>For more information see the core RDS standard <xref linkend="iec62106" />
 and the RBDS standard <xref linkend="nrsc4" />.</para>
 
       <para>Note that the RBDS standard as is used in the USA is almost identical
diff --git a/Documentation/DocBook/media/v4l/dev-subdev.xml b/Documentation/DocBook/media/v4l/dev-subdev.xml
index a3d9dd0..d15aaf8 100644
--- a/Documentation/DocBook/media/v4l/dev-subdev.xml
+++ b/Documentation/DocBook/media/v4l/dev-subdev.xml
@@ -374,29 +374,29 @@
       rectangle --- if it is supported by the hardware.</para>
 
       <orderedlist>
-	<listitem>Sink pad format. The user configures the sink pad
+	<listitem><para>Sink pad format. The user configures the sink pad
 	format. This format defines the parameters of the image the
-	entity receives through the pad for further processing.</listitem>
+	entity receives through the pad for further processing.</para></listitem>
 
-	<listitem>Sink pad actual crop selection. The sink pad crop
-	defines the crop performed to the sink pad format.</listitem>
+	<listitem><para>Sink pad actual crop selection. The sink pad crop
+	defines the crop performed to the sink pad format.</para></listitem>
 
-	<listitem>Sink pad actual compose selection. The size of the
+	<listitem><para>Sink pad actual compose selection. The size of the
 	sink pad compose rectangle defines the scaling ratio compared
 	to the size of the sink pad crop rectangle. The location of
 	the compose rectangle specifies the location of the actual
 	sink compose rectangle in the sink compose bounds
-	rectangle.</listitem>
+	rectangle.</para></listitem>
 
-	<listitem>Source pad actual crop selection. Crop on the source
+	<listitem><para>Source pad actual crop selection. Crop on the source
 	pad defines crop performed to the image in the sink compose
-	bounds rectangle.</listitem>
+	bounds rectangle.</para></listitem>
 
-	<listitem>Source pad format. The source pad format defines the
+	<listitem><para>Source pad format. The source pad format defines the
 	output pixel format of the subdev, as well as the other
 	parameters with the exception of the image width and height.
 	Width and height are defined by the size of the source pad
-	actual crop selection.</listitem>
+	actual crop selection.</para></listitem>
       </orderedlist>
 
       <para>Accessing any of the above rectangles not supported by the
diff --git a/Documentation/DocBook/media/v4l/gen-errors.xml b/Documentation/DocBook/media/v4l/gen-errors.xml
index 5bbf3ce..737ecaa 100644
--- a/Documentation/DocBook/media/v4l/gen-errors.xml
+++ b/Documentation/DocBook/media/v4l/gen-errors.xml
@@ -7,6 +7,13 @@
     <tbody valign="top">
 	<!-- Keep it ordered alphabetically -->
       <row>
+	<entry>EAGAIN</entry>
+	<entry>The ioctl can't be handled because the device is in state where
+	       it can't perform it. This could happen for example in case where
+	       device is sleeping and ioctl is performed to query statistics.
+	</entry>
+      </row>
+      <row>
 	<entry>EBADF</entry>
 	<entry>The file descriptor is not a valid.</entry>
       </row>
@@ -51,11 +58,6 @@
 	       for periodic transfers (up to 80% of the USB bandwidth).</entry>
       </row>
       <row>
-	<entry>ENOSYS or EOPNOTSUPP</entry>
-	<entry>Function not available for this device (dvb API only. Will likely
-	       be replaced anytime soon by ENOTTY).</entry>
-      </row>
-      <row>
 	<entry>EPERM</entry>
 	<entry>Permission denied. Can be returned if the device needs write
 		permission, or some special capabilities is needed
diff --git a/Documentation/DocBook/media/v4l/pixfmt-srggb10dpcm8.xml b/Documentation/DocBook/media/v4l/pixfmt-srggb10dpcm8.xml
index 8eace3e..2d3f0b1a 100644
--- a/Documentation/DocBook/media/v4l/pixfmt-srggb10dpcm8.xml
+++ b/Documentation/DocBook/media/v4l/pixfmt-srggb10dpcm8.xml
@@ -22,8 +22,7 @@
 	with 10 bits per colour compressed to 8 bits each, using DPCM
 	compression. DPCM, differential pulse-code modulation, is lossy.
 	Each colour component consumes 8 bits of memory. In other respects
-	this format is similar to <xref
-	linkend="pixfmt-srggb10">.</xref></para>
+	this format is similar to <xref linkend="pixfmt-srggb10" />.</para>
 
       </refsect1>
     </refentry>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-yvu420m.xml b/Documentation/DocBook/media/v4l/pixfmt-yvu420m.xml
new file mode 100644
index 0000000..2330667
--- /dev/null
+++ b/Documentation/DocBook/media/v4l/pixfmt-yvu420m.xml
@@ -0,0 +1,154 @@
+    <refentry id="V4L2-PIX-FMT-YVU420M">
+      <refmeta>
+	<refentrytitle>V4L2_PIX_FMT_YVU420M ('YM21')</refentrytitle>
+	&manvol;
+      </refmeta>
+      <refnamediv>
+	<refname> <constant>V4L2_PIX_FMT_YVU420M</constant></refname>
+	<refpurpose>Variation of <constant>V4L2_PIX_FMT_YVU420</constant>
+	  with planes non contiguous in memory. </refpurpose>
+      </refnamediv>
+
+      <refsect1>
+	<title>Description</title>
+
+	<para>This is a multi-planar format, as opposed to a packed format.
+The three components are separated into three sub-images or planes.
+
+The Y plane is first. The Y plane has one byte per pixel. The Cr data
+constitutes the second plane which is half the width and half
+the height of the Y plane (and of the image). Each Cr belongs to four
+pixels, a two-by-two square of the image. For example,
+Cr<subscript>0</subscript> belongs to Y'<subscript>00</subscript>,
+Y'<subscript>01</subscript>, Y'<subscript>10</subscript>, and
+Y'<subscript>11</subscript>. The Cb data, just like the Cr plane, constitutes
+the third plane. </para>
+
+	<para>If the Y plane has pad bytes after each row, then the Cr
+and Cb planes have half as many pad bytes after their rows. In other
+words, two Cx rows (including padding) is exactly as long as one Y row
+(including padding).</para>
+
+	<para><constant>V4L2_PIX_FMT_YVU420M</constant> is intended to be
+used only in drivers and applications that support the multi-planar API,
+described in <xref linkend="planar-apis"/>. </para>
+
+	<example>
+	  <title><constant>V4L2_PIX_FMT_YVU420M</constant> 4 &times; 4
+pixel image</title>
+
+	  <formalpara>
+	    <title>Byte Order.</title>
+	    <para>Each cell is one byte.
+		<informaltable frame="none">
+		<tgroup cols="5" align="center">
+		  <colspec align="left" colwidth="2*" />
+		  <tbody valign="top">
+		    <row>
+		      <entry>start0&nbsp;+&nbsp;0:</entry>
+		      <entry>Y'<subscript>00</subscript></entry>
+		      <entry>Y'<subscript>01</subscript></entry>
+		      <entry>Y'<subscript>02</subscript></entry>
+		      <entry>Y'<subscript>03</subscript></entry>
+		    </row>
+		    <row>
+		      <entry>start0&nbsp;+&nbsp;4:</entry>
+		      <entry>Y'<subscript>10</subscript></entry>
+		      <entry>Y'<subscript>11</subscript></entry>
+		      <entry>Y'<subscript>12</subscript></entry>
+		      <entry>Y'<subscript>13</subscript></entry>
+		    </row>
+		    <row>
+		      <entry>start0&nbsp;+&nbsp;8:</entry>
+		      <entry>Y'<subscript>20</subscript></entry>
+		      <entry>Y'<subscript>21</subscript></entry>
+		      <entry>Y'<subscript>22</subscript></entry>
+		      <entry>Y'<subscript>23</subscript></entry>
+		    </row>
+		    <row>
+		      <entry>start0&nbsp;+&nbsp;12:</entry>
+		      <entry>Y'<subscript>30</subscript></entry>
+		      <entry>Y'<subscript>31</subscript></entry>
+		      <entry>Y'<subscript>32</subscript></entry>
+		      <entry>Y'<subscript>33</subscript></entry>
+		    </row>
+		    <row><entry></entry></row>
+		    <row>
+		      <entry>start1&nbsp;+&nbsp;0:</entry>
+		      <entry>Cr<subscript>00</subscript></entry>
+		      <entry>Cr<subscript>01</subscript></entry>
+		    </row>
+		    <row>
+		      <entry>start1&nbsp;+&nbsp;2:</entry>
+		      <entry>Cr<subscript>10</subscript></entry>
+		      <entry>Cr<subscript>11</subscript></entry>
+		    </row>
+		    <row><entry></entry></row>
+		    <row>
+		      <entry>start2&nbsp;+&nbsp;0:</entry>
+		      <entry>Cb<subscript>00</subscript></entry>
+		      <entry>Cb<subscript>01</subscript></entry>
+		    </row>
+		    <row>
+		      <entry>start2&nbsp;+&nbsp;2:</entry>
+		      <entry>Cb<subscript>10</subscript></entry>
+		      <entry>Cb<subscript>11</subscript></entry>
+		    </row>
+		  </tbody>
+		</tgroup>
+		</informaltable>
+	      </para>
+	  </formalpara>
+
+	  <formalpara>
+	    <title>Color Sample Location.</title>
+	    <para>
+		<informaltable frame="none">
+		<tgroup cols="7" align="center">
+		  <tbody valign="top">
+		    <row>
+		      <entry></entry>
+		      <entry>0</entry><entry></entry><entry>1</entry><entry></entry>
+		      <entry>2</entry><entry></entry><entry>3</entry>
+		    </row>
+		    <row>
+		      <entry>0</entry>
+		      <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
+		      <entry>Y</entry><entry></entry><entry>Y</entry>
+		    </row>
+		    <row>
+		      <entry></entry>
+		      <entry></entry><entry>C</entry><entry></entry><entry></entry>
+		      <entry></entry><entry>C</entry><entry></entry>
+		    </row>
+		    <row>
+		      <entry>1</entry>
+		      <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
+		      <entry>Y</entry><entry></entry><entry>Y</entry>
+		    </row>
+		    <row>
+		      <entry></entry>
+		    </row>
+		    <row>
+		      <entry>2</entry>
+		      <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
+		      <entry>Y</entry><entry></entry><entry>Y</entry>
+		    </row>
+		    <row>
+		      <entry></entry>
+		      <entry></entry><entry>C</entry><entry></entry><entry></entry>
+		      <entry></entry><entry>C</entry><entry></entry>
+		    </row>
+		    <row>
+		      <entry>3</entry>
+		      <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
+		      <entry>Y</entry><entry></entry><entry>Y</entry>
+		    </row>
+		  </tbody>
+		</tgroup>
+		</informaltable>
+	      </para>
+	  </formalpara>
+	</example>
+      </refsect1>
+    </refentry>
diff --git a/Documentation/DocBook/media/v4l/pixfmt.xml b/Documentation/DocBook/media/v4l/pixfmt.xml
index e58934c..1ddbfab 100644
--- a/Documentation/DocBook/media/v4l/pixfmt.xml
+++ b/Documentation/DocBook/media/v4l/pixfmt.xml
@@ -708,6 +708,7 @@ information.</para>
     &sub-y41p;
     &sub-yuv420;
     &sub-yuv420m;
+    &sub-yvu420m;
     &sub-yuv410;
     &sub-yuv422p;
     &sub-yuv411p;
diff --git a/Documentation/DocBook/media/v4l/selection-api.xml b/Documentation/DocBook/media/v4l/selection-api.xml
index e7ed507..4c238ce 100644
--- a/Documentation/DocBook/media/v4l/selection-api.xml
+++ b/Documentation/DocBook/media/v4l/selection-api.xml
@@ -40,6 +40,7 @@ cropping and composing rectangles have the same size.</para>
     <section>
       <title>Selection targets</title>
 
+      <para>
       <figure id="sel-targets-capture">
 	<title>Cropping and composing targets</title>
 	<mediaobject>
@@ -52,12 +53,12 @@ cropping and composing rectangles have the same size.</para>
 	  </textobject>
 	</mediaobject>
       </figure>
+      </para>
 
+      <para>See <xref linkend="v4l2-selection-targets" /> for more
+    information.</para>
     </section>
 
-    See <xref linkend="v4l2-selection-targets" /> for more
-    information.
-
   <section>
 
   <title>Configuration</title>
@@ -216,18 +217,17 @@ composing and cropping operations by setting the appropriate targets.  The V4L2
 API lacks any support for composing to and cropping from an image inside a
 memory buffer.  The application could configure a capture device to fill only a
 part of an image by abusing V4L2 API.  Cropping a smaller image from a larger
-one is achieved by setting the field <structfield>
-&v4l2-pix-format;::bytesperline </structfield>.  Introducing an image offsets
-could be done by modifying field <structfield> &v4l2-buffer;::m:userptr
-</structfield> before calling <constant> VIDIOC_QBUF </constant>. Those
+one is achieved by setting the field
+&v4l2-pix-format;<structfield>::bytesperline</structfield>.  Introducing an image offsets
+could be done by modifying field &v4l2-buffer;<structfield>::m_userptr</structfield>
+before calling <constant> VIDIOC_QBUF </constant>. Those
 operations should be avoided because they are not portable (endianness), and do
 not work for macroblock and Bayer formats and mmap buffers.  The selection API
 deals with configuration of buffer cropping/composing in a clear, intuitive and
 portable way.  Next, with the selection API the concepts of the padded target
-and constraints flags are introduced.  Finally, <structname> &v4l2-crop;
-</structname> and <structname> &v4l2-cropcap; </structname> have no reserved
-fields. Therefore there is no way to extend their functionality.  The new
-<structname> &v4l2-selection; </structname> provides a lot of place for future
+and constraints flags are introduced.  Finally, &v4l2-crop; and &v4l2-cropcap;
+have no reserved fields. Therefore there is no way to extend their functionality.
+The new &v4l2-selection; provides a lot of place for future
 extensions.  Driver developers are encouraged to implement only selection API.
 The former cropping API would be simulated using the new one. </para>
 
diff --git a/Documentation/DocBook/media/v4l/v4l2.xml b/Documentation/DocBook/media/v4l/v4l2.xml
index eee6908..0292ed1 100644
--- a/Documentation/DocBook/media/v4l/v4l2.xml
+++ b/Documentation/DocBook/media/v4l/v4l2.xml
@@ -145,9 +145,12 @@ applications. -->
 	<authorinitials>hv</authorinitials>
 	<revremark>Added VIDIOC_ENUM_FREQ_BANDS.
 	</revremark>
+      </revision>
+
+      <revision>
 	<revnumber>3.5</revnumber>
 	<date>2012-05-07</date>
-	<authorinitials>sa, sn</authorinitials>
+	<authorinitials>sa, sn, hv</authorinitials>
 	<revremark>Added V4L2_CTRL_TYPE_INTEGER_MENU and V4L2 subdev
 	    selections API. Improved the description of V4L2_CID_COLORFX
 	    control, added V4L2_CID_COLORFX_CBCR control.
@@ -158,11 +161,8 @@ applications. -->
 	    V4L2_CID_3A_LOCK, V4L2_CID_AUTO_FOCUS_START,
 	    V4L2_CID_AUTO_FOCUS_STOP, V4L2_CID_AUTO_FOCUS_STATUS
 	    and V4L2_CID_AUTO_FOCUS_RANGE.
-	</revremark>
-	<date>2012-05-01</date>
-	<authorinitials>hv</authorinitials>
-	<revremark>Added VIDIOC_ENUM_DV_TIMINGS, VIDIOC_QUERY_DV_TIMINGS and
-	VIDIOC_DV_TIMINGS_CAP.
+	    Added VIDIOC_ENUM_DV_TIMINGS, VIDIOC_QUERY_DV_TIMINGS and
+	    VIDIOC_DV_TIMINGS_CAP.
 	</revremark>
       </revision>
 
@@ -472,7 +472,7 @@ and discussions on the V4L mailing list.</revremark>
 </partinfo>
 
 <title>Video for Linux Two API Specification</title>
- <subtitle>Revision 3.5</subtitle>
+ <subtitle>Revision 3.6</subtitle>
 
   <chapter id="common">
     &sub-common;
diff --git a/Documentation/DocBook/media/v4l/vidioc-g-selection.xml b/Documentation/DocBook/media/v4l/vidioc-g-selection.xml
index f76d8a6..b11ec75 100644
--- a/Documentation/DocBook/media/v4l/vidioc-g-selection.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-g-selection.xml
@@ -152,12 +152,10 @@ satisfactory parameters have been negotiated. If constraints flags have to be
 violated at then ERANGE is returned. The error indicates that <emphasis> there
 exist no rectangle </emphasis> that satisfies the constraints.</para>
 
-  </refsect1>
-
   <para>Selection targets and flags are documented in <xref
   linkend="v4l2-selections-common"/>.</para>
 
-    <section>
+    <para>
       <figure id="sel-const-adjust">
 	<title>Size adjustments with constraint flags.</title>
 	<mediaobject>
@@ -170,9 +168,9 @@ exist no rectangle </emphasis> that satisfies the constraints.</para>
 	  </textobject>
 	</mediaobject>
       </figure>
-    </section>
+    </para>
 
-  <refsect1>
+  <para>
     <table pgwide="1" frame="none" id="v4l2-selection">
       <title>struct <structname>v4l2_selection</structname></title>
       <tgroup cols="3">
@@ -208,6 +206,7 @@ exist no rectangle </emphasis> that satisfies the constraints.</para>
 	</tbody>
       </tgroup>
     </table>
+  </para>
   </refsect1>
 
   <refsect1>
diff --git a/Documentation/DocBook/media/v4l/vidioc-g-tuner.xml b/Documentation/DocBook/media/v4l/vidioc-g-tuner.xml
index 701138f..6cc8201 100644
--- a/Documentation/DocBook/media/v4l/vidioc-g-tuner.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-g-tuner.xml
@@ -354,6 +354,12 @@ radio tuners.</entry>
 	<entry>The &VIDIOC-ENUM-FREQ-BANDS; ioctl can be used to enumerate
 	the available frequency bands.</entry>
 	  </row>
+	  <row>
+	<entry><constant>V4L2_TUNER_CAP_HWSEEK_PROG_LIM</constant></entry>
+	<entry>0x0800</entry>
+	<entry>The range to search when using the hardware seek functionality
+	is programmable, see &VIDIOC-S-HW-FREQ-SEEK; for details.</entry>
+	  </row>
 	</tbody>
       </tgroup>
     </table>
diff --git a/Documentation/DocBook/media/v4l/vidioc-qbuf.xml b/Documentation/DocBook/media/v4l/vidioc-qbuf.xml
index 77ff5be..6a821a6 100644
--- a/Documentation/DocBook/media/v4l/vidioc-qbuf.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-qbuf.xml
@@ -155,6 +155,8 @@ or no buffers have been allocated yet, or the
 <structfield>userptr</structfield> or
 <structfield>length</structfield> are invalid.</para>
 	</listitem>
+      </varlistentry>
+      <varlistentry>
 	<term><errorcode>EIO</errorcode></term>
 	<listitem>
 	  <para><constant>VIDIOC_DQBUF</constant> failed due to an
diff --git a/Documentation/DocBook/media/v4l/vidioc-subdev-g-selection.xml b/Documentation/DocBook/media/v4l/vidioc-subdev-g-selection.xml
index f33cc81..1ba9e99 100644
--- a/Documentation/DocBook/media/v4l/vidioc-subdev-g-selection.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-subdev-g-selection.xml
@@ -69,23 +69,22 @@
     more information on how each selection target affects the image
     processing pipeline inside the subdevice.</para>
 
-    <section>
+    <refsect2>
       <title>Types of selection targets</title>
 
       <para>There are two types of selection targets: actual and bounds. The
       actual targets are the targets which configure the hardware. The BOUNDS
       target will return a rectangle that contain all possible actual
       rectangles.</para>
-    </section>
+    </refsect2>
 
-    <section>
+    <refsect2>
       <title>Discovering supported features</title>
 
       <para>To discover which targets are supported, the user can
       perform <constant>VIDIOC_SUBDEV_G_SELECTION</constant> on them.
       Any unsupported target will return
       <constant>EINVAL</constant>.</para>
-    </section>
 
     <para>Selection targets and flags are documented in <xref
     linkend="v4l2-selections-common"/>.</para>
@@ -132,6 +131,7 @@
 	</tbody>
       </tgroup>
     </table>
+    </refsect2>
 
   </refsect1>
 
diff --git a/Documentation/DocBook/media_api.tmpl b/Documentation/DocBook/media_api.tmpl
index 4e8e898..f2413ac 100644
--- a/Documentation/DocBook/media_api.tmpl
+++ b/Documentation/DocBook/media_api.tmpl
@@ -29,7 +29,7 @@
 <title>LINUX MEDIA INFRASTRUCTURE API</title>
 
 <copyright>
-	<year>2009-2011</year>
+	<year>2009-2012</year>
 	<holder>LinuxTV Developers</holder>
 </copyright>
 
@@ -53,7 +53,7 @@ Foundation. A copy of the license is included in the chapter entitled
 		video and radio straming devices, including video cameras,
 		analog and digital TV receiver cards, AM/FM receiver cards,
 		streaming capture devices.</para>
-	<para>It is divided into three parts.</para>
+	<para>It is divided into four parts.</para>
 	<para>The first part covers radio, capture,
 		cameras and analog TV devices.</para>
 	<para>The second part covers the
@@ -62,7 +62,8 @@ Foundation. A copy of the license is included in the chapter entitled
 		in fact it covers several different video standards including
 		DVB-T, DVB-S, DVB-C and ATSC. The API is currently being updated
 		to documment support also for DVB-S2, ISDB-T and ISDB-S.</para>
-	<para>The third part covers Remote Controller API</para>
+	<para>The third part covers the Remote Controller API.</para>
+	<para>The fourth part covers the Media Controller API.</para>
 	<para>For additional information and for the latest development code,
 		see: <ulink url="http://linuxtv.org">http://linuxtv.org</ulink>.</para>
 	<para>For discussing improvements, reporting troubles, sending new drivers, etc, please mail to: <ulink url="http://vger.kernel.org/vger-lists.html#linux-media">Linux Media Mailing List (LMML).</ulink>.</para>
@@ -87,7 +88,7 @@ Foundation. A copy of the license is included in the chapter entitled
 </author>
 </authorgroup>
 <copyright>
-	<year>2009-2011</year>
+	<year>2009-2012</year>
 	<holder>Mauro Carvalho Chehab</holder>
 </copyright>
 
diff --git a/Documentation/DocBook/mtdnand.tmpl b/Documentation/DocBook/mtdnand.tmpl
index e0aedb7..fe122d6 100644
--- a/Documentation/DocBook/mtdnand.tmpl
+++ b/Documentation/DocBook/mtdnand.tmpl
@@ -1216,8 +1216,6 @@ in this page</entry>
 #define	NAND_BBT_LASTBLOCK	0x00000010
 /* The bbt is at the given page, else we must scan for the bbt */
 #define NAND_BBT_ABSPAGE	0x00000020
-/* The bbt is at the given page, else we must scan for the bbt */
-#define NAND_BBT_SEARCH		0x00000040
 /* bbt is stored per chip on multichip devices */
 #define NAND_BBT_PERCHIP	0x00000080
 /* bbt has a version counter at offset veroffs */
diff --git a/Documentation/RCU/checklist.txt b/Documentation/RCU/checklist.txt
index fc103d7..cdb20d4 100644
--- a/Documentation/RCU/checklist.txt
+++ b/Documentation/RCU/checklist.txt
@@ -310,6 +310,12 @@ over a rather long period of time, but improvements are always welcome!
 	code under the influence of preempt_disable(), you instead
 	need to use synchronize_irq() or synchronize_sched().
 
+	This same limitation also applies to synchronize_rcu_bh()
+	and synchronize_srcu(), as well as to the asynchronous and
+	expedited forms of the three primitives, namely call_rcu(),
+	call_rcu_bh(), call_srcu(), synchronize_rcu_expedited(),
+	synchronize_rcu_bh_expedited(), and synchronize_srcu_expedited().
+
 12.	Any lock acquired by an RCU callback must be acquired elsewhere
 	with softirq disabled, e.g., via spin_lock_irqsave(),
 	spin_lock_bh(), etc.  Failing to disable irq on a given
diff --git a/Documentation/RCU/stallwarn.txt b/Documentation/RCU/stallwarn.txt
index 523364e..1927151 100644
--- a/Documentation/RCU/stallwarn.txt
+++ b/Documentation/RCU/stallwarn.txt
@@ -99,7 +99,7 @@ In kernels with CONFIG_RCU_FAST_NO_HZ, even more information is
 printed:
 
 	INFO: rcu_preempt detected stall on CPU
-	0: (64628 ticks this GP) idle=dd5/3fffffffffffffff/0 drain=0 . timer=-1
+	0: (64628 ticks this GP) idle=dd5/3fffffffffffffff/0 drain=0 . timer not pending
 	   (t=65000 jiffies)
 
 The "(64628 ticks this GP)" indicates that this CPU has taken more
@@ -116,13 +116,13 @@ number between the two "/"s is the value of the nesting, which will
 be a small positive number if in the idle loop and a very large positive
 number (as shown above) otherwise.
 
-For CONFIG_RCU_FAST_NO_HZ kernels, the "drain=0" indicates that the
-CPU is not in the process of trying to force itself into dyntick-idle
-state, the "." indicates that the CPU has not given up forcing RCU
-into dyntick-idle mode (it would be "H" otherwise), and the "timer=-1"
-indicates that the CPU has not recented forced RCU into dyntick-idle
-mode (it would otherwise indicate the number of microseconds remaining
-in this forced state).
+For CONFIG_RCU_FAST_NO_HZ kernels, the "drain=0" indicates that the CPU is
+not in the process of trying to force itself into dyntick-idle state, the
+"." indicates that the CPU has not given up forcing RCU into dyntick-idle
+mode (it would be "H" otherwise), and the "timer not pending" indicates
+that the CPU has not recently forced RCU into dyntick-idle mode (it
+would otherwise indicate the number of microseconds remaining in this
+forced state).
 
 
 Multiple Warnings From One Stall
diff --git a/Documentation/RCU/trace.txt b/Documentation/RCU/trace.txt
index f6f15ce..672d190 100644
--- a/Documentation/RCU/trace.txt
+++ b/Documentation/RCU/trace.txt
@@ -333,23 +333,23 @@ o	Each element of the form "1/1 0:127 ^0" represents one struct
 The output of "cat rcu/rcu_pending" looks as follows:
 
 rcu_sched:
-  0 np=255892 qsp=53936 rpq=85 cbr=0 cng=14417 gpc=10033 gps=24320 nf=6445 nn=146741
-  1 np=261224 qsp=54638 rpq=33 cbr=0 cng=25723 gpc=16310 gps=2849 nf=5912 nn=155792
-  2 np=237496 qsp=49664 rpq=23 cbr=0 cng=2762 gpc=45478 gps=1762 nf=1201 nn=136629
-  3 np=236249 qsp=48766 rpq=98 cbr=0 cng=286 gpc=48049 gps=1218 nf=207 nn=137723
-  4 np=221310 qsp=46850 rpq=7 cbr=0 cng=26 gpc=43161 gps=4634 nf=3529 nn=123110
-  5 np=237332 qsp=48449 rpq=9 cbr=0 cng=54 gpc=47920 gps=3252 nf=201 nn=137456
-  6 np=219995 qsp=46718 rpq=12 cbr=0 cng=50 gpc=42098 gps=6093 nf=4202 nn=120834
-  7 np=249893 qsp=49390 rpq=42 cbr=0 cng=72 gpc=38400 gps=17102 nf=41 nn=144888
+  0 np=255892 qsp=53936 rpq=85 cbr=0 cng=14417 gpc=10033 gps=24320 nn=146741
+  1 np=261224 qsp=54638 rpq=33 cbr=0 cng=25723 gpc=16310 gps=2849 nn=155792
+  2 np=237496 qsp=49664 rpq=23 cbr=0 cng=2762 gpc=45478 gps=1762 nn=136629
+  3 np=236249 qsp=48766 rpq=98 cbr=0 cng=286 gpc=48049 gps=1218 nn=137723
+  4 np=221310 qsp=46850 rpq=7 cbr=0 cng=26 gpc=43161 gps=4634 nn=123110
+  5 np=237332 qsp=48449 rpq=9 cbr=0 cng=54 gpc=47920 gps=3252 nn=137456
+  6 np=219995 qsp=46718 rpq=12 cbr=0 cng=50 gpc=42098 gps=6093 nn=120834
+  7 np=249893 qsp=49390 rpq=42 cbr=0 cng=72 gpc=38400 gps=17102 nn=144888
 rcu_bh:
-  0 np=146741 qsp=1419 rpq=6 cbr=0 cng=6 gpc=0 gps=0 nf=2 nn=145314
-  1 np=155792 qsp=12597 rpq=3 cbr=0 cng=0 gpc=4 gps=8 nf=3 nn=143180
-  2 np=136629 qsp=18680 rpq=1 cbr=0 cng=0 gpc=7 gps=6 nf=0 nn=117936
-  3 np=137723 qsp=2843 rpq=0 cbr=0 cng=0 gpc=10 gps=7 nf=0 nn=134863
-  4 np=123110 qsp=12433 rpq=0 cbr=0 cng=0 gpc=4 gps=2 nf=0 nn=110671
-  5 np=137456 qsp=4210 rpq=1 cbr=0 cng=0 gpc=6 gps=5 nf=0 nn=133235
-  6 np=120834 qsp=9902 rpq=2 cbr=0 cng=0 gpc=6 gps=3 nf=2 nn=110921
-  7 np=144888 qsp=26336 rpq=0 cbr=0 cng=0 gpc=8 gps=2 nf=0 nn=118542
+  0 np=146741 qsp=1419 rpq=6 cbr=0 cng=6 gpc=0 gps=0 nn=145314
+  1 np=155792 qsp=12597 rpq=3 cbr=0 cng=0 gpc=4 gps=8 nn=143180
+  2 np=136629 qsp=18680 rpq=1 cbr=0 cng=0 gpc=7 gps=6 nn=117936
+  3 np=137723 qsp=2843 rpq=0 cbr=0 cng=0 gpc=10 gps=7 nn=134863
+  4 np=123110 qsp=12433 rpq=0 cbr=0 cng=0 gpc=4 gps=2 nn=110671
+  5 np=137456 qsp=4210 rpq=1 cbr=0 cng=0 gpc=6 gps=5 nn=133235
+  6 np=120834 qsp=9902 rpq=2 cbr=0 cng=0 gpc=6 gps=3 nn=110921
+  7 np=144888 qsp=26336 rpq=0 cbr=0 cng=0 gpc=8 gps=2 nn=118542
 
 As always, this is once again split into "rcu_sched" and "rcu_bh"
 portions, with CONFIG_TREE_PREEMPT_RCU kernels having an additional
@@ -377,17 +377,6 @@ o	"gpc" is the number of times that an old grace period had
 o	"gps" is the number of times that a new grace period had started,
 	but this CPU was not yet aware of it.
 
-o	"nf" is the number of times that this CPU suspected that the
-	current grace period had run for too long, and thus needed to
-	be forced.
-
-	Please note that "forcing" consists of sending resched IPIs
-	to holdout CPUs.  If that CPU really still is in an old RCU
-	read-side critical section, then we really do have to wait for it.
-	The assumption behing "forcing" is that the CPU is not still in
-	an old RCU read-side critical section, but has not yet responded
-	for some other reason.
-
 o	"nn" is the number of times that this CPU needed nothing.  Alert
 	readers will note that the rcu "nn" number for a given CPU very
 	closely matches the rcu_bh "np" number for that same CPU.  This
diff --git a/Documentation/RCU/whatisRCU.txt b/Documentation/RCU/whatisRCU.txt
index 69ee188..bf0f6de 100644
--- a/Documentation/RCU/whatisRCU.txt
+++ b/Documentation/RCU/whatisRCU.txt
@@ -873,7 +873,7 @@ d.	Do you need to treat NMI handlers, hardirq handlers,
 	and code segments with preemption disabled (whether
 	via preempt_disable(), local_irq_save(), local_bh_disable(),
 	or some other mechanism) as if they were explicit RCU readers?
-	If so, you need RCU-sched.
+	If so, RCU-sched is the only choice that will work for you.
 
 e.	Do you need RCU grace periods to complete even in the face
 	of softirq monopolization of one or more of the CPUs?  For
@@ -884,7 +884,12 @@ f.	Is your workload too update-intensive for normal use of
 	RCU, but inappropriate for other synchronization mechanisms?
 	If so, consider SLAB_DESTROY_BY_RCU.  But please be careful!
 
-g.	Otherwise, use RCU.
+g.	Do you need read-side critical sections that are respected
+	even though they are in the middle of the idle loop, during
+	user-mode execution, or on an offlined CPU?  If so, SRCU is the
+	only choice that will work for you.
+
+h.	Otherwise, use RCU.
 
 Of course, this all assumes that you have determined that RCU is in fact
 the right tool for your job.
diff --git a/Documentation/accounting/getdelays.c b/Documentation/accounting/getdelays.c
index f6318f6..6f706ac 100644
--- a/Documentation/accounting/getdelays.c
+++ b/Documentation/accounting/getdelays.c
@@ -98,10 +98,9 @@ static int create_nl_socket(int protocol)
 	if (rcvbufsz)
 		if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF,
 				&rcvbufsz, sizeof(rcvbufsz)) < 0) {
-			fprintf(stderr, "Unable to set socket rcv buf size "
-					"to %d\n",
+			fprintf(stderr, "Unable to set socket rcv buf size to %d\n",
 				rcvbufsz);
-			return -1;
+			goto error;
 		}
 
 	memset(&local, 0, sizeof(local));
diff --git a/Documentation/aoe/aoe.txt b/Documentation/aoe/aoe.txt
index 5f5aa16..b3e4756 100644
--- a/Documentation/aoe/aoe.txt
+++ b/Documentation/aoe/aoe.txt
@@ -1,8 +1,11 @@
-The EtherDrive (R) HOWTO for users of 2.6 kernels is found at ...
+The EtherDrive (R) HOWTO for 2.6 and 3.x kernels is found at ...
 
-  http://www.coraid.com/SUPPORT/EtherDrive-HBA  
+  http://support.coraid.com/support/linux/EtherDrive-2.6-HOWTO.html
 
-  It has many tips and hints!
+It has many tips and hints!  Please see, especially, recommended
+tunings for virtual memory:
+
+  http://support.coraid.com/support/linux/EtherDrive-2.6-HOWTO-5.html#ss5.19
 
 The aoetools are userland programs that are designed to work with this
 driver.  The aoetools are on sourceforge.
diff --git a/Documentation/arm/Marvell/README b/Documentation/arm/Marvell/README
new file mode 100644
index 0000000..8f08a86
--- /dev/null
+++ b/Documentation/arm/Marvell/README
@@ -0,0 +1,232 @@
+ARM Marvell SoCs
+================
+
+This document lists all the ARM Marvell SoCs that are currently
+supported in mainline by the Linux kernel. As the Marvell families of
+SoCs are large and complex, it is hard to understand where the support
+for a particular SoC is available in the Linux kernel. This document
+tries to help in understanding where those SoCs are supported, and to
+match them with their corresponding public datasheet, when available.
+
+Orion family
+------------
+
+  Flavors:
+        88F5082
+        88F5181
+        88F5181L
+        88F5182
+               Datasheet               : http://www.embeddedarm.com/documentation/third-party/MV88F5182-datasheet.pdf
+               Programmer's User Guide : http://www.embeddedarm.com/documentation/third-party/MV88F5182-opensource-manual.pdf
+               User Manual             : http://www.embeddedarm.com/documentation/third-party/MV88F5182-usermanual.pdf
+        88F5281
+               Datasheet               : http://www.ocmodshop.com/images/reviews/networking/qnap_ts409u/marvel_88f5281_data_sheet.pdf
+        88F6183
+  Core: Feroceon ARMv5 compatible
+  Linux kernel mach directory: arch/arm/mach-orion5x
+  Linux kernel plat directory: arch/arm/plat-orion
+
+Kirkwood family
+---------------
+
+  Flavors:
+        88F6282 a.k.a Armada 300
+                Product Brief  : http://www.marvell.com/embedded-processors/armada-300/assets/armada_310.pdf
+        88F6283 a.k.a Armada 310
+                Product Brief  : http://www.marvell.com/embedded-processors/armada-300/assets/armada_310.pdf
+        88F6190
+                Product Brief  : http://www.marvell.com/embedded-processors/kirkwood/assets/88F6190-003_WEB.pdf
+                Hardware Spec  : http://www.marvell.com/embedded-processors/kirkwood/assets/HW_88F619x_OpenSource.pdf
+                Functional Spec: http://www.marvell.com/embedded-processors/kirkwood/assets/FS_88F6180_9x_6281_OpenSource.pdf
+        88F6192
+                Product Brief  : http://www.marvell.com/embedded-processors/kirkwood/assets/88F6192-003_ver1.pdf
+                Hardware Spec  : http://www.marvell.com/embedded-processors/kirkwood/assets/HW_88F619x_OpenSource.pdf
+                Functional Spec: http://www.marvell.com/embedded-processors/kirkwood/assets/FS_88F6180_9x_6281_OpenSource.pdf
+        88F6182
+        88F6180
+                Product Brief  : http://www.marvell.com/embedded-processors/kirkwood/assets/88F6180-003_ver1.pdf
+                Hardware Spec  : http://www.marvell.com/embedded-processors/kirkwood/assets/HW_88F6180_OpenSource.pdf
+                Functional Spec: http://www.marvell.com/embedded-processors/kirkwood/assets/FS_88F6180_9x_6281_OpenSource.pdf
+        88F6281
+                Product Brief  : http://www.marvell.com/embedded-processors/kirkwood/assets/88F6281-004_ver1.pdf
+                Hardware Spec  : http://www.marvell.com/embedded-processors/kirkwood/assets/HW_88F6281_OpenSource.pdf
+                Functional Spec: http://www.marvell.com/embedded-processors/kirkwood/assets/FS_88F6180_9x_6281_OpenSource.pdf
+  Homepage: http://www.marvell.com/embedded-processors/kirkwood/
+  Core: Feroceon ARMv5 compatible
+  Linux kernel mach directory: arch/arm/mach-kirkwood
+  Linux kernel plat directory: arch/arm/plat-orion
+
+Discovery family
+----------------
+
+  Flavors:
+        MV78100
+                Product Brief  : http://www.marvell.com/embedded-processors/discovery-innovation/assets/MV78100-003_WEB.pdf
+                Hardware Spec  : http://www.marvell.com/embedded-processors/discovery-innovation/assets/HW_MV78100_OpenSource.pdf
+                Functional Spec: http://www.marvell.com/embedded-processors/discovery-innovation/assets/FS_MV76100_78100_78200_OpenSource.pdf
+        MV78200
+                Product Brief  : http://www.marvell.com/embedded-processors/discovery-innovation/assets/MV78200-002_WEB.pdf
+                Hardware Spec  : http://www.marvell.com/embedded-processors/discovery-innovation/assets/HW_MV78200_OpenSource.pdf
+                Functional Spec: http://www.marvell.com/embedded-processors/discovery-innovation/assets/FS_MV76100_78100_78200_OpenSource.pdf
+        MV76100
+                Not supported by the Linux kernel.
+
+  Core: Feroceon ARMv5 compatible
+
+  Linux kernel mach directory: arch/arm/mach-mv78xx0
+  Linux kernel plat directory: arch/arm/plat-orion
+
+EBU Armada family
+-----------------
+
+  Armada 370 Flavors:
+        88F6710
+        88F6707
+        88F6W11
+
+  Armada XP Flavors:
+        MV78230
+        MV78260
+        MV78460
+
+  Product Brief: http://www.marvell.com/embedded-processors/armada-xp/assets/Marvell-ArmadaXP-SoC-product%20brief.pdf
+  No public datasheet available.
+
+  Core: Sheeva ARMv7 compatible
+
+  Linux kernel mach directory: arch/arm/mach-mvebu
+  Linux kernel plat directory: none
+
+Avanta family
+-------------
+
+  Flavors:
+       88F6510
+       88F6530P
+       88F6550
+       88F6560
+  Homepage     : http://www.marvell.com/broadband/
+  Product Brief: http://www.marvell.com/broadband/assets/Marvell_Avanta_88F6510_305_060-001_product_brief.pdf
+  No public datasheet available.
+
+  Core: ARMv5 compatible
+
+  Linux kernel mach directory: no code in mainline yet, planned for the future
+  Linux kernel plat directory: no code in mainline yet, planned for the future
+
+Dove family (application processor)
+-----------------------------------
+
+  Flavors:
+        88AP510 a.k.a Armada 510
+                Product Brief   : http://www.marvell.com/application-processors/armada-500/assets/Marvell_Armada510_SoC.pdf
+                Hardware Spec   : http://www.marvell.com/application-processors/armada-500/assets/Armada-510-Hardware-Spec.pdf
+                Functional Spec : http://www.marvell.com/application-processors/armada-500/assets/Armada-510-Functional-Spec.pdf
+  Homepage: http://www.marvell.com/application-processors/armada-500/
+  Core: ARMv7 compatible
+  Directory: arch/arm/mach-dove
+
+PXA 2xx/3xx/93x/95x family
+--------------------------
+
+  Flavors:
+        PXA21x, PXA25x, PXA26x
+             Application processor only
+             Core: ARMv5 XScale core
+        PXA270, PXA271, PXA272
+             Product Brief         : http://www.marvell.com/application-processors/pxa-family/assets/pxa_27x_pb.pdf
+             Design guide          : http://www.marvell.com/application-processors/pxa-family/assets/pxa_27x_design_guide.pdf
+             Developers manual     : http://www.marvell.com/application-processors/pxa-family/assets/pxa_27x_dev_man.pdf
+             Specification         : http://www.marvell.com/application-processors/pxa-family/assets/pxa_27x_emts.pdf
+             Specification update  : http://www.marvell.com/application-processors/pxa-family/assets/pxa_27x_spec_update.pdf
+             Application processor only
+             Core: ARMv5 XScale core
+        PXA300, PXA310, PXA320
+             PXA 300 Product Brief : http://www.marvell.com/application-processors/pxa-family/assets/PXA300_PB_R4.pdf
+             PXA 310 Product Brief : http://www.marvell.com/application-processors/pxa-family/assets/PXA310_PB_R4.pdf
+             PXA 320 Product Brief : http://www.marvell.com/application-processors/pxa-family/assets/PXA320_PB_R4.pdf
+             Design guide          : http://www.marvell.com/application-processors/pxa-family/assets/PXA3xx_Design_Guide.pdf
+             Developers manual     : http://www.marvell.com/application-processors/pxa-family/assets/PXA3xx_Developers_Manual.zip
+             Specifications        : http://www.marvell.com/application-processors/pxa-family/assets/PXA3xx_EMTS.pdf
+             Specification Update  : http://www.marvell.com/application-processors/pxa-family/assets/PXA3xx_Spec_Update.zip
+             Reference Manual      : http://www.marvell.com/application-processors/pxa-family/assets/PXA3xx_TavorP_BootROM_Ref_Manual.pdf
+             Application processor only
+             Core: ARMv5 XScale core
+        PXA930, PXA935
+             Application processor with Communication processor
+             Core: ARMv5 XScale core
+        PXA955
+             Application processor with Communication processor
+             Core: ARMv7 compatible Sheeva PJ4 core
+
+   Comments:
+
+    * This line of SoCs originates from the XScale family developed by
+      Intel and acquired by Marvell in ~2006. The PXA21x, PXA25x,
+      PXA26x, PXA27x, PXA3xx and PXA93x were developed by Intel, while
+      the later PXA95x were developed by Marvell.
+
+    * Due to their XScale origin, these SoCs have virtually nothing in
+      common with the other (Kirkwood, Dove, etc.) families of Marvell
+      SoCs, except with the MMP/MMP2 family of SoCs.
+
+   Linux kernel mach directory: arch/arm/mach-pxa
+   Linux kernel plat directory: arch/arm/plat-pxa
+
+MMP/MMP2 family (communication processor)
+-----------------------------------------
+
+   Flavors:
+        PXA168, a.k.a Armada 168
+             Homepage             : http://www.marvell.com/application-processors/armada-100/armada-168.jsp
+             Product brief        : http://www.marvell.com/application-processors/armada-100/assets/pxa_168_pb.pdf
+             Hardware manual      : http://www.marvell.com/application-processors/armada-100/assets/armada_16x_datasheet.pdf
+             Software manual      : http://www.marvell.com/application-processors/armada-100/assets/armada_16x_software_manual.pdf
+             Specification update : http://www.marvell.com/application-processors/armada-100/assets/ARMADA16x_Spec_update.pdf
+             Boot ROM manual      : http://www.marvell.com/application-processors/armada-100/assets/armada_16x_ref_manual.pdf
+             App node package     : http://www.marvell.com/application-processors/armada-100/assets/armada_16x_app_note_package.pdf
+             Application processor only
+             Core: ARMv5 compatible Marvell PJ1 (Mohawk)
+        PXA910
+             Homepage             : http://www.marvell.com/communication-processors/pxa910/
+             Product Brief        : http://www.marvell.com/communication-processors/pxa910/assets/Marvell_PXA910_Platform-001_PB_final.pdf
+             Application processor with Communication processor
+             Core: ARMv5 compatible Marvell PJ1 (Mohawk)
+        MMP2, a.k.a Armada 610
+             Product Brief        : http://www.marvell.com/application-processors/armada-600/assets/armada610_pb.pdf
+             Application processor only
+             Core: ARMv7 compatible Sheeva PJ4 core
+
+   Comments:
+
+    * This line of SoCs originates from the XScale family developed by
+      Intel and acquired by Marvell in ~2006. All the processors of
+      this MMP/MMP2 family were developed by Marvell.
+
+    * Due to their XScale origin, these SoCs have virtually nothing in
+      common with the other (Kirkwood, Dove, etc.) families of Marvell
+      SoCs, except with the PXA family of SoCs listed above.
+
+   Linux kernel mach directory: arch/arm/mach-mmp
+   Linux kernel plat directory: arch/arm/plat-pxa
+
+Long-term plans
+---------------
+
+ * Unify the mach-dove/, mach-mv78xx0/, mach-orion5x/ and
+   mach-kirkwood/ into the mach-mvebu/ to support all SoCs from the
+   Marvell EBU (Engineering Business Unit) in a single mach-<foo>
+   directory. The plat-orion/ would therefore disappear.
+
+ * Unify the mach-mmp/ and mach-pxa/ into the same mach-pxa
+   directory. The plat-pxa/ would therefore disappear.
+
+Credits
+-------
+
+ Maen Suleiman <maen@marvell.com>
+ Lior Amsalem <alior@marvell.com>
+ Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ Andrew Lunn <andrew@lunn.ch>
+ Nicolas Pitre <nico@fluxnic.net>
+ Eric Miao <eric.y.miao@gmail.com>
diff --git a/Documentation/arm/Samsung-S3C24XX/GPIO.txt b/Documentation/arm/Samsung-S3C24XX/GPIO.txt
index 816d607..8b46c79 100644
--- a/Documentation/arm/Samsung-S3C24XX/GPIO.txt
+++ b/Documentation/arm/Samsung-S3C24XX/GPIO.txt
@@ -1,4 +1,4 @@
-			S3C2410 GPIO Control
+			S3C24XX GPIO Control
 			====================
 
 Introduction
@@ -12,7 +12,7 @@ Introduction
   of the s3c2410 GPIO system, please read the Samsung provided
   data-sheet/users manual to find out the complete list.
 
-  See Documentation/arm/Samsung/GPIO.txt for the core implemetation.
+  See Documentation/arm/Samsung/GPIO.txt for the core implementation.
 
 
 GPIOLIB
@@ -41,8 +41,8 @@ GPIOLIB
 GPIOLIB conversion
 ------------------
 
-If you need to convert your board or driver to use gpiolib from the exiting
-s3c2410 api, then here are some notes on the process.
+If you need to convert your board or driver to use gpiolib from the phased
+out s3c2410 API, then here are some notes on the process.
 
 1) If your board is exclusively using an GPIO, say to control peripheral
    power, then it will require to claim the gpio with gpio_request() before
@@ -55,7 +55,7 @@ s3c2410 api, then here are some notes on the process.
    as they have the same arguments, and can either take the pin specific
    values, or the more generic special-function-number arguments.
 
-3) s3c2410_gpio_pullup() changs have the problem that whilst the 
+3) s3c2410_gpio_pullup() changes have the problem that whilst the
    s3c2410_gpio_pullup(x, 1) can be easily translated to the
    s3c_gpio_setpull(x, S3C_GPIO_PULL_NONE), the s3c2410_gpio_pullup(x, 0)
    are not so easy.
@@ -74,7 +74,7 @@ s3c2410 api, then here are some notes on the process.
    when using gpio_get_value() on an output pin (s3c2410_gpio_getpin
    would return the value the pin is supposed to be outputting).
 
-6) s3c2410_gpio_getirq() should be directly replacable with the
+6) s3c2410_gpio_getirq() should be directly replaceable with the
    gpio_to_irq() call.
 
 The s3c2410_gpio and gpio_ calls have always operated on the same gpio
@@ -105,7 +105,7 @@ PIN Numbers
 -----------
 
   Each pin has an unique number associated with it in regs-gpio.h,
-  eg S3C2410_GPA(0) or S3C2410_GPF(1). These defines are used to tell
+  e.g. S3C2410_GPA(0) or S3C2410_GPF(1). These defines are used to tell
   the GPIO functions which pin is to be used.
 
   With the conversion to gpiolib, there is no longer a direct conversion
@@ -120,31 +120,27 @@ Configuring a pin
   The following function allows the configuration of a given pin to
   be changed.
 
-    void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function);
+    void s3c_gpio_cfgpin(unsigned int pin, unsigned int function);
 
-  Eg:
+  e.g.:
 
-     s3c2410_gpio_cfgpin(S3C2410_GPA(0), S3C2410_GPA0_ADDR0);
-     s3c2410_gpio_cfgpin(S3C2410_GPE(8), S3C2410_GPE8_SDDAT1);
+     s3c_gpio_cfgpin(S3C2410_GPA(0), S3C_GPIO_SFN(1));
+     s3c_gpio_cfgpin(S3C2410_GPE(8), S3C_GPIO_SFN(2));
 
    which would turn GPA(0) into the lowest Address line A0, and set
    GPE(8) to be connected to the SDIO/MMC controller's SDDAT1 line.
 
-   The s3c_gpio_cfgpin() call is a functional replacement for this call.
-
 
 Reading the current configuration
 ---------------------------------
 
-  The current configuration of a pin can be read by using:
+  The current configuration of a pin can be read by using standard
+  gpiolib function:
 
-  s3c2410_gpio_getcfg(unsigned int pin);
+  s3c_gpio_getcfg(unsigned int pin);
 
   The return value will be from the same set of values which can be
-  passed to s3c2410_gpio_cfgpin().
-
-  The s3c_gpio_getcfg() call should be a functional replacement for
-  this call.
+  passed to s3c_gpio_cfgpin().
 
 
 Configuring a pull-up resistor
@@ -154,61 +150,33 @@ Configuring a pull-up resistor
   pull-up resistors enabled. This can be configured by the following
   function:
 
-    void s3c2410_gpio_pullup(unsigned int pin, unsigned int to);
-
-  Where the to value is zero to set the pull-up off, and 1 to enable
-  the specified pull-up. Any other values are currently undefined.
-
-  The s3c_gpio_setpull() offers similar functionality, but with the
-  ability to encode whether the pull is up or down. Currently there
-  is no 'just on' state, so up or down must be selected.
-
-
-Getting the state of a PIN
---------------------------
-
-  The state of a pin can be read by using the function:
-
-    unsigned int s3c2410_gpio_getpin(unsigned int pin);
+    void s3c_gpio_setpull(unsigned int pin, unsigned int to);
 
-  This will return either zero or non-zero. Do not count on this
-  function returning 1 if the pin is set.
+  Where the to value is S3C_GPIO_PULL_NONE to set the pull-up off,
+  and S3C_GPIO_PULL_UP to enable the specified pull-up. Any other
+  values are currently undefined.
 
-  This call is now implemented by the relevant gpiolib calls, convert
-  your board or driver to use gpiolib.
-
-
-Setting the state of a PIN
---------------------------
-
-  The value an pin is outputing can be modified by using the following:
 
-    void s3c2410_gpio_setpin(unsigned int pin, unsigned int to);
+Getting and setting the state of a PIN
+--------------------------------------
 
-  Which sets the given pin to the value. Use 0 to write 0, and 1 to
-  set the output to 1.
-
-  This call is now implemented by the relevant gpiolib calls, convert
+  These calls are now implemented by the relevant gpiolib calls, convert
   your board or driver to use gpiolib.
 
 
 Getting the IRQ number associated with a PIN
 --------------------------------------------
 
-  The following function can map the given pin number to an IRQ
+  A standard gpiolib function can map the given pin number to an IRQ
   number to pass to the IRQ system.
 
-   int s3c2410_gpio_getirq(unsigned int pin);
+   int gpio_to_irq(unsigned int pin);
 
   Note, not all pins have an IRQ.
 
-  This call is now implemented by the relevant gpiolib calls, convert
-  your board or driver to use gpiolib.
-
 
-Authour
+Author
 -------
 
-
 Ben Dooks, 03 October 2004
 Copyright 2004 Ben Dooks, Simtec Electronics
diff --git a/Documentation/arm/Samsung/GPIO.txt b/Documentation/arm/Samsung/GPIO.txt
index 513f256..795adfd 100644
--- a/Documentation/arm/Samsung/GPIO.txt
+++ b/Documentation/arm/Samsung/GPIO.txt
@@ -5,14 +5,14 @@ Introduction
 ------------
 
 This outlines the Samsung GPIO implementation and the architecture
-specific calls provided alongisde the drivers/gpio core.
+specific calls provided alongside the drivers/gpio core.
 
 
 S3C24XX (Legacy)
 ----------------
 
 See Documentation/arm/Samsung-S3C24XX/GPIO.txt for more information
-about these devices. Their implementation is being brought into line
+about these devices. Their implementation has been brought into line
 with the core samsung implementation described in this document.
 
 
@@ -29,7 +29,7 @@ GPIO numbering is synchronised between the Samsung and gpiolib system.
 PIN configuration
 -----------------
 
-Pin configuration is specific to the Samsung architecutre, with each SoC
+Pin configuration is specific to the Samsung architecture, with each SoC
 registering the necessary information for the core gpio configuration
 implementation to configure pins as necessary.
 
@@ -38,5 +38,3 @@ driver or machine to change gpio configuration.
 
 See arch/arm/plat-samsung/include/plat/gpio-cfg.h for more information
 on these functions.
-
-
diff --git a/Documentation/arm/memory.txt b/Documentation/arm/memory.txt
index 208a2d4..4bfb9ff 100644
--- a/Documentation/arm/memory.txt
+++ b/Documentation/arm/memory.txt
@@ -51,6 +51,9 @@ ffc00000	ffefffff	DMA memory mapping region.  Memory returned
 ff000000	ffbfffff	Reserved for future expansion of DMA
 				mapping region.
 
+fee00000	feffffff	Mapping of PCI I/O space. This is a static
+				mapping within the vmalloc space.
+
 VMALLOC_START	VMALLOC_END-1	vmalloc() / ioremap() space.
 				Memory returned by vmalloc/ioremap will
 				be dynamically placed in this region.
diff --git a/Documentation/arm64/booting.txt b/Documentation/arm64/booting.txt
new file mode 100644
index 0000000..9c4d388
--- /dev/null
+++ b/Documentation/arm64/booting.txt
@@ -0,0 +1,152 @@
+			Booting AArch64 Linux
+			=====================
+
+Author: Will Deacon <will.deacon@arm.com>
+Date  : 07 September 2012
+
+This document is based on the ARM booting document by Russell King and
+is relevant to all public releases of the AArch64 Linux kernel.
+
+The AArch64 exception model is made up of a number of exception levels
+(EL0 - EL3), with EL0 and EL1 having a secure and a non-secure
+counterpart.  EL2 is the hypervisor level and exists only in non-secure
+mode. EL3 is the highest priority level and exists only in secure mode.
+
+For the purposes of this document, we will use the term `boot loader'
+simply to define all software that executes on the CPU(s) before control
+is passed to the Linux kernel.  This may include secure monitor and
+hypervisor code, or it may just be a handful of instructions for
+preparing a minimal boot environment.
+
+Essentially, the boot loader should provide (as a minimum) the
+following:
+
+1. Setup and initialise the RAM
+2. Setup the device tree
+3. Decompress the kernel image
+4. Call the kernel image
+
+
+1. Setup and initialise RAM
+---------------------------
+
+Requirement: MANDATORY
+
+The boot loader is expected to find and initialise all RAM that the
+kernel will use for volatile data storage in the system.  It performs
+this in a machine dependent manner.  (It may use internal algorithms
+to automatically locate and size all RAM, or it may use knowledge of
+the RAM in the machine, or any other method the boot loader designer
+sees fit.)
+
+
+2. Setup the device tree
+-------------------------
+
+Requirement: MANDATORY
+
+The device tree blob (dtb) must be no bigger than 2 megabytes in size
+and placed at a 2-megabyte boundary within the first 512 megabytes from
+the start of the kernel image. This is to allow the kernel to map the
+blob using a single section mapping in the initial page tables.
+
+
+3. Decompress the kernel image
+------------------------------
+
+Requirement: OPTIONAL
+
+The AArch64 kernel does not currently provide a decompressor and
+therefore requires decompression (gzip etc.) to be performed by the boot
+loader if a compressed Image target (e.g. Image.gz) is used.  For
+bootloaders that do not implement this requirement, the uncompressed
+Image target is available instead.
+
+
+4. Call the kernel image
+------------------------
+
+Requirement: MANDATORY
+
+The decompressed kernel image contains a 32-byte header as follows:
+
+  u32 magic	= 0x14000008;	/* branch to stext, little-endian */
+  u32 res0	= 0;		/* reserved */
+  u64 text_offset;		/* Image load offset */
+  u64 res1	= 0;		/* reserved */
+  u64 res2	= 0;		/* reserved */
+
+The image must be placed at the specified offset (currently 0x80000)
+from the start of the system RAM and called there. The start of the
+system RAM must be aligned to 2MB.
+
+Before jumping into the kernel, the following conditions must be met:
+
+- Quiesce all DMA capable devices so that memory does not get
+  corrupted by bogus network packets or disk data.  This will save
+  you many hours of debug.
+
+- Primary CPU general-purpose register settings
+  x0 = physical address of device tree blob (dtb) in system RAM.
+  x1 = 0 (reserved for future use)
+  x2 = 0 (reserved for future use)
+  x3 = 0 (reserved for future use)
+
+- CPU mode
+  All forms of interrupts must be masked in PSTATE.DAIF (Debug, SError,
+  IRQ and FIQ).
+  The CPU must be in either EL2 (RECOMMENDED in order to have access to
+  the virtualisation extensions) or non-secure EL1.
+
+- Caches, MMUs
+  The MMU must be off.
+  Instruction cache may be on or off.
+  Data cache must be off and invalidated.
+  External caches (if present) must be configured and disabled.
+
+- Architected timers
+  CNTFRQ must be programmed with the timer frequency.
+  If entering the kernel at EL1, CNTHCTL_EL2 must have EL1PCTEN (bit 0)
+  set where available.
+
+- Coherency
+  All CPUs to be booted by the kernel must be part of the same coherency
+  domain on entry to the kernel.  This may require IMPLEMENTATION DEFINED
+  initialisation to enable the receiving of maintenance operations on
+  each CPU.
+
+- System registers
+  All writable architected system registers at the exception level where
+  the kernel image will be entered must be initialised by software at a
+  higher exception level to prevent execution in an UNKNOWN state.
+
+The boot loader is expected to enter the kernel on each CPU in the
+following manner:
+
+- The primary CPU must jump directly to the first instruction of the
+  kernel image.  The device tree blob passed by this CPU must contain
+  for each CPU node:
+
+    1. An 'enable-method' property. Currently, the only supported value
+       for this field is the string "spin-table".
+
+    2. A 'cpu-release-addr' property identifying a 64-bit,
+       zero-initialised memory location.
+
+  It is expected that the bootloader will generate these device tree
+  properties and insert them into the blob prior to kernel entry.
+
+- Any secondary CPUs must spin outside of the kernel in a reserved area
+  of memory (communicated to the kernel by a /memreserve/ region in the
+  device tree) polling their cpu-release-addr location, which must be
+  contained in the reserved region.  A wfe instruction may be inserted
+  to reduce the overhead of the busy-loop and a sev will be issued by
+  the primary CPU.  When a read of the location pointed to by the
+  cpu-release-addr returns a non-zero value, the CPU must jump directly
+  to this value.
+
+- Secondary CPU general-purpose register settings
+  x0 = 0 (reserved for future use)
+  x1 = 0 (reserved for future use)
+  x2 = 0 (reserved for future use)
+  x3 = 0 (reserved for future use)
diff --git a/Documentation/arm64/memory.txt b/Documentation/arm64/memory.txt
new file mode 100644
index 0000000..dbbdcbb
--- /dev/null
+++ b/Documentation/arm64/memory.txt
@@ -0,0 +1,73 @@
+		     Memory Layout on AArch64 Linux
+		     ==============================
+
+Author: Catalin Marinas <catalin.marinas@arm.com>
+Date  : 20 February 2012
+
+This document describes the virtual memory layout used by the AArch64
+Linux kernel. The architecture allows up to 4 levels of translation
+tables with a 4KB page size and up to 3 levels with a 64KB page size.
+
+AArch64 Linux uses 3 levels of translation tables with the 4KB page
+configuration, allowing 39-bit (512GB) virtual addresses for both user
+and kernel. With 64KB pages, only 2 levels of translation tables are
+used but the memory layout is the same.
+
+User addresses have bits 63:39 set to 0 while the kernel addresses have
+the same bits set to 1. TTBRx selection is given by bit 63 of the
+virtual address. The swapper_pg_dir contains only kernel (global)
+mappings while the user pgd contains only user (non-global) mappings.
+The swapper_pgd_dir address is written to TTBR1 and never written to
+TTBR0.
+
+
+AArch64 Linux memory layout:
+
+Start			End			Size		Use
+-----------------------------------------------------------------------
+0000000000000000	0000007fffffffff	 512GB		user
+
+ffffff8000000000	ffffffbbfffcffff	~240GB		vmalloc
+
+ffffffbbfffd0000	ffffffbcfffdffff	  64KB		[guard page]
+
+ffffffbbfffe0000	ffffffbcfffeffff	  64KB		PCI I/O space
+
+ffffffbbffff0000	ffffffbcffffffff	  64KB		[guard page]
+
+ffffffbc00000000	ffffffbdffffffff	   8GB		vmemmap
+
+ffffffbe00000000	ffffffbffbffffff	  ~8GB		[guard, future vmmemap]
+
+ffffffbffc000000	ffffffbfffffffff	  64MB		modules
+
+ffffffc000000000	ffffffffffffffff	 256GB		memory
+
+
+Translation table lookup with 4KB pages:
+
++--------+--------+--------+--------+--------+--------+--------+--------+
+|63    56|55    48|47    40|39    32|31    24|23    16|15     8|7      0|
++--------+--------+--------+--------+--------+--------+--------+--------+
+ |                 |         |         |         |         |
+ |                 |         |         |         |         v
+ |                 |         |         |         |   [11:0]  in-page offset
+ |                 |         |         |         +-> [20:12] L3 index
+ |                 |         |         +-----------> [29:21] L2 index
+ |                 |         +---------------------> [38:30] L1 index
+ |                 +-------------------------------> [47:39] L0 index (not used)
+ +-------------------------------------------------> [63] TTBR0/1
+
+
+Translation table lookup with 64KB pages:
+
++--------+--------+--------+--------+--------+--------+--------+--------+
+|63    56|55    48|47    40|39    32|31    24|23    16|15     8|7      0|
++--------+--------+--------+--------+--------+--------+--------+--------+
+ |                 |    |               |              |
+ |                 |    |               |              v
+ |                 |    |               |            [15:0]  in-page offset
+ |                 |    |               +----------> [28:16] L3 index
+ |                 |    +--------------------------> [41:29] L2 index (only 38:29 used)
+ |                 +-------------------------------> [47:42] L1 index (not used)
+ +-------------------------------------------------> [63] TTBR0/1
diff --git a/Documentation/block/biodoc.txt b/Documentation/block/biodoc.txt
index e418dc0..8df5e8e 100644
--- a/Documentation/block/biodoc.txt
+++ b/Documentation/block/biodoc.txt
@@ -465,7 +465,6 @@ struct bio {
        bio_end_io_t	*bi_end_io;  /* bi_end_io (bio) */
        atomic_t		bi_cnt;	     /* pin count: free when it hits zero */
        void             *bi_private;
-       bio_destructor_t *bi_destructor; /* bi_destructor (bio) */
 };
 
 With this multipage bio design:
@@ -647,10 +646,6 @@ for a non-clone bio. There are the 6 pools setup for different size biovecs,
 so bio_alloc(gfp_mask, nr_iovecs) will allocate a vec_list of the
 given size from these slabs.
 
-The bi_destructor() routine takes into account the possibility of the bio
-having originated from a different source (see later discussions on
-n/w to block transfers and kvec_cb)
-
 The bio_get() routine may be used to hold an extra reference on a bio prior
 to i/o submission, if the bio fields are likely to be accessed after the
 i/o is issued (since the bio may otherwise get freed in case i/o completion
diff --git a/Documentation/cgroups/cgroups.txt b/Documentation/cgroups/cgroups.txt
index 4a0b64c..9e04196 100644
--- a/Documentation/cgroups/cgroups.txt
+++ b/Documentation/cgroups/cgroups.txt
@@ -29,7 +29,8 @@ CONTENTS:
   3.1 Overview
   3.2 Synchronization
   3.3 Subsystem API
-4. Questions
+4. Extended attributes usage
+5. Questions
 
 1. Control Groups
 =================
@@ -62,9 +63,9 @@ an instance of the cgroup virtual filesystem associated with it.
 At any one time there may be multiple active hierarchies of task
 cgroups. Each hierarchy is a partition of all tasks in the system.
 
-User level code may create and destroy cgroups by name in an
+User-level code may create and destroy cgroups by name in an
 instance of the cgroup virtual file system, specify and query to
-which cgroup a task is assigned, and list the task pids assigned to
+which cgroup a task is assigned, and list the task PIDs assigned to
 a cgroup. Those creations and assignments only affect the hierarchy
 associated with that instance of the cgroup file system.
 
@@ -72,7 +73,7 @@ On their own, the only use for cgroups is for simple job
 tracking. The intention is that other subsystems hook into the generic
 cgroup support to provide new attributes for cgroups, such as
 accounting/limiting the resources which processes in a cgroup can
-access. For example, cpusets (see Documentation/cgroups/cpusets.txt) allows
+access. For example, cpusets (see Documentation/cgroups/cpusets.txt) allow
 you to associate a set of CPUs and a set of memory nodes with the
 tasks in each cgroup.
 
@@ -80,11 +81,11 @@ tasks in each cgroup.
 ----------------------------
 
 There are multiple efforts to provide process aggregations in the
-Linux kernel, mainly for resource tracking purposes. Such efforts
+Linux kernel, mainly for resource-tracking purposes. Such efforts
 include cpusets, CKRM/ResGroups, UserBeanCounters, and virtual server
 namespaces. These all require the basic notion of a
 grouping/partitioning of processes, with newly forked processes ending
-in the same group (cgroup) as their parent process.
+up in the same group (cgroup) as their parent process.
 
 The kernel cgroup patch provides the minimum essential kernel
 mechanisms required to efficiently implement such groups. It has
@@ -127,14 +128,14 @@ following lines:
                                / \
                Professors (15%)  students (5%)
 
-Browsers like Firefox/Lynx go into the WWW network class, while (k)nfsd go
-into NFS network class.
+Browsers like Firefox/Lynx go into the WWW network class, while (k)nfsd goes
+into the NFS network class.
 
 At the same time Firefox/Lynx will share an appropriate CPU/Memory class
 depending on who launched it (prof/student).
 
 With the ability to classify tasks differently for different resources
-(by putting those resource subsystems in different hierarchies) then
+(by putting those resource subsystems in different hierarchies),
 the admin can easily set up a script which receives exec notifications
 and depending on who is launching the browser he can
 
@@ -145,19 +146,19 @@ a separate cgroup for every browser launched and associate it with
 appropriate network and other resource class.  This may lead to
 proliferation of such cgroups.
 
-Also lets say that the administrator would like to give enhanced network
+Also let's say that the administrator would like to give enhanced network
 access temporarily to a student's browser (since it is night and the user
-wants to do online gaming :))  OR give one of the students simulation
-apps enhanced CPU power,
+wants to do online gaming :))  OR give one of the student's simulation
+apps enhanced CPU power.
 
-With ability to write pids directly to resource classes, it's just a
-matter of :
+With ability to write PIDs directly to resource classes, it's just a
+matter of:
 
        # echo pid > /sys/fs/cgroup/network/<new_class>/tasks
        (after some time)
        # echo pid > /sys/fs/cgroup/network/<orig_class>/tasks
 
-Without this ability, he would have to split the cgroup into
+Without this ability, the administrator would have to split the cgroup into
 multiple separate ones and then associate the new cgroups with the
 new resource classes.
 
@@ -184,20 +185,20 @@ Control Groups extends the kernel as follows:
    field of each task_struct using the css_set, anchored at
    css_set->tasks.
 
- - A cgroup hierarchy filesystem can be mounted  for browsing and
+ - A cgroup hierarchy filesystem can be mounted for browsing and
    manipulation from user space.
 
- - You can list all the tasks (by pid) attached to any cgroup.
+ - You can list all the tasks (by PID) attached to any cgroup.
 
 The implementation of cgroups requires a few, simple hooks
-into the rest of the kernel, none in performance critical paths:
+into the rest of the kernel, none in performance-critical paths:
 
  - in init/main.c, to initialize the root cgroups and initial
    css_set at system boot.
 
  - in fork and exit, to attach and detach a task from its css_set.
 
-In addition a new file system, of type "cgroup" may be mounted, to
+In addition, a new file system of type "cgroup" may be mounted, to
 enable browsing and modifying the cgroups presently known to the
 kernel.  When mounting a cgroup hierarchy, you may specify a
 comma-separated list of subsystems to mount as the filesystem mount
@@ -230,13 +231,13 @@ as the path relative to the root of the cgroup file system.
 Each cgroup is represented by a directory in the cgroup file system
 containing the following files describing that cgroup:
 
- - tasks: list of tasks (by pid) attached to that cgroup.  This list
-   is not guaranteed to be sorted.  Writing a thread id into this file
+ - tasks: list of tasks (by PID) attached to that cgroup.  This list
+   is not guaranteed to be sorted.  Writing a thread ID into this file
    moves the thread into this cgroup.
- - cgroup.procs: list of tgids in the cgroup.  This list is not
-   guaranteed to be sorted or free of duplicate tgids, and userspace
+ - cgroup.procs: list of thread group IDs in the cgroup.  This list is
+   not guaranteed to be sorted or free of duplicate TGIDs, and userspace
    should sort/uniquify the list if this property is required.
-   Writing a thread group id into this file moves all threads in that
+   Writing a thread group ID into this file moves all threads in that
    group into this cgroup.
  - notify_on_release flag: run the release agent on exit?
  - release_agent: the path to use for release notifications (this file
@@ -261,7 +262,7 @@ cgroup file system directories.
 
 When a task is moved from one cgroup to another, it gets a new
 css_set pointer - if there's an already existing css_set with the
-desired collection of cgroups then that group is reused, else a new
+desired collection of cgroups then that group is reused, otherwise a new
 css_set is allocated. The appropriate existing css_set is located by
 looking into a hash table.
 
@@ -292,7 +293,7 @@ file system) of the abandoned cgroup.  This enables automatic
 removal of abandoned cgroups.  The default value of
 notify_on_release in the root cgroup at system boot is disabled
 (0).  The default value of other cgroups at creation is the current
-value of their parents notify_on_release setting. The default value of
+value of their parents' notify_on_release settings. The default value of
 a cgroup hierarchy's release_agent path is empty.
 
 1.5 What does clone_children do ?
@@ -316,7 +317,7 @@ the "cpuset" cgroup subsystem, the steps are something like:
  4) Create the new cgroup by doing mkdir's and write's (or echo's) in
     the /sys/fs/cgroup virtual file system.
  5) Start a task that will be the "founding father" of the new job.
- 6) Attach that task to the new cgroup by writing its pid to the
+ 6) Attach that task to the new cgroup by writing its PID to the
     /sys/fs/cgroup/cpuset/tasks file for that cgroup.
  7) fork, exec or clone the job tasks from this founding father task.
 
@@ -344,7 +345,7 @@ and then start a subshell 'sh' in that cgroup:
 2.1 Basic Usage
 ---------------
 
-Creating, modifying, using the cgroups can be done through the cgroup
+Creating, modifying, using cgroups can be done through the cgroup
 virtual filesystem.
 
 To mount a cgroup hierarchy with all available subsystems, type:
@@ -441,7 +442,7 @@ You can attach the current shell task by echoing 0:
 # echo 0 > tasks
 
 You can use the cgroup.procs file instead of the tasks file to move all
-threads in a threadgroup at once. Echoing the pid of any task in a
+threads in a threadgroup at once. Echoing the PID of any task in a
 threadgroup to cgroup.procs causes all tasks in that threadgroup to be
 be attached to the cgroup. Writing 0 to cgroup.procs moves all tasks
 in the writing task's threadgroup.
@@ -479,7 +480,7 @@ in /proc/mounts and /proc/<pid>/cgroups.
 There is mechanism which allows to get notifications about changing
 status of a cgroup.
 
-To register new notification handler you need:
+To register a new notification handler you need to:
  - create a file descriptor for event notification using eventfd(2);
  - open a control file to be monitored (e.g. memory.usage_in_bytes);
  - write "<event_fd> <control_fd> <args>" to cgroup.event_control.
@@ -488,7 +489,7 @@ To register new notification handler you need:
 eventfd will be woken up by control file implementation or when the
 cgroup is removed.
 
-To unregister notification handler just close eventfd.
+To unregister a notification handler just close eventfd.
 
 NOTE: Support of notifications should be implemented for the control
 file. See documentation for the subsystem.
@@ -502,7 +503,7 @@ file. See documentation for the subsystem.
 Each kernel subsystem that wants to hook into the generic cgroup
 system needs to create a cgroup_subsys object. This contains
 various methods, which are callbacks from the cgroup system, along
-with a subsystem id which will be assigned by the cgroup system.
+with a subsystem ID which will be assigned by the cgroup system.
 
 Other fields in the cgroup_subsys object include:
 
@@ -516,7 +517,7 @@ Other fields in the cgroup_subsys object include:
   at system boot.
 
 Each cgroup object created by the system has an array of pointers,
-indexed by subsystem id; this pointer is entirely managed by the
+indexed by subsystem ID; this pointer is entirely managed by the
 subsystem; the generic cgroup code will never touch this pointer.
 
 3.2 Synchronization
@@ -639,7 +640,7 @@ void post_clone(struct cgroup *cgrp)
 
 Called during cgroup_create() to do any parameter
 initialization which might be required before a task could attach.  For
-example in cpusets, no task may attach before 'cpus' and 'mems' are set
+example, in cpusets, no task may attach before 'cpus' and 'mems' are set
 up.
 
 void bind(struct cgroup *root)
@@ -650,7 +651,26 @@ and root cgroup. Currently this will only involve movement between
 the default hierarchy (which never has sub-cgroups) and a hierarchy
 that is being created/destroyed (and hence has no sub-cgroups).
 
-4. Questions
+4. Extended attribute usage
+===========================
+
+cgroup filesystem supports certain types of extended attributes in its
+directories and files.  The current supported types are:
+	- Trusted (XATTR_TRUSTED)
+	- Security (XATTR_SECURITY)
+
+Both require CAP_SYS_ADMIN capability to set.
+
+Like in tmpfs, the extended attributes in cgroup filesystem are stored
+using kernel memory and it's advised to keep the usage at minimum.  This
+is the reason why user defined extended attributes are not supported, since
+any user can do it and there's no limit in the value size.
+
+The current known users for this feature are SELinux to limit cgroup usage
+in containers and systemd for assorted meta data like main PID in a cgroup
+(systemd creates a cgroup per service).
+
+5. Questions
 ============
 
 Q: what's up with this '/bin/echo' ?
@@ -660,5 +680,5 @@ A: bash's builtin 'echo' command does not check calls to write() against
 
 Q: When I attach processes, only the first of the line gets really attached !
 A: We can only return one error code per call to write(). So you should also
-   put only ONE pid.
+   put only ONE PID.
 
diff --git a/Documentation/cgroups/memory.txt b/Documentation/cgroups/memory.txt
index 4372e6b..c07f7b4 100644
--- a/Documentation/cgroups/memory.txt
+++ b/Documentation/cgroups/memory.txt
@@ -18,16 +18,16 @@ from the rest of the system. The article on LWN [12] mentions some probable
 uses of the memory controller. The memory controller can be used to
 
 a. Isolate an application or a group of applications
-   Memory hungry applications can be isolated and limited to a smaller
+   Memory-hungry applications can be isolated and limited to a smaller
    amount of memory.
-b. Create a cgroup with limited amount of memory, this can be used
+b. Create a cgroup with a limited amount of memory; this can be used
    as a good alternative to booting with mem=XXXX.
 c. Virtualization solutions can control the amount of memory they want
    to assign to a virtual machine instance.
 d. A CD/DVD burner could control the amount of memory used by the
    rest of the system to ensure that burning does not fail due to lack
    of available memory.
-e. There are several other use cases, find one or use the controller just
+e. There are several other use cases; find one or use the controller just
    for fun (to learn and hack on the VM subsystem).
 
 Current Status: linux-2.6.34-mmotm(development version of 2010/April)
@@ -38,12 +38,12 @@ Features:
  - optionally, memory+swap usage can be accounted and limited.
  - hierarchical accounting
  - soft limit
- - moving(recharging) account at moving a task is selectable.
+ - moving (recharging) account at moving a task is selectable.
  - usage threshold notifier
  - oom-killer disable knob and oom-notifier
  - Root cgroup has no limit controls.
 
- Kernel memory support is work in progress, and the current version provides
+ Kernel memory support is a work in progress, and the current version provides
  basically functionality. (See Section 2.7)
 
 Brief summary of control files.
@@ -144,9 +144,9 @@ Figure 1 shows the important aspects of the controller
 3. Each page has a pointer to the page_cgroup, which in turn knows the
    cgroup it belongs to
 
-The accounting is done as follows: mem_cgroup_charge() is invoked to setup
+The accounting is done as follows: mem_cgroup_charge() is invoked to set up
 the necessary data structures and check if the cgroup that is being charged
-is over its limit. If it is then reclaim is invoked on the cgroup.
+is over its limit. If it is, then reclaim is invoked on the cgroup.
 More details can be found in the reclaim section of this document.
 If everything goes well, a page meta-data-structure called page_cgroup is
 updated. page_cgroup has its own LRU on cgroup.
@@ -163,13 +163,13 @@ for earlier. A file page will be accounted for as Page Cache when it's
 inserted into inode (radix-tree). While it's mapped into the page tables of
 processes, duplicate accounting is carefully avoided.
 
-A RSS page is unaccounted when it's fully unmapped. A PageCache page is
+An RSS page is unaccounted when it's fully unmapped. A PageCache page is
 unaccounted when it's removed from radix-tree. Even if RSS pages are fully
 unmapped (by kswapd), they may exist as SwapCache in the system until they
-are really freed. Such SwapCaches also also accounted.
+are really freed. Such SwapCaches are also accounted.
 A swapped-in page is not accounted until it's mapped.
 
-Note: The kernel does swapin-readahead and read multiple swaps at once.
+Note: The kernel does swapin-readahead and reads multiple swaps at once.
 This means swapped-in pages may contain pages for other tasks than a task
 causing page fault. So, we avoid accounting at swap-in I/O.
 
@@ -209,7 +209,7 @@ memsw.limit_in_bytes.
 Example: Assume a system with 4G of swap. A task which allocates 6G of memory
 (by mistake) under 2G memory limitation will use all swap.
 In this case, setting memsw.limit_in_bytes=3G will prevent bad use of swap.
-By using memsw limit, you can avoid system OOM which can be caused by swap
+By using the memsw limit, you can avoid system OOM which can be caused by swap
 shortage.
 
 * why 'memory+swap' rather than swap.
@@ -217,7 +217,7 @@ The global LRU(kswapd) can swap out arbitrary pages. Swap-out means
 to move account from memory to swap...there is no change in usage of
 memory+swap. In other words, when we want to limit the usage of swap without
 affecting global LRU, memory+swap limit is better than just limiting swap from
-OS point of view.
+an OS point of view.
 
 * What happens when a cgroup hits memory.memsw.limit_in_bytes
 When a cgroup hits memory.memsw.limit_in_bytes, it's useless to do swap-out
@@ -236,7 +236,7 @@ an OOM routine is invoked to select and kill the bulkiest task in the
 cgroup. (See 10. OOM Control below.)
 
 The reclaim algorithm has not been modified for cgroups, except that
-pages that are selected for reclaiming come from the per cgroup LRU
+pages that are selected for reclaiming come from the per-cgroup LRU
 list.
 
 NOTE: Reclaim does not work for the root cgroup, since we cannot set any
@@ -316,7 +316,7 @@ We can check the usage:
 # cat /sys/fs/cgroup/memory/0/memory.usage_in_bytes
 1216512
 
-A successful write to this file does not guarantee a successful set of
+A successful write to this file does not guarantee a successful setting of
 this limit to the value written into the file. This can be due to a
 number of factors, such as rounding up to page boundaries or the total
 availability of memory on the system. The user is required to re-read
@@ -350,7 +350,7 @@ Trying usual test under memory controller is always helpful.
 4.1 Troubleshooting
 
 Sometimes a user might find that the application under a cgroup is
-terminated by OOM killer. There are several causes for this:
+terminated by the OOM killer. There are several causes for this:
 
 1. The cgroup limit is too low (just too low to do anything useful)
 2. The user is using anonymous memory and swap is turned off or too low
@@ -358,7 +358,7 @@ terminated by OOM killer. There are several causes for this:
 A sync followed by echo 1 > /proc/sys/vm/drop_caches will help get rid of
 some of the pages cached in the cgroup (page cache pages).
 
-To know what happens, disable OOM_Kill by 10. OOM Control(see below) and
+To know what happens, disabling OOM_Kill as per "10. OOM Control" (below) and
 seeing what happens will be helpful.
 
 4.2 Task migration
@@ -399,10 +399,10 @@ About use_hierarchy, see Section 6.
 
   Almost all pages tracked by this memory cgroup will be unmapped and freed.
   Some pages cannot be freed because they are locked or in-use. Such pages are
-  moved to parent(if use_hierarchy==1) or root (if use_hierarchy==0) and this
+  moved to parent (if use_hierarchy==1) or root (if use_hierarchy==0) and this
   cgroup will be empty.
 
-  Typical use case of this interface is that calling this before rmdir().
+  The typical use case for this interface is before calling rmdir().
   Because rmdir() moves all pages to parent, some out-of-use page caches can be
   moved to the parent. If you want to avoid that, force_empty will be useful.
 
@@ -486,7 +486,7 @@ You can reset failcnt by writing 0 to failcnt file.
 
 For efficiency, as other kernel components, memory cgroup uses some optimization
 to avoid unnecessary cacheline false sharing. usage_in_bytes is affected by the
-method and doesn't show 'exact' value of memory(and swap) usage, it's an fuzz
+method and doesn't show 'exact' value of memory (and swap) usage, it's a fuzz
 value for efficient access. (Of course, when necessary, it's synchronized.)
 If you want to know more exact memory usage, you should use RSS+CACHE(+SWAP)
 value in memory.stat(see 5.2).
@@ -496,8 +496,8 @@ value in memory.stat(see 5.2).
 This is similar to numa_maps but operates on a per-memcg basis.  This is
 useful for providing visibility into the numa locality information within
 an memcg since the pages are allowed to be allocated from any physical
-node.  One of the usecases is evaluating application performance by
-combining this information with the application's cpu allocation.
+node.  One of the use cases is evaluating application performance by
+combining this information with the application's CPU allocation.
 
 We export "total", "file", "anon" and "unevictable" pages per-node for
 each memcg.  The ouput format of memory.numa_stat is:
@@ -561,10 +561,10 @@ are pushed back to their soft limits. If the soft limit of each control
 group is very high, they are pushed back as much as possible to make
 sure that one control group does not starve the others of memory.
 
-Please note that soft limits is a best effort feature, it comes with
+Please note that soft limits is a best-effort feature; it comes with
 no guarantees, but it does its best to make sure that when memory is
 heavily contended for, memory is allocated based on the soft limit
-hints/setup. Currently soft limit based reclaim is setup such that
+hints/setup. Currently soft limit based reclaim is set up such that
 it gets invoked from balance_pgdat (kswapd).
 
 7.1 Interface
@@ -592,7 +592,7 @@ page tables.
 
 8.1 Interface
 
-This feature is disabled by default. It can be enabled(and disabled again) by
+This feature is disabled by default. It can be enabledi (and disabled again) by
 writing to memory.move_charge_at_immigrate of the destination cgroup.
 
 If you want to enable it:
@@ -601,8 +601,8 @@ If you want to enable it:
 
 Note: Each bits of move_charge_at_immigrate has its own meaning about what type
       of charges should be moved. See 8.2 for details.
-Note: Charges are moved only when you move mm->owner, IOW, a leader of a thread
-      group.
+Note: Charges are moved only when you move mm->owner, in other words,
+      a leader of a thread group.
 Note: If we cannot find enough space for the task in the destination cgroup, we
       try to make space by reclaiming memory. Task migration may fail if we
       cannot make enough space.
@@ -612,25 +612,25 @@ And if you want disable it again:
 
 # echo 0 > memory.move_charge_at_immigrate
 
-8.2 Type of charges which can be move
+8.2 Type of charges which can be moved
 
-Each bits of move_charge_at_immigrate has its own meaning about what type of
-charges should be moved. But in any cases, it must be noted that an account of
-a page or a swap can be moved only when it is charged to the task's current(old)
-memory cgroup.
+Each bit in move_charge_at_immigrate has its own meaning about what type of
+charges should be moved. But in any case, it must be noted that an account of
+a page or a swap can be moved only when it is charged to the task's current
+(old) memory cgroup.
 
   bit | what type of charges would be moved ?
  -----+------------------------------------------------------------------------
-   0  | A charge of an anonymous page(or swap of it) used by the target task.
-      | You must enable Swap Extension(see 2.4) to enable move of swap charges.
+   0  | A charge of an anonymous page (or swap of it) used by the target task.
+      | You must enable Swap Extension (see 2.4) to enable move of swap charges.
  -----+------------------------------------------------------------------------
-   1  | A charge of file pages(normal file, tmpfs file(e.g. ipc shared memory)
+   1  | A charge of file pages (normal file, tmpfs file (e.g. ipc shared memory)
       | and swaps of tmpfs file) mmapped by the target task. Unlike the case of
-      | anonymous pages, file pages(and swaps) in the range mmapped by the task
+      | anonymous pages, file pages (and swaps) in the range mmapped by the task
       | will be moved even if the task hasn't done page fault, i.e. they might
       | not be the task's "RSS", but other task's "RSS" that maps the same file.
-      | And mapcount of the page is ignored(the page can be moved even if
-      | page_mapcount(page) > 1). You must enable Swap Extension(see 2.4) to
+      | And mapcount of the page is ignored (the page can be moved even if
+      | page_mapcount(page) > 1). You must enable Swap Extension (see 2.4) to
       | enable move of swap charges.
 
 8.3 TODO
@@ -640,11 +640,11 @@ memory cgroup.
 
 9. Memory thresholds
 
-Memory cgroup implements memory thresholds using cgroups notification
+Memory cgroup implements memory thresholds using the cgroups notification
 API (see cgroups.txt). It allows to register multiple memory and memsw
 thresholds and gets notifications when it crosses.
 
-To register a threshold application need:
+To register a threshold, an application must:
 - create an eventfd using eventfd(2);
 - open memory.usage_in_bytes or memory.memsw.usage_in_bytes;
 - write string like "<event_fd> <fd of memory.usage_in_bytes> <threshold>" to
@@ -659,24 +659,24 @@ It's applicable for root and non-root cgroup.
 
 memory.oom_control file is for OOM notification and other controls.
 
-Memory cgroup implements OOM notifier using cgroup notification
+Memory cgroup implements OOM notifier using the cgroup notification
 API (See cgroups.txt). It allows to register multiple OOM notification
 delivery and gets notification when OOM happens.
 
-To register a notifier, application need:
+To register a notifier, an application must:
  - create an eventfd using eventfd(2)
  - open memory.oom_control file
  - write string like "<event_fd> <fd of memory.oom_control>" to
    cgroup.event_control
 
-Application will be notified through eventfd when OOM happens.
-OOM notification doesn't work for root cgroup.
+The application will be notified through eventfd when OOM happens.
+OOM notification doesn't work for the root cgroup.
 
-You can disable OOM-killer by writing "1" to memory.oom_control file, as:
+You can disable the OOM-killer by writing "1" to memory.oom_control file, as:
 
 	#echo 1 > memory.oom_control
 
-This operation is only allowed to the top cgroup of sub-hierarchy.
+This operation is only allowed to the top cgroup of a sub-hierarchy.
 If OOM-killer is disabled, tasks under cgroup will hang/sleep
 in memory cgroup's OOM-waitqueue when they request accountable memory.
 
diff --git a/Documentation/cpu-freq/boost.txt b/Documentation/cpu-freq/boost.txt
new file mode 100644
index 0000000..9b4edfc
--- /dev/null
+++ b/Documentation/cpu-freq/boost.txt
@@ -0,0 +1,93 @@
+Processor boosting control
+
+	- information for users -
+
+Quick guide for the impatient:
+--------------------
+/sys/devices/system/cpu/cpufreq/boost
+controls the boost setting for the whole system. You can read and write
+that file with either "0" (boosting disabled) or "1" (boosting allowed).
+Reading or writing 1 does not mean that the system is boosting at this
+very moment, but only that the CPU _may_ raise the frequency at it's
+discretion.
+--------------------
+
+Introduction
+-------------
+Some CPUs support a functionality to raise the operating frequency of
+some cores in a multi-core package if certain conditions apply, mostly
+if the whole chip is not fully utilized and below it's intended thermal
+budget. This is done without operating system control by a combination
+of hardware and firmware.
+On Intel CPUs this is called "Turbo Boost", AMD calls it "Turbo-Core",
+in technical documentation "Core performance boost". In Linux we use
+the term "boost" for convenience.
+
+Rationale for disable switch
+----------------------------
+
+Though the idea is to just give better performance without any user
+intervention, sometimes the need arises to disable this functionality.
+Most systems offer a switch in the (BIOS) firmware to disable the
+functionality at all, but a more fine-grained and dynamic control would
+be desirable:
+1. While running benchmarks, reproducible results are important. Since
+   the boosting functionality depends on the load of the whole package,
+   single thread performance can vary. By explicitly disabling the boost
+   functionality at least for the benchmark's run-time the system will run
+   at a fixed frequency and results are reproducible again.
+2. To examine the impact of the boosting functionality it is helpful
+   to do tests with and without boosting.
+3. Boosting means overclocking the processor, though under controlled
+   conditions. By raising the frequency and the voltage the processor
+   will consume more power than without the boosting, which may be
+   undesirable for instance for mobile users. Disabling boosting may
+   save power here, though this depends on the workload.
+
+
+User controlled switch
+----------------------
+
+To allow the user to toggle the boosting functionality, the acpi-cpufreq
+driver exports a sysfs knob to disable it. There is a file:
+/sys/devices/system/cpu/cpufreq/boost
+which can either read "0" (boosting disabled) or "1" (boosting enabled).
+Reading the file is always supported, even if the processor does not
+support boosting. In this case the file will be read-only and always
+reads as "0". Explicitly changing the permissions and writing to that
+file anyway will return EINVAL.
+
+On supported CPUs one can write either a "0" or a "1" into this file.
+This will either disable the boost functionality on all cores in the
+whole system (0) or will allow the hardware to boost at will (1).
+
+Writing a "1" does not explicitly boost the system, but just allows the
+CPU (and the firmware) to boost at their discretion. Some implementations
+take external factors like the chip's temperature into account, so
+boosting once does not necessarily mean that it will occur every time
+even using the exact same software setup.
+
+
+AMD legacy cpb switch
+---------------------
+The AMD powernow-k8 driver used to support a very similar switch to
+disable or enable the "Core Performance Boost" feature of some AMD CPUs.
+This switch was instantiated in each CPU's cpufreq directory
+(/sys/devices/system/cpu[0-9]*/cpufreq) and was called "cpb".
+Though the per CPU existence hints at a more fine grained control, the
+actual implementation only supported a system-global switch semantics,
+which was simply reflected into each CPU's file. Writing a 0 or 1 into it
+would pull the other CPUs to the same state.
+For compatibility reasons this file and its behavior is still supported
+on AMD CPUs, though it is now protected by a config switch
+(X86_ACPI_CPUFREQ_CPB). On Intel CPUs this file will never be created,
+even with the config option set.
+This functionality is considered legacy and will be removed in some future
+kernel version.
+
+More fine grained boosting control
+----------------------------------
+
+Technically it is possible to switch the boosting functionality at least
+on a per package basis, for some CPUs even per core. Currently the driver
+does not support it, but this may be implemented in the future.
diff --git a/Documentation/cpuidle/sysfs.txt b/Documentation/cpuidle/sysfs.txt
index 9d28a34..b6f44f4 100644
--- a/Documentation/cpuidle/sysfs.txt
+++ b/Documentation/cpuidle/sysfs.txt
@@ -76,9 +76,17 @@ total 0
 
 
 * desc : Small description about the idle state (string)
-* disable : Option to disable this idle state (bool)
+* disable : Option to disable this idle state (bool) -> see note below
 * latency : Latency to exit out of this idle state (in microseconds)
 * name : Name of the idle state (string)
 * power : Power consumed while in this idle state (in milliwatts)
 * time : Total time spent in this idle state (in microseconds)
 * usage : Number of times this state was entered (count)
+
+Note:
+The behavior and the effect of the disable variable depends on the
+implementation of a particular governor. In the ladder governor, for
+example, it is not coherent, i.e. if one is disabling a light state,
+then all deeper states are disabled as well, but the disable variable
+does not reflect it. Likewise, if one enables a deep state but a lighter
+state still is disabled, then this has no effect.
diff --git a/Documentation/device-mapper/dm-raid.txt b/Documentation/device-mapper/dm-raid.txt
index 1c18449..728c38c 100644
--- a/Documentation/device-mapper/dm-raid.txt
+++ b/Documentation/device-mapper/dm-raid.txt
@@ -132,3 +132,12 @@ Here we can see the RAID type is raid4, there are 5 devices - all of
 which are 'A'live, and the array is 2/490221568 complete with recovery.
 Faulty or missing devices are marked 'D'.  Devices that are out-of-sync
 are marked 'a'.
+
+
+Version History
+---------------
+1.0.0	Initial version.  Support for RAID 4/5/6
+1.1.0	Added support for RAID 1
+1.2.0	Handle creation of arrays that contain failed devices.
+1.3.0	Added support for RAID 10
+1.3.1	Allow device replacement/rebuild for RAID 10
diff --git a/Documentation/devicetree/bindings/arm/arm-boards b/Documentation/devicetree/bindings/arm/arm-boards
index 91f2614..fc81a7d 100644
--- a/Documentation/devicetree/bindings/arm/arm-boards
+++ b/Documentation/devicetree/bindings/arm/arm-boards
@@ -1,3 +1,15 @@
+ARM Integrator/AP (Application Platform) and Integrator/CP (Compact Platform)
+-----------------------------------------------------------------------------
+ARM's oldest Linux-supported platform with connectors for different core
+tiles of ARMv4, ARMv5 and ARMv6 type.
+
+Required properties (in root node):
+	compatible = "arm,integrator-ap";  /* Application Platform */
+	compatible = "arm,integrator-cp";  /* Compact Platform */
+
+FPGA type interrupt controllers, see the versatile-fpga-irq binding doc.
+
+
 ARM Versatile Application and Platform Baseboards
 -------------------------------------------------
 ARM's development hardware platform with connectors for customizable
diff --git a/Documentation/devicetree/bindings/arm/bcm2835.txt b/Documentation/devicetree/bindings/arm/bcm2835.txt
new file mode 100644
index 0000000..ac68348
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/bcm2835.txt
@@ -0,0 +1,8 @@
+Broadcom BCM2835 device tree bindings
+-------------------------------------------
+
+Boards with the BCM2835 SoC shall have the following properties:
+
+Required root node property:
+
+compatible = "brcm,bcm2835";
diff --git a/Documentation/devicetree/bindings/arm/calxeda/combophy.txt b/Documentation/devicetree/bindings/arm/calxeda/combophy.txt
new file mode 100644
index 0000000..6622bdb
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/calxeda/combophy.txt
@@ -0,0 +1,17 @@
+Calxeda Highbank Combination Phys for SATA
+
+Properties:
+- compatible : Should be "calxeda,hb-combophy"
+- #phy-cells: Should be 1.
+- reg : Address and size for Combination Phy registers.
+- phydev: device ID for programming the combophy.
+
+Example:
+
+	combophy5: combo-phy@fff5d000 {
+		compatible = "calxeda,hb-combophy";
+		#phy-cells = <1>;
+		reg = <0xfff5d000 0x1000>;
+		phydev = <31>;
+	};
+
diff --git a/Documentation/devicetree/bindings/arm/davinci/nand.txt b/Documentation/devicetree/bindings/arm/davinci/nand.txt
new file mode 100644
index 0000000..e37241f
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/davinci/nand.txt
@@ -0,0 +1,51 @@
+* Texas Instruments Davinci NAND
+
+This file provides information, what the device node for the
+davinci nand interface contain.
+
+Required properties:
+- compatible: "ti,davinci-nand";
+- reg : contain 2 offset/length values:
+        - offset and length for the access window
+        - offset and length for accessing the aemif control registers
+- ti,davinci-chipselect: Indicates on the davinci_nand driver which
+                         chipselect is used for accessing the nand.
+
+Recommended properties :
+- ti,davinci-mask-ale: mask for ale
+- ti,davinci-mask-cle: mask for cle
+- ti,davinci-mask-chipsel: mask for chipselect
+- ti,davinci-ecc-mode: ECC mode valid values for davinci driver:
+		- "none"
+		- "soft"
+		- "hw"
+- ti,davinci-ecc-bits: used ECC bits, currently supported 1 or 4.
+- ti,davinci-nand-buswidth: buswidth 8 or 16
+- ti,davinci-nand-use-bbt: use flash based bad block table support.
+
+Example (enbw_cmc board):
+aemif@60000000 {
+	compatible = "ti,davinci-aemif";
+	#address-cells = <2>;
+	#size-cells = <1>;
+	reg = <0x68000000 0x80000>;
+	ranges = <2 0 0x60000000 0x02000000
+		  3 0 0x62000000 0x02000000
+		  4 0 0x64000000 0x02000000
+		  5 0 0x66000000 0x02000000
+		  6 0 0x68000000 0x02000000>;
+	nand@3,0 {
+		compatible = "ti,davinci-nand";
+		reg = <3 0x0 0x807ff
+			6 0x0 0x8000>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ti,davinci-chipselect = <1>;
+		ti,davinci-mask-ale = <0>;
+		ti,davinci-mask-cle = <0>;
+		ti,davinci-mask-chipsel = <0>;
+		ti,davinci-ecc-mode = "hw";
+		ti,davinci-ecc-bits = <4>;
+		ti,davinci-nand-use-bbt;
+	};
+};
diff --git a/Documentation/devicetree/bindings/arm/mrvl/tauros2.txt b/Documentation/devicetree/bindings/arm/mrvl/tauros2.txt
new file mode 100644
index 0000000..31af1cbb
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/mrvl/tauros2.txt
@@ -0,0 +1,17 @@
+* Marvell Tauros2 Cache
+
+Required properties:
+- compatible : Should be "marvell,tauros2-cache".
+- marvell,tauros2-cache-features : Specify the features supported for the
+  tauros2 cache.
+  The features including
+    CACHE_TAUROS2_PREFETCH_ON       (1 << 0)
+    CACHE_TAUROS2_LINEFILL_BURST8   (1 << 1)
+  The definition can be found at
+  arch/arm/include/asm/hardware/cache-tauros2.h
+
+Example:
+	L2: l2-cache {
+		compatible = "marvell,tauros2-cache";
+		marvell,tauros2-cache-features = <0x3>;
+	};
diff --git a/Documentation/devicetree/bindings/arm/msm/timer.txt b/Documentation/devicetree/bindings/arm/msm/timer.txt
new file mode 100644
index 0000000..8c5907b
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/timer.txt
@@ -0,0 +1,38 @@
+* MSM Timer
+
+Properties:
+
+- compatible : Should at least contain "qcom,msm-timer". More specific
+  properties such as "qcom,msm-gpt" and "qcom,msm-dgt" specify a general
+  purpose timer and a debug timer respectively.
+
+- interrupts : Interrupt indicating a match event.
+
+- reg : Specifies the base address of the timer registers. The second region
+  specifies an optional register used to configure the clock divider.
+
+- clock-frequency : The frequency of the timer in Hz.
+
+Optional:
+
+- cpu-offset : per-cpu offset used when the timer is accessed without the
+  CPU remapping facilities. The offset is cpu-offset * cpu-nr.
+
+Example:
+
+       timer@200a004 {
+               compatible = "qcom,msm-gpt", "qcom,msm-timer";
+               interrupts = <1 2 0x301>;
+               reg = <0x0200a004 0x10>;
+               clock-frequency = <32768>;
+               cpu-offset = <0x40000>;
+       };
+
+       timer@200a024 {
+               compatible = "qcom,msm-dgt", "qcom,msm-timer";
+               interrupts = <1 3 0x301>;
+               reg = <0x0200a024 0x10>,
+                     <0x0200a034 0x4>;
+               clock-frequency = <6750000>;
+               cpu-offset = <0x40000>;
+       };
diff --git a/Documentation/devicetree/bindings/arm/omap/omap.txt b/Documentation/devicetree/bindings/arm/omap/omap.txt
index ccdd0e5..d0051a7 100644
--- a/Documentation/devicetree/bindings/arm/omap/omap.txt
+++ b/Documentation/devicetree/bindings/arm/omap/omap.txt
@@ -36,6 +36,9 @@ Boards:
 - OMAP3 BeagleBoard : Low cost community board
   compatible = "ti,omap3-beagle", "ti,omap3"
 
+- OMAP3 Tobi with Overo : Commercial expansion board with daughter board
+  compatible = "ti,omap3-tobi", "ti,omap3-overo", "ti,omap3"
+
 - OMAP4 SDP : Software Developement Board
   compatible = "ti,omap4-sdp", "ti,omap4430"
 
diff --git a/Documentation/devicetree/bindings/arm/pmu.txt b/Documentation/devicetree/bindings/arm/pmu.txt
index 1c044eb..343781b 100644
--- a/Documentation/devicetree/bindings/arm/pmu.txt
+++ b/Documentation/devicetree/bindings/arm/pmu.txt
@@ -7,8 +7,12 @@ representation in the device tree should be done as under:-
 Required properties:
 
 - compatible : should be one of
+	"arm,cortex-a15-pmu"
 	"arm,cortex-a9-pmu"
 	"arm,cortex-a8-pmu"
+	"arm,cortex-a7-pmu"
+	"arm,cortex-a5-pmu"
+	"arm,arm11mpcore-pmu"
 	"arm,arm1176-pmu"
 	"arm,arm1136-pmu"
 - interrupts : 1 combined interrupt or 1 per core.
diff --git a/Documentation/devicetree/bindings/arm/versatile-fpga-irq.txt b/Documentation/devicetree/bindings/arm/versatile-fpga-irq.txt
new file mode 100644
index 0000000..9989eda
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/versatile-fpga-irq.txt
@@ -0,0 +1,31 @@
+* ARM Versatile FPGA interrupt controller
+
+One or more FPGA IRQ controllers can be synthesized in an ARM reference board
+such as the Integrator or Versatile family. The output of these different
+controllers are OR:ed together and fed to the CPU tile's IRQ input. Each
+instance can handle up to 32 interrupts.
+
+Required properties:
+- compatible: "arm,versatile-fpga-irq"
+- interrupt-controller: Identifies the node as an interrupt controller
+- #interrupt-cells: The number of cells to define the interrupts.  Must be 1
+  as the FPGA IRQ controller has no configuration options for interrupt
+  sources.  The cell is a u32 and defines the interrupt number.
+- reg: The register bank for the FPGA interrupt controller.
+- clear-mask: a u32 number representing the mask written to clear all IRQs
+  on the controller at boot for example.
+- valid-mask: a u32 number representing a bit mask determining which of
+  the interrupts are valid. Unconnected/unused lines are set to 0, and
+  the system till not make it possible for devices to request these
+  interrupts.
+
+Example:
+
+pic: pic@14000000 {
+        compatible = "arm,versatile-fpga-irq";
+        #interrupt-cells = <1>;
+        interrupt-controller;
+        reg = <0x14000000 0x100>;
+        clear-mask = <0xffffffff>;
+        valid-mask = <0x003fffff>;
+};
diff --git a/Documentation/devicetree/bindings/arm/vt8500.txt b/Documentation/devicetree/bindings/arm/vt8500.txt
new file mode 100644
index 0000000..d657832
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/vt8500.txt
@@ -0,0 +1,14 @@
+VIA/Wondermedia VT8500 Platforms Device Tree Bindings
+---------------------------------------
+
+Boards with the VIA VT8500 SoC shall have the following properties:
+Required root node property:
+compatible = "via,vt8500";
+
+Boards with the Wondermedia WM8505 SoC shall have the following properties:
+Required root node property:
+compatible = "wm,wm8505";
+
+Boards with the Wondermedia WM8650 SoC shall have the following properties:
+Required root node property:
+compatible = "wm,wm8650";
diff --git a/Documentation/devicetree/bindings/arm/vt8500/via,vt8500-intc.txt b/Documentation/devicetree/bindings/arm/vt8500/via,vt8500-intc.txt
new file mode 100644
index 0000000..0a4ce10
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/vt8500/via,vt8500-intc.txt
@@ -0,0 +1,16 @@
+VIA/Wondermedia VT8500 Interrupt Controller
+-----------------------------------------------------
+
+Required properties:
+- compatible : "via,vt8500-intc"
+- reg : Should contain 1 register ranges(address and length)
+- #interrupt-cells : should be <1>
+
+Example:
+
+	intc: interrupt-controller@d8140000 {
+		compatible = "via,vt8500-intc";
+		interrupt-controller;
+		reg = <0xd8140000 0x10000>;
+		#interrupt-cells = <1>;
+	};
diff --git a/Documentation/devicetree/bindings/arm/vt8500/via,vt8500-pmc.txt b/Documentation/devicetree/bindings/arm/vt8500/via,vt8500-pmc.txt
new file mode 100644
index 0000000..521b9c7
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/vt8500/via,vt8500-pmc.txt
@@ -0,0 +1,13 @@
+VIA/Wondermedia VT8500 Power Management Controller
+-----------------------------------------------------
+
+Required properties:
+- compatible : "via,vt8500-pmc"
+- reg : Should contain 1 register ranges(address and length)
+
+Example:
+
+	pmc@d8130000 {
+		compatible = "via,vt8500-pmc";
+		reg = <0xd8130000 0x1000>;
+	};
diff --git a/Documentation/devicetree/bindings/arm/vt8500/via,vt8500-timer.txt b/Documentation/devicetree/bindings/arm/vt8500/via,vt8500-timer.txt
new file mode 100644
index 0000000..901c73f
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/vt8500/via,vt8500-timer.txt
@@ -0,0 +1,15 @@
+VIA/Wondermedia VT8500 Timer
+-----------------------------------------------------
+
+Required properties:
+- compatible : "via,vt8500-timer"
+- reg : Should contain 1 register ranges(address and length)
+- interrupts : interrupt for the timer
+
+Example:
+
+	timer@d8130100 {
+		compatible = "via,vt8500-timer";
+		reg = <0xd8130100 0x28>;
+		interrupts = <36>;
+	};
diff --git a/Documentation/devicetree/bindings/ata/ahci-platform.txt b/Documentation/devicetree/bindings/ata/ahci-platform.txt
index 8bb8a76..b519f9b 100644
--- a/Documentation/devicetree/bindings/ata/ahci-platform.txt
+++ b/Documentation/devicetree/bindings/ata/ahci-platform.txt
@@ -8,9 +8,18 @@ Required properties:
 - interrupts        : <interrupt mapping for SATA IRQ>
 - reg               : <registers mapping>
 
+Optional properties:
+- calxeda,port-phys: phandle-combophy and lane assignment, which maps each
+			SATA port to a combophy and a lane within that
+			combophy
+- dma-coherent      : Present if dma operations are coherent
+
 Example:
         sata@ffe08000 {
 		compatible = "calxeda,hb-ahci";
                 reg = <0xffe08000 0x1000>;
                 interrupts = <115>;
+		calxeda,port-phys = <&combophy5 0 &combophy0 0 &combophy0 1
+					&combophy0 2 &combophy0 3>;
+
         };
diff --git a/Documentation/devicetree/bindings/ata/pata-arasan.txt b/Documentation/devicetree/bindings/ata/pata-arasan.txt
new file mode 100644
index 0000000..95ec7f8
--- /dev/null
+++ b/Documentation/devicetree/bindings/ata/pata-arasan.txt
@@ -0,0 +1,17 @@
+* ARASAN PATA COMPACT FLASH CONTROLLER
+
+Required properties:
+- compatible: "arasan,cf-spear1340"
+- reg: Address range of the CF registers
+- interrupt-parent: Should be the phandle for the interrupt controller
+  that services interrupts for this device
+- interrupt: Should contain the CF interrupt number
+
+Example:
+
+	cf@fc000000 {
+		compatible = "arasan,cf-spear1340";
+		reg = <0xfc000000 0x1000>;
+		interrupt-parent = <&vic1>;
+		interrupts = <12>;
+	};
diff --git a/Documentation/devicetree/bindings/bus/omap-ocp2scp.txt b/Documentation/devicetree/bindings/bus/omap-ocp2scp.txt
new file mode 100644
index 0000000..d2fe064
--- /dev/null
+++ b/Documentation/devicetree/bindings/bus/omap-ocp2scp.txt
@@ -0,0 +1,10 @@
+* OMAP OCP2SCP - ocp interface to scp interface
+
+properties:
+- compatible : Should be "ti,omap-ocp2scp"
+- #address-cells, #size-cells : Must be present if the device has sub-nodes
+- ranges : the child address space are mapped 1:1 onto the parent address space
+- ti,hwmods : must be "ocp2scp_usb_phy"
+
+Sub-nodes:
+All the devices connected to ocp2scp are described using sub-node to ocp2scp
diff --git a/Documentation/devicetree/bindings/clock/imx23-clock.txt b/Documentation/devicetree/bindings/clock/imx23-clock.txt
new file mode 100644
index 0000000..a0b867e
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/imx23-clock.txt
@@ -0,0 +1,76 @@
+* Clock bindings for Freescale i.MX23
+
+Required properties:
+- compatible: Should be "fsl,imx23-clkctrl"
+- reg: Address and length of the register set
+- #clock-cells: Should be <1>
+
+The clock consumer should specify the desired clock by having the clock
+ID in its "clocks" phandle cell.  The following is a full list of i.MX23
+clocks and IDs.
+
+	Clock		ID
+	------------------
+	ref_xtal	0
+	pll		1
+	ref_cpu		2
+	ref_emi		3
+	ref_pix		4
+	ref_io		5
+	saif_sel	6
+	lcdif_sel	7
+	gpmi_sel	8
+	ssp_sel		9
+	emi_sel		10
+	cpu		11
+	etm_sel		12
+	cpu_pll		13
+	cpu_xtal	14
+	hbus		15
+	xbus		16
+	lcdif_div	17
+	ssp_div		18
+	gpmi_div	19
+	emi_pll		20
+	emi_xtal	21
+	etm_div		22
+	saif_div	23
+	clk32k_div	24
+	rtc		25
+	adc		26
+	spdif_div	27
+	clk32k		28
+	dri		29
+	pwm		30
+	filt		31
+	uart		32
+	ssp		33
+	gpmi		34
+	spdif		35
+	emi		36
+	saif		37
+	lcdif		38
+	etm		39
+	usb		40
+	usb_pwr		41
+
+Examples:
+
+clks: clkctrl@80040000 {
+	compatible = "fsl,imx23-clkctrl";
+	reg = <0x80040000 0x2000>;
+	#clock-cells = <1>;
+	clock-output-names =
+		...
+		"uart",		/* 32 */
+		...
+		"end_of_list";
+};
+
+auart0: serial@8006c000 {
+	compatible = "fsl,imx23-auart";
+	reg = <0x8006c000 0x2000>;
+	interrupts = <24 25 23>;
+	clocks = <&clks 32>;
+	status = "disabled";
+};
diff --git a/Documentation/devicetree/bindings/clock/imx28-clock.txt b/Documentation/devicetree/bindings/clock/imx28-clock.txt
new file mode 100644
index 0000000..aa2af28
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/imx28-clock.txt
@@ -0,0 +1,99 @@
+* Clock bindings for Freescale i.MX28
+
+Required properties:
+- compatible: Should be "fsl,imx28-clkctrl"
+- reg: Address and length of the register set
+- #clock-cells: Should be <1>
+
+The clock consumer should specify the desired clock by having the clock
+ID in its "clocks" phandle cell.  The following is a full list of i.MX28
+clocks and IDs.
+
+	Clock		ID
+	------------------
+	ref_xtal	0
+	pll0		1
+	pll1		2
+	pll2		3
+	ref_cpu		4
+	ref_emi		5
+	ref_io0		6
+	ref_io1		7
+	ref_pix		8
+	ref_hsadc	9
+	ref_gpmi	10
+	saif0_sel	11
+	saif1_sel	12
+	gpmi_sel	13
+	ssp0_sel	14
+	ssp1_sel	15
+	ssp2_sel	16
+	ssp3_sel	17
+	emi_sel		18
+	etm_sel		19
+	lcdif_sel	20
+	cpu		21
+	ptp_sel		22
+	cpu_pll		23
+	cpu_xtal	24
+	hbus		25
+	xbus		26
+	ssp0_div	27
+	ssp1_div	28
+	ssp2_div	29
+	ssp3_div	30
+	gpmi_div	31
+	emi_pll		32
+	emi_xtal	33
+	lcdif_div	34
+	etm_div		35
+	ptp		36
+	saif0_div	37
+	saif1_div	38
+	clk32k_div	39
+	rtc		40
+	lradc		41
+	spdif_div	42
+	clk32k		43
+	pwm		44
+	uart		45
+	ssp0		46
+	ssp1		47
+	ssp2		48
+	ssp3		49
+	gpmi		50
+	spdif		51
+	emi		52
+	saif0		53
+	saif1		54
+	lcdif		55
+	etm		56
+	fec		57
+	can0		58
+	can1		59
+	usb0		60
+	usb1		61
+	usb0_pwr	62
+	usb1_pwr	63
+	enet_out	64
+
+Examples:
+
+clks: clkctrl@80040000 {
+	compatible = "fsl,imx28-clkctrl";
+	reg = <0x80040000 0x2000>;
+	#clock-cells = <1>;
+	clock-output-names =
+		...
+		"uart",		/* 45 */
+		...
+		"end_of_list";
+};
+
+auart0: serial@8006a000 {
+	compatible = "fsl,imx28-auart", "fsl,imx23-auart";
+	reg = <0x8006a000 0x2000>;
+	interrupts = <112 70 71>;
+	clocks = <&clks 45>;
+	status = "disabled";
+};
diff --git a/Documentation/devicetree/bindings/clock/imx6q-clock.txt b/Documentation/devicetree/bindings/clock/imx6q-clock.txt
new file mode 100644
index 0000000..492bd99
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/imx6q-clock.txt
@@ -0,0 +1,222 @@
+* Clock bindings for Freescale i.MX6 Quad
+
+Required properties:
+- compatible: Should be "fsl,imx6q-ccm"
+- reg: Address and length of the register set
+- interrupts: Should contain CCM interrupt
+- #clock-cells: Should be <1>
+
+The clock consumer should specify the desired clock by having the clock
+ID in its "clocks" phandle cell.  The following is a full list of i.MX6Q
+clocks and IDs.
+
+	Clock			ID
+	---------------------------
+	dummy			0
+	ckil			1
+	ckih			2
+	osc			3
+	pll2_pfd0_352m		4
+	pll2_pfd1_594m		5
+	pll2_pfd2_396m		6
+	pll3_pfd0_720m		7
+	pll3_pfd1_540m		8
+	pll3_pfd2_508m		9
+	pll3_pfd3_454m		10
+	pll2_198m		11
+	pll3_120m		12
+	pll3_80m		13
+	pll3_60m		14
+	twd			15
+	step			16
+	pll1_sw			17
+	periph_pre		18
+	periph2_pre		19
+	periph_clk2_sel		20
+	periph2_clk2_sel	21
+	axi_sel			22
+	esai_sel		23
+	asrc_sel		24
+	spdif_sel		25
+	gpu2d_axi		26
+	gpu3d_axi		27
+	gpu2d_core_sel		28
+	gpu3d_core_sel		29
+	gpu3d_shader_sel	30
+	ipu1_sel		31
+	ipu2_sel		32
+	ldb_di0_sel		33
+	ldb_di1_sel		34
+	ipu1_di0_pre_sel	35
+	ipu1_di1_pre_sel	36
+	ipu2_di0_pre_sel	37
+	ipu2_di1_pre_sel	38
+	ipu1_di0_sel		39
+	ipu1_di1_sel		40
+	ipu2_di0_sel		41
+	ipu2_di1_sel		42
+	hsi_tx_sel		43
+	pcie_axi_sel		44
+	ssi1_sel		45
+	ssi2_sel		46
+	ssi3_sel		47
+	usdhc1_sel		48
+	usdhc2_sel		49
+	usdhc3_sel		50
+	usdhc4_sel		51
+	enfc_sel		52
+	emi_sel			53
+	emi_slow_sel		54
+	vdo_axi_sel		55
+	vpu_axi_sel		56
+	cko1_sel		57
+	periph			58
+	periph2			59
+	periph_clk2		60
+	periph2_clk2		61
+	ipg			62
+	ipg_per			63
+	esai_pred		64
+	esai_podf		65
+	asrc_pred		66
+	asrc_podf		67
+	spdif_pred		68
+	spdif_podf		69
+	can_root		70
+	ecspi_root		71
+	gpu2d_core_podf		72
+	gpu3d_core_podf		73
+	gpu3d_shader		74
+	ipu1_podf		75
+	ipu2_podf		76
+	ldb_di0_podf		77
+	ldb_di1_podf		78
+	ipu1_di0_pre		79
+	ipu1_di1_pre		80
+	ipu2_di0_pre		81
+	ipu2_di1_pre		82
+	hsi_tx_podf		83
+	ssi1_pred		84
+	ssi1_podf		85
+	ssi2_pred		86
+	ssi2_podf		87
+	ssi3_pred		88
+	ssi3_podf		89
+	uart_serial_podf	90
+	usdhc1_podf		91
+	usdhc2_podf		92
+	usdhc3_podf		93
+	usdhc4_podf		94
+	enfc_pred		95
+	enfc_podf		96
+	emi_podf		97
+	emi_slow_podf		98
+	vpu_axi_podf		99
+	cko1_podf		100
+	axi			101
+	mmdc_ch0_axi_podf	102
+	mmdc_ch1_axi_podf	103
+	arm			104
+	ahb			105
+	apbh_dma		106
+	asrc			107
+	can1_ipg		108
+	can1_serial		109
+	can2_ipg		110
+	can2_serial		111
+	ecspi1			112
+	ecspi2			113
+	ecspi3			114
+	ecspi4			115
+	ecspi5			116
+	enet			117
+	esai			118
+	gpt_ipg			119
+	gpt_ipg_per		120
+	gpu2d_core		121
+	gpu3d_core		122
+	hdmi_iahb		123
+	hdmi_isfr		124
+	i2c1			125
+	i2c2			126
+	i2c3			127
+	iim			128
+	enfc			129
+	ipu1			130
+	ipu1_di0		131
+	ipu1_di1		132
+	ipu2			133
+	ipu2_di0		134
+	ldb_di0			135
+	ldb_di1			136
+	ipu2_di1		137
+	hsi_tx			138
+	mlb			139
+	mmdc_ch0_axi		140
+	mmdc_ch1_axi		141
+	ocram			142
+	openvg_axi		143
+	pcie_axi		144
+	pwm1			145
+	pwm2			146
+	pwm3			147
+	pwm4			148
+	per1_bch		149
+	gpmi_bch_apb		150
+	gpmi_bch		151
+	gpmi_io			152
+	gpmi_apb		153
+	sata			154
+	sdma			155
+	spba			156
+	ssi1			157
+	ssi2			158
+	ssi3			159
+	uart_ipg		160
+	uart_serial		161
+	usboh3			162
+	usdhc1			163
+	usdhc2			164
+	usdhc3			165
+	usdhc4			166
+	vdo_axi			167
+	vpu_axi			168
+	cko1			169
+	pll1_sys		170
+	pll2_bus		171
+	pll3_usb_otg		172
+	pll4_audio		173
+	pll5_video		174
+	pll6_mlb		175
+	pll7_usb_host		176
+	pll8_enet		177
+	ssi1_ipg		178
+	ssi2_ipg		179
+	ssi3_ipg		180
+	rom			181
+	usbphy1			182
+	usbphy2			183
+	ldb_di0_div_3_5		184
+	ldb_di1_div_3_5		185
+
+Examples:
+
+clks: ccm@020c4000 {
+	compatible = "fsl,imx6q-ccm";
+	reg = <0x020c4000 0x4000>;
+	interrupts = <0 87 0x04 0 88 0x04>;
+	#clock-cells = <1>;
+	clock-output-names = ...
+			     "uart_ipg",
+			     "uart_serial",
+			     ...;
+};
+
+uart1: serial@02020000 {
+	compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
+	reg = <0x02020000 0x4000>;
+	interrupts = <0 26 0x04>;
+	clocks = <&clks 160>, <&clks 161>;
+	clock-names = "ipg", "per";
+	status = "disabled";
+};
diff --git a/Documentation/devicetree/bindings/clock/vt8500.txt b/Documentation/devicetree/bindings/clock/vt8500.txt
new file mode 100644
index 0000000..a880c70
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/vt8500.txt
@@ -0,0 +1,72 @@
+Device Tree Clock bindings for arch-vt8500
+
+This binding uses the common clock binding[1].
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+- compatible : shall be one of the following:
+	"via,vt8500-pll-clock" - for a VT8500/WM8505 PLL clock
+	"wm,wm8650-pll-clock" - for a WM8650 PLL clock
+	"via,vt8500-device-clock" - for a VT/WM device clock
+
+Required properties for PLL clocks:
+- reg : shall be the control register offset from PMC base for the pll clock.
+- clocks : shall be the input parent clock phandle for the clock. This should
+	be the reference clock.
+- #clock-cells : from common clock binding; shall be set to 0.
+
+Required properties for device clocks:
+- clocks : shall be the input parent clock phandle for the clock. This should
+	be a pll output.
+- #clock-cells : from common clock binding; shall be set to 0.
+
+
+Device Clocks
+
+Device clocks are required to have one or both of the following sets of
+properties:
+
+
+Gated device clocks:
+
+Required properties:
+- enable-reg : shall be the register offset from PMC base for the enable
+	register.
+- enable-bit : shall be the bit within enable-reg to enable/disable the clock.
+
+
+Divisor device clocks:
+
+Required property:
+- divisor-reg : shall be the register offset from PMC base for the divisor
+	register.
+Optional property:
+- divisor-mask : shall be the mask for the divisor register. Defaults to 0x1f
+	if not specified.
+
+
+For example:
+
+ref25: ref25M {
+	#clock-cells = <0>;
+	compatible = "fixed-clock";
+	clock-frequency = <25000000>;
+};
+
+plla: plla {
+	#clock-cells = <0>;
+	compatible = "wm,wm8650-pll-clock";
+	clocks = <&ref25>;
+	reg = <0x200>;
+};
+
+sdhc: sdhc {
+	#clock-cells = <0>;
+	compatible = "via,vt8500-device-clock";
+	clocks = <&pllb>;
+	divisor-reg = <0x328>;
+	divisor-mask = <0x3f>;
+	enable-reg = <0x254>;
+	enable-bit = <18>;
+};
diff --git a/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt b/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt
new file mode 100644
index 0000000..4416ccc
--- /dev/null
+++ b/Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt
@@ -0,0 +1,55 @@
+Generic CPU0 cpufreq driver
+
+It is a generic cpufreq driver for CPU0 frequency management.  It
+supports both uniprocessor (UP) and symmetric multiprocessor (SMP)
+systems which share clock and voltage across all CPUs.
+
+Both required and optional properties listed below must be defined
+under node /cpus/cpu@0.
+
+Required properties:
+- operating-points: Refer to Documentation/devicetree/bindings/power/opp.txt
+  for details
+
+Optional properties:
+- clock-latency: Specify the possible maximum transition latency for clock,
+  in unit of nanoseconds.
+- voltage-tolerance: Specify the CPU voltage tolerance in percentage.
+
+Examples:
+
+cpus {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	cpu@0 {
+		compatible = "arm,cortex-a9";
+		reg = <0>;
+		next-level-cache = <&L2>;
+		operating-points = <
+			/* kHz    uV */
+			792000  1100000
+			396000  950000
+			198000  850000
+		>;
+		transition-latency = <61036>; /* two CLK32 periods */
+	};
+
+	cpu@1 {
+		compatible = "arm,cortex-a9";
+		reg = <1>;
+		next-level-cache = <&L2>;
+	};
+
+	cpu@2 {
+		compatible = "arm,cortex-a9";
+		reg = <2>;
+		next-level-cache = <&L2>;
+	};
+
+	cpu@3 {
+		compatible = "arm,cortex-a9";
+		reg = <3>;
+		next-level-cache = <&L2>;
+	};
+};
diff --git a/Documentation/devicetree/bindings/crypto/fsl-sec4.txt b/Documentation/devicetree/bindings/crypto/fsl-sec4.txt
index bf57ecd..bd7ce12 100644
--- a/Documentation/devicetree/bindings/crypto/fsl-sec4.txt
+++ b/Documentation/devicetree/bindings/crypto/fsl-sec4.txt
@@ -9,6 +9,7 @@ Copyright (C) 2008-2011 Freescale Semiconductor Inc.
    -Run Time Integrity Check (RTIC) Node
    -Run Time Integrity Check (RTIC) Memory Node
    -Secure Non-Volatile Storage (SNVS) Node
+   -Secure Non-Volatile Storage (SNVS) Low Power (LP) RTC Node
    -Full Example
 
 NOTE: the SEC 4 is also known as Freescale's Cryptographic Accelerator
@@ -294,6 +295,27 @@ Secure Non-Volatile Storage (SNVS) Node
           address and length of the SEC4 configuration
           registers.
 
+   - #address-cells
+       Usage: required
+       Value type: <u32>
+       Definition: A standard property.  Defines the number of cells
+           for representing physical addresses in child nodes.  Must
+           have a value of 1.
+
+   - #size-cells
+       Usage: required
+       Value type: <u32>
+       Definition: A standard property.  Defines the number of cells
+           for representing the size of physical addresses in
+           child nodes.  Must have a value of 1.
+
+   - ranges
+       Usage: required
+       Value type: <prop-encoded-array>
+       Definition: A standard property.  Specifies the physical address
+           range of the SNVS register space.  A triplet that includes
+           the child address, parent address, & length.
+
    - interrupts
       Usage: required
       Value type: <prop_encoded-array>
@@ -314,11 +336,34 @@ EXAMPLE
 	sec_mon@314000 {
 		compatible = "fsl,sec-v4.0-mon";
 		reg = <0x314000 0x1000>;
+		ranges = <0 0x314000 0x1000>;
 		interrupt-parent = <&mpic>;
 		interrupts = <93 2>;
 	};
 
 =====================================================================
+Secure Non-Volatile Storage (SNVS) Low Power (LP) RTC Node
+
+  A SNVS child node that defines SNVS LP RTC.
+
+  - compatible
+      Usage: required
+      Value type: <string>
+      Definition: Must include "fsl,sec-v4.0-mon-rtc-lp".
+
+  - reg
+      Usage: required
+      Value type: <prop-encoded-array>
+      Definition: A standard property.  Specifies the physical
+          address and length of the SNVS LP configuration registers.
+
+EXAMPLE
+	sec_mon_rtc_lp@314000 {
+		compatible = "fsl,sec-v4.0-mon-rtc-lp";
+		reg = <0x34 0x58>;
+	};
+
+=====================================================================
 FULL EXAMPLE
 
 	crypto: crypto@300000 {
@@ -390,8 +435,14 @@ FULL EXAMPLE
 	sec_mon: sec_mon@314000 {
 		compatible = "fsl,sec-v4.0-mon";
 		reg = <0x314000 0x1000>;
+		ranges = <0 0x314000 0x1000>;
 		interrupt-parent = <&mpic>;
 		interrupts = <93 2>;
+
+		sec_mon_rtc_lp@34 {
+			compatible = "fsl,sec-v4.0-mon-rtc-lp";
+			reg = <0x34 0x58>;
+		};
 	};
 
 =====================================================================
diff --git a/Documentation/devicetree/bindings/crypto/mv_cesa.txt b/Documentation/devicetree/bindings/crypto/mv_cesa.txt
new file mode 100644
index 0000000..47229b1
--- /dev/null
+++ b/Documentation/devicetree/bindings/crypto/mv_cesa.txt
@@ -0,0 +1,20 @@
+Marvell Cryptographic Engines And Security Accelerator
+
+Required properties:
+- compatible : should be "marvell,orion-crypto"
+- reg : base physical address of the engine and length of memory mapped
+        region, followed by base physical address of sram and its memory
+        length
+- reg-names : "regs" , "sram";
+- interrupts : interrupt number
+
+Examples:
+
+	crypto@30000 {
+		compatible = "marvell,orion-crypto";
+		reg = <0x30000 0x10000>,
+		      <0x4000000 0x800>;
+		reg-names = "regs" , "sram";
+		interrupts = <22>;
+		status = "okay";
+	};
diff --git a/Documentation/devicetree/bindings/dma/arm-pl330.txt b/Documentation/devicetree/bindings/dma/arm-pl330.txt
index a4cd273..36e27d5 100644
--- a/Documentation/devicetree/bindings/dma/arm-pl330.txt
+++ b/Documentation/devicetree/bindings/dma/arm-pl330.txt
@@ -9,6 +9,9 @@ Required properties:
     region.
   - interrupts: interrupt number to the cpu.
 
+Optional properties:
+- dma-coherent      : Present if dma operations are coherent
+
 Example:
 
 	pdma0: pdma@12680000 {
diff --git a/Documentation/devicetree/bindings/gpio/gpio-74x164.txt b/Documentation/devicetree/bindings/gpio/gpio-74x164.txt
new file mode 100644
index 0000000..cc26080
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/gpio-74x164.txt
@@ -0,0 +1,22 @@
+* Generic 8-bits shift register GPIO driver
+
+Required properties:
+- compatible : Should be "fairchild,74hc595"
+- reg : chip select number
+- gpio-controller : Marks the device node as a gpio controller.
+- #gpio-cells : Should be two.  The first cell is the pin number and
+  the second cell is used to specify the gpio polarity:
+      0 = active high
+      1 = active low
+- registers-number: Number of daisy-chained shift registers
+
+Example:
+
+gpio5: gpio5@0 {
+	compatible = "fairchild,74hc595";
+	reg = <0>;
+	gpio-controller;
+	#gpio-cells = <2>;
+	registers-number = <4>;
+	spi-max-frequency = <100000>;
+};
diff --git a/Documentation/devicetree/bindings/gpio/gpio-adnp.txt b/Documentation/devicetree/bindings/gpio/gpio-adnp.txt
new file mode 100644
index 0000000..af66b27
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/gpio-adnp.txt
@@ -0,0 +1,34 @@
+Avionic Design N-bit GPIO expander bindings
+
+Required properties:
+- compatible: should be "ad,gpio-adnp"
+- reg: The I2C slave address for this device.
+- interrupt-parent: phandle of the parent interrupt controller.
+- interrupts: Interrupt specifier for the controllers interrupt.
+- #gpio-cells: Should be 2. The first cell is the GPIO number and the
+  second cell is used to specify optional parameters:
+  - bit 0: polarity (0: normal, 1: inverted)
+- gpio-controller: Marks the device as a GPIO controller
+- nr-gpios: The number of pins supported by the controller.
+
+The GPIO expander can optionally be used as an interrupt controller, in
+which case it uses the default two cell specifier as described in
+Documentation/devicetree/bindings/interrupt-controller/interrupts.txt.
+
+Example:
+
+	gpioext: gpio-controller@41 {
+		compatible = "ad,gpio-adnp";
+		reg = <0x41>;
+
+		interrupt-parent = <&gpio>;
+		interrupts = <160 1>;
+
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+
+		nr-gpios = <64>;
+	};
diff --git a/Documentation/devicetree/bindings/gpio/gpio-fan.txt b/Documentation/devicetree/bindings/gpio/gpio-fan.txt
new file mode 100644
index 0000000..2dd457a
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/gpio-fan.txt
@@ -0,0 +1,25 @@
+Bindings for fan connected to GPIO lines
+
+Required properties:
+- compatible : "gpio-fan"
+- gpios: Specifies the pins that map to bits in the control value,
+  ordered MSB-->LSB.
+- gpio-fan,speed-map: A mapping of possible fan RPM speeds and the
+  control value that should be set to achieve them. This array
+  must have the RPM values in ascending order.
+
+Optional properties:
+- alarm-gpios: This pin going active indicates something is wrong with
+  the fan, and a udev event will be fired.
+
+Examples:
+
+	gpio_fan {
+		compatible = "gpio-fan";
+		gpios = <&gpio1 14 1
+			 &gpio1 13 1>;
+		gpio-fan,speed-map = <0    0
+				      3000 1
+				      6000 2>;
+		alarm-gpios = <&gpio1 15 1>;
+	};
diff --git a/Documentation/devicetree/bindings/gpio/gpio-mvebu.txt b/Documentation/devicetree/bindings/gpio/gpio-mvebu.txt
new file mode 100644
index 0000000..a6f3bec
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/gpio-mvebu.txt
@@ -0,0 +1,53 @@
+* Marvell EBU GPIO controller
+
+Required properties:
+
+- compatible : Should be "marvell,orion-gpio", "marvell,mv78200-gpio"
+  or "marvell,armadaxp-gpio". "marvell,orion-gpio" should be used for
+  Orion, Kirkwood, Dove, Discovery (except MV78200) and Armada
+  370. "marvell,mv78200-gpio" should be used for the Discovery
+  MV78200. "marvel,armadaxp-gpio" should be used for all Armada XP
+  SoCs (MV78230, MV78260, MV78460).
+
+- reg: Address and length of the register set for the device. Only one
+  entry is expected, except for the "marvell,armadaxp-gpio" variant
+  for which two entries are expected: one for the general registers,
+  one for the per-cpu registers.
+
+- interrupts: The list of interrupts that are used for all the pins
+  managed by this GPIO bank. There can be more than one interrupt
+  (example: 1 interrupt per 8 pins on Armada XP, which means 4
+  interrupts per bank of 32 GPIOs).
+
+- interrupt-controller: identifies the node as an interrupt controller
+
+- #interrupt-cells: specifies the number of cells needed to encode an
+  interrupt source. Should be two.
+  The first cell is the GPIO number.
+  The second cell is used to specify flags:
+    bits[3:0] trigger type and level flags:
+      1 = low-to-high edge triggered.
+      2 = high-to-low edge triggered.
+      4 = active high level-sensitive.
+      8 = active low level-sensitive.
+
+- gpio-controller: marks the device node as a gpio controller
+
+- ngpios: number of GPIOs this controller has
+
+- #gpio-cells: Should be two. The first cell is the pin number. The
+  second cell is reserved for flags, unused at the moment.
+
+Example:
+
+		gpio0: gpio@d0018100 {
+			compatible = "marvell,armadaxp-gpio";
+			reg = <0xd0018100 0x40>,
+			    <0xd0018800 0x30>;
+			ngpios = <32>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			interrupts = <16>, <17>, <18>, <19>;
+		};
diff --git a/Documentation/devicetree/bindings/gpio/gpio-samsung.txt b/Documentation/devicetree/bindings/gpio/gpio-samsung.txt
index 5375625..f1e5dfe 100644
--- a/Documentation/devicetree/bindings/gpio/gpio-samsung.txt
+++ b/Documentation/devicetree/bindings/gpio/gpio-samsung.txt
@@ -39,3 +39,46 @@ Example:
 		#gpio-cells = <4>;
 		gpio-controller;
 	};
+
+
+Samsung S3C24XX GPIO Controller
+
+Required properties:
+- compatible: Compatible property value should be "samsung,s3c24xx-gpio".
+
+- reg: Physical base address of the controller and length of memory mapped
+  region.
+
+- #gpio-cells: Should be 3. The syntax of the gpio specifier used by client nodes
+  should be the following with values derived from the SoC user manual.
+     <[phandle of the gpio controller node]
+      [pin number within the gpio controller]
+      [mux function]
+      [flags and pull up/down]
+
+  Values for gpio specifier:
+  - Pin number: depending on the controller a number from 0 up to 15.
+  - Mux function: Depending on the SoC and the gpio bank the gpio can be set
+                  as input, output or a special function
+  - Flags and Pull Up/Down: the values to use differ for the individual SoCs
+                    example S3C2416/S3C2450:
+                            0 - Pull Up/Down Disabled.
+                            1 - Pull Down Enabled.
+                            2 - Pull Up Enabled.
+          Bit 16 (0x00010000) - Input is active low.
+  Consult the user manual for the correct values of Mux and Pull Up/Down.
+
+- gpio-controller: Specifies that the node is a gpio controller.
+- #address-cells: should be 1.
+- #size-cells: should be 1.
+
+Example:
+
+	gpa: gpio-controller@56000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "samsung,s3c24xx-gpio";
+		reg = <0x56000000 0x10>;
+		#gpio-cells = <3>;
+		gpio-controller;
+	};
diff --git a/Documentation/devicetree/bindings/gpio/gpio-twl4030.txt b/Documentation/devicetree/bindings/gpio/gpio-twl4030.txt
index 16695d9..66788fd 100644
--- a/Documentation/devicetree/bindings/gpio/gpio-twl4030.txt
+++ b/Documentation/devicetree/bindings/gpio/gpio-twl4030.txt
@@ -11,6 +11,11 @@ Required properties:
 - interrupt-controller: Mark the device node as an interrupt controller
   The first cell is the GPIO number.
   The second cell is not used.
+- ti,use-leds : Enables LEDA and LEDB outputs if set
+- ti,debounce : if n-th bit is set, debounces GPIO-n
+- ti,mmc-cd : if n-th bit is set, GPIO-n controls VMMC(n+1)
+- ti,pullups : if n-th bit is set, set a pullup on GPIO-n
+- ti,pulldowns : if n-th bit is set, set a pulldown on GPIO-n
 
 Example:
 
@@ -20,4 +25,5 @@ twl_gpio: gpio {
     gpio-controller;
     #interrupt-cells = <2>;
     interrupt-controller;
+    ti,use-leds;
 };
diff --git a/Documentation/devicetree/bindings/gpio/gpio-vt8500.txt b/Documentation/devicetree/bindings/gpio/gpio-vt8500.txt
new file mode 100644
index 0000000..f4dc523
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/gpio-vt8500.txt
@@ -0,0 +1,24 @@
+VIA/Wondermedia VT8500 GPIO Controller
+-----------------------------------------------------
+
+Required properties:
+- compatible : "via,vt8500-gpio", "wm,wm8505-gpio"
+	or "wm,wm8650-gpio" depending on your SoC
+- reg : Should contain 1 register range (address and length)
+- #gpio-cells : should be <3>.
+	1) bank
+	2) pin number
+	3) flags - should be 0
+
+Example:
+
+	gpio: gpio-controller@d8110000 {
+		compatible = "via,vt8500-gpio";
+		gpio-controller;
+		reg = <0xd8110000 0x10000>;
+		#gpio-cells = <3>;
+	};
+
+	vibrate {
+		gpios = <&gpio 0 1 0>; /* Bank 0, Pin 1, No flags */
+	};
diff --git a/Documentation/devicetree/bindings/gpio/led.txt b/Documentation/devicetree/bindings/gpio/led.txt
index 9bb308a..edc83c1 100644
--- a/Documentation/devicetree/bindings/gpio/led.txt
+++ b/Documentation/devicetree/bindings/gpio/led.txt
@@ -8,7 +8,7 @@ node's name represents the name of the corresponding LED.
 
 LED sub-node properties:
 - gpios :  Should specify the LED's GPIO, see "gpios property" in
-  Documentation/devicetree/gpio.txt.  Active low LEDs should be
+  Documentation/devicetree/bindings/gpio/gpio.txt.  Active low LEDs should be
   indicated using flags in the GPIO specifier.
 - label :  (optional) The label for this LED.  If omitted, the label is
   taken from the node name (excluding the unit address).
diff --git a/Documentation/devicetree/bindings/i2c/atmel-i2c.txt b/Documentation/devicetree/bindings/i2c/atmel-i2c.txt
new file mode 100644
index 0000000..b689a0d
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/atmel-i2c.txt
@@ -0,0 +1,30 @@
+I2C for Atmel platforms
+
+Required properties :
+- compatible : Must be "atmel,at91rm9200-i2c", "atmel,at91sam9261-i2c",
+     "atmel,at91sam9260-i2c", "atmel,at91sam9g20-i2c", "atmel,at91sam9g10-i2c"
+     or "atmel,at91sam9x5-i2c"
+- reg: physical base address of the controller and length of memory mapped
+     region.
+- interrupts: interrupt number to the cpu.
+- #address-cells = <1>;
+- #size-cells = <0>;
+
+Optional properties:
+- Child nodes conforming to i2c bus binding
+
+Examples :
+
+i2c0: i2c@fff84000 {
+	compatible = "atmel,at91sam9g20-i2c";
+	reg = <0xfff84000 0x100>;
+	interrupts = <12 4 6>;
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	24c512@50 {
+		compatible = "24c512";
+		reg = <0x50>;
+		pagesize = <128>;
+	}
+}
diff --git a/Documentation/devicetree/bindings/i2c/davinci.txt b/Documentation/devicetree/bindings/i2c/davinci.txt
new file mode 100644
index 0000000..2dc935b
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/davinci.txt
@@ -0,0 +1,28 @@
+* Texas Instruments Davinci I2C
+
+This file provides information, what the device node for the
+davinci i2c interface contain.
+
+Required properties:
+- compatible: "ti,davinci-i2c";
+- reg : Offset and length of the register set for the device
+
+Recommended properties :
+- interrupts : standard interrupt property.
+- clock-frequency : desired I2C bus clock frequency in Hz.
+
+Example (enbw_cmc board):
+	i2c@1c22000 {
+		compatible = "ti,davinci-i2c";
+		reg = <0x22000 0x1000>;
+		clock-frequency = <100000>;
+		interrupts = <15>;
+		interrupt-parent = <&intc>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		dtt@48 {
+			compatible = "national,lm75";
+			reg = <0x48>;
+		};
+	};
diff --git a/Documentation/devicetree/bindings/i2c/trivial-devices.txt b/Documentation/devicetree/bindings/i2c/trivial-devices.txt
index 1a85f98..2f5322b 100644
--- a/Documentation/devicetree/bindings/i2c/trivial-devices.txt
+++ b/Documentation/devicetree/bindings/i2c/trivial-devices.txt
@@ -56,3 +56,4 @@ stm,m41t00		Serial Access TIMEKEEPER
 stm,m41t62		Serial real-time clock (RTC) with alarm
 stm,m41t80		M41T80 - SERIAL ACCESS RTC WITH ALARMS
 ti,tsc2003		I2C Touch-Screen Controller
+ti,tmp102		Low Power Digital Temperature Sensor with SMBUS/Two Wire Serial Interface
diff --git a/Documentation/devicetree/bindings/input/gpio-keys-polled.txt b/Documentation/devicetree/bindings/input/gpio-keys-polled.txt
new file mode 100644
index 0000000..313abef
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/gpio-keys-polled.txt
@@ -0,0 +1,38 @@
+Device-Tree bindings for input/gpio_keys_polled.c keyboard driver
+
+Required properties:
+	- compatible = "gpio-keys-polled";
+	- poll-interval: Poll interval time in milliseconds
+
+Optional properties:
+	- autorepeat: Boolean, Enable auto repeat feature of Linux input
+	  subsystem.
+
+Each button (key) is represented as a sub-node of "gpio-keys-polled":
+Subnode properties:
+
+	- gpios: OF device-tree gpio specification.
+	- label: Descriptive name of the key.
+	- linux,code: Keycode to emit.
+
+Optional subnode-properties:
+	- linux,input-type: Specify event type this button/key generates.
+	  If not specified defaults to <1> == EV_KEY.
+	- debounce-interval: Debouncing interval time in milliseconds.
+	  If not specified defaults to 5.
+	- gpio-key,wakeup: Boolean, button can wake-up the system.
+
+Example nodes:
+
+	gpio_keys_polled {
+			compatible = "gpio-keys-polled";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			poll-interval = <100>;
+			autorepeat;
+			button@21 {
+				label = "GPIO Key UP";
+				linux,code = <103>;
+				gpios = <&gpio1 0 1>;
+			};
+			...
diff --git a/Documentation/devicetree/bindings/input/rotary-encoder.txt b/Documentation/devicetree/bindings/input/rotary-encoder.txt
new file mode 100644
index 0000000..3315495
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/rotary-encoder.txt
@@ -0,0 +1,36 @@
+Rotary encoder DT bindings
+
+Required properties:
+- gpios: a spec for two GPIOs to be used
+
+Optional properties:
+- linux,axis: the input subsystem axis to map to this rotary encoder.
+  Defaults to 0 (ABS_X / REL_X)
+- rotary-encoder,steps: Number of steps in a full turnaround of the
+  encoder. Only relevant for absolute axis. Defaults to 24 which is a
+  typical value for such devices.
+- rotary-encoder,relative-axis: register a relative axis rather than an
+  absolute one. Relative axis will only generate +1/-1 events on the input
+  device, hence no steps need to be passed.
+- rotary-encoder,rollover: Automatic rollove when the rotary value becomes
+  greater than the specified steps or smaller than 0. For absolute axis only.
+- rotary-encoder,half-period: Makes the driver work on half-period mode.
+
+See Documentation/input/rotary-encoder.txt for more information.
+
+Example:
+
+		rotary@0 {
+			compatible = "rotary-encoder";
+			gpios = <&gpio 19 1>, <&gpio 20 0>; /* GPIO19 is inverted */
+			linux,axis = <0>; /* REL_X */
+			rotary-encoder,relative-axis;
+		};
+
+		rotary@1 {
+			compatible = "rotary-encoder";
+			gpios = <&gpio 21 0>, <&gpio 22 0>;
+			linux,axis = <1>; /* ABS_Y */
+			rotary-encoder,steps = <24>;
+			rotary-encoder,rollover;
+		};
diff --git a/Documentation/devicetree/bindings/interrupt-controller/brcm,bcm2835-armctrl-ic.txt b/Documentation/devicetree/bindings/interrupt-controller/brcm,bcm2835-armctrl-ic.txt
new file mode 100644
index 0000000..548892c
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/brcm,bcm2835-armctrl-ic.txt
@@ -0,0 +1,110 @@
+BCM2835 Top-Level ("ARMCTRL") Interrupt Controller
+
+The BCM2835 contains a custom top-level interrupt controller, which supports
+72 interrupt sources using a 2-level register scheme. The interrupt
+controller, or the HW block containing it, is referred to occasionally
+as "armctrl" in the SoC documentation, hence naming of this binding.
+
+Required properties:
+
+- compatible : should be "brcm,bcm2835-armctrl-ic.txt"
+- reg : Specifies base physical address and size of the registers.
+- interrupt-controller : Identifies the node as an interrupt controller
+- #interrupt-cells : Specifies the number of cells needed to encode an
+  interrupt source. The value shall be 2.
+
+  The 1st cell is the interrupt bank; 0 for interrupts in the "IRQ basic
+  pending" register, or 1/2 respectively for interrupts in the "IRQ pending
+  1/2" register.
+
+  The 2nd cell contains the interrupt number within the bank. Valid values
+  are 0..7 for bank 0, and 0..31 for bank 1.
+
+The interrupt sources are as follows:
+
+Bank 0:
+0: ARM_TIMER
+1: ARM_MAILBOX
+2: ARM_DOORBELL_0
+3: ARM_DOORBELL_1
+4: VPU0_HALTED
+5: VPU1_HALTED
+6: ILLEGAL_TYPE0
+7: ILLEGAL_TYPE1
+
+Bank 1:
+0: TIMER0
+1: TIMER1
+2: TIMER2
+3: TIMER3
+4: CODEC0
+5: CODEC1
+6: CODEC2
+7: VC_JPEG
+8: ISP
+9: VC_USB
+10: VC_3D
+11: TRANSPOSER
+12: MULTICORESYNC0
+13: MULTICORESYNC1
+14: MULTICORESYNC2
+15: MULTICORESYNC3
+16: DMA0
+17: DMA1
+18: VC_DMA2
+19: VC_DMA3
+20: DMA4
+21: DMA5
+22: DMA6
+23: DMA7
+24: DMA8
+25: DMA9
+26: DMA10
+27: DMA11
+28: DMA12
+29: AUX
+30: ARM
+31: VPUDMA
+
+Bank 2:
+0: HOSTPORT
+1: VIDEOSCALER
+2: CCP2TX
+3: SDC
+4: DSI0
+5: AVE
+6: CAM0
+7: CAM1
+8: HDMI0
+9: HDMI1
+10: PIXELVALVE1
+11: I2CSPISLV
+12: DSI1
+13: PWA0
+14: PWA1
+15: CPR
+16: SMI
+17: GPIO0
+18: GPIO1
+19: GPIO2
+20: GPIO3
+21: VC_I2C
+22: VC_SPI
+23: VC_I2SPCM
+24: VC_SDIO
+25: VC_UART
+26: SLIMBUS
+27: VEC
+28: CPG
+29: RNG
+30: VC_ARASANSDIO
+31: AVSPMON
+
+Example:
+
+intc: interrupt-controller {
+	compatible = "brcm,bcm2835-armctrl-ic";
+	reg = <0x7e00b200 0x200>;
+	interrupt-controller;
+	#interrupt-cells = <2>;
+};
diff --git a/Documentation/devicetree/bindings/lpddr2/lpddr2-timings.txt b/Documentation/devicetree/bindings/lpddr2/lpddr2-timings.txt
new file mode 100644
index 0000000..9ceb19e
--- /dev/null
+++ b/Documentation/devicetree/bindings/lpddr2/lpddr2-timings.txt
@@ -0,0 +1,52 @@
+* AC timing parameters of LPDDR2(JESD209-2) memories for a given speed-bin
+
+Required properties:
+- compatible : Should be "jedec,lpddr2-timings"
+- min-freq : minimum DDR clock frequency for the speed-bin. Type is <u32>
+- max-freq : maximum DDR clock frequency for the speed-bin. Type is <u32>
+
+Optional properties:
+
+The following properties represent AC timing parameters from the memory
+data-sheet of the device for a given speed-bin. All these properties are
+of type <u32> and the default unit is ps (pico seconds). Parameters with
+a different unit have a suffix indicating the unit such as 'tRAS-max-ns'
+- tRCD
+- tWR
+- tRAS-min
+- tRRD
+- tWTR
+- tXP
+- tRTP
+- tDQSCK-max
+- tFAW
+- tZQCS
+- tZQinit
+- tRPab
+- tZQCL
+- tCKESR
+- tRAS-max-ns
+- tDQSCK-max-derated
+
+Example:
+
+timings_elpida_ECB240ABACN_400mhz: lpddr2-timings@0 {
+	compatible	= "jedec,lpddr2-timings";
+	min-freq	= <10000000>;
+	max-freq	= <400000000>;
+	tRPab		= <21000>;
+	tRCD		= <18000>;
+	tWR		= <15000>;
+	tRAS-min	= <42000>;
+	tRRD		= <10000>;
+	tWTR		= <7500>;
+	tXP		= <7500>;
+	tRTP		= <7500>;
+	tCKESR		= <15000>;
+	tDQSCK-max	= <5500>;
+	tFAW		= <50000>;
+	tZQCS		= <90000>;
+	tZQCL		= <360000>;
+	tZQinit		= <1000000>;
+	tRAS-max-ns	= <70000>;
+};
diff --git a/Documentation/devicetree/bindings/lpddr2/lpddr2.txt b/Documentation/devicetree/bindings/lpddr2/lpddr2.txt
new file mode 100644
index 0000000..58354a0
--- /dev/null
+++ b/Documentation/devicetree/bindings/lpddr2/lpddr2.txt
@@ -0,0 +1,102 @@
+* LPDDR2 SDRAM memories compliant to JEDEC JESD209-2
+
+Required properties:
+- compatible : Should be one of - "jedec,lpddr2-nvm", "jedec,lpddr2-s2",
+  "jedec,lpddr2-s4"
+
+  "ti,jedec-lpddr2-s2" should be listed if the memory part is LPDDR2-S2 type
+
+  "ti,jedec-lpddr2-s4" should be listed if the memory part is LPDDR2-S4 type
+
+  "ti,jedec-lpddr2-nvm" should be listed if the memory part is LPDDR2-NVM type
+
+- density  : <u32> representing density in Mb (Mega bits)
+
+- io-width : <u32> representing bus width. Possible values are 8, 16, and 32
+
+Optional properties:
+
+The following optional properties represent the minimum value of some AC
+timing parameters of the DDR device in terms of number of clock cycles.
+These values shall be obtained from the device data-sheet.
+- tRRD-min-tck
+- tWTR-min-tck
+- tXP-min-tck
+- tRTP-min-tck
+- tCKE-min-tck
+- tRPab-min-tck
+- tRCD-min-tck
+- tWR-min-tck
+- tRASmin-min-tck
+- tCKESR-min-tck
+- tFAW-min-tck
+
+Child nodes:
+- The lpddr2 node may have one or more child nodes of type "lpddr2-timings".
+  "lpddr2-timings" provides AC timing parameters of the device for
+  a given speed-bin. The user may provide the timings for as many
+  speed-bins as is required. Please see Documentation/devicetree/
+  bindings/lpddr2/lpddr2-timings.txt for more information on "lpddr2-timings"
+
+Example:
+
+elpida_ECB240ABACN : lpddr2 {
+	compatible	= "Elpida,ECB240ABACN","jedec,lpddr2-s4";
+	density		= <2048>;
+	io-width	= <32>;
+
+	tRPab-min-tck	= <3>;
+	tRCD-min-tck	= <3>;
+	tWR-min-tck	= <3>;
+	tRASmin-min-tck	= <3>;
+	tRRD-min-tck	= <2>;
+	tWTR-min-tck	= <2>;
+	tXP-min-tck	= <2>;
+	tRTP-min-tck	= <2>;
+	tCKE-min-tck	= <3>;
+	tCKESR-min-tck	= <3>;
+	tFAW-min-tck	= <8>;
+
+	timings_elpida_ECB240ABACN_400mhz: lpddr2-timings@0 {
+		compatible	= "jedec,lpddr2-timings";
+		min-freq	= <10000000>;
+		max-freq	= <400000000>;
+		tRPab		= <21000>;
+		tRCD		= <18000>;
+		tWR		= <15000>;
+		tRAS-min	= <42000>;
+		tRRD		= <10000>;
+		tWTR		= <7500>;
+		tXP		= <7500>;
+		tRTP		= <7500>;
+		tCKESR		= <15000>;
+		tDQSCK-max	= <5500>;
+		tFAW		= <50000>;
+		tZQCS		= <90000>;
+		tZQCL		= <360000>;
+		tZQinit		= <1000000>;
+		tRAS-max-ns	= <70000>;
+	};
+
+	timings_elpida_ECB240ABACN_200mhz: lpddr2-timings@1 {
+		compatible	= "jedec,lpddr2-timings";
+		min-freq	= <10000000>;
+		max-freq	= <200000000>;
+		tRPab		= <21000>;
+		tRCD		= <18000>;
+		tWR		= <15000>;
+		tRAS-min	= <42000>;
+		tRRD		= <10000>;
+		tWTR		= <10000>;
+		tXP		= <7500>;
+		tRTP		= <7500>;
+		tCKESR		= <15000>;
+		tDQSCK-max	= <5500>;
+		tFAW		= <50000>;
+		tZQCS		= <90000>;
+		tZQCL		= <360000>;
+		tZQinit		= <1000000>;
+		tRAS-max-ns	= <70000>;
+	};
+
+}
diff --git a/Documentation/devicetree/bindings/media/exynos5-gsc.txt b/Documentation/devicetree/bindings/media/exynos5-gsc.txt
new file mode 100644
index 0000000..0604d42
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/exynos5-gsc.txt
@@ -0,0 +1,30 @@
+* Samsung Exynos5 G-Scaler device
+
+G-Scaler is used for scaling and color space conversion on EXYNOS5 SoCs.
+
+Required properties:
+- compatible: should be "samsung,exynos5-gsc"
+- reg: should contain G-Scaler physical address location and length.
+- interrupts: should contain G-Scaler interrupt number
+
+Example:
+
+gsc_0:  gsc@0x13e00000 {
+	compatible = "samsung,exynos5-gsc";
+	reg = <0x13e00000 0x1000>;
+	interrupts = <0 85 0>;
+};
+
+Aliases:
+Each G-Scaler node should have a numbered alias in the aliases node,
+in the form of gscN, N = 0...3. G-Scaler driver uses these aliases
+to retrieve the device IDs using "of_alias_get_id()" call.
+
+Example:
+
+aliases {
+	gsc0 =&gsc_0;
+	gsc1 =&gsc_1;
+	gsc2 =&gsc_2;
+	gsc3 =&gsc_3;
+};
diff --git a/Documentation/devicetree/bindings/memory-controllers/ti/emif.txt b/Documentation/devicetree/bindings/memory-controllers/ti/emif.txt
new file mode 100644
index 0000000..938f8e1
--- /dev/null
+++ b/Documentation/devicetree/bindings/memory-controllers/ti/emif.txt
@@ -0,0 +1,55 @@
+* EMIF family of TI SDRAM controllers
+
+EMIF - External Memory Interface - is an SDRAM controller used in
+TI SoCs. EMIF supports, based on the IP revision, one or more of
+DDR2/DDR3/LPDDR2 protocols. This binding describes a given instance
+of the EMIF IP and memory parts attached to it.
+
+Required properties:
+- compatible	: Should be of the form "ti,emif-<ip-rev>" where <ip-rev>
+  is the IP revision of the specific EMIF instance.
+
+- phy-type	: <u32> indicating the DDR phy type. Following are the
+  allowed values
+  <1>	: Attila PHY
+  <2>	: Intelli PHY
+
+- device-handle	: phandle to a "lpddr2" node representing the memory part
+
+- ti,hwmods	: For TI hwmods processing and omap device creation
+  the value shall be "emif<n>" where <n> is the number of the EMIF
+  instance with base 1.
+
+Optional properties:
+- cs1-used		: Have this property if CS1 of this EMIF
+  instance has a memory part attached to it. If there is a memory
+  part attached to CS1, it should be the same type as the one on CS0,
+  so there is no need to give the details of this memory part.
+
+- cal-resistor-per-cs	: Have this property if the board has one
+  calibration resistor per chip-select.
+
+- hw-caps-read-idle-ctrl: Have this property if the controller
+  supports read idle window programming
+
+- hw-caps-dll-calib-ctrl: Have this property if the controller
+  supports dll calibration control
+
+- hw-caps-ll-interface	: Have this property if the controller
+  has a low latency interface and corresponding interrupt events
+
+- hw-caps-temp-alert	: Have this property if the controller
+  has capability for generating SDRAM temperature alerts
+
+Example:
+
+emif1: emif@0x4c000000 {
+	compatible	= "ti,emif-4d";
+	ti,hwmods	= "emif2";
+	phy-type	= <1>;
+	device-handle	= <&elpida_ECB240ABACN>;
+	cs1-used;
+	hw-caps-read-idle-ctrl;
+	hw-caps-ll-interface;
+	hw-caps-temp-alert;
+};
diff --git a/Documentation/devicetree/bindings/mfd/ab8500.txt b/Documentation/devicetree/bindings/mfd/ab8500.txt
index 69e757a..ce83c8d 100644
--- a/Documentation/devicetree/bindings/mfd/ab8500.txt
+++ b/Documentation/devicetree/bindings/mfd/ab8500.txt
@@ -23,6 +23,7 @@ Device                     IRQ Names              Supply Names   Description
 ab8500-bm                :                      :              : Battery Manager
 ab8500-btemp             :                      :              : Battery Temperature
 ab8500-charger           :                      :              : Battery Charger
+ab8500-codec             :                      :              : Audio Codec
 ab8500-fg                :                      :              : Fuel Gauge
 ab8500-gpadc             : HW_CONV_END          : vddadc       : Analogue to Digital Converter
                            SW_CONV_END          :              :
@@ -52,6 +53,14 @@ Optional child device properties:
                            supplied in the interrupts property
 - <supply_name>-supply   : contains a phandle to the regulator supply node in Device Tree
 
+Non-standard child device properties:
+ - Audio CODEC:
+   - stericsson,amic[1|2]-type-single-ended : Single-ended Analoge Mic (default: differential)
+   - stericsson,amic1a-bias-vamic2          : Analoge Mic wishes to use a non-standard Vamic
+   - stericsson,amic1b-bias-vamic2          : Analoge Mic wishes to use a non-standard Vamic
+   - stericsson,amic2-bias-vamic1           : Analoge Mic wishes to use a non-standard Vamic
+   - stericsson,earpeice-cmv                : Earpeice voltage (only: 950 | 1100 | 1270 | 1580)
+
 ab8500@5 {
          compatible = "stericsson,ab8500";
          reg = <5>; /* mailbox 5 is i2c */
@@ -110,6 +119,12 @@ ab8500@5 {
                 compatible = "stericsson,ab8500-pwm";
         };
 
+	codec: ab8500-codec {
+		compatible = "stericsson,ab8500-codec";
+
+		stericsson,earpeice-cmv = <950>; /* Units in mV. */
+	};
+
         ab8500-regulators {
                 compatible = "stericsson,ab8500-regulator";
 
diff --git a/Documentation/devicetree/bindings/mfd/syscon.txt b/Documentation/devicetree/bindings/mfd/syscon.txt
new file mode 100644
index 0000000..fe8150b
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/syscon.txt
@@ -0,0 +1,20 @@
+* System Controller Registers R/W driver
+
+System controller node represents a register region containing a set
+of miscellaneous registers. The registers are not cohesive enough to
+represent as any specific type of device. The typical use-case is for
+some other node's driver, or platform-specific code, to acquire a
+reference to the syscon node (e.g. by phandle, node path, or search
+using a specific compatible value), interrogate the node (or associated
+OS driver) to determine the location of the registers, and access the
+registers directly.
+
+Required properties:
+- compatible: Should contain "syscon".
+- reg: the register region can be accessed from syscon
+
+Examples:
+gpr: iomuxc-gpr@020e0000 {
+	compatible = "fsl,imx6q-iomuxc-gpr", "syscon";
+	reg = <0x020e0000 0x38>;
+};
diff --git a/Documentation/devicetree/bindings/mfd/tps65910.txt b/Documentation/devicetree/bindings/mfd/tps65910.txt
index db03599..2e33048 100644
--- a/Documentation/devicetree/bindings/mfd/tps65910.txt
+++ b/Documentation/devicetree/bindings/mfd/tps65910.txt
@@ -59,6 +59,8 @@ Optional properties:
   in TPS6591X datasheet)
 - ti,en-gpio-sleep: enable sleep control for gpios
   There should be 9 entries here, one for each gpio.
+- ti,system-power-controller: Telling whether or not this pmic is controlling
+  the system power.
 
 Regulator Optional properties:
 - ti,regulator-ext-sleep-control: enable external sleep
@@ -79,6 +81,8 @@ Example:
 		#interrupt-cells = <2>;
 		interrupt-controller;
 
+		ti,system-power-controller;
+
 		ti,vmbch-threshold = 0;
 		ti,vmbch2-threshold = 0;
 		ti,en-ck32k-xtal;
diff --git a/Documentation/devicetree/bindings/mfd/twl4030-audio.txt b/Documentation/devicetree/bindings/mfd/twl4030-audio.txt
new file mode 100644
index 0000000..414d2ae
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/twl4030-audio.txt
@@ -0,0 +1,46 @@
+Texas Instruments TWL family (twl4030) audio module
+
+The audio module inside the TWL family consist of an audio codec and a vibra
+driver.
+
+Required properties:
+- compatible : must be "ti,twl4030-audio"
+
+Optional properties, nodes:
+
+Audio functionality:
+- codec { }: Need to be present if the audio functionality is used. Within this
+	     section the following options can be used:
+- ti,digimic_delay: Delay need after enabling the digimic to reduce artifacts
+		    from the start of the recorded sample (in ms)
+-ti,ramp_delay_value: HS ramp delay configuration to reduce pop noise
+-ti,hs_extmute: Use external mute for HS pop reduction
+-ti,hs_extmute_gpio: Use external GPIO to control the external mute
+-ti,offset_cncl_path: Offset cancellation path selection, refer to TRM for the
+		      valid values.
+
+Vibra functionality
+- ti,enable-vibra: Need to be set to <1> if the vibra functionality is used. if
+		   missing or it is 0, the vibra functionality is disabled.
+
+Example:
+&i2c1 {
+	clock-frequency = <2600000>;
+
+	twl: twl@48 {
+		reg = <0x48>;
+		interrupts = <7>; /* SYS_NIRQ cascaded to intc */
+		interrupt-parent = <&intc>;
+
+		twl_audio: audio {
+			compatible = "ti,twl4030-audio";
+
+			ti,enable-vibra = <1>;
+
+			codec {
+				ti,ramp_delay_value = <3>;
+			};
+
+		};
+	};
+};
diff --git a/Documentation/devicetree/bindings/mfd/twl6040.txt b/Documentation/devicetree/bindings/mfd/twl6040.txt
index c855240..0f5dd70 100644
--- a/Documentation/devicetree/bindings/mfd/twl6040.txt
+++ b/Documentation/devicetree/bindings/mfd/twl6040.txt
@@ -1,7 +1,7 @@
 Texas Instruments TWL6040 family
 
-The TWL6040s are 8-channel high quality low-power audio codecs providing audio
-and vibra functionality on OMAP4+ platforms.
+The TWL6040s are 8-channel high quality low-power audio codecs providing audio,
+vibra and GPO functionality on OMAP4+ platforms.
 They are connected ot the host processor via i2c for commands, McPDM for audio
 data and commands.
 
@@ -10,6 +10,8 @@ Required properties:
 - reg: must be 0x4b for i2c address
 - interrupts: twl6040 has one interrupt line connecteded to the main SoC
 - interrupt-parent: The parent interrupt controller
+- gpio-controller:
+- #gpio-cells = <1>: twl6040 provides GPO lines.
 - twl6040,audpwron-gpio: Power on GPIO line for the twl6040
 
 - vio-supply: Regulator for the twl6040 VIO supply
@@ -37,7 +39,6 @@ Example:
 &i2c1 {
 	twl6040: twl@4b {
 		compatible = "ti,twl6040";
-		reg = <0x4b>;
 
 		interrupts = <0 119 4>;
 		interrupt-parent = <&gic>;
@@ -60,3 +61,5 @@ Example:
 		};
 	};
 };
+
+/include/ "twl6040.dtsi"
diff --git a/Documentation/devicetree/bindings/misc/at25.txt b/Documentation/devicetree/bindings/misc/at25.txt
index ab3c327..1d34471 100644
--- a/Documentation/devicetree/bindings/misc/at25.txt
+++ b/Documentation/devicetree/bindings/misc/at25.txt
@@ -1,21 +1,35 @@
-Atmel AT25 eeprom
+EEPROMs (SPI) compatible with Atmel at25.
 
 Required properties:
 - compatible : "atmel,at25".
 - reg : chip select number
 - spi-max-frequency : max spi frequency to use
+- pagesize : size of the eeprom page
+- size : total eeprom size in bytes
+- address-width : number of address bits (one of 8, 16, or 24)
 
+Optional properties:
+- spi-cpha : SPI shifted clock phase, as per spi-bus bindings.
+- spi-cpol : SPI inverse clock polarity, as per spi-bus bindings.
+- read-only : this parameter-less property disables writes to the eeprom
+
+Obsolete legacy properties are can be used in place of "size", "pagesize",
+"address-width", and "read-only":
 - at25,byte-len : total eeprom size in bytes
 - at25,addr-mode : addr-mode flags, as defined in include/linux/spi/eeprom.h
 - at25,page-size : size of the eeprom page
 
-Examples:
-at25@0 {
-	compatible = "atmel,at25";
-	reg = <0>
-	spi-max-frequency = <5000000>;
+Additional compatible properties are also allowed.
+
+Example:
+	at25@0 {
+		compatible = "atmel,at25", "st,m95256";
+		reg = <0>
+		spi-max-frequency = <5000000>;
+		spi-cpha;
+		spi-cpol;
 
-	at25,byte-len = <0x8000>;
-	at25,addr-mode = <2>;
-	at25,page-size = <64>;
-};
+		pagesize = <64>;
+		size = <32768>;
+		address-width = <16>;
+	};
diff --git a/Documentation/devicetree/bindings/misc/ifm-csi.txt b/Documentation/devicetree/bindings/misc/ifm-csi.txt
new file mode 100644
index 0000000..5bdfffb
--- /dev/null
+++ b/Documentation/devicetree/bindings/misc/ifm-csi.txt
@@ -0,0 +1,41 @@
+IFM camera sensor interface on mpc5200 LocalPlus bus
+
+Required properties:
+- compatible: "ifm,o2d-csi"
+- reg: specifies sensor chip select number and associated address range
+- interrupts: external interrupt line number and interrupt sense mode
+  of the interrupt line signaling frame valid events
+- gpios: three gpio-specifiers for "capture", "reset" and "master enable"
+  GPIOs (strictly in this order).
+- ifm,csi-clk-handle: the phandle to a node in the DT describing the sensor
+  clock generator. This node is usually a general purpose timer controller.
+- ifm,csi-addr-bus-width: address bus width (valid values are 16, 24, 25)
+- ifm,csi-data-bus-width: data bus width (valid values are 8 and 16)
+- ifm,csi-wait-cycles: sensor bus wait cycles
+
+Optional properties:
+- ifm,csi-byte-swap: if this property is present, the byte swapping on
+  the bus will be enabled.
+
+Example:
+
+	csi@3,0 {
+		compatible = "ifm,o2d-csi";
+		reg = <3 0 0x00100000>;		/* CS 3, 1 MiB range */
+		interrupts = <1 1 2>;		/* IRQ1, edge falling */
+
+		ifm,csi-clk-handle = <&timer7>;
+		gpios = <&gpio_simple 23 0	/* image_capture */
+			 &gpio_simple 26 0	/* image_reset */
+			 &gpio_simple 29 0>;	/* image_master_en */
+
+		ifm,csi-addr-bus-width = <24>;
+		ifm,csi-data-bus-width = <8>;
+		ifm,csi-wait-cycles = <0>;
+	};
+
+The base address of the used chip select is specified in the
+ranges property of the parent localbus node, for example:
+
+	ranges = <0 0 0xff000000 0x01000000
+		  3 0 0xe3000000 0x00100000>;
diff --git a/Documentation/devicetree/bindings/misc/lis302.txt b/Documentation/devicetree/bindings/misc/lis302.txt
new file mode 100644
index 0000000..6def86f
--- /dev/null
+++ b/Documentation/devicetree/bindings/misc/lis302.txt
@@ -0,0 +1,112 @@
+LIS302 accelerometer devicetree bindings
+
+This device is matched via its bus drivers, and has a number of properties
+that apply in on the generic device (independent from the bus).
+
+
+Required properties for the SPI bindings:
+ - compatible: 		should be set to "st,lis3lv02d_spi"
+ - reg:			the chipselect index
+ - spi-max-frequency:	maximal bus speed, should be set to 1000000 unless
+			constrained by external circuitry
+ - interrupts:		the interrupt generated by the device
+
+Required properties for the I2C bindings:
+ - compatible:		should be set to "st,lis3lv02d"
+ - reg:			i2c slave address
+ - Vdd-supply:		The input supply for Vdd
+ - Vdd_IO-supply:	The input supply for Vdd_IO
+
+
+Optional properties for all bus drivers:
+
+ - st,click-single-{x,y,z}:	if present, tells the device to issue an
+				interrupt on single click events on the
+				x/y/z axis.
+ - st,click-double-{x,y,z}:	if present, tells the device to issue an
+				interrupt on double click events on the
+				x/y/z axis.
+ - st,click-thresh-{x,y,z}:	set the x/y/z axis threshold
+ - st,click-click-time-limit:	click time limit, from 0 to 127.5msec
+				with step of 0.5 msec
+ - st,click-latency:		click latency, from 0 to 255 msec with
+				step of 1 msec.
+ - st,click-window:		click window, from 0 to 255 msec with
+				step of 1 msec.
+ - st,irq{1,2}-disable:		disable IRQ 1/2
+ - st,irq{1,2}-ff-wu-1:		raise IRQ 1/2 on FF_WU_1 condition
+ - st,irq{1,2}-ff-wu-2:		raise IRQ 1/2 on FF_WU_2 condition
+ - st,irq{1,2}-data-ready:	raise IRQ 1/2 on data ready contition
+ - st,irq{1,2}-click:		raise IRQ 1/2 on click condition
+ - st,irq-open-drain:		consider IRQ lines open-drain
+ - st,irq-active-low:		make IRQ lines active low
+ - st,wu-duration-1:		duration register for Free-Fall/Wake-Up
+				interrupt 1
+ - st,wu-duration-2:		duration register for Free-Fall/Wake-Up
+				interrupt 2
+ - st,wakeup-{x,y,z}-{lo,hi}:	set wakeup condition on x/y/z axis for
+				upper/lower limit
+ - st,highpass-cutoff-hz=:	1, 2, 4 or 8 for 1Hz, 2Hz, 4Hz or 8Hz of
+				highpass cut-off frequency
+ - st,hipass{1,2}-disable:	disable highpass 1/2.
+ - st,default-rate=:		set the default rate
+ - st,axis-{x,y,z}=:		set the axis to map to the three coordinates
+ - st,{min,max}-limit-{x,y,z}	set the min/max limits for x/y/z axis
+				(used by self-test)
+
+
+Example for a SPI device node:
+
+	lis302@0 {
+		compatible = "st,lis302dl-spi";
+		reg = <0>;
+		spi-max-frequency = <1000000>;
+		interrupt-parent = <&gpio>;
+		interrupts = <104 0>;
+
+		st,click-single-x;
+		st,click-single-y;
+		st,click-single-z;
+		st,click-thresh-x = <10>;
+		st,click-thresh-y = <10>;
+		st,click-thresh-z = <10>;
+		st,irq1-click;
+		st,irq2-click;
+		st,wakeup-x-lo;
+		st,wakeup-x-hi;
+		st,wakeup-y-lo;
+		st,wakeup-y-hi;
+		st,wakeup-z-lo;
+		st,wakeup-z-hi;
+	};
+
+Example for a I2C device node:
+
+	lis331dlh: lis331dlh@18 {
+		compatible = "st,lis331dlh", "st,lis3lv02d";
+		reg = <0x18>;
+		Vdd-supply = <&lis3_reg>;
+		Vdd_IO-supply = <&lis3_reg>;
+
+		st,click-single-x;
+		st,click-single-y;
+		st,click-single-z;
+		st,click-thresh-x = <10>;
+		st,click-thresh-y = <10>;
+		st,click-thresh-z = <10>;
+		st,irq1-click;
+		st,irq2-click;
+		st,wakeup-x-lo;
+		st,wakeup-x-hi;
+		st,wakeup-y-lo;
+		st,wakeup-y-hi;
+		st,wakeup-z-lo;
+		st,wakeup-z-hi;
+		st,min-limit-x = <120>;
+		st,min-limit-y = <120>;
+		st,min-limit-z = <140>;
+		st,max-limit-x = <550>;
+		st,max-limit-y = <550>;
+		st,max-limit-z = <750>;
+	};
+
diff --git a/Documentation/devicetree/bindings/mmc/atmel-hsmci.txt b/Documentation/devicetree/bindings/mmc/atmel-hsmci.txt
new file mode 100644
index 0000000..0a85c70
--- /dev/null
+++ b/Documentation/devicetree/bindings/mmc/atmel-hsmci.txt
@@ -0,0 +1,68 @@
+* Atmel High Speed MultiMedia Card Interface
+
+This controller on atmel products provides an interface for MMC, SD and SDIO
+types of memory cards.
+
+This file documents differences between the core properties described
+by mmc.txt and the properties used by the atmel-mci driver.
+
+1) MCI node
+
+Required properties:
+- compatible: should be "atmel,hsmci"
+- #address-cells: should be one. The cell is the slot id.
+- #size-cells: should be zero.
+- at least one slot node
+
+The node contains child nodes for each slot that the platform uses
+
+Example MCI node:
+
+mmc0: mmc@f0008000 {
+	compatible = "atmel,hsmci";
+	reg = <0xf0008000 0x600>;
+	interrupts = <12 4>;
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	[ child node definitions...]
+};
+
+2) slot nodes
+
+Required properties:
+- reg: should contain the slot id.
+- bus-width: number of data lines connected to the controller
+
+Optional properties:
+- cd-gpios: specify GPIOs for card detection
+- cd-inverted: invert the value of external card detect gpio line
+- wp-gpios: specify GPIOs for write protection
+
+Example slot node:
+
+slot@0 {
+	reg = <0>;
+	bus-width = <4>;
+	cd-gpios = <&pioD 15 0>
+	cd-inverted;
+};
+
+Example full MCI node:
+mmc0: mmc@f0008000 {
+	compatible = "atmel,hsmci";
+	reg = <0xf0008000 0x600>;
+	interrupts = <12 4>;
+	#address-cells = <1>;
+	#size-cells = <0>;
+	slot@0 {
+		reg = <0>;
+		bus-width = <4>;
+		cd-gpios = <&pioD 15 0>
+		cd-inverted;
+	};
+	slot@1 {
+		reg = <1>;
+		bus-width = <4>;
+	};
+};
diff --git a/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt
new file mode 100644
index 0000000..7927689
--- /dev/null
+++ b/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt
@@ -0,0 +1,87 @@
+* Samsung Exynos specific extensions to the Synopsis Designware Mobile
+  Storage Host Controller
+
+The Synopsis designware mobile storage host controller is used to interface
+a SoC with storage medium such as eMMC or SD/MMC cards. This file documents
+differences between the core Synopsis dw mshc controller properties described
+by synposis-dw-mshc.txt and the properties used by the Samsung Exynos specific
+extensions to the Synopsis Designware Mobile Storage Host Controller.
+
+Required Properties:
+
+* compatible: should be
+	- "samsung,exynos4210-dw-mshc": for controllers with Samsung Exynos4210
+	  specific extentions.
+	- "samsung,exynos4412-dw-mshc": for controllers with Samsung Exynos4412
+	  specific extentions.
+	- "samsung,exynos5250-dw-mshc": for controllers with Samsung Exynos5250
+	  specific extentions.
+
+* samsung,dw-mshc-ciu-div: Specifies the divider value for the card interface
+  unit (ciu) clock. This property is applicable only for Exynos5 SoC's and
+  ignored for Exynos4 SoC's. The valid range of divider value is 0 to 7.
+
+* samsung,dw-mshc-sdr-timing: Specifies the value of CIU clock phase shift value
+  in transmit mode and CIU clock phase shift value in receive mode for single
+  data rate mode operation. Refer notes below for the order of the cells and the
+  valid values.
+
+* samsung,dw-mshc-ddr-timing: Specifies the value of CUI clock phase shift value
+  in transmit mode and CIU clock phase shift value in receive mode for double
+  data rate mode operation. Refer notes below for the order of the cells and the
+  valid values.
+
+  Notes for the sdr-timing and ddr-timing values:
+
+    The order of the cells should be
+      - First Cell: CIU clock phase shift value for tx mode.
+      - Second Cell: CIU clock phase shift value for rx mode.
+
+    Valid values for SDR and DDR CIU clock timing for Exynos5250:
+      - valid value for tx phase shift and rx phase shift is 0 to 7.
+      - when CIU clock divider value is set to 3, all possible 8 phase shift
+        values can be used.
+      - if CIU clock divider value is 0 (that is divide by 1), both tx and rx
+        phase shift clocks should be 0.
+
+Required properties for a slot:
+
+* gpios: specifies a list of gpios used for command, clock and data bus. The
+  first gpio is the command line and the second gpio is the clock line. The
+  rest of the gpios (depending on the bus-width property) are the data lines in
+  no particular order. The format of the gpio specifier depends on the gpio
+  controller.
+
+Example:
+
+  The MSHC controller node can be split into two portions, SoC specific and
+  board specific portions as listed below.
+
+	dwmmc0@12200000 {
+		compatible = "samsung,exynos5250-dw-mshc";
+		reg = <0x12200000 0x1000>;
+		interrupts = <0 75 0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+	};
+
+	dwmmc0@12200000 {
+		num-slots = <1>;
+		supports-highspeed;
+		broken-cd;
+		fifo-depth = <0x80>;
+		card-detect-delay = <200>;
+		samsung,dw-mshc-ciu-div = <3>;
+		samsung,dw-mshc-sdr-timing = <2 3>;
+		samsung,dw-mshc-ddr-timing = <1 2>;
+
+		slot@0 {
+			reg = <0>;
+			bus-width = <8>;
+			gpios = <&gpc0 0 2 0 3>, <&gpc0 1 2 0 3>,
+				<&gpc1 0 2 3 3>, <&gpc1 1 2 3 3>,
+				<&gpc1 2 2 3 3>, <&gpc1 3 2 3 3>,
+				<&gpc0 3 2 3 3>, <&gpc0 4 2 3 3>,
+				<&gpc0 5 2 3 3>, <&gpc0 6 2 3 3>;
+		};
+	};
diff --git a/Documentation/devicetree/bindings/mmc/mmc.txt b/Documentation/devicetree/bindings/mmc/mmc.txt
index 8a6811f..8e2e0ba 100644
--- a/Documentation/devicetree/bindings/mmc/mmc.txt
+++ b/Documentation/devicetree/bindings/mmc/mmc.txt
@@ -9,12 +9,17 @@ Interpreted by the OF core:
 Required properties:
 - bus-width: Number of data lines, can be <1>, <4>, or <8>
 
+Card detection:
+If no property below is supplied, standard SDHCI card detect is used.
+Only one of the properties in this section should be supplied:
+  - broken-cd: There is no card detection available; polling must be used.
+  - cd-gpios: Specify GPIOs for card detection, see gpio binding
+  - non-removable: non-removable slot (like eMMC); assume always present.
+
 Optional properties:
-- cd-gpios: Specify GPIOs for card detection, see gpio binding
 - wp-gpios: Specify GPIOs for write protection, see gpio binding
 - cd-inverted: when present, polarity on the cd gpio line is inverted
 - wp-inverted: when present, polarity on the wp gpio line is inverted
-- non-removable: non-removable slot (like eMMC)
 - max-frequency: maximum operating clock frequency
 
 Example:
diff --git a/Documentation/devicetree/bindings/mmc/pxa-mmc.txt b/Documentation/devicetree/bindings/mmc/pxa-mmc.txt
new file mode 100644
index 0000000..b7025de
--- /dev/null
+++ b/Documentation/devicetree/bindings/mmc/pxa-mmc.txt
@@ -0,0 +1,25 @@
+* PXA MMC drivers
+
+Driver bindings for the PXA MCI (MMC/SDIO) interfaces
+
+Required properties:
+- compatible: Should be "marvell,pxa-mmc".
+- vmmc-supply: A regulator for VMMC
+
+Optional properties:
+- marvell,detect-delay-ms: sets the detection delay timeout in ms.
+- marvell,gpio-power: GPIO spec for the card power enable pin
+
+This file documents differences between the core properties in mmc.txt
+and the properties used by the pxa-mmc driver.
+
+Examples:
+
+mmc0: mmc@41100000 {
+	compatible = "marvell,pxa-mmc";
+	reg = <0x41100000 0x1000>;
+	interrupts = <23>;
+	cd-gpios = <&gpio 23 0>;
+	wp-gpios = <&gpio 24 0>;
+};
+
diff --git a/Documentation/devicetree/bindings/mmc/samsung-sdhci.txt b/Documentation/devicetree/bindings/mmc/samsung-sdhci.txt
new file mode 100644
index 0000000..630a7d7
--- /dev/null
+++ b/Documentation/devicetree/bindings/mmc/samsung-sdhci.txt
@@ -0,0 +1,53 @@
+* Samsung's SDHCI Controller device tree bindings
+
+Samsung's SDHCI controller is used as a connectivity interface with external
+MMC, SD and eMMC storage mediums. This file documents differences between the
+core mmc properties described by mmc.txt and the properties used by the
+Samsung implmentation of the SDHCI controller.
+
+Note: The mmc core bindings documentation states that if none of the core
+card-detect bindings are used, then the standard sdhci card detect mechanism
+is used. The Samsung's SDHCI controller bindings extends this as listed below.
+
+[A] The property "samsung,cd-pinmux-gpio" can be used as stated in the
+    "Optional Board Specific Properties" section below.
+
+[B] If core card-detect bindings and "samsung,cd-pinmux-gpio" property
+    is not specified, it is assumed that there is no card detection
+    mechanism used.
+
+Required SoC Specific Properties:
+- compatible: should be one of the following
+  - "samsung,s3c6410-sdhci": For controllers compatible with s3c6410 sdhci
+    controller.
+  - "samsung,exynos4210-sdhci": For controllers compatible with Exynos4 sdhci
+    controller.
+
+Required Board Specific Properties:
+- gpios: Should specify the gpios used for clock, command and data lines. The
+  gpio specifier format depends on the gpio controller.
+
+Optional Board Specific Properties:
+- samsung,cd-pinmux-gpio: Specifies the card detect line that is routed
+  through a pinmux to the card-detect pin of the card slot. This property
+  should be used only if none of the mmc core card-detect properties are
+  used.
+
+Example:
+	sdhci@12530000 {
+		compatible = "samsung,exynos4210-sdhci";
+		reg = <0x12530000 0x100>;
+		interrupts = <0 75 0>;
+		bus-width = <4>;
+		cd-gpios = <&gpk2 2 2 3 3>;
+		gpios = <&gpk2 0 2 0 3>,  /* clock line */
+			<&gpk2 1 2 0 3>,  /* command line */
+			<&gpk2 3 2 3 3>,  /* data line 0 */
+			<&gpk2 4 2 3 3>,  /* data line 1 */
+			<&gpk2 5 2 3 3>,  /* data line 2 */
+			<&gpk2 6 2 3 3>;  /* data line 3 */
+	};
+
+	Note: This example shows both SoC specific and board specific properties
+	in a single device node. The properties can be actually be seperated
+	into SoC specific node and board specific node.
diff --git a/Documentation/devicetree/bindings/mmc/sdhci-dove.txt b/Documentation/devicetree/bindings/mmc/sdhci-dove.txt
new file mode 100644
index 0000000..ae9aab9
--- /dev/null
+++ b/Documentation/devicetree/bindings/mmc/sdhci-dove.txt
@@ -0,0 +1,14 @@
+* Marvell sdhci-dove controller
+
+This file documents differences between the core properties in mmc.txt
+and the properties used by the sdhci-pxav2 and sdhci-pxav3 drivers.
+
+- compatible: Should be "marvell,dove-sdhci".
+
+Example:
+
+sdio0: sdio@92000 {
+	compatible = "marvell,dove-sdhci";
+	reg = <0x92000 0x100>;
+	interrupts = <35>;
+};
diff --git a/Documentation/devicetree/bindings/mmc/synposis-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/synposis-dw-mshc.txt
new file mode 100644
index 0000000..06cd32d08
--- /dev/null
+++ b/Documentation/devicetree/bindings/mmc/synposis-dw-mshc.txt
@@ -0,0 +1,79 @@
+* Synopsis Designware Mobile Storage Host Controller
+
+The Synopsis designware mobile storage host controller is used to interface
+a SoC with storage medium such as eMMC or SD/MMC cards. This file documents
+differences between the core mmc properties described by mmc.txt and the
+properties used by the Synopsis Designware Mobile Storage Host Controller.
+
+Required Properties:
+
+* compatible: should be
+	- snps,dw-mshc: for controllers compliant with synopsis dw-mshc.
+* #address-cells: should be 1.
+* #size-cells: should be 0.
+
+# Slots: The slot specific information are contained within child-nodes with
+  each child-node representing a supported slot. There should be atleast one
+  child node representing a card slot. The name of the child node representing
+  the slot is recommended to be slot@n where n is the unique number of the slot
+  connnected to the controller. The following are optional properties which
+  can be included in the slot child node.
+
+	* reg: specifies the physical slot number. The valid values of this
+	  property is 0 to (num-slots -1), where num-slots is the value
+	  specified by the num-slots property.
+
+	* bus-width: as documented in mmc core bindings.
+
+	* wp-gpios: specifies the write protect gpio line. The format of the
+	  gpio specifier depends on the gpio controller. If the write-protect
+	  line is not available, this property is optional.
+
+Optional properties:
+
+* num-slots: specifies the number of slots supported by the controller.
+  The number of physical slots actually used could be equal or less than the
+  value specified by num-slots. If this property is not specified, the value
+  of num-slot property is assumed to be 1.
+
+* fifo-depth: The maximum size of the tx/rx fifo's. If this property is not
+  specified, the default value of the fifo size is determined from the
+  controller registers.
+
+* card-detect-delay: Delay in milli-seconds before detecting card after card
+  insert event. The default value is 0.
+
+* supports-highspeed: Enables support for high speed cards (upto 50MHz)
+
+* broken-cd: as documented in mmc core bindings.
+
+Aliases:
+
+- All the MSHC controller nodes should be represented in the aliases node using
+  the following format 'mshc{n}' where n is a unique number for the alias.
+
+Example:
+
+The MSHC controller node can be split into two portions, SoC specific and
+board specific portions as listed below.
+
+	dwmmc0@12200000 {
+		compatible = "snps,dw-mshc";
+		reg = <0x12200000 0x1000>;
+		interrupts = <0 75 0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+	};
+
+	dwmmc0@12200000 {
+		num-slots = <1>;
+		supports-highspeed;
+		broken-cd;
+		fifo-depth = <0x80>;
+		card-detect-delay = <200>;
+
+		slot@0 {
+			reg = <0>;
+			bus-width = <8>;
+		};
+	};
diff --git a/Documentation/devicetree/bindings/mtd/atmel-nand.txt b/Documentation/devicetree/bindings/mtd/atmel-nand.txt
index a200695..d555421 100644
--- a/Documentation/devicetree/bindings/mtd/atmel-nand.txt
+++ b/Documentation/devicetree/bindings/mtd/atmel-nand.txt
@@ -3,7 +3,9 @@ Atmel NAND flash
 Required properties:
 - compatible : "atmel,at91rm9200-nand".
 - reg : should specify localbus address and size used for the chip,
-	and if availlable the ECC.
+	and hardware ECC controller if available.
+	If the hardware ECC is PMECC, it should contain address and size for
+	PMECC, PMECC Error Location controller and ROM which has lookup tables.
 - atmel,nand-addr-offset : offset for the address latch.
 - atmel,nand-cmd-offset : offset for the command latch.
 - #address-cells, #size-cells : Must be present if the device has sub-nodes
@@ -16,6 +18,15 @@ Optional properties:
 - nand-ecc-mode : String, operation mode of the NAND ecc mode, soft by default.
   Supported values are: "none", "soft", "hw", "hw_syndrome", "hw_oob_first",
   "soft_bch".
+- atmel,has-pmecc : boolean to enable Programmable Multibit ECC hardware.
+  Only supported by at91sam9x5 or later sam9 product.
+- atmel,pmecc-cap : error correct capability for Programmable Multibit ECC
+  Controller. Supported values are: 2, 4, 8, 12, 24.
+- atmel,pmecc-sector-size : sector size for ECC computation. Supported values
+  are: 512, 1024.
+- atmel,pmecc-lookup-table-offset : includes two offsets of lookup table in ROM
+  for different sector size. First one is for sector size 512, the next is for
+  sector size 1024.
 - nand-bus-width : 8 or 16 bus width if not present 8
 - nand-on-flash-bbt: boolean to enable on flash bbt option if not present false
 
@@ -39,3 +50,30 @@ nand0: nand@40000000,0 {
 		...
 	};
 };
+
+/* for PMECC supported chips */
+nand0: nand@40000000 {
+	compatible = "atmel,at91rm9200-nand";
+	#address-cells = <1>;
+	#size-cells = <1>;
+	reg = < 0x40000000 0x10000000	/* bus addr & size */
+		0xffffe000 0x00000600	/* PMECC addr & size */
+		0xffffe600 0x00000200	/* PMECC ERRLOC addr & size */
+		0x00100000 0x00100000	/* ROM addr & size */
+		>;
+	atmel,nand-addr-offset = <21>;	/* ale */
+	atmel,nand-cmd-offset = <22>;	/* cle */
+	nand-on-flash-bbt;
+	nand-ecc-mode = "hw";
+	atmel,has-pmecc;	/* enable PMECC */
+	atmel,pmecc-cap = <2>;
+	atmel,pmecc-sector-size = <512>;
+	atmel,pmecc-lookup-table-offset = <0x8000 0x10000>;
+	gpios = <&pioD 5 0	/* rdy */
+		 &pioD 4 0	/* nce */
+		 0		/* cd */
+		>;
+	partition@0 {
+		...
+	};
+};
diff --git a/Documentation/devicetree/bindings/mtd/gpmi-nand.txt b/Documentation/devicetree/bindings/mtd/gpmi-nand.txt
index 1a5bbd3..3fb3f901 100644
--- a/Documentation/devicetree/bindings/mtd/gpmi-nand.txt
+++ b/Documentation/devicetree/bindings/mtd/gpmi-nand.txt
@@ -12,6 +12,10 @@ Required properties:
   - interrupt-names : The interrupt names "gpmi-dma", "bch";
   - fsl,gpmi-dma-channel : Should contain the dma channel it uses.
 
+Optional properties:
+  - nand-on-flash-bbt: boolean to enable on flash bbt option if not
+                       present false
+
 The device tree may optionally contain sub-nodes describing partitions of the
 address space. See partition.txt for more detail.
 
diff --git a/Documentation/devicetree/bindings/mtd/lpc32xx-mlc.txt b/Documentation/devicetree/bindings/mtd/lpc32xx-mlc.txt
new file mode 100644
index 0000000..d0a3725
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/lpc32xx-mlc.txt
@@ -0,0 +1,50 @@
+NXP LPC32xx SoC NAND MLC controller
+
+Required properties:
+- compatible: "nxp,lpc3220-mlc"
+- reg: Address and size of the controller
+- interrupts: The NAND interrupt specification
+- gpios: GPIO specification for NAND write protect
+
+The following required properties are very controller specific. See the LPC32xx
+User Manual 7.5.14 MLC NAND Timing Register (the values here are specified in
+Hz, to make them independent of actual clock speed and to provide for good
+accuracy:)
+- nxp,tcea_delay: TCEA_DELAY
+- nxp,busy_delay: BUSY_DELAY
+- nxp,nand_ta: NAND_TA
+- nxp,rd_high: RD_HIGH
+- nxp,rd_low: RD_LOW
+- nxp,wr_high: WR_HIGH
+- nxp,wr_low: WR_LOW
+
+Optional subnodes:
+- Partitions, see Documentation/devicetree/bindings/mtd/partition.txt
+
+Example:
+
+	mlc: flash@200A8000 {
+		compatible = "nxp,lpc3220-mlc";
+		reg = <0x200A8000 0x11000>;
+		interrupts = <11 0>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		nxp,tcea-delay = <333333333>;
+		nxp,busy-delay = <10000000>;
+		nxp,nand-ta = <18181818>;
+		nxp,rd-high = <31250000>;
+		nxp,rd-low = <45454545>;
+		nxp,wr-high = <40000000>;
+		nxp,wr-low = <83333333>;
+		gpios = <&gpio 5 19 1>; /* GPO_P3 19, active low */
+
+		mtd0@00000000 {
+			label = "boot";
+			reg = <0x00000000 0x00064000>;
+			read-only;
+		};
+
+		...
+
+	};
diff --git a/Documentation/devicetree/bindings/mtd/lpc32xx-slc.txt b/Documentation/devicetree/bindings/mtd/lpc32xx-slc.txt
new file mode 100644
index 0000000..d94edc0
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/lpc32xx-slc.txt
@@ -0,0 +1,52 @@
+NXP LPC32xx SoC NAND SLC controller
+
+Required properties:
+- compatible: "nxp,lpc3220-slc"
+- reg: Address and size of the controller
+- nand-on-flash-bbt: Use bad block table on flash
+- gpios: GPIO specification for NAND write protect
+
+The following required properties are very controller specific. See the LPC32xx
+User Manual:
+- nxp,wdr-clks: Delay before Ready signal is tested on write (W_RDY)
+- nxp,rdr-clks: Delay before Ready signal is tested on read (R_RDY)
+(The following values are specified in Hz, to make them independent of actual
+clock speed:)
+- nxp,wwidth: Write pulse width (W_WIDTH)
+- nxp,whold: Write hold time (W_HOLD)
+- nxp,wsetup: Write setup time (W_SETUP)
+- nxp,rwidth: Read pulse width (R_WIDTH)
+- nxp,rhold: Read hold time (R_HOLD)
+- nxp,rsetup: Read setup time (R_SETUP)
+
+Optional subnodes:
+- Partitions, see Documentation/devicetree/bindings/mtd/partition.txt
+
+Example:
+
+	slc: flash@20020000 {
+		compatible = "nxp,lpc3220-slc";
+		reg = <0x20020000 0x1000>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		nxp,wdr-clks = <14>;
+		nxp,wwidth = <40000000>;
+		nxp,whold = <100000000>;
+		nxp,wsetup = <100000000>;
+		nxp,rdr-clks = <14>;
+		nxp,rwidth = <40000000>;
+		nxp,rhold = <66666666>;
+		nxp,rsetup = <100000000>;
+		nand-on-flash-bbt;
+		gpios = <&gpio 5 19 1>; /* GPO_P3 19, active low */
+
+		mtd0@00000000 {
+			label = "phy3250-boot";
+			reg = <0x00000000 0x00064000>;
+			read-only;
+		};
+
+		...
+
+	};
diff --git a/Documentation/devicetree/bindings/mtd/mtd-physmap.txt b/Documentation/devicetree/bindings/mtd/mtd-physmap.txt
index a63c2bd7..94de19b 100644
--- a/Documentation/devicetree/bindings/mtd/mtd-physmap.txt
+++ b/Documentation/devicetree/bindings/mtd/mtd-physmap.txt
@@ -16,6 +16,13 @@ file systems on embedded devices.
  - #address-cells, #size-cells : Must be present if the device has
    sub-nodes representing partitions (see below).  In this case
    both #address-cells and #size-cells must be equal to 1.
+ - no-unaligned-direct-access: boolean to disable the default direct
+   mapping of the flash.
+   On some platforms (e.g. MPC5200) a direct 1:1 mapping may cause
+   problems with JFFS2 usage, as the local bus (LPB) doesn't support
+   unaligned accesses as implemented in the JFFS2 code via memcpy().
+   By defining "no-unaligned-direct-access", the flash will not be
+   exposed directly to the MTD users (e.g. JFFS2) any more.
 
 For JEDEC compatible devices, the following additional properties
 are defined:
diff --git a/Documentation/devicetree/bindings/mtd/pxa3xx-nand.txt b/Documentation/devicetree/bindings/mtd/pxa3xx-nand.txt
new file mode 100644
index 0000000..f1421e2
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/pxa3xx-nand.txt
@@ -0,0 +1,31 @@
+PXA3xx NAND DT bindings
+
+Required properties:
+
+ - compatible:		Should be "marvell,pxa3xx-nand"
+ - reg: 		The register base for the controller
+ - interrupts:		The interrupt to map
+ - #address-cells:	Set to <1> if the node includes partitions
+
+Optional properties:
+
+ - marvell,nand-enable-arbiter:	Set to enable the bus arbiter
+ - marvell,nand-keep-config:	Set to keep the NAND controller config as set
+				by the bootloader
+ - num-cs:			Number of chipselect lines to usw
+
+Example:
+
+	nand0: nand@43100000 {
+		compatible = "marvell,pxa3xx-nand";
+		reg = <0x43100000 90>;
+		interrupts = <45>;
+		#address-cells = <1>;
+
+		marvell,nand-enable-arbiter;
+		marvell,nand-keep-config;
+		num-cs = <1>;
+
+		/* partitions (optional) */
+	};
+
diff --git a/Documentation/devicetree/bindings/net/calxeda-xgmac.txt b/Documentation/devicetree/bindings/net/calxeda-xgmac.txt
index 411727a..c8ae996 100644
--- a/Documentation/devicetree/bindings/net/calxeda-xgmac.txt
+++ b/Documentation/devicetree/bindings/net/calxeda-xgmac.txt
@@ -6,6 +6,9 @@ Required properties:
 - interrupts : Should contain 3 xgmac interrupts. The 1st is main interrupt.
   The 2nd is pwr mgt interrupt. The 3rd is low power state interrupt.
 
+Optional properties:
+- dma-coherent      : Present if dma operations are coherent
+
 Example:
 
 ethernet@fff50000 {
diff --git a/Documentation/devicetree/bindings/net/can/c_can.txt b/Documentation/devicetree/bindings/net/can/c_can.txt
new file mode 100644
index 0000000..8f1ae81
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/can/c_can.txt
@@ -0,0 +1,49 @@
+Bosch C_CAN/D_CAN controller Device Tree Bindings
+-------------------------------------------------
+
+Required properties:
+- compatible		: Should be "bosch,c_can" for C_CAN controllers and
+			  "bosch,d_can" for D_CAN controllers.
+- reg			: physical base address and size of the C_CAN/D_CAN
+			  registers map
+- interrupts		: property with a value describing the interrupt
+			  number
+
+Optional properties:
+- ti,hwmods		: Must be "d_can<n>" or "c_can<n>", n being the
+			  instance number
+
+Note: "ti,hwmods" field is used to fetch the base address and irq
+resources from TI, omap hwmod data base during device registration.
+Future plan is to migrate hwmod data base contents into device tree
+blob so that, all the required data will be used from device tree dts
+file.
+
+Example:
+
+Step1: SoC common .dtsi file
+
+	dcan1: d_can@481d0000 {
+		compatible = "bosch,d_can";
+		reg = <0x481d0000 0x2000>;
+		interrupts = <55>;
+		interrupt-parent = <&intc>;
+		status = "disabled";
+	};
+
+(or)
+
+	dcan1: d_can@481d0000 {
+		compatible = "bosch,d_can";
+		ti,hwmods = "d_can1";
+		reg = <0x481d0000 0x2000>;
+		interrupts = <55>;
+		interrupt-parent = <&intc>;
+		status = "disabled";
+	};
+
+Step 2: board specific .dts file
+
+	&dcan1 {
+		status = "okay";
+	};
diff --git a/Documentation/devicetree/bindings/net/cpsw.txt b/Documentation/devicetree/bindings/net/cpsw.txt
new file mode 100644
index 0000000..dcaabe9
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/cpsw.txt
@@ -0,0 +1,109 @@
+TI SoC Ethernet Switch Controller Device Tree Bindings
+------------------------------------------------------
+
+Required properties:
+- compatible		: Should be "ti,cpsw"
+- reg			: physical base address and size of the cpsw
+			  registers map
+- interrupts		: property with a value describing the interrupt
+			  number
+- interrupt-parent	: The parent interrupt controller
+- cpdma_channels 	: Specifies number of channels in CPDMA
+- host_port_no		: Specifies host port shift
+- cpdma_reg_ofs		: Specifies CPDMA submodule register offset
+- cpdma_sram_ofs	: Specifies CPDMA SRAM offset
+- ale_reg_ofs		: Specifies ALE submodule register offset
+- ale_entries		: Specifies No of entries ALE can hold
+- host_port_reg_ofs	: Specifies host port register offset
+- hw_stats_reg_ofs	: Specifies hardware statistics register offset
+- bd_ram_ofs		: Specifies internal desciptor RAM offset
+- bd_ram_size		: Specifies internal descriptor RAM size
+- rx_descs		: Specifies number of Rx descriptors
+- mac_control		: Specifies Default MAC control register content
+			  for the specific platform
+- slaves		: Specifies number for slaves
+- slave_reg_ofs		: Specifies slave register offset
+- sliver_reg_ofs	: Specifies slave sliver register offset
+- phy_id		: Specifies slave phy id
+- mac-address		: Specifies slave MAC address
+
+Optional properties:
+- ti,hwmods		: Must be "cpgmac0"
+- no_bd_ram		: Must be 0 or 1
+
+Note: "ti,hwmods" field is used to fetch the base address and irq
+resources from TI, omap hwmod data base during device registration.
+Future plan is to migrate hwmod data base contents into device tree
+blob so that, all the required data will be used from device tree dts
+file.
+
+Examples:
+
+	mac: ethernet@4A100000 {
+		compatible = "ti,cpsw";
+		reg = <0x4A100000 0x1000>;
+		interrupts = <55 0x4>;
+		interrupt-parent = <&intc>;
+		cpdma_channels = <8>;
+		host_port_no = <0>;
+		cpdma_reg_ofs = <0x800>;
+		cpdma_sram_ofs = <0xa00>;
+		ale_reg_ofs = <0xd00>;
+		ale_entries = <1024>;
+		host_port_reg_ofs = <0x108>;
+		hw_stats_reg_ofs = <0x900>;
+		bd_ram_ofs = <0x2000>;
+		bd_ram_size = <0x2000>;
+		no_bd_ram = <0>;
+		rx_descs = <64>;
+		mac_control = <0x20>;
+		slaves = <2>;
+		cpsw_emac0: slave@0 {
+			slave_reg_ofs = <0x208>;
+			sliver_reg_ofs = <0xd80>;
+			phy_id = "davinci_mdio.16:00";
+			/* Filled in by U-Boot */
+			mac-address = [ 00 00 00 00 00 00 ];
+		};
+		cpsw_emac1: slave@1 {
+			slave_reg_ofs = <0x308>;
+			sliver_reg_ofs = <0xdc0>;
+			phy_id = "davinci_mdio.16:01";
+			/* Filled in by U-Boot */
+			mac-address = [ 00 00 00 00 00 00 ];
+		};
+	};
+
+(or)
+	mac: ethernet@4A100000 {
+		compatible = "ti,cpsw";
+		ti,hwmods = "cpgmac0";
+		cpdma_channels = <8>;
+		host_port_no = <0>;
+		cpdma_reg_ofs = <0x800>;
+		cpdma_sram_ofs = <0xa00>;
+		ale_reg_ofs = <0xd00>;
+		ale_entries = <1024>;
+		host_port_reg_ofs = <0x108>;
+		hw_stats_reg_ofs = <0x900>;
+		bd_ram_ofs = <0x2000>;
+		bd_ram_size = <0x2000>;
+		no_bd_ram = <0>;
+		rx_descs = <64>;
+		mac_control = <0x20>;
+		slaves = <2>;
+		cpsw_emac0: slave@0 {
+			slave_reg_ofs = <0x208>;
+			sliver_reg_ofs = <0xd80>;
+			phy_id = "davinci_mdio.16:00";
+			/* Filled in by U-Boot */
+			mac-address = [ 00 00 00 00 00 00 ];
+		};
+		cpsw_emac1: slave@1 {
+			slave_reg_ofs = <0x308>;
+			sliver_reg_ofs = <0xdc0>;
+			phy_id = "davinci_mdio.16:01";
+			/* Filled in by U-Boot */
+			mac-address = [ 00 00 00 00 00 00 ];
+		};
+	};
diff --git a/Documentation/devicetree/bindings/net/davinci-mdio.txt b/Documentation/devicetree/bindings/net/davinci-mdio.txt
new file mode 100644
index 0000000..72efaaf
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/davinci-mdio.txt
@@ -0,0 +1,33 @@
+TI SoC Davinci MDIO Controller Device Tree Bindings
+---------------------------------------------------
+
+Required properties:
+- compatible		: Should be "ti,davinci_mdio"
+- reg			: physical base address and size of the davinci mdio
+			  registers map
+- bus_freq		: Mdio Bus frequency
+
+Optional properties:
+- ti,hwmods		: Must be "davinci_mdio"
+
+Note: "ti,hwmods" field is used to fetch the base address and irq
+resources from TI, omap hwmod data base during device registration.
+Future plan is to migrate hwmod data base contents into device tree
+blob so that, all the required data will be used from device tree dts
+file.
+
+Examples:
+
+	mdio: davinci_mdio@4A101000 {
+		compatible = "ti,cpsw";
+		reg = <0x4A101000 0x1000>;
+		bus_freq = <1000000>;
+	};
+
+(or)
+
+	mdio: davinci_mdio@4A101000 {
+		compatible = "ti,cpsw";
+		ti,hwmods = "davinci_mdio";
+		bus_freq = <1000000>;
+	};
diff --git a/Documentation/devicetree/bindings/net/mdio-mux-mmioreg.txt b/Documentation/devicetree/bindings/net/mdio-mux-mmioreg.txt
new file mode 100644
index 0000000..8516929
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/mdio-mux-mmioreg.txt
@@ -0,0 +1,75 @@
+Properties for an MDIO bus multiplexer controlled by a memory-mapped device
+
+This is a special case of a MDIO bus multiplexer.  A memory-mapped device,
+like an FPGA, is used to control which child bus is connected.  The mdio-mux
+node must be a child of the memory-mapped device.  The driver currently only
+supports devices with eight-bit registers.
+
+Required properties in addition to the generic multiplexer properties:
+
+- compatible : string, must contain "mdio-mux-mmioreg"
+
+- reg : integer, contains the offset of the register that controls the bus
+	multiplexer.  The size field in the 'reg' property is the size of
+	register, and must therefore be 1.
+
+- mux-mask : integer, contains an eight-bit mask that specifies which
+	bits in the register control the actual bus multiplexer.  The
+	'reg' property of each child mdio-mux node must be constrained by
+	this mask.
+
+Example:
+
+The FPGA node defines a memory-mapped FPGA with a register space of 0x30 bytes.
+For the "EMI2" MDIO bus, register 9 (BRDCFG1) controls the mux on that bus.
+A bitmask of 0x6 means that bits 1 and 2 (bit 0 is lsb) are the bits on
+BRDCFG1 that control the actual mux.
+
+	/* The FPGA node */
+	fpga: board-control@3,0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "fsl,p5020ds-fpga", "fsl,fpga-ngpixis";
+		reg = <3 0 0x30>;
+		ranges = <0 3 0 0x30>;
+
+		mdio-mux-emi2 {
+			compatible = "mdio-mux-mmioreg", "mdio-mux";
+			mdio-parent-bus = <&xmdio0>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <9 1>; // BRDCFG1
+			mux-mask = <0x6>; // EMI2
+
+			emi2_slot1: mdio@0 {	// Slot 1 XAUI (FM2)
+				reg = <0>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				phy_xgmii_slot1: ethernet-phy@0 {
+					compatible = "ethernet-phy-ieee802.3-c45";
+					reg = <4>;
+				};
+			};
+
+			emi2_slot2: mdio@2 {	// Slot 2 XAUI (FM1)
+				reg = <2>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				phy_xgmii_slot2: ethernet-phy@4 {
+					compatible = "ethernet-phy-ieee802.3-c45";
+					reg = <0>;
+				};
+			};
+		};
+	};
+
+	/* The parent MDIO bus. */
+	xmdio0: mdio@f1000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "fsl,fman-xmdio";
+		reg = <0xf1000 0x1000>;
+		interrupts = <100 1 0 0>;
+	};
diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,imx35-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/fsl,imx35-pinctrl.txt
new file mode 100644
index 0000000..1183f1a
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/fsl,imx35-pinctrl.txt
@@ -0,0 +1,984 @@
+* Freescale IMX35 IOMUX Controller
+
+Please refer to fsl,imx-pinctrl.txt in this directory for common binding part
+and usage.
+
+Required properties:
+- compatible: "fsl,imx35-iomuxc"
+- fsl,pins: two integers array, represents a group of pins mux and config
+  setting. The format is fsl,pins = <PIN_FUNC_ID CONFIG>, PIN_FUNC_ID is a
+  pin working on a specific function, CONFIG is the pad setting value like
+  pull-up for this pin. Please refer to imx35 datasheet for the valid pad
+  config settings.
+
+CONFIG bits definition:
+PAD_CTL_DRIVE_VOLAGAGE_18	(1 << 13)
+PAD_CTL_DRIVE_VOLAGAGE_33	(0 << 13)
+PAD_CTL_HYS			(1 << 8)
+PAD_CTL_PKE			(1 << 7)
+PAD_CTL_PUE			(1 << 6)
+PAD_CTL_PUS_100K_DOWN		(0 << 4)
+PAD_CTL_PUS_47K_UP		(1 << 4)
+PAD_CTL_PUS_100K_UP		(2 << 4)
+PAD_CTL_PUS_22K_UP		(3 << 4)
+PAD_CTL_ODE_CMOS		(0 << 3)
+PAD_CTL_ODE_OPENDRAIN		(1 << 3)
+PAD_CTL_DSE_NOMINAL		(0 << 1)
+PAD_CTL_DSE_HIGH		(1 << 1)
+PAD_CTL_DSE_MAX			(2 << 1)
+PAD_CTL_SRE_FAST		(1 << 0)
+PAD_CTL_SRE_SLOW		(0 << 0)
+
+See below for available PIN_FUNC_ID for imx35:
+0 MX35_PAD_CAPTURE__GPT_CAPIN1
+1 MX35_PAD_CAPTURE__GPT_CMPOUT2
+2 MX35_PAD_CAPTURE__CSPI2_SS1
+3 MX35_PAD_CAPTURE__EPIT1_EPITO
+4 MX35_PAD_CAPTURE__CCM_CLK32K
+5 MX35_PAD_CAPTURE__GPIO1_4
+6 MX35_PAD_COMPARE__GPT_CMPOUT1
+7 MX35_PAD_COMPARE__GPT_CAPIN2
+8 MX35_PAD_COMPARE__GPT_CMPOUT3
+9 MX35_PAD_COMPARE__EPIT2_EPITO
+10 MX35_PAD_COMPARE__GPIO1_5
+11 MX35_PAD_COMPARE__SDMA_EXTDMA_2
+12 MX35_PAD_WDOG_RST__WDOG_WDOG_B
+13 MX35_PAD_WDOG_RST__IPU_FLASH_STROBE
+14 MX35_PAD_WDOG_RST__GPIO1_6
+15 MX35_PAD_GPIO1_0__GPIO1_0
+16 MX35_PAD_GPIO1_0__CCM_PMIC_RDY
+17 MX35_PAD_GPIO1_0__OWIRE_LINE
+18 MX35_PAD_GPIO1_0__SDMA_EXTDMA_0
+19 MX35_PAD_GPIO1_1__GPIO1_1
+20 MX35_PAD_GPIO1_1__PWM_PWMO
+21 MX35_PAD_GPIO1_1__CSPI1_SS2
+22 MX35_PAD_GPIO1_1__SCC_TAMPER_DETECT
+23 MX35_PAD_GPIO1_1__SDMA_EXTDMA_1
+24 MX35_PAD_GPIO2_0__GPIO2_0
+25 MX35_PAD_GPIO2_0__USB_TOP_USBOTG_CLK
+26 MX35_PAD_GPIO3_0__GPIO3_0
+27 MX35_PAD_GPIO3_0__USB_TOP_USBH2_CLK
+28 MX35_PAD_RESET_IN_B__CCM_RESET_IN_B
+29 MX35_PAD_POR_B__CCM_POR_B
+30 MX35_PAD_CLKO__CCM_CLKO
+31 MX35_PAD_CLKO__GPIO1_8
+32 MX35_PAD_BOOT_MODE0__CCM_BOOT_MODE_0
+33 MX35_PAD_BOOT_MODE1__CCM_BOOT_MODE_1
+34 MX35_PAD_CLK_MODE0__CCM_CLK_MODE_0
+35 MX35_PAD_CLK_MODE1__CCM_CLK_MODE_1
+36 MX35_PAD_POWER_FAIL__CCM_DSM_WAKEUP_INT_26
+37 MX35_PAD_VSTBY__CCM_VSTBY
+38 MX35_PAD_VSTBY__GPIO1_7
+39 MX35_PAD_A0__EMI_EIM_DA_L_0
+40 MX35_PAD_A1__EMI_EIM_DA_L_1
+41 MX35_PAD_A2__EMI_EIM_DA_L_2
+42 MX35_PAD_A3__EMI_EIM_DA_L_3
+43 MX35_PAD_A4__EMI_EIM_DA_L_4
+44 MX35_PAD_A5__EMI_EIM_DA_L_5
+45 MX35_PAD_A6__EMI_EIM_DA_L_6
+46 MX35_PAD_A7__EMI_EIM_DA_L_7
+47 MX35_PAD_A8__EMI_EIM_DA_H_8
+48 MX35_PAD_A9__EMI_EIM_DA_H_9
+49 MX35_PAD_A10__EMI_EIM_DA_H_10
+50 MX35_PAD_MA10__EMI_MA10
+51 MX35_PAD_A11__EMI_EIM_DA_H_11
+52 MX35_PAD_A12__EMI_EIM_DA_H_12
+53 MX35_PAD_A13__EMI_EIM_DA_H_13
+54 MX35_PAD_A14__EMI_EIM_DA_H2_14
+55 MX35_PAD_A15__EMI_EIM_DA_H2_15
+56 MX35_PAD_A16__EMI_EIM_A_16
+57 MX35_PAD_A17__EMI_EIM_A_17
+58 MX35_PAD_A18__EMI_EIM_A_18
+59 MX35_PAD_A19__EMI_EIM_A_19
+60 MX35_PAD_A20__EMI_EIM_A_20
+61 MX35_PAD_A21__EMI_EIM_A_21
+62 MX35_PAD_A22__EMI_EIM_A_22
+63 MX35_PAD_A23__EMI_EIM_A_23
+64 MX35_PAD_A24__EMI_EIM_A_24
+65 MX35_PAD_A25__EMI_EIM_A_25
+66 MX35_PAD_SDBA1__EMI_EIM_SDBA1
+67 MX35_PAD_SDBA0__EMI_EIM_SDBA0
+68 MX35_PAD_SD0__EMI_DRAM_D_0
+69 MX35_PAD_SD1__EMI_DRAM_D_1
+70 MX35_PAD_SD2__EMI_DRAM_D_2
+71 MX35_PAD_SD3__EMI_DRAM_D_3
+72 MX35_PAD_SD4__EMI_DRAM_D_4
+73 MX35_PAD_SD5__EMI_DRAM_D_5
+74 MX35_PAD_SD6__EMI_DRAM_D_6
+75 MX35_PAD_SD7__EMI_DRAM_D_7
+76 MX35_PAD_SD8__EMI_DRAM_D_8
+77 MX35_PAD_SD9__EMI_DRAM_D_9
+78 MX35_PAD_SD10__EMI_DRAM_D_10
+79 MX35_PAD_SD11__EMI_DRAM_D_11
+80 MX35_PAD_SD12__EMI_DRAM_D_12
+81 MX35_PAD_SD13__EMI_DRAM_D_13
+82 MX35_PAD_SD14__EMI_DRAM_D_14
+83 MX35_PAD_SD15__EMI_DRAM_D_15
+84 MX35_PAD_SD16__EMI_DRAM_D_16
+85 MX35_PAD_SD17__EMI_DRAM_D_17
+86 MX35_PAD_SD18__EMI_DRAM_D_18
+87 MX35_PAD_SD19__EMI_DRAM_D_19
+88 MX35_PAD_SD20__EMI_DRAM_D_20
+89 MX35_PAD_SD21__EMI_DRAM_D_21
+90 MX35_PAD_SD22__EMI_DRAM_D_22
+91 MX35_PAD_SD23__EMI_DRAM_D_23
+92 MX35_PAD_SD24__EMI_DRAM_D_24
+93 MX35_PAD_SD25__EMI_DRAM_D_25
+94 MX35_PAD_SD26__EMI_DRAM_D_26
+95 MX35_PAD_SD27__EMI_DRAM_D_27
+96 MX35_PAD_SD28__EMI_DRAM_D_28
+97 MX35_PAD_SD29__EMI_DRAM_D_29
+98 MX35_PAD_SD30__EMI_DRAM_D_30
+99 MX35_PAD_SD31__EMI_DRAM_D_31
+100 MX35_PAD_DQM0__EMI_DRAM_DQM_0
+101 MX35_PAD_DQM1__EMI_DRAM_DQM_1
+102 MX35_PAD_DQM2__EMI_DRAM_DQM_2
+103 MX35_PAD_DQM3__EMI_DRAM_DQM_3
+104 MX35_PAD_EB0__EMI_EIM_EB0_B
+105 MX35_PAD_EB1__EMI_EIM_EB1_B
+106 MX35_PAD_OE__EMI_EIM_OE
+107 MX35_PAD_CS0__EMI_EIM_CS0
+108 MX35_PAD_CS1__EMI_EIM_CS1
+109 MX35_PAD_CS1__EMI_NANDF_CE3
+110 MX35_PAD_CS2__EMI_EIM_CS2
+111 MX35_PAD_CS3__EMI_EIM_CS3
+112 MX35_PAD_CS4__EMI_EIM_CS4
+113 MX35_PAD_CS4__EMI_DTACK_B
+114 MX35_PAD_CS4__EMI_NANDF_CE1
+115 MX35_PAD_CS4__GPIO1_20
+116 MX35_PAD_CS5__EMI_EIM_CS5
+117 MX35_PAD_CS5__CSPI2_SS2
+118 MX35_PAD_CS5__CSPI1_SS2
+119 MX35_PAD_CS5__EMI_NANDF_CE2
+120 MX35_PAD_CS5__GPIO1_21
+121 MX35_PAD_NF_CE0__EMI_NANDF_CE0
+122 MX35_PAD_NF_CE0__GPIO1_22
+123 MX35_PAD_ECB__EMI_EIM_ECB
+124 MX35_PAD_LBA__EMI_EIM_LBA
+125 MX35_PAD_BCLK__EMI_EIM_BCLK
+126 MX35_PAD_RW__EMI_EIM_RW
+127 MX35_PAD_RAS__EMI_DRAM_RAS
+128 MX35_PAD_CAS__EMI_DRAM_CAS
+129 MX35_PAD_SDWE__EMI_DRAM_SDWE
+130 MX35_PAD_SDCKE0__EMI_DRAM_SDCKE_0
+131 MX35_PAD_SDCKE1__EMI_DRAM_SDCKE_1
+132 MX35_PAD_SDCLK__EMI_DRAM_SDCLK
+133 MX35_PAD_SDQS0__EMI_DRAM_SDQS_0
+134 MX35_PAD_SDQS1__EMI_DRAM_SDQS_1
+135 MX35_PAD_SDQS2__EMI_DRAM_SDQS_2
+136 MX35_PAD_SDQS3__EMI_DRAM_SDQS_3
+137 MX35_PAD_NFWE_B__EMI_NANDF_WE_B
+138 MX35_PAD_NFWE_B__USB_TOP_USBH2_DATA_3
+139 MX35_PAD_NFWE_B__IPU_DISPB_D0_VSYNC
+140 MX35_PAD_NFWE_B__GPIO2_18
+141 MX35_PAD_NFWE_B__ARM11P_TOP_TRACE_0
+142 MX35_PAD_NFRE_B__EMI_NANDF_RE_B
+143 MX35_PAD_NFRE_B__USB_TOP_USBH2_DIR
+144 MX35_PAD_NFRE_B__IPU_DISPB_BCLK
+145 MX35_PAD_NFRE_B__GPIO2_19
+146 MX35_PAD_NFRE_B__ARM11P_TOP_TRACE_1
+147 MX35_PAD_NFALE__EMI_NANDF_ALE
+148 MX35_PAD_NFALE__USB_TOP_USBH2_STP
+149 MX35_PAD_NFALE__IPU_DISPB_CS0
+150 MX35_PAD_NFALE__GPIO2_20
+151 MX35_PAD_NFALE__ARM11P_TOP_TRACE_2
+152 MX35_PAD_NFCLE__EMI_NANDF_CLE
+153 MX35_PAD_NFCLE__USB_TOP_USBH2_NXT
+154 MX35_PAD_NFCLE__IPU_DISPB_PAR_RS
+155 MX35_PAD_NFCLE__GPIO2_21
+156 MX35_PAD_NFCLE__ARM11P_TOP_TRACE_3
+157 MX35_PAD_NFWP_B__EMI_NANDF_WP_B
+158 MX35_PAD_NFWP_B__USB_TOP_USBH2_DATA_7
+159 MX35_PAD_NFWP_B__IPU_DISPB_WR
+160 MX35_PAD_NFWP_B__GPIO2_22
+161 MX35_PAD_NFWP_B__ARM11P_TOP_TRCTL
+162 MX35_PAD_NFRB__EMI_NANDF_RB
+163 MX35_PAD_NFRB__IPU_DISPB_RD
+164 MX35_PAD_NFRB__GPIO2_23
+165 MX35_PAD_NFRB__ARM11P_TOP_TRCLK
+166 MX35_PAD_D15__EMI_EIM_D_15
+167 MX35_PAD_D14__EMI_EIM_D_14
+168 MX35_PAD_D13__EMI_EIM_D_13
+169 MX35_PAD_D12__EMI_EIM_D_12
+170 MX35_PAD_D11__EMI_EIM_D_11
+171 MX35_PAD_D10__EMI_EIM_D_10
+172 MX35_PAD_D9__EMI_EIM_D_9
+173 MX35_PAD_D8__EMI_EIM_D_8
+174 MX35_PAD_D7__EMI_EIM_D_7
+175 MX35_PAD_D6__EMI_EIM_D_6
+176 MX35_PAD_D5__EMI_EIM_D_5
+177 MX35_PAD_D4__EMI_EIM_D_4
+178 MX35_PAD_D3__EMI_EIM_D_3
+179 MX35_PAD_D2__EMI_EIM_D_2
+180 MX35_PAD_D1__EMI_EIM_D_1
+181 MX35_PAD_D0__EMI_EIM_D_0
+182 MX35_PAD_CSI_D8__IPU_CSI_D_8
+183 MX35_PAD_CSI_D8__KPP_COL_0
+184 MX35_PAD_CSI_D8__GPIO1_20
+185 MX35_PAD_CSI_D8__ARM11P_TOP_EVNTBUS_13
+186 MX35_PAD_CSI_D9__IPU_CSI_D_9
+187 MX35_PAD_CSI_D9__KPP_COL_1
+188 MX35_PAD_CSI_D9__GPIO1_21
+189 MX35_PAD_CSI_D9__ARM11P_TOP_EVNTBUS_14
+190 MX35_PAD_CSI_D10__IPU_CSI_D_10
+191 MX35_PAD_CSI_D10__KPP_COL_2
+192 MX35_PAD_CSI_D10__GPIO1_22
+193 MX35_PAD_CSI_D10__ARM11P_TOP_EVNTBUS_15
+194 MX35_PAD_CSI_D11__IPU_CSI_D_11
+195 MX35_PAD_CSI_D11__KPP_COL_3
+196 MX35_PAD_CSI_D11__GPIO1_23
+197 MX35_PAD_CSI_D12__IPU_CSI_D_12
+198 MX35_PAD_CSI_D12__KPP_ROW_0
+199 MX35_PAD_CSI_D12__GPIO1_24
+200 MX35_PAD_CSI_D13__IPU_CSI_D_13
+201 MX35_PAD_CSI_D13__KPP_ROW_1
+202 MX35_PAD_CSI_D13__GPIO1_25
+203 MX35_PAD_CSI_D14__IPU_CSI_D_14
+204 MX35_PAD_CSI_D14__KPP_ROW_2
+205 MX35_PAD_CSI_D14__GPIO1_26
+206 MX35_PAD_CSI_D15__IPU_CSI_D_15
+207 MX35_PAD_CSI_D15__KPP_ROW_3
+208 MX35_PAD_CSI_D15__GPIO1_27
+209 MX35_PAD_CSI_MCLK__IPU_CSI_MCLK
+210 MX35_PAD_CSI_MCLK__GPIO1_28
+211 MX35_PAD_CSI_VSYNC__IPU_CSI_VSYNC
+212 MX35_PAD_CSI_VSYNC__GPIO1_29
+213 MX35_PAD_CSI_HSYNC__IPU_CSI_HSYNC
+214 MX35_PAD_CSI_HSYNC__GPIO1_30
+215 MX35_PAD_CSI_PIXCLK__IPU_CSI_PIXCLK
+216 MX35_PAD_CSI_PIXCLK__GPIO1_31
+217 MX35_PAD_I2C1_CLK__I2C1_SCL
+218 MX35_PAD_I2C1_CLK__GPIO2_24
+219 MX35_PAD_I2C1_CLK__CCM_USB_BYP_CLK
+220 MX35_PAD_I2C1_DAT__I2C1_SDA
+221 MX35_PAD_I2C1_DAT__GPIO2_25
+222 MX35_PAD_I2C2_CLK__I2C2_SCL
+223 MX35_PAD_I2C2_CLK__CAN1_TXCAN
+224 MX35_PAD_I2C2_CLK__USB_TOP_USBH2_PWR
+225 MX35_PAD_I2C2_CLK__GPIO2_26
+226 MX35_PAD_I2C2_CLK__SDMA_DEBUG_BUS_DEVICE_2
+227 MX35_PAD_I2C2_DAT__I2C2_SDA
+228 MX35_PAD_I2C2_DAT__CAN1_RXCAN
+229 MX35_PAD_I2C2_DAT__USB_TOP_USBH2_OC
+230 MX35_PAD_I2C2_DAT__GPIO2_27
+231 MX35_PAD_I2C2_DAT__SDMA_DEBUG_BUS_DEVICE_3
+232 MX35_PAD_STXD4__AUDMUX_AUD4_TXD
+233 MX35_PAD_STXD4__GPIO2_28
+234 MX35_PAD_STXD4__ARM11P_TOP_ARM_COREASID0
+235 MX35_PAD_SRXD4__AUDMUX_AUD4_RXD
+236 MX35_PAD_SRXD4__GPIO2_29
+237 MX35_PAD_SRXD4__ARM11P_TOP_ARM_COREASID1
+238 MX35_PAD_SCK4__AUDMUX_AUD4_TXC
+239 MX35_PAD_SCK4__GPIO2_30
+240 MX35_PAD_SCK4__ARM11P_TOP_ARM_COREASID2
+241 MX35_PAD_STXFS4__AUDMUX_AUD4_TXFS
+242 MX35_PAD_STXFS4__GPIO2_31
+243 MX35_PAD_STXFS4__ARM11P_TOP_ARM_COREASID3
+244 MX35_PAD_STXD5__AUDMUX_AUD5_TXD
+245 MX35_PAD_STXD5__SPDIF_SPDIF_OUT1
+246 MX35_PAD_STXD5__CSPI2_MOSI
+247 MX35_PAD_STXD5__GPIO1_0
+248 MX35_PAD_STXD5__ARM11P_TOP_ARM_COREASID4
+249 MX35_PAD_SRXD5__AUDMUX_AUD5_RXD
+250 MX35_PAD_SRXD5__SPDIF_SPDIF_IN1
+251 MX35_PAD_SRXD5__CSPI2_MISO
+252 MX35_PAD_SRXD5__GPIO1_1
+253 MX35_PAD_SRXD5__ARM11P_TOP_ARM_COREASID5
+254 MX35_PAD_SCK5__AUDMUX_AUD5_TXC
+255 MX35_PAD_SCK5__SPDIF_SPDIF_EXTCLK
+256 MX35_PAD_SCK5__CSPI2_SCLK
+257 MX35_PAD_SCK5__GPIO1_2
+258 MX35_PAD_SCK5__ARM11P_TOP_ARM_COREASID6
+259 MX35_PAD_STXFS5__AUDMUX_AUD5_TXFS
+260 MX35_PAD_STXFS5__CSPI2_RDY
+261 MX35_PAD_STXFS5__GPIO1_3
+262 MX35_PAD_STXFS5__ARM11P_TOP_ARM_COREASID7
+263 MX35_PAD_SCKR__ESAI_SCKR
+264 MX35_PAD_SCKR__GPIO1_4
+265 MX35_PAD_SCKR__ARM11P_TOP_EVNTBUS_10
+266 MX35_PAD_FSR__ESAI_FSR
+267 MX35_PAD_FSR__GPIO1_5
+268 MX35_PAD_FSR__ARM11P_TOP_EVNTBUS_11
+269 MX35_PAD_HCKR__ESAI_HCKR
+270 MX35_PAD_HCKR__AUDMUX_AUD5_RXFS
+271 MX35_PAD_HCKR__CSPI2_SS0
+272 MX35_PAD_HCKR__IPU_FLASH_STROBE
+273 MX35_PAD_HCKR__GPIO1_6
+274 MX35_PAD_HCKR__ARM11P_TOP_EVNTBUS_12
+275 MX35_PAD_SCKT__ESAI_SCKT
+276 MX35_PAD_SCKT__GPIO1_7
+277 MX35_PAD_SCKT__IPU_CSI_D_0
+278 MX35_PAD_SCKT__KPP_ROW_2
+279 MX35_PAD_FST__ESAI_FST
+280 MX35_PAD_FST__GPIO1_8
+281 MX35_PAD_FST__IPU_CSI_D_1
+282 MX35_PAD_FST__KPP_ROW_3
+283 MX35_PAD_HCKT__ESAI_HCKT
+284 MX35_PAD_HCKT__AUDMUX_AUD5_RXC
+285 MX35_PAD_HCKT__GPIO1_9
+286 MX35_PAD_HCKT__IPU_CSI_D_2
+287 MX35_PAD_HCKT__KPP_COL_3
+288 MX35_PAD_TX5_RX0__ESAI_TX5_RX0
+289 MX35_PAD_TX5_RX0__AUDMUX_AUD4_RXC
+290 MX35_PAD_TX5_RX0__CSPI2_SS2
+291 MX35_PAD_TX5_RX0__CAN2_TXCAN
+292 MX35_PAD_TX5_RX0__UART2_DTR
+293 MX35_PAD_TX5_RX0__GPIO1_10
+294 MX35_PAD_TX5_RX0__EMI_M3IF_CHOSEN_MASTER_0
+295 MX35_PAD_TX4_RX1__ESAI_TX4_RX1
+296 MX35_PAD_TX4_RX1__AUDMUX_AUD4_RXFS
+297 MX35_PAD_TX4_RX1__CSPI2_SS3
+298 MX35_PAD_TX4_RX1__CAN2_RXCAN
+299 MX35_PAD_TX4_RX1__UART2_DSR
+300 MX35_PAD_TX4_RX1__GPIO1_11
+301 MX35_PAD_TX4_RX1__IPU_CSI_D_3
+302 MX35_PAD_TX4_RX1__KPP_ROW_0
+303 MX35_PAD_TX3_RX2__ESAI_TX3_RX2
+304 MX35_PAD_TX3_RX2__I2C3_SCL
+305 MX35_PAD_TX3_RX2__EMI_NANDF_CE1
+306 MX35_PAD_TX3_RX2__GPIO1_12
+307 MX35_PAD_TX3_RX2__IPU_CSI_D_4
+308 MX35_PAD_TX3_RX2__KPP_ROW_1
+309 MX35_PAD_TX2_RX3__ESAI_TX2_RX3
+310 MX35_PAD_TX2_RX3__I2C3_SDA
+311 MX35_PAD_TX2_RX3__EMI_NANDF_CE2
+312 MX35_PAD_TX2_RX3__GPIO1_13
+313 MX35_PAD_TX2_RX3__IPU_CSI_D_5
+314 MX35_PAD_TX2_RX3__KPP_COL_0
+315 MX35_PAD_TX1__ESAI_TX1
+316 MX35_PAD_TX1__CCM_PMIC_RDY
+317 MX35_PAD_TX1__CSPI1_SS2
+318 MX35_PAD_TX1__EMI_NANDF_CE3
+319 MX35_PAD_TX1__UART2_RI
+320 MX35_PAD_TX1__GPIO1_14
+321 MX35_PAD_TX1__IPU_CSI_D_6
+322 MX35_PAD_TX1__KPP_COL_1
+323 MX35_PAD_TX0__ESAI_TX0
+324 MX35_PAD_TX0__SPDIF_SPDIF_EXTCLK
+325 MX35_PAD_TX0__CSPI1_SS3
+326 MX35_PAD_TX0__EMI_DTACK_B
+327 MX35_PAD_TX0__UART2_DCD
+328 MX35_PAD_TX0__GPIO1_15
+329 MX35_PAD_TX0__IPU_CSI_D_7
+330 MX35_PAD_TX0__KPP_COL_2
+331 MX35_PAD_CSPI1_MOSI__CSPI1_MOSI
+332 MX35_PAD_CSPI1_MOSI__GPIO1_16
+333 MX35_PAD_CSPI1_MOSI__ECT_CTI_TRIG_OUT1_2
+334 MX35_PAD_CSPI1_MISO__CSPI1_MISO
+335 MX35_PAD_CSPI1_MISO__GPIO1_17
+336 MX35_PAD_CSPI1_MISO__ECT_CTI_TRIG_OUT1_3
+337 MX35_PAD_CSPI1_SS0__CSPI1_SS0
+338 MX35_PAD_CSPI1_SS0__OWIRE_LINE
+339 MX35_PAD_CSPI1_SS0__CSPI2_SS3
+340 MX35_PAD_CSPI1_SS0__GPIO1_18
+341 MX35_PAD_CSPI1_SS0__ECT_CTI_TRIG_OUT1_4
+342 MX35_PAD_CSPI1_SS1__CSPI1_SS1
+343 MX35_PAD_CSPI1_SS1__PWM_PWMO
+344 MX35_PAD_CSPI1_SS1__CCM_CLK32K
+345 MX35_PAD_CSPI1_SS1__GPIO1_19
+346 MX35_PAD_CSPI1_SS1__IPU_DIAGB_29
+347 MX35_PAD_CSPI1_SS1__ECT_CTI_TRIG_OUT1_5
+348 MX35_PAD_CSPI1_SCLK__CSPI1_SCLK
+349 MX35_PAD_CSPI1_SCLK__GPIO3_4
+350 MX35_PAD_CSPI1_SCLK__IPU_DIAGB_30
+351 MX35_PAD_CSPI1_SCLK__EMI_M3IF_CHOSEN_MASTER_1
+352 MX35_PAD_CSPI1_SPI_RDY__CSPI1_RDY
+353 MX35_PAD_CSPI1_SPI_RDY__GPIO3_5
+354 MX35_PAD_CSPI1_SPI_RDY__IPU_DIAGB_31
+355 MX35_PAD_CSPI1_SPI_RDY__EMI_M3IF_CHOSEN_MASTER_2
+356 MX35_PAD_RXD1__UART1_RXD_MUX
+357 MX35_PAD_RXD1__CSPI2_MOSI
+358 MX35_PAD_RXD1__KPP_COL_4
+359 MX35_PAD_RXD1__GPIO3_6
+360 MX35_PAD_RXD1__ARM11P_TOP_EVNTBUS_16
+361 MX35_PAD_TXD1__UART1_TXD_MUX
+362 MX35_PAD_TXD1__CSPI2_MISO
+363 MX35_PAD_TXD1__KPP_COL_5
+364 MX35_PAD_TXD1__GPIO3_7
+365 MX35_PAD_TXD1__ARM11P_TOP_EVNTBUS_17
+366 MX35_PAD_RTS1__UART1_RTS
+367 MX35_PAD_RTS1__CSPI2_SCLK
+368 MX35_PAD_RTS1__I2C3_SCL
+369 MX35_PAD_RTS1__IPU_CSI_D_0
+370 MX35_PAD_RTS1__KPP_COL_6
+371 MX35_PAD_RTS1__GPIO3_8
+372 MX35_PAD_RTS1__EMI_NANDF_CE1
+373 MX35_PAD_RTS1__ARM11P_TOP_EVNTBUS_18
+374 MX35_PAD_CTS1__UART1_CTS
+375 MX35_PAD_CTS1__CSPI2_RDY
+376 MX35_PAD_CTS1__I2C3_SDA
+377 MX35_PAD_CTS1__IPU_CSI_D_1
+378 MX35_PAD_CTS1__KPP_COL_7
+379 MX35_PAD_CTS1__GPIO3_9
+380 MX35_PAD_CTS1__EMI_NANDF_CE2
+381 MX35_PAD_CTS1__ARM11P_TOP_EVNTBUS_19
+382 MX35_PAD_RXD2__UART2_RXD_MUX
+383 MX35_PAD_RXD2__KPP_ROW_4
+384 MX35_PAD_RXD2__GPIO3_10
+385 MX35_PAD_TXD2__UART2_TXD_MUX
+386 MX35_PAD_TXD2__SPDIF_SPDIF_EXTCLK
+387 MX35_PAD_TXD2__KPP_ROW_5
+388 MX35_PAD_TXD2__GPIO3_11
+389 MX35_PAD_RTS2__UART2_RTS
+390 MX35_PAD_RTS2__SPDIF_SPDIF_IN1
+391 MX35_PAD_RTS2__CAN2_RXCAN
+392 MX35_PAD_RTS2__IPU_CSI_D_2
+393 MX35_PAD_RTS2__KPP_ROW_6
+394 MX35_PAD_RTS2__GPIO3_12
+395 MX35_PAD_RTS2__AUDMUX_AUD5_RXC
+396 MX35_PAD_RTS2__UART3_RXD_MUX
+397 MX35_PAD_CTS2__UART2_CTS
+398 MX35_PAD_CTS2__SPDIF_SPDIF_OUT1
+399 MX35_PAD_CTS2__CAN2_TXCAN
+400 MX35_PAD_CTS2__IPU_CSI_D_3
+401 MX35_PAD_CTS2__KPP_ROW_7
+402 MX35_PAD_CTS2__GPIO3_13
+403 MX35_PAD_CTS2__AUDMUX_AUD5_RXFS
+404 MX35_PAD_CTS2__UART3_TXD_MUX
+405 MX35_PAD_RTCK__ARM11P_TOP_RTCK
+406 MX35_PAD_TCK__SJC_TCK
+407 MX35_PAD_TMS__SJC_TMS
+408 MX35_PAD_TDI__SJC_TDI
+409 MX35_PAD_TDO__SJC_TDO
+410 MX35_PAD_TRSTB__SJC_TRSTB
+411 MX35_PAD_DE_B__SJC_DE_B
+412 MX35_PAD_SJC_MOD__SJC_MOD
+413 MX35_PAD_USBOTG_PWR__USB_TOP_USBOTG_PWR
+414 MX35_PAD_USBOTG_PWR__USB_TOP_USBH2_PWR
+415 MX35_PAD_USBOTG_PWR__GPIO3_14
+416 MX35_PAD_USBOTG_OC__USB_TOP_USBOTG_OC
+417 MX35_PAD_USBOTG_OC__USB_TOP_USBH2_OC
+418 MX35_PAD_USBOTG_OC__GPIO3_15
+419 MX35_PAD_LD0__IPU_DISPB_DAT_0
+420 MX35_PAD_LD0__GPIO2_0
+421 MX35_PAD_LD0__SDMA_SDMA_DEBUG_PC_0
+422 MX35_PAD_LD1__IPU_DISPB_DAT_1
+423 MX35_PAD_LD1__GPIO2_1
+424 MX35_PAD_LD1__SDMA_SDMA_DEBUG_PC_1
+425 MX35_PAD_LD2__IPU_DISPB_DAT_2
+426 MX35_PAD_LD2__GPIO2_2
+427 MX35_PAD_LD2__SDMA_SDMA_DEBUG_PC_2
+428 MX35_PAD_LD3__IPU_DISPB_DAT_3
+429 MX35_PAD_LD3__GPIO2_3
+430 MX35_PAD_LD3__SDMA_SDMA_DEBUG_PC_3
+431 MX35_PAD_LD4__IPU_DISPB_DAT_4
+432 MX35_PAD_LD4__GPIO2_4
+433 MX35_PAD_LD4__SDMA_SDMA_DEBUG_PC_4
+434 MX35_PAD_LD5__IPU_DISPB_DAT_5
+435 MX35_PAD_LD5__GPIO2_5
+436 MX35_PAD_LD5__SDMA_SDMA_DEBUG_PC_5
+437 MX35_PAD_LD6__IPU_DISPB_DAT_6
+438 MX35_PAD_LD6__GPIO2_6
+439 MX35_PAD_LD6__SDMA_SDMA_DEBUG_PC_6
+440 MX35_PAD_LD7__IPU_DISPB_DAT_7
+441 MX35_PAD_LD7__GPIO2_7
+442 MX35_PAD_LD7__SDMA_SDMA_DEBUG_PC_7
+443 MX35_PAD_LD8__IPU_DISPB_DAT_8
+444 MX35_PAD_LD8__GPIO2_8
+445 MX35_PAD_LD8__SDMA_SDMA_DEBUG_PC_8
+446 MX35_PAD_LD9__IPU_DISPB_DAT_9
+447 MX35_PAD_LD9__GPIO2_9
+448 MX35_PAD_LD9__SDMA_SDMA_DEBUG_PC_9
+449 MX35_PAD_LD10__IPU_DISPB_DAT_10
+450 MX35_PAD_LD10__GPIO2_10
+451 MX35_PAD_LD10__SDMA_SDMA_DEBUG_PC_10
+452 MX35_PAD_LD11__IPU_DISPB_DAT_11
+453 MX35_PAD_LD11__GPIO2_11
+454 MX35_PAD_LD11__SDMA_SDMA_DEBUG_PC_11
+455 MX35_PAD_LD11__ARM11P_TOP_TRACE_4
+456 MX35_PAD_LD12__IPU_DISPB_DAT_12
+457 MX35_PAD_LD12__GPIO2_12
+458 MX35_PAD_LD12__SDMA_SDMA_DEBUG_PC_12
+459 MX35_PAD_LD12__ARM11P_TOP_TRACE_5
+460 MX35_PAD_LD13__IPU_DISPB_DAT_13
+461 MX35_PAD_LD13__GPIO2_13
+462 MX35_PAD_LD13__SDMA_SDMA_DEBUG_PC_13
+463 MX35_PAD_LD13__ARM11P_TOP_TRACE_6
+464 MX35_PAD_LD14__IPU_DISPB_DAT_14
+465 MX35_PAD_LD14__GPIO2_14
+466 MX35_PAD_LD14__SDMA_SDMA_DEBUG_EVENT_CHANNEL_0
+467 MX35_PAD_LD14__ARM11P_TOP_TRACE_7
+468 MX35_PAD_LD15__IPU_DISPB_DAT_15
+469 MX35_PAD_LD15__GPIO2_15
+470 MX35_PAD_LD15__SDMA_SDMA_DEBUG_EVENT_CHANNEL_1
+471 MX35_PAD_LD15__ARM11P_TOP_TRACE_8
+472 MX35_PAD_LD16__IPU_DISPB_DAT_16
+473 MX35_PAD_LD16__IPU_DISPB_D12_VSYNC
+474 MX35_PAD_LD16__GPIO2_16
+475 MX35_PAD_LD16__SDMA_SDMA_DEBUG_EVENT_CHANNEL_2
+476 MX35_PAD_LD16__ARM11P_TOP_TRACE_9
+477 MX35_PAD_LD17__IPU_DISPB_DAT_17
+478 MX35_PAD_LD17__IPU_DISPB_CS2
+479 MX35_PAD_LD17__GPIO2_17
+480 MX35_PAD_LD17__SDMA_SDMA_DEBUG_EVENT_CHANNEL_3
+481 MX35_PAD_LD17__ARM11P_TOP_TRACE_10
+482 MX35_PAD_LD18__IPU_DISPB_DAT_18
+483 MX35_PAD_LD18__IPU_DISPB_D0_VSYNC
+484 MX35_PAD_LD18__IPU_DISPB_D12_VSYNC
+485 MX35_PAD_LD18__ESDHC3_CMD
+486 MX35_PAD_LD18__USB_TOP_USBOTG_DATA_3
+487 MX35_PAD_LD18__GPIO3_24
+488 MX35_PAD_LD18__SDMA_SDMA_DEBUG_EVENT_CHANNEL_4
+489 MX35_PAD_LD18__ARM11P_TOP_TRACE_11
+490 MX35_PAD_LD19__IPU_DISPB_DAT_19
+491 MX35_PAD_LD19__IPU_DISPB_BCLK
+492 MX35_PAD_LD19__IPU_DISPB_CS1
+493 MX35_PAD_LD19__ESDHC3_CLK
+494 MX35_PAD_LD19__USB_TOP_USBOTG_DIR
+495 MX35_PAD_LD19__GPIO3_25
+496 MX35_PAD_LD19__SDMA_SDMA_DEBUG_EVENT_CHANNEL_5
+497 MX35_PAD_LD19__ARM11P_TOP_TRACE_12
+498 MX35_PAD_LD20__IPU_DISPB_DAT_20
+499 MX35_PAD_LD20__IPU_DISPB_CS0
+500 MX35_PAD_LD20__IPU_DISPB_SD_CLK
+501 MX35_PAD_LD20__ESDHC3_DAT0
+502 MX35_PAD_LD20__GPIO3_26
+503 MX35_PAD_LD20__SDMA_SDMA_DEBUG_CORE_STATUS_3
+504 MX35_PAD_LD20__ARM11P_TOP_TRACE_13
+505 MX35_PAD_LD21__IPU_DISPB_DAT_21
+506 MX35_PAD_LD21__IPU_DISPB_PAR_RS
+507 MX35_PAD_LD21__IPU_DISPB_SER_RS
+508 MX35_PAD_LD21__ESDHC3_DAT1
+509 MX35_PAD_LD21__USB_TOP_USBOTG_STP
+510 MX35_PAD_LD21__GPIO3_27
+511 MX35_PAD_LD21__SDMA_DEBUG_EVENT_CHANNEL_SEL
+512 MX35_PAD_LD21__ARM11P_TOP_TRACE_14
+513 MX35_PAD_LD22__IPU_DISPB_DAT_22
+514 MX35_PAD_LD22__IPU_DISPB_WR
+515 MX35_PAD_LD22__IPU_DISPB_SD_D_I
+516 MX35_PAD_LD22__ESDHC3_DAT2
+517 MX35_PAD_LD22__USB_TOP_USBOTG_NXT
+518 MX35_PAD_LD22__GPIO3_28
+519 MX35_PAD_LD22__SDMA_DEBUG_BUS_ERROR
+520 MX35_PAD_LD22__ARM11P_TOP_TRCTL
+521 MX35_PAD_LD23__IPU_DISPB_DAT_23
+522 MX35_PAD_LD23__IPU_DISPB_RD
+523 MX35_PAD_LD23__IPU_DISPB_SD_D_IO
+524 MX35_PAD_LD23__ESDHC3_DAT3
+525 MX35_PAD_LD23__USB_TOP_USBOTG_DATA_7
+526 MX35_PAD_LD23__GPIO3_29
+527 MX35_PAD_LD23__SDMA_DEBUG_MATCHED_DMBUS
+528 MX35_PAD_LD23__ARM11P_TOP_TRCLK
+529 MX35_PAD_D3_HSYNC__IPU_DISPB_D3_HSYNC
+530 MX35_PAD_D3_HSYNC__IPU_DISPB_SD_D_IO
+531 MX35_PAD_D3_HSYNC__GPIO3_30
+532 MX35_PAD_D3_HSYNC__SDMA_DEBUG_RTBUFFER_WRITE
+533 MX35_PAD_D3_HSYNC__ARM11P_TOP_TRACE_15
+534 MX35_PAD_D3_FPSHIFT__IPU_DISPB_D3_CLK
+535 MX35_PAD_D3_FPSHIFT__IPU_DISPB_SD_CLK
+536 MX35_PAD_D3_FPSHIFT__GPIO3_31
+537 MX35_PAD_D3_FPSHIFT__SDMA_SDMA_DEBUG_CORE_STATUS_0
+538 MX35_PAD_D3_FPSHIFT__ARM11P_TOP_TRACE_16
+539 MX35_PAD_D3_DRDY__IPU_DISPB_D3_DRDY
+540 MX35_PAD_D3_DRDY__IPU_DISPB_SD_D_O
+541 MX35_PAD_D3_DRDY__GPIO1_0
+542 MX35_PAD_D3_DRDY__SDMA_SDMA_DEBUG_CORE_STATUS_1
+543 MX35_PAD_D3_DRDY__ARM11P_TOP_TRACE_17
+544 MX35_PAD_CONTRAST__IPU_DISPB_CONTR
+545 MX35_PAD_CONTRAST__GPIO1_1
+546 MX35_PAD_CONTRAST__SDMA_SDMA_DEBUG_CORE_STATUS_2
+547 MX35_PAD_CONTRAST__ARM11P_TOP_TRACE_18
+548 MX35_PAD_D3_VSYNC__IPU_DISPB_D3_VSYNC
+549 MX35_PAD_D3_VSYNC__IPU_DISPB_CS1
+550 MX35_PAD_D3_VSYNC__GPIO1_2
+551 MX35_PAD_D3_VSYNC__SDMA_DEBUG_YIELD
+552 MX35_PAD_D3_VSYNC__ARM11P_TOP_TRACE_19
+553 MX35_PAD_D3_REV__IPU_DISPB_D3_REV
+554 MX35_PAD_D3_REV__IPU_DISPB_SER_RS
+555 MX35_PAD_D3_REV__GPIO1_3
+556 MX35_PAD_D3_REV__SDMA_DEBUG_BUS_RWB
+557 MX35_PAD_D3_REV__ARM11P_TOP_TRACE_20
+558 MX35_PAD_D3_CLS__IPU_DISPB_D3_CLS
+559 MX35_PAD_D3_CLS__IPU_DISPB_CS2
+560 MX35_PAD_D3_CLS__GPIO1_4
+561 MX35_PAD_D3_CLS__SDMA_DEBUG_BUS_DEVICE_0
+562 MX35_PAD_D3_CLS__ARM11P_TOP_TRACE_21
+563 MX35_PAD_D3_SPL__IPU_DISPB_D3_SPL
+564 MX35_PAD_D3_SPL__IPU_DISPB_D12_VSYNC
+565 MX35_PAD_D3_SPL__GPIO1_5
+566 MX35_PAD_D3_SPL__SDMA_DEBUG_BUS_DEVICE_1
+567 MX35_PAD_D3_SPL__ARM11P_TOP_TRACE_22
+568 MX35_PAD_SD1_CMD__ESDHC1_CMD
+569 MX35_PAD_SD1_CMD__MSHC_SCLK
+570 MX35_PAD_SD1_CMD__IPU_DISPB_D0_VSYNC
+571 MX35_PAD_SD1_CMD__USB_TOP_USBOTG_DATA_4
+572 MX35_PAD_SD1_CMD__GPIO1_6
+573 MX35_PAD_SD1_CMD__ARM11P_TOP_TRCTL
+574 MX35_PAD_SD1_CLK__ESDHC1_CLK
+575 MX35_PAD_SD1_CLK__MSHC_BS
+576 MX35_PAD_SD1_CLK__IPU_DISPB_BCLK
+577 MX35_PAD_SD1_CLK__USB_TOP_USBOTG_DATA_5
+578 MX35_PAD_SD1_CLK__GPIO1_7
+579 MX35_PAD_SD1_CLK__ARM11P_TOP_TRCLK
+580 MX35_PAD_SD1_DATA0__ESDHC1_DAT0
+581 MX35_PAD_SD1_DATA0__MSHC_DATA_0
+582 MX35_PAD_SD1_DATA0__IPU_DISPB_CS0
+583 MX35_PAD_SD1_DATA0__USB_TOP_USBOTG_DATA_6
+584 MX35_PAD_SD1_DATA0__GPIO1_8
+585 MX35_PAD_SD1_DATA0__ARM11P_TOP_TRACE_23
+586 MX35_PAD_SD1_DATA1__ESDHC1_DAT1
+587 MX35_PAD_SD1_DATA1__MSHC_DATA_1
+588 MX35_PAD_SD1_DATA1__IPU_DISPB_PAR_RS
+589 MX35_PAD_SD1_DATA1__USB_TOP_USBOTG_DATA_0
+590 MX35_PAD_SD1_DATA1__GPIO1_9
+591 MX35_PAD_SD1_DATA1__ARM11P_TOP_TRACE_24
+592 MX35_PAD_SD1_DATA2__ESDHC1_DAT2
+593 MX35_PAD_SD1_DATA2__MSHC_DATA_2
+594 MX35_PAD_SD1_DATA2__IPU_DISPB_WR
+595 MX35_PAD_SD1_DATA2__USB_TOP_USBOTG_DATA_1
+596 MX35_PAD_SD1_DATA2__GPIO1_10
+597 MX35_PAD_SD1_DATA2__ARM11P_TOP_TRACE_25
+598 MX35_PAD_SD1_DATA3__ESDHC1_DAT3
+599 MX35_PAD_SD1_DATA3__MSHC_DATA_3
+600 MX35_PAD_SD1_DATA3__IPU_DISPB_RD
+601 MX35_PAD_SD1_DATA3__USB_TOP_USBOTG_DATA_2
+602 MX35_PAD_SD1_DATA3__GPIO1_11
+603 MX35_PAD_SD1_DATA3__ARM11P_TOP_TRACE_26
+604 MX35_PAD_SD2_CMD__ESDHC2_CMD
+605 MX35_PAD_SD2_CMD__I2C3_SCL
+606 MX35_PAD_SD2_CMD__ESDHC1_DAT4
+607 MX35_PAD_SD2_CMD__IPU_CSI_D_2
+608 MX35_PAD_SD2_CMD__USB_TOP_USBH2_DATA_4
+609 MX35_PAD_SD2_CMD__GPIO2_0
+610 MX35_PAD_SD2_CMD__SPDIF_SPDIF_OUT1
+611 MX35_PAD_SD2_CMD__IPU_DISPB_D12_VSYNC
+612 MX35_PAD_SD2_CLK__ESDHC2_CLK
+613 MX35_PAD_SD2_CLK__I2C3_SDA
+614 MX35_PAD_SD2_CLK__ESDHC1_DAT5
+615 MX35_PAD_SD2_CLK__IPU_CSI_D_3
+616 MX35_PAD_SD2_CLK__USB_TOP_USBH2_DATA_5
+617 MX35_PAD_SD2_CLK__GPIO2_1
+618 MX35_PAD_SD2_CLK__SPDIF_SPDIF_IN1
+619 MX35_PAD_SD2_CLK__IPU_DISPB_CS2
+620 MX35_PAD_SD2_DATA0__ESDHC2_DAT0
+621 MX35_PAD_SD2_DATA0__UART3_RXD_MUX
+622 MX35_PAD_SD2_DATA0__ESDHC1_DAT6
+623 MX35_PAD_SD2_DATA0__IPU_CSI_D_4
+624 MX35_PAD_SD2_DATA0__USB_TOP_USBH2_DATA_6
+625 MX35_PAD_SD2_DATA0__GPIO2_2
+626 MX35_PAD_SD2_DATA0__SPDIF_SPDIF_EXTCLK
+627 MX35_PAD_SD2_DATA1__ESDHC2_DAT1
+628 MX35_PAD_SD2_DATA1__UART3_TXD_MUX
+629 MX35_PAD_SD2_DATA1__ESDHC1_DAT7
+630 MX35_PAD_SD2_DATA1__IPU_CSI_D_5
+631 MX35_PAD_SD2_DATA1__USB_TOP_USBH2_DATA_0
+632 MX35_PAD_SD2_DATA1__GPIO2_3
+633 MX35_PAD_SD2_DATA2__ESDHC2_DAT2
+634 MX35_PAD_SD2_DATA2__UART3_RTS
+635 MX35_PAD_SD2_DATA2__CAN1_RXCAN
+636 MX35_PAD_SD2_DATA2__IPU_CSI_D_6
+637 MX35_PAD_SD2_DATA2__USB_TOP_USBH2_DATA_1
+638 MX35_PAD_SD2_DATA2__GPIO2_4
+639 MX35_PAD_SD2_DATA3__ESDHC2_DAT3
+640 MX35_PAD_SD2_DATA3__UART3_CTS
+641 MX35_PAD_SD2_DATA3__CAN1_TXCAN
+642 MX35_PAD_SD2_DATA3__IPU_CSI_D_7
+643 MX35_PAD_SD2_DATA3__USB_TOP_USBH2_DATA_2
+644 MX35_PAD_SD2_DATA3__GPIO2_5
+645 MX35_PAD_ATA_CS0__ATA_CS0
+646 MX35_PAD_ATA_CS0__CSPI1_SS3
+647 MX35_PAD_ATA_CS0__IPU_DISPB_CS1
+648 MX35_PAD_ATA_CS0__GPIO2_6
+649 MX35_PAD_ATA_CS0__IPU_DIAGB_0
+650 MX35_PAD_ATA_CS0__ARM11P_TOP_MAX1_HMASTER_0
+651 MX35_PAD_ATA_CS1__ATA_CS1
+652 MX35_PAD_ATA_CS1__IPU_DISPB_CS2
+653 MX35_PAD_ATA_CS1__CSPI2_SS0
+654 MX35_PAD_ATA_CS1__GPIO2_7
+655 MX35_PAD_ATA_CS1__IPU_DIAGB_1
+656 MX35_PAD_ATA_CS1__ARM11P_TOP_MAX1_HMASTER_1
+657 MX35_PAD_ATA_DIOR__ATA_DIOR
+658 MX35_PAD_ATA_DIOR__ESDHC3_DAT0
+659 MX35_PAD_ATA_DIOR__USB_TOP_USBOTG_DIR
+660 MX35_PAD_ATA_DIOR__IPU_DISPB_BE0
+661 MX35_PAD_ATA_DIOR__CSPI2_SS1
+662 MX35_PAD_ATA_DIOR__GPIO2_8
+663 MX35_PAD_ATA_DIOR__IPU_DIAGB_2
+664 MX35_PAD_ATA_DIOR__ARM11P_TOP_MAX1_HMASTER_2
+665 MX35_PAD_ATA_DIOW__ATA_DIOW
+666 MX35_PAD_ATA_DIOW__ESDHC3_DAT1
+667 MX35_PAD_ATA_DIOW__USB_TOP_USBOTG_STP
+668 MX35_PAD_ATA_DIOW__IPU_DISPB_BE1
+669 MX35_PAD_ATA_DIOW__CSPI2_MOSI
+670 MX35_PAD_ATA_DIOW__GPIO2_9
+671 MX35_PAD_ATA_DIOW__IPU_DIAGB_3
+672 MX35_PAD_ATA_DIOW__ARM11P_TOP_MAX1_HMASTER_3
+673 MX35_PAD_ATA_DMACK__ATA_DMACK
+674 MX35_PAD_ATA_DMACK__ESDHC3_DAT2
+675 MX35_PAD_ATA_DMACK__USB_TOP_USBOTG_NXT
+676 MX35_PAD_ATA_DMACK__CSPI2_MISO
+677 MX35_PAD_ATA_DMACK__GPIO2_10
+678 MX35_PAD_ATA_DMACK__IPU_DIAGB_4
+679 MX35_PAD_ATA_DMACK__ARM11P_TOP_MAX0_HMASTER_0
+680 MX35_PAD_ATA_RESET_B__ATA_RESET_B
+681 MX35_PAD_ATA_RESET_B__ESDHC3_DAT3
+682 MX35_PAD_ATA_RESET_B__USB_TOP_USBOTG_DATA_0
+683 MX35_PAD_ATA_RESET_B__IPU_DISPB_SD_D_O
+684 MX35_PAD_ATA_RESET_B__CSPI2_RDY
+685 MX35_PAD_ATA_RESET_B__GPIO2_11
+686 MX35_PAD_ATA_RESET_B__IPU_DIAGB_5
+687 MX35_PAD_ATA_RESET_B__ARM11P_TOP_MAX0_HMASTER_1
+688 MX35_PAD_ATA_IORDY__ATA_IORDY
+689 MX35_PAD_ATA_IORDY__ESDHC3_DAT4
+690 MX35_PAD_ATA_IORDY__USB_TOP_USBOTG_DATA_1
+691 MX35_PAD_ATA_IORDY__IPU_DISPB_SD_D_IO
+692 MX35_PAD_ATA_IORDY__ESDHC2_DAT4
+693 MX35_PAD_ATA_IORDY__GPIO2_12
+694 MX35_PAD_ATA_IORDY__IPU_DIAGB_6
+695 MX35_PAD_ATA_IORDY__ARM11P_TOP_MAX0_HMASTER_2
+696 MX35_PAD_ATA_DATA0__ATA_DATA_0
+697 MX35_PAD_ATA_DATA0__ESDHC3_DAT5
+698 MX35_PAD_ATA_DATA0__USB_TOP_USBOTG_DATA_2
+699 MX35_PAD_ATA_DATA0__IPU_DISPB_D12_VSYNC
+700 MX35_PAD_ATA_DATA0__ESDHC2_DAT5
+701 MX35_PAD_ATA_DATA0__GPIO2_13
+702 MX35_PAD_ATA_DATA0__IPU_DIAGB_7
+703 MX35_PAD_ATA_DATA0__ARM11P_TOP_MAX0_HMASTER_3
+704 MX35_PAD_ATA_DATA1__ATA_DATA_1
+705 MX35_PAD_ATA_DATA1__ESDHC3_DAT6
+706 MX35_PAD_ATA_DATA1__USB_TOP_USBOTG_DATA_3
+707 MX35_PAD_ATA_DATA1__IPU_DISPB_SD_CLK
+708 MX35_PAD_ATA_DATA1__ESDHC2_DAT6
+709 MX35_PAD_ATA_DATA1__GPIO2_14
+710 MX35_PAD_ATA_DATA1__IPU_DIAGB_8
+711 MX35_PAD_ATA_DATA1__ARM11P_TOP_TRACE_27
+712 MX35_PAD_ATA_DATA2__ATA_DATA_2
+713 MX35_PAD_ATA_DATA2__ESDHC3_DAT7
+714 MX35_PAD_ATA_DATA2__USB_TOP_USBOTG_DATA_4
+715 MX35_PAD_ATA_DATA2__IPU_DISPB_SER_RS
+716 MX35_PAD_ATA_DATA2__ESDHC2_DAT7
+717 MX35_PAD_ATA_DATA2__GPIO2_15
+718 MX35_PAD_ATA_DATA2__IPU_DIAGB_9
+719 MX35_PAD_ATA_DATA2__ARM11P_TOP_TRACE_28
+720 MX35_PAD_ATA_DATA3__ATA_DATA_3
+721 MX35_PAD_ATA_DATA3__ESDHC3_CLK
+722 MX35_PAD_ATA_DATA3__USB_TOP_USBOTG_DATA_5
+723 MX35_PAD_ATA_DATA3__CSPI2_SCLK
+724 MX35_PAD_ATA_DATA3__GPIO2_16
+725 MX35_PAD_ATA_DATA3__IPU_DIAGB_10
+726 MX35_PAD_ATA_DATA3__ARM11P_TOP_TRACE_29
+727 MX35_PAD_ATA_DATA4__ATA_DATA_4
+728 MX35_PAD_ATA_DATA4__ESDHC3_CMD
+729 MX35_PAD_ATA_DATA4__USB_TOP_USBOTG_DATA_6
+730 MX35_PAD_ATA_DATA4__GPIO2_17
+731 MX35_PAD_ATA_DATA4__IPU_DIAGB_11
+732 MX35_PAD_ATA_DATA4__ARM11P_TOP_TRACE_30
+733 MX35_PAD_ATA_DATA5__ATA_DATA_5
+734 MX35_PAD_ATA_DATA5__USB_TOP_USBOTG_DATA_7
+735 MX35_PAD_ATA_DATA5__GPIO2_18
+736 MX35_PAD_ATA_DATA5__IPU_DIAGB_12
+737 MX35_PAD_ATA_DATA5__ARM11P_TOP_TRACE_31
+738 MX35_PAD_ATA_DATA6__ATA_DATA_6
+739 MX35_PAD_ATA_DATA6__CAN1_TXCAN
+740 MX35_PAD_ATA_DATA6__UART1_DTR
+741 MX35_PAD_ATA_DATA6__AUDMUX_AUD6_TXD
+742 MX35_PAD_ATA_DATA6__GPIO2_19
+743 MX35_PAD_ATA_DATA6__IPU_DIAGB_13
+744 MX35_PAD_ATA_DATA7__ATA_DATA_7
+745 MX35_PAD_ATA_DATA7__CAN1_RXCAN
+746 MX35_PAD_ATA_DATA7__UART1_DSR
+747 MX35_PAD_ATA_DATA7__AUDMUX_AUD6_RXD
+748 MX35_PAD_ATA_DATA7__GPIO2_20
+749 MX35_PAD_ATA_DATA7__IPU_DIAGB_14
+750 MX35_PAD_ATA_DATA8__ATA_DATA_8
+751 MX35_PAD_ATA_DATA8__UART3_RTS
+752 MX35_PAD_ATA_DATA8__UART1_RI
+753 MX35_PAD_ATA_DATA8__AUDMUX_AUD6_TXC
+754 MX35_PAD_ATA_DATA8__GPIO2_21
+755 MX35_PAD_ATA_DATA8__IPU_DIAGB_15
+756 MX35_PAD_ATA_DATA9__ATA_DATA_9
+757 MX35_PAD_ATA_DATA9__UART3_CTS
+758 MX35_PAD_ATA_DATA9__UART1_DCD
+759 MX35_PAD_ATA_DATA9__AUDMUX_AUD6_TXFS
+760 MX35_PAD_ATA_DATA9__GPIO2_22
+761 MX35_PAD_ATA_DATA9__IPU_DIAGB_16
+762 MX35_PAD_ATA_DATA10__ATA_DATA_10
+763 MX35_PAD_ATA_DATA10__UART3_RXD_MUX
+764 MX35_PAD_ATA_DATA10__AUDMUX_AUD6_RXC
+765 MX35_PAD_ATA_DATA10__GPIO2_23
+766 MX35_PAD_ATA_DATA10__IPU_DIAGB_17
+767 MX35_PAD_ATA_DATA11__ATA_DATA_11
+768 MX35_PAD_ATA_DATA11__UART3_TXD_MUX
+769 MX35_PAD_ATA_DATA11__AUDMUX_AUD6_RXFS
+770 MX35_PAD_ATA_DATA11__GPIO2_24
+771 MX35_PAD_ATA_DATA11__IPU_DIAGB_18
+772 MX35_PAD_ATA_DATA12__ATA_DATA_12
+773 MX35_PAD_ATA_DATA12__I2C3_SCL
+774 MX35_PAD_ATA_DATA12__GPIO2_25
+775 MX35_PAD_ATA_DATA12__IPU_DIAGB_19
+776 MX35_PAD_ATA_DATA13__ATA_DATA_13
+777 MX35_PAD_ATA_DATA13__I2C3_SDA
+778 MX35_PAD_ATA_DATA13__GPIO2_26
+779 MX35_PAD_ATA_DATA13__IPU_DIAGB_20
+780 MX35_PAD_ATA_DATA14__ATA_DATA_14
+781 MX35_PAD_ATA_DATA14__IPU_CSI_D_0
+782 MX35_PAD_ATA_DATA14__KPP_ROW_0
+783 MX35_PAD_ATA_DATA14__GPIO2_27
+784 MX35_PAD_ATA_DATA14__IPU_DIAGB_21
+785 MX35_PAD_ATA_DATA15__ATA_DATA_15
+786 MX35_PAD_ATA_DATA15__IPU_CSI_D_1
+787 MX35_PAD_ATA_DATA15__KPP_ROW_1
+788 MX35_PAD_ATA_DATA15__GPIO2_28
+789 MX35_PAD_ATA_DATA15__IPU_DIAGB_22
+790 MX35_PAD_ATA_INTRQ__ATA_INTRQ
+791 MX35_PAD_ATA_INTRQ__IPU_CSI_D_2
+792 MX35_PAD_ATA_INTRQ__KPP_ROW_2
+793 MX35_PAD_ATA_INTRQ__GPIO2_29
+794 MX35_PAD_ATA_INTRQ__IPU_DIAGB_23
+795 MX35_PAD_ATA_BUFF_EN__ATA_BUFFER_EN
+796 MX35_PAD_ATA_BUFF_EN__IPU_CSI_D_3
+797 MX35_PAD_ATA_BUFF_EN__KPP_ROW_3
+798 MX35_PAD_ATA_BUFF_EN__GPIO2_30
+799 MX35_PAD_ATA_BUFF_EN__IPU_DIAGB_24
+800 MX35_PAD_ATA_DMARQ__ATA_DMARQ
+801 MX35_PAD_ATA_DMARQ__IPU_CSI_D_4
+802 MX35_PAD_ATA_DMARQ__KPP_COL_0
+803 MX35_PAD_ATA_DMARQ__GPIO2_31
+804 MX35_PAD_ATA_DMARQ__IPU_DIAGB_25
+805 MX35_PAD_ATA_DMARQ__ECT_CTI_TRIG_IN1_4
+806 MX35_PAD_ATA_DA0__ATA_DA_0
+807 MX35_PAD_ATA_DA0__IPU_CSI_D_5
+808 MX35_PAD_ATA_DA0__KPP_COL_1
+809 MX35_PAD_ATA_DA0__GPIO3_0
+810 MX35_PAD_ATA_DA0__IPU_DIAGB_26
+811 MX35_PAD_ATA_DA0__ECT_CTI_TRIG_IN1_5
+812 MX35_PAD_ATA_DA1__ATA_DA_1
+813 MX35_PAD_ATA_DA1__IPU_CSI_D_6
+814 MX35_PAD_ATA_DA1__KPP_COL_2
+815 MX35_PAD_ATA_DA1__GPIO3_1
+816 MX35_PAD_ATA_DA1__IPU_DIAGB_27
+817 MX35_PAD_ATA_DA1__ECT_CTI_TRIG_IN1_6
+818 MX35_PAD_ATA_DA2__ATA_DA_2
+819 MX35_PAD_ATA_DA2__IPU_CSI_D_7
+820 MX35_PAD_ATA_DA2__KPP_COL_3
+821 MX35_PAD_ATA_DA2__GPIO3_2
+822 MX35_PAD_ATA_DA2__IPU_DIAGB_28
+823 MX35_PAD_ATA_DA2__ECT_CTI_TRIG_IN1_7
+824 MX35_PAD_MLB_CLK__MLB_MLBCLK
+825 MX35_PAD_MLB_CLK__GPIO3_3
+826 MX35_PAD_MLB_DAT__MLB_MLBDAT
+827 MX35_PAD_MLB_DAT__GPIO3_4
+828 MX35_PAD_MLB_SIG__MLB_MLBSIG
+829 MX35_PAD_MLB_SIG__GPIO3_5
+830 MX35_PAD_FEC_TX_CLK__FEC_TX_CLK
+831 MX35_PAD_FEC_TX_CLK__ESDHC1_DAT4
+832 MX35_PAD_FEC_TX_CLK__UART3_RXD_MUX
+833 MX35_PAD_FEC_TX_CLK__USB_TOP_USBH2_DIR
+834 MX35_PAD_FEC_TX_CLK__CSPI2_MOSI
+835 MX35_PAD_FEC_TX_CLK__GPIO3_6
+836 MX35_PAD_FEC_TX_CLK__IPU_DISPB_D12_VSYNC
+837 MX35_PAD_FEC_TX_CLK__ARM11P_TOP_EVNTBUS_0
+838 MX35_PAD_FEC_RX_CLK__FEC_RX_CLK
+839 MX35_PAD_FEC_RX_CLK__ESDHC1_DAT5
+840 MX35_PAD_FEC_RX_CLK__UART3_TXD_MUX
+841 MX35_PAD_FEC_RX_CLK__USB_TOP_USBH2_STP
+842 MX35_PAD_FEC_RX_CLK__CSPI2_MISO
+843 MX35_PAD_FEC_RX_CLK__GPIO3_7
+844 MX35_PAD_FEC_RX_CLK__IPU_DISPB_SD_D_I
+845 MX35_PAD_FEC_RX_CLK__ARM11P_TOP_EVNTBUS_1
+846 MX35_PAD_FEC_RX_DV__FEC_RX_DV
+847 MX35_PAD_FEC_RX_DV__ESDHC1_DAT6
+848 MX35_PAD_FEC_RX_DV__UART3_RTS
+849 MX35_PAD_FEC_RX_DV__USB_TOP_USBH2_NXT
+850 MX35_PAD_FEC_RX_DV__CSPI2_SCLK
+851 MX35_PAD_FEC_RX_DV__GPIO3_8
+852 MX35_PAD_FEC_RX_DV__IPU_DISPB_SD_CLK
+853 MX35_PAD_FEC_RX_DV__ARM11P_TOP_EVNTBUS_2
+854 MX35_PAD_FEC_COL__FEC_COL
+855 MX35_PAD_FEC_COL__ESDHC1_DAT7
+856 MX35_PAD_FEC_COL__UART3_CTS
+857 MX35_PAD_FEC_COL__USB_TOP_USBH2_DATA_0
+858 MX35_PAD_FEC_COL__CSPI2_RDY
+859 MX35_PAD_FEC_COL__GPIO3_9
+860 MX35_PAD_FEC_COL__IPU_DISPB_SER_RS
+861 MX35_PAD_FEC_COL__ARM11P_TOP_EVNTBUS_3
+862 MX35_PAD_FEC_RDATA0__FEC_RDATA_0
+863 MX35_PAD_FEC_RDATA0__PWM_PWMO
+864 MX35_PAD_FEC_RDATA0__UART3_DTR
+865 MX35_PAD_FEC_RDATA0__USB_TOP_USBH2_DATA_1
+866 MX35_PAD_FEC_RDATA0__CSPI2_SS0
+867 MX35_PAD_FEC_RDATA0__GPIO3_10
+868 MX35_PAD_FEC_RDATA0__IPU_DISPB_CS1
+869 MX35_PAD_FEC_RDATA0__ARM11P_TOP_EVNTBUS_4
+870 MX35_PAD_FEC_TDATA0__FEC_TDATA_0
+871 MX35_PAD_FEC_TDATA0__SPDIF_SPDIF_OUT1
+872 MX35_PAD_FEC_TDATA0__UART3_DSR
+873 MX35_PAD_FEC_TDATA0__USB_TOP_USBH2_DATA_2
+874 MX35_PAD_FEC_TDATA0__CSPI2_SS1
+875 MX35_PAD_FEC_TDATA0__GPIO3_11
+876 MX35_PAD_FEC_TDATA0__IPU_DISPB_CS0
+877 MX35_PAD_FEC_TDATA0__ARM11P_TOP_EVNTBUS_5
+878 MX35_PAD_FEC_TX_EN__FEC_TX_EN
+879 MX35_PAD_FEC_TX_EN__SPDIF_SPDIF_IN1
+880 MX35_PAD_FEC_TX_EN__UART3_RI
+881 MX35_PAD_FEC_TX_EN__USB_TOP_USBH2_DATA_3
+882 MX35_PAD_FEC_TX_EN__GPIO3_12
+883 MX35_PAD_FEC_TX_EN__IPU_DISPB_PAR_RS
+884 MX35_PAD_FEC_TX_EN__ARM11P_TOP_EVNTBUS_6
+885 MX35_PAD_FEC_MDC__FEC_MDC
+886 MX35_PAD_FEC_MDC__CAN2_TXCAN
+887 MX35_PAD_FEC_MDC__UART3_DCD
+888 MX35_PAD_FEC_MDC__USB_TOP_USBH2_DATA_4
+889 MX35_PAD_FEC_MDC__GPIO3_13
+890 MX35_PAD_FEC_MDC__IPU_DISPB_WR
+891 MX35_PAD_FEC_MDC__ARM11P_TOP_EVNTBUS_7
+892 MX35_PAD_FEC_MDIO__FEC_MDIO
+893 MX35_PAD_FEC_MDIO__CAN2_RXCAN
+894 MX35_PAD_FEC_MDIO__USB_TOP_USBH2_DATA_5
+895 MX35_PAD_FEC_MDIO__GPIO3_14
+896 MX35_PAD_FEC_MDIO__IPU_DISPB_RD
+897 MX35_PAD_FEC_MDIO__ARM11P_TOP_EVNTBUS_8
+898 MX35_PAD_FEC_TX_ERR__FEC_TX_ERR
+899 MX35_PAD_FEC_TX_ERR__OWIRE_LINE
+900 MX35_PAD_FEC_TX_ERR__SPDIF_SPDIF_EXTCLK
+901 MX35_PAD_FEC_TX_ERR__USB_TOP_USBH2_DATA_6
+902 MX35_PAD_FEC_TX_ERR__GPIO3_15
+903 MX35_PAD_FEC_TX_ERR__IPU_DISPB_D0_VSYNC
+904 MX35_PAD_FEC_TX_ERR__ARM11P_TOP_EVNTBUS_9
+905 MX35_PAD_FEC_RX_ERR__FEC_RX_ERR
+906 MX35_PAD_FEC_RX_ERR__IPU_CSI_D_0
+907 MX35_PAD_FEC_RX_ERR__USB_TOP_USBH2_DATA_7
+908 MX35_PAD_FEC_RX_ERR__KPP_COL_4
+909 MX35_PAD_FEC_RX_ERR__GPIO3_16
+910 MX35_PAD_FEC_RX_ERR__IPU_DISPB_SD_D_IO
+911 MX35_PAD_FEC_CRS__FEC_CRS
+912 MX35_PAD_FEC_CRS__IPU_CSI_D_1
+913 MX35_PAD_FEC_CRS__USB_TOP_USBH2_PWR
+914 MX35_PAD_FEC_CRS__KPP_COL_5
+915 MX35_PAD_FEC_CRS__GPIO3_17
+916 MX35_PAD_FEC_CRS__IPU_FLASH_STROBE
+917 MX35_PAD_FEC_RDATA1__FEC_RDATA_1
+918 MX35_PAD_FEC_RDATA1__IPU_CSI_D_2
+919 MX35_PAD_FEC_RDATA1__AUDMUX_AUD6_RXC
+920 MX35_PAD_FEC_RDATA1__USB_TOP_USBH2_OC
+921 MX35_PAD_FEC_RDATA1__KPP_COL_6
+922 MX35_PAD_FEC_RDATA1__GPIO3_18
+923 MX35_PAD_FEC_RDATA1__IPU_DISPB_BE0
+924 MX35_PAD_FEC_TDATA1__FEC_TDATA_1
+925 MX35_PAD_FEC_TDATA1__IPU_CSI_D_3
+926 MX35_PAD_FEC_TDATA1__AUDMUX_AUD6_RXFS
+927 MX35_PAD_FEC_TDATA1__KPP_COL_7
+928 MX35_PAD_FEC_TDATA1__GPIO3_19
+929 MX35_PAD_FEC_TDATA1__IPU_DISPB_BE1
+930 MX35_PAD_FEC_RDATA2__FEC_RDATA_2
+931 MX35_PAD_FEC_RDATA2__IPU_CSI_D_4
+932 MX35_PAD_FEC_RDATA2__AUDMUX_AUD6_TXD
+933 MX35_PAD_FEC_RDATA2__KPP_ROW_4
+934 MX35_PAD_FEC_RDATA2__GPIO3_20
+935 MX35_PAD_FEC_TDATA2__FEC_TDATA_2
+936 MX35_PAD_FEC_TDATA2__IPU_CSI_D_5
+937 MX35_PAD_FEC_TDATA2__AUDMUX_AUD6_RXD
+938 MX35_PAD_FEC_TDATA2__KPP_ROW_5
+939 MX35_PAD_FEC_TDATA2__GPIO3_21
+940 MX35_PAD_FEC_RDATA3__FEC_RDATA_3
+941 MX35_PAD_FEC_RDATA3__IPU_CSI_D_6
+942 MX35_PAD_FEC_RDATA3__AUDMUX_AUD6_TXC
+943 MX35_PAD_FEC_RDATA3__KPP_ROW_6
+944 MX35_PAD_FEC_RDATA3__GPIO3_22
+945 MX35_PAD_FEC_TDATA3__FEC_TDATA_3
+946 MX35_PAD_FEC_TDATA3__IPU_CSI_D_7
+947 MX35_PAD_FEC_TDATA3__AUDMUX_AUD6_TXFS
+948 MX35_PAD_FEC_TDATA3__KPP_ROW_7
+949 MX35_PAD_FEC_TDATA3__GPIO3_23
+950 MX35_PAD_EXT_ARMCLK__CCM_EXT_ARMCLK
+951 MX35_PAD_TEST_MODE__TCU_TEST_MODE
diff --git a/Documentation/devicetree/bindings/pinctrl/marvell,armada-370-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/marvell,armada-370-pinctrl.txt
new file mode 100644
index 0000000..01ef408
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/marvell,armada-370-pinctrl.txt
@@ -0,0 +1,95 @@
+* Marvell Armada 370 SoC pinctrl driver for mpp
+
+Please refer to marvell,mvebu-pinctrl.txt in this directory for common binding
+part and usage.
+
+Required properties:
+- compatible: "marvell,88f6710-pinctrl"
+
+Available mpp pins/groups and functions:
+Note: brackets (x) are not part of the mpp name for marvell,function and given
+only for more detailed description in this document.
+
+name          pins     functions
+================================================================================
+mpp0          0        gpio, uart0(rxd)
+mpp1          1        gpo, uart0(txd)
+mpp2          2        gpio, i2c0(sck), uart0(txd)
+mpp3          3        gpio, i2c0(sda), uart0(rxd)
+mpp4          4        gpio, cpu_pd(vdd)
+mpp5          5        gpo, ge0(txclko), uart1(txd), spi1(clk), audio(mclk)
+mpp6          6        gpio, ge0(txd0), sata0(prsnt), tdm(rst), audio(sdo)
+mpp7          7        gpo, ge0(txd1), tdm(tdx), audio(lrclk)
+mpp8          8        gpio, ge0(txd2), uart0(rts), tdm(drx), audio(bclk)
+mpp9          9        gpo, ge0(txd3), uart1(txd), sd0(clk), audio(spdifo)
+mpp10         10       gpio, ge0(txctl), uart0(cts), tdm(fsync), audio(sdi)
+mpp11         11       gpio, ge0(rxd0), uart1(rxd), sd0(cmd), spi0(cs1),
+                       sata1(prsnt), spi1(cs1)
+mpp12         12       gpio, ge0(rxd1), i2c1(sda), sd0(d0), spi1(cs0),
+                       audio(spdifi)
+mpp13         13       gpio, ge0(rxd2), i2c1(sck), sd0(d1), tdm(pclk),
+                       audio(rmclk)
+mpp14         14       gpio, ge0(rxd3), pcie(clkreq0), sd0(d2), spi1(mosi),
+                       spi0(cs2)
+mpp15         15       gpio, ge0(rxctl), pcie(clkreq1), sd0(d3), spi1(miso),
+                       spi0(cs3)
+mpp16         16       gpio, ge0(rxclk), uart1(rxd), tdm(int), audio(extclk)
+mpp17         17       gpo, ge(mdc)
+mpp18         18       gpio, ge(mdio)
+mpp19         19       gpio, ge0(txclk), ge1(txclkout), tdm(pclk)
+mpp20         20       gpo, ge0(txd4), ge1(txd0)
+mpp21         21       gpo, ge0(txd5), ge1(txd1), uart1(txd)
+mpp22         22       gpo, ge0(txd6), ge1(txd2), uart0(rts)
+mpp23         23       gpo, ge0(txd7), ge1(txd3), spi1(mosi)
+mpp24         24       gpio, ge0(col), ge1(txctl), spi1(cs0)
+mpp25         25       gpio, ge0(rxerr), ge1(rxd0), uart1(rxd)
+mpp26         26       gpio, ge0(crs), ge1(rxd1), spi1(miso)
+mpp27         27       gpio, ge0(rxd4), ge1(rxd2), uart0(cts)
+mpp28         28       gpio, ge0(rxd5), ge1(rxd3)
+mpp29         29       gpio, ge0(rxd6), ge1(rxctl), i2c1(sda)
+mpp30         30       gpio, ge0(rxd7), ge1(rxclk), i2c1(sck)
+mpp31         31       gpio, tclk, ge0(txerr)
+mpp32         32       gpio, spi0(cs0)
+mpp33         33       gpio, dev(bootcs), spi0(cs0)
+mpp34         34       gpo, dev(wen0), spi0(mosi)
+mpp35         35       gpo, dev(oen), spi0(sck)
+mpp36         36       gpo, dev(a1), spi0(miso)
+mpp37         37       gpo, dev(a0), sata0(prsnt)
+mpp38         38       gpio, dev(ready), uart1(cts), uart0(cts)
+mpp39         39       gpo, dev(ad0), audio(spdifo)
+mpp40         40       gpio, dev(ad1), uart1(rts), uart0(rts)
+mpp41         41       gpio, dev(ad2), uart1(rxd)
+mpp42         42       gpo, dev(ad3), uart1(txd)
+mpp43         43       gpo, dev(ad4), audio(bclk)
+mpp44         44       gpo, dev(ad5), audio(mclk)
+mpp45         45       gpo, dev(ad6), audio(lrclk)
+mpp46         46       gpo, dev(ad7), audio(sdo)
+mpp47         47       gpo, dev(ad8), sd0(clk), audio(spdifo)
+mpp48         48       gpio, dev(ad9), uart0(rts), sd0(cmd), sata1(prsnt),
+                       spi0(cs1)
+mpp49         49       gpio, dev(ad10), pcie(clkreq1), sd0(d0), spi1(cs0),
+                       audio(spdifi)
+mpp50         50       gpio, dev(ad11), uart0(cts), sd0(d1), spi1(miso),
+                       audio(rmclk)
+mpp51         51       gpio, dev(ad12), i2c1(sda), sd0(d2), spi1(mosi)
+mpp52         52       gpio, dev(ad13), i2c1(sck), sd0(d3), spi1(sck)
+mpp53         53       gpio, dev(ad14), sd0(clk), tdm(pclk), spi0(cs2),
+                       pcie(clkreq1)
+mpp54         54       gpo, dev(ad15), tdm(dtx)
+mpp55         55       gpio, dev(cs1), uart1(txd), tdm(rst), sata1(prsnt),
+                       sata0(prsnt)
+mpp56         56       gpio, dev(cs2), uart1(cts), uart0(cts), spi0(cs3),
+                       pcie(clkreq0), spi1(cs1)
+mpp57         57       gpio, dev(cs3), uart1(rxd), tdm(fsync), sata0(prsnt),
+                       audio(sdo)
+mpp58         58       gpio, dev(cs0), uart1(rts), tdm(int), audio(extclk),
+                       uart0(rts)
+mpp59         59       gpo, dev(ale0), uart1(rts), uart0(rts), audio(bclk)
+mpp60         60       gpio, dev(ale1), uart1(rxd), sata0(prsnt), pcie(rst-out),
+                       audio(sdi)
+mpp61         61       gpo, dev(wen1), uart1(txd), audio(rclk)
+mpp62         62       gpio, dev(a2), uart1(cts), tdm(drx), pcie(clkreq0),
+                       audio(mclk), uart0(cts)
+mpp63         63       gpo, spi0(sck), tclk
+mpp64         64       gpio, spi0(miso), spi0-1(cs1)
+mpp65         65       gpio, spi0(mosi), spi0-1(cs2)
diff --git a/Documentation/devicetree/bindings/pinctrl/marvell,armada-xp-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/marvell,armada-xp-pinctrl.txt
new file mode 100644
index 0000000..bfa0a2e
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/marvell,armada-xp-pinctrl.txt
@@ -0,0 +1,100 @@
+* Marvell Armada XP SoC pinctrl driver for mpp
+
+Please refer to marvell,mvebu-pinctrl.txt in this directory for common binding
+part and usage.
+
+Required properties:
+- compatible: "marvell,mv78230-pinctrl", "marvell,mv78260-pinctrl",
+              "marvell,mv78460-pinctrl"
+
+This driver supports all Armada XP variants, i.e. mv78230, mv78260, and mv78460.
+
+Available mpp pins/groups and functions:
+Note: brackets (x) are not part of the mpp name for marvell,function and given
+only for more detailed description in this document.
+
+* Marvell Armada XP (all variants)
+
+name          pins     functions
+================================================================================
+mpp0          0        gpio, ge0(txclko), lcd(d0)
+mpp1          1        gpio, ge0(txd0), lcd(d1)
+mpp2          2        gpio, ge0(txd1), lcd(d2)
+mpp3          3        gpio, ge0(txd2), lcd(d3)
+mpp4          4        gpio, ge0(txd3), lcd(d4)
+mpp5          5        gpio, ge0(txctl), lcd(d5)
+mpp6          6        gpio, ge0(rxd0), lcd(d6)
+mpp7          7        gpio, ge0(rxd1), lcd(d7)
+mpp8          8        gpio, ge0(rxd2), lcd(d8)
+mpp9          9        gpio, ge0(rxd3), lcd(d9)
+mpp10         10       gpio, ge0(rxctl), lcd(d10)
+mpp11         11       gpio, ge0(rxclk), lcd(d11)
+mpp12         12       gpio, ge0(txd4), ge1(txd0), lcd(d12)
+mpp13         13       gpio, ge0(txd5), ge1(txd1), lcd(d13)
+mpp14         14       gpio, ge0(txd6), ge1(txd2), lcd(d15)
+mpp15         15       gpio, ge0(txd7), ge1(txd3), lcd(d16)
+mpp16         16       gpio, ge0(txd7), ge1(txd3), lcd(d16)
+mpp17         17       gpio, ge0(col), ge1(txctl), lcd(d17)
+mpp18         18       gpio, ge0(rxerr), ge1(rxd0), lcd(d18), ptp(trig)
+mpp19         19       gpio, ge0(crs), ge1(rxd1), lcd(d19), ptp(evreq)
+mpp20         20       gpio, ge0(rxd4), ge1(rxd2), lcd(d20), ptp(clk)
+mpp21         21       gpio, ge0(rxd5), ge1(rxd3), lcd(d21), mem(bat)
+mpp22         22       gpio, ge0(rxd6), ge1(rxctl), lcd(d22), sata0(prsnt)
+mpp23         23       gpio, ge0(rxd7), ge1(rxclk), lcd(d23), sata1(prsnt)
+mpp24         24       gpio, lcd(hsync), sata1(prsnt), nf(bootcs-re), tdm(rst)
+mpp25         25       gpio, lcd(vsync), sata0(prsnt), nf(bootcs-we), tdm(pclk)
+mpp26         26       gpio, lcd(clk), tdm(fsync), vdd(cpu1-pd)
+mpp27         27       gpio, lcd(e), tdm(dtx), ptp(trig)
+mpp28         28       gpio, lcd(pwm), tdm(drx), ptp(evreq)
+mpp29         29       gpio, lcd(ref-clk), tdm(int0), ptp(clk), vdd(cpu0-pd)
+mpp30         30       gpio, tdm(int1), sd0(clk)
+mpp31         31       gpio, tdm(int2), sd0(cmd), vdd(cpu0-pd)
+mpp32         32       gpio, tdm(int3), sd0(d0), vdd(cpu1-pd)
+mpp33         33       gpio, tdm(int4), sd0(d1), mem(bat)
+mpp34         34       gpio, tdm(int5), sd0(d2), sata0(prsnt)
+mpp35         35       gpio, tdm(int6), sd0(d3), sata1(prsnt)
+mpp36         36       gpio, spi(mosi)
+mpp37         37       gpio, spi(miso)
+mpp38         38       gpio, spi(sck)
+mpp39         39       gpio, spi(cs0)
+mpp40         40       gpio, spi(cs1), uart2(cts), lcd(vga-hsync), vdd(cpu1-pd),
+                       pcie(clkreq0)
+mpp41         41       gpio, spi(cs2), uart2(rts), lcd(vga-vsync), sata1(prsnt),
+                       pcie(clkreq1)
+mpp42         42       gpio, uart2(rxd), uart0(cts), tdm(int7), tdm-1(timer),
+                       vdd(cpu0-pd)
+mpp43         43       gpio, uart2(txd), uart0(rts), spi(cs3), pcie(rstout),
+                       vdd(cpu2-3-pd){1}
+mpp44         44       gpio, uart2(cts), uart3(rxd), spi(cs4), pcie(clkreq2),
+                       mem(bat)
+mpp45         45       gpio, uart2(rts), uart3(txd), spi(cs5), sata1(prsnt)
+mpp46         46       gpio, uart3(rts), uart1(rts), spi(cs6), sata0(prsnt)
+mpp47         47       gpio, uart3(cts), uart1(cts), spi(cs7), pcie(clkreq3),
+                       ref(clkout)
+mpp48         48       gpio, tclk, dev(burst/last)
+
+* Marvell Armada XP (mv78260 and mv78460 only)
+
+name          pins     functions
+================================================================================
+mpp49         49       gpio, dev(we3)
+mpp50         50       gpio, dev(we2)
+mpp51         51       gpio, dev(ad16)
+mpp52         52       gpio, dev(ad17)
+mpp53         53       gpio, dev(ad18)
+mpp54         54       gpio, dev(ad19)
+mpp55         55       gpio, dev(ad20), vdd(cpu0-pd)
+mpp56         56       gpio, dev(ad21), vdd(cpu1-pd)
+mpp57         57       gpio, dev(ad22), vdd(cpu2-3-pd){1}
+mpp58         58       gpio, dev(ad23)
+mpp59         59       gpio, dev(ad24)
+mpp60         60       gpio, dev(ad25)
+mpp61         61       gpio, dev(ad26)
+mpp62         62       gpio, dev(ad27)
+mpp63         63       gpio, dev(ad28)
+mpp64         64       gpio, dev(ad29)
+mpp65         65       gpio, dev(ad30)
+mpp66         66       gpio, dev(ad31)
+
+Notes:
+* {1} vdd(cpu2-3-pd) only available on mv78460.
diff --git a/Documentation/devicetree/bindings/pinctrl/marvell,dove-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/marvell,dove-pinctrl.txt
new file mode 100644
index 0000000..a648aaa
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/marvell,dove-pinctrl.txt
@@ -0,0 +1,72 @@
+* Marvell Dove SoC pinctrl driver for mpp
+
+Please refer to marvell,mvebu-pinctrl.txt in this directory for common binding
+part and usage.
+
+Required properties:
+- compatible: "marvell,dove-pinctrl"
+- clocks: (optional) phandle of pdma clock
+
+Available mpp pins/groups and functions:
+Note: brackets (x) are not part of the mpp name for marvell,function and given
+only for more detailed description in this document.
+
+name          pins     functions
+================================================================================
+mpp0          0        gpio, pmu, uart2(rts), sdio0(cd), lcd0(pwm)
+mpp1          1        gpio, pmu, uart2(cts), sdio0(wp), lcd1(pwm)
+mpp2          2        gpio, pmu, uart2(txd), sdio0(buspwr), sata(prsnt),
+                       uart1(rts)
+mpp3          3        gpio, pmu, uart2(rxd), sdio0(ledctrl), sata(act),
+                       uart1(cts), lcd-spi(cs1)
+mpp4          4        gpio, pmu, uart3(rts), sdio1(cd), spi1(miso)
+mpp5          5        gpio, pmu, uart3(cts), sdio1(wp), spi1(cs)
+mpp6          6        gpio, pmu, uart3(txd), sdio1(buspwr), spi1(mosi)
+mpp7          7        gpio, pmu, uart3(rxd), sdio1(ledctrl), spi1(sck)
+mpp8          8        gpio, pmu, watchdog(rstout)
+mpp9          9        gpio, pmu, pex1(clkreq)
+mpp10         10       gpio, pmu, ssp(sclk)
+mpp11         11       gpio, pmu, sata(prsnt), sata-1(act), sdio0(ledctrl),
+                       sdio1(ledctrl), pex0(clkreq)
+mpp12         12       gpio, pmu, uart2(rts), audio0(extclk), sdio1(cd), sata(act)
+mpp13         13       gpio, pmu, uart2(cts), audio1(extclk), sdio1(wp),
+                       ssp(extclk)
+mpp14         14       gpio, pmu, uart2(txd), sdio1(buspwr), ssp(rxd)
+mpp15         15       gpio, pmu, uart2(rxd), sdio1(ledctrl), ssp(sfrm)
+mpp16         16       gpio, uart3(rts), sdio0(cd), ac97(sdi1), lcd-spi(cs1)
+mpp17         17       gpio, uart3(cts), sdio0(wp), ac97(sdi2), twsi(sda),
+                       ac97-1(sysclko)
+mpp18         18       gpio, uart3(txd), sdio0(buspwr), ac97(sdi3), lcd0(pwm)
+mpp19         19       gpio, uart3(rxd), sdio0(ledctrl), twsi(sck)
+mpp20         20       gpio, sdio0(cd), sdio1(cd), spi1(miso), lcd-spi(miso),
+                       ac97(sysclko)
+mpp21         21       gpio, sdio0(wp), sdio1(wp), spi1(cs), lcd-spi(cs0),
+                       uart1(cts), ssp(sfrm)
+mpp22         22       gpio, sdio0(buspwr), sdio1(buspwr), spi1(mosi),
+                       lcd-spi(mosi), uart1(cts), ssp(txd)
+mpp23         23       gpio, sdio0(ledctrl), sdio1(ledctrl), spi1(sck),
+                       lcd-spi(sck), ssp(sclk)
+mpp_camera    24-39    gpio, camera
+mpp_sdio0     40-45    gpio, sdio0
+mpp_sdio1     46-51    gpio, sdio1
+mpp_audio1    52-57    gpio, i2s1/spdifo, i2s1, spdifo, twsi, ssp/spdifo, ssp,
+                       ssp/twsi
+mpp_spi0      58-61    gpio, spi0
+mpp_uart1     62-63    gpio, uart1
+mpp_nand      64-71    gpo, nand
+audio0        -        i2s, ac97
+twsi          -        none, opt1, opt2, opt3
+
+Notes:
+* group "mpp_audio1" allows the following functions and gpio pins:
+  - gpio          : gpio on pins 52-57
+  - i2s1/spdifo   : audio1 i2s on pins 52-55 and spdifo on 57, no gpios
+  - i2s1          : audio1 i2s on pins 52-55, gpio on pins 56,57
+  - spdifo        : spdifo on pin 57, gpio on pins 52-55
+  - twsi          : twsi on pins 56,57, gpio on pins 52-55
+  - ssp/spdifo    : ssp on pins 52-55, spdifo on pin 57, no gpios
+  - ssp           : ssp on pins 52-55, gpio on pins 56,57
+  - ssp/twsi      : ssp on pins 52-55, twsi on pins 56,57, no gpios
+* group "audio0" internally muxes i2s0 or ac97 controller to the dedicated
+  audio0 pins.
+* group "twsi" internally muxes twsi controller to the dedicated or option pins.
diff --git a/Documentation/devicetree/bindings/pinctrl/marvell,kirkwood-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/marvell,kirkwood-pinctrl.txt
new file mode 100644
index 0000000..361bccb
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/marvell,kirkwood-pinctrl.txt
@@ -0,0 +1,279 @@
+* Marvell Kirkwood SoC pinctrl driver for mpp
+
+Please refer to marvell,mvebu-pinctrl.txt in this directory for common binding
+part and usage.
+
+Required properties:
+- compatible: "marvell,88f6180-pinctrl",
+              "marvell,88f6190-pinctrl", "marvell,88f6192-pinctrl",
+              "marvell,88f6281-pinctrl", "marvell,88f6282-pinctrl"
+
+This driver supports all kirkwood variants, i.e. 88f6180, 88f619x, and 88f628x.
+
+Available mpp pins/groups and functions:
+Note: brackets (x) are not part of the mpp name for marvell,function and given
+only for more detailed description in this document.
+
+* Marvell Kirkwood 88f6180
+
+name          pins     functions
+================================================================================
+mpp0          0        gpio, nand(io2), spi(cs)
+mpp1          1        gpo, nand(io3), spi(mosi)
+mpp2          2        gpo, nand(io4), spi(sck)
+mpp3          3        gpo, nand(io5), spi(miso)
+mpp4          4        gpio, nand(io6), uart0(rxd), ptp(clk)
+mpp5          5        gpo, nand(io7), uart0(txd), ptp(trig)
+mpp6          6        sysrst(out), spi(mosi), ptp(trig)
+mpp7          7        gpo, pex(rsto), spi(cs), ptp(trig)
+mpp8          8        gpio, twsi0(sda), uart0(rts), uart1(rts), ptp(clk),
+                       mii(col)
+mpp9          9        gpio, twsi(sck), uart0(cts), uart1(cts), ptp(evreq),
+                       mii(crs)
+mpp10         10       gpo, spi(sck), uart0(txd), ptp(trig)
+mpp11         11       gpio, spi(miso), uart0(rxd), ptp(clk), ptp-1(evreq),
+                       ptp-2(trig)
+mpp12         12       gpo, sdio(clk)
+mpp13         13       gpio, sdio(cmd), uart1(txd)
+mpp14         14       gpio, sdio(d0), uart1(rxd), mii(col)
+mpp15         15       gpio, sdio(d1), uart0(rts), uart1(txd)
+mpp16         16       gpio, sdio(d2), uart0(cts), uart1(rxd), mii(crs)
+mpp17         17       gpio, sdio(d3)
+mpp18         18       gpo, nand(io0)
+mpp19         19       gpo, nand(io1)
+mpp20         20       gpio, mii(rxerr)
+mpp21         21       gpio, audio(spdifi)
+mpp22         22       gpio, audio(spdifo)
+mpp23         23       gpio, audio(rmclk)
+mpp24         24       gpio, audio(bclk)
+mpp25         25       gpio, audio(sdo)
+mpp26         26       gpio, audio(lrclk)
+mpp27         27       gpio, audio(mclk)
+mpp28         28       gpio, audio(sdi)
+mpp29         29       gpio, audio(extclk)
+
+* Marvell Kirkwood 88f6190
+
+name          pins     functions
+================================================================================
+mpp0          0        gpio, nand(io2), spi(cs)
+mpp1          1        gpo, nand(io3), spi(mosi)
+mpp2          2        gpo, nand(io4), spi(sck)
+mpp3          3        gpo, nand(io5), spi(miso)
+mpp4          4        gpio, nand(io6), uart0(rxd), ptp(clk)
+mpp5          5        gpo, nand(io7), uart0(txd), ptp(trig), sata0(act)
+mpp6          6        sysrst(out), spi(mosi), ptp(trig)
+mpp7          7        gpo, pex(rsto), spi(cs), ptp(trig)
+mpp8          8        gpio, twsi0(sda), uart0(rts), uart1(rts), ptp(clk),
+                       mii(col), mii-1(rxerr)
+mpp9          9        gpio, twsi(sck), uart0(cts), uart1(cts), ptp(evreq),
+                       mii(crs), sata0(prsnt)
+mpp10         10       gpo, spi(sck), uart0(txd), ptp(trig)
+mpp11         11       gpio, spi(miso), uart0(rxd), ptp(clk), ptp-1(evreq),
+                       ptp-2(trig), sata0(act)
+mpp12         12       gpo, sdio(clk)
+mpp13         13       gpio, sdio(cmd), uart1(txd)
+mpp14         14       gpio, sdio(d0), uart1(rxd), mii(col)
+mpp15         15       gpio, sdio(d1), uart0(rts), uart1(txd), sata0(act)
+mpp16         16       gpio, sdio(d2), uart0(cts), uart1(rxd), mii(crs)
+mpp17         17       gpio, sdio(d3), sata0(prsnt)
+mpp18         18       gpo, nand(io0)
+mpp19         19       gpo, nand(io1)
+mpp20         20       gpio, ge1(txd0)
+mpp21         21       gpio, ge1(txd1), sata0(act)
+mpp22         22       gpio, ge1(txd2)
+mpp23         23       gpio, ge1(txd3), sata0(prsnt)
+mpp24         24       gpio, ge1(rxd0)
+mpp25         25       gpio, ge1(rxd1)
+mpp26         26       gpio, ge1(rxd2)
+mpp27         27       gpio, ge1(rxd3)
+mpp28         28       gpio, ge1(col)
+mpp29         29       gpio, ge1(txclk)
+mpp30         30       gpio, ge1(rxclk)
+mpp31         31       gpio, ge1(rxclk)
+mpp32         32       gpio, ge1(txclko)
+mpp33         33       gpo, ge1(txclk)
+mpp34         34       gpio, ge1(txen)
+mpp35         35       gpio, ge1(rxerr), sata0(act), mii(rxerr)
+
+* Marvell Kirkwood 88f6192
+
+name          pins     functions
+================================================================================
+mpp0          0        gpio, nand(io2), spi(cs)
+mpp1          1        gpo, nand(io3), spi(mosi)
+mpp2          2        gpo, nand(io4), spi(sck)
+mpp3          3        gpo, nand(io5), spi(miso)
+mpp4          4        gpio, nand(io6), uart0(rxd), ptp(clk), sata1(act)
+mpp5          5        gpo, nand(io7), uart0(txd), ptp(trig), sata0(act)
+mpp6          6        sysrst(out), spi(mosi), ptp(trig)
+mpp7          7        gpo, pex(rsto), spi(cs), ptp(trig)
+mpp8          8        gpio, twsi0(sda), uart0(rts), uart1(rts), ptp(clk),
+                       mii(col), mii-1(rxerr), sata1(prsnt)
+mpp9          9        gpio, twsi(sck), uart0(cts), uart1(cts), ptp(evreq),
+                       mii(crs), sata0(prsnt)
+mpp10         10       gpo, spi(sck), uart0(txd), ptp(trig), sata1(act)
+mpp11         11       gpio, spi(miso), uart0(rxd), ptp(clk), ptp-1(evreq),
+                       ptp-2(trig), sata0(act)
+mpp12         12       gpo, sdio(clk)
+mpp13         13       gpio, sdio(cmd), uart1(txd)
+mpp14         14       gpio, sdio(d0), uart1(rxd), mii(col), sata1(prsnt)
+mpp15         15       gpio, sdio(d1), uart0(rts), uart1(txd), sata0(act)
+mpp16         16       gpio, sdio(d2), uart0(cts), uart1(rxd), mii(crs),
+                       sata1(act)
+mpp17         17       gpio, sdio(d3), sata0(prsnt)
+mpp18         18       gpo, nand(io0)
+mpp19         19       gpo, nand(io1)
+mpp20         20       gpio, ge1(txd0), ts(mp0), tdm(tx0ql), audio(spdifi),
+                       sata1(act)
+mpp21         21       gpio, ge1(txd1), sata0(act), ts(mp1), tdm(rx0ql),
+                       audio(spdifo)
+mpp22         22       gpio, ge1(txd2), ts(mp2), tdm(tx2ql), audio(rmclk),
+                       sata1(prsnt)
+mpp23         23       gpio, ge1(txd3), sata0(prsnt), ts(mp3), tdm(rx2ql),
+                       audio(bclk)
+mpp24         24       gpio, ge1(rxd0), ts(mp4), tdm(spi-cs0), audio(sdo)
+mpp25         25       gpio, ge1(rxd1), ts(mp5), tdm(spi-sck), audio(lrclk)
+mpp26         26       gpio, ge1(rxd2), ts(mp6), tdm(spi-miso), audio(mclk)
+mpp27         27       gpio, ge1(rxd3), ts(mp7), tdm(spi-mosi), audio(sdi)
+mpp28         28       gpio, ge1(col), ts(mp8), tdm(int), audio(extclk)
+mpp29         29       gpio, ge1(txclk), ts(mp9), tdm(rst)
+mpp30         30       gpio, ge1(rxclk), ts(mp10), tdm(pclk)
+mpp31         31       gpio, ge1(rxclk), ts(mp11), tdm(fs)
+mpp32         32       gpio, ge1(txclko), ts(mp12), tdm(drx)
+mpp33         33       gpo, ge1(txclk), tdm(drx)
+mpp34         34       gpio, ge1(txen), tdm(spi-cs1)
+mpp35         35       gpio, ge1(rxerr), sata0(act), mii(rxerr), tdm(tx0ql)
+
+* Marvell Kirkwood 88f6281
+
+name          pins     functions
+================================================================================
+mpp0          0        gpio, nand(io2), spi(cs)
+mpp1          1        gpo, nand(io3), spi(mosi)
+mpp2          2        gpo, nand(io4), spi(sck)
+mpp3          3        gpo, nand(io5), spi(miso)
+mpp4          4        gpio, nand(io6), uart0(rxd), ptp(clk), sata1(act)
+mpp5          5        gpo, nand(io7), uart0(txd), ptp(trig), sata0(act)
+mpp6          6        sysrst(out), spi(mosi), ptp(trig)
+mpp7          7        gpo, pex(rsto), spi(cs), ptp(trig)
+mpp8          8        gpio, twsi0(sda), uart0(rts), uart1(rts), ptp(clk),
+                       mii(col), mii-1(rxerr), sata1(prsnt)
+mpp9          9        gpio, twsi(sck), uart0(cts), uart1(cts), ptp(evreq),
+                       mii(crs), sata0(prsnt)
+mpp10         10       gpo, spi(sck), uart0(txd), ptp(trig), sata1(act)
+mpp11         11       gpio, spi(miso), uart0(rxd), ptp(clk), ptp-1(evreq),
+                       ptp-2(trig), sata0(act)
+mpp12         12       gpio, sdio(clk)
+mpp13         13       gpio, sdio(cmd), uart1(txd)
+mpp14         14       gpio, sdio(d0), uart1(rxd), mii(col), sata1(prsnt)
+mpp15         15       gpio, sdio(d1), uart0(rts), uart1(txd), sata0(act)
+mpp16         16       gpio, sdio(d2), uart0(cts), uart1(rxd), mii(crs),
+                       sata1(act)
+mpp17         17       gpio, sdio(d3), sata0(prsnt)
+mpp18         18       gpo, nand(io0)
+mpp19         19       gpo, nand(io1)
+mpp20         20       gpio, ge1(txd0), ts(mp0), tdm(tx0ql), audio(spdifi),
+                       sata1(act)
+mpp21         21       gpio, ge1(txd1), sata0(act), ts(mp1), tdm(rx0ql),
+                       audio(spdifo)
+mpp22         22       gpio, ge1(txd2), ts(mp2), tdm(tx2ql), audio(rmclk),
+                       sata1(prsnt)
+mpp23         23       gpio, ge1(txd3), sata0(prsnt), ts(mp3), tdm(rx2ql),
+                       audio(bclk)
+mpp24         24       gpio, ge1(rxd0), ts(mp4), tdm(spi-cs0), audio(sdo)
+mpp25         25       gpio, ge1(rxd1), ts(mp5), tdm(spi-sck), audio(lrclk)
+mpp26         26       gpio, ge1(rxd2), ts(mp6), tdm(spi-miso), audio(mclk)
+mpp27         27       gpio, ge1(rxd3), ts(mp7), tdm(spi-mosi), audio(sdi)
+mpp28         28       gpio, ge1(col), ts(mp8), tdm(int), audio(extclk)
+mpp29         29       gpio, ge1(txclk), ts(mp9), tdm(rst)
+mpp30         30       gpio, ge1(rxclk), ts(mp10), tdm(pclk)
+mpp31         31       gpio, ge1(rxclk), ts(mp11), tdm(fs)
+mpp32         32       gpio, ge1(txclko), ts(mp12), tdm(drx)
+mpp33         33       gpo, ge1(txclk), tdm(drx)
+mpp34         34       gpio, ge1(txen), tdm(spi-cs1), sata1(act)
+mpp35         35       gpio, ge1(rxerr), sata0(act), mii(rxerr), tdm(tx0ql)
+mpp36         36       gpio, ts(mp0), tdm(spi-cs1), audio(spdifi)
+mpp37         37       gpio, ts(mp1), tdm(tx2ql), audio(spdifo)
+mpp38         38       gpio, ts(mp2), tdm(rx2ql), audio(rmclk)
+mpp39         39       gpio, ts(mp3), tdm(spi-cs0), audio(bclk)
+mpp40         40       gpio, ts(mp4), tdm(spi-sck), audio(sdo)
+mpp41         41       gpio, ts(mp5), tdm(spi-miso), audio(lrclk)
+mpp42         42       gpio, ts(mp6), tdm(spi-mosi), audio(mclk)
+mpp43         43       gpio, ts(mp7), tdm(int), audio(sdi)
+mpp44         44       gpio, ts(mp8), tdm(rst), audio(extclk)
+mpp45         45       gpio, ts(mp9), tdm(pclk)
+mpp46         46       gpio, ts(mp10), tdm(fs)
+mpp47         47       gpio, ts(mp11), tdm(drx)
+mpp48         48       gpio, ts(mp12), tdm(dtx)
+mpp49         49       gpio, ts(mp9), tdm(rx0ql), ptp(clk)
+
+* Marvell Kirkwood 88f6282
+
+name          pins     functions
+================================================================================
+mpp0          0        gpio, nand(io2), spi(cs)
+mpp1          1        gpo, nand(io3), spi(mosi)
+mpp2          2        gpo, nand(io4), spi(sck)
+mpp3          3        gpo, nand(io5), spi(miso)
+mpp4          4        gpio, nand(io6), uart0(rxd), sata1(act), lcd(hsync)
+mpp5          5        gpo, nand(io7), uart0(txd), sata0(act), lcd(vsync)
+mpp6          6        sysrst(out), spi(mosi)
+mpp7          7        gpo, spi(cs), lcd(pwm)
+mpp8          8        gpio, twsi0(sda), uart0(rts), uart1(rts), mii(col),
+                       mii-1(rxerr), sata1(prsnt)
+mpp9          9        gpio, twsi(sck), uart0(cts), uart1(cts), mii(crs),
+                       sata0(prsnt)
+mpp10         10       gpo, spi(sck), uart0(txd), sata1(act)
+mpp11         11       gpio, spi(miso), uart0(rxd), sata0(act)
+mpp12         12       gpo, sdio(clk), audio(spdifo), spi(mosi), twsi(sda)
+mpp13         13       gpio, sdio(cmd), uart1(txd), audio(rmclk), lcd(pwm)
+mpp14         14       gpio, sdio(d0), uart1(rxd), mii(col), sata1(prsnt),
+                       audio(spdifi), audio-1(sdi)
+mpp15         15       gpio, sdio(d1), uart0(rts), uart1(txd), sata0(act),
+                       spi(cs)
+mpp16         16       gpio, sdio(d2), uart0(cts), uart1(rxd), mii(crs),
+                       sata1(act), lcd(extclk)
+mpp17         17       gpio, sdio(d3), sata0(prsnt), sata1(act), twsi1(sck)
+mpp18         18       gpo, nand(io0), pex(clkreq)
+mpp19         19       gpo, nand(io1)
+mpp20         20       gpio, ge1(txd0), ts(mp0), tdm(tx0ql), audio(spdifi),
+                       sata1(act), lcd(d0)
+mpp21         21       gpio, ge1(txd1), sata0(act), ts(mp1), tdm(rx0ql),
+                       audio(spdifo), lcd(d1)
+mpp22         22       gpio, ge1(txd2), ts(mp2), tdm(tx2ql), audio(rmclk),
+                       sata1(prsnt), lcd(d2)
+mpp23         23       gpio, ge1(txd3), sata0(prsnt), ts(mp3), tdm(rx2ql),
+                       audio(bclk), lcd(d3)
+mpp24         24       gpio, ge1(rxd0), ts(mp4), tdm(spi-cs0), audio(sdo),
+                       lcd(d4)
+mpp25         25       gpio, ge1(rxd1), ts(mp5), tdm(spi-sck), audio(lrclk),
+                       lcd(d5)
+mpp26         26       gpio, ge1(rxd2), ts(mp6), tdm(spi-miso), audio(mclk),
+                       lcd(d6)
+mpp27         27       gpio, ge1(rxd3), ts(mp7), tdm(spi-mosi), audio(sdi),
+                       lcd(d7)
+mpp28         28       gpio, ge1(col), ts(mp8), tdm(int), audio(extclk),
+                       lcd(d8)
+mpp29         29       gpio, ge1(txclk), ts(mp9), tdm(rst), lcd(d9)
+mpp30         30       gpio, ge1(rxclk), ts(mp10), tdm(pclk), lcd(d10)
+mpp31         31       gpio, ge1(rxclk), ts(mp11), tdm(fs), lcd(d11)
+mpp32         32       gpio, ge1(txclko), ts(mp12), tdm(drx), lcd(d12)
+mpp33         33       gpo, ge1(txclk), tdm(drx), lcd(d13)
+mpp34         34       gpio, ge1(txen), tdm(spi-cs1), sata1(act), lcd(d14)
+mpp35         35       gpio, ge1(rxerr), sata0(act), mii(rxerr), tdm(tx0ql),
+                       lcd(d15)
+mpp36         36       gpio, ts(mp0), tdm(spi-cs1), audio(spdifi), twsi1(sda)
+mpp37         37       gpio, ts(mp1), tdm(tx2ql), audio(spdifo), twsi1(sck)
+mpp38         38       gpio, ts(mp2), tdm(rx2ql), audio(rmclk), lcd(d18)
+mpp39         39       gpio, ts(mp3), tdm(spi-cs0), audio(bclk), lcd(d19)
+mpp40         40       gpio, ts(mp4), tdm(spi-sck), audio(sdo), lcd(d20)
+mpp41         41       gpio, ts(mp5), tdm(spi-miso), audio(lrclk), lcd(d21)
+mpp42         42       gpio, ts(mp6), tdm(spi-mosi), audio(mclk), lcd(d22)
+mpp43         43       gpio, ts(mp7), tdm(int), audio(sdi), lcd(d23)
+mpp44         44       gpio, ts(mp8), tdm(rst), audio(extclk), lcd(clk)
+mpp45         45       gpio, ts(mp9), tdm(pclk), lcd(e)
+mpp46         46       gpio, ts(mp10), tdm(fs), lcd(hsync)
+mpp47         47       gpio, ts(mp11), tdm(drx), lcd(vsync)
+mpp48         48       gpio, ts(mp12), tdm(dtx), lcd(d16)
+mpp49         49       gpo, tdm(rx0ql), pex(clkreq), lcd(d17)
diff --git a/Documentation/devicetree/bindings/pinctrl/marvell,mvebu-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/marvell,mvebu-pinctrl.txt
new file mode 100644
index 0000000..0a26c3a
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/marvell,mvebu-pinctrl.txt
@@ -0,0 +1,46 @@
+* Marvell SoC pinctrl core driver for mpp
+
+The pinctrl driver enables Marvell SoCs to configure the multi-purpose pins
+(mpp) to a specific function. For each SoC family there is a SoC specific
+driver using this core driver.
+
+Please refer to pinctrl-bindings.txt in this directory for details of the
+common pinctrl bindings used by client devices, including the meaning of the
+phrase "pin configuration node".
+
+A Marvell SoC pin configuration node is a node of a group of pins which can
+be used for a specific device or function. Each node requires one or more
+mpp pins or group of pins and a mpp function common to all pins.
+
+Required properties for pinctrl driver:
+- compatible: "marvell,<soc>-pinctrl"
+  Please refer to each marvell,<soc>-pinctrl.txt binding doc for supported SoCs.
+
+Required properties for pin configuration node:
+- marvell,pins: string array of mpp pins or group of pins to be muxed.
+- marvell,function: string representing a function to mux to for all
+    marvell,pins given in this pin configuration node. The function has to be
+    common for all marvell,pins. Please refer to marvell,<soc>-pinctrl.txt for
+    valid pin/pin group names and available function names for each SoC.
+
+Examples:
+
+uart1: serial@12100 {
+	compatible = "ns16550a";
+	reg = <0x12100 0x100>;
+	reg-shift = <2>;
+	interrupts = <7>;
+
+	pinctrl-0 = <&pmx_uart1_sw>;
+	pinctrl-names = "default";
+};
+
+pinctrl: pinctrl@d0200 {
+	compatible = "marvell,dove-pinctrl";
+	reg = <0xd0200 0x20>;
+
+	pmx_uart1_sw: pmx-uart1-sw {
+		marvell,pins = "mpp_uart1";
+		marvell,function = "uart1";
+	};
+};
diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt
index 5187f0d..2c81e45 100644
--- a/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt
+++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt
@@ -14,10 +14,12 @@ Optional properties:
 - pinctrl-single,function-off : function off mode for disabled state if
   available and same for all registers; if not specified, disabling of
   pin functions is ignored
+- pinctrl-single,bit-per-mux : boolean to indicate that one register controls
+  more than one pin
 
-This driver assumes that there is only one register for each pin,
-and uses the common pinctrl bindings as specified in the pinctrl-bindings.txt
-document in this directory.
+This driver assumes that there is only one register for each pin (unless the
+pinctrl-single,bit-per-mux is set), and uses the common pinctrl bindings as
+specified in the pinctrl-bindings.txt document in this directory.
 
 The pin configuration nodes for pinctrl-single are specified as pinctrl
 register offset and value pairs using pinctrl-single,pins. Only the bits
@@ -31,6 +33,15 @@ device pinctrl register, and 0x118 contains the desired value of the
 pinctrl register. See the device example and static board pins example
 below for more information.
 
+In case when one register changes more than one pin's mux the
+pinctrl-single,bits need to be used which takes three parameters:
+
+	pinctrl-single,bits = <0xdc 0x18, 0xff>;
+
+Where 0xdc is the offset from the pinctrl register base address for the
+device pinctrl register, 0x18 is the desired value, and 0xff is the sub mask to
+be used when applying this change to the register.
+
 Example:
 
 /* SoC common file */
@@ -55,6 +66,15 @@ pmx_wkup: pinmux@4a31e040 {
 	pinctrl-single,function-mask = <0xffff>;
 };
 
+control_devconf0: pinmux@48002274 {
+	compatible = "pinctrl-single";
+	reg = <0x48002274 4>;	/* Single register */
+	#address-cells = <1>;
+	#size-cells = <0>;
+	pinctrl-single,bit-per-mux;
+	pinctrl-single,register-width = <32>;
+	pinctrl-single,function-mask = <0x5F>;
+};
 
 /* board specific .dts file */
 
@@ -87,6 +107,21 @@ pmx_wkup: pinmux@4a31e040 {
 	};
 };
 
+&control_devconf0 {
+	mcbsp1_pins: pinmux_mcbsp1_pins {
+		pinctrl-single,bits = <
+			0x00 0x18 0x18 /* FSR/CLKR signal from FSX/CLKX pin */
+		>;
+	};
+
+	mcbsp2_clks_pins: pinmux_mcbsp2_clks_pins {
+		pinctrl-single,bits = <
+			0x00 0x40 0x40 /* McBSP2 CLKS from McBSP_CLKS pin */
+		>;
+	};
+
+};
+
 &uart2 {
        pinctrl-names = "default";
        pinctrl-0 = <&uart2_pins>;
diff --git a/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt
new file mode 100644
index 0000000..03dee50
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt
@@ -0,0 +1,196 @@
+Samsung GPIO and Pin Mux/Config controller
+
+Samsung's ARM based SoC's integrates a GPIO and Pin mux/config hardware
+controller. It controls the input/output settings on the available pads/pins
+and also provides ability to multiplex and configure the output of various
+on-chip controllers onto these pads.
+
+Required Properties:
+- compatible: should be one of the following.
+  - "samsung,pinctrl-exynos4210": for Exynos4210 compatible pin-controller.
+  - "samsung,pinctrl-exynos5250": for Exynos5250 compatible pin-controller.
+
+- reg: Base address of the pin controller hardware module and length of
+  the address space it occupies.
+
+- interrupts: interrupt specifier for the controller. The format and value of
+  the interrupt specifier depends on the interrupt parent for the controller.
+
+- Pin mux/config groups as child nodes: The pin mux (selecting pin function
+  mode) and pin config (pull up/down, driver strength) settings are represented
+  as child nodes of the pin-controller node. There should be atleast one
+  child node and there is no limit on the count of these child nodes.
+
+  The child node should contain a list of pin(s) on which a particular pin
+  function selection or pin configuration (or both) have to applied. This
+  list of pins is specified using the property name "samsung,pins". There
+  should be atleast one pin specfied for this property and there is no upper
+  limit on the count of pins that can be specified. The pins are specified
+  using pin names which are derived from the hardware manual of the SoC. As
+  an example, the pins in GPA0 bank of the pin controller can be represented
+  as "gpa0-0", "gpa0-1", "gpa0-2" and so on. The names should be in lower case.
+  The format of the pin names should be (as per the hardware manual)
+  "[pin bank name]-[pin number within the bank]".
+
+  The pin function selection that should be applied on the pins listed in the
+  child node is specified using the "samsung,pin-function" property. The value
+  of this property that should be applied to each of the pins listed in the
+  "samsung,pins" property should be picked from the hardware manual of the SoC
+  for the specified pin group. This property is optional in the child node if
+  no specific function selection is desired for the pins listed in the child
+  node. The value of this property is used as-is to program the pin-controller
+  function selector register of the pin-bank.
+
+  The child node can also optionally specify one or more of the pin
+  configuration that should be applied on all the pins listed in the
+  "samsung,pins" property of the child node. The following pin configuration
+  properties are supported.
+
+  - samsung,pin-pud: Pull up/down configuration.
+  - samsung,pin-drv: Drive strength configuration.
+  - samsung,pin-pud-pdn: Pull up/down configuration in power down mode.
+  - samsung,pin-drv-pdn: Drive strength configuration in power down mode.
+
+  The values specified by these config properties should be derived from the
+  hardware manual and these values are programmed as-is into the pin
+  pull up/down and driver strength register of the pin-controller.
+
+  Note: A child should include atleast a pin function selection property or
+  pin configuration property (one or more) or both.
+
+  The client nodes that require a particular pin function selection and/or
+  pin configuration should use the bindings listed in the "pinctrl-bindings.txt"
+  file.
+
+External GPIO and Wakeup Interrupts:
+
+The controller supports two types of external interrupts over gpio. The first
+is the external gpio interrupt and second is the external wakeup interrupts.
+The difference between the two is that the external wakeup interrupts can be
+used as system wakeup events.
+
+A. External GPIO Interrupts: For supporting external gpio interrupts, the
+   following properties should be specified in the pin-controller device node.
+
+- interrupt-controller: identifies the controller node as interrupt-parent.
+- #interrupt-cells: the value of this property should be 2.
+  - First Cell: represents the external gpio interrupt number local to the
+    external gpio interrupt space of the controller.
+  - Second Cell: flags to identify the type of the interrupt
+    - 1 = rising edge triggered
+    - 2 = falling edge triggered
+    - 3 = rising and falling edge triggered
+    - 4 = high level triggered
+    - 8 = low level triggered
+
+B. External Wakeup Interrupts: For supporting external wakeup interrupts, a
+   child node representing the external wakeup interrupt controller should be
+   included in the pin-controller device node. This child node should include
+   the following properties.
+
+   - compatible: identifies the type of the external wakeup interrupt controller
+     The possible values are:
+     - samsung,exynos4210-wakeup-eint: represents wakeup interrupt controller
+       found on Samsung Exynos4210 SoC.
+   - interrupt-parent: phandle of the interrupt parent to which the external
+     wakeup interrupts are forwarded to.
+   - interrupt-controller: identifies the node as interrupt-parent.
+   - #interrupt-cells: the value of this property should be 2
+     - First Cell: represents the external wakeup interrupt number local to
+       the external wakeup interrupt space of the controller.
+     - Second Cell: flags to identify the type of the interrupt
+       - 1 = rising edge triggered
+       - 2 = falling edge triggered
+       - 3 = rising and falling edge triggered
+       - 4 = high level triggered
+       - 8 = low level triggered
+
+Aliases:
+
+All the pin controller nodes should be represented in the aliases node using
+the following format 'pinctrl{n}' where n is a unique number for the alias.
+
+Example 1: A pin-controller node with pin groups.
+
+	pinctrl_0: pinctrl@11400000 {
+		compatible = "samsung,pinctrl-exynos4210";
+		reg = <0x11400000 0x1000>;
+		interrupts = <0 47 0>;
+
+		uart0_data: uart0-data {
+			samsung,pins = "gpa0-0", "gpa0-1";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		uart0_fctl: uart0-fctl {
+			samsung,pins = "gpa0-2", "gpa0-3";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		uart1_data: uart1-data {
+			samsung,pins = "gpa0-4", "gpa0-5";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		uart1_fctl: uart1-fctl {
+			samsung,pins = "gpa0-6", "gpa0-7";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		i2c2_bus: i2c2-bus {
+			samsung,pins = "gpa0-6", "gpa0-7";
+			samsung,pin-function = <3>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <0>;
+		};
+	};
+
+Example 2: A pin-controller node with external wakeup interrupt controller node.
+
+	pinctrl_1: pinctrl@11000000 {
+		compatible = "samsung,pinctrl-exynos4210";
+		reg = <0x11000000 0x1000>;
+		interrupts = <0 46 0>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+
+		wakup_eint: wakeup-interrupt-controller {
+			compatible = "samsung,exynos4210-wakeup-eint";
+			interrupt-parent = <&gic>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			interrupts = <0 16 0>, <0 17 0>, <0 18 0>, <0 19 0>,
+					<0 20 0>, <0 21 0>, <0 22 0>, <0 23 0>,
+					<0 24 0>, <0 25 0>, <0 26 0>, <0 27 0>,
+					<0 28 0>, <0 29 0>, <0 30 0>, <0 31 0>,
+					<0 32 0>;
+		};
+	};
+
+Example 3: A uart client node that supports 'default' and 'flow-control' states.
+
+	uart@13800000 {
+		compatible = "samsung,exynos4210-uart";
+		reg = <0x13800000 0x100>;
+		interrupts = <0 52 0>;
+		pinctrl-names = "default", "flow-control;
+		pinctrl-0 = <&uart0_data>;
+		pinctrl-1 = <&uart0_data &uart0_fctl>;
+	};
+
+Example 4: Set up the default pin state for uart controller.
+
+	static int s3c24xx_serial_probe(struct platform_device *pdev) {
+		struct pinctrl *pinctrl;
+		...
+		...
+		pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+	}
diff --git a/Documentation/devicetree/bindings/power/opp.txt b/Documentation/devicetree/bindings/power/opp.txt
new file mode 100644
index 0000000..74499e5
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/opp.txt
@@ -0,0 +1,25 @@
+* Generic OPP Interface
+
+SoCs have a standard set of tuples consisting of frequency and
+voltage pairs that the device will support per voltage domain. These
+are called Operating Performance Points or OPPs.
+
+Properties:
+- operating-points: An array of 2-tuples items, and each item consists
+  of frequency and voltage like <freq-kHz vol-uV>.
+	freq: clock frequency in kHz
+	vol: voltage in microvolt
+
+Examples:
+
+cpu@0 {
+	compatible = "arm,cortex-a9";
+	reg = <0>;
+	next-level-cache = <&L2>;
+	operating-points = <
+		/* kHz    uV */
+		792000  1100000
+		396000  950000
+		198000  850000
+	>;
+};
diff --git a/Documentation/devicetree/bindings/powerpc/fsl/ifc.txt b/Documentation/devicetree/bindings/powerpc/fsl/ifc.txt
index 939a26d..d5e3704 100644
--- a/Documentation/devicetree/bindings/powerpc/fsl/ifc.txt
+++ b/Documentation/devicetree/bindings/powerpc/fsl/ifc.txt
@@ -12,9 +12,12 @@ Properties:
 - #size-cells : Either one or two, depending on how large each chipselect
                 can be.
 - reg : Offset and length of the register set for the device
-- interrupts : IFC has two interrupts. The first one is the "common"
-               interrupt(CM_EVTER_STAT), and second is the NAND interrupt
-               (NAND_EVTER_STAT).
+- interrupts: IFC may have one or two interrupts.  If two interrupt
+              specifiers are present, the first is the "common"
+              interrupt (CM_EVTER_STAT), and the second is the NAND
+              interrupt (NAND_EVTER_STAT).  If there is only one,
+              that interrupt reports both types of event.
+
 
 - ranges : Each range corresponds to a single chipselect, and covers
            the entire access window as configured.
diff --git a/Documentation/devicetree/bindings/pwm/imx-pwm.txt b/Documentation/devicetree/bindings/pwm/imx-pwm.txt
new file mode 100644
index 0000000..9b9b185
--- /dev/null
+++ b/Documentation/devicetree/bindings/pwm/imx-pwm.txt
@@ -0,0 +1,17 @@
+Freescale i.MX PWM controller
+
+Required properties:
+- compatible: should be "fsl,<soc>-pwm"
+- reg: physical base address and length of the controller's registers
+- #pwm-cells: should be 2.  The first cell specifies the per-chip index
+  of the PWM to use and the second cell is the duty cycle in nanoseconds.
+- interrupts: The interrupt for the pwm controller
+
+Example:
+
+pwm1: pwm@53fb4000 {
+	#pwm-cells = <2>;
+	compatible = "fsl,imx53-pwm", "fsl,imx27-pwm";
+	reg = <0x53fb4000 0x4000>;
+	interrupts = <61>;
+};
diff --git a/Documentation/devicetree/bindings/pwm/mxs-pwm.txt b/Documentation/devicetree/bindings/pwm/mxs-pwm.txt
index b16f4a5..11963e4 100644
--- a/Documentation/devicetree/bindings/pwm/mxs-pwm.txt
+++ b/Documentation/devicetree/bindings/pwm/mxs-pwm.txt
@@ -11,7 +11,7 @@ Example:
 
 pwm: pwm@80064000 {
 	compatible = "fsl,imx28-pwm", "fsl,imx23-pwm";
-	reg = <0x80064000 2000>;
+	reg = <0x80064000 0x2000>;
 	#pwm-cells = <2>;
 	fsl,pwm-number = <8>;
 };
diff --git a/Documentation/devicetree/bindings/regulator/max8907.txt b/Documentation/devicetree/bindings/regulator/max8907.txt
new file mode 100644
index 0000000..371eccd
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/max8907.txt
@@ -0,0 +1,69 @@
+MAX8907 regulator
+
+Required properties:
+- compatible: "maxim,max8907"
+- reg: I2C slave address
+- interrupts: The interrupt output of the controller
+- mbatt-supply: The input supply for MBATT, BBAT, SDBY, VRTC.
+- in-v1-supply: The input supply for SD1.
+- in-v2-supply: The input supply for SD2.
+- in-v3-supply: The input supply for SD3.
+- in1-supply: The input supply for LDO1.
+...
+- in20-supply: The input supply for LDO20.
+- regulators: A node that houses a sub-node for each regulator within the
+  device. Each sub-node is identified using the node's name (or the deprecated
+  regulator-compatible property if present), with valid values listed below.
+  The content of each sub-node is defined by the standard binding for
+  regulators; see regulator.txt.
+
+Optional properties:
+- maxim,system-power-controller: Boolean property indicating that the PMIC
+  controls the overall system power.
+
+The valid names for regulators are:
+
+  sd1, sd2, sd3, ldo1, ldo2, ldo3, ldo4, ldo5, ldo6, ldo7, ldo8, ldo9, ldo10,
+  ldo11, ldo12, ldo13, ldo14, ldo15, ldo16, ldo17, ldo18, ldo19, ldo20, out5v,
+  out33v, bbat, sdby, vrtc.
+
+Example:
+
+		max8907@3c {
+			compatible = "maxim,max8907";
+			reg = <0x3c>;
+			interrupts = <0 86 0x4>;
+
+			maxim,system-power-controller;
+
+			mbatt-supply = <&some_reg>;
+			in-v1-supply = <&mbatt_reg>;
+			...
+			in1-supply = <&mbatt_reg>;
+			...
+
+			regulators {
+				mbatt_reg: mbatt {
+					regulator-name = "vbat_pmu";
+					regulator-min-microvolt = <5000000>;
+					regulator-max-microvolt = <5000000>;
+					regulator-always-on;
+				};
+
+				sd1 {
+					regulator-name = "nvvdd_sv1,vdd_cpu_pmu";
+					regulator-min-microvolt = <1000000>;
+					regulator-max-microvolt = <1000000>;
+					regulator-always-on;
+				};
+
+				sd2 {
+					regulator-name = "nvvdd_sv2,vdd_core";
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+					regulator-always-on;
+				};
+...
+			};
+		};
+	};
diff --git a/Documentation/devicetree/bindings/regulator/regulator.txt b/Documentation/devicetree/bindings/regulator/regulator.txt
index 66ece3f..ecfc6cc 100644
--- a/Documentation/devicetree/bindings/regulator/regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/regulator.txt
@@ -11,10 +11,13 @@ Optional properties:
 - regulator-boot-on: bootloader/firmware enabled regulator
 - <name>-supply: phandle to the parent supply/regulator node
 - regulator-ramp-delay: ramp delay for regulator(in uV/uS)
+
+Deprecated properties:
 - regulator-compatible: If a regulator chip contains multiple
   regulators, and if the chip's binding contains a child node that
   describes each regulator, then this property indicates which regulator
-  this child node is intended to configure.
+  this child node is intended to configure. If this property is missing,
+  the node's name will be used instead.
 
 Example:
 
diff --git a/Documentation/devicetree/bindings/regulator/tps65217.txt b/Documentation/devicetree/bindings/regulator/tps65217.txt
index 0487e96..d316fb8 100644
--- a/Documentation/devicetree/bindings/regulator/tps65217.txt
+++ b/Documentation/devicetree/bindings/regulator/tps65217.txt
@@ -22,66 +22,49 @@ Example:
 		compatible = "ti,tps65217";
 
 		regulators {
-			#address-cells = <1>;
-			#size-cells = <0>;
-
-			dcdc1_reg: regulator@0 {
-				reg = <0>;
-				regulator-compatible = "dcdc1";
+			dcdc1_reg: dcdc1 {
 				regulator-min-microvolt = <900000>;
 				regulator-max-microvolt = <1800000>;
 				regulator-boot-on;
 				regulator-always-on;
 			};
 
-			dcdc2_reg: regulator@1 {
-				reg = <1>;
-				regulator-compatible = "dcdc2";
+			dcdc2_reg: dcdc2 {
 				regulator-min-microvolt = <900000>;
 				regulator-max-microvolt = <3300000>;
 				regulator-boot-on;
 				regulator-always-on;
 			};
 
-			dcdc3_reg: regulator@2 {
-				reg = <2>;
-				regulator-compatible = "dcdc3";
+			dcdc3_reg: dcc3 {
 				regulator-min-microvolt = <900000>;
 				regulator-max-microvolt = <1500000>;
 				regulator-boot-on;
 				regulator-always-on;
 			};
 
-			ldo1_reg: regulator@3 {
-				reg = <3>;
-				regulator-compatible = "ldo1";
+			ldo1_reg: ldo1 {
 				regulator-min-microvolt = <1000000>;
 				regulator-max-microvolt = <3300000>;
 				regulator-boot-on;
 				regulator-always-on;
 			};
 
-			ldo2_reg: regulator@4 {
-				reg = <4>;
-				regulator-compatible = "ldo2";
+			ldo2_reg: ldo2 {
 				regulator-min-microvolt = <900000>;
 				regulator-max-microvolt = <3300000>;
 				regulator-boot-on;
 				regulator-always-on;
 			};
 
-			ldo3_reg: regulator@5 {
-				reg = <5>;
-				regulator-compatible = "ldo3";
+			ldo3_reg: ldo3 {
 				regulator-min-microvolt = <1800000>;
 				regulator-max-microvolt = <3300000>;
 				regulator-boot-on;
 				regulator-always-on;
 			};
 
-			ldo4_reg: regulator@6 {
-				reg = <6>;
-				regulator-compatible = "ldo4";
+			ldo4_reg: ldo4 {
 				regulator-min-microvolt = <1800000>;
 				regulator-max-microvolt = <3300000>;
 				regulator-boot-on;
diff --git a/Documentation/devicetree/bindings/regulator/tps6586x.txt b/Documentation/devicetree/bindings/regulator/tps6586x.txt
index da80c2a..8b40cac 100644
--- a/Documentation/devicetree/bindings/regulator/tps6586x.txt
+++ b/Documentation/devicetree/bindings/regulator/tps6586x.txt
@@ -6,9 +6,13 @@ Required properties:
 - interrupts: the interrupt outputs of the controller
 - #gpio-cells: number of cells to describe a GPIO
 - gpio-controller: mark the device as a GPIO controller
-- regulators: list of regulators provided by this controller, must have
-  property "regulator-compatible" to match their hardware counterparts:
-  sm[0-2], ldo[0-9] and ldo_rtc
+- regulators: A node that houses a sub-node for each regulator within the
+  device. Each sub-node is identified using the node's name (or the deprecated
+  regulator-compatible property if present), with valid values listed below.
+  The content of each sub-node is defined by the standard binding for
+  regulators; see regulator.txt.
+  sys, sm[0-2], ldo[0-9] and ldo_rtc
+- sys-supply: The input supply for SYS.
 - vin-sm0-supply: The input supply for the SM0.
 - vin-sm1-supply: The input supply for the SM1.
 - vin-sm2-supply: The input supply for the SM2.
@@ -18,8 +22,15 @@ Required properties:
 - vinldo678-supply: The input supply for the LDO6, LDO7 and LDO8
 - vinldo9-supply: The input supply for the LDO9
 
+Optional properties:
+- ti,system-power-controller: Telling whether or not this pmic is controlling
+  the system power.
+
 Each regulator is defined using the standard binding for regulators.
 
+Note: LDO5 and LDO_RTC is supplied by SYS regulator internally and driver
+      take care of making proper parent child relationship.
+
 Example:
 
 	pmu: tps6586x@34 {
@@ -30,6 +41,9 @@ Example:
 		#gpio-cells = <2>;
 		gpio-controller;
 
+		ti,system-power-controller;
+
+		sys-supply = <&some_reg>;
 		vin-sm0-supply = <&some_reg>;
 		vin-sm1-supply = <&some_reg>;
 		vin-sm2-supply = <&some_reg>;
@@ -40,103 +54,80 @@ Example:
 		vinldo9-supply = <...>;
 
 		regulators {
-			#address-cells = <1>;
-			#size-cells = <0>;
+			sys_reg: sys {
+				regulator-name = "vdd_sys";
+				regulator-boot-on;
+				regulator-always-on;
+			};
 
-			sm0_reg: regulator@0 {
-				reg = <0>;
-				regulator-compatible = "sm0";
+			sm0_reg: sm0 {
 				regulator-min-microvolt = < 725000>;
 				regulator-max-microvolt = <1500000>;
 				regulator-boot-on;
 				regulator-always-on;
 			};
 
-			sm1_reg: regulator@1 {
-				reg = <1>;
-				regulator-compatible = "sm1";
+			sm1_reg: sm1 {
 				regulator-min-microvolt = < 725000>;
 				regulator-max-microvolt = <1500000>;
 				regulator-boot-on;
 				regulator-always-on;
 			};
 
-			sm2_reg: regulator@2 {
-				reg = <2>;
-				regulator-compatible = "sm2";
+			sm2_reg: sm2 {
 				regulator-min-microvolt = <3000000>;
 				regulator-max-microvolt = <4550000>;
 				regulator-boot-on;
 				regulator-always-on;
 			};
 
-			ldo0_reg: regulator@3 {
-				reg = <3>;
-				regulator-compatible = "ldo0";
+			ldo0_reg: ldo0 {
 				regulator-name = "PCIE CLK";
 				regulator-min-microvolt = <3300000>;
 				regulator-max-microvolt = <3300000>;
 			};
 
-			ldo1_reg: regulator@4 {
-				reg = <4>;
-				regulator-compatible = "ldo1";
+			ldo1_reg: ldo1 {
 				regulator-min-microvolt = < 725000>;
 				regulator-max-microvolt = <1500000>;
 			};
 
-			ldo2_reg: regulator@5 {
-				reg = <5>;
-				regulator-compatible = "ldo2";
+			ldo2_reg: ldo2 {
 				regulator-min-microvolt = < 725000>;
 				regulator-max-microvolt = <1500000>;
 			};
 
-			ldo3_reg: regulator@6 {
-				reg = <6>;
-				regulator-compatible = "ldo3";
+			ldo3_reg: ldo3 {
 				regulator-min-microvolt = <1250000>;
 				regulator-max-microvolt = <3300000>;
 			};
 
-			ldo4_reg: regulator@7 {
-				reg = <7>;
-				regulator-compatible = "ldo4";
+			ldo4_reg: ldo4 {
 				regulator-min-microvolt = <1700000>;
 				regulator-max-microvolt = <2475000>;
 			};
 
-			ldo5_reg: regulator@8 {
-				reg = <8>;
-				regulator-compatible = "ldo5";
+			ldo5_reg: ldo5 {
 				regulator-min-microvolt = <1250000>;
 				regulator-max-microvolt = <3300000>;
 			};
 
-			ldo6_reg: regulator@9 {
-				reg = <9>;
-				regulator-compatible = "ldo6";
+			ldo6_reg: ldo6 {
 				regulator-min-microvolt = <1250000>;
 				regulator-max-microvolt = <3300000>;
 			};
 
-			ldo7_reg: regulator@10 {
-				reg = <10>;
-				regulator-compatible = "ldo7";
+			ldo7_reg: ldo7 {
 				regulator-min-microvolt = <1250000>;
 				regulator-max-microvolt = <3300000>;
 			};
 
-			ldo8_reg: regulator@11 {
-				reg = <11>;
-				regulator-compatible = "ldo8";
+			ldo8_reg: ldo8 {
 				regulator-min-microvolt = <1250000>;
 				regulator-max-microvolt = <3300000>;
 			};
 
-			ldo9_reg: regulator@12 {
-				reg = <12>;
-				regulator-compatible = "ldo9";
+			ldo9_reg: ldo9 {
 				regulator-min-microvolt = <1250000>;
 				regulator-max-microvolt = <3300000>;
 			};
diff --git a/Documentation/devicetree/bindings/rtc/pxa-rtc.txt b/Documentation/devicetree/bindings/rtc/pxa-rtc.txt
new file mode 100644
index 0000000..8c6672a
--- /dev/null
+++ b/Documentation/devicetree/bindings/rtc/pxa-rtc.txt
@@ -0,0 +1,14 @@
+* PXA RTC
+
+PXA specific RTC driver.
+
+Required properties:
+- compatible : Should be "marvell,pxa-rtc"
+
+Examples:
+
+rtc@40900000 {
+	compatible = "marvell,pxa-rtc";
+	reg = <0x40900000 0x3c>;
+	interrupts = <30 31>;
+};
diff --git a/Documentation/devicetree/bindings/rtc/snvs-rtc.txt b/Documentation/devicetree/bindings/rtc/snvs-rtc.txt
new file mode 100644
index 0000000..fb61ed7
--- /dev/null
+++ b/Documentation/devicetree/bindings/rtc/snvs-rtc.txt
@@ -0,0 +1 @@
+See Documentation/devicetree/bindings/crypto/fsl-sec4.txt for details.
diff --git a/Documentation/devicetree/bindings/rtc/via,vt8500-rtc.txt b/Documentation/devicetree/bindings/rtc/via,vt8500-rtc.txt
new file mode 100644
index 0000000..3c0484c
--- /dev/null
+++ b/Documentation/devicetree/bindings/rtc/via,vt8500-rtc.txt
@@ -0,0 +1,15 @@
+VIA/Wondermedia VT8500 Realtime Clock Controller
+-----------------------------------------------------
+
+Required properties:
+- compatible : "via,vt8500-rtc"
+- reg : Should contain 1 register ranges(address and length)
+- interrupts : alarm interrupt
+
+Example:
+
+	rtc@d8100000 {
+		compatible = "via,vt8500-rtc";
+		reg = <0xd8100000 0x10000>;
+		interrupts = <48>;
+	};
diff --git a/Documentation/devicetree/bindings/serial/fsl-imx-uart.txt b/Documentation/devicetree/bindings/serial/fsl-imx-uart.txt
new file mode 100644
index 0000000..c58573b
--- /dev/null
+++ b/Documentation/devicetree/bindings/serial/fsl-imx-uart.txt
@@ -0,0 +1,35 @@
+* Freescale i.MX UART controller
+
+Required properties:
+- compatible : should be "fsl,imx21-uart"
+- reg : Address and length of the register set for the device
+- interrupts : Should contain UART interrupt number
+
+Optional properties:
+- fsl,uart-has-rtscts: indicate that RTS/CTS signals are used
+
+Note: Each uart controller should have an alias correctly numbered
+in "aliases" node.
+
+Example:
+
+- From imx51.dtsi:
+aliases {
+	serial0 = &uart1;
+	serial1 = &uart2;
+	serial2 = &uart3;
+};
+
+uart1: serial@73fbc000 {
+	compatible = "fsl,imx51-uart", "fsl,imx21-uart";
+	reg = <0x73fbc000 0x4000>;
+	interrupts = <31>;
+	status = "disabled";
+}
+
+- From imx51-babbage.dts:
+uart1: serial@73fbc000 {
+	fsl,uart-has-rtscts;
+	status = "okay";
+};
+
diff --git a/Documentation/devicetree/bindings/sound/cs4270.txt b/Documentation/devicetree/bindings/sound/cs4270.txt
new file mode 100644
index 0000000..6b222f9
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/cs4270.txt
@@ -0,0 +1,21 @@
+CS4270 audio CODEC
+
+The driver for this device currently only supports I2C.
+
+Required properties:
+
+  - compatible : "cirrus,cs4270"
+
+  - reg : the I2C address of the device for I2C
+
+Optional properties:
+
+  - reset-gpio : a GPIO spec for the reset pin. If specified, it will be
+		 deasserted before communication to the codec starts.
+
+Example:
+
+codec: cs4270@48 {
+	compatible = "cirrus,cs4270";
+	reg = <0x48>;
+};
diff --git a/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt b/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt
new file mode 100644
index 0000000..374e145
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt
@@ -0,0 +1,45 @@
+Texas Instruments McASP controller
+
+Required properties:
+- compatible :
+	"ti,dm646x-mcasp-audio"	: for DM646x platforms
+	"ti,da830-mcasp-audio"	: for both DA830 & DA850 platforms
+	"ti,omap2-mcasp-audio"	: for OMAP2 platforms (TI81xx, AM33xx)
+
+- reg : Should contain McASP registers offset and length
+- interrupts : Interrupt number for McASP
+- op-mode : I2S/DIT ops mode.
+- tdm-slots : Slots for TDM operation.
+- num-serializer : Serializers used by McASP.
+- serial-dir : A list of serializer pin mode. The list number should be equal
+		to "num-serializer" parameter. Each entry is a number indication
+		serializer pin direction. (0 - INACTIVE, 1 - TX, 2 - RX)
+
+
+Optional properties:
+
+- ti,hwmods : Must be "mcasp<n>", n is controller instance starting 0
+- tx-num-evt : FIFO levels.
+- rx-num-evt : FIFO levels.
+- sram-size-playback : size of sram to be allocated during playback
+- sram-size-capture  : size of sram to be allocated during capture
+
+Example:
+
+mcasp0: mcasp0@1d00000 {
+	compatible = "ti,da830-mcasp-audio";
+	#address-cells = <1>;
+	#size-cells = <0>;
+	reg = <0x100000 0x3000>;
+	interrupts = <82 83>;
+	op-mode = <0>;		/* MCASP_IIS_MODE */
+	tdm-slots = <2>;
+	num-serializer = <16>;
+	serial-dir = <
+			0 0 0 0	/* 0: INACTIVE, 1: TX, 2: RX */
+			0 0 0 0
+			0 0 0 1
+			2 0 0 0 >;
+	tx-num-evt = <1>;
+	rx-num-evt = <1>;
+};
diff --git a/Documentation/devicetree/bindings/sound/omap-abe-twl6040.txt b/Documentation/devicetree/bindings/sound/omap-abe-twl6040.txt
new file mode 100644
index 0000000..65dec87
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/omap-abe-twl6040.txt
@@ -0,0 +1,91 @@
+* Texas Instruments OMAP4+ and twl6040 based audio setups
+
+Required properties:
+- compatible: "ti,abe-twl6040"
+- ti,model: Name of the sound card ( for example "SDP4430")
+- ti,mclk-freq: MCLK frequency for HPPLL operation
+- ti,mcpdm: phandle for the McPDM node
+- ti,twl6040: phandle for the twl6040 core node
+- ti,audio-routing: List of connections between audio components.
+  Each entry is a pair of strings, the first being the connection's sink,
+  the second being the connection's source.
+
+Optional properties:
+- ti,dmic: phandle for the OMAP dmic node if the machine have it connected
+- ti,jack_detection: Need to be set to <1> if the board capable to detect jack
+  insertion, removal.
+
+Available audio endpoints for the audio-routing table:
+
+Board connectors:
+ * Headset Stereophone
+ * Earphone Spk
+ * Ext Spk
+ * Line Out
+ * Vibrator
+ * Headset Mic
+ * Main Handset Mic
+ * Sub Handset Mic
+ * Line In
+ * Digital Mic
+
+twl6040 pins:
+ * HSOL
+ * HSOR
+ * EP
+ * HFL
+ * HFR
+ * AUXL
+ * AUXR
+ * VIBRAL
+ * VIBRAR
+ * HSMIC
+ * MAINMIC
+ * SUBMIC
+ * AFML
+ * AFMR
+
+ * Headset Mic Bias
+ * Main Mic Bias
+ * Digital Mic1 Bias
+ * Digital Mic2 Bias
+
+Digital mic pins:
+ * DMic
+
+Example:
+
+sound {
+	compatible = "ti,abe-twl6040";
+	ti,model = "SDP4430";
+
+	ti,jack-detection = <1>;
+	ti,mclk-freq = <38400000>;
+
+	ti,mcpdm = <&mcpdm>;
+	ti,dmic = <&dmic>;
+
+	ti,twl6040 = <&twl6040>;
+
+	/* Audio routing */
+	ti,audio-routing =
+		"Headset Stereophone", "HSOL",
+		"Headset Stereophone", "HSOR",
+		"Earphone Spk", "EP",
+		"Ext Spk", "HFL",
+		"Ext Spk", "HFR",
+		"Line Out", "AUXL",
+		"Line Out", "AUXR",
+		"Vibrator", "VIBRAL",
+		"Vibrator", "VIBRAR",
+		"HSMIC", "Headset Mic",
+		"Headset Mic", "Headset Mic Bias",
+		"MAINMIC", "Main Handset Mic",
+		"Main Handset Mic", "Main Mic Bias",
+		"SUBMIC", "Sub Handset Mic",
+		"Sub Handset Mic", "Main Mic Bias",
+		"AFML", "Line In",
+		"AFMR", "Line In",
+		"DMic", "Digital Mic",
+		"Digital Mic", "Digital Mic1 Bias";
+};
diff --git a/Documentation/devicetree/bindings/sound/omap-mcbsp.txt b/Documentation/devicetree/bindings/sound/omap-mcbsp.txt
new file mode 100644
index 0000000..17cce44
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/omap-mcbsp.txt
@@ -0,0 +1,37 @@
+* Texas Instruments OMAP2+ McBSP module
+
+Required properties:
+- compatible: "ti,omap2420-mcbsp" for McBSP on OMAP2420
+	      "ti,omap2430-mcbsp" for McBSP on OMAP2430
+	      "ti,omap3-mcbsp" for McBSP on OMAP3
+	      "ti,omap4-mcbsp" for McBSP on OMAP4 and newer SoC
+- reg: Register location and size, for OMAP4+ as an array:
+       <MPU access base address, size>,
+       <L3 interconnect address, size>;
+- reg-names: Array of strings associated with the address space
+- interrupts: Interrupt numbers for the McBSP port, as an array in case the
+	      McBSP IP have more interrupt lines:
+	<OCP compliant irq>,
+	<TX irq>,
+	<RX irq>;
+- interrupt-names: Array of strings associated with the interrupt numbers
+- interrupt-parent: The parent interrupt controller
+- ti,buffer-size: Size of the FIFO on the port (OMAP2430 and newer SoC)
+- ti,hwmods: Name of the hwmod associated to the McBSP port
+
+Example:
+
+mcbsp2: mcbsp@49022000 {
+	compatible = "ti,omap3-mcbsp";
+	reg = <0x49022000 0xff>,
+	      <0x49028000 0xff>;
+	reg-names = "mpu", "sidetone";
+	interrupts = <0 17 0x4>, /* OCP compliant interrupt */
+		     <0 62 0x4>, /* TX interrupt */
+		     <0 63 0x4>, /* RX interrupt */
+		     <0 4 0x4>;  /* Sidetone */
+	interrupt-names = "common", "tx", "rx", "sidetone";
+	interrupt-parent = <&intc>;
+	ti,buffer-size = <1280>;
+	ti,hwmods = "mcbsp2";
+};
diff --git a/Documentation/devicetree/bindings/sound/omap-twl4030.txt b/Documentation/devicetree/bindings/sound/omap-twl4030.txt
new file mode 100644
index 0000000..6fae51c
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/omap-twl4030.txt
@@ -0,0 +1,17 @@
+* Texas Instruments SoC with twl4030 based audio setups
+
+Required properties:
+- compatible: "ti,omap-twl4030"
+- ti,model: Name of the sound card (for example "omap3beagle")
+- ti,mcbsp: phandle for the McBSP node
+- ti,codec: phandle for the twl4030 audio node
+
+Example:
+
+sound {
+	compatible = "ti,omap-twl4030";
+	ti,model = "omap3beagle";
+
+	ti,mcbsp = <&mcbsp2>;
+	ti,codec = <&twl_audio>;
+};
diff --git a/Documentation/devicetree/bindings/sound/tlv320aic3x.txt b/Documentation/devicetree/bindings/sound/tlv320aic3x.txt
new file mode 100644
index 0000000..e7b98f4
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/tlv320aic3x.txt
@@ -0,0 +1,20 @@
+Texas Instruments - tlv320aic3x Codec module
+
+The tlv320aic3x serial control bus communicates through I2C protocols
+
+Required properties:
+- compatible - "string" -  "ti,tlv320aic3x"
+- reg - <int> -  I2C slave address
+
+
+Optional properties:
+
+- gpio-reset - gpio pin number used for codec reset
+- ai3x-gpio-func - <array of 2 int> - AIC3X_GPIO1 & AIC3X_GPIO2 Functionality
+
+Example:
+
+tlv320aic3x: tlv320aic3x@1b {
+	compatible = "ti,tlv320aic3x";
+	reg = <0x1b>;
+};
diff --git a/Documentation/devicetree/bindings/sound/ux500-mop500.txt b/Documentation/devicetree/bindings/sound/ux500-mop500.txt
new file mode 100644
index 0000000..48e071c
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/ux500-mop500.txt
@@ -0,0 +1,39 @@
+* MOP500 Audio Machine Driver
+
+This node is responsible for linking together all ux500 Audio Driver components.
+
+Required properties:
+ - compatible              : "stericsson,snd-soc-mop500"
+
+Non-standard properties:
+ - stericsson,cpu-dai      : Phandle to the CPU-side DAI
+ - stericsson,audio-codec  : Phandle to the Audio CODEC
+ - stericsson,card-name    : Over-ride default card name
+
+Example:
+
+	sound {
+		compatible = "stericsson,snd-soc-mop500";
+
+		stericsson,cpu-dai = <&msp1 &msp3>;
+		stericsson,audio-codec = <&codec>;
+	};
+
+	msp1: msp@80124000 {
+		compatible = "stericsson,ux500-msp-i2s";
+		reg = <0x80124000 0x1000>;
+		interrupts = <0 62 0x4>;
+		v-ape-supply = <&db8500_vape_reg>;
+	};
+
+	msp3: msp@80125000 {
+		compatible = "stericsson,ux500-msp-i2s";
+		reg = <0x80125000 0x1000>;
+		interrupts = <0 62 0x4>;
+		v-ape-supply = <&db8500_vape_reg>;
+	};
+
+	codec: ab8500-codec {
+		compatible = "stericsson,ab8500-codec";
+		stericsson,earpeice-cmv = <950>; /* Units in mV. */
+	};
diff --git a/Documentation/devicetree/bindings/sound/ux500-msp.txt b/Documentation/devicetree/bindings/sound/ux500-msp.txt
new file mode 100644
index 0000000..99acd9c
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/ux500-msp.txt
@@ -0,0 +1,43 @@
+* ux500 MSP (CPU-side Digital Audio Interface)
+
+Required properties:
+ - compatible       :"stericsson,ux500-msp-i2s"
+ - reg              : Physical base address and length of the device's registers.
+
+Optional properties:
+ - interrupts       : The interrupt output from the device.
+ - interrupt-parent : The parent interrupt controller.
+ - <name>-supply    : Phandle to the regulator <name> supply
+
+Example:
+
+	sound {
+		compatible = "stericsson,snd-soc-mop500";
+
+		stericsson,platform-pcm-dma = <&pcm>;
+		stericsson,cpu-dai = <&msp1 &msp3>;
+		stericsson,audio-codec = <&codec>;
+	};
+
+	pcm: ux500-pcm {
+		compatible = "stericsson,ux500-pcm";
+	};
+
+	msp1: msp@80124000 {
+		compatible = "stericsson,ux500-msp-i2s";
+		reg = <0x80124000 0x1000>;
+		interrupts = <0 62 0x4>;
+		v-ape-supply = <&db8500_vape_reg>;
+	};
+
+	msp3: msp@80125000 {
+		compatible = "stericsson,ux500-msp-i2s";
+		reg = <0x80125000 0x1000>;
+		interrupts = <0 62 0x4>;
+		v-ape-supply = <&db8500_vape_reg>;
+	};
+
+	codec: ab8500-codec {
+		compatible = "stericsson,ab8500-codec";
+		stericsson,earpeice-cmv = <950>; /* Units in mV. */
+	};
diff --git a/Documentation/devicetree/bindings/spi/mxs-spi.txt b/Documentation/devicetree/bindings/spi/mxs-spi.txt
new file mode 100644
index 0000000..e2e1395
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/mxs-spi.txt
@@ -0,0 +1,22 @@
+* Freescale MX233/MX28 SSP/SPI
+
+Required properties:
+- compatible: Should be "fsl,<soc>-spi", where soc is "imx23" or "imx28"
+- reg: Offset and length of the register set for the device
+- interrupts: Should contain SSP interrupts (error irq first, dma irq second)
+- fsl,ssp-dma-channel: APBX DMA channel for the SSP
+
+Optional properties:
+- clock-frequency : Input clock frequency to the SPI block in Hz.
+		    Default is 160000000 Hz.
+
+Example:
+
+ssp0: ssp@80010000 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	compatible = "fsl,imx28-spi";
+	reg = <0x80010000 0x2000>;
+	interrupts = <96 82>;
+	fsl,ssp-dma-channel = <0>;
+};
diff --git a/Documentation/devicetree/bindings/spi/spi-bus.txt b/Documentation/devicetree/bindings/spi/spi-bus.txt
index e782add..d2c33d0 100644
--- a/Documentation/devicetree/bindings/spi/spi-bus.txt
+++ b/Documentation/devicetree/bindings/spi/spi-bus.txt
@@ -21,6 +21,9 @@ assumption that board specific platform code will be used to manage
 chip selects.  Individual drivers can define additional properties to
 support describing the chip select layout.
 
+Optional property:
+- num-cs : total number of chipselects
+
 SPI slave nodes must be children of the SPI master node and can
 contain the following properties.
 - reg             - (required) chip select address of device.
diff --git a/Documentation/devicetree/bindings/spi/spi-gpio.txt b/Documentation/devicetree/bindings/spi/spi-gpio.txt
new file mode 100644
index 0000000..8a824be
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/spi-gpio.txt
@@ -0,0 +1,29 @@
+SPI-GPIO devicetree bindings
+
+Required properties:
+
+ - compatible: should be set to "spi-gpio"
+ - #address-cells: should be set to <0x1>
+ - ranges
+ - gpio-sck: GPIO spec for the SCK line to use
+ - gpio-miso: GPIO spec for the MISO line to use
+ - gpio-mosi: GPIO spec for the MOSI line to use
+ - cs-gpios: GPIOs to use for chipselect lines
+ - num-chipselects: number of chipselect lines
+
+Example:
+
+	spi {
+		compatible = "spi-gpio";
+		#address-cells = <0x1>;
+		ranges;
+
+		gpio-sck = <&gpio 95 0>;
+		gpio-miso = <&gpio 98 0>;
+		gpio-mosi = <&gpio 97 0>;
+		cs-gpios = <&gpio 125 0>;
+		num-chipselects = <1>;
+
+		/* clients */
+	};
+
diff --git a/Documentation/devicetree/bindings/spi/spi-sc18is602.txt b/Documentation/devicetree/bindings/spi/spi-sc18is602.txt
new file mode 100644
index 0000000..02f9033
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/spi-sc18is602.txt
@@ -0,0 +1,23 @@
+NXP SC18IS602/SCIS603
+
+Required properties:
+	- compatible : Should be one of
+		"nxp,sc18is602"
+		"nxp,sc18is602b"
+		"nxp,sc18is603"
+	- reg: I2C bus address
+
+Optional properties:
+	- clock-frequency : external oscillator clock frequency. If not
+	  specified, the SC18IS602 default frequency (7372000) will be used.
+
+The clock-frequency property is relevant and needed only if the chip has an
+external oscillator (SC18IS603).
+
+Example:
+
+	sc18is603@28 {
+		compatible = "nxp,sc18is603";
+		reg = <0x28>;
+		clock-frequency = <14744000>;
+	}
diff --git a/Documentation/devicetree/bindings/spi/spi_pl022.txt b/Documentation/devicetree/bindings/spi/spi_pl022.txt
index 306ec3f..f158fd3 100644
--- a/Documentation/devicetree/bindings/spi/spi_pl022.txt
+++ b/Documentation/devicetree/bindings/spi/spi_pl022.txt
@@ -6,7 +6,29 @@ Required properties:
 - interrupts : Should contain SPI controller interrupt
 
 Optional properties:
+- num-cs : total number of chipselects
 - cs-gpios : should specify GPIOs used for chipselects.
   The gpios will be referred to as reg = <index> in the SPI child nodes.
   If unspecified, a single SPI device without a chip select can be used.
+- pl022,autosuspend-delay : delay in ms following transfer completion before
+			    the runtime power management system suspends the
+			    device. A setting of 0 indicates no delay and the
+                            device will be suspended immediately
+- pl022,rt : indicates the controller should run the message pump with realtime
+             priority to minimise the transfer latency on the bus (boolean)
+
+
+SPI slave nodes must be children of the SPI master node and can
+contain the following properties.
+
+- pl022,interface : interface type:
+	0: SPI
+	1: Texas Instruments Synchronous Serial Frame Format
+	2: Microwire (Half Duplex)
+- pl022,com-mode : polling, interrupt or dma
+- pl022,rx-level-trig : Rx FIFO watermark level
+- pl022,tx-level-trig : Tx FIFO watermark level
+- pl022,ctrl-len : Microwire interface: Control length
+- pl022,wait-state : Microwire interface: Wait state
+- pl022,duplex : Microwire interface: Full/Half duplex
 
diff --git a/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt b/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt
new file mode 100644
index 0000000..801d58c
--- /dev/null
+++ b/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt
@@ -0,0 +1,15 @@
+* Freescale i.MX28 LRADC device driver
+
+Required properties:
+- compatible: Should be "fsl,imx28-lradc"
+- reg: Address and length of the register set for the device
+- interrupts: Should contain the LRADC interrupts
+
+Examples:
+
+	lradc@80050000 {
+		compatible = "fsl,imx28-lradc";
+		reg = <0x80050000 0x2000>;
+		interrupts = <10 14 15 16 17 18 19
+				20 21 22 23 24 25>;
+	};
diff --git a/Documentation/devicetree/bindings/staging/imx-drm/fsl-imx-drm.txt b/Documentation/devicetree/bindings/staging/imx-drm/fsl-imx-drm.txt
new file mode 100644
index 0000000..07654f0
--- /dev/null
+++ b/Documentation/devicetree/bindings/staging/imx-drm/fsl-imx-drm.txt
@@ -0,0 +1,41 @@
+Freescale i.MX IPUv3
+====================
+
+Required properties:
+- compatible: Should be "fsl,<chip>-ipu"
+- reg: should be register base and length as documented in the
+  datasheet
+- interrupts: Should contain sync interrupt and error interrupt,
+  in this order.
+- #crtc-cells: 1, See below
+
+example:
+
+ipu: ipu@18000000 {
+	#crtc-cells = <1>;
+	compatible = "fsl,imx53-ipu";
+	reg = <0x18000000 0x080000000>;
+	interrupts = <11 10>;
+};
+
+Parallel display support
+========================
+
+Required properties:
+- compatible: Should be "fsl,imx-parallel-display"
+- crtc: the crtc this display is connected to, see below
+Optional properties:
+- interface_pix_fmt: How this display is connected to the
+  crtc. Currently supported types: "rgb24", "rgb565"
+- edid: verbatim EDID data block describing attached display.
+- ddc: phandle describing the i2c bus handling the display data
+  channel
+
+example:
+
+display@di0 {
+	compatible = "fsl,imx-parallel-display";
+	edid = [edid-data];
+	crtc = <&ipu 0>;
+	interface-pix-fmt = "rgb24";
+};
diff --git a/Documentation/devicetree/bindings/timer/brcm,bcm2835-system-timer.txt b/Documentation/devicetree/bindings/timer/brcm,bcm2835-system-timer.txt
new file mode 100644
index 0000000..2de21c2
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/brcm,bcm2835-system-timer.txt
@@ -0,0 +1,22 @@
+BCM2835 System Timer
+
+The System Timer peripheral provides four 32-bit timer channels and a
+single 64-bit free running counter. Each channel has an output compare
+register, which is compared against the 32 least significant bits of the
+free running counter values, and generates an interrupt.
+
+Required properties:
+
+- compatible : should be "brcm,bcm2835-system-timer.txt"
+- reg : Specifies base physical address and size of the registers.
+- interrupts : A list of 4 interrupt sinks; one per timer channel.
+- clock-frequency : The frequency of the clock that drives the counter, in Hz.
+
+Example:
+
+timer {
+	compatible = "brcm,bcm2835-system-timer";
+	reg = <0x7e003000 0x1000>;
+	interrupts = <1 0>, <1 1>, <1 2>, <1 3>;
+	clock-frequency = <1000000>;
+};
diff --git a/Documentation/devicetree/bindings/tty/serial/nxp-lpc32xx-hsuart.txt b/Documentation/devicetree/bindings/tty/serial/nxp-lpc32xx-hsuart.txt
new file mode 100644
index 0000000..0d439df
--- /dev/null
+++ b/Documentation/devicetree/bindings/tty/serial/nxp-lpc32xx-hsuart.txt
@@ -0,0 +1,14 @@
+* NXP LPC32xx SoC High Speed UART
+
+Required properties:
+- compatible: Should be "nxp,lpc3220-hsuart"
+- reg: Should contain registers location and length
+- interrupts: Should contain interrupt
+
+Example:
+
+	uart1: serial@40014000 {
+		compatible = "nxp,lpc3220-hsuart";
+		reg = <0x40014000 0x1000>;
+		interrupts = <26 0>;
+	};
diff --git a/Documentation/devicetree/bindings/tty/serial/of-serial.txt b/Documentation/devicetree/bindings/tty/serial/of-serial.txt
index 0847fde..ba385f2 100644
--- a/Documentation/devicetree/bindings/tty/serial/of-serial.txt
+++ b/Documentation/devicetree/bindings/tty/serial/of-serial.txt
@@ -25,6 +25,8 @@ Optional properties:
   accesses to the UART (e.g. TI davinci).
 - used-by-rtas : set to indicate that the port is in use by the OpenFirmware
   RTAS and should not be registered.
+- no-loopback-test: set to indicate that the port does not implements loopback
+  test mode
 
 Example:
 
diff --git a/Documentation/devicetree/bindings/tty/serial/via,vt8500-uart.txt b/Documentation/devicetree/bindings/tty/serial/via,vt8500-uart.txt
new file mode 100644
index 0000000..5feef1e
--- /dev/null
+++ b/Documentation/devicetree/bindings/tty/serial/via,vt8500-uart.txt
@@ -0,0 +1,17 @@
+VIA/Wondermedia VT8500 UART Controller
+-----------------------------------------------------
+
+Required properties:
+- compatible : "via,vt8500-uart"
+- reg : Should contain 1 register ranges(address and length)
+- interrupts : UART interrupt
+- clocks : phandle to the uart source clock (usually a 24Mhz fixed clock)
+
+Example:
+
+	uart@d8210000 {
+		compatible = "via,vt8500-uart";
+		reg = <0xd8210000 0x1040>;
+		interrupts = <47>;
+		clocks = <&ref24>;
+	};
diff --git a/Documentation/devicetree/bindings/usb/am33xx-usb.txt b/Documentation/devicetree/bindings/usb/am33xx-usb.txt
new file mode 100644
index 0000000..ca8fa56
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/am33xx-usb.txt
@@ -0,0 +1,14 @@
+AM33XX MUSB GLUE
+ - compatible : Should be "ti,musb-am33xx"
+ - ti,hwmods : must be "usb_otg_hs"
+ - multipoint : Should be "1" indicating the musb controller supports
+   multipoint. This is a MUSB configuration-specific setting.
+ - num_eps : Specifies the number of endpoints. This is also a
+   MUSB configuration-specific setting. Should be set to "16"
+ - ram_bits : Specifies the ram address size. Should be set to "12"
+ - port0_mode : Should be "3" to represent OTG. "1" signifies HOST and "2"
+   represents PERIPHERAL.
+ - port1_mode : Should be "1" to represent HOST. "3" signifies OTG and "2"
+   represents PERIPHERAL.
+ - power : Should be "250". This signifies the controller can supply upto
+   500mA when operating in host mode.
diff --git a/Documentation/devicetree/bindings/usb/ci13xxx-imx.txt b/Documentation/devicetree/bindings/usb/ci13xxx-imx.txt
index 2c29041..5778b9c 100644
--- a/Documentation/devicetree/bindings/usb/ci13xxx-imx.txt
+++ b/Documentation/devicetree/bindings/usb/ci13xxx-imx.txt
@@ -7,7 +7,10 @@ Required properties:
 
 Optional properties:
 - fsl,usbphy: phandler of usb phy that connects to the only one port
+- fsl,usbmisc: phandler of non-core register device, with one argument
+  that indicate usb controller index
 - vbus-supply: regulator for vbus
+- disable-over-current: disable over current detect
 
 Examples:
 usb@02184000 { /* USB OTG */
@@ -15,4 +18,6 @@ usb@02184000 { /* USB OTG */
 	reg = <0x02184000 0x200>;
 	interrupts = <0 43 0x04>;
 	fsl,usbphy = <&usbphy1>;
+	fsl,usbmisc = <&usbmisc 0>;
+	disable-over-current;
 };
diff --git a/Documentation/devicetree/bindings/usb/omap-usb.txt b/Documentation/devicetree/bindings/usb/omap-usb.txt
new file mode 100644
index 0000000..29a043e
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/omap-usb.txt
@@ -0,0 +1,33 @@
+OMAP GLUE
+
+OMAP MUSB GLUE
+ - compatible : Should be "ti,omap4-musb" or "ti,omap3-musb"
+ - ti,hwmods : must be "usb_otg_hs"
+ - multipoint : Should be "1" indicating the musb controller supports
+   multipoint. This is a MUSB configuration-specific setting.
+ - num_eps : Specifies the number of endpoints. This is also a
+   MUSB configuration-specific setting. Should be set to "16"
+ - ram_bits : Specifies the ram address size. Should be set to "12"
+ - interface_type : This is a board specific setting to describe the type of
+   interface between the controller and the phy. It should be "0" or "1"
+   specifying ULPI and UTMI respectively.
+ - mode : Should be "3" to represent OTG. "1" signifies HOST and "2"
+   represents PERIPHERAL.
+ - power : Should be "50". This signifies the controller can supply upto
+   100mA when operating in host mode.
+
+SOC specific device node entry
+usb_otg_hs: usb_otg_hs@4a0ab000 {
+	compatible = "ti,omap4-musb";
+	ti,hwmods = "usb_otg_hs";
+	multipoint = <1>;
+	num_eps = <16>;
+	ram_bits = <12>;
+};
+
+Board specific device node entry
+&usb_otg_hs {
+	interface_type = <1>;
+	mode = <3>;
+	power = <50>;
+};
diff --git a/Documentation/devicetree/bindings/usb/platform-uhci.txt b/Documentation/devicetree/bindings/usb/platform-uhci.txt
new file mode 100644
index 0000000..a4fb071
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/platform-uhci.txt
@@ -0,0 +1,15 @@
+Generic Platform UHCI Controller
+-----------------------------------------------------
+
+Required properties:
+- compatible : "platform-uhci"
+- reg : Should contain 1 register ranges(address and length)
+- interrupts : UHCI controller interrupt
+
+Example:
+
+	uhci@d8007b00 {
+		compatible = "platform-uhci";
+		reg = <0xd8007b00 0x200>;
+		interrupts = <43>;
+	};
diff --git a/Documentation/devicetree/bindings/usb/pxa-usb.txt b/Documentation/devicetree/bindings/usb/pxa-usb.txt
new file mode 100644
index 0000000..79729a9
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/pxa-usb.txt
@@ -0,0 +1,31 @@
+PXA USB controllers
+
+OHCI
+
+Required properties:
+ - compatible: Should be "marvell,pxa-ohci" for USB controllers
+   used in host mode.
+
+Optional properties:
+ - "marvell,enable-port1", "marvell,enable-port2", "marvell,enable-port3"
+   If present, enables the appropriate USB port of the controller.
+ - "marvell,port-mode" selects the mode of the ports:
+	1 = PMM_NPS_MODE
+	2 = PMM_GLOBAL_MODE
+	3 = PMM_PERPORT_MODE
+ - "marvell,power-sense-low" - power sense pin is low-active.
+ - "marvell,power-control-low" - power control pin is low-active.
+ - "marvell,no-oc-protection" - disable over-current protection.
+ - "marvell,oc-mode-perport" - enable per-port over-current protection.
+ - "marvell,power_on_delay" Power On to Power Good time - in ms.
+
+Example:
+
+	usb0: ohci@4c000000 {
+		compatible = "marvell,pxa-ohci", "usb-ohci";
+		reg = <0x4c000000 0x100000>;
+		interrupts = <18>;
+		marvell,enable-port1;
+		marvell,port-mode = <2>; /* PMM_GLOBAL_MODE */
+	};
+
diff --git a/Documentation/devicetree/bindings/usb/twlxxxx-usb.txt b/Documentation/devicetree/bindings/usb/twlxxxx-usb.txt
new file mode 100644
index 0000000..36b9aed
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/twlxxxx-usb.txt
@@ -0,0 +1,40 @@
+USB COMPARATOR OF TWL CHIPS
+
+TWL6030 USB COMPARATOR
+ - compatible : Should be "ti,twl6030-usb"
+ - interrupts : Two interrupt numbers to the cpu should be specified. First
+   interrupt number is the otg interrupt number that raises ID interrupts when
+   the controller has to act as host and the second interrupt number is the
+   usb interrupt number that raises VBUS interrupts when the controller has to
+   act as device
+ - usb-supply : phandle to the regulator device tree node. It should be vusb
+   if it is twl6030 or ldousb if it is twl6025 subclass.
+
+twl6030-usb {
+	compatible = "ti,twl6030-usb";
+	interrupts = < 4 10 >;
+};
+
+Board specific device node entry
+&twl6030-usb {
+	usb-supply = <&vusb>;
+};
+
+TWL4030 USB PHY AND COMPARATOR
+ - compatible : Should be "ti,twl4030-usb"
+ - interrupts : The interrupt numbers to the cpu should be specified. First
+   interrupt number is the otg interrupt number that raises ID interrupts
+   and VBUS interrupts. The second interrupt number is optional.
+ - <supply-name>-supply : phandle to the regulator device tree node.
+   <supply-name> should be vusb1v5, vusb1v8 and vusb3v1
+ - usb_mode : The mode used by the phy to connect to the controller. "1"
+   specifies "ULPI" mode and "2" specifies "CEA2011_3PIN" mode.
+
+twl4030-usb {
+	compatible = "ti,twl4030-usb";
+	interrupts = < 10 4 >;
+	usb1v5-supply = <&vusb1v5>;
+	usb1v8-supply = <&vusb1v8>;
+	usb3v1-supply = <&vusb3v1>;
+	usb_mode = <1>;
+};
diff --git a/Documentation/devicetree/bindings/usb/usb-phy.txt b/Documentation/devicetree/bindings/usb/usb-phy.txt
new file mode 100644
index 0000000..80d4148
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/usb-phy.txt
@@ -0,0 +1,17 @@
+USB PHY
+
+OMAP USB2 PHY
+
+Required properties:
+ - compatible: Should be "ti,omap-usb2"
+ - reg : Address and length of the register set for the device. Also
+add the address of control module dev conf register until a driver for
+control module is added
+
+This is usually a subnode of ocp2scp to which it is connected.
+
+usb2phy@4a0ad080 {
+	compatible = "ti,omap-usb2";
+	reg = <0x4a0ad080 0x58>,
+	      <0x4a002300 0x4>;
+};
diff --git a/Documentation/devicetree/bindings/usb/usbmisc-imx.txt b/Documentation/devicetree/bindings/usb/usbmisc-imx.txt
new file mode 100644
index 0000000..97ce94e
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/usbmisc-imx.txt
@@ -0,0 +1,14 @@
+* Freescale i.MX non-core registers
+
+Required properties:
+- #index-cells: Cells used to descibe usb controller index. Should be <1>
+- compatible: Should be one of below:
+	"fsl,imx6q-usbmisc" for imx6q
+- reg: Should contain registers location and length
+
+Examples:
+usbmisc@02184800 {
+	#index-cells = <1>;
+	compatible = "fsl,imx6q-usbmisc";
+	reg = <0x02184800 0x200>;
+};
diff --git a/Documentation/devicetree/bindings/usb/via,vt8500-ehci.txt b/Documentation/devicetree/bindings/usb/via,vt8500-ehci.txt
new file mode 100644
index 0000000..17b3ad1
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/via,vt8500-ehci.txt
@@ -0,0 +1,15 @@
+VIA/Wondermedia VT8500 EHCI Controller
+-----------------------------------------------------
+
+Required properties:
+- compatible : "via,vt8500-ehci"
+- reg : Should contain 1 register ranges(address and length)
+- interrupts : ehci controller interrupt
+
+Example:
+
+	ehci@d8007900 {
+		compatible = "via,vt8500-ehci";
+		reg = <0xd8007900 0x200>;
+		interrupts = <43>;
+	};
diff --git a/Documentation/devicetree/bindings/usb/vt8500-ehci.txt b/Documentation/devicetree/bindings/usb/vt8500-ehci.txt
new file mode 100644
index 0000000..5fb8fd6
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/vt8500-ehci.txt
@@ -0,0 +1,12 @@
+VIA VT8500 and Wondermedia WM8xxx SoC USB controllers.
+
+Required properties:
+ - compatible: Should be "via,vt8500-ehci" or "wm,prizm-ehci".
+ - reg: Address range of the ehci registers. size should be 0x200
+ - interrupts: Should contain the ehci interrupt.
+
+usb: ehci@D8007100 {
+	compatible = "wm,prizm-ehci", "usb-ehci";
+	reg = <0xD8007100 0x200>;
+	interrupts = <1>;
+};
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index db4d3af..9de2b9f 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -10,6 +10,7 @@ apm	Applied Micro Circuits Corporation (APM)
 arm	ARM Ltd.
 atmel	Atmel Corporation
 bosch	Bosch Sensortec GmbH
+brcm	Broadcom Corporation
 cavium	Cavium, Inc.
 chrp	Common Hardware Reference Platform
 cortina	Cortina Systems, Inc.
@@ -47,5 +48,7 @@ sirf	SiRF Technology, Inc.
 st	STMicroelectronics
 stericsson	ST-Ericsson
 ti	Texas Instruments
+via	VIA Technologies, Inc.
 wlf	Wolfson Microelectronics
+wm	Wondermedia Technologies, Inc.
 xlnx	Xilinx
diff --git a/Documentation/devicetree/bindings/video/via,vt8500-fb.txt b/Documentation/devicetree/bindings/video/via,vt8500-fb.txt
new file mode 100644
index 0000000..c870b64
--- /dev/null
+++ b/Documentation/devicetree/bindings/video/via,vt8500-fb.txt
@@ -0,0 +1,62 @@
+VIA VT8500 Framebuffer
+-----------------------------------------------------
+
+Required properties:
+- compatible : "via,vt8500-fb"
+- reg : Should contain 1 register ranges(address and length)
+- interrupts : framebuffer controller interrupt
+- display: a phandle pointing to the display node
+
+Required nodes:
+- display: a display node is required to initialize the lcd panel
+	This should be in the board dts.
+- default-mode: a videomode within the display with timing parameters
+	as specified below.
+
+Example:
+
+	fb@d800e400 {
+		compatible = "via,vt8500-fb";
+		reg = <0xd800e400 0x400>;
+		interrupts = <12>;
+		display = <&display>;
+		default-mode = <&mode0>;
+	};
+
+VIA VT8500 Display
+-----------------------------------------------------
+Required properties (as per of_videomode_helper):
+
+ - hactive, vactive: Display resolution
+ - hfront-porch, hback-porch, hsync-len: Horizontal Display timing parameters
+   in pixels
+   vfront-porch, vback-porch, vsync-len: Vertical display timing parameters in
+   lines
+ - clock: displayclock in Hz
+ - bpp: lcd panel bit-depth.
+	<16> for RGB565, <32> for RGB888
+
+Optional properties (as per of_videomode_helper):
+ - width-mm, height-mm: Display dimensions in mm
+ - hsync-active-high (bool): Hsync pulse is active high
+ - vsync-active-high (bool): Vsync pulse is active high
+ - interlaced (bool): This is an interlaced mode
+ - doublescan (bool): This is a doublescan mode
+
+Example:
+	display: display@0 {
+		modes {
+			mode0: mode@0 {
+				hactive = <800>;
+				vactive = <480>;
+				hback-porch = <88>;
+				hfront-porch = <40>;
+				hsync-len = <0>;
+				vback-porch = <32>;
+				vfront-porch = <11>;
+				vsync-len = <1>;
+				clock = <0>;	/* unused but required */
+				bpp = <16>;	/* non-standard but required */
+			};
+		};
+	};
diff --git a/Documentation/devicetree/bindings/video/wm,prizm-ge-rops.txt b/Documentation/devicetree/bindings/video/wm,prizm-ge-rops.txt
new file mode 100644
index 0000000..a850fa0
--- /dev/null
+++ b/Documentation/devicetree/bindings/video/wm,prizm-ge-rops.txt
@@ -0,0 +1,13 @@
+VIA/Wondermedia Graphics Engine Controller
+-----------------------------------------------------
+
+Required properties:
+- compatible : "wm,prizm-ge-rops"
+- reg : Should contain 1 register ranges(address and length)
+
+Example:
+
+	ge_rops@d8050400 {
+		compatible = "wm,prizm-ge-rops";
+		reg = <0xd8050400 0x100>;
+	};
diff --git a/Documentation/devicetree/bindings/video/wm,wm8505-fb.txt b/Documentation/devicetree/bindings/video/wm,wm8505-fb.txt
new file mode 100644
index 0000000..3d325e1
--- /dev/null
+++ b/Documentation/devicetree/bindings/video/wm,wm8505-fb.txt
@@ -0,0 +1,23 @@
+Wondermedia WM8505 Framebuffer
+-----------------------------------------------------
+
+Required properties:
+- compatible : "wm,wm8505-fb"
+- reg : Should contain 1 register ranges(address and length)
+- via,display: a phandle pointing to the display node
+
+Required nodes:
+- display: a display node is required to initialize the lcd panel
+	This should be in the board dts. See definition in
+	Documentation/devicetree/bindings/video/via,vt8500-fb.txt
+- default-mode: a videomode node as specified in
+	Documentation/devicetree/bindings/video/via,vt8500-fb.txt
+
+Example:
+
+	fb@d8050800 {
+		compatible = "wm,wm8505-fb";
+		reg = <0xd8050800 0x200>;
+		display = <&display>;
+		default-mode = <&mode0>;
+	};
diff --git a/Documentation/devicetree/bindings/w1/w1-gpio.txt b/Documentation/devicetree/bindings/w1/w1-gpio.txt
new file mode 100644
index 0000000..6e09c35
--- /dev/null
+++ b/Documentation/devicetree/bindings/w1/w1-gpio.txt
@@ -0,0 +1,22 @@
+w1-gpio devicetree bindings
+
+Required properties:
+
+ - compatible: "w1-gpio"
+ - gpios: one or two GPIO specs:
+		- the first one is used as data I/O pin
+		- the second one is optional. If specified, it is used as
+		  enable pin for an external pin pullup.
+
+Optional properties:
+
+ - linux,open-drain: if specified, the data pin is considered in
+		     open-drain mode.
+
+Examples:
+
+	onewire@0 {
+		compatible = "w1-gpio";
+		gpios = <&gpio 126 0>, <&gpio 105 0>;
+	};
+
diff --git a/Documentation/dontdiff b/Documentation/dontdiff
index 39462cf..74c25c8 100644
--- a/Documentation/dontdiff
+++ b/Documentation/dontdiff
@@ -162,7 +162,6 @@ mach-types.h
 machtypes.h
 map
 map_hugetlb
-maui_boot.h
 media
 mconf
 miboot*
diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt
index 950856b..43cff70 100644
--- a/Documentation/driver-model/devres.txt
+++ b/Documentation/driver-model/devres.txt
@@ -284,3 +284,7 @@ CLOCK
 PINCTRL
   devm_pinctrl_get()
   devm_pinctrl_put()
+
+PWM
+  devm_pwm_get()
+  devm_pwm_put()
diff --git a/Documentation/dvb/README.dvb-usb b/Documentation/dvb/README.dvb-usb
index c4d963a..8eb9226 100644
--- a/Documentation/dvb/README.dvb-usb
+++ b/Documentation/dvb/README.dvb-usb
@@ -30,7 +30,7 @@ with the device via the bus. The connection between the DVB-API-functionality
 is done via callbacks, assigned in a static device-description (struct
 dvb_usb_device) each device-driver has to have.
 
-For an example have a look in drivers/media/dvb/dvb-usb/vp7045*.
+For an example have a look in drivers/media/usb/dvb-usb/vp7045*.
 
 Objective is to migrate all the usb-devices (dibusb, cinergyT2, maybe the
 ttusb; flexcop-usb already benefits from the generic flexcop-device) to use
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index f4d8c71..6ccec94 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -6,6 +6,15 @@ be removed from this file.  The suggested deprecation period is 3 releases.
 
 ---------------------------
 
+What:	support for i.mx25 in mx2_camera.c
+When:	v3.8
+Why:	it's been broken for a year. Furthermore, i.MX25 video capture
+	HW doesn't have much in common with i.MX27. A separate driver
+	will be needed for it.
+Who:	Javier Martin<javier.martin@vista-silicon.com>
+
+---------------------------
+
 What:	ddebug_query="query" boot cmdline param
 When:	v3.8
 Why:	obsoleted by dyndbg="query" and module.dyndbg="query"
@@ -115,31 +124,6 @@ Who:	Pavel Machek <pavel@ucw.cz>
 
 ---------------------------
 
-What:	/proc/<pid>/oom_adj
-When:	August 2012
-Why:	/proc/<pid>/oom_adj allows userspace to influence the oom killer's
-	badness heuristic used to determine which task to kill when the kernel
-	is out of memory.
-
-	The badness heuristic has since been rewritten since the introduction of
-	this tunable such that its meaning is deprecated.  The value was
-	implemented as a bitshift on a score generated by the badness()
-	function that did not have any precise units of measure.  With the
-	rewrite, the score is given as a proportion of available memory to the
-	task allocating pages, so using a bitshift which grows the score
-	exponentially is, thus, impossible to tune with fine granularity.
-
-	A much more powerful interface, /proc/<pid>/oom_score_adj, was
-	introduced with the oom killer rewrite that allows users to increase or
-	decrease the badness score linearly.  This interface will replace
-	/proc/<pid>/oom_adj.
-
-	A warning will be emitted to the kernel log if an application uses this
-	deprecated interface.  After it is printed once, future warnings will be
-	suppressed until the kernel is rebooted.
-
----------------------------
-
 What:	remove EXPORT_SYMBOL(kernel_thread)
 When:	August 2006
 Files:	arch/*/kernel/*_ksyms.c
@@ -253,38 +237,6 @@ Who:	Dave Jones <davej@redhat.com>, Matthew Garrett <mjg@redhat.com>
 
 -----------------------------
 
-What:	fakephp and associated sysfs files in /sys/bus/pci/slots/
-When:	2011
-Why:	In 2.6.27, the semantics of /sys/bus/pci/slots was redefined to
-	represent a machine's physical PCI slots. The change in semantics
-	had userspace implications, as the hotplug core no longer allowed
-	drivers to create multiple sysfs files per physical slot (required
-	for multi-function devices, e.g.). fakephp was seen as a developer's
-	tool only, and its interface changed. Too late, we learned that
-	there were some users of the fakephp interface.
-
-	In 2.6.30, the original fakephp interface was restored. At the same
-	time, the PCI core gained the ability that fakephp provided, namely
-	function-level hot-remove and hot-add.
-
-	Since the PCI core now provides the same functionality, exposed in:
-
-		/sys/bus/pci/rescan
-		/sys/bus/pci/devices/.../remove
-		/sys/bus/pci/devices/.../rescan
-
-	there is no functional reason to maintain fakephp as well.
-
-	We will keep the existing module so that 'modprobe fakephp' will
-	present the old /sys/bus/pci/slots/... interface for compatibility,
-	but users are urged to migrate their applications to the API above.
-
-	After a reasonable transition period, we will remove the legacy
-	fakephp interface.
-Who:	Alex Chiang <achiang@hp.com>
-
----------------------------
-
 What:	CONFIG_RFKILL_INPUT
 When:	2.6.33
 Why:	Should be implemented in userspace, policy daemon.
@@ -353,14 +305,6 @@ Why:	Internal alias support has been present in module-init-tools for some
 
 Who:	Wey-Yi Guy <wey-yi.w.guy@intel.com>
 
----------------------------
-
-What:	xt_NOTRACK
-Files:	net/netfilter/xt_NOTRACK.c
-When:	April 2011
-Why:	Superseded by xt_CT
-Who:	Netfilter developer team <netfilter-devel@vger.kernel.org>
-
 ----------------------------
 
 What:	IRQF_DISABLED
@@ -389,16 +333,6 @@ Who:	Wey-Yi Guy <wey-yi.w.guy@intel.com>
 
 ----------------------------
 
-What:	Legacy, non-standard chassis intrusion detection interface.
-When:	June 2011
-Why:	The adm9240, w83792d and w83793 hardware monitoring drivers have
-	legacy interfaces for chassis intrusion detection. A standard
-	interface has been added to each driver, so the legacy interface
-	can be removed.
-Who:	Jean Delvare <khali@linux-fr.org>
-
-----------------------------
-
 What:	i2c_driver.attach_adapter
 	i2c_driver.detach_adapter
 When:	September 2011
@@ -495,17 +429,6 @@ Who:	Bjorn Helgaas <bhelgaas@google.com>
 
 ----------------------------
 
-What:	Low Performance USB Block driver ("CONFIG_BLK_DEV_UB")
-When:	3.6
-Why:	This driver provides support for USB storage devices like "USB
-	sticks". As of now, it is deactivated in Debian, Fedora and
-        Ubuntu. All current users can switch over to usb-storage
-        (CONFIG_USB_STORAGE) which only drawback is the additional SCSI
-        stack.
-Who:	Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
-
-----------------------------
-
 What:	get_robust_list syscall
 When:	2013
 Why:	There appear to be no production users of the get_robust_list syscall,
@@ -516,18 +439,6 @@ Who:	Kees Cook <keescook@chromium.org>
 
 ----------------------------
 
-What:	Removing the pn544 raw driver.
-When:	3.6
-Why:	With the introduction of the NFC HCI and SHDL kernel layers, pn544.c
-	is being replaced by pn544_hci.c which is accessible through the netlink
-	and socket NFC APIs. Moreover, pn544.c is outdated and does not seem to
-	work properly with the latest Android stacks.
-	Having 2 drivers for the same hardware is confusing and as such we
-	should only keep the one following the kernel NFC APIs.
-Who:	Samuel Ortiz <sameo@linux.intel.com>
-
-----------------------------
-
 What:	setitimer accepts user NULL pointer (value)
 When:	3.6
 Why:	setitimer is not returning -EFAULT if user pointer is NULL. This
diff --git a/Documentation/filesystems/debugfs.txt b/Documentation/filesystems/debugfs.txt
index 7a34f82..3a863f6 100644
--- a/Documentation/filesystems/debugfs.txt
+++ b/Documentation/filesystems/debugfs.txt
@@ -15,8 +15,8 @@ Debugfs is typically mounted with a command like:
     mount -t debugfs none /sys/kernel/debug
 
 (Or an equivalent /etc/fstab line).
-The debugfs root directory is accessible by anyone by default. To
-restrict access to the tree the "uid", "gid" and "mode" mount
+The debugfs root directory is accessible only to the root user by
+default. To change access to the tree the "uid", "gid" and "mode" mount
 options can be used.
 
 Note that the debugfs API is exported GPL-only to modules.
diff --git a/Documentation/filesystems/ext4.txt b/Documentation/filesystems/ext4.txt
index 1b7f9ac..104322b 100644
--- a/Documentation/filesystems/ext4.txt
+++ b/Documentation/filesystems/ext4.txt
@@ -375,6 +375,16 @@ dioread_nolock		locking. If the dioread_nolock option is specified
 			Because of the restrictions this options comprises
 			it is off by default (e.g. dioread_lock).
 
+max_dir_size_kb=n	This limits the size of directories so that any
+			attempt to expand them beyond the specified
+			limit in kilobytes will cause an ENOSPC error.
+			This is useful in memory constrained
+			environments, where a very large directory can
+			cause severe performance problems or even
+			provoke the Out Of Memory killer.  (For example,
+			if there is only 512mb memory available, a 176mb
+			directory may seriously cramp the system's style.)
+
 i_version		Enable 64-bit inode version support. This option is
 			off by default.
 
diff --git a/Documentation/filesystems/jfs.txt b/Documentation/filesystems/jfs.txt
index 26ebde7..f743335 100644
--- a/Documentation/filesystems/jfs.txt
+++ b/Documentation/filesystems/jfs.txt
@@ -3,6 +3,7 @@ IBM's Journaled File System (JFS) for Linux
 JFS Homepage:  http://jfs.sourceforge.net/
 
 The following mount options are supported:
+(*) == default
 
 iocharset=name	Character set to use for converting from Unicode to
 		ASCII.  The default is to do no conversion.  Use
@@ -21,12 +22,12 @@ nointegrity	Do not write to the journal.  The primary use of this option
 		from backup media.  The integrity of the volume is not
 		guaranteed if the system abnormally abends.
 
-integrity	Default.  Commit metadata changes to the journal.  Use this
-		option to remount a volume where the nointegrity option was
+integrity(*)	Commit metadata changes to the journal.  Use this option to
+		remount a volume where the nointegrity option was
 		previously specified in order to restore normal behavior.
 
 errors=continue		Keep going on a filesystem error.
-errors=remount-ro	Default. Remount the filesystem read-only on an error.
+errors=remount-ro(*)	Remount the filesystem read-only on an error.
 errors=panic		Panic and halt the machine if an error occurs.
 
 uid=value	Override on-disk uid with specified value
@@ -35,7 +36,17 @@ umask=value	Override on-disk umask with specified octal value.  For
 		directories, the execute bit will be set if the corresponding
 		read bit is set.
 
-Please send bugs, comments, cards and letters to shaggy@linux.vnet.ibm.com.
+discard=minlen	This enables/disables the use of discard/TRIM commands.
+discard		The discard/TRIM commands are sent to the underlying
+nodiscard(*)	block device when blocks are freed. This is useful for SSD
+		devices and sparse/thinly-provisioned LUNs.  The FITRIM ioctl
+		command is also available together with the nodiscard option.
+		The value of minlen specifies the minimum blockcount, when
+		a TRIM command to the block device is considered usefull.
+		When no value is given to the discard option, it defaults to
+		64 blocks, which means 256KiB in JFS.
+		The minlen value of discard overrides the minlen value given
+		on an FITRIM ioctl().
 
 The JFS mailing list can be subscribed to by using the link labeled
 "Mail list Subscribe" at our web page http://jfs.sourceforge.net/
diff --git a/Documentation/filesystems/nfs/nfsd-admin-interfaces.txt b/Documentation/filesystems/nfs/nfsd-admin-interfaces.txt
new file mode 100644
index 0000000..56a96fb
--- /dev/null
+++ b/Documentation/filesystems/nfs/nfsd-admin-interfaces.txt
@@ -0,0 +1,41 @@
+Administrative interfaces for nfsd
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Note that normally these interfaces are used only by the utilities in
+nfs-utils.
+
+nfsd is controlled mainly by pseudofiles under the "nfsd" filesystem,
+which is normally mounted at /proc/fs/nfsd/.
+
+The server is always started by the first write of a nonzero value to
+nfsd/threads.
+
+Before doing that, NFSD can be told which sockets to listen on by
+writing to nfsd/portlist; that write may be:
+
+	- an ascii-encoded file descriptor, which should refer to a
+	  bound (and listening, for tcp) socket, or
+	- "transportname port", where transportname is currently either
+	  "udp", "tcp", or "rdma".
+
+If nfsd is started without doing any of these, then it will create one
+udp and one tcp listener at port 2049 (see nfsd_init_socks).
+
+On startup, nfsd and lockd grace periods start.
+
+nfsd is shut down by a write of 0 to nfsd/threads.  All locks and state
+are thrown away at that point.
+
+Between startup and shutdown, the number of threads may be adjusted up
+or down by additional writes to nfsd/threads or by writes to
+nfsd/pool_threads.
+
+For more detail about files under nfsd/ and what they control, see
+fs/nfsd/nfsctl.c; most of them have detailed comments.
+
+Implementation notes
+^^^^^^^^^^^^^^^^^^^^
+
+Note that the rpc server requires the caller to serialize addition and
+removal of listening sockets, and startup and shutdown of the server.
+For nfsd this is done using nfsd_mutex.
diff --git a/Documentation/filesystems/nfs/nfsroot.txt b/Documentation/filesystems/nfs/nfsroot.txt
index ffdd9d8..2d66ed6 100644
--- a/Documentation/filesystems/nfs/nfsroot.txt
+++ b/Documentation/filesystems/nfs/nfsroot.txt
@@ -78,7 +78,8 @@ nfsroot=[<server-ip>:]<root-dir>[,<nfs-options>]
 			flags		= hard, nointr, noposix, cto, ac
 
 
-ip=<client-ip>:<server-ip>:<gw-ip>:<netmask>:<hostname>:<device>:<autoconf>
+ip=<client-ip>:<server-ip>:<gw-ip>:<netmask>:<hostname>:<device>:<autoconf>:
+   <dns0-ip>:<dns1-ip>
 
   This parameter tells the kernel how to configure IP addresses of devices
   and also how to set up the IP routing table. It was originally called
@@ -158,6 +159,13 @@ ip=<client-ip>:<server-ip>:<gw-ip>:<netmask>:<hostname>:<device>:<autoconf>
 
                 Default: any
 
+  <dns0-ip>	IP address of first nameserver.
+		Value gets exported by /proc/net/pnp which is often linked
+		on embedded systems by /etc/resolv.conf.
+
+  <dns1-ip>	IP address of secound nameserver.
+		Same as above.
+
 
 nfsrootdebug
 
diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
index fb0a6ae..a1793d6 100644
--- a/Documentation/filesystems/proc.txt
+++ b/Documentation/filesystems/proc.txt
@@ -33,7 +33,7 @@ Table of Contents
   2	Modifying System Parameters
 
   3	Per-Process Parameters
-  3.1	/proc/<pid>/oom_adj & /proc/<pid>/oom_score_adj - Adjust the oom-killer
+  3.1	/proc/<pid>/oom_score_adj - Adjust the oom-killer
 								score
   3.2	/proc/<pid>/oom_score - Display current oom-killer score
   3.3	/proc/<pid>/io - Display the IO accounting fields
@@ -1320,10 +1320,10 @@ of the kernel.
 CHAPTER 3: PER-PROCESS PARAMETERS
 ------------------------------------------------------------------------------
 
-3.1 /proc/<pid>/oom_adj & /proc/<pid>/oom_score_adj- Adjust the oom-killer score
+3.1 /proc/<pid>/oom_score_adj- Adjust the oom-killer score
 --------------------------------------------------------------------------------
 
-These file can be used to adjust the badness heuristic used to select which
+This file can be used to adjust the badness heuristic used to select which
 process gets killed in out of memory conditions.
 
 The badness heuristic assigns a value to each candidate task ranging from 0
@@ -1361,22 +1361,10 @@ same system, cpuset, mempolicy, or memory controller resources to use at least
 equivalent to discounting 50% of the task's allowed memory from being considered
 as scoring against the task.
 
-For backwards compatibility with previous kernels, /proc/<pid>/oom_adj may also
-be used to tune the badness score.  Its acceptable values range from -16
-(OOM_ADJUST_MIN) to +15 (OOM_ADJUST_MAX) and a special value of -17
-(OOM_DISABLE) to disable oom killing entirely for that task.  Its value is
-scaled linearly with /proc/<pid>/oom_score_adj.
-
-Writing to /proc/<pid>/oom_score_adj or /proc/<pid>/oom_adj will change the
-other with its scaled value.
-
 The value of /proc/<pid>/oom_score_adj may be reduced no lower than the last
 value set by a CAP_SYS_RESOURCE process. To reduce the value any lower
 requires CAP_SYS_RESOURCE.
 
-NOTICE: /proc/<pid>/oom_adj is deprecated and will be removed, please see
-Documentation/feature-removal-schedule.txt.
-
 Caveat: when a parent task is selected, the oom killer will sacrifice any first
 generation children with separate address spaces instead, if possible.  This
 avoids servers and important system daemons from being killed and loses the
@@ -1387,9 +1375,7 @@ minimal amount of work.
 -------------------------------------------------------------
 
 This file can be used to check the current score used by the oom-killer is for
-any given <pid>. Use it together with /proc/<pid>/oom_adj to tune which
-process should be killed in an out-of-memory situation.
-
+any given <pid>.
 
 3.3  /proc/<pid>/io - Display the IO accounting fields
 -------------------------------------------------------
diff --git a/Documentation/hid/hid-sensor.txt b/Documentation/hid/hid-sensor.txt
new file mode 100755
index 0000000..948b098
--- /dev/null
+++ b/Documentation/hid/hid-sensor.txt
@@ -0,0 +1,140 @@
+
+HID Sensors Framework
+======================
+HID sensor framework provides necessary interfaces to implement sensor drivers,
+which are connected to a sensor hub. The sensor hub is a HID device and it provides
+a report descriptor conforming to HID 1.12 sensor usage tables.
+
+Description from the HID 1.12 "HID Sensor Usages" specification:
+"Standardization of HID usages for sensors would allow (but not require) sensor
+hardware vendors to provide a consistent Plug And Play interface at the USB boundary,
+thereby enabling some operating systems to incorporate common device drivers that
+could be reused between vendors, alleviating any need for the vendors to provide
+the drivers themselves."
+
+This specification describes many usage IDs, which describe the type of sensor
+and also the individual data fields. Each sensor can have variable number of
+data fields. The length and order is specified in the report descriptor. For
+example a part of report descriptor can look like:
+
+   INPUT(1)[INPUT]
+ ..
+    Field(2)
+      Physical(0020.0073)
+      Usage(1)
+        0020.045f
+      Logical Minimum(-32767)
+      Logical Maximum(32767)
+      Report Size(8)
+      Report Count(1)
+      Report Offset(16)
+      Flags(Variable Absolute)
+..
+..
+
+The report is indicating "sensor page (0x20)" contains an accelerometer-3D (0x73).
+This accelerometer-3D has some fields. Here for example field 2 is motion intensity
+(0x045f) with a logical minimum value of -32767 and logical maximum of 32767. The
+order of fields and length of each field is important as the input event raw
+data will use this format.
+
+
+Implementation
+=================
+
+This specification defines many different types of sensors with different sets of
+data fields. It is difficult to have a common input event to user space applications,
+for different sensors. For example an accelerometer can send X,Y and Z data, whereas
+an ambient light sensor can send illumination data.
+So the implementation has two parts:
+- Core hid driver
+- Individual sensor processing part (sensor drivers)
+
+Core driver
+-----------
+The core driver registers (hid-sensor-hub) registers as a HID driver. It parses
+report descriptors and identifies all the sensors present. It adds an MFD device
+with name HID-SENSOR-xxxx (where xxxx is usage id from the specification).
+For example
+HID-SENSOR-200073 is registered for an Accelerometer 3D driver.
+So if any driver with this name is inserted, then the probe routine for that
+function will be called. So an accelerometer processing driver can register
+with this name and will be probed if there is an accelerometer-3D detected.
+
+The core driver provides a set of APIs which can be used by the processing
+drivers to register and get events for that usage id. Also it provides parsing
+functions, which get and set each input/feature/output report.
+
+Individual sensor processing part (sensor drivers)
+-----------
+The processing driver will use an interface provided by the core driver to parse
+the report and get the indexes of the fields and also can get events. This driver
+can use IIO interface to use the standard ABI defined for a type of sensor.
+
+
+Core driver Interface
+=====================
+
+Callback structure:
+Each processing driver can use this structure to set some callbacks.
+	int (*suspend)(..): Callback when HID suspend is received
+	int (*resume)(..): Callback when HID resume is received
+	int (*capture_sample)(..): Capture a sample for one of its data fields
+	int (*send_event)(..): One complete event is received which can have
+                               multiple data fields.
+
+Registration functions:
+int sensor_hub_register_callback(struct hid_sensor_hub_device *hsdev,
+			u32 usage_id,
+			struct hid_sensor_hub_callbacks *usage_callback):
+
+Registers callbacks for an usage id. The callback functions are not allowed
+to sleep.
+
+
+int sensor_hub_remove_callback(struct hid_sensor_hub_device *hsdev,
+			u32 usage_id):
+
+Removes callbacks for an usage id.
+
+
+Parsing function:
+int sensor_hub_input_get_attribute_info(struct hid_sensor_hub_device *hsdev,
+			u8 type,
+			u32 usage_id, u32 attr_usage_id,
+			struct hid_sensor_hub_attribute_info *info);
+
+A processing driver can look for some field of interest and check if it exists
+in a report descriptor. If it exists it will store necessary information
+so that fields can be set or get individually.
+These indexes avoid searching every time and getting field index to get or set.
+
+
+Set Feature report
+int sensor_hub_set_feature(struct hid_sensor_hub_device *hsdev, u32 report_id,
+			u32 field_index, s32 value);
+
+This interface is used to set a value for a field in feature report. For example
+if there is a field report_interval, which is parsed by a call to
+sensor_hub_input_get_attribute_info before, then it can directly set that individual
+field.
+
+
+int sensor_hub_get_feature(struct hid_sensor_hub_device *hsdev, u32 report_id,
+			u32 field_index, s32 *value);
+
+This interface is used to get a value for a field in input report. For example
+if there is a field report_interval, which is parsed by a call to
+sensor_hub_input_get_attribute_info before, then it can directly get that individual
+field value.
+
+
+int sensor_hub_input_attr_get_raw_value(struct hid_sensor_hub_device *hsdev,
+			u32 usage_id,
+			u32 attr_usage_id, u32 report_id);
+
+This is used to get a particular field value through input reports. For example
+accelerometer wants to poll X axis value, then it can call this function with
+the usage id of X axis. HID sensors can provide events, so this is not necessary
+to poll for any field. If there is some new sample, the core driver will call
+registered callback function to process the sample.
diff --git a/Documentation/hwmon/adt7410 b/Documentation/hwmon/adt7410
new file mode 100644
index 0000000..9600400
--- /dev/null
+++ b/Documentation/hwmon/adt7410
@@ -0,0 +1,51 @@
+Kernel driver adt7410
+=====================
+
+Supported chips:
+  * Analog Devices ADT7410
+    Prefix: 'adt7410'
+    Addresses scanned: I2C 0x48 - 0x4B
+    Datasheet: Publicly available at the Analog Devices website
+               http://www.analog.com/static/imported-files/data_sheets/ADT7410.pdf
+
+Author: Hartmut Knaack <knaack.h@gmx.de>
+
+Description
+-----------
+
+The ADT7410 is a temperature sensor with rated temperature range of -55°C to
++150°C. It has a high accuracy of +/-0.5°C and can be operated at a resolution
+of 13 bits (0.0625°C) or 16 bits (0.0078°C). The sensor provides an INT pin to
+indicate that a minimum or maximum temperature set point has been exceeded, as
+well as a critical temperature (CT) pin to indicate that the critical
+temperature set point has been exceeded. Both pins can be set up with a common
+hysteresis of 0°C - 15°C and a fault queue, ranging from 1 to 4 events. Both
+pins can individually set to be active-low or active-high, while the whole
+device can either run in comparator mode or interrupt mode. The ADT7410
+supports continous temperature sampling, as well as sampling one temperature
+value per second or even justget one sample on demand for power saving.
+Besides, it can completely power down its ADC, if power management is
+required.
+
+Configuration Notes
+-------------------
+
+Since the device uses one hysteresis value, which is an offset to minimum,
+maximum and critical temperature, it can only be set for temp#_max_hyst.
+However, temp#_min_hyst and temp#_crit_hyst show their corresponding
+hysteresis.
+The device is set to 16 bit resolution and comparator mode.
+
+sysfs-Interface
+---------------
+
+temp#_input		- temperature input
+temp#_min		- temperature minimum setpoint
+temp#_max		- temperature maximum setpoint
+temp#_crit		- critical temperature setpoint
+temp#_min_hyst		- hysteresis for temperature minimum (read-only)
+temp#_max_hyst		- hysteresis for temperature maximum (read/write)
+temp#_crit_hyst		- hysteresis for critical temperature (read-only)
+temp#_min_alarm		- temperature minimum alarm flag
+temp#_max_alarm		- temperature maximum alarm flag
+temp#_crit_alarm	- critical temperature alarm flag
diff --git a/Documentation/hwmon/exynos4_tmu b/Documentation/hwmon/exynos4_tmu
deleted file mode 100644
index c3c6b41..0000000
--- a/Documentation/hwmon/exynos4_tmu
+++ /dev/null
@@ -1,81 +0,0 @@
-Kernel driver exynos4_tmu
-=================
-
-Supported chips:
-* ARM SAMSUNG EXYNOS4 series of SoC
-  Prefix: 'exynos4-tmu'
-  Datasheet: Not publicly available
-
-Authors: Donggeun Kim <dg77.kim@samsung.com>
-
-Description
------------
-
-This driver allows to read temperature inside SAMSUNG EXYNOS4 series of SoC.
-
-The chip only exposes the measured 8-bit temperature code value
-through a register.
-Temperature can be taken from the temperature code.
-There are three equations converting from temperature to temperature code.
-
-The three equations are:
-  1. Two point trimming
-	Tc = (T - 25) * (TI2 - TI1) / (85 - 25) + TI1
-
-  2. One point trimming
-	Tc = T + TI1 - 25
-
-  3. No trimming
-	Tc = T + 50
-
-  Tc: Temperature code, T: Temperature,
-  TI1: Trimming info for 25 degree Celsius (stored at TRIMINFO register)
-       Temperature code measured at 25 degree Celsius which is unchanged
-  TI2: Trimming info for 85 degree Celsius (stored at TRIMINFO register)
-       Temperature code measured at 85 degree Celsius which is unchanged
-
-TMU(Thermal Management Unit) in EXYNOS4 generates interrupt
-when temperature exceeds pre-defined levels.
-The maximum number of configurable threshold is four.
-The threshold levels are defined as follows:
-  Level_0: current temperature > trigger_level_0 + threshold
-  Level_1: current temperature > trigger_level_1 + threshold
-  Level_2: current temperature > trigger_level_2 + threshold
-  Level_3: current temperature > trigger_level_3 + threshold
-
-  The threshold and each trigger_level are set
-  through the corresponding registers.
-
-When an interrupt occurs, this driver notify user space of
-one of four threshold levels for the interrupt
-through kobject_uevent_env and sysfs_notify functions.
-Although an interrupt condition for level_0 can be set,
-it is not notified to user space through sysfs_notify function.
-
-Sysfs Interface
----------------
-name		name of the temperature sensor
-		RO
-
-temp1_input	temperature
-		RO
-
-temp1_max	temperature for level_1 interrupt
-		RO
-
-temp1_crit	temperature for level_2 interrupt
-		RO
-
-temp1_emergency	temperature for level_3 interrupt
-		RO
-
-temp1_max_alarm	alarm for level_1 interrupt
-		RO
-
-temp1_crit_alarm
-		alarm for level_2 interrupt
-		RO
-
-temp1_emergency_alarm
-		alarm for level_3 interrupt
-		RO
diff --git a/Documentation/hwmon/ina2xx b/Documentation/hwmon/ina2xx
index f50a6cc..03444f9 100644
--- a/Documentation/hwmon/ina2xx
+++ b/Documentation/hwmon/ina2xx
@@ -8,12 +8,24 @@ Supported chips:
     Datasheet: Publicly available at the Texas Instruments website
                http://www.ti.com/
 
+  * Texas Instruments INA220
+    Prefix: 'ina220'
+    Addresses: I2C 0x40 - 0x4f
+    Datasheet: Publicly available at the Texas Instruments website
+               http://www.ti.com/
+
   * Texas Instruments INA226
     Prefix: 'ina226'
     Addresses: I2C 0x40 - 0x4f
     Datasheet: Publicly available at the Texas Instruments website
                http://www.ti.com/
 
+  * Texas Instruments INA230
+    Prefix: 'ina230'
+    Addresses: I2C 0x40 - 0x4f
+    Datasheet: Publicly available at the Texas Instruments website
+               http://www.ti.com/
+
 Author: Lothar Felten <l-felten@ti.com>
 
 Description
@@ -23,7 +35,13 @@ The INA219 is a high-side current shunt and power monitor with an I2C
 interface. The INA219 monitors both shunt drop and supply voltage, with
 programmable conversion times and filtering.
 
+The INA220 is a high or low side current shunt and power monitor with an I2C
+interface. The INA220 monitors both shunt drop and supply voltage.
+
 The INA226 is a current shunt and power monitor with an I2C interface.
 The INA226 monitors both a shunt voltage drop and bus supply voltage.
 
+The INA230 is a high or low side current shunt and power monitor with an I2C
+interface. The INA230 monitors both a shunt voltage drop and bus supply voltage.
+
 The shunt value in micro-ohms can be set via platform data.
diff --git a/Documentation/hwmon/lm70 b/Documentation/hwmon/lm70
index 0d24029..86d1829 100644
--- a/Documentation/hwmon/lm70
+++ b/Documentation/hwmon/lm70
@@ -6,6 +6,10 @@ Supported chips:
     Datasheet: http://www.national.com/pf/LM/LM70.html
   * Texas Instruments TMP121/TMP123
     Information: http://focus.ti.com/docs/prod/folders/print/tmp121.html
+  * National Semiconductor LM71
+    Datasheet: http://www.ti.com/product/LM71
+  * National Semiconductor LM74
+    Datasheet: http://www.ti.com/product/LM74
 
 Author:
         Kaiwan N Billimoria <kaiwan@designergraphix.com>
@@ -31,9 +35,11 @@ As a real (in-tree) example of this "SPI protocol driver" interfacing
 with a "SPI master controller driver", see drivers/spi/spi_lm70llp.c
 and its associated documentation.
 
-The TMP121/TMP123 are very similar; main differences are 4 wire SPI inter-
-face (read only) and 13-bit temperature data (0.0625 degrees celsius reso-
-lution).
+The LM74 and TMP121/TMP123 are very similar; main difference is 13-bit
+temperature data (0.0625 degrees celsius resolution).
+
+The LM71 is also very similar; main difference is 14-bit temperature
+data (0.03125 degrees celsius resolution).
 
 Thanks to
 ---------
diff --git a/Documentation/hwmon/max1619 b/Documentation/hwmon/max1619
index d6f8d9c..e6d8739 100644
--- a/Documentation/hwmon/max1619
+++ b/Documentation/hwmon/max1619
@@ -9,7 +9,7 @@ Supported chips:
                http://pdfserv.maxim-ic.com/en/ds/MAX1619.pdf
 
 Authors:
-        Alexey Fisher <fishor@mail.ru>,
+        Oleksij Rempel <bug-track@fisher-privat.net>,
         Jean Delvare <khali@linux-fr.org>
 
 Description
diff --git a/Documentation/hwmon/max197 b/Documentation/hwmon/max197
new file mode 100644
index 0000000..8d89b90
--- /dev/null
+++ b/Documentation/hwmon/max197
@@ -0,0 +1,60 @@
+Maxim MAX197 driver
+===================
+
+Author:
+  * Vivien Didelot <vivien.didelot@savoirfairelinux.com>
+
+Supported chips:
+  * Maxim MAX197
+    Prefix: 'max197'
+    Datasheet: http://datasheets.maxim-ic.com/en/ds/MAX197.pdf
+
+  * Maxim MAX199
+    Prefix: 'max199'
+    Datasheet: http://datasheets.maxim-ic.com/en/ds/MAX199.pdf
+
+Description
+-----------
+
+The A/D converters MAX197, and MAX199 are both 8-Channel, Multi-Range, 5V,
+12-Bit DAS with 8+4 Bus Interface and Fault Protection.
+
+The available ranges for the MAX197 are {0,-5V} to 5V, and {0,-10V} to 10V,
+while they are {0,-2V} to 2V, and {0,-4V} to 4V on the MAX199.
+
+Platform data
+-------------
+
+The MAX197 platform data (defined in linux/platform_data/max197.h) should be
+filled with a pointer to a conversion function, defined like:
+
+    int convert(u8 ctrl);
+
+ctrl is the control byte to write to start a new conversion.
+On success, the function must return the 12-bit raw value read from the chip,
+or a negative error code otherwise.
+
+Control byte format:
+
+Bit     Name       Description
+7,6     PD1,PD0    Clock and Power-Down modes
+5       ACQMOD     Internal or External Controlled Acquisition
+4       RNG        Full-scale voltage magnitude at the input
+3       BIP        Unipolar or Bipolar conversion mode
+2,1,0   A2,A1,A0   Channel
+
+Sysfs interface
+---------------
+
+* in[0-7]_input: The conversion value for the corresponding channel.
+                 RO
+
+* in[0-7]_min:   The lower limit (in mV) for the corresponding channel.
+                 For the MAX197, it will be adjusted to -10000, -5000, or 0.
+                 For the MAX199, it will be adjusted to -4000, -2000, or 0.
+                 RW
+
+* in[0-7]_max:   The higher limit (in mV) for the corresponding channel.
+                 For the MAX197, it will be adjusted to 0, 5000, or 10000.
+                 For the MAX199, it will be adjusted to 0, 2000, or 4000.
+                 RW
diff --git a/Documentation/hwmon/mcp3021 b/Documentation/hwmon/mcp3021
index 325fd87..74a6b72 100644
--- a/Documentation/hwmon/mcp3021
+++ b/Documentation/hwmon/mcp3021
@@ -5,18 +5,25 @@ Supported chips:
   * Microchip Technology MCP3021
     Prefix: 'mcp3021'
     Datasheet: http://ww1.microchip.com/downloads/en/DeviceDoc/21805a.pdf
+  * Microchip Technology MCP3221
+    Prefix: 'mcp3221'
+    Datasheet: http://ww1.microchip.com/downloads/en/DeviceDoc/21732c.pdf
 
-Author: Mingkai Hu
+Authors:
+   Mingkai Hu
+   Sven Schuchmann <schuchmann@schleissheimer.de>
 
 Description
 -----------
 
-This driver implements support for the Microchip Technology MCP3021 chip.
+This driver implements support for the Microchip Technology MCP3021 and
+MCP3221 chip.
 
 The Microchip Technology Inc. MCP3021 is a successive approximation A/D
-converter (ADC) with 10-bit resolution.
-This device provides one single-ended input with very low power consumption.
-Communication to the MCP3021 is performed using a 2-wire I2C compatible
-interface. Standard (100 kHz) and Fast (400 kHz) I2C modes are available.
-The default I2C device address is 0x4d (contact the Microchip factory for
-additional address options).
+converter (ADC) with 10-bit resolution. The MCP3221 has 12-bit resolution.
+
+These devices provide one single-ended input with very low power consumption.
+Communication to the MCP3021/MCP3221  is performed using a 2-wire I2C
+compatible interface. Standard (100 kHz) and Fast (400 kHz) I2C modes are
+available. The default I2C device address is 0x4d (contact the Microchip
+factory for additional address options).
diff --git a/Documentation/ia64/aliasing-test.c b/Documentation/ia64/aliasing-test.c
index 5caa2af..62a190d 100644
--- a/Documentation/ia64/aliasing-test.c
+++ b/Documentation/ia64/aliasing-test.c
@@ -132,6 +132,7 @@ static int read_rom(char *path)
 
 	rc = write(fd, "1", 2);
 	if (rc <= 0) {
+		close(fd);
 		perror("write");
 		return -1;
 	}
diff --git a/Documentation/infiniband/ipoib.txt b/Documentation/infiniband/ipoib.txt
index 64eeb55..f2cfe26 100644
--- a/Documentation/infiniband/ipoib.txt
+++ b/Documentation/infiniband/ipoib.txt
@@ -24,6 +24,9 @@ Partitions and P_Keys
   The P_Key for any interface is given by the "pkey" file, and the
   main interface for a subinterface is in "parent."
 
+  Child interface create/delete can also be done using IPoIB's
+  rtnl_link_ops, where childs created using either way behave the same.
+
 Datagram vs Connected modes
 
   The IPoIB driver supports two modes of operation: datagram and
diff --git a/Documentation/ioctl/ioctl-number.txt b/Documentation/ioctl/ioctl-number.txt
index 849b771..2152b0e 100644
--- a/Documentation/ioctl/ioctl-number.txt
+++ b/Documentation/ioctl/ioctl-number.txt
@@ -178,7 +178,6 @@ Code  Seq#(hex)	Include File		Comments
 'V'	C0	linux/ivtv.h		conflict!
 'V'	C0	media/davinci/vpfe_capture.h	conflict!
 'V'	C0	media/si4713.h		conflict!
-'V'	C0-CF	drivers/media/video/mxb.h	conflict!
 'W'	00-1F	linux/watchdog.h	conflict!
 'W'	00-1F	linux/wanrouter.h	conflict!
 'W'	00-3F	sound/asound.h		conflict!
@@ -204,8 +203,6 @@ Code  Seq#(hex)	Include File		Comments
 'c'	A0-AF   arch/x86/include/asm/msr.h	conflict!
 'd'	00-FF	linux/char/drm/drm/h	conflict!
 'd'	02-40	pcmcia/ds.h		conflict!
-'d'	10-3F	drivers/media/video/dabusb.h	conflict!
-'d'	C0-CF	drivers/media/video/saa7191.h	conflict!
 'd'	F0-FF	linux/digi1.h
 'e'	all	linux/digi1.h		conflict!
 'e'	00-1F	drivers/net/irda/irtty-sir.h	conflict!
@@ -267,9 +264,7 @@ Code  Seq#(hex)	Include File		Comments
 'v'	00-1F	linux/ext2_fs.h		conflict!
 'v'	00-1F	linux/fs.h		conflict!
 'v'	00-0F	linux/sonypi.h		conflict!
-'v'	C0-DF	media/pwc-ioctl.h	conflict!
 'v'	C0-FF	linux/meye.h		conflict!
-'v'	D0-DF	drivers/media/video/cpia2/cpia2dev.h	conflict!
 'w'	all				CERN SCI driver
 'y'	00-1F				packet based user level communications
 					<mailto:zapman@interlan.net>
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index ad7e2e5..f777fa9 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -1051,6 +1051,14 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 	ihash_entries=	[KNL]
 			Set number of hash buckets for inode cache.
 
+	ima_appraise=	[IMA] appraise integrity measurements
+			Format: { "off" | "enforce" | "fix" }
+			default: "enforce"
+
+	ima_appraise_tcb [IMA]
+			The builtin appraise policy appraises all files
+			owned by uid=0.
+
 	ima_audit=	[IMA]
 			Format: { "0" | "1" }
 			0 -- integrity auditing messages. (Default)
@@ -1350,6 +1358,9 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 			* nohrst, nosrst, norst: suppress hard, soft
                           and both resets.
 
+			* rstonce: only attempt one reset during
+			  hot-unplug link recovery
+
 			* dump_id: dump IDENTIFY data.
 
 			If there are multiple matching configurations changing
@@ -1812,8 +1823,12 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 			noexec=on: enable non-executable mappings (default)
 			noexec=off: disable non-executable mappings
 
+	nosmap		[X86]
+			Disable SMAP (Supervisor Mode Access Prevention)
+			even if it is supported by processor.
+
 	nosmep		[X86]
-			Disable SMEP (Supervisor Mode Execution Protection)
+			Disable SMEP (Supervisor Mode Execution Prevention)
 			even if it is supported by processor.
 
 	noexec32	[X86-64]
@@ -1833,6 +1848,12 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 			and restore using xsave. The kernel will fallback to
 			enabling legacy floating-point and sse state.
 
+	eagerfpu=	[X86]
+			on	enable eager fpu restore
+			off	disable eager fpu restore
+			auto	selects the default scheme, which automatically
+				enables eagerfpu restore for xsaveopt.
+
 	nohlt		[BUGS=ARM,SH] Tells the kernel that the sleep(SH) or
 			wfi(ARM) instruction doesn't work correctly and not to
 			use it. This is also useful when using JTAG debugger.
@@ -2385,6 +2406,17 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 	rcutree.rcu_cpu_stall_timeout= [KNL,BOOT]
 			Set timeout for RCU CPU stall warning messages.
 
+	rcutree.jiffies_till_first_fqs= [KNL,BOOT]
+			Set delay from grace-period initialization to
+			first attempt to force quiescent states.
+			Units are jiffies, minimum value is zero,
+			and maximum value is HZ.
+
+	rcutree.jiffies_till_next_fqs= [KNL,BOOT]
+			Set delay between subsequent attempts to force
+			quiescent states.  Units are jiffies, minimum
+			value is one, and maximum value is HZ.
+
 	rcutorture.fqs_duration= [KNL,BOOT]
 			Set duration of force_quiescent_state bursts.
 
@@ -2638,9 +2670,6 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 	smart2=		[HW]
 			Format: <io1>[,<io2>[,...,<io8>]]
 
-	smp-alt-once	[X86-32,SMP] On a hotplug CPU system, only
-			attempt to substitute SMP alternatives once at boot.
-
 	smsc-ircc2.nopnp	[HW] Don't use PNP to discover SMC devices
 	smsc-ircc2.ircc_cfg=	[HW] Device configuration I/O port
 	smsc-ircc2.ircc_sir=	[HW] SIR base I/O port
diff --git a/Documentation/kobject.txt b/Documentation/kobject.txt
index 49578cf..c5182bb 100644
--- a/Documentation/kobject.txt
+++ b/Documentation/kobject.txt
@@ -284,9 +284,11 @@ instead, it is associated with the ktype. So let us introduce struct
 kobj_type:
 
     struct kobj_type {
-	    void (*release)(struct kobject *);
+	    void (*release)(struct kobject *kobj);
 	    const struct sysfs_ops *sysfs_ops;
-	    struct attribute	**default_attrs;
+	    struct attribute **default_attrs;
+	    const struct kobj_ns_type_operations *(*child_ns_type)(struct kobject *kobj);
+	    const void *(*namespace)(struct kobject *kobj);
     };
 
 This structure is used to describe a particular type of kobject (or, more
diff --git a/Documentation/leds/leds-lp5523.txt b/Documentation/leds/leds-lp5523.txt
index fad2feb..c2743f5 100644
--- a/Documentation/leds/leds-lp5523.txt
+++ b/Documentation/leds/leds-lp5523.txt
@@ -10,8 +10,22 @@ Contact: Samu Onkalo (samu.p.onkalo-at-nokia.com)
 Description
 -----------
 LP5523 can drive up to 9 channels. Leds can be controlled directly via
-the led class control interface. Channels have generic names:
-lp5523:channelx where x is 0...8
+the led class control interface.
+The name of each channel is configurable in the platform data - name and label.
+There are three options to make the channel name.
+
+a) Define the 'name' in the platform data
+To make specific channel name, then use 'name' platform data.
+/sys/class/leds/R1               (name: 'R1')
+/sys/class/leds/B1               (name: 'B1')
+
+b) Use the 'label' with no 'name' field
+For one device name with channel number, then use 'label'.
+/sys/class/leds/RGB:channelN     (label: 'RGB', N: 0 ~ 8)
+
+c) Default
+If both fields are NULL, 'lp5523' is used by default.
+/sys/class/leds/lp5523:channelN  (N: 0 ~ 8)
 
 The chip provides 3 engines. Each engine can control channels without
 interaction from the main CPU. Details of the micro engine code can be found
@@ -46,12 +60,13 @@ Note - chan_nr can have values between 0 and 8.
 
 static struct lp5523_led_config lp5523_led_config[] = {
         {
+		.name		= "D1",
                 .chan_nr        = 0,
                 .led_current    = 50,
 		.max_current    = 130,
         },
 ...
-        }, {
+        {
                 .chan_nr        = 8,
                 .led_current    = 50,
 		.max_current    = 130,
diff --git a/Documentation/memory.txt b/Documentation/memory.txt
deleted file mode 100644
index 802efe5..0000000
--- a/Documentation/memory.txt
+++ /dev/null
@@ -1,33 +0,0 @@
-There are several classic problems related to memory on Linux
-systems.
-
-	1) There are some motherboards that will not cache above
-	   a certain quantity of memory.  If you have one of these
-	   motherboards, your system will be SLOWER, not faster
-	   as you add more memory.  Consider exchanging your 
-           motherboard.
-
-All of these problems can be addressed with the "mem=XXXM" boot option
-(where XXX is the size of RAM to use in megabytes).  
-It can also tell Linux to use less memory than is actually installed.
-If you use "mem=" on a machine with PCI, consider using "memmap=" to avoid
-physical address space collisions.
-
-See the documentation of your boot loader (LILO, grub, loadlin, etc.) about
-how to pass options to the kernel.
-
-There are other memory problems which Linux cannot deal with.  Random
-corruption of memory is usually a sign of serious hardware trouble.
-Try:
-
-	* Reducing memory settings in the BIOS to the most conservative 
-          timings.
-
-	* Adding a cooling fan.
-
-	* Not overclocking your CPU.
-
-	* Having the memory tested in a memory tester or exchanged
-	  with the vendor. Consider testing it with memtest86 yourself.
-	
-	* Exchanging your CPU, cache, or motherboard for one that works.
diff --git a/Documentation/misc-devices/lis3lv02d b/Documentation/misc-devices/lis3lv02d
index f1a4ec8..af815b9 100644
--- a/Documentation/misc-devices/lis3lv02d
+++ b/Documentation/misc-devices/lis3lv02d
@@ -4,7 +4,8 @@ Kernel driver lis3lv02d
 Supported chips:
 
   * STMicroelectronics LIS3LV02DL, LIS3LV02DQ (12 bits precision)
-  * STMicroelectronics LIS302DL, LIS3L02DQ, LIS331DL (8 bits)
+  * STMicroelectronics LIS302DL, LIS3L02DQ, LIS331DL (8 bits) and
+    LIS331DLH (16 bits)
 
 Authors:
         Yan Burman <burman.yan@gmail.com>
diff --git a/Documentation/networking/batman-adv.txt b/Documentation/networking/batman-adv.txt
index 8f3ae4a..a173d2a 100644
--- a/Documentation/networking/batman-adv.txt
+++ b/Documentation/networking/batman-adv.txt
@@ -75,9 +75,10 @@ folder:
 
 There is a special folder for debugging information:
 
-#  ls /sys/kernel/debug/batman_adv/bat0/
-# bla_claim_table    log                socket             transtable_local
-# gateways           originators        transtable_global  vis_data
+# ls /sys/kernel/debug/batman_adv/bat0/
+# bla_backbone_table  log                 transtable_global
+# bla_claim_table     originators         transtable_local
+# gateways            socket              vis_data
 
 Some of the files contain all sort of status information  regard-
 ing  the  mesh  network.  For  example, you can view the table of
diff --git a/Documentation/networking/bonding.txt b/Documentation/networking/bonding.txt
index 6b1c711..10a015c 100644
--- a/Documentation/networking/bonding.txt
+++ b/Documentation/networking/bonding.txt
@@ -752,12 +752,22 @@ xmit_hash_policy
 		protocol information to generate the hash.
 
 		Uses XOR of hardware MAC addresses and IP addresses to
-		generate the hash.  The formula is
+		generate the hash.  The IPv4 formula is
 
 		(((source IP XOR dest IP) AND 0xffff) XOR
 			( source MAC XOR destination MAC ))
 				modulo slave count
 
+		The IPv6 formula is
+
+		hash = (source ip quad 2 XOR dest IP quad 2) XOR
+		       (source ip quad 3 XOR dest IP quad 3) XOR
+		       (source ip quad 4 XOR dest IP quad 4)
+
+		(((hash >> 24) XOR (hash >> 16) XOR (hash >> 8) XOR hash)
+			XOR (source MAC XOR destination MAC))
+				modulo slave count
+
 		This algorithm will place all traffic to a particular
 		network peer on the same slave.  For non-IP traffic,
 		the formula is the same as for the layer2 transmit
@@ -778,19 +788,29 @@ xmit_hash_policy
 		slaves, although a single connection will not span
 		multiple slaves.
 
-		The formula for unfragmented TCP and UDP packets is
+		The formula for unfragmented IPv4 TCP and UDP packets is
 
 		((source port XOR dest port) XOR
 			 ((source IP XOR dest IP) AND 0xffff)
 				modulo slave count
 
-		For fragmented TCP or UDP packets and all other IP
-		protocol traffic, the source and destination port
+		The formula for unfragmented IPv6 TCP and UDP packets is
+
+		hash = (source port XOR dest port) XOR
+		       ((source ip quad 2 XOR dest IP quad 2) XOR
+			(source ip quad 3 XOR dest IP quad 3) XOR
+			(source ip quad 4 XOR dest IP quad 4))
+
+		((hash >> 24) XOR (hash >> 16) XOR (hash >> 8) XOR hash)
+			modulo slave count
+
+		For fragmented TCP or UDP packets and all other IPv4 and
+		IPv6 protocol traffic, the source and destination port
 		information is omitted.  For non-IP traffic, the
 		formula is the same as for the layer2 transmit hash
 		policy.
 
-		This policy is intended to mimic the behavior of
+		The IPv4 policy is intended to mimic the behavior of
 		certain switches, notably Cisco switches with PFC2 as
 		well as some Foundry and IBM products.
 
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index ca447b3..c7fc107 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -439,7 +439,9 @@ tcp_stdurg - BOOLEAN
 tcp_synack_retries - INTEGER
 	Number of times SYNACKs for a passive TCP connection attempt will
 	be retransmitted. Should not be higher than 255. Default value
-	is 5, which corresponds to ~180seconds.
+	is 5, which corresponds to 31seconds till the last retransmission
+	with the current initial RTO of 1second. With this the final timeout
+	for a passive TCP connection will happen after 63seconds.
 
 tcp_syncookies - BOOLEAN
 	Only valid when the kernel was compiled with CONFIG_SYNCOOKIES
@@ -465,20 +467,37 @@ tcp_syncookies - BOOLEAN
 tcp_fastopen - INTEGER
 	Enable TCP Fast Open feature (draft-ietf-tcpm-fastopen) to send data
 	in the opening SYN packet. To use this feature, the client application
-	must not use connect(). Instead, it should use sendmsg() or sendto()
-	with MSG_FASTOPEN flag which performs a TCP handshake automatically.
-
-	The values (bitmap) are:
-	1: Enables sending data in the opening SYN on the client
-	5: Enables sending data in the opening SYN on the client regardless
-	   of cookie availability.
+	must use sendmsg() or sendto() with MSG_FASTOPEN flag rather than
+	connect() to perform a TCP handshake automatically.
+
+	The values (bitmap) are
+	1: Enables sending data in the opening SYN on the client.
+	2: Enables TCP Fast Open on the server side, i.e., allowing data in
+	   a SYN packet to be accepted and passed to the application before
+	   3-way hand shake finishes.
+	4: Send data in the opening SYN regardless of cookie availability and
+	   without a cookie option.
+	0x100: Accept SYN data w/o validating the cookie.
+	0x200: Accept data-in-SYN w/o any cookie option present.
+	0x400/0x800: Enable Fast Open on all listeners regardless of the
+	   TCP_FASTOPEN socket option. The two different flags designate two
+	   different ways of setting max_qlen without the TCP_FASTOPEN socket
+	   option.
 
 	Default: 0
 
+	Note that the client & server side Fast Open flags (1 and 2
+	respectively) must be also enabled before the rest of flags can take
+	effect.
+
+	See include/net/tcp.h and the code for more details.
+
 tcp_syn_retries - INTEGER
 	Number of times initial SYNs for an active TCP connection attempt
 	will be retransmitted. Should not be higher than 255. Default value
-	is 5, which corresponds to ~180seconds.
+	is 6, which corresponds to 63seconds till the last restransmission
+	with the current initial RTO of 1second. With this the final timeout
+	for an active TCP connection attempt will happen after 127seconds.
 
 tcp_timestamps - BOOLEAN
 	Enable timestamps as defined in RFC1323.
diff --git a/Documentation/networking/stmmac.txt b/Documentation/networking/stmmac.txt
index c676b9c..ef9ee71 100644
--- a/Documentation/networking/stmmac.txt
+++ b/Documentation/networking/stmmac.txt
@@ -173,7 +173,6 @@ Where:
 For MDIO bus The we have:
 
  struct stmmac_mdio_bus_data {
-	int bus_id;
 	int (*phy_reset)(void *priv);
 	unsigned int phy_mask;
 	int *irqs;
@@ -181,7 +180,6 @@ For MDIO bus The we have:
  };
 
 Where:
- o bus_id: bus identifier;
  o phy_reset: hook to reset the phy device attached to the bus.
  o phy_mask: phy mask passed when register the MDIO bus within the driver.
  o irqs: list of IRQs, one per PHY.
@@ -230,9 +228,6 @@ there are two MAC cores: one MAC is for MDIO Bus/PHY emulation
 with fixed_link support.
 
 static struct stmmac_mdio_bus_data stmmac1_mdio_bus = {
-	.bus_id = 1,
-		|
-		|-> phy device on the bus_id 1
 	.phy_reset = phy_reset;
 		|
 		|-> function to provide the phy_reset on this board
diff --git a/Documentation/pinctrl.txt b/Documentation/pinctrl.txt
index 1479aca..3b4ee53 100644
--- a/Documentation/pinctrl.txt
+++ b/Documentation/pinctrl.txt
@@ -289,6 +289,11 @@ Interaction with the GPIO subsystem
 The GPIO drivers may want to perform operations of various types on the same
 physical pins that are also registered as pin controller pins.
 
+First and foremost, the two subsystems can be used as completely orthogonal,
+see the section named "pin control requests from drivers" and
+"drivers needing both pin control and GPIOs" below for details. But in some
+situations a cross-subsystem mapping between pins and GPIOs is needed.
+
 Since the pin controller subsystem have its pinspace local to the pin
 controller we need a mapping so that the pin control subsystem can figure out
 which pin controller handles control of a certain GPIO pin. Since a single
@@ -359,6 +364,7 @@ will get an pin number into its handled number range. Further it is also passed
 the range ID value, so that the pin controller knows which range it should
 deal with.
 
+
 PINMUX interfaces
 =================
 
@@ -960,8 +966,8 @@ all get selected, and they all get enabled and disable simultaneously by the
 pinmux core.
 
 
-Pinmux requests from drivers
-============================
+Pin control requests from drivers
+=================================
 
 Generally it is discouraged to let individual drivers get and enable pin
 control. So if possible, handle the pin control in platform code or some other
@@ -969,6 +975,11 @@ place where you have access to all the affected struct device * pointers. In
 some cases where a driver needs to e.g. switch between different mux mappings
 at runtime this is not possible.
 
+A typical case is if a driver needs to switch bias of pins from normal
+operation and going to sleep, moving from the PINCTRL_STATE_DEFAULT to
+PINCTRL_STATE_SLEEP at runtime, re-biasing or even re-muxing pins to save
+current in sleep mode.
+
 A driver may request a certain control state to be activated, usually just the
 default state like this:
 
@@ -1058,6 +1069,51 @@ registered. Thus make sure that the error path in your driver gracefully
 cleans up and is ready to retry the probing later in the startup process.
 
 
+Drivers needing both pin control and GPIOs
+==========================================
+
+Again, it is discouraged to let drivers lookup and select pin control states
+themselves, but again sometimes this is unavoidable.
+
+So say that your driver is fetching its resources like this:
+
+#include <linux/pinctrl/consumer.h>
+#include <linux/gpio.h>
+
+struct pinctrl *pinctrl;
+int gpio;
+
+pinctrl = devm_pinctrl_get_select_default(&dev);
+gpio = devm_gpio_request(&dev, 14, "foo");
+
+Here we first request a certain pin state and then request GPIO 14 to be
+used. If you're using the subsystems orthogonally like this, you should
+nominally always get your pinctrl handle and select the desired pinctrl
+state BEFORE requesting the GPIO. This is a semantic convention to avoid
+situations that can be electrically unpleasant, you will certainly want to
+mux in and bias pins in a certain way before the GPIO subsystems starts to
+deal with them.
+
+The above can be hidden: using pinctrl hogs, the pin control driver may be
+setting up the config and muxing for the pins when it is probing,
+nevertheless orthogonal to the GPIO subsystem.
+
+But there are also situations where it makes sense for the GPIO subsystem
+to communicate directly with with the pinctrl subsystem, using the latter
+as a back-end. This is when the GPIO driver may call out to the functions
+described in the section "Pin control interaction with the GPIO subsystem"
+above. This only involves per-pin multiplexing, and will be completely
+hidden behind the gpio_*() function namespace. In this case, the driver
+need not interact with the pin control subsystem at all.
+
+If a pin control driver and a GPIO driver is dealing with the same pins
+and the use cases involve multiplexing, you MUST implement the pin controller
+as a back-end for the GPIO driver like this, unless your hardware design
+is such that the GPIO controller can override the pin controller's
+multiplexing state through hardware without the need to interact with the
+pin control system.
+
+
 System pin control hogging
 ==========================
 
diff --git a/Documentation/power/power_supply_class.txt b/Documentation/power/power_supply_class.txt
index 2f0ddc1..9c647bd 100644
--- a/Documentation/power/power_supply_class.txt
+++ b/Documentation/power/power_supply_class.txt
@@ -81,6 +81,9 @@ This defines trickle and fast charges.  For batteries that
 are already charged or discharging, 'n/a' can be displayed (or
 'unknown', if the status is not known).
 
+AUTHENTIC - indicates the power supply (battery or charger) connected
+to the platform is authentic(1) or non authentic(0).
+
 HEALTH - represents health of the battery, values corresponds to
 POWER_SUPPLY_HEALTH_*, defined in battery.h.
 
@@ -113,8 +116,12 @@ be negative; there is no empty or full value.  It is only useful for
 relative, time-based measurements.
 
 CONSTANT_CHARGE_CURRENT - constant charge current programmed by charger.
+CONSTANT_CHARGE_CURRENT_MAX - maximum charge current supported by the
+power supply object.
 
 CONSTANT_CHARGE_VOLTAGE - constant charge voltage programmed by charger.
+CONSTANT_CHARGE_VOLTAGE_MAX - maximum charge voltage supported by the
+power supply object.
 
 ENERGY_FULL, ENERGY_EMPTY - same as above but for energy.
 
diff --git a/Documentation/power/swsusp.txt b/Documentation/power/swsusp.txt
index 92341b8..0b4b63e 100644
--- a/Documentation/power/swsusp.txt
+++ b/Documentation/power/swsusp.txt
@@ -53,7 +53,7 @@ before suspend (it is limited to 500 MB by default).
 
 Article about goals and implementation of Software Suspend for Linux
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Author: Gábor Kuti
+Author: Gábor Kuti
 Last revised: 2003-10-20 by Pavel Machek
 
 Idea and goals to achieve
diff --git a/Documentation/printk-formats.txt b/Documentation/printk-formats.txt
index 7561d7e..8ffb274 100644
--- a/Documentation/printk-formats.txt
+++ b/Documentation/printk-formats.txt
@@ -69,6 +69,7 @@ MAC/FDDI addresses:
 	%pMR	05:04:03:02:01:00
 	%pMF	00-01-02-03-04-05
 	%pm	000102030405
+	%pmR	050403020100
 
 	For printing 6-byte MAC/FDDI addresses in hex notation. The 'M' and 'm'
 	specifiers result in a printed address with ('M') or without ('m') byte
diff --git a/Documentation/prio_tree.txt b/Documentation/prio_tree.txt
deleted file mode 100644
index 3aa68f9..0000000
--- a/Documentation/prio_tree.txt
+++ /dev/null
@@ -1,107 +0,0 @@
-The prio_tree.c code indexes vmas using 3 different indexes:
-	* heap_index  = vm_pgoff + vm_size_in_pages : end_vm_pgoff
-	* radix_index = vm_pgoff : start_vm_pgoff
-	* size_index = vm_size_in_pages
-
-A regular radix-priority-search-tree indexes vmas using only heap_index and
-radix_index. The conditions for indexing are:
-	* ->heap_index >= ->left->heap_index &&
-		->heap_index >= ->right->heap_index
-	* if (->heap_index == ->left->heap_index)
-		then ->radix_index < ->left->radix_index;
-	* if (->heap_index == ->right->heap_index)
-		then ->radix_index < ->right->radix_index;
-	* nodes are hashed to left or right subtree using radix_index
-	  similar to a pure binary radix tree.
-
-A regular radix-priority-search-tree helps to store and query
-intervals (vmas). However, a regular radix-priority-search-tree is only
-suitable for storing vmas with different radix indices (vm_pgoff).
-
-Therefore, the prio_tree.c extends the regular radix-priority-search-tree
-to handle many vmas with the same vm_pgoff. Such vmas are handled in
-2 different ways: 1) All vmas with the same radix _and_ heap indices are
-linked using vm_set.list, 2) if there are many vmas with the same radix
-index, but different heap indices and if the regular radix-priority-search
-tree cannot index them all, we build an overflow-sub-tree that indexes such
-vmas using heap and size indices instead of heap and radix indices. For
-example, in the figure below some vmas with vm_pgoff = 0 (zero) are
-indexed by regular radix-priority-search-tree whereas others are pushed
-into an overflow-subtree. Note that all vmas in an overflow-sub-tree have
-the same vm_pgoff (radix_index) and if necessary we build different
-overflow-sub-trees to handle each possible radix_index. For example,
-in figure we have 3 overflow-sub-trees corresponding to radix indices
-0, 2, and 4.
-
-In the final tree the first few (prio_tree_root->index_bits) levels
-are indexed using heap and radix indices whereas the overflow-sub-trees below
-those levels (i.e. levels prio_tree_root->index_bits + 1 and higher) are
-indexed using heap and size indices. In overflow-sub-trees the size_index
-is used for hashing the nodes to appropriate places.
-
-Now, an example prio_tree:
-
-  vmas are represented [radix_index, size_index, heap_index]
-                 i.e., [start_vm_pgoff, vm_size_in_pages, end_vm_pgoff]
-
-level  prio_tree_root->index_bits = 3
------
-												_
-  0			 				[0,7,7]					 |
-  							/     \					 |
-				      ------------------       ------------			 |     Regular
-  				     /					   \			 |  radix priority
-  1		 		[1,6,7]					  [4,3,7]		 |   search tree
-  				/     \					  /     \		 |
-			 -------       -----			    ------       -----		 |  heap-and-radix
-			/		    \			   /		      \		 |      indexed
-  2		    [0,6,6]	 	   [2,5,7]		[5,2,7]		    [6,1,7]	 |
-		    /     \		   /     \		/     \		    /     \	 |
-  3		[0,5,5]	[1,5,6]		[2,4,6]	[3,4,7]	    [4,2,6] [5,1,6]	[6,0,6]	[7,0,7]	 |
-		   /			   /		       /		   		_
-                  /		          /		      /					_
-  4	      [0,4,4]		      [2,3,5]		   [4,1,5]				 |
-  		 /			 /		      /					 |
-  5	     [0,3,3]		     [2,2,4]		  [4,0,4]				 |  Overflow-sub-trees
-  		/			/							 |
-  6	    [0,2,2]		    [2,1,3]							 |    heap-and-size
-  	       /		       /							 |       indexed
-  7	   [0,1,1]		   [2,0,2]							 |
-  	      /											 |
-  8	  [0,0,0]										 |
-  												_
-
-Note that we use prio_tree_root->index_bits to optimize the height
-of the heap-and-radix indexed tree. Since prio_tree_root->index_bits is
-set according to the maximum end_vm_pgoff mapped, we are sure that all
-bits (in vm_pgoff) above prio_tree_root->index_bits are 0 (zero). Therefore,
-we only use the first prio_tree_root->index_bits as radix_index.
-Whenever index_bits is increased in prio_tree_expand, we shuffle the tree
-to make sure that the first prio_tree_root->index_bits levels of the tree
-is indexed properly using heap and radix indices.
-
-We do not optimize the height of overflow-sub-trees using index_bits.
-The reason is: there can be many such overflow-sub-trees and all of
-them have to be suffled whenever the index_bits increases. This may involve
-walking the whole prio_tree in prio_tree_insert->prio_tree_expand code
-path which is not desirable. Hence, we do not optimize the height of the
-heap-and-size indexed overflow-sub-trees using prio_tree->index_bits.
-Instead the overflow sub-trees are indexed using full BITS_PER_LONG bits
-of size_index. This may lead to skewed sub-trees because most of the
-higher significant bits of the size_index are likely to be 0 (zero). In
-the example above, all 3 overflow-sub-trees are skewed. This may marginally
-affect the performance. However, processes rarely map many vmas with the
-same start_vm_pgoff but different end_vm_pgoffs. Therefore, we normally
-do not require overflow-sub-trees to index all vmas.
-
-From the above discussion it is clear that the maximum height of
-a prio_tree can be prio_tree_root->index_bits + BITS_PER_LONG.
-However, in most of the common cases we do not need overflow-sub-trees,
-so the tree height in the common cases will be prio_tree_root->index_bits.
-
-It is fair to mention here that the prio_tree_root->index_bits
-is increased on demand, however, the index_bits is not decreased when
-vmas are removed from the prio_tree. That's tricky to do. Hence, it's
-left as a home work problem.
-
-
diff --git a/Documentation/pwm.txt b/Documentation/pwm.txt
index 554290e..7d2b4c9 100644
--- a/Documentation/pwm.txt
+++ b/Documentation/pwm.txt
@@ -36,7 +36,8 @@ Legacy users can request a PWM device using pwm_request() and free it
 after usage with pwm_free().
 
 New users should use the pwm_get() function and pass to it the consumer
-device or a consumer name. pwm_put() is used to free the PWM device.
+device or a consumer name. pwm_put() is used to free the PWM device. Managed
+variants of these functions, devm_pwm_get() and devm_pwm_put(), also exist.
 
 After being requested a PWM has to be configured using:
 
diff --git a/Documentation/ramoops.txt b/Documentation/ramoops.txt
index 197ad59..69b3cac 100644
--- a/Documentation/ramoops.txt
+++ b/Documentation/ramoops.txt
@@ -102,9 +102,7 @@ related hangs. The functions call chain log is stored in a "ftrace-ramoops"
 file. Here is an example of usage:
 
  # mount -t debugfs debugfs /sys/kernel/debug/
- # cd /sys/kernel/debug/tracing
- # echo function > current_tracer
- # echo 1 > options/func_pstore
+ # echo 1 > /sys/kernel/debug/pstore/record_ftrace
  # reboot -f
  [...]
  # mount -t pstore pstore /mnt/
diff --git a/Documentation/rbtree.txt b/Documentation/rbtree.txt
index 8d32d85..61b6c48 100644
--- a/Documentation/rbtree.txt
+++ b/Documentation/rbtree.txt
@@ -193,24 +193,55 @@ Example:
 Support for Augmented rbtrees
 -----------------------------
 
-Augmented rbtree is an rbtree with "some" additional data stored in each node.
-This data can be used to augment some new functionality to rbtree.
-Augmented rbtree is an optional feature built on top of basic rbtree
-infrastructure. An rbtree user who wants this feature will have to call the
-augmentation functions with the user provided augmentation callback
-when inserting and erasing nodes.
-
-On insertion, the user must call rb_augment_insert() once the new node is in
-place. This will cause the augmentation function callback to be called for
-each node between the new node and the root which has been affected by the
-insertion.
-
-When erasing a node, the user must call rb_augment_erase_begin() first to
-retrieve the deepest node on the rebalance path. Then, after erasing the
-original node, the user must call rb_augment_erase_end() with the deepest
-node found earlier. This will cause the augmentation function to be called
-for each affected node between the deepest node and the root.
-
+Augmented rbtree is an rbtree with "some" additional data stored in
+each node, where the additional data for node N must be a function of
+the contents of all nodes in the subtree rooted at N. This data can
+be used to augment some new functionality to rbtree. Augmented rbtree
+is an optional feature built on top of basic rbtree infrastructure.
+An rbtree user who wants this feature will have to call the augmentation
+functions with the user provided augmentation callback when inserting
+and erasing nodes.
+
+C files implementing augmented rbtree manipulation must include
+<linux/rbtree_augmented.h> instead of <linus/rbtree.h>. Note that
+linux/rbtree_augmented.h exposes some rbtree implementations details
+you are not expected to rely on; please stick to the documented APIs
+there and do not include <linux/rbtree_augmented.h> from header files
+either so as to minimize chances of your users accidentally relying on
+such implementation details.
+
+On insertion, the user must update the augmented information on the path
+leading to the inserted node, then call rb_link_node() as usual and
+rb_augment_inserted() instead of the usual rb_insert_color() call.
+If rb_augment_inserted() rebalances the rbtree, it will callback into
+a user provided function to update the augmented information on the
+affected subtrees.
+
+When erasing a node, the user must call rb_erase_augmented() instead of
+rb_erase(). rb_erase_augmented() calls back into user provided functions
+to updated the augmented information on affected subtrees.
+
+In both cases, the callbacks are provided through struct rb_augment_callbacks.
+3 callbacks must be defined:
+
+- A propagation callback, which updates the augmented value for a given
+  node and its ancestors, up to a given stop point (or NULL to update
+  all the way to the root).
+
+- A copy callback, which copies the augmented value for a given subtree
+  to a newly assigned subtree root.
+
+- A tree rotation callback, which copies the augmented value for a given
+  subtree to a newly assigned subtree root AND recomputes the augmented
+  information for the former subtree root.
+
+The compiled code for rb_erase_augmented() may inline the propagation and
+copy callbacks, which results in a large function, so each augmented rbtree
+user should have a single rb_erase_augmented() call site in order to limit
+compiled code size.
+
+
+Sample usage:
 
 Interval tree is an example of augmented rb tree. Reference -
 "Introduction to Algorithms" by Cormen, Leiserson, Rivest and Stein.
@@ -230,26 +261,132 @@ and its immediate children. And this will be used in O(log n) lookup
 for lowest match (lowest start address among all possible matches)
 with something like:
 
-find_lowest_match(lo, hi, node)
+struct interval_tree_node *
+interval_tree_first_match(struct rb_root *root,
+			  unsigned long start, unsigned long last)
 {
-	lowest_match = NULL;
-	while (node) {
-		if (max_hi(node->left) > lo) {
-			// Lowest overlap if any must be on left side
-			node = node->left;
-		} else if (overlap(lo, hi, node)) {
-			lowest_match = node;
-			break;
-		} else if (lo > node->lo) {
-			// Lowest overlap if any must be on right side
-			node = node->right;
-		} else {
-			break;
+	struct interval_tree_node *node;
+
+	if (!root->rb_node)
+		return NULL;
+	node = rb_entry(root->rb_node, struct interval_tree_node, rb);
+
+	while (true) {
+		if (node->rb.rb_left) {
+			struct interval_tree_node *left =
+				rb_entry(node->rb.rb_left,
+					 struct interval_tree_node, rb);
+			if (left->__subtree_last >= start) {
+				/*
+				 * Some nodes in left subtree satisfy Cond2.
+				 * Iterate to find the leftmost such node N.
+				 * If it also satisfies Cond1, that's the match
+				 * we are looking for. Otherwise, there is no
+				 * matching interval as nodes to the right of N
+				 * can't satisfy Cond1 either.
+				 */
+				node = left;
+				continue;
+			}
 		}
+		if (node->start <= last) {		/* Cond1 */
+			if (node->last >= start)	/* Cond2 */
+				return node;	/* node is leftmost match */
+			if (node->rb.rb_right) {
+				node = rb_entry(node->rb.rb_right,
+					struct interval_tree_node, rb);
+				if (node->__subtree_last >= start)
+					continue;
+			}
+		}
+		return NULL;	/* No match */
+	}
+}
+
+Insertion/removal are defined using the following augmented callbacks:
+
+static inline unsigned long
+compute_subtree_last(struct interval_tree_node *node)
+{
+	unsigned long max = node->last, subtree_last;
+	if (node->rb.rb_left) {
+		subtree_last = rb_entry(node->rb.rb_left,
+			struct interval_tree_node, rb)->__subtree_last;
+		if (max < subtree_last)
+			max = subtree_last;
+	}
+	if (node->rb.rb_right) {
+		subtree_last = rb_entry(node->rb.rb_right,
+			struct interval_tree_node, rb)->__subtree_last;
+		if (max < subtree_last)
+			max = subtree_last;
+	}
+	return max;
+}
+
+static void augment_propagate(struct rb_node *rb, struct rb_node *stop)
+{
+	while (rb != stop) {
+		struct interval_tree_node *node =
+			rb_entry(rb, struct interval_tree_node, rb);
+		unsigned long subtree_last = compute_subtree_last(node);
+		if (node->__subtree_last == subtree_last)
+			break;
+		node->__subtree_last = subtree_last;
+		rb = rb_parent(&node->rb);
 	}
-	return lowest_match;
 }
 
-Finding exact match will be to first find lowest match and then to follow
-successor nodes looking for exact match, until the start of a node is beyond
-the hi value we are looking for.
+static void augment_copy(struct rb_node *rb_old, struct rb_node *rb_new)
+{
+	struct interval_tree_node *old =
+		rb_entry(rb_old, struct interval_tree_node, rb);
+	struct interval_tree_node *new =
+		rb_entry(rb_new, struct interval_tree_node, rb);
+
+	new->__subtree_last = old->__subtree_last;
+}
+
+static void augment_rotate(struct rb_node *rb_old, struct rb_node *rb_new)
+{
+	struct interval_tree_node *old =
+		rb_entry(rb_old, struct interval_tree_node, rb);
+	struct interval_tree_node *new =
+		rb_entry(rb_new, struct interval_tree_node, rb);
+
+	new->__subtree_last = old->__subtree_last;
+	old->__subtree_last = compute_subtree_last(old);
+}
+
+static const struct rb_augment_callbacks augment_callbacks = {
+	augment_propagate, augment_copy, augment_rotate
+};
+
+void interval_tree_insert(struct interval_tree_node *node,
+			  struct rb_root *root)
+{
+	struct rb_node **link = &root->rb_node, *rb_parent = NULL;
+	unsigned long start = node->start, last = node->last;
+	struct interval_tree_node *parent;
+
+	while (*link) {
+		rb_parent = *link;
+		parent = rb_entry(rb_parent, struct interval_tree_node, rb);
+		if (parent->__subtree_last < last)
+			parent->__subtree_last = last;
+		if (start < parent->start)
+			link = &parent->rb.rb_left;
+		else
+			link = &parent->rb.rb_right;
+	}
+
+	node->__subtree_last = last;
+	rb_link_node(&node->rb, rb_parent, link);
+	rb_insert_augmented(&node->rb, root, &augment_callbacks);
+}
+
+void interval_tree_remove(struct interval_tree_node *node,
+			  struct rb_root *root)
+{
+	rb_erase_augmented(&node->rb, root, &augment_callbacks);
+}
diff --git a/Documentation/remoteproc.txt b/Documentation/remoteproc.txt
index 23a09b8..e6469fd 100644
--- a/Documentation/remoteproc.txt
+++ b/Documentation/remoteproc.txt
@@ -129,6 +129,13 @@ int dummy_rproc_example(struct rproc *my_rproc)
 
       Returns 0 on success and -EINVAL if @rproc isn't valid.
 
+  void rproc_report_crash(struct rproc *rproc, enum rproc_crash_type type)
+    - Report a crash in a remoteproc
+      This function must be called every time a crash is detected by the
+      platform specific rproc implementation. This should not be called from a
+      non-remoteproc driver. This function can be called from atomic/interrupt
+      context.
+
 5. Implementation callbacks
 
 These callbacks should be provided by platform-specific remoteproc
diff --git a/Documentation/rtc.txt b/Documentation/rtc.txt
index 2501604..32aa400 100644
--- a/Documentation/rtc.txt
+++ b/Documentation/rtc.txt
@@ -119,8 +119,9 @@ three different userspace interfaces:
     *	/sys/class/rtc/rtcN ... sysfs attributes support readonly
 	access to some RTC attributes.
 
-    *	/proc/driver/rtc ... the first RTC (rtc0) may expose itself
-	using a procfs interface.  More information is (currently) shown
+    *	/proc/driver/rtc ... the system clock RTC may expose itself
+	using a procfs interface. If there is no RTC for the system clock,
+	rtc0 is used by default. More information is (currently) shown
 	here than through sysfs.
 
 The RTC Class framework supports a wide variety of RTCs, ranging from those
diff --git a/Documentation/scheduler/sched-arch.txt b/Documentation/scheduler/sched-arch.txt
index 28aa107..b1b8587 100644
--- a/Documentation/scheduler/sched-arch.txt
+++ b/Documentation/scheduler/sched-arch.txt
@@ -17,16 +17,6 @@ you must `#define __ARCH_WANT_UNLOCKED_CTXSW` in a header file
 Unlocked context switches introduce only a very minor performance
 penalty to the core scheduler implementation in the CONFIG_SMP case.
 
-2. Interrupt status
-By default, the switch_to arch function is called with interrupts
-disabled. Interrupts may be enabled over the call if it is likely to
-introduce a significant interrupt latency by adding the line
-`#define __ARCH_WANT_INTERRUPTS_ON_CTXSW` in the same place as for
-unlocked context switches. This define also implies
-`__ARCH_WANT_UNLOCKED_CTXSW`. See arch/arm/include/asm/system.h for an
-example.
-
-
 CPU idle
 ========
 Your cpu_idle routines need to obey the following rules:
diff --git a/Documentation/scsi/ChangeLog.megaraid_sas b/Documentation/scsi/ChangeLog.megaraid_sas
index 80441ab..3a30794 100644
--- a/Documentation/scsi/ChangeLog.megaraid_sas
+++ b/Documentation/scsi/ChangeLog.megaraid_sas
@@ -1,3 +1,13 @@
+Release Date    : Tue. Jun 17, 2012 17:00:00 PST 2012 -
+			(emaild-id:megaraidlinux@lsi.com)
+			Adam Radford/Kashyap Desai
+Current Version : 00.00.06.18-rc1
+Old Version     : 00.00.06.15-rc1
+    1. Fix Copyright dates.
+    2. Add throttlequeuedepth module parameter.
+    3. Add resetwaittime module parameter.
+    4. Move poll_aen_lock initializer.
+-------------------------------------------------------------------------------
 Release Date    : Mon. Mar 19, 2012 17:00:00 PST 2012 -
 			(emaild-id:megaraidlinux@lsi.com)
 			Adam Radford
diff --git a/Documentation/scsi/LICENSE.qla2xxx b/Documentation/scsi/LICENSE.qla2xxx
index ce0fdf3..27a91cf 100644
--- a/Documentation/scsi/LICENSE.qla2xxx
+++ b/Documentation/scsi/LICENSE.qla2xxx
@@ -1,4 +1,4 @@
-Copyright (c) 2003-2011 QLogic Corporation
+Copyright (c) 2003-2012 QLogic Corporation
 QLogic Linux FC-FCoE Driver
 
 This program includes a device driver for Linux 3.x.
diff --git a/Documentation/scsi/LICENSE.qla4xxx b/Documentation/scsi/LICENSE.qla4xxx
index ab89959..78c169f 100644
--- a/Documentation/scsi/LICENSE.qla4xxx
+++ b/Documentation/scsi/LICENSE.qla4xxx
@@ -1,4 +1,4 @@
-Copyright (c) 2003-2011 QLogic Corporation
+Copyright (c) 2003-2012 QLogic Corporation
 QLogic Linux iSCSI Driver
 
 This program includes a device driver for Linux 3.x.
diff --git a/Documentation/scsi/st.txt b/Documentation/scsi/st.txt
index 685bf35..f346abb 100644
--- a/Documentation/scsi/st.txt
+++ b/Documentation/scsi/st.txt
@@ -112,10 +112,8 @@ attempted).
 
 MINOR NUMBERS
 
-The tape driver currently supports 128 drives by default. This number
-can be increased by editing st.h and recompiling the driver if
-necessary. The upper limit is 2^17 drives if 4 modes for each drive
-are used.
+The tape driver currently supports up to 2^17 drives if 4 modes for
+each drive are used.
 
 The minor numbers consist of the following bit fields:
 
diff --git a/Documentation/security/Smack.txt b/Documentation/security/Smack.txt
index a416479..e68536d 100644
--- a/Documentation/security/Smack.txt
+++ b/Documentation/security/Smack.txt
@@ -194,6 +194,9 @@ onlycap
 	these capabilities are effective at for processes with any
 	label. The value is set by writing the desired label to the
 	file or cleared by writing "-" to the file.
+revoke-subject
+	Writing a Smack label here sets the access to '-' for all access
+	rules with that subject label.
 
 You can add access rules in /etc/smack/accesses. They take the form:
 
diff --git a/Documentation/serial/00-INDEX b/Documentation/serial/00-INDEX
index e09468a..f7b0c7d 100644
--- a/Documentation/serial/00-INDEX
+++ b/Documentation/serial/00-INDEX
@@ -2,8 +2,6 @@
 	- this file.
 README.cycladesZ
 	- info on Cyclades-Z firmware loading.
-computone.txt
-	- info on Computone Intelliport II/Plus Multiport Serial Driver.
 digiepca.txt
 	- info on Digi Intl. {PC,PCI,EISA}Xx and Xem series cards.
 hayes-esp.txt
diff --git a/Documentation/serial/computone.txt b/Documentation/serial/computone.txt
deleted file mode 100644
index a6a1158..0000000
--- a/Documentation/serial/computone.txt
+++ /dev/null
@@ -1,520 +0,0 @@
-NOTE: This is an unmaintained driver.  It is not guaranteed to work due to
-changes made in the tty layer in 2.6.  If you wish to take over maintenance of
-this driver, contact Michael Warfield <mhw@wittsend.com>.
-
-Changelog:
-----------
-11-01-2001:	Original Document
-
-10-29-2004:	Minor misspelling & format fix, update status of driver.
-		James Nelson <james4765@gmail.com>
-
-Computone Intelliport II/Plus Multiport Serial Driver
------------------------------------------------------
-
-Release Notes For Linux Kernel 2.2 and higher.
-These notes are for the drivers which have already been integrated into the
-kernel and have been tested on Linux kernels 2.0, 2.2, 2.3, and 2.4.
-
-Version: 1.2.14
-Date: 11/01/2001
-Historical Author: Andrew Manison <amanison@america.net>
-Primary Author: Doug McNash
-
-This file assumes that you are using the Computone drivers which are
-integrated into the kernel sources.  For updating the drivers or installing
-drivers into kernels which do not already have Computone drivers, please
-refer to the instructions in the README.computone file in the driver patch.
-
-
-1. INTRODUCTION
-
-This driver supports the entire family of Intelliport II/Plus controllers
-with the exception of the MicroChannel controllers.  It does not support
-products previous to the Intelliport II.
-
-This driver was developed on the v2.0.x Linux tree and has been tested up
-to v2.4.14; it will probably not work with earlier v1.X kernels,.
-
-
-2. QUICK INSTALLATION
-
-Hardware - If you have an ISA card, find a free interrupt and io port. 
-		   List those in use with `cat /proc/interrupts` and 
-		   `cat /proc/ioports`.  Set the card dip switches to a free 
-		   address.  You may need to configure your BIOS to reserve an
-		   irq for an ISA card.  PCI and EISA parameters are set
-		   automagically.  Insert card into computer with the power off 
-		   before or after drivers installation.
-
-	Note the hardware address from the Computone ISA cards installed into
-		the system.  These are required for editing ip2.c or editing
-		/etc/modprobe.d/*.conf, or for specification on the modprobe
-		command line.
-
-	Note that the /etc/modules.conf should be used for older (pre-2.6)
-		kernels.
-
-Software -
-
-Module installation:
-
-a) Determine free irq/address to use if any (configure BIOS if need be)
-b) Run "make config" or "make menuconfig" or "make xconfig"
-   Select (m) module for CONFIG_COMPUTONE under character
-   devices.  CONFIG_PCI and CONFIG_MODULES also may need to be set.
-c) Set address on ISA cards then:
-   edit /usr/src/linux/drivers/char/ip2.c if needed 
-	or
-   edit config file in  /etc/modprobe.d/ if needed (module).
-	or both to match this setting.
-d) Run "make modules"
-e) Run "make modules_install"
-f) Run "/sbin/depmod -a"
-g) install driver using `modprobe ip2 <options>` (options listed below)
-h) run ip2mkdev (either the script below or the binary version)
-
-
-Kernel installation:
-
-a) Determine free irq/address to use if any (configure BIOS if need be)
-b) Run "make config" or "make menuconfig" or "make xconfig"
-   Select (y) kernel for CONFIG_COMPUTONE under character
-   devices.  CONFIG_PCI may need to be set if you have PCI bus.
-c) Set address on ISA cards then:
-	   edit /usr/src/linux/drivers/char/ip2.c  
-           (Optional - may be specified on kernel command line now)
-d) Run "make zImage" or whatever target you prefer.
-e) mv /usr/src/linux/arch/x86/boot/zImage to /boot.
-f) Add new config for this kernel into /etc/lilo.conf, run "lilo"
-	or copy to a floppy disk and boot from that floppy disk.
-g) Reboot using this kernel
-h) run ip2mkdev (either the script below or the binary version)
-
-Kernel command line options:
-
-When compiling the driver into the kernel, io and irq may be
-compiled into the driver by editing ip2.c and setting the values for
-io and irq in the appropriate array.  An alternative is to specify
-a command line parameter to the kernel at boot up.
-
-        ip2=io0,irq0,io1,irq1,io2,irq2,io3,irq3
-
-Note that this order is very different from the specifications for the
-modload parameters which have separate IRQ and IO specifiers.
-
-The io port also selects PCI (1) and EISA (2) boards.
-
-        io=0    No board
-        io=1    PCI board
-        io=2    EISA board
-        else    ISA board io address
-
-You only need to specify the boards which are present.
-
-        Examples:
-
-                2 PCI boards:
-
-                        ip2=1,0,1,0
-
-                1 ISA board at 0x310 irq 5:
-
-                        ip2=0x310,5
-
-This can be added to and "append" option in lilo.conf similar to this:
-
-        append="ip2=1,0,1,0"
-
-
-3. INSTALLATION
-
-Previously, the driver sources were packaged with a set of patch files
-to update the character drivers' makefile and configuration file, and other 
-kernel source files. A build script (ip2build) was included which applies 
-the patches if needed, and build any utilities needed.
-What you receive may be a single patch file in conventional kernel
-patch format build script. That form can also be applied by
-running patch -p1 < ThePatchFile.  Otherwise run ip2build.
- 
-The driver can be installed as a module (recommended) or built into the 
-kernel. This is selected as for other drivers through the `make config`
-command from the root of the Linux source tree. If the driver is built 
-into the kernel you will need to edit the file ip2.c to match the boards 
-you are installing. See that file for instructions. If the driver is 
-installed as a module the configuration can also be specified on the
-modprobe command line as follows:
-
-	modprobe ip2 irq=irq1,irq2,irq3,irq4 io=addr1,addr2,addr3,addr4
-
-where irqnum is one of the valid Intelliport II interrupts (3,4,5,7,10,11,
-12,15) and addr1-4 are the base addresses for up to four controllers. If 
-the irqs are not specified the driver uses the default in ip2.c (which 
-selects polled mode). If no base addresses are specified the defaults in 
-ip2.c are used. If you are autoloading the driver module with kerneld or
-kmod the base addresses and interrupt number must also be set in ip2.c
-and recompile or just insert and options line in /etc/modprobe.d/*.conf or both.
-The options line is equivalent to the command line and takes precedence over
-what is in ip2.c. 
-
-config sample to put /etc/modprobe.d/*.conf:
-	options ip2 io=1,0x328 irq=1,10
-	alias char-major-71 ip2
-	alias char-major-72 ip2
-	alias char-major-73 ip2
-
-The equivalent in ip2.c:
-
-static int io[IP2_MAX_BOARDS]= { 1, 0x328, 0, 0 };
-static int irq[IP2_MAX_BOARDS] = { 1, 10, -1, -1 }; 
-
-The equivalent for the kernel command line (in lilo.conf):
-
-        append="ip2=1,1,0x328,10"
-
-
-Note:	Both io and irq should be updated to reflect YOUR system.  An "io"
-	address of 1 or 2 indicates a PCI or EISA card in the board table.
-	The PCI or EISA irq will be assigned automatically.
-
-Specifying an invalid or in-use irq will default the driver into
-running in polled mode for that card.  If all irq entries are 0 then
-all cards will operate in polled mode.
-
-If you select the driver as part of the kernel run :
-
-	make zlilo (or whatever you do to create a bootable kernel)
-
-If you selected a module run :
-
-	make modules && make modules_install
-
-The utility ip2mkdev (see 5 and 7 below) creates all the device nodes
-required by the driver.  For a device to be created it must be configured
-in the driver and the board must be installed. Only devices corresponding
-to real IntelliPort II ports are created. With multiple boards and expansion
-boxes this will leave gaps in the sequence of device names. ip2mkdev uses
-Linux tty naming conventions: ttyF0 - ttyF255 for normal devices, and
-cuf0 - cuf255 for callout devices.
-
-
-4. USING THE DRIVERS
-
-As noted above, the driver implements the ports in accordance with Linux
-conventions, and the devices should be interchangeable with the standard
-serial devices. (This is a key point for problem reporting: please make
-sure that what you are trying do works on the ttySx/cuax ports first; then 
-tell us what went wrong with the ip2 ports!)
-
-Higher speeds can be obtained using the setserial utility which remaps 
-38,400 bps (extb) to 57,600 bps, 115,200 bps, or a custom speed. 
-Intelliport II installations using the PowerPort expansion module can
-use the custom speed setting to select the highest speeds: 153,600 bps,
-230,400 bps, 307,200 bps, 460,800bps and 921,600 bps. The base for
-custom baud rate configuration is fixed at 921,600 for cards/expansion
-modules with ST654's and 115200 for those with Cirrus CD1400's.  This
-corresponds to the maximum bit rates those chips are capable.  
-For example if the baud base is 921600 and the baud divisor is 18 then
-the custom rate is 921600/18 = 51200 bps.  See the setserial man page for
-complete details. Of course if stty accepts the higher rates now you can
-use that as well as the standard ioctls().
-
-
-5. ip2mkdev and assorted utilities...
-
-Several utilities, including the source for a binary ip2mkdev utility are
-available under .../drivers/char/ip2.  These can be build by changing to
-that directory and typing "make" after the kernel has be built.  If you do
-not wish to compile the binary utilities, the shell script below can be
-cut out and run as "ip2mkdev" to create the necessary device files.  To
-use the ip2mkdev script, you must have procfs enabled and the proc file
-system mounted on /proc.
-
-
-6. NOTES
-
-This is a release version of the driver, but it is impossible to test it
-in all configurations of Linux. If there is any anomalous behaviour that 
-does not match the standard serial port's behaviour please let us know.
-
-
-7. ip2mkdev shell script
-
-Previously, this script was simply attached here.  It is now attached as a
-shar archive to make it easier to extract the script from the documentation.
-To create the ip2mkdev shell script change to a convenient directory (/tmp
-works just fine) and run the following command:
-
-	unshar Documentation/serial/computone.txt
-		(This file)
-
-You should now have a file ip2mkdev in your current working directory with
-permissions set to execute.  Running that script with then create the
-necessary devices for the Computone boards, interfaces, and ports which
-are present on you system at the time it is run.
-
-
-#!/bin/sh
-# This is a shell archive (produced by GNU sharutils 4.2.1).
-# To extract the files from this archive, save it to some FILE, remove
-# everything before the `!/bin/sh' line above, then type `sh FILE'.
-#
-# Made on 2001-10-29 10:32 EST by <mhw@alcove.wittsend.com>.
-# Source directory was `/home2/src/tmp'.
-#
-# Existing files will *not* be overwritten unless `-c' is specified.
-#
-# This shar contains:
-# length mode       name
-# ------ ---------- ------------------------------------------
-#   4251 -rwxr-xr-x ip2mkdev
-#
-save_IFS="${IFS}"
-IFS="${IFS}:"
-gettext_dir=FAILED
-locale_dir=FAILED
-first_param="$1"
-for dir in $PATH
-do
-  if test "$gettext_dir" = FAILED && test -f $dir/gettext \
-     && ($dir/gettext --version >/dev/null 2>&1)
-  then
-    set `$dir/gettext --version 2>&1`
-    if test "$3" = GNU
-    then
-      gettext_dir=$dir
-    fi
-  fi
-  if test "$locale_dir" = FAILED && test -f $dir/shar \
-     && ($dir/shar --print-text-domain-dir >/dev/null 2>&1)
-  then
-    locale_dir=`$dir/shar --print-text-domain-dir`
-  fi
-done
-IFS="$save_IFS"
-if test "$locale_dir" = FAILED || test "$gettext_dir" = FAILED
-then
-  echo=echo
-else
-  TEXTDOMAINDIR=$locale_dir
-  export TEXTDOMAINDIR
-  TEXTDOMAIN=sharutils
-  export TEXTDOMAIN
-  echo="$gettext_dir/gettext -s"
-fi
-if touch -am -t 200112312359.59 $$.touch >/dev/null 2>&1 && test ! -f 200112312359.59 -a -f $$.touch; then
-  shar_touch='touch -am -t $1$2$3$4$5$6.$7 "$8"'
-elif touch -am 123123592001.59 $$.touch >/dev/null 2>&1 && test ! -f 123123592001.59 -a ! -f 123123592001.5 -a -f $$.touch; then
-  shar_touch='touch -am $3$4$5$6$1$2.$7 "$8"'
-elif touch -am 1231235901 $$.touch >/dev/null 2>&1 && test ! -f 1231235901 -a -f $$.touch; then
-  shar_touch='touch -am $3$4$5$6$2 "$8"'
-else
-  shar_touch=:
-  echo
-  $echo 'WARNING: not restoring timestamps.  Consider getting and'
-  $echo "installing GNU \`touch', distributed in GNU File Utilities..."
-  echo
-fi
-rm -f 200112312359.59 123123592001.59 123123592001.5 1231235901 $$.touch
-#
-if mkdir _sh17581; then
-  $echo 'x -' 'creating lock directory'
-else
-  $echo 'failed to create lock directory'
-  exit 1
-fi
-# ============= ip2mkdev ==============
-if test -f 'ip2mkdev' && test "$first_param" != -c; then
-  $echo 'x -' SKIPPING 'ip2mkdev' '(file already exists)'
-else
-  $echo 'x -' extracting 'ip2mkdev' '(text)'
-  sed 's/^X//' << 'SHAR_EOF' > 'ip2mkdev' &&
-#!/bin/sh -
-#
-#	ip2mkdev
-#
-#	Make or remove devices as needed for Computone Intelliport drivers
-#
-#	First rule!  If the dev file exists and you need it, don't mess
-#	with it.  That prevents us from screwing up open ttys, ownership
-#	and permissions on a running system!
-#
-#	This script will NOT remove devices that no longer exist if their
-#	board or interface box has been removed.  If you want to get rid
-#	of them, you can manually do an "rm -f /dev/ttyF* /dev/cuaf*"
-#	before running this script.  Running this script will then recreate
-#	all the valid devices.
-#
-#	Michael H. Warfield
-#	/\/\|=mhw=|\/\/
-#	mhw@wittsend.com
-#
-#	Updated 10/29/2000 for version 1.2.13 naming convention
-#		under devfs.	/\/\|=mhw=|\/\/
-#
-#	Updated 03/09/2000 for devfs support in ip2 drivers. /\/\|=mhw=|\/\/
-#
-X
-if test -d /dev/ip2 ; then
-#	This is devfs mode...  We don't do anything except create symlinks
-#	from the real devices to the old names!
-X	cd /dev
-X	echo "Creating symbolic links to devfs devices"
-X	for i in `ls ip2` ; do
-X		if test ! -L ip2$i ; then
-X			# Remove it incase it wasn't a symlink (old device)
-X			rm -f ip2$i
-X			ln -s ip2/$i ip2$i
-X		fi
-X	done
-X	for i in `( cd tts ; ls F* )` ; do
-X		if test ! -L tty$i ; then
-X			# Remove it incase it wasn't a symlink (old device)
-X			rm -f tty$i
-X			ln -s tts/$i tty$i
-X		fi
-X	done
-X	for i in `( cd cua ; ls F* )` ; do
-X		DEVNUMBER=`expr $i : 'F\(.*\)'`
-X		if test ! -L cuf$DEVNUMBER ; then
-X			# Remove it incase it wasn't a symlink (old device)
-X			rm -f cuf$DEVNUMBER
-X			ln -s cua/$i cuf$DEVNUMBER
-X		fi
-X	done
-X	exit 0
-fi
-X
-if test ! -f /proc/tty/drivers
-then
-X	echo "\
-Unable to check driver status.
-Make sure proc file system is mounted."
-X
-X	exit 255
-fi
-X
-if test ! -f /proc/tty/driver/ip2
-then
-X	echo "\
-Unable to locate ip2 proc file.
-Attempting to load driver"
-X
-X	if /sbin/insmod ip2
-X	then
-X		if test ! -f /proc/tty/driver/ip2
-X		then
-X			echo "\
-Unable to locate ip2 proc file after loading driver.
-Driver initialization failure or driver version error.
-"
-X		exit 255
-X		fi
-X	else
-X		echo "Unable to load ip2 driver."
-X		exit 255
-X	fi
-fi
-X
-# Ok...  So we got the driver loaded and we can locate the procfs files.
-# Next we need our major numbers.
-X
-TTYMAJOR=`sed -e '/^ip2/!d' -e '/\/dev\/tt/!d' -e 's/.*tt[^ 	]*[ 	]*\([0-9]*\)[ 	]*.*/\1/' < /proc/tty/drivers`
-CUAMAJOR=`sed -e '/^ip2/!d' -e '/\/dev\/cu/!d' -e 's/.*cu[^ 	]*[ 	]*\([0-9]*\)[ 	]*.*/\1/' < /proc/tty/drivers`
-BRDMAJOR=`sed -e '/^Driver: /!d' -e 's/.*IMajor=\([0-9]*\)[ 	]*.*/\1/' < /proc/tty/driver/ip2`
-X
-echo "\
-TTYMAJOR = $TTYMAJOR
-CUAMAJOR = $CUAMAJOR
-BRDMAJOR = $BRDMAJOR
-"
-X
-# Ok...  Now we should know our major numbers, if appropriate...
-# Now we need our boards and start the device loops.
-X
-grep '^Board [0-9]:' /proc/tty/driver/ip2 | while read token number type alltherest
-do
-X	# The test for blank "type" will catch the stats lead-in lines
-X	# if they exist in the file
-X	if test "$type" = "vacant" -o "$type" = "Vacant" -o "$type" = ""
-X	then
-X		continue
-X	fi
-X
-X	BOARDNO=`expr "$number" : '\([0-9]\):'`
-X	PORTS=`expr "$alltherest" : '.*ports=\([0-9]*\)' | tr ',' ' '`
-X	MINORS=`expr "$alltherest" : '.*minors=\([0-9,]*\)' | tr ',' ' '`
-X
-X	if test "$BOARDNO" = "" -o "$PORTS" = ""
-X	then
-#	This may be a bug.  We should at least get this much information
-X		echo "Unable to process board line"
-X		continue
-X	fi
-X
-X	if test "$MINORS" = ""
-X	then
-#	Silently skip this one.  This board seems to have no boxes
-X		continue
-X	fi
-X
-X	echo "board $BOARDNO: $type ports = $PORTS; port numbers = $MINORS"
-X
-X	if test "$BRDMAJOR" != ""
-X	then
-X		BRDMINOR=`expr $BOARDNO \* 4`
-X		STSMINOR=`expr $BRDMINOR + 1`
-X		if test ! -c /dev/ip2ipl$BOARDNO ; then
-X			mknod /dev/ip2ipl$BOARDNO c $BRDMAJOR $BRDMINOR
-X		fi
-X		if test ! -c /dev/ip2stat$BOARDNO ; then
-X			mknod /dev/ip2stat$BOARDNO c $BRDMAJOR $STSMINOR
-X		fi
-X	fi
-X
-X	if test "$TTYMAJOR" != ""
-X	then
-X		PORTNO=$BOARDBASE
-X
-X		for PORTNO in $MINORS
-X		do
-X			if test ! -c /dev/ttyF$PORTNO ; then
-X				# We got the hardware but no device - make it
-X				mknod /dev/ttyF$PORTNO c $TTYMAJOR $PORTNO
-X			fi	
-X		done
-X	fi
-X
-X	if test "$CUAMAJOR" != ""
-X	then
-X		PORTNO=$BOARDBASE
-X
-X		for PORTNO in $MINORS
-X		do
-X			if test ! -c /dev/cuf$PORTNO ; then
-X				# We got the hardware but no device - make it
-X				mknod /dev/cuf$PORTNO c $CUAMAJOR $PORTNO
-X			fi	
-X		done
-X	fi
-done
-X
-Xexit 0
-SHAR_EOF
-  (set 20 01 10 29 10 32 01 'ip2mkdev'; eval "$shar_touch") &&
-  chmod 0755 'ip2mkdev' ||
-  $echo 'restore of' 'ip2mkdev' 'failed'
-  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
-  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
-    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
-    || $echo 'ip2mkdev:' 'MD5 check failed'
-cb5717134509f38bad9fde6b1f79b4a4  ip2mkdev
-SHAR_EOF
-  else
-    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'ip2mkdev'`"
-    test 4251 -eq "$shar_count" ||
-    $echo 'ip2mkdev:' 'original size' '4251,' 'current size' "$shar_count!"
-  fi
-fi
-rm -fr _sh17581
-exit 0
diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index 4e4d0bc..d90d8ec 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -860,8 +860,14 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
 
     [Multiple options for each card instance]
     model	- force the model name
-    position_fix - Fix DMA pointer (0 = auto, 1 = use LPIB, 2 = POSBUF,
-    		   3 = VIACOMBO, 4 = COMBO)
+    position_fix - Fix DMA pointer
+		  -1 = system default: choose appropriate one per controller
+			hardware
+		  0 = auto: falls back to LPIB when POSBUF doesn't work
+		  1 = use LPIB
+		  2 = POSBUF: use position buffer
+		  3 = VIACOMBO: VIA-specific workaround for capture
+		  4 = COMBO: use LPIB for playback, auto for capture stream
     probe_mask  - Bitmask to probe codecs (default = -1, meaning all slots)
     		  When the bit 8 (0x100) is set, the lower 8 bits are used
 		  as the "fixed" codec slots; i.e. the driver probes the
diff --git a/Documentation/sound/alsa/Channel-Mapping-API.txt b/Documentation/sound/alsa/Channel-Mapping-API.txt
new file mode 100644
index 0000000..3c43d1a
--- /dev/null
+++ b/Documentation/sound/alsa/Channel-Mapping-API.txt
@@ -0,0 +1,153 @@
+ALSA PCM channel-mapping API
+============================
+					Takashi Iwai <tiwai@suse.de>
+
+GENERAL
+-------
+
+The channel mapping API allows user to query the possible channel maps
+and the current channel map, also optionally to modify the channel map
+of the current stream.
+
+A channel map is an array of position for each PCM channel.
+Typically, a stereo PCM stream has a channel map of
+  { front_left, front_right }
+while a 4.0 surround PCM stream has a channel map of
+  { front left, front right, rear left, rear right }.
+
+The problem, so far, was that we had no standard channel map
+explicitly, and applications had no way to know which channel
+corresponds to which (speaker) position.  Thus, applications applied
+wrong channels for 5.1 outputs, and you hear suddenly strange sound
+from rear.  Or, some devices secretly assume that center/LFE is the
+third/fourth channels while others that C/LFE as 5th/6th channels.
+
+Also, some devices such as HDMI are configurable for different speaker
+positions even with the same number of total channels.  However, there
+was no way to specify this because of lack of channel map
+specification.  These are the main motivations for the new channel
+mapping API.
+
+
+DESIGN
+------
+
+Actually, "the channel mapping API" doesn't introduce anything new in
+the kernel/user-space ABI perspective.  It uses only the existing
+control element features.
+
+As a ground design, each PCM substream may contain a control element
+providing the channel mapping information and configuration.  This
+element is specified by:
+	iface = SNDRV_CTL_ELEM_IFACE_PCM
+	name = "Playback Channel Map" or "Capture Channel Map"
+	device = the same device number for the assigned PCM substream
+	index = the same index number for the assigned PCM substream
+
+Note the name is different depending on the PCM substream direction.
+
+Each control element provides at least the TLV read operation and the
+read operation.  Optionally, the write operation can be provided to
+allow user to change the channel map dynamically.
+
+* TLV
+
+The TLV operation gives the list of available channel
+maps.  A list item of a channel map is usually a TLV of
+	type data-bytes ch0 ch1 ch2...
+where type is the TLV type value, the second argument is the total
+bytes (not the numbers) of channel values, and the rest are the
+position value for each channel.
+
+As a TLV type, either SNDRV_CTL_TLVT_CHMAP_FIXED,
+SNDRV_CTL_TLV_CHMAP_VAR or SNDRV_CTL_TLVT_CHMAP_PAIRED can be used.
+The _FIXED type is for a channel map with the fixed channel position
+while the latter two are for flexible channel positions.  _VAR type is
+for a channel map where all channels are freely swappable and _PAIRED
+type is where pair-wise channels are swappable.  For example, when you
+have {FL/FR/RL/RR} channel map, _PAIRED type would allow you to swap
+only {RL/RR/FL/FR} while _VAR type would allow even swapping FL and
+RR.
+
+These new TLV types are defined in sound/tlv.h.
+
+The available channel position values are defined in sound/asound.h,
+here is a cut:
+
+/* channel positions */
+enum {
+	SNDRV_CHMAP_UNKNOWN = 0,
+	SNDRV_CHMAP_NA,		/* N/A, silent */
+	SNDRV_CHMAP_MONO,	/* mono stream */
+	/* this follows the alsa-lib mixer channel value + 3 */
+	SNDRV_CHMAP_FL,		/* front left */
+	SNDRV_CHMAP_FR,		/* front right */
+	SNDRV_CHMAP_RL,		/* rear left */
+	SNDRV_CHMAP_RR,		/* rear right */
+	SNDRV_CHMAP_FC,		/* front center */
+	SNDRV_CHMAP_LFE,	/* LFE */
+	SNDRV_CHMAP_SL,		/* side left */
+	SNDRV_CHMAP_SR,		/* side right */
+	SNDRV_CHMAP_RC,		/* rear center */
+	/* new definitions */
+	SNDRV_CHMAP_FLC,	/* front left center */
+	SNDRV_CHMAP_FRC,	/* front right center */
+	SNDRV_CHMAP_RLC,	/* rear left center */
+	SNDRV_CHMAP_RRC,	/* rear right center */
+	SNDRV_CHMAP_FLW,	/* front left wide */
+	SNDRV_CHMAP_FRW,	/* front right wide */
+	SNDRV_CHMAP_FLH,	/* front left high */
+	SNDRV_CHMAP_FCH,	/* front center high */
+	SNDRV_CHMAP_FRH,	/* front right high */
+	SNDRV_CHMAP_TC,		/* top center */
+	SNDRV_CHMAP_TFL,	/* top front left */
+	SNDRV_CHMAP_TFR,	/* top front right */
+	SNDRV_CHMAP_TFC,	/* top front center */
+	SNDRV_CHMAP_TRL,	/* top rear left */
+	SNDRV_CHMAP_TRR,	/* top rear right */
+	SNDRV_CHMAP_TRC,	/* top rear center */
+	SNDRV_CHMAP_LAST = SNDRV_CHMAP_TRC,
+};
+
+When a PCM stream can provide more than one channel map, you can
+provide multiple channel maps in a TLV container type.  The TLV data
+to be returned will contain such as:
+	SNDRV_CTL_TLVT_CONTAINER 96
+	    SNDRV_CTL_TLVT_CHMAP_FIXED 4 SNDRV_CHMAP_FC
+	    SNDRV_CTL_TLVT_CHMAP_FIXED 8 SNDRV_CHMAP_FL SNDRV_CHMAP_FR
+	    SNDRV_CTL_TLVT_CHMAP_FIXED 16 NDRV_CHMAP_FL SNDRV_CHMAP_FR \
+		SNDRV_CHMAP_RL SNDRV_CHMAP_RR
+
+The channel position is provided in LSB 16bits.  The upper bits are
+used for bit flags.
+
+#define SNDRV_CHMAP_POSITION_MASK	0xffff
+#define SNDRV_CHMAP_PHASE_INVERSE	(0x01 << 16)
+#define SNDRV_CHMAP_DRIVER_SPEC		(0x02 << 16)
+
+SNDRV_CHMAP_PHASE_INVERSE indicates the channel is phase inverted,
+(thus summing left and right channels would result in almost silence).
+Some digital mic devices have this.
+
+When SNDRV_CHMAP_DRIVER_SPEC is set, all the channel position values
+don't follow the standard definition above but driver-specific.
+
+* READ OPERATION
+
+The control read operation is for providing the current channel map of
+the given stream.  The control element returns an integer array
+containing the position of each channel.
+
+When this is performed before the number of the channel is specified
+(i.e. hw_params is set), it should return all channels set to
+UNKNOWN.
+
+* WRITE OPERATION
+
+The control write operation is optional, and only for devices that can
+change the channel configuration on the fly, such as HDMI.  User needs
+to pass an integer value containing the valid channel positions for
+all channels of the assigned PCM substream.
+
+This operation is allowed only at PCM PREPARED state.  When called in
+other states, it shall return an error.
diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt
index a92bba8..16dfe57 100644
--- a/Documentation/sound/alsa/HD-Audio-Models.txt
+++ b/Documentation/sound/alsa/HD-Audio-Models.txt
@@ -74,7 +74,8 @@ CMI9880
 
 AD1882 / AD1882A
 ================
-  3stack	3-stack mode (default)
+  3stack	3-stack mode
+  3stack-automute 3-stack with automute front HP (default)
   6stack	6-stack mode
 
 AD1884A / AD1883 / AD1984A / AD1984B
diff --git a/Documentation/spi/ep93xx_spi b/Documentation/spi/ep93xx_spi
index d8eb01c..832ddce 100644
--- a/Documentation/spi/ep93xx_spi
+++ b/Documentation/spi/ep93xx_spi
@@ -26,7 +26,7 @@ arch/arm/mach-ep93xx/ts72xx.c:
 #include <linux/gpio.h>
 #include <linux/spi/spi.h>
 
-#include <mach/ep93xx_spi.h>
+#include <linux/platform_data/spi-ep93xx.h>
 
 /* this is our GPIO line used for chip select */
 #define MMC_CHIP_SELECT_GPIO EP93XX_GPIO_LINE_EGPIO9
diff --git a/Documentation/spi/spi-sc18is602 b/Documentation/spi/spi-sc18is602
new file mode 100644
index 0000000..a457028
--- /dev/null
+++ b/Documentation/spi/spi-sc18is602
@@ -0,0 +1,36 @@
+Kernel driver spi-sc18is602
+===========================
+
+Supported chips:
+  * NXP SI18IS602/602B/603
+    Datasheet: http://www.nxp.com/documents/data_sheet/SC18IS602_602B_603.pdf
+
+Author:
+        Guenter Roeck <linux@roeck-us.net>
+
+
+Description
+-----------
+
+This driver provides connects a NXP SC18IS602/603 I2C-bus to SPI bridge to the
+kernel's SPI core subsystem.
+
+The driver does not probe for supported chips, since the SI18IS602/603 does not
+support Chip ID registers. You will have to instantiate the devices explicitly.
+Please see Documentation/i2c/instantiating-devices for details.
+
+
+Usage Notes
+-----------
+
+This driver requires the I2C adapter driver to support raw I2C messages. I2C
+adapter drivers which can only handle the SMBus protocol are not supported.
+
+The maximum SPI message size supported by SC18IS602/603 is 200 bytes. Attempts
+to initiate longer transfers will fail with -EINVAL. EEPROM read operations and
+similar large accesses have to be split into multiple chunks of no more than
+200 bytes per SPI message (128 bytes of data per message is recommended). This
+means that programs such as "cp" or "od", which automatically use large block
+sizes to access a device, can not be used directly to read data from EEPROM.
+Programs such as dd, where the block size can be specified, should be used
+instead.
diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt
index 6d78841..2907ba6 100644
--- a/Documentation/sysctl/kernel.txt
+++ b/Documentation/sysctl/kernel.txt
@@ -181,6 +181,8 @@ core_pattern is used to specify a core dumpfile pattern name.
 	%p	pid
 	%u	uid
 	%g	gid
+	%d	dump mode, matches PR_SET_DUMPABLE and
+		/proc/sys/fs/suid_dumpable
 	%s	signal number
 	%t	UNIX time of dump
 	%h	hostname
diff --git a/Documentation/target/tcm_mod_builder.py b/Documentation/target/tcm_mod_builder.py
index a78879b..3fe0d81 100755
--- a/Documentation/target/tcm_mod_builder.py
+++ b/Documentation/target/tcm_mod_builder.py
@@ -402,8 +402,6 @@ def tcm_mod_build_configfs(proto_ident, fabric_mod_dir_var, fabric_mod_name):
 	buf += "	.queue_data_in			= " + fabric_mod_name + "_queue_data_in,\n"
 	buf += "	.queue_status			= " + fabric_mod_name + "_queue_status,\n"
 	buf += "	.queue_tm_rsp			= " + fabric_mod_name + "_queue_tm_rsp,\n"
-	buf += "	.get_fabric_sense_len		= " + fabric_mod_name + "_get_fabric_sense_len,\n"
-	buf += "	.set_fabric_sense_len		= " + fabric_mod_name + "_set_fabric_sense_len,\n"
 	buf += "	.is_state_remove		= " + fabric_mod_name + "_is_state_remove,\n"
 	buf += "	/*\n"
 	buf += "	 * Setup function pointers for generic logic in target_core_fabric_configfs.c\n"
@@ -906,20 +904,6 @@ def tcm_mod_dump_fabric_ops(proto_ident, fabric_mod_dir_var, fabric_mod_name):
 			buf += "}\n\n"
 			bufi += "int " + fabric_mod_name + "_queue_tm_rsp(struct se_cmd *);\n"
 
-		if re.search('get_fabric_sense_len\)\(', fo):
-			buf += "u16 " + fabric_mod_name + "_get_fabric_sense_len(void)\n"
-			buf += "{\n"
-			buf += "	return 0;\n"
-			buf += "}\n\n"
-			bufi += "u16 " + fabric_mod_name + "_get_fabric_sense_len(void);\n"
-
-		if re.search('set_fabric_sense_len\)\(', fo):
-			buf += "u16 " + fabric_mod_name + "_set_fabric_sense_len(struct se_cmd *se_cmd, u32 sense_length)\n"
-			buf += "{\n"
-			buf += "	return 0;\n"
-			buf += "}\n\n"
-			bufi += "u16 " + fabric_mod_name + "_set_fabric_sense_len(struct se_cmd *, u32);\n"
-
 		if re.search('is_state_remove\)\(', fo):
 			buf += "int " + fabric_mod_name + "_is_state_remove(struct se_cmd *se_cmd)\n"
 			buf += "{\n"
diff --git a/Documentation/thermal/cpu-cooling-api.txt b/Documentation/thermal/cpu-cooling-api.txt
new file mode 100644
index 0000000..fca24c9
--- /dev/null
+++ b/Documentation/thermal/cpu-cooling-api.txt
@@ -0,0 +1,32 @@
+CPU cooling APIs How To
+===================================
+
+Written by Amit Daniel Kachhap <amit.kachhap@linaro.org>
+
+Updated: 12 May 2012
+
+Copyright (c)  2012 Samsung Electronics Co., Ltd(http://www.samsung.com)
+
+0. Introduction
+
+The generic cpu cooling(freq clipping) provides registration/unregistration APIs
+to the caller. The binding of the cooling devices to the trip point is left for
+the user. The registration APIs returns the cooling device pointer.
+
+1. cpu cooling APIs
+
+1.1 cpufreq registration/unregistration APIs
+1.1.1 struct thermal_cooling_device *cpufreq_cooling_register(
+	struct cpumask *clip_cpus)
+
+    This interface function registers the cpufreq cooling device with the name
+    "thermal-cpufreq-%x". This api can support multiple instances of cpufreq
+    cooling devices.
+
+   clip_cpus: cpumask of cpus where the frequency constraints will happen.
+
+1.1.2 void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev)
+
+    This interface function unregisters the "thermal-cpufreq-%x" cooling device.
+
+    cdev: Cooling device pointer which has to be unregistered.
diff --git a/Documentation/thermal/exynos_thermal b/Documentation/thermal/exynos_thermal
new file mode 100644
index 0000000..2b46f67
--- /dev/null
+++ b/Documentation/thermal/exynos_thermal
@@ -0,0 +1,52 @@
+Kernel driver exynos4_tmu
+=================
+
+Supported chips:
+* ARM SAMSUNG EXYNOS4 series of SoC
+  Prefix: 'exynos4-tmu'
+  Datasheet: Not publicly available
+
+Authors: Donggeun Kim <dg77.kim@samsung.com>
+
+Description
+-----------
+
+This driver allows to read temperature inside SAMSUNG EXYNOS4 series of SoC.
+
+The chip only exposes the measured 8-bit temperature code value
+through a register.
+Temperature can be taken from the temperature code.
+There are three equations converting from temperature to temperature code.
+
+The three equations are:
+  1. Two point trimming
+	Tc = (T - 25) * (TI2 - TI1) / (85 - 25) + TI1
+
+  2. One point trimming
+	Tc = T + TI1 - 25
+
+  3. No trimming
+	Tc = T + 50
+
+  Tc: Temperature code, T: Temperature,
+  TI1: Trimming info for 25 degree Celsius (stored at TRIMINFO register)
+       Temperature code measured at 25 degree Celsius which is unchanged
+  TI2: Trimming info for 85 degree Celsius (stored at TRIMINFO register)
+       Temperature code measured at 85 degree Celsius which is unchanged
+
+TMU(Thermal Management Unit) in EXYNOS4 generates interrupt
+when temperature exceeds pre-defined levels.
+The maximum number of configurable threshold is four.
+The threshold levels are defined as follows:
+  Level_0: current temperature > trigger_level_0 + threshold
+  Level_1: current temperature > trigger_level_1 + threshold
+  Level_2: current temperature > trigger_level_2 + threshold
+  Level_3: current temperature > trigger_level_3 + threshold
+
+  The threshold and each trigger_level are set
+  through the corresponding registers.
+
+When an interrupt occurs, this driver notify kernel thermal framework
+with the function exynos4_report_trigger.
+Although an interrupt condition for level_0 can be set,
+it can be used to synchronize the cooling action.
diff --git a/Documentation/thermal/sysfs-api.txt b/Documentation/thermal/sysfs-api.txt
index c087dbc..88c0233 100644
--- a/Documentation/thermal/sysfs-api.txt
+++ b/Documentation/thermal/sysfs-api.txt
@@ -84,7 +84,8 @@ temperature) and throttle appropriate devices.
 
 1.3 interface for binding a thermal zone device with a thermal cooling device
 1.3.1 int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
-		int trip, struct thermal_cooling_device *cdev);
+	int trip, struct thermal_cooling_device *cdev,
+	unsigned long upper, unsigned long lower);
 
     This interface function bind a thermal cooling device to the certain trip
     point of a thermal zone device.
@@ -93,6 +94,12 @@ temperature) and throttle appropriate devices.
     cdev: thermal cooling device
     trip: indicates which trip point the cooling devices is associated with
 	  in this thermal zone.
+    upper:the Maximum cooling state for this trip point.
+          THERMAL_NO_LIMIT means no upper limit,
+	  and the cooling device can be in max_state.
+    lower:the Minimum cooling state can be used for this trip point.
+          THERMAL_NO_LIMIT means no lower limit,
+	  and the cooling device can be in cooling state 0.
 
 1.3.2 int thermal_zone_unbind_cooling_device(struct thermal_zone_device *tz,
 		int trip, struct thermal_cooling_device *cdev);
@@ -105,6 +112,29 @@ temperature) and throttle appropriate devices.
     trip: indicates which trip point the cooling devices is associated with
 	  in this thermal zone.
 
+1.4 Thermal Zone Parameters
+1.4.1 struct thermal_bind_params
+    This structure defines the following parameters that are used to bind
+    a zone with a cooling device for a particular trip point.
+    .cdev: The cooling device pointer
+    .weight: The 'influence' of a particular cooling device on this zone.
+             This is on a percentage scale. The sum of all these weights
+             (for a particular zone) cannot exceed 100.
+    .trip_mask:This is a bit mask that gives the binding relation between
+               this thermal zone and cdev, for a particular trip point.
+               If nth bit is set, then the cdev and thermal zone are bound
+               for trip point n.
+    .match: This call back returns success(0) if the 'tz and cdev' need to
+	    be bound, as per platform data.
+1.4.2 struct thermal_zone_params
+    This structure defines the platform level parameters for a thermal zone.
+    This data, for each thermal zone should come from the platform layer.
+    This is an optional feature where some platforms can choose not to
+    provide this data.
+    .governor_name: Name of the thermal governor used for this zone
+    .num_tbps: Number of thermal_bind_params entries for this zone
+    .tbp: thermal_bind_params entries
+
 2. sysfs attributes structure
 
 RO	read only value
@@ -119,6 +149,7 @@ Thermal zone device sys I/F, created once it's registered:
     |---type:			Type of the thermal zone
     |---temp:			Current temperature
     |---mode:			Working mode of the thermal zone
+    |---policy:			Thermal governor used for this zone
     |---trip_point_[0-*]_temp:	Trip point temperature
     |---trip_point_[0-*]_type:	Trip point type
     |---trip_point_[0-*]_hyst:	Hysteresis value for this trip point
@@ -180,6 +211,10 @@ mode
 			  charge of the thermal management.
 	RW, Optional
 
+policy
+	One of the various thermal governors used for a particular zone.
+	RW, Required
+
 trip_point_[0-*]_temp
 	The temperature above which trip point will be fired.
 	Unit: millidegree Celsius
@@ -257,6 +292,7 @@ method, the sys I/F structure will be built like this:
     |---type:			acpitz
     |---temp:			37000
     |---mode:			enabled
+    |---policy:			step_wise
     |---trip_point_0_temp:	100000
     |---trip_point_0_type:	critical
     |---trip_point_1_temp:	80000
@@ -298,3 +334,38 @@ to a thermal_zone_device when it registers itself with the framework. The
 event will be one of:{THERMAL_AUX0, THERMAL_AUX1, THERMAL_CRITICAL,
 THERMAL_DEV_FAULT}. Notification can be sent when the current temperature
 crosses any of the configured thresholds.
+
+5. Export Symbol APIs:
+
+5.1: get_tz_trend:
+This function returns the trend of a thermal zone, i.e the rate of change
+of temperature of the thermal zone. Ideally, the thermal sensor drivers
+are supposed to implement the callback. If they don't, the thermal
+framework calculated the trend by comparing the previous and the current
+temperature values.
+
+5.2:get_thermal_instance:
+This function returns the thermal_instance corresponding to a given
+{thermal_zone, cooling_device, trip_point} combination. Returns NULL
+if such an instance does not exist.
+
+5.3:notify_thermal_framework:
+This function handles the trip events from sensor drivers. It starts
+throttling the cooling devices according to the policy configured.
+For CRITICAL and HOT trip points, this notifies the respective drivers,
+and does actual throttling for other trip points i.e ACTIVE and PASSIVE.
+The throttling policy is based on the configured platform data; if no
+platform data is provided, this uses the step_wise throttling policy.
+
+5.4:thermal_cdev_update:
+This function serves as an arbitrator to set the state of a cooling
+device. It sets the cooling device to the deepest cooling state if
+possible.
+
+5.5:thermal_register_governor:
+This function lets the various thermal governors to register themselves
+with the Thermal framework. At run time, depending on a zone's platform
+data, a particular governor is used for throttling.
+
+5.6:thermal_unregister_governor:
+This function unregisters a governor from the thermal framework.
diff --git a/Documentation/usb/persist.txt b/Documentation/usb/persist.txt
index 074b159..35d70ed 100644
--- a/Documentation/usb/persist.txt
+++ b/Documentation/usb/persist.txt
@@ -155,6 +155,9 @@ If the kernel gets fooled in this way, it's almost certain to cause
 data corruption and to crash your system.  You'll have no one to blame
 but yourself.
 
+For those devices with avoid_reset_quirk attribute being set, persist
+maybe fail because they may morph after reset.
+
 YOU HAVE BEEN WARNED!  USE AT YOUR OWN RISK!
 
 That having been said, most of the time there shouldn't be any trouble
diff --git a/Documentation/vfio.txt b/Documentation/vfio.txt
index 0cb6685..8eda363 100644
--- a/Documentation/vfio.txt
+++ b/Documentation/vfio.txt
@@ -133,7 +133,7 @@ character devices for this group:
 $ lspci -n -s 0000:06:0d.0
 06:0d.0 0401: 1102:0002 (rev 08)
 # echo 0000:06:0d.0 > /sys/bus/pci/devices/0000:06:0d.0/driver/unbind
-# echo 1102 0002 > /sys/bus/pci/drivers/vfio/new_id
+# echo 1102 0002 > /sys/bus/pci/drivers/vfio-pci/new_id
 
 Now we need to look at what other devices are in the group to free
 it for use by VFIO:
diff --git a/Documentation/video4linux/CARDLIST.cx23885 b/Documentation/video4linux/CARDLIST.cx23885
index 652aecd..1299b5e 100644
--- a/Documentation/video4linux/CARDLIST.cx23885
+++ b/Documentation/video4linux/CARDLIST.cx23885
@@ -35,3 +35,4 @@
  34 -> TerraTec Cinergy T PCIe Dual                        [153b:117e]
  35 -> TeVii S471                                          [d471:9022]
  36 -> Hauppauge WinTV-HVR1255                             [0070:2259]
+ 37 -> Prof Revolution DVB-S2 8000                         [8000:3034]
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
index bf33aaa..a12f4e4 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -857,7 +857,8 @@ struct kvm_userspace_memory_region {
 };
 
 /* for kvm_memory_region::flags */
-#define KVM_MEM_LOG_DIRTY_PAGES  1UL
+#define KVM_MEM_LOG_DIRTY_PAGES	(1UL << 0)
+#define KVM_MEM_READONLY	(1UL << 1)
 
 This ioctl allows the user to create or modify a guest physical memory
 slot.  When changing an existing slot, it may be moved in the guest
@@ -873,14 +874,17 @@ It is recommended that the lower 21 bits of guest_phys_addr and userspace_addr
 be identical.  This allows large pages in the guest to be backed by large
 pages in the host.
 
-The flags field supports just one flag, KVM_MEM_LOG_DIRTY_PAGES, which
-instructs kvm to keep track of writes to memory within the slot.  See
-the KVM_GET_DIRTY_LOG ioctl.
+The flags field supports two flag, KVM_MEM_LOG_DIRTY_PAGES, which instructs
+kvm to keep track of writes to memory within the slot.  See KVM_GET_DIRTY_LOG
+ioctl.  The KVM_CAP_READONLY_MEM capability indicates the availability of the
+KVM_MEM_READONLY flag.  When this flag is set for a memory region, KVM only
+allows read accesses.  Writes will be posted to userspace as KVM_EXIT_MMIO
+exits.
 
-When the KVM_CAP_SYNC_MMU capability, changes in the backing of the memory
-region are automatically reflected into the guest.  For example, an mmap()
-that affects the region will be made visible immediately.  Another example
-is madvise(MADV_DROP).
+When the KVM_CAP_SYNC_MMU capability is available, changes in the backing of
+the memory region are automatically reflected into the guest.  For example, an
+mmap() that affects the region will be made visible immediately.  Another
+example is madvise(MADV_DROP).
 
 It is recommended to use this API instead of the KVM_SET_MEMORY_REGION ioctl.
 The KVM_SET_MEMORY_REGION does not allow fine grained control over memory
@@ -1190,12 +1194,15 @@ struct kvm_ppc_pvinfo {
 This ioctl fetches PV specific information that need to be passed to the guest
 using the device tree or other means from vm context.
 
-For now the only implemented piece of information distributed here is an array
-of 4 instructions that make up a hypercall.
+The hcall array defines 4 instructions that make up a hypercall.
 
 If any additional field gets added to this structure later on, a bit for that
 additional piece of information will be set in the flags bitmap.
 
+The flags bitmap is defined as:
+
+   /* the host supports the ePAPR idle hcall
+   #define KVM_PPC_PVINFO_FLAGS_EV_IDLE   (1<<0)
 
 4.48 KVM_ASSIGN_PCI_DEVICE
 
@@ -1727,7 +1734,12 @@ registers, find a list below:
   Arch  |       Register        | Width (bits)
         |                       |
   PPC   | KVM_REG_PPC_HIOR      | 64
-
+  PPC   | KVM_REG_PPC_IAC1      | 64
+  PPC   | KVM_REG_PPC_IAC2      | 64
+  PPC   | KVM_REG_PPC_IAC3      | 64
+  PPC   | KVM_REG_PPC_IAC4      | 64
+  PPC   | KVM_REG_PPC_DAC1      | 64
+  PPC   | KVM_REG_PPC_DAC2      | 64
 
 4.69 KVM_GET_ONE_REG
 
@@ -1743,7 +1755,7 @@ kvm_one_reg struct passed in. On success, the register value can be found
 at the memory location pointed to by "addr".
 
 The list of registers accessible using this interface is identical to the
-list in 4.64.
+list in 4.68.
 
 
 4.70 KVM_KVMCLOCK_CTRL
diff --git a/Documentation/virtual/kvm/hypercalls.txt b/Documentation/virtual/kvm/hypercalls.txt
new file mode 100644
index 0000000..ea113b5
--- /dev/null
+++ b/Documentation/virtual/kvm/hypercalls.txt
@@ -0,0 +1,66 @@
+Linux KVM Hypercall:
+===================
+X86:
+ KVM Hypercalls have a three-byte sequence of either the vmcall or the vmmcall
+ instruction. The hypervisor can replace it with instructions that are
+ guaranteed to be supported.
+
+ Up to four arguments may be passed in rbx, rcx, rdx, and rsi respectively.
+ The hypercall number should be placed in rax and the return value will be
+ placed in rax.  No other registers will be clobbered unless explicitly stated
+ by the particular hypercall.
+
+S390:
+  R2-R7 are used for parameters 1-6. In addition, R1 is used for hypercall
+  number. The return value is written to R2.
+
+  S390 uses diagnose instruction as hypercall (0x500) along with hypercall
+  number in R1.
+
+ PowerPC:
+  It uses R3-R10 and hypercall number in R11. R4-R11 are used as output registers.
+  Return value is placed in R3.
+
+  KVM hypercalls uses 4 byte opcode, that are patched with 'hypercall-instructions'
+  property inside the device tree's /hypervisor node.
+  For more information refer to Documentation/virtual/kvm/ppc-pv.txt
+
+KVM Hypercalls Documentation
+===========================
+The template for each hypercall is:
+1. Hypercall name.
+2. Architecture(s)
+3. Status (deprecated, obsolete, active)
+4. Purpose
+
+1. KVM_HC_VAPIC_POLL_IRQ
+------------------------
+Architecture: x86
+Status: active
+Purpose: Trigger guest exit so that the host can check for pending
+interrupts on reentry.
+
+2. KVM_HC_MMU_OP
+------------------------
+Architecture: x86
+Status: deprecated.
+Purpose: Support MMU operations such as writing to PTE,
+flushing TLB, release PT.
+
+3. KVM_HC_FEATURES
+------------------------
+Architecture: PPC
+Status: active
+Purpose: Expose hypercall availability to the guest. On x86 platforms, cpuid
+used to enumerate which hypercalls are available. On PPC, either device tree
+based lookup ( which is also what EPAPR dictates) OR KVM specific enumeration
+mechanism (which is this hypercall) can be used.
+
+4. KVM_HC_PPC_MAP_MAGIC_PAGE
+------------------------
+Architecture: PPC
+Status: active
+Purpose: To enable communication between the hypervisor and guest there is a
+shared page that contains parts of supervisor visible register state.
+The guest can map this shared page to access its supervisor register through
+memory using this hypercall.
diff --git a/Documentation/virtual/kvm/msr.txt b/Documentation/virtual/kvm/msr.txt
index 7304710..6d470ae 100644
--- a/Documentation/virtual/kvm/msr.txt
+++ b/Documentation/virtual/kvm/msr.txt
@@ -34,9 +34,12 @@ MSR_KVM_WALL_CLOCK_NEW:   0x4b564d00
 		time information and check that they are both equal and even.
 		An odd version indicates an in-progress update.
 
-		sec: number of seconds for wallclock.
+		sec: number of seconds for wallclock at time of boot.
 
-		nsec: number of nanoseconds for wallclock.
+		nsec: number of nanoseconds for wallclock at time of boot.
+
+	In order to get the current wallclock time, the system_time from
+	MSR_KVM_SYSTEM_TIME_NEW needs to be added.
 
 	Note that although MSRs are per-CPU entities, the effect of this
 	particular MSR is global.
@@ -82,20 +85,25 @@ MSR_KVM_SYSTEM_TIME_NEW:  0x4b564d01
 		time at the time this structure was last updated. Unit is
 		nanoseconds.
 
-		tsc_to_system_mul: a function of the tsc frequency. One has
-		to multiply any tsc-related quantity by this value to get
-		a value in nanoseconds, besides dividing by 2^tsc_shift
+		tsc_to_system_mul: multiplier to be used when converting
+		tsc-related quantity to nanoseconds
 
-		tsc_shift: cycle to nanosecond divider, as a power of two, to
-		allow for shift rights. One has to shift right any tsc-related
-		quantity by this value to get a value in nanoseconds, besides
-		multiplying by tsc_to_system_mul.
+		tsc_shift: shift to be used when converting tsc-related
+		quantity to nanoseconds. This shift will ensure that
+		multiplication with tsc_to_system_mul does not overflow.
+		A positive value denotes a left shift, a negative value
+		a right shift.
 
-		With this information, guests can derive per-CPU time by
-		doing:
+		The conversion from tsc to nanoseconds involves an additional
+		right shift by 32 bits. With this information, guests can
+		derive per-CPU time by doing:
 
 			time = (current_tsc - tsc_timestamp)
-			time = (time * tsc_to_system_mul) >> tsc_shift
+			if (tsc_shift >= 0)
+				time <<= tsc_shift;
+			else
+				time >>= -tsc_shift;
+			time = (time * tsc_to_system_mul) >> 32
 			time = time + system_time
 
 		flags: bits in this field indicate extended capabilities
diff --git a/Documentation/virtual/kvm/ppc-pv.txt b/Documentation/virtual/kvm/ppc-pv.txt
index 4911cf9..4cd076f 100644
--- a/Documentation/virtual/kvm/ppc-pv.txt
+++ b/Documentation/virtual/kvm/ppc-pv.txt
@@ -174,3 +174,25 @@ following:
 That way we can inject an arbitrary amount of code as replacement for a single
 instruction. This allows us to check for pending interrupts when setting EE=1
 for example.
+
+Hypercall ABIs in KVM on PowerPC
+=================================
+1) KVM hypercalls (ePAPR)
+
+These are ePAPR compliant hypercall implementation (mentioned above). Even
+generic hypercalls are implemented here, like the ePAPR idle hcall. These are
+available on all targets.
+
+2) PAPR hypercalls
+
+PAPR hypercalls are needed to run server PowerPC PAPR guests (-M pseries in QEMU).
+These are the same hypercalls that pHyp, the POWER hypervisor implements. Some of
+them are handled in the kernel, some are handled in user space. This is only
+available on book3s_64.
+
+3) OSI hypercalls
+
+Mac-on-Linux is another user of KVM on PowerPC, which has its own hypercall (long
+before KVM). This is supported to maintain compatibility. All these hypercalls get
+forwarded to user space. This is only useful on book3s_32, but can be used with
+book3s_64 as well.
diff --git a/Documentation/vm/ksm.txt b/Documentation/vm/ksm.txt
index b392e49..100d58d 100644
--- a/Documentation/vm/ksm.txt
+++ b/Documentation/vm/ksm.txt
@@ -58,6 +58,13 @@ sleep_millisecs  - how many milliseconds ksmd should sleep before next scan
                    e.g. "echo 20 > /sys/kernel/mm/ksm/sleep_millisecs"
                    Default: 20 (chosen for demonstration purposes)
 
+merge_nodes      - specifies if pages from different numa nodes can be merged.
+                   When set to 0, ksm merges only pages which physically
+                   reside in the memory area of same NUMA node. It brings
+                   lower latency to access to shared page. Value can be
+                   changed only when there is no ksm shared pages in system.
+                   Default: 1
+
 run              - set 0 to stop ksmd from running but keep merged pages,
                    set 1 to run ksmd e.g. "echo 1 > /sys/kernel/mm/ksm/run",
                    set 2 to stop ksmd and unmerge all pages currently merged,
diff --git a/Documentation/vm/unevictable-lru.txt b/Documentation/vm/unevictable-lru.txt
index fa206cc..a68db769 100644
--- a/Documentation/vm/unevictable-lru.txt
+++ b/Documentation/vm/unevictable-lru.txt
@@ -197,12 +197,8 @@ the pages are also "rescued" from the unevictable list in the process of
 freeing them.
 
 page_evictable() also checks for mlocked pages by testing an additional page
-flag, PG_mlocked (as wrapped by PageMlocked()).  If the page is NOT mlocked,
-and a non-NULL VMA is supplied, page_evictable() will check whether the VMA is
-VM_LOCKED via is_mlocked_vma().  is_mlocked_vma() will SetPageMlocked() and
-update the appropriate statistics if the vma is VM_LOCKED.  This method allows
-efficient "culling" of pages in the fault path that are being faulted in to
-VM_LOCKED VMAs.
+flag, PG_mlocked (as wrapped by PageMlocked()), which is set when a page is
+faulted into a VM_LOCKED vma, or found in a vma being VM_LOCKED.
 
 
 VMSCAN'S HANDLING OF UNEVICTABLE PAGES
@@ -371,8 +367,8 @@ mlock_fixup() filters several classes of "special" VMAs:
    mlock_fixup() will call make_pages_present() in the hugetlbfs VMA range to
    allocate the huge pages and populate the ptes.
 
-3) VMAs with VM_DONTEXPAND or VM_RESERVED are generally userspace mappings of
-   kernel pages, such as the VDSO page, relay channel pages, etc.  These pages
+3) VMAs with VM_DONTEXPAND are generally userspace mappings of kernel pages,
+   such as the VDSO page, relay channel pages, etc. These pages
    are inherently unevictable and are not managed on the LRU lists.
    mlock_fixup() treats these VMAs the same as hugetlbfs VMAs.  It calls
    make_pages_present() to populate the ptes.
@@ -651,7 +647,7 @@ PAGE RECLAIM IN shrink_*_list()
 -------------------------------
 
 shrink_active_list() culls any obviously unevictable pages - i.e.
-!page_evictable(page, NULL) - diverting these to the unevictable list.
+!page_evictable(page) - diverting these to the unevictable list.
 However, shrink_active_list() only sees unevictable pages that made it onto the
 active/inactive lru lists.  Note that these pages do not have PageUnevictable
 set - otherwise they would be on the unevictable list and shrink_active_list
diff --git a/Documentation/zh_CN/arm/Booting b/Documentation/zh_CN/arm/Booting
new file mode 100644
index 0000000..3014ea8
--- /dev/null
+++ b/Documentation/zh_CN/arm/Booting
@@ -0,0 +1,175 @@
+﻿Chinese translated version of Documentation/arm/Booting
+
+If you have any comment or update to the content, please contact the
+original document maintainer directly.  However, if you have a problem
+communicating in English you can also ask the Chinese maintainer for
+help.  Contact the Chinese maintainer if this translation is outdated
+or if there is a problem with the translation.
+
+Maintainer: Russell King <linux@arm.linux.org.uk>
+Chinese maintainer: Fu Wei <tekkamanninja@gmail.com>
+---------------------------------------------------------------------
+Documentation/arm/Booting 的中文翻译
+
+如果想评论或更新本文的内容，请直接联系原文档的维护者。如果你使用英文
+交流有困难的话，也可以向中文版维护者求助。如果本翻译更新不及时或者翻
+译存在问题，请联系中文版维护者。
+
+英文版维护者： Russell King <linux@arm.linux.org.uk>
+中文版维护者： 傅炜  Fu Wei <tekkamanninja@gmail.com>
+中文版翻译者： 傅炜  Fu Wei <tekkamanninja@gmail.com>
+中文版校译者： 傅炜  Fu Wei <tekkamanninja@gmail.com>
+
+以下为正文
+---------------------------------------------------------------------
+
+			启动 ARM Linux
+			==============
+
+作者：Russell King
+日期：2002年5月18日
+
+以下文档适用于 2.4.18-rmk6 及以上版本。
+
+为了启动 ARM Linux，你需要一个引导装载程序（boot loader），
+它是一个在主内核启动前运行的一个小程序。引导装载程序需要初始化各种
+设备，并最终调用 Linux 内核，将信息传递给内核。
+
+从本质上讲，引导装载程序应提供（至少）以下功能：
+
+1、设置和初始化 RAM。
+2、初始化一个串口。
+3、检测机器的类型（machine type）。
+4、设置内核标签列表（tagged list）。
+5、调用内核映像。
+
+
+1、设置和初始化 RAM
+-------------------
+
+现有的引导加载程序:		强制
+新开发的引导加载程序:		强制
+
+引导装载程序应该找到并初始化系统中所有内核用于保持系统变量数据的 RAM。
+这个操作的执行是设备依赖的。（它可能使用内部算法来自动定位和计算所有
+RAM，或可能使用对这个设备已知的 RAM 信息，还可能使用任何引导装载程序
+设计者想到的匹配方法。）
+
+
+2、初始化一个串口
+-----------------------------
+
+现有的引导加载程序:		可选、建议
+新开发的引导加载程序:		可选、建议
+
+引导加载程序应该初始化并使能一个目标板上的串口。这允许内核串口驱动
+自动检测哪个串口用于内核控制台。(一般用于调试或与目标板通信。)
+
+作为替代方案，引导加载程序也可以通过标签列表传递相关的'console='
+选项给内核以指定某个串口，而串口数据格式的选项在以下文档中描述：
+
+       Documentation/kernel-parameters.txt。
+
+
+3、检测机器类型
+--------------------------
+
+现有的引导加载程序:		可选
+新开发的引导加载程序:		强制
+
+引导加载程序应该通过某些方式检测自身所处的机器类型。这是一个硬件
+代码或通过查看所连接的硬件用某些算法得到，这些超出了本文档的范围。
+引导加载程序最终必须能提供一个 MACH_TYPE_xxx 值给内核。
+(详见 linux/arch/arm/tools/mach-types )。
+
+4、设置启动数据
+------------------
+
+现有的引导加载程序:		可选、强烈建议
+新开发的引导加载程序:		强制
+
+引导加载程序必须提供标签列表或者 dtb 映像以传递配置数据给内核。启动
+数据的物理地址通过寄存器 r2 传递给内核。
+
+4a、设置内核标签列表
+--------------------------------
+
+bootloader 必须创建和初始化内核标签列表。一个有效的标签列表以
+ATAG_CORE 标签开始，并以 ATAG_NONE 标签结束。ATAG_CORE 标签可以是
+空的，也可以是非空。一个空 ATAG_CORE 标签其 size 域设置为
+‘2’(0x00000002)。ATAG_NONE 标签的 size 域必须设置为零。
+
+在列表中可以保存任意数量的标签。对于一个重复的标签是追加到之前标签
+所携带的信息之后，还是会覆盖原来的信息，是未定义的。某些标签的行为
+是前者，其他是后者。
+
+bootloader 必须传递一个系统内存的位置和最小值，以及根文件系统位置。
+因此，最小的标签列表如下所示：
+
+		+-----------+
+基地址 ->	| ATAG_CORE |  |
+		+-----------+  |
+		| ATAG_MEM  |  | 地址增长方向
+		+-----------+  |
+		| ATAG_NONE |  |
+		+-----------+  v
+
+标签列表应该保存在系统的 RAM 中。
+
+标签列表必须置于内核自解压和 initrd'bootp' 程序都不会覆盖的内存区。
+建议放在 RAM 的头 16KiB 中。
+
+4b、设置设备树
+-------------------------
+
+bootloader 必须以 64bit 地址对齐的形式加载一个设备树映像(dtb)到系统
+RAM 中，并用启动数据初始化它。dtb 格式在文档
+Documentation/devicetree/booting-without-of.txt 中。内核将会在
+dtb 物理地址处查找 dtb 魔数值（0xd00dfeed），以确定 dtb 是否已经代替
+标签列表被传递进来。
+
+bootloader 必须传递一个系统内存的位置和最小值，以及根文件系统位置。
+dtb 必须置于内核自解压不会覆盖的内存区。建议将其放置于 RAM 的头 16KiB
+中。但是不可将其放置于“0”物理地址处，因为内核认为：r2 中为 0，意味着
+没有标签列表和 dtb 传递过来。
+
+5、调用内核映像
+---------------------------
+
+现有的引导加载程序:		强制
+新开发的引导加载程序:		强制
+
+调用内核映像 zImage 有两个选择。如果 zImge 保存在 flash 中，且是为了
+在 flash 中直接运行而被正确链接的。这样引导加载程序就可以在 flash 中
+直接调用 zImage。
+
+zImage 也可以被放在系统 RAM（任意位置）中被调用。注意：内核使用映像
+基地址的前 16KB RAM 空间来保存页表。建议将映像置于 RAM 的 32KB 处。
+
+对于以上任意一种情况，都必须符合以下启动状态：
+
+- 停止所有 DMA 设备，这样内存数据就不会因为虚假网络包或磁盘数据而被破坏。
+  这可能可以节省你许多的调试时间。
+
+- CPU 寄存器配置
+  r0 = 0，
+  r1 = （在上面 3 中获取的）机器类型码。
+  r2 = 标签列表在系统 RAM 中的物理地址，或
+       设备树块(dtb)在系统 RAM 中的物理地址
+
+- CPU 模式
+  所有形式的中断必须被禁止 (IRQs 和 FIQs)
+  CPU 必须处于 SVC 模式。(对于 Angel 调试有特例存在)
+
+- 缓存，MMUs
+  MMU 必须关闭。
+  指令缓存开启或关闭都可以。
+  数据缓存必须关闭。
+
+- 引导加载程序应该通过直接跳转到内核映像的第一条指令来调用内核映像。
+
+  对于支持 ARM 指令集的 CPU，跳入内核入口时必须处在 ARM 状态，即使
+  对于 Thumb-2 内核也是如此。
+
+  对于仅支持 Thumb 指令集的 CPU，比如 Cortex-M 系列的 CPU，跳入
+  内核入口时必须处于 Thumb 状态。
diff --git a/Documentation/zh_CN/basic_profiling.txt b/Documentation/zh_CN/basic_profiling.txt
new file mode 100644
index 0000000..1e6bf0b
--- /dev/null
+++ b/Documentation/zh_CN/basic_profiling.txt
@@ -0,0 +1,71 @@
+Chinese translated version of Documentation/basic_profiling
+
+If you have any comment or update to the content, please post to LKML directly.
+However, if you have problem communicating in English you can also ask the
+Chinese maintainer for help.  Contact the Chinese maintainer, if this
+translation is outdated or there is problem with translation.
+
+Chinese maintainer: Liang Xie <xieliang@xiaomi.com>
+---------------------------------------------------------------------
+Documentation/basic_profiling的中文翻译
+
+如果想评论或更新本文的内容，请直接发信到LKML。如果你使用英文交流有困难的话，也可
+以向中文版维护者求助。如果本翻译更新不及时或者翻译存在问题，请联系中文版维护者。
+
+中文版维护者： 谢良 Liang Xie <xieliang007@gmail.com>
+中文版翻译者： 谢良 Liang Xie <xieliang007@gmail.com>
+中文版校译者：
+以下为正文
+---------------------------------------------------------------------
+
+下面这些说明指令都是非常基础的，如果你想进一步了解请阅读相关专业文档：）
+请不要再在本文档增加新的内容，但可以修复文档中的错误：）(mbligh@aracnet.com)
+感谢John Levon，Dave Hansen等在撰写时的帮助
+
+<test> 用于表示要测量的目标
+请先确保您已经有正确的System.map / vmlinux配置！
+
+对于linux系统来说，配置vmlinuz最容易的方法可能就是使用“make install”，然后修改
+/sbin/installkernel将vmlinux拷贝到/boot目录，而System.map通常是默认安装好的
+
+Readprofile
+-----------
+2.6系列内核需要版本相对较新的readprofile，比如util-linux 2.12a中包含的，可以从:
+
+http://www.kernel.org/pub/linux/utils/util-linux/ 下载
+
+大部分linux发行版已经包含了.
+
+启用readprofile需要在kernel启动命令行增加”profile=2“
+
+clear		readprofile -r
+		<test>
+dump output	readprofile -m /boot/System.map > captured_profile
+
+Oprofile
+--------
+
+从http://oprofile.sourceforge.net/获取源代码（请参考Changes以获取匹配的版本）
+在kernel启动命令行增加“idle=poll”
+
+配置CONFIG_PROFILING=y和CONFIG_OPROFILE=y然后重启进入新kernel
+
+./configure --with-kernel-support
+make install
+
+想得到好的测量结果，请确保启用了本地APIC特性。如果opreport显示有0Hz CPU，
+说明APIC特性没有开启。另外注意idle=poll选项可能有损性能。
+
+One time setup:
+		opcontrol --setup --vmlinux=/boot/vmlinux
+
+clear		opcontrol --reset
+start		opcontrol --start
+		<test>
+stop		opcontrol --stop
+dump output	opreport >  output_file
+
+如果只看kernel相关的报告结果，请运行命令 opreport -l /boot/vmlinux > output_file
+
+通过reset选项可以清理过期统计数据，相当于重启的效果。
+
diff --git a/Documentation/zh_CN/filesystems/sysfs.txt b/Documentation/zh_CN/filesystems/sysfs.txt
new file mode 100644
index 0000000..e230eaa
--- /dev/null
+++ b/Documentation/zh_CN/filesystems/sysfs.txt
@@ -0,0 +1,372 @@
+Chinese translated version of Documentation/filesystems/sysfs.txt
+
+If you have any comment or update to the content, please contact the
+original document maintainer directly.  However, if you have a problem
+communicating in English you can also ask the Chinese maintainer for
+help.  Contact the Chinese maintainer if this translation is outdated
+or if there is a problem with the translation.
+
+Maintainer: Patrick Mochel	<mochel@osdl.org>
+		Mike Murphy <mamurph@cs.clemson.edu>
+Chinese maintainer: Fu Wei <tekkamanninja@gmail.com>
+---------------------------------------------------------------------
+Documentation/filesystems/sysfs.txt 的中文翻译
+
+如果想评论或更新本文的内容，请直接联系原文档的维护者。如果你使用英文
+交流有困难的话，也可以向中文版维护者求助。如果本翻译更新不及时或者翻
+译存在问题，请联系中文版维护者。
+英文版维护者： Patrick Mochel	<mochel@osdl.org>
+		Mike Murphy <mamurph@cs.clemson.edu>
+中文版维护者： 傅炜 Fu Wei <tekkamanninja@gmail.com>
+中文版翻译者： 傅炜 Fu Wei <tekkamanninja@gmail.com>
+中文版校译者： 傅炜 Fu Wei <tekkamanninja@gmail.com>
+
+
+以下为正文
+---------------------------------------------------------------------
+sysfs - 用于导出内核对象(kobject)的文件系统
+
+Patrick Mochel	<mochel@osdl.org>
+Mike Murphy <mamurph@cs.clemson.edu>
+
+修订:    16 August 2011
+原始版本:   10 January 2003
+
+
+sysfs 简介:
+~~~~~~~~~~
+
+sysfs 是一个最初基于 ramfs 且位于内存的文件系统。它提供导出内核
+数据结构及其属性，以及它们之间的关联到用户空间的方法。
+
+sysfs 始终与 kobject 的底层结构紧密相关。请阅读
+Documentation/kobject.txt 文档以获得更多关于 kobject 接口的
+信息。
+
+
+使用 sysfs
+~~~~~~~~~~~
+
+只要内核配置中定义了 CONFIG_SYSFS ，sysfs 总是被编译进内核。你可
+通过以下命令挂载它:
+
+    mount -t sysfs sysfs /sys
+
+
+创建目录
+~~~~~~~~
+
+任何 kobject 在系统中注册，就会有一个目录在 sysfs 中被创建。这个
+目录是作为该 kobject 的父对象所在目录的子目录创建的，以准确地传递
+内核的对象层次到用户空间。sysfs 中的顶层目录代表着内核对象层次的
+共同祖先；例如：某些对象属于某个子系统。
+
+Sysfs 在与其目录关联的 sysfs_dirent 对象中内部保存一个指向实现
+目录的 kobject 的指针。以前，这个 kobject 指针被 sysfs 直接用于
+kobject 文件打开和关闭的引用计数。而现在的 sysfs 实现中，kobject
+引用计数只能通过 sysfs_schedule_callback() 函数直接修改。
+
+
+属性
+~~~~
+
+kobject 的属性可在文件系统中以普通文件的形式导出。Sysfs 为属性定义
+了面向文件 I/O 操作的方法，以提供对内核属性的读写。
+
+
+属性应为 ASCII 码文本文件。以一个文件只存储一个属性值为宜。但一个
+文件只包含一个属性值可能影响效率，所以一个包含相同数据类型的属性值
+数组也被广泛地接受。
+
+混合类型、表达多行数据以及一些怪异的数据格式会遭到强烈反对。这样做是
+很丢脸的,而且其代码会在未通知作者的情况下被重写。
+
+
+一个简单的属性结构定义如下:
+
+struct attribute {
+        char                    * name;
+        struct module		*owner;
+        umode_t                 mode;
+};
+
+
+int sysfs_create_file(struct kobject * kobj, const struct attribute * attr);
+void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr);
+
+
+一个单独的属性结构并不包含读写其属性值的方法。子系统最好为增删特定
+对象类型的属性定义自己的属性结构体和封装函数。
+
+例如:驱动程序模型定义的 device_attribute 结构体如下:
+
+struct device_attribute {
+	struct attribute	attr;
+	ssize_t (*show)(struct device *dev, struct device_attribute *attr,
+			char *buf);
+	ssize_t (*store)(struct device *dev, struct device_attribute *attr,
+			 const char *buf, size_t count);
+};
+
+int device_create_file(struct device *, const struct device_attribute *);
+void device_remove_file(struct device *, const struct device_attribute *);
+
+为了定义设备属性，同时定义了一下辅助宏:
+
+#define DEVICE_ATTR(_name, _mode, _show, _store) \
+struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store)
+
+例如:声明
+
+static DEVICE_ATTR(foo, S_IWUSR | S_IRUGO, show_foo, store_foo);
+
+等同于如下代码：
+
+static struct device_attribute dev_attr_foo = {
+       .attr	= {
+		.name = "foo",
+		.mode = S_IWUSR | S_IRUGO,
+		.show = show_foo,
+		.store = store_foo,
+	},
+};
+
+
+子系统特有的回调函数
+~~~~~~~~~~~~~~~~~~~
+
+当一个子系统定义一个新的属性类型时，必须实现一系列的 sysfs 操作，
+以帮助读写调用实现属性所有者的显示和储存方法。
+
+struct sysfs_ops {
+        ssize_t (*show)(struct kobject *, struct attribute *, char *);
+        ssize_t (*store)(struct kobject *, struct attribute *, const char *, size_t);
+};
+
+[子系统应已经定义了一个 struct kobj_type 结构体作为这个类型的
+描述符，并在此保存 sysfs_ops 的指针。更多的信息参见 kobject 的
+文档]
+
+sysfs 会为这个类型调用适当的方法。当一个文件被读写时，这个方法会
+将一般的kobject 和 attribute 结构体指针转换为适当的指针类型后
+调用相关联的函数。
+
+
+示例:
+
+#define to_dev(obj) container_of(obj, struct device, kobj)
+#define to_dev_attr(_attr) container_of(_attr, struct device_attribute, attr)
+
+static ssize_t dev_attr_show(struct kobject *kobj, struct attribute *attr,
+                             char *buf)
+{
+        struct device_attribute *dev_attr = to_dev_attr(attr);
+        struct device *dev = to_dev(kobj);
+        ssize_t ret = -EIO;
+
+        if (dev_attr->show)
+                ret = dev_attr->show(dev, dev_attr, buf);
+        if (ret >= (ssize_t)PAGE_SIZE) {
+                print_symbol("dev_attr_show: %s returned bad count\n",
+                                (unsigned long)dev_attr->show);
+        }
+        return ret;
+}
+
+
+
+读写属性数据
+~~~~~~~~~~~~
+
+在声明属性时，必须指定 show() 或 store() 方法，以实现属性的
+读或写。这些方法的类型应该和以下的设备属性定义一样简单。
+
+ssize_t (*show)(struct device *dev, struct device_attribute *attr, char *buf);
+ssize_t (*store)(struct device *dev, struct device_attribute *attr,
+                 const char *buf, size_t count);
+
+也就是说,他们应只以一个处理对象、一个属性和一个缓冲指针作为参数。
+
+sysfs 会分配一个大小为 (PAGE_SIZE) 的缓冲区并传递给这个方法。
+Sysfs 将会为每次读写操作调用一次这个方法。这使得这些方法在执行时
+会出现以下的行为:
+
+- 在读方面（read(2)），show() 方法应该填充整个缓冲区。回想属性
+  应只导出了一个属性值或是一个同类型属性值的数组，所以这个代价将
+  不会不太高。
+
+  这使得用户空间可以局部地读和任意的向前搜索整个文件。如果用户空间
+  向后搜索到零或使用‘0’偏移执行一个pread(2)操作，show()方法将
+  再次被调用，以重新填充缓存。
+
+- 在写方面（write(2)），sysfs 希望在第一次写操作时得到整个缓冲区。
+  之后 Sysfs 传递整个缓冲区给 store() 方法。
+
+  当要写 sysfs 文件时，用户空间进程应首先读取整个文件，修该想要
+  改变的值，然后回写整个缓冲区。
+
+  在读写属性值时，属性方法的执行应操作相同的缓冲区。
+
+注记:
+
+- 写操作导致的 show() 方法重载，会忽略当前文件位置。
+
+- 缓冲区应总是 PAGE_SIZE 大小。对于i386，这个值为4096。
+
+- show() 方法应该返回写入缓冲区的字节数，也就是 snprintf()的
+  返回值。
+
+- show() 应始终使用 snprintf()。
+
+- store() 应返回缓冲区的已用字节数。如果整个缓存都已填满，只需返回
+  count 参数。
+
+- show() 或 store() 可以返回错误值。当得到一个非法值，必须返回一个
+  错误值。
+
+- 一个传递给方法的对象将会通过 sysfs 调用对象内嵌的引用计数固定在
+  内存中。尽管如此，对象代表的物理实体(如设备)可能已不存在。如有必要，
+  应该实现一个检测机制。
+
+一个简单的(未经实验证实的)设备属性实现如下：
+
+static ssize_t show_name(struct device *dev, struct device_attribute *attr,
+                         char *buf)
+{
+	return scnprintf(buf, PAGE_SIZE, "%s\n", dev->name);
+}
+
+static ssize_t store_name(struct device *dev, struct device_attribute *attr,
+                          const char *buf, size_t count)
+{
+        snprintf(dev->name, sizeof(dev->name), "%.*s",
+                 (int)min(count, sizeof(dev->name) - 1), buf);
+	return count;
+}
+
+static DEVICE_ATTR(name, S_IRUGO, show_name, store_name);
+
+
+（注意：真正的实现不允许用户空间设置设备名。）
+
+顶层目录布局
+~~~~~~~~~~~~
+
+sysfs 目录的安排显示了内核数据结构之间的关系。
+
+顶层 sysfs 目录如下:
+
+block/
+bus/
+class/
+dev/
+devices/
+firmware/
+net/
+fs/
+
+devices/ 包含了一个设备树的文件系统表示。他直接映射了内部的内核
+设备树，反映了设备的层次结构。
+
+bus/ 包含了内核中各种总线类型的平面目录布局。每个总线目录包含两个
+子目录:
+
+	devices/
+	drivers/
+
+devices/ 包含了系统中出现的每个设备的符号链接，他们指向 root/ 下的
+设备目录。
+
+drivers/ 包含了每个已为特定总线上的设备而挂载的驱动程序的目录(这里
+假定驱动没有跨越多个总线类型)。
+
+fs/ 包含了一个为文件系统设立的目录。现在每个想要导出属性的文件系统必须
+在 fs/ 下创建自己的层次结构(参见Documentation/filesystems/fuse.txt)。
+
+dev/ 包含两个子目录： char/ 和 block/。在这两个子目录中，有以
+<major>:<minor> 格式命名的符号链接。这些符号链接指向 sysfs 目录
+中相应的设备。/sys/dev 提供一个通过一个 stat(2) 操作结果，查找
+设备 sysfs 接口快捷的方法。
+
+更多有关 driver-model 的特性信息可以在 Documentation/driver-model/
+中找到。
+
+
+TODO: 完成这一节。
+
+
+当前接口
+~~~~~~~~
+
+以下的接口层普遍存在于当前的sysfs中:
+
+- 设备 (include/linux/device.h)
+----------------------------------
+结构体:
+
+struct device_attribute {
+	struct attribute	attr;
+	ssize_t (*show)(struct device *dev, struct device_attribute *attr,
+			char *buf);
+	ssize_t (*store)(struct device *dev, struct device_attribute *attr,
+			 const char *buf, size_t count);
+};
+
+声明:
+
+DEVICE_ATTR(_name, _mode, _show, _store);
+
+增/删属性:
+
+int device_create_file(struct device *dev, const struct device_attribute * attr);
+void device_remove_file(struct device *dev, const struct device_attribute * attr);
+
+
+- 总线驱动程序 (include/linux/device.h)
+--------------------------------------
+结构体:
+
+struct bus_attribute {
+        struct attribute        attr;
+        ssize_t (*show)(struct bus_type *, char * buf);
+        ssize_t (*store)(struct bus_type *, const char * buf, size_t count);
+};
+
+声明:
+
+BUS_ATTR(_name, _mode, _show, _store)
+
+增/删属性:
+
+int bus_create_file(struct bus_type *, struct bus_attribute *);
+void bus_remove_file(struct bus_type *, struct bus_attribute *);
+
+
+- 设备驱动程序 (include/linux/device.h)
+-----------------------------------------
+
+结构体:
+
+struct driver_attribute {
+        struct attribute        attr;
+        ssize_t (*show)(struct device_driver *, char * buf);
+        ssize_t (*store)(struct device_driver *, const char * buf,
+                         size_t count);
+};
+
+声明:
+
+DRIVER_ATTR(_name, _mode, _show, _store)
+
+增/删属性：
+
+int driver_create_file(struct device_driver *, const struct driver_attribute *);
+void driver_remove_file(struct device_driver *, const struct driver_attribute *);
+
+
+文档
+~~~~
+
+sysfs 目录结构以及其中包含的属性定义了一个内核与用户空间之间的 ABI。
+对于任何 ABI，其自身的稳定和适当的文档是非常重要的。所有新的 sysfs
+属性必须在 Documentation/ABI 中有文档。详见 Documentation/ABI/README。
diff --git a/Documentation/zh_CN/gpio.txt b/Documentation/zh_CN/gpio.txt
new file mode 100644
index 0000000..0484387
--- /dev/null
+++ b/Documentation/zh_CN/gpio.txt
@@ -0,0 +1,662 @@
+Chinese translated version of Documentation/gpio.txt
+
+If you have any comment or update to the content, please contact the
+original document maintainer directly.  However, if you have a problem
+communicating in English you can also ask the Chinese maintainer for
+help.  Contact the Chinese maintainer if this translation is outdated
+or if there is a problem with the translation.
+
+Maintainer: Grant Likely <grant.likely@secretlab.ca>
+		Linus Walleij <linus.walleij@linaro.org>
+Chinese maintainer: Fu Wei <tekkamanninja@gmail.com>
+---------------------------------------------------------------------
+Documentation/gpio.txt 的中文翻译
+
+如果想评论或更新本文的内容，请直接联系原文档的维护者。如果你使用英文
+交流有困难的话，也可以向中文版维护者求助。如果本翻译更新不及时或者翻
+译存在问题，请联系中文版维护者。
+英文版维护者： Grant Likely <grant.likely@secretlab.ca>
+		Linus Walleij <linus.walleij@linaro.org>
+中文版维护者： 傅炜 Fu Wei <tekkamanninja@gmail.com>
+中文版翻译者： 傅炜 Fu Wei <tekkamanninja@gmail.com>
+中文版校译者： 傅炜 Fu Wei <tekkamanninja@gmail.com>
+
+
+以下为正文
+---------------------------------------------------------------------
+GPIO 接口
+
+本文档提供了一个在Linux下访问GPIO的公约概述。
+
+这些函数以 gpio_* 作为前缀。其他的函数不允许使用这样的前缀或相关的
+__gpio_* 前缀。
+
+
+什么是GPIO?
+==========
+"通用输入/输出口"(GPIO)是一个灵活的由软件控制的数字信号。他们可
+由多种芯片提供,且对于从事嵌入式和定制硬件的 Linux 开发者来说是
+比较熟悉。每个GPIO 都代表一个连接到特定引脚或球栅阵列(BGA)封装中
+“球珠”的一个位。电路板原理图显示了 GPIO 与外部硬件的连接关系。
+驱动可以编写成通用代码，以使板级启动代码可传递引脚配置数据给驱动。
+
+片上系统 (SOC) 处理器对 GPIO 有很大的依赖。在某些情况下,每个
+非专用引脚都可配置为 GPIO,且大多数芯片都最少有一些 GPIO。
+可编程逻辑器件(类似 FPGA) 可以方便地提供 GPIO。像电源管理和
+音频编解码器这样的多功能芯片经常留有一些这样的引脚来帮助那些引脚
+匮乏的 SOC。同时还有通过 I2C 或 SPI 串行总线连接的“GPIO扩展器”
+芯片。大多数 PC 的南桥有一些拥有 GPIO 能力的引脚 (只有BIOS
+固件才知道如何使用他们)。
+
+GPIO 的实际功能因系统而异。通常用法有:
+
+  - 输出值可写 (高电平=1，低电平=0)。一些芯片也有如何驱动这些值的选项,
+    例如只允许输出一个值、支持“线与”及其他取值类似的模式(值得注意的是
+    “开漏”信号)
+
+  - 输入值可读(1、0)。一些芯片支持引脚在配置为“输出”时回读，这对于类似
+    “线与”的情况(以支持双向信号)是非常有用的。GPIO 控制器可能有输入
+    去毛刺/消抖逻辑,这有时需要软件控制。
+
+  - 输入通常可作为 IRQ 信号,一般是沿触发,但有时是电平触发。这样的 IRQ
+    可能配置为系统唤醒事件,以将系统从低功耗状态下唤醒。
+
+  - 通常一个 GPIO 根据不同产品电路板的需求,可以配置为输入或输出,也有仅
+    支持单向的。
+
+  - 大部分 GPIO 可以在持有自旋锁时访问,但是通常由串行总线扩展的 GPIO
+    不允许持有自旋锁。但某些系统也支持这种类型。
+
+对于给定的电路板,每个 GPIO 都用于某个特定的目的,如监控 MMC/SD 卡的
+插入/移除、检测卡的写保护状态、驱动 LED、配置收发器、模拟串行总线、
+复位硬件看门狗、感知开关状态等等。
+
+
+GPIO 公约
+=========
+注意,这个叫做“公约”，因为这不是强制性的，不遵循这个公约是无伤大雅的，
+因为此时可移植性并不重要。GPIO 常用于板级特定的电路逻辑,甚至可能
+随着电路板的版本而改变，且不可能在不同走线的电路板上使用。仅有在少数
+功能上才具有可移植性，其他功能是平台特定。这也是由于“胶合”的逻辑造成的。
+
+此外，这不需要任何的执行框架，只是一个接口。某个平台可能通过一个简单地
+访问芯片寄存器的内联函数来实现它，其他平台可能通过委托一系列不同的GPIO
+控制器的抽象函数来实现它。(有一些可选的代码能支持这种策略的实现,本文档
+后面会介绍，但作为 GPIO 接口的客户端驱动程序必须与它的实现无关。)
+
+也就是说,如果在他们的平台上支持这个公约，驱动应尽可能的使用它。平台
+必须在 Kconfig 中声明对 GENERIC_GPIO的支持 (布尔型 true)，并提供
+一个 <asm/gpio.h> 文件。那些调用标准 GPIO 函数的驱动应该在 Kconfig
+入口中声明依赖GENERIC_GPIO。当驱动包含文件:
+
+	#include <linux/gpio.h>
+
+则 GPIO 函数是可用,无论是“真实代码”还是经优化过的语句。如果你遵守
+这个公约，当你的代码完成后，对其他的开发者来说会更容易看懂和维护。
+
+注意，这些操作包含所用平台的 I/O 屏障代码，驱动无须显式地调用他们。
+
+
+标识 GPIO
+---------
+GPIO 是通过无符号整型来标识的,范围是 0 到 MAX_INT。保留“负”数
+用于其他目的,例如标识信号“在这个板子上不可用”或指示错误。未接触底层
+硬件的代码会忽略这些整数。
+
+平台会定义这些整数的用法,且通常使用 #define 来定义 GPIO，这样
+板级特定的启动代码可以直接关联相应的原理图。相对来说，驱动应该仅使用
+启动代码传递过来的 GPIO 编号，使用 platform_data 保存板级特定
+引脚配置数据 (同时还有其他须要的板级特定数据)，避免可能出现的问题。
+
+例如一个平台使用编号 32-159 来标识 GPIO,而在另一个平台使用编号0-63
+标识一组 GPIO 控制器,64-79标识另一类 GPIO 控制器,且在一个含有
+FPGA 的特定板子上使用 80-95。编号不一定要连续,那些平台中，也可以
+使用编号2000-2063来标识一个 I2C 接口的 GPIO 扩展器中的 GPIO。
+
+如果你要初始化一个带有无效 GPIO 编号的结构体,可以使用一些负编码
+(如"-EINVAL")，那将使其永远不会是有效。来测试这样一个结构体中的编号
+是否关联一个 GPIO，你可使用以下断言:
+
+	int gpio_is_valid(int number);
+
+如果编号不存在，则请求和释放 GPIO 的函数将拒绝执行相关操作(见下文)。
+其他编号也可能被拒绝,比如一个编号可能存在，但暂时在给定的电路上不可用。
+
+一个平台是否支持多个 GPIO 控制器为平台特定的实现问题，就像是否可以
+在 GPIO 编号空间中有“空洞”和是否可以在运行时添加新的控制器一样。
+这些问题会影响其他事情，包括相邻的 GPIO 编号是否存在等。
+
+使用 GPIO
+---------
+对于一个 GPIO，系统应该做的第一件事情就是通过 gpio_request()
+函数分配他，见下文。
+
+而接下来要做的是标识它的方向，这通常是在板级启动代码中为 GPIO 设置
+一个 platform_device 时做的。
+
+	/* 设置为输入或输出, 返回 0 或负的错误代码 */
+	int gpio_direction_input(unsigned gpio);
+	int gpio_direction_output(unsigned gpio, int value);
+
+返回值为零代表成功，否则返回一个负的错误代码。这个返回值需要检查，因为
+get/set(获取/设置)函数调用没法返回错误,且有可能是配置错误。通常，
+你应该在进程上下文中调用这些函数。然而,对于自旋锁安全的 GPIO，在板子
+启动的早期、进程启动前使用他们也是可以的。
+
+对于作为输出的 GPIO，为其提供初始输出值，对于避免在系统启动期间出现
+信号毛刺是很有帮助的。
+
+为了与传统的 GPIO 接口兼容, 在设置一个 GPIO 方向时，如果它还未被申请，
+则隐含了申请那个 GPIO 的操作(见下文)。这种兼容性正在从可选的 gpiolib
+框架中移除。
+
+如果这个 GPIO 编码不存在，或者特定的 GPIO 不能用于那种模式，则方向
+设置可能失败。依赖启动固件来正确地设置方向通常是一个坏主意，因为它可能
+除了启动Linux，并没有做更多的验证工作。(同理, 板子的启动代码可能需要
+将这个复用的引脚设置为 GPIO，并正确地配置上拉/下拉电阻。)
+
+
+访问自旋锁安全的 GPIO
+-------------------
+大多数 GPIO 控制器可以通过内存读/写指令来访问。这些指令不会休眠,可以
+安全地在硬(非线程)中断例程和类似的上下文中完成。
+
+对于那些用 gpio_cansleep()测试总是返回失败的 GPIO(见下文)，使用
+以下的函数访问:
+
+	/* GPIO 输入:返回零或非零 */
+	int gpio_get_value(unsigned gpio);
+
+	/* GPIO 输入 */
+	void gpio_set_value(unsigned gpio, int value);
+
+返回值是布尔值，零表示低电平，非零表示高电平。当读取一个输出引脚的值时，
+返回值应该是引脚上的值。这个值不总是和输出值相符，因为存在开漏输出信号和
+输出潜伏期的问题。
+
+以上的 get/set 函数不会对早期已经通过 gpio_direction_*()报告“无效的
+GPIO”返回错误。此外,还需要注意的是并不是所有平台都可以从输出引脚中读取
+数据的，那些引脚也不总是返回零。且对那些无法安全访问(可能会休眠)的 GPIO
+(见下文)使用这些函数是错误的。
+
+在 GPIO 编号(还有输出、值)为常数的情况下,鼓励通过平台特定的实现来优化
+这两个函数来访问 GPIO 值。这种情况(读写一个硬件寄存器)下只需要几条指令
+是很正常的,且无须自旋锁。这种优化函数比起那些在子程序上花费许多指令的
+函数可以使得模拟接口(译者注:例如 GPIO 模拟 I2C、1-wire 或 SPI)的
+应用(在空间和时间上都)更具效率。
+
+
+访问可能休眠的 GPIO
+-----------------
+某些 GPIO 控制器必须通过基于总线(如 I2C 或 SPI)的消息访问。读或写这些
+GPIO 值的命令需要等待其信息排到队首才发送命令，再获得其反馈。期间需要
+休眠，这不能在 IRQ 例程(中断上下文)中执行。
+
+支持此类 GPIO 的平台通过以下函数返回非零值来区分出这种 GPIO。(此函数需要
+一个之前通过 gpio_request 分配到的有效 GPIO 编号):
+
+	int gpio_cansleep(unsigned gpio);
+
+为了访问这种 GPIO,内核定义了一套不同的函数:
+
+	/* GPIO 输入:返回零或非零 ,可能会休眠 */
+	int gpio_get_value_cansleep(unsigned gpio);
+
+	/* GPIO 输入,可能会休眠 */
+	void gpio_set_value_cansleep(unsigned gpio, int value);
+
+
+访问这样的 GPIO 需要一个允许休眠的上下文，例如线程 IRQ 处理例程，并用以上的
+访问函数替换那些没有 cansleep()后缀的自旋锁安全访问函数。
+
+除了这些访问函数可能休眠，且它们操作的 GPIO 不能在硬件 IRQ 处理例程中访问的
+事实，这些处理例程实际上和自旋锁安全的函数是一样的。
+
+** 除此之外 ** 调用设置和配置此类 GPIO 的函数也必须在允许休眠的上下文中，
+因为它们可能也需要访问 GPIO 控制器芯片: (这些设置函数通常在板级启动代码或者
+驱动探测/断开代码中，所以这是一个容易满足的约束条件。)
+
+	gpio_direction_input()
+	gpio_direction_output()
+	gpio_request()
+
+## 	gpio_request_one()
+##	gpio_request_array()
+## 	gpio_free_array()
+
+	gpio_free()
+	gpio_set_debounce()
+
+
+
+声明和释放 GPIO
+----------------------------
+为了有助于捕获系统配置错误,定义了两个函数。
+
+	/* 申请 GPIO, 返回 0 或负的错误代码.
+	 * 非空标签可能有助于诊断.
+	 */
+	int gpio_request(unsigned gpio, const char *label);
+
+	/* 释放之前声明的 GPIO */
+	void gpio_free(unsigned gpio);
+
+将无效的 GPIO 编码传递给 gpio_request()会导致失败，申请一个已使用这个
+函数声明过的 GPIO 也会失败。gpio_request()的返回值必须检查。你应该在
+进程上下文中调用这些函数。然而,对于自旋锁安全的 GPIO,在板子启动的早期、
+进入进程之前是可以申请的。
+
+这个函数完成两个基本的目标。一是标识那些实际上已作为 GPIO 使用的信号线，
+这样便于更好地诊断;系统可能需要服务几百个潜在的 GPIO，但是对于任何一个
+给定的电路板通常只有一些被使用。另一个目的是捕获冲突，查明错误:如两个或
+更多驱动错误地认为他们已经独占了某个信号线,或是错误地认为移除一个管理着
+某个已激活信号的驱动是安全的。也就是说，申请 GPIO 的作用类似一种锁机制。
+
+某些平台可能也使用 GPIO 作为电源管理激活信号(例如通过关闭未使用芯片区和
+简单地关闭未使用时钟)。
+
+对于 GPIO 使用 pinctrl 子系统已知的引脚，子系统应该被告知其使用情况；
+一个 gpiolib 驱动的 .request()操作应调用 pinctrl_request_gpio()，
+而 gpiolib 驱动的 .free()操作应调用 pinctrl_free_gpio()。pinctrl
+子系统允许 pinctrl_request_gpio()在某个引脚或引脚组以复用形式“属于”
+一个设备时都成功返回。
+
+任何须将 GPIO 信号导向适当引脚的引脚复用硬件的编程应该发生在 GPIO
+驱动的 .direction_input()或 .direction_output()函数中，以及
+任何输出 GPIO 值的设置之后。这样可使从引脚特殊功能到 GPIO 的转换
+不会在引脚产生毛刺波形。有时当用一个 GPIO 实现其信号驱动一个非 GPIO
+硬件模块的解决方案时，就需要这种机制。
+
+某些平台允许部分或所有 GPIO 信号使用不同的引脚。类似的，GPIO 或引脚的
+其他方面也需要配置，如上拉/下拉。平台软件应该在对这些 GPIO 调用
+gpio_request()前将这类细节配置好，例如使用 pinctrl 子系统的映射表，
+使得 GPIO 的用户无须关注这些细节。
+
+还有一个值得注意的是在释放 GPIO 前，你必须停止使用它。
+
+
+注意:申请一个 GPIO 并没有以任何方式配置它，只不过标识那个 GPIO 处于使用
+状态。必须有另外的代码来处理引脚配置(如控制 GPIO 使用的引脚、上拉/下拉)。
+考虑到大多数情况下声明 GPIO 之后就会立即配置它们,所以定义了以下三个辅助函数:
+
+	/* 申请一个 GPIO 信号, 同时通过特定的'flags'初始化配置,
+	 * 其他和 gpio_request()的参数和返回值相同
+	 *
+	 */
+	int gpio_request_one(unsigned gpio, unsigned long flags, const char *label);
+
+	/* 在单个函数中申请多个 GPIO
+	 */
+	int gpio_request_array(struct gpio *array, size_t num);
+
+	/* 在单个函数中释放多个 GPIO
+	 */
+	void gpio_free_array(struct gpio *array, size_t num);
+
+这里 'flags' 当前定义可指定以下属性:
+
+	* GPIOF_DIR_IN		- 配置方向为输入
+	* GPIOF_DIR_OUT		- 配置方向为输出
+
+	* GPIOF_INIT_LOW	- 在作为输出时,初始值为低电平
+	* GPIOF_INIT_HIGH	- 在作为输出时,初始值为高电平
+	* GPIOF_OPEN_DRAIN	- gpio引脚为开漏信号
+	* GPIOF_OPEN_SOURCE	- gpio引脚为源极开路信号
+
+	* GPIOF_EXPORT_DIR_FIXED	- 将 gpio 导出到 sysfs，并保持方向
+	* GPIOF_EXPORT_DIR_CHANGEABLE	- 同样是导出, 但允许改变方向
+
+因为 GPIOF_INIT_* 仅有在配置为输出的时候才存在,所以有效的组合为:
+
+	* GPIOF_IN		- 配置为输入
+	* GPIOF_OUT_INIT_LOW	- 配置为输出,并初始化为低电平
+	* GPIOF_OUT_INIT_HIGH	- 配置为输出,并初始化为高电平
+
+当设置 flag 为 GPIOF_OPEN_DRAIN 时，则假设引脚是开漏信号。这样的引脚
+将不会在输出模式下置1。这样的引脚需要连接上拉电阻。通过使能这个标志，gpio库
+将会在被要求输出模式下置1时将引脚变为输入状态来使引脚置高。引脚在输出模式下
+通过置0使其输出低电平。
+
+当设置 flag 为 GPIOF_OPEN_SOURCE 时，则假设引脚为源极开路信号。这样的引脚
+将不会在输出模式下置0。这样的引脚需要连接下拉电阻。通过使能这个标志，gpio库
+将会在被要求输出模式下置0时将引脚变为输入状态来使引脚置低。引脚在输出模式下
+通过置1使其输出高电平。
+
+将来这些标志可能扩展到支持更多的属性。
+
+更进一步,为了更简单地声明/释放多个 GPIO,'struct gpio'被引进来封装所有
+这三个领域:
+
+	struct gpio {
+		unsigned	gpio;
+		unsigned long	flags;
+		const char	*label;
+	};
+
+一个典型的用例:
+
+	static struct gpio leds_gpios[] = {
+		{ 32, GPIOF_OUT_INIT_HIGH, "Power LED" }, /* 默认开启 */
+		{ 33, GPIOF_OUT_INIT_LOW,  "Green LED" }, /* 默认关闭 */
+		{ 34, GPIOF_OUT_INIT_LOW,  "Red LED"   }, /* 默认关闭 */
+		{ 35, GPIOF_OUT_INIT_LOW,  "Blue LED"  }, /* 默认关闭 */
+		{ ... },
+	};
+
+	err = gpio_request_one(31, GPIOF_IN, "Reset Button");
+	if (err)
+		...
+
+	err = gpio_request_array(leds_gpios, ARRAY_SIZE(leds_gpios));
+	if (err)
+		...
+
+	gpio_free_array(leds_gpios, ARRAY_SIZE(leds_gpios));
+
+
+GPIO 映射到 IRQ
+--------------------
+GPIO 编号是无符号整数;IRQ 编号也是。这些构成了两个逻辑上不同的命名空间
+(GPIO 0 不一定使用 IRQ 0)。你可以通过以下函数在它们之间实现映射:
+
+	/* 映射 GPIO 编号到 IRQ 编号 */
+	int gpio_to_irq(unsigned gpio);
+
+	/* 映射 IRQ 编号到 GPIO 编号 (尽量避免使用) */
+	int irq_to_gpio(unsigned irq);
+
+它们的返回值为对应命名空间的相关编号，或是负的错误代码(如果无法映射)。
+(例如,某些 GPIO 无法做为 IRQ 使用。)以下的编号错误是未经检测的:使用一个
+未通过 gpio_direction_input()配置为输入的 GPIO 编号，或者使用一个
+并非来源于gpio_to_irq()的 IRQ 编号。
+
+这两个映射函数可能会在信号编号的加减计算过程上花些时间。它们不可休眠。
+
+gpio_to_irq()返回的非错误值可以传递给 request_irq()或者 free_irq()。
+它们通常通过板级特定的初始化代码存放到平台设备的 IRQ 资源中。注意:IRQ
+触发选项是 IRQ 接口的一部分，如 IRQF_TRIGGER_FALLING，系统唤醒能力
+也是如此。
+
+irq_to_gpio()返回的非错误值大多数通常可以被 gpio_get_value()所使用，
+比如在 IRQ 是沿触发时初始化或更新驱动状态。注意某些平台不支持反映射,所以
+你应该尽量避免使用它。
+
+它们的返回值为对应命名空间的相关编号，或是负的错误代码(如果无法映射)。
+(例如,某些 GPIO 无法做为 IRQ 使用。)以下的编号错误是未经检测的：
+使用一个未通过 gpio_direction_input()配置为输入的 GPIO 编号，
+或者使用一个并非来源于gpio_to_irq()的 IRQ 编号。
+
+
+模拟开漏信号
+----------------------------
+有时在只有低电平信号作为实际驱动结果(译者注:多个输出连接于一点，逻辑电平
+结果为所有输出的逻辑与)的时候,共享的信号线需要使用“开漏”信号。(该术语
+适用于 CMOS 管；而 TTL 用“集电极开路”。)一个上拉电阻使信号为高电平。这
+有时被称为“线与”。实际上，从负逻辑(低电平为真)的角度来看，这是一个“线或”。
+
+一个开漏信号的常见例子是共享的低电平使能 IRQ 信号线。此外,有时双向数据总线
+信号也使用漏极开路信号。
+
+某些 GPIO 控制器直接支持开漏输出，还有许多不支持。当你需要开漏信号，但
+硬件又不直接支持的时候，一个常用的方法是用任何即可作输入也可作输出的 GPIO
+引脚来模拟:
+
+ LOW:	gpio_direction_output(gpio, 0) ... 这代码驱动信号并覆盖
+	上拉配置。
+
+ HIGH:	gpio_direction_input(gpio) ... 这代码关闭输出,所以上拉电阻
+	(或其他的一些器件)控制了信号。
+
+如果你将信号线“驱动”为高电平，但是 gpio_get_value(gpio)报告了一个
+低电平(在适当的上升时间后)，你就可以知道是其他的一些组件将共享信号线拉低了。
+这不一定是错误的。一个常见的例子就是 I2C 时钟的延长：一个需要较慢时钟的
+从设备延迟 SCK 的上升沿，而 I2C 主设备相应地调整其信号传输速率。
+
+
+这些公约忽略了什么?
+================
+这些公约忽略的最大一件事就是引脚复用，因为这属于高度芯片特定的属性且
+没有可移植性。某个平台可能不需要明确的复用信息；有的对于任意给定的引脚
+可能只有两个功能选项；有的可能每个引脚有八个功能选项；有的可能可以将
+几个引脚中的任何一个作为给定的 GPIO。(是的，这些例子都来自于当前运行
+Linux 的系统。)
+
+在某些系统中,与引脚复用相关的是配置和使能集成的上、下拉模式。并不是所有
+平台都支持这种模式,或者不会以相同的方式来支持这种模式；且任何给定的电路板
+可能使用外置的上拉(或下拉)电阻,这时芯片上的就不应该使用。(当一个电路需要
+5kOhm 的拉动电阻,芯片上的 100 kOhm 电阻就不能做到。)同样的，驱动能力
+(2 mA vs 20 mA)和电压(1.8V vs 3.3V)是平台特定问题,就像模型一样在
+可配置引脚和 GPIO 之间(没)有一一对应的关系。
+
+还有其他一些系统特定的机制没有在这里指出，例如上述的输入去毛刺和线与输出
+选项。硬件可能支持批量读或写 GPIO，但是那一般是配置相关的：对于处于同一
+块区(bank)的GPIO。(GPIO 通常以 16 或 32 个组成一个区块，一个给定的
+片上系统一般有几个这样的区块。)某些系统可以通过输出 GPIO 触发 IRQ，
+或者从并非以 GPIO 管理的引脚取值。这些机制的相关代码没有必要具有可移植性。
+
+当前，动态定义 GPIO 并不是标准的，例如作为配置一个带有某些 GPIO 扩展器的
+附加电路板的副作用。
+
+GPIO 实现者的框架 (可选)
+=====================
+前面提到了，有一个可选的实现框架，让平台使用相同的编程接口，更加简单地支持
+不同种类的 GPIO 控制器。这个框架称为"gpiolib"。
+
+作为一个辅助调试功能，如果 debugfs 可用，就会有一个 /sys/kernel/debug/gpio
+文件。通过这个框架，它可以列出所有注册的控制器,以及当前正在使用中的 GPIO
+的状态。
+
+
+控制器驱动: gpio_chip
+-------------------
+在框架中每个 GPIO 控制器都包装为一个 "struct gpio_chip"，他包含了
+该类型的每个控制器的常用信息:
+
+ - 设置 GPIO 方向的方法
+ - 用于访问 GPIO 值的方法
+ - 告知调用其方法是否可能休眠的标志
+ - 可选的 debugfs 信息导出方法 (显示类似上拉配置一样的额外状态)
+ - 诊断标签
+
+也包含了来自 device.platform_data 的每个实例的数据：它第一个 GPIO 的
+编号和它可用的 GPIO 的数量。
+
+实现 gpio_chip 的代码应支持多控制器实例，这可能使用驱动模型。那些代码要
+配置每个 gpio_chip，并发起gpiochip_add()。卸载一个 GPIO 控制器很少见，
+但在必要的时候可以使用 gpiochip_remove()。
+
+大部分 gpio_chip 是一个实例特定结构体的一部分，而并不将 GPIO 接口单独
+暴露出来,比如编址、电源管理等。类似编解码器这样的芯片会有复杂的非 GPIO
+状态。
+
+任何一个 debugfs 信息导出方法通常应该忽略还未申请作为 GPIO 的信号线。
+他们可以使用 gpiochip_is_requested()测试，当这个 GPIO 已经申请过了
+就返回相关的标签，否则返回 NULL。
+
+
+平台支持
+-------
+为了支持这个框架，一个平台的 Kconfig 文件将会 "select"(选择)
+ARCH_REQUIRE_GPIOLIB 或 ARCH_WANT_OPTIONAL_GPIOLIB，并让它的
+<asm/gpio.h> 包含 <asm-generic/gpio.h>，同时定义三个方法:
+gpio_get_value()、gpio_set_value()和 gpio_cansleep()。
+
+它也应提供一个 ARCH_NR_GPIOS 的定义值，这样可以更好地反映该平台 GPIO
+的实际数量,节省静态表的空间。(这个定义值应该包含片上系统内建 GPIO 和
+GPIO 扩展器中的数据。)
+
+ARCH_REQUIRE_GPIOLIB 意味着 gpiolib 核心在这个构架中将总是编译进内核。
+
+ARCH_WANT_OPTIONAL_GPIOLIB 意味着 gpiolib 核心默认关闭,且用户可以
+使能它,并将其编译进内核(可选)。
+
+如果这些选项都没被选择,该平台就不通过 GPIO-lib 支持 GPIO,且代码不可以
+被用户使能。
+
+以下这些方法的实现可以直接使用框架代码,并总是通过 gpio_chip 调度:
+
+  #define gpio_get_value	__gpio_get_value
+  #define gpio_set_value	__gpio_set_value
+  #define gpio_cansleep		__gpio_cansleep
+
+这些定义可以用更理想的实现方法替代，那就是使用经过逻辑优化的内联函数来访问
+基于特定片上系统的 GPIO。例如,若引用 GPIO 的(寄存器地址)是常量“12”，
+读取或设置它可能只需少则两或三个指令，且不会休眠。当这样的优化无法实现时，
+那些函数必须使用框架提供的代码，那就至少要几十条指令才可以实现。对于用 GPIO
+模拟的 I/O 接口, 如此精简指令是很有意义的。
+
+对于片上系统，平台特定代码为片上 GPIO 每个区(bank)定义并注册 gpio_chip
+实例。那些 GPIO 应该根据芯片厂商的文档进行编码/标签,并直接和电路板原理图
+对应。他们应该开始于零并终止于平台特定的限制。这些 GPIO(代码)通常从
+arch_initcall()或者更早的地方集成进平台初始化代码，使这些 GPIO 总是可用，
+且他们通常可以作为 IRQ 使用。
+
+板级支持
+-------
+对于外部 GPIO 控制器(例如 I2C 或 SPI 扩展器、专用芯片、多功能器件、FPGA
+或 CPLD)，大多数常用板级特定代码都可以注册控制器设备，并保证他们的驱动知道
+gpiochip_add()所使用的 GPIO 编号。他们的起始编号通常跟在平台特定的 GPIO
+编号之后。
+
+例如板级启动代码应该创建结构体指明芯片公开的 GPIO 范围，并使用 platform_data
+将其传递给每个 GPIO 扩展器芯片。然后芯片驱动中的 probe()例程可以将这个
+数据传递给 gpiochip_add()。
+
+初始化顺序很重要。例如，如果一个设备依赖基于 I2C 的(扩展)GPIO，那么它的
+probe()例程就应该在那个 GPIO 有效以后才可以被调用。这意味着设备应该在
+GPIO 可以工作之后才可被注册。解决这类依赖的的一种方法是让这种 gpio_chip
+控制器向板级特定代码提供 setup()和 teardown()回调函数。一旦所有必须的
+资源可用之后，这些板级特定的回调函数将会注册设备，并可以在这些 GPIO 控制器
+设备变成无效时移除它们。
+
+
+用户空间的 Sysfs 接口(可选)
+========================
+使用“gpiolib”实现框架的平台可以选择配置一个 GPIO 的 sysfs 用户接口。
+这不同于 debugfs 接口，因为它提供的是对 GPIO方向和值的控制，而不只显示
+一个GPIO 的状态摘要。此外,它可以出现在没有调试支持的产品级系统中。
+
+例如，通过适当的系统硬件文档，用户空间可以知道 GIOP #23 控制 Flash
+存储器的写保护(用于保护其中 Bootloader 分区)。产品的系统升级可能需要
+临时解除这个保护：首先导入一个 GPIO，改变其输出状态，然后在重新使能写保护
+前升级代码。通常情况下,GPIO #23 是不会被触及的，并且内核也不需要知道他。
+
+根据适当的硬件文档，某些系统的用户空间 GPIO 可以用于确定系统配置数据，
+这些数据是标准内核不知道的。在某些任务中，简单的用户空间 GPIO 驱动可能是
+系统真正需要的。
+
+注意：标准内核驱动中已经存在通用的“LED 和按键”GPIO 任务，分别是:
+"leds-gpio" 和 "gpio_keys"。请使用这些来替代直接访问 GPIO，因为集成在
+内核框架中的这类驱动比你在用户空间的代码更好。
+
+
+Sysfs 中的路径
+--------------
+在/sys/class/gpio 中有 3 类入口:
+
+   -	用于在用户空间控制 GPIO 的控制接口;
+
+   -	GPIOs 本身;以及
+
+   -	GPIO 控制器 ("gpio_chip" 实例)。
+
+除了这些标准的文件,还包含“device”符号链接。
+
+控制接口是只写的:
+
+    /sys/class/gpio/
+
+    	"export" ... 用户空间可以通过写其编号到这个文件，要求内核导出
+		一个 GPIO 的控制到用户空间。
+
+		例如: 如果内核代码没有申请 GPIO #19,"echo 19 > export"
+		将会为 GPIO #19 创建一个 "gpio19" 节点。
+
+    	"unexport" ... 导出到用户空间的逆操作。
+
+		例如: "echo 19 > unexport" 将会移除使用"export"文件导出的
+		"gpio19" 节点。
+
+GPIO 信号的路径类似 /sys/class/gpio/gpio42/ (对于 GPIO #42 来说)，
+并有如下的读/写属性:
+
+    /sys/class/gpio/gpioN/
+
+	"direction" ... 读取得到 "in" 或 "out"。这个值通常运行写入。
+		写入"out" 时,其引脚的默认输出为低电平。为了确保无故障运行，
+		"low" 或 "high" 的电平值应该写入 GPIO 的配置，作为初始输出值。
+
+		注意:如果内核不支持改变 GPIO 的方向，或者在导出时内核代码没有
+		明确允许用户空间可以重新配置 GPIO 方向，那么这个属性将不存在。
+
+	"value" ... 读取得到 0 (低电平) 或 1 (高电平)。如果 GPIO 配置为
+		输出,这个值允许写操作。任何非零值都以高电平看待。
+
+		如果引脚可以配置为中断信号，且如果已经配置了产生中断的模式
+		（见"edge"的描述），你可以对这个文件使用轮询操作(poll(2))，
+		且轮询操作会在任何中断触发时返回。如果你使用轮询操作(poll(2))，
+		请在 events 中设置 POLLPRI 和 POLLERR。如果你使用轮询操作
+		(select(2))，请在 exceptfds 设置你期望的文件描述符。在
+		轮询操作(poll(2))返回之后，既可以通过 lseek(2)操作读取
+		sysfs 文件的开始部分，也可以关闭这个文件并重新打开它来读取数据。
+
+	"edge" ... 读取得到“none”、“rising”、“falling”或者“both”。
+		将这些字符串写入这个文件可以选择沿触发模式，会使得轮询操作
+		(select(2))在"value"文件中返回。
+
+		这个文件仅有在这个引脚可以配置为可产生中断输入引脚时，才存在。
+
+	"active_low" ... 读取得到 0 (假) 或 1 (真)。写入任何非零值可以
+		翻转这个属性的(读写)值。已存在或之后通过"edge"属性设置了"rising"
+		和 "falling" 沿触发模式的轮询操作(poll(2))将会遵循这个设置。
+
+GPIO 控制器的路径类似 /sys/class/gpio/gpiochip42/ (对于从#42 GPIO
+开始实现控制的控制器),并有着以下只读属性:
+
+    /sys/class/gpio/gpiochipN/
+
+    	"base" ... 与以上的 N 相同,代表此芯片管理的第一个 GPIO 的编号
+
+    	"label" ... 用于诊断 (并不总是只有唯一值)
+
+    	"ngpio" ... 此控制器所管理的 GPIO 数量(而 GPIO 编号从 N 到
+    		N + ngpio - 1)
+
+大多数情况下,电路板的文档应当标明每个 GPIO 的使用目的。但是那些编号并不总是
+固定的,例如在扩展卡上的 GPIO会根据所使用的主板或所在堆叠架构中其他的板子而
+有所不同。在这种情况下,你可能需要使用 gpiochip 节点(尽可能地结合电路图)来
+确定给定信号所用的 GPIO 编号。
+
+
+从内核代码中导出
+-------------
+内核代码可以明确地管理那些已通过 gpio_request()申请的 GPIO 的导出:
+
+	/* 导出 GPIO 到用户空间 */
+	int gpio_export(unsigned gpio, bool direction_may_change);
+
+	/* gpio_export()的逆操作 */
+	void gpio_unexport();
+
+	/* 创建一个 sysfs 连接到已导出的 GPIO 节点 */
+	int gpio_export_link(struct device *dev, const char *name,
+		unsigned gpio)
+
+	/* 改变 sysfs 中的一个 GPIO 节点的极性 */
+	int gpio_sysfs_set_active_low(unsigned gpio, int value);
+
+在一个内核驱动申请一个 GPIO 之后，它可以通过 gpio_export()使其在 sysfs
+接口中可见。该驱动可以控制信号方向是否可修改。这有助于防止用户空间代码无意间
+破坏重要的系统状态。
+
+这个明确的导出有助于(通过使某些实验更容易来)调试，也可以提供一个始终存在的接口，
+与文档配合作为板级支持包的一部分。
+
+在 GPIO 被导出之后，gpio_export_link()允许在 sysfs 文件系统的任何地方
+创建一个到这个 GPIO sysfs 节点的符号链接。这样驱动就可以通过一个描述性的
+名字，在 sysfs 中他们所拥有的设备下提供一个(到这个 GPIO sysfs 节点的)接口。
+
+驱动可以使用 gpio_sysfs_set_active_low() 来在用户空间隐藏电路板之间
+GPIO 线的极性差异。这个仅对 sysfs 接口起作用。极性的改变可以在 gpio_export()
+前后进行,且之前使能的轮询操作(poll(2))支持(上升或下降沿)将会被重新配置来遵循
+这个设置。
diff --git a/Documentation/zh_CN/video4linux/v4l2-framework.txt b/Documentation/zh_CN/video4linux/v4l2-framework.txt
new file mode 100644
index 0000000..3e74f13
--- /dev/null
+++ b/Documentation/zh_CN/video4linux/v4l2-framework.txt
@@ -0,0 +1,983 @@
+Chinese translated version of Documentation/video4linux/v4l2-framework.txt
+
+If you have any comment or update to the content, please contact the
+original document maintainer directly.  However, if you have a problem
+communicating in English you can also ask the Chinese maintainer for
+help.  Contact the Chinese maintainer if this translation is outdated
+or if there is a problem with the translation.
+
+Maintainer: Mauro Carvalho Chehab <mchehab@infradead.org>
+Chinese maintainer: Fu Wei <tekkamanninja@gmail.com>
+---------------------------------------------------------------------
+Documentation/video4linux/v4l2-framework.txt 的中文翻译
+
+如果想评论或更新本文的内容，请直接联系原文档的维护者。如果你使用英文
+交流有困难的话，也可以向中文版维护者求助。如果本翻译更新不及时或者翻
+译存在问题，请联系中文版维护者。
+英文版维护者： Mauro Carvalho Chehab <mchehab@infradead.org>
+中文版维护者： 傅炜 Fu Wei <tekkamanninja@gmail.com>
+中文版翻译者： 傅炜 Fu Wei <tekkamanninja@gmail.com>
+中文版校译者： 傅炜 Fu Wei <tekkamanninja@gmail.com>
+
+
+以下为正文
+---------------------------------------------------------------------
+V4L2 驱动框架概览
+==============
+
+本文档描述 V4L2 框架所提供的各种结构和它们之间的关系。
+
+
+介绍
+----
+
+大部分现代 V4L2 设备由多个 IC 组成，在 /dev 下导出多个设备节点，
+并同时创建非 V4L2 设备（如 DVB、ALSA、FB、I2C 和红外输入设备）。
+由于这种硬件的复杂性，V4L2 驱动也变得非常复杂。
+
+尤其是 V4L2 必须支持 IC 实现音视频的多路复用和编解码，这就更增加了其
+复杂性。通常这些 IC 通过一个或多个 I2C 总线连接到主桥驱动器，但也可
+使用其他总线。这些设备称为“子设备”。
+
+长期以来，这个框架仅限于通过 video_device 结构体创建 V4L 设备节点，
+并使用 video_buf 处理视频缓冲（注：本文不讨论 video_buf 框架）。
+
+这意味着所有驱动必须自己设置设备实例并连接到子设备。其中一部分要正确地
+完成是比较复杂的，使得许多驱动都没有正确地实现。
+
+由于框架的缺失，有很多通用代码都不可重复利用。
+
+因此，这个框架构建所有驱动都需要的基本结构块，而统一的框架将使通用代码
+创建成实用函数并在所有驱动中共享变得更加容易。
+
+
+驱动结构
+-------
+
+所有 V4L2 驱动都有如下结构：
+
+1) 每个设备实例的结构体--包含其设备状态。
+
+2) 初始化和控制子设备的方法（如果有）。
+
+3) 创建 V4L2 设备节点 (/dev/videoX、/dev/vbiX 和 /dev/radioX)
+   并跟踪设备节点的特定数据。
+
+4) 特定文件句柄结构体--包含每个文件句柄的数据。
+
+5) 视频缓冲处理。
+
+以下是它们的初略关系图：
+
+    device instances（设备实例）
+      |
+      +-sub-device instances（子设备实例）
+      |
+      \-V4L2 device nodes（V4L2 设备节点）
+	  |
+	  \-filehandle instances（文件句柄实例）
+
+
+框架结构
+-------
+
+该框架非常类似驱动结构：它有一个 v4l2_device 结构用于保存设备
+实例的数据；一个 v4l2_subdev 结构体代表子设备实例；video_device
+结构体保存 V4L2 设备节点的数据；将来 v4l2_fh 结构体将跟踪文件句柄
+实例（暂未尚未实现）。
+
+V4L2 框架也可与媒体框架整合（可选的）。如果驱动设置了 v4l2_device
+结构体的 mdev 域，子设备和视频节点的入口将自动出现在媒体框架中。
+
+
+v4l2_device 结构体
+----------------
+
+每个设备实例都通过 v4l2_device (v4l2-device.h)结构体来表示。
+简单设备可以仅分配这个结构体，但在大多数情况下，都会将这个结构体
+嵌入到一个更大的结构体中。
+
+你必须注册这个设备实例：
+
+	v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev);
+
+注册操作将会初始化 v4l2_device 结构体。如果 dev->driver_data 域
+为 NULL，就将其指向 v4l2_dev。
+
+需要与媒体框架整合的驱动必须手动设置 dev->driver_data，指向包含
+v4l2_device 结构体实例的驱动特定设备结构体。这可以在注册 V4L2 设备
+实例前通过 dev_set_drvdata() 函数完成。同时必须设置 v4l2_device
+结构体的 mdev 域，指向适当的初始化并注册过的 media_device 实例。
+
+如果 v4l2_dev->name 为空，则它将被设置为从 dev 中衍生出的值（为了
+更加精确，形式为驱动名后跟 bus_id）。如果你在调用 v4l2_device_register
+前已经设置好了，则不会被修改。如果 dev 为 NULL，则你*必须*在调用
+v4l2_device_register 前设置 v4l2_dev->name。
+
+你可以基于驱动名和驱动的全局 atomic_t 类型的实例编号，通过
+v4l2_device_set_name() 设置 name。这样会生成类似 ivtv0、ivtv1 等
+名字。若驱动名以数字结尾，则会在编号和驱动名间插入一个破折号，如：
+cx18-0、cx18-1 等。此函数返回实例编号。
+
+第一个 “dev” 参数通常是一个指向 pci_dev、usb_interface 或
+platform_device 的指针。很少使其为 NULL，除非是一个ISA设备或者
+当一个设备创建了多个 PCI 设备，使得 v4l2_dev 无法与一个特定的父设备
+关联。
+
+你也可以提供一个 notify() 回调，使子设备可以调用它实现事件通知。
+但这个设置与子设备相关。子设备支持的任何通知必须在
+include/media/<subdevice>.h 中定义一个消息头。
+
+注销 v4l2_device 使用如下函数：
+
+	v4l2_device_unregister(struct v4l2_device *v4l2_dev);
+
+如果 dev->driver_data 域指向 v4l2_dev，将会被重置为 NULL。注销同时
+会自动从设备中注销所有子设备。
+
+如果你有一个热插拔设备（如USB设备），则当断开发生时，父设备将无效。
+由于 v4l2_device 有一个指向父设备的指针必须被清除，同时标志父设备
+已消失，所以必须调用以下函数：
+
+	v4l2_device_disconnect(struct v4l2_device *v4l2_dev);
+
+这个函数并*不*注销子设备，因此你依然要调用 v4l2_device_unregister()
+函数。如果你的驱动器并非热插拔的，就没有必要调用 v4l2_device_disconnect()。
+
+有时你需要遍历所有被特定驱动注册的设备。这通常发生在多个设备驱动使用
+同一个硬件的情况下。如：ivtvfb 驱动是一个使用 ivtv 硬件的帧缓冲驱动，
+同时 alsa 驱动也使用此硬件。
+
+你可以使用如下例程遍历所有注册的设备：
+
+static int callback(struct device *dev, void *p)
+{
+	struct v4l2_device *v4l2_dev = dev_get_drvdata(dev);
+
+	/* 测试这个设备是否已经初始化 */
+	if (v4l2_dev == NULL)
+		return 0;
+	...
+	return 0;
+}
+
+int iterate(void *p)
+{
+	struct device_driver *drv;
+	int err;
+
+	/* 在PCI 总线上查找ivtv驱动。
+	   pci_bus_type是全局的. 对于USB总线使用usb_bus_type。 */
+	drv = driver_find("ivtv", &pci_bus_type);
+	/* 遍历所有的ivtv设备实例 */
+	err = driver_for_each_device(drv, NULL, p, callback);
+	put_driver(drv);
+	return err;
+}
+
+有时你需要一个设备实例的运行计数。这个通常用于映射一个设备实例到一个
+模块选择数组的索引。
+
+推荐方法如下：
+
+static atomic_t drv_instance = ATOMIC_INIT(0);
+
+static int __devinit drv_probe(struct pci_dev *pdev,
+				const struct pci_device_id *pci_id)
+{
+	...
+	state->instance = atomic_inc_return(&drv_instance) - 1;
+}
+
+如果你有多个设备节点，对于热插拔设备，知道何时注销 v4l2_device 结构体
+就比较困难。为此 v4l2_device 有引用计数支持。当调用 video_register_device
+时增加引用计数，而设备节点释放时减小引用计数。当引用计数为零，则
+v4l2_device 的release() 回调将被执行。你就可以在此时做最后的清理工作。
+
+如果创建了其他设备节点（比如 ALSA），则你可以通过以下函数手动增减
+引用计数：
+
+void v4l2_device_get(struct v4l2_device *v4l2_dev);
+
+或:
+
+int v4l2_device_put(struct v4l2_device *v4l2_dev);
+
+由于引用技术初始化为 1 ，你也需要在 disconnect() 回调（对于 USB 设备）中
+调用 v4l2_device_put，或者 remove() 回调（例如对于 PCI 设备），否则
+引用计数将永远不会为 0 。
+
+v4l2_subdev结构体
+------------------
+
+许多驱动需要与子设备通信。这些设备可以完成各种任务，但通常他们负责
+音视频复用和编解码。如网络摄像头的子设备通常是传感器和摄像头控制器。
+
+这些一般为 I2C 接口设备，但并不一定都是。为了给驱动提供调用子设备的
+统一接口，v4l2_subdev 结构体（v4l2-subdev.h）产生了。
+
+每个子设备驱动都必须有一个 v4l2_subdev 结构体。这个结构体可以单独
+代表一个简单的子设备，也可以嵌入到一个更大的结构体中，与更多设备状态
+信息保存在一起。通常有一个下级设备结构体（比如：i2c_client）包含了
+内核创建的设备数据。建议使用 v4l2_set_subdevdata() 将这个结构体的
+指针保存在 v4l2_subdev 的私有数据域(dev_priv)中。这使得通过 v4l2_subdev
+找到实际的低层总线特定设备数据变得容易。
+
+你同时需要一个从低层结构体获取 v4l2_subdev 指针的方法。对于常用的
+i2c_client 结构体，i2c_set_clientdata() 函数可用于保存一个 v4l2_subdev
+指针；对于其他总线你可能需要使用其他相关函数。
+
+桥驱动中也应保存每个子设备的私有数据，比如一个指向特定桥的各设备私有
+数据的指针。为此 v4l2_subdev 结构体提供主机私有数据域(host_priv)，
+并可通过 v4l2_get_subdev_hostdata() 和 v4l2_set_subdev_hostdata()
+访问。
+
+从总线桥驱动的视角，驱动加载子设备模块并以某种方式获得 v4l2_subdev
+结构体指针。对于 i2c 总线设备相对简单：调用 i2c_get_clientdata()。
+对于其他总线也需要做类似的操作。针对 I2C 总线上的子设备辅助函数帮你
+完成了大部分复杂的工作。
+
+每个 v4l2_subdev 都包含子设备驱动需要实现的函数指针（如果对此设备
+不适用，可为NULL）。由于子设备可完成许多不同的工作，而在一个庞大的
+函数指针结构体中通常仅有少数有用的函数实现其功能肯定不合适。所以，
+函数指针根据其实现的功能被分类，每一类都有自己的函数指针结构体。
+
+顶层函数指针结构体包含了指向各类函数指针结构体的指针，如果子设备驱动
+不支持该类函数中的任何一个功能，则指向该类结构体的指针为NULL。
+
+这些结构体定义如下：
+
+struct v4l2_subdev_core_ops {
+	int (*g_chip_ident)(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip);
+	int (*log_status)(struct v4l2_subdev *sd);
+	int (*init)(struct v4l2_subdev *sd, u32 val);
+	...
+};
+
+struct v4l2_subdev_tuner_ops {
+	...
+};
+
+struct v4l2_subdev_audio_ops {
+	...
+};
+
+struct v4l2_subdev_video_ops {
+	...
+};
+
+struct v4l2_subdev_pad_ops {
+	...
+};
+
+struct v4l2_subdev_ops {
+	const struct v4l2_subdev_core_ops  *core;
+	const struct v4l2_subdev_tuner_ops *tuner;
+	const struct v4l2_subdev_audio_ops *audio;
+	const struct v4l2_subdev_video_ops *video;
+	const struct v4l2_subdev_pad_ops *video;
+};
+
+其中 core（核心）函数集通常可用于所有子设备，其他类别的实现依赖于
+子设备。如视频设备可能不支持音频操作函数，反之亦然。
+
+这样的设置在限制了函数指针数量的同时，还使增加新的操作函数和分类
+变得较为容易。
+
+子设备驱动可使用如下函数初始化 v4l2_subdev 结构体：
+
+	v4l2_subdev_init(sd, &ops);
+
+然后，你必须用一个唯一的名字初始化 subdev->name，并初始化模块的
+owner 域。若使用 i2c 辅助函数，这些都会帮你处理好。
+
+若需同媒体框架整合，你必须调用 media_entity_init() 初始化 v4l2_subdev
+结构体中的 media_entity 结构体（entity 域）：
+
+	struct media_pad *pads = &my_sd->pads;
+	int err;
+
+	err = media_entity_init(&sd->entity, npads, pads, 0);
+
+pads 数组必须预先初始化。无须手动设置 media_entity 的 type 和
+name 域，但如有必要，revision 域必须初始化。
+
+当（任何）子设备节点被打开/关闭，对 entity 的引用将被自动获取/释放。
+
+在子设备被注销之后，不要忘记清理 media_entity 结构体：
+
+	media_entity_cleanup(&sd->entity);
+
+如果子设备驱动趋向于处理视频并整合进了媒体框架，必须使用 v4l2_subdev_pad_ops
+替代 v4l2_subdev_video_ops 实现格式相关的功能。
+
+这种情况下，子设备驱动应该设置 link_validate 域，以提供它自身的链接
+验证函数。链接验证函数应对管道（两端链接的都是 V4L2 子设备）中的每个
+链接调用。驱动还要负责验证子设备和视频节点间格式配置的正确性。
+
+如果 link_validate 操作没有设置，默认的 v4l2_subdev_link_validate_default()
+函数将会被调用。这个函数保证宽、高和媒体总线像素格式在链接的收发两端
+都一致。子设备驱动除了它们自己的检测外，也可以自由使用这个函数以执行
+上面提到的检查。
+
+设备（桥）驱动程序必须向 v4l2_device 注册 v4l2_subdev：
+
+	int err = v4l2_device_register_subdev(v4l2_dev, sd);
+
+如果子设备模块在它注册前消失，这个操作可能失败。在这个函数成功返回后，
+subdev->dev 域就指向了 v4l2_device。
+
+如果 v4l2_device 父设备的 mdev 域为非 NULL 值，则子设备实体将被自动
+注册为媒体设备。
+
+注销子设备则可用如下函数：
+
+	v4l2_device_unregister_subdev(sd);
+
+此后，子设备模块就可卸载，且 sd->dev == NULL。
+
+注册之设备后，可通过以下方式直接调用其操作函数：
+
+	err = sd->ops->core->g_chip_ident(sd, &chip);
+
+但使用如下宏会比较容易且合适：
+
+	err = v4l2_subdev_call(sd, core, g_chip_ident, &chip);
+
+这个宏将会做 NULL 指针检查，如果 subdev 为 NULL，则返回-ENODEV；如果
+subdev->core 或 subdev->core->g_chip_ident 为 NULL，则返回 -ENOIOCTLCMD；
+否则将返回 subdev->ops->core->g_chip_ident ops 调用的实际结果。
+
+有时也可能同时调用所有或一系列子设备的某个操作函数：
+
+	v4l2_device_call_all(v4l2_dev, 0, core, g_chip_ident, &chip);
+
+任何不支持此操作的子设备都会被跳过，并忽略错误返回值。但如果你需要
+检查出错码，则可使用如下函数：
+
+	err = v4l2_device_call_until_err(v4l2_dev, 0, core, g_chip_ident, &chip);
+
+除 -ENOIOCTLCMD 外的任何错误都会跳出循环并返回错误值。如果（除 -ENOIOCTLCMD
+外）没有错误发生，则返回 0。
+
+对于以上两个函数的第二个参数为组 ID。如果为 0，则所有子设备都会执行
+这个操作。如果为非 0 值，则只有那些组 ID 匹配的子设备才会执行此操作。
+在桥驱动注册一个子设备前，可以设置 sd->grp_id 为任何期望值（默认值为
+0）。这个值属于桥驱动，且子设备驱动将不会修改和使用它。
+
+组 ID 赋予了桥驱动更多对于如何调用回调的控制。例如，电路板上有多个
+音频芯片，每个都有改变音量的能力。但当用户想要改变音量的时候，通常
+只有一个会被实际使用。你可以对这样的子设备设置组 ID 为（例如 AUDIO_CONTROLLER）
+并在调用 v4l2_device_call_all() 时指定它为组 ID 值。这就保证了只有
+需要的子设备才会执行这个回调。
+
+如果子设备需要通知它的 v4l2_device 父设备一个事件，可以调用
+v4l2_subdev_notify(sd, notification, arg)。这个宏检查是否有一个
+notify() 回调被注册，如果没有，返回 -ENODEV。否则返回 notify() 调用
+结果。
+
+使用 v4l2_subdev 的好处在于它是一个通用结构体，且不包含任何底层硬件
+信息。所有驱动可以包含多个 I2C 总线的子设备，但也有子设备是通过 GPIO
+控制。这个区别仅在配置设备时有关系，一旦子设备注册完成，对于 v4l2
+子系统来说就完全透明了。
+
+
+V4L2 子设备用户空间API
+--------------------
+
+除了通过 v4l2_subdev_ops 结构导出的内核 API，V4L2 子设备也可以直接
+通过用户空间应用程序来控制。
+
+可以在 /dev 中创建名为 v4l-subdevX 设备节点，以通过其直接访问子设备。
+如果子设备支持用户空间直接配置，必须在注册前设置 V4L2_SUBDEV_FL_HAS_DEVNODE
+标志。
+
+注册子设备之后， v4l2_device 驱动会通过调用 v4l2_device_register_subdev_nodes()
+函数为所有已注册并设置了 V4L2_SUBDEV_FL_HAS_DEVNODE 的子设备创建
+设备节点。这些设备节点会在子设备注销时自动删除。
+
+这些设备节点处理 V4L2 API 的一个子集。
+
+VIDIOC_QUERYCTRL
+VIDIOC_QUERYMENU
+VIDIOC_G_CTRL
+VIDIOC_S_CTRL
+VIDIOC_G_EXT_CTRLS
+VIDIOC_S_EXT_CTRLS
+VIDIOC_TRY_EXT_CTRLS
+
+	这些 ioctls 控制与 V4L2 中定义的一致。他们行为相同，唯一的
+	不同是他们只处理子设备的控制实现。根据驱动程序，这些控制也
+	可以通过一个（或多个） V4L2 设备节点访问。
+
+VIDIOC_DQEVENT
+VIDIOC_SUBSCRIBE_EVENT
+VIDIOC_UNSUBSCRIBE_EVENT
+
+	这些  ioctls 事件与 V4L2 中定义的一致。他们行为相同，唯一的
+	不同是他们只处理子设备产生的事件。根据驱动程序，这些事件也
+	可以通过一个（或多个） V4L2 设备节点上报。
+
+	要使用事件通知的子设备驱动，在注册子设备前必须在 v4l2_subdev::flags
+	中设置 V4L2_SUBDEV_USES_EVENTS 并在 v4l2_subdev::nevents
+	中初始化事件队列深度。注册完成后，事件会在 v4l2_subdev::devnode
+	设备节点中像通常一样被排队。
+
+	为正确支持事件机制，poll() 文件操作也应被实现。
+
+私有 ioctls
+
+	不在以上列表中的所有 ioctls 会通过 core::ioctl 操作直接传递
+	给子设备驱动。
+
+
+I2C 子设备驱动
+-------------
+
+由于这些驱动很常见，所以内特提供了特定的辅助函数(v4l2-common.h)让这些
+设备的使用更加容易。
+
+添加 v4l2_subdev 支持的推荐方法是让 I2C 驱动将 v4l2_subdev 结构体
+嵌入到为每个 I2C 设备实例创建的状态结构体中。而最简单的设备没有状态
+结构体，此时可以直接创建一个 v4l2_subdev 结构体。
+
+一个典型的状态结构体如下所示（‘chipname’用芯片名代替）：
+
+struct chipname_state {
+	struct v4l2_subdev sd;
+	...  /* 附加的状态域*/
+};
+
+初始化 v4l2_subdev 结构体的方法如下：
+
+	v4l2_i2c_subdev_init(&state->sd, client, subdev_ops);
+
+这个函数将填充 v4l2_subdev 结构体中的所有域，并保证 v4l2_subdev 和
+i2c_client 都指向彼此。
+
+同时，你也应该为从 v4l2_subdev 指针找到 chipname_state 结构体指针
+添加一个辅助内联函数。
+
+static inline struct chipname_state *to_state(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct chipname_state, sd);
+}
+
+使用以下函数可以通过 v4l2_subdev 结构体指针获得 i2c_client 结构体
+指针：
+
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+而以下函数则相反，通过 i2c_client 结构体指针获得 v4l2_subdev 结构体
+指针：
+
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+
+当 remove()函数被调用前，必须保证先调用 v4l2_device_unregister_subdev(sd)。
+此操作将会从桥驱动中注销子设备。即使子设备没有注册，调用此函数也是
+安全的。
+
+必须这样做的原因是：当桥驱动注销 i2c 适配器时，remove()回调函数
+会被那个适配器上的 i2c 设备调用。此后，相应的 v4l2_subdev 结构体
+就不存在了，所有它们必须先被注销。在 remove()回调函数中调用
+v4l2_device_unregister_subdev(sd)，可以保证执行总是正确的。
+
+
+桥驱动也有一些辅组函数可用：
+
+struct v4l2_subdev *sd = v4l2_i2c_new_subdev(v4l2_dev, adapter,
+	       "module_foo", "chipid", 0x36, NULL);
+
+这个函数会加载给定的模块（如果没有模块需要加载，可以为 NULL），
+并用给定的 i2c 适配器结构体指针（i2c_adapter）和 器件地址（chip/address）
+作为参数调用 i2c_new_device()。如果一切顺利，则就在 v4l2_device
+中注册了子设备。
+
+你也可以利用 v4l2_i2c_new_subdev()的最后一个参数，传递一个可能的
+I2C 地址数组，让函数自动探测。这些探测地址只有在前一个参数为 0 的
+情况下使用。非零参数意味着你知道准确的 i2c 地址，所以此时无须进行
+探测。
+
+如果出错，两个函数都返回 NULL。
+
+注意：传递给 v4l2_i2c_new_subdev()的 chipid 通常与模块名一致。
+它允许你指定一个芯片的变体，比如“saa7114”或“saa7115”。一般通过
+i2c 驱动自动探测。chipid 的使用是在今后需要深入了解的事情。这个与
+i2c 驱动不同，较容易混淆。要知道支持哪些芯片变体，你可以查阅 i2c
+驱动代码的 i2c_device_id 表，上面列出了所有可能支持的芯片。
+
+还有两个辅助函数：
+
+v4l2_i2c_new_subdev_cfg：这个函数添加新的 irq 和 platform_data
+参数，并有‘addr’和‘probed_addrs’参数：如果 addr 非零，则被使用
+（不探测变体），否则 probed_addrs 中的地址将用于自动探测。
+
+例如：以下代码将会探测地址（0x10）：
+
+struct v4l2_subdev *sd = v4l2_i2c_new_subdev_cfg(v4l2_dev, adapter,
+	       "module_foo", "chipid", 0, NULL, 0, I2C_ADDRS(0x10));
+
+v4l2_i2c_new_subdev_board 使用一个 i2c_board_info 结构体，将其
+替代 irq、platform_data 和 add r参数传递给 i2c 驱动。
+
+如果子设备支持 s_config 核心操作，这个操作会在子设备配置好之后以 irq 和
+platform_data 为参数调用。早期的 v4l2_i2c_new_(probed_)subdev 函数
+同样也会调用 s_config，但仅在 irq 为 0 且 platform_data 为 NULL 时。
+
+video_device结构体
+-----------------
+
+在 /dev 目录下的实际设备节点根据 video_device 结构体(v4l2-dev.h)
+创建。此结构体既可以动态分配也可以嵌入到一个更大的结构体中。
+
+动态分配方法如下：
+
+	struct video_device *vdev = video_device_alloc();
+
+	if (vdev == NULL)
+		return -ENOMEM;
+
+	vdev->release = video_device_release;
+
+如果将其嵌入到一个大结构体中，则必须自己实现 release()回调。
+
+	struct video_device *vdev = &my_vdev->vdev;
+
+	vdev->release = my_vdev_release;
+
+release()回调必须被设置，且在最后一个 video_device 用户退出之后
+被调用。
+
+默认的 video_device_release()回调只是调用 kfree 来释放之前分配的
+内存。
+
+你应该设置这些域：
+
+- v4l2_dev: 设置为 v4l2_device 父设备。
+
+- name: 设置为唯一的描述性设备名。
+
+- fops: 设置为已有的 v4l2_file_operations 结构体。
+
+- ioctl_ops: 如果你使用v4l2_ioctl_ops 来简化 ioctl 的维护
+  (强烈建议使用，且将来可能变为强制性的!)，然后设置你自己的
+  v4l2_ioctl_ops 结构体.
+
+- lock: 如果你要在驱动中实现所有的锁操作，则设为 NULL 。否则
+  就要设置一个指向 struct mutex_lock 结构体的指针，这个锁将
+  在 unlocked_ioctl 文件操作被调用前由内核获得，并在调用返回后
+  释放。详见下一节。
+
+- prio: 保持对优先级的跟踪。用于实现 VIDIOC_G/S_PRIORITY。如果
+  设置为 NULL，则会使用 v4l2_device 中的 v4l2_prio_state 结构体。
+  如果要对每个设备节点（组）实现独立的优先级，可以将其指向自己
+  实现的 v4l2_prio_state 结构体。
+
+- parent: 仅在使用 NULL 作为父设备结构体参数注册 v4l2_device 时
+  设置此参数。只有在一个硬件设备包含多一个 PCI 设备，共享同一个
+  v4l2_device 核心时才会发生。
+
+  cx88 驱动就是一个例子：一个 v4l2_device 结构体核心，被一个裸的
+  视频 PCI 设备(cx8800)和一个 MPEG PCI 设备(cx8802)共用。由于
+  v4l2_device 无法与特定的 PCI 设备关联，所有没有设置父设备。但当
+  video_device 配置后，就知道使用哪个父 PCI 设备了。
+
+- flags：可选。如果你要让框架处理设置 VIDIOC_G/S_PRIORITY ioctls，
+  请设置 V4L2_FL_USE_FH_PRIO。这要求你使用 v4l2_fh 结构体。
+  一旦所有驱动使用了核心的优先级处理，最终这个标志将消失。但现在它
+  必须被显式设置。
+
+如果你使用 v4l2_ioctl_ops，则应该在 v4l2_file_operations 结构体中
+设置 .unlocked_ioctl 指向 video_ioctl2。
+
+请勿使用 .ioctl！它已被废弃，今后将消失。
+
+某些情况下你要告诉核心：你在 v4l2_ioctl_ops 指定的某个函数应被忽略。
+你可以在 video_device_register 被调用前通过以下函数标记这个 ioctls。
+
+void v4l2_disable_ioctl(struct video_device *vdev, unsigned int cmd);
+
+基于外部因素（例如某个板卡已被使用），在不创建新结构体的情况下，你想
+要关闭 v4l2_ioctl_ops 中某个特性往往需要这个机制。
+
+v4l2_file_operations 结构体是 file_operations 的一个子集。其主要
+区别在于：因 inode 参数从未被使用，它将被忽略。
+
+如果需要与媒体框架整合，你必须通过调用 media_entity_init() 初始化
+嵌入在 video_device 结构体中的 media_entity（entity 域）结构体：
+
+	struct media_pad *pad = &my_vdev->pad;
+	int err;
+
+	err = media_entity_init(&vdev->entity, 1, pad, 0);
+
+pads 数组必须预先初始化。没有必要手动设置 media_entity 的 type 和
+name 域。
+
+当（任何）子设备节点被打开/关闭，对 entity 的引用将被自动获取/释放。
+
+v4l2_file_operations 与锁
+--------------------------
+
+你可以在 video_device 结构体中设置一个指向 mutex_lock 的指针。通常
+这既可是一个顶层互斥锁也可为设备节点自身的互斥锁。默认情况下，此锁
+用于 unlocked_ioctl，但为了使用 ioctls 你通过以下函数可禁用锁定：
+
+	void v4l2_disable_ioctl_locking(struct video_device *vdev, unsigned int cmd);
+
+例如: v4l2_disable_ioctl_locking(vdev, VIDIOC_DQBUF);
+
+你必须在注册 video_device 前调用这个函数。
+
+特别是对于 USB 驱动程序，某些命令（如设置控制）需要很长的时间，可能
+需要自行为缓冲区队列的 ioctls 实现锁定。
+
+如果你需要更细粒度的锁，你必须设置 mutex_lock 为 NULL，并完全自己实现
+锁机制。
+
+这完全由驱动开发者决定使用何种方法。然而，如果你的驱动存在长延时操作
+（例如，改变 USB 摄像头的曝光时间可能需要较长时间），而你又想让用户
+在等待长延时操作完成期间做其他的事，则你最好自己实现锁机制。
+
+如果指定一个锁，则所有 ioctl 操作将在这个锁的作用下串行执行。如果你
+使用 videobuf，则必须将同一个锁传递给 videobuf 队列初始化函数；如
+videobuf 必须等待一帧的到达，则可临时解锁并在这之后重新上锁。如果驱动
+也在代码执行期间等待，则可做同样的工作（临时解锁，再上锁）让其他进程
+可以在第一个进程阻塞时访问设备节点。
+
+在使用 videobuf2 的情况下，必须实现 wait_prepare 和 wait_finish 回调
+在适当的时候解锁/加锁。进一步来说，如果你在 video_device 结构体中使用
+锁，则必须在 wait_prepare 和 wait_finish 中对这个互斥锁进行解锁/加锁。
+
+热插拔的断开实现也必须在调用 v4l2_device_disconnect 前获得锁。
+
+video_device注册
+---------------
+
+接下来你需要注册视频设备：这会为你创建一个字符设备。
+
+	err = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
+	if (err) {
+		video_device_release(vdev); /* or kfree(my_vdev); */
+		return err;
+	}
+
+如果 v4l2_device 父设备的 mdev 域为非 NULL 值，视频设备实体将自动
+注册为媒体设备。
+
+注册哪种设备是根据类型（type）参数。存在以下类型：
+
+VFL_TYPE_GRABBER: 用于视频输入/输出设备的 videoX
+VFL_TYPE_VBI: 用于垂直消隐数据的 vbiX (例如，隐藏式字幕，图文电视)
+VFL_TYPE_RADIO: 用于广播调谐器的 radioX
+
+最后一个参数让你确定一个所控制设备的设备节点号数量(例如 videoX 中的 X)。
+通常你可以传入-1，让 v4l2 框架自己选择第一个空闲的编号。但是有时用户
+需要选择一个特定的节点号。驱动允许用户通过驱动模块参数选择一个特定的
+设备节点号是很普遍的。这个编号将会传递给这个函数，且 video_register_device
+将会试图选择这个设备节点号。如果这个编号被占用，下一个空闲的设备节点
+编号将被选中，并向内核日志中发送一个警告信息。
+
+另一个使用场景是当驱动创建多个设备时。这种情况下，对不同的视频设备在
+编号上使用不同的范围是很有用的。例如，视频捕获设备从 0 开始，视频
+输出设备从 16 开始。所以你可以使用最后一个参数来指定设备节点号最小值，
+而 v4l2 框架会试图选择第一个的空闲编号（等于或大于你提供的编号）。
+如果失败，则它会就选择第一个空闲的编号。
+
+由于这种情况下，你会忽略无法选择特定设备节点号的警告，则可调用
+video_register_device_no_warn() 函数避免警告信息的产生。
+
+只要设备节点被创建，一些属性也会同时创建。在 /sys/class/video4linux
+目录中你会找到这些设备。例如进入其中的 video0 目录，你会看到‘name’和
+‘index’属性。‘name’属性值就是 video_device 结构体中的‘name’域。
+
+‘index’属性值就是设备节点的索引值：每次调用 video_register_device()，
+索引值都递增 1 。第一个视频设备节点总是从索引值 0 开始。
+
+用户可以设置 udev 规则，利用索引属性生成花哨的设备名（例如：用‘mpegX’
+代表 MPEG 视频捕获设备节点）。
+
+在设备成功注册后，就可以使用这些域：
+
+- vfl_type: 传递给 video_register_device 的设备类型。
+- minor: 已指派的次设备号。
+- num: 设备节点编号 (例如 videoX 中的 X)。
+- index: 设备索引号。
+
+如果注册失败，你必须调用 video_device_release() 来释放已分配的
+video_device 结构体；如果 video_device 是嵌入在自己创建的结构体中，
+你也必须释放它。vdev->release() 回调不会在注册失败之后被调用，
+你也不应试图在注册失败后注销设备。
+
+
+video_device 注销
+----------------
+
+当视频设备节点已被移除，不论是卸载驱动还是USB设备断开，你都应注销
+它们：
+
+	video_unregister_device(vdev);
+
+这个操作将从 sysfs 中移除设备节点（导致 udev 将其从 /dev 中移除）。
+
+video_unregister_device() 返回之后，就无法完成打开操作。尽管如此，
+USB 设备的情况则不同，某些应用程序可能依然打开着其中一个已注销设备
+节点。所以在注销之后，所有文件操作（当然除了 release ）也应返回错误值。
+
+当最后一个视频设备节点的用户退出，则 vdev->release() 回调会被调用，
+并且你可以做最后的清理操作。
+
+不要忘记清理与视频设备相关的媒体入口（如果被初始化过）：
+
+	media_entity_cleanup(&vdev->entity);
+
+这可以在 release 回调中完成。
+
+
+video_device 辅助函数
+---------------------
+
+一些有用的辅助函数如下：
+
+- file/video_device 私有数据
+
+你可以用以下函数在 video_device 结构体中设置/获取驱动私有数据：
+
+void *video_get_drvdata(struct video_device *vdev);
+void video_set_drvdata(struct video_device *vdev, void *data);
+
+注意：在调用 video_register_device() 前执行 video_set_drvdata()
+是安全的。
+
+而以下函数：
+
+struct video_device *video_devdata(struct file *file);
+
+返回 file 结构体中拥有的的 video_device 指针。
+
+video_drvdata 辅助函数结合了 video_get_drvdata 和 video_devdata
+的功能：
+
+void *video_drvdata(struct file *file);
+
+你可以使用如下代码从 video_device 结构体中获取 v4l2_device 结构体
+指针：
+
+struct v4l2_device *v4l2_dev = vdev->v4l2_dev;
+
+- 设备节点名
+
+video_device 设备节点在内核中的名称可以通过以下函数获得
+
+const char *video_device_node_name(struct video_device *vdev);
+
+这个名字被用户空间工具（例如 udev）作为提示信息使用。应尽可能使用
+此功能，而非访问 video_device::num 和 video_device::minor 域。
+
+
+视频缓冲辅助函数
+---------------
+
+v4l2 核心 API 提供了一个处理视频缓冲的标准方法(称为“videobuf”)。
+这些方法使驱动可以通过统一的方式实现 read()、mmap() 和 overlay()。
+目前在设备上支持视频缓冲的方法有分散/聚集 DMA(videobuf-dma-sg)、
+线性 DMA(videobuf-dma-contig)以及大多用于 USB 设备的用 vmalloc
+分配的缓冲(videobuf-vmalloc)。
+
+请参阅 Documentation/video4linux/videobuf，以获得更多关于 videobuf
+层的使用信息。
+
+v4l2_fh 结构体
+-------------
+
+v4l2_fh 结构体提供一个保存用于 V4L2 框架的文件句柄特定数据的简单方法。
+如果 video_device 的 flag 设置了 V4L2_FL_USE_FH_PRIO 标志，新驱动
+必须使用 v4l2_fh 结构体，因为它也用于实现优先级处理（VIDIOC_G/S_PRIORITY）。
+
+v4l2_fh 的用户（位于 V4l2 框架中，并非驱动）可通过测试
+video_device->flags 中的 V4L2_FL_USES_V4L2_FH 位得知驱动是否使用
+v4l2_fh 作为他的 file->private_data 指针。这个位会在调用 v4l2_fh_init()
+时被设置。
+
+v4l2_fh 结构体作为驱动自身文件句柄结构体的一部分被分配，且驱动在
+其打开函数中将 file->private_data 指向它。
+
+在许多情况下，v4l2_fh 结构体会嵌入到一个更大的结构体中。这钟情况下，
+应该在 open() 中调用 v4l2_fh_init+v4l2_fh_add，并在 release() 中
+调用 v4l2_fh_del+v4l2_fh_exit。
+
+驱动可以通过使用 container_of 宏提取他们自己的文件句柄结构体。例如：
+
+struct my_fh {
+	int blah;
+	struct v4l2_fh fh;
+};
+
+...
+
+int my_open(struct file *file)
+{
+	struct my_fh *my_fh;
+	struct video_device *vfd;
+	int ret;
+
+	...
+
+	my_fh = kzalloc(sizeof(*my_fh), GFP_KERNEL);
+
+	...
+
+	v4l2_fh_init(&my_fh->fh, vfd);
+
+	...
+
+	file->private_data = &my_fh->fh;
+	v4l2_fh_add(&my_fh->fh);
+	return 0;
+}
+
+int my_release(struct file *file)
+{
+	struct v4l2_fh *fh = file->private_data;
+	struct my_fh *my_fh = container_of(fh, struct my_fh, fh);
+
+	...
+	v4l2_fh_del(&my_fh->fh);
+	v4l2_fh_exit(&my_fh->fh);
+	kfree(my_fh);
+	return 0;
+}
+
+以下是 v4l2_fh 函数使用的简介：
+
+void v4l2_fh_init(struct v4l2_fh *fh, struct video_device *vdev)
+
+  初始化文件句柄。这*必须*在驱动的 v4l2_file_operations->open()
+  函数中执行。
+
+void v4l2_fh_add(struct v4l2_fh *fh)
+
+  添加一个 v4l2_fh 到 video_device 文件句柄列表。一旦文件句柄
+  初始化完成就必须调用。
+
+void v4l2_fh_del(struct v4l2_fh *fh)
+
+  从 video_device() 中解除文件句柄的关联。文件句柄的退出函数也
+  将被调用。
+
+void v4l2_fh_exit(struct v4l2_fh *fh)
+
+  清理文件句柄。在清理完 v4l2_fh 后，相关内存会被释放。
+
+
+如果 v4l2_fh 不是嵌入在其他结构体中的，则可以用这些辅助函数：
+
+int v4l2_fh_open(struct file *filp)
+
+  分配一个 v4l2_fh 结构体空间，初始化并将其添加到 file 结构体相关的
+  video_device 结构体中。
+
+int v4l2_fh_release(struct file *filp)
+
+  从 file 结构体相关的 video_device 结构体中删除 v4l2_fh ，清理
+  v4l2_fh 并释放空间。
+
+这两个函数可以插入到 v4l2_file_operation 的 open() 和 release()
+操作中。
+
+
+某些驱动需要在第一个文件句柄打开和最后一个文件句柄关闭的时候做些
+工作。所以加入了两个辅助函数以检查 v4l2_fh 结构体是否是相关设备
+节点打开的唯一文件句柄。
+
+int v4l2_fh_is_singular(struct v4l2_fh *fh)
+
+  如果此文件句柄是唯一打开的文件句柄，则返回 1 ，否则返回 0 。
+
+int v4l2_fh_is_singular_file(struct file *filp)
+
+  功能相同，但通过 filp->private_data 调用 v4l2_fh_is_singular。
+
+
+V4L2 事件机制
+-----------
+
+V4L2 事件机制提供了一个通用的方法将事件传递到用户空间。驱动必须使用
+v4l2_fh 才能支持 V4L2 事件机制。
+
+
+事件通过一个类型和选择 ID 来定义。ID 对应一个 V4L2 对象，例如
+一个控制 ID。如果未使用，则 ID 为 0。
+
+当用户订阅一个事件，驱动会为此分配一些 kevent 结构体。所以每个
+事件组（类型、ID）都会有自己的一套 kevent 结构体。这保证了如果
+一个驱动短时间内产生了许多同类事件，不会覆盖其他类型的事件。
+
+但如果你收到的事件数量大于同类事件 kevent 的保存数量，则最早的
+事件将被丢弃，并加入新事件。
+
+此外，v4l2_subscribed_event 结构体内部有可供驱动设置的 merge() 和
+replace() 回调，这些回调会在新事件产生且没有多余空间的时候被调用。
+replace() 回调让你可以将早期事件的净荷替换为新事件的净荷，将早期
+净荷的相关数据合并到替换进来的新净荷中。当该类型的事件仅分配了一个
+kevent 结构体时，它将被调用。merge() 回调让你可以合并最早的事件净荷
+到在它之后的那个事件净荷中。当该类型的事件分配了两个或更多 kevent
+结构体时，它将被调用。
+
+这种方法不会有状态信息丢失，只会导致中间步骤信息丢失。
+
+
+关于 replace/merge 回调的一个不错的例子在 v4l2-event.c 中：用于
+控制事件的 ctrls_replace() 和 ctrls_merge() 回调。
+
+注意：这些回调可以在中断上下文中调用，所以它们必须尽快完成并退出。
+
+有用的函数：
+
+void v4l2_event_queue(struct video_device *vdev, const struct v4l2_event *ev)
+
+  将事件加入视频设备的队列。驱动仅负责填充 type 和 data 域。
+  其他域由 V4L2 填充。
+
+int v4l2_event_subscribe(struct v4l2_fh *fh,
+			 struct v4l2_event_subscription *sub, unsigned elems,
+			 const struct v4l2_subscribed_event_ops *ops)
+
+  video_device->ioctl_ops->vidioc_subscribe_event 必须检测驱动能
+  产生特定 id 的事件。然后调用 v4l2_event_subscribe() 来订阅该事件。
+
+  elems 参数是该事件的队列大小。若为 0，V4L2 框架将会（根据事件类型）
+  填充默认值。
+
+  ops 参数允许驱动指定一系列回调：
+  * add:     当添加一个新监听者时调用（重复订阅同一个事件，此回调
+             仅被执行一次）。
+  * del:     当一个监听者停止监听时调用。
+  * replace: 用‘新’事件替换‘早期‘事件。
+  * merge:   将‘早期‘事件合并到‘新’事件中。
+  这四个调用都是可选的，如果不想指定任何回调，则 ops 可为 NULL。
+
+int v4l2_event_unsubscribe(struct v4l2_fh *fh,
+			   struct v4l2_event_subscription *sub)
+
+  v4l2_ioctl_ops 结构体中的 vidioc_unsubscribe_event 回调函数。
+  驱动程序可以直接使用 v4l2_event_unsubscribe() 实现退订事件过程。
+
+  特殊的 V4L2_EVENT_ALL 类型，可用于退订所有事件。驱动可能在特殊
+  情况下需要做此操作。
+
+int v4l2_event_pending(struct v4l2_fh *fh)
+
+  返回未决事件的数量。有助于实现轮询（poll）操作。
+
+事件通过 poll 系统调用传递到用户空间。驱动可用
+v4l2_fh->wait (wait_queue_head_t 类型)作为参数调用 poll_wait()。
+
+事件分为标准事件和私有事件。新的标准事件必须使用可用的最小事件类型
+编号。驱动必须从他们本类型的编号起始处分配事件。类型的编号起始为
+V4L2_EVENT_PRIVATE_START + n * 1000 ，其中 n 为可用最小编号。每个
+类型中的第一个事件类型编号是为以后的使用保留的，所以第一个可用事件
+类型编号是‘class base + 1’。
+
+V4L2 事件机制的使用实例可以在 OMAP3 ISP 的驱动
+(drivers/media/video/omap3isp)中找到。
diff --git a/MAINTAINERS b/MAINTAINERS
index b17587d..f9d40d1 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -595,7 +595,6 @@ M:	Will Deacon <will.deacon@arm.com>
 S:	Maintained
 F:	arch/arm/kernel/perf_event*
 F:	arch/arm/oprofile/common.c
-F:	arch/arm/kernel/pmu.c
 F:	arch/arm/include/asm/pmu.h
 F:	arch/arm/kernel/hw_breakpoint.c
 F:	arch/arm/include/asm/hw_breakpoint.h
@@ -665,15 +664,6 @@ L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:	Maintained
 F:	arch/arm/mach-bcmring
 
-ARM/BCMRING MTD NAND DRIVER
-M:	Jiandong Zheng <jdzheng@broadcom.com>
-M:	Scott Branden <sbranden@broadcom.com>
-L:	linux-mtd@lists.infradead.org
-S:	Maintained
-F:	drivers/mtd/nand/bcm_umi_nand.c
-F:	drivers/mtd/nand/bcm_umi_bch.c
-F:	drivers/mtd/nand/nand_bcm_umi.h
-
 ARM/CALXEDA HIGHBANK ARCHITECTURE
 M:	Rob Herring <rob.herring@calxeda.com>
 L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@ -777,6 +767,7 @@ S:	Maintained
 T:	git git://git.pengutronix.de/git/imx/linux-2.6.git
 F:	arch/arm/mach-imx/
 F:	arch/arm/plat-mxc/
+F:	arch/arm/configs/imx*_defconfig
 
 ARM/FREESCALE IMX6
 M:	Shawn Guo <shawn.guo@linaro.org>
@@ -913,6 +904,12 @@ W:	http://www.digriz.org.uk/ts78xx/kernel
 S:	Maintained
 F:	arch/arm/mach-orion5x/ts78xx-*
 
+ARM/MICREL KS8695 ARCHITECTURE
+M:	Greg Ungerer <gerg@uclinux.org>
+L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+F:	arch/arm/mach-ks8695
+S:	Odd Fixes
+
 ARM/MIOA701 MACHINE SUPPORT
 M:	Robert Jarzmik <robert.jarzmik@free.fr>
 L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@ -1073,7 +1070,7 @@ L:	linux-media@vger.kernel.org
 S:	Maintained
 F:	arch/arm/plat-s5p/dev-fimc*
 F:	arch/arm/plat-samsung/include/plat/*fimc*
-F:	drivers/media/video/s5p-fimc/
+F:	drivers/media/platform/s5p-fimc/
 
 ARM/SAMSUNG S5P SERIES Multi Format Codec (MFC) SUPPORT
 M:	Kyungmin Park <kyungmin.park@samsung.com>
@@ -1083,7 +1080,7 @@ L:	linux-arm-kernel@lists.infradead.org
 L:	linux-media@vger.kernel.org
 S:	Maintained
 F:	arch/arm/plat-s5p/dev-mfc.c
-F:	drivers/media/video/s5p-mfc/
+F:	drivers/media/platform/s5p-mfc/
 
 ARM/SAMSUNG S5P SERIES TV SUBSYSTEM SUPPORT
 M:	Kyungmin Park <kyungmin.park@samsung.com>
@@ -1091,7 +1088,7 @@ M:	Tomasz Stanislawski <t.stanislaws@samsung.com>
 L:	linux-arm-kernel@lists.infradead.org
 L:	linux-media@vger.kernel.org
 S:	Maintained
-F:	drivers/media/video/s5p-tv/
+F:	drivers/media/platform/s5p-tv/
 
 ARM/SHMOBILE ARM ARCHITECTURE
 M:	Paul Mundt <lethal@linux-sh.org>
@@ -1209,6 +1206,12 @@ S:	Maintained
 F:	arch/arm/mach-pxa/z2.c
 F:	arch/arm/mach-pxa/include/mach/z2.h
 
+ARM64 PORT (AARCH64 ARCHITECTURE)
+M:	Catalin Marinas <catalin.marinas@arm.com>
+L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S:	Maintained
+F:	arch/arm64/
+
 ASC7621 HARDWARE MONITOR DRIVER
 M:	George Joseph <george.joseph@fairview5.com>
 L:	lm-sensors@lm-sensors.org
@@ -1250,7 +1253,7 @@ F:	include/linux/i2c/at24.h
 
 ATA OVER ETHERNET (AOE) DRIVER
 M:	"Ed L. Cashin" <ecashin@coraid.com>
-W:	http://www.coraid.com/support/linux
+W:	http://support.coraid.com/support/linux
 S:	Supported
 F:	Documentation/aoe/
 F:	drivers/block/aoe/
@@ -1357,7 +1360,7 @@ ATMEL ISI DRIVER
 M:	Josh Wu <josh.wu@atmel.com>
 L:	linux-media@vger.kernel.org
 S:	Supported
-F:	drivers/media/video/atmel-isi.c
+F:	drivers/media/platform/atmel-isi.c
 F:	include/media/atmel-isi.h
 
 ATMEL LCDFB DRIVER
@@ -1518,7 +1521,7 @@ S:	Supported
 F:	drivers/rtc/rtc-bfin.c
 
 BLACKFIN SDH DRIVER
-M:	Cliff Cai <cliff.cai@analog.com>
+M:	Sonic Zhang <sonic.zhang@analog.com>
 L:	uclinux-dist-devel@blackfin.uclinux.org
 W:	http://blackfin.uclinux.org
 S:	Supported
@@ -1613,6 +1616,16 @@ L:	netdev@vger.kernel.org
 S:	Supported
 F:	drivers/net/ethernet/broadcom/bnx2x/
 
+BROADCOM BCM2835 ARM ARCHICTURE
+M:	Stephen Warren <swarren@wwwdotorg.org>
+L:	linux-rpi-kernel@lists.infradead.org (moderated for non-subscribers)
+T:	git git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-rpi.git
+S:	Maintained
+F:	arch/arm/mach-bcm2835/
+F:	arch/arm/boot/dts/bcm2835*
+F:	arch/arm/configs/bcm2835_defconfig
+F:	drivers/*/*bcm2835*
+
 BROADCOM TG3 GIGABIT ETHERNET DRIVER
 M:	Matt Carlson <mcarlson@broadcom.com>
 M:	Michael Chan <mchan@broadcom.com>
@@ -1645,7 +1658,6 @@ F:	drivers/bcma/
 F:	include/linux/bcma/
 
 BROCADE BFA FC SCSI DRIVER
-M:	Jing Huang <huangj@brocade.com>
 M:	Krishna C Gudipati <kgudipat@brocade.com>
 L:	linux-scsi@vger.kernel.org
 S:	Supported
@@ -1695,7 +1707,7 @@ W:	http://linuxtv.org
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
 S:	Maintained
 F:	Documentation/video4linux/bttv/
-F:	drivers/media/video/bt8xx/bttv*
+F:	drivers/media/pci/bt8xx/bttv*
 
 C-MEDIA CMI8788 DRIVER
 M:	Clemens Ladisch <clemens@ladisch.de>
@@ -1725,7 +1737,7 @@ L:	linux-media@vger.kernel.org
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
 S:	Maintained
 F:	Documentation/video4linux/cafe_ccic
-F:	drivers/media/video/marvell-ccic/
+F:	drivers/media/platform/marvell-ccic/
 
 CAIF NETWORK LAYER
 M:	Sjur Braendeland <sjur.brandeland@stericsson.com>
@@ -2114,7 +2126,7 @@ W:	http://linuxtv.org
 W:	http://www.ivtvdriver.org/index.php/Cx18
 S:	Maintained
 F:	Documentation/video4linux/cx18.txt
-F:	drivers/media/video/cx18/
+F:	drivers/media/pci/cx18/
 
 CXGB3 ETHERNET DRIVER (CXGB3)
 M:	Divy Le Ray <divy@chelsio.com>
@@ -2378,11 +2390,6 @@ S:	Maintained
 F:	Documentation/hwmon/dme1737
 F:	drivers/hwmon/dme1737.c
 
-DOCBOOK FOR DOCUMENTATION
-M:	Randy Dunlap <rdunlap@xenotime.net>
-S:	Maintained
-F:	scripts/kernel-doc
-
 DOCKING STATION DRIVER
 M:	Shaohua Li <shaohua.li@intel.com>
 L:	linux-acpi@vger.kernel.org
@@ -2778,8 +2785,8 @@ FC0011 TUNER DRIVER
 M:	Michael Buesch <m@bues.ch>
 L:	linux-media@vger.kernel.org
 S:	Maintained
-F:	drivers/media/common/tuners/fc0011.h
-F:	drivers/media/common/tuners/fc0011.c
+F:	drivers/media/tuners/fc0011.h
+F:	drivers/media/tuners/fc0011.c
 
 FANOTIFY
 M:	Eric Paris <eparis@redhat.com>
@@ -2859,7 +2866,9 @@ F:	include/linux/firewire*.h
 F:	tools/firewire/
 
 FIRMWARE LOADER (request_firmware)
-S:	Orphan
+M:	Ming Lei <ming.lei@canonical.com>
+L:	linux-kernel@vger.kernel.org
+S:	Maintained
 F:	Documentation/firmware_class/
 F:	drivers/base/firmware*.c
 F:	include/linux/firmware.h
@@ -3007,7 +3016,7 @@ M:	Kyungmin Park <kyungmin.park@samsung.com>
 M:	Heungjun Kim <riverful.kim@samsung.com>
 L:	linux-media@vger.kernel.org
 S:	Maintained
-F:	drivers/media/video/m5mols/
+F:	drivers/media/i2c/m5mols/
 F:	include/media/m5mols.h
 
 FUJITSU TABLET EXTRAS
@@ -3105,6 +3114,7 @@ T:	git git://git.secretlab.ca/git/linux-2.6.git
 F:	Documentation/gpio.txt
 F:	drivers/gpio/
 F:	include/linux/gpio*
+F:	include/asm-generic/gpio.h
 
 GRE DEMULTIPLEXER DRIVER
 M:	Dmitry Kozlov <xeb@mail.ru>
@@ -3124,49 +3134,49 @@ M:	Frank Zago <frank@zago.net>
 L:	linux-media@vger.kernel.org
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
 S:	Maintained
-F:	drivers/media/video/gspca/finepix.c
+F:	drivers/media/usb/gspca/finepix.c
 
 GSPCA GL860 SUBDRIVER
 M:	Olivier Lorin <o.lorin@laposte.net>
 L:	linux-media@vger.kernel.org
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
 S:	Maintained
-F:	drivers/media/video/gspca/gl860/
+F:	drivers/media/usb/gspca/gl860/
 
 GSPCA M5602 SUBDRIVER
 M:	Erik Andren <erik.andren@gmail.com>
 L:	linux-media@vger.kernel.org
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
 S:	Maintained
-F:	drivers/media/video/gspca/m5602/
+F:	drivers/media/usb/gspca/m5602/
 
 GSPCA PAC207 SONIXB SUBDRIVER
 M:	Hans de Goede <hdegoede@redhat.com>
 L:	linux-media@vger.kernel.org
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
 S:	Maintained
-F:	drivers/media/video/gspca/pac207.c
+F:	drivers/media/usb/gspca/pac207.c
 
 GSPCA SN9C20X SUBDRIVER
 M:	Brian Johnson <brijohn@gmail.com>
 L:	linux-media@vger.kernel.org
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
 S:	Maintained
-F:	drivers/media/video/gspca/sn9c20x.c
+F:	drivers/media/usb/gspca/sn9c20x.c
 
 GSPCA T613 SUBDRIVER
 M:	Leandro Costantino <lcostantino@gmail.com>
 L:	linux-media@vger.kernel.org
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
 S:	Maintained
-F:	drivers/media/video/gspca/t613.c
+F:	drivers/media/usb/gspca/t613.c
 
 GSPCA USB WEBCAM DRIVER
 M:	Hans de Goede <hdegoede@redhat.com>
 L:	linux-media@vger.kernel.org
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
 S:	Maintained
-F:	drivers/media/video/gspca/
+F:	drivers/media/usb/gspca/
 
 HARD DRIVE ACTIVE PROTECTION SYSTEM (HDAPS) DRIVER
 M:	Frank Seidel <frank@f-seidel.de>
@@ -3420,6 +3430,18 @@ T:	git git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux.git
 S:	Maintained
 F:	arch/ia64/
 
+IBM Power in-Nest Crypto Acceleration
+M:	Kent Yoder <key@linux.vnet.ibm.com>
+L:	linux-crypto@vger.kernel.org
+S:	Supported
+F:	drivers/crypto/nx/
+
+IBM Power 842 compression accelerator
+M:	Robert Jennings <rcj@linux.vnet.ibm.com>
+S:	Supported
+F:	drivers/crypto/nx/nx-842.c
+F:	include/linux/nx842.h
+
 IBM Power Linux RAID adapter
 M:	Brian King <brking@us.ibm.com>
 S:	Supported
@@ -3431,6 +3453,13 @@ L:	netdev@vger.kernel.org
 S:	Supported
 F:	drivers/net/ethernet/ibm/ibmveth.*
 
+IBM Power Virtual SCSI/FC Device Drivers
+M:	Robert Jennings <rcj@linux.vnet.ibm.com>
+L:	linux-scsi@vger.kernel.org
+S:	Supported
+F:	drivers/scsi/ibmvscsi/
+X:	drivers/scsi/ibmvscsi/ibmvstgt.c
+
 IBM ServeRAID RAID DRIVER
 P:	Jack Hammer
 M:	Dave Jeffery <ipslinux@adaptec.com>
@@ -3866,7 +3895,7 @@ T:	git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
 W:	http://www.ivtvdriver.org
 S:	Maintained
 F:	Documentation/video4linux/*.ivtv
-F:	drivers/media/video/ivtv/
+F:	drivers/media/pci/ivtv/
 F:	include/linux/ivtv*
 
 JC42.4 TEMPERATURE SENSOR DRIVER
@@ -4562,7 +4591,7 @@ MOTION EYE VAIO PICTUREBOOK CAMERA DRIVER
 W:	http://popies.net/meye/
 S:	Orphan
 F:	Documentation/video4linux/meye.txt
-F:	drivers/media/video/meye.*
+F:	drivers/media/pci/meye/
 F:	include/linux/meye.h
 
 MOTOROLA IMX MMC/SD HOST CONTROLLER INTERFACE DRIVER
@@ -4644,6 +4673,14 @@ L:	alsa-devel@alsa-project.org
 W:	http://www.native-instruments.com
 F:	sound/usb/caiaq/
 
+NATIVE LINUX KVM TOOL
+M:	Pekka Enberg <penberg@kernel.org>
+M:	Sasha Levin <levinsasha928@gmail.com>
+M:	Asias He <asias.hejun@gmail.com>
+L:	kvm@vger.kernel.org
+S:	Maintained
+F:	tools/kvm/
+
 NCP FILESYSTEM
 M:	Petr Vandrovec <petr@vandrovec.name>
 S:	Odd Fixes
@@ -4798,6 +4835,7 @@ M:	Lauro Ramos Venancio <lauro.venancio@openbossa.org>
 M:	Aloisio Almeida Jr <aloisio.almeida@openbossa.org>
 M:	Samuel Ortiz <sameo@linux.intel.com>
 L:	linux-wireless@vger.kernel.org
+L:	linux-nfc@lists.01.org (moderated for non-subscribers)
 S:	Maintained
 F:	net/nfc/
 F:	include/linux/nfc.h
@@ -4938,8 +4976,10 @@ S:	Maintained
 F:	drivers/mmc/host/omap.c
 
 OMAP HS MMC SUPPORT
+M:	Venkatraman S <svenkatr@ti.com>
+L:	linux-mmc@vger.kernel.org
 L:	linux-omap@vger.kernel.org
-S:	Orphan
+S:	Maintained
 F:	drivers/mmc/host/omap_hsmmc.c
 
 OMAP RANDOM NUMBER GENERATOR SUPPORT
@@ -4965,7 +5005,7 @@ OMAP IMAGE SIGNAL PROCESSOR (ISP)
 M:	Laurent Pinchart <laurent.pinchart@ideasonboard.com>
 L:	linux-media@vger.kernel.org
 S:	Maintained
-F:	drivers/media/video/omap3isp/*
+F:	drivers/media/platform/omap3isp/
 
 OMAP USB SUPPORT
 M:	Felipe Balbi <balbi@ti.com>
@@ -5006,7 +5046,7 @@ M:	Jonathan Corbet <corbet@lwn.net>
 L:	linux-media@vger.kernel.org
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
 S:	Maintained
-F:	drivers/media/video/ov7670.c
+F:	drivers/media/i2c/ov7670.c
 
 ONENAND FLASH DRIVER
 M:	Kyungmin Park <kyungmin.park@samsung.com>
@@ -5321,6 +5361,12 @@ L:	linux-mtd@lists.infradead.org
 S:	Maintained
 F:	drivers/mtd/devices/phram.c
 
+PICOLCD HID DRIVER
+M:	Bruno Prémont <bonbons@linux-vserver.org>
+L:	linux-input@vger.kernel.org
+S:	Maintained
+F:	drivers/hid/hid-picolcd*
+
 PICOXCELL SUPPORT
 M:	Jamie Iles <jamie@jamieiles.com>
 L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@ -5345,7 +5391,7 @@ S:	Maintained
 F:	drivers/pinctrl/spear/
 
 PKTCDVD DRIVER
-M:	Peter Osterlund <petero2@telia.com>
+M:	Jiri Kosina <jkosina@suse.cz>
 S:	Maintained
 F:	drivers/block/pktcdvd.c
 F:	include/linux/pktcdvd.h
@@ -5502,13 +5548,25 @@ L:	cbe-oss-dev@lists.ozlabs.org
 S:	Maintained
 F:	drivers/block/ps3vram.c
 
+PSTORE FILESYSTEM
+M:	Anton Vorontsov <cbouatmailru@gmail.com>
+M:	Colin Cross <ccross@android.com>
+M:	Kees Cook <keescook@chromium.org>
+M:	Tony Luck <tony.luck@intel.com>
+S:	Maintained
+T:	git git://git.infradead.org/users/cbou/linux-pstore.git
+F:	fs/pstore/
+F:	include/linux/pstore*
+F:	drivers/firmware/efivars.c
+F:	drivers/acpi/apei/erst.c
+
 PTP HARDWARE CLOCK SUPPORT
 M:	Richard Cochran <richardcochran@gmail.com>
 S:	Maintained
 W:	http://linuxptp.sourceforge.net/
 F:	Documentation/ABI/testing/sysfs-ptp
 F:	Documentation/ptp/*
-F:	drivers/net/gianfar_ptp.c
+F:	drivers/net/ethernet/freescale/gianfar_ptp.c
 F:	drivers/net/phy/dp83640*
 F:	drivers/ptp/*
 F:	include/linux/ptp_cl*
@@ -5531,7 +5589,7 @@ W:	http://www.isely.net/pvrusb2/
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
 S:	Maintained
 F:	Documentation/video4linux/README.pvrusb2
-F:	drivers/media/video/pvrusb2/
+F:	drivers/media/usb/pvrusb2/
 
 PWM SUBSYSTEM
 M:	Thierry Reding <thierry.reding@avionic-design.de>
@@ -5544,6 +5602,8 @@ F:	Documentation/devicetree/bindings/pwm/
 F:	include/linux/pwm.h
 F:	include/linux/of_pwm.h
 F:	drivers/pwm/
+F:	drivers/video/backlight/pwm_bl.c
+F:	include/linux/pwm_backlight.h
 
 PXA2xx/PXA3xx SUPPORT
 M:	Eric Miao <eric.y.miao@gmail.com>
@@ -5899,9 +5959,9 @@ L:	linux-media@vger.kernel.org
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
 W:	http://www.mihu.de/linux/saa7146
 S:	Maintained
-F:	drivers/media/common/saa7146*
-F:	drivers/media/video/*7146*
-F:	include/media/*7146*
+F:	drivers/media/common/saa7146/
+F:	drivers/media/pci/saa7146/
+F:	include/media/saa7146*
 
 SAMSUNG LAPTOP DRIVER
 M:	Corentin Chary <corentincj@iksaif.net>
@@ -5962,7 +6022,7 @@ M:	Huang Shijie <shijie8@gmail.com>
 M:	Kang Yong <kangyong@telegent.com>
 M:	Zhang Xiaobing <xbzhang@telegent.com>
 S:	Supported
-F:	drivers/media/video/tlg2300
+F:	drivers/media/usb/tlg2300
 
 SC1200 WDT DRIVER
 M:	Zwane Mwaikambo <zwane@arm.linux.org.uk>
@@ -6350,8 +6410,9 @@ M:	Guennadi Liakhovetski <g.liakhovetski@gmx.de>
 L:	linux-media@vger.kernel.org
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
 S:	Maintained
-F:	include/media/v4l2*
-F:	drivers/media/video/v4l2*
+F:	include/media/soc*
+F:	drivers/media/i2c/soc_camera/
+F:	drivers/media/platform/soc_camera/
 
 SOEKRIS NET48XX LED SUPPORT
 M:	Chris Boot <bootc@bootc.net>
@@ -6394,6 +6455,11 @@ W:	http://tifmxx.berlios.de/
 S:	Maintained
 F:	drivers/memstick/host/tifm_ms.c
 
+SONY MEMORYSTICK STANDARD SUPPORT
+M:	Maxim Levitsky <maximlevitsky@gmail.com>
+S:	Maintained
+F:	drivers/memstick/core/ms_block.*
+
 SOUND
 M:	Jaroslav Kysela <perex@perex.cz>
 M:	Takashi Iwai <tiwai@suse.de>
@@ -6777,14 +6843,14 @@ F:	drivers/net/team/
 F:	include/linux/if_team.h
 
 TEGRA SUPPORT
-M:	Colin Cross <ccross@android.com>
-M:	Olof Johansson <olof@lixom.net>
 M:	Stephen Warren <swarren@wwwdotorg.org>
 L:	linux-tegra@vger.kernel.org
 Q:	http://patchwork.ozlabs.org/project/linux-tegra/list/
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-tegra.git
 S:	Supported
 F:	arch/arm/mach-tegra
+F:	arch/arm/boot/dts/tegra*
+F:	arch/arm/configs/tegra_defconfig
 
 TEHUTI ETHERNET DRIVER
 M:	Andy Gospodarek <andy@greyhouse.net>
@@ -7131,15 +7197,6 @@ S:	Maintained
 F:	Documentation/usb/ehci.txt
 F:	drivers/usb/host/ehci*
 
-USB ET61X[12]51 DRIVER
-M:	Luca Risolia <luca.risolia@studio.unibo.it>
-L:	linux-usb@vger.kernel.org
-L:	linux-media@vger.kernel.org
-T:	git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
-W:	http://www.linux-projects.org
-S:	Maintained
-F:	drivers/media/video/et61x251/
-
 USB GADGET/PERIPHERAL SUBSYSTEM
 M:	Felipe Balbi <balbi@ti.com>
 L:	linux-usb@vger.kernel.org
@@ -7309,7 +7366,7 @@ T:	git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
 W:	http://www.linux-projects.org
 S:	Maintained
 F:	Documentation/video4linux/sn9c102.txt
-F:	drivers/media/video/sn9c102/
+F:	drivers/media/usb/sn9c102/
 
 USB SUBSYSTEM
 M:	Greg Kroah-Hartman <gregkh@linuxfoundation.org>
@@ -7344,17 +7401,7 @@ L:	linux-media@vger.kernel.org
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
 W:	http://www.ideasonboard.org/uvc/
 S:	Maintained
-F:	drivers/media/video/uvc/
-
-USB W996[87]CF DRIVER
-M:	Luca Risolia <luca.risolia@studio.unibo.it>
-L:	linux-usb@vger.kernel.org
-L:	linux-media@vger.kernel.org
-T:	git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
-W:	http://www.linux-projects.org
-S:	Maintained
-F:	Documentation/video4linux/w9968cf.txt
-F:	drivers/media/video/w996*
+F:	drivers/media/usb/uvc/
 
 USB WIRELESS RNDIS DRIVER (rndis_wlan)
 M:	Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
@@ -7383,7 +7430,7 @@ T:	git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
 W:	http://royale.zerezo.com/zr364xx/
 S:	Maintained
 F:	Documentation/video4linux/zr364xx.txt
-F:	drivers/media/video/zr364xx.c
+F:	drivers/media/usb/zr364xx/
 
 USER-MODE LINUX (UML)
 M:	Jeff Dike <jdike@addtoit.com>
@@ -7441,7 +7488,7 @@ M:	Marek Szyprowski <m.szyprowski@samsung.com>
 M:	Kyungmin Park <kyungmin.park@samsung.com>
 L:	linux-media@vger.kernel.org
 S:	Maintained
-F:	drivers/media/video/videobuf2-*
+F:	drivers/media/v4l2-core/videobuf2-*
 F:	include/media/videobuf2-*
 
 VIRTIO CONSOLE DRIVER
@@ -7843,7 +7890,7 @@ L:	linux-media@vger.kernel.org
 W:	http://mjpeg.sourceforge.net/driver-zoran/
 T:	Mercurial http://linuxtv.org/hg/v4l-dvb
 S:	Odd Fixes
-F:	drivers/media/video/zoran/
+F:	drivers/media/pci/zoran/
 
 ZS DECSTATION Z85C30 SERIAL DRIVER
 M:	"Maciej W. Rozycki" <macro@linux-mips.org>
diff --git a/Makefile b/Makefile
index a3c11d5..2b2e6c7 100644
--- a/Makefile
+++ b/Makefile
@@ -609,7 +609,11 @@ KBUILD_CFLAGS 	+= $(call cc-option, -femit-struct-debug-baseonly)
 endif
 
 ifdef CONFIG_FUNCTION_TRACER
-KBUILD_CFLAGS	+= -pg
+ifdef CONFIG_HAVE_FENTRY
+CC_USING_FENTRY	:= $(call cc-option, -mfentry -DCC_USING_FENTRY)
+endif
+KBUILD_CFLAGS	+= -pg $(CC_USING_FENTRY)
+KBUILD_AFLAGS	+= $(CC_USING_FENTRY)
 ifdef CONFIG_DYNAMIC_FTRACE
 	ifdef CONFIG_HAVE_C_RECORDMCOUNT
 		BUILD_C_RECORDMCOUNT := y
@@ -648,22 +652,9 @@ ifeq ($(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-goto.sh $(CC)), y)
 endif
 
 # Add user supplied CPPFLAGS, AFLAGS and CFLAGS as the last assignments
-# But warn user when we do so
-warn-assign = \
-$(warning "WARNING: Appending $$K$(1) ($(K$(1))) from $(origin K$(1)) to kernel $$$(1)")
-
-ifneq ($(KCPPFLAGS),)
-        $(call warn-assign,CPPFLAGS)
-        KBUILD_CPPFLAGS += $(KCPPFLAGS)
-endif
-ifneq ($(KAFLAGS),)
-        $(call warn-assign,AFLAGS)
-        KBUILD_AFLAGS += $(KAFLAGS)
-endif
-ifneq ($(KCFLAGS),)
-        $(call warn-assign,CFLAGS)
-        KBUILD_CFLAGS += $(KCFLAGS)
-endif
+KBUILD_CPPFLAGS += $(KCPPFLAGS)
+KBUILD_AFLAGS += $(KAFLAGS)
+KBUILD_CFLAGS += $(KCFLAGS)
 
 # Use --build-id when available.
 LDFLAGS_BUILD_ID = $(patsubst -Wl$(comma)%,%,\
diff --git a/Next/SHA1s b/Next/SHA1s
new file mode 100644
index 0000000..cab546c
--- /dev/null
+++ b/Next/SHA1s
@@ -0,0 +1,202 @@
+Name		SHA1
+----		----
+origin		6f0f9b6b3fcfe5e156f20d4f804f0d505c750b3c
+fixes		9023a4093d6594040fb8142cdd2615d3461caa7a
+kbuild-current	24cc7fb69a5b5edfdff1d38c6a213d6a33648829
+arm-current	bf619faeced5c2beb32a39559e1f1117f88fd702
+m68k-current	3be71847389b017550d302a5f860c11f6ec76862
+powerpc-merge	636802ef96eebe279b22ad9f9dacfe29291e45c7
+sparc		a9e8d1a6b87167116e5779378f1d25ffed2e833b
+net		96af69ea2a83d292238bdba20e4508ee967cf8cb
+sound-current	5d037f9064a8f3b9abbe383cdfb35e159d813711
+pci-current	0ff9514b579b4f2f3e6038cd961ce64c224c3c73
+wireless	a7be50b7e30f9d77cb059a7ffdb781bb0fb92eba
+driver-core.current	5698bd757d55b1bb87edd1a9744ab09c142abfc2
+tty.current	5698bd757d55b1bb87edd1a9744ab09c142abfc2
+usb.current	5698bd757d55b1bb87edd1a9744ab09c142abfc2
+staging.current	5698bd757d55b1bb87edd1a9744ab09c142abfc2
+char-misc.current	fea7a08acb13524b47711625eebea40a0ede69a0
+input-current	35b1da4e1e1026b5195649170dfb9ebb52f808e0
+md-current	58e94ae18478c08229626daece2fc108a4a23261
+audit-current	c158a35c8a681cf68d36f22f058f9f5466386c71
+crypto-current	9b2f4cb65f7083cde86553cd56d6c2878e04932a
+ide		9974e43d900af7979e0a571b8e0c9674c7399b79
+dwmw2		244dc4e54b73567fae7f8fd9ba56584be9375442
+sh-current	44033109e99cf584d6285226ed521098f5ef7250
+irqdomain-current	15e06bf64f686befd2030da867a3dad965b96cc0
+devicetree-current	4e8383b6b06b275999f51337adf7064b2c135a04
+spi-current	d1c185bcb15184ebcbc1b2e003e9a6c4658985c4
+gpio-current	96b70641b937e99c1579cb6ebbcdb7b0af98cdd0
+arm		84230215df895cba1e0177aa8a5af5306960c7a0
+arm-perf	b90c4b95f5cee1ce804e227fa4308f7deb370a3b
+davinci		fe0d42203cb5616eeff68b14576a0f7e2dd56625
+xilinx		b85a3ef4ac65169b65fd2fe9bec7912bbf475ba4
+arm64		0d0109a440ea211e398118752c26d4bad540e604
+blackfin	6895f97e15895625e03c95df904d92befdac7118
+c6x		2547ab374e65029d87c5e5b62b58850f3d3a7add
+cris		2608747768e9a1b039b365a460ebe306fc73d9e1
+hexagon		5042ab91c4272e158748180ae70a2e097f9e90e3
+ia64		0967237ca6521c63822340138e4d62ecf8a3d173
+m68k		f82735d55056b200eab19749398457a2f534306b
+m68knommu	42ec57498163adc43abed35d8fe82cecf97d5da1
+microblaze	a01ee165a132fadb57659d26246e340d6ac53265
+mips		8ca152883aed5a2256646fffb3205b5d1a67abb1
+openrisc	4c8faa4f62d51b4dc8add1d2836b62e42c99c55d
+parisc		5b24c421621792fcc588af6f644d6acf2dd798cc
+s390		dfc09c0800cb73101f2621967bf6994dfb25f519
+sh		16d74ebeb1b056dfc80e69b44cc3a26515db1925
+sparc-next	da201161662b8ee9c8d7bd8cc50ce3cb3366d400
+tile		e70cf54073acb6494620620af2ab993d57ae8d3f
+unicore32	e4baa56a9a94a75580cffc657c7fad8e1d92e9a6
+xtensa		1c6b4c626974de49a795f0a1e8547c6fb3847c69
+ceph		5ce765a540f34d1e2005e1210f49f67fdf11e997
+cifs		1b359204901e182b27aa9da432095cbe2cfd2512
+configfs	b930c26416c4ea6855726fd977145ccea9afbdda
+ecryptfs	0d7614f09c1ebdbaa1599a5aba7593f147bf96ee
+ext3		09e05d4805e6c524c1af74e524e5d0528bb3fef3
+ext4		f9195e3761173e161b5a8d8a0692bc83fd980725
+fuse		c7a3f5e3e7a1e4938a41f0196d4b4ee632b30b38
+gfs2		2216db70c95a9610f5279b8da53bec614d98270f
+jfs		84f4141ee3ea11035f741d4298cb6bbad1850fcf
+logfs		ab2ec19f42dc084880ba9b77e1c153adc1e9c439
+nfs		f743c735b817547b590d36a6e275235c7beb8600
+nfsd		fac7a17b5fd056db969e4b3ec9936679c01f25a5
+ocfs2		4538df64655dcfe17b33080b219dc783161a262e
+omfs		976d167615b64e14bc1491ca51d424e2ba9a5e84
+squashfs	4b0180a49f08dd1c681cdc99edc9e0cec0a833fa
+v9fs		552aad02a283ee88406b102b4d6455eef7127196
+ubifs		3668b70fcf1fdc6799abf15f70fe3f50f407ec82
+xfs		4026c9fde9c67266932afd209e25bfef4474a1be
+vfs		319074ee92c16eb4739653eba96ad1114943ed25
+pci		78c8f84302ce007aedcfa11912fd4aacf22727ab
+powerpc		caa1d631fc99940f866480c2bb88a6f5a235e7a2
+4xx		2074b1d9d53ae696dd3f49482bad43254f40f01d
+mpc5xxx		9d9fd8871b4136755160bf95a9abd0d23d738ddc
+galak		4d56dec5dca496655ef035ef3b80f7c47dc22b77
+hid		45654be988c7d86d925e71611f9f12a42e80c17d
+i2c		cde3336dd460209f66ec00401242079e748e1bfb
+i2c-embedded	2bdbfa9c4a14f0015d1e189b17175a989d7c2a40
+jdelvare-hwmon	46e486ee043a807a7b6b26c607d0aef4c07e9217
+hwmon-staging	592758b12f2e327bb5902dabd3d36b2e86049871
+v4l-dvb		0421fb6ef6581639ede08f20d56a5d6d29d93baf
+kbuild		f4d278bf46c7d7093b95e5dd06f1d3ff4a12e597
+kconfig		45f4c81d690a57838822d4d01ad4c03651b76b95
+libata		633de4cc2c049949459dd0b73d78576cd23906b5
+infiniband	09ef9fd569992c56aacb8c2ee08576bc69a8590f
+pstore		80c9d03c22f13a17df67b4b99a83ed5e9acf6093
+acpi		b76c4c261a65c18f2e27cd57747f60e78163b740
+cpuidle		3cf7997a389de59498c966c529456696ce8bc1a7
+cpupowerutils	f16603386b38c28979f4df1cafdc2fe73fa87d37
+thermal		cf68bdc1353572bce029300272451034a69745c9
+ieee1394	52439d605d6604c15954281a1d2831471dbd024c
+ubi		9bfd58fa5f7f56e1e2ffc49c10149ced3640033f
+dlm		2b75bc9121e54e22537207b47b71373bcb0be41c
+scsi		3da4202c7639db4f74bebe8a2e4b3a56327953b3
+target-updates	f25590f39d543272f7ae7b00d533359c8d7ff331
+target-merge	d9875690d9b89a866022ff49e3fcea892345ad92
+ibft		935a9fee51c945b8942be2d7b4bae069167b4886
+isci		6734092e66011def7875bd67beef889d0fee1cc9
+slave-dma	027478851791df751176398be02a3b1c5f6aa824
+dmaengine	a2bd1140a264b561e38d99e656cd843c2d840e86
+net-next	842b08bbee448b2069aaebb7f18b40942ad2a1bd
+wireless-next	944f8a1a6f5ff8b503f3544811d0aa4ac27dd2aa
+bluetooth	90e6274d2ecf3bcb44e3727a395e56b7ef467218
+mtd		2361f738b67ab7f1152187fa3d321a09b7c95c09
+l2-mtd		42ae99e288e512254492b16e9c87c75c49606ca4
+crypto		821873abc20e28fe3faa98591dab91d9b00700a5
+drm		7facf16690dc4160e5ff605271704183ff56b2d9
+sound		b7ef37d0e382298bcf7ba399ce67b044d9add23a
+sound-asoc	f76fe059dd5034c55c560d9e0005e19481843726
+rr		2feb41c726bbd62147cfce7b821c8a8f0d2787ba
+input		fb4f552e895cec29934d94a99cbd1f1f00448a88
+input-mt	51c80b74002f86477d691ed7c8ac479dcfa6271c
+cgroup		c0a93e2857b16ef01659e056eb276a55d7718134
+block		1b6576ccd0d9ac0f5a84e0864a43362cc0f6b39f
+device-mapper	8c05ce49d40e9faedd5285b43749714a68ba363b
+embedded	4744b43431e8613f920c5cba88346756f53c5165
+firmware	6e03a201bbe8137487f340d26aa662110e324b20
+pcmcia		80af9e6d7ae633309cc5bca96aee6a45117e7c98
+mmc		b9418b14d1980b9d14388c5c0fcad3e7ec3bea59
+kgdb		15d7ea09071e85388729062e4df0224593a6db5d
+slab		f90765d77d1fcbdbbcfdd8c019ab8e5fa65f916e
+uclinux		5e442a493fc59fa536c76db1fff5b49ca36a88c5
+md		0179d361662367ab0f80b5822b162a1c0ba9b57d
+mfd		396f70be54f026a6601012a73db87dc75c6d8f1d
+battery		18766f0936d444fd7ff2e0064bd6e69a89d5c6fc
+fbdev		ebe9f7b02590d870506ef493483fe4abdb08e967
+viafb		838ac785d521e091bd8b5f6a2b545166f5f32b77
+omap_dss2	6659145746bcf01ac650c76e5736c5003c2db230
+regulator	ca3184addf398cc402ceaece1ea5451afc8537e8
+security	0a72ba7aff26fb6e918cee6d2bbfd289069f10ae
+selinux		c2d7b247f0c028d325a5da5b9611b60ba160f237
+lblnet		7e27d6e778cd87b6f2415515d7127eba53fe5d02
+watchdog	fea16668629d9f2ce4a670d349e428083af59c81
+dwmw2-iommu	c3b92c8787367a8bb53d57d9789b558f1295cc96
+iommu		08a49c34fe37a11a51f99f4c0cf867655d055bb0
+vfio		b68e7fa879cd3b1126a7c455d9da1b70299efc0d
+osd		b8017d2957fb0ebf0c2aa91d48f2465f6f799738
+jc_docs		5c050fb96380a87a85aad9084b68fdcd2b84c193
+trivial		7dfd8cc536dc4984ee92d9a8863ea705b955bc37
+audit		dcd6c92267155e70a94b3927bce681ce74b80d1f
+pm		1ac9af79e28fe85b65cf22edd86fc2ebead518a4
+apm		fb9d78aca709b7a6389c79d6211fb384c69bb79f
+fsnotify	1aec9c0d718693553543349e92138033b0bcea4c
+edac		cfe503149482bf0bb76ff453b44dedd5e801870f
+edac-amd	305f1c3cfd7eef63bef2128b6934a9054d902976
+devicetree	efd68e7254503f3207805f674a1ea1d743f5dfe2
+dt-rh		ee67016fcc58998c44a9c99b0721568b3d2edc6e
+spi		d8e328b3bd65fdefc9c49a27ee80c28e0a44b653
+spi-mb		08896f71b3b8b60fabd371fd3c65132684babf8f
+tip		cd216c4105e7cf0285219e115af00abc04fb921c
+rcu		593d1006cdf710ab3469c0c37c184fea0bc3da97
+cputime		c3e0ef9a298e028a82ada28101ccd5cf64d209ee
+uprobes		0326f5a94ddea33fa331b2519f4172f4fb387baa
+kmemleak	48786770bf3b3a47bda766ba5f711199e7f24d8f
+kvm		1e08ec4a130e2745d96df169e67c58df98a07311
+kvm-ppc		8f1aeaa46db8885546b10b8b25f5d0450593f356
+oprofile	61bccf191fe2d55b8d003b4ea3f94913745aaefa
+xen		af3a3ab2966112c0d0a44df7eeb1e95fe32d4495
+xen-two		526c795eb8244bc2a2e869ff466941527a5366be
+xen-pvhvm	b056b6a0144de90707cd22cf7b4f60bf69c86d59
+percpu		6101167727932a929e37fb8a6eeb68bdbf54d58e
+workqueues	2b0f620dfe3e869e4665030d2599ede49c662d83
+drivers-x86	455f38ccba672b33cda0a96cf9089be312ba95de
+hwpoison	46e387bbd82d438b9131e237e6e2cb55a825da49
+sysctl		4e474a00d7ff746ed177ddae14fa8b2d4bad7a00
+regmap		613dac31a612f9417bd1b1438acebbc3b8f9073e
+hsi		43139a61fc68f4b0af7327a0e63f340a7c81c69a
+leds		2f73c3927318abe3d7fcaecadfbad89e2d12f881
+driver-core	666f355f3805d68b6ed5f7013806f1f65abfbf03
+tty		4dac2116547b4aab7ac327edb344bb68ed1e8839
+usb		655db7980596f0ad4f15f8f4c51beb3e705762de
+staging		9970eeae4854e0eee03e5e467ace4ec7cbf36d1f
+char-misc	65929215d85702dd4a76db0ba9fbfc022ab99e55
+tmem		a728d5ea1c20adbc4997287d8f17c528bda7ce8c
+writeback	0e2f2b23672055e1301c11509d5b8eda7b718d8e
+arm-dt		ede338f4ce2fb5ee99d18751df32fbd3b10df268
+hwspinlock	8b37fcfc9b3400b647748783a2cafff67793e0ad
+pinctrl		01194d60672b8996f3b43f474da09941aa20dee6
+vhost		e0953c8b85baaa38d77ebd5dc4051bc3837c1191
+memblock	7bd0b0f0da3b1ec11cbcc798eb0ef747a1184077
+remoteproc	ec4d02d9180f407c41f8310a13b34e473c671fbb
+irqdomain	f5a1ad057e6da5d0fc9c5677ff44797d193d3e62
+gpio		ddf343f635fe4440cad528e12f96f28bd50aa099
+gpio-lw		6b6fe01500d59b3bd1f2163d180d74be833b9b90
+arm-soc		143fe301012e71ccbd9ad3aa6c6b880a05ca3eca
+ep93xx		70f0f7c302ed9bdbc626b380a16bdbac62513adb
+ixp4xx		2346020ac8e07d1a83b8471eb86056f581d9c08c
+msm		fe3a47b1c7cd74a7e39cec1fa0d89bd3724f4f65
+renesas		cadd90f8304d617b18cf3ae085448e58015897bd
+samsung		d211921aefb7bc50a23ac83b98a79205b3d46fd6
+tegra		979570e02981d4a8fc20b3cc8fd651856c98ee9d
+kvmtool		5a337ac3c4d0ae3b078912396b90de35fa11e7f0
+dma-mapping	8aa8bee5828cbb2576bb030219d9681416edd1db
+pwm		6173f8f4ed9c2bd4184908e35f46755a0d14b0f2
+dma-buf		56d27adcb536b7430d5f8a6240df8ad261eb00bd
+userns		72235465864d84cedb2d9f26f8e1de824ee20339
+ktest		648a182c615272f01b5cda01dc87a16de9f695bb
+signal		3af7caed0252a28f688a4979e2128a8218f22141
+clk		494bfec99922d54054d2d0873f1017680cfc3f13
+random		d2e7c96af1e54b507ae2a6a7dd2baf588417a7e5
+scsi-post-merge	65112dccf8a113737684366349d7f9ec373ddc47
+akpm		dad0019944369f58c193c1991c39ffda7ff584d2
diff --git a/Next/Trees b/Next/Trees
new file mode 100644
index 0000000..1ff2fab
--- /dev/null
+++ b/Next/Trees
@@ -0,0 +1,204 @@
+Trees included into this release:
+
+Name		Type	URL
+----		----	---
+origin		git	git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git#master
+fixes		git	git://git.kernel.org/pub/scm/linux/kernel/git/sfr/next-fixes.git#master
+kbuild-current	git	git://git.kernel.org/pub/scm/linux/kernel/git/mmarek/kbuild.git#rc-fixes
+arm-current	git	git://ftp.arm.linux.org.uk/pub/linux/arm/kernel/git-cur/linux-arm.git#fixes
+m68k-current	git	git://git.kernel.org/pub/scm/linux/kernel/git/geert/linux-m68k.git#for-linus
+powerpc-merge	git	git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc.git#merge
+sparc		git	git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc.git#master
+net		git	git://git.kernel.org/pub/scm/linux/kernel/git/davem/net.git#master
+sound-current	git	git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git#for-linus
+pci-current	git	git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git#for-linus
+wireless	git	git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless.git#master
+driver-core.current	git	git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core.git#driver-core-linus
+tty.current	git	git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty.git#tty-linus
+usb.current	git	git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git#usb-linus
+staging.current	git	git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git#staging-linus
+char-misc.current	git	git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git#char-misc-linus
+input-current	git	git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git#for-linus
+md-current	git	git://neil.brown.name/md#for-linus
+audit-current	git	git://git.kernel.org/pub/scm/linux/kernel/git/viro/audit.git#for-linus
+crypto-current	git	git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6.git#master
+ide		git	git://git.kernel.org/pub/scm/linux/kernel/git/davem/ide.git#master
+dwmw2		git	git://git.infradead.org/users/dwmw2/random-2.6.git#master
+sh-current	git	git://github.com/pmundt/linux-sh.git#sh-fixes-for-linus
+irqdomain-current	git	git://git.secretlab.ca/git/linux-2.6.git#irqdomain/merge
+devicetree-current	git	git://git.secretlab.ca/git/linux-2.6#devicetree/merge
+spi-current	git	git://git.secretlab.ca/git/linux-2.6#spi/merge
+gpio-current	git	git://git.secretlab.ca/git/linux-2.6#gpio/merge
+arm		git	git://ftp.arm.linux.org.uk/pub/linux/arm/kernel/git-cur/linux-arm.git#for-next
+arm-perf	git	git://git.kernel.org/pub/scm/linux/kernel/git/will/linux.git#for-next/perf
+davinci		git	git://gitorious.org/linux-davinci/linux-davinci.git#davinci-next
+xilinx		git	git://git.xilinx.com/linux-2.6-xlnx.git#arm-next
+arm64		git	git://git.kernel.org/pub/scm/linux/kernel/git/cmarinas/linux-aarch64.git#upstream
+blackfin	git	git://git.kernel.org/pub/scm/linux/kernel/git/lliubbo/blackfin.git#for-linus
+c6x		git	git://linux-c6x.org/git/projects/linux-c6x-upstreaming.git#for-linux-next
+cris		git	git://www.jni.nu/cris.git#for-next
+hexagon		git	git://git.kernel.org/pub/scm/linux/kernel/git/rkuo/linux-hexagon-kernel.git#linux-next
+ia64		git	git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux.git#next
+m68k		git	git://git.kernel.org/pub/scm/linux/kernel/git/geert/linux-m68k.git#for-next
+m68knommu	git	git://git.kernel.org/pub/scm/linux/kernel/git/gerg/m68knommu.git#for-next
+microblaze	git	git://git.monstr.eu/linux-2.6-microblaze.git#next
+mips		git	git://git.linux-mips.org/pub/scm/ralf/upstream-sfr.git#mips-for-linux-next
+openrisc	git	git://openrisc.net/jonas/linux#for-upstream
+parisc		git	git://git.kernel.org/pub/scm/linux/kernel/git/jejb/parisc-2.6.git#for-next
+s390		git	git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux.git#features
+sh		git	git://github.com/pmundt/linux-sh.git#sh-latest
+sparc-next	git	git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-next.git#master
+tile		git	git://git.kernel.org/pub/scm/linux/kernel/git/cmetcalf/linux-tile.git#master
+unicore32	git	git://github.com/gxt/linux.git#unicore32
+xtensa		git	git://github.com/czankel/xtensa-linux.git#for_next
+ceph		git	git://github.com/ceph/ceph-client.git#master
+cifs		git	git://git.samba.org/sfrench/cifs-2.6.git#for-next
+configfs	git	git://git.kernel.org/pub/scm/linux/kernel/git/jlbec/configfs.git#linux-next
+ecryptfs	git	git://git.kernel.org/pub/scm/linux/kernel/git/tyhicks/ecryptfs.git#next
+ext3		git	git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs.git#for_next
+ext4		git	git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4.git#dev
+fuse		git	git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse.git#for-next
+gfs2		git	git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-3.0-nmw.git#master
+jfs		git	git://github.com/kleikamp/linux-shaggy.git#jfs-next
+logfs		git	git://github.com/prasad-joshi/logfs_upstream.git#master
+nfs		git	git://git.linux-nfs.org/projects/trondmy/nfs-2.6.git#linux-next
+nfsd		git	git://git.linux-nfs.org/~bfields/linux.git#nfsd-next
+ocfs2		git	git://git.kernel.org/pub/scm/linux/kernel/git/jlbec/ocfs2.git#linux-next
+omfs		git	git://github.com/bcopeland/omfs.git#for-next
+squashfs	git	git://git.kernel.org/pub/scm/linux/kernel/git/pkl/squashfs-next.git#master
+v9fs		git	git://git.kernel.org/pub/scm/linux/kernel/git/ericvh/v9fs.git#for-next
+ubifs		git	git://git.infradead.org/ubifs-2.6.git#linux-next
+xfs		git	git://oss.sgi.com/xfs/xfs.git#for-next
+vfs		git	git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6.git#for-next
+pci		git	git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git#next
+powerpc		git	git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc.git#next
+4xx		git	git://git.kernel.org/pub/scm/linux/kernel/git/jwboyer/powerpc-4xx.git#next
+mpc5xxx		git	git://git.denx.de/linux-2.6-agust.git#next
+galak		git	git://git.kernel.org/pub/scm/linux/kernel/git/galak/powerpc.git#next
+hid		git	git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid.git#for-next
+i2c		quilt	http://khali.linux-fr.org/devel/linux-3/jdelvare-i2c/
+i2c-embedded	git	git://git.pengutronix.de/git/wsa/linux.git#i2c-embedded/for-next
+jdelvare-hwmon	quilt	http://khali.linux-fr.org/devel/linux-3/jdelvare-hwmon/
+hwmon-staging	git	git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging.git#hwmon-next
+v4l-dvb		git	git://linuxtv.org/mchehab/media-next.git#master
+kbuild		git	git://git.kernel.org/pub/scm/linux/kernel/git/mmarek/kbuild.git#for-next
+kconfig		git	git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-kconfig.git#for-next
+libata		git	git://git.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev.git#NEXT
+infiniband	git	git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband.git#for-next
+pstore		git	git://git.infradead.org/users/cbou/linux-pstore.git#master
+acpi		git	git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux.git#next
+cpuidle		git	git://git.linaro.org/people/dlezcano/cpuidle-next.git#cpuidle-next
+cpupowerutils	git	git://git.kernel.org/pub/scm/linux/kernel/git/brodo/cpupowerutils.git#master
+thermal		git	git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux.git#next
+ieee1394	git	git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394.git#for-next
+ubi		git	git://git.infradead.org/ubi-2.6.git#linux-next
+dlm		git	git://git.kernel.org/pub/scm/linux/kernel/git/teigland/linux-dlm.git#next
+scsi		git	git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git#for-next
+target-updates	git	git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending.git#for-next
+target-merge	git	git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending.git#for-next-merge
+ibft		git	git://git.kernel.org/pub/scm/linux/kernel/git/konrad/ibft.git#linux-next
+isci		git	git://git.kernel.org/pub/scm/linux/kernel/git/djbw/isci.git#all
+slave-dma	git	git://git.infradead.org/users/vkoul/slave-dma.git#next
+dmaengine	git	git://git.kernel.org/pub/scm/linux/kernel/git/djbw/dmaengine.git#next
+net-next	git	git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git#master
+wireless-next	git	git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next.git#master
+bluetooth	git	git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next.git#master
+mtd		git	git://git.infradead.org/mtd-2.6.git#master
+l2-mtd		git	git://git.infradead.org/users/dedekind/l2-mtd-2.6.git#master
+crypto		git	git://git.kernel.org/pub/scm/linux/kernel/git/herbert/cryptodev-2.6.git#master
+drm		git	git://people.freedesktop.org/~airlied/linux.git#drm-next
+sound		git	git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git#for-next
+sound-asoc	git	git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git#for-next
+rr		quilt	http://ozlabs.org/~rusty/kernel/rr-latest/
+input		git	git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git#next
+input-mt	git	git://github.com/rydberg/linux.git#for-next
+cgroup		git	git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup.git#for-next
+block		git	git://git.kernel.dk/linux-block.git#for-next
+device-mapper	quilt	http://people.redhat.com/agk/patches/linux/editing/
+embedded	git	git://git.infradead.org/embedded-2.6.git#master
+firmware	git	git://git.infradead.org/users/dwmw2/firmware-2.6.git#master
+pcmcia		git	git://git.kernel.org/pub/scm/linux/kernel/git/brodo/pcmcia.git#master
+mmc		git	git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc.git#mmc-next
+kgdb		git	git://git.kernel.org/pub/scm/linux/kernel/git/jwessel/kgdb.git#kgdb-next
+slab		git	git://github.com/penberg/linux.git#for-next
+uclinux		git	git://git.kernel.org/pub/scm/linux/kernel/git/gerg/uclinux.git#for-next
+md		git	git://neil.brown.name/md#for-next
+mfd		git	git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6.git#for-next
+battery		git	git://git.infradead.org/battery-2.6.git#master
+fbdev		git	git://github.com/schandinat/linux-2.6.git#fbdev-next
+viafb		git	git://github.com/schandinat/linux-2.6.git#viafb-next
+omap_dss2	git	git://gitorious.org/linux-omap-dss2/linux.git#for-next
+regulator	git	git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator.git#for-next
+security	git	git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security.git#next
+selinux		git	git://git.infradead.org/users/eparis/selinux.git#master
+lblnet		git	git://git.infradead.org/users/pcmoore/lblnet-2.6_next#master
+watchdog	git	git://www.linux-watchdog.org/linux-watchdog-next.git#master
+dwmw2-iommu	git	git://git.infradead.org/iommu-2.6.git#master
+iommu		git	git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git#next
+vfio		git	git://github.com/awilliam/linux-vfio.git#next
+osd		git	git://git.open-osd.org/linux-open-osd.git#linux-next
+jc_docs		git	git://git.lwn.net/linux-2.6.git#docs-next
+trivial		git	git://git.kernel.org/pub/scm/linux/kernel/git/jikos/trivial.git#for-next
+audit		git	git://git.kernel.org/pub/scm/linux/kernel/git/viro/audit.git#for-next
+pm		git	git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git#linux-next
+apm		git	git://git.kernel.org/pub/scm/linux/kernel/git/jikos/apm.git#for-next
+fsnotify	git	git://git.infradead.org/users/eparis/notify.git#for-next
+edac		git	git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-edac.git#linux_next
+edac-amd	git	git://git.kernel.org/pub/scm/linux/kernel/git/bp/bp.git#for-next
+devicetree	git	git://git.secretlab.ca/git/linux-2.6#devicetree/next
+dt-rh		git	git://sources.calxeda.com/kernel/linux.git#for-next
+spi		git	git://git.secretlab.ca/git/linux-2.6#spi/next
+spi-mb		git	git://git.kernel.org/pub/scm/linux/kernel/git/broonie/misc.git#spi-next
+tip		git	git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git#auto-latest
+rcu		git	git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu.git#rcu/next
+cputime		git	git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux.git#cputime
+uprobes		git	git://github.com/srikard/linux.git#for-next
+kmemleak	git	git://git.kernel.org/pub/scm/linux/kernel/git/cmarinas/linux.git#kmemleak
+kvm		git	git://git.kernel.org/pub/scm/virt/kvm/kvm.git#linux-next
+kvm-ppc		git	git://github.com/agraf/linux-2.6.git#kvm-ppc-next
+oprofile	git	git://git.kernel.org/pub/scm/linux/kernel/git/rric/oprofile.git#for-next
+xen		git	git://git.kernel.org/pub/scm/linux/kernel/git/jeremy/xen.git#upstream/xen
+xen-two		git	git://git.kernel.org/pub/scm/linux/kernel/git/konrad/xen.git#linux-next
+xen-pvhvm	git	git://xenbits.xen.org/people/sstabellini/linux-pvhvm.git#linux-next
+percpu		git	git://git.kernel.org/pub/scm/linux/kernel/git/tj/percpu.git#for-next
+workqueues	git	git://git.kernel.org/pub/scm/linux/kernel/git/tj/wq.git#for-next
+drivers-x86	git	git://cavan.codon.org.uk/platform-drivers-x86.git#linux-next
+hwpoison	git	git://git.kernel.org/pub/scm/linux/kernel/git/ak/linux-mce-2.6.git#hwpoison
+sysctl		git	git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/sysctl.git#master
+regmap		git	git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap.git#for-next
+hsi		git	git://gitorious.org/kernel-hsi/kernel-hsi.git#for-next
+leds		git	git://git.kernel.org/pub/scm/linux/kernel/git/cooloney/linux-leds.git#for-next
+driver-core	git	git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core.git#driver-core-next
+tty		git	git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty.git#tty-next
+usb		git	git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git#usb-next
+staging		git	git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git#staging-next
+char-misc	git	git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git#char-misc-next
+tmem		git	git://git.kernel.org/pub/scm/linux/kernel/git/konrad/mm.git#linux-next
+writeback	git	git://git.kernel.org/pub/scm/linux/kernel/git/wfg/linux.git#writeback-for-next
+arm-dt		git	git://git.secretlab.ca/git/linux-2.6#devicetree/arm-next
+hwspinlock	git	git://github.com/ohadbc/hwspinlock-next.git#linux-next
+pinctrl		git	git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl.git#for-next
+vhost		git	git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost.git#linux-next
+memblock	git	git://git.kernel.org/pub/scm/linux/kernel/git/tj/misc.git#memblock-kill-early_node_map
+remoteproc	git	git://git.kernel.org/pub/scm/linux/kernel/git/ohad/remoteproc.git#for-next
+irqdomain	git	git://git.secretlab.ca/git/linux-2.6.git#irqdomain/next
+gpio		git	git://git.secretlab.ca/git/linux-2.6#gpio/next
+gpio-lw		git	git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio.git#for-next
+arm-soc		git	git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc.git#for-next
+ep93xx		git	git://github.com/RyanMallon/linux-ep93xx.git#ep93xx-for-next
+ixp4xx		git	git://git.kernel.org/pub/scm/linux/kernel/git/chris/linux.git#next
+msm		git	git://git.kernel.org/pub/scm/linux/kernel/git/davidb/linux-msm.git#for-next
+renesas		git	git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git#next
+samsung		git	git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git#for-next
+tegra		git	git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-tegra.git#for-next
+kvmtool		git	git://github.com/penberg/linux-kvm.git#master
+dma-mapping	git	git://git.linaro.org/people/mszyprowski/linux-dma-mapping.git#dma-mapping-next
+pwm		git	git://gitorious.org/linux-pwm/linux-pwm.git#for-next
+dma-buf		git	git://git.linaro.org/people/sumitsemwal/linux-dma-buf.git#for-next
+userns		git	git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace.git#for-next
+ktest		git	git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-ktest.git#for-next
+signal		git	git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal.git#for-next
+clk		git	git://git.linaro.org/people/mturquette/linux.git#clk-next
+random		git	git://git.kernel.org/pub/scm/linux/kernel/git/tytso/random.git#dev
+scsi-post-merge	git	git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-post-merge-2.6.git#master
+akpm		mmotm	http://www.ozlabs.org/~akpm/mmotm/
diff --git a/Next/merge.log b/Next/merge.log
new file mode 100644
index 0000000..5dad918
--- /dev/null
+++ b/Next/merge.log
@@ -0,0 +1,17363 @@
+$ date
+Wednesday 26 September  09:55:04 EST 2012
+$ git checkout master
+Already on 'master'
+$ git reset --hard stable
+HEAD is now at 56d27ad Merge git://git.kernel.org/pub/scm/linux/kernel/git/cmetcalf/linux-tile
+Merging origin/master (6f0f9b6 Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net)
+$ git merge origin/master
+Updating 56d27ad..6f0f9b6
+Fast-forward
+ MAINTAINERS                               |    2 ++
+ arch/arm/mach-mxs/mach-mxs.c              |    2 +-
+ drivers/net/phy/bcm87xx.c                 |    2 ++
+ drivers/net/phy/micrel.c                  |   45 +++++++++++++++++++++++------
+ drivers/net/ppp/pppoe.c                   |    2 +-
+ drivers/net/team/team.c                   |   32 +++++++++++++++-----
+ drivers/net/wireless/iwlwifi/pcie/trans.c |    1 +
+ drivers/sh/pfc/pinctrl.c                  |    2 ++
+ include/linux/micrel_phy.h                |   19 ++++++++++--
+ include/linux/security.h                  |    1 +
+ lib/flex_proportions.c                    |    2 +-
+ net/batman-adv/bat_iv_ogm.c               |   13 +++++----
+ net/batman-adv/soft-interface.c           |    7 +++--
+ net/bluetooth/hci_core.c                  |    2 ++
+ net/bluetooth/l2cap_core.c                |    2 +-
+ net/bluetooth/mgmt.c                      |   16 ++++++++++
+ net/core/sock.c                           |    3 +-
+ net/ipv4/raw.c                            |   14 +++++----
+ net/ipv6/mip6.c                           |   20 +++++++------
+ net/ipv6/raw.c                            |   21 +++++++-------
+ net/wireless/reg.c                        |   12 ++++++--
+ scripts/checksyscalls.sh                  |    2 +-
+ 22 files changed, 159 insertions(+), 63 deletions(-)
+Merging fixes/master (9023a40 Merge tag 'mmc-fixes-for-3.5-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc)
+$ git merge fixes/master
+Already up-to-date.
+Merging kbuild-current/rc-fixes (24cc7fb x86/kbuild: archscripts depends on scripts_basic)
+$ git merge kbuild-current/rc-fixes
+Already up-to-date.
+Merging arm-current/fixes (bf619fa ARM: reserve syscall 378 for kcmp)
+$ git merge arm-current/fixes
+Already up-to-date.
+Merging m68k-current/for-linus (3be7184 m68k: Add missing RCU idle APIs on idle loop)
+$ git merge m68k-current/for-linus
+Merge made by the 'recursive' strategy.
+ arch/m68k/kernel/process.c |    3 +++
+ 1 file changed, 3 insertions(+)
+Merging powerpc-merge/merge (636802e powerpc: Don't use __put_user() in patch_instruction)
+$ git merge powerpc-merge/merge
+Already up-to-date.
+Merging sparc/master (a9e8d1a sparc: fix the return value of module_alloc())
+$ git merge sparc/master
+Already up-to-date.
+Merging net/master (96af69e ipv6: mip6: fix mip6_mh_filter())
+$ git merge net/master
+Already up-to-date.
+Merging sound-current/for-linus (5d037f9 Merge tag 'asoc-3.6' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-linus)
+$ git merge sound-current/for-linus
+Already up-to-date.
+Merging pci-current/for-linus (0ff9514 PCI: Don't print anything while decoding is disabled)
+$ git merge pci-current/for-linus
+Already up-to-date.
+Merging wireless/master (a7be50b iwlwifi: don't double free the interrupt in failure path)
+$ git merge wireless/master
+Already up-to-date.
+Merging driver-core.current/driver-core-linus (5698bd7 Linux 3.6-rc6)
+$ git merge driver-core.current/driver-core-linus
+Already up-to-date.
+Merging tty.current/tty-linus (5698bd7 Linux 3.6-rc6)
+$ git merge tty.current/tty-linus
+Already up-to-date.
+Merging usb.current/usb-linus (5698bd7 Linux 3.6-rc6)
+$ git merge usb.current/usb-linus
+Already up-to-date.
+Merging staging.current/staging-linus (5698bd7 Linux 3.6-rc6)
+$ git merge staging.current/staging-linus
+Already up-to-date.
+Merging char-misc.current/char-misc-linus (fea7a08 Linux 3.6-rc3)
+$ git merge char-misc.current/char-misc-linus
+Already up-to-date.
+Merging input-current/for-linus (35b1da4 Input: edt-ft5x06 - return -EFAULT on copy_to_user() error)
+$ git merge input-current/for-linus
+Already up-to-date.
+Merging md-current/for-linus (58e94ae md/raid1: close some possible races on write errors during resync)
+$ git merge md-current/for-linus
+Already up-to-date.
+Merging audit-current/for-linus (c158a35 audit: no leading space in audit_log_d_path prefix)
+$ git merge audit-current/for-linus
+Already up-to-date.
+Merging crypto-current/master (9b2f4cb crypto: authenc - Fix crash with zero-length assoc data)
+$ git merge crypto-current/master
+Already up-to-date.
+Merging ide/master (9974e43 ide: fix generic_ide_suspend/resume Oops)
+$ git merge ide/master
+Already up-to-date.
+Merging dwmw2/master (244dc4e Merge git://git.infradead.org/users/dwmw2/random-2.6)
+$ git merge dwmw2/master
+Already up-to-date.
+Merging sh-current/sh-fixes-for-linus (4403310 SH: Convert out[bwl] macros to inline functions)
+$ git merge sh-current/sh-fixes-for-linus
+Already up-to-date.
+Merging irqdomain-current/irqdomain/merge (15e06bf irqdomain: Fix debugfs formatting)
+$ git merge irqdomain-current/irqdomain/merge
+Already up-to-date.
+Merging devicetree-current/devicetree/merge (4e8383b of: release node fix for of_parse_phandle_with_args)
+$ git merge devicetree-current/devicetree/merge
+Auto-merging drivers/of/base.c
+Merge made by the 'recursive' strategy.
+ drivers/of/base.c |    2 ++
+ 1 file changed, 2 insertions(+)
+Merging spi-current/spi/merge (d1c185b of/spi: Fix SPI module loading by using proper "spi:" modalias prefixes.)
+$ git merge spi-current/spi/merge
+Auto-merging drivers/spi/spi.c
+Auto-merging drivers/spi/spi-s3c64xx.c
+Auto-merging drivers/spi/spi-bcm63xx.c
+Merge made by the 'recursive' strategy.
+ drivers/spi/spi-bcm63xx.c |   16 ++++++----------
+ drivers/spi/spi-s3c64xx.c |   10 ++++------
+ drivers/spi/spi.c         |    5 ++++-
+ 3 files changed, 14 insertions(+), 17 deletions(-)
+Merging gpio-current/gpio/merge (96b7064 gpio/tca6424: merge I2C transactions, remove cast)
+$ git merge gpio-current/gpio/merge
+Already up-to-date.
+Merging arm/for-next (8423021 Merge branches 'arch-timers', 'atags', 'cache-l2x0', 'clkdev', 'fixes', 'integrator', 'misc', 'opcodes' and 'syscall' into for-next)
+$ git merge arm/for-next
+Removing arch/arm/mach-sa1100/include/mach/lart.h
+Removing arch/arm/mach-sa1100/include/mach/SA-1111.h
+Removing arch/arm/kernel/compat.h
+Auto-merging arch/arm/kernel/atags_compat.c
+Removing arch/arm/include/asm/unaligned.h
+Removing arch/arm/include/asm/types.h
+Removing arch/arm/include/asm/termios.h
+Removing arch/arm/include/asm/termbits.h
+Removing arch/arm/include/asm/sockios.h
+Removing arch/arm/include/asm/socket.h
+Removing arch/arm/include/asm/shmbuf.h
+Removing arch/arm/include/asm/serial.h
+Removing arch/arm/include/asm/sembuf.h
+Removing arch/arm/include/asm/segment.h
+Removing arch/arm/include/asm/parport.h
+Removing arch/arm/include/asm/param.h
+Removing arch/arm/include/asm/msgbuf.h
+Removing arch/arm/include/asm/ipcbuf.h
+Removing arch/arm/include/asm/hardware/linkup-l1110.h
+Removing arch/arm/include/asm/exec.h
+Removing arch/arm/include/asm/current.h
+Merge made by the 'recursive' strategy.
+ Documentation/devicetree/bindings/arm/arm-boards   |   12 +
+ .../devicetree/bindings/arm/versatile-fpga-irq.txt |   31 ++
+ arch/arm/Kconfig                                   |   31 +-
+ arch/arm/Makefile                                  |    9 +-
+ arch/arm/boot/compressed/decompress.c              |    3 +
+ arch/arm/boot/dts/integrator.dtsi                  |   76 ++++
+ arch/arm/boot/dts/integratorap.dts                 |   68 ++++
+ arch/arm/boot/dts/integratorcp.dts                 |  110 ++++++
+ arch/arm/include/asm/Kbuild                        |   17 +
+ arch/arm/include/asm/arch_timer.h                  |    7 +
+ arch/arm/include/asm/current.h                     |   15 -
+ arch/arm/include/asm/exec.h                        |    6 -
+ arch/arm/include/asm/glue-cache.h                  |   16 +-
+ arch/arm/include/asm/hardirq.h                     |    2 +-
+ arch/arm/include/asm/hardware/linkup-l1110.h       |   48 ---
+ arch/arm/include/asm/io.h                          |   67 +++-
+ arch/arm/include/asm/ipcbuf.h                      |    1 -
+ arch/arm/include/asm/msgbuf.h                      |   31 --
+ arch/arm/include/asm/mutex.h                       |    9 +-
+ arch/arm/include/asm/opcodes-virt.h                |   29 ++
+ arch/arm/include/asm/opcodes.h                     |  181 +++++++++-
+ arch/arm/include/asm/param.h                       |   31 --
+ arch/arm/include/asm/parport.h                     |   18 -
+ arch/arm/include/asm/segment.h                     |   11 -
+ arch/arm/include/asm/sembuf.h                      |   25 --
+ arch/arm/include/asm/serial.h                      |   19 -
+ arch/arm/include/asm/shmbuf.h                      |   42 ---
+ arch/arm/include/asm/socket.h                      |   72 ----
+ arch/arm/include/asm/sockios.h                     |   13 -
+ arch/arm/include/asm/syscall.h                     |    4 +
+ arch/arm/include/asm/termbits.h                    |  198 -----------
+ arch/arm/include/asm/termios.h                     |   92 -----
+ arch/arm/include/asm/thread_info.h                 |    6 +-
+ arch/arm/include/asm/timex.h                       |    6 +-
+ arch/arm/include/asm/types.h                       |   16 -
+ arch/arm/include/asm/unaligned.h                   |   19 -
+ arch/arm/include/asm/unistd.h                      |    8 +
+ arch/arm/kernel/Makefile                           |    5 +-
+ arch/arm/kernel/arch_timer.c                       |  368 ++++++++++++++------
+ arch/arm/kernel/asm-offsets.c                      |    2 +
+ arch/arm/kernel/atags.h                            |   14 +
+ arch/arm/kernel/{compat.c => atags_compat.c}       |    4 +-
+ arch/arm/kernel/atags_parse.c                      |  238 +++++++++++++
+ arch/arm/kernel/{atags.c => atags_proc.c}          |    0
+ arch/arm/kernel/compat.h                           |   11 -
+ arch/arm/kernel/entry-common.S                     |    9 +
+ arch/arm/kernel/ptrace.c                           |   19 +-
+ arch/arm/kernel/sched_clock.c                      |    8 +
+ arch/arm/kernel/setup.c                            |  236 +------------
+ arch/arm/kernel/smp.c                              |   13 +-
+ arch/arm/mach-exynos/platsmp.c                     |    2 +-
+ arch/arm/mach-imx/mach-imx27_visstrim_m10.c        |    6 +-
+ arch/arm/mach-integrator/common.h                  |    3 +
+ arch/arm/mach-integrator/core.c                    |   17 +-
+ arch/arm/mach-integrator/integrator_ap.c           |  276 +++++++++++----
+ arch/arm/mach-integrator/integrator_cp.c           |  325 +++++++++++------
+ arch/arm/mach-sa1100/include/mach/SA-1111.h        |    5 -
+ arch/arm/mach-sa1100/include/mach/lart.h           |   13 -
+ arch/arm/mach-shmobile/smp-emev2.c                 |    2 +-
+ arch/arm/mm/alignment.c                            |    6 +-
+ arch/arm/mm/cache-l2x0.c                           |    8 +-
+ arch/arm/mm/init.c                                 |    2 +-
+ arch/arm/plat-versatile/fpga-irq.c                 |   72 +++-
+ arch/arm/plat-versatile/include/plat/fpga-irq.h    |    2 +
+ 64 files changed, 1728 insertions(+), 1287 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/arm/versatile-fpga-irq.txt
+ create mode 100644 arch/arm/boot/dts/integrator.dtsi
+ create mode 100644 arch/arm/boot/dts/integratorap.dts
+ create mode 100644 arch/arm/boot/dts/integratorcp.dts
+ delete mode 100644 arch/arm/include/asm/current.h
+ delete mode 100644 arch/arm/include/asm/exec.h
+ delete mode 100644 arch/arm/include/asm/hardware/linkup-l1110.h
+ delete mode 100644 arch/arm/include/asm/ipcbuf.h
+ delete mode 100644 arch/arm/include/asm/msgbuf.h
+ create mode 100644 arch/arm/include/asm/opcodes-virt.h
+ delete mode 100644 arch/arm/include/asm/param.h
+ delete mode 100644 arch/arm/include/asm/parport.h
+ delete mode 100644 arch/arm/include/asm/segment.h
+ delete mode 100644 arch/arm/include/asm/sembuf.h
+ delete mode 100644 arch/arm/include/asm/serial.h
+ delete mode 100644 arch/arm/include/asm/shmbuf.h
+ delete mode 100644 arch/arm/include/asm/socket.h
+ delete mode 100644 arch/arm/include/asm/sockios.h
+ delete mode 100644 arch/arm/include/asm/termbits.h
+ delete mode 100644 arch/arm/include/asm/termios.h
+ delete mode 100644 arch/arm/include/asm/types.h
+ delete mode 100644 arch/arm/include/asm/unaligned.h
+ rename arch/arm/kernel/{compat.c => atags_compat.c} (99%)
+ create mode 100644 arch/arm/kernel/atags_parse.c
+ rename arch/arm/kernel/{atags.c => atags_proc.c} (100%)
+ delete mode 100644 arch/arm/kernel/compat.h
+ delete mode 100644 arch/arm/mach-sa1100/include/mach/SA-1111.h
+ delete mode 100644 arch/arm/mach-sa1100/include/mach/lart.h
+Merging arm-perf/for-next/perf (b90c4b9 Merge branch 'hw-breakpoint' into for-next/perf)
+$ git merge arm-perf/for-next/perf
+Resolved 'arch/arm/kernel/hw_breakpoint.c' using previous resolution.
+Auto-merging arch/arm/plat-samsung/devs.c
+Removing arch/arm/kernel/pmu.c
+Auto-merging arch/arm/kernel/hw_breakpoint.c
+CONFLICT (content): Merge conflict in arch/arm/kernel/hw_breakpoint.c
+Auto-merging arch/arm/kernel/Makefile
+Auto-merging arch/arm/Kconfig
+Auto-merging MAINTAINERS
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master 8106359] Merge remote-tracking branch 'arm-perf/for-next/perf'
+$ git diff -M --stat --summary HEAD^..
+ Documentation/devicetree/bindings/arm/pmu.txt |    4 +
+ MAINTAINERS                                   |    1 -
+ arch/arm/Kconfig                              |    8 +-
+ arch/arm/include/asm/perf_event.h             |    9 +-
+ arch/arm/include/asm/pmu.h                    |   77 ++----
+ arch/arm/kernel/Makefile                      |    3 +-
+ arch/arm/kernel/perf_event.c                  |  347 ++++---------------------
+ arch/arm/kernel/perf_event_cpu.c              |  295 +++++++++++++++++++++
+ arch/arm/kernel/perf_event_v6.c               |   12 +-
+ arch/arm/kernel/perf_event_v7.c               |   32 +--
+ arch/arm/kernel/perf_event_xscale.c           |   10 +-
+ arch/arm/kernel/pmu.c                         |   36 ---
+ arch/arm/mach-bcmring/arch.c                  |    3 +-
+ arch/arm/mach-omap2/devices.c                 |    3 +-
+ arch/arm/mach-pxa/devices.c                   |    3 +-
+ arch/arm/mach-realview/realview_eb.c          |    3 +-
+ arch/arm/mach-realview/realview_pb1176.c      |    3 +-
+ arch/arm/mach-realview/realview_pb11mp.c      |    3 +-
+ arch/arm/mach-realview/realview_pba8.c        |    3 +-
+ arch/arm/mach-realview/realview_pbx.c         |    3 +-
+ arch/arm/mach-tegra/devices.c                 |    3 +-
+ arch/arm/mach-ux500/cpu-db8500.c              |    3 +-
+ arch/arm/mach-vexpress/ct-ca9x4.c             |    3 +-
+ arch/arm/plat-iop/pmu.c                       |    3 +-
+ arch/arm/plat-samsung/devs.c                  |    3 +-
+ 25 files changed, 424 insertions(+), 449 deletions(-)
+ create mode 100644 arch/arm/kernel/perf_event_cpu.c
+ delete mode 100644 arch/arm/kernel/pmu.c
+Merging davinci/davinci-next (fe0d422 Linux 3.0-rc6)
+$ git merge davinci/davinci-next
+Already up-to-date.
+Merging xilinx/arm-next (b85a3ef ARM: Xilinx: Adding Xilinx board support)
+$ git merge xilinx/arm-next
+Already up-to-date.
+Merging arm64/upstream (0d0109a arm64: Do not set the SMP/nAMP processor bit)
+$ git merge arm64/upstream
+Auto-merging fs/stat.c
+Auto-merging MAINTAINERS
+Merge made by the 'recursive' strategy.
+ Documentation/arm64/booting.txt               |  152 +++
+ Documentation/arm64/memory.txt                |   73 ++
+ MAINTAINERS                                   |    6 +
+ arch/arm64/Kconfig                            |  222 ++++
+ arch/arm64/Kconfig.debug                      |   27 +
+ arch/arm64/Makefile                           |   71 ++
+ arch/arm64/boot/.gitignore                    |    2 +
+ arch/arm64/boot/Makefile                      |   36 +
+ arch/arm64/boot/install.sh                    |   46 +
+ arch/arm64/configs/defconfig                  |   85 ++
+ arch/arm64/include/asm/Kbuild                 |   51 +
+ arch/arm64/include/asm/arm_generic.h          |  100 ++
+ arch/arm64/include/asm/asm-offsets.h          |    1 +
+ arch/arm64/include/asm/assembler.h            |  109 ++
+ arch/arm64/include/asm/atomic.h               |  305 ++++++
+ arch/arm64/include/asm/auxvec.h               |   22 +
+ arch/arm64/include/asm/barrier.h              |   52 +
+ arch/arm64/include/asm/bitops.h               |   53 +
+ arch/arm64/include/asm/bitsperlong.h          |   23 +
+ arch/arm64/include/asm/byteorder.h            |   21 +
+ arch/arm64/include/asm/cache.h                |   32 +
+ arch/arm64/include/asm/cacheflush.h           |  148 +++
+ arch/arm64/include/asm/cachetype.h            |   48 +
+ arch/arm64/include/asm/cmpxchg.h              |  173 ++++
+ arch/arm64/include/asm/compat.h               |  242 +++++
+ arch/arm64/include/asm/compiler.h             |   30 +
+ arch/arm64/include/asm/cputable.h             |   30 +
+ arch/arm64/include/asm/cputype.h              |   49 +
+ arch/arm64/include/asm/debug-monitors.h       |   88 ++
+ arch/arm64/include/asm/device.h               |   26 +
+ arch/arm64/include/asm/dma-mapping.h          |  124 +++
+ arch/arm64/include/asm/elf.h                  |  179 ++++
+ arch/arm64/include/asm/exception.h            |   23 +
+ arch/arm64/include/asm/exec.h                 |   23 +
+ arch/arm64/include/asm/fb.h                   |   34 +
+ arch/arm64/include/asm/fcntl.h                |   29 +
+ arch/arm64/include/asm/fpsimd.h               |   64 ++
+ arch/arm64/include/asm/futex.h                |  136 +++
+ arch/arm64/include/asm/hardirq.h              |   52 +
+ arch/arm64/include/asm/hw_breakpoint.h        |  137 +++
+ arch/arm64/include/asm/hwcap.h                |   53 +
+ arch/arm64/include/asm/io.h                   |  258 +++++
+ arch/arm64/include/asm/irq.h                  |    8 +
+ arch/arm64/include/asm/irqflags.h             |   91 ++
+ arch/arm64/include/asm/memblock.h             |   21 +
+ arch/arm64/include/asm/memory.h               |  144 +++
+ arch/arm64/include/asm/mmu.h                  |   30 +
+ arch/arm64/include/asm/mmu_context.h          |  152 +++
+ arch/arm64/include/asm/module.h               |   23 +
+ arch/arm64/include/asm/page.h                 |   67 ++
+ arch/arm64/include/asm/param.h                |   23 +
+ arch/arm64/include/asm/perf_event.h           |   22 +
+ arch/arm64/include/asm/pgalloc.h              |  113 ++
+ arch/arm64/include/asm/pgtable-2level-hwdef.h |   43 +
+ arch/arm64/include/asm/pgtable-2level-types.h |   60 ++
+ arch/arm64/include/asm/pgtable-3level-hwdef.h |   50 +
+ arch/arm64/include/asm/pgtable-3level-types.h |   66 ++
+ arch/arm64/include/asm/pgtable-hwdef.h        |   94 ++
+ arch/arm64/include/asm/pgtable.h              |  328 ++++++
+ arch/arm64/include/asm/pmu.h                  |   82 ++
+ arch/arm64/include/asm/proc-fns.h             |   50 +
+ arch/arm64/include/asm/processor.h            |  175 ++++
+ arch/arm64/include/asm/prom.h                 |    1 +
+ arch/arm64/include/asm/ptrace.h               |  212 ++++
+ arch/arm64/include/asm/setup.h                |   26 +
+ arch/arm64/include/asm/shmparam.h             |   28 +
+ arch/arm64/include/asm/sigcontext.h           |   69 ++
+ arch/arm64/include/asm/siginfo.h              |   23 +
+ arch/arm64/include/asm/signal.h               |   24 +
+ arch/arm64/include/asm/signal32.h             |   53 +
+ arch/arm64/include/asm/smp.h                  |   69 ++
+ arch/arm64/include/asm/sparsemem.h            |   24 +
+ arch/arm64/include/asm/spinlock.h             |  202 ++++
+ arch/arm64/include/asm/spinlock_types.h       |   38 +
+ arch/arm64/include/asm/stacktrace.h           |   29 +
+ arch/arm64/include/asm/stat.h                 |   62 ++
+ arch/arm64/include/asm/statfs.h               |   23 +
+ arch/arm64/include/asm/syscall.h              |  101 ++
+ arch/arm64/include/asm/syscalls.h             |   40 +
+ arch/arm64/include/asm/system_misc.h          |   54 +
+ arch/arm64/include/asm/thread_info.h          |  127 +++
+ arch/arm64/include/asm/timex.h                |   29 +
+ arch/arm64/include/asm/tlb.h                  |  190 ++++
+ arch/arm64/include/asm/tlbflush.h             |  122 +++
+ arch/arm64/include/asm/traps.h                |   30 +
+ arch/arm64/include/asm/uaccess.h              |  297 ++++++
+ arch/arm64/include/asm/ucontext.h             |   30 +
+ arch/arm64/include/asm/unistd.h               |   27 +
+ arch/arm64/include/asm/unistd32.h             |  758 ++++++++++++++
+ arch/arm64/include/asm/vdso.h                 |   41 +
+ arch/arm64/include/asm/vdso_datapage.h        |   43 +
+ arch/arm64/kernel/.gitignore                  |    1 +
+ arch/arm64/kernel/Makefile                    |   27 +
+ arch/arm64/kernel/arm64ksyms.c                |   46 +
+ arch/arm64/kernel/asm-offsets.c               |  108 ++
+ arch/arm64/kernel/cputable.c                  |   33 +
+ arch/arm64/kernel/debug-monitors.c            |  288 ++++++
+ arch/arm64/kernel/entry-fpsimd.S              |   80 ++
+ arch/arm64/kernel/entry.S                     |  695 +++++++++++++
+ arch/arm64/kernel/fpsimd.c                    |  106 ++
+ arch/arm64/kernel/head.S                      |  510 +++++++++
+ arch/arm64/kernel/hw_breakpoint.c             |  880 ++++++++++++++++
+ arch/arm64/kernel/io.c                        |   64 ++
+ arch/arm64/kernel/irq.c                       |   84 ++
+ arch/arm64/kernel/kuser32.S                   |   77 ++
+ arch/arm64/kernel/module.c                    |  456 +++++++++
+ arch/arm64/kernel/perf_event.c                | 1368 +++++++++++++++++++++++++
+ arch/arm64/kernel/process.c                   |  408 ++++++++
+ arch/arm64/kernel/ptrace.c                    | 1126 ++++++++++++++++++++
+ arch/arm64/kernel/setup.c                     |  347 +++++++
+ arch/arm64/kernel/signal.c                    |  437 ++++++++
+ arch/arm64/kernel/signal32.c                  |  876 ++++++++++++++++
+ arch/arm64/kernel/smp.c                       |  469 +++++++++
+ arch/arm64/kernel/stacktrace.c                |  127 +++
+ arch/arm64/kernel/sys.c                       |  138 +++
+ arch/arm64/kernel/sys32.S                     |  282 +++++
+ arch/arm64/kernel/sys_compat.c                |  164 +++
+ arch/arm64/kernel/time.c                      |   65 ++
+ arch/arm64/kernel/traps.c                     |  348 +++++++
+ arch/arm64/kernel/vdso.c                      |  261 +++++
+ arch/arm64/kernel/vdso/.gitignore             |    2 +
+ arch/arm64/kernel/vdso/Makefile               |   63 ++
+ arch/arm64/kernel/vdso/gen_vdso_offsets.sh    |   15 +
+ arch/arm64/kernel/vdso/gettimeofday.S         |  242 +++++
+ arch/arm64/kernel/vdso/note.S                 |   28 +
+ arch/arm64/kernel/vdso/sigreturn.S            |   37 +
+ arch/arm64/kernel/vdso/vdso.S                 |   33 +
+ arch/arm64/kernel/vdso/vdso.lds.S             |  100 ++
+ arch/arm64/kernel/vmlinux.lds.S               |  126 +++
+ arch/arm64/lib/Makefile                       |    4 +
+ arch/arm64/lib/bitops.c                       |   25 +
+ arch/arm64/lib/clear_page.S                   |   39 +
+ arch/arm64/lib/clear_user.S                   |   58 ++
+ arch/arm64/lib/copy_from_user.S               |   66 ++
+ arch/arm64/lib/copy_in_user.S                 |   63 ++
+ arch/arm64/lib/copy_page.S                    |   46 +
+ arch/arm64/lib/copy_to_user.S                 |   61 ++
+ arch/arm64/lib/delay.c                        |   55 +
+ arch/arm64/lib/strncpy_from_user.S            |   50 +
+ arch/arm64/lib/strnlen_user.S                 |   47 +
+ arch/arm64/mm/Makefile                        |    4 +
+ arch/arm64/mm/cache.S                         |  168 +++
+ arch/arm64/mm/context.c                       |  159 +++
+ arch/arm64/mm/copypage.c                      |   34 +
+ arch/arm64/mm/dma-mapping.c                   |   79 ++
+ arch/arm64/mm/extable.c                       |   17 +
+ arch/arm64/mm/fault.c                         |  534 ++++++++++
+ arch/arm64/mm/flush.c                         |  135 +++
+ arch/arm64/mm/init.c                          |  437 ++++++++
+ arch/arm64/mm/ioremap.c                       |   84 ++
+ arch/arm64/mm/mm.h                            |    2 +
+ arch/arm64/mm/mmap.c                          |  144 +++
+ arch/arm64/mm/mmu.c                           |  395 +++++++
+ arch/arm64/mm/pgd.c                           |   54 +
+ arch/arm64/mm/proc-macros.S                   |   55 +
+ arch/arm64/mm/proc.S                          |  175 ++++
+ arch/arm64/mm/tlb.S                           |   71 ++
+ drivers/clocksource/Kconfig                   |    5 +
+ drivers/clocksource/Makefile                  |    1 +
+ drivers/clocksource/arm_generic.c             |  232 +++++
+ fs/stat.c                                     |    4 +-
+ include/asm-generic/bitops/builtin-__ffs.h    |   15 +
+ include/asm-generic/bitops/builtin-__fls.h    |   15 +
+ include/asm-generic/bitops/builtin-ffs.h      |   17 +
+ include/asm-generic/bitops/builtin-fls.h      |   16 +
+ include/clocksource/arm_generic.h             |   21 +
+ include/linux/elf.h                           |    3 +
+ init/Kconfig                                  |    3 +-
+ kernel/sysctl.c                               |    2 +-
+ lib/Kconfig.debug                             |    6 +-
+ tools/perf/perf.h                             |    6 +
+ 171 files changed, 21767 insertions(+), 6 deletions(-)
+ create mode 100644 Documentation/arm64/booting.txt
+ create mode 100644 Documentation/arm64/memory.txt
+ create mode 100644 arch/arm64/Kconfig
+ create mode 100644 arch/arm64/Kconfig.debug
+ create mode 100644 arch/arm64/Makefile
+ create mode 100644 arch/arm64/boot/.gitignore
+ create mode 100644 arch/arm64/boot/Makefile
+ create mode 100644 arch/arm64/boot/install.sh
+ create mode 100644 arch/arm64/configs/defconfig
+ create mode 100644 arch/arm64/include/asm/Kbuild
+ create mode 100644 arch/arm64/include/asm/arm_generic.h
+ create mode 100644 arch/arm64/include/asm/asm-offsets.h
+ create mode 100644 arch/arm64/include/asm/assembler.h
+ create mode 100644 arch/arm64/include/asm/atomic.h
+ create mode 100644 arch/arm64/include/asm/auxvec.h
+ create mode 100644 arch/arm64/include/asm/barrier.h
+ create mode 100644 arch/arm64/include/asm/bitops.h
+ create mode 100644 arch/arm64/include/asm/bitsperlong.h
+ create mode 100644 arch/arm64/include/asm/byteorder.h
+ create mode 100644 arch/arm64/include/asm/cache.h
+ create mode 100644 arch/arm64/include/asm/cacheflush.h
+ create mode 100644 arch/arm64/include/asm/cachetype.h
+ create mode 100644 arch/arm64/include/asm/cmpxchg.h
+ create mode 100644 arch/arm64/include/asm/compat.h
+ create mode 100644 arch/arm64/include/asm/compiler.h
+ create mode 100644 arch/arm64/include/asm/cputable.h
+ create mode 100644 arch/arm64/include/asm/cputype.h
+ create mode 100644 arch/arm64/include/asm/debug-monitors.h
+ create mode 100644 arch/arm64/include/asm/device.h
+ create mode 100644 arch/arm64/include/asm/dma-mapping.h
+ create mode 100644 arch/arm64/include/asm/elf.h
+ create mode 100644 arch/arm64/include/asm/exception.h
+ create mode 100644 arch/arm64/include/asm/exec.h
+ create mode 100644 arch/arm64/include/asm/fb.h
+ create mode 100644 arch/arm64/include/asm/fcntl.h
+ create mode 100644 arch/arm64/include/asm/fpsimd.h
+ create mode 100644 arch/arm64/include/asm/futex.h
+ create mode 100644 arch/arm64/include/asm/hardirq.h
+ create mode 100644 arch/arm64/include/asm/hw_breakpoint.h
+ create mode 100644 arch/arm64/include/asm/hwcap.h
+ create mode 100644 arch/arm64/include/asm/io.h
+ create mode 100644 arch/arm64/include/asm/irq.h
+ create mode 100644 arch/arm64/include/asm/irqflags.h
+ create mode 100644 arch/arm64/include/asm/memblock.h
+ create mode 100644 arch/arm64/include/asm/memory.h
+ create mode 100644 arch/arm64/include/asm/mmu.h
+ create mode 100644 arch/arm64/include/asm/mmu_context.h
+ create mode 100644 arch/arm64/include/asm/module.h
+ create mode 100644 arch/arm64/include/asm/page.h
+ create mode 100644 arch/arm64/include/asm/param.h
+ create mode 100644 arch/arm64/include/asm/perf_event.h
+ create mode 100644 arch/arm64/include/asm/pgalloc.h
+ create mode 100644 arch/arm64/include/asm/pgtable-2level-hwdef.h
+ create mode 100644 arch/arm64/include/asm/pgtable-2level-types.h
+ create mode 100644 arch/arm64/include/asm/pgtable-3level-hwdef.h
+ create mode 100644 arch/arm64/include/asm/pgtable-3level-types.h
+ create mode 100644 arch/arm64/include/asm/pgtable-hwdef.h
+ create mode 100644 arch/arm64/include/asm/pgtable.h
+ create mode 100644 arch/arm64/include/asm/pmu.h
+ create mode 100644 arch/arm64/include/asm/proc-fns.h
+ create mode 100644 arch/arm64/include/asm/processor.h
+ create mode 100644 arch/arm64/include/asm/prom.h
+ create mode 100644 arch/arm64/include/asm/ptrace.h
+ create mode 100644 arch/arm64/include/asm/setup.h
+ create mode 100644 arch/arm64/include/asm/shmparam.h
+ create mode 100644 arch/arm64/include/asm/sigcontext.h
+ create mode 100644 arch/arm64/include/asm/siginfo.h
+ create mode 100644 arch/arm64/include/asm/signal.h
+ create mode 100644 arch/arm64/include/asm/signal32.h
+ create mode 100644 arch/arm64/include/asm/smp.h
+ create mode 100644 arch/arm64/include/asm/sparsemem.h
+ create mode 100644 arch/arm64/include/asm/spinlock.h
+ create mode 100644 arch/arm64/include/asm/spinlock_types.h
+ create mode 100644 arch/arm64/include/asm/stacktrace.h
+ create mode 100644 arch/arm64/include/asm/stat.h
+ create mode 100644 arch/arm64/include/asm/statfs.h
+ create mode 100644 arch/arm64/include/asm/syscall.h
+ create mode 100644 arch/arm64/include/asm/syscalls.h
+ create mode 100644 arch/arm64/include/asm/system_misc.h
+ create mode 100644 arch/arm64/include/asm/thread_info.h
+ create mode 100644 arch/arm64/include/asm/timex.h
+ create mode 100644 arch/arm64/include/asm/tlb.h
+ create mode 100644 arch/arm64/include/asm/tlbflush.h
+ create mode 100644 arch/arm64/include/asm/traps.h
+ create mode 100644 arch/arm64/include/asm/uaccess.h
+ create mode 100644 arch/arm64/include/asm/ucontext.h
+ create mode 100644 arch/arm64/include/asm/unistd.h
+ create mode 100644 arch/arm64/include/asm/unistd32.h
+ create mode 100644 arch/arm64/include/asm/vdso.h
+ create mode 100644 arch/arm64/include/asm/vdso_datapage.h
+ create mode 100644 arch/arm64/kernel/.gitignore
+ create mode 100644 arch/arm64/kernel/Makefile
+ create mode 100644 arch/arm64/kernel/arm64ksyms.c
+ create mode 100644 arch/arm64/kernel/asm-offsets.c
+ create mode 100644 arch/arm64/kernel/cputable.c
+ create mode 100644 arch/arm64/kernel/debug-monitors.c
+ create mode 100644 arch/arm64/kernel/entry-fpsimd.S
+ create mode 100644 arch/arm64/kernel/entry.S
+ create mode 100644 arch/arm64/kernel/fpsimd.c
+ create mode 100644 arch/arm64/kernel/head.S
+ create mode 100644 arch/arm64/kernel/hw_breakpoint.c
+ create mode 100644 arch/arm64/kernel/io.c
+ create mode 100644 arch/arm64/kernel/irq.c
+ create mode 100644 arch/arm64/kernel/kuser32.S
+ create mode 100644 arch/arm64/kernel/module.c
+ create mode 100644 arch/arm64/kernel/perf_event.c
+ create mode 100644 arch/arm64/kernel/process.c
+ create mode 100644 arch/arm64/kernel/ptrace.c
+ create mode 100644 arch/arm64/kernel/setup.c
+ create mode 100644 arch/arm64/kernel/signal.c
+ create mode 100644 arch/arm64/kernel/signal32.c
+ create mode 100644 arch/arm64/kernel/smp.c
+ create mode 100644 arch/arm64/kernel/stacktrace.c
+ create mode 100644 arch/arm64/kernel/sys.c
+ create mode 100644 arch/arm64/kernel/sys32.S
+ create mode 100644 arch/arm64/kernel/sys_compat.c
+ create mode 100644 arch/arm64/kernel/time.c
+ create mode 100644 arch/arm64/kernel/traps.c
+ create mode 100644 arch/arm64/kernel/vdso.c
+ create mode 100644 arch/arm64/kernel/vdso/.gitignore
+ create mode 100644 arch/arm64/kernel/vdso/Makefile
+ create mode 100755 arch/arm64/kernel/vdso/gen_vdso_offsets.sh
+ create mode 100644 arch/arm64/kernel/vdso/gettimeofday.S
+ create mode 100644 arch/arm64/kernel/vdso/note.S
+ create mode 100644 arch/arm64/kernel/vdso/sigreturn.S
+ create mode 100644 arch/arm64/kernel/vdso/vdso.S
+ create mode 100644 arch/arm64/kernel/vdso/vdso.lds.S
+ create mode 100644 arch/arm64/kernel/vmlinux.lds.S
+ create mode 100644 arch/arm64/lib/Makefile
+ create mode 100644 arch/arm64/lib/bitops.c
+ create mode 100644 arch/arm64/lib/clear_page.S
+ create mode 100644 arch/arm64/lib/clear_user.S
+ create mode 100644 arch/arm64/lib/copy_from_user.S
+ create mode 100644 arch/arm64/lib/copy_in_user.S
+ create mode 100644 arch/arm64/lib/copy_page.S
+ create mode 100644 arch/arm64/lib/copy_to_user.S
+ create mode 100644 arch/arm64/lib/delay.c
+ create mode 100644 arch/arm64/lib/strncpy_from_user.S
+ create mode 100644 arch/arm64/lib/strnlen_user.S
+ create mode 100644 arch/arm64/mm/Makefile
+ create mode 100644 arch/arm64/mm/cache.S
+ create mode 100644 arch/arm64/mm/context.c
+ create mode 100644 arch/arm64/mm/copypage.c
+ create mode 100644 arch/arm64/mm/dma-mapping.c
+ create mode 100644 arch/arm64/mm/extable.c
+ create mode 100644 arch/arm64/mm/fault.c
+ create mode 100644 arch/arm64/mm/flush.c
+ create mode 100644 arch/arm64/mm/init.c
+ create mode 100644 arch/arm64/mm/ioremap.c
+ create mode 100644 arch/arm64/mm/mm.h
+ create mode 100644 arch/arm64/mm/mmap.c
+ create mode 100644 arch/arm64/mm/mmu.c
+ create mode 100644 arch/arm64/mm/pgd.c
+ create mode 100644 arch/arm64/mm/proc-macros.S
+ create mode 100644 arch/arm64/mm/proc.S
+ create mode 100644 arch/arm64/mm/tlb.S
+ create mode 100644 drivers/clocksource/arm_generic.c
+ create mode 100644 include/asm-generic/bitops/builtin-__ffs.h
+ create mode 100644 include/asm-generic/bitops/builtin-__fls.h
+ create mode 100644 include/asm-generic/bitops/builtin-ffs.h
+ create mode 100644 include/asm-generic/bitops/builtin-fls.h
+ create mode 100644 include/clocksource/arm_generic.h
+Merging blackfin/for-linus (6895f97 kbuild: add symbol prefix arg to kallsyms)
+$ git merge blackfin/for-linus
+Already up-to-date.
+Merging c6x/for-linux-next (2547ab3 syscalls: add __NR_kcmp syscall to generic unistd.h)
+$ git merge c6x/for-linux-next
+Removing arch/c6x/include/asm/barrier.h
+Merge made by the 'recursive' strategy.
+ arch/c6x/include/asm/Kbuild    |    1 +
+ arch/c6x/include/asm/barrier.h |   27 ---------------------------
+ include/asm-generic/unistd.h   |    4 +++-
+ 3 files changed, 4 insertions(+), 28 deletions(-)
+ delete mode 100644 arch/c6x/include/asm/barrier.h
+Merging cris/for-next (2608747 CRIS: Remove VCS simulator specific code)
+$ git merge cris/for-next
+Removing arch/cris/arch-v32/mach-fs/vcs_hook.h
+Removing arch/cris/arch-v32/mach-fs/vcs_hook.c
+Removing arch/cris/arch-v32/mach-a3/vcs_hook.h
+Removing arch/cris/arch-v32/mach-a3/vcs_hook.c
+Auto-merging arch/cris/arch-v32/drivers/pci/bios.c
+Auto-merging arch/cris/Kconfig
+Merge made by the 'recursive' strategy.
+ arch/cris/Kconfig                                  |    5 -
+ arch/cris/arch-v32/drivers/axisflashmap.c          |   29 ------
+ arch/cris/arch-v32/drivers/pci/bios.c              |   25 -----
+ arch/cris/arch-v32/kernel/head.S                   |   58 +----------
+ arch/cris/arch-v32/kernel/kgdb.c                   |   14 ---
+ arch/cris/arch-v32/mach-a3/Makefile                |    2 -
+ arch/cris/arch-v32/mach-a3/vcs_hook.c              |  103 --------------------
+ arch/cris/arch-v32/mach-a3/vcs_hook.h              |   58 -----------
+ arch/cris/arch-v32/mach-fs/Makefile                |    2 -
+ arch/cris/arch-v32/mach-fs/vcs_hook.c              |  100 -------------------
+ arch/cris/arch-v32/mach-fs/vcs_hook.h              |   42 --------
+ arch/cris/arch-v32/mm/init.c                       |    8 --
+ arch/cris/include/arch-v32/arch/page.h             |    5 -
+ arch/cris/include/arch-v32/arch/processor.h        |    6 +-
+ .../cris/include/arch-v32/mach-fs/mach/startup.inc |    6 --
+ arch/cris/include/asm/pci.h                        |    1 -
+ 16 files changed, 3 insertions(+), 461 deletions(-)
+ delete mode 100644 arch/cris/arch-v32/mach-a3/vcs_hook.c
+ delete mode 100644 arch/cris/arch-v32/mach-a3/vcs_hook.h
+ delete mode 100644 arch/cris/arch-v32/mach-fs/vcs_hook.c
+ delete mode 100644 arch/cris/arch-v32/mach-fs/vcs_hook.h
+Merging hexagon/linux-next (5042ab9 various Kconfig cleanup and old platform build code removal)
+$ git merge hexagon/linux-next
+Already up-to-date.
+Merging ia64/next (0967237 [IA64] Must enable interrupts in do_notify_resume_user before calling tracehook_notify_resume())
+$ git merge ia64/next
+Merge made by the 'recursive' strategy.
+ arch/ia64/include/asm/numa.h     |    2 +-
+ arch/ia64/kernel/machine_kexec.c |    3 ++-
+ arch/ia64/kernel/process.c       |    4 ++--
+ 3 files changed, 5 insertions(+), 4 deletions(-)
+Merging m68k/for-next (f82735d m68k: Use PTR_RET rather than if(IS_ERR(...)) + PTR_ERR)
+$ git merge m68k/for-next
+Merge made by the 'recursive' strategy.
+ arch/m68k/amiga/platform.c       |    5 +----
+ arch/m68k/include/asm/apollohw.h |   12 ------------
+ arch/m68k/kernel/time.c          |    5 +----
+ arch/m68k/q40/config.c           |    5 +----
+ 4 files changed, 3 insertions(+), 24 deletions(-)
+Merging m68knommu/for-next (42ec574 m68knommu: use "r", not "i" constraint in cacheflus asm's)
+$ git merge m68knommu/for-next
+Merge made by the 'recursive' strategy.
+ arch/m68k/include/asm/cacheflush_no.h |   19 ++++++++-----------
+ arch/m68k/platform/68VZ328/Makefile   |    8 +-------
+ 2 files changed, 9 insertions(+), 18 deletions(-)
+Merging microblaze/next (a01ee16 Merge branch 'for-linus' of git://git.open-osd.org/linux-open-osd)
+$ git merge microblaze/next
+Already up-to-date.
+Merging mips/mips-for-linux-next (8ca1528 Merge branch 'next/p3/trace' into mips-for-linux-next)
+$ git merge mips/mips-for-linux-next
+Removing arch/mips/mipssim/sim_time.c
+Removing arch/mips/mipssim/sim_smtc.c
+Removing arch/mips/mipssim/sim_setup.c
+Removing arch/mips/mipssim/sim_platform.c
+Removing arch/mips/mipssim/sim_mem.c
+Removing arch/mips/mipssim/sim_int.c
+Removing arch/mips/mipssim/sim_console.c
+Removing arch/mips/mipssim/Platform
+Removing arch/mips/mipssim/Makefile
+Removing arch/mips/include/asm/mips-boards/simint.h
+Removing arch/mips/include/asm/mach-mipssim/war.h
+Removing arch/mips/include/asm/mach-mipssim/cpu-feature-overrides.h
+Removing arch/mips/configs/mipssim_defconfig
+Merge made by the 'recursive' strategy.
+ arch/mips/Kbuild.platforms                         |    1 -
+ arch/mips/Kconfig                                  |   24 +-
+ arch/mips/ath79/clock.c                            |  109 ++-
+ arch/mips/bcm63xx/boards/board_bcm963xx.c          |   16 +-
+ arch/mips/configs/mipssim_defconfig                |   64 --
+ arch/mips/include/asm/elf.h                        |    1 +
+ arch/mips/include/asm/mach-ath79/ar71xx_regs.h     |   23 +
+ .../asm/mach-mipssim/cpu-feature-overrides.h       |   67 --
+ arch/mips/include/asm/mach-mipssim/war.h           |   25 -
+ arch/mips/include/asm/mips-boards/simint.h         |   31 -
+ arch/mips/include/asm/ptrace.h                     |   15 +-
+ arch/mips/include/asm/siginfo.h                    |    9 +
+ arch/mips/include/asm/syscall.h                    |   97 +++
+ arch/mips/include/asm/thread_info.h                |    6 +-
+ arch/mips/kernel/Makefile                          |    1 +
+ arch/mips/kernel/entry.S                           |   15 +-
+ arch/mips/kernel/ftrace.c                          |   33 +
+ arch/mips/kernel/ptrace.c                          |  193 +++--
+ arch/mips/kernel/scall32-o32.S                     |  845 +++++++++-----------
+ arch/mips/kernel/scall64-64.S                      |   16 +-
+ arch/mips/kernel/scall64-n32.S                     |   20 +-
+ arch/mips/kernel/scall64-o32.S                     |   23 +-
+ arch/mips/kernel/signal.c                          |    8 -
+ arch/mips/mipssim/Makefile                         |   23 -
+ arch/mips/mipssim/Platform                         |    6 -
+ arch/mips/mipssim/sim_console.c                    |   40 -
+ arch/mips/mipssim/sim_int.c                        |   87 --
+ arch/mips/mipssim/sim_mem.c                        |  115 ---
+ arch/mips/mipssim/sim_platform.c                   |   35 -
+ arch/mips/mipssim/sim_setup.c                      |   99 ---
+ arch/mips/mipssim/sim_smtc.c                       |  116 ---
+ arch/mips/mipssim/sim_time.c                       |  117 ---
+ 32 files changed, 834 insertions(+), 1446 deletions(-)
+ delete mode 100644 arch/mips/configs/mipssim_defconfig
+ delete mode 100644 arch/mips/include/asm/mach-mipssim/cpu-feature-overrides.h
+ delete mode 100644 arch/mips/include/asm/mach-mipssim/war.h
+ delete mode 100644 arch/mips/include/asm/mips-boards/simint.h
+ create mode 100644 arch/mips/include/asm/syscall.h
+ delete mode 100644 arch/mips/mipssim/Makefile
+ delete mode 100644 arch/mips/mipssim/Platform
+ delete mode 100644 arch/mips/mipssim/sim_console.c
+ delete mode 100644 arch/mips/mipssim/sim_int.c
+ delete mode 100644 arch/mips/mipssim/sim_mem.c
+ delete mode 100644 arch/mips/mipssim/sim_platform.c
+ delete mode 100644 arch/mips/mipssim/sim_setup.c
+ delete mode 100644 arch/mips/mipssim/sim_smtc.c
+ delete mode 100644 arch/mips/mipssim/sim_time.c
+Merging openrisc/for-upstream (4c8faa4 openrisc: mask interrupts in irq_mask_ack function)
+$ git merge openrisc/for-upstream
+Merge made by the 'recursive' strategy.
+ arch/openrisc/include/asm/processor.h |    2 +-
+ arch/openrisc/kernel/irq.c            |   20 +++++++++++---------
+ arch/openrisc/kernel/ptrace.c         |    2 +-
+ arch/openrisc/lib/delay.c             |    6 +++---
+ include/linux/audit.h                 |    1 +
+ 5 files changed, 17 insertions(+), 14 deletions(-)
+Merging parisc/for-next (5b24c42 [PARISC] fix personality flag check in copy_thread())
+$ git merge parisc/for-next
+Already up-to-date.
+Merging s390/features (dfc09c0 s390/cmpxchg,percpu: implement cmpxchg_double())
+$ git merge s390/features
+Auto-merging include/linux/elf.h
+Removing arch/s390/kernel/crash.c
+Merge made by the 'recursive' strategy.
+ arch/s390/Kbuild                       |    1 +
+ arch/s390/Kconfig                      |  414 +++++++--------
+ arch/s390/boot/compressed/Makefile     |    1 +
+ arch/s390/boot/compressed/misc.c       |   45 +-
+ arch/s390/defconfig                    |   13 +-
+ arch/s390/include/asm/appldata.h       |    2 +-
+ arch/s390/include/asm/chsc.h           |   28 --
+ arch/s390/include/asm/cio.h            |   28 +-
+ arch/s390/include/asm/cmpxchg.h        |   60 +++
+ arch/s390/include/asm/cpu_mf.h         |    4 +
+ arch/s390/include/asm/css_chars.h      |   39 ++
+ arch/s390/include/asm/eadm.h           |  124 +++++
+ arch/s390/include/asm/elf.h            |    3 +
+ arch/s390/include/asm/etr.h            |    8 +-
+ arch/s390/include/asm/irq.h            |    2 +
+ arch/s390/include/asm/isc.h            |    1 +
+ arch/s390/include/asm/lowcore.h        |    6 +-
+ arch/s390/include/asm/mmu_context.h    |    2 +-
+ arch/s390/include/asm/percpu.h         |   50 +-
+ arch/s390/include/asm/processor.h      |   59 ++-
+ arch/s390/include/asm/ptrace.h         |   12 +-
+ arch/s390/include/asm/runtime_instr.h  |   98 ++++
+ arch/s390/include/asm/scsw.h           |   38 +-
+ arch/s390/include/asm/setup.h          |    5 +-
+ arch/s390/include/asm/smp.h            |    4 +-
+ arch/s390/include/asm/string.h         |    8 -
+ arch/s390/include/asm/switch_to.h      |    2 +
+ arch/s390/include/asm/sysinfo.h        |   39 +-
+ arch/s390/include/asm/topology.h       |   20 +-
+ arch/s390/include/asm/uaccess.h        |   15 +-
+ arch/s390/include/asm/unistd.h         |    4 +-
+ arch/s390/kernel/Makefile              |   12 +-
+ arch/s390/kernel/asm-offsets.c         |    2 +
+ arch/s390/kernel/cache.c               |  385 ++++++++++++++
+ arch/s390/kernel/compat_wrapper.S      |   13 +
+ arch/s390/kernel/crash.c               |   14 -
+ arch/s390/kernel/crash_dump.c          |    3 +-
+ arch/s390/kernel/dis.c                 |   56 +++
+ arch/s390/kernel/early.c               |   38 +-
+ arch/s390/kernel/entry64.S             |   17 +-
+ arch/s390/kernel/irq.c                 |   56 ++-
+ arch/s390/kernel/kprobes.c             |    2 +-
+ arch/s390/kernel/lgr.c                 |   29 +-
+ arch/s390/kernel/machine_kexec.c       |    9 +-
+ arch/s390/kernel/process.c             |    8 +
+ arch/s390/kernel/processor.c           |    7 +-
+ arch/s390/kernel/ptrace.c              |   70 +++
+ arch/s390/kernel/runtime_instr.c       |  150 ++++++
+ arch/s390/kernel/s390_ksyms.c          |    2 +
+ arch/s390/kernel/setup.c               |   54 +-
+ arch/s390/kernel/smp.c                 |   46 +-
+ arch/s390/kernel/syscalls.S            |    2 +
+ arch/s390/kernel/sysinfo.c             |  351 ++++++-------
+ arch/s390/kernel/time.c                |    4 +-
+ arch/s390/kernel/topology.c            |   27 +-
+ arch/s390/kernel/traps.c               |   39 +-
+ arch/s390/kernel/vdso.c                |    8 +-
+ arch/s390/kernel/vtime.c               |    3 +-
+ arch/s390/kvm/Kconfig                  |    2 +-
+ arch/s390/kvm/priv.c                   |    4 +-
+ arch/s390/lib/Makefile                 |    3 +-
+ arch/s390/lib/mem32.S                  |   92 ++++
+ arch/s390/lib/mem64.S                  |   88 ++++
+ arch/s390/lib/string.c                 |   56 +--
+ arch/s390/mm/Makefile                  |    2 +-
+ arch/s390/mm/extable.c                 |   81 +++
+ arch/s390/mm/fault.c                   |    7 +-
+ arch/s390/mm/gup.c                     |   37 ++
+ arch/s390/mm/pgtable.c                 |    6 +-
+ arch/s390/mm/vmem.c                    |    2 +-
+ arch/s390/net/Makefile                 |    4 +
+ arch/s390/net/bpf_jit.S                |  130 +++++
+ arch/s390/net/bpf_jit_comp.c           |  771 ++++++++++++++++++++++++++++
+ block/partitions/ibm.c                 |  455 ++++++++++-------
+ drivers/s390/block/Kconfig             |   18 +
+ drivers/s390/block/Makefile            |    6 +
+ drivers/s390/block/dasd_eckd.c         |    7 +-
+ drivers/s390/block/dasd_ioctl.c        |    4 +-
+ drivers/s390/block/scm_blk.c           |  445 +++++++++++++++++
+ drivers/s390/block/scm_blk.h           |  117 +++++
+ drivers/s390/block/scm_blk_cluster.c   |  228 +++++++++
+ drivers/s390/block/scm_drv.c           |   81 +++
+ drivers/s390/char/con3270.c            |    1 -
+ drivers/s390/char/sclp.c               |    2 +-
+ drivers/s390/char/sclp_rw.c            |    2 +-
+ drivers/s390/char/tape.h               |    1 -
+ drivers/s390/char/tape_std.h           |    4 -
+ drivers/s390/char/vmlogrdr.c           |    2 +-
+ drivers/s390/cio/Makefile              |    2 +
+ drivers/s390/cio/chsc.c                |   52 ++
+ drivers/s390/cio/chsc.h                |   43 ++
+ drivers/s390/cio/cio.c                 |    2 +-
+ drivers/s390/cio/css.c                 |    1 +
+ drivers/s390/cio/eadm_sch.c            |  401 +++++++++++++++
+ drivers/s390/cio/eadm_sch.h            |   20 +
+ drivers/s390/cio/orb.h                 |   24 +
+ drivers/s390/cio/qdio_debug.h          |   38 +-
+ drivers/s390/cio/scm.c                 |  317 ++++++++++++
+ drivers/s390/crypto/Makefile           |    3 +-
+ drivers/s390/crypto/ap_bus.c           |  209 ++++++--
+ drivers/s390/crypto/ap_bus.h           |   35 +-
+ drivers/s390/crypto/zcrypt_api.c       |  187 ++++++-
+ drivers/s390/crypto/zcrypt_api.h       |   19 +-
+ drivers/s390/crypto/zcrypt_cex2a.c     |  371 +-------------
+ drivers/s390/crypto/zcrypt_cex4.c      |  149 ++++++
+ drivers/s390/crypto/zcrypt_cex4.h      |   12 +
+ drivers/s390/crypto/zcrypt_debug.h     |   59 +++
+ drivers/s390/crypto/zcrypt_error.h     |   13 +
+ drivers/s390/crypto/zcrypt_msgtype50.c |  531 ++++++++++++++++++++
+ drivers/s390/crypto/zcrypt_msgtype50.h |   39 ++
+ drivers/s390/crypto/zcrypt_msgtype6.c  |  856 ++++++++++++++++++++++++++++++++
+ drivers/s390/crypto/zcrypt_msgtype6.h  |  169 +++++++
+ drivers/s390/crypto/zcrypt_pcixcc.c    |  781 +----------------------------
+ drivers/s390/crypto/zcrypt_pcixcc.h    |    3 +-
+ drivers/s390/net/qeth_core_main.c      |   15 +-
+ include/linux/elf.h                    |    1 +
+ scripts/sortextable.c                  |   10 +-
+ 117 files changed, 7386 insertions(+), 2176 deletions(-)
+ create mode 100644 arch/s390/include/asm/css_chars.h
+ create mode 100644 arch/s390/include/asm/eadm.h
+ create mode 100644 arch/s390/include/asm/runtime_instr.h
+ create mode 100644 arch/s390/kernel/cache.c
+ delete mode 100644 arch/s390/kernel/crash.c
+ create mode 100644 arch/s390/kernel/runtime_instr.c
+ create mode 100644 arch/s390/lib/mem32.S
+ create mode 100644 arch/s390/lib/mem64.S
+ create mode 100644 arch/s390/mm/extable.c
+ create mode 100644 arch/s390/net/Makefile
+ create mode 100644 arch/s390/net/bpf_jit.S
+ create mode 100644 arch/s390/net/bpf_jit_comp.c
+ create mode 100644 drivers/s390/block/scm_blk.c
+ create mode 100644 drivers/s390/block/scm_blk.h
+ create mode 100644 drivers/s390/block/scm_blk_cluster.c
+ create mode 100644 drivers/s390/block/scm_drv.c
+ create mode 100644 drivers/s390/cio/eadm_sch.c
+ create mode 100644 drivers/s390/cio/eadm_sch.h
+ create mode 100644 drivers/s390/cio/scm.c
+ create mode 100644 drivers/s390/crypto/zcrypt_cex4.c
+ create mode 100644 drivers/s390/crypto/zcrypt_cex4.h
+ create mode 100644 drivers/s390/crypto/zcrypt_debug.h
+ create mode 100644 drivers/s390/crypto/zcrypt_msgtype50.c
+ create mode 100644 drivers/s390/crypto/zcrypt_msgtype50.h
+ create mode 100644 drivers/s390/crypto/zcrypt_msgtype6.c
+ create mode 100644 drivers/s390/crypto/zcrypt_msgtype6.h
+Merging sh/sh-latest (16d74eb sh: pfc: Fix up GPIO mux type reconfig case.)
+$ git merge sh/sh-latest
+Already up-to-date.
+Merging sparc-next/master (da20116 drivers/sbus/char: removes unnecessary semicolon)
+$ git merge sparc-next/master
+Merge made by the 'recursive' strategy.
+ arch/sparc/Kbuild                   |    1 +
+ arch/sparc/crypto/Makefile          |   25 +
+ arch/sparc/crypto/aes_asm.S         | 1535 +++++++++++++++++++++++++++++++++++
+ arch/sparc/crypto/aes_glue.c        |  477 +++++++++++
+ arch/sparc/crypto/camellia_asm.S    |  563 +++++++++++++
+ arch/sparc/crypto/camellia_glue.c   |  322 ++++++++
+ arch/sparc/crypto/crc32c_asm.S      |   20 +
+ arch/sparc/crypto/crc32c_glue.c     |  179 ++++
+ arch/sparc/crypto/crop_devid.c      |   14 +
+ arch/sparc/crypto/des_asm.S         |  418 ++++++++++
+ arch/sparc/crypto/des_glue.c        |  529 ++++++++++++
+ arch/sparc/crypto/md5_asm.S         |   70 ++
+ arch/sparc/crypto/md5_glue.c        |  188 +++++
+ arch/sparc/crypto/opcodes.h         |   99 +++
+ arch/sparc/crypto/sha1_asm.S        |   72 ++
+ arch/sparc/crypto/sha1_glue.c       |  183 +++++
+ arch/sparc/crypto/sha256_asm.S      |   78 ++
+ arch/sparc/crypto/sha256_glue.c     |  241 ++++++
+ arch/sparc/crypto/sha512_asm.S      |  102 +++
+ arch/sparc/crypto/sha512_glue.c     |  226 ++++++
+ arch/sparc/include/asm/asi.h        |    4 +-
+ arch/sparc/include/asm/elf_64.h     |    9 +
+ arch/sparc/include/asm/hypervisor.h |   11 +
+ arch/sparc/include/asm/mdesc.h      |    1 +
+ arch/sparc/include/asm/pcr.h        |   36 +-
+ arch/sparc/include/asm/perfctr.h    |   30 -
+ arch/sparc/include/asm/pstate.h     |   14 +
+ arch/sparc/kernel/hvapi.c           |    1 +
+ arch/sparc/kernel/hvcalls.S         |   16 +
+ arch/sparc/kernel/ktlb.S            |   25 +-
+ arch/sparc/kernel/mdesc.c           |   24 +
+ arch/sparc/kernel/nmi.c             |   21 +-
+ arch/sparc/kernel/pci_sun4v.c       |    2 +-
+ arch/sparc/kernel/pcr.c             |  172 +++-
+ arch/sparc/kernel/perf_event.c      |  516 +++++++++---
+ arch/sparc/kernel/setup_64.c        |   67 +-
+ arch/sparc/lib/ksyms.c              |    4 +
+ arch/sparc/mm/init_64.c             |  230 +++++-
+ arch/sparc/mm/init_64.h             |    4 +-
+ crypto/Kconfig                      |   97 +++
+ drivers/crypto/n2_core.c            |    2 +-
+ drivers/sbus/char/display7seg.c     |    2 +-
+ drivers/sbus/char/envctrl.c         |    8 +-
+ drivers/sbus/char/openprom.c        |    4 +-
+ 44 files changed, 6373 insertions(+), 269 deletions(-)
+ create mode 100644 arch/sparc/crypto/Makefile
+ create mode 100644 arch/sparc/crypto/aes_asm.S
+ create mode 100644 arch/sparc/crypto/aes_glue.c
+ create mode 100644 arch/sparc/crypto/camellia_asm.S
+ create mode 100644 arch/sparc/crypto/camellia_glue.c
+ create mode 100644 arch/sparc/crypto/crc32c_asm.S
+ create mode 100644 arch/sparc/crypto/crc32c_glue.c
+ create mode 100644 arch/sparc/crypto/crop_devid.c
+ create mode 100644 arch/sparc/crypto/des_asm.S
+ create mode 100644 arch/sparc/crypto/des_glue.c
+ create mode 100644 arch/sparc/crypto/md5_asm.S
+ create mode 100644 arch/sparc/crypto/md5_glue.c
+ create mode 100644 arch/sparc/crypto/opcodes.h
+ create mode 100644 arch/sparc/crypto/sha1_asm.S
+ create mode 100644 arch/sparc/crypto/sha1_glue.c
+ create mode 100644 arch/sparc/crypto/sha256_asm.S
+ create mode 100644 arch/sparc/crypto/sha256_glue.c
+ create mode 100644 arch/sparc/crypto/sha512_asm.S
+ create mode 100644 arch/sparc/crypto/sha512_glue.c
+Merging tile/master (e70cf54 tile: gxio iorpc numbering change for TRIO interface)
+$ git merge tile/master
+Already up-to-date.
+Merging unicore32/unicore32 (e4baa56 UniCore32-bugfix: Remove definitions in asm/bug.h to solve difference between native and cross compiler)
+$ git merge unicore32/unicore32
+Auto-merging arch/unicore32/Kconfig
+Merge made by the 'recursive' strategy.
+ arch/unicore32/Kconfig               |    3 +++
+ arch/unicore32/include/asm/bug.h     |    5 -----
+ arch/unicore32/include/asm/cmpxchg.h |    2 +-
+ arch/unicore32/kernel/setup.h        |    6 ++++++
+ arch/unicore32/mm/fault.c            |   37 +++++++++++++++++++++++++---------
+ 5 files changed, 37 insertions(+), 16 deletions(-)
+Merging xtensa/for_next (1c6b4c6 xtensa: add missing symbol exports)
+$ git merge xtensa/for_next
+Removing arch/xtensa/platforms/iss/io.c
+Removing arch/xtensa/kernel/io.c
+Merge made by the 'recursive' strategy.
+ arch/xtensa/Kconfig                                |    6 +-
+ arch/xtensa/Makefile                               |    2 +-
+ arch/xtensa/boot/boot-elf/Makefile                 |    9 +-
+ arch/xtensa/boot/boot-redboot/Makefile             |   12 +-
+ arch/xtensa/include/asm/io.h                       |  172 +++-----------------
+ arch/xtensa/include/asm/regs.h                     |    2 +-
+ arch/xtensa/kernel/Makefile                        |    3 +-
+ arch/xtensa/kernel/io.c                            |   75 ---------
+ arch/xtensa/kernel/irq.c                           |    4 +-
+ arch/xtensa/kernel/pci-dma.c                       |    4 +
+ arch/xtensa/kernel/pci.c                           |    2 +-
+ arch/xtensa/kernel/platform.c                      |    4 +-
+ arch/xtensa/kernel/xtensa_ksyms.c                  |    8 +
+ arch/xtensa/platforms/iss/Makefile                 |    4 +-
+ arch/xtensa/platforms/iss/console.c                |   15 +-
+ .../platforms/iss/include/platform/simcall.h       |   53 ++++++
+ arch/xtensa/platforms/iss/io.c                     |   32 ----
+ arch/xtensa/platforms/iss/network.c                |   49 ------
+ arch/xtensa/platforms/iss/setup.c                  |   14 +-
+ drivers/isdn/hisax/Kconfig                         |   10 +-
+ drivers/parport/Kconfig                            |    2 +-
+ drivers/usb/musb/musb_io.h                         |    3 +-
+ scripts/mod/modpost.c                              |    2 +
+ 23 files changed, 135 insertions(+), 352 deletions(-)
+ delete mode 100644 arch/xtensa/kernel/io.c
+ create mode 100644 arch/xtensa/platforms/iss/include/platform/serial.h
+ delete mode 100644 arch/xtensa/platforms/iss/io.c
+Merging ceph/master (5ce765a libceph: only kunmap kmapped pages)
+$ git merge ceph/master
+Already up-to-date.
+Merging cifs/for-next (1b35920 cifs: remove support for deprecated "forcedirectio" and "strictcache" mount options)
+$ git merge cifs/for-next
+Merge made by the 'recursive' strategy.
+ fs/cifs/Kconfig         |    3 +-
+ fs/cifs/Makefile        |    2 +-
+ fs/cifs/cifsacl.c       |    2 +-
+ fs/cifs/cifsencrypt.c   |   67 ++-
+ fs/cifs/cifsfs.c        |   63 ++-
+ fs/cifs/cifsfs.h        |    2 +-
+ fs/cifs/cifsglob.h      |  258 ++++++++++-
+ fs/cifs/cifspdu.h       |    2 +-
+ fs/cifs/cifsproto.h     |  130 +++---
+ fs/cifs/cifssmb.c       |  246 +++++-----
+ fs/cifs/connect.c       |  193 +-------
+ fs/cifs/dir.c           |  124 +++--
+ fs/cifs/file.c          | 1054 ++++++++++++++++++++++++------------------
+ fs/cifs/inode.c         |  377 +++++++--------
+ fs/cifs/ioctl.c         |   32 +-
+ fs/cifs/link.c          |   74 +--
+ fs/cifs/misc.c          |   32 +-
+ fs/cifs/netmisc.c       |    3 +-
+ fs/cifs/readdir.c       |  165 ++++---
+ fs/cifs/smb1ops.c       |  330 ++++++++++++-
+ fs/cifs/smb2file.c      |  302 ++++++++++++
+ fs/cifs/smb2glob.h      |   14 +
+ fs/cifs/smb2inode.c     |   98 +++-
+ fs/cifs/smb2maperror.c  |    3 +-
+ fs/cifs/smb2misc.c      |  240 +++++++++-
+ fs/cifs/smb2ops.c       |  327 ++++++++++++-
+ fs/cifs/smb2pdu.c       | 1174 ++++++++++++++++++++++++++++++++++++++++++++++-
+ fs/cifs/smb2pdu.h       |  272 ++++++++++-
+ fs/cifs/smb2proto.h     |   87 +++-
+ fs/cifs/smb2transport.c |  204 ++++++--
+ fs/cifs/transport.c     |  283 ++++++++----
+ 31 files changed, 4730 insertions(+), 1433 deletions(-)
+ create mode 100644 fs/cifs/smb2file.c
+Merging configfs/linux-next (b930c26 Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs)
+$ git merge configfs/linux-next
+Already up-to-date.
+Merging ecryptfs/next (0d7614f Linux 3.6-rc1)
+$ git merge ecryptfs/next
+Already up-to-date.
+Merging ext3/for_next (09e05d4 jbd: Fix assertion failure in commit code due to lacking transaction credits)
+$ git merge ext3/for_next
+Merge made by the 'recursive' strategy.
+ fs/ext3/super.c      |    8 ++++---
+ fs/jbd/commit.c      |   45 ++++++++++++++++++++++++++---------
+ fs/jbd/transaction.c |   64 ++++++++++++++++++++++++++++++++++----------------
+ fs/reiserfs/xattr.c  |    2 +-
+ fs/udf/file.c        |    9 +++++++
+ fs/udf/inode.c       |   59 +++++++++++++++++++++++++++++++++-------------
+ 6 files changed, 136 insertions(+), 51 deletions(-)
+Merging ext4/dev (f9195e3 ext4: check free inode count before allocating an inode)
+$ git merge ext4/dev
+Auto-merging fs/jbd2/journal.c
+Auto-merging fs/ext4/super.c
+Auto-merging fs/ext4/inode.c
+Merge made by the 'recursive' strategy.
+ Documentation/ABI/testing/sysfs-fs-ext4 |   13 +
+ Documentation/filesystems/ext4.txt      |   10 +
+ fs/ext4/Makefile                        |    2 +-
+ fs/ext4/ext4.h                          |   20 +-
+ fs/ext4/ext4_extents.h                  |    3 +-
+ fs/ext4/extents.c                       |  412 ++++++++--------------------
+ fs/ext4/extents_status.c                |  442 +++++++++++++++++++++++++++++++
+ fs/ext4/extents_status.h                |   45 ++++
+ fs/ext4/file.c                          |  153 ++++++++++-
+ fs/ext4/fsync.c                         |    9 +-
+ fs/ext4/ialloc.c                        |    9 +
+ fs/ext4/indirect.c                      |    4 +-
+ fs/ext4/inode.c                         |   94 +++----
+ fs/ext4/ioctl.c                         |   15 --
+ fs/ext4/mballoc.c                       |  118 +++++----
+ fs/ext4/mballoc.h                       |    5 -
+ fs/ext4/namei.c                         |   16 +-
+ fs/ext4/resize.c                        |  413 +++++++++++++++++++++++------
+ fs/ext4/super.c                         |   94 +++++--
+ fs/fs-writeback.c                       |    1 +
+ fs/jbd2/journal.c                       |    5 +
+ fs/jbd2/recovery.c                      |    7 +-
+ include/trace/events/ext4.h             |  343 +++++++++++++++---------
+ 23 files changed, 1552 insertions(+), 681 deletions(-)
+ create mode 100644 fs/ext4/extents_status.c
+ create mode 100644 fs/ext4/extents_status.h
+Merging fuse/for-next (c7a3f5e fuse: Move CUSE Kconfig entry from fs/Kconfig into fs/fuse/Kconfig)
+$ git merge fuse/for-next
+Auto-merging fs/fuse/inode.c
+Auto-merging fs/fuse/dev.c
+Merge made by the 'recursive' strategy.
+ fs/Kconfig           |   10 ----
+ fs/fuse/Kconfig      |   16 ++++-
+ fs/fuse/dev.c        |   19 ++++++
+ fs/fuse/dir.c        |  160 ++++++++++++++++++++++++++++++++++++++++++++++++--
+ fs/fuse/fuse_i.h     |    6 ++
+ fs/fuse/inode.c      |    5 +-
+ include/linux/fuse.h |   12 ++++
+ 7 files changed, 211 insertions(+), 17 deletions(-)
+Merging gfs2/master (2216db7 GFS2: Write out dirty inode metadata in delayed deletes)
+$ git merge gfs2/master
+Merge made by the 'recursive' strategy.
+ fs/gfs2/aops.c       |   11 +-
+ fs/gfs2/bmap.c       |    2 +-
+ fs/gfs2/file.c       |    4 +-
+ fs/gfs2/glock.c      |   60 +--
+ fs/gfs2/glops.c      |    1 +
+ fs/gfs2/incore.h     |   30 +-
+ fs/gfs2/inode.c      |   20 +-
+ fs/gfs2/ops_fstype.c |    8 +
+ fs/gfs2/quota.c      |   11 +-
+ fs/gfs2/rgrp.c       | 1203 ++++++++++++++++++++++++--------------------------
+ fs/gfs2/rgrp.h       |   28 +-
+ fs/gfs2/super.c      |    9 +-
+ fs/gfs2/trace_gfs2.h |   20 +-
+ fs/gfs2/trans.h      |    7 +-
+ fs/gfs2/xattr.c      |   96 ++--
+ 15 files changed, 710 insertions(+), 800 deletions(-)
+Merging jfs/jfs-next (84f4141 jfs: Fix do_div precision in commit b40c2e66)
+$ git merge jfs/jfs-next
+Merge made by the 'recursive' strategy.
+ Documentation/filesystems/jfs.txt |   19 ++++--
+ fs/jfs/Makefile                   |    2 +-
+ fs/jfs/ioctl.c                    |   43 ++++++++++++-
+ fs/jfs/jfs_discard.c              |  117 ++++++++++++++++++++++++++++++++++
+ fs/jfs/jfs_discard.h              |   26 ++++++++
+ fs/jfs/jfs_dmap.c                 |  126 +++++++++++++++++++++++++++++++++++--
+ fs/jfs/jfs_dmap.h                 |    2 +
+ fs/jfs/jfs_filsys.h               |    3 +
+ fs/jfs/jfs_incore.h               |    1 +
+ fs/jfs/jfs_txnmgr.c               |    9 +--
+ fs/jfs/super.c                    |   71 ++++++++++++++++-----
+ 11 files changed, 388 insertions(+), 31 deletions(-)
+ create mode 100644 fs/jfs/jfs_discard.c
+ create mode 100644 fs/jfs/jfs_discard.h
+Merging logfs/master (ab2ec19 logfs: fix possible memory leak in logfs_mtd_can_write_buf())
+$ git merge logfs/master
+Merge made by the 'recursive' strategy.
+ fs/logfs/dev_mtd.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+Merging nfs/linux-next (f743c73 NFSv4.1: nfs4_proc_layoutreturn must always drop the plh_block_lgets count)
+$ git merge nfs/linux-next
+Merge made by the 'recursive' strategy.
+ fs/nfs/blocklayout/blocklayout.c |    2 +-
+ fs/nfs/callback_proc.c           |   31 +++-
+ fs/nfs/direct.c                  |   16 +-
+ fs/nfs/file.c                    |   41 +++--
+ fs/nfs/inode.c                   |   10 +-
+ fs/nfs/nfs4_fs.h                 |    8 +-
+ fs/nfs/nfs4file.c                |   29 ++--
+ fs/nfs/nfs4filelayout.c          |   41 +++--
+ fs/nfs/nfs4filelayout.h          |   16 +-
+ fs/nfs/nfs4filelayoutdev.c       |   17 +--
+ fs/nfs/nfs4proc.c                |   60 ++++----
+ fs/nfs/nfs4state.c               |   29 ++--
+ fs/nfs/nfs4xdr.c                 |    9 +-
+ fs/nfs/pagelist.c                |   12 +-
+ fs/nfs/pnfs.c                    |  311 ++++++++++++++++++++++----------------
+ fs/nfs/pnfs.h                    |   54 ++-----
+ fs/nfs/pnfs_dev.c                |   27 ++++
+ fs/nfs/write.c                   |   11 +-
+ include/linux/nfs_fs.h           |    9 +-
+ include/linux/nfs_xdr.h          |    1 -
+ include/linux/sunrpc/xprt.h      |    3 +-
+ net/sunrpc/xdr.c                 |   23 ++-
+ net/sunrpc/xprt.c                |    8 +-
+ net/sunrpc/xprtrdma/transport.c  |   22 +--
+ net/sunrpc/xprtsock.c            |   39 ++---
+ 25 files changed, 473 insertions(+), 356 deletions(-)
+Merging nfsd/nfsd-next (fac7a17 nfsd4: cast readlink() bug argument)
+$ git merge nfsd/nfsd-next
+Merge made by the 'recursive' strategy.
+ .../filesystems/nfs/nfsd-admin-interfaces.txt      |   41 ++++
+ fs/lockd/svc.c                                     |   17 +-
+ fs/locks.c                                         |    6 +-
+ fs/nfs/callback.c                                  |   16 +-
+ fs/nfsd/nfs2acl.c                                  |    3 +-
+ fs/nfsd/nfs3proc.c                                 |    2 +-
+ fs/nfsd/nfs4callback.c                             |    1 -
+ fs/nfsd/nfs4idmap.c                                |    4 +-
+ fs/nfsd/nfs4proc.c                                 |    4 +-
+ fs/nfsd/nfs4state.c                                |  134 ++++++-----
+ fs/nfsd/nfsctl.c                                   |   84 +------
+ fs/nfsd/nfsd.h                                     |    4 +-
+ fs/nfsd/nfssvc.c                                   |   26 +--
+ fs/nfsd/state.h                                    |    6 +-
+ fs/nfsd/vfs.c                                      |    2 +-
+ include/linux/sunrpc/svc_xprt.h                    |    5 +-
+ include/linux/sunrpc/svcsock.h                     |    3 -
+ net/sunrpc/svc_xprt.c                              |  233 ++++++++++++--------
+ net/sunrpc/svcsock.c                               |  157 +++++--------
+ net/sunrpc/xprtrdma/svc_rdma_transport.c           |    4 -
+ 20 files changed, 340 insertions(+), 412 deletions(-)
+ create mode 100644 Documentation/filesystems/nfs/nfsd-admin-interfaces.txt
+Merging ocfs2/linux-next (4538df6 ocfs2: Don't spam on -EDQUOT.)
+$ git merge ocfs2/linux-next
+Merge made by the 'recursive' strategy.
+ fs/ocfs2/cluster/heartbeat.c |   40 +++++++++-------------------------------
+ fs/ocfs2/cluster/masklog.h   |    3 ++-
+ fs/ocfs2/dlm/dlmmaster.c     |   10 ++++++++--
+ fs/ocfs2/dlm/dlmrecovery.c   |    7 +++++++
+ fs/ocfs2/symlink.c           |    2 +-
+ 5 files changed, 27 insertions(+), 35 deletions(-)
+Merging omfs/for-next (976d167 Linux 3.1-rc9)
+$ git merge omfs/for-next
+Already up-to-date.
+Merging squashfs/master (4b0180a Squashfs: add mount time sanity check for block_size and block_log match)
+$ git merge squashfs/master
+Already up-to-date.
+Merging v9fs/for-next (552aad0 9P: Fix race between p9_write_work() and p9_fd_request())
+$ git merge v9fs/for-next
+Merge made by the 'recursive' strategy.
+ fs/9p/v9fs.c      |   30 +++++++++++++++++++-----------
+ fs/9p/vfs_inode.c |    8 ++++----
+ net/9p/client.c   |   18 ++++++++++++++++--
+ net/9p/trans_fd.c |   38 ++++++++++++++++++++------------------
+ 4 files changed, 59 insertions(+), 35 deletions(-)
+Merging ubifs/linux-next (3668b70 UBIFS: print less)
+$ git merge ubifs/linux-next
+Merge made by the 'recursive' strategy.
+ fs/ubifs/budget.c     |    5 +-
+ fs/ubifs/commit.c     |    8 +-
+ fs/ubifs/compress.c   |    7 +-
+ fs/ubifs/debug.c      |  633 +++++++++++++++++++++----------------------------
+ fs/ubifs/debug.h      |   15 +-
+ fs/ubifs/dir.c        |    4 +-
+ fs/ubifs/file.c       |    4 +-
+ fs/ubifs/gc.c         |    6 +-
+ fs/ubifs/log.c        |   14 +-
+ fs/ubifs/lprops.c     |   66 +++---
+ fs/ubifs/lpt.c        |    5 +-
+ fs/ubifs/lpt_commit.c |   58 ++---
+ fs/ubifs/orphan.c     |    7 +-
+ fs/ubifs/recovery.c   |   11 +-
+ fs/ubifs/replay.c     |   16 +-
+ fs/ubifs/sb.c         |   19 +-
+ fs/ubifs/scan.c       |   15 +-
+ fs/ubifs/super.c      |  119 +++++-----
+ fs/ubifs/tnc_misc.c   |    4 +-
+ fs/ubifs/ubifs.h      |   13 +-
+ 20 files changed, 451 insertions(+), 578 deletions(-)
+Merging xfs/for-next (4026c9f xfs: stop the sync worker before xfs_unmountfs)
+$ git merge xfs/for-next
+Merge made by the 'recursive' strategy.
+ fs/xfs/xfs_file.c  |  379 +++++++++++++++++++++++++++++++++++++++++++++++-----
+ fs/xfs/xfs_mount.h |    5 -
+ fs/xfs/xfs_trace.h |    1 +
+ 3 files changed, 345 insertions(+), 40 deletions(-)
+Merging vfs/for-next (319074e do_add_mount()/umount -l races)
+$ git merge vfs/for-next
+Resolved 'fs/stat.c' using previous resolution.
+Resolved 'kernel/events/core.c' using previous resolution.
+Auto-merging net/socket.c
+Auto-merging net/9p/trans_fd.c
+Auto-merging mm/mmap.c
+Auto-merging kernel/events/core.c
+CONFLICT (content): Merge conflict in kernel/events/core.c
+Auto-merging fs/stat.c
+CONFLICT (content): Merge conflict in fs/stat.c
+Auto-merging fs/ocfs2/cluster/heartbeat.c
+Auto-merging fs/nfsd/nfs4state.c
+Auto-merging fs/locks.c
+Auto-merging fs/fuse/dev.c
+Auto-merging fs/ext4/ioctl.c
+Auto-merging fs/btrfs/ioctl.c
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master 42c9076] Merge remote-tracking branch 'vfs/for-next'
+$ git diff -M --stat --summary HEAD^..
+ arch/alpha/kernel/osf_sys.c                  |   13 +-
+ arch/ia64/kernel/perfmon.c                   |   18 +-
+ arch/parisc/hpux/fs.c                        |   17 +-
+ arch/powerpc/platforms/cell/spu_syscalls.c   |   21 +-
+ arch/powerpc/platforms/cell/spufs/coredump.c |   40 +-
+ arch/um/drivers/mconsole_kern.c              |   99 +----
+ drivers/base/dma-buf.c                       |    3 +-
+ drivers/infiniband/core/ucma.c               |   10 +-
+ drivers/infiniband/core/uverbs_cmd.c         |   21 +-
+ drivers/infiniband/core/uverbs_main.c        |   11 +-
+ drivers/staging/android/binder.c             |  113 +----
+ drivers/staging/omapdrm/omap_gem.c           |    3 +-
+ drivers/tty/tty_io.c                         |   45 +-
+ drivers/vfio/vfio.c                          |   15 +-
+ drivers/vhost/vhost.c                        |    8 +-
+ drivers/video/msm/mdp.c                      |   12 +-
+ fs/autofs4/dev-ioctl.c                       |   18 +-
+ fs/autofs4/waitq.c                           |    3 +-
+ fs/btrfs/ioctl.c                             |   32 +-
+ fs/btrfs/reada.c                             |   18 +-
+ fs/coda/inode.c                              |   32 +-
+ fs/compat.c                                  |   90 ++--
+ fs/compat_ioctl.c                            |   27 +-
+ fs/eventpoll.c                               |   23 +-
+ fs/exec.c                                    |   59 +--
+ fs/ext4/ioctl.c                              |   15 +-
+ fs/fcntl.c                                   |  128 +-----
+ fs/fhandle.c                                 |   17 +-
+ fs/file.c                                    |  573 ++++++++++++++++++++++++--
+ fs/file_table.c                              |  106 -----
+ fs/fuse/dev.c                                |    3 +-
+ fs/ioctl.c                                   |   25 +-
+ fs/lockd/svclock.c                           |    3 +-
+ fs/locks.c                                   |   20 +-
+ fs/namei.c                                   |    2 +-
+ fs/namespace.c                               |   10 +-
+ fs/nfsd/nfs4state.c                          |    3 +-
+ fs/notify/fanotify/fanotify_user.c           |   87 ++--
+ fs/notify/inotify/inotify_user.c             |   28 +-
+ fs/ocfs2/cluster/heartbeat.c                 |   38 +-
+ fs/open.c                                    |  117 ++----
+ fs/pipe.c                                    |   31 +-
+ fs/proc/Makefile                             |    2 +-
+ fs/proc/base.c                               |  417 +------------------
+ fs/proc/fd.c                                 |  367 +++++++++++++++++
+ fs/proc/fd.h                                 |   14 +
+ fs/proc/internal.h                           |   48 +++
+ fs/read_write.c                              |  176 ++++----
+ fs/readdir.c                                 |   36 +-
+ fs/select.c                                  |   31 +-
+ fs/signalfd.c                                |   13 +-
+ fs/splice.c                                  |   69 ++--
+ fs/stat.c                                    |   10 +-
+ fs/statfs.c                                  |    9 +-
+ fs/sync.c                                    |   33 +-
+ fs/timerfd.c                                 |   45 +-
+ fs/utimes.c                                  |   11 +-
+ fs/xattr.c                                   |   52 +--
+ fs/xfs/xfs_dfrag.c                           |   34 +-
+ fs/xfs/xfs_ioctl.c                           |   10 +-
+ include/linux/fdtable.h                      |   39 +-
+ include/linux/file.h                         |   27 +-
+ include/linux/fs.h                           |    6 +-
+ include/linux/net.h                          |    3 +-
+ ipc/mqueue.c                                 |   78 ++--
+ kernel/events/core.c                         |   70 ++--
+ kernel/exit.c                                |   97 +----
+ kernel/sys.c                                 |   14 +-
+ kernel/taskstats.c                           |   11 +-
+ mm/fadvise.c                                 |   34 +-
+ mm/fremap.c                                  |    3 +-
+ mm/mmap.c                                    |    3 +-
+ mm/nommu.c                                   |    6 +-
+ mm/readahead.c                               |   14 +-
+ net/9p/trans_fd.c                            |   16 +-
+ net/compat.c                                 |    3 +-
+ net/core/netprio_cgroup.c                    |   38 +-
+ net/core/scm.c                               |    3 +-
+ net/sctp/socket.c                            |   25 +-
+ net/socket.c                                 |   66 +--
+ security/selinux/hooks.c                     |   73 +---
+ sound/core/pcm_native.c                      |   13 +-
+ 82 files changed, 1903 insertions(+), 2073 deletions(-)
+ create mode 100644 fs/proc/fd.c
+ create mode 100644 fs/proc/fd.h
+Merging pci/next (78c8f84 Merge branch 'pci/yinghai-misc' into next)
+$ git merge pci/next
+Removing drivers/pci/hotplug/fakephp.c
+Auto-merging drivers/net/wireless/iwlwifi/pcie/trans.c
+Auto-merging drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
+Auto-merging drivers/net/ethernet/mellanox/mlx4/main.c
+Auto-merging drivers/net/ethernet/intel/e1000/e1000_main.c
+Auto-merging drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+Auto-merging arch/xtensa/kernel/pci.c
+Merge made by the 'recursive' strategy.
+ Documentation/feature-removal-schedule.txt         |   32 --
+ arch/alpha/kernel/pci.c                            |    6 -
+ arch/arm/kernel/bios32.c                           |    9 -
+ arch/arm/mach-tegra/pcie.c                         |   12 +-
+ arch/frv/mb93090-mb00/pci-vdk.c                    |    4 +-
+ arch/ia64/pci/pci.c                                |   11 +-
+ arch/ia64/sn/kernel/io_common.c                    |    4 +-
+ arch/m68k/kernel/pcibios.c                         |    5 -
+ arch/mips/pci/pci-octeon.c                         |   15 +-
+ arch/mips/pci/pci.c                                |    6 -
+ arch/powerpc/include/asm/machdep.h                 |    3 +
+ arch/powerpc/kernel/pci-common.c                   |   20 ++
+ arch/powerpc/platforms/powernv/pci-ioda.c          |   41 ++-
+ arch/sh/drivers/pci/pci.c                          |    5 -
+ arch/sparc/kernel/leon_pci.c                       |    9 -
+ arch/sparc/kernel/pci.c                            |    4 -
+ arch/tile/kernel/pci.c                             |   34 +-
+ arch/tile/kernel/pci_gx.c                          |    8 -
+ arch/unicore32/kernel/pci.c                        |    8 -
+ arch/x86/pci/acpi.c                                |    3 +-
+ arch/x86/pci/visws.c                               |    5 -
+ arch/xtensa/kernel/pci.c                           |    8 -
+ drivers/acpi/pci_root.c                            |  101 +++---
+ drivers/acpi/pci_slot.c                            |   44 +--
+ drivers/block/nvme.c                               |    2 +-
+ drivers/char/agp/sgi-agp.c                         |    5 +-
+ drivers/gpu/drm/radeon/evergreen.c                 |   10 +-
+ drivers/gpu/vga/vgaarb.c                           |   29 +-
+ drivers/infiniband/hw/mthca/mthca_reset.c          |    8 +-
+ drivers/infiniband/hw/qib/qib.h                    |    2 +-
+ drivers/infiniband/hw/qib/qib_pcie.c               |   40 +--
+ drivers/iommu/intel-iommu.c                        |    6 +-
+ drivers/media/dvb/ngene/ngene-cards.c              |    2 +-
+ drivers/net/ethernet/atheros/atl1c/atl1c_main.c    |    4 +-
+ drivers/net/ethernet/atheros/atl1e/atl1e_main.c    |    2 +-
+ drivers/net/ethernet/broadcom/bnx2.c               |    2 +-
+ drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c   |   20 +-
+ drivers/net/ethernet/broadcom/tg3.c                |   52 +--
+ drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c    |    2 +-
+ drivers/net/ethernet/chelsio/cxgb3/t3_hw.c         |   22 +-
+ drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c    |   12 +-
+ drivers/net/ethernet/chelsio/cxgb4/t4_hw.c         |    6 +-
+ drivers/net/ethernet/emulex/benet/be_main.c        |    2 +-
+ drivers/net/ethernet/intel/e100.c                  |    2 +-
+ drivers/net/ethernet/intel/e1000/e1000_main.c      |    2 +-
+ drivers/net/ethernet/intel/e1000e/netdev.c         |   29 +-
+ drivers/net/ethernet/intel/igb/igb_main.c          |   14 +-
+ drivers/net/ethernet/intel/igbvf/netdev.c          |    2 +-
+ drivers/net/ethernet/intel/ixgb/ixgb_main.c        |    2 +-
+ drivers/net/ethernet/intel/ixgbe/ixgbe_main.c      |    4 +-
+ drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c  |    2 +-
+ drivers/net/ethernet/mellanox/mlx4/main.c          |    2 +-
+ drivers/net/ethernet/mellanox/mlx4/reset.c         |    8 +-
+ drivers/net/ethernet/myricom/myri10ge/myri10ge.c   |   31 +-
+ drivers/net/ethernet/neterion/s2io.c               |    2 +-
+ drivers/net/ethernet/neterion/vxge/vxge-config.c   |    4 +-
+ drivers/net/ethernet/neterion/vxge/vxge-main.c     |    2 +-
+ .../net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c   |    2 +-
+ .../net/ethernet/qlogic/netxen/netxen_nic_main.c   |    4 +-
+ drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c   |    2 +-
+ drivers/net/ethernet/qlogic/qlge/qlge_main.c       |    2 +-
+ drivers/net/ethernet/realtek/r8169.c               |   44 +--
+ drivers/net/ethernet/sun/niu.c                     |   19 +-
+ drivers/net/wireless/ath/ath9k/pci.c               |   21 +-
+ drivers/net/wireless/iwlegacy/common.h             |    4 +-
+ drivers/net/wireless/iwlwifi/pcie/trans.c          |    7 +-
+ drivers/net/wireless/rtlwifi/pci.c                 |    8 +-
+ drivers/parisc/dino.c                              |   10 +-
+ drivers/parisc/lba_pci.c                           |    7 +-
+ drivers/pci/Kconfig                                |    1 -
+ drivers/pci/access.c                               |  202 +++++++++++
+ drivers/pci/bus.c                                  |    6 +-
+ drivers/pci/hotplug/Kconfig                        |   24 +-
+ drivers/pci/hotplug/Makefile                       |    3 -
+ drivers/pci/hotplug/acpiphp_glue.c                 |   99 +++---
+ drivers/pci/hotplug/cpcihp_generic.c               |    8 +-
+ drivers/pci/hotplug/cpqphp_ctrl.c                  |   21 +-
+ drivers/pci/hotplug/fakephp.c                      |  164 ---------
+ drivers/pci/hotplug/pciehp_acpi.c                  |    6 +-
+ drivers/pci/hotplug/pciehp_core.c                  |   28 +-
+ drivers/pci/hotplug/pciehp_hpc.c                   |   12 +-
+ drivers/pci/hotplug/pcihp_slot.c                   |   20 +-
+ drivers/pci/iov.c                                  |    6 +-
+ drivers/pci/pci-driver.c                           |   57 +---
+ drivers/pci/pci.c                                  |  358 +++++---------------
+ drivers/pci/pcie/aer/aer_inject.c                  |    2 +-
+ drivers/pci/pcie/aer/aerdrv.c                      |   26 +-
+ drivers/pci/pcie/aer/aerdrv_acpi.c                 |    2 +-
+ drivers/pci/pcie/aer/aerdrv_core.c                 |   67 +---
+ drivers/pci/pcie/aspm.c                            |  119 +++----
+ drivers/pci/pcie/pme.c                             |   29 +-
+ drivers/pci/pcie/portdrv_bus.c                     |    2 +-
+ drivers/pci/pcie/portdrv_core.c                    |   34 +-
+ drivers/pci/pcie/portdrv_pci.c                     |   27 +-
+ drivers/pci/probe.c                                |   39 +--
+ drivers/pci/proc.c                                 |   19 --
+ drivers/pci/quirks.c                               |   31 +-
+ drivers/pci/remove.c                               |  156 +++------
+ drivers/pci/rom.c                                  |   59 ----
+ drivers/pci/search.c                               |   63 ++--
+ drivers/pci/setup-bus.c                            |   81 +++--
+ drivers/pci/setup-irq.c                            |    9 +-
+ drivers/pci/xen-pcifront.c                         |   10 +-
+ drivers/pcmcia/cardbus.c                           |   15 +-
+ drivers/rapidio/devices/tsi721.c                   |   18 +-
+ drivers/scsi/ipr.c                                 |    2 +-
+ drivers/scsi/lpfc/lpfc_init.c                      |    2 +-
+ drivers/scsi/mpt2sas/mpt2sas_scsih.c               |    2 +-
+ drivers/scsi/qla2xxx/qla_nx.c                      |    8 +-
+ drivers/scsi/qla2xxx/qla_os.c                      |    2 +-
+ drivers/scsi/qla4xxx/ql4_nx.c                      |    4 +-
+ drivers/scsi/qla4xxx/ql4_os.c                      |    2 +-
+ drivers/scsi/sym53c8xx_2/sym_glue.c                |    2 +-
+ drivers/staging/et131x/et131x.c                    |   19 +-
+ drivers/staging/rtl8192e/rtl8192e/rtl_pci.c        |    8 +-
+ drivers/tty/serial/8250/8250_pci.c                 |    2 +-
+ drivers/tty/serial/jsm/jsm_driver.c                |    2 +-
+ drivers/xen/xen-pciback/pci_stub.c                 |    2 +-
+ include/linux/acpi.h                               |    6 +-
+ include/linux/pci-acpi.h                           |   17 +-
+ include/linux/pci.h                                |   55 ++-
+ include/linux/pci_regs.h                           |    7 +
+ include/linux/pcieport_if.h                        |    2 +-
+ 123 files changed, 1078 insertions(+), 1750 deletions(-)
+ delete mode 100644 drivers/pci/hotplug/fakephp.c
+Merging powerpc/next (caa1d63 Merge remote-tracking branch 'kumar/next' into next)
+$ git merge powerpc/next
+Auto-merging drivers/scsi/ipr.c
+Removing arch/powerpc/include/asm/abs_addr.h
+Removing arch/powerpc/boot/dts/p2020rdb_camp_core1.dts
+Removing arch/powerpc/boot/dts/p2020rdb_camp_core0.dts
+Removing arch/powerpc/boot/dts/p1020rdb_camp_core1.dts
+Removing arch/powerpc/boot/dts/p1020rdb_camp_core0.dts
+Merge made by the 'recursive' strategy.
+ .../devicetree/bindings/powerpc/fsl/ifc.txt        |    9 +-
+ arch/powerpc/Kconfig                               |   17 +-
+ arch/powerpc/boot/Makefile                         |    1 +
+ arch/powerpc/boot/dts/fsl/e500mc_power_isa.dtsi    |   58 ++
+ arch/powerpc/boot/dts/fsl/e500v2_power_isa.dtsi    |   52 ++
+ arch/powerpc/boot/dts/fsl/e5500_power_isa.dtsi     |   59 ++
+ arch/powerpc/boot/dts/fsl/mpc8536si-pre.dtsi       |    3 +
+ arch/powerpc/boot/dts/fsl/mpc8544si-pre.dtsi       |    3 +
+ arch/powerpc/boot/dts/fsl/mpc8548si-pre.dtsi       |    3 +
+ arch/powerpc/boot/dts/fsl/mpc8568si-pre.dtsi       |    3 +
+ arch/powerpc/boot/dts/fsl/mpc8569si-pre.dtsi       |    3 +
+ arch/powerpc/boot/dts/fsl/mpc8572si-pre.dtsi       |    3 +
+ arch/powerpc/boot/dts/fsl/p1010si-pre.dtsi         |    3 +
+ arch/powerpc/boot/dts/fsl/p1020si-pre.dtsi         |    3 +
+ arch/powerpc/boot/dts/fsl/p1021si-pre.dtsi         |    3 +
+ arch/powerpc/boot/dts/fsl/p1022si-pre.dtsi         |    3 +
+ arch/powerpc/boot/dts/fsl/p1023si-pre.dtsi         |    3 +
+ arch/powerpc/boot/dts/fsl/p2020si-pre.dtsi         |    3 +
+ arch/powerpc/boot/dts/fsl/p2041si-pre.dtsi         |    3 +
+ arch/powerpc/boot/dts/fsl/p3041si-pre.dtsi         |    3 +
+ arch/powerpc/boot/dts/fsl/p4080si-pre.dtsi         |    3 +
+ arch/powerpc/boot/dts/fsl/p5020si-pre.dtsi         |    3 +
+ arch/powerpc/boot/dts/fsl/p5040si-post.dtsi        |  320 +++++++++
+ arch/powerpc/boot/dts/fsl/p5040si-pre.dtsi         |  114 ++++
+ arch/powerpc/boot/dts/fsl/qoriq-sec5.2-0.dtsi      |  118 ++++
+ arch/powerpc/boot/dts/mpc8536ds.dtsi               |    4 +
+ arch/powerpc/boot/dts/mpc8540ads.dts               |    2 +
+ arch/powerpc/boot/dts/mpc8541cds.dts               |    2 +
+ arch/powerpc/boot/dts/mpc8544ds.dts                |    4 +-
+ arch/powerpc/boot/dts/mpc8544ds.dtsi               |   39 ++
+ arch/powerpc/boot/dts/mpc8555cds.dts               |    2 +
+ arch/powerpc/boot/dts/mpc8560ads.dts               |    2 +
+ arch/powerpc/boot/dts/p1020rdb_camp_core0.dts      |   63 --
+ arch/powerpc/boot/dts/p1020rdb_camp_core1.dts      |  141 ----
+ arch/powerpc/boot/dts/p1022ds.dtsi                 |    4 +
+ arch/powerpc/boot/dts/p1022rdk.dts                 |  188 ++++++
+ arch/powerpc/boot/dts/p2020rdb_camp_core0.dts      |   67 --
+ arch/powerpc/boot/dts/p2020rdb_camp_core1.dts      |  125 ----
+ arch/powerpc/boot/dts/p2041rdb.dts                 |    4 +
+ arch/powerpc/boot/dts/p3041ds.dts                  |    4 +
+ arch/powerpc/boot/dts/p4080ds.dts                  |    4 +
+ arch/powerpc/boot/dts/p5020ds.dts                  |    4 +
+ arch/powerpc/boot/dts/p5040ds.dts                  |  207 ++++++
+ arch/powerpc/configs/corenet32_smp_defconfig       |    1 +
+ arch/powerpc/configs/corenet64_smp_defconfig       |    1 +
+ arch/powerpc/configs/mpc85xx_defconfig             |    1 +
+ arch/powerpc/configs/mpc85xx_smp_defconfig         |    1 +
+ arch/powerpc/configs/ppc64_defconfig               |    1 +
+ arch/powerpc/configs/pseries_defconfig             |    1 +
+ arch/powerpc/include/asm/abs_addr.h                |   56 --
+ arch/powerpc/include/asm/cacheflush.h              |    2 +
+ arch/powerpc/include/asm/debug.h                   |    2 +-
+ arch/powerpc/include/asm/eeh.h                     |  141 ++--
+ arch/powerpc/include/asm/eeh_event.h               |    6 +-
+ arch/powerpc/include/asm/exception-64e.h           |    6 +-
+ arch/powerpc/include/asm/fsl_guts.h                |    2 +
+ arch/powerpc/include/asm/fsl_ifc.h                 |   14 +-
+ arch/powerpc/include/asm/hvcall.h                  |    5 -
+ arch/powerpc/include/asm/hw_breakpoint.h           |    9 +-
+ arch/powerpc/include/asm/kprobes.h                 |   15 +-
+ arch/powerpc/include/asm/kvm_book3s.h              |    2 +-
+ arch/powerpc/include/asm/kvm_book3s_asm.h          |    1 -
+ arch/powerpc/include/asm/machdep.h                 |    9 +-
+ arch/powerpc/include/asm/mmu-hash64.h              |  169 +++--
+ arch/powerpc/include/asm/mmu.h                     |    9 +
+ arch/powerpc/include/asm/mpic.h                    |   19 +
+ arch/powerpc/include/asm/paca.h                    |    3 +-
+ arch/powerpc/include/asm/page_64.h                 |   10 +-
+ arch/powerpc/include/asm/pci-bridge.h              |   11 +
+ arch/powerpc/include/asm/pgtable-ppc64-4k.h        |    4 +-
+ arch/powerpc/include/asm/pgtable-ppc64-64k.h       |    2 +-
+ arch/powerpc/include/asm/pgtable-ppc64.h           |   19 +-
+ arch/powerpc/include/asm/pgtable.h                 |   10 +-
+ arch/powerpc/include/asm/ppc-opcode.h              |    3 +
+ arch/powerpc/include/asm/ppc-pci.h                 |   20 +-
+ arch/powerpc/include/asm/probes.h                  |   42 ++
+ arch/powerpc/include/asm/processor.h               |    6 +-
+ arch/powerpc/include/asm/pte-hash64-64k.h          |   18 +-
+ arch/powerpc/include/asm/reg.h                     |   50 +-
+ arch/powerpc/include/asm/setup.h                   |    2 +-
+ arch/powerpc/include/asm/smp.h                     |    2 +
+ arch/powerpc/include/asm/sparsemem.h               |    4 +-
+ arch/powerpc/include/asm/swiotlb.h                 |    6 +
+ arch/powerpc/include/asm/thread_info.h             |    7 +-
+ arch/powerpc/include/asm/tlbflush.h                |    7 +-
+ arch/powerpc/include/asm/uaccess.h                 |   11 -
+ arch/powerpc/include/asm/uprobes.h                 |   54 ++
+ arch/powerpc/kernel/Makefile                       |    1 +
+ arch/powerpc/kernel/asm-offsets.c                  |    2 +-
+ arch/powerpc/kernel/cpu_setup_fsl_booke.S          |   74 ++-
+ arch/powerpc/kernel/cputable.c                     |    4 +
+ arch/powerpc/kernel/dma-swiotlb.c                  |   22 +-
+ arch/powerpc/kernel/dma.c                          |    3 +-
+ arch/powerpc/kernel/entry_32.S                     |   47 +-
+ arch/powerpc/kernel/entry_64.S                     |   35 +
+ arch/powerpc/kernel/exceptions-64e.S               |  212 +++---
+ arch/powerpc/kernel/exceptions-64s.S               |  127 +++-
+ arch/powerpc/kernel/fadump.c                       |    3 +-
+ arch/powerpc/kernel/head_fsl_booke.S               |   46 +-
+ arch/powerpc/kernel/hw_breakpoint.c                |   25 +-
+ arch/powerpc/kernel/ibmebus.c                      |    1 -
+ arch/powerpc/kernel/irq.c                          |    8 +-
+ arch/powerpc/kernel/machine_kexec.c                |   14 +-
+ arch/powerpc/kernel/paca.c                         |    1 +
+ arch/powerpc/kernel/pci-common.c                   |   16 +-
+ arch/powerpc/kernel/process.c                      |   16 +-
+ arch/powerpc/kernel/prom.c                         |    4 +-
+ arch/powerpc/kernel/prom_init.c                    |    2 +-
+ arch/powerpc/kernel/ptrace.c                       |    3 +
+ arch/powerpc/kernel/rtas_flash.c                   |    7 +-
+ arch/powerpc/kernel/rtas_pci.c                     |    5 +-
+ arch/powerpc/kernel/signal.c                       |    8 +-
+ arch/powerpc/kernel/smp.c                          |   12 +-
+ arch/powerpc/kernel/time.c                         |    8 +-
+ arch/powerpc/kernel/traps.c                        |    1 +
+ arch/powerpc/kernel/uprobes.c                      |  184 ++++++
+ arch/powerpc/kernel/vdso.c                         |    4 +-
+ arch/powerpc/kernel/vio.c                          |    1 -
+ arch/powerpc/kvm/book3s_32_mmu_host.c              |    8 +-
+ arch/powerpc/kvm/book3s_64_mmu_host.c              |   17 +-
+ arch/powerpc/kvm/book3s_hv_rmhandlers.S            |    2 +-
+ arch/powerpc/kvm/trace.h                           |   14 +-
+ arch/powerpc/lib/sstep.c                           |   36 +-
+ arch/powerpc/mm/fault.c                            |    1 +
+ arch/powerpc/mm/hash_low_64.S                      |   97 +--
+ arch/powerpc/mm/hash_native_64.c                   |  166 +++--
+ arch/powerpc/mm/hash_utils_64.c                    |   48 +-
+ arch/powerpc/mm/hugetlbpage-hash64.c               |   15 +-
+ arch/powerpc/mm/init_64.c                          |    1 -
+ arch/powerpc/mm/mem.c                              |    5 +-
+ arch/powerpc/mm/mmu_context_hash64.c               |   10 +-
+ arch/powerpc/mm/pgtable_64.c                       |   13 +-
+ arch/powerpc/mm/slb_low.S                          |   62 +-
+ arch/powerpc/mm/slice.c                            |  112 ++--
+ arch/powerpc/mm/stab.c                             |    3 +-
+ arch/powerpc/mm/subpage-prot.c                     |    6 +-
+ arch/powerpc/mm/tlb_hash64.c                       |   11 +-
+ arch/powerpc/mm/tlb_low_64e.S                      |   18 +-
+ arch/powerpc/oprofile/op_model_power4.c            |  116 +++-
+ arch/powerpc/perf/core-book3s.c                    |    2 +-
+ arch/powerpc/platforms/44x/currituck.c             |   10 +-
+ arch/powerpc/platforms/85xx/Kconfig                |   21 +
+ arch/powerpc/platforms/85xx/Makefile               |    2 +
+ arch/powerpc/platforms/85xx/common.c               |   10 +
+ arch/powerpc/platforms/85xx/corenet_ds.c           |   38 +-
+ arch/powerpc/platforms/85xx/ge_imp3a.c             |   62 +-
+ arch/powerpc/platforms/85xx/mpc8536_ds.c           |   36 +-
+ arch/powerpc/platforms/85xx/mpc85xx_ads.c          |   11 +-
+ arch/powerpc/platforms/85xx/mpc85xx_cds.c          |   44 +-
+ arch/powerpc/platforms/85xx/mpc85xx_ds.c           |   15 +-
+ arch/powerpc/platforms/85xx/mpc85xx_mds.c          |   40 +-
+ arch/powerpc/platforms/85xx/mpc85xx_rdb.c          |   30 +-
+ arch/powerpc/platforms/85xx/p1010rdb.c             |   14 +-
+ arch/powerpc/platforms/85xx/p1022_ds.c             |   36 +-
+ arch/powerpc/platforms/85xx/p1022_rdk.c            |  167 +++++
+ arch/powerpc/platforms/85xx/p1023_rds.c            |    9 +-
+ arch/powerpc/platforms/85xx/p2041_rdb.c            |    2 +-
+ arch/powerpc/platforms/85xx/p3041_ds.c             |    2 +-
+ arch/powerpc/platforms/85xx/p4080_ds.c             |    2 +-
+ arch/powerpc/platforms/85xx/p5020_ds.c             |    2 +-
+ arch/powerpc/platforms/85xx/p5040_ds.c             |   89 +++
+ arch/powerpc/platforms/85xx/qemu_e500.c            |    5 +-
+ arch/powerpc/platforms/85xx/sbc8548.c              |   21 +-
+ arch/powerpc/platforms/85xx/smp.c                  |  220 +++++--
+ arch/powerpc/platforms/85xx/socrates.c             |   11 +-
+ arch/powerpc/platforms/85xx/stx_gp3.c              |   13 +-
+ arch/powerpc/platforms/85xx/tqm85xx.c              |   21 +-
+ arch/powerpc/platforms/85xx/xes_mpc85xx.c          |   56 +-
+ arch/powerpc/platforms/86xx/gef_ppc9a.c            |   12 +-
+ arch/powerpc/platforms/86xx/gef_sbc310.c           |   13 +-
+ arch/powerpc/platforms/86xx/gef_sbc610.c           |   12 +-
+ arch/powerpc/platforms/86xx/mpc8610_hpcd.c         |   21 +-
+ arch/powerpc/platforms/86xx/mpc86xx_hpcn.c         |   42 +-
+ arch/powerpc/platforms/86xx/sbc8641d.c             |   14 +-
+ arch/powerpc/platforms/cell/beat.c                 |    4 +-
+ arch/powerpc/platforms/cell/beat.h                 |    2 +-
+ arch/powerpc/platforms/cell/beat_htab.c            |   45 +-
+ arch/powerpc/platforms/pasemi/iommu.c              |    6 +-
+ arch/powerpc/platforms/powernv/pci-ioda.c          |  695 +++++---------------
+ arch/powerpc/platforms/powernv/pci-p5ioc2.c        |    1 -
+ arch/powerpc/platforms/powernv/pci.c               |    7 +-
+ arch/powerpc/platforms/powernv/pci.h               |   21 +-
+ arch/powerpc/platforms/ps3/htab.c                  |   22 +-
+ arch/powerpc/platforms/ps3/setup.c                 |   10 +-
+ arch/powerpc/platforms/pseries/Makefile            |    5 +-
+ arch/powerpc/platforms/pseries/eeh.c               |  543 ++++-----------
+ arch/powerpc/platforms/pseries/eeh_cache.c         |   59 +-
+ arch/powerpc/platforms/pseries/eeh_dev.c           |   14 +-
+ arch/powerpc/platforms/pseries/eeh_driver.c        |  310 ++++-----
+ arch/powerpc/platforms/pseries/eeh_event.c         |   54 +-
+ arch/powerpc/platforms/pseries/eeh_pe.c            |  655 ++++++++++++++++++
+ arch/powerpc/platforms/pseries/eeh_pseries.c       |  247 ++++---
+ arch/powerpc/platforms/pseries/eeh_sysfs.c         |    9 -
+ arch/powerpc/platforms/pseries/iommu.c             |   12 +-
+ arch/powerpc/platforms/pseries/lpar.c              |   77 +--
+ arch/powerpc/platforms/pseries/msi.c               |   26 +-
+ arch/powerpc/platforms/pseries/pci.c               |    2 +-
+ arch/powerpc/platforms/pseries/pci_dlpar.c         |   32 +-
+ arch/powerpc/platforms/pseries/setup.c             |   22 +-
+ arch/powerpc/sysdev/Makefile                       |    2 +-
+ arch/powerpc/sysdev/dart_iommu.c                   |    7 +-
+ arch/powerpc/sysdev/fsl_85xx_l2ctlr.c              |   10 +
+ arch/powerpc/sysdev/fsl_mpic_err.c                 |  149 +++++
+ arch/powerpc/sysdev/fsl_pci.c                      |  118 ++--
+ arch/powerpc/sysdev/fsl_pci.h                      |   20 +-
+ arch/powerpc/sysdev/mpic.c                         |  102 ++-
+ arch/powerpc/sysdev/mpic.h                         |   22 +
+ arch/powerpc/xmon/xmon.c                           |  111 +++-
+ drivers/crypto/nx/nx.c                             |   17 +-
+ drivers/edac/mpc85xx_edac.c                        |   43 +-
+ drivers/infiniband/hw/ehca/ehca_cq.c               |    2 +-
+ drivers/infiniband/hw/ehca/ehca_eq.c               |    2 +-
+ drivers/infiniband/hw/ehca/ehca_mrmw.c             |   45 +-
+ drivers/infiniband/hw/ehca/ehca_qp.c               |    6 +-
+ drivers/infiniband/hw/ehca/ehca_reqs.c             |    2 +-
+ drivers/infiniband/hw/ehca/ehca_tools.h            |    1 -
+ drivers/infiniband/hw/ehca/hcp_if.c                |   12 +-
+ drivers/infiniband/hw/ehca/ipz_pt_fn.c             |    2 +-
+ drivers/macintosh/smu.c                            |    3 +-
+ drivers/net/ethernet/ibm/ehea/ehea.h               |    1 -
+ drivers/net/ethernet/ibm/ehea/ehea_phyp.c          |   12 +-
+ drivers/net/ethernet/ibm/ehea/ehea_qmr.c           |   14 +-
+ drivers/pci/hotplug/rpadlpar_core.c                |    2 +-
+ drivers/scsi/ipr.c                                 |   18 +-
+ drivers/tty/hvc/hvc_console.c                      |   33 +-
+ drivers/tty/hvc/hvc_vio.c                          |  123 ++--
+ drivers/video/ps3fb.c                              |    3 +-
+ 227 files changed, 5780 insertions(+), 3170 deletions(-)
+ create mode 100644 arch/powerpc/boot/dts/fsl/e500mc_power_isa.dtsi
+ create mode 100644 arch/powerpc/boot/dts/fsl/e500v2_power_isa.dtsi
+ create mode 100644 arch/powerpc/boot/dts/fsl/e5500_power_isa.dtsi
+ create mode 100644 arch/powerpc/boot/dts/fsl/p5040si-post.dtsi
+ create mode 100644 arch/powerpc/boot/dts/fsl/p5040si-pre.dtsi
+ create mode 100644 arch/powerpc/boot/dts/fsl/qoriq-sec5.2-0.dtsi
+ delete mode 100644 arch/powerpc/boot/dts/p1020rdb_camp_core0.dts
+ delete mode 100644 arch/powerpc/boot/dts/p1020rdb_camp_core1.dts
+ create mode 100644 arch/powerpc/boot/dts/p1022rdk.dts
+ delete mode 100644 arch/powerpc/boot/dts/p2020rdb_camp_core0.dts
+ delete mode 100644 arch/powerpc/boot/dts/p2020rdb_camp_core1.dts
+ create mode 100644 arch/powerpc/boot/dts/p5040ds.dts
+ delete mode 100644 arch/powerpc/include/asm/abs_addr.h
+ create mode 100644 arch/powerpc/include/asm/probes.h
+ create mode 100644 arch/powerpc/include/asm/uprobes.h
+ create mode 100644 arch/powerpc/kernel/uprobes.c
+ create mode 100644 arch/powerpc/platforms/85xx/p1022_rdk.c
+ create mode 100644 arch/powerpc/platforms/85xx/p5040_ds.c
+ create mode 100644 arch/powerpc/platforms/pseries/eeh_pe.c
+ create mode 100644 arch/powerpc/sysdev/fsl_mpic_err.c
+Merging 4xx/next (2074b1d powerpc: Fix irq distribution)
+$ git merge 4xx/next
+Already up-to-date.
+Merging mpc5xxx/next (9d9fd88 powerpc/mpc52xx_lpbfifo: optionally defer fifo transfer start)
+$ git merge mpc5xxx/next
+Merge made by the 'recursive' strategy.
+ Documentation/devicetree/bindings/misc/ifm-csi.txt |   41 ++++++
+ arch/powerpc/boot/dts/o2d.dts                      |   47 +++++++
+ arch/powerpc/boot/dts/o2d.dtsi                     |  139 ++++++++++++++++++++
+ arch/powerpc/boot/dts/o2d300.dts                   |   52 ++++++++
+ arch/powerpc/boot/dts/o2dnt2.dts                   |   48 +++++++
+ arch/powerpc/boot/dts/o2i.dts                      |   33 +++++
+ arch/powerpc/boot/dts/o2mnt.dts                    |   33 +++++
+ arch/powerpc/boot/dts/o3dnt.dts                    |   48 +++++++
+ arch/powerpc/include/asm/mpc52xx.h                 |    2 +
+ arch/powerpc/platforms/512x/Kconfig                |    1 +
+ arch/powerpc/platforms/512x/clock.c                |    6 +-
+ arch/powerpc/platforms/512x/mpc512x_shared.c       |    6 -
+ arch/powerpc/platforms/52xx/mpc5200_simple.c       |    1 +
+ arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c      |   35 ++++-
+ 14 files changed, 483 insertions(+), 9 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/misc/ifm-csi.txt
+ create mode 100644 arch/powerpc/boot/dts/o2d.dts
+ create mode 100644 arch/powerpc/boot/dts/o2d.dtsi
+ create mode 100644 arch/powerpc/boot/dts/o2d300.dts
+ create mode 100644 arch/powerpc/boot/dts/o2dnt2.dts
+ create mode 100644 arch/powerpc/boot/dts/o2i.dts
+ create mode 100644 arch/powerpc/boot/dts/o2mnt.dts
+ create mode 100644 arch/powerpc/boot/dts/o3dnt.dts
+Merging galak/next (4d56dec powerpc/fsl-pci: fix warning when CONFIG_SWIOTLB is disabled)
+$ git merge galak/next
+Merge made by the 'recursive' strategy.
+ arch/powerpc/configs/85xx/p1023rds_defconfig |    6 ++++++
+ arch/powerpc/kernel/smp.c                    |    2 +-
+ arch/powerpc/sysdev/fsl_ifc.c                |   20 ++++++++------------
+ arch/powerpc/sysdev/fsl_pci.c                |    2 ++
+ 4 files changed, 17 insertions(+), 13 deletions(-)
+Merging hid/for-next (45654be Merge branch 'logitech' into for-next)
+$ git merge hid/for-next
+Removing drivers/hid/hid-picolcd.c
+Auto-merging MAINTAINERS
+Merge made by the 'recursive' strategy.
+ Documentation/ABI/testing/sysfs-driver-wacom |   13 +
+ MAINTAINERS                                  |    6 +
+ drivers/hid/Kconfig                          |    9 +-
+ drivers/hid/Makefile                         |   20 +
+ drivers/hid/hid-a4tech.c                     |    1 -
+ drivers/hid/hid-apple.c                      |    1 -
+ drivers/hid/hid-aureal.c                     |    1 -
+ drivers/hid/hid-belkin.c                     |    1 -
+ drivers/hid/hid-cherry.c                     |    1 -
+ drivers/hid/hid-core.c                       |   20 +-
+ drivers/hid/hid-cypress.c                    |    1 -
+ drivers/hid/hid-debug.c                      |   12 +-
+ drivers/hid/hid-ezkey.c                      |    1 -
+ drivers/hid/hid-gyration.c                   |    1 -
+ drivers/hid/hid-holtekff.c                   |    3 +-
+ drivers/hid/hid-ids.h                        |   13 +-
+ drivers/hid/hid-input.c                      |   11 +-
+ drivers/hid/hid-lcpower.c                    |    2 +-
+ drivers/hid/hid-lenovo-tpkbd.c               |  147 +-
+ drivers/hid/hid-lg.c                         |   20 +-
+ drivers/hid/hid-lg.h                         |    4 +
+ drivers/hid/hid-lg4ff.c                      |  198 +-
+ drivers/hid/hid-magicmouse.c                 |    2 +-
+ drivers/hid/hid-microsoft.c                  |    1 -
+ drivers/hid/hid-monterey.c                   |    1 -
+ drivers/hid/hid-multitouch.c                 |  234 ++-
+ drivers/hid/hid-ntrig.c                      |    8 +-
+ drivers/hid/hid-petalynx.c                   |    1 -
+ drivers/hid/hid-picolcd.c                    | 2748 --------------------------
+ drivers/hid/hid-picolcd.h                    |  309 +++
+ drivers/hid/hid-picolcd_backlight.c          |  122 ++
+ drivers/hid/hid-picolcd_cir.c                |  152 ++
+ drivers/hid/hid-picolcd_core.c               |  689 +++++++
+ drivers/hid/hid-picolcd_debugfs.c            |  899 +++++++++
+ drivers/hid/hid-picolcd_fb.c                 |  615 ++++++
+ drivers/hid/hid-picolcd_lcd.c                |  107 +
+ drivers/hid/hid-picolcd_leds.c               |  175 ++
+ drivers/hid/hid-primax.c                     |   25 -
+ drivers/hid/hid-prodikeys.c                  |   18 +-
+ drivers/hid/hid-samsung.c                    |    1 -
+ drivers/hid/hid-sony.c                       |    1 -
+ drivers/hid/hid-sunplus.c                    |    1 -
+ drivers/hid/hid-uclogic.c                    |   98 +
+ drivers/hid/hid-wacom.c                      |  170 +-
+ drivers/hid/hid-waltop.c                     |   29 -
+ drivers/hid/hid-wiimote-ext.c                |   96 +
+ drivers/hid/hidraw.c                         |   15 +-
+ drivers/hid/usbhid/hid-quirks.c              |    3 +-
+ drivers/input/evdev.c                        |   78 +-
+ drivers/input/input-mt.c                     |  305 ++-
+ drivers/input/input.c                        |  254 ++-
+ drivers/input/misc/uinput.c                  |    2 +-
+ drivers/input/mouse/alps.c                   |    2 +-
+ drivers/input/mouse/bcm5974.c                |  348 ++--
+ drivers/input/mouse/elantech.c               |    4 +-
+ drivers/input/mouse/sentelic.c               |    2 +-
+ drivers/input/mouse/synaptics.c              |    4 +-
+ drivers/input/tablet/wacom_wac.c             |    6 +-
+ drivers/input/touchscreen/atmel_mxt_ts.c     |    2 +-
+ drivers/input/touchscreen/cyttsp_core.c      |    2 +-
+ drivers/input/touchscreen/edt-ft5x06.c       |    2 +-
+ drivers/input/touchscreen/egalax_ts.c        |    2 +-
+ drivers/input/touchscreen/ili210x.c          |    2 +-
+ drivers/input/touchscreen/mms114.c           |    2 +-
+ drivers/input/touchscreen/penmount.c         |    2 +-
+ drivers/input/touchscreen/wacom_w8001.c      |    2 +-
+ include/linux/hid.h                          |    5 +-
+ include/linux/input.h                        |   35 +-
+ include/linux/input/mt.h                     |   57 +-
+ 69 files changed, 4607 insertions(+), 3517 deletions(-)
+ delete mode 100644 drivers/hid/hid-picolcd.c
+ create mode 100644 drivers/hid/hid-picolcd.h
+ create mode 100644 drivers/hid/hid-picolcd_backlight.c
+ create mode 100644 drivers/hid/hid-picolcd_cir.c
+ create mode 100644 drivers/hid/hid-picolcd_core.c
+ create mode 100644 drivers/hid/hid-picolcd_debugfs.c
+ create mode 100644 drivers/hid/hid-picolcd_fb.c
+ create mode 100644 drivers/hid/hid-picolcd_lcd.c
+ create mode 100644 drivers/hid/hid-picolcd_leds.c
+Merging quilt/i2c (cde3336 i2c/scx200_*: Replace printks with pr_<level>s)
+$ git merge quilt/i2c
+Merge made by the 'recursive' strategy.
+ drivers/i2c/Kconfig                 |   16 ++-
+ drivers/i2c/busses/Kconfig          |   15 +--
+ drivers/i2c/busses/i2c-i801.c       |  214 ++++++++++++++++++++++++++++++++++-
+ drivers/i2c/busses/scx200_acb.c     |   24 ++--
+ drivers/i2c/busses/scx200_i2c.c     |   15 ++-
+ drivers/i2c/i2c-core.c              |   16 ++-
+ drivers/i2c/i2c-mux.c               |   22 ++++
+ drivers/i2c/i2c-smbus.c             |   11 +-
+ drivers/i2c/muxes/i2c-mux-gpio.c    |    4 +-
+ drivers/i2c/muxes/i2c-mux-pca9541.c |    2 +-
+ drivers/i2c/muxes/i2c-mux-pca954x.c |   10 +-
+ drivers/i2c/muxes/i2c-mux-pinctrl.c |    2 +-
+ include/linux/i2c-mux-gpio.h        |    2 +
+ include/linux/i2c-mux.h             |    1 +
+ include/linux/i2c/pca954x.h         |    1 +
+ 15 files changed, 302 insertions(+), 53 deletions(-)
+Merging i2c-embedded/i2c-embedded/for-next (2bdbfa9 i2c: davinci: preparation for switch to common clock framework)
+$ git merge i2c-embedded/i2c-embedded/for-next
+Auto-merging drivers/i2c/busses/Kconfig
+Removing arch/arm/mach-at91/include/mach/at91_twi.h
+Auto-merging arch/arm/boot/dts/at91sam9x5.dtsi
+Auto-merging arch/arm/boot/dts/at91sam9n12.dtsi
+Auto-merging arch/arm/boot/dts/at91sam9g45.dtsi
+Auto-merging arch/arm/boot/dts/at91sam9263.dtsi
+Auto-merging arch/arm/boot/dts/at91sam9260.dtsi
+Merge made by the 'recursive' strategy.
+ .../devicetree/bindings/i2c/atmel-i2c.txt          |   30 +
+ Documentation/devicetree/bindings/i2c/davinci.txt  |   28 +
+ arch/arm/boot/dts/at91sam9260.dtsi                 |   10 +
+ arch/arm/boot/dts/at91sam9263.dtsi                 |   10 +
+ arch/arm/boot/dts/at91sam9g20.dtsi                 |    4 +
+ arch/arm/boot/dts/at91sam9g25ek.dts                |   12 +
+ arch/arm/boot/dts/at91sam9g45.dtsi                 |   20 +
+ arch/arm/boot/dts/at91sam9m10g45ek.dts             |    8 +
+ arch/arm/boot/dts/at91sam9n12.dtsi                 |   20 +
+ arch/arm/boot/dts/at91sam9n12ek.dts                |    8 +
+ arch/arm/boot/dts/at91sam9x5.dtsi                  |   30 +
+ arch/arm/mach-at91/at91rm9200.c                    |    1 +
+ arch/arm/mach-at91/at91rm9200_devices.c            |    2 +-
+ arch/arm/mach-at91/at91sam9260.c                   |    3 +
+ arch/arm/mach-at91/at91sam9260_devices.c           |    8 +-
+ arch/arm/mach-at91/at91sam9261.c                   |    2 +
+ arch/arm/mach-at91/at91sam9261_devices.c           |   14 +-
+ arch/arm/mach-at91/at91sam9263.c                   |    2 +
+ arch/arm/mach-at91/at91sam9263_devices.c           |    2 +-
+ arch/arm/mach-at91/at91sam9g45.c                   |    4 +
+ arch/arm/mach-at91/at91sam9g45_devices.c           |   10 +-
+ arch/arm/mach-at91/at91sam9n12.c                   |    2 +
+ arch/arm/mach-at91/at91sam9rl.c                    |    2 +
+ arch/arm/mach-at91/at91sam9rl_devices.c            |    2 +-
+ arch/arm/mach-at91/at91sam9x5.c                    |    3 +
+ arch/arm/mach-at91/include/mach/at91_twi.h         |   68 --
+ drivers/i2c/busses/Kconfig                         |   17 +-
+ drivers/i2c/busses/i2c-at91.c                      |  667 +++++++++++++-------
+ drivers/i2c/busses/i2c-davinci.c                   |   58 +-
+ drivers/i2c/busses/i2c-imx.c                       |    6 +-
+ drivers/i2c/busses/i2c-nomadik.c                   |   17 -
+ drivers/i2c/busses/i2c-omap.c                      |  448 ++++++++-----
+ 32 files changed, 1003 insertions(+), 515 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/i2c/atmel-i2c.txt
+ create mode 100644 Documentation/devicetree/bindings/i2c/davinci.txt
+ delete mode 100644 arch/arm/mach-at91/include/mach/at91_twi.h
+Merging quilt/jdelvare-hwmon (46e486e hwmon: Update Alexey Fisher's name)
+$ git merge quilt/jdelvare-hwmon
+Merge made by the 'recursive' strategy.
+ Documentation/hwmon/max1619 |    2 +-
+ drivers/hwmon/max1619.c     |    4 ++--
+ drivers/hwmon/max6642.c     |    2 +-
+ 3 files changed, 4 insertions(+), 4 deletions(-)
+Merging hwmon-staging/hwmon-next (592758b hwmon: (mcp3021) Add MCP3221 support)
+$ git merge hwmon-staging/hwmon-next
+Auto-merging include/linux/platform_data/sht15.h
+Auto-merging Documentation/feature-removal-schedule.txt
+Merge made by the 'recursive' strategy.
+ Documentation/feature-removal-schedule.txt |   10 -
+ Documentation/hwmon/adt7410                |   51 +++
+ Documentation/hwmon/ina2xx                 |   18 ++
+ Documentation/hwmon/lm70                   |   12 +-
+ Documentation/hwmon/max197                 |   60 ++++
+ Documentation/hwmon/mcp3021                |   23 +-
+ arch/arm/mach-pxa/stargate2.c              |    2 +-
+ drivers/hwmon/Kconfig                      |  126 ++++----
+ drivers/hwmon/Makefile                     |    2 +
+ drivers/hwmon/abituguru.c                  |    7 +-
+ drivers/hwmon/abituguru3.c                 |    6 +-
+ drivers/hwmon/ad7314.c                     |   16 +-
+ drivers/hwmon/ad7414.c                     |   21 +-
+ drivers/hwmon/ad7418.c                     |   21 +-
+ drivers/hwmon/adcxx.c                      |    9 +-
+ drivers/hwmon/adm1029.c                    |   21 +-
+ drivers/hwmon/adm9240.c                    |   26 --
+ drivers/hwmon/ads1015.c                    |   12 +-
+ drivers/hwmon/ads7828.c                    |   15 +-
+ drivers/hwmon/ads7871.c                    |   21 +-
+ drivers/hwmon/adt7410.c                    |  464 ++++++++++++++++++++++++++++
+ drivers/hwmon/adt7411.c                    |    9 +-
+ drivers/hwmon/adt7462.c                    |   15 +-
+ drivers/hwmon/adt7470.c                    |   15 +-
+ drivers/hwmon/amc6821.c                    |   16 +-
+ drivers/hwmon/asb100.c                     |   17 +-
+ drivers/hwmon/asus_atk0110.c               |    1 -
+ drivers/hwmon/dme1737.c                    |   45 +--
+ drivers/hwmon/ds620.c                      |   16 +-
+ drivers/hwmon/emc1403.c                    |   18 +-
+ drivers/hwmon/emc2103.c                    |   10 +-
+ drivers/hwmon/f71882fg.c                   |   48 ++-
+ drivers/hwmon/f75375s.c                    |    8 +-
+ drivers/hwmon/fam15h_power.c               |   25 +-
+ drivers/hwmon/g760a.c                      |   10 +-
+ drivers/hwmon/ina2xx.c                     |  169 ++++------
+ drivers/hwmon/jz4740-hwmon.c               |   53 +---
+ drivers/hwmon/lm70.c                       |   42 ++-
+ drivers/hwmon/lm93.c                       |    2 +-
+ drivers/hwmon/lm95241.c                    |   15 +-
+ drivers/hwmon/lm95245.c                    |   15 +-
+ drivers/hwmon/ltc4151.c                    |   15 +-
+ drivers/hwmon/ltc4215.c                    |   15 +-
+ drivers/hwmon/ltc4245.c                    |   14 +-
+ drivers/hwmon/max1111.c                    |   74 ++++-
+ drivers/hwmon/max1668.c                    |    8 +-
+ drivers/hwmon/max197.c                     |  349 +++++++++++++++++++++
+ drivers/hwmon/mcp3021.c                    |   67 ++--
+ drivers/hwmon/sch5627.c                    |    5 +-
+ drivers/hwmon/sch5636.c                    |    6 +-
+ drivers/hwmon/sch56xx-common.c             |   28 +-
+ drivers/hwmon/sht15.c                      |  154 +++------
+ drivers/hwmon/sht21.c                      |   13 +-
+ drivers/hwmon/via-cputemp.c                |   23 +-
+ drivers/hwmon/vt8231.c                     |   24 +-
+ drivers/hwmon/w83791d.c                    |    7 +-
+ drivers/hwmon/w83792d.c                    |   58 +---
+ drivers/hwmon/w83793.c                     |   23 --
+ drivers/hwmon/w83l786ng.c                  |   13 +-
+ include/linux/platform_data/max197.h       |   21 ++
+ include/linux/{ => platform_data}/sht15.h  |    1 -
+ 61 files changed, 1528 insertions(+), 882 deletions(-)
+ create mode 100644 Documentation/hwmon/adt7410
+ create mode 100644 Documentation/hwmon/max197
+ create mode 100644 drivers/hwmon/adt7410.c
+ create mode 100644 drivers/hwmon/max197.c
+ create mode 100644 include/linux/platform_data/max197.h
+ rename include/linux/{ => platform_data}/sht15.h (99%)
+Merging v4l-dvb/master (0421fb6 Merge /home/v4l/v4l/patchwork)
+$ git merge v4l-dvb/master
+Removing drivers/staging/media/lirc/lirc_ttusbir.c
+Removing drivers/staging/media/lirc/lirc_ene0100.h
+Removing drivers/staging/media/easycap/easycap_testcard.c
+Removing drivers/staging/media/easycap/easycap_sound.c
+Removing drivers/staging/media/easycap/easycap_settings.c
+Removing drivers/staging/media/easycap/easycap_main.c
+Removing drivers/staging/media/easycap/easycap_low.c
+Removing drivers/staging/media/easycap/easycap_ioctl.c
+Removing drivers/staging/media/easycap/easycap.h
+Removing drivers/staging/media/easycap/README
+Removing drivers/staging/media/easycap/Makefile
+Removing drivers/staging/media/easycap/Kconfig
+Removing drivers/media/video/tlg2300/Makefile
+Removing drivers/media/video/cx23885/Kconfig
+Removing drivers/media/video/bt8xx/Makefile
+Removing drivers/media/video/bt8xx/Kconfig
+Removing drivers/media/video/Makefile
+Removing drivers/media/video/Kconfig
+Auto-merging drivers/media/v4l2-core/videobuf2-vmalloc.c
+Auto-merging drivers/media/v4l2-core/videobuf2-core.c
+Auto-merging drivers/media/v4l2-core/videobuf-dvb.c
+Auto-merging drivers/media/v4l2-core/v4l2-subdev.c
+Auto-merging drivers/media/v4l2-core/v4l2-mem2mem.c
+Auto-merging drivers/media/v4l2-core/v4l2-ioctl.c
+Auto-merging drivers/media/v4l2-core/v4l2-dev.c
+Auto-merging drivers/media/v4l2-core/v4l2-ctrls.c
+Auto-merging drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+Auto-merging drivers/media/v4l2-core/v4l2-common.c
+Auto-merging drivers/media/usb/uvc/uvcvideo.h
+Auto-merging drivers/media/usb/uvc/uvc_video.c
+Auto-merging drivers/media/usb/uvc/uvc_driver.c
+Auto-merging drivers/media/usb/usbvision/usbvision-video.c
+Auto-merging drivers/media/usb/usbvision/Makefile
+Auto-merging drivers/media/usb/usbvision/Kconfig
+Auto-merging drivers/media/usb/ttusb-dec/Makefile
+Auto-merging drivers/media/usb/ttusb-budget/Kconfig
+Auto-merging drivers/media/usb/tm6000/tm6000-video.c
+Auto-merging drivers/media/usb/tm6000/tm6000-input.c
+Auto-merging drivers/media/usb/tm6000/tm6000-alsa.c
+Auto-merging drivers/media/usb/tm6000/Makefile
+Auto-merging drivers/media/usb/tlg2300/pd-alsa.c
+Auto-merging drivers/media/usb/s2255/s2255drv.c
+Auto-merging drivers/media/usb/pwc/pwc-if.c
+Auto-merging drivers/media/usb/pwc/Makefile
+Auto-merging drivers/media/usb/pvrusb2/pvrusb2-devattr.c
+Auto-merging drivers/media/usb/pvrusb2/Makefile
+Auto-merging drivers/media/usb/pvrusb2/Kconfig
+Auto-merging drivers/media/usb/hdpvr/Makefile
+Auto-merging drivers/media/usb/gspca/zc3xx.c
+Auto-merging drivers/media/usb/gspca/xirlink_cit.c
+Auto-merging drivers/media/usb/gspca/vicam.c
+Auto-merging drivers/media/usb/gspca/vc032x.c
+Auto-merging drivers/media/usb/gspca/stv06xx/Makefile
+Auto-merging drivers/media/usb/gspca/sq930x.c
+Auto-merging drivers/media/usb/gspca/sq905c.c
+Auto-merging drivers/media/usb/gspca/sq905.c
+Auto-merging drivers/media/usb/gspca/sonixj.c
+Auto-merging drivers/media/usb/gspca/sn9c20x.c
+Auto-merging drivers/media/usb/gspca/pac7302.c
+Auto-merging drivers/media/usb/gspca/ov519.c
+Auto-merging drivers/media/usb/gspca/m5602/Makefile
+Auto-merging drivers/media/usb/gspca/jl2005bcd.c
+Auto-merging drivers/media/usb/gspca/gspca.c
+Auto-merging drivers/media/usb/gspca/gl860/Makefile
+Auto-merging drivers/media/usb/gspca/finepix.c
+Auto-merging drivers/media/usb/gspca/cpia1.c
+Auto-merging drivers/media/usb/gspca/Kconfig
+Auto-merging drivers/media/usb/em28xx/em28xx-video.c
+Auto-merging drivers/media/usb/em28xx/em28xx-core.c
+Auto-merging drivers/media/usb/em28xx/em28xx-audio.c
+Auto-merging drivers/media/usb/em28xx/Makefile
+Auto-merging drivers/media/usb/em28xx/Kconfig
+Auto-merging drivers/media/usb/dvb-usb/ttusb2.c
+Auto-merging drivers/media/usb/dvb-usb/pctv452e.c
+Auto-merging drivers/media/usb/dvb-usb/dvb-usb.h
+Auto-merging drivers/media/usb/dvb-usb/dvb-usb-dvb.c
+Auto-merging drivers/media/usb/dvb-usb/dib0700_core.c
+Auto-merging drivers/media/usb/dvb-usb-v2/rtl28xxu.h
+Auto-merging drivers/media/usb/dvb-usb-v2/rtl28xxu.c
+Auto-merging drivers/media/usb/dvb-usb-v2/mxl111sf.h
+Auto-merging drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.c
+Auto-merging drivers/media/usb/dvb-usb-v2/lmedm04.c
+Auto-merging drivers/media/usb/dvb-usb-v2/gl861.h
+Auto-merging drivers/media/usb/dvb-usb-v2/gl861.c
+Auto-merging drivers/media/usb/dvb-usb-v2/ec168.h
+Auto-merging drivers/media/usb/dvb-usb-v2/ec168.c
+Auto-merging drivers/media/usb/dvb-usb-v2/ce6230.h
+Auto-merging drivers/media/usb/dvb-usb-v2/ce6230.c
+Auto-merging drivers/media/usb/dvb-usb-v2/az6007.c
+Auto-merging drivers/media/usb/dvb-usb-v2/au6610.h
+Auto-merging drivers/media/usb/dvb-usb-v2/au6610.c
+Auto-merging drivers/media/usb/dvb-usb-v2/anysee.h
+Auto-merging drivers/media/usb/dvb-usb-v2/anysee.c
+Auto-merging drivers/media/usb/dvb-usb-v2/af9035.h
+Auto-merging drivers/media/usb/dvb-usb-v2/af9035.c
+Auto-merging drivers/media/usb/dvb-usb-v2/af9015.h
+Auto-merging drivers/media/usb/cx231xx/cx231xx-video.c
+Auto-merging drivers/media/usb/cx231xx/cx231xx-417.c
+Auto-merging drivers/media/usb/cx231xx/Makefile
+Auto-merging drivers/media/usb/cx231xx/Kconfig
+Auto-merging drivers/media/usb/cpia2/cpia2_v4l.c
+Auto-merging drivers/media/usb/cpia2/cpia2_core.c
+Auto-merging drivers/media/usb/b2c2/flexcop-usb.c
+Auto-merging drivers/media/usb/au0828/au0828.h
+Auto-merging drivers/media/usb/au0828/au0828-video.c
+Auto-merging drivers/media/usb/au0828/au0828-reg.h
+Auto-merging drivers/media/usb/au0828/au0828-i2c.c
+Auto-merging drivers/media/usb/au0828/au0828-dvb.c
+Auto-merging drivers/media/usb/au0828/au0828-core.c
+Auto-merging drivers/media/usb/au0828/au0828-cards.c
+Auto-merging drivers/media/usb/au0828/Makefile
+Auto-merging drivers/media/usb/au0828/Kconfig
+Auto-merging drivers/media/tuners/xc5000.c
+Auto-merging drivers/media/tuners/xc4000.c
+Auto-merging drivers/media/tuners/tuner-xc2028.c
+Auto-merging drivers/media/tuners/tua9001.h
+Auto-merging drivers/media/tuners/tua9001.c
+Auto-merging drivers/media/tuners/tda18271-common.c
+Auto-merging drivers/media/tuners/tda18218_priv.h
+Auto-merging drivers/media/tuners/tda18218.c
+Auto-merging drivers/media/tuners/tda18212.c
+Auto-merging drivers/media/tuners/qt1010.c
+Auto-merging drivers/media/tuners/mxl5005s.c
+Auto-merging drivers/media/tuners/mc44s803.c
+Auto-merging drivers/media/tuners/Makefile
+Auto-merging drivers/media/tuners/Kconfig
+Auto-merging drivers/media/platform/vivi.c
+Auto-merging drivers/media/platform/soc_camera/soc_camera_platform.c
+Auto-merging drivers/media/platform/soc_camera/soc_camera.c
+Auto-merging drivers/media/platform/soc_camera/omap1_camera.c
+Auto-merging drivers/media/platform/soc_camera/mx3_camera.c
+Auto-merging drivers/media/platform/soc_camera/mx2_camera.c
+Auto-merging drivers/media/platform/sh_vou.c
+Auto-merging drivers/media/platform/s5p-tv/sii9234_drv.c
+Auto-merging drivers/media/platform/s5p-tv/sdo_drv.c
+Auto-merging drivers/media/platform/s5p-tv/regs-sdo.h
+Auto-merging drivers/media/platform/s5p-tv/mixer_video.c
+Auto-merging drivers/media/platform/s5p-tv/mixer_drv.c
+Auto-merging drivers/media/platform/s5p-tv/hdmi_drv.c
+Auto-merging drivers/media/platform/s5p-tv/Makefile
+Auto-merging drivers/media/platform/s5p-tv/Kconfig
+Auto-merging drivers/media/platform/s5p-mfc/s5p_mfc_shm.h
+Auto-merging drivers/media/platform/s5p-mfc/s5p_mfc_shm.c
+Auto-merging drivers/media/platform/s5p-mfc/s5p_mfc_pm.h
+Auto-merging drivers/media/platform/s5p-mfc/s5p_mfc_pm.c
+Auto-merging drivers/media/platform/s5p-mfc/s5p_mfc_opr.h
+Auto-merging drivers/media/platform/s5p-mfc/s5p_mfc_opr.c
+Auto-merging drivers/media/platform/s5p-mfc/s5p_mfc_intr.h
+Auto-merging drivers/media/platform/s5p-mfc/s5p_mfc_intr.c
+Auto-merging drivers/media/platform/s5p-mfc/s5p_mfc_enc.h
+Auto-merging drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
+Auto-merging drivers/media/platform/s5p-mfc/s5p_mfc_dec.h
+Auto-merging drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
+Auto-merging drivers/media/platform/s5p-mfc/s5p_mfc_debug.h
+Auto-merging drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.h
+Auto-merging drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
+Auto-merging drivers/media/platform/s5p-mfc/s5p_mfc_cmd.h
+Auto-merging drivers/media/platform/s5p-mfc/s5p_mfc_cmd.c
+Auto-merging drivers/media/platform/s5p-mfc/s5p_mfc.c
+Auto-merging drivers/media/platform/s5p-jpeg/jpeg-regs.h
+Auto-merging drivers/media/platform/s5p-jpeg/jpeg-hw.h
+Auto-merging drivers/media/platform/s5p-jpeg/jpeg-core.h
+Auto-merging drivers/media/platform/s5p-jpeg/jpeg-core.c
+Auto-merging drivers/media/platform/s5p-g2d/g2d.c
+Auto-merging drivers/media/platform/s5p-fimc/fimc-reg.c
+Auto-merging drivers/media/platform/s5p-fimc/fimc-mdevice.h
+Auto-merging drivers/media/platform/s5p-fimc/fimc-mdevice.c
+Auto-merging drivers/media/platform/s5p-fimc/fimc-m2m.c
+Auto-merging drivers/media/platform/s5p-fimc/fimc-lite.h
+Auto-merging drivers/media/platform/s5p-fimc/fimc-lite.c
+Auto-merging drivers/media/platform/s5p-fimc/fimc-lite-reg.c
+Auto-merging drivers/media/platform/s5p-fimc/fimc-core.h
+Auto-merging drivers/media/platform/s5p-fimc/fimc-capture.c
+Auto-merging drivers/media/platform/s5p-fimc/Kconfig
+Auto-merging drivers/media/platform/omap3isp/ispvideo.h
+Auto-merging drivers/media/platform/omap3isp/ispvideo.c
+Auto-merging drivers/media/platform/omap3isp/ispresizer.c
+Auto-merging drivers/media/platform/omap3isp/ispqueue.c
+Auto-merging drivers/media/platform/omap3isp/isppreview.h
+Auto-merging drivers/media/platform/omap3isp/isppreview.c
+Auto-merging drivers/media/platform/omap3isp/isphist.c
+Auto-merging drivers/media/platform/omap3isp/isph3a_af.c
+Auto-merging drivers/media/platform/omap3isp/isph3a_aewb.c
+Auto-merging drivers/media/platform/omap3isp/ispcsi2.c
+Auto-merging drivers/media/platform/omap3isp/ispccdc.h
+Auto-merging drivers/media/platform/omap3isp/ispccdc.c
+Auto-merging drivers/media/platform/omap3isp/isp.h
+Auto-merging drivers/media/platform/omap3isp/isp.c
+Auto-merging drivers/media/platform/omap3isp/cfa_coef_table.h
+Auto-merging drivers/media/platform/omap24xxcam.h
+Auto-merging drivers/media/platform/omap24xxcam.c
+Auto-merging drivers/media/platform/omap24xxcam-dma.c
+Auto-merging drivers/media/platform/omap/Makefile
+Auto-merging drivers/media/platform/mx2_emmaprp.c
+Auto-merging drivers/media/platform/mem2mem_testdev.c
+Auto-merging drivers/media/platform/fsl-viu.c
+Auto-merging drivers/media/platform/davinci/vpss.c
+Auto-merging drivers/media/platform/davinci/vpif_display.c
+Auto-merging drivers/media/platform/davinci/vpif_capture.c
+Auto-merging drivers/media/platform/davinci/vpif.c
+Auto-merging drivers/media/platform/davinci/vpfe_capture.c
+Auto-merging drivers/media/platform/davinci/vpbe_display.c
+Auto-merging drivers/media/platform/davinci/isif.c
+Auto-merging drivers/media/platform/davinci/dm644x_ccdc.c
+Auto-merging drivers/media/platform/davinci/dm355_ccdc.c
+Auto-merging drivers/media/platform/davinci/Kconfig
+Auto-merging drivers/media/platform/blackfin/bfin_capture.c
+Auto-merging drivers/media/pci/zoran/Kconfig
+Auto-merging drivers/media/pci/ttpci/budget.c
+Auto-merging drivers/media/pci/ttpci/Makefile
+Auto-merging drivers/media/pci/ttpci/Kconfig
+Auto-merging drivers/media/pci/saa7164/saa7164.h
+Auto-merging drivers/media/pci/saa7164/saa7164-core.c
+Auto-merging drivers/media/pci/saa7164/saa7164-api.c
+Auto-merging drivers/media/pci/saa7164/Makefile
+Auto-merging drivers/media/pci/saa7164/Kconfig
+Auto-merging drivers/media/pci/saa7134/saa7134.h
+Auto-merging drivers/media/pci/saa7134/saa7134-input.c
+Auto-merging drivers/media/pci/saa7134/saa7134-dvb.c
+Auto-merging drivers/media/pci/saa7134/Makefile
+Auto-merging drivers/media/pci/saa7134/Kconfig
+Auto-merging drivers/media/pci/pt1/va1j5jf8007s.c
+Auto-merging drivers/media/pci/pt1/Makefile
+Auto-merging drivers/media/pci/ngene/ngene-core.c
+Auto-merging drivers/media/pci/ngene/ngene-cards.c
+Auto-merging drivers/media/pci/ngene/Makefile
+Auto-merging drivers/media/pci/mantis/mantis_dvb.c
+Auto-merging drivers/media/pci/mantis/mantis_core.c
+Auto-merging drivers/media/pci/mantis/mantis_cards.c
+Auto-merging drivers/media/pci/mantis/Makefile
+Auto-merging drivers/media/pci/mantis/Kconfig
+Auto-merging drivers/media/pci/ivtv/ivtv-streams.c
+Auto-merging drivers/media/pci/ivtv/ivtv-irq.c
+Auto-merging drivers/media/pci/ivtv/ivtv-firmware.c
+Auto-merging drivers/media/pci/ivtv/ivtv-fileops.h
+Auto-merging drivers/media/pci/ivtv/ivtv-fileops.c
+Auto-merging drivers/media/pci/ivtv/ivtv-driver.h
+Auto-merging drivers/media/pci/ivtv/ivtv-driver.c
+Auto-merging drivers/media/pci/ivtv/Makefile
+Auto-merging drivers/media/pci/ivtv/Kconfig
+Auto-merging drivers/media/pci/dm1105/Kconfig
+Auto-merging drivers/media/pci/ddbridge/ddbridge-core.c
+Auto-merging drivers/media/pci/ddbridge/Makefile
+Auto-merging drivers/media/pci/ddbridge/Kconfig
+Auto-merging drivers/media/pci/cx88/cx88.h
+Auto-merging drivers/media/pci/cx88/cx88-dvb.c
+Auto-merging drivers/media/pci/cx88/cx88-core.c
+Auto-merging drivers/media/pci/cx88/cx88-cards.c
+Auto-merging drivers/media/pci/cx88/cx88-alsa.c
+Auto-merging drivers/media/pci/cx88/Makefile
+Auto-merging drivers/media/pci/cx88/Kconfig
+Auto-merging drivers/media/pci/cx25821/Makefile
+Auto-merging drivers/media/pci/cx23885/cx23885.h
+Auto-merging drivers/media/pci/cx23885/cx23885-input.c
+Auto-merging drivers/media/pci/cx23885/cx23885-dvb.c
+Auto-merging drivers/media/pci/cx23885/cx23885-cards.c
+Auto-merging drivers/media/pci/cx23885/cx23885-417.c
+Auto-merging drivers/media/pci/cx23885/altera-ci.c
+Auto-merging drivers/media/pci/cx23885/Makefile
+Auto-merging drivers/media/pci/cx18/cx18-firmware.c
+Auto-merging drivers/media/pci/cx18/cx18-dvb.c
+Auto-merging drivers/media/pci/cx18/cx18-driver.c
+Auto-merging drivers/media/pci/cx18/cx18-av-firmware.c
+Auto-merging drivers/media/pci/cx18/Makefile
+Auto-merging drivers/media/pci/cx18/Kconfig
+Auto-merging drivers/media/pci/bt8xx/dst_ca.c
+Auto-merging drivers/media/i2c/tvp514x_regs.h
+Auto-merging drivers/media/i2c/tvp514x.c
+Auto-merging drivers/media/i2c/tea6415c.c
+Auto-merging drivers/media/i2c/tcm825x.h
+Auto-merging drivers/media/i2c/tcm825x.c
+Auto-merging drivers/media/i2c/soc_camera/tw9910.c
+Auto-merging drivers/media/i2c/soc_camera/rj54n1cb0c.c
+Auto-merging drivers/media/i2c/soc_camera/ov9740.c
+Auto-merging drivers/media/i2c/soc_camera/ov9640.c
+Auto-merging drivers/media/i2c/soc_camera/ov772x.c
+Auto-merging drivers/media/i2c/soc_camera/ov6650.c
+Auto-merging drivers/media/i2c/soc_camera/ov5642.c
+Auto-merging drivers/media/i2c/soc_camera/ov2640.c
+Auto-merging drivers/media/i2c/soc_camera/mt9v022.c
+Auto-merging drivers/media/i2c/soc_camera/mt9t112.c
+Auto-merging drivers/media/i2c/soc_camera/mt9t031.c
+Auto-merging drivers/media/i2c/soc_camera/mt9m111.c
+Auto-merging drivers/media/i2c/soc_camera/mt9m001.c
+Auto-merging drivers/media/i2c/soc_camera/imx074.c
+Auto-merging drivers/media/i2c/smiapp/smiapp.h
+Auto-merging drivers/media/i2c/smiapp/smiapp-regs.c
+Auto-merging drivers/media/i2c/smiapp/smiapp-reg.h
+Auto-merging drivers/media/i2c/smiapp/smiapp-reg-defs.h
+Auto-merging drivers/media/i2c/smiapp/smiapp-quirk.h
+Auto-merging drivers/media/i2c/smiapp/smiapp-quirk.c
+Auto-merging drivers/media/i2c/smiapp/smiapp-limits.h
+Auto-merging drivers/media/i2c/smiapp/smiapp-limits.c
+Auto-merging drivers/media/i2c/smiapp/smiapp-core.c
+Auto-merging drivers/media/i2c/smiapp/Makefile
+Auto-merging drivers/media/i2c/smiapp-pll.h
+Auto-merging drivers/media/i2c/smiapp-pll.c
+Auto-merging drivers/media/i2c/saa7127.c
+Auto-merging drivers/media/i2c/s5k6aa.c
+Auto-merging drivers/media/i2c/mt9v032.c
+Auto-merging drivers/media/i2c/mt9p031.c
+Auto-merging drivers/media/i2c/mt9m032.c
+Auto-merging drivers/media/i2c/m5mols/m5mols_core.c
+Auto-merging drivers/media/i2c/m5mols/m5mols_controls.c
+Auto-merging drivers/media/i2c/m5mols/m5mols.h
+Auto-merging drivers/media/i2c/cx25840/cx25840-firmware.c
+Auto-merging drivers/media/i2c/cx25840/Makefile
+Auto-merging drivers/media/i2c/as3645a.c
+Auto-merging drivers/media/i2c/adp1653.c
+Auto-merging drivers/media/firewire/Makefile
+Removing drivers/media/dvb/ttusb-budget/Makefile
+Removing drivers/media/dvb/siano/Kconfig
+Removing drivers/media/dvb/pluto2/Makefile
+Removing drivers/media/dvb/ngene/Kconfig
+Removing drivers/media/dvb/frontends/ec100_priv.h
+Removing drivers/media/dvb/dvb-usb/mxl111sf.c
+Removing drivers/media/dvb/dvb-usb/it913x.c
+Removing drivers/media/dvb/dvb-usb/af9015.c
+Removing drivers/media/dvb/dvb-usb/Makefile
+Removing drivers/media/dvb/dvb-usb/Kconfig
+Removing drivers/media/dvb/dm1105/Makefile
+Removing drivers/media/dvb/bt8xx/Makefile
+Removing drivers/media/dvb/bt8xx/Kconfig
+Removing drivers/media/dvb/b2c2/MakefilResolved 'arch/arm/mach-imx/mach-imx27_visstrim_m10.c' using previous resolution.
+e
+Removing drivers/media/dvb/b2c2/Kconfig
+Removing drivers/media/dvb/Makefile
+Removing drivers/media/dvb/Kconfig
+Auto-merging drivers/media/dvb-frontends/tda8261.c
+Auto-merging drivers/media/dvb-frontends/tda10071_priv.h
+Auto-merging drivers/media/dvb-frontends/tda10071.c
+Auto-merging drivers/media/dvb-frontends/stv090x.c
+Auto-merging drivers/media/dvb-frontends/stb0899_drv.c
+Auto-merging drivers/media/dvb-frontends/rtl2832_priv.h
+Auto-merging drivers/media/dvb-frontends/rtl2832.h
+Auto-merging drivers/media/dvb-frontends/rtl2832.c
+Auto-merging drivers/media/dvb-frontends/rtl2830_priv.h
+Auto-merging drivers/media/dvb-frontends/rtl2830.h
+Auto-merging drivers/media/dvb-frontends/rtl2830.c
+Auto-merging drivers/media/dvb-frontends/nxt200x.c
+Auto-merging drivers/media/dvb-frontends/m88rs2000.c
+Auto-merging drivers/media/dvb-frontends/lgs8gxx.c
+Auto-merging drivers/media/dvb-frontends/lgs8gl5.c
+Auto-merging drivers/media/dvb-frontends/it913x-fe.c
+Auto-merging drivers/media/dvb-frontends/hd29l2_priv.h
+Auto-merging drivers/media/dvb-frontends/hd29l2.h
+Auto-merging drivers/media/dvb-frontends/hd29l2.c
+Auto-merging drivers/media/dvb-frontends/ec100.h
+Auto-merging drivers/media/dvb-frontends/ec100.c
+Auto-merging drivers/media/dvb-frontends/dvb-pll.h
+Auto-merging drivers/media/dvb-frontends/dvb-pll.c
+Auto-merging drivers/media/dvb-frontends/cxd2820r_t.c
+Auto-merging drivers/media/dvb-frontends/au8522_priv.h
+Auto-merging drivers/media/dvb-frontends/au8522_dig.c
+Auto-merging drivers/media/dvb-frontends/au8522_decoder.c
+Auto-merging drivers/media/dvb-frontends/au8522_common.c
+Auto-merging drivers/media/dvb-frontends/atbm8830.c
+Auto-merging drivers/media/dvb-frontends/af9033.h
+Auto-merging drivers/media/dvb-frontends/af9033.c
+Auto-merging drivers/media/dvb-frontends/af9013_priv.h
+Auto-merging drivers/media/dvb-frontends/af9013.h
+Auto-merging drivers/media/dvb-frontends/af9013.c
+Auto-merging drivers/media/dvb-frontends/Makefile
+Auto-merging drivers/media/dvb-frontends/Kconfig
+Auto-merging drivers/media/dvb-core/dvbdev.h
+Auto-merging drivers/media/dvb-core/dvbdev.c
+Auto-merging drivers/media/dvb-core/dvb_frontend.h
+Auto-merging drivers/media/dvb-core/dvb_frontend.c
+Auto-merging drivers/media/dvb-core/dvb_demux.c
+Auto-merging drivers/media/dvb-core/dvb-usb-ids.h
+Auto-merging drivers/media/dvb-core/dmxdev.c
+Auto-merging drivers/media/common/siano/Makefile
+Auto-merging drivers/media/common/saa7146/saa7146_fops.c
+Auto-merging drivers/media/common/saa7146/saa7146_core.c
+Auto-merging drivers/media/common/b2c2/flexcop.c
+Auto-merging arch/arm/mach-imx/mach-imx27_visstrim_m10.c
+CONFLICT (content): Merge conflict in arch/arm/mach-imx/mach-imx27_visstrim_m10.c
+Auto-merging MAINTAINERS
+Auto-merging Documentation/feature-removal-schedule.txt
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master e03396b] Merge remote-tracking branch 'v4l-dvb/master'
+$ git diff -M --stat --summary HEAD^..
+ Documentation/DocBook/media/Makefile               |    2 +-
+ Documentation/DocBook/media/dvb/audio.xml          |  113 +-
+ Documentation/DocBook/media/dvb/ca.xml             |  353 ++
+ Documentation/DocBook/media/dvb/demux.xml          |  230 +-
+ Documentation/DocBook/media/dvb/dvbapi.xml         |    4 +-
+ Documentation/DocBook/media/dvb/dvbproperty.xml    |   97 +-
+ Documentation/DocBook/media/dvb/frontend.xml       |   71 +-
+ Documentation/DocBook/media/dvb/intro.xml          |    2 +-
+ Documentation/DocBook/media/dvb/kdapi.xml          |    2 +-
+ Documentation/DocBook/media/dvb/net.xml            |  127 +
+ Documentation/DocBook/media/dvb/video.xml          |  333 +-
+ Documentation/DocBook/media/v4l/biblio.xml         |   52 +-
+ Documentation/DocBook/media/v4l/compat.xml         |   16 -
+ Documentation/DocBook/media/v4l/controls.xml       |  614 +--
+ Documentation/DocBook/media/v4l/dev-rds.xml        |    2 +-
+ Documentation/DocBook/media/v4l/dev-subdev.xml     |   20 +-
+ Documentation/DocBook/media/v4l/gen-errors.xml     |   12 +-
+ .../DocBook/media/v4l/pixfmt-srggb10dpcm8.xml      |    3 +-
+ Documentation/DocBook/media/v4l/pixfmt-yvu420m.xml |  154 +
+ Documentation/DocBook/media/v4l/pixfmt.xml         |    1 +
+ Documentation/DocBook/media/v4l/selection-api.xml  |   22 +-
+ Documentation/DocBook/media/v4l/v4l2.xml           |   14 +-
+ .../DocBook/media/v4l/vidioc-g-selection.xml       |    9 +-
+ Documentation/DocBook/media/v4l/vidioc-g-tuner.xml |    6 +
+ Documentation/DocBook/media/v4l/vidioc-qbuf.xml    |    2 +
+ .../media/v4l/vidioc-subdev-g-selection.xml        |    8 +-
+ Documentation/DocBook/media_api.tmpl               |    9 +-
+ Documentation/dvb/README.dvb-usb                   |    2 +-
+ Documentation/feature-removal-schedule.txt         |    9 +
+ Documentation/ioctl/ioctl-number.txt               |    5 -
+ Documentation/video4linux/CARDLIST.cx23885         |    1 +
+ MAINTAINERS                                        |   86 +-
+ arch/arm/mach-imx/clk-imx27.c                      |    4 +-
+ arch/arm/mach-imx/devices-imx27.h                  |    4 +
+ arch/arm/mach-imx/mach-imx27_visstrim_m10.c        |   45 +-
+ arch/arm/mach-omap2/board-rx51-peripherals.c       |   30 +
+ arch/arm/plat-mxc/devices/Kconfig                  |    6 +-
+ arch/arm/plat-mxc/devices/Makefile                 |    1 +
+ arch/arm/plat-mxc/devices/platform-imx27-coda.c    |   37 +
+ arch/arm/plat-mxc/include/mach/devices-common.h    |    8 +
+ drivers/gpio/gpio-bt8xx.c                          |    2 +-
+ drivers/media/Kconfig                              |   53 +-
+ drivers/media/Makefile                             |   23 +-
+ drivers/media/common/Kconfig                       |   12 +-
+ drivers/media/common/Makefile                      |    7 +-
+ drivers/media/common/b2c2/Kconfig                  |   28 +
+ drivers/media/common/b2c2/Makefile                 |    8 +
+ .../media/{dvb => common}/b2c2/flexcop-common.h    |    0
+ .../media/{dvb => common}/b2c2/flexcop-eeprom.c    |    0
+ .../media/{dvb => common}/b2c2/flexcop-fe-tuner.c  |    0
+ .../media/{dvb => common}/b2c2/flexcop-hw-filter.c |    0
+ drivers/media/{dvb => common}/b2c2/flexcop-i2c.c   |    0
+ drivers/media/{dvb => common}/b2c2/flexcop-misc.c  |    0
+ drivers/media/{dvb => common}/b2c2/flexcop-reg.h   |    0
+ drivers/media/{dvb => common}/b2c2/flexcop-sram.c  |    0
+ drivers/media/{dvb => common}/b2c2/flexcop.c       |    1 +
+ drivers/media/{dvb => common}/b2c2/flexcop.h       |    0
+ .../{dvb => common}/b2c2/flexcop_ibi_value_be.h    |    0
+ .../{dvb => common}/b2c2/flexcop_ibi_value_le.h    |    0
+ drivers/media/common/saa7146/Kconfig               |    9 +
+ drivers/media/common/saa7146/Makefile              |    5 +
+ drivers/media/common/{ => saa7146}/saa7146_core.c  |    8 -
+ drivers/media/common/{ => saa7146}/saa7146_fops.c  |   55 +-
+ drivers/media/common/{ => saa7146}/saa7146_hlp.c   |    0
+ drivers/media/common/{ => saa7146}/saa7146_i2c.c   |    0
+ drivers/media/common/{ => saa7146}/saa7146_vbi.c   |    0
+ drivers/media/common/{ => saa7146}/saa7146_video.c |    0
+ drivers/media/common/siano/Kconfig                 |   17 +
+ drivers/media/{dvb => common}/siano/Makefile       |    6 +-
+ drivers/media/{dvb => common}/siano/sms-cards.c    |    0
+ drivers/media/{dvb => common}/siano/sms-cards.h    |    0
+ drivers/media/{dvb => common}/siano/smscoreapi.c   |    0
+ drivers/media/{dvb => common}/siano/smscoreapi.h   |    0
+ drivers/media/{dvb => common}/siano/smsdvb.c       |    0
+ drivers/media/{dvb => common}/siano/smsendian.c    |    0
+ drivers/media/{dvb => common}/siano/smsendian.h    |    0
+ drivers/media/{dvb => common}/siano/smsir.c        |    0
+ drivers/media/{dvb => common}/siano/smsir.h        |    0
+ drivers/media/dvb-core/Kconfig                     |   29 +
+ drivers/media/{dvb => }/dvb-core/Makefile          |    0
+ drivers/media/{dvb => }/dvb-core/demux.h           |    0
+ drivers/media/{dvb => }/dvb-core/dmxdev.c          |    4 +-
+ drivers/media/{dvb => }/dvb-core/dmxdev.h          |    0
+ .../media/{dvb/dvb-usb => dvb-core}/dvb-usb-ids.h  |    2 +
+ drivers/media/{dvb => }/dvb-core/dvb_ca_en50221.c  |    0
+ drivers/media/{dvb => }/dvb-core/dvb_ca_en50221.h  |    0
+ drivers/media/{dvb => }/dvb-core/dvb_demux.c       |   29 +-
+ drivers/media/{dvb => }/dvb-core/dvb_demux.h       |    0
+ drivers/media/{dvb => }/dvb-core/dvb_filter.c      |    0
+ drivers/media/{dvb => }/dvb-core/dvb_filter.h      |    0
+ drivers/media/{dvb => }/dvb-core/dvb_frontend.c    |  329 +-
+ drivers/media/{dvb => }/dvb-core/dvb_frontend.h    |   11 +-
+ drivers/media/{dvb => }/dvb-core/dvb_math.c        |    0
+ drivers/media/{dvb => }/dvb-core/dvb_math.h        |    0
+ drivers/media/{dvb => }/dvb-core/dvb_net.c         |    0
+ drivers/media/{dvb => }/dvb-core/dvb_net.h         |    0
+ drivers/media/{dvb => }/dvb-core/dvb_ringbuffer.c  |    0
+ drivers/media/{dvb => }/dvb-core/dvb_ringbuffer.h  |    0
+ drivers/media/{dvb => }/dvb-core/dvbdev.c          |    2 +-
+ drivers/media/{dvb => }/dvb-core/dvbdev.h          |   26 -
+ .../media/{dvb/frontends => dvb-frontends}/Kconfig |  195 +-
+ .../{dvb/frontends => dvb-frontends}/Makefile      |   12 +-
+ .../media/{dvb/frontends => dvb-frontends}/a8293.c |    0
+ .../media/{dvb/frontends => dvb-frontends}/a8293.h |    0
+ .../{dvb/frontends => dvb-frontends}/af9013.c      |  158 +-
+ .../{dvb/frontends => dvb-frontends}/af9013.h      |    2 +-
+ .../{dvb/frontends => dvb-frontends}/af9013_priv.h |   15 +-
+ .../{dvb/frontends => dvb-frontends}/af9033.c      |   83 +-
+ .../{dvb/frontends => dvb-frontends}/af9033.h      |    2 +-
+ .../{dvb/frontends => dvb-frontends}/af9033_priv.h |    0
+ .../{dvb/frontends => dvb-frontends}/atbm8830.c    |    2 +-
+ .../{dvb/frontends => dvb-frontends}/atbm8830.h    |    0
+ .../frontends => dvb-frontends}/atbm8830_priv.h    |    0
+ .../{dvb/frontends => dvb-frontends}/au8522.h      |    0
+ .../frontends => dvb-frontends}/au8522_common.c    |   22 +-
+ .../frontends => dvb-frontends}/au8522_decoder.c   |   11 +-
+ .../{dvb/frontends => dvb-frontends}/au8522_dig.c  |   98 +-
+ .../{dvb/frontends => dvb-frontends}/au8522_priv.h |   29 +-
+ .../{dvb/frontends => dvb-frontends}/bcm3510.c     |    0
+ .../{dvb/frontends => dvb-frontends}/bcm3510.h     |    0
+ .../frontends => dvb-frontends}/bcm3510_priv.h     |    0
+ .../{dvb/frontends => dvb-frontends}/bsbe1-d01a.h  |    0
+ .../media/{dvb/frontends => dvb-frontends}/bsbe1.h |    0
+ .../media/{dvb/frontends => dvb-frontends}/bsru6.h |    0
+ .../{dvb/frontends => dvb-frontends}/cx22700.c     |    0
+ .../{dvb/frontends => dvb-frontends}/cx22700.h     |    0
+ .../{dvb/frontends => dvb-frontends}/cx22702.c     |    0
+ .../{dvb/frontends => dvb-frontends}/cx22702.h     |    0
+ .../{dvb/frontends => dvb-frontends}/cx24110.c     |    0
+ .../{dvb/frontends => dvb-frontends}/cx24110.h     |    0
+ .../{dvb/frontends => dvb-frontends}/cx24113.c     |    0
+ .../{dvb/frontends => dvb-frontends}/cx24113.h     |    0
+ .../{dvb/frontends => dvb-frontends}/cx24116.c     |    0
+ .../{dvb/frontends => dvb-frontends}/cx24116.h     |    0
+ .../{dvb/frontends => dvb-frontends}/cx24123.c     |    0
+ .../{dvb/frontends => dvb-frontends}/cx24123.h     |    0
+ .../{dvb/frontends => dvb-frontends}/cxd2820r.h    |    0
+ .../{dvb/frontends => dvb-frontends}/cxd2820r_c.c  |    0
+ .../frontends => dvb-frontends}/cxd2820r_core.c    |    0
+ .../frontends => dvb-frontends}/cxd2820r_priv.h    |    0
+ .../{dvb/frontends => dvb-frontends}/cxd2820r_t.c  |    3 +-
+ .../{dvb/frontends => dvb-frontends}/cxd2820r_t2.c |    0
+ .../{dvb/frontends => dvb-frontends}/dib0070.c     |    0
+ .../{dvb/frontends => dvb-frontends}/dib0070.h     |    0
+ .../{dvb/frontends => dvb-frontends}/dib0090.c     |    0
+ .../{dvb/frontends => dvb-frontends}/dib0090.h     |    0
+ .../{dvb/frontends => dvb-frontends}/dib3000.h     |    0
+ .../{dvb/frontends => dvb-frontends}/dib3000mb.c   |    0
+ .../frontends => dvb-frontends}/dib3000mb_priv.h   |    0
+ .../{dvb/frontends => dvb-frontends}/dib3000mc.c   |    0
+ .../{dvb/frontends => dvb-frontends}/dib3000mc.h   |    0
+ .../{dvb/frontends => dvb-frontends}/dib7000m.c    |    0
+ .../{dvb/frontends => dvb-frontends}/dib7000m.h    |    0
+ .../{dvb/frontends => dvb-frontends}/dib7000p.c    |    0
+ .../{dvb/frontends => dvb-frontends}/dib7000p.h    |    0
+ .../{dvb/frontends => dvb-frontends}/dib8000.c     |    0
+ .../{dvb/frontends => dvb-frontends}/dib8000.h     |    0
+ .../{dvb/frontends => dvb-frontends}/dib9000.c     |    0
+ .../{dvb/frontends => dvb-frontends}/dib9000.h     |    0
+ .../frontends => dvb-frontends}/dibx000_common.c   |    0
+ .../frontends => dvb-frontends}/dibx000_common.h   |    0
+ .../media/{dvb/frontends => dvb-frontends}/drxd.h  |    0
+ .../{dvb/frontends => dvb-frontends}/drxd_firm.c   |    0
+ .../{dvb/frontends => dvb-frontends}/drxd_firm.h   |    0
+ .../{dvb/frontends => dvb-frontends}/drxd_hard.c   |    0
+ .../frontends => dvb-frontends}/drxd_map_firm.h    |    0
+ .../media/{dvb/frontends => dvb-frontends}/drxk.h  |    0
+ .../{dvb/frontends => dvb-frontends}/drxk_hard.c   |    0
+ .../{dvb/frontends => dvb-frontends}/drxk_hard.h   |    0
+ .../{dvb/frontends => dvb-frontends}/drxk_map.h    |    0
+ .../{dvb/frontends => dvb-frontends}/ds3000.c      |    0
+ .../{dvb/frontends => dvb-frontends}/ds3000.h      |    0
+ .../{dvb/frontends => dvb-frontends}/dvb-pll.c     |   26 +
+ .../{dvb/frontends => dvb-frontends}/dvb-pll.h     |    1 +
+ .../frontends => dvb-frontends}/dvb_dummy_fe.c     |    0
+ .../frontends => dvb-frontends}/dvb_dummy_fe.h     |    0
+ .../media/{dvb/frontends => dvb-frontends}/ec100.c |   60 +-
+ .../media/{dvb/frontends => dvb-frontends}/ec100.h |    2 +-
+ .../{dvb/frontends => dvb-frontends}/eds1547.h     |    0
+ .../{dvb/frontends => dvb-frontends}/hd29l2.c      |   75 +-
+ .../{dvb/frontends => dvb-frontends}/hd29l2.h      |    2 +-
+ .../{dvb/frontends => dvb-frontends}/hd29l2_priv.h |   13 -
+ .../{dvb/frontends => dvb-frontends}/isl6405.c     |    0
+ .../{dvb/frontends => dvb-frontends}/isl6405.h     |    0
+ .../{dvb/frontends => dvb-frontends}/isl6421.c     |    0
+ .../{dvb/frontends => dvb-frontends}/isl6421.h     |    0
+ .../{dvb/frontends => dvb-frontends}/isl6423.c     |    0
+ .../{dvb/frontends => dvb-frontends}/isl6423.h     |    0
+ .../frontends => dvb-frontends}/it913x-fe-priv.h   |    0
+ .../{dvb/frontends => dvb-frontends}/it913x-fe.c   |    2 +-
+ .../{dvb/frontends => dvb-frontends}/it913x-fe.h   |    0
+ .../{dvb/frontends => dvb-frontends}/itd1000.c     |    0
+ .../{dvb/frontends => dvb-frontends}/itd1000.h     |    0
+ .../frontends => dvb-frontends}/itd1000_priv.h     |    0
+ .../{dvb/frontends => dvb-frontends}/ix2505v.c     |    0
+ .../{dvb/frontends => dvb-frontends}/ix2505v.h     |    0
+ .../{dvb/frontends => dvb-frontends}/l64781.c      |    0
+ .../{dvb/frontends => dvb-frontends}/l64781.h      |    0
+ .../{dvb/frontends => dvb-frontends}/lg2160.c      |    0
+ .../{dvb/frontends => dvb-frontends}/lg2160.h      |    0
+ .../{dvb/frontends => dvb-frontends}/lgdt3305.c    |    0
+ .../{dvb/frontends => dvb-frontends}/lgdt3305.h    |    0
+ .../{dvb/frontends => dvb-frontends}/lgdt330x.c    |    0
+ .../{dvb/frontends => dvb-frontends}/lgdt330x.h    |    0
+ .../frontends => dvb-frontends}/lgdt330x_priv.h    |    0
+ .../{dvb/frontends => dvb-frontends}/lgs8gl5.c     |    2 +-
+ .../{dvb/frontends => dvb-frontends}/lgs8gl5.h     |    0
+ .../{dvb/frontends => dvb-frontends}/lgs8gxx.c     |    2 +-
+ .../{dvb/frontends => dvb-frontends}/lgs8gxx.h     |    0
+ .../frontends => dvb-frontends}/lgs8gxx_priv.h     |    0
+ .../{dvb/frontends => dvb-frontends}/lnbh24.h      |    0
+ .../{dvb/frontends => dvb-frontends}/lnbp21.c      |    0
+ .../{dvb/frontends => dvb-frontends}/lnbp21.h      |    0
+ .../{dvb/frontends => dvb-frontends}/lnbp22.c      |    0
+ .../{dvb/frontends => dvb-frontends}/lnbp22.h      |    0
+ .../{dvb/frontends => dvb-frontends}/m88rs2000.c   |    2 +-
+ .../{dvb/frontends => dvb-frontends}/m88rs2000.h   |    0
+ .../{dvb/frontends => dvb-frontends}/mb86a16.c     |    0
+ .../{dvb/frontends => dvb-frontends}/mb86a16.h     |    0
+ .../frontends => dvb-frontends}/mb86a16_priv.h     |    0
+ .../{dvb/frontends => dvb-frontends}/mb86a20s.c    |    0
+ .../{dvb/frontends => dvb-frontends}/mb86a20s.h    |    0
+ .../media/{dvb/frontends => dvb-frontends}/mt312.c |    0
+ .../media/{dvb/frontends => dvb-frontends}/mt312.h |    0
+ .../{dvb/frontends => dvb-frontends}/mt312_priv.h  |    0
+ .../media/{dvb/frontends => dvb-frontends}/mt352.c |    0
+ .../media/{dvb/frontends => dvb-frontends}/mt352.h |    0
+ .../{dvb/frontends => dvb-frontends}/mt352_priv.h  |    0
+ .../{dvb/frontends => dvb-frontends}/nxt200x.c     |   64 +-
+ .../{dvb/frontends => dvb-frontends}/nxt200x.h     |    0
+ .../{dvb/frontends => dvb-frontends}/nxt6000.c     |    0
+ .../{dvb/frontends => dvb-frontends}/nxt6000.h     |    0
+ .../frontends => dvb-frontends}/nxt6000_priv.h     |    0
+ .../{dvb/frontends => dvb-frontends}/or51132.c     |    0
+ .../{dvb/frontends => dvb-frontends}/or51132.h     |    0
+ .../{dvb/frontends => dvb-frontends}/or51211.c     |    0
+ .../{dvb/frontends => dvb-frontends}/or51211.h     |    0
+ .../{dvb/frontends => dvb-frontends}/rtl2830.c     |  124 +-
+ .../{dvb/frontends => dvb-frontends}/rtl2830.h     |    9 +-
+ .../frontends => dvb-frontends}/rtl2830_priv.h     |   13 -
+ .../{dvb/frontends => dvb-frontends}/rtl2832.c     |  297 +-
+ .../{dvb/frontends => dvb-frontends}/rtl2832.h     |   12 +-
+ .../frontends => dvb-frontends}/rtl2832_priv.h     |   75 +-
+ .../{dvb/frontends => dvb-frontends}/s5h1409.c     |    0
+ .../{dvb/frontends => dvb-frontends}/s5h1409.h     |    0
+ .../{dvb/frontends => dvb-frontends}/s5h1411.c     |    0
+ .../{dvb/frontends => dvb-frontends}/s5h1411.h     |    0
+ .../{dvb/frontends => dvb-frontends}/s5h1420.c     |    0
+ .../{dvb/frontends => dvb-frontends}/s5h1420.h     |    0
+ .../frontends => dvb-frontends}/s5h1420_priv.h     |    0
+ .../{dvb/frontends => dvb-frontends}/s5h1432.c     |    0
+ .../{dvb/frontends => dvb-frontends}/s5h1432.h     |    0
+ .../media/{dvb/frontends => dvb-frontends}/s921.c  |    0
+ .../media/{dvb/frontends => dvb-frontends}/s921.h  |    0
+ .../{dvb/frontends => dvb-frontends}/si21xx.c      |    0
+ .../{dvb/frontends => dvb-frontends}/si21xx.h      |    0
+ .../{dvb/frontends => dvb-frontends}/sp8870.c      |    0
+ .../{dvb/frontends => dvb-frontends}/sp8870.h      |    0
+ .../{dvb/frontends => dvb-frontends}/sp887x.c      |    0
+ .../{dvb/frontends => dvb-frontends}/sp887x.h      |    0
+ .../frontends => dvb-frontends}/stb0899_algo.c     |    0
+ .../{dvb/frontends => dvb-frontends}/stb0899_cfg.h |    0
+ .../{dvb/frontends => dvb-frontends}/stb0899_drv.c |    1 +
+ .../{dvb/frontends => dvb-frontends}/stb0899_drv.h |    0
+ .../frontends => dvb-frontends}/stb0899_priv.h     |    0
+ .../{dvb/frontends => dvb-frontends}/stb0899_reg.h |    0
+ .../{dvb/frontends => dvb-frontends}/stb6000.c     |    0
+ .../{dvb/frontends => dvb-frontends}/stb6000.h     |    0
+ .../{dvb/frontends => dvb-frontends}/stb6100.c     |    0
+ .../{dvb/frontends => dvb-frontends}/stb6100.h     |    0
+ .../{dvb/frontends => dvb-frontends}/stb6100_cfg.h |    0
+ .../frontends => dvb-frontends}/stb6100_proc.h     |    0
+ .../{dvb/frontends => dvb-frontends}/stv0288.c     |    0
+ .../{dvb/frontends => dvb-frontends}/stv0288.h     |    0
+ .../{dvb/frontends => dvb-frontends}/stv0297.c     |    0
+ .../{dvb/frontends => dvb-frontends}/stv0297.h     |    0
+ .../{dvb/frontends => dvb-frontends}/stv0299.c     |    0
+ .../{dvb/frontends => dvb-frontends}/stv0299.h     |    0
+ .../{dvb/frontends => dvb-frontends}/stv0367.c     |    0
+ .../{dvb/frontends => dvb-frontends}/stv0367.h     |    0
+ .../frontends => dvb-frontends}/stv0367_priv.h     |    0
+ .../frontends => dvb-frontends}/stv0367_regs.h     |    0
+ .../{dvb/frontends => dvb-frontends}/stv0900.h     |    0
+ .../frontends => dvb-frontends}/stv0900_core.c     |    0
+ .../frontends => dvb-frontends}/stv0900_init.h     |    0
+ .../frontends => dvb-frontends}/stv0900_priv.h     |    0
+ .../{dvb/frontends => dvb-frontends}/stv0900_reg.h |    0
+ .../{dvb/frontends => dvb-frontends}/stv0900_sw.c  |    0
+ .../{dvb/frontends => dvb-frontends}/stv090x.c     |   32 +
+ .../{dvb/frontends => dvb-frontends}/stv090x.h     |    0
+ .../frontends => dvb-frontends}/stv090x_priv.h     |    0
+ .../{dvb/frontends => dvb-frontends}/stv090x_reg.h |    0
+ .../{dvb/frontends => dvb-frontends}/stv6110.c     |    0
+ .../{dvb/frontends => dvb-frontends}/stv6110.h     |    0
+ .../{dvb/frontends => dvb-frontends}/stv6110x.c    |    0
+ .../{dvb/frontends => dvb-frontends}/stv6110x.h    |    0
+ .../frontends => dvb-frontends}/stv6110x_priv.h    |    0
+ .../frontends => dvb-frontends}/stv6110x_reg.h     |    0
+ .../{dvb/frontends => dvb-frontends}/tda10021.c    |    0
+ .../{dvb/frontends => dvb-frontends}/tda10023.c    |    0
+ .../{dvb/frontends => dvb-frontends}/tda1002x.h    |    0
+ .../{dvb/frontends => dvb-frontends}/tda10048.c    |    0
+ .../{dvb/frontends => dvb-frontends}/tda10048.h    |    0
+ .../{dvb/frontends => dvb-frontends}/tda1004x.c    |    0
+ .../{dvb/frontends => dvb-frontends}/tda1004x.h    |    0
+ .../{dvb/frontends => dvb-frontends}/tda10071.c    |    7 +-
+ .../{dvb/frontends => dvb-frontends}/tda10071.h    |    0
+ .../frontends => dvb-frontends}/tda10071_priv.h    |    2 +-
+ .../{dvb/frontends => dvb-frontends}/tda10086.c    |    0
+ .../{dvb/frontends => dvb-frontends}/tda10086.h    |    0
+ .../frontends => dvb-frontends}/tda18271c2dd.c     |    0
+ .../frontends => dvb-frontends}/tda18271c2dd.h     |    0
+ .../tda18271c2dd_maps.h                            |    0
+ .../{dvb/frontends => dvb-frontends}/tda665x.c     |    0
+ .../{dvb/frontends => dvb-frontends}/tda665x.h     |    0
+ .../{dvb/frontends => dvb-frontends}/tda8083.c     |    0
+ .../{dvb/frontends => dvb-frontends}/tda8083.h     |    0
+ .../{dvb/frontends => dvb-frontends}/tda8261.c     |   28 +-
+ .../{dvb/frontends => dvb-frontends}/tda8261.h     |    0
+ .../{dvb/frontends => dvb-frontends}/tda8261_cfg.h |    0
+ .../{dvb/frontends => dvb-frontends}/tda826x.c     |    0
+ .../{dvb/frontends => dvb-frontends}/tda826x.h     |    0
+ .../media/{dvb/frontends => dvb-frontends}/tdhd1.h |    0
+ .../{dvb/frontends => dvb-frontends}/tua6100.c     |    0
+ .../{dvb/frontends => dvb-frontends}/tua6100.h     |    0
+ .../{dvb/frontends => dvb-frontends}/ves1820.c     |    0
+ .../{dvb/frontends => dvb-frontends}/ves1820.h     |    0
+ .../{dvb/frontends => dvb-frontends}/ves1x93.c     |    0
+ .../{dvb/frontends => dvb-frontends}/ves1x93.h     |    0
+ .../{dvb/frontends => dvb-frontends}/z0194a.h      |    0
+ .../{dvb/frontends => dvb-frontends}/zl10036.c     |    0
+ .../{dvb/frontends => dvb-frontends}/zl10036.h     |    0
+ .../{dvb/frontends => dvb-frontends}/zl10039.c     |    0
+ .../{dvb/frontends => dvb-frontends}/zl10039.h     |    0
+ .../{dvb/frontends => dvb-frontends}/zl10353.c     |    0
+ .../{dvb/frontends => dvb-frontends}/zl10353.h     |    0
+ .../frontends => dvb-frontends}/zl10353_priv.h     |    0
+ drivers/media/dvb/Kconfig                          |   91 -
+ drivers/media/dvb/Makefile                         |   21 -
+ drivers/media/dvb/b2c2/Kconfig                     |   45 -
+ drivers/media/dvb/b2c2/Makefile                    |   16 -
+ drivers/media/dvb/bt8xx/Kconfig                    |   22 -
+ drivers/media/dvb/bt8xx/Makefile                   |    6 -
+ drivers/media/dvb/dm1105/Makefile                  |    3 -
+ drivers/media/dvb/dvb-usb/Kconfig                  |  440 --
+ drivers/media/dvb/dvb-usb/Makefile                 |  121 -
+ drivers/media/dvb/dvb-usb/af9015.c                 | 1952 ---------
+ drivers/media/dvb/dvb-usb/it913x.c                 |  931 -----
+ drivers/media/dvb/dvb-usb/mxl111sf.c               | 1835 ---------
+ drivers/media/dvb/frontends/ec100_priv.h           |   39 -
+ drivers/media/dvb/ngene/Kconfig                    |   13 -
+ drivers/media/dvb/pluto2/Makefile                  |    3 -
+ drivers/media/dvb/siano/Kconfig                    |   34 -
+ drivers/media/dvb/ttusb-budget/Makefile            |    3 -
+ drivers/media/{dvb => }/firewire/Kconfig           |    0
+ drivers/media/{dvb => }/firewire/Makefile          |    4 +-
+ drivers/media/{dvb => }/firewire/firedtv-avc.c     |    0
+ drivers/media/{dvb => }/firewire/firedtv-ci.c      |    0
+ drivers/media/{dvb => }/firewire/firedtv-dvb.c     |    0
+ drivers/media/{dvb => }/firewire/firedtv-fe.c      |    0
+ drivers/media/{dvb => }/firewire/firedtv-fw.c      |    0
+ drivers/media/{dvb => }/firewire/firedtv-rc.c      |    0
+ drivers/media/{dvb => }/firewire/firedtv.h         |    0
+ drivers/media/i2c/Kconfig                          |  584 +++
+ drivers/media/i2c/Makefile                         |   66 +
+ drivers/media/i2c/ad9389b.c                        | 1328 ++++++
+ drivers/media/{video => i2c}/adp1653.c             |    2 +-
+ drivers/media/{video => i2c}/adv7170.c             |    0
+ drivers/media/{video => i2c}/adv7175.c             |    0
+ drivers/media/{video => i2c}/adv7180.c             |    0
+ drivers/media/{video => i2c}/adv7183.c             |    0
+ drivers/media/{video => i2c}/adv7183_regs.h        |    0
+ drivers/media/{video => i2c}/adv7343.c             |    0
+ drivers/media/{video => i2c}/adv7343_regs.h        |    0
+ drivers/media/{video => i2c}/adv7393.c             |    0
+ drivers/media/{video => i2c}/adv7393_regs.h        |    0
+ drivers/media/i2c/adv7604.c                        | 1959 +++++++++
+ drivers/media/{video => i2c}/ak881x.c              |    0
+ drivers/media/{video => i2c}/aptina-pll.c          |    0
+ drivers/media/{video => i2c}/aptina-pll.h          |    0
+ drivers/media/{video => i2c}/as3645a.c             |    2 +-
+ drivers/media/{video => i2c}/bt819.c               |    0
+ drivers/media/{video => i2c}/bt856.c               |    0
+ drivers/media/{video => i2c}/bt866.c               |    0
+ drivers/media/{video => i2c}/btcx-risc.c           |    0
+ drivers/media/{video => i2c}/btcx-risc.h           |    0
+ drivers/media/{video => i2c}/cs5345.c              |    0
+ drivers/media/{video => i2c}/cs53l32a.c            |    0
+ drivers/media/{video => i2c}/cx2341x.c             |    0
+ drivers/media/{video => i2c}/cx25840/Kconfig       |    0
+ drivers/media/{video => i2c}/cx25840/Makefile      |    2 +-
+ .../media/{video => i2c}/cx25840/cx25840-audio.c   |    0
+ .../media/{video => i2c}/cx25840/cx25840-core.c    |    0
+ .../media/{video => i2c}/cx25840/cx25840-core.h    |    0
+ .../{video => i2c}/cx25840/cx25840-firmware.c      |   15 +-
+ drivers/media/{video => i2c}/cx25840/cx25840-ir.c  |    0
+ drivers/media/{video => i2c}/cx25840/cx25840-vbi.c |    0
+ drivers/media/{video => i2c}/ir-kbd-i2c.c          |    0
+ drivers/media/{video => i2c}/ks0127.c              |    0
+ drivers/media/{video => i2c}/ks0127.h              |    0
+ drivers/media/{video => i2c}/m52790.c              |    0
+ drivers/media/{video => i2c}/m5mols/Kconfig        |    0
+ drivers/media/{video => i2c}/m5mols/Makefile       |    0
+ drivers/media/{video => i2c}/m5mols/m5mols.h       |    4 +-
+ .../media/{video => i2c}/m5mols/m5mols_capture.c   |    0
+ .../media/{video => i2c}/m5mols/m5mols_controls.c  |    4 +-
+ drivers/media/{video => i2c}/m5mols/m5mols_core.c  |    6 +-
+ drivers/media/{video => i2c}/m5mols/m5mols_reg.h   |    0
+ drivers/media/{video => i2c}/msp3400-driver.c      |    0
+ drivers/media/{video => i2c}/msp3400-driver.h      |    0
+ drivers/media/{video => i2c}/msp3400-kthreads.c    |    0
+ drivers/media/{video => i2c}/mt9m032.c             |    2 +-
+ drivers/media/{video => i2c}/mt9p031.c             |   12 +-
+ drivers/media/{video => i2c}/mt9t001.c             |    0
+ drivers/media/{video => i2c}/mt9v011.c             |    0
+ drivers/media/{video => i2c}/mt9v032.c             |  100 +-
+ drivers/media/{video => i2c}/noon010pc30.c         |    0
+ drivers/media/{video => i2c}/ov7670.c              |    0
+ drivers/media/{video => i2c}/s5k6aa.c              |    9 +-
+ drivers/media/{video => i2c}/saa6588.c             |    0
+ drivers/media/{video => i2c}/saa7110.c             |    0
+ drivers/media/{video => i2c}/saa7115.c             |    0
+ drivers/media/{video => i2c}/saa711x_regs.h        |    0
+ drivers/media/{video => i2c}/saa7127.c             |    5 +-
+ drivers/media/{video => i2c}/saa717x.c             |    0
+ drivers/media/{video => i2c}/saa7185.c             |    0
+ drivers/media/{video => i2c}/saa7191.c             |    0
+ drivers/media/{video => i2c}/saa7191.h             |    0
+ drivers/media/{video => i2c}/smiapp-pll.c          |    2 +-
+ drivers/media/{video => i2c}/smiapp-pll.h          |    2 +-
+ drivers/media/{video => i2c}/smiapp/Kconfig        |    0
+ drivers/media/{video => i2c}/smiapp/Makefile       |    2 +-
+ drivers/media/{video => i2c}/smiapp/smiapp-core.c  |    2 +-
+ .../media/{video => i2c}/smiapp/smiapp-limits.c    |    2 +-
+ .../media/{video => i2c}/smiapp/smiapp-limits.h    |    2 +-
+ drivers/media/{video => i2c}/smiapp/smiapp-quirk.c |    2 +-
+ drivers/media/{video => i2c}/smiapp/smiapp-quirk.h |    2 +-
+ .../media/{video => i2c}/smiapp/smiapp-reg-defs.h  |    2 +-
+ drivers/media/{video => i2c}/smiapp/smiapp-reg.h   |    2 +-
+ drivers/media/{video => i2c}/smiapp/smiapp-regs.c  |    2 +-
+ drivers/media/{video => i2c}/smiapp/smiapp-regs.h  |    0
+ drivers/media/{video => i2c}/smiapp/smiapp.h       |    2 +-
+ drivers/media/i2c/soc_camera/Kconfig               |   89 +
+ drivers/media/i2c/soc_camera/Makefile              |   14 +
+ drivers/media/{video => i2c/soc_camera}/imx074.c   |   30 +-
+ drivers/media/{video => i2c/soc_camera}/mt9m001.c  |   26 +-
+ drivers/media/{video => i2c/soc_camera}/mt9m111.c  |  116 +-
+ drivers/media/{video => i2c/soc_camera}/mt9t031.c  |   48 +-
+ drivers/media/{video => i2c/soc_camera}/mt9t112.c  |   21 +-
+ drivers/media/{video => i2c/soc_camera}/mt9v022.c  |   50 +-
+ drivers/media/{video => i2c/soc_camera}/ov2640.c   |   20 +-
+ drivers/media/{video => i2c/soc_camera}/ov5642.c   |   31 +-
+ drivers/media/{video => i2c/soc_camera}/ov6650.c   |   28 +-
+ drivers/media/{video => i2c/soc_camera}/ov772x.c   |  447 ++-
+ drivers/media/{video => i2c/soc_camera}/ov9640.c   |   27 +-
+ drivers/media/{video => i2c/soc_camera}/ov9640.h   |    0
+ drivers/media/{video => i2c/soc_camera}/ov9740.c   |   47 +-
+ .../media/{video => i2c/soc_camera}/rj54n1cb0c.c   |   27 +-
+ drivers/media/{video => i2c/soc_camera}/tw9910.c   |   21 +-
+ drivers/media/{video => i2c}/sr030pc30.c           |    0
+ drivers/media/{video => i2c}/tcm825x.c             |    2 +-
+ drivers/media/{video => i2c}/tcm825x.h             |    2 +-
+ drivers/media/{video => i2c}/tda7432.c             |    0
+ drivers/media/{video => i2c}/tda9840.c             |    0
+ drivers/media/{video => i2c}/tea6415c.c            |    4 +-
+ drivers/media/{video => i2c}/tea6415c.h            |    0
+ drivers/media/{video => i2c}/tea6420.c             |    0
+ drivers/media/{video => i2c}/tea6420.h             |    0
+ drivers/media/{video => i2c}/ths7303.c             |    0
+ drivers/media/{video => i2c}/tlv320aic23b.c        |    0
+ drivers/media/{video => i2c}/tvaudio.c             |    0
+ drivers/media/{video => i2c}/tveeprom.c            |    0
+ drivers/media/{video => i2c}/tvp514x.c             |    2 +-
+ drivers/media/{video => i2c}/tvp514x_regs.h        |    2 +-
+ drivers/media/{video => i2c}/tvp5150.c             |    0
+ drivers/media/{video => i2c}/tvp5150_reg.h         |    0
+ drivers/media/{video => i2c}/tvp7002.c             |    0
+ drivers/media/{video => i2c}/tvp7002_reg.h         |    0
+ drivers/media/{video => i2c}/upd64031a.c           |    0
+ drivers/media/{video => i2c}/upd64083.c            |    0
+ drivers/media/{video => i2c}/vp27smpx.c            |    0
+ drivers/media/{video => i2c}/vpx3220.c             |    0
+ drivers/media/{video => i2c}/vs6624.c              |    0
+ drivers/media/{video => i2c}/vs6624_regs.h         |    0
+ drivers/media/{video => i2c}/wm8739.c              |    0
+ drivers/media/{video => i2c}/wm8775.c              |    0
+ drivers/media/media-device.c                       |    4 +-
+ drivers/media/mmc/Kconfig                          |    2 +
+ drivers/media/mmc/Makefile                         |    1 +
+ drivers/media/mmc/siano/Kconfig                    |   10 +
+ drivers/media/mmc/siano/Makefile                   |    6 +
+ drivers/media/{dvb => mmc}/siano/smssdio.c         |    0
+ drivers/media/parport/Kconfig                      |   52 +
+ drivers/media/parport/Makefile                     |    4 +
+ drivers/media/{video => parport}/bw-qcam.c         |    0
+ drivers/media/{video => parport}/c-qcam.c          |    0
+ drivers/media/{video => parport}/pms.c             |    0
+ drivers/media/{video => parport}/w9966.c           |    0
+ drivers/media/pci/Kconfig                          |   47 +
+ drivers/media/pci/Makefile                         |   26 +
+ drivers/media/pci/b2c2/Kconfig                     |   15 +
+ drivers/media/pci/b2c2/Makefile                    |    9 +
+ drivers/media/{dvb => pci}/b2c2/flexcop-dma.c      |    0
+ drivers/media/{dvb => pci}/b2c2/flexcop-pci.c      |    0
+ drivers/media/pci/bt8xx/Kconfig                    |   43 +
+ drivers/media/pci/bt8xx/Makefile                   |   11 +
+ drivers/media/{video => pci}/bt8xx/bt848.h         |    0
+ drivers/media/{dvb => pci}/bt8xx/bt878.c           |    0
+ drivers/media/{dvb => pci}/bt8xx/bt878.h           |    0
+ .../media/{video => pci}/bt8xx/bttv-audio-hook.c   |    0
+ .../media/{video => pci}/bt8xx/bttv-audio-hook.h   |    0
+ drivers/media/{video => pci}/bt8xx/bttv-cards.c    |    0
+ drivers/media/{video => pci}/bt8xx/bttv-driver.c   |    0
+ drivers/media/{video => pci}/bt8xx/bttv-gpio.c     |    0
+ drivers/media/{video => pci}/bt8xx/bttv-i2c.c      |    0
+ drivers/media/{video => pci}/bt8xx/bttv-if.c       |    0
+ drivers/media/{video => pci}/bt8xx/bttv-input.c    |    0
+ drivers/media/{video => pci}/bt8xx/bttv-risc.c     |    0
+ drivers/media/{video => pci}/bt8xx/bttv-vbi.c      |    0
+ drivers/media/{video => pci}/bt8xx/bttv.h          |    0
+ drivers/media/{video => pci}/bt8xx/bttvp.h         |    0
+ drivers/media/{dvb => pci}/bt8xx/dst.c             |    0
+ drivers/media/{dvb => pci}/bt8xx/dst_ca.c          |    3 +-
+ drivers/media/{dvb => pci}/bt8xx/dst_ca.h          |    0
+ drivers/media/{dvb => pci}/bt8xx/dst_common.h      |    0
+ drivers/media/{dvb => pci}/bt8xx/dst_priv.h        |    0
+ drivers/media/{dvb => pci}/bt8xx/dvb-bt8xx.c       |    0
+ drivers/media/{dvb => pci}/bt8xx/dvb-bt8xx.h       |    0
+ drivers/media/{video => pci}/cx18/Kconfig          |   10 +-
+ drivers/media/{video => pci}/cx18/Makefile         |    6 +-
+ drivers/media/{video => pci}/cx18/cx18-alsa-main.c |    0
+ .../media/{video => pci}/cx18/cx18-alsa-mixer.c    |    0
+ .../media/{video => pci}/cx18/cx18-alsa-mixer.h    |    0
+ drivers/media/{video => pci}/cx18/cx18-alsa-pcm.c  |    0
+ drivers/media/{video => pci}/cx18/cx18-alsa-pcm.h  |    0
+ drivers/media/{video => pci}/cx18/cx18-alsa.h      |    0
+ drivers/media/{video => pci}/cx18/cx18-audio.c     |    0
+ drivers/media/{video => pci}/cx18/cx18-audio.h     |    0
+ drivers/media/{video => pci}/cx18/cx18-av-audio.c  |    0
+ drivers/media/{video => pci}/cx18/cx18-av-core.c   |    0
+ drivers/media/{video => pci}/cx18/cx18-av-core.h   |    0
+ .../media/{video => pci}/cx18/cx18-av-firmware.c   |    2 +
+ drivers/media/{video => pci}/cx18/cx18-av-vbi.c    |    0
+ drivers/media/{video => pci}/cx18/cx18-cards.c     |    0
+ drivers/media/{video => pci}/cx18/cx18-cards.h     |    0
+ drivers/media/{video => pci}/cx18/cx18-controls.c  |    0
+ drivers/media/{video => pci}/cx18/cx18-controls.h  |    0
+ drivers/media/{video => pci}/cx18/cx18-driver.c    |    1 +
+ drivers/media/{video => pci}/cx18/cx18-driver.h    |    0
+ drivers/media/{video => pci}/cx18/cx18-dvb.c       |    6 +-
+ drivers/media/{video => pci}/cx18/cx18-dvb.h       |    0
+ drivers/media/{video => pci}/cx18/cx18-fileops.c   |    0
+ drivers/media/{video => pci}/cx18/cx18-fileops.h   |    0
+ drivers/media/{video => pci}/cx18/cx18-firmware.c  |   10 +-
+ drivers/media/{video => pci}/cx18/cx18-firmware.h  |    0
+ drivers/media/{video => pci}/cx18/cx18-gpio.c      |    0
+ drivers/media/{video => pci}/cx18/cx18-gpio.h      |    0
+ drivers/media/{video => pci}/cx18/cx18-i2c.c       |    0
+ drivers/media/{video => pci}/cx18/cx18-i2c.h       |    0
+ drivers/media/{video => pci}/cx18/cx18-io.c        |    0
+ drivers/media/{video => pci}/cx18/cx18-io.h        |    0
+ drivers/media/{video => pci}/cx18/cx18-ioctl.c     |    0
+ drivers/media/{video => pci}/cx18/cx18-ioctl.h     |    0
+ drivers/media/{video => pci}/cx18/cx18-irq.c       |    0
+ drivers/media/{video => pci}/cx18/cx18-irq.h       |    0
+ drivers/media/{video => pci}/cx18/cx18-mailbox.c   |    0
+ drivers/media/{video => pci}/cx18/cx18-mailbox.h   |    0
+ drivers/media/{video => pci}/cx18/cx18-queue.c     |    0
+ drivers/media/{video => pci}/cx18/cx18-queue.h     |    0
+ drivers/media/{video => pci}/cx18/cx18-scb.c       |    0
+ drivers/media/{video => pci}/cx18/cx18-scb.h       |    0
+ drivers/media/{video => pci}/cx18/cx18-streams.c   |    0
+ drivers/media/{video => pci}/cx18/cx18-streams.h   |    0
+ drivers/media/{video => pci}/cx18/cx18-vbi.c       |    0
+ drivers/media/{video => pci}/cx18/cx18-vbi.h       |    0
+ drivers/media/{video => pci}/cx18/cx18-version.h   |    0
+ drivers/media/{video => pci}/cx18/cx18-video.c     |    0
+ drivers/media/{video => pci}/cx18/cx18-video.h     |    0
+ drivers/media/{video => pci}/cx18/cx23418.h        |    0
+ drivers/media/pci/cx23885/Kconfig                  |   48 +
+ drivers/media/{video => pci}/cx23885/Makefile      |    8 +-
+ drivers/media/{video => pci}/cx23885/altera-ci.c   |    4 +-
+ drivers/media/{video => pci}/cx23885/altera-ci.h   |    0
+ drivers/media/{video => pci}/cx23885/cimax2.c      |    0
+ drivers/media/{video => pci}/cx23885/cimax2.h      |    0
+ drivers/media/{video => pci}/cx23885/cx23885-417.c |    2 +
+ .../media/{video => pci}/cx23885/cx23885-alsa.c    |    0
+ drivers/media/{video => pci}/cx23885/cx23885-av.c  |    0
+ drivers/media/{video => pci}/cx23885/cx23885-av.h  |    0
+ .../media/{video => pci}/cx23885/cx23885-cards.c   |   16 +-
+ .../media/{video => pci}/cx23885/cx23885-core.c    |    0
+ drivers/media/{video => pci}/cx23885/cx23885-dvb.c |   59 +-
+ .../media/{video => pci}/cx23885/cx23885-f300.c    |    0
+ .../media/{video => pci}/cx23885/cx23885-f300.h    |    0
+ drivers/media/{video => pci}/cx23885/cx23885-i2c.c |    0
+ .../media/{video => pci}/cx23885/cx23885-input.c   |    9 +
+ .../media/{video => pci}/cx23885/cx23885-input.h   |    0
+ .../media/{video => pci}/cx23885/cx23885-ioctl.c   |    0
+ .../media/{video => pci}/cx23885/cx23885-ioctl.h   |    0
+ drivers/media/{video => pci}/cx23885/cx23885-ir.c  |    0
+ drivers/media/{video => pci}/cx23885/cx23885-ir.h  |    0
+ drivers/media/{video => pci}/cx23885/cx23885-reg.h |    0
+ drivers/media/{video => pci}/cx23885/cx23885-vbi.c |    0
+ .../media/{video => pci}/cx23885/cx23885-video.c   |    0
+ drivers/media/{video => pci}/cx23885/cx23885.h     |    1 +
+ drivers/media/{video => pci}/cx23885/cx23888-ir.c  |    0
+ drivers/media/{video => pci}/cx23885/cx23888-ir.h  |    0
+ .../media/{video => pci}/cx23885/netup-eeprom.c    |    0
+ .../media/{video => pci}/cx23885/netup-eeprom.h    |    0
+ drivers/media/{video => pci}/cx23885/netup-init.c  |    0
+ drivers/media/{video => pci}/cx23885/netup-init.h  |    0
+ drivers/media/{video => pci}/cx25821/Kconfig       |    0
+ drivers/media/{video => pci}/cx25821/Makefile      |    8 +-
+ .../media/{video => pci}/cx25821/cx25821-alsa.c    |    0
+ .../cx25821/cx25821-audio-upstream.c               |    0
+ .../cx25821/cx25821-audio-upstream.h               |    0
+ .../media/{video => pci}/cx25821/cx25821-audio.h   |    0
+ .../{video => pci}/cx25821/cx25821-biffuncs.h      |    0
+ .../media/{video => pci}/cx25821/cx25821-cards.c   |    0
+ .../media/{video => pci}/cx25821/cx25821-core.c    |    0
+ .../media/{video => pci}/cx25821/cx25821-gpio.c    |    0
+ drivers/media/{video => pci}/cx25821/cx25821-i2c.c |    0
+ .../cx25821/cx25821-medusa-defines.h               |    0
+ .../{video => pci}/cx25821/cx25821-medusa-reg.h    |    0
+ .../{video => pci}/cx25821/cx25821-medusa-video.c  |    0
+ .../{video => pci}/cx25821/cx25821-medusa-video.h  |    0
+ drivers/media/{video => pci}/cx25821/cx25821-reg.h |    0
+ .../media/{video => pci}/cx25821/cx25821-sram.h    |    0
+ .../cx25821/cx25821-video-upstream-ch2.c           |    0
+ .../cx25821/cx25821-video-upstream-ch2.h           |    0
+ .../cx25821/cx25821-video-upstream.c               |    0
+ .../cx25821/cx25821-video-upstream.h               |    0
+ .../media/{video => pci}/cx25821/cx25821-video.c   |    0
+ .../media/{video => pci}/cx25821/cx25821-video.h   |    0
+ drivers/media/{video => pci}/cx25821/cx25821.h     |    0
+ drivers/media/{video => pci}/cx88/Kconfig          |   36 +-
+ drivers/media/{video => pci}/cx88/Makefile         |    8 +-
+ drivers/media/{video => pci}/cx88/cx88-alsa.c      |    2 +-
+ drivers/media/{video => pci}/cx88/cx88-blackbird.c |    0
+ drivers/media/{video => pci}/cx88/cx88-cards.c     |    4 +-
+ drivers/media/{video => pci}/cx88/cx88-core.c      |    2 +-
+ drivers/media/{video => pci}/cx88/cx88-dsp.c       |    0
+ drivers/media/{video => pci}/cx88/cx88-dvb.c       |    2 +-
+ drivers/media/{video => pci}/cx88/cx88-i2c.c       |    0
+ drivers/media/{video => pci}/cx88/cx88-input.c     |    0
+ drivers/media/{video => pci}/cx88/cx88-mpeg.c      |    0
+ drivers/media/{video => pci}/cx88/cx88-reg.h       |    0
+ drivers/media/{video => pci}/cx88/cx88-tvaudio.c   |    0
+ drivers/media/{video => pci}/cx88/cx88-vbi.c       |    0
+ drivers/media/{video => pci}/cx88/cx88-video.c     |    0
+ .../media/{video => pci}/cx88/cx88-vp3054-i2c.c    |    0
+ .../media/{video => pci}/cx88/cx88-vp3054-i2c.h    |    0
+ drivers/media/{video => pci}/cx88/cx88.h           |    2 +-
+ drivers/media/{dvb => pci}/ddbridge/Kconfig        |   10 +-
+ drivers/media/{dvb => pci}/ddbridge/Makefile       |    6 +-
+ .../media/{dvb => pci}/ddbridge/ddbridge-core.c    |   15 +-
+ .../media/{dvb => pci}/ddbridge/ddbridge-regs.h    |    0
+ drivers/media/{dvb => pci}/ddbridge/ddbridge.h     |    0
+ drivers/media/{dvb => pci}/dm1105/Kconfig          |   14 +-
+ drivers/media/pci/dm1105/Makefile                  |    3 +
+ drivers/media/{dvb => pci}/dm1105/dm1105.c         |    0
+ drivers/media/{video => pci}/ivtv/Kconfig          |   16 +
+ drivers/media/{video => pci}/ivtv/Makefile         |   10 +-
+ drivers/media/pci/ivtv/ivtv-alsa-main.c            |  303 ++
+ drivers/media/pci/ivtv/ivtv-alsa-mixer.c           |  175 +
+ drivers/media/pci/ivtv/ivtv-alsa-mixer.h           |   23 +
+ drivers/media/pci/ivtv/ivtv-alsa-pcm.c             |  357 ++
+ drivers/media/pci/ivtv/ivtv-alsa-pcm.h             |   27 +
+ drivers/media/pci/ivtv/ivtv-alsa.h                 |   75 +
+ drivers/media/{video => pci}/ivtv/ivtv-cards.c     |    0
+ drivers/media/{video => pci}/ivtv/ivtv-cards.h     |    0
+ drivers/media/{video => pci}/ivtv/ivtv-controls.c  |    0
+ drivers/media/{video => pci}/ivtv/ivtv-controls.h  |    0
+ drivers/media/{video => pci}/ivtv/ivtv-driver.c    |   37 +
+ drivers/media/{video => pci}/ivtv/ivtv-driver.h    |   11 +
+ drivers/media/{video => pci}/ivtv/ivtv-fileops.c   |   56 +-
+ drivers/media/{video => pci}/ivtv/ivtv-fileops.h   |    4 +-
+ drivers/media/{video => pci}/ivtv/ivtv-firmware.c  |    4 +
+ drivers/media/{video => pci}/ivtv/ivtv-firmware.h  |    0
+ drivers/media/{video => pci}/ivtv/ivtv-gpio.c      |    0
+ drivers/media/{video => pci}/ivtv/ivtv-gpio.h      |    0
+ drivers/media/{video => pci}/ivtv/ivtv-i2c.c       |    0
+ drivers/media/{video => pci}/ivtv/ivtv-i2c.h       |    0
+ drivers/media/{video => pci}/ivtv/ivtv-ioctl.c     |    0
+ drivers/media/{video => pci}/ivtv/ivtv-ioctl.h     |    0
+ drivers/media/{video => pci}/ivtv/ivtv-irq.c       |   50 +
+ drivers/media/{video => pci}/ivtv/ivtv-irq.h       |    0
+ drivers/media/{video => pci}/ivtv/ivtv-mailbox.c   |    0
+ drivers/media/{video => pci}/ivtv/ivtv-mailbox.h   |    0
+ drivers/media/{video => pci}/ivtv/ivtv-queue.c     |    0
+ drivers/media/{video => pci}/ivtv/ivtv-queue.h     |    0
+ drivers/media/{video => pci}/ivtv/ivtv-routing.c   |    0
+ drivers/media/{video => pci}/ivtv/ivtv-routing.h   |    0
+ drivers/media/{video => pci}/ivtv/ivtv-streams.c   |    6 +-
+ drivers/media/{video => pci}/ivtv/ivtv-streams.h   |    0
+ drivers/media/{video => pci}/ivtv/ivtv-udma.c      |    0
+ drivers/media/{video => pci}/ivtv/ivtv-udma.h      |    0
+ drivers/media/{video => pci}/ivtv/ivtv-vbi.c       |    0
+ drivers/media/{video => pci}/ivtv/ivtv-vbi.h       |    0
+ drivers/media/{video => pci}/ivtv/ivtv-version.h   |    0
+ drivers/media/{video => pci}/ivtv/ivtv-yuv.c       |    0
+ drivers/media/{video => pci}/ivtv/ivtv-yuv.h       |    0
+ drivers/media/{video => pci}/ivtv/ivtvfb.c         |    0
+ drivers/media/{dvb => pci}/mantis/Kconfig          |   20 +-
+ drivers/media/{dvb => pci}/mantis/Makefile         |    2 +-
+ drivers/media/{dvb => pci}/mantis/hopper_cards.c   |    0
+ drivers/media/{dvb => pci}/mantis/hopper_vp3028.c  |    0
+ drivers/media/{dvb => pci}/mantis/hopper_vp3028.h  |    0
+ drivers/media/{dvb => pci}/mantis/mantis_ca.c      |    0
+ drivers/media/{dvb => pci}/mantis/mantis_ca.h      |    0
+ drivers/media/{dvb => pci}/mantis/mantis_cards.c   |    2 +-
+ drivers/media/{dvb => pci}/mantis/mantis_common.h  |    0
+ drivers/media/{dvb => pci}/mantis/mantis_core.c    |    2 +-
+ drivers/media/{dvb => pci}/mantis/mantis_core.h    |    0
+ drivers/media/{dvb => pci}/mantis/mantis_dma.c     |    0
+ drivers/media/{dvb => pci}/mantis/mantis_dma.h     |    0
+ drivers/media/{dvb => pci}/mantis/mantis_dvb.c     |    6 +-
+ drivers/media/{dvb => pci}/mantis/mantis_dvb.h     |    0
+ drivers/media/{dvb => pci}/mantis/mantis_evm.c     |    0
+ drivers/media/{dvb => pci}/mantis/mantis_hif.c     |    0
+ drivers/media/{dvb => pci}/mantis/mantis_hif.h     |    0
+ drivers/media/{dvb => pci}/mantis/mantis_i2c.c     |    0
+ drivers/media/{dvb => pci}/mantis/mantis_i2c.h     |    0
+ drivers/media/{dvb => pci}/mantis/mantis_input.c   |    0
+ drivers/media/{dvb => pci}/mantis/mantis_ioc.c     |    0
+ drivers/media/{dvb => pci}/mantis/mantis_ioc.h     |    0
+ drivers/media/{dvb => pci}/mantis/mantis_link.h    |    0
+ drivers/media/{dvb => pci}/mantis/mantis_pci.c     |    0
+ drivers/media/{dvb => pci}/mantis/mantis_pci.h     |    0
+ drivers/media/{dvb => pci}/mantis/mantis_pcmcia.c  |    0
+ drivers/media/{dvb => pci}/mantis/mantis_reg.h     |    0
+ drivers/media/{dvb => pci}/mantis/mantis_uart.c    |    0
+ drivers/media/{dvb => pci}/mantis/mantis_uart.h    |    0
+ drivers/media/{dvb => pci}/mantis/mantis_vp1033.c  |    0
+ drivers/media/{dvb => pci}/mantis/mantis_vp1033.h  |    0
+ drivers/media/{dvb => pci}/mantis/mantis_vp1034.c  |    0
+ drivers/media/{dvb => pci}/mantis/mantis_vp1034.h  |    0
+ drivers/media/{dvb => pci}/mantis/mantis_vp1041.c  |    0
+ drivers/media/{dvb => pci}/mantis/mantis_vp1041.h  |    0
+ drivers/media/{dvb => pci}/mantis/mantis_vp2033.c  |    0
+ drivers/media/{dvb => pci}/mantis/mantis_vp2033.h  |    0
+ drivers/media/{dvb => pci}/mantis/mantis_vp2040.c  |    0
+ drivers/media/{dvb => pci}/mantis/mantis_vp2040.h  |    0
+ drivers/media/{dvb => pci}/mantis/mantis_vp3028.c  |    0
+ drivers/media/{dvb => pci}/mantis/mantis_vp3028.h  |    0
+ drivers/media/{dvb => pci}/mantis/mantis_vp3030.c  |    0
+ drivers/media/{dvb => pci}/mantis/mantis_vp3030.h  |    0
+ drivers/media/pci/meye/Kconfig                     |   13 +
+ drivers/media/pci/meye/Makefile                    |    1 +
+ drivers/media/{video => pci/meye}/meye.c           |    0
+ drivers/media/{video => pci/meye}/meye.h           |    0
+ drivers/media/pci/ngene/Kconfig                    |   13 +
+ drivers/media/{dvb => pci}/ngene/Makefile          |    6 +-
+ drivers/media/{dvb => pci}/ngene/ngene-cards.c     |  263 ++
+ drivers/media/{dvb => pci}/ngene/ngene-core.c      |   14 +-
+ drivers/media/{dvb => pci}/ngene/ngene-dvb.c       |    0
+ drivers/media/{dvb => pci}/ngene/ngene-i2c.c       |    0
+ drivers/media/{dvb => pci}/ngene/ngene.h           |    0
+ drivers/media/{dvb => pci}/pluto2/Kconfig          |    0
+ drivers/media/pci/pluto2/Makefile                  |    3 +
+ drivers/media/{dvb => pci}/pluto2/pluto2.c         |    0
+ drivers/media/{dvb => pci}/pt1/Kconfig             |    0
+ drivers/media/{dvb => pci}/pt1/Makefile            |    2 +-
+ drivers/media/{dvb => pci}/pt1/pt1.c               |    0
+ drivers/media/{dvb => pci}/pt1/va1j5jf8007s.c      |   11 +-
+ drivers/media/{dvb => pci}/pt1/va1j5jf8007s.h      |    0
+ drivers/media/{dvb => pci}/pt1/va1j5jf8007t.c      |    0
+ drivers/media/{dvb => pci}/pt1/va1j5jf8007t.h      |    0
+ drivers/media/{video => pci}/saa7134/Kconfig       |   40 +-
+ drivers/media/{video => pci}/saa7134/Makefile      |   10 +-
+ drivers/media/{video => pci}/saa7134/saa6752hs.c   |    0
+ .../media/{video => pci}/saa7134/saa7134-alsa.c    |    0
+ .../media/{video => pci}/saa7134/saa7134-cards.c   |    0
+ .../media/{video => pci}/saa7134/saa7134-core.c    |    0
+ drivers/media/{video => pci}/saa7134/saa7134-dvb.c |    4 +-
+ .../media/{video => pci}/saa7134/saa7134-empress.c |    0
+ drivers/media/{video => pci}/saa7134/saa7134-i2c.c |    0
+ .../media/{video => pci}/saa7134/saa7134-input.c   |   10 +-
+ drivers/media/{video => pci}/saa7134/saa7134-reg.h |    0
+ drivers/media/{video => pci}/saa7134/saa7134-ts.c  |    0
+ .../media/{video => pci}/saa7134/saa7134-tvaudio.c |    0
+ drivers/media/{video => pci}/saa7134/saa7134-vbi.c |    0
+ .../media/{video => pci}/saa7134/saa7134-video.c   |    0
+ drivers/media/{video => pci}/saa7134/saa7134.h     |    1 -
+ drivers/media/pci/saa7146/Kconfig                  |   38 +
+ drivers/media/pci/saa7146/Makefile                 |    5 +
+ .../media/{video => pci/saa7146}/hexium_gemini.c   |    0
+ .../media/{video => pci/saa7146}/hexium_orion.c    |    0
+ drivers/media/{video => pci/saa7146}/mxb.c         |    0
+ drivers/media/{video => pci}/saa7164/Kconfig       |    8 +-
+ drivers/media/{video => pci}/saa7164/Makefile      |    8 +-
+ drivers/media/{video => pci}/saa7164/saa7164-api.c |   15 +-
+ .../media/{video => pci}/saa7164/saa7164-buffer.c  |    0
+ drivers/media/{video => pci}/saa7164/saa7164-bus.c |    0
+ .../media/{video => pci}/saa7164/saa7164-cards.c   |    0
+ drivers/media/{video => pci}/saa7164/saa7164-cmd.c |    0
+ .../media/{video => pci}/saa7164/saa7164-core.c    |   46 +-
+ drivers/media/{video => pci}/saa7164/saa7164-dvb.c |    0
+ .../media/{video => pci}/saa7164/saa7164-encoder.c |    0
+ drivers/media/{video => pci}/saa7164/saa7164-fw.c  |    0
+ drivers/media/{video => pci}/saa7164/saa7164-i2c.c |    0
+ drivers/media/{video => pci}/saa7164/saa7164-reg.h |    0
+ .../media/{video => pci}/saa7164/saa7164-types.h   |    0
+ drivers/media/{video => pci}/saa7164/saa7164-vbi.c |    0
+ drivers/media/{video => pci}/saa7164/saa7164.h     |    1 -
+ drivers/media/pci/sta2x11/Kconfig                  |   12 +
+ drivers/media/pci/sta2x11/Makefile                 |    1 +
+ drivers/media/{video => pci/sta2x11}/sta2x11_vip.c |    0
+ drivers/media/{video => pci/sta2x11}/sta2x11_vip.h |    0
+ drivers/media/{dvb => pci}/ttpci/Kconfig           |   84 +-
+ drivers/media/{dvb => pci}/ttpci/Makefile          |    4 +-
+ drivers/media/{dvb => pci}/ttpci/av7110.c          |    0
+ drivers/media/{dvb => pci}/ttpci/av7110.h          |    0
+ drivers/media/{dvb => pci}/ttpci/av7110_av.c       |    0
+ drivers/media/{dvb => pci}/ttpci/av7110_av.h       |    0
+ drivers/media/{dvb => pci}/ttpci/av7110_ca.c       |    0
+ drivers/media/{dvb => pci}/ttpci/av7110_ca.h       |    0
+ drivers/media/{dvb => pci}/ttpci/av7110_hw.c       |    0
+ drivers/media/{dvb => pci}/ttpci/av7110_hw.h       |    0
+ drivers/media/{dvb => pci}/ttpci/av7110_ipack.c    |    0
+ drivers/media/{dvb => pci}/ttpci/av7110_ipack.h    |    0
+ drivers/media/{dvb => pci}/ttpci/av7110_ir.c       |    0
+ drivers/media/{dvb => pci}/ttpci/av7110_v4l.c      |    0
+ drivers/media/{dvb => pci}/ttpci/budget-av.c       |    0
+ drivers/media/{dvb => pci}/ttpci/budget-ci.c       |    0
+ drivers/media/{dvb => pci}/ttpci/budget-core.c     |    0
+ drivers/media/{dvb => pci}/ttpci/budget-patch.c    |    0
+ drivers/media/{dvb => pci}/ttpci/budget.c          |   60 +
+ drivers/media/{dvb => pci}/ttpci/budget.h          |    0
+ drivers/media/{dvb => pci}/ttpci/ttpci-eeprom.c    |    0
+ drivers/media/{dvb => pci}/ttpci/ttpci-eeprom.h    |    0
+ drivers/media/{video => pci}/zoran/Kconfig         |   26 +-
+ drivers/media/{video => pci}/zoran/Makefile        |    0
+ drivers/media/{video => pci}/zoran/videocodec.c    |    0
+ drivers/media/{video => pci}/zoran/videocodec.h    |    0
+ drivers/media/{video => pci}/zoran/zoran.h         |    0
+ drivers/media/{video => pci}/zoran/zoran_card.c    |    0
+ drivers/media/{video => pci}/zoran/zoran_card.h    |    0
+ drivers/media/{video => pci}/zoran/zoran_device.c  |    0
+ drivers/media/{video => pci}/zoran/zoran_device.h  |    0
+ drivers/media/{video => pci}/zoran/zoran_driver.c  |    0
+ drivers/media/{video => pci}/zoran/zoran_procfs.c  |    0
+ drivers/media/{video => pci}/zoran/zoran_procfs.h  |    0
+ drivers/media/{video => pci}/zoran/zr36016.c       |    0
+ drivers/media/{video => pci}/zoran/zr36016.h       |    0
+ drivers/media/{video => pci}/zoran/zr36050.c       |    0
+ drivers/media/{video => pci}/zoran/zr36050.h       |    0
+ drivers/media/{video => pci}/zoran/zr36057.h       |    0
+ drivers/media/{video => pci}/zoran/zr36060.c       |    0
+ drivers/media/{video => pci}/zoran/zr36060.h       |    0
+ drivers/media/platform/Kconfig                     |  222 +
+ drivers/media/platform/Makefile                    |   50 +
+ drivers/media/{video => platform}/arv.c            |    0
+ drivers/media/{video => platform}/blackfin/Kconfig |    0
+ .../media/{video => platform}/blackfin/Makefile    |    0
+ .../{video => platform}/blackfin/bfin_capture.c    |   18 +-
+ drivers/media/{video => platform}/blackfin/ppi.c   |    0
+ drivers/media/platform/coda.c                      | 1847 +++++++++
+ drivers/media/platform/coda.h                      |  216 +
+ drivers/media/{video => platform}/davinci/Kconfig  |    4 +-
+ drivers/media/{video => platform}/davinci/Makefile |    0
+ .../{video => platform}/davinci/ccdc_hw_device.h   |    0
+ .../media/{video => platform}/davinci/dm355_ccdc.c |    2 +-
+ .../{video => platform}/davinci/dm355_ccdc_regs.h  |    0
+ .../{video => platform}/davinci/dm644x_ccdc.c      |    2 +-
+ .../{video => platform}/davinci/dm644x_ccdc_regs.h |    0
+ drivers/media/{video => platform}/davinci/isif.c   |    2 +-
+ .../media/{video => platform}/davinci/isif_regs.h  |    0
+ drivers/media/{video => platform}/davinci/vpbe.c   |    0
+ .../{video => platform}/davinci/vpbe_display.c     |   22 +-
+ .../media/{video => platform}/davinci/vpbe_osd.c   |    0
+ .../{video => platform}/davinci/vpbe_osd_regs.h    |    0
+ .../media/{video => platform}/davinci/vpbe_venc.c  |    0
+ .../{video => platform}/davinci/vpbe_venc_regs.h   |    0
+ .../{video => platform}/davinci/vpfe_capture.c     |   17 +-
+ drivers/media/{video => platform}/davinci/vpif.c   |    2 +-
+ drivers/media/{video => platform}/davinci/vpif.h   |    0
+ .../{video => platform}/davinci/vpif_capture.c     |   28 +-
+ .../{video => platform}/davinci/vpif_capture.h     |    0
+ .../{video => platform}/davinci/vpif_display.c     |   34 +-
+ .../{video => platform}/davinci/vpif_display.h     |    0
+ drivers/media/{video => platform}/davinci/vpss.c   |    2 +-
+ drivers/media/platform/exynos-gsc/Makefile         |    3 +
+ drivers/media/platform/exynos-gsc/gsc-core.c       | 1253 ++++++
+ drivers/media/platform/exynos-gsc/gsc-core.h       |  527 +++
+ drivers/media/platform/exynos-gsc/gsc-m2m.c        |  771 ++++
+ drivers/media/platform/exynos-gsc/gsc-regs.c       |  425 ++
+ drivers/media/platform/exynos-gsc/gsc-regs.h       |  172 +
+ drivers/media/{video => platform}/fsl-viu.c        |   27 +-
+ drivers/media/{video => platform}/indycam.c        |    0
+ drivers/media/{video => platform}/indycam.h        |    0
+ drivers/media/platform/m2m-deinterlace.c           | 1118 ++++++
+ .../media/{video => platform}/marvell-ccic/Kconfig |    0
+ .../{video => platform}/marvell-ccic/Makefile      |    0
+ .../{video => platform}/marvell-ccic/cafe-driver.c |    0
+ .../{video => platform}/marvell-ccic/mcam-core.c   |    0
+ .../{video => platform}/marvell-ccic/mcam-core.h   |    0
+ .../{video => platform}/marvell-ccic/mmp-driver.c  |    0
+ .../media/{video => platform}/mem2mem_testdev.c    |   40 +-
+ drivers/media/{video => platform}/mx2_emmaprp.c    |   77 +-
+ drivers/media/{video => platform}/omap/Kconfig     |    0
+ drivers/media/{video => platform}/omap/Makefile    |    2 +-
+ drivers/media/{video => platform}/omap/omap_vout.c |    0
+ .../{video => platform}/omap/omap_vout_vrfb.c      |    0
+ .../{video => platform}/omap/omap_vout_vrfb.h      |    0
+ .../media/{video => platform}/omap/omap_voutdef.h  |    0
+ .../media/{video => platform}/omap/omap_voutlib.c  |    0
+ .../media/{video => platform}/omap/omap_voutlib.h  |    0
+ .../media/{video => platform}/omap24xxcam-dma.c    |    2 +-
+ drivers/media/{video => platform}/omap24xxcam.c    |    2 +-
+ drivers/media/{video => platform}/omap24xxcam.h    |    2 +-
+ .../media/{video => platform}/omap3isp/Makefile    |    0
+ .../{video => platform}/omap3isp/cfa_coef_table.h  |   16 +-
+ .../{video => platform}/omap3isp/gamma_table.h     |    0
+ drivers/media/{video => platform}/omap3isp/isp.c   |   51 +-
+ drivers/media/{video => platform}/omap3isp/isp.h   |   11 +-
+ .../media/{video => platform}/omap3isp/ispccdc.c   |  234 +-
+ .../media/{video => platform}/omap3isp/ispccdc.h   |   37 -
+ .../media/{video => platform}/omap3isp/ispccp2.c   |    0
+ .../media/{video => platform}/omap3isp/ispccp2.h   |    0
+ .../media/{video => platform}/omap3isp/ispcsi2.c   |   27 +-
+ .../media/{video => platform}/omap3isp/ispcsi2.h   |    0
+ .../media/{video => platform}/omap3isp/ispcsiphy.c |    0
+ .../media/{video => platform}/omap3isp/ispcsiphy.h |    0
+ .../media/{video => platform}/omap3isp/isph3a.h    |    0
+ .../{video => platform}/omap3isp/isph3a_aewb.c     |   10 +-
+ .../media/{video => platform}/omap3isp/isph3a_af.c |   10 +-
+ .../media/{video => platform}/omap3isp/isphist.c   |    6 +-
+ .../media/{video => platform}/omap3isp/isphist.h   |    0
+ .../{video => platform}/omap3isp/isppreview.c      |  707 ++--
+ .../{video => platform}/omap3isp/isppreview.h      |    1 +
+ .../media/{video => platform}/omap3isp/ispqueue.c  |   15 +-
+ .../media/{video => platform}/omap3isp/ispqueue.h  |    0
+ .../media/{video => platform}/omap3isp/ispreg.h    |    0
+ .../{video => platform}/omap3isp/ispresizer.c      |    8 +-
+ .../{video => platform}/omap3isp/ispresizer.h      |    0
+ .../media/{video => platform}/omap3isp/ispstat.c   |    0
+ .../media/{video => platform}/omap3isp/ispstat.h   |    0
+ .../media/{video => platform}/omap3isp/ispvideo.c  |   57 +-
+ .../media/{video => platform}/omap3isp/ispvideo.h  |    6 +-
+ .../omap3isp/luma_enhance_table.h                  |    0
+ .../omap3isp/noise_filter_table.h                  |    0
+ drivers/media/{video => platform}/s5p-fimc/Kconfig |    2 +-
+ .../media/{video => platform}/s5p-fimc/Makefile    |    0
+ .../{video => platform}/s5p-fimc/fimc-capture.c    |   31 +-
+ .../media/{video => platform}/s5p-fimc/fimc-core.c |    0
+ .../media/{video => platform}/s5p-fimc/fimc-core.h |    4 +-
+ .../{video => platform}/s5p-fimc/fimc-lite-reg.c   |    2 +-
+ .../{video => platform}/s5p-fimc/fimc-lite-reg.h   |    0
+ .../media/{video => platform}/s5p-fimc/fimc-lite.c |   42 +-
+ .../media/{video => platform}/s5p-fimc/fimc-lite.h |    2 +-
+ .../media/{video => platform}/s5p-fimc/fimc-m2m.c  |   42 +-
+ .../{video => platform}/s5p-fimc/fimc-mdevice.c    |    9 +-
+ .../{video => platform}/s5p-fimc/fimc-mdevice.h    |    6 +-
+ .../media/{video => platform}/s5p-fimc/fimc-reg.c  |    6 +-
+ .../media/{video => platform}/s5p-fimc/fimc-reg.h  |    0
+ .../media/{video => platform}/s5p-fimc/mipi-csis.c |    0
+ .../media/{video => platform}/s5p-fimc/mipi-csis.h |    0
+ drivers/media/{video => platform}/s5p-g2d/Makefile |    0
+ drivers/media/{video => platform}/s5p-g2d/g2d-hw.c |    0
+ .../media/{video => platform}/s5p-g2d/g2d-regs.h   |    0
+ drivers/media/{video => platform}/s5p-g2d/g2d.c    |   29 +-
+ drivers/media/{video => platform}/s5p-g2d/g2d.h    |    0
+ .../media/{video => platform}/s5p-jpeg/Makefile    |    0
+ .../media/{video => platform}/s5p-jpeg/jpeg-core.c |   38 +-
+ .../media/{video => platform}/s5p-jpeg/jpeg-core.h |    2 +-
+ .../media/{video => platform}/s5p-jpeg/jpeg-hw.h   |    2 +-
+ .../media/{video => platform}/s5p-jpeg/jpeg-regs.h |    2 +-
+ drivers/media/{video => platform}/s5p-mfc/Makefile |    0
+ .../media/{video => platform}/s5p-mfc/regs-mfc.h   |    0
+ .../media/{video => platform}/s5p-mfc/s5p_mfc.c    |   19 +-
+ .../{video => platform}/s5p-mfc/s5p_mfc_cmd.c      |    2 +-
+ .../{video => platform}/s5p-mfc/s5p_mfc_cmd.h      |    2 +-
+ .../{video => platform}/s5p-mfc/s5p_mfc_common.h   |    0
+ .../{video => platform}/s5p-mfc/s5p_mfc_ctrl.c     |    4 +-
+ .../{video => platform}/s5p-mfc/s5p_mfc_ctrl.h     |    2 +-
+ .../{video => platform}/s5p-mfc/s5p_mfc_debug.h    |    2 +-
+ .../{video => platform}/s5p-mfc/s5p_mfc_dec.c      |    2 +-
+ .../{video => platform}/s5p-mfc/s5p_mfc_dec.h      |    2 +-
+ .../{video => platform}/s5p-mfc/s5p_mfc_enc.c      |    2 +-
+ .../{video => platform}/s5p-mfc/s5p_mfc_enc.h      |    2 +-
+ .../{video => platform}/s5p-mfc/s5p_mfc_intr.c     |    2 +-
+ .../{video => platform}/s5p-mfc/s5p_mfc_intr.h     |    2 +-
+ .../{video => platform}/s5p-mfc/s5p_mfc_opr.c      |    2 +-
+ .../{video => platform}/s5p-mfc/s5p_mfc_opr.h      |    2 +-
+ .../media/{video => platform}/s5p-mfc/s5p_mfc_pm.c |    2 +-
+ .../media/{video => platform}/s5p-mfc/s5p_mfc_pm.h |    2 +-
+ .../{video => platform}/s5p-mfc/s5p_mfc_shm.c      |    2 +-
+ .../{video => platform}/s5p-mfc/s5p_mfc_shm.h      |    2 +-
+ drivers/media/{video => platform}/s5p-tv/Kconfig   |    2 +-
+ drivers/media/{video => platform}/s5p-tv/Makefile  |    2 +-
+ .../media/{video => platform}/s5p-tv/hdmi_drv.c    |    6 +-
+ .../media/{video => platform}/s5p-tv/hdmiphy_drv.c |    0
+ drivers/media/{video => platform}/s5p-tv/mixer.h   |    0
+ .../media/{video => platform}/s5p-tv/mixer_drv.c   |    6 +-
+ .../{video => platform}/s5p-tv/mixer_grp_layer.c   |    0
+ .../media/{video => platform}/s5p-tv/mixer_reg.c   |    0
+ .../media/{video => platform}/s5p-tv/mixer_video.c |   33 +-
+ .../{video => platform}/s5p-tv/mixer_vp_layer.c    |    0
+ .../media/{video => platform}/s5p-tv/regs-hdmi.h   |    0
+ .../media/{video => platform}/s5p-tv/regs-mixer.h  |    0
+ .../media/{video => platform}/s5p-tv/regs-sdo.h    |    2 +-
+ drivers/media/{video => platform}/s5p-tv/regs-vp.h |    0
+ drivers/media/{video => platform}/s5p-tv/sdo_drv.c |   10 +-
+ .../media/{video => platform}/s5p-tv/sii9234_drv.c |   17 +-
+ drivers/media/{video => platform}/sh_vou.c         |   25 +-
+ drivers/media/platform/soc_camera/Kconfig          |   87 +
+ drivers/media/platform/soc_camera/Makefile         |   14 +
+ .../{video => platform/soc_camera}/atmel-isi.c     |    0
+ .../{video => platform/soc_camera}/mx1_camera.c    |    0
+ .../{video => platform/soc_camera}/mx2_camera.c    |   40 +
+ .../{video => platform/soc_camera}/mx3_camera.c    |    4 +-
+ .../{video => platform/soc_camera}/omap1_camera.c  |    2 +-
+ .../{video => platform/soc_camera}/pxa_camera.c    |    0
+ .../soc_camera}/sh_mobile_ceu_camera.c             |    0
+ .../soc_camera}/sh_mobile_csi2.c                   |    0
+ .../{video => platform/soc_camera}/soc_camera.c    |  197 +-
+ .../soc_camera}/soc_camera_platform.c              |   11 +-
+ .../{video => platform/soc_camera}/soc_mediabus.c  |    0
+ drivers/media/{video => platform}/timblogiw.c      |    0
+ drivers/media/{video => platform}/via-camera.c     |    0
+ drivers/media/{video => platform}/via-camera.h     |    0
+ drivers/media/{video => platform}/vino.c           |    0
+ drivers/media/{video => platform}/vino.h           |    0
+ drivers/media/{video => platform}/vivi.c           |   49 +-
+ drivers/media/radio/radio-shark.c                  |   44 +-
+ drivers/media/radio/radio-shark2.c                 |   52 +-
+ drivers/media/radio/radio-si4713.c                 |    7 +-
+ drivers/media/radio/radio-tea5777.c                |  198 +-
+ drivers/media/radio/radio-tea5777.h                |    3 +
+ drivers/media/radio/radio-timb.c                   |    8 +-
+ drivers/media/radio/radio-wl1273.c                 |   23 +-
+ drivers/media/radio/wl128x/fmdrv_v4l2.c            |   38 +-
+ drivers/media/rc/Kconfig                           |   32 +-
+ drivers/media/rc/Makefile                          |    2 +
+ drivers/media/rc/ati_remote.c                      |   15 +-
+ drivers/media/rc/fintek-cir.c                      |   11 +-
+ drivers/media/rc/iguanair.c                        |  247 +-
+ drivers/media/rc/ir-lirc-codec.c                   |   35 +-
+ drivers/media/rc/ir-nec-decoder.c                  |    4 +-
+ drivers/media/rc/ir-raw.c                          |    6 +-
+ drivers/media/rc/ir-rx51.c                         |  498 +++
+ drivers/media/rc/ite-cir.c                         |    2 +-
+ drivers/media/rc/keymaps/rc-tt-1500.c              |    2 +-
+ drivers/media/rc/mceusb.c                          |   30 +-
+ drivers/media/rc/rc-loopback.c                     |   12 -
+ drivers/media/rc/redrat3.c                         |    5 +-
+ drivers/media/rc/ttusbir.c                         |  447 +++
+ drivers/media/{common => }/tuners/Kconfig          |  102 +-
+ drivers/media/{common => }/tuners/Makefile         |    6 +-
+ drivers/media/tuners/e4000.c                       |  408 ++
+ drivers/media/tuners/e4000.h                       |   52 +
+ drivers/media/tuners/e4000_priv.h                  |  147 +
+ drivers/media/{common => }/tuners/fc0011.c         |    0
+ drivers/media/{common => }/tuners/fc0011.h         |    0
+ drivers/media/{common => }/tuners/fc0012-priv.h    |    0
+ drivers/media/{common => }/tuners/fc0012.c         |    0
+ drivers/media/{common => }/tuners/fc0012.h         |    0
+ drivers/media/{common => }/tuners/fc0013-priv.h    |    0
+ drivers/media/{common => }/tuners/fc0013.c         |    0
+ drivers/media/{common => }/tuners/fc0013.h         |    0
+ drivers/media/{common => }/tuners/fc001x-common.h  |    0
+ drivers/media/tuners/fc2580.c                      |  524 +++
+ drivers/media/tuners/fc2580.h                      |   52 +
+ drivers/media/tuners/fc2580_priv.h                 |  134 +
+ drivers/media/{common => }/tuners/max2165.c        |    0
+ drivers/media/{common => }/tuners/max2165.h        |    0
+ drivers/media/{common => }/tuners/max2165_priv.h   |    0
+ drivers/media/{common => }/tuners/mc44s803.c       |    9 +-
+ drivers/media/{common => }/tuners/mc44s803.h       |    0
+ drivers/media/{common => }/tuners/mc44s803_priv.h  |    0
+ drivers/media/{common => }/tuners/mt2060.c         |    0
+ drivers/media/{common => }/tuners/mt2060.h         |    0
+ drivers/media/{common => }/tuners/mt2060_priv.h    |    0
+ drivers/media/{common => }/tuners/mt2063.c         |    0
+ drivers/media/{common => }/tuners/mt2063.h         |    0
+ drivers/media/{common => }/tuners/mt20xx.c         |    0
+ drivers/media/{common => }/tuners/mt20xx.h         |    0
+ drivers/media/{common => }/tuners/mt2131.c         |    0
+ drivers/media/{common => }/tuners/mt2131.h         |    0
+ drivers/media/{common => }/tuners/mt2131_priv.h    |    0
+ drivers/media/{common => }/tuners/mt2266.c         |    0
+ drivers/media/{common => }/tuners/mt2266.h         |    0
+ drivers/media/{common => }/tuners/mxl5005s.c       |   11 +
+ drivers/media/{common => }/tuners/mxl5005s.h       |    0
+ drivers/media/{common => }/tuners/mxl5007t.c       |    0
+ drivers/media/{common => }/tuners/mxl5007t.h       |    0
+ drivers/media/{common => }/tuners/qt1010.c         |   66 +-
+ drivers/media/{common => }/tuners/qt1010.h         |    0
+ drivers/media/{common => }/tuners/qt1010_priv.h    |    0
+ drivers/media/{common => }/tuners/tda18212.c       |   37 +-
+ drivers/media/{common => }/tuners/tda18212.h       |    0
+ drivers/media/{common => }/tuners/tda18218.c       |   52 +-
+ drivers/media/{common => }/tuners/tda18218.h       |    0
+ drivers/media/{common => }/tuners/tda18218_priv.h  |   13 +-
+ .../media/{common => }/tuners/tda18271-common.c    |   10 +-
+ drivers/media/{common => }/tuners/tda18271-fe.c    |    0
+ drivers/media/{common => }/tuners/tda18271-maps.c  |    0
+ drivers/media/{common => }/tuners/tda18271-priv.h  |    0
+ drivers/media/{common => }/tuners/tda18271.h       |    0
+ drivers/media/{common => }/tuners/tda827x.c        |    0
+ drivers/media/{common => }/tuners/tda827x.h        |    0
+ drivers/media/{common => }/tuners/tda8290.c        |    0
+ drivers/media/{common => }/tuners/tda8290.h        |    0
+ drivers/media/{common => }/tuners/tda9887.c        |    0
+ drivers/media/{common => }/tuners/tda9887.h        |    0
+ drivers/media/{common => }/tuners/tea5761.c        |    0
+ drivers/media/{common => }/tuners/tea5761.h        |    0
+ drivers/media/{common => }/tuners/tea5767.c        |    0
+ drivers/media/{common => }/tuners/tea5767.h        |    0
+ drivers/media/{common => }/tuners/tua9001.c        |   95 +-
+ drivers/media/{common => }/tuners/tua9001.h        |   20 +
+ drivers/media/{common => }/tuners/tua9001_priv.h   |    0
+ drivers/media/{common => }/tuners/tuner-i2c.h      |    0
+ drivers/media/{common => }/tuners/tuner-simple.c   |    0
+ drivers/media/{common => }/tuners/tuner-simple.h   |    0
+ drivers/media/{common => }/tuners/tuner-types.c    |    0
+ .../media/{common => }/tuners/tuner-xc2028-types.h |    0
+ drivers/media/{common => }/tuners/tuner-xc2028.c   |    7 +-
+ drivers/media/{common => }/tuners/tuner-xc2028.h   |    0
+ drivers/media/{common => }/tuners/xc4000.c         |    3 +-
+ drivers/media/{common => }/tuners/xc4000.h         |    0
+ drivers/media/{common => }/tuners/xc5000.c         |  161 +-
+ drivers/media/{common => }/tuners/xc5000.h         |    0
+ drivers/media/usb/Kconfig                          |   54 +
+ drivers/media/usb/Makefile                         |   22 +
+ drivers/media/{video => usb}/au0828/Kconfig        |   11 +-
+ drivers/media/{video => usb}/au0828/Makefile       |    6 +-
+ drivers/media/{video => usb}/au0828/au0828-cards.c |    4 +-
+ drivers/media/{video => usb}/au0828/au0828-cards.h |    0
+ drivers/media/{video => usb}/au0828/au0828-core.c  |   59 +-
+ drivers/media/{video => usb}/au0828/au0828-dvb.c   |   54 +-
+ drivers/media/{video => usb}/au0828/au0828-i2c.c   |   21 +-
+ drivers/media/{video => usb}/au0828/au0828-reg.h   |    1 +
+ drivers/media/{video => usb}/au0828/au0828-vbi.c   |    0
+ drivers/media/{video => usb}/au0828/au0828-video.c |   76 +-
+ drivers/media/{video => usb}/au0828/au0828.h       |    2 +
+ drivers/media/usb/b2c2/Kconfig                     |   15 +
+ drivers/media/usb/b2c2/Makefile                    |    5 +
+ drivers/media/{dvb => usb}/b2c2/flexcop-usb.c      |    5 +-
+ drivers/media/{dvb => usb}/b2c2/flexcop-usb.h      |    0
+ drivers/media/{video => usb}/cpia2/Kconfig         |    0
+ drivers/media/{video => usb}/cpia2/Makefile        |    0
+ drivers/media/{video => usb}/cpia2/cpia2.h         |    0
+ drivers/media/{video => usb}/cpia2/cpia2_core.c    |    6 +-
+ .../media/{video => usb}/cpia2/cpia2_registers.h   |    0
+ drivers/media/{video => usb}/cpia2/cpia2_usb.c     |    0
+ drivers/media/{video => usb}/cpia2/cpia2_v4l.c     |   39 +-
+ drivers/media/{video => usb}/cx231xx/Kconfig       |    8 +-
+ drivers/media/{video => usb}/cx231xx/Makefile      |   11 +-
+ drivers/media/{video => usb}/cx231xx/cx231xx-417.c |    2 +
+ .../media/{video => usb}/cx231xx/cx231xx-audio.c   |    0
+ .../media/{video => usb}/cx231xx/cx231xx-avcore.c  |    0
+ .../media/{video => usb}/cx231xx/cx231xx-cards.c   |    0
+ .../{video => usb}/cx231xx/cx231xx-conf-reg.h      |    0
+ .../media/{video => usb}/cx231xx/cx231xx-core.c    |    0
+ drivers/media/{video => usb}/cx231xx/cx231xx-dif.h |    0
+ drivers/media/{video => usb}/cx231xx/cx231xx-dvb.c |    0
+ drivers/media/{video => usb}/cx231xx/cx231xx-i2c.c |    0
+ .../media/{video => usb}/cx231xx/cx231xx-input.c   |    0
+ .../media/{video => usb}/cx231xx/cx231xx-pcb-cfg.c |    0
+ .../media/{video => usb}/cx231xx/cx231xx-pcb-cfg.h |    0
+ drivers/media/{video => usb}/cx231xx/cx231xx-reg.h |    0
+ drivers/media/{video => usb}/cx231xx/cx231xx-vbi.c |    0
+ drivers/media/{video => usb}/cx231xx/cx231xx-vbi.h |    0
+ .../media/{video => usb}/cx231xx/cx231xx-video.c   |   47 +-
+ drivers/media/{video => usb}/cx231xx/cx231xx.h     |    0
+ drivers/media/usb/dvb-usb-v2/Kconfig               |  148 +
+ drivers/media/usb/dvb-usb-v2/Makefile              |   49 +
+ drivers/media/usb/dvb-usb-v2/af9015.c              | 1454 +++++++
+ .../media/{dvb/dvb-usb => usb/dvb-usb-v2}/af9015.h |   55 +-
+ .../media/{dvb/dvb-usb => usb/dvb-usb-v2}/af9035.c |  796 ++--
+ .../media/{dvb/dvb-usb => usb/dvb-usb-v2}/af9035.h |    6 +-
+ .../media/{dvb/dvb-usb => usb/dvb-usb-v2}/anysee.c |  663 ++-
+ .../media/{dvb/dvb-usb => usb/dvb-usb-v2}/anysee.h |    9 +-
+ .../media/{dvb/dvb-usb => usb/dvb-usb-v2}/au6610.c |  123 +-
+ .../media/{dvb/dvb-usb => usb/dvb-usb-v2}/au6610.h |   13 +-
+ .../media/{dvb/dvb-usb => usb/dvb-usb-v2}/az6007.c |  410 +-
+ .../media/{dvb/dvb-usb => usb/dvb-usb-v2}/ce6230.c |  188 +-
+ .../media/{dvb/dvb-usb => usb/dvb-usb-v2}/ce6230.h |   33 +-
+ drivers/media/usb/dvb-usb-v2/cypress_firmware.c    |  125 +
+ drivers/media/usb/dvb-usb-v2/cypress_firmware.h    |   31 +
+ drivers/media/usb/dvb-usb-v2/dvb_usb.h             |  403 ++
+ drivers/media/usb/dvb-usb-v2/dvb_usb_common.h      |   35 +
+ drivers/media/usb/dvb-usb-v2/dvb_usb_core.c        | 1046 +++++
+ drivers/media/usb/dvb-usb-v2/dvb_usb_urb.c         |   77 +
+ .../media/{dvb/dvb-usb => usb/dvb-usb-v2}/ec168.c  |  326 +-
+ .../media/{dvb/dvb-usb => usb/dvb-usb-v2}/ec168.h  |   24 +-
+ .../media/{dvb/dvb-usb => usb/dvb-usb-v2}/gl861.c  |  132 +-
+ .../media/{dvb/dvb-usb => usb/dvb-usb-v2}/gl861.h  |    5 +-
+ drivers/media/usb/dvb-usb-v2/it913x.c              |  799 ++++
+ .../{dvb/dvb-usb => usb/dvb-usb-v2}/lmedm04.c      |  586 ++-
+ .../{dvb/dvb-usb => usb/dvb-usb-v2}/lmedm04.h      |    0
+ .../dvb-usb => usb/dvb-usb-v2}/mxl111sf-demod.c    |    0
+ .../dvb-usb => usb/dvb-usb-v2}/mxl111sf-demod.h    |    0
+ .../dvb-usb => usb/dvb-usb-v2}/mxl111sf-gpio.c     |    0
+ .../dvb-usb => usb/dvb-usb-v2}/mxl111sf-gpio.h     |    0
+ .../{dvb/dvb-usb => usb/dvb-usb-v2}/mxl111sf-i2c.c |    0
+ .../{dvb/dvb-usb => usb/dvb-usb-v2}/mxl111sf-i2c.h |    0
+ .../{dvb/dvb-usb => usb/dvb-usb-v2}/mxl111sf-phy.c |    0
+ .../{dvb/dvb-usb => usb/dvb-usb-v2}/mxl111sf-phy.h |    0
+ .../{dvb/dvb-usb => usb/dvb-usb-v2}/mxl111sf-reg.h |    0
+ .../dvb-usb => usb/dvb-usb-v2}/mxl111sf-tuner.c    |    2 +
+ .../dvb-usb => usb/dvb-usb-v2}/mxl111sf-tuner.h    |    0
+ drivers/media/usb/dvb-usb-v2/mxl111sf.c            | 1431 +++++++
+ .../{dvb/dvb-usb => usb/dvb-usb-v2}/mxl111sf.h     |   22 +-
+ .../{dvb/dvb-usb => usb/dvb-usb-v2}/rtl28xxu.c     |  777 ++--
+ .../{dvb/dvb-usb => usb/dvb-usb-v2}/rtl28xxu.h     |   28 +-
+ drivers/media/usb/dvb-usb-v2/usb_urb.c             |  358 ++
+ drivers/media/usb/dvb-usb/Kconfig                  |  313 ++
+ drivers/media/usb/dvb-usb/Makefile                 |   83 +
+ drivers/media/{dvb => usb}/dvb-usb/a800.c          |    0
+ drivers/media/{dvb => usb}/dvb-usb/af9005-fe.c     |    0
+ drivers/media/{dvb => usb}/dvb-usb/af9005-remote.c |    0
+ drivers/media/{dvb => usb}/dvb-usb/af9005-script.h |    0
+ drivers/media/{dvb => usb}/dvb-usb/af9005.c        |    0
+ drivers/media/{dvb => usb}/dvb-usb/af9005.h        |    0
+ drivers/media/{dvb => usb}/dvb-usb/az6027.c        |    0
+ drivers/media/{dvb => usb}/dvb-usb/az6027.h        |    0
+ .../media/{dvb => usb}/dvb-usb/cinergyT2-core.c    |    0
+ drivers/media/{dvb => usb}/dvb-usb/cinergyT2-fe.c  |    0
+ drivers/media/{dvb => usb}/dvb-usb/cinergyT2.h     |    0
+ drivers/media/{dvb => usb}/dvb-usb/cxusb.c         |    0
+ drivers/media/{dvb => usb}/dvb-usb/cxusb.h         |    0
+ drivers/media/{dvb => usb}/dvb-usb/dib0700.h       |    0
+ drivers/media/{dvb => usb}/dvb-usb/dib0700_core.c  |    6 +-
+ .../media/{dvb => usb}/dvb-usb/dib0700_devices.c   |    0
+ drivers/media/{dvb => usb}/dvb-usb/dib07x0.h       |    0
+ drivers/media/{dvb => usb}/dvb-usb/dibusb-common.c |    0
+ drivers/media/{dvb => usb}/dvb-usb/dibusb-mb.c     |    0
+ drivers/media/{dvb => usb}/dvb-usb/dibusb-mc.c     |    0
+ drivers/media/{dvb => usb}/dvb-usb/dibusb.h        |    0
+ drivers/media/{dvb => usb}/dvb-usb/digitv.c        |    0
+ drivers/media/{dvb => usb}/dvb-usb/digitv.h        |    0
+ drivers/media/{dvb => usb}/dvb-usb/dtt200u-fe.c    |    0
+ drivers/media/{dvb => usb}/dvb-usb/dtt200u.c       |    0
+ drivers/media/{dvb => usb}/dvb-usb/dtt200u.h       |    0
+ drivers/media/{dvb => usb}/dvb-usb/dtv5100.c       |    0
+ drivers/media/{dvb => usb}/dvb-usb/dtv5100.h       |    0
+ .../media/{dvb => usb}/dvb-usb/dvb-usb-common.h    |    0
+ drivers/media/{dvb => usb}/dvb-usb/dvb-usb-dvb.c   |    1 -
+ .../media/{dvb => usb}/dvb-usb/dvb-usb-firmware.c  |    0
+ drivers/media/{dvb => usb}/dvb-usb/dvb-usb-i2c.c   |    0
+ drivers/media/{dvb => usb}/dvb-usb/dvb-usb-init.c  |    0
+ .../media/{dvb => usb}/dvb-usb/dvb-usb-remote.c    |    0
+ drivers/media/{dvb => usb}/dvb-usb/dvb-usb-urb.c   |    0
+ drivers/media/{dvb => usb}/dvb-usb/dvb-usb.h       |    2 -
+ drivers/media/{dvb => usb}/dvb-usb/dw2102.c        |    0
+ drivers/media/{dvb => usb}/dvb-usb/dw2102.h        |    0
+ drivers/media/{dvb => usb}/dvb-usb/friio-fe.c      |    0
+ drivers/media/{dvb => usb}/dvb-usb/friio.c         |    0
+ drivers/media/{dvb => usb}/dvb-usb/friio.h         |    0
+ drivers/media/{dvb => usb}/dvb-usb/gp8psk-fe.c     |    0
+ drivers/media/{dvb => usb}/dvb-usb/gp8psk.c        |    0
+ drivers/media/{dvb => usb}/dvb-usb/gp8psk.h        |    0
+ drivers/media/{dvb => usb}/dvb-usb/m920x.c         |    0
+ drivers/media/{dvb => usb}/dvb-usb/m920x.h         |    0
+ drivers/media/{dvb => usb}/dvb-usb/nova-t-usb2.c   |    0
+ drivers/media/{dvb => usb}/dvb-usb/opera1.c        |    0
+ drivers/media/{dvb => usb}/dvb-usb/pctv452e.c      |    7 +-
+ .../media/{dvb => usb}/dvb-usb/technisat-usb2.c    |    0
+ drivers/media/{dvb => usb}/dvb-usb/ttusb2.c        |    2 +-
+ drivers/media/{dvb => usb}/dvb-usb/ttusb2.h        |    0
+ drivers/media/{dvb => usb}/dvb-usb/umt-010.c       |    0
+ drivers/media/{dvb => usb}/dvb-usb/usb-urb.c       |    0
+ drivers/media/{dvb => usb}/dvb-usb/vp702x-fe.c     |    0
+ drivers/media/{dvb => usb}/dvb-usb/vp702x.c        |    0
+ drivers/media/{dvb => usb}/dvb-usb/vp702x.h        |    0
+ drivers/media/{dvb => usb}/dvb-usb/vp7045-fe.c     |    0
+ drivers/media/{dvb => usb}/dvb-usb/vp7045.c        |    0
+ drivers/media/{dvb => usb}/dvb-usb/vp7045.h        |    0
+ drivers/media/{video => usb}/em28xx/Kconfig        |   28 +-
+ drivers/media/{video => usb}/em28xx/Makefile       |   10 +-
+ drivers/media/{video => usb}/em28xx/em28xx-audio.c |    1 -
+ drivers/media/{video => usb}/em28xx/em28xx-cards.c |    0
+ drivers/media/{video => usb}/em28xx/em28xx-core.c  |    4 -
+ drivers/media/{video => usb}/em28xx/em28xx-dvb.c   |    0
+ drivers/media/{video => usb}/em28xx/em28xx-i2c.c   |    0
+ drivers/media/{video => usb}/em28xx/em28xx-input.c |    0
+ drivers/media/{video => usb}/em28xx/em28xx-reg.h   |    0
+ drivers/media/{video => usb}/em28xx/em28xx-vbi.c   |    0
+ drivers/media/{video => usb}/em28xx/em28xx-video.c |   52 +-
+ drivers/media/{video => usb}/em28xx/em28xx.h       |    0
+ drivers/media/{video => usb}/gspca/Kconfig         |    6 +-
+ drivers/media/{video => usb}/gspca/Makefile        |    0
+ .../{video => usb}/gspca/autogain_functions.c      |    0
+ .../{video => usb}/gspca/autogain_functions.h      |    0
+ drivers/media/{video => usb}/gspca/benq.c          |    0
+ drivers/media/{video => usb}/gspca/conex.c         |    0
+ drivers/media/{video => usb}/gspca/cpia1.c         |    2 +-
+ drivers/media/{video => usb}/gspca/etoms.c         |    0
+ drivers/media/{video => usb}/gspca/finepix.c       |   18 +-
+ drivers/media/{video => usb}/gspca/gl860/Kconfig   |    0
+ drivers/media/{video => usb}/gspca/gl860/Makefile  |    2 +-
+ .../{video => usb}/gspca/gl860/gl860-mi1320.c      |    0
+ .../{video => usb}/gspca/gl860/gl860-mi2020.c      |    0
+ .../{video => usb}/gspca/gl860/gl860-ov2640.c      |    0
+ .../{video => usb}/gspca/gl860/gl860-ov9655.c      |    0
+ drivers/media/{video => usb}/gspca/gl860/gl860.c   |    0
+ drivers/media/{video => usb}/gspca/gl860/gl860.h   |    0
+ drivers/media/{video => usb}/gspca/gspca.c         |   12 +-
+ drivers/media/{video => usb}/gspca/gspca.h         |    0
+ drivers/media/{video => usb}/gspca/jeilinj.c       |    0
+ drivers/media/{video => usb}/gspca/jl2005bcd.c     |   18 +-
+ drivers/media/{video => usb}/gspca/jpeg.h          |    0
+ drivers/media/{video => usb}/gspca/kinect.c        |    0
+ drivers/media/{video => usb}/gspca/konica.c        |    0
+ drivers/media/{video => usb}/gspca/m5602/Kconfig   |    0
+ drivers/media/{video => usb}/gspca/m5602/Makefile  |    2 +-
+ .../{video => usb}/gspca/m5602/m5602_bridge.h      |    0
+ .../media/{video => usb}/gspca/m5602/m5602_core.c  |    0
+ .../{video => usb}/gspca/m5602/m5602_mt9m111.c     |    0
+ .../{video => usb}/gspca/m5602/m5602_mt9m111.h     |    0
+ .../{video => usb}/gspca/m5602/m5602_ov7660.c      |    0
+ .../{video => usb}/gspca/m5602/m5602_ov7660.h      |    0
+ .../{video => usb}/gspca/m5602/m5602_ov9650.c      |    0
+ .../{video => usb}/gspca/m5602/m5602_ov9650.h      |    0
+ .../{video => usb}/gspca/m5602/m5602_po1030.c      |    0
+ .../{video => usb}/gspca/m5602/m5602_po1030.h      |    0
+ .../{video => usb}/gspca/m5602/m5602_s5k4aa.c      |    0
+ .../{video => usb}/gspca/m5602/m5602_s5k4aa.h      |    0
+ .../{video => usb}/gspca/m5602/m5602_s5k83a.c      |    0
+ .../{video => usb}/gspca/m5602/m5602_s5k83a.h      |    0
+ .../{video => usb}/gspca/m5602/m5602_sensor.h      |    0
+ drivers/media/{video => usb}/gspca/mars.c          |    0
+ drivers/media/{video => usb}/gspca/mr97310a.c      |    0
+ drivers/media/{video => usb}/gspca/nw80x.c         |    0
+ drivers/media/{video => usb}/gspca/ov519.c         |   16 +-
+ drivers/media/{video => usb}/gspca/ov534.c         |    0
+ drivers/media/{video => usb}/gspca/ov534_9.c       |    0
+ drivers/media/{video => usb}/gspca/pac207.c        |    0
+ drivers/media/{video => usb}/gspca/pac7302.c       |   47 +-
+ drivers/media/{video => usb}/gspca/pac7311.c       |    0
+ drivers/media/{video => usb}/gspca/pac_common.h    |    0
+ drivers/media/{video => usb}/gspca/se401.c         |    0
+ drivers/media/{video => usb}/gspca/se401.h         |    0
+ drivers/media/{video => usb}/gspca/sn9c2028.c      |    0
+ drivers/media/{video => usb}/gspca/sn9c2028.h      |    0
+ drivers/media/{video => usb}/gspca/sn9c20x.c       |    2 +
+ drivers/media/{video => usb}/gspca/sonixb.c        |    0
+ drivers/media/{video => usb}/gspca/sonixj.c        |    2 +
+ drivers/media/{video => usb}/gspca/spca1528.c      |    0
+ drivers/media/{video => usb}/gspca/spca500.c       |    0
+ drivers/media/{video => usb}/gspca/spca501.c       |    0
+ drivers/media/{video => usb}/gspca/spca505.c       |    0
+ drivers/media/{video => usb}/gspca/spca506.c       |    0
+ drivers/media/{video => usb}/gspca/spca508.c       |    0
+ drivers/media/{video => usb}/gspca/spca561.c       |    0
+ drivers/media/{video => usb}/gspca/sq905.c         |   19 +-
+ drivers/media/{video => usb}/gspca/sq905c.c        |   25 +-
+ drivers/media/{video => usb}/gspca/sq930x.c        |   10 +-
+ drivers/media/{video => usb}/gspca/stk014.c        |    0
+ drivers/media/{video => usb}/gspca/stv0680.c       |    0
+ drivers/media/{video => usb}/gspca/stv06xx/Kconfig |    0
+ .../media/{video => usb}/gspca/stv06xx/Makefile    |    2 +-
+ .../media/{video => usb}/gspca/stv06xx/stv06xx.c   |    0
+ .../media/{video => usb}/gspca/stv06xx/stv06xx.h   |    0
+ .../{video => usb}/gspca/stv06xx/stv06xx_hdcs.c    |    0
+ .../{video => usb}/gspca/stv06xx/stv06xx_hdcs.h    |    0
+ .../{video => usb}/gspca/stv06xx/stv06xx_pb0100.c  |    0
+ .../{video => usb}/gspca/stv06xx/stv06xx_pb0100.h  |    0
+ .../{video => usb}/gspca/stv06xx/stv06xx_sensor.h  |    0
+ .../{video => usb}/gspca/stv06xx/stv06xx_st6422.c  |    0
+ .../{video => usb}/gspca/stv06xx/stv06xx_st6422.h  |    0
+ .../{video => usb}/gspca/stv06xx/stv06xx_vv6410.c  |    0
+ .../{video => usb}/gspca/stv06xx/stv06xx_vv6410.h  |    0
+ drivers/media/{video => usb}/gspca/sunplus.c       |    0
+ drivers/media/{video => usb}/gspca/t613.c          |    0
+ drivers/media/{video => usb}/gspca/topro.c         |    0
+ drivers/media/{video => usb}/gspca/tv8532.c        |    0
+ drivers/media/{video => usb}/gspca/vc032x.c        |    7 +-
+ drivers/media/{video => usb}/gspca/vicam.c         |   17 +-
+ drivers/media/{video => usb}/gspca/w996Xcf.c       |    0
+ drivers/media/{video => usb}/gspca/xirlink_cit.c   |    4 +-
+ drivers/media/{video => usb}/gspca/zc3xx-reg.h     |    0
+ drivers/media/{video => usb}/gspca/zc3xx.c         |    8 +-
+ drivers/media/{video => usb}/hdpvr/Kconfig         |    0
+ drivers/media/{video => usb}/hdpvr/Makefile        |    2 +-
+ drivers/media/{video => usb}/hdpvr/hdpvr-control.c |    0
+ drivers/media/{video => usb}/hdpvr/hdpvr-core.c    |    0
+ drivers/media/{video => usb}/hdpvr/hdpvr-i2c.c     |    0
+ drivers/media/{video => usb}/hdpvr/hdpvr-video.c   |    0
+ drivers/media/{video => usb}/hdpvr/hdpvr.h         |    0
+ drivers/media/{video => usb}/pvrusb2/Kconfig       |   14 +-
+ drivers/media/{video => usb}/pvrusb2/Makefile      |    8 +-
+ .../media/{video => usb}/pvrusb2/pvrusb2-audio.c   |    0
+ .../media/{video => usb}/pvrusb2/pvrusb2-audio.h   |    0
+ .../media/{video => usb}/pvrusb2/pvrusb2-context.c |    0
+ .../media/{video => usb}/pvrusb2/pvrusb2-context.h |    0
+ .../{video => usb}/pvrusb2/pvrusb2-cs53l32a.c      |    0
+ .../{video => usb}/pvrusb2/pvrusb2-cs53l32a.h      |    0
+ .../media/{video => usb}/pvrusb2/pvrusb2-ctrl.c    |    0
+ .../media/{video => usb}/pvrusb2/pvrusb2-ctrl.h    |    0
+ .../{video => usb}/pvrusb2/pvrusb2-cx2584x-v4l.c   |    0
+ .../{video => usb}/pvrusb2/pvrusb2-cx2584x-v4l.h   |    0
+ .../media/{video => usb}/pvrusb2/pvrusb2-debug.h   |    0
+ .../{video => usb}/pvrusb2/pvrusb2-debugifc.c      |    0
+ .../{video => usb}/pvrusb2/pvrusb2-debugifc.h      |    0
+ .../media/{video => usb}/pvrusb2/pvrusb2-devattr.c |   17 +-
+ .../media/{video => usb}/pvrusb2/pvrusb2-devattr.h |    0
+ drivers/media/{video => usb}/pvrusb2/pvrusb2-dvb.c |    0
+ drivers/media/{video => usb}/pvrusb2/pvrusb2-dvb.h |    0
+ .../media/{video => usb}/pvrusb2/pvrusb2-eeprom.c  |    0
+ .../media/{video => usb}/pvrusb2/pvrusb2-eeprom.h  |    0
+ .../media/{video => usb}/pvrusb2/pvrusb2-encoder.c |    0
+ .../media/{video => usb}/pvrusb2/pvrusb2-encoder.h |    0
+ .../media/{video => usb}/pvrusb2/pvrusb2-fx2-cmd.h |    0
+ .../{video => usb}/pvrusb2/pvrusb2-hdw-internal.h  |    0
+ drivers/media/{video => usb}/pvrusb2/pvrusb2-hdw.c |    0
+ drivers/media/{video => usb}/pvrusb2/pvrusb2-hdw.h |    0
+ .../{video => usb}/pvrusb2/pvrusb2-i2c-core.c      |    0
+ .../{video => usb}/pvrusb2/pvrusb2-i2c-core.h      |    0
+ drivers/media/{video => usb}/pvrusb2/pvrusb2-io.c  |    0
+ drivers/media/{video => usb}/pvrusb2/pvrusb2-io.h  |    0
+ .../media/{video => usb}/pvrusb2/pvrusb2-ioread.c  |    0
+ .../media/{video => usb}/pvrusb2/pvrusb2-ioread.h  |    0
+ .../media/{video => usb}/pvrusb2/pvrusb2-main.c    |    0
+ drivers/media/{video => usb}/pvrusb2/pvrusb2-std.c |    0
+ drivers/media/{video => usb}/pvrusb2/pvrusb2-std.h |    0
+ .../media/{video => usb}/pvrusb2/pvrusb2-sysfs.c   |    0
+ .../media/{video => usb}/pvrusb2/pvrusb2-sysfs.h   |    0
+ .../media/{video => usb}/pvrusb2/pvrusb2-util.h    |    0
+ .../media/{video => usb}/pvrusb2/pvrusb2-v4l2.c    |    0
+ .../media/{video => usb}/pvrusb2/pvrusb2-v4l2.h    |    0
+ .../{video => usb}/pvrusb2/pvrusb2-video-v4l.c     |    0
+ .../{video => usb}/pvrusb2/pvrusb2-video-v4l.h     |    0
+ .../media/{video => usb}/pvrusb2/pvrusb2-wm8775.c  |    0
+ .../media/{video => usb}/pvrusb2/pvrusb2-wm8775.h  |    0
+ drivers/media/{video => usb}/pvrusb2/pvrusb2.h     |    0
+ drivers/media/{video => usb}/pwc/Kconfig           |    0
+ drivers/media/{video => usb}/pwc/Makefile          |    2 +-
+ drivers/media/{video => usb}/pwc/philips.txt       |    0
+ drivers/media/{video => usb}/pwc/pwc-ctrl.c        |    0
+ drivers/media/{video => usb}/pwc/pwc-dec1.c        |    0
+ drivers/media/{video => usb}/pwc/pwc-dec1.h        |    0
+ drivers/media/{video => usb}/pwc/pwc-dec23.c       |    0
+ drivers/media/{video => usb}/pwc/pwc-dec23.h       |    0
+ drivers/media/{video => usb}/pwc/pwc-if.c          |    3 +-
+ drivers/media/{video => usb}/pwc/pwc-kiara.c       |    0
+ drivers/media/{video => usb}/pwc/pwc-kiara.h       |    0
+ drivers/media/{video => usb}/pwc/pwc-misc.c        |    0
+ drivers/media/{video => usb}/pwc/pwc-nala.h        |    0
+ drivers/media/{video => usb}/pwc/pwc-timon.c       |    0
+ drivers/media/{video => usb}/pwc/pwc-timon.h       |    0
+ drivers/media/{video => usb}/pwc/pwc-uncompress.c  |    0
+ drivers/media/{video => usb}/pwc/pwc-v4l.c         |    0
+ drivers/media/{video => usb}/pwc/pwc.h             |    0
+ drivers/media/usb/s2255/Kconfig                    |    9 +
+ drivers/media/usb/s2255/Makefile                   |    2 +
+ drivers/media/{video => usb/s2255}/s2255drv.c      |   43 +-
+ drivers/media/usb/siano/Kconfig                    |   10 +
+ drivers/media/usb/siano/Makefile                   |    6 +
+ drivers/media/{dvb => usb}/siano/smsusb.c          |    0
+ drivers/media/{video => usb}/sn9c102/Kconfig       |    0
+ drivers/media/{video => usb}/sn9c102/Makefile      |    0
+ drivers/media/{video => usb}/sn9c102/sn9c102.h     |    0
+ .../media/{video => usb}/sn9c102/sn9c102_config.h  |    0
+ .../media/{video => usb}/sn9c102/sn9c102_core.c    |    0
+ .../{video => usb}/sn9c102/sn9c102_devtable.h      |    0
+ .../media/{video => usb}/sn9c102/sn9c102_hv7131d.c |    0
+ .../media/{video => usb}/sn9c102/sn9c102_hv7131r.c |    0
+ .../media/{video => usb}/sn9c102/sn9c102_mi0343.c  |    0
+ .../media/{video => usb}/sn9c102/sn9c102_mi0360.c  |    0
+ .../media/{video => usb}/sn9c102/sn9c102_mt9v111.c |    0
+ .../media/{video => usb}/sn9c102/sn9c102_ov7630.c  |    0
+ .../media/{video => usb}/sn9c102/sn9c102_ov7660.c  |    0
+ .../media/{video => usb}/sn9c102/sn9c102_pas106b.c |    0
+ .../{video => usb}/sn9c102/sn9c102_pas202bcb.c     |    0
+ .../media/{video => usb}/sn9c102/sn9c102_sensor.h  |    0
+ .../{video => usb}/sn9c102/sn9c102_tas5110c1b.c    |    0
+ .../{video => usb}/sn9c102/sn9c102_tas5110d.c      |    0
+ .../{video => usb}/sn9c102/sn9c102_tas5130d1b.c    |    0
+ drivers/media/usb/stk1160/Kconfig                  |   20 +
+ drivers/media/usb/stk1160/Makefile                 |   11 +
+ drivers/media/usb/stk1160/stk1160-ac97.c           |  152 +
+ drivers/media/usb/stk1160/stk1160-core.c           |  430 ++
+ drivers/media/usb/stk1160/stk1160-i2c.c            |  294 ++
+ drivers/media/usb/stk1160/stk1160-reg.h            |   93 +
+ drivers/media/usb/stk1160/stk1160-v4l.c            |  739 ++++
+ drivers/media/usb/stk1160/stk1160-video.c          |  518 +++
+ drivers/media/usb/stk1160/stk1160.h                |  208 +
+ drivers/media/usb/stkwebcam/Kconfig                |   13 +
+ drivers/media/usb/stkwebcam/Makefile               |    4 +
+ .../media/{video => usb/stkwebcam}/stk-sensor.c    |    0
+ .../media/{video => usb/stkwebcam}/stk-webcam.c    |    0
+ .../media/{video => usb/stkwebcam}/stk-webcam.h    |    0
+ drivers/media/{video => usb}/tlg2300/Kconfig       |    0
+ drivers/media/usb/tlg2300/Makefile                 |    9 +
+ drivers/media/{video => usb}/tlg2300/pd-alsa.c     |    4 +
+ drivers/media/{video => usb}/tlg2300/pd-common.h   |    0
+ drivers/media/{video => usb}/tlg2300/pd-dvb.c      |    0
+ drivers/media/{video => usb}/tlg2300/pd-main.c     |    0
+ drivers/media/{video => usb}/tlg2300/pd-radio.c    |    0
+ drivers/media/{video => usb}/tlg2300/pd-video.c    |    0
+ drivers/media/{video => usb}/tlg2300/vendorcmds.h  |    0
+ drivers/media/{video => usb}/tm6000/Kconfig        |    0
+ drivers/media/{video => usb}/tm6000/Makefile       |    8 +-
+ drivers/media/{video => usb}/tm6000/tm6000-alsa.c  |    3 +-
+ drivers/media/{video => usb}/tm6000/tm6000-cards.c |    0
+ drivers/media/{video => usb}/tm6000/tm6000-core.c  |    0
+ drivers/media/{video => usb}/tm6000/tm6000-dvb.c   |    0
+ drivers/media/{video => usb}/tm6000/tm6000-i2c.c   |    0
+ drivers/media/{video => usb}/tm6000/tm6000-input.c |    3 +-
+ drivers/media/{video => usb}/tm6000/tm6000-regs.h  |    0
+ drivers/media/{video => usb}/tm6000/tm6000-stds.c  |    0
+ .../media/{video => usb}/tm6000/tm6000-usb-isoc.h  |    0
+ drivers/media/{video => usb}/tm6000/tm6000-video.c |   52 +-
+ drivers/media/{video => usb}/tm6000/tm6000.h       |    0
+ drivers/media/{dvb => usb}/ttusb-budget/Kconfig    |   14 +-
+ drivers/media/usb/ttusb-budget/Makefile            |    3 +
+ .../{dvb => usb}/ttusb-budget/dvb-ttusb-budget.c   |    0
+ drivers/media/{dvb => usb}/ttusb-dec/Kconfig       |    0
+ drivers/media/{dvb => usb}/ttusb-dec/Makefile      |    2 +-
+ drivers/media/{dvb => usb}/ttusb-dec/ttusb_dec.c   |    0
+ drivers/media/{dvb => usb}/ttusb-dec/ttusbdecfe.c  |    0
+ drivers/media/{dvb => usb}/ttusb-dec/ttusbdecfe.h  |    0
+ drivers/media/{video => usb}/usbvision/Kconfig     |    2 +-
+ drivers/media/{video => usb}/usbvision/Makefile    |    4 +-
+ .../{video => usb}/usbvision/usbvision-cards.c     |    0
+ .../{video => usb}/usbvision/usbvision-cards.h     |    0
+ .../{video => usb}/usbvision/usbvision-core.c      |    0
+ .../media/{video => usb}/usbvision/usbvision-i2c.c |    0
+ .../{video => usb}/usbvision/usbvision-video.c     |   42 +-
+ drivers/media/{video => usb}/usbvision/usbvision.h |    0
+ drivers/media/{video => usb}/uvc/Kconfig           |    0
+ drivers/media/{video => usb}/uvc/Makefile          |    0
+ drivers/media/{video => usb}/uvc/uvc_ctrl.c        |    0
+ drivers/media/{video => usb}/uvc/uvc_debugfs.c     |    0
+ drivers/media/{video => usb}/uvc/uvc_driver.c      |   40 +-
+ drivers/media/{video => usb}/uvc/uvc_entity.c      |    0
+ drivers/media/{video => usb}/uvc/uvc_isight.c      |    0
+ drivers/media/{video => usb}/uvc/uvc_queue.c       |    0
+ drivers/media/{video => usb}/uvc/uvc_status.c      |    0
+ drivers/media/{video => usb}/uvc/uvc_v4l2.c        |    0
+ drivers/media/{video => usb}/uvc/uvc_video.c       |   30 +-
+ drivers/media/{video => usb}/uvc/uvcvideo.h        |    9 +
+ drivers/media/usb/zr364xx/Kconfig                  |   14 +
+ drivers/media/usb/zr364xx/Makefile                 |    2 +
+ drivers/media/{video => usb/zr364xx}/zr364xx.c     |    0
+ drivers/media/v4l2-core/Kconfig                    |   81 +
+ drivers/media/v4l2-core/Makefile                   |   35 +
+ drivers/media/{video => v4l2-core}/tuner-core.c    |    0
+ drivers/media/{video => v4l2-core}/v4l2-common.c   |  360 +-
+ .../{video => v4l2-core}/v4l2-compat-ioctl32.c     |   57 +
+ drivers/media/{video => v4l2-core}/v4l2-ctrls.c    |  174 +-
+ drivers/media/{video => v4l2-core}/v4l2-dev.c      |   51 +-
+ drivers/media/{video => v4l2-core}/v4l2-device.c   |    0
+ drivers/media/{video => v4l2-core}/v4l2-event.c    |    0
+ drivers/media/{video => v4l2-core}/v4l2-fh.c       |    0
+ .../media/{video => v4l2-core}/v4l2-int-device.c   |    0
+ drivers/media/{video => v4l2-core}/v4l2-ioctl.c    |   21 +-
+ drivers/media/{video => v4l2-core}/v4l2-mem2mem.c  |    6 +-
+ drivers/media/{video => v4l2-core}/v4l2-subdev.c   |    6 +
+ drivers/media/{video => v4l2-core}/videobuf-core.c |    0
+ .../{video => v4l2-core}/videobuf-dma-contig.c     |    0
+ .../media/{video => v4l2-core}/videobuf-dma-sg.c   |    0
+ drivers/media/{video => v4l2-core}/videobuf-dvb.c  |   11 +-
+ .../media/{video => v4l2-core}/videobuf-vmalloc.c  |    0
+ .../media/{video => v4l2-core}/videobuf2-core.c    |   21 +-
+ .../{video => v4l2-core}/videobuf2-dma-contig.c    |    0
+ .../media/{video => v4l2-core}/videobuf2-dma-sg.c  |    0
+ .../media/{video => v4l2-core}/videobuf2-memops.c  |    0
+ .../media/{video => v4l2-core}/videobuf2-vmalloc.c |    1 +
+ drivers/media/video/Kconfig                        | 1263 ------
+ drivers/media/video/Makefile                       |  218 -
+ drivers/media/video/bt8xx/Kconfig                  |   27 -
+ drivers/media/video/bt8xx/Makefile                 |   13 -
+ drivers/media/video/cx23885/Kconfig                |   46 -
+ drivers/media/video/tlg2300/Makefile               |    9 -
+ drivers/staging/media/Kconfig                      |    2 -
+ drivers/staging/media/Makefile                     |    1 -
+ drivers/staging/media/as102/Makefile               |    2 +-
+ drivers/staging/media/cxd2099/Makefile             |    6 +-
+ drivers/staging/media/cxd2099/cxd2099.c            |   13 +-
+ drivers/staging/media/dt3155v4l/dt3155v4l.c        |   29 +-
+ drivers/staging/media/easycap/Kconfig              |   30 -
+ drivers/staging/media/easycap/Makefile             |   10 -
+ drivers/staging/media/easycap/README               |  141 -
+ drivers/staging/media/easycap/easycap.h            |  567 ---
+ drivers/staging/media/easycap/easycap_ioctl.c      | 2443 -----------
+ drivers/staging/media/easycap/easycap_low.c        |  968 -----
+ drivers/staging/media/easycap/easycap_main.c       | 4239 --------------------
+ drivers/staging/media/easycap/easycap_settings.c   |  696 ----
+ drivers/staging/media/easycap/easycap_sound.c      |  750 ----
+ drivers/staging/media/easycap/easycap_testcard.c   |  155 -
+ drivers/staging/media/go7007/Makefile              |    6 +-
+ drivers/staging/media/lirc/Kconfig                 |    6 -
+ drivers/staging/media/lirc/Makefile                |    1 -
+ drivers/staging/media/lirc/lirc_ene0100.h          |  169 -
+ drivers/staging/media/lirc/lirc_igorplugusb.c      |    4 +-
+ drivers/staging/media/lirc/lirc_ttusbir.c          |  376 --
+ drivers/staging/media/lirc/lirc_zilog.c            |    3 +-
+ include/linux/dvb/frontend.h                       |   59 +-
+ include/linux/dvb/version.h                        |    2 +-
+ include/linux/omap3isp.h                           |    6 +-
+ include/linux/v4l2-common.h                        |    8 +-
+ include/linux/v4l2-subdev.h                        |   10 +
+ include/linux/videodev2.h                          |   24 +
+ include/media/ad9389b.h                            |   49 +
+ include/media/adv7604.h                            |  153 +
+ include/media/ir-rx51.h                            |   10 +
+ include/media/mt9v032.h                            |    3 +
+ include/media/omap3isp.h                           |   14 +-
+ include/media/saa7146.h                            |    4 -
+ include/media/soc_camera.h                         |   12 +
+ include/media/v4l2-chip-ident.h                    |    6 +
+ include/media/v4l2-common.h                        |   17 +-
+ include/media/v4l2-ctrls.h                         |   23 +
+ include/media/v4l2-dev.h                           |    3 -
+ include/media/v4l2-mem2mem.h                       |    4 +-
+ include/media/v4l2-subdev.h                        |    4 +-
+ include/media/videobuf-dvb.h                       |    4 +-
+ include/sound/tea575x-tuner.h                      |    4 +
+ sound/i2c/other/tea575x-tuner.c                    |  200 +-
+ sound/pci/Kconfig                                  |    4 +-
+ 1615 files changed, 34040 insertions(+), 24099 deletions(-)
+ create mode 100644 Documentation/DocBook/media/v4l/pixfmt-yvu420m.xml
+ create mode 100644 arch/arm/plat-mxc/devices/platform-imx27-coda.c
+ create mode 100644 drivers/media/common/b2c2/Kconfig
+ create mode 100644 drivers/media/common/b2c2/Makefile
+ rename drivers/media/{dvb => common}/b2c2/flexcop-common.h (100%)
+ rename drivers/media/{dvb => common}/b2c2/flexcop-eeprom.c (100%)
+ rename drivers/media/{dvb => common}/b2c2/flexcop-fe-tuner.c (100%)
+ rename drivers/media/{dvb => common}/b2c2/flexcop-hw-filter.c (100%)
+ rename drivers/media/{dvb => common}/b2c2/flexcop-i2c.c (100%)
+ rename drivers/media/{dvb => common}/b2c2/flexcop-misc.c (100%)
+ rename drivers/media/{dvb => common}/b2c2/flexcop-reg.h (100%)
+ rename drivers/media/{dvb => common}/b2c2/flexcop-sram.c (100%)
+ rename drivers/media/{dvb => common}/b2c2/flexcop.c (99%)
+ rename drivers/media/{dvb => common}/b2c2/flexcop.h (100%)
+ rename drivers/media/{dvb => common}/b2c2/flexcop_ibi_value_be.h (100%)
+ rename drivers/media/{dvb => common}/b2c2/flexcop_ibi_value_le.h (100%)
+ create mode 100644 drivers/media/common/saa7146/Kconfig
+ create mode 100644 drivers/media/common/saa7146/Makefile
+ rename drivers/media/common/{ => saa7146}/saa7146_core.c (98%)
+ rename drivers/media/common/{ => saa7146}/saa7146_fops.c (94%)
+ rename drivers/media/common/{ => saa7146}/saa7146_hlp.c (100%)
+ rename drivers/media/common/{ => saa7146}/saa7146_i2c.c (100%)
+ rename drivers/media/common/{ => saa7146}/saa7146_vbi.c (100%)
+ rename drivers/media/common/{ => saa7146}/saa7146_video.c (100%)
+ create mode 100644 drivers/media/common/siano/Kconfig
+ rename drivers/media/{dvb => common}/siano/Makefile (57%)
+ rename drivers/media/{dvb => common}/siano/sms-cards.c (100%)
+ rename drivers/media/{dvb => common}/siano/sms-cards.h (100%)
+ rename drivers/media/{dvb => common}/siano/smscoreapi.c (100%)
+ rename drivers/media/{dvb => common}/siano/smscoreapi.h (100%)
+ rename drivers/media/{dvb => common}/siano/smsdvb.c (100%)
+ rename drivers/media/{dvb => common}/siano/smsendian.c (100%)
+ rename drivers/media/{dvb => common}/siano/smsendian.h (100%)
+ rename drivers/media/{dvb => common}/siano/smsir.c (100%)
+ rename drivers/media/{dvb => common}/siano/smsir.h (100%)
+ create mode 100644 drivers/media/dvb-core/Kconfig
+ rename drivers/media/{dvb => }/dvb-core/Makefile (100%)
+ rename drivers/media/{dvb => }/dvb-core/demux.h (100%)
+ rename drivers/media/{dvb => }/dvb-core/dmxdev.c (99%)
+ rename drivers/media/{dvb => }/dvb-core/dmxdev.h (100%)
+ rename drivers/media/{dvb/dvb-usb => dvb-core}/dvb-usb-ids.h (99%)
+ rename drivers/media/{dvb => }/dvb-core/dvb_ca_en50221.c (100%)
+ rename drivers/media/{dvb => }/dvb-core/dvb_ca_en50221.h (100%)
+ rename drivers/media/{dvb => }/dvb-core/dvb_demux.c (98%)
+ rename drivers/media/{dvb => }/dvb-core/dvb_demux.h (100%)
+ rename drivers/media/{dvb => }/dvb-core/dvb_filter.c (100%)
+ rename drivers/media/{dvb => }/dvb-core/dvb_filter.h (100%)
+ rename drivers/media/{dvb => }/dvb-core/dvb_frontend.c (90%)
+ rename drivers/media/{dvb => }/dvb-core/dvb_frontend.h (98%)
+ rename drivers/media/{dvb => }/dvb-core/dvb_math.c (100%)
+ rename drivers/media/{dvb => }/dvb-core/dvb_math.h (100%)
+ rename drivers/media/{dvb => }/dvb-core/dvb_net.c (100%)
+ rename drivers/media/{dvb => }/dvb-core/dvb_net.h (100%)
+ rename drivers/media/{dvb => }/dvb-core/dvb_ringbuffer.c (100%)
+ rename drivers/media/{dvb => }/dvb-core/dvb_ringbuffer.h (100%)
+ rename drivers/media/{dvb => }/dvb-core/dvbdev.c (99%)
+ rename drivers/media/{dvb => }/dvb-core/dvbdev.h (80%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/Kconfig (83%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/Makefile (92%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/a8293.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/a8293.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/af9013.c (86%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/af9013.h (97%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/af9013_priv.h (98%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/af9033.c (88%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/af9033.h (96%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/af9033_priv.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/atbm8830.c (99%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/atbm8830.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/atbm8830_priv.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/au8522.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/au8522_common.c (93%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/au8522_decoder.c (98%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/au8522_dig.c (95%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/au8522_priv.h (93%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/bcm3510.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/bcm3510.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/bcm3510_priv.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/bsbe1-d01a.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/bsbe1.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/bsru6.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/cx22700.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/cx22700.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/cx22702.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/cx22702.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/cx24110.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/cx24110.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/cx24113.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/cx24113.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/cx24116.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/cx24116.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/cx24123.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/cx24123.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/cxd2820r.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/cxd2820r_c.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/cxd2820r_core.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/cxd2820r_priv.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/cxd2820r_t.c (99%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/cxd2820r_t2.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/dib0070.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/dib0070.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/dib0090.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/dib0090.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/dib3000.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/dib3000mb.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/dib3000mb_priv.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/dib3000mc.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/dib3000mc.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/dib7000m.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/dib7000m.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/dib7000p.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/dib7000p.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/dib8000.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/dib8000.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/dib9000.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/dib9000.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/dibx000_common.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/dibx000_common.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/drxd.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/drxd_firm.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/drxd_firm.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/drxd_hard.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/drxd_map_firm.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/drxk.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/drxk_hard.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/drxk_hard.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/drxk_map.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/ds3000.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/ds3000.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/dvb-pll.c (96%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/dvb-pll.h (97%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/dvb_dummy_fe.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/dvb_dummy_fe.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/ec100.c (87%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/ec100.h (95%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/eds1547.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/hd29l2.c (89%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/hd29l2.h (96%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/hd29l2_priv.h (96%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/isl6405.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/isl6405.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/isl6421.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/isl6421.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/isl6423.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/isl6423.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/it913x-fe-priv.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/it913x-fe.c (99%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/it913x-fe.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/itd1000.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/itd1000.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/itd1000_priv.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/ix2505v.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/ix2505v.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/l64781.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/l64781.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/lg2160.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/lg2160.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/lgdt3305.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/lgdt3305.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/lgdt330x.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/lgdt330x.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/lgdt330x_priv.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/lgs8gl5.c (99%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/lgs8gl5.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/lgs8gxx.c (99%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/lgs8gxx.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/lgs8gxx_priv.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/lnbh24.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/lnbp21.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/lnbp21.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/lnbp22.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/lnbp22.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/m88rs2000.c (99%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/m88rs2000.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/mb86a16.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/mb86a16.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/mb86a16_priv.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/mb86a20s.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/mb86a20s.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/mt312.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/mt312.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/mt312_priv.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/mt352.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/mt352.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/mt352_priv.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/nxt200x.c (93%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/nxt200x.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/nxt6000.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/nxt6000.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/nxt6000_priv.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/or51132.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/or51132.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/or51211.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/or51211.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/rtl2830.c (88%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/rtl2830.h (90%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/rtl2830_priv.h (75%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/rtl2832.c (77%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/rtl2832.h (86%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/rtl2832_priv.h (67%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/s5h1409.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/s5h1409.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/s5h1411.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/s5h1411.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/s5h1420.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/s5h1420.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/s5h1420_priv.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/s5h1432.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/s5h1432.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/s921.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/s921.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/si21xx.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/si21xx.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/sp8870.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/sp8870.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/sp887x.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/sp887x.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/stb0899_algo.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/stb0899_cfg.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/stb0899_drv.c (99%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/stb0899_drv.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/stb0899_priv.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/stb0899_reg.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/stb6000.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/stb6000.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/stb6100.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/stb6100.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/stb6100_cfg.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/stb6100_proc.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/stv0288.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/stv0288.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/stv0297.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/stv0297.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/stv0299.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/stv0299.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/stv0367.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/stv0367.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/stv0367_priv.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/stv0367_regs.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/stv0900.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/stv0900_core.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/stv0900_init.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/stv0900_priv.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/stv0900_reg.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/stv0900_sw.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/stv090x.c (99%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/stv090x.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/stv090x_priv.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/stv090x_reg.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/stv6110.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/stv6110.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/stv6110x.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/stv6110x.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/stv6110x_priv.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/stv6110x_reg.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/tda10021.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/tda10023.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/tda1002x.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/tda10048.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/tda10048.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/tda1004x.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/tda1004x.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/tda10071.c (99%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/tda10071.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/tda10071_priv.h (98%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/tda10086.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/tda10086.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/tda18271c2dd.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/tda18271c2dd.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/tda18271c2dd_maps.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/tda665x.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/tda665x.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/tda8083.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/tda8083.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/tda8261.c (86%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/tda8261.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/tda8261_cfg.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/tda826x.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/tda826x.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/tdhd1.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/tua6100.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/tua6100.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/ves1820.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/ves1820.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/ves1x93.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/ves1x93.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/z0194a.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/zl10036.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/zl10036.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/zl10039.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/zl10039.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/zl10353.c (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/zl10353.h (100%)
+ rename drivers/media/{dvb/frontends => dvb-frontends}/zl10353_priv.h (100%)
+ delete mode 100644 drivers/media/dvb/Kconfig
+ delete mode 100644 drivers/media/dvb/Makefile
+ delete mode 100644 drivers/media/dvb/b2c2/Kconfig
+ delete mode 100644 drivers/media/dvb/b2c2/Makefile
+ delete mode 100644 drivers/media/dvb/bt8xx/Kconfig
+ delete mode 100644 drivers/media/dvb/bt8xx/Makefile
+ delete mode 100644 drivers/media/dvb/dm1105/Makefile
+ delete mode 100644 drivers/media/dvb/dvb-usb/Kconfig
+ delete mode 100644 drivers/media/dvb/dvb-usb/Makefile
+ delete mode 100644 drivers/media/dvb/dvb-usb/af9015.c
+ delete mode 100644 drivers/media/dvb/dvb-usb/it913x.c
+ delete mode 100644 drivers/media/dvb/dvb-usb/mxl111sf.c
+ delete mode 100644 drivers/media/dvb/frontends/ec100_priv.h
+ delete mode 100644 drivers/media/dvb/ngene/Kconfig
+ delete mode 100644 drivers/media/dvb/pluto2/Makefile
+ delete mode 100644 drivers/media/dvb/siano/Kconfig
+ delete mode 100644 drivers/media/dvb/ttusb-budget/Makefile
+ rename drivers/media/{dvb => }/firewire/Kconfig (100%)
+ rename drivers/media/{dvb => }/firewire/Makefile (51%)
+ rename drivers/media/{dvb => }/firewire/firedtv-avc.c (100%)
+ rename drivers/media/{dvb => }/firewire/firedtv-ci.c (100%)
+ rename drivers/media/{dvb => }/firewire/firedtv-dvb.c (100%)
+ rename drivers/media/{dvb => }/firewire/firedtv-fe.c (100%)
+ rename drivers/media/{dvb => }/firewire/firedtv-fw.c (100%)
+ rename drivers/media/{dvb => }/firewire/firedtv-rc.c (100%)
+ rename drivers/media/{dvb => }/firewire/firedtv.h (100%)
+ create mode 100644 drivers/media/i2c/Kconfig
+ create mode 100644 drivers/media/i2c/Makefile
+ create mode 100644 drivers/media/i2c/ad9389b.c
+ rename drivers/media/{video => i2c}/adp1653.c (99%)
+ rename drivers/media/{video => i2c}/adv7170.c (100%)
+ rename drivers/media/{video => i2c}/adv7175.c (100%)
+ rename drivers/media/{video => i2c}/adv7180.c (100%)
+ rename drivers/media/{video => i2c}/adv7183.c (100%)
+ rename drivers/media/{video => i2c}/adv7183_regs.h (100%)
+ rename drivers/media/{video => i2c}/adv7343.c (100%)
+ rename drivers/media/{video => i2c}/adv7343_regs.h (100%)
+ rename drivers/media/{video => i2c}/adv7393.c (100%)
+ rename drivers/media/{video => i2c}/adv7393_regs.h (100%)
+ create mode 100644 drivers/media/i2c/adv7604.c
+ rename drivers/media/{video => i2c}/ak881x.c (100%)
+ rename drivers/media/{video => i2c}/aptina-pll.c (100%)
+ rename drivers/media/{video => i2c}/aptina-pll.h (100%)
+ rename drivers/media/{video => i2c}/as3645a.c (99%)
+ rename drivers/media/{video => i2c}/bt819.c (100%)
+ rename drivers/media/{video => i2c}/bt856.c (100%)
+ rename drivers/media/{video => i2c}/bt866.c (100%)
+ rename drivers/media/{video => i2c}/btcx-risc.c (100%)
+ rename drivers/media/{video => i2c}/btcx-risc.h (100%)
+ rename drivers/media/{video => i2c}/cs5345.c (100%)
+ rename drivers/media/{video => i2c}/cs53l32a.c (100%)
+ rename drivers/media/{video => i2c}/cx2341x.c (100%)
+ rename drivers/media/{video => i2c}/cx25840/Kconfig (100%)
+ rename drivers/media/{video => i2c}/cx25840/Makefile (80%)
+ rename drivers/media/{video => i2c}/cx25840/cx25840-audio.c (100%)
+ rename drivers/media/{video => i2c}/cx25840/cx25840-core.c (100%)
+ rename drivers/media/{video => i2c}/cx25840/cx25840-core.h (100%)
+ rename drivers/media/{video => i2c}/cx25840/cx25840-firmware.c (92%)
+ rename drivers/media/{video => i2c}/cx25840/cx25840-ir.c (100%)
+ rename drivers/media/{video => i2c}/cx25840/cx25840-vbi.c (100%)
+ rename drivers/media/{video => i2c}/ir-kbd-i2c.c (100%)
+ rename drivers/media/{video => i2c}/ks0127.c (100%)
+ rename drivers/media/{video => i2c}/ks0127.h (100%)
+ rename drivers/media/{video => i2c}/m52790.c (100%)
+ rename drivers/media/{video => i2c}/m5mols/Kconfig (100%)
+ rename drivers/media/{video => i2c}/m5mols/Makefile (100%)
+ rename drivers/media/{video => i2c}/m5mols/m5mols.h (99%)
+ rename drivers/media/{video => i2c}/m5mols/m5mols_capture.c (100%)
+ rename drivers/media/{video => i2c}/m5mols/m5mols_controls.c (99%)
+ rename drivers/media/{video => i2c}/m5mols/m5mols_core.c (99%)
+ rename drivers/media/{video => i2c}/m5mols/m5mols_reg.h (100%)
+ rename drivers/media/{video => i2c}/msp3400-driver.c (100%)
+ rename drivers/media/{video => i2c}/msp3400-driver.h (100%)
+ rename drivers/media/{video => i2c}/msp3400-kthreads.c (100%)
+ rename drivers/media/{video => i2c}/mt9m032.c (99%)
+ rename drivers/media/{video => i2c}/mt9p031.c (98%)
+ rename drivers/media/{video => i2c}/mt9t001.c (100%)
+ rename drivers/media/{video => i2c}/mt9v011.c (100%)
+ rename drivers/media/{video => i2c}/mt9v032.c (88%)
+ rename drivers/media/{video => i2c}/noon010pc30.c (100%)
+ rename drivers/media/{video => i2c}/ov7670.c (100%)
+ rename drivers/media/{video => i2c}/s5k6aa.c (99%)
+ rename drivers/media/{video => i2c}/saa6588.c (100%)
+ rename drivers/media/{video => i2c}/saa7110.c (100%)
+ rename drivers/media/{video => i2c}/saa7115.c (100%)
+ rename drivers/media/{video => i2c}/saa711x_regs.h (100%)
+ rename drivers/media/{video => i2c}/saa7127.c (99%)
+ rename drivers/media/{video => i2c}/saa717x.c (100%)
+ rename drivers/media/{video => i2c}/saa7185.c (100%)
+ rename drivers/media/{video => i2c}/saa7191.c (100%)
+ rename drivers/media/{video => i2c}/saa7191.h (100%)
+ rename drivers/media/{video => i2c}/smiapp-pll.c (99%)
+ rename drivers/media/{video => i2c}/smiapp-pll.h (98%)
+ rename drivers/media/{video => i2c}/smiapp/Kconfig (100%)
+ rename drivers/media/{video => i2c}/smiapp/Makefile (78%)
+ rename drivers/media/{video => i2c}/smiapp/smiapp-core.c (99%)
+ rename drivers/media/{video => i2c}/smiapp/smiapp-limits.c (99%)
+ rename drivers/media/{video => i2c}/smiapp/smiapp-limits.h (99%)
+ rename drivers/media/{video => i2c}/smiapp/smiapp-quirk.c (99%)
+ rename drivers/media/{video => i2c}/smiapp/smiapp-quirk.h (98%)
+ rename drivers/media/{video => i2c}/smiapp/smiapp-reg-defs.h (99%)
+ rename drivers/media/{video => i2c}/smiapp/smiapp-reg.h (98%)
+ rename drivers/media/{video => i2c}/smiapp/smiapp-regs.c (99%)
+ rename drivers/media/{video => i2c}/smiapp/smiapp-regs.h (100%)
+ rename drivers/media/{video => i2c}/smiapp/smiapp.h (99%)
+ create mode 100644 drivers/media/i2c/soc_camera/Kconfig
+ create mode 100644 drivers/media/i2c/soc_camera/Makefile
+ rename drivers/media/{video => i2c/soc_camera}/imx074.c (95%)
+ rename drivers/media/{video => i2c/soc_camera}/mt9m001.c (97%)
+ rename drivers/media/{video => i2c/soc_camera}/mt9m111.c (96%)
+ rename drivers/media/{video => i2c/soc_camera}/mt9t031.c (98%)
+ rename drivers/media/{video => i2c/soc_camera}/mt9t112.c (98%)
+ rename drivers/media/{video => i2c/soc_camera}/mt9v022.c (94%)
+ rename drivers/media/{video => i2c/soc_camera}/ov2640.c (98%)
+ rename drivers/media/{video => i2c/soc_camera}/ov5642.c (98%)
+ rename drivers/media/{video => i2c/soc_camera}/ov6650.c (98%)
+ rename drivers/media/{video => i2c/soc_camera}/ov772x.c (81%)
+ rename drivers/media/{video => i2c/soc_camera}/ov9640.c (97%)
+ rename drivers/media/{video => i2c/soc_camera}/ov9640.h (100%)
+ rename drivers/media/{video => i2c/soc_camera}/ov9740.c (97%)
+ rename drivers/media/{video => i2c/soc_camera}/rj54n1cb0c.c (98%)
+ rename drivers/media/{video => i2c/soc_camera}/tw9910.c (98%)
+ rename drivers/media/{video => i2c}/sr030pc30.c (100%)
+ rename drivers/media/{video => i2c}/tcm825x.c (99%)
+ rename drivers/media/{video => i2c}/tcm825x.h (99%)
+ rename drivers/media/{video => i2c}/tda7432.c (100%)
+ rename drivers/media/{video => i2c}/tda9840.c (100%)
+ rename drivers/media/{video => i2c}/tea6415c.c (99%)
+ rename drivers/media/{video => i2c}/tea6415c.h (100%)
+ rename drivers/media/{video => i2c}/tea6420.c (100%)
+ rename drivers/media/{video => i2c}/tea6420.h (100%)
+ rename drivers/media/{video => i2c}/ths7303.c (100%)
+ rename drivers/media/{video => i2c}/tlv320aic23b.c (100%)
+ rename drivers/media/{video => i2c}/tvaudio.c (100%)
+ rename drivers/media/{video => i2c}/tveeprom.c (100%)
+ rename drivers/media/{video => i2c}/tvp514x.c (99%)
+ rename drivers/media/{video => i2c}/tvp514x_regs.h (99%)
+ rename drivers/media/{video => i2c}/tvp5150.c (100%)
+ rename drivers/media/{video => i2c}/tvp5150_reg.h (100%)
+ rename drivers/media/{video => i2c}/tvp7002.c (100%)
+ rename drivers/media/{video => i2c}/tvp7002_reg.h (100%)
+ rename drivers/media/{video => i2c}/upd64031a.c (100%)
+ rename drivers/media/{video => i2c}/upd64083.c (100%)
+ rename drivers/media/{video => i2c}/vp27smpx.c (100%)
+ rename drivers/media/{video => i2c}/vpx3220.c (100%)
+ rename drivers/media/{video => i2c}/vs6624.c (100%)
+ rename drivers/media/{video => i2c}/vs6624_regs.h (100%)
+ rename drivers/media/{video => i2c}/wm8739.c (100%)
+ rename drivers/media/{video => i2c}/wm8775.c (100%)
+ create mode 100644 drivers/media/mmc/Kconfig
+ create mode 100644 drivers/media/mmc/Makefile
+ create mode 100644 drivers/media/mmc/siano/Kconfig
+ create mode 100644 drivers/media/mmc/siano/Makefile
+ rename drivers/media/{dvb => mmc}/siano/smssdio.c (100%)
+ create mode 100644 drivers/media/parport/Kconfig
+ create mode 100644 drivers/media/parport/Makefile
+ rename drivers/media/{video => parport}/bw-qcam.c (100%)
+ rename drivers/media/{video => parport}/c-qcam.c (100%)
+ rename drivers/media/{video => parport}/pms.c (100%)
+ rename drivers/media/{video => parport}/w9966.c (100%)
+ create mode 100644 drivers/media/pci/Kconfig
+ create mode 100644 drivers/media/pci/Makefile
+ create mode 100644 drivers/media/pci/b2c2/Kconfig
+ create mode 100644 drivers/media/pci/b2c2/Makefile
+ rename drivers/media/{dvb => pci}/b2c2/flexcop-dma.c (100%)
+ rename drivers/media/{dvb => pci}/b2c2/flexcop-pci.c (100%)
+ create mode 100644 drivers/media/pci/bt8xx/Kconfig
+ create mode 100644 drivers/media/pci/bt8xx/Makefile
+ rename drivers/media/{video => pci}/bt8xx/bt848.h (100%)
+ rename drivers/media/{dvb => pci}/bt8xx/bt878.c (100%)
+ rename drivers/media/{dvb => pci}/bt8xx/bt878.h (100%)
+ rename drivers/media/{video => pci}/bt8xx/bttv-audio-hook.c (100%)
+ rename drivers/media/{video => pci}/bt8xx/bttv-audio-hook.h (100%)
+ rename drivers/media/{video => pci}/bt8xx/bttv-cards.c (100%)
+ rename drivers/media/{video => pci}/bt8xx/bttv-driver.c (100%)
+ rename drivers/media/{video => pci}/bt8xx/bttv-gpio.c (100%)
+ rename drivers/media/{video => pci}/bt8xx/bttv-i2c.c (100%)
+ rename drivers/media/{video => pci}/bt8xx/bttv-if.c (100%)
+ rename drivers/media/{video => pci}/bt8xx/bttv-input.c (100%)
+ rename drivers/media/{video => pci}/bt8xx/bttv-risc.c (100%)
+ rename drivers/media/{video => pci}/bt8xx/bttv-vbi.c (100%)
+ rename drivers/media/{video => pci}/bt8xx/bttv.h (100%)
+ rename drivers/media/{video => pci}/bt8xx/bttvp.h (100%)
+ rename drivers/media/{dvb => pci}/bt8xx/dst.c (100%)
+ rename drivers/media/{dvb => pci}/bt8xx/dst_ca.c (99%)
+ rename drivers/media/{dvb => pci}/bt8xx/dst_ca.h (100%)
+ rename drivers/media/{dvb => pci}/bt8xx/dst_common.h (100%)
+ rename drivers/media/{dvb => pci}/bt8xx/dst_priv.h (100%)
+ rename drivers/media/{dvb => pci}/bt8xx/dvb-bt8xx.c (100%)
+ rename drivers/media/{dvb => pci}/bt8xx/dvb-bt8xx.h (100%)
+ rename drivers/media/{video => pci}/cx18/Kconfig (77%)
+ rename drivers/media/{video => pci}/cx18/Makefile (78%)
+ rename drivers/media/{video => pci}/cx18/cx18-alsa-main.c (100%)
+ rename drivers/media/{video => pci}/cx18/cx18-alsa-mixer.c (100%)
+ rename drivers/media/{video => pci}/cx18/cx18-alsa-mixer.h (100%)
+ rename drivers/media/{video => pci}/cx18/cx18-alsa-pcm.c (100%)
+ rename drivers/media/{video => pci}/cx18/cx18-alsa-pcm.h (100%)
+ rename drivers/media/{video => pci}/cx18/cx18-alsa.h (100%)
+ rename drivers/media/{video => pci}/cx18/cx18-audio.c (100%)
+ rename drivers/media/{video => pci}/cx18/cx18-audio.h (100%)
+ rename drivers/media/{video => pci}/cx18/cx18-av-audio.c (100%)
+ rename drivers/media/{video => pci}/cx18/cx18-av-core.c (100%)
+ rename drivers/media/{video => pci}/cx18/cx18-av-core.h (100%)
+ rename drivers/media/{video => pci}/cx18/cx18-av-firmware.c (99%)
+ rename drivers/media/{video => pci}/cx18/cx18-av-vbi.c (100%)
+ rename drivers/media/{video => pci}/cx18/cx18-cards.c (100%)
+ rename drivers/media/{video => pci}/cx18/cx18-cards.h (100%)
+ rename drivers/media/{video => pci}/cx18/cx18-controls.c (100%)
+ rename drivers/media/{video => pci}/cx18/cx18-controls.h (100%)
+ rename drivers/media/{video => pci}/cx18/cx18-driver.c (99%)
+ rename drivers/media/{video => pci}/cx18/cx18-driver.h (100%)
+ rename drivers/media/{video => pci}/cx18/cx18-dvb.c (99%)
+ rename drivers/media/{video => pci}/cx18/cx18-dvb.h (100%)
+ rename drivers/media/{video => pci}/cx18/cx18-fileops.c (100%)
+ rename drivers/media/{video => pci}/cx18/cx18-fileops.h (100%)
+ rename drivers/media/{video => pci}/cx18/cx18-firmware.c (98%)
+ rename drivers/media/{video => pci}/cx18/cx18-firmware.h (100%)
+ rename drivers/media/{video => pci}/cx18/cx18-gpio.c (100%)
+ rename drivers/media/{video => pci}/cx18/cx18-gpio.h (100%)
+ rename drivers/media/{video => pci}/cx18/cx18-i2c.c (100%)
+ rename drivers/media/{video => pci}/cx18/cx18-i2c.h (100%)
+ rename drivers/media/{video => pci}/cx18/cx18-io.c (100%)
+ rename drivers/media/{video => pci}/cx18/cx18-io.h (100%)
+ rename drivers/media/{video => pci}/cx18/cx18-ioctl.c (100%)
+ rename drivers/media/{video => pci}/cx18/cx18-ioctl.h (100%)
+ rename drivers/media/{video => pci}/cx18/cx18-irq.c (100%)
+ rename drivers/media/{video => pci}/cx18/cx18-irq.h (100%)
+ rename drivers/media/{video => pci}/cx18/cx18-mailbox.c (100%)
+ rename drivers/media/{video => pci}/cx18/cx18-mailbox.h (100%)
+ rename drivers/media/{video => pci}/cx18/cx18-queue.c (100%)
+ rename drivers/media/{video => pci}/cx18/cx18-queue.h (100%)
+ rename drivers/media/{video => pci}/cx18/cx18-scb.c (100%)
+ rename drivers/media/{video => pci}/cx18/cx18-scb.h (100%)
+ rename drivers/media/{video => pci}/cx18/cx18-streams.c (100%)
+ rename drivers/media/{video => pci}/cx18/cx18-streams.h (100%)
+ rename drivers/media/{video => pci}/cx18/cx18-vbi.c (100%)
+ rename drivers/media/{video => pci}/cx18/cx18-vbi.h (100%)
+ rename drivers/media/{video => pci}/cx18/cx18-version.h (100%)
+ rename drivers/media/{video => pci}/cx18/cx18-video.c (100%)
+ rename drivers/media/{video => pci}/cx18/cx18-video.h (100%)
+ rename drivers/media/{video => pci}/cx18/cx23418.h (100%)
+ create mode 100644 drivers/media/pci/cx23885/Kconfig
+ rename drivers/media/{video => pci}/cx23885/Makefile (72%)
+ rename drivers/media/{video => pci}/cx23885/altera-ci.c (99%)
+ rename drivers/media/{video => pci}/cx23885/altera-ci.h (100%)
+ rename drivers/media/{video => pci}/cx23885/cimax2.c (100%)
+ rename drivers/media/{video => pci}/cx23885/cimax2.h (100%)
+ rename drivers/media/{video => pci}/cx23885/cx23885-417.c (99%)
+ rename drivers/media/{video => pci}/cx23885/cx23885-alsa.c (100%)
+ rename drivers/media/{video => pci}/cx23885/cx23885-av.c (100%)
+ rename drivers/media/{video => pci}/cx23885/cx23885-av.h (100%)
+ rename drivers/media/{video => pci}/cx23885/cx23885-cards.c (98%)
+ rename drivers/media/{video => pci}/cx23885/cx23885-core.c (100%)
+ rename drivers/media/{video => pci}/cx23885/cx23885-dvb.c (95%)
+ rename drivers/media/{video => pci}/cx23885/cx23885-f300.c (100%)
+ rename drivers/media/{video => pci}/cx23885/cx23885-f300.h (100%)
+ rename drivers/media/{video => pci}/cx23885/cx23885-i2c.c (100%)
+ rename drivers/media/{video => pci}/cx23885/cx23885-input.c (96%)
+ rename drivers/media/{video => pci}/cx23885/cx23885-input.h (100%)
+ rename drivers/media/{video => pci}/cx23885/cx23885-ioctl.c (100%)
+ rename drivers/media/{video => pci}/cx23885/cx23885-ioctl.h (100%)
+ rename drivers/media/{video => pci}/cx23885/cx23885-ir.c (100%)
+ rename drivers/media/{video => pci}/cx23885/cx23885-ir.h (100%)
+ rename drivers/media/{video => pci}/cx23885/cx23885-reg.h (100%)
+ rename drivers/media/{video => pci}/cx23885/cx23885-vbi.c (100%)
+ rename drivers/media/{video => pci}/cx23885/cx23885-video.c (100%)
+ rename drivers/media/{video => pci}/cx23885/cx23885.h (99%)
+ rename drivers/media/{video => pci}/cx23885/cx23888-ir.c (100%)
+ rename drivers/media/{video => pci}/cx23885/cx23888-ir.h (100%)
+ rename drivers/media/{video => pci}/cx23885/netup-eeprom.c (100%)
+ rename drivers/media/{video => pci}/cx23885/netup-eeprom.h (100%)
+ rename drivers/media/{video => pci}/cx23885/netup-init.c (100%)
+ rename drivers/media/{video => pci}/cx23885/netup-init.h (100%)
+ rename drivers/media/{video => pci}/cx25821/Kconfig (100%)
+ rename drivers/media/{video => pci}/cx25821/Makefile (67%)
+ rename drivers/media/{video => pci}/cx25821/cx25821-alsa.c (100%)
+ rename drivers/media/{video => pci}/cx25821/cx25821-audio-upstream.c (100%)
+ rename drivers/media/{video => pci}/cx25821/cx25821-audio-upstream.h (100%)
+ rename drivers/media/{video => pci}/cx25821/cx25821-audio.h (100%)
+ rename drivers/media/{video => pci}/cx25821/cx25821-biffuncs.h (100%)
+ rename drivers/media/{video => pci}/cx25821/cx25821-cards.c (100%)
+ rename drivers/media/{video => pci}/cx25821/cx25821-core.c (100%)
+ rename drivers/media/{video => pci}/cx25821/cx25821-gpio.c (100%)
+ rename drivers/media/{video => pci}/cx25821/cx25821-i2c.c (100%)
+ rename drivers/media/{video => pci}/cx25821/cx25821-medusa-defines.h (100%)
+ rename drivers/media/{video => pci}/cx25821/cx25821-medusa-reg.h (100%)
+ rename drivers/media/{video => pci}/cx25821/cx25821-medusa-video.c (100%)
+ rename drivers/media/{video => pci}/cx25821/cx25821-medusa-video.h (100%)
+ rename drivers/media/{video => pci}/cx25821/cx25821-reg.h (100%)
+ rename drivers/media/{video => pci}/cx25821/cx25821-sram.h (100%)
+ rename drivers/media/{video => pci}/cx25821/cx25821-video-upstream-ch2.c (100%)
+ rename drivers/media/{video => pci}/cx25821/cx25821-video-upstream-ch2.h (100%)
+ rename drivers/media/{video => pci}/cx25821/cx25821-video-upstream.c (100%)
+ rename drivers/media/{video => pci}/cx25821/cx25821-video-upstream.h (100%)
+ rename drivers/media/{video => pci}/cx25821/cx25821-video.c (100%)
+ rename drivers/media/{video => pci}/cx25821/cx25821-video.h (100%)
+ rename drivers/media/{video => pci}/cx25821/cx25821.h (100%)
+ rename drivers/media/{video => pci}/cx88/Kconfig (70%)
+ rename drivers/media/{video => pci}/cx88/Makefile (73%)
+ rename drivers/media/{video => pci}/cx88/cx88-alsa.c (99%)
+ rename drivers/media/{video => pci}/cx88/cx88-blackbird.c (100%)
+ rename drivers/media/{video => pci}/cx88/cx88-cards.c (99%)
+ rename drivers/media/{video => pci}/cx88/cx88-core.c (99%)
+ rename drivers/media/{video => pci}/cx88/cx88-dsp.c (100%)
+ rename drivers/media/{video => pci}/cx88/cx88-dvb.c (99%)
+ rename drivers/media/{video => pci}/cx88/cx88-i2c.c (100%)
+ rename drivers/media/{video => pci}/cx88/cx88-input.c (100%)
+ rename drivers/media/{video => pci}/cx88/cx88-mpeg.c (100%)
+ rename drivers/media/{video => pci}/cx88/cx88-reg.h (100%)
+ rename drivers/media/{video => pci}/cx88/cx88-tvaudio.c (100%)
+ rename drivers/media/{video => pci}/cx88/cx88-vbi.c (100%)
+ rename drivers/media/{video => pci}/cx88/cx88-video.c (100%)
+ rename drivers/media/{video => pci}/cx88/cx88-vp3054-i2c.c (100%)
+ rename drivers/media/{video => pci}/cx88/cx88-vp3054-i2c.h (100%)
+ rename drivers/media/{video => pci}/cx88/cx88.h (99%)
+ rename drivers/media/{dvb => pci}/ddbridge/Kconfig (60%)
+ rename drivers/media/{dvb => pci}/ddbridge/Makefile (61%)
+ rename drivers/media/{dvb => pci}/ddbridge/ddbridge-core.c (99%)
+ rename drivers/media/{dvb => pci}/ddbridge/ddbridge-regs.h (100%)
+ rename drivers/media/{dvb => pci}/ddbridge/ddbridge.h (100%)
+ rename drivers/media/{dvb => pci}/dm1105/Kconfig (57%)
+ create mode 100644 drivers/media/pci/dm1105/Makefile
+ rename drivers/media/{dvb => pci}/dm1105/dm1105.c (100%)
+ rename drivers/media/{video => pci}/ivtv/Kconfig (67%)
+ rename drivers/media/{video => pci}/ivtv/Makefile (53%)
+ create mode 100644 drivers/media/pci/ivtv/ivtv-alsa-main.c
+ create mode 100644 drivers/media/pci/ivtv/ivtv-alsa-mixer.c
+ create mode 100644 drivers/media/pci/ivtv/ivtv-alsa-mixer.h
+ create mode 100644 drivers/media/pci/ivtv/ivtv-alsa-pcm.c
+ create mode 100644 drivers/media/pci/ivtv/ivtv-alsa-pcm.h
+ create mode 100644 drivers/media/pci/ivtv/ivtv-alsa.h
+ rename drivers/media/{video => pci}/ivtv/ivtv-cards.c (100%)
+ rename drivers/media/{video => pci}/ivtv/ivtv-cards.h (100%)
+ rename drivers/media/{video => pci}/ivtv/ivtv-controls.c (100%)
+ rename drivers/media/{video => pci}/ivtv/ivtv-controls.h (100%)
+ rename drivers/media/{video => pci}/ivtv/ivtv-driver.c (98%)
+ rename drivers/media/{video => pci}/ivtv/ivtv-driver.h (98%)
+ rename drivers/media/{video => pci}/ivtv/ivtv-fileops.c (96%)
+ rename drivers/media/{video => pci}/ivtv/ivtv-fileops.h (94%)
+ rename drivers/media/{video => pci}/ivtv/ivtv-firmware.c (98%)
+ rename drivers/media/{video => pci}/ivtv/ivtv-firmware.h (100%)
+ rename drivers/media/{video => pci}/ivtv/ivtv-gpio.c (100%)
+ rename drivers/media/{video => pci}/ivtv/ivtv-gpio.h (100%)
+ rename drivers/media/{video => pci}/ivtv/ivtv-i2c.c (100%)
+ rename drivers/media/{video => pci}/ivtv/ivtv-i2c.h (100%)
+ rename drivers/media/{video => pci}/ivtv/ivtv-ioctl.c (100%)
+ rename drivers/media/{video => pci}/ivtv/ivtv-ioctl.h (100%)
+ rename drivers/media/{video => pci}/ivtv/ivtv-irq.c (95%)
+ rename drivers/media/{video => pci}/ivtv/ivtv-irq.h (100%)
+ rename drivers/media/{video => pci}/ivtv/ivtv-mailbox.c (100%)
+ rename drivers/media/{video => pci}/ivtv/ivtv-mailbox.h (100%)
+ rename drivers/media/{video => pci}/ivtv/ivtv-queue.c (100%)
+ rename drivers/media/{video => pci}/ivtv/ivtv-queue.h (100%)
+ rename drivers/media/{video => pci}/ivtv/ivtv-routing.c (100%)
+ rename drivers/media/{video => pci}/ivtv/ivtv-routing.h (100%)
+ rename drivers/media/{video => pci}/ivtv/ivtv-streams.c (99%)
+ rename drivers/media/{video => pci}/ivtv/ivtv-streams.h (100%)
+ rename drivers/media/{video => pci}/ivtv/ivtv-udma.c (100%)
+ rename drivers/media/{video => pci}/ivtv/ivtv-udma.h (100%)
+ rename drivers/media/{video => pci}/ivtv/ivtv-vbi.c (100%)
+ rename drivers/media/{video => pci}/ivtv/ivtv-vbi.h (100%)
+ rename drivers/media/{video => pci}/ivtv/ivtv-version.h (100%)
+ rename drivers/media/{video => pci}/ivtv/ivtv-yuv.c (100%)
+ rename drivers/media/{video => pci}/ivtv/ivtv-yuv.h (100%)
+ rename drivers/media/{video => pci}/ivtv/ivtvfb.c (100%)
+ rename drivers/media/{dvb => pci}/mantis/Kconfig (62%)
+ rename drivers/media/{dvb => pci}/mantis/Makefile (88%)
+ rename drivers/media/{dvb => pci}/mantis/hopper_cards.c (100%)
+ rename drivers/media/{dvb => pci}/mantis/hopper_vp3028.c (100%)
+ rename drivers/media/{dvb => pci}/mantis/hopper_vp3028.h (100%)
+ rename drivers/media/{dvb => pci}/mantis/mantis_ca.c (100%)
+ rename drivers/media/{dvb => pci}/mantis/mantis_ca.h (100%)
+ rename drivers/media/{dvb => pci}/mantis/mantis_cards.c (99%)
+ rename drivers/media/{dvb => pci}/mantis/mantis_common.h (100%)
+ rename drivers/media/{dvb => pci}/mantis/mantis_core.c (99%)
+ rename drivers/media/{dvb => pci}/mantis/mantis_core.h (100%)
+ rename drivers/media/{dvb => pci}/mantis/mantis_dma.c (100%)
+ rename drivers/media/{dvb => pci}/mantis/mantis_dma.h (100%)
+ rename drivers/media/{dvb => pci}/mantis/mantis_dvb.c (98%)
+ rename drivers/media/{dvb => pci}/mantis/mantis_dvb.h (100%)
+ rename drivers/media/{dvb => pci}/mantis/mantis_evm.c (100%)
+ rename drivers/media/{dvb => pci}/mantis/mantis_hif.c (100%)
+ rename drivers/media/{dvb => pci}/mantis/mantis_hif.h (100%)
+ rename drivers/media/{dvb => pci}/mantis/mantis_i2c.c (100%)
+ rename drivers/media/{dvb => pci}/mantis/mantis_i2c.h (100%)
+ rename drivers/media/{dvb => pci}/mantis/mantis_input.c (100%)
+ rename drivers/media/{dvb => pci}/mantis/mantis_ioc.c (100%)
+ rename drivers/media/{dvb => pci}/mantis/mantis_ioc.h (100%)
+ rename drivers/media/{dvb => pci}/mantis/mantis_link.h (100%)
+ rename drivers/media/{dvb => pci}/mantis/mantis_pci.c (100%)
+ rename drivers/media/{dvb => pci}/mantis/mantis_pci.h (100%)
+ rename drivers/media/{dvb => pci}/mantis/mantis_pcmcia.c (100%)
+ rename drivers/media/{dvb => pci}/mantis/mantis_reg.h (100%)
+ rename drivers/media/{dvb => pci}/mantis/mantis_uart.c (100%)
+ rename drivers/media/{dvb => pci}/mantis/mantis_uart.h (100%)
+ rename drivers/media/{dvb => pci}/mantis/mantis_vp1033.c (100%)
+ rename drivers/media/{dvb => pci}/mantis/mantis_vp1033.h (100%)
+ rename drivers/media/{dvb => pci}/mantis/mantis_vp1034.c (100%)
+ rename drivers/media/{dvb => pci}/mantis/mantis_vp1034.h (100%)
+ rename drivers/media/{dvb => pci}/mantis/mantis_vp1041.c (100%)
+ rename drivers/media/{dvb => pci}/mantis/mantis_vp1041.h (100%)
+ rename drivers/media/{dvb => pci}/mantis/mantis_vp2033.c (100%)
+ rename drivers/media/{dvb => pci}/mantis/mantis_vp2033.h (100%)
+ rename drivers/media/{dvb => pci}/mantis/mantis_vp2040.c (100%)
+ rename drivers/media/{dvb => pci}/mantis/mantis_vp2040.h (100%)
+ rename drivers/media/{dvb => pci}/mantis/mantis_vp3028.c (100%)
+ rename drivers/media/{dvb => pci}/mantis/mantis_vp3028.h (100%)
+ rename drivers/media/{dvb => pci}/mantis/mantis_vp3030.c (100%)
+ rename drivers/media/{dvb => pci}/mantis/mantis_vp3030.h (100%)
+ create mode 100644 drivers/media/pci/meye/Kconfig
+ create mode 100644 drivers/media/pci/meye/Makefile
+ rename drivers/media/{video => pci/meye}/meye.c (100%)
+ rename drivers/media/{video => pci/meye}/meye.h (100%)
+ create mode 100644 drivers/media/pci/ngene/Kconfig
+ rename drivers/media/{dvb => pci}/ngene/Makefile (63%)
+ rename drivers/media/{dvb => pci}/ngene/ngene-cards.c (71%)
+ rename drivers/media/{dvb => pci}/ngene/ngene-core.c (98%)
+ rename drivers/media/{dvb => pci}/ngene/ngene-dvb.c (100%)
+ rename drivers/media/{dvb => pci}/ngene/ngene-i2c.c (100%)
+ rename drivers/media/{dvb => pci}/ngene/ngene.h (100%)
+ rename drivers/media/{dvb => pci}/pluto2/Kconfig (100%)
+ create mode 100644 drivers/media/pci/pluto2/Makefile
+ rename drivers/media/{dvb => pci}/pluto2/pluto2.c (100%)
+ rename drivers/media/{dvb => pci}/pt1/Kconfig (100%)
+ rename drivers/media/{dvb => pci}/pt1/Makefile (56%)
+ rename drivers/media/{dvb => pci}/pt1/pt1.c (100%)
+ rename drivers/media/{dvb => pci}/pt1/va1j5jf8007s.c (98%)
+ rename drivers/media/{dvb => pci}/pt1/va1j5jf8007s.h (100%)
+ rename drivers/media/{dvb => pci}/pt1/va1j5jf8007t.c (100%)
+ rename drivers/media/{dvb => pci}/pt1/va1j5jf8007t.h (100%)
+ rename drivers/media/{video => pci}/saa7134/Kconfig (56%)
+ rename drivers/media/{video => pci}/saa7134/Makefile (54%)
+ rename drivers/media/{video => pci}/saa7134/saa6752hs.c (100%)
+ rename drivers/media/{video => pci}/saa7134/saa7134-alsa.c (100%)
+ rename drivers/media/{video => pci}/saa7134/saa7134-cards.c (100%)
+ rename drivers/media/{video => pci}/saa7134/saa7134-core.c (100%)
+ rename drivers/media/{video => pci}/saa7134/saa7134-dvb.c (99%)
+ rename drivers/media/{video => pci}/saa7134/saa7134-empress.c (100%)
+ rename drivers/media/{video => pci}/saa7134/saa7134-i2c.c (100%)
+ rename drivers/media/{video => pci}/saa7134/saa7134-input.c (99%)
+ rename drivers/media/{video => pci}/saa7134/saa7134-reg.h (100%)
+ rename drivers/media/{video => pci}/saa7134/saa7134-ts.c (100%)
+ rename drivers/media/{video => pci}/saa7134/saa7134-tvaudio.c (100%)
+ rename drivers/media/{video => pci}/saa7134/saa7134-vbi.c (100%)
+ rename drivers/media/{video => pci}/saa7134/saa7134-video.c (100%)
+ rename drivers/media/{video => pci}/saa7134/saa7134.h (99%)
+ create mode 100644 drivers/media/pci/saa7146/Kconfig
+ create mode 100644 drivers/media/pci/saa7146/Makefile
+ rename drivers/media/{video => pci/saa7146}/hexium_gemini.c (100%)
+ rename drivers/media/{video => pci/saa7146}/hexium_orion.c (100%)
+ rename drivers/media/{video => pci/saa7146}/mxb.c (100%)
+ rename drivers/media/{video => pci}/saa7164/Kconfig (62%)
+ rename drivers/media/{video => pci}/saa7164/Makefile (57%)
+ rename drivers/media/{video => pci}/saa7164/saa7164-api.c (98%)
+ rename drivers/media/{video => pci}/saa7164/saa7164-buffer.c (100%)
+ rename drivers/media/{video => pci}/saa7164/saa7164-bus.c (100%)
+ rename drivers/media/{video => pci}/saa7164/saa7164-cards.c (100%)
+ rename drivers/media/{video => pci}/saa7164/saa7164-cmd.c (100%)
+ rename drivers/media/{video => pci}/saa7164/saa7164-core.c (96%)
+ rename drivers/media/{video => pci}/saa7164/saa7164-dvb.c (100%)
+ rename drivers/media/{video => pci}/saa7164/saa7164-encoder.c (100%)
+ rename drivers/media/{video => pci}/saa7164/saa7164-fw.c (100%)
+ rename drivers/media/{video => pci}/saa7164/saa7164-i2c.c (100%)
+ rename drivers/media/{video => pci}/saa7164/saa7164-reg.h (100%)
+ rename drivers/media/{video => pci}/saa7164/saa7164-types.h (100%)
+ rename drivers/media/{video => pci}/saa7164/saa7164-vbi.c (100%)
+ rename drivers/media/{video => pci}/saa7164/saa7164.h (99%)
+ create mode 100644 drivers/media/pci/sta2x11/Kconfig
+ create mode 100644 drivers/media/pci/sta2x11/Makefile
+ rename drivers/media/{video => pci/sta2x11}/sta2x11_vip.c (100%)
+ rename drivers/media/{video => pci/sta2x11}/sta2x11_vip.h (100%)
+ rename drivers/media/{dvb => pci}/ttpci/Kconfig (66%)
+ rename drivers/media/{dvb => pci}/ttpci/Makefile (82%)
+ rename drivers/media/{dvb => pci}/ttpci/av7110.c (100%)
+ rename drivers/media/{dvb => pci}/ttpci/av7110.h (100%)
+ rename drivers/media/{dvb => pci}/ttpci/av7110_av.c (100%)
+ rename drivers/media/{dvb => pci}/ttpci/av7110_av.h (100%)
+ rename drivers/media/{dvb => pci}/ttpci/av7110_ca.c (100%)
+ rename drivers/media/{dvb => pci}/ttpci/av7110_ca.h (100%)
+ rename drivers/media/{dvb => pci}/ttpci/av7110_hw.c (100%)
+ rename drivers/media/{dvb => pci}/ttpci/av7110_hw.h (100%)
+ rename drivers/media/{dvb => pci}/ttpci/av7110_ipack.c (100%)
+ rename drivers/media/{dvb => pci}/ttpci/av7110_ipack.h (100%)
+ rename drivers/media/{dvb => pci}/ttpci/av7110_ir.c (100%)
+ rename drivers/media/{dvb => pci}/ttpci/av7110_v4l.c (100%)
+ rename drivers/media/{dvb => pci}/ttpci/budget-av.c (100%)
+ rename drivers/media/{dvb => pci}/ttpci/budget-ci.c (100%)
+ rename drivers/media/{dvb => pci}/ttpci/budget-core.c (100%)
+ rename drivers/media/{dvb => pci}/ttpci/budget-patch.c (100%)
+ rename drivers/media/{dvb => pci}/ttpci/budget.c (91%)
+ rename drivers/media/{dvb => pci}/ttpci/budget.h (100%)
+ rename drivers/media/{dvb => pci}/ttpci/ttpci-eeprom.c (100%)
+ rename drivers/media/{dvb => pci}/ttpci/ttpci-eeprom.h (100%)
+ rename drivers/media/{video => pci}/zoran/Kconfig (75%)
+ rename drivers/media/{video => pci}/zoran/Makefile (100%)
+ rename drivers/media/{video => pci}/zoran/videocodec.c (100%)
+ rename drivers/media/{video => pci}/zoran/videocodec.h (100%)
+ rename drivers/media/{video => pci}/zoran/zoran.h (100%)
+ rename drivers/media/{video => pci}/zoran/zoran_card.c (100%)
+ rename drivers/media/{video => pci}/zoran/zoran_card.h (100%)
+ rename drivers/media/{video => pci}/zoran/zoran_device.c (100%)
+ rename drivers/media/{video => pci}/zoran/zoran_device.h (100%)
+ rename drivers/media/{video => pci}/zoran/zoran_driver.c (100%)
+ rename drivers/media/{video => pci}/zoran/zoran_procfs.c (100%)
+ rename drivers/media/{video => pci}/zoran/zoran_procfs.h (100%)
+ rename drivers/media/{video => pci}/zoran/zr36016.c (100%)
+ rename drivers/media/{video => pci}/zoran/zr36016.h (100%)
+ rename drivers/media/{video => pci}/zoran/zr36050.c (100%)
+ rename drivers/media/{video => pci}/zoran/zr36050.h (100%)
+ rename drivers/media/{video => pci}/zoran/zr36057.h (100%)
+ rename drivers/media/{video => pci}/zoran/zr36060.c (100%)
+ rename drivers/media/{video => pci}/zoran/zr36060.h (100%)
+ create mode 100644 drivers/media/platform/Kconfig
+ create mode 100644 drivers/media/platform/Makefile
+ rename drivers/media/{video => platform}/arv.c (100%)
+ rename drivers/media/{video => platform}/blackfin/Kconfig (100%)
+ rename drivers/media/{video => platform}/blackfin/Makefile (100%)
+ rename drivers/media/{video => platform}/blackfin/bfin_capture.c (98%)
+ rename drivers/media/{video => platform}/blackfin/ppi.c (100%)
+ create mode 100644 drivers/media/platform/coda.c
+ create mode 100644 drivers/media/platform/coda.h
+ rename drivers/media/{video => platform}/davinci/Kconfig (97%)
+ rename drivers/media/{video => platform}/davinci/Makefile (100%)
+ rename drivers/media/{video => platform}/davinci/ccdc_hw_device.h (100%)
+ rename drivers/media/{video => platform}/davinci/dm355_ccdc.c (99%)
+ rename drivers/media/{video => platform}/davinci/dm355_ccdc_regs.h (100%)
+ rename drivers/media/{video => platform}/davinci/dm644x_ccdc.c (99%)
+ rename drivers/media/{video => platform}/davinci/dm644x_ccdc_regs.h (100%)
+ rename drivers/media/{video => platform}/davinci/isif.c (99%)
+ rename drivers/media/{video => platform}/davinci/isif_regs.h (100%)
+ rename drivers/media/{video => platform}/davinci/vpbe.c (100%)
+ rename drivers/media/{video => platform}/davinci/vpbe_display.c (99%)
+ rename drivers/media/{video => platform}/davinci/vpbe_osd.c (100%)
+ rename drivers/media/{video => platform}/davinci/vpbe_osd_regs.h (100%)
+ rename drivers/media/{video => platform}/davinci/vpbe_venc.c (100%)
+ rename drivers/media/{video => platform}/davinci/vpbe_venc_regs.h (100%)
+ rename drivers/media/{video => platform}/davinci/vpfe_capture.c (99%)
+ rename drivers/media/{video => platform}/davinci/vpif.c (99%)
+ rename drivers/media/{video => platform}/davinci/vpif.h (100%)
+ rename drivers/media/{video => platform}/davinci/vpif_capture.c (99%)
+ rename drivers/media/{video => platform}/davinci/vpif_capture.h (100%)
+ rename drivers/media/{video => platform}/davinci/vpif_display.c (98%)
+ rename drivers/media/{video => platform}/davinci/vpif_display.h (100%)
+ rename drivers/media/{video => platform}/davinci/vpss.c (99%)
+ create mode 100644 drivers/media/platform/exynos-gsc/Makefile
+ create mode 100644 drivers/media/platform/exynos-gsc/gsc-core.c
+ create mode 100644 drivers/media/platform/exynos-gsc/gsc-core.h
+ create mode 100644 drivers/media/platform/exynos-gsc/gsc-m2m.c
+ create mode 100644 drivers/media/platform/exynos-gsc/gsc-regs.c
+ create mode 100644 drivers/media/platform/exynos-gsc/gsc-regs.h
+ rename drivers/media/{video => platform}/fsl-viu.c (98%)
+ rename drivers/media/{video => platform}/indycam.c (100%)
+ rename drivers/media/{video => platform}/indycam.h (100%)
+ create mode 100644 drivers/media/platform/m2m-deinterlace.c
+ rename drivers/media/{video => platform}/marvell-ccic/Kconfig (100%)
+ rename drivers/media/{video => platform}/marvell-ccic/Makefile (100%)
+ rename drivers/media/{video => platform}/marvell-ccic/cafe-driver.c (100%)
+ rename drivers/media/{video => platform}/marvell-ccic/mcam-core.c (100%)
+ rename drivers/media/{video => platform}/marvell-ccic/mcam-core.h (100%)
+ rename drivers/media/{video => platform}/marvell-ccic/mmp-driver.c (100%)
+ rename drivers/media/{video => platform}/mem2mem_testdev.c (97%)
+ rename drivers/media/{video => platform}/mx2_emmaprp.c (94%)
+ rename drivers/media/{video => platform}/omap/Kconfig (100%)
+ rename drivers/media/{video => platform}/omap/Makefile (81%)
+ rename drivers/media/{video => platform}/omap/omap_vout.c (100%)
+ rename drivers/media/{video => platform}/omap/omap_vout_vrfb.c (100%)
+ rename drivers/media/{video => platform}/omap/omap_vout_vrfb.h (100%)
+ rename drivers/media/{video => platform}/omap/omap_voutdef.h (100%)
+ rename drivers/media/{video => platform}/omap/omap_voutlib.c (100%)
+ rename drivers/media/{video => platform}/omap/omap_voutlib.h (100%)
+ rename drivers/media/{video => platform}/omap24xxcam-dma.c (99%)
+ rename drivers/media/{video => platform}/omap24xxcam.c (99%)
+ rename drivers/media/{video => platform}/omap24xxcam.h (99%)
+ rename drivers/media/{video => platform}/omap3isp/Makefile (100%)
+ rename drivers/media/{video => platform}/omap3isp/cfa_coef_table.h (91%)
+ rename drivers/media/{video => platform}/omap3isp/gamma_table.h (100%)
+ rename drivers/media/{video => platform}/omap3isp/isp.c (98%)
+ rename drivers/media/{video => platform}/omap3isp/isp.h (97%)
+ rename drivers/media/{video => platform}/omap3isp/ispccdc.c (94%)
+ rename drivers/media/{video => platform}/omap3isp/ispccdc.h (83%)
+ rename drivers/media/{video => platform}/omap3isp/ispccp2.c (100%)
+ rename drivers/media/{video => platform}/omap3isp/ispccp2.h (100%)
+ rename drivers/media/{video => platform}/omap3isp/ispcsi2.c (98%)
+ rename drivers/media/{video => platform}/omap3isp/ispcsi2.h (100%)
+ rename drivers/media/{video => platform}/omap3isp/ispcsiphy.c (100%)
+ rename drivers/media/{video => platform}/omap3isp/ispcsiphy.h (100%)
+ rename drivers/media/{video => platform}/omap3isp/isph3a.h (100%)
+ rename drivers/media/{video => platform}/omap3isp/isph3a_aewb.c (96%)
+ rename drivers/media/{video => platform}/omap3isp/isph3a_af.c (96%)
+ rename drivers/media/{video => platform}/omap3isp/isphist.c (98%)
+ rename drivers/media/{video => platform}/omap3isp/isphist.h (100%)
+ rename drivers/media/{video => platform}/omap3isp/isppreview.c (89%)
+ rename drivers/media/{video => platform}/omap3isp/isppreview.h (99%)
+ rename drivers/media/{video => platform}/omap3isp/ispqueue.c (98%)
+ rename drivers/media/{video => platform}/omap3isp/ispqueue.h (100%)
+ rename drivers/media/{video => platform}/omap3isp/ispreg.h (100%)
+ rename drivers/media/{video => platform}/omap3isp/ispresizer.c (99%)
+ rename drivers/media/{video => platform}/omap3isp/ispresizer.h (100%)
+ rename drivers/media/{video => platform}/omap3isp/ispstat.c (100%)
+ rename drivers/media/{video => platform}/omap3isp/ispstat.h (100%)
+ rename drivers/media/{video => platform}/omap3isp/ispvideo.c (96%)
+ rename drivers/media/{video => platform}/omap3isp/ispvideo.h (97%)
+ rename drivers/media/{video => platform}/omap3isp/luma_enhance_table.h (100%)
+ rename drivers/media/{video => platform}/omap3isp/noise_filter_table.h (100%)
+ rename drivers/media/{video => platform}/s5p-fimc/Kconfig (96%)
+ rename drivers/media/{video => platform}/s5p-fimc/Makefile (100%)
+ rename drivers/media/{video => platform}/s5p-fimc/fimc-capture.c (98%)
+ rename drivers/media/{video => platform}/s5p-fimc/fimc-core.c (100%)
+ rename drivers/media/{video => platform}/s5p-fimc/fimc-core.h (99%)
+ rename drivers/media/{video => platform}/s5p-fimc/fimc-lite-reg.c (99%)
+ rename drivers/media/{video => platform}/s5p-fimc/fimc-lite-reg.h (100%)
+ rename drivers/media/{video => platform}/s5p-fimc/fimc-lite.c (98%)
+ rename drivers/media/{video => platform}/s5p-fimc/fimc-lite.h (99%)
+ rename drivers/media/{video => platform}/s5p-fimc/fimc-m2m.c (96%)
+ rename drivers/media/{video => platform}/s5p-fimc/fimc-mdevice.c (99%)
+ rename drivers/media/{video => platform}/s5p-fimc/fimc-mdevice.h (94%)
+ rename drivers/media/{video => platform}/s5p-fimc/fimc-reg.c (99%)
+ rename drivers/media/{video => platform}/s5p-fimc/fimc-reg.h (100%)
+ rename drivers/media/{video => platform}/s5p-fimc/mipi-csis.c (100%)
+ rename drivers/media/{video => platform}/s5p-fimc/mipi-csis.h (100%)
+ rename drivers/media/{video => platform}/s5p-g2d/Makefile (100%)
+ rename drivers/media/{video => platform}/s5p-g2d/g2d-hw.c (100%)
+ rename drivers/media/{video => platform}/s5p-g2d/g2d-regs.h (100%)
+ rename drivers/media/{video => platform}/s5p-g2d/g2d.c (97%)
+ rename drivers/media/{video => platform}/s5p-g2d/g2d.h (100%)
+ rename drivers/media/{video => platform}/s5p-jpeg/Makefile (100%)
+ rename drivers/media/{video => platform}/s5p-jpeg/jpeg-core.c (98%)
+ rename drivers/media/{video => platform}/s5p-jpeg/jpeg-core.h (98%)
+ rename drivers/media/{video => platform}/s5p-jpeg/jpeg-hw.h (99%)
+ rename drivers/media/{video => platform}/s5p-jpeg/jpeg-regs.h (98%)
+ rename drivers/media/{video => platform}/s5p-mfc/Makefile (100%)
+ rename drivers/media/{video => platform}/s5p-mfc/regs-mfc.h (100%)
+ rename drivers/media/{video => platform}/s5p-mfc/s5p_mfc.c (98%)
+ rename drivers/media/{video => platform}/s5p-mfc/s5p_mfc_cmd.c (98%)
+ rename drivers/media/{video => platform}/s5p-mfc/s5p_mfc_cmd.h (93%)
+ rename drivers/media/{video => platform}/s5p-mfc/s5p_mfc_common.h (100%)
+ rename drivers/media/{video => platform}/s5p-mfc/s5p_mfc_ctrl.c (98%)
+ rename drivers/media/{video => platform}/s5p-mfc/s5p_mfc_ctrl.h (93%)
+ rename drivers/media/{video => platform}/s5p-mfc/s5p_mfc_debug.h (95%)
+ rename drivers/media/{video => platform}/s5p-mfc/s5p_mfc_dec.c (99%)
+ rename drivers/media/{video => platform}/s5p-mfc/s5p_mfc_dec.h (93%)
+ rename drivers/media/{video => platform}/s5p-mfc/s5p_mfc_enc.c (99%)
+ rename drivers/media/{video => platform}/s5p-mfc/s5p_mfc_enc.h (93%)
+ rename drivers/media/{video => platform}/s5p-mfc/s5p_mfc_intr.c (97%)
+ rename drivers/media/{video => platform}/s5p-mfc/s5p_mfc_intr.h (93%)
+ rename drivers/media/{video => platform}/s5p-mfc/s5p_mfc_opr.c (99%)
+ rename drivers/media/{video => platform}/s5p-mfc/s5p_mfc_opr.h (98%)
+ rename drivers/media/{video => platform}/s5p-mfc/s5p_mfc_pm.c (98%)
+ rename drivers/media/{video => platform}/s5p-mfc/s5p_mfc_pm.h (92%)
+ rename drivers/media/{video => platform}/s5p-mfc/s5p_mfc_shm.c (96%)
+ rename drivers/media/{video => platform}/s5p-mfc/s5p_mfc_shm.h (98%)
+ rename drivers/media/{video => platform}/s5p-tv/Kconfig (98%)
+ rename drivers/media/{video => platform}/s5p-tv/Makefile (92%)
+ rename drivers/media/{video => platform}/s5p-tv/hdmi_drv.c (99%)
+ rename drivers/media/{video => platform}/s5p-tv/hdmiphy_drv.c (100%)
+ rename drivers/media/{video => platform}/s5p-tv/mixer.h (100%)
+ rename drivers/media/{video => platform}/s5p-tv/mixer_drv.c (98%)
+ rename drivers/media/{video => platform}/s5p-tv/mixer_grp_layer.c (100%)
+ rename drivers/media/{video => platform}/s5p-tv/mixer_reg.c (100%)
+ rename drivers/media/{video => platform}/s5p-tv/mixer_video.c (97%)
+ rename drivers/media/{video => platform}/s5p-tv/mixer_vp_layer.c (100%)
+ rename drivers/media/{video => platform}/s5p-tv/regs-hdmi.h (100%)
+ rename drivers/media/{video => platform}/s5p-tv/regs-mixer.h (100%)
+ rename drivers/media/{video => platform}/s5p-tv/regs-sdo.h (97%)
+ rename drivers/media/{video => platform}/s5p-tv/regs-vp.h (100%)
+ rename drivers/media/{video => platform}/s5p-tv/sdo_drv.c (98%)
+ rename drivers/media/{video => platform}/s5p-tv/sii9234_drv.c (97%)
+ rename drivers/media/{video => platform}/sh_vou.c (98%)
+ create mode 100644 drivers/media/platform/soc_camera/Kconfig
+ create mode 100644 drivers/media/platform/soc_camera/Makefile
+ rename drivers/media/{video => platform/soc_camera}/atmel-isi.c (100%)
+ rename drivers/media/{video => platform/soc_camera}/mx1_camera.c (100%)
+ rename drivers/media/{video => platform/soc_camera}/mx2_camera.c (97%)
+ rename drivers/media/{video => platform/soc_camera}/mx3_camera.c (99%)
+ rename drivers/media/{video => platform/soc_camera}/omap1_camera.c (99%)
+ rename drivers/media/{video => platform/soc_camera}/pxa_camera.c (100%)
+ rename drivers/media/{video => platform/soc_camera}/sh_mobile_ceu_camera.c (100%)
+ rename drivers/media/{video => platform/soc_camera}/sh_mobile_csi2.c (100%)
+ rename drivers/media/{video => platform/soc_camera}/soc_camera.c (92%)
+ rename drivers/media/{video => platform/soc_camera}/soc_camera_platform.c (94%)
+ rename drivers/media/{video => platform/soc_camera}/soc_mediabus.c (100%)
+ rename drivers/media/{video => platform}/timblogiw.c (100%)
+ rename drivers/media/{video => platform}/via-camera.c (100%)
+ rename drivers/media/{video => platform}/via-camera.h (100%)
+ rename drivers/media/{video => platform}/vino.c (100%)
+ rename drivers/media/{video => platform}/vino.h (100%)
+ rename drivers/media/{video => platform}/vivi.c (97%)
+ create mode 100644 drivers/media/rc/ir-rx51.c
+ create mode 100644 drivers/media/rc/ttusbir.c
+ rename drivers/media/{common => }/tuners/Kconfig (72%)
+ rename drivers/media/{common => }/tuners/Makefile (88%)
+ create mode 100644 drivers/media/tuners/e4000.c
+ create mode 100644 drivers/media/tuners/e4000.h
+ create mode 100644 drivers/media/tuners/e4000_priv.h
+ rename drivers/media/{common => }/tuners/fc0011.c (100%)
+ rename drivers/media/{common => }/tuners/fc0011.h (100%)
+ rename drivers/media/{common => }/tuners/fc0012-priv.h (100%)
+ rename drivers/media/{common => }/tuners/fc0012.c (100%)
+ rename drivers/media/{common => }/tuners/fc0012.h (100%)
+ rename drivers/media/{common => }/tuners/fc0013-priv.h (100%)
+ rename drivers/media/{common => }/tuners/fc0013.c (100%)
+ rename drivers/media/{common => }/tuners/fc0013.h (100%)
+ rename drivers/media/{common => }/tuners/fc001x-common.h (100%)
+ create mode 100644 drivers/media/tuners/fc2580.c
+ create mode 100644 drivers/media/tuners/fc2580.h
+ create mode 100644 drivers/media/tuners/fc2580_priv.h
+ rename drivers/media/{common => }/tuners/max2165.c (100%)
+ rename drivers/media/{common => }/tuners/max2165.h (100%)
+ rename drivers/media/{common => }/tuners/max2165_priv.h (100%)
+ rename drivers/media/{common => }/tuners/mc44s803.c (97%)
+ rename drivers/media/{common => }/tuners/mc44s803.h (100%)
+ rename drivers/media/{common => }/tuners/mc44s803_priv.h (100%)
+ rename drivers/media/{common => }/tuners/mt2060.c (100%)
+ rename drivers/media/{common => }/tuners/mt2060.h (100%)
+ rename drivers/media/{common => }/tuners/mt2060_priv.h (100%)
+ rename drivers/media/{common => }/tuners/mt2063.c (100%)
+ rename drivers/media/{common => }/tuners/mt2063.h (100%)
+ rename drivers/media/{common => }/tuners/mt20xx.c (100%)
+ rename drivers/media/{common => }/tuners/mt20xx.h (100%)
+ rename drivers/media/{common => }/tuners/mt2131.c (100%)
+ rename drivers/media/{common => }/tuners/mt2131.h (100%)
+ rename drivers/media/{common => }/tuners/mt2131_priv.h (100%)
+ rename drivers/media/{common => }/tuners/mt2266.c (100%)
+ rename drivers/media/{common => }/tuners/mt2266.h (100%)
+ rename drivers/media/{common => }/tuners/mxl5005s.c (99%)
+ rename drivers/media/{common => }/tuners/mxl5005s.h (100%)
+ rename drivers/media/{common => }/tuners/mxl5007t.c (100%)
+ rename drivers/media/{common => }/tuners/mxl5007t.h (100%)
+ rename drivers/media/{common => }/tuners/qt1010.c (90%)
+ rename drivers/media/{common => }/tuners/qt1010.h (100%)
+ rename drivers/media/{common => }/tuners/qt1010_priv.h (100%)
+ rename drivers/media/{common => }/tuners/tda18212.c (91%)
+ rename drivers/media/{common => }/tuners/tda18212.h (100%)
+ rename drivers/media/{common => }/tuners/tda18218.c (87%)
+ rename drivers/media/{common => }/tuners/tda18218.h (100%)
+ rename drivers/media/{common => }/tuners/tda18218_priv.h (90%)
+ rename drivers/media/{common => }/tuners/tda18271-common.c (99%)
+ rename drivers/media/{common => }/tuners/tda18271-fe.c (100%)
+ rename drivers/media/{common => }/tuners/tda18271-maps.c (100%)
+ rename drivers/media/{common => }/tuners/tda18271-priv.h (100%)
+ rename drivers/media/{common => }/tuners/tda18271.h (100%)
+ rename drivers/media/{common => }/tuners/tda827x.c (100%)
+ rename drivers/media/{common => }/tuners/tda827x.h (100%)
+ rename drivers/media/{common => }/tuners/tda8290.c (100%)
+ rename drivers/media/{common => }/tuners/tda8290.h (100%)
+ rename drivers/media/{common => }/tuners/tda9887.c (100%)
+ rename drivers/media/{common => }/tuners/tda9887.h (100%)
+ rename drivers/media/{common => }/tuners/tea5761.c (100%)
+ rename drivers/media/{common => }/tuners/tea5761.h (100%)
+ rename drivers/media/{common => }/tuners/tea5767.c (100%)
+ rename drivers/media/{common => }/tuners/tea5767.h (100%)
+ rename drivers/media/{common => }/tuners/tua9001.c (68%)
+ rename drivers/media/{common => }/tuners/tua9001.h (78%)
+ rename drivers/media/{common => }/tuners/tua9001_priv.h (100%)
+ rename drivers/media/{common => }/tuners/tuner-i2c.h (100%)
+ rename drivers/media/{common => }/tuners/tuner-simple.c (100%)
+ rename drivers/media/{common => }/tuners/tuner-simple.h (100%)
+ rename drivers/media/{common => }/tuners/tuner-types.c (100%)
+ rename drivers/media/{common => }/tuners/tuner-xc2028-types.h (100%)
+ rename drivers/media/{common => }/tuners/tuner-xc2028.c (99%)
+ rename drivers/media/{common => }/tuners/tuner-xc2028.h (100%)
+ rename drivers/media/{common => }/tuners/xc4000.c (99%)
+ rename drivers/media/{common => }/tuners/xc4000.h (100%)
+ rename drivers/media/{common => }/tuners/xc5000.c (88%)
+ rename drivers/media/{common => }/tuners/xc5000.h (100%)
+ create mode 100644 drivers/media/usb/Kconfig
+ create mode 100644 drivers/media/usb/Makefile
+ rename drivers/media/{video => usb}/au0828/Kconfig (54%)
+ rename drivers/media/{video => usb}/au0828/Makefile (59%)
+ rename drivers/media/{video => usb}/au0828/au0828-cards.c (99%)
+ rename drivers/media/{video => usb}/au0828/au0828-cards.h (100%)
+ rename drivers/media/{video => usb}/au0828/au0828-core.c (85%)
+ rename drivers/media/{video => usb}/au0828/au0828-dvb.c (90%)
+ rename drivers/media/{video => usb}/au0828/au0828-i2c.c (93%)
+ rename drivers/media/{video => usb}/au0828/au0828-reg.h (98%)
+ rename drivers/media/{video => usb}/au0828/au0828-vbi.c (100%)
+ rename drivers/media/{video => usb}/au0828/au0828-video.c (96%)
+ rename drivers/media/{video => usb}/au0828/au0828.h (98%)
+ create mode 100644 drivers/media/usb/b2c2/Kconfig
+ create mode 100644 drivers/media/usb/b2c2/Makefile
+ rename drivers/media/{dvb => usb}/b2c2/flexcop-usb.c (99%)
+ rename drivers/media/{dvb => usb}/b2c2/flexcop-usb.h (100%)
+ rename drivers/media/{video => usb}/cpia2/Kconfig (100%)
+ rename drivers/media/{video => usb}/cpia2/Makefile (100%)
+ rename drivers/media/{video => usb}/cpia2/cpia2.h (100%)
+ rename drivers/media/{video => usb}/cpia2/cpia2_core.c (99%)
+ rename drivers/media/{video => usb}/cpia2/cpia2_registers.h (100%)
+ rename drivers/media/{video => usb}/cpia2/cpia2_usb.c (100%)
+ rename drivers/media/{video => usb}/cpia2/cpia2_v4l.c (97%)
+ rename drivers/media/{video => usb}/cx231xx/Kconfig (86%)
+ rename drivers/media/{video => usb}/cx231xx/Makefile (65%)
+ rename drivers/media/{video => usb}/cx231xx/cx231xx-417.c (99%)
+ rename drivers/media/{video => usb}/cx231xx/cx231xx-audio.c (100%)
+ rename drivers/media/{video => usb}/cx231xx/cx231xx-avcore.c (100%)
+ rename drivers/media/{video => usb}/cx231xx/cx231xx-cards.c (100%)
+ rename drivers/media/{video => usb}/cx231xx/cx231xx-conf-reg.h (100%)
+ rename drivers/media/{video => usb}/cx231xx/cx231xx-core.c (100%)
+ rename drivers/media/{video => usb}/cx231xx/cx231xx-dif.h (100%)
+ rename drivers/media/{video => usb}/cx231xx/cx231xx-dvb.c (100%)
+ rename drivers/media/{video => usb}/cx231xx/cx231xx-i2c.c (100%)
+ rename drivers/media/{video => usb}/cx231xx/cx231xx-input.c (100%)
+ rename drivers/media/{video => usb}/cx231xx/cx231xx-pcb-cfg.c (100%)
+ rename drivers/media/{video => usb}/cx231xx/cx231xx-pcb-cfg.h (100%)
+ rename drivers/media/{video => usb}/cx231xx/cx231xx-reg.h (100%)
+ rename drivers/media/{video => usb}/cx231xx/cx231xx-vbi.c (100%)
+ rename drivers/media/{video => usb}/cx231xx/cx231xx-vbi.h (100%)
+ rename drivers/media/{video => usb}/cx231xx/cx231xx-video.c (98%)
+ rename drivers/media/{video => usb}/cx231xx/cx231xx.h (100%)
+ create mode 100644 drivers/media/usb/dvb-usb-v2/Kconfig
+ create mode 100644 drivers/media/usb/dvb-usb-v2/Makefile
+ create mode 100644 drivers/media/usb/dvb-usb-v2/af9015.c
+ rename drivers/media/{dvb/dvb-usb => usb/dvb-usb-v2}/af9015.h (78%)
+ rename drivers/media/{dvb/dvb-usb => usb/dvb-usb-v2}/af9035.c (57%)
+ rename drivers/media/{dvb/dvb-usb => usb/dvb-usb-v2}/af9035.h (96%)
+ rename drivers/media/{dvb/dvb-usb => usb/dvb-usb-v2}/anysee.c (67%)
+ rename drivers/media/{dvb/dvb-usb => usb/dvb-usb-v2}/anysee.h (97%)
+ rename drivers/media/{dvb/dvb-usb => usb/dvb-usb-v2}/au6610.c (64%)
+ rename drivers/media/{dvb/dvb-usb => usb/dvb-usb-v2}/au6610.h (80%)
+ rename drivers/media/{dvb/dvb-usb => usb/dvb-usb-v2}/az6007.c (63%)
+ rename drivers/media/{dvb/dvb-usb => usb/dvb-usb-v2}/ce6230.c (58%)
+ rename drivers/media/{dvb/dvb-usb => usb/dvb-usb-v2}/ce6230.h (58%)
+ create mode 100644 drivers/media/usb/dvb-usb-v2/cypress_firmware.c
+ create mode 100644 drivers/media/usb/dvb-usb-v2/cypress_firmware.h
+ create mode 100644 drivers/media/usb/dvb-usb-v2/dvb_usb.h
+ create mode 100644 drivers/media/usb/dvb-usb-v2/dvb_usb_common.h
+ create mode 100644 drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
+ create mode 100644 drivers/media/usb/dvb-usb-v2/dvb_usb_urb.c
+ rename drivers/media/{dvb/dvb-usb => usb/dvb-usb-v2}/ec168.c (57%)
+ rename drivers/media/{dvb/dvb-usb => usb/dvb-usb-v2}/ec168.h (62%)
+ rename drivers/media/{dvb/dvb-usb => usb/dvb-usb-v2}/gl861.c (54%)
+ rename drivers/media/{dvb/dvb-usb => usb/dvb-usb-v2}/gl861.h (59%)
+ create mode 100644 drivers/media/usb/dvb-usb-v2/it913x.c
+ rename drivers/media/{dvb/dvb-usb => usb/dvb-usb-v2}/lmedm04.c (69%)
+ rename drivers/media/{dvb/dvb-usb => usb/dvb-usb-v2}/lmedm04.h (100%)
+ rename drivers/media/{dvb/dvb-usb => usb/dvb-usb-v2}/mxl111sf-demod.c (100%)
+ rename drivers/media/{dvb/dvb-usb => usb/dvb-usb-v2}/mxl111sf-demod.h (100%)
+ rename drivers/media/{dvb/dvb-usb => usb/dvb-usb-v2}/mxl111sf-gpio.c (100%)
+ rename drivers/media/{dvb/dvb-usb => usb/dvb-usb-v2}/mxl111sf-gpio.h (100%)
+ rename drivers/media/{dvb/dvb-usb => usb/dvb-usb-v2}/mxl111sf-i2c.c (100%)
+ rename drivers/media/{dvb/dvb-usb => usb/dvb-usb-v2}/mxl111sf-i2c.h (100%)
+ rename drivers/media/{dvb/dvb-usb => usb/dvb-usb-v2}/mxl111sf-phy.c (100%)
+ rename drivers/media/{dvb/dvb-usb => usb/dvb-usb-v2}/mxl111sf-phy.h (100%)
+ rename drivers/media/{dvb/dvb-usb => usb/dvb-usb-v2}/mxl111sf-reg.h (100%)
+ rename drivers/media/{dvb/dvb-usb => usb/dvb-usb-v2}/mxl111sf-tuner.c (99%)
+ rename drivers/media/{dvb/dvb-usb => usb/dvb-usb-v2}/mxl111sf-tuner.h (100%)
+ create mode 100644 drivers/media/usb/dvb-usb-v2/mxl111sf.c
+ rename drivers/media/{dvb/dvb-usb => usb/dvb-usb-v2}/mxl111sf.h (98%)
+ rename drivers/media/{dvb/dvb-usb => usb/dvb-usb-v2}/rtl28xxu.c (66%)
+ rename drivers/media/{dvb/dvb-usb => usb/dvb-usb-v2}/rtl28xxu.h (91%)
+ create mode 100644 drivers/media/usb/dvb-usb-v2/usb_urb.c
+ create mode 100644 drivers/media/usb/dvb-usb/Kconfig
+ create mode 100644 drivers/media/usb/dvb-usb/Makefile
+ rename drivers/media/{dvb => usb}/dvb-usb/a800.c (100%)
+ rename drivers/media/{dvb => usb}/dvb-usb/af9005-fe.c (100%)
+ rename drivers/media/{dvb => usb}/dvb-usb/af9005-remote.c (100%)
+ rename drivers/media/{dvb => usb}/dvb-usb/af9005-script.h (100%)
+ rename drivers/media/{dvb => usb}/dvb-usb/af9005.c (100%)
+ rename drivers/media/{dvb => usb}/dvb-usb/af9005.h (100%)
+ rename drivers/media/{dvb => usb}/dvb-usb/az6027.c (100%)
+ rename drivers/media/{dvb => usb}/dvb-usb/az6027.h (100%)
+ rename drivers/media/{dvb => usb}/dvb-usb/cinergyT2-core.c (100%)
+ rename drivers/media/{dvb => usb}/dvb-usb/cinergyT2-fe.c (100%)
+ rename drivers/media/{dvb => usb}/dvb-usb/cinergyT2.h (100%)
+ rename drivers/media/{dvb => usb}/dvb-usb/cxusb.c (100%)
+ rename drivers/media/{dvb => usb}/dvb-usb/cxusb.h (100%)
+ rename drivers/media/{dvb => usb}/dvb-usb/dib0700.h (100%)
+ rename drivers/media/{dvb => usb}/dvb-usb/dib0700_core.c (99%)
+ rename drivers/media/{dvb => usb}/dvb-usb/dib0700_devices.c (100%)
+ rename drivers/media/{dvb => usb}/dvb-usb/dib07x0.h (100%)
+ rename drivers/media/{dvb => usb}/dvb-usb/dibusb-common.c (100%)
+ rename drivers/media/{dvb => usb}/dvb-usb/dibusb-mb.c (100%)
+ rename drivers/media/{dvb => usb}/dvb-usb/dibusb-mc.c (100%)
+ rename drivers/media/{dvb => usb}/dvb-usb/dibusb.h (100%)
+ rename drivers/media/{dvb => usb}/dvb-usb/digitv.c (100%)
+ rename drivers/media/{dvb => usb}/dvb-usb/digitv.h (100%)
+ rename drivers/media/{dvb => usb}/dvb-usb/dtt200u-fe.c (100%)
+ rename drivers/media/{dvb => usb}/dvb-usb/dtt200u.c (100%)
+ rename drivers/media/{dvb => usb}/dvb-usb/dtt200u.h (100%)
+ rename drivers/media/{dvb => usb}/dvb-usb/dtv5100.c (100%)
+ rename drivers/media/{dvb => usb}/dvb-usb/dtv5100.h (100%)
+ rename drivers/media/{dvb => usb}/dvb-usb/dvb-usb-common.h (100%)
+ rename drivers/media/{dvb => usb}/dvb-usb/dvb-usb-dvb.c (99%)
+ rename drivers/media/{dvb => usb}/dvb-usb/dvb-usb-firmware.c (100%)
+ rename drivers/media/{dvb => usb}/dvb-usb/dvb-usb-i2c.c (100%)
+ rename drivers/media/{dvb => usb}/dvb-usb/dvb-usb-init.c (100%)
+ rename drivers/media/{dvb => usb}/dvb-usb/dvb-usb-remote.c (100%)
+ rename drivers/media/{dvb => usb}/dvb-usb/dvb-usb-urb.c (100%)
+ rename drivers/media/{dvb => usb}/dvb-usb/dvb-usb.h (99%)
+ rename drivers/media/{dvb => usb}/dvb-usb/dw2102.c (100%)
+ rename drivers/media/{dvb => usb}/dvb-usb/dw2102.h (100%)
+ rename drivers/media/{dvb => usb}/dvb-usb/friio-fe.c (100%)
+ rename drivers/media/{dvb => usb}/dvb-usb/friio.c (100%)
+ rename drivers/media/{dvb => usb}/dvb-usb/friio.h (100%)
+ rename drivers/media/{dvb => usb}/dvb-usb/gp8psk-fe.c (100%)
+ rename drivers/media/{dvb => usb}/dvb-usb/gp8psk.c (100%)
+ rename drivers/media/{dvb => usb}/dvb-usb/gp8psk.h (100%)
+ rename drivers/media/{dvb => usb}/dvb-usb/m920x.c (100%)
+ rename drivers/media/{dvb => usb}/dvb-usb/m920x.h (100%)
+ rename drivers/media/{dvb => usb}/dvb-usb/nova-t-usb2.c (100%)
+ rename drivers/media/{dvb => usb}/dvb-usb/opera1.c (100%)
+ rename drivers/media/{dvb => usb}/dvb-usb/pctv452e.c (99%)
+ rename drivers/media/{dvb => usb}/dvb-usb/technisat-usb2.c (100%)
+ rename drivers/media/{dvb => usb}/dvb-usb/ttusb2.c (99%)
+ rename drivers/media/{dvb => usb}/dvb-usb/ttusb2.h (100%)
+ rename drivers/media/{dvb => usb}/dvb-usb/umt-010.c (100%)
+ rename drivers/media/{dvb => usb}/dvb-usb/usb-urb.c (100%)
+ rename drivers/media/{dvb => usb}/dvb-usb/vp702x-fe.c (100%)
+ rename drivers/media/{dvb => usb}/dvb-usb/vp702x.c (100%)
+ rename drivers/media/{dvb => usb}/dvb-usb/vp702x.h (100%)
+ rename drivers/media/{dvb => usb}/dvb-usb/vp7045-fe.c (100%)
+ rename drivers/media/{dvb => usb}/dvb-usb/vp7045.c (100%)
+ rename drivers/media/{dvb => usb}/dvb-usb/vp7045.h (100%)
+ rename drivers/media/{video => usb}/em28xx/Kconfig (67%)
+ rename drivers/media/{video => usb}/em28xx/Makefile (57%)
+ rename drivers/media/{video => usb}/em28xx/em28xx-audio.c (99%)
+ rename drivers/media/{video => usb}/em28xx/em28xx-cards.c (100%)
+ rename drivers/media/{video => usb}/em28xx/em28xx-core.c (99%)
+ rename drivers/media/{video => usb}/em28xx/em28xx-dvb.c (100%)
+ rename drivers/media/{video => usb}/em28xx/em28xx-i2c.c (100%)
+ rename drivers/media/{video => usb}/em28xx/em28xx-input.c (100%)
+ rename drivers/media/{video => usb}/em28xx/em28xx-reg.h (100%)
+ rename drivers/media/{video => usb}/em28xx/em28xx-vbi.c (100%)
+ rename drivers/media/{video => usb}/em28xx/em28xx-video.c (98%)
+ rename drivers/media/{video => usb}/em28xx/em28xx.h (100%)
+ rename drivers/media/{video => usb}/gspca/Kconfig (98%)
+ rename drivers/media/{video => usb}/gspca/Makefile (100%)
+ rename drivers/media/{video => usb}/gspca/autogain_functions.c (100%)
+ rename drivers/media/{video => usb}/gspca/autogain_functions.h (100%)
+ rename drivers/media/{video => usb}/gspca/benq.c (100%)
+ rename drivers/media/{video => usb}/gspca/conex.c (100%)
+ rename drivers/media/{video => usb}/gspca/cpia1.c (99%)
+ rename drivers/media/{video => usb}/gspca/etoms.c (100%)
+ rename drivers/media/{video => usb}/gspca/finepix.c (92%)
+ rename drivers/media/{video => usb}/gspca/gl860/Kconfig (100%)
+ rename drivers/media/{video => usb}/gspca/gl860/Makefile (75%)
+ rename drivers/media/{video => usb}/gspca/gl860/gl860-mi1320.c (100%)
+ rename drivers/media/{video => usb}/gspca/gl860/gl860-mi2020.c (100%)
+ rename drivers/media/{video => usb}/gspca/gl860/gl860-ov2640.c (100%)
+ rename drivers/media/{video => usb}/gspca/gl860/gl860-ov9655.c (100%)
+ rename drivers/media/{video => usb}/gspca/gl860/gl860.c (100%)
+ rename drivers/media/{video => usb}/gspca/gl860/gl860.h (100%)
+ rename drivers/media/{video => usb}/gspca/gspca.c (99%)
+ rename drivers/media/{video => usb}/gspca/gspca.h (100%)
+ rename drivers/media/{video => usb}/gspca/jeilinj.c (100%)
+ rename drivers/media/{video => usb}/gspca/jl2005bcd.c (95%)
+ rename drivers/media/{video => usb}/gspca/jpeg.h (100%)
+ rename drivers/media/{video => usb}/gspca/kinect.c (100%)
+ rename drivers/media/{video => usb}/gspca/konica.c (100%)
+ rename drivers/media/{video => usb}/gspca/m5602/Kconfig (100%)
+ rename drivers/media/{video => usb}/gspca/m5602/Makefile (80%)
+ rename drivers/media/{video => usb}/gspca/m5602/m5602_bridge.h (100%)
+ rename drivers/media/{video => usb}/gspca/m5602/m5602_core.c (100%)
+ rename drivers/media/{video => usb}/gspca/m5602/m5602_mt9m111.c (100%)
+ rename drivers/media/{video => usb}/gspca/m5602/m5602_mt9m111.h (100%)
+ rename drivers/media/{video => usb}/gspca/m5602/m5602_ov7660.c (100%)
+ rename drivers/media/{video => usb}/gspca/m5602/m5602_ov7660.h (100%)
+ rename drivers/media/{video => usb}/gspca/m5602/m5602_ov9650.c (100%)
+ rename drivers/media/{video => usb}/gspca/m5602/m5602_ov9650.h (100%)
+ rename drivers/media/{video => usb}/gspca/m5602/m5602_po1030.c (100%)
+ rename drivers/media/{video => usb}/gspca/m5602/m5602_po1030.h (100%)
+ rename drivers/media/{video => usb}/gspca/m5602/m5602_s5k4aa.c (100%)
+ rename drivers/media/{video => usb}/gspca/m5602/m5602_s5k4aa.h (100%)
+ rename drivers/media/{video => usb}/gspca/m5602/m5602_s5k83a.c (100%)
+ rename drivers/media/{video => usb}/gspca/m5602/m5602_s5k83a.h (100%)
+ rename drivers/media/{video => usb}/gspca/m5602/m5602_sensor.h (100%)
+ rename drivers/media/{video => usb}/gspca/mars.c (100%)
+ rename drivers/media/{video => usb}/gspca/mr97310a.c (100%)
+ rename drivers/media/{video => usb}/gspca/nw80x.c (100%)
+ rename drivers/media/{video => usb}/gspca/ov519.c (99%)
+ rename drivers/media/{video => usb}/gspca/ov534.c (100%)
+ rename drivers/media/{video => usb}/gspca/ov534_9.c (100%)
+ rename drivers/media/{video => usb}/gspca/pac207.c (100%)
+ rename drivers/media/{video => usb}/gspca/pac7302.c (95%)
+ rename drivers/media/{video => usb}/gspca/pac7311.c (100%)
+ rename drivers/media/{video => usb}/gspca/pac_common.h (100%)
+ rename drivers/media/{video => usb}/gspca/se401.c (100%)
+ rename drivers/media/{video => usb}/gspca/se401.h (100%)
+ rename drivers/media/{video => usb}/gspca/sn9c2028.c (100%)
+ rename drivers/media/{video => usb}/gspca/sn9c2028.h (100%)
+ rename drivers/media/{video => usb}/gspca/sn9c20x.c (99%)
+ rename drivers/media/{video => usb}/gspca/sonixb.c (100%)
+ rename drivers/media/{video => usb}/gspca/sonixj.c (99%)
+ rename drivers/media/{video => usb}/gspca/spca1528.c (100%)
+ rename drivers/media/{video => usb}/gspca/spca500.c (100%)
+ rename drivers/media/{video => usb}/gspca/spca501.c (100%)
+ rename drivers/media/{video => usb}/gspca/spca505.c (100%)
+ rename drivers/media/{video => usb}/gspca/spca506.c (100%)
+ rename drivers/media/{video => usb}/gspca/spca508.c (100%)
+ rename drivers/media/{video => usb}/gspca/spca561.c (100%)
+ rename drivers/media/{video => usb}/gspca/sq905.c (95%)
+ rename drivers/media/{video => usb}/gspca/sq905c.c (91%)
+ rename drivers/media/{video => usb}/gspca/sq930x.c (99%)
+ rename drivers/media/{video => usb}/gspca/stk014.c (100%)
+ rename drivers/media/{video => usb}/gspca/stv0680.c (100%)
+ rename drivers/media/{video => usb}/gspca/stv06xx/Kconfig (100%)
+ rename drivers/media/{video => usb}/gspca/stv06xx/Makefile (78%)
+ rename drivers/media/{video => usb}/gspca/stv06xx/stv06xx.c (100%)
+ rename drivers/media/{video => usb}/gspca/stv06xx/stv06xx.h (100%)
+ rename drivers/media/{video => usb}/gspca/stv06xx/stv06xx_hdcs.c (100%)
+ rename drivers/media/{video => usb}/gspca/stv06xx/stv06xx_hdcs.h (100%)
+ rename drivers/media/{video => usb}/gspca/stv06xx/stv06xx_pb0100.c (100%)
+ rename drivers/media/{video => usb}/gspca/stv06xx/stv06xx_pb0100.h (100%)
+ rename drivers/media/{video => usb}/gspca/stv06xx/stv06xx_sensor.h (100%)
+ rename drivers/media/{video => usb}/gspca/stv06xx/stv06xx_st6422.c (100%)
+ rename drivers/media/{video => usb}/gspca/stv06xx/stv06xx_st6422.h (100%)
+ rename drivers/media/{video => usb}/gspca/stv06xx/stv06xx_vv6410.c (100%)
+ rename drivers/media/{video => usb}/gspca/stv06xx/stv06xx_vv6410.h (100%)
+ rename drivers/media/{video => usb}/gspca/sunplus.c (100%)
+ rename drivers/media/{video => usb}/gspca/t613.c (100%)
+ rename drivers/media/{video => usb}/gspca/topro.c (100%)
+ rename drivers/media/{video => usb}/gspca/tv8532.c (100%)
+ rename drivers/media/{video => usb}/gspca/vc032x.c (99%)
+ rename drivers/media/{video => usb}/gspca/vicam.c (94%)
+ rename drivers/media/{video => usb}/gspca/w996Xcf.c (100%)
+ rename drivers/media/{video => usb}/gspca/xirlink_cit.c (99%)
+ rename drivers/media/{video => usb}/gspca/zc3xx-reg.h (100%)
+ rename drivers/media/{video => usb}/gspca/zc3xx.c (99%)
+ rename drivers/media/{video => usb}/hdpvr/Kconfig (100%)
+ rename drivers/media/{video => usb}/hdpvr/Makefile (81%)
+ rename drivers/media/{video => usb}/hdpvr/hdpvr-control.c (100%)
+ rename drivers/media/{video => usb}/hdpvr/hdpvr-core.c (100%)
+ rename drivers/media/{video => usb}/hdpvr/hdpvr-i2c.c (100%)
+ rename drivers/media/{video => usb}/hdpvr/hdpvr-video.c (100%)
+ rename drivers/media/{video => usb}/hdpvr/hdpvr.h (100%)
+ rename drivers/media/{video => usb}/pvrusb2/Kconfig (82%)
+ rename drivers/media/{video => usb}/pvrusb2/Makefile (80%)
+ rename drivers/media/{video => usb}/pvrusb2/pvrusb2-audio.c (100%)
+ rename drivers/media/{video => usb}/pvrusb2/pvrusb2-audio.h (100%)
+ rename drivers/media/{video => usb}/pvrusb2/pvrusb2-context.c (100%)
+ rename drivers/media/{video => usb}/pvrusb2/pvrusb2-context.h (100%)
+ rename drivers/media/{video => usb}/pvrusb2/pvrusb2-cs53l32a.c (100%)
+ rename drivers/media/{video => usb}/pvrusb2/pvrusb2-cs53l32a.h (100%)
+ rename drivers/media/{video => usb}/pvrusb2/pvrusb2-ctrl.c (100%)
+ rename drivers/media/{video => usb}/pvrusb2/pvrusb2-ctrl.h (100%)
+ rename drivers/media/{video => usb}/pvrusb2/pvrusb2-cx2584x-v4l.c (100%)
+ rename drivers/media/{video => usb}/pvrusb2/pvrusb2-cx2584x-v4l.h (100%)
+ rename drivers/media/{video => usb}/pvrusb2/pvrusb2-debug.h (100%)
+ rename drivers/media/{video => usb}/pvrusb2/pvrusb2-debugifc.c (100%)
+ rename drivers/media/{video => usb}/pvrusb2/pvrusb2-debugifc.h (100%)
+ rename drivers/media/{video => usb}/pvrusb2/pvrusb2-devattr.c (97%)
+ rename drivers/media/{video => usb}/pvrusb2/pvrusb2-devattr.h (100%)
+ rename drivers/media/{video => usb}/pvrusb2/pvrusb2-dvb.c (100%)
+ rename drivers/media/{video => usb}/pvrusb2/pvrusb2-dvb.h (100%)
+ rename drivers/media/{video => usb}/pvrusb2/pvrusb2-eeprom.c (100%)
+ rename drivers/media/{video => usb}/pvrusb2/pvrusb2-eeprom.h (100%)
+ rename drivers/media/{video => usb}/pvrusb2/pvrusb2-encoder.c (100%)
+ rename drivers/media/{video => usb}/pvrusb2/pvrusb2-encoder.h (100%)
+ rename drivers/media/{video => usb}/pvrusb2/pvrusb2-fx2-cmd.h (100%)
+ rename drivers/media/{video => usb}/pvrusb2/pvrusb2-hdw-internal.h (100%)
+ rename drivers/media/{video => usb}/pvrusb2/pvrusb2-hdw.c (100%)
+ rename drivers/media/{video => usb}/pvrusb2/pvrusb2-hdw.h (100%)
+ rename drivers/media/{video => usb}/pvrusb2/pvrusb2-i2c-core.c (100%)
+ rename drivers/media/{video => usb}/pvrusb2/pvrusb2-i2c-core.h (100%)
+ rename drivers/media/{video => usb}/pvrusb2/pvrusb2-io.c (100%)
+ rename drivers/media/{video => usb}/pvrusb2/pvrusb2-io.h (100%)
+ rename drivers/media/{video => usb}/pvrusb2/pvrusb2-ioread.c (100%)
+ rename drivers/media/{video => usb}/pvrusb2/pvrusb2-ioread.h (100%)
+ rename drivers/media/{video => usb}/pvrusb2/pvrusb2-main.c (100%)
+ rename drivers/media/{video => usb}/pvrusb2/pvrusb2-std.c (100%)
+ rename drivers/media/{video => usb}/pvrusb2/pvrusb2-std.h (100%)
+ rename drivers/media/{video => usb}/pvrusb2/pvrusb2-sysfs.c (100%)
+ rename drivers/media/{video => usb}/pvrusb2/pvrusb2-sysfs.h (100%)
+ rename drivers/media/{video => usb}/pvrusb2/pvrusb2-util.h (100%)
+ rename drivers/media/{video => usb}/pvrusb2/pvrusb2-v4l2.c (100%)
+ rename drivers/media/{video => usb}/pvrusb2/pvrusb2-v4l2.h (100%)
+ rename drivers/media/{video => usb}/pvrusb2/pvrusb2-video-v4l.c (100%)
+ rename drivers/media/{video => usb}/pvrusb2/pvrusb2-video-v4l.h (100%)
+ rename drivers/media/{video => usb}/pvrusb2/pvrusb2-wm8775.c (100%)
+ rename drivers/media/{video => usb}/pvrusb2/pvrusb2-wm8775.h (100%)
+ rename drivers/media/{video => usb}/pvrusb2/pvrusb2.h (100%)
+ rename drivers/media/{video => usb}/pwc/Kconfig (100%)
+ rename drivers/media/{video => usb}/pwc/Makefile (60%)
+ rename drivers/media/{video => usb}/pwc/philips.txt (100%)
+ rename drivers/media/{video => usb}/pwc/pwc-ctrl.c (100%)
+ rename drivers/media/{video => usb}/pwc/pwc-dec1.c (100%)
+ rename drivers/media/{video => usb}/pwc/pwc-dec1.h (100%)
+ rename drivers/media/{video => usb}/pwc/pwc-dec23.c (100%)
+ rename drivers/media/{video => usb}/pwc/pwc-dec23.h (100%)
+ rename drivers/media/{video => usb}/pwc/pwc-if.c (99%)
+ rename drivers/media/{video => usb}/pwc/pwc-kiara.c (100%)
+ rename drivers/media/{video => usb}/pwc/pwc-kiara.h (100%)
+ rename drivers/media/{video => usb}/pwc/pwc-misc.c (100%)
+ rename drivers/media/{video => usb}/pwc/pwc-nala.h (100%)
+ rename drivers/media/{video => usb}/pwc/pwc-timon.c (100%)
+ rename drivers/media/{video => usb}/pwc/pwc-timon.h (100%)
+ rename drivers/media/{video => usb}/pwc/pwc-uncompress.c (100%)
+ rename drivers/media/{video => usb}/pwc/pwc-v4l.c (100%)
+ rename drivers/media/{video => usb}/pwc/pwc.h (100%)
+ create mode 100644 drivers/media/usb/s2255/Kconfig
+ create mode 100644 drivers/media/usb/s2255/Makefile
+ rename drivers/media/{video => usb/s2255}/s2255drv.c (99%)
+ create mode 100644 drivers/media/usb/siano/Kconfig
+ create mode 100644 drivers/media/usb/siano/Makefile
+ rename drivers/media/{dvb => usb}/siano/smsusb.c (100%)
+ rename drivers/media/{video => usb}/sn9c102/Kconfig (100%)
+ rename drivers/media/{video => usb}/sn9c102/Makefile (100%)
+ rename drivers/media/{video => usb}/sn9c102/sn9c102.h (100%)
+ rename drivers/media/{video => usb}/sn9c102/sn9c102_config.h (100%)
+ rename drivers/media/{video => usb}/sn9c102/sn9c102_core.c (100%)
+ rename drivers/media/{video => usb}/sn9c102/sn9c102_devtable.h (100%)
+ rename drivers/media/{video => usb}/sn9c102/sn9c102_hv7131d.c (100%)
+ rename drivers/media/{video => usb}/sn9c102/sn9c102_hv7131r.c (100%)
+ rename drivers/media/{video => usb}/sn9c102/sn9c102_mi0343.c (100%)
+ rename drivers/media/{video => usb}/sn9c102/sn9c102_mi0360.c (100%)
+ rename drivers/media/{video => usb}/sn9c102/sn9c102_mt9v111.c (100%)
+ rename drivers/media/{video => usb}/sn9c102/sn9c102_ov7630.c (100%)
+ rename drivers/media/{video => usb}/sn9c102/sn9c102_ov7660.c (100%)
+ rename drivers/media/{video => usb}/sn9c102/sn9c102_pas106b.c (100%)
+ rename drivers/media/{video => usb}/sn9c102/sn9c102_pas202bcb.c (100%)
+ rename drivers/media/{video => usb}/sn9c102/sn9c102_sensor.h (100%)
+ rename drivers/media/{video => usb}/sn9c102/sn9c102_tas5110c1b.c (100%)
+ rename drivers/media/{video => usb}/sn9c102/sn9c102_tas5110d.c (100%)
+ rename drivers/media/{video => usb}/sn9c102/sn9c102_tas5130d1b.c (100%)
+ create mode 100644 drivers/media/usb/stk1160/Kconfig
+ create mode 100644 drivers/media/usb/stk1160/Makefile
+ create mode 100644 drivers/media/usb/stk1160/stk1160-ac97.c
+ create mode 100644 drivers/media/usb/stk1160/stk1160-core.c
+ create mode 100644 drivers/media/usb/stk1160/stk1160-i2c.c
+ create mode 100644 drivers/media/usb/stk1160/stk1160-reg.h
+ create mode 100644 drivers/media/usb/stk1160/stk1160-v4l.c
+ create mode 100644 drivers/media/usb/stk1160/stk1160-video.c
+ create mode 100644 drivers/media/usb/stk1160/stk1160.h
+ create mode 100644 drivers/media/usb/stkwebcam/Kconfig
+ create mode 100644 drivers/media/usb/stkwebcam/Makefile
+ rename drivers/media/{video => usb/stkwebcam}/stk-sensor.c (100%)
+ rename drivers/media/{video => usb/stkwebcam}/stk-webcam.c (100%)
+ rename drivers/media/{video => usb/stkwebcam}/stk-webcam.h (100%)
+ rename drivers/media/{video => usb}/tlg2300/Kconfig (100%)
+ create mode 100644 drivers/media/usb/tlg2300/Makefile
+ rename drivers/media/{video => usb}/tlg2300/pd-alsa.c (99%)
+ rename drivers/media/{video => usb}/tlg2300/pd-common.h (100%)
+ rename drivers/media/{video => usb}/tlg2300/pd-dvb.c (100%)
+ rename drivers/media/{video => usb}/tlg2300/pd-main.c (100%)
+ rename drivers/media/{video => usb}/tlg2300/pd-radio.c (100%)
+ rename drivers/media/{video => usb}/tlg2300/pd-video.c (100%)
+ rename drivers/media/{video => usb}/tlg2300/vendorcmds.h (100%)
+ rename drivers/media/{video => usb}/tm6000/Kconfig (100%)
+ rename drivers/media/{video => usb}/tm6000/Makefile (62%)
+ rename drivers/media/{video => usb}/tm6000/tm6000-alsa.c (99%)
+ rename drivers/media/{video => usb}/tm6000/tm6000-cards.c (100%)
+ rename drivers/media/{video => usb}/tm6000/tm6000-core.c (100%)
+ rename drivers/media/{video => usb}/tm6000/tm6000-dvb.c (100%)
+ rename drivers/media/{video => usb}/tm6000/tm6000-i2c.c (100%)
+ rename drivers/media/{video => usb}/tm6000/tm6000-input.c (99%)
+ rename drivers/media/{video => usb}/tm6000/tm6000-regs.h (100%)
+ rename drivers/media/{video => usb}/tm6000/tm6000-stds.c (100%)
+ rename drivers/media/{video => usb}/tm6000/tm6000-usb-isoc.h (100%)
+ rename drivers/media/{video => usb}/tm6000/tm6000-video.c (97%)
+ rename drivers/media/{video => usb}/tm6000/tm6000.h (100%)
+ rename drivers/media/{dvb => usb}/ttusb-budget/Kconfig (56%)
+ create mode 100644 drivers/media/usb/ttusb-budget/Makefile
+ rename drivers/media/{dvb => usb}/ttusb-budget/dvb-ttusb-budget.c (100%)
+ rename drivers/media/{dvb => usb}/ttusb-dec/Kconfig (100%)
+ rename drivers/media/{dvb => usb}/ttusb-dec/Makefile (57%)
+ rename drivers/media/{dvb => usb}/ttusb-dec/ttusb_dec.c (100%)
+ rename drivers/media/{dvb => usb}/ttusb-dec/ttusbdecfe.c (100%)
+ rename drivers/media/{dvb => usb}/ttusb-dec/ttusbdecfe.h (100%)
+ rename drivers/media/{video => usb}/usbvision/Kconfig (88%)
+ rename drivers/media/{video => usb}/usbvision/Makefile (63%)
+ rename drivers/media/{video => usb}/usbvision/usbvision-cards.c (100%)
+ rename drivers/media/{video => usb}/usbvision/usbvision-cards.h (100%)
+ rename drivers/media/{video => usb}/usbvision/usbvision-core.c (100%)
+ rename drivers/media/{video => usb}/usbvision/usbvision-i2c.c (100%)
+ rename drivers/media/{video => usb}/usbvision/usbvision-video.c (97%)
+ rename drivers/media/{video => usb}/usbvision/usbvision.h (100%)
+ rename drivers/media/{video => usb}/uvc/Kconfig (100%)
+ rename drivers/media/{video => usb}/uvc/Makefile (100%)
+ rename drivers/media/{video => usb}/uvc/uvc_ctrl.c (100%)
+ rename drivers/media/{video => usb}/uvc/uvc_debugfs.c (100%)
+ rename drivers/media/{video => usb}/uvc/uvc_driver.c (98%)
+ rename drivers/media/{video => usb}/uvc/uvc_entity.c (100%)
+ rename drivers/media/{video => usb}/uvc/uvc_isight.c (100%)
+ rename drivers/media/{video => usb}/uvc/uvc_queue.c (100%)
+ rename drivers/media/{video => usb}/uvc/uvc_status.c (100%)
+ rename drivers/media/{video => usb}/uvc/uvc_v4l2.c (100%)
+ rename drivers/media/{video => usb}/uvc/uvc_video.c (98%)
+ rename drivers/media/{video => usb}/uvc/uvcvideo.h (98%)
+ create mode 100644 drivers/media/usb/zr364xx/Kconfig
+ create mode 100644 drivers/media/usb/zr364xx/Makefile
+ rename drivers/media/{video => usb/zr364xx}/zr364xx.c (100%)
+ create mode 100644 drivers/media/v4l2-core/Kconfig
+ create mode 100644 drivers/media/v4l2-core/Makefile
+ rename drivers/media/{video => v4l2-core}/tuner-core.c (100%)
+ rename drivers/media/{video => v4l2-core}/v4l2-common.c (62%)
+ rename drivers/media/{video => v4l2-core}/v4l2-compat-ioctl32.c (94%)
+ rename drivers/media/{video => v4l2-core}/v4l2-ctrls.c (95%)
+ rename drivers/media/{video => v4l2-core}/v4l2-dev.c (95%)
+ rename drivers/media/{video => v4l2-core}/v4l2-device.c (100%)
+ rename drivers/media/{video => v4l2-core}/v4l2-event.c (100%)
+ rename drivers/media/{video => v4l2-core}/v4l2-fh.c (100%)
+ rename drivers/media/{video => v4l2-core}/v4l2-int-device.c (100%)
+ rename drivers/media/{video => v4l2-core}/v4l2-ioctl.c (99%)
+ rename drivers/media/{video => v4l2-core}/v4l2-mem2mem.c (98%)
+ rename drivers/media/{video => v4l2-core}/v4l2-subdev.c (98%)
+ rename drivers/media/{video => v4l2-core}/videobuf-core.c (100%)
+ rename drivers/media/{video => v4l2-core}/videobuf-dma-contig.c (100%)
+ rename drivers/media/{video => v4l2-core}/videobuf-dma-sg.c (100%)
+ rename drivers/media/{video => v4l2-core}/videobuf-dvb.c (96%)
+ rename drivers/media/{video => v4l2-core}/videobuf-vmalloc.c (100%)
+ rename drivers/media/{video => v4l2-core}/videobuf2-core.c (98%)
+ rename drivers/media/{video => v4l2-core}/videobuf2-dma-contig.c (100%)
+ rename drivers/media/{video => v4l2-core}/videobuf2-dma-sg.c (100%)
+ rename drivers/media/{video => v4l2-core}/videobuf2-memops.c (100%)
+ rename drivers/media/{video => v4l2-core}/videobuf2-vmalloc.c (99%)
+ delete mode 100644 drivers/media/video/Kconfig
+ delete mode 100644 drivers/media/video/Makefile
+ delete mode 100644 drivers/media/video/bt8xx/Kconfig
+ delete mode 100644 drivers/media/video/bt8xx/Makefile
+ delete mode 100644 drivers/media/video/cx23885/Kconfig
+ delete mode 100644 drivers/media/video/tlg2300/Makefile
+ delete mode 100644 drivers/staging/media/easycap/Kconfig
+ delete mode 100644 drivers/staging/media/easycap/Makefile
+ delete mode 100644 drivers/staging/media/easycap/README
+ delete mode 100644 drivers/staging/media/easycap/easycap.h
+ delete mode 100644 drivers/staging/media/easycap/easycap_ioctl.c
+ delete mode 100644 drivers/staging/media/easycap/easycap_low.c
+ delete mode 100644 drivers/staging/media/easycap/easycap_main.c
+ delete mode 100644 drivers/staging/media/easycap/easycap_settings.c
+ delete mode 100644 drivers/staging/media/easycap/easycap_sound.c
+ delete mode 100644 drivers/staging/media/easycap/easycap_testcard.c
+ delete mode 100644 drivers/staging/media/lirc/lirc_ene0100.h
+ delete mode 100644 drivers/staging/media/lirc/lirc_ttusbir.c
+ create mode 100644 include/media/ad9389b.h
+ create mode 100644 include/media/adv7604.h
+ create mode 100644 include/media/ir-rx51.h
+Merging kbuild/for-next (f4d278b Merge branch 'kbuild/rc-fixes' into kbuild/for-next)
+$ git merge kbuild/for-next
+Auto-merging scripts/kernel-doc
+Auto-merging Makefile
+Auto-merging MAINTAINERS
+Merge made by the 'recursive' strategy.
+ MAINTAINERS                          |    5 -
+ Makefile                             |   19 +--
+ scripts/Makefile.modinst             |    2 +-
+ scripts/Makefile.modpost             |    2 +-
+ scripts/coccinelle/api/ptr_ret.cocci |   26 ++++
+ scripts/kconfig/conf.c               |    2 +-
+ scripts/kconfig/lxdialog/dialog.h    |    1 +
+ scripts/kconfig/lxdialog/util.c      |    7 +
+ scripts/kconfig/mconf.c              |    4 -
+ scripts/kernel-doc                   |  273 +++++++++++++++++++++++++++++++++-
+ scripts/tags.sh                      |    8 +-
+ 11 files changed, 312 insertions(+), 37 deletions(-)
+Merging kconfig/for-next (45f4c81 localmodconfig: Use my variable for loop in streamline_config.pl)
+$ git merge kconfig/for-next
+Merge made by the 'recursive' strategy.
+ scripts/kconfig/streamline_config.pl |   48 ++++++++++++++++------------------
+ 1 file changed, 22 insertions(+), 26 deletions(-)
+Merging libata/NEXT (633de4c [libata] export ata_dev_set_feature())
+$ git merge libata/NEXT
+Auto-merging drivers/ata/libata-core.c
+Merge made by the 'recursive' strategy.
+ .../devicetree/bindings/arm/calxeda/combophy.txt   |   17 +
+ .../devicetree/bindings/ata/ahci-platform.txt      |    8 +
+ .../devicetree/bindings/ata/pata-arasan.txt        |   17 +
+ arch/arm/boot/dts/highbank.dts                     |   17 +
+ drivers/ata/Kconfig                                |    8 +
+ drivers/ata/Makefile                               |    1 +
+ drivers/ata/ahci.h                                 |   16 +
+ drivers/ata/ahci_platform.c                        |   58 ++-
+ drivers/ata/libahci.c                              |   97 ++++-
+ drivers/ata/libata-core.c                          |   32 +-
+ drivers/ata/libata-eh.c                            |   12 +-
+ drivers/ata/libata-scsi.c                          |  255 ++++++++++-
+ drivers/ata/libata.h                               |    2 +
+ drivers/ata/pata_arasan_cf.c                       |   14 +-
+ drivers/ata/sata_fsl.c                             |   39 +-
+ drivers/ata/sata_highbank.c                        |  450 ++++++++++++++++++++
+ include/linux/ata.h                                |   30 +-
+ include/linux/libata.h                             |    4 +
+ 18 files changed, 1020 insertions(+), 57 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/arm/calxeda/combophy.txt
+ create mode 100644 Documentation/devicetree/bindings/ata/pata-arasan.txt
+ create mode 100644 drivers/ata/sata_highbank.c
+Merging infiniband/for-next (09ef9fd Merge branches 'cma', 'cxgb4', 'ipoib', 'mlx4', 'mlx4-sriov', 'nes', 'ocrdma', 'qib' and 'srp' into for-next)
+$ git merge infiniband/for-next
+Auto-merging include/linux/mlx4/device.h
+Auto-merging drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
+Auto-merging drivers/net/ethernet/mellanox/mlx4/mlx4.h
+Auto-merging drivers/net/ethernet/mellanox/mlx4/main.c
+Auto-merging drivers/infiniband/core/ucma.c
+Merge made by the 'recursive' strategy.
+ drivers/infiniband/core/cache.c                    |   43 +-
+ drivers/infiniband/core/cma.c                      |    5 +-
+ drivers/infiniband/core/device.c                   |   16 +-
+ drivers/infiniband/core/ucm.c                      |    1 -
+ drivers/infiniband/core/ucma.c                     |    1 -
+ drivers/infiniband/hw/cxgb4/qp.c                   |   62 +-
+ drivers/infiniband/hw/mlx4/Makefile                |    2 +-
+ drivers/infiniband/hw/mlx4/alias_GUID.c            |  688 +++++++++
+ drivers/infiniband/hw/mlx4/cm.c                    |  437 ++++++
+ drivers/infiniband/hw/mlx4/cq.c                    |   31 +-
+ drivers/infiniband/hw/mlx4/mad.c                   | 1573 +++++++++++++++++++-
+ drivers/infiniband/hw/mlx4/main.c                  |  273 +++-
+ drivers/infiniband/hw/mlx4/mcg.c                   | 1254 ++++++++++++++++
+ drivers/infiniband/hw/mlx4/mlx4_ib.h               |  341 ++++-
+ drivers/infiniband/hw/mlx4/qp.c                    |  660 +++++++-
+ drivers/infiniband/hw/mlx4/sysfs.c                 |  794 ++++++++++
+ drivers/infiniband/hw/nes/nes.h                    |   15 +-
+ drivers/infiniband/hw/nes/nes_cm.c                 |   34 +-
+ drivers/infiniband/hw/nes/nes_hw.c                 |    4 +-
+ drivers/infiniband/hw/nes/nes_nic.c                |   40 +-
+ drivers/infiniband/hw/nes/nes_utils.c              |    2 +-
+ drivers/infiniband/hw/nes/nes_verbs.c              |   14 +-
+ drivers/infiniband/hw/qib/qib_common.h             |   14 +-
+ drivers/infiniband/hw/qib/qib_driver.c             |    3 +-
+ drivers/infiniband/hw/qib/qib_verbs.c              |    2 +-
+ drivers/infiniband/ulp/ipoib/ipoib_main.c          |    2 +-
+ drivers/infiniband/ulp/ipoib/ipoib_multicast.c     |   19 +-
+ drivers/infiniband/ulp/srp/ib_srp.c                |    3 +-
+ drivers/net/ethernet/mellanox/mlx4/cmd.c           |  191 ++-
+ drivers/net/ethernet/mellanox/mlx4/eq.c            |  245 ++-
+ drivers/net/ethernet/mellanox/mlx4/fw.c            |  246 ++-
+ drivers/net/ethernet/mellanox/mlx4/fw.h            |   11 +-
+ drivers/net/ethernet/mellanox/mlx4/main.c          |   91 +-
+ drivers/net/ethernet/mellanox/mlx4/mlx4.h          |   50 +
+ drivers/net/ethernet/mellanox/mlx4/port.c          |   10 +
+ drivers/net/ethernet/mellanox/mlx4/qp.c            |  100 +-
+ .../net/ethernet/mellanox/mlx4/resource_tracker.c  |  222 ++-
+ include/linux/mlx4/device.h                        |   69 +-
+ include/linux/mlx4/driver.h                        |    2 +
+ include/linux/mlx4/qp.h                            |    3 +-
+ include/rdma/ib_cache.h                            |   16 +
+ include/rdma/ib_verbs.h                            |    3 +
+ 42 files changed, 7204 insertions(+), 388 deletions(-)
+ create mode 100644 drivers/infiniband/hw/mlx4/alias_GUID.c
+ create mode 100644 drivers/infiniband/hw/mlx4/cm.c
+ create mode 100644 drivers/infiniband/hw/mlx4/mcg.c
+ create mode 100644 drivers/infiniband/hw/mlx4/sysfs.c
+Merging pstore/master (80c9d03 pstore: Avoid recursive spinlocks in the oops_in_progress case)
+$ git merge pstore/master
+Auto-merging MAINTAINERS
+Merge made by the 'recursive' strategy.
+ Documentation/ramoops.txt      |    4 +-
+ MAINTAINERS                    |   12 +++++
+ fs/pstore/Kconfig              |    1 +
+ fs/pstore/ftrace.c             |   96 +++++++++++++++++++++++++++++++++++++++-
+ fs/pstore/internal.h           |    6 +++
+ fs/pstore/platform.c           |    9 +++-
+ fs/pstore/ram.c                |   28 ++++++------
+ include/linux/pstore.h         |    8 ----
+ kernel/trace/trace_functions.c |   15 +------
+ 9 files changed, 139 insertions(+), 40 deletions(-)
+Merging acpi/next (b76c4c2 Merge branch 'misc' into next)
+$ git merge acpi/next
+Merge made by the 'recursive' strategy.
+ drivers/acpi/acpica/Makefile             |    1 +
+ drivers/acpi/acpica/achware.h            |    3 +-
+ drivers/acpi/acpica/aclocal.h            |   23 +-
+ drivers/acpi/acpica/acmacros.h           |   29 +-
+ drivers/acpi/acpica/dswload.c            |   14 +
+ drivers/acpi/acpica/dswload2.c           |   14 +
+ drivers/acpi/acpica/evgpe.c              |   24 +-
+ drivers/acpi/acpica/evxfgpe.c            |    3 +-
+ drivers/acpi/acpica/hwgpe.c              |   15 +-
+ drivers/acpi/acpica/hwxfsleep.c          |    1 -
+ drivers/acpi/acpica/nsdump.c             |    2 +-
+ drivers/acpi/acpica/tbinstal.c           |   20 +-
+ drivers/acpi/acpica/tbxface.c            |   41 +--
+ drivers/acpi/acpica/utosi.c              |    1 +
+ drivers/acpi/acpica/utxface.c            |  354 +++++--------------
+ drivers/acpi/acpica/utxfinit.c           |  317 +++++++++++++++++
+ drivers/acpi/bus.c                       |    8 +-
+ drivers/acpi/button.c                    |   13 +-
+ drivers/acpi/fan.c                       |   22 +-
+ drivers/acpi/glue.c                      |  135 ++++---
+ drivers/acpi/hed.c                       |   20 +-
+ drivers/acpi/proc.c                      |   57 +--
+ drivers/acpi/sbshc.c                     |   18 +-
+ drivers/acpi/scan.c                      |    2 +
+ drivers/acpi/utils.c                     |   11 +-
+ drivers/i2c/busses/i2c-scmi.c            |   14 +-
+ drivers/input/misc/atlas_btns.c          |   17 +-
+ drivers/platform/x86/hp_accel.c          |   25 +-
+ drivers/platform/x86/ideapad-laptop.c    |   14 +-
+ drivers/platform/x86/topstar-laptop.c    |   22 +-
+ drivers/platform/x86/toshiba_bluetooth.c |   22 +-
+ drivers/platform/x86/xo15-ebook.c        |   14 +-
+ drivers/pnp/pnpacpi/core.c               |    7 +-
+ drivers/usb/core/usb-acpi.c              |    5 +-
+ include/acpi/acbuffer.h                  |  235 +++++++++++++
+ include/acpi/acnames.h                   |    3 +-
+ include/acpi/acpi_bus.h                  |   59 ++--
+ include/acpi/acpixf.h                    |    7 +-
+ include/acpi/actbl.h                     |   60 ++--
+ include/acpi/actbl1.h                    |   16 +-
+ include/acpi/actbl2.h                    |  123 ++++++-
+ include/acpi/actbl3.h                    |   13 +-
+ include/acpi/actypes.h                   |    7 -
+ tools/power/acpi/Makefile                |   18 +
+ tools/power/acpi/acpidump.8              |   59 ++++
+ tools/power/acpi/acpidump.c              |  560 ++++++++++++++++++++++++++++++
+ tools/power/x86/turbostat/turbostat.8    |   22 +-
+ tools/power/x86/turbostat/turbostat.c    |  198 ++++++++++-
+ 48 files changed, 1953 insertions(+), 715 deletions(-)
+ create mode 100644 drivers/acpi/acpica/utxfinit.c
+ create mode 100644 include/acpi/acbuffer.h
+ create mode 100644 tools/power/acpi/Makefile
+ create mode 100644 tools/power/acpi/acpidump.8
+ create mode 100644 tools/power/acpi/acpidump.c
+Merging cpuidle/cpuidle-next (3cf7997 acpi: intel_idle : break dependency between modules)
+$ git merge cpuidle/cpuidle-next
+Resolved 'drivers/cpuidle/coupled.c' using previous resolution.
+Resolved 'include/linux/cpuidle.h' using previous resolution.
+Auto-merging include/linux/cpuidle.h
+CONFLICT (content): Merge conflict in include/linux/cpuidle.h
+Auto-merging drivers/cpuidle/coupled.c
+CONFLICT (add/add): Merge conflict in drivers/cpuidle/coupled.c
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master be0765b] Merge remote-tracking branch 'cpuidle/cpuidle-next'
+$ git diff -M --stat --summary HEAD^..
+Merging cpupowerutils/master (f166033 cpupower tools: add install target to the debug tools' makefiles)
+$ git merge cpupowerutils/master
+Already up-to-date.
+Merging thermal/next (cf68bdc Thermal: Provide option to choose default thermal governor)
+$ git merge thermal/next
+Auto-merging include/linux/platform_data/exynos_thermal.h
+Removing drivers/hwmon/exynos4_tmu.c
+Auto-merging drivers/hwmon/Makefile
+Auto-merging drivers/hwmon/Kconfig
+Auto-merging drivers/acpi/thermal.c
+Auto-merging Documentation/thermal/exynos_thermal
+Merge made by the 'recursive' strategy.
+ Documentation/thermal/cpu-cooling-api.txt          |   32 +
+ .../{hwmon/exynos4_tmu => thermal/exynos_thermal}  |   35 +-
+ Documentation/thermal/sysfs-api.txt                |   73 +-
+ drivers/acpi/thermal.c                             |   97 +-
+ drivers/hwmon/Kconfig                              |   10 -
+ drivers/hwmon/Makefile                             |    1 -
+ drivers/hwmon/exynos4_tmu.c                        |  518 ----------
+ drivers/platform/x86/acerhdf.c                     |    5 +-
+ drivers/platform/x86/intel_mid_thermal.c           |    2 +-
+ drivers/power/power_supply_core.c                  |    2 +-
+ drivers/staging/omap-thermal/omap-thermal-common.c |    6 +-
+ drivers/thermal/Kconfig                            |   75 ++
+ drivers/thermal/Makefile                           |    8 +-
+ drivers/thermal/cpu_cooling.c                      |  450 +++++++++
+ drivers/thermal/exynos_thermal.c                   |  994 ++++++++++++++++++++
+ drivers/thermal/fair_share.c                       |  133 +++
+ drivers/thermal/rcar_thermal.c                     |  260 +++++
+ drivers/thermal/spear_thermal.c                    |    2 +-
+ drivers/thermal/step_wise.c                        |  194 ++++
+ drivers/thermal/thermal_core.h                     |   53 ++
+ drivers/thermal/thermal_sys.c                      |  766 ++++++++++-----
+ drivers/thermal/user_space.c                       |   68 ++
+ include/linux/cpu_cooling.h                        |   58 ++
+ .../{exynos4_tmu.h => exynos_thermal.h}            |   47 +-
+ include/linux/thermal.h                            |  150 ++-
+ 25 files changed, 3161 insertions(+), 878 deletions(-)
+ create mode 100644 Documentation/thermal/cpu-cooling-api.txt
+ rename Documentation/{hwmon/exynos4_tmu => thermal/exynos_thermal} (71%)
+ delete mode 100644 drivers/hwmon/exynos4_tmu.c
+ create mode 100644 drivers/thermal/cpu_cooling.c
+ create mode 100644 drivers/thermal/exynos_thermal.c
+ create mode 100644 drivers/thermal/fair_share.c
+ create mode 100644 drivers/thermal/rcar_thermal.c
+ create mode 100644 drivers/thermal/step_wise.c
+ create mode 100644 drivers/thermal/thermal_core.h
+ create mode 100644 drivers/thermal/user_space.c
+ create mode 100644 include/linux/cpu_cooling.h
+ rename include/linux/platform_data/{exynos4_tmu.h => exynos_thermal.h} (64%)
+Merging ieee1394/for-next (52439d6 firewire: ohci: get IR bit from TSB41BA3D phy)
+$ git merge ieee1394/for-next
+Merge made by the 'recursive' strategy.
+ drivers/firewire/core-device.c |    3 +++
+ drivers/firewire/ohci.c        |   28 +++++++++++++++++++++++++++-
+ 2 files changed, 30 insertions(+), 1 deletion(-)
+Merging ubi/linux-next (9bfd58f UBI: fix trivial typo 'it' => 'is')
+$ git merge ubi/linux-next
+Auto-merging drivers/mtd/ubi/vtbl.c
+Merge made by the 'recursive' strategy.
+ arch/arm/configs/sam9_l9260_defconfig |    2 +-
+ drivers/mtd/mtdpart.c                 |   12 +-
+ drivers/mtd/ubi/Kconfig               |   40 ++++---
+ drivers/mtd/ubi/attach.c              |   46 ++++----
+ drivers/mtd/ubi/build.c               |  204 ++++++++++++++++++++-------------
+ drivers/mtd/ubi/cdev.c                |   18 +--
+ drivers/mtd/ubi/debug.c               |  153 ++++++++++++-------------
+ drivers/mtd/ubi/debug.h               |   12 +-
+ drivers/mtd/ubi/eba.c                 |   33 +++---
+ drivers/mtd/ubi/gluebi.c              |   30 +++--
+ drivers/mtd/ubi/io.c                  |   80 +++++++------
+ drivers/mtd/ubi/misc.c                |   14 ++-
+ drivers/mtd/ubi/ubi.h                 |   16 +--
+ drivers/mtd/ubi/vtbl.c                |   10 +-
+ drivers/mtd/ubi/wl.c                  |   48 +++++---
+ include/linux/mtd/partitions.h        |    3 +-
+ include/mtd/ubi-user.h                |   16 ++-
+ 17 files changed, 412 insertions(+), 325 deletions(-)
+Merging dlm/next (2b75bc9 dlm: check the maximum size of a request from user)
+$ git merge dlm/next
+Merge made by the 'recursive' strategy.
+ fs/dlm/ast.c          |    4 +-
+ fs/dlm/config.c       |   79 ++++--------------
+ fs/dlm/config.h       |    2 -
+ fs/dlm/dlm_internal.h |   46 ++++++++---
+ fs/dlm/lockspace.c    |   15 +++-
+ fs/dlm/lowcomms.c     |  215 +++++++++++++++++++++++++++++++++++++++++--------
+ fs/dlm/lowcomms.h     |    2 +
+ fs/dlm/main.c         |    2 +
+ fs/dlm/member.c       |   17 ++--
+ fs/dlm/rcom.c         |    2 +-
+ fs/dlm/recoverd.c     |   27 ++++---
+ fs/dlm/recoverd.h     |    1 -
+ fs/dlm/user.c         |    7 ++
+ 13 files changed, 289 insertions(+), 130 deletions(-)
+Merging scsi/for-next (3da4202 Merge branch 'misc' into for-next)
+$ git merge scsi/for-next
+Resolved 'drivers/scsi/ipr.c' using previous resolution.
+Resolved 'drivers/scsi/qla2xxx/qla_nx.c' using previous resolution.
+Auto-merging include/linux/libata.h
+Auto-merging drivers/scsi/qla4xxx/ql4_os.c
+Auto-merging drivers/scsi/qla4xxx/ql4_nx.c
+Auto-merging drivers/scsi/qla2xxx/qla_os.c
+Auto-merging drivers/scsi/qla2xxx/qla_nx.c
+CONFLICT (content): Merge conflict in drivers/scsi/qla2xxx/qla_nx.c
+Auto-merging drivers/scsi/mpt2sas/mpt2sas_scsih.c
+Auto-merging drivers/scsi/mpt2sas/mpt2sas_base.c
+Auto-merging drivers/scsi/lpfc/lpfc_init.c
+Auto-merging drivers/scsi/ipr.c
+CONFLICT (content): Merge conflict in drivers/scsi/ipr.c
+Removing drivers/scsi/ibmvscsi/rpa_vscsi.c
+Auto-merging drivers/scsi/hpsa.c
+Auto-merging drivers/ata/libata-eh.c
+Auto-merging drivers/ata/libata-core.c
+Auto-merging MAINTAINERS
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master 66dc8f3] Merge remote-tracking branch 'scsi/for-next'
+$ git diff -M --stat --summary HEAD^..
+ Documentation/kernel-parameters.txt         |    3 +
+ Documentation/scsi/ChangeLog.megaraid_sas   |   10 +
+ Documentation/scsi/LICENSE.qla2xxx          |    2 +-
+ Documentation/scsi/LICENSE.qla4xxx          |    2 +-
+ Documentation/scsi/st.txt                   |    6 +-
+ MAINTAINERS                                 |    8 +-
+ drivers/ata/libata-core.c                   |   69 +-
+ drivers/ata/libata-eh.c                     |    2 +
+ drivers/message/fusion/mptbase.c            |   18 +-
+ drivers/s390/scsi/zfcp_aux.c                |    1 +
+ drivers/s390/scsi/zfcp_ccw.c                |   80 +-
+ drivers/s390/scsi/zfcp_cfdc.c               |    2 +-
+ drivers/s390/scsi/zfcp_dbf.c                |   22 +-
+ drivers/s390/scsi/zfcp_dbf.h                |    1 +
+ drivers/s390/scsi/zfcp_def.h                |    2 +
+ drivers/s390/scsi/zfcp_erp.c                |    2 +-
+ drivers/s390/scsi/zfcp_ext.h                |    4 +
+ drivers/s390/scsi/zfcp_fc.c                 |   23 +-
+ drivers/s390/scsi/zfcp_fsf.c                |   59 +-
+ drivers/s390/scsi/zfcp_qdio.c               |   16 +-
+ drivers/s390/scsi/zfcp_sysfs.c              |   18 +-
+ drivers/s390/scsi/zfcp_unit.c               |   36 +-
+ drivers/scsi/be2iscsi/be_cmds.c             |  160 ++-
+ drivers/scsi/be2iscsi/be_cmds.h             |   27 +
+ drivers/scsi/be2iscsi/be_iscsi.c            |  355 ++++--
+ drivers/scsi/be2iscsi/be_main.c             |  890 +++++++++------
+ drivers/scsi/be2iscsi/be_main.h             |   40 +-
+ drivers/scsi/be2iscsi/be_mgmt.c             |  314 +++++-
+ drivers/scsi/be2iscsi/be_mgmt.h             |   11 +
+ drivers/scsi/bfa/bfa_core.c                 |   21 +-
+ drivers/scsi/bfa/bfa_cs.h                   |    4 +-
+ drivers/scsi/bfa/bfa_defs_fcs.h             |   18 +
+ drivers/scsi/bfa/bfa_fc.h                   |   10 +
+ drivers/scsi/bfa/bfa_fcbuild.c              |   21 +
+ drivers/scsi/bfa/bfa_fcbuild.h              |    2 +
+ drivers/scsi/bfa/bfa_fcpim.c                |   12 +-
+ drivers/scsi/bfa/bfa_fcs.c                  |  182 ++-
+ drivers/scsi/bfa/bfa_fcs.h                  |   66 +-
+ drivers/scsi/bfa/bfa_fcs_fcpim.c            |  129 ++-
+ drivers/scsi/bfa/bfa_fcs_lport.c            |  632 ++++++++++-
+ drivers/scsi/bfa/bfa_fcs_rport.c            |  466 ++++++--
+ drivers/scsi/bfa/bfa_ioc.c                  |   24 +-
+ drivers/scsi/bfa/bfa_ioc.h                  |    2 +
+ drivers/scsi/bfa/bfa_modules.h              |    1 +
+ drivers/scsi/bfa/bfa_svc.c                  |   95 +-
+ drivers/scsi/bfa/bfa_svc.h                  |   23 +-
+ drivers/scsi/bfa/bfad.c                     |  236 +++-
+ drivers/scsi/bfa/bfad_attr.c                |   46 +-
+ drivers/scsi/bfa/bfad_bsg.c                 |   39 +-
+ drivers/scsi/bfa/bfad_bsg.h                 |    2 +
+ drivers/scsi/bfa/bfad_drv.h                 |    5 +-
+ drivers/scsi/bfa/bfad_im.c                  |    9 +
+ drivers/scsi/bnx2fc/bnx2fc_io.c             |    2 +-
+ drivers/scsi/constants.c                    |    3 +-
+ drivers/scsi/device_handler/scsi_dh_alua.c  |    3 +-
+ drivers/scsi/device_handler/scsi_dh_rdac.c  |   26 +-
+ drivers/scsi/hpsa.c                         |   39 +-
+ drivers/scsi/ibmvscsi/Makefile              |    6 +-
+ drivers/scsi/ibmvscsi/ibmvfc.c              |   36 +-
+ drivers/scsi/ibmvscsi/ibmvfc.h              |    4 +-
+ drivers/scsi/ibmvscsi/ibmvscsi.c            |  352 +++++-
+ drivers/scsi/ibmvscsi/ibmvscsi.h            |   22 -
+ drivers/scsi/ibmvscsi/rpa_vscsi.c           |  368 ------
+ drivers/scsi/ipr.c                          |  234 ++--
+ drivers/scsi/ipr.h                          |    5 +-
+ drivers/scsi/isci/host.c                    |   24 +-
+ drivers/scsi/isci/host.h                    |    2 +-
+ drivers/scsi/isci/init.c                    |   59 +-
+ drivers/scsi/isci/phy.c                     |    4 +-
+ drivers/scsi/isci/probe_roms.c              |    1 -
+ drivers/scsi/isci/remote_node_context.h     |    2 +-
+ drivers/scsi/iscsi_tcp.c                    |    2 +-
+ drivers/scsi/libsas/sas_ata.c               |   91 +-
+ drivers/scsi/libsas/sas_discover.c          |   69 +-
+ drivers/scsi/libsas/sas_dump.c              |    1 +
+ drivers/scsi/libsas/sas_event.c             |    4 +-
+ drivers/scsi/libsas/sas_init.c              |   90 +-
+ drivers/scsi/libsas/sas_internal.h          |    1 +
+ drivers/scsi/libsas/sas_phy.c               |   21 +
+ drivers/scsi/libsas/sas_port.c              |   52 +-
+ drivers/scsi/lpfc/lpfc.h                    |    6 +-
+ drivers/scsi/lpfc/lpfc_attr.c               |   76 +-
+ drivers/scsi/lpfc/lpfc_bsg.c                |    8 +-
+ drivers/scsi/lpfc/lpfc_crtn.h               |    6 +-
+ drivers/scsi/lpfc/lpfc_ct.c                 |   16 +-
+ drivers/scsi/lpfc/lpfc_debugfs.c            |  494 ++++----
+ drivers/scsi/lpfc/lpfc_debugfs.h            |   72 +-
+ drivers/scsi/lpfc/lpfc_disc.h               |   10 +-
+ drivers/scsi/lpfc/lpfc_els.c                |  186 +++-
+ drivers/scsi/lpfc/lpfc_hbadisc.c            |   98 +-
+ drivers/scsi/lpfc/lpfc_hw.h                 |   18 +-
+ drivers/scsi/lpfc/lpfc_hw4.h                |   42 +-
+ drivers/scsi/lpfc/lpfc_init.c               |  839 +++++++-------
+ drivers/scsi/lpfc/lpfc_mbox.c               |   38 +-
+ drivers/scsi/lpfc/lpfc_mem.c                |    6 +-
+ drivers/scsi/lpfc/lpfc_nportdisc.c          |  127 +++
+ drivers/scsi/lpfc/lpfc_scsi.c               |  144 ++-
+ drivers/scsi/lpfc/lpfc_sli.c                |  621 ++++++-----
+ drivers/scsi/lpfc/lpfc_sli.h                |   42 +-
+ drivers/scsi/lpfc/lpfc_sli4.h               |   63 +-
+ drivers/scsi/lpfc/lpfc_version.h            |    7 +-
+ drivers/scsi/megaraid/megaraid_sas.h        |    8 +-
+ drivers/scsi/megaraid/megaraid_sas_base.c   |   39 +-
+ drivers/scsi/megaraid/megaraid_sas_fusion.c |   12 +-
+ drivers/scsi/mpt2sas/Kconfig                |    2 +-
+ drivers/scsi/mpt2sas/mpi/mpi2.h             |   14 +-
+ drivers/scsi/mpt2sas/mpi/mpi2_init.h        |    9 +-
+ drivers/scsi/mpt2sas/mpi/mpi2_ioc.h         |    8 +-
+ drivers/scsi/mpt2sas/mpi/mpi2_raid.h        |    7 +-
+ drivers/scsi/mpt2sas/mpt2sas_base.c         |    6 +-
+ drivers/scsi/mpt2sas/mpt2sas_base.h         |   14 +-
+ drivers/scsi/mpt2sas/mpt2sas_config.c       |   38 +-
+ drivers/scsi/mpt2sas/mpt2sas_ctl.c          |   80 +-
+ drivers/scsi/mpt2sas/mpt2sas_ctl.h          |    2 +-
+ drivers/scsi/mpt2sas/mpt2sas_debug.h        |    2 +-
+ drivers/scsi/mpt2sas/mpt2sas_scsih.c        |   59 +-
+ drivers/scsi/mpt2sas/mpt2sas_transport.c    |    2 +-
+ drivers/scsi/mvsas/mv_sas.c                 |    2 +-
+ drivers/scsi/qla2xxx/qla_attr.c             |  147 ++-
+ drivers/scsi/qla2xxx/qla_bsg.c              |  376 ++++++-
+ drivers/scsi/qla2xxx/qla_bsg.h              |   30 +-
+ drivers/scsi/qla2xxx/qla_dbg.c              |   29 +-
+ drivers/scsi/qla2xxx/qla_dbg.h              |    2 +-
+ drivers/scsi/qla2xxx/qla_def.h              |  166 ++-
+ drivers/scsi/qla2xxx/qla_dfs.c              |    2 +-
+ drivers/scsi/qla2xxx/qla_fw.h               |   49 +-
+ drivers/scsi/qla2xxx/qla_gbl.h              |   39 +-
+ drivers/scsi/qla2xxx/qla_gs.c               |    4 +-
+ drivers/scsi/qla2xxx/qla_init.c             |  565 ++++++++--
+ drivers/scsi/qla2xxx/qla_inline.h           |   28 +-
+ drivers/scsi/qla2xxx/qla_iocb.c             |  261 ++++-
+ drivers/scsi/qla2xxx/qla_isr.c              |  437 +++++++-
+ drivers/scsi/qla2xxx/qla_mbx.c              |  224 +++-
+ drivers/scsi/qla2xxx/qla_mid.c              |    5 +-
+ drivers/scsi/qla2xxx/qla_nx.c               |  151 +--
+ drivers/scsi/qla2xxx/qla_nx.h               |   17 +-
+ drivers/scsi/qla2xxx/qla_os.c               |  770 ++++++++++++-
+ drivers/scsi/qla2xxx/qla_settings.h         |    2 +-
+ drivers/scsi/qla2xxx/qla_sup.c              |   67 +-
+ drivers/scsi/qla2xxx/qla_version.h          |    6 +-
+ drivers/scsi/qla4xxx/Kconfig                |    4 +-
+ drivers/scsi/qla4xxx/Makefile               |    2 +-
+ drivers/scsi/qla4xxx/ql4_83xx.c             | 1611 +++++++++++++++++++++++++++
+ drivers/scsi/qla4xxx/ql4_83xx.h             |  283 +++++
+ drivers/scsi/qla4xxx/ql4_attr.c             |   26 +-
+ drivers/scsi/qla4xxx/ql4_dbg.c              |   32 +-
+ drivers/scsi/qla4xxx/ql4_dbg.h              |    2 +-
+ drivers/scsi/qla4xxx/ql4_def.h              |   65 +-
+ drivers/scsi/qla4xxx/ql4_fw.h               |   59 +-
+ drivers/scsi/qla4xxx/ql4_glbl.h             |   94 +-
+ drivers/scsi/qla4xxx/ql4_init.c             |   23 +-
+ drivers/scsi/qla4xxx/ql4_inline.h           |    2 +-
+ drivers/scsi/qla4xxx/ql4_iocb.c             |   28 +-
+ drivers/scsi/qla4xxx/ql4_isr.c              |  406 +++++--
+ drivers/scsi/qla4xxx/ql4_mbx.c              |  186 ++--
+ drivers/scsi/qla4xxx/ql4_nvram.c            |    2 +-
+ drivers/scsi/qla4xxx/ql4_nvram.h            |    2 +-
+ drivers/scsi/qla4xxx/ql4_nx.c               | 1432 ++++++++++++++++--------
+ drivers/scsi/qla4xxx/ql4_nx.h               |  198 ++--
+ drivers/scsi/qla4xxx/ql4_os.c               |  494 +++++---
+ drivers/scsi/qla4xxx/ql4_version.h          |    4 +-
+ drivers/scsi/scsi_debug.c                   |   30 +-
+ drivers/scsi/scsi_devinfo.c                 |    1 +
+ drivers/scsi/scsi_lib.c                     |    3 +-
+ drivers/scsi/scsi_scan.c                    |    3 +
+ drivers/scsi/scsi_sysfs.c                   |   30 +-
+ drivers/scsi/sd.c                           |   80 +-
+ drivers/scsi/sd.h                           |    2 +-
+ drivers/scsi/sd_dif.c                       |   25 +-
+ drivers/scsi/st.c                           |  416 +++----
+ drivers/scsi/st.h                           |    5 +-
+ include/linux/libata.h                      |   15 +-
+ include/linux/pci_ids.h                     |    1 +
+ include/scsi/libsas.h                       |   20 +-
+ include/scsi/sas_ata.h                      |   10 +
+ include/scsi/scsi_bsg_fc.h                  |    2 -
+ include/scsi/scsi_device.h                  |    4 +
+ include/scsi/scsi_devinfo.h                 |    1 +
+ include/scsi/scsi_host.h                    |    6 +
+ 179 files changed, 13497 insertions(+), 4463 deletions(-)
+ delete mode 100644 drivers/scsi/ibmvscsi/rpa_vscsi.c
+ create mode 100644 drivers/scsi/qla4xxx/ql4_83xx.c
+ create mode 100644 drivers/scsi/qla4xxx/ql4_83xx.h
+Merging target-updates/for-next (f25590f iscsi-target: Correctly set 0xffffffff field within ISCSI_OP_REJECT PDU)
+$ git merge target-updates/for-next
+Merge made by the 'recursive' strategy.
+ Documentation/target/tcm_mod_builder.py      |   16 ---
+ drivers/infiniband/ulp/srpt/ib_srpt.c        |   12 --
+ drivers/scsi/qla2xxx/qla_target.c            |    2 +-
+ drivers/scsi/qla2xxx/tcm_qla2xxx.c           |   15 ---
+ drivers/target/iscsi/iscsi_target.c          |   14 +-
+ drivers/target/iscsi/iscsi_target_configfs.c |   25 ----
+ drivers/target/iscsi/iscsi_target_nego.c     |    1 -
+ drivers/target/loopback/tcm_loop.c           |   12 --
+ drivers/target/sbp/sbp_target.c              |   27 +---
+ drivers/target/target_core_alua.c            |    2 +-
+ drivers/target/target_core_configfs.c        |   18 ++-
+ drivers/target/target_core_device.c          |   16 ++-
+ drivers/target/target_core_fabric_configfs.c |    1 -
+ drivers/target/target_core_fabric_lib.c      |    8 +-
+ drivers/target/target_core_file.c            |    2 -
+ drivers/target/target_core_iblock.c          |   17 +--
+ drivers/target/target_core_pr.c              |   14 +-
+ drivers/target/target_core_pscsi.c           |    2 +-
+ drivers/target/target_core_sbc.c             |   23 ++--
+ drivers/target/target_core_spc.c             |   48 ++-----
+ drivers/target/target_core_stat.c            |    1 -
+ drivers/target/target_core_tpg.c             |    2 +-
+ drivers/target/target_core_transport.c       |  184 +++++++++++---------------
+ drivers/target/tcm_fc/tfc_cmd.c              |    1 -
+ drivers/target/tcm_fc/tfc_conf.c             |   12 --
+ drivers/target/tcm_fc/tfc_io.c               |    4 +-
+ drivers/target/tcm_fc/tfc_sess.c             |    1 -
+ drivers/usb/gadget/tcm_usb_gadget.c          |   12 --
+ drivers/vhost/tcm_vhost.c                    |   13 --
+ include/target/target_core_backend.h         |    3 -
+ include/target/target_core_fabric.h          |    2 -
+ 31 files changed, 162 insertions(+), 348 deletions(-)
+Merging target-merge/for-next-merge (d987569 Linux 3.6-rc2)
+$ git merge target-merge/for-next-merge
+Already up-to-date.
+Merging ibft/linux-next (935a9fe ibft: Fix finding IBFT ACPI table on UEFI)
+$ git merge ibft/linux-next
+Already up-to-date.
+Merging isci/all (6734092 isci: add a couple __iomem annotations)
+$ git merge isci/all
+Already up-to-date.
+Merging slave-dma/next (0274788 DMA: PL330: return ENOMEM instead of 0 from pl330_alloc_chan_resources)
+$ git merge slave-dma/next
+Auto-merging drivers/dma/tegra20-apb-dma.c
+Auto-merging drivers/dma/pl330.c
+Merge made by the 'recursive' strategy.
+ arch/arm/mach-exynos/dma.c            |    2 +
+ drivers/dma/Kconfig                   |   17 +
+ drivers/dma/Makefile                  |    2 +
+ drivers/dma/amba-pl08x.c              |    2 +
+ drivers/dma/dw_dmac.c                 |   58 +--
+ drivers/dma/dw_dmac_regs.h            |    2 -
+ drivers/dma/edma.c                    |  671 +++++++++++++++++++++++++
+ drivers/dma/ioat/dma_v2.c             |    3 +-
+ drivers/dma/ioat/pci.c                |   22 +
+ drivers/dma/mmp_pdma.c                |  875 +++++++++++++++++++++++++++++++++
+ drivers/dma/mmp_tdma.c                |   51 +-
+ drivers/dma/mxs-dma.c                 |   14 +-
+ drivers/dma/pl330.c                   |   76 +--
+ drivers/dma/sirf-dma.c                |   23 +-
+ drivers/dma/ste_dma40.c               |   14 +-
+ drivers/dma/tegra20-apb-dma.c         |    6 +-
+ drivers/mmc/host/davinci_mmc.c        |  271 +++-------
+ drivers/spi/Kconfig                   |    1 +
+ drivers/spi/spi-davinci.c             |  292 +++++------
+ include/linux/edma.h                  |   29 ++
+ include/linux/platform_data/mmp_dma.h |   19 +
+ 21 files changed, 1932 insertions(+), 518 deletions(-)
+ create mode 100644 drivers/dma/edma.c
+ create mode 100644 drivers/dma/mmp_pdma.c
+ create mode 100644 include/linux/edma.h
+ create mode 100644 include/linux/platform_data/mmp_dma.h
+$ git am -3 ../patches/DMA__PL330__Fix_build_error_on_linux-next-20120924.patch
+Applying: DMA: PL330: Fix build error (on linux-next-20120924)
+$ git reset HEAD^
+Unstaged changes after reset:
+M	drivers/dma/pl330.c
+$ git add .
+$ git commit -v -a --amend
+[master d26e298] Merge remote-tracking branch 'slave-dma/next'
+Merging dmaengine/next (a2bd114 netdma: adding alignment check for NETDMA ops)
+$ git merge dmaengine/next
+Already up-to-date.
+Merging net-next/master (842b08b ipconfig: fix trivial build error)
+$ git merge net-next/master
+Auto-merging net/xfrm/xfrm_user.c
+Auto-merging net/xfrm/xfrm_policy.c
+Auto-merging net/wireless/reg.c
+Auto-merging net/socket.c
+CONFLICT (content): Merge conflict in net/socket.c
+Auto-merging net/sctp/socket.c
+Removing net/netfilter/xt_NOTRACK.c
+Auto-merging net/netfilter/nf_nat_tftp.c
+Auto-merging net/netfilter/nf_nat_sip.c
+Auto-merging net/netfilter/nf_nat_proto_unknown.c
+Auto-merging net/netfilter/nf_nat_proto_udplite.c
+Auto-merging net/netfilter/nf_nat_proto_udp.c
+Auto-merging net/netfilter/nf_nat_proto_tcp.c
+Auto-merging net/netfilter/nf_nat_proto_sctp.c
+Auto-merging net/netfilter/nf_nat_proto_dccp.c
+Auto-merging net/netfilter/nf_nat_proto_common.c
+Auto-merging net/netfilter/nf_nat_irc.c
+Auto-merging net/netfilter/nf_nat_helper.c
+Auto-merging net/netfilter/nf_nat_ftp.c
+Auto-merging net/netfilter/nf_nat_core.c
+Auto-merging net/netfilter/nf_nat_amanda.c
+Auto-merging net/ipv6/route.c
+Auto-merging net/ipv6/raw.c
+Auto-merging net/ipv4/tcp_input.c
+Auto-merging net/ipv4/tcp.c
+Auto-merging net/ipv4/route.c
+CONFLICT (content): Merge conflict in net/ipv4/route.c
+Auto-merging net/ipv4/raw.c
+Removing net/ipv4/netfilter/nf_nat_rule.c
+Auto-merging net/ipv4/netfilter/iptable_nat.c
+Removing net/ipv4/netfilter/ipt_REDIRECT.c
+Removing net/ipv4/netfilter/ipt_NETMAP.c
+Auto-merging net/ipv4/fib_trie.c
+Auto-merging net/ipv4/fib_frontend.c
+CONFLICT (content): Merge conflict in net/ipv4/fib_frontend.c
+Auto-merging net/ipv4/devinet.c
+Auto-merging net/core/sock.c
+Auto-merging net/core/skbuff.c
+Auto-merging net/core/scm.c
+Auto-merging net/core/netprio_cgroup.c
+Auto-merging net/core/dev.c
+Auto-merging net/bluetooth/mgmt.c
+Auto-merging net/bluetooth/l2cap_core.c
+Auto-merging net/bluetooth/hidp/sock.c
+Auto-merging net/bluetooth/hci_sock.c
+Auto-merging net/bluetooth/hci_core.c
+Auto-merging net/bluetooth/cmtp/sock.c
+Auto-merging net/bluetooth/bnep/sock.c
+Auto-merging net/batman-adv/soft-interface.c
+Auto-merging net/batman-adv/bat_iv_ogm.c
+CONFLICT (content): Merge conflict in net/batman-adv/bat_iv_ogm.c
+Auto-merging kernel/taskstats.c
+Auto-merging kernel/pid_namespace.c
+Auto-merging kernel/exit.c
+Auto-merging init/Kconfig
+Auto-merging include/net/sock.h
+Auto-merging include/net/netns/ipv4.h
+Removing include/net/netfilter/nf_nat_rule.h
+Removing include/net/netfilter/nf_nat_protocol.h
+Auto-merging include/net/net_namespace.h
+Auto-merging include/net/ip6_fib.h
+Auto-merging include/linux/sched.h
+Auto-merging fs/namei.c
+Removing firmware/cxgb3/t3fw-7.10.0.bin.ihex
+Auto-merging drivers/s390/net/qeth_core_main.c
+Auto-merging drivers/net/wireless/rtlwifi/rtl8192ce/sw.c
+Auto-merging drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
+Auto-merging drivers/net/wireless/rtlwifi/pci.c
+Auto-merging drivers/net/wireless/iwlwifi/pcie/trans.c
+Auto-merging drivers/net/wireless/iwlegacy/common.h
+Auto-merging drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
+Auto-merging drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c
+Auto-merging drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
+Auto-merging drivers/net/wireless/ath/ath9k/pci.c
+Auto-merging drivers/net/wireless/ath/ath9k/hw.h
+Auto-merging drivers/net/wireless/ath/ath9k/hw.c
+Auto-merging drivers/net/wireless/ath/ath9k/debug.c
+Auto-merging drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
+Auto-merging drivers/net/usb/qmi_wwan.c
+CONFLICT (content): Merge conflict in drivers/net/usb/qmi_wwan.c
+Auto-merging drivers/net/usb/asix_devices.c
+Auto-merging drivers/net/team/team.c
+CONFLICT (content): Merge conflict in drivers/net/team/team.c
+Auto-merging drivers/net/ieee802154/fakehard.c
+Auto-merging drivers/net/ieee802154/at86rf230.c
+Auto-merging drivers/net/ieee802154/Makefile
+Auto-merging drivers/net/ieee802154/Kconfig
+Auto-merging drivers/net/ethernet/realtek/r8169.c
+Removing drivers/net/ethernet/mipsnet.c
+Auto-merging drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
+Auto-merging drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+Auto-merging drivers/net/ethernet/intel/igb/igb_main.c
+Auto-merging drivers/net/ethernet/intel/e1000e/netdev.c
+Auto-merging drivers/net/ethernet/intel/e1000/e1000_main.c
+Auto-merging drivers/net/ethRecorded preimage for 'net/batman-adv/bat_iv_ogm.c'
+Resolved 'drivers/net/team/team.c' using previous resolution.
+Resolved 'drivers/net/usb/qmi_wwan.c' using previous resolution.
+Resolved 'net/ipv4/fib_frontend.c' using previous resolution.
+Resolved 'net/ipv4/route.c' using previous resolution.
+Resolved 'net/socket.c' using previous resolution.
+ernet/freescale/gianfar_ptp.c
+Removing drivers/net/ethernet/freescale/fsl_pq_mdio.h
+Auto-merging drivers/net/ethernet/emulex/benet/be_main.c
+Auto-merging drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
+Auto-merging drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+Auto-merging drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+Auto-merging drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+Auto-merging drivers/infiniband/ulp/ipoib/ipoib_main.c
+Auto-merging drivers/infiniband/ulp/ipoib/ipoib.h
+Auto-merging drivers/infiniband/hw/cxgb4/qp.c
+Auto-merging arch/powerpc/configs/ppc64_defconfig
+Auto-merging Documentation/feature-removal-schedule.txt
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+Recorded resolution for 'net/batman-adv/bat_iv_ogm.c'.
+[master 176c60d] Merge remote-tracking branch 'net-next/master'
+$ git diff -M --stat --summary HEAD^..
+ Documentation/ABI/testing/sysfs-ptp                |    6 +-
+ .../devicetree/bindings/net/can/c_can.txt          |   49 +
+ Documentation/devicetree/bindings/net/cpsw.txt     |  109 ++
+ .../devicetree/bindings/net/davinci-mdio.txt       |   33 +
+ .../devicetree/bindings/net/mdio-mux-mmioreg.txt   |   75 +
+ Documentation/feature-removal-schedule.txt         |    8 -
+ Documentation/filesystems/nfs/nfsroot.txt          |   10 +-
+ Documentation/infiniband/ipoib.txt                 |    3 +
+ Documentation/networking/batman-adv.txt            |    7 +-
+ Documentation/networking/bonding.txt               |   30 +-
+ Documentation/networking/ip-sysctl.txt             |   37 +-
+ Documentation/networking/stmmac.txt                |    5 -
+ arch/m68k/configs/amiga_defconfig                  |    1 -
+ arch/m68k/configs/apollo_defconfig                 |    1 -
+ arch/m68k/configs/atari_defconfig                  |    1 -
+ arch/m68k/configs/bvme6000_defconfig               |    1 -
+ arch/m68k/configs/hp300_defconfig                  |    1 -
+ arch/m68k/configs/mac_defconfig                    |    1 -
+ arch/m68k/configs/multi_defconfig                  |    1 -
+ arch/m68k/configs/mvme147_defconfig                |    1 -
+ arch/m68k/configs/mvme16x_defconfig                |    1 -
+ arch/m68k/configs/q40_defconfig                    |    1 -
+ arch/m68k/configs/sun3_defconfig                   |    1 -
+ arch/m68k/configs/sun3x_defconfig                  |    1 -
+ arch/mips/configs/ar7_defconfig                    |    1 -
+ arch/mips/configs/bcm47xx_defconfig                |    1 -
+ arch/mips/configs/ip22_defconfig                   |    1 -
+ arch/mips/configs/jazz_defconfig                   |    1 -
+ arch/mips/configs/malta_defconfig                  |    1 -
+ arch/mips/configs/markeins_defconfig               |    1 -
+ arch/mips/configs/nlm_xlp_defconfig                |    1 -
+ arch/mips/configs/nlm_xlr_defconfig                |    1 -
+ arch/mips/configs/rm200_defconfig                  |    1 -
+ arch/powerpc/configs/pmac32_defconfig              |    1 -
+ arch/powerpc/configs/ppc64_defconfig               |    1 -
+ arch/powerpc/configs/ppc64e_defconfig              |    1 -
+ arch/powerpc/configs/ppc6xx_defconfig              |    1 -
+ arch/tile/configs/tilegx_defconfig                 |    1 -
+ arch/tile/configs/tilepro_defconfig                |    1 -
+ arch/x86/net/bpf_jit_comp.c                        |   34 +
+ crypto/crypto_user.c                               |    7 +-
+ drivers/Makefile                                   |    1 -
+ drivers/bcma/Kconfig                               |    4 +-
+ drivers/bcma/bcma_private.h                        |    2 +
+ drivers/bcma/driver_chipcommon_nflash.c            |   28 +-
+ drivers/bcma/driver_chipcommon_pmu.c               |    4 +-
+ drivers/bcma/driver_chipcommon_sflash.c            |  123 +-
+ drivers/bcma/host_pci.c                            |   11 +-
+ drivers/bcma/host_soc.c                            |    2 +-
+ drivers/bcma/main.c                                |   27 +
+ drivers/bluetooth/bcm203x.c                        |    8 +-
+ drivers/bluetooth/bfusb.c                          |   12 +-
+ drivers/bluetooth/bluecard_cs.c                    |    5 +-
+ drivers/bluetooth/bpa10x.c                         |    8 +-
+ drivers/bluetooth/bt3c_cs.c                        |    5 +-
+ drivers/bluetooth/btmrvl_sdio.c                    |   15 +-
+ drivers/bluetooth/btsdio.c                         |    8 +-
+ drivers/bluetooth/btuart_cs.c                      |    5 +-
+ drivers/bluetooth/btusb.c                          |   13 +-
+ drivers/bluetooth/btwilink.c                       |    8 +-
+ drivers/bluetooth/dtl1_cs.c                        |    3 +-
+ drivers/connector/connector.c                      |    3 +-
+ drivers/infiniband/core/netlink.c                  |    2 +-
+ drivers/infiniband/hw/cxgb4/qp.c                   |    2 +-
+ drivers/infiniband/ulp/ipoib/Makefile              |    3 +-
+ drivers/infiniband/ulp/ipoib/ipoib.h               |   13 +
+ drivers/infiniband/ulp/ipoib/ipoib_main.c          |   25 +-
+ drivers/infiniband/ulp/ipoib/ipoib_netlink.c       |  114 ++
+ drivers/infiniband/ulp/ipoib/ipoib_vlan.c          |  102 +-
+ drivers/isdn/gigaset/common.c                      |    1 -
+ drivers/net/Kconfig                                |    4 +-
+ drivers/net/Makefile                               |    1 +
+ drivers/net/bonding/bond_main.c                    |  140 +-
+ drivers/net/can/c_can/c_can.c                      |  127 +-
+ drivers/net/can/c_can/c_can.h                      |   14 +-
+ drivers/net/can/c_can/c_can_pci.c                  |    6 +-
+ drivers/net/can/c_can/c_can_platform.c             |  123 +-
+ drivers/net/can/mscan/mpc5xxx_can.c                |    4 +-
+ drivers/net/can/sja1000/sja1000.c                  |   31 +-
+ drivers/net/can/usb/peak_usb/pcan_usb_core.c       |    8 +-
+ drivers/net/can/usb/peak_usb/pcan_usb_core.h       |    2 +-
+ drivers/net/can/usb/peak_usb/pcan_usb_pro.c        |    8 +-
+ drivers/net/ethernet/Kconfig                       |    9 -
+ drivers/net/ethernet/Makefile                      |    1 -
+ drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c    |   12 +-
+ drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h    |   16 +-
+ .../net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c    |   27 +-
+ drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h    |   51 +
+ drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c   | 1197 ++++++++----
+ drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h   |    7 +-
+ drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c   |   34 +-
+ drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h    |   14 +-
+ drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c     |    3 +-
+ drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c  |   35 +-
+ drivers/net/ethernet/broadcom/cnic.c               |  104 +-
+ drivers/net/ethernet/broadcom/cnic.h               |    5 +
+ drivers/net/ethernet/broadcom/cnic_if.h            |    4 +-
+ drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c    |   18 +-
+ drivers/net/ethernet/chelsio/cxgb4/sge.c           |    4 +-
+ drivers/net/ethernet/chelsio/cxgb4/t4_hw.c         |   12 +-
+ drivers/net/ethernet/chelsio/cxgb4/t4_regs.h       |   54 +-
+ drivers/net/ethernet/emulex/benet/be.h             |    1 +
+ drivers/net/ethernet/emulex/benet/be_cmds.c        |    2 +-
+ drivers/net/ethernet/emulex/benet/be_main.c        |   30 +-
+ drivers/net/ethernet/freescale/Kconfig             |    7 +
+ drivers/net/ethernet/freescale/Makefile            |    1 +
+ drivers/net/ethernet/freescale/fsl_pq_mdio.c       |  549 +++---
+ drivers/net/ethernet/freescale/fsl_pq_mdio.h       |   52 -
+ drivers/net/ethernet/freescale/gianfar.c           |   12 +-
+ drivers/net/ethernet/freescale/gianfar.h           |   11 +-
+ drivers/net/ethernet/freescale/gianfar_ptp.c       |    2 +-
+ drivers/net/ethernet/freescale/ucc_geth.c          |    1 -
+ drivers/net/ethernet/freescale/xgmac_mdio.c        |  274 +++
+ drivers/net/ethernet/i825xx/Kconfig                |    2 +-
+ drivers/net/ethernet/i825xx/znet.c                 |    4 +-
+ drivers/net/ethernet/intel/e1000/e1000_ethtool.c   |   39 +
+ drivers/net/ethernet/intel/e1000/e1000_main.c      |   14 +
+ drivers/net/ethernet/intel/e1000e/82571.c          |    4 +-
+ drivers/net/ethernet/intel/e1000e/ethtool.c        |   44 +-
+ drivers/net/ethernet/intel/e1000e/netdev.c         |   19 +-
+ drivers/net/ethernet/intel/e1000e/phy.c            |   31 +-
+ drivers/net/ethernet/intel/igb/e1000_82575.c       |   17 +-
+ drivers/net/ethernet/intel/igb/e1000_defines.h     |   11 +-
+ drivers/net/ethernet/intel/igb/e1000_phy.c         |   29 +-
+ drivers/net/ethernet/intel/igb/e1000_phy.h         |    5 +-
+ drivers/net/ethernet/intel/igb/e1000_regs.h        |    3 +
+ drivers/net/ethernet/intel/igb/igb.h               |   41 +-
+ drivers/net/ethernet/intel/igb/igb_ethtool.c       |  198 +-
+ drivers/net/ethernet/intel/igb/igb_main.c          |  711 ++-----
+ drivers/net/ethernet/intel/igb/igb_ptp.c           |  677 +++++--
+ drivers/net/ethernet/intel/ixgbe/Makefile          |    2 +-
+ drivers/net/ethernet/intel/ixgbe/ixgbe.h           |   35 +-
+ drivers/net/ethernet/intel/ixgbe/ixgbe_debugfs.c   |  300 +++
+ drivers/net/ethernet/intel/ixgbe/ixgbe_main.c      |  571 +++---
+ drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c       |    3 +-
+ drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c     |  105 +-
+ drivers/net/ethernet/intel/ixgbevf/defines.h       |    1 +
+ drivers/net/ethernet/intel/ixgbevf/ixgbevf.h       |    9 +-
+ drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c  |  272 ++-
+ drivers/net/ethernet/intel/ixgbevf/mbx.c           |   15 +-
+ drivers/net/ethernet/intel/ixgbevf/mbx.h           |   21 +-
+ drivers/net/ethernet/intel/ixgbevf/vf.c            |  122 +-
+ drivers/net/ethernet/intel/ixgbevf/vf.h            |    4 +
+ drivers/net/ethernet/mipsnet.c                     |  345 ----
+ drivers/net/ethernet/nvidia/forcedeth.c            |   17 +-
+ drivers/net/ethernet/realtek/r8169.c               |    4 +-
+ drivers/net/ethernet/sfc/Kconfig                   |    7 +
+ drivers/net/ethernet/sfc/Makefile                  |    1 +
+ drivers/net/ethernet/sfc/efx.c                     |  250 +--
+ drivers/net/ethernet/sfc/efx.h                     |    1 +
+ drivers/net/ethernet/sfc/ethtool.c                 |    5 +-
+ drivers/net/ethernet/sfc/falcon_boards.c           |    2 +-
+ drivers/net/ethernet/sfc/mcdi.c                    |   49 +-
+ drivers/net/ethernet/sfc/mcdi.h                    |    6 +
+ drivers/net/ethernet/sfc/mcdi_pcol.h               |   29 +-
+ drivers/net/ethernet/sfc/mtd.c                     |    7 +-
+ drivers/net/ethernet/sfc/net_driver.h              |   78 +-
+ drivers/net/ethernet/sfc/nic.c                     |    6 +-
+ drivers/net/ethernet/sfc/nic.h                     |   36 +
+ drivers/net/ethernet/sfc/ptp.c                     | 1484 +++++++++++++++
+ drivers/net/ethernet/sfc/rx.c                      |   20 +-
+ drivers/net/ethernet/sfc/siena.c                   |    1 +
+ drivers/net/ethernet/sfc/siena_sriov.c             |    7 +
+ drivers/net/ethernet/sfc/tx.c                      |  627 +++----
+ drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c  |   11 +-
+ drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c   |    1 -
+ .../net/ethernet/stmicro/stmmac/stmmac_platform.c  |   39 +-
+ drivers/net/ethernet/sun/sunbmac.c                 |    1 -
+ drivers/net/ethernet/ti/Kconfig                    |    4 +-
+ drivers/net/ethernet/ti/cpsw.c                     |  174 +-
+ drivers/net/ethernet/ti/davinci_mdio.c             |   41 +-
+ drivers/net/ethernet/tundra/tsi108_eth.c           |    1 -
+ drivers/net/ethernet/wiznet/w5100.c                |    3 +-
+ drivers/net/ethernet/wiznet/w5300.c                |    3 +-
+ drivers/net/hyperv/netvsc_drv.c                    |    2 +-
+ drivers/net/hyperv/rndis_filter.c                  |    8 +-
+ drivers/{ => net}/ieee802154/Kconfig               |   11 +
+ drivers/{ => net}/ieee802154/Makefile              |    1 +
+ drivers/{ => net}/ieee802154/at86rf230.c           |   12 +-
+ drivers/{ => net}/ieee802154/fakehard.c            |    1 -
+ drivers/{ => net}/ieee802154/fakelb.c              |    0
+ drivers/net/ieee802154/mrf24j40.c                  |  767 ++++++++
+ drivers/net/loopback.c                             |    3 +-
+ drivers/net/macvlan.c                              |    4 +-
+ drivers/net/phy/Kconfig                            |   13 +
+ drivers/net/phy/Makefile                           |    1 +
+ drivers/net/phy/dp83640.c                          |    2 +-
+ drivers/net/phy/mdio-gpio.c                        |  132 +-
+ drivers/net/phy/mdio-mux-mmioreg.c                 |  171 ++
+ drivers/net/phy/phy.c                              |   74 +-
+ drivers/net/ppp/ppp_generic.c                      |   58 +-
+ drivers/net/team/Kconfig                           |    4 +-
+ drivers/net/team/team.c                            |  343 +++-
+ drivers/net/team/team_mode_broadcast.c             |    8 +-
+ drivers/net/team/team_mode_roundrobin.c            |    8 +-
+ drivers/net/tun.c                                  |   46 +-
+ drivers/net/usb/asix_devices.c                     |   36 +-
+ drivers/net/usb/catc.c                             |   55 +-
+ drivers/net/usb/cx82310_eth.c                      |   11 +-
+ drivers/net/usb/gl620a.c                           |   10 +-
+ drivers/net/usb/kaweth.c                           |  134 +-
+ drivers/net/usb/net1080.c                          |   51 +-
+ drivers/net/usb/qmi_wwan.c                         |   51 +-
+ drivers/net/usb/rtl8150.c                          |    6 +-
+ drivers/net/usb/sierra_net.c                       |   25 +-
+ drivers/net/veth.c                                 |    3 +
+ drivers/net/virtio_net.c                           |    2 +-
+ drivers/net/wimax/i2400m/driver.c                  |    3 +-
+ drivers/net/wireless/adm8211.c                     |    4 +-
+ drivers/net/wireless/airo.c                        |   55 +-
+ drivers/net/wireless/at76c50x-usb.c                |   58 +-
+ drivers/net/wireless/ath/ath5k/ath5k.h             |    2 +-
+ drivers/net/wireless/ath/ath5k/base.c              |    5 +-
+ drivers/net/wireless/ath/ath5k/mac80211-ops.c      |    7 +-
+ drivers/net/wireless/ath/ath5k/phy.c               |   43 +-
+ drivers/net/wireless/ath/ath9k/ani.c               |    2 +-
+ drivers/net/wireless/ath/ath9k/ar9003_eeprom.c     |  270 +--
+ drivers/net/wireless/ath/ath9k/ar9003_eeprom.h     |    3 +-
+ drivers/net/wireless/ath/ath9k/ar9003_hw.c         |   57 +-
+ drivers/net/wireless/ath/ath9k/ar9003_mac.c        |    4 +-
+ drivers/net/wireless/ath/ath9k/ar9003_mci.c        |   15 +-
+ drivers/net/wireless/ath/ath9k/ar9003_mci.h        |    2 -
+ drivers/net/wireless/ath/ath9k/ar9003_phy.c        |  131 +-
+ drivers/net/wireless/ath/ath9k/ar9003_phy.h        |   71 +-
+ .../net/wireless/ath/ath9k/ar9462_2p0_initvals.h   |    2 +-
+ .../net/wireless/ath/ath9k/ar9565_1p0_initvals.h   | 1233 +++++++++++++
+ drivers/net/wireless/ath/ath9k/ath9k.h             |    4 +-
+ drivers/net/wireless/ath/ath9k/debug.c             |    3 +
+ drivers/net/wireless/ath/ath9k/debug.h             |    4 +-
+ drivers/net/wireless/ath/ath9k/eeprom.h            |    3 +-
+ drivers/net/wireless/ath/ath9k/gpio.c              |    9 +-
+ drivers/net/wireless/ath/ath9k/hif_usb.c           |   33 +-
+ drivers/net/wireless/ath/ath9k/hif_usb.h           |    4 +-
+ drivers/net/wireless/ath/ath9k/htc.h               |    1 +
+ drivers/net/wireless/ath/ath9k/htc_drv_beacon.c    |    2 +-
+ drivers/net/wireless/ath/ath9k/htc_drv_gpio.c      |   11 +-
+ drivers/net/wireless/ath/ath9k/htc_drv_init.c      |    5 +
+ drivers/net/wireless/ath/ath9k/htc_drv_main.c      |   49 +-
+ drivers/net/wireless/ath/ath9k/htc_drv_txrx.c      |    2 +-
+ drivers/net/wireless/ath/ath9k/hw.c                |   45 +-
+ drivers/net/wireless/ath/ath9k/hw.h                |    1 +
+ drivers/net/wireless/ath/ath9k/init.c              |    2 +-
+ drivers/net/wireless/ath/ath9k/main.c              |   64 +-
+ drivers/net/wireless/ath/ath9k/mci.c               |   21 +-
+ drivers/net/wireless/ath/ath9k/pci.c               |    1 +
+ drivers/net/wireless/ath/ath9k/rc.c                |  812 ++++----
+ drivers/net/wireless/ath/ath9k/rc.h                |    4 -
+ drivers/net/wireless/ath/ath9k/reg.h               |    9 +
+ drivers/net/wireless/ath/ath9k/xmit.c              |   11 +-
+ drivers/net/wireless/ath/carl9170/carl9170.h       |    5 +-
+ drivers/net/wireless/ath/carl9170/fw.c             |    1 +
+ drivers/net/wireless/ath/carl9170/mac.c            |    2 +-
+ drivers/net/wireless/ath/carl9170/main.c           |    4 +-
+ drivers/net/wireless/ath/carl9170/rx.c             |   16 +-
+ drivers/net/wireless/ath/carl9170/tx.c             |   16 +-
+ drivers/net/wireless/b43/Makefile                  |    1 +
+ drivers/net/wireless/b43/b43.h                     |   10 +-
+ drivers/net/wireless/b43/main.c                    |   54 +-
+ drivers/net/wireless/b43/phy_common.c              |   17 +-
+ drivers/net/wireless/b43/phy_common.h              |    6 +
+ drivers/net/wireless/b43/phy_n.c                   |  668 ++++++-
+ drivers/net/wireless/b43/phy_n.h                   |    1 +
+ drivers/net/wireless/b43/radio_2057.c              |  141 ++
+ drivers/net/wireless/b43/radio_2057.h              |  430 +++++
+ drivers/net/wireless/b43/tables_nphy.c             |   75 +
+ drivers/net/wireless/b43/tables_nphy.h             |   10 +
+ drivers/net/wireless/b43legacy/main.c              |    3 +-
+ drivers/net/wireless/brcm80211/Kconfig             |    8 +
+ .../net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c |    2 +
+ drivers/net/wireless/brcm80211/brcmfmac/dhd.h      |   25 +
+ drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h  |    2 +-
+ .../net/wireless/brcm80211/brcmfmac/dhd_common.c   |    8 +-
+ .../net/wireless/brcm80211/brcmfmac/dhd_linux.c    |   24 +-
+ drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c |   10 +-
+ .../net/wireless/brcm80211/brcmfmac/sdio_chip.c    |   17 +
+ drivers/net/wireless/brcm80211/brcmfmac/usb.c      |  215 ++-
+ .../net/wireless/brcm80211/brcmfmac/wl_cfg80211.c  |  583 +++++-
+ .../net/wireless/brcm80211/brcmfmac/wl_cfg80211.h  |   25 +
+ drivers/net/wireless/brcm80211/brcmsmac/aiutils.c  |    3 -
+ .../net/wireless/brcm80211/brcmsmac/mac80211_if.c  |   10 +-
+ drivers/net/wireless/brcm80211/brcmsmac/main.c     |   13 +-
+ .../net/wireless/brcm80211/include/brcm_hw_ids.h   |    1 +
+ .../net/wireless/brcm80211/include/brcmu_wifi.h    |    5 -
+ drivers/net/wireless/hostap/hostap_info.c          |    4 +-
+ drivers/net/wireless/hostap/hostap_ioctl.c         |   15 +-
+ drivers/net/wireless/hostap/hostap_main.c          |    2 +-
+ drivers/net/wireless/ipw2x00/ipw2100.c             |   11 +-
+ drivers/net/wireless/ipw2x00/ipw2200.c             |   11 +-
+ drivers/net/wireless/iwlegacy/3945-mac.c           |   12 +-
+ drivers/net/wireless/iwlegacy/4965-mac.c           |   26 +-
+ drivers/net/wireless/iwlegacy/4965.h               |    8 +-
+ drivers/net/wireless/iwlegacy/common.c             |   15 +-
+ drivers/net/wireless/iwlegacy/common.h             |    2 -
+ drivers/net/wireless/iwlwifi/dvm/agn.h             |   13 +-
+ drivers/net/wireless/iwlwifi/dvm/commands.h        |    3 +-
+ drivers/net/wireless/iwlwifi/dvm/debugfs.c         |   56 +-
+ drivers/net/wireless/iwlwifi/dvm/dev.h             |    1 +
+ drivers/net/wireless/iwlwifi/dvm/mac80211.c        |    8 +-
+ drivers/net/wireless/iwlwifi/dvm/main.c            |   24 +-
+ drivers/net/wireless/iwlwifi/dvm/rx.c              |   11 +
+ drivers/net/wireless/iwlwifi/dvm/sta.c             |    2 +-
+ drivers/net/wireless/iwlwifi/dvm/tx.c              |   18 +-
+ drivers/net/wireless/iwlwifi/iwl-devtrace.h        |   34 +-
+ drivers/net/wireless/iwlwifi/iwl-drv.c             |  141 +-
+ drivers/net/wireless/iwlwifi/iwl-drv.h             |    6 +-
+ drivers/net/wireless/iwlwifi/iwl-eeprom-parse.h    |    2 -
+ drivers/net/wireless/iwlwifi/iwl-op-mode.h         |    3 +-
+ drivers/net/wireless/iwlwifi/iwl-trans.h           |   12 +-
+ drivers/net/wireless/iwlwifi/pcie/drv.c            |    6 +
+ drivers/net/wireless/iwlwifi/pcie/internal.h       |    1 +
+ drivers/net/wireless/iwlwifi/pcie/rx.c             |   16 +-
+ drivers/net/wireless/iwlwifi/pcie/trans.c          |   28 +-
+ drivers/net/wireless/iwlwifi/pcie/tx.c             |   51 +-
+ drivers/net/wireless/libertas/cmd.c                |   16 +
+ drivers/net/wireless/libertas/cmd.h                |    1 +
+ drivers/net/wireless/libertas/main.c               |    4 +-
+ drivers/net/wireless/libertas_tf/main.c            |    4 +-
+ drivers/net/wireless/mac80211_hwsim.c              |   54 +-
+ drivers/net/wireless/mwifiex/11n.c                 |   64 +-
+ drivers/net/wireless/mwifiex/11n.h                 |   20 +-
+ drivers/net/wireless/mwifiex/11n_aggr.c            |   14 +-
+ drivers/net/wireless/mwifiex/11n_rxreorder.c       |   66 +-
+ drivers/net/wireless/mwifiex/11n_rxreorder.h       |    5 +
+ drivers/net/wireless/mwifiex/Makefile              |    2 +
+ drivers/net/wireless/mwifiex/cfg80211.c            |   68 +-
+ drivers/net/wireless/mwifiex/cmdevt.c              |    5 +-
+ drivers/net/wireless/mwifiex/decl.h                |    3 +
+ drivers/net/wireless/mwifiex/fw.h                  |   50 +-
+ drivers/net/wireless/mwifiex/init.c                |  111 +-
+ drivers/net/wireless/mwifiex/ioctl.h               |   12 +-
+ drivers/net/wireless/mwifiex/main.c                |    4 +-
+ drivers/net/wireless/mwifiex/main.h                |   47 +-
+ drivers/net/wireless/mwifiex/scan.c                |   10 +-
+ drivers/net/wireless/mwifiex/sta_cmd.c             |   58 +-
+ drivers/net/wireless/mwifiex/sta_cmdresp.c         |   38 +-
+ drivers/net/wireless/mwifiex/sta_event.c           |   64 +-
+ drivers/net/wireless/mwifiex/sta_ioctl.c           |   52 +-
+ drivers/net/wireless/mwifiex/sta_rx.c              |   38 +-
+ drivers/net/wireless/mwifiex/txrx.c                |   11 +-
+ drivers/net/wireless/mwifiex/uap_cmd.c             |   40 +-
+ drivers/net/wireless/mwifiex/uap_event.c           |  290 +++
+ drivers/net/wireless/mwifiex/uap_txrx.c            |  325 ++++
+ drivers/net/wireless/mwifiex/wmm.c                 |   68 +-
+ drivers/net/wireless/mwl8k.c                       |   17 +-
+ drivers/net/wireless/orinoco/wext.c                |    7 +-
+ drivers/net/wireless/p54/eeprom.c                  |  108 +-
+ drivers/net/wireless/p54/eeprom.h                  |   12 +
+ drivers/net/wireless/p54/lmac.h                    |    4 +-
+ drivers/net/wireless/p54/main.c                    |    3 +-
+ drivers/net/wireless/p54/p54pci.c                  |   88 +-
+ drivers/net/wireless/p54/p54pci.h                  |    1 +
+ drivers/net/wireless/p54/txrx.c                    |   15 +-
+ drivers/net/wireless/rndis_wlan.c                  |    3 -
+ drivers/net/wireless/rt2x00/rt2400pci.c            |    4 +-
+ drivers/net/wireless/rt2x00/rt2400pci.h            |   27 +-
+ drivers/net/wireless/rt2x00/rt2500pci.c            |    2 +-
+ drivers/net/wireless/rt2x00/rt2500pci.h            |   18 +-
+ drivers/net/wireless/rt2x00/rt2500usb.c            |    4 +-
+ drivers/net/wireless/rt2x00/rt2500usb.h            |   27 +-
+ drivers/net/wireless/rt2x00/rt2800.h               |   52 +-
+ drivers/net/wireless/rt2x00/rt2800lib.c            |  329 +++-
+ drivers/net/wireless/rt2x00/rt2800lib.h            |   22 +-
+ drivers/net/wireless/rt2x00/rt2800pci.c            |   82 +-
+ drivers/net/wireless/rt2x00/rt2800usb.c            |   61 +-
+ drivers/net/wireless/rt2x00/rt2x00.h               |    5 +-
+ drivers/net/wireless/rt2x00/rt2x00dev.c            |    2 +-
+ drivers/net/wireless/rt2x00/rt2x00mac.c            |    4 +-
+ drivers/net/wireless/rt2x00/rt2x00queue.c          |   20 +-
+ drivers/net/wireless/rt2x00/rt61pci.c              |   12 +-
+ drivers/net/wireless/rt2x00/rt61pci.h              |   28 +-
+ drivers/net/wireless/rt2x00/rt73usb.c              |    4 +-
+ drivers/net/wireless/rt2x00/rt73usb.h              |   34 +-
+ drivers/net/wireless/rtl818x/rtl8180/dev.c         |    6 +-
+ drivers/net/wireless/rtl818x/rtl8187/dev.c         |    6 +-
+ drivers/net/wireless/rtlwifi/Kconfig               |    8 +-
+ drivers/net/wireless/rtlwifi/base.c                |    3 +-
+ drivers/net/wireless/rtlwifi/core.c                |    8 +-
+ drivers/net/wireless/rtlwifi/pci.c                 |   16 +-
+ drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c  |   41 +-
+ drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c  |    3 +-
+ drivers/net/wireless/rtlwifi/rtl8192ce/hw.c        |    4 +-
+ drivers/net/wireless/rtlwifi/rtl8192ce/sw.c        |    2 +-
+ drivers/net/wireless/rtlwifi/rtl8192ce/trx.c       |    5 +-
+ drivers/net/wireless/rtlwifi/rtl8192ce/trx.h       |    1 +
+ drivers/net/wireless/rtlwifi/rtl8192cu/trx.c       |    7 +-
+ drivers/net/wireless/rtlwifi/rtl8192cu/trx.h       |    4 +-
+ drivers/net/wireless/rtlwifi/rtl8192de/dm.c        |   10 +-
+ drivers/net/wireless/rtlwifi/rtl8192de/fw.c        |    3 +-
+ drivers/net/wireless/rtlwifi/rtl8192de/phy.c       |    2 +-
+ drivers/net/wireless/rtlwifi/rtl8192de/trx.c       |    5 +-
+ drivers/net/wireless/rtlwifi/rtl8192de/trx.h       |    1 +
+ drivers/net/wireless/rtlwifi/rtl8192se/trx.c       |   11 +-
+ drivers/net/wireless/rtlwifi/rtl8192se/trx.h       |    1 +
+ drivers/net/wireless/rtlwifi/usb.c                 |   17 +-
+ drivers/net/wireless/rtlwifi/wifi.h                |  121 +-
+ drivers/net/wireless/ti/wl1251/main.c              |    4 +-
+ drivers/net/wireless/ti/wl18xx/main.c              |    1 -
+ drivers/net/wireless/ti/wlcore/main.c              |    6 +-
+ drivers/net/wireless/ti/wlcore/tx.c                |   61 +-
+ drivers/net/wireless/ti/wlcore/tx.h                |    4 +-
+ drivers/net/wireless/wl3501_cs.c                   |    3 +-
+ drivers/net/wireless/zd1211rw/zd_mac.c             |    9 +-
+ drivers/net/xen-netfront.c                         |    2 +-
+ drivers/ptp/ptp_clock.c                            |   16 +-
+ drivers/ptp/ptp_ixp46x.c                           |    2 +-
+ drivers/ptp/ptp_pch.c                              |    2 +-
+ drivers/ptp/ptp_private.h                          |    1 +
+ drivers/s390/net/ctcm_fsms.c                       |    2 +-
+ drivers/s390/net/ctcm_main.c                       |    2 +-
+ drivers/s390/net/lcs.c                             |    2 +-
+ drivers/s390/net/qeth_core_main.c                  |   78 +-
+ drivers/s390/net/qeth_l3_main.c                    |    2 +
+ drivers/scsi/scsi_netlink.c                        |  557 +-----
+ drivers/scsi/scsi_transport_iscsi.c                |    7 +-
+ drivers/ssb/driver_mipscore.c                      |   28 +-
+ drivers/staging/gdm72xx/netlink_k.c                |    4 +-
+ drivers/staging/winbond/wbusb.c                    |    4 +-
+ firmware/Makefile                                  |    1 -
+ firmware/cxgb3/t3fw-7.10.0.bin.ihex                | 1935 --------------------
+ fs/dlm/netlink.c                                   |    8 +-
+ fs/namei.c                                         |    6 +-
+ fs/seq_file.c                                      |    4 +
+ include/linux/Kbuild                               |    2 +
+ include/linux/bcma/bcma_driver_chipcommon.h        |  111 ++
+ include/linux/bcma/bcma_regs.h                     |    4 +
+ include/linux/etherdevice.h                        |   11 +
+ include/linux/ethtool.h                            |   17 +-
+ include/linux/filter.h                             |    7 +
+ include/linux/hash.h                               |   10 +
+ include/linux/if_arp.h                             |    1 +
+ include/linux/if_link.h                            |   11 +
+ include/linux/if_team.h                            |   11 +-
+ include/linux/if_tunnel.h                          |    3 +
+ include/linux/if_vlan.h                            |    9 +-
+ include/linux/inet_diag.h                          |    1 +
+ include/linux/inetdevice.h                         |   11 +-
+ include/linux/ip6_tunnel.h                         |   17 +
+ include/linux/ipv6.h                               |    1 +
+ include/linux/jiffies.h                            |    6 +
+ include/linux/mdio.h                               |   83 +
+ include/linux/netdevice.h                          |   41 +-
+ include/linux/netfilter.h                          |   14 +-
+ include/linux/netfilter/ipset/ip_set.h             |   15 +-
+ include/linux/netfilter/ipset/ip_set_ahash.h       |  106 +-
+ include/linux/netfilter/nf_conntrack_amanda.h      |    1 +
+ include/linux/netfilter/nf_conntrack_ftp.h         |    7 +-
+ include/linux/netfilter/nf_conntrack_h323.h        |   15 +-
+ include/linux/netfilter/nf_conntrack_irc.h         |    1 +
+ include/linux/netfilter/nf_conntrack_pptp.h        |    2 +
+ include/linux/netfilter/nf_conntrack_sip.h         |   21 +-
+ include/linux/netfilter/nf_nat.h                   |    8 +
+ include/linux/netfilter/nfnetlink_conntrack.h      |    8 +-
+ include/linux/netfilter/nfnetlink_queue.h          |    1 +
+ include/linux/netfilter/xt_time.h                  |    5 +
+ include/linux/netfilter_ipv4.h                     |    1 -
+ include/linux/netfilter_ipv6/Kbuild                |    1 +
+ include/linux/netfilter_ipv6/ip6t_NPT.h            |   16 +
+ include/linux/netlink.h                            |   40 +-
+ include/linux/nl80211.h                            |   30 +-
+ include/linux/of_mdio.h                            |   33 +
+ include/linux/packet_diag.h                        |   72 +
+ include/linux/pps_kernel.h                         |    9 +
+ include/linux/ptp_clock_kernel.h                   |   21 +-
+ include/linux/rfkill.h                             |   31 +
+ include/linux/sched.h                              |    3 +
+ include/linux/seq_file.h                           |   14 +
+ include/linux/skbuff.h                             |    9 +-
+ include/linux/snmp.h                               |   16 +-
+ include/linux/ssb/ssb_driver_chipcommon.h          |    4 +-
+ include/linux/stmmac.h                             |    1 -
+ include/linux/tcp.h                                |   49 +-
+ include/linux/tcp_metrics.h                        |   54 +
+ include/linux/tipc_config.h                        |    8 +-
+ include/net/addrconf.h                             |    2 +-
+ include/net/arp.h                                  |    3 +-
+ include/net/ax25.h                                 |    4 +-
+ include/net/bluetooth/bluetooth.h                  |   10 +
+ include/net/bluetooth/hci.h                        |   11 +
+ include/net/bluetooth/hci_core.h                   |   22 +-
+ include/net/bluetooth/l2cap.h                      |   17 +-
+ include/net/bluetooth/smp.h                        |    8 +-
+ include/net/cfg80211.h                             |   43 +-
+ include/net/checksum.h                             |    3 +
+ include/net/dst.h                                  |   10 +-
+ include/net/genetlink.h                            |   34 +-
+ include/net/ieee80211_radiotap.h                   |   11 +
+ include/net/inet_frag.h                            |    4 +-
+ include/net/inet_sock.h                            |    4 +-
+ include/net/ip.h                                   |    2 +
+ include/net/ip6_fib.h                              |    1 +
+ include/net/ip6_tunnel.h                           |   41 +-
+ include/net/ip_vs.h                                |   16 +-
+ include/net/ipv6.h                                 |   38 +-
+ include/net/llc.h                                  |    1 -
+ include/net/mac80211.h                             |   87 +-
+ include/net/ndisc.h                                |    3 +-
+ include/net/neighbour.h                            |   14 +-
+ include/net/net_namespace.h                        |   15 +
+ include/net/netfilter/nf_conntrack_ecache.h        |   32 +-
+ include/net/netfilter/nf_conntrack_expect.h        |    2 +-
+ include/net/netfilter/nf_conntrack_timeout.h       |   20 +
+ include/net/netfilter/nf_nat.h                     |    6 +-
+ include/net/netfilter/nf_nat_core.h                |    5 +-
+ include/net/netfilter/nf_nat_helper.h              |   11 +-
+ include/net/netfilter/nf_nat_l3proto.h             |   52 +
+ include/net/netfilter/nf_nat_l4proto.h             |   72 +
+ include/net/netfilter/nf_nat_protocol.h            |   67 -
+ include/net/netfilter/nf_nat_rule.h                |   15 -
+ include/net/netlink.h                              |  124 +-
+ include/net/netns/conntrack.h                      |    4 +
+ include/net/netns/ipv4.h                           |    5 +-
+ include/net/netns/ipv6.h                           |    9 +
+ include/net/netns/packet.h                         |    4 +-
+ include/net/netns/sctp.h                           |  131 ++
+ include/net/nfc/nfc.h                              |    2 +-
+ include/net/request_sock.h                         |   49 +-
+ include/net/sch_generic.h                          |    3 +-
+ include/net/scm.h                                  |   25 +-
+ include/net/sctp/sctp.h                            |   69 +-
+ include/net/sctp/sm.h                              |    8 +-
+ include/net/sctp/structs.h                         |  154 +-
+ include/net/snmp.h                                 |   10 +-
+ include/net/sock.h                                 |   38 +-
+ include/net/tcp.h                                  |   93 +-
+ include/net/xfrm.h                                 |    8 +-
+ include/scsi/scsi_netlink.h                        |   24 -
+ init/Kconfig                                       |   19 -
+ kernel/audit.c                                     |   23 +-
+ kernel/exit.c                                      |    3 +
+ kernel/fork.c                                      |    1 +
+ kernel/pid.c                                       |    1 +
+ kernel/pid_namespace.c                             |    2 +
+ kernel/taskstats.c                                 |    4 +-
+ lib/kobject_uevent.c                               |    5 +-
+ lib/nlattr.c                                       |    4 +
+ net/8021q/vlan_core.c                              |    6 +
+ net/Kconfig                                        |    2 +
+ net/appletalk/atalk_proc.c                         |    3 +-
+ net/atm/resources.c                                |    2 +-
+ net/ax25/ax25_uid.c                                |   21 +-
+ net/batman-adv/bat_iv_ogm.c                        |   86 +-
+ net/batman-adv/bridge_loop_avoidance.c             |  214 ++-
+ net/batman-adv/bridge_loop_avoidance.h             |   11 +-
+ net/batman-adv/debugfs.c                           |   12 +
+ net/batman-adv/gateway_client.c                    |   53 +-
+ net/batman-adv/hard-interface.c                    |   13 +-
+ net/batman-adv/main.c                              |   27 +-
+ net/batman-adv/main.h                              |   29 +-
+ net/batman-adv/packet.h                            |   35 +-
+ net/batman-adv/routing.c                           |   85 +-
+ net/batman-adv/send.c                              |    8 +-
+ net/batman-adv/soft-interface.c                    |   79 +-
+ net/batman-adv/soft-interface.h                    |    5 +-
+ net/batman-adv/translation-table.c                 |  416 +++--
+ net/batman-adv/translation-table.h                 |    4 +-
+ net/batman-adv/types.h                             |  120 +-
+ net/batman-adv/unicast.c                           |   16 +-
+ net/batman-adv/vis.c                               |  144 +-
+ net/batman-adv/vis.h                               |    2 +-
+ net/bluetooth/a2mp.c                               |   16 +-
+ net/bluetooth/af_bluetooth.c                       |  141 ++
+ net/bluetooth/bnep/sock.c                          |   22 +-
+ net/bluetooth/cmtp/sock.c                          |   23 +-
+ net/bluetooth/hci_core.c                           |    6 +-
+ net/bluetooth/hci_event.c                          |   93 +-
+ net/bluetooth/hci_sock.c                           |   13 +-
+ net/bluetooth/hidp/sock.c                          |   22 +-
+ net/bluetooth/l2cap_core.c                         |   32 +-
+ net/bluetooth/l2cap_sock.c                         |   22 +-
+ net/bluetooth/mgmt.c                               |   34 +-
+ net/bluetooth/rfcomm/sock.c                        |   14 +-
+ net/bluetooth/sco.c                                |   16 +-
+ net/bridge/br_fdb.c                                |   14 +-
+ net/bridge/br_netlink.c                            |    2 +-
+ net/bridge/br_private.h                            |    4 +-
+ net/bridge/br_stp_timer.c                          |    2 +-
+ net/bridge/netfilter/ebt_ulog.c                    |    3 +-
+ net/bridge/netfilter/ebtable_filter.c              |    4 +-
+ net/bridge/netfilter/ebtable_nat.c                 |    4 +-
+ net/can/gw.c                                       |    2 +-
+ net/core/dev.c                                     |  114 +-
+ net/core/dev_addr_lists.c                          |   40 +-
+ net/core/dst.c                                     |    2 +-
+ net/core/ethtool.c                                 |   12 -
+ net/core/fib_rules.c                               |    6 +-
+ net/core/filter.c                                  |   27 +-
+ net/core/link_watch.c                              |    8 +
+ net/core/neighbour.c                               |    8 +-
+ net/core/net-sysfs.c                               |   18 +-
+ net/core/netpoll.c                                 |    5 +-
+ net/core/netprio_cgroup.c                          |   41 +-
+ net/core/request_sock.c                            |   95 +
+ net/core/rtnetlink.c                               |   32 +-
+ net/core/scm.c                                     |   44 +-
+ net/core/secure_seq.c                              |    1 +
+ net/core/skbuff.c                                  |   37 +-
+ net/core/sock.c                                    |   61 +-
+ net/core/sock_diag.c                               |    3 +-
+ net/core/utils.c                                   |   20 +
+ net/dcb/dcbnl.c                                    |   18 +-
+ net/decnet/af_decnet.c                             |    4 +-
+ net/decnet/dn_dev.c                                |    6 +-
+ net/decnet/dn_route.c                              |   16 +-
+ net/decnet/dn_table.c                              |   12 +-
+ net/decnet/netfilter/dn_rtmsg.c                    |    3 +-
+ net/ieee802154/6lowpan.c                           |   53 +-
+ net/ieee802154/nl-mac.c                            |    6 +-
+ net/ieee802154/nl-phy.c                            |    6 +-
+ net/ipv4/af_inet.c                                 |   27 +-
+ net/ipv4/devinet.c                                 |   67 +-
+ net/ipv4/fib_frontend.c                            |   25 +-
+ net/ipv4/fib_semantics.c                           |    8 +-
+ net/ipv4/fib_trie.c                                |   15 +-
+ net/ipv4/igmp.c                                    |   37 +-
+ net/ipv4/inet_connection_sock.c                    |   57 +-
+ net/ipv4/inet_diag.c                               |   45 +-
+ net/ipv4/inet_fragment.c                           |    9 +-
+ net/ipv4/ip_fragment.c                             |   13 +-
+ net/ipv4/ip_gre.c                                  |   12 +
+ net/ipv4/ip_output.c                               |   74 +-
+ net/ipv4/ipconfig.c                                |   43 +-
+ net/ipv4/ipmr.c                                    |   12 +-
+ net/ipv4/netfilter.c                               |   41 +-
+ net/ipv4/netfilter/Kconfig                         |   90 +-
+ net/ipv4/netfilter/Makefile                        |   18 +-
+ net/ipv4/netfilter/ipt_MASQUERADE.c                |   18 +-
+ net/ipv4/netfilter/ipt_NETMAP.c                    |   98 -
+ net/ipv4/netfilter/ipt_REDIRECT.c                  |  110 --
+ net/ipv4/netfilter/ipt_ULOG.c                      |    3 +-
+ net/ipv4/netfilter/ipt_rpfilter.c                  |    2 +-
+ net/ipv4/netfilter/iptable_filter.c                |   10 +-
+ net/ipv4/netfilter/iptable_mangle.c                |   10 +-
+ .../{nf_nat_standalone.c => iptable_nat.c}         |  264 ++-
+ net/ipv4/netfilter/iptable_raw.c                   |   10 +-
+ net/ipv4/netfilter/iptable_security.c              |    5 +-
+ net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c     |    8 +-
+ net/ipv4/netfilter/nf_nat_h323.c                   |   71 +-
+ net/ipv4/netfilter/nf_nat_l3proto_ipv4.c           |  281 +++
+ net/ipv4/netfilter/nf_nat_pptp.c                   |   21 +-
+ net/ipv4/netfilter/nf_nat_proto_gre.c              |   30 +-
+ net/ipv4/netfilter/nf_nat_proto_icmp.c             |   24 +-
+ net/ipv4/netfilter/nf_nat_rule.c                   |  214 ---
+ net/ipv4/ping.c                                    |   22 +-
+ net/ipv4/proc.c                                    |    4 +
+ net/ipv4/raw.c                                     |    4 +-
+ net/ipv4/route.c                                   |   30 +-
+ net/ipv4/syncookies.c                              |    1 +
+ net/ipv4/sysctl_net_ipv4.c                         |   87 +-
+ net/ipv4/tcp.c                                     |  135 +-
+ net/ipv4/tcp_fastopen.c                            |   83 +-
+ net/ipv4/tcp_input.c                               |  281 +--
+ net/ipv4/tcp_ipv4.c                                |  308 +++-
+ net/ipv4/tcp_metrics.c                             |  354 +++-
+ net/ipv4/tcp_minisocks.c                           |   75 +-
+ net/ipv4/tcp_output.c                              |   27 +-
+ net/ipv4/tcp_timer.c                               |   39 +-
+ net/ipv4/udp.c                                     |    4 +-
+ net/ipv4/udp_diag.c                                |    9 +-
+ net/ipv6/Kconfig                                   |   16 +
+ net/ipv6/Makefile                                  |    1 +
+ net/ipv6/addrconf.c                                |   73 +-
+ net/ipv6/addrlabel.c                               |   24 +-
+ net/ipv6/ip6_flowlabel.c                           |   47 +-
+ net/ipv6/ip6_gre.c                                 | 1792 ++++++++++++++++++
+ net/ipv6/ip6_output.c                              |   85 +-
+ net/ipv6/ip6_tunnel.c                              |   91 +-
+ net/ipv6/ip6mr.c                                   |   10 +-
+ net/ipv6/netfilter.c                               |    8 +
+ net/ipv6/netfilter/Kconfig                         |   37 +-
+ net/ipv6/netfilter/Makefile                        |    6 +
+ net/ipv6/netfilter/ip6t_MASQUERADE.c               |  135 ++
+ net/ipv6/netfilter/ip6t_NPT.c                      |  165 ++
+ net/ipv6/netfilter/ip6table_filter.c               |    4 +-
+ net/ipv6/netfilter/ip6table_mangle.c               |    4 +-
+ net/ipv6/netfilter/ip6table_nat.c                  |  321 ++++
+ net/ipv6/netfilter/ip6table_raw.c                  |    4 +-
+ net/ipv6/netfilter/ip6table_security.c             |    5 +-
+ net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c     |  137 +-
+ net/ipv6/netfilter/nf_conntrack_reasm.c            |  218 ++-
+ net/ipv6/netfilter/nf_nat_l3proto_ipv6.c           |  288 +++
+ net/ipv6/netfilter/nf_nat_proto_icmpv6.c           |   90 +
+ net/ipv6/raw.c                                     |    3 +-
+ net/ipv6/reassembly.c                              |   89 +-
+ net/ipv6/route.c                                   |   96 +-
+ net/ipv6/syncookies.c                              |    1 +
+ net/ipv6/tcp_ipv6.c                                |   26 +-
+ net/ipv6/udp.c                                     |    3 +-
+ net/ipx/ipx_proc.c                                 |    3 +-
+ net/irda/irnetlink.c                               |    2 +-
+ net/key/af_key.c                                   |   38 +-
+ net/l2tp/Kconfig                                   |    1 +
+ net/l2tp/l2tp_eth.c                                |    3 +-
+ net/l2tp/l2tp_netlink.c                            |   24 +-
+ net/llc/llc_proc.c                                 |    2 +-
+ net/llc/llc_station.c                              |  600 +-----
+ net/llc/sysctl_net_llc.c                           |    7 -
+ net/mac80211/aes_cmac.c                            |    6 +-
+ net/mac80211/cfg.c                                 |   66 +-
+ net/mac80211/debugfs.c                             |   32 -
+ net/mac80211/driver-ops.h                          |   11 +-
+ net/mac80211/ibss.c                                |   15 +-
+ net/mac80211/ieee80211_i.h                         |   30 +-
+ net/mac80211/iface.c                               |  305 +--
+ net/mac80211/main.c                                |   21 +-
+ net/mac80211/mesh.c                                |   49 +-
+ net/mac80211/mesh.h                                |    5 +-
+ net/mac80211/mesh_hwmp.c                           |    2 -
+ net/mac80211/mesh_pathtbl.c                        |   44 +-
+ net/mac80211/mesh_plink.c                          |   82 +-
+ net/mac80211/mlme.c                                |  240 ++-
+ net/mac80211/offchannel.c                          |    6 +
+ net/mac80211/rate.h                                |    2 +-
+ net/mac80211/rx.c                                  |   60 +-
+ net/mac80211/scan.c                                |   12 +-
+ net/mac80211/status.c                              |   22 +-
+ net/mac80211/trace.h                               |   11 +-
+ net/mac80211/tx.c                                  |   71 +-
+ net/mac80211/util.c                                |   57 +-
+ net/netfilter/Kconfig                              |   83 +-
+ net/netfilter/Makefile                             |   21 +-
+ net/netfilter/core.c                               |   21 +-
+ net/netfilter/ipset/ip_set_bitmap_ip.c             |   19 +-
+ net/netfilter/ipset/ip_set_bitmap_ipmac.c          |   18 +-
+ net/netfilter/ipset/ip_set_bitmap_port.c           |    9 +-
+ net/netfilter/ipset/ip_set_core.c                  |   39 +-
+ net/netfilter/ipset/ip_set_hash_ip.c               |   15 +-
+ net/netfilter/ipset/ip_set_hash_ipport.c           |   24 +-
+ net/netfilter/ipset/ip_set_hash_ipportip.c         |   24 +-
+ net/netfilter/ipset/ip_set_hash_ipportnet.c        |   47 +-
+ net/netfilter/ipset/ip_set_hash_net.c              |   25 +-
+ net/netfilter/ipset/ip_set_hash_netiface.c         |   66 +-
+ net/netfilter/ipset/ip_set_hash_netport.c          |   36 +-
+ net/netfilter/ipset/ip_set_list_set.c              |    9 +-
+ net/netfilter/ipvs/Kconfig                         |    3 +-
+ net/netfilter/ipvs/ip_vs_app.c                     |   58 +-
+ net/netfilter/ipvs/ip_vs_core.c                    |   76 +-
+ net/netfilter/ipvs/ip_vs_ctl.c                     |   25 +-
+ net/netfilter/ipvs/ip_vs_ftp.c                     |   22 +-
+ net/netfilter/ipvs/ip_vs_xmit.c                    |  111 +-
+ net/netfilter/nf_conntrack_amanda.c                |    5 +-
+ net/netfilter/nf_conntrack_core.c                  |   15 +-
+ net/netfilter/nf_conntrack_ecache.c                |    2 +-
+ net/netfilter/nf_conntrack_ftp.c                   |   24 +-
+ net/netfilter/nf_conntrack_h323_main.c             |  232 ++-
+ net/netfilter/nf_conntrack_irc.c                   |    3 +-
+ net/netfilter/nf_conntrack_netlink.c               |  114 +-
+ net/netfilter/nf_conntrack_pptp.c                  |   18 +-
+ net/netfilter/nf_conntrack_proto.c                 |    5 -
+ net/netfilter/nf_conntrack_proto_tcp.c             |    8 +-
+ net/netfilter/nf_conntrack_sip.c                   |  143 +-
+ net/netfilter/nf_internals.h                       |    4 +-
+ net/{ipv4 => }/netfilter/nf_nat_amanda.c           |    4 +-
+ net/{ipv4 => }/netfilter/nf_nat_core.c             |  679 ++++---
+ net/{ipv4 => }/netfilter/nf_nat_ftp.c              |   34 +-
+ net/{ipv4 => }/netfilter/nf_nat_helper.c           |  109 +-
+ net/{ipv4 => }/netfilter/nf_nat_irc.c              |   10 +-
+ net/{ipv4 => }/netfilter/nf_nat_proto_common.c     |   54 +-
+ net/{ipv4 => }/netfilter/nf_nat_proto_dccp.c       |   56 +-
+ net/{ipv4 => }/netfilter/nf_nat_proto_sctp.c       |   53 +-
+ net/{ipv4 => }/netfilter/nf_nat_proto_tcp.c        |   40 +-
+ net/{ipv4 => }/netfilter/nf_nat_proto_udp.c        |   42 +-
+ net/{ipv4 => }/netfilter/nf_nat_proto_udplite.c    |   58 +-
+ net/{ipv4 => }/netfilter/nf_nat_proto_unknown.c    |   16 +-
+ net/{ipv4 => }/netfilter/nf_nat_sip.c              |  270 +--
+ net/{ipv4 => }/netfilter/nf_nat_tftp.c             |    1 -
+ net/netfilter/nf_queue.c                           |   10 +-
+ net/netfilter/nfnetlink.c                          |    2 +-
+ net/netfilter/nfnetlink_acct.c                     |   16 +-
+ net/netfilter/nfnetlink_cthelper.c                 |   17 +-
+ net/netfilter/nfnetlink_cttimeout.c                |   12 +-
+ net/netfilter/nfnetlink_log.c                      |   27 +-
+ net/netfilter/nfnetlink_queue_core.c               |   50 +-
+ net/netfilter/xt_CT.c                              |  262 ++-
+ net/netfilter/xt_LOG.c                             |    8 +-
+ net/netfilter/xt_NETMAP.c                          |  165 ++
+ net/netfilter/xt_NFQUEUE.c                         |    8 +-
+ net/netfilter/xt_NOTRACK.c                         |   53 -
+ net/netfilter/xt_REDIRECT.c                        |  190 ++
+ net/netfilter/xt_nat.c                             |  170 ++
+ net/netfilter/xt_osf.c                             |    2 +-
+ net/netfilter/xt_owner.c                           |   30 +-
+ net/netfilter/xt_recent.c                          |   13 +-
+ net/netfilter/xt_set.c                             |   22 +
+ net/netfilter/xt_socket.c                          |   12 +-
+ net/netfilter/xt_time.c                            |   24 +-
+ net/netlabel/netlabel_cipso_v4.c                   |    2 +-
+ net/netlabel/netlabel_mgmt.c                       |    4 +-
+ net/netlabel/netlabel_unlabeled.c                  |    2 +-
+ net/netlink/af_netlink.c                           |  216 ++-
+ net/netlink/genetlink.c                            |   48 +-
+ net/nfc/netlink.c                                  |   26 +-
+ net/openvswitch/actions.c                          |    6 +-
+ net/openvswitch/datapath.c                         |  453 +++--
+ net/openvswitch/datapath.h                         |   52 +-
+ net/openvswitch/dp_notify.c                        |    8 +-
+ net/openvswitch/flow.c                             |   21 +-
+ net/openvswitch/flow.h                             |    3 +-
+ net/openvswitch/vport-internal_dev.c               |    7 +-
+ net/openvswitch/vport-netdev.c                     |    2 +-
+ net/openvswitch/vport.c                            |   27 +-
+ net/openvswitch/vport.h                            |   13 +-
+ net/packet/Kconfig                                 |    8 +
+ net/packet/Makefile                                |    2 +
+ net/packet/af_packet.c                             |  145 +-
+ net/packet/diag.c                                  |  242 +++
+ net/packet/internal.h                              |  121 ++
+ net/phonet/pn_netlink.c                            |   14 +-
+ net/phonet/socket.c                                |    6 +-
+ net/rds/tcp_connect.c                              |    4 +-
+ net/rds/tcp_listen.c                               |    4 +-
+ net/rds/tcp_recv.c                                 |    4 +-
+ net/rds/tcp_send.c                                 |    4 +-
+ net/rfkill/core.c                                  |   14 +
+ net/sched/act_api.c                                |   52 +-
+ net/sched/cls_api.c                                |   16 +-
+ net/sched/cls_basic.c                              |    3 +-
+ net/sched/cls_cgroup.c                             |    3 +-
+ net/sched/cls_flow.c                               |   19 +-
+ net/sched/cls_fw.c                                 |    3 +-
+ net/sched/cls_route.c                              |    3 +-
+ net/sched/cls_rsvp.h                               |    3 +-
+ net/sched/cls_tcindex.c                            |    3 +-
+ net/sched/cls_u32.c                                |    3 +-
+ net/sched/em_meta.c                                |    2 +-
+ net/sched/sch_api.c                                |   44 +-
+ net/sched/sch_generic.c                            |   27 +-
+ net/sctp/associola.c                               |   25 +-
+ net/sctp/auth.c                                    |   20 +-
+ net/sctp/bind_addr.c                               |   20 +-
+ net/sctp/chunk.c                                   |    2 +-
+ net/sctp/endpointola.c                             |   25 +-
+ net/sctp/input.c                                   |  115 +-
+ net/sctp/ipv6.c                                    |   36 +-
+ net/sctp/objcnt.c                                  |    8 +-
+ net/sctp/output.c                                  |    2 +-
+ net/sctp/outqueue.c                                |   28 +-
+ net/sctp/primitive.c                               |    4 +-
+ net/sctp/proc.c                                    |   61 +-
+ net/sctp/protocol.c                                |  454 ++---
+ net/sctp/sm_make_chunk.c                           |   61 +-
+ net/sctp/sm_sideeffect.c                           |   26 +-
+ net/sctp/sm_statefuns.c                            |  725 ++++----
+ net/sctp/sm_statetable.c                           |   17 +-
+ net/sctp/socket.c                                  |  119 +-
+ net/sctp/sysctl.c                                  |  198 +-
+ net/sctp/transport.c                               |   23 +-
+ net/sctp/ulpqueue.c                                |   18 +-
+ net/socket.c                                       |   83 +-
+ net/tipc/bearer.c                                  |   21 +-
+ net/tipc/config.c                                  |   48 +-
+ net/tipc/core.c                                    |   22 +-
+ net/tipc/core.h                                    |   18 +-
+ net/tipc/eth_media.c                               |   29 +-
+ net/tipc/handler.c                                 |    2 +-
+ net/tipc/link.c                                    |    4 +-
+ net/tipc/name_table.c                              |   16 +-
+ net/tipc/net.c                                     |    3 +-
+ net/tipc/net.h                                     |    2 +-
+ net/tipc/netlink.c                                 |    2 +-
+ net/tipc/subscr.c                                  |    4 +-
+ net/unix/af_unix.c                                 |   17 +-
+ net/unix/diag.c                                    |   14 +-
+ net/wireless/chan.c                                |    7 +-
+ net/wireless/core.c                                |   53 +-
+ net/wireless/core.h                                |    2 +-
+ net/wireless/mlme.c                                |   26 +-
+ net/wireless/nl80211.c                             |  232 ++-
+ net/wireless/radiotap.c                            |    2 +
+ net/wireless/reg.c                                 |    6 +-
+ net/wireless/scan.c                                |    2 +-
+ net/wireless/util.c                                |   36 +-
+ net/wireless/wext-core.c                           |    8 +-
+ net/xfrm/xfrm_policy.c                             |   83 +-
+ net/xfrm/xfrm_state.c                              |   12 +-
+ net/xfrm/xfrm_user.c                               |   77 +-
+ security/selinux/netlink.c                         |    5 +-
+ 876 files changed, 30629 insertions(+), 15811 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/net/can/c_can.txt
+ create mode 100644 Documentation/devicetree/bindings/net/cpsw.txt
+ create mode 100644 Documentation/devicetree/bindings/net/davinci-mdio.txt
+ create mode 100644 Documentation/devicetree/bindings/net/mdio-mux-mmioreg.txt
+ create mode 100644 drivers/infiniband/ulp/ipoib/ipoib_netlink.c
+ delete mode 100644 drivers/net/ethernet/freescale/fsl_pq_mdio.h
+ create mode 100644 drivers/net/ethernet/freescale/xgmac_mdio.c
+ create mode 100644 drivers/net/ethernet/intel/ixgbe/ixgbe_debugfs.c
+ delete mode 100644 drivers/net/ethernet/mipsnet.c
+ create mode 100644 drivers/net/ethernet/sfc/ptp.c
+ rename drivers/{ => net}/ieee802154/Kconfig (76%)
+ rename drivers/{ => net}/ieee802154/Makefile (74%)
+ rename drivers/{ => net}/ieee802154/at86rf230.c (98%)
+ rename drivers/{ => net}/ieee802154/fakehard.c (99%)
+ rename drivers/{ => net}/ieee802154/fakelb.c (100%)
+ create mode 100644 drivers/net/ieee802154/mrf24j40.c
+ create mode 100644 drivers/net/phy/mdio-mux-mmioreg.c
+ create mode 100644 drivers/net/wireless/ath/ath9k/ar9565_1p0_initvals.h
+ create mode 100644 drivers/net/wireless/b43/radio_2057.c
+ create mode 100644 drivers/net/wireless/b43/radio_2057.h
+ create mode 100644 drivers/net/wireless/mwifiex/uap_event.c
+ create mode 100644 drivers/net/wireless/mwifiex/uap_txrx.c
+ delete mode 100644 firmware/cxgb3/t3fw-7.10.0.bin.ihex
+ create mode 100644 include/linux/netfilter_ipv6/ip6t_NPT.h
+ create mode 100644 include/linux/packet_diag.h
+ create mode 100644 include/linux/tcp_metrics.h
+ create mode 100644 include/net/netfilter/nf_nat_l3proto.h
+ create mode 100644 include/net/netfilter/nf_nat_l4proto.h
+ delete mode 100644 include/net/netfilter/nf_nat_protocol.h
+ delete mode 100644 include/net/netfilter/nf_nat_rule.h
+ create mode 100644 include/net/netns/sctp.h
+ delete mode 100644 net/ipv4/netfilter/ipt_NETMAP.c
+ delete mode 100644 net/ipv4/netfilter/ipt_REDIRECT.c
+ rename net/ipv4/netfilter/{nf_nat_standalone.c => iptable_nat.c} (52%)
+ create mode 100644 net/ipv4/netfilter/nf_nat_l3proto_ipv4.c
+ delete mode 100644 net/ipv4/netfilter/nf_nat_rule.c
+ create mode 100644 net/ipv6/ip6_gre.c
+ create mode 100644 net/ipv6/netfilter/ip6t_MASQUERADE.c
+ create mode 100644 net/ipv6/netfilter/ip6t_NPT.c
+ create mode 100644 net/ipv6/netfilter/ip6table_nat.c
+ create mode 100644 net/ipv6/netfilter/nf_nat_l3proto_ipv6.c
+ create mode 100644 net/ipv6/netfilter/nf_nat_proto_icmpv6.c
+ rename net/{ipv4 => }/netfilter/nf_nat_amanda.c (96%)
+ rename net/{ipv4 => }/netfilter/nf_nat_core.c (51%)
+ rename net/{ipv4 => }/netfilter/nf_nat_ftp.c (79%)
+ rename net/{ipv4 => }/netfilter/nf_nat_helper.c (82%)
+ rename net/{ipv4 => }/netfilter/nf_nat_irc.c (89%)
+ rename net/{ipv4 => }/netfilter/nf_nat_proto_common.c (62%)
+ rename net/{ipv4 => }/netfilter/nf_nat_proto_dccp.c (61%)
+ rename net/{ipv4 => }/netfilter/nf_nat_proto_sctp.c (61%)
+ rename net/{ipv4 => }/netfilter/nf_nat_proto_tcp.c (65%)
+ rename net/{ipv4 => }/netfilter/nf_nat_proto_udp.c (60%)
+ rename net/{ipv4 => }/netfilter/nf_nat_proto_udplite.c (58%)
+ rename net/{ipv4 => }/netfilter/nf_nat_proto_unknown.c (76%)
+ rename net/{ipv4 => }/netfilter/nf_nat_sip.c (62%)
+ rename net/{ipv4 => }/netfilter/nf_nat_tftp.c (97%)
+ create mode 100644 net/netfilter/xt_NETMAP.c
+ delete mode 100644 net/netfilter/xt_NOTRACK.c
+ create mode 100644 net/netfilter/xt_REDIRECT.c
+ create mode 100644 net/netfilter/xt_nat.c
+ create mode 100644 net/packet/diag.c
+ create mode 100644 net/packet/internal.h
+$ git am -3 ../patches/0001-net-cope-with-sock_alloc_file-API-change.patch
+Applying: net: cope with sock_alloc_file() API change
+$ git reset HEAD^
+Unstaged changes after reset:
+M	include/linux/net.h
+M	net/9p/trans_fd.c
+M	net/sctp/socket.c
+$ git add .
+$ git commit -v -a --amend
+[master ccc2145] Merge remote-tracking branch 'net-next/master'
+Merging wireless-next/master (944f8a1 ath5k: add missing breaks in ath5k_hw_set_spur_mitigation_filter)
+$ git merge wireless-next/master
+Recorded preimage for 'drivers/net/wireless/ath/ath9k/pci.c'
+Auto-merging net/wireless/reg.c
+Auto-merging net/wireless/nl80211.c
+Auto-merging net/wireless/mlme.c
+Auto-merging net/nfc/hci/llc_shdlc.c
+Auto-merging net/bluetooth/mgmt.c
+Auto-merging net/bluetooth/l2cap_core.c
+Auto-merging net/bluetooth/hci_core.c
+Removing include/net/nfc/shdlc.h
+Auto-merging include/net/nfc/nfc.h
+Auto-merging include/net/cfg80211.h
+Removing drivers/nfc/pn544.c
+Auto-merging drivers/net/wireless/mac80211_hwsim.c
+Auto-merging drivers/net/wireless/iwlwifi/pcie/trans.c
+Auto-merging drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
+Auto-merging drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c
+Auto-merging drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
+Auto-merging drivers/net/wireless/ath/ath9k/pci.c
+CONFLICT (content): Merge conflict in drivers/net/wireless/ath/ath9k/pci.c
+Auto-merging drivers/net/wireless/ath/ath9k/hw.h
+Auto-merging drivers/net/wireless/ath/ath9k/hw.c
+Auto-merging drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
+Auto-merging MAINTAINERS
+Auto-merging Documentation/feature-removal-schedule.txt
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+Recorded resolution for 'drivers/net/wireless/ath/ath9k/pci.c'.
+[master 46416e1] Merge remote-tracking branch 'wireless-next/master'
+$ git diff -M --stat --summary HEAD^..
+ Documentation/feature-removal-schedule.txt         |   12 -
+ MAINTAINERS                                        |    1 +
+ drivers/bcma/host_pci.c                            |    1 +
+ drivers/bcma/sprom.c                               |    2 +
+ drivers/bluetooth/bluecard_cs.c                    |    2 +-
+ drivers/bluetooth/btmrvl_sdio.c                    |    3 +-
+ drivers/bluetooth/btuart_cs.c                      |    2 +-
+ drivers/bluetooth/btusb.c                          |    3 +-
+ drivers/bluetooth/btwilink.c                       |   16 +-
+ drivers/bluetooth/hci_ldisc.c                      |    2 +-
+ drivers/bluetooth/hci_ll.c                         |    2 +-
+ drivers/bluetooth/hci_vhci.c                       |    2 +-
+ drivers/net/wireless/ath/ath.h                     |    1 +
+ drivers/net/wireless/ath/ath5k/base.c              |    1 +
+ drivers/net/wireless/ath/ath5k/mac80211-ops.c      |    5 +-
+ drivers/net/wireless/ath/ath5k/phy.c               |    2 +
+ drivers/net/wireless/ath/ath6kl/cfg80211.c         |    4 +-
+ drivers/net/wireless/ath/ath6kl/cfg80211.h         |    2 +-
+ drivers/net/wireless/ath/ath9k/antenna.c           |  117 ++-
+ drivers/net/wireless/ath/ath9k/ar9003_eeprom.c     |   20 +-
+ drivers/net/wireless/ath/ath9k/ar9003_mci.c        |    7 +-
+ drivers/net/wireless/ath/ath9k/ar9003_mci.h        |    4 +-
+ drivers/net/wireless/ath/ath9k/ar9003_phy.c        |   66 +-
+ drivers/net/wireless/ath/ath9k/ar9003_phy.h        |   24 +
+ .../net/wireless/ath/ath9k/ar9565_1p0_initvals.h   |  100 +-
+ drivers/net/wireless/ath/ath9k/ath9k.h             |    6 +-
+ drivers/net/wireless/ath/ath9k/gpio.c              |   58 +-
+ drivers/net/wireless/ath/ath9k/hif_usb.c           |    5 +-
+ drivers/net/wireless/ath/ath9k/htc_drv_main.c      |    2 +-
+ drivers/net/wireless/ath/ath9k/hw-ops.h            |    7 +
+ drivers/net/wireless/ath/ath9k/hw.c                |   12 +-
+ drivers/net/wireless/ath/ath9k/hw.h                |    3 +-
+ drivers/net/wireless/ath/ath9k/init.c              |   13 +
+ drivers/net/wireless/ath/ath9k/main.c              |    2 +-
+ drivers/net/wireless/ath/ath9k/mci.c               |   62 +-
+ drivers/net/wireless/ath/ath9k/pci.c               |    5 +-
+ drivers/net/wireless/ath/ath9k/rc.c                |   11 +-
+ drivers/net/wireless/ath/carl9170/mac.c            |    3 +-
+ drivers/net/wireless/ath/carl9170/main.c           |    2 +
+ drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c   |   39 +-
+ .../net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c |   25 -
+ drivers/net/wireless/brcm80211/brcmfmac/dhd.h      |    4 -
+ .../net/wireless/brcm80211/brcmfmac/dhd_common.c   |   19 +-
+ drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h  |    2 +
+ .../net/wireless/brcm80211/brcmfmac/dhd_linux.c    |   41 +-
+ drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | 1037 ++++++++------------
+ .../net/wireless/brcm80211/brcmfmac/sdio_host.h    |    2 +
+ drivers/net/wireless/brcm80211/brcmfmac/usb.c      |   90 +-
+ .../net/wireless/brcm80211/brcmfmac/wl_cfg80211.c  |  422 ++++++--
+ .../net/wireless/brcm80211/brcmfmac/wl_cfg80211.h  |  202 +++-
+ .../net/wireless/brcm80211/brcmsmac/mac80211_if.c  |    5 +-
+ drivers/net/wireless/ipw2x00/libipw_wx.c           |    2 +-
+ drivers/net/wireless/iwlegacy/common.c             |    4 +-
+ drivers/net/wireless/iwlwifi/dvm/scan.c            |    4 +-
+ drivers/net/wireless/iwlwifi/dvm/sta.c             |    7 +-
+ drivers/net/wireless/iwlwifi/dvm/ucode.c           |    4 +-
+ drivers/net/wireless/iwlwifi/iwl-drv.c             |   26 +-
+ drivers/net/wireless/iwlwifi/iwl-fw.h              |    3 +-
+ drivers/net/wireless/iwlwifi/pcie/drv.c            |   13 -
+ drivers/net/wireless/iwlwifi/pcie/internal.h       |    2 +-
+ drivers/net/wireless/iwlwifi/pcie/rx.c             |   75 +-
+ drivers/net/wireless/iwlwifi/pcie/trans.c          |   84 +-
+ drivers/net/wireless/mac80211_hwsim.c              |    5 +-
+ drivers/net/wireless/mwifiex/cfg80211.c            |    8 +-
+ drivers/net/wireless/mwifiex/ie.c                  |    2 +-
+ drivers/net/wireless/mwifiex/init.c                |    1 +
+ drivers/net/wireless/mwifiex/main.h                |    4 +-
+ drivers/net/wireless/mwifiex/sta_ioctl.c           |   13 +
+ drivers/net/wireless/p54/main.c                    |   12 +
+ drivers/net/wireless/rt2x00/rt2400pci.c            |    1 -
+ drivers/net/wireless/rt2x00/rt2500pci.c            |    1 -
+ drivers/net/wireless/rt2x00/rt2500usb.c            |    1 -
+ drivers/net/wireless/rt2x00/rt2800lib.c            |   72 +-
+ drivers/net/wireless/rt2x00/rt2800pci.c            |    1 -
+ drivers/net/wireless/rt2x00/rt2800usb.c            |    1 -
+ drivers/net/wireless/rt2x00/rt2x00.h               |   15 +-
+ drivers/net/wireless/rt2x00/rt2x00dev.c            |   33 +
+ drivers/net/wireless/rt2x00/rt2x00mac.c            |   40 -
+ drivers/net/wireless/rt2x00/rt61pci.c              |    1 -
+ drivers/net/wireless/rt2x00/rt73usb.c              |    1 -
+ drivers/nfc/Kconfig                                |   14 +-
+ drivers/nfc/Makefile                               |    1 -
+ drivers/nfc/nfcwilink.c                            |   20 +-
+ drivers/nfc/pn533.c                                |  106 +-
+ drivers/nfc/pn544.c                                |  893 -----------------
+ drivers/nfc/pn544_hci.c                            |  177 ++--
+ include/linux/ieee80211.h                          |   80 --
+ include/linux/nl80211.h                            |   24 +
+ include/net/bluetooth/hci.h                        |   21 +
+ include/net/bluetooth/hci_core.h                   |   26 +-
+ include/net/bluetooth/l2cap.h                      |    3 +-
+ include/net/bluetooth/mgmt.h                       |   16 +
+ include/net/cfg80211.h                             |   25 +-
+ include/net/mac80211.h                             |   12 +-
+ include/net/nfc/hci.h                              |   21 +-
+ include/net/nfc/llc.h                              |   54 +
+ include/net/nfc/nci.h                              |   29 +
+ include/net/nfc/nci_core.h                         |    5 +
+ include/net/nfc/nfc.h                              |    2 +-
+ include/net/nfc/shdlc.h                            |  107 --
+ net/bluetooth/af_bluetooth.c                       |   10 +-
+ net/bluetooth/hci_conn.c                           |  100 +-
+ net/bluetooth/hci_core.c                           |    6 +-
+ net/bluetooth/hci_event.c                          |   99 +-
+ net/bluetooth/l2cap_core.c                         |   17 +-
+ net/bluetooth/mgmt.c                               |   28 +-
+ net/mac80211/agg-tx.c                              |    2 +-
+ net/mac80211/cfg.c                                 |   37 +-
+ net/mac80211/chan.c                                |   67 +-
+ net/mac80211/debugfs.c                             |    4 +
+ net/mac80211/ibss.c                                |   35 +-
+ net/mac80211/ieee80211_i.h                         |   23 +-
+ net/mac80211/iface.c                               |   15 +-
+ net/mac80211/key.c                                 |    2 +-
+ net/mac80211/main.c                                |   10 +-
+ net/mac80211/mesh_plink.c                          |    3 +-
+ net/mac80211/mlme.c                                |  207 ++--
+ net/mac80211/offchannel.c                          |    3 +-
+ net/mac80211/scan.c                                |   41 +-
+ net/mac80211/sta_info.c                            |  123 +--
+ net/mac80211/sta_info.h                            |    2 +
+ net/mac80211/status.c                              |   48 +-
+ net/mac80211/tx.c                                  |    2 +-
+ net/mac80211/util.c                                |   51 +-
+ net/nfc/core.c                                     |   13 +-
+ net/nfc/hci/Makefile                               |    4 +-
+ net/nfc/hci/command.c                              |   45 +-
+ net/nfc/hci/core.c                                 |  336 ++++---
+ net/nfc/hci/hci.h                                  |   15 +-
+ net/nfc/hci/hcp.c                                  |    6 +-
+ net/nfc/hci/llc.c                                  |  170 ++++
+ net/nfc/hci/llc.h                                  |   61 ++
+ net/nfc/hci/llc_nop.c                              |   99 ++
+ net/nfc/hci/{shdlc.c => llc_shdlc.c}               |  544 +++++-----
+ net/nfc/llcp/llcp.c                                |   71 +-
+ net/nfc/llcp/llcp.h                                |    3 -
+ net/nfc/llcp/sock.c                                |    3 -
+ net/nfc/nci/core.c                                 |   91 +-
+ net/nfc/nci/ntf.c                                  |   52 +
+ net/nfc/nci/rsp.c                                  |   14 +
+ net/rfkill/core.c                                  |    8 +-
+ net/wireless/mlme.c                                |   11 +
+ net/wireless/nl80211.c                             |   34 +
+ net/wireless/nl80211.h                             |    5 +
+ net/wireless/reg.c                                 |   39 +-
+ 145 files changed, 3716 insertions(+), 3395 deletions(-)
+ delete mode 100644 drivers/nfc/pn544.c
+ create mode 100644 include/net/nfc/llc.h
+ delete mode 100644 include/net/nfc/shdlc.h
+ create mode 100644 net/nfc/hci/llc.c
+ create mode 100644 net/nfc/hci/llc.h
+ create mode 100644 net/nfc/hci/llc_nop.c
+ rename net/nfc/hci/{shdlc.c => llc_shdlc.c} (54%)
+Merging bluetooth/master (90e6274 ath5k: disable HW crypto in management frame)
+$ git merge bluetooth/master
+Already up-to-date.
+Merging mtd/master (2361f73 Merge tag 'v3.6-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux)
+$ git merge mtd/master
+Removing drivers/mtd/maps/wr_sbc82xx_flash.c
+Merge made by the 'recursive' strategy.
+ Documentation/DocBook/mtdnand.tmpl                 |    2 -
+ .../devicetree/bindings/mtd/atmel-nand.txt         |   40 +-
+ .../devicetree/bindings/mtd/gpmi-nand.txt          |    4 +
+ .../devicetree/bindings/mtd/lpc32xx-mlc.txt        |   50 +
+ .../devicetree/bindings/mtd/lpc32xx-slc.txt        |   52 +
+ arch/arm/boot/dts/imx51.dtsi                       |    7 +
+ arch/arm/boot/dts/imx53.dtsi                       |    7 +
+ arch/arm/mach-imx/clk-imx51-imx53.c                |    2 +
+ arch/arm/plat-mxc/devices/platform-mxc_nand.c      |   11 +-
+ drivers/mtd/chips/Kconfig                          |   11 +-
+ drivers/mtd/chips/cfi_cmdset_0002.c                |   67 ++
+ drivers/mtd/devices/Kconfig                        |    2 +-
+ drivers/mtd/devices/m25p80.c                       |    6 +
+ drivers/mtd/devices/spear_smi.c                    |   54 +-
+ drivers/mtd/maps/Kconfig                           |   12 -
+ drivers/mtd/maps/Makefile                          |    1 -
+ drivers/mtd/maps/wr_sbc82xx_flash.c                |  174 ----
+ drivers/mtd/mtdcore.c                              |    9 +
+ drivers/mtd/mtdoops.c                              |   14 +-
+ drivers/mtd/nand/Kconfig                           |   62 +-
+ drivers/mtd/nand/Makefile                          |    2 +
+ drivers/mtd/nand/atmel_nand.c                      |  934 +++++++++++++++--
+ drivers/mtd/nand/atmel_nand_ecc.h                  |  114 ++-
+ drivers/mtd/nand/bcm_umi_bch.c                     |    6 +-
+ drivers/mtd/nand/bf5xx_nand.c                      |    6 +-
+ drivers/mtd/nand/cafe_nand.c                       |   13 +-
+ drivers/mtd/nand/denali.c                          |   12 +-
+ drivers/mtd/nand/docg4.c                           |    8 +-
+ drivers/mtd/nand/fsl_elbc_nand.c                   |   15 +-
+ drivers/mtd/nand/fsl_ifc_nand.c                    |    5 +-
+ drivers/mtd/nand/gpmi-nand/gpmi-nand.c             |   13 +-
+ drivers/mtd/nand/lpc32xx_mlc.c                     |  925 +++++++++++++++++
+ drivers/mtd/nand/lpc32xx_slc.c                     | 1059 ++++++++++++++++++++
+ drivers/mtd/nand/mxc_nand.c                        |  141 +--
+ drivers/mtd/nand/nand_base.c                       |   50 +-
+ drivers/mtd/nand/nand_bbt.c                        |   21 +-
+ drivers/mtd/nand/nand_ids.c                        |    7 +-
+ drivers/mtd/nand/pxa3xx_nand.c                     |    5 +-
+ drivers/mtd/nand/sh_flctl.c                        |  302 +++---
+ drivers/mtd/tests/mtd_speedtest.c                  |   16 +-
+ drivers/mtd/tests/mtd_stresstest.c                 |   39 +-
+ include/linux/mtd/bbm.h                            |    7 +-
+ include/linux/mtd/mtd.h                            |    9 +-
+ include/linux/mtd/nand.h                           |   11 +-
+ include/linux/mtd/sh_flctl.h                       |   23 +-
+ 45 files changed, 3653 insertions(+), 677 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/mtd/lpc32xx-mlc.txt
+ create mode 100644 Documentation/devicetree/bindings/mtd/lpc32xx-slc.txt
+ delete mode 100644 drivers/mtd/maps/wr_sbc82xx_flash.c
+ create mode 100644 drivers/mtd/nand/lpc32xx_mlc.c
+ create mode 100644 drivers/mtd/nand/lpc32xx_slc.c
+Merging l2-mtd/master (42ae99e mtd: nandsim: BUG: Fail if overridesize is too big)
+$ git merge l2-mtd/master
+Removing drivers/mtd/nand/nand_bcm_umi.h
+Removing drivers/mtd/nand/nand_bcm_umi.c
+Removing drivers/mtd/nand/bcm_umi_nand.c
+Removing drivers/mtd/nand/bcm_umi_bch.c
+Auto-merging drivers/mtd/mtdpart.c
+Auto-merging arch/powerpc/configs/mpc83xx_defconfig
+Auto-merging MAINTAINERS
+Merge made by the 'recursive' strategy.
+ .../devicetree/bindings/arm/davinci/nand.txt       |   51 ++
+ .../devicetree/bindings/mtd/mtd-physmap.txt        |    7 +
+ MAINTAINERS                                        |    9 -
+ arch/arm/configs/bcmring_defconfig                 |    1 -
+ arch/arm/configs/cam60_defconfig                   |    1 -
+ arch/arm/configs/corgi_defconfig                   |    1 -
+ arch/arm/configs/ep93xx_defconfig                  |    1 -
+ arch/arm/configs/mini2440_defconfig                |    1 -
+ arch/arm/configs/mv78xx0_defconfig                 |    1 -
+ arch/arm/configs/nhk8815_defconfig                 |    1 -
+ arch/arm/configs/orion5x_defconfig                 |    1 -
+ arch/arm/configs/pxa3xx_defconfig                  |    1 -
+ arch/arm/configs/spitz_defconfig                   |    1 -
+ arch/arm/mach-clps711x/autcpu12.c                  |   19 +
+ arch/blackfin/configs/BF561-ACVILON_defconfig      |    1 -
+ arch/mips/configs/rb532_defconfig                  |    1 -
+ arch/powerpc/configs/83xx/mpc8313_rdb_defconfig    |    1 -
+ arch/powerpc/configs/83xx/mpc8315_rdb_defconfig    |    1 -
+ arch/powerpc/configs/mpc83xx_defconfig             |    1 -
+ drivers/mtd/Kconfig                                |    7 +
+ drivers/mtd/Makefile                               |    1 +
+ drivers/mtd/bcm47xxpart.c                          |  202 +++++++
+ drivers/mtd/chips/cfi_cmdset_0001.c                |   14 +-
+ drivers/mtd/cmdlinepart.c                          |  183 ++++---
+ drivers/mtd/devices/Kconfig                        |    8 +
+ drivers/mtd/devices/Makefile                       |    1 +
+ drivers/mtd/devices/bcm47xxsflash.c                |  105 ++++
+ drivers/mtd/devices/doc2001plus.c                  |   14 +-
+ drivers/mtd/devices/docg3.c                        |   12 +-
+ drivers/mtd/devices/m25p80.c                       |   18 +-
+ drivers/mtd/devices/spear_smi.c                    |   87 +--
+ drivers/mtd/maps/Kconfig                           |    4 +-
+ drivers/mtd/maps/autcpu12-nvram.c                  |  153 +++---
+ drivers/mtd/maps/pci.c                             |   23 -
+ drivers/mtd/maps/physmap_of.c                      |   14 +
+ drivers/mtd/maps/rbtx4939-flash.c                  |    2 -
+ drivers/mtd/maps/uclinux.c                         |   15 +-
+ drivers/mtd/mtdcore.c                              |   14 +-
+ drivers/mtd/mtdpart.c                              |    5 +-
+ drivers/mtd/nand/Kconfig                           |   37 +-
+ drivers/mtd/nand/Makefile                          |    2 +-
+ drivers/mtd/nand/ams-delta.c                       |   13 -
+ drivers/mtd/nand/atmel_nand.c                      |   65 ++-
+ drivers/mtd/nand/au1550nd.c                        |   46 --
+ drivers/mtd/nand/bcm_umi_bch.c                     |  219 --------
+ drivers/mtd/nand/bcm_umi_nand.c                    |  555 --------------------
+ drivers/mtd/nand/cafe_nand.c                       |    7 -
+ drivers/mtd/nand/cmx270_nand.c                     |   13 -
+ drivers/mtd/nand/davinci_nand.c                    |   78 ++-
+ drivers/mtd/nand/diskonchip.c                      |   63 ---
+ drivers/mtd/nand/docg4.c                           |   35 +-
+ drivers/mtd/nand/fsl_elbc_nand.c                   |   36 --
+ drivers/mtd/nand/fsl_ifc_nand.c                    |   41 --
+ drivers/mtd/nand/gpio.c                            |   54 +-
+ drivers/mtd/nand/gpmi-nand/gpmi-lib.c              |   49 +-
+ drivers/mtd/nand/gpmi-nand/gpmi-nand.c             |  136 +++--
+ drivers/mtd/nand/gpmi-nand/gpmi-nand.h             |    7 +-
+ drivers/mtd/nand/lpc32xx_mlc.c                     |   59 +--
+ drivers/mtd/nand/lpc32xx_slc.c                     |   84 ++-
+ drivers/mtd/nand/mpc5121_nfc.c                     |   22 -
+ drivers/mtd/nand/mxc_nand.c                        |   29 +-
+ drivers/mtd/nand/nand_base.c                       |   69 +--
+ drivers/mtd/nand/nand_bbt.c                        |  125 ++---
+ drivers/mtd/nand/nand_bcm_umi.c                    |  149 ------
+ drivers/mtd/nand/nand_bcm_umi.h                    |  337 ------------
+ drivers/mtd/nand/nandsim.c                         |   17 +-
+ drivers/mtd/nand/ndfc.c                            |   13 -
+ drivers/mtd/nand/nuc900_nand.c                     |   17 -
+ drivers/mtd/nand/omap2.c                           |   36 +-
+ drivers/mtd/nand/orion_nand.c                      |    1 -
+ drivers/mtd/nand/plat_nand.c                       |    5 +
+ drivers/mtd/nand/pxa3xx_nand.c                     |    7 -
+ drivers/mtd/nand/r852.c                            |   22 -
+ drivers/mtd/nand/s3c2410.c                         |  191 +++----
+ drivers/mtd/nand/sh_flctl.c                        |   27 +-
+ drivers/mtd/nand/socrates_nand.c                   |   19 -
+ drivers/mtd/nand/tmio_nand.c                       |   13 -
+ drivers/mtd/nand/txx9ndfmc.c                       |   13 -
+ drivers/mtd/nand/xway_nand.c                       |  201 +++++++
+ drivers/mtd/sm_ftl.c                               |    1 -
+ drivers/mtd/tests/Makefile                         |    1 +
+ drivers/mtd/tests/mtd_nandbiterrs.c                |  460 ++++++++++++++++
+ drivers/mtd/tests/mtd_nandecctest.c                |  294 +++++++++--
+ fs/jffs2/super.c                                   |    4 +
+ fs/jffs2/wbuf.c                                    |    8 +-
+ include/linux/bcma/bcma_driver_chipcommon.h        |    2 +
+ include/linux/mtd/lpc32xx_mlc.h                    |   20 +
+ include/linux/mtd/lpc32xx_slc.h                    |   20 +
+ include/linux/mtd/nand.h                           |   20 +-
+ 89 files changed, 2169 insertions(+), 2556 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/arm/davinci/nand.txt
+ create mode 100644 drivers/mtd/bcm47xxpart.c
+ create mode 100644 drivers/mtd/devices/bcm47xxsflash.c
+ delete mode 100644 drivers/mtd/nand/bcm_umi_bch.c
+ delete mode 100644 drivers/mtd/nand/bcm_umi_nand.c
+ delete mode 100644 drivers/mtd/nand/nand_bcm_umi.c
+ delete mode 100644 drivers/mtd/nand/nand_bcm_umi.h
+ create mode 100644 drivers/mtd/nand/xway_nand.c
+ create mode 100644 drivers/mtd/tests/mtd_nandbiterrs.c
+ create mode 100644 include/linux/mtd/lpc32xx_mlc.h
+ create mode 100644 include/linux/mtd/lpc32xx_slc.h
+Merging crypto/master (821873a hwrng: mxc-rnga - Access data via structure)
+$ git merge crypto/master
+Resolved 'crypto/Kconfig' using previous resolution.
+Auto-merging drivers/crypto/caam/key_gen.c
+Auto-merging crypto/crypto_user.c
+Auto-merging crypto/cast6_generic.c
+Auto-merging crypto/cast5_generic.c
+Auto-merging crypto/Kconfig
+CONFLICT (content): Merge conflict in crypto/Kconfig
+Auto-merging arch/powerpc/kernel/prom_init.c
+Auto-merging arch/powerpc/configs/pseries_defconfig
+Auto-merging arch/powerpc/configs/ppc64_defconfig
+Auto-merging arch/arm/Makefile
+Auto-merging MAINTAINERS
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master abcb03b] Merge remote-tracking branch 'crypto/master'
+$ git diff -M --stat --summary HEAD^..
+ MAINTAINERS                                 |   12 +
+ arch/arm/Makefile                           |    1 +
+ arch/arm/crypto/Makefile                    |    9 +
+ arch/arm/crypto/aes-armv4.S                 | 1112 ++++++++++++
+ arch/arm/crypto/aes_glue.c                  |  108 ++
+ arch/arm/crypto/sha1-armv4-large.S          |  503 ++++++
+ arch/arm/crypto/sha1_glue.c                 |  179 ++
+ arch/powerpc/configs/ppc64_defconfig        |    3 +-
+ arch/powerpc/configs/pseries_defconfig      |    3 +-
+ arch/powerpc/kernel/prom_init.c             |    4 +-
+ arch/s390/crypto/aes_s390.c                 |    5 -
+ arch/s390/crypto/des_s390.c                 |   10 -
+ arch/s390/crypto/ghash_s390.c               |    1 -
+ arch/x86/crypto/Makefile                    |    4 +
+ arch/x86/crypto/aes_glue.c                  |    1 -
+ arch/x86/crypto/aesni-intel_glue.c          |  258 ++-
+ arch/x86/crypto/blowfish_glue.c             |    4 -
+ arch/x86/crypto/camellia_glue.c             | 1382 ++++++++-------
+ arch/x86/crypto/cast5-avx-x86_64-asm_64.S   |  376 ++++
+ arch/x86/crypto/cast5_avx_glue.c            |  530 ++++++
+ arch/x86/crypto/cast6-avx-x86_64-asm_64.S   |  383 ++++
+ arch/x86/crypto/cast6_avx_glue.c            |  648 +++++++
+ arch/x86/crypto/ghash-clmulni-intel_glue.c  |    2 -
+ arch/x86/crypto/salsa20_glue.c              |    1 -
+ arch/x86/crypto/serpent_avx_glue.c          |   10 -
+ arch/x86/crypto/serpent_sse2_glue.c         |   10 -
+ arch/x86/crypto/twofish-avx-x86_64-asm_64.S |  227 ++-
+ arch/x86/crypto/twofish_avx_glue.c          |   10 -
+ arch/x86/crypto/twofish_glue.c              |    1 -
+ arch/x86/crypto/twofish_glue_3way.c         |    5 -
+ crypto/842.c                                |  182 ++
+ crypto/Kconfig                              |   75 +
+ crypto/Makefile                             |    5 +-
+ crypto/aes_generic.c                        |    1 -
+ crypto/ansi_cprng.c                         |   63 +-
+ crypto/anubis.c                             |    1 -
+ crypto/blowfish_generic.c                   |    1 -
+ crypto/camellia_generic.c                   |    1 -
+ crypto/{cast5.c => cast5_generic.c}         |   80 +-
+ crypto/{cast6.c => cast6_generic.c}         |   73 +-
+ crypto/crypto_null.c                        |   57 +-
+ crypto/crypto_user.c                        |    2 +-
+ crypto/deflate.c                            |    1 -
+ crypto/des_generic.c                        |   25 +-
+ crypto/fcrypt.c                             |    1 -
+ crypto/ghash-generic.c                      |    1 -
+ crypto/khazad.c                             |    1 -
+ crypto/krng.c                               |    1 -
+ crypto/lzo.c                                |    1 -
+ crypto/salsa20_generic.c                    |    1 -
+ crypto/seed.c                               |    1 -
+ crypto/serpent_generic.c                    |   53 +-
+ crypto/sha256_generic.c                     |   25 +-
+ crypto/sha512_generic.c                     |   20 +-
+ crypto/shash.c                              |   36 +
+ crypto/tcrypt.c                             |   82 +
+ crypto/tcrypt.h                             |    1 +
+ crypto/tea.c                                |   41 +-
+ crypto/testmgr.c                            |  210 +++
+ crypto/testmgr.h                            | 2538 +++++++++++++++++++++++++--
+ crypto/tgr192.c                             |   38 +-
+ crypto/twofish_generic.c                    |    1 -
+ crypto/vmac.c                               |   10 +-
+ crypto/wp512.c                              |   39 +-
+ drivers/char/hw_random/mxc-rnga.c           |  108 +-
+ drivers/char/hw_random/octeon-rng.c         |   17 +-
+ drivers/crypto/Kconfig                      |   22 +-
+ drivers/crypto/atmel-aes.c                  |    7 -
+ drivers/crypto/atmel-sha.c                  |    5 -
+ drivers/crypto/atmel-tdes.c                 |    6 -
+ drivers/crypto/caam/caamalg.c               |   51 +-
+ drivers/crypto/caam/caamhash.c              |   22 +-
+ drivers/crypto/caam/caamrng.c               |    9 +-
+ drivers/crypto/caam/compat.h                |    1 +
+ drivers/crypto/caam/key_gen.c               |    4 +
+ drivers/crypto/geode-aes.c                  |   18 +-
+ drivers/crypto/nx/Kconfig                   |   26 +
+ drivers/crypto/nx/Makefile                  |    5 +-
+ drivers/crypto/nx/nx-842.c                  | 1617 +++++++++++++++++
+ drivers/crypto/nx/nx-aes-cbc.c              |    1 -
+ drivers/crypto/nx/nx-aes-ccm.c              |    2 -
+ drivers/crypto/nx/nx-aes-ctr.c              |    2 -
+ drivers/crypto/nx/nx-aes-ecb.c              |    1 -
+ drivers/crypto/nx/nx-aes-gcm.c              |    2 -
+ drivers/crypto/omap-aes.c                   |    1 -
+ drivers/crypto/padlock-aes.c                |    3 -
+ drivers/crypto/s5p-sss.c                    |    1 -
+ drivers/crypto/talitos.c                    |  442 ++---
+ drivers/crypto/tegra-aes.c                  |    2 -
+ drivers/crypto/ux500/hash/hash_core.c       |    1 -
+ include/crypto/cast5.h                      |   27 +
+ include/crypto/cast6.h                      |   28 +
+ include/crypto/internal/hash.h              |    2 +
+ include/linux/nx842.h                       |   11 +
+ 94 files changed, 10114 insertions(+), 1800 deletions(-)
+ create mode 100644 arch/arm/crypto/Makefile
+ create mode 100644 arch/arm/crypto/aes-armv4.S
+ create mode 100644 arch/arm/crypto/aes_glue.c
+ create mode 100644 arch/arm/crypto/sha1-armv4-large.S
+ create mode 100644 arch/arm/crypto/sha1_glue.c
+ create mode 100644 arch/x86/crypto/cast5-avx-x86_64-asm_64.S
+ create mode 100644 arch/x86/crypto/cast5_avx_glue.c
+ create mode 100644 arch/x86/crypto/cast6-avx-x86_64-asm_64.S
+ create mode 100644 arch/x86/crypto/cast6_avx_glue.c
+ create mode 100644 crypto/842.c
+ rename crypto/{cast5.c => cast5_generic.c} (95%)
+ rename crypto/{cast6.c => cast6_generic.c} (93%)
+ create mode 100644 drivers/crypto/nx/Kconfig
+ create mode 100644 drivers/crypto/nx/nx-842.c
+ create mode 100644 include/crypto/cast5.h
+ create mode 100644 include/crypto/cast6.h
+ create mode 100644 include/linux/nx842.h
+Merging drm/drm-next (7facf16 Merge branch 'for-airlied' of git://people.freedesktop.org/~danvet/drm-intel into drm-next)
+$ git merge drm/drm-next
+Resolved 'drivers/gpu/drm/i915/i915_dma.c' using previous resolution.
+Resolved 'drivers/gpu/drm/i915/intel_sdvo.c' using previous resolution.
+Auto-merging include/drm/drm_fourcc.h
+Auto-merging include/drm/drm_crtc.h
+Auto-merging drivers/staging/omapdrm/omap_connector.c
+Auto-merging drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+Auto-merging drivers/gpu/drm/radeon/atombios_dp.c
+Auto-merging drivers/gpu/drm/i915/intel_sdvo.c
+CONFLICT (content): Merge conflict in drivers/gpu/drm/i915/intel_sdvo.c
+Auto-merging drivers/gpu/drm/i915/intel_pm.c
+Auto-merging drivers/gpu/drm/i915/intel_lvds.c
+Auto-merging drivers/gpu/drm/i915/intel_hdmi.c
+Auto-merging drivers/gpu/drm/i915/intel_dp.c
+Auto-merging drivers/gpu/drm/i915/intel_display.c
+Auto-merging drivers/gpu/drm/i915/i915_irq.c
+Auto-merging drivers/gpu/drm/i915/i915_gem_gtt.c
+Auto-merging drivers/gpu/drm/i915/i915_gem.c
+Auto-merging drivers/gpu/drm/i915/i915_dma.c
+CONFLICT (content): Merge conflict in drivers/gpu/drm/i915/i915_dma.c
+Removing drivers/gpu/drm/gma500/gem_glue.h
+Removing drivers/gpu/drm/gma500/gem_glue.c
+Auto-merging drivers/gpu/drm/exynos/exynos_drm_vidi.c
+Auto-merging drivers/gpu/drm/drm_edid.c
+Auto-merging drivers/gpu/drm/drm_crtc.c
+Auto-merging drivers/gpu/drm/ast/ast_mode.c
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master f24aece] Merge remote-tracking branch 'drm/drm-next'
+$ git diff -M --stat --summary HEAD^..
+ Documentation/DocBook/drm.tmpl                 | 2835 +++++++++++++++++++-----
+ drivers/gpu/drm/Kconfig                        |   19 +-
+ drivers/gpu/drm/Makefile                       |    3 +
+ drivers/gpu/drm/ast/ast_drv.h                  |    1 -
+ drivers/gpu/drm/ast/ast_mode.c                 |    1 +
+ drivers/gpu/drm/cirrus/cirrus_drv.h            |    1 -
+ drivers/gpu/drm/drm_cache.c                    |    3 +-
+ drivers/gpu/drm/drm_crtc.c                     |    6 +
+ drivers/gpu/drm/drm_drv.c                      |   12 +-
+ drivers/gpu/drm/drm_edid.c                     |  208 +-
+ drivers/gpu/drm/drm_edid_load.c                |   29 +-
+ drivers/gpu/drm/drm_edid_modes.h               |   42 +-
+ drivers/gpu/drm/drm_fb_cma_helper.c            |  406 ++++
+ drivers/gpu/drm/drm_fb_helper.c                |   10 +-
+ drivers/gpu/drm/drm_gem_cma_helper.c           |  251 +++
+ drivers/gpu/drm/drm_irq.c                      |    2 +-
+ drivers/gpu/drm/drm_vm.c                       |   11 +-
+ drivers/gpu/drm/exynos/exynos_drm_connector.c  |    4 +-
+ drivers/gpu/drm/exynos/exynos_drm_vidi.c       |   13 -
+ drivers/gpu/drm/gma500/Makefile                |    5 +-
+ drivers/gpu/drm/gma500/backlight.c             |   45 +
+ drivers/gpu/drm/gma500/cdv_device.c            |   72 +-
+ drivers/gpu/drm/gma500/cdv_intel_display.c     |  236 +-
+ drivers/gpu/drm/gma500/cdv_intel_dp.c          | 1951 ++++++++++++++++
+ drivers/gpu/drm/gma500/cdv_intel_hdmi.c        |    6 +-
+ drivers/gpu/drm/gma500/cdv_intel_lvds.c        |   12 +-
+ drivers/gpu/drm/gma500/framebuffer.c           |    7 +
+ drivers/gpu/drm/gma500/gem.c                   |    9 +-
+ drivers/gpu/drm/gma500/gem_glue.c              |   90 -
+ drivers/gpu/drm/gma500/gem_glue.h              |    2 -
+ drivers/gpu/drm/gma500/intel_bios.c            |  101 +
+ drivers/gpu/drm/gma500/intel_bios.h            |   46 +
+ drivers/gpu/drm/gma500/mdfld_dsi_output.c      |   13 +-
+ drivers/gpu/drm/gma500/mid_bios.c              |    8 +-
+ drivers/gpu/drm/gma500/oaktrail_hdmi.c         |    1 -
+ drivers/gpu/drm/gma500/opregion.c              |    3 +-
+ drivers/gpu/drm/gma500/psb_device.c            |    1 +
+ drivers/gpu/drm/gma500/psb_drv.h               |   20 +-
+ drivers/gpu/drm/gma500/psb_intel_drv.h         |   28 +-
+ drivers/gpu/drm/gma500/psb_intel_lvds.c        |   13 +-
+ drivers/gpu/drm/gma500/psb_intel_reg.h         |  197 +-
+ drivers/gpu/drm/gma500/psb_intel_sdvo.c        |    4 -
+ drivers/gpu/drm/i2c/ch7006_drv.c               |   16 +-
+ drivers/gpu/drm/i915/Makefile                  |    1 +
+ drivers/gpu/drm/i915/dvo.h                     |   16 +-
+ drivers/gpu/drm/i915/dvo_ch7017.c              |   21 +-
+ drivers/gpu/drm/i915/dvo_ch7xxx.c              |   17 +-
+ drivers/gpu/drm/i915/dvo_ivch.c                |   23 +-
+ drivers/gpu/drm/i915/dvo_ns2501.c              |  588 +++++
+ drivers/gpu/drm/i915/dvo_sil164.c              |   20 +-
+ drivers/gpu/drm/i915/dvo_tfp410.c              |   18 +-
+ drivers/gpu/drm/i915/i915_debugfs.c            |  237 +-
+ drivers/gpu/drm/i915/i915_dma.c                |   57 +-
+ drivers/gpu/drm/i915/i915_drv.c                |   61 +-
+ drivers/gpu/drm/i915/i915_drv.h                |  185 +-
+ drivers/gpu/drm/i915/i915_gem.c                | 1377 ++++++------
+ drivers/gpu/drm/i915/i915_gem_context.c        |   65 +-
+ drivers/gpu/drm/i915/i915_gem_dmabuf.c         |   37 +-
+ drivers/gpu/drm/i915/i915_gem_evict.c          |   44 +-
+ drivers/gpu/drm/i915/i915_gem_execbuffer.c     |  378 +---
+ drivers/gpu/drm/i915/i915_gem_gtt.c            |   21 +-
+ drivers/gpu/drm/i915/i915_irq.c                |  161 +-
+ drivers/gpu/drm/i915/i915_reg.h                |  324 ++-
+ drivers/gpu/drm/i915/i915_sysfs.c              |   17 +-
+ drivers/gpu/drm/i915/i915_trace.h              |   25 +-
+ drivers/gpu/drm/i915/intel_crt.c               |  165 +-
+ drivers/gpu/drm/i915/intel_ddi.c               |  144 +-
+ drivers/gpu/drm/i915/intel_display.c           | 1881 ++++++++++++----
+ drivers/gpu/drm/i915/intel_dp.c                |  325 +--
+ drivers/gpu/drm/i915/intel_drv.h               |  145 +-
+ drivers/gpu/drm/i915/intel_dvo.c               |  115 +-
+ drivers/gpu/drm/i915/intel_hdmi.c              |  205 +-
+ drivers/gpu/drm/i915/intel_lvds.c              |   99 +-
+ drivers/gpu/drm/i915/intel_modes.c             |    1 -
+ drivers/gpu/drm/i915/intel_overlay.c           |   60 +-
+ drivers/gpu/drm/i915/intel_pm.c                |  378 ++--
+ drivers/gpu/drm/i915/intel_ringbuffer.c        |  143 +-
+ drivers/gpu/drm/i915/intel_ringbuffer.h        |   20 +-
+ drivers/gpu/drm/i915/intel_sdvo.c              |  210 +-
+ drivers/gpu/drm/i915/intel_tv.c                |   70 +-
+ drivers/gpu/drm/mgag200/mgag200_drv.h          |    1 -
+ drivers/gpu/drm/mgag200/mgag200_mode.c         |    1 -
+ drivers/gpu/drm/nouveau/nouveau_dp.c           |    4 +-
+ drivers/gpu/drm/radeon/atombios_dp.c           |    4 +-
+ drivers/gpu/drm/shmobile/Kconfig               |   10 +
+ drivers/gpu/drm/shmobile/Makefile              |    7 +
+ drivers/gpu/drm/shmobile/shmob_drm_backlight.c |   90 +
+ drivers/gpu/drm/shmobile/shmob_drm_backlight.h |   23 +
+ drivers/gpu/drm/shmobile/shmob_drm_crtc.c      |  763 +++++++
+ drivers/gpu/drm/shmobile/shmob_drm_crtc.h      |   60 +
+ drivers/gpu/drm/shmobile/shmob_drm_drv.c       |  361 +++
+ drivers/gpu/drm/shmobile/shmob_drm_drv.h       |   47 +
+ drivers/gpu/drm/shmobile/shmob_drm_kms.c       |  160 ++
+ drivers/gpu/drm/shmobile/shmob_drm_kms.h       |   34 +
+ drivers/gpu/drm/shmobile/shmob_drm_plane.c     |  268 +++
+ drivers/gpu/drm/shmobile/shmob_drm_plane.h     |   22 +
+ drivers/gpu/drm/shmobile/shmob_drm_regs.h      |  311 +++
+ drivers/gpu/drm/ttm/ttm_bo_util.c              |    2 +-
+ drivers/gpu/drm/udl/udl_connector.c            |    3 -
+ drivers/gpu/drm/udl/udl_fb.c                   |   22 +-
+ drivers/gpu/drm/udl/udl_gem.c                  |    7 -
+ drivers/gpu/drm/udl/udl_main.c                 |    7 +-
+ drivers/gpu/drm/vmwgfx/vmwgfx_drv.c            |    1 -
+ drivers/gpu/drm/vmwgfx/vmwgfx_kms.c            |    1 -
+ drivers/staging/omapdrm/omap_connector.c       |    5 +-
+ include/drm/drm_crtc.h                         |    5 +-
+ include/drm/drm_fb_cma_helper.h                |   27 +
+ include/drm/drm_fourcc.h                       |    2 +
+ include/drm/drm_gem_cma_helper.h               |   44 +
+ include/drm/drm_sarea.h                        |    2 +
+ include/drm/i915_drm.h                         |   35 +-
+ include/linux/platform_data/shmob_drm.h        |   99 +
+ 112 files changed, 13162 insertions(+), 3663 deletions(-)
+ create mode 100644 drivers/gpu/drm/drm_fb_cma_helper.c
+ create mode 100644 drivers/gpu/drm/drm_gem_cma_helper.c
+ create mode 100644 drivers/gpu/drm/gma500/cdv_intel_dp.c
+ delete mode 100644 drivers/gpu/drm/gma500/gem_glue.c
+ delete mode 100644 drivers/gpu/drm/gma500/gem_glue.h
+ create mode 100644 drivers/gpu/drm/i915/dvo_ns2501.c
+ create mode 100644 drivers/gpu/drm/shmobile/Kconfig
+ create mode 100644 drivers/gpu/drm/shmobile/Makefile
+ create mode 100644 drivers/gpu/drm/shmobile/shmob_drm_backlight.c
+ create mode 100644 drivers/gpu/drm/shmobile/shmob_drm_backlight.h
+ create mode 100644 drivers/gpu/drm/shmobile/shmob_drm_crtc.c
+ create mode 100644 drivers/gpu/drm/shmobile/shmob_drm_crtc.h
+ create mode 100644 drivers/gpu/drm/shmobile/shmob_drm_drv.c
+ create mode 100644 drivers/gpu/drm/shmobile/shmob_drm_drv.h
+ create mode 100644 drivers/gpu/drm/shmobile/shmob_drm_kms.c
+ create mode 100644 drivers/gpu/drm/shmobile/shmob_drm_kms.h
+ create mode 100644 drivers/gpu/drm/shmobile/shmob_drm_plane.c
+ create mode 100644 drivers/gpu/drm/shmobile/shmob_drm_plane.h
+ create mode 100644 drivers/gpu/drm/shmobile/shmob_drm_regs.h
+ create mode 100644 include/drm/drm_fb_cma_helper.h
+ create mode 100644 include/drm/drm_gem_cma_helper.h
+ create mode 100644 include/linux/platform_data/shmob_drm.h
+$ git am -3 ../patches/0001-drm-i915-HDMI-update-for-API-change.patch
+Applying: drm/i915: HDMI: update for API change
+$ git reset HEAD^
+Unstaged changes after reset:
+M	drivers/gpu/drm/i915/intel_hdmi.c
+$ git add .
+$ git commit -v -a --amend
+[master 6dc9a43] Merge remote-tracking branch 'drm/drm-next'
+Merging sound/for-next (b7ef37d ARM: SAMSUNG: dma-ops: Fix dmaengine_prep_dma_cyclic() parameter list)
+$ git merge sound/for-next
+Resolved 'arch/arm/mach-imx/mach-imx27_visstrim_m10.c' using previous resolution.
+Removing sound/soc/omap/overo.c
+Removing sound/soc/omap/omap3evm.c
+Removing sound/soc/omap/omap3beagle.c
+Removing sound/soc/omap/igep0020.c
+Removing include/sound/version.h
+Auto-merging include/sound/tegra_wm8903.h
+Auto-merging include/linux/platform_data/davinci_asp.h
+Auto-merging drivers/dma/tegra20-apb-dma.c
+Auto-merging drivers/dma/ste_dma40.c
+Auto-merging drivers/dma/sirf-dma.c
+Auto-merging drivers/dma/pl330.c
+Auto-merging drivers/dma/mxs-dma.c
+Auto-merging drivers/dma/mmp_tdma.c
+Auto-merging drivers/dma/at_hdmac.c
+Auto-merging arch/arm/mach-imx/mach-imx27_visstrim_m10.c
+CONFLICT (content): Merge conflict in arch/arm/mach-imx/mach-imx27_visstrim_m10.c
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master bf36e241] Merge remote-tracking branch 'sound/for-next'
+$ git diff -M --stat --summary HEAD^..
+ .../devicetree/bindings/mfd/twl4030-audio.txt      |   46 +
+ Documentation/devicetree/bindings/sound/cs4270.txt |   21 +
+ .../bindings/sound/davinci-mcasp-audio.txt         |   45 +
+ .../devicetree/bindings/sound/omap-abe-twl6040.txt |   91 ++
+ .../devicetree/bindings/sound/omap-mcbsp.txt       |   37 +
+ .../devicetree/bindings/sound/omap-twl4030.txt     |   17 +
+ .../devicetree/bindings/sound/tlv320aic3x.txt      |   20 +
+ Documentation/sound/alsa/ALSA-Configuration.txt    |   10 +-
+ Documentation/sound/alsa/Channel-Mapping-API.txt   |  153 ++++
+ Documentation/sound/alsa/HD-Audio-Models.txt       |    3 +-
+ arch/arm/mach-davinci/asp.h                        |   49 +
+ arch/arm/mach-davinci/davinci.h                    |    3 +-
+ arch/arm/mach-davinci/devices-da8xx.c              |    8 +-
+ arch/arm/mach-davinci/devices.c                    |   11 -
+ arch/arm/mach-davinci/dm355.c                      |    2 +-
+ arch/arm/mach-davinci/dm365.c                      |    2 +-
+ arch/arm/mach-davinci/dm644x.c                     |    2 +-
+ arch/arm/mach-davinci/dm646x.c                     |    2 +-
+ arch/arm/mach-davinci/include/mach/da8xx.h         |    2 +-
+ arch/arm/mach-imx/mach-imx27_visstrim_m10.c        |   42 +-
+ arch/arm/mach-omap2/board-am3517evm.c              |   13 +
+ arch/arm/mach-omap2/board-cm-t35.c                 |    1 +
+ arch/arm/mach-omap2/board-devkit8000.c             |    1 +
+ arch/arm/mach-omap2/board-igep0020.c               |    1 +
+ arch/arm/mach-omap2/board-omap3beagle.c            |    1 +
+ arch/arm/mach-omap2/board-omap3evm.c               |    1 +
+ arch/arm/mach-omap2/board-overo.c                  |    1 +
+ arch/arm/mach-omap2/board-zoom-peripherals.c       |    9 +-
+ arch/arm/mach-omap2/include/mach/board-zoom.h      |    2 -
+ arch/arm/mach-omap2/mcbsp.c                        |  126 +--
+ arch/arm/mach-omap2/omap_hwmod_44xx_data.c         |    2 +
+ arch/arm/mach-omap2/twl-common.c                   |   27 +
+ arch/arm/mach-omap2/twl-common.h                   |    2 +
+ arch/arm/plat-omap/include/plat/mcbsp.h            |    2 -
+ arch/arm/plat-samsung/dma-ops.c                    |    3 +-
+ arch/blackfin/mach-bf527/boards/ezkit.c            |   20 +
+ arch/blackfin/mach-bf533/boards/stamp.c            |   20 +
+ arch/blackfin/mach-bf537/boards/stamp.c            |   20 +
+ arch/blackfin/mach-bf561/boards/ezkit.c            |   20 +
+ arch/blackfin/mach-bf609/boards/ezkit.c            |   19 +
+ drivers/dma/at_hdmac.c                             |    3 +-
+ drivers/dma/ep93xx_dma.c                           |    4 +-
+ drivers/dma/imx-dma.c                              |    2 +-
+ drivers/dma/imx-sdma.c                             |    2 +-
+ drivers/dma/mmp_tdma.c                             |    2 +-
+ drivers/dma/mxs-dma.c                              |    2 +-
+ drivers/dma/omap-dma.c                             |   45 +-
+ drivers/dma/pl330.c                                |    2 +-
+ drivers/dma/sa11x0-dma.c                           |    2 +-
+ drivers/dma/sirf-dma.c                             |    2 +-
+ drivers/dma/ste_dma40.c                            |    3 +-
+ drivers/dma/tegra20-apb-dma.c                      |    2 +-
+ drivers/input/misc/twl4030-vibra.c                 |   18 +-
+ drivers/mfd/twl-core.c                             |   32 +
+ drivers/mfd/twl4030-audio.c                        |  105 ++-
+ include/linux/dmaengine.h                          |    7 +-
+ include/linux/i2c/twl.h                            |    3 +-
+ include/linux/mfd/wm8994/pdata.h                   |    4 +
+ include/linux/of.h                                 |    6 +
+ include/linux/platform_data/asoc-mx27vis.h         |   11 +
+ .../linux/platform_data/davinci_asp.h              |   74 +-
+ include/linux/platform_data/omap-twl4030.h         |   32 +
+ include/sound/ac97_codec.h                         |    3 +
+ include/sound/ad1816a.h                            |    9 +-
+ include/sound/asound.h                             |   39 +
+ include/sound/compress_driver.h                    |    1 +
+ include/sound/compress_params.h                    |    1 +
+ include/sound/emu10k1.h                            |    4 +-
+ include/sound/initval.h                            |   14 +
+ include/sound/memalloc.h                           |   27 +-
+ include/sound/pcm.h                                |   87 +-
+ include/sound/soc-dai.h                            |    3 +
+ include/sound/soc-dapm.h                           |    7 +-
+ include/sound/soc.h                                |   20 +-
+ .../sound/tegra_wm8903.h                           |    7 +-
+ include/sound/tlv.h                                |    8 +
+ include/sound/version.h                            |    3 -
+ include/sound/wm0010.h                             |   27 +
+ include/sound/wm8960.h                             |    2 +-
+ include/sound/wm8993.h                             |    4 +
+ sound/core/compress_offload.c                      |   26 +
+ sound/core/control.c                               |    1 +
+ sound/core/info.c                                  |    7 +-
+ sound/core/info_oss.c                              |    3 +-
+ sound/core/oss/mixer_oss.c                         |    2 +
+ sound/core/pcm.c                                   |    4 +
+ sound/core/pcm_lib.c                               |  214 +++++
+ sound/core/pcm_memory.c                            |   26 -
+ sound/core/seq/seq_device.c                        |    2 +
+ sound/core/sgbuf.c                                 |   27 +
+ sound/core/sound.c                                 |    3 +-
+ sound/drivers/opl4/opl4_synth.c                    |    9 +-
+ sound/isa/Kconfig                                  |   12 +
+ sound/isa/Makefile                                 |    2 +
+ sound/isa/ad1816a/ad1816a.c                        |   64 +-
+ sound/isa/ad1816a/ad1816a_lib.c                    |   38 +-
+ sound/isa/cmi8328.c                                |  483 ++++++++++
+ sound/isa/gus/interwave.c                          |    5 +-
+ sound/isa/opti9xx/miro.c                           |   15 +-
+ sound/isa/opti9xx/opti92x-ad1848.c                 |   14 +-
+ sound/isa/sb/emu8000.c                             |   15 +-
+ sound/last.c                                       |    1 -
+ sound/pci/ac97/ac97_patch.c                        |   24 +-
+ sound/pci/ali5451/ali5451.c                        |   10 +-
+ sound/pci/als300.c                                 |    2 +-
+ sound/pci/als4000.c                                |    4 +-
+ sound/pci/asihpi/asihpi.c                          |    2 +-
+ sound/pci/atiixp.c                                 |   15 +-
+ sound/pci/atiixp_modem.c                           |    6 +-
+ sound/pci/azt3328.c                                |    6 +-
+ sound/pci/ca0106/ca0106.h                          |    4 +-
+ sound/pci/ca0106/ca0106_main.c                     |   30 +-
+ sound/pci/ca0106/ca0106_mixer.c                    |    4 +-
+ sound/pci/cmipci.c                                 |   12 +-
+ sound/pci/cs4281.c                                 |    6 +-
+ sound/pci/cs46xx/cs46xx.c                          |    2 +-
+ sound/pci/cs46xx/cs46xx.h                          |    2 +-
+ sound/pci/cs46xx/cs46xx_lib.c                      |    8 +-
+ sound/pci/cs46xx/cs46xx_lib.h                      |    2 +-
+ sound/pci/cs46xx/dsp_spos.c                        |    8 +-
+ sound/pci/cs46xx/dsp_spos_scb_lib.c                |    2 +-
+ sound/pci/cs5530.c                                 |    3 +-
+ sound/pci/cs5535audio/Makefile                     |    2 +-
+ sound/pci/cs5535audio/cs5535audio.c                |    2 +-
+ sound/pci/ctxfi/ctatc.c                            |    4 +-
+ sound/pci/ctxfi/ctatc.h                            |    2 +-
+ sound/pci/ctxfi/cthardware.h                       |    2 +-
+ sound/pci/ctxfi/cthw20k1.c                         |    4 +-
+ sound/pci/ctxfi/cthw20k2.c                         |    4 +-
+ sound/pci/ctxfi/ctmixer.c                          |    4 +-
+ sound/pci/ctxfi/ctmixer.h                          |    2 +-
+ sound/pci/ctxfi/ctpcm.c                            |   52 +-
+ sound/pci/ctxfi/xfi.c                              |    2 +-
+ sound/pci/echoaudio/echoaudio.c                    |   12 +-
+ sound/pci/echoaudio/echoaudio.h                    |    2 +-
+ sound/pci/emu10k1/emu10k1.c                        |    4 +-
+ sound/pci/emu10k1/emu10k1_main.c                   |    8 +-
+ sound/pci/emu10k1/emu10k1x.c                       |   21 +
+ sound/pci/emu10k1/emufx.c                          |    2 +-
+ sound/pci/emu10k1/memory.c                         |    4 +-
+ sound/pci/emu10k1/p16v.c                           |    2 +-
+ sound/pci/ens1370.c                                |   70 +-
+ sound/pci/es1938.c                                 |    6 +-
+ sound/pci/es1968.c                                 |   12 +-
+ sound/pci/fm801.c                                  |   13 +-
+ sound/pci/hda/Kconfig                              |   10 +-
+ sound/pci/hda/hda_auto_parser.c                    |    7 +-
+ sound/pci/hda/hda_codec.c                          |  270 +++---
+ sound/pci/hda/hda_codec.h                          |   82 +-
+ sound/pci/hda/hda_generic.c                        |    8 +-
+ sound/pci/hda/hda_hwdep.c                          |   43 +-
+ sound/pci/hda/hda_intel.c                          |  306 +++++--
+ sound/pci/hda/hda_jack.c                           |    5 +-
+ sound/pci/hda/hda_local.h                          |    2 +-
+ sound/pci/hda/hda_proc.c                           |    9 +-
+ sound/pci/hda/hda_trace.h                          |   26 +
+ sound/pci/hda/patch_analog.c                       |   90 +-
+ sound/pci/hda/patch_cirrus.c                       |  225 +++--
+ sound/pci/hda/patch_conexant.c                     |   31 +-
+ sound/pci/hda/patch_hdmi.c                         |  407 ++++++++-
+ sound/pci/hda/patch_realtek.c                      |   19 +-
+ sound/pci/hda/patch_sigmatel.c                     |   95 +-
+ sound/pci/hda/patch_via.c                          |   37 +-
+ sound/pci/ice1712/aureon.c                         |    4 +-
+ sound/pci/ice1712/ice1712.h                        |    2 +-
+ sound/pci/ice1712/ice1724.c                        |    4 +-
+ sound/pci/ice1712/juli.c                           |    4 +-
+ sound/pci/ice1712/prodigy_hifi.c                   |    4 +-
+ sound/pci/intel8x0.c                               |   24 +-
+ sound/pci/intel8x0m.c                              |    4 +-
+ sound/pci/korg1212/korg1212.c                      |    4 +-
+ sound/pci/maestro3.c                               |   10 +-
+ sound/pci/nm256/nm256.c                            |    4 +-
+ sound/pci/oxygen/oxygen.c                          |    2 +-
+ sound/pci/oxygen/oxygen.h                          |    2 +-
+ sound/pci/oxygen/oxygen_lib.c                      |    4 +-
+ sound/pci/oxygen/virtuoso.c                        |    2 +-
+ sound/pci/pcxhr/pcxhr.c                            |   24 +
+ sound/pci/pcxhr/pcxhr_hwdep.c                      |    6 +-
+ sound/pci/riptide/riptide.c                        |    6 +-
+ sound/pci/sis7019.c                                |    6 +-
+ sound/pci/trident/trident.c                        |    2 +-
+ sound/pci/trident/trident_main.c                   |    4 +-
+ sound/pci/via82xx.c                                |   33 +-
+ sound/pci/via82xx_modem.c                          |    4 +-
+ sound/pci/vx222/vx222.c                            |    2 +-
+ sound/pci/ymfpci/ymfpci.c                          |    2 +-
+ sound/pci/ymfpci/ymfpci.h                          |    2 +-
+ sound/pci/ymfpci/ymfpci_main.c                     |   26 +-
+ sound/soc/Kconfig                                  |    3 +-
+ sound/soc/Makefile                                 |    4 +-
+ sound/soc/blackfin/bf5xx-ad1836.c                  |   73 +-
+ sound/soc/{ep93xx => cirrus}/Kconfig               |    0
+ sound/soc/{ep93xx => cirrus}/Makefile              |    0
+ sound/soc/{ep93xx => cirrus}/edb93xx.c             |    0
+ sound/soc/{ep93xx => cirrus}/ep93xx-ac97.c         |    0
+ sound/soc/{ep93xx => cirrus}/ep93xx-i2s.c          |    0
+ sound/soc/{ep93xx => cirrus}/ep93xx-pcm.c          |    0
+ sound/soc/{ep93xx => cirrus}/ep93xx-pcm.h          |    0
+ sound/soc/{ep93xx => cirrus}/simone.c              |    0
+ sound/soc/{ep93xx => cirrus}/snappercl15.c         |    0
+ sound/soc/codecs/Kconfig                           |    4 +
+ sound/soc/codecs/Makefile                          |    2 +
+ sound/soc/codecs/ab8500-codec.c                    |   13 +-
+ sound/soc/codecs/ad1836.c                          |   88 +-
+ sound/soc/codecs/ad193x.c                          |   50 +-
+ sound/soc/codecs/ad1980.c                          |    1 -
+ sound/soc/codecs/adau1373.c                        |   12 +-
+ sound/soc/codecs/adau1701.c                        |   12 +-
+ sound/soc/codecs/ak4671.c                          |   12 +-
+ sound/soc/codecs/arizona.c                         |   68 +-
+ sound/soc/codecs/arizona.h                         |    6 +-
+ sound/soc/codecs/cs4270.c                          |  152 ++--
+ sound/soc/codecs/cs42l51.c                         |   19 +-
+ sound/soc/codecs/cs42l52.c                         |    1 -
+ sound/soc/codecs/isabelle.c                        |    1 -
+ sound/soc/codecs/lm4857.c                          |   12 +-
+ sound/soc/codecs/max98088.c                        |   18 +-
+ sound/soc/codecs/max98095.c                        |   18 +-
+ sound/soc/codecs/max9850.c                         |   12 +-
+ sound/soc/codecs/max9877.c                         |   12 +-
+ sound/soc/codecs/mc13783.c                         |   60 +-
+ sound/soc/codecs/sta32x.c                          |  151 ++--
+ sound/soc/codecs/sta529.c                          |    2 +-
+ sound/soc/codecs/stac9766.c                        |    1 -
+ sound/soc/codecs/tlv320aic26.c                     |   12 +-
+ sound/soc/codecs/tlv320aic32x4.c                   |   19 +-
+ sound/soc/codecs/tlv320aic3x.c                     |   49 +-
+ sound/soc/codecs/tlv320dac33.c                     |   19 +-
+ sound/soc/codecs/tpa6130a2.c                       |   13 +-
+ sound/soc/codecs/twl4030.c                         |  157 +++-
+ sound/soc/codecs/twl6040.c                         |   43 +-
+ sound/soc/codecs/wm0010.c                          |  944 ++++++++++++++++++++
+ sound/soc/codecs/wm2000.c                          |   12 +-
+ sound/soc/codecs/wm2200.c                          |   16 +-
+ sound/soc/codecs/wm5100.c                          |    6 +-
+ sound/soc/codecs/wm5102.c                          |   52 +-
+ sound/soc/codecs/wm5110.c                          |   18 +-
+ sound/soc/codecs/wm8510.c                          |  129 ++-
+ sound/soc/codecs/wm8523.c                          |  184 ++--
+ sound/soc/codecs/wm8580.c                          |  149 ++-
+ sound/soc/codecs/wm8711.c                          |   65 +-
+ sound/soc/codecs/wm8728.c                          |   60 +-
+ sound/soc/codecs/wm8737.c                          |  132 +--
+ sound/soc/codecs/wm8741.c                          |  115 ++-
+ sound/soc/codecs/wm8770.c                          |   19 +-
+ sound/soc/codecs/wm8776.c                          |   75 +-
+ sound/soc/codecs/wm8900.c                          |  166 ++--
+ sound/soc/codecs/wm8903.c                          |   18 +-
+ sound/soc/codecs/wm8904.c                          |    2 -
+ sound/soc/codecs/wm8940.c                          |   18 +-
+ sound/soc/codecs/wm8955.c                          |   18 +-
+ sound/soc/codecs/wm8958-dsp2.c                     |   28 +-
+ sound/soc/codecs/wm8960.c                          |  150 +++-
+ sound/soc/codecs/wm8961.c                          |  492 ++++------
+ sound/soc/codecs/wm8971.c                          |   18 +-
+ sound/soc/codecs/wm8974.c                          |   18 +-
+ sound/soc/codecs/wm8978.c                          |   18 +-
+ sound/soc/codecs/wm8983.c                          |  162 ++--
+ sound/soc/codecs/wm8990.c                          |    8 +-
+ sound/soc/codecs/wm8991.c                          |   25 +-
+ sound/soc/codecs/wm8993.c                          |    2 +
+ sound/soc/codecs/wm8994.c                          |  132 ++-
+ sound/soc/codecs/wm8994.h                          |   12 +-
+ sound/soc/codecs/wm8996.c                          |    2 +-
+ sound/soc/codecs/wm9090.c                          |   12 +-
+ sound/soc/codecs/wm9712.c                          |   12 +-
+ sound/soc/codecs/wm9713.c                          |    1 -
+ sound/soc/codecs/wm_hubs.c                         |  114 ++-
+ sound/soc/codecs/wm_hubs.h                         |    6 +
+ sound/soc/davinci/davinci-evm.c                    |   19 +-
+ sound/soc/davinci/davinci-i2s.c                    |   13 +-
+ sound/soc/davinci/davinci-mcasp.c                  |  260 +++++-
+ sound/soc/davinci/davinci-mcasp.h                  |    6 +-
+ sound/soc/davinci/davinci-pcm.c                    |   24 +-
+ sound/soc/davinci/davinci-pcm.h                    |    6 +-
+ sound/soc/davinci/davinci-sffsdr.c                 |    2 +-
+ sound/soc/davinci/davinci-vcif.c                   |    8 +
+ sound/soc/fsl/Kconfig                              |    2 +-
+ sound/soc/fsl/fsl_dma.c                            |    6 -
+ sound/soc/fsl/imx-audmux.c                         |    3 -
+ sound/soc/fsl/imx-pcm-dma.c                        |    5 +-
+ sound/soc/fsl/imx-ssi.c                            |   30 +-
+ sound/soc/fsl/mpc5200_dma.c                        |   24 +-
+ sound/soc/fsl/mpc5200_dma.h                        |    3 +
+ sound/soc/fsl/mpc5200_psc_ac97.c                   |   10 +
+ sound/soc/fsl/mpc5200_psc_i2s.c                    |    8 +
+ sound/soc/fsl/mpc8610_hpcd.c                       |   32 +-
+ sound/soc/fsl/mx27vis-aic32x4.c                    |   42 +-
+ sound/soc/fsl/p1022_ds.c                           |   31 +-
+ sound/soc/fsl/pcm030-audio-fabric.c                |  100 ++-
+ sound/soc/mid-x86/mfld_machine.c                   |    9 +
+ sound/soc/mid-x86/sst_dsp.h                        |  134 +++
+ sound/soc/mid-x86/sst_platform.c                   |  204 ++++-
+ sound/soc/mid-x86/sst_platform.h                   |   26 +-
+ sound/soc/mxs/mxs-saif.c                           |   20 +-
+ sound/soc/omap/Kconfig                             |   51 +-
+ sound/soc/omap/Makefile                            |   10 +-
+ sound/soc/omap/am3517evm.c                         |   21 +-
+ sound/soc/omap/igep0020.c                          |  120 ---
+ sound/soc/omap/mcbsp.c                             |   54 +-
+ sound/soc/omap/mcbsp.h                             |    3 -
+ sound/soc/omap/omap-abe-twl6040.c                  |  145 ++-
+ sound/soc/omap/omap-dmic.c                         |    9 +-
+ sound/soc/omap/omap-hdmi.c                         |   17 +-
+ sound/soc/omap/omap-mcbsp.c                        |  230 ++---
+ sound/soc/omap/omap-mcbsp.h                        |   20 -
+ sound/soc/omap/omap-mcpdm.c                        |   92 +-
+ sound/soc/omap/omap-pcm.c                          |  236 ++---
+ sound/soc/omap/omap-pcm.h                          |    4 +-
+ sound/soc/omap/omap-twl4030.c                      |  188 ++++
+ sound/soc/omap/omap3beagle.c                       |  150 ----
+ sound/soc/omap/omap3evm.c                          |  118 ---
+ sound/soc/omap/overo.c                             |  122 ---
+ sound/soc/omap/zoom2.c                             |    4 -
+ sound/soc/samsung/Kconfig                          |   11 +-
+ sound/soc/samsung/Makefile                         |    2 +
+ sound/soc/samsung/bells.c                          |  346 +++++++
+ sound/soc/samsung/speyside.c                       |   42 +-
+ sound/soc/sh/fsi.c                                 |   28 +-
+ sound/soc/soc-compress.c                           |  294 ++++++
+ sound/soc/soc-core.c                               |  100 ++-
+ sound/soc/soc-dapm.c                               |   44 +-
+ sound/soc/soc-dmaengine-pcm.c                      |    6 +-
+ sound/soc/soc-jack.c                               |    6 -
+ sound/soc/tegra/tegra_wm8903.c                     |    3 +-
+ sound/soc/ux500/ux500_msp_dai.c                    |    3 +
+ sound/soc/ux500/ux500_msp_i2s.c                    |    2 +
+ sound/usb/6fire/firmware.c                         |    5 +-
+ sound/usb/card.c                                   |    2 +
+ sound/usb/card.h                                   |    7 +-
+ sound/usb/endpoint.c                               |   39 +-
+ sound/usb/endpoint.h                               |    5 +-
+ sound/usb/helper.c                                 |    5 +
+ sound/usb/mixer.c                                  |    7 +
+ sound/usb/pcm.c                                    |  126 ++-
+ sound/usb/quirks-table.h                           |   53 ++
+ sound/usb/quirks.c                                 |   24 +
+ sound/usb/quirks.h                                 |   10 +
+ 339 files changed, 8984 insertions(+), 4046 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/mfd/twl4030-audio.txt
+ create mode 100644 Documentation/devicetree/bindings/sound/cs4270.txt
+ create mode 100644 Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt
+ create mode 100644 Documentation/devicetree/bindings/sound/omap-abe-twl6040.txt
+ create mode 100644 Documentation/devicetree/bindings/sound/omap-mcbsp.txt
+ create mode 100644 Documentation/devicetree/bindings/sound/omap-twl4030.txt
+ create mode 100644 Documentation/devicetree/bindings/sound/tlv320aic3x.txt
+ create mode 100644 Documentation/sound/alsa/Channel-Mapping-API.txt
+ create mode 100644 arch/arm/mach-davinci/asp.h
+ create mode 100644 include/linux/platform_data/asoc-mx27vis.h
+ rename arch/arm/mach-davinci/include/mach/asp.h => include/linux/platform_data/davinci_asp.h (56%)
+ create mode 100644 include/linux/platform_data/omap-twl4030.h
+ rename arch/arm/mach-tegra/include/mach/tegra_wm8903_pdata.h => include/sound/tegra_wm8903.h (89%)
+ delete mode 100644 include/sound/version.h
+ create mode 100644 include/sound/wm0010.h
+ create mode 100644 sound/isa/cmi8328.c
+ rename sound/soc/{ep93xx => cirrus}/Kconfig (100%)
+ rename sound/soc/{ep93xx => cirrus}/Makefile (100%)
+ rename sound/soc/{ep93xx => cirrus}/edb93xx.c (100%)
+ rename sound/soc/{ep93xx => cirrus}/ep93xx-ac97.c (100%)
+ rename sound/soc/{ep93xx => cirrus}/ep93xx-i2s.c (100%)
+ rename sound/soc/{ep93xx => cirrus}/ep93xx-pcm.c (100%)
+ rename sound/soc/{ep93xx => cirrus}/ep93xx-pcm.h (100%)
+ rename sound/soc/{ep93xx => cirrus}/simone.c (100%)
+ rename sound/soc/{ep93xx => cirrus}/snappercl15.c (100%)
+ create mode 100644 sound/soc/codecs/wm0010.c
+ create mode 100644 sound/soc/mid-x86/sst_dsp.h
+ delete mode 100644 sound/soc/omap/igep0020.c
+ create mode 100644 sound/soc/omap/omap-twl4030.c
+ delete mode 100644 sound/soc/omap/omap3beagle.c
+ delete mode 100644 sound/soc/omap/omap3evm.c
+ delete mode 100644 sound/soc/omap/overo.c
+ create mode 100644 sound/soc/samsung/bells.c
+ create mode 100644 sound/soc/soc-compress.c
+Merging sound-asoc/for-next (f76fe05 ASoC: cs4270: Remove mono support)
+$ git merge sound-asoc/for-next
+Merge made by the 'recursive' strategy.
+ .../devicetree/bindings/sound/ux500-mop500.txt     |   39 +++++++++
+ .../devicetree/bindings/sound/ux500-msp.txt        |   43 ++++++++++
+ arch/arm/mach-ux500/board-mop500-msp.c             |   79 +----------------
+ arch/arm/mach-ux500/include/mach/msp.h             |    2 -
+ include/linux/mfd/abx500/ab8500-codec.h            |    6 +-
+ sound/soc/codecs/ab8500-codec.c                    |   81 ++++++++++++++++++
+ sound/soc/codecs/cs4270.c                          |    4 +-
+ sound/soc/codecs/wm2000.c                          |   60 ++++++++++---
+ sound/soc/ux500/mop500.c                           |   47 +++++++++--
+ sound/soc/ux500/ux500_msp_dai.c                    |    6 ++
+ sound/soc/ux500/ux500_msp_i2s.c                    |   89 +++++++++++++++-----
+ sound/soc/ux500/ux500_msp_i2s.h                    |    8 +-
+ 12 files changed, 342 insertions(+), 122 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/sound/ux500-mop500.txt
+ create mode 100644 Documentation/devicetree/bindings/sound/ux500-msp.txt
+Merging quilt/rr (2feb41c virtio_mmio: Don't attempt to create empty virtqueues)
+$ git merge quilt/rr
+Recorded preimage for 'arch/xtensa/Kconfig'
+Auto-merging arch/xtensa/Kconfig
+CONFLICT (content): Merge conflict in arch/xtensa/Kconfig
+Auto-merging arch/x86/Kconfig
+Auto-merging arch/unicore32/Kconfig
+Removing arch/sparc/include/asm/module.h
+Auto-merging arch/s390/Kconfig
+Auto-merging arch/powerpc/Kconfig
+Auto-merging arch/mips/kernel/Makefile
+Auto-merging arch/mips/Kconfig
+Removing arch/m32r/include/asm/module.h
+Removing arch/h8300/include/asm/module.h
+Removing arch/cris/include/asm/module.h
+Auto-merging arch/cris/Kconfig
+Auto-merging arch/arm/Kconfig
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+Recorded resolution for 'arch/xtensa/Kconfig'.
+[master a569dd3] Merge branch 'quilt/rr'
+$ git diff -M --stat --summary HEAD^..
+ arch/Kconfig                                |   19 ++
+ arch/alpha/Kconfig                          |    2 +
+ arch/alpha/include/asm/module.h             |   10 +-
+ arch/arm/Kconfig                            |    2 +
+ arch/arm/include/asm/module.h               |    8 +-
+ arch/avr32/Kconfig                          |    2 +
+ arch/avr32/include/asm/module.h             |    6 +-
+ arch/blackfin/Kconfig                       |    2 +
+ arch/blackfin/include/asm/module.h          |    4 +-
+ arch/c6x/Kconfig                            |    1 +
+ arch/c6x/include/asm/module.h               |   12 +-
+ arch/cris/Kconfig                           |    1 +
+ arch/cris/include/asm/Kbuild                |    2 +
+ arch/cris/include/asm/module.h              |    9 -
+ arch/frv/include/asm/module.h               |    8 +-
+ arch/h8300/Kconfig                          |    1 +
+ arch/h8300/include/asm/Kbuild               |    2 +
+ arch/h8300/include/asm/module.h             |   11 -
+ arch/hexagon/Kconfig                        |    1 +
+ arch/ia64/Kconfig                           |    2 +
+ arch/ia64/include/asm/module.h              |    6 +-
+ arch/m32r/Kconfig                           |    1 +
+ arch/m32r/include/asm/Kbuild                |    2 +
+ arch/m32r/include/asm/module.h              |   10 -
+ arch/m32r/kernel/module.c                   |   15 --
+ arch/m68k/Kconfig                           |    3 +
+ arch/m68k/include/asm/module.h              |    6 +-
+ arch/microblaze/Kconfig                     |    1 +
+ arch/mips/Kconfig                           |    3 +
+ arch/mips/include/asm/module.h              |   10 +-
+ arch/mips/kernel/Makefile                   |    1 +
+ arch/mips/kernel/module-rela.c              |  145 +++++++++++++
+ arch/mips/kernel/module.c                   |  121 +----------
+ arch/mn10300/Kconfig                        |    1 +
+ arch/mn10300/include/asm/module.h           |    7 +-
+ arch/openrisc/Kconfig                       |    1 +
+ arch/parisc/Kconfig                         |    2 +
+ arch/parisc/include/asm/module.h            |   16 +-
+ arch/powerpc/Kconfig                        |    2 +
+ arch/powerpc/include/asm/module.h           |    7 +-
+ arch/s390/Kconfig                           |    3 +-
+ arch/s390/include/asm/module.h              |   18 +-
+ arch/score/Kconfig                          |    2 +
+ arch/score/include/asm/module.h             |    6 +-
+ arch/score/kernel/module.c                  |   10 -
+ arch/sh/Kconfig                             |    2 +
+ arch/sh/include/asm/module.h                |   14 +-
+ arch/sparc/Kconfig                          |    1 +
+ arch/sparc/include/asm/Kbuild               |    1 +
+ arch/sparc/include/asm/module.h             |   24 ---
+ arch/tile/Kconfig                           |    1 +
+ arch/unicore32/Kconfig                      |    1 +
+ arch/x86/Kconfig                            |    2 +
+ arch/x86/lguest/Kconfig                     |    1 -
+ arch/x86/um/Kconfig                         |    2 +
+ arch/xtensa/include/asm/module.h            |    9 +-
+ drivers/block/virtio_blk.c                  |  303 +++++++++++++++++++++++----
+ drivers/char/virtio_console.c               |  210 +++++++++++++++++--
+ drivers/lguest/lguest_device.c              |    5 +-
+ drivers/remoteproc/remoteproc_virtio.c      |    5 +-
+ drivers/rpmsg/Kconfig                       |    1 -
+ drivers/s390/kvm/kvm_virtio.c               |    5 +-
+ drivers/virtio/Kconfig                      |   17 +-
+ drivers/virtio/Makefile                     |    3 +-
+ drivers/virtio/virtio.c                     |    2 +-
+ drivers/virtio/virtio_mmio.c                |   29 ++-
+ drivers/virtio/virtio_pci.c                 |   68 +++++-
+ drivers/virtio/virtio_ring.c                |   14 +-
+ include/asm-generic/module.h                |   40 +++-
+ include/linux/moduleloader.h                |   36 +++-
+ include/linux/virtio.h                      |    2 +
+ include/linux/virtio_config.h               |   23 ++
+ include/linux/virtio_ring.h                 |    3 +-
+ kernel/module.c                             |   60 +++---
+ kernel/trace/trace.c                        |    8 +-
+ tools/virtio/virtio-trace/Makefile          |   13 ++
+ tools/virtio/virtio-trace/README            |  118 +++++++++++
+ tools/virtio/virtio-trace/trace-agent-ctl.c |  137 ++++++++++++
+ tools/virtio/virtio-trace/trace-agent-rw.c  |  192 +++++++++++++++++
+ tools/virtio/virtio-trace/trace-agent.c     |  270 ++++++++++++++++++++++++
+ tools/virtio/virtio-trace/trace-agent.h     |   75 +++++++
+ 81 files changed, 1745 insertions(+), 456 deletions(-)
+ delete mode 100644 arch/cris/include/asm/module.h
+ delete mode 100644 arch/h8300/include/asm/module.h
+ delete mode 100644 arch/m32r/include/asm/module.h
+ create mode 100644 arch/mips/kernel/module-rela.c
+ delete mode 100644 arch/sparc/include/asm/module.h
+ create mode 100644 tools/virtio/virtio-trace/Makefile
+ create mode 100644 tools/virtio/virtio-trace/README
+ create mode 100644 tools/virtio/virtio-trace/trace-agent-ctl.c
+ create mode 100644 tools/virtio/virtio-trace/trace-agent-rw.c
+ create mode 100644 tools/virtio/virtio-trace/trace-agent.c
+ create mode 100644 tools/virtio/virtio-trace/trace-agent.h
+Merging input/next (fb4f552 Input: hgpk - use %*ph to dump small buffer)
+$ git merge input/next
+Auto-merging fs/compat_ioctl.c
+Auto-merging drivers/input/misc/uinput.c
+Auto-merging drivers/input/input.c
+Merge made by the 'recursive' strategy.
+ .../devicetree/bindings/input/gpio-keys-polled.txt |   38 ++++
+ .../devicetree/bindings/input/rotary-encoder.txt   |   36 ++++
+ drivers/input/apm-power.c                          |    2 +-
+ drivers/input/ff-core.c                            |    4 +-
+ drivers/input/ff-memless.c                         |   14 +-
+ drivers/input/input.c                              |   43 +++--
+ drivers/input/joydev.c                             |    2 +-
+ drivers/input/keyboard/gpio_keys.c                 |  169 +++++++++--------
+ drivers/input/keyboard/gpio_keys_polled.c          |  147 +++++++++++++--
+ drivers/input/keyboard/omap-keypad.c               |    8 +-
+ drivers/input/keyboard/samsung-keypad.c            |   10 +-
+ drivers/input/keyboard/tegra-kbc.c                 |    2 +-
+ drivers/input/misc/rotary_encoder.c                |  140 +++++++++-----
+ drivers/input/misc/twl4030-pwrbutton.c             |    1 +
+ drivers/input/misc/uinput.c                        |  197 ++++++++++++--------
+ drivers/input/mouse/hgpk.c                         |    9 +-
+ drivers/input/mousedev.c                           |    9 +-
+ drivers/input/sparse-keymap.c                      |    4 +-
+ drivers/input/touchscreen/s3c2410_ts.c             |    2 +-
+ fs/compat_ioctl.c                                  |    2 +
+ .../mach/kbc.h => include/linux/input/tegra_kbc.h  |    0
+ include/linux/uinput.h                             |   27 +--
+ 22 files changed, 587 insertions(+), 279 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/input/gpio-keys-polled.txt
+ create mode 100644 Documentation/devicetree/bindings/input/rotary-encoder.txt
+ rename arch/arm/mach-tegra/include/mach/kbc.h => include/linux/input/tegra_kbc.h (100%)
+Merging input-mt/for-next (51c80b7 Input: bcm5974 - Convert to MT-B)
+$ git merge input-mt/for-next
+Already up-to-date.
+Merging cgroup/for-next (c0a93e2 Merge branch 'for-3.7-hierarchy' into for-next)
+$ git merge cgroup/for-next
+Auto-merging net/sched/cls_cgroup.c
+Auto-merging net/core/sock.c
+Auto-merging net/core/netprio_cgroup.c
+Auto-merging kernel/events/core.c
+Auto-merging include/net/sock.h
+Auto-merging fs/xattr.c
+Auto-merging drivers/net/tun.c
+Merge made by the 'recursive' strategy.
+ Documentation/cgroups/cgroups.txt |   92 ++++++----
+ block/blk-cgroup.c                |    8 +
+ drivers/net/tun.c                 |    1 +
+ fs/xattr.c                        |  180 ++++++++++++++++++++
+ include/linux/cgroup.h            |   40 +++--
+ include/linux/cgroup_subsys.h     |   24 +--
+ include/linux/shmem_fs.h          |    3 +-
+ include/linux/xattr.h             |   48 ++++++
+ include/net/cls_cgroup.h          |   27 +--
+ include/net/netprio_cgroup.h      |   30 ++--
+ include/net/sock.h                |    8 -
+ kernel/cgroup.c                   |  332 +++++++++++++++++++++++++------------
+ kernel/cgroup_freezer.c           |    8 +
+ kernel/events/core.c              |    7 +
+ mm/memcontrol.c                   |    7 +
+ mm/shmem.c                        |  171 ++-----------------
+ net/core/netprio_cgroup.c         |   23 ++-
+ net/core/sock.c                   |   15 +-
+ net/sched/cls_cgroup.c            |   22 +--
+ security/device_cgroup.c          |    9 +
+ 20 files changed, 660 insertions(+), 395 deletions(-)
+Merging block/for-next (1b6576c Merge branch 'for-3.7/core' into for-next)
+$ git merge block/for-next
+Auto-merging init/Kconfig
+Auto-merging include/linux/fs.h
+Auto-merging drivers/target/target_core_iblock.c
+Auto-merging drivers/md/md.c
+Auto-merging block/ioctl.c
+Auto-merging block/blk-core.c
+Auto-merging MAINTAINERS
+Merge made by the 'recursive' strategy.
+ Documentation/ABI/testing/sysfs-block |   14 +++
+ Documentation/block/biodoc.txt        |    5 -
+ MAINTAINERS                           |    2 +-
+ block/blk-core.c                      |   51 ++++----
+ block/blk-lib.c                       |  104 +++++++++++++++-
+ block/blk-merge.c                     |   53 +++-----
+ block/blk-settings.c                  |   16 +++
+ block/blk-sysfs.c                     |   44 ++++++-
+ block/blk-tag.c                       |    6 +-
+ block/blk.h                           |    5 +-
+ block/elevator.c                      |    6 +-
+ block/genhd.c                         |    6 +-
+ block/ioctl.c                         |   27 +++++
+ drivers/block/Kconfig                 |    1 +
+ drivers/block/cciss.c                 |    1 -
+ drivers/block/drbd/drbd_main.c        |   13 +-
+ drivers/block/floppy.c                |   97 +++++++--------
+ drivers/block/loop.c                  |    4 +-
+ drivers/block/osdblk.c                |    3 +-
+ drivers/block/pktcdvd.c               |   52 ++------
+ drivers/block/xen-blkback/xenbus.c    |    9 +-
+ drivers/md/dm-crypt.c                 |   16 +--
+ drivers/md/dm-io.c                    |   11 --
+ drivers/md/dm.c                       |   74 ++++--------
+ drivers/md/md.c                       |   44 +------
+ drivers/md/raid0.c                    |    1 +
+ drivers/target/target_core_iblock.c   |    9 --
+ fs/bio-integrity.c                    |   44 +++----
+ fs/bio.c                              |  215 +++++++++++++++------------------
+ fs/exofs/ore.c                        |    5 +-
+ include/linux/bio.h                   |   70 ++++++++---
+ include/linux/blk_types.h             |   36 ++++--
+ include/linux/blkdev.h                |   82 +++++++++++--
+ include/linux/fs.h                    |    1 +
+ include/linux/loop.h                  |    2 +-
+ init/Kconfig                          |    1 -
+ 36 files changed, 612 insertions(+), 518 deletions(-)
+Merging quilt/device-mapper (8c05ce4 Use the recently-added bio front_pad field to allocate struct dm_target_io.)
+$ git merge quilt/device-mapper
+Merge made by the 'recursive' strategy.
+ drivers/md/dm-bufio.c  |   13 ++--
+ drivers/md/dm-mpath.c  |   14 +++--
+ drivers/md/dm-table.c  |   61 +++++++++++++++++--
+ drivers/md/dm-thin.c   |  157 +++++++++++++++++++++++++++++++-----------------
+ drivers/md/dm-verity.c |   10 +--
+ drivers/md/dm.c        |  151 +++++++++++++++++++++++++++-------------------
+ drivers/md/dm.h        |    1 +
+ 7 files changed, 267 insertions(+), 140 deletions(-)
+Merging embedded/master (4744b43 embedded: fix vc_translate operator precedence)
+$ git merge embedded/master
+Already up-to-date.
+Merging firmware/master (6e03a20 firmware: speed up request_firmware(), v3)
+$ git merge firmware/master
+Already up-to-date.
+Merging pcmcia/master (80af9e6 pcmcia at91_cf: fix raw gpio number usage)
+$ git merge pcmcia/master
+Already up-to-date.
+Merging mmc/mmc-next (b9418b1 mmc: sdhci-s3c: Add clk_(enable/disable) in runtime suspend/resume)
+$ git merge mmc/mmc-next
+Auto-merging MAINTAINERS
+Merge made by the 'recursive' strategy.
+ .../devicetree/bindings/mmc/atmel-hsmci.txt        |   68 +
+ .../devicetree/bindings/mmc/exynos-dw-mshc.txt     |   87 ++
+ Documentation/devicetree/bindings/mmc/mmc.txt      |    9 +-
+ Documentation/devicetree/bindings/mmc/pxa-mmc.txt  |   25 +
+ .../devicetree/bindings/mmc/samsung-sdhci.txt      |   53 +
+ .../devicetree/bindings/mmc/sdhci-dove.txt         |   14 +
+ .../devicetree/bindings/mmc/synposis-dw-mshc.txt   |   79 ++
+ MAINTAINERS                                        |    6 +-
+ drivers/mmc/core/core.c                            |  178 ++-
+ drivers/mmc/core/debugfs.c                         |    2 +-
+ drivers/mmc/core/mmc.c                             |   11 +
+ drivers/mmc/core/mmc_ops.c                         |   84 +-
+ drivers/mmc/core/sdio_bus.c                        |    7 -
+ drivers/mmc/core/slot-gpio.c                       |    8 +-
+ drivers/mmc/host/Kconfig                           |   16 +
+ drivers/mmc/host/Makefile                          |    2 +
+ drivers/mmc/host/atmel-mci-regs.h                  |    7 +
+ drivers/mmc/host/atmel-mci.c                       |  113 +-
+ drivers/mmc/host/bfin_sdh.c                        |  210 +--
+ drivers/mmc/host/dw_mmc-exynos.c                   |  253 ++++
+ drivers/mmc/host/dw_mmc-pci.c                      |   15 +-
+ drivers/mmc/host/dw_mmc-pltfm.c                    |   62 +-
+ drivers/mmc/host/dw_mmc-pltfm.h                    |   20 +
+ drivers/mmc/host/dw_mmc.c                          |  321 ++++-
+ drivers/mmc/host/dw_mmc.h                          |   24 +
+ drivers/mmc/host/mmc_spi.c                         |   15 +-
+ drivers/mmc/host/mmci.c                            |   13 +-
+ drivers/mmc/host/mxcmmc.c                          |   76 +-
+ drivers/mmc/host/omap.c                            |   39 +-
+ drivers/mmc/host/omap_hsmmc.c                      |  125 +-
+ drivers/mmc/host/pxamci.c                          |   52 +
+ drivers/mmc/host/rtsx_pci_sdmmc.c                  | 1332 ++++++++++++++++++++
+ drivers/mmc/host/sdhci-dove.c                      |    8 +
+ drivers/mmc/host/sdhci-of-esdhc.c                  |   36 +-
+ drivers/mmc/host/sdhci-pci.c                       |   19 +-
+ drivers/mmc/host/sdhci-pltfm.c                     |    3 +
+ drivers/mmc/host/sdhci-pxav2.c                     |    6 +-
+ drivers/mmc/host/sdhci-pxav3.c                     |   35 +-
+ drivers/mmc/host/sdhci-s3c.c                       |  216 +++-
+ drivers/mmc/host/sdhci-tegra.c                     |    7 +-
+ drivers/mmc/host/sdhci.c                           |  196 ++-
+ drivers/mmc/host/sh_mmcif.c                        |    8 +-
+ drivers/mmc/host/via-sdmmc.c                       |   16 +-
+ drivers/mmc/host/vub300.c                          |    4 +-
+ include/linux/mmc/card.h                           |    8 +
+ include/linux/mmc/core.h                           |    4 +
+ include/linux/mmc/dw_mmc.h                         |   15 +-
+ include/linux/mmc/host.h                           |    1 +
+ include/linux/mmc/mmc.h                            |   19 +
+ include/linux/mmc/sdhci.h                          |    3 +-
+ include/linux/platform_data/pxa_sdhci.h            |    1 +
+ 51 files changed, 3420 insertions(+), 511 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/mmc/atmel-hsmci.txt
+ create mode 100644 Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt
+ create mode 100644 Documentation/devicetree/bindings/mmc/pxa-mmc.txt
+ create mode 100644 Documentation/devicetree/bindings/mmc/samsung-sdhci.txt
+ create mode 100644 Documentation/devicetree/bindings/mmc/sdhci-dove.txt
+ create mode 100644 Documentation/devicetree/bindings/mmc/synposis-dw-mshc.txt
+ create mode 100644 drivers/mmc/host/dw_mmc-exynos.c
+ create mode 100644 drivers/mmc/host/dw_mmc-pltfm.h
+ create mode 100644 drivers/mmc/host/rtsx_pci_sdmmc.c
+Merging kgdb/kgdb-next (15d7ea0 kgdboc: Accept either kbd or kdb to activate the vga + keyboard kdb shell)
+$ git merge kgdb/kgdb-next
+Merge made by the 'recursive' strategy.
+ arch/mips/kernel/kgdb.c     |    9 +++++++++
+ arch/x86/kernel/kgdb.c      |    2 ++
+ drivers/tty/serial/kgdboc.c |    3 ++-
+ 3 files changed, 13 insertions(+), 1 deletion(-)
+Merging slab/for-next (f90765d Merge branch 'slab/tracing' into for-next)
+$ git merge slab/for-next
+Auto-merging mm/slub.c
+Auto-merging mm/slab.c
+Merge made by the 'recursive' strategy.
+ include/linux/slab.h     |    6 +-
+ include/linux/slab_def.h |   13 +-
+ include/linux/slob_def.h |    6 +-
+ mm/slab.c                |  335 +++++++++++++++++++---------------------------
+ mm/slab.h                |   19 ++-
+ mm/slab_common.c         |  159 ++++++++++++++++------
+ mm/slob.c                |   91 +++++++------
+ mm/slub.c                |  204 +++++++++++++---------------
+ mm/util.c                |   35 +++--
+ 9 files changed, 447 insertions(+), 421 deletions(-)
+Merging uclinux/for-next (5e442a4 Revert "proc: fix races against execve() of /proc/PID/fd**")
+$ git merge uclinux/for-next
+Already up-to-date.
+Merging md/for-next (0179d36 md/raid5: make sure to_read and to_write never go negative.)
+$ git merge md/for-next
+Resolved 'drivers/md/raid0.c' using previous resolution.
+Resolved 'fs/bio.c' using previous resolution.
+Auto-merging fs/bio.c
+CONFLICT (content): Merge conflict in fs/bio.c
+Auto-merging drivers/md/raid0.c
+CONFLICT (content): Merge conflict in drivers/md/raid0.c
+Auto-merging drivers/md/md.c
+Auto-merging block/blk-core.c
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master 8f70c68] Merge remote-tracking branch 'md/for-next'
+$ git diff -M --stat --summary HEAD^..
+ Documentation/device-mapper/dm-raid.txt |    9 +
+ block/blk-core.c                        |    1 +
+ crypto/xor.c                            |    4 +-
+ drivers/md/bitmap.c                     |   17 +-
+ drivers/md/dm-raid.c                    |  124 ++++--
+ drivers/md/linear.c                     |   25 +-
+ drivers/md/md.c                         |  134 +++++--
+ drivers/md/md.h                         |   15 +-
+ drivers/md/multipath.c                  |    3 +-
+ drivers/md/raid0.c                      |   19 +-
+ drivers/md/raid1.c                      |   32 +-
+ drivers/md/raid10.c                     |   89 ++++-
+ drivers/md/raid5.c                      |  660 ++++++++++++++++++++++++++++---
+ drivers/md/raid5.h                      |   20 +
+ fs/bio.c                                |   27 +-
+ 15 files changed, 1020 insertions(+), 159 deletions(-)
+Merging mfd/for-next (396f70b mfd: max8907: Remove regulator-compatible from DT docs)
+$ git merge mfd/for-next
+Resolved 'Documentation/devicetree/bindings/regulator/tps6586x.txt' using previous resolution.
+Resolved 'drivers/mfd/88pm860x-core.c' using previous resolution.
+Resolved 'drivers/mfd/max8925-core.c' using previous resolution.
+Resolved 'drivers/mfd/tc3589x.c' using previous resolution.
+Resolved 'drivers/mfd/tps65217.c' using previous resolution.
+Resolved 'drivers/regulator/anatop-regulator.c' using previous resolution.
+Auto-merging include/linux/mfd/tps65217.h
+Removing include/linux/mfd/anatop.h
+Auto-merging drivers/regulator/palmas-regulator.c
+Auto-merging drivers/regulator/anatop-regulator.c
+CONFLICT (content): Merge conflict in drivers/regulator/anatop-regulator.c
+Auto-merging drivers/regulator/ab3100.c
+Auto-merging drivers/pwm/pwm-twl6030.c
+Auto-merging drivers/pwm/Kconfig
+Auto-merging drivers/mfd/wm8994-core.c
+Auto-merging drivers/mfd/wm831x-core.c
+Auto-merging drivers/mfd/twl6040-core.c
+Auto-merging drivers/mfd/twl-core.c
+Auto-merging drivers/mfd/tps65910.c
+Auto-merging drivers/mfd/tps6586x.c
+Auto-merging drivers/mfd/tps65217.c
+CONFLICT (content): Merge conflict in drivers/mfd/tps65217.c
+Auto-merging drivers/mfd/tps65090.c
+Auto-merging drivers/mfd/tc3589x.c
+CONFLICT (content): Merge conflict in drivers/mfd/tc3589x.c
+Auto-merging drivers/mfd/rc5t583.c
+Auto-merging drivers/mfd/palmas.c
+Auto-merging drivers/mfd/mc13xxx-core.c
+Auto-merging drivers/mfd/max8925-core.c
+CONFLICT (content): Merge conflict in drivers/mfd/max8925-core.c
+Auto-merging drivers/mfd/lpc_ich.c
+Auto-merging drivers/mfd/db8500-prcmu.c
+Removing drivers/mfd/anatop-mfd.c
+Auto-merging drivers/mfd/ab8500-core.c
+Auto-merging drivers/mfd/ab3100-core.c
+Auto-merging drivers/mfd/Kconfig
+Auto-merging drivers/mfd/88pm860x-core.c
+CONFLICT (content): Merge conflict in drivers/mfd/88pm860x-core.c
+Auto-merging drivers/gpio/Kconfig
+Auto-merging arch/arm/mach-imx/mach-imx6q.c
+Auto-merging Documentation/devicetree/bindings/regulator/tps6586x.txt
+CONFLICT (content): Merge conflict in Documentation/devicetree/bindings/regulator/tps6586x.txt
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master 3fe5cf5] Merge remote-tracking branch 'mfd/for-next'
+$ git diff -M --stat --summary HEAD^..
+ Documentation/devicetree/bindings/mfd/syscon.txt   |   20 +
+ Documentation/devicetree/bindings/mfd/tps65910.txt |    4 +
+ Documentation/devicetree/bindings/mfd/twl6040.txt  |    9 +-
+ .../devicetree/bindings/regulator/max8907.txt      |   69 +++
+ .../devicetree/bindings/regulator/tps6586x.txt     |    6 +
+ arch/arm/boot/dts/imx6q.dtsi                       |    9 +-
+ arch/arm/mach-imx/Kconfig                          |    2 +-
+ arch/arm/mach-imx/mach-imx6q.c                     |   47 +-
+ arch/arm/mach-omap2/usb-host.c                     |   31 +-
+ arch/arm/mach-u300/i2c.c                           |    2 +-
+ arch/arm/plat-omap/include/plat/usb.h              |    7 +
+ drivers/gpio/Kconfig                               |    7 +
+ drivers/gpio/Makefile                              |    1 +
+ drivers/gpio/gpio-ich.c                            |   79 ++-
+ drivers/gpio/gpio-twl6040.c                        |  137 ++++
+ drivers/leds/leds-88pm860x.c                       |  176 +++---
+ drivers/mfd/88pm860x-core.c                        |  651 +++++++++++++++-----
+ drivers/mfd/88pm860x-i2c.c                         |  174 +-----
+ drivers/mfd/Kconfig                                |   46 +-
+ drivers/mfd/Makefile                               |    8 +-
+ drivers/mfd/ab3100-core.c                          |    1 +
+ drivers/mfd/ab8500-core.c                          |   37 +-
+ drivers/mfd/anatop-mfd.c                           |  124 ----
+ drivers/mfd/arizona-irq.c                          |   55 +-
+ drivers/mfd/db8500-prcmu.c                         |   88 ++-
+ drivers/mfd/dbx500-prcmu-regs.h                    |    4 +-
+ drivers/mfd/lp8788-irq.c                           |  198 ++++++
+ drivers/mfd/lp8788.c                               |  245 ++++++++
+ drivers/mfd/lpc_ich.c                              |   43 +-
+ drivers/mfd/max8907.c                              |  351 +++++++++++
+ drivers/mfd/max8925-core.c                         |  427 ++++++++++---
+ drivers/mfd/mc13xxx-core.c                         |    1 -
+ drivers/mfd/omap-usb-host.c                        |  238 +------
+ drivers/mfd/omap-usb-tll.c                         |  471 ++++++++++++++
+ drivers/mfd/palmas.c                               |  149 ++---
+ drivers/mfd/rc5t583-irq.c                          |    2 +-
+ drivers/mfd/rc5t583.c                              |    2 +-
+ drivers/mfd/syscon.c                               |  176 ++++++
+ drivers/mfd/tc3589x.c                              |  112 +++-
+ drivers/mfd/tps65090.c                             |    2 +-
+ drivers/mfd/tps65217.c                             |    3 +
+ drivers/mfd/tps6586x.c                             |   19 +
+ drivers/mfd/tps65910.c                             |   22 +
+ drivers/mfd/twl-core.c                             |  124 +---
+ drivers/mfd/twl6040-core.c                         |   17 +-
+ drivers/mfd/wm831x-core.c                          |   66 +-
+ drivers/mfd/wm8994-core.c                          |    2 +-
+ drivers/mfd/wm8994-regmap.c                        |    2 +-
+ drivers/pwm/Kconfig                                |    9 +
+ drivers/pwm/Makefile                               |    1 +
+ drivers/{mfd/twl6030-pwm.c => pwm/pwm-twl6030.c}   |  119 ++--
+ drivers/regulator/88pm8607.c                       |  101 ++-
+ drivers/regulator/Kconfig                          |    2 +-
+ drivers/regulator/ab3100.c                         |    1 +
+ drivers/regulator/anatop-regulator.c               |   31 +-
+ drivers/regulator/max8925-regulator.c              |   35 +-
+ drivers/regulator/palmas-regulator.c               |  127 +++-
+ drivers/regulator/wm831x-dcdc.c                    |   12 +-
+ drivers/regulator/wm831x-isink.c                   |    4 +-
+ drivers/regulator/wm831x-ldo.c                     |   12 +-
+ drivers/video/backlight/88pm860x_bl.c              |  114 ++--
+ drivers/video/backlight/Kconfig                    |    7 +
+ drivers/video/backlight/Makefile                   |    1 +
+ drivers/video/backlight/max8925_bl.c               |   79 +--
+ drivers/video/backlight/tps65217_bl.c              |  352 +++++++++++
+ drivers/watchdog/iTCO_wdt.c                        |    1 +
+ include/linux/ioport.h                             |    3 +-
+ include/linux/mfd/88pm860x.h                       |   42 +-
+ include/linux/mfd/ab3100.h                         |  129 ++++
+ include/linux/mfd/abx500.h                         |  117 +---
+ include/linux/mfd/abx500/ab8500.h                  |    2 -
+ include/linux/mfd/anatop.h                         |   40 --
+ include/linux/mfd/dbx500-prcmu.h                   |    1 +
+ include/linux/mfd/lp8788-isink.h                   |   52 ++
+ include/linux/mfd/lp8788.h                         |  364 +++++++++++
+ include/linux/mfd/lpc_ich.h                        |    1 +
+ include/linux/mfd/max8907.h                        |  252 ++++++++
+ include/linux/mfd/max8925.h                        |   26 +-
+ include/linux/mfd/palmas.h                         |  232 ++++++-
+ include/linux/mfd/syscon.h                         |   23 +
+ include/linux/mfd/syscon/imx6q-iomuxc-gpr.h        |  319 ++++++++++
+ include/linux/mfd/tc3589x.h                        |    1 +
+ include/linux/mfd/tps65217.h                       |   18 +
+ include/linux/mfd/tps6586x.h                       |    1 +
+ include/linux/mfd/tps65910.h                       |    3 +
+ include/linux/mfd/twl6040.h                        |   11 +-
+ 86 files changed, 5434 insertions(+), 1677 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/mfd/syscon.txt
+ create mode 100644 Documentation/devicetree/bindings/regulator/max8907.txt
+ create mode 100644 drivers/gpio/gpio-twl6040.c
+ delete mode 100644 drivers/mfd/anatop-mfd.c
+ create mode 100644 drivers/mfd/lp8788-irq.c
+ create mode 100644 drivers/mfd/lp8788.c
+ create mode 100644 drivers/mfd/max8907.c
+ create mode 100644 drivers/mfd/omap-usb-tll.c
+ create mode 100644 drivers/mfd/syscon.c
+ rename drivers/{mfd/twl6030-pwm.c => pwm/pwm-twl6030.c} (55%)
+ create mode 100644 drivers/video/backlight/tps65217_bl.c
+ create mode 100644 include/linux/mfd/ab3100.h
+ delete mode 100644 include/linux/mfd/anatop.h
+ create mode 100644 include/linux/mfd/lp8788-isink.h
+ create mode 100644 include/linux/mfd/lp8788.h
+ create mode 100644 include/linux/mfd/max8907.h
+ create mode 100644 include/linux/mfd/syscon.h
+ create mode 100644 include/linux/mfd/syscon/imx6q-iomuxc-gpr.h
+Merging battery/master (18766f0 Merge with upstream to accommodate with MFD changes)
+$ git merge battery/master
+Resolved 'include/linux/mfd/88pm860x.h' using previous resolution.
+Auto-merging include/linux/mfd/88pm860x.h
+CONFLICT (content): Merge conflict in include/linux/mfd/88pm860x.h
+Auto-merging drivers/mfd/88pm860x-core.c
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master 736894e] Merge remote-tracking branch 'battery/master'
+$ git diff -M --stat --summary HEAD^..
+ Documentation/power/power_supply_class.txt |    7 +
+ drivers/mfd/88pm860x-core.c                |   22 +-
+ drivers/power/88pm860x_battery.c           | 1041 ++++++++++++++++++++++++++++
+ drivers/power/88pm860x_charger.c           |  746 ++++++++++++++++++++
+ drivers/power/Kconfig                      |   20 +-
+ drivers/power/Makefile                     |    3 +
+ drivers/power/ab8500_btemp.c               |    1 +
+ drivers/power/ab8500_charger.c             |    1 +
+ drivers/power/ab8500_fg.c                  |    1 +
+ drivers/power/bq27x00_battery.c            |    3 +-
+ drivers/power/charger-manager.c            |  434 ++++++++++--
+ drivers/power/da9030_battery.c             |    4 +-
+ drivers/power/da9052-battery.c             |   11 +-
+ drivers/power/ds2781_battery.c             |   28 +-
+ drivers/power/lp8727_charger.c             |  360 ++++++----
+ drivers/power/lp8788-charger.c             |  795 +++++++++++++++++++++
+ drivers/power/pda_power.c                  |   13 +-
+ drivers/power/power_supply_sysfs.c         |    3 +
+ drivers/power/sbs-battery.c                |   10 +
+ drivers/power/smb347-charger.c             |   97 ++-
+ drivers/power/twl4030_charger.c            |   25 +-
+ drivers/power/wm97xx_battery.c             |    4 +-
+ include/linux/mfd/88pm860x.h               |   84 ++-
+ include/linux/platform_data/lp8727.h       |   51 +-
+ include/linux/power/charger-manager.h      |   47 +-
+ include/linux/power_supply.h               |    5 +
+ 26 files changed, 3519 insertions(+), 297 deletions(-)
+ create mode 100644 drivers/power/88pm860x_battery.c
+ create mode 100644 drivers/power/88pm860x_charger.c
+ create mode 100644 drivers/power/lp8788-charger.c
+Merging fbdev/fbdev-next (ebe9f7b video: exynos_mipi_dsi: Remove unnecessary NULL check)
+$ git merge fbdev/fbdev-next
+Auto-merging include/video/samsung_fimd.h
+Auto-merging drivers/video/ps3fb.c
+Removing drivers/video/pnx4008/sdum.h
+Removing drivers/video/pnx4008/sdum.c
+Removing drivers/video/pnx4008/pnxrgbfb.c
+Removing drivers/video/pnx4008/fbcommon.h
+Removing drivers/video/pnx4008/dum.h
+Removing drivers/video/pnx4008/Makefile
+Auto-merging drivers/video/msm/mdp.c
+Auto-merging drivers/gpu/drm/exynos/exynos_drm_fimd.c
+Removing arch/arm/plat-samsung/include/plat/regs-fb-v4.h
+Auto-merging arch/arm/mach-exynos/mach-smdkv310.c
+Auto-merging arch/arm/mach-exynos/mach-origen.c
+Merge made by the 'recursive' strategy.
+ arch/arm/mach-exynos/mach-nuri.c                   |    2 +-
+ arch/arm/mach-exynos/mach-origen.c                 |    2 +-
+ arch/arm/mach-exynos/mach-smdk4x12.c               |    2 +-
+ arch/arm/mach-exynos/mach-smdkv310.c               |    2 +-
+ arch/arm/mach-exynos/mach-universal_c210.c         |    2 +-
+ arch/arm/mach-exynos/setup-fimd0.c                 |    2 +-
+ arch/arm/mach-s3c24xx/mach-smdk2416.c              |    2 +-
+ arch/arm/mach-s3c64xx/mach-anw6410.c               |    2 +-
+ arch/arm/mach-s3c64xx/mach-crag6410.c              |    2 +-
+ arch/arm/mach-s3c64xx/mach-hmt.c                   |    2 +-
+ arch/arm/mach-s3c64xx/mach-mini6410.c              |    2 +-
+ arch/arm/mach-s3c64xx/mach-ncp.c                   |    2 +-
+ arch/arm/mach-s3c64xx/mach-real6410.c              |    2 +-
+ arch/arm/mach-s3c64xx/mach-smartq5.c               |    2 +-
+ arch/arm/mach-s3c64xx/mach-smartq7.c               |    2 +-
+ arch/arm/mach-s3c64xx/mach-smdk6410.c              |    2 +-
+ arch/arm/mach-s5p64x0/mach-smdk6440.c              |    2 +-
+ arch/arm/mach-s5p64x0/mach-smdk6450.c              |    2 +-
+ arch/arm/mach-s5pc100/mach-smdkc100.c              |    2 +-
+ arch/arm/mach-s5pv210/mach-aquila.c                |    2 +-
+ arch/arm/mach-s5pv210/mach-goni.c                  |    2 +-
+ arch/arm/mach-s5pv210/mach-smdkv210.c              |    2 +-
+ arch/arm/plat-samsung/include/plat/regs-fb-v4.h    |  159 ----
+ drivers/gpu/drm/exynos/exynos_drm_fimd.c           |    2 +-
+ drivers/video/Kconfig                              |   15 -
+ drivers/video/Makefile                             |    2 -
+ drivers/video/amifb.c                              |    2 -
+ drivers/video/arcfb.c                              |    1 +
+ drivers/video/atmel_lcdfb.c                        |    5 +-
+ drivers/video/bf537-lq035.c                        |   12 +-
+ drivers/video/bf54x-lq043fb.c                      |    9 +-
+ drivers/video/bfin-lq035q1-fb.c                    |   13 +-
+ drivers/video/bfin-t350mcqb-fb.c                   |    1 +
+ drivers/video/bw2.c                                |    4 +-
+ drivers/video/cg3.c                                |    3 +-
+ drivers/video/cobalt_lcdfb.c                       |    5 +-
+ drivers/video/console/font_mini_4x6.c              |    2 +-
+ drivers/video/console/font_sun8x16.c               |    2 +-
+ drivers/video/cyber2000fb.c                        |    4 +-
+ drivers/video/da8xx-fb.c                           |  191 +++--
+ drivers/video/ep93xx-fb.c                          |   17 +-
+ drivers/video/epson1355fb.c                        |   16 +-
+ drivers/video/exynos/exynos_dp_core.c              |  314 ++++---
+ drivers/video/exynos/exynos_dp_core.h              |    6 +-
+ drivers/video/exynos/exynos_dp_reg.c               |   58 +-
+ drivers/video/exynos/exynos_dp_reg.h               |    3 +-
+ drivers/video/exynos/exynos_mipi_dsi.c             |    6 +-
+ drivers/video/exynos/exynos_mipi_dsi_common.c      |    8 -
+ drivers/video/fsl-diu-fb.c                         |   10 +-
+ drivers/video/gbefb.c                              |   15 +-
+ drivers/video/hpfb.c                               |   28 +-
+ drivers/video/imxfb.c                              |    1 +
+ drivers/video/jz4740_fb.c                          |   44 +-
+ drivers/video/mb862xx/mb862xxfbdrv.c               |   10 +-
+ drivers/video/mbx/mbxfb.c                          |   25 +-
+ drivers/video/msm/mddi.c                           |    3 -
+ drivers/video/msm/mddi_client_nt35399.c            |    6 +-
+ drivers/video/msm/mdp.c                            |    1 -
+ drivers/video/msm/mdp_hw.h                         |    1 -
+ drivers/video/pnx4008/Makefile                     |    7 -
+ drivers/video/pnx4008/dum.h                        |  211 -----
+ drivers/video/pnx4008/fbcommon.h                   |   43 -
+ drivers/video/pnx4008/pnxrgbfb.c                   |  198 -----
+ drivers/video/pnx4008/sdum.c                       |  861 --------------------
+ drivers/video/pnx4008/sdum.h                       |  136 ----
+ drivers/video/ps3fb.c                              |    7 +-
+ drivers/video/s3c-fb.c                             |   26 +-
+ drivers/video/s3c2410fb.c                          |   34 +-
+ drivers/video/sis/initextlfb.c                     |    2 +-
+ drivers/video/sunxvr1000.c                         |    4 +-
+ drivers/video/sunxvr2500.c                         |    4 +-
+ drivers/video/sunxvr500.c                          |    8 +-
+ drivers/video/uvesafb.c                            |    2 +
+ drivers/video/vermilion/vermilion.c                |    3 +-
+ drivers/video/via/via_clock.c                      |   19 +
+ .../plat/regs-fb.h => include/video/samsung_fimd.h |  152 +++-
+ 76 files changed, 673 insertions(+), 2092 deletions(-)
+ delete mode 100644 arch/arm/plat-samsung/include/plat/regs-fb-v4.h
+ delete mode 100644 drivers/video/pnx4008/Makefile
+ delete mode 100644 drivers/video/pnx4008/dum.h
+ delete mode 100644 drivers/video/pnx4008/fbcommon.h
+ delete mode 100644 drivers/video/pnx4008/pnxrgbfb.c
+ delete mode 100644 drivers/video/pnx4008/sdum.c
+ delete mode 100644 drivers/video/pnx4008/sdum.h
+ rename arch/arm/plat-samsung/include/plat/regs-fb.h => include/video/samsung_fimd.h (73%)
+Merging viafb/viafb-next (838ac78 viafb: avoid refresh and mode lookup in set_par)
+$ git merge viafb/viafb-next
+Already up-to-date.
+Merging omap_dss2/for-next (6659145 Merge branch 'fbdev-for-linus' of git://github.com/schandinat/linux-2.6)
+$ git merge omap_dss2/for-next
+Auto-merging arch/arm/mach-omap2/twl-common.c
+Merge made by the 'recursive' strategy.
+ arch/arm/mach-omap2/board-4430sdp.c                |   73 +--
+ arch/arm/mach-omap2/board-omap4panda.c             |   27 +-
+ arch/arm/mach-omap2/display.c                      |    1 -
+ arch/arm/mach-omap2/twl-common.c                   |    6 +
+ drivers/video/omap/hwa742.c                        |    1 -
+ drivers/video/omap/lcd_ams_delta.c                 |    1 -
+ drivers/video/omap/lcd_palmte.c                    |    1 -
+ drivers/video/omap/omapfb_main.c                   |    9 -
+ drivers/video/omap2/displays/panel-acx565akm.c     |   14 +-
+ drivers/video/omap2/displays/panel-generic-dpi.c   |   76 ++-
+ .../omap2/displays/panel-lgphilips-lb035q02.c      |    3 +
+ drivers/video/omap2/displays/panel-n8x0.c          |   31 +-
+ .../omap2/displays/panel-nec-nl8048hl11-01b.c      |    3 +
+ drivers/video/omap2/displays/panel-picodlp.c       |    4 +
+ .../video/omap2/displays/panel-sharp-ls037v7dw01.c |    3 +
+ drivers/video/omap2/displays/panel-taal.c          |  239 ++++-----
+ drivers/video/omap2/displays/panel-tfp410.c        |   20 +-
+ .../video/omap2/displays/panel-tpo-td043mtea1.c    |    7 +-
+ drivers/video/omap2/dss/Makefile                   |    4 +-
+ drivers/video/omap2/dss/apply.c                    |  240 ++--------
+ drivers/video/omap2/dss/dispc.c                    |  506 +++++++++++++-------
+ drivers/video/omap2/dss/dispc.h                    |    4 +
+ drivers/video/omap2/dss/display.c                  |    4 +
+ drivers/video/omap2/dss/dpi.c                      |   72 ++-
+ drivers/video/omap2/dss/dsi.c                      |  342 ++++++++++---
+ drivers/video/omap2/dss/dss.c                      |  184 +++----
+ drivers/video/omap2/dss/dss.h                      |   30 +-
+ drivers/video/omap2/dss/dss_features.c             |    3 +
+ drivers/video/omap2/dss/dss_features.h             |    2 +
+ drivers/video/omap2/dss/hdmi.c                     |  147 ++++--
+ drivers/video/omap2/dss/hdmi_panel.c               |   31 +-
+ drivers/video/omap2/dss/manager-sysfs.c            |  499 +++++++++++++++++++
+ drivers/video/omap2/dss/manager.c                  |  462 +-----------------
+ drivers/video/omap2/dss/overlay-sysfs.c            |  456 ++++++++++++++++++
+ drivers/video/omap2/dss/overlay.c                  |  421 +---------------
+ drivers/video/omap2/dss/rfbi.c                     |  127 +++--
+ drivers/video/omap2/dss/sdi.c                      |   23 +-
+ drivers/video/omap2/dss/venc.c                     |  245 +++-------
+ drivers/video/omap2/dss/venc_panel.c               |  251 ++++++++++
+ drivers/video/omap2/omapfb/omapfb-main.c           |   26 +
+ drivers/video/omap2/vram.c                         |   56 ---
+ include/video/omapdss.h                            |   49 +-
+ 42 files changed, 2625 insertions(+), 2078 deletions(-)
+ create mode 100644 drivers/video/omap2/dss/manager-sysfs.c
+ create mode 100644 drivers/video/omap2/dss/overlay-sysfs.c
+ create mode 100644 drivers/video/omap2/dss/venc_panel.c
+Merging regulator/for-next (ca3184a Merge remote-tracking branches 'regulator/topic/core', 'regulator/topic/bypass', 'regulator/topic/tol', 'regulator/topic/drivers' and 'regulator/topic/tps6586x' into regulator-next)
+$ git merge regulator/for-next
+Resolved 'Documentation/devicetree/bindings/regulator/tps6586x.txt' using previous resolution.
+Auto-merging include/linux/mfd/tps6586x.h
+Auto-merging drivers/regulator/wm831x-ldo.c
+Auto-merging drivers/regulator/wm831x-dcdc.c
+Auto-merging drivers/regulator/palmas-regulator.c
+Auto-merging drivers/regulator/ab3100.c
+Auto-merging drivers/regulator/Kconfig
+Auto-merging drivers/mfd/tps6586x.c
+Auto-merging Documentation/devicetree/bindings/regulator/tps6586x.txt
+CONFLICT (content): Merge conflict in Documentation/devicetree/bindings/regulator/tps6586x.txt
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master d2c5870] Merge remote-tracking branch 'regulator/for-next'
+$ git diff -M --stat --summary HEAD^..
+ Documentation/ABI/testing/sysfs-class-regulator    |   21 +
+ .../devicetree/bindings/regulator/regulator.txt    |    5 +-
+ .../devicetree/bindings/regulator/tps65217.txt     |   31 +-
+ .../devicetree/bindings/regulator/tps6586x.txt     |   73 ++--
+ arch/arm/mach-tegra/board-harmony-power.c          |   12 +-
+ drivers/extcon/extcon-arizona.c                    |    5 +
+ drivers/mfd/tps6586x.c                             |   13 +
+ drivers/regulator/Kconfig                          |   38 +-
+ drivers/regulator/Makefile                         |    2 +
+ drivers/regulator/aat2870-regulator.c              |    2 +-
+ drivers/regulator/ab3100.c                         |    6 -
+ drivers/regulator/ab8500.c                         |   36 +-
+ drivers/regulator/arizona-ldo1.c                   |    4 +
+ drivers/regulator/arizona-micsupp.c                |    5 +
+ drivers/regulator/core.c                           |  153 +++++++-
+ drivers/regulator/da9052-regulator.c               |    4 +-
+ drivers/regulator/dummy.c                          |    2 +-
+ drivers/regulator/fan53555.c                       |  322 +++++++++++++++
+ drivers/regulator/isl6271a-regulator.c             |    6 -
+ drivers/regulator/lp872x.c                         |   88 ++---
+ drivers/regulator/lp8788-buck.c                    |   80 +---
+ drivers/regulator/lp8788-ldo.c                     |    8 +
+ drivers/regulator/max77686.c                       |   30 +-
+ drivers/regulator/max8907-regulator.c              |  408 ++++++++++++++++++++
+ drivers/regulator/mc13783-regulator.c              |   89 ++++-
+ drivers/regulator/mc13892-regulator.c              |   77 ++--
+ drivers/regulator/mc13xxx-regulator-core.c         |   17 +-
+ drivers/regulator/mc13xxx.h                        |    1 -
+ drivers/regulator/of_regulator.c                   |   25 +-
+ drivers/regulator/palmas-regulator.c               |   45 +--
+ drivers/regulator/s2mps11.c                        |   27 +-
+ drivers/regulator/tps6524x-regulator.c             |   10 +-
+ drivers/regulator/tps6586x-regulator.c             |   96 ++---
+ drivers/regulator/twl-regulator.c                  |  110 +++---
+ drivers/regulator/wm831x-dcdc.c                    |   11 +-
+ drivers/regulator/wm831x-ldo.c                     |   12 +
+ drivers/regulator/wm8400-regulator.c               |    7 +-
+ include/linux/mfd/max77686.h                       |    1 +
+ include/linux/mfd/tps6586x.h                       |    1 +
+ include/linux/regulator/consumer.h                 |   15 +
+ include/linux/regulator/driver.h                   |   18 +-
+ include/linux/regulator/fan53555.h                 |   60 +++
+ include/linux/regulator/machine.h                  |    2 +
+ 43 files changed, 1416 insertions(+), 562 deletions(-)
+ create mode 100644 drivers/regulator/fan53555.c
+ create mode 100644 drivers/regulator/max8907-regulator.c
+ create mode 100644 include/linux/regulator/fan53555.h
+Merging security/next (0a72ba7 ima: change flags container data type)
+$ git merge security/next
+Auto-merging security/yama/yama_lsm.c
+Auto-merging include/linux/xattr.h
+Auto-merging include/linux/security.h
+Auto-merging include/linux/audit.h
+Auto-merging fs/xattr.c
+Auto-merging fs/file_table.c
+Auto-merging drivers/char/tpm/tpm_eventlog.c
+Auto-merging arch/powerpc/kernel/prom_init.c
+Auto-merging Documentation/kernel-parameters.txt
+Merge made by the 'recursive' strategy.
+ Documentation/ABI/testing/ima_policy            |   25 +-
+ Documentation/ABI/testing/sysfs-driver-ppi      |   70 +++
+ Documentation/kernel-parameters.txt             |    8 +
+ Documentation/security/Smack.txt                |    3 +
+ arch/powerpc/kernel/prom_init.c                 |   62 ++
+ drivers/char/hw_random/Kconfig                  |   13 +
+ drivers/char/hw_random/Makefile                 |    1 +
+ drivers/char/hw_random/tpm-rng.c                |   50 ++
+ drivers/char/tpm/Kconfig                        |   19 +
+ drivers/char/tpm/Makefile                       |    8 +
+ drivers/char/tpm/tpm.c                          |   74 ++-
+ drivers/char/tpm/tpm.h                          |   35 +-
+ drivers/char/tpm/tpm_acpi.c                     |  109 ++++
+ drivers/char/tpm/{tpm_bios.c => tpm_eventlog.c} |  147 +----
+ drivers/char/tpm/tpm_eventlog.h                 |   86 +++
+ drivers/char/tpm/tpm_i2c_infineon.c             |  695 +++++++++++++++++++++
+ drivers/char/tpm/tpm_ibmvtpm.c                  |  749 +++++++++++++++++++++++
+ drivers/char/tpm/tpm_ibmvtpm.h                  |   77 +++
+ drivers/char/tpm/tpm_of.c                       |   73 +++
+ drivers/char/tpm/tpm_ppi.c                      |  461 ++++++++++++++
+ drivers/char/tpm/tpm_tis.c                      |    3 +-
+ fs/attr.c                                       |    2 +
+ fs/file_table.c                                 |    2 +-
+ fs/xattr.c                                      |    6 +-
+ include/linux/audit.h                           |    2 +
+ include/linux/ima.h                             |   27 +
+ include/linux/integrity.h                       |    7 +-
+ include/linux/ptrace.h                          |    2 -
+ include/linux/security.h                        |   31 +
+ include/linux/tpm.h                             |    4 +
+ include/linux/xattr.h                           |    3 +
+ kernel/auditsc.c                                |   74 +--
+ kernel/ptrace.c                                 |    3 +-
+ samples/seccomp/Makefile                        |   24 +-
+ samples/seccomp/bpf-helper.h                    |   15 +-
+ security/integrity/evm/evm_main.c               |    3 +
+ security/integrity/iint.c                       |   64 +-
+ security/integrity/ima/Kconfig                  |   16 +
+ security/integrity/ima/Makefile                 |    1 +
+ security/integrity/ima/ima.h                    |   39 +-
+ security/integrity/ima/ima_api.c                |   86 ++-
+ security/integrity/ima/ima_appraise.c           |  263 ++++++++
+ security/integrity/ima/ima_crypto.c             |    8 +-
+ security/integrity/ima/ima_main.c               |   93 ++-
+ security/integrity/ima/ima_policy.c             |  195 ++++--
+ security/integrity/integrity.h                  |   22 +-
+ security/keys/trusted.c                         |   54 +-
+ security/security.c                             |   27 +
+ security/smack/smack_lsm.c                      |   51 +-
+ security/smack/smackfs.c                        |   75 +++
+ security/yama/Kconfig                           |    8 +
+ security/yama/yama_lsm.c                        |   16 +-
+ 52 files changed, 3537 insertions(+), 454 deletions(-)
+ create mode 100644 Documentation/ABI/testing/sysfs-driver-ppi
+ create mode 100644 drivers/char/hw_random/tpm-rng.c
+ create mode 100644 drivers/char/tpm/tpm_acpi.c
+ rename drivers/char/tpm/{tpm_bios.c => tpm_eventlog.c} (75%)
+ create mode 100644 drivers/char/tpm/tpm_eventlog.h
+ create mode 100644 drivers/char/tpm/tpm_i2c_infineon.c
+ create mode 100644 drivers/char/tpm/tpm_ibmvtpm.c
+ create mode 100644 drivers/char/tpm/tpm_ibmvtpm.h
+ create mode 100644 drivers/char/tpm/tpm_of.c
+ create mode 100644 drivers/char/tpm/tpm_ppi.c
+ create mode 100644 security/integrity/ima/ima_appraise.c
+Merging selinux/master (c2d7b24 Merge tag 'v3.4' into 20120409)
+$ git merge selinux/master
+Already up-to-date!
+Merge made by the 'recursive' strategy.
+Merging lblnet/master (7e27d6e Linux 2.6.35-rc3)
+$ git merge lblnet/master
+Already up-to-date.
+Merging watchdog/master (fea1666 Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux)
+$ git merge watchdog/master
+Already up-to-date!
+Merge made by the 'recursive' strategy.
+Merging dwmw2-iommu/master (c3b92c8 Linux 3.1)
+$ git merge dwmw2-iommu/master
+Already up-to-date.
+Merging iommu/next (08a49c3 Merge branches 'iommu/fixes', 'arm/tegra', 'arm/exynos', 'x86/amd' and 'x86/vt-d' into next)
+$ git merge iommu/next
+Auto-merging drivers/iommu/intel-iommu.c
+Removing arch/arm/mach-tegra/include/mach/smmu.h
+Merge made by the 'recursive' strategy.
+ arch/arm/mach-tegra/include/mach/smmu.h |   63 --------
+ drivers/iommu/amd_iommu.c               |   10 +-
+ drivers/iommu/amd_iommu_init.c          |   11 +-
+ drivers/iommu/amd_iommu_types.h         |    4 +-
+ drivers/iommu/exynos-iommu.c            |    3 +-
+ drivers/iommu/intel-iommu.c             |    4 +-
+ drivers/iommu/tegra-smmu.c              |  261 +++++++++++++++++++++++++++++--
+ include/linux/iommu.h                   |   42 ++---
+ 8 files changed, 288 insertions(+), 110 deletions(-)
+ delete mode 100644 arch/arm/mach-tegra/include/mach/smmu.h
+Merging vfio/next (b68e7fa vfio: Fix virqfd release race)
+$ git merge vfio/next
+Already up-to-date.
+Merging osd/linux-next (b8017d2 exofs: check for allocation failure in uri_store())
+$ git merge osd/linux-next
+Merge made by the 'recursive' strategy.
+ fs/exofs/sys.c |    7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+Merging jc_docs/docs-next (5c050fb docs: update the development process document)
+$ git merge jc_docs/docs-next
+Already up-to-date.
+Merging trivial/for-next (7dfd8cc fs/fs-writeback.c: cleanup riteback_sb_inodes kerneldoc)
+$ git merge trivial/for-next
+Resolved 'drivers/scsi/ipr.c' using previous resolution.
+Resolved 'drivers/video/backlight/88pm860x_bl.c' using previous resolution.
+Auto-merging tools/perf/util/python-ext-sources
+Auto-merging tools/perf/util/parse-events-test.c
+Auto-merging include/linux/irqdesc.h
+Auto-merging fs/nfs/super.c
+Auto-merging fs/fs-writeback.c
+Auto-merging fs/ext4/mballoc.c
+Auto-merging fs/ext4/inode.c
+Auto-merging fs/ext3/inode.c
+Auto-merging fs/ext3/balloc.c
+Auto-merging fs/ext2/balloc.c
+Auto-merging fs/btrfs/inode.c
+Auto-merging fs/btrfs/delayed-ref.h
+Auto-merging fs/btrfs/ctree.h
+Auto-merging drivers/w1/masters/ds1wm.c
+Auto-merging drivers/video/exynos/exynos_mipi_dsi.c
+Auto-merging drivers/video/backlight/88pm860x_bl.c
+CONFLICT (content): Merge conflict in drivers/video/backlight/88pm860x_bl.c
+Auto-merging drivers/scsi/qla4xxx/ql4_os.c
+Auto-merging drivers/scsi/megaraid.c
+Auto-merging drivers/scsi/lpfc/lpfc_sli.c
+Auto-merging drivers/scsi/lpfc/lpfc_init.c
+Auto-merging drivers/scsi/isci/init.c
+Auto-merging drivers/scsi/isci/host.c
+Auto-merging drivers/scsi/ipr.c
+CONFLICT (content): Merge conflict in drivers/scsi/ipr.c
+Auto-merging drivers/scsi/bnx2fc/bnx2fc_fcoe.c
+Auto-merging drivers/scsi/bfa/bfa_ioc.h
+Auto-merging drivers/scsi/bfa/bfa_ioc.c
+Removing drivers/pci/.gitignore
+Auto-merging drivers/net/wireless/rtlwifi/rtl8192de/fw.c
+Auto-merging drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c
+Auto-merging drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
+Auto-merging drivers/mmc/host/vub300.c
+Auto-merging drivers/mmc/host/omap_hsmmc.c
+Auto-merging drivers/mmc/host/atmel-mci.c
+Auto-merging drivers/mfd/rdc321x-southbridge.c
+Auto-merging drivers/mfd/rc5t583.c
+Auto-merging drivers/mfd/ab8500-gpadc.c
+Auto-merging drivers/dma/pl330.c
+Auto-merging drivers/dma/imx-dma.c
+Auto-merging drivers/dma/ep93xx_dma.c
+Auto-merging drivers/dma/at_hdmac.c
+Auto-merging Documentation/dontdiff
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master 95ac84c] Merge remote-tracking branch 'trivial/for-next'
+$ git diff -M --stat --summary HEAD^..
+ Documentation/accounting/getdelays.c               |    5 ++-
+ Documentation/dontdiff                             |    1 -
+ Documentation/ia64/aliasing-test.c                 |    1 +
+ Documentation/power/swsusp.txt                     |    2 +-
+ arch/powerpc/boot/.gitignore                       |    4 ---
+ arch/x86/include/asm/hpet.h                        |    2 --
+ drivers/dma/at_hdmac.c                             |    8 ++---
+ drivers/dma/ep93xx_dma.c                           |    2 +-
+ drivers/dma/fsldma.c                               |    2 +-
+ drivers/dma/imx-dma.c                              |    4 +--
+ drivers/dma/intel_mid_dma.c                        |    2 +-
+ drivers/dma/intel_mid_dma_regs.h                   |    6 ++--
+ drivers/dma/ioat/hw.h                              |    4 ---
+ drivers/dma/pl330.c                                |    2 +-
+ drivers/dma/ppc4xx/adma.c                          |    2 +-
+ drivers/dma/ste_dma40_ll.h                         |    2 +-
+ drivers/mfd/ab8500-gpadc.c                         |    2 +-
+ drivers/mfd/rc5t583.c                              |    2 +-
+ drivers/mfd/rdc321x-southbridge.c                  |    2 +-
+ drivers/mfd/tps65911-comparator.c                  |    2 +-
+ drivers/mmc/core/sdio.c                            |    2 +-
+ drivers/mmc/host/at91_mci.c                        |    2 +-
+ drivers/mmc/host/atmel-mci.c                       |    2 +-
+ drivers/mmc/host/omap_hsmmc.c                      |    2 +-
+ drivers/mmc/host/sdhci-esdhc-imx.c                 |    2 +-
+ drivers/mmc/host/vub300.c                          |    2 +-
+ drivers/net/ethernet/3com/typhoon.c                |    2 +-
+ drivers/net/ethernet/broadcom/bnx2x/bnx2x.h        |    2 +-
+ drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h     |    2 +-
+ drivers/net/wireless/b43/Kconfig                   |    4 +--
+ drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c  |    6 ++--
+ drivers/net/wireless/rtlwifi/rtl8192de/fw.c        |    6 ++--
+ drivers/pci/.gitignore                             |    4 ---
+ drivers/scsi/aic7xxx/aic79xx_core.c                |    2 +-
+ drivers/scsi/bfa/bfa_ioc.c                         |    2 +-
+ drivers/scsi/bfa/bfa_ioc.h                         |    2 +-
+ drivers/scsi/bnx2fc/bnx2fc_fcoe.c                  |    4 +--
+ drivers/scsi/gdth.h                                |    9 -----
+ drivers/scsi/isci/host.c                           |    2 +-
+ drivers/scsi/isci/init.c                           |    2 +-
+ drivers/scsi/isci/port.c                           |    2 +-
+ drivers/scsi/isci/request.c                        |    2 +-
+ drivers/scsi/isci/task.c                           |    2 +-
+ drivers/scsi/lpfc/lpfc_init.c                      |    2 +-
+ drivers/scsi/lpfc/lpfc_sli.c                       |    4 +--
+ drivers/scsi/megaraid.c                            |    5 ++-
+ drivers/scsi/megaraid.h                            |   35 --------------------
+ drivers/scsi/mvumi.c                               |    6 ++--
+ drivers/scsi/qla4xxx/ql4_os.c                      |    6 ++--
+ drivers/scsi/vmw_pvscsi.c                          |    4 +--
+ drivers/spi/spi-au1550.c                           |    2 +-
+ drivers/spi/spi-bfin-sport.c                       |    2 +-
+ drivers/spi/spi-oc-tiny.c                          |    2 +-
+ drivers/spi/spi-ppc4xx.c                           |    4 +--
+ drivers/spi/spi-topcliff-pch.c                     |    2 +-
+ drivers/target/iscsi/iscsi_target_parameters.c     |    4 +--
+ drivers/video/exynos/exynos_mipi_dsi.c             |    2 +-
+ drivers/video/tmiofb.c                             |    4 +++
+ drivers/w1/masters/ds1wm.c                         |    2 +-
+ fs/btrfs/ctree.h                                   |    2 +-
+ fs/btrfs/delayed-ref.h                             |    2 +-
+ fs/btrfs/inode.c                                   |    4 +--
+ fs/ext2/balloc.c                                   |    2 +-
+ fs/ext3/balloc.c                                   |    2 +-
+ fs/ext3/inode.c                                    |    2 +-
+ fs/ext4/inode.c                                    |   14 ++++----
+ fs/ext4/mballoc.c                                  |    2 +-
+ fs/fs-writeback.c                                  |    4 ---
+ fs/libfs.c                                         |    2 +-
+ fs/nfs/super.c                                     |    2 +-
+ include/linux/irqdesc.h                            |    2 --
+ include/linux/mfd/max8998.h                        |    2 +-
+ include/trace/define_trace.h                       |    2 +-
+ mm/bootmem.c                                       |    2 +-
+ net/8021q/vlanproc.c                               |    2 +-
+ scripts/coccinelle/api/memdup_user.cocci           |    4 +--
+ security/apparmor/.gitignore                       |    1 -
+ sound/oss/.gitignore                               |    1 -
+ tools/perf/util/callchain.h                        |    2 +-
+ tools/perf/util/parse-events-test.c                |    2 +-
+ tools/perf/util/python-ext-sources                 |    2 +-
+ tools/testing/ktest/examples/include/defaults.conf |    2 +-
+ tools/testing/ktest/examples/include/tests.conf    |    2 +-
+ tools/testing/selftests/vm/run_vmtests             |    6 ++--
+ 84 files changed, 108 insertions(+), 172 deletions(-)
+ delete mode 100644 drivers/pci/.gitignore
+Merging audit/for-next (dcd6c92 Linux 3.3-rc1)
+$ git merge audit/for-next
+Already up-to-date.
+Merging pm/linux-next (1ac9af7 Merge branch 'master' into linux-next)
+$ git merge pm/linux-next
+Auto-merging drivers/pci/pci-driver.c
+Removing arch/arm/mach-shmobile/common.c
+Auto-merging arch/arm/kernel/smp.c
+Merge made by the 'recursive' strategy.
+ Documentation/ABI/testing/sysfs-devices-system-cpu |   11 +
+ Documentation/cpu-freq/boost.txt                   |   93 +++++
+ Documentation/cpuidle/sysfs.txt                    |   10 +-
+ .../devicetree/bindings/cpufreq/cpufreq-cpu0.txt   |   55 +++
+ Documentation/devicetree/bindings/power/opp.txt    |   25 ++
+ arch/arm/kernel/smp.c                              |   54 +++
+ arch/arm/mach-shmobile/Makefile                    |    2 +-
+ arch/arm/mach-shmobile/board-ap4evb.c              |   21 +-
+ arch/arm/mach-shmobile/board-armadillo800eva.c     |    6 +-
+ arch/arm/mach-shmobile/board-mackerel.c            |   34 +-
+ arch/arm/mach-shmobile/common.c                    |   24 --
+ arch/arm/mach-shmobile/cpuidle.c                   |   39 +-
+ arch/arm/mach-shmobile/include/mach/common.h       |   14 +-
+ arch/arm/mach-shmobile/include/mach/pm-rmobile.h   |   35 +-
+ arch/arm/mach-shmobile/include/mach/r8a7740.h      |    6 +-
+ arch/arm/mach-shmobile/include/mach/r8a7779.h      |   12 +-
+ arch/arm/mach-shmobile/include/mach/sh7372.h       |   20 +-
+ arch/arm/mach-shmobile/pm-r8a7740.c                |   42 +-
+ arch/arm/mach-shmobile/pm-r8a7779.c                |   71 ++--
+ arch/arm/mach-shmobile/pm-rmobile.c                |   33 +-
+ arch/arm/mach-shmobile/pm-sh7372.c                 |  283 +++++++++-----
+ arch/arm/mach-shmobile/setup-r8a7740.c             |   27 +-
+ arch/arm/mach-shmobile/setup-r8a7779.c             |    5 +-
+ arch/arm/mach-shmobile/setup-sh7372.c              |   69 ++--
+ arch/x86/include/asm/msr-index.h                   |    3 +
+ drivers/acpi/processor_driver.c                    |    8 +-
+ drivers/acpi/processor_idle.c                      |   40 +-
+ drivers/acpi/processor_perflib.c                   |   30 ++
+ drivers/base/platform.c                            |    2 +
+ drivers/base/power/domain.c                        |  244 ++++++++++--
+ drivers/base/power/main.c                          |   66 +++-
+ drivers/base/power/opp.c                           |   47 +++
+ drivers/base/power/power.h                         |   36 +-
+ drivers/base/power/runtime.c                       |    3 +
+ drivers/base/power/wakeup.c                        |   46 ++-
+ drivers/clocksource/sh_cmt.c                       |   71 +++-
+ drivers/clocksource/sh_mtu2.c                      |   41 +-
+ drivers/clocksource/sh_tmu.c                       |  112 +++++-
+ drivers/cpufreq/Kconfig                            |   11 +
+ drivers/cpufreq/Kconfig.x86                        |   18 +-
+ drivers/cpufreq/Makefile                           |    4 +-
+ drivers/cpufreq/acpi-cpufreq.c                     |  272 ++++++++++++-
+ drivers/cpufreq/cpufreq-cpu0.c                     |  269 +++++++++++++
+ drivers/cpufreq/cpufreq_conservative.c             |    2 +
+ drivers/cpufreq/cpufreq_ondemand.c                 |    1 +
+ drivers/cpufreq/longhaul.h                         |   26 +-
+ drivers/cpufreq/omap-cpufreq.c                     |   39 +-
+ drivers/cpufreq/powernow-k8.c                      |  406 ++------------------
+ drivers/cpufreq/powernow-k8.h                      |   32 --
+ drivers/cpuidle/driver.c                           |   18 +-
+ drivers/cpuidle/governors/ladder.c                 |    6 +-
+ drivers/pci/pci-driver.c                           |   17 -
+ drivers/xen/xen-acpi-processor.c                   |    1 -
+ include/acpi/processor.h                           |    9 +-
+ include/linux/clockchips.h                         |    8 +
+ include/linux/device.h                             |    7 +
+ include/linux/opp.h                                |    8 +
+ include/linux/pm.h                                 |    2 +
+ include/linux/pm_domain.h                          |   92 ++++-
+ kernel/power/Kconfig                               |    4 +
+ kernel/power/poweroff.c                            |    2 +-
+ kernel/power/process.c                             |    2 +-
+ kernel/power/qos.c                                 |    1 +
+ kernel/time/clockevents.c                          |   24 ++
+ kernel/time/timekeeping.c                          |    2 +
+ 65 files changed, 2061 insertions(+), 962 deletions(-)
+ create mode 100644 Documentation/cpu-freq/boost.txt
+ create mode 100644 Documentation/devicetree/bindings/cpufreq/cpufreq-cpu0.txt
+ create mode 100644 Documentation/devicetree/bindings/power/opp.txt
+ delete mode 100644 arch/arm/mach-shmobile/common.c
+ create mode 100644 drivers/cpufreq/cpufreq-cpu0.c
+Merging apm/for-next (fb9d78a Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/apm)
+$ git merge apm/for-next
+Already up-to-date.
+Merging fsnotify/for-next (1aec9c0 inotify: automatically restart syscalls)
+$ git merge fsnotify/for-next
+Resolved 'kernel/audit_tree.c' using previous resolution.
+Auto-merging kernel/audit_watch.c
+Auto-merging kernel/audit_tree.c
+CONFLICT (content): Merge conflict in kernel/audit_tree.c
+Auto-merging include/linux/fsnotify_backend.h
+Auto-merging fs/notify/notification.c
+Auto-merging fs/notify/inotify/inotify_user.c
+Auto-merging fs/notify/fanotify/fanotify_user.c
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master f9382e8] Merge remote-tracking branch 'fsnotify/for-next'
+$ git diff -M --stat --summary HEAD^..
+ fs/notify/dnotify/dnotify.c          |    4 +-
+ fs/notify/fanotify/fanotify.c        |    6 +++
+ fs/notify/fanotify/fanotify_user.c   |   37 +++++++++-----
+ fs/notify/group.c                    |   47 ++++++++++--------
+ fs/notify/inode_mark.c               |   14 ++++--
+ fs/notify/inotify/inotify_fsnotify.c |    4 +-
+ fs/notify/inotify/inotify_user.c     |   34 ++++++-------
+ fs/notify/mark.c                     |   91 +++++++++++++++++++---------------
+ fs/notify/notification.c             |    1 +
+ fs/notify/vfsmount_mark.c            |   14 ++++--
+ include/linux/fsnotify_backend.h     |   31 ++++++++----
+ kernel/audit_tree.c                  |   10 ++--
+ kernel/audit_watch.c                 |    4 +-
+ 13 files changed, 178 insertions(+), 119 deletions(-)
+Merging edac/linux_next (cfe5031 edac: edac_mc no longer deals with kobjects directly)
+$ git merge edac/linux_next
+Merge made by the 'recursive' strategy.
+ drivers/edac/edac_mc.c    |    7 -------
+ drivers/edac/i3200_edac.c |    2 +-
+ drivers/edac/i5000_edac.c |    4 ++++
+ drivers/edac/sb_edac.c    |    7 ++++---
+ include/linux/edac.h      |    1 -
+ 5 files changed, 9 insertions(+), 12 deletions(-)
+Merging edac-amd/for-next (305f1c3 Merge branch '3.3-pci_device_id' into edac-for-next)
+$ git merge edac-amd/for-next
+Resolved 'Documentation/edac.txt' using previous resolution.
+Resolved 'drivers/edac/amd64_edac.c' using previous resolution.
+Auto-merging drivers/edac/amd64_edac.c
+CONFLICT (content): Merge conflict in drivers/edac/amd64_edac.c
+Auto-merging Documentation/edac.txt
+CONFLICT (content): Merge conflict in Documentation/edac.txt
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master 62828bd] Merge remote-tracking branch 'edac-amd/for-next'
+$ git diff -M --stat --summary HEAD^..
+Merging devicetree/devicetree/next (efd68e7 devicetree: add helper inline for retrieving a node's full name)
+$ git merge devicetree/devicetree/next
+Already up-to-date.
+Merging dt-rh/for-next (ee67016 of: i2c: add support for wakeup-source property)
+$ git merge dt-rh/for-next
+Merge made by the 'recursive' strategy.
+ Documentation/devicetree/bindings/pwm/mxs-pwm.txt  |    2 +-
+ .../devicetree/bindings/serial/fsl-imx-uart.txt    |   35 ++++++++++++++++++++
+ drivers/of/address.c                               |   35 +++++++++++++++++---
+ drivers/of/irq.c                                   |    1 +
+ drivers/of/of_i2c.c                                |    3 ++
+ drivers/of/platform.c                              |   16 +++++++--
+ include/linux/of_address.h                         |    1 +
+ 7 files changed, 85 insertions(+), 8 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/serial/fsl-imx-uart.txt
+Merging spi/spi/next (d8e328b spi: Add "spi:" prefix to modalias attribute of spi devices)
+$ git merge spi/spi/next
+Already up-to-date.
+Merging spi-mb/spi-next (08896f7 Merge branches 'spi-drivers' and 'spi-mxs' into spi-next)
+$ git merge spi-mb/spi-next
+Auto-merging drivers/spi/spi-topcliff-pch.c
+Auto-merging drivers/spi/spi-s3c64xx.c
+Auto-merging drivers/spi/Kconfig
+Merge made by the 'recursive' strategy.
+ Documentation/devicetree/bindings/spi/mxs-spi.txt  |   22 +
+ Documentation/devicetree/bindings/spi/spi-bus.txt  |    3 +
+ Documentation/devicetree/bindings/spi/spi-gpio.txt |   29 +
+ .../devicetree/bindings/spi/spi-sc18is602.txt      |   23 +
+ .../devicetree/bindings/spi/spi_pl022.txt          |   22 +
+ Documentation/spi/spi-sc18is602                    |   36 ++
+ arch/arm/mach-u300/core.c                          |    3 -
+ drivers/clk/mxs/Makefile                           |    2 +-
+ drivers/clk/mxs/clk-ssp.c                          |   62 ++
+ drivers/mmc/host/mxs-mmc.c                         |  323 +++-------
+ drivers/spi/Kconfig                                |   13 +
+ drivers/spi/Makefile                               |    2 +
+ drivers/spi/spi-altera.c                           |    4 +-
+ drivers/spi/spi-gpio.c                             |  131 +++-
+ drivers/spi/spi-mpc512x-psc.c                      |    3 +-
+ drivers/spi/spi-mpc52xx-psc.c                      |    3 +-
+ drivers/spi/spi-mpc52xx.c                          |    9 +-
+ drivers/spi/spi-mxs.c                              |  674 ++++++++++++++++++++
+ drivers/spi/spi-omap2-mcspi.c                      |  321 +++++-----
+ drivers/spi/spi-orion.c                            |  209 ++----
+ drivers/spi/spi-pl022.c                            |  196 +++++-
+ drivers/spi/spi-s3c24xx.c                          |    1 +
+ drivers/spi/spi-s3c64xx.c                          |   11 +-
+ drivers/spi/spi-sc18is602.c                        |  364 +++++++++++
+ drivers/spi/spi-sh-hspi.c                          |    5 +-
+ drivers/spi/spi-stmp.c                             |    6 +-
+ drivers/spi/spi-tegra.c                            |    4 +-
+ drivers/spi/spi-tle62x0.c                          |   13 +-
+ drivers/spi/spi-topcliff-pch.c                     |    2 -
+ include/linux/amba/pl022.h                         |    2 +
+ include/linux/platform_data/sc18is602.h            |   19 +
+ include/linux/spi/mxs-spi.h                        |  150 +++++
+ 32 files changed, 2082 insertions(+), 585 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/spi/mxs-spi.txt
+ create mode 100644 Documentation/devicetree/bindings/spi/spi-gpio.txt
+ create mode 100644 Documentation/devicetree/bindings/spi/spi-sc18is602.txt
+ create mode 100644 Documentation/spi/spi-sc18is602
+ create mode 100644 drivers/clk/mxs/clk-ssp.c
+ create mode 100644 drivers/spi/spi-mxs.c
+ create mode 100644 drivers/spi/spi-sc18is602.c
+ create mode 100644 include/linux/platform_data/sc18is602.h
+ create mode 100644 include/linux/spi/mxs-spi.h
+Merging tip/auto-latest (cd216c4 Merge branch 'linus')
+$ git merge tip/auto-latest
+Resolved 'arch/Kconfig' using previous resolution.
+Resolved 'arch/s390/Kconfig' using previous resolution.
+Auto-merging tools/perf/util/parse-events-test.c
+Auto-merging tools/perf/perf.h
+Auto-merging kernel/trace/trace_functions.c
+Auto-merging kernel/trace/trace.c
+Auto-merging kernel/sysctl.c
+Auto-merging kernel/fork.c
+Auto-merging kernel/events/core.c
+Auto-merging init/Kconfig
+Auto-merging include/linux/sched.h
+Auto-merging arch/x86/Kconfig
+Auto-merging arch/s390/kernel/vtime.c
+Auto-merging arch/s390/include/asm/switch_to.h
+Auto-merging arch/s390/Kconfig
+CONFLICT (content): Merge conflict in arch/s390/Kconfig
+Auto-merging arch/powerpc/kernel/time.c
+Auto-merging arch/powerpc/kernel/process.c
+Auto-merging arch/ia64/Kconfig
+Auto-merging arch/Kconfig
+CONFLICT (content): Merge conflict in arch/Kconfig
+Auto-merging Makefile
+Auto-merging MAINTAINERS
+Auto-merging Documentation/kernel-parameters.txt
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master 9b933c7] Merge remote-tracking branch 'tip/auto-latest'
+$ git diff -M --stat --summary HEAD^..
+ Documentation/kernel-parameters.txt                |   15 +-
+ Documentation/scheduler/sched-arch.txt             |   10 -
+ MAINTAINERS                                        |    8 +
+ Makefile                                           |    6 +-
+ arch/Kconfig                                       |   16 +
+ arch/ia64/Kconfig                                  |   12 +-
+ arch/ia64/include/asm/switch_to.h                  |    8 -
+ arch/ia64/kernel/time.c                            |    4 +-
+ arch/powerpc/include/asm/time.h                    |    6 -
+ arch/powerpc/kernel/process.c                      |    3 -
+ arch/powerpc/kernel/time.c                         |    6 +
+ arch/powerpc/platforms/Kconfig.cputype             |   16 +-
+ arch/s390/Kconfig                                  |    5 +-
+ arch/s390/include/asm/switch_to.h                  |    4 -
+ arch/s390/kernel/vtime.c                           |    4 +-
+ arch/tile/include/asm/topology.h                   |    1 -
+ arch/x86/Kconfig                                   |  116 +-
+ arch/x86/Kconfig.cpu                               |    5 +-
+ arch/x86/boot/compressed/Makefile                  |    3 +
+ arch/x86/boot/compressed/eboot.c                   |   34 +-
+ arch/x86/boot/compressed/eboot.h                   |    4 +
+ arch/x86/boot/header.S                             |    4 -
+ arch/x86/configs/i386_defconfig                    |   23 +-
+ arch/x86/configs/x86_64_defconfig                  |   23 +-
+ arch/x86/ia32/ia32_signal.c                        |   31 +-
+ arch/x86/ia32/ia32entry.S                          |    6 +
+ arch/x86/ia32/sys_ia32.c                           |    2 +-
+ arch/x86/include/asm/alternative-asm.h             |    9 +-
+ arch/x86/include/asm/alternative.h                 |   36 +-
+ arch/x86/include/asm/bitops.h                      |   14 +-
+ arch/x86/include/asm/cpufeature.h                  |    4 +
+ arch/x86/include/asm/fpu-internal.h                |  409 +++---
+ arch/x86/include/asm/ftrace.h                      |   56 +-
+ arch/x86/include/asm/futex.h                       |   19 +-
+ arch/x86/include/asm/i387.h                        |   29 +-
+ arch/x86/include/asm/iommu_table.h                 |    6 +-
+ arch/x86/include/asm/kprobes.h                     |    1 +
+ arch/x86/include/asm/mce.h                         |   12 +-
+ arch/x86/include/asm/microcode.h                   |   10 +-
+ arch/x86/include/asm/perf_event.h                  |    2 +
+ arch/x86/include/asm/perf_regs.h                   |   33 +
+ arch/x86/include/asm/pgtable_types.h               |    6 +-
+ arch/x86/include/asm/processor-flags.h             |    1 +
+ arch/x86/include/asm/processor.h                   |    3 +-
+ arch/x86/include/asm/signal.h                      |    4 +
+ arch/x86/include/asm/smap.h                        |   91 ++
+ arch/x86/include/asm/sys_ia32.h                    |    2 +-
+ arch/x86/include/asm/uaccess.h                     |   28 +-
+ arch/x86/include/asm/uaccess_32.h                  |    3 -
+ arch/x86/include/asm/uaccess_64.h                  |    3 -
+ arch/x86/include/asm/uprobes.h                     |    3 +-
+ arch/x86/include/asm/vdso.h                        |    3 +-
+ arch/x86/include/asm/x86_init.h                    |    9 +-
+ arch/x86/include/asm/xor_32.h                      |   56 +-
+ arch/x86/include/asm/xor_64.h                      |   61 +-
+ arch/x86/include/asm/xor_avx.h                     |   54 +-
+ arch/x86/include/asm/xsave.h                       |   23 +-
+ arch/x86/kernel/Makefile                           |    2 +
+ arch/x86/kernel/alternative.c                      |  111 +-
+ arch/x86/kernel/apic/apic.c                        |    2 +-
+ arch/x86/kernel/cpu/amd.c                          |   67 +
+ arch/x86/kernel/cpu/bugs.c                         |    7 +-
+ arch/x86/kernel/cpu/common.c                       |   48 +-
+ arch/x86/kernel/cpu/intel.c                        |    4 +
+ arch/x86/kernel/cpu/mcheck/mce-inject.c            |    8 +
+ arch/x86/kernel/cpu/mcheck/mce-internal.h          |   12 +
+ arch/x86/kernel/cpu/mcheck/mce.c                   |   84 +-
+ arch/x86/kernel/cpu/mcheck/mce_intel.c             |  133 +-
+ arch/x86/kernel/cpu/perf_event_intel_uncore.c      |   28 +-
+ arch/x86/kernel/cpu/perf_event_intel_uncore.h      |    6 +-
+ arch/x86/kernel/devicetree.c                       |   51 +-
+ arch/x86/kernel/entry_32.S                         |  100 +-
+ arch/x86/kernel/entry_64.S                         |  143 +-
+ arch/x86/kernel/ftrace.c                           |   73 +-
+ arch/x86/kernel/i387.c                             |  292 +---
+ arch/x86/kernel/i8259.c                            |    2 +-
+ arch/x86/kernel/kprobes.c                          |   67 +
+ arch/x86/kernel/microcode_amd.c                    |  357 +++--
+ arch/x86/kernel/microcode_core.c                   |   67 +-
+ arch/x86/kernel/microcode_intel.c                  |    3 +-
+ arch/x86/kernel/perf_regs.c                        |  105 ++
+ arch/x86/kernel/probe_roms.c                       |    2 +-
+ arch/x86/kernel/process.c                          |   22 +-
+ arch/x86/kernel/process_32.c                       |    4 -
+ arch/x86/kernel/process_64.c                       |    4 -
+ arch/x86/kernel/ptrace.c                           |    3 -
+ arch/x86/kernel/setup.c                            |    4 +-
+ arch/x86/kernel/signal.c                           |  227 ++-
+ arch/x86/kernel/smpboot.c                          |   20 +-
+ arch/x86/kernel/step.c                             |   53 +-
+ arch/x86/kernel/traps.c                            |    5 +-
+ arch/x86/kernel/uprobes.c                          |   52 +-
+ arch/x86/kernel/x8664_ksyms_64.c                   |    6 +-
+ arch/x86/kernel/x86_init.c                         |    4 +-
+ arch/x86/kernel/xsave.c                            |  517 ++++---
+ arch/x86/kvm/vmx.c                                 |   12 +-
+ arch/x86/kvm/x86.c                                 |    3 +-
+ arch/x86/lib/copy_user_64.S                        |    7 +
+ arch/x86/lib/copy_user_nocache_64.S                |    3 +
+ arch/x86/lib/getuser.S                             |   10 +
+ arch/x86/lib/putuser.S                             |    8 +-
+ arch/x86/lib/usercopy_32.c                         |   13 +-
+ arch/x86/lib/usercopy_64.c                         |    3 +
+ arch/x86/mm/fault.c                                |   18 +
+ arch/x86/mm/init_32.c                              |   13 +-
+ arch/x86/mm/tlb.c                                  |    2 +-
+ arch/x86/pci/mmconfig-shared.c                     |    2 +-
+ arch/x86/platform/efi/efi.c                        |    1 +
+ arch/x86/xen/mmu.c                                 |   18 +-
+ arch/x86/xen/smp.c                                 |    6 +-
+ drivers/infiniband/hw/ehca/ehca_irq.c              |  250 ++--
+ drivers/infiniband/hw/ehca/ehca_irq.h              |    6 +-
+ drivers/lguest/x86/core.c                          |   10 +-
+ drivers/oprofile/cpu_buffer.c                      |   11 +-
+ drivers/video/efifb.c                              |    4 +-
+ include/linux/ftrace.h                             |  158 +-
+ include/linux/kernel_stat.h                        |    6 +
+ include/linux/kprobes.h                            |   27 +
+ include/linux/kthread.h                            |   11 +-
+ include/linux/perf_event.h                         |   60 +-
+ include/linux/perf_regs.h                          |   25 +
+ include/linux/sched.h                              |   13 +-
+ include/linux/screen_info.h                        |    2 +
+ include/linux/smpboot.h                            |   43 +
+ include/linux/task_work.h                          |    3 +-
+ include/linux/timer.h                              |  165 +--
+ include/linux/topology.h                           |    2 -
+ include/linux/tracepoint.h                         |   28 +-
+ include/linux/uprobes.h                            |   15 +-
+ init/Kconfig                                       |   13 +
+ kernel/Kconfig.locks                               |  103 +-
+ kernel/Makefile                                    |    5 +-
+ kernel/cpu.c                                       |   21 +-
+ kernel/events/callchain.c                          |   38 +-
+ kernel/events/core.c                               |  214 +++
+ kernel/events/internal.h                           |   82 +-
+ kernel/events/ring_buffer.c                        |   10 +-
+ kernel/events/uprobes.c                            |  248 ++--
+ kernel/fork.c                                      |   10 +-
+ kernel/irq/chip.c                                  |    1 +
+ kernel/irq/dummychip.c                             |    2 +
+ kernel/kprobes.c                                   |  247 +++-
+ kernel/kthread.c                                   |  185 ++-
+ kernel/lockdep.c                                   |   39 +
+ kernel/rcutree.c                                   |   12 +-
+ kernel/rcutree.h                                   |   15 +-
+ kernel/rcutree_plugin.h                            |  403 +-----
+ kernel/rcutree_trace.c                             |    3 +-
+ kernel/sched/Makefile                              |    2 +-
+ kernel/sched/core.c                                |  677 +--------
+ kernel/sched/cputime.c                             |  504 +++++++
+ kernel/sched/fair.c                                |   81 +-
+ kernel/sched/features.h                            |   10 +-
+ kernel/sched/rt.c                                  |    5 -
+ kernel/sched/sched.h                               |   69 +-
+ kernel/signal.c                                    |   18 +-
+ kernel/smpboot.c                                   |  233 +++
+ kernel/smpboot.h                                   |    4 +
+ kernel/softirq.c                                   |  111 +-
+ kernel/sysctl.c                                    |    6 +-
+ kernel/task_work.c                                 |  111 +-
+ kernel/time/tick-sched.c                           |    3 +-
+ kernel/timer.c                                     |  108 +-
+ kernel/trace/Kconfig                               |   10 +
+ kernel/trace/Makefile                              |    8 +-
+ kernel/trace/ftrace.c                              |  322 ++++-
+ kernel/trace/ring_buffer.c                         |    4 +-
+ kernel/trace/trace.c                               |    6 +-
+ kernel/trace/trace.h                               |    2 +-
+ kernel/trace/trace_event_perf.c                    |    3 +-
+ kernel/trace/trace_events.c                        |    8 +-
+ kernel/trace/trace_events_filter.c                 |    2 +-
+ kernel/trace/trace_functions.c                     |   14 +-
+ kernel/trace/trace_functions_graph.c               |    5 +-
+ kernel/trace/trace_irqsoff.c                       |    5 +-
+ kernel/trace/trace_sched_wakeup.c                  |    5 +-
+ kernel/trace/trace_selftest.c                      |  304 +++-
+ kernel/trace/trace_stack.c                         |    4 +-
+ kernel/watchdog.c                                  |  263 ++--
+ scripts/kconfig/Makefile                           |    7 +-
+ scripts/recordmcount.h                             |    4 +-
+ security/keys/keyctl.c                             |    2 -
+ tools/kvm/.gitignore                               |   12 +
+ tools/kvm/CREDITS-Git                              |   30 +
+ tools/kvm/Documentation/kernel-debugging.txt       |   15 +
+ tools/kvm/Documentation/kvm-balloon.txt            |   24 +
+ tools/kvm/Documentation/kvm-debug.txt              |   16 +
+ tools/kvm/Documentation/kvm-list.txt               |   16 +
+ tools/kvm/Documentation/kvm-pause.txt              |   16 +
+ tools/kvm/Documentation/kvm-resume.txt             |   16 +
+ tools/kvm/Documentation/kvm-run.txt                |   62 +
+ tools/kvm/Documentation/kvm-sandbox.txt            |   16 +
+ tools/kvm/Documentation/kvm-setup.txt              |   15 +
+ tools/kvm/Documentation/kvm-stat.txt               |   19 +
+ tools/kvm/Documentation/kvm-stop.txt               |   16 +
+ tools/kvm/Documentation/kvm-version.txt            |   21 +
+ tools/kvm/Documentation/virtio-console.txt         |   41 +
+ tools/kvm/Makefile                                 |  440 ++++++
+ tools/kvm/README                                   |  112 ++
+ tools/kvm/builtin-balloon.c                        |   80 +
+ tools/kvm/builtin-debug.c                          |  110 ++
+ tools/kvm/builtin-help.c                           |   63 +
+ tools/kvm/builtin-list.c                           |  149 ++
+ tools/kvm/builtin-pause.c                          |   88 ++
+ tools/kvm/builtin-resume.c                         |   88 ++
+ tools/kvm/builtin-run.c                            | 1426 ++++++++++++++++++
+ tools/kvm/builtin-sandbox.c                        |    9 +
+ tools/kvm/builtin-setup.c                          |  262 ++++
+ tools/kvm/builtin-stat.c                           |  127 ++
+ tools/kvm/builtin-stop.c                           |   70 +
+ tools/kvm/builtin-version.c                        |   15 +
+ tools/kvm/code16gcc.h                              |   15 +
+ tools/kvm/command-list.txt                         |   15 +
+ tools/kvm/config/feature-tests.mak                 |  177 +++
+ tools/kvm/config/utilities.mak                     |  196 +++
+ tools/kvm/disk/blk.c                               |   76 +
+ tools/kvm/disk/core.c                              |  289 ++++
+ tools/kvm/disk/qcow.c                              | 1529 ++++++++++++++++++++
+ tools/kvm/disk/raw.c                               |  141 ++
+ tools/kvm/framebuffer.c                            |   75 +
+ tools/kvm/guest/init.c                             |   72 +
+ tools/kvm/guest_compat.c                           |   99 ++
+ tools/kvm/hw/i8042.c                               |  348 +++++
+ tools/kvm/hw/pci-shmem.c                           |  268 ++++
+ tools/kvm/hw/rtc.c                                 |  137 ++
+ tools/kvm/hw/serial.c                              |  446 ++++++
+ tools/kvm/hw/vesa.c                                |   85 ++
+ tools/kvm/include/asm/hweight.h                    |    8 +
+ tools/kvm/include/bios/memcpy.h                    |    9 +
+ tools/kvm/include/kvm/8250-serial.h                |   11 +
+ tools/kvm/include/kvm/apic.h                       |   17 +
+ tools/kvm/include/kvm/brlock.h                     |   41 +
+ tools/kvm/include/kvm/builtin-balloon.h            |    9 +
+ tools/kvm/include/kvm/builtin-debug.h              |   20 +
+ tools/kvm/include/kvm/builtin-help.h               |    6 +
+ tools/kvm/include/kvm/builtin-list.h               |   10 +
+ tools/kvm/include/kvm/builtin-pause.h              |    9 +
+ tools/kvm/include/kvm/builtin-resume.h             |    9 +
+ tools/kvm/include/kvm/builtin-run.h                |   11 +
+ tools/kvm/include/kvm/builtin-sandbox.h            |    6 +
+ tools/kvm/include/kvm/builtin-setup.h              |   11 +
+ tools/kvm/include/kvm/builtin-stat.h               |    9 +
+ tools/kvm/include/kvm/builtin-stop.h               |    9 +
+ tools/kvm/include/kvm/builtin-version.h            |    6 +
+ tools/kvm/include/kvm/compiler.h                   |   10 +
+ tools/kvm/include/kvm/disk-image.h                 |   95 ++
+ tools/kvm/include/kvm/e820.h                       |   13 +
+ tools/kvm/include/kvm/framebuffer.h                |   35 +
+ tools/kvm/include/kvm/guest_compat.h               |    9 +
+ tools/kvm/include/kvm/i8042.h                      |   12 +
+ tools/kvm/include/kvm/ioeventfd.h                  |   28 +
+ tools/kvm/include/kvm/ioport.h                     |   69 +
+ tools/kvm/include/kvm/irq.h                        |   33 +
+ tools/kvm/include/kvm/kvm-cmd.h                    |   17 +
+ tools/kvm/include/kvm/kvm-cpu.h                    |   24 +
+ tools/kvm/include/kvm/kvm-ipc.h                    |   24 +
+ tools/kvm/include/kvm/kvm.h                        |   93 ++
+ tools/kvm/include/kvm/msi.h                        |   10 +
+ tools/kvm/include/kvm/mutex.h                      |   33 +
+ tools/kvm/include/kvm/parse-options.h              |  214 +++
+ tools/kvm/include/kvm/pci-shmem.h                  |   28 +
+ tools/kvm/include/kvm/pci.h                        |   95 ++
+ tools/kvm/include/kvm/qcow.h                       |  133 ++
+ tools/kvm/include/kvm/rbtree-interval.h            |   28 +
+ tools/kvm/include/kvm/read-write.h                 |   43 +
+ tools/kvm/include/kvm/rtc.h                        |    9 +
+ tools/kvm/include/kvm/rwsem.h                      |   39 +
+ tools/kvm/include/kvm/sdl.h                        |   22 +
+ tools/kvm/include/kvm/segment.h                    |   21 +
+ tools/kvm/include/kvm/strbuf.h                     |   20 +
+ tools/kvm/include/kvm/symbol.h                     |   30 +
+ tools/kvm/include/kvm/term.h                       |   20 +
+ tools/kvm/include/kvm/threadpool.h                 |   37 +
+ tools/kvm/include/kvm/types.h                      |    7 +
+ tools/kvm/include/kvm/uip.h                        |  360 +++++
+ tools/kvm/include/kvm/util.h                       |   97 ++
+ tools/kvm/include/kvm/vesa.h                       |   18 +
+ tools/kvm/include/kvm/virtio-9p.h                  |   73 +
+ tools/kvm/include/kvm/virtio-balloon.h             |    8 +
+ tools/kvm/include/kvm/virtio-blk.h                 |   12 +
+ tools/kvm/include/kvm/virtio-console.h             |    9 +
+ tools/kvm/include/kvm/virtio-mmio.h                |   58 +
+ tools/kvm/include/kvm/virtio-net.h                 |   26 +
+ tools/kvm/include/kvm/virtio-pci-dev.h             |   38 +
+ tools/kvm/include/kvm/virtio-pci.h                 |   49 +
+ tools/kvm/include/kvm/virtio-rng.h                 |    9 +
+ tools/kvm/include/kvm/virtio-scsi.h                |   26 +
+ tools/kvm/include/kvm/virtio.h                     |  102 ++
+ tools/kvm/include/kvm/vnc.h                        |   20 +
+ tools/kvm/include/linux/bitops.h                   |   33 +
+ tools/kvm/include/linux/byteorder.h                |    7 +
+ tools/kvm/include/linux/compiler.h                 |   20 +
+ tools/kvm/include/linux/kernel.h                   |   39 +
+ tools/kvm/include/linux/module.h                   |    6 +
+ tools/kvm/include/linux/prefetch.h                 |    6 +
+ tools/kvm/include/linux/stddef.h                   |   16 +
+ tools/kvm/include/linux/types.h                    |   51 +
+ tools/kvm/ioeventfd.c                              |  214 +++
+ tools/kvm/ioport.c                                 |  195 +++
+ tools/kvm/kvm-cmd.c                                |   91 ++
+ tools/kvm/kvm-cpu.c                                |  175 +++
+ tools/kvm/kvm-ipc.c                                |  231 +++
+ tools/kvm/kvm.c                                    |  593 ++++++++
+ tools/kvm/main.c                                   |   19 +
+ tools/kvm/mmio.c                                   |  140 ++
+ tools/kvm/net/uip/arp.c                            |   30 +
+ tools/kvm/net/uip/buf.c                            |  114 ++
+ tools/kvm/net/uip/core.c                           |  190 +++
+ tools/kvm/net/uip/csum.c                           |   92 ++
+ tools/kvm/net/uip/dhcp.c                           |  202 +++
+ tools/kvm/net/uip/icmp.c                           |   29 +
+ tools/kvm/net/uip/ipv4.c                           |   29 +
+ tools/kvm/net/uip/tcp.c                            |  345 +++++
+ tools/kvm/net/uip/udp.c                            |  236 +++
+ tools/kvm/pci.c                                    |  213 +++
+ tools/kvm/powerpc/boot.c                           |    8 +
+ tools/kvm/powerpc/cpu_info.c                       |  195 +++
+ tools/kvm/powerpc/cpu_info.h                       |   42 +
+ tools/kvm/powerpc/include/kvm/barrier.h            |    6 +
+ tools/kvm/powerpc/include/kvm/kvm-arch.h           |   90 ++
+ tools/kvm/powerpc/include/kvm/kvm-cpu-arch.h       |   76 +
+ tools/kvm/powerpc/ioport.c                         |   18 +
+ tools/kvm/powerpc/irq.c                            |   75 +
+ tools/kvm/powerpc/kvm-cpu.c                        |  293 ++++
+ tools/kvm/powerpc/kvm.c                            |  529 +++++++
+ tools/kvm/powerpc/spapr.h                          |   93 ++
+ tools/kvm/powerpc/spapr_hcall.c                    |  134 ++
+ tools/kvm/powerpc/spapr_hvcons.c                   |  102 ++
+ tools/kvm/powerpc/spapr_hvcons.h                   |   19 +
+ tools/kvm/powerpc/spapr_pci.c                      |  423 ++++++
+ tools/kvm/powerpc/spapr_pci.h                      |   57 +
+ tools/kvm/powerpc/spapr_rtas.c                     |  229 +++
+ tools/kvm/powerpc/xics.c                           |  514 +++++++
+ tools/kvm/powerpc/xics.h                           |   23 +
+ tools/kvm/symbol.c                                 |  131 ++
+ tools/kvm/term.c                                   |  166 +++
+ tools/kvm/tests/Makefile                           |   19 +
+ tools/kvm/tests/boot/Makefile                      |   13 +
+ tools/kvm/tests/boot/init.c                        |   11 +
+ tools/kvm/tests/kernel/.gitignore                  |    2 +
+ tools/kvm/tests/kernel/Makefile                    |   20 +
+ tools/kvm/tests/kernel/README                      |   16 +
+ tools/kvm/tests/kernel/kernel.S                    |    8 +
+ tools/kvm/tests/pit/.gitignore                     |    2 +
+ tools/kvm/tests/pit/Makefile                       |   20 +
+ tools/kvm/tests/pit/README                         |   16 +
+ tools/kvm/tests/pit/tick.S                         |  109 ++
+ tools/kvm/ui/sdl.c                                 |  303 ++++
+ tools/kvm/ui/vnc.c                                 |  230 +++
+ tools/kvm/util/KVMTOOLS-VERSION-GEN                |   40 +
+ tools/kvm/util/generate-cmdlist.sh                 |   23 +
+ tools/kvm/util/kvm-ifup-vbr0                       |    6 +
+ tools/kvm/util/parse-options.c                     |  577 ++++++++
+ tools/kvm/util/rbtree-interval.c                   |   89 ++
+ tools/kvm/util/read-write.c                        |  354 +++++
+ tools/kvm/util/set_private_br.sh                   |   51 +
+ tools/kvm/util/strbuf.c                            |   62 +
+ tools/kvm/util/threadpool.c                        |  145 ++
+ tools/kvm/util/util.c                              |  133 ++
+ tools/kvm/virtio/9p-pdu.c                          |  287 ++++
+ tools/kvm/virtio/9p.c                              | 1379 ++++++++++++++++++
+ tools/kvm/virtio/balloon.c                         |  259 ++++
+ tools/kvm/virtio/blk.c                             |  313 ++++
+ tools/kvm/virtio/console.c                         |  185 +++
+ tools/kvm/virtio/core.c                            |  233 +++
+ tools/kvm/virtio/mmio.c                            |  264 ++++
+ tools/kvm/virtio/net.c                             |  546 +++++++
+ tools/kvm/virtio/pci.c                             |  398 +++++
+ tools/kvm/virtio/rng.c                             |  188 +++
+ tools/kvm/virtio/scsi.c                            |  307 ++++
+ tools/kvm/x86/bios.c                               |  174 +++
+ tools/kvm/x86/bios/.gitignore                      |    3 +
+ tools/kvm/x86/bios/bios-rom.S                      |   12 +
+ tools/kvm/x86/bios/e820.c                          |   72 +
+ tools/kvm/x86/bios/entry.S                         |   92 ++
+ tools/kvm/x86/bios/gen-offsets.sh                  |   14 +
+ tools/kvm/x86/bios/int10.c                         |  110 ++
+ tools/kvm/x86/bios/int15.c                         |   18 +
+ tools/kvm/x86/bios/local.S                         |    7 +
+ tools/kvm/x86/bios/macro.S                         |   25 +
+ tools/kvm/x86/bios/memcpy.c                        |   23 +
+ tools/kvm/x86/bios/rom.ld.S                        |   16 +
+ tools/kvm/x86/boot.c                               |   41 +
+ tools/kvm/x86/cpuid.c                              |   60 +
+ tools/kvm/x86/include/kvm/assembly.h               |   24 +
+ tools/kvm/x86/include/kvm/barrier.h                |   20 +
+ tools/kvm/x86/include/kvm/bios-export.h            |   13 +
+ tools/kvm/x86/include/kvm/bios.h                   |   93 ++
+ tools/kvm/x86/include/kvm/boot-protocol.h          |   16 +
+ tools/kvm/x86/include/kvm/cpufeature.h             |   41 +
+ tools/kvm/x86/include/kvm/interrupt.h              |   26 +
+ tools/kvm/x86/include/kvm/kvm-arch.h               |   67 +
+ tools/kvm/x86/include/kvm/kvm-cpu-arch.h           |   49 +
+ tools/kvm/x86/include/kvm/mptable.h                |    9 +
+ tools/kvm/x86/interrupt.c                          |   28 +
+ tools/kvm/x86/ioport.c                             |   77 +
+ tools/kvm/x86/irq.c                                |  222 +++
+ tools/kvm/x86/kvm-cpu.c                            |  425 ++++++
+ tools/kvm/x86/kvm.c                                |  372 +++++
+ tools/kvm/x86/mptable.c                            |  287 ++++
+ tools/lib/traceevent/Makefile                      |    2 +-
+ tools/lib/traceevent/event-parse.c                 |  198 ++-
+ tools/lib/traceevent/event-parse.h                 |   43 +-
+ tools/lib/traceevent/event-utils.h                 |    6 +
+ tools/perf/.gitignore                              |    2 +
+ tools/perf/Documentation/Makefile                  |    6 +-
+ tools/perf/Documentation/jit-interface.txt         |   15 +
+ tools/perf/Documentation/perf-annotate.txt         |    3 +
+ tools/perf/Documentation/perf-diff.txt             |    3 +
+ tools/perf/Documentation/perf-list.txt             |   48 +-
+ tools/perf/Documentation/perf-report.txt           |    3 +
+ tools/perf/Documentation/perf-script-perl.txt      |    4 +-
+ tools/perf/Documentation/perf-script-python.txt    |   10 +-
+ tools/perf/MANIFEST                                |    1 +
+ tools/perf/Makefile                                |  154 +-
+ tools/perf/arch/x86/Makefile                       |    3 +
+ tools/perf/arch/x86/include/perf_regs.h            |   80 +
+ tools/perf/arch/x86/util/unwind.c                  |  111 ++
+ tools/perf/bash_completion                         |   26 +
+ tools/perf/bench/bench.h                           |    3 +-
+ tools/perf/bench/mem-memcpy.c                      |    2 +-
+ tools/perf/bench/mem-memset.c                      |    2 +-
+ tools/perf/bench/sched-messaging.c                 |    2 +-
+ tools/perf/bench/sched-pipe.c                      |   10 +-
+ tools/perf/builtin-annotate.c                      |    4 +-
+ tools/perf/builtin-bench.c                         |    2 +-
+ tools/perf/builtin-buildid-cache.c                 |   10 +-
+ tools/perf/builtin-buildid-list.c                  |    7 +-
+ tools/perf/builtin-diff.c                          |   96 +-
+ tools/perf/builtin-evlist.c                        |    2 +-
+ tools/perf/builtin-help.c                          |   50 +-
+ tools/perf/builtin-inject.c                        |   29 +-
+ tools/perf/builtin-kmem.c                          |  182 +--
+ tools/perf/builtin-kvm.c                           |    2 +-
+ tools/perf/builtin-list.c                          |   16 +-
+ tools/perf/builtin-lock.c                          |  317 ++--
+ tools/perf/builtin-probe.c                         |   24 +-
+ tools/perf/builtin-record.c                        |  297 +++-
+ tools/perf/builtin-report.c                        |   47 +-
+ tools/perf/builtin-sched.c                         | 1522 +++++++++----------
+ tools/perf/builtin-script.c                        |  229 +--
+ tools/perf/builtin-stat.c                          |  134 +-
+ tools/perf/builtin-test.c                          |  147 +-
+ tools/perf/builtin-timechart.c                     |   30 +-
+ tools/perf/builtin-top.c                           |   31 +-
+ tools/perf/builtin.h                               |    1 +
+ tools/perf/command-list.txt                        |    2 +-
+ tools/perf/config/feature-tests.mak                |   39 +
+ tools/perf/perf-archive.sh                         |    6 +-
+ tools/perf/perf.c                                  |   72 +-
+ tools/perf/perf.h                                  |    9 +-
+ .../Perf-Trace-Util/lib/Perf/Trace/EventClass.py   |   94 ++
+ .../python/bin/event_analyzing_sample-record       |    8 +
+ .../python/bin/event_analyzing_sample-report       |    3 +
+ .../perf/scripts/python/event_analyzing_sample.py  |  189 +++
+ tools/perf/ui/browser.c                            |    7 +-
+ tools/perf/ui/browsers/annotate.c                  |    6 +-
+ tools/perf/ui/browsers/hists.c                     |  133 +-
+ tools/perf/ui/gtk/browser.c                        |  111 +-
+ tools/perf/ui/gtk/gtk.h                            |    3 +
+ tools/perf/ui/gtk/helpline.c                       |   56 +
+ tools/perf/ui/gtk/setup.c                          |    6 +-
+ tools/perf/ui/gtk/util.c                           |    9 +-
+ tools/perf/ui/helpline.c                           |   56 +-
+ tools/perf/ui/helpline.h                           |   33 +-
+ tools/perf/ui/hist.c                               |  390 +++++
+ tools/perf/ui/setup.c                              |   10 +-
+ tools/perf/ui/stdio/hist.c                         |  498 +++++++
+ tools/perf/ui/tui/helpline.c                       |   57 +
+ tools/perf/ui/tui/setup.c                          |   10 +-
+ tools/perf/util/alias.c                            |    3 +-
+ tools/perf/util/annotate.c                         |   19 +-
+ tools/perf/util/annotate.h                         |   15 +-
+ tools/perf/util/build-id.c                         |   11 +-
+ tools/perf/util/cache.h                            |    6 +-
+ tools/perf/util/callchain.c                        |    6 +-
+ tools/perf/util/cgroup.c                           |    4 +-
+ tools/perf/util/config.c                           |    6 +-
+ tools/perf/util/cpumap.c                           |   22 +-
+ tools/perf/util/cpumap.h                           |    2 +-
+ tools/perf/util/debug.c                            |    4 +-
+ tools/perf/util/debug.h                            |   17 +-
+ tools/perf/util/dso-test-data.c                    |    2 +-
+ tools/perf/util/event.c                            |   71 +-
+ tools/perf/util/event.h                            |   14 +-
+ tools/perf/util/evlist.c                           |   86 +-
+ tools/perf/util/evlist.h                           |   29 +-
+ tools/perf/util/evsel.c                            |  134 +-
+ tools/perf/util/evsel.h                            |   42 +-
+ tools/perf/util/generate-cmdlist.sh                |   15 +
+ tools/perf/util/header.c                           |  574 +++++---
+ tools/perf/util/header.h                           |    5 +-
+ tools/perf/util/help.c                             |    4 +-
+ tools/perf/util/hist.c                             |  712 +--------
+ tools/perf/util/hist.h                             |   75 +-
+ tools/perf/util/include/linux/bitops.h             |    4 +
+ tools/perf/util/include/linux/compiler.h           |    9 +-
+ tools/perf/util/include/linux/kernel.h             |   17 +-
+ tools/perf/util/include/linux/magic.h              |   12 +
+ tools/perf/util/include/linux/rbtree.h             |    1 +
+ tools/perf/util/include/linux/string.h             |    2 +
+ tools/perf/util/include/linux/types.h              |    8 +
+ tools/perf/util/intlist.c                          |    8 +-
+ tools/perf/util/map.c                              |   42 +-
+ tools/perf/util/map.h                              |    9 +-
+ tools/perf/util/parse-events-test.c                |  424 +++++-
+ tools/perf/util/parse-events.c                     |  208 ++-
+ tools/perf/util/parse-events.h                     |   18 +-
+ tools/perf/util/parse-events.l                     |   56 +-
+ tools/perf/util/parse-events.y                     |  125 +-
+ tools/perf/util/parse-options.c                    |    3 +-
+ tools/perf/util/perf_regs.h                        |   14 +
+ tools/perf/util/pmu.c                              |   80 +-
+ tools/perf/util/pmu.h                              |    3 +
+ tools/perf/util/pmu.y                              |    6 +-
+ tools/perf/util/probe-event.c                      |   33 +-
+ tools/perf/util/probe-finder.c                     |   28 +-
+ tools/perf/util/python.c                           |   15 +-
+ .../perf/util/scripting-engines/trace-event-perl.c |   50 +-
+ .../util/scripting-engines/trace-event-python.c    |  113 +-
+ tools/perf/util/session.c                          |  192 ++-
+ tools/perf/util/session.h                          |   10 +-
+ tools/perf/util/sort.c                             |   25 +-
+ tools/perf/util/sort.h                             |    2 +-
+ tools/perf/util/stat.c                             |   57 +
+ tools/perf/util/stat.h                             |   16 +
+ tools/perf/util/string.c                           |   18 +-
+ tools/perf/util/strlist.c                          |    2 +-
+ tools/perf/util/symbol-elf.c                       |  841 +++++++++++
+ tools/perf/util/symbol-minimal.c                   |  307 ++++
+ tools/perf/util/symbol.c                           |  942 ++----------
+ tools/perf/util/symbol.h                           |   66 +-
+ tools/perf/util/target.c                           |    4 +-
+ tools/perf/util/top.c                              |    3 +-
+ tools/perf/util/top.h                              |    1 +
+ tools/perf/util/trace-event-parse.c                |   36 +-
+ tools/perf/util/trace-event-scripting.c            |   34 +-
+ tools/perf/util/trace-event.h                      |   12 +-
+ tools/perf/util/unwind.c                           |  571 ++++++++
+ tools/perf/util/unwind.h                           |   35 +
+ tools/perf/util/util.c                             |   25 +
+ tools/perf/util/util.h                             |    9 +-
+ tools/perf/util/vdso.c                             |  111 ++
+ tools/perf/util/vdso.h                             |   18 +
+ tools/perf/util/wrapper.c                          |    3 +-
+ tools/scripts/Makefile.include                     |    6 +-
+ 546 files changed, 39300 insertions(+), 7806 deletions(-)
+ create mode 100644 arch/x86/include/asm/perf_regs.h
+ create mode 100644 arch/x86/include/asm/smap.h
+ create mode 100644 arch/x86/kernel/perf_regs.c
+ create mode 100644 include/linux/perf_regs.h
+ create mode 100644 include/linux/smpboot.h
+ create mode 100644 kernel/sched/cputime.c
+ create mode 100644 tools/kvm/.gitignore
+ create mode 100644 tools/kvm/CREDITS-Git
+ create mode 100644 tools/kvm/Documentation/kernel-debugging.txt
+ create mode 100644 tools/kvm/Documentation/kvm-balloon.txt
+ create mode 100644 tools/kvm/Documentation/kvm-debug.txt
+ create mode 100644 tools/kvm/Documentation/kvm-list.txt
+ create mode 100644 tools/kvm/Documentation/kvm-pause.txt
+ create mode 100644 tools/kvm/Documentation/kvm-resume.txt
+ create mode 100644 tools/kvm/Documentation/kvm-run.txt
+ create mode 100644 tools/kvm/Documentation/kvm-sandbox.txt
+ create mode 100644 tools/kvm/Documentation/kvm-setup.txt
+ create mode 100644 tools/kvm/Documentation/kvm-stat.txt
+ create mode 100644 tools/kvm/Documentation/kvm-stop.txt
+ create mode 100644 tools/kvm/Documentation/kvm-version.txt
+ create mode 100644 tools/kvm/Documentation/virtio-console.txt
+ create mode 100644 tools/kvm/Makefile
+ create mode 100644 tools/kvm/README
+ create mode 100644 tools/kvm/builtin-balloon.c
+ create mode 100644 tools/kvm/builtin-debug.c
+ create mode 100644 tools/kvm/builtin-help.c
+ create mode 100644 tools/kvm/builtin-list.c
+ create mode 100644 tools/kvm/builtin-pause.c
+ create mode 100644 tools/kvm/builtin-resume.c
+ create mode 100644 tools/kvm/builtin-run.c
+ create mode 100644 tools/kvm/builtin-sandbox.c
+ create mode 100644 tools/kvm/builtin-setup.c
+ create mode 100644 tools/kvm/builtin-stat.c
+ create mode 100644 tools/kvm/builtin-stop.c
+ create mode 100644 tools/kvm/builtin-version.c
+ create mode 100644 tools/kvm/code16gcc.h
+ create mode 100644 tools/kvm/command-list.txt
+ create mode 100644 tools/kvm/config/feature-tests.mak
+ create mode 100644 tools/kvm/config/utilities.mak
+ create mode 100644 tools/kvm/disk/blk.c
+ create mode 100644 tools/kvm/disk/core.c
+ create mode 100644 tools/kvm/disk/qcow.c
+ create mode 100644 tools/kvm/disk/raw.c
+ create mode 100644 tools/kvm/framebuffer.c
+ create mode 100644 tools/kvm/guest/init.c
+ create mode 100644 tools/kvm/guest_compat.c
+ create mode 100644 tools/kvm/hw/i8042.c
+ create mode 100644 tools/kvm/hw/pci-shmem.c
+ create mode 100644 tools/kvm/hw/rtc.c
+ create mode 100644 tools/kvm/hw/serial.c
+ create mode 100644 tools/kvm/hw/vesa.c
+ create mode 100644 tools/kvm/include/asm/hweight.h
+ create mode 100644 tools/kvm/include/bios/memcpy.h
+ create mode 100644 tools/kvm/include/kvm/8250-serial.h
+ create mode 100644 tools/kvm/include/kvm/apic.h
+ create mode 100644 tools/kvm/include/kvm/brlock.h
+ create mode 100644 tools/kvm/include/kvm/builtin-balloon.h
+ create mode 100644 tools/kvm/include/kvm/builtin-debug.h
+ create mode 100644 tools/kvm/include/kvm/builtin-help.h
+ create mode 100644 tools/kvm/include/kvm/builtin-list.h
+ create mode 100644 tools/kvm/include/kvm/builtin-pause.h
+ create mode 100644 tools/kvm/include/kvm/builtin-resume.h
+ create mode 100644 tools/kvm/include/kvm/builtin-run.h
+ create mode 100644 tools/kvm/include/kvm/builtin-sandbox.h
+ create mode 100644 tools/kvm/include/kvm/builtin-setup.h
+ create mode 100644 tools/kvm/include/kvm/builtin-stat.h
+ create mode 100644 tools/kvm/include/kvm/builtin-stop.h
+ create mode 100644 tools/kvm/include/kvm/builtin-version.h
+ create mode 100644 tools/kvm/include/kvm/compiler.h
+ create mode 100644 tools/kvm/include/kvm/disk-image.h
+ create mode 100644 tools/kvm/include/kvm/e820.h
+ create mode 100644 tools/kvm/include/kvm/framebuffer.h
+ create mode 100644 tools/kvm/include/kvm/guest_compat.h
+ create mode 100644 tools/kvm/include/kvm/i8042.h
+ create mode 100644 tools/kvm/include/kvm/ioeventfd.h
+ create mode 100644 tools/kvm/include/kvm/ioport.h
+ create mode 100644 tools/kvm/include/kvm/irq.h
+ create mode 100644 tools/kvm/include/kvm/kvm-cmd.h
+ create mode 100644 tools/kvm/include/kvm/kvm-cpu.h
+ create mode 100644 tools/kvm/include/kvm/kvm-ipc.h
+ create mode 100644 tools/kvm/include/kvm/kvm.h
+ create mode 100644 tools/kvm/include/kvm/msi.h
+ create mode 100644 tools/kvm/include/kvm/mutex.h
+ create mode 100644 tools/kvm/include/kvm/parse-options.h
+ create mode 100644 tools/kvm/include/kvm/pci-shmem.h
+ create mode 100644 tools/kvm/include/kvm/pci.h
+ create mode 100644 tools/kvm/include/kvm/qcow.h
+ create mode 100644 tools/kvm/include/kvm/rbtree-interval.h
+ create mode 100644 tools/kvm/include/kvm/read-write.h
+ create mode 100644 tools/kvm/include/kvm/rtc.h
+ create mode 100644 tools/kvm/include/kvm/rwsem.h
+ create mode 100644 tools/kvm/include/kvm/sdl.h
+ create mode 100644 tools/kvm/include/kvm/segment.h
+ create mode 100644 tools/kvm/include/kvm/strbuf.h
+ create mode 100644 tools/kvm/include/kvm/symbol.h
+ create mode 100644 tools/kvm/include/kvm/term.h
+ create mode 100644 tools/kvm/include/kvm/threadpool.h
+ create mode 100644 tools/kvm/include/kvm/types.h
+ create mode 100644 tools/kvm/include/kvm/uip.h
+ create mode 100644 tools/kvm/include/kvm/util.h
+ create mode 100644 tools/kvm/include/kvm/vesa.h
+ create mode 100644 tools/kvm/include/kvm/virtio-9p.h
+ create mode 100644 tools/kvm/include/kvm/virtio-balloon.h
+ create mode 100644 tools/kvm/include/kvm/virtio-blk.h
+ create mode 100644 tools/kvm/include/kvm/virtio-console.h
+ create mode 100644 tools/kvm/include/kvm/virtio-mmio.h
+ create mode 100644 tools/kvm/include/kvm/virtio-net.h
+ create mode 100644 tools/kvm/include/kvm/virtio-pci-dev.h
+ create mode 100644 tools/kvm/include/kvm/virtio-pci.h
+ create mode 100644 tools/kvm/include/kvm/virtio-rng.h
+ create mode 100644 tools/kvm/include/kvm/virtio-scsi.h
+ create mode 100644 tools/kvm/include/kvm/virtio.h
+ create mode 100644 tools/kvm/include/kvm/vnc.h
+ create mode 100644 tools/kvm/include/linux/bitops.h
+ create mode 100644 tools/kvm/include/linux/byteorder.h
+ create mode 100644 tools/kvm/include/linux/compiler.h
+ create mode 100644 tools/kvm/include/linux/kernel.h
+ create mode 100644 tools/kvm/include/linux/module.h
+ create mode 100644 tools/kvm/include/linux/prefetch.h
+ create mode 100644 tools/kvm/include/linux/stddef.h
+ create mode 100644 tools/kvm/include/linux/types.h
+ create mode 100644 tools/kvm/ioeventfd.c
+ create mode 100644 tools/kvm/ioport.c
+ create mode 100644 tools/kvm/kvm-cmd.c
+ create mode 100644 tools/kvm/kvm-cpu.c
+ create mode 100644 tools/kvm/kvm-ipc.c
+ create mode 100644 tools/kvm/kvm.c
+ create mode 100644 tools/kvm/main.c
+ create mode 100644 tools/kvm/mmio.c
+ create mode 100644 tools/kvm/net/uip/arp.c
+ create mode 100644 tools/kvm/net/uip/buf.c
+ create mode 100644 tools/kvm/net/uip/core.c
+ create mode 100644 tools/kvm/net/uip/csum.c
+ create mode 100644 tools/kvm/net/uip/dhcp.c
+ create mode 100644 tools/kvm/net/uip/icmp.c
+ create mode 100644 tools/kvm/net/uip/ipv4.c
+ create mode 100644 tools/kvm/net/uip/tcp.c
+ create mode 100644 tools/kvm/net/uip/udp.c
+ create mode 100644 tools/kvm/pci.c
+ create mode 100644 tools/kvm/powerpc/boot.c
+ create mode 100644 tools/kvm/powerpc/cpu_info.c
+ create mode 100644 tools/kvm/powerpc/cpu_info.h
+ create mode 100644 tools/kvm/powerpc/include/kvm/barrier.h
+ create mode 100644 tools/kvm/powerpc/include/kvm/kvm-arch.h
+ create mode 100644 tools/kvm/powerpc/include/kvm/kvm-cpu-arch.h
+ create mode 100644 tools/kvm/powerpc/ioport.c
+ create mode 100644 tools/kvm/powerpc/irq.c
+ create mode 100644 tools/kvm/powerpc/kvm-cpu.c
+ create mode 100644 tools/kvm/powerpc/kvm.c
+ create mode 100644 tools/kvm/powerpc/spapr.h
+ create mode 100644 tools/kvm/powerpc/spapr_hcall.c
+ create mode 100644 tools/kvm/powerpc/spapr_hvcons.c
+ create mode 100644 tools/kvm/powerpc/spapr_hvcons.h
+ create mode 100644 tools/kvm/powerpc/spapr_pci.c
+ create mode 100644 tools/kvm/powerpc/spapr_pci.h
+ create mode 100644 tools/kvm/powerpc/spapr_rtas.c
+ create mode 100644 tools/kvm/powerpc/xics.c
+ create mode 100644 tools/kvm/powerpc/xics.h
+ create mode 100644 tools/kvm/symbol.c
+ create mode 100644 tools/kvm/term.c
+ create mode 100644 tools/kvm/tests/Makefile
+ create mode 100644 tools/kvm/tests/boot/Makefile
+ create mode 100644 tools/kvm/tests/boot/init.c
+ create mode 100644 tools/kvm/tests/kernel/.gitignore
+ create mode 100644 tools/kvm/tests/kernel/Makefile
+ create mode 100644 tools/kvm/tests/kernel/README
+ create mode 100644 tools/kvm/tests/kernel/kernel.S
+ create mode 100644 tools/kvm/tests/pit/.gitignore
+ create mode 100644 tools/kvm/tests/pit/Makefile
+ create mode 100644 tools/kvm/tests/pit/README
+ create mode 100644 tools/kvm/tests/pit/tick.S
+ create mode 100644 tools/kvm/ui/sdl.c
+ create mode 100644 tools/kvm/ui/vnc.c
+ create mode 100755 tools/kvm/util/KVMTOOLS-VERSION-GEN
+ create mode 100755 tools/kvm/util/generate-cmdlist.sh
+ create mode 100755 tools/kvm/util/kvm-ifup-vbr0
+ create mode 100644 tools/kvm/util/parse-options.c
+ create mode 100644 tools/kvm/util/rbtree-interval.c
+ create mode 100644 tools/kvm/util/read-write.c
+ create mode 100755 tools/kvm/util/set_private_br.sh
+ create mode 100644 tools/kvm/util/strbuf.c
+ create mode 100644 tools/kvm/util/threadpool.c
+ create mode 100644 tools/kvm/util/util.c
+ create mode 100644 tools/kvm/virtio/9p-pdu.c
+ create mode 100644 tools/kvm/virtio/9p.c
+ create mode 100644 tools/kvm/virtio/balloon.c
+ create mode 100644 tools/kvm/virtio/blk.c
+ create mode 100644 tools/kvm/virtio/console.c
+ create mode 100644 tools/kvm/virtio/core.c
+ create mode 100644 tools/kvm/virtio/mmio.c
+ create mode 100644 tools/kvm/virtio/net.c
+ create mode 100644 tools/kvm/virtio/pci.c
+ create mode 100644 tools/kvm/virtio/rng.c
+ create mode 100644 tools/kvm/virtio/scsi.c
+ create mode 100644 tools/kvm/x86/bios.c
+ create mode 100644 tools/kvm/x86/bios/.gitignore
+ create mode 100644 tools/kvm/x86/bios/bios-rom.S
+ create mode 100644 tools/kvm/x86/bios/e820.c
+ create mode 100644 tools/kvm/x86/bios/entry.S
+ create mode 100644 tools/kvm/x86/bios/gen-offsets.sh
+ create mode 100644 tools/kvm/x86/bios/int10.c
+ create mode 100644 tools/kvm/x86/bios/int15.c
+ create mode 100644 tools/kvm/x86/bios/local.S
+ create mode 100644 tools/kvm/x86/bios/macro.S
+ create mode 100644 tools/kvm/x86/bios/memcpy.c
+ create mode 100644 tools/kvm/x86/bios/rom.ld.S
+ create mode 100644 tools/kvm/x86/boot.c
+ create mode 100644 tools/kvm/x86/cpuid.c
+ create mode 100644 tools/kvm/x86/include/kvm/assembly.h
+ create mode 100644 tools/kvm/x86/include/kvm/barrier.h
+ create mode 100644 tools/kvm/x86/include/kvm/bios-export.h
+ create mode 100644 tools/kvm/x86/include/kvm/bios.h
+ create mode 100644 tools/kvm/x86/include/kvm/boot-protocol.h
+ create mode 100644 tools/kvm/x86/include/kvm/cpufeature.h
+ create mode 100644 tools/kvm/x86/include/kvm/interrupt.h
+ create mode 100644 tools/kvm/x86/include/kvm/kvm-arch.h
+ create mode 100644 tools/kvm/x86/include/kvm/kvm-cpu-arch.h
+ create mode 100644 tools/kvm/x86/include/kvm/mptable.h
+ create mode 100644 tools/kvm/x86/interrupt.c
+ create mode 100644 tools/kvm/x86/ioport.c
+ create mode 100644 tools/kvm/x86/irq.c
+ create mode 100644 tools/kvm/x86/kvm-cpu.c
+ create mode 100644 tools/kvm/x86/kvm.c
+ create mode 100644 tools/kvm/x86/mptable.c
+ create mode 100644 tools/perf/Documentation/jit-interface.txt
+ create mode 100644 tools/perf/arch/x86/include/perf_regs.h
+ create mode 100644 tools/perf/arch/x86/util/unwind.c
+ create mode 100644 tools/perf/bash_completion
+ create mode 100755 tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/EventClass.py
+ create mode 100644 tools/perf/scripts/python/bin/event_analyzing_sample-record
+ create mode 100644 tools/perf/scripts/python/bin/event_analyzing_sample-report
+ create mode 100644 tools/perf/scripts/python/event_analyzing_sample.py
+ create mode 100644 tools/perf/ui/gtk/helpline.c
+ create mode 100644 tools/perf/ui/hist.c
+ create mode 100644 tools/perf/ui/stdio/hist.c
+ create mode 100644 tools/perf/ui/tui/helpline.c
+ create mode 100644 tools/perf/util/include/linux/magic.h
+ create mode 100644 tools/perf/util/perf_regs.h
+ create mode 100644 tools/perf/util/stat.c
+ create mode 100644 tools/perf/util/stat.h
+ create mode 100644 tools/perf/util/symbol-elf.c
+ create mode 100644 tools/perf/util/symbol-minimal.c
+ create mode 100644 tools/perf/util/unwind.c
+ create mode 100644 tools/perf/util/unwind.h
+ create mode 100644 tools/perf/util/vdso.c
+ create mode 100644 tools/perf/util/vdso.h
+Merging rcu/rcu/next (593d100 Merge remote-tracking branch 'tip/core/rcu' into next.2012.09.25b)
+$ git merge rcu/rcu/next
+Auto-merging lib/Kconfig.debug
+Auto-merging kernel/time/tick-sched.c
+Auto-merging arch/ia64/kernel/process.c
+Auto-merging Documentation/kernel-parameters.txt
+Merge made by the 'recursive' strategy.
+ Documentation/RCU/checklist.txt     |    6 +
+ Documentation/RCU/stallwarn.txt     |   16 +-
+ Documentation/RCU/trace.txt         |   43 +--
+ Documentation/RCU/whatisRCU.txt     |    9 +-
+ Documentation/kernel-parameters.txt |   11 +
+ arch/alpha/kernel/process.c         |    6 +-
+ arch/alpha/kernel/smp.c             |    1 +
+ arch/cris/kernel/process.c          |    3 +
+ arch/frv/kernel/process.c           |    3 +
+ arch/h8300/kernel/process.c         |    3 +
+ arch/ia64/kernel/process.c          |    3 +
+ arch/m32r/kernel/process.c          |    3 +
+ arch/mn10300/kernel/process.c       |    3 +
+ arch/parisc/kernel/process.c        |    3 +
+ arch/score/kernel/process.c         |    4 +-
+ arch/x86/kernel/cpuid.c             |    5 +
+ arch/x86/kernel/msr.c               |    5 +
+ arch/xtensa/kernel/process.c        |    3 +
+ include/linux/interrupt.h           |    2 +
+ include/linux/rcupdate.h            |    6 +-
+ kernel/rcupdate.c                   |    4 +
+ kernel/rcutiny.c                    |   33 +-
+ kernel/rcutiny_plugin.h             |   10 +-
+ kernel/rcutorture.c                 |  159 ++++----
+ kernel/rcutree.c                    |  694 ++++++++++++++++++-----------------
+ kernel/rcutree.h                    |   31 +-
+ kernel/rcutree_plugin.h             |  174 +++++++--
+ kernel/rcutree_trace.c              |   19 +-
+ kernel/time/tick-sched.c            |    3 +-
+ lib/Kconfig.debug                   |   14 +
+ mm/kmemleak.c                       |    6 +-
+ 31 files changed, 751 insertions(+), 534 deletions(-)
+Merging cputime/cputime (c3e0ef9 [S390] fix cputime overflow in uptime_proc_show)
+$ git merge cputime/cputime
+Already up-to-date.
+Merging uprobes/for-next (0326f5a uprobes/core: Handle breakpoint and singlestep exceptions)
+$ git merge uprobes/for-next
+Already up-to-date.
+Merging kmemleak/kmemleak (4878677 kmemleak: do not leak object after tree insertion error)
+$ git merge kmemleak/kmemleak
+Auto-merging mm/kmemleak.c
+Merge made by the 'recursive' strategy.
+ mm/kmemleak.c |    1 +
+ 1 file changed, 1 insertion(+)
+Merging kvm/linux-next (1e08ec4 KVM: optimize apic interrupt delivery)
+$ git merge kvm/linux-next
+Resolved 'arch/s390/include/asm/processor.h' using previous resolution.
+Resolved 'arch/x86/kvm/i8259.c' using previous resolution.
+Auto-merging virt/kvm/kvm_main.c
+Auto-merging arch/x86/kvm/x86.c
+Auto-merging arch/x86/kvm/vmx.c
+Removing arch/x86/kvm/timer.c
+Removing arch/x86/kvm/kvm_timer.h
+Auto-merging arch/x86/kvm/i8259.c
+CONFLICT (content): Merge conflict in arch/x86/kvm/i8259.c
+Auto-merging arch/x86/kernel/setup.c
+Auto-merging arch/x86/kernel/Makefile
+Auto-merging arch/x86/Kconfig
+Auto-merging arch/s390/kvm/priv.c
+Auto-merging arch/s390/kvm/Kconfig
+Auto-merging arch/s390/kernel/dis.c
+Auto-merging arch/s390/include/asm/processor.h
+CONFLICT (content): Merge conflict in arch/s390/include/asm/processor.h
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master c2193bc] Merge remote-tracking branch 'kvm/linux-next'
+$ git diff -M --stat --summary HEAD^..
+ Documentation/virtual/kvm/api.txt        |   22 +-
+ Documentation/virtual/kvm/hypercalls.txt |   66 ++++
+ Documentation/virtual/kvm/msr.txt        |   32 +-
+ Documentation/virtual/kvm/ppc-pv.txt     |   22 ++
+ arch/ia64/kvm/kvm-ia64.c                 |   41 +--
+ arch/powerpc/include/asm/kvm_host.h      |    3 +
+ arch/powerpc/kvm/44x_tlb.c               |    1 -
+ arch/powerpc/kvm/book3s_64_mmu_hv.c      |   51 ++-
+ arch/powerpc/kvm/book3s_hv_rm_mmu.c      |    6 +-
+ arch/powerpc/kvm/book3s_pr.c             |    4 +-
+ arch/powerpc/kvm/e500_tlb.c              |    3 +-
+ arch/powerpc/kvm/powerpc.c               |   14 +-
+ arch/s390/include/asm/processor.h        |    1 +
+ arch/s390/kernel/dis.c                   |   27 ++
+ arch/s390/kvm/Kconfig                    |    1 +
+ arch/s390/kvm/diag.c                     |    4 +
+ arch/s390/kvm/intercept.c                |   11 +
+ arch/s390/kvm/interrupt.c                |   23 ++
+ arch/s390/kvm/kvm-s390.c                 |   17 +-
+ arch/s390/kvm/priv.c                     |    9 +-
+ arch/s390/kvm/sigp.c                     |    2 +
+ arch/s390/kvm/trace-s390.h               |  210 ++++++++++++
+ arch/s390/kvm/trace.h                    |  341 +++++++++++++++++++
+ arch/x86/Kconfig                         |   21 +-
+ arch/x86/include/asm/kvm.h               |    1 +
+ arch/x86/include/asm/kvm_emulate.h       |   48 ++-
+ arch/x86/include/asm/kvm_host.h          |   32 +-
+ arch/x86/include/asm/kvm_para.h          |    6 +-
+ arch/x86/kernel/Makefile                 |    3 +-
+ arch/x86/kernel/kvm.c                    |    3 +-
+ arch/x86/kernel/setup.c                  |    2 +-
+ arch/x86/kvm/Kconfig                     |    2 +
+ arch/x86/kvm/Makefile                    |    2 +-
+ arch/x86/kvm/cpuid.c                     |   14 +-
+ arch/x86/kvm/emulate.c                   |  538 ++++++++++++++++-------------
+ arch/x86/kvm/i8254.c                     |   64 ++--
+ arch/x86/kvm/i8254.h                     |    6 +-
+ arch/x86/kvm/i8259.c                     |   70 ++--
+ arch/x86/kvm/irq.h                       |    2 +-
+ arch/x86/kvm/kvm_timer.h                 |   18 -
+ arch/x86/kvm/lapic.c                     |  484 ++++++++++++++++++--------
+ arch/x86/kvm/lapic.h                     |   61 +++-
+ arch/x86/kvm/mmu.c                       |  240 +++++++++----
+ arch/x86/kvm/mmu.h                       |   25 +-
+ arch/x86/kvm/mmu_audit.c                 |    8 +-
+ arch/x86/kvm/paging_tmpl.h               |  199 +++++------
+ arch/x86/kvm/pmu.c                       |    2 +-
+ arch/x86/kvm/svm.c                       |   59 ++--
+ arch/x86/kvm/timer.c                     |   47 ---
+ arch/x86/kvm/vmx.c                       |  219 ++++++------
+ arch/x86/kvm/x86.c                       |  354 ++++++++++---------
+ arch/x86/kvm/x86.h                       |    1 +
+ include/linux/kvm.h                      |   13 +-
+ include/linux/kvm_host.h                 |  140 ++++++--
+ kernel/jump_label.c                      |    1 +
+ virt/kvm/Kconfig                         |    3 +
+ virt/kvm/async_pf.c                      |   11 +-
+ virt/kvm/ioapic.c                        |   37 +-
+ virt/kvm/iommu.c                         |   16 +-
+ virt/kvm/irq_comm.c                      |   11 +-
+ virt/kvm/kvm_main.c                      |  541 ++++++++++++++++++------------
+ 61 files changed, 2799 insertions(+), 1416 deletions(-)
+ create mode 100644 Documentation/virtual/kvm/hypercalls.txt
+ create mode 100644 arch/s390/kvm/trace-s390.h
+ create mode 100644 arch/s390/kvm/trace.h
+ delete mode 100644 arch/x86/kvm/kvm_timer.h
+ delete mode 100644 arch/x86/kvm/timer.c
+Merging kvm-ppc/kvm-ppc-next (8f1aeaa KVM: PPC: set IN_GUEST_MODE before checking requests)
+$ git merge kvm-ppc/kvm-ppc-next
+Auto-merging arch/powerpc/kvm/trace.h
+Auto-merging arch/powerpc/kvm/book3s_64_mmu_host.c
+Auto-merging arch/powerpc/kvm/book3s_32_mmu_host.c
+Auto-merging arch/powerpc/include/asm/kvm_book3s.h
+Merge made by the 'recursive' strategy.
+ Documentation/virtual/kvm/api.txt           |   16 +-
+ arch/powerpc/include/asm/Kbuild             |    1 +
+ arch/powerpc/include/asm/epapr_hcalls.h     |   36 ++--
+ arch/powerpc/include/asm/fsl_hcalls.h       |   36 ++--
+ arch/powerpc/include/asm/kvm.h              |   12 ++
+ arch/powerpc/include/asm/kvm_book3s.h       |    2 +-
+ arch/powerpc/include/asm/kvm_booke_hv_asm.h |    4 +-
+ arch/powerpc/include/asm/kvm_host.h         |   38 +++-
+ arch/powerpc/include/asm/kvm_para.h         |   21 +-
+ arch/powerpc/include/asm/kvm_ppc.h          |   26 ++-
+ arch/powerpc/include/asm/reg_booke.h        |    7 +
+ arch/powerpc/kernel/epapr_hcalls.S          |   28 +++
+ arch/powerpc/kernel/epapr_paravirt.c        |   11 +-
+ arch/powerpc/kernel/kvm.c                   |    2 +-
+ arch/powerpc/kernel/ppc_ksyms.c             |    5 +
+ arch/powerpc/kvm/44x.c                      |    1 +
+ arch/powerpc/kvm/44x_emulate.c              |  110 ++++++----
+ arch/powerpc/kvm/Kconfig                    |    3 +
+ arch/powerpc/kvm/book3s.c                   |    9 +
+ arch/powerpc/kvm/book3s_32_mmu_host.c       |    1 +
+ arch/powerpc/kvm/book3s_64_mmu_host.c       |    1 +
+ arch/powerpc/kvm/book3s_64_mmu_hv.c         |   65 ++++--
+ arch/powerpc/kvm/book3s_hv.c                |  155 +++++++++-----
+ arch/powerpc/kvm/book3s_hv_builtin.c        |    4 +-
+ arch/powerpc/kvm/book3s_hv_rm_mmu.c         |    4 +-
+ arch/powerpc/kvm/book3s_mmu_hpte.c          |    5 -
+ arch/powerpc/kvm/book3s_pr.c                |  131 +++++++----
+ arch/powerpc/kvm/book3s_rmhandlers.S        |   15 +-
+ arch/powerpc/kvm/booke.c                    |  310 ++++++++++++++++++++++-----
+ arch/powerpc/kvm/booke_emulate.c            |   22 +-
+ arch/powerpc/kvm/e500.h                     |    3 +-
+ arch/powerpc/kvm/e500_tlb.c                 |   73 ++++++-
+ arch/powerpc/kvm/powerpc.c                  |  150 ++++++++++---
+ arch/powerpc/kvm/trace.h                    |  200 ++++++++++++++---
+ arch/powerpc/platforms/Kconfig              |    1 +
+ arch/powerpc/sysdev/fsl_msi.c               |    9 +-
+ arch/powerpc/sysdev/fsl_soc.c               |    2 +
+ drivers/tty/Kconfig                         |    1 +
+ drivers/virt/Kconfig                        |    1 +
+ include/linux/kvm.h                         |   10 +-
+ include/linux/kvm_host.h                    |    1 +
+ 41 files changed, 1182 insertions(+), 350 deletions(-)
+Merging oprofile/for-next (61bccf1 oprofile: Remove 'WQ on CPUx, prefer CPUy' warning)
+$ git merge oprofile/for-next
+Already up-to-date.
+Merging xen/upstream/xen (af3a3ab Merge git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-3.0-fixes)
+$ git merge xen/upstream/xen
+Already up-to-date.
+Merging xen-two/linux-next (526c795 Merge branch 'stable/for-linus-3.7' into linux-next)
+$ git merge xen-two/linux-next
+Auto-merging drivers/xen/xen-pciback/pci_stub.c
+Auto-merging drivers/pci/xen-pcifront.c
+Merge made by the 'recursive' strategy.
+ arch/ia64/include/asm/xen/interface.h      |    7 +-
+ arch/x86/include/asm/xen/interface.h       |    7 +
+ arch/x86/include/asm/xen/swiotlb-xen.h     |    2 +
+ arch/x86/xen/apic.c                        |    3 +-
+ arch/x86/xen/enlighten.c                   |   15 ++-
+ arch/x86/xen/mmu.c                         |  190 ++++++++++++++++++++++------
+ arch/x86/xen/p2m.c                         |   92 +++++++++++++-
+ arch/x86/xen/pci-swiotlb-xen.c             |   52 +++++++-
+ arch/x86/xen/platform-pci-unplug.c         |    1 +
+ arch/x86/xen/setup.c                       |   18 +++
+ arch/x86/xen/vga.c                         |    7 +
+ arch/x86/xen/xen-head.S                    |   56 +++++++-
+ arch/x86/xen/xen-ops.h                     |    3 +-
+ drivers/pci/xen-pcifront.c                 |   15 ++-
+ drivers/tty/hvc/hvc_xen.c                  |    2 +
+ drivers/xen/events.c                       |   18 ++-
+ drivers/xen/gntdev.c                       |    2 +-
+ drivers/xen/grant-table.c                  |   14 +-
+ drivers/xen/privcmd.c                      |  135 +++++++++++++++-----
+ drivers/xen/swiotlb-xen.c                  |  119 ++++++++++-------
+ drivers/xen/sys-hypervisor.c               |   13 +-
+ drivers/xen/tmem.c                         |    1 +
+ drivers/xen/xen-pciback/pci_stub.c         |   89 ++++++++++++-
+ drivers/xen/xenbus/xenbus_comms.c          |    2 +-
+ drivers/xen/xenbus/xenbus_dev_backend.c    |    2 +-
+ drivers/xen/xenbus/xenbus_probe.c          |   56 +++++---
+ drivers/xen/xenbus/xenbus_probe_frontend.c |    1 +
+ drivers/xen/xenbus/xenbus_xs.c             |    3 +-
+ include/linux/swiotlb.h                    |    1 +
+ include/xen/interface/grant_table.h        |   12 +-
+ include/xen/interface/memory.h             |    9 +-
+ include/xen/interface/platform.h           |    7 +-
+ include/xen/interface/version.h            |    3 +
+ include/xen/interface/xen.h                |    8 +-
+ include/xen/privcmd.h                      |   27 +++-
+ include/xen/swiotlb-xen.h                  |   11 +-
+ lib/swiotlb.c                              |   33 +++--
+ 37 files changed, 822 insertions(+), 214 deletions(-)
+Merging xen-pvhvm/linux-next (b056b6a xen: suspend: remove xen_hvm_suspend)
+$ git merge xen-pvhvm/linux-next
+Already up-to-date.
+Merging percpu/for-next (61011677 Merge tag 'dlm-3.5' of git://git.kernel.org/pub/scm/linux/kernel/git/teigland/linux-dlm)
+$ git merge percpu/for-next
+Already up-to-date.
+Merging workqueues/for-next (2b0f620 Merge branch 'for-3.7' into for-next)
+$ git merge workqueues/for-next
+Resolved 'drivers/isdn/mISDN/hwchannel.c' using previous resolution.
+Resolved 'drivers/thermal/thermal_sys.c' using previous resolution.
+Resolved 'drivers/video/omap2/displays/panel-taal.c' using previous resolution.
+Auto-merging sound/soc/soc-core.c
+Auto-merging sound/pci/oxygen/oxygen_lib.c
+Auto-merging net/core/neighbour.c
+Auto-merging net/core/link_watch.c
+Auto-merging net/core/dst.c
+Auto-merging net/9p/trans_fd.c
+Auto-merging mm/slab.c
+Auto-merging fs/xfs/xfs_super.c
+Auto-merging fs/gfs2/super.c
+Auto-merging drivers/video/omap2/dss/dsi.c
+Auto-merging drivers/video/omap2/displays/panel-taal.c
+CONFLICT (content): Merge conflict in drivers/video/omap2/displays/panel-taal.c
+Auto-merging drivers/usb/gadget/u_ether.c
+Auto-merging drivers/tty/serial/kgdboc.c
+Auto-merging drivers/thermal/thermal_sys.c
+CONFLICT (content): Merge conflict in drivers/thermal/thermal_sys.c
+Auto-merging drivers/scsi/qla2xxx/qla_target.c
+Auto-merging drivers/scsi/ipr.c
+Auto-merging drivers/regulator/core.c
+Auto-merging drivers/power/wm97xx_battery.c
+Auto-merging drivers/power/charger-manager.c
+Auto-merging drivers/power/ab8500_fg.c
+Auto-merging drivers/power/ab8500_charger.c
+Auto-merging drivers/power/ab8500_btemp.c
+Auto-merging drivers/platform/x86/thinkpad_acpi.c
+Auto-merging drivers/net/wireless/ipw2x00/ipw2100.c
+Auto-merging drivers/net/virtio_net.c
+Auto-merging drivers/net/ethernet/sun/niu.c
+Auto-merging drivers/net/ethernet/neterion/vxge/vxge-main.c
+Auto-merging drivers/net/ethernet/mellanox/mlx4/sense.c
+Auto-merging drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
+Auto-merging drivers/mtd/mtdoops.c
+Auto-merging drivers/media/usb/tm6000/tm6000-cards.c
+Auto-merging drivers/media/usb/em28xx/em28xx-cards.c
+Auto-merging drivers/media/usb/cx231xx/cx231xx-cards.c
+Auto-merging drivers/media/platform/omap24xxcam.c
+Auto-merging drivers/media/pci/saa7134/saa7134-empress.c
+Auto-merging drivers/media/pci/saa7134/saa7134-core.c
+Auto-merging drivers/media/pci/mantis/mantis_uart.c
+Auto-merging drivers/media/pci/mantis/mantis_evm.c
+Auto-merging drivers/media/pci/cx88/cx88-mpeg.c
+Auto-merging drivers/media/pci/cx23885/cx23885-input.c
+Auto-merging drivers/media/pci/cx18/cx18-driver.c
+Auto-merging drivers/media/pci/bt8xx/bttv-driver.c
+Auto-merging drivers/media/dvb-core/dvb_net.c
+Auto-merging drivers/md/dm-mpath.c
+Auto-merging drivers/leds/leds-lp8788.c
+Auto-merging drivers/isdn/mISDN/hwchannel.c
+CONFLICT (content): Merge conflict in drivers/isdn/mISDN/hwchannel.c
+Auto-merging drivers/infiniband/hw/nes/nes_nic.c
+Auto-merging drivers/infiniband/hw/nes/nes_hw.c
+Auto-merging drivers/hid/hid-wiimote-ext.c
+CONFLICT (modify/delete): drivers/hid/hid-picolcd.c deleted in HEAD and modified in workqueues/for-next. Version workqueues/for-next of drivers/hid/hid-picolcd.c left in tree.
+Auto-merging drivers/gpu/drm/exynos/exynos_drm_g2d.c
+Auto-merging drivers/edac/edac_mc.c
+Auto-merging drivers/cpufreq/cpufreq_ondemand.c
+Auto-merging drivers/cpufreq/cpufreq_conservative.c
+Auto-merging drivers/char/tpm/tpm.c
+Auto-merging drivers/block/floppy.c
+Auto-merging block/genhd.c
+Auto-merging block/blk-core.c
+Automatic merge failed; fix conflicts and then commit the result.
+$ git rm -f drivers/hid/hid-picolcd.c
+drivers/hid/hid-picolcd.c: needs merge
+rm 'drivers/hid/hid-picolcd.c'
+$ git commit -v -a
+[master eb1c81c] Merge remote-tracking branch 'workqueues/for-next'
+$ git diff -M --stat --summary HEAD^..
+ arch/arm/mach-pxa/sharpsl_pm.c                  |    4 +-
+ arch/arm/plat-omap/mailbox.c                    |    2 +-
+ arch/powerpc/platforms/cell/cpufreq_spudemand.c |    2 +-
+ arch/sh/drivers/push-switch.c                   |    2 +-
+ block/blk-core.c                                |    8 +-
+ block/blk-throttle.c                            |   14 +-
+ block/genhd.c                                   |   14 +-
+ drivers/block/floppy.c                          |    5 +-
+ drivers/block/xen-blkfront.c                    |    4 +-
+ drivers/cdrom/gdrom.c                           |    2 +-
+ drivers/char/sonypi.c                           |    2 +-
+ drivers/char/tpm/tpm.c                          |    4 +-
+ drivers/cpufreq/cpufreq_conservative.c          |    2 +-
+ drivers/cpufreq/cpufreq_ondemand.c              |    2 +-
+ drivers/devfreq/devfreq.c                       |    2 +-
+ drivers/edac/edac_mc.c                          |   17 +-
+ drivers/gpu/drm/drm_crtc_helper.c               |    6 +-
+ drivers/gpu/drm/exynos/exynos_drm_g2d.c         |    2 +-
+ drivers/gpu/drm/nouveau/nouveau_gpio.c          |    2 +-
+ drivers/gpu/drm/radeon/radeon_irq_kms.c         |    2 +-
+ drivers/gpu/drm/vmwgfx/vmwgfx_fb.c              |    2 +-
+ drivers/hid/hid-wiimote-ext.c                   |    2 +-
+ drivers/infiniband/core/addr.c                  |    4 +-
+ drivers/infiniband/core/mad.c                   |   16 +-
+ drivers/infiniband/hw/nes/nes_hw.c              |    6 +-
+ drivers/infiniband/hw/nes/nes_nic.c             |    5 +-
+ drivers/input/keyboard/qt2160.c                 |    3 +-
+ drivers/input/mouse/synaptics_i2c.c             |    7 +-
+ drivers/input/touchscreen/wm831x-ts.c           |    2 +-
+ drivers/isdn/mISDN/hwchannel.c                  |    2 +-
+ drivers/leds/leds-lm3533.c                      |    6 +-
+ drivers/leds/leds-lp8788.c                      |    2 +-
+ drivers/leds/leds-wm8350.c                      |    2 +-
+ drivers/macintosh/ams/ams-core.c                |    2 +-
+ drivers/md/dm-mpath.c                           |    2 +-
+ drivers/md/dm-raid1.c                           |    2 +-
+ drivers/md/dm-stripe.c                          |    2 +-
+ drivers/media/dvb-core/dvb_net.c                |    4 +-
+ drivers/media/pci/bt8xx/bttv-driver.c           |    2 +-
+ drivers/media/pci/cx18/cx18-driver.c            |    2 +-
+ drivers/media/pci/cx23885/cx23885-input.c       |    6 +-
+ drivers/media/pci/cx88/cx88-mpeg.c              |    2 +-
+ drivers/media/pci/mantis/mantis_evm.c           |    2 +-
+ drivers/media/pci/mantis/mantis_uart.c          |    2 +-
+ drivers/media/pci/saa7134/saa7134-core.c        |    2 +-
+ drivers/media/pci/saa7134/saa7134-empress.c     |    2 +-
+ drivers/media/platform/omap24xxcam.c            |    6 +-
+ drivers/media/usb/cx231xx/cx231xx-cards.c       |    2 +-
+ drivers/media/usb/em28xx/em28xx-cards.c         |    2 +-
+ drivers/media/usb/tm6000/tm6000-cards.c         |    2 +-
+ drivers/mfd/menelaus.c                          |    4 +-
+ drivers/misc/ioc4.c                             |    2 +-
+ drivers/mmc/core/host.c                         |    4 +-
+ drivers/mtd/mtdoops.c                           |    4 +-
+ drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c |    2 +-
+ drivers/net/ethernet/mellanox/mlx4/sense.c      |    2 +-
+ drivers/net/ethernet/neterion/vxge/vxge-main.c  |    2 +-
+ drivers/net/ethernet/sun/cassini.c              |    2 +-
+ drivers/net/ethernet/sun/niu.c                  |    2 +-
+ drivers/net/virtio_net.c                        |   12 +-
+ drivers/net/wireless/hostap/hostap_ap.c         |    4 +-
+ drivers/net/wireless/hostap/hostap_hw.c         |   10 +-
+ drivers/net/wireless/ipw2x00/ipw2100.c          |    8 +-
+ drivers/net/wireless/zd1211rw/zd_usb.c          |    3 +-
+ drivers/platform/x86/thinkpad_acpi.c            |   20 +-
+ drivers/power/ab8500_btemp.c                    |    2 +-
+ drivers/power/ab8500_charger.c                  |    8 +-
+ drivers/power/ab8500_fg.c                       |    8 +-
+ drivers/power/abx500_chargalg.c                 |    4 +-
+ drivers/power/charger-manager.c                 |    9 +-
+ drivers/power/collie_battery.c                  |    2 +-
+ drivers/power/ds2760_battery.c                  |    9 +-
+ drivers/power/jz4740-battery.c                  |    6 +-
+ drivers/power/max17040_battery.c                |    2 +-
+ drivers/power/tosa_battery.c                    |    2 +-
+ drivers/power/wm97xx_battery.c                  |    2 +-
+ drivers/power/z2_battery.c                      |    2 +-
+ drivers/regulator/core.c                        |    2 +-
+ drivers/scsi/arcmsr/arcmsr_hba.c                |    4 +-
+ drivers/scsi/ipr.c                              |    2 +-
+ drivers/scsi/pmcraid.c                          |    2 +-
+ drivers/scsi/qla2xxx/qla_target.c               |    2 +-
+ drivers/thermal/thermal_sys.c                   |   15 +-
+ drivers/tty/hvc/hvsi.c                          |    2 +-
+ drivers/tty/ipwireless/hardware.c               |    2 +-
+ drivers/tty/ipwireless/network.c                |    4 +-
+ drivers/tty/serial/kgdboc.c                     |    2 +-
+ drivers/tty/serial/omap-serial.c                |    2 +-
+ drivers/tty/tty_ldisc.c                         |    6 +-
+ drivers/usb/atm/speedtch.c                      |    2 +-
+ drivers/usb/atm/ueagle-atm.c                    |    2 +-
+ drivers/usb/gadget/u_ether.c                    |    2 +-
+ drivers/usb/host/ohci-hcd.c                     |    2 +-
+ drivers/usb/otg/isp1301_omap.c                  |    2 +-
+ drivers/video/omap2/displays/panel-taal.c       |    4 +-
+ drivers/video/omap2/dss/dsi.c                   |    6 +-
+ fs/affs/super.c                                 |    2 +-
+ fs/afs/callback.c                               |    4 +-
+ fs/afs/server.c                                 |   10 +-
+ fs/afs/vlocation.c                              |   14 +-
+ fs/gfs2/lock_dlm.c                              |    2 +-
+ fs/gfs2/super.c                                 |    2 +-
+ fs/hfs/inode.c                                  |    2 +-
+ fs/ncpfs/inode.c                                |    6 +-
+ fs/nfs/nfs4renewd.c                             |    3 +-
+ fs/ocfs2/cluster/quorum.c                       |    2 +-
+ fs/xfs/xfs_super.c                              |    2 +-
+ fs/xfs/xfs_sync.c                               |    2 +-
+ include/linux/workqueue.h                       |  220 ++--
+ kernel/srcu.c                                   |    4 +-
+ kernel/workqueue.c                              | 1335 ++++++++++++-----------
+ mm/slab.c                                       |    2 +-
+ mm/vmstat.c                                     |    2 +-
+ net/9p/trans_fd.c                               |    2 +-
+ net/core/dst.c                                  |    4 +-
+ net/core/link_watch.c                           |   21 +-
+ net/core/neighbour.c                            |    2 +-
+ net/dsa/dsa.c                                   |    2 +-
+ net/ipv4/inetpeer.c                             |    2 +-
+ net/rfkill/input.c                              |    3 +-
+ net/sunrpc/cache.c                              |    2 +-
+ security/keys/gc.c                              |    8 +-
+ security/keys/key.c                             |    2 +-
+ sound/i2c/other/ak4113.c                        |    2 +-
+ sound/i2c/other/ak4114.c                        |    2 +-
+ sound/pci/oxygen/oxygen_lib.c                   |    8 +-
+ sound/soc/codecs/wm8350.c                       |    2 +-
+ sound/soc/codecs/wm8753.c                       |    2 +-
+ sound/soc/soc-core.c                            |    6 +-
+ virt/kvm/eventfd.c                              |    2 +-
+ 130 files changed, 1041 insertions(+), 1048 deletions(-)
+Merging drivers-x86/linux-next (455f38c eeepc-laptop: fix device reference count leakage in eeepc_rfkill_hotplug())
+$ git merge drivers-x86/linux-next
+Auto-merging drivers/platform/x86/asus-wmi.c
+Merge made by the 'recursive' strategy.
+ drivers/platform/x86/asus-wmi.c |   76 +++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 76 insertions(+)
+Merging hwpoison/hwpoison (46e387b Merge branch 'hwpoison-hugepages' into hwpoison)
+$ git merge hwpoison/hwpoison
+Already up-to-date.
+Merging sysctl/master (4e474a0 sysctl: protect poll() in entries that may go away)
+$ git merge sysctl/master
+Already up-to-date.
+Merging regmap/for-next (613dac3 Merge remote-tracking branches 'regmap/topic/cache' and 'regmap/topic/irq' into regmap-next)
+$ git merge regmap/for-next
+Merge made by the 'recursive' strategy.
+ drivers/base/regmap/regmap-irq.c |   92 +++++++++++++++++++++++++++++++-------
+ drivers/base/regmap/regmap.c     |   13 ++----
+ drivers/mfd/wm8994-irq.c         |    1 +
+ include/linux/regmap.h           |    3 ++
+ 4 files changed, 83 insertions(+), 26 deletions(-)
+Merging hsi/for-next (43139a6 HSI: hsi_char: Update ioctl-number.txt)
+$ git merge hsi/for-next
+Already up-to-date.
+Merging leds/for-next (2f73c39 leds: add output driver configuration for pca9633 led driver)
+$ git merge leds/for-next
+Removing include/linux/platform_data/leds-lm3556.h
+Auto-merging drivers/leds/leds-wm8350.c
+Removing drivers/leds/leds-lm3556.c
+Merge made by the 'recursive' strategy.
+ Documentation/leds/leds-lp5523.txt         |   21 +-
+ drivers/leds/Kconfig                       |   26 +-
+ drivers/leds/Makefile                      |    3 +-
+ drivers/leds/led-class.c                   |   15 +
+ drivers/leds/led-core.c                    |   16 +-
+ drivers/leds/led-triggers.c                |   17 +-
+ drivers/leds/leds-clevo-mail.c             |   10 +-
+ drivers/leds/leds-gpio.c                   |   19 +-
+ drivers/leds/leds-lm3530.c                 |   16 +-
+ drivers/leds/leds-lm3556.c                 |  512 -------------------------
+ drivers/leds/leds-lm355x.c                 |  572 ++++++++++++++++++++++++++++
+ drivers/leds/leds-lm3642.c                 |  462 ++++++++++++++++++++++
+ drivers/leds/leds-lp5523.c                 |   75 ++--
+ drivers/leds/leds-pca9633.c                |   19 +-
+ drivers/leds/leds-wm8350.c                 |   29 +-
+ drivers/leds/leds.h                        |    2 +
+ include/linux/leds-lp5523.h                |    1 +
+ include/linux/leds.h                       |    4 +
+ include/linux/platform_data/leds-lm3556.h  |   50 ---
+ include/linux/platform_data/leds-lm355x.h  |   66 ++++
+ include/linux/platform_data/leds-lm3642.h  |   38 ++
+ include/linux/platform_data/leds-pca9633.h |   35 ++
+ 22 files changed, 1350 insertions(+), 658 deletions(-)
+ delete mode 100644 drivers/leds/leds-lm3556.c
+ create mode 100644 drivers/leds/leds-lm355x.c
+ create mode 100644 drivers/leds/leds-lm3642.c
+ delete mode 100644 include/linux/platform_data/leds-lm3556.h
+ create mode 100644 include/linux/platform_data/leds-lm355x.h
+ create mode 100644 include/linux/platform_data/leds-lm3642.h
+ create mode 100644 include/linux/platform_data/leds-pca9633.h
+Merging driver-core/driver-core-next (666f355 device and dynamic_debug: Use dev_vprintk_emit and dev_printk_emit)
+$ git merge driver-core/driver-core-next
+Auto-merging net/core/dev.c
+Auto-merging init/Kconfig
+Auto-merging include/linux/pm.h
+Auto-merging include/linux/netdevice.h
+Auto-merging include/linux/device.h
+Auto-merging drivers/extcon/extcon-class.c
+Auto-merging drivers/extcon/extcon-arizona.c
+Auto-merging drivers/base/power/main.c
+Auto-merging drivers/base/platform.c
+Auto-merging arch/xtensa/Kconfig
+Auto-merging arch/tile/Kconfig
+Auto-merging MAINTAINERS
+Merge made by the 'recursive' strategy.
+ Documentation/ABI/testing/sysfs-class-extcon       |   22 +-
+ Documentation/filesystems/debugfs.txt              |    4 +-
+ Documentation/kobject.txt                          |    6 +-
+ Documentation/zh_CN/arm/Booting                    |  175 ++++
+ Documentation/zh_CN/basic_profiling.txt            |   71 ++
+ Documentation/zh_CN/filesystems/sysfs.txt          |  372 +++++++
+ Documentation/zh_CN/gpio.txt                       |  662 +++++++++++++
+ Documentation/zh_CN/video4linux/v4l2-framework.txt |  983 +++++++++++++++++++
+ MAINTAINERS                                        |    4 +-
+ arch/tile/Kconfig                                  |    8 -
+ arch/xtensa/Kconfig                                |   18 -
+ drivers/base/core.c                                |  105 +-
+ drivers/base/devres.c                              |   42 +
+ drivers/base/firmware_class.c                      |  838 ++++++++++++++--
+ drivers/base/platform.c                            |   41 +-
+ drivers/base/power/main.c                          |   22 +
+ drivers/extcon/Kconfig                             |    8 +-
+ drivers/extcon/Makefile                            |    5 +-
+ drivers/extcon/extcon-adc-jack.c                   |  198 ++++
+ drivers/extcon/extcon-arizona.c                    |   78 +-
+ drivers/extcon/{extcon_class.c => extcon-class.c}  |   12 +-
+ drivers/extcon/{extcon_gpio.c => extcon-gpio.c}    |    0
+ drivers/extcon/extcon-max77693.c                   |    8 +-
+ drivers/firmware/efivars.c                         |   17 +-
+ drivers/hv/hv.c                                    |   34 +-
+ drivers/hv/hv_kvp.c                                |  253 ++++-
+ drivers/hv/hv_util.c                               |    4 +-
+ drivers/hv/hyperv_vmbus.h                          |   47 +-
+ drivers/hv/vmbus_drv.c                             |   42 +-
+ drivers/memory/Makefile                            |    3 +
+ drivers/memory/emif.c                              |  182 +++-
+ drivers/memory/of_memory.c                         |  153 +++
+ drivers/memory/of_memory.h                         |   36 +
+ drivers/vme/bridges/vme_ca91cx42.c                 |   20 +-
+ drivers/vme/bridges/vme_tsi148.c                   |   10 +-
+ fs/debugfs/inode.c                                 |    8 +-
+ fs/sysfs/symlink.c                                 |    2 +-
+ include/linux/device.h                             |   83 +-
+ include/linux/extcon.h                             |   18 +-
+ include/linux/extcon/extcon-adc-jack.h             |   71 ++
+ include/linux/firmware.h                           |   15 +
+ include/linux/hyperv.h                             |  101 +-
+ include/linux/netdevice.h                          |    3 -
+ include/linux/platform_device.h                    |    4 +
+ include/linux/pm.h                                 |    5 +
+ init/Kconfig                                       |    8 +-
+ lib/dynamic_debug.c                                |   56 +-
+ net/core/dev.c                                     |   20 +-
+ tools/hv/hv_get_dhcp_info.sh                       |   28 +
+ tools/hv/hv_get_dns_info.sh                        |   13 +
+ tools/hv/hv_kvp_daemon.c                           | 1036 +++++++++++++++++---
+ tools/hv/hv_set_ifconfig.sh                        |   68 ++
+ 52 files changed, 5505 insertions(+), 517 deletions(-)
+ create mode 100644 Documentation/zh_CN/arm/Booting
+ create mode 100644 Documentation/zh_CN/basic_profiling.txt
+ create mode 100644 Documentation/zh_CN/filesystems/sysfs.txt
+ create mode 100644 Documentation/zh_CN/gpio.txt
+ create mode 100644 Documentation/zh_CN/video4linux/v4l2-framework.txt
+ create mode 100644 drivers/extcon/extcon-adc-jack.c
+ rename drivers/extcon/{extcon_class.c => extcon-class.c} (98%)
+ rename drivers/extcon/{extcon_gpio.c => extcon-gpio.c} (100%)
+ create mode 100644 drivers/memory/of_memory.c
+ create mode 100644 drivers/memory/of_memory.h
+ create mode 100644 include/linux/extcon/extcon-adc-jack.h
+ create mode 100755 tools/hv/hv_get_dhcp_info.sh
+ create mode 100755 tools/hv/hv_get_dns_info.sh
+ create mode 100755 tools/hv/hv_set_ifconfig.sh
+$ git am -3 ../patches/0001-extcon-adc_jack-update-for-INIT_DELAYED_WORK_DEFERRA.patch
+Applying: extcon: adc_jack: update for INIT_DELAYED_WORK_DEFERRABLE name change
+$ git reset HEAD^
+Unstaged changes after reset:
+M	drivers/extcon/extcon-adc-jack.c
+$ git add .
+$ git commit -v -a --amend
+[master 0504338] Merge remote-tracking branch 'driver-core/driver-core-next'
+Merging tty/tty-next (4dac211 staging: dgrp: using vmalloc needs to include vmalloc.h)
+$ git merge tty/tty-next
+Resolved 'drivers/tty/serial/omap-serial.c' using previous resolution.
+Removing include/linux/stallion.h
+Removing include/linux/serial167.h
+Removing include/linux/sc26198.h
+Removing include/linux/istallion.h
+Removing include/linux/generic_serial.h
+Removing include/linux/comstats.h
+Removing include/linux/cdk.h
+Removing include/linux/cd1400.h
+Auto-merging include/linux/Kbuild
+Auto-merging fs/compat_ioctl.c
+Removing firmware/intelliport2.bin.ihex
+Auto-merging firmware/Makefile
+Auto-merging drivers/tty/tty_ldisc.c
+Auto-merging drivers/tty/tty_io.c
+Auto-merging drivers/tty/serial/omap-serial.c
+CONFLICT (content): Merge conflict in drivers/tty/serial/omap-serial.c
+Removing drivers/tty/serial/max3107.h
+Removing drivers/tty/serial/max3107.c
+Auto-merging drivers/tty/serial/8250/8250_pci.c
+Auto-merging drivers/tty/ipwireless/network.c
+Auto-merging drivers/tty/hvc/hvsi.c
+Auto-merging drivers/tty/hvc/hvc_console.c
+Auto-merging drivers/tty/Kconfig
+Auto-merging arch/xtensa/platforms/iss/console.c
+Removing Documentation/serial/computone.txt
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master df1037d] Merge remote-tracking branch 'tty/tty-next'
+$ git diff -M --stat --summary HEAD^..
+ Documentation/ABI/testing/sysfs-tty                |    9 +
+ .../bindings/tty/serial/nxp-lpc32xx-hsuart.txt     |   14 +
+ .../devicetree/bindings/tty/serial/of-serial.txt   |    2 +
+ Documentation/serial/00-INDEX                      |    2 -
+ Documentation/serial/computone.txt                 |  520 ---
+ arch/alpha/kernel/srmcons.c                        |    1 +
+ arch/arm/mach-omap2/serial.c                       |   18 +-
+ arch/arm/mach-ux500/board-mop500.c                 |   21 -
+ arch/arm/plat-omap/include/plat/omap-serial.h      |   50 +-
+ arch/ia64/hp/sim/simserial.c                       |    3 +-
+ arch/m68k/emu/nfcon.c                              |    4 +
+ arch/mips/cavium-octeon/serial.c                   |   30 +-
+ arch/mips/sni/a20r.c                               |   32 +
+ arch/parisc/kernel/pdc_cons.c                      |    1 +
+ arch/um/drivers/line.c                             |    3 +-
+ arch/xtensa/platforms/iss/console.c                |    1 +
+ drivers/bluetooth/hci_ath.c                        |    2 +-
+ drivers/char/mwave/mwavedd.c                       |   16 +-
+ drivers/char/pcmcia/synclink_cs.c                  |  131 +-
+ drivers/char/ttyprintk.c                           |   33 +-
+ drivers/isdn/capi/capi.c                           |    3 +-
+ drivers/isdn/gigaset/interface.c                   |    7 +-
+ drivers/isdn/i4l/isdn_tty.c                        |   41 +-
+ drivers/misc/ibmasm/uart.c                         |   16 +-
+ drivers/misc/pti.c                                 |  128 +-
+ drivers/mmc/card/sdio_uart.c                       |   24 +-
+ drivers/net/ethernet/sgi/ioc3-eth.c                |   22 +-
+ drivers/net/irda/irtty-sir.c                       |   10 +-
+ drivers/net/usb/hso.c                              |   19 +-
+ drivers/parport/parport_gsc.c                      |    1 +
+ drivers/parport/parport_serial.c                   |   11 +-
+ drivers/s390/char/con3215.c                        |   28 +-
+ drivers/s390/char/sclp_tty.c                       |    1 +
+ drivers/s390/char/sclp_vt220.c                     |    1 +
+ drivers/s390/char/tty3270.c                        |   34 +-
+ drivers/staging/Kconfig                            |    2 +
+ drivers/staging/Makefile                           |    1 +
+ drivers/staging/dgrp/Kconfig                       |    9 +
+ drivers/staging/dgrp/Makefile                      |   12 +
+ drivers/staging/dgrp/README                        |    2 +
+ drivers/staging/dgrp/TODO                          |   13 +
+ drivers/staging/dgrp/dgrp_common.c                 |  200 ++
+ drivers/staging/dgrp/dgrp_common.h                 |  208 ++
+ drivers/staging/dgrp/dgrp_dpa_ops.c                |  556 +++
+ drivers/staging/dgrp/dgrp_driver.c                 |  110 +
+ drivers/staging/dgrp/dgrp_mon_ops.c                |  346 ++
+ drivers/staging/dgrp/dgrp_net_ops.c                | 3737 ++++++++++++++++++++
+ drivers/staging/dgrp/dgrp_ports_ops.c              |  170 +
+ drivers/staging/dgrp/dgrp_specproc.c               |  822 +++++
+ drivers/staging/dgrp/dgrp_sysfs.c                  |  555 +++
+ drivers/staging/dgrp/dgrp_tty.c                    | 3331 +++++++++++++++++
+ drivers/staging/dgrp/digirp.h                      |  129 +
+ drivers/staging/dgrp/drp.h                         |  693 ++++
+ drivers/staging/ipack/devices/ipoctal.c            |   14 +-
+ drivers/staging/serqt_usb2/serqt_usb2.c            |   18 +-
+ drivers/staging/speakup/serialio.h                 |    3 +-
+ drivers/tty/Kconfig                                |    9 +-
+ drivers/tty/amiserial.c                            |   45 +-
+ drivers/tty/bfin_jtag_comm.c                       |    1 +
+ drivers/tty/cyclades.c                             |  102 +-
+ drivers/tty/ehv_bytechan.c                         |    9 +-
+ drivers/tty/hvc/Kconfig                            |    2 +-
+ drivers/tty/hvc/hvc_console.c                      |   33 +-
+ drivers/tty/hvc/hvcs.c                             |   82 +-
+ drivers/tty/hvc/hvsi.c                             |    2 +
+ drivers/tty/hvc/hvsi_lib.c                         |    2 +-
+ drivers/tty/ipwireless/network.c                   |    7 +-
+ drivers/tty/ipwireless/tty.c                       |    2 +-
+ drivers/tty/isicom.c                               |   13 +-
+ drivers/tty/moxa.c                                 |   39 +-
+ drivers/tty/mxser.c                                |   63 +-
+ drivers/tty/n_gsm.c                                |  144 +-
+ drivers/tty/n_r3964.c                              |   10 +-
+ drivers/tty/n_tty.c                                |   29 +-
+ drivers/tty/nozomi.c                               |    4 +-
+ drivers/tty/pty.c                                  |  234 +-
+ drivers/tty/rocket.c                               |   22 +-
+ drivers/tty/serial/68328serial.c                   |   23 +-
+ drivers/tty/serial/8250/8250.c                     |  109 +-
+ drivers/tty/serial/8250/8250.h                     |   34 +-
+ drivers/tty/serial/8250/8250_acorn.c               |   22 +-
+ drivers/tty/serial/8250/8250_dw.c                  |   38 +-
+ drivers/tty/serial/8250/8250_gsc.c                 |   26 +-
+ drivers/tty/serial/8250/8250_hp300.c               |   26 +-
+ drivers/tty/serial/8250/8250_pci.c                 |  205 +-
+ drivers/tty/serial/8250/8250_pnp.c                 |   28 +-
+ drivers/tty/serial/8250/serial_cs.c                |   30 +-
+ drivers/tty/serial/Kconfig                         |   54 +-
+ drivers/tty/serial/Makefile                        |    4 +-
+ drivers/tty/serial/altera_uart.c                   |    6 +-
+ drivers/tty/serial/amba-pl010.c                    |   15 +-
+ drivers/tty/serial/amba-pl011.c                    |   89 +-
+ drivers/tty/serial/bfin_uart.c                     |    2 +-
+ drivers/tty/serial/crisv10.c                       |   45 +-
+ drivers/tty/serial/ifx6x60.c                       |    4 +-
+ drivers/tty/serial/imx.c                           |   13 +-
+ drivers/tty/serial/ioc3_serial.c                   |    3 +-
+ drivers/tty/serial/ioc4_serial.c                   |    5 +-
+ drivers/tty/serial/jsm/jsm_tty.c                   |    8 +-
+ drivers/tty/serial/lpc32xx_hs.c                    |  823 +++++
+ drivers/tty/serial/m32r_sio.c                      |   36 +-
+ drivers/tty/serial/max3100.c                       |   26 +-
+ drivers/tty/serial/max3107.c                       | 1215 -------
+ drivers/tty/serial/max3107.h                       |  441 ---
+ drivers/tty/serial/max310x.c                       | 1260 +++++++
+ drivers/tty/serial/mpc52xx_uart.c                  |    8 +-
+ drivers/tty/serial/msm_serial.c                    |    2 +-
+ drivers/tty/serial/msm_smd_tty.c                   |    8 +-
+ drivers/tty/serial/mxs-auart.c                     |    8 +-
+ drivers/tty/serial/of_serial.c                     |   13 +-
+ drivers/tty/serial/omap-serial.c                   |  881 ++---
+ drivers/tty/serial/pch_uart.c                      |    4 +
+ drivers/tty/serial/pxa.c                           |   14 +
+ drivers/tty/serial/samsung.c                       |   48 +-
+ drivers/tty/serial/sc26xx.c                        |    4 +
+ drivers/tty/serial/sccnxp.c                        |  985 ++++++
+ drivers/tty/serial/serial_core.c                   |  234 +-
+ drivers/tty/serial/sirfsoc_uart.c                  |    8 +-
+ drivers/tty/serial/sunsu.c                         |    8 +-
+ drivers/tty/synclink.c                             |   86 +-
+ drivers/tty/synclink_gt.c                          |   37 +-
+ drivers/tty/synclinkmp.c                           |   58 +-
+ drivers/tty/tty_io.c                               |  375 +-
+ drivers/tty/tty_ioctl.c                            |  100 +-
+ drivers/tty/tty_ldisc.c                            |   78 +-
+ drivers/tty/tty_mutex.c                            |   71 +-
+ drivers/tty/tty_port.c                             |   94 +-
+ drivers/tty/vt/keyboard.c                          |   50 +-
+ drivers/tty/vt/vt.c                                |  141 +-
+ drivers/usb/class/cdc-acm.c                        |    5 +-
+ drivers/usb/gadget/u_serial.c                      |    3 +-
+ drivers/usb/serial/ark3116.c                       |    4 +-
+ drivers/usb/serial/belkin_sa.c                     |    2 +-
+ drivers/usb/serial/console.c                       |    4 +-
+ drivers/usb/serial/cp210x.c                        |    8 +-
+ drivers/usb/serial/cypress_m8.c                    |   40 +-
+ drivers/usb/serial/digi_acceleport.c               |   14 +-
+ drivers/usb/serial/empeg.c                         |    2 +-
+ drivers/usb/serial/f81232.c                        |    3 +-
+ drivers/usb/serial/ftdi_sio.c                      |    2 +-
+ drivers/usb/serial/io_edgeport.c                   |   12 +-
+ drivers/usb/serial/io_ti.c                         |   12 +-
+ drivers/usb/serial/ir-usb.c                        |    2 +-
+ drivers/usb/serial/iuu_phoenix.c                   |   28 +-
+ drivers/usb/serial/keyspan.c                       |    6 +-
+ drivers/usb/serial/keyspan_pda.c                   |    4 +-
+ drivers/usb/serial/kl5kusb105.c                    |   18 +-
+ drivers/usb/serial/kobil_sct.c                     |   14 +-
+ drivers/usb/serial/mct_u232.c                      |    4 +-
+ drivers/usb/serial/metro-usb.c                     |    6 -
+ drivers/usb/serial/mos7720.c                       |   14 +-
+ drivers/usb/serial/mos7840.c                       |   12 +-
+ drivers/usb/serial/oti6858.c                       |   10 +-
+ drivers/usb/serial/pl2303.c                        |    6 +-
+ drivers/usb/serial/quatech2.c                      |    4 +-
+ drivers/usb/serial/sierra.c                        |    2 +-
+ drivers/usb/serial/spcp8x5.c                       |   12 +-
+ drivers/usb/serial/ssu100.c                        |    4 +-
+ drivers/usb/serial/ti_usb_3410_5052.c              |   10 +-
+ drivers/usb/serial/usb-serial.c                    |    7 +-
+ drivers/usb/serial/usb_wwan.c                      |    2 +-
+ drivers/usb/serial/whiteheat.c                     |    2 +-
+ firmware/Makefile                                  |    1 -
+ firmware/intelliport2.bin.ihex                     | 2147 -----------
+ fs/compat_ioctl.c                                  |    6 +
+ include/linux/Kbuild                               |    4 +-
+ include/linux/amba/serial.h                        |    1 -
+ include/linux/cd1400.h                             |  292 --
+ include/linux/cdk.h                                |  486 ---
+ include/linux/comstats.h                           |  119 -
+ include/linux/generic_serial.h                     |   35 -
+ include/linux/istallion.h                          |  123 -
+ include/linux/kbd_kern.h                           |   13 -
+ include/linux/platform_data/max310x.h              |   67 +
+ include/linux/platform_data/sccnxp.h               |   93 +
+ include/linux/sc26198.h                            |  533 ---
+ include/linux/serial.h                             |   81 +-
+ include/linux/serial167.h                          |  157 -
+ include/linux/serial_8250.h                        |   33 +-
+ include/linux/serial_core.h                        |    4 +-
+ include/linux/serial_reg.h                         |    4 +
+ include/linux/stallion.h                           |  147 -
+ include/linux/tty.h                                |   92 +-
+ include/linux/tty_driver.h                         |   47 +-
+ include/linux/tty_flags.h                          |   78 +
+ include/net/irda/ircomm_tty.h                      |   17 +-
+ net/bluetooth/rfcomm/tty.c                         |   10 +-
+ net/irda/ircomm/ircomm_param.c                     |    5 -
+ net/irda/ircomm/ircomm_tty.c                       |  320 +-
+ net/irda/ircomm/ircomm_tty_attach.c                |   40 +-
+ net/irda/ircomm/ircomm_tty_ioctl.c                 |   33 +-
+ 191 files changed, 17306 insertions(+), 8889 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/tty/serial/nxp-lpc32xx-hsuart.txt
+ delete mode 100644 Documentation/serial/computone.txt
+ create mode 100644 drivers/staging/dgrp/Kconfig
+ create mode 100644 drivers/staging/dgrp/Makefile
+ create mode 100644 drivers/staging/dgrp/README
+ create mode 100644 drivers/staging/dgrp/TODO
+ create mode 100644 drivers/staging/dgrp/dgrp_common.c
+ create mode 100644 drivers/staging/dgrp/dgrp_common.h
+ create mode 100644 drivers/staging/dgrp/dgrp_dpa_ops.c
+ create mode 100644 drivers/staging/dgrp/dgrp_driver.c
+ create mode 100644 drivers/staging/dgrp/dgrp_mon_ops.c
+ create mode 100644 drivers/staging/dgrp/dgrp_net_ops.c
+ create mode 100644 drivers/staging/dgrp/dgrp_ports_ops.c
+ create mode 100644 drivers/staging/dgrp/dgrp_specproc.c
+ create mode 100644 drivers/staging/dgrp/dgrp_sysfs.c
+ create mode 100644 drivers/staging/dgrp/dgrp_tty.c
+ create mode 100644 drivers/staging/dgrp/digirp.h
+ create mode 100644 drivers/staging/dgrp/drp.h
+ create mode 100644 drivers/tty/serial/lpc32xx_hs.c
+ delete mode 100644 drivers/tty/serial/max3107.c
+ delete mode 100644 drivers/tty/serial/max3107.h
+ create mode 100644 drivers/tty/serial/max310x.c
+ create mode 100644 drivers/tty/serial/sccnxp.c
+ delete mode 100644 firmware/intelliport2.bin.ihex
+ delete mode 100644 include/linux/cd1400.h
+ delete mode 100644 include/linux/cdk.h
+ delete mode 100644 include/linux/comstats.h
+ delete mode 100644 include/linux/generic_serial.h
+ delete mode 100644 include/linux/istallion.h
+ create mode 100644 include/linux/platform_data/max310x.h
+ create mode 100644 include/linux/platform_data/sccnxp.h
+ delete mode 100644 include/linux/sc26198.h
+ delete mode 100644 include/linux/serial167.h
+ delete mode 100644 include/linux/stallion.h
+ create mode 100644 include/linux/tty_flags.h
+Merging usb/usb-next (655db79 Merge tag 'for-usb-next-2012-09-25' of git://git.kernel.org/pub/scm/linux/kernel/git/sarah/xhci into usb-next)
+$ git merge usb/usb-next
+Resolved 'drivers/usb/core/usb-acpi.c' using previous resolution.
+Resolved 'drivers/usb/serial/digi_acceleport.c' using previous resolution.
+Resolved 'drivers/usb/serial/io_edgeport.c' using previous resolution.
+Resolved 'drivers/usb/serial/io_ti.c' using previous resolution.
+Resolved 'drivers/usb/serial/kl5kusb105.c' using previous resolution.
+Resolved 'drivers/usb/serial/mos7720.c' using previous resolution.
+Resolved 'drivers/usb/serial/mos7840.c' using previous resolution.
+Auto-merging include/linux/usb/tegra_usb_phy.h
+Removing drivers/usb/storage/libusual.c
+Auto-merging drivers/usb/serial/whiteheat.c
+Auto-merging drivers/usb/serial/usb_wwan.c
+Auto-merging drivers/usb/serial/usb-serial.c
+Auto-merging drivers/usb/serial/ti_usb_3410_5052.c
+Auto-merging drivers/usb/serial/ssu100.c
+Auto-merging drivers/usb/serial/spcp8x5.c
+Auto-merging drivers/usb/serial/sierra.c
+Auto-merging drivers/usb/serial/quatech2.c
+Auto-merging drivers/usb/serial/pl2303.c
+Auto-merging drivers/usb/serial/oti6858.c
+Auto-merging drivers/usb/serial/mos7840.c
+CONFLICT (content): Merge conflict in drivers/usb/serial/mos7840.c
+Auto-merging drivers/usb/serial/mos7720.c
+CONFLICT (content): Merge conflict in drivers/usb/serial/mos7720.c
+Auto-merging drivers/usb/serial/metro-usb.c
+Auto-merging drivers/usb/serial/mct_u232.c
+Auto-merging drivers/usb/serial/kobil_sct.c
+Auto-merging drivers/usb/serial/kl5kusb105.c
+CONFLICT (content): Merge conflict in drivers/usb/serial/kl5kusb105.c
+Auto-merging drivers/usb/serial/keyspan_pda.c
+Auto-merging drivers/usb/serial/keyspan.c
+Auto-merging drivers/usb/serial/iuu_phoenix.c
+Auto-merging drivers/usb/serial/ir-usb.c
+Auto-merging drivers/usb/serial/io_ti.c
+CONFLICT (content): Merge conflict in drivers/usb/serial/io_ti.c
+Auto-merging drivers/usb/serial/io_edgeport.c
+CONFLICT (content): Merge conflict in drivers/usb/serial/io_edgeport.c
+Auto-merging drivers/usb/serial/ftdi_sio.c
+Auto-merging drivers/usb/serial/f81232.c
+Auto-merging drivers/usb/serial/empeg.c
+Auto-merging drivers/usb/serial/digi_acceleport.c
+CONFLICT (content): Merge conflict in drivers/usb/serial/digi_acceleport.c
+Auto-merging drivers/usb/serial/cypress_m8.c
+Auto-merging drivers/usb/serial/cp210x.c
+Auto-merging drivers/usb/serial/console.c
+Auto-merging drivers/usb/serial/belkin_sa.c
+Auto-merging drivers/usb/serial/ark3116.c
+Auto-merging drivers/usb/phy/tegra_usb_phy.c
+Auto-merging drivers/usb/gadget/u_ether.c
+Auto-merging drivers/usb/gadget/tcm_usb_gadget.c
+Auto-merging drivers/usb/core/usb-acpi.c
+CONFLICT (content): Merge conflict in drivers/usb/core/usb-acpi.c
+Auto-merging drivers/usb/class/cdc-acm.c
+Auto-merging drivers/usb/atm/ueagle-atm.c
+Auto-merging drivers/staging/serqt_usb2/serqt_usb2.c
+Removing drivers/block/ub.c
+Auto-merging drivers/block/Kconfig
+Auto-merging arch/arm/mach-tegra/devices.c
+Auto-merging arch/arm/mach-omap2/twl-common.c
+Auto-merging arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+Auto-merging arch/arm/mach-omap2/board-omap3evm.c
+Auto-merging Documentation/feature-removal-schedule.txt
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master f693504] Merge remote-tracking branch 'usb/usb-next'
+$ git diff -M --stat --summary HEAD^..
+ Documentation/ABI/testing/sysfs-bus-usb            |    7 +
+ .../devicetree/bindings/usb/am33xx-usb.txt         |   14 +
+ .../devicetree/bindings/usb/ci13xxx-imx.txt        |    5 +
+ Documentation/devicetree/bindings/usb/omap-usb.txt |   33 +
+ .../devicetree/bindings/usb/platform-uhci.txt      |   12 +
+ Documentation/devicetree/bindings/usb/pxa-usb.txt  |   31 +
+ .../devicetree/bindings/usb/twlxxxx-usb.txt        |   40 +
+ Documentation/devicetree/bindings/usb/usb-phy.txt  |   17 +
+ .../devicetree/bindings/usb/usbmisc-imx.txt        |   14 +
+ .../devicetree/bindings/usb/vt8500-ehci.txt        |   12 +
+ Documentation/feature-removal-schedule.txt         |   11 -
+ Documentation/usb/persist.txt                      |    3 +
+ arch/arm/mach-omap2/board-omap3evm.c               |    1 +
+ arch/arm/mach-omap2/omap_hwmod_44xx_data.c         |    6 +
+ arch/arm/mach-omap2/omap_phy_internal.c            |  138 -
+ arch/arm/mach-omap2/twl-common.c                   |    5 -
+ arch/arm/mach-omap2/usb-musb.c                     |    3 -
+ arch/arm/mach-tegra/Makefile                       |    1 -
+ arch/arm/mach-tegra/devices.c                      |    2 +-
+ arch/arm/mach-tegra/devices.h                      |    2 +-
+ arch/arm/mach-vt8500/bv07.c                        |    1 +
+ arch/arm/mach-vt8500/devices-vt8500.c              |    5 +
+ arch/arm/mach-vt8500/devices-wm8505.c              |    4 +
+ arch/arm/mach-vt8500/devices.c                     |   11 +
+ arch/arm/mach-vt8500/devices.h                     |    1 +
+ arch/arm/mach-vt8500/wm8505_7in.c                  |    1 +
+ drivers/block/Kconfig                              |   12 -
+ drivers/block/Makefile                             |    1 -
+ drivers/block/ub.c                                 | 2474 ---------------
+ drivers/staging/ccg/Kconfig                        |    5 +
+ drivers/staging/ccg/Makefile                       |    2 -
+ drivers/staging/ccg/ccg.c                          |   29 +-
+ drivers/staging/ccg/composite.c                    | 1688 +++++++++++
+ drivers/staging/ccg/composite.h                    |  395 +++
+ drivers/staging/ccg/config.c                       |  158 +
+ drivers/staging/ccg/epautoconf.c                   |  393 +++
+ drivers/staging/ccg/f_acm.c                        |  814 +++++
+ drivers/staging/ccg/f_fs.c                         | 2455 +++++++++++++++
+ drivers/staging/ccg/f_mass_storage.c               | 3135 ++++++++++++++++++++
+ drivers/staging/ccg/f_rndis.c                      |  918 ++++++
+ drivers/staging/ccg/gadget_chips.h                 |  150 +
+ drivers/staging/ccg/ndis.h                         |   47 +
+ drivers/staging/ccg/rndis.c                        | 1175 ++++++++
+ drivers/staging/ccg/rndis.h                        |  222 ++
+ drivers/staging/ccg/storage_common.c               |  893 ++++++
+ drivers/staging/ccg/u_ether.c                      |  986 ++++++
+ drivers/staging/ccg/u_ether.h                      |  154 +
+ drivers/staging/ccg/u_serial.c                     | 1341 +++++++++
+ drivers/staging/ccg/u_serial.h                     |   65 +
+ drivers/staging/ccg/usbstring.c                    |   71 +
+ drivers/staging/keucr/usb.c                        |    2 +-
+ drivers/staging/serqt_usb2/serqt_usb2.c            |  154 +-
+ drivers/staging/usbip/usbip_common.c               |    3 +-
+ drivers/usb/Kconfig                                |    1 +
+ drivers/usb/atm/ueagle-atm.c                       |   79 +-
+ drivers/usb/atm/usbatm.c                           |   46 +-
+ drivers/usb/chipidea/Kconfig                       |    1 -
+ drivers/usb/chipidea/Makefile                      |    4 +-
+ drivers/usb/chipidea/ci.h                          |    1 +
+ drivers/usb/chipidea/ci13xxx_imx.c                 |   71 +
+ drivers/usb/chipidea/ci13xxx_imx.h                 |   28 +
+ drivers/usb/chipidea/core.c                        |   24 +-
+ drivers/usb/chipidea/udc.c                         |   39 +-
+ drivers/usb/chipidea/usbmisc_imx6q.c               |  162 +
+ drivers/usb/class/cdc-acm.c                        |    1 -
+ drivers/usb/core/Kconfig                           |    2 +-
+ drivers/usb/core/config.c                          |    2 +
+ drivers/usb/core/devices.c                         |    7 +-
+ drivers/usb/core/devio.c                           |   35 +
+ drivers/usb/core/driver.c                          |   11 +-
+ drivers/usb/core/endpoint.c                        |   10 +-
+ drivers/usb/core/hcd.c                             |   22 +-
+ drivers/usb/core/hub.c                             |  214 +-
+ drivers/usb/core/message.c                         |    2 -
+ drivers/usb/core/quirks.c                          |    2 +-
+ drivers/usb/core/sysfs.c                           |   12 +-
+ drivers/usb/core/usb-acpi.c                        |  206 +-
+ drivers/usb/core/usb.h                             |   13 +
+ drivers/usb/dwc3/Kconfig                           |    2 -
+ drivers/usb/dwc3/core.c                            |   18 +-
+ drivers/usb/dwc3/core.h                            |    7 +-
+ drivers/usb/dwc3/dwc3-exynos.c                     |   66 +
+ drivers/usb/dwc3/dwc3-omap.c                       |   66 +
+ drivers/usb/dwc3/dwc3-pci.c                        |   67 +
+ drivers/usb/dwc3/ep0.c                             |  217 +-
+ drivers/usb/dwc3/gadget.c                          |  101 +-
+ drivers/usb/early/ehci-dbgp.c                      |   17 +-
+ drivers/usb/gadget/Kconfig                         |   78 +-
+ drivers/usb/gadget/Makefile                        |    4 +
+ drivers/usb/gadget/acm_ms.c                        |   55 +-
+ drivers/usb/gadget/amd5536udc.c                    |    6 +-
+ drivers/usb/gadget/at91_udc.c                      |    5 +-
+ drivers/usb/gadget/audio.c                         |   62 +-
+ drivers/usb/gadget/bcm63xx_udc.c                   | 2464 +++++++++++++++
+ drivers/usb/gadget/cdc2.c                          |   56 +-
+ drivers/usb/gadget/composite.c                     |  290 +-
+ drivers/usb/gadget/config.c                        |    6 +-
+ drivers/usb/gadget/dbgp.c                          |   11 +-
+ drivers/usb/gadget/dummy_hcd.c                     |    2 +
+ drivers/usb/gadget/epautoconf.c                    |   33 +-
+ drivers/usb/gadget/ether.c                         |   61 +-
+ drivers/usb/gadget/f_ecm.c                         |    5 +-
+ drivers/usb/gadget/f_hid.c                         |    2 +-
+ drivers/usb/gadget/f_mass_storage.c                |   16 +-
+ drivers/usb/gadget/f_midi.c                        |    1 -
+ drivers/usb/gadget/f_ncm.c                         |    5 +-
+ drivers/usb/gadget/f_sourcesink.c                  |    2 +-
+ drivers/usb/gadget/f_subset.c                      |    5 +-
+ drivers/usb/gadget/f_uac2.c                        |    2 +-
+ drivers/usb/gadget/file_storage.c                  |   38 +-
+ drivers/usb/gadget/fsl_udc_core.c                  |    6 +-
+ drivers/usb/gadget/fusb300_udc.c                   |    4 +-
+ drivers/usb/gadget/g_ffs.c                         |   26 +-
+ drivers/usb/gadget/gadget_chips.h                  |   96 +-
+ drivers/usb/gadget/gmidi.c                         |   61 +-
+ drivers/usb/gadget/goku_udc.c                      |    6 +-
+ drivers/usb/gadget/hid.c                           |   52 +-
+ drivers/usb/gadget/inode.c                         |   29 +-
+ drivers/usb/gadget/lpc32xx_udc.c                   |  129 +-
+ drivers/usb/gadget/m66592-udc.c                    |    4 +-
+ drivers/usb/gadget/mass_storage.c                  |   39 +-
+ drivers/usb/gadget/multi.c                         |   42 +-
+ drivers/usb/gadget/mv_udc_core.c                   |   91 +-
+ drivers/usb/gadget/ncm.c                           |   62 +-
+ drivers/usb/gadget/nokia.c                         |   58 +-
+ drivers/usb/gadget/omap_udc.c                      |    6 +-
+ drivers/usb/gadget/pch_udc.c                       |    6 +-
+ drivers/usb/gadget/printer.c                       |  173 +-
+ drivers/usb/gadget/pxa25x_udc.c                    |    7 +-
+ drivers/usb/gadget/pxa25x_udc.h                    |    2 +-
+ drivers/usb/gadget/pxa27x_udc.c                    |    6 +-
+ drivers/usb/gadget/rndis.c                         |   22 +-
+ drivers/usb/gadget/s3c-hsotg.c                     |    8 +-
+ drivers/usb/gadget/s3c-hsudc.c                     |   51 +-
+ drivers/usb/gadget/s3c2410_udc.c                   |  148 +-
+ drivers/usb/gadget/serial.c                        |   72 +-
+ drivers/usb/gadget/tcm_usb_gadget.c                |   49 +-
+ drivers/usb/gadget/tcm_usb_gadget.h                |   11 +-
+ drivers/usb/gadget/u_ether.c                       |    8 +-
+ drivers/usb/gadget/udc-core.c                      |   13 +-
+ drivers/usb/gadget/usbstring.c                     |    3 +-
+ drivers/usb/gadget/webcam.c                        |   42 +-
+ drivers/usb/gadget/zero.c                          |   73 +-
+ drivers/usb/host/Kconfig                           |   40 +-
+ drivers/usb/host/ehci-atmel.c                      |   30 +-
+ drivers/usb/host/ehci-au1xxx.c                     |   20 +-
+ drivers/usb/host/ehci-cns3xxx.c                    |   16 +-
+ drivers/usb/host/ehci-dbg.c                        |    6 +-
+ drivers/usb/host/ehci-fsl.c                        |   57 +-
+ drivers/usb/host/ehci-fsl.h                        |    1 +
+ drivers/usb/host/ehci-grlib.c                      |   18 +-
+ drivers/usb/host/ehci-hcd.c                        |    4 +-
+ drivers/usb/host/ehci-hub.c                        |    4 +-
+ drivers/usb/host/ehci-ixp4xx.c                     |   19 +-
+ drivers/usb/host/ehci-ls1x.c                       |   20 +-
+ drivers/usb/host/ehci-msm.c                        |   13 +-
+ drivers/usb/host/ehci-mv.c                         |   51 +-
+ drivers/usb/host/ehci-mxc.c                        |   45 +-
+ drivers/usb/host/ehci-platform.c                   |   50 +-
+ drivers/usb/host/ehci-ppc-of.c                     |   28 +-
+ drivers/usb/host/ehci-s5p.c                        |    7 +-
+ drivers/usb/host/ehci-sead3.c                      |   15 +-
+ drivers/usb/host/ehci-sh.c                         |   35 +-
+ drivers/usb/host/ehci-tegra.c                      |   57 +-
+ drivers/usb/host/ehci-timer.c                      |    6 +-
+ drivers/usb/host/ehci-vt8500.c                     |   24 +-
+ drivers/usb/host/ehci-xilinx-of.c                  |   20 +-
+ drivers/usb/host/fhci-sched.c                      |    3 +-
+ drivers/usb/host/fsl-mph-dr-of.c                   |    2 +
+ drivers/usb/host/ohci-at91.c                       |    3 +-
+ drivers/usb/host/ohci-nxp.c                        |    2 +-
+ drivers/usb/host/ohci-platform.c                   |   46 +-
+ drivers/usb/host/ohci-pxa27x.c                     |   68 +
+ drivers/usb/host/ohci-xls.c                        |    2 +-
+ drivers/usb/host/r8a66597-hcd.c                    |    5 +-
+ drivers/usb/host/sl811-hcd.c                       |    2 +-
+ drivers/usb/host/uhci-hcd.c                        |    5 +
+ drivers/usb/host/uhci-platform.c                   |  157 +
+ drivers/usb/host/whci/hcd.c                        |    8 +-
+ drivers/usb/host/whci/qset.c                       |   11 +-
+ drivers/usb/host/xhci-hub.c                        |   20 +-
+ drivers/usb/host/xhci-mem.c                        |    7 +
+ drivers/usb/host/xhci-pci.c                        |    1 +
+ drivers/usb/host/xhci-ring.c                       |  290 +-
+ drivers/usb/host/xhci.c                            |   43 +-
+ drivers/usb/host/xhci.h                            |   20 +
+ drivers/usb/misc/legousbtower.c                    |    3 -
+ drivers/usb/misc/rio500.c                          |    2 +-
+ drivers/usb/musb/Kconfig                           |    3 +-
+ drivers/usb/musb/am35x.c                           |   67 +-
+ drivers/usb/musb/blackfin.c                        |   64 +-
+ drivers/usb/musb/cppi_dma.c                        |    2 +-
+ drivers/usb/musb/da8xx.c                           |   59 +-
+ drivers/usb/musb/davinci.c                         |   67 +-
+ drivers/usb/musb/musb_core.c                       |  331 +--
+ drivers/usb/musb/musb_core.h                       |   17 +-
+ drivers/usb/musb/musb_debugfs.c                    |    8 +-
+ drivers/usb/musb/musb_dma.h                        |    2 +-
+ drivers/usb/musb/musb_dsps.c                       |  194 +-
+ drivers/usb/musb/musb_gadget.c                     |  172 +-
+ drivers/usb/musb/musb_host.c                       |  264 +-
+ drivers/usb/musb/musb_host.h                       |    3 +
+ drivers/usb/musb/musb_virthub.c                    |   13 +-
+ drivers/usb/musb/musbhsdma.c                       |    2 +-
+ drivers/usb/musb/omap2430.c                        |  156 +-
+ drivers/usb/musb/omap2430.h                        |    9 +
+ drivers/usb/musb/tusb6010.c                        |   57 +-
+ drivers/usb/musb/tusb6010_omap.c                   |    2 +-
+ drivers/usb/musb/ux500.c                           |   33 +-
+ drivers/usb/musb/ux500_dma.c                       |    2 +-
+ drivers/usb/otg/Kconfig                            |    2 +-
+ drivers/usb/otg/fsl_otg.c                          |   34 +-
+ drivers/usb/otg/mxs-phy.c                          |   38 +-
+ drivers/usb/otg/nop-usb-xceiv.c                    |    8 +-
+ drivers/usb/otg/otg.c                              |    2 +-
+ drivers/usb/otg/twl4030-usb.c                      |   26 +-
+ drivers/usb/otg/twl6030-usb.c                      |  157 +-
+ drivers/usb/phy/Kconfig                            |   17 +
+ drivers/usb/phy/Makefile                           |    3 +
+ drivers/usb/phy/isp1301.c                          |    6 -
+ drivers/usb/phy/mv_u3d_phy.c                       |  345 +++
+ drivers/usb/phy/mv_u3d_phy.h                       |  105 +
+ drivers/usb/phy/omap-usb2.c                        |  271 ++
+ .../usb_phy.c => drivers/usb/phy/tegra_usb_phy.c   |  152 +-
+ drivers/usb/renesas_usbhs/common.c                 |   15 +-
+ drivers/usb/renesas_usbhs/mod.c                    |   25 +-
+ drivers/usb/serial/Kconfig                         |    8 +
+ drivers/usb/serial/Makefile                        |    1 +
+ drivers/usb/serial/aircable.c                      |    5 -
+ drivers/usb/serial/ark3116.c                       |    7 +-
+ drivers/usb/serial/belkin_sa.c                     |    8 +-
+ drivers/usb/serial/ch341.c                         |   49 +-
+ drivers/usb/serial/console.c                       |   23 +-
+ drivers/usb/serial/cp210x.c                        |  141 +-
+ drivers/usb/serial/cyberjack.c                     |   77 +-
+ drivers/usb/serial/cypress_m8.c                    |  157 +-
+ drivers/usb/serial/digi_acceleport.c               |   50 +-
+ drivers/usb/serial/empeg.c                         |    5 -
+ drivers/usb/serial/ezusb.c                         |  141 +-
+ drivers/usb/serial/f81232.c                        |    8 +-
+ drivers/usb/serial/ftdi_sio.c                      |  138 +-
+ drivers/usb/serial/ftdi_sio_ids.h                  |    5 +
+ drivers/usb/serial/funsoft.c                       |    5 -
+ drivers/usb/serial/garmin_gps.c                    |  129 +-
+ drivers/usb/serial/generic.c                       |   11 +-
+ drivers/usb/serial/io_edgeport.c                   |  616 ++--
+ drivers/usb/serial/io_ti.c                         |  408 ++-
+ drivers/usb/serial/ipaq.c                          |    4 -
+ drivers/usb/serial/ipw.c                           |   66 +-
+ drivers/usb/serial/ir-usb.c                        |   16 +-
+ drivers/usb/serial/iuu_phoenix.c                   |  134 +-
+ drivers/usb/serial/keyspan.c                       |  338 +--
+ drivers/usb/serial/keyspan.h                       |   17 +-
+ drivers/usb/serial/keyspan_pda.c                   |   73 +-
+ drivers/usb/serial/kl5kusb105.c                    |   41 +-
+ drivers/usb/serial/kobil_sct.c                     |   98 +-
+ drivers/usb/serial/mct_u232.c                      |  104 +-
+ drivers/usb/serial/metro-usb.c                     |    7 -
+ drivers/usb/serial/mos7720.c                       |  231 +-
+ drivers/usb/serial/mos7840.c                       |  478 ++-
+ drivers/usb/serial/navman.c                        |    8 +-
+ drivers/usb/serial/omninet.c                       |   43 +-
+ drivers/usb/serial/opticon.c                       |   30 +-
+ drivers/usb/serial/option.c                        |   23 +-
+ drivers/usb/serial/oti6858.c                       |   77 +-
+ drivers/usb/serial/pl2303.c                        |    8 +-
+ drivers/usb/serial/qcaux.c                         |   10 +-
+ drivers/usb/serial/qcserial.c                      |    5 -
+ drivers/usb/serial/quatech2.c                      |    7 +-
+ drivers/usb/serial/safe_serial.c                   |   12 +-
+ drivers/usb/serial/sierra.c                        |   11 +-
+ drivers/usb/serial/spcp8x5.c                       |    5 -
+ drivers/usb/serial/ssu100.c                        |   37 +-
+ drivers/usb/serial/symbolserial.c                  |    8 +-
+ drivers/usb/serial/ti_usb_3410_5052.c              |  150 +-
+ drivers/usb/serial/usb-serial.c                    |  176 +-
+ drivers/usb/serial/usb_wwan.c                      |   56 +-
+ drivers/usb/serial/visor.c                         |   13 +-
+ drivers/usb/serial/whiteheat.c                     |  135 +-
+ drivers/usb/serial/zte_ev.c                        |  307 ++
+ drivers/usb/storage/Kconfig                        |   14 -
+ drivers/usb/storage/Makefile                       |    9 +-
+ drivers/usb/storage/alauda.c                       |    2 +-
+ drivers/usb/storage/cypress_atacb.c                |    2 +-
+ drivers/usb/storage/datafab.c                      |    2 +-
+ drivers/usb/storage/ene_ub6250.c                   |   30 +-
+ drivers/usb/storage/freecom.c                      |    2 +-
+ drivers/usb/storage/isd200.c                       |    5 +-
+ drivers/usb/storage/jumpshot.c                     |    2 +-
+ drivers/usb/storage/karma.c                        |    2 +-
+ drivers/usb/storage/libusual.c                     |  243 --
+ drivers/usb/storage/onetouch.c                     |    2 +-
+ drivers/usb/storage/realtek_cr.c                   |    2 +-
+ drivers/usb/storage/sddr09.c                       |    2 +-
+ drivers/usb/storage/sddr55.c                       |    2 +-
+ drivers/usb/storage/shuttle_usbat.c                |    2 +-
+ drivers/usb/storage/sierra_ms.c                    |    3 +-
+ drivers/usb/storage/transport.c                    |    2 +-
+ drivers/usb/storage/uas.c                          |   89 +-
+ drivers/usb/storage/unusual_devs.h                 |   36 +-
+ drivers/usb/storage/usb.c                          |   17 +-
+ drivers/usb/storage/usual-tables.c                 |   18 +-
+ drivers/usb/wusbcore/Kconfig                       |    3 +-
+ drivers/usb/wusbcore/security.c                    |    7 +-
+ drivers/usb/wusbcore/wa-hc.c                       |    4 +-
+ drivers/xen/Makefile                               |    2 +-
+ drivers/xen/dbgp.c                                 |   48 +
+ include/linux/bcd.h                                |   17 +-
+ include/linux/fsl_devices.h                        |    2 +
+ include/linux/usb.h                                |   32 +-
+ include/linux/usb/ch11.h                           |    4 +-
+ include/linux/usb/composite.h                      |   97 +-
+ include/linux/usb/ehci_def.h                       |   35 +-
+ include/linux/usb/ehci_pdriver.h                   |    8 +
+ include/linux/usb/ezusb.h                          |   16 +
+ include/linux/usb/gadget.h                         |   33 +-
+ include/linux/usb/hcd.h                            |    4 +-
+ include/linux/usb/nop-usb-xceiv.h                  |   24 +
+ include/linux/usb/ohci_pdriver.h                   |    8 +
+ include/linux/usb/omap_usb.h                       |   46 +
+ include/linux/usb/otg.h                            |  236 +-
+ include/linux/usb/phy.h                            |  233 ++
+ include/linux/usb/phy_companion.h                  |   34 +
+ include/linux/usb/quirks.h                         |    4 +-
+ include/linux/usb/serial.h                         |   32 +-
+ .../usb_phy.h => include/linux/usb/tegra_usb_phy.h |   16 +-
+ include/linux/usb_usual.h                          |   24 -
+ include/linux/usbdevice_fs.h                       |   14 +
+ include/xen/interface/physdev.h                    |   16 +
+ lib/bcd.c                                          |    8 +-
+ tools/usb/testusb.c                                |   25 +-
+ 331 files changed, 25551 insertions(+), 9000 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/usb/am33xx-usb.txt
+ create mode 100644 Documentation/devicetree/bindings/usb/omap-usb.txt
+ create mode 100644 Documentation/devicetree/bindings/usb/platform-uhci.txt
+ create mode 100644 Documentation/devicetree/bindings/usb/pxa-usb.txt
+ create mode 100644 Documentation/devicetree/bindings/usb/twlxxxx-usb.txt
+ create mode 100644 Documentation/devicetree/bindings/usb/usb-phy.txt
+ create mode 100644 Documentation/devicetree/bindings/usb/usbmisc-imx.txt
+ create mode 100644 Documentation/devicetree/bindings/usb/vt8500-ehci.txt
+ delete mode 100644 drivers/block/ub.c
+ create mode 100644 drivers/staging/ccg/composite.c
+ create mode 100644 drivers/staging/ccg/composite.h
+ create mode 100644 drivers/staging/ccg/config.c
+ create mode 100644 drivers/staging/ccg/epautoconf.c
+ create mode 100644 drivers/staging/ccg/f_acm.c
+ create mode 100644 drivers/staging/ccg/f_fs.c
+ create mode 100644 drivers/staging/ccg/f_mass_storage.c
+ create mode 100644 drivers/staging/ccg/f_rndis.c
+ create mode 100644 drivers/staging/ccg/gadget_chips.h
+ create mode 100644 drivers/staging/ccg/ndis.h
+ create mode 100644 drivers/staging/ccg/rndis.c
+ create mode 100644 drivers/staging/ccg/rndis.h
+ create mode 100644 drivers/staging/ccg/storage_common.c
+ create mode 100644 drivers/staging/ccg/u_ether.c
+ create mode 100644 drivers/staging/ccg/u_ether.h
+ create mode 100644 drivers/staging/ccg/u_serial.c
+ create mode 100644 drivers/staging/ccg/u_serial.h
+ create mode 100644 drivers/staging/ccg/usbstring.c
+ create mode 100644 drivers/usb/chipidea/ci13xxx_imx.h
+ create mode 100644 drivers/usb/chipidea/usbmisc_imx6q.c
+ create mode 100644 drivers/usb/gadget/bcm63xx_udc.c
+ create mode 100644 drivers/usb/host/uhci-platform.c
+ create mode 100644 drivers/usb/phy/mv_u3d_phy.c
+ create mode 100644 drivers/usb/phy/mv_u3d_phy.h
+ create mode 100644 drivers/usb/phy/omap-usb2.c
+ rename arch/arm/mach-tegra/usb_phy.c => drivers/usb/phy/tegra_usb_phy.c (94%)
+ create mode 100644 drivers/usb/serial/zte_ev.c
+ delete mode 100644 drivers/usb/storage/libusual.c
+ create mode 100644 drivers/xen/dbgp.c
+ create mode 100644 include/linux/usb/ezusb.h
+ create mode 100644 include/linux/usb/nop-usb-xceiv.h
+ create mode 100644 include/linux/usb/omap_usb.h
+ create mode 100644 include/linux/usb/phy.h
+ create mode 100644 include/linux/usb/phy_companion.h
+ rename arch/arm/mach-tegra/include/mach/usb_phy.h => include/linux/usb/tegra_usb_phy.h (86%)
+$ git am -3 ../patches/0001-usb-acpi-Comply-with-the-ACPI-API-change-after-usb-t.patch
+Applying: usb-acpi: Comply with the ACPI API change after usb tree merge
+$ git reset HEAD^
+Unstaged changes after reset:
+M	drivers/usb/core/usb-acpi.c
+$ git add .
+$ git commit -v -a --amend
+[master d2ec640] Merge remote-tracking branch 'usb/usb-next'
+Merging staging/staging-next (9970eea staging: winbond: Coding Style correction and removal of unused macro)
+$ git merge staging/staging-next
+Resolved 'drivers/staging/Kconfig' using previous resolution.
+Resolved 'drivers/staging/Makefile' using previous resolution.
+Resolved 'drivers/staging/android/binder.c' using previous resolution.
+Resolved 'drivers/staging/ipack/devices/ipoctal.c' using previous resolution.
+Resolved 'drivers/staging/omap-thermal/omap-thermal-common.c' using previous resolution.
+Resolved 'drivers/staging/serqt_usb2/serqt_usb2.c' using previous resolution.
+Removing drivers/staging/zsmalloc/zsmalloc_int.h
+Removing drivers/staging/usbip/userspace/doc/usbip_bind_driver.8
+Auto-merging drivers/staging/usbip/usbip_common.c
+Auto-merging drivers/staging/serqt_usb2/serqt_usb2.c
+CONFLICT (content): Merge conflict in drivers/staging/serqt_usb2/serqt_usb2.c
+Removing drivers/staging/rtl8712/usb_vendor_req.h
+Removing drivers/staging/ramster/xvmalloc_int.h
+Removing drivers/staging/ramster/xvmalloc.h
+Removing drivers/staging/ramster/xvmalloc.c
+Auto-merging drivers/staging/ramster/ramster/tcp.c
+Auto-merging drivers/staging/ramster/ramster/r2net.c
+Auto-merging drivers/staging/ramster/ramster/nodemanager.c
+Auto-merging drivers/staging/ramster/ramster/heartbeat.c
+Removing drivers/staging/ramster/cluster/Makefile
+Removing drivers/staging/ramster/TODO
+Auto-merging drivers/staging/omapdrm/omap_gem.c
+Auto-merging drivers/staging/omap-thermal/omap-thermal-common.c
+CONFLICT (content): Merge conflict in drivers/staging/omap-thermal/omap-thermal-common.c
+Auto-merging drivers/staging/ipack/devices/ipoctal.c
+CONFLICT (content): Merge conflict in drivers/staging/ipack/devices/ipoctal.c
+Removing drivers/staging/iio/adc/ad7476_ring.c
+Removing drivers/staging/iio/adc/ad7476.h
+Auto-merging drivers/staging/et131x/et131x.c
+Removing drivers/staging/csr/csr_formatted_io.h
+Removing drivers/staging/csr/csr_formatted_io.c
+Removing drivers/staging/comedi/drivers/me4000.h
+Removing drivers/staging/comedi/drivers/icp_multi.h
+Removing drivers/staging/comedi/drivers/cb_pcidio.c
+Removing drivers/staging/comedi/drivers/adl_pci7432.c
+Removing drivers/staging/comedi/drivers/adl_pci7296.c
+Removing drivers/staging/comedi/drivers/adl_pci7230.c
+Removing drivers/staging/comedi/drivers/addi_apci_all.c
+Removing drivers/staging/comedi/drivers/addi-data/amcc_s5933_58.h
+Removing drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.h
+Removing drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c
+Auto-merging drivers/staging/ccg/ccg.c
+Auto-merging drivers/staging/ccg/Kconfig
+Auto-merging drivers/staging/android/binder.c
+CONFLICT (content): Merge conflict in drivers/staging/android/binder.c
+Auto-merging drivers/staging/Makefile
+CONFLICT (content): Merge conflict in drivers/staging/Makefile
+Auto-merging drivers/staging/Kconfig
+CONFLICT (content): Merge conflict in drivers/staging/Kconfig
+Removing drivers/iio/dac/ad5446.h
+Auto-merging drivers/iio/adc/ad7476.c
+Auto-merging drivers/hid/hid-ids.h
+Auto-merging drivers/hid/hid-core.c
+Auto-merging drivers/hid/Makefile
+Auto-merging drivers/hid/Kconfig
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master e3015ac] Merge remote-tracking branch 'staging/staging-next'
+$ git diff -M --stat --summary HEAD^..
+ .../bindings/staging/iio/adc/mxs-lradc.txt         |   15 +
+ .../bindings/staging/imx-drm/fsl-imx-drm.txt       |   41 +
+ Documentation/hid/hid-sensor.txt                   |  140 +
+ drivers/hid/Kconfig                                |   14 +
+ drivers/hid/Makefile                               |    1 +
+ drivers/hid/hid-core.c                             |    5 +
+ drivers/hid/hid-ids.h                              |    6 +
+ drivers/hid/hid-sensor-hub.c                       |  695 ++
+ drivers/iio/Kconfig                                |    7 +-
+ drivers/iio/Makefile                               |    5 +
+ drivers/iio/accel/Kconfig                          |   16 +
+ drivers/iio/accel/Makefile                         |    5 +
+ drivers/iio/accel/hid-sensor-accel-3d.c            |  418 +
+ drivers/iio/adc/Kconfig                            |   32 +
+ drivers/iio/adc/Makefile                           |    3 +
+ drivers/iio/adc/ad7266.c                           |    2 +-
+ .../iio/adc/ad7476_core.c => iio/adc/ad7476.c}     |  210 +-
+ drivers/iio/adc/ad7791.c                           |  460 +
+ drivers/iio/adc/ad_sigma_delta.c                   |  558 ++
+ drivers/iio/adc/at91_adc.c                         |   77 +-
+ drivers/iio/common/Kconfig                         |    5 +
+ drivers/iio/common/Makefile                        |    9 +
+ drivers/iio/common/hid-sensors/Kconfig             |   26 +
+ drivers/iio/common/hid-sensors/Makefile            |    6 +
+ .../iio/common/hid-sensors/hid-sensor-attributes.c |  250 +
+ .../iio/common/hid-sensors/hid-sensor-attributes.h |   57 +
+ .../iio/common/hid-sensors/hid-sensor-trigger.c    |  102 +
+ .../iio/common/hid-sensors/hid-sensor-trigger.h    |   26 +
+ drivers/iio/dac/Kconfig                            |   20 +-
+ drivers/iio/dac/Makefile                           |    1 +
+ drivers/iio/dac/ad5446.c                           |  450 +-
+ drivers/iio/dac/ad5446.h                           |   91 -
+ drivers/iio/dac/ad5755.c                           |  650 ++
+ drivers/iio/gyro/Kconfig                           |   16 +
+ drivers/iio/gyro/Makefile                          |    5 +
+ drivers/iio/gyro/hid-sensor-gyro-3d.c              |  418 +
+ drivers/iio/industrialio-buffer.c                  |   15 +-
+ drivers/iio/industrialio-core.c                    |   13 +-
+ drivers/iio/inkern.c                               |  129 +-
+ drivers/iio/kfifo_buf.c                            |   31 +-
+ drivers/iio/light/Kconfig                          |   10 +
+ drivers/iio/light/Makefile                         |    1 +
+ drivers/iio/light/adjd_s311.c                      |    2 +-
+ drivers/iio/light/hid-sensor-als.c                 |  385 +
+ drivers/iio/magnetometer/Kconfig                   |   16 +
+ drivers/iio/magnetometer/Makefile                  |    5 +
+ drivers/iio/magnetometer/hid-sensor-magn-3d.c      |  419 +
+ drivers/staging/Kconfig                            |   10 +-
+ drivers/staging/Makefile                           |    5 +-
+ drivers/staging/android/alarm-dev.c                |   17 +-
+ drivers/staging/android/ashmem.c                   |   32 +-
+ drivers/staging/android/binder.c                   |    2 +-
+ drivers/staging/android/logger.c                   |   40 +-
+ drivers/staging/android/logger.h                   |   24 +-
+ drivers/staging/android/timed_gpio.c               |   13 +-
+ drivers/staging/asus_oled/asus_oled.c              |   56 +-
+ drivers/staging/bcm/Bcmchar.c                      |    2 +
+ drivers/staging/bcm/CmHost.c                       |   82 +-
+ drivers/staging/bcm/InterfaceInit.c                |   17 +-
+ drivers/staging/bcm/InterfaceInit.h                |   33 +-
+ drivers/staging/bcm/Kconfig                        |    2 +-
+ drivers/staging/bcm/Misc.c                         |    5 +-
+ drivers/staging/bcm/PHSModule.c                    |    4 +-
+ drivers/staging/bcm/Transmit.c                     |  234 +-
+ drivers/staging/bcm/cntrl_SignalingInterface.h     |  736 +-
+ drivers/staging/bcm/nvm.c                          |    4 +-
+ drivers/staging/bcm/target_params.h                |    2 +-
+ drivers/staging/ccg/Kconfig                        |    2 +-
+ drivers/staging/ccg/ccg.c                          |   14 +-
+ drivers/staging/ced1401/Kconfig                    |    6 +
+ drivers/staging/ced1401/Makefile                   |    3 +
+ drivers/staging/ced1401/TODO                       |   10 +
+ drivers/staging/ced1401/ced_ioc.c                  | 1515 ++++
+ drivers/staging/ced1401/ced_ioctl.h                |  345 +
+ drivers/staging/ced1401/machine.h                  |  127 +
+ drivers/staging/ced1401/usb1401.c                  | 1637 ++++
+ drivers/staging/ced1401/usb1401.h                  |  249 +
+ drivers/staging/ced1401/use1401.h                  |  287 +
+ drivers/staging/ced1401/use14_ioc.h                |  301 +
+ drivers/staging/ced1401/userspace/use1401.c        | 3035 +++++++
+ drivers/staging/comedi/Kconfig                     |   66 +-
+ drivers/staging/comedi/comedi.h                    | 1109 ++-
+ drivers/staging/comedi/comedi_fops.c               |  152 +-
+ drivers/staging/comedi/comedidev.h                 |    2 +-
+ drivers/staging/comedi/drivers.c                   |   82 +-
+ drivers/staging/comedi/drivers/8253.h              |   15 +-
+ drivers/staging/comedi/drivers/8255.c              |    4 +-
+ drivers/staging/comedi/drivers/8255_pci.c          |  353 +
+ drivers/staging/comedi/drivers/Makefile            |    6 +-
+ drivers/staging/comedi/drivers/acl7225b.c          |    6 +-
+ .../comedi/drivers/addi-data/addi_amcc_S5920.c     |  195 -
+ .../comedi/drivers/addi-data/addi_amcc_S5920.h     |   27 -
+ .../staging/comedi/drivers/addi-data/addi_common.c |   14 +-
+ .../comedi/drivers/addi-data/amcc_s5933_58.h       |  453 -
+ .../comedi/drivers/addi-data/hwdrv_APCI1710.c      |   18 +-
+ .../comedi/drivers/addi-data/hwdrv_apci3120.c      |    6 +-
+ .../comedi/drivers/addi-data/hwdrv_apci3200.c      |   14 +-
+ drivers/staging/comedi/drivers/addi_apci_all.c     |   18 -
+ drivers/staging/comedi/drivers/adl_pci6208.c       |  183 +-
+ drivers/staging/comedi/drivers/adl_pci7230.c       |  190 -
+ drivers/staging/comedi/drivers/adl_pci7296.c       |  183 -
+ drivers/staging/comedi/drivers/adl_pci7432.c       |  200 -
+ drivers/staging/comedi/drivers/adl_pci7x3x.c       |  332 +
+ drivers/staging/comedi/drivers/adl_pci8164.c       |   73 +-
+ drivers/staging/comedi/drivers/adl_pci9111.c       |  973 +--
+ drivers/staging/comedi/drivers/adl_pci9118.c       |  986 +--
+ drivers/staging/comedi/drivers/adq12b.c            |   29 +-
+ drivers/staging/comedi/drivers/adv_pci1710.c       |  764 +-
+ drivers/staging/comedi/drivers/adv_pci1723.c       |  222 +-
+ drivers/staging/comedi/drivers/adv_pci_dio.c       |  473 +-
+ drivers/staging/comedi/drivers/aio_aio12_8.c       |  218 +-
+ drivers/staging/comedi/drivers/aio_iiro_16.c       |    4 +-
+ drivers/staging/comedi/drivers/amplc_dio200.c      |   63 +-
+ drivers/staging/comedi/drivers/amplc_pc236.c       |   72 +-
+ drivers/staging/comedi/drivers/amplc_pc263.c       |   54 +-
+ drivers/staging/comedi/drivers/amplc_pci224.c      |    4 +-
+ drivers/staging/comedi/drivers/amplc_pci230.c      |    8 +-
+ drivers/staging/comedi/drivers/c6xdigio.c          |    6 +-
+ drivers/staging/comedi/drivers/cb_das16_cs.c       |    6 +-
+ drivers/staging/comedi/drivers/cb_pcidas.c         |  100 +-
+ drivers/staging/comedi/drivers/cb_pcidas64.c       |   22 +-
+ drivers/staging/comedi/drivers/cb_pcidda.c         |  382 +-
+ drivers/staging/comedi/drivers/cb_pcidio.c         |  211 -
+ drivers/staging/comedi/drivers/cb_pcimdas.c        |  279 +-
+ drivers/staging/comedi/drivers/cb_pcimdda.c        |  393 +-
+ drivers/staging/comedi/drivers/comedi_bond.c       |  110 +-
+ drivers/staging/comedi/drivers/comedi_fc.h         |   32 +
+ drivers/staging/comedi/drivers/comedi_parport.c    |   49 +-
+ drivers/staging/comedi/drivers/comedi_test.c       |   65 +-
+ drivers/staging/comedi/drivers/contec_pci_dio.c    |  146 +-
+ drivers/staging/comedi/drivers/daqboard2000.c      |  466 +-
+ drivers/staging/comedi/drivers/das08.c             |  482 +-
+ drivers/staging/comedi/drivers/das08.h             |   15 +-
+ drivers/staging/comedi/drivers/das08_cs.c          |   26 +
+ drivers/staging/comedi/drivers/das16.c             |   30 +-
+ drivers/staging/comedi/drivers/das16m1.c           |   10 +-
+ drivers/staging/comedi/drivers/das1800.c           |   87 +-
+ drivers/staging/comedi/drivers/das6402.c           |    4 +-
+ drivers/staging/comedi/drivers/das800.c            |    8 +-
+ drivers/staging/comedi/drivers/dmm32at.c           |    6 +-
+ drivers/staging/comedi/drivers/dt2801.c            |   12 +-
+ drivers/staging/comedi/drivers/dt2811.c            |    8 +-
+ drivers/staging/comedi/drivers/dt2814.c            |    4 +-
+ drivers/staging/comedi/drivers/dt2815.c            |    2 +-
+ drivers/staging/comedi/drivers/dt2817.c            |    2 +-
+ drivers/staging/comedi/drivers/dt282x.c            |   14 +-
+ drivers/staging/comedi/drivers/dt3000.c            |   12 +-
+ drivers/staging/comedi/drivers/dt9812.c            |    8 +-
+ drivers/staging/comedi/drivers/dyna_pci10xx.c      |  161 +-
+ drivers/staging/comedi/drivers/fl512.c             |    4 +-
+ drivers/staging/comedi/drivers/gsc_hpdi.c          |    2 +-
+ drivers/staging/comedi/drivers/icp_multi.c         |  692 +-
+ drivers/staging/comedi/drivers/icp_multi.h         |  297 -
+ drivers/staging/comedi/drivers/ii_pci20kc.c        |    4 +-
+ drivers/staging/comedi/drivers/jr3_pci.c           |    7 +-
+ drivers/staging/comedi/drivers/jr3_pci.h           |    4 +-
+ drivers/staging/comedi/drivers/ke_counter.c        |  103 +-
+ drivers/staging/comedi/drivers/me4000.c            | 1533 ++--
+ drivers/staging/comedi/drivers/me4000.h            |  409 -
+ drivers/staging/comedi/drivers/me_daq.c            |  221 +-
+ drivers/staging/comedi/drivers/mite.c              |  285 +-
+ drivers/staging/comedi/drivers/mite.h              |   66 +-
+ drivers/staging/comedi/drivers/mpc624.c            |    2 +-
+ drivers/staging/comedi/drivers/mpc8260cpm.c        |    2 +-
+ drivers/staging/comedi/drivers/multiq3.c           |   14 +-
+ drivers/staging/comedi/drivers/ni_6527.c           |  134 +-
+ drivers/staging/comedi/drivers/ni_65xx.c           |  144 +-
+ drivers/staging/comedi/drivers/ni_660x.c           |  133 +-
+ drivers/staging/comedi/drivers/ni_670x.c           |   62 +-
+ drivers/staging/comedi/drivers/ni_at_a2150.c       |    2 +-
+ drivers/staging/comedi/drivers/ni_at_ao.c          |    8 +-
+ drivers/staging/comedi/drivers/ni_atmio.c          |    2 +-
+ drivers/staging/comedi/drivers/ni_atmio16d.c       |   19 +-
+ drivers/staging/comedi/drivers/ni_daq_700.c        |    2 +-
+ drivers/staging/comedi/drivers/ni_daq_dio24.c      |   12 +-
+ drivers/staging/comedi/drivers/ni_labpc.c          |  415 +-
+ drivers/staging/comedi/drivers/ni_labpc_cs.c       |    6 +-
+ drivers/staging/comedi/drivers/ni_mio_common.c     |   81 +-
+ drivers/staging/comedi/drivers/ni_mio_cs.c         |    4 +-
+ drivers/staging/comedi/drivers/ni_pcidio.c         |  425 +-
+ drivers/staging/comedi/drivers/ni_pcimio.c         |   70 +-
+ drivers/staging/comedi/drivers/pcl711.c            |   10 +-
+ drivers/staging/comedi/drivers/pcl724.c            |   15 +-
+ drivers/staging/comedi/drivers/pcl725.c            |    4 +-
+ drivers/staging/comedi/drivers/pcl726.c            |    6 +-
+ drivers/staging/comedi/drivers/pcl730.c            |    8 +-
+ drivers/staging/comedi/drivers/pcl812.c            |   12 +-
+ drivers/staging/comedi/drivers/pcl816.c            |    6 +-
+ drivers/staging/comedi/drivers/pcl818.c            |   18 +-
+ drivers/staging/comedi/drivers/pcm3724.c           |   26 +-
+ drivers/staging/comedi/drivers/pcm3730.c           |   12 +-
+ drivers/staging/comedi/drivers/pcmad.c             |    2 +-
+ drivers/staging/comedi/drivers/pcmda12.c           |    2 +-
+ drivers/staging/comedi/drivers/pcmmio.c            |   32 +-
+ drivers/staging/comedi/drivers/pcmuio.c            |   14 +-
+ drivers/staging/comedi/drivers/poc.c               |    2 +-
+ drivers/staging/comedi/drivers/quatech_daqp_cs.c   |    8 +-
+ drivers/staging/comedi/drivers/rtd520.c            |   12 +-
+ drivers/staging/comedi/drivers/rti800.c            |   10 +-
+ drivers/staging/comedi/drivers/rti802.c            |    2 +-
+ drivers/staging/comedi/drivers/s526.c              |  602 +-
+ drivers/staging/comedi/drivers/serial2002.c        |   14 +-
+ drivers/staging/comedi/drivers/skel.c              |    6 +-
+ drivers/staging/comedi/drivers/ssv_dnp.c           |    7 +-
+ drivers/staging/comedi/drivers/usbdux.c            |   71 +-
+ drivers/staging/comedi/drivers/usbduxfast.c        |   58 +-
+ drivers/staging/comedi/drivers/usbduxsigma.c       |   67 +-
+ drivers/staging/comedi/drivers/vmk80xx.c           |   14 +-
+ .../staging/comedi/kcomedilib/kcomedilib_main.c    |   23 +-
+ drivers/staging/comedi/range.c                     |   18 +-
+ drivers/staging/cptm1217/clearpad_tm1217.c         |   13 +-
+ drivers/staging/crystalhd/crystalhd_lnx.c          |    6 +-
+ drivers/staging/csr/Makefile                       |    1 -
+ drivers/staging/csr/bh.c                           |  173 +-
+ drivers/staging/csr/csr_formatted_io.c             |   27 -
+ drivers/staging/csr/csr_formatted_io.h             |   25 -
+ drivers/staging/csr/csr_framework_ext.c            |   13 +-
+ drivers/staging/csr/csr_panic.c                    |    1 -
+ drivers/staging/csr/csr_time.c                     |   27 +-
+ drivers/staging/csr/csr_wifi_hip_card_sdio.c       |    8 +-
+ drivers/staging/csr/csr_wifi_hip_download.c        |    2 +
+ drivers/staging/csr/csr_wifi_hip_send.c            |    9 +-
+ drivers/staging/csr/csr_wifi_hip_udi.c             |   94 +-
+ drivers/staging/csr/csr_wifi_hip_unifi.h           |    1 -
+ drivers/staging/csr/drv.c                          |   46 +-
+ drivers/staging/csr/firmware.c                     |    6 +-
+ drivers/staging/csr/io.c                           |   53 +-
+ drivers/staging/csr/monitor.c                      |    7 +-
+ drivers/staging/csr/netdev.c                       |  630 +-
+ drivers/staging/csr/sdio_events.c                  |    4 +-
+ drivers/staging/csr/sdio_mmc.c                     |   65 +-
+ drivers/staging/csr/sme_blocking.c                 |    4 +-
+ drivers/staging/csr/sme_native.c                   |    6 +-
+ drivers/staging/csr/sme_sys.c                      |   22 +-
+ drivers/staging/csr/sme_wext.c                     |    8 +-
+ drivers/staging/csr/ul_int.c                       |    5 +-
+ drivers/staging/csr/unifi_pdu_processing.c         |    5 +-
+ drivers/staging/csr/unifi_priv.h                   |   40 -
+ drivers/staging/csr/unifi_wext.h                   |   27 +-
+ drivers/staging/csr/wext_events.c                  |    8 +-
+ drivers/staging/cxt1e1/linux.c                     |   12 +-
+ drivers/staging/cxt1e1/musycc.c                    |   10 +-
+ drivers/staging/et131x/et131x.c                    |    7 +-
+ drivers/staging/ft1000/ft1000-pcmcia/ft1000_dnld.c |   34 +-
+ drivers/staging/ft1000/ft1000-usb/ft1000_hw.c      |   14 +-
+ drivers/staging/ft1000/ft1000-usb/ft1000_usb.h     |    2 -
+ drivers/staging/gdm72xx/gdm_qos.c                  |  118 +-
+ drivers/staging/gdm72xx/gdm_qos.h                  |   58 +-
+ drivers/staging/gdm72xx/gdm_sdio.c                 |   37 +-
+ drivers/staging/gdm72xx/gdm_usb.c                  |   62 +-
+ drivers/staging/gdm72xx/gdm_usb.h                  |   16 +-
+ drivers/staging/gdm72xx/gdm_wimax.c                |   16 +-
+ drivers/staging/gdm72xx/usb_boot.c                 |  220 +-
+ drivers/staging/iio/Documentation/generic_buffer.c |   10 +
+ drivers/staging/iio/Documentation/inkernel.txt     |    6 +-
+ drivers/staging/iio/Kconfig                        |    2 +-
+ drivers/staging/iio/TODO                           |    2 +-
+ drivers/staging/iio/accel/adis16201_core.c         |    4 +-
+ drivers/staging/iio/accel/adis16201_ring.c         |    3 +-
+ drivers/staging/iio/accel/adis16203_core.c         |    4 +-
+ drivers/staging/iio/accel/adis16203_ring.c         |    5 +-
+ drivers/staging/iio/accel/adis16204_core.c         |    4 +-
+ drivers/staging/iio/accel/adis16204_ring.c         |    3 +-
+ drivers/staging/iio/accel/adis16209_core.c         |    4 +-
+ drivers/staging/iio/accel/adis16209_ring.c         |    3 +-
+ drivers/staging/iio/accel/adis16220_core.c         |   11 +-
+ drivers/staging/iio/accel/adis16240_core.c         |    4 +-
+ drivers/staging/iio/accel/adis16240_ring.c         |    3 +-
+ drivers/staging/iio/accel/kxsd9.c                  |    6 +-
+ drivers/staging/iio/accel/lis3l02dq.h              |   14 +-
+ drivers/staging/iio/accel/lis3l02dq_core.c         |   12 +-
+ drivers/staging/iio/accel/lis3l02dq_ring.c         |   31 +-
+ drivers/staging/iio/accel/sca3000.h                |    2 +-
+ drivers/staging/iio/accel/sca3000_core.c           |    8 +-
+ drivers/staging/iio/accel/sca3000_ring.c           |    2 +-
+ drivers/staging/iio/adc/Kconfig                    |   39 +-
+ drivers/staging/iio/adc/Makefile                   |    5 +-
+ drivers/staging/iio/adc/ad7192.c                   |  523 +-
+ drivers/staging/iio/adc/ad7298_core.c              |    2 +-
+ drivers/staging/iio/adc/ad7298_ring.c              |    3 +-
+ drivers/staging/iio/adc/ad7476.h                   |   66 -
+ drivers/staging/iio/adc/ad7476_ring.c              |   64 -
+ drivers/staging/iio/adc/ad7606.h                   |    2 +-
+ drivers/staging/iio/adc/ad7606_core.c              |    6 +-
+ drivers/staging/iio/adc/ad7606_ring.c              |    3 +-
+ drivers/staging/iio/adc/ad7780.c                   |  188 +-
+ drivers/staging/iio/adc/ad7793.c                   |  688 +-
+ drivers/staging/iio/adc/ad7793.h                   |   10 +-
+ drivers/staging/iio/adc/ad7887_core.c              |    2 +-
+ drivers/staging/iio/adc/ad7887_ring.c              |    2 +-
+ drivers/staging/iio/adc/ad799x_ring.c              |    3 +-
+ drivers/staging/iio/adc/lpc32xx_adc.c              |    2 +-
+ drivers/staging/iio/adc/max1363.h                  |    2 +-
+ drivers/staging/iio/adc/max1363_core.c             |   32 +-
+ drivers/staging/iio/adc/max1363_ring.c             |    2 +-
+ drivers/staging/iio/adc/mxs-lradc.c                |  590 ++
+ drivers/staging/iio/adc/spear_adc.c                |   27 +-
+ drivers/staging/iio/gyro/adis16060_core.c          |    4 +-
+ drivers/staging/iio/gyro/adis16080_core.c          |    2 +-
+ drivers/staging/iio/gyro/adis16130_core.c          |    2 +-
+ drivers/staging/iio/gyro/adis16260_core.c          |    2 +-
+ drivers/staging/iio/gyro/adis16260_ring.c          |    3 +-
+ drivers/staging/iio/gyro/adxrs450_core.c           |    2 +-
+ drivers/staging/iio/iio_dummy_evgen.c              |    2 +-
+ drivers/staging/iio/iio_hwmon.c                    |   47 +-
+ drivers/staging/iio/iio_simple_dummy.c             |    4 +-
+ drivers/staging/iio/iio_simple_dummy_buffer.c      |    2 +-
+ drivers/staging/iio/impedance-analyzer/ad5933.c    |    4 +-
+ drivers/staging/iio/imu/adis16400.h                |    2 +-
+ drivers/staging/iio/imu/adis16400_core.c           |   10 +-
+ drivers/staging/iio/imu/adis16400_ring.c           |    2 +-
+ drivers/staging/iio/light/isl29018.c               |   17 +-
+ drivers/staging/iio/light/tsl2563.c                |    2 +-
+ drivers/staging/iio/magnetometer/hmc5843.c         |    2 +-
+ drivers/staging/iio/meter/ade7753.c                |    2 +-
+ drivers/staging/iio/meter/ade7754.c                |    2 +-
+ drivers/staging/iio/meter/ade7758.h                |    2 +-
+ drivers/staging/iio/meter/ade7758_core.c           |    4 +-
+ drivers/staging/iio/meter/ade7758_ring.c           |    3 +-
+ drivers/staging/iio/meter/ade7759.c                |    2 +-
+ drivers/staging/iio/meter/ade7854-spi.c            |    2 +-
+ drivers/staging/iio/resolver/ad2s1210.c            |    2 +-
+ drivers/staging/iio/ring_hw.h                      |    2 +-
+ drivers/staging/iio/ring_sw.c                      |    7 +-
+ drivers/staging/iio/trigger/Kconfig                |    2 +
+ drivers/staging/iio/trigger/iio-trig-bfin-timer.c  |  109 +-
+ drivers/staging/iio/trigger/iio-trig-bfin-timer.h  |   24 +
+ drivers/staging/iio/trigger/iio-trig-gpio.c        |    8 +-
+ .../staging/iio/trigger/iio-trig-periodic-rtc.c    |    8 +-
+ drivers/staging/iio/trigger/iio-trig-sysfs.c       |   17 +-
+ drivers/staging/imx-drm/Kconfig                    |   35 +
+ drivers/staging/imx-drm/Makefile                   |    9 +
+ drivers/staging/imx-drm/TODO                       |   22 +
+ drivers/staging/imx-drm/imx-drm-core.c             |  884 ++
+ drivers/staging/imx-drm/imx-drm.h                  |   58 +
+ drivers/staging/imx-drm/imx-fb.c                   |   47 +
+ drivers/staging/imx-drm/imx-fbdev.c                |   74 +
+ drivers/staging/imx-drm/ipu-v3/Makefile            |    3 +
+ drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h        |  318 +
+ drivers/staging/imx-drm/ipu-v3/ipu-common.c        | 1143 +++
+ drivers/staging/imx-drm/ipu-v3/ipu-dc.c            |  372 +
+ drivers/staging/imx-drm/ipu-v3/ipu-di.c            |  700 ++
+ drivers/staging/imx-drm/ipu-v3/ipu-dmfc.c          |  408 +
+ drivers/staging/imx-drm/ipu-v3/ipu-dp.c            |  336 +
+ drivers/staging/imx-drm/ipu-v3/ipu-prv.h           |  206 +
+ drivers/staging/imx-drm/ipuv3-crtc.c               |  579 ++
+ drivers/staging/imx-drm/parallel-display.c         |  261 +
+ drivers/staging/ipack/Kconfig                      |    1 +
+ drivers/staging/ipack/TODO                         |   25 +-
+ drivers/staging/ipack/bridges/tpci200.c            |  735 +-
+ drivers/staging/ipack/bridges/tpci200.h            |   39 +-
+ drivers/staging/ipack/devices/ipoctal.c            |  738 +-
+ drivers/staging/ipack/devices/scc2698.h            |  117 +-
+ drivers/staging/ipack/ipack.c                      |  372 +-
+ drivers/staging/ipack/ipack.h                      |   88 +-
+ drivers/staging/ipack/ipack_ids.h                  |   32 +
+ drivers/staging/keucr/smcommon.h                   |    2 -
+ drivers/staging/line6/pcm.c                        |    8 +-
+ drivers/staging/line6/variax.c                     |    8 +-
+ drivers/staging/nvec/Kconfig                       |    2 +-
+ drivers/staging/nvec/nvec.c                        |   25 +-
+ drivers/staging/olpc_dcon/olpc_dcon.c              |   53 +-
+ drivers/staging/olpc_dcon/olpc_dcon_xo_1.c         |   15 +-
+ drivers/staging/olpc_dcon/olpc_dcon_xo_1_5.c       |    6 +-
+ drivers/staging/omap-thermal/omap-bandgap.c        |   23 +-
+ drivers/staging/omap-thermal/omap-thermal-common.c |   38 +-
+ drivers/staging/omap-thermal/omap4-thermal.c       |   54 +-
+ drivers/staging/omap-thermal/omap5-thermal.c       |   38 +-
+ drivers/staging/omapdrm/omap_crtc.c                |   33 +-
+ drivers/staging/omapdrm/omap_dmm_tiler.c           |   51 +-
+ drivers/staging/omapdrm/omap_dmm_tiler.h           |   17 +-
+ drivers/staging/omapdrm/omap_drv.c                 |   21 +-
+ drivers/staging/omapdrm/omap_drv.h                 |   33 +-
+ drivers/staging/omapdrm/omap_fb.c                  |   99 +-
+ drivers/staging/omapdrm/omap_gem.c                 |   60 +-
+ drivers/staging/omapdrm/omap_plane.c               |  111 +-
+ drivers/staging/ozwpan/ozcdev.c                    |   14 +-
+ drivers/staging/ozwpan/ozevent.c                   |    6 +-
+ drivers/staging/ozwpan/ozhcd.c                     |  104 +-
+ drivers/staging/ozwpan/ozmain.c                    |    2 +-
+ drivers/staging/ozwpan/ozpd.c                      |   11 +-
+ drivers/staging/ozwpan/ozpd.h                      |    1 +
+ drivers/staging/ozwpan/ozproto.c                   |   13 +
+ drivers/staging/ozwpan/ozproto.h                   |    8 +-
+ drivers/staging/ozwpan/ozprotocol.h                |    6 +-
+ drivers/staging/panel/panel.c                      |   52 +-
+ drivers/staging/ramster/Kconfig                    |   25 +-
+ drivers/staging/ramster/Makefile                   |    7 +-
+ drivers/staging/ramster/TODO                       |   13 -
+ drivers/staging/ramster/cluster/Makefile           |    3 -
+ drivers/staging/ramster/ramster.h                  |  113 +-
+ .../ramster/{cluster => ramster}/heartbeat.c       |    6 +-
+ .../ramster/{cluster => ramster}/heartbeat.h       |    0
+ .../staging/ramster/{cluster => ramster}/masklog.c |    0
+ .../staging/ramster/{cluster => ramster}/masklog.h |    0
+ .../ramster/{cluster => ramster}/nodemanager.c     |   15 +-
+ .../ramster/{cluster => ramster}/nodemanager.h     |    0
+ drivers/staging/ramster/{ => }/ramster/r2net.c     |   79 +-
+ drivers/staging/ramster/ramster/ramster.c          |  985 +++
+ drivers/staging/ramster/ramster/ramster.h          |  161 +
+ .../{cluster => ramster}/ramster_nodemanager.h     |    0
+ drivers/staging/ramster/{cluster => ramster}/tcp.c |   53 +-
+ drivers/staging/ramster/{cluster => ramster}/tcp.h |    0
+ .../ramster/{cluster => ramster}/tcp_internal.h    |    0
+ drivers/staging/ramster/tmem.c                     |  313 +-
+ drivers/staging/ramster/tmem.h                     |  109 +-
+ drivers/staging/ramster/xvmalloc.c                 |  509 --
+ drivers/staging/ramster/xvmalloc.h                 |   30 -
+ drivers/staging/ramster/xvmalloc_int.h             |   95 -
+ drivers/staging/ramster/zbud.c                     | 1060 +++
+ drivers/staging/ramster/zbud.h                     |   33 +
+ drivers/staging/ramster/zcache-main.c              | 3566 +++-----
+ drivers/staging/ramster/zcache.h                   |   55 +-
+ drivers/staging/rtl8187se/ieee80211/ieee80211.h    |    2 +-
+ .../rtl8187se/ieee80211/ieee80211_softmac.c        |   13 +-
+ .../rtl8187se/ieee80211/ieee80211_softmac_wx.c     |    5 +-
+ drivers/staging/rtl8187se/r8180_core.c             |    4 +-
+ drivers/staging/rtl8187se/r8180_hw.h               |    9 +-
+ drivers/staging/rtl8187se/r8185b_init.c            |    2 +-
+ .../staging/rtl8192e/rtl8192e/r8192E_firmware.c    |    9 +-
+ .../staging/rtl8192e/rtl8192e/r8192E_firmware.h    |    4 +
+ drivers/staging/rtl8192e/rtl8192e/rtl_core.c       |    6 +-
+ drivers/staging/rtl8192e/rtl8192e/rtl_dm.c         |    2 +-
+ drivers/staging/rtl8192e/rtllib.h                  |    8 +-
+ drivers/staging/rtl8192e/rtllib_softmac.c          |   24 +-
+ drivers/staging/rtl8192e/rtllib_softmac_wx.c       |    7 +-
+ drivers/staging/rtl8192u/ieee80211/ieee80211.h     |    4 +-
+ .../staging/rtl8192u/ieee80211/ieee80211_softmac.c |   20 +-
+ .../rtl8192u/ieee80211/ieee80211_softmac_wx.c      |    5 +-
+ .../staging/rtl8192u/ieee80211/rtl819x_BAProc.c    |    2 +-
+ drivers/staging/rtl8192u/ieee80211/rtl819x_HT.h    |    4 +-
+ .../staging/rtl8192u/ieee80211/rtl819x_HTProc.c    |    2 +-
+ drivers/staging/rtl8192u/r8192U_core.c             |   27 +-
+ drivers/staging/rtl8192u/r819xU_HTType.h           |    2 +-
+ drivers/staging/rtl8192u/r819xU_phyreg.h           |    2 +-
+ drivers/staging/rtl8712/drv_types.h                |    9 -
+ drivers/staging/rtl8712/ethernet.h                 |    8 -
+ drivers/staging/rtl8712/rtl8712_recv.c             |    4 +
+ drivers/staging/rtl8712/rtl8712_recv.h             |    2 +-
+ drivers/staging/rtl8712/rtl871x_ioctl_linux.c      |    4 +-
+ drivers/staging/rtl8712/rtl871x_ioctl_set.c        |    5 +-
+ drivers/staging/rtl8712/rtl871x_mlme.c             |    5 +-
+ drivers/staging/rtl8712/rtl871x_pwrctrl.h          |   20 -
+ drivers/staging/rtl8712/rtl871x_recv.c             |    9 +-
+ drivers/staging/rtl8712/usb_intf.c                 |    1 -
+ drivers/staging/rtl8712/usb_osintf.h               |    3 -
+ drivers/staging/rtl8712/usb_vendor_req.h           |   58 -
+ drivers/staging/rts5139/trace.h                    |   32 +-
+ drivers/staging/rts_pstor/ms.c                     |  872 +-
+ drivers/staging/rts_pstor/rtsx.c                   |  112 +-
+ drivers/staging/rts_pstor/rtsx_card.c              |  186 +-
+ drivers/staging/rts_pstor/rtsx_chip.c              |  563 +-
+ drivers/staging/rts_pstor/rtsx_scsi.c              |  405 +-
+ drivers/staging/rts_pstor/rtsx_transport.c         |  100 +-
+ drivers/staging/rts_pstor/sd.c                     | 1055 +--
+ drivers/staging/rts_pstor/trace.h                  |   30 +-
+ drivers/staging/sbe-2t3e3/2t3e3.h                  |    1 -
+ drivers/staging/sbe-2t3e3/dc.c                     |   10 +-
+ drivers/staging/sbe-2t3e3/module.c                 |   15 +-
+ drivers/staging/sbe-2t3e3/netdev.c                 |    8 +-
+ drivers/staging/sep/sep_main.c                     |    2 +-
+ drivers/staging/serqt_usb2/serqt_usb2.c            |    9 +-
+ drivers/staging/silicom/Kconfig                    |   46 +
+ drivers/staging/silicom/Makefile                   |    9 +
+ drivers/staging/silicom/README                     |   14 +
+ drivers/staging/silicom/TODO                       |    8 +
+ drivers/staging/silicom/bits.h                     |   56 +
+ drivers/staging/silicom/bp_ioctl.h                 |  140 +
+ drivers/staging/silicom/bp_mod.c                   | 8931 ++++++++++++++++++++
+ drivers/staging/silicom/bp_mod.h                   |  704 ++
+ drivers/staging/silicom/bp_proc.c                  | 1350 +++
+ drivers/staging/silicom/bypass.h                   |  202 +
+ drivers/staging/silicom/bypasslib/Makefile         |    6 +
+ drivers/staging/silicom/bypasslib/bp_ioctl.h       |  198 +
+ drivers/staging/silicom/bypasslib/bplibk.h         |   47 +
+ drivers/staging/silicom/bypasslib/bypass.c         |  529 ++
+ drivers/staging/silicom/bypasslib/libbp_sd.h       |  509 ++
+ drivers/staging/silicom/libbp_sd.h                 |  550 ++
+ drivers/staging/slicoss/slicoss.c                  |   40 +-
+ drivers/staging/sm7xxfb/sm7xx.h                    |    2 +-
+ drivers/staging/sm7xxfb/sm7xxfb.c                  |  119 +-
+ drivers/staging/speakup/i18n.c                     |    1 +
+ drivers/staging/speakup/speakup_soft.c             |   15 +-
+ drivers/staging/telephony/ixj.c                    |    4 +-
+ .../staging/tidspbridge/Documentation/error-codes  |    2 +-
+ drivers/staging/tidspbridge/core/_tiomap.h         |    2 +-
+ drivers/staging/tidspbridge/core/chnl_sm.c         |    9 +-
+ drivers/staging/tidspbridge/core/dsp-clock.c       |    2 +
+ drivers/staging/tidspbridge/core/io_sm.c           |   10 +-
+ drivers/staging/tidspbridge/core/sync.c            |    2 +-
+ drivers/staging/tidspbridge/core/tiomap3430.c      |    8 +-
+ drivers/staging/tidspbridge/core/tiomap3430_pwr.c  |    2 +-
+ drivers/staging/tidspbridge/core/wdt.c             |    7 +-
+ drivers/staging/tidspbridge/dynload/tramp.c        |    8 +-
+ drivers/staging/tidspbridge/gen/uuidutil.c         |   21 -
+ drivers/staging/tidspbridge/hw/hw_mmu.c            |    6 +-
+ .../tidspbridge/include/dspbridge/dspioctl.h       |    2 +-
+ .../staging/tidspbridge/include/dspbridge/mbx_sh.h |    2 +-
+ .../staging/tidspbridge/include/dspbridge/node.h   |    2 +-
+ .../staging/tidspbridge/include/dspbridge/ntfy.h   |    2 +-
+ .../staging/tidspbridge/include/dspbridge/proc.h   |    2 +-
+ .../staging/tidspbridge/include/dspbridge/strm.h   |    2 +-
+ .../staging/tidspbridge/include/dspbridge/sync.h   |    4 +-
+ .../tidspbridge/include/dspbridge/uuidutil.h       |   20 -
+ drivers/staging/tidspbridge/rmgr/dbdcd.c           |   29 +-
+ drivers/staging/tidspbridge/rmgr/drv_interface.c   |   14 +-
+ drivers/staging/tidspbridge/rmgr/dspdrv.c          |    4 +-
+ drivers/staging/tidspbridge/rmgr/mgr.c             |    4 +-
+ drivers/staging/tidspbridge/rmgr/nldr.c            |    2 +-
+ drivers/staging/tidspbridge/rmgr/node.c            |    5 +-
+ drivers/staging/tidspbridge/rmgr/proc.c            |    2 +-
+ drivers/staging/usbip/Kconfig                      |    4 +-
+ drivers/staging/usbip/stub_dev.c                   |    8 +-
+ drivers/staging/usbip/stub_rx.c                    |    2 +-
+ drivers/staging/usbip/usbip_common.c               |    4 +
+ drivers/staging/usbip/userspace/configure.ac       |   12 +-
+ drivers/staging/usbip/userspace/doc/usbip.8        |   66 +-
+ .../usbip/userspace/doc/usbip_bind_driver.8        |   42 -
+ drivers/staging/usbip/userspace/doc/usbipd.8       |   16 +-
+ drivers/staging/usbip/vhci_hcd.c                   |   31 +-
+ drivers/staging/vme/devices/vme_pio2_core.c        |   10 +-
+ drivers/staging/vme/devices/vme_user.c             |   10 +-
+ drivers/staging/vt6655/80211mgr.h                  |    2 +-
+ drivers/staging/vt6655/baseband.c                  |  172 +-
+ drivers/staging/vt6655/baseband.h                  |   10 +-
+ drivers/staging/vt6655/bssdb.c                     |    4 +-
+ drivers/staging/vt6655/card.c                      |  101 +-
+ drivers/staging/vt6655/datarate.c                  |    2 +-
+ drivers/staging/vt6655/device.h                    |    4 +-
+ drivers/staging/vt6655/device_main.c               |  104 +-
+ drivers/staging/vt6655/dpc.c                       |    2 +-
+ drivers/staging/vt6655/hostap.c                    |    8 +-
+ drivers/staging/vt6655/ioctl.c                     |    9 +-
+ drivers/staging/vt6655/iwctl.c                     |    6 +-
+ drivers/staging/vt6655/key.c                       |    2 +-
+ drivers/staging/vt6655/mac.c                       |   12 +-
+ drivers/staging/vt6655/mac.h                       |    2 +-
+ drivers/staging/vt6655/mib.c                       |    2 +-
+ drivers/staging/vt6655/power.c                     |    2 +-
+ drivers/staging/vt6655/rf.c                        |   82 +-
+ drivers/staging/vt6655/rf.h                        |    2 +-
+ drivers/staging/vt6655/rxtx.c                      |   42 +-
+ drivers/staging/vt6655/tcrc.c                      |    2 +-
+ drivers/staging/vt6655/tcrc.h                      |    2 +-
+ drivers/staging/vt6655/tether.c                    |    4 +-
+ drivers/staging/vt6655/tkip.c                      |    2 +-
+ drivers/staging/vt6655/vntwifi.c                   |    2 +-
+ drivers/staging/vt6655/wcmd.c                      |    6 +-
+ drivers/staging/vt6655/wmgr.c                      |   56 +-
+ drivers/staging/vt6655/wmgr.h                      |    4 +-
+ drivers/staging/vt6655/wpa.c                       |    2 +-
+ drivers/staging/vt6655/wpa2.c                      |    8 +-
+ drivers/staging/vt6655/wpactl.c                    |    6 +-
+ drivers/staging/vt6655/wroute.c                    |    2 +-
+ drivers/staging/vt6656/80211mgr.h                  |    4 +-
+ drivers/staging/vt6656/baseband.c                  |    6 +-
+ drivers/staging/vt6656/baseband.h                  |    2 +-
+ drivers/staging/vt6656/bssdb.c                     |   18 +-
+ drivers/staging/vt6656/card.c                      |   38 +-
+ drivers/staging/vt6656/device.h                    |    2 +-
+ drivers/staging/vt6656/dpc.c                       |    2 +-
+ drivers/staging/vt6656/hostap.c                    |   30 +-
+ drivers/staging/vt6656/int.c                       |    2 +-
+ drivers/staging/vt6656/ioctl.c                     |   11 +-
+ drivers/staging/vt6656/iwctl.c                     |    2 +-
+ drivers/staging/vt6656/key.c                       |    4 +-
+ drivers/staging/vt6656/main_usb.c                  |   20 +-
+ drivers/staging/vt6656/power.c                     |    2 +-
+ drivers/staging/vt6656/rf.c                        |   58 +-
+ drivers/staging/vt6656/rf.h                        |    2 +-
+ drivers/staging/vt6656/rxtx.c                      |   52 +-
+ drivers/staging/vt6656/tcrc.c                      |    2 +-
+ drivers/staging/vt6656/tcrc.h                      |    2 +-
+ drivers/staging/vt6656/tether.c                    |    4 +-
+ drivers/staging/vt6656/tkip.c                      |    2 +-
+ drivers/staging/vt6656/wcmd.c                      |    8 +-
+ drivers/staging/vt6656/wctl.c                      |    2 +-
+ drivers/staging/vt6656/wmgr.c                      |   26 +-
+ drivers/staging/vt6656/wpa.c                       |    2 +-
+ drivers/staging/vt6656/wpa2.c                      |    6 +-
+ drivers/staging/vt6656/wpactl.c                    |    6 +-
+ drivers/staging/winbond/Kconfig                    |    2 +-
+ drivers/staging/winbond/localpara.h                |    4 +-
+ drivers/staging/winbond/mds.c                      |    2 +-
+ drivers/staging/winbond/mto.c                      |    2 +-
+ drivers/staging/winbond/phy_calibration.c          |   14 +-
+ drivers/staging/winbond/reg.c                      |    2 +-
+ drivers/staging/winbond/sme_api.h                  |   11 +-
+ drivers/staging/winbond/wb35reg.c                  |    4 +-
+ drivers/staging/winbond/wb35tx.c                   |    8 +-
+ drivers/staging/winbond/wb35tx_s.h                 |    2 +-
+ drivers/staging/wlags49_h2/README.ubuntu           |   12 +-
+ drivers/staging/wlags49_h2/TODO                    |   10 +-
+ drivers/staging/wlags49_h2/hcf.c                   |   20 +-
+ drivers/staging/wlags49_h2/hcfcfg.h                |    2 +-
+ drivers/staging/wlags49_h2/hcfdef.h                |    6 +-
+ drivers/staging/wlags49_h2/mdd.h                   |    8 +-
+ drivers/staging/wlags49_h2/sta_h2.c                |    2 +-
+ drivers/staging/wlags49_h2/sta_h25.c               |    2 +-
+ drivers/staging/wlags49_h2/wl_enc.h                |    2 +-
+ drivers/staging/wlags49_h2/wl_if.h                 |    2 +-
+ drivers/staging/wlags49_h2/wl_internal.h           |    4 +-
+ drivers/staging/wlags49_h2/wl_main.c               |   18 +-
+ drivers/staging/wlags49_h2/wl_netdev.c             |   59 +-
+ drivers/staging/wlags49_h2/wl_pci.c                |    8 +-
+ drivers/staging/wlags49_h2/wl_priv.c               |    2 +-
+ drivers/staging/wlags49_h2/wl_profile.c            |    2 +-
+ drivers/staging/wlags49_h2/wl_version.h            |    2 +-
+ drivers/staging/wlags49_h2/wl_wext.c               |   27 +-
+ drivers/staging/wlags49_h25/Kconfig                |    2 +-
+ drivers/staging/wlags49_h25/TODO                   |    8 +-
+ drivers/staging/wlan-ng/cfg80211.c                 |    7 +-
+ drivers/staging/wlan-ng/hfa384x_usb.c              |   37 +-
+ drivers/staging/wlan-ng/p80211conv.c               |    9 +-
+ drivers/staging/wlan-ng/p80211netdev.c             |   19 +-
+ drivers/staging/wlan-ng/p80211netdev.h             |    2 +-
+ drivers/staging/wlan-ng/p80211req.c                |  152 +-
+ drivers/staging/wlan-ng/p80211wep.c                |   18 +-
+ drivers/staging/wlan-ng/prism2fw.c                 |   54 +-
+ drivers/staging/wlan-ng/prism2sta.c                |   53 +-
+ drivers/staging/xgifb/XGI_main_26.c                |   45 +-
+ drivers/staging/xgifb/vb_def.h                     |   21 -
+ drivers/staging/xgifb/vb_init.c                    |    5 +-
+ drivers/staging/xgifb/vb_setmode.c                 |  601 +-
+ drivers/staging/xgifb/vb_struct.h                  |   49 +-
+ drivers/staging/xgifb/vb_table.h                   |  194 +-
+ drivers/staging/zcache/tmem.c                      |    2 +-
+ drivers/staging/zsmalloc/zsmalloc-main.c           |  322 +-
+ drivers/staging/zsmalloc/zsmalloc_int.h            |  155 -
+ include/linux/hid-sensor-hub.h                     |  160 +
+ include/linux/hid-sensor-ids.h                     |  112 +
+ include/linux/iio/adc/ad_sigma_delta.h             |  173 +
+ include/linux/iio/buffer.h                         |    6 +-
+ include/linux/iio/consumer.h                       |   44 +-
+ include/linux/iio/iio.h                            |   65 +-
+ include/linux/iio/kfifo_buf.h                      |    3 +
+ include/linux/iio/machine.h                        |    5 +
+ include/linux/iio/trigger.h                        |   13 +-
+ include/linux/iio/trigger_consumer.h               |   11 +
+ include/linux/iio/types.h                          |    1 +
+ include/linux/mod_devicetable.h                    |    8 +
+ include/linux/platform_data/ad5755.h               |  103 +
+ include/linux/platform_data/ad7791.h               |   17 +
+ scripts/mod/file2alias.c                           |   15 +
+ 644 files changed, 49506 insertions(+), 23846 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt
+ create mode 100644 Documentation/devicetree/bindings/staging/imx-drm/fsl-imx-drm.txt
+ create mode 100755 Documentation/hid/hid-sensor.txt
+ create mode 100644 drivers/hid/hid-sensor-hub.c
+ create mode 100644 drivers/iio/accel/Kconfig
+ create mode 100644 drivers/iio/accel/Makefile
+ create mode 100644 drivers/iio/accel/hid-sensor-accel-3d.c
+ rename drivers/{staging/iio/adc/ad7476_core.c => iio/adc/ad7476.c} (52%)
+ create mode 100644 drivers/iio/adc/ad7791.c
+ create mode 100644 drivers/iio/adc/ad_sigma_delta.c
+ create mode 100644 drivers/iio/common/Kconfig
+ create mode 100644 drivers/iio/common/Makefile
+ create mode 100644 drivers/iio/common/hid-sensors/Kconfig
+ create mode 100644 drivers/iio/common/hid-sensors/Makefile
+ create mode 100644 drivers/iio/common/hid-sensors/hid-sensor-attributes.c
+ create mode 100644 drivers/iio/common/hid-sensors/hid-sensor-attributes.h
+ create mode 100644 drivers/iio/common/hid-sensors/hid-sensor-trigger.c
+ create mode 100644 drivers/iio/common/hid-sensors/hid-sensor-trigger.h
+ delete mode 100644 drivers/iio/dac/ad5446.h
+ create mode 100644 drivers/iio/dac/ad5755.c
+ create mode 100644 drivers/iio/gyro/Kconfig
+ create mode 100644 drivers/iio/gyro/Makefile
+ create mode 100644 drivers/iio/gyro/hid-sensor-gyro-3d.c
+ create mode 100644 drivers/iio/light/hid-sensor-als.c
+ create mode 100644 drivers/iio/magnetometer/Kconfig
+ create mode 100644 drivers/iio/magnetometer/Makefile
+ create mode 100644 drivers/iio/magnetometer/hid-sensor-magn-3d.c
+ create mode 100644 drivers/staging/ced1401/Kconfig
+ create mode 100644 drivers/staging/ced1401/Makefile
+ create mode 100644 drivers/staging/ced1401/TODO
+ create mode 100644 drivers/staging/ced1401/ced_ioc.c
+ create mode 100644 drivers/staging/ced1401/ced_ioctl.h
+ create mode 100644 drivers/staging/ced1401/machine.h
+ create mode 100644 drivers/staging/ced1401/usb1401.c
+ create mode 100644 drivers/staging/ced1401/usb1401.h
+ create mode 100644 drivers/staging/ced1401/use1401.h
+ create mode 100644 drivers/staging/ced1401/use14_ioc.h
+ create mode 100644 drivers/staging/ced1401/userspace/use1401.c
+ create mode 100644 drivers/staging/comedi/drivers/8255_pci.c
+ delete mode 100644 drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c
+ delete mode 100644 drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.h
+ delete mode 100644 drivers/staging/comedi/drivers/addi-data/amcc_s5933_58.h
+ delete mode 100644 drivers/staging/comedi/drivers/addi_apci_all.c
+ delete mode 100644 drivers/staging/comedi/drivers/adl_pci7230.c
+ delete mode 100644 drivers/staging/comedi/drivers/adl_pci7296.c
+ delete mode 100644 drivers/staging/comedi/drivers/adl_pci7432.c
+ create mode 100644 drivers/staging/comedi/drivers/adl_pci7x3x.c
+ delete mode 100644 drivers/staging/comedi/drivers/cb_pcidio.c
+ delete mode 100644 drivers/staging/comedi/drivers/icp_multi.h
+ delete mode 100644 drivers/staging/comedi/drivers/me4000.h
+ delete mode 100644 drivers/staging/csr/csr_formatted_io.c
+ delete mode 100644 drivers/staging/csr/csr_formatted_io.h
+ delete mode 100644 drivers/staging/iio/adc/ad7476.h
+ delete mode 100644 drivers/staging/iio/adc/ad7476_ring.c
+ create mode 100644 drivers/staging/iio/adc/mxs-lradc.c
+ create mode 100644 drivers/staging/iio/trigger/iio-trig-bfin-timer.h
+ create mode 100644 drivers/staging/imx-drm/Kconfig
+ create mode 100644 drivers/staging/imx-drm/Makefile
+ create mode 100644 drivers/staging/imx-drm/TODO
+ create mode 100644 drivers/staging/imx-drm/imx-drm-core.c
+ create mode 100644 drivers/staging/imx-drm/imx-drm.h
+ create mode 100644 drivers/staging/imx-drm/imx-fb.c
+ create mode 100644 drivers/staging/imx-drm/imx-fbdev.c
+ create mode 100644 drivers/staging/imx-drm/ipu-v3/Makefile
+ create mode 100644 drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h
+ create mode 100644 drivers/staging/imx-drm/ipu-v3/ipu-common.c
+ create mode 100644 drivers/staging/imx-drm/ipu-v3/ipu-dc.c
+ create mode 100644 drivers/staging/imx-drm/ipu-v3/ipu-di.c
+ create mode 100644 drivers/staging/imx-drm/ipu-v3/ipu-dmfc.c
+ create mode 100644 drivers/staging/imx-drm/ipu-v3/ipu-dp.c
+ create mode 100644 drivers/staging/imx-drm/ipu-v3/ipu-prv.h
+ create mode 100644 drivers/staging/imx-drm/ipuv3-crtc.c
+ create mode 100644 drivers/staging/imx-drm/parallel-display.c
+ create mode 100644 drivers/staging/ipack/ipack_ids.h
+ delete mode 100644 drivers/staging/ramster/TODO
+ delete mode 100644 drivers/staging/ramster/cluster/Makefile
+ rename drivers/staging/ramster/{cluster => ramster}/heartbeat.c (98%)
+ rename drivers/staging/ramster/{cluster => ramster}/heartbeat.h (100%)
+ rename drivers/staging/ramster/{cluster => ramster}/masklog.c (100%)
+ rename drivers/staging/ramster/{cluster => ramster}/masklog.h (100%)
+ rename drivers/staging/ramster/{cluster => ramster}/nodemanager.c (98%)
+ rename drivers/staging/ramster/{cluster => ramster}/nodemanager.h (100%)
+ rename drivers/staging/ramster/{ => }/ramster/r2net.c (86%)
+ create mode 100644 drivers/staging/ramster/ramster/ramster.c
+ create mode 100644 drivers/staging/ramster/ramster/ramster.h
+ rename drivers/staging/ramster/{cluster => ramster}/ramster_nodemanager.h (100%)
+ rename drivers/staging/ramster/{cluster => ramster}/tcp.c (97%)
+ rename drivers/staging/ramster/{cluster => ramster}/tcp.h (100%)
+ rename drivers/staging/ramster/{cluster => ramster}/tcp_internal.h (100%)
+ delete mode 100644 drivers/staging/ramster/xvmalloc.c
+ delete mode 100644 drivers/staging/ramster/xvmalloc.h
+ delete mode 100644 drivers/staging/ramster/xvmalloc_int.h
+ create mode 100644 drivers/staging/ramster/zbud.c
+ create mode 100644 drivers/staging/ramster/zbud.h
+ delete mode 100644 drivers/staging/rtl8712/usb_vendor_req.h
+ create mode 100644 drivers/staging/silicom/Kconfig
+ create mode 100644 drivers/staging/silicom/Makefile
+ create mode 100644 drivers/staging/silicom/README
+ create mode 100644 drivers/staging/silicom/TODO
+ create mode 100644 drivers/staging/silicom/bits.h
+ create mode 100644 drivers/staging/silicom/bp_ioctl.h
+ create mode 100644 drivers/staging/silicom/bp_mod.c
+ create mode 100644 drivers/staging/silicom/bp_mod.h
+ create mode 100644 drivers/staging/silicom/bp_proc.c
+ create mode 100644 drivers/staging/silicom/bypass.h
+ create mode 100644 drivers/staging/silicom/bypasslib/Makefile
+ create mode 100644 drivers/staging/silicom/bypasslib/bp_ioctl.h
+ create mode 100644 drivers/staging/silicom/bypasslib/bplibk.h
+ create mode 100644 drivers/staging/silicom/bypasslib/bypass.c
+ create mode 100644 drivers/staging/silicom/bypasslib/libbp_sd.h
+ create mode 100644 drivers/staging/silicom/libbp_sd.h
+ delete mode 100644 drivers/staging/usbip/userspace/doc/usbip_bind_driver.8
+ delete mode 100644 drivers/staging/zsmalloc/zsmalloc_int.h
+ create mode 100644 include/linux/hid-sensor-hub.h
+ create mode 100644 include/linux/hid-sensor-ids.h
+ create mode 100644 include/linux/iio/adc/ad_sigma_delta.h
+ create mode 100644 include/linux/platform_data/ad5755.h
+ create mode 100644 include/linux/platform_data/ad7791.h
+$ git am -3 ../patches/0001-HID-sensors-fix-up-for-mfd_add_devices-API-change.patch
+Applying: HID: sensors: fix up for mfd_add_devices() API change
+$ git reset HEAD^
+Unstaged changes after reset:
+M	drivers/hid/hid-sensor-hub.c
+$ git add .
+$ git commit -v -a --amend
+[master 5a18cfd] Merge remote-tracking branch 'staging/staging-next'
+Merging char-misc/char-misc-next (6592921 char/misc: remove CONFIG_EXPERIMENTAL dependencies)
+$ git merge char-misc/char-misc-next
+Merge made by the 'recursive' strategy.
+ Documentation/devicetree/bindings/misc/at25.txt  |   34 +++++--
+ Documentation/devicetree/bindings/w1/w1-gpio.txt |   22 +++++
+ Documentation/misc-devices/lis3lv02d             |    3 +-
+ drivers/char/Kconfig                             |    6 +-
+ drivers/char/ppdev.c                             |    3 +-
+ drivers/char/tlclk.c                             |    4 +-
+ drivers/misc/Kconfig                             |   14 +--
+ drivers/misc/bmp085-i2c.c                        |    7 --
+ drivers/misc/bmp085-spi.c                        |   13 +--
+ drivers/misc/c2port/Kconfig                      |    5 +-
+ drivers/misc/carma/carma-fpga-program.c          |    1 -
+ drivers/misc/carma/carma-fpga.c                  |    2 +-
+ drivers/misc/eeprom/Kconfig                      |    2 +-
+ drivers/misc/eeprom/at25.c                       |   83 +++++++++++-----
+ drivers/misc/lis3lv02d/lis3lv02d.c               |   42 ++++++++-
+ drivers/misc/lis3lv02d/lis3lv02d.h               |   44 +++++++--
+ drivers/misc/lis3lv02d/lis3lv02d_i2c.c           |    7 +-
+ drivers/misc/mei/Kconfig                         |    2 +-
+ drivers/misc/mei/hw.h                            |   83 ++++++++--------
+ drivers/misc/mei/init.c                          |   93 ++++++++++--------
+ drivers/misc/mei/interface.h                     |   10 +-
+ drivers/misc/mei/interrupt.c                     |   44 ++++-----
+ drivers/misc/mei/iorw.c                          |   59 ++++++------
+ drivers/misc/mei/main.c                          |  107 ++++++++++-----------
+ drivers/misc/mei/mei_dev.h                       |   78 +++++++++-------
+ drivers/misc/mei/wd.c                            |   91 +++++++++---------
+ drivers/misc/pch_phub.c                          |   15 +--
+ drivers/misc/ti-st/st_core.c                     |   12 ++-
+ drivers/misc/ti-st/st_kim.c                      |  109 +++++++++-------------
+ drivers/misc/tifm_7xx1.c                         |   14 +--
+ drivers/w1/masters/Kconfig                       |    1 -
+ drivers/w1/masters/omap_hdq.c                    |   57 +++--------
+ drivers/w1/masters/w1-gpio.c                     |   66 ++++++++++++-
+ include/linux/ti_wilink_st.h                     |    3 +-
+ include/linux/w1-gpio.h                          |    1 +
+ 35 files changed, 635 insertions(+), 502 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/w1/w1-gpio.txt
+Merging tmem/linux-next (a728d5e Merge commit 'v3.6-rc6' into linux-next)
+$ git merge tmem/linux-next
+Auto-merging include/xen/interface/xen.h
+Auto-merging arch/x86/xen/smp.c
+Auto-merging arch/x86/xen/setup.c
+Auto-merging arch/x86/include/asm/xen/page.h
+Auto-merging arch/x86/include/asm/xen/interface.h
+Merge made by the 'recursive' strategy.
+ arch/x86/include/asm/xen/interface.h |    3 ++-
+ arch/x86/include/asm/xen/page.h      |    3 +++
+ arch/x86/xen/setup.c                 |   13 +++++++++---
+ arch/x86/xen/smp.c                   |   39 ++++++++++++++++++----------------
+ drivers/xen/cpu_hotplug.c            |    3 ++-
+ include/linux/frontswap.h            |    2 ++
+ include/xen/interface/xen.h          |    1 +
+ include/xen/xen.h                    |    4 ++++
+ mm/frontswap.c                       |   34 +++++++++++++++++++++++++----
+ 9 files changed, 75 insertions(+), 27 deletions(-)
+Merging writeback/writeback-for-next (0e2f2b2 writeback: correct comment for move_expired_inodes())
+$ git merge writeback/writeback-for-next
+Auto-merging fs/fs-writeback.c
+Merge made by the 'recursive' strategy.
+ fs/fs-writeback.c |    2 +-
+ mm/backing-dev.c  |   50 ++++++++++++++++++++++++++------------------------
+ 2 files changed, 27 insertions(+), 25 deletions(-)
+Merging arm-dt/devicetree/arm-next (ede338f dt: add documentation of ARM dt boot interface)
+$ git merge arm-dt/devicetree/arm-next
+Already up-to-date.
+Merging hwspinlock/linux-next (8b37fcf hwspinlock: add MAINTAINERS entries)
+$ git merge hwspinlock/linux-next
+Already up-to-date.
+Merging pinctrl/for-next (01194d6 ARM: ux500: tidy up pin sleep modes)
+$ git merge pinctrl/for-next
+Auto-merging arch/arm/Kconfig
+Merge made by the 'recursive' strategy.
+ .../bindings/pinctrl/fsl,imx35-pinctrl.txt         |  984 ++++++++++++
+ .../devicetree/bindings/pinctrl/pinctrl-single.txt |   41 +-
+ Documentation/pinctrl.txt                          |   60 +-
+ arch/arm/Kconfig                                   |    1 +
+ arch/arm/mach-nomadik/board-nhk8815.c              |   36 +
+ arch/arm/mach-nomadik/cpu-8815.c                   |   13 +
+ arch/arm/mach-ux500/board-mop500-pins.c            |   54 +-
+ drivers/pinctrl/Kconfig                            |   16 +
+ drivers/pinctrl/Makefile                           |    3 +
+ drivers/pinctrl/pinctrl-imx.c                      |    2 +-
+ drivers/pinctrl/pinctrl-imx35.c                    | 1595 ++++++++++++++++++++
+ drivers/pinctrl/pinctrl-imx51.c                    |  490 +++---
+ drivers/pinctrl/pinctrl-imx53.c                    |  402 ++---
+ drivers/pinctrl/pinctrl-nomadik-db8500.c           |    5 +-
+ drivers/pinctrl/pinctrl-nomadik-db8540.c           |  999 ++++++++++++
+ drivers/pinctrl/pinctrl-nomadik-stn8815.c          |  357 +++++
+ drivers/pinctrl/pinctrl-nomadik.c                  |    6 +
+ drivers/pinctrl/pinctrl-nomadik.h                  |   27 +
+ drivers/pinctrl/pinctrl-single.c                   |   46 +-
+ drivers/pinctrl/pinmux.c                           |    5 +-
+ include/linux/pinctrl/consumer.h                   |    2 +-
+ 21 files changed, 4654 insertions(+), 490 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/pinctrl/fsl,imx35-pinctrl.txt
+ create mode 100644 drivers/pinctrl/pinctrl-imx35.c
+ create mode 100644 drivers/pinctrl/pinctrl-nomadik-db8540.c
+ create mode 100644 drivers/pinctrl/pinctrl-nomadik-stn8815.c
+Merging vhost/linux-next (e0953c8 tun: experimental zero copy tx support)
+$ git merge vhost/linux-next
+Resolved 'drivers/net/tun.c' using previous resolution.
+Auto-merging drivers/net/tun.c
+CONFLICT (content): Merge conflict in drivers/net/tun.c
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master a149299] Merge remote-tracking branch 'vhost/linux-next'
+$ git diff -M --stat --summary HEAD^..
+Merging memblock/memblock-kill-early_node_map (7bd0b0f memblock: Reimplement memblock allocation using reverse free area iterator)
+$ git merge memblock/memblock-kill-early_node_map
+Already up-to-date.
+Merging remoteproc/for-next (ec4d02d remoteproc: Add STE modem driver)
+$ git merge remoteproc/for-next
+Merge made by the 'recursive' strategy.
+ Documentation/remoteproc.txt                 |    7 +
+ arch/arm/plat-omap/include/plat/remoteproc.h |    2 +
+ drivers/remoteproc/Kconfig                   |   13 ++
+ drivers/remoteproc/Makefile                  |    1 +
+ drivers/remoteproc/omap_remoteproc.c         |    3 +
+ drivers/remoteproc/remoteproc_core.c         |  177 ++++++++++++--
+ drivers/remoteproc/remoteproc_debugfs.c      |   81 +++++++
+ drivers/remoteproc/remoteproc_internal.h     |    1 +
+ drivers/remoteproc/ste_modem_rproc.c         |  322 ++++++++++++++++++++++++++
+ include/linux/remoteproc.h                   |   24 ++
+ include/linux/ste_modem_shm.h                |   56 +++++
+ 11 files changed, 662 insertions(+), 25 deletions(-)
+ create mode 100644 drivers/remoteproc/ste_modem_rproc.c
+ create mode 100644 include/linux/ste_modem_shm.h
+Merging irqdomain/irqdomain/next (f5a1ad0 irqdomain: Improve diagnostics when a domain mapping fails)
+$ git merge irqdomain/irqdomain/next
+Already up-to-date.
+Merging gpio/gpio/next (ddf343f Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux)
+$ git merge gpio/gpio/next
+Already up-to-date.
+Merging gpio-lw/for-next (6b6fe01 Merge branch 'devel' into for-next)
+$ git merge gpio-lw/for-next
+Auto-merging drivers/gpio/gpio-bt8xx.c
+Auto-merging drivers/gpio/Makefile
+Auto-merging drivers/gpio/Kconfig
+Merge made by the 'recursive' strategy.
+ .../devicetree/bindings/gpio/gpio-74x164.txt       |   22 +
+ .../devicetree/bindings/gpio/gpio-adnp.txt         |   34 ++
+ Documentation/devicetree/bindings/gpio/led.txt     |    2 +-
+ arch/arm/configs/kzm9g_defconfig                   |    2 +-
+ arch/arm/mach-shmobile/board-kzm9g.c               |    5 +-
+ drivers/gpio/Kconfig                               |   13 +-
+ drivers/gpio/Makefile                              |    1 +
+ drivers/gpio/gpio-74x164.c                         |  103 +++-
+ drivers/gpio/gpio-adnp.c                           |  611 ++++++++++++++++++++
+ drivers/gpio/gpio-adp5588.c                        |   14 +-
+ drivers/gpio/gpio-bt8xx.c                          |    2 +-
+ drivers/gpio/gpio-da9052.c                         |   15 +-
+ drivers/gpio/gpio-davinci.c                        |    2 +-
+ drivers/gpio/gpio-em.c                             |   12 +-
+ drivers/gpio/gpio-lpc32xx.c                        |    5 +
+ drivers/gpio/gpio-mc9s08dz60.c                     |   21 +-
+ drivers/gpio/gpio-ml-ioh.c                         |   20 +-
+ drivers/gpio/gpio-msm-v2.c                         |    4 +-
+ drivers/gpio/gpio-pcf857x.c                        |  122 ++++
+ drivers/gpio/gpio-pch.c                            |   22 +-
+ drivers/gpio/gpio-pxa.c                            |   13 +-
+ drivers/gpio/gpio-sodaville.c                      |    2 +-
+ drivers/gpio/gpio-sx150x.c                         |   24 +-
+ drivers/gpio/gpio-tc3589x.c                        |  120 ++--
+ drivers/gpio/gpio-tps65912.c                       |   17 +-
+ drivers/gpio/gpio-wm831x.c                         |   19 +-
+ drivers/gpio/gpio-wm8350.c                         |   19 +-
+ drivers/gpio/gpiolib.c                             |  102 +++-
+ include/linux/i2c/pcf857x.h                        |    3 +
+ 29 files changed, 1104 insertions(+), 247 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/gpio/gpio-74x164.txt
+ create mode 100644 Documentation/devicetree/bindings/gpio/gpio-adnp.txt
+ create mode 100644 drivers/gpio/gpio-adnp.c
+Merging arm-soc/for-next (143fe30 Merge branch 'next/soc' into for-next)
+$ git merge arm-soc/for-next
+Auto-merging sound/soc/omap/zoom2.c
+CONFLICT (modify/delete): sound/soc/omap/overo.c deleted in HEAD and modified in arm-soc/for-next. Version arm-soc/for-next of sound/soc/omap/overo.c left in tree.
+CONFLICT (modify/delete): sound/soc/omap/omap3evm.c deleted in HEAD and modified in arm-soc/for-next. Version arm-soc/for-next of sound/soc/omap/omap3evm.c left in tree.
+CONFLICT (modify/delete): sound/soc/omap/omap3beagle.c deleted in HEAD and modified in arm-soc/for-next. Version arm-soc/for-next of sound/soc/omap/omap3beagle.c left in tree.
+Auto-merging sound/soc/omap/omap-pcm.c
+CONFLICT (content): Merge conflict in sound/soc/omap/omap-pcm.c
+Auto-merging sound/soc/omap/omap-mcpdm.c
+Auto-merging sound/soc/omap/omap-mcbsp.c
+CONFLICT (content): Merge conflict in sound/soc/omap/omap-mcbsp.c
+Auto-merging sound/soc/omap/omap-abe-twl6040.c
+Auto-merging sound/soc/omap/mcbsp.c
+CONFLICT (modify/delete): sound/soc/omap/igep0020.c deleted in HEAD and modified in arm-soc/for-next. Version arm-soc/for-next of sound/soc/omap/igep0020.c left in tree.
+Auto-merging sound/soc/omap/am3517evm.c
+Auto-merging sound/soc/fsl/imx-ssi.c
+Auto-merging sound/soc/fsl/imx-pcm-dma.c
+Auto-merging sound/soc/cirrus/ep93xx-pcm.c
+Auto-merging sound/soc/cirrus/ep93xx-i2s.c
+Auto-merging sound/soc/cirrus/ep93xx-ac97.c
+Auto-merging include/linux/platform_data/pinctrl-coh901.h
+Auto-merging include/linux/platform_data/mtd-nand-omap2.h
+Auto-merging include/linux/platform_data/mmc-sdhci-tegra.h
+Auto-merging include/linux/platform_data/gpio-omap.h
+Auto-merging include/linux/platform_data/camera-mx2.h
+Auto-merging include/linux/mod_devicetable.h
+Auto-merging include/linux/mfd/twl6040.h
+Auto-merging include/linux/leds.h
+Auto-merging include/linux/irqchip/bcm2835.h
+Auto-merging include/linux/i2c/twl.h
+Auto-merging include/linux/clk/bcm2835.h
+Auto-merging include/linux/bcm2835_timer.h
+Auto-merging drivers/w1/masters/omap_hdq.c
+CONFLICT (content): Merge conflict in drivers/w1/masters/omap_hdq.c
+Auto-merging drivers/video/omap2/omapfb/omapfb-main.c
+Auto-merging drivers/video/omap2/dss/dispc.c
+CONFLICT (content): Merge conflict in drivers/video/omap2/dss/dispc.c
+Auto-merging drivers/video/omap/lcd_ams_delta.c
+CONFLICT (content): Merge conflict in drivers/video/omap/lcd_ams_delta.c
+Auto-merging drivers/video/msm/mdp_hw.h
+CONFLICT (content): Merge conflict in drivers/video/msm/mdp_hw.h
+Auto-merging drivers/video/msm/mdp.c
+CONFLICT (content): Merge conflict in drivers/video/msm/mdp.c
+Auto-merging drivers/video/msm/mddi_client_nt35399.c
+Auto-merging drivers/video/msm/mddi.c
+CONFLICT (content): Merge conflict in drivers/video/msm/mddi.c
+Auto-merging drivers/video/imxfb.c
+Auto-merging drivers/video/ep93xx-fb.c
+Auto-merging drivers/video/da8xx-fb.c
+Auto-merging drivers/video/Kconfig
+Auto-merging drivers/usb/otg/isp1301_omap.c
+Auto-merging drivers/usb/musb/ux500_dma.c
+Auto-merging drivers/usb/musb/tusb6010_omap.c
+Auto-merging drivers/usb/musb/da8xx.c
+Auto-merging drivers/usb/host/ohci-pxa27x.c
+Auto-merging drivers/usb/host/ohci-nxp.c
+Auto-merging drivers/usb/host/ohci-hcd.c
+Auto-merging drivers/usb/host/ehci-s5p.c
+Auto-merging drivers/usb/host/ehci-mxc.c
+Auto-merging drivers/usb/host/Kconfig
+CONFLICT (content): Merge conflict in drivers/usb/host/Kconfig
+Auto-merging drivers/usb/gadget/s3c2410_udc.c
+Auto-merging drivers/usb/gadget/pxa27x_udc.c
+Auto-merging drivers/usb/Kconfig
+Auto-merging drivers/tty/serial/imx.c
+Auto-merging drivers/staging/tidspbridge/rmgr/drv_interface.c
+Auto-merging drivers/staging/tidspbridge/core/wdt.c
+CONFLICT (content): Merge conflict in drivers/staging/tidspbridge/core/wdt.c
+Auto-merging drivers/staging/tidspbridge/core/tiomap3430_pwr.c
+Auto-merging drivers/staging/tidspbridge/core/tiomap3430.c
+Auto-merging drivers/staging/tidspbridge/core/dsp-clock.c
+Auto-merging drivers/spi/spi-tegra.c
+Auto-merging drivers/spi/spi-s3c64xx.c
+Auto-merging drivers/spi/spi-omap2-mcspi.c
+Auto-merging drivers/spi/spi-davinci.c
+CONFLICT (content): Merge conflict in drivers/spi/spi-davinci.c
+Auto-merging drivers/spi/Kconfig
+Auto-merging drivers/remoteproc/omap_remoteproc.c
+Auto-merging drivers/pinctrl/Makefile
+Auto-merging drivers/pinctrl/Kconfig
+Auto-merging drivers/net/can/mscan/mpc5xxx_can.c
+Auto-merging drivers/mtd/nand/s3c2410.c
+Auto-merging drivers/mtd/nand/pxa3xx_nand.c
+Auto-merging drivers/mtd/nand/orion_nand.c
+CONFLICT (content): Merge conflict in drivers/mtd/nand/orion_nand.c
+Auto-merging drivers/mtd/nand/omap2.c
+CONFLICT (modify/delete): drivers/mtd/nand/nand_bcm_umi.h deleted in HEAD and modified in arm-soc/for-next. Version arm-soc/for-next of drivers/mtd/nand/nand_bcm_umi.h left in tree.
+Auto-merging drivers/mtd/nand/mxc_nand.c
+Auto-merging drivers/mtd/nand/davinci_nand.c
+CONFLICT (modify/delete): drivers/mtd/nand/bcm_umi_nand.c deleted in HEAD and modified in arm-soc/for-next. Version arm-soc/for-next of drivers/mtd/nand/bcm_umi_nand.c left in tree.
+Auto-merging drivers/mtd/nand/ams-delta.c
+Auto-merging drivers/mtd/nand/Kconfig
+CONFLICT (content): Merge conflict in drivers/mtd/nand/Kconfig
+Auto-merging drivers/mmc/host/sdhci-tegra.c
+Auto-merging drivers/mmc/host/sdhci-esdhc-imx.c
+Auto-merging drivers/mmc/host/pxamci.c
+Auto-merging drivers/mmc/host/omap_hsmmc.c
+Auto-merging drivers/mmc/host/omap.c
+CONFLICT (content): Merge conflict in drivers/mmc/host/omap.c
+Auto-merging drivers/mmc/host/mxcmmc.c
+Auto-merging drivers/mmc/host/davinci_mmc.c
+CONFLICT (content): Merge conflict in drivers/mmc/host/davinci_mmc.c
+Auto-merging drivers/mfd/twl-core.c
+Auto-merging drivers/mfd/db8500-prcmu.c
+CONFLICT (content): Merge conflict in drivers/mfd/db8500-prcmu.c
+Auto-merging drivers/media/platform/soc_camera/pxa_camera.c
+Auto-merging drivers/media/platform/soc_camera/mx3_camera.c
+Auto-merging drivers/media/platform/soc_camera/mx2_camera.c
+Auto-merging drivers/media/platform/soc_camera/mx1_camera.c
+Auto-merging drivers/media/platform/s5p-fimc/mipi-csis.c
+Auto-merging drivers/media/platform/omap3isp/isp.c
+Auto-merging drivers/media/platform/omap/omap_vout.c
+Auto-merging drivers/media/platform/davinci/vpbe_venc.c
+Auto-merging drivers/leds/Makefile
+Auto-merging drivers/leds/Kconfig
+Auto-merging drivers/input/touchscreen/s3c2410_ts.c
+Auto-merging drivers/input/keyboard/omap-keypad.c
+CONFLICT (content): Merge conflict in drivers/input/keyboard/omap-keypad.c
+Auto-merging drivers/i2c/busses/i2c-omap.c
+CONFLICT (content): Merge conflict in drivers/i2c/busses/i2c-omap.c
+Auto-merging drivers/i2c/busses/i2c-imx.c
+Auto-merging drivers/i2c/busses/i2c-davinci.c
+Auto-merging drivers/i2c/busses/Kconfig
+Auto-merging drivers/gpio/gpio-pxa.c
+Auto-merging drivers/gpio/Makefile
+Auto-merging drivers/gpio/Kconfig
+Auto-merging drivers/dma/tegra20-apb-dma.c
+Auto-merging drivers/dma/omap-dma.c
+Auto-merging drivers/dma/mmp_tdma.c
+CONFLICT (content): Merge conflict in drivers/dma/mmp_tdma.c
+Auto-merging drivers/dma/imx-sdma.c
+Auto-merging drivers/dma/imx-dma.c
+Auto-merging drivers/dma/ep93xx_dma.c
+Auto-merging drivers/crypto/ux500/hash/hash_core.c
+Auto-merging drivers/clocksource/Makefile
+CONFLICT (content): Merge conflict in drivers/clocksource/Makefile
+Auto-merging drivers/clk/Makefile
+Auto-merging drivers/bus/omap_l3_noc.c
+Auto-merging drivers/Makefile
+Auto-merging arch/powerpc/sysdev/fsl_msi.c
+Removing arch/arm/plat-spear/include/plat/gpio.h
+Auto-merging arch/arm/plat-samsung/devs.c
+Auto-merging arch/arm/plat-samsung/clock.c
+Auto-merging arch/arm/plat-orion/include/plat/orion-gpio.h
+Removing arch/arm/plat-omap/mux.c
+Auto-merging arch/arm/plat-omap/include/plat/usb.h
+Removing arch/arm/plat-omap/include/plat/param.h
+Removing arch/arm/plat-omap/include/plat/irqs.h
+Removing arch/arm/plat-omap/include/plat/irqs-44xx.h
+Removing arch/arm/plat-omap/include/plat/hardware.h
+Removing arch/arm/plat-omap/include/plat/gpio-switch.h
+Removing arch/arm/plat-omap/include/plat/board.h
+Removing arch/arm/plat-omap/devices.c
+Removing arch/arm/plat-mxc/include/mach/iomux-mx53.h
+Removing arch/arm/plat-mxc/include/mach/gpio.h
+Auto-merging arch/arm/plat-mxc/include/mach/devices-common.h
+Removing arch/arm/plat-mxc/include/mach/clock.h
+Removing arch/arm/plat-mxc/clock.c
+Auto-merging arch/arm/mm/cache-l2x0.c
+CONFLICT (modify/delete): arch/arm/mach-vt8500/wm8505_7in.c deleted in arm-soc/for-next and modified in HEAD. Version HEAD of arch/arm/mach-vt8500/wm8505_7in.c left in tree.
+Removing arch/arm/mach-vt8500/restart.c
+Removing arch/arm/mach-vt8500/include/mach/wm8505_regs.h
+Removing arch/arm/mach-vt8500/include/mach/wm8505_irqs.h
+Removing arch/arm/mach-vt8500/include/mach/vt8500_regs.h
+Removing arch/arm/mach-vt8500/include/mach/vt8500_irqs.h
+Removing arch/arm/mach-vt8500/include/mach/gpio.h
+Removing arch/arm/mach-vt8500/gpio.c
+CONFLICT (modify/delete): arch/arm/mach-vt8500/devices.h deleted in arm-soc/for-next and modified in HEAD. Version HEAD of arch/arm/mach-vt8500/devices.h left in tree.
+CONFLICT (modify/delete): arch/arm/mach-vt8500/devices.c deleted in arm-soc/for-next and modified in HEAD. Version HEAD of arch/arm/mach-vt8500/devices.c left in tree.
+CONFLICT (modify/delete): arch/arm/mach-vt8500/devices-wm8505.c deleted in arm-soc/for-next and modified in HEAD. Version HEAD of arch/arm/mach-vt8500/devices-wm8505.c left in tree.
+CONFLICT (modify/delete): arch/arm/mach-vt8500/devices-vt8500.c deleted in arm-soc/for-next and modified in HEAD. Version HEAD of arch/arm/mach-vt8500/devices-vt8500.c left in tree.
+Auto-merging arch/arm/mach-vt8500/common.h
+CONFLICT (modify/delete): arch/arm/mach-vt8500/bv07.c deleted in arm-soc/for-next and modified in HEAD. Version HEAD of arch/arm/mach-vt8500/bv07.c left in tree.
+Removing arch/arm/mach-vt8500/Kconfig
+Removing arch/arm/mach-vexpress/include/mach/uncompress.h
+Removing arch/arm/mach-vexpress/include/mach/timex.h
+Removing arch/arm/mach-vexpress/include/mach/gpio.h
+Auto-merging arch/arm/mach-vexpress/ct-ca9x4.c
+Removing arch/arm/mach-vexpress/Makefile.boot
+Removing arch/arm/mach-versatile/include/mach/gpio.h
+Removing arch/arm/mach-ux500/include/mach/gpio.h
+Auto-merging arch/arm/mach-ux500/cpu-db8500.c
+CONFLICT (content): Merge conflict in arch/arm/mach-ux500/cpu-db8500.c
+Removing arch/arm/mach-ux500/clock.h
+Removing arch/arm/mach-ux500/clock.c
+Removing arch/arm/mach-ux500/board-mop500-msp.h
+Auto-merging arch/arm/mach-ux500/board-mop500-audio.c
+Removing arch/arm/mach-u300/u300.c
+Removing arch/arm/mach-u300/include/mach/platform.h
+Removing arch/arm/mach-u300/include/mach/gpio.h
+Removing arch/arm/mach-u300/include/mach/clkdev.h
+Auto-merging arch/arm/mach-u300/i2c.c
+Auto-merging arch/arm/mach-u300/dma_channels.h
+Auto-merging arch/arm/mach-u300/core.c
+Removing arch/arm/mach-tegra/tegra2_clocks.c
+Auto-merging arch/arm/mach-tegra/pcie.c
+Removing arch/arm/mach-tegra/include/mach/suspend.h
+Removing arch/arm/mach-tegra/include/mach/pinconf-tegra.h
+Removing arch/arm/mach-tegra/include/mach/io.h
+Removing arch/arm/mach-tegra/include/mach/gpio.h
+Removing arch/arm/mach-tegra/dma.c
+Removing arch/arm/mach-tegra/devices.h
+CONFLICT (modify/delete): arch/arm/mach-tegra/devices.c deleted in arm-soc/for-next and modified in HEAD. Version HEAD of arch/arm/mach-tegra/devices.c left in tree.
+Removing arch/arm/mach-tegra/board-trimslice.h
+Removing arch/arm/mach-tegra/board-trimslice.c
+Removing arch/arm/mach-tegra/board-trimslice-pinmux.c
+Removing arch/arm/mach-tegra/board-pinmux.h
+Removing arch/arm/mach-tegra/board-pinmux.c
+Removing arch/arm/mach-tegra/board-paz00-pinmux.c
+Removing arch/arm/mach-tegra/board-harmony.h
+Removing arch/arm/mach-tegra/board-harmony.c
+Removing arch/arm/mach-tegra/board-harmony-power.c
+Removing arch/arm/mach-tegra/board-harmony-pinmux.c
+Removing arch/arm/mach-spear6xx/include/mach/gpio.h
+Removing arch/arm/mach-spear3xx/include/mach/gpio.h
+Removing arch/arm/mach-spear13xx/include/mach/gpio.h
+Removing arch/arm/mach-socfpga/include/mach/uncompress.h
+Removing arch/arm/mach-socfpga/Makefile.boot
+Auto-merging arch/arm/mach-shmobile/smp-emev2.c
+Auto-merging arch/arm/mach-shmobile/sh-gpio.h
+Auto-merging arch/arm/mach-shmobile/pm-sh7372.c
+Auto-merging arch/arm/mach-shmobile/pm-rmobile.c
+Auto-merging arch/arm/mach-shmobile/include/mach/r8a7779.h
+Auto-merging arch/arm/mach-shmobile/include/mach/common.h
+CONFLICT (content): Merge conflict in arch/arm/mach-shmobile/include/mach/common.h
+Auto-merging arch/arm/mach-shmobile/board-mackerel.c
+Auto-merging arch/arm/mach-shmobile/board-kzm9g.c
+Auto-merging arch/arm/mach-shmobile/board-armadillo800eva.c
+Auto-merging arch/arm/mach-shmobile/board-ap4evb.c
+Removing arch/arm/mach-shark/include/mach/io.h
+Removing arch/arm/mach-sa1100/leds.h
+Removing arch/arm/mach-sa1100/leds.c
+Removing arch/arm/mach-sa1100/leds-lart.c
+Removing arch/arm/mach-sa1100/leds-hackkit.c
+Removing arch/arm/mach-sa1100/leds-cerf.c
+Removing arch/arm/mach-sa1100/leds-badge4.c
+Removing arch/arm/mach-sa1100/leds-assabet.c
+Auto-merging arch/arm/mach-s5pv210/mach-smdkv210.c
+Auto-merging arch/arm/mach-s5pv210/mach-goni.c
+Auto-merging arch/arm/mach-s5pc100/mach-smdkc100.c
+Auto-merging arch/arm/mach-s5p64x0/mach-smdk6450.c
+Auto-merging arch/arm/mach-s5p64x0/mach-smdk6440.c
+Auto-merging arch/arm/mach-s3c64xx/mach-smdk6410.c
+Auto-merging arch/arm/mach-s3c64xx/mach-real6410.c
+CONFLICT (content): Merge conflict in arch/arm/mach-s3c64xx/mach-real6410.c
+Auto-merging arch/arm/mach-s3c64xx/mach-ncp.c
+Auto-merging arch/arm/mach-s3c64xx/mach-mini6410.c
+CONFLICT (content): Merge conflict in arch/arm/mach-s3c64xx/mach-mini6410.c
+Auto-merging arch/arm/mach-s3c64xx/mach-hmt.c
+Auto-merging arch/arm/mach-s3c64xx/mach-crag6410.c
+Auto-merging arch/arm/mach-s3c64xx/mach-anw6410.c
+Auto-merging arch/arm/mach-s3c24xx/mach-smdk2416.c
+Auto-merging arch/arm/mach-realview/realview_pbx.c
+Auto-merging arch/arm/mach-realview/realview_pba8.c
+Auto-merging arch/arm/mach-realview/realview_pb11mp.c
+Auto-merging arch/arm/mach-realview/realview_pb1176.c
+Auto-merging arch/arm/mach-realview/realview_eb.c
+Removing arch/arm/mach-realview/include/mach/gpio.h
+Removing arch/arm/mach-realview/include/mach/clkdev.h
+Auto-merging arch/arm/mach-pxa/stargate2.c
+Auto-merging arch/arm/mach-pxa/sharpsl_pm.c
+Removing arch/arm/mach-pxa/leds.h
+Removing arch/arm/mach-pxa/leds.c
+Removing arch/arm/mach-pxa/leds-mainstone.c
+Removing arch/arm/mach-pxa/leds-lubbock.c
+Removing arch/arm/mach-pxa/leds-idp.c
+Auto-merging arch/arm/mach-pxa/devices.c
+Auto-merging arch/arm/mach-prima2/common.c
+Removing arch/arm/mach-prima2/clock.c
+Removing arch/arm/mach-pnx4008/time.h
+Removing arch/arm/mach-pnx4008/time.c
+Removing arch/arm/mach-pnx4008/sleep.S
+Removing arch/arm/mach-pnx4008/serial.c
+Removing arch/arm/mach-pnx4008/pm.c
+Removing arch/arm/mach-pnx4008/irq.c
+Removing arch/arm/mach-pnx4008/include/mach/uncompress.h
+Removing arch/arm/mach-pnx4008/include/mach/timex.h
+Removing arch/arm/mach-pnx4008/include/mach/pm.h
+Removing arch/arm/mach-pnx4008/include/mach/platform.h
+Removing arch/arm/mach-pnx4008/include/mach/irqs.h
+Removing arch/arm/mach-pnx4008/include/mach/irq.h
+Removing arch/arm/mach-pnx4008/include/mach/hardware.h
+Removing arch/arm/mach-pnx4008/include/mach/gpio-pnx4008.h
+Removing arch/arm/mach-pnx4008/include/mach/entry-macro.S
+Removing arch/arm/mach-pnx4008/include/mach/dma.h
+Removing arch/arm/mach-pnx4008/include/mach/debug-macro.S
+Removing arch/arm/mach-pnx4008/include/mach/clock.h
+Removing arch/arm/mach-pnx4008/i2c.c
+Removing arch/arm/mach-pnx4008/gpio.c
+Removing arch/arm/mach-pnx4008/dma.c
+Removing arch/arm/mach-pnx4008/core.c
+Removing arch/arm/mach-pnx4008/clock.h
+Removing arch/arm/mach-pnx4008/clock.c
+Removing arch/arm/mach-pnx4008/Makefile.boot
+Removing arch/arm/mach-pnx4008/Makefile
+Removing arch/arm/mach-picoxcell/include/mach/uncompress.h
+Removing arch/arm/mach-picoxcell/include/mach/timex.h
+Removing arch/arm/mach-picoxcell/include/mach/picoxcell_soc.h
+Removing arch/arm/mach-picoxcell/include/mach/gpio.h
+Removing arch/arm/mach-picoxcell/Makefile.boot
+Removing arch/arm/mach-orion5x/include/mach/io.h
+Removing arch/arm/mach-orion5x/include/mach/gpio.h
+Auto-merging arch/arm/mach-omap2/usb-host.c
+Auto-merging arch/arm/mach-omap2/twl-common.h
+Auto-merging arch/arm/mach-omap2/twl-common.c
+Auto-merging arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+Auto-merging arch/arm/mach-omap2/omap44xx.h
+Auto-merging arch/arm/mach-omap2/omap4-keypad.h
+Auto-merging arch/arm/mach-omap2/omap34xx.h
+Auto-merging arch/arm/mach-omap2/omap24xx.h
+Auto-merging arch/arm/mach-omap2/mcbsp.c
+Removing arch/arm/mach-omap2/include/mach/smp.h
+Auto-merging arch/arm/mach-omap2/devices.c
+Auto-merging arch/arm/mach-omap2/board-zoom-peripherals.c
+Auto-merging arch/arm/mach-omap2/board-rx51-peripherals.c
+CONFLICT (content): Merge conflict in arch/arm/mach-omap2/board-rx51-peripherals.c
+Auto-merging arch/arm/mach-omap2/board-overo.c
+Auto-merging arch/arm/mach-omap2/board-omap4panda.c
+Auto-merging arch/arm/mach-omap2/board-omap3evm.c
+Auto-merging arch/arm/mach-omap2/board-omap3beagle.c
+Auto-merging arch/arm/mach-omap2/board-igep0020.c
+Auto-merging arch/arm/mach-omap2/board-devkit8000.c
+Auto-merging arch/arm/mach-omap2/board-cm-t35.c
+Auto-merging arch/arm/mach-omap2/board-am3517evm.c
+Auto-merging arch/arm/mach-omap2/board-4430sdp.c
+Removing arch/arm/mach-omap1/leds.h
+Removing arch/arm/mach-omap1/leds.c
+Removing arch/arm/mach-omap1/leds-osk.c
+Removing arch/arm/mach-omap1/leds-innovator.c
+Removing arch/arm/mach-omap1/leds-h2p2-debug.c
+Removing arch/arm/mach-omap1/include/mach/smp.h
+Auto-merging arch/arm/mach-omap1/include/mach/omap7xx.h
+Auto-merging arch/arm/mach-omap1/include/mach/omap16xx.h
+Auto-merging arch/arm/mach-omap1/include/mach/omap1510.h
+Removing arch/arm/mach-nomadik/include/mach/gpio.h
+Auto-merging arch/arm/mach-nomadik/board-nhk8815.c
+Removing arch/arm/mach-mxs/module-tx28.h
+Removing arch/arm/mach-mxs/module-tx28.c
+Removing arch/arm/mach-mxs/mach-tx28.c
+Removing arch/arm/mach-mxs/mach-stmp378x_devb.c
+Auto-merging arch/arm/mach-mxs/mach-mxs.c
+Removing arch/arm/mach-mxs/mach-mx28evk.c
+Removing arch/arm/mach-mxs/mach-mx23evk.c
+Removing arch/arm/mach-mxs/mach-m28evk.c
+Removing arch/arm/mach-mxs/mach-apx4devkit.c
+Removing arch/arm/mach-mxs/iomux.c
+Removing arch/arm/mach-mxs/include/mach/irqs.h
+Removing arch/arm/mach-mxs/include/mach/iomux.h
+Removing arch/arm/mach-mxs/include/mach/iomux-mx28.h
+Removing arch/arm/mach-mxs/include/mach/iomux-mx23.h
+Removing arch/arm/mach-mxs/include/mach/gpio.h
+Removing arch/arm/mach-mxs/include/mach/entry-macro.S
+Removing arch/arm/mach-mxs/include/mach/devices-common.h
+Removing arch/arm/mach-mxs/devices/platform-rtc-stmp3xxx.c
+Removing arch/arm/mach-mxs/devices/platform-mxsfb.c
+Removing arch/arm/mach-mxs/devices/platform-mxs-saif.c
+Removing arch/arm/mach-mxs/devices/platform-mxs-pwm.c
+Removing arch/arm/mach-mxs/devices/platform-mxs-mmc.c
+Removing arch/arm/mach-mxs/devices/platform-mxs-i2c.c
+Removing arch/arm/mach-mxs/devices/platform-gpmi-nand.c
+Removing arch/arm/mach-mxs/devices/platform-gpio-mxs.c
+Removing arch/arm/mach-mxs/devices/platform-flexcan.c
+Removing arch/arm/mach-mxs/devices/platform-fec.c
+Removing arch/arm/mach-mxs/devices/platform-dma.c
+Removing arch/arm/mach-mxs/devices/platform-auart.c
+Removing arch/arm/mach-mxs/devices/Makefile
+Removing arch/arm/mach-mxs/devices/Kconfig
+Removing arch/arm/mach-mxs/devices.c
+Removing arch/arm/mach-mxs/devices-mx28.h
+Removing arch/arm/mach-mxs/devices-mx23.h
+Removing arch/arm/mach-mvebu/include/mach/uncompress.h
+Removing arch/arm/mach-mvebu/include/mach/timex.h
+Auto-merging arch/arm/mach-mvebu/armada-370-xp.h
+Removing arch/arm/mach-mvebu/Makefile.boot
+Removing arch/arm/mach-mv78xx0/include/mach/io.h
+Removing arch/arm/mach-msm/include/mach/system.h
+Removing arch/arm/mach-msm/include/mach/gpio.h
+Removing arch/arm/mach-msm/idle.c
+Removing arch/arm/mach-msm/devices-msm8960.c
+Removing arch/arm/mach-msm/board-msm8x60.c
+Removing arch/arm/mach-msm/board-msm8960.c
+Removing arch/arm/mach-msm/board-msm7x27.c
+Removing arch/arm/mach-msm/acpuclock.h
+Removing arch/arm/mach-msm/acpuclock-arm11.c
+Removing arch/arm/mach-ks8695/leds.c
+Removing arch/arm/mach-ks8695/include/mach/regs-timer.h
+Removing arch/arm/mach-kirkwood/include/mach/io.h
+Removing arch/arm/mach-kirkwood/include/mach/gpio.h
+Removing arch/arm/mach-ixp4xx/include/mach/gpio.h
+Removing arch/arm/mach-iop33x/include/mach/io.h
+Removing arch/arm/mach-iop32x/include/mach/io.h
+Removing arch/arm/mach-iop13xx/include/mach/io.h
+Auto-merging arch/arm/mach-integrator/integrator_cp.c
+CONFLICT (content): Merge conflict in arch/arm/mach-integrator/integrator_cp.c
+Auto-merging arch/arm/mach-integrator/integrator_ap.c
+Removing arch/arm/mach-integrator/include/mach/io.h
+Auto-merging arch/arm/mach-integrator/core.c
+Removing arch/arm/mach-imx/mx51_efika.c
+Removing arch/arm/mach-imx/mach-mx53_smd.c
+Removing arch/arm/mach-imx/mach-mx53_loco.c
+Removing arch/arm/mach-imx/mach-mx53_evk.c
+Removing arch/arm/mach-imx/mach-mx53_ard.c
+Removing arch/arm/mach-imx/mach-mx51_efikasb.c
+Removing arch/arm/mach-imx/mach-mx51_efikamx.c
+Auto-merging arch/arm/mach-imx/mach-imx6q.c
+Auto-merging arch/arm/mach-imx/mach-imx53.c
+Removing arch/arm/mach-imx/efika.h
+Removing arch/arm/mach-imx/devices-imx53.h
+Auto-merging arch/arm/mach-imx/clk-imx51-imx53.c
+CONFLICT (content): Merge conflict in arch/arm/mach-imx/clk-imx51-imx53.c
+Auto-merging arch/arm/mach-imx/Kconfig
+Removing arch/arm/mach-highbank/include/mach/uncompress.h
+Removing arch/arm/mach-highbank/include/mach/timex.h
+Removing arch/arm/mach-highbank/include/mach/gpio.h
+Removing arch/arm/mach-highbank/Makefile.boot
+Removing arch/arm/mach-footbridge/netwinder-leds.c
+Removing arch/arm/mach-footbridge/ebsa285-leds.c
+Auto-merging arch/arm/mach-exynos/platsmp.c
+Auto-merging arch/arm/mach-exynos/mach-universal_c210.c
+Auto-merging arch/arm/mach-exynos/mach-smdkv310.c
+Auto-merging arch/arm/mach-exynos/mach-smdk4x12.c
+Auto-merging arch/arm/mach-exynos/mach-origen.c
+Auto-merging arch/arm/mach-exynos/mach-nuri.c
+Removing arch/arm/mach-dove/include/mach/io.h
+Removing arch/arm/mach-dove/include/mach/gpio.h
+Auto-merging arch/arm/mach-davinci/include/mach/da8xx.h
+CONFLICT (content): Merge conflict in arch/arm/mach-davinci/include/mach/da8xx.h
+Auto-merging arch/arm/mach-davinci/dm365.c
+CONFLICT (content): Merge conflict in arch/arm/mach-davinci/dm365.c
+Auto-merging arch/arm/mach-davinci/dm355.c
+CONFLICT (content): Merge conflict in arch/arm/mach-davinci/dm355.c
+Auto-merging arch/arm/mach-davinci/devices.c
+Auto-merging arch/arm/mach-davinci/davinci.h
+CONFLICT (content): Merge conflict in arch/arm/mach-davinci/davinci.h
+Removing arch/arm/mach-clps711x/p720t-leds.c
+Auto-merging arch/arm/mach-bcmring/include/mach/csp/tmrHw.h
+Auto-merging arch/arm/mach-bcmring/include/mach/csp/reg.h
+Auto-merging arch/arm/mach-bcmring/include/mach/csp/dmacHw.h
+Auto-merging arch/arm/mach-bcmring/include/mach/cfg_global.h
+Removing arch/arm/mach-bcmring/include/csp/string.h
+Removing arch/arm/mach-bcmring/include/csp/stdint.h
+Removing arch/arm/mach-bcmring/include/csp/secHw.h
+Removing arch/arm/mach-bcmring/include/csp/module.h
+Removing arch/arm/mach-bcmring/include/csp/intcHw.h
+Removing arch/arm/mach-bcmring/include/csp/errno.h
+Removing arch/arm/mach-bcmring/include/csp/delay.h
+Removing arch/arm/mach-bcmring/include/csp/cache.h
+Removing arch/arm/mach-bcmring/include/cfg_global.h
+Auto-merging arch/arm/mach-bcmring/arch.c
+Auto-merging arch/arm/mach-bcm2835/include/mach/timex.h
+Auto-merging arch/arm/mach-bcm2835/include/mach/bcm2835_soc.h
+Auto-merging arch/arm/mach-at91/at91sam9rl_devices.c
+Auto-merging arch/arm/mach-at91/at91sam9g45_devices.c
+Auto-merging arch/arm/mach-at91/at91sam9263_devices.c
+Auto-merging arch/arm/mach-at91/at91sam9263.c
+Auto-merging arch/arm/mach-at91/at91sam9261_devices.c
+Auto-merging arch/arm/mach-at91/at91sam9260_devices.c
+Auto-merging arch/arm/mach-at91/at91rm9200_devices.c
+Auto-merging arch/arm/kernel/smp.c
+Auto-merging arch/arm/kernel/setup.c
+Removing arch/arm/kernel/leds.c
+Auto-merging arch/arm/kernel/bios32.c
+Auto-merging arch/arm/kernel/Makefile
+Auto-merging arch/arm/include/debug/picoxcell.S
+Auto-merging arch/arm/include/debug/mvebu.S
+Auto-merging arch/arm/include/debug/highbank.S
+Auto-merging arch/arm/include/asm/timex.h
+Removing arch/arm/include/asm/leds.h
+Auto-merging arch/arm/include/asm/io.h
+Removing arch/arm/configs/pnx4008_defconfig
+Auto-merging arch/arm/configs/kzm9g_defconfig
+Removing arch/arm/boot/dts/tegra30-cardhu.dts
+Removing arch/arm/boot/dts/prima2-cb.dts
+Auto-merging arch/arm/boot/dts/omap3-beagle-xm.dts
+Auto-merging arch/arm/boot/dts/imx6q.dtsi
+Auto-merging arch/arm/boot/dts/imx53.dtsi
+Auto-merging arch/arm/boot/dts/imx51.dtsi
+Auto-merging arch/arm/boot/dts/dbx5x0.dtsi
+Auto-merging arch/arm/Makefile
+Auto-merging arch/arm/Kconfig
+Auto-merging MRecorded preimage for 'drivers/mfd/db8500-prcmu.c'
+Resolved 'Documentation/devicetree/bindings/usb/platform-uhci.txt' using previous resolution.
+Resolved 'arch/arm/mach-davinci/davinci.h' using previous resolution.
+Resolved 'arch/arm/mach-davinci/dm355.c' using previous resolution.
+Resolved 'arch/arm/mach-davinci/dm365.c' using previous resolution.
+Resolved 'arch/arm/mach-davinci/include/mach/da8xx.h' using previous resolution.
+Resolved 'arch/arm/mach-imx/clk-imx51-imx53.c' using previous resolution.
+Resolved 'arch/arm/mach-integrator/integrator_cp.c' using previous resolution.
+Resolved 'arch/arm/mach-omap2/board-rx51-peripherals.c' using previous resolution.
+Resolved 'arch/arm/mach-s3c64xx/mach-mini6410.c' using previous resolution.
+Resolved 'arch/arm/mach-s3c64xx/mach-real6410.c' using previous resolution.
+Resolved 'arch/arm/mach-shmobile/include/mach/common.h' using previous resolution.
+Resolved 'arch/arm/mach-ux500/cpu-db8500.c' using previous resolution.
+Resolved 'drivers/clocksource/Makefile' using previous resolution.
+Resolved 'drivers/dma/mmp_tdma.c' using previous resolution.
+Resolved 'drivers/i2c/busses/i2c-omap.c' using previous resolution.
+Resolved 'drivers/input/keyboard/omap-keypad.c' using previous resolution.
+Resolved 'drivers/mmc/host/davinci_mmc.c' using previous resolution.
+Resolved 'drivers/mmc/host/omap.c' using previous resolution.
+Resolved 'drivers/mtd/nand/Kconfig' using previous resolution.
+Resolved 'drivers/mtd/nand/orion_nand.c' using previous resolution.
+Resolved 'drivers/spi/spi-davinci.c' using previous resolution.
+Resolved 'drivers/staging/tidspbridge/core/wdt.c' using previous resolution.
+Resolved 'drivers/usb/host/Kconfig' using previous resolution.
+Resolved 'drivers/video/msm/mddi.c' using previous resolution.
+Resolved 'drivers/video/msm/mdp.c' using previous resolution.
+Resolved 'drivers/video/omap/lcd_ams_delta.c' using previous resolution.
+Resolved 'drivers/video/omap2/dss/dispc.c' using previous resolution.
+Resolved 'drivers/w1/masters/omap_hdq.c' using previous resolution.
+Resolved 'sound/soc/omap/omap-mcbsp.c' using previous resolution.
+Resolved 'sound/soc/omap/omap-pcm.c' using previous resolution.
+AINTAINERS
+Auto-merging Documentation/devicetree/bindings/usb/platform-uhci.txt
+CONFLICT (add/add): Merge conflict in Documentation/devicetree/bindings/usb/platform-uhci.txt
+Automatic merge failed; fix conflicts and then commit the result.
+$ git rm -f sound/soc/omap/igep0020.c sound/soc/omap/omap3beagle.c sound/soc/omap/omap3evm.c sound/soc/omap/overo.c
+sound/soc/omap/igep0020.c: needs merge
+sound/soc/omap/omap3beagle.c: needs merge
+sound/soc/omap/omap3evm.c: needs merge
+sound/soc/omap/overo.c: needs merge
+rm 'sound/soc/omap/igep0020.c'
+rm 'sound/soc/omap/omap3beagle.c'
+rm 'sound/soc/omap/omap3evm.c'
+rm 'sound/soc/omap/overo.c'
+$ git rm -f arch/arm/mach-tegra/devices.c
+arch/arm/mach-tegra/devices.c: needs merge
+rm 'arch/arm/mach-tegra/devices.c'
+$ git rm -f drivers/mtd/nand/bcm_umi_nand.c drivers/mtd/nand/nand_bcm_umi.h
+drivers/mtd/nand/bcm_umi_nand.c: needs merge
+drivers/mtd/nand/nand_bcm_umi.h: needs merge
+rm 'drivers/mtd/nand/bcm_umi_nand.c'
+rm 'drivers/mtd/nand/nand_bcm_umi.h'
+$ git rm -f arch/arm/mach-vt8500/bv07.c arch/arm/mach-vt8500/devices-vt8500.c arch/arm/mach-vt8500/devices-wm8505.c arch/arm/mach-vt8500/devices.c arch/arm/mach-vt8500/devices.h arch/arm/mach-vt8500/wm8505_7in.c
+arch/arm/mach-vt8500/bv07.c: needs merge
+arch/arm/mach-vt8500/devices-vt8500.c: needs merge
+arch/arm/mach-vt8500/devices-wm8505.c: needs merge
+arch/arm/mach-vt8500/devices.c: needs merge
+arch/arm/mach-vt8500/devices.h: needs merge
+arch/arm/mach-vt8500/wm8505_7in.c: needs merge
+rm 'arch/arm/mach-vt8500/bv07.c'
+rm 'arch/arm/mach-vt8500/devices-vt8500.c'
+rm 'arch/arm/mach-vt8500/devices-wm8505.c'
+rm 'arch/arm/mach-vt8500/devices.c'
+rm 'arch/arm/mach-vt8500/devices.h'
+rm 'arch/arm/mach-vt8500/wm8505_7in.c'
+$ git commit -v -a
+Recorded resolution for 'drivers/mfd/db8500-prcmu.c'.
+Recorded resolution for 'drivers/video/msm/mdp_hw.h'.
+[master 90cbdf0] Merge remote-tracking branch 'arm-soc/for-next'
+$ git diff -M --stat --summary HEAD^..
+ Documentation/arm/Marvell/README                   |  232 ++
+ Documentation/arm/Samsung-S3C24XX/GPIO.txt         |   82 +-
+ Documentation/arm/Samsung/GPIO.txt                 |    8 +-
+ Documentation/arm/memory.txt                       |    3 +
+ Documentation/devicetree/bindings/arm/bcm2835.txt  |    8 +
+ .../devicetree/bindings/arm/mrvl/tauros2.txt       |   17 +
+ .../devicetree/bindings/arm/msm/timer.txt          |   38 +
+ .../devicetree/bindings/arm/omap/omap.txt          |    3 +
+ Documentation/devicetree/bindings/arm/vt8500.txt   |   14 +
+ .../bindings/arm/vt8500/via,vt8500-intc.txt        |   16 +
+ .../bindings/arm/vt8500/via,vt8500-pmc.txt         |   13 +
+ .../bindings/arm/vt8500/via,vt8500-timer.txt       |   15 +
+ .../devicetree/bindings/bus/omap-ocp2scp.txt       |   10 +
+ .../devicetree/bindings/clock/imx23-clock.txt      |   76 +
+ .../devicetree/bindings/clock/imx28-clock.txt      |   99 +
+ .../devicetree/bindings/clock/imx6q-clock.txt      |  222 ++
+ Documentation/devicetree/bindings/clock/vt8500.txt |   72 +
+ .../devicetree/bindings/crypto/mv_cesa.txt         |   20 +
+ .../devicetree/bindings/gpio/gpio-fan.txt          |   25 +
+ .../devicetree/bindings/gpio/gpio-mvebu.txt        |   53 +
+ .../devicetree/bindings/gpio/gpio-samsung.txt      |   43 +
+ .../devicetree/bindings/gpio/gpio-twl4030.txt      |    6 +
+ .../devicetree/bindings/gpio/gpio-vt8500.txt       |   24 +
+ .../devicetree/bindings/i2c/trivial-devices.txt    |    1 +
+ .../brcm,bcm2835-armctrl-ic.txt                    |  110 +
+ .../devicetree/bindings/lpddr2/lpddr2-timings.txt  |   52 +
+ .../devicetree/bindings/lpddr2/lpddr2.txt          |  102 +
+ .../devicetree/bindings/media/exynos5-gsc.txt      |   30 +
+ .../bindings/memory-controllers/ti/emif.txt        |   55 +
+ Documentation/devicetree/bindings/mfd/ab8500.txt   |   15 +
+ .../devicetree/bindings/mtd/pxa3xx-nand.txt        |   31 +
+ .../pinctrl/marvell,armada-370-pinctrl.txt         |   95 +
+ .../bindings/pinctrl/marvell,armada-xp-pinctrl.txt |  100 +
+ .../bindings/pinctrl/marvell,dove-pinctrl.txt      |   72 +
+ .../bindings/pinctrl/marvell,kirkwood-pinctrl.txt  |  279 ++
+ .../bindings/pinctrl/marvell,mvebu-pinctrl.txt     |   46 +
+ .../bindings/pinctrl/samsung-pinctrl.txt           |  196 ++
+ Documentation/devicetree/bindings/rtc/pxa-rtc.txt  |   14 +
+ .../devicetree/bindings/rtc/via,vt8500-rtc.txt     |   15 +
+ .../bindings/timer/brcm,bcm2835-system-timer.txt   |   22 +
+ .../bindings/tty/serial/via,vt8500-uart.txt        |   17 +
+ .../devicetree/bindings/usb/platform-uhci.txt      |   21 +-
+ .../devicetree/bindings/usb/via,vt8500-ehci.txt    |   15 +
+ .../devicetree/bindings/vendor-prefixes.txt        |    3 +
+ .../devicetree/bindings/video/via,vt8500-fb.txt    |   62 +
+ .../devicetree/bindings/video/wm,prizm-ge-rops.txt |   13 +
+ .../devicetree/bindings/video/wm,wm8505-fb.txt     |   23 +
+ Documentation/spi/ep93xx_spi                       |    2 +-
+ MAINTAINERS                                        |   20 +-
+ arch/arm/Kconfig                                   |  304 +-
+ arch/arm/Kconfig.debug                             |   47 +
+ arch/arm/Makefile                                  |  150 +-
+ arch/arm/arm-soc-for-next-contents.txt             |  155 +
+ arch/arm/boot/Makefile                             |    2 +
+ arch/arm/boot/compressed/misc.c                    |    6 +
+ arch/arm/boot/dts/Makefile                         |  106 +
+ arch/arm/boot/dts/am335x-bone.dts                  |   60 +
+ arch/arm/boot/dts/am335x-evm.dts                   |  100 +
+ arch/arm/boot/dts/am33xx.dtsi                      |   71 +-
+ arch/arm/boot/dts/armada-370-xp.dtsi               |    5 +
+ arch/arm/boot/dts/armada-370.dtsi                  |   44 +
+ arch/arm/boot/dts/armada-xp-db.dts                 |    4 +-
+ arch/arm/boot/dts/armada-xp-mv78230.dtsi           |   57 +
+ arch/arm/boot/dts/armada-xp-mv78260.dtsi           |   70 +
+ arch/arm/boot/dts/armada-xp-mv78460.dtsi           |   70 +
+ arch/arm/boot/dts/bcm2835-rpi-b.dts                |   12 +
+ arch/arm/boot/dts/bcm2835.dtsi                     |   39 +
+ arch/arm/boot/dts/{db8500.dtsi => dbx5x0.dtsi}     |   71 +-
+ arch/arm/boot/dts/dove-cm-a510.dts                 |   38 +
+ arch/arm/boot/dts/dove-cubox.dts                   |   42 +
+ arch/arm/boot/dts/dove-dove-db.dts                 |   38 +
+ arch/arm/boot/dts/dove.dtsi                        |  143 +
+ arch/arm/boot/dts/ea3250.dts                       |  109 +-
+ arch/arm/boot/dts/elpida_ecb240abacn.dtsi          |   67 +
+ arch/arm/boot/dts/exynos4210-origen.dts            |   18 +-
+ arch/arm/boot/dts/exynos4210-pinctrl.dtsi          |  457 +++
+ arch/arm/boot/dts/exynos4210.dtsi                  |   37 +
+ arch/arm/boot/dts/exynos5250.dtsi                  |   28 +
+ arch/arm/boot/dts/hrefv60plus.dts                  |   95 +
+ arch/arm/boot/dts/imx23-evk.dts                    |    3 +-
+ arch/arm/boot/dts/imx23-olinuxino.dts              |   57 +
+ arch/arm/boot/dts/imx23-stmp378x_devb.dts          |    2 +-
+ arch/arm/boot/dts/imx23.dtsi                       |   43 +-
+ arch/arm/boot/dts/imx27-phytec-phycore.dts         |    6 +-
+ arch/arm/boot/dts/imx27.dtsi                       |    1 -
+ arch/arm/boot/dts/imx28-apx4devkit.dts             |    2 +-
+ arch/arm/boot/dts/imx28-cfa10049.dts               |   99 +
+ arch/arm/boot/dts/imx28-evk.dts                    |   29 +-
+ arch/arm/boot/dts/imx28-m28evk.dts                 |   83 +-
+ arch/arm/boot/dts/imx28-tx28.dts                   |   23 +-
+ arch/arm/boot/dts/imx28.dtsi                       |  128 +-
+ arch/arm/boot/dts/imx51-babbage.dts                |   44 +-
+ arch/arm/boot/dts/imx51.dtsi                       |  146 +-
+ arch/arm/boot/dts/imx53-ard.dts                    |   59 +-
+ arch/arm/boot/dts/imx53-evk.dts                    |   39 +-
+ arch/arm/boot/dts/imx53-qsb.dts                    |   42 +-
+ arch/arm/boot/dts/imx53-smd.dts                    |   46 +-
+ arch/arm/boot/dts/imx53.dtsi                       |  199 +-
+ arch/arm/boot/dts/imx6q-arm2.dts                   |   21 +
+ arch/arm/boot/dts/imx6q-sabrelite.dts              |   31 +-
+ arch/arm/boot/dts/imx6q-sabresd.dts                |   25 +-
+ arch/arm/boot/dts/imx6q.dtsi                       |  316 +-
+ arch/arm/boot/dts/kirkwood-dnskw.dtsi              |   10 +
+ arch/arm/boot/dts/kirkwood-dockstar.dts            |   57 +
+ arch/arm/boot/dts/kirkwood-iconnect.dts            |   50 +-
+ arch/arm/boot/dts/kirkwood-iomega_ix2_200.dts      |  105 +
+ arch/arm/boot/dts/kirkwood-km_kirkwood.dts         |   29 +
+ arch/arm/boot/dts/kirkwood.dtsi                    |   12 +-
+ arch/arm/boot/dts/mmp2.dtsi                        |    5 +
+ arch/arm/boot/dts/msm8660-surf.dts                 |   19 +-
+ arch/arm/boot/dts/msm8960-cdp.dts                  |   41 +
+ arch/arm/boot/dts/omap2420-h4.dts                  |    2 +-
+ arch/arm/boot/dts/omap2420.dtsi                    |   48 +
+ arch/arm/boot/dts/omap2430.dtsi                    |   92 +
+ .../dts/{omap3-beagle.dts => omap3-beagle-xm.dts}  |   54 +-
+ arch/arm/boot/dts/omap3-evm.dts                    |   13 +
+ arch/arm/boot/dts/omap3-overo.dtsi                 |   57 +
+ arch/arm/boot/dts/omap3-tobi.dts                   |   35 +
+ arch/arm/boot/dts/omap3.dtsi                       |   94 +-
+ arch/arm/boot/dts/omap36xx.dtsi                    |   25 +
+ arch/arm/boot/dts/omap4-panda.dts                  |   11 +
+ arch/arm/boot/dts/omap4-sdp.dts                    |  127 +-
+ arch/arm/boot/dts/omap4.dtsi                       |  203 +-
+ arch/arm/boot/dts/omap5-evm.dts                    |   64 +
+ arch/arm/boot/dts/omap5.dtsi                       |  127 +
+ arch/arm/boot/dts/phy3250.dts                      |    4 +-
+ arch/arm/boot/dts/prima2-cb.dts                    |  424 ---
+ arch/arm/boot/dts/prima2-evb.dts                   |   37 +
+ arch/arm/boot/dts/prima2.dtsi                      |  640 ++++
+ arch/arm/boot/dts/pxa27x.dtsi                      |   14 +
+ arch/arm/boot/dts/pxa2xx.dtsi                      |  132 +
+ arch/arm/boot/dts/pxa3xx.dtsi                      |   32 +
+ arch/arm/boot/dts/pxa910.dtsi                      |    5 +
+ arch/arm/boot/dts/snowball.dts                     |   19 +-
+ arch/arm/boot/dts/tegra20-harmony.dts              |  220 ++
+ arch/arm/boot/dts/tegra20-medcom-wide.dts          |   58 +
+ arch/arm/boot/dts/tegra20-paz00.dts                |  173 +
+ arch/arm/boot/dts/tegra20-plutux.dts               |   50 +
+ arch/arm/boot/dts/tegra20-seaboard.dts             |  186 ++
+ arch/arm/boot/dts/tegra20-tamonten.dtsi            |  449 +++
+ arch/arm/boot/dts/tegra20-tec.dts                  |   53 +
+ arch/arm/boot/dts/tegra20-ventana.dts              |  206 ++
+ arch/arm/boot/dts/tegra20-whistler.dts             |  295 ++
+ arch/arm/boot/dts/tegra20.dtsi                     |    2 +-
+ arch/arm/boot/dts/tegra30-cardhu-a02.dts           |   87 +
+ arch/arm/boot/dts/tegra30-cardhu-a04.dts           |   98 +
+ arch/arm/boot/dts/tegra30-cardhu.dts               |  171 -
+ arch/arm/boot/dts/tegra30-cardhu.dtsi              |  475 +++
+ arch/arm/boot/dts/tegra30.dtsi                     |    2 +-
+ arch/arm/boot/dts/tps65217.dtsi                    |   56 +
+ arch/arm/boot/dts/tps65910.dtsi                    |   86 +
+ arch/arm/boot/dts/twl4030.dtsi                     |    6 +-
+ arch/arm/boot/dts/twl6030.dtsi                     |   26 +-
+ arch/arm/boot/dts/vt8500-bv07.dts                  |   36 +
+ arch/arm/boot/dts/vt8500.dtsi                      |  116 +
+ arch/arm/boot/dts/wm8505-ref.dts                   |   36 +
+ arch/arm/boot/dts/wm8505.dtsi                      |  143 +
+ arch/arm/boot/dts/wm8650-mid.dts                   |   36 +
+ arch/arm/boot/dts/wm8650.dtsi                      |  147 +
+ arch/arm/configs/afeb9260_defconfig                |    1 -
+ arch/arm/configs/armadillo800eva_defconfig         |    3 +
+ arch/arm/configs/at91rm9200_defconfig              |    2 +-
+ arch/arm/configs/at91sam9261_defconfig             |    2 +-
+ arch/arm/configs/at91sam9263_defconfig             |    3 +-
+ arch/arm/configs/at91sam9g20_defconfig             |    2 +-
+ arch/arm/configs/at91sam9rl_defconfig              |    2 +-
+ arch/arm/configs/bcm2835_defconfig                 |   95 +
+ arch/arm/configs/cpu9260_defconfig                 |    2 +-
+ arch/arm/configs/cpu9g20_defconfig                 |    2 +-
+ arch/arm/configs/imx_v6_v7_defconfig               |    8 +-
+ arch/arm/configs/kirkwood_defconfig                |   38 +-
+ arch/arm/configs/kzm9d_defconfig                   |    1 +
+ arch/arm/configs/kzm9g_defconfig                   |    1 +
+ arch/arm/configs/lpc32xx_defconfig                 |    7 +-
+ arch/arm/configs/marzen_defconfig                  |   17 +-
+ arch/arm/configs/mmp2_defconfig                    |    5 +-
+ arch/arm/configs/mvebu_defconfig                   |    2 +
+ arch/arm/configs/mxs_defconfig                     |   42 +-
+ arch/arm/configs/omap2plus_defconfig               |    1 +
+ arch/arm/configs/pnx4008_defconfig                 |  472 ---
+ arch/arm/configs/prima2_defconfig                  |    7 +-
+ arch/arm/configs/pxa910_defconfig                  |    4 +-
+ arch/arm/configs/qil-a9260_defconfig               |    3 +-
+ arch/arm/configs/s3c6400_defconfig                 |    3 +
+ arch/arm/configs/stamp9g20_defconfig               |    1 -
+ arch/arm/configs/tegra_defconfig                   |   53 +-
+ arch/arm/configs/usb-a9260_defconfig               |    1 -
+ arch/arm/include/asm/gpio.h                        |    2 +
+ arch/arm/include/asm/hardware/cache-tauros2.h      |    5 +-
+ arch/arm/include/asm/hardware/iop3xx.h             |   12 +-
+ arch/arm/include/asm/io.h                          |    8 +
+ arch/arm/include/asm/leds.h                        |   50 -
+ arch/arm/include/asm/mach/arch.h                   |    7 +
+ arch/arm/include/asm/mach/map.h                    |    8 +
+ arch/arm/include/asm/mach/pci.h                    |   13 +
+ arch/arm/include/asm/smp.h                         |   48 +-
+ arch/arm/include/asm/timex.h                       |    4 +
+ .../debug-macro.S => include/debug/highbank.S}     |    6 +-
+ arch/arm/include/debug/icedcc.S                    |   90 +
+ .../mach/debug-macro.S => include/debug/mvebu.S}   |    3 +-
+ .../debug-macro.S => include/debug/picoxcell.S}    |    4 +-
+ .../mach/debug-macro.S => include/debug/socfpga.S} |    0
+ .../debug-macro.S => include/debug/vexpress.S}     |    0
+ arch/arm/kernel/Makefile                           |    1 -
+ arch/arm/kernel/bios32.c                           |   54 +-
+ arch/arm/kernel/debug.S                            |   87 +-
+ arch/arm/kernel/head.S                             |    4 +-
+ arch/arm/kernel/leds.c                             |  121 -
+ arch/arm/kernel/process.c                          |    6 +-
+ arch/arm/kernel/setup.c                            |    4 +-
+ arch/arm/kernel/smp.c                              |   72 +-
+ arch/arm/kernel/time.c                             |   17 -
+ arch/arm/mach-at91/Makefile.boot                   |   24 -
+ arch/arm/mach-at91/at91rm9200_devices.c            |   92 +-
+ arch/arm/mach-at91/at91sam9260_devices.c           |   84 +-
+ arch/arm/mach-at91/at91sam9261_devices.c           |   60 +-
+ arch/arm/mach-at91/at91sam9263.c                   |    4 +-
+ arch/arm/mach-at91/at91sam9263_devices.c           |  161 +-
+ arch/arm/mach-at91/at91sam9g45_devices.c           |    2 +-
+ arch/arm/mach-at91/at91sam9rl_devices.c            |   62 +-
+ arch/arm/mach-at91/at91x40.c                       |    2 +-
+ arch/arm/mach-at91/at91x40_time.c                  |    4 +-
+ arch/arm/mach-at91/board-afeb-9260v1.c             |   14 +-
+ arch/arm/mach-at91/board-carmeva.c                 |   14 +-
+ arch/arm/mach-at91/board-cpu9krea.c                |   17 +-
+ arch/arm/mach-at91/board-cpuat91.c                 |   13 +-
+ arch/arm/mach-at91/board-csb337.c                  |   16 +-
+ arch/arm/mach-at91/board-eb9200.c                  |   14 +-
+ arch/arm/mach-at91/board-ecbat91.c                 |   32 +-
+ arch/arm/mach-at91/board-eco920.c                  |   36 +-
+ arch/arm/mach-at91/board-flexibity.c               |   14 +-
+ arch/arm/mach-at91/board-foxg20.c                  |   16 +-
+ arch/arm/mach-at91/board-kafa.c                    |   17 +-
+ arch/arm/mach-at91/board-kb9202.c                  |   37 +-
+ arch/arm/mach-at91/board-neocore926.c              |   13 +-
+ arch/arm/mach-at91/board-picotux200.c              |   14 +-
+ arch/arm/mach-at91/board-qil-a9260.c               |   14 +-
+ arch/arm/mach-at91/board-rm9200dk.c                |   17 +-
+ arch/arm/mach-at91/board-rm9200ek.c                |   17 +-
+ arch/arm/mach-at91/board-rsi-ews.c                 |   16 +-
+ arch/arm/mach-at91/board-sam9-l9260.c              |   39 +-
+ arch/arm/mach-at91/board-sam9260ek.c               |   16 +-
+ arch/arm/mach-at91/board-sam9261ek.c               |   16 +-
+ arch/arm/mach-at91/board-sam9263ek.c               |   13 +-
+ arch/arm/mach-at91/board-sam9g20ek.c               |   16 +-
+ arch/arm/mach-at91/board-sam9rlek.c                |   13 +-
+ arch/arm/mach-at91/board-stamp9g20.c               |   14 -
+ arch/arm/mach-at91/board-usb-a926x.c               |    2 -
+ arch/arm/mach-at91/board-yl-9200.c                 |   16 +-
+ arch/arm/mach-at91/include/mach/atmel-mci.h        |    2 +-
+ arch/arm/mach-at91/include/mach/board.h            |    1 -
+ arch/arm/mach-at91/include/mach/hardware.h         |    4 +-
+ arch/arm/mach-at91/include/mach/uncompress.h       |    6 +-
+ arch/arm/mach-at91/leds.c                          |  105 -
+ arch/arm/mach-at91/setup.c                         |    4 +-
+ arch/arm/mach-bcm2835/Makefile                     |    1 +
+ arch/arm/mach-bcm2835/Makefile.boot                |    3 +
+ arch/arm/mach-bcm2835/bcm2835.c                    |   64 +
+ .../include/mach/bcm2835_soc.h}                    |   24 +-
+ arch/arm/mach-bcm2835/include/mach/debug-macro.S   |   21 +
+ .../param.h => mach-bcm2835/include/mach/timex.h}  |   11 +-
+ arch/arm/mach-bcm2835/include/mach/uncompress.h    |   45 +
+ arch/arm/mach-bcmring/arch.c                       |    2 +-
+ arch/arm/mach-bcmring/core.c                       |    3 +-
+ arch/arm/mach-bcmring/csp/chipc/chipcHw.c          |  137 +-
+ arch/arm/mach-bcmring/csp/chipc/chipcHw_init.c     |   90 +-
+ arch/arm/mach-bcmring/csp/chipc/chipcHw_reset.c    |   19 +-
+ arch/arm/mach-bcmring/csp/dmac/dmacHw.c            |   27 +-
+ arch/arm/mach-bcmring/csp/dmac/dmacHw_extra.c      |    6 +-
+ arch/arm/mach-bcmring/csp/tmr/tmrHw.c              |    6 +-
+ arch/arm/mach-bcmring/include/cfg_global.h         |   13 -
+ arch/arm/mach-bcmring/include/csp/cache.h          |   35 -
+ arch/arm/mach-bcmring/include/csp/delay.h          |   36 -
+ arch/arm/mach-bcmring/include/csp/errno.h          |   32 -
+ arch/arm/mach-bcmring/include/csp/intcHw.h         |   40 -
+ arch/arm/mach-bcmring/include/csp/module.h         |   32 -
+ arch/arm/mach-bcmring/include/csp/secHw.h          |   65 -
+ arch/arm/mach-bcmring/include/csp/stdint.h         |   30 -
+ arch/arm/mach-bcmring/include/csp/string.h         |   34 -
+ .../{cfg_global_defines.h => mach/cfg_global.h}    |   11 +
+ .../arm/mach-bcmring/include/mach/csp/cap_inline.h |    2 +-
+ .../mach-bcmring/include/mach/csp/chipcHw_def.h    |    6 +-
+ .../mach-bcmring/include/mach/csp/chipcHw_inline.h |  119 +-
+ .../mach-bcmring/include/mach/csp/chipcHw_reg.h    |    6 +-
+ arch/arm/mach-bcmring/include/mach/csp/ddrcReg.h   |    6 +-
+ .../mach-bcmring/include/{ => mach}/csp/dmacHw.h   |    4 +-
+ .../mach-bcmring/include/mach/csp/dmacHw_priv.h    |    2 +-
+ .../arm/mach-bcmring/include/mach/csp/dmacHw_reg.h |  106 +-
+ arch/arm/mach-bcmring/include/mach/csp/hw_cfg.h    |    2 +-
+ .../arm/mach-bcmring/include/mach/csp/intcHw_reg.h |   18 +-
+ arch/arm/mach-bcmring/include/mach/csp/mm_addr.h   |    2 +-
+ arch/arm/mach-bcmring/include/mach/csp/mm_io.h     |    8 +-
+ arch/arm/mach-bcmring/include/{ => mach}/csp/reg.h |   25 +-
+ .../mach-bcmring/include/mach/csp/secHw_inline.h   |   10 +-
+ .../mach-bcmring/include/{ => mach}/csp/tmrHw.h    |    2 +-
+ arch/arm/mach-bcmring/include/mach/dma.h           |    2 +-
+ arch/arm/mach-bcmring/include/mach/hardware.h      |    2 +-
+ arch/arm/mach-bcmring/include/mach/reg_nand.h      |    2 +-
+ arch/arm/mach-bcmring/include/mach/reg_umi.h       |    4 +-
+ arch/arm/mach-bcmring/mm.c                         |    4 +-
+ arch/arm/mach-bcmring/timer.c                      |    2 +-
+ arch/arm/mach-clps711x/Makefile                    |    2 -
+ arch/arm/mach-clps711x/common.c                    |    1 -
+ arch/arm/mach-clps711x/p720t-leds.c                |   63 -
+ arch/arm/mach-clps711x/p720t.c                     |   62 +
+ arch/arm/mach-davinci/aemif.c                      |    2 +-
+ arch/arm/mach-davinci/board-da830-evm.c            |    8 +-
+ arch/arm/mach-davinci/board-da850-evm.c            |    6 +-
+ arch/arm/mach-davinci/board-dm355-evm.c            |    8 +-
+ arch/arm/mach-davinci/board-dm355-leopard.c        |    8 +-
+ arch/arm/mach-davinci/board-dm365-evm.c            |    8 +-
+ arch/arm/mach-davinci/board-dm644x-evm.c           |   10 +-
+ arch/arm/mach-davinci/board-dm646x-evm.c           |    6 +-
+ arch/arm/mach-davinci/board-mityomapl138.c         |    4 +-
+ arch/arm/mach-davinci/board-neuros-osd2.c          |    8 +-
+ arch/arm/mach-davinci/board-sffsdr.c               |    4 +-
+ arch/arm/mach-davinci/davinci.h                    |    2 +-
+ arch/arm/mach-davinci/devices.c                    |    4 +-
+ arch/arm/mach-davinci/dm355.c                      |    2 +-
+ arch/arm/mach-davinci/dm365.c                      |    4 +-
+ arch/arm/mach-davinci/include/mach/da8xx.h         |    8 +-
+ arch/arm/mach-davinci/include/mach/tnetv107x.h     |    4 +-
+ arch/arm/mach-davinci/usb.c                        |    2 +-
+ arch/arm/mach-dove/Kconfig                         |    7 +
+ arch/arm/mach-dove/Makefile                        |    4 +-
+ arch/arm/mach-dove/common.c                        |  171 +-
+ arch/arm/mach-dove/common.h                        |    4 +
+ arch/arm/mach-dove/include/mach/bridge-regs.h      |   16 +-
+ arch/arm/mach-dove/include/mach/dove.h             |  134 +-
+ arch/arm/mach-dove/include/mach/gpio.h             |    9 -
+ arch/arm/mach-dove/include/mach/io.h               |   19 -
+ arch/arm/mach-dove/include/mach/pm.h               |   54 +-
+ arch/arm/mach-dove/irq.c                           |   11 +-
+ arch/arm/mach-dove/mpp.c                           |    1 +
+ arch/arm/mach-dove/pcie.c                          |   49 +-
+ arch/arm/mach-ebsa110/Makefile                     |    4 +-
+ arch/arm/mach-ebsa110/core.c                       |    8 +-
+ arch/arm/mach-ebsa110/core.h                       |   12 +-
+ arch/arm/mach-ebsa110/leds.c                       |   81 +-
+ arch/arm/mach-ep93xx/core.c                        |    6 +-
+ arch/arm/mach-ep93xx/dma.c                         |    2 +-
+ arch/arm/mach-ep93xx/edb93xx.c                     |    4 +-
+ arch/arm/mach-ep93xx/simone.c                      |    2 +-
+ arch/arm/mach-ep93xx/snappercl15.c                 |    2 +-
+ arch/arm/mach-ep93xx/vision_ep9307.c               |    4 +-
+ arch/arm/mach-exynos/Kconfig                       |    9 +-
+ arch/arm/mach-exynos/Makefile.boot                 |    3 -
+ arch/arm/mach-exynos/clock-exynos4.c               |   31 +
+ arch/arm/mach-exynos/clock-exynos5.c               |  127 +-
+ arch/arm/mach-exynos/common.c                      |   26 +
+ arch/arm/mach-exynos/common.h                      |    5 +
+ arch/arm/mach-exynos/dev-audio.c                   |    2 +-
+ arch/arm/mach-exynos/dev-ohci.c                    |    2 +-
+ arch/arm/mach-exynos/hotplug.c                     |   18 +-
+ arch/arm/mach-exynos/include/mach/map.h            |    8 +-
+ arch/arm/mach-exynos/include/mach/sysmmu.h         |    2 +-
+ arch/arm/mach-exynos/mach-armlex4210.c             |    1 +
+ arch/arm/mach-exynos/mach-exynos5-dt.c             |    9 +
+ arch/arm/mach-exynos/mach-nuri.c                   |    7 +-
+ arch/arm/mach-exynos/mach-origen.c                 |   13 +-
+ arch/arm/mach-exynos/mach-smdk4x12.c               |   10 +-
+ arch/arm/mach-exynos/mach-smdkv310.c               |   15 +-
+ arch/arm/mach-exynos/mach-universal_c210.c         |    5 +-
+ arch/arm/mach-exynos/platsmp.c                     |   27 +-
+ arch/arm/mach-exynos/setup-i2c0.c                  |    2 +-
+ arch/arm/mach-exynos/setup-i2c1.c                  |    2 +-
+ arch/arm/mach-exynos/setup-i2c2.c                  |    2 +-
+ arch/arm/mach-exynos/setup-i2c3.c                  |    2 +-
+ arch/arm/mach-exynos/setup-i2c4.c                  |    2 +-
+ arch/arm/mach-exynos/setup-i2c5.c                  |    2 +-
+ arch/arm/mach-exynos/setup-i2c6.c                  |    2 +-
+ arch/arm/mach-exynos/setup-i2c7.c                  |    2 +-
+ arch/arm/mach-footbridge/Makefile                  |    4 -
+ arch/arm/mach-footbridge/common.c                  |   12 +-
+ arch/arm/mach-footbridge/dc21285.c                 |   16 +-
+ arch/arm/mach-footbridge/ebsa285-leds.c            |  138 -
+ arch/arm/mach-footbridge/ebsa285.c                 |   81 +
+ .../arm/mach-footbridge/include/mach/debug-macro.S |    3 +-
+ arch/arm/mach-footbridge/include/mach/io.h         |   12 +-
+ arch/arm/mach-footbridge/netwinder-hw.c            |  112 +-
+ arch/arm/mach-footbridge/netwinder-leds.c          |  138 -
+ arch/arm/mach-highbank/Kconfig                     |   15 +
+ arch/arm/mach-highbank/Makefile.boot               |    1 -
+ arch/arm/mach-highbank/core.h                      |    9 +
+ arch/arm/mach-highbank/highbank.c                  |    2 +
+ arch/arm/mach-highbank/hotplug.c                   |   16 +-
+ arch/arm/mach-highbank/include/mach/gpio.h         |    1 -
+ arch/arm/mach-highbank/include/mach/timex.h        |    6 -
+ arch/arm/mach-highbank/include/mach/uncompress.h   |    9 -
+ arch/arm/mach-highbank/platsmp.c                   |   18 +-
+ arch/arm/mach-highbank/pm.c                        |    4 +-
+ arch/arm/mach-imx/Kconfig                          |  107 +-
+ arch/arm/mach-imx/Makefile                         |   11 +-
+ arch/arm/mach-imx/Makefile.boot                    |    7 -
+ arch/arm/mach-imx/clk-imx21.c                      |    1 -
+ arch/arm/mach-imx/clk-imx35.c                      |   11 +-
+ arch/arm/mach-imx/clk-imx51-imx53.c                |   18 +-
+ arch/arm/mach-imx/clk-imx6q.c                      |   51 +-
+ arch/arm/mach-imx/clk-pllv1.c                      |   49 +-
+ arch/arm/mach-imx/clk.c                            |    3 +
+ arch/arm/mach-imx/clk.h                            |    3 +-
+ arch/arm/mach-imx/devices-imx53.h                  |   48 -
+ arch/arm/mach-imx/efika.h                          |   10 -
+ arch/arm/mach-imx/ehci-imx25.c                     |    2 +-
+ arch/arm/mach-imx/ehci-imx27.c                     |    2 +-
+ arch/arm/mach-imx/ehci-imx31.c                     |    2 +-
+ arch/arm/mach-imx/ehci-imx35.c                     |    2 +-
+ arch/arm/mach-imx/ehci-imx5.c                      |    2 +-
+ arch/arm/mach-imx/hotplug.c                        |   16 +-
+ arch/arm/mach-imx/imx51-dt.c                       |   21 -
+ arch/arm/mach-imx/{imx53-dt.c => mach-imx53.c}     |   27 -
+ arch/arm/mach-imx/mach-imx6q.c                     |   12 +-
+ arch/arm/mach-imx/mach-kzm_arm11_01.c              |    5 +-
+ arch/arm/mach-imx/mach-mx27_3ds.c                  |   21 +-
+ arch/arm/mach-imx/mach-mx31ads.c                   |    2 +-
+ arch/arm/mach-imx/mach-mx31lite.c                  |    2 +-
+ arch/arm/mach-imx/mach-mx31moboard.c               |    2 +-
+ arch/arm/mach-imx/mach-mx51_efikamx.c              |  300 --
+ arch/arm/mach-imx/mach-mx51_efikasb.c              |  296 --
+ arch/arm/mach-imx/mach-mx53_ard.c                  |  272 --
+ arch/arm/mach-imx/mach-mx53_evk.c                  |  179 --
+ arch/arm/mach-imx/mach-mx53_loco.c                 |  321 --
+ arch/arm/mach-imx/mach-mx53_smd.c                  |  168 -
+ arch/arm/mach-imx/mm-imx5.c                        |   47 -
+ arch/arm/mach-imx/mx1-camera-fiq-ksym.c            |    2 +-
+ arch/arm/mach-imx/mx51_efika.c                     |  633 ----
+ arch/arm/mach-imx/platsmp.c                        |   18 +-
+ arch/arm/mach-integrator/Makefile                  |    3 +-
+ arch/arm/mach-integrator/core.c                    |    7 +-
+ arch/arm/mach-integrator/cpu.c                     |    8 +-
+ arch/arm/mach-integrator/include/mach/cm.h         |    2 +
+ arch/arm/mach-integrator/include/mach/io.h         |   33 -
+ arch/arm/mach-integrator/include/mach/platform.h   |    4 +
+ arch/arm/mach-integrator/integrator_ap.c           |   21 +-
+ arch/arm/mach-integrator/integrator_cp.c           |    6 +-
+ arch/arm/mach-integrator/leds.c                    |  161 +-
+ arch/arm/mach-integrator/pci_v3.c                  |   62 +-
+ arch/arm/mach-iop13xx/include/mach/io.h            |   28 -
+ arch/arm/mach-iop13xx/include/mach/iop13xx.h       |   48 +-
+ arch/arm/mach-iop13xx/include/mach/memory.h        |   14 +-
+ arch/arm/mach-iop13xx/io.c                         |   35 +-
+ arch/arm/mach-iop13xx/pci.c                        |   53 +-
+ arch/arm/mach-iop13xx/pci.h                        |    4 +-
+ arch/arm/mach-iop13xx/setup.c                      |   20 +-
+ arch/arm/mach-iop32x/glantank.c                    |    2 +-
+ arch/arm/mach-iop32x/include/mach/io.h             |   19 -
+ arch/arm/mach-iop33x/include/mach/io.h             |   19 -
+ arch/arm/mach-ixp4xx/common.c                      |    8 +-
+ arch/arm/mach-ixp4xx/include/mach/cpu.h            |    5 +-
+ arch/arm/mach-ixp4xx/include/mach/gpio.h           |    2 -
+ arch/arm/mach-ixp4xx/include/mach/ixp4xx-regs.h    |   10 +-
+ arch/arm/mach-kirkwood/Kconfig                     |   21 +
+ arch/arm/mach-kirkwood/Makefile                    |    3 +
+ arch/arm/mach-kirkwood/Makefile.boot               |   11 -
+ arch/arm/mach-kirkwood/addr-map.c                  |    3 +-
+ arch/arm/mach-kirkwood/board-dnskw.c               |   35 -
+ arch/arm/mach-kirkwood/board-dockstar.c            |   61 +
+ arch/arm/mach-kirkwood/board-dreamplug.c           |    2 +-
+ arch/arm/mach-kirkwood/board-dt.c                  |   14 +-
+ arch/arm/mach-kirkwood/board-goflexnet.c           |    2 +-
+ arch/arm/mach-kirkwood/board-iconnect.c            |   48 -
+ arch/arm/mach-kirkwood/board-iomega_ix2_200.c      |   57 +
+ arch/arm/mach-kirkwood/board-km_kirkwood.c         |   57 +
+ arch/arm/mach-kirkwood/common.c                    |   28 +-
+ arch/arm/mach-kirkwood/common.h                    |   18 +
+ arch/arm/mach-kirkwood/d2net_v2-setup.c            |    2 +-
+ arch/arm/mach-kirkwood/db88f6281-bp-setup.c        |    2 +-
+ arch/arm/mach-kirkwood/dockstar-setup.c            |    2 +-
+ arch/arm/mach-kirkwood/guruplug-setup.c            |    2 +-
+ arch/arm/mach-kirkwood/include/mach/bridge-regs.h  |   20 +-
+ arch/arm/mach-kirkwood/include/mach/gpio.h         |    9 -
+ arch/arm/mach-kirkwood/include/mach/io.h           |   24 -
+ arch/arm/mach-kirkwood/include/mach/kirkwood.h     |  120 +-
+ arch/arm/mach-kirkwood/irq.c                       |   10 +-
+ arch/arm/mach-kirkwood/netspace_v2-setup.c         |    2 +-
+ arch/arm/mach-kirkwood/netxbig_v2-setup.c          |    2 +-
+ arch/arm/mach-kirkwood/openrd-setup.c              |    2 +-
+ arch/arm/mach-kirkwood/pcie.c                      |   56 +-
+ arch/arm/mach-kirkwood/rd88f6192-nas-setup.c       |    1 +
+ arch/arm/mach-kirkwood/rd88f6281-setup.c           |    2 +-
+ arch/arm/mach-kirkwood/sheevaplug-setup.c          |    2 +-
+ arch/arm/mach-kirkwood/ts41x-setup.c               |    3 +-
+ arch/arm/mach-ks8695/Kconfig                       |   61 +
+ arch/arm/mach-ks8695/Makefile                      |   11 +-
+ arch/arm/mach-ks8695/board-og.c                    |  199 ++
+ arch/arm/mach-ks8695/board-sg.c                    |  121 +
+ arch/arm/mach-ks8695/cpu.c                         |    2 +-
+ arch/arm/mach-ks8695/devices.c                     |   21 -
+ arch/arm/mach-ks8695/include/mach/devices.h        |    5 -
+ arch/arm/mach-ks8695/include/mach/hardware.h       |    2 +-
+ arch/arm/mach-ks8695/include/mach/regs-timer.h     |   40 -
+ arch/arm/mach-ks8695/include/mach/uncompress.h     |    6 +-
+ arch/arm/mach-ks8695/leds.c                        |   92 -
+ arch/arm/mach-ks8695/time.c                        |  133 +-
+ arch/arm/mach-lpc32xx/Makefile.boot                |    2 -
+ arch/arm/mach-lpc32xx/common.c                     |    8 +-
+ arch/arm/mach-lpc32xx/include/mach/hardware.h      |    2 +-
+ arch/arm/mach-lpc32xx/irq.c                        |    7 +-
+ arch/arm/mach-lpc32xx/phy3250.c                    |   20 +-
+ arch/arm/mach-mmp/Kconfig                          |    3 +
+ arch/arm/mach-mmp/Makefile                         |    8 +-
+ arch/arm/mach-mmp/aspenite.c                       |    2 +-
+ arch/arm/mach-mmp/clock-mmp2.c                     |  111 +
+ arch/arm/mach-mmp/clock-pxa168.c                   |   91 +
+ arch/arm/mach-mmp/clock-pxa910.c                   |   67 +
+ arch/arm/mach-mmp/common.h                         |    3 +
+ arch/arm/mach-mmp/include/mach/debug-macro.S       |   12 +-
+ arch/arm/mach-mmp/include/mach/mmp2.h              |    2 +-
+ arch/arm/mach-mmp/include/mach/pxa168.h            |    4 +-
+ arch/arm/mach-mmp/include/mach/pxa910.h            |    2 +-
+ arch/arm/mach-mmp/include/mach/regs-apbc.h         |   95 -
+ arch/arm/mach-mmp/include/mach/regs-apmu.h         |   15 -
+ arch/arm/mach-mmp/irq.c                            |    4 +-
+ arch/arm/mach-mmp/mmp2.c                           |   73 +-
+ arch/arm/mach-mmp/pxa168.c                         |   58 +-
+ arch/arm/mach-mmp/pxa910.c                         |   44 +-
+ arch/arm/mach-mmp/sram.c                           |    2 +-
+ arch/arm/mach-mmp/teton_bga.c                      |    2 +-
+ arch/arm/mach-mmp/ttc_dkb.c                        |   10 +
+ arch/arm/mach-msm/Kconfig                          |   49 +-
+ arch/arm/mach-msm/Makefile                         |    8 +-
+ arch/arm/mach-msm/acpuclock-arm11.c                |  525 ---
+ arch/arm/mach-msm/acpuclock.h                      |   32 -
+ arch/arm/mach-msm/board-dt-8660.c                  |   64 +
+ arch/arm/mach-msm/board-dt-8960.c                  |   50 +
+ arch/arm/mach-msm/board-halibut.c                  |    5 +-
+ arch/arm/mach-msm/board-mahimahi.c                 |    1 -
+ arch/arm/mach-msm/board-msm7x27.c                  |  170 -
+ arch/arm/mach-msm/board-msm7x30.c                  |    9 +-
+ arch/arm/mach-msm/board-msm8960.c                  |  122 -
+ arch/arm/mach-msm/board-msm8x60.c                  |  166 -
+ arch/arm/mach-msm/board-qsd8x50.c                  |    9 +-
+ arch/arm/mach-msm/board-sapphire.c                 |    1 -
+ arch/arm/mach-msm/board-trout-mmc.c                |    2 +-
+ arch/arm/mach-msm/board-trout-panel.c              |    2 +-
+ arch/arm/mach-msm/board-trout.c                    |    5 +-
+ arch/arm/mach-msm/clock-pcom.c                     |   18 +-
+ arch/arm/mach-msm/common.h                         |   32 +
+ arch/arm/mach-msm/core.h                           |    2 +
+ arch/arm/mach-msm/devices-msm7x00.c                |    2 +-
+ arch/arm/mach-msm/devices-msm7x30.c                |    2 +-
+ arch/arm/mach-msm/devices-msm8960.c                |   85 -
+ arch/arm/mach-msm/devices-qsd8x50.c                |    2 +-
+ arch/arm/mach-msm/dma.c                            |    3 +-
+ arch/arm/mach-msm/hotplug.c                        |   18 +-
+ arch/arm/mach-msm/idle.c                           |   49 -
+ arch/arm/mach-msm/include/mach/board.h             |   15 +-
+ arch/arm/mach-msm/include/mach/gpio.h              |    1 -
+ arch/arm/mach-msm/include/mach/msm_iomap-7x00.h    |    7 -
+ arch/arm/mach-msm/include/mach/msm_iomap-7x30.h    |    4 -
+ arch/arm/mach-msm/include/mach/msm_iomap-8960.h    |    6 +-
+ arch/arm/mach-msm/include/mach/msm_iomap-8x50.h    |    4 -
+ arch/arm/mach-msm/include/mach/msm_iomap-8x60.h    |   17 +-
+ arch/arm/mach-msm/include/mach/msm_iomap.h         |    3 +-
+ arch/arm/mach-msm/include/mach/system.h            |   19 -
+ arch/arm/mach-msm/io.c                             |   32 +-
+ arch/arm/mach-msm/platsmp.c                        |   32 +-
+ arch/arm/mach-msm/proc_comm.c                      |    1 -
+ arch/arm/mach-msm/smd.c                            |   26 +-
+ arch/arm/mach-msm/timer.c                          |  188 +-
+ arch/arm/mach-mv78xx0/addr-map.c                   |    9 +-
+ arch/arm/mach-mv78xx0/common.c                     |   13 +-
+ arch/arm/mach-mv78xx0/include/mach/bridge-regs.h   |   12 +-
+ arch/arm/mach-mv78xx0/include/mach/io.h            |   24 -
+ arch/arm/mach-mv78xx0/include/mach/mv78xx0.h       |  105 +-
+ arch/arm/mach-mv78xx0/irq.c                        |   10 +-
+ arch/arm/mach-mv78xx0/pcie.c                       |  122 +-
+ arch/arm/mach-mvebu/Kconfig                        |   28 +-
+ arch/arm/mach-mvebu/Makefile                       |    4 +-
+ arch/arm/mach-mvebu/Makefile.boot                  |    3 -
+ arch/arm/mach-mvebu/addr-map.c                     |  134 +
+ arch/arm/mach-mvebu/armada-370-xp.c                |    4 +-
+ .../mach-mvebu/{include/mach => }/armada-370-xp.h  |    2 +-
+ .../include/mach/gpio.h                            |    0
+ arch/arm/mach-mvebu/include/mach/timex.h           |   13 -
+ arch/arm/mach-mvebu/include/mach/uncompress.h      |   43 -
+ arch/arm/mach-mxs/Kconfig                          |   89 -
+ arch/arm/mach-mxs/Makefile                         |   11 +-
+ arch/arm/mach-mxs/Makefile.boot                    |    9 -
+ arch/arm/mach-mxs/devices-mx23.h                   |   43 -
+ arch/arm/mach-mxs/devices-mx28.h                   |   63 -
+ arch/arm/mach-mxs/devices.c                        |   87 -
+ arch/arm/mach-mxs/devices/Kconfig                  |   33 -
+ arch/arm/mach-mxs/devices/Makefile                 |   12 -
+ arch/arm/mach-mxs/devices/platform-auart.c         |   65 -
+ arch/arm/mach-mxs/devices/platform-dma.c           |   31 -
+ arch/arm/mach-mxs/devices/platform-fec.c           |   52 -
+ arch/arm/mach-mxs/devices/platform-flexcan.c       |   51 -
+ arch/arm/mach-mxs/devices/platform-gpio-mxs.c      |   33 -
+ arch/arm/mach-mxs/devices/platform-gpmi-nand.c     |   81 -
+ arch/arm/mach-mxs/devices/platform-mxs-i2c.c       |   52 -
+ arch/arm/mach-mxs/devices/platform-mxs-mmc.c       |   76 -
+ arch/arm/mach-mxs/devices/platform-mxs-pwm.c       |   22 -
+ arch/arm/mach-mxs/devices/platform-mxs-saif.c      |   61 -
+ arch/arm/mach-mxs/devices/platform-mxsfb.c         |   47 -
+ arch/arm/mach-mxs/devices/platform-rtc-stmp3xxx.c  |   51 -
+ arch/arm/mach-mxs/icoll.c                          |   63 +-
+ arch/arm/mach-mxs/include/mach/common.h            |   12 +-
+ arch/arm/mach-mxs/include/mach/devices-common.h    |  114 -
+ arch/arm/mach-mxs/include/mach/entry-macro.S       |   35 -
+ arch/arm/mach-mxs/include/mach/gpio.h              |    1 -
+ arch/arm/mach-mxs/include/mach/iomux-mx23.h        |  355 --
+ arch/arm/mach-mxs/include/mach/iomux-mx28.h        |  537 ----
+ arch/arm/mach-mxs/include/mach/iomux.h             |  168 -
+ arch/arm/mach-mxs/include/mach/irqs.h              |   32 -
+ arch/arm/mach-mxs/iomux.c                          |  101 -
+ arch/arm/mach-mxs/mach-apx4devkit.c                |  273 --
+ arch/arm/mach-mxs/mach-m28evk.c                    |  366 ---
+ arch/arm/mach-mxs/mach-mx23evk.c                   |  190 --
+ arch/arm/mach-mxs/mach-mx28evk.c                   |  477 ---
+ arch/arm/mach-mxs/mach-mxs.c                       |  169 +-
+ arch/arm/mach-mxs/mach-stmp378x_devb.c             |  123 -
+ arch/arm/mach-mxs/mach-tx28.c                      |  184 --
+ arch/arm/mach-mxs/mm.c                             |   39 -
+ arch/arm/mach-mxs/module-tx28.c                    |  160 -
+ arch/arm/mach-mxs/module-tx28.h                    |   10 -
+ arch/arm/mach-mxs/timer.c                          |   13 +-
+ arch/arm/mach-netx/nxdb500.c                       |    2 +-
+ arch/arm/mach-netx/nxdkn.c                         |    2 +-
+ arch/arm/mach-netx/nxeb500hmi.c                    |    2 +-
+ arch/arm/mach-nomadik/board-nhk8815.c              |    2 +-
+ arch/arm/mach-nomadik/include/mach/gpio.h          |    4 -
+ arch/arm/mach-nomadik/include/mach/hardware.h      |    2 +-
+ arch/arm/mach-nomadik/include/mach/uncompress.h    |    8 +-
+ arch/arm/mach-omap1/Makefile                       |    8 -
+ arch/arm/mach-omap1/ams-delta-fiq-handler.S        |    3 +-
+ arch/arm/mach-omap1/ams-delta-fiq.c                |    2 +-
+ arch/arm/mach-omap1/board-ams-delta.c              |    8 +-
+ arch/arm/mach-omap1/board-fsample.c                |    7 +-
+ arch/arm/mach-omap1/board-generic.c                |    8 +-
+ arch/arm/mach-omap1/board-h2.c                     |   41 +-
+ arch/arm/mach-omap1/board-h3.c                     |   39 +-
+ arch/arm/mach-omap1/board-htcherald.c              |    8 +-
+ arch/arm/mach-omap1/board-innovator.c              |    6 +-
+ arch/arm/mach-omap1/board-nokia770.c               |    8 +-
+ arch/arm/mach-omap1/board-osk.c                    |   41 +-
+ arch/arm/mach-omap1/board-palmte.c                 |   10 +-
+ arch/arm/mach-omap1/board-palmtt.c                 |   10 +-
+ arch/arm/mach-omap1/board-palmz71.c                |   10 +-
+ arch/arm/mach-omap1/board-perseus2.c               |    7 +-
+ arch/arm/mach-omap1/board-sx1-mmc.c                |    2 +-
+ arch/arm/mach-omap1/board-sx1.c                    |   11 +-
+ arch/arm/mach-omap1/board-voiceblue.c              |   12 +-
+ arch/arm/mach-omap1/clock.c                        |    4 +-
+ arch/arm/mach-omap1/clock_data.c                   |   21 +-
+ arch/arm/mach-omap1/devices.c                      |    5 +-
+ arch/arm/mach-omap1/dma.c                          |    8 +-
+ arch/arm/mach-omap1/flash.c                        |    2 +-
+ arch/arm/mach-omap1/gpio15xx.c                     |    1 +
+ arch/arm/mach-omap1/gpio16xx.c                     |    1 +
+ arch/arm/mach-omap1/gpio7xx.c                      |    1 +
+ arch/arm/mach-omap1/i2c.c                          |    2 +-
+ arch/arm/mach-omap1/include/mach/ams-delta-fiq.h   |    2 -
+ .../include/mach}/board-ams-delta.h                |    0
+ .../plat => mach-omap1/include/mach}/board-sx1.h   |    0
+ .../include/mach}/board-voiceblue.h                |    0
+ .../plat => mach-omap1/include/mach}/flash.h       |    0
+ arch/arm/mach-omap1/include/mach/gpio.h            |    2 -
+ arch/arm/mach-omap1/include/mach/hardware.h        |  285 +-
+ .../plat => mach-omap1/include/mach}/irda.h        |    0
+ arch/arm/mach-omap1/include/mach/irqs.h            |  267 +-
+ .../include/plat => mach-omap1/include/mach}/mux.h |    0
+ .../plat => mach-omap1/include/mach}/omap1510.h    |    3 +-
+ .../plat => mach-omap1/include/mach}/omap16xx.h    |    3 +-
+ .../plat => mach-omap1/include/mach}/omap7xx.h     |    3 +-
+ arch/arm/mach-omap1/include/mach/smp.h             |    5 -
+ arch/arm/mach-omap1/io.c                           |    2 +-
+ arch/arm/mach-omap1/lcd_dma.c                      |    6 +-
+ arch/arm/mach-omap1/leds-h2p2-debug.c              |  166 -
+ arch/arm/mach-omap1/leds-innovator.c               |   98 -
+ arch/arm/mach-omap1/leds-osk.c                     |  113 -
+ arch/arm/mach-omap1/leds.c                         |   69 -
+ arch/arm/mach-omap1/leds.h                         |    3 -
+ arch/arm/mach-omap1/mcbsp.c                        |    4 +-
+ arch/arm/mach-omap1/mux.c                          |   58 +-
+ arch/arm/mach-omap1/pm.c                           |    2 +-
+ arch/arm/mach-omap1/serial.c                       |    3 +-
+ arch/arm/mach-omap1/time.c                         |    1 -
+ arch/arm/mach-omap1/timer32k.c                     |    1 -
+ arch/arm/mach-omap1/usb.c                          |    2 +-
+ arch/arm/mach-omap2/Kconfig                        |    3 +
+ arch/arm/mach-omap2/Makefile                       |  114 +-
+ .../include/plat => mach-omap2}/am33xx.h           |    0
+ arch/arm/mach-omap2/am35xx-emac.c                  |    2 +-
+ arch/arm/mach-omap2/{include/mach => }/am35xx.h    |    0
+ arch/arm/mach-omap2/board-2430sdp.c                |    8 +-
+ arch/arm/mach-omap2/board-3430sdp.c                |   14 +-
+ arch/arm/mach-omap2/board-3630sdp.c                |    8 +-
+ arch/arm/mach-omap2/board-4430sdp.c                |    9 +-
+ arch/arm/mach-omap2/board-am3517crane.c            |   10 -
+ arch/arm/mach-omap2/board-am3517evm.c              |   13 +-
+ arch/arm/mach-omap2/board-apollon.c                |    2 -
+ arch/arm/mach-omap2/board-cm-t35.c                 |   16 +-
+ arch/arm/mach-omap2/board-cm-t3517.c               |   13 +-
+ arch/arm/mach-omap2/board-devkit8000.c             |   13 +-
+ arch/arm/mach-omap2/board-flash.c                  |    8 +-
+ arch/arm/mach-omap2/board-generic.c                |    4 +-
+ arch/arm/mach-omap2/board-h4.c                     |    5 +-
+ arch/arm/mach-omap2/board-igep0020.c               |    9 +-
+ arch/arm/mach-omap2/board-ldp.c                    |   11 +-
+ arch/arm/mach-omap2/board-n8x0.c                   |   16 +-
+ arch/arm/mach-omap2/board-omap3beagle.c            |    7 +-
+ arch/arm/mach-omap2/board-omap3evm.c               |   29 +-
+ arch/arm/mach-omap2/board-omap3logic.c             |   18 +-
+ arch/arm/mach-omap2/board-omap3pandora.c           |    9 +-
+ arch/arm/mach-omap2/board-omap3stalker.c           |   21 +-
+ arch/arm/mach-omap2/board-omap3touchbook.c         |    9 +-
+ arch/arm/mach-omap2/board-omap4panda.c             |    7 +-
+ arch/arm/mach-omap2/board-overo.c                  |   19 +-
+ arch/arm/mach-omap2/board-rm680.c                  |    8 +-
+ arch/arm/mach-omap2/board-rx51-peripherals.c       |   15 +-
+ arch/arm/mach-omap2/board-rx51-video.c             |    4 +-
+ arch/arm/mach-omap2/board-rx51.c                   |    4 +-
+ .../arm/mach-omap2/{include/mach => }/board-rx51.h |    0
+ arch/arm/mach-omap2/board-ti8168evm.c              |    8 -
+ arch/arm/mach-omap2/board-zoom-debugboard.c        |   12 +-
+ arch/arm/mach-omap2/board-zoom-display.c           |    4 +-
+ arch/arm/mach-omap2/board-zoom-peripherals.c       |    6 +-
+ arch/arm/mach-omap2/board-zoom.c                   |    1 -
+ arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c       |    2 +-
+ arch/arm/mach-omap2/clkt34xx_dpll3m2.c             |   10 +-
+ arch/arm/mach-omap2/clkt_clksel.c                  |   28 +-
+ arch/arm/mach-omap2/clkt_dpll.c                    |   14 +-
+ arch/arm/mach-omap2/clock.c                        |   28 +-
+ arch/arm/mach-omap2/clock2420_data.c               |    2 +-
+ arch/arm/mach-omap2/clock2430.c                    |    2 +-
+ arch/arm/mach-omap2/clock2430_data.c               |    3 +-
+ arch/arm/mach-omap2/clock2xxx.c                    |    2 +-
+ arch/arm/mach-omap2/clock33xx_data.c               |    4 +-
+ arch/arm/mach-omap2/clock3xxx.c                    |    5 +-
+ arch/arm/mach-omap2/clock3xxx_data.c               |    3 +-
+ arch/arm/mach-omap2/clock44xx_data.c               |    2 +-
+ arch/arm/mach-omap2/clockdomain.c                  |   74 +-
+ arch/arm/mach-omap2/cm2xxx_3xxx.c                  |    3 +-
+ arch/arm/mach-omap2/common-board-devices.c         |    8 +-
+ arch/arm/mach-omap2/common.c                       |    4 +-
+ arch/arm/mach-omap2/common.h                       |   14 +-
+ arch/arm/mach-omap2/control.c                      |    2 +-
+ arch/arm/mach-omap2/control.h                      |   10 +-
+ arch/arm/mach-omap2/cpuidle34xx.c                  |    1 -
+ .../{include/mach => }/ctrl_module_core_44xx.h     |    0
+ .../{include/mach => }/ctrl_module_pad_core_44xx.h |    0
+ .../{include/mach => }/ctrl_module_pad_wkup_44xx.h |    0
+ .../{include/mach => }/ctrl_module_wkup_44xx.h     |    0
+ arch/arm/mach-omap2/debug-devices.h                |    9 +
+ arch/arm/mach-omap2/devices.c                      |   28 +-
+ arch/arm/mach-omap2/dpll3xxx.c                     |   13 +-
+ arch/arm/mach-omap2/dpll44xx.c                     |    2 +-
+ arch/arm/mach-omap2/dsp.c                          |    2 +-
+ arch/arm/mach-omap2/emu.c                          |    3 +-
+ arch/arm/mach-omap2/gpio.c                         |    3 +
+ arch/arm/mach-omap2/gpmc-nand.c                    |   34 +-
+ arch/arm/mach-omap2/gpmc-onenand.c                 |   29 +-
+ arch/arm/mach-omap2/gpmc-smc91x.c                  |    5 +-
+ .../include/plat => mach-omap2}/gpmc-smc91x.h      |    0
+ arch/arm/mach-omap2/gpmc-smsc911x.c                |    3 +-
+ .../include/plat => mach-omap2}/gpmc-smsc911x.h    |    0
+ arch/arm/mach-omap2/gpmc.c                         |  169 +-
+ arch/arm/mach-omap2/hdq1w.c                        |    2 +-
+ .../{plat-omap/include/plat => mach-omap2}/hdq1w.h |    0
+ arch/arm/mach-omap2/hsmmc.c                        |    3 +-
+ arch/arm/mach-omap2/i2c.c                          |    1 -
+ arch/arm/mach-omap2/id.c                           |    9 +-
+ arch/arm/mach-omap2/{include/mach => }/id.h        |    0
+ arch/arm/mach-omap2/include/mach/gpio.h            |    2 -
+ arch/arm/mach-omap2/include/mach/hardware.h        |    2 -
+ arch/arm/mach-omap2/include/mach/irqs.h            |    2 -
+ arch/arm/mach-omap2/include/mach/smp.h             |    5 -
+ arch/arm/mach-omap2/io.c                           |    3 +
+ arch/arm/mach-omap2/irq.c                          |   10 +-
+ .../include/plat => mach-omap2}/l3_2xxx.h          |    0
+ .../include/plat => mach-omap2}/l3_3xxx.h          |    0
+ .../include/plat => mach-omap2}/l4_2xxx.h          |    0
+ .../include/plat => mach-omap2}/l4_3xxx.h          |    0
+ arch/arm/mach-omap2/mailbox.c                      |    4 +-
+ arch/arm/mach-omap2/mcbsp.c                        |    4 +-
+ arch/arm/mach-omap2/msdi.c                         |    1 +
+ arch/arm/mach-omap2/omap-hotplug.c                 |   18 +-
+ arch/arm/mach-omap2/omap-iommu.c                   |   12 +-
+ arch/arm/mach-omap2/omap-mpuss-lowpower.c          |    3 +-
+ arch/arm/mach-omap2/omap-secure.c                  |    2 +-
+ .../mach-omap2/{include/mach => }/omap-secure.h    |    0
+ arch/arm/mach-omap2/omap-smp.c                     |   24 +-
+ arch/arm/mach-omap2/omap-wakeupgen.c               |   13 +-
+ .../mach-omap2/{include/mach => }/omap-wakeupgen.h |    0
+ .../include/plat => mach-omap2}/omap24xx.h         |    2 -
+ .../include/plat => mach-omap2}/omap34xx.h         |    2 -
+ arch/arm/mach-omap2/omap4-common.c                 |   16 +-
+ .../include/plat => mach-omap2}/omap4-keypad.h     |    2 +
+ .../include/plat => mach-omap2}/omap44xx.h         |    2 +-
+ .../include/plat => mach-omap2}/omap54xx.h         |    0
+ arch/arm/mach-omap2/omap_hwmod.c                   |  229 +-
+ arch/arm/mach-omap2/omap_hwmod_2420_data.c         |   32 +-
+ arch/arm/mach-omap2/omap_hwmod_2430_data.c         |   80 +-
+ .../mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c |  110 +-
+ .../mach-omap2/omap_hwmod_2xxx_interconnect_data.c |    4 +-
+ arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c |   10 +-
+ arch/arm/mach-omap2/omap_hwmod_33xx_data.c         | 3381 ++++++++++++++++++++
+ arch/arm/mach-omap2/omap_hwmod_3xxx_data.c         |  160 +-
+ arch/arm/mach-omap2/omap_hwmod_44xx_data.c         |    7 +-
+ arch/arm/mach-omap2/omap_hwmod_common_data.h       |    1 +
+ arch/arm/mach-omap2/omap_phy_internal.c            |    2 +
+ arch/arm/mach-omap2/opp.c                          |   15 +-
+ arch/arm/mach-omap2/opp2420_data.c                 |    2 +-
+ arch/arm/mach-omap2/opp2430_data.c                 |    2 +-
+ arch/arm/mach-omap2/opp3xxx_data.c                 |    2 -
+ arch/arm/mach-omap2/opp4xxx_data.c                 |    3 +-
+ arch/arm/mach-omap2/pm-debug.c                     |    1 -
+ arch/arm/mach-omap2/pm.c                           |    4 +-
+ arch/arm/mach-omap2/pm24xx.c                       |   14 +-
+ arch/arm/mach-omap2/pm34xx.c                       |   10 +-
+ arch/arm/mach-omap2/pm44xx.c                       |    8 +-
+ arch/arm/mach-omap2/powerdomain.c                  |   42 +-
+ arch/arm/mach-omap2/powerdomain2xxx_3xxx.c         |    4 +-
+ arch/arm/mach-omap2/powerdomain44xx.c              |    4 +-
+ arch/arm/mach-omap2/powerdomains3xxx_data.c        |    4 +-
+ arch/arm/mach-omap2/prcm.c                         |    9 +-
+ arch/arm/mach-omap2/prm2xxx_3xxx.c                 |    7 +-
+ arch/arm/mach-omap2/prm44xx.c                      |    5 +-
+ arch/arm/mach-omap2/prm_common.c                   |    1 -
+ arch/arm/mach-omap2/sdrc2xxx.c                     |    2 +-
+ arch/arm/mach-omap2/serial.c                       |   14 +-
+ arch/arm/mach-omap2/sleep24xx.S                    |    3 +-
+ arch/arm/mach-omap2/sleep34xx.S                    |    2 +-
+ arch/arm/mach-omap2/sleep44xx.S                    |    4 +-
+ arch/arm/mach-omap2/soc.h                          |    7 +
+ arch/arm/mach-omap2/sr_device.c                    |   13 +-
+ arch/arm/mach-omap2/sram242x.S                     |    3 +-
+ arch/arm/mach-omap2/sram243x.S                     |    3 +-
+ arch/arm/mach-omap2/sram34xx.S                     |    3 +-
+ .../include/plat => mach-omap2}/ti81xx.h           |    0
+ arch/arm/mach-omap2/timer.c                        |   17 +-
+ arch/arm/mach-omap2/twl-common.c                   |    3 +-
+ arch/arm/mach-omap2/twl-common.h                   |    6 +-
+ arch/arm/mach-omap2/usb-host.c                     |    2 -
+ arch/arm/mach-omap2/usb-musb.c                     |    7 +-
+ arch/arm/mach-omap2/vc.c                           |    8 +-
+ arch/arm/mach-omap2/voltage.c                      |   12 +-
+ arch/arm/mach-omap2/voltage.h                      |    2 +-
+ arch/arm/mach-omap2/voltagedomains3xxx_data.c      |    3 +-
+ arch/arm/mach-omap2/vp.c                           |   16 +-
+ arch/arm/mach-orion5x/addr-map.c                   |    3 +-
+ arch/arm/mach-orion5x/common.c                     |   18 +-
+ arch/arm/mach-orion5x/d2net-setup.c                |    1 +
+ arch/arm/mach-orion5x/db88f5281-setup.c            |    2 +-
+ arch/arm/mach-orion5x/dns323-setup.c               |    3 +-
+ arch/arm/mach-orion5x/include/mach/bridge-regs.h   |   20 +-
+ arch/arm/mach-orion5x/include/mach/gpio.h          |    9 -
+ arch/arm/mach-orion5x/include/mach/io.h            |   22 -
+ arch/arm/mach-orion5x/include/mach/orion5x.h       |   72 +-
+ arch/arm/mach-orion5x/irq.c                        |    6 +-
+ arch/arm/mach-orion5x/kurobox_pro-setup.c          |    2 +-
+ arch/arm/mach-orion5x/net2big-setup.c              |    1 +
+ arch/arm/mach-orion5x/pci.c                        |   62 +-
+ arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c       |    1 -
+ arch/arm/mach-orion5x/rd88f5181l-ge-setup.c        |    1 -
+ arch/arm/mach-orion5x/rd88f5182-setup.c            |   72 +-
+ arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c       |    1 -
+ arch/arm/mach-picoxcell/Kconfig                    |   14 +
+ arch/arm/mach-picoxcell/Makefile.boot              |    1 -
+ arch/arm/mach-picoxcell/common.c                   |   13 +-
+ arch/arm/mach-picoxcell/include/mach/gpio.h        |    1 -
+ .../mach-picoxcell/include/mach/picoxcell_soc.h    |   25 -
+ arch/arm/mach-picoxcell/include/mach/timex.h       |   25 -
+ arch/arm/mach-picoxcell/include/mach/uncompress.h  |   21 -
+ arch/arm/mach-pnx4008/Makefile                     |   12 -
+ arch/arm/mach-pnx4008/Makefile.boot                |    4 -
+ arch/arm/mach-pnx4008/clock.c                      | 1001 ------
+ arch/arm/mach-pnx4008/clock.h                      |   43 -
+ arch/arm/mach-pnx4008/core.c                       |  290 --
+ arch/arm/mach-pnx4008/dma.c                        | 1105 -------
+ arch/arm/mach-pnx4008/gpio.c                       |  328 --
+ arch/arm/mach-pnx4008/i2c.c                        |   86 -
+ arch/arm/mach-pnx4008/include/mach/clock.h         |   62 -
+ arch/arm/mach-pnx4008/include/mach/debug-macro.S   |   21 -
+ arch/arm/mach-pnx4008/include/mach/dma.h           |  160 -
+ arch/arm/mach-pnx4008/include/mach/entry-macro.S   |  116 -
+ arch/arm/mach-pnx4008/include/mach/gpio-pnx4008.h  |  241 --
+ arch/arm/mach-pnx4008/include/mach/hardware.h      |   32 -
+ arch/arm/mach-pnx4008/include/mach/irq.h           |   42 -
+ arch/arm/mach-pnx4008/include/mach/irqs.h          |  215 --
+ arch/arm/mach-pnx4008/include/mach/platform.h      |   69 -
+ arch/arm/mach-pnx4008/include/mach/pm.h            |   33 -
+ arch/arm/mach-pnx4008/include/mach/timex.h         |   19 -
+ arch/arm/mach-pnx4008/include/mach/uncompress.h    |   46 -
+ arch/arm/mach-pnx4008/irq.c                        |  121 -
+ arch/arm/mach-pnx4008/pm.c                         |  153 -
+ arch/arm/mach-pnx4008/serial.c                     |   67 -
+ arch/arm/mach-pnx4008/sleep.S                      |  195 --
+ arch/arm/mach-pnx4008/time.c                       |  134 -
+ arch/arm/mach-pnx4008/time.h                       |   70 -
+ arch/arm/mach-prima2/Kconfig                       |   19 +
+ arch/arm/mach-prima2/Makefile                      |    5 +-
+ arch/arm/mach-prima2/clock.c                       |  510 ---
+ arch/arm/mach-prima2/{prima2.c => common.c}        |   12 +-
+ arch/arm/mach-prima2/include/mach/uncompress.h     |    4 +-
+ arch/arm/mach-prima2/irq.c                         |    2 +-
+ arch/arm/mach-prima2/timer.c                       |    8 +-
+ arch/arm/mach-pxa/Kconfig                          |   12 +
+ arch/arm/mach-pxa/Makefile                         |   11 +-
+ arch/arm/mach-pxa/am200epd.c                       |    2 +-
+ arch/arm/mach-pxa/am300epd.c                       |    2 +-
+ arch/arm/mach-pxa/balloon3.c                       |    8 +-
+ arch/arm/mach-pxa/clock-pxa3xx.c                   |    8 +-
+ arch/arm/mach-pxa/cm-x270.c                        |    4 +-
+ arch/arm/mach-pxa/cm-x2xx.c                        |    2 +-
+ arch/arm/mach-pxa/cm-x300.c                        |   10 +-
+ arch/arm/mach-pxa/colibri-evalboard.c              |    4 +-
+ arch/arm/mach-pxa/colibri-pxa270-income.c          |    6 +-
+ arch/arm/mach-pxa/colibri-pxa300.c                 |    4 +-
+ arch/arm/mach-pxa/colibri-pxa320.c                 |    4 +-
+ arch/arm/mach-pxa/colibri-pxa3xx.c                 |    6 +-
+ arch/arm/mach-pxa/corgi.c                          |    4 +-
+ arch/arm/mach-pxa/csb726.c                         |    4 +-
+ arch/arm/mach-pxa/devices.c                        |   31 +-
+ arch/arm/mach-pxa/em-x270.c                        |   10 +-
+ arch/arm/mach-pxa/eseries.c                        |    4 +-
+ arch/arm/mach-pxa/ezx.c                            |    8 +-
+ arch/arm/mach-pxa/gumstix.c                        |    2 +-
+ arch/arm/mach-pxa/hx4700.c                         |    2 +-
+ arch/arm/mach-pxa/idp.c                            |   85 +-
+ arch/arm/mach-pxa/include/mach/pxa3xx-regs.h       |    1 +
+ arch/arm/mach-pxa/irq.c                            |  131 +-
+ arch/arm/mach-pxa/leds-idp.c                       |  115 -
+ arch/arm/mach-pxa/leds-lubbock.c                   |  124 -
+ arch/arm/mach-pxa/leds-mainstone.c                 |  119 -
+ arch/arm/mach-pxa/leds.c                           |   32 -
+ arch/arm/mach-pxa/leds.h                           |   13 -
+ arch/arm/mach-pxa/littleton.c                      |    8 +-
+ arch/arm/mach-pxa/lpd270.c                         |    8 +-
+ arch/arm/mach-pxa/lubbock.c                        |  101 +-
+ arch/arm/mach-pxa/magician.c                       |    8 +-
+ arch/arm/mach-pxa/mainstone.c                      |  104 +-
+ arch/arm/mach-pxa/mioa701.c                        |    8 +-
+ arch/arm/mach-pxa/mxm8x10.c                        |    8 +-
+ arch/arm/mach-pxa/palm27x.c                        |    8 +-
+ arch/arm/mach-pxa/palmld.c                         |   10 +-
+ arch/arm/mach-pxa/palmt5.c                         |   10 +-
+ arch/arm/mach-pxa/palmtc.c                         |    6 +-
+ arch/arm/mach-pxa/palmte2.c                        |    8 +-
+ arch/arm/mach-pxa/palmtreo.c                       |   14 +-
+ arch/arm/mach-pxa/palmtx.c                         |   10 +-
+ arch/arm/mach-pxa/palmz72.c                        |   12 +-
+ arch/arm/mach-pxa/pcm990-baseboard.c               |    8 +-
+ arch/arm/mach-pxa/poodle.c                         |    6 +-
+ arch/arm/mach-pxa/pxa-dt.c                         |   63 +
+ arch/arm/mach-pxa/pxa27x.c                         |    2 +-
+ arch/arm/mach-pxa/pxa2xx.c                         |    2 +-
+ arch/arm/mach-pxa/pxa3xx-ulpi.c                    |    2 +-
+ arch/arm/mach-pxa/pxa3xx.c                         |   25 +-
+ arch/arm/mach-pxa/raumfeld.c                       |    8 +-
+ arch/arm/mach-pxa/saar.c                           |    2 +-
+ arch/arm/mach-pxa/sharpsl_pm.c                     |   30 +-
+ arch/arm/mach-pxa/spitz.c                          |    8 +-
+ arch/arm/mach-pxa/stargate2.c                      |    2 +-
+ arch/arm/mach-pxa/tavorevb.c                       |    4 +-
+ arch/arm/mach-pxa/tosa.c                           |    4 +-
+ arch/arm/mach-pxa/trizeps4.c                       |    8 +-
+ arch/arm/mach-pxa/viper.c                          |    4 +-
+ arch/arm/mach-pxa/vpac270.c                        |    8 +-
+ arch/arm/mach-pxa/z2.c                             |    6 +-
+ arch/arm/mach-pxa/zeus.c                           |    8 +-
+ arch/arm/mach-pxa/zylonite.c                       |   10 +-
+ arch/arm/mach-realview/core.c                      |  145 -
+ arch/arm/mach-realview/core.h                      |    5 +-
+ arch/arm/mach-realview/hotplug.c                   |   18 +-
+ arch/arm/mach-realview/include/mach/clkdev.h       |   16 -
+ arch/arm/mach-realview/include/mach/gpio.h         |    1 -
+ arch/arm/mach-realview/platsmp.c                   |   18 +-
+ arch/arm/mach-realview/realview_eb.c               |    7 +-
+ arch/arm/mach-realview/realview_pb1176.c           |    7 +-
+ arch/arm/mach-realview/realview_pb11mp.c           |    8 +-
+ arch/arm/mach-realview/realview_pba8.c             |    7 +-
+ arch/arm/mach-realview/realview_pbx.c              |    8 +-
+ arch/arm/mach-s3c24xx/clock-s3c2440.c              |   14 +
+ arch/arm/mach-s3c24xx/common-smdk.c                |    4 +-
+ arch/arm/mach-s3c24xx/h1940-bluetooth.c            |   14 +-
+ arch/arm/mach-s3c24xx/mach-amlm5900.c              |    2 +-
+ arch/arm/mach-s3c24xx/mach-anubis.c                |    9 +-
+ arch/arm/mach-s3c24xx/mach-at2440evb.c             |    6 +-
+ arch/arm/mach-s3c24xx/mach-bast.c                  |    8 +-
+ arch/arm/mach-s3c24xx/mach-gta02.c                 |   10 +-
+ arch/arm/mach-s3c24xx/mach-h1940.c                 |   12 +-
+ arch/arm/mach-s3c24xx/mach-jive.c                  |   18 +-
+ arch/arm/mach-s3c24xx/mach-mini2440.c              |   14 +-
+ arch/arm/mach-s3c24xx/mach-n30.c                   |    8 +-
+ arch/arm/mach-s3c24xx/mach-nexcoder.c              |   24 +-
+ arch/arm/mach-s3c24xx/mach-osiris-dvs.c            |   13 +-
+ arch/arm/mach-s3c24xx/mach-osiris.c                |   11 +-
+ arch/arm/mach-s3c24xx/mach-otom.c                  |    2 +-
+ arch/arm/mach-s3c24xx/mach-qt2410.c                |    8 +-
+ arch/arm/mach-s3c24xx/mach-rx1950.c                |   10 +-
+ arch/arm/mach-s3c24xx/mach-rx3715.c                |    2 +-
+ arch/arm/mach-s3c24xx/mach-smdk2410.c              |    2 +-
+ arch/arm/mach-s3c24xx/mach-smdk2413.c              |    4 +-
+ arch/arm/mach-s3c24xx/mach-smdk2416.c              |    8 +-
+ arch/arm/mach-s3c24xx/mach-smdk2440.c              |    2 +-
+ arch/arm/mach-s3c24xx/mach-smdk2443.c              |    2 +-
+ arch/arm/mach-s3c24xx/mach-tct_hammer.c            |    2 +-
+ arch/arm/mach-s3c24xx/mach-vr1000.c                |    6 +-
+ arch/arm/mach-s3c24xx/mach-vstms.c                 |    4 +-
+ arch/arm/mach-s3c24xx/setup-i2c.c                  |    2 +-
+ arch/arm/mach-s3c24xx/simtec-audio.c               |    2 +-
+ arch/arm/mach-s3c24xx/simtec-usb.c                 |    2 +-
+ arch/arm/mach-s3c64xx/dev-audio.c                  |    2 +-
+ arch/arm/mach-s3c64xx/mach-anw6410.c               |    2 +-
+ arch/arm/mach-s3c64xx/mach-crag6410-module.c       |   38 +-
+ arch/arm/mach-s3c64xx/mach-crag6410.c              |   16 +-
+ arch/arm/mach-s3c64xx/mach-hmt.c                   |    4 +-
+ arch/arm/mach-s3c64xx/mach-mini6410.c              |    4 +-
+ arch/arm/mach-s3c64xx/mach-ncp.c                   |    2 +-
+ arch/arm/mach-s3c64xx/mach-real6410.c              |    4 +-
+ arch/arm/mach-s3c64xx/mach-smartq.c                |    8 +-
+ arch/arm/mach-s3c64xx/mach-smdk6400.c              |    2 +-
+ arch/arm/mach-s3c64xx/mach-smdk6410.c              |    6 +-
+ arch/arm/mach-s3c64xx/setup-i2c0.c                 |    2 +-
+ arch/arm/mach-s3c64xx/setup-i2c1.c                 |    2 +-
+ arch/arm/mach-s3c64xx/setup-ide.c                  |    2 +-
+ arch/arm/mach-s5p64x0/dev-audio.c                  |    2 +-
+ arch/arm/mach-s5p64x0/mach-smdk6440.c              |    4 +-
+ arch/arm/mach-s5p64x0/mach-smdk6450.c              |    4 +-
+ arch/arm/mach-s5p64x0/setup-i2c0.c                 |    2 +-
+ arch/arm/mach-s5p64x0/setup-i2c1.c                 |    2 +-
+ arch/arm/mach-s5pc100/dev-audio.c                  |    2 +-
+ arch/arm/mach-s5pc100/mach-smdkc100.c              |    8 +-
+ arch/arm/mach-s5pc100/setup-i2c0.c                 |    2 +-
+ arch/arm/mach-s5pc100/setup-i2c1.c                 |    2 +-
+ arch/arm/mach-s5pv210/dev-audio.c                  |    2 +-
+ arch/arm/mach-s5pv210/mach-goni.c                  |    2 +-
+ arch/arm/mach-s5pv210/mach-smdkc110.c              |    4 +-
+ arch/arm/mach-s5pv210/mach-smdkv210.c              |    6 +-
+ arch/arm/mach-s5pv210/mach-torbreck.c              |    2 +-
+ arch/arm/mach-s5pv210/setup-i2c0.c                 |    2 +-
+ arch/arm/mach-s5pv210/setup-i2c1.c                 |    2 +-
+ arch/arm/mach-s5pv210/setup-i2c2.c                 |    2 +-
+ arch/arm/mach-sa1100/Makefile                      |    9 -
+ arch/arm/mach-sa1100/assabet.c                     |   87 +-
+ arch/arm/mach-sa1100/badge4.c                      |   30 +
+ arch/arm/mach-sa1100/cerf.c                        |   44 +-
+ arch/arm/mach-sa1100/collie.c                      |    2 +-
+ arch/arm/mach-sa1100/hackkit.c                     |   32 +
+ arch/arm/mach-sa1100/include/mach/simpad.h         |    2 +-
+ arch/arm/mach-sa1100/lart.c                        |   28 +-
+ arch/arm/mach-sa1100/leds-assabet.c                |  113 -
+ arch/arm/mach-sa1100/leds-badge4.c                 |  110 -
+ arch/arm/mach-sa1100/leds-cerf.c                   |  110 -
+ arch/arm/mach-sa1100/leds-hackkit.c                |  112 -
+ arch/arm/mach-sa1100/leds-lart.c                   |  101 -
+ arch/arm/mach-sa1100/leds.c                        |   50 -
+ arch/arm/mach-sa1100/leds.h                        |   13 -
+ arch/arm/mach-sa1100/shannon.c                     |    2 +-
+ arch/arm/mach-sa1100/simpad.c                      |    4 +-
+ arch/arm/mach-shark/Makefile                       |    4 +-
+ arch/arm/mach-shark/core.c                         |   19 -
+ arch/arm/mach-shark/include/mach/debug-macro.S     |    7 +-
+ arch/arm/mach-shark/include/mach/entry-macro.S     |    3 +-
+ arch/arm/mach-shark/include/mach/io.h              |   18 -
+ arch/arm/mach-shark/leds.c                         |  220 +-
+ arch/arm/mach-shark/pci.c                          |    5 +
+ arch/arm/mach-shmobile/board-ag5evm.c              |    2 +-
+ arch/arm/mach-shmobile/board-ap4evb.c              |   14 +-
+ arch/arm/mach-shmobile/board-armadillo800eva.c     |   33 +-
+ arch/arm/mach-shmobile/board-bonito.c              |    8 +-
+ arch/arm/mach-shmobile/board-g3evm.c               |   12 +-
+ arch/arm/mach-shmobile/board-g4evm.c               |   32 +-
+ arch/arm/mach-shmobile/board-kota2.c               |    1 +
+ arch/arm/mach-shmobile/board-kzm9d.c               |    1 +
+ arch/arm/mach-shmobile/board-kzm9g.c               |   17 +-
+ arch/arm/mach-shmobile/board-mackerel.c            |   24 +-
+ arch/arm/mach-shmobile/board-marzen.c              |   69 +-
+ arch/arm/mach-shmobile/clock-r8a7740.c             |   46 +-
+ arch/arm/mach-shmobile/clock-r8a7779.c             |   11 +-
+ arch/arm/mach-shmobile/clock-sh7367.c              |   44 +-
+ arch/arm/mach-shmobile/clock-sh7372.c              |   60 +-
+ arch/arm/mach-shmobile/clock-sh7377.c              |   50 +-
+ arch/arm/mach-shmobile/clock-sh73a0.c              |   70 +-
+ arch/arm/mach-shmobile/hotplug.c                   |   31 +-
+ arch/arm/mach-shmobile/include/mach/common.h       |   24 +-
+ arch/arm/mach-shmobile/include/mach/emev2.h        |    7 +-
+ arch/arm/mach-shmobile/include/mach/r8a7779.h      |    2 +
+ arch/arm/mach-shmobile/include/mach/sh73a0.h       |    2 +
+ arch/arm/mach-shmobile/intc-r8a7779.c              |   14 +-
+ arch/arm/mach-shmobile/intc-sh7372.c               |   27 +-
+ arch/arm/mach-shmobile/intc-sh73a0.c               |   20 +-
+ arch/arm/mach-shmobile/pfc-r8a7740.c               |    2 +-
+ arch/arm/mach-shmobile/pfc-r8a7779.c               |    2 +-
+ arch/arm/mach-shmobile/pfc-sh7367.c                |    2 +-
+ arch/arm/mach-shmobile/pfc-sh7372.c                |    2 +-
+ arch/arm/mach-shmobile/pfc-sh7377.c                |    2 +-
+ arch/arm/mach-shmobile/pfc-sh73a0.c                |    2 +-
+ arch/arm/mach-shmobile/platsmp.c                   |   96 +-
+ arch/arm/mach-shmobile/pm-rmobile.c                |    6 +-
+ arch/arm/mach-shmobile/pm-sh7372.c                 |   57 +-
+ arch/arm/mach-shmobile/setup-emev2.c               |   22 +
+ arch/arm/mach-shmobile/setup-sh7367.c              |    2 +-
+ arch/arm/mach-shmobile/setup-sh7377.c              |    2 +-
+ arch/arm/mach-shmobile/setup-sh73a0.c              |   23 +-
+ .../{include/mach/gpio.h => sh-gpio.h}             |   20 +-
+ arch/arm/mach-shmobile/smp-emev2.c                 |   47 +-
+ arch/arm/mach-shmobile/smp-r8a7779.c               |   48 +-
+ arch/arm/mach-shmobile/smp-sh73a0.c                |   48 +-
+ arch/arm/mach-socfpga/Kconfig                      |   16 +
+ arch/arm/mach-socfpga/Makefile.boot                |    1 -
+ arch/arm/mach-socfpga/include/mach/uncompress.h    |    9 -
+ arch/arm/mach-spear13xx/Makefile.boot              |    3 -
+ arch/arm/mach-spear13xx/hotplug.c                  |   22 +-
+ arch/arm/mach-spear13xx/include/mach/generic.h     |    3 +
+ arch/arm/mach-spear13xx/include/mach/gpio.h        |   19 -
+ arch/arm/mach-spear13xx/include/mach/spear.h       |   14 +-
+ arch/arm/mach-spear13xx/platsmp.c                  |   25 +-
+ arch/arm/mach-spear13xx/spear1310.c                |    1 +
+ arch/arm/mach-spear13xx/spear1340.c                |    1 +
+ arch/arm/mach-spear13xx/spear13xx.c                |    6 +-
+ arch/arm/mach-spear3xx/Makefile.boot               |    4 -
+ arch/arm/mach-spear3xx/include/mach/gpio.h         |   19 -
+ arch/arm/mach-spear6xx/Makefile.boot               |    2 -
+ arch/arm/mach-spear6xx/include/mach/gpio.h         |   19 -
+ arch/arm/mach-tegra/Kconfig                        |   27 -
+ arch/arm/mach-tegra/Makefile                       |   20 +-
+ arch/arm/mach-tegra/Makefile.boot                  |    8 -
+ arch/arm/mach-tegra/apbio.c                        |  122 +-
+ arch/arm/mach-tegra/board-dt-tegra20.c             |   53 +-
+ arch/arm/mach-tegra/board-dt-tegra30.c             |    2 +
+ arch/arm/mach-tegra/board-harmony-pcie.c           |   49 +-
+ arch/arm/mach-tegra/board-harmony-pinmux.c         |  156 -
+ arch/arm/mach-tegra/board-harmony-power.c          |  156 -
+ arch/arm/mach-tegra/board-harmony.c                |  197 --
+ arch/arm/mach-tegra/board-harmony.h                |   41 -
+ arch/arm/mach-tegra/board-paz00-pinmux.c           |  156 -
+ arch/arm/mach-tegra/board-paz00.c                  |  192 --
+ arch/arm/mach-tegra/board-paz00.h                  |   17 +-
+ arch/arm/mach-tegra/board-pinmux.c                 |   87 -
+ arch/arm/mach-tegra/board-pinmux.h                 |   54 -
+ arch/arm/mach-tegra/board-trimslice-pinmux.c       |  155 -
+ arch/arm/mach-tegra/board-trimslice.c              |  183 --
+ arch/arm/mach-tegra/board-trimslice.h              |   30 -
+ arch/arm/mach-tegra/clock.c                        |  574 +---
+ arch/arm/mach-tegra/clock.h                        |   40 +-
+ arch/arm/mach-tegra/common.c                       |    5 +-
+ arch/arm/mach-tegra/common.h                       |    4 +
+ arch/arm/mach-tegra/cpu-tegra.c                    |   48 +-
+ arch/arm/mach-tegra/devices.c                      |  701 ----
+ arch/arm/mach-tegra/devices.h                      |   60 -
+ arch/arm/mach-tegra/dma.c                          |  823 -----
+ arch/arm/mach-tegra/fuse.c                         |    4 +-
+ arch/arm/mach-tegra/headsmp.S                      |    6 +-
+ arch/arm/mach-tegra/hotplug.c                      |  127 +-
+ arch/arm/mach-tegra/include/mach/clk.h             |    3 +
+ arch/arm/mach-tegra/include/mach/dma.h             |   97 -
+ arch/arm/mach-tegra/include/mach/gpio.h            |    1 -
+ arch/arm/mach-tegra/include/mach/io.h              |   46 -
+ arch/arm/mach-tegra/include/mach/iomap.h           |    3 +
+ arch/arm/mach-tegra/include/mach/pinconf-tegra.h   |   63 -
+ arch/arm/mach-tegra/include/mach/suspend.h         |   38 -
+ arch/arm/mach-tegra/pcie.c                         |   95 +-
+ arch/arm/mach-tegra/platsmp.c                      |   52 +-
+ arch/arm/mach-tegra/powergate.c                    |   43 +-
+ arch/arm/mach-tegra/sleep-t20.S                    |   82 +
+ arch/arm/mach-tegra/sleep-t30.S                    |  107 +
+ arch/arm/mach-tegra/sleep.S                        |   33 +-
+ arch/arm/mach-tegra/sleep.h                        |   85 +
+ arch/arm/mach-tegra/tegra20_clocks.c               | 1624 ++++++++++
+ arch/arm/mach-tegra/tegra20_clocks.h               |   42 +
+ arch/arm/mach-tegra/tegra20_clocks_data.c          | 1139 +++++++
+ arch/arm/mach-tegra/tegra2_clocks.c                | 2484 --------------
+ arch/arm/mach-tegra/tegra30_clocks.c               | 2593 ++++++---------
+ arch/arm/mach-tegra/tegra30_clocks.h               |   53 +
+ arch/arm/mach-tegra/tegra30_clocks_data.c          | 1377 ++++++++
+ arch/arm/mach-tegra/tegra_cpu_car.h                |   87 +
+ arch/arm/mach-tegra/timer.c                        |    1 -
+ arch/arm/mach-u300/Kconfig                         |   43 +-
+ arch/arm/mach-u300/Makefile                        |    1 -
+ arch/arm/mach-u300/core.c                          |  100 +-
+ .../mach-u300/{include/mach => }/dma_channels.h    |   11 +-
+ arch/arm/mach-u300/i2c.c                           |    6 +-
+ arch/arm/mach-u300/include/mach/clkdev.h           |    7 -
+ arch/arm/mach-u300/include/mach/gpio.h             |    1 -
+ arch/arm/mach-u300/include/mach/irqs.h             |   36 +-
+ arch/arm/mach-u300/include/mach/platform.h         |   20 -
+ arch/arm/mach-u300/include/mach/syscon.h           |   32 +-
+ arch/arm/mach-u300/include/mach/u300-regs.h        |   19 +-
+ arch/arm/mach-u300/spi.c                           |    2 +-
+ arch/arm/mach-u300/timer.c                         |    5 +-
+ arch/arm/mach-u300/timer.h                         |    1 +
+ arch/arm/mach-u300/u300-gpio.h                     |   46 +-
+ arch/arm/mach-u300/u300.c                          |   57 -
+ arch/arm/mach-ux500/Kconfig                        |    2 +
+ arch/arm/mach-ux500/Makefile                       |    4 +-
+ arch/arm/mach-ux500/Makefile.boot                  |    2 -
+ .../{board-mop500-msp.c => board-mop500-audio.c}   |   27 +-
+ arch/arm/mach-ux500/board-mop500-msp.h             |   14 -
+ arch/arm/mach-ux500/board-mop500-regulators.c      |   15 +
+ arch/arm/mach-ux500/board-mop500-regulators.h      |    1 +
+ arch/arm/mach-ux500/board-mop500-sdi.c             |    4 +-
+ arch/arm/mach-ux500/board-mop500.c                 |   64 +-
+ arch/arm/mach-ux500/board-mop500.h                 |   11 +
+ arch/arm/mach-ux500/cache-l2x0.c                   |    2 +-
+ arch/arm/mach-ux500/clock.c                        |  715 -----
+ arch/arm/mach-ux500/clock.h                        |  164 -
+ arch/arm/mach-ux500/cpu-db8500.c                   |   15 +-
+ arch/arm/mach-ux500/cpu.c                          |   18 +-
+ arch/arm/mach-ux500/devices-common.h               |    2 +-
+ arch/arm/mach-ux500/hotplug.c                      |   36 +-
+ arch/arm/mach-ux500/include/mach/gpio.h            |    5 -
+ arch/arm/mach-ux500/include/mach/id.h              |   44 +-
+ arch/arm/mach-ux500/include/mach/setup.h           |    3 +
+ arch/arm/mach-ux500/platsmp.c                      |   28 +-
+ arch/arm/mach-ux500/timer.c                        |    2 +-
+ arch/arm/mach-ux500/usb.c                          |    2 +-
+ arch/arm/mach-versatile/core.c                     |   10 -
+ arch/arm/mach-versatile/include/mach/gpio.h        |    1 -
+ arch/arm/mach-versatile/include/mach/hardware.h    |    1 -
+ arch/arm/mach-versatile/pci.c                      |   22 +-
+ arch/arm/mach-vexpress/Kconfig                     |   64 +-
+ arch/arm/mach-vexpress/Makefile                    |    2 +
+ arch/arm/mach-vexpress/Makefile.boot               |   10 -
+ arch/arm/mach-vexpress/core.h                      |    4 +
+ arch/arm/mach-vexpress/ct-ca9x4.c                  |    1 +
+ arch/arm/mach-vexpress/hotplug.c                   |   18 +-
+ arch/arm/mach-vexpress/include/mach/gpio.h         |    1 -
+ arch/arm/mach-vexpress/include/mach/irqs.h         |    2 +
+ arch/arm/mach-vexpress/include/mach/timex.h        |   23 -
+ arch/arm/mach-vexpress/include/mach/uncompress.h   |   86 -
+ arch/arm/mach-vexpress/platsmp.c                   |   18 +-
+ arch/arm/mach-vexpress/v2m.c                       |    8 +-
+ arch/arm/mach-vt8500/Kconfig                       |   73 -
+ arch/arm/mach-vt8500/Makefile                      |    8 +-
+ arch/arm/mach-vt8500/bv07.c                        |   81 -
+ .../mach/gpio-tegra.h => mach-vt8500/common.h}     |   22 +-
+ arch/arm/mach-vt8500/devices-vt8500.c              |   96 -
+ arch/arm/mach-vt8500/devices-wm8505.c              |  103 -
+ arch/arm/mach-vt8500/devices.c                     |  281 --
+ arch/arm/mach-vt8500/devices.h                     |   89 -
+ arch/arm/mach-vt8500/gpio.c                        |  240 --
+ arch/arm/mach-vt8500/include/mach/gpio.h           |    1 -
+ arch/arm/mach-vt8500/include/mach/restart.h        |    4 +-
+ arch/arm/mach-vt8500/include/mach/vt8500_irqs.h    |   88 -
+ arch/arm/mach-vt8500/include/mach/vt8500_regs.h    |   79 -
+ arch/arm/mach-vt8500/include/mach/wm8505_irqs.h    |  115 -
+ arch/arm/mach-vt8500/include/mach/wm8505_regs.h    |   78 -
+ arch/arm/mach-vt8500/irq.c                         |  209 +-
+ arch/arm/mach-vt8500/restart.c                     |   54 -
+ arch/arm/mach-vt8500/timer.c                       |   67 +-
+ arch/arm/mach-vt8500/vt8500.c                      |  196 ++
+ arch/arm/mach-vt8500/wm8505_7in.c                  |   80 -
+ arch/arm/mach-w90x900/dev.c                        |    6 +-
+ arch/arm/mach-w90x900/mach-nuc950evb.c             |    2 +-
+ arch/arm/mm/cache-l2x0.c                           |    2 +-
+ arch/arm/mm/cache-tauros2.c                        |   83 +-
+ arch/arm/mm/ioremap.c                              |   14 +
+ arch/arm/mm/mmu.c                                  |   54 +-
+ arch/arm/plat-iop/pci.c                            |   25 +-
+ arch/arm/plat-iop/setup.c                          |    5 -
+ arch/arm/plat-mxc/Makefile                         |    2 +-
+ arch/arm/plat-mxc/clock.c                          |  257 --
+ arch/arm/plat-mxc/cpufreq.c                        |    1 -
+ arch/arm/plat-mxc/devices/platform-imx-uart.c      |    2 +-
+ .../plat-mxc/devices/platform-sdhci-esdhc-imx.c    |    2 +-
+ arch/arm/plat-mxc/include/mach/clock.h             |   70 -
+ arch/arm/plat-mxc/include/mach/common.h            |   10 +-
+ arch/arm/plat-mxc/include/mach/devices-common.h    |   32 +-
+ arch/arm/plat-mxc/include/mach/gpio.h              |    1 -
+ arch/arm/plat-mxc/include/mach/iomux-mx3.h         |    5 +
+ arch/arm/plat-mxc/include/mach/iomux-mx53.h        | 1219 -------
+ arch/arm/plat-mxc/include/mach/mx31.h              |    6 +-
+ arch/arm/plat-mxc/ssi-fiq-ksym.c                   |    2 +-
+ arch/arm/plat-mxc/ssi-fiq.S                        |   89 +-
+ arch/arm/plat-mxc/system.c                         |    4 -
+ arch/arm/plat-omap/Kconfig                         |    4 +-
+ arch/arm/plat-omap/Makefile                        |    3 +-
+ arch/arm/plat-omap/common.c                        |   42 +-
+ arch/arm/plat-omap/counter_32k.c                   |    3 -
+ arch/arm/plat-omap/debug-devices.c                 |    3 -
+ arch/arm/plat-omap/debug-leds.c                    |  294 +-
+ arch/arm/plat-omap/devices.c                       |   92 -
+ arch/arm/plat-omap/dma.c                           |   54 +-
+ arch/arm/plat-omap/fb.c                            |    2 -
+ arch/arm/plat-omap/i2c.c                           |    4 +-
+ arch/arm/plat-omap/include/plat/board.h            |  138 -
+ arch/arm/plat-omap/include/plat/cpu.h              |    3 +
+ arch/arm/plat-omap/include/plat/dma.h              |    2 +
+ arch/arm/plat-omap/include/plat/gpio-switch.h      |   54 -
+ arch/arm/plat-omap/include/plat/gpmc.h             |   19 +
+ arch/arm/plat-omap/include/plat/hardware.h         |  293 --
+ arch/arm/plat-omap/include/plat/irqs-44xx.h        |  144 -
+ arch/arm/plat-omap/include/plat/irqs.h             |  453 ---
+ arch/arm/plat-omap/include/plat/mmc.h              |    1 -
+ arch/arm/plat-omap/include/plat/omap-serial.h      |    2 -
+ arch/arm/plat-omap/include/plat/omap_device.h      |    2 +
+ arch/arm/plat-omap/include/plat/omap_hwmod.h       |    2 +
+ arch/arm/plat-omap/include/plat/param.h            |    8 -
+ arch/arm/plat-omap/include/plat/usb.h              |    1 -
+ arch/arm/plat-omap/mux.c                           |   90 -
+ arch/arm/plat-omap/omap-pm-noop.c                  |   39 +-
+ arch/arm/plat-omap/omap_device.c                   |  160 +-
+ arch/arm/plat-omap/sram.c                          |    1 -
+ arch/arm/plat-orion/Makefile                       |    9 +-
+ arch/arm/plat-orion/addr-map.c                     |   11 +-
+ arch/arm/plat-orion/common.c                       |   16 +-
+ arch/arm/plat-orion/gpio.c                         |    2 +-
+ arch/arm/plat-orion/include/plat/addr-map.h        |    4 +-
+ arch/arm/plat-orion/include/plat/common.h          |    8 +-
+ arch/arm/plat-orion/include/plat/mpp.h             |    2 +-
+ .../include/plat/{gpio.h => orion-gpio.h}          |    2 +-
+ arch/arm/plat-orion/include/plat/time.h            |    4 +-
+ arch/arm/plat-orion/irq.c                          |    2 +-
+ arch/arm/plat-orion/mpp.c                          |    7 +-
+ arch/arm/plat-orion/time.c                         |    8 +-
+ arch/arm/plat-samsung/clock.c                      |    8 +-
+ arch/arm/plat-samsung/devs.c                       |   25 +-
+ arch/arm/plat-samsung/include/plat/gpio-fns.h      |   97 -
+ arch/arm/plat-samsung/s5p-irq-gpioint.c            |    4 +-
+ arch/arm/plat-samsung/time.c                       |    1 -
+ arch/arm/plat-spear/include/plat/gpio.h            |    1 -
+ arch/arm/plat-versatile/Kconfig                    |    4 +-
+ arch/arm/plat-versatile/Makefile                   |    2 +
+ arch/arm/plat-versatile/include/plat/platsmp.h     |   14 +
+ arch/arm/plat-versatile/leds.c                     |    8 +-
+ arch/arm/plat-versatile/platsmp.c                  |   10 +-
+ arch/arm/tools/mach-types                          |    1 -
+ arch/powerpc/platforms/83xx/suspend.c              |    2 +-
+ arch/powerpc/platforms/cell/celleb_pci.c           |    2 +-
+ arch/powerpc/sysdev/fsl_msi.c                      |    8 +-
+ drivers/Kconfig                                    |    4 +
+ drivers/Makefile                                   |    3 +
+ drivers/ata/pata_ep93xx.c                          |    2 +-
+ drivers/ata/pata_pxa.c                             |    2 +-
+ drivers/ata/pata_samsung_cf.c                      |    2 +-
+ drivers/bus/Kconfig                                |   21 +
+ drivers/bus/Makefile                               |    8 +
+ drivers/bus/omap-ocp2scp.c                         |   88 +
+ {arch/arm/mach-omap2 => drivers/bus}/omap_l3_noc.c |    4 +-
+ {arch/arm/mach-omap2 => drivers/bus}/omap_l3_noc.h |    0
+ {arch/arm/mach-omap2 => drivers/bus}/omap_l3_smx.c |    0
+ {arch/arm/mach-omap2 => drivers/bus}/omap_l3_smx.h |    0
+ drivers/char/nwflash.c                             |   34 -
+ drivers/clk/Kconfig                                |   13 +
+ drivers/clk/Makefile                               |   11 +-
+ drivers/clk/clk-bcm2835.c                          |   59 +
+ drivers/clk/clk-ls1x.c                             |  111 +
+ drivers/clk/clk-max77686.c                         |  244 ++
+ drivers/clk/clk-prima2.c                           | 1171 +++++++
+ drivers/clk/clk-vt8500.c                           |  510 +++
+ drivers/clk/clk.c                                  |   57 +-
+ drivers/clk/mmp/Makefile                           |    9 +
+ drivers/clk/mmp/clk-apbc.c                         |  152 +
+ drivers/clk/mmp/clk-apmu.c                         |   97 +
+ drivers/clk/mmp/clk-frac.c                         |  153 +
+ drivers/clk/mmp/clk-mmp2.c                         |  449 +++
+ drivers/clk/mmp/clk-pxa168.c                       |  346 ++
+ drivers/clk/mmp/clk-pxa910.c                       |  320 ++
+ drivers/clk/mmp/clk.h                              |   35 +
+ drivers/clk/mxs/clk-imx23.c                        |   57 +-
+ drivers/clk/mxs/clk-imx28.c                        |  115 +-
+ drivers/clk/ux500/Makefile                         |   12 +
+ drivers/clk/ux500/clk-prcc.c                       |  164 +
+ drivers/clk/ux500/clk-prcmu.c                      |  252 ++
+ drivers/clk/ux500/clk.h                            |   48 +
+ drivers/clk/ux500/u8500_clk.c                      |  477 +++
+ drivers/clk/ux500/u8540_clk.c                      |   21 +
+ drivers/clk/ux500/u9540_clk.c                      |   21 +
+ drivers/clk/versatile/Makefile                     |    1 +
+ drivers/clk/versatile/clk-realview.c               |  114 +
+ drivers/clocksource/Makefile                       |    1 +
+ drivers/clocksource/bcm2835_timer.c                |  161 +
+ drivers/crypto/mv_cesa.c                           |   17 +-
+ drivers/crypto/ux500/cryp/cryp_core.c              |    2 +-
+ drivers/crypto/ux500/hash/hash_core.c              |    2 +-
+ drivers/dma/at_hdmac_regs.h                        |    2 +-
+ drivers/dma/ep93xx_dma.c                           |    2 +-
+ drivers/dma/imx-dma.c                              |    2 +-
+ drivers/dma/imx-sdma.c                             |    4 +-
+ drivers/dma/mmp_tdma.c                             |    2 +-
+ drivers/dma/mv_xor.c                               |    2 +-
+ drivers/dma/omap-dma.c                             |    2 +
+ drivers/dma/tegra20-apb-dma.c                      |    8 +-
+ drivers/gpio/Kconfig                               |   12 +
+ drivers/gpio/Makefile                              |    2 +
+ drivers/gpio/gpio-mpc8xxx.c                        |    2 +-
+ drivers/gpio/gpio-mvebu.c                          |  679 ++++
+ drivers/gpio/gpio-mxs.c                            |   48 +-
+ drivers/gpio/gpio-omap.c                           |   23 +-
+ drivers/gpio/gpio-pxa.c                            |   77 +-
+ drivers/gpio/gpio-samsung.c                        |  124 +-
+ drivers/gpio/gpio-tegra.c                          |    3 -
+ drivers/gpio/gpio-twl4030.c                        |   90 +-
+ drivers/gpio/gpio-vt8500.c                         |  316 ++
+ drivers/hwmon/gpio-fan.c                           |  120 +
+ drivers/hwmon/s3c-hwmon.c                          |    2 +-
+ drivers/i2c/busses/Kconfig                         |    2 +-
+ drivers/i2c/busses/i2c-davinci.c                   |    2 +-
+ drivers/i2c/busses/i2c-imx.c                       |    2 +-
+ drivers/i2c/busses/i2c-iop3xx.c                    |  121 +-
+ drivers/i2c/busses/i2c-mpc.c                       |   12 +-
+ drivers/i2c/busses/i2c-nuc900.c                    |    2 +-
+ drivers/i2c/busses/i2c-omap.c                      |    3 +-
+ drivers/i2c/busses/i2c-s3c2410.c                   |    2 +-
+ drivers/i2c/busses/i2c-tegra.c                     |  130 +-
+ drivers/input/keyboard/Kconfig                     |    2 +-
+ drivers/input/keyboard/davinci_keyscan.c           |    2 +-
+ drivers/input/keyboard/ep93xx_keypad.c             |    2 +-
+ drivers/input/keyboard/nomadik-ske-keypad.c        |    2 +-
+ drivers/input/keyboard/omap-keypad.c               |  156 +-
+ drivers/input/keyboard/pxa27x_keypad.c             |    2 +-
+ drivers/input/keyboard/pxa930_rotary.c             |    2 +-
+ drivers/input/keyboard/spear-keyboard.c            |    2 +-
+ drivers/input/keyboard/w90p910_keypad.c            |    2 +-
+ drivers/input/mouse/pxa930_trkball.c               |    2 +-
+ drivers/input/mouse/rpcmouse.c                     |    2 +-
+ drivers/input/serio/ams_delta_serio.c              |    2 +-
+ drivers/input/touchscreen/s3c2410_ts.c             |    2 +-
+ drivers/irqchip/Kconfig                            |    1 +
+ drivers/irqchip/Makefile                           |    1 +
+ drivers/irqchip/irq-bcm2835.c                      |  223 ++
+ drivers/leds/Kconfig                               |   10 +
+ drivers/leds/Makefile                              |    1 +
+ drivers/leds/leds-netxbig.c                        |    2 +-
+ drivers/leds/leds-ns2.c                            |    2 +-
+ drivers/leds/leds-s3c24xx.c                        |    2 +-
+ drivers/leds/ledtrig-cpu.c                         |  163 +
+ drivers/macintosh/mediabay.c                       |    8 +-
+ drivers/media/platform/davinci/vpbe_venc.c         |    2 +-
+ drivers/media/platform/omap/omap_vout.c            |    1 +
+ drivers/media/platform/omap3isp/isp.c              |    2 +
+ drivers/media/platform/s5p-fimc/mipi-csis.c        |    2 +-
+ drivers/media/platform/soc_camera/mx1_camera.c     |    2 +-
+ drivers/media/platform/soc_camera/mx2_camera.c     |    2 +-
+ drivers/media/platform/soc_camera/mx3_camera.c     |    4 +-
+ drivers/media/platform/soc_camera/pxa_camera.c     |    2 +-
+ drivers/mfd/da9052-i2c.c                           |    4 +-
+ drivers/mfd/mcp-sa11x0.c                           |    2 +-
+ drivers/mfd/twl-core.c                             |   54 +-
+ drivers/mmc/host/davinci_mmc.c                     |    2 +-
+ drivers/mmc/host/msm_sdcc.c                        |    2 +-
+ drivers/mmc/host/mvsdio.c                          |    2 +-
+ drivers/mmc/host/mxcmmc.c                          |    4 +-
+ drivers/mmc/host/omap_hsmmc.c                      |    3 +-
+ drivers/mmc/host/pxamci.c                          |    2 +-
+ drivers/mmc/host/s3cmci.c                          |    2 +-
+ drivers/mmc/host/sdhci-esdhc-imx.c                 |    2 +-
+ drivers/mmc/host/sdhci-tegra.c                     |    3 +-
+ drivers/mtd/nand/ams-delta.c                       |   10 +-
+ drivers/mtd/nand/davinci_nand.c                    |    4 +-
+ drivers/mtd/nand/mxc_nand.c                        |    2 +-
+ drivers/mtd/nand/nomadik_nand.c                    |    2 +-
+ drivers/mtd/nand/omap2.c                           |  303 +-
+ drivers/mtd/nand/orion_nand.c                      |    2 +-
+ drivers/mtd/nand/pxa3xx_nand.c                     |   89 +-
+ drivers/mtd/nand/s3c2410.c                         |    2 +-
+ drivers/mtd/onenand/omap2.c                        |   34 +-
+ drivers/net/can/mscan/mpc5xxx_can.c                |    4 +-
+ drivers/net/ethernet/netx-eth.c                    |    2 +-
+ drivers/net/ethernet/seeq/ether3.c                 |    4 +-
+ drivers/net/irda/pxaficp_ir.c                      |   30 +-
+ drivers/pcmcia/omap_cf.c                           |    2 +-
+ drivers/pcmcia/pxa2xx_base.c                       |    2 +-
+ drivers/pcmcia/pxa2xx_viper.c                      |    2 +-
+ drivers/pinctrl/Kconfig                            |   31 +
+ drivers/pinctrl/Makefile                           |    7 +
+ drivers/pinctrl/pinctrl-armada-370.c               |  421 +++
+ drivers/pinctrl/pinctrl-armada-xp.c                |  468 +++
+ drivers/pinctrl/pinctrl-coh901.c                   |  220 +-
+ drivers/pinctrl/pinctrl-dove.c                     |  620 ++++
+ drivers/pinctrl/pinctrl-exynos.c                   |  579 ++++
+ drivers/pinctrl/pinctrl-exynos.h                   |  218 ++
+ drivers/pinctrl/pinctrl-kirkwood.c                 |  472 +++
+ drivers/pinctrl/pinctrl-mvebu.c                    |  754 +++++
+ drivers/pinctrl/pinctrl-mvebu.h                    |  192 ++
+ drivers/pinctrl/pinctrl-samsung.c                  |  888 +++++
+ drivers/pinctrl/pinctrl-samsung.h                  |  239 ++
+ drivers/pinctrl/pinctrl-sirf.c                     |   58 +-
+ drivers/pinctrl/pinctrl-tegra.c                    |    2 -
+ drivers/pinctrl/pinctrl-tegra.h                    |   44 +
+ drivers/power/avs/smartreflex.c                    |    2 +
+ drivers/remoteproc/omap_remoteproc.c               |    2 +-
+ drivers/rtc/rtc-ab8500.c                           |    6 -
+ drivers/rtc/rtc-pxa.c                              |   11 +
+ drivers/rtc/rtc-vt8500.c                           |    9 +-
+ drivers/scsi/arm/eesox.c                           |    2 +-
+ drivers/sh/pfc/gpio.c                              |    1 +
+ drivers/spi/Kconfig                                |    2 +-
+ drivers/spi/spi-davinci.c                          |    2 +-
+ drivers/spi/spi-ep93xx.c                           |    4 +-
+ drivers/spi/spi-imx.c                              |    4 +-
+ drivers/spi/spi-nuc900.c                           |    2 +-
+ drivers/spi/spi-omap-uwire.c                       |    5 +-
+ drivers/spi/spi-omap2-mcspi.c                      |    4 +-
+ drivers/spi/spi-s3c64xx.c                          |    2 +-
+ drivers/spi/spi-tegra.c                            |   55 +-
+ .../staging/ste_rmi4/board-mop500-u8500uib-rmi4.c  |    1 -
+ drivers/staging/tidspbridge/core/dsp-clock.c       |    2 +-
+ drivers/staging/tidspbridge/core/tiomap3430.c      |    2 +-
+ drivers/staging/tidspbridge/core/tiomap3430_pwr.c  |    2 +-
+ drivers/staging/tidspbridge/core/tiomap_io.c       |    2 +-
+ drivers/staging/tidspbridge/core/wdt.c             |    2 +-
+ drivers/staging/tidspbridge/rmgr/drv_interface.c   |    2 +-
+ drivers/tty/serial/imx.c                           |    2 +-
+ drivers/tty/serial/mpc52xx_uart.c                  |    2 +-
+ drivers/tty/serial/serial_ks8695.c                 |    4 +-
+ drivers/tty/serial/vt8500_serial.c                 |   58 +-
+ drivers/usb/Kconfig                                |    1 -
+ drivers/usb/gadget/imx_udc.c                       |    2 +-
+ drivers/usb/gadget/pxa27x_udc.c                    |    2 +-
+ drivers/usb/gadget/s3c2410_udc.c                   |    2 +-
+ drivers/usb/host/Kconfig                           |    2 +-
+ drivers/usb/host/ehci-mxc.c                        |    2 +-
+ drivers/usb/host/ehci-orion.c                      |    2 +-
+ drivers/usb/host/ehci-s5p.c                        |    2 +-
+ drivers/usb/host/imx21-hcd.h                       |    2 +-
+ drivers/usb/host/ohci-da8xx.c                      |    2 +-
+ drivers/usb/host/ohci-exynos.c                     |    2 +-
+ drivers/usb/host/ohci-hcd.c                        |    2 +-
+ drivers/usb/host/ohci-nxp.c                        |   84 +-
+ drivers/usb/host/ohci-omap.c                       |    2 +-
+ drivers/usb/host/ohci-pxa27x.c                     |    4 +-
+ drivers/usb/host/ohci-s3c2410.c                    |    2 +-
+ drivers/usb/musb/da8xx.c                           |    2 +-
+ drivers/usb/musb/tusb6010_omap.c                   |    1 -
+ drivers/usb/musb/ux500_dma.c                       |    2 +-
+ drivers/usb/otg/isp1301_omap.c                     |    2 +-
+ drivers/usb/phy/tegra_usb_phy.c                    |    1 -
+ drivers/video/Kconfig                              |    6 +-
+ drivers/video/backlight/omap1_bl.c                 |    4 +-
+ drivers/video/da8xx-fb.c                           |    8 +-
+ drivers/video/ep93xx-fb.c                          |    2 +-
+ drivers/video/imxfb.c                              |    2 +-
+ drivers/video/msm/mddi.c                           |    2 +-
+ drivers/video/msm/mddi_client_dummy.c              |    2 +-
+ drivers/video/msm/mddi_client_nt35399.c            |    2 +-
+ drivers/video/msm/mddi_client_toshiba.c            |    2 +-
+ drivers/video/msm/mdp.c                            |    2 +-
+ drivers/video/msm/mdp_hw.h                         |    2 +-
+ drivers/video/msm/mdp_ppp.c                        |    2 +-
+ drivers/video/msm/msm_fb.c                         |    2 +-
+ drivers/video/mx3fb.c                              |    4 +-
+ drivers/video/nuc900fb.c                           |    2 +-
+ drivers/video/nuc900fb.h                           |    2 +-
+ drivers/video/omap/lcd_ams_delta.c                 |    2 +-
+ drivers/video/omap/lcd_mipid.c                     |    2 +-
+ drivers/video/omap/lcd_osk.c                       |    2 +-
+ drivers/video/omap2/dss/dispc.c                    |    2 +
+ drivers/video/omap2/omapfb/omapfb-main.c           |    1 +
+ drivers/video/pxafb.c                              |    2 +-
+ drivers/video/vt8500lcdfb.c                        |   81 +-
+ drivers/video/wm8505fb.c                           |   99 +-
+ drivers/video/wmt_ge_rops.c                        |    9 +-
+ drivers/watchdog/Kconfig                           |    6 +-
+ drivers/watchdog/ks8695_wdt.c                      |   14 +-
+ drivers/watchdog/mpc8xxx_wdt.c                     |    2 +-
+ drivers/watchdog/omap_wdt.c                        |    5 +
+ include/linux/atmel_tc.h                           |    2 +-
+ .../hardware.h => include/linux/bcm2835_timer.h    |   13 +-
+ include/linux/clk-provider.h                       |    6 +
+ .../mach/timex.h => include/linux/clk/bcm2835.h    |    9 +-
+ include/linux/i2c/twl.h                            |    3 -
+ .../mach/io.h => include/linux/irqchip/bcm2835.h   |   16 +-
+ include/linux/leds.h                               |   16 +
+ include/linux/mfd/twl6040.h                        |    1 -
+ include/linux/mod_devicetable.h                    |    2 +-
+ include/linux/of_irq.h                             |    5 +
+ include/linux/omapfb.h                             |    7 +-
+ .../linux/platform_data/asoc-imx-ssi.h             |    0
+ .../linux/platform_data/asoc-kirkwood.h            |    0
+ .../linux/platform_data/asoc-palm27x.h             |    0
+ .../linux/platform_data/asoc-s3c.h                 |    0
+ .../linux/platform_data/asoc-s3c24xx_simtec.h      |    0
+ .../linux/platform_data/asoc-ti-mcbsp.h            |    0
+ .../linux/platform_data/ata-pxa.h                  |    0
+ .../linux/platform_data/ata-samsung_cf.h           |    0
+ include/linux/platform_data/atmel-aes.h            |    2 +-
+ .../linux/platform_data/camera-mx1.h               |    0
+ .../linux/platform_data/camera-mx2.h               |    2 -
+ .../linux/platform_data/camera-mx3.h               |    0
+ .../linux/platform_data/camera-pxa.h               |    0
+ include/linux/platform_data/clk-realview.h         |    1 +
+ include/linux/platform_data/clk-ux500.h            |   17 +
+ .../linux/platform_data}/crypto-ux500.h            |    0
+ .../linux/platform_data/dma-atmel.h                |    0
+ .../linux/platform_data/dma-ep93xx.h               |    0
+ .../linux/platform_data/dma-imx-sdma.h             |    0
+ .../dma.h => include/linux/platform_data/dma-imx.h |    0
+ .../linux/platform_data/dma-mmp_tdma.h             |    0
+ .../linux/platform_data/dma-mv_xor.h               |    0
+ .../linux/platform_data/dsp-omap.h                 |    0
+ .../linux/platform_data/eth-netx.h                 |    0
+ .../linux/platform_data/gpio-omap.h                |   15 +-
+ .../linux/platform_data/hwmon-s3c.h                |    0
+ .../linux/platform_data/i2c-davinci.h              |    0
+ .../i2c.h => include/linux/platform_data/i2c-imx.h |    0
+ .../linux/platform_data/i2c-nuc900.h               |    0
+ .../linux/platform_data/i2c-s3c2410.h              |    0
+ .../linux/platform_data/irda-pxaficp.h             |    0
+ .../linux/platform_data/keyboard-pxa930_rotary.h   |    0
+ .../linux/platform_data/keyboard-spear.h           |    0
+ .../linux/platform_data/keypad-ep93xx.h            |    0
+ .../linux/platform_data/keypad-nomadik-ske.h       |    0
+ .../linux/platform_data/keypad-omap.h              |    0
+ .../linux/platform_data/keypad-pxa27x.h            |    0
+ .../linux/platform_data/keypad-w90p910.h           |    0
+ .../linux/platform_data/keyscan-davinci.h          |    0
+ .../linux/platform_data/lcd-mipid.h                |    0
+ .../linux/platform_data/leds-kirkwood-netxbig.h    |    0
+ .../linux/platform_data/leds-kirkwood-ns2.h        |    0
+ .../linux/platform_data/leds-s3c24xx.h             |    0
+ .../linux/platform_data/mfd-mcp-sa11x0.h           |    0
+ .../linux/platform_data/mipi-csis.h                |    0
+ .../linux/platform_data/mmc-davinci.h              |    0
+ .../linux/platform_data/mmc-esdhc-imx.h            |    0
+ .../linux/platform_data/mmc-msm_sdcc.h             |    0
+ .../linux/platform_data/mmc-mvsdio.h               |    0
+ .../linux/platform_data/mmc-mxcmmc.h               |    0
+ .../linux/platform_data/mmc-pxamci.h               |    0
+ .../linux/platform_data/mmc-s3cmci.h               |    0
+ .../linux/platform_data/mmc-sdhci-tegra.h          |    6 +-
+ .../linux/platform_data/mouse-pxa930_trkball.h     |    0
+ .../linux/platform_data/mtd-davinci-aemif.h        |    0
+ .../linux/platform_data/mtd-davinci.h              |    0
+ .../linux/platform_data/mtd-mxc_nand.h             |    0
+ .../linux/platform_data/mtd-nand-omap2.h           |    3 +-
+ .../linux/platform_data/mtd-nand-pxa3xx.h          |    0
+ .../linux/platform_data/mtd-nand-s3c2410.h         |    0
+ .../linux/platform_data/mtd-nomadik-nand.h         |    0
+ .../linux/platform_data/mtd-onenand-omap2.h        |    0
+ .../linux/platform_data/mtd-orion_nand.h           |    0
+ include/linux/platform_data/omap1_bl.h             |   11 +
+ .../linux/platform_data/pcmcia-pxa2xx_viper.h      |    0
+ .../linux/platform_data/pinctrl-coh901.h           |   13 +-
+ .../linux/platform_data/remoteproc-omap.h          |    0
+ .../linux/platform_data/serial-imx.h               |    0
+ .../linux/platform_data/spi-davinci.h              |    0
+ .../linux/platform_data/spi-ep93xx.h               |    0
+ .../spi.h => include/linux/platform_data/spi-imx.h |    0
+ .../linux/platform_data/spi-nuc900.h               |    0
+ .../linux/platform_data/spi-omap2-mcspi.h          |    0
+ .../linux/platform_data/spi-s3c64xx.h              |    0
+ .../linux/platform_data/touchscreen-s3c2410.h      |    0
+ .../linux/platform_data/usb-davinci.h              |    0
+ .../linux/platform_data/usb-ehci-mxc.h             |    0
+ .../linux/platform_data/usb-ehci-orion.h           |    0
+ .../linux/platform_data/usb-ehci-s5p.h             |    0
+ .../linux/platform_data/usb-exynos.h               |    0
+ .../linux/platform_data/usb-imx_udc.h              |    0
+ .../linux/platform_data/usb-musb-ux500.h           |    0
+ .../linux/platform_data/usb-mx2.h                  |    0
+ .../linux/platform_data/usb-ohci-pxa27x.h          |    0
+ .../linux/platform_data/usb-ohci-s3c2410.h         |    0
+ .../linux/platform_data/usb-pxa3xx-ulpi.h          |    0
+ .../linux/platform_data/usb-s3c2410_udc.h          |    0
+ .../linux/platform_data/video-ep93xx.h             |    0
+ .../linux/platform_data/video-imxfb.h              |    0
+ .../linux/platform_data/video-msm_fb.h             |    0
+ .../linux/platform_data/video-mx3fb.h              |    0
+ .../linux/platform_data/video-nuc900fb.h           |    0
+ .../linux/platform_data/video-pxafb.h              |    0
+ .../linux/platform_data/video-vt8500lcdfb.h        |    0
+ .../linux/platform_data/voltage-omap.h             |    0
+ include/linux/power/smartreflex.h                  |    2 +-
+ sound/soc/cirrus/ep93xx-ac97.c                     |    2 +-
+ sound/soc/cirrus/ep93xx-i2s.c                      |    2 +-
+ sound/soc/cirrus/ep93xx-pcm.c                      |    2 +-
+ sound/soc/fsl/imx-pcm-dma.c                        |    2 +-
+ sound/soc/fsl/imx-pcm-fiq.c                        |    2 +-
+ sound/soc/fsl/imx-ssi.c                            |    2 +-
+ sound/soc/fsl/imx-ssi.h                            |    2 +-
+ sound/soc/kirkwood/kirkwood-i2s.c                  |    2 +-
+ sound/soc/kirkwood/kirkwood-openrd.c               |    2 +-
+ sound/soc/kirkwood/kirkwood-t5325.c                |    2 +-
+ sound/soc/omap/am3517evm.c                         |    2 +-
+ sound/soc/omap/ams-delta.c                         |    4 +-
+ sound/soc/omap/mcbsp.c                             |    4 +-
+ sound/soc/omap/n810.c                              |    2 +-
+ sound/soc/omap/omap-abe-twl6040.c                  |    4 -
+ sound/soc/omap/omap-mcbsp.c                        |    3 +-
+ sound/soc/omap/omap-mcpdm.c                        |    2 +
+ sound/soc/omap/omap-pcm.c                          |    1 +
+ sound/soc/omap/omap3pandora.c                      |    2 +-
+ sound/soc/omap/osk5912.c                           |    2 +-
+ sound/soc/omap/rx51.c                              |    2 +-
+ sound/soc/omap/sdp3430.c                           |    3 +-
+ sound/soc/omap/zoom2.c                             |    2 +-
+ sound/soc/pxa/palm27x.c                            |    2 +-
+ sound/soc/samsung/ac97.c                           |    2 +-
+ sound/soc/samsung/i2s.c                            |    2 +-
+ sound/soc/samsung/pcm.c                            |    2 +-
+ sound/soc/samsung/s3c24xx_simtec.c                 |    2 +-
+ sound/soc/samsung/spdif.c                          |    2 +-
+ sound/soc/tegra/Kconfig                            |    2 +-
+ sound/soc/tegra/tegra_pcm.c                        |  232 --
+ sound/soc/tegra/tegra_pcm.h                        |   14 -
+ 1689 files changed, 43267 insertions(+), 39600 deletions(-)
+ create mode 100644 Documentation/arm/Marvell/README
+ create mode 100644 Documentation/devicetree/bindings/arm/bcm2835.txt
+ create mode 100644 Documentation/devicetree/bindings/arm/mrvl/tauros2.txt
+ create mode 100644 Documentation/devicetree/bindings/arm/msm/timer.txt
+ create mode 100644 Documentation/devicetree/bindings/arm/vt8500.txt
+ create mode 100644 Documentation/devicetree/bindings/arm/vt8500/via,vt8500-intc.txt
+ create mode 100644 Documentation/devicetree/bindings/arm/vt8500/via,vt8500-pmc.txt
+ create mode 100644 Documentation/devicetree/bindings/arm/vt8500/via,vt8500-timer.txt
+ create mode 100644 Documentation/devicetree/bindings/bus/omap-ocp2scp.txt
+ create mode 100644 Documentation/devicetree/bindings/clock/imx23-clock.txt
+ create mode 100644 Documentation/devicetree/bindings/clock/imx28-clock.txt
+ create mode 100644 Documentation/devicetree/bindings/clock/imx6q-clock.txt
+ create mode 100644 Documentation/devicetree/bindings/clock/vt8500.txt
+ create mode 100644 Documentation/devicetree/bindings/crypto/mv_cesa.txt
+ create mode 100644 Documentation/devicetree/bindings/gpio/gpio-fan.txt
+ create mode 100644 Documentation/devicetree/bindings/gpio/gpio-mvebu.txt
+ create mode 100644 Documentation/devicetree/bindings/gpio/gpio-vt8500.txt
+ create mode 100644 Documentation/devicetree/bindings/interrupt-controller/brcm,bcm2835-armctrl-ic.txt
+ create mode 100644 Documentation/devicetree/bindings/lpddr2/lpddr2-timings.txt
+ create mode 100644 Documentation/devicetree/bindings/lpddr2/lpddr2.txt
+ create mode 100644 Documentation/devicetree/bindings/media/exynos5-gsc.txt
+ create mode 100644 Documentation/devicetree/bindings/memory-controllers/ti/emif.txt
+ create mode 100644 Documentation/devicetree/bindings/mtd/pxa3xx-nand.txt
+ create mode 100644 Documentation/devicetree/bindings/pinctrl/marvell,armada-370-pinctrl.txt
+ create mode 100644 Documentation/devicetree/bindings/pinctrl/marvell,armada-xp-pinctrl.txt
+ create mode 100644 Documentation/devicetree/bindings/pinctrl/marvell,dove-pinctrl.txt
+ create mode 100644 Documentation/devicetree/bindings/pinctrl/marvell,kirkwood-pinctrl.txt
+ create mode 100644 Documentation/devicetree/bindings/pinctrl/marvell,mvebu-pinctrl.txt
+ create mode 100644 Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt
+ create mode 100644 Documentation/devicetree/bindings/rtc/pxa-rtc.txt
+ create mode 100644 Documentation/devicetree/bindings/rtc/via,vt8500-rtc.txt
+ create mode 100644 Documentation/devicetree/bindings/timer/brcm,bcm2835-system-timer.txt
+ create mode 100644 Documentation/devicetree/bindings/tty/serial/via,vt8500-uart.txt
+ create mode 100644 Documentation/devicetree/bindings/usb/via,vt8500-ehci.txt
+ create mode 100644 Documentation/devicetree/bindings/video/via,vt8500-fb.txt
+ create mode 100644 Documentation/devicetree/bindings/video/wm,prizm-ge-rops.txt
+ create mode 100644 Documentation/devicetree/bindings/video/wm,wm8505-fb.txt
+ create mode 100644 arch/arm/arm-soc-for-next-contents.txt
+ create mode 100644 arch/arm/boot/dts/Makefile
+ create mode 100644 arch/arm/boot/dts/armada-xp-mv78230.dtsi
+ create mode 100644 arch/arm/boot/dts/armada-xp-mv78260.dtsi
+ create mode 100644 arch/arm/boot/dts/armada-xp-mv78460.dtsi
+ create mode 100644 arch/arm/boot/dts/bcm2835-rpi-b.dts
+ create mode 100644 arch/arm/boot/dts/bcm2835.dtsi
+ rename arch/arm/boot/dts/{db8500.dtsi => dbx5x0.dtsi} (88%)
+ create mode 100644 arch/arm/boot/dts/dove-cm-a510.dts
+ create mode 100644 arch/arm/boot/dts/dove-cubox.dts
+ create mode 100644 arch/arm/boot/dts/dove-dove-db.dts
+ create mode 100644 arch/arm/boot/dts/dove.dtsi
+ create mode 100644 arch/arm/boot/dts/elpida_ecb240abacn.dtsi
+ create mode 100644 arch/arm/boot/dts/exynos4210-pinctrl.dtsi
+ create mode 100644 arch/arm/boot/dts/hrefv60plus.dts
+ create mode 100644 arch/arm/boot/dts/imx28-cfa10049.dts
+ create mode 100644 arch/arm/boot/dts/kirkwood-dockstar.dts
+ create mode 100644 arch/arm/boot/dts/kirkwood-iomega_ix2_200.dts
+ create mode 100644 arch/arm/boot/dts/kirkwood-km_kirkwood.dts
+ create mode 100644 arch/arm/boot/dts/msm8960-cdp.dts
+ create mode 100644 arch/arm/boot/dts/omap2420.dtsi
+ create mode 100644 arch/arm/boot/dts/omap2430.dtsi
+ rename arch/arm/boot/dts/{omap3-beagle.dts => omap3-beagle-xm.dts} (52%)
+ create mode 100644 arch/arm/boot/dts/omap3-overo.dtsi
+ create mode 100644 arch/arm/boot/dts/omap3-tobi.dts
+ create mode 100644 arch/arm/boot/dts/omap36xx.dtsi
+ delete mode 100644 arch/arm/boot/dts/prima2-cb.dts
+ create mode 100644 arch/arm/boot/dts/prima2-evb.dts
+ create mode 100644 arch/arm/boot/dts/prima2.dtsi
+ create mode 100644 arch/arm/boot/dts/pxa27x.dtsi
+ create mode 100644 arch/arm/boot/dts/pxa2xx.dtsi
+ create mode 100644 arch/arm/boot/dts/pxa3xx.dtsi
+ create mode 100644 arch/arm/boot/dts/tegra20-medcom-wide.dts
+ create mode 100644 arch/arm/boot/dts/tegra20-plutux.dts
+ create mode 100644 arch/arm/boot/dts/tegra20-tamonten.dtsi
+ create mode 100644 arch/arm/boot/dts/tegra20-tec.dts
+ create mode 100644 arch/arm/boot/dts/tegra30-cardhu-a02.dts
+ create mode 100644 arch/arm/boot/dts/tegra30-cardhu-a04.dts
+ delete mode 100644 arch/arm/boot/dts/tegra30-cardhu.dts
+ create mode 100644 arch/arm/boot/dts/tegra30-cardhu.dtsi
+ create mode 100644 arch/arm/boot/dts/tps65217.dtsi
+ create mode 100644 arch/arm/boot/dts/tps65910.dtsi
+ create mode 100644 arch/arm/boot/dts/vt8500-bv07.dts
+ create mode 100644 arch/arm/boot/dts/vt8500.dtsi
+ create mode 100644 arch/arm/boot/dts/wm8505-ref.dts
+ create mode 100644 arch/arm/boot/dts/wm8505.dtsi
+ create mode 100644 arch/arm/boot/dts/wm8650-mid.dts
+ create mode 100644 arch/arm/boot/dts/wm8650.dtsi
+ create mode 100644 arch/arm/configs/bcm2835_defconfig
+ delete mode 100644 arch/arm/configs/pnx4008_defconfig
+ delete mode 100644 arch/arm/include/asm/leds.h
+ rename arch/arm/{mach-highbank/include/mach/debug-macro.S => include/debug/highbank.S} (83%)
+ create mode 100644 arch/arm/include/debug/icedcc.S
+ rename arch/arm/{mach-mvebu/include/mach/debug-macro.S => include/debug/mvebu.S} (86%)
+ rename arch/arm/{mach-picoxcell/include/mach/debug-macro.S => include/debug/picoxcell.S} (89%)
+ rename arch/arm/{mach-socfpga/include/mach/debug-macro.S => include/debug/socfpga.S} (100%)
+ rename arch/arm/{mach-vexpress/include/mach/debug-macro.S => include/debug/vexpress.S} (100%)
+ delete mode 100644 arch/arm/kernel/leds.c
+ create mode 100644 arch/arm/mach-bcm2835/Makefile
+ create mode 100644 arch/arm/mach-bcm2835/Makefile.boot
+ create mode 100644 arch/arm/mach-bcm2835/bcm2835.c
+ rename arch/arm/{mach-picoxcell/include/mach/map.h => mach-bcm2835/include/mach/bcm2835_soc.h} (57%)
+ create mode 100644 arch/arm/mach-bcm2835/include/mach/debug-macro.S
+ rename arch/arm/{mach-pnx4008/include/mach/param.h => mach-bcm2835/include/mach/timex.h} (81%)
+ create mode 100644 arch/arm/mach-bcm2835/include/mach/uncompress.h
+ delete mode 100644 arch/arm/mach-bcmring/include/cfg_global.h
+ delete mode 100644 arch/arm/mach-bcmring/include/csp/cache.h
+ delete mode 100644 arch/arm/mach-bcmring/include/csp/delay.h
+ delete mode 100644 arch/arm/mach-bcmring/include/csp/errno.h
+ delete mode 100644 arch/arm/mach-bcmring/include/csp/intcHw.h
+ delete mode 100644 arch/arm/mach-bcmring/include/csp/module.h
+ delete mode 100644 arch/arm/mach-bcmring/include/csp/secHw.h
+ delete mode 100644 arch/arm/mach-bcmring/include/csp/stdint.h
+ delete mode 100644 arch/arm/mach-bcmring/include/csp/string.h
+ rename arch/arm/mach-bcmring/include/{cfg_global_defines.h => mach/cfg_global.h} (74%)
+ rename arch/arm/mach-bcmring/include/{ => mach}/csp/dmacHw.h (99%)
+ rename arch/arm/mach-bcmring/include/{ => mach}/csp/reg.h (81%)
+ rename arch/arm/mach-bcmring/include/{ => mach}/csp/tmrHw.h (99%)
+ delete mode 100644 arch/arm/mach-clps711x/p720t-leds.c
+ delete mode 100644 arch/arm/mach-dove/include/mach/gpio.h
+ delete mode 100644 arch/arm/mach-dove/include/mach/io.h
+ delete mode 100644 arch/arm/mach-footbridge/ebsa285-leds.c
+ delete mode 100644 arch/arm/mach-footbridge/netwinder-leds.c
+ create mode 100644 arch/arm/mach-highbank/Kconfig
+ delete mode 100644 arch/arm/mach-highbank/Makefile.boot
+ delete mode 100644 arch/arm/mach-highbank/include/mach/gpio.h
+ delete mode 100644 arch/arm/mach-highbank/include/mach/timex.h
+ delete mode 100644 arch/arm/mach-highbank/include/mach/uncompress.h
+ create mode 100644 arch/arm/mach-imx/clk.c
+ delete mode 100644 arch/arm/mach-imx/devices-imx53.h
+ delete mode 100644 arch/arm/mach-imx/efika.h
+ rename arch/arm/mach-imx/{imx53-dt.c => mach-imx53.c} (81%)
+ delete mode 100644 arch/arm/mach-imx/mach-mx51_efikamx.c
+ delete mode 100644 arch/arm/mach-imx/mach-mx51_efikasb.c
+ delete mode 100644 arch/arm/mach-imx/mach-mx53_ard.c
+ delete mode 100644 arch/arm/mach-imx/mach-mx53_evk.c
+ delete mode 100644 arch/arm/mach-imx/mach-mx53_loco.c
+ delete mode 100644 arch/arm/mach-imx/mach-mx53_smd.c
+ delete mode 100644 arch/arm/mach-imx/mx51_efika.c
+ delete mode 100644 arch/arm/mach-integrator/include/mach/io.h
+ delete mode 100644 arch/arm/mach-iop13xx/include/mach/io.h
+ delete mode 100644 arch/arm/mach-iop32x/include/mach/io.h
+ delete mode 100644 arch/arm/mach-iop33x/include/mach/io.h
+ delete mode 100644 arch/arm/mach-ixp4xx/include/mach/gpio.h
+ create mode 100644 arch/arm/mach-kirkwood/board-dockstar.c
+ create mode 100644 arch/arm/mach-kirkwood/board-iomega_ix2_200.c
+ create mode 100644 arch/arm/mach-kirkwood/board-km_kirkwood.c
+ delete mode 100644 arch/arm/mach-kirkwood/include/mach/gpio.h
+ delete mode 100644 arch/arm/mach-kirkwood/include/mach/io.h
+ create mode 100644 arch/arm/mach-ks8695/board-og.c
+ create mode 100644 arch/arm/mach-ks8695/board-sg.c
+ delete mode 100644 arch/arm/mach-ks8695/include/mach/regs-timer.h
+ delete mode 100644 arch/arm/mach-ks8695/leds.c
+ create mode 100644 arch/arm/mach-mmp/clock-mmp2.c
+ create mode 100644 arch/arm/mach-mmp/clock-pxa168.c
+ create mode 100644 arch/arm/mach-mmp/clock-pxa910.c
+ delete mode 100644 arch/arm/mach-msm/acpuclock-arm11.c
+ delete mode 100644 arch/arm/mach-msm/acpuclock.h
+ create mode 100644 arch/arm/mach-msm/board-dt-8660.c
+ create mode 100644 arch/arm/mach-msm/board-dt-8960.c
+ delete mode 100644 arch/arm/mach-msm/board-msm7x27.c
+ delete mode 100644 arch/arm/mach-msm/board-msm8960.c
+ delete mode 100644 arch/arm/mach-msm/board-msm8x60.c
+ create mode 100644 arch/arm/mach-msm/common.h
+ create mode 100644 arch/arm/mach-msm/core.h
+ delete mode 100644 arch/arm/mach-msm/devices-msm8960.c
+ delete mode 100644 arch/arm/mach-msm/idle.c
+ delete mode 100644 arch/arm/mach-msm/include/mach/gpio.h
+ delete mode 100644 arch/arm/mach-msm/include/mach/system.h
+ delete mode 100644 arch/arm/mach-mv78xx0/include/mach/io.h
+ delete mode 100644 arch/arm/mach-mvebu/Makefile.boot
+ create mode 100644 arch/arm/mach-mvebu/addr-map.c
+ rename arch/arm/mach-mvebu/{include/mach => }/armada-370-xp.h (91%)
+ rename arch/arm/{mach-ep93xx => mach-mvebu}/include/mach/gpio.h (100%)
+ delete mode 100644 arch/arm/mach-mvebu/include/mach/timex.h
+ delete mode 100644 arch/arm/mach-mvebu/include/mach/uncompress.h
+ delete mode 100644 arch/arm/mach-mxs/devices-mx23.h
+ delete mode 100644 arch/arm/mach-mxs/devices-mx28.h
+ delete mode 100644 arch/arm/mach-mxs/devices.c
+ delete mode 100644 arch/arm/mach-mxs/devices/Kconfig
+ delete mode 100644 arch/arm/mach-mxs/devices/Makefile
+ delete mode 100644 arch/arm/mach-mxs/devices/platform-auart.c
+ delete mode 100644 arch/arm/mach-mxs/devices/platform-dma.c
+ delete mode 100644 arch/arm/mach-mxs/devices/platform-fec.c
+ delete mode 100644 arch/arm/mach-mxs/devices/platform-flexcan.c
+ delete mode 100644 arch/arm/mach-mxs/devices/platform-gpio-mxs.c
+ delete mode 100644 arch/arm/mach-mxs/devices/platform-gpmi-nand.c
+ delete mode 100644 arch/arm/mach-mxs/devices/platform-mxs-i2c.c
+ delete mode 100644 arch/arm/mach-mxs/devices/platform-mxs-mmc.c
+ delete mode 100644 arch/arm/mach-mxs/devices/platform-mxs-pwm.c
+ delete mode 100644 arch/arm/mach-mxs/devices/platform-mxs-saif.c
+ delete mode 100644 arch/arm/mach-mxs/devices/platform-mxsfb.c
+ delete mode 100644 arch/arm/mach-mxs/devices/platform-rtc-stmp3xxx.c
+ delete mode 100644 arch/arm/mach-mxs/include/mach/devices-common.h
+ delete mode 100644 arch/arm/mach-mxs/include/mach/entry-macro.S
+ delete mode 100644 arch/arm/mach-mxs/include/mach/gpio.h
+ delete mode 100644 arch/arm/mach-mxs/include/mach/iomux-mx23.h
+ delete mode 100644 arch/arm/mach-mxs/include/mach/iomux-mx28.h
+ delete mode 100644 arch/arm/mach-mxs/include/mach/iomux.h
+ delete mode 100644 arch/arm/mach-mxs/include/mach/irqs.h
+ delete mode 100644 arch/arm/mach-mxs/iomux.c
+ delete mode 100644 arch/arm/mach-mxs/mach-apx4devkit.c
+ delete mode 100644 arch/arm/mach-mxs/mach-m28evk.c
+ delete mode 100644 arch/arm/mach-mxs/mach-mx23evk.c
+ delete mode 100644 arch/arm/mach-mxs/mach-mx28evk.c
+ delete mode 100644 arch/arm/mach-mxs/mach-stmp378x_devb.c
+ delete mode 100644 arch/arm/mach-mxs/mach-tx28.c
+ delete mode 100644 arch/arm/mach-mxs/module-tx28.c
+ delete mode 100644 arch/arm/mach-mxs/module-tx28.h
+ delete mode 100644 arch/arm/mach-nomadik/include/mach/gpio.h
+ rename arch/arm/{plat-omap/include/plat => mach-omap1/include/mach}/board-ams-delta.h (100%)
+ rename arch/arm/{plat-omap/include/plat => mach-omap1/include/mach}/board-sx1.h (100%)
+ rename arch/arm/{plat-omap/include/plat => mach-omap1/include/mach}/board-voiceblue.h (100%)
+ rename arch/arm/{plat-omap/include/plat => mach-omap1/include/mach}/flash.h (100%)
+ rename arch/arm/{plat-omap/include/plat => mach-omap1/include/mach}/irda.h (100%)
+ rename arch/arm/{plat-omap/include/plat => mach-omap1/include/mach}/mux.h (100%)
+ rename arch/arm/{plat-omap/include/plat => mach-omap1/include/mach}/omap1510.h (97%)
+ rename arch/arm/{plat-omap/include/plat => mach-omap1/include/mach}/omap16xx.h (99%)
+ rename arch/arm/{plat-omap/include/plat => mach-omap1/include/mach}/omap7xx.h (98%)
+ delete mode 100644 arch/arm/mach-omap1/include/mach/smp.h
+ delete mode 100644 arch/arm/mach-omap1/leds-h2p2-debug.c
+ delete mode 100644 arch/arm/mach-omap1/leds-innovator.c
+ delete mode 100644 arch/arm/mach-omap1/leds-osk.c
+ delete mode 100644 arch/arm/mach-omap1/leds.c
+ delete mode 100644 arch/arm/mach-omap1/leds.h
+ rename arch/arm/{plat-omap/include/plat => mach-omap2}/am33xx.h (100%)
+ rename arch/arm/mach-omap2/{include/mach => }/am35xx.h (100%)
+ rename arch/arm/mach-omap2/{include/mach => }/board-rx51.h (100%)
+ rename arch/arm/mach-omap2/{include/mach => }/ctrl_module_core_44xx.h (100%)
+ rename arch/arm/mach-omap2/{include/mach => }/ctrl_module_pad_core_44xx.h (100%)
+ rename arch/arm/mach-omap2/{include/mach => }/ctrl_module_pad_wkup_44xx.h (100%)
+ rename arch/arm/mach-omap2/{include/mach => }/ctrl_module_wkup_44xx.h (100%)
+ create mode 100644 arch/arm/mach-omap2/debug-devices.h
+ rename arch/arm/{plat-omap/include/plat => mach-omap2}/gpmc-smc91x.h (100%)
+ rename arch/arm/{plat-omap/include/plat => mach-omap2}/gpmc-smsc911x.h (100%)
+ rename arch/arm/{plat-omap/include/plat => mach-omap2}/hdq1w.h (100%)
+ rename arch/arm/mach-omap2/{include/mach => }/id.h (100%)
+ delete mode 100644 arch/arm/mach-omap2/include/mach/smp.h
+ rename arch/arm/{plat-omap/include/plat => mach-omap2}/l3_2xxx.h (100%)
+ rename arch/arm/{plat-omap/include/plat => mach-omap2}/l3_3xxx.h (100%)
+ rename arch/arm/{plat-omap/include/plat => mach-omap2}/l4_2xxx.h (100%)
+ rename arch/arm/{plat-omap/include/plat => mach-omap2}/l4_3xxx.h (100%)
+ rename arch/arm/mach-omap2/{include/mach => }/omap-secure.h (100%)
+ rename arch/arm/mach-omap2/{include/mach => }/omap-wakeupgen.h (100%)
+ rename arch/arm/{plat-omap/include/plat => mach-omap2}/omap24xx.h (98%)
+ rename arch/arm/{plat-omap/include/plat => mach-omap2}/omap34xx.h (98%)
+ rename arch/arm/{plat-omap/include/plat => mach-omap2}/omap4-keypad.h (87%)
+ rename arch/arm/{plat-omap/include/plat => mach-omap2}/omap44xx.h (97%)
+ rename arch/arm/{plat-omap/include/plat => mach-omap2}/omap54xx.h (100%)
+ create mode 100644 arch/arm/mach-omap2/omap_hwmod_33xx_data.c
+ create mode 100644 arch/arm/mach-omap2/soc.h
+ rename arch/arm/{plat-omap/include/plat => mach-omap2}/ti81xx.h (100%)
+ delete mode 100644 arch/arm/mach-orion5x/include/mach/gpio.h
+ delete mode 100644 arch/arm/mach-orion5x/include/mach/io.h
+ create mode 100644 arch/arm/mach-picoxcell/Kconfig
+ delete mode 100644 arch/arm/mach-picoxcell/Makefile.boot
+ delete mode 100644 arch/arm/mach-picoxcell/include/mach/gpio.h
+ delete mode 100644 arch/arm/mach-picoxcell/include/mach/picoxcell_soc.h
+ delete mode 100644 arch/arm/mach-picoxcell/include/mach/timex.h
+ delete mode 100644 arch/arm/mach-picoxcell/include/mach/uncompress.h
+ delete mode 100644 arch/arm/mach-pnx4008/Makefile
+ delete mode 100644 arch/arm/mach-pnx4008/Makefile.boot
+ delete mode 100644 arch/arm/mach-pnx4008/clock.c
+ delete mode 100644 arch/arm/mach-pnx4008/clock.h
+ delete mode 100644 arch/arm/mach-pnx4008/core.c
+ delete mode 100644 arch/arm/mach-pnx4008/dma.c
+ delete mode 100644 arch/arm/mach-pnx4008/gpio.c
+ delete mode 100644 arch/arm/mach-pnx4008/i2c.c
+ delete mode 100644 arch/arm/mach-pnx4008/include/mach/clock.h
+ delete mode 100644 arch/arm/mach-pnx4008/include/mach/debug-macro.S
+ delete mode 100644 arch/arm/mach-pnx4008/include/mach/dma.h
+ delete mode 100644 arch/arm/mach-pnx4008/include/mach/entry-macro.S
+ delete mode 100644 arch/arm/mach-pnx4008/include/mach/gpio-pnx4008.h
+ delete mode 100644 arch/arm/mach-pnx4008/include/mach/hardware.h
+ delete mode 100644 arch/arm/mach-pnx4008/include/mach/irq.h
+ delete mode 100644 arch/arm/mach-pnx4008/include/mach/irqs.h
+ delete mode 100644 arch/arm/mach-pnx4008/include/mach/platform.h
+ delete mode 100644 arch/arm/mach-pnx4008/include/mach/pm.h
+ delete mode 100644 arch/arm/mach-pnx4008/include/mach/timex.h
+ delete mode 100644 arch/arm/mach-pnx4008/include/mach/uncompress.h
+ delete mode 100644 arch/arm/mach-pnx4008/irq.c
+ delete mode 100644 arch/arm/mach-pnx4008/pm.c
+ delete mode 100644 arch/arm/mach-pnx4008/serial.c
+ delete mode 100644 arch/arm/mach-pnx4008/sleep.S
+ delete mode 100644 arch/arm/mach-pnx4008/time.c
+ delete mode 100644 arch/arm/mach-pnx4008/time.h
+ create mode 100644 arch/arm/mach-prima2/Kconfig
+ delete mode 100644 arch/arm/mach-prima2/clock.c
+ rename arch/arm/mach-prima2/{prima2.c => common.c} (81%)
+ delete mode 100644 arch/arm/mach-pxa/leds-idp.c
+ delete mode 100644 arch/arm/mach-pxa/leds-lubbock.c
+ delete mode 100644 arch/arm/mach-pxa/leds-mainstone.c
+ delete mode 100644 arch/arm/mach-pxa/leds.c
+ delete mode 100644 arch/arm/mach-pxa/leds.h
+ create mode 100644 arch/arm/mach-pxa/pxa-dt.c
+ delete mode 100644 arch/arm/mach-realview/include/mach/clkdev.h
+ delete mode 100644 arch/arm/mach-realview/include/mach/gpio.h
+ delete mode 100644 arch/arm/mach-sa1100/leds-assabet.c
+ delete mode 100644 arch/arm/mach-sa1100/leds-badge4.c
+ delete mode 100644 arch/arm/mach-sa1100/leds-cerf.c
+ delete mode 100644 arch/arm/mach-sa1100/leds-hackkit.c
+ delete mode 100644 arch/arm/mach-sa1100/leds-lart.c
+ delete mode 100644 arch/arm/mach-sa1100/leds.c
+ delete mode 100644 arch/arm/mach-sa1100/leds.h
+ delete mode 100644 arch/arm/mach-shark/include/mach/io.h
+ rename arch/arm/mach-shmobile/{include/mach/gpio.h => sh-gpio.h} (69%)
+ create mode 100644 arch/arm/mach-socfpga/Kconfig
+ delete mode 100644 arch/arm/mach-socfpga/Makefile.boot
+ delete mode 100644 arch/arm/mach-socfpga/include/mach/uncompress.h
+ delete mode 100644 arch/arm/mach-spear13xx/include/mach/gpio.h
+ delete mode 100644 arch/arm/mach-spear3xx/include/mach/gpio.h
+ delete mode 100644 arch/arm/mach-spear6xx/include/mach/gpio.h
+ delete mode 100644 arch/arm/mach-tegra/board-harmony-pinmux.c
+ delete mode 100644 arch/arm/mach-tegra/board-harmony-power.c
+ delete mode 100644 arch/arm/mach-tegra/board-harmony.c
+ delete mode 100644 arch/arm/mach-tegra/board-harmony.h
+ delete mode 100644 arch/arm/mach-tegra/board-paz00-pinmux.c
+ delete mode 100644 arch/arm/mach-tegra/board-pinmux.c
+ delete mode 100644 arch/arm/mach-tegra/board-pinmux.h
+ delete mode 100644 arch/arm/mach-tegra/board-trimslice-pinmux.c
+ delete mode 100644 arch/arm/mach-tegra/board-trimslice.c
+ delete mode 100644 arch/arm/mach-tegra/board-trimslice.h
+ create mode 100644 arch/arm/mach-tegra/common.h
+ delete mode 100644 arch/arm/mach-tegra/devices.c
+ delete mode 100644 arch/arm/mach-tegra/devices.h
+ delete mode 100644 arch/arm/mach-tegra/dma.c
+ delete mode 100644 arch/arm/mach-tegra/include/mach/gpio.h
+ delete mode 100644 arch/arm/mach-tegra/include/mach/io.h
+ delete mode 100644 arch/arm/mach-tegra/include/mach/pinconf-tegra.h
+ delete mode 100644 arch/arm/mach-tegra/include/mach/suspend.h
+ create mode 100644 arch/arm/mach-tegra/sleep-t20.S
+ create mode 100644 arch/arm/mach-tegra/sleep-t30.S
+ create mode 100644 arch/arm/mach-tegra/sleep.h
+ create mode 100644 arch/arm/mach-tegra/tegra20_clocks.c
+ create mode 100644 arch/arm/mach-tegra/tegra20_clocks.h
+ create mode 100644 arch/arm/mach-tegra/tegra20_clocks_data.c
+ delete mode 100644 arch/arm/mach-tegra/tegra2_clocks.c
+ create mode 100644 arch/arm/mach-tegra/tegra30_clocks.h
+ create mode 100644 arch/arm/mach-tegra/tegra30_clocks_data.c
+ create mode 100644 arch/arm/mach-tegra/tegra_cpu_car.h
+ rename arch/arm/mach-u300/{include/mach => }/dma_channels.h (88%)
+ delete mode 100644 arch/arm/mach-u300/include/mach/clkdev.h
+ delete mode 100644 arch/arm/mach-u300/include/mach/gpio.h
+ delete mode 100644 arch/arm/mach-u300/include/mach/platform.h
+ create mode 100644 arch/arm/mach-u300/timer.h
+ delete mode 100644 arch/arm/mach-u300/u300.c
+ rename arch/arm/mach-ux500/{board-mop500-msp.c => board-mop500-audio.c} (88%)
+ delete mode 100644 arch/arm/mach-ux500/board-mop500-msp.h
+ delete mode 100644 arch/arm/mach-ux500/clock.c
+ delete mode 100644 arch/arm/mach-ux500/clock.h
+ delete mode 100644 arch/arm/mach-ux500/include/mach/gpio.h
+ delete mode 100644 arch/arm/mach-versatile/include/mach/gpio.h
+ delete mode 100644 arch/arm/mach-vexpress/Makefile.boot
+ delete mode 100644 arch/arm/mach-vexpress/include/mach/gpio.h
+ delete mode 100644 arch/arm/mach-vexpress/include/mach/timex.h
+ delete mode 100644 arch/arm/mach-vexpress/include/mach/uncompress.h
+ delete mode 100644 arch/arm/mach-vt8500/Kconfig
+ delete mode 100644 arch/arm/mach-vt8500/bv07.c
+ rename arch/arm/{mach-tegra/include/mach/gpio-tegra.h => mach-vt8500/common.h} (53%)
+ delete mode 100644 arch/arm/mach-vt8500/devices-vt8500.c
+ delete mode 100644 arch/arm/mach-vt8500/devices-wm8505.c
+ delete mode 100644 arch/arm/mach-vt8500/devices.c
+ delete mode 100644 arch/arm/mach-vt8500/devices.h
+ delete mode 100644 arch/arm/mach-vt8500/gpio.c
+ delete mode 100644 arch/arm/mach-vt8500/include/mach/gpio.h
+ delete mode 100644 arch/arm/mach-vt8500/include/mach/vt8500_irqs.h
+ delete mode 100644 arch/arm/mach-vt8500/include/mach/vt8500_regs.h
+ delete mode 100644 arch/arm/mach-vt8500/include/mach/wm8505_irqs.h
+ delete mode 100644 arch/arm/mach-vt8500/include/mach/wm8505_regs.h
+ delete mode 100644 arch/arm/mach-vt8500/restart.c
+ create mode 100644 arch/arm/mach-vt8500/vt8500.c
+ delete mode 100644 arch/arm/mach-vt8500/wm8505_7in.c
+ delete mode 100644 arch/arm/plat-mxc/clock.c
+ delete mode 100644 arch/arm/plat-mxc/include/mach/clock.h
+ delete mode 100644 arch/arm/plat-mxc/include/mach/gpio.h
+ delete mode 100644 arch/arm/plat-mxc/include/mach/iomux-mx53.h
+ delete mode 100644 arch/arm/plat-omap/devices.c
+ delete mode 100644 arch/arm/plat-omap/include/plat/board.h
+ delete mode 100644 arch/arm/plat-omap/include/plat/gpio-switch.h
+ delete mode 100644 arch/arm/plat-omap/include/plat/hardware.h
+ delete mode 100644 arch/arm/plat-omap/include/plat/irqs-44xx.h
+ delete mode 100644 arch/arm/plat-omap/include/plat/irqs.h
+ delete mode 100644 arch/arm/plat-omap/include/plat/param.h
+ delete mode 100644 arch/arm/plat-omap/mux.c
+ rename arch/arm/plat-orion/include/plat/{gpio.h => orion-gpio.h} (95%)
+ delete mode 100644 arch/arm/plat-spear/include/plat/gpio.h
+ create mode 100644 arch/arm/plat-versatile/include/plat/platsmp.h
+ create mode 100644 drivers/bus/Kconfig
+ create mode 100644 drivers/bus/Makefile
+ create mode 100644 drivers/bus/omap-ocp2scp.c
+ rename {arch/arm/mach-omap2 => drivers/bus}/omap_l3_noc.c (99%)
+ rename {arch/arm/mach-omap2 => drivers/bus}/omap_l3_noc.h (100%)
+ rename {arch/arm/mach-omap2 => drivers/bus}/omap_l3_smx.c (100%)
+ rename {arch/arm/mach-omap2 => drivers/bus}/omap_l3_smx.h (100%)
+ create mode 100644 drivers/clk/clk-bcm2835.c
+ create mode 100644 drivers/clk/clk-ls1x.c
+ create mode 100644 drivers/clk/clk-max77686.c
+ create mode 100644 drivers/clk/clk-prima2.c
+ create mode 100644 drivers/clk/clk-vt8500.c
+ create mode 100644 drivers/clk/mmp/Makefile
+ create mode 100644 drivers/clk/mmp/clk-apbc.c
+ create mode 100644 drivers/clk/mmp/clk-apmu.c
+ create mode 100644 drivers/clk/mmp/clk-frac.c
+ create mode 100644 drivers/clk/mmp/clk-mmp2.c
+ create mode 100644 drivers/clk/mmp/clk-pxa168.c
+ create mode 100644 drivers/clk/mmp/clk-pxa910.c
+ create mode 100644 drivers/clk/mmp/clk.h
+ create mode 100644 drivers/clk/ux500/Makefile
+ create mode 100644 drivers/clk/ux500/clk-prcc.c
+ create mode 100644 drivers/clk/ux500/clk-prcmu.c
+ create mode 100644 drivers/clk/ux500/clk.h
+ create mode 100644 drivers/clk/ux500/u8500_clk.c
+ create mode 100644 drivers/clk/ux500/u8540_clk.c
+ create mode 100644 drivers/clk/ux500/u9540_clk.c
+ create mode 100644 drivers/clk/versatile/clk-realview.c
+ create mode 100644 drivers/clocksource/bcm2835_timer.c
+ create mode 100644 drivers/gpio/gpio-mvebu.c
+ create mode 100644 drivers/gpio/gpio-vt8500.c
+ create mode 100644 drivers/irqchip/Kconfig
+ create mode 100644 drivers/irqchip/Makefile
+ create mode 100644 drivers/irqchip/irq-bcm2835.c
+ create mode 100644 drivers/leds/ledtrig-cpu.c
+ create mode 100644 drivers/pinctrl/pinctrl-armada-370.c
+ create mode 100644 drivers/pinctrl/pinctrl-armada-xp.c
+ create mode 100644 drivers/pinctrl/pinctrl-dove.c
+ create mode 100644 drivers/pinctrl/pinctrl-exynos.c
+ create mode 100644 drivers/pinctrl/pinctrl-exynos.h
+ create mode 100644 drivers/pinctrl/pinctrl-kirkwood.c
+ create mode 100644 drivers/pinctrl/pinctrl-mvebu.c
+ create mode 100644 drivers/pinctrl/pinctrl-mvebu.h
+ create mode 100644 drivers/pinctrl/pinctrl-samsung.c
+ create mode 100644 drivers/pinctrl/pinctrl-samsung.h
+ rename arch/arm/mach-picoxcell/include/mach/hardware.h => include/linux/bcm2835_timer.h (70%)
+ rename arch/arm/mach-socfpga/include/mach/timex.h => include/linux/clk/bcm2835.h (83%)
+ rename arch/arm/mach-versatile/include/mach/io.h => include/linux/irqchip/bcm2835.h (74%)
+ rename arch/arm/plat-mxc/include/mach/ssi.h => include/linux/platform_data/asoc-imx-ssi.h (100%)
+ rename arch/arm/plat-orion/include/plat/audio.h => include/linux/platform_data/asoc-kirkwood.h (100%)
+ rename arch/arm/mach-pxa/include/mach/palmasoc.h => include/linux/platform_data/asoc-palm27x.h (100%)
+ rename arch/arm/plat-samsung/include/plat/audio.h => include/linux/platform_data/asoc-s3c.h (100%)
+ rename arch/arm/plat-samsung/include/plat/audio-simtec.h => include/linux/platform_data/asoc-s3c24xx_simtec.h (100%)
+ rename arch/arm/plat-omap/include/plat/mcbsp.h => include/linux/platform_data/asoc-ti-mcbsp.h (100%)
+ rename arch/arm/mach-pxa/include/mach/pata_pxa.h => include/linux/platform_data/ata-pxa.h (100%)
+ rename arch/arm/plat-samsung/include/plat/ata.h => include/linux/platform_data/ata-samsung_cf.h (100%)
+ rename arch/arm/plat-mxc/include/mach/mx1_camera.h => include/linux/platform_data/camera-mx1.h (100%)
+ rename arch/arm/plat-mxc/include/mach/mx2_cam.h => include/linux/platform_data/camera-mx2.h (95%)
+ rename arch/arm/plat-mxc/include/mach/mx3_camera.h => include/linux/platform_data/camera-mx3.h (100%)
+ rename arch/arm/mach-pxa/include/mach/camera.h => include/linux/platform_data/camera-pxa.h (100%)
+ create mode 100644 include/linux/platform_data/clk-realview.h
+ create mode 100644 include/linux/platform_data/clk-ux500.h
+ rename {arch/arm/mach-ux500/include/mach => include/linux/platform_data}/crypto-ux500.h (100%)
+ rename arch/arm/mach-at91/include/mach/at_hdmac.h => include/linux/platform_data/dma-atmel.h (100%)
+ rename arch/arm/mach-ep93xx/include/mach/dma.h => include/linux/platform_data/dma-ep93xx.h (100%)
+ rename arch/arm/plat-mxc/include/mach/sdma.h => include/linux/platform_data/dma-imx-sdma.h (100%)
+ rename arch/arm/plat-mxc/include/mach/dma.h => include/linux/platform_data/dma-imx.h (100%)
+ rename arch/arm/mach-mmp/include/mach/sram.h => include/linux/platform_data/dma-mmp_tdma.h (100%)
+ rename arch/arm/plat-orion/include/plat/mv_xor.h => include/linux/platform_data/dma-mv_xor.h (100%)
+ rename arch/arm/plat-omap/include/plat/dsp.h => include/linux/platform_data/dsp-omap.h (100%)
+ rename arch/arm/mach-netx/include/mach/eth.h => include/linux/platform_data/eth-netx.h (100%)
+ rename arch/arm/plat-omap/include/plat/gpio.h => include/linux/platform_data/gpio-omap.h (94%)
+ rename arch/arm/plat-samsung/include/plat/hwmon.h => include/linux/platform_data/hwmon-s3c.h (100%)
+ rename arch/arm/mach-davinci/include/mach/i2c.h => include/linux/platform_data/i2c-davinci.h (100%)
+ rename arch/arm/plat-mxc/include/mach/i2c.h => include/linux/platform_data/i2c-imx.h (100%)
+ rename arch/arm/mach-w90x900/include/mach/i2c.h => include/linux/platform_data/i2c-nuc900.h (100%)
+ rename arch/arm/plat-samsung/include/plat/iic.h => include/linux/platform_data/i2c-s3c2410.h (100%)
+ rename arch/arm/mach-pxa/include/mach/irda.h => include/linux/platform_data/irda-pxaficp.h (100%)
+ rename arch/arm/mach-pxa/include/mach/pxa930_rotary.h => include/linux/platform_data/keyboard-pxa930_rotary.h (100%)
+ rename arch/arm/plat-spear/include/plat/keyboard.h => include/linux/platform_data/keyboard-spear.h (100%)
+ rename arch/arm/mach-ep93xx/include/mach/ep93xx_keypad.h => include/linux/platform_data/keypad-ep93xx.h (100%)
+ rename arch/arm/plat-nomadik/include/plat/ske.h => include/linux/platform_data/keypad-nomadik-ske.h (100%)
+ rename arch/arm/plat-omap/include/plat/keypad.h => include/linux/platform_data/keypad-omap.h (100%)
+ rename arch/arm/plat-pxa/include/plat/pxa27x_keypad.h => include/linux/platform_data/keypad-pxa27x.h (100%)
+ rename arch/arm/mach-w90x900/include/mach/w90p910_keypad.h => include/linux/platform_data/keypad-w90p910.h (100%)
+ rename arch/arm/mach-davinci/include/mach/keyscan.h => include/linux/platform_data/keyscan-davinci.h (100%)
+ rename arch/arm/plat-omap/include/plat/lcd_mipid.h => include/linux/platform_data/lcd-mipid.h (100%)
+ rename arch/arm/mach-kirkwood/include/mach/leds-netxbig.h => include/linux/platform_data/leds-kirkwood-netxbig.h (100%)
+ rename arch/arm/mach-kirkwood/include/mach/leds-ns2.h => include/linux/platform_data/leds-kirkwood-ns2.h (100%)
+ rename arch/arm/mach-s3c24xx/include/mach/leds-gpio.h => include/linux/platform_data/leds-s3c24xx.h (100%)
+ rename arch/arm/mach-sa1100/include/mach/mcp.h => include/linux/platform_data/mfd-mcp-sa11x0.h (100%)
+ rename arch/arm/plat-samsung/include/plat/mipi_csis.h => include/linux/platform_data/mipi-csis.h (100%)
+ rename arch/arm/mach-davinci/include/mach/mmc.h => include/linux/platform_data/mmc-davinci.h (100%)
+ rename arch/arm/plat-mxc/include/mach/esdhc.h => include/linux/platform_data/mmc-esdhc-imx.h (100%)
+ rename arch/arm/mach-msm/include/mach/mmc.h => include/linux/platform_data/mmc-msm_sdcc.h (100%)
+ rename arch/arm/plat-orion/include/plat/mvsdio.h => include/linux/platform_data/mmc-mvsdio.h (100%)
+ rename arch/arm/plat-mxc/include/mach/mmc.h => include/linux/platform_data/mmc-mxcmmc.h (100%)
+ rename arch/arm/mach-pxa/include/mach/mmc.h => include/linux/platform_data/mmc-pxamci.h (100%)
+ rename arch/arm/plat-samsung/include/plat/mci.h => include/linux/platform_data/mmc-s3cmci.h (100%)
+ rename arch/arm/mach-tegra/include/mach/sdhci.h => include/linux/platform_data/mmc-sdhci-tegra.h (84%)
+ rename arch/arm/mach-pxa/include/mach/pxa930_trkball.h => include/linux/platform_data/mouse-pxa930_trkball.h (100%)
+ rename arch/arm/mach-davinci/include/mach/aemif.h => include/linux/platform_data/mtd-davinci-aemif.h (100%)
+ rename arch/arm/mach-davinci/include/mach/nand.h => include/linux/platform_data/mtd-davinci.h (100%)
+ rename arch/arm/plat-mxc/include/mach/mxc_nand.h => include/linux/platform_data/mtd-mxc_nand.h (100%)
+ rename arch/arm/plat-omap/include/plat/nand.h => include/linux/platform_data/mtd-nand-omap2.h (96%)
+ rename arch/arm/plat-pxa/include/plat/pxa3xx_nand.h => include/linux/platform_data/mtd-nand-pxa3xx.h (100%)
+ rename arch/arm/plat-samsung/include/plat/nand.h => include/linux/platform_data/mtd-nand-s3c2410.h (100%)
+ rename arch/arm/mach-nomadik/include/mach/nand.h => include/linux/platform_data/mtd-nomadik-nand.h (100%)
+ rename arch/arm/plat-omap/include/plat/onenand.h => include/linux/platform_data/mtd-onenand-omap2.h (100%)
+ rename arch/arm/plat-orion/include/plat/orion_nand.h => include/linux/platform_data/mtd-orion_nand.h (100%)
+ create mode 100644 include/linux/platform_data/omap1_bl.h
+ rename arch/arm/mach-pxa/include/mach/arcom-pcmcia.h => include/linux/platform_data/pcmcia-pxa2xx_viper.h (100%)
+ rename arch/arm/mach-u300/include/mach/gpio-u300.h => include/linux/platform_data/pinctrl-coh901.h (72%)
+ rename arch/arm/plat-omap/include/plat/remoteproc.h => include/linux/platform_data/remoteproc-omap.h (100%)
+ rename arch/arm/plat-mxc/include/mach/imx-uart.h => include/linux/platform_data/serial-imx.h (100%)
+ rename arch/arm/mach-davinci/include/mach/spi.h => include/linux/platform_data/spi-davinci.h (100%)
+ rename arch/arm/mach-ep93xx/include/mach/ep93xx_spi.h => include/linux/platform_data/spi-ep93xx.h (100%)
+ rename arch/arm/plat-mxc/include/mach/spi.h => include/linux/platform_data/spi-imx.h (100%)
+ rename arch/arm/mach-w90x900/include/mach/nuc900_spi.h => include/linux/platform_data/spi-nuc900.h (100%)
+ rename arch/arm/plat-omap/include/plat/mcspi.h => include/linux/platform_data/spi-omap2-mcspi.h (100%)
+ rename arch/arm/plat-samsung/include/plat/s3c64xx-spi.h => include/linux/platform_data/spi-s3c64xx.h (100%)
+ rename arch/arm/plat-samsung/include/plat/ts.h => include/linux/platform_data/touchscreen-s3c2410.h (100%)
+ rename arch/arm/mach-davinci/include/mach/usb.h => include/linux/platform_data/usb-davinci.h (100%)
+ rename arch/arm/plat-mxc/include/mach/mxc_ehci.h => include/linux/platform_data/usb-ehci-mxc.h (100%)
+ rename arch/arm/plat-orion/include/plat/ehci-orion.h => include/linux/platform_data/usb-ehci-orion.h (100%)
+ rename arch/arm/plat-samsung/include/plat/ehci.h => include/linux/platform_data/usb-ehci-s5p.h (100%)
+ rename arch/arm/mach-exynos/include/mach/ohci.h => include/linux/platform_data/usb-exynos.h (100%)
+ rename arch/arm/plat-mxc/include/mach/usb.h => include/linux/platform_data/usb-imx_udc.h (100%)
+ rename arch/arm/mach-ux500/include/mach/usb.h => include/linux/platform_data/usb-musb-ux500.h (100%)
+ rename arch/arm/plat-mxc/include/mach/mx21-usbhost.h => include/linux/platform_data/usb-mx2.h (100%)
+ rename arch/arm/mach-pxa/include/mach/ohci.h => include/linux/platform_data/usb-ohci-pxa27x.h (100%)
+ rename arch/arm/plat-samsung/include/plat/usb-control.h => include/linux/platform_data/usb-ohci-s3c2410.h (100%)
+ rename arch/arm/mach-pxa/include/mach/pxa3xx-u2d.h => include/linux/platform_data/usb-pxa3xx-ulpi.h (100%)
+ rename arch/arm/plat-samsung/include/plat/udc.h => include/linux/platform_data/usb-s3c2410_udc.h (100%)
+ rename arch/arm/mach-ep93xx/include/mach/fb.h => include/linux/platform_data/video-ep93xx.h (100%)
+ rename arch/arm/plat-mxc/include/mach/imxfb.h => include/linux/platform_data/video-imxfb.h (100%)
+ rename arch/arm/mach-msm/include/mach/msm_fb.h => include/linux/platform_data/video-msm_fb.h (100%)
+ rename arch/arm/plat-mxc/include/mach/mx3fb.h => include/linux/platform_data/video-mx3fb.h (100%)
+ rename arch/arm/mach-w90x900/include/mach/fb.h => include/linux/platform_data/video-nuc900fb.h (100%)
+ rename arch/arm/mach-pxa/include/mach/pxafb.h => include/linux/platform_data/video-pxafb.h (100%)
+ rename arch/arm/mach-vt8500/include/mach/vt8500fb.h => include/linux/platform_data/video-vt8500lcdfb.h (100%)
+ rename arch/arm/plat-omap/include/plat/voltage.h => include/linux/platform_data/voltage-omap.h (100%)
+Merging ep93xx/ep93xx-for-next (70f0f7c Merge branch 'ep93xx-fixes' into ep93xx-for-next)
+$ git merge ep93xx/ep93xx-for-next
+Auto-merging arch/arm/mach-ep93xx/ts72xx.h
+Merge made by the 'recursive' strategy.
+ arch/arm/mach-ep93xx/adssphere.c                 |    1 +
+ arch/arm/mach-ep93xx/gesbc9312.c                 |    1 +
+ arch/arm/mach-ep93xx/ts72xx.c                    |   12 ++++++------
+ arch/arm/mach-ep93xx/{include/mach => }/ts72xx.h |   10 +++++-----
+ 4 files changed, 13 insertions(+), 11 deletions(-)
+ rename arch/arm/mach-ep93xx/{include/mach => }/ts72xx.h (89%)
+Merging ixp4xx/next (2346020 IXP4xx: map CPU config registers within VMALLOC region.)
+$ git merge ixp4xx/next
+Resolved 'arch/arm/mach-ixp4xx/common.c' using previous resolution.
+Resolved 'arch/arm/mach-ixp4xx/include/mach/ixp4xx-regs.h' using previous resolution.
+Auto-merging drivers/crypto/Kconfig
+Auto-merging drivers/char/hw_random/Kconfig
+Auto-merging arch/arm/mach-ixp4xx/include/mach/ixp4xx-regs.h
+CONFLICT (content): Merge conflict in arch/arm/mach-ixp4xx/include/mach/ixp4xx-regs.h
+Auto-merging arch/arm/mach-ixp4xx/common.c
+CONFLICT (content): Merge conflict in arch/arm/mach-ixp4xx/common.c
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master 65f789a] Merge remote-tracking branch 'ixp4xx/next'
+$ git diff -M --stat --summary HEAD^..
+ arch/arm/common/dmabounce.c                     |    4 +-
+ arch/arm/mach-ixp4xx/common-pci.c               |    1 +
+ arch/arm/mach-ixp4xx/common.c                   |   13 +++----
+ arch/arm/mach-ixp4xx/goramo_mlr.c               |    3 +-
+ arch/arm/mach-ixp4xx/include/mach/debug-macro.S |    4 +-
+ arch/arm/mach-ixp4xx/include/mach/ixp4xx-regs.h |   46 ++++++++++-------------
+ arch/arm/mach-ixp4xx/include/mach/qmgr.h        |   12 +++---
+ arch/arm/mach-ixp4xx/ixp4xx_npe.c               |    9 ++++-
+ arch/arm/mach-ixp4xx/ixp4xx_qmgr.c              |   14 +------
+ drivers/char/hw_random/Kconfig                  |    6 +--
+ drivers/char/hw_random/ixp4xx-rng.c             |    5 ++-
+ drivers/crypto/Kconfig                          |    2 +-
+ drivers/crypto/ixp4xx_crypto.c                  |   12 +++---
+ drivers/net/wan/ixp4xx_hss.c                    |    2 +-
+ 14 files changed, 62 insertions(+), 71 deletions(-)
+Merging msm/for-next (fe3a47b ARM: msm: Allow 8960 and 8660 to compile together)
+$ git merge msm/for-next
+Resolved 'arch/arm/mach-msm/board-dt-8660.c' using previous resolution.
+Resolved 'arch/arm/mach-msm/common.h' using previous resolution.
+CONFLICT (rename/delete): arch/arm/mach-vt8500/include/mach/restart.h deleted in msm/for-next and renamed in HEAD. Version HEAD of arch/arm/mach-vt8500/include/mach/restart.h left in tree.
+Auto-merging arch/arm/mach-msm/common.h
+CONFLICT (add/add): Merge conflict in arch/arm/mach-msm/common.h
+Auto-merging arch/arm/mach-msm/board-dt-8960.c
+CONFLICT (add/add): Merge conflict in arch/arm/mach-msm/board-dt-8960.c
+Auto-merging arch/arm/mach-msm/board-dt-8660.c
+CONFLICT (add/add): Merge conflict in arch/arm/mach-msm/board-dt-8660.c
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+Recorded resolution for 'arch/arm/mach-msm/board-dt-8960.c'.
+[master 17204c9] Merge remote-tracking branch 'msm/for-next'
+$ git diff -M --stat --summary HEAD^..
+ arch/arm/mach-msm/Makefile.boot |    3 +++
+ 1 file changed, 3 insertions(+)
+Merging renesas/next (cadd90f Merge branch 'heads/boards' into next)
+$ git merge renesas/next
+Auto-merging arch/arm/mach-shmobile/setup-sh7372.c
+Auto-merging arch/arm/mach-shmobile/setup-r8a7740.c
+Auto-merging arch/arm/mach-shmobile/include/mach/sh7372.h
+Auto-merging arch/arm/mach-shmobile/board-kzm9g.c
+Auto-merging arch/arm/configs/kzm9g_defconfig
+Auto-merging arch/arm/Kconfig
+Merge made by the 'recursive' strategy.
+ arch/arm/Kconfig                             |   19 +++++++++++++++++++
+ arch/arm/configs/armadillo800eva_defconfig   |    1 +
+ arch/arm/configs/kzm9g_defconfig             |    4 ++++
+ arch/arm/mach-shmobile/board-kzm9g.c         |   14 +++++++++++++-
+ arch/arm/mach-shmobile/include/mach/sh7372.h |    4 ++++
+ arch/arm/mach-shmobile/setup-r8a7740.c       |   16 ++++++++++++++++
+ arch/arm/mach-shmobile/setup-sh7372.c        |   20 ++++++++++++++++++++
+ arch/arm/mm/cache-v7.S                       |    3 +++
+ arch/arm/mm/proc-v7-2level.S                 |    8 ++++++++
+ 9 files changed, 88 insertions(+), 1 deletion(-)
+Merging samsung/for-next (d211921 Merge branch 'next/dt-samsung-new' into for-next)
+$ git merge samsung/for-next
+Resolved 'arch/arm/mach-exynos/Makefile.boot' using previous resolution.
+Auto-merging arch/arm/mach-exynos/Makefile.boot
+CONFLICT (content): Merge conflict in arch/arm/mach-exynos/Makefile.boot
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master 3c521f8] Merge remote-tracking branch 'samsung/for-next'
+$ git diff -M --stat --summary HEAD^..
+ arch/arm/boot/dts/exynos4.dtsi            |  248 +++++++++++++++++++++++++++++
+ arch/arm/boot/dts/exynos4210-origen.dts   |   63 +-------
+ arch/arm/boot/dts/exynos4210-smdkv310.dts |   54 +------
+ arch/arm/boot/dts/exynos4210-trats.dts    |  237 +++++++++++++++++++++++++++
+ arch/arm/boot/dts/exynos4210.dtsi         |  186 +---------------------
+ arch/arm/boot/dts/exynos5250-smdk5250.dts |    2 +-
+ arch/arm/mach-exynos/mach-exynos4-dt.c    |   32 ++--
+ 7 files changed, 526 insertions(+), 296 deletions(-)
+ create mode 100644 arch/arm/boot/dts/exynos4.dtsi
+ create mode 100644 arch/arm/boot/dts/exynos4210-trats.dts
+$ git am -3 ../patches/0001-ARM-fix-up-for-movemment-of-dtb-targets.patch
+Applying: ARM: fix up for movemment of dtb targets
+$ git reset HEAD^
+Unstaged changes after reset:
+M	arch/arm/boot/dts/Makefile
+$ git add .
+$ git commit -v -a --amend
+[master 8c11ead] Merge remote-tracking branch 'samsung/for-next'
+Merging tegra/for-next (979570e Linux 3.6-rc7)
+$ git merge tegra/for-next
+Already up-to-date.
+Merging kvmtool/master (5a337ac kvm tools: don't exit on debug ioport write)
+$ git merge kvmtool/master
+Merge made by the 'recursive' strategy.
+ tools/kvm/Makefile                       |   17 +
+ tools/kvm/builtin-run.c                  | 1111 +++++-------------------------
+ tools/kvm/disk/core.c                    |   73 +-
+ tools/kvm/framebuffer.c                  |    9 +-
+ tools/kvm/hw/i8042.c                     |   15 +-
+ tools/kvm/hw/pci-shmem.c                 |  147 +++-
+ tools/kvm/hw/rtc.c                       |   14 +-
+ tools/kvm/hw/serial.c                    |   24 +-
+ tools/kvm/hw/vesa.c                      |    6 +-
+ tools/kvm/include/kvm/brlock.h           |   16 +-
+ tools/kvm/include/kvm/disk-image.h       |    9 +-
+ tools/kvm/include/kvm/framebuffer.h      |    5 +-
+ tools/kvm/include/kvm/i8042.h            |    2 +-
+ tools/kvm/include/kvm/ioport.h           |    7 +-
+ tools/kvm/include/kvm/kvm-config.h       |   60 ++
+ tools/kvm/include/kvm/kvm-cpu.h          |    6 +-
+ tools/kvm/include/kvm/kvm-ipc.h          |    8 +-
+ tools/kvm/include/kvm/kvm.h              |   38 +-
+ tools/kvm/include/kvm/parse-options.h    |   16 +-
+ tools/kvm/include/kvm/pci-shmem.h        |    6 +-
+ tools/kvm/include/kvm/sdl.h              |   18 +-
+ tools/kvm/include/kvm/term.h             |   16 +-
+ tools/kvm/include/kvm/threadpool.h       |    3 +-
+ tools/kvm/include/kvm/util-init.h        |   51 ++
+ tools/kvm/include/kvm/virtio-9p.h        |    3 +
+ tools/kvm/include/kvm/virtio-balloon.h   |    3 +-
+ tools/kvm/include/kvm/virtio-console.h   |    3 +-
+ tools/kvm/include/kvm/virtio-net.h       |    6 +-
+ tools/kvm/include/kvm/vnc.h              |   10 +-
+ tools/kvm/ioeventfd.c                    |    2 +
+ tools/kvm/ioport.c                       |   23 +-
+ tools/kvm/kvm-cpu.c                      |   81 ++-
+ tools/kvm/kvm-ipc.c                      |  301 +++++++-
+ tools/kvm/kvm.c                          |  229 ++----
+ tools/kvm/mmio.c                         |   13 +-
+ tools/kvm/pci.c                          |   12 +-
+ tools/kvm/powerpc/cpu_info.c             |    2 +-
+ tools/kvm/powerpc/include/kvm/kvm-arch.h |   24 +-
+ tools/kvm/powerpc/irq.c                  |    2 +-
+ tools/kvm/powerpc/kvm-cpu.c              |    8 +-
+ tools/kvm/powerpc/kvm.c                  |   42 +-
+ tools/kvm/powerpc/spapr_hvcons.c         |   14 +-
+ tools/kvm/powerpc/spapr_pci.c            |    2 +-
+ tools/kvm/powerpc/xics.c                 |   24 +-
+ tools/kvm/symbol.c                       |    4 +-
+ tools/kvm/term.c                         |   61 +-
+ tools/kvm/tests/pit/tick.S               |   14 +-
+ tools/kvm/ui/sdl.c                       |   26 +-
+ tools/kvm/ui/vnc.c                       |   26 +-
+ tools/kvm/util/init.c                    |   69 ++
+ tools/kvm/util/threadpool.c              |   38 +-
+ tools/kvm/virtio/9p.c                    |   69 ++
+ tools/kvm/virtio/balloon.c               |   23 +-
+ tools/kvm/virtio/blk.c                   |    2 +
+ tools/kvm/virtio/console.c               |   26 +-
+ tools/kvm/virtio/net.c                   |  142 +++-
+ tools/kvm/virtio/pci.c                   |    6 +-
+ tools/kvm/virtio/rng.c                   |    5 +
+ tools/kvm/virtio/scsi.c                  |    2 +
+ tools/kvm/x86/bios.c                     |    6 +-
+ tools/kvm/x86/boot.c                     |    6 +-
+ tools/kvm/x86/include/kvm/kvm-arch.h     |   26 +-
+ tools/kvm/x86/ioport.c                   |   22 +-
+ tools/kvm/x86/irq.c                      |    2 +
+ tools/kvm/x86/kvm-cpu.c                  |   32 +-
+ tools/kvm/x86/kvm.c                      |   26 +-
+ tools/kvm/x86/mptable.c                  |    2 +
+ 67 files changed, 1664 insertions(+), 1452 deletions(-)
+ create mode 100644 tools/kvm/include/kvm/kvm-config.h
+ create mode 100644 tools/kvm/include/kvm/util-init.h
+ create mode 100644 tools/kvm/util/init.c
+Merging dma-mapping/dma-mapping-next (8aa8bee Merge branch 'next-cleanup' into HEAD)
+$ git merge dma-mapping/dma-mapping-next
+Resolved 'Documentation/devicetree/bindings/ata/ahci-platform.txt' using previous resolution.
+Resolved 'arch/arm/boot/dts/highbank.dts' using previous resolution.
+Auto-merging arch/arm/mm/mmu.c
+Auto-merging arch/arm/mach-highbank/highbank.c
+Auto-merging arch/arm/boot/dts/highbank.dts
+CONFLICT (content): Merge conflict in arch/arm/boot/dts/highbank.dts
+Auto-merging Documentation/devicetree/bindings/ata/ahci-platform.txt
+CONFLICT (content): Merge conflict in Documentation/devicetree/bindings/ata/ahci-platform.txt
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master b82b633] Merge remote-tracking branch 'dma-mapping/dma-mapping-next'
+$ git diff -M --stat --summary HEAD^..
+ .../devicetree/bindings/ata/ahci-platform.txt      |    1 +
+ .../devicetree/bindings/dma/arm-pl330.txt          |    3 +
+ .../devicetree/bindings/net/calxeda-xgmac.txt      |    3 +
+ arch/arm/boot/dts/highbank.dts                     |    1 +
+ arch/arm/include/asm/barrier.h                     |    7 +-
+ arch/arm/include/asm/dma-mapping.h                 |    1 +
+ arch/arm/include/asm/memory.h                      |    8 -
+ arch/arm/mach-highbank/highbank.c                  |   52 ++++
+ arch/arm/mm/dma-mapping.c                          |  266 +++++++++++++++-----
+ arch/arm/mm/mmu.c                                  |   11 -
+ drivers/base/dma-contiguous.c                      |   18 +-
+ 11 files changed, 280 insertions(+), 91 deletions(-)
+Merging pwm/for-next (6173f8f pwm: Move AB8500 PWM driver to PWM framework)
+$ git merge pwm/for-next
+Auto-merging drivers/pwm/pwm-ab8500.c
+Auto-merging drivers/pwm/Makefile
+Auto-merging drivers/pwm/Kconfig
+Auto-merging drivers/misc/Kconfig
+Merge made by the 'recursive' strategy.
+ Documentation/devicetree/bindings/pwm/imx-pwm.txt |   17 ++
+ Documentation/driver-model/devres.txt             |    4 +
+ Documentation/pwm.txt                             |    3 +-
+ drivers/misc/Kconfig                              |   10 -
+ drivers/misc/Makefile                             |    1 -
+ drivers/pwm/Kconfig                               |    9 +
+ drivers/pwm/Makefile                              |    1 +
+ drivers/pwm/core.c                                |   80 ++++++
+ drivers/{misc/ab8500-pwm.c => pwm/pwm-ab8500.c}   |  116 ++++-----
+ drivers/pwm/pwm-imx.c                             |  278 ++++++++++++++-------
+ drivers/pwm/pwm-tiecap.c                          |   22 ++
+ drivers/pwm/pwm-tiehrpwm.c                        |   73 ++++--
+ include/linux/pwm.h                               |  108 +++++++-
+ 13 files changed, 524 insertions(+), 198 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/pwm/imx-pwm.txt
+ rename drivers/{misc/ab8500-pwm.c => pwm/pwm-ab8500.c} (52%)
+Merging dma-buf/for-next (56d27ad Merge git://git.kernel.org/pub/scm/linux/kernel/git/cmetcalf/linux-tile)
+$ git merge dma-buf/for-next
+Already up-to-date.
+Merging userns/for-next (72235465 userns: Convert the ufs filesystem to use kuid/kgid where appropriate)
+$ git merge userns/for-next
+Resolved 'fs/ubifs/debug.c' using previous resolution.
+Resolved 'init/Kconfig' using previous resolution.
+Resolved 'kernel/audit.c' using previous resolution.
+Resolved 'kernel/auditsc.c' using previous resolution.
+Resolved 'security/integrity/ima/ima_policy.c' using previous resolution.
+Auto-merging security/security.c
+Auto-merging security/keys/keyctl.c
+Auto-merging security/keys/key.c
+Auto-merging security/integrity/ima/ima_policy.c
+CONFLICT (content): Merge conflict in security/integrity/ima/ima_policy.c
+Auto-merging net/xfrm/xfrm_user.c
+Auto-merging net/xfrm/xfrm_state.c
+Auto-merging net/xfrm/xfrm_policy.c
+Auto-merging net/netlabel/netlabel_unlabeled.c
+Auto-merging net/core/dev.c
+Auto-merging kernel/trace/trace.h
+Auto-merging kernel/trace/trace.c
+Auto-merging kernel/taskstats.c
+Auto-merging kernel/auditsc.c
+CONFLICT (content): Merge conflict in kernel/auditsc.c
+Auto-merging kernel/audit_watch.c
+Auto-merging kernel/audit.c
+CONFLICT (content): Merge conflict in kernel/audit.c
+Auto-merging init/Kconfig
+CONFLICT (content): Merge conflict in init/Kconfig
+Auto-merging include/net/xfrm.h
+Auto-merging include/linux/tty.h
+Auto-merging include/linux/security.h
+Auto-merging include/linux/sched.h
+Auto-merging include/linux/audit.h
+Auto-merging fs/xattr.c
+Auto-merging fs/udf/super.c
+Auto-merging fs/udf/inode.c
+Auto-merging fs/ubifs/ubifs.h
+Auto-merging fs/ubifs/super.c
+Auto-merging fs/ubifs/sb.c
+Auto-merging fs/ubifs/debug.c
+CONFLICT (content): Merge conflict in fs/ubifs/debug.c
+Auto-merging fs/ubifs/budget.c
+Auto-merging fs/reiserfs/inode.c
+Auto-merging fs/quota/dquot.c
+Auto-merging fs/proc/base.c
+Auto-merging fs/open.c
+Auto-merging fs/nfsd/vfs.c
+Auto-merging fs/logfs/readwrite.c
+Auto-merging fs/logfs/inode.c
+Auto-merging fs/jfs/super.c
+Auto-merging fs/jfs/jfs_incore.h
+Auto-merging fs/hfs/inode.c
+Auto-merging fs/gfs2/quota.c
+Auto-merging fs/ext4/super.c
+Auto-merging fs/ext3/super.c
+Auto-merging fs/exofs/inode.c
+Auto-merging fs/ecryptfs/main.c
+Auto-merging fs/debugfs/inode.c
+Auto-merging fs/btrfs/ioctl.c
+Auto-merging fs/btrfs/inode.c
+Auto-merging fs/btrfs/delayed-inode.c
+Auto-merging fs/affs/super.c
+Auto-merging drivers/usb/gadget/inode.c
+Auto-merging drivers/usb/gadget/f_fs.c
+Auto-merging drivers/staging/android/binder.c
+Auto-merging arch/s390/kernel/compat_linux.c
+Auto-merging arch/powerpc/mm/fault.c
+Auto-merging arch/ia64/kernel/perfmon.c
+Auto-merging arch/alpha/kernel/osf_sys.c
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+[master 161e2b6] Merge remote-tracking branch 'userns/for-next'
+$ git diff -M --stat --summary HEAD^..
+ arch/alpha/kernel/osf_sys.c         |    4 +-
+ arch/ia64/kernel/mca_drv.c          |    3 +-
+ arch/ia64/kernel/perfmon.c          |   32 +++---
+ arch/ia64/kernel/signal.c           |    4 +-
+ arch/powerpc/mm/fault.c             |    2 +-
+ arch/s390/hypfs/inode.c             |   20 +++-
+ arch/s390/kernel/compat_linux.c     |   36 ++++--
+ drivers/base/devtmpfs.c             |    4 +-
+ drivers/connector/cn_proc.c         |   18 ++-
+ drivers/gpu/drm/drm_fops.c          |    3 +-
+ drivers/gpu/drm/drm_info.c          |    5 +-
+ drivers/gpu/drm/drm_ioctl.c         |    4 +-
+ drivers/infiniband/hw/qib/qib_fs.c  |    4 +-
+ drivers/staging/android/binder.c    |   14 +--
+ drivers/tty/tty_audit.c             |   17 +--
+ drivers/usb/gadget/f_fs.c           |   23 ++--
+ drivers/usb/gadget/inode.c          |    4 +-
+ drivers/xen/xenfs/super.c           |    3 +-
+ fs/9p/acl.c                         |    8 +-
+ fs/adfs/adfs.h                      |    4 +-
+ fs/adfs/inode.c                     |    4 +-
+ fs/adfs/super.c                     |   21 ++--
+ fs/affs/affs.h                      |    4 +-
+ fs/affs/inode.c                     |   20 ++--
+ fs/affs/super.c                     |   18 +--
+ fs/befs/befs.h                      |    4 +-
+ fs/befs/linuxvfs.c                  |   27 +++--
+ fs/bfs/inode.c                      |    8 +-
+ fs/btrfs/acl.c                      |    8 +-
+ fs/btrfs/delayed-inode.c            |    8 +-
+ fs/btrfs/inode.c                    |    8 +-
+ fs/btrfs/ioctl.c                    |    6 +-
+ fs/configfs/inode.c                 |    4 +-
+ fs/cramfs/inode.c                   |    4 +-
+ fs/debugfs/inode.c                  |   26 +++--
+ fs/ecryptfs/main.c                  |    5 +-
+ fs/ecryptfs/messaging.c             |    5 +-
+ fs/efs/inode.c                      |    4 +-
+ fs/exofs/inode.c                    |    8 +-
+ fs/ext2/acl.c                       |   32 ++++--
+ fs/ext3/acl.c                       |   32 ++++--
+ fs/ext3/super.c                     |    2 +-
+ fs/ext4/acl.c                       |   31 +++--
+ fs/ext4/super.c                     |    2 +-
+ fs/fat/fat.h                        |    4 +-
+ fs/fat/file.c                       |    6 +-
+ fs/fat/inode.c                      |   18 ++-
+ fs/freevxfs/vxfs_inode.c            |    4 +-
+ fs/generic_acl.c                    |    4 +-
+ fs/gfs2/acl.c                       |   14 +--
+ fs/gfs2/quota.c                     |   32 +++---
+ fs/hfs/hfs_fs.h                     |    4 +-
+ fs/hfs/inode.c                      |    4 +-
+ fs/hfs/super.c                      |   16 ++-
+ fs/hfsplus/catalog.c                |    4 +-
+ fs/hfsplus/hfsplus_fs.h             |    4 +-
+ fs/hfsplus/inode.c                  |    8 +-
+ fs/hfsplus/options.c                |   15 ++-
+ fs/hostfs/hostfs_kern.c             |    8 +-
+ fs/hpfs/hpfs_fn.h                   |    4 +-
+ fs/hpfs/inode.c                     |   19 +--
+ fs/hpfs/namei.c                     |    8 +-
+ fs/hpfs/super.c                     |   18 +--
+ fs/hugetlbfs/inode.c                |   16 ++-
+ fs/isofs/inode.c                    |   17 ++-
+ fs/isofs/isofs.h                    |    4 +-
+ fs/isofs/rock.c                     |    4 +-
+ fs/jffs2/acl.c                      |   30 +++--
+ fs/jffs2/file.c                     |    8 +-
+ fs/jffs2/fs.c                       |   24 ++--
+ fs/jffs2/os-linux.h                 |    4 +-
+ fs/jfs/acl.c                        |    4 +-
+ fs/jfs/file.c                       |    4 +-
+ fs/jfs/jfs_imap.c                   |   22 ++--
+ fs/jfs/jfs_incore.h                 |    8 +-
+ fs/jfs/super.c                      |   22 ++--
+ fs/jfs/xattr.c                      |    4 +-
+ fs/logfs/inode.c                    |    4 +-
+ fs/logfs/readwrite.c                |    8 +-
+ fs/minix/inode.c                    |   16 +--
+ fs/nfs/nfs3acl.c                    |    4 +-
+ fs/nfsd/vfs.c                       |    8 +-
+ fs/nilfs2/inode.c                   |    8 +-
+ fs/ntfs/inode.c                     |    7 +-
+ fs/ntfs/super.c                     |   39 +++++--
+ fs/ntfs/volume.h                    |    5 +-
+ fs/ocfs2/acl.c                      |    4 +-
+ fs/ocfs2/file.c                     |    6 +-
+ fs/ocfs2/quota_global.c             |   43 ++++---
+ fs/ocfs2/quota_local.c              |   15 ++-
+ fs/omfs/inode.c                     |    8 +-
+ fs/omfs/omfs.h                      |    4 +-
+ fs/open.c                           |    2 +-
+ fs/posix_acl.c                      |   30 ++---
+ fs/proc/base.c                      |   27 ++++-
+ fs/qnx4/inode.c                     |    4 +-
+ fs/qnx6/inode.c                     |    4 +-
+ fs/quota/Makefile                   |    2 +-
+ fs/quota/dquot.c                    |  114 +++++++++---------
+ fs/quota/kqid.c                     |  132 +++++++++++++++++++++
+ fs/quota/netlink.c                  |   10 +-
+ fs/quota/quota.c                    |   28 ++++-
+ fs/quota/quota_tree.c               |   22 ++--
+ fs/quota/quota_v1.c                 |   12 +-
+ fs/quota/quota_v2.c                 |   26 +++--
+ fs/reiserfs/inode.c                 |   26 ++---
+ fs/reiserfs/xattr_acl.c             |   24 +++-
+ fs/squashfs/inode.c                 |    8 +-
+ fs/sysv/inode.c                     |    8 +-
+ fs/ubifs/budget.c                   |    4 +-
+ fs/ubifs/debug.c                    |    4 +-
+ fs/ubifs/journal.c                  |    4 +-
+ fs/ubifs/sb.c                       |    4 +-
+ fs/ubifs/super.c                    |    4 +-
+ fs/ubifs/ubifs.h                    |    4 +-
+ fs/udf/inode.c                      |   12 +-
+ fs/udf/super.c                      |   20 ++--
+ fs/udf/udf_sb.h                     |    4 +-
+ fs/ufs/inode.c                      |   16 +--
+ fs/xattr.c                          |    7 ++
+ fs/xattr_acl.c                      |   96 ++++++++++++++--
+ fs/xfs/xfs_acl.c                    |    4 +-
+ fs/xfs/xfs_quotaops.c               |   12 +-
+ fs/xfs/xfs_trans_dquot.c            |    8 +-
+ include/drm/drmP.h                  |    4 +-
+ include/linux/audit.h               |   12 +-
+ include/linux/init_task.h           |    2 +-
+ include/linux/ipc.h                 |    9 +-
+ include/linux/key.h                 |    9 +-
+ include/linux/posix_acl.h           |    8 +-
+ include/linux/posix_acl_xattr.h     |   18 ++-
+ include/linux/projid.h              |  104 +++++++++++++++++
+ include/linux/quota.h               |  136 +++++++++++++++++++++-
+ include/linux/quotaops.h            |    6 +-
+ include/linux/sched.h               |    2 +-
+ include/linux/security.h            |    6 +-
+ include/linux/tsacct_kern.h         |    8 +-
+ include/linux/tty.h                 |    4 +-
+ include/linux/user_namespace.h      |    3 +
+ include/net/netlabel.h              |    2 +-
+ include/net/xfrm.h                  |   23 ++--
+ init/Kconfig                        |   69 -----------
+ ipc/msg.c                           |   14 ++-
+ ipc/sem.c                           |   13 ++-
+ ipc/shm.c                           |   19 +--
+ ipc/util.c                          |   35 +++---
+ ipc/util.h                          |    2 +-
+ kernel/acct.c                       |    4 +-
+ kernel/audit.c                      |  121 ++++++++------------
+ kernel/audit.h                      |    4 +-
+ kernel/audit_watch.c                |    2 +-
+ kernel/auditfilter.c                |  137 +++++++++++++++++++---
+ kernel/auditsc.c                    |  216 ++++++++++++++++++-----------------
+ kernel/cred.c                       |   10 +-
+ kernel/taskstats.c                  |   23 +++-
+ kernel/trace/trace.c                |    3 +-
+ kernel/trace/trace.h                |    2 +-
+ kernel/tsacct.c                     |   12 +-
+ kernel/user.c                       |    8 ++
+ kernel/user_namespace.c             |  128 ++++++++++++++++++++-
+ net/core/dev.c                      |    2 +-
+ net/dns_resolver/dns_key.c          |    3 +-
+ net/netlabel/netlabel_unlabeled.c   |    2 +-
+ net/netlabel/netlabel_user.c        |    2 +-
+ net/rxrpc/ar-key.c                  |    6 +-
+ net/xfrm/xfrm_policy.c              |    8 +-
+ net/xfrm/xfrm_state.c               |    6 +-
+ net/xfrm/xfrm_user.c                |   12 +-
+ security/apparmor/domain.c          |    4 +-
+ security/apparmor/file.c            |   12 +-
+ security/apparmor/include/audit.h   |    2 +-
+ security/apparmor/include/file.h    |    4 +-
+ security/apparmor/lsm.c             |    2 +-
+ security/capability.c               |    2 +-
+ security/integrity/evm/evm_crypto.c |    4 +-
+ security/integrity/ima/ima_audit.c  |    5 +-
+ security/integrity/ima/ima_policy.c |   28 ++---
+ security/keys/internal.h            |    6 +-
+ security/keys/key.c                 |   23 ++--
+ security/keys/keyctl.c              |   50 ++++----
+ security/keys/keyring.c             |    4 +-
+ security/keys/permission.c          |   14 +--
+ security/keys/proc.c                |   44 +++----
+ security/keys/process_keys.c        |   15 +--
+ security/keys/request_key.c         |    6 +-
+ security/security.c                 |    2 +-
+ security/selinux/selinuxfs.c        |    6 +-
+ security/selinux/ss/services.c      |    2 +-
+ security/tomoyo/audit.c             |   23 ++--
+ security/tomoyo/common.c            |    4 +-
+ security/tomoyo/common.h            |    4 +-
+ security/tomoyo/condition.c         |   20 ++--
+ security/tomoyo/tomoyo.c            |   12 +-
+ 193 files changed, 2115 insertions(+), 1131 deletions(-)
+ create mode 100644 fs/quota/kqid.c
+ create mode 100644 include/linux/projid.h
+$ git am -3 ../patches/0001-audit-fix-up-for-pid-to-portid-change.patch
+Applying: audit: fix up for pid to portid change
+$ git reset HEAD^
+Unstaged changes after reset:
+M	kernel/audit.c
+$ git add .
+$ git commit -v -a --amend
+[master d4ea11d] Merge remote-tracking branch 'userns/for-next'
+Merging ktest/for-next (648a182 ktest: Allow a test to override REBOOT_ON_SUCCESS)
+$ git merge ktest/for-next
+Already up-to-date.
+Merging signal/for-next (3af7cae alpha: don't open-code trace_report_syscall_{enter,exit})
+$ git merge signal/for-next
+Recorded preimage for 'arch/x86/Kconfig'
+Resolved 'arch/alpha/Kconfig' using previous resolution.
+Resolved 'arch/arm/Kconfig' using previous resolution.
+Resolved 'arch/arm/include/asm/thread_info.h' using previous resolution.
+Resolved 'arch/c6x/Kconfig' using previous resolution.
+Resolved 'arch/cris/include/asm/Kbuild' using previous resolution.
+Resolved 'arch/h8300/include/asm/Kbuild' using previous resolution.
+Resolved 'arch/m32r/include/asm/Kbuild' using previous resolution.
+Resolved 'arch/m68k/Kconfig' using previous resolution.
+Resolved 'arch/mn10300/Kconfig' using previous resolution.
+Resolved 'arch/x86/kernel/process_32.c' using previous resolution.
+Auto-merging kernel/sched/core.c
+Auto-merging kernel/fork.c
+Auto-merging include/linux/sched.h
+Auto-merging include/linux/ptrace.h
+Auto-merging fs/exec.c
+Removing arch/xtensa/include/asm/exec.h
+Auto-merging arch/x86/um/Kconfig
+Removing arch/x86/kernel/sys_i386_32.c
+Auto-merging arch/x86/kernel/signal.c
+Auto-merging arch/x86/kernel/process_64.c
+Auto-merging arch/x86/kernel/process_32.c
+CONFLICT (content): Merge conflict in arch/x86/kernel/process_32.c
+Auto-merging arch/x86/kernel/process.c
+Auto-merging arch/x86/kernel/entry_64.S
+Auto-merging arch/x86/kernel/entry_32.S
+Auto-merging arch/x86/kernel/Makefile
+Auto-merging arch/x86/include/asm/sys_ia32.h
+Auto-merging arch/x86/include/asm/processor.h
+Auto-merging arch/x86/ia32/sys_ia32.c
+Auto-merging arch/x86/ia32/ia32entry.S
+Auto-merging arch/x86/Kconfig
+CONFLICT (content): Merge conflict in arch/x86/Kconfig
+Removing arch/unicore32/include/asm/exec.h
+Removing arch/um/kernel/internal.h
+Removing arch/tile/include/asm/exec.h
+Removing arch/sparc/include/asm/exec.h
+Auto-merging arch/sparc/include/asm/Kbuild
+Removing arch/sh/include/asm/exec.h
+Auto-merging arch/s390/kernel/process.c
+Auto-merging arch/s390/kernel/entry64.S
+Auto-merging arch/s390/kernel/compat_wrapper.S
+Auto-merging arch/s390/kernel/compat_linux.c
+Auto-merging arch/s390/include/asm/unistd.h
+Auto-merging arch/s390/include/asm/processor.h
+Auto-merging arch/s390/Kconfig
+CONFLICT (content): Merge conflict in arch/s390/Kconfig
+Auto-merging arch/powerpc/kernel/process.c
+Auto-merging arch/powerpc/kernel/ppc_ksyms.c
+Auto-merging arch/powerpc/kernel/entry_64.S
+Auto-merging arch/powerpc/kernel/entry_32.S
+Auto-merging arch/powerpc/include/asm/thread_info.h
+Auto-merging arch/powerpc/include/asm/processor.h
+Auto-merging arch/powerpc/Kconfig
+CONFLICT (content): Merge conflict in arch/powerpc/Kconfig
+Removing arch/parisc/include/asm/exec.h
+Auto-merging arch/mn10300/kernel/process.c
+Removing arch/mn10300/kernel/kthread.S
+Removing arch/mn10300/kernel/kernel_execve.S
+Removing arch/mn10300/include/asm/exec.h
+Auto-merging arch/mn10300/Kconfig
+CONFLICT (content): Merge conflict in arch/mn10300/Kconfig
+Auto-merging arch/mips/include/asm/thread_info.h
+Removing arch/microblaze/include/asm/exec.h
+Auto-merging arch/m68k/kernel/process.c
+Removing arch/m68k/include/asm/exec.h
+Auto-merging arch/m68k/Kconfig
+CONFLICT (content): Merge conflict in arch/m68k/Kconfig
+Removing arch/m32r/include/asm/exec.h
+Auto-merging arch/m32r/include/asm/Kbuild
+CONFLICT (content): Merge conflict in arch/m32r/include/asm/Kbuild
+Auto-merging arch/ia64/kernel/signal.c
+Removing arch/ia64/include/asm/exec.h
+Removing arch/h8300/include/asm/exec.h
+Auto-merging arch/h8300/include/asm/Kbuild
+CONFLICT (content): Merge conflict in arch/h8300/include/asm/Kbuild
+Auto-merging arch/frv/kernel/process.c
+Removing arch/frv/kernel/kernel_thread.S
+Removing arch/frv/kernel/kernel_execve.S
+Removing arch/frv/include/asm/exec.h
+Removing arch/cris/include/asm/exec.h
+Auto-merging arch/cris/include/asm/Kbuild
+CONFLICT (content): Merge conflict in arch/cris/include/asm/Kbuild
+Removing arch/c6x/include/asm/exec.h
+Auto-merging arch/c6x/include/asm/Kbuild
+Auto-merging arch/c6x/Kconfig
+CONFLICT (content): Merge conflict in arch/c6x/Kconfig
+Removing arch/avr32/include/asm/exec.h
+Auto-merging arch/arm/kernel/process.c
+Auto-merging arch/arm/kernel/entry-common.S
+Auto-merging arch/arm/kernel/calls.S
+Auto-merging arch/arm/include/asm/unistd.h
+Auto-merging arch/arm/include/asm/thread_info.h
+CONFLICT (content): Merge conflict in arch/arm/include/asm/thread_info.h
+Auto-merging arch/arm/Kconfig
+CONFLICT (content): Merge conflict in arch/arm/Kconfig
+Auto-merging arch/alpha/kernel/process.c
+Removing arch/alpha/include/asm/exec.h
+Auto-merging arch/alpha/Kconfig
+CONFLICT (content): Merge conflict in arch/alpha/Kconfig
+Auto-merging arch/Kconfig
+Automatic merge failed; fix conflicts and then commit the result.
+$ git commit -v -a
+Recorded resolution for 'arch/powerpc/Kconfig'.
+Recorded resolution for 'arch/s390/Kconfig'.
+Recorded resolution for 'arch/x86/Kconfig'.
+[master d12a41d] Merge remote-tracking branch 'signal/for-next'
+$ git diff -M --stat --summary HEAD^..
+ arch/Kconfig                              |    3 +
+ arch/alpha/Kconfig                        |    1 +
+ arch/alpha/include/asm/Kbuild             |    1 +
+ arch/alpha/include/asm/exec.h             |    6 --
+ arch/alpha/include/asm/processor.h        |    3 -
+ arch/alpha/include/asm/thread_info.h      |    3 +-
+ arch/alpha/include/asm/unistd.h           |    2 +
+ arch/alpha/kernel/alpha_ksyms.c           |    3 -
+ arch/alpha/kernel/entry.S                 |   81 +++++++---------------
+ arch/alpha/kernel/process.c               |   79 ++++++---------------
+ arch/alpha/kernel/ptrace.c                |   32 ++++-----
+ arch/arm/Kconfig                          |    1 +
+ arch/arm/include/asm/processor.h          |    5 --
+ arch/arm/include/asm/ptrace.h             |    5 ++
+ arch/arm/include/asm/system.h             |    1 -
+ arch/arm/include/asm/thread_info.h        |    2 -
+ arch/arm/include/asm/unistd.h             |    2 +
+ arch/arm/kernel/calls.S                   |    2 +-
+ arch/arm/kernel/entry-common.S            |   29 ++++++--
+ arch/arm/kernel/process.c                 |   75 ++++----------------
+ arch/arm/kernel/signal.c                  |    1 -
+ arch/arm/kernel/sys_arm.c                 |   63 -----------------
+ arch/avr32/include/asm/Kbuild             |    1 +
+ arch/avr32/include/asm/exec.h             |   13 ----
+ arch/avr32/include/asm/thread_info.h      |   18 ++---
+ arch/avr32/kernel/signal.c                |    1 -
+ arch/blackfin/include/asm/thread_info.h   |    4 --
+ arch/blackfin/kernel/signal.c             |    1 -
+ arch/c6x/Kconfig                          |    1 +
+ arch/c6x/include/asm/Kbuild               |    1 +
+ arch/c6x/include/asm/exec.h               |    6 --
+ arch/c6x/include/asm/processor.h          |    2 -
+ arch/c6x/include/asm/syscalls.h           |    5 --
+ arch/c6x/include/asm/thread_info.h        |    1 -
+ arch/c6x/include/asm/unistd.h             |    3 +
+ arch/c6x/kernel/asm-offsets.c             |    1 -
+ arch/c6x/kernel/entry.S                   |   56 +++++++--------
+ arch/c6x/kernel/process.c                 |   72 +++----------------
+ arch/cris/include/asm/Kbuild              |    1 +
+ arch/cris/include/asm/exec.h              |    6 --
+ arch/cris/include/asm/thread_info.h       |    3 -
+ arch/frv/Kconfig                          |    1 +
+ arch/frv/include/asm/Kbuild               |    1 +
+ arch/frv/include/asm/exec.h               |   17 -----
+ arch/frv/include/asm/processor.h          |    9 +--
+ arch/frv/include/asm/ptrace.h             |    1 +
+ arch/frv/include/asm/thread_info.h        |    3 -
+ arch/frv/include/asm/unistd.h             |    2 +
+ arch/frv/kernel/Makefile                  |    4 +-
+ arch/frv/kernel/entry.S                   |   13 ++++
+ arch/frv/kernel/frv_ksyms.c               |    1 -
+ arch/frv/kernel/kernel_execve.S           |   33 ---------
+ arch/frv/kernel/kernel_thread.S           |   77 ---------------------
+ arch/frv/kernel/process.c                 |   66 +++++++-----------
+ arch/frv/kernel/signal.c                  |    9 ---
+ arch/h8300/include/asm/Kbuild             |    1 +
+ arch/h8300/include/asm/exec.h             |    6 --
+ arch/h8300/include/asm/thread_info.h      |    7 +-
+ arch/h8300/kernel/signal.c                |    1 -
+ arch/hexagon/include/asm/thread_info.h    |    5 --
+ arch/hexagon/kernel/signal.c              |    1 -
+ arch/hexagon/kernel/syscall.c             |    1 -
+ arch/ia64/include/asm/Kbuild              |    1 +
+ arch/ia64/include/asm/exec.h              |   14 ----
+ arch/ia64/include/asm/thread_info.h       |    2 -
+ arch/ia64/kernel/signal.c                 |    8 ---
+ arch/m32r/include/asm/Kbuild              |    1 +
+ arch/m32r/include/asm/exec.h              |   14 ----
+ arch/m32r/include/asm/thread_info.h       |    9 +--
+ arch/m32r/kernel/signal.c                 |    3 -
+ arch/m68k/Kconfig                         |    1 +
+ arch/m68k/include/asm/Kbuild              |    1 +
+ arch/m68k/include/asm/exec.h              |    6 --
+ arch/m68k/include/asm/processor.h         |   25 ++++---
+ arch/m68k/include/asm/ptrace.h            |    2 +
+ arch/m68k/include/asm/unistd.h            |    2 +
+ arch/m68k/kernel/entry.S                  |   16 +++++
+ arch/m68k/kernel/process.c                |  104 +++++++---------------------
+ arch/m68k/kernel/sys_m68k.c               |   17 -----
+ arch/microblaze/include/asm/Kbuild        |    1 +
+ arch/microblaze/include/asm/exec.h        |   14 ----
+ arch/microblaze/include/asm/thread_info.h |    3 +-
+ arch/microblaze/kernel/signal.c           |    7 +-
+ arch/mips/include/asm/thread_info.h       |    3 -
+ arch/mn10300/Kconfig                      |    1 +
+ arch/mn10300/include/asm/Kbuild           |    2 +
+ arch/mn10300/include/asm/exec.h           |   16 -----
+ arch/mn10300/include/asm/frame.inc        |    2 +-
+ arch/mn10300/include/asm/processor.h      |   18 +----
+ arch/mn10300/include/asm/ptrace.h         |    1 +
+ arch/mn10300/include/asm/thread_info.h    |    3 +-
+ arch/mn10300/include/asm/unistd.h         |    2 +
+ arch/mn10300/kernel/Makefile              |    4 +-
+ arch/mn10300/kernel/entry.S               |   18 +++++
+ arch/mn10300/kernel/internal.h            |    6 +-
+ arch/mn10300/kernel/kernel_execve.S       |   37 ----------
+ arch/mn10300/kernel/kthread.S             |   31 ---------
+ arch/mn10300/kernel/process.c             |   91 +++++++-----------------
+ arch/mn10300/kernel/signal.c              |   13 ----
+ arch/openrisc/include/asm/thread_info.h   |    3 +-
+ arch/parisc/hpux/gate.S                   |    2 +-
+ arch/parisc/include/asm/Kbuild            |    1 +
+ arch/parisc/include/asm/exec.h            |    6 --
+ arch/parisc/include/asm/thread_info.h     |    5 +-
+ arch/parisc/kernel/signal.c               |   45 ++++--------
+ arch/parisc/kernel/syscall.S              |    9 +--
+ arch/powerpc/Kconfig                      |    1 +
+ arch/powerpc/include/asm/processor.h      |    3 -
+ arch/powerpc/include/asm/syscalls.h       |    3 -
+ arch/powerpc/include/asm/thread_info.h    |    2 +
+ arch/powerpc/include/asm/unistd.h         |    2 +
+ arch/powerpc/kernel/entry_32.S            |   16 +++++
+ arch/powerpc/kernel/entry_64.S            |   16 +++++
+ arch/powerpc/kernel/misc.S                |    7 --
+ arch/powerpc/kernel/misc_32.S             |   33 ---------
+ arch/powerpc/kernel/misc_64.S             |   34 ---------
+ arch/powerpc/kernel/ppc_ksyms.c           |    1 -
+ arch/powerpc/kernel/process.c             |   59 ++++++++--------
+ arch/powerpc/kernel/signal_32.c           |    1 -
+ arch/powerpc/kernel/sys_ppc32.c           |   22 ------
+ arch/s390/Kconfig                         |    1 +
+ arch/s390/include/asm/processor.h         |    4 +-
+ arch/s390/include/asm/thread_info.h       |    4 --
+ arch/s390/include/asm/unistd.h            |    2 +
+ arch/s390/kernel/compat_linux.c           |   26 -------
+ arch/s390/kernel/compat_linux.h           |    2 -
+ arch/s390/kernel/compat_wrapper.S         |    2 +-
+ arch/s390/kernel/entry.S                  |   51 ++++++--------
+ arch/s390/kernel/entry.h                  |    3 -
+ arch/s390/kernel/entry64.S                |   50 ++++++--------
+ arch/s390/kernel/process.c                |  107 +++++++++--------------------
+ arch/score/include/asm/thread_info.h      |    4 --
+ arch/score/kernel/signal.c                |    1 +
+ arch/sh/include/asm/Kbuild                |    1 +
+ arch/sh/include/asm/exec.h                |   10 ---
+ arch/sh/include/asm/thread_info.h         |    3 +
+ arch/sh/kernel/signal_32.c                |    1 -
+ arch/sh/kernel/signal_64.c                |    1 -
+ arch/sparc/include/asm/Kbuild             |    1 +
+ arch/sparc/include/asm/exec.h             |    6 --
+ arch/sparc/include/asm/thread_info_32.h   |    3 +-
+ arch/sparc/include/asm/thread_info_64.h   |    3 +
+ arch/tile/include/asm/Kbuild              |    1 +
+ arch/tile/include/asm/exec.h              |   20 ------
+ arch/tile/kernel/compat_signal.c          |    9 ---
+ arch/tile/kernel/signal.c                 |   12 +---
+ arch/um/include/asm/processor-generic.h   |   11 ---
+ arch/um/include/asm/thread_info.h         |    3 -
+ arch/um/kernel/exec.c                     |   46 ++-----------
+ arch/um/kernel/internal.h                 |    1 -
+ arch/um/kernel/process.c                  |   25 ++-----
+ arch/um/kernel/signal.c                   |    6 +-
+ arch/um/kernel/syscall.c                  |   41 ++++-------
+ arch/unicore32/include/asm/Kbuild         |    1 +
+ arch/unicore32/include/asm/exec.h         |   15 ----
+ arch/unicore32/include/asm/thread_info.h  |    4 +-
+ arch/unicore32/kernel/entry.S             |    2 -
+ arch/unicore32/kernel/signal.c            |    1 -
+ arch/unicore32/kernel/sys.c               |    1 -
+ arch/x86/Kconfig                          |    1 +
+ arch/x86/ia32/ia32entry.S                 |    2 +-
+ arch/x86/ia32/sys_ia32.c                  |   15 ----
+ arch/x86/include/asm/processor.h          |    5 --
+ arch/x86/include/asm/sys_ia32.h           |    2 -
+ arch/x86/include/asm/syscalls.h           |    2 +-
+ arch/x86/include/asm/thread_info.h        |    2 -
+ arch/x86/include/asm/unistd.h             |    2 +
+ arch/x86/kernel/Makefile                  |    2 +-
+ arch/x86/kernel/asm-offsets.c             |    3 +
+ arch/x86/kernel/entry_32.S                |   43 +++++++-----
+ arch/x86/kernel/entry_64.S                |   74 +++++++-------------
+ arch/x86/kernel/process.c                 |   65 ------------------
+ arch/x86/kernel/process_32.c              |   37 ++++++++--
+ arch/x86/kernel/process_64.c              |   35 ++++++----
+ arch/x86/kernel/signal.c                  |    4 --
+ arch/x86/kernel/sys_i386_32.c             |   40 -----------
+ arch/x86/kernel/vm86_32.c                 |    6 +-
+ arch/x86/syscalls/syscall_32.tbl          |    2 +-
+ arch/x86/um/Kconfig                       |    1 +
+ arch/x86/um/shared/sysdep/syscalls.h      |    2 +
+ arch/x86/um/signal.c                      |    6 --
+ arch/x86/um/sys_call_table_32.c           |    3 +-
+ arch/x86/um/syscalls_32.c                 |   27 ++------
+ arch/x86/um/syscalls_64.c                 |   23 +------
+ arch/xtensa/include/asm/Kbuild            |    2 +
+ arch/xtensa/include/asm/exec.h            |   14 ----
+ arch/xtensa/include/asm/thread_info.h     |    5 --
+ arch/xtensa/kernel/signal.c               |    4 --
+ fs/binfmt_elf.c                           |    1 -
+ fs/binfmt_elf_fdpic.c                     |    1 -
+ fs/exec.c                                 |   64 +++++++++++++++--
+ include/linux/binfmts.h                   |    6 ++
+ include/linux/compat.h                    |    8 ++-
+ include/linux/ptrace.h                    |    4 ++
+ include/linux/sched.h                     |    3 +
+ kernel/fork.c                             |   13 +++-
+ kernel/sched/core.c                       |    2 +-
+ 197 files changed, 772 insertions(+), 1869 deletions(-)
+ delete mode 100644 arch/alpha/include/asm/exec.h
+ delete mode 100644 arch/avr32/include/asm/exec.h
+ delete mode 100644 arch/c6x/include/asm/exec.h
+ delete mode 100644 arch/cris/include/asm/exec.h
+ delete mode 100644 arch/frv/include/asm/exec.h
+ delete mode 100644 arch/frv/kernel/kernel_execve.S
+ delete mode 100644 arch/frv/kernel/kernel_thread.S
+ delete mode 100644 arch/h8300/include/asm/exec.h
+ delete mode 100644 arch/ia64/include/asm/exec.h
+ delete mode 100644 arch/m32r/include/asm/exec.h
+ delete mode 100644 arch/m68k/include/asm/exec.h
+ delete mode 100644 arch/microblaze/include/asm/exec.h
+ delete mode 100644 arch/mn10300/include/asm/exec.h
+ delete mode 100644 arch/mn10300/kernel/kernel_execve.S
+ delete mode 100644 arch/mn10300/kernel/kthread.S
+ delete mode 100644 arch/parisc/include/asm/exec.h
+ delete mode 100644 arch/sh/include/asm/exec.h
+ delete mode 100644 arch/sparc/include/asm/exec.h
+ delete mode 100644 arch/tile/include/asm/exec.h
+ delete mode 100644 arch/um/kernel/internal.h
+ delete mode 100644 arch/unicore32/include/asm/exec.h
+ delete mode 100644 arch/x86/kernel/sys_i386_32.c
+ delete mode 100644 arch/xtensa/include/asm/exec.h
+Merging clk/clk-next (494bfec clk: add of_clk_src_onecell_get() support)
+$ git merge clk/clk-next
+Already up-to-date.
+Merging random/dev (d2e7c96 random: mix in architectural randomness in extract_buf())
+$ git merge random/dev
+Already up-to-date.
+Merging scsi-post-merge/merge-base:master ()
+$ git clone -s -l -n -q . ../rebase-tmp
+$ cd ../rebase-tmp
+$ git fetch --no-tags ../next refs/heads/akpm/master:akpm
+From ../next
+ * [new branch]      akpm/master -> akpm
+$ git fetch --no-tags ../next refs/heads/akpm/base:akpm-base
+From ../next
+ * [new branch]      akpm/base  -> akpm-base
+$ git checkout akpm
+Switched to branch 'akpm'
+$ git rebase --onto master akpm-base
+First, rewinding head to replay your work on top of it...
+Applying: thp: avoid VM_BUG_ON page_count(page) false positives in __collapse_huge_page_copy
+Applying: pagemap: fix wrong KPF_THP on slab pages
+Applying: CRIS: Fix I/O macros
+Applying: selinux: fix sel_netnode_insert() suspicious rcu dereference
+Applying: vfs: d_obtain_alias() needs to use "/" as default name.
+Applying: x86 cpu_hotplug: unmap cpu2node when the cpu is hotremoved
+Applying: cpu_hotplug-unmap-cpu2node-when-the-cpu-is-hotremoved-fix
+Applying: acpi_memhotplug.c: fix memory leak when memory device is unbound from the module acpi_memhotplug
+Applying: acpi_memhotplug.c: free memory device if acpi_memory_enable_device() failed
+Applying: acpi_memhotplug.c: remove memory info from list before freeing it
+Applying: acpi_memhotplug.c: don't allow to eject the memory device if it is being used
+Applying: acpi_memhotplug.c: bind the memory device when the driver is being loaded
+Applying: acpi_memhotplug.c: auto bind the memory device which is hotplugged before the driver is loaded
+Applying: arch/x86/platform/iris/iris.c: register a platform device and a platform driver
+Applying: x86 numa: don't check if node is NUMA_NO_NODE
+Applying: arch/x86/tools/insn_sanity.c: identify source of messages
+Applying: audit.h: replace defines with C stubs
+Applying: mn10300: only add -mmem-funcs to KBUILD_CFLAGS if gcc supports it
+Applying: drivers/dma/dmaengine.c: lower the priority of 'failed to get' dma channel message
+Applying: pcmcia: move unbind/rebind into dev_pm_ops.complete
+Applying: prctl: use access_ok() instead of TASK_SIZE in prctl_set_mm()
+Applying: drm/i915: optimize DIV_ROUND_CLOSEST() call
+Applying: gpu/drm/ttm: use copy_highpage
+Applying: timeconst.pl: remove deprecated defined(@array)
+Applying: time: don't inline EXPORT_SYMBOL functions
+Applying: kbuild: make: fix if_changed when command contains backslashes
+Applying: h8300: select generic atomic64_t support
+Applying: unicore32: select generic atomic64_t support
+Applying: readahead: fault retry breaks mmap file read random detection
+Applying: drivers/scsi/atp870u.c: fix bad use of udelay
+Applying: cciss: cleanup bitops usage
+Applying: cciss: use check_signature()
+Applying: block: store partition_meta_info.uuid as a string
+Applying: init: reduce PARTUUID min length to 1 from 36
+Applying: block: partition: msdos: provide UUIDs for partitions
+Applying: drbd: use copy_highpage
+Applying: vfs: increment iversion when a file is truncated
+Applying: fs: push rcu_barrier() from deactivate_locked_super() to filesystems
+Applying: fs: change return values from -EACCES to -EPERM
+Applying: mm/page_alloc.c: remove duplicate check
+Applying: mm: remove __GFP_NO_KSWAPD
+Applying: x86, pat: remove the dependency on 'vm_pgoff' in track/untrack pfn vma routines
+Applying: x86, pat: separate the pfn attribute tracking for remap_pfn_range and vm_insert_pfn
+Applying: x86-pat-separate-the-pfn-attribute-tracking-for-remap_pfn_range-and-vm_insert_pfn-fix
+Applying: mm, x86, pat: rework linear pfn-mmap tracking
+Applying: mm: introduce arch-specific vma flag VM_ARCH_1
+Applying: mm: kill vma flag VM_INSERTPAGE
+Applying: mm: kill vma flag VM_CAN_NONLINEAR
+Applying: mm: use mm->exe_file instead of first VM_EXECUTABLE vma->vm_file
+Applying: mm: kill vma flag VM_EXECUTABLE and mm->num_exe_file_vmas
+Applying: mm: prepare VM_DONTDUMP for using in drivers
+Applying: mm: kill vma flag VM_RESERVED and mm->reserved_vm counter
+Applying: mm-kill-vma-flag-vm_reserved-and-mm-reserved_vm-counter-fix
+Applying: mm: fix nonuniform page status when writing new file with small buffer
+Applying: mm-fix-nonuniform-page-status-when-writing-new-file-with-small-buffer-fix
+Applying: mm-fix-nonuniform-page-status-when-writing-new-file-with-small-buffer-fix-fix
+Applying: mm/mmap.c: replace find_vma_prepare() with clearer find_vma_links()
+Applying: mm-mmapc-replace-find_vma_prepare-with-clearer-find_vma_links fix
+Applying: mm: compaction: update comment in try_to_compact_pages
+Applying: mm: vmscan: scale number of pages reclaimed by reclaim/compaction based on failures
+Applying: mm-vmscan-scale-number-of-pages-reclaimed-by-reclaim-compaction-based-on-failures-fix
+Applying: mm: compaction: capture a suitable high-order page immediately when it is made available
+Applying: Revert "mm: mempolicy: Let vma_merge and vma_split handle vma->vm_policy linkages"
+Applying: mempolicy: remove mempolicy sharing
+Applying: mempolicy: fix a race in shared_policy_replace()
+Applying: mempolicy: fix refcount leak in mpol_set_shared_policy()
+Applying: mempolicy: fix a memory corruption by refcount imbalance in alloc_pages_vma()
+Applying: mempolicy-fix-a-memory-corruption-by-refcount-imbalance-in-alloc_pages_vma-v2
+Applying: mm: mmu_notifier: fix inconsistent memory between secondary MMU and host
+Applying: mm-mmu_notifier-fix-inconsistent-memory-between-secondary-mmu-and-host-fix
+Applying: mm: mmu_notifier: have mmu_notifiers use a global SRCU so they may safely schedule
+Applying: mm/mmu_notifier: init notifier if necessary
+Applying: mm/mmu_notifier: init notifier if necessary
+Applying: mm/vmscan: fix error number for failed kthread
+Applying: oom: remove deprecated oom_adj
+Applying: mm: hugetlb: add arch hook for clearing page flags before entering pool
+Applying: mm: adjust final #endif position in mm/internal.h
+Applying: thp: fix the count of THP_COLLAPSE_ALLOC
+Applying: thp: remove unnecessary check in start_khugepaged
+Applying: thp: move khugepaged_mutex out of khugepaged
+Applying: thp: remove unnecessary khugepaged_thread check
+Applying: thp: remove wake_up_interruptible in the exit path
+Applying: thp: remove some code depend on CONFIG_NUMA
+Applying: thp: merge page pre-alloc in khugepaged_loop into khugepaged_do_scan
+Applying: thp: release page in page pre-alloc path
+Applying: thp: introduce khugepaged_prealloc_page and khugepaged_alloc_page
+Applying: thp: remove khugepaged_loop
+Applying: thp: use khugepaged_enabled to remove duplicate code
+Applying: thp: remove unnecessary set_recommended_min_free_kbytes
+Applying: mm: fix potential anon_vma locking issue in mprotect()
+Applying: thp, x86: introduce HAVE_ARCH_TRANSPARENT_HUGEPAGE
+Using index info to reconstruct a base tree...
+M	arch/Kconfig
+M	arch/x86/Kconfig
+Falling back to patching base and 3-way merge...
+Auto-merging arch/x86/Kconfig
+Auto-merging arch/Kconfig
+CONFLICT (content): Merge conflict in arch/Kconfig
+Failed to merge in the changes.
+Patch failed at 0095 thp, x86: introduce HAVE_ARCH_TRANSPARENT_HUGEPAGE
+
+When you have resolved this problem run "git rebase --continue".
+If you would prefer to skip this patch, instead run "git rebase --skip".
+To check out the original branch and stop rebasing run "git rebase --abort".
+
+$ git rebase --continue
+Applying: thp: remove assumptions on pgtable_t type
+Applying: thp: introduce pmdp_invalidate()
+Applying: thp: make MADV_HUGEPAGE check for mm->def_flags
+Applying: thp, s390: thp splitting backend for s390
+Applying: thp, s390: thp pagetable pre-allocation for s390
+Applying: thp, s390: disable thp for kvm host on s390
+Applying: thp, s390: architecture backend for thp on s390
+Applying: thp, s390: add missing earlyclobber to inline assembly
+Applying: ipc/mqueue: remove unnecessary rb_init_node() calls
+Applying: rbtree: reference Documentation/rbtree.txt for usage instructions
+Applying: rbtree: empty nodes have no color
+Applying: rbtree-empty-nodes-have-no-color-fix
+Applying: rbtree: fix incorrect rbtree node insertion in fs/proc/proc_sysctl.c
+Applying: rbtree: move some implementation details from rbtree.h to rbtree.c
+Applying: rbtree: fix jffs2 build issue due to renamed __rb_parent_color field
+Applying: rbtree: performance and correctness test
+Applying: rbtree-performance-and-correctness-test-fix
+Applying: rbtree: break out of rb_insert_color loop after tree rotation
+Applying: rbtree: adjust root color in rb_insert_color() only when necessary
+Applying: rbtree: low level optimizations in rb_insert_color()
+Applying: rbtree: adjust node color in __rb_erase_color() only when necessary
+Applying: perf tools: fix build for another rbtree.c change
+Applying: rbtree: optimize case selection logic in __rb_erase_color()
+Applying: rbtree: low level optimizations in __rb_erase_color()
+Applying: rbtree: coding style adjustments
+Applying: rbtree: optimize fetching of sibling node
+Applying: rbtree test: fix sparse warning about 64-bit constant
+Applying: rbtree: add __rb_change_child() helper function
+Applying: rbtree: place easiest case first in rb_erase()
+Applying: rbtree: handle 1-child recoloring in rb_erase() instead of rb_erase_color()
+Applying: rbtree: low level optimizations in rb_erase()
+Applying: rbtree: augmented rbtree test
+Applying: rbtree: faster augmented rbtree manipulation
+Applying: rbtree: remove prior augmented rbtree implementation
+Applying: rbtree: add RB_DECLARE_CALLBACKS() macro
+Applying: rbtree: add prio tree and interval tree tests
+Applying: mm: replace vma prio_tree with an interval tree
+Applying: kmemleak: use rbtree instead of prio tree
+Applying: prio_tree: remove
+Applying: rbtree: move augmented rbtree functionality to rbtree_augmented.h
+Applying: mm: interval tree updates
+Applying: mm anon rmap: remove anon_vma_moveto_tail
+Applying: mm anon rmap: replace same_anon_vma linked list with an interval tree.
+Applying: mm rmap: remove vma_address check for address inside vma
+Applying: mm: add CONFIG_DEBUG_VM_RB build option
+Applying: mm anon rmap: in mremap, set the new vma's position before anon_vma_clone()
+Applying: mm: avoid taking rmap locks in move_ptes()
+Applying: memory-hotplug: build zonelists when offlining pages
+Applying: mm: mmu_notifier: make the mmu_notifier srcu static
+Applying: mm: cma: discard clean pages during contiguous allocation instead of migration
+Applying: mm-cma-discard-clean-pages-during-contiguous-allocation-instead-of-migration-fix
+Applying: mm-cma-discard-clean-pages-during-contiguous-allocation-instead-of-migration-fix-fix
+Applying: mm: fix tracing in free_pcppages_bulk()
+Applying: mm-fix-tracing-in-free_pcppages_bulk-fix
+Applying: cma: fix counting of isolated pages
+Applying: cma: count free CMA pages
+Applying: cma-count-free-cma-pages-fix
+Applying: cma: fix watermark checking
+Applying: cma: fix watermark checking cleanup
+Applying: mm: page_alloc: use get_freepage_migratetype() instead of page_private()
+Applying: mm: remain migratetype in freed page
+Applying: memory-hotplug: bug fix race between isolation and allocation
+Applying: memory-hotplug: fix pages missed by race rather than failing
+Applying: memory-hotplug-fix-pages-missed-by-race-rather-than-failng-fix
+Applying: atomic: implement generic atomic_dec_if_positive()
+Applying: atomic-implement-generic-atomic_dec_if_positive-fix
+Applying: swap: add a simple detector for inappropriate swapin readahead
+Applying: swap-add-a-simple-detector-for-inappropriate-swapin-readahead-fix
+Applying: mm/memblock: reduce overhead in binary search
+Applying: mm/memblock: use existing interface to set nid
+Applying: mm/memblock: cleanup early_node_map[] related comments
+Applying: mm: compaction: abort compaction loop if lock is contended or run too long
+Applying: mm-compaction-abort-compaction-loop-if-lock-is-contended-or-run-too-long-fix
+Applying: mm-compaction-abort-compaction-loop-if-lock-is-contended-or-run-too-long-fix-2
+Applying: mm: compaction: move fatal signal check out of compact_checklock_irqsave
+Applying: mm: compaction: Update try_to_compact_pages()kerneldoc comment
+Applying: mm: compaction: acquire the zone->lru_lock as late as possible
+Applying: mm-compaction-acquire-the-zone-lru_lock-as-late-as-possible-fix
+Applying: mm: compaction: acquire the zone->lock as late as possible
+Applying: mm: compaction: iron out isolate_freepages_block() and isolate_freepages_range()
+Applying: Revert "mm: have order > 0 compaction start off where it left"
+Applying: mm: compaction: cache if a pageblock was scanned and no pages were isolated
+Applying: mm: compaction: Restart compaction from near where it left off
+Applying: mm/hugetlb.c: remove duplicate inclusion of header file
+Applying: mm/page_alloc: refactor out __alloc_contig_migrate_alloc()
+Applying: mm-page_alloc-refactor-out-__alloc_contig_migrate_alloc-checkpatch-fixes
+Applying: memory-hotplug: don't replace lowmem pages with highmem
+Applying: thp: khugepaged_prealloc_page() forgot to reset the page alloc indicator
+Applying: mm: thp: fix the pmd_clear() arguments in pmdp_get_and_clear()
+Applying: mm: thp: fix the update_mmu_cache() last argument passing in mm/huge_memory.c
+Applying: mm: enable CONFIG_COMPACTION by default
+Applying: mm: fix-up zone present pages
+Applying: memcg: trivial fixes for Documentation/cgroups/memory.txt
+Applying: memcg: cleanup kmem tcp ifdefs
+Applying: memcg: move mem_cgroup_is_root upwards
+Applying: mm: fix invalidate_complete_page2() lock ordering
+Applying: mm: remove vma arg from page_evictable
+Applying: mm: use clear_page_mlock() in page_remove_rmap()
+Applying: mm: remove free_page_mlock
+Applying: mm, numa: reclaim from all nodes within reclaim distance
+Applying: mm-numa-reclaim-from-all-nodes-within-reclaim-distance-fix
+Applying: memory.txt: remove stray information
+Applying: mm: thp: fix pmd_present for split_huge_page and PROT_NONE with THP
+Applying: hugetlb: do not use vma_hugecache_offset() for vma_prio_tree_foreach
+Applying: mm: move all mmu notifier invocations to be done outside the PT lock
+Applying: mm: wrap calls to set_pte_at_notify with invalidate_range_start and invalidate_range_end
+Applying: mm: call invalidate_range_end in do_wp_page even for zero pages
+Applying: Revert 0def08e3 because check_range can't fail in migrate_to_node with
+Applying: mm: enhance comment and bug check
+Applying: memory-hotplug: fix zone stat mismatch
+Applying: mm: remove unevictable_pgs_mlockfreed
+Applying: KSM: numa awareness sysfs knob
+Applying: mm/memory.c: fix typo in comment
+Applying: sections: disable const sections for PA-RISC v2
+Applying: sections: fix section conflicts in arch/arm/
+Applying: sections: fix section conflicts in arch/frv
+Applying: sections: fix section conflicts in arch/h8300
+Applying: sections-fix-section-conflicts-in-arch-h8300-checkpatch-fixes
+Applying: sections: fix section conflicts in arch/ia64
+Applying: sections: fix section conflicts in arch/mips
+Applying: sections: fix section conflicts in arch/powerpc
+Applying: sections: fix section conflicts in arch/score
+Applying: sections: fix section conflicts in arch/sh
+Applying: sections-fix-section-conflicts-in-arch-sh-fix
+Applying: sections: fix section conflicts in arch/x86
+Applying: sections: fix section conflicts in drivers/atm
+Applying: sections: fix section conflicts in drivers/char
+Applying: sections: fix section conflicts in drivers/ide
+Applying: sections: fix section conflicts in drivers/macintosh
+Applying: sections-fix-section-conflicts-in-drivers-macintosh-checkpatch-fixes
+Applying: sections: fix section conflicts in drivers/mfd
+Applying: sections: fix section conflicts in drivers/mmc
+Applying: sections: fix section conflicts in drivers/net
+Applying: sections: fix section conflicts in drivers/net/hamradio
+Applying: sections: fix section conflicts in drivers/net/wan
+Applying: sections: fix section conflicts in drivers/platform/x86
+Applying: sections: fix section conflicts in drivers/scsi
+Applying: sections: fix section conflicts in drivers/video
+Applying: sections: fix section conflicts in mm/percpu.c
+Applying: sections: fix section conflicts in net/can
+Applying: sections: fix section conflicts in net
+Applying: sections: fix section conflicts in sound
+Applying: sections: fix const sections for crc32 table
+Applying: sectons-fix-const-sections-for-crc32-table-checkpatch-fixes
+Applying: frv: kill used but uninitialized variable
+Applying: score: select generic atomic64_t support
+Applying: cross-arch: don't corrupt personality flags upon exec()
+Applying: tile: fix personality bits handling upon exec()
+Applying: kernel/sys.c: call disable_nonboot_cpus() in kernel_restart()
+Applying: poweroff: fix bug in orderly_poweroff()
+Applying: drivers/misc/lis3lv02d: add generic DT matching code
+Applying: misc: lis3: fix undefined reference to lis3lv02d_init_dt
+Applying: drivers/misc/lis3lv02d/lis3lv02d_spi.c: add DT matching table passthru code
+Applying: lis3: lis3lv02d_spi.c: include linux/of.h
+Applying: drivers-misc-lis3lv02d-lis3lv02d_spic-add-dt-matching-table-passthru-code-fix-fix
+Applying: drivers/misc/lis3lv02d: remove lis3lv02d driver DT init
+Applying: drivers/misc/lis3lv02d/lis3lv02d_spi.c: add lis3lv02d device tree init
+Applying: drivers-misc-lis3lv02d-lis3lv02d_spic-add-lis3lv02d-device-tree-init-fix
+Applying: drivers/misc/lis3lv02d/lis3lv02d_i2c.c: add lis3lv02d device tree init
+Applying: drivers-misc-lis3lv02d-lis3lv02d_i2cc-add-lis3lv02d-device-tree-init-fix
+Applying: drivers/misc/lis3lv02d: fix some comments specific to lis331dlh driver
+Applying: lib: vsprintf: optimize division by 10 for small integers
+Applying: lib: vsprintf: optimize division by 10000
+Applying: lib: vsprintf: optimize put_dec_trunc8()
+Applying: lib-vsprintf-optimize-put_dec_trunc8-fix
+Applying: lib: vsprintf: fix broken comments
+Applying: lib/vsprintf: update documentation to cover all of %p[Mm][FR]
+Applying: MAINTAINERS: update gpio subsystem file list
+Applying: MAINTAINERS: add defconfig file to IMX section
+Applying: MAINTAINERS: Update gianfar_ptp after renaming
+Applying: drivers/video/backlight/da9052_bl.c: use usleep_range() instead of msleep() for small sleeps
+Applying: drivers/video/backlight/ltv350qv.c: use usleep_range() instead of msleep() for small sleeps
+Applying: drivers/video/backlight/kb3886_bl.c: use usleep_range() instead of msleep() for small sleeps
+Applying: backlight: lp855x: add FAST bit description for LP8556
+Applying: backlight: add Backlight driver for lm3630 chip
+Applying: backlight-add-backlight-driver-for-lm3630-chip-fix
+Applying: backlight: add new lm3639 backlight driver
+Applying: backlight-add-new-lm3639-backlight-driver-fix
+Applying: backlight-add-new-lm3639-backlight-driver-fix-2
+Applying: backlight: remove ProGear driver
+Applying: drivers/video/backlight/da9052_bl.c: drop devm_kfree of devm_kzalloc'd data
+Applying: drivers/video/backlight/platform_lcd.c: add support for device tree based probe
+Applying: backlight-platform-lcd-add-support-for-device-tree-based-probe-fix
+Applying: drivers/net/ethernet/sfc: use standard __{clear,set}_bit_le() functions
+Applying: drivers/net/ethernet/dec/tulip: Use standard __set_bit_le() function
+Applying: bitops: introduce generic {clear,set}_bit_le()
+Applying: powerpc: bitops: introduce {clear,set}_bit_le()
+Applying: kvm: replace test_and_set_bit_le() in mark_page_dirty_in_slot() with set_bit_le()
+Applying: idr: rename MAX_LEVEL to MAX_IDR_LEVEL
+Applying: idr-rename-max_level-to-max_idr_level-fix
+Applying: idr-rename-max_level-to-max_idr_level-fix-fix-2
+Applying: idr-rename-max_level-to-max_idr_level-fix-fix-2-fix
+Applying: idr-rename-max_level-to-max_idr_level-fix-3
+Applying: lib/parser.c: avoid overflow in match_number()
+Applying: lib-parserc-avoid-overflow-in-match_number-fix
+Applying: lib/Kconfig.debug: adjust hard-lockup related Kconfig options
+Applying: lib/gcd.c: prevent possible div by 0
+Applying: genalloc: make it possible to use a custom allocation algorithm
+Applying: lib/spinlock_debug: avoid livelock in do_raw_spin_lock()
+Applying: lib-spinlock_debug-avoid-livelock-in-do_raw_spin_lock-fix
+Applying: lib/vsprintf.c: improve standard conformance of sscanf()
+Applying: lib/plist.c: make plist test announcements KERN_DEBUG
+Applying: scatterlist: atomic sg_mapping_iter() no longer needs disabled IRQs
+Applying: drivers/firmware/dmi_scan.c: check dmi version when get system uuid
+Applying: drivers-firmware-dmi_scanc-check-dmi-version-when-get-system-uuid-fix
+Applying: drivers/firmware/dmi_scan.c: fetch dmi version from SMBIOS if it exists
+Applying: drivers-firmware-dmi_scanc-fetch-dmi-version-from-smbios-if-it-exists-checkpatch-fixes
+Applying: checkpatch: check utf-8 content from a commit log when it's missing from charset
+Applying: checkpatch: update suggested printk conversions
+Applying: checkpatch: check networking specific block comment style
+Applying: CodingStyle: add networking specific block comment style
+Applying: epoll: support for disabling items, and a self-test app
+Applying: drivers/rtc/rtc-isl1208.c: add support for the ISL1218
+Applying: rtc-proc: permit the /proc/driver/rtc device to use other devices
+Applying: rtc: add Dallas DS2404 driver
+Applying: rtc-add-dallas-ds2404-driver-fix
+Applying: rtc: snvs: add Freescale rtc-snvs driver
+Applying: rtc: snvs: change timeout to use a fixed number of loop
+Applying: rtc: recycle id when unloading a rtc driver
+Applying: drivers/rtc/rtc-at91sam9.c: use module_platform_driver() macro
+Applying: rtc: tps65910: add RTC driver for TPS65910 PMIC RTC
+Applying: rtc: tps65910: change RTC driver name as per mfd
+Applying: rtc: add MAX8907 RTC driver
+Applying: rtc: kconfig: remove unnecessary dependencies.
+Applying: drivers/rtc/rtc-jz4740.c: fix IRQ error check
+Applying: drivers/rtc/rtc-spear.c: fix several error checks
+Applying: rtc: rc5t583: add ricoh rc5t583 RTC driver
+Applying: drivers/rtc/rtc-coh901331.c: use clk_prepare_enable() and clk_disable_unprepare()
+Applying: rtc: rtc-mxc: adapt to the new i.mx clock framework
+Applying: rtc: rtc-mxc: convert to module_platform_driver
+Applying: rtc_sysfs_show_hctosys(): display 0 if resume failed
+Applying: rtc_sysfs_show_hctosys-return-0-if-resume-failed-fix
+Applying: rtc_sysfs_show_hctosys-return-0-if-resume-failed-fix-fix
+Applying: drivers/rtc/rtc-s3c.c: fix return value in s3c_rtc_probe()
+Applying: drivers/rtc/rtc-ds1672.c: convert struct i2c_msg initialization to C99 format
+Applying: drivers/rtc/rtc-x1205.c: convert struct i2c_msg initialization to C99 format
+Applying: drivers/rtc/rtc-s35390a.c: convert struct i2c_msg initialization to C99 format
+Applying: drivers/rtc/rtc-rs5c372.c: convert struct i2c_msg initialization to C99 format
+Applying: drivers/rtc/rtc-pcf8563.c: convert struct i2c_msg initialization to C99 format
+Applying: drivers/rtc/rtc-isl1208.c: convert struct i2c_msg initialization to C99 format
+Applying: drivers/rtc/rtc-em3027.c: convert struct i2c_msg initialization to C99 format
+Applying: rtc: kconfig: fix up dependency for ab8500
+Applying: drivers/rtc/rtc-tps65910.c: use platform_get_irq() to get RTC irq details
+Applying: drivers/rtc/rtc-m41t80.c: remove disabled alarm functionality
+Applying: hfsplus: add on-disk layout declarations related to attributes tree
+Applying: hfsplus: add functionality of manipulating by records in attributes tree
+Applying: hfsplus: rework functionality of getting, setting and deleting of extended attributes
+Applying: hfsplus: add support of manipulation by attributes file
+Applying: hfsplus-add-support-of-manipulation-by-attributes-file-checkpatch-fixes
+Applying: fat: use accessor function for msdos_dir_entry 'start'
+Applying: fat (exportfs): move NFS support code
+Applying: fat (exportfs): fix dentry reconnection
+Applying: fs/fat: fix a checkpatch issue in namei_msdos.c
+Applying: fs/fat: fix some checkpatch issues in fat.h
+Applying: fs/fat: chang indentation of some comments in fat.h
+Applying: fs/fat: fix two checkpatch issues in cache.c
+Applying: fs/fat: fix some small checkpatch issues in dir.c
+Applying: fs/fat: fix all other checkpatch issues in dir.c
+Applying: fs-fat-fix-all-other-checkpatch-issues-in-dirc-fix
+Applying: fs/fat: fix checkpatch issues in fatent.c
+Applying: fat: no need to reset EOF in ent_put for FAT32
+Applying: fat: simplify writeback_inode()
+Applying: fat-simplify-writeback_inode-checkpatch-fixes
+Applying: fat-simplify-writeback_inode-checkpatch-fixes-fix
+Applying: device_cgroup: add "deny_all" in dev_cgroup structure
+Applying: device_cgroup: introduce dev_whitelist_clean()
+Applying: device_cgroup: convert device_cgroup internally to policy + exceptions
+Applying: device_cgroup: rename whitelist to exception list
+Applying: coredump: prevent double-free on an error path in core dumper
+Applying: coredump: move core dump functionality into its own file
+Applying: coredump: make core dump functionality optional
+Applying: fs: amended coredump-related sysctl functions
+Applying: coredump-make-core-dump-functionality-optional-fix-fix
+Applying: coredump: update coredump-related headers
+Applying: coredump: add support for %d=__get_dumpable() in core name
+Applying: coredump-add-support-for-%d=__get_dumpable-in-core-name-fix
+Applying: coredump: use SUID_DUMPABLE_ENABLED rather than hardcoded 1
+Applying: coredump-use-suid_dumpable_enabled-rather-than-hardcoded-1-checkpatch-fixes
+Applying: coredump: pass siginfo_t* to do_coredump() and below, not merely signr
+Applying: compat: move compat_siginfo_t definition to asm/compat.h
+Applying: coredump: add a new elf note with siginfo of the signal
+Applying: coredump: extend core dump note section to contain file names of mapped files
+Applying: proc: return -ENOMEM when inode allocation failed
+Applying: proc: no need to initialize proc_inode->fd in proc_get_inode()
+Applying: proc: use kzalloc instead of kmalloc and memset
+Applying: proc-use-kzalloc-instead-of-kmalloc-and-memset-fix
+Applying: proc_sysctl.c: use BUG_ON instead of BUG
+Applying: fs/proc/root.c: use NULL instead of 0 for pointer
+Applying: kdump: remove unneeded include
+Applying: ipc/sem.c: alternatives to preempt_disable()
+Applying: rapidio/tsi721: modify mport name assignment
+Applying: rapidio: fix kerneldoc warnings after DMA support was added
+Applying: drivers/rapidio/devices/tsi721.c: fix error return code
+Applying: rapidio: add inbound memory mapping interface
+Applying: rapidio/tsi721: add inbound memory mapping callbacks
+Applying: rapidio: apply RX/TX enable to active switch ports only
+Applying: nbd: add set flags ioctl
+Applying: nbd: handle discard requests
+Applying: aoe: for performance support larger packet payloads
+Applying: aoe: kernel thread handles I/O completions for simple locking
+Applying: aoe: cleanup an allocation a bit
+Applying: aoe: become I/O request queue handler for increased user control
+Applying: aoe: use a kernel thread for transmissions
+Applying: aoe: use packets that work with the smallest-MTU local interface
+Applying: aoe: failover remote interface based on aoe_deadsecs parameter
+Applying: aoe: do revalidation steps in order
+Applying: aoe: disallow unsupported AoE minor addresses
+Applying: aoe: associate frames with the AoE storage target
+Applying: aoe: increase net_device reference count while using it
+Applying: aoe: remove unused code and add cosmetic improvements
+Applying: aoe: update internal version number to 49
+Applying: aoe: update copyright year in touched files
+Applying: aoe: update documentation with new URL and VM settings reference
+Applying: taskstats: cgroupstats_user_cmd() may leak on error
+Applying: memstick: add support for legacy memorysticks
+Applying: kernel/resource.c: fix stack overflow in __reserve_region_with_split()
+Applying: lib/decompress.c add __init to decompress_method and data
+$ cd ../next
+$ git fetch -f ../rebase-tmp akpm:akpm/master
+From ../rebase-tmp
+ + 1f023da...dad0019 akpm       -> akpm/master  (forced update)
+$ rm -rf ../rebase-tmp
+Merging akpm/master (dad0019 lib/decompress.c add __init to decompress_method and data)
+$ git merge --no-ff akpm/master
+Removing mm/prio_tree.c
+Removing lib/prio_tree.c
+Removing include/linux/prio_tree.h
+Removing drivers/video/backlight/progear_bl.c
+Removing Documentation/prio_tree.txt
+Removing Documentation/memory.txt
+Removing Documentation/ABI/obsolete/proc-pid-oom_adj
+Merge made by the 'recursive' strategy.
+ Documentation/00-INDEX                             |    2 -
+ Documentation/ABI/obsolete/proc-pid-oom_adj        |   22 -
+ Documentation/CodingStyle                          |   10 +
+ Documentation/aoe/aoe.txt                          |    9 +-
+ Documentation/cgroups/memory.txt                   |   90 +-
+ .../devicetree/bindings/crypto/fsl-sec4.txt        |   51 +
+ Documentation/devicetree/bindings/misc/lis302.txt  |  112 +
+ Documentation/devicetree/bindings/rtc/snvs-rtc.txt |    1 +
+ Documentation/feature-removal-schedule.txt         |   25 -
+ Documentation/filesystems/proc.txt                 |   22 +-
+ Documentation/memory.txt                           |   33 -
+ Documentation/printk-formats.txt                   |    1 +
+ Documentation/prio_tree.txt                        |  107 -
+ Documentation/rbtree.txt                           |  209 +-
+ Documentation/rtc.txt                              |    5 +-
+ Documentation/sysctl/kernel.txt                    |    2 +
+ Documentation/vm/ksm.txt                           |    7 +
+ Documentation/vm/unevictable-lru.txt               |   14 +-
+ MAINTAINERS                                        |   11 +-
+ arch/Kconfig                                       |    3 +
+ arch/alpha/kernel/pci-sysfs.c                      |    2 +-
+ arch/arm/mach-at91/clock.c                         |    2 +-
+ arch/arm/mach-davinci/board-tnetv107x-evm.c        |    6 +-
+ arch/arm/mach-davinci/da830.c                      |   48 +-
+ arch/arm/mach-davinci/da850.c                      |    6 +-
+ arch/arm/mach-msm/board-qsd8x50.c                  |    4 +-
+ arch/arm/mach-omap2/display.c                      |    6 +-
+ arch/arm/mm/fault-armv.c                           |    3 +-
+ arch/arm/mm/fault.c                                |    1 +
+ arch/arm/mm/flush.c                                |    3 +-
+ arch/arm64/include/asm/compat.h                    |   60 +-
+ arch/arm64/kernel/signal32.c                       |   53 -
+ arch/avr32/include/asm/elf.h                       |    3 +-
+ arch/avr32/mm/fault.c                              |    1 +
+ arch/blackfin/include/asm/elf.h                    |    3 +-
+ arch/c6x/include/asm/elf.h                         |    3 +-
+ arch/cris/include/asm/elf.h                        |    3 +-
+ arch/cris/include/asm/io.h                         |   39 +-
+ arch/cris/mm/fault.c                               |    1 +
+ arch/frv/include/asm/elf.h                         |    3 +-
+ arch/frv/kernel/pm.c                               |   19 +-
+ arch/frv/kernel/setup.c                            |    2 +-
+ arch/frv/mb93090-mb00/pci-irq.c                    |    2 +-
+ arch/h8300/Kconfig                                 |    1 +
+ arch/h8300/include/asm/elf.h                       |    3 +-
+ arch/h8300/kernel/sys_h8300.c                      |    1 +
+ arch/h8300/kernel/timer/itu.c                      |    2 +-
+ arch/h8300/kernel/timer/timer16.c                  |    2 +-
+ arch/h8300/kernel/timer/timer8.c                   |    2 +-
+ arch/h8300/kernel/timer/tpu.c                      |    2 +-
+ arch/h8300/platform/h8300h/irq.c                   |    4 +-
+ arch/h8300/platform/h8s/irq.c                      |    4 +-
+ arch/hexagon/include/asm/elf.h                     |    3 +-
+ arch/hexagon/mm/vm_fault.c                         |    1 +
+ arch/ia64/include/asm/hugetlb.h                    |    4 +
+ arch/ia64/kernel/perfmon.c                         |    2 +-
+ arch/ia64/mm/fault.c                               |    1 +
+ arch/ia64/mm/init.c                                |    4 +-
+ arch/ia64/xen/irq_xen.c                            |    2 +-
+ arch/ia64/xen/irq_xen.h                            |    2 +-
+ arch/m32r/include/asm/elf.h                        |    3 +-
+ arch/m68k/include/asm/elf.h                        |    3 +-
+ arch/m68k/mm/fault.c                               |    1 +
+ arch/microblaze/include/asm/atomic.h               |    1 +
+ arch/microblaze/include/asm/elf.h                  |    3 +-
+ arch/microblaze/mm/fault.c                         |    1 +
+ arch/mips/bcm63xx/boards/board_bcm963xx.c          |    2 +-
+ arch/mips/include/asm/compat-signal.h              |   62 -
+ arch/mips/include/asm/compat.h                     |   69 +-
+ arch/mips/include/asm/hugetlb.h                    |    4 +
+ arch/mips/mm/fault.c                               |    1 +
+ arch/mips/pci/pci-octeon.c                         |    2 +-
+ arch/mn10300/Makefile                              |    2 +-
+ arch/mn10300/include/asm/elf.h                     |    3 +-
+ arch/openrisc/include/asm/elf.h                    |    3 +-
+ arch/openrisc/mm/fault.c                           |    1 +
+ arch/parisc/Kconfig                                |    1 +
+ arch/parisc/include/asm/compat.h                   |   59 +-
+ arch/parisc/kernel/cache.c                         |    3 +-
+ arch/parisc/kernel/signal32.h                      |   52 -
+ arch/powerpc/include/asm/atomic.h                  |    1 +
+ arch/powerpc/include/asm/bitops.h                  |   10 +
+ arch/powerpc/include/asm/compat.h                  |   60 +-
+ arch/powerpc/include/asm/hugetlb.h                 |    4 +
+ arch/powerpc/include/asm/siginfo.h                 |    1 -
+ arch/powerpc/kernel/ppc32.h                        |   51 -
+ arch/powerpc/kvm/book3s_hv.c                       |    2 +-
+ arch/powerpc/mm/fault.c                            |    1 +
+ arch/powerpc/oprofile/cell/spu_task_sync.c         |   15 +-
+ arch/powerpc/platforms/40x/ppc40x_simple.c         |    2 +-
+ arch/powerpc/platforms/512x/mpc5121_generic.c      |    2 +-
+ arch/powerpc/platforms/52xx/lite5200.c             |    2 +-
+ arch/powerpc/platforms/52xx/media5200.c            |    2 +-
+ arch/powerpc/platforms/83xx/mpc837x_rdb.c          |    2 +-
+ arch/powerpc/platforms/85xx/tqm85xx.c              |    2 +-
+ arch/s390/include/asm/compat.h                     |   75 +-
+ arch/s390/include/asm/hugetlb.h                    |   19 +-
+ arch/s390/include/asm/pgtable.h                    |  209 ++
+ arch/s390/include/asm/setup.h                      |    5 +-
+ arch/s390/include/asm/tlb.h                        |    1 +
+ arch/s390/kernel/compat_linux.h                    |   68 -
+ arch/s390/kernel/early.c                           |    2 +
+ arch/s390/mm/fault.c                               |    1 +
+ arch/s390/mm/gup.c                                 |   11 +-
+ arch/s390/mm/pgtable.c                             |  108 +
+ arch/score/Kconfig                                 |    3 +-
+ arch/score/include/asm/elf.h                       |    2 +-
+ arch/score/kernel/sys_score.c                      |    1 +
+ arch/sh/include/asm/elf.h                          |    3 +-
+ arch/sh/include/asm/hugetlb.h                      |    6 +
+ arch/sh/include/asm/io.h                           |    2 +-
+ arch/sh/kernel/ioport.c                            |    2 +-
+ arch/sh/mm/fault.c                                 |    1 +
+ arch/sparc/include/asm/compat.h                    |   61 +-
+ arch/sparc/include/asm/elf_32.h                    |    3 +-
+ arch/sparc/include/asm/hugetlb.h                   |    4 +
+ arch/sparc/include/asm/siginfo.h                   |    1 -
+ arch/sparc/kernel/pci.c                            |    2 +-
+ arch/sparc/kernel/signal32.c                       |   52 -
+ arch/sparc/mm/fault_32.c                           |    1 +
+ arch/sparc/mm/fault_64.c                           |    1 +
+ arch/tile/include/asm/compat.h                     |   62 +
+ arch/tile/include/asm/elf.h                        |    4 +-
+ arch/tile/include/asm/hugetlb.h                    |    4 +
+ arch/tile/kernel/compat_signal.c                   |   57 -
+ arch/tile/mm/elf.c                                 |   19 +-
+ arch/tile/mm/fault.c                               |    1 +
+ arch/um/kernel/trap.c                              |    1 +
+ arch/unicore32/Kconfig                             |    1 +
+ arch/unicore32/kernel/process.c                    |    2 +-
+ arch/x86/Kconfig                                   |    1 +
+ arch/x86/include/asm/apic.h                        |    2 +-
+ arch/x86/include/asm/atomic.h                      |   24 -
+ arch/x86/include/asm/compat.h                      |   74 +-
+ arch/x86/include/asm/hugetlb.h                     |    4 +
+ arch/x86/include/asm/ia32.h                        |   67 -
+ arch/x86/include/asm/pgtable.h                     |   11 +-
+ arch/x86/kernel/acpi/boot.c                        |    7 +-
+ arch/x86/kernel/apic/apic_numachip.c               |    4 +-
+ arch/x86/kernel/rtc.c                              |    2 +-
+ arch/x86/mm/fault.c                                |    1 +
+ arch/x86/mm/hugetlbpage.c                          |    3 +-
+ arch/x86/mm/numa.c                                 |    3 +-
+ arch/x86/mm/pat.c                                  |   87 +-
+ arch/x86/mm/pat_rbtree.c                           |   34 +-
+ arch/x86/platform/iris/iris.c                      |   67 +-
+ arch/x86/tools/insn_sanity.c                       |   10 +-
+ arch/x86/xen/mmu.c                                 |    3 +-
+ arch/xtensa/include/asm/elf.h                      |    3 +-
+ arch/xtensa/mm/fault.c                             |    1 +
+ block/genhd.c                                      |    8 +-
+ block/partitions/efi.c                             |    7 +-
+ block/partitions/msdos.c                           |   21 +-
+ drivers/acpi/acpi_memhotplug.c                     |  123 +-
+ drivers/atm/eni.c                                  |    2 +-
+ drivers/block/aoe/aoe.h                            |   85 +-
+ drivers/block/aoe/aoeblk.c                         |   89 +-
+ drivers/block/aoe/aoechr.c                         |   11 +-
+ drivers/block/aoe/aoecmd.c                         | 1222 ++++++----
+ drivers/block/aoe/aoedev.c                         |  161 +-
+ drivers/block/aoe/aoemain.c                        |   10 +-
+ drivers/block/aoe/aoenet.c                         |   61 +-
+ drivers/block/cciss.c                              |   21 +-
+ drivers/block/drbd/drbd_bitmap.c                   |    7 +-
+ drivers/block/nbd.c                                |   23 +-
+ drivers/char/mbcs.c                                |    4 +-
+ drivers/char/mem.c                                 |    2 +-
+ drivers/char/mspec.c                               |    2 +-
+ drivers/dma/dmaengine.c                            |    2 +-
+ drivers/firmware/dmi_scan.c                        |   78 +-
+ drivers/gpu/drm/drm_gem.c                          |    2 +-
+ drivers/gpu/drm/drm_vm.c                           |   10 +-
+ drivers/gpu/drm/exynos/exynos_drm_gem.c            |    2 +-
+ drivers/gpu/drm/gma500/framebuffer.c               |    3 +-
+ drivers/gpu/drm/i915/intel_pm.c                    |    3 +-
+ drivers/gpu/drm/ttm/ttm_bo_vm.c                    |    4 +-
+ drivers/gpu/drm/ttm/ttm_tt.c                       |   16 +-
+ drivers/gpu/drm/udl/udl_fb.c                       |    2 +-
+ drivers/i2c/i2c-core.c                             |    2 +-
+ drivers/ide/aec62xx.c                              |    2 +-
+ drivers/ide/ali14xx.c                              |    4 +-
+ drivers/ide/alim15x3.c                             |    2 +-
+ drivers/ide/amd74xx.c                              |    2 +-
+ drivers/ide/atiixp.c                               |    2 +-
+ drivers/ide/cmd640.c                               |    2 +-
+ drivers/ide/cmd64x.c                               |    2 +-
+ drivers/ide/cs5520.c                               |    2 +-
+ drivers/ide/cs5530.c                               |    2 +-
+ drivers/ide/cs5535.c                               |    2 +-
+ drivers/ide/cy82c693.c                             |    2 +-
+ drivers/ide/dtc2278.c                              |    2 +-
+ drivers/ide/hpt366.c                               |   24 +-
+ drivers/ide/ht6560b.c                              |    2 +-
+ drivers/ide/icside.c                               |    2 +-
+ drivers/ide/ide-pci-generic.c                      |    2 +-
+ drivers/ide/it8172.c                               |    2 +-
+ drivers/ide/it8213.c                               |    2 +-
+ drivers/ide/it821x.c                               |    2 +-
+ drivers/ide/jmicron.c                              |    2 +-
+ drivers/ide/ns87415.c                              |    2 +-
+ drivers/ide/opti621.c                              |    2 +-
+ drivers/ide/pdc202xx_new.c                         |    2 +-
+ drivers/ide/pdc202xx_old.c                         |    2 +-
+ drivers/ide/piix.c                                 |    2 +-
+ drivers/ide/qd65xx.c                               |    2 +-
+ drivers/ide/rz1000.c                               |    2 +-
+ drivers/ide/sc1200.c                               |    2 +-
+ drivers/ide/scc_pata.c                             |    2 +-
+ drivers/ide/serverworks.c                          |    2 +-
+ drivers/ide/siimage.c                              |    2 +-
+ drivers/ide/sis5513.c                              |    2 +-
+ drivers/ide/sl82c105.c                             |    2 +-
+ drivers/ide/slc90e66.c                             |    2 +-
+ drivers/ide/tc86c001.c                             |    2 +-
+ drivers/ide/triflex.c                              |    2 +-
+ drivers/ide/trm290.c                               |    2 +-
+ drivers/ide/tx4938ide.c                            |    2 +-
+ drivers/ide/tx4939ide.c                            |    2 +-
+ drivers/ide/umc8672.c                              |    2 +-
+ drivers/ide/via82cxxx.c                            |    2 +-
+ drivers/infiniband/core/cm.c                       |    2 +-
+ drivers/infiniband/hw/ehca/ehca_uverbs.c           |    4 +-
+ drivers/infiniband/hw/ipath/ipath_file_ops.c       |    2 +-
+ drivers/infiniband/hw/mlx4/cm.c                    |    2 +-
+ drivers/infiniband/hw/qib/qib_file_ops.c           |    2 +-
+ drivers/macintosh/macio_asic.c                     |    2 +-
+ drivers/media/pci/meye/meye.c                      |    2 +-
+ drivers/media/platform/omap/omap_vout.c            |    2 +-
+ drivers/media/platform/vino.c                      |    2 +-
+ drivers/media/usb/sn9c102/sn9c102_core.c           |    3 +-
+ drivers/media/usb/usbvision/usbvision-video.c      |    3 +-
+ drivers/media/v4l2-core/videobuf-dma-sg.c          |    2 +-
+ drivers/media/v4l2-core/videobuf-vmalloc.c         |    2 +-
+ drivers/media/v4l2-core/videobuf2-memops.c         |    2 +-
+ drivers/memstick/core/Kconfig                      |   12 +
+ drivers/memstick/core/Makefile                     |    2 +-
+ drivers/memstick/core/ms_block.c                   | 2424 ++++++++++++++++++++
+ drivers/memstick/core/ms_block.h                   |  246 ++
+ drivers/mfd/wm8994-core.c                          |    6 +-
+ drivers/misc/carma/carma-fpga.c                    |    2 -
+ drivers/misc/lis3lv02d/lis3lv02d.c                 |  162 +-
+ drivers/misc/lis3lv02d/lis3lv02d.h                 |    7 +-
+ drivers/misc/lis3lv02d/lis3lv02d_i2c.c             |   25 +-
+ drivers/misc/lis3lv02d/lis3lv02d_spi.c             |   21 +
+ drivers/misc/sgi-gru/grufile.c                     |    5 +-
+ drivers/mmc/host/sdhci-pci.c                       |    2 +-
+ drivers/mtd/mtdchar.c                              |    2 +-
+ drivers/mtd/mtdcore.c                              |    6 +-
+ drivers/net/can/slcan.c                            |    2 +-
+ drivers/net/can/vcan.c                             |    2 +-
+ drivers/net/ethernet/8390/ne3210.c                 |    2 +-
+ drivers/net/ethernet/adaptec/starfire.c            |    2 +-
+ drivers/net/ethernet/atheros/atl1c/atl1c_main.c    |    2 +-
+ drivers/net/ethernet/atheros/atlx/atl2.c           |    2 +-
+ drivers/net/ethernet/dec/tulip/de2104x.c           |    7 +-
+ drivers/net/ethernet/dec/tulip/eeprom.c            |    2 +-
+ drivers/net/ethernet/dec/tulip/tulip_core.c        |    7 +-
+ drivers/net/ethernet/dec/tulip/winbond-840.c       |    2 +-
+ drivers/net/ethernet/dlink/sundance.c              |    2 +-
+ drivers/net/ethernet/fealnx.c                      |    2 +-
+ drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c     |    2 +-
+ drivers/net/ethernet/realtek/8139too.c             |    2 +-
+ drivers/net/ethernet/sfc/efx.c                     |    4 +-
+ drivers/net/ethernet/sfc/net_driver.h              |   12 -
+ drivers/net/ethernet/sfc/nic.c                     |    4 +-
+ drivers/net/ethernet/sis/sis190.c                  |    2 +-
+ drivers/net/hamradio/6pack.c                       |    6 +-
+ drivers/net/hamradio/bpqether.c                    |    2 +-
+ drivers/net/hamradio/mkiss.c                       |    6 +-
+ drivers/net/hamradio/scc.c                         |    2 +-
+ drivers/net/hamradio/yam.c                         |    2 +-
+ drivers/net/wan/z85230.c                           |    2 +-
+ drivers/oprofile/buffer_sync.c                     |   17 +-
+ drivers/pcmcia/cs.c                                |   37 +-
+ drivers/platform/x86/amilo-rfkill.c                |    2 +-
+ drivers/platform/x86/fujitsu-tablet.c              |   10 +-
+ drivers/platform/x86/thinkpad_acpi.c               |    2 +-
+ drivers/pps/pps.c                                  |    2 +-
+ drivers/rapidio/devices/tsi721.c                   |   94 +-
+ drivers/rapidio/devices/tsi721.h                   |   15 +-
+ drivers/rapidio/rio-scan.c                         |    9 +-
+ drivers/rapidio/rio.c                              |   44 +
+ drivers/rtc/Kconfig                                |   87 +-
+ drivers/rtc/Makefile                               |    5 +
+ drivers/rtc/class.c                                |    9 +-
+ drivers/rtc/hctosys.c                              |    4 +-
+ drivers/rtc/rtc-at91sam9.c                         |   13 +-
+ drivers/rtc/rtc-coh901331.c                        |    3 +-
+ drivers/rtc/rtc-ds1672.c                           |   26 +-
+ drivers/rtc/rtc-ds2404.c                           |  303 +++
+ drivers/rtc/rtc-em3027.c                           |   17 +-
+ drivers/rtc/rtc-isl1208.c                          |   21 +-
+ drivers/rtc/rtc-jz4740.c                           |    2 +-
+ drivers/rtc/rtc-m41t80.c                           |  157 +-
+ drivers/rtc/rtc-max8907.c                          |  245 ++
+ drivers/rtc/rtc-mxc.c                              |   30 +-
+ drivers/rtc/rtc-pcf8563.c                          |   13 +-
+ drivers/rtc/rtc-proc.c                             |   24 +-
+ drivers/rtc/rtc-rc5t583.c                          |  331 +++
+ drivers/rtc/rtc-rs5c372.c                          |    7 +-
+ drivers/rtc/rtc-s35390a.c                          |   13 +-
+ drivers/rtc/rtc-s3c.c                              |    4 +-
+ drivers/rtc/rtc-snvs.c                             |  350 +++
+ drivers/rtc/rtc-spear.c                            |   12 +-
+ drivers/rtc/rtc-sysfs.c                            |    6 +
+ drivers/rtc/rtc-tps65910.c                         |  349 +++
+ drivers/rtc/rtc-x1205.c                            |   92 +-
+ drivers/scsi/aacraid/linit.c                       |    2 +-
+ drivers/scsi/aic94xx/aic94xx_init.c                |    2 +-
+ drivers/scsi/atp870u.c                             |   11 +-
+ drivers/scsi/sg.c                                  |    2 +-
+ drivers/staging/android/ashmem.c                   |    1 -
+ drivers/staging/omapdrm/omap_gem_dmabuf.c          |    2 +-
+ drivers/staging/tidspbridge/rmgr/drv_interface.c   |    2 +-
+ drivers/thermal/cpu_cooling.c                      |    2 +-
+ drivers/thermal/thermal_sys.c                      |    2 +-
+ drivers/uio/uio.c                                  |    4 +-
+ drivers/usb/mon/mon_bin.c                          |    2 +-
+ drivers/vfio/pci/vfio_pci.c                        |    2 +-
+ drivers/video/68328fb.c                            |    2 +-
+ drivers/video/aty/aty128fb.c                       |    2 +-
+ drivers/video/aty/atyfb_base.c                     |    3 +-
+ drivers/video/backlight/Kconfig                    |   23 +-
+ drivers/video/backlight/Makefile                   |    3 +-
+ drivers/video/backlight/da9052_bl.c                |    4 +-
+ drivers/video/backlight/kb3886_bl.c                |    4 +-
+ drivers/video/backlight/lm3630_bl.c                |  475 ++++
+ drivers/video/backlight/lm3639_bl.c                |  437 ++++
+ drivers/video/backlight/ltv350qv.c                 |    6 +-
+ drivers/video/backlight/platform_lcd.c             |   10 +
+ drivers/video/backlight/progear_bl.c               |  162 --
+ drivers/video/fb-puv3.c                            |    3 +-
+ drivers/video/fb_defio.c                           |    2 +-
+ drivers/video/fbmem.c                              |    3 +-
+ drivers/video/gbefb.c                              |    2 +-
+ drivers/video/geode/gx1fb_core.c                   |    2 +-
+ drivers/video/gxt4500.c                            |    4 +-
+ drivers/video/i810/i810_main.c                     |    2 +-
+ drivers/video/jz4740_fb.c                          |    2 +-
+ drivers/video/omap2/omapfb/omapfb-main.c           |    2 +-
+ drivers/video/sbuslib.c                            |    5 +-
+ drivers/video/smscufx.c                            |    1 -
+ drivers/video/udlfb.c                              |    1 -
+ drivers/video/vermilion/vermilion.c                |    1 -
+ drivers/video/vfb.c                                |    1 -
+ drivers/xen/gntalloc.c                             |    2 +-
+ drivers/xen/gntdev.c                               |    2 +-
+ drivers/xen/privcmd.c                              |    3 +-
+ fs/9p/v9fs.c                                       |    5 +
+ fs/9p/vfs_file.c                                   |    1 +
+ fs/Kconfig.binfmt                                  |    8 +
+ fs/Makefile                                        |    1 +
+ fs/adfs/super.c                                    |    5 +
+ fs/affs/super.c                                    |    5 +
+ fs/afs/super.c                                     |    5 +
+ fs/attr.c                                          |    5 +
+ fs/autofs4/root.c                                  |    2 +-
+ fs/befs/linuxvfs.c                                 |    5 +
+ fs/bfs/inode.c                                     |    5 +
+ fs/binfmt_aout.c                                   |   54 +-
+ fs/binfmt_elf.c                                    |  170 +-
+ fs/binfmt_elf_fdpic.c                              |    8 +-
+ fs/binfmt_flat.c                                   |    2 +-
+ fs/btrfs/extent_io.c                               |    6 +
+ fs/btrfs/file.c                                    |    2 +-
+ fs/btrfs/inode.c                                   |    5 +
+ fs/ceph/addr.c                                     |    2 +-
+ fs/ceph/super.c                                    |    5 +
+ fs/cifs/cifsfs.c                                   |    5 +
+ fs/cifs/file.c                                     |    1 +
+ fs/coda/inode.c                                    |    5 +
+ fs/compat_binfmt_elf.c                             |    7 +
+ fs/coredump.c                                      |  692 ++++++
+ fs/coredump.h                                      |    6 +
+ fs/dcache.c                                        |    2 +-
+ fs/dlm/config.c                                    |    2 +-
+ fs/ecryptfs/main.c                                 |    6 +
+ fs/efs/super.c                                     |    5 +
+ fs/eventpoll.c                                     |   38 +-
+ fs/exec.c                                          |  650 +-----
+ fs/exofs/super.c                                   |    5 +
+ fs/ext2/super.c                                    |    5 +
+ fs/ext3/super.c                                    |    5 +
+ fs/ext4/file.c                                     |    2 +-
+ fs/ext4/super.c                                    |    5 +
+ fs/fat/Makefile                                    |    2 +-
+ fs/fat/cache.c                                     |   10 +-
+ fs/fat/dir.c                                       |   56 +-
+ fs/fat/fat.h                                       |   97 +-
+ fs/fat/fatent.c                                    |   13 +-
+ fs/fat/inode.c                                     |  192 +-
+ fs/fat/namei_msdos.c                               |    7 +-
+ fs/fat/namei_vfat.c                                |    5 +-
+ fs/fat/nfs.c                                       |  101 +
+ fs/freevxfs/vxfs_super.c                           |    5 +
+ fs/fuse/file.c                                     |    1 +
+ fs/fuse/inode.c                                    |    6 +
+ fs/gfs2/file.c                                     |    2 +-
+ fs/gfs2/sys.c                                      |   18 +-
+ fs/hfs/super.c                                     |    6 +
+ fs/hfsplus/Makefile                                |    3 +-
+ fs/hfsplus/attributes.c                            |  388 ++++
+ fs/hfsplus/bfind.c                                 |   79 +-
+ fs/hfsplus/bnode.c                                 |    6 +-
+ fs/hfsplus/brec.c                                  |   23 +-
+ fs/hfsplus/btree.c                                 |    8 +
+ fs/hfsplus/catalog.c                               |   36 +-
+ fs/hfsplus/dir.c                                   |    6 +-
+ fs/hfsplus/extents.c                               |    4 +-
+ fs/hfsplus/hfsplus_fs.h                            |   41 +-
+ fs/hfsplus/hfsplus_raw.h                           |   72 +-
+ fs/hfsplus/inode.c                                 |   13 +
+ fs/hfsplus/ioctl.c                                 |  542 ++++-
+ fs/hfsplus/super.c                                 |   39 +-
+ fs/hfsplus/unicode.c                               |    7 +-
+ fs/hpfs/super.c                                    |    5 +
+ fs/hugetlbfs/inode.c                               |   16 +-
+ fs/inode.c                                         |    2 +-
+ fs/isofs/inode.c                                   |    5 +
+ fs/jffs2/readinode.c                               |   13 +-
+ fs/jffs2/super.c                                   |    6 +
+ fs/jfs/super.c                                     |    6 +
+ fs/logfs/inode.c                                   |    5 +
+ fs/minix/inode.c                                   |    5 +
+ fs/ncpfs/inode.c                                   |    5 +
+ fs/ncpfs/ioctl.c                                   |    2 +-
+ fs/nfs/file.c                                      |    1 +
+ fs/nfs/inode.c                                     |    5 +
+ fs/nilfs2/file.c                                   |    2 +-
+ fs/nilfs2/super.c                                  |    6 +
+ fs/ntfs/super.c                                    |    6 +
+ fs/ocfs2/dlmfs/dlmfs.c                             |    5 +
+ fs/ocfs2/mmap.c                                    |    2 +-
+ fs/ocfs2/super.c                                   |    5 +
+ fs/openpromfs/inode.c                              |    5 +
+ fs/proc/base.c                                     |  123 +-
+ fs/proc/generic.c                                  |   15 +-
+ fs/proc/inode.c                                    |    1 -
+ fs/proc/internal.h                                 |    2 +-
+ fs/proc/page.c                                     |    7 +-
+ fs/proc/proc_sysctl.c                              |    8 +-
+ fs/proc/root.c                                     |    2 +-
+ fs/proc/task_mmu.c                                 |    2 +-
+ fs/qnx4/inode.c                                    |    5 +
+ fs/qnx6/inode.c                                    |    5 +
+ fs/reiserfs/super.c                                |    5 +
+ fs/romfs/super.c                                   |    5 +
+ fs/squashfs/super.c                                |    5 +
+ fs/super.c                                         |    8 +-
+ fs/sysv/inode.c                                    |    5 +
+ fs/ubifs/file.c                                    |    1 +
+ fs/ubifs/super.c                                   |    6 +
+ fs/udf/file.c                                      |    2 +-
+ fs/udf/super.c                                     |    5 +
+ fs/ufs/super.c                                     |    5 +
+ fs/xfs/xfs_file.c                                  |    2 +-
+ fs/xfs/xfs_super.c                                 |    5 +
+ include/asm-generic/bitops/le.h                    |   10 +
+ include/asm-generic/pgtable.h                      |   72 +-
+ include/linux/atomic.h                             |   25 +
+ include/linux/audit.h                              |  189 +-
+ include/linux/binfmts.h                            |    3 +-
+ include/linux/compaction.h                         |    4 +-
+ include/linux/compat.h                             |    5 -
+ include/linux/coredump.h                           |    5 +
+ include/linux/elf.h                                |    6 +
+ include/linux/eventpoll.h                          |    1 +
+ include/linux/fs.h                                 |    8 +-
+ include/linux/genalloc.h                           |   27 +
+ include/linux/genhd.h                              |    8 +-
+ include/linux/gfp.h                                |    5 +-
+ include/linux/huge_mm.h                            |    1 -
+ include/linux/idr.h                                |   10 +-
+ include/linux/init.h                               |   27 +-
+ include/linux/interval_tree.h                      |   27 +
+ include/linux/interval_tree_generic.h              |  191 ++
+ include/linux/memblock.h                           |    3 +-
+ include/linux/mempolicy.h                          |    4 +-
+ include/linux/mfd/rc5t583.h                        |   22 +
+ include/linux/mfd/tps65910.h                       |   10 +
+ include/linux/mm.h                                 |  140 +-
+ include/linux/mm_types.h                           |   16 +-
+ include/linux/mman.h                               |    1 -
+ include/linux/mmu_notifier.h                       |   60 +-
+ include/linux/mmzone.h                             |    7 +-
+ include/linux/nbd.h                                |   15 +-
+ include/linux/oom.h                                |   11 -
+ include/linux/page-isolation.h                     |    7 +-
+ include/linux/pageblock-flags.h                    |   19 +-
+ include/linux/percpu.h                             |    2 +-
+ include/linux/platform_data/lm3630_bl.h            |   57 +
+ include/linux/platform_data/lm3639_bl.h            |   69 +
+ include/linux/platform_data/lp855x.h               |    2 +
+ include/linux/prio_tree.h                          |  120 -
+ include/linux/rbtree.h                             |  119 +-
+ include/linux/rbtree_augmented.h                   |  223 ++
+ include/linux/rio.h                                |   11 +-
+ include/linux/rio_drv.h                            |    5 +
+ include/linux/rmap.h                               |   39 +-
+ include/linux/rtc-ds2404.h                         |   20 +
+ include/linux/rtc.h                                |    2 +-
+ include/linux/sched.h                              |    1 -
+ include/linux/swap.h                               |    2 +-
+ include/linux/timerqueue.h                         |    2 +-
+ include/linux/vm_event_item.h                      |    1 -
+ include/linux/vmstat.h                             |   12 +
+ include/net/net_namespace.h                        |    2 +
+ include/trace/events/gfpflags.h                    |    1 -
+ init/Kconfig                                       |    7 +
+ init/do_mounts.c                                   |   61 +-
+ init/main.c                                        |    2 -
+ ipc/mqueue.c                                       |    3 -
+ ipc/sem.c                                          |  250 +-
+ kernel/auditsc.c                                   |   13 +-
+ kernel/events/core.c                               |    2 +-
+ kernel/events/uprobes.c                            |    8 +-
+ kernel/fork.c                                      |   32 +-
+ kernel/kexec.c                                     |    1 -
+ kernel/resource.c                                  |   50 +-
+ kernel/signal.c                                    |    3 +-
+ kernel/sys.c                                       |    5 +-
+ kernel/sysctl.c                                    |   12 +-
+ kernel/taskstats.c                                 |    1 +
+ kernel/time.c                                      |    4 +-
+ kernel/timeconst.pl                                |    2 +-
+ lib/Kconfig.debug                                  |   31 +-
+ lib/Makefile                                       |    7 +-
+ lib/crc32.c                                        |    9 +-
+ lib/decompress.c                                   |    9 +-
+ lib/gcd.c                                          |    3 +
+ lib/gen_crc32table.c                               |    6 +-
+ lib/genalloc.c                                     |   88 +-
+ lib/idr.c                                          |   32 +-
+ lib/interval_tree.c                                |   10 +
+ lib/interval_tree_test_main.c                      |  105 +
+ lib/parser.c                                       |   10 +-
+ lib/plist.c                                        |    4 +-
+ lib/prio_tree.c                                    |  466 ----
+ lib/rbtree.c                                       |  656 +++---
+ lib/rbtree_test.c                                  |  234 ++
+ lib/scatterlist.c                                  |   16 +-
+ lib/spinlock_debug.c                               |   32 +-
+ lib/vsprintf.c                                     |  139 +-
+ mm/Kconfig                                         |    3 +-
+ mm/Makefile                                        |    4 +-
+ mm/bootmem.c                                       |   10 +-
+ mm/compaction.c                                    |  515 +++--
+ mm/filemap.c                                       |    6 +-
+ mm/filemap_xip.c                                   |   10 +-
+ mm/fremap.c                                        |   16 +-
+ mm/huge_memory.c                                   |  439 ++--
+ mm/hugetlb.c                                       |   29 +-
+ mm/internal.h                                      |   92 +-
+ mm/interval_tree.c                                 |  112 +
+ mm/kmemleak.c                                      |  101 +-
+ mm/ksm.c                                           |  175 +-
+ mm/madvise.c                                       |    8 +-
+ mm/memblock.c                                      |    7 +-
+ mm/memcontrol.c                                    |   22 +-
+ mm/memory-failure.c                                |    8 +-
+ mm/memory.c                                        |  116 +-
+ mm/memory_hotplug.c                                |   29 +-
+ mm/mempolicy.c                                     |  148 +-
+ mm/mlock.c                                         |   18 +-
+ mm/mmap.c                                          |  207 +-
+ mm/mmu_notifier.c                                  |  103 +-
+ mm/mremap.c                                        |   73 +-
+ mm/nobootmem.c                                     |    5 +-
+ mm/nommu.c                                         |   33 +-
+ mm/oom_kill.c                                      |    4 +-
+ mm/page_alloc.c                                    |  270 ++-
+ mm/page_isolation.c                                |   43 +-
+ mm/percpu.c                                        |    2 +-
+ mm/pgtable-generic.c                               |   50 +
+ mm/prio_tree.c                                     |  208 --
+ mm/rmap.c                                          |  162 +-
+ mm/shmem.c                                         |    4 +-
+ mm/swap.c                                          |   13 +-
+ mm/swap_state.c                                    |    6 +
+ mm/truncate.c                                      |    3 -
+ mm/vmalloc.c                                       |    3 +-
+ mm/vmscan.c                                        |   99 +-
+ mm/vmstat.c                                        |   14 +-
+ net/can/af_can.c                                   |    2 +-
+ net/can/bcm.c                                      |    2 +-
+ net/can/gw.c                                       |    2 +-
+ net/can/raw.c                                      |    2 +-
+ net/ceph/osd_client.c                              |    1 -
+ net/decnet/dn_rules.c                              |    2 +-
+ net/ipv4/fib_rules.c                               |    2 +-
+ net/ipv4/ipmr.c                                    |    2 +-
+ net/ipv6/addrlabel.c                               |    2 +-
+ net/ipv6/fib6_rules.c                              |    2 +-
+ net/ipv6/ip6mr.c                                   |    2 +-
+ scripts/Kbuild.include                             |    2 +-
+ scripts/checkpatch.pl                              |   35 +-
+ security/device_cgroup.c                           |  373 +--
+ security/selinux/netnode.c                         |    3 +-
+ security/selinux/selinuxfs.c                       |    2 +-
+ security/tomoyo/util.c                             |    9 +-
+ sound/core/pcm_native.c                            |    6 +-
+ sound/soc/codecs/wm5100.c                          |    2 +-
+ sound/usb/usx2y/us122l.c                           |    2 +-
+ sound/usb/usx2y/usX2Yhwdep.c                       |    2 +-
+ sound/usb/usx2y/usx2yhwdeppcm.c                    |    2 +-
+ tools/perf/util/include/linux/rbtree.h             |    1 +
+ tools/testing/selftests/Makefile                   |    2 +-
+ tools/testing/selftests/epoll/Makefile             |   11 +
+ tools/testing/selftests/epoll/test_epoll.c         |  344 +++
+ virt/kvm/kvm_main.c                                |    3 +-
+ 610 files changed, 16504 insertions(+), 6655 deletions(-)
+ delete mode 100644 Documentation/ABI/obsolete/proc-pid-oom_adj
+ create mode 100644 Documentation/devicetree/bindings/misc/lis302.txt
+ create mode 100644 Documentation/devicetree/bindings/rtc/snvs-rtc.txt
+ delete mode 100644 Documentation/memory.txt
+ delete mode 100644 Documentation/prio_tree.txt
+ create mode 100644 drivers/memstick/core/ms_block.c
+ create mode 100644 drivers/memstick/core/ms_block.h
+ create mode 100644 drivers/rtc/rtc-ds2404.c
+ create mode 100644 drivers/rtc/rtc-max8907.c
+ create mode 100644 drivers/rtc/rtc-rc5t583.c
+ create mode 100644 drivers/rtc/rtc-snvs.c
+ create mode 100644 drivers/rtc/rtc-tps65910.c
+ create mode 100644 drivers/video/backlight/lm3630_bl.c
+ create mode 100644 drivers/video/backlight/lm3639_bl.c
+ delete mode 100644 drivers/video/backlight/progear_bl.c
+ create mode 100644 fs/coredump.c
+ create mode 100644 fs/coredump.h
+ create mode 100644 fs/fat/nfs.c
+ create mode 100644 fs/hfsplus/attributes.c
+ create mode 100644 include/linux/interval_tree.h
+ create mode 100644 include/linux/interval_tree_generic.h
+ create mode 100644 include/linux/platform_data/lm3630_bl.h
+ create mode 100644 include/linux/platform_data/lm3639_bl.h
+ delete mode 100644 include/linux/prio_tree.h
+ create mode 100644 include/linux/rbtree_augmented.h
+ create mode 100644 include/linux/rtc-ds2404.h
+ create mode 100644 lib/interval_tree.c
+ create mode 100644 lib/interval_tree_test_main.c
+ delete mode 100644 lib/prio_tree.c
+ create mode 100644 lib/rbtree_test.c
+ create mode 100644 mm/interval_tree.c
+ delete mode 100644 mm/prio_tree.c
+ create mode 100644 tools/testing/selftests/epoll/Makefile
+ create mode 100644 tools/testing/selftests/epoll/test_epoll.c
+$ git revert e269b4131288
+[master 706e5eb] Revert "audit.h: replace defines with C stubs"
+ 1 file changed, 51 insertions(+), 138 deletions(-)
diff --git a/Next/quilt-import.log b/Next/quilt-import.log
new file mode 100644
index 0000000..43e4b6e
--- /dev/null
+++ b/Next/quilt-import.log
@@ -0,0 +1,77 @@
+Importing i2c based on 3.6-rc7
+Unchanged quilt series i2c
+Importing jdelvare-hwmon based on 3.6-rc7
+$ git clone -s -l -n -q . ../quilt-tmp
+$ cd ../quilt-tmp
+$ git reset --hard 979570e02981d4a8fc20b3cc8fd651856c98ee9d
+HEAD is now at 979570e Linux 3.6-rc7
+$ git am ../quilt/jdelvare-hwmon/hwmon-update-Alexey-Fisher-s-name.patch
+Applying: hwmon: Update Alexey Fisher's name
+$ cd ../next
+$ git fetch -f ../quilt-tmp master:quilt/jdelvare-hwmon
+From ../quilt-tmp
+ + 5e25f31...46e486e master     -> quilt/jdelvare-hwmon  (forced update)
+Importing rr based on v3.6-rc6-28-g925a6f0
+$ cd ../quilt-tmp
+$ git reset --hard 925a6f0bf8bd122d5d2429af7f0ca0fecf4ae71f
+HEAD is now at 925a6f0 Merge tag 'hwspinlock-3.6-fix' of git://git.kernel.org/pub/scm/linux/kernel/git/ohad/hwspinlock
+$ git am ../quilt/rr/module:taint_kernel_when_lve_is_loaded.patch
+Applying: module: taint kernel when lve module is loaded
+$ git am ../quilt/rr/module:mips_fix_c_build_for_32_bit.patch
+Applying: MIPS: Fix module.c build for 32 bit
+$ git am ../quilt/rr/module:make_most_arch_asm_h_files_use_asm_generic_h.patch
+Applying: Make most arch asm/module.h files use asm-generic/module.h
+$ git am ../quilt/rr/module-fix-wakeup-for-symbols.patch
+Applying: module: fix symbol waiting when module fails before init
+$ git am ../quilt/rr/module-wait-on-loading-module.patch
+Applying: module: wait when loading a module which is currently initializing.
+$ git am ../quilt/rr/virtio:console_add_splice_write_support.patch
+Applying: virtio/console: Add splice_write support
+$ git am ../quilt/rr/virtio:console_add_a_failback_for_unstealable_pipe_buffer.patch
+Applying: virtio/console: Add a failback for unstealable pipe buffer
+$ git am ../quilt/rr/virtio:console_wait_until_the_port_is_ready_on_splice.patch
+Applying: virtio/console: Wait until the port is ready on splice
+$ git am ../quilt/rr/misc:ftrace_allow_stealing_pages_from_pipe_buffer.patch
+Applying: ftrace: Allow stealing pages from pipe buffer
+$ git am ../quilt/rr/virtio:console_allocate_scatterlist_according_to_the_current_pipe_size.patch
+Applying: virtio/console: Allocate scatterlist according to the current pipe size
+$ git am ../quilt/rr/misc:tools_add_guest_trace_agent_as_a_user_tool.patch
+Applying: tools: Add guest trace agent as a user tool
+$ git am ../quilt/rr/virtio:tools_fix_pthread_flag_for_makefile_of_trace_agent_used_by_trace.patch
+Applying: tools: Fix pthread flag for Makefile of trace-agent used by virtio-trace
+$ git am ../quilt/rr/virtio:console_fix_error_handling_in_init_function.patch
+Applying: virtio: console: fix error handling in init() function
+$ git am ../quilt/rr/virtio:blk_add_bio_based_io_path_for_blk.patch
+Applying: virtio-blk: Add bio-based IO path for virtio-blk
+$ git am ../quilt/rr/virtio:blk_add_req_flush_and_req_fua_support_to_bio_path.patch
+Applying: virtio-blk: Add REQ_FLUSH and REQ_FUA support to bio path
+$ git am ../quilt/rr/virtio:blk_add_req_flush_and_req_fua_support_to_bio_path.patch-fix
+Applying: virtio-blk: fix NULL checking in virtblk_alloc_req()
+$ git am ../quilt/rr/virtio:blk_fix_kconfig_option.patch
+Applying: virtio-balloon: dependency fix
+$ git am ../quilt/rr/virtio-blk-not-experimental.patch
+Applying: virtio_balloon: not EXPERIMENTAL any more.
+$ git am ../quilt/rr/virtio:ring_move_queue_index_to_vring_virtqueue.patch
+Applying: virtio-ring: move queue_index to vring_virtqueue
+$ git am ../quilt/rr/virtio:introduce_an_api_to_set_affinity_for_a_virtqueue.patch
+Applying: virtio: introduce an API to set affinity for a virtqueue
+$ git am ../quilt/rr/virtio:support_reserved_vqs.patch
+Applying: virtio: support reserved vqs
+$ git am ../quilt/rr/virtio-config-cleanup.patch
+Applying: virtio: add help to CONFIG_VIRTIO option.
+$ git am ../quilt/rr/virtio-remove-ring-option.patch
+Applying: virtio: remove CONFIG_VIRTIO_RING
+$ git am ../quilt/rr/virtio-remove-extra-debug-check.patch
+Applying: virtio: don't crash when device is buggy
+$ git am ../quilt/rr/virtio:drivers_pci_c_fix_error_return_code.patch
+Applying: drivers/virtio/virtio_pci.c: fix error return code
+$ git am ../quilt/rr/virtio:mmio_fix_off_by_one_error_allocating_queue.patch
+Applying: virtio_mmio: fix off by one error allocating queue
+$ git am ../quilt/rr/virtio:mmio_don_t_attempt_to_create_empty_virtqueues.patch
+Applying: virtio_mmio: Don't attempt to create empty virtqueues
+$ cd ../next
+$ git fetch -f ../quilt-tmp master:quilt/rr
+From ../quilt-tmp
+ + 98bec22...76e01ba master     -> quilt/rr  (forced update)
+Importing device-mapper based on block/for-next
+Unchanged quilt series device-mapper
diff --git a/arch/Kconfig b/arch/Kconfig
index 72f2fa1..a9e8f74 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -222,6 +222,19 @@ config HAVE_PERF_EVENTS_NMI
 	  subsystem.  Also has support for calculating CPU cycle events
 	  to determine how many clock cycles in a given period.
 
+config HAVE_PERF_REGS
+	bool
+	help
+	  Support selective register dumps for perf events. This includes
+	  bit-mapping of each registers and a unique architecture id.
+
+config HAVE_PERF_USER_STACK_DUMP
+	bool
+	help
+	  Support user stack dumps for perf event samples. This needs
+	  access to the user stack pointer which is not unified across
+	  architectures.
+
 config HAVE_ARCH_JUMP_LABEL
 	bool
 
@@ -258,6 +271,9 @@ config ARCH_WANT_OLD_COMPAT_IPC
 	select ARCH_WANT_COMPAT_IPC_PARSE_VERSION
 	bool
 
+config GENERIC_KERNEL_THREAD
+	bool
+
 config HAVE_ARCH_SECCOMP_FILTER
 	bool
 	help
@@ -281,4 +297,29 @@ config SECCOMP_FILTER
 
 	  See Documentation/prctl/seccomp_filter.txt for details.
 
+config HAVE_MOD_ARCH_SPECIFIC
+	bool
+	help
+	  The arch uses struct mod_arch_specific to store data.  Many arches
+	  just need a simple module loader without arch specific data - those
+	  should not enable this.
+
+config MODULES_USE_ELF_RELA
+	bool
+	help
+	  Modules only use ELF RELA relocations.  Modules with ELF REL
+	  relocations will give an error.
+
+config MODULES_USE_ELF_REL
+	bool
+	help
+	  Modules only use ELF REL relocations.  Modules with ELF RELA
+	  relocations will give an error.
+
+config HAVE_VIRT_CPU_ACCOUNTING
+	bool
+
+config HAVE_ARCH_TRANSPARENT_HUGEPAGE
+	bool
+
 source "kernel/gcov/Kconfig"
diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig
index 9944ded..6ac8f6e 100644
--- a/arch/alpha/Kconfig
+++ b/arch/alpha/Kconfig
@@ -20,6 +20,9 @@ config ALPHA
 	select GENERIC_CMOS_UPDATE
 	select GENERIC_STRNCPY_FROM_USER
 	select GENERIC_STRNLEN_USER
+	select HAVE_MOD_ARCH_SPECIFIC
+	select MODULES_USE_ELF_RELA
+	select GENERIC_KERNEL_THREAD
 	help
 	  The Alpha is a 64-bit general-purpose processor designed and
 	  marketed by the Digital Equipment Corporation of blessed memory,
diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild
index e423def..3bae7c9 100644
--- a/arch/alpha/include/asm/Kbuild
+++ b/arch/alpha/include/asm/Kbuild
@@ -8,3 +8,4 @@ header-y += pal.h
 header-y += reg.h
 header-y += regdef.h
 header-y += sysinfo.h
+generic-y += exec.h
diff --git a/arch/alpha/include/asm/exec.h b/arch/alpha/include/asm/exec.h
deleted file mode 100644
index 4a5a41f..0000000
--- a/arch/alpha/include/asm/exec.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __ALPHA_EXEC_H
-#define __ALPHA_EXEC_H
-
-#define arch_align_stack(x) (x)
-
-#endif /* __ALPHA_EXEC_H */
diff --git a/arch/alpha/include/asm/module.h b/arch/alpha/include/asm/module.h
index 7b63743..9cd13b5 100644
--- a/arch/alpha/include/asm/module.h
+++ b/arch/alpha/include/asm/module.h
@@ -1,19 +1,13 @@
 #ifndef _ALPHA_MODULE_H
 #define _ALPHA_MODULE_H
 
+#include <asm-generic/module.h>
+
 struct mod_arch_specific
 {
 	unsigned int gotsecindex;
 };
 
-#define Elf_Sym Elf64_Sym
-#define Elf_Shdr Elf64_Shdr
-#define Elf_Ehdr Elf64_Ehdr
-#define Elf_Phdr Elf64_Phdr
-#define Elf_Dyn Elf64_Dyn
-#define Elf_Rel Elf64_Rel
-#define Elf_Rela Elf64_Rela
-
 #define ARCH_SHF_SMALL SHF_ALPHA_GPREL
 
 #ifdef MODULE
diff --git a/arch/alpha/include/asm/processor.h b/arch/alpha/include/asm/processor.h
index e37b887..6cb7fe8 100644
--- a/arch/alpha/include/asm/processor.h
+++ b/arch/alpha/include/asm/processor.h
@@ -49,9 +49,6 @@ extern void start_thread(struct pt_regs *, unsigned long, unsigned long);
 /* Free all resources held by a thread. */
 extern void release_thread(struct task_struct *);
 
-/* Create a kernel thread without removing it from tasklists.  */
-extern long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
-
 unsigned long get_wchan(struct task_struct *p);
 
 #define KSTK_EIP(tsk) (task_pt_regs(tsk)->pc)
diff --git a/arch/alpha/include/asm/thread_info.h b/arch/alpha/include/asm/thread_info.h
index 28335bd..4554ecb 100644
--- a/arch/alpha/include/asm/thread_info.h
+++ b/arch/alpha/include/asm/thread_info.h
@@ -84,7 +84,6 @@ register struct thread_info *__current_thread_info __asm__("$8");
 #define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
-#define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
 #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
 
 /* Work to do on interrupt/exception return.  */
@@ -117,5 +116,7 @@ register struct thread_info *__current_thread_info __asm__("$8");
 		 (int __user *)(value));				\
 	})
 
+#define tsk_is_polling(t) test_tsk_thread_flag(t, TIF_POLLING_NRFLAG)
+
 #endif /* __KERNEL__ */
 #endif /* _ALPHA_THREAD_INFO_H */
diff --git a/arch/alpha/include/asm/unistd.h b/arch/alpha/include/asm/unistd.h
index a31a78e..3cb6c11 100644
--- a/arch/alpha/include/asm/unistd.h
+++ b/arch/alpha/include/asm/unistd.h
@@ -481,6 +481,8 @@
 #define __ARCH_WANT_SYS_OLDUMOUNT
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_RT_SIGSUSPEND
+#define __ARCH_WANT_SYS_EXECVE
+#define __ARCH_WANT_KERNEL_EXECVE
 
 /* "Conditional" syscalls.  What we want is
 
diff --git a/arch/alpha/kernel/alpha_ksyms.c b/arch/alpha/kernel/alpha_ksyms.c
index 15fa821..89566b3 100644
--- a/arch/alpha/kernel/alpha_ksyms.c
+++ b/arch/alpha/kernel/alpha_ksyms.c
@@ -50,9 +50,6 @@ EXPORT_SYMBOL(alpha_read_fp_reg_s);
 EXPORT_SYMBOL(alpha_write_fp_reg);
 EXPORT_SYMBOL(alpha_write_fp_reg_s);
 
-/* entry.S */
-EXPORT_SYMBOL(kernel_thread);
-
 /* Networking helper routines. */
 EXPORT_SYMBOL(csum_tcpudp_magic);
 EXPORT_SYMBOL(ip_compute_csum);
diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S
index ec0da05..b36fc1b 100644
--- a/arch/alpha/kernel/entry.S
+++ b/arch/alpha/kernel/entry.S
@@ -418,11 +418,10 @@ $work_notifysig:
 strace:
 	/* set up signal stack, call syscall_trace */
 	bsr	$1, do_switch_stack
-	jsr	$26, syscall_trace
+	jsr	$26, syscall_trace_enter /* returns the syscall number */
 	bsr	$1, undo_switch_stack
 
-	/* get the system call number and the arguments back.. */
-	ldq	$0, 0($sp)
+	/* get the arguments back.. */
 	ldq	$16, SP_OFF+24($sp)
 	ldq	$17, SP_OFF+32($sp)
 	ldq	$18, SP_OFF+40($sp)
@@ -449,7 +448,7 @@ $strace_success:
 	stq	$0, 0($sp)		/* save return value */
 
 	bsr	$1, do_switch_stack
-	jsr	$26, syscall_trace
+	jsr	$26, syscall_trace_leave
 	bsr	$1, undo_switch_stack
 	br	$31, ret_from_sys_call
 
@@ -467,7 +466,7 @@ $strace_error:
 	bsr	$1, do_switch_stack
 	mov	$19, $9		/* save old syscall number */
 	mov	$20, $10	/* save old a3 */
-	jsr	$26, syscall_trace
+	jsr	$26, syscall_trace_leave
 	mov	$9, $19
 	mov	$10, $20
 	bsr	$1, undo_switch_stack
@@ -609,59 +608,34 @@ ret_from_fork:
 .end ret_from_fork
 
 /*
- * kernel_thread(fn, arg, clone_flags)
+ * ... and new kernel threads - here
  */
 	.align 4
-	.globl	kernel_thread
-	.ent	kernel_thread
-kernel_thread:
-	/* We can be called from a module.  */
-	ldgp	$gp, 0($27)
-	.prologue 1
-	subq	$sp, SP_OFF+6*8, $sp
-	br	$1, 2f		/* load start address */
-
-	/* We've now "returned" from a fake system call.  */
-	unop
-	blt	$0, 1f		/* error?  */
-	ldi	$1, 0x3fff
-	beq	$20, 1f		/* parent or child?  */
-
-	bic	$sp, $1, $8	/* in child.  */
-	jsr	$26, ($27)
+	.globl	ret_from_kernel_thread
+	.ent	ret_from_kernel_thread
+ret_from_kernel_thread:
+	mov	$17, $16
+	jsr	$26, schedule_tail
+	mov	$9, $27
+	mov	$10, $16
+	jsr	$26, ($9)
 	ldgp	$gp, 0($26)
 	mov	$0, $16
 	mov	$31, $26
 	jmp	$31, sys_exit
+.end ret_from_kernel_thread
 
-1:	ret			/* in parent.  */
-
-	.align 4
-2:	/* Fake a system call stack frame, as we can't do system calls
-	   from kernel space.  Note that we store FN and ARG as they
-	   need to be set up in the child for the call.  Also store $8
-	   and $26 for use in the parent.  */
-	stq	$31, SP_OFF($sp)	/* ps */
-	stq	$1, SP_OFF+8($sp)	/* pc */
-	stq	$gp, SP_OFF+16($sp)	/* gp */
-	stq	$16, 136($sp)		/* $27; FN for child */
-	stq	$17, SP_OFF+24($sp)	/* $16; ARG for child */
-	stq	$8, 64($sp)		/* $8 */
-	stq	$26, 128($sp)		/* $26 */
+	.globl	ret_from_kernel_execve
+	.align	4
+	.ent	ret_from_kernel_execve
+ret_from_kernel_execve:
+	mov	$0, $sp
 	/* Avoid the HAE being gratuitously wrong, to avoid restoring it.  */
 	ldq	$2, alpha_mv+HAE_CACHE
 	stq	$2, 152($sp)		/* HAE */
+	br	$31, ret_to_user
 
-	/* Shuffle FLAGS to the front; add CLONE_VM.  */
-	ldi	$1, CLONE_VM|CLONE_UNTRACED
-	or	$18, $1, $16
-	bsr	$26, sys_clone
-
-	/* We don't actually care for a3 success widgetry in the kernel.
-	   Not for positive errno values.  */
-	stq	$0, 0($sp)		/* $0 */
-	br	ret_to_kernel
-.end kernel_thread
+.end	ret_from_kernel_execve
 
 
 /*
@@ -722,7 +696,7 @@ sys_sigreturn:
 	lda	$sp, -SWITCH_STACK_SIZE($sp)
 	jsr	$26, do_sigreturn
 	bne	$9, 1f
-	jsr	$26, syscall_trace
+	jsr	$26, syscall_trace_leave
 1:	br	$1, undo_switch_stack
 	br	ret_from_sys_call
 .end sys_sigreturn
@@ -739,21 +713,12 @@ sys_rt_sigreturn:
 	lda	$sp, -SWITCH_STACK_SIZE($sp)
 	jsr	$26, do_rt_sigreturn
 	bne	$9, 1f
-	jsr	$26, syscall_trace
+	jsr	$26, syscall_trace_leave
 1:	br	$1, undo_switch_stack
 	br	ret_from_sys_call
 .end sys_rt_sigreturn
 
 	.align	4
-	.globl	sys_execve
-	.ent	sys_execve
-sys_execve:
-	.prologue 0
-	mov	$sp, $19
-	jmp	$31, do_sys_execve
-.end sys_execve
-
-	.align	4
 	.globl	alpha_ni_syscall
 	.ent	alpha_ni_syscall
 alpha_ni_syscall:
diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c
index bc1acdd..63e77e3 100644
--- a/arch/alpha/kernel/osf_sys.c
+++ b/arch/alpha/kernel/osf_sys.c
@@ -145,27 +145,24 @@ SYSCALL_DEFINE4(osf_getdirentries, unsigned int, fd,
 		long __user *, basep)
 {
 	int error;
-	struct file *file;
+	struct fd arg = fdget(fd);
 	struct osf_dirent_callback buf;
 
-	error = -EBADF;
-	file = fget(fd);
-	if (!file)
-		goto out;
+	if (!arg.file)
+		return -EBADF;
 
 	buf.dirent = dirent;
 	buf.basep = basep;
 	buf.count = count;
 	buf.error = 0;
 
-	error = vfs_readdir(file, osf_filldir, &buf);
+	error = vfs_readdir(arg.file, osf_filldir, &buf);
 	if (error >= 0)
 		error = buf.error;
 	if (count != buf.count)
 		error = count - buf.count;
 
-	fput(file);
- out:
+	fdput(arg);
 	return error;
 }
 
@@ -278,8 +275,8 @@ linux_to_osf_stat(struct kstat *lstat, struct osf_stat __user *osf_stat)
 	tmp.st_dev	= lstat->dev;
 	tmp.st_mode	= lstat->mode;
 	tmp.st_nlink	= lstat->nlink;
-	tmp.st_uid	= lstat->uid;
-	tmp.st_gid	= lstat->gid;
+	tmp.st_uid	= from_kuid_munged(current_user_ns(), lstat->uid);
+	tmp.st_gid	= from_kgid_munged(current_user_ns(), lstat->gid);
 	tmp.st_rdev	= lstat->rdev;
 	tmp.st_ldev	= lstat->rdev;
 	tmp.st_size	= lstat->size;
diff --git a/arch/alpha/kernel/pci-sysfs.c b/arch/alpha/kernel/pci-sysfs.c
index 53649c7..b51f7b4 100644
--- a/arch/alpha/kernel/pci-sysfs.c
+++ b/arch/alpha/kernel/pci-sysfs.c
@@ -26,7 +26,7 @@ static int hose_mmap_page_range(struct pci_controller *hose,
 		base = sparse ? hose->sparse_io_base : hose->dense_io_base;
 
 	vma->vm_pgoff += base >> PAGE_SHIFT;
-	vma->vm_flags |= (VM_IO | VM_RESERVED);
+	vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP;
 
 	return io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
 				  vma->vm_end - vma->vm_start,
diff --git a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c
index 9816d5a..ef75714 100644
--- a/arch/alpha/kernel/pci.c
+++ b/arch/alpha/kernel/pci.c
@@ -256,12 +256,6 @@ pcibios_fixup_bus(struct pci_bus *bus)
 	}
 }
 
-void __init
-pcibios_update_irq(struct pci_dev *dev, int irq)
-{
-	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
-}
-
 int
 pcibios_enable_device(struct pci_dev *dev, int mask)
 {
diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c
index d6fde98..93ec11f 100644
--- a/arch/alpha/kernel/process.c
+++ b/arch/alpha/kernel/process.c
@@ -28,6 +28,7 @@
 #include <linux/tty.h>
 #include <linux/console.h>
 #include <linux/slab.h>
+#include <linux/rcupdate.h>
 
 #include <asm/reg.h>
 #include <asm/uaccess.h>
@@ -54,9 +55,12 @@ cpu_idle(void)
 		/* FIXME -- EV6 and LCA45 know how to power down
 		   the CPU.  */
 
+		rcu_idle_enter();
 		while (!need_resched())
 			cpu_relax();
-		schedule();
+
+		rcu_idle_exit();
+		schedule_preempt_disabled();
 	}
 }
 
@@ -259,33 +263,35 @@ alpha_vfork(struct pt_regs *regs)
 
 /*
  * Copy an alpha thread..
- *
- * Note the "stack_offset" stuff: when returning to kernel mode, we need
- * to have some extra stack-space for the kernel stack that still exists
- * after the "ret_from_fork".  When returning to user mode, we only want
- * the space needed by the syscall stack frame (ie "struct pt_regs").
- * Use the passed "regs" pointer to determine how much space we need
- * for a kernel fork().
  */
 
 int
 copy_thread(unsigned long clone_flags, unsigned long usp,
-	    unsigned long unused,
+	    unsigned long arg,
 	    struct task_struct * p, struct pt_regs * regs)
 {
 	extern void ret_from_fork(void);
+	extern void ret_from_kernel_thread(void);
 
 	struct thread_info *childti = task_thread_info(p);
-	struct pt_regs * childregs;
-	struct switch_stack * childstack, *stack;
-	unsigned long stack_offset, settls;
-
-	stack_offset = PAGE_SIZE - sizeof(struct pt_regs);
-	if (!(regs->ps & 8))
-		stack_offset = (PAGE_SIZE-1) & (unsigned long) regs;
-	childregs = (struct pt_regs *)
-	  (stack_offset + PAGE_SIZE + task_stack_page(p));
-		
+	struct pt_regs *childregs = task_pt_regs(p);
+	struct switch_stack *childstack, *stack;
+	unsigned long settls;
+
+	childstack = ((struct switch_stack *) childregs) - 1;
+	if (unlikely(!regs)) {
+		/* kernel thread */
+		memset(childstack, 0,
+			sizeof(struct switch_stack) + sizeof(struct pt_regs));
+		childstack->r26 = (unsigned long) ret_from_kernel_thread;
+		childstack->r9 = usp;	/* function */
+		childstack->r10 = arg;	/* function */
+		childregs->hae = alpha_mv.hae_cache,
+		childti->pcb.usp = 0;
+		childti->pcb.ksp = (unsigned long) childstack;
+		childti->pcb.flags = 1;	/* set FEN, clear everything else */
+		return 0;
+	}
 	*childregs = *regs;
 	settls = regs->r20;
 	childregs->r0 = 0;
@@ -293,7 +299,6 @@ copy_thread(unsigned long clone_flags, unsigned long usp,
 	childregs->r20 = 1;	/* OSF/1 has some strange fork() semantics.  */
 	regs->r20 = 0;
 	stack = ((struct switch_stack *) regs) - 1;
-	childstack = ((struct switch_stack *) childregs) - 1;
 	*childstack = *stack;
 	childstack->r26 = (unsigned long) ret_from_fork;
 	childti->pcb.usp = usp;
@@ -382,27 +387,6 @@ dump_elf_task_fp(elf_fpreg_t *dest, struct task_struct *task)
 EXPORT_SYMBOL(dump_elf_task_fp);
 
 /*
- * sys_execve() executes a new program.
- */
-asmlinkage int
-do_sys_execve(const char __user *ufilename,
-	      const char __user *const __user *argv,
-	      const char __user *const __user *envp, struct pt_regs *regs)
-{
-	int error;
-	char *filename;
-
-	filename = getname(ufilename);
-	error = PTR_ERR(filename);
-	if (IS_ERR(filename))
-		goto out;
-	error = do_execve(filename, argv, envp, regs);
-	putname(filename);
-out:
-	return error;
-}
-
-/*
  * Return saved PC of a blocked thread.  This assumes the frame
  * pointer is the 6th saved long on the kernel stack and that the
  * saved return address is the first long in the frame.  This all
@@ -455,22 +439,3 @@ get_wchan(struct task_struct *p)
 	}
 	return pc;
 }
-
-int kernel_execve(const char *path, const char *const argv[], const char *const envp[])
-{
-	/* Avoid the HAE being gratuitously wrong, which would cause us
-	   to do the whole turn off interrupts thing and restore it.  */
-	struct pt_regs regs = {.hae = alpha_mv.hae_cache};
-	int err = do_execve(path, argv, envp, &regs);
-	if (!err) {
-		struct pt_regs *p = current_pt_regs();
-		/* copy regs to normal position and off to userland we go... */
-		*p = regs;
-		__asm__ __volatile__ (
-			"mov	%0, $sp;"
-			"br	$31, ret_from_sys_call"
-			: : "r"(p));
-	}
-	return err;
-}
-EXPORT_SYMBOL(kernel_execve);
diff --git a/arch/alpha/kernel/ptrace.c b/arch/alpha/kernel/ptrace.c
index 54616f4..2a4a80f 100644
--- a/arch/alpha/kernel/ptrace.c
+++ b/arch/alpha/kernel/ptrace.c
@@ -13,6 +13,7 @@
 #include <linux/user.h>
 #include <linux/security.h>
 #include <linux/signal.h>
+#include <linux/tracehook.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -312,25 +313,18 @@ long arch_ptrace(struct task_struct *child, long request,
 	return ret;
 }
 
+asmlinkage unsigned long syscall_trace_enter(void)
+{
+	unsigned long ret = 0;
+	if (test_thread_flag(TIF_SYSCALL_TRACE) &&
+	    tracehook_report_syscall_entry(current_pt_regs()))
+		ret = -1UL;
+	return ret ?: current_pt_regs()->r0;
+}
+
 asmlinkage void
-syscall_trace(void)
+syscall_trace_leave(void)
 {
-	if (!test_thread_flag(TIF_SYSCALL_TRACE))
-		return;
-	if (!(current->ptrace & PT_PTRACED))
-		return;
-	/* The 0x80 provides a way for the tracing parent to distinguish
-	   between a syscall stop and SIGTRAP delivery */
-	ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
-				 ? 0x80 : 0));
-
-	/*
-	 * This isn't the same as continuing with a signal, but it will do
-	 * for normal use.  strace only continues with a signal if the
-	 * stopping signal is not SIGTRAP.  -brl
-	 */
-	if (current->exit_code) {
-		send_sig(current->exit_code, current, 1);
-		current->exit_code = 0;
-	}
+	if (test_thread_flag(TIF_SYSCALL_TRACE))
+		tracehook_report_syscall_exit(current_pt_regs(), 0);
 }
diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c
index 35ddc02..a41ad90 100644
--- a/arch/alpha/kernel/smp.c
+++ b/arch/alpha/kernel/smp.c
@@ -166,6 +166,7 @@ smp_callin(void)
 	DBGS(("smp_callin: commencing CPU %d current %p active_mm %p\n",
 	      cpuid, current, current->active_mm));
 
+	preempt_disable();
 	/* Do nothing.  */
 	cpu_idle();
 }
diff --git a/arch/alpha/kernel/srmcons.c b/arch/alpha/kernel/srmcons.c
index 3ea8094..5d58652 100644
--- a/arch/alpha/kernel/srmcons.c
+++ b/arch/alpha/kernel/srmcons.c
@@ -223,6 +223,7 @@ srmcons_init(void)
 		driver->subtype = SYSTEM_TYPE_SYSCONS;
 		driver->init_termios = tty_std_termios;
 		tty_set_operations(driver, &srmcons_ops);
+		tty_port_link_device(&srmcons_singleton.port, driver, 0);
 		err = tty_register_driver(driver);
 		if (err) {
 			put_tty_driver(driver);
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 2f88d8d..3e186c0 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -16,6 +16,7 @@ config ARM
 	select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL
 	select HAVE_ARCH_KGDB
 	select HAVE_ARCH_TRACEHOOK
+	select HAVE_SYSCALL_TRACEPOINTS
 	select HAVE_KPROBES if !XIP_KERNEL
 	select HAVE_KRETPROBES if (HAVE_KPROBES)
 	select HAVE_FUNCTION_TRACER if (!XIP_KERNEL)
@@ -49,6 +50,9 @@ config ARM
 	select GENERIC_STRNCPY_FROM_USER
 	select GENERIC_STRNLEN_USER
 	select DCACHE_WORD_ACCESS if (CPU_V6 || CPU_V6K || CPU_V7) && !CPU_BIG_ENDIAN
+	select HAVE_MOD_ARCH_SPECIFIC if ARM_UNWIND
+	select MODULES_USE_ELF_REL
+	select GENERIC_KERNEL_THREAD
 	help
 	  The ARM series is a line of low-power-consumption RISC chip designs
 	  licensed by ARM Ltd and targeted at embedded applications and
@@ -202,6 +206,13 @@ config ARM_PATCH_PHYS_VIRT
 	  this feature (eg, building a kernel for a single machine) and
 	  you need to shrink the kernel to the minimal size.
 
+config NEED_MACH_GPIO_H
+	bool
+	help
+	  Select this when mach/gpio.h is required to provide special
+	  definitions for this platform. The need for mach/gpio.h should
+	  be avoided when possible.
+
 config NEED_MACH_IO_H
 	bool
 	help
@@ -247,39 +258,29 @@ config MMU
 #
 choice
 	prompt "ARM system type"
-	default ARCH_VERSATILE
+	default ARCH_MULTIPLATFORM
 
-config ARCH_SOCFPGA
-	bool "Altera SOCFPGA family"
-	select ARCH_WANT_OPTIONAL_GPIOLIB
-	select ARM_AMBA
-	select ARM_GIC
-	select CACHE_L2X0
-	select CLKDEV_LOOKUP
+config ARCH_MULTIPLATFORM
+	bool "Allow multiple platforms to be selected"
+	select ARM_PATCH_PHYS_VIRT
+	select AUTO_ZRELADDR
 	select COMMON_CLK
-	select CPU_V7
-	select DW_APB_TIMER
-	select DW_APB_TIMER_OF
-	select GENERIC_CLOCKEVENTS
-	select GPIO_PL061 if GPIOLIB
-	select HAVE_ARM_SCU
+	select MULTI_IRQ_HANDLER
 	select SPARSE_IRQ
 	select USE_OF
-	help
-	  This enables support for Altera SOCFPGA Cyclone V platform
+	depends on MMU
 
 config ARCH_INTEGRATOR
 	bool "ARM Ltd. Integrator family"
 	select ARM_AMBA
 	select ARCH_HAS_CPUFREQ
 	select COMMON_CLK
-	select CLK_VERSATILE
+	select COMMON_CLK_VERSATILE
 	select HAVE_TCM
 	select ICST
 	select GENERIC_CLOCKEVENTS
 	select PLAT_VERSATILE
 	select PLAT_VERSATILE_FPGA_IRQ
-	select NEED_MACH_IO_H
 	select NEED_MACH_MEMORY_H
 	select SPARSE_IRQ
 	select MULTI_IRQ_HANDLER
@@ -289,13 +290,12 @@ config ARCH_INTEGRATOR
 config ARCH_REALVIEW
 	bool "ARM Ltd. RealView family"
 	select ARM_AMBA
-	select CLKDEV_LOOKUP
-	select HAVE_MACH_CLKDEV
+	select COMMON_CLK
+	select COMMON_CLK_VERSATILE
 	select ICST
 	select GENERIC_CLOCKEVENTS
 	select ARCH_WANT_OPTIONAL_GPIOLIB
 	select PLAT_VERSATILE
-	select PLAT_VERSATILE_CLOCK
 	select PLAT_VERSATILE_CLCD
 	select ARM_TIMER_SP804
 	select GPIO_PL061 if GPIOLIB
@@ -312,7 +312,6 @@ config ARCH_VERSATILE
 	select ICST
 	select GENERIC_CLOCKEVENTS
 	select ARCH_WANT_OPTIONAL_GPIOLIB
-	select NEED_MACH_IO_H if PCI
 	select PLAT_VERSATILE
 	select PLAT_VERSATILE_CLOCK
 	select PLAT_VERSATILE_CLCD
@@ -321,64 +320,46 @@ config ARCH_VERSATILE
 	help
 	  This enables support for ARM Ltd Versatile board.
 
-config ARCH_VEXPRESS
-	bool "ARM Ltd. Versatile Express family"
-	select ARCH_WANT_OPTIONAL_GPIOLIB
-	select ARM_AMBA
-	select ARM_TIMER_SP804
-	select CLKDEV_LOOKUP
-	select COMMON_CLK
-	select GENERIC_CLOCKEVENTS
-	select HAVE_CLK
-	select HAVE_PATA_PLATFORM
-	select ICST
-	select NO_IOPORT
-	select PLAT_VERSATILE
-	select PLAT_VERSATILE_CLCD
-	select REGULATOR_FIXED_VOLTAGE if REGULATOR
-	help
-	  This enables support for the ARM Ltd Versatile Express boards.
-
 config ARCH_AT91
 	bool "Atmel AT91"
 	select ARCH_REQUIRE_GPIOLIB
 	select HAVE_CLK
 	select CLKDEV_LOOKUP
 	select IRQ_DOMAIN
+	select NEED_MACH_GPIO_H
 	select NEED_MACH_IO_H if PCCARD
 	help
 	  This enables support for systems based on Atmel
 	  AT91RM9200 and AT91SAM9* processors.
 
-config ARCH_BCMRING
-	bool "Broadcom BCMRING"
-	depends on MMU
-	select CPU_V6
+config ARCH_BCM2835
+	bool "Broadcom BCM2835 family"
+	select ARCH_WANT_OPTIONAL_GPIOLIB
 	select ARM_AMBA
+	select ARM_ERRATA_411920
 	select ARM_TIMER_SP804
 	select CLKDEV_LOOKUP
+	select COMMON_CLK
+	select CPU_V6
 	select GENERIC_CLOCKEVENTS
-	select ARCH_WANT_OPTIONAL_GPIOLIB
+	select MULTI_IRQ_HANDLER
+	select SPARSE_IRQ
+	select USE_OF
 	help
-	  Support for Broadcom's BCMRing platform.
+	  This enables support for the Broadcom BCM2835 SoC. This SoC is
+	  use in the Raspberry Pi, and Roku 2 devices.
 
-config ARCH_HIGHBANK
-	bool "Calxeda Highbank-based"
-	select ARCH_WANT_OPTIONAL_GPIOLIB
+config ARCH_BCMRING
+	bool "Broadcom BCMRING"
+	depends on MMU
+	select CPU_V6
 	select ARM_AMBA
-	select ARM_GIC
 	select ARM_TIMER_SP804
-	select CACHE_L2X0
 	select CLKDEV_LOOKUP
-	select COMMON_CLK
-	select CPU_V7
 	select GENERIC_CLOCKEVENTS
-	select HAVE_ARM_SCU
-	select HAVE_SMP
-	select SPARSE_IRQ
-	select USE_OF
+	select ARCH_WANT_OPTIONAL_GPIOLIB
 	help
-	  Support for the Calxeda Highbank SoC based boards.
+	  Support for Broadcom's BCMRing platform.
 
 config ARCH_CLPS711X
 	bool "Cirrus Logic CLPS711x/EP721x/EP731x-based"
@@ -407,21 +388,19 @@ config ARCH_GEMINI
 	help
 	  Support for the Cortina Systems Gemini family SoCs
 
-config ARCH_PRIMA2
-	bool "CSR SiRFSoC PRIMA2 ARM Cortex A9 Platform"
-	select CPU_V7
+config ARCH_SIRF
+	bool "CSR SiRF"
 	select NO_IOPORT
 	select ARCH_REQUIRE_GPIOLIB
 	select GENERIC_CLOCKEVENTS
-	select CLKDEV_LOOKUP
+	select COMMON_CLK
 	select GENERIC_IRQ_CHIP
 	select MIGHT_HAVE_CACHE_L2X0
 	select PINCTRL
 	select PINCTRL_SIRF
 	select USE_OF
-	select ZONE_DMA
 	help
-          Support for CSR SiRFSoC ARM Cortex A9 Platform
+	  Support for CSR SiRFprimaII/Marco/Polo platforms
 
 config ARCH_EBSA110
 	bool "EBSA-110"
@@ -456,7 +435,7 @@ config ARCH_FOOTBRIDGE
 	select FOOTBRIDGE
 	select GENERIC_CLOCKEVENTS
 	select HAVE_IDE
-	select NEED_MACH_IO_H
+	select NEED_MACH_IO_H if !MMU
 	select NEED_MACH_MEMORY_H
 	help
 	  Support for systems based on the DC21285 companion chip
@@ -483,7 +462,9 @@ config ARCH_MXS
 	select CLKSRC_MMIO
 	select COMMON_CLK
 	select HAVE_CLK_PREPARE
+	select MULTI_IRQ_HANDLER
 	select PINCTRL
+	select SPARSE_IRQ
 	select USE_OF
 	help
 	  Support for Freescale MXS-based family of processors
@@ -513,7 +494,6 @@ config ARCH_IOP13XX
 	select PCI
 	select ARCH_SUPPORTS_MSI
 	select VMSPLIT_1G
-	select NEED_MACH_IO_H
 	select NEED_MACH_MEMORY_H
 	select NEED_RET_TO_USER
 	help
@@ -523,7 +503,7 @@ config ARCH_IOP32X
 	bool "IOP32x-based"
 	depends on MMU
 	select CPU_XSCALE
-	select NEED_MACH_IO_H
+	select NEED_MACH_GPIO_H
 	select NEED_RET_TO_USER
 	select PLAT_IOP
 	select PCI
@@ -536,7 +516,7 @@ config ARCH_IOP33X
 	bool "IOP33x-based"
 	depends on MMU
 	select CPU_XSCALE
-	select NEED_MACH_IO_H
+	select NEED_MACH_GPIO_H
 	select NEED_RET_TO_USER
 	select PLAT_IOP
 	select PCI
@@ -558,26 +538,14 @@ config ARCH_IXP4XX
 	help
 	  Support for Intel's IXP4XX (XScale) family of processors.
 
-config ARCH_MVEBU
-	bool "Marvell SOCs with Device Tree support"
-	select GENERIC_CLOCKEVENTS
-	select MULTI_IRQ_HANDLER
-	select SPARSE_IRQ
-	select CLKSRC_MMIO
-	select GENERIC_IRQ_CHIP
-	select IRQ_DOMAIN
-	select COMMON_CLK
-	help
-	  Support for the Marvell SoC Family with device tree support
-
 config ARCH_DOVE
 	bool "Marvell Dove"
 	select CPU_V7
-	select PCI
 	select ARCH_REQUIRE_GPIOLIB
 	select GENERIC_CLOCKEVENTS
-	select NEED_MACH_IO_H
-	select PLAT_ORION
+	select MIGHT_HAVE_PCI
+	select PLAT_ORION_LEGACY
+	select USB_ARCH_HAS_EHCI
 	help
 	  Support for the Marvell Dove SoC 88AP510
 
@@ -587,8 +555,7 @@ config ARCH_KIRKWOOD
 	select PCI
 	select ARCH_REQUIRE_GPIOLIB
 	select GENERIC_CLOCKEVENTS
-	select NEED_MACH_IO_H
-	select PLAT_ORION
+	select PLAT_ORION_LEGACY
 	help
 	  Support for the following Marvell Kirkwood series SoCs:
 	  88F6180, 88F6192 and 88F6281.
@@ -614,8 +581,7 @@ config ARCH_MV78XX0
 	select PCI
 	select ARCH_REQUIRE_GPIOLIB
 	select GENERIC_CLOCKEVENTS
-	select NEED_MACH_IO_H
-	select PLAT_ORION
+	select PLAT_ORION_LEGACY
 	help
 	  Support for the following Marvell MV78xx0 series SoCs:
 	  MV781x0, MV782x0.
@@ -627,8 +593,7 @@ config ARCH_ORION5X
 	select PCI
 	select ARCH_REQUIRE_GPIOLIB
 	select GENERIC_CLOCKEVENTS
-	select NEED_MACH_IO_H
-	select PLAT_ORION
+	select PLAT_ORION_LEGACY
 	help
 	  Support for the following Marvell Orion 5x series SoCs:
 	  Orion-1 (5181), Orion-VoIP (5181L), Orion-NAS (5182),
@@ -645,6 +610,7 @@ config ARCH_MMP
 	select PLAT_PXA
 	select SPARSE_IRQ
 	select GENERIC_ALLOCATOR
+	select NEED_MACH_GPIO_H
 	help
 	  Support for Marvell's PXA168/PXA910(MMP) and MMP2 processor line.
 
@@ -652,8 +618,9 @@ config ARCH_KS8695
 	bool "Micrel/Kendin KS8695"
 	select CPU_ARM922T
 	select ARCH_REQUIRE_GPIOLIB
-	select ARCH_USES_GETTIMEOFFSET
 	select NEED_MACH_MEMORY_H
+	select CLKSRC_MMIO
+	select GENERIC_CLOCKEVENTS
 	help
 	  Support for Micrel/Kendin KS8695 "Centaur" (ARM922T) based
 	  System-on-Chip devices.
@@ -683,40 +650,13 @@ config ARCH_TEGRA
 	select HAVE_CLK
 	select HAVE_SMP
 	select MIGHT_HAVE_CACHE_L2X0
-	select NEED_MACH_IO_H if PCI
 	select ARCH_HAS_CPUFREQ
 	select USE_OF
+	select COMMON_CLK
 	help
 	  This enables support for NVIDIA Tegra based systems (Tegra APX,
 	  Tegra 6xx and Tegra 2 series).
 
-config ARCH_PICOXCELL
-	bool "Picochip picoXcell"
-	select ARCH_REQUIRE_GPIOLIB
-	select ARM_PATCH_PHYS_VIRT
-	select ARM_VIC
-	select CPU_V6K
-	select DW_APB_TIMER
-	select DW_APB_TIMER_OF
-	select GENERIC_CLOCKEVENTS
-	select GENERIC_GPIO
-	select HAVE_TCM
-	select NO_IOPORT
-	select SPARSE_IRQ
-	select USE_OF
-	help
-	  This enables support for systems based on the Picochip picoXcell
-	  family of Femtocell devices.  The picoxcell support requires device tree
-	  for all boards.
-
-config ARCH_PNX4008
-	bool "Philips Nexperia PNX4008 Mobile"
-	select CPU_ARM926T
-	select CLKDEV_LOOKUP
-	select ARCH_USES_GETTIMEOFFSET
-	help
-	  This enables support for Philips PNX4008 mobile platform.
-
 config ARCH_PXA
 	bool "PXA2xx/PXA3xx-based"
 	depends on MMU
@@ -733,6 +673,7 @@ config ARCH_PXA
 	select MULTI_IRQ_HANDLER
 	select ARM_CPU_SUSPEND if PM
 	select HAVE_IDE
+	select NEED_MACH_GPIO_H
 	help
 	  Support for Intel/Marvell's PXA2xx/PXA3xx processor line.
 
@@ -795,6 +736,7 @@ config ARCH_SA1100
 	select CLKDEV_LOOKUP
 	select ARCH_REQUIRE_GPIOLIB
 	select HAVE_IDE
+	select NEED_MACH_GPIO_H
 	select NEED_MACH_MEMORY_H
 	select SPARSE_IRQ
 	help
@@ -810,6 +752,7 @@ config ARCH_S3C24XX
 	select HAVE_S3C2410_I2C if I2C
 	select HAVE_S3C_RTC if RTC_CLASS
 	select HAVE_S3C2410_WATCHDOG if WATCHDOG
+	select NEED_MACH_GPIO_H
 	select NEED_MACH_IO_H
 	help
 	  Samsung S3C2410, S3C2412, S3C2413, S3C2416, S3C2440, S3C2442, S3C2443
@@ -837,6 +780,7 @@ config ARCH_S3C64XX
 	select SAMSUNG_GPIOLIB_4BIT
 	select HAVE_S3C2410_I2C if I2C
 	select HAVE_S3C2410_WATCHDOG if WATCHDOG
+	select NEED_MACH_GPIO_H
 	help
 	  Samsung S3C64XX series based systems
 
@@ -851,6 +795,7 @@ config ARCH_S5P64X0
 	select GENERIC_CLOCKEVENTS
 	select HAVE_S3C2410_I2C if I2C
 	select HAVE_S3C_RTC if RTC_CLASS
+	select NEED_MACH_GPIO_H
 	help
 	  Samsung S5P64X0 CPU based systems, such as the Samsung SMDK6440,
 	  SMDK6450.
@@ -865,6 +810,7 @@ config ARCH_S5PC100
 	select HAVE_S3C2410_I2C if I2C
 	select HAVE_S3C_RTC if RTC_CLASS
 	select HAVE_S3C2410_WATCHDOG if WATCHDOG
+	select NEED_MACH_GPIO_H
 	help
 	  Samsung S5PC100 series based systems
 
@@ -882,6 +828,7 @@ config ARCH_S5PV210
 	select HAVE_S3C2410_I2C if I2C
 	select HAVE_S3C_RTC if RTC_CLASS
 	select HAVE_S3C2410_WATCHDOG if WATCHDOG
+	select NEED_MACH_GPIO_H
 	select NEED_MACH_MEMORY_H
 	help
 	  Samsung S5PV210/S5PC110 series based systems
@@ -899,6 +846,7 @@ config ARCH_EXYNOS
 	select HAVE_S3C_RTC if RTC_CLASS
 	select HAVE_S3C2410_I2C if I2C
 	select HAVE_S3C2410_WATCHDOG if WATCHDOG
+	select NEED_MACH_GPIO_H
 	select NEED_MACH_MEMORY_H
 	help
 	  Support for SAMSUNG's EXYNOS SoCs (EXYNOS4/5)
@@ -912,7 +860,6 @@ config ARCH_SHARK
 	select PCI
 	select ARCH_USES_GETTIMEOFFSET
 	select NEED_MACH_MEMORY_H
-	select NEED_MACH_IO_H
 	help
 	  Support for the StrongARM based Digital DNARD machine, also known
 	  as "Shark" (<http://www.shark-linux.de/shark.html>).
@@ -931,6 +878,7 @@ config ARCH_U300
 	select COMMON_CLK
 	select GENERIC_GPIO
 	select ARCH_REQUIRE_GPIOLIB
+	select SPARSE_IRQ
 	help
 	  Support for ST-Ericsson U300 series mobile platforms.
 
@@ -956,6 +904,7 @@ config ARCH_NOMADIK
 	select COMMON_CLK
 	select GENERIC_CLOCKEVENTS
 	select PINCTRL
+	select PINCTRL_STN8815
 	select MIGHT_HAVE_CACHE_L2X0
 	select ARCH_REQUIRE_GPIOLIB
 	help
@@ -971,6 +920,7 @@ config ARCH_DAVINCI
 	select GENERIC_ALLOCATOR
 	select GENERIC_IRQ_CHIP
 	select ARCH_HAS_HOLES_MEMORYMODEL
+	select NEED_MACH_GPIO_H
 	help
 	  Support for TI's DaVinci platform.
 
@@ -983,6 +933,7 @@ config ARCH_OMAP
 	select CLKSRC_MMIO
 	select GENERIC_CLOCKEVENTS
 	select ARCH_HAS_HOLES_MEMORYMODEL
+	select NEED_MACH_GPIO_H
 	help
 	  Support for TI's OMAP platform (OMAP1/2/3/4).
 
@@ -1005,6 +956,10 @@ config ARCH_VT8500
 	select ARCH_HAS_CPUFREQ
 	select GENERIC_CLOCKEVENTS
 	select ARCH_REQUIRE_GPIOLIB
+	select USE_OF
+	select COMMON_CLK
+	select HAVE_CLK
+	select CLKDEV_LOOKUP
 	help
 	  Support for VIA/WonderMedia VT8500/WM85xx System-on-Chip.
 
@@ -1022,6 +977,50 @@ config ARCH_ZYNQ
 	  Support for Xilinx Zynq ARM Cortex A9 Platform
 endchoice
 
+menu "Multiple platform selection"
+	depends on ARCH_MULTIPLATFORM
+
+comment "CPU Core family selection"
+
+config ARCH_MULTI_V4
+	bool "ARMv4 based platforms (FA526, StrongARM)"
+	select ARCH_MULTI_V4_V5
+	depends on !ARCH_MULTI_V6_V7
+
+config ARCH_MULTI_V4T
+	bool "ARMv4T based platforms (ARM720T, ARM920T, ...)"
+	select ARCH_MULTI_V4_V5
+	depends on !ARCH_MULTI_V6_V7
+
+config ARCH_MULTI_V5
+	bool "ARMv5 based platforms (ARM926T, XSCALE, PJ1, ...)"
+	select ARCH_MULTI_V4_V5
+	depends on !ARCH_MULTI_V6_V7
+
+config ARCH_MULTI_V4_V5
+	bool
+
+config ARCH_MULTI_V6
+	bool "ARMv6 based platforms (ARM11, Scorpion, ...)"
+	select CPU_V6
+	select ARCH_MULTI_V6_V7
+
+config ARCH_MULTI_V7
+	bool "ARMv7 based platforms (Cortex-A, PJ4, Krait)"
+	select CPU_V7
+	select ARCH_VEXPRESS
+	default y
+	select ARCH_MULTI_V6_V7
+
+config ARCH_MULTI_V6_V7
+	bool
+
+config ARCH_MULTI_CPU_AUTO
+	def_bool !(ARCH_MULTI_V4 || ARCH_MULTI_V4T || ARCH_MULTI_V6_V7)
+	select ARCH_MULTI_V5
+
+endmenu
+
 #
 # This is sorted alphabetically by mach-* pathname.  However, plat-*
 # Kconfigs may be included either alphabetically (according to the
@@ -1049,6 +1048,8 @@ source "arch/arm/mach-gemini/Kconfig"
 
 source "arch/arm/mach-h720x/Kconfig"
 
+source "arch/arm/mach-highbank/Kconfig"
+
 source "arch/arm/mach-integrator/Kconfig"
 
 source "arch/arm/mach-iop32x/Kconfig"
@@ -1084,6 +1085,8 @@ source "arch/arm/mach-omap2/Kconfig"
 
 source "arch/arm/mach-orion5x/Kconfig"
 
+source "arch/arm/mach-picoxcell/Kconfig"
+
 source "arch/arm/mach-pxa/Kconfig"
 source "arch/arm/plat-pxa/Kconfig"
 
@@ -1096,6 +1099,8 @@ source "arch/arm/mach-sa1100/Kconfig"
 source "arch/arm/plat-samsung/Kconfig"
 source "arch/arm/plat-s3c24xx/Kconfig"
 
+source "arch/arm/mach-socfpga/Kconfig"
+
 source "arch/arm/plat-spear/Kconfig"
 
 source "arch/arm/mach-s3c24xx/Kconfig"
@@ -1118,6 +1123,8 @@ source "arch/arm/mach-exynos/Kconfig"
 
 source "arch/arm/mach-shmobile/Kconfig"
 
+source "arch/arm/mach-prima2/Kconfig"
+
 source "arch/arm/mach-tegra/Kconfig"
 
 source "arch/arm/mach-u300/Kconfig"
@@ -1129,8 +1136,6 @@ source "arch/arm/mach-versatile/Kconfig"
 source "arch/arm/mach-vexpress/Kconfig"
 source "arch/arm/plat-versatile/Kconfig"
 
-source "arch/arm/mach-vt8500/Kconfig"
-
 source "arch/arm/mach-w90x900/Kconfig"
 
 # Definitions to make life easier
@@ -1148,6 +1153,10 @@ config PLAT_ORION
 	select IRQ_DOMAIN
 	select COMMON_CLK
 
+config PLAT_ORION_LEGACY
+	bool
+	select PLAT_ORION
+
 config PLAT_PXA
 	bool
 
@@ -1179,12 +1188,6 @@ config XSCALE_PMU
 	depends on CPU_XSCALE
 	default y
 
-config CPU_HAS_PMU
-	depends on (CPU_V6 || CPU_V6K || CPU_V7 || XSCALE_PMU) && \
-		   (!ARCH_OMAP3 || OMAP3_EMU)
-	default y
-	bool
-
 config MULTI_IRQ_HANDLER
 	bool
 	help
@@ -1413,6 +1416,25 @@ config PL310_ERRATA_769419
 	  on systems with an outer cache, the store buffer is drained
 	  explicitly.
 
+config ARM_ERRATA_775420
+       bool "ARM errata: A data cache maintenance operation which aborts, might lead to deadlock"
+       depends on CPU_V7
+       help
+	 This option enables the workaround for the 775420 Cortex-A9 (r2p2,
+	 r2p6,r2p8,r2p10,r3p0) erratum. In case a date cache maintenance
+	 operation aborts with MMU exception, it might cause the processor
+	 to deadlock. This workaround puts DSB before executing ISB if
+	 an abort may occur on cache maintenance.
+
+config ARM_ERRATA_782773
+	bool "ARM errata: Updating a translation entry might cause an unexpected translation fault"
+	depends on CPU_V7
+	help
+	  This option enables the workaround for the 782773 Cortex-A9 (all r0,
+	  r2 and r3 revisions) erratum. It might cause MMU exception in case
+	  page table walk happens just after updating the existing
+	  with setting page table in L1 data cache.
+
 endmenu
 
 source "arch/arm/common/Kconfig"
@@ -1623,6 +1645,7 @@ config ARCH_NR_GPIO
 	default 355 if ARCH_U8500
 	default 264 if MACH_H4700
 	default 512 if SOC_OMAP5
+	default 288 if ARCH_VT8500
 	default 0
 	help
 	  Maximum number of GPIOs in the system.
@@ -1757,7 +1780,7 @@ config HIGHPTE
 
 config HW_PERF_EVENTS
 	bool "Enable hardware performance counter support for perf events"
-	depends on PERF_EVENTS && CPU_HAS_PMU
+	depends on PERF_EVENTS
 	default y
 	help
 	  Enable hardware performance counter support for perf events. If
@@ -1781,59 +1804,6 @@ config FORCE_MAX_ZONEORDER
 	  This config option is actually maximum order plus one. For example,
 	  a value of 11 means that the largest free memory block is 2^10 pages.
 
-config LEDS
-	bool "Timer and CPU usage LEDs"
-	depends on ARCH_CDB89712 || ARCH_EBSA110 || \
-		   ARCH_EBSA285 || ARCH_INTEGRATOR || \
-		   ARCH_LUBBOCK || MACH_MAINSTONE || ARCH_NETWINDER || \
-		   ARCH_OMAP || ARCH_P720T || ARCH_PXA_IDP || \
-		   ARCH_SA1100 || ARCH_SHARK || ARCH_VERSATILE || \
-		   ARCH_AT91 || ARCH_DAVINCI || \
-		   ARCH_KS8695 || MACH_RD88F5182 || ARCH_REALVIEW
-	help
-	  If you say Y here, the LEDs on your machine will be used
-	  to provide useful information about your current system status.
-
-	  If you are compiling a kernel for a NetWinder or EBSA-285, you will
-	  be able to select which LEDs are active using the options below. If
-	  you are compiling a kernel for the EBSA-110 or the LART however, the
-	  red LED will simply flash regularly to indicate that the system is
-	  still functional. It is safe to say Y here if you have a CATS
-	  system, but the driver will do nothing.
-
-config LEDS_TIMER
-	bool "Timer LED" if (!ARCH_CDB89712 && !ARCH_OMAP) || \
-			    OMAP_OSK_MISTRAL || MACH_OMAP_H2 \
-			    || MACH_OMAP_PERSEUS2
-	depends on LEDS
-	depends on !GENERIC_CLOCKEVENTS
-	default y if ARCH_EBSA110
-	help
-	  If you say Y here, one of the system LEDs (the green one on the
-	  NetWinder, the amber one on the EBSA285, or the red one on the LART)
-	  will flash regularly to indicate that the system is still
-	  operational. This is mainly useful to kernel hackers who are
-	  debugging unstable kernels.
-
-	  The LART uses the same LED for both Timer LED and CPU usage LED
-	  functions. You may choose to use both, but the Timer LED function
-	  will overrule the CPU usage LED.
-
-config LEDS_CPU
-	bool "CPU usage LED" if (!ARCH_CDB89712 && !ARCH_EBSA110 && \
-			!ARCH_OMAP) \
-			|| OMAP_OSK_MISTRAL || MACH_OMAP_H2 \
-			|| MACH_OMAP_PERSEUS2
-	depends on LEDS
-	help
-	  If you say Y here, the red LED will be used to give a good real
-	  time indication of CPU usage, by lighting whenever the idle task
-	  is not currently executing.
-
-	  The LART uses the same LED for both Timer LED and CPU usage LED
-	  functions. You may choose to use both, but the Timer LED function
-	  will overrule the CPU usage LED.
-
 config ALIGNMENT_TRAP
 	bool
 	depends on CPU_CP15_MMU
@@ -1849,8 +1819,8 @@ config ALIGNMENT_TRAP
 	  configuration it is safe to say N, otherwise say Y.
 
 config UACCESS_WITH_MEMCPY
-	bool "Use kernel mem{cpy,set}() for {copy_to,clear}_user() (EXPERIMENTAL)"
-	depends on MMU && EXPERIMENTAL
+	bool "Use kernel mem{cpy,set}() for {copy_to,clear}_user()"
+	depends on MMU
 	default y if CPU_FEROCEON
 	help
 	  Implement faster copy_to_user and clear_user methods for CPU
@@ -1891,12 +1861,6 @@ config CC_STACKPROTECTOR
 	  neutralized via a kernel panic.
 	  This feature requires gcc version 4.2 or above.
 
-config DEPRECATED_PARAM_STRUCT
-	bool "Provide old way to pass kernel parameters"
-	help
-	  This was deprecated in 2001 and announced to live on for 5 years.
-	  Some old boot loaders still use this way.
-
 endmenu
 
 menu "Boot options"
@@ -1909,6 +1873,23 @@ config USE_OF
 	help
 	  Include support for flattened device tree machine descriptions.
 
+config ATAGS
+	bool "Support for the traditional ATAGS boot data passing" if USE_OF
+	default y
+	help
+	  This is the traditional way of passing data to the kernel at boot
+	  time. If you are solely relying on the flattened device tree (or
+	  the ARM_ATAG_DTB_COMPAT option) then you may unselect this option
+	  to remove ATAGS support from your kernel binary.  If unsure,
+	  leave this to y.
+
+config DEPRECATED_PARAM_STRUCT
+	bool "Provide old way to pass kernel parameters"
+	depends on ATAGS
+	help
+	  This was deprecated in 2001 and announced to live on for 5 years.
+	  Some old boot loaders still use this way.
+
 # Compressed boot loader in ROM.  Yes, we really want to ask about
 # TEXT and BSS so we preserve their values in the config files.
 config ZBOOT_ROM_TEXT
@@ -2035,6 +2016,7 @@ config CMDLINE
 choice
 	prompt "Kernel command line type" if CMDLINE != ""
 	default CMDLINE_FROM_BOOTLOADER
+	depends on ATAGS
 
 config CMDLINE_FROM_BOOTLOADER
 	bool "Use bootloader kernel arguments if available"
@@ -2060,7 +2042,7 @@ endchoice
 
 config XIP_KERNEL
 	bool "Kernel Execute-In-Place from ROM"
-	depends on !ZBOOT_ROM && !ARM_LPAE
+	depends on !ZBOOT_ROM && !ARM_LPAE && !ARCH_MULTIPLATFORM
 	help
 	  Execute-In-Place allows the kernel to run from non-volatile storage
 	  directly addressable by the CPU, such as NOR flash. This saves RAM
@@ -2104,7 +2086,7 @@ config KEXEC
 
 config ATAGS_PROC
 	bool "Export atags in procfs"
-	depends on KEXEC
+	depends on ATAGS && KEXEC
 	default y
 	help
 	  Should the atags used to boot the kernel be exported in an "atags"
@@ -2313,7 +2295,7 @@ menu "Power management options"
 source "kernel/power/Kconfig"
 
 config ARCH_SUSPEND_POSSIBLE
-	depends on !ARCH_S5PC100 && !ARCH_TEGRA
+	depends on !ARCH_S5PC100
 	depends on CPU_ARM920T || CPU_ARM926T || CPU_SA1100 || \
 		CPU_V6 || CPU_V6K || CPU_V7 || CPU_XSC3 || CPU_XSCALE || CPU_MOHAWK
 	def_bool y
diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index e968a52..b0f3857 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -224,6 +224,20 @@ choice
 		  Say Y here if you want kernel low-level debugging support
 		  on i.MX6Q UART4.
 
+	config DEBUG_MMP_UART2
+		bool "Kernel low-level debugging message via MMP UART2"
+		depends on ARCH_MMP
+		help
+		  Say Y here if you want kernel low-level debugging support
+		  on MMP UART2.
+
+	config DEBUG_MMP_UART3
+		bool "Kernel low-level debugging message via MMP UART3"
+		depends on ARCH_MMP
+		help
+		  Say Y here if you want kernel low-level debugging support
+		  on MMP UART3.
+
 	config DEBUG_MSM_UART1
 		bool "Kernel low-level debugging messages via MSM UART1"
 		depends on ARCH_MSM7X00A || ARCH_MSM7X30 || ARCH_QSD8X50
@@ -261,6 +275,20 @@ choice
 		  Say Y here if you want the debug print routines to direct
 		  their output to the serial port on MSM 8960 devices.
 
+	config DEBUG_MVEBU_UART
+		bool "Kernel low-level debugging messages via MVEBU UART"
+		depends on ARCH_MVEBU
+		help
+		  Say Y here if you want kernel low-level debugging support
+		  on MVEBU based platforms.
+
+	config DEBUG_PICOXCELL_UART
+		depends on ARCH_PICOXCELL
+		bool "Use PicoXcell UART for low-level debug"
+		help
+		  Say Y here if you want kernel low-level debugging support
+		  on PicoXcell based platforms.
+
 	config DEBUG_REALVIEW_STD_PORT
 		bool "RealView Default UART"
 		depends on ARCH_REALVIEW
@@ -310,6 +338,13 @@ choice
 		  The uncompressor code port configuration is now handled
 		  by CONFIG_S3C_LOWLEVEL_UART_PORT.
 
+	config DEBUG_SOCFPGA_UART
+		depends on ARCH_SOCFPGA
+		bool "Use SOCFPGA UART for low-level debug"
+		help
+		  Say Y here if you want kernel low-level debugging support
+		  on SOCFPGA based platforms.
+
 	config DEBUG_VEXPRESS_UART0_DETECT
 		bool "Autodetect UART0 on Versatile Express Cortex-A core tiles"
 		depends on ARCH_VEXPRESS && CPU_CP15_MMU
@@ -338,6 +373,7 @@ choice
 
 	config DEBUG_LL_UART_NONE
 		bool "No low-level debugging UART"
+		depends on !ARCH_MULTIPLATFORM
 		help
 		  Say Y here if your platform doesn't provide a UART option
 		  below. This relies on your platform choosing the right UART
@@ -373,6 +409,17 @@ choice
 
 endchoice
 
+config DEBUG_LL_INCLUDE
+	string
+	default "debug/icedcc.S" if DEBUG_ICEDCC
+	default "debug/highbank.S" if DEBUG_HIGHBANK_UART
+	default "debug/mvebu.S" if DEBUG_MVEBU_UART
+	default "debug/picoxcell.S" if DEBUG_PICOXCELL_UART
+	default "debug/socfpga.S" if DEBUG_SOCFPGA_UART
+	default "debug/vexpress.S" if DEBUG_VEXPRESS_UART0_DETECT || \
+		DEBUG_VEXPRESS_UART0_CA9 || DEBUG_VEXPRESS_UART0_RS1
+	default "mach/debug-macro.S"
+
 config EARLY_PRINTK
 	bool "Early printk"
 	depends on DEBUG_LL
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index a051dfb..b396706 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -135,84 +135,79 @@ textofs-$(CONFIG_ARCH_MSM8960) := 0x00208000
 
 # Machine directory name.  This list is sorted alphanumerically
 # by CONFIG_* macro name.
-machine-$(CONFIG_ARCH_AT91)		:= at91
-machine-$(CONFIG_ARCH_BCMRING)		:= bcmring
-machine-$(CONFIG_ARCH_CLPS711X)		:= clps711x
-machine-$(CONFIG_ARCH_CNS3XXX)		:= cns3xxx
-machine-$(CONFIG_ARCH_DAVINCI)		:= davinci
-machine-$(CONFIG_ARCH_DOVE)		:= dove
-machine-$(CONFIG_ARCH_EBSA110)		:= ebsa110
-machine-$(CONFIG_ARCH_EP93XX)		:= ep93xx
-machine-$(CONFIG_ARCH_GEMINI)		:= gemini
-machine-$(CONFIG_ARCH_H720X)		:= h720x
-machine-$(CONFIG_ARCH_HIGHBANK)		:= highbank
-machine-$(CONFIG_ARCH_INTEGRATOR)	:= integrator
-machine-$(CONFIG_ARCH_IOP13XX)		:= iop13xx
-machine-$(CONFIG_ARCH_IOP32X)		:= iop32x
-machine-$(CONFIG_ARCH_IOP33X)		:= iop33x
-machine-$(CONFIG_ARCH_IXP4XX)		:= ixp4xx
-machine-$(CONFIG_ARCH_KIRKWOOD)		:= kirkwood
-machine-$(CONFIG_ARCH_KS8695)		:= ks8695
-machine-$(CONFIG_ARCH_LPC32XX)		:= lpc32xx
-machine-$(CONFIG_ARCH_MMP)		:= mmp
-machine-$(CONFIG_ARCH_MSM)		:= msm
-machine-$(CONFIG_ARCH_MV78XX0)		:= mv78xx0
-machine-$(CONFIG_ARCH_IMX_V4_V5)	:= imx
-machine-$(CONFIG_ARCH_IMX_V6_V7)	:= imx
-machine-$(CONFIG_ARCH_MXS)		:= mxs
-machine-$(CONFIG_ARCH_MVEBU)		:= mvebu
-machine-$(CONFIG_ARCH_NETX)		:= netx
-machine-$(CONFIG_ARCH_NOMADIK)		:= nomadik
-machine-$(CONFIG_ARCH_OMAP1)		:= omap1
-machine-$(CONFIG_ARCH_OMAP2PLUS)	:= omap2
-machine-$(CONFIG_ARCH_ORION5X)		:= orion5x
-machine-$(CONFIG_ARCH_PICOXCELL)	:= picoxcell
-machine-$(CONFIG_ARCH_PNX4008)		:= pnx4008
-machine-$(CONFIG_ARCH_PRIMA2)		:= prima2
-machine-$(CONFIG_ARCH_PXA)		:= pxa
-machine-$(CONFIG_ARCH_REALVIEW)		:= realview
-machine-$(CONFIG_ARCH_RPC)		:= rpc
-machine-$(CONFIG_ARCH_S3C24XX)		:= s3c24xx s3c2412 s3c2440
-machine-$(CONFIG_ARCH_S3C64XX)		:= s3c64xx
-machine-$(CONFIG_ARCH_S5P64X0)		:= s5p64x0
-machine-$(CONFIG_ARCH_S5PC100)		:= s5pc100
-machine-$(CONFIG_ARCH_S5PV210)		:= s5pv210
-machine-$(CONFIG_ARCH_EXYNOS4)		:= exynos
-machine-$(CONFIG_ARCH_EXYNOS5)		:= exynos
-machine-$(CONFIG_ARCH_SA1100)		:= sa1100
-machine-$(CONFIG_ARCH_SHARK)		:= shark
-machine-$(CONFIG_ARCH_SHMOBILE) 	:= shmobile
-machine-$(CONFIG_ARCH_TEGRA)		:= tegra
-machine-$(CONFIG_ARCH_U300)		:= u300
-machine-$(CONFIG_ARCH_U8500)		:= ux500
-machine-$(CONFIG_ARCH_VERSATILE)	:= versatile
-machine-$(CONFIG_ARCH_VEXPRESS)		:= vexpress
-machine-$(CONFIG_ARCH_VT8500)		:= vt8500
-machine-$(CONFIG_ARCH_W90X900)		:= w90x900
-machine-$(CONFIG_FOOTBRIDGE)		:= footbridge
-machine-$(CONFIG_ARCH_SOCFPGA)		:= socfpga
-machine-$(CONFIG_MACH_SPEAR1310)	:= spear13xx
-machine-$(CONFIG_MACH_SPEAR1340)	:= spear13xx
-machine-$(CONFIG_MACH_SPEAR300)		:= spear3xx
-machine-$(CONFIG_MACH_SPEAR310)		:= spear3xx
-machine-$(CONFIG_MACH_SPEAR320)		:= spear3xx
-machine-$(CONFIG_MACH_SPEAR600)		:= spear6xx
-machine-$(CONFIG_ARCH_ZYNQ)		:= zynq
+machine-$(CONFIG_ARCH_AT91)		+= at91
+machine-$(CONFIG_ARCH_BCM2835)		+= bcm2835
+machine-$(CONFIG_ARCH_BCMRING)		+= bcmring
+machine-$(CONFIG_ARCH_CLPS711X)		+= clps711x
+machine-$(CONFIG_ARCH_CNS3XXX)		+= cns3xxx
+machine-$(CONFIG_ARCH_DAVINCI)		+= davinci
+machine-$(CONFIG_ARCH_DOVE)		+= dove
+machine-$(CONFIG_ARCH_EBSA110)		+= ebsa110
+machine-$(CONFIG_ARCH_EP93XX)		+= ep93xx
+machine-$(CONFIG_ARCH_GEMINI)		+= gemini
+machine-$(CONFIG_ARCH_H720X)		+= h720x
+machine-$(CONFIG_ARCH_HIGHBANK)		+= highbank
+machine-$(CONFIG_ARCH_INTEGRATOR)	+= integrator
+machine-$(CONFIG_ARCH_IOP13XX)		+= iop13xx
+machine-$(CONFIG_ARCH_IOP32X)		+= iop32x
+machine-$(CONFIG_ARCH_IOP33X)		+= iop33x
+machine-$(CONFIG_ARCH_IXP4XX)		+= ixp4xx
+machine-$(CONFIG_ARCH_KIRKWOOD)		+= kirkwood
+machine-$(CONFIG_ARCH_KS8695)		+= ks8695
+machine-$(CONFIG_ARCH_LPC32XX)		+= lpc32xx
+machine-$(CONFIG_ARCH_MMP)		+= mmp
+machine-$(CONFIG_ARCH_MSM)		+= msm
+machine-$(CONFIG_ARCH_MV78XX0)		+= mv78xx0
+machine-$(CONFIG_ARCH_MXC)		+= imx
+machine-$(CONFIG_ARCH_MXS)		+= mxs
+machine-$(CONFIG_ARCH_MVEBU)		+= mvebu
+machine-$(CONFIG_ARCH_NETX)		+= netx
+machine-$(CONFIG_ARCH_NOMADIK)		+= nomadik
+machine-$(CONFIG_ARCH_OMAP1)		+= omap1
+machine-$(CONFIG_ARCH_OMAP2PLUS)	+= omap2
+machine-$(CONFIG_ARCH_ORION5X)		+= orion5x
+machine-$(CONFIG_ARCH_PICOXCELL)	+= picoxcell
+machine-$(CONFIG_ARCH_PRIMA2)		+= prima2
+machine-$(CONFIG_ARCH_PXA)		+= pxa
+machine-$(CONFIG_ARCH_REALVIEW)		+= realview
+machine-$(CONFIG_ARCH_RPC)		+= rpc
+machine-$(CONFIG_ARCH_S3C24XX)		+= s3c24xx s3c2412 s3c2440
+machine-$(CONFIG_ARCH_S3C64XX)		+= s3c64xx
+machine-$(CONFIG_ARCH_S5P64X0)		+= s5p64x0
+machine-$(CONFIG_ARCH_S5PC100)		+= s5pc100
+machine-$(CONFIG_ARCH_S5PV210)		+= s5pv210
+machine-$(CONFIG_ARCH_EXYNOS)		+= exynos
+machine-$(CONFIG_ARCH_SA1100)		+= sa1100
+machine-$(CONFIG_ARCH_SHARK)		+= shark
+machine-$(CONFIG_ARCH_SHMOBILE) 	+= shmobile
+machine-$(CONFIG_ARCH_TEGRA)		+= tegra
+machine-$(CONFIG_ARCH_U300)		+= u300
+machine-$(CONFIG_ARCH_U8500)		+= ux500
+machine-$(CONFIG_ARCH_VERSATILE)	+= versatile
+machine-$(CONFIG_ARCH_VEXPRESS)		+= vexpress
+machine-$(CONFIG_ARCH_VT8500)		+= vt8500
+machine-$(CONFIG_ARCH_W90X900)		+= w90x900
+machine-$(CONFIG_FOOTBRIDGE)		+= footbridge
+machine-$(CONFIG_ARCH_SOCFPGA)		+= socfpga
+machine-$(CONFIG_ARCH_SPEAR13XX)	+= spear13xx
+machine-$(CONFIG_ARCH_SPEAR3XX)		+= spear3xx
+machine-$(CONFIG_MACH_SPEAR600)		+= spear6xx
+machine-$(CONFIG_ARCH_ZYNQ)		+= zynq
 
 # Platform directory name.  This list is sorted alphanumerically
 # by CONFIG_* macro name.
-plat-$(CONFIG_ARCH_MXC)		:= mxc
-plat-$(CONFIG_ARCH_OMAP)	:= omap
-plat-$(CONFIG_ARCH_S3C64XX)	:= samsung
-plat-$(CONFIG_ARCH_ZYNQ)	:= versatile
-plat-$(CONFIG_PLAT_IOP)		:= iop
-plat-$(CONFIG_PLAT_NOMADIK)	:= nomadik
-plat-$(CONFIG_PLAT_ORION)	:= orion
-plat-$(CONFIG_PLAT_PXA)		:= pxa
-plat-$(CONFIG_PLAT_S3C24XX)	:= s3c24xx samsung
-plat-$(CONFIG_PLAT_S5P)		:= samsung
-plat-$(CONFIG_PLAT_SPEAR)	:= spear
-plat-$(CONFIG_PLAT_VERSATILE)	:= versatile
+plat-$(CONFIG_ARCH_MXC)		+= mxc
+plat-$(CONFIG_ARCH_OMAP)	+= omap
+plat-$(CONFIG_ARCH_S3C64XX)	+= samsung
+plat-$(CONFIG_ARCH_ZYNQ)	+= versatile
+plat-$(CONFIG_PLAT_IOP)		+= iop
+plat-$(CONFIG_PLAT_NOMADIK)	+= nomadik
+plat-$(CONFIG_PLAT_ORION)	+= orion
+plat-$(CONFIG_PLAT_PXA)		+= pxa
+plat-$(CONFIG_PLAT_S3C24XX)	+= s3c24xx samsung
+plat-$(CONFIG_PLAT_S5P)		+= samsung
+plat-$(CONFIG_PLAT_SPEAR)	+= spear
+plat-$(CONFIG_PLAT_VERSATILE)	+= versatile
 
 ifeq ($(CONFIG_ARCH_EBSA110),y)
 # This is what happens if you forget the IOCS16 line.
@@ -230,15 +225,20 @@ MACHINE  := arch/arm/mach-$(word 1,$(machine-y))/
 else
 MACHINE  :=
 endif
+ifeq ($(CONFIG_ARCH_MULTIPLATFORM),y)
+MACHINE  :=
+endif
 
 machdirs := $(patsubst %,arch/arm/mach-%/,$(machine-y))
 platdirs := $(patsubst %,arch/arm/plat-%/,$(plat-y))
 
+ifneq ($(CONFIG_ARCH_MULTIPLATFORM),y)
 ifeq ($(KBUILD_SRC),)
 KBUILD_CPPFLAGS += $(patsubst %,-I%include,$(machdirs) $(platdirs))
 else
 KBUILD_CPPFLAGS += $(patsubst %,-I$(srctree)/%include,$(machdirs) $(platdirs))
 endif
+endif
 
 export	TEXT_OFFSET GZFLAGS MMUEXT
 
@@ -255,6 +255,7 @@ core-$(CONFIG_VFP)		+= arch/arm/vfp/
 # If we have a machine-specific directory, then include it in the build.
 core-y				+= arch/arm/kernel/ arch/arm/mm/ arch/arm/common/
 core-y				+= arch/arm/net/
+core-y				+= arch/arm/crypto/
 core-y				+= $(machdirs) $(platdirs)
 
 drivers-$(CONFIG_OPROFILE)      += arch/arm/oprofile/
@@ -268,7 +269,12 @@ else
 KBUILD_IMAGE := zImage
 endif
 
-all:	$(KBUILD_IMAGE)
+# Build the DT binary blobs if we have OF configured
+ifeq ($(CONFIG_USE_OF),y)
+KBUILD_DTBS := dtbs
+endif
+
+all:	$(KBUILD_IMAGE) $(KBUILD_DTBS)
 
 boot := arch/arm/boot
 
@@ -306,7 +312,7 @@ define archhelp
   echo  '  uImage        - U-Boot wrapped zImage'
   echo  '  bootpImage    - Combined zImage and initial RAM disk' 
   echo  '                  (supply initrd image via make variable INITRD=<path>)'
-  echo  '  dtbs          - Build device tree blobs for enabled boards'
+  echo  '* dtbs          - Build device tree blobs for enabled boards'
   echo  '  install       - Install uncompressed kernel'
   echo  '  zinstall      - Install compressed kernel'
   echo  '  uinstall      - Install U-Boot wrapped compressed kernel'
diff --git a/arch/arm/arm-soc-for-next-contents.txt b/arch/arm/arm-soc-for-next-contents.txt
new file mode 100644
index 0000000..89f0fde
--- /dev/null
+++ b/arch/arm/arm-soc-for-next-contents.txt
@@ -0,0 +1,155 @@
+This file lists all branches that are pulled into the for-next branch
+of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc.git
+and their external dependencies.
+
+It also includes a couple of directly applied patches for build breaks with subject
+The next/* branches are kept in the order in which they get applied.
+
+external dependencies:
+depends/clk-3.7	git://git.linaro.org/people/mturquette/linux.git clk-3.7
+depends/tps6589x-dt  git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator.git tps6589x-dt
+depends/tty-omap-serial git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty.git tty-next @ cdd86b277dc82220aa630414896505517a02a201
+depends/usb-xceiv	git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git xceiv-for-v3.7
+
+fixes:
+
+next/fixes-non-critical:
+ux500/fixes-non-critical http://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson.git tags/ux500-core-updates
+cleanup/of-deviceid-data git://git.pengutronix.de/git/ukl/linux ofdeviceiddata 
+				(pulled again on Sep 12)
+imx/fixes-non-critical	 git://git.pengutronix.de/git/imx/linux-2.6.git tags/imx-fixes
+msm/fixes-non-critical	 git://git.kernel.org/pub/scm/linux/kernel/git/davidb/linux-msm.git tags/msm-fix-noncrit-for-3.7
+tegra/fixes-non-critical git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-tegra.git tegra-for-3.7-fixes
+omap/fixes-non-critical   git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap tags/omap-fixes-noncritical-for-v3.7
+samsung/fixes-non-critical git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git v3.7-samsung-fixes-1
+pxa/fixes		git://github.com/hzhuang1/linux.git fixes
+
+next/cleanup:
+cleanup/io-pci:   git://sources.calxeda.com/kernel/linux.git io-cleanup-pci-v2
+bcmring/cleanup:  patches from Arnd
+u300/cleanup	  git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson.git u300-cleanup
+csr/marco-prepare git://gitorious.org/sirfprima2-kernel/sirfprima2-kernel.git marco-prepare
+			(includes two patches from clk-next that adds prima2 clocks)
+pmu/cleanup       git://git.kernel.org/pub/scm/linux/kernel/git/will/linux.git tags/arm-perf-3.7
+ks8695/timer      http://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson.git tags/ks8695-time-for-arm-soc
+			+ http://marc.info/?l=linux-arm-kernel&m=134734253519144
+renesas/ag5evm    git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git ag5evm
+nxp4008/removal   git://git.antcom.de/linux-2.6.git pnx4008-removal
+pxa/clk		  git://github.com/hzhuang1/linux.git clk
+imx/cleanup	  git://git.pengutronix.de/git/imx/linux-2.6.git tags/imx-cleanup
+msm/cleanup	  git://git.kernel.org/pub/scm/linux/kernel/git/davidb/linux-msm.git tags/msm-cleanup-for-3.7
+tegra/cleanup	  git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-tegra.git tegra-for-3.7-cleanup
+tegra/board-removal git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-tegra.git tegra-for-3.7-board-removal
+		+patch for omap platform-data headers from Arnd
+samsung/cleanup   git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git next/cleanup-samsung
+			depends on depends/tps6589x-dt
+omap/gpmc-cleanup   git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap tags/omap-devel-gpmc-fixed-for-v3.7
+omap/atag-cleanup   git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap tags/cleanup-omap-tags-for-v3.7
+omap/cleanup-sparseirq git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap tags/omap-cleanup-sparseirq-for-v3.7
+			depends on depends/tty-omap-serial
+omap/cleanup-makefile-sparse git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap tags/omap-cleanup-makefile-sparse-for-v3.7
+omap/cleanup-fixes     git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap tags/cleanup-fixes-for-v3.7
+(email)			message-id = 1348176039-6094-1-git-send-email-swarren@wwwdotorg.org
+tegra/dmaengine-removal git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-tegra.git tegra-for-3.7-dmaengine
+omap/cleanup-headers	git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap tags/omap-cleanup-local-headers-for-v3.7
+pxa/cleanup	  git://github.com/hzhuang1/linux.git board
+
+next/maintainers:
+[email]		  Entry for ks8695 from Arnd
+tegra/maintainers git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-tegra.git tegra-for-3.7-maintainers
+
+next/soc:
+ux500/asic-id:	git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson.git ux500-core
+		 + http://marc.info/?l=linux-arm-kernel&m=134667789927502
+renesas/kzm9g   git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git kzm9g
+lpc32xx/core	git://git.antcom.de/linux-2.6.git lpc32xx/core
+renesas/soc	git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git soc
+renesas/pmu	git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git pmu/cleanup
+			depends on pmu/cleanup (next/cleanup)
+imx/soc		git://git.pengutronix.de/git/imx/linux-2.6.git tags/imx-soc
+tegra/common-clk git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-tegra.git tegra-for-3.7-common-clk
+tegra/cpu-hotplug git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-tegra.git tegra-for-3.7-cpu-hotplug
+omap/omap-device git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap tags/devel-omap-device-for-v3.7
+omap/am33xx	git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap tags/omap-devel-am33xx-for-v3.7
+			depends on omap cleanup branches
+bcm2835/soc	git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-tegra.git rpi-for-3.7
+			+ Message-Id: <1348506174-28641-1-git-send-email-swarren@wwwdotorg.org>
+samsung/devel	git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git next/devel-samsung
+
+next/dt:
+pxa/dt:		git://github.com/hzhuang1/linux.git dt
+renesas/soc-core git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git soc-core
+csr/pinmux-dt   git://gitorious.org/sirfprima2-kernel/sirfprima2-kernel.git pinmux-dt
+lpc32xx/dts	git://git.antcom.de/linux-2.6.git lpc32xx/dts
+mxs/dt		git://git.linaro.org/people/shawnguo/linux-2.6.git tags/mxs-dt-3.7
+depends/clk-3.7	git://git.linaro.org/people/mturquette/linux.git clk-3.7
+			-> this is a prereq for mxs/clk-dt-lookup below
+mxs/clk-dt-lookup	git://git.linaro.org/people/shawnguo/linux-2.6.git tags/mxs-clk-dt-lookup
+imx/dt		git://git.linaro.org/people/shawnguo/linux-2.6.git tags/imx-dt-3.7
+imx/clk-dt-lookup	git://git.linaro.org/people/shawnguo/linux-2.6.git tags/imx-clk-dt-lookup
+msm/dt		git://git.kernel.org/pub/scm/linux/kernel/git/davidb/linux-msm.git tags/msm-dt-for-3.7
+tegra/dt       git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-tegra.git tegra-for-3.7-dt
+samsung/gpio-dt git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git next/gpio-samsung
+tegra/dt2	git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-tegra.git tegra-for-3.7-dt2
+mxs/dt2		git://git.linaro.org/people/shawnguo/linux-2.6.git tags/mxs-dt-3.7-2
+imx/dt2		git://git.linaro.org/people/shawnguo/linux-2.6.git tags/imx-dt-3.7-2
+ux500/dt	git://git.linaro.org/people/ljones/linux-3.0-ux500.git for-arm-soc-next
+vt8500/devel	git://git.code.sf.net/p/linuxwmt/code tags/vt8500-for-next
+
+next/cleanup2:
+tegra/cleanup2	git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-tegra.git tegra-for-3.7-cleanup2
+
+next/soc2:
+mxs/sparse-irq	git://git.linaro.org/people/shawnguo/linux-2.6.git tags/mxs-sparse-irq
+		 (functionally depends on mxs/dt)
+
+next/defconfig:
+renesas/defconfig git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git defconfig
+lpc32xx/defconfig git://git.antcom.de/linux-2.6.git lpc32xx/defconfig
+mxs/defconfig	  git://git.linaro.org/people/shawnguo/linux-2.6.git tags/mxs-defconfig-3.7
+imx/defconfig	  git://git.pengutronix.de/git/imx/linux-2.6.git tags/imx-defconfig
+tegra/defconfig   git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-tegra.git tegra-for-3.7-defconfig
+samsung/defconfig git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git next/defconfig-samsung
+
+next/drivers:
+devel/led-driver	git://git.kernel.org/pub/scm/linux/kernel/git/cooloney/linux-leds.git for-arm-soc
+at91/mci	git://github.com/at91linux/linux-at91 at91-for-next-soc
+drivers/ocp2scp	patches from Kishon Vijay Abraham I <kishon@ti.com>
+		+ http://marc.info/?l=linux-next&m=134574365000518&w=2
+		+ http://lkml.org/lkml/2012/9/14/135
+tegra/drivers-i2c	git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-tegra.git tegra-for-3.7-drivers-i2c
+samsung/pinctrl	git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git next/pinctrl-samsung
+			(pulled twice, second from next/pinctrl-samsung-2)
+samsung/gscaler git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git next/dt-gscaler
+
+next/boards:
+pxa/board	git://github.com/hzhuang1/linux.git board
+ks8695/boards	<1346995449-5436-1-git-send-email-gerg@snapgear.com> and
+		<1346996139-5692-1-git-send-email-gerg@snapgear.com>
+renesas/boards	git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git boards
+		 (pulled twice)
+pxa/boards	git://github.com/hzhuang1/linux.git board
+imx/boards	git://git.pengutronix.de/git/imx/linux-2.6.git tags/imx-boards
+msm/boards	git://git.kernel.org/pub/scm/linux/kernel/git/davidb/linux-msm.git tags/msm-board-for-3.7
+samsung/boards  git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git next/board-samsung
+
+next/docs:
+mvebu/docs:	git://github.com/MISL-EBU-System-SW/mainline-public.git marvell-doc
+
+
+next/multiplatform:
+multiplatform/devel git://sources.calxeda.com/kernel/linux.git tags/multi-platform-for-3.7
+			depends on next/cleanup next/dt and next/soc to do conflict resolution locally
+			+ local patch for more dtb moves
+			+ Message-Id: <1347893712-21819-1-git-send-email-robherring2@gmail.com>
+multiplatform/smp_ops  <local contents from testing/smp_ops>
+			+ Message-Id: <1347490900-8409-2-git-send-email-davidb@codeaurora.org>
+
+
+late/kirkwood:
+kirkwood/boards		git://git.infradead.org/users/jcooper/linux.git kirkwood/boards
+kirkwood/defconfig	git://git.infradead.org/users/jcooper/linux.git kirkwood/defconfig
+kirkwood/dt		git://git.infradead.org/users/jcooper/linux.git kirkwood/dt
+kirkwood/cleanup	git://git.infradead.org/users/jcooper/linux.git kirkwood/cleanup
+kirkwood/addr_decode	git://git.infradead.org/users/jcooper/linux.git kirkwood/addr_decode
+kirkwood/drivers	git://git.infradead.org/users/jcooper/linux.git kirkwood/drivers
diff --git a/arch/arm/boot/Makefile b/arch/arm/boot/Makefile
index c877087..3fdab01 100644
--- a/arch/arm/boot/Makefile
+++ b/arch/arm/boot/Makefile
@@ -15,6 +15,8 @@ ifneq ($(MACHINE),)
 include $(srctree)/$(MACHINE)/Makefile.boot
 endif
 
+include $(srctree)/arch/arm/boot/dts/Makefile
+
 # Note: the following conditions must always be true:
 #   ZRELADDR == virt_to_phys(PAGE_OFFSET + TEXT_OFFSET)
 #   PARAMS_PHYS must be within 4MB of ZRELADDR
diff --git a/arch/arm/boot/compressed/decompress.c b/arch/arm/boot/compressed/decompress.c
index f41b38c..9deb56a 100644
--- a/arch/arm/boot/compressed/decompress.c
+++ b/arch/arm/boot/compressed/decompress.c
@@ -32,6 +32,9 @@ extern void error(char *);
 #  define Tracecv(c,x)
 #endif
 
+/* Not needed, but used in some headers pulled in by decompressors */
+extern char * strstr(const char * s1, const char *s2);
+
 #ifdef CONFIG_KERNEL_GZIP
 #include "../../../../lib/decompress_inflate.c"
 #endif
diff --git a/arch/arm/boot/compressed/misc.c b/arch/arm/boot/compressed/misc.c
index 8e2a8fc..df89983 100644
--- a/arch/arm/boot/compressed/misc.c
+++ b/arch/arm/boot/compressed/misc.c
@@ -25,7 +25,13 @@ unsigned int __machine_arch_type;
 static void putstr(const char *ptr);
 extern void error(char *x);
 
+#ifdef CONFIG_ARCH_MULTIPLATFORM
+static inline void putc(int c) {}
+static inline void flush(void) {}
+static inline void arch_decomp_setup(void) {}
+#else
 #include <mach/uncompress.h>
+#endif
 
 #ifdef CONFIG_DEBUG_ICEDCC
 
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
new file mode 100644
index 0000000..99e5e8e
--- /dev/null
+++ b/arch/arm/boot/dts/Makefile
@@ -0,0 +1,106 @@
+ifeq ($(CONFIG_OF),y)
+
+dtb-$(CONFIG_ARCH_AT91) += aks-cdu.dtb \
+	at91sam9263ek.dtb \
+	at91sam9g20ek_2mmc.dtb \
+	at91sam9g20ek.dtb \
+	at91sam9g25ek.dtb \
+	at91sam9m10g45ek.dtb \
+	at91sam9n12ek.dtb \
+	ethernut5.dtb \
+	evk-pro3.dtb \
+	kizbox.dtb \
+	tny_a9260.dtb \
+	tny_a9263.dtb \
+	tny_a9g20.dtb \
+	usb_a9260.dtb \
+	usb_a9263.dtb \
+	usb_a9g20.dtb
+dtb-$(CONFIG_ARCH_BCM2835) += bcm2835-rpi-b.dtb
+dtb-$(CONFIG_ARCH_DOVE) += dove-cm-a510.dtb \
+	dove-cubox.dtb \
+	dove-dove-db.dtb
+dtb-$(CONFIG_ARCH_EXYNOS) += exynos4210-origen.dtb \
+	exynos4210-smdkv310.dtb exynos4210-trats.dtb \
+	exynos5250-smdk5250.dtb
+dtb-$(CONFIG_ARCH_HIGHBANK) += highbank.dtb
+dtb-$(CONFIG_ARCH_IMX5) += imx51-babbage.dtb \
+	imx53-ard.dtb \
+	imx53-evk.dtb \
+	imx53-qsb.dtb \
+	imx53-smd.dtb
+dtb-$(CONFIG_SOC_IMX6Q) += imx6q-arm2.dtb \
+	imx6q-sabrelite.dtb \
+	imx6q-sabresd.dtb
+dtb-$(CONFIG_ARCH_LPC32XX) += ea3250.dtb phy3250.dtb
+dtb-$(CONFIG_ARCH_KIRKWOOD) += kirkwood-dns320.dtb \
+	kirkwood-dns325.dtb \
+	kirkwood-dockstar.dtb \
+	kirkwood-dreamplug.dtb \
+	kirkwood-goflexnet.dtb \
+	kirkwood-ib62x0.dtb \
+	kirkwood-iconnect.dtb \
+	kirkwood-iomega_ix2_200.dtb \
+	kirkwood-km_kirkwood.dtb \
+	kirkwood-lschlv2.dtb \
+	kirkwood-lsxhl.dtb \
+	kirkwood-ts219-6281.dtb \
+	kirkwood-ts219-6282.dtb
+dtb-$(CONFIG_ARCH_MSM) += msm8660-surf.dtb \
+	msm8960-cdp.dtb
+dtb-$(CONFIG_ARCH_MVEBU) += armada-370-db.dtb \
+	armada-xp-db.dtb
+dtb-$(CONFIG_ARCH_MXC) += imx51-babbage.dtb \
+	imx53-ard.dtb \
+	imx53-evk.dtb \
+	imx53-qsb.dtb \
+	imx53-smd.dtb \
+	imx6q-arm2.dtb \
+	imx6q-sabrelite.dtb \
+	imx6q-sabresd.dtb
+dtb-$(CONFIG_ARCH_MXS) += imx23-evk.dtb \
+	imx23-olinuxino.dtb \
+	imx23-stmp378x_devb.dtb \
+	imx28-apx4devkit.dtb \
+	imx28-cfa10036.dtb \
+	imx28-cfa10049.dtb \
+	imx28-evk.dtb \
+	imx28-m28evk.dtb \
+	imx28-tx28.dtb
+dtb-$(CONFIG_ARCH_OMAP2PLUS) += omap2420-h4.dtb \
+	omap3-beagle-xm.dtb \
+	omap3-evm.dtb \
+	omap3-tobi.dtb \
+	omap4-panda.dtb \
+	omap4-pandaES.dtb \
+	omap4-var_som.dtb \
+	omap4-sdp.dtb \
+	omap5-evm.dtb
+dtb-$(CONFIG_ARCH_PRIMA2) += prima2-evb.dtb
+dtb-$(CONFIG_ARCH_U8500) += snowball.dtb
+dtb-$(CONFIG_ARCH_SHMOBILE) += emev2-kzm9d.dtb \
+	r8a7740-armadillo800eva.dtb \
+	sh73a0-kzm9g.dtb
+dtb-$(CONFIG_ARCH_SPEAR13XX) += spear1310-evb.dtb \
+	spear1340-evb.dtb
+dtb-$(CONFIG_ARCH_SPEAR3XX)+= spear300-evb.dtb \
+	spear310-evb.dtb \
+	spear320-evb.dtb
+dtb-$(CONFIG_ARCH_SPEAR6XX)+= spear600-evb.dtb
+dtb-$(CONFIG_ARCH_TEGRA) += tegra20-harmony.dtb \
+	tegra20-medcom-wide.dtb \
+	tegra20-paz00.dtb \
+	tegra20-plutux.dtb \
+	tegra20-seaboard.dtb \
+	tegra20-tec.dtb \
+	tegra20-trimslice.dtb \
+	tegra20-ventana.dtb \
+	tegra20-whistler.dtb \
+	tegra30-cardhu-a02.dtb \
+	tegra30-cardhu-a04.dtb
+dtb-$(CONFIG_ARCH_VEXPRESS) += vexpress-v2p-ca5s.dtb \
+	vexpress-v2p-ca9.dtb \
+	vexpress-v2p-ca15-tc1.dtb \
+	vexpress-v2p-ca15_a7.dtb
+
+endif
diff --git a/arch/arm/boot/dts/am335x-bone.dts b/arch/arm/boot/dts/am335x-bone.dts
index a9af4db..c634f87 100644
--- a/arch/arm/boot/dts/am335x-bone.dts
+++ b/arch/arm/boot/dts/am335x-bone.dts
@@ -17,4 +17,64 @@
 		device_type = "memory";
 		reg = <0x80000000 0x10000000>; /* 256 MB */
 	};
+
+	ocp {
+		uart1: serial@44e09000 {
+			status = "okay";
+		};
+
+		i2c1: i2c@44e0b000 {
+			status = "okay";
+			clock-frequency = <400000>;
+
+			tps: tps@24 {
+				reg = <0x24>;
+			};
+
+		};
+	};
+};
+
+/include/ "tps65217.dtsi"
+
+&tps {
+	regulators {
+		dcdc1_reg: regulator@0 {
+			regulator-always-on;
+		};
+
+		dcdc2_reg: regulator@1 {
+			/* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */
+			regulator-name = "vdd_mpu";
+			regulator-min-microvolt = <925000>;
+			regulator-max-microvolt = <1325000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		dcdc3_reg: regulator@2 {
+			/* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */
+			regulator-name = "vdd_core";
+			regulator-min-microvolt = <925000>;
+			regulator-max-microvolt = <1150000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		ldo1_reg: regulator@3 {
+			regulator-always-on;
+		};
+
+		ldo2_reg: regulator@4 {
+			regulator-always-on;
+		};
+
+		ldo3_reg: regulator@5 {
+			regulator-always-on;
+		};
+
+		ldo4_reg: regulator@6 {
+			regulator-always-on;
+		};
+	};
 };
diff --git a/arch/arm/boot/dts/am335x-evm.dts b/arch/arm/boot/dts/am335x-evm.dts
index d6a97d9..185d632 100644
--- a/arch/arm/boot/dts/am335x-evm.dts
+++ b/arch/arm/boot/dts/am335x-evm.dts
@@ -17,4 +17,104 @@
 		device_type = "memory";
 		reg = <0x80000000 0x10000000>; /* 256 MB */
 	};
+
+	ocp {
+		uart1: serial@44e09000 {
+			status = "okay";
+		};
+
+		i2c1: i2c@44e0b000 {
+			status = "okay";
+			clock-frequency = <400000>;
+
+			tps: tps@2d {
+				reg = <0x2d>;
+			};
+		};
+	};
+
+	vbat: fixedregulator@0 {
+		compatible = "regulator-fixed";
+		regulator-name = "vbat";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-boot-on;
+	};
+};
+
+/include/ "tps65910.dtsi"
+
+&tps {
+	vcc1-supply = <&vbat>;
+	vcc2-supply = <&vbat>;
+	vcc3-supply = <&vbat>;
+	vcc4-supply = <&vbat>;
+	vcc5-supply = <&vbat>;
+	vcc6-supply = <&vbat>;
+	vcc7-supply = <&vbat>;
+	vccio-supply = <&vbat>;
+
+	regulators {
+		vrtc_reg: regulator@0 {
+			regulator-always-on;
+		};
+
+		vio_reg: regulator@1 {
+			regulator-always-on;
+		};
+
+		vdd1_reg: regulator@2 {
+			/* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */
+			regulator-name = "vdd_mpu";
+			regulator-min-microvolt = <912500>;
+			regulator-max-microvolt = <1312500>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		vdd2_reg: regulator@3 {
+			/* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */
+			regulator-name = "vdd_core";
+			regulator-min-microvolt = <912500>;
+			regulator-max-microvolt = <1150000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+
+		vdd3_reg: regulator@4 {
+			regulator-always-on;
+		};
+
+		vdig1_reg: regulator@5 {
+			regulator-always-on;
+		};
+
+		vdig2_reg: regulator@6 {
+			regulator-always-on;
+		};
+
+		vpll_reg: regulator@7 {
+			regulator-always-on;
+		};
+
+		vdac_reg: regulator@8 {
+			regulator-always-on;
+		};
+
+		vaux1_reg: regulator@9 {
+			regulator-always-on;
+		};
+
+		vaux2_reg: regulator@10 {
+			regulator-always-on;
+		};
+
+		vaux33_reg: regulator@11 {
+			regulator-always-on;
+		};
+
+		vmmc_reg: regulator@12 {
+			regulator-always-on;
+		};
+	};
 };
diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
index bd0cff3..bb31bff 100644
--- a/arch/arm/boot/dts/am33xx.dtsi
+++ b/arch/arm/boot/dts/am33xx.dtsi
@@ -69,95 +69,146 @@
 			#gpio-cells = <2>;
 			interrupt-controller;
 			#interrupt-cells = <1>;
+			reg = <0x44e07000 0x1000>;
+			interrupt-parent = <&intc>;
+			interrupts = <96>;
 		};
 
-		gpio2: gpio@4804C000 {
+		gpio2: gpio@4804c000 {
 			compatible = "ti,omap4-gpio";
 			ti,hwmods = "gpio2";
 			gpio-controller;
 			#gpio-cells = <2>;
 			interrupt-controller;
 			#interrupt-cells = <1>;
+			reg = <0x4804c000 0x1000>;
+			interrupt-parent = <&intc>;
+			interrupts = <98>;
 		};
 
-		gpio3: gpio@481AC000 {
+		gpio3: gpio@481ac000 {
 			compatible = "ti,omap4-gpio";
 			ti,hwmods = "gpio3";
 			gpio-controller;
 			#gpio-cells = <2>;
 			interrupt-controller;
 			#interrupt-cells = <1>;
+			reg = <0x481ac000 0x1000>;
+			interrupt-parent = <&intc>;
+			interrupts = <32>;
 		};
 
-		gpio4: gpio@481AE000 {
+		gpio4: gpio@481ae000 {
 			compatible = "ti,omap4-gpio";
 			ti,hwmods = "gpio4";
 			gpio-controller;
 			#gpio-cells = <2>;
 			interrupt-controller;
 			#interrupt-cells = <1>;
+			reg = <0x481ae000 0x1000>;
+			interrupt-parent = <&intc>;
+			interrupts = <62>;
 		};
 
-		uart1: serial@44E09000 {
+		uart1: serial@44e09000 {
 			compatible = "ti,omap3-uart";
 			ti,hwmods = "uart1";
 			clock-frequency = <48000000>;
+			reg = <0x44e09000 0x2000>;
+			interrupt-parent = <&intc>;
+			interrupts = <72>;
+			status = "disabled";
 		};
 
 		uart2: serial@48022000 {
 			compatible = "ti,omap3-uart";
 			ti,hwmods = "uart2";
 			clock-frequency = <48000000>;
+			reg = <0x48022000 0x2000>;
+			interrupt-parent = <&intc>;
+			interrupts = <73>;
+			status = "disabled";
 		};
 
 		uart3: serial@48024000 {
 			compatible = "ti,omap3-uart";
 			ti,hwmods = "uart3";
 			clock-frequency = <48000000>;
+			reg = <0x48024000 0x2000>;
+			interrupt-parent = <&intc>;
+			interrupts = <74>;
+			status = "disabled";
 		};
 
-		uart4: serial@481A6000 {
+		uart4: serial@481a6000 {
 			compatible = "ti,omap3-uart";
 			ti,hwmods = "uart4";
 			clock-frequency = <48000000>;
+			reg = <0x481a6000 0x2000>;
+			interrupt-parent = <&intc>;
+			interrupts = <44>;
+			status = "disabled";
 		};
 
-		uart5: serial@481A8000 {
+		uart5: serial@481a8000 {
 			compatible = "ti,omap3-uart";
 			ti,hwmods = "uart5";
 			clock-frequency = <48000000>;
+			reg = <0x481a8000 0x2000>;
+			interrupt-parent = <&intc>;
+			interrupts = <45>;
+			status = "disabled";
 		};
 
-		uart6: serial@481AA000 {
+		uart6: serial@481aa000 {
 			compatible = "ti,omap3-uart";
 			ti,hwmods = "uart6";
 			clock-frequency = <48000000>;
+			reg = <0x481aa000 0x2000>;
+			interrupt-parent = <&intc>;
+			interrupts = <46>;
+			status = "disabled";
 		};
 
-		i2c1: i2c@44E0B000 {
+		i2c1: i2c@44e0b000 {
 			compatible = "ti,omap4-i2c";
 			#address-cells = <1>;
 			#size-cells = <0>;
 			ti,hwmods = "i2c1";
+			reg = <0x44e0b000 0x1000>;
+			interrupt-parent = <&intc>;
+			interrupts = <70>;
+			status = "disabled";
 		};
 
-		i2c2: i2c@4802A000 {
+		i2c2: i2c@4802a000 {
 			compatible = "ti,omap4-i2c";
 			#address-cells = <1>;
 			#size-cells = <0>;
 			ti,hwmods = "i2c2";
+			reg = <0x4802a000 0x1000>;
+			interrupt-parent = <&intc>;
+			interrupts = <71>;
+			status = "disabled";
 		};
 
-		i2c3: i2c@4819C000 {
+		i2c3: i2c@4819c000 {
 			compatible = "ti,omap4-i2c";
 			#address-cells = <1>;
 			#size-cells = <0>;
 			ti,hwmods = "i2c3";
+			reg = <0x4819c000 0x1000>;
+			interrupt-parent = <&intc>;
+			interrupts = <30>;
+			status = "disabled";
 		};
 
 		wdt2: wdt@44e35000 {
 			compatible = "ti,omap3-wdt";
 			ti,hwmods = "wd_timer2";
+			reg = <0x44e35000 0x1000>;
+			interrupt-parent = <&intc>;
+			interrupts = <91>;
 		};
 	};
 };
diff --git a/arch/arm/boot/dts/armada-370-xp.dtsi b/arch/arm/boot/dts/armada-370-xp.dtsi
index 6b6b932..16cc82c 100644
--- a/arch/arm/boot/dts/armada-370-xp.dtsi
+++ b/arch/arm/boot/dts/armada-370-xp.dtsi
@@ -63,6 +63,11 @@
 			       reg = <0xd0020300 0x30>;
 			       interrupts = <37>, <38>, <39>, <40>;
 		};
+
+		addr-decoding@d0020000 {
+			compatible = "marvell,armada-addr-decoding-controller";
+			reg = <0xd0020000 0x258>;
+		};
 	};
 };
 
diff --git a/arch/arm/boot/dts/armada-370.dtsi b/arch/arm/boot/dts/armada-370.dtsi
index 3228ccc..2069151 100644
--- a/arch/arm/boot/dts/armada-370.dtsi
+++ b/arch/arm/boot/dts/armada-370.dtsi
@@ -21,6 +21,12 @@
 	model = "Marvell Armada 370 family SoC";
 	compatible = "marvell,armada370", "marvell,armada-370-xp";
 
+	aliases {
+		gpio0 = &gpio0;
+		gpio1 = &gpio1;
+		gpio2 = &gpio2;
+	};
+
 	mpic: interrupt-controller@d0020000 {
 	      reg = <0xd0020a00 0x1d0>,
 		    <0xd0021870 0x58>;
@@ -31,5 +37,43 @@
 				compatible = "marvell,armada-370-xp-system-controller";
 				reg = <0xd0018200 0x100>;
 		};
+
+		pinctrl {
+			compatible = "marvell,mv88f6710-pinctrl";
+			reg = <0xd0018000 0x38>;
+	        };
+
+		gpio0: gpio@d0018100 {
+			compatible = "marvell,orion-gpio";
+			reg = <0xd0018100 0x40>;
+			ngpios = <32>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupts-cells = <2>;
+			interrupts = <82>, <83>, <84>, <85>;
+		};
+
+		gpio1: gpio@d0018140 {
+			compatible = "marvell,orion-gpio";
+			reg = <0xd0018140 0x40>;
+			ngpios = <32>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupts-cells = <2>;
+			interrupts = <87>, <88>, <89>, <90>;
+		};
+
+		gpio2: gpio@d0018180 {
+			compatible = "marvell,orion-gpio";
+			reg = <0xd0018180 0x40>;
+			ngpios = <2>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupts-cells = <2>;
+			interrupts = <91>;
+		};
 	};
 };
diff --git a/arch/arm/boot/dts/armada-xp-db.dts b/arch/arm/boot/dts/armada-xp-db.dts
index f97040d..b1fc728 100644
--- a/arch/arm/boot/dts/armada-xp-db.dts
+++ b/arch/arm/boot/dts/armada-xp-db.dts
@@ -14,11 +14,11 @@
  */
 
 /dts-v1/;
-/include/ "armada-xp.dtsi"
+/include/ "armada-xp-mv78460.dtsi"
 
 / {
 	model = "Marvell Armada XP Evaluation Board";
-	compatible = "marvell,axp-db", "marvell,armadaxp", "marvell,armada-370-xp";
+	compatible = "marvell,axp-db", "marvell,armadaxp-mv78460", "marvell,armadaxp", "marvell,armada-370-xp";
 
 	chosen {
 		bootargs = "console=ttyS0,115200 earlyprintk";
diff --git a/arch/arm/boot/dts/armada-xp-mv78230.dtsi b/arch/arm/boot/dts/armada-xp-mv78230.dtsi
new file mode 100644
index 0000000..ea35519
--- /dev/null
+++ b/arch/arm/boot/dts/armada-xp-mv78230.dtsi
@@ -0,0 +1,57 @@
+/*
+ * Device Tree Include file for Marvell Armada XP family SoC
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ *
+ * Contains definitions specific to the Armada XP MV78230 SoC that are not
+ * common to all Armada XP SoCs.
+ */
+
+/include/ "armada-xp.dtsi"
+
+/ {
+	model = "Marvell Armada XP MV78230 SoC";
+	compatible = "marvell,armadaxp-mv78230", "marvell,armadaxp", "marvell,armada-370-xp";
+
+	aliases {
+		gpio0 = &gpio0;
+		gpio1 = &gpio1;
+	};
+
+	soc {
+		pinctrl {
+			compatible = "marvell,mv78230-pinctrl";
+			reg = <0xd0018000 0x38>;
+		};
+
+		gpio0: gpio@d0018100 {
+			compatible = "marvell,armadaxp-gpio";
+			reg = <0xd0018100 0x40>,
+			    <0xd0018800 0x30>;
+			ngpios = <32>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupts-cells = <2>;
+			interrupts = <16>, <17>, <18>, <19>;
+		};
+
+		gpio1: gpio@d0018140 {
+			compatible = "marvell,armadaxp-gpio";
+			reg = <0xd0018140 0x40>,
+			    <0xd0018840 0x30>;
+			ngpios = <17>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupts-cells = <2>;
+			interrupts = <20>, <21>, <22>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/armada-xp-mv78260.dtsi b/arch/arm/boot/dts/armada-xp-mv78260.dtsi
new file mode 100644
index 0000000..2057863
--- /dev/null
+++ b/arch/arm/boot/dts/armada-xp-mv78260.dtsi
@@ -0,0 +1,70 @@
+/*
+ * Device Tree Include file for Marvell Armada XP family SoC
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ *
+ * Contains definitions specific to the Armada XP MV78260 SoC that are not
+ * common to all Armada XP SoCs.
+ */
+
+/include/ "armada-xp.dtsi"
+
+/ {
+	model = "Marvell Armada XP MV78260 SoC";
+	compatible = "marvell,armadaxp-mv78260", "marvell,armadaxp", "marvell,armada-370-xp";
+
+	aliases {
+		gpio0 = &gpio0;
+		gpio1 = &gpio1;
+		gpio2 = &gpio2;
+	};
+
+	soc {
+		pinctrl {
+			compatible = "marvell,mv78260-pinctrl";
+			reg = <0xd0018000 0x38>;
+		};
+
+		gpio0: gpio@d0018100 {
+			compatible = "marvell,armadaxp-gpio";
+			reg = <0xd0018100 0x40>,
+			    <0xd0018800 0x30>;
+			ngpios = <32>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupts-cells = <2>;
+			interrupts = <16>, <17>, <18>, <19>;
+		};
+
+		gpio1: gpio@d0018140 {
+			compatible = "marvell,armadaxp-gpio";
+			reg = <0xd0018140 0x40>,
+			    <0xd0018840 0x30>;
+			ngpios = <32>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupts-cells = <2>;
+			interrupts = <20>, <21>, <22>, <23>;
+		};
+
+		gpio2: gpio@d0018180 {
+			compatible = "marvell,armadaxp-gpio";
+			reg = <0xd0018180 0x40>,
+			    <0xd0018870 0x30>;
+			ngpios = <3>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupts-cells = <2>;
+			interrupts = <24>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/armada-xp-mv78460.dtsi b/arch/arm/boot/dts/armada-xp-mv78460.dtsi
new file mode 100644
index 0000000..ffac983
--- /dev/null
+++ b/arch/arm/boot/dts/armada-xp-mv78460.dtsi
@@ -0,0 +1,70 @@
+/*
+ * Device Tree Include file for Marvell Armada XP family SoC
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ *
+ * Contains definitions specific to the Armada XP MV78460 SoC that are not
+ * common to all Armada XP SoCs.
+ */
+
+/include/ "armada-xp.dtsi"
+
+/ {
+	model = "Marvell Armada XP MV78460 SoC";
+	compatible = "marvell,armadaxp-mv78460", "marvell,armadaxp", "marvell,armada-370-xp";
+
+	aliases {
+		gpio0 = &gpio0;
+		gpio1 = &gpio1;
+		gpio2 = &gpio2;
+	};
+
+	soc {
+		pinctrl {
+			compatible = "marvell,mv78460-pinctrl";
+			reg = <0xd0018000 0x38>;
+		};
+
+		gpio0: gpio@d0018100 {
+			compatible = "marvell,armadaxp-gpio";
+			reg = <0xd0018100 0x40>,
+			    <0xd0018800 0x30>;
+			ngpios = <32>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupts-cells = <2>;
+			interrupts = <16>, <17>, <18>, <19>;
+		};
+
+		gpio1: gpio@d0018140 {
+			compatible = "marvell,armadaxp-gpio";
+			reg = <0xd0018140 0x40>,
+			    <0xd0018840 0x30>;
+			ngpios = <32>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupts-cells = <2>;
+			interrupts = <20>, <21>, <22>, <23>;
+		};
+
+		gpio2: gpio@d0018180 {
+			compatible = "marvell,armadaxp-gpio";
+			reg = <0xd0018180 0x40>,
+			    <0xd0018870 0x30>;
+			ngpios = <3>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupts-cells = <2>;
+			interrupts = <24>;
+		};
+	};
+ };
diff --git a/arch/arm/boot/dts/at91sam9260.dtsi b/arch/arm/boot/dts/at91sam9260.dtsi
index 7c95f76..d410581 100644
--- a/arch/arm/boot/dts/at91sam9260.dtsi
+++ b/arch/arm/boot/dts/at91sam9260.dtsi
@@ -28,6 +28,7 @@
 		gpio2 = &pioC;
 		tcb0 = &tcb0;
 		tcb1 = &tcb1;
+		i2c0 = &i2c0;
 	};
 	cpus {
 		cpu@0 {
@@ -202,6 +203,15 @@
 				status = "disabled";
 			};
 
+			i2c0: i2c@fffac000 {
+				compatible = "atmel,at91sam9260-i2c";
+				reg = <0xfffac000 0x100>;
+				interrupts = <11 4 6>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				status = "disabled";
+			};
+
 			adc0: adc@fffe0000 {
 				compatible = "atmel,at91sam9260-adc";
 				reg = <0xfffe0000 0x100>;
diff --git a/arch/arm/boot/dts/at91sam9263.dtsi b/arch/arm/boot/dts/at91sam9263.dtsi
index 195019b..3e6e5c1 100644
--- a/arch/arm/boot/dts/at91sam9263.dtsi
+++ b/arch/arm/boot/dts/at91sam9263.dtsi
@@ -24,6 +24,7 @@
 		gpio3 = &pioD;
 		gpio4 = &pioE;
 		tcb0 = &tcb0;
+		i2c0 = &i2c0;
 	};
 	cpus {
 		cpu@0 {
@@ -185,6 +186,15 @@
 				interrupts = <24 4 2>;
 				status = "disabled";
 			};
+
+			i2c0: i2c@fff88000 {
+				compatible = "atmel,at91sam9263-i2c";
+				reg = <0xfff88000 0x100>;
+				interrupts = <13 4 6>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				status = "disabled";
+			};
 		};
 
 		nand0: nand@40000000 {
diff --git a/arch/arm/boot/dts/at91sam9g20.dtsi b/arch/arm/boot/dts/at91sam9g20.dtsi
index 2a1d1ca..75ce6e7 100644
--- a/arch/arm/boot/dts/at91sam9g20.dtsi
+++ b/arch/arm/boot/dts/at91sam9g20.dtsi
@@ -18,6 +18,10 @@
 
 	ahb {
 		apb {
+			i2c0: i2c@fffac000 {
+				compatible = "atmel,at91sam9g20-i2c";
+			};
+
 			adc0: adc@fffe0000 {
 				atmel,adc-startup-time = <40>;
 			};
diff --git a/arch/arm/boot/dts/at91sam9g25ek.dts b/arch/arm/boot/dts/at91sam9g25ek.dts
index 96514c1..877c08f 100644
--- a/arch/arm/boot/dts/at91sam9g25ek.dts
+++ b/arch/arm/boot/dts/at91sam9g25ek.dts
@@ -32,6 +32,18 @@
 				phy-mode = "rmii";
 				status = "okay";
 			};
+
+			i2c0: i2c@f8010000 {
+				status = "okay";
+			};
+
+			i2c1: i2c@f8014000 {
+				status = "okay";
+			};
+
+			i2c2: i2c@f8018000 {
+				status = "okay";
+			};
 		};
 
 		usb0: ohci@00600000 {
diff --git a/arch/arm/boot/dts/at91sam9g45.dtsi b/arch/arm/boot/dts/at91sam9g45.dtsi
index 63751b1..3add030 100644
--- a/arch/arm/boot/dts/at91sam9g45.dtsi
+++ b/arch/arm/boot/dts/at91sam9g45.dtsi
@@ -29,6 +29,8 @@
 		gpio4 = &pioE;
 		tcb0 = &tcb0;
 		tcb1 = &tcb1;
+		i2c0 = &i2c0;
+		i2c1 = &i2c1;
 	};
 	cpus {
 		cpu@0 {
@@ -206,6 +208,24 @@
 				status = "disabled";
 			};
 
+			i2c0: i2c@fff84000 {
+				compatible = "atmel,at91sam9g10-i2c";
+				reg = <0xfff84000 0x100>;
+				interrupts = <12 4 6>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				status = "disabled";
+			};
+
+			i2c1: i2c@fff88000 {
+				compatible = "atmel,at91sam9g10-i2c";
+				reg = <0xfff88000 0x100>;
+				interrupts = <13 4 6>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				status = "disabled";
+			};
+
 			adc0: adc@fffb0000 {
 				compatible = "atmel,at91sam9260-adc";
 				reg = <0xfffb0000 0x100>;
diff --git a/arch/arm/boot/dts/at91sam9m10g45ek.dts b/arch/arm/boot/dts/at91sam9m10g45ek.dts
index a3633bd..15e1dd4 100644
--- a/arch/arm/boot/dts/at91sam9m10g45ek.dts
+++ b/arch/arm/boot/dts/at91sam9m10g45ek.dts
@@ -46,6 +46,14 @@
 				phy-mode = "rmii";
 				status = "okay";
 			};
+
+			i2c0: i2c@fff84000 {
+				status = "okay";
+			};
+
+			i2c1: i2c@fff88000 {
+				status = "okay";
+			};
 		};
 
 		nand0: nand@40000000 {
diff --git a/arch/arm/boot/dts/at91sam9n12.dtsi b/arch/arm/boot/dts/at91sam9n12.dtsi
index ef9336a..82508d6 100644
--- a/arch/arm/boot/dts/at91sam9n12.dtsi
+++ b/arch/arm/boot/dts/at91sam9n12.dtsi
@@ -26,6 +26,8 @@
 		gpio3 = &pioD;
 		tcb0 = &tcb0;
 		tcb1 = &tcb1;
+		i2c0 = &i2c0;
+		i2c1 = &i2c1;
 	};
 	cpus {
 		cpu@0 {
@@ -182,6 +184,24 @@
 				atmel,use-dma-tx;
 				status = "disabled";
 			};
+
+			i2c0: i2c@f8010000 {
+				compatible = "atmel,at91sam9x5-i2c";
+				reg = <0xf8010000 0x100>;
+				interrupts = <9 4 6>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				status = "disabled";
+			};
+
+			i2c1: i2c@f8014000 {
+				compatible = "atmel,at91sam9x5-i2c";
+				reg = <0xf8014000 0x100>;
+				interrupts = <10 4 6>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				status = "disabled";
+			};
 		};
 
 		nand0: nand@40000000 {
diff --git a/arch/arm/boot/dts/at91sam9n12ek.dts b/arch/arm/boot/dts/at91sam9n12ek.dts
index f4e43e3..912b2c2 100644
--- a/arch/arm/boot/dts/at91sam9n12ek.dts
+++ b/arch/arm/boot/dts/at91sam9n12ek.dts
@@ -37,6 +37,14 @@
 			dbgu: serial@fffff200 {
 				status = "okay";
 			};
+
+			i2c0: i2c@f8010000 {
+				status = "okay";
+			};
+
+			i2c1: i2c@f8014000 {
+				status = "okay";
+			};
 		};
 
 		nand0: nand@40000000 {
diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi
index 8a387a8..03fc136 100644
--- a/arch/arm/boot/dts/at91sam9x5.dtsi
+++ b/arch/arm/boot/dts/at91sam9x5.dtsi
@@ -27,6 +27,9 @@
 		gpio3 = &pioD;
 		tcb0 = &tcb0;
 		tcb1 = &tcb1;
+		i2c0 = &i2c0;
+		i2c1 = &i2c1;
+		i2c2 = &i2c2;
 	};
 	cpus {
 		cpu@0 {
@@ -196,6 +199,33 @@
 				status = "disabled";
 			};
 
+			i2c0: i2c@f8010000 {
+				compatible = "atmel,at91sam9x5-i2c";
+				reg = <0xf8010000 0x100>;
+				interrupts = <9 4 6>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				status = "disabled";
+			};
+
+			i2c1: i2c@f8014000 {
+				compatible = "atmel,at91sam9x5-i2c";
+				reg = <0xf8014000 0x100>;
+				interrupts = <10 4 6>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				status = "disabled";
+			};
+
+			i2c2: i2c@f8018000 {
+				compatible = "atmel,at91sam9x5-i2c";
+				reg = <0xf8018000 0x100>;
+				interrupts = <11 4 6>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				status = "disabled";
+			};
+
 			adc0: adc@f804c000 {
 				compatible = "atmel,at91sam9260-adc";
 				reg = <0xf804c000 0x100>;
diff --git a/arch/arm/boot/dts/bcm2835-rpi-b.dts b/arch/arm/boot/dts/bcm2835-rpi-b.dts
new file mode 100644
index 0000000..7dd860f
--- /dev/null
+++ b/arch/arm/boot/dts/bcm2835-rpi-b.dts
@@ -0,0 +1,12 @@
+/dts-v1/;
+/memreserve/ 0x0c000000 0x04000000;
+/include/ "bcm2835.dtsi"
+
+/ {
+	compatible = "raspberrypi,model-b", "brcm,bcm2835";
+	model = "Raspberry Pi Model B";
+
+	memory {
+		reg = <0 0x10000000>;
+	};
+};
diff --git a/arch/arm/boot/dts/bcm2835.dtsi b/arch/arm/boot/dts/bcm2835.dtsi
new file mode 100644
index 0000000..0b61939
--- /dev/null
+++ b/arch/arm/boot/dts/bcm2835.dtsi
@@ -0,0 +1,39 @@
+/include/ "skeleton.dtsi"
+
+/ {
+	compatible = "brcm,bcm2835";
+	model = "BCM2835";
+	interrupt-parent = <&intc>;
+
+	chosen {
+		bootargs = "earlyprintk console=ttyAMA0";
+	};
+
+	soc {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0x7e000000 0x20000000 0x02000000>;
+
+		timer {
+			compatible = "brcm,bcm2835-system-timer";
+			reg = <0x7e003000 0x1000>;
+			interrupts = <1 0>, <1 1>, <1 2>, <1 3>;
+			clock-frequency = <1000000>;
+		};
+
+		intc: interrupt-controller {
+			compatible = "brcm,bcm2835-armctrl-ic";
+			reg = <0x7e00b200 0x200>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		uart@20201000 {
+			compatible = "brcm,bcm2835-pl011", "arm,pl011", "arm,primecell";
+			reg = <0x7e201000 0x1000>;
+			interrupts = <2 25>;
+			clock-frequency = <3000000>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/db8500.dtsi b/arch/arm/boot/dts/db8500.dtsi
deleted file mode 100644
index 3180a9c..0000000
--- a/arch/arm/boot/dts/db8500.dtsi
+++ /dev/null
@@ -1,592 +0,0 @@
-/*
- * Copyright 2012 Linaro Ltd
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-/include/ "skeleton.dtsi"
-
-/ {
-	soc-u9500 {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		compatible = "stericsson,db8500";
-		interrupt-parent = <&intc>;
-		ranges;
-
-		intc: interrupt-controller@a0411000 {
-			compatible = "arm,cortex-a9-gic";
-			#interrupt-cells = <3>;
-			#address-cells = <1>;
-			interrupt-controller;
-			reg = <0xa0411000 0x1000>,
-			      <0xa0410100 0x100>;
-		};
-
-		L2: l2-cache {
-			compatible = "arm,pl310-cache";
-			reg = <0xa0412000 0x1000>;
-			interrupts = <0 13 4>;
-			cache-unified;
-			cache-level = <2>;
-		};
-
-		pmu {
-			compatible = "arm,cortex-a9-pmu";
-			interrupts = <0 7 0x4>;
-		};
-
-		timer@a0410600 {
-			compatible = "arm,cortex-a9-twd-timer";
-			reg = <0xa0410600 0x20>;
-			interrupts = <1 13 0x304>;
-		};
-
-		rtc@80154000 {
-			compatible = "arm,rtc-pl031", "arm,primecell";
-			reg = <0x80154000 0x1000>;
-			interrupts = <0 18 0x4>;
-		};
-
-		gpio0: gpio@8012e000 {
-			compatible = "stericsson,db8500-gpio",
-				"st,nomadik-gpio";
-			reg =  <0x8012e000 0x80>;
-			interrupts = <0 119 0x4>;
-			interrupt-controller;
-			#interrupt-cells = <2>;
-			st,supports-sleepmode;
-			gpio-controller;
-			#gpio-cells = <2>;
-			gpio-bank = <0>;
-		};
-
-		gpio1: gpio@8012e080 {
-			compatible = "stericsson,db8500-gpio",
-				"st,nomadik-gpio";
-			reg =  <0x8012e080 0x80>;
-			interrupts = <0 120 0x4>;
-			interrupt-controller;
-			#interrupt-cells = <2>;
-			st,supports-sleepmode;
-			gpio-controller;
-			#gpio-cells = <2>;
-			gpio-bank = <1>;
-		};
-
-		gpio2: gpio@8000e000 {
-			compatible = "stericsson,db8500-gpio",
-				"st,nomadik-gpio";
-			reg =  <0x8000e000 0x80>;
-			interrupts = <0 121 0x4>;
-			interrupt-controller;
-			#interrupt-cells = <2>;
-			st,supports-sleepmode;
-			gpio-controller;
-			#gpio-cells = <2>;
-			gpio-bank = <2>;
-		};
-
-		gpio3: gpio@8000e080 {
-			compatible = "stericsson,db8500-gpio",
-				"st,nomadik-gpio";
-			reg =  <0x8000e080 0x80>;
-			interrupts = <0 122 0x4>;
-			interrupt-controller;
-			#interrupt-cells = <2>;
-			st,supports-sleepmode;
-			gpio-controller;
-			#gpio-cells = <2>;
-			gpio-bank = <3>;
-		};
-
-		gpio4: gpio@8000e100 {
-			compatible = "stericsson,db8500-gpio",
-				"st,nomadik-gpio";
-			reg =  <0x8000e100 0x80>;
-			interrupts = <0 123 0x4>;
-			interrupt-controller;
-			#interrupt-cells = <2>;
-			st,supports-sleepmode;
-			gpio-controller;
-			#gpio-cells = <2>;
-			gpio-bank = <4>;
-		};
-
-		gpio5: gpio@8000e180 {
-			compatible = "stericsson,db8500-gpio",
-				"st,nomadik-gpio";
-			reg =  <0x8000e180 0x80>;
-			interrupts = <0 124 0x4>;
-			interrupt-controller;
-			#interrupt-cells = <2>;
-			st,supports-sleepmode;
-			gpio-controller;
-			#gpio-cells = <2>;
-			gpio-bank = <5>;
-		};
-
-		gpio6: gpio@8011e000 {
-			compatible = "stericsson,db8500-gpio",
-				"st,nomadik-gpio";
-			reg =  <0x8011e000 0x80>;
-			interrupts = <0 125 0x4>;
-			interrupt-controller;
-			#interrupt-cells = <2>;
-			st,supports-sleepmode;
-			gpio-controller;
-			#gpio-cells = <2>;
-			gpio-bank = <6>;
-		};
-
-		gpio7: gpio@8011e080 {
-			compatible = "stericsson,db8500-gpio",
-				"st,nomadik-gpio";
-			reg =  <0x8011e080 0x80>;
-			interrupts = <0 126 0x4>;
-			interrupt-controller;
-			#interrupt-cells = <2>;
-			st,supports-sleepmode;
-			gpio-controller;
-			#gpio-cells = <2>;
-			gpio-bank = <7>;
-		};
-
-		gpio8: gpio@a03fe000 {
-			compatible = "stericsson,db8500-gpio",
-				"st,nomadik-gpio";
-			reg =  <0xa03fe000 0x80>;
-			interrupts = <0 127 0x4>;
-			interrupt-controller;
-			#interrupt-cells = <2>;
-			st,supports-sleepmode;
-			gpio-controller;
-			#gpio-cells = <2>;
-			gpio-bank = <8>;
-		};
-
-		pinctrl {
-			compatible = "stericsson,nmk_pinctrl";
-		};
-
-		usb@a03e0000 {
-			compatible = "stericsson,db8500-musb",
-				"mentor,musb";
-			reg = <0xa03e0000 0x10000>;
-			interrupts = <0 23 0x4>;
-		};
-
-		dma-controller@801C0000 {
-			compatible = "stericsson,db8500-dma40",
-					"stericsson,dma40";
-			reg = <0x801C0000 0x1000 0x40010000 0x800>;
-			interrupts = <0 25 0x4>;
-		};
-
-		prcmu@80157000 {
-			compatible = "stericsson,db8500-prcmu";
-			reg = <0x80157000 0x1000>;
-			interrupts = <0 47 0x4>;
-			#address-cells = <1>;
-			#size-cells = <1>;
-			ranges;
-
-			prcmu-timer-4@80157450 {
-				compatible = "stericsson,db8500-prcmu-timer-4";
-				reg = <0x80157450 0xC>;
-			};
-
-			db8500-prcmu-regulators {
-				compatible = "stericsson,db8500-prcmu-regulator";
-
-				// DB8500_REGULATOR_VAPE
-				db8500_vape_reg: db8500_vape {
-					regulator-compatible = "db8500_vape";
-					regulator-name = "db8500-vape";
-					regulator-always-on;
-				};
-
-				// DB8500_REGULATOR_VARM
-				db8500_varm_reg: db8500_varm {
-					regulator-compatible = "db8500_varm";
-					regulator-name = "db8500-varm";
-				};
-
-				// DB8500_REGULATOR_VMODEM
-				db8500_vmodem_reg: db8500_vmodem {
-					regulator-compatible = "db8500_vmodem";
-					regulator-name = "db8500-vmodem";
-				};
-
-				// DB8500_REGULATOR_VPLL
-				db8500_vpll_reg: db8500_vpll {
-					regulator-compatible = "db8500_vpll";
-					regulator-name = "db8500-vpll";
-				};
-
-				// DB8500_REGULATOR_VSMPS1
-				db8500_vsmps1_reg: db8500_vsmps1 {
-					regulator-compatible = "db8500_vsmps1";
-					regulator-name = "db8500-vsmps1";
-				};
-
-				// DB8500_REGULATOR_VSMPS2
-				db8500_vsmps2_reg: db8500_vsmps2 {
-					regulator-compatible = "db8500_vsmps2";
-					regulator-name = "db8500-vsmps2";
-				};
-
-				// DB8500_REGULATOR_VSMPS3
-				db8500_vsmps3_reg: db8500_vsmps3 {
-					regulator-compatible = "db8500_vsmps3";
-					regulator-name = "db8500-vsmps3";
-				};
-
-				// DB8500_REGULATOR_VRF1
-				db8500_vrf1_reg: db8500_vrf1 {
-					regulator-compatible = "db8500_vrf1";
-					regulator-name = "db8500-vrf1";
-				};
-
-				// DB8500_REGULATOR_SWITCH_SVAMMDSP
-				db8500_sva_mmdsp_reg: db8500_sva_mmdsp {
-					regulator-compatible = "db8500_sva_mmdsp";
-					regulator-name = "db8500-sva-mmdsp";
-				};
-
-				// DB8500_REGULATOR_SWITCH_SVAMMDSPRET
-				db8500_sva_mmdsp_ret_reg: db8500_sva_mmdsp_ret {
-					regulator-compatible = "db8500_sva_mmdsp_ret";
-					regulator-name = "db8500-sva-mmdsp-ret";
-				};
-
-				// DB8500_REGULATOR_SWITCH_SVAPIPE
-				db8500_sva_pipe_reg: db8500_sva_pipe {
-					regulator-compatible = "db8500_sva_pipe";
-					regulator-name = "db8500_sva_pipe";
-				};
-
-				// DB8500_REGULATOR_SWITCH_SIAMMDSP
-				db8500_sia_mmdsp_reg: db8500_sia_mmdsp {
-					regulator-compatible = "db8500_sia_mmdsp";
-					regulator-name = "db8500_sia_mmdsp";
-				};
-
-				// DB8500_REGULATOR_SWITCH_SIAMMDSPRET
-				db8500_sia_mmdsp_ret_reg: db8500_sia_mmdsp_ret {
-					regulator-name = "db8500-sia-mmdsp-ret";
-				};
-
-				// DB8500_REGULATOR_SWITCH_SIAPIPE
-				db8500_sia_pipe_reg: db8500_sia_pipe {
-					regulator-compatible = "db8500_sia_pipe";
-					regulator-name = "db8500-sia-pipe";
-				};
-
-				// DB8500_REGULATOR_SWITCH_SGA
-				db8500_sga_reg: db8500_sga {
-					regulator-compatible = "db8500_sga";
-					regulator-name = "db8500-sga";
-					vin-supply = <&db8500_vape_reg>;
-				};
-
-				// DB8500_REGULATOR_SWITCH_B2R2_MCDE
-				db8500_b2r2_mcde_reg: db8500_b2r2_mcde {
-					regulator-compatible = "db8500_b2r2_mcde";
-					regulator-name = "db8500-b2r2-mcde";
-					vin-supply = <&db8500_vape_reg>;
-				};
-
-				// DB8500_REGULATOR_SWITCH_ESRAM12
-				db8500_esram12_reg: db8500_esram12 {
-					regulator-compatible = "db8500_esram12";
-					regulator-name = "db8500-esram12";
-				};
-
-				// DB8500_REGULATOR_SWITCH_ESRAM12RET
-				db8500_esram12_ret_reg: db8500_esram12_ret {
-					regulator-compatible = "db8500_esram12_ret";
-					regulator-name = "db8500-esram12-ret";
-				};
-
-				// DB8500_REGULATOR_SWITCH_ESRAM34
-				db8500_esram34_reg: db8500_esram34 {
-					regulator-compatible = "db8500_esram34";
-					regulator-name = "db8500-esram34";
-				};
-
-				// DB8500_REGULATOR_SWITCH_ESRAM34RET
-				db8500_esram34_ret_reg: db8500_esram34_ret {
-					regulator-compatible = "db8500_esram34_ret";
-					regulator-name = "db8500-esram34-ret";
-				};
-			};
-
-			ab8500@5 {
-				compatible = "stericsson,ab8500";
-				reg = <5>; /* mailbox 5 is i2c */
-				interrupts = <0 40 0x4>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-
-				ab8500-rtc {
-					compatible = "stericsson,ab8500-rtc";
-					interrupts = <17 0x4
-					              18 0x4>;
-					interrupt-names = "60S", "ALARM";
-				};
-
-				ab8500-gpadc {
-					compatible = "stericsson,ab8500-gpadc";
-					interrupts = <32 0x4
-						      39 0x4>;
-					interrupt-names = "HW_CONV_END", "SW_CONV_END";
-					vddadc-supply = <&ab8500_ldo_tvout_reg>;
-				};
-
-				ab8500-usb {
-					compatible = "stericsson,ab8500-usb";
-					interrupts = < 90 0x4
-						       96 0x4
-						       14 0x4
-						       15 0x4
-						       79 0x4
-						       74 0x4
-						       75 0x4>;
-					interrupt-names = "ID_WAKEUP_R",
-							  "ID_WAKEUP_F",
-							  "VBUS_DET_F",
-							  "VBUS_DET_R",
-							  "USB_LINK_STATUS",
-							  "USB_ADP_PROBE_PLUG",
-							  "USB_ADP_PROBE_UNPLUG";
-					vddulpivio18-supply = <&ab8500_ldo_initcore_reg>;
-					v-ape-supply = <&db8500_vape_reg>;
-					musb_1v8-supply = <&db8500_vsmps2_reg>;
-				};
-
-				ab8500-ponkey {
-					compatible = "stericsson,ab8500-ponkey";
-					interrupts = <6 0x4
-						      7 0x4>;
-					interrupt-names = "ONKEY_DBF", "ONKEY_DBR";
-				};
-
-				ab8500-sysctrl {
-					compatible = "stericsson,ab8500-sysctrl";
-				};
-
-				ab8500-pwm {
-					compatible = "stericsson,ab8500-pwm";
-				};
-
-				ab8500-debugfs {
-					compatible = "stericsson,ab8500-debug";
-				};
-
-				ab8500-regulators {
-					compatible = "stericsson,ab8500-regulator";
-
-					// supplies to the display/camera
-					ab8500_ldo_aux1_reg: ab8500_ldo_aux1 {
-						regulator-compatible = "ab8500_ldo_aux1";
-						regulator-name = "V-DISPLAY";
-						regulator-min-microvolt = <2500000>;
-						regulator-max-microvolt = <2900000>;
-						regulator-boot-on;
-						/* BUG: If turned off MMC will be affected. */
-						regulator-always-on;
-					};
-
-					// supplies to the on-board eMMC
-					ab8500_ldo_aux2_reg: ab8500_ldo_aux2 {
-						regulator-compatible = "ab8500_ldo_aux2";
-						regulator-name = "V-eMMC1";
-						regulator-min-microvolt = <1100000>;
-						regulator-max-microvolt = <3300000>;
-					};
-
-					// supply for VAUX3; SDcard slots
-					ab8500_ldo_aux3_reg: ab8500_ldo_aux3 {
-						regulator-compatible = "ab8500_ldo_aux3";
-						regulator-name = "V-MMC-SD";
-						regulator-min-microvolt = <1100000>;
-						regulator-max-microvolt = <3300000>;
-					};
-
-					// supply for v-intcore12; VINTCORE12 LDO
-					ab8500_ldo_initcore_reg: ab8500_ldo_initcore {
-						regulator-compatible = "ab8500_ldo_initcore";
-						regulator-name = "V-INTCORE";
-					};
-
-					// supply for tvout; gpadc; TVOUT LDO
-					ab8500_ldo_tvout_reg: ab8500_ldo_tvout {
-						regulator-compatible = "ab8500_ldo_tvout";
-						regulator-name = "V-TVOUT";
-					};
-
-					// supply for ab8500-usb; USB LDO
-					ab8500_ldo_usb_reg: ab8500_ldo_usb {
-						regulator-compatible = "ab8500_ldo_usb";
-						regulator-name = "dummy";
-					};
-
-					// supply for ab8500-vaudio; VAUDIO LDO
-					ab8500_ldo_audio_reg: ab8500_ldo_audio {
-						regulator-compatible = "ab8500_ldo_audio";
-						regulator-name = "V-AUD";
-					};
-
-					// supply for v-anamic1 VAMic1-LDO
-					ab8500_ldo_anamic1_reg: ab8500_ldo_anamic1 {
-						regulator-compatible = "ab8500_ldo_anamic1";
-						regulator-name = "V-AMIC1";
-					};
-
-					// supply for v-amic2; VAMIC2 LDO; reuse constants for AMIC1
-					ab8500_ldo_amamic2_reg: ab8500_ldo_amamic2 {
-						regulator-compatible = "ab8500_ldo_amamic2";
-						regulator-name = "V-AMIC2";
-					};
-
-					// supply for v-dmic; VDMIC LDO
-					ab8500_ldo_dmic_reg: ab8500_ldo_dmic {
-						regulator-compatible = "ab8500_ldo_dmic";
-						regulator-name = "V-DMIC";
-					};
-
-					// supply for U8500 CSI/DSI; VANA LDO
-					ab8500_ldo_ana_reg: ab8500_ldo_ana {
-						regulator-compatible = "ab8500_ldo_ana";
-						regulator-name = "V-CSI/DSI";
-					};
-				};
-			};
-		};
-
-		i2c@80004000 {
-			compatible = "stericsson,db8500-i2c", "st,nomadik-i2c";
-			reg = <0x80004000 0x1000>;
-			interrupts = <0 21 0x4>;
-			#address-cells = <1>;
-			#size-cells = <0>;
-		};
-
-		i2c@80122000 {
-			compatible = "stericsson,db8500-i2c", "st,nomadik-i2c";
-			reg = <0x80122000 0x1000>;
-			interrupts = <0 22 0x4>;
-			#address-cells = <1>;
-			#size-cells = <0>;
-		};
-
-		i2c@80128000 {
-			compatible = "stericsson,db8500-i2c", "st,nomadik-i2c";
-			reg = <0x80128000 0x1000>;
-			interrupts = <0 55 0x4>;
-			#address-cells = <1>;
-			#size-cells = <0>;
-		};
-
-		i2c@80110000 {
-			compatible = "stericsson,db8500-i2c", "st,nomadik-i2c";
-			reg = <0x80110000 0x1000>;
-			interrupts = <0 12 0x4>;
-			#address-cells = <1>;
-			#size-cells = <0>;
-		};
-
-		i2c@8012a000 {
-			compatible = "stericsson,db8500-i2c", "st,nomadik-i2c";
-			reg = <0x8012a000 0x1000>;
-			interrupts = <0 51 0x4>;
-			#address-cells = <1>;
-			#size-cells = <0>;
-		};
-
-		ssp@80002000 {
-			compatible = "arm,pl022", "arm,primecell";
-			reg = <80002000 0x1000>;
-			interrupts = <0 14 0x4>;
-			#address-cells = <1>;
-			#size-cells = <0>;
-			status = "disabled";
-
-			// Add one of these for each child device
-			cs-gpios = <&gpio0 31 0x4 &gpio4 14 0x4 &gpio4 16 0x4
-				    &gpio6 22 0x4 &gpio7 0 0x4>;
-
-		};
-
-		uart@80120000 {
-			compatible = "arm,pl011", "arm,primecell";
-			reg = <0x80120000 0x1000>;
-			interrupts = <0 11 0x4>;
-			status = "disabled";
-		};
-		uart@80121000 {
-			compatible = "arm,pl011", "arm,primecell";
-			reg = <0x80121000 0x1000>;
-			interrupts = <0 19 0x4>;
-			status = "disabled";
-		};
-		uart@80007000 {
-			compatible = "arm,pl011", "arm,primecell";
-			reg = <0x80007000 0x1000>;
-			interrupts = <0 26 0x4>;
-			status = "disabled";
-		};
-
-		sdi@80126000 {
-			compatible = "arm,pl18x", "arm,primecell";
-			reg = <0x80126000 0x1000>;
-			interrupts = <0 60 0x4>;
-			status = "disabled";
-		};
-		sdi@80118000 {
-			compatible = "arm,pl18x", "arm,primecell";
-			reg = <0x80118000 0x1000>;
-			interrupts = <0 50 0x4>;
-			status = "disabled";
-		};
-		sdi@80005000 {
-			compatible = "arm,pl18x", "arm,primecell";
-			reg = <0x80005000 0x1000>;
-			interrupts = <0 41 0x4>;
-			status = "disabled";
-		};
-		sdi@80119000 {
-			compatible = "arm,pl18x", "arm,primecell";
-			reg = <0x80119000 0x1000>;
-			interrupts = <0 59 0x4>;
-			status = "disabled";
-		};
-		sdi@80114000 {
-			compatible = "arm,pl18x", "arm,primecell";
-			reg = <0x80114000 0x1000>;
-			interrupts = <0 99 0x4>;
-			status = "disabled";
-		};
-		sdi@80008000 {
-			compatible = "arm,pl18x", "arm,primecell";
-			reg = <0x80114000 0x1000>;
-			interrupts = <0 100 0x4>;
-			status = "disabled";
-		};
-
-		external-bus@50000000 {
-			compatible = "simple-bus";
-			reg = <0x50000000 0x4000000>;
-			#address-cells = <1>;
-			#size-cells = <1>;
-			ranges = <0 0x50000000 0x4000000>;
-			status = "disabled";
-		};
-	};
-};
diff --git a/arch/arm/boot/dts/dbx5x0.dtsi b/arch/arm/boot/dts/dbx5x0.dtsi
new file mode 100644
index 0000000..748ba7a
--- /dev/null
+++ b/arch/arm/boot/dts/dbx5x0.dtsi
@@ -0,0 +1,649 @@
+/*
+ * Copyright 2012 Linaro Ltd
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+	soc-u9500 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "stericsson,db8500";
+		interrupt-parent = <&intc>;
+		ranges;
+
+		intc: interrupt-controller@a0411000 {
+			compatible = "arm,cortex-a9-gic";
+			#interrupt-cells = <3>;
+			#address-cells = <1>;
+			interrupt-controller;
+			reg = <0xa0411000 0x1000>,
+			      <0xa0410100 0x100>;
+		};
+
+		L2: l2-cache {
+			compatible = "arm,pl310-cache";
+			reg = <0xa0412000 0x1000>;
+			interrupts = <0 13 4>;
+			cache-unified;
+			cache-level = <2>;
+		};
+
+		pmu {
+			compatible = "arm,cortex-a9-pmu";
+			interrupts = <0 7 0x4>;
+		};
+
+		timer@a0410600 {
+			compatible = "arm,cortex-a9-twd-timer";
+			reg = <0xa0410600 0x20>;
+			interrupts = <1 13 0x304>;
+		};
+
+		rtc@80154000 {
+			compatible = "arm,rtc-pl031", "arm,primecell";
+			reg = <0x80154000 0x1000>;
+			interrupts = <0 18 0x4>;
+		};
+
+		gpio0: gpio@8012e000 {
+			compatible = "stericsson,db8500-gpio",
+				"st,nomadik-gpio";
+			reg =  <0x8012e000 0x80>;
+			interrupts = <0 119 0x4>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			st,supports-sleepmode;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-bank = <0>;
+		};
+
+		gpio1: gpio@8012e080 {
+			compatible = "stericsson,db8500-gpio",
+				"st,nomadik-gpio";
+			reg =  <0x8012e080 0x80>;
+			interrupts = <0 120 0x4>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			st,supports-sleepmode;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-bank = <1>;
+		};
+
+		gpio2: gpio@8000e000 {
+			compatible = "stericsson,db8500-gpio",
+				"st,nomadik-gpio";
+			reg =  <0x8000e000 0x80>;
+			interrupts = <0 121 0x4>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			st,supports-sleepmode;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-bank = <2>;
+		};
+
+		gpio3: gpio@8000e080 {
+			compatible = "stericsson,db8500-gpio",
+				"st,nomadik-gpio";
+			reg =  <0x8000e080 0x80>;
+			interrupts = <0 122 0x4>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			st,supports-sleepmode;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-bank = <3>;
+		};
+
+		gpio4: gpio@8000e100 {
+			compatible = "stericsson,db8500-gpio",
+				"st,nomadik-gpio";
+			reg =  <0x8000e100 0x80>;
+			interrupts = <0 123 0x4>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			st,supports-sleepmode;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-bank = <4>;
+		};
+
+		gpio5: gpio@8000e180 {
+			compatible = "stericsson,db8500-gpio",
+				"st,nomadik-gpio";
+			reg =  <0x8000e180 0x80>;
+			interrupts = <0 124 0x4>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			st,supports-sleepmode;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-bank = <5>;
+		};
+
+		gpio6: gpio@8011e000 {
+			compatible = "stericsson,db8500-gpio",
+				"st,nomadik-gpio";
+			reg =  <0x8011e000 0x80>;
+			interrupts = <0 125 0x4>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			st,supports-sleepmode;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-bank = <6>;
+		};
+
+		gpio7: gpio@8011e080 {
+			compatible = "stericsson,db8500-gpio",
+				"st,nomadik-gpio";
+			reg =  <0x8011e080 0x80>;
+			interrupts = <0 126 0x4>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			st,supports-sleepmode;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-bank = <7>;
+		};
+
+		gpio8: gpio@a03fe000 {
+			compatible = "stericsson,db8500-gpio",
+				"st,nomadik-gpio";
+			reg =  <0xa03fe000 0x80>;
+			interrupts = <0 127 0x4>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			st,supports-sleepmode;
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-bank = <8>;
+		};
+
+		pinctrl {
+			compatible = "stericsson,nmk_pinctrl";
+		};
+
+		usb@a03e0000 {
+			compatible = "stericsson,db8500-musb",
+				"mentor,musb";
+			reg = <0xa03e0000 0x10000>;
+			interrupts = <0 23 0x4>;
+		};
+
+		dma-controller@801C0000 {
+			compatible = "stericsson,db8500-dma40",
+					"stericsson,dma40";
+			reg = <0x801C0000 0x1000 0x40010000 0x800>;
+			interrupts = <0 25 0x4>;
+		};
+
+		prcmu@80157000 {
+			compatible = "stericsson,db8500-prcmu";
+			reg = <0x80157000 0x1000>;
+			interrupts = <0 47 0x4>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			ranges;
+
+			prcmu-timer-4@80157450 {
+				compatible = "stericsson,db8500-prcmu-timer-4";
+				reg = <0x80157450 0xC>;
+			};
+
+			db8500-prcmu-regulators {
+				compatible = "stericsson,db8500-prcmu-regulator";
+
+				// DB8500_REGULATOR_VAPE
+				db8500_vape_reg: db8500_vape {
+					regulator-compatible = "db8500_vape";
+					regulator-name = "db8500-vape";
+					regulator-always-on;
+				};
+
+				// DB8500_REGULATOR_VARM
+				db8500_varm_reg: db8500_varm {
+					regulator-compatible = "db8500_varm";
+					regulator-name = "db8500-varm";
+				};
+
+				// DB8500_REGULATOR_VMODEM
+				db8500_vmodem_reg: db8500_vmodem {
+					regulator-compatible = "db8500_vmodem";
+					regulator-name = "db8500-vmodem";
+				};
+
+				// DB8500_REGULATOR_VPLL
+				db8500_vpll_reg: db8500_vpll {
+					regulator-compatible = "db8500_vpll";
+					regulator-name = "db8500-vpll";
+				};
+
+				// DB8500_REGULATOR_VSMPS1
+				db8500_vsmps1_reg: db8500_vsmps1 {
+					regulator-compatible = "db8500_vsmps1";
+					regulator-name = "db8500-vsmps1";
+				};
+
+				// DB8500_REGULATOR_VSMPS2
+				db8500_vsmps2_reg: db8500_vsmps2 {
+					regulator-compatible = "db8500_vsmps2";
+					regulator-name = "db8500-vsmps2";
+				};
+
+				// DB8500_REGULATOR_VSMPS3
+				db8500_vsmps3_reg: db8500_vsmps3 {
+					regulator-compatible = "db8500_vsmps3";
+					regulator-name = "db8500-vsmps3";
+				};
+
+				// DB8500_REGULATOR_VRF1
+				db8500_vrf1_reg: db8500_vrf1 {
+					regulator-compatible = "db8500_vrf1";
+					regulator-name = "db8500-vrf1";
+				};
+
+				// DB8500_REGULATOR_SWITCH_SVAMMDSP
+				db8500_sva_mmdsp_reg: db8500_sva_mmdsp {
+					regulator-compatible = "db8500_sva_mmdsp";
+					regulator-name = "db8500-sva-mmdsp";
+				};
+
+				// DB8500_REGULATOR_SWITCH_SVAMMDSPRET
+				db8500_sva_mmdsp_ret_reg: db8500_sva_mmdsp_ret {
+					regulator-compatible = "db8500_sva_mmdsp_ret";
+					regulator-name = "db8500-sva-mmdsp-ret";
+				};
+
+				// DB8500_REGULATOR_SWITCH_SVAPIPE
+				db8500_sva_pipe_reg: db8500_sva_pipe {
+					regulator-compatible = "db8500_sva_pipe";
+					regulator-name = "db8500_sva_pipe";
+				};
+
+				// DB8500_REGULATOR_SWITCH_SIAMMDSP
+				db8500_sia_mmdsp_reg: db8500_sia_mmdsp {
+					regulator-compatible = "db8500_sia_mmdsp";
+					regulator-name = "db8500_sia_mmdsp";
+				};
+
+				// DB8500_REGULATOR_SWITCH_SIAMMDSPRET
+				db8500_sia_mmdsp_ret_reg: db8500_sia_mmdsp_ret {
+					regulator-name = "db8500-sia-mmdsp-ret";
+				};
+
+				// DB8500_REGULATOR_SWITCH_SIAPIPE
+				db8500_sia_pipe_reg: db8500_sia_pipe {
+					regulator-compatible = "db8500_sia_pipe";
+					regulator-name = "db8500-sia-pipe";
+				};
+
+				// DB8500_REGULATOR_SWITCH_SGA
+				db8500_sga_reg: db8500_sga {
+					regulator-compatible = "db8500_sga";
+					regulator-name = "db8500-sga";
+					vin-supply = <&db8500_vape_reg>;
+				};
+
+				// DB8500_REGULATOR_SWITCH_B2R2_MCDE
+				db8500_b2r2_mcde_reg: db8500_b2r2_mcde {
+					regulator-compatible = "db8500_b2r2_mcde";
+					regulator-name = "db8500-b2r2-mcde";
+					vin-supply = <&db8500_vape_reg>;
+				};
+
+				// DB8500_REGULATOR_SWITCH_ESRAM12
+				db8500_esram12_reg: db8500_esram12 {
+					regulator-compatible = "db8500_esram12";
+					regulator-name = "db8500-esram12";
+				};
+
+				// DB8500_REGULATOR_SWITCH_ESRAM12RET
+				db8500_esram12_ret_reg: db8500_esram12_ret {
+					regulator-compatible = "db8500_esram12_ret";
+					regulator-name = "db8500-esram12-ret";
+				};
+
+				// DB8500_REGULATOR_SWITCH_ESRAM34
+				db8500_esram34_reg: db8500_esram34 {
+					regulator-compatible = "db8500_esram34";
+					regulator-name = "db8500-esram34";
+				};
+
+				// DB8500_REGULATOR_SWITCH_ESRAM34RET
+				db8500_esram34_ret_reg: db8500_esram34_ret {
+					regulator-compatible = "db8500_esram34_ret";
+					regulator-name = "db8500-esram34-ret";
+				};
+			};
+
+			ab8500@5 {
+				compatible = "stericsson,ab8500";
+				reg = <5>; /* mailbox 5 is i2c */
+				interrupt-parent = <&intc>;
+				interrupts = <0 40 0x4>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+
+				ab8500-rtc {
+					compatible = "stericsson,ab8500-rtc";
+					interrupts = <17 0x4
+					              18 0x4>;
+					interrupt-names = "60S", "ALARM";
+				};
+
+				ab8500-gpadc {
+					compatible = "stericsson,ab8500-gpadc";
+					interrupts = <32 0x4
+						      39 0x4>;
+					interrupt-names = "HW_CONV_END", "SW_CONV_END";
+					vddadc-supply = <&ab8500_ldo_tvout_reg>;
+				};
+
+				ab8500-usb {
+					compatible = "stericsson,ab8500-usb";
+					interrupts = < 90 0x4
+						       96 0x4
+						       14 0x4
+						       15 0x4
+						       79 0x4
+						       74 0x4
+						       75 0x4>;
+					interrupt-names = "ID_WAKEUP_R",
+							  "ID_WAKEUP_F",
+							  "VBUS_DET_F",
+							  "VBUS_DET_R",
+							  "USB_LINK_STATUS",
+							  "USB_ADP_PROBE_PLUG",
+							  "USB_ADP_PROBE_UNPLUG";
+					vddulpivio18-supply = <&ab8500_ldo_initcore_reg>;
+					v-ape-supply = <&db8500_vape_reg>;
+					musb_1v8-supply = <&db8500_vsmps2_reg>;
+				};
+
+				ab8500-ponkey {
+					compatible = "stericsson,ab8500-poweron-key";
+					interrupts = <6 0x4
+						      7 0x4>;
+					interrupt-names = "ONKEY_DBF", "ONKEY_DBR";
+				};
+
+				ab8500-sysctrl {
+					compatible = "stericsson,ab8500-sysctrl";
+				};
+
+				ab8500-pwm {
+					compatible = "stericsson,ab8500-pwm";
+				};
+
+				ab8500-debugfs {
+					compatible = "stericsson,ab8500-debug";
+				};
+
+				codec: ab8500-codec {
+					compatible = "stericsson,ab8500-codec";
+
+					stericsson,earpeice-cmv = <950>; /* Units in mV. */
+				};
+
+				ab8500-regulators {
+					compatible = "stericsson,ab8500-regulator";
+
+					// supplies to the display/camera
+					ab8500_ldo_aux1_reg: ab8500_ldo_aux1 {
+						regulator-compatible = "ab8500_ldo_aux1";
+						regulator-name = "V-DISPLAY";
+						regulator-min-microvolt = <2500000>;
+						regulator-max-microvolt = <2900000>;
+						regulator-boot-on;
+						/* BUG: If turned off MMC will be affected. */
+						regulator-always-on;
+					};
+
+					// supplies to the on-board eMMC
+					ab8500_ldo_aux2_reg: ab8500_ldo_aux2 {
+						regulator-compatible = "ab8500_ldo_aux2";
+						regulator-name = "V-eMMC1";
+						regulator-min-microvolt = <1100000>;
+						regulator-max-microvolt = <3300000>;
+					};
+
+					// supply for VAUX3; SDcard slots
+					ab8500_ldo_aux3_reg: ab8500_ldo_aux3 {
+						regulator-compatible = "ab8500_ldo_aux3";
+						regulator-name = "V-MMC-SD";
+						regulator-min-microvolt = <1100000>;
+						regulator-max-microvolt = <3300000>;
+					};
+
+					// supply for v-intcore12; VINTCORE12 LDO
+					ab8500_ldo_initcore_reg: ab8500_ldo_initcore {
+						regulator-compatible = "ab8500_ldo_initcore";
+						regulator-name = "V-INTCORE";
+					};
+
+					// supply for tvout; gpadc; TVOUT LDO
+					ab8500_ldo_tvout_reg: ab8500_ldo_tvout {
+						regulator-compatible = "ab8500_ldo_tvout";
+						regulator-name = "V-TVOUT";
+					};
+
+					// supply for ab8500-usb; USB LDO
+					ab8500_ldo_usb_reg: ab8500_ldo_usb {
+						regulator-compatible = "ab8500_ldo_usb";
+						regulator-name = "dummy";
+					};
+
+					// supply for ab8500-vaudio; VAUDIO LDO
+					ab8500_ldo_audio_reg: ab8500_ldo_audio {
+						regulator-compatible = "ab8500_ldo_audio";
+						regulator-name = "V-AUD";
+					};
+
+					// supply for v-anamic1 VAMic1-LDO
+					ab8500_ldo_anamic1_reg: ab8500_ldo_anamic1 {
+						regulator-compatible = "ab8500_ldo_anamic1";
+						regulator-name = "V-AMIC1";
+					};
+
+					// supply for v-amic2; VAMIC2 LDO; reuse constants for AMIC1
+					ab8500_ldo_amamic2_reg: ab8500_ldo_amamic2 {
+						regulator-compatible = "ab8500_ldo_amamic2";
+						regulator-name = "V-AMIC2";
+					};
+
+					// supply for v-dmic; VDMIC LDO
+					ab8500_ldo_dmic_reg: ab8500_ldo_dmic {
+						regulator-compatible = "ab8500_ldo_dmic";
+						regulator-name = "V-DMIC";
+					};
+
+					// supply for U8500 CSI/DSI; VANA LDO
+					ab8500_ldo_ana_reg: ab8500_ldo_ana {
+						regulator-compatible = "ab8500_ldo_ana";
+						regulator-name = "V-CSI/DSI";
+					};
+				};
+			};
+		};
+
+		i2c@80004000 {
+			compatible = "stericsson,db8500-i2c", "st,nomadik-i2c", "arm,primecell";
+			reg = <0x80004000 0x1000>;
+			interrupts = <0 21 0x4>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			v-i2c-supply = <&db8500_vape_reg>;
+
+			clock-frequency = <400000>;
+		};
+
+		i2c@80122000 {
+			compatible = "stericsson,db8500-i2c", "st,nomadik-i2c", "arm,primecell";
+			reg = <0x80122000 0x1000>;
+			interrupts = <0 22 0x4>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			v-i2c-supply = <&db8500_vape_reg>;
+
+			clock-frequency = <400000>;
+		};
+
+		i2c@80128000 {
+			compatible = "stericsson,db8500-i2c", "st,nomadik-i2c", "arm,primecell";
+			reg = <0x80128000 0x1000>;
+			interrupts = <0 55 0x4>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			v-i2c-supply = <&db8500_vape_reg>;
+
+			clock-frequency = <400000>;
+		};
+
+		i2c@80110000 {
+			compatible = "stericsson,db8500-i2c", "st,nomadik-i2c", "arm,primecell";
+			reg = <0x80110000 0x1000>;
+			interrupts = <0 12 0x4>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			v-i2c-supply = <&db8500_vape_reg>;
+
+			clock-frequency = <400000>;
+		};
+
+		i2c@8012a000 {
+			compatible = "stericsson,db8500-i2c", "st,nomadik-i2c", "arm,primecell";
+			reg = <0x8012a000 0x1000>;
+			interrupts = <0 51 0x4>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			v-i2c-supply = <&db8500_vape_reg>;
+
+			clock-frequency = <400000>;
+		};
+
+		ssp@80002000 {
+			compatible = "arm,pl022", "arm,primecell";
+			reg = <0x80002000 0x1000>;
+			interrupts = <0 14 0x4>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+
+			// Add one of these for each child device
+			cs-gpios = <&gpio0 31 0x4 &gpio4 14 0x4 &gpio4 16 0x4
+				    &gpio6 22 0x4 &gpio7 0 0x4>;
+
+		};
+
+		uart@80120000 {
+			compatible = "arm,pl011", "arm,primecell";
+			reg = <0x80120000 0x1000>;
+			interrupts = <0 11 0x4>;
+			status = "disabled";
+		};
+		uart@80121000 {
+			compatible = "arm,pl011", "arm,primecell";
+			reg = <0x80121000 0x1000>;
+			interrupts = <0 19 0x4>;
+			status = "disabled";
+		};
+		uart@80007000 {
+			compatible = "arm,pl011", "arm,primecell";
+			reg = <0x80007000 0x1000>;
+			interrupts = <0 26 0x4>;
+			status = "disabled";
+		};
+
+		sdi@80126000 {
+			compatible = "arm,pl18x", "arm,primecell";
+			reg = <0x80126000 0x1000>;
+			interrupts = <0 60 0x4>;
+			status = "disabled";
+		};
+		sdi@80118000 {
+			compatible = "arm,pl18x", "arm,primecell";
+			reg = <0x80118000 0x1000>;
+			interrupts = <0 50 0x4>;
+			status = "disabled";
+		};
+		sdi@80005000 {
+			compatible = "arm,pl18x", "arm,primecell";
+			reg = <0x80005000 0x1000>;
+			interrupts = <0 41 0x4>;
+			status = "disabled";
+		};
+		sdi@80119000 {
+			compatible = "arm,pl18x", "arm,primecell";
+			reg = <0x80119000 0x1000>;
+			interrupts = <0 59 0x4>;
+			status = "disabled";
+		};
+		sdi@80114000 {
+			compatible = "arm,pl18x", "arm,primecell";
+			reg = <0x80114000 0x1000>;
+			interrupts = <0 99 0x4>;
+			status = "disabled";
+		};
+		sdi@80008000 {
+			compatible = "arm,pl18x", "arm,primecell";
+			reg = <0x80114000 0x1000>;
+			interrupts = <0 100 0x4>;
+			status = "disabled";
+		};
+
+		msp0: msp@80123000 {
+			compatible = "stericsson,ux500-msp-i2s";
+			reg = <0x80123000 0x1000>;
+			interrupts = <0 31 0x4>;
+			v-ape-supply = <&db8500_vape_reg>;
+			status = "disabled";
+		};
+
+		msp1: msp@80124000 {
+			compatible = "stericsson,ux500-msp-i2s";
+			reg = <0x80124000 0x1000>;
+			interrupts = <0 62 0x4>;
+			v-ape-supply = <&db8500_vape_reg>;
+			status = "disabled";
+		};
+
+		// HDMI sound
+		msp2: msp@80117000 {
+			compatible = "stericsson,ux500-msp-i2s";
+			reg = <0x80117000 0x1000>;
+			interrupts = <0 98 0x4>;
+			v-ape-supply = <&db8500_vape_reg>;
+			status = "disabled";
+		};
+
+		msp3: msp@80125000 {
+			compatible = "stericsson,ux500-msp-i2s";
+			reg = <0x80125000 0x1000>;
+			interrupts = <0 62 0x4>;
+			v-ape-supply = <&db8500_vape_reg>;
+			status = "disabled";
+		};
+
+		external-bus@50000000 {
+			compatible = "simple-bus";
+			reg = <0x50000000 0x4000000>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 0x50000000 0x4000000>;
+			status = "disabled";
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/dove-cm-a510.dts b/arch/arm/boot/dts/dove-cm-a510.dts
new file mode 100644
index 0000000..61a8062
--- /dev/null
+++ b/arch/arm/boot/dts/dove-cm-a510.dts
@@ -0,0 +1,38 @@
+/dts-v1/;
+
+/include/ "dove.dtsi"
+
+/ {
+	model = "Compulab CM-A510";
+	compatible = "compulab,cm-a510", "marvell,dove";
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x40000000>;
+	};
+
+	chosen {
+		bootargs = "console=ttyS0,115200n8 earlyprintk";
+	};
+};
+
+&uart0 { status = "okay"; };
+&uart1 { status = "okay"; };
+&sdio0 { status = "okay"; };
+&sdio1 { status = "okay"; };
+&sata0 { status = "okay"; };
+
+&spi0 {
+	status = "okay";
+
+	/* spi0.0: 4M Flash Winbond W25Q32BV */
+	spi-flash@0 {
+		compatible = "st,w25q32";
+		spi-max-frequency = <20000000>;
+		reg = <0>;
+	};
+};
+
+&i2c0 {
+	  status = "okay";
+};
diff --git a/arch/arm/boot/dts/dove-cubox.dts b/arch/arm/boot/dts/dove-cubox.dts
new file mode 100644
index 0000000..0adbd5a
--- /dev/null
+++ b/arch/arm/boot/dts/dove-cubox.dts
@@ -0,0 +1,42 @@
+/dts-v1/;
+
+/include/ "dove.dtsi"
+
+/ {
+	model = "SolidRun CuBox";
+	compatible = "solidrun,cubox", "marvell,dove";
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x40000000>;
+	};
+
+	chosen {
+		bootargs = "console=ttyS0,115200n8 earlyprintk";
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		power {
+			label = "Power";
+			gpios = <&gpio0 18 1>;
+			linux,default-trigger = "default-on";
+		};
+	};
+};
+
+&uart0 { status = "okay"; };
+&sdio0 { status = "okay"; };
+&sata0 { status = "okay"; };
+&i2c0 { status = "okay"; };
+
+&spi0 {
+	status = "okay";
+
+	/* spi0.0: 4M Flash Winbond W25Q32BV */
+	spi-flash@0 {
+		compatible = "st,w25q32";
+		spi-max-frequency = <20000000>;
+		reg = <0>;
+	};
+};
diff --git a/arch/arm/boot/dts/dove-dove-db.dts b/arch/arm/boot/dts/dove-dove-db.dts
new file mode 100644
index 0000000..e5a920b
--- /dev/null
+++ b/arch/arm/boot/dts/dove-dove-db.dts
@@ -0,0 +1,38 @@
+/dts-v1/;
+
+/include/ "dove.dtsi"
+
+/ {
+	model = "Marvell DB-MV88AP510-BP Development Board";
+	compatible = "marvell,dove-db", "marvell,dove";
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x40000000>;
+	};
+
+	chosen {
+		bootargs = "console=ttyS0,115200n8 earlyprintk";
+	};
+};
+
+&uart0 { status = "okay"; };
+&uart1 { status = "okay"; };
+&sdio0 { status = "okay"; };
+&sdio1 { status = "okay"; };
+&sata0 { status = "okay"; };
+
+&spi0 {
+	status = "okay";
+
+	/* spi0.0: 4M Flash ST-M25P32-VMF6P */
+	spi-flash@0 {
+		compatible = "st,m25p32";
+		spi-max-frequency = <20000000>;
+		reg = <0>;
+	};
+};
+
+&i2c0 {
+	  status = "okay";
+};
diff --git a/arch/arm/boot/dts/dove.dtsi b/arch/arm/boot/dts/dove.dtsi
new file mode 100644
index 0000000..96fb824
--- /dev/null
+++ b/arch/arm/boot/dts/dove.dtsi
@@ -0,0 +1,143 @@
+/include/ "skeleton.dtsi"
+
+/ {
+	compatible = "marvell,dove";
+	model = "Marvell Armada 88AP510 SoC";
+
+	interrupt-parent = <&intc>;
+
+	intc: interrupt-controller {
+		compatible = "marvell,orion-intc";
+		interrupt-controller;
+		#interrupt-cells = <1>;
+		reg = <0xf1020204 0x04>,
+		      <0xf1020214 0x04>;
+	};
+
+	mbus@f1000000 {
+		compatible = "simple-bus";
+		ranges = <0 0xf1000000 0x4000000>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		uart0: serial@12000 {
+			compatible = "ns16550a";
+			reg = <0x12000 0x100>;
+			reg-shift = <2>;
+			interrupts = <7>;
+			clock-frequency = <166666667>;
+			status = "disabled";
+		};
+
+		uart1: serial@12100 {
+			compatible = "ns16550a";
+			reg = <0x12100 0x100>;
+			reg-shift = <2>;
+			interrupts = <8>;
+			clock-frequency = <166666667>;
+			status = "disabled";
+		};
+
+		uart2: serial@12200 {
+			compatible = "ns16550a";
+			reg = <0x12000 0x100>;
+			reg-shift = <2>;
+			interrupts = <9>;
+			clock-frequency = <166666667>;
+			status = "disabled";
+		};
+
+		uart3: serial@12300 {
+			compatible = "ns16550a";
+			reg = <0x12100 0x100>;
+			reg-shift = <2>;
+			interrupts = <10>;
+			clock-frequency = <166666667>;
+			status = "disabled";
+		};
+
+		wdt: wdt@20300 {
+			compatible = "marvell,orion-wdt";
+			reg = <0x20300 0x28>;
+		};
+
+		gpio0: gpio@d0400 {
+			compatible = "marvell,orion-gpio";
+			#gpio-cells = <2>;
+			gpio-controller;
+			reg = <0xd0400 0x20>;
+			ngpio = <32>;
+			interrupts = <12>, <13>, <14>, <60>;
+		};
+
+		gpio1: gpio@d0420 {
+			compatible = "marvell,orion-gpio";
+			#gpio-cells = <2>;
+			gpio-controller;
+			reg = <0xd0420 0x20>;
+			ngpio = <32>;
+			interrupts = <61>;
+		};
+
+		gpio2: gpio@e8400 {
+			compatible = "marvell,orion-gpio";
+			#gpio-cells = <2>;
+			gpio-controller;
+			reg = <0xe8400 0x0c>;
+			ngpio = <8>;
+		};
+
+		spi0: spi@10600 {
+			compatible = "marvell,orion-spi";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <0>;
+			interrupts = <6>;
+			reg = <0x10600 0x28>;
+			status = "disabled";
+		};
+
+		spi1: spi@14600 {
+			compatible = "marvell,orion-spi";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <1>;
+			interrupts = <5>;
+			reg = <0x14600 0x28>;
+			status = "disabled";
+		};
+
+		i2c0: i2c@11000 {
+			compatible = "marvell,mv64xxx-i2c";
+			reg = <0x11000 0x20>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupts = <11>;
+			clock-frequency = <400000>;
+			timeout-ms = <1000>;
+			status = "disabled";
+		};
+
+		sdio0: sdio@92000 {
+			compatible = "marvell,dove-sdhci";
+			reg = <0x92000 0x100>;
+			interrupts = <35>, <37>;
+			status = "disabled";
+		};
+
+		sdio1: sdio@90000 {
+			compatible = "marvell,dove-sdhci";
+			reg = <0x90000 0x100>;
+			interrupts = <36>, <38>;
+			status = "disabled";
+		};
+
+		sata0: sata@a0000 {
+			compatible = "marvell,orion-sata";
+			reg = <0xa0000 0x2400>;
+			interrupts = <62>;
+			nr-ports = <1>;
+			status = "disabled";
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/ea3250.dts b/arch/arm/boot/dts/ea3250.dts
index d79b28d..a4ba31b 100644
--- a/arch/arm/boot/dts/ea3250.dts
+++ b/arch/arm/boot/dts/ea3250.dts
@@ -166,9 +166,116 @@
 		#size-cells = <0>;
 		autorepeat;
 		button@21 {
-			label = "GPIO Key UP";
+			label = "Interrupt Key";
 			linux,code = <103>;
 			gpios = <&gpio 4 1 0>; /* GPI_P3 1 */
 		};
+		key1 {
+			label = "KEY1";
+			linux,code = <1>;
+			gpios = <&pca9532 0 0>;
+		};
+		key2 {
+			label = "KEY2";
+			linux,code = <2>;
+			gpios = <&pca9532 1 0>;
+		};
+		key3 {
+			label = "KEY3";
+			linux,code = <3>;
+			gpios = <&pca9532 2 0>;
+		};
+		key4 {
+			label = "KEY4";
+			linux,code = <4>;
+			gpios = <&pca9532 3 0>;
+		};
+		joy0 {
+			label = "Joystick Key 0";
+			linux,code = <10>;
+			gpios = <&gpio 2 0 0>; /* P2.0 */
+		};
+		joy1 {
+			label = "Joystick Key 1";
+			linux,code = <11>;
+			gpios = <&gpio 2 1 0>; /* P2.1 */
+		};
+		joy2 {
+			label = "Joystick Key 2";
+			linux,code = <12>;
+			gpios = <&gpio 2 2 0>; /* P2.2 */
+		};
+		joy3 {
+			label = "Joystick Key 3";
+			linux,code = <13>;
+			gpios = <&gpio 2 3 0>; /* P2.3 */
+		};
+		joy4 {
+			label = "Joystick Key 4";
+			linux,code = <14>;
+			gpios = <&gpio 2 4 0>; /* P2.4 */
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		/* LEDs on OEM Board */
+
+		led1 {
+			gpios = <&gpio 5 14 1>; /* GPO_P3 14, GPIO 93, active low */
+			linux,default-trigger = "timer";
+			default-state = "off";
+		};
+
+		led2 {
+			gpios = <&gpio 2 10 1>; /* P2.10, active low */
+			default-state = "off";
+		};
+
+		led3 {
+			gpios = <&gpio 2 11 1>; /* P2.11, active low */
+			default-state = "off";
+		};
+
+		led4 {
+			gpios = <&gpio 2 12 1>; /* P2.12, active low */
+			default-state = "off";
+		};
+
+		/* LEDs on Base Board */
+
+		lede1 {
+			gpios = <&pca9532 8 0>;
+			default-state = "off";
+		};
+		lede2 {
+			gpios = <&pca9532 9 0>;
+			default-state = "off";
+		};
+		lede3 {
+			gpios = <&pca9532 10 0>;
+			default-state = "off";
+		};
+		lede4 {
+			gpios = <&pca9532 11 0>;
+			default-state = "off";
+		};
+		lede5 {
+			gpios = <&pca9532 12 0>;
+			default-state = "off";
+		};
+		lede6 {
+			gpios = <&pca9532 13 0>;
+			default-state = "off";
+		};
+		lede7 {
+			gpios = <&pca9532 14 0>;
+			default-state = "off";
+		};
+		lede8 {
+			gpios = <&pca9532 15 0>;
+			default-state = "off";
+		};
 	};
 };
diff --git a/arch/arm/boot/dts/elpida_ecb240abacn.dtsi b/arch/arm/boot/dts/elpida_ecb240abacn.dtsi
new file mode 100644
index 0000000..f97f70f
--- /dev/null
+++ b/arch/arm/boot/dts/elpida_ecb240abacn.dtsi
@@ -0,0 +1,67 @@
+/*
+ * Common devices used in different OMAP boards
+ */
+
+/ {
+	elpida_ECB240ABACN: lpddr2 {
+		compatible	= "Elpida,ECB240ABACN","jedec,lpddr2-s4";
+		density		= <2048>;
+		io-width	= <32>;
+
+		tRPab-min-tck	= <3>;
+		tRCD-min-tck	= <3>;
+		tWR-min-tck	= <3>;
+		tRASmin-min-tck	= <3>;
+		tRRD-min-tck	= <2>;
+		tWTR-min-tck	= <2>;
+		tXP-min-tck	= <2>;
+		tRTP-min-tck	= <2>;
+		tCKE-min-tck	= <3>;
+		tCKESR-min-tck	= <3>;
+		tFAW-min-tck	= <8>;
+
+		timings_elpida_ECB240ABACN_400mhz: lpddr2-timings@0 {
+			compatible	= "jedec,lpddr2-timings";
+			min-freq	= <10000000>;
+			max-freq	= <400000000>;
+			tRPab		= <21000>;
+			tRCD		= <18000>;
+			tWR		= <15000>;
+			tRAS-min	= <42000>;
+			tRRD		= <10000>;
+			tWTR		= <7500>;
+			tXP		= <7500>;
+			tRTP		= <7500>;
+			tCKESR		= <15000>;
+			tDQSCK-max	= <5500>;
+			tFAW		= <50000>;
+			tZQCS		= <90000>;
+			tZQCL		= <360000>;
+			tZQinit		= <1000000>;
+			tRAS-max-ns	= <70000>;
+			tDQSCK-max-derated = <6000>;
+		};
+
+		timings_elpida_ECB240ABACN_200mhz: lpddr2-timings@1 {
+			compatible	= "jedec,lpddr2-timings";
+			min-freq	= <10000000>;
+			max-freq	= <200000000>;
+			tRPab		= <21000>;
+			tRCD		= <18000>;
+			tWR		= <15000>;
+			tRAS-min	= <42000>;
+			tRRD		= <10000>;
+			tWTR		= <10000>;
+			tXP		= <7500>;
+			tRTP		= <7500>;
+			tCKESR		= <15000>;
+			tDQSCK-max	= <5500>;
+			tFAW		= <50000>;
+			tZQCS		= <90000>;
+			tZQCL		= <360000>;
+			tZQinit		= <1000000>;
+			tRAS-max-ns	= <70000>;
+			tDQSCK-max-derated = <6000>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/exynos4.dtsi b/arch/arm/boot/dts/exynos4.dtsi
new file mode 100644
index 0000000..a26c3dd
--- /dev/null
+++ b/arch/arm/boot/dts/exynos4.dtsi
@@ -0,0 +1,248 @@
+/*
+ * Samsung's Exynos4 SoC series common device tree source
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ * Copyright (c) 2010-2011 Linaro Ltd.
+ *		www.linaro.org
+ *
+ * Samsung's Exynos4 SoC series device nodes are listed in this file.  Particular
+ * SoCs from Exynos4 series can include this file and provide values for SoCs
+ * specfic bindings.
+ *
+ * Note: This file does not include device nodes for all the controllers in
+ * Exynos4 SoCs. As device tree coverage for Exynos4 increases, additional
+ * nodes can be added to this file.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+	interrupt-parent = <&gic>;
+
+	aliases {
+		spi0 = &spi_0;
+		spi1 = &spi_1;
+		spi2 = &spi_2;
+	};
+
+	gic:interrupt-controller@10490000 {
+		compatible = "arm,cortex-a9-gic";
+		#interrupt-cells = <3>;
+		interrupt-controller;
+		reg = <0x10490000 0x1000>, <0x10480000 0x100>;
+	};
+
+	combiner:interrupt-controller@10440000 {
+		compatible = "samsung,exynos4210-combiner";
+		#interrupt-cells = <2>;
+		interrupt-controller;
+		reg = <0x10440000 0x1000>;
+	};
+
+	watchdog@10060000 {
+		compatible = "samsung,s3c2410-wdt";
+		reg = <0x10060000 0x100>;
+		interrupts = <0 43 0>;
+		status = "disabled";
+	};
+
+	rtc@10070000 {
+		compatible = "samsung,s3c6410-rtc";
+		reg = <0x10070000 0x100>;
+		interrupts = <0 44 0>, <0 45 0>;
+		status = "disabled";
+	};
+
+	keypad@100A0000 {
+		compatible = "samsung,s5pv210-keypad";
+		reg = <0x100A0000 0x100>;
+		interrupts = <0 109 0>;
+		status = "disabled";
+	};
+
+	sdhci@12510000 {
+		compatible = "samsung,exynos4210-sdhci";
+		reg = <0x12510000 0x100>;
+		interrupts = <0 73 0>;
+		status = "disabled";
+	};
+
+	sdhci@12520000 {
+		compatible = "samsung,exynos4210-sdhci";
+		reg = <0x12520000 0x100>;
+		interrupts = <0 74 0>;
+		status = "disabled";
+	};
+
+	sdhci@12530000 {
+		compatible = "samsung,exynos4210-sdhci";
+		reg = <0x12530000 0x100>;
+		interrupts = <0 75 0>;
+		status = "disabled";
+	};
+
+	sdhci@12540000 {
+		compatible = "samsung,exynos4210-sdhci";
+		reg = <0x12540000 0x100>;
+		interrupts = <0 76 0>;
+		status = "disabled";
+	};
+
+	serial@13800000 {
+		compatible = "samsung,exynos4210-uart";
+		reg = <0x13800000 0x100>;
+		interrupts = <0 52 0>;
+		status = "disabled";
+	};
+
+	serial@13810000 {
+		compatible = "samsung,exynos4210-uart";
+		reg = <0x13810000 0x100>;
+		interrupts = <0 53 0>;
+		status = "disabled";
+	};
+
+	serial@13820000 {
+		compatible = "samsung,exynos4210-uart";
+		reg = <0x13820000 0x100>;
+		interrupts = <0 54 0>;
+		status = "disabled";
+	};
+
+	serial@13830000 {
+		compatible = "samsung,exynos4210-uart";
+		reg = <0x13830000 0x100>;
+		interrupts = <0 55 0>;
+		status = "disabled";
+	};
+
+	i2c@13860000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "samsung,s3c2440-i2c";
+		reg = <0x13860000 0x100>;
+		interrupts = <0 58 0>;
+		status = "disabled";
+	};
+
+	i2c@13870000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "samsung,s3c2440-i2c";
+		reg = <0x13870000 0x100>;
+		interrupts = <0 59 0>;
+		status = "disabled";
+	};
+
+	i2c@13880000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "samsung,s3c2440-i2c";
+		reg = <0x13880000 0x100>;
+		interrupts = <0 60 0>;
+		status = "disabled";
+	};
+
+	i2c@13890000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "samsung,s3c2440-i2c";
+		reg = <0x13890000 0x100>;
+		interrupts = <0 61 0>;
+		status = "disabled";
+	};
+
+	i2c@138A0000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "samsung,s3c2440-i2c";
+		reg = <0x138A0000 0x100>;
+		interrupts = <0 62 0>;
+		status = "disabled";
+	};
+
+	i2c@138B0000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "samsung,s3c2440-i2c";
+		reg = <0x138B0000 0x100>;
+		interrupts = <0 63 0>;
+		status = "disabled";
+	};
+
+	i2c@138C0000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "samsung,s3c2440-i2c";
+		reg = <0x138C0000 0x100>;
+		interrupts = <0 64 0>;
+		status = "disabled";
+	};
+
+	i2c@138D0000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "samsung,s3c2440-i2c";
+		reg = <0x138D0000 0x100>;
+		interrupts = <0 65 0>;
+		status = "disabled";
+	};
+
+	spi_0: spi@13920000 {
+		compatible = "samsung,exynos4210-spi";
+		reg = <0x13920000 0x100>;
+		interrupts = <0 66 0>;
+		tx-dma-channel = <&pdma0 7>; /* preliminary */
+		rx-dma-channel = <&pdma0 6>; /* preliminary */
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	spi_1: spi@13930000 {
+		compatible = "samsung,exynos4210-spi";
+		reg = <0x13930000 0x100>;
+		interrupts = <0 67 0>;
+		tx-dma-channel = <&pdma1 7>; /* preliminary */
+		rx-dma-channel = <&pdma1 6>; /* preliminary */
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	spi_2: spi@13940000 {
+		compatible = "samsung,exynos4210-spi";
+		reg = <0x13940000 0x100>;
+		interrupts = <0 68 0>;
+		tx-dma-channel = <&pdma0 9>; /* preliminary */
+		rx-dma-channel = <&pdma0 8>; /* preliminary */
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
+	amba {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "arm,amba-bus";
+		interrupt-parent = <&gic>;
+		ranges;
+
+		pdma0: pdma@12680000 {
+			compatible = "arm,pl330", "arm,primecell";
+			reg = <0x12680000 0x1000>;
+			interrupts = <0 35 0>;
+		};
+
+		pdma1: pdma@12690000 {
+			compatible = "arm,pl330", "arm,primecell";
+			reg = <0x12690000 0x1000>;
+			interrupts = <0 36 0>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/exynos4210-origen.dts b/arch/arm/boot/dts/exynos4210-origen.dts
index 0c49caa..3e68f52 100644
--- a/arch/arm/boot/dts/exynos4210-origen.dts
+++ b/arch/arm/boot/dts/exynos4210-origen.dts
@@ -40,6 +40,7 @@
 			<&gpk2 4 2 3 3>,
 			<&gpk2 5 2 3 3>,
 			<&gpk2 6 2 3 3>;
+		status = "okay";
 	};
 
 	sdhci@12510000 {
@@ -53,6 +54,7 @@
 			<&gpk0 4 2 3 3>,
 			<&gpk0 5 2 3 3>,
 			<&gpk0 6 2 3 3>;
+		status = "okay";
 	};
 
 	gpio_keys {
@@ -62,88 +64,45 @@
 
 		up {
 			label = "Up";
-			gpios = <&gpx2 0 0 0 2>;
+			gpios = <&gpx2 0 0 0x10000 2>;
 			linux,code = <103>;
+			gpio-key,wakeup;
 		};
 
 		down {
 			label = "Down";
-			gpios = <&gpx2 1 0 0 2>;
+			gpios = <&gpx2 1 0 0x10000 2>;
 			linux,code = <108>;
+			gpio-key,wakeup;
 		};
 
 		back {
 			label = "Back";
-			gpios = <&gpx1 7 0 0 2>;
+			gpios = <&gpx1 7 0 0x10000 2>;
 			linux,code = <158>;
+			gpio-key,wakeup;
 		};
 
 		home {
 			label = "Home";
-			gpios = <&gpx1 6 0 0 2>;
+			gpios = <&gpx1 6 0 0x10000 2>;
 			linux,code = <102>;
+			gpio-key,wakeup;
 		};
 
 		menu {
 			label = "Menu";
-			gpios = <&gpx1 5 0 0 2>;
+			gpios = <&gpx1 5 0 0x10000 2>;
 			linux,code = <139>;
+			gpio-key,wakeup;
 		};
 	};
 
-	keypad@100A0000 {
-		status = "disabled";
-	};
-
-	sdhci@12520000 {
-		status = "disabled";
-	};
-
-	sdhci@12540000 {
-		status = "disabled";
-	};
-
-	i2c@13860000 {
-		status = "disabled";
-	};
-
-	i2c@13870000 {
-		status = "disabled";
-	};
-
-	i2c@13880000 {
-		status = "disabled";
-	};
-
-	i2c@13890000 {
-		status = "disabled";
-	};
-
-	i2c@138A0000 {
-		status = "disabled";
-	};
-
-	i2c@138B0000 {
-		status = "disabled";
-	};
-
-	i2c@138C0000 {
-		status = "disabled";
-	};
-
-	i2c@138D0000 {
-		status = "disabled";
-	};
-
-	spi_0: spi@13920000 {
-		status = "disabled";
-	};
-
-	spi_1: spi@13930000 {
-		status = "disabled";
-	};
-
-	spi_2: spi@13940000 {
-		status = "disabled";
+	leds {
+		compatible = "gpio-leds";
+		status {
+			gpios = <&gpx1 3 0 0x10000 2>;
+			linux,default-trigger = "heartbeat";
+		};
 	};
 };
diff --git a/arch/arm/boot/dts/exynos4210-pinctrl.dtsi b/arch/arm/boot/dts/exynos4210-pinctrl.dtsi
new file mode 100644
index 0000000..b12cf27
--- /dev/null
+++ b/arch/arm/boot/dts/exynos4210-pinctrl.dtsi
@@ -0,0 +1,457 @@
+/*
+ * Samsung's Exynos4210 SoC pin-mux and pin-config device tree source
+ *
+ * Copyright (c) 2011-2012 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ * Copyright (c) 2011-2012 Linaro Ltd.
+ *		www.linaro.org
+ *
+ * Samsung's Exynos4210 SoC pin-mux and pin-config optiosn are listed as device
+ * tree nodes are listed in this file.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+/ {
+	pinctrl@11400000 {
+		uart0_data: uart0-data {
+			samsung,pins = "gpa0-0", "gpa0-1";
+			samsung,pin-function = <0x2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		uart0_fctl: uart0-fctl {
+			samsung,pins = "gpa0-2", "gpa0-3";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		uart1_data: uart1-data {
+			samsung,pins = "gpa0-4", "gpa0-5";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		uart1_fctl: uart1-fctl {
+			samsung,pins = "gpa0-6", "gpa0-7";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		i2c2_bus: i2c2-bus {
+			samsung,pins = "gpa0-6", "gpa0-7";
+			samsung,pin-function = <3>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <0>;
+		};
+
+		uart2_data: uart2-data {
+			samsung,pins = "gpa1-0", "gpa1-1";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		uart2_fctl: uart2-fctl {
+			samsung,pins = "gpa1-2", "gpa1-3";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		uart_audio_a: uart-audio-a {
+			samsung,pins = "gpa1-0", "gpa1-1";
+			samsung,pin-function = <4>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		i2c3_bus: i2c3-bus {
+			samsung,pins = "gpa1-2", "gpa1-3";
+			samsung,pin-function = <3>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <0>;
+		};
+
+		uart3_data: uart3-data {
+			samsung,pins = "gpa1-4", "gpa1-5";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		uart_audio_b: uart-audio-b {
+			samsung,pins = "gpa1-4", "gpa1-5";
+			samsung,pin-function = <4>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		spi0_bus: spi0-bus {
+			samsung,pins = "gpb-0", "gpb-2", "gpb-3";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <0>;
+		};
+
+		i2c4_bus: i2c4-bus {
+			samsung,pins = "gpb-2", "gpb-3";
+			samsung,pin-function = <3>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <0>;
+		};
+
+		spi1_bus: spi1-bus {
+			samsung,pins = "gpb-4", "gpb-6", "gpb-7";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <0>;
+		};
+
+		i2c5_bus: i2c5-bus {
+			samsung,pins = "gpb-6", "gpb-7";
+			samsung,pin-function = <3>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <0>;
+		};
+
+		i2s1_bus: i2s1-bus {
+			samsung,pins = "gpc0-0", "gpc0-1", "gpc0-2", "gpc0-3",
+					"gpc0-4";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		pcm1_bus: pcm1-bus {
+			samsung,pins = "gpc0-0", "gpc0-1", "gpc0-2", "gpc0-3",
+					"gpc0-4";
+			samsung,pin-function = <3>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		ac97_bus: ac97-bus {
+			samsung,pins = "gpc0-0", "gpc0-1", "gpc0-2", "gpc0-3",
+					"gpc0-4";
+			samsung,pin-function = <4>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		i2s2_bus: i2s2-bus {
+			samsung,pins = "gpc1-0", "gpc1-1", "gpc1-2", "gpc1-3",
+					"gpc1-4";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		pcm2_bus: pcm2-bus {
+			samsung,pins = "gpc1-0", "gpc1-1", "gpc1-2", "gpc1-3",
+					"gpc1-4";
+			samsung,pin-function = <3>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		spdif_bus: spdif-bus {
+			samsung,pins = "gpc1-0", "gpc1-1";
+			samsung,pin-function = <4>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		i2c6_bus: i2c6-bus {
+			samsung,pins = "gpc1-3", "gpc1-4";
+			samsung,pin-function = <4>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <0>;
+		};
+
+		spi2_bus: spi2-bus {
+			samsung,pins = "gpc1-1", "gpc1-2", "gpc1-3", "gpc1-4";
+			samsung,pin-function = <5>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <0>;
+		};
+
+		i2c7_bus: i2c7-bus {
+			samsung,pins = "gpd0-2", "gpd0-3";
+			samsung,pin-function = <3>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <0>;
+		};
+
+		i2c0_bus: i2c0-bus {
+			samsung,pins = "gpd1-0", "gpd1-1";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <0>;
+		};
+
+		i2c1_bus: i2c1-bus {
+			samsung,pins = "gpd1-2", "gpd1-3";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <0>;
+		};
+	};
+
+	pinctrl@11000000 {
+		sd0_clk: sd0-clk {
+			samsung,pins = "gpk0-0";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		sd0_cmd: sd0-cmd {
+			samsung,pins = "gpk0-1";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		sd0_cd: sd0-cd {
+			samsung,pins = "gpk0-2";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <0>;
+		};
+
+		sd0_bus1: sd0-bus-width1 {
+			samsung,pins = "gpk0-3";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <0>;
+		};
+
+		sd0_bus4: sd0-bus-width4 {
+			samsung,pins = "gpk0-3", "gpk0-4", "gpk0-5", "gpk0-6";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <0>;
+		};
+
+		sd0_bus8: sd0-bus-width8 {
+			samsung,pins = "gpk1-3", "gpk1-4", "gpk1-5", "gpk1-6";
+			samsung,pin-function = <3>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <0>;
+		};
+
+		sd4_clk: sd4-clk {
+			samsung,pins = "gpk0-0";
+			samsung,pin-function = <3>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		sd4_cmd: sd4-cmd {
+			samsung,pins = "gpk0-1";
+			samsung,pin-function = <3>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		sd4_cd: sd4-cd {
+			samsung,pins = "gpk0-2";
+			samsung,pin-function = <3>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <0>;
+		};
+
+		sd4_bus1: sd4-bus-width1 {
+			samsung,pins = "gpk0-3";
+			samsung,pin-function = <3>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <0>;
+		};
+
+		sd4_bus4: sd4-bus-width4 {
+			samsung,pins = "gpk0-3", "gpk0-4", "gpk0-5", "gpk0-6";
+			samsung,pin-function = <3>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <0>;
+		};
+
+		sd4_bus8: sd4-bus-width8 {
+			samsung,pins = "gpk1-3", "gpk1-4", "gpk1-5", "gpk1-6";
+			samsung,pin-function = <3>;
+			samsung,pin-pud = <4>;
+			samsung,pin-drv = <0>;
+		};
+
+		sd1_clk: sd1-clk {
+			samsung,pins = "gpk1-0";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		sd1_cmd: sd1-cmd {
+			samsung,pins = "gpk1-1";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		sd1_cd: sd1-cd {
+			samsung,pins = "gpk1-2";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <0>;
+		};
+
+		sd1_bus1: sd1-bus-width1 {
+			samsung,pins = "gpk1-3";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <0>;
+		};
+
+		sd1_bus4: sd1-bus-width4 {
+			samsung,pins = "gpk1-3", "gpk1-4", "gpk1-5", "gpk1-6";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <0>;
+		};
+
+		sd2_clk: sd2-clk {
+			samsung,pins = "gpk2-0";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		sd2_cmd: sd2-cmd {
+			samsung,pins = "gpk2-1";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		sd2_cd: sd2-cd {
+			samsung,pins = "gpk2-2";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <0>;
+		};
+
+		sd2_bus1: sd2-bus-width1 {
+			samsung,pins = "gpk2-3";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <0>;
+		};
+
+		sd2_bus4: sd2-bus-width4 {
+			samsung,pins = "gpk2-3", "gpk2-4", "gpk2-5", "gpk2-6";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <0>;
+		};
+
+		sd2_bus8: sd2-bus-width8 {
+			samsung,pins = "gpk3-3", "gpk3-4", "gpk3-5", "gpk3-6";
+			samsung,pin-function = <3>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <0>;
+		};
+
+		sd3_clk: sd3-clk {
+			samsung,pins = "gpk3-0";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		sd3_cmd: sd3-cmd {
+			samsung,pins = "gpk3-1";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		sd3_cd: sd3-cd {
+			samsung,pins = "gpk3-2";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <0>;
+		};
+
+		sd3_bus1: sd3-bus-width1 {
+			samsung,pins = "gpk3-3";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <0>;
+		};
+
+		sd3_bus4: sd3-bus-width4 {
+			samsung,pins = "gpk3-3", "gpk3-4", "gpk3-5", "gpk3-6";
+			samsung,pin-function = <2>;
+			samsung,pin-pud = <3>;
+			samsung,pin-drv = <0>;
+		};
+
+		eint0: ext-int0 {
+			samsung,pins = "gpx0-0";
+			samsung,pin-function = <0xf>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		eint8: ext-int8 {
+			samsung,pins = "gpx1-0";
+			samsung,pin-function = <0xf>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		eint15: ext-int15 {
+			samsung,pins = "gpx1-7";
+			samsung,pin-function = <0xf>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		eint16: ext-int16 {
+			samsung,pins = "gpx2-0";
+			samsung,pin-function = <0xf>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		eint31: ext-int31 {
+			samsung,pins = "gpx3-7";
+			samsung,pin-function = <0xf>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+	};
+
+	pinctrl@03860000 {
+		i2s0_bus: i2s0-bus {
+			samsung,pins = "gpz-0", "gpz-1", "gpz-2", "gpz-3",
+					"gpz-4", "gpz-5", "gpz-6";
+			samsung,pin-function = <0x2>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+
+		pcm0_bus: pcm0-bus {
+			samsung,pins = "gpz-0", "gpz-1", "gpz-2", "gpz-3",
+					"gpz-4";
+			samsung,pin-function = <0x3>;
+			samsung,pin-pud = <0>;
+			samsung,pin-drv = <0>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/exynos4210-smdkv310.dts b/arch/arm/boot/dts/exynos4210-smdkv310.dts
index 1beccc8..63610c3 100644
--- a/arch/arm/boot/dts/exynos4210-smdkv310.dts
+++ b/arch/arm/boot/dts/exynos4210-smdkv310.dts
@@ -26,7 +26,7 @@
 	};
 
 	chosen {
-		bootargs = "root=/dev/ram0 rw ramdisk=8192 initrd=0x41000000,8M console=ttySAC1,115200 init=/linuxrc";
+		bootargs = "root=/dev/ram0 rw ramdisk=8192 initrd=0x41000000,8M console=ttySAC2,115200 init=/linuxrc";
 	};
 
 	sdhci@12530000 {
@@ -40,6 +40,7 @@
 			<&gpk2 4 2 3 3>,
 			<&gpk2 5 2 3 3>,
 			<&gpk2 6 2 3 3>;
+		status = "okay";
 	};
 
 	keypad@100A0000 {
@@ -47,6 +48,7 @@
 		samsung,keypad-num-columns = <8>;
 		linux,keypad-no-autorepeat;
 		linux,keypad-wakeup;
+		status = "okay";
 
 		row-gpios = <&gpx2 0 3 3 0>,
 			    <&gpx2 1 3 3 0>;
@@ -128,6 +130,7 @@
 		samsung,i2c-max-bus-freq = <20000>;
 		gpios = <&gpd1 0 2 3 0>,
 			<&gpd1 1 2 3 0>;
+		status = "okay";
 
 		eeprom@50 {
 			compatible = "samsung,24ad0xd1";
@@ -140,58 +143,11 @@
 		};
 	};
 
-	sdhci@12510000 {
-		status = "disabled";
-	};
-
-	sdhci@12520000 {
-		status = "disabled";
-	};
-
-	sdhci@12540000 {
-		status = "disabled";
-	};
-
-	i2c@13870000 {
-		status = "disabled";
-	};
-
-	i2c@13880000 {
-		status = "disabled";
-	};
-
-	i2c@13890000 {
-		status = "disabled";
-	};
-
-	i2c@138A0000 {
-		status = "disabled";
-	};
-
-	i2c@138B0000 {
-		status = "disabled";
-	};
-
-	i2c@138C0000 {
-		status = "disabled";
-	};
-
-	i2c@138D0000 {
-		status = "disabled";
-	};
-
-	spi_0: spi@13920000 {
-		status = "disabled";
-	};
-
-	spi_1: spi@13930000 {
-		status = "disabled";
-	};
-
 	spi_2: spi@13940000 {
 		gpios = <&gpc1 1 5 3 0>,
 			<&gpc1 3 5 3 0>,
 			<&gpc1 4 5 3 0>;
+		status = "okay";
 
 		w25x80@0 {
 			#address-cells = <1>;
diff --git a/arch/arm/boot/dts/exynos4210-trats.dts b/arch/arm/boot/dts/exynos4210-trats.dts
new file mode 100644
index 0000000..73567b8
--- /dev/null
+++ b/arch/arm/boot/dts/exynos4210-trats.dts
@@ -0,0 +1,237 @@
+/*
+ * Samsung's Exynos4210 based Trats board device tree source
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Device tree source file for Samsung's Trats board which is based on
+ * Samsung's Exynos4210 SoC.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+/dts-v1/;
+/include/ "exynos4210.dtsi"
+
+/ {
+	model = "Samsung Trats based on Exynos4210";
+	compatible = "samsung,trats", "samsung,exynos4210";
+
+	memory {
+		reg =  <0x40000000 0x20000000
+			0x60000000 0x20000000>;
+	};
+
+	chosen {
+		bootargs = "console=ttySAC2,115200N8 root=/dev/mmcblk0p5 rootwait earlyprintk panic=5";
+	};
+
+	vemmc_reg: voltage-regulator@0 {
+	        compatible = "regulator-fixed";
+		regulator-name = "VMEM_VDD_2.8V";
+		regulator-min-microvolt = <2800000>;
+		regulator-max-microvolt = <2800000>;
+		gpio = <&gpk0 2 1 0 0>;
+		enable-active-high;
+	};
+
+	sdhci_emmc: sdhci@12510000 {
+		bus-width = <8>;
+		non-removable;
+		broken-voltage;
+		gpios = <&gpk0 0 2 0 3>,
+			<&gpk0 1 2 0 3>,
+			<&gpk0 3 2 2 3>,
+			<&gpk0 4 2 2 3>,
+			<&gpk0 5 2 2 3>,
+			<&gpk0 6 2 2 3>,
+			<&gpk1 3 3 3 3>,
+			<&gpk1 4 3 3 3>,
+			<&gpk1 5 3 3 3>,
+			<&gpk1 6 3 3 3>;
+		vmmc-supply = <&vemmc_reg>;
+		status = "okay";
+	};
+
+	serial@13800000 {
+		status = "okay";
+	};
+
+	serial@13810000 {
+		status = "okay";
+	};
+
+	serial@13820000 {
+		status = "okay";
+	};
+
+	serial@13830000 {
+		status = "okay";
+	};
+
+	i2c@138B0000 {
+		samsung,i2c-sda-delay = <100>;
+		samsung,i2c-slave-addr = <0x10>;
+		samsung,i2c-max-bus-freq = <100000>;
+		gpios = <&gpb 6 3 3 0>,
+			<&gpb 7 3 3 0>;
+		status = "okay";
+
+		max8997_pmic@66 {
+			compatible = "maxim,max8997-pmic";
+
+			reg = <0x66>;
+
+			max8997,pmic-buck1-uses-gpio-dvs;
+			max8997,pmic-buck2-uses-gpio-dvs;
+			max8997,pmic-buck5-uses-gpio-dvs;
+
+			max8997,pmic-ignore-gpiodvs-side-effect;
+			max8997,pmic-buck125-default-dvs-idx = <0>;
+
+			max8997,pmic-buck125-dvs-gpios = <&gpx0 5 1 0 0>,
+						         <&gpx0 6 1 0 0>,
+							 <&gpl0 0 1 0 0>;
+
+			max8997,pmic-buck1-dvs-voltage = <1350000>, <1300000>,
+							 <1250000>, <1200000>,
+							 <1150000>, <1100000>,
+							 <1000000>, <950000>;
+
+			max8997,pmic-buck2-dvs-voltage = <1100000>, <1000000>,
+							 <950000>,  <900000>,
+							 <1100000>, <1000000>,
+							 <950000>,  <900000>;
+
+			max8997,pmic-buck5-dvs-voltage = <1200000>, <1200000>,
+							 <1200000>, <1200000>,
+							 <1200000>, <1200000>,
+							 <1200000>, <1200000>;
+
+			regulators {
+				valive_reg: LDO2 {
+				     regulator-name = "VALIVE_1.1V_C210";
+				     regulator-min-microvolt = <1100000>;
+				     regulator-max-microvolt = <1100000>;
+				     regulator-always-on;
+				};
+
+				vusb_reg: LDO3 {
+				     regulator-name = "VUSB_1.1V_C210";
+				     regulator-min-microvolt = <1100000>;
+				     regulator-max-microvolt = <1100000>;
+				};
+
+				vmipi_reg: LDO4 {
+				     regulator-name = "VMIPI_1.8V";
+				     regulator-min-microvolt = <1800000>;
+				     regulator-max-microvolt = <1800000>;
+				};
+
+				vpda_reg: LDO6 {
+				     regulator-name = "VCC_1.8V_PDA";
+				     regulator-min-microvolt = <1800000>;
+				     regulator-max-microvolt = <1800000>;
+				     regulator-always-on;
+				};
+
+				vcam_reg: LDO7 {
+				     regulator-name = "CAM_ISP_1.8V";
+				     regulator-min-microvolt = <1800000>;
+				     regulator-max-microvolt = <1800000>;
+				};
+
+				vusbdac_reg: LDO8 {
+				     regulator-name = "VUSB/VDAC_3.3V_C210";
+				     regulator-min-microvolt = <3300000>;
+				     regulator-max-microvolt = <3300000>;
+				};
+
+				vccpda_reg: LDO9 {
+				     regulator-name = "VCC_2.8V_PDA";
+				     regulator-min-microvolt = <2800000>;
+				     regulator-max-microvolt = <2800000>;
+				     regulator-always-on;
+				};
+
+				vpll_reg: LDO10 {
+				     regulator-name = "VPLL_1.1V_C210";
+				     regulator-min-microvolt = <1100000>;
+				     regulator-max-microvolt = <1100000>;
+				     regulator-always-on;
+				};
+
+				vcclcd_reg: LDO13 {
+				     regulator-name = "VCC_3.3V_LCD";
+				     regulator-min-microvolt = <3300000>;
+				     regulator-max-microvolt = <3300000>;
+				};
+
+				vlcd_reg: LDO15 {
+				     regulator-name = "VLCD_2.2V";
+				     regulator-min-microvolt = <2200000>;
+				     regulator-max-microvolt = <2200000>;
+				};
+
+				camsensor_reg: LDO16 {
+				     regulator-name = "CAM_SENSOR_IO_1.8V";
+				     regulator-min-microvolt = <1800000>;
+				     regulator-max-microvolt = <1800000>;
+				};
+
+				vddq_reg: LDO21 {
+				     regulator-name = "VDDQ_M1M2_1.2V";
+				     regulator-min-microvolt = <1200000>;
+				     regulator-max-microvolt = <1200000>;
+				     regulator-always-on;
+				};
+
+				varm_breg: BUCK1 {
+				     regulator-name = "VARM_1.2V_C210";
+				     regulator-min-microvolt = <900000>;
+				     regulator-max-microvolt = <1350000>;
+				     regulator-always-on;
+				};
+
+				vint_breg: BUCK2 {
+				     regulator-name = "VINT_1.1V_C210";
+				     regulator-min-microvolt = <900000>;
+				     regulator-max-microvolt = <1100000>;
+				     regulator-always-on;
+				};
+
+				camisp_breg: BUCK4 {
+				     regulator-name = "CAM_ISP_CORE_1.2V";
+				     regulator-min-microvolt = <1200000>;
+				     regulator-max-microvolt = <1200000>;
+				};
+
+				vmem_breg: BUCK5 {
+				     regulator-name = "VMEM_1.2V_C210";
+				     regulator-min-microvolt = <1200000>;
+				     regulator-max-microvolt = <1200000>;
+				     regulator-always-on;
+				};
+
+				vccsub_breg: BUCK7 {
+				     regulator-name = "VCC_SUB_2.0V";
+				     regulator-min-microvolt = <2000000>;
+				     regulator-max-microvolt = <2000000>;
+				     regulator-always-on;
+				};
+
+				safe1_sreg: ESAFEOUT1 {
+				     regulator-name = "SAFEOUT1";
+				     regulator-always-on;
+				};
+
+				safe2_sreg: ESAFEOUT2 {
+				     regulator-name = "SAFEOUT2";
+				     regulator-boot-on;
+				};
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/exynos4210.dtsi b/arch/arm/boot/dts/exynos4210.dtsi
index 02891fe..214c557 100644
--- a/arch/arm/boot/dts/exynos4210.dtsi
+++ b/arch/arm/boot/dts/exynos4210.dtsi
@@ -19,199 +19,60 @@
  * published by the Free Software Foundation.
 */
 
-/include/ "skeleton.dtsi"
+/include/ "exynos4.dtsi"
+/include/ "exynos4210-pinctrl.dtsi"
 
 / {
 	compatible = "samsung,exynos4210";
-	interrupt-parent = <&gic>;
 
 	aliases {
-		spi0 = &spi_0;
-		spi1 = &spi_1;
-		spi2 = &spi_2;
+		pinctrl0 = &pinctrl_0;
+		pinctrl1 = &pinctrl_1;
+		pinctrl2 = &pinctrl_2;
 	};
 
 	gic:interrupt-controller@10490000 {
-		compatible = "arm,cortex-a9-gic";
-		#interrupt-cells = <3>;
-		interrupt-controller;
 		cpu-offset = <0x8000>;
-		reg = <0x10490000 0x1000>, <0x10480000 0x100>;
 	};
 
 	combiner:interrupt-controller@10440000 {
-		compatible = "samsung,exynos4210-combiner";
-		#interrupt-cells = <2>;
-		interrupt-controller;
-		reg = <0x10440000 0x1000>;
 		interrupts = <0 0 0>, <0 1 0>, <0 2 0>, <0 3 0>,
 			     <0 4 0>, <0 5 0>, <0 6 0>, <0 7 0>,
 			     <0 8 0>, <0 9 0>, <0 10 0>, <0 11 0>,
 			     <0 12 0>, <0 13 0>, <0 14 0>, <0 15 0>;
 	};
 
-	watchdog@10060000 {
-		compatible = "samsung,s3c2410-wdt";
-		reg = <0x10060000 0x100>;
-		interrupts = <0 43 0>;
-	};
-
-	rtc@10070000 {
-		compatible = "samsung,s3c6410-rtc";
-		reg = <0x10070000 0x100>;
-		interrupts = <0 44 0>, <0 45 0>;
-	};
-
-	keypad@100A0000 {
-		compatible = "samsung,s5pv210-keypad";
-		reg = <0x100A0000 0x100>;
-		interrupts = <0 109 0>;
-	};
-
-	sdhci@12510000 {
-		compatible = "samsung,exynos4210-sdhci";
-		reg = <0x12510000 0x100>;
-		interrupts = <0 73 0>;
-	};
-
-	sdhci@12520000 {
-		compatible = "samsung,exynos4210-sdhci";
-		reg = <0x12520000 0x100>;
-		interrupts = <0 74 0>;
-	};
-
-	sdhci@12530000 {
-		compatible = "samsung,exynos4210-sdhci";
-		reg = <0x12530000 0x100>;
-		interrupts = <0 75 0>;
-	};
-
-	sdhci@12540000 {
-		compatible = "samsung,exynos4210-sdhci";
-		reg = <0x12540000 0x100>;
-		interrupts = <0 76 0>;
-	};
-
-	serial@13800000 {
-		compatible = "samsung,exynos4210-uart";
-		reg = <0x13800000 0x100>;
-		interrupts = <0 52 0>;
-	};
-
-	serial@13810000 {
-		compatible = "samsung,exynos4210-uart";
-		reg = <0x13810000 0x100>;
-		interrupts = <0 53 0>;
-	};
-
-	serial@13820000 {
-		compatible = "samsung,exynos4210-uart";
-		reg = <0x13820000 0x100>;
-		interrupts = <0 54 0>;
-	};
-
-	serial@13830000 {
-		compatible = "samsung,exynos4210-uart";
-		reg = <0x13830000 0x100>;
-		interrupts = <0 55 0>;
-	};
-
-	i2c@13860000 {
-		compatible = "samsung,s3c2440-i2c";
-		reg = <0x13860000 0x100>;
-		interrupts = <0 58 0>;
-	};
-
-	i2c@13870000 {
-		compatible = "samsung,s3c2440-i2c";
-		reg = <0x13870000 0x100>;
-		interrupts = <0 59 0>;
-	};
-
-	i2c@13880000 {
-		compatible = "samsung,s3c2440-i2c";
-		reg = <0x13880000 0x100>;
-		interrupts = <0 60 0>;
-	};
-
-	i2c@13890000 {
-		compatible = "samsung,s3c2440-i2c";
-		reg = <0x13890000 0x100>;
-		interrupts = <0 61 0>;
-	};
-
-	i2c@138A0000 {
-		compatible = "samsung,s3c2440-i2c";
-		reg = <0x138A0000 0x100>;
-		interrupts = <0 62 0>;
-	};
-
-	i2c@138B0000 {
-		compatible = "samsung,s3c2440-i2c";
-		reg = <0x138B0000 0x100>;
-		interrupts = <0 63 0>;
-	};
-
-	i2c@138C0000 {
-		compatible = "samsung,s3c2440-i2c";
-		reg = <0x138C0000 0x100>;
-		interrupts = <0 64 0>;
-	};
-
-	i2c@138D0000 {
-		compatible = "samsung,s3c2440-i2c";
-		reg = <0x138D0000 0x100>;
-		interrupts = <0 65 0>;
-	};
-
-	spi_0: spi@13920000 {
-		compatible = "samsung,exynos4210-spi";
-		reg = <0x13920000 0x100>;
-		interrupts = <0 66 0>;
-		tx-dma-channel = <&pdma0 7>; /* preliminary */
-		rx-dma-channel = <&pdma0 6>; /* preliminary */
-		#address-cells = <1>;
-		#size-cells = <0>;
-	};
-
-	spi_1: spi@13930000 {
-		compatible = "samsung,exynos4210-spi";
-		reg = <0x13930000 0x100>;
-		interrupts = <0 67 0>;
-		tx-dma-channel = <&pdma1 7>; /* preliminary */
-		rx-dma-channel = <&pdma1 6>; /* preliminary */
-		#address-cells = <1>;
-		#size-cells = <0>;
-	};
-
-	spi_2: spi@13940000 {
-		compatible = "samsung,exynos4210-spi";
-		reg = <0x13940000 0x100>;
-		interrupts = <0 68 0>;
-		tx-dma-channel = <&pdma0 9>; /* preliminary */
-		rx-dma-channel = <&pdma0 8>; /* preliminary */
-		#address-cells = <1>;
-		#size-cells = <0>;
+	pinctrl_0: pinctrl@11400000 {
+		compatible = "samsung,pinctrl-exynos4210";
+		reg = <0x11400000 0x1000>;
+		interrupts = <0 47 0>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
 	};
 
-	amba {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		compatible = "arm,amba-bus";
-		interrupt-parent = <&gic>;
-		ranges;
+	pinctrl_1: pinctrl@11000000 {
+		compatible = "samsung,pinctrl-exynos4210";
+		reg = <0x11000000 0x1000>;
+		interrupts = <0 46 0>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
 
-		pdma0: pdma@12680000 {
-			compatible = "arm,pl330", "arm,primecell";
-			reg = <0x12680000 0x1000>;
-			interrupts = <0 35 0>;
+		wakup_eint: wakeup-interrupt-controller {
+			compatible = "samsung,exynos4210-wakeup-eint";
+			interrupt-parent = <&gic>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			interrupts = <0 16 0>, <0 17 0>, <0 18 0>, <0 19 0>,
+				     <0 20 0>, <0 21 0>, <0 22 0>, <0 23 0>,
+				     <0 24 0>, <0 25 0>, <0 26 0>, <0 27 0>,
+				     <0 28 0>, <0 29 0>, <0 30 0>, <0 31 0>,
+				     <0 32 0>;
 		};
+	};
 
-		pdma1: pdma@12690000 {
-			compatible = "arm,pl330", "arm,primecell";
-			reg = <0x12690000 0x1000>;
-			interrupts = <0 36 0>;
-		};
+	pinctrl_2: pinctrl@03860000 {
+		compatible = "samsung,pinctrl-exynos4210";
+		reg = <0x03860000 0x1000>;
 	};
 
 	gpio-controllers {
diff --git a/arch/arm/boot/dts/exynos5250-smdk5250.dts b/arch/arm/boot/dts/exynos5250-smdk5250.dts
index 8a5e348..62e1039 100644
--- a/arch/arm/boot/dts/exynos5250-smdk5250.dts
+++ b/arch/arm/boot/dts/exynos5250-smdk5250.dts
@@ -21,7 +21,7 @@
 	};
 
 	chosen {
-		bootargs = "root=/dev/ram0 rw ramdisk=8192 console=ttySAC1,115200";
+		bootargs = "root=/dev/ram0 rw ramdisk=8192 initrd=0x41000000,8M console=ttySAC2,115200 init=/linuxrc";
 	};
 
 	i2c@12C60000 {
diff --git a/arch/arm/boot/dts/exynos5250.dtsi b/arch/arm/boot/dts/exynos5250.dtsi
index 004aaa8..b55794b4 100644
--- a/arch/arm/boot/dts/exynos5250.dtsi
+++ b/arch/arm/boot/dts/exynos5250.dtsi
@@ -27,6 +27,10 @@
 		spi0 = &spi_0;
 		spi1 = &spi_1;
 		spi2 = &spi_2;
+		gsc0 = &gsc_0;
+		gsc1 = &gsc_1;
+		gsc2 = &gsc_2;
+		gsc3 = &gsc_3;
 	};
 
 	gic:interrupt-controller@10481000 {
@@ -460,4 +464,28 @@
 			#gpio-cells = <4>;
 		};
 	};
+
+	gsc_0:  gsc@0x13e00000 {
+		compatible = "samsung,exynos5-gsc";
+		reg = <0x13e00000 0x1000>;
+		interrupts = <0 85 0>;
+	};
+
+	gsc_1:  gsc@0x13e10000 {
+		compatible = "samsung,exynos5-gsc";
+		reg = <0x13e10000 0x1000>;
+		interrupts = <0 86 0>;
+	};
+
+	gsc_2:  gsc@0x13e20000 {
+		compatible = "samsung,exynos5-gsc";
+		reg = <0x13e20000 0x1000>;
+		interrupts = <0 87 0>;
+	};
+
+	gsc_3:  gsc@0x13e30000 {
+		compatible = "samsung,exynos5-gsc";
+		reg = <0x13e30000 0x1000>;
+		interrupts = <0 88 0>;
+	};
 };
diff --git a/arch/arm/boot/dts/highbank.dts b/arch/arm/boot/dts/highbank.dts
index 9fecf1a..0c6fc34 100644
--- a/arch/arm/boot/dts/highbank.dts
+++ b/arch/arm/boot/dts/highbank.dts
@@ -121,6 +121,10 @@
 			compatible = "calxeda,hb-ahci";
 			reg = <0xffe08000 0x10000>;
 			interrupts = <0 83 4>;
+			calxeda,port-phys = <&combophy5 0 &combophy0 0
+					     &combophy0 1 &combophy0 2
+					     &combophy0 3>;
+			dma-coherent;
 		};
 
 		sdhci@ffe0e000 {
@@ -306,5 +310,19 @@
 			reg = <0xfff51000 0x1000>;
 			interrupts = <0 80 4  0 81 4  0 82 4>;
 		};
+
+		combophy0: combo-phy@fff58000 {
+			compatible = "calxeda,hb-combophy";
+			#phy-cells = <1>;
+			reg = <0xfff58000 0x1000>;
+			phydev = <5>;
+		};
+
+		combophy5: combo-phy@fff5d000 {
+			compatible = "calxeda,hb-combophy";
+			#phy-cells = <1>;
+			reg = <0xfff5d000 0x1000>;
+			phydev = <31>;
+		};
 	};
 };
diff --git a/arch/arm/boot/dts/hrefv60plus.dts b/arch/arm/boot/dts/hrefv60plus.dts
new file mode 100644
index 0000000..2131d77
--- /dev/null
+++ b/arch/arm/boot/dts/hrefv60plus.dts
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2012 ST-Ericsson AB
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "dbx5x0.dtsi"
+
+/ {
+	model = "ST-Ericsson HREF platform with Device Tree";
+	compatible = "st-ericsson,hrefv60+";
+
+	memory {
+		reg = <0x00000000 0x20000000>;
+	};
+
+	soc-u9500 {
+		uart@80120000 {
+			status = "okay";
+		};
+
+		uart@80121000 {
+			status = "okay";
+		};
+
+		uart@80007000 {
+			status = "okay";
+		};
+
+		i2c@80004000 {
+			tc3589x@42 {
+				compatible = "tc3589x";
+				reg = <0x42>;
+				interrupt-parent = <&gpio6>;
+				interrupts = <25 0x1>;
+
+				interrupt-controller;
+				#interrupt-cells = <2>;
+
+				tc3589x_gpio: tc3589x_gpio {
+					compatible = "tc3589x-gpio";
+					interrupts = <0 0x1>;
+
+					interrupt-controller;
+					#interrupt-cells = <2>;
+					gpio-controller;
+					#gpio-cells = <2>;
+				};
+			};
+
+			tps61052@33 {
+				compatible = "tps61052";
+				reg = <0x33>;
+			};
+		};
+
+		i2c@80128000 {
+			lp5521@0x33 {
+				compatible = "lp5521";
+				reg = <0x33>;
+			};
+
+			lp5521@0x34 {
+				compatible = "lp5521";
+				reg = <0x34>;
+			};
+
+			bh1780@0x29 {
+				compatible = "rohm,bh1780gli";
+				reg = <0x33>;
+			};
+		};
+
+		sound {
+			compatible = "stericsson,snd-soc-mop500";
+
+			stericsson,cpu-dai = <&msp1 &msp3>;
+			stericsson,audio-codec = <&codec>;
+		};
+
+		msp1: msp@80124000 {
+			status = "okay";
+		};
+
+		msp3: msp@80125000 {
+			status = "okay";
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/imx23-evk.dts b/arch/arm/boot/dts/imx23-evk.dts
index e3486f4..035c13f 100644
--- a/arch/arm/boot/dts/imx23-evk.dts
+++ b/arch/arm/boot/dts/imx23-evk.dts
@@ -42,12 +42,13 @@
 				pinctrl-names = "default";
 				pinctrl-0 = <&hog_pins_a>;
 
-				hog_pins_a: hog-gpios@0 {
+				hog_pins_a: hog@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
 						0x1123 /* MX23_PAD_LCD_RESET__GPIO_1_18 */
 						0x11d3 /* MX23_PAD_PWM3__GPIO_1_29 */
 						0x11e3 /* MX23_PAD_PWM4__GPIO_1_30 */
+						0x2010 /* MX23_PAD_SSP1_DETECT__SSP1_DETECT */
 					>;
 					fsl,drive-strength = <0>;
 					fsl,voltage = <1>;
diff --git a/arch/arm/boot/dts/imx23-olinuxino.dts b/arch/arm/boot/dts/imx23-olinuxino.dts
index 20912b1..384d8b6 100644
--- a/arch/arm/boot/dts/imx23-olinuxino.dts
+++ b/arch/arm/boot/dts/imx23-olinuxino.dts
@@ -31,6 +31,22 @@
 				bus-width = <4>;
 				status = "okay";
 			};
+
+			pinctrl@80018000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&hog_pins_a>;
+
+				hog_pins_a: hog@0 {
+					reg = <0>;
+					fsl,pinmux-ids = <
+						0x2013 /* MX23_PAD_SSP1_DETECT__GPIO_2_1 */
+						0x0113 /* MX23_PAD_GPMI_ALE__GPIO_0_17 */
+					>;
+					fsl,drive-strength = <0>;
+					fsl,voltage = <1>;
+					fsl,pull-up = <0>;
+				};
+			};
 		};
 
 		apbx@80040000 {
@@ -39,6 +55,47 @@
 				pinctrl-0 = <&duart_pins_a>;
 				status = "okay";
 			};
+
+			auart0: serial@8006c000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&auart0_2pins_a>;
+				status = "okay";
+			};
+
+			usbphy0: usbphy@8007c000 {
+				status = "okay";
+			};
+		};
+	};
+
+	ahb@80080000 {
+		usb0: usb@80080000 {
+			vbus-supply = <&reg_usb0_vbus>;
+			status = "okay";
+		};
+	};
+
+	regulators {
+		compatible = "simple-bus";
+
+		reg_usb0_vbus: usb0_vbus {
+			compatible = "regulator-fixed";
+			regulator-name = "usb0_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			enable-active-high;
+			startup-delay-us = <300>; /* LAN9215 requires a POR of 200us minimum */
+			gpio = <&gpio0 17 0>;
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		user {
+			label = "green";
+			gpios = <&gpio2 1 0>;
+			linux,default-trigger = "default-on";
 		};
 	};
 };
diff --git a/arch/arm/boot/dts/imx23-stmp378x_devb.dts b/arch/arm/boot/dts/imx23-stmp378x_devb.dts
index 757a327..85c3864 100644
--- a/arch/arm/boot/dts/imx23-stmp378x_devb.dts
+++ b/arch/arm/boot/dts/imx23-stmp378x_devb.dts
@@ -36,7 +36,7 @@
 				pinctrl-names = "default";
 				pinctrl-0 = <&hog_pins_a>;
 
-				hog_pins_a: hog-gpios@0 {
+				hog_pins_a: hog@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
 						0x11d3 /* MX23_PAD_PWM3__GPIO_1_29 */
diff --git a/arch/arm/boot/dts/imx23.dtsi b/arch/arm/boot/dts/imx23.dtsi
index e613831..9ca4ca7 100644
--- a/arch/arm/boot/dts/imx23.dtsi
+++ b/arch/arm/boot/dts/imx23.dtsi
@@ -43,7 +43,7 @@
 			ranges;
 
 			icoll: interrupt-controller@80000000 {
-				compatible = "fsl,imx23-icoll", "fsl,mxs-icoll";
+				compatible = "fsl,imx23-icoll", "fsl,icoll";
 				interrupt-controller;
 				#interrupt-cells = <1>;
 				reg = <0x80000000 0x2000>;
@@ -52,6 +52,7 @@
 			dma-apbh@80004000 {
 				compatible = "fsl,imx23-dma-apbh";
 				reg = <0x80004000 0x2000>;
+				clocks = <&clks 15>;
 			};
 
 			ecc@80008000 {
@@ -67,6 +68,7 @@
 				reg-names = "gpmi-nand", "bch";
 				interrupts = <13>, <56>;
 				interrupt-names = "gpmi-dma", "bch";
+				clocks = <&clks 34>;
 				fsl,gpmi-dma-channel = <4>;
 				status = "disabled";
 			};
@@ -74,6 +76,7 @@
 			ssp0: ssp@80010000 {
 				reg = <0x80010000 0x2000>;
 				interrupts = <15 14>;
+				clocks = <&clks 33>;
 				fsl,ssp-dma-channel = <1>;
 				status = "disabled";
 			};
@@ -140,6 +143,17 @@
 					fsl,pull-up = <0>;
 				};
 
+				auart0_2pins_a: auart0-2pins@0 {
+					reg = <0>;
+					fsl,pinmux-ids = <
+						0x01e2 /* MX23_PAD_I2C_SCL__AUART1_TX */
+						0x01f2 /* MX23_PAD_I2C_SDA__AUART1_RX */
+					>;
+					fsl,drive-strength = <0>;
+					fsl,voltage = <1>;
+					fsl,pull-up = <0>;
+				};
+
 				gpmi_pins_a: gpmi-nand@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
@@ -183,7 +197,6 @@
 						0x2040 /* MX23_PAD_SSP1_DATA2__SSP1_DATA2 */
 						0x2050 /* MX23_PAD_SSP1_DATA3__SSP1_DATA3 */
 						0x2000 /* MX23_PAD_SSP1_CMD__SSP1_CMD */
-						0x2010 /* MX23_PAD_SSP1_DETECT__SSP1_DETECT */
 						0x2060 /* MX23_PAD_SSP1_SCK__SSP1_SCK */
 					>;
 					fsl,drive-strength = <1>;
@@ -280,6 +293,7 @@
 			dma-apbx@80024000 {
 				compatible = "fsl,imx23-dma-apbx";
 				reg = <0x80024000 0x2000>;
+				clocks = <&clks 16>;
 			};
 
 			dcp@80028000 {
@@ -306,12 +320,14 @@
 				compatible = "fsl,imx23-lcdif";
 				reg = <0x80030000 2000>;
 				interrupts = <46 45>;
+				clocks = <&clks 38>;
 				status = "disabled";
 			};
 
 			ssp1: ssp@80034000 {
 				reg = <0x80034000 0x2000>;
 				interrupts = <2 20>;
+				clocks = <&clks 33>;
 				fsl,ssp-dma-channel = <2>;
 				status = "disabled";
 			};
@@ -329,9 +345,10 @@
 			reg = <0x80040000 0x40000>;
 			ranges;
 
-			clkctl@80040000 {
+			clks: clkctrl@80040000 {
+				compatible = "fsl,imx23-clkctrl";
 				reg = <0x80040000 0x2000>;
-				status = "disabled";
+				#clock-cells = <1>;
 			};
 
 			saif0: saif@80042000 {
@@ -383,20 +400,23 @@
 			pwm: pwm@80064000 {
 				compatible = "fsl,imx23-pwm";
 				reg = <0x80064000 0x2000>;
+				clocks = <&clks 30>;
 				#pwm-cells = <2>;
 				fsl,pwm-number = <5>;
 				status = "disabled";
 			};
 
 			timrot@80068000 {
+				compatible = "fsl,imx23-timrot", "fsl,timrot";
 				reg = <0x80068000 0x2000>;
-				status = "disabled";
+				interrupts = <28 29 30 31>;
 			};
 
 			auart0: serial@8006c000 {
 				compatible = "fsl,imx23-auart";
 				reg = <0x8006c000 0x2000>;
 				interrupts = <24 25 23>;
+				clocks = <&clks 32>;
 				status = "disabled";
 			};
 
@@ -404,6 +424,7 @@
 				compatible = "fsl,imx23-auart";
 				reg = <0x8006e000 0x2000>;
 				interrupts = <59 60 58>;
+				clocks = <&clks 32>;
 				status = "disabled";
 			};
 
@@ -411,11 +432,15 @@
 				compatible = "arm,pl011", "arm,primecell";
 				reg = <0x80070000 0x2000>;
 				interrupts = <0>;
+				clocks = <&clks 32>, <&clks 16>;
+				clock-names = "uart", "apb_pclk";
 				status = "disabled";
 			};
 
-			usbphy@8007c000 {
+			usbphy0: usbphy@8007c000 {
+				compatible = "fsl,imx23-usbphy";
 				reg = <0x8007c000 0x2000>;
+				clocks = <&clks 41>;
 				status = "disabled";
 			};
 		};
@@ -428,8 +453,12 @@
 		reg = <0x80080000 0x80000>;
 		ranges;
 
-		usbctrl@80080000 {
+		usb0: usb@80080000 {
+			compatible = "fsl,imx23-usb", "fsl,imx27-usb";
 			reg = <0x80080000 0x40000>;
+			interrupts = <11>;
+			fsl,usbphy = <&usbphy0>;
+			clocks = <&clks 40>;
 			status = "disabled";
 		};
 	};
diff --git a/arch/arm/boot/dts/imx27-phytec-phycore.dts b/arch/arm/boot/dts/imx27-phytec-phycore.dts
index 2b0ff60..af50469 100644
--- a/arch/arm/boot/dts/imx27-phytec-phycore.dts
+++ b/arch/arm/boot/dts/imx27-phytec-phycore.dts
@@ -23,10 +23,6 @@
 	soc {
 		aipi@10000000 { /* aipi */
 
-			wdog@10002000 {
-				status = "okay";
-			};
-
 			serial@1000a000 {
 				fsl,uart-has-rtscts;
 				status = "okay";
@@ -49,7 +45,7 @@
 			i2c@1001d000 {
 				clock-frequency = <400000>;
 				status = "okay";
-				at24@4c {
+				at24@52 {
 					compatible = "at,24c32";
 					pagesize = <32>;
 					reg = <0x52>;
diff --git a/arch/arm/boot/dts/imx27.dtsi b/arch/arm/boot/dts/imx27.dtsi
index 5303ab6..3e54f14 100644
--- a/arch/arm/boot/dts/imx27.dtsi
+++ b/arch/arm/boot/dts/imx27.dtsi
@@ -62,7 +62,6 @@
 				compatible = "fsl,imx27-wdt", "fsl,imx21-wdt";
 				reg = <0x10002000 0x4000>;
 				interrupts = <27>;
-				status = "disabled";
 			};
 
 			uart1: serial@1000a000 {
diff --git a/arch/arm/boot/dts/imx28-apx4devkit.dts b/arch/arm/boot/dts/imx28-apx4devkit.dts
index b383417..5171667 100644
--- a/arch/arm/boot/dts/imx28-apx4devkit.dts
+++ b/arch/arm/boot/dts/imx28-apx4devkit.dts
@@ -37,7 +37,7 @@
 				pinctrl-names = "default";
 				pinctrl-0 = <&hog_pins_a>;
 
-				hog_pins_a: hog-gpios@0 {
+				hog_pins_a: hog@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
 						0x0113 /* MX28_PAD_GPMI_CE1N__GPIO_0_17 */
diff --git a/arch/arm/boot/dts/imx28-cfa10049.dts b/arch/arm/boot/dts/imx28-cfa10049.dts
new file mode 100644
index 0000000..05c892e
--- /dev/null
+++ b/arch/arm/boot/dts/imx28-cfa10049.dts
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2012 Free Electrons
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/*
+ * The CFA-10049 is an expansion board for the CFA-10036 module, thus we
+ * need to include the CFA-10036 DTS.
+ */
+/include/ "imx28-cfa10036.dts"
+
+/ {
+	model = "Crystalfontz CFA-10049 Board";
+	compatible = "crystalfontz,cfa10049", "crystalfontz,cfa10036", "fsl,imx28";
+
+	apb@80000000 {
+		apbh@80000000 {
+			pinctrl@80018000 {
+				spi3_pins_cfa10049: spi3-cfa10049@0 {
+					reg = <0>;
+					fsl,pinmux-ids = <
+						0x0181 /* MX28_PAD_GPMI_RDN__SSP3_SCK */
+						0x01c1 /* MX28_PAD_GPMI_RESETN__SSP3_CMD */
+						0x0111 /* MX28_PAD_GPMI_CE1N__SSP3_D3 */
+						0x01a2 /* MX28_PAD_GPMI_ALE__SSP3_D4 */
+					>;
+					fsl,drive-strength = <1>;
+					fsl,voltage = <1>;
+					fsl,pull-up = <1>;
+				};
+			};
+
+			ssp3: ssp@80016000 {
+				compatible = "fsl,imx28-spi";
+				pinctrl-names = "default";
+				pinctrl-0 = <&spi3_pins_cfa10049>;
+				status = "okay";
+
+				gpio5: gpio5@0 {
+					compatible = "fairchild,74hc595";
+					gpio-controller;
+					#gpio-cells = <2>;
+					reg = <0>;
+					registers-number = <2>;
+					spi-max-frequency = <100000>;
+				};
+
+				gpio6: gpio6@1 {
+					compatible = "fairchild,74hc595";
+					gpio-controller;
+					#gpio-cells = <2>;
+					reg = <1>;
+					registers-number = <4>;
+					spi-max-frequency = <100000>;
+				};
+
+			};
+		};
+
+		apbx@80040000 {
+			i2c1: i2c@8005a000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&i2c1_pins_a>;
+				status = "okay";
+			};
+
+			usbphy1: usbphy@8007e000 {
+				status = "okay";
+			};
+		};
+	};
+
+	ahb@80080000 {
+		usb1: usb@80090000 {
+			vbus-supply = <&reg_usb1_vbus>;
+			pinctrl-0 = <&usbphy1_pins_a>;
+			pinctrl-names = "default";
+			status = "okay";
+		};
+	};
+
+	regulators {
+		compatible = "simple-bus";
+
+		reg_usb1_vbus: usb1_vbus {
+			compatible = "regulator-fixed";
+			regulator-name = "usb1_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			gpio = <&gpio0 7 1>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/imx28-evk.dts b/arch/arm/boot/dts/imx28-evk.dts
index 773c0e8..a0ad71c 100644
--- a/arch/arm/boot/dts/imx28-evk.dts
+++ b/arch/arm/boot/dts/imx28-evk.dts
@@ -46,11 +46,28 @@
 				wp-gpios = <&gpio0 28 0>;
 			};
 
+			ssp2: ssp@80014000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx28-spi";
+				pinctrl-names = "default";
+				pinctrl-0 = <&spi2_pins_a>;
+				status = "okay";
+
+				flash: m25p80@0 {
+					#address-cells = <1>;
+					#size-cells = <1>;
+					compatible = "sst,sst25vf016b";
+					spi-max-frequency = <40000000>;
+					reg = <0>;
+				};
+			};
+
 			pinctrl@80018000 {
 				pinctrl-names = "default";
 				pinctrl-0 = <&hog_pins_a>;
 
-				hog_pins_a: hog-gpios@0 {
+				hog_pins_a: hog@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
 						0x20d3 /* MX28_PAD_SSP1_CMD__GPIO_2_13 */
@@ -128,6 +145,10 @@
 				status = "okay";
 			};
 
+			lradc@80050000 {
+				status = "okay";
+			};
+
 			i2c0: i2c@80058000 {
 				pinctrl-names = "default";
 				pinctrl-0 = <&i2c0_pins_a>;
@@ -140,6 +161,12 @@
 					VDDIO-supply = <&reg_3p3v>;
 
 				};
+
+				at24@51 {
+					compatible = "at24,24c32";
+					pagesize = <32>;
+					reg = <0x51>;
+				};
 			};
 
 			pwm: pwm@80064000 {
diff --git a/arch/arm/boot/dts/imx28-m28evk.dts b/arch/arm/boot/dts/imx28-m28evk.dts
index 183a3fd..3bab6b0 100644
--- a/arch/arm/boot/dts/imx28-m28evk.dts
+++ b/arch/arm/boot/dts/imx28-m28evk.dts
@@ -23,6 +23,8 @@
 	apb@80000000 {
 		apbh@80000000 {
 			gpmi-nand@8000c000 {
+				#address-cells = <1>;
+				#size-cells = <1>;
 				pinctrl-names = "default";
 				pinctrl-0 = <&gpmi_pins_a &gpmi_status_cfg>;
 				status = "okay";
@@ -61,19 +63,40 @@
 					     &mmc0_cd_cfg
 					     &mmc0_sck_cfg>;
 				bus-width = <8>;
-				wp-gpios = <&gpio3 10 1>;
+				wp-gpios = <&gpio3 10 0>;
+				vmmc-supply = <&reg_vddio_sd0>;
 				status = "okay";
 			};
 
+			ssp2: ssp@80014000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx28-spi";
+				pinctrl-names = "default";
+				pinctrl-0 = <&spi2_pins_a>;
+				status = "okay";
+
+				flash: m25p80@0 {
+					#address-cells = <1>;
+					#size-cells = <1>;
+					compatible = "m25p80";
+					spi-max-frequency = <40000000>;
+					reg = <0>;
+				};
+			};
+
 			pinctrl@80018000 {
 				pinctrl-names = "default";
 				pinctrl-0 = <&hog_pins_a>;
 
-				hog_pins_a: hog-gpios@0 {
+				hog_pins_a: hog@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
+						0x31c3 /* MX28_PAD_PWM3__GPIO_3_28 */
 						0x30a3 /* MX28_PAD_AUART2_CTS__GPIO_3_10 */
 						0x30b3 /* MX28_PAD_AUART2_RTS__GPIO_3_11 */
+						0x30c3 /* MX28_PAD_AUART3_RX__GPIO_3_12 */
+						0x30d3 /* MX28_PAD_AUART3_TX__GPIO_3_13 */
 					>;
 					fsl,drive-strength = <0>;
 					fsl,voltage = <1>;
@@ -129,6 +152,7 @@
 			i2c0: i2c@80058000 {
 				pinctrl-names = "default";
 				pinctrl-0 = <&i2c0_pins_a>;
+				clock-frequency = <400000>;
 				status = "okay";
 
 				sgtl5000: codec@0a {
@@ -151,32 +175,51 @@
 				};
 			};
 
+			lradc@80050000 {
+				status = "okay";
+			};
+
 			duart: serial@80074000 {
 				pinctrl-names = "default";
 				pinctrl-0 = <&duart_pins_a>;
 				status = "okay";
 			};
 
-			auart0: serial@8006a000 {
-				pinctrl-names = "default";
-				pinctrl-0 = <&auart0_2pins_a>;
+			usbphy0: usbphy@8007c000 {
 				status = "okay";
 			};
 
-			auart3: serial@80070000 {
+			usbphy1: usbphy@8007e000 {
+				status = "okay";
+			};
+
+			auart0: serial@8006a000 {
 				pinctrl-names = "default";
-				pinctrl-0 = <&auart3_pins_a>;
+				pinctrl-0 = <&auart0_2pins_a>;
 				status = "okay";
 			};
 		};
 	};
 
 	ahb@80080000 {
+		usb0: usb@80080000 {
+			vbus-supply = <&reg_usb0_vbus>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&usbphy0_pins_a>;
+			status = "okay";
+		};
+
+		usb1: usb@80090000 {
+			vbus-supply = <&reg_usb1_vbus>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&usbphy1_pins_a>;
+			status = "okay";
+		};
+
 		mac0: ethernet@800f0000 {
 			phy-mode = "rmii";
 			pinctrl-names = "default";
 			pinctrl-0 = <&mac0_pins_a>;
-			phy-reset-gpios = <&gpio3 11 0>;
 			status = "okay";
 		};
 
@@ -198,6 +241,30 @@
 			regulator-max-microvolt = <3300000>;
 			regulator-always-on;
 		};
+
+		reg_vddio_sd0: vddio-sd0 {
+			compatible = "regulator-fixed";
+			regulator-name = "vddio-sd0";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			gpio = <&gpio3 28 0>;
+		};
+
+		reg_usb0_vbus: usb0_vbus {
+			compatible = "regulator-fixed";
+			regulator-name = "usb0_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			gpio = <&gpio3 12 0>;
+		};
+
+		reg_usb1_vbus: usb1_vbus {
+			compatible = "regulator-fixed";
+			regulator-name = "usb1_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			gpio = <&gpio3 13 0>;
+		};
 	};
 
 	sound {
diff --git a/arch/arm/boot/dts/imx28-tx28.dts b/arch/arm/boot/dts/imx28-tx28.dts
index 62bf767..37be532 100644
--- a/arch/arm/boot/dts/imx28-tx28.dts
+++ b/arch/arm/boot/dts/imx28-tx28.dts
@@ -25,7 +25,7 @@
 				pinctrl-names = "default";
 				pinctrl-0 = <&hog_pins_a>;
 
-				hog_pins_a: hog-gpios@0 {
+				hog_pins_a: hog@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
 						0x40a3 /* MX28_PAD_ENET0_RXD3__GPIO_4_10 */
@@ -34,6 +34,24 @@
 					fsl,voltage = <1>;
 					fsl,pull-up = <0>;
 				};
+
+				mac0_pins_gpio: mac0-gpio-mode@0 {
+					reg = <0>;
+					fsl,pinmux-ids = <
+						0x4003 /* MX28_PAD_ENET0_MDC__GPIO_4_0 */
+						0x4013 /* MX28_PAD_ENET0_MDIO__GPIO_4_1 */
+						0x4023 /* MX28_PAD_ENET0_RX_EN__GPIO_4_2 */
+						0x4033 /* MX28_PAD_ENET0_RXD0__GPIO_4_3 */
+						0x4043 /* MX28_PAD_ENET0_RXD1__GPIO_4_4 */
+						0x4063 /* MX28_PAD_ENET0_TX_EN__GPIO_4_6 */
+						0x4073 /* MX28_PAD_ENET0_TXD0__GPIO_4_7 */
+						0x4083 /* MX28_PAD_ENET0_TXD1__GPIO_4_8 */
+						0x4103 /* MX28_PAD_ENET_CLK__GPIO_4_16 */
+					>;
+					fsl,drive-strength = <0>;
+					fsl,voltage = <1>;
+					fsl,pull-up = <0>;
+				};
 			};
 		};
 
@@ -72,8 +90,9 @@
 	ahb@80080000 {
 		mac0: ethernet@800f0000 {
 			phy-mode = "rmii";
-			pinctrl-names = "default";
+			pinctrl-names = "default", "gpio_mode";
 			pinctrl-0 = <&mac0_pins_a>;
+			pinctrl-1 = <&mac0_pins_gpio>;
 			status = "okay";
 		};
 	};
diff --git a/arch/arm/boot/dts/imx28.dtsi b/arch/arm/boot/dts/imx28.dtsi
index 3fa6d19..59fbfba 100644
--- a/arch/arm/boot/dts/imx28.dtsi
+++ b/arch/arm/boot/dts/imx28.dtsi
@@ -27,6 +27,8 @@
 		serial2 = &auart2;
 		serial3 = &auart3;
 		serial4 = &auart4;
+		ethernet0 = &mac0;
+		ethernet1 = &mac1;
 	};
 
 	cpus {
@@ -50,7 +52,7 @@
 			ranges;
 
 			icoll: interrupt-controller@80000000 {
-				compatible = "fsl,imx28-icoll", "fsl,mxs-icoll";
+				compatible = "fsl,imx28-icoll", "fsl,icoll";
 				interrupt-controller;
 				#interrupt-cells = <1>;
 				reg = <0x80000000 0x2000>;
@@ -65,6 +67,7 @@
 			dma-apbh@80004000 {
 				compatible = "fsl,imx28-dma-apbh";
 				reg = <0x80004000 0x2000>;
+				clocks = <&clks 25>;
 			};
 
 			perfmon@80006000 {
@@ -81,34 +84,47 @@
 				reg-names = "gpmi-nand", "bch";
 				interrupts = <88>, <41>;
 				interrupt-names = "gpmi-dma", "bch";
+				clocks = <&clks 50>;
 				fsl,gpmi-dma-channel = <4>;
 				status = "disabled";
 			};
 
 			ssp0: ssp@80010000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
 				reg = <0x80010000 0x2000>;
 				interrupts = <96 82>;
+				clocks = <&clks 46>;
 				fsl,ssp-dma-channel = <0>;
 				status = "disabled";
 			};
 
 			ssp1: ssp@80012000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
 				reg = <0x80012000 0x2000>;
 				interrupts = <97 83>;
+				clocks = <&clks 47>;
 				fsl,ssp-dma-channel = <1>;
 				status = "disabled";
 			};
 
 			ssp2: ssp@80014000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
 				reg = <0x80014000 0x2000>;
 				interrupts = <98 84>;
+				clocks = <&clks 48>;
 				fsl,ssp-dma-channel = <2>;
 				status = "disabled";
 			};
 
 			ssp3: ssp@80016000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
 				reg = <0x80016000 0x2000>;
 				interrupts = <99 85>;
+				clocks = <&clks 49>;
 				fsl,ssp-dma-channel = <3>;
 				status = "disabled";
 			};
@@ -410,6 +426,28 @@
 					fsl,pull-up = <1>;
 				};
 
+				i2c0_pins_b: i2c0@1 {
+					reg = <1>;
+					fsl,pinmux-ids = <
+						0x3001 /* MX28_PAD_AUART0_RX__I2C0_SCL */
+						0x3011 /* MX28_PAD_AUART0_TX__I2C0_SDA */
+					>;
+					fsl,drive-strength = <1>;
+					fsl,voltage = <1>;
+					fsl,pull-up = <1>;
+				};
+
+				i2c1_pins_a: i2c1@0 {
+					reg = <0>;
+					fsl,pinmux-ids = <
+						0x3101 /* MX28_PAD_PWM0__I2C1_SCL */
+						0x3111 /* MX28_PAD_PWM1__I2C1_SDA */
+					>;
+					fsl,drive-strength = <1>;
+					fsl,voltage = <1>;
+					fsl,pull-up = <1>;
+				};
+
 				saif0_pins_a: saif0@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
@@ -453,6 +491,16 @@
 					fsl,pull-up = <0>;
 				};
 
+				pwm4_pins_a: pwm4@0 {
+					reg = <0>;
+					fsl,pinmux-ids = <
+						0x31d0 /* MX28_PAD_PWM4__PWM_4 */
+					>;
+					fsl,drive-strength = <0>;
+					fsl,voltage = <1>;
+					fsl,pull-up = <0>;
+				};
+
 				lcdif_24bit_pins_a: lcdif-24bit@0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
@@ -507,6 +555,49 @@
 					fsl,voltage = <1>;
 					fsl,pull-up = <0>;
 				};
+
+				spi2_pins_a: spi2@0 {
+					reg = <0>;
+					fsl,pinmux-ids = <
+						0x2100 /* MX28_PAD_SSP2_SCK__SSP2_SCK */
+						0x2110 /* MX28_PAD_SSP2_MOSI__SSP2_CMD */
+						0x2120 /* MX28_PAD_SSP2_MISO__SSP2_D0 */
+						0x2130 /* MX28_PAD_SSP2_SS0__SSP2_D3 */
+					>;
+					fsl,drive-strength = <1>;
+					fsl,voltage = <1>;
+					fsl,pull-up = <1>;
+				};
+
+				usbphy0_pins_a: usbphy0@0 {
+					reg = <0>;
+					fsl,pinmux-ids = <
+						0x2152 /* MX28_PAD_SSP2_SS2__USB0_OVERCURRENT */
+					>;
+					fsl,drive-strength = <2>;
+					fsl,voltage = <1>;
+					fsl,pull-up = <0>;
+				};
+
+				usbphy0_pins_b: usbphy0@1 {
+					reg = <1>;
+					fsl,pinmux-ids = <
+						0x3061 /* MX28_PAD_AUART1_CTS__USB0_OVERCURRENT */
+					>;
+					fsl,drive-strength = <2>;
+					fsl,voltage = <1>;
+					fsl,pull-up = <0>;
+				};
+
+				usbphy1_pins_a: usbphy1@0 {
+					reg = <0>;
+					fsl,pinmux-ids = <
+						0x2142 /* MX28_PAD_SSP2_SS1__USB1_OVERCURRENT */
+					>;
+					fsl,drive-strength = <2>;
+					fsl,voltage = <1>;
+					fsl,pull-up = <0>;
+				};
 			};
 
 			digctl@8001c000 {
@@ -523,6 +614,7 @@
 			dma-apbx@80024000 {
 				compatible = "fsl,imx28-dma-apbx";
 				reg = <0x80024000 0x2000>;
+				clocks = <&clks 26>;
 			};
 
 			dcp@80028000 {
@@ -551,6 +643,7 @@
 				compatible = "fsl,imx28-lcdif";
 				reg = <0x80030000 0x2000>;
 				interrupts = <38 86>;
+				clocks = <&clks 55>;
 				status = "disabled";
 			};
 
@@ -558,6 +651,8 @@
 				compatible = "fsl,imx28-flexcan", "fsl,p1010-flexcan";
 				reg = <0x80032000 0x2000>;
 				interrupts = <8>;
+				clocks = <&clks 58>, <&clks 58>;
+				clock-names = "ipg", "per";
 				status = "disabled";
 			};
 
@@ -565,6 +660,8 @@
 				compatible = "fsl,imx28-flexcan", "fsl,p1010-flexcan";
 				reg = <0x80034000 0x2000>;
 				interrupts = <9>;
+				clocks = <&clks 59>, <&clks 59>;
+				clock-names = "ipg", "per";
 				status = "disabled";
 			};
 
@@ -611,15 +708,17 @@
 			reg = <0x80040000 0x40000>;
 			ranges;
 
-			clkctl@80040000 {
+			clks: clkctrl@80040000 {
+				compatible = "fsl,imx28-clkctrl";
 				reg = <0x80040000 0x2000>;
-				status = "disabled";
+				#clock-cells = <1>;
 			};
 
 			saif0: saif@80042000 {
 				compatible = "fsl,imx28-saif";
 				reg = <0x80042000 0x2000>;
 				interrupts = <59 80>;
+				clocks = <&clks 53>;
 				fsl,saif-dma-channel = <4>;
 				status = "disabled";
 			};
@@ -633,12 +732,16 @@
 				compatible = "fsl,imx28-saif";
 				reg = <0x80046000 0x2000>;
 				interrupts = <58 81>;
+				clocks = <&clks 54>;
 				fsl,saif-dma-channel = <5>;
 				status = "disabled";
 			};
 
 			lradc@80050000 {
+				compatible = "fsl,imx28-lradc";
 				reg = <0x80050000 0x2000>;
+				interrupts = <10 14 15 16 17 18 19
+						20 21 22 23 24 25>;
 				status = "disabled";
 			};
 
@@ -677,20 +780,23 @@
 			pwm: pwm@80064000 {
 				compatible = "fsl,imx28-pwm", "fsl,imx23-pwm";
 				reg = <0x80064000 0x2000>;
+				clocks = <&clks 44>;
 				#pwm-cells = <2>;
 				fsl,pwm-number = <8>;
 				status = "disabled";
 			};
 
 			timrot@80068000 {
+				compatible = "fsl,imx28-timrot", "fsl,timrot";
 				reg = <0x80068000 0x2000>;
-				status = "disabled";
+				interrupts = <48 49 50 51>;
 			};
 
 			auart0: serial@8006a000 {
 				compatible = "fsl,imx28-auart", "fsl,imx23-auart";
 				reg = <0x8006a000 0x2000>;
 				interrupts = <112 70 71>;
+				clocks = <&clks 45>;
 				status = "disabled";
 			};
 
@@ -698,6 +804,7 @@
 				compatible = "fsl,imx28-auart", "fsl,imx23-auart";
 				reg = <0x8006c000 0x2000>;
 				interrupts = <113 72 73>;
+				clocks = <&clks 45>;
 				status = "disabled";
 			};
 
@@ -705,6 +812,7 @@
 				compatible = "fsl,imx28-auart", "fsl,imx23-auart";
 				reg = <0x8006e000 0x2000>;
 				interrupts = <114 74 75>;
+				clocks = <&clks 45>;
 				status = "disabled";
 			};
 
@@ -712,6 +820,7 @@
 				compatible = "fsl,imx28-auart", "fsl,imx23-auart";
 				reg = <0x80070000 0x2000>;
 				interrupts = <115 76 77>;
+				clocks = <&clks 45>;
 				status = "disabled";
 			};
 
@@ -719,6 +828,7 @@
 				compatible = "fsl,imx28-auart", "fsl,imx23-auart";
 				reg = <0x80072000 0x2000>;
 				interrupts = <116 78 79>;
+				clocks = <&clks 45>;
 				status = "disabled";
 			};
 
@@ -726,18 +836,22 @@
 				compatible = "arm,pl011", "arm,primecell";
 				reg = <0x80074000 0x1000>;
 				interrupts = <47>;
+				clocks = <&clks 45>, <&clks 26>;
+				clock-names = "uart", "apb_pclk";
 				status = "disabled";
 			};
 
 			usbphy0: usbphy@8007c000 {
 				compatible = "fsl,imx28-usbphy", "fsl,imx23-usbphy";
 				reg = <0x8007c000 0x2000>;
+				clocks = <&clks 62>;
 				status = "disabled";
 			};
 
 			usbphy1: usbphy@8007e000 {
 				compatible = "fsl,imx28-usbphy", "fsl,imx23-usbphy";
 				reg = <0x8007e000 0x2000>;
+				clocks = <&clks 63>;
 				status = "disabled";
 			};
 		};
@@ -754,6 +868,7 @@
 			compatible = "fsl,imx28-usb", "fsl,imx27-usb";
 			reg = <0x80080000 0x10000>;
 			interrupts = <93>;
+			clocks = <&clks 60>;
 			fsl,usbphy = <&usbphy0>;
 			status = "disabled";
 		};
@@ -762,6 +877,7 @@
 			compatible = "fsl,imx28-usb", "fsl,imx27-usb";
 			reg = <0x80090000 0x10000>;
 			interrupts = <92>;
+			clocks = <&clks 61>;
 			fsl,usbphy = <&usbphy1>;
 			status = "disabled";
 		};
@@ -775,6 +891,8 @@
 			compatible = "fsl,imx28-fec";
 			reg = <0x800f0000 0x4000>;
 			interrupts = <101>;
+			clocks = <&clks 57>, <&clks 57>;
+			clock-names = "ipg", "ahb";
 			status = "disabled";
 		};
 
@@ -782,6 +900,8 @@
 			compatible = "fsl,imx28-fec";
 			reg = <0x800f4000 0x4000>;
 			interrupts = <102>;
+			clocks = <&clks 57>, <&clks 57>;
+			clock-names = "ipg", "ahb";
 			status = "disabled";
 		};
 
diff --git a/arch/arm/boot/dts/imx51-babbage.dts b/arch/arm/boot/dts/imx51-babbage.dts
index 59d9789..cbd2b1c 100644
--- a/arch/arm/boot/dts/imx51-babbage.dts
+++ b/arch/arm/boot/dts/imx51-babbage.dts
@@ -25,23 +25,31 @@
 		aips@70000000 { /* aips-1 */
 			spba@70000000 {
 				esdhc@70004000 { /* ESDHC1 */
+					pinctrl-names = "default";
+					pinctrl-0 = <&pinctrl_esdhc1_1>;
 					fsl,cd-controller;
 					fsl,wp-controller;
 					status = "okay";
 				};
 
 				esdhc@70008000 { /* ESDHC2 */
+					pinctrl-names = "default";
+					pinctrl-0 = <&pinctrl_esdhc2_1>;
 					cd-gpios = <&gpio1 6 0>;
 					wp-gpios = <&gpio1 5 0>;
 					status = "okay";
 				};
 
 				uart3: serial@7000c000 {
+					pinctrl-names = "default";
+					pinctrl-0 = <&pinctrl_uart3_1>;
 					fsl,uart-has-rtscts;
 					status = "okay";
 				};
 
 				ecspi@70010000 { /* ECSPI1 */
+					pinctrl-names = "default";
+					pinctrl-0 = <&pinctrl_ecspi1_1>;
 					fsl,spi-num-chipselects = <2>;
 					cs-gpios = <&gpio4 24 0>, <&gpio4 25 0>;
 					status = "okay";
@@ -169,31 +177,43 @@
 				};
 			};
 
-			wdog@73f98000 { /* WDOG1 */
-				status = "okay";
-			};
-
 			iomuxc@73fa8000 {
-				compatible = "fsl,imx51-iomuxc-babbage";
-				reg = <0x73fa8000 0x4000>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_hog>;
+
+				hog {
+					pinctrl_hog: hoggrp {
+						fsl,pins = <
+							694  0x20d5	/* MX51_PAD_GPIO1_0__SD1_CD */
+							697  0x20d5	/* MX51_PAD_GPIO1_1__SD1_WP */
+							737  0x100	/* MX51_PAD_GPIO1_5__GPIO1_5 */
+							740  0x100	/* MX51_PAD_GPIO1_6__GPIO1_6 */
+							121  0x5	/* MX51_PAD_EIM_A27__GPIO2_21 */
+							402  0x85	/* MX51_PAD_CSPI1_SS0__GPIO4_24 */
+							405  0x85	/* MX51_PAD_CSPI1_SS1__GPIO4_25 */
+						>;
+					};
+				};
 			};
 
 			uart1: serial@73fbc000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_uart1_1>;
 				fsl,uart-has-rtscts;
 				status = "okay";
 			};
 
 			uart2: serial@73fc0000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_uart2_1>;
 				status = "okay";
 			};
 		};
 
 		aips@80000000 {	/* aips-2 */
-			sdma@83fb0000 {
-				fsl,sdma-ram-script-name = "imx/sdma/sdma-imx51.bin";
-			};
-
 			i2c@83fc4000 { /* I2C2 */
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_i2c2_1>;
 				status = "okay";
 
 				sgtl5000: codec@0a {
@@ -206,10 +226,14 @@
 			};
 
 			audmux@83fd0000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_audmux_1>;
 				status = "okay";
 			};
 
 			ethernet@83fec000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_fec_1>;
 				phy-mode = "mii";
 				status = "okay";
 			};
diff --git a/arch/arm/boot/dts/imx51.dtsi b/arch/arm/boot/dts/imx51.dtsi
index aba28dc..75d069f 100644
--- a/arch/arm/boot/dts/imx51.dtsi
+++ b/arch/arm/boot/dts/imx51.dtsi
@@ -130,6 +130,34 @@
 				};
 			};
 
+			usb@73f80000 {
+				compatible = "fsl,imx51-usb", "fsl,imx27-usb";
+				reg = <0x73f80000 0x0200>;
+				interrupts = <18>;
+				status = "disabled";
+			};
+
+			usb@73f80200 {
+				compatible = "fsl,imx51-usb", "fsl,imx27-usb";
+				reg = <0x73f80200 0x0200>;
+				interrupts = <14>;
+				status = "disabled";
+			};
+
+			usb@73f80400 {
+				compatible = "fsl,imx51-usb", "fsl,imx27-usb";
+				reg = <0x73f80400 0x0200>;
+				interrupts = <16>;
+				status = "disabled";
+			};
+
+			usb@73f80600 {
+				compatible = "fsl,imx51-usb", "fsl,imx27-usb";
+				reg = <0x73f80600 0x0200>;
+				interrupts = <17>;
+				status = "disabled";
+			};
+
 			gpio1: gpio@73f84000 {
 				compatible = "fsl,imx51-gpio", "fsl,imx35-gpio";
 				reg = <0x73f84000 0x4000>;
@@ -174,7 +202,6 @@
 				compatible = "fsl,imx51-wdt", "fsl,imx21-wdt";
 				reg = <0x73f98000 0x4000>;
 				interrupts = <58>;
-				status = "disabled";
 			};
 
 			wdog@73f9c000 { /* WDOG2 */
@@ -184,6 +211,122 @@
 				status = "disabled";
 			};
 
+			iomuxc@73fa8000 {
+				compatible = "fsl,imx51-iomuxc";
+				reg = <0x73fa8000 0x4000>;
+
+				audmux {
+					pinctrl_audmux_1: audmuxgrp-1 {
+						fsl,pins = <
+							384 0x80000000	/* MX51_PAD_AUD3_BB_TXD__AUD3_TXD */
+							386 0x80000000	/* MX51_PAD_AUD3_BB_RXD__AUD3_RXD */
+							389 0x80000000	/* MX51_PAD_AUD3_BB_CK__AUD3_TXC */
+							391 0x80000000	/* MX51_PAD_AUD3_BB_FS__AUD3_TXFS */
+						>;
+					};
+				};
+
+				fec {
+					pinctrl_fec_1: fecgrp-1 {
+						fsl,pins = <
+							128 0x80000000	/* MX51_PAD_EIM_EB2__FEC_MDIO */
+							134 0x80000000	/* MX51_PAD_EIM_EB3__FEC_RDATA1 */
+							146 0x80000000	/* MX51_PAD_EIM_CS2__FEC_RDATA2 */
+							152 0x80000000	/* MX51_PAD_EIM_CS3__FEC_RDATA3 */
+							158 0x80000000	/* MX51_PAD_EIM_CS4__FEC_RX_ER */
+							165 0x80000000	/* MX51_PAD_EIM_CS5__FEC_CRS */
+							206 0x80000000	/* MX51_PAD_NANDF_RB2__FEC_COL */
+							213 0x80000000	/* MX51_PAD_NANDF_RB3__FEC_RX_CLK */
+							293 0x80000000	/* MX51_PAD_NANDF_D9__FEC_RDATA0 */
+							298 0x80000000	/* MX51_PAD_NANDF_D8__FEC_TDATA0 */
+							225 0x80000000	/* MX51_PAD_NANDF_CS2__FEC_TX_ER */
+							231 0x80000000	/* MX51_PAD_NANDF_CS3__FEC_MDC */
+							237 0x80000000	/* MX51_PAD_NANDF_CS4__FEC_TDATA1 */
+							243 0x80000000	/* MX51_PAD_NANDF_CS5__FEC_TDATA2 */
+							250 0x80000000	/* MX51_PAD_NANDF_CS6__FEC_TDATA3 */
+							255 0x80000000	/* MX51_PAD_NANDF_CS7__FEC_TX_EN */
+							260 0x80000000	/* MX51_PAD_NANDF_RDY_INT__FEC_TX_CLK */
+						>;
+					};
+				};
+
+				ecspi1 {
+					pinctrl_ecspi1_1: ecspi1grp-1 {
+						fsl,pins = <
+							398 0x185	/* MX51_PAD_CSPI1_MISO__ECSPI1_MISO */
+							394 0x185	/* MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI */
+							409 0x185	/* MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK */
+						>;
+					};
+				};
+
+				esdhc1 {
+					pinctrl_esdhc1_1: esdhc1grp-1 {
+						fsl,pins = <
+							666 0x400020d5	/* MX51_PAD_SD1_CMD__SD1_CMD */
+							669 0x20d5	/* MX51_PAD_SD1_CLK__SD1_CLK */
+							672 0x20d5	/* MX51_PAD_SD1_DATA0__SD1_DATA0 */
+							678 0x20d5	/* MX51_PAD_SD1_DATA1__SD1_DATA1 */
+							684 0x20d5	/* MX51_PAD_SD1_DATA2__SD1_DATA2 */
+							691 0x20d5	/* MX51_PAD_SD1_DATA3__SD1_DATA3 */
+						>;
+					};
+				};
+
+				esdhc2 {
+					pinctrl_esdhc2_1: esdhc2grp-1 {
+						fsl,pins = <
+							704 0x400020d5	/* MX51_PAD_SD2_CMD__SD2_CMD */
+							707 0x20d5	/* MX51_PAD_SD2_CLK__SD2_CLK */
+							710 0x20d5	/* MX51_PAD_SD2_DATA0__SD2_DATA0 */
+							712 0x20d5	/* MX51_PAD_SD2_DATA1__SD2_DATA1 */
+							715 0x20d5	/* MX51_PAD_SD2_DATA2__SD2_DATA2 */
+							719 0x20d5	/* MX51_PAD_SD2_DATA3__SD2_DATA3 */
+						>;
+					};
+				};
+
+				i2c2 {
+					pinctrl_i2c2_1: i2c2grp-1 {
+						fsl,pins = <
+							449 0x400001ed	/* MX51_PAD_KEY_COL4__I2C2_SCL */
+							454 0x400001ed	/* MX51_PAD_KEY_COL5__I2C2_SDA */
+						>;
+					};
+				};
+
+				uart1 {
+					pinctrl_uart1_1: uart1grp-1 {
+						fsl,pins = <
+							413 0x1c5	/* MX51_PAD_UART1_RXD__UART1_RXD */
+							416 0x1c5	/* MX51_PAD_UART1_TXD__UART1_TXD */
+							418 0x1c5	/* MX51_PAD_UART1_RTS__UART1_RTS */
+							420 0x1c5	/* MX51_PAD_UART1_CTS__UART1_CTS */
+						>;
+					};
+				};
+
+				uart2 {
+					pinctrl_uart2_1: uart2grp-1 {
+						fsl,pins = <
+							423 0x1c5	/* MX51_PAD_UART2_RXD__UART2_RXD */
+							426 0x1c5	/* MX51_PAD_UART2_TXD__UART2_TXD */
+						>;
+					};
+				};
+
+				uart3 {
+					pinctrl_uart3_1: uart3grp-1 {
+						fsl,pins = <
+							54 0x1c5	/* MX51_PAD_EIM_D25__UART3_RXD */
+							59 0x1c5	/* MX51_PAD_EIM_D26__UART3_TXD */
+							65 0x1c5	/* MX51_PAD_EIM_D27__UART3_RTS */
+							49 0x1c5	/* MX51_PAD_EIM_D24__UART3_CTS */
+						>;
+					};
+				};
+			};
+
 			uart1: serial@73fbc000 {
 				compatible = "fsl,imx51-uart", "fsl,imx21-uart";
 				reg = <0x73fbc000 0x4000>;
@@ -219,6 +362,7 @@
 				compatible = "fsl,imx51-sdma", "fsl,imx35-sdma";
 				reg = <0x83fb0000 0x4000>;
 				interrupts = <6>;
+				fsl,sdma-ram-script-name = "imx/sdma/sdma-imx51.bin";
 			};
 
 			cspi@83fc0000 {
@@ -263,6 +407,13 @@
 				status = "disabled";
 			};
 
+			nand@83fdb000 {
+				compatible = "fsl,imx51-nand";
+				reg = <0x83fdb000 0x1000 0xcfff0000 0x10000>;
+				interrupts = <8>;
+				status = "disabled";
+			};
+
 			ssi3: ssi@83fe8000 {
 				compatible = "fsl,imx51-ssi", "fsl,imx21-ssi";
 				reg = <0x83fe8000 0x4000>;
diff --git a/arch/arm/boot/dts/imx53-ard.dts b/arch/arm/boot/dts/imx53-ard.dts
index da895e9..4be76f2 100644
--- a/arch/arm/boot/dts/imx53-ard.dts
+++ b/arch/arm/boot/dts/imx53-ard.dts
@@ -25,31 +25,66 @@
 		aips@50000000 { /* AIPS1 */
 			spba@50000000 {
 				esdhc@50004000 { /* ESDHC1 */
+					pinctrl-names = "default";
+					pinctrl-0 = <&pinctrl_esdhc1_2>;
 					cd-gpios = <&gpio1 1 0>;
 					wp-gpios = <&gpio1 9 0>;
 					status = "okay";
 				};
 			};
 
-			wdog@53f98000 { /* WDOG1 */
-				status = "okay";
-			};
-
 			iomuxc@53fa8000 {
-				compatible = "fsl,imx53-iomuxc-ard";
-				reg = <0x53fa8000 0x4000>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_hog>;
+
+				hog {
+					pinctrl_hog: hoggrp {
+						fsl,pins = <
+							1077 0x80000000	/* MX53_PAD_GPIO_1__GPIO1_1 */
+							1085 0x80000000	/* MX53_PAD_GPIO_9__GPIO1_9 */
+							486  0x80000000	/* MX53_PAD_EIM_EB3__GPIO2_31 */
+							739  0x80000000	/* MX53_PAD_GPIO_10__GPIO4_0 */
+							218  0x80000000	/* MX53_PAD_DISP0_DAT16__GPIO5_10 */
+							226  0x80000000	/* MX53_PAD_DISP0_DAT17__GPIO5_11 */
+							233  0x80000000	/* MX53_PAD_DISP0_DAT18__GPIO5_12 */
+							241  0x80000000	/* MX53_PAD_DISP0_DAT19__GPIO5_13 */
+							429  0x80000000	/* MX53_PAD_EIM_D16__EMI_WEIM_D_16 */
+							435  0x80000000	/* MX53_PAD_EIM_D17__EMI_WEIM_D_17 */
+							441  0x80000000	/* MX53_PAD_EIM_D18__EMI_WEIM_D_18 */
+							448  0x80000000	/* MX53_PAD_EIM_D19__EMI_WEIM_D_19 */
+							456  0x80000000	/* MX53_PAD_EIM_D20__EMI_WEIM_D_20 */
+							464  0x80000000	/* MX53_PAD_EIM_D21__EMI_WEIM_D_21 */
+							471  0x80000000	/* MX53_PAD_EIM_D22__EMI_WEIM_D_22 */
+							477  0x80000000	/* MX53_PAD_EIM_D23__EMI_WEIM_D_23 */
+							492  0x80000000	/* MX53_PAD_EIM_D24__EMI_WEIM_D_24 */
+							500  0x80000000	/* MX53_PAD_EIM_D25__EMI_WEIM_D_25 */
+							508  0x80000000	/* MX53_PAD_EIM_D26__EMI_WEIM_D_26 */
+							516  0x80000000	/* MX53_PAD_EIM_D27__EMI_WEIM_D_27 */
+							524  0x80000000	/* MX53_PAD_EIM_D28__EMI_WEIM_D_28 */
+							532  0x80000000	/* MX53_PAD_EIM_D29__EMI_WEIM_D_29 */
+							540  0x80000000	/* MX53_PAD_EIM_D30__EMI_WEIM_D_30 */
+							548  0x80000000	/* MX53_PAD_EIM_D31__EMI_WEIM_D_31 */
+							637  0x80000000	/* MX53_PAD_EIM_DA0__EMI_NAND_WEIM_DA_0 */
+							642  0x80000000	/* MX53_PAD_EIM_DA1__EMI_NAND_WEIM_DA_1 */
+							647  0x80000000	/* MX53_PAD_EIM_DA2__EMI_NAND_WEIM_DA_2 */
+							652  0x80000000	/* MX53_PAD_EIM_DA3__EMI_NAND_WEIM_DA_3 */
+							657  0x80000000	/* MX53_PAD_EIM_DA4__EMI_NAND_WEIM_DA_4 */
+							662  0x80000000	/* MX53_PAD_EIM_DA5__EMI_NAND_WEIM_DA_5 */
+							667  0x80000000	/* MX53_PAD_EIM_DA6__EMI_NAND_WEIM_DA_6 */
+							611  0x80000000	/* MX53_PAD_EIM_OE__EMI_WEIM_OE */
+							616  0x80000000	/* MX53_PAD_EIM_RW__EMI_WEIM_RW */
+							607  0x80000000	/* MX53_PAD_EIM_CS1__EMI_WEIM_CS_1 */
+						>;
+					};
+				};
 			};
 
 			uart1: serial@53fbc000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_uart1_2>;
 				status = "okay";
 			};
 		};
-
-		aips@60000000 {	/* AIPS2 */
-			sdma@63fb0000 {
-				fsl,sdma-ram-script-name = "imx/sdma/sdma-imx53.bin";
-			};
-		};
 	};
 
 	eim-cs1@f4000000 {
diff --git a/arch/arm/boot/dts/imx53-evk.dts b/arch/arm/boot/dts/imx53-evk.dts
index 9c79803..a124d1e 100644
--- a/arch/arm/boot/dts/imx53-evk.dts
+++ b/arch/arm/boot/dts/imx53-evk.dts
@@ -25,12 +25,16 @@
 		aips@50000000 { /* AIPS1 */
 			spba@50000000 {
 				esdhc@50004000 { /* ESDHC1 */
+					pinctrl-names = "default";
+					pinctrl-0 = <&pinctrl_esdhc1_1>;
 					cd-gpios = <&gpio3 13 0>;
 					wp-gpios = <&gpio3 14 0>;
 					status = "okay";
 				};
 
 				ecspi@50010000 { /* ECSPI1 */
+					pinctrl-names = "default";
+					pinctrl-0 = <&pinctrl_ecspi1_1>;
 					fsl,spi-num-chipselects = <2>;
 					cs-gpios = <&gpio2 30 0>, <&gpio3 19 0>;
 					status = "okay";
@@ -56,32 +60,45 @@
 				};
 
 				esdhc@50020000 { /* ESDHC3 */
+					pinctrl-names = "default";
+					pinctrl-0 = <&pinctrl_esdhc3_1>;
 					cd-gpios = <&gpio3 11 0>;
 					wp-gpios = <&gpio3 12 0>;
 					status = "okay";
 				};
 			};
 
-			wdog@53f98000 { /* WDOG1 */
-				status = "okay";
-			};
-
 			iomuxc@53fa8000 {
-				compatible = "fsl,imx53-iomuxc-evk";
-				reg = <0x53fa8000 0x4000>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_hog>;
+
+				hog {
+					pinctrl_hog: hoggrp {
+						fsl,pins = <
+							424  0x80000000	/* MX53_PAD_EIM_EB2__GPIO2_30 */
+							449  0x80000000	/* MX53_PAD_EIM_D19__GPIO3_19 */
+							693  0x80000000	/* MX53_PAD_EIM_DA11__GPIO3_11 */
+							697  0x80000000	/* MX53_PAD_EIM_DA12__GPIO3_12 */
+							701  0x80000000	/* MX53_PAD_EIM_DA13__GPIO3_13 */
+							705  0x80000000	/* MX53_PAD_EIM_DA14__GPIO3_14 */
+							868  0x80000000	/* MX53_PAD_PATA_DA_0__GPIO7_6 */
+							873  0x80000000	/* MX53_PAD_PATA_DA_1__GPIO7_7 */
+						>;
+					};
+				};
 			};
 
 			uart1: serial@53fbc000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_uart1_1>;
 				status = "okay";
 			};
 		};
 
 		aips@60000000 {	/* AIPS2 */
-			sdma@63fb0000 {
-				fsl,sdma-ram-script-name = "imx/sdma/sdma-imx53.bin";
-			};
-
 			i2c@63fc4000 { /* I2C2 */
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_i2c2_1>;
 				status = "okay";
 
 				pmic: mc13892@08 {
@@ -96,6 +113,8 @@
 			};
 
 			ethernet@63fec000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_fec_1>;
 				phy-mode = "rmii";
 				phy-reset-gpios = <&gpio7 6 0>;
 				status = "okay";
diff --git a/arch/arm/boot/dts/imx53-qsb.dts b/arch/arm/boot/dts/imx53-qsb.dts
index 2d803a9..08948af 100644
--- a/arch/arm/boot/dts/imx53-qsb.dts
+++ b/arch/arm/boot/dts/imx53-qsb.dts
@@ -25,6 +25,8 @@
 		aips@50000000 { /* AIPS1 */
 			spba@50000000 {
 				esdhc@50004000 { /* ESDHC1 */
+					pinctrl-names = "default";
+					pinctrl-0 = <&pinctrl_esdhc1_1>;
 					cd-gpios = <&gpio3 13 0>;
 					status = "okay";
 				};
@@ -35,32 +37,46 @@
 				};
 
 				esdhc@50020000 { /* ESDHC3 */
+					pinctrl-names = "default";
+					pinctrl-0 = <&pinctrl_esdhc3_1>;
 					cd-gpios = <&gpio3 11 0>;
 					wp-gpios = <&gpio3 12 0>;
 					status = "okay";
 				};
 			};
 
-			wdog@53f98000 { /* WDOG1 */
-				status = "okay";
-			};
-
 			iomuxc@53fa8000 {
-				compatible = "fsl,imx53-iomuxc-qsb";
-				reg = <0x53fa8000 0x4000>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_hog>;
+
+				hog {
+					pinctrl_hog: hoggrp {
+						fsl,pins = <
+							1071 0x80000000	/* MX53_PAD_GPIO_0__CCM_SSI_EXT1_CLK */
+							1141 0x80000000	/* MX53_PAD_GPIO_8__GPIO1_8 */
+							982  0x80000000	/* MX53_PAD_PATA_DATA14__GPIO2_14 */
+							989  0x80000000	/* MX53_PAD_PATA_DATA15__GPIO2_15 */
+							693  0x80000000	/* MX53_PAD_EIM_DA11__GPIO3_11 */
+							697  0x80000000	/* MX53_PAD_EIM_DA12__GPIO3_12 */
+							701  0x80000000	/* MX53_PAD_EIM_DA13__GPIO3_13 */
+							868  0x80000000	/* MX53_PAD_PATA_DA_0__GPIO7_6 */
+							873  0x80000000	/* MX53_PAD_PATA_DA_1__GPIO7_7 */
+						>;
+					};
+				};
 			};
 
 			uart1: serial@53fbc000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_uart1_1>;
 				status = "okay";
 			};
 		};
 
 		aips@60000000 {	/* AIPS2 */
-			sdma@63fb0000 {
-				fsl,sdma-ram-script-name = "imx/sdma/sdma-imx53.bin";
-			};
-
 			i2c@63fc4000 { /* I2C2 */
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_i2c2_1>;
 				status = "okay";
 
 				sgtl5000: codec@0a {
@@ -72,6 +88,8 @@
 			};
 
 			i2c@63fc8000 { /* I2C1 */
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_i2c1_1>;
 				status = "okay";
 
 				accelerometer: mma8450@1c {
@@ -158,10 +176,14 @@
 			};
 
 			audmux@63fd0000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_audmux_1>;
 				status = "okay";
 			};
 
 			ethernet@63fec000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_fec_1>;
 				phy-mode = "rmii";
 				phy-reset-gpios = <&gpio7 6 0>;
 				status = "okay";
diff --git a/arch/arm/boot/dts/imx53-smd.dts b/arch/arm/boot/dts/imx53-smd.dts
index 0809102..06c6858 100644
--- a/arch/arm/boot/dts/imx53-smd.dts
+++ b/arch/arm/boot/dts/imx53-smd.dts
@@ -25,22 +25,30 @@
 		aips@50000000 { /* AIPS1 */
 			spba@50000000 {
 				esdhc@50004000 { /* ESDHC1 */
+					pinctrl-names = "default";
+					pinctrl-0 = <&pinctrl_esdhc1_1>;
 					cd-gpios = <&gpio3 13 0>;
 					wp-gpios = <&gpio4 11 0>;
 					status = "okay";
 				};
 
 				esdhc@50008000 { /* ESDHC2 */
+					pinctrl-names = "default";
+					pinctrl-0 = <&pinctrl_esdhc2_1>;
 					non-removable;
 					status = "okay";
 				};
 
 				uart3: serial@5000c000 {
+					pinctrl-names = "default";
+					pinctrl-0 = <&pinctrl_uart3_1>;
 					fsl,uart-has-rtscts;
 					status = "okay";
 				};
 
 				ecspi@50010000 { /* ECSPI1 */
+					pinctrl-names = "default";
+					pinctrl-0 = <&pinctrl_ecspi1_1>;
 					fsl,spi-num-chipselects = <2>;
 					cs-gpios = <&gpio2 30 0>, <&gpio3 19 0>;
 					status = "okay";
@@ -72,35 +80,49 @@
 				};
 
 				esdhc@50020000 { /* ESDHC3 */
+					pinctrl-names = "default";
+					pinctrl-0 = <&pinctrl_esdhc3_1>;
 					non-removable;
 					status = "okay";
 				};
 			};
 
-			wdog@53f98000 { /* WDOG1 */
-				status = "okay";
-			};
-
 			iomuxc@53fa8000 {
-				compatible = "fsl,imx53-iomuxc-smd";
-				reg = <0x53fa8000 0x4000>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_hog>;
+
+				hog {
+					pinctrl_hog: hoggrp {
+						fsl,pins = <
+							982  0x80000000	/* MX53_PAD_PATA_DATA14__GPIO2_14 */
+							989  0x80000000	/* MX53_PAD_PATA_DATA15__GPIO2_15 */
+							424  0x80000000	/* MX53_PAD_EIM_EB2__GPIO2_30 */
+							701  0x80000000	/* MX53_PAD_EIM_DA13__GPIO3_13 */
+							449  0x80000000	/* MX53_PAD_EIM_D19__GPIO3_19 */
+							43   0x80000000	/* MX53_PAD_KEY_ROW2__GPIO4_11 */
+							868  0x80000000	/* MX53_PAD_PATA_DA_0__GPIO7_6 */
+						>;
+					};
+				};
 			};
 
 			uart1: serial@53fbc000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_uart1_1>;
 				status = "okay";
 			};
 
 			uart2: serial@53fc0000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_uart2_1>;
 				status = "okay";
 			};
 		};
 
 		aips@60000000 {	/* AIPS2 */
-			sdma@63fb0000 {
-				fsl,sdma-ram-script-name = "imx/sdma/sdma-imx53.bin";
-			};
-
 			i2c@63fc4000 { /* I2C2 */
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_i2c2_1>;
 				status = "okay";
 
 				codec: sgtl5000@0a {
@@ -120,6 +142,8 @@
 			};
 
 			i2c@63fc8000 { /* I2C1 */
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_i2c1_1>;
 				status = "okay";
 
 				accelerometer: mma8450@1c {
@@ -139,6 +163,8 @@
 			};
 
 			ethernet@63fec000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_fec_1>;
 				phy-mode = "rmii";
 				phy-reset-gpios = <&gpio7 6 0>;
 				status = "okay";
diff --git a/arch/arm/boot/dts/imx53.dtsi b/arch/arm/boot/dts/imx53.dtsi
index cd37165..76ebb1a 100644
--- a/arch/arm/boot/dts/imx53.dtsi
+++ b/arch/arm/boot/dts/imx53.dtsi
@@ -135,6 +135,34 @@
 				};
 			};
 
+			usb@53f80000 {
+				compatible = "fsl,imx53-usb", "fsl,imx27-usb";
+				reg = <0x53f80000 0x0200>;
+				interrupts = <18>;
+				status = "disabled";
+			};
+
+			usb@53f80200 {
+				compatible = "fsl,imx53-usb", "fsl,imx27-usb";
+				reg = <0x53f80200 0x0200>;
+				interrupts = <14>;
+				status = "disabled";
+			};
+
+			usb@53f80400 {
+				compatible = "fsl,imx53-usb", "fsl,imx27-usb";
+				reg = <0x53f80400 0x0200>;
+				interrupts = <16>;
+				status = "disabled";
+			};
+
+			usb@53f80600 {
+				compatible = "fsl,imx53-usb", "fsl,imx27-usb";
+				reg = <0x53f80600 0x0200>;
+				interrupts = <17>;
+				status = "disabled";
+			};
+
 			gpio1: gpio@53f84000 {
 				compatible = "fsl,imx53-gpio", "fsl,imx35-gpio";
 				reg = <0x53f84000 0x4000>;
@@ -179,7 +207,6 @@
 				compatible = "fsl,imx53-wdt", "fsl,imx21-wdt";
 				reg = <0x53f98000 0x4000>;
 				interrupts = <58>;
-				status = "disabled";
 			};
 
 			wdog@53f9c000 { /* WDOG2 */
@@ -189,6 +216,161 @@
 				status = "disabled";
 			};
 
+			iomuxc@53fa8000 {
+				compatible = "fsl,imx53-iomuxc";
+				reg = <0x53fa8000 0x4000>;
+
+				audmux {
+					pinctrl_audmux_1: audmuxgrp-1 {
+						fsl,pins = <
+							10 0x80000000	/* MX53_PAD_KEY_COL0__AUDMUX_AUD5_TXC */
+							17 0x80000000	/* MX53_PAD_KEY_ROW0__AUDMUX_AUD5_TXD */
+							23 0x80000000	/* MX53_PAD_KEY_COL1__AUDMUX_AUD5_TXFS */
+							30 0x80000000	/* MX53_PAD_KEY_ROW1__AUDMUX_AUD5_RXD */
+						>;
+					};
+				};
+
+				fec {
+					pinctrl_fec_1: fecgrp-1 {
+						fsl,pins = <
+							820 0x80000000	/* MX53_PAD_FEC_MDC__FEC_MDC */
+							779 0x80000000	/* MX53_PAD_FEC_MDIO__FEC_MDIO */
+							786 0x80000000	/* MX53_PAD_FEC_REF_CLK__FEC_TX_CLK */
+							791 0x80000000	/* MX53_PAD_FEC_RX_ER__FEC_RX_ER */
+							796 0x80000000	/* MX53_PAD_FEC_CRS_DV__FEC_RX_DV */
+							799 0x80000000	/* MX53_PAD_FEC_RXD1__FEC_RDATA_1 */
+							804 0x80000000	/* MX53_PAD_FEC_RXD0__FEC_RDATA_0 */
+							808 0x80000000	/* MX53_PAD_FEC_TX_EN__FEC_TX_EN */
+							811 0x80000000	/* MX53_PAD_FEC_TXD1__FEC_TDATA_1 */
+							816 0x80000000	/* MX53_PAD_FEC_TXD0__FEC_TDATA_0 */
+						>;
+					};
+				};
+
+				ecspi1 {
+					pinctrl_ecspi1_1: ecspi1grp-1 {
+						fsl,pins = <
+							433 0x80000000	/* MX53_PAD_EIM_D16__ECSPI1_SCLK */
+							439 0x80000000	/* MX53_PAD_EIM_D17__ECSPI1_MISO */
+							445 0x80000000	/* MX53_PAD_EIM_D18__ECSPI1_MOSI */
+						>;
+					};
+				};
+
+				esdhc1 {
+					pinctrl_esdhc1_1: esdhc1grp-1 {
+						fsl,pins = <
+							995  0x1d5	/* MX53_PAD_SD1_DATA0__ESDHC1_DAT0 */
+							1000 0x1d5	/* MX53_PAD_SD1_DATA1__ESDHC1_DAT1 */
+							1010 0x1d5	/* MX53_PAD_SD1_DATA2__ESDHC1_DAT2 */
+							1024 0x1d5	/* MX53_PAD_SD1_DATA3__ESDHC1_DAT3 */
+							1005 0x1d5	/* MX53_PAD_SD1_CMD__ESDHC1_CMD */
+							1018 0x1d5	/* MX53_PAD_SD1_CLK__ESDHC1_CLK */
+						>;
+					};
+
+					pinctrl_esdhc1_2: esdhc1grp-2 {
+						fsl,pins = <
+							995  0x1d5	/* MX53_PAD_SD1_DATA0__ESDHC1_DAT0 */
+							1000 0x1d5	/* MX53_PAD_SD1_DATA1__ESDHC1_DAT1 */
+							1010 0x1d5	/* MX53_PAD_SD1_DATA2__ESDHC1_DAT2 */
+							1024 0x1d5	/* MX53_PAD_SD1_DATA3__ESDHC1_DAT3 */
+							941  0x1d5	/* MX53_PAD_PATA_DATA8__ESDHC1_DAT4 */
+							948  0x1d5	/* MX53_PAD_PATA_DATA9__ESDHC1_DAT5 */
+							955  0x1d5	/* MX53_PAD_PATA_DATA10__ESDHC1_DAT6 */
+							962  0x1d5	/* MX53_PAD_PATA_DATA11__ESDHC1_DAT7 */
+							1005 0x1d5	/* MX53_PAD_SD1_CMD__ESDHC1_CMD */
+							1018 0x1d5	/* MX53_PAD_SD1_CLK__ESDHC1_CLK */
+						>;
+					};
+				};
+
+				esdhc2 {
+					pinctrl_esdhc2_1: esdhc2grp-1 {
+						fsl,pins = <
+							1038 0x1d5	/* MX53_PAD_SD2_CMD__ESDHC2_CMD */
+							1032 0x1d5	/* MX53_PAD_SD2_CLK__ESDHC2_CLK */
+							1062 0x1d5	/* MX53_PAD_SD2_DATA0__ESDHC2_DAT0 */
+							1056 0x1d5	/* MX53_PAD_SD2_DATA1__ESDHC2_DAT1 */
+							1050 0x1d5	/* MX53_PAD_SD2_DATA2__ESDHC2_DAT2 */
+							1044 0x1d5	/* MX53_PAD_SD2_DATA3__ESDHC2_DAT3 */
+						>;
+					};
+				};
+
+				esdhc3 {
+					pinctrl_esdhc3_1: esdhc3grp-1 {
+						fsl,pins = <
+							943 0x1d5	/* MX53_PAD_PATA_DATA8__ESDHC3_DAT0 */
+							950 0x1d5	/* MX53_PAD_PATA_DATA9__ESDHC3_DAT1 */
+							957 0x1d5	/* MX53_PAD_PATA_DATA10__ESDHC3_DAT2 */
+							964 0x1d5	/* MX53_PAD_PATA_DATA11__ESDHC3_DAT3 */
+							893 0x1d5	/* MX53_PAD_PATA_DATA0__ESDHC3_DAT4 */
+							900 0x1d5	/* MX53_PAD_PATA_DATA1__ESDHC3_DAT5 */
+							906 0x1d5	/* MX53_PAD_PATA_DATA2__ESDHC3_DAT6 */
+							912 0x1d5	/* MX53_PAD_PATA_DATA3__ESDHC3_DAT7 */
+							857 0x1d5	/* MX53_PAD_PATA_RESET_B__ESDHC3_CMD */
+							863 0x1d5	/* MX53_PAD_PATA_IORDY__ESDHC3_CLK */
+						>;
+					};
+				};
+
+				i2c1 {
+					pinctrl_i2c1_1: i2c1grp-1 {
+						fsl,pins = <
+							333 0xc0000000	/* MX53_PAD_CSI0_DAT8__I2C1_SDA */
+							341 0xc0000000	/* MX53_PAD_CSI0_DAT9__I2C1_SCL */
+						>;
+					};
+				};
+
+				i2c2 {
+					pinctrl_i2c2_1: i2c2grp-1 {
+						fsl,pins = <
+							61 0xc0000000	/* MX53_PAD_KEY_ROW3__I2C2_SDA */
+							53 0xc0000000	/* MX53_PAD_KEY_COL3__I2C2_SCL */
+						>;
+					};
+				};
+
+				uart1 {
+					pinctrl_uart1_1: uart1grp-1 {
+						fsl,pins = <
+							346 0x1c5	/* MX53_PAD_CSI0_DAT10__UART1_TXD_MUX */
+							354 0x1c5	/* MX53_PAD_CSI0_DAT11__UART1_RXD_MUX */
+						>;
+					};
+
+					pinctrl_uart1_2: uart1grp-2 {
+						fsl,pins = <
+							828 0x1c5	/* MX53_PAD_PATA_DIOW__UART1_TXD_MUX */
+							832 0x1c5	/* MX53_PAD_PATA_DMACK__UART1_RXD_MUX */
+						>;
+					};
+				};
+
+				uart2 {
+					pinctrl_uart2_1: uart2grp-1 {
+						fsl,pins = <
+							841 0x1c5	/* MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX */
+							836 0x1c5	/* MX53_PAD_PATA_DMARQ__UART2_TXD_MUX */
+						>;
+					};
+				};
+
+				uart3 {
+					pinctrl_uart3_1: uart3grp-1 {
+						fsl,pins = <
+							884 0x1c5	/* MX53_PAD_PATA_CS_0__UART3_TXD_MUX */
+							888 0x1c5	/* MX53_PAD_PATA_CS_1__UART3_RXD_MUX */
+							875 0x1c5	/* MX53_PAD_PATA_DA_1__UART3_CTS */
+							880 0x1c5	/* MX53_PAD_PATA_DA_2__UART3_RTS */
+						>;
+					};
+				};
+			};
+
 			uart1: serial@53fbc000 {
 				compatible = "fsl,imx53-uart", "fsl,imx21-uart";
 				reg = <0x53fbc000 0x4000>;
@@ -203,6 +385,20 @@
 				status = "disabled";
 			};
 
+			can1: can@53fc8000 {
+				compatible = "fsl,imx53-flexcan", "fsl,p1010-flexcan";
+				reg = <0x53fc8000 0x4000>;
+				interrupts = <82>;
+				status = "disabled";
+			};
+
+			can2: can@53fcc000 {
+				compatible = "fsl,imx53-flexcan", "fsl,p1010-flexcan";
+				reg = <0x53fcc000 0x4000>;
+				interrupts = <83>;
+				status = "disabled";
+			};
+
 			gpio5: gpio@53fdc000 {
 				compatible = "fsl,imx53-gpio", "fsl,imx35-gpio";
 				reg = <0x53fdc000 0x4000>;
@@ -277,6 +473,7 @@
 				compatible = "fsl,imx53-sdma", "fsl,imx35-sdma";
 				reg = <0x63fb0000 0x4000>;
 				interrupts = <6>;
+				fsl,sdma-ram-script-name = "imx/sdma/sdma-imx53.bin";
 			};
 
 			cspi@63fc0000 {
@@ -321,6 +518,13 @@
 				status = "disabled";
 			};
 
+			nand@63fdb000 {
+				compatible = "fsl,imx53-nand";
+				reg = <0x63fdb000 0x1000 0xf7ff0000 0x10000>;
+				interrupts = <8>;
+				status = "disabled";
+			};
+
 			ssi3: ssi@63fe8000 {
 				compatible = "fsl,imx53-ssi", "fsl,imx21-ssi";
 				reg = <0x63fe8000 0x4000>;
diff --git a/arch/arm/boot/dts/imx6q-arm2.dts b/arch/arm/boot/dts/imx6q-arm2.dts
index d792581..15df4c1 100644
--- a/arch/arm/boot/dts/imx6q-arm2.dts
+++ b/arch/arm/boot/dts/imx6q-arm2.dts
@@ -28,8 +28,27 @@
 			status = "disabled"; /* gpmi nand conflicts with SD */
 		};
 
+		aips-bus@02000000 { /* AIPS1 */
+			iomuxc@020e0000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_hog>;
+
+				hog {
+					pinctrl_hog: hoggrp {
+						fsl,pins = <
+							176  0x80000000	/* MX6Q_PAD_EIM_D25__GPIO_3_25 */
+							1363 0x80000000	/* MX6Q_PAD_NANDF_CS0__GPIO_6_11 */
+							1369 0x80000000 /* MX6Q_PAD_NANDF_CS1__GPIO_6_14 */
+						>;
+					};
+				};
+			};
+		};
+
 		aips-bus@02100000 { /* AIPS2 */
 			ethernet@02188000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_enet_2>;
 				phy-mode = "rgmii";
 				status = "okay";
 			};
@@ -52,6 +71,8 @@
 			};
 
 			uart4: serial@021f0000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_uart4_1>;
 				status = "okay";
 			};
 		};
diff --git a/arch/arm/boot/dts/imx6q-sabrelite.dts b/arch/arm/boot/dts/imx6q-sabrelite.dts
index 72f30f3..d152328 100644
--- a/arch/arm/boot/dts/imx6q-sabrelite.dts
+++ b/arch/arm/boot/dts/imx6q-sabrelite.dts
@@ -46,15 +46,20 @@
 
 			iomuxc@020e0000 {
 				pinctrl-names = "default";
-				pinctrl-0 = <&pinctrl_gpio_hog>;
+				pinctrl-0 = <&pinctrl_hog>;
 
-				gpios {
-					pinctrl_gpio_hog: gpiohog {
+				hog {
+					pinctrl_hog: hoggrp {
 						fsl,pins = <
-							   144  0x80000000	/* MX6Q_PAD_EIM_D22__GPIO_3_22 */
-							   121  0x80000000	/* MX6Q_PAD_EIM_D19__GPIO_3_19 */
-							   953  0x80000000	/* MX6Q_PAD_GPIO_0__CCM_CLKO */
-							   >;
+							1450 0x80000000	/* MX6Q_PAD_NANDF_D6__GPIO_2_6 */
+							1458 0x80000000	/* MX6Q_PAD_NANDF_D7__GPIO_2_7 */
+							121  0x80000000	/* MX6Q_PAD_EIM_D19__GPIO_3_19 */
+							144  0x80000000	/* MX6Q_PAD_EIM_D22__GPIO_3_22 */
+							152  0x80000000	/* MX6Q_PAD_EIM_D23__GPIO_3_23 */
+							1262 0x80000000 /* MX6Q_PAD_SD3_DAT5__GPIO_7_0 */
+							1270 0x1f0b0	/* MX6Q_PAD_SD3_DAT4__GPIO_7_1 */
+							953  0x80000000	/* MX6Q_PAD_GPIO_0__CCM_CLKO */
+						>;
 					};
 				};
 			};
@@ -63,6 +68,9 @@
 		aips-bus@02100000 { /* AIPS2 */
 			usb@02184000 { /* USB OTG */
 				vbus-supply = <&reg_usb_otg_vbus>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_usbotg_1>;
+				disable-over-current;
 				status = "okay";
 			};
 
@@ -71,12 +79,16 @@
 			};
 
 			ethernet@02188000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_enet_1>;
 				phy-mode = "rgmii";
 				phy-reset-gpios = <&gpio3 23 0>;
 				status = "okay";
 			};
 
 			usdhc@02198000 { /* uSDHC3 */
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_usdhc3_2>;
 				cd-gpios = <&gpio7 0 0>;
 				wp-gpios = <&gpio7 1 0>;
 				vmmc-supply = <&reg_3p3v>;
@@ -84,6 +96,8 @@
 			};
 
 			usdhc@0219c000 { /* uSDHC4 */
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_usdhc4_2>;
 				cd-gpios = <&gpio2 6 0>;
 				wp-gpios = <&gpio2 7 0>;
 				vmmc-supply = <&reg_3p3v>;
@@ -99,7 +113,7 @@
 			uart2: serial@021e8000 {
 				status = "okay";
 				pinctrl-names = "default";
-				pinctrl-0 = <&pinctrl_serial2_1>;
+				pinctrl-0 = <&pinctrl_uart2_1>;
 			};
 
 			i2c@021a0000 { /* I2C1 */
@@ -111,6 +125,7 @@
 				codec: sgtl5000@0a {
 					compatible = "fsl,sgtl5000";
 					reg = <0x0a>;
+					clocks = <&clks 169>;
 					VDDA-supply = <&reg_2p5v>;
 					VDDIO-supply = <&reg_3p3v>;
 				};
diff --git a/arch/arm/boot/dts/imx6q-sabresd.dts b/arch/arm/boot/dts/imx6q-sabresd.dts
index 07509a1..e596c28c 100644
--- a/arch/arm/boot/dts/imx6q-sabresd.dts
+++ b/arch/arm/boot/dts/imx6q-sabresd.dts
@@ -22,28 +22,51 @@
 	};
 
 	soc {
-
 		aips-bus@02000000 { /* AIPS1 */
 			spba-bus@02000000 {
 				uart1: serial@02020000 {
+					pinctrl-names = "default";
+					pinctrl-0 = <&pinctrl_uart1_1>;
 					status = "okay";
 				};
 			};
+
+			iomuxc@020e0000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_hog>;
+
+				hog {
+					pinctrl_hog: hoggrp {
+						fsl,pins = <
+							1402 0x80000000	/* MX6Q_PAD_NANDF_D0__GPIO_2_0 */
+							1410 0x80000000	/* MX6Q_PAD_NANDF_D1__GPIO_2_1 */
+							1418 0x80000000	/* MX6Q_PAD_NANDF_D2__GPIO_2_2 */
+							1426 0x80000000	/* MX6Q_PAD_NANDF_D3__GPIO_2_3 */
+						>;
+					};
+				};
+			};
 		};
 
 		aips-bus@02100000 { /* AIPS2 */
 			ethernet@02188000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_enet_1>;
 				phy-mode = "rgmii";
 				status = "okay";
 			};
 
 			usdhc@02194000 { /* uSDHC2 */
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_usdhc2_1>;
 				cd-gpios = <&gpio2 2 0>;
 				wp-gpios = <&gpio2 3 0>;
 				status = "okay";
 			};
 
 			usdhc@02198000 { /* uSDHC3 */
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_usdhc3_1>;
 				cd-gpios = <&gpio2 0 0>;
 				wp-gpios = <&gpio2 1 0>;
 				status = "okay";
diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi
index fd57079..f3990b0 100644
--- a/arch/arm/boot/dts/imx6q.dtsi
+++ b/arch/arm/boot/dts/imx6q.dtsi
@@ -97,18 +97,23 @@
 		dma-apbh@00110000 {
 			compatible = "fsl,imx6q-dma-apbh", "fsl,imx28-dma-apbh";
 			reg = <0x00110000 0x2000>;
+			clocks = <&clks 106>;
 		};
 
 		gpmi-nand@00112000 {
-		       compatible = "fsl,imx6q-gpmi-nand";
-		       #address-cells = <1>;
-		       #size-cells = <1>;
-		       reg = <0x00112000 0x2000>, <0x00114000 0x2000>;
-		       reg-names = "gpmi-nand", "bch";
-		       interrupts = <0 13 0x04>, <0 15 0x04>;
-		       interrupt-names = "gpmi-dma", "bch";
-		       fsl,gpmi-dma-channel = <0>;
-		       status = "disabled";
+			compatible = "fsl,imx6q-gpmi-nand";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x00112000 0x2000>, <0x00114000 0x2000>;
+			reg-names = "gpmi-nand", "bch";
+			interrupts = <0 13 0x04>, <0 15 0x04>;
+			interrupt-names = "gpmi-dma", "bch";
+			clocks = <&clks 152>, <&clks 153>, <&clks 151>,
+				 <&clks 150>, <&clks 149>;
+			clock-names = "gpmi_io", "gpmi_apb", "gpmi_bch",
+				      "gpmi_bch_apb", "per1_bch";
+			fsl,gpmi-dma-channel = <0>;
+			status = "disabled";
 		};
 
 		timer@00a00600 {
@@ -150,6 +155,8 @@
 					compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
 					reg = <0x02008000 0x4000>;
 					interrupts = <0 31 0x04>;
+					clocks = <&clks 112>, <&clks 112>;
+					clock-names = "ipg", "per";
 					status = "disabled";
 				};
 
@@ -159,6 +166,8 @@
 					compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
 					reg = <0x0200c000 0x4000>;
 					interrupts = <0 32 0x04>;
+					clocks = <&clks 113>, <&clks 113>;
+					clock-names = "ipg", "per";
 					status = "disabled";
 				};
 
@@ -168,6 +177,8 @@
 					compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
 					reg = <0x02010000 0x4000>;
 					interrupts = <0 33 0x04>;
+					clocks = <&clks 114>, <&clks 114>;
+					clock-names = "ipg", "per";
 					status = "disabled";
 				};
 
@@ -177,6 +188,8 @@
 					compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
 					reg = <0x02014000 0x4000>;
 					interrupts = <0 34 0x04>;
+					clocks = <&clks 115>, <&clks 115>;
+					clock-names = "ipg", "per";
 					status = "disabled";
 				};
 
@@ -186,6 +199,8 @@
 					compatible = "fsl,imx6q-ecspi", "fsl,imx51-ecspi";
 					reg = <0x02018000 0x4000>;
 					interrupts = <0 35 0x04>;
+					clocks = <&clks 116>, <&clks 116>;
+					clock-names = "ipg", "per";
 					status = "disabled";
 				};
 
@@ -193,6 +208,8 @@
 					compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
 					reg = <0x02020000 0x4000>;
 					interrupts = <0 26 0x04>;
+					clocks = <&clks 160>, <&clks 161>;
+					clock-names = "ipg", "per";
 					status = "disabled";
 				};
 
@@ -205,6 +222,7 @@
 					compatible = "fsl,imx6q-ssi","fsl,imx21-ssi";
 					reg = <0x02028000 0x4000>;
 					interrupts = <0 46 0x04>;
+					clocks = <&clks 178>;
 					fsl,fifo-depth = <15>;
 					fsl,ssi-dma-events = <38 37>;
 					status = "disabled";
@@ -214,6 +232,7 @@
 					compatible = "fsl,imx6q-ssi","fsl,imx21-ssi";
 					reg = <0x0202c000 0x4000>;
 					interrupts = <0 47 0x04>;
+					clocks = <&clks 179>;
 					fsl,fifo-depth = <15>;
 					fsl,ssi-dma-events = <42 41>;
 					status = "disabled";
@@ -223,6 +242,7 @@
 					compatible = "fsl,imx6q-ssi","fsl,imx21-ssi";
 					reg = <0x02030000 0x4000>;
 					interrupts = <0 48 0x04>;
+					clocks = <&clks 180>;
 					fsl,fifo-depth = <15>;
 					fsl,ssi-dma-events = <46 45>;
 					status = "disabled";
@@ -362,24 +382,26 @@
 				compatible = "fsl,imx6q-wdt", "fsl,imx21-wdt";
 				reg = <0x020bc000 0x4000>;
 				interrupts = <0 80 0x04>;
-				status = "disabled";
+				clocks = <&clks 0>;
 			};
 
 			wdog@020c0000 { /* WDOG2 */
 				compatible = "fsl,imx6q-wdt", "fsl,imx21-wdt";
 				reg = <0x020c0000 0x4000>;
 				interrupts = <0 81 0x04>;
+				clocks = <&clks 0>;
 				status = "disabled";
 			};
 
-			ccm@020c4000 {
+			clks: ccm@020c4000 {
 				compatible = "fsl,imx6q-ccm";
 				reg = <0x020c4000 0x4000>;
 				interrupts = <0 87 0x04 0 88 0x04>;
+				#clock-cells = <1>;
 			};
 
-			anatop@020c8000 {
-				compatible = "fsl,imx6q-anatop";
+			anatop: anatop@020c8000 {
+				compatible = "fsl,imx6q-anatop", "syscon", "simple-bus";
 				reg = <0x020c8000 0x1000>;
 				interrupts = <0 49 0x04 0 54 0x04 0 127 0x04>;
 
@@ -472,12 +494,14 @@
 				compatible = "fsl,imx6q-usbphy", "fsl,imx23-usbphy";
 				reg = <0x020c9000 0x1000>;
 				interrupts = <0 44 0x04>;
+				clocks = <&clks 182>;
 			};
 
 			usbphy2: usbphy@020ca000 {
 				compatible = "fsl,imx6q-usbphy", "fsl,imx23-usbphy";
 				reg = <0x020ca000 0x1000>;
 				interrupts = <0 45 0x04>;
+				clocks = <&clks 183>;
 			};
 
 			snvs@020cc000 {
@@ -507,6 +531,11 @@
 				interrupts = <0 89 0x04 0 90 0x04>;
 			};
 
+			gpr: iomuxc-gpr@020e0000 {
+				compatible = "fsl,imx6q-iomuxc-gpr", "syscon";
+				reg = <0x020e0000 0x38>;
+			};
+
 			iomuxc@020e0000 {
 				compatible = "fsl,imx6q-iomuxc";
 				reg = <0x020e0000 0x4000>;
@@ -514,86 +543,207 @@
 				/* shared pinctrl settings */
 				audmux {
 					pinctrl_audmux_1: audmux-1 {
-						fsl,pins = <18   0x80000000	/* MX6Q_PAD_SD2_DAT0__AUDMUX_AUD4_RXD */
-							    1586 0x80000000	/* MX6Q_PAD_SD2_DAT3__AUDMUX_AUD4_TXC */
-							    11   0x80000000	/* MX6Q_PAD_SD2_DAT2__AUDMUX_AUD4_TXD */
-							    3    0x80000000>;	/* MX6Q_PAD_SD2_DAT1__AUDMUX_AUD4_TXFS */
+						fsl,pins = <
+							18   0x80000000	/* MX6Q_PAD_SD2_DAT0__AUDMUX_AUD4_RXD */
+							1586 0x80000000	/* MX6Q_PAD_SD2_DAT3__AUDMUX_AUD4_TXC */
+							11   0x80000000	/* MX6Q_PAD_SD2_DAT2__AUDMUX_AUD4_TXD */
+							3    0x80000000	/* MX6Q_PAD_SD2_DAT1__AUDMUX_AUD4_TXFS */
+						>;
+					};
+				};
+
+				ecspi1 {
+					pinctrl_ecspi1_1: ecspi1grp-1 {
+						fsl,pins = <
+							101 0x100b1	/* MX6Q_PAD_EIM_D17__ECSPI1_MISO */
+							109 0x100b1	/* MX6Q_PAD_EIM_D18__ECSPI1_MOSI */
+							94  0x100b1	/* MX6Q_PAD_EIM_D16__ECSPI1_SCLK */
+						>;
+					};
+				};
+
+				enet {
+					pinctrl_enet_1: enetgrp-1 {
+						fsl,pins = <
+							695 0x1b0b0	/* MX6Q_PAD_ENET_MDIO__ENET_MDIO */
+							756 0x1b0b0	/* MX6Q_PAD_ENET_MDC__ENET_MDC */
+							24  0x1b0b0	/* MX6Q_PAD_RGMII_TXC__ENET_RGMII_TXC */
+							30  0x1b0b0	/* MX6Q_PAD_RGMII_TD0__ENET_RGMII_TD0 */
+							34  0x1b0b0	/* MX6Q_PAD_RGMII_TD1__ENET_RGMII_TD1 */
+							39  0x1b0b0	/* MX6Q_PAD_RGMII_TD2__ENET_RGMII_TD2 */
+							44  0x1b0b0	/* MX6Q_PAD_RGMII_TD3__ENET_RGMII_TD3 */
+							56  0x1b0b0	/* MX6Q_PAD_RGMII_TX_CTL__RGMII_TX_CTL */
+							702 0x1b0b0	/* MX6Q_PAD_ENET_REF_CLK__ENET_TX_CLK */
+							74  0x1b0b0	/* MX6Q_PAD_RGMII_RXC__ENET_RGMII_RXC */
+							52  0x1b0b0	/* MX6Q_PAD_RGMII_RD0__ENET_RGMII_RD0 */
+							61  0x1b0b0	/* MX6Q_PAD_RGMII_RD1__ENET_RGMII_RD1 */
+							66  0x1b0b0	/* MX6Q_PAD_RGMII_RD2__ENET_RGMII_RD2 */
+							70  0x1b0b0	/* MX6Q_PAD_RGMII_RD3__ENET_RGMII_RD3 */
+							48  0x1b0b0	/* MX6Q_PAD_RGMII_RX_CTL__RGMII_RX_CTL */
+						>;
+					};
+
+					pinctrl_enet_2: enetgrp-2 {
+						fsl,pins = <
+							890 0x1b0b0	/* MX6Q_PAD_KEY_COL1__ENET_MDIO */
+							909 0x1b0b0	/* MX6Q_PAD_KEY_COL2__ENET_MDC */
+							24  0x1b0b0	/* MX6Q_PAD_RGMII_TXC__ENET_RGMII_TXC */
+							30  0x1b0b0	/* MX6Q_PAD_RGMII_TD0__ENET_RGMII_TD0 */
+							34  0x1b0b0	/* MX6Q_PAD_RGMII_TD1__ENET_RGMII_TD1 */
+							39  0x1b0b0	/* MX6Q_PAD_RGMII_TD2__ENET_RGMII_TD2 */
+							44  0x1b0b0	/* MX6Q_PAD_RGMII_TD3__ENET_RGMII_TD3 */
+							56  0x1b0b0	/* MX6Q_PAD_RGMII_TX_CTL__RGMII_TX_CTL */
+							702 0x1b0b0	/* MX6Q_PAD_ENET_REF_CLK__ENET_TX_CLK */
+							74  0x1b0b0	/* MX6Q_PAD_RGMII_RXC__ENET_RGMII_RXC */
+							52  0x1b0b0	/* MX6Q_PAD_RGMII_RD0__ENET_RGMII_RD0 */
+							61  0x1b0b0	/* MX6Q_PAD_RGMII_RD1__ENET_RGMII_RD1 */
+							66  0x1b0b0	/* MX6Q_PAD_RGMII_RD2__ENET_RGMII_RD2 */
+							70  0x1b0b0	/* MX6Q_PAD_RGMII_RD3__ENET_RGMII_RD3 */
+							48  0x1b0b0	/* MX6Q_PAD_RGMII_RX_CTL__RGMII_RX_CTL */
+						>;
 					};
 				};
 
 				gpmi-nand {
 					pinctrl_gpmi_nand_1: gpmi-nand-1 {
-						fsl,pins = <1328 0xb0b1		/* MX6Q_PAD_NANDF_CLE__RAWNAND_CLE */
-							    1336 0xb0b1		/* MX6Q_PAD_NANDF_ALE__RAWNAND_ALE */
-							    1344 0xb0b1		/* MX6Q_PAD_NANDF_WP_B__RAWNAND_RESETN */
-							    1352 0xb000		/* MX6Q_PAD_NANDF_RB0__RAWNAND_READY0 */
-							    1360 0xb0b1		/* MX6Q_PAD_NANDF_CS0__RAWNAND_CE0N */
-							    1365 0xb0b1		/* MX6Q_PAD_NANDF_CS1__RAWNAND_CE1N */
-							    1371 0xb0b1		/* MX6Q_PAD_NANDF_CS2__RAWNAND_CE2N */
-							    1378 0xb0b1		/* MX6Q_PAD_NANDF_CS3__RAWNAND_CE3N */
-							    1387 0xb0b1		/* MX6Q_PAD_SD4_CMD__RAWNAND_RDN */
-							    1393 0xb0b1		/* MX6Q_PAD_SD4_CLK__RAWNAND_WRN */
-							    1397 0xb0b1		/* MX6Q_PAD_NANDF_D0__RAWNAND_D0 */
-							    1405 0xb0b1		/* MX6Q_PAD_NANDF_D1__RAWNAND_D1 */
-							    1413 0xb0b1		/* MX6Q_PAD_NANDF_D2__RAWNAND_D2 */
-							    1421 0xb0b1		/* MX6Q_PAD_NANDF_D3__RAWNAND_D3 */
-							    1429 0xb0b1		/* MX6Q_PAD_NANDF_D4__RAWNAND_D4 */
-							    1437 0xb0b1		/* MX6Q_PAD_NANDF_D5__RAWNAND_D5 */
-							    1445 0xb0b1		/* MX6Q_PAD_NANDF_D6__RAWNAND_D6 */
-							    1453 0xb0b1		/* MX6Q_PAD_NANDF_D7__RAWNAND_D7 */
-							    1463 0x00b1>;	/* MX6Q_PAD_SD4_DAT0__RAWNAND_DQS */
+						fsl,pins = <
+							1328 0xb0b1	/* MX6Q_PAD_NANDF_CLE__RAWNAND_CLE */
+							1336 0xb0b1	/* MX6Q_PAD_NANDF_ALE__RAWNAND_ALE */
+							1344 0xb0b1	/* MX6Q_PAD_NANDF_WP_B__RAWNAND_RESETN */
+							1352 0xb000	/* MX6Q_PAD_NANDF_RB0__RAWNAND_READY0 */
+							1360 0xb0b1	/* MX6Q_PAD_NANDF_CS0__RAWNAND_CE0N */
+							1365 0xb0b1	/* MX6Q_PAD_NANDF_CS1__RAWNAND_CE1N */
+							1371 0xb0b1	/* MX6Q_PAD_NANDF_CS2__RAWNAND_CE2N */
+							1378 0xb0b1	/* MX6Q_PAD_NANDF_CS3__RAWNAND_CE3N */
+							1387 0xb0b1	/* MX6Q_PAD_SD4_CMD__RAWNAND_RDN */
+							1393 0xb0b1	/* MX6Q_PAD_SD4_CLK__RAWNAND_WRN */
+							1397 0xb0b1	/* MX6Q_PAD_NANDF_D0__RAWNAND_D0 */
+							1405 0xb0b1	/* MX6Q_PAD_NANDF_D1__RAWNAND_D1 */
+							1413 0xb0b1	/* MX6Q_PAD_NANDF_D2__RAWNAND_D2 */
+							1421 0xb0b1	/* MX6Q_PAD_NANDF_D3__RAWNAND_D3 */
+							1429 0xb0b1	/* MX6Q_PAD_NANDF_D4__RAWNAND_D4 */
+							1437 0xb0b1	/* MX6Q_PAD_NANDF_D5__RAWNAND_D5 */
+							1445 0xb0b1	/* MX6Q_PAD_NANDF_D6__RAWNAND_D6 */
+							1453 0xb0b1	/* MX6Q_PAD_NANDF_D7__RAWNAND_D7 */
+							1463 0x00b1	/* MX6Q_PAD_SD4_DAT0__RAWNAND_DQS */
+						>;
 					};
 				};
 
 				i2c1 {
 					pinctrl_i2c1_1: i2c1grp-1 {
-						fsl,pins = <137 0x4001b8b1	/* MX6Q_PAD_EIM_D21__I2C1_SCL */
-							    196 0x4001b8b1>;	/* MX6Q_PAD_EIM_D28__I2C1_SDA */
+						fsl,pins = <
+							137 0x4001b8b1	/* MX6Q_PAD_EIM_D21__I2C1_SCL */
+							196 0x4001b8b1	/* MX6Q_PAD_EIM_D28__I2C1_SDA */
+						>;
+					};
+				};
+
+				uart1 {
+					pinctrl_uart1_1: uart1grp-1 {
+						fsl,pins = <
+							1140 0x1b0b1	/* MX6Q_PAD_CSI0_DAT10__UART1_TXD */
+							1148 0x1b0b1	/* MX6Q_PAD_CSI0_DAT11__UART1_RXD */
+						>;
 					};
 				};
 
-				serial2 {
-					pinctrl_serial2_1: serial2grp-1 {
-						fsl,pins = <183 0x1b0b1		/* MX6Q_PAD_EIM_D26__UART2_TXD */
-							    191 0x1b0b1>;	/* MX6Q_PAD_EIM_D27__UART2_RXD */
+				uart2 {
+					pinctrl_uart2_1: uart2grp-1 {
+						fsl,pins = <
+							183 0x1b0b1	/* MX6Q_PAD_EIM_D26__UART2_TXD */
+							191 0x1b0b1	/* MX6Q_PAD_EIM_D27__UART2_RXD */
+						>;
+					};
+				};
+
+				uart4 {
+					pinctrl_uart4_1: uart4grp-1 {
+						fsl,pins = <
+							877 0x1b0b1	/* MX6Q_PAD_KEY_COL0__UART4_TXD */
+							885 0x1b0b1	/* MX6Q_PAD_KEY_ROW0__UART4_RXD */
+						>;
+					};
+				};
+
+				usbotg {
+					pinctrl_usbotg_1: usbotggrp-1 {
+						fsl,pins = <
+							1592 0x17059	/* MX6Q_PAD_GPIO_1__ANATOP_USBOTG_ID */
+						>;
+					};
+				};
+
+				usdhc2 {
+					pinctrl_usdhc2_1: usdhc2grp-1 {
+						fsl,pins = <
+							1577 0x17059	/* MX6Q_PAD_SD2_CMD__USDHC2_CMD */
+							1569 0x10059	/* MX6Q_PAD_SD2_CLK__USDHC2_CLK */
+							16   0x17059	/* MX6Q_PAD_SD2_DAT0__USDHC2_DAT0 */
+							0    0x17059	/* MX6Q_PAD_SD2_DAT1__USDHC2_DAT1 */
+							8    0x17059	/* MX6Q_PAD_SD2_DAT2__USDHC2_DAT2 */
+							1583 0x17059	/* MX6Q_PAD_SD2_DAT3__USDHC2_DAT3 */
+							1430 0x17059	/* MX6Q_PAD_NANDF_D4__USDHC2_DAT4 */
+							1438 0x17059	/* MX6Q_PAD_NANDF_D5__USDHC2_DAT5 */
+							1446 0x17059	/* MX6Q_PAD_NANDF_D6__USDHC2_DAT6 */
+							1454 0x17059	/* MX6Q_PAD_NANDF_D7__USDHC2_DAT7 */
+						>;
 					};
 				};
 
 				usdhc3 {
 					pinctrl_usdhc3_1: usdhc3grp-1 {
-						fsl,pins = <1273 0x17059	/* MX6Q_PAD_SD3_CMD__USDHC3_CMD */
-							    1281 0x10059	/* MX6Q_PAD_SD3_CLK__USDHC3_CLK	*/
-							    1289 0x17059	/* MX6Q_PAD_SD3_DAT0__USDHC3_DAT0 */
-							    1297 0x17059	/* MX6Q_PAD_SD3_DAT1__USDHC3_DAT1 */
-							    1305 0x17059	/* MX6Q_PAD_SD3_DAT2__USDHC3_DAT2 */
-							    1312 0x17059	/* MX6Q_PAD_SD3_DAT3__USDHC3_DAT3 */
-							    1265 0x17059	/* MX6Q_PAD_SD3_DAT4__USDHC3_DAT4 */
-							    1257 0x17059	/* MX6Q_PAD_SD3_DAT5__USDHC3_DAT5 */
-							    1249 0x17059	/* MX6Q_PAD_SD3_DAT6__USDHC3_DAT6 */
-							    1241 0x17059>;	/* MX6Q_PAD_SD3_DAT7__USDHC3_DAT7 */
+						fsl,pins = <
+							1273 0x17059	/* MX6Q_PAD_SD3_CMD__USDHC3_CMD */
+							1281 0x10059	/* MX6Q_PAD_SD3_CLK__USDHC3_CLK	*/
+							1289 0x17059	/* MX6Q_PAD_SD3_DAT0__USDHC3_DAT0 */
+							1297 0x17059	/* MX6Q_PAD_SD3_DAT1__USDHC3_DAT1 */
+							1305 0x17059	/* MX6Q_PAD_SD3_DAT2__USDHC3_DAT2 */
+							1312 0x17059	/* MX6Q_PAD_SD3_DAT3__USDHC3_DAT3 */
+							1265 0x17059	/* MX6Q_PAD_SD3_DAT4__USDHC3_DAT4 */
+							1257 0x17059	/* MX6Q_PAD_SD3_DAT5__USDHC3_DAT5 */
+							1249 0x17059	/* MX6Q_PAD_SD3_DAT6__USDHC3_DAT6 */
+							1241 0x17059	/* MX6Q_PAD_SD3_DAT7__USDHC3_DAT7 */
+						>;
+					};
+
+					pinctrl_usdhc3_2: usdhc3grp-2 {
+						fsl,pins = <
+							1273 0x17059	/* MX6Q_PAD_SD3_CMD__USDHC3_CMD */
+							1281 0x10059	/* MX6Q_PAD_SD3_CLK__USDHC3_CLK	*/
+							1289 0x17059	/* MX6Q_PAD_SD3_DAT0__USDHC3_DAT0 */
+							1297 0x17059	/* MX6Q_PAD_SD3_DAT1__USDHC3_DAT1 */
+							1305 0x17059	/* MX6Q_PAD_SD3_DAT2__USDHC3_DAT2 */
+							1312 0x17059	/* MX6Q_PAD_SD3_DAT3__USDHC3_DAT3 */
+						>;
 					};
 				};
 
 				usdhc4 {
 					pinctrl_usdhc4_1: usdhc4grp-1 {
-						fsl,pins = <1386 0x17059	/* MX6Q_PAD_SD4_CMD__USDHC4_CMD */
-							    1392 0x10059	/* MX6Q_PAD_SD4_CLK__USDHC4_CLK	*/
-							    1462 0x17059	/* MX6Q_PAD_SD4_DAT0__USDHC4_DAT0 */
-							    1470 0x17059	/* MX6Q_PAD_SD4_DAT1__USDHC4_DAT1 */
-							    1478 0x17059	/* MX6Q_PAD_SD4_DAT2__USDHC4_DAT2 */
-							    1486 0x17059	/* MX6Q_PAD_SD4_DAT3__USDHC4_DAT3 */
-							    1493 0x17059	/* MX6Q_PAD_SD4_DAT4__USDHC4_DAT4 */
-							    1501 0x17059	/* MX6Q_PAD_SD4_DAT5__USDHC4_DAT5 */
-							    1509 0x17059	/* MX6Q_PAD_SD4_DAT6__USDHC4_DAT6 */
-							    1517 0x17059>;	/* MX6Q_PAD_SD4_DAT7__USDHC4_DAT7 */
+						fsl,pins = <
+							1386 0x17059	/* MX6Q_PAD_SD4_CMD__USDHC4_CMD */
+							1392 0x10059	/* MX6Q_PAD_SD4_CLK__USDHC4_CLK	*/
+							1462 0x17059	/* MX6Q_PAD_SD4_DAT0__USDHC4_DAT0 */
+							1470 0x17059	/* MX6Q_PAD_SD4_DAT1__USDHC4_DAT1 */
+							1478 0x17059	/* MX6Q_PAD_SD4_DAT2__USDHC4_DAT2 */
+							1486 0x17059	/* MX6Q_PAD_SD4_DAT3__USDHC4_DAT3 */
+							1493 0x17059	/* MX6Q_PAD_SD4_DAT4__USDHC4_DAT4 */
+							1501 0x17059	/* MX6Q_PAD_SD4_DAT5__USDHC4_DAT5 */
+							1509 0x17059	/* MX6Q_PAD_SD4_DAT6__USDHC4_DAT6 */
+							1517 0x17059	/* MX6Q_PAD_SD4_DAT7__USDHC4_DAT7 */
+						>;
 					};
-				};
 
-				ecspi1 {
-					pinctrl_ecspi1_1: ecspi1grp-1 {
-						fsl,pins = <101 0x100b1		/* MX6Q_PAD_EIM_D17__ECSPI1_MISO */
-							    109 0x100b1		/* MX6Q_PAD_EIM_D18__ECSPI1_MOSI */
-							    94  0x100b1>;	/* MX6Q_PAD_EIM_D16__ECSPI1_SCLK */
+					pinctrl_usdhc4_2: usdhc4grp-2 {
+						fsl,pins = <
+							1386 0x17059	/* MX6Q_PAD_SD4_CMD__USDHC4_CMD */
+							1392 0x10059	/* MX6Q_PAD_SD4_CLK__USDHC4_CLK	*/
+							1462 0x17059	/* MX6Q_PAD_SD4_DAT0__USDHC4_DAT0 */
+							1470 0x17059	/* MX6Q_PAD_SD4_DAT1__USDHC4_DAT1 */
+							1478 0x17059	/* MX6Q_PAD_SD4_DAT2__USDHC4_DAT2 */
+							1486 0x17059	/* MX6Q_PAD_SD4_DAT3__USDHC4_DAT3 */
+						>;
 					};
 				};
 			};
@@ -612,6 +762,9 @@
 				compatible = "fsl,imx6q-sdma", "fsl,imx35-sdma";
 				reg = <0x020ec000 0x4000>;
 				interrupts = <0 2 0x04>;
+				clocks = <&clks 155>, <&clks 155>;
+				clock-names = "ipg", "ahb";
+				fsl,sdma-ram-script-name = "imx/sdma/sdma-imx6q-to1.bin";
 			};
 		};
 
@@ -635,7 +788,9 @@
 				compatible = "fsl,imx6q-usb", "fsl,imx27-usb";
 				reg = <0x02184000 0x200>;
 				interrupts = <0 43 0x04>;
+				clocks = <&clks 162>;
 				fsl,usbphy = <&usbphy1>;
+				fsl,usbmisc = <&usbmisc 0>;
 				status = "disabled";
 			};
 
@@ -643,7 +798,9 @@
 				compatible = "fsl,imx6q-usb", "fsl,imx27-usb";
 				reg = <0x02184200 0x200>;
 				interrupts = <0 40 0x04>;
+				clocks = <&clks 162>;
 				fsl,usbphy = <&usbphy2>;
+				fsl,usbmisc = <&usbmisc 1>;
 				status = "disabled";
 			};
 
@@ -651,6 +808,8 @@
 				compatible = "fsl,imx6q-usb", "fsl,imx27-usb";
 				reg = <0x02184400 0x200>;
 				interrupts = <0 41 0x04>;
+				clocks = <&clks 162>;
+				fsl,usbmisc = <&usbmisc 2>;
 				status = "disabled";
 			};
 
@@ -658,13 +817,24 @@
 				compatible = "fsl,imx6q-usb", "fsl,imx27-usb";
 				reg = <0x02184600 0x200>;
 				interrupts = <0 42 0x04>;
+				clocks = <&clks 162>;
+				fsl,usbmisc = <&usbmisc 3>;
 				status = "disabled";
 			};
 
+			usbmisc: usbmisc@02184800 {
+				#index-cells = <1>;
+				compatible = "fsl,imx6q-usbmisc";
+				reg = <0x02184800 0x200>;
+				clocks = <&clks 162>;
+			};
+
 			ethernet@02188000 {
 				compatible = "fsl,imx6q-fec";
 				reg = <0x02188000 0x4000>;
 				interrupts = <0 118 0x04 0 119 0x04>;
+				clocks = <&clks 117>, <&clks 117>;
+				clock-names = "ipg", "ahb";
 				status = "disabled";
 			};
 
@@ -677,6 +847,8 @@
 				compatible = "fsl,imx6q-usdhc";
 				reg = <0x02190000 0x4000>;
 				interrupts = <0 22 0x04>;
+				clocks = <&clks 163>, <&clks 163>, <&clks 163>;
+				clock-names = "ipg", "ahb", "per";
 				status = "disabled";
 			};
 
@@ -684,6 +856,8 @@
 				compatible = "fsl,imx6q-usdhc";
 				reg = <0x02194000 0x4000>;
 				interrupts = <0 23 0x04>;
+				clocks = <&clks 164>, <&clks 164>, <&clks 164>;
+				clock-names = "ipg", "ahb", "per";
 				status = "disabled";
 			};
 
@@ -691,6 +865,8 @@
 				compatible = "fsl,imx6q-usdhc";
 				reg = <0x02198000 0x4000>;
 				interrupts = <0 24 0x04>;
+				clocks = <&clks 165>, <&clks 165>, <&clks 165>;
+				clock-names = "ipg", "ahb", "per";
 				status = "disabled";
 			};
 
@@ -698,6 +874,8 @@
 				compatible = "fsl,imx6q-usdhc";
 				reg = <0x0219c000 0x4000>;
 				interrupts = <0 25 0x04>;
+				clocks = <&clks 166>, <&clks 166>, <&clks 166>;
+				clock-names = "ipg", "ahb", "per";
 				status = "disabled";
 			};
 
@@ -707,6 +885,7 @@
 				compatible = "fsl,imx6q-i2c", "fsl,imx1-i2c";
 				reg = <0x021a0000 0x4000>;
 				interrupts = <0 36 0x04>;
+				clocks = <&clks 125>;
 				status = "disabled";
 			};
 
@@ -716,6 +895,7 @@
 				compatible = "fsl,imx6q-i2c", "fsl,imx1-i2c";
 				reg = <0x021a4000 0x4000>;
 				interrupts = <0 37 0x04>;
+				clocks = <&clks 126>;
 				status = "disabled";
 			};
 
@@ -725,6 +905,7 @@
 				compatible = "fsl,imx6q-i2c", "fsl,imx1-i2c";
 				reg = <0x021a8000 0x4000>;
 				interrupts = <0 38 0x04>;
+				clocks = <&clks 127>;
 				status = "disabled";
 			};
 
@@ -788,6 +969,8 @@
 				compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
 				reg = <0x021e8000 0x4000>;
 				interrupts = <0 27 0x04>;
+				clocks = <&clks 160>, <&clks 161>;
+				clock-names = "ipg", "per";
 				status = "disabled";
 			};
 
@@ -795,6 +978,8 @@
 				compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
 				reg = <0x021ec000 0x4000>;
 				interrupts = <0 28 0x04>;
+				clocks = <&clks 160>, <&clks 161>;
+				clock-names = "ipg", "per";
 				status = "disabled";
 			};
 
@@ -802,6 +987,8 @@
 				compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
 				reg = <0x021f0000 0x4000>;
 				interrupts = <0 29 0x04>;
+				clocks = <&clks 160>, <&clks 161>;
+				clock-names = "ipg", "per";
 				status = "disabled";
 			};
 
@@ -809,6 +996,8 @@
 				compatible = "fsl,imx6q-uart", "fsl,imx21-uart";
 				reg = <0x021f4000 0x4000>;
 				interrupts = <0 30 0x04>;
+				clocks = <&clks 160>, <&clks 161>;
+				clock-names = "ipg", "per";
 				status = "disabled";
 			};
 		};
diff --git a/arch/arm/boot/dts/integrator.dtsi b/arch/arm/boot/dts/integrator.dtsi
new file mode 100644
index 0000000..813b91d
--- /dev/null
+++ b/arch/arm/boot/dts/integrator.dtsi
@@ -0,0 +1,76 @@
+/*
+ * SoC core Device Tree for the ARM Integrator platforms
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+	timer@13000000 {
+		reg = <0x13000000 0x100>;
+		interrupt-parent = <&pic>;
+		interrupts = <5>;
+	};
+
+	timer@13000100 {
+		reg = <0x13000100 0x100>;
+		interrupt-parent = <&pic>;
+		interrupts = <6>;
+	};
+
+	timer@13000200 {
+		reg = <0x13000200 0x100>;
+		interrupt-parent = <&pic>;
+		interrupts = <7>;
+	};
+
+	pic@14000000 {
+		compatible = "arm,versatile-fpga-irq";
+		#interrupt-cells = <1>;
+		interrupt-controller;
+		reg = <0x14000000 0x100>;
+		clear-mask = <0xffffffff>;
+	};
+
+	flash@24000000 {
+		compatible = "cfi-flash";
+		reg = <0x24000000 0x02000000>;
+	};
+
+	fpga {
+		compatible = "arm,amba-bus", "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		interrupt-parent = <&pic>;
+
+		/*
+		 * These PrimeCells are in the same locations and using the
+		 * same interrupts in all Integrators, however the silicon
+		 * version deployed is different.
+		 */
+		rtc@15000000 {
+			reg = <0x15000000 0x1000>;
+			interrupts = <8>;
+		};
+
+		uart@16000000 {
+			reg = <0x16000000 0x1000>;
+			interrupts = <1>;
+		};
+
+		uart@17000000 {
+			reg = <0x17000000 0x1000>;
+			interrupts = <2>;
+		};
+
+		kmi@18000000 {
+			reg = <0x18000000 0x1000>;
+			interrupts = <3>;
+		};
+
+		kmi@19000000 {
+			reg = <0x19000000 0x1000>;
+			interrupts = <4>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/integratorap.dts b/arch/arm/boot/dts/integratorap.dts
new file mode 100644
index 0000000..6176775
--- /dev/null
+++ b/arch/arm/boot/dts/integratorap.dts
@@ -0,0 +1,68 @@
+/*
+ * Device Tree for the ARM Integrator/AP platform
+ */
+
+/dts-v1/;
+/include/ "integrator.dtsi"
+
+/ {
+	model = "ARM Integrator/AP";
+	compatible = "arm,integrator-ap";
+
+	aliases {
+		arm,timer-primary = &timer2;
+		arm,timer-secondary = &timer1;
+	};
+
+	chosen {
+		bootargs = "root=/dev/ram0 console=ttyAM0,38400n8 earlyprintk";
+	};
+
+	timer0: timer@13000000 {
+		compatible = "arm,integrator-timer";
+	};
+
+	timer1: timer@13000100 {
+		compatible = "arm,integrator-timer";
+	};
+
+	timer2: timer@13000200 {
+		compatible = "arm,integrator-timer";
+	};
+
+	pic: pic@14000000 {
+		valid-mask = <0x003fffff>;
+	};
+
+	fpga {
+		/*
+		 * The Integator/AP predates the idea to have magic numbers
+		 * identifying the PrimeCell in hardware, thus we have to
+		 * supply these from the device tree.
+		 */
+		rtc: rtc@15000000 {
+			compatible = "arm,pl030", "arm,primecell";
+			arm,primecell-periphid = <0x00041030>;
+		};
+
+		uart0: uart@16000000 {
+			compatible = "arm,pl010", "arm,primecell";
+			arm,primecell-periphid = <0x00041010>;
+		};
+
+		uart1: uart@17000000 {
+			compatible = "arm,pl010", "arm,primecell";
+			arm,primecell-periphid = <0x00041010>;
+		};
+
+		kmi0: kmi@18000000 {
+			compatible = "arm,pl050", "arm,primecell";
+			arm,primecell-periphid = <0x00041050>;
+		};
+
+		kmi1: kmi@19000000 {
+			compatible = "arm,pl050", "arm,primecell";
+			arm,primecell-periphid = <0x00041050>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/integratorcp.dts b/arch/arm/boot/dts/integratorcp.dts
new file mode 100644
index 0000000..2dd5e4e
--- /dev/null
+++ b/arch/arm/boot/dts/integratorcp.dts
@@ -0,0 +1,110 @@
+/*
+ * Device Tree for the ARM Integrator/CP platform
+ */
+
+/dts-v1/;
+/include/ "integrator.dtsi"
+
+/ {
+	model = "ARM Integrator/CP";
+	compatible = "arm,integrator-cp";
+
+	aliases {
+		arm,timer-primary = &timer2;
+		arm,timer-secondary = &timer1;
+	};
+
+	chosen {
+		bootargs = "root=/dev/ram0 console=ttyAMA0,38400n8 earlyprintk";
+	};
+
+	timer0: timer@13000000 {
+		compatible = "arm,sp804", "arm,primecell";
+	};
+
+	timer1: timer@13000100 {
+		compatible = "arm,sp804", "arm,primecell";
+	};
+
+	timer2: timer@13000200 {
+		compatible = "arm,sp804", "arm,primecell";
+	};
+
+	pic: pic@14000000 {
+		valid-mask = <0x1fc003ff>;
+	};
+
+	cic: cic@10000040 {
+		compatible = "arm,versatile-fpga-irq";
+		#interrupt-cells = <1>;
+		interrupt-controller;
+		reg = <0x10000040 0x100>;
+		clear-mask = <0xffffffff>;
+		valid-mask = <0x00000007>;
+	};
+
+	sic: sic@ca000000 {
+		compatible = "arm,versatile-fpga-irq";
+		#interrupt-cells = <1>;
+		interrupt-controller;
+		reg = <0xca000000 0x100>;
+		clear-mask = <0x00000fff>;
+		valid-mask = <0x00000fff>;
+	};
+
+	ethernet@c8000000 {
+		compatible = "smsc,lan91c111";
+		reg = <0xc8000000 0x10>;
+		interrupt-parent = <&pic>;
+		interrupts = <27>;
+	};
+
+	fpga {
+		/*
+		 * These PrimeCells are at the same location and using
+		 * the same interrupts in all Integrators, but in the CP
+		 * slightly newer versions are deployed.
+		 */
+		rtc@15000000 {
+			compatible = "arm,pl031", "arm,primecell";
+		};
+
+		uart@16000000 {
+			compatible = "arm,pl011", "arm,primecell";
+		};
+
+		uart@17000000 {
+			compatible = "arm,pl011", "arm,primecell";
+		};
+
+		kmi@18000000 {
+			compatible = "arm,pl050", "arm,primecell";
+		};
+
+		kmi@19000000 {
+			compatible = "arm,pl050", "arm,primecell";
+		};
+
+		/*
+		 * These PrimeCells are only available on the Integrator/CP
+		 */
+		mmc@1c000000 {
+			compatible = "arm,pl180", "arm,primecell";
+			reg = <0x1c000000 0x1000>;
+			interrupts = <23 24>;
+			max-frequency = <515633>;
+		};
+
+		aaci@1d000000 {
+			compatible = "arm,pl041", "arm,primecell";
+			reg = <0x1d000000 0x1000>;
+			interrupts = <25>;
+		};
+
+		clcd@c0000000 {
+			compatible = "arm,pl110", "arm,primecell";
+			reg = <0xC0000000 0x1000>;
+			interrupts = <22>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/kirkwood-dnskw.dtsi b/arch/arm/boot/dts/kirkwood-dnskw.dtsi
index 7408655..9b32d02 100644
--- a/arch/arm/boot/dts/kirkwood-dnskw.dtsi
+++ b/arch/arm/boot/dts/kirkwood-dnskw.dtsi
@@ -25,6 +25,16 @@
 		};
 	};
 
+	gpio_fan {
+		/* Fan: ADDA AD045HB-G73 40mm 6000rpm@5v */
+		compatible = "gpio-fan";
+		gpios = <&gpio1 14 1
+			 &gpio1 13 1>;
+		gpio-fan,speed-map = <0    0
+				      3000 1
+				      6000 2>;
+	};
+
 	ocp@f1000000 {
 		sata@80000 {
 			status = "okay";
diff --git a/arch/arm/boot/dts/kirkwood-dockstar.dts b/arch/arm/boot/dts/kirkwood-dockstar.dts
new file mode 100644
index 0000000..08a5824
--- /dev/null
+++ b/arch/arm/boot/dts/kirkwood-dockstar.dts
@@ -0,0 +1,57 @@
+/dts-v1/;
+
+/include/ "kirkwood.dtsi"
+
+/ {
+	model = "Seagate FreeAgent Dockstar";
+	compatible = "seagate,dockstar", "marvell,kirkwood-88f6281", "marvell,kirkwood";
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x8000000>;
+	};
+
+	chosen {
+		bootargs = "console=ttyS0,115200n8 earlyprintk root=/dev/sda1 rootdelay=10";
+	};
+
+	ocp@f1000000 {
+		serial@12000 {
+			clock-frequency = <200000000>;
+			status = "ok";
+		};
+
+		nand@3000000 {
+			status = "okay";
+
+			partition@0 {
+				label = "u-boot";
+				reg = <0x0000000 0x100000>;
+				read-only;
+			};
+
+			partition@100000 {
+				label = "uImage";
+				reg = <0x0100000 0x400000>;
+			};
+
+			partition@500000 {
+				label = "data";
+				reg = <0x0500000 0xfb00000>;
+			};
+		};
+	};
+	gpio-leds {
+		compatible = "gpio-leds";
+
+		health {
+			label = "status:green:health";
+			gpios = <&gpio1 14 1>;
+			linux,default-trigger = "default-on";
+		};
+		fault {
+			label = "status:orange:fault";
+			gpios = <&gpio1 15 1>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/kirkwood-iconnect.dts b/arch/arm/boot/dts/kirkwood-iconnect.dts
index f8ca6fa..d97cd9d 100644
--- a/arch/arm/boot/dts/kirkwood-iconnect.dts
+++ b/arch/arm/boot/dts/kirkwood-iconnect.dts
@@ -12,7 +12,7 @@
 	};
 
 	chosen {
-		bootargs = "console=ttyS0,115200n8 earlyprintk mtdparts=orion_nand:0xc0000@0x0(uboot),0x20000@0xa0000(env),0x300000@0x100000(zImage),0x300000@0x540000(initrd),0x1f400000@0x980000(boot)";
+		bootargs = "console=ttyS0,115200n8 earlyprintk";
 		linux,initrd-start = <0x4500040>;
 		linux,initrd-end   = <0x4800000>;
 	};
@@ -30,7 +30,37 @@
 			clock-frequency = <200000000>;
 			status = "ok";
 		};
+
+		nand@3000000 {
+			status = "okay";
+
+			partition@0 {
+				label = "uboot";
+				reg = <0x0000000 0xc0000>;
+			};
+
+			partition@a0000 {
+				label = "env";
+				reg = <0xa0000 0x20000>;
+			};
+
+			partition@100000 {
+				label = "zImage";
+				reg = <0x100000 0x300000>;
+			};
+
+			partition@540000 {
+				label = "initrd";
+				reg = <0x540000 0x300000>;
+			};
+
+			partition@980000 {
+				label = "boot";
+				reg = <0x980000 0x1f400000>;
+			};
+		};
 	};
+
 	gpio-leds {
 		compatible = "gpio-leds";
 
@@ -69,4 +99,22 @@
 			gpios = <&gpio1 16 0>;
 		};
 	};
+
+	gpio_keys {
+		compatible = "gpio-keys";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		button@1 {
+			label = "OTB Button";
+			linux,code = <133>;
+			gpios = <&gpio1 3 1>;
+			debounce-interval = <100>;
+		};
+		button@2 {
+			label = "Reset";
+			linux,code = <0x198>;
+			gpios = <&gpio0 12 1>;
+			debounce-interval = <100>;
+		};
+	};
 };
diff --git a/arch/arm/boot/dts/kirkwood-iomega_ix2_200.dts b/arch/arm/boot/dts/kirkwood-iomega_ix2_200.dts
new file mode 100644
index 0000000..865aeec
--- /dev/null
+++ b/arch/arm/boot/dts/kirkwood-iomega_ix2_200.dts
@@ -0,0 +1,105 @@
+/dts-v1/;
+
+/include/ "kirkwood.dtsi"
+
+/ {
+	model = "Iomega StorCenter ix2-200";
+	compatible = "iom,ix2-200", "marvell,kirkwood-88f6281", "marvell,kirkwood";
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x10000000>;
+	};
+
+	chosen {
+		bootargs = "console=ttyS0,115200n8 earlyprintk";
+	};
+
+	ocp@f1000000 {
+		i2c@11000 {
+			status = "okay";
+
+			lm63: lm63@4c {
+				compatible = "national,lm63";
+				reg = <0x4c>;
+			};
+		};
+
+		serial@12000 {
+			clock-frequency = <200000000>;
+			status = "ok";
+		};
+
+		nand@3000000 {
+			status = "okay";
+
+			partition@0 {
+				label = "u-boot";
+				reg = <0x0000000 0x100000>;
+				read-only;
+			};
+
+			partition@a0000 {
+				label = "env";
+				reg = <0xa0000 0x20000>;
+				read-only;
+			};
+
+			partition@100000 {
+				label = "uImage";
+				reg = <0x100000 0x300000>;
+			};
+
+			partition@400000 {
+				label = "uInitrd";
+				reg = <0x540000 0x1000000>;
+			};
+		};
+		sata@80000 {
+			status = "okay";
+			nr-ports = <2>;
+		};
+
+	};
+	gpio-leds {
+		compatible = "gpio-leds";
+
+		power_led {
+			label = "status:white:power_led";
+			gpios = <&gpio0 16 0>;
+			linux,default-trigger = "default-on";
+		};
+		health_led1 {
+			label = "status:red:health_led";
+			gpios = <&gpio1 5 0>;
+		};
+		health_led2 {
+			label = "status:white:health_led";
+			gpios = <&gpio1 4 0>;
+		};
+		backup_led {
+			label = "status:blue:backup_led";
+			gpios = <&gpio0 15 0>;
+		};
+	};
+	gpio-keys {
+		compatible = "gpio-keys";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		Power {
+			label = "Power Button";
+			linux,code = <116>;
+			gpios = <&gpio0 14 1>;
+		};
+		Reset {
+			label = "Reset Button";
+			linux,code = <0x198>;
+			gpios = <&gpio0 12 1>;
+		};
+		OTB {
+			label = "OTB Button";
+			linux,code = <133>;
+			gpios = <&gpio1 3 1>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/kirkwood-km_kirkwood.dts b/arch/arm/boot/dts/kirkwood-km_kirkwood.dts
new file mode 100644
index 0000000..75bdb93
--- /dev/null
+++ b/arch/arm/boot/dts/kirkwood-km_kirkwood.dts
@@ -0,0 +1,29 @@
+/dts-v1/;
+
+/include/ "kirkwood.dtsi"
+
+/ {
+	model = "Keymile Kirkwood Reference Design";
+	compatible = "keymile,km_kirkwood", "marvell,kirkwood-98DX4122", "marvell,kirkwood";
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x08000000>;
+	};
+
+	chosen {
+		bootargs = "console=ttyS0,115200n8 earlyprintk";
+	};
+
+	ocp@f1000000 {
+		serial@12000 {
+			clock-frequency = <200000000>;
+			status = "ok";
+		};
+
+		nand@3000000 {
+			status = "ok";
+			chip-delay = <25>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/kirkwood.dtsi b/arch/arm/boot/dts/kirkwood.dtsi
index cef9616..4e5b815 100644
--- a/arch/arm/boot/dts/kirkwood.dtsi
+++ b/arch/arm/boot/dts/kirkwood.dtsi
@@ -14,7 +14,8 @@
 
 	ocp@f1000000 {
 		compatible = "simple-bus";
-		ranges = <0 0xf1000000 0x4000000>;
+		ranges = <0x00000000 0xf1000000 0x4000000
+		          0xf5000000 0xf5000000 0x0000400>;
 		#address-cells = <1>;
 		#size-cells = <1>;
 
@@ -105,5 +106,14 @@
 			clock-frequency = <100000>;
 			status = "disabled";
 		};
+
+		crypto@30000 {
+			compatible = "marvell,orion-crypto";
+			reg = <0x30000 0x10000>,
+			      <0xf5000000 0x800>;
+			reg-names = "regs", "sram";
+			interrupts = <22>;
+			status = "okay";
+		};
 	};
 };
diff --git a/arch/arm/boot/dts/mmp2.dtsi b/arch/arm/boot/dts/mmp2.dtsi
index 80f74e2..0514fb4 100644
--- a/arch/arm/boot/dts/mmp2.dtsi
+++ b/arch/arm/boot/dts/mmp2.dtsi
@@ -26,6 +26,11 @@
 		interrupt-parent = <&intc>;
 		ranges;
 
+		L2: l2-cache {
+			compatible = "marvell,tauros2-cache";
+			marvell,tauros2-cache-features = <0x3>;
+		};
+
 		axi@d4200000 {	/* AXI */
 			compatible = "mrvl,axi-bus", "simple-bus";
 			#address-cells = <1>;
diff --git a/arch/arm/boot/dts/msm8660-surf.dts b/arch/arm/boot/dts/msm8660-surf.dts
index 45bc4bb..31f2157 100644
--- a/arch/arm/boot/dts/msm8660-surf.dts
+++ b/arch/arm/boot/dts/msm8660-surf.dts
@@ -7,7 +7,7 @@
 	compatible = "qcom,msm8660-surf", "qcom,msm8660";
 	interrupt-parent = <&intc>;
 
-	intc: interrupt-controller@02080000 {
+	intc: interrupt-controller@2080000 {
 		compatible = "qcom,msm-8660-qgic";
 		interrupt-controller;
 		#interrupt-cells = <3>;
@@ -15,6 +15,23 @@
 		      < 0x02081000 0x1000 >;
 	};
 
+	timer@2000004 {
+		compatible = "qcom,msm-gpt", "qcom,msm-timer";
+		interrupts = <1 1 0x301>;
+		reg = <0x02000004 0x10>;
+		clock-frequency = <32768>;
+		cpu-offset = <0x40000>;
+	};
+
+	timer@2000024 {
+		compatible = "qcom,msm-dgt", "qcom,msm-timer";
+		interrupts = <1 0 0x301>;
+		reg = <0x02000024 0x10>,
+		      <0x02000034 0x4>;
+		clock-frequency = <6750000>;
+		cpu-offset = <0x40000>;
+	};
+
 	serial@19c400000 {
 		compatible = "qcom,msm-hsuart", "qcom,msm-uart";
 		reg = <0x19c40000 0x1000>,
diff --git a/arch/arm/boot/dts/msm8960-cdp.dts b/arch/arm/boot/dts/msm8960-cdp.dts
new file mode 100644
index 0000000..9e621b5
--- /dev/null
+++ b/arch/arm/boot/dts/msm8960-cdp.dts
@@ -0,0 +1,41 @@
+/dts-v1/;
+
+/include/ "skeleton.dtsi"
+
+/ {
+	model = "Qualcomm MSM8960 CDP";
+	compatible = "qcom,msm8960-cdp", "qcom,msm8960";
+	interrupt-parent = <&intc>;
+
+	intc: interrupt-controller@2000000 {
+		compatible = "qcom,msm-qgic2";
+		interrupt-controller;
+		#interrupt-cells = <3>;
+		reg = < 0x02000000 0x1000 >,
+		      < 0x02002000 0x1000 >;
+	};
+
+	timer@200a004 {
+		compatible = "qcom,msm-gpt", "qcom,msm-timer";
+		interrupts = <1 2 0x301>;
+		reg = <0x0200a004 0x10>;
+		clock-frequency = <32768>;
+		cpu-offset = <0x80000>;
+	};
+
+	timer@200a024 {
+		compatible = "qcom,msm-dgt", "qcom,msm-timer";
+		interrupts = <1 1 0x301>;
+		reg = <0x0200a024 0x10>,
+		      <0x0200a034 0x4>;
+		clock-frequency = <6750000>;
+		cpu-offset = <0x80000>;
+	};
+
+	serial@19c400000 {
+		compatible = "qcom,msm-hsuart", "qcom,msm-uart";
+		reg = <0x16440000 0x1000>,
+		      <0x16400000 0x1000>;
+		interrupts = <0 154 0x0>;
+	};
+};
diff --git a/arch/arm/boot/dts/omap2420-h4.dts b/arch/arm/boot/dts/omap2420-h4.dts
index 25b50b7..77b84e1 100644
--- a/arch/arm/boot/dts/omap2420-h4.dts
+++ b/arch/arm/boot/dts/omap2420-h4.dts
@@ -7,7 +7,7 @@
  */
 /dts-v1/;
 
-/include/ "omap2.dtsi"
+/include/ "omap2420.dtsi"
 
 / {
 	model = "TI OMAP2420 H4 board";
diff --git a/arch/arm/boot/dts/omap2420.dtsi b/arch/arm/boot/dts/omap2420.dtsi
new file mode 100644
index 0000000..bfd76b4
--- /dev/null
+++ b/arch/arm/boot/dts/omap2420.dtsi
@@ -0,0 +1,48 @@
+/*
+ * Device Tree Source for OMAP2420 SoC
+ *
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+/include/ "omap2.dtsi"
+
+/ {
+	compatible = "ti,omap2420", "ti,omap2";
+
+	ocp {
+		omap2420_pmx: pinmux@48000030 {
+			compatible = "ti,omap2420-padconf", "pinctrl-single";
+			reg = <0x48000030 0x0113>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			pinctrl-single,register-width = <8>;
+			pinctrl-single,function-mask = <0x3f>;
+		};
+
+		mcbsp1: mcbsp@48074000 {
+			compatible = "ti,omap2420-mcbsp";
+			reg = <0x48074000 0xff>;
+			reg-names = "mpu";
+			interrupts = <59>, /* TX interrupt */
+				     <60>; /* RX interrupt */
+			interrupt-names = "tx", "rx";
+			interrupt-parent = <&intc>;
+			ti,hwmods = "mcbsp1";
+		};
+
+		mcbsp2: mcbsp@48076000 {
+			compatible = "ti,omap2420-mcbsp";
+			reg = <0x48076000 0xff>;
+			reg-names = "mpu";
+			interrupts = <62>, /* TX interrupt */
+				     <63>; /* RX interrupt */
+			interrupt-names = "tx", "rx";
+			interrupt-parent = <&intc>;
+			ti,hwmods = "mcbsp2";
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/omap2430.dtsi b/arch/arm/boot/dts/omap2430.dtsi
new file mode 100644
index 0000000..4565d97
--- /dev/null
+++ b/arch/arm/boot/dts/omap2430.dtsi
@@ -0,0 +1,92 @@
+/*
+ * Device Tree Source for OMAP243x SoC
+ *
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+/include/ "omap2.dtsi"
+
+/ {
+	compatible = "ti,omap2430", "ti,omap2";
+
+	ocp {
+		omap2430_pmx: pinmux@49002030 {
+			compatible = "ti,omap2430-padconf", "pinctrl-single";
+			reg = <0x49002030 0x0154>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			pinctrl-single,register-width = <8>;
+			pinctrl-single,function-mask = <0x3f>;
+		};
+
+		mcbsp1: mcbsp@48074000 {
+			compatible = "ti,omap2430-mcbsp";
+			reg = <0x48074000 0xff>;
+			reg-names = "mpu";
+			interrupts = <64>, /* OCP compliant interrupt */
+				     <59>, /* TX interrupt */
+				     <60>, /* RX interrupt */
+				     <61>; /* RX overflow interrupt */
+			interrupt-names = "common", "tx", "rx", "rx_overflow";
+			interrupt-parent = <&intc>;
+			ti,buffer-size = <128>;
+			ti,hwmods = "mcbsp1";
+		};
+
+		mcbsp2: mcbsp@48076000 {
+			compatible = "ti,omap2430-mcbsp";
+			reg = <0x48076000 0xff>;
+			reg-names = "mpu";
+			interrupts = <16>, /* OCP compliant interrupt */
+				     <62>, /* TX interrupt */
+				     <63>; /* RX interrupt */
+			interrupt-names = "common", "tx", "rx";
+			interrupt-parent = <&intc>;
+			ti,buffer-size = <128>;
+			ti,hwmods = "mcbsp2";
+		};
+
+		mcbsp3: mcbsp@4808c000 {
+			compatible = "ti,omap2430-mcbsp";
+			reg = <0x4808c000 0xff>;
+			reg-names = "mpu";
+			interrupts = <17>, /* OCP compliant interrupt */
+				     <89>, /* TX interrupt */
+				     <90>; /* RX interrupt */
+			interrupt-names = "common", "tx", "rx";
+			interrupt-parent = <&intc>;
+			ti,buffer-size = <128>;
+			ti,hwmods = "mcbsp3";
+		};
+
+		mcbsp4: mcbsp@4808e000 {
+			compatible = "ti,omap2430-mcbsp";
+			reg = <0x4808e000 0xff>;
+			reg-names = "mpu";
+			interrupts = <18>, /* OCP compliant interrupt */
+				     <54>, /* TX interrupt */
+				     <55>; /* RX interrupt */
+			interrupt-names = "common", "tx", "rx";
+			interrupt-parent = <&intc>;
+			ti,buffer-size = <128>;
+			ti,hwmods = "mcbsp4";
+		};
+
+		mcbsp5: mcbsp@48096000 {
+			compatible = "ti,omap2430-mcbsp";
+			reg = <0x48096000 0xff>;
+			reg-names = "mpu";
+			interrupts = <19>, /* OCP compliant interrupt */
+				     <81>, /* TX interrupt */
+				     <82>; /* RX interrupt */
+			interrupt-names = "common", "tx", "rx";
+			interrupt-parent = <&intc>;
+			ti,buffer-size = <128>;
+			ti,hwmods = "mcbsp5";
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/omap3-beagle-xm.dts b/arch/arm/boot/dts/omap3-beagle-xm.dts
new file mode 100644
index 0000000..c38cf76
--- /dev/null
+++ b/arch/arm/boot/dts/omap3-beagle-xm.dts
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+/include/ "omap36xx.dtsi"
+
+/ {
+	model = "TI OMAP3 BeagleBoard xM";
+	compatible = "ti,omap3-beagle-xm, ti,omap3-beagle", "ti,omap3";
+
+	memory {
+		device_type = "memory";
+		reg = <0x80000000 0x20000000>; /* 512 MB */
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		pmu_stat {
+			label = "beagleboard::pmu_stat";
+			gpios = <&twl_gpio 19 0>; /* LEDB */
+		};
+
+		heartbeat {
+			label = "beagleboard::usr0";
+			gpios = <&gpio5 22 0>; /* 150 -> D6 LED */
+			linux,default-trigger = "heartbeat";
+		};
+
+		mmc {
+			label = "beagleboard::usr1";
+			gpios = <&gpio5 21 0>; /* 149 -> D7 LED */
+			linux,default-trigger = "mmc0";
+		};
+	};
+
+	sound {
+		compatible = "ti,omap-twl4030";
+		ti,model = "omap3beagle";
+
+		ti,mcbsp = <&mcbsp2>;
+		ti,codec = <&twl_audio>;
+	};
+};
+
+&i2c1 {
+	clock-frequency = <2600000>;
+
+	twl: twl@48 {
+		reg = <0x48>;
+		interrupts = <7>; /* SYS_NIRQ cascaded to intc */
+		interrupt-parent = <&intc>;
+
+		vsim: regulator-vsim {
+			compatible = "ti,twl4030-vsim";
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <3000000>;
+		};
+
+		twl_audio: audio {
+			compatible = "ti,twl4030-audio";
+			codec {
+			};
+		};
+	};
+};
+
+/include/ "twl4030.dtsi"
+
+&i2c2 {
+	clock-frequency = <400000>;
+};
+
+&i2c3 {
+	clock-frequency = <100000>;
+
+	/*
+	 * Display monitor features are burnt in the EEPROM
+	 * as EDID data.
+	 */
+	eeprom@50 {
+		compatible = "ti,eeprom";
+		reg = <0x50>;
+	};
+};
+
+&mmc1 {
+	vmmc-supply = <&vmmc1>;
+	vmmc_aux-supply = <&vsim>;
+	bus-width = <8>;
+};
+
+&mmc2 {
+	status = "disabled";
+};
+
+&mmc3 {
+	status = "disabled";
+};
+
+&twl_gpio {
+	ti,use-leds;
+	/* pullups: BIT(1) */
+	ti,pullups = <0x000002>;
+	/*
+	 * pulldowns:
+	 * BIT(2), BIT(6), BIT(7), BIT(8), BIT(13)
+	 * BIT(15), BIT(16), BIT(17)
+	 */
+	ti,pulldowns = <0x03a1c4>;
+};
diff --git a/arch/arm/boot/dts/omap3-beagle.dts b/arch/arm/boot/dts/omap3-beagle.dts
deleted file mode 100644
index cdcb98c..0000000
--- a/arch/arm/boot/dts/omap3-beagle.dts
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-/dts-v1/;
-
-/include/ "omap3.dtsi"
-
-/ {
-	model = "TI OMAP3 BeagleBoard";
-	compatible = "ti,omap3-beagle", "ti,omap3";
-
-	memory {
-		device_type = "memory";
-		reg = <0x80000000 0x20000000>; /* 512 MB */
-	};
-};
-
-&i2c1 {
-	clock-frequency = <2600000>;
-
-	twl: twl@48 {
-		reg = <0x48>;
-		interrupts = <7>; /* SYS_NIRQ cascaded to intc */
-		interrupt-parent = <&intc>;
-
-		vsim: regulator@10 {
-			compatible = "ti,twl4030-vsim";
-			regulator-min-microvolt = <1800000>;
-			regulator-max-microvolt = <3000000>;
-		};
-	};
-};
-
-/include/ "twl4030.dtsi"
-
-&i2c2 {
-	clock-frequency = <400000>;
-};
-
-&i2c3 {
-	clock-frequency = <100000>;
-
-	/*
-	 * Display monitor features are burnt in the EEPROM
-	 * as EDID data.
-	 */
-	eeprom@50 {
-		compatible = "ti,eeprom";
-		reg = <0x50>;
-	};
-};
-
-&mmc1 {
-	vmmc-supply = <&vmmc1>;
-	vmmc_aux-supply = <&vsim>;
-	bus-width = <8>;
-};
-
-&mmc2 {
-	status = "disabled";
-};
-
-&mmc3 {
-	status = "disabled";
-};
diff --git a/arch/arm/boot/dts/omap3-evm.dts b/arch/arm/boot/dts/omap3-evm.dts
index f349ee9..e8ba1c2 100644
--- a/arch/arm/boot/dts/omap3-evm.dts
+++ b/arch/arm/boot/dts/omap3-evm.dts
@@ -17,6 +17,15 @@
 		device_type = "memory";
 		reg = <0x80000000 0x10000000>; /* 256 MB */
 	};
+
+	leds {
+		compatible = "gpio-leds";
+		ledb {
+			label = "omap3evm::ledb";
+			gpios = <&twl_gpio 19 0>; /* LEDB */
+			linux,default-trigger = "default-on";
+		};
+	};
 };
 
 &i2c1 {
@@ -46,3 +55,7 @@
 		reg = <0x5c>;
 	};
 };
+
+&twl_gpio {
+	ti,use-leds;
+};
diff --git a/arch/arm/boot/dts/omap3-overo.dtsi b/arch/arm/boot/dts/omap3-overo.dtsi
new file mode 100644
index 0000000..89808ce
--- /dev/null
+++ b/arch/arm/boot/dts/omap3-overo.dtsi
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2012 Florian Vaussard, 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 version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * The Gumstix Overo must be combined with an expansion board.
+ */
+/dts-v1/;
+
+/include/ "omap3.dtsi"
+
+/ {
+	leds {
+		compatible = "gpio-leds";
+		overo {
+			label = "overo:blue:COM";
+			gpios = <&twl_gpio 19 0>;
+			linux,default-trigger = "mmc0";
+		};
+	};
+};
+
+&i2c1 {
+	clock-frequency = <2600000>;
+
+	twl: twl@48 {
+		reg = <0x48>;
+		interrupts = <7>; /* SYS_NIRQ cascaded to intc */
+		interrupt-parent = <&intc>;
+	};
+};
+
+/include/ "twl4030.dtsi"
+
+/* i2c2 pins are used for gpio */
+&i2c2 {
+	status = "disabled";
+};
+
+/* on board microSD slot */
+&mmc1 {
+	vmmc-supply = <&vmmc1>;
+	bus-width = <4>;
+};
+
+/* optional on board WiFi */
+&mmc2 {
+	bus-width = <4>;
+};
+
+&twl_gpio {
+	ti,use-leds;
+};
diff --git a/arch/arm/boot/dts/omap3-tobi.dts b/arch/arm/boot/dts/omap3-tobi.dts
new file mode 100644
index 0000000..a13d12d
--- /dev/null
+++ b/arch/arm/boot/dts/omap3-tobi.dts
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2012 Florian Vaussard, 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 version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * Tobi expansion board is manufactured by Gumstix Inc.
+ */
+
+/include/ "omap3-overo.dtsi"
+
+/ {
+	model = "TI OMAP3 Gumstix Overo on Tobi";
+	compatible = "ti,omap3-tobi", "ti,omap3-overo", "ti,omap3";
+
+	leds {
+		compatible = "gpio-leds";
+		heartbeat {
+			label = "overo:red:gpio21";
+			gpios = <&gpio1 21 0>;
+			linux,default-trigger = "heartbeat";
+		};
+	};
+};
+
+&i2c3 {
+	clock-frequency = <100000>;
+};
+
+&mmc3 {
+	status = "disabled";
+};
diff --git a/arch/arm/boot/dts/omap3.dtsi b/arch/arm/boot/dts/omap3.dtsi
index 8109471..f38ea87 100644
--- a/arch/arm/boot/dts/omap3.dtsi
+++ b/arch/arm/boot/dts/omap3.dtsi
@@ -17,7 +17,6 @@
 		serial0 = &uart1;
 		serial1 = &uart2;
 		serial2 = &uart3;
-		serial3 = &uart4;
 	};
 
 	cpus {
@@ -69,6 +68,24 @@
 			reg = <0x48200000 0x1000>;
 		};
 
+		omap3_pmx_core: pinmux@48002030 {
+			compatible = "ti,omap3-padconf", "pinctrl-single";
+			reg = <0x48002030 0x05cc>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			pinctrl-single,register-width = <16>;
+			pinctrl-single,function-mask = <0x7fff>;
+		};
+
+		omap3_pmx_wkup: pinmux@0x48002a58 {
+			compatible = "ti,omap3-padconf", "pinctrl-single";
+			reg = <0x48002a58 0x5c>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			pinctrl-single,register-width = <16>;
+			pinctrl-single,function-mask = <0x7fff>;
+		};
+
 		gpio1: gpio@48310000 {
 			compatible = "ti,omap3-gpio";
 			ti,hwmods = "gpio1";
@@ -141,12 +158,6 @@
 			clock-frequency = <48000000>;
 		};
 
-		uart4: serial@49042000 {
-			compatible = "ti,omap3-uart";
-			ti,hwmods = "uart4";
-			clock-frequency = <48000000>;
-		};
-
 		i2c1: i2c@48070000 {
 			compatible = "ti,omap3-i2c";
 			#address-cells = <1>;
@@ -220,5 +231,74 @@
 			compatible = "ti,omap3-wdt";
 			ti,hwmods = "wd_timer2";
 		};
+
+		mcbsp1: mcbsp@48074000 {
+			compatible = "ti,omap3-mcbsp";
+			reg = <0x48074000 0xff>;
+			reg-names = "mpu";
+			interrupts = <16>, /* OCP compliant interrupt */
+				     <59>, /* TX interrupt */
+				     <60>; /* RX interrupt */
+			interrupt-names = "common", "tx", "rx";
+			interrupt-parent = <&intc>;
+			ti,buffer-size = <128>;
+			ti,hwmods = "mcbsp1";
+		};
+
+		mcbsp2: mcbsp@49022000 {
+			compatible = "ti,omap3-mcbsp";
+			reg = <0x49022000 0xff>,
+			      <0x49028000 0xff>;
+			reg-names = "mpu", "sidetone";
+			interrupts = <17>, /* OCP compliant interrupt */
+				     <62>, /* TX interrupt */
+				     <63>, /* RX interrupt */
+				     <4>;  /* Sidetone */
+			interrupt-names = "common", "tx", "rx", "sidetone";
+			interrupt-parent = <&intc>;
+			ti,buffer-size = <1280>;
+			ti,hwmods = "mcbsp2";
+		};
+
+		mcbsp3: mcbsp@49024000 {
+			compatible = "ti,omap3-mcbsp";
+			reg = <0x49024000 0xff>,
+			      <0x4902a000 0xff>;
+			reg-names = "mpu", "sidetone";
+			interrupts = <22>, /* OCP compliant interrupt */
+				     <89>, /* TX interrupt */
+				     <90>, /* RX interrupt */
+				     <5>;  /* Sidetone */
+			interrupt-names = "common", "tx", "rx", "sidetone";
+			interrupt-parent = <&intc>;
+			ti,buffer-size = <128>;
+			ti,hwmods = "mcbsp3";
+		};
+
+		mcbsp4: mcbsp@49026000 {
+			compatible = "ti,omap3-mcbsp";
+			reg = <0x49026000 0xff>;
+			reg-names = "mpu";
+			interrupts = <23>, /* OCP compliant interrupt */
+				     <54>, /* TX interrupt */
+				     <55>; /* RX interrupt */
+			interrupt-names = "common", "tx", "rx";
+			interrupt-parent = <&intc>;
+			ti,buffer-size = <128>;
+			ti,hwmods = "mcbsp4";
+		};
+
+		mcbsp5: mcbsp@48096000 {
+			compatible = "ti,omap3-mcbsp";
+			reg = <0x48096000 0xff>;
+			reg-names = "mpu";
+			interrupts = <27>, /* OCP compliant interrupt */
+				     <81>, /* TX interrupt */
+				     <82>; /* RX interrupt */
+			interrupt-names = "common", "tx", "rx";
+			interrupt-parent = <&intc>;
+			ti,buffer-size = <128>;
+			ti,hwmods = "mcbsp5";
+		};
 	};
 };
diff --git a/arch/arm/boot/dts/omap36xx.dtsi b/arch/arm/boot/dts/omap36xx.dtsi
new file mode 100644
index 0000000..96bf028
--- /dev/null
+++ b/arch/arm/boot/dts/omap36xx.dtsi
@@ -0,0 +1,25 @@
+/*
+ * Device Tree Source for OMAP3 SoC
+ *
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+/include/ "omap3.dtsi"
+
+/ {
+	aliases {
+		serial3 = &uart4;
+	};
+
+	ocp {
+		uart4: serial@49042000 {
+			compatible = "ti,omap3-uart";
+			ti,hwmods = "uart4";
+			clock-frequency = <48000000>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/omap4-panda.dts b/arch/arm/boot/dts/omap4-panda.dts
index 9880c12..20b966e 100644
--- a/arch/arm/boot/dts/omap4-panda.dts
+++ b/arch/arm/boot/dts/omap4-panda.dts
@@ -8,6 +8,7 @@
 /dts-v1/;
 
 /include/ "omap4.dtsi"
+/include/ "elpida_ecb240abacn.dtsi"
 
 / {
 	model = "TI OMAP4 PandaBoard";
@@ -126,3 +127,13 @@
 	ti,non-removable;
 	bus-width = <4>;
 };
+
+&emif1 {
+	cs1-used;
+	device-handle = <&elpida_ECB240ABACN>;
+};
+
+&emif2 {
+	cs1-used;
+	device-handle = <&elpida_ECB240ABACN>;
+};
diff --git a/arch/arm/boot/dts/omap4-sdp.dts b/arch/arm/boot/dts/omap4-sdp.dts
index 72216e9..94a23b3 100644
--- a/arch/arm/boot/dts/omap4-sdp.dts
+++ b/arch/arm/boot/dts/omap4-sdp.dts
@@ -8,6 +8,7 @@
 /dts-v1/;
 
 /include/ "omap4.dtsi"
+/include/ "elpida_ecb240abacn.dtsi"
 
 / {
 	model = "TI OMAP4 SDP board";
@@ -18,7 +19,7 @@
 		reg = <0x80000000 0x40000000>; /* 1 GB */
 	};
 
-	vdd_eth: fixedregulator@0 {
+	vdd_eth: fixedregulator-vdd-eth {
 		compatible = "regulator-fixed";
 		regulator-name = "VDD_ETH";
 		regulator-min-microvolt = <3300000>;
@@ -28,7 +29,7 @@
 		regulator-boot-on;
 	};
 
-	vbat: fixedregulator@2 {
+	vbat: fixedregulator-vbat {
 		compatible = "regulator-fixed";
 		regulator-name = "VBAT";
 		regulator-min-microvolt = <3750000>;
@@ -115,6 +116,33 @@
 	};
 };
 
+&omap4_pmx_core {
+	uart2_pins: pinmux_uart2_pins {
+		pinctrl-single,pins = <
+			0xd8 0x118	/* uart2_cts.uart2_cts INPUT_PULLUP | MODE0 */
+			0xda 0		/* uart2_rts.uart2_rts OUTPUT | MODE0 */
+			0xdc 0x118	/* uart2_rx.uart2_rx INPUT_PULLUP | MODE0 */
+			0xde 0		/* uart2_tx.uart2_tx OUTPUT | MODE0 */
+		>;
+	};
+
+	uart3_pins: pinmux_uart3_pins {
+		pinctrl-single,pins = <
+			0x100 0x118	/* uart3_cts_rctx.uart3_cts_rctx INPUT_PULLUP | MODE0 */
+			0x102 0		/* uart3_rts_sd.uart3_rts_sd OUTPUT | MODE0 */
+			0x104 0x100	/* uart3_rx_irrx.uart3_rx_irrx INPUT | MODE0 */
+			0x106 0		/* uart3_tx_irtx.uart3_tx_irtx OUTPUT | MODE0 */
+		>;
+	};
+
+	uart4_pins: pinmux_uart4_pins {
+		pinctrl-single,pins = <
+			0x11c 0x100	/* uart4_rx.uart4_rx INPUT | MODE0 */
+			0x11e 0		/* uart4_tx.uart4_tx OUTPUT | MODE0 */
+		>;
+	};
+};
+
 &i2c1 {
 	clock-frequency = <400000>;
 
@@ -226,3 +254,98 @@
 	bus-width = <4>;
 	ti,non-removable;
 };
+
+&emif1 {
+	cs1-used;
+	device-handle = <&elpida_ECB240ABACN>;
+};
+
+&emif2 {
+	cs1-used;
+	device-handle = <&elpida_ECB240ABACN>;
+};
+
+&keypad {
+	keypad,num-rows = <8>;
+	keypad,num-columns = <8>;
+	linux,keymap = <0x00000012	/* KEY_E */
+			0x00010013	/* KEY_R */
+			0x00020014	/* KEY_T */
+			0x00030066	/* KEY_HOME */
+			0x0004003f	/* KEY_F5 */
+			0x000500f0	/* KEY_UNKNOWN */
+			0x00060017	/* KEY_I */
+			0x0007002a	/* KEY_LEFTSHIFT */
+			0x01000020	/* KEY_D*/
+			0x01010021	/* KEY_F */
+			0x01020022	/* KEY_G */
+			0x010300e7	/* KEY_SEND */
+			0x01040040	/* KEY_F6 */
+			0x010500f0	/* KEY_UNKNOWN */
+			0x01060025	/* KEY_K */
+			0x0107001c	/* KEY_ENTER */
+			0x0200002d	/* KEY_X */
+			0x0201002e	/* KEY_C */
+			0x0202002f	/* KEY_V */
+			0x0203006b	/* KEY_END */
+			0x02040041	/* KEY_F7 */
+			0x020500f0	/* KEY_UNKNOWN */
+			0x02060034	/* KEY_DOT */
+			0x0207003a	/* KEY_CAPSLOCK */
+			0x0300002c	/* KEY_Z */
+			0x0301004e	/* KEY_KPLUS */
+			0x03020030	/* KEY_B */
+			0x0303003b	/* KEY_F1 */
+			0x03040042	/* KEY_F8 */
+			0x030500f0	/* KEY_UNKNOWN */
+			0x03060018	/* KEY_O */
+			0x03070039	/* KEY_SPACE */
+			0x04000011	/* KEY_W */
+			0x04010015	/* KEY_Y */
+			0x04020016	/* KEY_U */
+			0x0403003c	/* KEY_F2 */
+			0x04040073	/* KEY_VOLUMEUP */
+			0x040500f0	/* KEY_UNKNOWN */
+			0x04060026	/* KEY_L */
+			0x04070069	/* KEY_LEFT */
+			0x0500001f	/* KEY_S */
+			0x05010023	/* KEY_H */
+			0x05020024	/* KEY_J */
+			0x0503003d	/* KEY_F3 */
+			0x05040043	/* KEY_F9 */
+			0x05050072	/* KEY_VOLUMEDOWN */
+			0x05060032	/* KEY_M */
+			0x0507006a	/* KEY_RIGHT */
+			0x06000010	/* KEY_Q */
+			0x0601001e	/* KEY_A */
+			0x06020031	/* KEY_N */
+			0x0603009e	/* KEY_BACK */
+			0x0604000e	/* KEY_BACKSPACE */
+			0x060500f0	/* KEY_UNKNOWN */
+			0x06060019	/* KEY_P */
+			0x06070067	/* KEY_UP */
+			0x07000094	/* KEY_PROG1 */
+			0x07010095	/* KEY_PROG2 */
+			0x070200ca	/* KEY_PROG3 */
+			0x070300cb	/* KEY_PROG4 */
+			0x0704003e	/* KEY_F4 */
+			0x070500f0	/* KEY_UNKNOWN */
+			0x07060160	/* KEY_OK */
+			0x0707006c>;	/* KEY_DOWN */
+	linux,input-no-autorepeat;
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart2_pins>;
+};
+
+&uart3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart3_pins>;
+};
+
+&uart4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart4_pins>;
+};
diff --git a/arch/arm/boot/dts/omap4.dtsi b/arch/arm/boot/dts/omap4.dtsi
index 04cbbcb..3883f94 100644
--- a/arch/arm/boot/dts/omap4.dtsi
+++ b/arch/arm/boot/dts/omap4.dtsi
@@ -30,12 +30,35 @@
 	cpus {
 		cpu@0 {
 			compatible = "arm,cortex-a9";
+			next-level-cache = <&L2>;
 		};
 		cpu@1 {
 			compatible = "arm,cortex-a9";
+			next-level-cache = <&L2>;
 		};
 	};
 
+	gic: interrupt-controller@48241000 {
+		compatible = "arm,cortex-a9-gic";
+		interrupt-controller;
+		#interrupt-cells = <3>;
+		reg = <0x48241000 0x1000>,
+		      <0x48240100 0x0100>;
+	};
+
+	L2: l2-cache-controller@48242000 {
+		compatible = "arm,pl310-cache";
+		reg = <0x48242000 0x1000>;
+		cache-unified;
+		cache-level = <2>;
+	};
+
+	local-timer@0x48240600 {
+		compatible = "arm,cortex-a9-twd-timer";
+		reg = <0x48240600 0x20>;
+		interrupts = <1 13 0x304>;
+	};
+
 	/*
 	 * The soc node represents the soc top level view. It is uses for IPs
 	 * that are not memory mapped in the MPU view or for the MPU itself.
@@ -61,30 +84,6 @@
 	/*
 	 * XXX: Use a flat representation of the OMAP4 interconnect.
 	 * The real OMAP interconnect network is quite complex.
-	 *
-	 * MPU -+-- MPU_PRIVATE - GIC, L2
-	 *      |
-	 *      +----------------+----------+
-	 *      |                |          |
-	 *      +            +- EMIF - DDR  |
-	 *      |            |              |
-	 *      |            +     +--------+
-	 *      |            |     |
-	 *      |            +- L4_ABE - AESS, MCBSP, TIMERs...
-	 *      |            |
-	 *      +- L3_MAIN --+- L4_CORE - IPs...
-	 *                   |
-	 *                   +- L4_PER - IPs...
-	 *                   |
-	 *                   +- L4_CFG -+- L4_WKUP - IPs...
-	 *                   |          |
-	 *                   |          +- IPs...
-	 *                   +- IPU ----+
-	 *                   |          |
-	 *                   +- DSP ----+
-	 *                   |          |
-	 *                   +- DSS ----+
-	 *
 	 * Since that will not bring real advantage to represent that in DT for
 	 * the moment, just use a fake OCP bus entry to represent the whole bus
 	 * hierarchy.
@@ -96,16 +95,27 @@
 		ranges;
 		ti,hwmods = "l3_main_1", "l3_main_2", "l3_main_3";
 
-		gic: interrupt-controller@48241000 {
-			compatible = "arm,cortex-a9-gic";
-			interrupt-controller;
-			#interrupt-cells = <3>;
-			reg = <0x48241000 0x1000>,
-			      <0x48240100 0x0100>;
+		omap4_pmx_core: pinmux@4a100040 {
+			compatible = "ti,omap4-padconf", "pinctrl-single";
+			reg = <0x4a100040 0x0196>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			pinctrl-single,register-width = <16>;
+			pinctrl-single,function-mask = <0x7fff>;
+		};
+		omap4_pmx_wkup: pinmux@4a31e040 {
+			compatible = "ti,omap4-padconf", "pinctrl-single";
+			reg = <0x4a31e040 0x0038>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			pinctrl-single,register-width = <16>;
+			pinctrl-single,function-mask = <0x7fff>;
 		};
 
 		gpio1: gpio@4a310000 {
 			compatible = "ti,omap4-gpio";
+			reg = <0x4a310000 0x200>;
+			interrupts = <0 29 0x4>;
 			ti,hwmods = "gpio1";
 			gpio-controller;
 			#gpio-cells = <2>;
@@ -115,6 +125,8 @@
 
 		gpio2: gpio@48055000 {
 			compatible = "ti,omap4-gpio";
+			reg = <0x48055000 0x200>;
+			interrupts = <0 30 0x4>;
 			ti,hwmods = "gpio2";
 			gpio-controller;
 			#gpio-cells = <2>;
@@ -124,6 +136,8 @@
 
 		gpio3: gpio@48057000 {
 			compatible = "ti,omap4-gpio";
+			reg = <0x48057000 0x200>;
+			interrupts = <0 31 0x4>;
 			ti,hwmods = "gpio3";
 			gpio-controller;
 			#gpio-cells = <2>;
@@ -133,6 +147,8 @@
 
 		gpio4: gpio@48059000 {
 			compatible = "ti,omap4-gpio";
+			reg = <0x48059000 0x200>;
+			interrupts = <0 32 0x4>;
 			ti,hwmods = "gpio4";
 			gpio-controller;
 			#gpio-cells = <2>;
@@ -142,6 +158,8 @@
 
 		gpio5: gpio@4805b000 {
 			compatible = "ti,omap4-gpio";
+			reg = <0x4805b000 0x200>;
+			interrupts = <0 33 0x4>;
 			ti,hwmods = "gpio5";
 			gpio-controller;
 			#gpio-cells = <2>;
@@ -151,6 +169,8 @@
 
 		gpio6: gpio@4805d000 {
 			compatible = "ti,omap4-gpio";
+			reg = <0x4805d000 0x200>;
+			interrupts = <0 34 0x4>;
 			ti,hwmods = "gpio6";
 			gpio-controller;
 			#gpio-cells = <2>;
@@ -160,30 +180,40 @@
 
 		uart1: serial@4806a000 {
 			compatible = "ti,omap4-uart";
+			reg = <0x4806a000 0x100>;
+			interrupts = <0 72 0x4>;
 			ti,hwmods = "uart1";
 			clock-frequency = <48000000>;
 		};
 
 		uart2: serial@4806c000 {
 			compatible = "ti,omap4-uart";
+			reg = <0x4806c000 0x100>;
+			interrupts = <0 73 0x4>;
 			ti,hwmods = "uart2";
 			clock-frequency = <48000000>;
 		};
 
 		uart3: serial@48020000 {
 			compatible = "ti,omap4-uart";
+			reg = <0x48020000 0x100>;
+			interrupts = <0 74 0x4>;
 			ti,hwmods = "uart3";
 			clock-frequency = <48000000>;
 		};
 
 		uart4: serial@4806e000 {
 			compatible = "ti,omap4-uart";
+			reg = <0x4806e000 0x100>;
+			interrupts = <0 70 0x4>;
 			ti,hwmods = "uart4";
 			clock-frequency = <48000000>;
 		};
 
 		i2c1: i2c@48070000 {
 			compatible = "ti,omap4-i2c";
+			reg = <0x48070000 0x100>;
+			interrupts = <0 56 0x4>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			ti,hwmods = "i2c1";
@@ -191,6 +221,8 @@
 
 		i2c2: i2c@48072000 {
 			compatible = "ti,omap4-i2c";
+			reg = <0x48072000 0x100>;
+			interrupts = <0 57 0x4>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			ti,hwmods = "i2c2";
@@ -198,6 +230,8 @@
 
 		i2c3: i2c@48060000 {
 			compatible = "ti,omap4-i2c";
+			reg = <0x48060000 0x100>;
+			interrupts = <0 61 0x4>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			ti,hwmods = "i2c3";
@@ -205,6 +239,8 @@
 
 		i2c4: i2c@48350000 {
 			compatible = "ti,omap4-i2c";
+			reg = <0x48350000 0x100>;
+			interrupts = <0 62 0x4>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			ti,hwmods = "i2c4";
@@ -212,6 +248,8 @@
 
 		mcspi1: spi@48098000 {
 			compatible = "ti,omap4-mcspi";
+			reg = <0x48098000 0x200>;
+			interrupts = <0 65 0x4>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			ti,hwmods = "mcspi1";
@@ -220,6 +258,8 @@
 
 		mcspi2: spi@4809a000 {
 			compatible = "ti,omap4-mcspi";
+			reg = <0x4809a000 0x200>;
+			interrupts = <0 66 0x4>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			ti,hwmods = "mcspi2";
@@ -228,6 +268,8 @@
 
 		mcspi3: spi@480b8000 {
 			compatible = "ti,omap4-mcspi";
+			reg = <0x480b8000 0x200>;
+			interrupts = <0 91 0x4>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			ti,hwmods = "mcspi3";
@@ -236,6 +278,8 @@
 
 		mcspi4: spi@480ba000 {
 			compatible = "ti,omap4-mcspi";
+			reg = <0x480ba000 0x200>;
+			interrupts = <0 48 0x4>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			ti,hwmods = "mcspi4";
@@ -244,6 +288,8 @@
 
 		mmc1: mmc@4809c000 {
 			compatible = "ti,omap4-hsmmc";
+			reg = <0x4809c000 0x400>;
+			interrupts = <0 83 0x4>;
 			ti,hwmods = "mmc1";
 			ti,dual-volt;
 			ti,needs-special-reset;
@@ -251,30 +297,40 @@
 
 		mmc2: mmc@480b4000 {
 			compatible = "ti,omap4-hsmmc";
+			reg = <0x480b4000 0x400>;
+			interrupts = <0 86 0x4>;
 			ti,hwmods = "mmc2";
 			ti,needs-special-reset;
 		};
 
 		mmc3: mmc@480ad000 {
 			compatible = "ti,omap4-hsmmc";
+			reg = <0x480ad000 0x400>;
+			interrupts = <0 94 0x4>;
 			ti,hwmods = "mmc3";
 			ti,needs-special-reset;
 		};
 
 		mmc4: mmc@480d1000 {
 			compatible = "ti,omap4-hsmmc";
+			reg = <0x480d1000 0x400>;
+			interrupts = <0 96 0x4>;
 			ti,hwmods = "mmc4";
 			ti,needs-special-reset;
 		};
 
 		mmc5: mmc@480d5000 {
 			compatible = "ti,omap4-hsmmc";
+			reg = <0x480d5000 0x400>;
+			interrupts = <0 59 0x4>;
 			ti,hwmods = "mmc5";
 			ti,needs-special-reset;
 		};
 
 		wdt2: wdt@4a314000 {
 			compatible = "ti,omap4-wdt", "ti,omap3-wdt";
+			reg = <0x4a314000 0x80>;
+			interrupts = <0 80 0x4>;
 			ti,hwmods = "wd_timer2";
 		};
 
@@ -282,6 +338,7 @@
 			compatible = "ti,omap4-mcpdm";
 			reg = <0x40132000 0x7f>, /* MPU private access */
 			      <0x49032000 0x7f>; /* L3 Interconnect */
+			reg-names = "mpu", "dma";
 			interrupts = <0 112 0x4>;
 			interrupt-parent = <&gic>;
 			ti,hwmods = "mcpdm";
@@ -291,9 +348,95 @@
 			compatible = "ti,omap4-dmic";
 			reg = <0x4012e000 0x7f>, /* MPU private access */
 			      <0x4902e000 0x7f>; /* L3 Interconnect */
+			reg-names = "mpu", "dma";
 			interrupts = <0 114 0x4>;
 			interrupt-parent = <&gic>;
 			ti,hwmods = "dmic";
 		};
+
+		mcbsp1: mcbsp@40122000 {
+			compatible = "ti,omap4-mcbsp";
+			reg = <0x40122000 0xff>, /* MPU private access */
+			      <0x49022000 0xff>; /* L3 Interconnect */
+			reg-names = "mpu", "dma";
+			interrupts = <0 17 0x4>;
+			interrupt-names = "common";
+			interrupt-parent = <&gic>;
+			ti,buffer-size = <128>;
+			ti,hwmods = "mcbsp1";
+		};
+
+		mcbsp2: mcbsp@40124000 {
+			compatible = "ti,omap4-mcbsp";
+			reg = <0x40124000 0xff>, /* MPU private access */
+			      <0x49024000 0xff>; /* L3 Interconnect */
+			reg-names = "mpu", "dma";
+			interrupts = <0 22 0x4>;
+			interrupt-names = "common";
+			interrupt-parent = <&gic>;
+			ti,buffer-size = <128>;
+			ti,hwmods = "mcbsp2";
+		};
+
+		mcbsp3: mcbsp@40126000 {
+			compatible = "ti,omap4-mcbsp";
+			reg = <0x40126000 0xff>, /* MPU private access */
+			      <0x49026000 0xff>; /* L3 Interconnect */
+			reg-names = "mpu", "dma";
+			interrupts = <0 23 0x4>;
+			interrupt-names = "common";
+			interrupt-parent = <&gic>;
+			ti,buffer-size = <128>;
+			ti,hwmods = "mcbsp3";
+		};
+
+		mcbsp4: mcbsp@48096000 {
+			compatible = "ti,omap4-mcbsp";
+			reg = <0x48096000 0xff>; /* L4 Interconnect */
+			reg-names = "mpu";
+			interrupts = <0 16 0x4>;
+			interrupt-names = "common";
+			interrupt-parent = <&gic>;
+			ti,buffer-size = <128>;
+			ti,hwmods = "mcbsp4";
+		};
+
+		keypad: keypad@4a31c000 {
+			compatible = "ti,omap4-keypad";
+			reg = <0x4a31c000 0x80>;
+			interrupts = <0 120 0x4>;
+			reg-names = "mpu";
+			ti,hwmods = "kbd";
+		};
+
+		emif1: emif@4c000000 {
+			compatible = "ti,emif-4d";
+			reg = <0x4c000000 0x100>;
+			interrupts = <0 110 0x4>;
+			ti,hwmods = "emif1";
+			phy-type = <1>;
+			hw-caps-read-idle-ctrl;
+			hw-caps-ll-interface;
+			hw-caps-temp-alert;
+		};
+
+		emif2: emif@4d000000 {
+			compatible = "ti,emif-4d";
+			reg = <0x4d000000 0x100>;
+			interrupts = <0 111 0x4>;
+			ti,hwmods = "emif2";
+			phy-type = <1>;
+			hw-caps-read-idle-ctrl;
+			hw-caps-ll-interface;
+			hw-caps-temp-alert;
+		};
+
+		ocp2scp {
+			compatible = "ti,omap-ocp2scp";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+			ti,hwmods = "ocp2scp_usb_phy";
+		};
 	};
 };
diff --git a/arch/arm/boot/dts/omap5-evm.dts b/arch/arm/boot/dts/omap5-evm.dts
index 200c39a..9c41a3f 100644
--- a/arch/arm/boot/dts/omap5-evm.dts
+++ b/arch/arm/boot/dts/omap5-evm.dts
@@ -17,4 +17,68 @@
 		device_type = "memory";
 		reg = <0x80000000 0x40000000>; /* 1 GB */
 	};
+
+	vmmcsd_fixed: fixedregulator-mmcsd {
+		compatible = "regulator-fixed";
+		regulator-name = "vmmcsd_fixed";
+		regulator-min-microvolt = <3000000>;
+		regulator-max-microvolt = <3000000>;
+	};
+
+};
+
+&mmc1 {
+	vmmc-supply = <&vmmcsd_fixed>;
+	bus-width = <4>;
+};
+
+&mmc2 {
+	vmmc-supply = <&vmmcsd_fixed>;
+	bus-width = <8>;
+	ti,non-removable;
+};
+
+&mmc3 {
+	bus-width = <4>;
+	ti,non-removable;
+};
+
+&mmc4 {
+	status = "disabled";
+};
+
+&mmc5 {
+	status = "disabled";
+};
+
+&i2c2 {
+	clock-frequency = <400000>;
+
+	/* Pressure Sensor */
+	bmp085@77 {
+		compatible = "bosch,bmp085";
+		reg = <0x77>;
+	};
+};
+
+&i2c4 {
+	clock-frequency = <400000>;
+
+	/* Temperature Sensor */
+	tmp102@48{
+		compatible = "ti,tmp102";
+		reg = <0x48>;
+	};
+};
+
+&keypad {
+	keypad,num-rows = <8>;
+	keypad,num-columns = <8>;
+	linux,keymap = <0x02020073	/* VOLUP */
+			0x02030072	/* VOLDOWM */
+			0x020400e7	/* SEND */
+			0x02050066	/* HOME */
+			0x0206006b	/* END */
+			0x020700d9>;	/* SEARCH */
+	linux,input-no-autorepeat;
 };
diff --git a/arch/arm/boot/dts/omap5.dtsi b/arch/arm/boot/dts/omap5.dtsi
index 57e5270..9ac75b3 100644
--- a/arch/arm/boot/dts/omap5.dtsi
+++ b/arch/arm/boot/dts/omap5.dtsi
@@ -145,6 +145,41 @@
 			#interrupt-cells = <1>;
 		};
 
+		i2c1: i2c@48070000 {
+			compatible = "ti,omap4-i2c";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			ti,hwmods = "i2c1";
+		};
+
+		i2c2: i2c@48072000 {
+			compatible = "ti,omap4-i2c";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			ti,hwmods = "i2c2";
+		};
+
+		i2c3: i2c@48060000 {
+			compatible = "ti,omap4-i2c";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			ti,hwmods = "i2c3";
+		};
+
+		i2c4: i2c@4807A000 {
+			compatible = "ti,omap4-i2c";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			ti,hwmods = "i2c4";
+		};
+
+		i2c5: i2c@4807C000 {
+			compatible = "ti,omap4-i2c";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			ti,hwmods = "i2c5";
+		};
+
 		uart1: serial@4806a000 {
 			compatible = "ti,omap4-uart";
 			ti,hwmods = "uart1";
@@ -180,5 +215,97 @@
 			ti,hwmods = "uart6";
 			clock-frequency = <48000000>;
 		};
+
+		mmc1: mmc@4809c000 {
+			compatible = "ti,omap4-hsmmc";
+			ti,hwmods = "mmc1";
+			ti,dual-volt;
+			ti,needs-special-reset;
+		};
+
+		mmc2: mmc@480b4000 {
+			compatible = "ti,omap4-hsmmc";
+			ti,hwmods = "mmc2";
+			ti,needs-special-reset;
+		};
+
+		mmc3: mmc@480ad000 {
+			compatible = "ti,omap4-hsmmc";
+			ti,hwmods = "mmc3";
+			ti,needs-special-reset;
+		};
+
+		mmc4: mmc@480d1000 {
+			compatible = "ti,omap4-hsmmc";
+			ti,hwmods = "mmc4";
+			ti,needs-special-reset;
+		};
+
+		mmc5: mmc@480d5000 {
+			compatible = "ti,omap4-hsmmc";
+			ti,hwmods = "mmc5";
+			ti,needs-special-reset;
+		};
+
+		keypad: keypad@4ae1c000 {
+			compatible = "ti,omap4-keypad";
+			ti,hwmods = "kbd";
+		};
+
+		mcpdm: mcpdm@40132000 {
+			compatible = "ti,omap4-mcpdm";
+			reg = <0x40132000 0x7f>, /* MPU private access */
+			      <0x49032000 0x7f>; /* L3 Interconnect */
+			reg-names = "mpu", "dma";
+			interrupts = <0 112 0x4>;
+			interrupt-parent = <&gic>;
+			ti,hwmods = "mcpdm";
+		};
+
+		dmic: dmic@4012e000 {
+			compatible = "ti,omap4-dmic";
+			reg = <0x4012e000 0x7f>, /* MPU private access */
+			      <0x4902e000 0x7f>; /* L3 Interconnect */
+			reg-names = "mpu", "dma";
+			interrupts = <0 114 0x4>;
+			interrupt-parent = <&gic>;
+			ti,hwmods = "dmic";
+		};
+
+		mcbsp1: mcbsp@40122000 {
+			compatible = "ti,omap4-mcbsp";
+			reg = <0x40122000 0xff>, /* MPU private access */
+			      <0x49022000 0xff>; /* L3 Interconnect */
+			reg-names = "mpu", "dma";
+			interrupts = <0 17 0x4>;
+			interrupt-names = "common";
+			interrupt-parent = <&gic>;
+			ti,buffer-size = <128>;
+			ti,hwmods = "mcbsp1";
+		};
+
+		mcbsp2: mcbsp@40124000 {
+			compatible = "ti,omap4-mcbsp";
+			reg = <0x40124000 0xff>, /* MPU private access */
+			      <0x49024000 0xff>; /* L3 Interconnect */
+			reg-names = "mpu", "dma";
+			interrupts = <0 22 0x4>;
+			interrupt-names = "common";
+			interrupt-parent = <&gic>;
+			ti,buffer-size = <128>;
+			ti,hwmods = "mcbsp2";
+		};
+
+		mcbsp3: mcbsp@40126000 {
+			compatible = "ti,omap4-mcbsp";
+			reg = <0x40126000 0xff>, /* MPU private access */
+			      <0x49026000 0xff>; /* L3 Interconnect */
+			reg-names = "mpu", "dma";
+			interrupts = <0 23 0x4>;
+			interrupt-names = "common";
+			interrupt-parent = <&gic>;
+			ti,buffer-size = <128>;
+			ti,hwmods = "mcbsp3";
+		};
 	};
 };
diff --git a/arch/arm/boot/dts/phy3250.dts b/arch/arm/boot/dts/phy3250.dts
index 802ec5b..a7ad85e 100644
--- a/arch/arm/boot/dts/phy3250.dts
+++ b/arch/arm/boot/dts/phy3250.dts
@@ -135,13 +135,11 @@
 			ssp0: ssp@20084000 {
 				#address-cells = <1>;
 				#size-cells = <0>;
-				pl022,num-chipselects = <1>;
+				num-cs = <1>;
 				cs-gpios = <&gpio 3 5 0>;
 
 				eeprom: at25@0 {
-					pl022,hierarchy = <0>;
 					pl022,interface = <0>;
-					pl022,slave-tx-disable = <0>;
 					pl022,com-mode = <0>;
 					pl022,rx-level-trig = <1>;
 					pl022,tx-level-trig = <1>;
diff --git a/arch/arm/boot/dts/prima2-cb.dts b/arch/arm/boot/dts/prima2-cb.dts
deleted file mode 100644
index 34ae3a6..0000000
--- a/arch/arm/boot/dts/prima2-cb.dts
+++ /dev/null
@@ -1,424 +0,0 @@
-/dts-v1/;
-/ {
-	model = "SiRF Prima2 eVB";
-	compatible = "sirf,prima2-cb", "sirf,prima2";
-	#address-cells = <1>;
-	#size-cells = <1>;
-	interrupt-parent = <&intc>;
-
-	memory {
-		reg = <0x00000000 0x20000000>;
-	};
-
-	chosen {
-		bootargs = "mem=512M real_root=/dev/mmcblk0p2 console=ttyS0 panel=1 bootsplash=true bpp=16 androidboot.console=ttyS1";
-		linux,stdout-path = &uart1;
-	};
-
-	cpus {
-		#address-cells = <1>;
-		#size-cells = <0>;
-
-		cpu@0 {
-			reg = <0x0>;
-			d-cache-line-size = <32>;
-			i-cache-line-size = <32>;
-			d-cache-size = <32768>;
-			i-cache-size = <32768>;
-			/* from bootloader */
-			timebase-frequency = <0>;
-			bus-frequency = <0>;
-			clock-frequency = <0>;
-		};
-	};
-
-	axi {
-		compatible = "simple-bus";
-		#address-cells = <1>;
-		#size-cells = <1>;
-		ranges = <0x40000000 0x40000000 0x80000000>;
-
-		l2-cache-controller@80040000 {
-			compatible = "arm,pl310-cache", "sirf,prima2-pl310-cache";
-			reg = <0x80040000 0x1000>;
-			interrupts = <59>;
-			arm,tag-latency = <1 1 1>;
-			arm,data-latency = <1 1 1>;
-			arm,filter-ranges = <0 0x40000000>;
-		};
-
-		intc: interrupt-controller@80020000 {
-			#interrupt-cells = <1>;
-			interrupt-controller;
-			compatible = "sirf,prima2-intc";
-			reg = <0x80020000 0x1000>;
-		};
-
-		sys-iobg {
-			compatible = "simple-bus";
-			#address-cells = <1>;
-			#size-cells = <1>;
-			ranges = <0x88000000 0x88000000 0x40000>;
-
-			clock-controller@88000000 {
-				compatible = "sirf,prima2-clkc";
-				reg = <0x88000000 0x1000>;
-				interrupts = <3>;
-			};
-
-			reset-controller@88010000 {
-				compatible = "sirf,prima2-rstc";
-				reg = <0x88010000 0x1000>;
-			};
-
-			rsc-controller@88020000 {
-				compatible = "sirf,prima2-rsc";
-				reg = <0x88020000 0x1000>;
-			};
-		};
-
-		mem-iobg {
-			compatible = "simple-bus";
-			#address-cells = <1>;
-			#size-cells = <1>;
-			ranges = <0x90000000 0x90000000 0x10000>;
-
-			memory-controller@90000000 {
-				compatible = "sirf,prima2-memc";
-				reg = <0x90000000 0x10000>;
-				interrupts = <27>;
-			};
-		};
-
-		disp-iobg {
-			compatible = "simple-bus";
-			#address-cells = <1>;
-			#size-cells = <1>;
-			ranges = <0x90010000 0x90010000 0x30000>;
-
-			display@90010000 {
-				compatible = "sirf,prima2-lcd";
-				reg = <0x90010000 0x20000>;
-				interrupts = <30>;
-			};
-
-			vpp@90020000 {
-				compatible = "sirf,prima2-vpp";
-				reg = <0x90020000 0x10000>;
-				interrupts = <31>;
-			};
-		};
-
-		graphics-iobg {
-			compatible = "simple-bus";
-			#address-cells = <1>;
-			#size-cells = <1>;
-			ranges = <0x98000000 0x98000000 0x8000000>;
-
-			graphics@98000000 {
-				compatible = "powervr,sgx531";
-				reg = <0x98000000 0x8000000>;
-				interrupts = <6>;
-			};
-		};
-
-		multimedia-iobg {
-			compatible = "simple-bus";
-			#address-cells = <1>;
-			#size-cells = <1>;
-			ranges = <0xa0000000 0xa0000000 0x8000000>;
-
-			multimedia@a0000000 {
-				compatible = "sirf,prima2-video-codec";
-				reg = <0xa0000000 0x8000000>;
-				interrupts = <5>;
-			};
-		};
-
-		dsp-iobg {
-			compatible = "simple-bus";
-			#address-cells = <1>;
-			#size-cells = <1>;
-			ranges = <0xa8000000 0xa8000000 0x2000000>;
-
-			dspif@a8000000 {
-				compatible = "sirf,prima2-dspif";
-				reg = <0xa8000000 0x10000>;
-				interrupts = <9>;
-			};
-
-			gps@a8010000 {
-				compatible = "sirf,prima2-gps";
-				reg = <0xa8010000 0x10000>;
-				interrupts = <7>;
-			};
-
-			dsp@a9000000 {
-				compatible = "sirf,prima2-dsp";
-				reg = <0xa9000000 0x1000000>;
-				interrupts = <8>;
-			};
-		};
-
-		peri-iobg {
-			compatible = "simple-bus";
-			#address-cells = <1>;
-			#size-cells = <1>;
-			ranges = <0xb0000000 0xb0000000 0x180000>;
-
-			timer@b0020000 {
-				compatible = "sirf,prima2-tick";
-				reg = <0xb0020000 0x1000>;
-				interrupts = <0>;
-			};
-
-			nand@b0030000 {
-				compatible = "sirf,prima2-nand";
-				reg = <0xb0030000 0x10000>;
-				interrupts = <41>;
-			};
-
-			audio@b0040000 {
-				compatible = "sirf,prima2-audio";
-				reg = <0xb0040000 0x10000>;
-				interrupts = <35>;
-			};
-
-			uart0: uart@b0050000 {
-				cell-index = <0>;
-				compatible = "sirf,prima2-uart";
-				reg = <0xb0050000 0x10000>;
-				interrupts = <17>;
-			};
-
-			uart1: uart@b0060000 {
-				cell-index = <1>;
-				compatible = "sirf,prima2-uart";
-				reg = <0xb0060000 0x10000>;
-				interrupts = <18>;
-			};
-
-			uart2: uart@b0070000 {
-				cell-index = <2>;
-				compatible = "sirf,prima2-uart";
-				reg = <0xb0070000 0x10000>;
-				interrupts = <19>;
-			};
-
-			usp0: usp@b0080000 {
-				cell-index = <0>;
-				compatible = "sirf,prima2-usp";
-				reg = <0xb0080000 0x10000>;
-				interrupts = <20>;
-			};
-
-			usp1: usp@b0090000 {
-				cell-index = <1>;
-				compatible = "sirf,prima2-usp";
-				reg = <0xb0090000 0x10000>;
-				interrupts = <21>;
-			};
-
-			usp2: usp@b00a0000 {
-				cell-index = <2>;
-				compatible = "sirf,prima2-usp";
-				reg = <0xb00a0000 0x10000>;
-				interrupts = <22>;
-			};
-
-			dmac0: dma-controller@b00b0000 {
-				cell-index = <0>;
-				compatible = "sirf,prima2-dmac";
-				reg = <0xb00b0000 0x10000>;
-				interrupts = <12>;
-			};
-
-			dmac1: dma-controller@b0160000 {
-				cell-index = <1>;
-				compatible = "sirf,prima2-dmac";
-				reg = <0xb0160000 0x10000>;
-				interrupts = <13>;
-			};
-
-			vip@b00C0000 {
-				compatible = "sirf,prima2-vip";
-				reg = <0xb00C0000 0x10000>;
-			};
-
-			spi0: spi@b00d0000 {
-				cell-index = <0>;
-				compatible = "sirf,prima2-spi";
-				reg = <0xb00d0000 0x10000>;
-				interrupts = <15>;
-			};
-
-			spi1: spi@b0170000 {
-				cell-index = <1>;
-				compatible = "sirf,prima2-spi";
-				reg = <0xb0170000 0x10000>;
-				interrupts = <16>;
-			};
-
-			i2c0: i2c@b00e0000 {
-				cell-index = <0>;
-				compatible = "sirf,prima2-i2c";
-				reg = <0xb00e0000 0x10000>;
-				interrupts = <24>;
-			};
-
-			i2c1: i2c@b00f0000 {
-				cell-index = <1>;
-				compatible = "sirf,prima2-i2c";
-				reg = <0xb00f0000 0x10000>;
-				interrupts = <25>;
-			};
-
-			tsc@b0110000 {
-				compatible = "sirf,prima2-tsc";
-				reg = <0xb0110000 0x10000>;
-				interrupts = <33>;
-			};
-
-			gpio: gpio-controller@b0120000 {
-				#gpio-cells = <2>;
-				#interrupt-cells = <2>;
-				compatible = "sirf,prima2-gpio-pinmux";
-				reg = <0xb0120000 0x10000>;
-				gpio-controller;
-				interrupt-controller;
-			};
-
-			pwm@b0130000 {
-				compatible = "sirf,prima2-pwm";
-				reg = <0xb0130000 0x10000>;
-			};
-
-			efusesys@b0140000 {
-				compatible = "sirf,prima2-efuse";
-				reg = <0xb0140000 0x10000>;
-			};
-
-			pulsec@b0150000 {
-				compatible = "sirf,prima2-pulsec";
-				reg = <0xb0150000 0x10000>;
-				interrupts = <48>;
-			};
-
-			pci-iobg {
-				compatible = "sirf,prima2-pciiobg", "simple-bus";
-				#address-cells = <1>;
-				#size-cells = <1>;
-				ranges = <0x56000000 0x56000000 0x1b00000>;
-
-				sd0: sdhci@56000000 {
-					cell-index = <0>;
-					compatible = "sirf,prima2-sdhc";
-					reg = <0x56000000 0x100000>;
-					interrupts = <38>;
-				};
-
-				sd1: sdhci@56100000 {
-					cell-index = <1>;
-					compatible = "sirf,prima2-sdhc";
-					reg = <0x56100000 0x100000>;
-					interrupts = <38>;
-				};
-
-				sd2: sdhci@56200000 {
-					cell-index = <2>;
-					compatible = "sirf,prima2-sdhc";
-					reg = <0x56200000 0x100000>;
-					interrupts = <23>;
-				};
-
-				sd3: sdhci@56300000 {
-					cell-index = <3>;
-					compatible = "sirf,prima2-sdhc";
-					reg = <0x56300000 0x100000>;
-					interrupts = <23>;
-				};
-
-				sd4: sdhci@56400000 {
-					cell-index = <4>;
-					compatible = "sirf,prima2-sdhc";
-					reg = <0x56400000 0x100000>;
-					interrupts = <39>;
-				};
-
-				sd5: sdhci@56500000 {
-					cell-index = <5>;
-					compatible = "sirf,prima2-sdhc";
-					reg = <0x56500000 0x100000>;
-					interrupts = <39>;
-				};
-
-				pci-copy@57900000 {
-					compatible = "sirf,prima2-pcicp";
-					reg = <0x57900000 0x100000>;
-					interrupts = <40>;
-				};
-
-				rom-interface@57a00000 {
-					compatible = "sirf,prima2-romif";
-					reg = <0x57a00000 0x100000>;
-				};
-			};
-		};
-
-		rtc-iobg {
-			compatible = "sirf,prima2-rtciobg", "sirf-prima2-rtciobg-bus";
-			#address-cells = <1>;
-			#size-cells = <1>;
-			reg = <0x80030000 0x10000>;
-
-			gpsrtc@1000 {
-				compatible = "sirf,prima2-gpsrtc";
-				reg = <0x1000 0x1000>;
-				interrupts = <55 56 57>;
-			};
-
-			sysrtc@2000 {
-				compatible = "sirf,prima2-sysrtc";
-				reg = <0x2000 0x1000>;
-				interrupts = <52 53 54>;
-			};
-
-			pwrc@3000 {
-				compatible = "sirf,prima2-pwrc";
-				reg = <0x3000 0x1000>;
-				interrupts = <32>;
-			};
-		};
-
-		uus-iobg {
-			compatible = "simple-bus";
-			#address-cells = <1>;
-			#size-cells = <1>;
-			ranges = <0xb8000000 0xb8000000 0x40000>;
-
-			usb0: usb@b00e0000 {
-				compatible = "chipidea,ci13611a-prima2";
-				reg = <0xb8000000 0x10000>;
-				interrupts = <10>;
-			};
-
-			usb1: usb@b00f0000 {
-				compatible = "chipidea,ci13611a-prima2";
-				reg = <0xb8010000 0x10000>;
-				interrupts = <11>;
-			};
-
-			sata@b00f0000 {
-				compatible = "synopsys,dwc-ahsata";
-				reg = <0xb8020000 0x10000>;
-				interrupts = <37>;
-			};
-
-			security@b00f0000 {
-				compatible = "sirf,prima2-security";
-				reg = <0xb8030000 0x10000>;
-				interrupts = <42>;
-			};
-		};
-	};
-};
diff --git a/arch/arm/boot/dts/prima2-evb.dts b/arch/arm/boot/dts/prima2-evb.dts
new file mode 100644
index 0000000..57286b4
--- /dev/null
+++ b/arch/arm/boot/dts/prima2-evb.dts
@@ -0,0 +1,37 @@
+/*
+ * DTS file for CSR SiRFprimaII Evaluation Board
+ *
+ * Copyright (c) 2012 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+/dts-v1/;
+
+/include/ "prima2.dtsi"
+
+/ {
+	model = "CSR SiRFprimaII Evaluation Board";
+	compatible = "sirf,prima2", "sirf,prima2-cb";
+
+	memory {
+		reg = <0x00000000 0x20000000>;
+	};
+
+	axi {
+		peri-iobg {
+			uart@b0060000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&uart1_pins_a>;
+			};
+			spi@b00d0000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&spi0_pins_a>;
+			};
+			spi@b0170000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&spi1_pins_a>;
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/prima2.dtsi b/arch/arm/boot/dts/prima2.dtsi
new file mode 100644
index 0000000..055fca5
--- /dev/null
+++ b/arch/arm/boot/dts/prima2.dtsi
@@ -0,0 +1,640 @@
+/*
+ * DTS file for CSR SiRFprimaII SoC
+ *
+ * Copyright (c) 2012 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+/include/ "skeleton.dtsi"
+/ {
+	compatible = "sirf,prima2";
+	#address-cells = <1>;
+	#size-cells = <1>;
+	interrupt-parent = <&intc>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			reg = <0x0>;
+			d-cache-line-size = <32>;
+			i-cache-line-size = <32>;
+			d-cache-size = <32768>;
+			i-cache-size = <32768>;
+			/* from bootloader */
+			timebase-frequency = <0>;
+			bus-frequency = <0>;
+			clock-frequency = <0>;
+		};
+	};
+
+	axi {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0x40000000 0x40000000 0x80000000>;
+
+		l2-cache-controller@80040000 {
+			compatible = "arm,pl310-cache", "sirf,prima2-pl310-cache";
+			reg = <0x80040000 0x1000>;
+			interrupts = <59>;
+			arm,tag-latency = <1 1 1>;
+			arm,data-latency = <1 1 1>;
+			arm,filter-ranges = <0 0x40000000>;
+		};
+
+		intc: interrupt-controller@80020000 {
+			#interrupt-cells = <1>;
+			interrupt-controller;
+			compatible = "sirf,prima2-intc";
+			reg = <0x80020000 0x1000>;
+		};
+
+		sys-iobg {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0x88000000 0x88000000 0x40000>;
+
+			clock-controller@88000000 {
+				compatible = "sirf,prima2-clkc";
+				reg = <0x88000000 0x1000>;
+				interrupts = <3>;
+			};
+
+			reset-controller@88010000 {
+				compatible = "sirf,prima2-rstc";
+				reg = <0x88010000 0x1000>;
+			};
+
+			rsc-controller@88020000 {
+				compatible = "sirf,prima2-rsc";
+				reg = <0x88020000 0x1000>;
+			};
+		};
+
+		mem-iobg {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0x90000000 0x90000000 0x10000>;
+
+			memory-controller@90000000 {
+				compatible = "sirf,prima2-memc";
+				reg = <0x90000000 0x10000>;
+				interrupts = <27>;
+			};
+		};
+
+		disp-iobg {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0x90010000 0x90010000 0x30000>;
+
+			display@90010000 {
+				compatible = "sirf,prima2-lcd";
+				reg = <0x90010000 0x20000>;
+				interrupts = <30>;
+			};
+
+			vpp@90020000 {
+				compatible = "sirf,prima2-vpp";
+				reg = <0x90020000 0x10000>;
+				interrupts = <31>;
+			};
+		};
+
+		graphics-iobg {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0x98000000 0x98000000 0x8000000>;
+
+			graphics@98000000 {
+				compatible = "powervr,sgx531";
+				reg = <0x98000000 0x8000000>;
+				interrupts = <6>;
+			};
+		};
+
+		multimedia-iobg {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0xa0000000 0xa0000000 0x8000000>;
+
+			multimedia@a0000000 {
+				compatible = "sirf,prima2-video-codec";
+				reg = <0xa0000000 0x8000000>;
+				interrupts = <5>;
+			};
+		};
+
+		dsp-iobg {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0xa8000000 0xa8000000 0x2000000>;
+
+			dspif@a8000000 {
+				compatible = "sirf,prima2-dspif";
+				reg = <0xa8000000 0x10000>;
+				interrupts = <9>;
+			};
+
+			gps@a8010000 {
+				compatible = "sirf,prima2-gps";
+				reg = <0xa8010000 0x10000>;
+				interrupts = <7>;
+			};
+
+			dsp@a9000000 {
+				compatible = "sirf,prima2-dsp";
+				reg = <0xa9000000 0x1000000>;
+				interrupts = <8>;
+			};
+		};
+
+		peri-iobg {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0xb0000000 0xb0000000 0x180000>;
+
+			timer@b0020000 {
+				compatible = "sirf,prima2-tick";
+				reg = <0xb0020000 0x1000>;
+				interrupts = <0>;
+			};
+
+			nand@b0030000 {
+				compatible = "sirf,prima2-nand";
+				reg = <0xb0030000 0x10000>;
+				interrupts = <41>;
+			};
+
+			audio@b0040000 {
+				compatible = "sirf,prima2-audio";
+				reg = <0xb0040000 0x10000>;
+				interrupts = <35>;
+			};
+
+			uart0: uart@b0050000 {
+				cell-index = <0>;
+				compatible = "sirf,prima2-uart";
+				reg = <0xb0050000 0x10000>;
+				interrupts = <17>;
+			};
+
+			uart1: uart@b0060000 {
+				cell-index = <1>;
+				compatible = "sirf,prima2-uart";
+				reg = <0xb0060000 0x10000>;
+				interrupts = <18>;
+			};
+
+			uart2: uart@b0070000 {
+				cell-index = <2>;
+				compatible = "sirf,prima2-uart";
+				reg = <0xb0070000 0x10000>;
+				interrupts = <19>;
+			};
+
+			usp0: usp@b0080000 {
+				cell-index = <0>;
+				compatible = "sirf,prima2-usp";
+				reg = <0xb0080000 0x10000>;
+				interrupts = <20>;
+			};
+
+			usp1: usp@b0090000 {
+				cell-index = <1>;
+				compatible = "sirf,prima2-usp";
+				reg = <0xb0090000 0x10000>;
+				interrupts = <21>;
+			};
+
+			usp2: usp@b00a0000 {
+				cell-index = <2>;
+				compatible = "sirf,prima2-usp";
+				reg = <0xb00a0000 0x10000>;
+				interrupts = <22>;
+			};
+
+			dmac0: dma-controller@b00b0000 {
+				cell-index = <0>;
+				compatible = "sirf,prima2-dmac";
+				reg = <0xb00b0000 0x10000>;
+				interrupts = <12>;
+			};
+
+			dmac1: dma-controller@b0160000 {
+				cell-index = <1>;
+				compatible = "sirf,prima2-dmac";
+				reg = <0xb0160000 0x10000>;
+				interrupts = <13>;
+			};
+
+			vip@b00C0000 {
+				compatible = "sirf,prima2-vip";
+				reg = <0xb00C0000 0x10000>;
+			};
+
+			spi0: spi@b00d0000 {
+				cell-index = <0>;
+				compatible = "sirf,prima2-spi";
+				reg = <0xb00d0000 0x10000>;
+				interrupts = <15>;
+			};
+
+			spi1: spi@b0170000 {
+				cell-index = <1>;
+				compatible = "sirf,prima2-spi";
+				reg = <0xb0170000 0x10000>;
+				interrupts = <16>;
+			};
+
+			i2c0: i2c@b00e0000 {
+				cell-index = <0>;
+				compatible = "sirf,prima2-i2c";
+				reg = <0xb00e0000 0x10000>;
+				interrupts = <24>;
+			};
+
+			i2c1: i2c@b00f0000 {
+				cell-index = <1>;
+				compatible = "sirf,prima2-i2c";
+				reg = <0xb00f0000 0x10000>;
+				interrupts = <25>;
+			};
+
+			tsc@b0110000 {
+				compatible = "sirf,prima2-tsc";
+				reg = <0xb0110000 0x10000>;
+				interrupts = <33>;
+			};
+
+			gpio: pinctrl@b0120000 {
+				#gpio-cells = <2>;
+				#interrupt-cells = <2>;
+				compatible = "sirf,prima2-pinctrl";
+				reg = <0xb0120000 0x10000>;
+				interrupts = <43 44 45 46 47>;
+				gpio-controller;
+				interrupt-controller;
+
+				lcd_16pins_a: lcd0@0 {
+					lcd {
+						sirf,pins = "lcd_16bitsgrp";
+						sirf,function = "lcd_16bits";
+					};
+				};
+				lcd_18pins_a: lcd0@1 {
+					lcd {
+						sirf,pins = "lcd_18bitsgrp";
+						sirf,function = "lcd_18bits";
+					};
+				};
+				lcd_24pins_a: lcd0@2 {
+					lcd {
+						sirf,pins = "lcd_24bitsgrp";
+						sirf,function = "lcd_24bits";
+					};
+				};
+				lcdrom_pins_a: lcdrom0@0 {
+					lcd {
+						sirf,pins = "lcdromgrp";
+						sirf,function = "lcdrom";
+					};
+				};
+				uart0_pins_a: uart0@0 {
+					uart {
+						sirf,pins = "uart0grp";
+						sirf,function = "uart0";
+					};
+				};
+				uart1_pins_a: uart1@0 {
+					uart {
+						sirf,pins = "uart1grp";
+						sirf,function = "uart1";
+					};
+				};
+				uart2_pins_a: uart2@0 {
+					uart {
+						sirf,pins = "uart2grp";
+						sirf,function = "uart2";
+					};
+				};
+				uart2_noflow_pins_a: uart2@1 {
+					uart {
+						sirf,pins = "uart2_nostreamctrlgrp";
+						sirf,function = "uart2_nostreamctrl";
+					};
+				};
+				spi0_pins_a: spi0@0 {
+					spi {
+						sirf,pins = "spi0grp";
+						sirf,function = "spi0";
+					};
+				};
+				spi1_pins_a: spi1@0 {
+					spi {
+						sirf,pins = "spi1grp";
+						sirf,function = "spi1";
+					};
+				};
+				i2c0_pins_a: i2c0@0 {
+					i2c {
+						sirf,pins = "i2c0grp";
+						sirf,function = "i2c0";
+					};
+				};
+				i2c1_pins_a: i2c1@0 {
+					i2c {
+						sirf,pins = "i2c1grp";
+						sirf,function = "i2c1";
+					};
+				};
+                                pwm0_pins_a: pwm0@0 {
+                                        pwm {
+                                                sirf,pins = "pwm0grp";
+                                                sirf,function = "pwm0";
+                                        };
+                                };
+                                pwm1_pins_a: pwm1@0 {
+                                        pwm {
+                                                sirf,pins = "pwm1grp";
+                                                sirf,function = "pwm1";
+                                        };
+                                };
+                                pwm2_pins_a: pwm2@0 {
+                                        pwm {
+                                                sirf,pins = "pwm2grp";
+                                                sirf,function = "pwm2";
+                                        };
+                                };
+                                pwm3_pins_a: pwm3@0 {
+                                        pwm {
+                                                sirf,pins = "pwm3grp";
+                                                sirf,function = "pwm3";
+                                        };
+                                };
+                                gps_pins_a: gps@0 {
+                                        gps {
+                                                sirf,pins = "gpsgrp";
+                                                sirf,function = "gps";
+                                        };
+                                };
+                                vip_pins_a: vip@0 {
+                                        vip {
+                                                sirf,pins = "vipgrp";
+                                                sirf,function = "vip";
+                                        };
+                                };
+                                sdmmc0_pins_a: sdmmc0@0 {
+                                        sdmmc0 {
+                                                sirf,pins = "sdmmc0grp";
+                                                sirf,function = "sdmmc0";
+                                        };
+                                };
+                                sdmmc1_pins_a: sdmmc1@0 {
+                                        sdmmc1 {
+                                                sirf,pins = "sdmmc1grp";
+                                                sirf,function = "sdmmc1";
+                                        };
+                                };
+                                sdmmc2_pins_a: sdmmc2@0 {
+                                        sdmmc2 {
+                                                sirf,pins = "sdmmc2grp";
+                                                sirf,function = "sdmmc2";
+                                        };
+                                };
+                                sdmmc3_pins_a: sdmmc3@0 {
+                                        sdmmc3 {
+                                                sirf,pins = "sdmmc3grp";
+                                                sirf,function = "sdmmc3";
+                                        };
+                                };
+                                sdmmc4_pins_a: sdmmc4@0 {
+                                        sdmmc4 {
+                                                sirf,pins = "sdmmc4grp";
+                                                sirf,function = "sdmmc4";
+                                        };
+                                };
+                                sdmmc5_pins_a: sdmmc5@0 {
+                                        sdmmc5 {
+                                                sirf,pins = "sdmmc5grp";
+                                                sirf,function = "sdmmc5";
+                                        };
+                                };
+                                i2s_pins_a: i2s@0 {
+                                        i2s {
+                                                sirf,pins = "i2sgrp";
+                                                sirf,function = "i2s";
+                                        };
+                                };
+                                ac97_pins_a: ac97@0 {
+                                        ac97 {
+                                                sirf,pins = "ac97grp";
+                                                sirf,function = "ac97";
+                                        };
+                                };
+                                nand_pins_a: nand@0 {
+                                        nand {
+                                                sirf,pins = "nandgrp";
+                                                sirf,function = "nand";
+                                        };
+                                };
+                                usp0_pins_a: usp0@0 {
+                                        usp0 {
+                                                sirf,pins = "usp0grp";
+                                                sirf,function = "usp0";
+                                        };
+                                };
+                                usp1_pins_a: usp1@0 {
+                                        usp1 {
+                                                sirf,pins = "usp1grp";
+                                                sirf,function = "usp1";
+                                        };
+                                };
+                                usp2_pins_a: usp2@0 {
+                                        usp2 {
+                                                sirf,pins = "usp2grp";
+                                                sirf,function = "usp2";
+                                        };
+                                };
+                                usb0_utmi_drvbus_pins_a: usb0_utmi_drvbus@0 {
+                                        usb0_utmi_drvbus {
+                                                sirf,pins = "usb0_utmi_drvbusgrp";
+                                                sirf,function = "usb0_utmi_drvbus";
+                                        };
+                                };
+                                usb1_utmi_drvbus_pins_a: usb1_utmi_drvbus@0 {
+                                        usb1_utmi_drvbus {
+                                                sirf,pins = "usb1_utmi_drvbusgrp";
+                                                sirf,function = "usb1_utmi_drvbus";
+                                        };
+                                };
+                                warm_rst_pins_a: warm_rst@0 {
+                                        warm_rst {
+                                                sirf,pins = "warm_rstgrp";
+                                                sirf,function = "warm_rst";
+                                        };
+                                };
+                                pulse_count_pins_a: pulse_count@0 {
+                                        pulse_count {
+                                                sirf,pins = "pulse_countgrp";
+                                                sirf,function = "pulse_count";
+                                        };
+                                };
+                                cko0_rst_pins_a: cko0_rst@0 {
+                                        cko0_rst {
+                                                sirf,pins = "cko0_rstgrp";
+                                                sirf,function = "cko0_rst";
+                                        };
+                                };
+                                cko1_rst_pins_a: cko1_rst@0 {
+                                        cko1_rst {
+                                                sirf,pins = "cko1_rstgrp";
+                                                sirf,function = "cko1_rst";
+                                        };
+                                };
+			};
+
+			pwm@b0130000 {
+				compatible = "sirf,prima2-pwm";
+				reg = <0xb0130000 0x10000>;
+			};
+
+			efusesys@b0140000 {
+				compatible = "sirf,prima2-efuse";
+				reg = <0xb0140000 0x10000>;
+			};
+
+			pulsec@b0150000 {
+				compatible = "sirf,prima2-pulsec";
+				reg = <0xb0150000 0x10000>;
+				interrupts = <48>;
+			};
+
+			pci-iobg {
+				compatible = "sirf,prima2-pciiobg", "simple-bus";
+				#address-cells = <1>;
+				#size-cells = <1>;
+				ranges = <0x56000000 0x56000000 0x1b00000>;
+
+				sd0: sdhci@56000000 {
+					cell-index = <0>;
+					compatible = "sirf,prima2-sdhc";
+					reg = <0x56000000 0x100000>;
+					interrupts = <38>;
+				};
+
+				sd1: sdhci@56100000 {
+					cell-index = <1>;
+					compatible = "sirf,prima2-sdhc";
+					reg = <0x56100000 0x100000>;
+					interrupts = <38>;
+				};
+
+				sd2: sdhci@56200000 {
+					cell-index = <2>;
+					compatible = "sirf,prima2-sdhc";
+					reg = <0x56200000 0x100000>;
+					interrupts = <23>;
+				};
+
+				sd3: sdhci@56300000 {
+					cell-index = <3>;
+					compatible = "sirf,prima2-sdhc";
+					reg = <0x56300000 0x100000>;
+					interrupts = <23>;
+				};
+
+				sd4: sdhci@56400000 {
+					cell-index = <4>;
+					compatible = "sirf,prima2-sdhc";
+					reg = <0x56400000 0x100000>;
+					interrupts = <39>;
+				};
+
+				sd5: sdhci@56500000 {
+					cell-index = <5>;
+					compatible = "sirf,prima2-sdhc";
+					reg = <0x56500000 0x100000>;
+					interrupts = <39>;
+				};
+
+				pci-copy@57900000 {
+					compatible = "sirf,prima2-pcicp";
+					reg = <0x57900000 0x100000>;
+					interrupts = <40>;
+				};
+
+				rom-interface@57a00000 {
+					compatible = "sirf,prima2-romif";
+					reg = <0x57a00000 0x100000>;
+				};
+			};
+		};
+
+		rtc-iobg {
+			compatible = "sirf,prima2-rtciobg", "sirf-prima2-rtciobg-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0x80030000 0x10000>;
+
+			gpsrtc@1000 {
+				compatible = "sirf,prima2-gpsrtc";
+				reg = <0x1000 0x1000>;
+				interrupts = <55 56 57>;
+			};
+
+			sysrtc@2000 {
+				compatible = "sirf,prima2-sysrtc";
+				reg = <0x2000 0x1000>;
+				interrupts = <52 53 54>;
+			};
+
+			pwrc@3000 {
+				compatible = "sirf,prima2-pwrc";
+				reg = <0x3000 0x1000>;
+				interrupts = <32>;
+			};
+		};
+
+		uus-iobg {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0xb8000000 0xb8000000 0x40000>;
+
+			usb0: usb@b00e0000 {
+				compatible = "chipidea,ci13611a-prima2";
+				reg = <0xb8000000 0x10000>;
+				interrupts = <10>;
+			};
+
+			usb1: usb@b00f0000 {
+				compatible = "chipidea,ci13611a-prima2";
+				reg = <0xb8010000 0x10000>;
+				interrupts = <11>;
+			};
+
+			sata@b00f0000 {
+				compatible = "synopsys,dwc-ahsata";
+				reg = <0xb8020000 0x10000>;
+				interrupts = <37>;
+			};
+
+			security@b00f0000 {
+				compatible = "sirf,prima2-security";
+				reg = <0xb8030000 0x10000>;
+				interrupts = <42>;
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/pxa27x.dtsi b/arch/arm/boot/dts/pxa27x.dtsi
new file mode 100644
index 0000000..d7c5d72
--- /dev/null
+++ b/arch/arm/boot/dts/pxa27x.dtsi
@@ -0,0 +1,14 @@
+/* The pxa3xx skeleton simply augments the 2xx version */
+/include/ "pxa2xx.dtsi"
+
+/ {
+	model = "Marvell PXA27x familiy SoC";
+	compatible = "marvell,pxa27x";
+
+	pxabus {
+		pxairq: interrupt-controller@40d00000 {
+			marvell,intc-priority;
+			marvell,intc-nr-irqs = <34>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/pxa2xx.dtsi b/arch/arm/boot/dts/pxa2xx.dtsi
new file mode 100644
index 0000000..f18aad3
--- /dev/null
+++ b/arch/arm/boot/dts/pxa2xx.dtsi
@@ -0,0 +1,132 @@
+/*
+ * pxa2xx.dtsi - Device Tree Include file for Marvell PXA2xx family SoC
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+	model = "Marvell PXA2xx family SoC";
+	compatible = "marvell,pxa2xx";
+	interrupt-parent = <&pxairq>;
+
+	aliases {
+		serial0 = &ffuart;
+		serial1 = &btuart;
+		serial2 = &stuart;
+		serial3 = &hwuart;
+		i2c0 = &pwri2c;
+		i2c1 = &pxai2c1;
+	};
+
+	cpus {
+		cpu@0 {
+			compatible = "arm,xscale";
+		};
+	};
+
+	pxabus {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		pxairq: interrupt-controller@40d00000 {
+			#interrupt-cells = <1>;
+			compatible = "marvell,pxa-intc";
+			interrupt-controller;
+			interrupt-parent;
+			marvell,intc-nr-irqs = <32>;
+			reg = <0x40d00000 0xd0>;
+		};
+
+		gpio: gpio@40e00000 {
+			compatible = "mrvl,pxa-gpio";
+			#address-cells = <0x1>;
+			#size-cells = <0x1>;
+			reg = <0x40e00000 0x10000>;
+			gpio-controller;
+			#gpio-cells = <0x2>;
+			interrupts = <10>;
+			interrupt-names = "gpio_mux";
+			interrupt-controller;
+			#interrupt-cells = <0x2>;
+			ranges;
+
+			gcb0: gpio@40e00000 {
+				reg = <0x40e00000 0x4>;
+			};
+
+			gcb1: gpio@40e00004 {
+				reg = <0x40e00004 0x4>;
+			};
+
+			gcb2: gpio@40e00008 {
+				reg = <0x40e00008 0x4>;
+			};
+			gcb3: gpio@40e0000c {
+				reg = <0x40e0000c 0x4>;
+			};
+		};
+
+		ffuart: uart@40100000 {
+			compatible = "mrvl,pxa-uart";
+			reg = <0x40100000 0x30>;
+			interrupts = <22>;
+			status = "disabled";
+		};
+
+		btuart: uart@40200000 {
+			compatible = "mrvl,pxa-uart";
+			reg = <0x40200000 0x30>;
+			interrupts = <21>;
+			status = "disabled";
+		};
+
+		stuart: uart@40700000 {
+			compatible = "mrvl,pxa-uart";
+			reg = <0x40700000 0x30>;
+			interrupts = <20>;
+			status = "disabled";
+		};
+
+		hwuart: uart@41100000 {
+			compatible = "mrvl,pxa-uart";
+			reg = <0x41100000 0x30>;
+			interrupts = <7>;
+			status = "disabled";
+		};
+
+		pxai2c1: i2c@40301680 {
+			compatible = "mrvl,pxa-i2c";
+			reg = <0x40301680 0x30>;
+			interrupts = <18>;
+			#address-cells = <0x1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		usb0: ohci@4c000000 {
+			compatible = "mrvl,pxa-ohci";
+			reg = <0x4c000000 0x10000>;
+			interrupts = <3>;
+			status = "disabled";
+		};
+
+		mmc0: mmc@41100000 {
+			compatible = "mrvl,pxa-mmc";
+			reg = <0x41100000 0x1000>;
+			interrupts = <23>;
+			status = "disabled";
+		};
+
+		rtc@40900000 {
+			compatible = "marvell,pxa-rtc";
+			reg = <0x40900000 0x3c>;
+			interrupts = <30 31>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/pxa3xx.dtsi b/arch/arm/boot/dts/pxa3xx.dtsi
new file mode 100644
index 0000000..f9d92da
--- /dev/null
+++ b/arch/arm/boot/dts/pxa3xx.dtsi
@@ -0,0 +1,32 @@
+/* The pxa3xx skeleton simply augments the 2xx version */
+/include/ "pxa2xx.dtsi"
+
+/ {
+	model = "Marvell PXA3xx familiy SoC";
+	compatible = "marvell,pxa3xx";
+
+	pxabus {
+		pwri2c: i2c@40f500c0 {
+			compatible = "mrvl,pwri2c";
+			reg = <0x40f500c0 0x30>;
+			interrupts = <6>;
+			#address-cells = <0x1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		nand0: nand@43100000 {
+			compatible = "marvell,pxa3xx-nand";
+			reg = <0x43100000 90>;
+			interrupts = <45>;
+			#address-cells = <1>;
+			#size-cells = <1>;	
+			status = "disabled";
+		};
+
+		pxairq: interrupt-controller@40d00000 {
+			marvell,intc-priority;
+			marvell,intc-nr-irqs = <56>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/pxa910.dtsi b/arch/arm/boot/dts/pxa910.dtsi
index aebf32d..a3be44d8 100644
--- a/arch/arm/boot/dts/pxa910.dtsi
+++ b/arch/arm/boot/dts/pxa910.dtsi
@@ -25,6 +25,11 @@
 		interrupt-parent = <&intc>;
 		ranges;
 
+		L2: l2-cache {
+			compatible = "marvell,tauros2-cache";
+			marvell,tauros2-cache-features = <0x3>;
+		};
+
 		axi@d4200000 {	/* AXI */
 			compatible = "mrvl,axi-bus", "simple-bus";
 			#address-cells = <1>;
diff --git a/arch/arm/boot/dts/snowball.dts b/arch/arm/boot/dts/snowball.dts
index 7e334d4..702c0ba 100644
--- a/arch/arm/boot/dts/snowball.dts
+++ b/arch/arm/boot/dts/snowball.dts
@@ -10,7 +10,7 @@
  */
 
 /dts-v1/;
-/include/ "db8500.dtsi"
+/include/ "dbx5x0.dtsi"
 
 / {
 	model = "Calao Systems Snowball platform with device tree";
@@ -83,6 +83,22 @@
 	};
 
 	soc-u9500 {
+
+		sound {
+			compatible = "stericsson,snd-soc-mop500";
+
+			stericsson,cpu-dai = <&msp1 &msp3>;
+			stericsson,audio-codec = <&codec>;
+		};
+
+		msp1: msp@80124000 {
+			status = "okay";
+		};
+
+		msp3: msp@80125000 {
+			status = "okay";
+		};
+
 		external-bus@50000000 {
 			status = "okay";
 
@@ -111,7 +127,6 @@
 			mmc-cap-mmc-highspeed;
 			vmmc-supply = <&ab8500_ldo_aux3_reg>;
 
-			#gpio-cells = <1>;
 			cd-gpios  = <&gpio6 26 0x4>; // 218
 			cd-inverted;
 
diff --git a/arch/arm/boot/dts/tegra20-harmony.dts b/arch/arm/boot/dts/tegra20-harmony.dts
index f146dbf..c3ef1ad 100644
--- a/arch/arm/boot/dts/tegra20-harmony.dts
+++ b/arch/arm/boot/dts/tegra20-harmony.dts
@@ -275,6 +275,160 @@
 	i2c@7000d000 {
 		status = "okay";
 		clock-frequency = <400000>;
+
+		pmic: tps6586x@34 {
+			compatible = "ti,tps6586x";
+			reg = <0x34>;
+			interrupts = <0 86 0x4>;
+
+			ti,system-power-controller;
+
+			#gpio-cells = <2>;
+			gpio-controller;
+
+			sys-supply = <&vdd_5v0_reg>;
+			vin-sm0-supply = <&sys_reg>;
+			vin-sm1-supply = <&sys_reg>;
+			vin-sm2-supply = <&sys_reg>;
+			vinldo01-supply = <&sm2_reg>;
+			vinldo23-supply = <&sm2_reg>;
+			vinldo4-supply = <&sm2_reg>;
+			vinldo678-supply = <&sm2_reg>;
+			vinldo9-supply = <&sm2_reg>;
+
+			regulators {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				sys_reg: regulator@0 {
+					reg = <0>;
+					regulator-compatible = "sys";
+					regulator-name = "vdd_sys";
+					regulator-always-on;
+				};
+
+				regulator@1 {
+					reg = <1>;
+					regulator-compatible = "sm0";
+					regulator-name = "vdd_sm0,vdd_core";
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+					regulator-always-on;
+				};
+
+				regulator@2 {
+					reg = <2>;
+					regulator-compatible = "sm1";
+					regulator-name = "vdd_sm1,vdd_cpu";
+					regulator-min-microvolt = <1000000>;
+					regulator-max-microvolt = <1000000>;
+					regulator-always-on;
+				};
+
+				sm2_reg: regulator@3 {
+					reg = <3>;
+					regulator-compatible = "sm2";
+					regulator-name = "vdd_sm2,vin_ldo*";
+					regulator-min-microvolt = <3700000>;
+					regulator-max-microvolt = <3700000>;
+					regulator-always-on;
+				};
+
+				regulator@4 {
+					reg = <4>;
+					regulator-compatible = "ldo0";
+					regulator-name = "vdd_ldo0,vddio_pex_clk";
+					regulator-min-microvolt = <3300000>;
+					regulator-max-microvolt = <3300000>;
+				};
+
+				regulator@5 {
+					reg = <5>;
+					regulator-compatible = "ldo1";
+					regulator-name = "vdd_ldo1,avdd_pll*";
+					regulator-min-microvolt = <1100000>;
+					regulator-max-microvolt = <1100000>;
+					regulator-always-on;
+				};
+
+				regulator@6 {
+					reg = <6>;
+					regulator-compatible = "ldo2";
+					regulator-name = "vdd_ldo2,vdd_rtc";
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+				};
+
+				regulator@7 {
+					reg = <7>;
+					regulator-compatible = "ldo3";
+					regulator-name = "vdd_ldo3,avdd_usb*";
+					regulator-min-microvolt = <3300000>;
+					regulator-max-microvolt = <3300000>;
+					regulator-always-on;
+				};
+
+				regulator@8 {
+					reg = <8>;
+					regulator-compatible = "ldo4";
+					regulator-name = "vdd_ldo4,avdd_osc,vddio_sys";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+				};
+
+				regulator@9 {
+					reg = <9>;
+					regulator-compatible = "ldo5";
+					regulator-name = "vdd_ldo5,vcore_mmc";
+					regulator-min-microvolt = <2850000>;
+					regulator-max-microvolt = <2850000>;
+					regulator-always-on;
+				};
+
+				regulator@10 {
+					reg = <10>;
+					regulator-compatible = "ldo6";
+					regulator-name = "vdd_ldo6,avdd_vdac";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+				};
+
+				regulator@11 {
+					reg = <11>;
+					regulator-compatible = "ldo7";
+					regulator-name = "vdd_ldo7,avdd_hdmi";
+					regulator-min-microvolt = <3300000>;
+					regulator-max-microvolt = <3300000>;
+				};
+
+				regulator@12 {
+					reg = <12>;
+					regulator-compatible = "ldo8";
+					regulator-name = "vdd_ldo8,avdd_hdmi_pll";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+				};
+
+				regulator@13 {
+					reg = <13>;
+					regulator-compatible = "ldo9";
+					regulator-name = "vdd_ldo9,avdd_2v85,vdd_ddr_rx";
+					regulator-min-microvolt = <2850000>;
+					regulator-max-microvolt = <2850000>;
+					regulator-always-on;
+				};
+
+				regulator@14 {
+					reg = <14>;
+					regulator-compatible = "ldo_rtc";
+					regulator-name = "vdd_rtc_out,vdd_cell";
+					regulator-min-microvolt = <3300000>;
+					regulator-max-microvolt = <3300000>;
+					regulator-always-on;
+				};
+			};
+		};
 	};
 
 	pmc {
@@ -310,6 +464,72 @@
 		bus-width = <8>;
 	};
 
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		vdd_5v0_reg: regulator@0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "vdd_5v0";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			regulator-always-on;
+		};
+
+		regulator@1 {
+			compatible = "regulator-fixed";
+			reg = <1>;
+			regulator-name = "vdd_1v5";
+			regulator-min-microvolt = <1500000>;
+			regulator-max-microvolt = <1500000>;
+			gpio = <&pmic 0 0>;
+		};
+
+		regulator@2 {
+			compatible = "regulator-fixed";
+			reg = <2>;
+			regulator-name = "vdd_1v2";
+			regulator-min-microvolt = <1200000>;
+			regulator-max-microvolt = <1200000>;
+			gpio = <&pmic 1 0>;
+			enable-active-high;
+		};
+
+		regulator@3 {
+			compatible = "regulator-fixed";
+			reg = <3>;
+			regulator-name = "vdd_1v05";
+			regulator-min-microvolt = <1050000>;
+			regulator-max-microvolt = <1050000>;
+			gpio = <&pmic 2 0>;
+			enable-active-high;
+			/* Hack until board-harmony-pcie.c is removed */
+			status = "disabled";
+		};
+
+		regulator@4 {
+			compatible = "regulator-fixed";
+			reg = <4>;
+			regulator-name = "vdd_pnl";
+			regulator-min-microvolt = <2800000>;
+			regulator-max-microvolt = <2800000>;
+			gpio = <&gpio 22 0>; /* gpio PC6 */
+			enable-active-high;
+		};
+
+		regulator@5 {
+			compatible = "regulator-fixed";
+			reg = <5>;
+			regulator-name = "vdd_bl";
+			regulator-min-microvolt = <2800000>;
+			regulator-max-microvolt = <2800000>;
+			gpio = <&gpio 176 0>; /* gpio PW0 */
+			enable-active-high;
+		};
+	};
+
 	sound {
 		compatible = "nvidia,tegra-audio-wm8903-harmony",
 			     "nvidia,tegra-audio-wm8903";
diff --git a/arch/arm/boot/dts/tegra20-medcom-wide.dts b/arch/arm/boot/dts/tegra20-medcom-wide.dts
new file mode 100644
index 0000000..a2d6d65
--- /dev/null
+++ b/arch/arm/boot/dts/tegra20-medcom-wide.dts
@@ -0,0 +1,58 @@
+/dts-v1/;
+
+/include/ "tegra20-tamonten.dtsi"
+
+/ {
+	model = "Avionic Design Medcom-Wide board";
+	compatible = "ad,medcom-wide", "ad,tamonten", "nvidia,tegra20";
+
+	i2c@7000c000 {
+		wm8903: wm8903@1a {
+			compatible = "wlf,wm8903";
+			reg = <0x1a>;
+			interrupt-parent = <&gpio>;
+			interrupts = <187 0x04>;
+
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			micdet-cfg = <0>;
+			micdet-delay = <100>;
+			gpio-cfg = <0xffffffff
+				    0xffffffff
+				    0
+				    0xffffffff
+				    0xffffffff>;
+		};
+	};
+
+	backlight {
+		compatible = "pwm-backlight";
+		pwms = <&pwm 0 5000000>;
+
+		brightness-levels = <0 4 8 16 32 64 128 255>;
+		default-brightness-level = <6>;
+	};
+
+	sound {
+		compatible = "ad,tegra-audio-wm8903-medcom-wide",
+			     "nvidia,tegra-audio-wm8903";
+		nvidia,model = "Avionic Design Medcom-Wide";
+
+		nvidia,audio-routing =
+			"Headphone Jack", "HPOUTR",
+			"Headphone Jack", "HPOUTL",
+			"Int Spk", "ROP",
+			"Int Spk", "RON",
+			"Int Spk", "LOP",
+			"Int Spk", "LON",
+			"Mic Jack", "MICBIAS",
+			"IN1L", "Mic Jack";
+
+		nvidia,i2s-controller = <&tegra_i2s1>;
+		nvidia,audio-codec = <&wm8903>;
+
+		nvidia,spkr-en-gpios = <&wm8903 2 0>;
+		nvidia,hp-det-gpios = <&gpio 178 0>; /* gpio PW2 */
+	};
+};
diff --git a/arch/arm/boot/dts/tegra20-paz00.dts b/arch/arm/boot/dts/tegra20-paz00.dts
index 684a9e1..ddf287f 100644
--- a/arch/arm/boot/dts/tegra20-paz00.dts
+++ b/arch/arm/boot/dts/tegra20-paz00.dts
@@ -272,12 +272,170 @@
 		status = "okay";
 		clock-frequency = <400000>;
 
+		pmic: tps6586x@34 {
+			compatible = "ti,tps6586x";
+			reg = <0x34>;
+			interrupts = <0 86 0x4>;
+
+			#gpio-cells = <2>;
+			gpio-controller;
+
+			sys-supply = <&p5valw_reg>;
+			vin-sm0-supply = <&sys_reg>;
+			vin-sm1-supply = <&sys_reg>;
+			vin-sm2-supply = <&sys_reg>;
+			vinldo01-supply = <&sm2_reg>;
+			vinldo23-supply = <&sm2_reg>;
+			vinldo4-supply = <&sm2_reg>;
+			vinldo678-supply = <&sm2_reg>;
+			vinldo9-supply = <&sm2_reg>;
+
+			regulators {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				sys_reg: regulator@0 {
+					reg = <0>;
+					regulator-compatible = "sys";
+					regulator-name = "vdd_sys";
+					regulator-always-on;
+				};
+
+				regulator@1 {
+					reg = <1>;
+					regulator-compatible = "sm0";
+					regulator-name = "+1.2vs_sm0,vdd_core";
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+					regulator-always-on;
+				};
+
+				regulator@2 {
+					reg = <2>;
+					regulator-compatible = "sm1";
+					regulator-name = "+1.0vs_sm1,vdd_cpu";
+					regulator-min-microvolt = <1000000>;
+					regulator-max-microvolt = <1000000>;
+					regulator-always-on;
+				};
+
+				sm2_reg: regulator@3 {
+					reg = <3>;
+					regulator-compatible = "sm2";
+					regulator-name = "+3.7vs_sm2,vin_ldo*";
+					regulator-min-microvolt = <3700000>;
+					regulator-max-microvolt = <3700000>;
+					regulator-always-on;
+				};
+
+				/* LDO0 is not connected to anything */
+
+				regulator@5 {
+					reg = <5>;
+					regulator-compatible = "ldo1";
+					regulator-name = "+1.1vs_ldo1,avdd_pll*";
+					regulator-min-microvolt = <1100000>;
+					regulator-max-microvolt = <1100000>;
+					regulator-always-on;
+				};
+
+				regulator@6 {
+					reg = <6>;
+					regulator-compatible = "ldo2";
+					regulator-name = "+1.2vs_ldo2,vdd_rtc";
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+				};
+
+				regulator@7 {
+					reg = <7>;
+					regulator-compatible = "ldo3";
+					regulator-name = "+3.3vs_ldo3,avdd_usb*";
+					regulator-min-microvolt = <3300000>;
+					regulator-max-microvolt = <3300000>;
+					regulator-always-on;
+				};
+
+				regulator@8 {
+					reg = <8>;
+					regulator-compatible = "ldo4";
+					regulator-name = "+1.8vs_ldo4,avdd_osc,vddio_sys";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+				};
+
+				regulator@9 {
+					reg = <9>;
+					regulator-compatible = "ldo5";
+					regulator-name = "+2.85vs_ldo5,vcore_mmc";
+					regulator-min-microvolt = <2850000>;
+					regulator-max-microvolt = <2850000>;
+					regulator-always-on;
+				};
+
+				regulator@10 {
+					reg = <10>;
+					regulator-compatible = "ldo6";
+					/*
+					 * Research indicates this should be
+					 * 1.8v; other boards that use this
+					 * rail for the same purpose need it
+					 * set to 1.8v. The schematic signal
+					 * name is incorrect; perhaps copied
+					 * from an incorrect NVIDIA reference.
+					 */
+					regulator-name = "+2.85vs_ldo6,avdd_vdac";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+				};
+
+				regulator@11 {
+					reg = <11>;
+					regulator-compatible = "ldo7";
+					regulator-name = "+3.3vs_ldo7,avdd_hdmi";
+					regulator-min-microvolt = <3300000>;
+					regulator-max-microvolt = <3300000>;
+				};
+
+				regulator@12 {
+					reg = <12>;
+					regulator-compatible = "ldo8";
+					regulator-name = "+1.8vs_ldo8,avdd_hdmi_pll";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+				};
+
+				regulator@13 {
+					reg = <13>;
+					regulator-compatible = "ldo9";
+					regulator-name = "+2.85vs_ldo9,vdd_ddr_rx";
+					regulator-min-microvolt = <2850000>;
+					regulator-max-microvolt = <2850000>;
+					regulator-always-on;
+				};
+
+				regulator@14 {
+					reg = <14>;
+					regulator-compatible = "ldo_rtc";
+					regulator-name = "+3.3vs_rtc";
+					regulator-min-microvolt = <3300000>;
+					regulator-max-microvolt = <3300000>;
+					regulator-always-on;
+				};
+			};
+		};
+
 		adt7461@4c {
 			compatible = "adi,adt7461";
 			reg = <0x4c>;
 		};
 	};
 
+	pmc {
+		nvidia,invert-interrupt;
+	};
+
 	usb@c5000000 {
 		status = "okay";
 	};
@@ -325,6 +483,21 @@
 		};
 	};
 
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		p5valw_reg: regulator@0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "+5valw";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			regulator-always-on;
+		};
+	};
+
 	sound {
 		compatible = "nvidia,tegra-audio-alc5632-paz00",
 			"nvidia,tegra-audio-alc5632";
diff --git a/arch/arm/boot/dts/tegra20-plutux.dts b/arch/arm/boot/dts/tegra20-plutux.dts
new file mode 100644
index 0000000..331a3ef
--- /dev/null
+++ b/arch/arm/boot/dts/tegra20-plutux.dts
@@ -0,0 +1,50 @@
+/dts-v1/;
+
+/include/ "tegra20-tamonten.dtsi"
+
+/ {
+	model = "Avionic Design Plutux board";
+	compatible = "ad,plutux", "ad,tamonten", "nvidia,tegra20";
+
+	i2c@7000c000 {
+		wm8903: wm8903@1a {
+			compatible = "wlf,wm8903";
+			reg = <0x1a>;
+			interrupt-parent = <&gpio>;
+			interrupts = <187 0x04>;
+
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			micdet-cfg = <0>;
+			micdet-delay = <100>;
+			gpio-cfg = <0xffffffff
+				    0xffffffff
+				    0
+				    0xffffffff
+				    0xffffffff>;
+		};
+	};
+
+	sound {
+		compatible = "ad,tegra-audio-plutux",
+			     "nvidia,tegra-audio-wm8903";
+		nvidia,model = "Avionic Design Plutux";
+
+		nvidia,audio-routing =
+			"Headphone Jack", "HPOUTR",
+			"Headphone Jack", "HPOUTL",
+			"Int Spk", "ROP",
+			"Int Spk", "RON",
+			"Int Spk", "LOP",
+			"Int Spk", "LON",
+			"Mic Jack", "MICBIAS",
+			"IN1L", "Mic Jack";
+
+		nvidia,i2s-controller = <&tegra_i2s1>;
+		nvidia,audio-codec = <&wm8903>;
+
+		nvidia,spkr-en-gpios = <&wm8903 2 0>;
+		nvidia,hp-det-gpios = <&gpio 178 0>; /* gpio PW2 */
+	};
+};
diff --git a/arch/arm/boot/dts/tegra20-seaboard.dts b/arch/arm/boot/dts/tegra20-seaboard.dts
index 85e621a..e60dc71 100644
--- a/arch/arm/boot/dts/tegra20-seaboard.dts
+++ b/arch/arm/boot/dts/tegra20-seaboard.dts
@@ -374,6 +374,154 @@
 		status = "okay";
 		clock-frequency = <400000>;
 
+		pmic: tps6586x@34 {
+			compatible = "ti,tps6586x";
+			reg = <0x34>;
+			interrupts = <0 86 0x4>;
+
+			ti,system-power-controller;
+
+			#gpio-cells = <2>;
+			gpio-controller;
+
+			sys-supply = <&vdd_5v0_reg>;
+			vin-sm0-supply = <&sys_reg>;
+			vin-sm1-supply = <&sys_reg>;
+			vin-sm2-supply = <&sys_reg>;
+			vinldo01-supply = <&sm2_reg>;
+			vinldo23-supply = <&sm2_reg>;
+			vinldo4-supply = <&sm2_reg>;
+			vinldo678-supply = <&sm2_reg>;
+			vinldo9-supply = <&sm2_reg>;
+
+			regulators {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				sys_reg: regulator@0 {
+					reg = <0>;
+					regulator-compatible = "sys";
+					regulator-name = "vdd_sys";
+					regulator-always-on;
+				};
+
+				regulator@1 {
+					reg = <1>;
+					regulator-compatible = "sm0";
+					regulator-name = "vdd_sm0,vdd_core";
+					regulator-min-microvolt = <1300000>;
+					regulator-max-microvolt = <1300000>;
+					regulator-always-on;
+				};
+
+				regulator@2 {
+					reg = <2>;
+					regulator-compatible = "sm1";
+					regulator-name = "vdd_sm1,vdd_cpu";
+					regulator-min-microvolt = <1125000>;
+					regulator-max-microvolt = <1125000>;
+					regulator-always-on;
+				};
+
+				sm2_reg: regulator@3 {
+					reg = <3>;
+					regulator-compatible = "sm2";
+					regulator-name = "vdd_sm2,vin_ldo*";
+					regulator-min-microvolt = <3700000>;
+					regulator-max-microvolt = <3700000>;
+					regulator-always-on;
+				};
+
+				/* LDO0 is not connected to anything */
+
+				regulator@5 {
+					reg = <5>;
+					regulator-compatible = "ldo1";
+					regulator-name = "vdd_ldo1,avdd_pll*";
+					regulator-min-microvolt = <1100000>;
+					regulator-max-microvolt = <1100000>;
+					regulator-always-on;
+				};
+
+				regulator@6 {
+					reg = <6>;
+					regulator-compatible = "ldo2";
+					regulator-name = "vdd_ldo2,vdd_rtc";
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+				};
+
+				regulator@7 {
+					reg = <7>;
+					regulator-compatible = "ldo3";
+					regulator-name = "vdd_ldo3,avdd_usb*";
+					regulator-min-microvolt = <3300000>;
+					regulator-max-microvolt = <3300000>;
+					regulator-always-on;
+				};
+
+				regulator@8 {
+					reg = <8>;
+					regulator-compatible = "ldo4";
+					regulator-name = "vdd_ldo4,avdd_osc,vddio_sys";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+				};
+
+				regulator@9 {
+					reg = <9>;
+					regulator-compatible = "ldo5";
+					regulator-name = "vdd_ldo5,vcore_mmc";
+					regulator-min-microvolt = <2850000>;
+					regulator-max-microvolt = <2850000>;
+					regulator-always-on;
+				};
+
+				regulator@10 {
+					reg = <10>;
+					regulator-compatible = "ldo6";
+					regulator-name = "vdd_ldo6,avdd_vdac,vddio_vi,vddio_cam";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+				};
+
+				regulator@11 {
+					reg = <11>;
+					regulator-compatible = "ldo7";
+					regulator-name = "vdd_ldo7,avdd_hdmi,vdd_fuse";
+					regulator-min-microvolt = <3300000>;
+					regulator-max-microvolt = <3300000>;
+				};
+
+				regulator@12 {
+					reg = <12>;
+					regulator-compatible = "ldo8";
+					regulator-name = "vdd_ldo8,avdd_hdmi_pll";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+				};
+
+				regulator@13 {
+					reg = <13>;
+					regulator-compatible = "ldo9";
+					regulator-name = "vdd_ldo9,avdd_2v85,vdd_ddr_rx";
+					regulator-min-microvolt = <2850000>;
+					regulator-max-microvolt = <2850000>;
+					regulator-always-on;
+				};
+
+				regulator@14 {
+					reg = <14>;
+					regulator-compatible = "ldo_rtc";
+					regulator-name = "vdd_rtc_out,vdd_cell";
+					regulator-min-microvolt = <3300000>;
+					regulator-max-microvolt = <3300000>;
+					regulator-always-on;
+				};
+			};
+		};
+
 		temperature-sensor@4c {
 			compatible = "nct1008";
 			reg = <0x4c>;
@@ -387,6 +535,10 @@
 		};
 	};
 
+	pmc {
+		nvidia,invert-interrupt;
+	};
+
 	memory-controller@0x7000f400 {
 		emc-table@190000 {
 			reg = <190000>;
@@ -473,6 +625,40 @@
 		};
 	};
 
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		vdd_5v0_reg: regulator@0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "vdd_5v0";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			regulator-always-on;
+		};
+
+		regulator@1 {
+			compatible = "regulator-fixed";
+			reg = <1>;
+			regulator-name = "vdd_1v5";
+			regulator-min-microvolt = <1500000>;
+			regulator-max-microvolt = <1500000>;
+			gpio = <&pmic 0 0>;
+		};
+
+		regulator@2 {
+			compatible = "regulator-fixed";
+			reg = <2>;
+			regulator-name = "vdd_1v2";
+			regulator-min-microvolt = <1200000>;
+			regulator-max-microvolt = <1200000>;
+			gpio = <&pmic 1 0>;
+			enable-active-high;
+		};
+	};
+
 	sound {
 		compatible = "nvidia,tegra-audio-wm8903-seaboard",
 			     "nvidia,tegra-audio-wm8903";
diff --git a/arch/arm/boot/dts/tegra20-tamonten.dtsi b/arch/arm/boot/dts/tegra20-tamonten.dtsi
new file mode 100644
index 0000000..f18cec9
--- /dev/null
+++ b/arch/arm/boot/dts/tegra20-tamonten.dtsi
@@ -0,0 +1,449 @@
+/include/ "tegra20.dtsi"
+
+/ {
+	model = "Avionic Design Tamonten SOM";
+	compatible = "ad,tamonten", "nvidia,tegra20";
+
+	memory {
+		reg = <0x00000000 0x20000000>;
+	};
+
+	pinmux {
+		pinctrl-names = "default";
+		pinctrl-0 = <&state_default>;
+
+		state_default: pinmux {
+			ata {
+				nvidia,pins = "ata";
+				nvidia,function = "ide";
+			};
+			atb {
+				nvidia,pins = "atb", "gma", "gme";
+				nvidia,function = "sdio4";
+			};
+			atc {
+				nvidia,pins = "atc";
+				nvidia,function = "nand";
+			};
+			atd {
+				nvidia,pins = "atd", "ate", "gmb", "gmd", "gpu",
+					"spia", "spib", "spic";
+				nvidia,function = "gmi";
+			};
+			cdev1 {
+				nvidia,pins = "cdev1";
+				nvidia,function = "plla_out";
+			};
+			cdev2 {
+				nvidia,pins = "cdev2";
+				nvidia,function = "pllp_out4";
+			};
+			crtp {
+				nvidia,pins = "crtp";
+				nvidia,function = "crt";
+			};
+			csus {
+				nvidia,pins = "csus";
+				nvidia,function = "vi_sensor_clk";
+			};
+			dap1 {
+				nvidia,pins = "dap1";
+				nvidia,function = "dap1";
+			};
+			dap2 {
+				nvidia,pins = "dap2";
+				nvidia,function = "dap2";
+			};
+			dap3 {
+				nvidia,pins = "dap3";
+				nvidia,function = "dap3";
+			};
+			dap4 {
+				nvidia,pins = "dap4";
+				nvidia,function = "dap4";
+			};
+			ddc {
+				nvidia,pins = "ddc";
+				nvidia,function = "i2c2";
+			};
+			dta {
+				nvidia,pins = "dta", "dtd";
+				nvidia,function = "sdio2";
+			};
+			dtb {
+				nvidia,pins = "dtb", "dtc", "dte";
+				nvidia,function = "rsvd1";
+			};
+			dtf {
+				nvidia,pins = "dtf";
+				nvidia,function = "i2c3";
+			};
+			gmc {
+				nvidia,pins = "gmc";
+				nvidia,function = "uartd";
+			};
+			gpu7 {
+				nvidia,pins = "gpu7";
+				nvidia,function = "rtck";
+			};
+			gpv {
+				nvidia,pins = "gpv", "slxa", "slxk";
+				nvidia,function = "pcie";
+			};
+			hdint {
+				nvidia,pins = "hdint", "pta";
+				nvidia,function = "hdmi";
+			};
+			i2cp {
+				nvidia,pins = "i2cp";
+				nvidia,function = "i2cp";
+			};
+			irrx {
+				nvidia,pins = "irrx", "irtx";
+				nvidia,function = "uarta";
+			};
+			kbca {
+				nvidia,pins = "kbca", "kbcb", "kbcc", "kbcd",
+					"kbce", "kbcf";
+				nvidia,function = "kbc";
+			};
+			lcsn {
+				nvidia,pins = "lcsn", "ld0", "ld1", "ld2",
+					"ld3", "ld4", "ld5", "ld6", "ld7",
+					"ld8", "ld9", "ld10", "ld11", "ld12",
+					"ld13", "ld14", "ld15", "ld16", "ld17",
+					"ldc", "ldi", "lhp0", "lhp1", "lhp2",
+					"lhs", "lm0", "lm1", "lpp", "lpw0",
+					"lpw1", "lpw2", "lsc0", "lsc1", "lsck",
+					"lsda", "lsdi", "lspi", "lvp0", "lvp1",
+					"lvs";
+				nvidia,function = "displaya";
+			};
+			owc {
+				nvidia,pins = "owc", "spdi", "spdo", "uac";
+				nvidia,function = "rsvd2";
+			};
+			pmc {
+				nvidia,pins = "pmc";
+				nvidia,function = "pwr_on";
+			};
+			rm {
+				nvidia,pins = "rm";
+				nvidia,function = "i2c1";
+			};
+			sdb {
+				nvidia,pins = "sdb", "sdc", "sdd";
+				nvidia,function = "pwm";
+			};
+			sdio1 {
+				nvidia,pins = "sdio1";
+				nvidia,function = "sdio1";
+			};
+			slxc {
+				nvidia,pins = "slxc", "slxd";
+				nvidia,function = "spdif";
+			};
+			spid {
+				nvidia,pins = "spid", "spie", "spif";
+				nvidia,function = "spi1";
+			};
+			spig {
+				nvidia,pins = "spig", "spih";
+				nvidia,function = "spi2_alt";
+			};
+			uaa {
+				nvidia,pins = "uaa", "uab", "uda";
+				nvidia,function = "ulpi";
+			};
+			uad {
+				nvidia,pins = "uad";
+				nvidia,function = "irda";
+			};
+			uca {
+				nvidia,pins = "uca", "ucb";
+				nvidia,function = "uartc";
+			};
+			conf_ata {
+				nvidia,pins = "ata", "atb", "atc", "atd", "ate",
+					"cdev1", "cdev2", "dap1", "dtb", "gma",
+					"gmb", "gmc", "gmd", "gme", "gpu7",
+					"gpv", "i2cp", "pta", "rm", "slxa",
+					"slxk", "spia", "spib", "uac";
+				nvidia,pull = <0>;
+				nvidia,tristate = <0>;
+			};
+			conf_ck32 {
+				nvidia,pins = "ck32", "ddrc", "pmca", "pmcb",
+					"pmcc", "pmcd", "pmce", "xm2c", "xm2d";
+				nvidia,pull = <0>;
+			};
+			conf_csus {
+				nvidia,pins = "csus", "spid", "spif";
+				nvidia,pull = <1>;
+				nvidia,tristate = <1>;
+			};
+			conf_crtp {
+				nvidia,pins = "crtp", "dap2", "dap3", "dap4",
+					"dtc", "dte", "dtf", "gpu", "sdio1",
+					"slxc", "slxd", "spdi", "spdo", "spig",
+					"uda";
+				nvidia,pull = <0>;
+				nvidia,tristate = <1>;
+			};
+			conf_ddc {
+				nvidia,pins = "ddc", "dta", "dtd", "kbca",
+					"kbcb", "kbcc", "kbcd", "kbce", "kbcf",
+					"sdc";
+				nvidia,pull = <2>;
+				nvidia,tristate = <0>;
+			};
+			conf_hdint {
+				nvidia,pins = "hdint", "lcsn", "ldc", "lm1",
+					"lpw1", "lsc1", "lsck", "lsda", "lsdi",
+					"lvp0", "owc", "sdb";
+				nvidia,tristate = <1>;
+			};
+			conf_irrx {
+				nvidia,pins = "irrx", "irtx", "sdd", "spic",
+					"spie", "spih", "uaa", "uab", "uad",
+					"uca", "ucb";
+				nvidia,pull = <2>;
+				nvidia,tristate = <1>;
+			};
+			conf_lc {
+				nvidia,pins = "lc", "ls";
+				nvidia,pull = <2>;
+			};
+			conf_ld0 {
+				nvidia,pins = "ld0", "ld1", "ld2", "ld3", "ld4",
+					"ld5", "ld6", "ld7", "ld8", "ld9",
+					"ld10", "ld11", "ld12", "ld13", "ld14",
+					"ld15", "ld16", "ld17", "ldi", "lhp0",
+					"lhp1", "lhp2", "lhs", "lm0", "lpp",
+					"lpw0", "lpw2", "lsc0", "lspi", "lvp1",
+					"lvs", "pmc";
+				nvidia,tristate = <0>;
+			};
+			conf_ld17_0 {
+				nvidia,pins = "ld17_0", "ld19_18", "ld21_20",
+					"ld23_22";
+				nvidia,pull = <1>;
+			};
+		};
+	};
+
+	i2s@70002800 {
+		status = "okay";
+	};
+
+	serial@70006300 {
+		clock-frequency = <216000000>;
+		status = "okay";
+	};
+
+	i2c@7000c000 {
+		clock-frequency = <400000>;
+		status = "okay";
+	};
+
+	i2c@7000d000 {
+		clock-frequency = <400000>;
+		status = "okay";
+
+		pmic: tps6586x@34 {
+			compatible = "ti,tps6586x";
+			reg = <0x34>;
+			interrupts = <0 86 0x4>;
+
+			ti,system-power-controller;
+
+			#gpio-cells = <2>;
+			gpio-controller;
+
+			sys-supply = <&vdd_5v0_reg>;
+			vin-sm0-supply = <&sys_reg>;
+			vin-sm1-supply = <&sys_reg>;
+			vin-sm2-supply = <&sys_reg>;
+			vinldo01-supply = <&sm2_reg>;
+			vinldo23-supply = <&sm2_reg>;
+			vinldo4-supply = <&sm2_reg>;
+			vinldo678-supply = <&sm2_reg>;
+			vinldo9-supply = <&sm2_reg>;
+
+			regulators {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				sys_reg: regulator@0 {
+					reg = <0>;
+					regulator-compatible = "sys";
+					regulator-name = "vdd_sys";
+					regulator-always-on;
+				};
+
+				regulator@1 {
+					reg = <1>;
+					regulator-compatible = "sm0";
+					regulator-name = "vdd_sys_sm0,vdd_core";
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+					regulator-always-on;
+				};
+
+				regulator@2 {
+					reg = <2>;
+					regulator-compatible = "sm1";
+					regulator-name = "vdd_sys_sm1,vdd_cpu";
+					regulator-min-microvolt = <1000000>;
+					regulator-max-microvolt = <1000000>;
+					regulator-always-on;
+				};
+
+				sm2_reg: regulator@3 {
+					reg = <3>;
+					regulator-compatible = "sm2";
+					regulator-name = "vdd_sys_sm2,vin_ldo*";
+					regulator-min-microvolt = <3700000>;
+					regulator-max-microvolt = <3700000>;
+					regulator-always-on;
+				};
+
+				regulator@4 {
+					reg = <4>;
+					regulator-compatible = "ldo0";
+					regulator-name = "vdd_ldo0,vddio_pex_clk";
+					regulator-min-microvolt = <3300000>;
+					regulator-max-microvolt = <3300000>;
+				};
+
+				regulator@5 {
+					reg = <5>;
+					regulator-compatible = "ldo1";
+					regulator-name = "vdd_ldo1,avdd_pll*";
+					regulator-min-microvolt = <1100000>;
+					regulator-max-microvolt = <1100000>;
+					regulator-always-on;
+				};
+
+				regulator@6 {
+					reg = <6>;
+					regulator-compatible = "ldo2";
+					regulator-name = "vdd_ldo2,vdd_rtc";
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+				};
+
+				regulator@7 {
+					reg = <7>;
+					regulator-compatible = "ldo3";
+					regulator-name = "vdd_ldo3,avdd_usb*";
+					regulator-min-microvolt = <3300000>;
+					regulator-max-microvolt = <3300000>;
+					regulator-always-on;
+				};
+
+				regulator@8 {
+					reg = <8>;
+					regulator-compatible = "ldo4";
+					regulator-name = "vdd_ldo4,avdd_osc,vddio_sys";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+				};
+
+				regulator@9 {
+					reg = <9>;
+					regulator-compatible = "ldo5";
+					regulator-name = "vdd_ldo5,vcore_mmc";
+					regulator-min-microvolt = <2850000>;
+					regulator-max-microvolt = <2850000>;
+				};
+
+				regulator@10 {
+					reg = <10>;
+					regulator-compatible = "ldo6";
+					regulator-name = "vdd_ldo6,avdd_vdac";
+					/*
+					 * According to the Tegra 2 Automotive
+					 * DataSheet, a typical value for this
+					 * would be 2.8V, but the PMIC only
+					 * supports 2.85V.
+					 */
+					regulator-min-microvolt = <2850000>;
+					regulator-max-microvolt = <2850000>;
+				};
+
+				regulator@11 {
+					reg = <11>;
+					regulator-compatible = "ldo7";
+					regulator-name = "vdd_ldo7,avdd_hdmi";
+					regulator-min-microvolt = <3300000>;
+					regulator-max-microvolt = <3300000>;
+				};
+
+				regulator@12 {
+					reg = <12>;
+					regulator-compatible = "ldo8";
+					regulator-name = "vdd_ldo8,avdd_hdmi_pll";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+				};
+
+				regulator@13 {
+					reg = <13>;
+					regulator-compatible = "ldo9";
+					regulator-name = "vdd_ldo9,vdd_ddr_rx,avdd_cam";
+					/*
+					 * According to the Tegra 2 Automotive
+					 * DataSheet, a typical value for this
+					 * would be 2.8V, but the PMIC only
+					 * supports 2.85V.
+					 */
+					regulator-min-microvolt = <2850000>;
+					regulator-max-microvolt = <2850000>;
+					regulator-always-on;
+				};
+
+				regulator@14 {
+					reg = <14>;
+					regulator-compatible = "ldo_rtc";
+					regulator-name = "vdd_rtc_out";
+					regulator-min-microvolt = <3300000>;
+					regulator-max-microvolt = <3300000>;
+					regulator-always-on;
+				};
+			};
+		};
+	};
+
+	pmc {
+		nvidia,invert-interrupt;
+	};
+
+	usb@c5008000 {
+		status = "okay";
+	};
+
+	sdhci@c8000600 {
+		cd-gpios = <&gpio 58 0>; /* gpio PH2 */
+		wp-gpios = <&gpio 59 0>; /* gpio PH3 */
+		bus-width = <4>;
+		status = "okay";
+	};
+
+	regulators {
+		compatible = "simple-bus";
+
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		vdd_5v0_reg: regulator@0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "vdd_5v0";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			regulator-always-on;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/tegra20-tec.dts b/arch/arm/boot/dts/tegra20-tec.dts
new file mode 100644
index 0000000..9aff31b
--- /dev/null
+++ b/arch/arm/boot/dts/tegra20-tec.dts
@@ -0,0 +1,53 @@
+/dts-v1/;
+
+/include/ "tegra20-tamonten.dtsi"
+
+/ {
+	model = "Avionic Design Tamonten Evaluation Carrier";
+	compatible = "ad,tec", "ad,tamonten", "nvidia,tegra20";
+
+	i2c@7000c000 {
+		clock-frequency = <400000>;
+		status = "okay";
+
+		wm8903: wm8903@1a {
+			compatible = "wlf,wm8903";
+			reg = <0x1a>;
+			interrupt-parent = <&gpio>;
+			interrupts = <187 0x04>;
+
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			micdet-cfg = <0>;
+			micdet-delay = <100>;
+			gpio-cfg = <0xffffffff
+				    0xffffffff
+				    0
+				    0xffffffff
+				    0xffffffff>;
+		};
+	};
+
+	sound {
+		compatible = "ad,tegra-audio-wm8903-tec",
+			     "nvidia,tegra-audio-wm8903";
+		nvidia,model = "Avionic Design TEC";
+
+		nvidia,audio-routing =
+			"Headphone Jack", "HPOUTR",
+			"Headphone Jack", "HPOUTL",
+			"Int Spk", "ROP",
+			"Int Spk", "RON",
+			"Int Spk", "LOP",
+			"Int Spk", "LON",
+			"Mic Jack", "MICBIAS",
+			"IN1L", "Mic Jack";
+
+		nvidia,i2s-controller = <&tegra_i2s1>;
+		nvidia,audio-codec = <&wm8903>;
+
+		nvidia,spkr-en-gpios = <&wm8903 2 0>;
+		nvidia,hp-det-gpios = <&gpio 178 0>; /* gpio PW2 */
+	};
+};
diff --git a/arch/arm/boot/dts/tegra20-ventana.dts b/arch/arm/boot/dts/tegra20-ventana.dts
index be90544..3e5952f 100644
--- a/arch/arm/boot/dts/tegra20-ventana.dts
+++ b/arch/arm/boot/dts/tegra20-ventana.dts
@@ -289,6 +289,158 @@
 	i2c@7000d000 {
 		status = "okay";
 		clock-frequency = <400000>;
+
+		pmic: tps6586x@34 {
+			compatible = "ti,tps6586x";
+			reg = <0x34>;
+			interrupts = <0 86 0x4>;
+
+			ti,system-power-controller;
+
+			#gpio-cells = <2>;
+			gpio-controller;
+
+			sys-supply = <&vdd_5v0_reg>;
+			vin-sm0-supply = <&sys_reg>;
+			vin-sm1-supply = <&sys_reg>;
+			vin-sm2-supply = <&sys_reg>;
+			vinldo01-supply = <&sm2_reg>;
+			vinldo23-supply = <&sm2_reg>;
+			vinldo4-supply = <&sm2_reg>;
+			vinldo678-supply = <&sm2_reg>;
+			vinldo9-supply = <&sm2_reg>;
+
+			regulators {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				sys_reg: regulator@0 {
+					reg = <0>;
+					regulator-compatible = "sys";
+					regulator-name = "vdd_sys";
+					regulator-always-on;
+				};
+
+				regulator@1 {
+					reg = <1>;
+					regulator-compatible = "sm0";
+					regulator-name = "vdd_sm0,vdd_core";
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+					regulator-always-on;
+				};
+
+				regulator@2 {
+					reg = <2>;
+					regulator-compatible = "sm1";
+					regulator-name = "vdd_sm1,vdd_cpu";
+					regulator-min-microvolt = <1000000>;
+					regulator-max-microvolt = <1000000>;
+					regulator-always-on;
+				};
+
+				sm2_reg: regulator@3 {
+					reg = <3>;
+					regulator-compatible = "sm2";
+					regulator-name = "vdd_sm2,vin_ldo*";
+					regulator-min-microvolt = <3700000>;
+					regulator-max-microvolt = <3700000>;
+					regulator-always-on;
+				};
+
+				/* LDO0 is not connected to anything */
+
+				regulator@5 {
+					reg = <5>;
+					regulator-compatible = "ldo1";
+					regulator-name = "vdd_ldo1,avdd_pll*";
+					regulator-min-microvolt = <1100000>;
+					regulator-max-microvolt = <1100000>;
+					regulator-always-on;
+				};
+
+				regulator@6 {
+					reg = <6>;
+					regulator-compatible = "ldo2";
+					regulator-name = "vdd_ldo2,vdd_rtc";
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+				};
+
+				regulator@7 {
+					reg = <7>;
+					regulator-compatible = "ldo3";
+					regulator-name = "vdd_ldo3,avdd_usb*";
+					regulator-min-microvolt = <3300000>;
+					regulator-max-microvolt = <3300000>;
+					regulator-always-on;
+				};
+
+				regulator@8 {
+					reg = <8>;
+					regulator-compatible = "ldo4";
+					regulator-name = "vdd_ldo4,avdd_osc,vddio_sys";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+				};
+
+				regulator@9 {
+					reg = <9>;
+					regulator-compatible = "ldo5";
+					regulator-name = "vdd_ldo5,vcore_mmc";
+					regulator-min-microvolt = <2850000>;
+					regulator-max-microvolt = <2850000>;
+					regulator-always-on;
+				};
+
+				regulator@10 {
+					reg = <10>;
+					regulator-compatible = "ldo6";
+					regulator-name = "vdd_ldo6,avdd_vdac";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+				};
+
+				regulator@11 {
+					reg = <11>;
+					regulator-compatible = "ldo7";
+					regulator-name = "vdd_ldo7,avdd_hdmi,vdd_fuse";
+					regulator-min-microvolt = <3300000>;
+					regulator-max-microvolt = <3300000>;
+				};
+
+				regulator@12 {
+					reg = <12>;
+					regulator-compatible = "ldo8";
+					regulator-name = "vdd_ldo8,avdd_hdmi_pll";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+				};
+
+				regulator@13 {
+					reg = <13>;
+					regulator-compatible = "ldo9";
+					regulator-name = "vdd_ldo9,avdd_2v85,vdd_ddr_rx";
+					regulator-min-microvolt = <2850000>;
+					regulator-max-microvolt = <2850000>;
+					regulator-always-on;
+				};
+
+				regulator@14 {
+					reg = <14>;
+					regulator-compatible = "ldo_rtc";
+					regulator-name = "vdd_rtc_out,vdd_cell";
+					regulator-min-microvolt = <3300000>;
+					regulator-max-microvolt = <3300000>;
+					regulator-always-on;
+				};
+			};
+		};
+	};
+
+	pmc {
+		nvidia,invert-interrupt;
 	};
 
 	usb@c5000000 {
@@ -317,6 +469,60 @@
 		bus-width = <8>;
 	};
 
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		vdd_5v0_reg: regulator@0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "vdd_5v0";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			regulator-always-on;
+		};
+
+		regulator@1 {
+			compatible = "regulator-fixed";
+			reg = <1>;
+			regulator-name = "vdd_1v5";
+			regulator-min-microvolt = <1500000>;
+			regulator-max-microvolt = <1500000>;
+			gpio = <&pmic 0 0>;
+		};
+
+		regulator@2 {
+			compatible = "regulator-fixed";
+			reg = <2>;
+			regulator-name = "vdd_1v2";
+			regulator-min-microvolt = <1200000>;
+			regulator-max-microvolt = <1200000>;
+			gpio = <&pmic 1 0>;
+			enable-active-high;
+		};
+
+		regulator@3 {
+			compatible = "regulator-fixed";
+			reg = <3>;
+			regulator-name = "vdd_pnl";
+			regulator-min-microvolt = <2800000>;
+			regulator-max-microvolt = <2800000>;
+			gpio = <&gpio 22 0>; /* gpio PC6 */
+			enable-active-high;
+		};
+
+		regulator@4 {
+			compatible = "regulator-fixed";
+			reg = <4>;
+			regulator-name = "vdd_bl";
+			regulator-min-microvolt = <2800000>;
+			regulator-max-microvolt = <2800000>;
+			gpio = <&gpio 176 0>; /* gpio PW0 */
+			enable-active-high;
+		};
+	};
+
 	sound {
 		compatible = "nvidia,tegra-audio-wm8903-ventana",
 			     "nvidia,tegra-audio-wm8903";
diff --git a/arch/arm/boot/dts/tegra20-whistler.dts b/arch/arm/boot/dts/tegra20-whistler.dts
index 6916310..c636d00 100644
--- a/arch/arm/boot/dts/tegra20-whistler.dts
+++ b/arch/arm/boot/dts/tegra20-whistler.dts
@@ -261,6 +261,286 @@
 			gpio-controller;
 			#gpio-cells = <2>;
 		};
+
+		max8907@3c {
+			compatible = "maxim,max8907";
+			reg = <0x3c>;
+			interrupts = <0 86 0x4>;
+
+			maxim,system-power-controller;
+
+			mbatt-supply = <&usb0_vbus_reg>;
+			in-v1-supply = <&mbatt_reg>;
+			in-v2-supply = <&mbatt_reg>;
+			in-v3-supply = <&mbatt_reg>;
+			in1-supply = <&mbatt_reg>;
+			in2-supply = <&nvvdd_sv3_reg>;
+			in3-supply = <&mbatt_reg>;
+			in4-supply = <&mbatt_reg>;
+			in5-supply = <&mbatt_reg>;
+			in6-supply = <&mbatt_reg>;
+			in7-supply = <&mbatt_reg>;
+			in8-supply = <&mbatt_reg>;
+			in9-supply = <&mbatt_reg>;
+			in10-supply = <&mbatt_reg>;
+			in11-supply = <&mbatt_reg>;
+			in12-supply = <&mbatt_reg>;
+			in13-supply = <&mbatt_reg>;
+			in14-supply = <&mbatt_reg>;
+			in15-supply = <&mbatt_reg>;
+			in16-supply = <&mbatt_reg>;
+			in17-supply = <&nvvdd_sv3_reg>;
+			in18-supply = <&nvvdd_sv3_reg>;
+			in19-supply = <&mbatt_reg>;
+			in20-supply = <&mbatt_reg>;
+
+			regulators {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				mbatt_reg: regulator@0 {
+					reg = <0>;
+					regulator-compatible = "mbatt";
+					regulator-name = "vbat_pmu";
+					regulator-always-on;
+				};
+
+				regulator@1 {
+					reg = <1>;
+					regulator-compatible = "sd1";
+					regulator-name = "nvvdd_sv1,vdd_cpu_pmu";
+					regulator-min-microvolt = <1000000>;
+					regulator-max-microvolt = <1000000>;
+					regulator-always-on;
+				};
+
+				regulator@2 {
+					reg = <2>;
+					regulator-compatible = "sd2";
+					regulator-name = "nvvdd_sv2,vdd_core";
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+					regulator-always-on;
+				};
+
+				nvvdd_sv3_reg: regulator@3 {
+					reg = <3>;
+					regulator-compatible = "sd3";
+					regulator-name = "nvvdd_sv3";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+				};
+
+				regulator@4 {
+					reg = <4>;
+					regulator-compatible = "ldo1";
+					regulator-name = "nvvdd_ldo1,vddio_rx_ddr,vcore_acc";
+					regulator-min-microvolt = <3300000>;
+					regulator-max-microvolt = <3300000>;
+					regulator-always-on;
+				};
+
+				regulator@5 {
+					reg = <5>;
+					regulator-compatible = "ldo2";
+					regulator-name = "nvvdd_ldo2,avdd_pll*";
+					regulator-min-microvolt = <1100000>;
+					regulator-max-microvolt = <1100000>;
+					regulator-always-on;
+				};
+
+				regulator@6 {
+					reg = <6>;
+					regulator-compatible = "ldo3";
+					regulator-name = "nvvdd_ldo3,vcom_1v8b";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+				};
+
+				regulator@7 {
+					reg = <7>;
+					regulator-compatible = "ldo4";
+					regulator-name = "nvvdd_ldo4,avdd_usb*";
+					regulator-min-microvolt = <3300000>;
+					regulator-max-microvolt = <3300000>;
+					regulator-always-on;
+				};
+
+				regulator@8 {
+					reg = <8>;
+					regulator-compatible = "ldo5";
+					regulator-name = "nvvdd_ldo5,vcore_mmc,avdd_lcd1,vddio_1wire";
+					regulator-min-microvolt = <2800000>;
+					regulator-max-microvolt = <2800000>;
+					regulator-always-on;
+				};
+
+				regulator@9 {
+					reg = <9>;
+					regulator-compatible = "ldo6";
+					regulator-name = "nvvdd_ldo6,avdd_hdmi_pll";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+				};
+
+				regulator@10 {
+					reg = <10>;
+					regulator-compatible = "ldo7";
+					regulator-name = "nvvdd_ldo7,avddio_audio";
+					regulator-min-microvolt = <2800000>;
+					regulator-max-microvolt = <2800000>;
+					regulator-always-on;
+				};
+
+				regulator@11 {
+					reg = <11>;
+					regulator-compatible = "ldo8";
+					regulator-name = "nvvdd_ldo8,vcom_3v0,vcore_cmps";
+					regulator-min-microvolt = <3000000>;
+					regulator-max-microvolt = <3000000>;
+				};
+
+				regulator@12 {
+					reg = <12>;
+					regulator-compatible = "ldo9";
+					regulator-name = "nvvdd_ldo9,avdd_cam*";
+					regulator-min-microvolt = <2800000>;
+					regulator-max-microvolt = <2800000>;
+				};
+
+				regulator@13 {
+					reg = <13>;
+					regulator-compatible = "ldo10";
+					regulator-name = "nvvdd_ldo10,avdd_usb_ic_3v0";
+					regulator-min-microvolt = <3000000>;
+					regulator-max-microvolt = <3000000>;
+					regulator-always-on;
+				};
+
+				regulator@14 {
+					reg = <14>;
+					regulator-compatible = "ldo11";
+					regulator-name = "nvvdd_ldo11,vddio_pex_clk,vcom_33,avdd_hdmi";
+					regulator-min-microvolt = <3300000>;
+					regulator-max-microvolt = <3300000>;
+				};
+
+				regulator@15 {
+					reg = <15>;
+					regulator-compatible = "ldo12";
+					regulator-name = "nvvdd_ldo12,vddio_sdio";
+					regulator-min-microvolt = <2800000>;
+					regulator-max-microvolt = <2800000>;
+					regulator-always-on;
+				};
+
+				regulator@16 {
+					reg = <16>;
+					regulator-compatible = "ldo13";
+					regulator-name = "nvvdd_ldo13,vcore_phtn,vdd_af";
+					regulator-min-microvolt = <2800000>;
+					regulator-max-microvolt = <2800000>;
+				};
+
+				regulator@17 {
+					reg = <17>;
+					regulator-compatible = "ldo14";
+					regulator-name = "nvvdd_ldo14,avdd_vdac";
+					regulator-min-microvolt = <2800000>;
+					regulator-max-microvolt = <2800000>;
+				};
+
+				regulator@18 {
+					reg = <18>;
+					regulator-compatible = "ldo15";
+					regulator-name = "nvvdd_ldo15,vcore_temp,vddio_hdcp";
+					regulator-min-microvolt = <3300000>;
+					regulator-max-microvolt = <3300000>;
+				};
+
+				regulator@19 {
+					reg = <19>;
+					regulator-compatible = "ldo16";
+					regulator-name = "nvvdd_ldo16,vdd_dbrtr";
+					regulator-min-microvolt = <1300000>;
+					regulator-max-microvolt = <1300000>;
+				};
+
+				regulator@20 {
+					reg = <20>;
+					regulator-compatible = "ldo17";
+					regulator-name = "nvvdd_ldo17,vddio_mipi";
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+				};
+
+				regulator@21 {
+					reg = <21>;
+					regulator-compatible = "ldo18";
+					regulator-name = "nvvdd_ldo18,vddio_vi,vcore_cam*";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+				};
+
+				regulator@22 {
+					reg = <22>;
+					regulator-compatible = "ldo19";
+					regulator-name = "nvvdd_ldo19,avdd_lcd2,vddio_lx";
+					regulator-min-microvolt = <2800000>;
+					regulator-max-microvolt = <2800000>;
+				};
+
+				regulator@23 {
+					reg = <23>;
+					regulator-compatible = "ldo20";
+					regulator-name = "nvvdd_ldo20,vddio_ddr_1v2,vddio_hsic,vcom_1v2";
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+					regulator-always-on;
+				};
+
+				regulator@24 {
+					reg = <24>;
+					regulator-compatible = "out5v";
+					regulator-name = "usb0_vbus_reg";
+				};
+
+				regulator@25 {
+					reg = <25>;
+					regulator-compatible = "out33v";
+					regulator-name = "pmu_out3v3";
+				};
+
+				regulator@26 {
+					reg = <26>;
+					regulator-compatible = "bbat";
+					regulator-name = "pmu_bbat";
+					regulator-min-microvolt = <2400000>;
+					regulator-max-microvolt = <2400000>;
+					regulator-always-on;
+				};
+
+				regulator@27 {
+					reg = <27>;
+					regulator-compatible = "sdby";
+					regulator-name = "vdd_aon";
+					regulator-always-on;
+				};
+
+				regulator@28 {
+					reg = <28>;
+					regulator-compatible = "vrtc";
+					regulator-name = "vrtc,pmu_vccadc";
+					regulator-always-on;
+				};
+			};
+		};
+	};
+
+	pmc {
+		nvidia,invert-interrupt;
 	};
 
 	usb@c5000000 {
@@ -284,6 +564,21 @@
 		bus-width = <8>;
 	};
 
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		usb0_vbus_reg: regulator {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "usb0_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			regulator-always-on;
+		};
+	};
+
 	sound {
 		compatible = "nvidia,tegra-audio-wm8753-whistler",
 			     "nvidia,tegra-audio-wm8753";
diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi
index 405d167..67a6cd9 100644
--- a/arch/arm/boot/dts/tegra20.dtsi
+++ b/arch/arm/boot/dts/tegra20.dtsi
@@ -123,7 +123,7 @@
 		status = "disabled";
 	};
 
-	pwm {
+	pwm: pwm {
 		compatible = "nvidia,tegra20-pwm";
 		reg = <0x7000a000 0x100>;
 		#pwm-cells = <2>;
diff --git a/arch/arm/boot/dts/tegra30-cardhu-a02.dts b/arch/arm/boot/dts/tegra30-cardhu-a02.dts
new file mode 100644
index 0000000..dd4222f
--- /dev/null
+++ b/arch/arm/boot/dts/tegra30-cardhu-a02.dts
@@ -0,0 +1,87 @@
+/dts-v1/;
+
+/include/ "tegra30-cardhu.dtsi"
+
+/* This dts file support the cardhu A02 version of board */
+
+/ {
+	model = "NVIDIA Tegra30 Cardhu A02 evaluation board";
+	compatible = "nvidia,cardhu-a02", "nvidia,cardhu", "nvidia,tegra30";
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		ddr_reg: regulator@100 {
+			compatible = "regulator-fixed";
+			reg = <100>;
+			regulator-name = "vdd_ddr";
+			regulator-min-microvolt = <1500000>;
+			regulator-max-microvolt = <1500000>;
+			regulator-always-on;
+			regulator-boot-on;
+			enable-active-high;
+			gpio = <&pmic 6 0>;
+		};
+
+		sys_3v3_reg: regulator@101 {
+			compatible = "regulator-fixed";
+			reg = <101>;
+			regulator-name = "sys_3v3";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+			regulator-boot-on;
+			enable-active-high;
+			gpio = <&pmic 7 0>;
+		};
+
+		usb1_vbus_reg: regulator@102 {
+			compatible = "regulator-fixed";
+			reg = <102>;
+			regulator-name = "usb1_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			enable-active-high;
+			gpio = <&gpio 68 0>; /* GPIO PI4 */
+			gpio-open-drain;
+			vin-supply = <&vdd_5v0_reg>;
+		};
+
+		usb3_vbus_reg: regulator@103 {
+			compatible = "regulator-fixed";
+			reg = <103>;
+			regulator-name = "usb3_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			enable-active-high;
+			gpio = <&gpio 63 0>; /* GPIO PH7 */
+			gpio-open-drain;
+			vin-supply = <&vdd_5v0_reg>;
+		};
+
+		vdd_5v0_reg: regulator@104 {
+			compatible = "regulator-fixed";
+			reg = <104>;
+			regulator-name = "5v0";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			enable-active-high;
+			gpio = <&pmic 2 0>;
+		};
+
+		vdd_bl_reg: regulator@105 {
+			compatible = "regulator-fixed";
+			reg = <105>;
+			regulator-name = "vdd_bl";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			regulator-always-on;
+			regulator-boot-on;
+			enable-active-high;
+			gpio = <&gpio 83 0>; /* GPIO PK3 */
+		};
+	};
+};
+
diff --git a/arch/arm/boot/dts/tegra30-cardhu-a04.dts b/arch/arm/boot/dts/tegra30-cardhu-a04.dts
new file mode 100644
index 0000000..0828f09
--- /dev/null
+++ b/arch/arm/boot/dts/tegra30-cardhu-a04.dts
@@ -0,0 +1,98 @@
+/dts-v1/;
+
+/include/ "tegra30-cardhu.dtsi"
+
+/* This dts file support the cardhu A04 and later versions of board */
+
+/ {
+	model = "NVIDIA Tegra30 Cardhu A04 (A05, A06, A07) evaluation board";
+	compatible = "nvidia,cardhu-a04", "nvidia,cardhu", "nvidia,tegra30";
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		ddr_reg: regulator@100 {
+			compatible = "regulator-fixed";
+			regulator-name = "ddr";
+			reg = <100>;
+			regulator-min-microvolt = <1500000>;
+			regulator-max-microvolt = <1500000>;
+			regulator-always-on;
+			regulator-boot-on;
+			enable-active-high;
+			gpio = <&pmic 7 0>;
+		};
+
+		sys_3v3_reg: regulator@101 {
+			compatible = "regulator-fixed";
+			reg = <101>;
+			regulator-name = "sys_3v3";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+			regulator-boot-on;
+			enable-active-high;
+			gpio = <&pmic 6 0>;
+		};
+
+		usb1_vbus_reg: regulator@102 {
+			compatible = "regulator-fixed";
+			reg = <102>;
+			regulator-name = "usb1_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			enable-active-high;
+			gpio = <&gpio 238 0>; /* GPIO PDD6 */
+			gpio-open-drain;
+			vin-supply = <&vdd_5v0_reg>;
+		};
+
+		usb3_vbus_reg: regulator@103 {
+			compatible = "regulator-fixed";
+			reg = <103>;
+			regulator-name = "usb3_vbus";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			enable-active-high;
+			gpio = <&gpio 236 0>; /* GPIO PDD4 */
+			gpio-open-drain;
+			vin-supply = <&vdd_5v0_reg>;
+		};
+
+		vdd_5v0_reg: regulator@104 {
+			compatible = "regulator-fixed";
+			reg = <104>;
+			regulator-name = "5v0";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			enable-active-high;
+			gpio = <&pmic 8 0>;
+		};
+
+		vdd_bl_reg: regulator@105 {
+			compatible = "regulator-fixed";
+			reg = <105>;
+			regulator-name = "vdd_bl";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			regulator-always-on;
+			regulator-boot-on;
+			enable-active-high;
+			gpio = <&gpio 234 0>; /* GPIO PDD2 */
+		};
+
+		vdd_bl2_reg: regulator@106 {
+			compatible = "regulator-fixed";
+			reg = <106>;
+			regulator-name = "vdd_bl2";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			regulator-always-on;
+			regulator-boot-on;
+			enable-active-high;
+			gpio = <&gpio 232 0>; /* GPIO PDD0 */
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/tegra30-cardhu.dts b/arch/arm/boot/dts/tegra30-cardhu.dts
deleted file mode 100644
index c169bce..0000000
--- a/arch/arm/boot/dts/tegra30-cardhu.dts
+++ /dev/null
@@ -1,171 +0,0 @@
-/dts-v1/;
-
-/include/ "tegra30.dtsi"
-
-/ {
-	model = "NVIDIA Tegra30 Cardhu evaluation board";
-	compatible = "nvidia,cardhu", "nvidia,tegra30";
-
-	memory {
-		reg = <0x80000000 0x40000000>;
-	};
-
-	pinmux {
-		pinctrl-names = "default";
-		pinctrl-0 = <&state_default>;
-
-		state_default: pinmux {
-			sdmmc1_clk_pz0 {
-				nvidia,pins = "sdmmc1_clk_pz0";
-				nvidia,function = "sdmmc1";
-				nvidia,pull = <0>;
-				nvidia,tristate = <0>;
-			};
-			sdmmc1_cmd_pz1 {
-				nvidia,pins =	"sdmmc1_cmd_pz1",
-						"sdmmc1_dat0_py7",
-						"sdmmc1_dat1_py6",
-						"sdmmc1_dat2_py5",
-						"sdmmc1_dat3_py4";
-				nvidia,function = "sdmmc1";
-				nvidia,pull = <2>;
-				nvidia,tristate = <0>;
-			};
-			sdmmc4_clk_pcc4 {
-				nvidia,pins =	"sdmmc4_clk_pcc4",
-						"sdmmc4_rst_n_pcc3";
-				nvidia,function = "sdmmc4";
-				nvidia,pull = <0>;
-				nvidia,tristate = <0>;
-			};
-			sdmmc4_dat0_paa0 {
-				nvidia,pins =	"sdmmc4_dat0_paa0",
-						"sdmmc4_dat1_paa1",
-						"sdmmc4_dat2_paa2",
-						"sdmmc4_dat3_paa3",
-						"sdmmc4_dat4_paa4",
-						"sdmmc4_dat5_paa5",
-						"sdmmc4_dat6_paa6",
-						"sdmmc4_dat7_paa7";
-				nvidia,function = "sdmmc4";
-				nvidia,pull = <2>;
-				nvidia,tristate = <0>;
-			};
-			dap2_fs_pa2 {
-				nvidia,pins =	"dap2_fs_pa2",
-						"dap2_sclk_pa3",
-						"dap2_din_pa4",
-						"dap2_dout_pa5";
-				nvidia,function = "i2s1";
-				nvidia,pull = <0>;
-				nvidia,tristate = <0>;
-			};
-		};
-	};
-
-	serial@70006000 {
-		status = "okay";
-		clock-frequency = <408000000>;
-	};
-
-	i2c@7000c000 {
-		status = "okay";
-		clock-frequency = <100000>;
-	};
-
-	i2c@7000c400 {
-		status = "okay";
-		clock-frequency = <100000>;
-	};
-
-	i2c@7000c500 {
-		status = "okay";
-		clock-frequency = <100000>;
-
-		/* ALS and Proximity sensor */
-		isl29028@44 {
-			compatible = "isil,isl29028";
-			reg = <0x44>;
-			interrupt-parent = <&gpio>;
-			interrupts = <88 0x04>; /*gpio PL0 */
-		};
-	};
-
-	i2c@7000c700 {
-		status = "okay";
-		clock-frequency = <100000>;
-	};
-
-	i2c@7000d000 {
-		status = "okay";
-		clock-frequency = <100000>;
-
-		wm8903: wm8903@1a {
-			compatible = "wlf,wm8903";
-			reg = <0x1a>;
-			interrupt-parent = <&gpio>;
-			interrupts = <179 0x04>; /* gpio PW3 */
-
-			gpio-controller;
-			#gpio-cells = <2>;
-
-			micdet-cfg = <0>;
-			micdet-delay = <100>;
-			gpio-cfg = <0xffffffff 0xffffffff 0 0xffffffff 0xffffffff>;
-		};
-
-		tps62361 {
-			compatible = "ti,tps62361";
-			reg = <0x60>;
-
-			regulator-name = "tps62361-vout";
-			regulator-min-microvolt = <500000>;
-			regulator-max-microvolt = <1500000>;
-			regulator-boot-on;
-			regulator-always-on;
-			ti,vsel0-state-high;
-			ti,vsel1-state-high;
-		};
-	};
-
-	ahub {
-		i2s@70080400 {
-			status = "okay";
-		};
-	};
-
-	sdhci@78000000 {
-		status = "okay";
-		cd-gpios = <&gpio 69 0>; /* gpio PI5 */
-		wp-gpios = <&gpio 155 0>; /* gpio PT3 */
-		power-gpios = <&gpio 31 0>; /* gpio PD7 */
-		bus-width = <4>;
-	};
-
-	sdhci@78000600 {
-		status = "okay";
-		bus-width = <8>;
-	};
-
-	sound {
-		compatible = "nvidia,tegra-audio-wm8903-cardhu",
-			     "nvidia,tegra-audio-wm8903";
-		nvidia,model = "NVIDIA Tegra Cardhu";
-
-		nvidia,audio-routing =
-			"Headphone Jack", "HPOUTR",
-			"Headphone Jack", "HPOUTL",
-			"Int Spk", "ROP",
-			"Int Spk", "RON",
-			"Int Spk", "LOP",
-			"Int Spk", "LON",
-			"Mic Jack", "MICBIAS",
-			"IN1L", "Mic Jack";
-
-		nvidia,i2s-controller = <&tegra_i2s1>;
-		nvidia,audio-codec = <&wm8903>;
-
-		nvidia,spkr-en-gpios = <&wm8903 2 0>;
-		nvidia,hp-det-gpios = <&gpio 178 0>; /* gpio PW2 */
-	};
-};
diff --git a/arch/arm/boot/dts/tegra30-cardhu.dtsi b/arch/arm/boot/dts/tegra30-cardhu.dtsi
new file mode 100644
index 0000000..d10c9c5
--- /dev/null
+++ b/arch/arm/boot/dts/tegra30-cardhu.dtsi
@@ -0,0 +1,475 @@
+/include/ "tegra30.dtsi"
+
+/**
+ * This file contains common DT entry for all fab version of Cardhu.
+ * There is multiple fab version of Cardhu starting from A01 to A07.
+ * Cardhu fab version A01 and A03 are not supported. Cardhu fab version
+ * A02 will have different sets of GPIOs for fixed regulator compare to
+ * Cardhu fab version A04. The Cardhu fab version A05, A06, A07 are
+ * compatible with fab version A04. Based on Cardhu fab version, the
+ * related dts file need to be chosen like for Cardhu fab version A02,
+ * use tegra30-cardhu-a02.dts, Cardhu fab version A04 and later, use
+ * tegra30-cardhu-a04.dts.
+ * The identification of board is done in two ways, by looking the sticker
+ * on PCB and by reading board id eeprom.
+ * The stciker will have number like 600-81291-1000-002 C.3. In this 4th
+ * number is the fab version like here it is 002 and hence fab version A02.
+ * The (downstream internal) U-Boot of Cardhu display the board-id as
+ * follows:
+ * BoardID: 0C5B, SKU: 0A01, Fab: 02, Rev: 45.00
+ * In this Fab version is 02 i.e. A02.
+ * The BoardID I2C eeprom is interfaced through i2c5 (pwr_i2c address 0x56).
+ * The location 0x8 of this eeprom contains the Fab version. It is 1 byte
+ * wide.
+ */
+
+/ {
+	model = "NVIDIA Tegra30 Cardhu evaluation board";
+	compatible = "nvidia,cardhu", "nvidia,tegra30";
+
+	memory {
+		reg = <0x80000000 0x40000000>;
+	};
+
+	pinmux {
+		pinctrl-names = "default";
+		pinctrl-0 = <&state_default>;
+
+		state_default: pinmux {
+			sdmmc1_clk_pz0 {
+				nvidia,pins = "sdmmc1_clk_pz0";
+				nvidia,function = "sdmmc1";
+				nvidia,pull = <0>;
+				nvidia,tristate = <0>;
+			};
+			sdmmc1_cmd_pz1 {
+				nvidia,pins =	"sdmmc1_cmd_pz1",
+						"sdmmc1_dat0_py7",
+						"sdmmc1_dat1_py6",
+						"sdmmc1_dat2_py5",
+						"sdmmc1_dat3_py4";
+				nvidia,function = "sdmmc1";
+				nvidia,pull = <2>;
+				nvidia,tristate = <0>;
+			};
+			sdmmc4_clk_pcc4 {
+				nvidia,pins =	"sdmmc4_clk_pcc4",
+						"sdmmc4_rst_n_pcc3";
+				nvidia,function = "sdmmc4";
+				nvidia,pull = <0>;
+				nvidia,tristate = <0>;
+			};
+			sdmmc4_dat0_paa0 {
+				nvidia,pins =	"sdmmc4_dat0_paa0",
+						"sdmmc4_dat1_paa1",
+						"sdmmc4_dat2_paa2",
+						"sdmmc4_dat3_paa3",
+						"sdmmc4_dat4_paa4",
+						"sdmmc4_dat5_paa5",
+						"sdmmc4_dat6_paa6",
+						"sdmmc4_dat7_paa7";
+				nvidia,function = "sdmmc4";
+				nvidia,pull = <2>;
+				nvidia,tristate = <0>;
+			};
+			dap2_fs_pa2 {
+				nvidia,pins =	"dap2_fs_pa2",
+						"dap2_sclk_pa3",
+						"dap2_din_pa4",
+						"dap2_dout_pa5";
+				nvidia,function = "i2s1";
+				nvidia,pull = <0>;
+				nvidia,tristate = <0>;
+			};
+		};
+	};
+
+	serial@70006000 {
+		status = "okay";
+		clock-frequency = <408000000>;
+	};
+
+	i2c@7000c000 {
+		status = "okay";
+		clock-frequency = <100000>;
+	};
+
+	i2c@7000c400 {
+		status = "okay";
+		clock-frequency = <100000>;
+	};
+
+	i2c@7000c500 {
+		status = "okay";
+		clock-frequency = <100000>;
+
+		/* ALS and Proximity sensor */
+		isl29028@44 {
+			compatible = "isil,isl29028";
+			reg = <0x44>;
+			interrupt-parent = <&gpio>;
+			interrupts = <88 0x04>; /*gpio PL0 */
+		};
+	};
+
+	i2c@7000c700 {
+		status = "okay";
+		clock-frequency = <100000>;
+	};
+
+	i2c@7000d000 {
+		status = "okay";
+		clock-frequency = <100000>;
+
+		wm8903: wm8903@1a {
+			compatible = "wlf,wm8903";
+			reg = <0x1a>;
+			interrupt-parent = <&gpio>;
+			interrupts = <179 0x04>; /* gpio PW3 */
+
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			micdet-cfg = <0>;
+			micdet-delay = <100>;
+			gpio-cfg = <0xffffffff 0xffffffff 0 0xffffffff 0xffffffff>;
+		};
+
+		tps62361 {
+			compatible = "ti,tps62361";
+			reg = <0x60>;
+
+			regulator-name = "tps62361-vout";
+			regulator-min-microvolt = <500000>;
+			regulator-max-microvolt = <1500000>;
+			regulator-boot-on;
+			regulator-always-on;
+			ti,vsel0-state-high;
+			ti,vsel1-state-high;
+		};
+
+		pmic: tps65911@2d {
+			compatible = "ti,tps65911";
+			reg = <0x2d>;
+
+			interrupts = <0 86 0x4>;
+			#interrupt-cells = <2>;
+			interrupt-controller;
+
+			ti,system-power-controller;
+
+			#gpio-cells = <2>;
+			gpio-controller;
+
+			vcc1-supply = <&vdd_ac_bat_reg>;
+			vcc2-supply = <&vdd_ac_bat_reg>;
+			vcc3-supply = <&vio_reg>;
+			vcc4-supply = <&vdd_5v0_reg>;
+			vcc5-supply = <&vdd_ac_bat_reg>;
+			vcc6-supply = <&vdd2_reg>;
+			vcc7-supply = <&vdd_ac_bat_reg>;
+			vccio-supply = <&vdd_ac_bat_reg>;
+
+			regulators {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				vdd1_reg: regulator@0 {
+					reg = <0>;
+					regulator-compatible = "vdd1";
+					regulator-name = "vddio_ddr_1v2";
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+					regulator-always-on;
+				};
+
+				vdd2_reg: regulator@1 {
+					reg = <1>;
+					regulator-compatible = "vdd2";
+					regulator-name = "vdd_1v5_gen";
+					regulator-min-microvolt = <1500000>;
+					regulator-max-microvolt = <1500000>;
+					regulator-always-on;
+				};
+
+				vddctrl_reg: regulator@2 {
+					reg = <2>;
+					regulator-compatible = "vddctrl";
+					regulator-name = "vdd_cpu,vdd_sys";
+					regulator-min-microvolt = <1000000>;
+					regulator-max-microvolt = <1000000>;
+					regulator-always-on;
+				};
+
+				vio_reg: regulator@3 {
+					reg = <3>;
+					regulator-compatible = "vio";
+					regulator-name = "vdd_1v8_gen";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+				};
+
+				ldo1_reg: regulator@4 {
+					reg = <4>;
+					regulator-compatible = "ldo1";
+					regulator-name = "vdd_pexa,vdd_pexb";
+					regulator-min-microvolt = <1050000>;
+					regulator-max-microvolt = <1050000>;
+				};
+
+				ldo2_reg: regulator@5 {
+					reg = <5>;
+					regulator-compatible = "ldo2";
+					regulator-name = "vdd_sata,avdd_plle";
+					regulator-min-microvolt = <1050000>;
+					regulator-max-microvolt = <1050000>;
+				};
+
+				/* LDO3 is not connected to anything */
+
+				ldo4_reg: regulator@7 {
+					reg = <7>;
+					regulator-compatible = "ldo4";
+					regulator-name = "vdd_rtc";
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+					regulator-always-on;
+				};
+
+				ldo5_reg: regulator@8 {
+					reg = <8>;
+					regulator-compatible = "ldo5";
+					regulator-name = "vddio_sdmmc,avdd_vdac";
+					regulator-min-microvolt = <3300000>;
+					regulator-max-microvolt = <3300000>;
+					regulator-always-on;
+				};
+
+				ldo6_reg: regulator@9 {
+					reg = <9>;
+					regulator-compatible = "ldo6";
+					regulator-name = "avdd_dsi_csi,pwrdet_mipi";
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+				};
+
+				ldo7_reg: regulator@10 {
+					reg = <10>;
+					regulator-compatible = "ldo7";
+					regulator-name = "vdd_pllm,x,u,a_p_c_s";
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+					regulator-always-on;
+				};
+
+				ldo8_reg: regulator@11 {
+					reg = <11>;
+					regulator-compatible = "ldo8";
+					regulator-name = "vdd_ddr_hs";
+					regulator-min-microvolt = <1000000>;
+					regulator-max-microvolt = <1000000>;
+					regulator-always-on;
+				};
+			};
+		};
+	};
+
+	ahub {
+		i2s@70080400 {
+			status = "okay";
+		};
+	};
+
+	pmc {
+		status = "okay";
+		nvidia,invert-interrupt;
+	};
+
+	sdhci@78000000 {
+		status = "okay";
+		cd-gpios = <&gpio 69 0>; /* gpio PI5 */
+		wp-gpios = <&gpio 155 0>; /* gpio PT3 */
+		power-gpios = <&gpio 31 0>; /* gpio PD7 */
+		bus-width = <4>;
+	};
+
+	sdhci@78000600 {
+		status = "okay";
+		bus-width = <8>;
+	};
+
+	regulators {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		vdd_ac_bat_reg: regulator@0 {
+			compatible = "regulator-fixed";
+			reg = <0>;
+			regulator-name = "vdd_ac_bat";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			regulator-always-on;
+		};
+
+		cam_1v8_reg: regulator@1 {
+			compatible = "regulator-fixed";
+			reg = <1>;
+			regulator-name = "cam_1v8";
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			enable-active-high;
+			gpio = <&gpio 220 0>; /* gpio PBB4 */
+			vin-supply = <&vio_reg>;
+		};
+
+		cp_5v_reg: regulator@2 {
+			compatible = "regulator-fixed";
+			reg = <2>;
+			regulator-name = "cp_5v";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			regulator-boot-on;
+			regulator-always-on;
+			enable-active-high;
+			gpio = <&pmic 0 0>; /* PMIC TPS65911 GPIO0 */
+		};
+
+		emmc_3v3_reg: regulator@3 {
+			compatible = "regulator-fixed";
+			reg = <3>;
+			regulator-name = "emmc_3v3";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+			regulator-boot-on;
+			enable-active-high;
+			gpio = <&gpio 25 0>; /* gpio PD1 */
+			vin-supply = <&sys_3v3_reg>;
+		};
+
+		modem_3v3_reg: regulator@4 {
+			compatible = "regulator-fixed";
+			reg = <4>;
+			regulator-name = "modem_3v3";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			enable-active-high;
+			gpio = <&gpio 30 0>; /* gpio PD6 */
+		};
+
+		pex_hvdd_3v3_reg: regulator@5 {
+			compatible = "regulator-fixed";
+			reg = <5>;
+			regulator-name = "pex_hvdd_3v3";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			enable-active-high;
+			gpio = <&gpio 95 0>; /* gpio PL7 */
+			vin-supply = <&sys_3v3_reg>;
+		};
+
+		vdd_cam1_ldo_reg: regulator@6 {
+			compatible = "regulator-fixed";
+			reg = <6>;
+			regulator-name = "vdd_cam1_ldo";
+			regulator-min-microvolt = <2800000>;
+			regulator-max-microvolt = <2800000>;
+			enable-active-high;
+			gpio = <&gpio 142 0>; /* gpio PR6 */
+			vin-supply = <&sys_3v3_reg>;
+		};
+
+		vdd_cam2_ldo_reg: regulator@7 {
+			compatible = "regulator-fixed";
+			reg = <7>;
+			regulator-name = "vdd_cam2_ldo";
+			regulator-min-microvolt = <2800000>;
+			regulator-max-microvolt = <2800000>;
+			enable-active-high;
+			gpio = <&gpio 143 0>; /* gpio PR7 */
+			vin-supply = <&sys_3v3_reg>;
+		};
+
+		vdd_cam3_ldo_reg: regulator@8 {
+			compatible = "regulator-fixed";
+			reg = <8>;
+			regulator-name = "vdd_cam3_ldo";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			enable-active-high;
+			gpio = <&gpio 144 0>; /* gpio PS0 */
+			vin-supply = <&sys_3v3_reg>;
+		};
+
+		vdd_com_reg: regulator@9 {
+			compatible = "regulator-fixed";
+			reg = <9>;
+			regulator-name = "vdd_com";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			enable-active-high;
+			gpio = <&gpio 24 0>; /* gpio PD0 */
+			vin-supply = <&sys_3v3_reg>;
+		};
+
+		vdd_fuse_3v3_reg: regulator@10 {
+			compatible = "regulator-fixed";
+			reg = <10>;
+			regulator-name = "vdd_fuse_3v3";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			enable-active-high;
+			gpio = <&gpio 94 0>; /* gpio PL6 */
+			vin-supply = <&sys_3v3_reg>;
+		};
+
+		vdd_pnl1_reg: regulator@11 {
+			compatible = "regulator-fixed";
+			reg = <11>;
+			regulator-name = "vdd_pnl1";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			regulator-always-on;
+			regulator-boot-on;
+			enable-active-high;
+			gpio = <&gpio 92 0>; /* gpio PL4 */
+			vin-supply = <&sys_3v3_reg>;
+		};
+
+		vdd_vid_reg: regulator@12 {
+			compatible = "regulator-fixed";
+			reg = <12>;
+			regulator-name = "vddio_vid";
+			regulator-min-microvolt = <5000000>;
+			regulator-max-microvolt = <5000000>;
+			enable-active-high;
+			gpio = <&gpio 152 0>; /* GPIO PT0 */
+			gpio-open-drain;
+			vin-supply = <&vdd_5v0_reg>;
+		};
+	};
+
+	sound {
+		compatible = "nvidia,tegra-audio-wm8903-cardhu",
+			     "nvidia,tegra-audio-wm8903";
+		nvidia,model = "NVIDIA Tegra Cardhu";
+
+		nvidia,audio-routing =
+			"Headphone Jack", "HPOUTR",
+			"Headphone Jack", "HPOUTL",
+			"Int Spk", "ROP",
+			"Int Spk", "RON",
+			"Int Spk", "LOP",
+			"Int Spk", "LON",
+			"Mic Jack", "MICBIAS",
+			"IN1L", "Mic Jack";
+
+		nvidia,i2s-controller = <&tegra_i2s1>;
+		nvidia,audio-codec = <&wm8903>;
+
+		nvidia,spkr-en-gpios = <&wm8903 2 0>;
+		nvidia,hp-det-gpios = <&gpio 178 0>; /* gpio PW2 */
+	};
+};
diff --git a/arch/arm/boot/dts/tegra30.dtsi b/arch/arm/boot/dts/tegra30.dtsi
index 3e4334d..b1497c7 100644
--- a/arch/arm/boot/dts/tegra30.dtsi
+++ b/arch/arm/boot/dts/tegra30.dtsi
@@ -117,7 +117,7 @@
 		status = "disabled";
 	};
 
-	pwm {
+	pwm: pwm {
 		compatible = "nvidia,tegra30-pwm", "nvidia,tegra20-pwm";
 		reg = <0x7000a000 0x100>;
 		#pwm-cells = <2>;
diff --git a/arch/arm/boot/dts/tps65217.dtsi b/arch/arm/boot/dts/tps65217.dtsi
new file mode 100644
index 0000000..a632724
--- /dev/null
+++ b/arch/arm/boot/dts/tps65217.dtsi
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * Integrated Power Management Chip
+ * http://www.ti.com/lit/ds/symlink/tps65217.pdf
+ */
+
+&tps {
+	compatible = "ti,tps65217";
+
+	regulators {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		dcdc1_reg: regulator@0 {
+			reg = <0>;
+			regulator-compatible = "dcdc1";
+		};
+
+		dcdc2_reg: regulator@1 {
+			reg = <1>;
+			regulator-compatible = "dcdc2";
+		};
+
+		dcdc3_reg: regulator@2 {
+			reg = <2>;
+			regulator-compatible = "dcdc3";
+		};
+
+		ldo1_reg: regulator@3 {
+			reg = <3>;
+			regulator-compatible = "ldo1";
+		};
+
+		ldo2_reg: regulator@4 {
+			reg = <4>;
+			regulator-compatible = "ldo2";
+		};
+
+		ldo3_reg: regulator@5 {
+			reg = <5>;
+			regulator-compatible = "ldo3";
+		};
+
+		ldo4_reg: regulator@6 {
+			reg = <6>;
+			regulator-compatible = "ldo4";
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/tps65910.dtsi b/arch/arm/boot/dts/tps65910.dtsi
new file mode 100644
index 0000000..92693a8
--- /dev/null
+++ b/arch/arm/boot/dts/tps65910.dtsi
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * Integrated Power Management Chip
+ * http://www.ti.com/lit/ds/symlink/tps65910.pdf
+ */
+
+&tps {
+	compatible = "ti,tps65910";
+
+	regulators {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		vrtc_reg: regulator@0 {
+			reg = <0>;
+			regulator-compatible = "vrtc";
+		};
+
+		vio_reg: regulator@1 {
+			reg = <1>;
+			regulator-compatible = "vio";
+		};
+
+		vdd1_reg: regulator@2 {
+			reg = <2>;
+			regulator-compatible = "vdd1";
+		};
+
+		vdd2_reg: regulator@3 {
+			reg = <3>;
+			regulator-compatible = "vdd2";
+		};
+
+		vdd3_reg: regulator@4 {
+			reg = <4>;
+			regulator-compatible = "vdd3";
+		};
+
+		vdig1_reg: regulator@5 {
+			reg = <5>;
+			regulator-compatible = "vdig1";
+		};
+
+		vdig2_reg: regulator@6 {
+			reg = <6>;
+			regulator-compatible = "vdig2";
+		};
+
+		vpll_reg: regulator@7 {
+			reg = <7>;
+			regulator-compatible = "vpll";
+		};
+
+		vdac_reg: regulator@8 {
+			reg = <8>;
+			regulator-compatible = "vdac";
+		};
+
+		vaux1_reg: regulator@9 {
+			reg = <9>;
+			regulator-compatible = "vaux1";
+		};
+
+		vaux2_reg: regulator@10 {
+			reg = <10>;
+			regulator-compatible = "vaux2";
+		};
+
+		vaux33_reg: regulator@11 {
+			reg = <11>;
+			regulator-compatible = "vaux33";
+		};
+
+		vmmc_reg: regulator@12 {
+			reg = <12>;
+			regulator-compatible = "vmmc";
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/twl4030.dtsi b/arch/arm/boot/dts/twl4030.dtsi
index 22f4d13..ff00017 100644
--- a/arch/arm/boot/dts/twl4030.dtsi
+++ b/arch/arm/boot/dts/twl4030.dtsi
@@ -19,19 +19,19 @@
 		interrupts = <11>;
 	};
 
-	vdac: regulator@0 {
+	vdac: regulator-vdac {
 		compatible = "ti,twl4030-vdac";
 		regulator-min-microvolt = <1800000>;
 		regulator-max-microvolt = <1800000>;
 	};
 
-	vpll2: regulator@1 {
+	vpll2: regulator-vpll2 {
 		compatible = "ti,twl4030-vpll2";
 		regulator-min-microvolt = <1800000>;
 		regulator-max-microvolt = <1800000>;
 	};
 
-	vmmc1: regulator@2 {
+	vmmc1: regulator-vmmc1 {
 		compatible = "ti,twl4030-vmmc1";
 		regulator-min-microvolt = <1850000>;
 		regulator-max-microvolt = <3150000>;
diff --git a/arch/arm/boot/dts/twl6030.dtsi b/arch/arm/boot/dts/twl6030.dtsi
index d351b27..123e2c4 100644
--- a/arch/arm/boot/dts/twl6030.dtsi
+++ b/arch/arm/boot/dts/twl6030.dtsi
@@ -20,70 +20,70 @@
 		interrupts = <11>;
 	};
 
-	vaux1: regulator@0 {
+	vaux1: regulator-vaux1 {
 		compatible = "ti,twl6030-vaux1";
 		regulator-min-microvolt = <1000000>;
 		regulator-max-microvolt = <3000000>;
 	};
 
-	vaux2: regulator@1 {
+	vaux2: regulator-vaux2 {
 		compatible = "ti,twl6030-vaux2";
 		regulator-min-microvolt = <1200000>;
 		regulator-max-microvolt = <2800000>;
 	};
 
-	vaux3: regulator@2 {
+	vaux3: regulator-vaux3 {
 		compatible = "ti,twl6030-vaux3";
 		regulator-min-microvolt = <1000000>;
 		regulator-max-microvolt = <3000000>;
 	};
 
-	vmmc: regulator@3 {
+	vmmc: regulator-vmmc {
 		compatible = "ti,twl6030-vmmc";
 		regulator-min-microvolt = <1200000>;
 		regulator-max-microvolt = <3000000>;
 	};
 
-	vpp: regulator@4 {
+	vpp: regulator-vpp {
 		compatible = "ti,twl6030-vpp";
 		regulator-min-microvolt = <1800000>;
 		regulator-max-microvolt = <2500000>;
 	};
 
-	vusim: regulator@5 {
+	vusim: regulator-vusim {
 		compatible = "ti,twl6030-vusim";
 		regulator-min-microvolt = <1200000>;
 		regulator-max-microvolt = <2900000>;
 	};
 
-	vdac: regulator@6 {
+	vdac: regulator-vdac {
 		compatible = "ti,twl6030-vdac";
 	};
 
-	vana: regulator@7 {
+	vana: regulator-vana {
 		compatible = "ti,twl6030-vana";
 	};
 
-	vcxio: regulator@8 {
+	vcxio: regulator-vcxio {
 		compatible = "ti,twl6030-vcxio";
 		regulator-always-on;
 	};
 
-	vusb: regulator@9 {
+	vusb: regulator-vusb {
 		compatible = "ti,twl6030-vusb";
 	};
 
-	v1v8: regulator@10 {
+	v1v8: regulator-v1v8 {
 		compatible = "ti,twl6030-v1v8";
 		regulator-always-on;
 	};
 
-	v2v1: regulator@11 {
+	v2v1: regulator-v2v1 {
 		compatible = "ti,twl6030-v2v1";
 		regulator-always-on;
 	};
 
-	clk32kg: regulator@12 {
+	clk32kg: regulator-clk32kg {
 		compatible = "ti,twl6030-clk32kg";
 	};
 };
diff --git a/arch/arm/boot/dts/vt8500-bv07.dts b/arch/arm/boot/dts/vt8500-bv07.dts
new file mode 100644
index 0000000..567cf4e
--- /dev/null
+++ b/arch/arm/boot/dts/vt8500-bv07.dts
@@ -0,0 +1,36 @@
+/*
+ * vt8500-bv07.dts - Device tree file for Benign BV07 Netbook
+ *
+ * Copyright (C) 2012 Tony Prisk <linux@prisktech.co.nz>
+ *
+ * Licensed under GPLv2 or later
+ */
+
+/dts-v1/;
+/include/ "vt8500.dtsi"
+
+/ {
+	model = "Benign BV07 Netbook";
+
+	/*
+	 * Display node is based on Sascha Hauer's patch on dri-devel.
+	 * Added a bpp property to calculate the size of the framebuffer
+	 * until the binding is formalized.
+	 */
+	display: display@0 {
+		modes {
+			mode0: mode@0 {
+				hactive = <800>;
+				vactive = <480>;
+				hback-porch = <88>;
+				hfront-porch = <40>;
+				hsync-len = <0>;
+				vback-porch = <32>;
+				vfront-porch = <11>;
+				vsync-len = <1>;
+				clock = <0>;	/* unused but required */
+				bpp = <16>;	/* non-standard but required */
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/vt8500.dtsi b/arch/arm/boot/dts/vt8500.dtsi
new file mode 100644
index 0000000..d8645e9
--- /dev/null
+++ b/arch/arm/boot/dts/vt8500.dtsi
@@ -0,0 +1,116 @@
+/*
+ * vt8500.dtsi - Device tree file for VIA VT8500 SoC
+ *
+ * Copyright (C) 2012 Tony Prisk <linux@prisktech.co.nz>
+ *
+ * Licensed under GPLv2 or later
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+	compatible = "via,vt8500";
+
+	soc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		ranges;
+		interrupt-parent = <&intc>;
+
+		intc: interrupt-controller@d8140000 {
+			compatible = "via,vt8500-intc";
+			interrupt-controller;
+			reg = <0xd8140000 0x10000>;
+			#interrupt-cells = <1>;
+		};
+
+		gpio: gpio-controller@d8110000 {
+			compatible = "via,vt8500-gpio";
+			gpio-controller;
+			reg = <0xd8110000 0x10000>;
+			#gpio-cells = <3>;
+		};
+
+		pmc@d8130000 {
+			compatible = "via,vt8500-pmc";
+			reg = <0xd8130000 0x1000>;
+
+			clocks {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				ref24: ref24M {
+					#clock-cells = <0>;
+					compatible = "fixed-clock";
+					clock-frequency = <24000000>;
+				};
+			};
+		};
+
+		timer@d8130100 {
+			compatible = "via,vt8500-timer";
+			reg = <0xd8130100 0x28>;
+			interrupts = <36>;
+		};
+
+		ehci@d8007900 {
+			compatible = "via,vt8500-ehci";
+			reg = <0xd8007900 0x200>;
+			interrupts = <43>;
+		};
+
+		uhci@d8007b00 {
+			compatible = "platform-uhci";
+			reg = <0xd8007b00 0x200>;
+			interrupts = <43>;
+		};
+
+		fb@d800e400 {
+			compatible = "via,vt8500-fb";
+			reg = <0xd800e400 0x400>;
+			interrupts = <12>;
+			display = <&display>;
+			default-mode = <&mode0>;
+		};
+
+		ge_rops@d8050400 {
+			compatible = "wm,prizm-ge-rops";
+			reg = <0xd8050400 0x100>;
+		};
+
+		uart@d8200000 {
+			compatible = "via,vt8500-uart";
+			reg = <0xd8200000 0x1040>;
+			interrupts = <32>;
+			clocks = <&ref24>;
+		};
+
+		uart@d82b0000 {
+			compatible = "via,vt8500-uart";
+			reg = <0xd82b0000 0x1040>;
+			interrupts = <33>;
+			clocks = <&ref24>;
+		};
+
+		uart@d8210000 {
+			compatible = "via,vt8500-uart";
+			reg = <0xd8210000 0x1040>;
+			interrupts = <47>;
+			clocks = <&ref24>;
+		};
+
+		uart@d82c0000 {
+			compatible = "via,vt8500-uart";
+			reg = <0xd82c0000 0x1040>;
+			interrupts = <50>;
+			clocks = <&ref24>;
+		};
+
+		rtc@d8100000 {
+			compatible = "via,vt8500-rtc";
+			reg = <0xd8100000 0x10000>;
+			interrupts = <48>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/wm8505-ref.dts b/arch/arm/boot/dts/wm8505-ref.dts
new file mode 100644
index 0000000..fd4e248
--- /dev/null
+++ b/arch/arm/boot/dts/wm8505-ref.dts
@@ -0,0 +1,36 @@
+/*
+ * wm8505-ref.dts - Device tree file for Wondermedia WM8505 reference netbook
+ *
+ * Copyright (C) 2012 Tony Prisk <linux@prisktech.co.nz>
+ *
+ * Licensed under GPLv2 or later
+ */
+
+/dts-v1/;
+/include/ "wm8505.dtsi"
+
+/ {
+	model = "Wondermedia WM8505 Netbook";
+
+	/*
+	 * Display node is based on Sascha Hauer's patch on dri-devel.
+	 * Added a bpp property to calculate the size of the framebuffer
+	 * until the binding is formalized.
+	 */
+	display: display@0 {
+		modes {
+			mode0: mode@0 {
+				hactive = <800>;
+				vactive = <480>;
+				hback-porch = <88>;
+				hfront-porch = <40>;
+				hsync-len = <0>;
+				vback-porch = <32>;
+				vfront-porch = <11>;
+				vsync-len = <1>;
+				clock = <0>;	/* unused but required */
+				bpp = <32>;	/* non-standard but required */
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/wm8505.dtsi b/arch/arm/boot/dts/wm8505.dtsi
new file mode 100644
index 0000000..b459691
--- /dev/null
+++ b/arch/arm/boot/dts/wm8505.dtsi
@@ -0,0 +1,143 @@
+/*
+ * wm8505.dtsi - Device tree file for Wondermedia WM8505 SoC
+ *
+ * Copyright (C) 2012 Tony Prisk <linux@prisktech.co.nz>
+ *
+ * Licensed under GPLv2 or later
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+	compatible = "wm,wm8505";
+
+	cpus {
+		cpu@0 {
+			compatible = "arm,arm926ejs";
+		};
+	};
+
+	soc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		ranges;
+		interrupt-parent = <&intc0>;
+
+		intc0: interrupt-controller@d8140000 {
+			compatible = "via,vt8500-intc";
+			interrupt-controller;
+			reg = <0xd8140000 0x10000>;
+			#interrupt-cells = <1>;
+		};
+
+		/* Secondary IC cascaded to intc0 */
+		intc1: interrupt-controller@d8150000 {
+			compatible = "via,vt8500-intc";
+			interrupt-controller;
+			#interrupt-cells = <1>;
+			reg = <0xD8150000 0x10000>;
+			interrupts = <56 57 58 59 60 61 62 63>;
+		};
+
+		gpio: gpio-controller@d8110000 {
+			compatible = "wm,wm8505-gpio";
+			gpio-controller;
+			reg = <0xd8110000 0x10000>;
+			#gpio-cells = <3>;
+		};
+
+		pmc@d8130000 {
+			compatible = "via,vt8500-pmc";
+			reg = <0xd8130000 0x1000>;
+			clocks {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				ref24: ref24M {
+					#clock-cells = <0>;
+					compatible = "fixed-clock";
+					clock-frequency = <24000000>;
+				};
+			};
+		};
+
+		timer@d8130100 {
+			compatible = "via,vt8500-timer";
+			reg = <0xd8130100 0x28>;
+			interrupts = <36>;
+		};
+
+		ehci@d8007100 {
+			compatible = "via,vt8500-ehci";
+			reg = <0xd8007100 0x200>;
+			interrupts = <43>;
+		};
+
+		uhci@d8007300 {
+			compatible = "platform-uhci";
+			reg = <0xd8007300 0x200>;
+			interrupts = <43>;
+		};
+
+		fb@d8050800 {
+			compatible = "wm,wm8505-fb";
+			reg = <0xd8050800 0x200>;
+			display = <&display>;
+			default-mode = <&mode0>;
+		};
+
+		ge_rops@d8050400 {
+			compatible = "wm,prizm-ge-rops";
+			reg = <0xd8050400 0x100>;
+		};
+
+		uart@d8200000 {
+			compatible = "via,vt8500-uart";
+			reg = <0xd8200000 0x1040>;
+			interrupts = <32>;
+			clocks = <&ref24>;
+		};
+
+		uart@d82b0000 {
+			compatible = "via,vt8500-uart";
+			reg = <0xd82b0000 0x1040>;
+			interrupts = <33>;
+			clocks = <&ref24>;
+		};
+
+		uart@d8210000 {
+			compatible = "via,vt8500-uart";
+			reg = <0xd8210000 0x1040>;
+			interrupts = <47>;
+			clocks = <&ref24>;
+		};
+
+		uart@d82c0000 {
+			compatible = "via,vt8500-uart";
+			reg = <0xd82c0000 0x1040>;
+			interrupts = <50>;
+			clocks = <&ref24>;
+		};
+
+		uart@d8370000 {
+			compatible = "via,vt8500-uart";
+			reg = <0xd8370000 0x1040>;
+			interrupts = <31>;
+			clocks = <&ref24>;
+		};
+
+		uart@d8380000 {
+			compatible = "via,vt8500-uart";
+			reg = <0xd8380000 0x1040>;
+			interrupts = <30>;
+			clocks = <&ref24>;
+		};
+
+		rtc@d8100000 {
+			compatible = "via,vt8500-rtc";
+			reg = <0xd8100000 0x10000>;
+			interrupts = <48>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/wm8650-mid.dts b/arch/arm/boot/dts/wm8650-mid.dts
new file mode 100644
index 0000000..cefd938
--- /dev/null
+++ b/arch/arm/boot/dts/wm8650-mid.dts
@@ -0,0 +1,36 @@
+/*
+ * wm8650-mid.dts - Device tree file for Wondermedia WM8650-MID Tablet
+ *
+ * Copyright (C) 2012 Tony Prisk <linux@prisktech.co.nz>
+ *
+ * Licensed under GPLv2 or later
+ */
+
+/dts-v1/;
+/include/ "wm8650.dtsi"
+
+/ {
+	model = "Wondermedia WM8650-MID Tablet";
+
+	/*
+	 * Display node is based on Sascha Hauer's patch on dri-devel.
+	 * Added a bpp property to calculate the size of the framebuffer
+	 * until the binding is formalized.
+	 */
+	display: display@0 {
+		modes {
+			mode0: mode@0 {
+				hactive = <800>;
+				vactive = <480>;
+				hback-porch = <88>;
+				hfront-porch = <40>;
+				hsync-len = <0>;
+				vback-porch = <32>;
+				vfront-porch = <11>;
+				vsync-len = <1>;
+				clock = <0>;	/* unused but required */
+				bpp = <16>;	/* non-standard but required */
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/wm8650.dtsi b/arch/arm/boot/dts/wm8650.dtsi
new file mode 100644
index 0000000..83b9467
--- /dev/null
+++ b/arch/arm/boot/dts/wm8650.dtsi
@@ -0,0 +1,147 @@
+/*
+ * wm8650.dtsi - Device tree file for Wondermedia WM8650 SoC
+ *
+ * Copyright (C) 2012 Tony Prisk <linux@prisktech.co.nz>
+ *
+ * Licensed under GPLv2 or later
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+	compatible = "wm,wm8650";
+
+	soc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		ranges;
+		interrupt-parent = <&intc0>;
+
+		intc0: interrupt-controller@d8140000 {
+			compatible = "via,vt8500-intc";
+			interrupt-controller;
+			reg = <0xd8140000 0x10000>;
+			#interrupt-cells = <1>;
+		};
+
+		/* Secondary IC cascaded to intc0 */
+		intc1: interrupt-controller@d8150000 {
+			compatible = "via,vt8500-intc";
+			interrupt-controller;
+			#interrupt-cells = <1>;
+			reg = <0xD8150000 0x10000>;
+			interrupts = <56 57 58 59 60 61 62 63>;
+		};
+
+		gpio: gpio-controller@d8110000 {
+			compatible = "wm,wm8650-gpio";
+			gpio-controller;
+			reg = <0xd8110000 0x10000>;
+			#gpio-cells = <3>;
+		};
+
+		pmc@d8130000 {
+			compatible = "via,vt8500-pmc";
+			reg = <0xd8130000 0x1000>;
+
+			clocks {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				ref25: ref25M {
+					#clock-cells = <0>;
+					compatible = "fixed-clock";
+					clock-frequency = <25000000>;
+				};
+
+				ref24: ref24M {
+					#clock-cells = <0>;
+					compatible = "fixed-clock";
+					clock-frequency = <24000000>;
+				};
+
+				plla: plla {
+					#clock-cells = <0>;
+					compatible = "wm,wm8650-pll-clock";
+					clocks = <&ref25>;
+					reg = <0x200>;
+				};
+
+				pllb: pllb {
+					#clock-cells = <0>;
+					compatible = "wm,wm8650-pll-clock";
+					clocks = <&ref25>;
+					reg = <0x204>;
+				};
+
+				arm: arm {
+					#clock-cells = <0>;
+					compatible = "via,vt8500-device-clock";
+					clocks = <&plla>;
+					divisor-reg = <0x300>;
+				};
+
+				sdhc: sdhc {
+					#clock-cells = <0>;
+					compatible = "via,vt8500-device-clock";
+					clocks = <&pllb>;
+					divisor-reg = <0x328>;
+					divisor-mask = <0x3f>;
+					enable-reg = <0x254>;
+					enable-bit = <18>;
+				};
+			};
+		};
+
+		timer@d8130100 {
+			compatible = "via,vt8500-timer";
+			reg = <0xd8130100 0x28>;
+			interrupts = <36>;
+		};
+
+		ehci@d8007900 {
+			compatible = "via,vt8500-ehci";
+			reg = <0xd8007900 0x200>;
+			interrupts = <43>;
+		};
+
+		uhci@d8007b00 {
+			compatible = "platform-uhci";
+			reg = <0xd8007b00 0x200>;
+			interrupts = <43>;
+		};
+
+		fb@d8050800 {
+			compatible = "wm,wm8505-fb";
+			reg = <0xd8050800 0x200>;
+			display = <&display>;
+			default-mode = <&mode0>;
+		};
+
+		ge_rops@d8050400 {
+			compatible = "wm,prizm-ge-rops";
+			reg = <0xd8050400 0x100>;
+		};
+
+		uart@d8200000 {
+			compatible = "via,vt8500-uart";
+			reg = <0xd8200000 0x1040>;
+			interrupts = <32>;
+			clocks = <&ref24>;
+		};
+
+		uart@d82b0000 {
+			compatible = "via,vt8500-uart";
+			reg = <0xd82b0000 0x1040>;
+			interrupts = <33>;
+			clocks = <&ref24>;
+		};
+
+		rtc@d8100000 {
+			compatible = "via,vt8500-rtc";
+			reg = <0xd8100000 0x10000>;
+			interrupts = <48>;
+		};
+	};
+};
diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c
index 1143c4d..b4c17cf 100644
--- a/arch/arm/common/dmabounce.c
+++ b/arch/arm/common/dmabounce.c
@@ -375,7 +375,7 @@ static int __dmabounce_sync_for_cpu(struct device *dev, dma_addr_t addr,
 
 	off = addr - buf->safe_dma_addr;
 
-	BUG_ON(buf->direction != dir);
+	BUG_ON(buf->direction != dir && buf->direction != DMA_BIDIRECTIONAL);
 
 	dev_dbg(dev, "%s: unsafe buffer %p (dma=%#x off=%#lx) mapped to %p (dma=%#x)\n",
 		__func__, buf->ptr, virt_to_dma(dev, buf->ptr), off,
@@ -415,7 +415,7 @@ static int __dmabounce_sync_for_device(struct device *dev, dma_addr_t addr,
 
 	off = addr - buf->safe_dma_addr;
 
-	BUG_ON(buf->direction != dir);
+	BUG_ON(buf->direction != dir && buf->direction != DMA_BIDIRECTIONAL);
 
 	dev_dbg(dev, "%s: unsafe buffer %p (dma=%#x off=%#lx) mapped to %p (dma=%#x)\n",
 		__func__, buf->ptr, virt_to_dma(dev, buf->ptr), off,
diff --git a/arch/arm/configs/afeb9260_defconfig b/arch/arm/configs/afeb9260_defconfig
index 2afdf67..c285a9d 100644
--- a/arch/arm/configs/afeb9260_defconfig
+++ b/arch/arm/configs/afeb9260_defconfig
@@ -39,7 +39,6 @@ CONFIG_MTD_BLOCK=y
 CONFIG_MTD_DATAFLASH=y
 CONFIG_MTD_NAND=y
 CONFIG_MTD_NAND_ATMEL=y
-CONFIG_MTD_NAND_ATMEL_ECC_SOFT=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=8192
 CONFIG_ATMEL_SSC=y
diff --git a/arch/arm/configs/armadillo800eva_defconfig b/arch/arm/configs/armadillo800eva_defconfig
index 90610c7..3d76407 100644
--- a/arch/arm/configs/armadillo800eva_defconfig
+++ b/arch/arm/configs/armadillo800eva_defconfig
@@ -7,6 +7,7 @@ CONFIG_LOG_BUF_SHIFT=16
 # CONFIG_IPC_NS is not set
 # CONFIG_PID_NS is not set
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_PERF_EVENTS=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
@@ -85,6 +86,7 @@ CONFIG_SERIAL_SH_SCI_NR_UARTS=8
 CONFIG_SERIAL_SH_SCI_CONSOLE=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
+CONFIG_I2C_GPIO=y
 CONFIG_I2C_SH_MOBILE=y
 # CONFIG_HWMON is not set
 CONFIG_MEDIA_SUPPORT=y
@@ -120,6 +122,8 @@ CONFIG_USB_ETH=m
 CONFIG_MMC=y
 CONFIG_MMC_SDHI=y
 CONFIG_MMC_SH_MMCIF=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_S35390A=y
 CONFIG_DMADEVICES=y
 CONFIG_SH_DMAE=y
 CONFIG_UIO=y
diff --git a/arch/arm/configs/at91rm9200_defconfig b/arch/arm/configs/at91rm9200_defconfig
index d54e2ac..4ae57a3 100644
--- a/arch/arm/configs/at91rm9200_defconfig
+++ b/arch/arm/configs/at91rm9200_defconfig
@@ -232,7 +232,7 @@ CONFIG_USB_GADGET=y
 CONFIG_USB_ETH=m
 CONFIG_USB_MASS_STORAGE=m
 CONFIG_MMC=y
-CONFIG_MMC_AT91=y
+CONFIG_MMC_ATMELMCI=y
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
 CONFIG_LEDS_GPIO=y
diff --git a/arch/arm/configs/at91sam9261_defconfig b/arch/arm/configs/at91sam9261_defconfig
index ade6b2f..1e8712e 100644
--- a/arch/arm/configs/at91sam9261_defconfig
+++ b/arch/arm/configs/at91sam9261_defconfig
@@ -128,7 +128,7 @@ CONFIG_USB_GADGETFS=m
 CONFIG_USB_FILE_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_MMC=y
-CONFIG_MMC_AT91=m
+CONFIG_MMC_ATMELMCI=m
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
 CONFIG_LEDS_GPIO=y
diff --git a/arch/arm/configs/at91sam9263_defconfig b/arch/arm/configs/at91sam9263_defconfig
index 1cf9626..d2050ca 100644
--- a/arch/arm/configs/at91sam9263_defconfig
+++ b/arch/arm/configs/at91sam9263_defconfig
@@ -61,7 +61,6 @@ CONFIG_MTD_DATAFLASH=y
 CONFIG_MTD_BLOCK2MTD=y
 CONFIG_MTD_NAND=y
 CONFIG_MTD_NAND_ATMEL=y
-CONFIG_MTD_NAND_ATMEL_ECC_SOFT=y
 CONFIG_MTD_UBI=y
 CONFIG_MTD_UBI_GLUEBI=y
 CONFIG_BLK_DEV_LOOP=y
@@ -138,7 +137,7 @@ CONFIG_USB_FILE_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_MMC=y
 CONFIG_SDIO_UART=m
-CONFIG_MMC_AT91=m
+CONFIG_MMC_ATMELMCI=m
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
 CONFIG_LEDS_ATMEL_PWM=y
diff --git a/arch/arm/configs/at91sam9g20_defconfig b/arch/arm/configs/at91sam9g20_defconfig
index 994d331..e1b0e80 100644
--- a/arch/arm/configs/at91sam9g20_defconfig
+++ b/arch/arm/configs/at91sam9g20_defconfig
@@ -99,7 +99,7 @@ CONFIG_USB_GADGETFS=m
 CONFIG_USB_FILE_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_MMC=y
-CONFIG_MMC_AT91=m
+CONFIG_MMC_ATMELMCI=m
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
 CONFIG_LEDS_GPIO=y
diff --git a/arch/arm/configs/at91sam9rl_defconfig b/arch/arm/configs/at91sam9rl_defconfig
index ad562ee..7cf8785 100644
--- a/arch/arm/configs/at91sam9rl_defconfig
+++ b/arch/arm/configs/at91sam9rl_defconfig
@@ -60,7 +60,7 @@ CONFIG_AT91SAM9X_WATCHDOG=y
 CONFIG_FB=y
 CONFIG_FB_ATMEL=y
 CONFIG_MMC=y
-CONFIG_MMC_AT91=m
+CONFIG_MMC_ATMELMCI=m
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_AT91SAM9=y
 CONFIG_EXT2_FS=y
diff --git a/arch/arm/configs/bcm2835_defconfig b/arch/arm/configs/bcm2835_defconfig
new file mode 100644
index 0000000..7aea702
--- /dev/null
+++ b/arch/arm/configs/bcm2835_defconfig
@@ -0,0 +1,95 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SYSVIPC=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+CONFIG_FHANDLE=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_LOG_BUF_SHIFT=18
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_DEVICE=y
+CONFIG_CPUSETS=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_RESOURCE_COUNTERS=y
+CONFIG_CGROUP_PERF=y
+CONFIG_CFS_BANDWIDTH=y
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_NAMESPACES=y
+CONFIG_SCHED_AUTOGROUP=y
+CONFIG_RELAY=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
+CONFIG_RD_XZ=y
+CONFIG_RD_LZO=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_EMBEDDED=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=y
+CONFIG_JUMP_LABEL=y
+# CONFIG_BLOCK is not set
+CONFIG_ARCH_BCM2835=y
+CONFIG_PREEMPT_VOLUNTARY=y
+CONFIG_AEABI=y
+CONFIG_COMPACTION=y
+CONFIG_KSM=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=65536
+CONFIG_CLEANCACHE=y
+CONFIG_SECCOMP=y
+CONFIG_CC_STACKPROTECTOR=y
+CONFIG_KEXEC=y
+CONFIG_CRASH_DUMP=y
+CONFIG_VFP=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_SUSPEND is not set
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_STANDALONE is not set
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+# CONFIG_VT is not set
+# CONFIG_UNIX98_PTYS is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_AMBA_PL011=y
+CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
+CONFIG_TTY_PRINTK=y
+# CONFIG_HW_RANDOM is not set
+# CONFIG_HWMON is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_IOMMU_SUPPORT is not set
+# CONFIG_FILE_LOCKING is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_INOTIFY_USER is not set
+# CONFIG_PROC_FS is not set
+# CONFIG_SYSFS is not set
+# CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_PRINTK_TIME=y
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_UNUSED_SYMBOLS=y
+CONFIG_LOCKUP_DETECTOR=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_MEMORY_INIT=y
+CONFIG_BOOT_PRINTK_DELAY=y
+CONFIG_SCHED_TRACER=y
+CONFIG_STACK_TRACER=y
+CONFIG_FUNCTION_PROFILER=y
+CONFIG_DYNAMIC_DEBUG=y
+CONFIG_KGDB=y
+CONFIG_KGDB_KDB=y
+CONFIG_TEST_KSTRTOX=y
+CONFIG_STRICT_DEVMEM=y
+CONFIG_DEBUG_LL=y
+CONFIG_EARLY_PRINTK=y
+# CONFIG_XZ_DEC_X86 is not set
+# CONFIG_XZ_DEC_POWERPC is not set
+# CONFIG_XZ_DEC_IA64 is not set
+# CONFIG_XZ_DEC_ARM is not set
+# CONFIG_XZ_DEC_ARMTHUMB is not set
+# CONFIG_XZ_DEC_SPARC is not set
diff --git a/arch/arm/configs/bcmring_defconfig b/arch/arm/configs/bcmring_defconfig
index 9e6a8fe..6c389d9 100644
--- a/arch/arm/configs/bcmring_defconfig
+++ b/arch/arm/configs/bcmring_defconfig
@@ -44,7 +44,6 @@ CONFIG_MTD_CFI_ADV_OPTIONS=y
 CONFIG_MTD_CFI_GEOMETRY=y
 # CONFIG_MTD_CFI_I2 is not set
 CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_VERIFY_WRITE=y
 CONFIG_MTD_NAND_BCM_UMI=y
 CONFIG_MTD_NAND_BCM_UMI_HWCS=y
 # CONFIG_MISC_DEVICES is not set
diff --git a/arch/arm/configs/cam60_defconfig b/arch/arm/configs/cam60_defconfig
index cedc92e..1457971 100644
--- a/arch/arm/configs/cam60_defconfig
+++ b/arch/arm/configs/cam60_defconfig
@@ -49,7 +49,6 @@ CONFIG_MTD_COMPLEX_MAPPINGS=y
 CONFIG_MTD_PLATRAM=m
 CONFIG_MTD_DATAFLASH=y
 CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_VERIFY_WRITE=y
 CONFIG_MTD_NAND_ATMEL=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
diff --git a/arch/arm/configs/corgi_defconfig b/arch/arm/configs/corgi_defconfig
index e53c475..4b8a25d 100644
--- a/arch/arm/configs/corgi_defconfig
+++ b/arch/arm/configs/corgi_defconfig
@@ -97,7 +97,6 @@ CONFIG_MTD_BLOCK=y
 CONFIG_MTD_ROM=y
 CONFIG_MTD_COMPLEX_MAPPINGS=y
 CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_VERIFY_WRITE=y
 CONFIG_MTD_NAND_SHARPSL=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_IDE=y
diff --git a/arch/arm/configs/cpu9260_defconfig b/arch/arm/configs/cpu9260_defconfig
index bbf729e..921480c 100644
--- a/arch/arm/configs/cpu9260_defconfig
+++ b/arch/arm/configs/cpu9260_defconfig
@@ -82,7 +82,7 @@ CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_ETH=m
 CONFIG_MMC=y
-CONFIG_MMC_AT91=m
+CONFIG_MMC_ATMELMCI=m
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
 CONFIG_LEDS_GPIO=y
diff --git a/arch/arm/configs/cpu9g20_defconfig b/arch/arm/configs/cpu9g20_defconfig
index e7d7942..ea116cb 100644
--- a/arch/arm/configs/cpu9g20_defconfig
+++ b/arch/arm/configs/cpu9g20_defconfig
@@ -82,7 +82,7 @@ CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_ETH=m
 CONFIG_MMC=y
-CONFIG_MMC_AT91=m
+CONFIG_MMC_ATMELMCI=m
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
 CONFIG_LEDS_GPIO=y
diff --git a/arch/arm/configs/ep93xx_defconfig b/arch/arm/configs/ep93xx_defconfig
index 8e97b2f..806005a 100644
--- a/arch/arm/configs/ep93xx_defconfig
+++ b/arch/arm/configs/ep93xx_defconfig
@@ -61,7 +61,6 @@ CONFIG_MTD_CFI_STAA=y
 CONFIG_MTD_ROM=y
 CONFIG_MTD_PHYSMAP=y
 CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_VERIFY_WRITE=y
 CONFIG_BLK_DEV_NBD=y
 CONFIG_EEPROM_LEGACY=y
 CONFIG_SCSI=y
diff --git a/arch/arm/configs/imx_v6_v7_defconfig b/arch/arm/configs/imx_v6_v7_defconfig
index 3c9f32f..66aa7a6 100644
--- a/arch/arm/configs/imx_v6_v7_defconfig
+++ b/arch/arm/configs/imx_v6_v7_defconfig
@@ -32,9 +32,7 @@ CONFIG_MACH_VPR200=y
 CONFIG_MACH_IMX51_DT=y
 CONFIG_MACH_MX51_3DS=y
 CONFIG_MACH_EUKREA_CPUIMX51SD=y
-CONFIG_MACH_MX51_EFIKAMX=y
-CONFIG_MACH_MX51_EFIKASB=y
-CONFIG_MACH_IMX53_DT=y
+CONFIG_SOC_IMX53=y
 CONFIG_SOC_IMX6Q=y
 CONFIG_MXC_PWM=y
 CONFIG_SMP=y
@@ -42,7 +40,6 @@ CONFIG_VMSPLIT_2G=y
 CONFIG_PREEMPT_VOLUNTARY=y
 CONFIG_AEABI=y
 # CONFIG_OABI_COMPAT is not set
-CONFIG_DEFAULT_MMAP_MIN_ADDR=32768
 CONFIG_CMDLINE="noinitrd console=ttymxc0,115200"
 CONFIG_VFP=y
 CONFIG_NEON=y
@@ -179,6 +176,9 @@ CONFIG_SND_SOC_IMX_MC13783=y
 CONFIG_USB=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_MXC=y
+CONFIG_USB_CHIPIDEA=y
+CONFIG_USB_CHIPIDEA_HOST=y
+CONFIG_USB_MXS_PHY=y
 CONFIG_USB_STORAGE=y
 CONFIG_MMC=y
 CONFIG_MMC_SDHCI=y
diff --git a/arch/arm/configs/kirkwood_defconfig b/arch/arm/configs/kirkwood_defconfig
index aeb3af5..74eee0c 100644
--- a/arch/arm/configs/kirkwood_defconfig
+++ b/arch/arm/configs/kirkwood_defconfig
@@ -1,5 +1,7 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
 CONFIG_LOG_BUF_SHIFT=19
 CONFIG_PROFILING=y
 CONFIG_OPROFILE=y
@@ -15,9 +17,19 @@ CONFIG_MACH_MV88F6281GTW_GE=y
 CONFIG_MACH_SHEEVAPLUG=y
 CONFIG_MACH_ESATA_SHEEVAPLUG=y
 CONFIG_MACH_GURUPLUG=y
-CONFIG_MACH_DOCKSTAR=y
+CONFIG_MACH_DREAMPLUG_DT=y
+CONFIG_MACH_ICONNECT_DT=y
+CONFIG_MACH_DLINK_KIRKWOOD_DT=y
+CONFIG_MACH_IB62X0_DT=y
+CONFIG_MACH_TS219_DT=y
+CONFIG_MACH_DOCKSTAR_DT=y
+CONFIG_MACH_GOFLEXNET_DT=y
+CONFIG_MACH_LSXL_DT=y
+CONFIG_MACH_IOMEGA_IX2_200_DT=y
+CONFIG_MACH_KM_KIRKWOOD_DT=y
 CONFIG_MACH_TS219=y
 CONFIG_MACH_TS41X=y
+CONFIG_MACH_DOCKSTAR=y
 CONFIG_MACH_OPENRD_BASE=y
 CONFIG_MACH_OPENRD_CLIENT=y
 CONFIG_MACH_OPENRD_ULTIMATE=y
@@ -29,8 +41,6 @@ CONFIG_MACH_NET2BIG_V2=y
 CONFIG_MACH_NET5BIG_V2=y
 CONFIG_MACH_T5325=y
 # CONFIG_CPU_FEROCEON_OLD_ID is not set
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
 # CONFIG_OABI_COMPAT is not set
@@ -47,13 +57,11 @@ CONFIG_IP_PNP_DHCP=y
 CONFIG_IP_PNP_BOOTP=y
 # CONFIG_IPV6 is not set
 CONFIG_NET_DSA=y
-CONFIG_NET_DSA_MV88E6123_61_65=y
 CONFIG_NET_PKTGEN=m
 CONFIG_CFG80211=y
 CONFIG_MAC80211=y
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
@@ -69,7 +77,6 @@ CONFIG_MTD_M25P80=y
 CONFIG_MTD_NAND=y
 CONFIG_MTD_NAND_ORION=y
 CONFIG_BLK_DEV_LOOP=y
-# CONFIG_MISC_DEVICES is not set
 # CONFIG_SCSI_PROC_FS is not set
 CONFIG_BLK_DEV_SD=y
 CONFIG_BLK_DEV_SR=m
@@ -78,22 +85,21 @@ CONFIG_ATA=y
 CONFIG_SATA_AHCI=y
 CONFIG_SATA_MV=y
 CONFIG_NETDEVICES=y
-CONFIG_MARVELL_PHY=y
-CONFIG_NET_ETHERNET=y
 CONFIG_MII=y
-CONFIG_NET_PCI=y
+CONFIG_NET_DSA_MV88E6123_61_65=y
 CONFIG_MV643XX_ETH=y
-# CONFIG_NETDEV_10000 is not set
+CONFIG_MARVELL_PHY=y
 CONFIG_LIBERTAS=y
 CONFIG_LIBERTAS_SDIO=y
 CONFIG_INPUT_EVDEV=y
 CONFIG_KEYBOARD_GPIO=y
 # CONFIG_INPUT_MOUSE is not set
+CONFIG_LEGACY_PTY_COUNT=16
 # CONFIG_DEVKMEM is not set
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_RUNTIME_UARTS=2
-CONFIG_LEGACY_PTY_COUNT=16
+CONFIG_SERIAL_OF_PLATFORM=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
 # CONFIG_I2C_COMPAT is not set
@@ -103,7 +109,8 @@ CONFIG_SPI=y
 CONFIG_SPI_ORION=y
 CONFIG_GPIO_SYSFS=y
 # CONFIG_HWMON is not set
-# CONFIG_VGA_CONSOLE is not set
+CONFIG_WATCHDOG=y
+CONFIG_ORION_WATCHDOG=y
 CONFIG_HID_DRAGONRISE=y
 CONFIG_HID_GYRATION=y
 CONFIG_HID_TWINHAN=y
@@ -119,10 +126,8 @@ CONFIG_HID_TOPSEED=y
 CONFIG_HID_THRUSTMASTER=y
 CONFIG_HID_ZEROPLUS=y
 CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_ROOT_HUB_TT=y
-CONFIG_USB_EHCI_TT_NEWSCHED=y
 CONFIG_USB_PRINTER=m
 CONFIG_USB_STORAGE=y
 CONFIG_USB_STORAGE_DATAFAB=y
@@ -148,7 +153,6 @@ CONFIG_MV_XOR=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_FS_XATTR is not set
-CONFIG_INOTIFY=y
 CONFIG_ISO9660_FS=m
 CONFIG_JOLIET=y
 CONFIG_UDF_FS=m
@@ -158,7 +162,6 @@ CONFIG_TMPFS=y
 CONFIG_JFFS2_FS=y
 CONFIG_CRAMFS=y
 CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
 CONFIG_ROOT_NFS=y
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_CODEPAGE_850=y
@@ -171,11 +174,8 @@ CONFIG_DEBUG_KERNEL=y
 # CONFIG_SCHED_DEBUG is not set
 # CONFIG_DEBUG_PREEMPT is not set
 CONFIG_DEBUG_INFO=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
 # CONFIG_FTRACE is not set
 CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_ERRORS=y
 CONFIG_DEBUG_LL=y
 CONFIG_CRYPTO_CBC=m
 CONFIG_CRYPTO_PCBC=m
diff --git a/arch/arm/configs/kzm9d_defconfig b/arch/arm/configs/kzm9d_defconfig
index 26146ff..8c49df6 100644
--- a/arch/arm/configs/kzm9d_defconfig
+++ b/arch/arm/configs/kzm9d_defconfig
@@ -8,6 +8,7 @@ CONFIG_LOG_BUF_SHIFT=16
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SYSCTL_SYSCALL=y
 CONFIG_EMBEDDED=y
+CONFIG_PERF_EVENTS=y
 CONFIG_SLAB=y
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_IOSCHED_DEADLINE is not set
diff --git a/arch/arm/configs/kzm9g_defconfig b/arch/arm/configs/kzm9g_defconfig
index 2388c86..ce99e3e 100644
--- a/arch/arm/configs/kzm9g_defconfig
+++ b/arch/arm/configs/kzm9g_defconfig
@@ -14,6 +14,7 @@ CONFIG_NAMESPACES=y
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SYSCTL_SYSCALL=y
 CONFIG_EMBEDDED=y
+CONFIG_PERF_EVENTS=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_FORCE_LOAD=y
@@ -22,7 +23,6 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_IOSCHED_DEADLINE is not set
 # CONFIG_IOSCHED_CFQ is not set
 CONFIG_ARCH_SHMOBILE=y
-CONFIG_KEYBOARD_GPIO_POLLED=y
 CONFIG_ARCH_SH73A0=y
 CONFIG_MACH_KZM9G=y
 CONFIG_MEMORY_START=0x41000000
@@ -70,9 +70,12 @@ CONFIG_INPUT_SPARSEKMAP=y
 # CONFIG_INPUT_MOUSEDEV is not set
 CONFIG_INPUT_EVDEV=y
 # CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_GPIO=y
 # CONFIG_INPUT_MOUSE is not set
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_ST1232=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_ADXL34X=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_SERIAL_SH_SCI=y
 CONFIG_SERIAL_SH_SCI_NR_UARTS=9
@@ -118,6 +121,8 @@ CONFIG_DMADEVICES=y
 CONFIG_SH_DMAE=y
 CONFIG_ASYNC_TX_DMA=y
 CONFIG_STAGING=y
+CONFIG_SENSORS_AK8975=y
+CONFIG_IIO=y
 # CONFIG_DNOTIFY is not set
 CONFIG_INOTIFY_USER=y
 CONFIG_VFAT_FS=y
diff --git a/arch/arm/configs/lpc32xx_defconfig b/arch/arm/configs/lpc32xx_defconfig
index e42a0e3..92386b2 100644
--- a/arch/arm/configs/lpc32xx_defconfig
+++ b/arch/arm/configs/lpc32xx_defconfig
@@ -133,7 +133,6 @@ CONFIG_SND_DEBUG_VERBOSE=y
 # CONFIG_SND_ARM is not set
 # CONFIG_SND_SPI is not set
 CONFIG_SND_SOC=y
-# CONFIG_HID_SUPPORT is not set
 CONFIG_USB=y
 CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_STORAGE=y
@@ -149,6 +148,7 @@ CONFIG_LEDS_CLASS=y
 CONFIG_LEDS_PCA9532=y
 CONFIG_LEDS_PCA9532_GPIO=y
 CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_PWM=y
 CONFIG_LEDS_TRIGGERS=y
 CONFIG_LEDS_TRIGGER_TIMER=y
 CONFIG_LEDS_TRIGGER_HEARTBEAT=y
@@ -161,10 +161,13 @@ CONFIG_RTC_DRV_DS1374=y
 CONFIG_RTC_DRV_PCF8563=y
 CONFIG_RTC_DRV_LPC32XX=y
 CONFIG_DMADEVICES=y
+CONFIG_AMBA_PL08X=y
 CONFIG_STAGING=y
 CONFIG_LPC32XX_ADC=y
-CONFIG_MAX517=y
 CONFIG_IIO=y
+CONFIG_MAX517=y
+CONFIG_PWM=y
+CONFIG_PWM_LPC32XX=y
 CONFIG_EXT2_FS=y
 CONFIG_AUTOFS4_FS=y
 CONFIG_MSDOS_FS=y
diff --git a/arch/arm/configs/marzen_defconfig b/arch/arm/configs/marzen_defconfig
index 864f9a5..53382b6 100644
--- a/arch/arm/configs/marzen_defconfig
+++ b/arch/arm/configs/marzen_defconfig
@@ -1,13 +1,14 @@
 # CONFIG_ARM_PATCH_PHYS_VIRT is not set
 CONFIG_EXPERIMENTAL=y
 CONFIG_KERNEL_LZMA=y
+CONFIG_NO_HZ=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=16
 CONFIG_SYSCTL_SYSCALL=y
 CONFIG_EMBEDDED=y
 CONFIG_SLAB=y
-# CONFIG_BLOCK is not set
+# CONFIG_IOSCHED_CFQ is not set
 CONFIG_ARCH_SHMOBILE=y
 CONFIG_ARCH_R8A7779=y
 CONFIG_MACH_MARZEN=y
@@ -21,7 +22,6 @@ CONFIG_ARM_ERRATA_458693=y
 CONFIG_ARM_ERRATA_460075=y
 CONFIG_ARM_ERRATA_743622=y
 CONFIG_ARM_ERRATA_754322=y
-CONFIG_NO_HZ=y
 CONFIG_SMP=y
 # CONFIG_ARM_CPU_TOPOLOGY is not set
 CONFIG_AEABI=y
@@ -29,13 +29,16 @@ CONFIG_AEABI=y
 CONFIG_HIGHMEM=y
 CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="console=ttySC2,115200 earlyprintk=sh-sci.2,115200 ignore_loglevel"
+CONFIG_CMDLINE="console=ttySC2,115200 earlyprintk=sh-sci.2,115200 ignore_loglevel root=/dev/nfs ip=on"
 CONFIG_CMDLINE_FORCE=y
 CONFIG_KEXEC=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 CONFIG_PM_RUNTIME=y
 CONFIG_NET=y
+CONFIG_UNIX=y
 CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
 # CONFIG_IPV6 is not set
 # CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
@@ -68,17 +71,21 @@ CONFIG_SERIAL_SH_SCI_CONSOLE=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_GPIO_SYSFS=y
 # CONFIG_HWMON is not set
+CONFIG_THERMAL=y
+CONFIG_RCAR_THERMAL=y
 CONFIG_SSB=y
-# CONFIG_HID_SUPPORT is not set
 # CONFIG_USB_SUPPORT is not set
+CONFIG_MMC=y
+CONFIG_MMC_SDHI=y
 CONFIG_UIO=y
 CONFIG_UIO_PDRV_GENIRQ=y
 # CONFIG_IOMMU_SUPPORT is not set
-# CONFIG_FILE_LOCKING is not set
 # CONFIG_DNOTIFY is not set
 # CONFIG_INOTIFY_USER is not set
 CONFIG_TMPFS=y
 # CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_NFS_FS=y
+CONFIG_ROOT_NFS=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_INFO=y
 CONFIG_DEBUG_INFO_REDUCED=y
diff --git a/arch/arm/configs/mini2440_defconfig b/arch/arm/configs/mini2440_defconfig
index 082175c..00630e6 100644
--- a/arch/arm/configs/mini2440_defconfig
+++ b/arch/arm/configs/mini2440_defconfig
@@ -102,7 +102,6 @@ CONFIG_MTD_CFI_STAA=y
 CONFIG_MTD_RAM=y
 CONFIG_MTD_ROM=y
 CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_VERIFY_WRITE=y
 CONFIG_MTD_NAND_S3C2410=y
 CONFIG_MTD_NAND_PLATFORM=y
 CONFIG_MTD_LPDDR=y
diff --git a/arch/arm/configs/mmp2_defconfig b/arch/arm/configs/mmp2_defconfig
index 5a58452..f1cb95e 100644
--- a/arch/arm/configs/mmp2_defconfig
+++ b/arch/arm/configs/mmp2_defconfig
@@ -16,7 +16,7 @@ CONFIG_PREEMPT=y
 CONFIG_AEABI=y
 CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="root=/dev/nfs rootfstype=nfs nfsroot=192.168.1.100:/nfsroot/ ip=192.168.1.101:192.168.1.100::255.255.255.0::eth0:on console=ttyS2,38400 mem=128M user_debug=255"
+CONFIG_CMDLINE="root=/dev/nfs rootfstype=nfs nfsroot=192.168.1.100:/nfsroot/ ip=192.168.1.101:192.168.1.100::255.255.255.0::eth0:on console=ttyS2,38400 mem=128M user_debug=255 earlyprintk"
 CONFIG_VFP=y
 CONFIG_NET=y
 CONFIG_PACKET=y
@@ -90,6 +90,9 @@ CONFIG_DEBUG_INFO=y
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_DYNAMIC_DEBUG is not set
 CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_LL=y
+CONFIG_DEBUG_MMP_UART3=y
+CONFIG_EARLY_PRINTK=y
 CONFIG_DEBUG_ERRORS=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRC_CCITT=y
diff --git a/arch/arm/configs/mv78xx0_defconfig b/arch/arm/configs/mv78xx0_defconfig
index 7305ebd..1f08219 100644
--- a/arch/arm/configs/mv78xx0_defconfig
+++ b/arch/arm/configs/mv78xx0_defconfig
@@ -49,7 +49,6 @@ CONFIG_MTD_CFI_INTELEXT=y
 CONFIG_MTD_CFI_AMDSTD=y
 CONFIG_MTD_PHYSMAP=y
 CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_VERIFY_WRITE=y
 CONFIG_MTD_NAND_ORION=y
 CONFIG_BLK_DEV_LOOP=y
 # CONFIG_SCSI_PROC_FS is not set
diff --git a/arch/arm/configs/mvebu_defconfig b/arch/arm/configs/mvebu_defconfig
index 2e86b31..7bcf850 100644
--- a/arch/arm/configs/mvebu_defconfig
+++ b/arch/arm/configs/mvebu_defconfig
@@ -21,6 +21,8 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_SYSFS=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_FS_XATTR is not set
diff --git a/arch/arm/configs/mxs_defconfig b/arch/arm/configs/mxs_defconfig
index 4edcfb4..048aaca 100644
--- a/arch/arm/configs/mxs_defconfig
+++ b/arch/arm/configs/mxs_defconfig
@@ -23,12 +23,6 @@ CONFIG_BLK_DEV_INTEGRITY=y
 # CONFIG_IOSCHED_CFQ is not set
 CONFIG_ARCH_MXS=y
 CONFIG_MACH_MXS_DT=y
-CONFIG_MACH_MX23EVK=y
-CONFIG_MACH_MX28EVK=y
-CONFIG_MACH_STMP378X_DEVB=y
-CONFIG_MACH_TX28=y
-CONFIG_MACH_M28EVK=y
-CONFIG_MACH_APX4DEVKIT=y
 # CONFIG_ARM_THUMB is not set
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
@@ -59,6 +53,9 @@ CONFIG_DEVTMPFS=y
 # CONFIG_FIRMWARE_IN_KERNEL is not set
 # CONFIG_BLK_DEV is not set
 CONFIG_MTD=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_DATAFLASH=y
+CONFIG_MTD_M25P80
 CONFIG_MTD_NAND=y
 CONFIG_MTD_NAND_GPMI_NAND=y
 CONFIG_NETDEVICES=y
@@ -88,13 +85,13 @@ CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_MXS=y
 CONFIG_SPI=y
 CONFIG_SPI_GPIO=m
+CONFIG_SPI_MXS=y
 CONFIG_DEBUG_GPIO=y
 CONFIG_GPIO_SYSFS=y
 # CONFIG_HWMON is not set
 # CONFIG_MFD_SUPPORT is not set
 CONFIG_DISPLAY_SUPPORT=m
 # CONFIG_HID_SUPPORT is not set
-# CONFIG_USB_SUPPORT is not set
 CONFIG_SOUND=y
 CONFIG_SND=y
 CONFIG_SND_TIMER=y
@@ -109,14 +106,45 @@ CONFIG_SND_SOC_I2C_AND_SPI=y
 CONFIG_SND_SOC_SGTL5000=y
 CONFIG_REGULATOR=y
 CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_FB=y
+CONFIG_FB_MXS=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_PWM=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FONTS=y
+CONFIG_LOGO=y
+CONFIG_USB=y
+CONFIG_USB_CHIPIDEA=y
+CONFIG_USB_CHIPIDEA_HOST=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_MXS_PHY=y
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
 CONFIG_MMC=y
 CONFIG_MMC_MXS=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_ONESHOT=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_BACKLIGHT=y
+CONFIG_LEDS_TRIGGER_GPIO=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_DS1307=m
 CONFIG_RTC_DRV_STMP=y
 CONFIG_DMADEVICES=y
 CONFIG_MXS_DMA=y
+CONFIG_STAGING=y
+CONFIG_MXS_LRADC=y
+CONFIG_IIO_SYSFS_TRIGGER=y
 CONFIG_COMMON_CLK_DEBUG=y
+CONFIG_IIO=y
+CONFIG_PWM=y
+CONFIG_PWM_MXS=y
 CONFIG_EXT3_FS=y
 # CONFIG_DNOTIFY is not set
 CONFIG_FSCACHE=m
diff --git a/arch/arm/configs/nhk8815_defconfig b/arch/arm/configs/nhk8815_defconfig
index bf123c5..240b25e 100644
--- a/arch/arm/configs/nhk8815_defconfig
+++ b/arch/arm/configs/nhk8815_defconfig
@@ -57,7 +57,6 @@ CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_NAND=y
 CONFIG_MTD_NAND_ECC_SMC=y
-CONFIG_MTD_NAND_VERIFY_WRITE=y
 CONFIG_MTD_NAND_NOMADIK=y
 CONFIG_MTD_ONENAND=y
 CONFIG_MTD_ONENAND_VERIFY_WRITE=y
diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig
index e58edc3..6230304 100644
--- a/arch/arm/configs/omap2plus_defconfig
+++ b/arch/arm/configs/omap2plus_defconfig
@@ -123,6 +123,7 @@ CONFIG_HW_RANDOM=y
 CONFIG_I2C_CHARDEV=y
 CONFIG_SPI=y
 CONFIG_SPI_OMAP24XX=y
+CONFIG_PINCTRL_SINGLE=y
 CONFIG_DEBUG_GPIO=y
 CONFIG_GPIO_SYSFS=y
 CONFIG_GPIO_TWL4030=y
diff --git a/arch/arm/configs/orion5x_defconfig b/arch/arm/configs/orion5x_defconfig
index a288d70..cd5e6ba 100644
--- a/arch/arm/configs/orion5x_defconfig
+++ b/arch/arm/configs/orion5x_defconfig
@@ -72,7 +72,6 @@ CONFIG_MTD_CFI_INTELEXT=y
 CONFIG_MTD_CFI_AMDSTD=y
 CONFIG_MTD_PHYSMAP=y
 CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_VERIFY_WRITE=y
 CONFIG_MTD_NAND_PLATFORM=y
 CONFIG_MTD_NAND_ORION=y
 CONFIG_BLK_DEV_LOOP=y
diff --git a/arch/arm/configs/pnx4008_defconfig b/arch/arm/configs/pnx4008_defconfig
deleted file mode 100644
index 35a31cc..0000000
--- a/arch/arm/configs/pnx4008_defconfig
+++ /dev/null
@@ -1,472 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-CONFIG_SYSVIPC=y
-CONFIG_POSIX_MQUEUE=y
-CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_AUDIT=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_EXPERT=y
-CONFIG_SLAB=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODULE_FORCE_UNLOAD=y
-CONFIG_MODVERSIONS=y
-CONFIG_MODULE_SRCVERSION_ALL=y
-CONFIG_ARCH_PNX4008=y
-CONFIG_PREEMPT=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="mem=64M console=ttyS0,115200"
-CONFIG_FPE_NWFPE=y
-CONFIG_BINFMT_AOUT=m
-CONFIG_BINFMT_MISC=m
-CONFIG_PM=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-CONFIG_IP_ADVANCED_ROUTER=y
-CONFIG_IP_MULTIPLE_TABLES=y
-CONFIG_IP_ROUTE_MULTIPATH=y
-CONFIG_IP_ROUTE_VERBOSE=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-CONFIG_IP_MROUTE=y
-CONFIG_IP_PIMSM_V1=y
-CONFIG_IP_PIMSM_V2=y
-CONFIG_SYN_COOKIES=y
-CONFIG_INET_AH=m
-CONFIG_INET_ESP=m
-CONFIG_INET_IPCOMP=m
-CONFIG_IPV6_PRIVACY=y
-CONFIG_INET6_AH=m
-CONFIG_INET6_ESP=m
-CONFIG_INET6_IPCOMP=m
-CONFIG_IPV6_TUNNEL=m
-CONFIG_NETFILTER=y
-CONFIG_IP_VS=m
-CONFIG_IP_VS_PROTO_TCP=y
-CONFIG_IP_VS_PROTO_UDP=y
-CONFIG_IP_VS_PROTO_ESP=y
-CONFIG_IP_VS_PROTO_AH=y
-CONFIG_IP_VS_RR=m
-CONFIG_IP_VS_WRR=m
-CONFIG_IP_VS_LC=m
-CONFIG_IP_VS_WLC=m
-CONFIG_IP_VS_LBLC=m
-CONFIG_IP_VS_LBLCR=m
-CONFIG_IP_VS_DH=m
-CONFIG_IP_VS_SH=m
-CONFIG_IP_VS_SED=m
-CONFIG_IP_VS_NQ=m
-CONFIG_IP_VS_FTP=m
-CONFIG_IP_NF_QUEUE=m
-CONFIG_IP6_NF_QUEUE=m
-CONFIG_DECNET_NF_GRABULATOR=m
-CONFIG_BRIDGE_NF_EBTABLES=m
-CONFIG_BRIDGE_EBT_BROUTE=m
-CONFIG_BRIDGE_EBT_T_FILTER=m
-CONFIG_BRIDGE_EBT_T_NAT=m
-CONFIG_BRIDGE_EBT_802_3=m
-CONFIG_BRIDGE_EBT_AMONG=m
-CONFIG_BRIDGE_EBT_ARP=m
-CONFIG_BRIDGE_EBT_IP=m
-CONFIG_BRIDGE_EBT_LIMIT=m
-CONFIG_BRIDGE_EBT_MARK=m
-CONFIG_BRIDGE_EBT_PKTTYPE=m
-CONFIG_BRIDGE_EBT_STP=m
-CONFIG_BRIDGE_EBT_VLAN=m
-CONFIG_BRIDGE_EBT_ARPREPLY=m
-CONFIG_BRIDGE_EBT_DNAT=m
-CONFIG_BRIDGE_EBT_MARK_T=m
-CONFIG_BRIDGE_EBT_REDIRECT=m
-CONFIG_BRIDGE_EBT_SNAT=m
-CONFIG_BRIDGE_EBT_LOG=m
-CONFIG_IP_SCTP=m
-CONFIG_ATM=y
-CONFIG_ATM_CLIP=y
-CONFIG_ATM_LANE=m
-CONFIG_ATM_MPOA=m
-CONFIG_ATM_BR2684=m
-CONFIG_BRIDGE=m
-CONFIG_VLAN_8021Q=m
-CONFIG_DECNET=m
-CONFIG_LLC2=m
-CONFIG_IPX=m
-CONFIG_ATALK=m
-CONFIG_DEV_APPLETALK=m
-CONFIG_IPDDP=m
-CONFIG_IPDDP_ENCAP=y
-CONFIG_IPDDP_DECAP=y
-CONFIG_X25=m
-CONFIG_LAPB=m
-CONFIG_ECONET=m
-CONFIG_ECONET_AUNUDP=y
-CONFIG_ECONET_NATIVE=y
-CONFIG_WAN_ROUTER=m
-CONFIG_NET_SCHED=y
-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_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_CLS_TCINDEX=m
-CONFIG_NET_CLS_ROUTE4=m
-CONFIG_NET_CLS_FW=m
-CONFIG_NET_CLS_U32=m
-CONFIG_NET_CLS_RSVP=m
-CONFIG_NET_CLS_RSVP6=m
-CONFIG_NET_PKTGEN=m
-CONFIG_MTD=y
-CONFIG_MTD_CONCAT=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_REDBOOT_PARTS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_SLRAM=m
-CONFIG_MTD_PHRAM=m
-CONFIG_MTD_MTDRAM=m
-CONFIG_MTD_DOC2000=m
-CONFIG_MTD_DOC2001=m
-CONFIG_MTD_DOC2001PLUS=m
-CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_NANDSIM=m
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_CRYPTOLOOP=y
-CONFIG_BLK_DEV_NBD=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=8192
-CONFIG_CDROM_PKTCDVD=m
-CONFIG_EEPROM_LEGACY=m
-CONFIG_SCSI=m
-CONFIG_BLK_DEV_SD=m
-CONFIG_CHR_DEV_ST=m
-CONFIG_CHR_DEV_OSST=m
-CONFIG_BLK_DEV_SR=m
-CONFIG_CHR_DEV_SG=m
-CONFIG_CHR_DEV_SCH=m
-CONFIG_SCSI_MULTI_LUN=y
-CONFIG_SCSI_CONSTANTS=y
-CONFIG_SCSI_LOGGING=y
-CONFIG_SCSI_SPI_ATTRS=m
-CONFIG_SCSI_FC_ATTRS=m
-CONFIG_SCSI_DEBUG=m
-CONFIG_NETDEVICES=y
-CONFIG_DUMMY=m
-CONFIG_BONDING=m
-CONFIG_EQUALIZER=m
-CONFIG_TUN=m
-CONFIG_NET_ETHERNET=y
-CONFIG_USB_CATC=m
-CONFIG_USB_KAWETH=m
-CONFIG_USB_PEGASUS=m
-CONFIG_USB_RTL8150=m
-CONFIG_USB_USBNET=m
-# CONFIG_USB_NET_CDC_SUBSET is not set
-CONFIG_WAN=y
-CONFIG_HDLC=m
-CONFIG_HDLC_RAW=m
-CONFIG_HDLC_RAW_ETH=m
-CONFIG_HDLC_CISCO=m
-CONFIG_HDLC_FR=m
-CONFIG_HDLC_PPP=m
-CONFIG_HDLC_X25=m
-CONFIG_DLCI=m
-CONFIG_WAN_ROUTER_DRIVERS=m
-CONFIG_LAPBETHER=m
-CONFIG_X25_ASY=m
-CONFIG_ATM_TCP=m
-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_PPPOATM=m
-CONFIG_SLIP=m
-CONFIG_SLIP_COMPRESSED=y
-CONFIG_SLIP_SMART=y
-CONFIG_SLIP_MODE_SLIP6=y
-CONFIG_NETCONSOLE=m
-# CONFIG_INPUT_MOUSEDEV is not set
-CONFIG_INPUT_JOYDEV=m
-CONFIG_INPUT_EVDEV=m
-CONFIG_INPUT_EVBUG=m
-CONFIG_KEYBOARD_LKKBD=m
-CONFIG_KEYBOARD_NEWTON=m
-CONFIG_KEYBOARD_SUNKBD=m
-CONFIG_KEYBOARD_XTKBD=m
-CONFIG_MOUSE_PS2=m
-CONFIG_MOUSE_SERIAL=m
-CONFIG_MOUSE_VSXXXAA=m
-CONFIG_INPUT_JOYSTICK=y
-CONFIG_JOYSTICK_ANALOG=m
-CONFIG_JOYSTICK_A3D=m
-CONFIG_JOYSTICK_ADI=m
-CONFIG_JOYSTICK_COBRA=m
-CONFIG_JOYSTICK_GF2K=m
-CONFIG_JOYSTICK_GRIP=m
-CONFIG_JOYSTICK_GRIP_MP=m
-CONFIG_JOYSTICK_GUILLEMOT=m
-CONFIG_JOYSTICK_INTERACT=m
-CONFIG_JOYSTICK_SIDEWINDER=m
-CONFIG_JOYSTICK_TMDC=m
-CONFIG_JOYSTICK_IFORCE=m
-CONFIG_JOYSTICK_IFORCE_USB=y
-CONFIG_JOYSTICK_IFORCE_232=y
-CONFIG_JOYSTICK_WARRIOR=m
-CONFIG_JOYSTICK_MAGELLAN=m
-CONFIG_JOYSTICK_SPACEORB=m
-CONFIG_JOYSTICK_SPACEBALL=m
-CONFIG_JOYSTICK_STINGER=m
-CONFIG_JOYSTICK_JOYDUMP=m
-CONFIG_INPUT_TOUCHSCREEN=y
-CONFIG_TOUCHSCREEN_GUNZE=m
-CONFIG_INPUT_MISC=y
-CONFIG_INPUT_UINPUT=m
-CONFIG_SERIO_SERPORT=m
-CONFIG_SERIO_RAW=m
-CONFIG_GAMEPORT_NS558=m
-CONFIG_GAMEPORT_L4=m
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_EXTENDED=y
-CONFIG_SERIAL_8250_MANY_PORTS=y
-CONFIG_SERIAL_8250_SHARE_IRQ=y
-CONFIG_SERIAL_8250_RSA=y
-CONFIG_HW_RANDOM=y
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_SPI=y
-CONFIG_SPI_BITBANG=y
-# CONFIG_HWMON is not set
-CONFIG_WATCHDOG=y
-CONFIG_SOFT_WATCHDOG=m
-CONFIG_USBPCWATCHDOG=m
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_SOUND=m
-CONFIG_SND=m
-CONFIG_SND_SEQUENCER=m
-CONFIG_SND_SEQ_DUMMY=m
-CONFIG_SND_MIXER_OSS=m
-CONFIG_SND_PCM_OSS=m
-CONFIG_SND_SEQUENCER_OSS=y
-CONFIG_SND_DUMMY=m
-CONFIG_SND_VIRMIDI=m
-CONFIG_SND_MTPAV=m
-CONFIG_SND_SERIAL_U16550=m
-CONFIG_SND_MPU401=m
-CONFIG_SND_USB_AUDIO=m
-CONFIG_SOUND_PRIME=m
-CONFIG_USB_HID=m
-CONFIG_USB_HIDDEV=y
-CONFIG_USB_KBD=m
-CONFIG_USB_MOUSE=m
-CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
-CONFIG_USB_MON=y
-CONFIG_USB_SL811_HCD=m
-CONFIG_USB_ACM=m
-CONFIG_USB_PRINTER=m
-CONFIG_USB_STORAGE=m
-CONFIG_USB_STORAGE_DATAFAB=m
-CONFIG_USB_STORAGE_FREECOM=m
-CONFIG_USB_STORAGE_USBAT=m
-CONFIG_USB_STORAGE_SDDR09=m
-CONFIG_USB_STORAGE_SDDR55=m
-CONFIG_USB_STORAGE_JUMPSHOT=m
-CONFIG_USB_MDC800=m
-CONFIG_USB_MICROTEK=m
-CONFIG_USB_SERIAL=m
-CONFIG_USB_SERIAL_GENERIC=y
-CONFIG_USB_SERIAL_BELKIN=m
-CONFIG_USB_SERIAL_WHITEHEAT=m
-CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
-CONFIG_USB_SERIAL_CYPRESS_M8=m
-CONFIG_USB_SERIAL_EMPEG=m
-CONFIG_USB_SERIAL_FTDI_SIO=m
-CONFIG_USB_SERIAL_VISOR=m
-CONFIG_USB_SERIAL_IPAQ=m
-CONFIG_USB_SERIAL_IR=m
-CONFIG_USB_SERIAL_EDGEPORT=m
-CONFIG_USB_SERIAL_EDGEPORT_TI=m
-CONFIG_USB_SERIAL_IPW=m
-CONFIG_USB_SERIAL_KEYSPAN_PDA=m
-CONFIG_USB_SERIAL_KEYSPAN=m
-CONFIG_USB_SERIAL_KLSI=m
-CONFIG_USB_SERIAL_KOBIL_SCT=m
-CONFIG_USB_SERIAL_MCT_U232=m
-CONFIG_USB_SERIAL_PL2303=m
-CONFIG_USB_SERIAL_SAFE=m
-CONFIG_USB_SERIAL_CYBERJACK=m
-CONFIG_USB_SERIAL_XIRCOM=m
-CONFIG_USB_SERIAL_OMNINET=m
-CONFIG_USB_RIO500=m
-CONFIG_USB_LEGOTOWER=m
-CONFIG_USB_LCD=m
-CONFIG_USB_LED=m
-CONFIG_USB_CYTHERM=m
-CONFIG_USB_TEST=m
-CONFIG_USB_ATM=m
-CONFIG_USB_SPEEDTOUCH=m
-CONFIG_USB_GADGET=m
-CONFIG_USB_GADGET_DUMMY_HCD=y
-CONFIG_USB_ZERO=m
-CONFIG_USB_ETH=m
-CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
-CONFIG_USB_G_SERIAL=m
-CONFIG_MMC=m
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-CONFIG_EXT2_FS_POSIX_ACL=y
-CONFIG_EXT2_FS_SECURITY=y
-CONFIG_EXT3_FS=m
-CONFIG_EXT3_FS_POSIX_ACL=y
-CONFIG_EXT3_FS_SECURITY=y
-CONFIG_REISERFS_FS=m
-CONFIG_REISERFS_FS_XATTR=y
-CONFIG_REISERFS_FS_POSIX_ACL=y
-CONFIG_REISERFS_FS_SECURITY=y
-CONFIG_JFS_FS=m
-CONFIG_JFS_POSIX_ACL=y
-CONFIG_JFS_STATISTICS=y
-CONFIG_XFS_FS=m
-CONFIG_XFS_QUOTA=y
-CONFIG_XFS_POSIX_ACL=y
-CONFIG_XFS_RT=y
-CONFIG_INOTIFY=y
-CONFIG_QUOTA=y
-CONFIG_QFMT_V1=m
-CONFIG_QFMT_V2=m
-CONFIG_AUTOFS_FS=m
-CONFIG_AUTOFS4_FS=m
-CONFIG_ISO9660_FS=m
-CONFIG_JOLIET=y
-CONFIG_ZISOFS=y
-CONFIG_UDF_FS=m
-CONFIG_MSDOS_FS=m
-CONFIG_VFAT_FS=m
-CONFIG_NTFS_FS=m
-CONFIG_TMPFS=y
-CONFIG_ADFS_FS=m
-CONFIG_AFFS_FS=m
-CONFIG_HFS_FS=m
-CONFIG_HFSPLUS_FS=m
-CONFIG_BEFS_FS=m
-CONFIG_BFS_FS=m
-CONFIG_EFS_FS=m
-CONFIG_JFFS2_FS=m
-CONFIG_CRAMFS=y
-CONFIG_VXFS_FS=m
-CONFIG_MINIX_FS=m
-CONFIG_HPFS_FS=m
-CONFIG_QNX4FS_FS=m
-CONFIG_ROMFS_FS=m
-CONFIG_SYSV_FS=m
-CONFIG_UFS_FS=m
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_NFS_V4=y
-CONFIG_ROOT_NFS=y
-CONFIG_NFSD=m
-CONFIG_NFSD_V4=y
-CONFIG_RPCSEC_GSS_SPKM3=m
-CONFIG_SMB_FS=m
-CONFIG_CIFS=m
-CONFIG_NCP_FS=m
-CONFIG_NCPFS_PACKET_SIGNING=y
-CONFIG_NCPFS_IOCTL_LOCKING=y
-CONFIG_NCPFS_STRONG=y
-CONFIG_NCPFS_NFS_NS=y
-CONFIG_NCPFS_OS2_NS=y
-CONFIG_NCPFS_NLS=y
-CONFIG_NCPFS_EXTRAS=y
-CONFIG_CODA_FS=m
-CONFIG_AFS_FS=m
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_ACORN_PARTITION=y
-CONFIG_ACORN_PARTITION_ICS=y
-CONFIG_ACORN_PARTITION_RISCIX=y
-CONFIG_OSF_PARTITION=y
-CONFIG_AMIGA_PARTITION=y
-CONFIG_ATARI_PARTITION=y
-CONFIG_MAC_PARTITION=y
-CONFIG_BSD_DISKLABEL=y
-CONFIG_MINIX_SUBPARTITION=y
-CONFIG_SOLARIS_X86_PARTITION=y
-CONFIG_UNIXWARE_DISKLABEL=y
-CONFIG_LDM_PARTITION=y
-CONFIG_SGI_PARTITION=y
-CONFIG_ULTRIX_PARTITION=y
-CONFIG_SUN_PARTITION=y
-CONFIG_NLS_DEFAULT="cp437"
-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_MAGIC_SYSRQ=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_MUTEXES=y
-# CONFIG_DEBUG_BUGVERBOSE is not set
-CONFIG_SECURITY=y
-CONFIG_CRYPTO_NULL=m
-CONFIG_CRYPTO_TEST=m
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_SHA256=m
-CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_WP512=m
-CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_BLOWFISH=m
-CONFIG_CRYPTO_CAST6=m
-CONFIG_CRYPTO_KHAZAD=m
-CONFIG_CRYPTO_SERPENT=m
-CONFIG_CRYPTO_TEA=m
-CONFIG_CRYPTO_TWOFISH=m
-CONFIG_CRC16=m
diff --git a/arch/arm/configs/prima2_defconfig b/arch/arm/configs/prima2_defconfig
index c328ac6..807d4e2 100644
--- a/arch/arm/configs/prima2_defconfig
+++ b/arch/arm/configs/prima2_defconfig
@@ -1,4 +1,6 @@
 CONFIG_EXPERIMENTAL=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
 CONFIG_RELAY=y
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_KALLSYMS_ALL=y
@@ -8,9 +10,7 @@ CONFIG_MODULE_UNLOAD=y
 CONFIG_PARTITION_ADVANCED=y
 CONFIG_BSD_DISKLABEL=y
 CONFIG_SOLARIS_X86_PARTITION=y
-CONFIG_ARCH_PRIMA2=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
+CONFIG_ARCH_SIRF=y
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
 CONFIG_KEXEC=y
@@ -36,7 +36,6 @@ CONFIG_SPI=y
 CONFIG_SPI_SIRF=y
 CONFIG_SPI_SPIDEV=y
 # CONFIG_HWMON is not set
-# CONFIG_HID_SUPPORT is not set
 CONFIG_USB_GADGET=y
 CONFIG_USB_FILE_STORAGE=m
 CONFIG_USB_MASS_STORAGE=m
diff --git a/arch/arm/configs/pxa3xx_defconfig b/arch/arm/configs/pxa3xx_defconfig
index 1677a06..60e3138 100644
--- a/arch/arm/configs/pxa3xx_defconfig
+++ b/arch/arm/configs/pxa3xx_defconfig
@@ -36,7 +36,6 @@ CONFIG_MTD_CONCAT=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_VERIFY_WRITE=y
 CONFIG_MTD_NAND_PXA3xx=y
 CONFIG_MTD_NAND_PXA3xx_BUILTIN=y
 CONFIG_MTD_ONENAND=y
diff --git a/arch/arm/configs/pxa910_defconfig b/arch/arm/configs/pxa910_defconfig
index 1cd381e..191118c 100644
--- a/arch/arm/configs/pxa910_defconfig
+++ b/arch/arm/configs/pxa910_defconfig
@@ -17,7 +17,7 @@ CONFIG_PREEMPT=y
 CONFIG_AEABI=y
 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_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 earlyprintk"
 CONFIG_FPE_NWFPE=y
 CONFIG_NET=y
 CONFIG_PACKET=y
@@ -66,5 +66,7 @@ CONFIG_DEBUG_INFO=y
 CONFIG_DEBUG_USER=y
 CONFIG_DEBUG_ERRORS=y
 CONFIG_DEBUG_LL=y
+CONFIG_DEBUG_MMP_UART2=y
+CONFIG_EARLY_PRINTK=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRC_CCITT=y
diff --git a/arch/arm/configs/qil-a9260_defconfig b/arch/arm/configs/qil-a9260_defconfig
index 9160f3b..42d5db1 100644
--- a/arch/arm/configs/qil-a9260_defconfig
+++ b/arch/arm/configs/qil-a9260_defconfig
@@ -50,7 +50,6 @@ CONFIG_MTD_BLOCK=y
 CONFIG_MTD_DATAFLASH=y
 CONFIG_MTD_NAND=y
 CONFIG_MTD_NAND_ATMEL=y
-CONFIG_MTD_NAND_ATMEL_ECC_SOFT=y
 CONFIG_BLK_DEV_LOOP=y
 # CONFIG_MISC_DEVICES is not set
 CONFIG_SCSI=y
@@ -87,7 +86,7 @@ CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_ETH=m
 CONFIG_MMC=y
-CONFIG_MMC_AT91=m
+CONFIG_MMC_ATMELMCI=m
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
 CONFIG_LEDS_GPIO=y
diff --git a/arch/arm/configs/s3c6400_defconfig b/arch/arm/configs/s3c6400_defconfig
index ba6a515..3a186d6 100644
--- a/arch/arm/configs/s3c6400_defconfig
+++ b/arch/arm/configs/s3c6400_defconfig
@@ -9,11 +9,14 @@ CONFIG_ARCH_S3C64XX=y
 CONFIG_S3C_BOOT_ERROR_RESET=y
 CONFIG_MACH_SMDK6400=y
 CONFIG_MACH_ANW6410=y
+CONFIG_MACH_MINI6410=y
+CONFIG_MACH_REAL6410=y
 CONFIG_MACH_SMDK6410=y
 CONFIG_MACH_NCP=y
 CONFIG_MACH_HMT=y
 CONFIG_MACH_SMARTQ5=y
 CONFIG_MACH_SMARTQ7=y
+CONFIG_MACH_WLF_CRAGG_6410=y
 CONFIG_CPU_32v6K=y
 CONFIG_AEABI=y
 CONFIG_CMDLINE="console=ttySAC0,115200 root=/dev/ram init=/linuxrc initrd=0x51000000,6M ramdisk_size=6144"
diff --git a/arch/arm/configs/sam9_l9260_defconfig b/arch/arm/configs/sam9_l9260_defconfig
index ecf2531..b4384af 100644
--- a/arch/arm/configs/sam9_l9260_defconfig
+++ b/arch/arm/configs/sam9_l9260_defconfig
@@ -39,7 +39,7 @@ CONFIG_MTD_NAND=y
 CONFIG_MTD_NAND_ATMEL=y
 CONFIG_MTD_NAND_PLATFORM=y
 CONFIG_MTD_UBI=y
-CONFIG_MTD_UBI_BEB_RESERVE=3
+CONFIG_MTD_UBI_BEB_LIMIT=25
 CONFIG_MTD_UBI_GLUEBI=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
diff --git a/arch/arm/configs/spitz_defconfig b/arch/arm/configs/spitz_defconfig
index 7015827..df77931 100644
--- a/arch/arm/configs/spitz_defconfig
+++ b/arch/arm/configs/spitz_defconfig
@@ -94,7 +94,6 @@ CONFIG_MTD_BLOCK=y
 CONFIG_MTD_ROM=y
 CONFIG_MTD_COMPLEX_MAPPINGS=y
 CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_VERIFY_WRITE=y
 CONFIG_MTD_NAND_SHARPSL=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_IDE=y
diff --git a/arch/arm/configs/stamp9g20_defconfig b/arch/arm/configs/stamp9g20_defconfig
index d5e260b..52f1488 100644
--- a/arch/arm/configs/stamp9g20_defconfig
+++ b/arch/arm/configs/stamp9g20_defconfig
@@ -100,7 +100,6 @@ CONFIG_USB_ETH=m
 CONFIG_USB_FILE_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_MMC=y
-# CONFIG_MMC_AT91 is not set
 CONFIG_MMC_ATMELMCI=y
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
diff --git a/arch/arm/configs/tegra_defconfig b/arch/arm/configs/tegra_defconfig
index db22453..e2184f6 100644
--- a/arch/arm/configs/tegra_defconfig
+++ b/arch/arm/configs/tegra_defconfig
@@ -24,11 +24,11 @@ CONFIG_EFI_PARTITION=y
 # CONFIG_IOSCHED_DEADLINE is not set
 # CONFIG_IOSCHED_CFQ is not set
 CONFIG_ARCH_TEGRA=y
+CONFIG_GPIO_PCA953X=y
 CONFIG_ARCH_TEGRA_2x_SOC=y
 CONFIG_ARCH_TEGRA_3x_SOC=y
-CONFIG_MACH_HARMONY=y
-CONFIG_MACH_PAZ00=y
-CONFIG_MACH_TRIMSLICE=y
+CONFIG_TEGRA_PCI=y
+CONFIG_TEGRA_DEBUG_UART_AUTO_ODMDATA=y
 CONFIG_TEGRA_EMC_SCALING_ENABLE=y
 CONFIG_SMP=y
 CONFIG_PREEMPT=y
@@ -67,7 +67,18 @@ CONFIG_INET6_IPCOMP=y
 CONFIG_IPV6_MIP6=y
 CONFIG_IPV6_TUNNEL=y
 CONFIG_IPV6_MULTIPLE_TABLES=y
-# CONFIG_WIRELESS is not set
+CONFIG_BT=y
+CONFIG_BT_RFCOMM=y
+CONFIG_BT_BNEP=y
+CONFIG_BT_HIDP=y
+CONFIG_BT_HCIBTUSB=m
+CONFIG_CFG80211=y
+CONFIG_MAC80211=y
+CONFIG_RFKILL=y
+CONFIG_RFKILL_INPUT=y
+CONFIG_RFKILL_GPIO=y
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_FIRMWARE_IN_KERNEL is not set
 CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
@@ -87,7 +98,8 @@ CONFIG_USB_PEGASUS=y
 CONFIG_USB_USBNET=y
 CONFIG_USB_NET_SMSC75XX=y
 CONFIG_USB_NET_SMSC95XX=y
-# CONFIG_WLAN is not set
+CONFIG_RT2X00=y
+CONFIG_RT2800USB=m
 CONFIG_INPUT_EVDEV=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_MPU3050=y
@@ -105,25 +117,31 @@ CONFIG_I2C_MUX_PINCTRL=y
 CONFIG_I2C_TEGRA=y
 CONFIG_SPI=y
 CONFIG_SPI_TEGRA=y
-CONFIG_GPIO_TPS65910=y
+CONFIG_GPIO_PCA953X_IRQ=y
 CONFIG_GPIO_TPS6586X=y
+CONFIG_GPIO_TPS65910=y
 CONFIG_POWER_SUPPLY=y
 CONFIG_BATTERY_SBS=y
 CONFIG_SENSORS_LM90=y
 CONFIG_MFD_TPS6586X=y
 CONFIG_MFD_TPS65910=y
+CONFIG_MFD_MAX8907=y
 CONFIG_REGULATOR=y
 CONFIG_REGULATOR_FIXED_VOLTAGE=y
 CONFIG_REGULATOR_VIRTUAL_CONSUMER=y
 CONFIG_REGULATOR_GPIO=y
+CONFIG_REGULATOR_MAX8907=y
 CONFIG_REGULATOR_TPS62360=y
 CONFIG_REGULATOR_TPS6586X=y
 CONFIG_REGULATOR_TPS65910=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MEDIA_USB_SUPPORT=y
+CONFIG_USB_VIDEO_CLASS=m
 CONFIG_SOUND=y
 CONFIG_SND=y
 # CONFIG_SND_SUPPORT_OLD_API is not set
 # CONFIG_SND_DRIVERS is not set
-# CONFIG_SND_PCI is not set
 # CONFIG_SND_ARM is not set
 # CONFIG_SND_SPI is not set
 # CONFIG_SND_USB is not set
@@ -136,15 +154,29 @@ CONFIG_SND_SOC_TEGRA_ALC5632=y
 CONFIG_USB=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_TEGRA=y
+CONFIG_USB_ACM=y
+CONFIG_USB_WDM=y
 CONFIG_USB_STORAGE=y
 CONFIG_MMC=y
 CONFIG_MMC_BLOCK_MINORS=16
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_PLTFM=y
 CONFIG_MMC_SDHCI_TEGRA=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_GPIO=y
 CONFIG_RTC_CLASS=y
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+CONFIG_RTC_DRV_MAX8907=y
+CONFIG_RTC_DRV_TPS65910=y
 CONFIG_RTC_DRV_EM3027=y
 CONFIG_RTC_DRV_TEGRA=y
+CONFIG_DMADEVICES=y
+CONFIG_TEGRA20_APB_DMA=y
 CONFIG_STAGING=y
 CONFIG_SENSORS_ISL29018=y
 CONFIG_SENSORS_ISL29028=y
@@ -152,10 +184,14 @@ CONFIG_SENSORS_AK8975=y
 CONFIG_MFD_NVEC=y
 CONFIG_KEYBOARD_NVEC=y
 CONFIG_SERIO_NVEC_PS2=y
+CONFIG_NVEC_POWER=y
+CONFIG_NVEC_PAZ00=y
 CONFIG_TEGRA_IOMMU_GART=y
 CONFIG_TEGRA_IOMMU_SMMU=y
 CONFIG_MEMORY=y
 CONFIG_IIO=y
+CONFIG_PWM=y
+CONFIG_PWM_TEGRA=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_POSIX_ACL=y
@@ -168,6 +204,7 @@ CONFIG_EXT4_FS=y
 # CONFIG_DNOTIFY is not set
 CONFIG_VFAT_FS=y
 CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
 CONFIG_NFS_FS=y
 CONFIG_ROOT_NFS=y
 CONFIG_NLS_CODEPAGE_437=y
@@ -186,8 +223,6 @@ CONFIG_DEBUG_VM=y
 CONFIG_DEBUG_SG=y
 CONFIG_DEBUG_LL=y
 CONFIG_EARLY_PRINTK=y
-CONFIG_CRYPTO_ECB=y
-CONFIG_CRYPTO_ARC4=y
 CONFIG_CRYPTO_TWOFISH=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRYPTO_DEV_TEGRA_AES=y
diff --git a/arch/arm/configs/usb-a9260_defconfig b/arch/arm/configs/usb-a9260_defconfig
index 2e39f38..a1501e1 100644
--- a/arch/arm/configs/usb-a9260_defconfig
+++ b/arch/arm/configs/usb-a9260_defconfig
@@ -49,7 +49,6 @@ CONFIG_MTD_BLOCK=y
 CONFIG_MTD_DATAFLASH=y
 CONFIG_MTD_NAND=y
 CONFIG_MTD_NAND_ATMEL=y
-CONFIG_MTD_NAND_ATMEL_ECC_SOFT=y
 CONFIG_BLK_DEV_LOOP=y
 # CONFIG_MISC_DEVICES is not set
 CONFIG_SCSI=y
diff --git a/arch/arm/crypto/Makefile b/arch/arm/crypto/Makefile
new file mode 100644
index 0000000..a2c8385
--- /dev/null
+++ b/arch/arm/crypto/Makefile
@@ -0,0 +1,9 @@
+#
+# Arch-specific CryptoAPI modules.
+#
+
+obj-$(CONFIG_CRYPTO_AES_ARM) += aes-arm.o
+obj-$(CONFIG_CRYPTO_SHA1_ARM) += sha1-arm.o
+
+aes-arm-y  := aes-armv4.o aes_glue.o
+sha1-arm-y := sha1-armv4-large.o sha1_glue.o
diff --git a/arch/arm/crypto/aes-armv4.S b/arch/arm/crypto/aes-armv4.S
new file mode 100644
index 0000000..e59b1d5
--- /dev/null
+++ b/arch/arm/crypto/aes-armv4.S
@@ -0,0 +1,1112 @@
+#define __ARM_ARCH__ __LINUX_ARM_ARCH__
+@ ====================================================================
+@ Written by Andy Polyakov <appro@fy.chalmers.se> for the OpenSSL
+@ project. The module is, however, dual licensed under OpenSSL and
+@ CRYPTOGAMS licenses depending on where you obtain it. For further
+@ details see http://www.openssl.org/~appro/cryptogams/.
+@ ====================================================================
+
+@ AES for ARMv4
+
+@ January 2007.
+@
+@ Code uses single 1K S-box and is >2 times faster than code generated
+@ by gcc-3.4.1. This is thanks to unique feature of ARMv4 ISA, which
+@ allows to merge logical or arithmetic operation with shift or rotate
+@ in one instruction and emit combined result every cycle. The module
+@ is endian-neutral. The performance is ~42 cycles/byte for 128-bit
+@ key [on single-issue Xscale PXA250 core].
+
+@ May 2007.
+@
+@ AES_set_[en|de]crypt_key is added.
+
+@ July 2010.
+@
+@ Rescheduling for dual-issue pipeline resulted in 12% improvement on
+@ Cortex A8 core and ~25 cycles per byte processed with 128-bit key.
+
+@ February 2011.
+@
+@ Profiler-assisted and platform-specific optimization resulted in 16%
+@ improvement on Cortex A8 core and ~21.5 cycles per byte.
+
+@ A little glue here to select the correct code below for the ARM CPU
+@ that is being targetted.
+
+.text
+.code	32
+
+.type	AES_Te,%object
+.align	5
+AES_Te:
+.word	0xc66363a5, 0xf87c7c84, 0xee777799, 0xf67b7b8d
+.word	0xfff2f20d, 0xd66b6bbd, 0xde6f6fb1, 0x91c5c554
+.word	0x60303050, 0x02010103, 0xce6767a9, 0x562b2b7d
+.word	0xe7fefe19, 0xb5d7d762, 0x4dababe6, 0xec76769a
+.word	0x8fcaca45, 0x1f82829d, 0x89c9c940, 0xfa7d7d87
+.word	0xeffafa15, 0xb25959eb, 0x8e4747c9, 0xfbf0f00b
+.word	0x41adadec, 0xb3d4d467, 0x5fa2a2fd, 0x45afafea
+.word	0x239c9cbf, 0x53a4a4f7, 0xe4727296, 0x9bc0c05b
+.word	0x75b7b7c2, 0xe1fdfd1c, 0x3d9393ae, 0x4c26266a
+.word	0x6c36365a, 0x7e3f3f41, 0xf5f7f702, 0x83cccc4f
+.word	0x6834345c, 0x51a5a5f4, 0xd1e5e534, 0xf9f1f108
+.word	0xe2717193, 0xabd8d873, 0x62313153, 0x2a15153f
+.word	0x0804040c, 0x95c7c752, 0x46232365, 0x9dc3c35e
+.word	0x30181828, 0x379696a1, 0x0a05050f, 0x2f9a9ab5
+.word	0x0e070709, 0x24121236, 0x1b80809b, 0xdfe2e23d
+.word	0xcdebeb26, 0x4e272769, 0x7fb2b2cd, 0xea75759f
+.word	0x1209091b, 0x1d83839e, 0x582c2c74, 0x341a1a2e
+.word	0x361b1b2d, 0xdc6e6eb2, 0xb45a5aee, 0x5ba0a0fb
+.word	0xa45252f6, 0x763b3b4d, 0xb7d6d661, 0x7db3b3ce
+.word	0x5229297b, 0xdde3e33e, 0x5e2f2f71, 0x13848497
+.word	0xa65353f5, 0xb9d1d168, 0x00000000, 0xc1eded2c
+.word	0x40202060, 0xe3fcfc1f, 0x79b1b1c8, 0xb65b5bed
+.word	0xd46a6abe, 0x8dcbcb46, 0x67bebed9, 0x7239394b
+.word	0x944a4ade, 0x984c4cd4, 0xb05858e8, 0x85cfcf4a
+.word	0xbbd0d06b, 0xc5efef2a, 0x4faaaae5, 0xedfbfb16
+.word	0x864343c5, 0x9a4d4dd7, 0x66333355, 0x11858594
+.word	0x8a4545cf, 0xe9f9f910, 0x04020206, 0xfe7f7f81
+.word	0xa05050f0, 0x783c3c44, 0x259f9fba, 0x4ba8a8e3
+.word	0xa25151f3, 0x5da3a3fe, 0x804040c0, 0x058f8f8a
+.word	0x3f9292ad, 0x219d9dbc, 0x70383848, 0xf1f5f504
+.word	0x63bcbcdf, 0x77b6b6c1, 0xafdada75, 0x42212163
+.word	0x20101030, 0xe5ffff1a, 0xfdf3f30e, 0xbfd2d26d
+.word	0x81cdcd4c, 0x180c0c14, 0x26131335, 0xc3ecec2f
+.word	0xbe5f5fe1, 0x359797a2, 0x884444cc, 0x2e171739
+.word	0x93c4c457, 0x55a7a7f2, 0xfc7e7e82, 0x7a3d3d47
+.word	0xc86464ac, 0xba5d5de7, 0x3219192b, 0xe6737395
+.word	0xc06060a0, 0x19818198, 0x9e4f4fd1, 0xa3dcdc7f
+.word	0x44222266, 0x542a2a7e, 0x3b9090ab, 0x0b888883
+.word	0x8c4646ca, 0xc7eeee29, 0x6bb8b8d3, 0x2814143c
+.word	0xa7dede79, 0xbc5e5ee2, 0x160b0b1d, 0xaddbdb76
+.word	0xdbe0e03b, 0x64323256, 0x743a3a4e, 0x140a0a1e
+.word	0x924949db, 0x0c06060a, 0x4824246c, 0xb85c5ce4
+.word	0x9fc2c25d, 0xbdd3d36e, 0x43acacef, 0xc46262a6
+.word	0x399191a8, 0x319595a4, 0xd3e4e437, 0xf279798b
+.word	0xd5e7e732, 0x8bc8c843, 0x6e373759, 0xda6d6db7
+.word	0x018d8d8c, 0xb1d5d564, 0x9c4e4ed2, 0x49a9a9e0
+.word	0xd86c6cb4, 0xac5656fa, 0xf3f4f407, 0xcfeaea25
+.word	0xca6565af, 0xf47a7a8e, 0x47aeaee9, 0x10080818
+.word	0x6fbabad5, 0xf0787888, 0x4a25256f, 0x5c2e2e72
+.word	0x381c1c24, 0x57a6a6f1, 0x73b4b4c7, 0x97c6c651
+.word	0xcbe8e823, 0xa1dddd7c, 0xe874749c, 0x3e1f1f21
+.word	0x964b4bdd, 0x61bdbddc, 0x0d8b8b86, 0x0f8a8a85
+.word	0xe0707090, 0x7c3e3e42, 0x71b5b5c4, 0xcc6666aa
+.word	0x904848d8, 0x06030305, 0xf7f6f601, 0x1c0e0e12
+.word	0xc26161a3, 0x6a35355f, 0xae5757f9, 0x69b9b9d0
+.word	0x17868691, 0x99c1c158, 0x3a1d1d27, 0x279e9eb9
+.word	0xd9e1e138, 0xebf8f813, 0x2b9898b3, 0x22111133
+.word	0xd26969bb, 0xa9d9d970, 0x078e8e89, 0x339494a7
+.word	0x2d9b9bb6, 0x3c1e1e22, 0x15878792, 0xc9e9e920
+.word	0x87cece49, 0xaa5555ff, 0x50282878, 0xa5dfdf7a
+.word	0x038c8c8f, 0x59a1a1f8, 0x09898980, 0x1a0d0d17
+.word	0x65bfbfda, 0xd7e6e631, 0x844242c6, 0xd06868b8
+.word	0x824141c3, 0x299999b0, 0x5a2d2d77, 0x1e0f0f11
+.word	0x7bb0b0cb, 0xa85454fc, 0x6dbbbbd6, 0x2c16163a
+@ Te4[256]
+.byte	0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5
+.byte	0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76
+.byte	0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0
+.byte	0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0
+.byte	0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc
+.byte	0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15
+.byte	0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a
+.byte	0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75
+.byte	0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0
+.byte	0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84
+.byte	0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b
+.byte	0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf
+.byte	0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85
+.byte	0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8
+.byte	0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5
+.byte	0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2
+.byte	0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17
+.byte	0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73
+.byte	0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88
+.byte	0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb
+.byte	0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c
+.byte	0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79
+.byte	0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9
+.byte	0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08
+.byte	0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6
+.byte	0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a
+.byte	0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e
+.byte	0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e
+.byte	0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94
+.byte	0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf
+.byte	0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68
+.byte	0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
+@ rcon[]
+.word	0x01000000, 0x02000000, 0x04000000, 0x08000000
+.word	0x10000000, 0x20000000, 0x40000000, 0x80000000
+.word	0x1B000000, 0x36000000, 0, 0, 0, 0, 0, 0
+.size	AES_Te,.-AES_Te
+
+@ void AES_encrypt(const unsigned char *in, unsigned char *out,
+@ 		 const AES_KEY *key) {
+.global AES_encrypt
+.type   AES_encrypt,%function
+.align	5
+AES_encrypt:
+	sub	r3,pc,#8		@ AES_encrypt
+	stmdb   sp!,{r1,r4-r12,lr}
+	mov	r12,r0		@ inp
+	mov	r11,r2
+	sub	r10,r3,#AES_encrypt-AES_Te	@ Te
+#if __ARM_ARCH__<7
+	ldrb	r0,[r12,#3]	@ load input data in endian-neutral
+	ldrb	r4,[r12,#2]	@ manner...
+	ldrb	r5,[r12,#1]
+	ldrb	r6,[r12,#0]
+	orr	r0,r0,r4,lsl#8
+	ldrb	r1,[r12,#7]
+	orr	r0,r0,r5,lsl#16
+	ldrb	r4,[r12,#6]
+	orr	r0,r0,r6,lsl#24
+	ldrb	r5,[r12,#5]
+	ldrb	r6,[r12,#4]
+	orr	r1,r1,r4,lsl#8
+	ldrb	r2,[r12,#11]
+	orr	r1,r1,r5,lsl#16
+	ldrb	r4,[r12,#10]
+	orr	r1,r1,r6,lsl#24
+	ldrb	r5,[r12,#9]
+	ldrb	r6,[r12,#8]
+	orr	r2,r2,r4,lsl#8
+	ldrb	r3,[r12,#15]
+	orr	r2,r2,r5,lsl#16
+	ldrb	r4,[r12,#14]
+	orr	r2,r2,r6,lsl#24
+	ldrb	r5,[r12,#13]
+	ldrb	r6,[r12,#12]
+	orr	r3,r3,r4,lsl#8
+	orr	r3,r3,r5,lsl#16
+	orr	r3,r3,r6,lsl#24
+#else
+	ldr	r0,[r12,#0]
+	ldr	r1,[r12,#4]
+	ldr	r2,[r12,#8]
+	ldr	r3,[r12,#12]
+#ifdef __ARMEL__
+	rev	r0,r0
+	rev	r1,r1
+	rev	r2,r2
+	rev	r3,r3
+#endif
+#endif
+	bl	_armv4_AES_encrypt
+
+	ldr	r12,[sp],#4		@ pop out
+#if __ARM_ARCH__>=7
+#ifdef __ARMEL__
+	rev	r0,r0
+	rev	r1,r1
+	rev	r2,r2
+	rev	r3,r3
+#endif
+	str	r0,[r12,#0]
+	str	r1,[r12,#4]
+	str	r2,[r12,#8]
+	str	r3,[r12,#12]
+#else
+	mov	r4,r0,lsr#24		@ write output in endian-neutral
+	mov	r5,r0,lsr#16		@ manner...
+	mov	r6,r0,lsr#8
+	strb	r4,[r12,#0]
+	strb	r5,[r12,#1]
+	mov	r4,r1,lsr#24
+	strb	r6,[r12,#2]
+	mov	r5,r1,lsr#16
+	strb	r0,[r12,#3]
+	mov	r6,r1,lsr#8
+	strb	r4,[r12,#4]
+	strb	r5,[r12,#5]
+	mov	r4,r2,lsr#24
+	strb	r6,[r12,#6]
+	mov	r5,r2,lsr#16
+	strb	r1,[r12,#7]
+	mov	r6,r2,lsr#8
+	strb	r4,[r12,#8]
+	strb	r5,[r12,#9]
+	mov	r4,r3,lsr#24
+	strb	r6,[r12,#10]
+	mov	r5,r3,lsr#16
+	strb	r2,[r12,#11]
+	mov	r6,r3,lsr#8
+	strb	r4,[r12,#12]
+	strb	r5,[r12,#13]
+	strb	r6,[r12,#14]
+	strb	r3,[r12,#15]
+#endif
+#if __ARM_ARCH__>=5
+	ldmia	sp!,{r4-r12,pc}
+#else
+	ldmia   sp!,{r4-r12,lr}
+	tst	lr,#1
+	moveq	pc,lr			@ be binary compatible with V4, yet
+	.word	0xe12fff1e			@ interoperable with Thumb ISA:-)
+#endif
+.size	AES_encrypt,.-AES_encrypt
+
+.type   _armv4_AES_encrypt,%function
+.align	2
+_armv4_AES_encrypt:
+	str	lr,[sp,#-4]!		@ push lr
+	ldmia	r11!,{r4-r7}
+	eor	r0,r0,r4
+	ldr	r12,[r11,#240-16]
+	eor	r1,r1,r5
+	eor	r2,r2,r6
+	eor	r3,r3,r7
+	sub	r12,r12,#1
+	mov	lr,#255
+
+	and	r7,lr,r0
+	and	r8,lr,r0,lsr#8
+	and	r9,lr,r0,lsr#16
+	mov	r0,r0,lsr#24
+.Lenc_loop:
+	ldr	r4,[r10,r7,lsl#2]	@ Te3[s0>>0]
+	and	r7,lr,r1,lsr#16	@ i0
+	ldr	r5,[r10,r8,lsl#2]	@ Te2[s0>>8]
+	and	r8,lr,r1
+	ldr	r6,[r10,r9,lsl#2]	@ Te1[s0>>16]
+	and	r9,lr,r1,lsr#8
+	ldr	r0,[r10,r0,lsl#2]	@ Te0[s0>>24]
+	mov	r1,r1,lsr#24
+
+	ldr	r7,[r10,r7,lsl#2]	@ Te1[s1>>16]
+	ldr	r8,[r10,r8,lsl#2]	@ Te3[s1>>0]
+	ldr	r9,[r10,r9,lsl#2]	@ Te2[s1>>8]
+	eor	r0,r0,r7,ror#8
+	ldr	r1,[r10,r1,lsl#2]	@ Te0[s1>>24]
+	and	r7,lr,r2,lsr#8	@ i0
+	eor	r5,r5,r8,ror#8
+	and	r8,lr,r2,lsr#16	@ i1
+	eor	r6,r6,r9,ror#8
+	and	r9,lr,r2
+	ldr	r7,[r10,r7,lsl#2]	@ Te2[s2>>8]
+	eor	r1,r1,r4,ror#24
+	ldr	r8,[r10,r8,lsl#2]	@ Te1[s2>>16]
+	mov	r2,r2,lsr#24
+
+	ldr	r9,[r10,r9,lsl#2]	@ Te3[s2>>0]
+	eor	r0,r0,r7,ror#16
+	ldr	r2,[r10,r2,lsl#2]	@ Te0[s2>>24]
+	and	r7,lr,r3		@ i0
+	eor	r1,r1,r8,ror#8
+	and	r8,lr,r3,lsr#8	@ i1
+	eor	r6,r6,r9,ror#16
+	and	r9,lr,r3,lsr#16	@ i2
+	ldr	r7,[r10,r7,lsl#2]	@ Te3[s3>>0]
+	eor	r2,r2,r5,ror#16
+	ldr	r8,[r10,r8,lsl#2]	@ Te2[s3>>8]
+	mov	r3,r3,lsr#24
+
+	ldr	r9,[r10,r9,lsl#2]	@ Te1[s3>>16]
+	eor	r0,r0,r7,ror#24
+	ldr	r7,[r11],#16
+	eor	r1,r1,r8,ror#16
+	ldr	r3,[r10,r3,lsl#2]	@ Te0[s3>>24]
+	eor	r2,r2,r9,ror#8
+	ldr	r4,[r11,#-12]
+	eor	r3,r3,r6,ror#8
+
+	ldr	r5,[r11,#-8]
+	eor	r0,r0,r7
+	ldr	r6,[r11,#-4]
+	and	r7,lr,r0
+	eor	r1,r1,r4
+	and	r8,lr,r0,lsr#8
+	eor	r2,r2,r5
+	and	r9,lr,r0,lsr#16
+	eor	r3,r3,r6
+	mov	r0,r0,lsr#24
+
+	subs	r12,r12,#1
+	bne	.Lenc_loop
+
+	add	r10,r10,#2
+
+	ldrb	r4,[r10,r7,lsl#2]	@ Te4[s0>>0]
+	and	r7,lr,r1,lsr#16	@ i0
+	ldrb	r5,[r10,r8,lsl#2]	@ Te4[s0>>8]
+	and	r8,lr,r1
+	ldrb	r6,[r10,r9,lsl#2]	@ Te4[s0>>16]
+	and	r9,lr,r1,lsr#8
+	ldrb	r0,[r10,r0,lsl#2]	@ Te4[s0>>24]
+	mov	r1,r1,lsr#24
+
+	ldrb	r7,[r10,r7,lsl#2]	@ Te4[s1>>16]
+	ldrb	r8,[r10,r8,lsl#2]	@ Te4[s1>>0]
+	ldrb	r9,[r10,r9,lsl#2]	@ Te4[s1>>8]
+	eor	r0,r7,r0,lsl#8
+	ldrb	r1,[r10,r1,lsl#2]	@ Te4[s1>>24]
+	and	r7,lr,r2,lsr#8	@ i0
+	eor	r5,r8,r5,lsl#8
+	and	r8,lr,r2,lsr#16	@ i1
+	eor	r6,r9,r6,lsl#8
+	and	r9,lr,r2
+	ldrb	r7,[r10,r7,lsl#2]	@ Te4[s2>>8]
+	eor	r1,r4,r1,lsl#24
+	ldrb	r8,[r10,r8,lsl#2]	@ Te4[s2>>16]
+	mov	r2,r2,lsr#24
+
+	ldrb	r9,[r10,r9,lsl#2]	@ Te4[s2>>0]
+	eor	r0,r7,r0,lsl#8
+	ldrb	r2,[r10,r2,lsl#2]	@ Te4[s2>>24]
+	and	r7,lr,r3		@ i0
+	eor	r1,r1,r8,lsl#16
+	and	r8,lr,r3,lsr#8	@ i1
+	eor	r6,r9,r6,lsl#8
+	and	r9,lr,r3,lsr#16	@ i2
+	ldrb	r7,[r10,r7,lsl#2]	@ Te4[s3>>0]
+	eor	r2,r5,r2,lsl#24
+	ldrb	r8,[r10,r8,lsl#2]	@ Te4[s3>>8]
+	mov	r3,r3,lsr#24
+
+	ldrb	r9,[r10,r9,lsl#2]	@ Te4[s3>>16]
+	eor	r0,r7,r0,lsl#8
+	ldr	r7,[r11,#0]
+	ldrb	r3,[r10,r3,lsl#2]	@ Te4[s3>>24]
+	eor	r1,r1,r8,lsl#8
+	ldr	r4,[r11,#4]
+	eor	r2,r2,r9,lsl#16
+	ldr	r5,[r11,#8]
+	eor	r3,r6,r3,lsl#24
+	ldr	r6,[r11,#12]
+
+	eor	r0,r0,r7
+	eor	r1,r1,r4
+	eor	r2,r2,r5
+	eor	r3,r3,r6
+
+	sub	r10,r10,#2
+	ldr	pc,[sp],#4		@ pop and return
+.size	_armv4_AES_encrypt,.-_armv4_AES_encrypt
+
+.global private_AES_set_encrypt_key
+.type   private_AES_set_encrypt_key,%function
+.align	5
+private_AES_set_encrypt_key:
+_armv4_AES_set_encrypt_key:
+	sub	r3,pc,#8		@ AES_set_encrypt_key
+	teq	r0,#0
+	moveq	r0,#-1
+	beq	.Labrt
+	teq	r2,#0
+	moveq	r0,#-1
+	beq	.Labrt
+
+	teq	r1,#128
+	beq	.Lok
+	teq	r1,#192
+	beq	.Lok
+	teq	r1,#256
+	movne	r0,#-1
+	bne	.Labrt
+
+.Lok:	stmdb   sp!,{r4-r12,lr}
+	sub	r10,r3,#_armv4_AES_set_encrypt_key-AES_Te-1024	@ Te4
+
+	mov	r12,r0		@ inp
+	mov	lr,r1			@ bits
+	mov	r11,r2			@ key
+
+#if __ARM_ARCH__<7
+	ldrb	r0,[r12,#3]	@ load input data in endian-neutral
+	ldrb	r4,[r12,#2]	@ manner...
+	ldrb	r5,[r12,#1]
+	ldrb	r6,[r12,#0]
+	orr	r0,r0,r4,lsl#8
+	ldrb	r1,[r12,#7]
+	orr	r0,r0,r5,lsl#16
+	ldrb	r4,[r12,#6]
+	orr	r0,r0,r6,lsl#24
+	ldrb	r5,[r12,#5]
+	ldrb	r6,[r12,#4]
+	orr	r1,r1,r4,lsl#8
+	ldrb	r2,[r12,#11]
+	orr	r1,r1,r5,lsl#16
+	ldrb	r4,[r12,#10]
+	orr	r1,r1,r6,lsl#24
+	ldrb	r5,[r12,#9]
+	ldrb	r6,[r12,#8]
+	orr	r2,r2,r4,lsl#8
+	ldrb	r3,[r12,#15]
+	orr	r2,r2,r5,lsl#16
+	ldrb	r4,[r12,#14]
+	orr	r2,r2,r6,lsl#24
+	ldrb	r5,[r12,#13]
+	ldrb	r6,[r12,#12]
+	orr	r3,r3,r4,lsl#8
+	str	r0,[r11],#16
+	orr	r3,r3,r5,lsl#16
+	str	r1,[r11,#-12]
+	orr	r3,r3,r6,lsl#24
+	str	r2,[r11,#-8]
+	str	r3,[r11,#-4]
+#else
+	ldr	r0,[r12,#0]
+	ldr	r1,[r12,#4]
+	ldr	r2,[r12,#8]
+	ldr	r3,[r12,#12]
+#ifdef __ARMEL__
+	rev	r0,r0
+	rev	r1,r1
+	rev	r2,r2
+	rev	r3,r3
+#endif
+	str	r0,[r11],#16
+	str	r1,[r11,#-12]
+	str	r2,[r11,#-8]
+	str	r3,[r11,#-4]
+#endif
+
+	teq	lr,#128
+	bne	.Lnot128
+	mov	r12,#10
+	str	r12,[r11,#240-16]
+	add	r6,r10,#256			@ rcon
+	mov	lr,#255
+
+.L128_loop:
+	and	r5,lr,r3,lsr#24
+	and	r7,lr,r3,lsr#16
+	ldrb	r5,[r10,r5]
+	and	r8,lr,r3,lsr#8
+	ldrb	r7,[r10,r7]
+	and	r9,lr,r3
+	ldrb	r8,[r10,r8]
+	orr	r5,r5,r7,lsl#24
+	ldrb	r9,[r10,r9]
+	orr	r5,r5,r8,lsl#16
+	ldr	r4,[r6],#4			@ rcon[i++]
+	orr	r5,r5,r9,lsl#8
+	eor	r5,r5,r4
+	eor	r0,r0,r5			@ rk[4]=rk[0]^...
+	eor	r1,r1,r0			@ rk[5]=rk[1]^rk[4]
+	str	r0,[r11],#16
+	eor	r2,r2,r1			@ rk[6]=rk[2]^rk[5]
+	str	r1,[r11,#-12]
+	eor	r3,r3,r2			@ rk[7]=rk[3]^rk[6]
+	str	r2,[r11,#-8]
+	subs	r12,r12,#1
+	str	r3,[r11,#-4]
+	bne	.L128_loop
+	sub	r2,r11,#176
+	b	.Ldone
+
+.Lnot128:
+#if __ARM_ARCH__<7
+	ldrb	r8,[r12,#19]
+	ldrb	r4,[r12,#18]
+	ldrb	r5,[r12,#17]
+	ldrb	r6,[r12,#16]
+	orr	r8,r8,r4,lsl#8
+	ldrb	r9,[r12,#23]
+	orr	r8,r8,r5,lsl#16
+	ldrb	r4,[r12,#22]
+	orr	r8,r8,r6,lsl#24
+	ldrb	r5,[r12,#21]
+	ldrb	r6,[r12,#20]
+	orr	r9,r9,r4,lsl#8
+	orr	r9,r9,r5,lsl#16
+	str	r8,[r11],#8
+	orr	r9,r9,r6,lsl#24
+	str	r9,[r11,#-4]
+#else
+	ldr	r8,[r12,#16]
+	ldr	r9,[r12,#20]
+#ifdef __ARMEL__
+	rev	r8,r8
+	rev	r9,r9
+#endif
+	str	r8,[r11],#8
+	str	r9,[r11,#-4]
+#endif
+
+	teq	lr,#192
+	bne	.Lnot192
+	mov	r12,#12
+	str	r12,[r11,#240-24]
+	add	r6,r10,#256			@ rcon
+	mov	lr,#255
+	mov	r12,#8
+
+.L192_loop:
+	and	r5,lr,r9,lsr#24
+	and	r7,lr,r9,lsr#16
+	ldrb	r5,[r10,r5]
+	and	r8,lr,r9,lsr#8
+	ldrb	r7,[r10,r7]
+	and	r9,lr,r9
+	ldrb	r8,[r10,r8]
+	orr	r5,r5,r7,lsl#24
+	ldrb	r9,[r10,r9]
+	orr	r5,r5,r8,lsl#16
+	ldr	r4,[r6],#4			@ rcon[i++]
+	orr	r5,r5,r9,lsl#8
+	eor	r9,r5,r4
+	eor	r0,r0,r9			@ rk[6]=rk[0]^...
+	eor	r1,r1,r0			@ rk[7]=rk[1]^rk[6]
+	str	r0,[r11],#24
+	eor	r2,r2,r1			@ rk[8]=rk[2]^rk[7]
+	str	r1,[r11,#-20]
+	eor	r3,r3,r2			@ rk[9]=rk[3]^rk[8]
+	str	r2,[r11,#-16]
+	subs	r12,r12,#1
+	str	r3,[r11,#-12]
+	subeq	r2,r11,#216
+	beq	.Ldone
+
+	ldr	r7,[r11,#-32]
+	ldr	r8,[r11,#-28]
+	eor	r7,r7,r3			@ rk[10]=rk[4]^rk[9]
+	eor	r9,r8,r7			@ rk[11]=rk[5]^rk[10]
+	str	r7,[r11,#-8]
+	str	r9,[r11,#-4]
+	b	.L192_loop
+
+.Lnot192:
+#if __ARM_ARCH__<7
+	ldrb	r8,[r12,#27]
+	ldrb	r4,[r12,#26]
+	ldrb	r5,[r12,#25]
+	ldrb	r6,[r12,#24]
+	orr	r8,r8,r4,lsl#8
+	ldrb	r9,[r12,#31]
+	orr	r8,r8,r5,lsl#16
+	ldrb	r4,[r12,#30]
+	orr	r8,r8,r6,lsl#24
+	ldrb	r5,[r12,#29]
+	ldrb	r6,[r12,#28]
+	orr	r9,r9,r4,lsl#8
+	orr	r9,r9,r5,lsl#16
+	str	r8,[r11],#8
+	orr	r9,r9,r6,lsl#24
+	str	r9,[r11,#-4]
+#else
+	ldr	r8,[r12,#24]
+	ldr	r9,[r12,#28]
+#ifdef __ARMEL__
+	rev	r8,r8
+	rev	r9,r9
+#endif
+	str	r8,[r11],#8
+	str	r9,[r11,#-4]
+#endif
+
+	mov	r12,#14
+	str	r12,[r11,#240-32]
+	add	r6,r10,#256			@ rcon
+	mov	lr,#255
+	mov	r12,#7
+
+.L256_loop:
+	and	r5,lr,r9,lsr#24
+	and	r7,lr,r9,lsr#16
+	ldrb	r5,[r10,r5]
+	and	r8,lr,r9,lsr#8
+	ldrb	r7,[r10,r7]
+	and	r9,lr,r9
+	ldrb	r8,[r10,r8]
+	orr	r5,r5,r7,lsl#24
+	ldrb	r9,[r10,r9]
+	orr	r5,r5,r8,lsl#16
+	ldr	r4,[r6],#4			@ rcon[i++]
+	orr	r5,r5,r9,lsl#8
+	eor	r9,r5,r4
+	eor	r0,r0,r9			@ rk[8]=rk[0]^...
+	eor	r1,r1,r0			@ rk[9]=rk[1]^rk[8]
+	str	r0,[r11],#32
+	eor	r2,r2,r1			@ rk[10]=rk[2]^rk[9]
+	str	r1,[r11,#-28]
+	eor	r3,r3,r2			@ rk[11]=rk[3]^rk[10]
+	str	r2,[r11,#-24]
+	subs	r12,r12,#1
+	str	r3,[r11,#-20]
+	subeq	r2,r11,#256
+	beq	.Ldone
+
+	and	r5,lr,r3
+	and	r7,lr,r3,lsr#8
+	ldrb	r5,[r10,r5]
+	and	r8,lr,r3,lsr#16
+	ldrb	r7,[r10,r7]
+	and	r9,lr,r3,lsr#24
+	ldrb	r8,[r10,r8]
+	orr	r5,r5,r7,lsl#8
+	ldrb	r9,[r10,r9]
+	orr	r5,r5,r8,lsl#16
+	ldr	r4,[r11,#-48]
+	orr	r5,r5,r9,lsl#24
+
+	ldr	r7,[r11,#-44]
+	ldr	r8,[r11,#-40]
+	eor	r4,r4,r5			@ rk[12]=rk[4]^...
+	ldr	r9,[r11,#-36]
+	eor	r7,r7,r4			@ rk[13]=rk[5]^rk[12]
+	str	r4,[r11,#-16]
+	eor	r8,r8,r7			@ rk[14]=rk[6]^rk[13]
+	str	r7,[r11,#-12]
+	eor	r9,r9,r8			@ rk[15]=rk[7]^rk[14]
+	str	r8,[r11,#-8]
+	str	r9,[r11,#-4]
+	b	.L256_loop
+
+.Ldone:	mov	r0,#0
+	ldmia   sp!,{r4-r12,lr}
+.Labrt:	tst	lr,#1
+	moveq	pc,lr			@ be binary compatible with V4, yet
+	.word	0xe12fff1e			@ interoperable with Thumb ISA:-)
+.size	private_AES_set_encrypt_key,.-private_AES_set_encrypt_key
+
+.global private_AES_set_decrypt_key
+.type   private_AES_set_decrypt_key,%function
+.align	5
+private_AES_set_decrypt_key:
+	str	lr,[sp,#-4]!            @ push lr
+#if 0
+	@ kernel does both of these in setkey so optimise this bit out by
+	@ expecting the key to already have the enc_key work done (see aes_glue.c)
+	bl	_armv4_AES_set_encrypt_key
+#else
+	mov	r0,#0
+#endif
+	teq	r0,#0
+	ldrne	lr,[sp],#4              @ pop lr
+	bne	.Labrt
+
+	stmdb   sp!,{r4-r12}
+
+	ldr	r12,[r2,#240]	@ AES_set_encrypt_key preserves r2,
+	mov	r11,r2			@ which is AES_KEY *key
+	mov	r7,r2
+	add	r8,r2,r12,lsl#4
+
+.Linv:	ldr	r0,[r7]
+	ldr	r1,[r7,#4]
+	ldr	r2,[r7,#8]
+	ldr	r3,[r7,#12]
+	ldr	r4,[r8]
+	ldr	r5,[r8,#4]
+	ldr	r6,[r8,#8]
+	ldr	r9,[r8,#12]
+	str	r0,[r8],#-16
+	str	r1,[r8,#16+4]
+	str	r2,[r8,#16+8]
+	str	r3,[r8,#16+12]
+	str	r4,[r7],#16
+	str	r5,[r7,#-12]
+	str	r6,[r7,#-8]
+	str	r9,[r7,#-4]
+	teq	r7,r8
+	bne	.Linv
+	ldr	r0,[r11,#16]!		@ prefetch tp1
+	mov	r7,#0x80
+	mov	r8,#0x1b
+	orr	r7,r7,#0x8000
+	orr	r8,r8,#0x1b00
+	orr	r7,r7,r7,lsl#16
+	orr	r8,r8,r8,lsl#16
+	sub	r12,r12,#1
+	mvn	r9,r7
+	mov	r12,r12,lsl#2	@ (rounds-1)*4
+
+.Lmix:	and	r4,r0,r7
+	and	r1,r0,r9
+	sub	r4,r4,r4,lsr#7
+	and	r4,r4,r8
+	eor	r1,r4,r1,lsl#1	@ tp2
+
+	and	r4,r1,r7
+	and	r2,r1,r9
+	sub	r4,r4,r4,lsr#7
+	and	r4,r4,r8
+	eor	r2,r4,r2,lsl#1	@ tp4
+
+	and	r4,r2,r7
+	and	r3,r2,r9
+	sub	r4,r4,r4,lsr#7
+	and	r4,r4,r8
+	eor	r3,r4,r3,lsl#1	@ tp8
+
+	eor	r4,r1,r2
+	eor	r5,r0,r3		@ tp9
+	eor	r4,r4,r3		@ tpe
+	eor	r4,r4,r1,ror#24
+	eor	r4,r4,r5,ror#24	@ ^= ROTATE(tpb=tp9^tp2,8)
+	eor	r4,r4,r2,ror#16
+	eor	r4,r4,r5,ror#16	@ ^= ROTATE(tpd=tp9^tp4,16)
+	eor	r4,r4,r5,ror#8	@ ^= ROTATE(tp9,24)
+
+	ldr	r0,[r11,#4]		@ prefetch tp1
+	str	r4,[r11],#4
+	subs	r12,r12,#1
+	bne	.Lmix
+
+	mov	r0,#0
+#if __ARM_ARCH__>=5
+	ldmia	sp!,{r4-r12,pc}
+#else
+	ldmia   sp!,{r4-r12,lr}
+	tst	lr,#1
+	moveq	pc,lr			@ be binary compatible with V4, yet
+	.word	0xe12fff1e			@ interoperable with Thumb ISA:-)
+#endif
+.size	private_AES_set_decrypt_key,.-private_AES_set_decrypt_key
+
+.type	AES_Td,%object
+.align	5
+AES_Td:
+.word	0x51f4a750, 0x7e416553, 0x1a17a4c3, 0x3a275e96
+.word	0x3bab6bcb, 0x1f9d45f1, 0xacfa58ab, 0x4be30393
+.word	0x2030fa55, 0xad766df6, 0x88cc7691, 0xf5024c25
+.word	0x4fe5d7fc, 0xc52acbd7, 0x26354480, 0xb562a38f
+.word	0xdeb15a49, 0x25ba1b67, 0x45ea0e98, 0x5dfec0e1
+.word	0xc32f7502, 0x814cf012, 0x8d4697a3, 0x6bd3f9c6
+.word	0x038f5fe7, 0x15929c95, 0xbf6d7aeb, 0x955259da
+.word	0xd4be832d, 0x587421d3, 0x49e06929, 0x8ec9c844
+.word	0x75c2896a, 0xf48e7978, 0x99583e6b, 0x27b971dd
+.word	0xbee14fb6, 0xf088ad17, 0xc920ac66, 0x7dce3ab4
+.word	0x63df4a18, 0xe51a3182, 0x97513360, 0x62537f45
+.word	0xb16477e0, 0xbb6bae84, 0xfe81a01c, 0xf9082b94
+.word	0x70486858, 0x8f45fd19, 0x94de6c87, 0x527bf8b7
+.word	0xab73d323, 0x724b02e2, 0xe31f8f57, 0x6655ab2a
+.word	0xb2eb2807, 0x2fb5c203, 0x86c57b9a, 0xd33708a5
+.word	0x302887f2, 0x23bfa5b2, 0x02036aba, 0xed16825c
+.word	0x8acf1c2b, 0xa779b492, 0xf307f2f0, 0x4e69e2a1
+.word	0x65daf4cd, 0x0605bed5, 0xd134621f, 0xc4a6fe8a
+.word	0x342e539d, 0xa2f355a0, 0x058ae132, 0xa4f6eb75
+.word	0x0b83ec39, 0x4060efaa, 0x5e719f06, 0xbd6e1051
+.word	0x3e218af9, 0x96dd063d, 0xdd3e05ae, 0x4de6bd46
+.word	0x91548db5, 0x71c45d05, 0x0406d46f, 0x605015ff
+.word	0x1998fb24, 0xd6bde997, 0x894043cc, 0x67d99e77
+.word	0xb0e842bd, 0x07898b88, 0xe7195b38, 0x79c8eedb
+.word	0xa17c0a47, 0x7c420fe9, 0xf8841ec9, 0x00000000
+.word	0x09808683, 0x322bed48, 0x1e1170ac, 0x6c5a724e
+.word	0xfd0efffb, 0x0f853856, 0x3daed51e, 0x362d3927
+.word	0x0a0fd964, 0x685ca621, 0x9b5b54d1, 0x24362e3a
+.word	0x0c0a67b1, 0x9357e70f, 0xb4ee96d2, 0x1b9b919e
+.word	0x80c0c54f, 0x61dc20a2, 0x5a774b69, 0x1c121a16
+.word	0xe293ba0a, 0xc0a02ae5, 0x3c22e043, 0x121b171d
+.word	0x0e090d0b, 0xf28bc7ad, 0x2db6a8b9, 0x141ea9c8
+.word	0x57f11985, 0xaf75074c, 0xee99ddbb, 0xa37f60fd
+.word	0xf701269f, 0x5c72f5bc, 0x44663bc5, 0x5bfb7e34
+.word	0x8b432976, 0xcb23c6dc, 0xb6edfc68, 0xb8e4f163
+.word	0xd731dcca, 0x42638510, 0x13972240, 0x84c61120
+.word	0x854a247d, 0xd2bb3df8, 0xaef93211, 0xc729a16d
+.word	0x1d9e2f4b, 0xdcb230f3, 0x0d8652ec, 0x77c1e3d0
+.word	0x2bb3166c, 0xa970b999, 0x119448fa, 0x47e96422
+.word	0xa8fc8cc4, 0xa0f03f1a, 0x567d2cd8, 0x223390ef
+.word	0x87494ec7, 0xd938d1c1, 0x8ccaa2fe, 0x98d40b36
+.word	0xa6f581cf, 0xa57ade28, 0xdab78e26, 0x3fadbfa4
+.word	0x2c3a9de4, 0x5078920d, 0x6a5fcc9b, 0x547e4662
+.word	0xf68d13c2, 0x90d8b8e8, 0x2e39f75e, 0x82c3aff5
+.word	0x9f5d80be, 0x69d0937c, 0x6fd52da9, 0xcf2512b3
+.word	0xc8ac993b, 0x10187da7, 0xe89c636e, 0xdb3bbb7b
+.word	0xcd267809, 0x6e5918f4, 0xec9ab701, 0x834f9aa8
+.word	0xe6956e65, 0xaaffe67e, 0x21bccf08, 0xef15e8e6
+.word	0xbae79bd9, 0x4a6f36ce, 0xea9f09d4, 0x29b07cd6
+.word	0x31a4b2af, 0x2a3f2331, 0xc6a59430, 0x35a266c0
+.word	0x744ebc37, 0xfc82caa6, 0xe090d0b0, 0x33a7d815
+.word	0xf104984a, 0x41ecdaf7, 0x7fcd500e, 0x1791f62f
+.word	0x764dd68d, 0x43efb04d, 0xccaa4d54, 0xe49604df
+.word	0x9ed1b5e3, 0x4c6a881b, 0xc12c1fb8, 0x4665517f
+.word	0x9d5eea04, 0x018c355d, 0xfa877473, 0xfb0b412e
+.word	0xb3671d5a, 0x92dbd252, 0xe9105633, 0x6dd64713
+.word	0x9ad7618c, 0x37a10c7a, 0x59f8148e, 0xeb133c89
+.word	0xcea927ee, 0xb761c935, 0xe11ce5ed, 0x7a47b13c
+.word	0x9cd2df59, 0x55f2733f, 0x1814ce79, 0x73c737bf
+.word	0x53f7cdea, 0x5ffdaa5b, 0xdf3d6f14, 0x7844db86
+.word	0xcaaff381, 0xb968c43e, 0x3824342c, 0xc2a3405f
+.word	0x161dc372, 0xbce2250c, 0x283c498b, 0xff0d9541
+.word	0x39a80171, 0x080cb3de, 0xd8b4e49c, 0x6456c190
+.word	0x7bcb8461, 0xd532b670, 0x486c5c74, 0xd0b85742
+@ Td4[256]
+.byte	0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38
+.byte	0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb
+.byte	0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87
+.byte	0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb
+.byte	0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d
+.byte	0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e
+.byte	0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2
+.byte	0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25
+.byte	0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16
+.byte	0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92
+.byte	0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda
+.byte	0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84
+.byte	0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a
+.byte	0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06
+.byte	0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02
+.byte	0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b
+.byte	0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea
+.byte	0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73
+.byte	0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85
+.byte	0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e
+.byte	0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89
+.byte	0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b
+.byte	0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20
+.byte	0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4
+.byte	0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31
+.byte	0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f
+.byte	0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d
+.byte	0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef
+.byte	0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0
+.byte	0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61
+.byte	0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26
+.byte	0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
+.size	AES_Td,.-AES_Td
+
+@ void AES_decrypt(const unsigned char *in, unsigned char *out,
+@ 		 const AES_KEY *key) {
+.global AES_decrypt
+.type   AES_decrypt,%function
+.align	5
+AES_decrypt:
+	sub	r3,pc,#8		@ AES_decrypt
+	stmdb   sp!,{r1,r4-r12,lr}
+	mov	r12,r0		@ inp
+	mov	r11,r2
+	sub	r10,r3,#AES_decrypt-AES_Td		@ Td
+#if __ARM_ARCH__<7
+	ldrb	r0,[r12,#3]	@ load input data in endian-neutral
+	ldrb	r4,[r12,#2]	@ manner...
+	ldrb	r5,[r12,#1]
+	ldrb	r6,[r12,#0]
+	orr	r0,r0,r4,lsl#8
+	ldrb	r1,[r12,#7]
+	orr	r0,r0,r5,lsl#16
+	ldrb	r4,[r12,#6]
+	orr	r0,r0,r6,lsl#24
+	ldrb	r5,[r12,#5]
+	ldrb	r6,[r12,#4]
+	orr	r1,r1,r4,lsl#8
+	ldrb	r2,[r12,#11]
+	orr	r1,r1,r5,lsl#16
+	ldrb	r4,[r12,#10]
+	orr	r1,r1,r6,lsl#24
+	ldrb	r5,[r12,#9]
+	ldrb	r6,[r12,#8]
+	orr	r2,r2,r4,lsl#8
+	ldrb	r3,[r12,#15]
+	orr	r2,r2,r5,lsl#16
+	ldrb	r4,[r12,#14]
+	orr	r2,r2,r6,lsl#24
+	ldrb	r5,[r12,#13]
+	ldrb	r6,[r12,#12]
+	orr	r3,r3,r4,lsl#8
+	orr	r3,r3,r5,lsl#16
+	orr	r3,r3,r6,lsl#24
+#else
+	ldr	r0,[r12,#0]
+	ldr	r1,[r12,#4]
+	ldr	r2,[r12,#8]
+	ldr	r3,[r12,#12]
+#ifdef __ARMEL__
+	rev	r0,r0
+	rev	r1,r1
+	rev	r2,r2
+	rev	r3,r3
+#endif
+#endif
+	bl	_armv4_AES_decrypt
+
+	ldr	r12,[sp],#4		@ pop out
+#if __ARM_ARCH__>=7
+#ifdef __ARMEL__
+	rev	r0,r0
+	rev	r1,r1
+	rev	r2,r2
+	rev	r3,r3
+#endif
+	str	r0,[r12,#0]
+	str	r1,[r12,#4]
+	str	r2,[r12,#8]
+	str	r3,[r12,#12]
+#else
+	mov	r4,r0,lsr#24		@ write output in endian-neutral
+	mov	r5,r0,lsr#16		@ manner...
+	mov	r6,r0,lsr#8
+	strb	r4,[r12,#0]
+	strb	r5,[r12,#1]
+	mov	r4,r1,lsr#24
+	strb	r6,[r12,#2]
+	mov	r5,r1,lsr#16
+	strb	r0,[r12,#3]
+	mov	r6,r1,lsr#8
+	strb	r4,[r12,#4]
+	strb	r5,[r12,#5]
+	mov	r4,r2,lsr#24
+	strb	r6,[r12,#6]
+	mov	r5,r2,lsr#16
+	strb	r1,[r12,#7]
+	mov	r6,r2,lsr#8
+	strb	r4,[r12,#8]
+	strb	r5,[r12,#9]
+	mov	r4,r3,lsr#24
+	strb	r6,[r12,#10]
+	mov	r5,r3,lsr#16
+	strb	r2,[r12,#11]
+	mov	r6,r3,lsr#8
+	strb	r4,[r12,#12]
+	strb	r5,[r12,#13]
+	strb	r6,[r12,#14]
+	strb	r3,[r12,#15]
+#endif
+#if __ARM_ARCH__>=5
+	ldmia	sp!,{r4-r12,pc}
+#else
+	ldmia   sp!,{r4-r12,lr}
+	tst	lr,#1
+	moveq	pc,lr			@ be binary compatible with V4, yet
+	.word	0xe12fff1e			@ interoperable with Thumb ISA:-)
+#endif
+.size	AES_decrypt,.-AES_decrypt
+
+.type   _armv4_AES_decrypt,%function
+.align	2
+_armv4_AES_decrypt:
+	str	lr,[sp,#-4]!		@ push lr
+	ldmia	r11!,{r4-r7}
+	eor	r0,r0,r4
+	ldr	r12,[r11,#240-16]
+	eor	r1,r1,r5
+	eor	r2,r2,r6
+	eor	r3,r3,r7
+	sub	r12,r12,#1
+	mov	lr,#255
+
+	and	r7,lr,r0,lsr#16
+	and	r8,lr,r0,lsr#8
+	and	r9,lr,r0
+	mov	r0,r0,lsr#24
+.Ldec_loop:
+	ldr	r4,[r10,r7,lsl#2]	@ Td1[s0>>16]
+	and	r7,lr,r1		@ i0
+	ldr	r5,[r10,r8,lsl#2]	@ Td2[s0>>8]
+	and	r8,lr,r1,lsr#16
+	ldr	r6,[r10,r9,lsl#2]	@ Td3[s0>>0]
+	and	r9,lr,r1,lsr#8
+	ldr	r0,[r10,r0,lsl#2]	@ Td0[s0>>24]
+	mov	r1,r1,lsr#24
+
+	ldr	r7,[r10,r7,lsl#2]	@ Td3[s1>>0]
+	ldr	r8,[r10,r8,lsl#2]	@ Td1[s1>>16]
+	ldr	r9,[r10,r9,lsl#2]	@ Td2[s1>>8]
+	eor	r0,r0,r7,ror#24
+	ldr	r1,[r10,r1,lsl#2]	@ Td0[s1>>24]
+	and	r7,lr,r2,lsr#8	@ i0
+	eor	r5,r8,r5,ror#8
+	and	r8,lr,r2		@ i1
+	eor	r6,r9,r6,ror#8
+	and	r9,lr,r2,lsr#16
+	ldr	r7,[r10,r7,lsl#2]	@ Td2[s2>>8]
+	eor	r1,r1,r4,ror#8
+	ldr	r8,[r10,r8,lsl#2]	@ Td3[s2>>0]
+	mov	r2,r2,lsr#24
+
+	ldr	r9,[r10,r9,lsl#2]	@ Td1[s2>>16]
+	eor	r0,r0,r7,ror#16
+	ldr	r2,[r10,r2,lsl#2]	@ Td0[s2>>24]
+	and	r7,lr,r3,lsr#16	@ i0
+	eor	r1,r1,r8,ror#24
+	and	r8,lr,r3,lsr#8	@ i1
+	eor	r6,r9,r6,ror#8
+	and	r9,lr,r3		@ i2
+	ldr	r7,[r10,r7,lsl#2]	@ Td1[s3>>16]
+	eor	r2,r2,r5,ror#8
+	ldr	r8,[r10,r8,lsl#2]	@ Td2[s3>>8]
+	mov	r3,r3,lsr#24
+
+	ldr	r9,[r10,r9,lsl#2]	@ Td3[s3>>0]
+	eor	r0,r0,r7,ror#8
+	ldr	r7,[r11],#16
+	eor	r1,r1,r8,ror#16
+	ldr	r3,[r10,r3,lsl#2]	@ Td0[s3>>24]
+	eor	r2,r2,r9,ror#24
+
+	ldr	r4,[r11,#-12]
+	eor	r0,r0,r7
+	ldr	r5,[r11,#-8]
+	eor	r3,r3,r6,ror#8
+	ldr	r6,[r11,#-4]
+	and	r7,lr,r0,lsr#16
+	eor	r1,r1,r4
+	and	r8,lr,r0,lsr#8
+	eor	r2,r2,r5
+	and	r9,lr,r0
+	eor	r3,r3,r6
+	mov	r0,r0,lsr#24
+
+	subs	r12,r12,#1
+	bne	.Ldec_loop
+
+	add	r10,r10,#1024
+
+	ldr	r5,[r10,#0]		@ prefetch Td4
+	ldr	r6,[r10,#32]
+	ldr	r4,[r10,#64]
+	ldr	r5,[r10,#96]
+	ldr	r6,[r10,#128]
+	ldr	r4,[r10,#160]
+	ldr	r5,[r10,#192]
+	ldr	r6,[r10,#224]
+
+	ldrb	r0,[r10,r0]		@ Td4[s0>>24]
+	ldrb	r4,[r10,r7]		@ Td4[s0>>16]
+	and	r7,lr,r1		@ i0
+	ldrb	r5,[r10,r8]		@ Td4[s0>>8]
+	and	r8,lr,r1,lsr#16
+	ldrb	r6,[r10,r9]		@ Td4[s0>>0]
+	and	r9,lr,r1,lsr#8
+
+	ldrb	r7,[r10,r7]		@ Td4[s1>>0]
+	ldrb	r1,[r10,r1,lsr#24]	@ Td4[s1>>24]
+	ldrb	r8,[r10,r8]		@ Td4[s1>>16]
+	eor	r0,r7,r0,lsl#24
+	ldrb	r9,[r10,r9]		@ Td4[s1>>8]
+	eor	r1,r4,r1,lsl#8
+	and	r7,lr,r2,lsr#8	@ i0
+	eor	r5,r5,r8,lsl#8
+	and	r8,lr,r2		@ i1
+	ldrb	r7,[r10,r7]		@ Td4[s2>>8]
+	eor	r6,r6,r9,lsl#8
+	ldrb	r8,[r10,r8]		@ Td4[s2>>0]
+	and	r9,lr,r2,lsr#16
+
+	ldrb	r2,[r10,r2,lsr#24]	@ Td4[s2>>24]
+	eor	r0,r0,r7,lsl#8
+	ldrb	r9,[r10,r9]		@ Td4[s2>>16]
+	eor	r1,r8,r1,lsl#16
+	and	r7,lr,r3,lsr#16	@ i0
+	eor	r2,r5,r2,lsl#16
+	and	r8,lr,r3,lsr#8	@ i1
+	ldrb	r7,[r10,r7]		@ Td4[s3>>16]
+	eor	r6,r6,r9,lsl#16
+	ldrb	r8,[r10,r8]		@ Td4[s3>>8]
+	and	r9,lr,r3		@ i2
+
+	ldrb	r9,[r10,r9]		@ Td4[s3>>0]
+	ldrb	r3,[r10,r3,lsr#24]	@ Td4[s3>>24]
+	eor	r0,r0,r7,lsl#16
+	ldr	r7,[r11,#0]
+	eor	r1,r1,r8,lsl#8
+	ldr	r4,[r11,#4]
+	eor	r2,r9,r2,lsl#8
+	ldr	r5,[r11,#8]
+	eor	r3,r6,r3,lsl#24
+	ldr	r6,[r11,#12]
+
+	eor	r0,r0,r7
+	eor	r1,r1,r4
+	eor	r2,r2,r5
+	eor	r3,r3,r6
+
+	sub	r10,r10,#1024
+	ldr	pc,[sp],#4		@ pop and return
+.size	_armv4_AES_decrypt,.-_armv4_AES_decrypt
+.asciz	"AES for ARMv4, CRYPTOGAMS by <appro@openssl.org>"
+.align	2
diff --git a/arch/arm/crypto/aes_glue.c b/arch/arm/crypto/aes_glue.c
new file mode 100644
index 0000000..59f7877
--- /dev/null
+++ b/arch/arm/crypto/aes_glue.c
@@ -0,0 +1,108 @@
+/*
+ * Glue Code for the asm optimized version of the AES Cipher Algorithm
+ */
+
+#include <linux/module.h>
+#include <linux/crypto.h>
+#include <crypto/aes.h>
+
+#define AES_MAXNR 14
+
+typedef struct {
+	unsigned int rd_key[4 *(AES_MAXNR + 1)];
+	int rounds;
+} AES_KEY;
+
+struct AES_CTX {
+	AES_KEY enc_key;
+	AES_KEY dec_key;
+};
+
+asmlinkage void AES_encrypt(const u8 *in, u8 *out, AES_KEY *ctx);
+asmlinkage void AES_decrypt(const u8 *in, u8 *out, AES_KEY *ctx);
+asmlinkage int private_AES_set_decrypt_key(const unsigned char *userKey, const int bits, AES_KEY *key);
+asmlinkage int private_AES_set_encrypt_key(const unsigned char *userKey, const int bits, AES_KEY *key);
+
+static void aes_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
+{
+	struct AES_CTX *ctx = crypto_tfm_ctx(tfm);
+	AES_encrypt(src, dst, &ctx->enc_key);
+}
+
+static void aes_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
+{
+	struct AES_CTX *ctx = crypto_tfm_ctx(tfm);
+	AES_decrypt(src, dst, &ctx->dec_key);
+}
+
+static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
+		unsigned int key_len)
+{
+	struct AES_CTX *ctx = crypto_tfm_ctx(tfm);
+
+	switch (key_len) {
+	case AES_KEYSIZE_128:
+		key_len = 128;
+		break;
+	case AES_KEYSIZE_192:
+		key_len = 192;
+		break;
+	case AES_KEYSIZE_256:
+		key_len = 256;
+		break;
+	default:
+		tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+		return -EINVAL;
+	}
+
+	if (private_AES_set_encrypt_key(in_key, key_len, &ctx->enc_key) == -1) {
+		tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+		return -EINVAL;
+	}
+	/* private_AES_set_decrypt_key expects an encryption key as input */
+	ctx->dec_key = ctx->enc_key;
+	if (private_AES_set_decrypt_key(in_key, key_len, &ctx->dec_key) == -1) {
+		tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static struct crypto_alg aes_alg = {
+	.cra_name		= "aes",
+	.cra_driver_name	= "aes-asm",
+	.cra_priority		= 200,
+	.cra_flags		= CRYPTO_ALG_TYPE_CIPHER,
+	.cra_blocksize		= AES_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct AES_CTX),
+	.cra_module		= THIS_MODULE,
+	.cra_list		= LIST_HEAD_INIT(aes_alg.cra_list),
+	.cra_u	= {
+		.cipher	= {
+			.cia_min_keysize	= AES_MIN_KEY_SIZE,
+			.cia_max_keysize	= AES_MAX_KEY_SIZE,
+			.cia_setkey			= aes_set_key,
+			.cia_encrypt		= aes_encrypt,
+			.cia_decrypt		= aes_decrypt
+		}
+	}
+};
+
+static int __init aes_init(void)
+{
+	return crypto_register_alg(&aes_alg);
+}
+
+static void __exit aes_fini(void)
+{
+	crypto_unregister_alg(&aes_alg);
+}
+
+module_init(aes_init);
+module_exit(aes_fini);
+
+MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm (ASM)");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("aes");
+MODULE_ALIAS("aes-asm");
+MODULE_AUTHOR("David McCullough <ucdevel@gmail.com>");
diff --git a/arch/arm/crypto/sha1-armv4-large.S b/arch/arm/crypto/sha1-armv4-large.S
new file mode 100644
index 0000000..7050ab1
--- /dev/null
+++ b/arch/arm/crypto/sha1-armv4-large.S
@@ -0,0 +1,503 @@
+#define __ARM_ARCH__ __LINUX_ARM_ARCH__
+@ ====================================================================
+@ Written by Andy Polyakov <appro@fy.chalmers.se> for the OpenSSL
+@ project. The module is, however, dual licensed under OpenSSL and
+@ CRYPTOGAMS licenses depending on where you obtain it. For further
+@ details see http://www.openssl.org/~appro/cryptogams/.
+@ ====================================================================
+
+@ sha1_block procedure for ARMv4.
+@
+@ January 2007.
+
+@ Size/performance trade-off
+@ ====================================================================
+@ impl		size in bytes	comp cycles[*]	measured performance
+@ ====================================================================
+@ thumb		304		3212		4420
+@ armv4-small	392/+29%	1958/+64%	2250/+96%
+@ armv4-compact	740/+89%	1552/+26%	1840/+22%
+@ armv4-large	1420/+92%	1307/+19%	1370/+34%[***]
+@ full unroll	~5100/+260%	~1260/+4%	~1300/+5%
+@ ====================================================================
+@ thumb		= same as 'small' but in Thumb instructions[**] and
+@		  with recurring code in two private functions;
+@ small		= detached Xload/update, loops are folded;
+@ compact	= detached Xload/update, 5x unroll;
+@ large		= interleaved Xload/update, 5x unroll;
+@ full unroll	= interleaved Xload/update, full unroll, estimated[!];
+@
+@ [*]	Manually counted instructions in "grand" loop body. Measured
+@	performance is affected by prologue and epilogue overhead,
+@	i-cache availability, branch penalties, etc.
+@ [**]	While each Thumb instruction is twice smaller, they are not as
+@	diverse as ARM ones: e.g., there are only two arithmetic
+@	instructions with 3 arguments, no [fixed] rotate, addressing
+@	modes are limited. As result it takes more instructions to do
+@	the same job in Thumb, therefore the code is never twice as
+@	small and always slower.
+@ [***]	which is also ~35% better than compiler generated code. Dual-
+@	issue Cortex A8 core was measured to process input block in
+@	~990 cycles.
+
+@ August 2010.
+@
+@ Rescheduling for dual-issue pipeline resulted in 13% improvement on
+@ Cortex A8 core and in absolute terms ~870 cycles per input block
+@ [or 13.6 cycles per byte].
+
+@ February 2011.
+@
+@ Profiler-assisted and platform-specific optimization resulted in 10%
+@ improvement on Cortex A8 core and 12.2 cycles per byte.
+
+.text
+
+.global	sha1_block_data_order
+.type	sha1_block_data_order,%function
+
+.align	2
+sha1_block_data_order:
+	stmdb	sp!,{r4-r12,lr}
+	add	r2,r1,r2,lsl#6	@ r2 to point at the end of r1
+	ldmia	r0,{r3,r4,r5,r6,r7}
+.Lloop:
+	ldr	r8,.LK_00_19
+	mov	r14,sp
+	sub	sp,sp,#15*4
+	mov	r5,r5,ror#30
+	mov	r6,r6,ror#30
+	mov	r7,r7,ror#30		@ [6]
+.L_00_15:
+#if __ARM_ARCH__<7
+	ldrb	r10,[r1,#2]
+	ldrb	r9,[r1,#3]
+	ldrb	r11,[r1,#1]
+	add	r7,r8,r7,ror#2			@ E+=K_00_19
+	ldrb	r12,[r1],#4
+	orr	r9,r9,r10,lsl#8
+	eor	r10,r5,r6			@ F_xx_xx
+	orr	r9,r9,r11,lsl#16
+	add	r7,r7,r3,ror#27			@ E+=ROR(A,27)
+	orr	r9,r9,r12,lsl#24
+#else
+	ldr	r9,[r1],#4			@ handles unaligned
+	add	r7,r8,r7,ror#2			@ E+=K_00_19
+	eor	r10,r5,r6			@ F_xx_xx
+	add	r7,r7,r3,ror#27			@ E+=ROR(A,27)
+#ifdef __ARMEL__
+	rev	r9,r9				@ byte swap
+#endif
+#endif
+	and	r10,r4,r10,ror#2
+	add	r7,r7,r9			@ E+=X[i]
+	eor	r10,r10,r6,ror#2		@ F_00_19(B,C,D)
+	str	r9,[r14,#-4]!
+	add	r7,r7,r10			@ E+=F_00_19(B,C,D)
+#if __ARM_ARCH__<7
+	ldrb	r10,[r1,#2]
+	ldrb	r9,[r1,#3]
+	ldrb	r11,[r1,#1]
+	add	r6,r8,r6,ror#2			@ E+=K_00_19
+	ldrb	r12,[r1],#4
+	orr	r9,r9,r10,lsl#8
+	eor	r10,r4,r5			@ F_xx_xx
+	orr	r9,r9,r11,lsl#16
+	add	r6,r6,r7,ror#27			@ E+=ROR(A,27)
+	orr	r9,r9,r12,lsl#24
+#else
+	ldr	r9,[r1],#4			@ handles unaligned
+	add	r6,r8,r6,ror#2			@ E+=K_00_19
+	eor	r10,r4,r5			@ F_xx_xx
+	add	r6,r6,r7,ror#27			@ E+=ROR(A,27)
+#ifdef __ARMEL__
+	rev	r9,r9				@ byte swap
+#endif
+#endif
+	and	r10,r3,r10,ror#2
+	add	r6,r6,r9			@ E+=X[i]
+	eor	r10,r10,r5,ror#2		@ F_00_19(B,C,D)
+	str	r9,[r14,#-4]!
+	add	r6,r6,r10			@ E+=F_00_19(B,C,D)
+#if __ARM_ARCH__<7
+	ldrb	r10,[r1,#2]
+	ldrb	r9,[r1,#3]
+	ldrb	r11,[r1,#1]
+	add	r5,r8,r5,ror#2			@ E+=K_00_19
+	ldrb	r12,[r1],#4
+	orr	r9,r9,r10,lsl#8
+	eor	r10,r3,r4			@ F_xx_xx
+	orr	r9,r9,r11,lsl#16
+	add	r5,r5,r6,ror#27			@ E+=ROR(A,27)
+	orr	r9,r9,r12,lsl#24
+#else
+	ldr	r9,[r1],#4			@ handles unaligned
+	add	r5,r8,r5,ror#2			@ E+=K_00_19
+	eor	r10,r3,r4			@ F_xx_xx
+	add	r5,r5,r6,ror#27			@ E+=ROR(A,27)
+#ifdef __ARMEL__
+	rev	r9,r9				@ byte swap
+#endif
+#endif
+	and	r10,r7,r10,ror#2
+	add	r5,r5,r9			@ E+=X[i]
+	eor	r10,r10,r4,ror#2		@ F_00_19(B,C,D)
+	str	r9,[r14,#-4]!
+	add	r5,r5,r10			@ E+=F_00_19(B,C,D)
+#if __ARM_ARCH__<7
+	ldrb	r10,[r1,#2]
+	ldrb	r9,[r1,#3]
+	ldrb	r11,[r1,#1]
+	add	r4,r8,r4,ror#2			@ E+=K_00_19
+	ldrb	r12,[r1],#4
+	orr	r9,r9,r10,lsl#8
+	eor	r10,r7,r3			@ F_xx_xx
+	orr	r9,r9,r11,lsl#16
+	add	r4,r4,r5,ror#27			@ E+=ROR(A,27)
+	orr	r9,r9,r12,lsl#24
+#else
+	ldr	r9,[r1],#4			@ handles unaligned
+	add	r4,r8,r4,ror#2			@ E+=K_00_19
+	eor	r10,r7,r3			@ F_xx_xx
+	add	r4,r4,r5,ror#27			@ E+=ROR(A,27)
+#ifdef __ARMEL__
+	rev	r9,r9				@ byte swap
+#endif
+#endif
+	and	r10,r6,r10,ror#2
+	add	r4,r4,r9			@ E+=X[i]
+	eor	r10,r10,r3,ror#2		@ F_00_19(B,C,D)
+	str	r9,[r14,#-4]!
+	add	r4,r4,r10			@ E+=F_00_19(B,C,D)
+#if __ARM_ARCH__<7
+	ldrb	r10,[r1,#2]
+	ldrb	r9,[r1,#3]
+	ldrb	r11,[r1,#1]
+	add	r3,r8,r3,ror#2			@ E+=K_00_19
+	ldrb	r12,[r1],#4
+	orr	r9,r9,r10,lsl#8
+	eor	r10,r6,r7			@ F_xx_xx
+	orr	r9,r9,r11,lsl#16
+	add	r3,r3,r4,ror#27			@ E+=ROR(A,27)
+	orr	r9,r9,r12,lsl#24
+#else
+	ldr	r9,[r1],#4			@ handles unaligned
+	add	r3,r8,r3,ror#2			@ E+=K_00_19
+	eor	r10,r6,r7			@ F_xx_xx
+	add	r3,r3,r4,ror#27			@ E+=ROR(A,27)
+#ifdef __ARMEL__
+	rev	r9,r9				@ byte swap
+#endif
+#endif
+	and	r10,r5,r10,ror#2
+	add	r3,r3,r9			@ E+=X[i]
+	eor	r10,r10,r7,ror#2		@ F_00_19(B,C,D)
+	str	r9,[r14,#-4]!
+	add	r3,r3,r10			@ E+=F_00_19(B,C,D)
+	teq	r14,sp
+	bne	.L_00_15		@ [((11+4)*5+2)*3]
+#if __ARM_ARCH__<7
+	ldrb	r10,[r1,#2]
+	ldrb	r9,[r1,#3]
+	ldrb	r11,[r1,#1]
+	add	r7,r8,r7,ror#2			@ E+=K_00_19
+	ldrb	r12,[r1],#4
+	orr	r9,r9,r10,lsl#8
+	eor	r10,r5,r6			@ F_xx_xx
+	orr	r9,r9,r11,lsl#16
+	add	r7,r7,r3,ror#27			@ E+=ROR(A,27)
+	orr	r9,r9,r12,lsl#24
+#else
+	ldr	r9,[r1],#4			@ handles unaligned
+	add	r7,r8,r7,ror#2			@ E+=K_00_19
+	eor	r10,r5,r6			@ F_xx_xx
+	add	r7,r7,r3,ror#27			@ E+=ROR(A,27)
+#ifdef __ARMEL__
+	rev	r9,r9				@ byte swap
+#endif
+#endif
+	and	r10,r4,r10,ror#2
+	add	r7,r7,r9			@ E+=X[i]
+	eor	r10,r10,r6,ror#2		@ F_00_19(B,C,D)
+	str	r9,[r14,#-4]!
+	add	r7,r7,r10			@ E+=F_00_19(B,C,D)
+	ldr	r9,[r14,#15*4]
+	ldr	r10,[r14,#13*4]
+	ldr	r11,[r14,#7*4]
+	add	r6,r8,r6,ror#2			@ E+=K_xx_xx
+	ldr	r12,[r14,#2*4]
+	eor	r9,r9,r10
+	eor	r11,r11,r12			@ 1 cycle stall
+	eor	r10,r4,r5			@ F_xx_xx
+	mov	r9,r9,ror#31
+	add	r6,r6,r7,ror#27			@ E+=ROR(A,27)
+	eor	r9,r9,r11,ror#31
+	str	r9,[r14,#-4]!
+	and r10,r3,r10,ror#2					@ F_xx_xx
+						@ F_xx_xx
+	add	r6,r6,r9			@ E+=X[i]
+	eor	r10,r10,r5,ror#2		@ F_00_19(B,C,D)
+	add	r6,r6,r10			@ E+=F_00_19(B,C,D)
+	ldr	r9,[r14,#15*4]
+	ldr	r10,[r14,#13*4]
+	ldr	r11,[r14,#7*4]
+	add	r5,r8,r5,ror#2			@ E+=K_xx_xx
+	ldr	r12,[r14,#2*4]
+	eor	r9,r9,r10
+	eor	r11,r11,r12			@ 1 cycle stall
+	eor	r10,r3,r4			@ F_xx_xx
+	mov	r9,r9,ror#31
+	add	r5,r5,r6,ror#27			@ E+=ROR(A,27)
+	eor	r9,r9,r11,ror#31
+	str	r9,[r14,#-4]!
+	and r10,r7,r10,ror#2					@ F_xx_xx
+						@ F_xx_xx
+	add	r5,r5,r9			@ E+=X[i]
+	eor	r10,r10,r4,ror#2		@ F_00_19(B,C,D)
+	add	r5,r5,r10			@ E+=F_00_19(B,C,D)
+	ldr	r9,[r14,#15*4]
+	ldr	r10,[r14,#13*4]
+	ldr	r11,[r14,#7*4]
+	add	r4,r8,r4,ror#2			@ E+=K_xx_xx
+	ldr	r12,[r14,#2*4]
+	eor	r9,r9,r10
+	eor	r11,r11,r12			@ 1 cycle stall
+	eor	r10,r7,r3			@ F_xx_xx
+	mov	r9,r9,ror#31
+	add	r4,r4,r5,ror#27			@ E+=ROR(A,27)
+	eor	r9,r9,r11,ror#31
+	str	r9,[r14,#-4]!
+	and r10,r6,r10,ror#2					@ F_xx_xx
+						@ F_xx_xx
+	add	r4,r4,r9			@ E+=X[i]
+	eor	r10,r10,r3,ror#2		@ F_00_19(B,C,D)
+	add	r4,r4,r10			@ E+=F_00_19(B,C,D)
+	ldr	r9,[r14,#15*4]
+	ldr	r10,[r14,#13*4]
+	ldr	r11,[r14,#7*4]
+	add	r3,r8,r3,ror#2			@ E+=K_xx_xx
+	ldr	r12,[r14,#2*4]
+	eor	r9,r9,r10
+	eor	r11,r11,r12			@ 1 cycle stall
+	eor	r10,r6,r7			@ F_xx_xx
+	mov	r9,r9,ror#31
+	add	r3,r3,r4,ror#27			@ E+=ROR(A,27)
+	eor	r9,r9,r11,ror#31
+	str	r9,[r14,#-4]!
+	and r10,r5,r10,ror#2					@ F_xx_xx
+						@ F_xx_xx
+	add	r3,r3,r9			@ E+=X[i]
+	eor	r10,r10,r7,ror#2		@ F_00_19(B,C,D)
+	add	r3,r3,r10			@ E+=F_00_19(B,C,D)
+
+	ldr	r8,.LK_20_39		@ [+15+16*4]
+	sub	sp,sp,#25*4
+	cmn	sp,#0			@ [+3], clear carry to denote 20_39
+.L_20_39_or_60_79:
+	ldr	r9,[r14,#15*4]
+	ldr	r10,[r14,#13*4]
+	ldr	r11,[r14,#7*4]
+	add	r7,r8,r7,ror#2			@ E+=K_xx_xx
+	ldr	r12,[r14,#2*4]
+	eor	r9,r9,r10
+	eor	r11,r11,r12			@ 1 cycle stall
+	eor	r10,r5,r6			@ F_xx_xx
+	mov	r9,r9,ror#31
+	add	r7,r7,r3,ror#27			@ E+=ROR(A,27)
+	eor	r9,r9,r11,ror#31
+	str	r9,[r14,#-4]!
+	eor r10,r4,r10,ror#2					@ F_xx_xx
+						@ F_xx_xx
+	add	r7,r7,r9			@ E+=X[i]
+	add	r7,r7,r10			@ E+=F_20_39(B,C,D)
+	ldr	r9,[r14,#15*4]
+	ldr	r10,[r14,#13*4]
+	ldr	r11,[r14,#7*4]
+	add	r6,r8,r6,ror#2			@ E+=K_xx_xx
+	ldr	r12,[r14,#2*4]
+	eor	r9,r9,r10
+	eor	r11,r11,r12			@ 1 cycle stall
+	eor	r10,r4,r5			@ F_xx_xx
+	mov	r9,r9,ror#31
+	add	r6,r6,r7,ror#27			@ E+=ROR(A,27)
+	eor	r9,r9,r11,ror#31
+	str	r9,[r14,#-4]!
+	eor r10,r3,r10,ror#2					@ F_xx_xx
+						@ F_xx_xx
+	add	r6,r6,r9			@ E+=X[i]
+	add	r6,r6,r10			@ E+=F_20_39(B,C,D)
+	ldr	r9,[r14,#15*4]
+	ldr	r10,[r14,#13*4]
+	ldr	r11,[r14,#7*4]
+	add	r5,r8,r5,ror#2			@ E+=K_xx_xx
+	ldr	r12,[r14,#2*4]
+	eor	r9,r9,r10
+	eor	r11,r11,r12			@ 1 cycle stall
+	eor	r10,r3,r4			@ F_xx_xx
+	mov	r9,r9,ror#31
+	add	r5,r5,r6,ror#27			@ E+=ROR(A,27)
+	eor	r9,r9,r11,ror#31
+	str	r9,[r14,#-4]!
+	eor r10,r7,r10,ror#2					@ F_xx_xx
+						@ F_xx_xx
+	add	r5,r5,r9			@ E+=X[i]
+	add	r5,r5,r10			@ E+=F_20_39(B,C,D)
+	ldr	r9,[r14,#15*4]
+	ldr	r10,[r14,#13*4]
+	ldr	r11,[r14,#7*4]
+	add	r4,r8,r4,ror#2			@ E+=K_xx_xx
+	ldr	r12,[r14,#2*4]
+	eor	r9,r9,r10
+	eor	r11,r11,r12			@ 1 cycle stall
+	eor	r10,r7,r3			@ F_xx_xx
+	mov	r9,r9,ror#31
+	add	r4,r4,r5,ror#27			@ E+=ROR(A,27)
+	eor	r9,r9,r11,ror#31
+	str	r9,[r14,#-4]!
+	eor r10,r6,r10,ror#2					@ F_xx_xx
+						@ F_xx_xx
+	add	r4,r4,r9			@ E+=X[i]
+	add	r4,r4,r10			@ E+=F_20_39(B,C,D)
+	ldr	r9,[r14,#15*4]
+	ldr	r10,[r14,#13*4]
+	ldr	r11,[r14,#7*4]
+	add	r3,r8,r3,ror#2			@ E+=K_xx_xx
+	ldr	r12,[r14,#2*4]
+	eor	r9,r9,r10
+	eor	r11,r11,r12			@ 1 cycle stall
+	eor	r10,r6,r7			@ F_xx_xx
+	mov	r9,r9,ror#31
+	add	r3,r3,r4,ror#27			@ E+=ROR(A,27)
+	eor	r9,r9,r11,ror#31
+	str	r9,[r14,#-4]!
+	eor r10,r5,r10,ror#2					@ F_xx_xx
+						@ F_xx_xx
+	add	r3,r3,r9			@ E+=X[i]
+	add	r3,r3,r10			@ E+=F_20_39(B,C,D)
+	teq	r14,sp			@ preserve carry
+	bne	.L_20_39_or_60_79	@ [+((12+3)*5+2)*4]
+	bcs	.L_done			@ [+((12+3)*5+2)*4], spare 300 bytes
+
+	ldr	r8,.LK_40_59
+	sub	sp,sp,#20*4		@ [+2]
+.L_40_59:
+	ldr	r9,[r14,#15*4]
+	ldr	r10,[r14,#13*4]
+	ldr	r11,[r14,#7*4]
+	add	r7,r8,r7,ror#2			@ E+=K_xx_xx
+	ldr	r12,[r14,#2*4]
+	eor	r9,r9,r10
+	eor	r11,r11,r12			@ 1 cycle stall
+	eor	r10,r5,r6			@ F_xx_xx
+	mov	r9,r9,ror#31
+	add	r7,r7,r3,ror#27			@ E+=ROR(A,27)
+	eor	r9,r9,r11,ror#31
+	str	r9,[r14,#-4]!
+	and r10,r4,r10,ror#2					@ F_xx_xx
+	and r11,r5,r6					@ F_xx_xx
+	add	r7,r7,r9			@ E+=X[i]
+	add	r7,r7,r10			@ E+=F_40_59(B,C,D)
+	add	r7,r7,r11,ror#2
+	ldr	r9,[r14,#15*4]
+	ldr	r10,[r14,#13*4]
+	ldr	r11,[r14,#7*4]
+	add	r6,r8,r6,ror#2			@ E+=K_xx_xx
+	ldr	r12,[r14,#2*4]
+	eor	r9,r9,r10
+	eor	r11,r11,r12			@ 1 cycle stall
+	eor	r10,r4,r5			@ F_xx_xx
+	mov	r9,r9,ror#31
+	add	r6,r6,r7,ror#27			@ E+=ROR(A,27)
+	eor	r9,r9,r11,ror#31
+	str	r9,[r14,#-4]!
+	and r10,r3,r10,ror#2					@ F_xx_xx
+	and r11,r4,r5					@ F_xx_xx
+	add	r6,r6,r9			@ E+=X[i]
+	add	r6,r6,r10			@ E+=F_40_59(B,C,D)
+	add	r6,r6,r11,ror#2
+	ldr	r9,[r14,#15*4]
+	ldr	r10,[r14,#13*4]
+	ldr	r11,[r14,#7*4]
+	add	r5,r8,r5,ror#2			@ E+=K_xx_xx
+	ldr	r12,[r14,#2*4]
+	eor	r9,r9,r10
+	eor	r11,r11,r12			@ 1 cycle stall
+	eor	r10,r3,r4			@ F_xx_xx
+	mov	r9,r9,ror#31
+	add	r5,r5,r6,ror#27			@ E+=ROR(A,27)
+	eor	r9,r9,r11,ror#31
+	str	r9,[r14,#-4]!
+	and r10,r7,r10,ror#2					@ F_xx_xx
+	and r11,r3,r4					@ F_xx_xx
+	add	r5,r5,r9			@ E+=X[i]
+	add	r5,r5,r10			@ E+=F_40_59(B,C,D)
+	add	r5,r5,r11,ror#2
+	ldr	r9,[r14,#15*4]
+	ldr	r10,[r14,#13*4]
+	ldr	r11,[r14,#7*4]
+	add	r4,r8,r4,ror#2			@ E+=K_xx_xx
+	ldr	r12,[r14,#2*4]
+	eor	r9,r9,r10
+	eor	r11,r11,r12			@ 1 cycle stall
+	eor	r10,r7,r3			@ F_xx_xx
+	mov	r9,r9,ror#31
+	add	r4,r4,r5,ror#27			@ E+=ROR(A,27)
+	eor	r9,r9,r11,ror#31
+	str	r9,[r14,#-4]!
+	and r10,r6,r10,ror#2					@ F_xx_xx
+	and r11,r7,r3					@ F_xx_xx
+	add	r4,r4,r9			@ E+=X[i]
+	add	r4,r4,r10			@ E+=F_40_59(B,C,D)
+	add	r4,r4,r11,ror#2
+	ldr	r9,[r14,#15*4]
+	ldr	r10,[r14,#13*4]
+	ldr	r11,[r14,#7*4]
+	add	r3,r8,r3,ror#2			@ E+=K_xx_xx
+	ldr	r12,[r14,#2*4]
+	eor	r9,r9,r10
+	eor	r11,r11,r12			@ 1 cycle stall
+	eor	r10,r6,r7			@ F_xx_xx
+	mov	r9,r9,ror#31
+	add	r3,r3,r4,ror#27			@ E+=ROR(A,27)
+	eor	r9,r9,r11,ror#31
+	str	r9,[r14,#-4]!
+	and r10,r5,r10,ror#2					@ F_xx_xx
+	and r11,r6,r7					@ F_xx_xx
+	add	r3,r3,r9			@ E+=X[i]
+	add	r3,r3,r10			@ E+=F_40_59(B,C,D)
+	add	r3,r3,r11,ror#2
+	teq	r14,sp
+	bne	.L_40_59		@ [+((12+5)*5+2)*4]
+
+	ldr	r8,.LK_60_79
+	sub	sp,sp,#20*4
+	cmp	sp,#0			@ set carry to denote 60_79
+	b	.L_20_39_or_60_79	@ [+4], spare 300 bytes
+.L_done:
+	add	sp,sp,#80*4		@ "deallocate" stack frame
+	ldmia	r0,{r8,r9,r10,r11,r12}
+	add	r3,r8,r3
+	add	r4,r9,r4
+	add	r5,r10,r5,ror#2
+	add	r6,r11,r6,ror#2
+	add	r7,r12,r7,ror#2
+	stmia	r0,{r3,r4,r5,r6,r7}
+	teq	r1,r2
+	bne	.Lloop			@ [+18], total 1307
+
+#if __ARM_ARCH__>=5
+	ldmia	sp!,{r4-r12,pc}
+#else
+	ldmia	sp!,{r4-r12,lr}
+	tst	lr,#1
+	moveq	pc,lr			@ be binary compatible with V4, yet
+	.word	0xe12fff1e			@ interoperable with Thumb ISA:-)
+#endif
+.align	2
+.LK_00_19:	.word	0x5a827999
+.LK_20_39:	.word	0x6ed9eba1
+.LK_40_59:	.word	0x8f1bbcdc
+.LK_60_79:	.word	0xca62c1d6
+.size	sha1_block_data_order,.-sha1_block_data_order
+.asciz	"SHA1 block transform for ARMv4, CRYPTOGAMS by <appro@openssl.org>"
+.align	2
diff --git a/arch/arm/crypto/sha1_glue.c b/arch/arm/crypto/sha1_glue.c
new file mode 100644
index 0000000..76cd976
--- /dev/null
+++ b/arch/arm/crypto/sha1_glue.c
@@ -0,0 +1,179 @@
+/*
+ * Cryptographic API.
+ * Glue code for the SHA1 Secure Hash Algorithm assembler implementation
+ *
+ * This file is based on sha1_generic.c and sha1_ssse3_glue.c
+ *
+ * Copyright (c) Alan Smithee.
+ * Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk>
+ * Copyright (c) Jean-Francois Dive <jef@linuxbe.org>
+ * Copyright (c) Mathias Krause <minipli@googlemail.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 <crypto/internal/hash.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/cryptohash.h>
+#include <linux/types.h>
+#include <crypto/sha.h>
+#include <asm/byteorder.h>
+
+struct SHA1_CTX {
+	uint32_t h0,h1,h2,h3,h4;
+	u64 count;
+	u8 data[SHA1_BLOCK_SIZE];
+};
+
+asmlinkage void sha1_block_data_order(struct SHA1_CTX *digest,
+		const unsigned char *data, unsigned int rounds);
+
+
+static int sha1_init(struct shash_desc *desc)
+{
+	struct SHA1_CTX *sctx = shash_desc_ctx(desc);
+	memset(sctx, 0, sizeof(*sctx));
+	sctx->h0 = SHA1_H0;
+	sctx->h1 = SHA1_H1;
+	sctx->h2 = SHA1_H2;
+	sctx->h3 = SHA1_H3;
+	sctx->h4 = SHA1_H4;
+	return 0;
+}
+
+
+static int __sha1_update(struct SHA1_CTX *sctx, const u8 *data,
+			       unsigned int len, unsigned int partial)
+{
+	unsigned int done = 0;
+
+	sctx->count += len;
+
+	if (partial) {
+		done = SHA1_BLOCK_SIZE - partial;
+		memcpy(sctx->data + partial, data, done);
+		sha1_block_data_order(sctx, sctx->data, 1);
+	}
+
+	if (len - done >= SHA1_BLOCK_SIZE) {
+		const unsigned int rounds = (len - done) / SHA1_BLOCK_SIZE;
+		sha1_block_data_order(sctx, data + done, rounds);
+		done += rounds * SHA1_BLOCK_SIZE;
+	}
+
+	memcpy(sctx->data, data + done, len - done);
+	return 0;
+}
+
+
+static int sha1_update(struct shash_desc *desc, const u8 *data,
+			     unsigned int len)
+{
+	struct SHA1_CTX *sctx = shash_desc_ctx(desc);
+	unsigned int partial = sctx->count % SHA1_BLOCK_SIZE;
+	int res;
+
+	/* Handle the fast case right here */
+	if (partial + len < SHA1_BLOCK_SIZE) {
+		sctx->count += len;
+		memcpy(sctx->data + partial, data, len);
+		return 0;
+	}
+	res = __sha1_update(sctx, data, len, partial);
+	return res;
+}
+
+
+/* Add padding and return the message digest. */
+static int sha1_final(struct shash_desc *desc, u8 *out)
+{
+	struct SHA1_CTX *sctx = shash_desc_ctx(desc);
+	unsigned int i, index, padlen;
+	__be32 *dst = (__be32 *)out;
+	__be64 bits;
+	static const u8 padding[SHA1_BLOCK_SIZE] = { 0x80, };
+
+	bits = cpu_to_be64(sctx->count << 3);
+
+	/* Pad out to 56 mod 64 and append length */
+	index = sctx->count % SHA1_BLOCK_SIZE;
+	padlen = (index < 56) ? (56 - index) : ((SHA1_BLOCK_SIZE+56) - index);
+	/* We need to fill a whole block for __sha1_update() */
+	if (padlen <= 56) {
+		sctx->count += padlen;
+		memcpy(sctx->data + index, padding, padlen);
+	} else {
+		__sha1_update(sctx, padding, padlen, index);
+	}
+	__sha1_update(sctx, (const u8 *)&bits, sizeof(bits), 56);
+
+	/* Store state in digest */
+	for (i = 0; i < 5; i++)
+		dst[i] = cpu_to_be32(((u32 *)sctx)[i]);
+
+	/* Wipe context */
+	memset(sctx, 0, sizeof(*sctx));
+	return 0;
+}
+
+
+static int sha1_export(struct shash_desc *desc, void *out)
+{
+	struct SHA1_CTX *sctx = shash_desc_ctx(desc);
+	memcpy(out, sctx, sizeof(*sctx));
+	return 0;
+}
+
+
+static int sha1_import(struct shash_desc *desc, const void *in)
+{
+	struct SHA1_CTX *sctx = shash_desc_ctx(desc);
+	memcpy(sctx, in, sizeof(*sctx));
+	return 0;
+}
+
+
+static struct shash_alg alg = {
+	.digestsize	=	SHA1_DIGEST_SIZE,
+	.init		=	sha1_init,
+	.update		=	sha1_update,
+	.final		=	sha1_final,
+	.export		=	sha1_export,
+	.import		=	sha1_import,
+	.descsize	=	sizeof(struct SHA1_CTX),
+	.statesize	=	sizeof(struct SHA1_CTX),
+	.base		=	{
+		.cra_name	=	"sha1",
+		.cra_driver_name=	"sha1-asm",
+		.cra_priority	=	150,
+		.cra_flags	=	CRYPTO_ALG_TYPE_SHASH,
+		.cra_blocksize	=	SHA1_BLOCK_SIZE,
+		.cra_module	=	THIS_MODULE,
+	}
+};
+
+
+static int __init sha1_mod_init(void)
+{
+	return crypto_register_shash(&alg);
+}
+
+
+static void __exit sha1_mod_fini(void)
+{
+	crypto_unregister_shash(&alg);
+}
+
+
+module_init(sha1_mod_init);
+module_exit(sha1_mod_fini);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm (ARM)");
+MODULE_ALIAS("sha1");
+MODULE_AUTHOR("David McCullough <ucdevel@gmail.com>");
diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild
index 960abce..8a7196c 100644
--- a/arch/arm/include/asm/Kbuild
+++ b/arch/arm/include/asm/Kbuild
@@ -5,16 +5,33 @@ header-y += hwcap.h
 generic-y += auxvec.h
 generic-y += bitsperlong.h
 generic-y += cputime.h
+generic-y += current.h
 generic-y += emergency-restart.h
 generic-y += errno.h
+generic-y += exec.h
 generic-y += ioctl.h
+generic-y += ipcbuf.h
 generic-y += irq_regs.h
 generic-y += kdebug.h
 generic-y += local.h
 generic-y += local64.h
+generic-y += msgbuf.h
+generic-y += param.h
+generic-y += parport.h
 generic-y += percpu.h
 generic-y += poll.h
 generic-y += resource.h
 generic-y += sections.h
+generic-y += segment.h
+generic-y += sembuf.h
+generic-y += serial.h
+generic-y += shmbuf.h
 generic-y += siginfo.h
 generic-y += sizes.h
+generic-y += socket.h
+generic-y += sockios.h
+generic-y += termbits.h
+generic-y += termios.h
+generic-y += timex.h
+generic-y += types.h
+generic-y += unaligned.h
diff --git a/arch/arm/include/asm/arch_timer.h b/arch/arm/include/asm/arch_timer.h
index 62e7547..ad9b155 100644
--- a/arch/arm/include/asm/arch_timer.h
+++ b/arch/arm/include/asm/arch_timer.h
@@ -2,11 +2,13 @@
 #define __ASMARM_ARCH_TIMER_H
 
 #include <asm/errno.h>
+#include <linux/clocksource.h>
 
 #ifdef CONFIG_ARM_ARCH_TIMER
 #define ARCH_HAS_READ_CURRENT_TIMER
 int arch_timer_of_register(void);
 int arch_timer_sched_clock_init(void);
+struct timecounter *arch_timer_get_timecounter(void);
 #else
 static inline int arch_timer_of_register(void)
 {
@@ -17,6 +19,11 @@ static inline int arch_timer_sched_clock_init(void)
 {
 	return -ENXIO;
 }
+
+static inline struct timecounter *arch_timer_get_timecounter(void)
+{
+	return NULL;
+}
 #endif
 
 #endif
diff --git a/arch/arm/include/asm/barrier.h b/arch/arm/include/asm/barrier.h
index 0511238..8dcd9c7 100644
--- a/arch/arm/include/asm/barrier.h
+++ b/arch/arm/include/asm/barrier.h
@@ -44,10 +44,9 @@
 #define rmb()		dsb()
 #define wmb()		mb()
 #else
-#include <asm/memory.h>
-#define mb()	do { if (arch_is_coherent()) dmb(); else barrier(); } while (0)
-#define rmb()	do { if (arch_is_coherent()) dmb(); else barrier(); } while (0)
-#define wmb()	do { if (arch_is_coherent()) dmb(); else barrier(); } while (0)
+#define mb()		barrier()
+#define rmb()		barrier()
+#define wmb()		barrier()
 #endif
 
 #ifndef CONFIG_SMP
diff --git a/arch/arm/include/asm/current.h b/arch/arm/include/asm/current.h
deleted file mode 100644
index 75d21e2..0000000
--- a/arch/arm/include/asm/current.h
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifndef _ASMARM_CURRENT_H
-#define _ASMARM_CURRENT_H
-
-#include <linux/thread_info.h>
-
-static inline struct task_struct *get_current(void) __attribute_const__;
-
-static inline struct task_struct *get_current(void)
-{
-	return current_thread_info()->task;
-}
-
-#define current (get_current())
-
-#endif /* _ASMARM_CURRENT_H */
diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h
index 5c44dcb..2300484 100644
--- a/arch/arm/include/asm/dma-mapping.h
+++ b/arch/arm/include/asm/dma-mapping.h
@@ -13,6 +13,7 @@
 
 #define DMA_ERROR_CODE	(~0)
 extern struct dma_map_ops arm_dma_ops;
+extern struct dma_map_ops arm_coherent_dma_ops;
 
 static inline struct dma_map_ops *get_dma_ops(struct device *dev)
 {
diff --git a/arch/arm/include/asm/exec.h b/arch/arm/include/asm/exec.h
deleted file mode 100644
index 7c4fbef..0000000
--- a/arch/arm/include/asm/exec.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __ASM_ARM_EXEC_H
-#define __ASM_ARM_EXEC_H
-
-#define arch_align_stack(x) (x)
-
-#endif /* __ASM_ARM_EXEC_H */
diff --git a/arch/arm/include/asm/glue-cache.h b/arch/arm/include/asm/glue-cache.h
index 7e30874..4f8d2c0 100644
--- a/arch/arm/include/asm/glue-cache.h
+++ b/arch/arm/include/asm/glue-cache.h
@@ -110,19 +110,19 @@
 #endif
 
 #if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K)
-//# ifdef _CACHE
+# ifdef _CACHE
 #  define MULTI_CACHE 1
-//# else
-//#  define _CACHE v6
-//# endif
+# else
+#  define _CACHE v6
+# endif
 #endif
 
 #if defined(CONFIG_CPU_V7)
-//# ifdef _CACHE
+# ifdef _CACHE
 #  define MULTI_CACHE 1
-//# else
-//#  define _CACHE v7
-//# endif
+# else
+#  define _CACHE v7
+# endif
 #endif
 
 #if !defined(_CACHE) && !defined(MULTI_CACHE)
diff --git a/arch/arm/include/asm/gpio.h b/arch/arm/include/asm/gpio.h
index c402e9b..477e020 100644
--- a/arch/arm/include/asm/gpio.h
+++ b/arch/arm/include/asm/gpio.h
@@ -6,7 +6,9 @@
 #endif
 
 /* not all ARM platforms necessarily support this API ... */
+#ifdef CONFIG_NEED_MACH_GPIO_H
 #include <mach/gpio.h>
+#endif
 
 #ifndef __ARM_GPIOLIB_COMPLEX
 /* Note: this may rely upon the value of ARCH_NR_GPIOS set in mach/gpio.h */
diff --git a/arch/arm/include/asm/hardirq.h b/arch/arm/include/asm/hardirq.h
index 436e60b..2740c2a 100644
--- a/arch/arm/include/asm/hardirq.h
+++ b/arch/arm/include/asm/hardirq.h
@@ -5,7 +5,7 @@
 #include <linux/threads.h>
 #include <asm/irq.h>
 
-#define NR_IPI	5
+#define NR_IPI	6
 
 typedef struct {
 	unsigned int __softirq_pending;
diff --git a/arch/arm/include/asm/hardware/cache-tauros2.h b/arch/arm/include/asm/hardware/cache-tauros2.h
index 538f17c..295e2e4 100644
--- a/arch/arm/include/asm/hardware/cache-tauros2.h
+++ b/arch/arm/include/asm/hardware/cache-tauros2.h
@@ -8,4 +8,7 @@
  * warranty of any kind, whether express or implied.
  */
 
-extern void __init tauros2_init(void);
+#define CACHE_TAUROS2_PREFETCH_ON	(1 << 0)
+#define CACHE_TAUROS2_LINEFILL_BURST8	(1 << 1)
+
+extern void __init tauros2_init(unsigned int features);
diff --git a/arch/arm/include/asm/hardware/iop3xx.h b/arch/arm/include/asm/hardware/iop3xx.h
index 2ff2c75..02fe2fb 100644
--- a/arch/arm/include/asm/hardware/iop3xx.h
+++ b/arch/arm/include/asm/hardware/iop3xx.h
@@ -217,18 +217,8 @@ extern int iop3xx_get_init_atu(void);
 #define IOP3XX_PCI_LOWER_MEM_PA	0x80000000
 #define IOP3XX_PCI_MEM_WINDOW_SIZE	0x08000000
 
-#define IOP3XX_PCI_IO_WINDOW_SIZE	0x00010000
 #define IOP3XX_PCI_LOWER_IO_PA		0x90000000
-#define IOP3XX_PCI_LOWER_IO_VA		0xfe000000
-#define IOP3XX_PCI_LOWER_IO_BA		0x90000000
-#define IOP3XX_PCI_UPPER_IO_PA		(IOP3XX_PCI_LOWER_IO_PA +\
-					IOP3XX_PCI_IO_WINDOW_SIZE - 1)
-#define IOP3XX_PCI_UPPER_IO_VA		(IOP3XX_PCI_LOWER_IO_VA +\
-					IOP3XX_PCI_IO_WINDOW_SIZE - 1)
-#define IOP3XX_PCI_IO_PHYS_TO_VIRT(addr) (((u32) (addr) -\
-					IOP3XX_PCI_LOWER_IO_PA) +\
-					IOP3XX_PCI_LOWER_IO_VA)
-
+#define IOP3XX_PCI_LOWER_IO_BA		0x00000000
 
 #ifndef __ASSEMBLY__
 
diff --git a/arch/arm/include/asm/hardware/linkup-l1110.h b/arch/arm/include/asm/hardware/linkup-l1110.h
deleted file mode 100644
index 7ec9116..0000000
--- a/arch/arm/include/asm/hardware/linkup-l1110.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
-*
-* Definitions for H3600 Handheld Computer
-*
-* Copyright 2001 Compaq Computer Corporation.
-*
-* Use consistent with the GNU GPL is permitted,
-* provided that this copyright notice is
-* preserved in its entirety in all copies and derived works.
-*
-* COMPAQ COMPUTER CORPORATION MAKES NO WARRANTIES, EXPRESSED OR IMPLIED,
-* AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
-* FITNESS FOR ANY PARTICULAR PURPOSE.
-*
-* Author: Jamey Hicks.
-*
-*/
-
-/* LinkUp Systems PCCard/CompactFlash Interface for SA-1100 */
-
-/* PC Card Status Register */
-#define LINKUP_PRS_S1	(1 << 0) /* voltage control bits S1-S4 */
-#define LINKUP_PRS_S2	(1 << 1)
-#define LINKUP_PRS_S3	(1 << 2)
-#define LINKUP_PRS_S4	(1 << 3)
-#define LINKUP_PRS_BVD1	(1 << 4)
-#define LINKUP_PRS_BVD2	(1 << 5)
-#define LINKUP_PRS_VS1	(1 << 6)
-#define LINKUP_PRS_VS2	(1 << 7)
-#define LINKUP_PRS_RDY	(1 << 8)
-#define LINKUP_PRS_CD1	(1 << 9)
-#define LINKUP_PRS_CD2	(1 << 10)
-
-/* PC Card Command Register */
-#define LINKUP_PRC_S1	(1 << 0)
-#define LINKUP_PRC_S2	(1 << 1)
-#define LINKUP_PRC_S3	(1 << 2)
-#define LINKUP_PRC_S4	(1 << 3)
-#define LINKUP_PRC_RESET (1 << 4)
-#define LINKUP_PRC_APOE	(1 << 5) /* Auto Power Off Enable: clears S1-S4 when either nCD goes high */
-#define LINKUP_PRC_CFE	(1 << 6) /* CompactFlash mode Enable: addresses A[10:0] only, A[25:11] high */
-#define LINKUP_PRC_SOE	(1 << 7) /* signal output driver enable */
-#define LINKUP_PRC_SSP	(1 << 8) /* sock select polarity: 0 for socket 0, 1 for socket 1 */
-#define LINKUP_PRC_MBZ	(1 << 15) /* must be zero */
-
-struct linkup_l1110 {
-	volatile short prc;
-};
diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h
index 815c669..35c1ed8 100644
--- a/arch/arm/include/asm/io.h
+++ b/arch/arm/include/asm/io.h
@@ -47,13 +47,68 @@ extern void __raw_readsb(const void __iomem *addr, void *data, int bytelen);
 extern void __raw_readsw(const void __iomem *addr, void *data, int wordlen);
 extern void __raw_readsl(const void __iomem *addr, void *data, int longlen);
 
-#define __raw_writeb(v,a)	((void)(__chk_io_ptr(a), *(volatile unsigned char __force  *)(a) = (v)))
-#define __raw_writew(v,a)	((void)(__chk_io_ptr(a), *(volatile unsigned short __force *)(a) = (v)))
-#define __raw_writel(v,a)	((void)(__chk_io_ptr(a), *(volatile unsigned int __force   *)(a) = (v)))
+#if __LINUX_ARM_ARCH__ < 6
+/*
+ * Half-word accesses are problematic with RiscPC due to limitations of
+ * the bus. Rather than special-case the machine, just let the compiler
+ * generate the access for CPUs prior to ARMv6.
+ */
+#define __raw_readw(a)         (__chk_io_ptr(a), *(volatile unsigned short __force *)(a))
+#define __raw_writew(v,a)      ((void)(__chk_io_ptr(a), *(volatile unsigned short __force *)(a) = (v)))
+#else
+/*
+ * When running under a hypervisor, we want to avoid I/O accesses with
+ * writeback addressing modes as these incur a significant performance
+ * overhead (the address generation must be emulated in software).
+ */
+static inline void __raw_writew(u16 val, volatile void __iomem *addr)
+{
+	asm volatile("strh %1, %0"
+		     : "+Qo" (*(volatile u16 __force *)addr)
+		     : "r" (val));
+}
+
+static inline u16 __raw_readw(const volatile void __iomem *addr)
+{
+	u16 val;
+	asm volatile("ldrh %1, %0"
+		     : "+Qo" (*(volatile u16 __force *)addr),
+		       "=r" (val));
+	return val;
+}
+#endif
+
+static inline void __raw_writeb(u8 val, volatile void __iomem *addr)
+{
+	asm volatile("strb %1, %0"
+		     : "+Qo" (*(volatile u8 __force *)addr)
+		     : "r" (val));
+}
+
+static inline void __raw_writel(u32 val, volatile void __iomem *addr)
+{
+	asm volatile("str %1, %0"
+		     : "+Qo" (*(volatile u32 __force *)addr)
+		     : "r" (val));
+}
+
+static inline u8 __raw_readb(const volatile void __iomem *addr)
+{
+	u8 val;
+	asm volatile("ldrb %1, %0"
+		     : "+Qo" (*(volatile u8 __force *)addr),
+		       "=r" (val));
+	return val;
+}
 
-#define __raw_readb(a)		(__chk_io_ptr(a), *(volatile unsigned char __force  *)(a))
-#define __raw_readw(a)		(__chk_io_ptr(a), *(volatile unsigned short __force *)(a))
-#define __raw_readl(a)		(__chk_io_ptr(a), *(volatile unsigned int __force   *)(a))
+static inline u32 __raw_readl(const volatile void __iomem *addr)
+{
+	u32 val;
+	asm volatile("ldr %1, %0"
+		     : "+Qo" (*(volatile u32 __force *)addr),
+		       "=r" (val));
+	return val;
+}
 
 /*
  * Architecture ioremap implementation.
@@ -113,11 +168,19 @@ static inline void __iomem *__typesafe_io(unsigned long addr)
 #define __iowmb()		do { } while (0)
 #endif
 
+/* PCI fixed i/o mapping */
+#define PCI_IO_VIRT_BASE	0xfee00000
+
+extern int pci_ioremap_io(unsigned int offset, phys_addr_t phys_addr);
+
 /*
  * Now, pick up the machine-defined IO definitions
  */
 #ifdef CONFIG_NEED_MACH_IO_H
 #include <mach/io.h>
+#elif defined(CONFIG_PCI)
+#define IO_SPACE_LIMIT	((resource_size_t)0xfffff)
+#define __io(a)		__typesafe_io(PCI_IO_VIRT_BASE + ((a) & IO_SPACE_LIMIT))
 #else
 #define __io(a)		__typesafe_io((a) & IO_SPACE_LIMIT)
 #endif
diff --git a/arch/arm/include/asm/ipcbuf.h b/arch/arm/include/asm/ipcbuf.h
deleted file mode 100644
index 84c7e51..0000000
--- a/arch/arm/include/asm/ipcbuf.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/ipcbuf.h>
diff --git a/arch/arm/include/asm/leds.h b/arch/arm/include/asm/leds.h
deleted file mode 100644
index c545739..0000000
--- a/arch/arm/include/asm/leds.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- *  arch/arm/include/asm/leds.h
- *
- *  Copyright (C) 1998 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- *  Event-driven interface for LEDs on machines
- *  Added led_start and led_stop- Alex Holden, 28th Dec 1998.
- */
-#ifndef ASM_ARM_LEDS_H
-#define ASM_ARM_LEDS_H
-
-
-typedef enum {
-	led_idle_start,
-	led_idle_end,
-	led_timer,
-	led_start,
-	led_stop,
-	led_claim,		/* override idle & timer leds */
-	led_release,		/* restore idle & timer leds */
-	led_start_timer_mode,
-	led_stop_timer_mode,
-	led_green_on,
-	led_green_off,
-	led_amber_on,
-	led_amber_off,
-	led_red_on,
-	led_red_off,
-	led_blue_on,
-	led_blue_off,
-	/*
-	 * I want this between led_timer and led_start, but
-	 * someone has decided to export this to user space
-	 */
-	led_halted
-} led_event_t;
-
-/* Use this routine to handle LEDs */
-
-#ifdef CONFIG_LEDS
-extern void (*leds_event)(led_event_t);
-#else
-#define leds_event(e)
-#endif
-
-#endif
diff --git a/arch/arm/include/asm/mach/arch.h b/arch/arm/include/asm/mach/arch.h
index 0b1c94b..917d4fc 100644
--- a/arch/arm/include/asm/mach/arch.h
+++ b/arch/arm/include/asm/mach/arch.h
@@ -14,6 +14,12 @@ struct tag;
 struct meminfo;
 struct sys_timer;
 struct pt_regs;
+struct smp_operations;
+#ifdef CONFIG_SMP
+#define smp_ops(ops) (&(ops))
+#else
+#define smp_ops(ops) (struct smp_operations *)NULL
+#endif
 
 struct machine_desc {
 	unsigned int		nr;		/* architecture number	*/
@@ -35,6 +41,7 @@ struct machine_desc {
 	unsigned char		reserve_lp1 :1;	/* never has lp1	*/
 	unsigned char		reserve_lp2 :1;	/* never has lp2	*/
 	char			restart_mode;	/* default restart mode	*/
+	struct smp_operations	*smp;		/* SMP operations	*/
 	void			(*fixup)(struct tag *, char **,
 					 struct meminfo *);
 	void			(*reserve)(void);/* reserve mem blocks	*/
diff --git a/arch/arm/include/asm/mach/map.h b/arch/arm/include/asm/mach/map.h
index a6efcdd..195ac2f 100644
--- a/arch/arm/include/asm/mach/map.h
+++ b/arch/arm/include/asm/mach/map.h
@@ -9,6 +9,9 @@
  *
  *  Page table mapping constructs and function prototypes
  */
+#ifndef __ASM_MACH_MAP_H
+#define __ASM_MACH_MAP_H
+
 #include <asm/io.h>
 
 struct map_desc {
@@ -34,6 +37,8 @@ struct map_desc {
 
 #ifdef CONFIG_MMU
 extern void iotable_init(struct map_desc *, int);
+extern void vm_reserve_area_early(unsigned long addr, unsigned long size,
+				  void *caller);
 
 struct mem_type;
 extern const struct mem_type *get_mem_type(unsigned int type);
@@ -44,4 +49,7 @@ extern int ioremap_page(unsigned long virt, unsigned long phys,
 			const struct mem_type *mtype);
 #else
 #define iotable_init(map,num)	do { } while (0)
+#define vm_reserve_area_early(a,s,c)	do { } while (0)
+#endif
+
 #endif
diff --git a/arch/arm/include/asm/mach/pci.h b/arch/arm/include/asm/mach/pci.h
index 26c511f..db9fedb 100644
--- a/arch/arm/include/asm/mach/pci.h
+++ b/arch/arm/include/asm/mach/pci.h
@@ -11,6 +11,8 @@
 #ifndef __ASM_MACH_PCI_H
 #define __ASM_MACH_PCI_H
 
+#include <linux/ioport.h>
+
 struct pci_sys_data;
 struct pci_ops;
 struct pci_bus;
@@ -42,6 +44,8 @@ struct pci_sys_data {
 	unsigned long	io_offset;	/* bus->cpu IO mapping offset		*/
 	struct pci_bus	*bus;		/* PCI bus				*/
 	struct list_head resources;	/* root bus resources (apertures)       */
+	struct resource io_res;
+	char		io_res_name[12];
 					/* Bridge swizzling			*/
 	u8		(*swizzle)(struct pci_dev *, u8 *);
 					/* IRQ mapping				*/
@@ -55,6 +59,15 @@ struct pci_sys_data {
 void pci_common_init(struct hw_pci *);
 
 /*
+ * Setup early fixed I/O mapping.
+ */
+#if defined(CONFIG_PCI)
+extern void pci_map_io_early(unsigned long pfn);
+#else
+static inline void pci_map_io_early(unsigned long pfn) {}
+#endif
+
+/*
  * PCI controllers
  */
 extern struct pci_ops iop3xx_ops;
diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h
index 5f6ddcc..73cf03a 100644
--- a/arch/arm/include/asm/memory.h
+++ b/arch/arm/include/asm/memory.h
@@ -275,14 +275,6 @@ static inline __deprecated void *bus_to_virt(unsigned long x)
 #define virt_to_page(kaddr)	pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
 #define virt_addr_valid(kaddr)	((unsigned long)(kaddr) >= PAGE_OFFSET && (unsigned long)(kaddr) < (unsigned long)high_memory)
 
-/*
- * Optional coherency support.  Currently used only by selected
- * Intel XSC3-based systems.
- */
-#ifndef arch_is_coherent
-#define arch_is_coherent()		0
-#endif
-
 #endif
 
 #include <asm-generic/memory_model.h>
diff --git a/arch/arm/include/asm/module.h b/arch/arm/include/asm/module.h
index 6c6809f..0d3a28d 100644
--- a/arch/arm/include/asm/module.h
+++ b/arch/arm/include/asm/module.h
@@ -1,9 +1,7 @@
 #ifndef _ASM_ARM_MODULE_H
 #define _ASM_ARM_MODULE_H
 
-#define Elf_Shdr	Elf32_Shdr
-#define Elf_Sym		Elf32_Sym
-#define Elf_Ehdr	Elf32_Ehdr
+#include <asm-generic/module.h>
 
 struct unwind_table;
 
@@ -16,13 +14,11 @@ enum {
 	ARM_SEC_DEVEXIT,
 	ARM_SEC_MAX,
 };
-#endif
 
 struct mod_arch_specific {
-#ifdef CONFIG_ARM_UNWIND
 	struct unwind_table *unwind[ARM_SEC_MAX];
-#endif
 };
+#endif
 
 /*
  * Add the ARM architecture version to the version magic string
diff --git a/arch/arm/include/asm/msgbuf.h b/arch/arm/include/asm/msgbuf.h
deleted file mode 100644
index 33b35b9..0000000
--- a/arch/arm/include/asm/msgbuf.h
+++ /dev/null
@@ -1,31 +0,0 @@
-#ifndef _ASMARM_MSGBUF_H
-#define _ASMARM_MSGBUF_H
-
-/* 
- * The msqid64_ds structure for arm architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 64-bit time_t to solve y2038 problem
- * - 2 miscellaneous 32-bit values
- */
-
-struct msqid64_ds {
-	struct ipc64_perm msg_perm;
-	__kernel_time_t msg_stime;	/* last msgsnd time */
-	unsigned long	__unused1;
-	__kernel_time_t msg_rtime;	/* last msgrcv time */
-	unsigned long	__unused2;
-	__kernel_time_t msg_ctime;	/* last change time */
-	unsigned long	__unused3;
-	unsigned long  msg_cbytes;	/* current number of bytes on queue */
-	unsigned long  msg_qnum;	/* number of messages in queue */
-	unsigned long  msg_qbytes;	/* max number of bytes on queue */
-	__kernel_pid_t msg_lspid;	/* pid of last msgsnd */
-	__kernel_pid_t msg_lrpid;	/* last receive pid */
-	unsigned long  __unused4;
-	unsigned long  __unused5;
-};
-
-#endif /* _ASMARM_MSGBUF_H */
diff --git a/arch/arm/include/asm/mutex.h b/arch/arm/include/asm/mutex.h
index b1479fd..87c0449 100644
--- a/arch/arm/include/asm/mutex.h
+++ b/arch/arm/include/asm/mutex.h
@@ -9,8 +9,13 @@
 #define _ASM_MUTEX_H
 /*
  * On pre-ARMv6 hardware this results in a swp-based implementation,
- * which is the most efficient. For ARMv6+, we emit a pair of exclusive
- * accesses instead.
+ * which is the most efficient. For ARMv6+, we have exclusive memory
+ * accessors and use atomic_dec to avoid the extra xchg operations
+ * on the locking slowpaths.
  */
+#if __LINUX_ARM_ARCH__ < 6
 #include <asm-generic/mutex-xchg.h>
+#else
+#include <asm-generic/mutex-dec.h>
 #endif
+#endif	/* _ASM_MUTEX_H */
diff --git a/arch/arm/include/asm/opcodes-virt.h b/arch/arm/include/asm/opcodes-virt.h
new file mode 100644
index 0000000..b85665a
--- /dev/null
+++ b/arch/arm/include/asm/opcodes-virt.h
@@ -0,0 +1,29 @@
+/*
+ * opcodes-virt.h: Opcode definitions for the ARM virtualization extensions
+ * Copyright (C) 2012  Linaro Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef __ASM_ARM_OPCODES_VIRT_H
+#define __ASM_ARM_OPCODES_VIRT_H
+
+#include <asm/opcodes.h>
+
+#define __HVC(imm16) __inst_arm_thumb32(				\
+	0xE1400070 | (((imm16) & 0xFFF0) << 4) | ((imm16) & 0x000F),	\
+	0xF7E08000 | (((imm16) & 0xF000) << 4) | ((imm16) & 0x0FFF)	\
+)
+
+#endif /* ! __ASM_ARM_OPCODES_VIRT_H */
diff --git a/arch/arm/include/asm/opcodes.h b/arch/arm/include/asm/opcodes.h
index 19c48de..74e211a 100644
--- a/arch/arm/include/asm/opcodes.h
+++ b/arch/arm/include/asm/opcodes.h
@@ -19,6 +19,33 @@ extern asmlinkage unsigned int arm_check_condition(u32 opcode, u32 psr);
 
 
 /*
+ * Assembler opcode byteswap helpers.
+ * These are only intended for use by this header: don't use them directly,
+ * because they will be suboptimal in most cases.
+ */
+#define ___asm_opcode_swab32(x) (	\
+	  (((x) << 24) & 0xFF000000)	\
+	| (((x) <<  8) & 0x00FF0000)	\
+	| (((x) >>  8) & 0x0000FF00)	\
+	| (((x) >> 24) & 0x000000FF)	\
+)
+#define ___asm_opcode_swab16(x) (	\
+	  (((x) << 8) & 0xFF00)		\
+	| (((x) >> 8) & 0x00FF)		\
+)
+#define ___asm_opcode_swahb32(x) (	\
+	  (((x) << 8) & 0xFF00FF00)	\
+	| (((x) >> 8) & 0x00FF00FF)	\
+)
+#define ___asm_opcode_swahw32(x) (	\
+	  (((x) << 16) & 0xFFFF0000)	\
+	| (((x) >> 16) & 0x0000FFFF)	\
+)
+#define ___asm_opcode_identity32(x) ((x) & 0xFFFFFFFF)
+#define ___asm_opcode_identity16(x) ((x) & 0xFFFF)
+
+
+/*
  * Opcode byteswap helpers
  *
  * These macros help with converting instructions between a canonical integer
@@ -41,39 +68,163 @@ extern asmlinkage unsigned int arm_check_condition(u32 opcode, u32 psr);
  * Note that values in the range 0x0000E800..0xE7FFFFFF intentionally do not
  * represent any valid Thumb-2 instruction.  For this range,
  * __opcode_is_thumb32() and __opcode_is_thumb16() will both be false.
+ *
+ * The ___asm variants are intended only for use by this header, in situations
+ * involving inline assembler.  For .S files, the normal __opcode_*() macros
+ * should do the right thing.
  */
+#ifdef __ASSEMBLY__
 
-#ifndef __ASSEMBLY__
+#define ___opcode_swab32(x) ___asm_opcode_swab32(x)
+#define ___opcode_swab16(x) ___asm_opcode_swab16(x)
+#define ___opcode_swahb32(x) ___asm_opcode_swahb32(x)
+#define ___opcode_swahw32(x) ___asm_opcode_swahw32(x)
+#define ___opcode_identity32(x) ___asm_opcode_identity32(x)
+#define ___opcode_identity16(x) ___asm_opcode_identity16(x)
+
+#else /* ! __ASSEMBLY__ */
 
 #include <linux/types.h>
 #include <linux/swab.h>
 
+#define ___opcode_swab32(x) swab32(x)
+#define ___opcode_swab16(x) swab16(x)
+#define ___opcode_swahb32(x) swahb32(x)
+#define ___opcode_swahw32(x) swahw32(x)
+#define ___opcode_identity32(x) ((u32)(x))
+#define ___opcode_identity16(x) ((u16)(x))
+
+#endif /* ! __ASSEMBLY__ */
+
+
 #ifdef CONFIG_CPU_ENDIAN_BE8
-#define __opcode_to_mem_arm(x) swab32(x)
-#define __opcode_to_mem_thumb16(x) swab16(x)
-#define __opcode_to_mem_thumb32(x) swahb32(x)
-#else
-#define __opcode_to_mem_arm(x) ((u32)(x))
-#define __opcode_to_mem_thumb16(x) ((u16)(x))
-#define __opcode_to_mem_thumb32(x) swahw32(x)
+
+#define __opcode_to_mem_arm(x) ___opcode_swab32(x)
+#define __opcode_to_mem_thumb16(x) ___opcode_swab16(x)
+#define __opcode_to_mem_thumb32(x) ___opcode_swahb32(x)
+#define ___asm_opcode_to_mem_arm(x) ___asm_opcode_swab32(x)
+#define ___asm_opcode_to_mem_thumb16(x) ___asm_opcode_swab16(x)
+#define ___asm_opcode_to_mem_thumb32(x) ___asm_opcode_swahb32(x)
+
+#else /* ! CONFIG_CPU_ENDIAN_BE8 */
+
+#define __opcode_to_mem_arm(x) ___opcode_identity32(x)
+#define __opcode_to_mem_thumb16(x) ___opcode_identity16(x)
+#define ___asm_opcode_to_mem_arm(x) ___asm_opcode_identity32(x)
+#define ___asm_opcode_to_mem_thumb16(x) ___asm_opcode_identity16(x)
+#ifndef CONFIG_CPU_ENDIAN_BE32
+/*
+ * On BE32 systems, using 32-bit accesses to store Thumb instructions will not
+ * work in all cases, due to alignment constraints.  For now, a correct
+ * version is not provided for BE32.
+ */
+#define __opcode_to_mem_thumb32(x) ___opcode_swahw32(x)
+#define ___asm_opcode_to_mem_thumb32(x) ___asm_opcode_swahw32(x)
 #endif
 
+#endif /* ! CONFIG_CPU_ENDIAN_BE8 */
+
 #define __mem_to_opcode_arm(x) __opcode_to_mem_arm(x)
 #define __mem_to_opcode_thumb16(x) __opcode_to_mem_thumb16(x)
+#ifndef CONFIG_CPU_ENDIAN_BE32
 #define __mem_to_opcode_thumb32(x) __opcode_to_mem_thumb32(x)
+#endif
 
 /* Operations specific to Thumb opcodes */
 
 /* Instruction size checks: */
-#define __opcode_is_thumb32(x) ((u32)(x) >= 0xE8000000UL)
-#define __opcode_is_thumb16(x) ((u32)(x) < 0xE800UL)
+#define __opcode_is_thumb32(x) (		\
+	   ((x) & 0xF8000000) == 0xE8000000	\
+	|| ((x) & 0xF0000000) == 0xF0000000	\
+)
+#define __opcode_is_thumb16(x) (					\
+	   ((x) & 0xFFFF0000) == 0					\
+	&& !(((x) & 0xF800) == 0xE800 || ((x) & 0xF000) == 0xF000)	\
+)
 
 /* Operations to construct or split 32-bit Thumb instructions: */
-#define __opcode_thumb32_first(x) ((u16)((x) >> 16))
-#define __opcode_thumb32_second(x) ((u16)(x))
-#define __opcode_thumb32_compose(first, second) \
-	(((u32)(u16)(first) << 16) | (u32)(u16)(second))
+#define __opcode_thumb32_first(x) (___opcode_identity16((x) >> 16))
+#define __opcode_thumb32_second(x) (___opcode_identity16(x))
+#define __opcode_thumb32_compose(first, second) (			\
+	  (___opcode_identity32(___opcode_identity16(first)) << 16)	\
+	| ___opcode_identity32(___opcode_identity16(second))		\
+)
+#define ___asm_opcode_thumb32_first(x) (___asm_opcode_identity16((x) >> 16))
+#define ___asm_opcode_thumb32_second(x) (___asm_opcode_identity16(x))
+#define ___asm_opcode_thumb32_compose(first, second) (			    \
+	  (___asm_opcode_identity32(___asm_opcode_identity16(first)) << 16) \
+	| ___asm_opcode_identity32(___asm_opcode_identity16(second))	    \
+)
 
-#endif /* __ASSEMBLY__ */
+/*
+ * Opcode injection helpers
+ *
+ * In rare cases it is necessary to assemble an opcode which the
+ * assembler does not support directly, or which would normally be
+ * rejected because of the CFLAGS or AFLAGS used to build the affected
+ * file.
+ *
+ * Before using these macros, consider carefully whether it is feasible
+ * instead to change the build flags for your file, or whether it really
+ * makes sense to support old assembler versions when building that
+ * particular kernel feature.
+ *
+ * The macros defined here should only be used where there is no viable
+ * alternative.
+ *
+ *
+ * __inst_arm(x): emit the specified ARM opcode
+ * __inst_thumb16(x): emit the specified 16-bit Thumb opcode
+ * __inst_thumb32(x): emit the specified 32-bit Thumb opcode
+ *
+ * __inst_arm_thumb16(arm, thumb): emit either the specified arm or
+ *	16-bit Thumb opcode, depending on whether an ARM or Thumb-2
+ *	kernel is being built
+ *
+ * __inst_arm_thumb32(arm, thumb): emit either the specified arm or
+ *	32-bit Thumb opcode, depending on whether an ARM or Thumb-2
+ *	kernel is being built
+ *
+ *
+ * Note that using these macros directly is poor practice.  Instead, you
+ * should use them to define human-readable wrapper macros to encode the
+ * instructions that you care about.  In code which might run on ARMv7 or
+ * above, you can usually use the __inst_arm_thumb{16,32} macros to
+ * specify the ARM and Thumb alternatives at the same time.  This ensures
+ * that the correct opcode gets emitted depending on the instruction set
+ * used for the kernel build.
+ *
+ * Look at opcodes-virt.h for an example of how to use these macros.
+ */
+#include <linux/stringify.h>
+
+#define __inst_arm(x) ___inst_arm(___asm_opcode_to_mem_arm(x))
+#define __inst_thumb32(x) ___inst_thumb32(				\
+	___asm_opcode_to_mem_thumb16(___asm_opcode_thumb32_first(x)),	\
+	___asm_opcode_to_mem_thumb16(___asm_opcode_thumb32_second(x))	\
+)
+#define __inst_thumb16(x) ___inst_thumb16(___asm_opcode_to_mem_thumb16(x))
+
+#ifdef CONFIG_THUMB2_KERNEL
+#define __inst_arm_thumb16(arm_opcode, thumb_opcode) \
+	__inst_thumb16(thumb_opcode)
+#define __inst_arm_thumb32(arm_opcode, thumb_opcode) \
+	__inst_thumb32(thumb_opcode)
+#else
+#define __inst_arm_thumb16(arm_opcode, thumb_opcode) __inst_arm(arm_opcode)
+#define __inst_arm_thumb32(arm_opcode, thumb_opcode) __inst_arm(arm_opcode)
+#endif
+
+/* Helpers for the helpers.  Don't use these directly. */
+#ifdef __ASSEMBLY__
+#define ___inst_arm(x) .long x
+#define ___inst_thumb16(x) .short x
+#define ___inst_thumb32(first, second) .short first, second
+#else
+#define ___inst_arm(x) ".long " __stringify(x) "\n\t"
+#define ___inst_thumb16(x) ".short " __stringify(x) "\n\t"
+#define ___inst_thumb32(first, second) \
+	".short " __stringify(first) ", " __stringify(second) "\n\t"
+#endif
 
 #endif /* __ASM_ARM_OPCODES_H */
diff --git a/arch/arm/include/asm/param.h b/arch/arm/include/asm/param.h
deleted file mode 100644
index 8b24bf94..0000000
--- a/arch/arm/include/asm/param.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- *  arch/arm/include/asm/param.h
- *
- *  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.
- */
-#ifndef __ASM_PARAM_H
-#define __ASM_PARAM_H
-
-#ifdef __KERNEL__
-# define HZ		CONFIG_HZ	/* Internal kernel timer frequency */
-# define USER_HZ	100		/* User interfaces are in "ticks" */
-# define CLOCKS_PER_SEC	(USER_HZ)	/* like times() */
-#else
-# define HZ		100
-#endif
-
-#define EXEC_PAGESIZE	4096
-
-#ifndef NOGROUP
-#define NOGROUP         (-1)
-#endif
-
-/* max length of hostname */
-#define MAXHOSTNAMELEN  64
-
-#endif
-
diff --git a/arch/arm/include/asm/parport.h b/arch/arm/include/asm/parport.h
deleted file mode 100644
index 26e94b0..0000000
--- a/arch/arm/include/asm/parport.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- *  arch/arm/include/asm/parport.h: ARM-specific parport initialisation
- *
- *  Copyright (C) 1999, 2000  Tim Waugh <tim@cyberelk.demon.co.uk>
- *
- * This file should only be included by drivers/parport/parport_pc.c.
- */
-
-#ifndef __ASMARM_PARPORT_H
-#define __ASMARM_PARPORT_H
-
-static int __devinit parport_pc_find_isa_ports (int autoirq, int autodma);
-static int __devinit parport_pc_find_nonpci_ports (int autoirq, int autodma)
-{
-	return parport_pc_find_isa_ports (autoirq, autodma);
-}
-
-#endif /* !(_ASMARM_PARPORT_H) */
diff --git a/arch/arm/include/asm/perf_event.h b/arch/arm/include/asm/perf_event.h
index e074948..625cd62 100644
--- a/arch/arm/include/asm/perf_event.h
+++ b/arch/arm/include/asm/perf_event.h
@@ -12,6 +12,13 @@
 #ifndef __ARM_PERF_EVENT_H__
 #define __ARM_PERF_EVENT_H__
 
-/* Nothing to see here... */
+/*
+ * The ARMv7 CPU PMU supports up to 32 event counters.
+ */
+#define ARMPMU_MAX_HWEVENTS		32
+
+#define HW_OP_UNSUPPORTED		0xFFFF
+#define C(_x)				PERF_COUNT_HW_CACHE_##_x
+#define CACHE_OP_UNSUPPORTED		0xFFFF
 
 #endif /* __ARM_PERF_EVENT_H__ */
diff --git a/arch/arm/include/asm/pmu.h b/arch/arm/include/asm/pmu.h
index 4432305..a26170d 100644
--- a/arch/arm/include/asm/pmu.h
+++ b/arch/arm/include/asm/pmu.h
@@ -16,69 +16,30 @@
 #include <linux/perf_event.h>
 
 /*
- * Types of PMUs that can be accessed directly and require mutual
- * exclusion between profiling tools.
- */
-enum arm_pmu_type {
-	ARM_PMU_DEVICE_CPU	= 0,
-	ARM_NUM_PMU_DEVICES,
-};
-
-/*
  * struct arm_pmu_platdata - ARM PMU platform data
  *
  * @handle_irq: an optional handler which will be called from the
  *	interrupt and passed the address of the low level handler,
  *	and can be used to implement any platform specific handling
  *	before or after calling it.
- * @enable_irq: an optional handler which will be called after
- *	request_irq and be used to handle some platform specific
- *	irq enablement
- * @disable_irq: an optional handler which will be called before
- *	free_irq and be used to handle some platform specific
- *	irq disablement
+ * @runtime_resume: an optional handler which will be called by the
+ *	runtime PM framework following a call to pm_runtime_get().
+ *	Note that if pm_runtime_get() is called more than once in
+ *	succession this handler will only be called once.
+ * @runtime_suspend: an optional handler which will be called by the
+ *	runtime PM framework following a call to pm_runtime_put().
+ *	Note that if pm_runtime_get() is called more than once in
+ *	succession this handler will only be called following the
+ *	final call to pm_runtime_put() that actually disables the
+ *	hardware.
  */
 struct arm_pmu_platdata {
 	irqreturn_t (*handle_irq)(int irq, void *dev,
 				  irq_handler_t pmu_handler);
-	void (*enable_irq)(int irq);
-	void (*disable_irq)(int irq);
+	int (*runtime_resume)(struct device *dev);
+	int (*runtime_suspend)(struct device *dev);
 };
 
-#ifdef CONFIG_CPU_HAS_PMU
-
-/**
- * reserve_pmu() - reserve the hardware performance counters
- *
- * Reserve the hardware performance counters in the system for exclusive use.
- * Returns 0 on success or -EBUSY if the lock is already held.
- */
-extern int
-reserve_pmu(enum arm_pmu_type type);
-
-/**
- * release_pmu() - Relinquish control of the performance counters
- *
- * Release the performance counters and allow someone else to use them.
- */
-extern void
-release_pmu(enum arm_pmu_type type);
-
-#else /* CONFIG_CPU_HAS_PMU */
-
-#include <linux/err.h>
-
-static inline int
-reserve_pmu(enum arm_pmu_type type)
-{
-	return -ENODEV;
-}
-
-static inline void
-release_pmu(enum arm_pmu_type type)	{ }
-
-#endif /* CONFIG_CPU_HAS_PMU */
-
 #ifdef CONFIG_HW_PERF_EVENTS
 
 /* The events for a given PMU register set. */
@@ -103,7 +64,6 @@ struct pmu_hw_events {
 
 struct arm_pmu {
 	struct pmu	pmu;
-	enum arm_pmu_type type;
 	cpumask_t	active_irqs;
 	char		*name;
 	irqreturn_t	(*handle_irq)(int irq_num, void *dev);
@@ -118,6 +78,8 @@ struct arm_pmu {
 	void		(*start)(void);
 	void		(*stop)(void);
 	void		(*reset)(void *);
+	int		(*request_irq)(irq_handler_t handler);
+	void		(*free_irq)(void);
 	int		(*map_event)(struct perf_event *event);
 	int		num_events;
 	atomic_t	active_events;
@@ -129,7 +91,9 @@ struct arm_pmu {
 
 #define to_arm_pmu(p) (container_of(p, struct arm_pmu, pmu))
 
-int __init armpmu_register(struct arm_pmu *armpmu, char *name, int type);
+extern const struct dev_pm_ops armpmu_dev_pm_ops;
+
+int armpmu_register(struct arm_pmu *armpmu, char *name, int type);
 
 u64 armpmu_event_update(struct perf_event *event,
 			struct hw_perf_event *hwc,
@@ -139,6 +103,13 @@ int armpmu_event_set_period(struct perf_event *event,
 			    struct hw_perf_event *hwc,
 			    int idx);
 
+int armpmu_map_event(struct perf_event *event,
+		     const unsigned (*event_map)[PERF_COUNT_HW_MAX],
+		     const unsigned (*cache_map)[PERF_COUNT_HW_CACHE_MAX]
+						[PERF_COUNT_HW_CACHE_OP_MAX]
+						[PERF_COUNT_HW_CACHE_RESULT_MAX],
+		     u32 raw_event_mask);
+
 #endif /* CONFIG_HW_PERF_EVENTS */
 
 #endif /* __ARM_PMU_H__ */
diff --git a/arch/arm/include/asm/processor.h b/arch/arm/include/asm/processor.h
index 99afa74..06e7d50 100644
--- a/arch/arm/include/asm/processor.h
+++ b/arch/arm/include/asm/processor.h
@@ -85,11 +85,6 @@ unsigned long get_wchan(struct task_struct *p);
 #define cpu_relax()			barrier()
 #endif
 
-/*
- * Create a new kernel thread
- */
-extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
-
 #define task_pt_regs(p) \
 	((struct pt_regs *)(THREAD_START_SP + task_stack_page(p)) - 1)
 
diff --git a/arch/arm/include/asm/ptrace.h b/arch/arm/include/asm/ptrace.h
index 355ece5..44fe998 100644
--- a/arch/arm/include/asm/ptrace.h
+++ b/arch/arm/include/asm/ptrace.h
@@ -254,6 +254,11 @@ static inline unsigned long user_stack_pointer(struct pt_regs *regs)
 	return regs->ARM_sp;
 }
 
+#define current_pt_regs(void) ({				\
+	register unsigned long sp asm ("sp");			\
+	(struct pt_regs *)((sp | (THREAD_SIZE - 1)) - 7) - 1;	\
+})
+
 #endif /* __KERNEL__ */
 
 #endif /* __ASSEMBLY__ */
diff --git a/arch/arm/include/asm/segment.h b/arch/arm/include/asm/segment.h
deleted file mode 100644
index 9e24c21..0000000
--- a/arch/arm/include/asm/segment.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef __ASM_ARM_SEGMENT_H
-#define __ASM_ARM_SEGMENT_H
-
-#define __KERNEL_CS   0x0
-#define __KERNEL_DS   0x0
-
-#define __USER_CS     0x1
-#define __USER_DS     0x1
-
-#endif /* __ASM_ARM_SEGMENT_H */
-
diff --git a/arch/arm/include/asm/sembuf.h b/arch/arm/include/asm/sembuf.h
deleted file mode 100644
index 1c02839..0000000
--- a/arch/arm/include/asm/sembuf.h
+++ /dev/null
@@ -1,25 +0,0 @@
-#ifndef _ASMARM_SEMBUF_H
-#define _ASMARM_SEMBUF_H
-
-/* 
- * The semid64_ds structure for arm architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 64-bit time_t to solve y2038 problem
- * - 2 miscellaneous 32-bit values
- */
-
-struct semid64_ds {
-	struct ipc64_perm sem_perm;		/* permissions .. see ipc.h */
-	__kernel_time_t	sem_otime;		/* last semop time */
-	unsigned long	__unused1;
-	__kernel_time_t	sem_ctime;		/* last change time */
-	unsigned long	__unused2;
-	unsigned long	sem_nsems;		/* no. of semaphores in array */
-	unsigned long	__unused3;
-	unsigned long	__unused4;
-};
-
-#endif /* _ASMARM_SEMBUF_H */
diff --git a/arch/arm/include/asm/serial.h b/arch/arm/include/asm/serial.h
deleted file mode 100644
index ebb0490..0000000
--- a/arch/arm/include/asm/serial.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- *  arch/arm/include/asm/serial.h
- *
- *  Copyright (C) 1996 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.
- *
- *  Changelog:
- *   15-10-1996	RMK	Created
- */
-
-#ifndef __ASM_SERIAL_H
-#define __ASM_SERIAL_H
-
-#define BASE_BAUD	(1843200 / 16)
-
-#endif
diff --git a/arch/arm/include/asm/shmbuf.h b/arch/arm/include/asm/shmbuf.h
deleted file mode 100644
index 2e5c67b..0000000
--- a/arch/arm/include/asm/shmbuf.h
+++ /dev/null
@@ -1,42 +0,0 @@
-#ifndef _ASMARM_SHMBUF_H
-#define _ASMARM_SHMBUF_H
-
-/* 
- * The shmid64_ds structure for arm architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 64-bit time_t to solve y2038 problem
- * - 2 miscellaneous 32-bit values
- */
-
-struct shmid64_ds {
-	struct ipc64_perm	shm_perm;	/* operation perms */
-	size_t			shm_segsz;	/* size of segment (bytes) */
-	__kernel_time_t		shm_atime;	/* last attach time */
-	unsigned long		__unused1;
-	__kernel_time_t		shm_dtime;	/* last detach time */
-	unsigned long		__unused2;
-	__kernel_time_t		shm_ctime;	/* last change time */
-	unsigned long		__unused3;
-	__kernel_pid_t		shm_cpid;	/* pid of creator */
-	__kernel_pid_t		shm_lpid;	/* pid of last operator */
-	unsigned long		shm_nattch;	/* no. of current attaches */
-	unsigned long		__unused4;
-	unsigned long		__unused5;
-};
-
-struct shminfo64 {
-	unsigned long	shmmax;
-	unsigned long	shmmin;
-	unsigned long	shmmni;
-	unsigned long	shmseg;
-	unsigned long	shmall;
-	unsigned long	__unused1;
-	unsigned long	__unused2;
-	unsigned long	__unused3;
-	unsigned long	__unused4;
-};
-
-#endif /* _ASMARM_SHMBUF_H */
diff --git a/arch/arm/include/asm/smp.h b/arch/arm/include/asm/smp.h
index ae29293..2e3be16 100644
--- a/arch/arm/include/asm/smp.h
+++ b/arch/arm/include/asm/smp.h
@@ -60,15 +60,6 @@ extern int boot_secondary(unsigned int cpu, struct task_struct *);
  */
 asmlinkage void secondary_start_kernel(void);
 
-/*
- * Perform platform specific initialisation of the specified CPU.
- */
-extern void platform_secondary_init(unsigned int cpu);
-
-/*
- * Initialize cpu_possible map, and enable coherency
- */
-extern void platform_smp_prepare_cpus(unsigned int);
 
 /*
  * Initial data for bringing up a secondary CPU.
@@ -79,18 +70,47 @@ struct secondary_data {
 	void *stack;
 };
 extern struct secondary_data secondary_data;
+extern volatile int pen_release;
 
 extern int __cpu_disable(void);
-extern int platform_cpu_disable(unsigned int cpu);
 
 extern void __cpu_die(unsigned int cpu);
 extern void cpu_die(void);
 
-extern void platform_cpu_die(unsigned int cpu);
-extern int platform_cpu_kill(unsigned int cpu);
-extern void platform_cpu_enable(unsigned int cpu);
-
 extern void arch_send_call_function_single_ipi(int cpu);
 extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
 
+struct smp_operations {
+#ifdef CONFIG_SMP
+	/*
+	 * Setup the set of possible CPUs (via set_cpu_possible)
+	 */
+	void (*smp_init_cpus)(void);
+	/*
+	 * Initialize cpu_possible map, and enable coherency
+	 */
+	void (*smp_prepare_cpus)(unsigned int max_cpus);
+
+	/*
+	 * Perform platform specific initialisation of the specified CPU.
+	 */
+	void (*smp_secondary_init)(unsigned int cpu);
+	/*
+	 * Boot a secondary CPU, and assign it the specified idle task.
+	 * This also gives us the initial stack to use for this CPU.
+	 */
+	int  (*smp_boot_secondary)(unsigned int cpu, struct task_struct *idle);
+#ifdef CONFIG_HOTPLUG_CPU
+	int  (*cpu_kill)(unsigned int cpu);
+	void (*cpu_die)(unsigned int cpu);
+	int  (*cpu_disable)(unsigned int cpu);
+#endif
+#endif
+};
+
+/*
+ * set platform specific SMP operations
+ */
+extern void smp_set_ops(struct smp_operations *);
+
 #endif /* ifndef __ASM_ARM_SMP_H */
diff --git a/arch/arm/include/asm/socket.h b/arch/arm/include/asm/socket.h
deleted file mode 100644
index 6433cad..0000000
--- a/arch/arm/include/asm/socket.h
+++ /dev/null
@@ -1,72 +0,0 @@
-#ifndef _ASMARM_SOCKET_H
-#define _ASMARM_SOCKET_H
-
-#include <asm/sockios.h>
-
-/* For setsockopt(2) */
-#define SOL_SOCKET	1
-
-#define SO_DEBUG	1
-#define SO_REUSEADDR	2
-#define SO_TYPE		3
-#define SO_ERROR	4
-#define SO_DONTROUTE	5
-#define SO_BROADCAST	6
-#define SO_SNDBUF	7
-#define SO_RCVBUF	8
-#define SO_SNDBUFFORCE	32
-#define SO_RCVBUFFORCE	33
-#define SO_KEEPALIVE	9
-#define SO_OOBINLINE	10
-#define SO_NO_CHECK	11
-#define SO_PRIORITY	12
-#define SO_LINGER	13
-#define SO_BSDCOMPAT	14
-/* To add :#define SO_REUSEPORT 15 */
-#define SO_PASSCRED	16
-#define SO_PEERCRED	17
-#define SO_RCVLOWAT	18
-#define SO_SNDLOWAT	19
-#define SO_RCVTIMEO	20
-#define SO_SNDTIMEO	21
-
-/* Security levels - as per NRL IPv6 - don't actually do anything */
-#define SO_SECURITY_AUTHENTICATION		22
-#define SO_SECURITY_ENCRYPTION_TRANSPORT	23
-#define SO_SECURITY_ENCRYPTION_NETWORK		24
-
-#define SO_BINDTODEVICE 25
-
-/* Socket filtering */
-#define SO_ATTACH_FILTER        26
-#define SO_DETACH_FILTER        27
-
-#define SO_PEERNAME             28
-#define SO_TIMESTAMP		29
-#define SCM_TIMESTAMP		SO_TIMESTAMP
-
-#define SO_ACCEPTCONN		30
-
-#define SO_PEERSEC		31
-#define SO_PASSSEC		34
-#define SO_TIMESTAMPNS		35
-#define SCM_TIMESTAMPNS		SO_TIMESTAMPNS
-
-#define SO_MARK			36
-
-#define SO_TIMESTAMPING		37
-#define SCM_TIMESTAMPING	SO_TIMESTAMPING
-
-#define SO_PROTOCOL		38
-#define SO_DOMAIN		39
-
-#define SO_RXQ_OVFL             40
-
-#define SO_WIFI_STATUS		41
-#define SCM_WIFI_STATUS		SO_WIFI_STATUS
-#define SO_PEEK_OFF		42
-
-/* Instruct lower device to use last 4-bytes of skb data as FCS */
-#define SO_NOFCS		43
-
-#endif /* _ASM_SOCKET_H */
diff --git a/arch/arm/include/asm/sockios.h b/arch/arm/include/asm/sockios.h
deleted file mode 100644
index a2588a2..0000000
--- a/arch/arm/include/asm/sockios.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef __ARCH_ARM_SOCKIOS_H
-#define __ARCH_ARM_SOCKIOS_H
-
-/* Socket-level I/O control calls. */
-#define FIOSETOWN 	0x8901
-#define SIOCSPGRP	0x8902
-#define FIOGETOWN	0x8903
-#define SIOCGPGRP	0x8904
-#define SIOCATMARK	0x8905
-#define SIOCGSTAMP	0x8906		/* Get stamp (timeval) */
-#define SIOCGSTAMPNS	0x8907		/* Get stamp (timespec) */
-
-#endif
diff --git a/arch/arm/include/asm/syscall.h b/arch/arm/include/asm/syscall.h
index c334a23..47486a4 100644
--- a/arch/arm/include/asm/syscall.h
+++ b/arch/arm/include/asm/syscall.h
@@ -9,6 +9,10 @@
 
 #include <linux/err.h>
 
+#include <asm/unistd.h>
+
+#define NR_syscalls (__NR_syscalls)
+
 extern const unsigned long sys_call_table[];
 
 static inline int syscall_get_nr(struct task_struct *task,
diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h
index 74542c5..368165e 100644
--- a/arch/arm/include/asm/system.h
+++ b/arch/arm/include/asm/system.h
@@ -2,7 +2,6 @@
 #include <asm/barrier.h>
 #include <asm/compiler.h>
 #include <asm/cmpxchg.h>
-#include <asm/exec.h>
 #include <asm/switch_to.h>
 #include <asm/system_info.h>
 #include <asm/system_misc.h>
diff --git a/arch/arm/include/asm/termbits.h b/arch/arm/include/asm/termbits.h
deleted file mode 100644
index 704135d..0000000
--- a/arch/arm/include/asm/termbits.h
+++ /dev/null
@@ -1,198 +0,0 @@
-#ifndef __ASM_ARM_TERMBITS_H
-#define __ASM_ARM_TERMBITS_H
-
-typedef unsigned char	cc_t;
-typedef unsigned int	speed_t;
-typedef unsigned int	tcflag_t;
-
-#define NCCS 19
-struct termios {
-	tcflag_t c_iflag;		/* input mode flags */
-	tcflag_t c_oflag;		/* output mode flags */
-	tcflag_t c_cflag;		/* control mode flags */
-	tcflag_t c_lflag;		/* local mode flags */
-	cc_t c_line;			/* line discipline */
-	cc_t c_cc[NCCS];		/* control characters */
-};
-
-struct termios2 {
-	tcflag_t c_iflag;		/* input mode flags */
-	tcflag_t c_oflag;		/* output mode flags */
-	tcflag_t c_cflag;		/* control mode flags */
-	tcflag_t c_lflag;		/* local mode flags */
-	cc_t c_line;			/* line discipline */
-	cc_t c_cc[NCCS];		/* control characters */
-	speed_t c_ispeed;		/* input speed */
-	speed_t c_ospeed;		/* output speed */
-};
-
-struct ktermios {
-	tcflag_t c_iflag;		/* input mode flags */
-	tcflag_t c_oflag;		/* output mode flags */
-	tcflag_t c_cflag;		/* control mode flags */
-	tcflag_t c_lflag;		/* local mode flags */
-	cc_t c_line;			/* line discipline */
-	cc_t c_cc[NCCS];		/* control characters */
-	speed_t c_ispeed;		/* input speed */
-	speed_t c_ospeed;		/* output speed */
-};
-
-
-/* c_cc characters */
-#define VINTR 0
-#define VQUIT 1
-#define VERASE 2
-#define VKILL 3
-#define VEOF 4
-#define VTIME 5
-#define VMIN 6
-#define VSWTC 7
-#define VSTART 8
-#define VSTOP 9
-#define VSUSP 10
-#define VEOL 11
-#define VREPRINT 12
-#define VDISCARD 13
-#define VWERASE 14
-#define VLNEXT 15
-#define VEOL2 16
-
-/* c_iflag bits */
-#define IGNBRK	0000001
-#define BRKINT	0000002
-#define IGNPAR	0000004
-#define PARMRK	0000010
-#define INPCK	0000020
-#define ISTRIP	0000040
-#define INLCR	0000100
-#define IGNCR	0000200
-#define ICRNL	0000400
-#define IUCLC	0001000
-#define IXON	0002000
-#define IXANY	0004000
-#define IXOFF	0010000
-#define IMAXBEL	0020000
-#define IUTF8	0040000
-
-/* c_oflag bits */
-#define OPOST	0000001
-#define OLCUC	0000002
-#define ONLCR	0000004
-#define OCRNL	0000010
-#define ONOCR	0000020
-#define ONLRET	0000040
-#define OFILL	0000100
-#define OFDEL	0000200
-#define NLDLY	0000400
-#define   NL0	0000000
-#define   NL1	0000400
-#define CRDLY	0003000
-#define   CR0	0000000
-#define   CR1	0001000
-#define   CR2	0002000
-#define   CR3	0003000
-#define TABDLY	0014000
-#define   TAB0	0000000
-#define   TAB1	0004000
-#define   TAB2	0010000
-#define   TAB3	0014000
-#define   XTABS	0014000
-#define BSDLY	0020000
-#define   BS0	0000000
-#define   BS1	0020000
-#define VTDLY	0040000
-#define   VT0	0000000
-#define   VT1	0040000
-#define FFDLY	0100000
-#define   FF0	0000000
-#define   FF1	0100000
-
-/* c_cflag bit meaning */
-#define CBAUD	0010017
-#define  B0	0000000		/* hang up */
-#define  B50	0000001
-#define  B75	0000002
-#define  B110	0000003
-#define  B134	0000004
-#define  B150	0000005
-#define  B200	0000006
-#define  B300	0000007
-#define  B600	0000010
-#define  B1200	0000011
-#define  B1800	0000012
-#define  B2400	0000013
-#define  B4800	0000014
-#define  B9600	0000015
-#define  B19200	0000016
-#define  B38400	0000017
-#define EXTA B19200
-#define EXTB B38400
-#define CSIZE	0000060
-#define   CS5	0000000
-#define   CS6	0000020
-#define   CS7	0000040
-#define   CS8	0000060
-#define CSTOPB	0000100
-#define CREAD	0000200
-#define PARENB	0000400
-#define PARODD	0001000
-#define HUPCL	0002000
-#define CLOCAL	0004000
-#define CBAUDEX 0010000
-#define    BOTHER 0010000
-#define    B57600 0010001
-#define   B115200 0010002
-#define   B230400 0010003
-#define   B460800 0010004
-#define   B500000 0010005
-#define   B576000 0010006
-#define   B921600 0010007
-#define  B1000000 0010010
-#define  B1152000 0010011
-#define  B1500000 0010012
-#define  B2000000 0010013
-#define  B2500000 0010014
-#define  B3000000 0010015
-#define  B3500000 0010016
-#define  B4000000 0010017
-#define CIBAUD	  002003600000		/* input baud rate */
-#define CMSPAR    010000000000		/* mark or space (stick) parity */
-#define CRTSCTS	  020000000000		/* flow control */
-
-#define IBSHIFT	   16
-
-/* c_lflag bits */
-#define ISIG	0000001
-#define ICANON	0000002
-#define XCASE	0000004
-#define ECHO	0000010
-#define ECHOE	0000020
-#define ECHOK	0000040
-#define ECHONL	0000100
-#define NOFLSH	0000200
-#define TOSTOP	0000400
-#define ECHOCTL	0001000
-#define ECHOPRT	0002000
-#define ECHOKE	0004000
-#define FLUSHO	0010000
-#define PENDIN	0040000
-#define IEXTEN	0100000
-#define EXTPROC	0200000
-
-/* tcflow() and TCXONC use these */
-#define	TCOOFF		0
-#define	TCOON		1
-#define	TCIOFF		2
-#define	TCION		3
-
-/* tcflush() and TCFLSH use these */
-#define	TCIFLUSH	0
-#define	TCOFLUSH	1
-#define	TCIOFLUSH	2
-
-/* tcsetattr uses these */
-#define	TCSANOW		0
-#define	TCSADRAIN	1
-#define	TCSAFLUSH	2
-
-#endif	/* __ASM_ARM_TERMBITS_H */
diff --git a/arch/arm/include/asm/termios.h b/arch/arm/include/asm/termios.h
deleted file mode 100644
index 293e3f1..0000000
--- a/arch/arm/include/asm/termios.h
+++ /dev/null
@@ -1,92 +0,0 @@
-#ifndef __ASM_ARM_TERMIOS_H
-#define __ASM_ARM_TERMIOS_H
-
-#include <asm/termbits.h>
-#include <asm/ioctls.h>
-
-struct winsize {
-	unsigned short ws_row;
-	unsigned short ws_col;
-	unsigned short ws_xpixel;
-	unsigned short ws_ypixel;
-};
-
-#define NCC 8
-struct termio {
-	unsigned short c_iflag;		/* input mode flags */
-	unsigned short c_oflag;		/* output mode flags */
-	unsigned short c_cflag;		/* control mode flags */
-	unsigned short c_lflag;		/* local mode flags */
-	unsigned char c_line;		/* line discipline */
-	unsigned char c_cc[NCC];	/* control characters */
-};
-
-#ifdef __KERNEL__
-/*	intr=^C		quit=^|		erase=del	kill=^U
-	eof=^D		vtime=\0	vmin=\1		sxtc=\0
-	start=^Q	stop=^S		susp=^Z		eol=\0
-	reprint=^R	discard=^U	werase=^W	lnext=^V
-	eol2=\0
-*/
-#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0"
-#endif
-
-/* modem lines */
-#define TIOCM_LE	0x001
-#define TIOCM_DTR	0x002
-#define TIOCM_RTS	0x004
-#define TIOCM_ST	0x008
-#define TIOCM_SR	0x010
-#define TIOCM_CTS	0x020
-#define TIOCM_CAR	0x040
-#define TIOCM_RNG	0x080
-#define TIOCM_DSR	0x100
-#define TIOCM_CD	TIOCM_CAR
-#define TIOCM_RI	TIOCM_RNG
-#define TIOCM_OUT1	0x2000
-#define TIOCM_OUT2	0x4000
-#define TIOCM_LOOP	0x8000
-
-/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
-
-#ifdef __KERNEL__
-
-/*
- * Translate a "termio" structure into a "termios". Ugh.
- */
-#define SET_LOW_TERMIOS_BITS(termios, termio, x) {		\
-	unsigned short __tmp;					\
-	get_user(__tmp,&(termio)->x);				\
-	*(unsigned short *) &(termios)->x = __tmp;		\
-}
-
-#define user_termio_to_kernel_termios(termios, termio) \
-({ \
-	SET_LOW_TERMIOS_BITS(termios, termio, c_iflag); \
-	SET_LOW_TERMIOS_BITS(termios, termio, c_oflag); \
-	SET_LOW_TERMIOS_BITS(termios, termio, c_cflag); \
-	SET_LOW_TERMIOS_BITS(termios, termio, c_lflag); \
-	copy_from_user((termios)->c_cc, (termio)->c_cc, NCC); \
-})
-
-/*
- * Translate a "termios" structure into a "termio". Ugh.
- */
-#define kernel_termios_to_user_termio(termio, termios) \
-({ \
-	put_user((termios)->c_iflag, &(termio)->c_iflag); \
-	put_user((termios)->c_oflag, &(termio)->c_oflag); \
-	put_user((termios)->c_cflag, &(termio)->c_cflag); \
-	put_user((termios)->c_lflag, &(termio)->c_lflag); \
-	put_user((termios)->c_line,  &(termio)->c_line); \
-	copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
-})
-
-#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios2))
-#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios2))
-#define user_termios_to_kernel_termios_1(k, u) copy_from_user(k, u, sizeof(struct termios))
-#define kernel_termios_to_user_termios_1(u, k) copy_to_user(u, k, sizeof(struct termios))
-
-#endif	/* __KERNEL__ */
-
-#endif	/* __ASM_ARM_TERMIOS_H */
diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h
index af7b0bd..8477b4c 100644
--- a/arch/arm/include/asm/thread_info.h
+++ b/arch/arm/include/asm/thread_info.h
@@ -59,7 +59,9 @@ struct thread_info {
 	__u32			syscall;	/* syscall number */
 	__u8			used_cp[16];	/* thread used copro */
 	unsigned long		tp_value;
+#ifdef CONFIG_CRUNCH
 	struct crunch_state	crunchstate;
+#endif
 	union fp_state		fpstate __attribute__((aligned(8)));
 	union vfp_state		vfpstate;
 #ifdef CONFIG_ARM_THUMBEE
@@ -148,7 +150,7 @@ extern int vfp_restore_user_hwstate(struct user_vfp __user *,
 #define TIF_NOTIFY_RESUME	2	/* callback before returning to user */
 #define TIF_SYSCALL_TRACE	8
 #define TIF_SYSCALL_AUDIT	9
-#define TIF_POLLING_NRFLAG	16
+#define TIF_SYSCALL_TRACEPOINT	10
 #define TIF_USING_IWMMXT	17
 #define TIF_MEMDIE		18	/* is terminating due to OOM killer */
 #define TIF_RESTORE_SIGMASK	20
@@ -160,12 +162,12 @@ extern int vfp_restore_user_hwstate(struct user_vfp __user *,
 #define _TIF_NOTIFY_RESUME	(1 << TIF_NOTIFY_RESUME)
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
 #define _TIF_SYSCALL_AUDIT	(1 << TIF_SYSCALL_AUDIT)
-#define _TIF_POLLING_NRFLAG	(1 << TIF_POLLING_NRFLAG)
+#define _TIF_SYSCALL_TRACEPOINT	(1 << TIF_SYSCALL_TRACEPOINT)
 #define _TIF_USING_IWMMXT	(1 << TIF_USING_IWMMXT)
 #define _TIF_SECCOMP		(1 << TIF_SECCOMP)
 
 /* Checks for any syscall work in entry-common.S */
-#define _TIF_SYSCALL_WORK (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT)
+#define _TIF_SYSCALL_WORK (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | _TIF_SYSCALL_TRACEPOINT)
 
 /*
  * Change these and you break ASM code in entry-common.S
diff --git a/arch/arm/include/asm/timex.h b/arch/arm/include/asm/timex.h
index ce11944..e44bd28 100644
--- a/arch/arm/include/asm/timex.h
+++ b/arch/arm/include/asm/timex.h
@@ -13,14 +13,16 @@
 #define _ASMARM_TIMEX_H
 
 #include <asm/arch_timer.h>
+#ifdef CONFIG_ARCH_MULTIPLATFORM
+#define CLOCK_TICK_RATE 1000000
+#else
 #include <mach/timex.h>
-
-typedef unsigned long cycles_t;
+#endif
 
 #ifdef ARCH_HAS_READ_CURRENT_TIMER
 #define get_cycles()	({ cycles_t c; read_current_timer(&c) ? 0 : c; })
-#else
-#define get_cycles()	(0)
 #endif
 
+#include <asm-generic/timex.h>
+
 #endif
diff --git a/arch/arm/include/asm/types.h b/arch/arm/include/asm/types.h
deleted file mode 100644
index 28beab9..0000000
--- a/arch/arm/include/asm/types.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef __ASM_ARM_TYPES_H
-#define __ASM_ARM_TYPES_H
-
-#include <asm-generic/int-ll64.h>
-
-/*
- * These aren't exported outside the kernel to avoid name space clashes
- */
-#ifdef __KERNEL__
-
-#define BITS_PER_LONG 32
-
-#endif /* __KERNEL__ */
-
-#endif
-
diff --git a/arch/arm/include/asm/unaligned.h b/arch/arm/include/asm/unaligned.h
deleted file mode 100644
index 44593a8..0000000
--- a/arch/arm/include/asm/unaligned.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef _ASM_ARM_UNALIGNED_H
-#define _ASM_ARM_UNALIGNED_H
-
-#include <linux/unaligned/le_byteshift.h>
-#include <linux/unaligned/be_byteshift.h>
-#include <linux/unaligned/generic.h>
-
-/*
- * Select endianness
- */
-#ifndef __ARMEB__
-#define get_unaligned	__get_unaligned_le
-#define put_unaligned	__put_unaligned_le
-#else
-#define get_unaligned	__get_unaligned_be
-#define put_unaligned	__put_unaligned_be
-#endif
-
-#endif /* _ASM_ARM_UNALIGNED_H */
diff --git a/arch/arm/include/asm/unistd.h b/arch/arm/include/asm/unistd.h
index 2fde5fd..f259921 100644
--- a/arch/arm/include/asm/unistd.h
+++ b/arch/arm/include/asm/unistd.h
@@ -407,6 +407,14 @@
 					/* 378 for kcmp */
 
 /*
+ * This may need to be greater than __NR_last_syscall+1 in order to
+ * account for the padding in the syscall table
+ */
+#ifdef __KERNEL__
+#define __NR_syscalls  (380)
+#endif /* __KERNEL__ */
+
+/*
  * The following SWIs are ARM private.
  */
 #define __ARM_NR_BASE			(__NR_SYSCALL_BASE+0x0f0000)
@@ -470,6 +478,8 @@
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_SYS_SOCKETCALL
 #endif
+#define __ARCH_WANT_SYS_EXECVE
+#define __ARCH_WANT_KERNEL_EXECVE
 
 /*
  * "Conditional" syscalls
diff --git a/arch/arm/include/debug/highbank.S b/arch/arm/include/debug/highbank.S
new file mode 100644
index 0000000..8cad432
--- /dev/null
+++ b/arch/arm/include/debug/highbank.S
@@ -0,0 +1,17 @@
+/*
+ * Debugging macro include header
+ *
+ *  Copyright (C) 1994-1999 Russell King
+ *  Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+		.macro	addruart,rp,rv,tmp
+		ldr	\rv, =0xfee36000
+		ldr	\rp, =0xfff36000
+		.endm
+
+#include <asm/hardware/debug-pl01x.S>
diff --git a/arch/arm/include/debug/icedcc.S b/arch/arm/include/debug/icedcc.S
new file mode 100644
index 0000000..43afcb0
--- /dev/null
+++ b/arch/arm/include/debug/icedcc.S
@@ -0,0 +1,90 @@
+/*
+ *  arch/arm/include/debug/icedcc.S
+ *
+ *  Copyright (C) 1994-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.
+ *
+ */
+
+		@@ debug using ARM EmbeddedICE DCC channel
+
+		.macro	addruart, rp, rv, tmp
+		.endm
+
+#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K) || defined(CONFIG_CPU_V7)
+
+		.macro	senduart, rd, rx
+		mcr	p14, 0, \rd, c0, c5, 0
+		.endm
+
+		.macro	busyuart, rd, rx
+1001:
+		mrc	p14, 0, \rx, c0, c1, 0
+		tst	\rx, #0x20000000
+		beq	1001b
+		.endm
+
+		.macro	waituart, rd, rx
+		mov	\rd, #0x2000000
+1001:
+		subs	\rd, \rd, #1
+		bmi	1002f
+		mrc	p14, 0, \rx, c0, c1, 0
+		tst	\rx, #0x20000000
+		bne	1001b
+1002:
+		.endm
+
+#elif defined(CONFIG_CPU_XSCALE)
+
+		.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	senduart, rd, rx
+		mcr	p14, 0, \rd, c1, c0, 0
+		.endm
+
+		.macro	busyuart, rd, rx
+1001:
+		mrc	p14, 0, \rx, c0, c0, 0
+		tst	\rx, #2
+		beq	1001b
+
+		.endm
+
+		.macro	waituart, rd, rx
+		mov	\rd, #0x2000000
+1001:
+		subs	\rd, \rd, #1
+		bmi	1002f
+		mrc	p14, 0, \rx, c0, c0, 0
+		tst	\rx, #2
+		bne	1001b
+1002:
+		.endm
+
+#endif	/* CONFIG_CPU_V6 */
diff --git a/arch/arm/include/debug/mvebu.S b/arch/arm/include/debug/mvebu.S
new file mode 100644
index 0000000..865c6d0
--- /dev/null
+++ b/arch/arm/include/debug/mvebu.S
@@ -0,0 +1,25 @@
+/*
+ * Early serial output macro for Marvell  SoC
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Lior Amsalem <alior@marvell.com>
+ * Gregory Clement <gregory.clement@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#define ARMADA_370_XP_REGS_PHYS_BASE	0xd0000000
+#define ARMADA_370_XP_REGS_VIRT_BASE	0xfeb00000
+
+	.macro	addruart, rp, rv, tmp
+	ldr	\rp, =ARMADA_370_XP_REGS_PHYS_BASE
+	ldr	\rv, =ARMADA_370_XP_REGS_VIRT_BASE
+	orr	\rp, \rp, #0x00012000
+	orr	\rv, \rv, #0x00012000
+	.endm
+
+#define UART_SHIFT	2
+#include <asm/hardware/debug-8250.S>
diff --git a/arch/arm/include/debug/picoxcell.S b/arch/arm/include/debug/picoxcell.S
new file mode 100644
index 0000000..7419deb
--- /dev/null
+++ b/arch/arm/include/debug/picoxcell.S
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Derived from arch/arm/mach-davinci/include/mach/debug-macro.S to use 32-bit
+ * accesses to the 8250.
+ */
+#include <linux/serial_reg.h>
+
+#define UART_SHIFT 2
+#define PICOXCELL_UART1_BASE		0x80230000
+#define PHYS_TO_IO(x)			(((x) & 0x00ffffff) | 0xfe000000)
+
+		.macro	addruart, rp, rv, tmp
+		ldr	\rv, =PHYS_TO_IO(PICOXCELL_UART1_BASE)
+		ldr	\rp, =PICOXCELL_UART1_BASE
+		.endm
+
+		.macro	senduart,rd,rx
+		str	\rd, [\rx, #UART_TX << UART_SHIFT]
+		.endm
+
+		.macro	busyuart,rd,rx
+1002:		ldr	\rd, [\rx, #UART_LSR << UART_SHIFT]
+		and	\rd, \rd, #UART_LSR_TEMT | UART_LSR_THRE
+		teq	\rd, #UART_LSR_TEMT | UART_LSR_THRE
+		bne	1002b
+		.endm
+
+		/* The UART's don't have any flow control IO's wired up. */
+		.macro	waituart,rd,rx
+		.endm
diff --git a/arch/arm/include/debug/socfpga.S b/arch/arm/include/debug/socfpga.S
new file mode 100644
index 0000000..d6f26d2
--- /dev/null
+++ b/arch/arm/include/debug/socfpga.S
@@ -0,0 +1,16 @@
+/*
+ *  Copyright (C) 1994-1999 Russell King
+ *  Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+		.macro	addruart, rp, rv, tmp
+		mov	\rp, #DEBUG_LL_UART_OFFSET
+		orr	\rp, \rp, #0x00c00000
+		orr	\rv, \rp, #0xfe000000	@ virtual base
+		orr	\rp, \rp, #0xff000000	@ physical base
+		.endm
+
diff --git a/arch/arm/include/debug/vexpress.S b/arch/arm/include/debug/vexpress.S
new file mode 100644
index 0000000..9f509f5
--- /dev/null
+++ b/arch/arm/include/debug/vexpress.S
@@ -0,0 +1,84 @@
+/* arch/arm/mach-realview/include/mach/debug-macro.S
+ *
+ * Debugging macro include header
+ *
+ *  Copyright (C) 1994-1999 Russell King
+ *  Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#define DEBUG_LL_PHYS_BASE		0x10000000
+#define DEBUG_LL_UART_OFFSET		0x00009000
+
+#define DEBUG_LL_PHYS_BASE_RS1		0x1c000000
+#define DEBUG_LL_UART_OFFSET_RS1	0x00090000
+
+#define DEBUG_LL_VIRT_BASE		0xf8000000
+
+#if defined(CONFIG_DEBUG_VEXPRESS_UART0_DETECT)
+
+		.macro	addruart,rp,rv,tmp
+
+		@ Make an educated guess regarding the memory map:
+		@ - the original A9 core tile, which has MPCore peripherals
+		@   located at 0x1e000000, should use UART at 0x10009000
+		@ - all other (RS1 complaint) tiles use UART mapped
+		@   at 0x1c090000
+		mrc	p15, 4, \tmp, c15, c0, 0
+		cmp	\tmp, #0x1e000000
+
+		@ Original memory map
+		moveq	\rp, #DEBUG_LL_UART_OFFSET
+		orreq	\rv, \rp, #DEBUG_LL_VIRT_BASE
+		orreq	\rp, \rp, #DEBUG_LL_PHYS_BASE
+
+		@ RS1 memory map
+		movne	\rp, #DEBUG_LL_UART_OFFSET_RS1
+		orrne	\rv, \rp, #DEBUG_LL_VIRT_BASE
+		orrne	\rp, \rp, #DEBUG_LL_PHYS_BASE_RS1
+
+		.endm
+
+#include <asm/hardware/debug-pl01x.S>
+
+#elif defined(CONFIG_DEBUG_VEXPRESS_UART0_CA9)
+
+		.macro	addruart,rp,rv,tmp
+		mov	\rp, #DEBUG_LL_UART_OFFSET
+		orr	\rv, \rp, #DEBUG_LL_VIRT_BASE
+		orr	\rp, \rp, #DEBUG_LL_PHYS_BASE
+		.endm
+
+#include <asm/hardware/debug-pl01x.S>
+
+#elif defined(CONFIG_DEBUG_VEXPRESS_UART0_RS1)
+
+		.macro	addruart,rp,rv,tmp
+		mov	\rp, #DEBUG_LL_UART_OFFSET_RS1
+		orr	\rv, \rp, #DEBUG_LL_VIRT_BASE
+		orr	\rp, \rp, #DEBUG_LL_PHYS_BASE_RS1
+		.endm
+
+#include <asm/hardware/debug-pl01x.S>
+
+#else /* CONFIG_DEBUG_LL_UART_NONE */
+
+		.macro	addruart, rp, rv, tmp
+		/* Safe dummy values */
+		mov	\rp, #0
+		mov	\rv, #DEBUG_LL_VIRT_BASE
+		.endm
+
+		.macro	senduart,rd,rx
+		.endm
+
+		.macro	waituart,rd,rx
+		.endm
+
+		.macro	busyuart,rd,rx
+		.endm
+
+#endif
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index 7ad2d5c..5dfef9d 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -19,9 +19,10 @@ obj-y		:= elf.o entry-armv.o entry-common.o irq.o opcodes.o \
 		   process.o ptrace.o return_address.o sched_clock.o \
 		   setup.o signal.o stacktrace.o sys_arm.o time.o traps.o
 
-obj-$(CONFIG_DEPRECATED_PARAM_STRUCT) += compat.o
+obj-$(CONFIG_ATAGS)		+= atags_parse.o
+obj-$(CONFIG_ATAGS_PROC)	+= atags_proc.o
+obj-$(CONFIG_DEPRECATED_PARAM_STRUCT) += atags_compat.o
 
-obj-$(CONFIG_LEDS)		+= leds.o
 obj-$(CONFIG_OC_ETM)		+= etm.o
 obj-$(CONFIG_CPU_IDLE)		+= cpuidle.o
 obj-$(CONFIG_ISA_DMA_API)	+= dma.o
@@ -52,7 +53,6 @@ test-kprobes-objs		+= kprobes-test-thumb.o
 else
 test-kprobes-objs		+= kprobes-test-arm.o
 endif
-obj-$(CONFIG_ATAGS_PROC)	+= atags.o
 obj-$(CONFIG_OABI_COMPAT)	+= sys_oabi-compat.o
 obj-$(CONFIG_ARM_THUMBEE)	+= thumbee.o
 obj-$(CONFIG_KGDB)		+= kgdb.o
@@ -69,8 +69,7 @@ obj-$(CONFIG_CPU_XSC3)		+= xscale-cp0.o
 obj-$(CONFIG_CPU_MOHAWK)	+= xscale-cp0.o
 obj-$(CONFIG_CPU_PJ4)		+= pj4-cp0.o
 obj-$(CONFIG_IWMMXT)		+= iwmmxt.o
-obj-$(CONFIG_CPU_HAS_PMU)	+= pmu.o
-obj-$(CONFIG_HW_PERF_EVENTS)	+= perf_event.o
+obj-$(CONFIG_HW_PERF_EVENTS)	+= perf_event.o perf_event_cpu.o
 AFLAGS_iwmmxt.o			:= -Wa,-mcpu=iwmmxt
 obj-$(CONFIG_ARM_CPU_TOPOLOGY)  += topology.o
 
diff --git a/arch/arm/kernel/arch_timer.c b/arch/arm/kernel/arch_timer.c
index cf25880..c04c2a6 100644
--- a/arch/arm/kernel/arch_timer.c
+++ b/arch/arm/kernel/arch_timer.c
@@ -27,13 +27,23 @@
 #include <asm/sched_clock.h>
 
 static unsigned long arch_timer_rate;
-static int arch_timer_ppi;
-static int arch_timer_ppi2;
+
+enum ppi_nr {
+	PHYS_SECURE_PPI,
+	PHYS_NONSECURE_PPI,
+	VIRT_PPI,
+	HYP_PPI,
+	MAX_TIMER_PPI
+};
+
+static int arch_timer_ppi[MAX_TIMER_PPI];
 
 static struct clock_event_device __percpu **arch_timer_evt;
 
 extern void init_current_timer_delay(unsigned long freq);
 
+static bool arch_timer_use_virtual = true;
+
 /*
  * Architected system timer support.
  */
@@ -46,50 +56,104 @@ extern void init_current_timer_delay(unsigned long freq);
 #define ARCH_TIMER_REG_FREQ		1
 #define ARCH_TIMER_REG_TVAL		2
 
-static void arch_timer_reg_write(int reg, u32 val)
+#define ARCH_TIMER_PHYS_ACCESS		0
+#define ARCH_TIMER_VIRT_ACCESS		1
+
+/*
+ * These register accessors are marked inline so the compiler can
+ * nicely work out which register we want, and chuck away the rest of
+ * the code. At least it does so with a recent GCC (4.6.3).
+ */
+static inline void arch_timer_reg_write(const int access, const int reg, u32 val)
 {
-	switch (reg) {
-	case ARCH_TIMER_REG_CTRL:
-		asm volatile("mcr p15, 0, %0, c14, c2, 1" : : "r" (val));
-		break;
-	case ARCH_TIMER_REG_TVAL:
-		asm volatile("mcr p15, 0, %0, c14, c2, 0" : : "r" (val));
-		break;
+	if (access == ARCH_TIMER_PHYS_ACCESS) {
+		switch (reg) {
+		case ARCH_TIMER_REG_CTRL:
+			asm volatile("mcr p15, 0, %0, c14, c2, 1" : : "r" (val));
+			break;
+		case ARCH_TIMER_REG_TVAL:
+			asm volatile("mcr p15, 0, %0, c14, c2, 0" : : "r" (val));
+			break;
+		}
+	}
+
+	if (access == ARCH_TIMER_VIRT_ACCESS) {
+		switch (reg) {
+		case ARCH_TIMER_REG_CTRL:
+			asm volatile("mcr p15, 0, %0, c14, c3, 1" : : "r" (val));
+			break;
+		case ARCH_TIMER_REG_TVAL:
+			asm volatile("mcr p15, 0, %0, c14, c3, 0" : : "r" (val));
+			break;
+		}
 	}
 
 	isb();
 }
 
-static u32 arch_timer_reg_read(int reg)
+static inline u32 arch_timer_reg_read(const int access, const int reg)
 {
-	u32 val;
+	u32 val = 0;
+
+	if (access == ARCH_TIMER_PHYS_ACCESS) {
+		switch (reg) {
+		case ARCH_TIMER_REG_CTRL:
+			asm volatile("mrc p15, 0, %0, c14, c2, 1" : "=r" (val));
+			break;
+		case ARCH_TIMER_REG_TVAL:
+			asm volatile("mrc p15, 0, %0, c14, c2, 0" : "=r" (val));
+			break;
+		case ARCH_TIMER_REG_FREQ:
+			asm volatile("mrc p15, 0, %0, c14, c0, 0" : "=r" (val));
+			break;
+		}
+	}
 
-	switch (reg) {
-	case ARCH_TIMER_REG_CTRL:
-		asm volatile("mrc p15, 0, %0, c14, c2, 1" : "=r" (val));
-		break;
-	case ARCH_TIMER_REG_FREQ:
-		asm volatile("mrc p15, 0, %0, c14, c0, 0" : "=r" (val));
-		break;
-	case ARCH_TIMER_REG_TVAL:
-		asm volatile("mrc p15, 0, %0, c14, c2, 0" : "=r" (val));
-		break;
-	default:
-		BUG();
+	if (access == ARCH_TIMER_VIRT_ACCESS) {
+		switch (reg) {
+		case ARCH_TIMER_REG_CTRL:
+			asm volatile("mrc p15, 0, %0, c14, c3, 1" : "=r" (val));
+			break;
+		case ARCH_TIMER_REG_TVAL:
+			asm volatile("mrc p15, 0, %0, c14, c3, 0" : "=r" (val));
+			break;
+		}
 	}
 
 	return val;
 }
 
-static irqreturn_t arch_timer_handler(int irq, void *dev_id)
+static inline cycle_t arch_timer_counter_read(const int access)
 {
-	struct clock_event_device *evt = *(struct clock_event_device **)dev_id;
-	unsigned long ctrl;
+	cycle_t cval = 0;
+
+	if (access == ARCH_TIMER_PHYS_ACCESS)
+		asm volatile("mrrc p15, 0, %Q0, %R0, c14" : "=r" (cval));
+
+	if (access == ARCH_TIMER_VIRT_ACCESS)
+		asm volatile("mrrc p15, 1, %Q0, %R0, c14" : "=r" (cval));
+
+	return cval;
+}
+
+static inline cycle_t arch_counter_get_cntpct(void)
+{
+	return arch_timer_counter_read(ARCH_TIMER_PHYS_ACCESS);
+}
 
-	ctrl = arch_timer_reg_read(ARCH_TIMER_REG_CTRL);
+static inline cycle_t arch_counter_get_cntvct(void)
+{
+	return arch_timer_counter_read(ARCH_TIMER_VIRT_ACCESS);
+}
+
+static irqreturn_t inline timer_handler(const int access,
+					struct clock_event_device *evt)
+{
+	unsigned long ctrl;
+	ctrl = arch_timer_reg_read(access, ARCH_TIMER_REG_CTRL);
 	if (ctrl & ARCH_TIMER_CTRL_IT_STAT) {
 		ctrl |= ARCH_TIMER_CTRL_IT_MASK;
-		arch_timer_reg_write(ARCH_TIMER_REG_CTRL, ctrl);
+		arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl);
 		evt->event_handler(evt);
 		return IRQ_HANDLED;
 	}
@@ -97,63 +161,100 @@ static irqreturn_t arch_timer_handler(int irq, void *dev_id)
 	return IRQ_NONE;
 }
 
-static void arch_timer_disable(void)
+static irqreturn_t arch_timer_handler_virt(int irq, void *dev_id)
 {
-	unsigned long ctrl;
+	struct clock_event_device *evt = *(struct clock_event_device **)dev_id;
+
+	return timer_handler(ARCH_TIMER_VIRT_ACCESS, evt);
+}
+
+static irqreturn_t arch_timer_handler_phys(int irq, void *dev_id)
+{
+	struct clock_event_device *evt = *(struct clock_event_device **)dev_id;
 
-	ctrl = arch_timer_reg_read(ARCH_TIMER_REG_CTRL);
-	ctrl &= ~ARCH_TIMER_CTRL_ENABLE;
-	arch_timer_reg_write(ARCH_TIMER_REG_CTRL, ctrl);
+	return timer_handler(ARCH_TIMER_PHYS_ACCESS, evt);
 }
 
-static void arch_timer_set_mode(enum clock_event_mode mode,
-				struct clock_event_device *clk)
+static inline void timer_set_mode(const int access, int mode)
 {
+	unsigned long ctrl;
 	switch (mode) {
 	case CLOCK_EVT_MODE_UNUSED:
 	case CLOCK_EVT_MODE_SHUTDOWN:
-		arch_timer_disable();
+		ctrl = arch_timer_reg_read(access, ARCH_TIMER_REG_CTRL);
+		ctrl &= ~ARCH_TIMER_CTRL_ENABLE;
+		arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl);
 		break;
 	default:
 		break;
 	}
 }
 
-static int arch_timer_set_next_event(unsigned long evt,
-				     struct clock_event_device *unused)
+static void arch_timer_set_mode_virt(enum clock_event_mode mode,
+				     struct clock_event_device *clk)
 {
-	unsigned long ctrl;
+	timer_set_mode(ARCH_TIMER_VIRT_ACCESS, mode);
+}
+
+static void arch_timer_set_mode_phys(enum clock_event_mode mode,
+				     struct clock_event_device *clk)
+{
+	timer_set_mode(ARCH_TIMER_PHYS_ACCESS, mode);
+}
 
-	ctrl = arch_timer_reg_read(ARCH_TIMER_REG_CTRL);
+static inline void set_next_event(const int access, unsigned long evt)
+{
+	unsigned long ctrl;
+	ctrl = arch_timer_reg_read(access, ARCH_TIMER_REG_CTRL);
 	ctrl |= ARCH_TIMER_CTRL_ENABLE;
 	ctrl &= ~ARCH_TIMER_CTRL_IT_MASK;
+	arch_timer_reg_write(access, ARCH_TIMER_REG_TVAL, evt);
+	arch_timer_reg_write(access, ARCH_TIMER_REG_CTRL, ctrl);
+}
 
-	arch_timer_reg_write(ARCH_TIMER_REG_TVAL, evt);
-	arch_timer_reg_write(ARCH_TIMER_REG_CTRL, ctrl);
+static int arch_timer_set_next_event_virt(unsigned long evt,
+					  struct clock_event_device *unused)
+{
+	set_next_event(ARCH_TIMER_VIRT_ACCESS, evt);
+	return 0;
+}
 
+static int arch_timer_set_next_event_phys(unsigned long evt,
+					  struct clock_event_device *unused)
+{
+	set_next_event(ARCH_TIMER_PHYS_ACCESS, evt);
 	return 0;
 }
 
 static int __cpuinit arch_timer_setup(struct clock_event_device *clk)
 {
-	/* Be safe... */
-	arch_timer_disable();
-
 	clk->features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_C3STOP;
 	clk->name = "arch_sys_timer";
 	clk->rating = 450;
-	clk->set_mode = arch_timer_set_mode;
-	clk->set_next_event = arch_timer_set_next_event;
-	clk->irq = arch_timer_ppi;
+	if (arch_timer_use_virtual) {
+		clk->irq = arch_timer_ppi[VIRT_PPI];
+		clk->set_mode = arch_timer_set_mode_virt;
+		clk->set_next_event = arch_timer_set_next_event_virt;
+	} else {
+		clk->irq = arch_timer_ppi[PHYS_SECURE_PPI];
+		clk->set_mode = arch_timer_set_mode_phys;
+		clk->set_next_event = arch_timer_set_next_event_phys;
+	}
+
+	clk->set_mode(CLOCK_EVT_MODE_SHUTDOWN, NULL);
 
 	clockevents_config_and_register(clk, arch_timer_rate,
 					0xf, 0x7fffffff);
 
 	*__this_cpu_ptr(arch_timer_evt) = clk;
 
-	enable_percpu_irq(clk->irq, 0);
-	if (arch_timer_ppi2)
-		enable_percpu_irq(arch_timer_ppi2, 0);
+	if (arch_timer_use_virtual)
+		enable_percpu_irq(arch_timer_ppi[VIRT_PPI], 0);
+	else {
+		enable_percpu_irq(arch_timer_ppi[PHYS_SECURE_PPI], 0);
+		if (arch_timer_ppi[PHYS_NONSECURE_PPI])
+			enable_percpu_irq(arch_timer_ppi[PHYS_NONSECURE_PPI], 0);
+	}
 
 	return 0;
 }
@@ -173,8 +274,8 @@ static int arch_timer_available(void)
 		return -ENXIO;
 
 	if (arch_timer_rate == 0) {
-		arch_timer_reg_write(ARCH_TIMER_REG_CTRL, 0);
-		freq = arch_timer_reg_read(ARCH_TIMER_REG_FREQ);
+		freq = arch_timer_reg_read(ARCH_TIMER_PHYS_ACCESS,
+					   ARCH_TIMER_REG_FREQ);
 
 		/* Check the timer frequency. */
 		if (freq == 0) {
@@ -185,43 +286,42 @@ static int arch_timer_available(void)
 		arch_timer_rate = freq;
 	}
 
-	pr_info_once("Architected local timer running at %lu.%02luMHz.\n",
-		     arch_timer_rate / 1000000, (arch_timer_rate / 10000) % 100);
+	pr_info_once("Architected local timer running at %lu.%02luMHz (%s).\n",
+		     arch_timer_rate / 1000000, (arch_timer_rate / 10000) % 100,
+		     arch_timer_use_virtual ? "virt" : "phys");
 	return 0;
 }
 
-static inline cycle_t arch_counter_get_cntpct(void)
-{
-	u32 cvall, cvalh;
-
-	asm volatile("mrrc p15, 0, %0, %1, c14" : "=r" (cvall), "=r" (cvalh));
-
-	return ((cycle_t) cvalh << 32) | cvall;
-}
-
-static inline cycle_t arch_counter_get_cntvct(void)
+static u32 notrace arch_counter_get_cntpct32(void)
 {
-	u32 cvall, cvalh;
+	cycle_t cnt = arch_counter_get_cntpct();
 
-	asm volatile("mrrc p15, 1, %0, %1, c14" : "=r" (cvall), "=r" (cvalh));
-
-	return ((cycle_t) cvalh << 32) | cvall;
+	/*
+	 * The sched_clock infrastructure only knows about counters
+	 * with at most 32bits. Forget about the upper 24 bits for the
+	 * time being...
+	 */
+	return (u32)cnt;
 }
 
 static u32 notrace arch_counter_get_cntvct32(void)
 {
-	cycle_t cntvct = arch_counter_get_cntvct();
+	cycle_t cnt = arch_counter_get_cntvct();
 
 	/*
 	 * The sched_clock infrastructure only knows about counters
 	 * with at most 32bits. Forget about the upper 24 bits for the
 	 * time being...
 	 */
-	return (u32)(cntvct & (u32)~0);
+	return (u32)cnt;
 }
 
 static cycle_t arch_counter_read(struct clocksource *cs)
 {
+	/*
+	 * Always use the physical counter for the clocksource.
+	 * CNTHCTL.PL1PCTEN must be set to 1.
+	 */
 	return arch_counter_get_cntpct();
 }
 
@@ -233,6 +333,15 @@ int read_current_timer(unsigned long *timer_val)
 	return 0;
 }
 
+static cycle_t arch_counter_read_cc(const struct cyclecounter *cc)
+{
+	/*
+	 * Always use the physical counter for the clocksource.
+	 * CNTHCTL.PL1PCTEN must be set to 1.
+	 */
+	return arch_counter_get_cntpct();
+}
+
 static struct clocksource clocksource_counter = {
 	.name	= "arch_sys_counter",
 	.rating	= 400,
@@ -241,14 +350,32 @@ static struct clocksource clocksource_counter = {
 	.flags	= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
+static struct cyclecounter cyclecounter = {
+	.read	= arch_counter_read_cc,
+	.mask	= CLOCKSOURCE_MASK(56),
+};
+
+static struct timecounter timecounter;
+
+struct timecounter *arch_timer_get_timecounter(void)
+{
+	return &timecounter;
+}
+
 static void __cpuinit arch_timer_stop(struct clock_event_device *clk)
 {
 	pr_debug("arch_timer_teardown disable IRQ%d cpu #%d\n",
 		 clk->irq, smp_processor_id());
-	disable_percpu_irq(clk->irq);
-	if (arch_timer_ppi2)
-		disable_percpu_irq(arch_timer_ppi2);
-	arch_timer_set_mode(CLOCK_EVT_MODE_UNUSED, clk);
+
+	if (arch_timer_use_virtual)
+		disable_percpu_irq(arch_timer_ppi[VIRT_PPI]);
+	else {
+		disable_percpu_irq(arch_timer_ppi[PHYS_SECURE_PPI]);
+		if (arch_timer_ppi[PHYS_NONSECURE_PPI])
+			disable_percpu_irq(arch_timer_ppi[PHYS_NONSECURE_PPI]);
+	}
+
+	clk->set_mode(CLOCK_EVT_MODE_UNUSED, clk);
 }
 
 static struct local_timer_ops arch_timer_ops __cpuinitdata = {
@@ -261,36 +388,48 @@ static struct clock_event_device arch_timer_global_evt;
 static int __init arch_timer_register(void)
 {
 	int err;
+	int ppi;
 
 	err = arch_timer_available();
 	if (err)
-		return err;
+		goto out;
 
 	arch_timer_evt = alloc_percpu(struct clock_event_device *);
-	if (!arch_timer_evt)
-		return -ENOMEM;
+	if (!arch_timer_evt) {
+		err = -ENOMEM;
+		goto out;
+	}
 
 	clocksource_register_hz(&clocksource_counter, arch_timer_rate);
+	cyclecounter.mult = clocksource_counter.mult;
+	cyclecounter.shift = clocksource_counter.shift;
+	timecounter_init(&timecounter, &cyclecounter,
+			 arch_counter_get_cntpct());
+
+	if (arch_timer_use_virtual) {
+		ppi = arch_timer_ppi[VIRT_PPI];
+		err = request_percpu_irq(ppi, arch_timer_handler_virt,
+					 "arch_timer", arch_timer_evt);
+	} else {
+		ppi = arch_timer_ppi[PHYS_SECURE_PPI];
+		err = request_percpu_irq(ppi, arch_timer_handler_phys,
+					 "arch_timer", arch_timer_evt);
+		if (!err && arch_timer_ppi[PHYS_NONSECURE_PPI]) {
+			ppi = arch_timer_ppi[PHYS_NONSECURE_PPI];
+			err = request_percpu_irq(ppi, arch_timer_handler_phys,
+						 "arch_timer", arch_timer_evt);
+			if (err)
+				free_percpu_irq(arch_timer_ppi[PHYS_SECURE_PPI],
+						arch_timer_evt);
+		}
+	}
 
-	err = request_percpu_irq(arch_timer_ppi, arch_timer_handler,
-				 "arch_timer", arch_timer_evt);
 	if (err) {
 		pr_err("arch_timer: can't register interrupt %d (%d)\n",
-		       arch_timer_ppi, err);
+		       ppi, err);
 		goto out_free;
 	}
 
-	if (arch_timer_ppi2) {
-		err = request_percpu_irq(arch_timer_ppi2, arch_timer_handler,
-					 "arch_timer", arch_timer_evt);
-		if (err) {
-			pr_err("arch_timer: can't register interrupt %d (%d)\n",
-			       arch_timer_ppi2, err);
-			arch_timer_ppi2 = 0;
-			goto out_free_irq;
-		}
-	}
-
 	err = local_timer_register(&arch_timer_ops);
 	if (err) {
 		/*
@@ -310,13 +449,19 @@ static int __init arch_timer_register(void)
 	return 0;
 
 out_free_irq:
-	free_percpu_irq(arch_timer_ppi, arch_timer_evt);
-	if (arch_timer_ppi2)
-		free_percpu_irq(arch_timer_ppi2, arch_timer_evt);
+	if (arch_timer_use_virtual)
+		free_percpu_irq(arch_timer_ppi[VIRT_PPI], arch_timer_evt);
+	else {
+		free_percpu_irq(arch_timer_ppi[PHYS_SECURE_PPI],
+				arch_timer_evt);
+		if (arch_timer_ppi[PHYS_NONSECURE_PPI])
+			free_percpu_irq(arch_timer_ppi[PHYS_NONSECURE_PPI],
+					arch_timer_evt);
+	}
 
 out_free:
 	free_percpu(arch_timer_evt);
-
+out:
 	return err;
 }
 
@@ -329,6 +474,7 @@ int __init arch_timer_of_register(void)
 {
 	struct device_node *np;
 	u32 freq;
+	int i;
 
 	np = of_find_matching_node(NULL, arch_timer_of_match);
 	if (!np) {
@@ -340,22 +486,40 @@ int __init arch_timer_of_register(void)
 	if (!of_property_read_u32(np, "clock-frequency", &freq))
 		arch_timer_rate = freq;
 
-	arch_timer_ppi = irq_of_parse_and_map(np, 0);
-	arch_timer_ppi2 = irq_of_parse_and_map(np, 1);
-	pr_info("arch_timer: found %s irqs %d %d\n",
-		np->name, arch_timer_ppi, arch_timer_ppi2);
+	for (i = PHYS_SECURE_PPI; i < MAX_TIMER_PPI; i++)
+		arch_timer_ppi[i] = irq_of_parse_and_map(np, i);
+
+	/*
+	 * If no interrupt provided for virtual timer, we'll have to
+	 * stick to the physical timer. It'd better be accessible...
+	 */
+	if (!arch_timer_ppi[VIRT_PPI]) {
+		arch_timer_use_virtual = false;
+
+		if (!arch_timer_ppi[PHYS_SECURE_PPI] ||
+		    !arch_timer_ppi[PHYS_NONSECURE_PPI]) {
+			pr_warn("arch_timer: No interrupt available, giving up\n");
+			return -EINVAL;
+		}
+	}
 
 	return arch_timer_register();
 }
 
 int __init arch_timer_sched_clock_init(void)
 {
+	u32 (*cnt32)(void);
 	int err;
 
 	err = arch_timer_available();
 	if (err)
 		return err;
 
-	setup_sched_clock(arch_counter_get_cntvct32, 32, arch_timer_rate);
+	if (arch_timer_use_virtual)
+		cnt32 = arch_counter_get_cntvct32;
+	else
+		cnt32 = arch_counter_get_cntpct32;
+
+	setup_sched_clock(cnt32, 32, arch_timer_rate);
 	return 0;
 }
diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
index 1429d89..c985b48 100644
--- a/arch/arm/kernel/asm-offsets.c
+++ b/arch/arm/kernel/asm-offsets.c
@@ -59,10 +59,12 @@ int main(void)
   DEFINE(TI_USED_CP,		offsetof(struct thread_info, used_cp));
   DEFINE(TI_TP_VALUE,		offsetof(struct thread_info, tp_value));
   DEFINE(TI_FPSTATE,		offsetof(struct thread_info, fpstate));
+#ifdef CONFIG_VFP
   DEFINE(TI_VFPSTATE,		offsetof(struct thread_info, vfpstate));
 #ifdef CONFIG_SMP
   DEFINE(VFP_CPU,		offsetof(union vfp_state, hard.cpu));
 #endif
+#endif
 #ifdef CONFIG_ARM_THUMBEE
   DEFINE(TI_THUMBEE_STATE,	offsetof(struct thread_info, thumbee_state));
 #endif
diff --git a/arch/arm/kernel/atags.c b/arch/arm/kernel/atags.c
deleted file mode 100644
index 42a1a14..0000000
--- a/arch/arm/kernel/atags.c
+++ /dev/null
@@ -1,83 +0,0 @@
-#include <linux/slab.h>
-#include <linux/proc_fs.h>
-#include <asm/setup.h>
-#include <asm/types.h>
-#include <asm/page.h>
-
-struct buffer {
-	size_t size;
-	char data[];
-};
-
-static int
-read_buffer(char* page, char** start, off_t off, int count,
-	int* eof, void* data)
-{
-	struct buffer *buffer = (struct buffer *)data;
-
-	if (off >= buffer->size) {
-		*eof = 1;
-		return 0;
-	}
-
-	count = min((int) (buffer->size - off), count);
-
-	memcpy(page, &buffer->data[off], count);
-
-	return count;
-}
-
-#define BOOT_PARAMS_SIZE 1536
-static char __initdata atags_copy[BOOT_PARAMS_SIZE];
-
-void __init save_atags(const struct tag *tags)
-{
-	memcpy(atags_copy, tags, sizeof(atags_copy));
-}
-
-static int __init init_atags_procfs(void)
-{
-	/*
-	 * This cannot go into save_atags() because kmalloc and proc don't work
-	 * yet when it is called.
-	 */
-	struct proc_dir_entry *tags_entry;
-	struct tag *tag = (struct tag *)atags_copy;
-	struct buffer *b;
-	size_t size;
-
-	if (tag->hdr.tag != ATAG_CORE) {
-		printk(KERN_INFO "No ATAGs?");
-		return -EINVAL;
-	}
-
-	for (; tag->hdr.size; tag = tag_next(tag))
-		;
-
-	/* include the terminating ATAG_NONE */
-	size = (char *)tag - atags_copy + sizeof(struct tag_header);
-
-	WARN_ON(tag->hdr.tag != ATAG_NONE);
-
-	b = kmalloc(sizeof(*b) + size, GFP_KERNEL);
-	if (!b)
-		goto nomem;
-
-	b->size = size;
-	memcpy(b->data, atags_copy, size);
-
-	tags_entry = create_proc_read_entry("atags", 0400,
-			NULL, read_buffer, b);
-
-	if (!tags_entry)
-		goto nomem;
-
-	return 0;
-
-nomem:
-	kfree(b);
-	printk(KERN_ERR "Exporting ATAGs: not enough memory\n");
-
-	return -ENOMEM;
-}
-arch_initcall(init_atags_procfs);
diff --git a/arch/arm/kernel/atags.h b/arch/arm/kernel/atags.h
index e5f028d..9edc969 100644
--- a/arch/arm/kernel/atags.h
+++ b/arch/arm/kernel/atags.h
@@ -3,3 +3,17 @@ extern void save_atags(struct tag *tags);
 #else
 static inline void save_atags(struct tag *tags) { }
 #endif
+
+void convert_to_tag_list(struct tag *tags);
+
+#ifdef CONFIG_ATAGS
+struct machine_desc *setup_machine_tags(phys_addr_t __atags_pointer, unsigned int machine_nr);
+#else
+static inline struct machine_desc *
+setup_machine_tags(phys_addr_t __atags_pointer, unsigned int machine_nr)
+{
+	early_print("no ATAGS support: can't continue\n");
+	while (true);
+	unreachable();
+}
+#endif
diff --git a/arch/arm/kernel/atags_compat.c b/arch/arm/kernel/atags_compat.c
new file mode 100644
index 0000000..5236ad3
--- /dev/null
+++ b/arch/arm/kernel/atags_compat.c
@@ -0,0 +1,219 @@
+/*
+ *  linux/arch/arm/kernel/atags_compat.c
+ *
+ *  Copyright (C) 2001 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * We keep the old params compatibility cruft in one place (here)
+ * so we don't end up with lots of mess around other places.
+ *
+ * NOTE:
+ *  The old struct param_struct is deprecated, but it will be kept in
+ *  the kernel for 5 years from now (2001). This will allow boot loaders
+ *  to convert to the new struct tag way.
+ */
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/init.h>
+
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/page.h>
+
+#include <asm/mach/arch.h>
+
+#include "atags.h"
+
+/*
+ * Usage:
+ *  - do not go blindly adding fields, add them at the end
+ *  - when adding fields, don't rely on the address until
+ *    a patch from me has been released
+ *  - unused fields should be zero (for future expansion)
+ *  - this structure is relatively short-lived - only
+ *    guaranteed to contain useful data in setup_arch()
+ *
+ * This is the old deprecated way to pass parameters to the kernel
+ */
+struct param_struct {
+    union {
+	struct {
+	    unsigned long page_size;		/*  0 */
+	    unsigned long nr_pages;		/*  4 */
+	    unsigned long ramdisk_size;		/*  8 */
+	    unsigned long flags;		/* 12 */
+#define FLAG_READONLY	1
+#define FLAG_RDLOAD	4
+#define FLAG_RDPROMPT	8
+	    unsigned long rootdev;		/* 16 */
+	    unsigned long video_num_cols;	/* 20 */
+	    unsigned long video_num_rows;	/* 24 */
+	    unsigned long video_x;		/* 28 */
+	    unsigned long video_y;		/* 32 */
+	    unsigned long memc_control_reg;	/* 36 */
+	    unsigned char sounddefault;		/* 40 */
+	    unsigned char adfsdrives;		/* 41 */
+	    unsigned char bytes_per_char_h;	/* 42 */
+	    unsigned char bytes_per_char_v;	/* 43 */
+	    unsigned long pages_in_bank[4];	/* 44 */
+	    unsigned long pages_in_vram;	/* 60 */
+	    unsigned long initrd_start;		/* 64 */
+	    unsigned long initrd_size;		/* 68 */
+	    unsigned long rd_start;		/* 72 */
+	    unsigned long system_rev;		/* 76 */
+	    unsigned long system_serial_low;	/* 80 */
+	    unsigned long system_serial_high;	/* 84 */
+	    unsigned long mem_fclk_21285;       /* 88 */
+	} s;
+	char unused[256];
+    } u1;
+    union {
+	char paths[8][128];
+	struct {
+	    unsigned long magic;
+	    char n[1024 - sizeof(unsigned long)];
+	} s;
+    } u2;
+    char commandline[COMMAND_LINE_SIZE];
+};
+
+static struct tag * __init memtag(struct tag *tag, unsigned long start, unsigned long size)
+{
+	tag = tag_next(tag);
+	tag->hdr.tag = ATAG_MEM;
+	tag->hdr.size = tag_size(tag_mem32);
+	tag->u.mem.size = size;
+	tag->u.mem.start = start;
+
+	return tag;
+}
+
+static void __init build_tag_list(struct param_struct *params, void *taglist)
+{
+	struct tag *tag = taglist;
+
+	if (params->u1.s.page_size != PAGE_SIZE) {
+		printk(KERN_WARNING "Warning: bad configuration page, "
+		       "trying to continue\n");
+		return;
+	}
+
+	printk(KERN_DEBUG "Converting old-style param struct to taglist\n");
+
+#ifdef CONFIG_ARCH_NETWINDER
+	if (params->u1.s.nr_pages != 0x02000 &&
+	    params->u1.s.nr_pages != 0x04000 &&
+	    params->u1.s.nr_pages != 0x08000 &&
+	    params->u1.s.nr_pages != 0x10000) {
+		printk(KERN_WARNING "Warning: bad NeTTrom parameters "
+		       "detected, using defaults\n");
+
+		params->u1.s.nr_pages = 0x1000;	/* 16MB */
+		params->u1.s.ramdisk_size = 0;
+		params->u1.s.flags = FLAG_READONLY;
+		params->u1.s.initrd_start = 0;
+		params->u1.s.initrd_size = 0;
+		params->u1.s.rd_start = 0;
+	}
+#endif
+
+	tag->hdr.tag  = ATAG_CORE;
+	tag->hdr.size = tag_size(tag_core);
+	tag->u.core.flags = params->u1.s.flags & FLAG_READONLY;
+	tag->u.core.pagesize = params->u1.s.page_size;
+	tag->u.core.rootdev = params->u1.s.rootdev;
+
+	tag = tag_next(tag);
+	tag->hdr.tag = ATAG_RAMDISK;
+	tag->hdr.size = tag_size(tag_ramdisk);
+	tag->u.ramdisk.flags = (params->u1.s.flags & FLAG_RDLOAD ? 1 : 0) |
+			       (params->u1.s.flags & FLAG_RDPROMPT ? 2 : 0);
+	tag->u.ramdisk.size  = params->u1.s.ramdisk_size;
+	tag->u.ramdisk.start = params->u1.s.rd_start;
+
+	tag = tag_next(tag);
+	tag->hdr.tag = ATAG_INITRD;
+	tag->hdr.size = tag_size(tag_initrd);
+	tag->u.initrd.start = params->u1.s.initrd_start;
+	tag->u.initrd.size  = params->u1.s.initrd_size;
+
+	tag = tag_next(tag);
+	tag->hdr.tag = ATAG_SERIAL;
+	tag->hdr.size = tag_size(tag_serialnr);
+	tag->u.serialnr.low = params->u1.s.system_serial_low;
+	tag->u.serialnr.high = params->u1.s.system_serial_high;
+
+	tag = tag_next(tag);
+	tag->hdr.tag = ATAG_REVISION;
+	tag->hdr.size = tag_size(tag_revision);
+	tag->u.revision.rev = params->u1.s.system_rev;
+
+#ifdef CONFIG_ARCH_ACORN
+	if (machine_is_riscpc()) {
+		int i;
+		for (i = 0; i < 4; i++)
+			tag = memtag(tag, PHYS_OFFSET + (i << 26),
+				 params->u1.s.pages_in_bank[i] * PAGE_SIZE);
+	} else
+#endif
+	tag = memtag(tag, PHYS_OFFSET, params->u1.s.nr_pages * PAGE_SIZE);
+
+#ifdef CONFIG_FOOTBRIDGE
+	if (params->u1.s.mem_fclk_21285) {
+		tag = tag_next(tag);
+		tag->hdr.tag = ATAG_MEMCLK;
+		tag->hdr.size = tag_size(tag_memclk);
+		tag->u.memclk.fmemclk = params->u1.s.mem_fclk_21285;
+	}
+#endif
+
+#ifdef CONFIG_ARCH_EBSA285
+	if (machine_is_ebsa285()) {
+		tag = tag_next(tag);
+		tag->hdr.tag = ATAG_VIDEOTEXT;
+		tag->hdr.size = tag_size(tag_videotext);
+		tag->u.videotext.x            = params->u1.s.video_x;
+		tag->u.videotext.y            = params->u1.s.video_y;
+		tag->u.videotext.video_page   = 0;
+		tag->u.videotext.video_mode   = 0;
+		tag->u.videotext.video_cols   = params->u1.s.video_num_cols;
+		tag->u.videotext.video_ega_bx = 0;
+		tag->u.videotext.video_lines  = params->u1.s.video_num_rows;
+		tag->u.videotext.video_isvga  = 1;
+		tag->u.videotext.video_points = 8;
+	}
+#endif
+
+#ifdef CONFIG_ARCH_ACORN
+	tag = tag_next(tag);
+	tag->hdr.tag = ATAG_ACORN;
+	tag->hdr.size = tag_size(tag_acorn);
+	tag->u.acorn.memc_control_reg = params->u1.s.memc_control_reg;
+	tag->u.acorn.vram_pages       = params->u1.s.pages_in_vram;
+	tag->u.acorn.sounddefault     = params->u1.s.sounddefault;
+	tag->u.acorn.adfsdrives       = params->u1.s.adfsdrives;
+#endif
+
+	tag = tag_next(tag);
+	tag->hdr.tag = ATAG_CMDLINE;
+	tag->hdr.size = (strlen(params->commandline) + 3 +
+			 sizeof(struct tag_header)) >> 2;
+	strcpy(tag->u.cmdline.cmdline, params->commandline);
+
+	tag = tag_next(tag);
+	tag->hdr.tag = ATAG_NONE;
+	tag->hdr.size = 0;
+
+	memmove(params, taglist, ((int)tag) - ((int)taglist) +
+				 sizeof(struct tag_header));
+}
+
+void __init convert_to_tag_list(struct tag *tags)
+{
+	struct param_struct *params = (struct param_struct *)tags;
+	build_tag_list(params, &params->u2);
+}
diff --git a/arch/arm/kernel/atags_parse.c b/arch/arm/kernel/atags_parse.c
new file mode 100644
index 0000000..14512e6
--- /dev/null
+++ b/arch/arm/kernel/atags_parse.c
@@ -0,0 +1,238 @@
+/*
+ * Tag parsing.
+ *
+ * Copyright (C) 1995-2001 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * This is the traditional way of passing data to the kernel at boot time.  Rather
+ * than passing a fixed inflexible structure to the kernel, we pass a list
+ * of variable-sized tags to the kernel.  The first tag must be a ATAG_CORE
+ * tag for the list to be recognised (to distinguish the tagged list from
+ * a param_struct).  The list is terminated with a zero-length tag (this tag
+ * is not parsed in any way).
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/root_dev.h>
+#include <linux/screen_info.h>
+
+#include <asm/setup.h>
+#include <asm/system_info.h>
+#include <asm/page.h>
+#include <asm/mach/arch.h>
+
+#include "atags.h"
+
+static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
+
+#ifndef MEM_SIZE
+#define MEM_SIZE	(16*1024*1024)
+#endif
+
+static struct {
+	struct tag_header hdr1;
+	struct tag_core   core;
+	struct tag_header hdr2;
+	struct tag_mem32  mem;
+	struct tag_header hdr3;
+} default_tags __initdata = {
+	{ tag_size(tag_core), ATAG_CORE },
+	{ 1, PAGE_SIZE, 0xff },
+	{ tag_size(tag_mem32), ATAG_MEM },
+	{ MEM_SIZE },
+	{ 0, ATAG_NONE }
+};
+
+static int __init parse_tag_core(const struct tag *tag)
+{
+	if (tag->hdr.size > 2) {
+		if ((tag->u.core.flags & 1) == 0)
+			root_mountflags &= ~MS_RDONLY;
+		ROOT_DEV = old_decode_dev(tag->u.core.rootdev);
+	}
+	return 0;
+}
+
+__tagtable(ATAG_CORE, parse_tag_core);
+
+static int __init parse_tag_mem32(const struct tag *tag)
+{
+	return arm_add_memory(tag->u.mem.start, tag->u.mem.size);
+}
+
+__tagtable(ATAG_MEM, parse_tag_mem32);
+
+#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
+static int __init parse_tag_videotext(const struct tag *tag)
+{
+	screen_info.orig_x            = tag->u.videotext.x;
+	screen_info.orig_y            = tag->u.videotext.y;
+	screen_info.orig_video_page   = tag->u.videotext.video_page;
+	screen_info.orig_video_mode   = tag->u.videotext.video_mode;
+	screen_info.orig_video_cols   = tag->u.videotext.video_cols;
+	screen_info.orig_video_ega_bx = tag->u.videotext.video_ega_bx;
+	screen_info.orig_video_lines  = tag->u.videotext.video_lines;
+	screen_info.orig_video_isVGA  = tag->u.videotext.video_isvga;
+	screen_info.orig_video_points = tag->u.videotext.video_points;
+	return 0;
+}
+
+__tagtable(ATAG_VIDEOTEXT, parse_tag_videotext);
+#endif
+
+#ifdef CONFIG_BLK_DEV_RAM
+static int __init parse_tag_ramdisk(const struct tag *tag)
+{
+	extern int rd_size, rd_image_start, rd_prompt, rd_doload;
+
+	rd_image_start = tag->u.ramdisk.start;
+	rd_doload = (tag->u.ramdisk.flags & 1) == 0;
+	rd_prompt = (tag->u.ramdisk.flags & 2) == 0;
+
+	if (tag->u.ramdisk.size)
+		rd_size = tag->u.ramdisk.size;
+
+	return 0;
+}
+
+__tagtable(ATAG_RAMDISK, parse_tag_ramdisk);
+#endif
+
+static int __init parse_tag_serialnr(const struct tag *tag)
+{
+	system_serial_low = tag->u.serialnr.low;
+	system_serial_high = tag->u.serialnr.high;
+	return 0;
+}
+
+__tagtable(ATAG_SERIAL, parse_tag_serialnr);
+
+static int __init parse_tag_revision(const struct tag *tag)
+{
+	system_rev = tag->u.revision.rev;
+	return 0;
+}
+
+__tagtable(ATAG_REVISION, parse_tag_revision);
+
+static int __init parse_tag_cmdline(const struct tag *tag)
+{
+#if defined(CONFIG_CMDLINE_EXTEND)
+	strlcat(default_command_line, " ", COMMAND_LINE_SIZE);
+	strlcat(default_command_line, tag->u.cmdline.cmdline,
+		COMMAND_LINE_SIZE);
+#elif defined(CONFIG_CMDLINE_FORCE)
+	pr_warning("Ignoring tag cmdline (using the default kernel command line)\n");
+#else
+	strlcpy(default_command_line, tag->u.cmdline.cmdline,
+		COMMAND_LINE_SIZE);
+#endif
+	return 0;
+}
+
+__tagtable(ATAG_CMDLINE, parse_tag_cmdline);
+
+/*
+ * Scan the tag table for this tag, and call its parse function.
+ * The tag table is built by the linker from all the __tagtable
+ * declarations.
+ */
+static int __init parse_tag(const struct tag *tag)
+{
+	extern struct tagtable __tagtable_begin, __tagtable_end;
+	struct tagtable *t;
+
+	for (t = &__tagtable_begin; t < &__tagtable_end; t++)
+		if (tag->hdr.tag == t->tag) {
+			t->parse(tag);
+			break;
+		}
+
+	return t < &__tagtable_end;
+}
+
+/*
+ * Parse all tags in the list, checking both the global and architecture
+ * specific tag tables.
+ */
+static void __init parse_tags(const struct tag *t)
+{
+	for (; t->hdr.size; t = tag_next(t))
+		if (!parse_tag(t))
+			printk(KERN_WARNING
+				"Ignoring unrecognised tag 0x%08x\n",
+				t->hdr.tag);
+}
+
+static void __init squash_mem_tags(struct tag *tag)
+{
+	for (; tag->hdr.size; tag = tag_next(tag))
+		if (tag->hdr.tag == ATAG_MEM)
+			tag->hdr.tag = ATAG_NONE;
+}
+
+struct machine_desc * __init setup_machine_tags(phys_addr_t __atags_pointer,
+						unsigned int machine_nr)
+{
+	struct tag *tags = (struct tag *)&default_tags;
+	struct machine_desc *mdesc = NULL, *p;
+	char *from = default_command_line;
+
+	default_tags.mem.start = PHYS_OFFSET;
+
+	/*
+	 * locate machine in the list of supported machines.
+	 */
+	for_each_machine_desc(p)
+		if (machine_nr == p->nr) {
+			printk("Machine: %s\n", p->name);
+			mdesc = p;
+			break;
+		}
+
+	if (!mdesc) {
+		early_print("\nError: unrecognized/unsupported machine ID"
+			    " (r1 = 0x%08x).\n\n", machine_nr);
+		dump_machine_table(); /* does not return */
+	}
+
+	if (__atags_pointer)
+		tags = phys_to_virt(__atags_pointer);
+	else if (mdesc->atag_offset)
+		tags = (void *)(PAGE_OFFSET + mdesc->atag_offset);
+
+#if defined(CONFIG_DEPRECATED_PARAM_STRUCT)
+	/*
+	 * If we have the old style parameters, convert them to
+	 * a tag list.
+	 */
+	if (tags->hdr.tag != ATAG_CORE)
+		convert_to_tag_list(tags);
+#endif
+	if (tags->hdr.tag != ATAG_CORE) {
+		early_print("Warning: Neither atags nor dtb found\n");
+		tags = (struct tag *)&default_tags;
+	}
+
+	if (mdesc->fixup)
+		mdesc->fixup(tags, &from, &meminfo);
+
+	if (tags->hdr.tag == ATAG_CORE) {
+		if (meminfo.nr_banks != 0)
+			squash_mem_tags(tags);
+		save_atags(tags);
+		parse_tags(tags);
+	}
+
+	/* parse_early_param needs a boot_command_line */
+	strlcpy(boot_command_line, from, COMMAND_LINE_SIZE);
+
+	return mdesc;
+}
diff --git a/arch/arm/kernel/atags_proc.c b/arch/arm/kernel/atags_proc.c
new file mode 100644
index 0000000..42a1a14
--- /dev/null
+++ b/arch/arm/kernel/atags_proc.c
@@ -0,0 +1,83 @@
+#include <linux/slab.h>
+#include <linux/proc_fs.h>
+#include <asm/setup.h>
+#include <asm/types.h>
+#include <asm/page.h>
+
+struct buffer {
+	size_t size;
+	char data[];
+};
+
+static int
+read_buffer(char* page, char** start, off_t off, int count,
+	int* eof, void* data)
+{
+	struct buffer *buffer = (struct buffer *)data;
+
+	if (off >= buffer->size) {
+		*eof = 1;
+		return 0;
+	}
+
+	count = min((int) (buffer->size - off), count);
+
+	memcpy(page, &buffer->data[off], count);
+
+	return count;
+}
+
+#define BOOT_PARAMS_SIZE 1536
+static char __initdata atags_copy[BOOT_PARAMS_SIZE];
+
+void __init save_atags(const struct tag *tags)
+{
+	memcpy(atags_copy, tags, sizeof(atags_copy));
+}
+
+static int __init init_atags_procfs(void)
+{
+	/*
+	 * This cannot go into save_atags() because kmalloc and proc don't work
+	 * yet when it is called.
+	 */
+	struct proc_dir_entry *tags_entry;
+	struct tag *tag = (struct tag *)atags_copy;
+	struct buffer *b;
+	size_t size;
+
+	if (tag->hdr.tag != ATAG_CORE) {
+		printk(KERN_INFO "No ATAGs?");
+		return -EINVAL;
+	}
+
+	for (; tag->hdr.size; tag = tag_next(tag))
+		;
+
+	/* include the terminating ATAG_NONE */
+	size = (char *)tag - atags_copy + sizeof(struct tag_header);
+
+	WARN_ON(tag->hdr.tag != ATAG_NONE);
+
+	b = kmalloc(sizeof(*b) + size, GFP_KERNEL);
+	if (!b)
+		goto nomem;
+
+	b->size = size;
+	memcpy(b->data, atags_copy, size);
+
+	tags_entry = create_proc_read_entry("atags", 0400,
+			NULL, read_buffer, b);
+
+	if (!tags_entry)
+		goto nomem;
+
+	return 0;
+
+nomem:
+	kfree(b);
+	printk(KERN_ERR "Exporting ATAGs: not enough memory\n");
+
+	return -ENOMEM;
+}
+arch_initcall(init_atags_procfs);
diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c
index 2b2f25e..9b72261 100644
--- a/arch/arm/kernel/bios32.c
+++ b/arch/arm/kernel/bios32.c
@@ -13,6 +13,7 @@
 #include <linux/io.h>
 
 #include <asm/mach-types.h>
+#include <asm/mach/map.h>
 #include <asm/mach/pci.h>
 
 static int debug_pci;
@@ -270,15 +271,6 @@ static void __devinit pci_fixup_it8152(struct pci_dev *dev)
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ITE, PCI_DEVICE_ID_ITE_8152, pci_fixup_it8152);
 
-
-
-void __devinit pcibios_update_irq(struct pci_dev *dev, int irq)
-{
-	if (debug_pci)
-		printk("PCI: Assigning IRQ %02d to %s\n", irq, pci_name(dev));
-	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
-}
-
 /*
  * If the bus contains any of these devices, then we must not turn on
  * parity checking of any kind.  Currently this is CyberPro 20x0 only.
@@ -423,6 +415,38 @@ static int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 	return irq;
 }
 
+static int __init pcibios_init_resources(int busnr, struct pci_sys_data *sys)
+{
+	int ret;
+	struct pci_host_bridge_window *window;
+
+	if (list_empty(&sys->resources)) {
+		pci_add_resource_offset(&sys->resources,
+			 &iomem_resource, sys->mem_offset);
+	}
+
+	list_for_each_entry(window, &sys->resources, list) {
+		if (resource_type(window->res) == IORESOURCE_IO)
+			return 0;
+	}
+
+	sys->io_res.start = (busnr * SZ_64K) ?  : pcibios_min_io;
+	sys->io_res.end = (busnr + 1) * SZ_64K - 1;
+	sys->io_res.flags = IORESOURCE_IO;
+	sys->io_res.name = sys->io_res_name;
+	sprintf(sys->io_res_name, "PCI%d I/O", busnr);
+
+	ret = request_resource(&ioport_resource, &sys->io_res);
+	if (ret) {
+		pr_err("PCI: unable to allocate I/O port region (%d)\n", ret);
+		return ret;
+	}
+	pci_add_resource_offset(&sys->resources, &sys->io_res,
+				sys->io_offset);
+
+	return 0;
+}
+
 static void __init pcibios_init_hw(struct hw_pci *hw, struct list_head *head)
 {
 	struct pci_sys_data *sys = NULL;
@@ -445,11 +469,10 @@ static void __init pcibios_init_hw(struct hw_pci *hw, struct list_head *head)
 		ret = hw->setup(nr, sys);
 
 		if (ret > 0) {
-			if (list_empty(&sys->resources)) {
-				pci_add_resource_offset(&sys->resources,
-					 &ioport_resource, sys->io_offset);
-				pci_add_resource_offset(&sys->resources,
-					 &iomem_resource, sys->mem_offset);
+			ret = pcibios_init_resources(nr, sys);
+			if (ret)  {
+				kfree(sys);
+				break;
 			}
 
 			if (hw->scan)
@@ -627,3 +650,15 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
 
 	return 0;
 }
+
+void __init pci_map_io_early(unsigned long pfn)
+{
+	struct map_desc pci_io_desc = {
+		.virtual	= PCI_IO_VIRT_BASE,
+		.type		= MT_DEVICE,
+		.length		= SZ_64K,
+	};
+
+	pci_io_desc.pfn = pfn;
+	iotable_init(&pci_io_desc, 1);
+}
diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S
index e337879..831cd38 100644
--- a/arch/arm/kernel/calls.S
+++ b/arch/arm/kernel/calls.S
@@ -20,7 +20,7 @@
 		CALL(sys_creat)
 		CALL(sys_link)
 /* 10 */	CALL(sys_unlink)
-		CALL(sys_execve_wrapper)
+		CALL(sys_execve)
 		CALL(sys_chdir)
 		CALL(OBSOLETE(sys_time))	/* used by libc4 */
 		CALL(sys_mknod)
diff --git a/arch/arm/kernel/compat.c b/arch/arm/kernel/compat.c
deleted file mode 100644
index 9256523..0000000
--- a/arch/arm/kernel/compat.c
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- *  linux/arch/arm/kernel/compat.c
- *
- *  Copyright (C) 2001 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * We keep the old params compatibility cruft in one place (here)
- * so we don't end up with lots of mess around other places.
- *
- * NOTE:
- *  The old struct param_struct is deprecated, but it will be kept in
- *  the kernel for 5 years from now (2001). This will allow boot loaders
- *  to convert to the new struct tag way.
- */
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/init.h>
-
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/page.h>
-
-#include <asm/mach/arch.h>
-
-#include "compat.h"
-
-/*
- * Usage:
- *  - do not go blindly adding fields, add them at the end
- *  - when adding fields, don't rely on the address until
- *    a patch from me has been released
- *  - unused fields should be zero (for future expansion)
- *  - this structure is relatively short-lived - only
- *    guaranteed to contain useful data in setup_arch()
- *
- * This is the old deprecated way to pass parameters to the kernel
- */
-struct param_struct {
-    union {
-	struct {
-	    unsigned long page_size;		/*  0 */
-	    unsigned long nr_pages;		/*  4 */
-	    unsigned long ramdisk_size;		/*  8 */
-	    unsigned long flags;		/* 12 */
-#define FLAG_READONLY	1
-#define FLAG_RDLOAD	4
-#define FLAG_RDPROMPT	8
-	    unsigned long rootdev;		/* 16 */
-	    unsigned long video_num_cols;	/* 20 */
-	    unsigned long video_num_rows;	/* 24 */
-	    unsigned long video_x;		/* 28 */
-	    unsigned long video_y;		/* 32 */
-	    unsigned long memc_control_reg;	/* 36 */
-	    unsigned char sounddefault;		/* 40 */
-	    unsigned char adfsdrives;		/* 41 */
-	    unsigned char bytes_per_char_h;	/* 42 */
-	    unsigned char bytes_per_char_v;	/* 43 */
-	    unsigned long pages_in_bank[4];	/* 44 */
-	    unsigned long pages_in_vram;	/* 60 */
-	    unsigned long initrd_start;		/* 64 */
-	    unsigned long initrd_size;		/* 68 */
-	    unsigned long rd_start;		/* 72 */
-	    unsigned long system_rev;		/* 76 */
-	    unsigned long system_serial_low;	/* 80 */
-	    unsigned long system_serial_high;	/* 84 */
-	    unsigned long mem_fclk_21285;       /* 88 */
-	} s;
-	char unused[256];
-    } u1;
-    union {
-	char paths[8][128];
-	struct {
-	    unsigned long magic;
-	    char n[1024 - sizeof(unsigned long)];
-	} s;
-    } u2;
-    char commandline[COMMAND_LINE_SIZE];
-};
-
-static struct tag * __init memtag(struct tag *tag, unsigned long start, unsigned long size)
-{
-	tag = tag_next(tag);
-	tag->hdr.tag = ATAG_MEM;
-	tag->hdr.size = tag_size(tag_mem32);
-	tag->u.mem.size = size;
-	tag->u.mem.start = start;
-
-	return tag;
-}
-
-static void __init build_tag_list(struct param_struct *params, void *taglist)
-{
-	struct tag *tag = taglist;
-
-	if (params->u1.s.page_size != PAGE_SIZE) {
-		printk(KERN_WARNING "Warning: bad configuration page, "
-		       "trying to continue\n");
-		return;
-	}
-
-	printk(KERN_DEBUG "Converting old-style param struct to taglist\n");
-
-#ifdef CONFIG_ARCH_NETWINDER
-	if (params->u1.s.nr_pages != 0x02000 &&
-	    params->u1.s.nr_pages != 0x04000 &&
-	    params->u1.s.nr_pages != 0x08000 &&
-	    params->u1.s.nr_pages != 0x10000) {
-		printk(KERN_WARNING "Warning: bad NeTTrom parameters "
-		       "detected, using defaults\n");
-
-		params->u1.s.nr_pages = 0x1000;	/* 16MB */
-		params->u1.s.ramdisk_size = 0;
-		params->u1.s.flags = FLAG_READONLY;
-		params->u1.s.initrd_start = 0;
-		params->u1.s.initrd_size = 0;
-		params->u1.s.rd_start = 0;
-	}
-#endif
-
-	tag->hdr.tag  = ATAG_CORE;
-	tag->hdr.size = tag_size(tag_core);
-	tag->u.core.flags = params->u1.s.flags & FLAG_READONLY;
-	tag->u.core.pagesize = params->u1.s.page_size;
-	tag->u.core.rootdev = params->u1.s.rootdev;
-
-	tag = tag_next(tag);
-	tag->hdr.tag = ATAG_RAMDISK;
-	tag->hdr.size = tag_size(tag_ramdisk);
-	tag->u.ramdisk.flags = (params->u1.s.flags & FLAG_RDLOAD ? 1 : 0) |
-			       (params->u1.s.flags & FLAG_RDPROMPT ? 2 : 0);
-	tag->u.ramdisk.size  = params->u1.s.ramdisk_size;
-	tag->u.ramdisk.start = params->u1.s.rd_start;
-
-	tag = tag_next(tag);
-	tag->hdr.tag = ATAG_INITRD;
-	tag->hdr.size = tag_size(tag_initrd);
-	tag->u.initrd.start = params->u1.s.initrd_start;
-	tag->u.initrd.size  = params->u1.s.initrd_size;
-
-	tag = tag_next(tag);
-	tag->hdr.tag = ATAG_SERIAL;
-	tag->hdr.size = tag_size(tag_serialnr);
-	tag->u.serialnr.low = params->u1.s.system_serial_low;
-	tag->u.serialnr.high = params->u1.s.system_serial_high;
-
-	tag = tag_next(tag);
-	tag->hdr.tag = ATAG_REVISION;
-	tag->hdr.size = tag_size(tag_revision);
-	tag->u.revision.rev = params->u1.s.system_rev;
-
-#ifdef CONFIG_ARCH_ACORN
-	if (machine_is_riscpc()) {
-		int i;
-		for (i = 0; i < 4; i++)
-			tag = memtag(tag, PHYS_OFFSET + (i << 26),
-				 params->u1.s.pages_in_bank[i] * PAGE_SIZE);
-	} else
-#endif
-	tag = memtag(tag, PHYS_OFFSET, params->u1.s.nr_pages * PAGE_SIZE);
-
-#ifdef CONFIG_FOOTBRIDGE
-	if (params->u1.s.mem_fclk_21285) {
-		tag = tag_next(tag);
-		tag->hdr.tag = ATAG_MEMCLK;
-		tag->hdr.size = tag_size(tag_memclk);
-		tag->u.memclk.fmemclk = params->u1.s.mem_fclk_21285;
-	}
-#endif
-
-#ifdef CONFIG_ARCH_EBSA285
-	if (machine_is_ebsa285()) {
-		tag = tag_next(tag);
-		tag->hdr.tag = ATAG_VIDEOTEXT;
-		tag->hdr.size = tag_size(tag_videotext);
-		tag->u.videotext.x            = params->u1.s.video_x;
-		tag->u.videotext.y            = params->u1.s.video_y;
-		tag->u.videotext.video_page   = 0;
-		tag->u.videotext.video_mode   = 0;
-		tag->u.videotext.video_cols   = params->u1.s.video_num_cols;
-		tag->u.videotext.video_ega_bx = 0;
-		tag->u.videotext.video_lines  = params->u1.s.video_num_rows;
-		tag->u.videotext.video_isvga  = 1;
-		tag->u.videotext.video_points = 8;
-	}
-#endif
-
-#ifdef CONFIG_ARCH_ACORN
-	tag = tag_next(tag);
-	tag->hdr.tag = ATAG_ACORN;
-	tag->hdr.size = tag_size(tag_acorn);
-	tag->u.acorn.memc_control_reg = params->u1.s.memc_control_reg;
-	tag->u.acorn.vram_pages       = params->u1.s.pages_in_vram;
-	tag->u.acorn.sounddefault     = params->u1.s.sounddefault;
-	tag->u.acorn.adfsdrives       = params->u1.s.adfsdrives;
-#endif
-
-	tag = tag_next(tag);
-	tag->hdr.tag = ATAG_CMDLINE;
-	tag->hdr.size = (strlen(params->commandline) + 3 +
-			 sizeof(struct tag_header)) >> 2;
-	strcpy(tag->u.cmdline.cmdline, params->commandline);
-
-	tag = tag_next(tag);
-	tag->hdr.tag = ATAG_NONE;
-	tag->hdr.size = 0;
-
-	memmove(params, taglist, ((int)tag) - ((int)taglist) +
-				 sizeof(struct tag_header));
-}
-
-void __init convert_to_tag_list(struct tag *tags)
-{
-	struct param_struct *params = (struct param_struct *)tags;
-	build_tag_list(params, &params->u2);
-}
diff --git a/arch/arm/kernel/compat.h b/arch/arm/kernel/compat.h
deleted file mode 100644
index 39264ab..0000000
--- a/arch/arm/kernel/compat.h
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- *  linux/arch/arm/kernel/compat.h
- *
- *  Copyright (C) 2001 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-extern void convert_to_tag_list(struct tag *tags);
diff --git a/arch/arm/kernel/debug.S b/arch/arm/kernel/debug.S
index c45522c..66f711b 100644
--- a/arch/arm/kernel/debug.S
+++ b/arch/arm/kernel/debug.S
@@ -20,90 +20,9 @@
  * references to these in a production kernel!
  */
 
-#if defined(CONFIG_DEBUG_ICEDCC)
-		@@ debug using ARM EmbeddedICE DCC channel
-
-		.macro	addruart, rp, rv, tmp
-		.endm
-
-#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K) || defined(CONFIG_CPU_V7)
-
-		.macro	senduart, rd, rx
-		mcr	p14, 0, \rd, c0, c5, 0
-		.endm
-
-		.macro	busyuart, rd, rx
-1001:
-		mrc	p14, 0, \rx, c0, c1, 0
-		tst	\rx, #0x20000000
-		beq	1001b
-		.endm
-
-		.macro	waituart, rd, rx
-		mov	\rd, #0x2000000
-1001:
-		subs	\rd, \rd, #1
-		bmi	1002f
-		mrc	p14, 0, \rx, c0, c1, 0
-		tst	\rx, #0x20000000
-		bne	1001b
-1002:
-		.endm
-
-#elif defined(CONFIG_CPU_XSCALE)
-
-		.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	senduart, rd, rx
-		mcr	p14, 0, \rd, c1, c0, 0
-		.endm
-
-		.macro	busyuart, rd, rx
-1001:
-		mrc	p14, 0, \rx, c0, c0, 0
-		tst	\rx, #2
-		beq	1001b
-
-		.endm
-
-		.macro	waituart, rd, rx
-		mov	\rd, #0x2000000
-1001:
-		subs	\rd, \rd, #1
-		bmi	1002f
-		mrc	p14, 0, \rx, c0, c0, 0
-		tst	\rx, #2
-		bne	1001b
-1002:
-		.endm
-
-#endif	/* CONFIG_CPU_V6 */
-
-#elif !defined(CONFIG_DEBUG_SEMIHOSTING)
-#include <mach/debug-macro.S>
-#endif	/* CONFIG_DEBUG_ICEDCC */
+#if !defined(CONFIG_DEBUG_SEMIHOSTING)
+#include CONFIG_DEBUG_LL_INCLUDE
+#endif
 
 #ifdef CONFIG_MMU
 		.macro	addruart_current, rx, tmp1, tmp2
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index 978eac5..e340fa1 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -91,9 +91,42 @@ ENTRY(ret_from_fork)
 	b	ret_slow_syscall
 ENDPROC(ret_from_fork)
 
+ENTRY(ret_from_kernel_thread)
+ UNWIND(.fnstart)
+ UNWIND(.cantunwind)
+	bl	schedule_tail
+	mov	r0, r4
+	adr	lr, BSYM(1f)	@ kernel threads should not exit
+	mov	pc, r5
+1:	bl	do_exit
+	nop
+ UNWIND(.fnend)
+ENDPROC(ret_from_kernel_thread)
+
+/*
+ * turn a kernel thread into userland process
+ * use: ret_from_kernel_execve(struct pt_regs *normal)
+ */
+ENTRY(ret_from_kernel_execve)
+	mov	why, #0			@ not a syscall
+	str	why, [r0, #S_R0]	@ ... and we want 0 in ->ARM_r0 as well
+	get_thread_info tsk		@ thread structure
+	mov	sp, r0			@ stack pointer just under pt_regs
+	b	ret_slow_syscall
+ENDPROC(ret_from_kernel_execve)
+
 	.equ NR_syscalls,0
 #define CALL(x) .equ NR_syscalls,NR_syscalls+1
 #include "calls.S"
+
+/*
+ * Ensure that the system call table is equal to __NR_syscalls,
+ * which is the value the rest of the system sees
+ */
+.ifne NR_syscalls - __NR_syscalls
+.error "__NR_syscalls is not equal to the size of the syscall table"
+.endif
+
 #undef CALL
 #define CALL(x) .long x
 
@@ -508,11 +541,6 @@ sys_vfork_wrapper:
 		b	sys_vfork
 ENDPROC(sys_vfork_wrapper)
 
-sys_execve_wrapper:
-		add	r3, sp, #S_OFF
-		b	sys_execve
-ENDPROC(sys_execve_wrapper)
-
 sys_clone_wrapper:
 		add	ip, sp, #S_OFF
 		str	ip, [sp, #4]
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index 3db960e..9874d07 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -23,8 +23,8 @@
 #include <asm/thread_info.h>
 #include <asm/pgtable.h>
 
-#ifdef CONFIG_DEBUG_LL
-#include <mach/debug-macro.S>
+#if defined(CONFIG_DEBUG_LL) && !defined(CONFIG_DEBUG_SEMIHOSTING)
+#include CONFIG_DEBUG_LL_INCLUDE
 #endif
 
 /*
diff --git a/arch/arm/kernel/leds.c b/arch/arm/kernel/leds.c
deleted file mode 100644
index 1911dae..0000000
--- a/arch/arm/kernel/leds.c
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * LED support code, ripped out of arch/arm/kernel/time.c
- *
- *  Copyright (C) 1994-2001 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <linux/export.h>
-#include <linux/init.h>
-#include <linux/device.h>
-#include <linux/syscore_ops.h>
-#include <linux/string.h>
-
-#include <asm/leds.h>
-
-static void dummy_leds_event(led_event_t evt)
-{
-}
-
-void (*leds_event)(led_event_t) = dummy_leds_event;
-
-struct leds_evt_name {
-	const char	name[8];
-	int		on;
-	int		off;
-};
-
-static const struct leds_evt_name evt_names[] = {
-	{ "amber", led_amber_on, led_amber_off },
-	{ "blue",  led_blue_on,  led_blue_off  },
-	{ "green", led_green_on, led_green_off },
-	{ "red",   led_red_on,   led_red_off   },
-};
-
-static ssize_t leds_store(struct device *dev,
-			struct device_attribute *attr,
-			const char *buf, size_t size)
-{
-	int ret = -EINVAL, len = strcspn(buf, " ");
-
-	if (len > 0 && buf[len] == '\0')
-		len--;
-
-	if (strncmp(buf, "claim", len) == 0) {
-		leds_event(led_claim);
-		ret = size;
-	} else if (strncmp(buf, "release", len) == 0) {
-		leds_event(led_release);
-		ret = size;
-	} else {
-		int i;
-
-		for (i = 0; i < ARRAY_SIZE(evt_names); i++) {
-			if (strlen(evt_names[i].name) != len ||
-			    strncmp(buf, evt_names[i].name, len) != 0)
-				continue;
-			if (strncmp(buf+len, " on", 3) == 0) {
-				leds_event(evt_names[i].on);
-				ret = size;
-			} else if (strncmp(buf+len, " off", 4) == 0) {
-				leds_event(evt_names[i].off);
-				ret = size;
-			}
-			break;
-		}
-	}
-	return ret;
-}
-
-static DEVICE_ATTR(event, 0200, NULL, leds_store);
-
-static struct bus_type leds_subsys = {
-	.name		= "leds",
-	.dev_name	= "leds",
-};
-
-static struct device leds_device = {
-	.id		= 0,
-	.bus		= &leds_subsys,
-};
-
-static int leds_suspend(void)
-{
-	leds_event(led_stop);
-	return 0;
-}
-
-static void leds_resume(void)
-{
-	leds_event(led_start);
-}
-
-static void leds_shutdown(void)
-{
-	leds_event(led_halted);
-}
-
-static struct syscore_ops leds_syscore_ops = {
-	.shutdown	= leds_shutdown,
-	.suspend	= leds_suspend,
-	.resume		= leds_resume,
-};
-
-static int __init leds_init(void)
-{
-	int ret;
-	ret = subsys_system_register(&leds_subsys, NULL);
-	if (ret == 0)
-		ret = device_register(&leds_device);
-	if (ret == 0)
-		ret = device_create_file(&leds_device, &dev_attr_event);
-	if (ret == 0)
-		register_syscore_ops(&leds_syscore_ops);
-	return ret;
-}
-
-device_initcall(leds_init);
-
-EXPORT_SYMBOL(leds_event);
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
index ab243b8..93971b1 100644
--- a/arch/arm/kernel/perf_event.c
+++ b/arch/arm/kernel/perf_event.c
@@ -12,68 +12,15 @@
  */
 #define pr_fmt(fmt) "hw perfevents: " fmt
 
-#include <linux/bitmap.h>
-#include <linux/interrupt.h>
 #include <linux/kernel.h>
-#include <linux/export.h>
-#include <linux/perf_event.h>
 #include <linux/platform_device.h>
-#include <linux/spinlock.h>
+#include <linux/pm_runtime.h>
 #include <linux/uaccess.h>
 
-#include <asm/cputype.h>
-#include <asm/irq.h>
 #include <asm/irq_regs.h>
 #include <asm/pmu.h>
 #include <asm/stacktrace.h>
 
-/*
- * ARMv6 supports a maximum of 3 events, starting from index 0. If we add
- * another platform that supports more, we need to increase this to be the
- * largest of all platforms.
- *
- * ARMv7 supports up to 32 events:
- *  cycle counter CCNT + 31 events counters CNT0..30.
- *  Cortex-A8 has 1+4 counters, Cortex-A9 has 1+6 counters.
- */
-#define ARMPMU_MAX_HWEVENTS		32
-
-static DEFINE_PER_CPU(struct perf_event * [ARMPMU_MAX_HWEVENTS], hw_events);
-static DEFINE_PER_CPU(unsigned long [BITS_TO_LONGS(ARMPMU_MAX_HWEVENTS)], used_mask);
-static DEFINE_PER_CPU(struct pmu_hw_events, cpu_hw_events);
-
-#define to_arm_pmu(p) (container_of(p, struct arm_pmu, pmu))
-
-/* Set at runtime when we know what CPU type we are. */
-static struct arm_pmu *cpu_pmu;
-
-const char *perf_pmu_name(void)
-{
-	if (!cpu_pmu)
-		return NULL;
-
-	return cpu_pmu->pmu.name;
-}
-EXPORT_SYMBOL_GPL(perf_pmu_name);
-
-int perf_num_counters(void)
-{
-	int max_events = 0;
-
-	if (cpu_pmu != NULL)
-		max_events = cpu_pmu->num_events;
-
-	return max_events;
-}
-EXPORT_SYMBOL_GPL(perf_num_counters);
-
-#define HW_OP_UNSUPPORTED		0xFFFF
-
-#define C(_x) \
-	PERF_COUNT_HW_CACHE_##_x
-
-#define CACHE_OP_UNSUPPORTED		0xFFFF
-
 static int
 armpmu_map_cache_event(const unsigned (*cache_map)
 				      [PERF_COUNT_HW_CACHE_MAX]
@@ -104,7 +51,7 @@ armpmu_map_cache_event(const unsigned (*cache_map)
 }
 
 static int
-armpmu_map_event(const unsigned (*event_map)[PERF_COUNT_HW_MAX], u64 config)
+armpmu_map_hw_event(const unsigned (*event_map)[PERF_COUNT_HW_MAX], u64 config)
 {
 	int mapping = (*event_map)[config];
 	return mapping == HW_OP_UNSUPPORTED ? -ENOENT : mapping;
@@ -116,19 +63,20 @@ armpmu_map_raw_event(u32 raw_event_mask, u64 config)
 	return (int)(config & raw_event_mask);
 }
 
-static int map_cpu_event(struct perf_event *event,
-			 const unsigned (*event_map)[PERF_COUNT_HW_MAX],
-			 const unsigned (*cache_map)
-					[PERF_COUNT_HW_CACHE_MAX]
-					[PERF_COUNT_HW_CACHE_OP_MAX]
-					[PERF_COUNT_HW_CACHE_RESULT_MAX],
-			 u32 raw_event_mask)
+int
+armpmu_map_event(struct perf_event *event,
+		 const unsigned (*event_map)[PERF_COUNT_HW_MAX],
+		 const unsigned (*cache_map)
+				[PERF_COUNT_HW_CACHE_MAX]
+				[PERF_COUNT_HW_CACHE_OP_MAX]
+				[PERF_COUNT_HW_CACHE_RESULT_MAX],
+		 u32 raw_event_mask)
 {
 	u64 config = event->attr.config;
 
 	switch (event->attr.type) {
 	case PERF_TYPE_HARDWARE:
-		return armpmu_map_event(event_map, config);
+		return armpmu_map_hw_event(event_map, config);
 	case PERF_TYPE_HW_CACHE:
 		return armpmu_map_cache_event(cache_map, config);
 	case PERF_TYPE_RAW:
@@ -222,7 +170,6 @@ armpmu_stop(struct perf_event *event, int flags)
 	 */
 	if (!(hwc->state & PERF_HES_STOPPED)) {
 		armpmu->disable(hwc, hwc->idx);
-		barrier(); /* why? */
 		armpmu_event_update(event, hwc, hwc->idx);
 		hwc->state |= PERF_HES_STOPPED | PERF_HES_UPTODATE;
 	}
@@ -350,99 +297,41 @@ validate_group(struct perf_event *event)
 	return 0;
 }
 
-static irqreturn_t armpmu_platform_irq(int irq, void *dev)
+static irqreturn_t armpmu_dispatch_irq(int irq, void *dev)
 {
 	struct arm_pmu *armpmu = (struct arm_pmu *) dev;
 	struct platform_device *plat_device = armpmu->plat_device;
 	struct arm_pmu_platdata *plat = dev_get_platdata(&plat_device->dev);
 
-	return plat->handle_irq(irq, dev, armpmu->handle_irq);
+	if (plat && plat->handle_irq)
+		return plat->handle_irq(irq, dev, armpmu->handle_irq);
+	else
+		return armpmu->handle_irq(irq, dev);
 }
 
 static void
 armpmu_release_hardware(struct arm_pmu *armpmu)
 {
-	int i, irq, irqs;
-	struct platform_device *pmu_device = armpmu->plat_device;
-	struct arm_pmu_platdata *plat =
-		dev_get_platdata(&pmu_device->dev);
-
-	irqs = min(pmu_device->num_resources, num_possible_cpus());
-
-	for (i = 0; i < irqs; ++i) {
-		if (!cpumask_test_and_clear_cpu(i, &armpmu->active_irqs))
-			continue;
-		irq = platform_get_irq(pmu_device, i);
-		if (irq >= 0) {
-			if (plat && plat->disable_irq)
-				plat->disable_irq(irq);
-			free_irq(irq, armpmu);
-		}
-	}
-
-	release_pmu(armpmu->type);
+	armpmu->free_irq();
+	pm_runtime_put_sync(&armpmu->plat_device->dev);
 }
 
 static int
 armpmu_reserve_hardware(struct arm_pmu *armpmu)
 {
-	struct arm_pmu_platdata *plat;
-	irq_handler_t handle_irq;
-	int i, err, irq, irqs;
+	int err;
 	struct platform_device *pmu_device = armpmu->plat_device;
 
 	if (!pmu_device)
 		return -ENODEV;
 
-	err = reserve_pmu(armpmu->type);
+	pm_runtime_get_sync(&pmu_device->dev);
+	err = armpmu->request_irq(armpmu_dispatch_irq);
 	if (err) {
-		pr_warning("unable to reserve pmu\n");
+		armpmu_release_hardware(armpmu);
 		return err;
 	}
 
-	plat = dev_get_platdata(&pmu_device->dev);
-	if (plat && plat->handle_irq)
-		handle_irq = armpmu_platform_irq;
-	else
-		handle_irq = armpmu->handle_irq;
-
-	irqs = min(pmu_device->num_resources, num_possible_cpus());
-	if (irqs < 1) {
-		pr_err("no irqs for PMUs defined\n");
-		return -ENODEV;
-	}
-
-	for (i = 0; i < irqs; ++i) {
-		err = 0;
-		irq = platform_get_irq(pmu_device, i);
-		if (irq < 0)
-			continue;
-
-		/*
-		 * If we have a single PMU interrupt that we can't shift,
-		 * assume that we're running on a uniprocessor machine and
-		 * continue. Otherwise, continue without this interrupt.
-		 */
-		if (irq_set_affinity(irq, cpumask_of(i)) && irqs > 1) {
-			pr_warning("unable to set irq affinity (irq=%d, cpu=%u)\n",
-				    irq, i);
-			continue;
-		}
-
-		err = request_irq(irq, handle_irq,
-				  IRQF_DISABLED | IRQF_NOBALANCING,
-				  "arm-pmu", armpmu);
-		if (err) {
-			pr_err("unable to request IRQ%d for ARM PMU counters\n",
-				irq);
-			armpmu_release_hardware(armpmu);
-			return err;
-		} else if (plat && plat->enable_irq)
-			plat->enable_irq(irq);
-
-		cpumask_set_cpu(i, &armpmu->active_irqs);
-	}
-
 	return 0;
 }
 
@@ -581,6 +470,32 @@ static void armpmu_disable(struct pmu *pmu)
 	armpmu->stop();
 }
 
+#ifdef CONFIG_PM_RUNTIME
+static int armpmu_runtime_resume(struct device *dev)
+{
+	struct arm_pmu_platdata *plat = dev_get_platdata(dev);
+
+	if (plat && plat->runtime_resume)
+		return plat->runtime_resume(dev);
+
+	return 0;
+}
+
+static int armpmu_runtime_suspend(struct device *dev)
+{
+	struct arm_pmu_platdata *plat = dev_get_platdata(dev);
+
+	if (plat && plat->runtime_suspend)
+		return plat->runtime_suspend(dev);
+
+	return 0;
+}
+#endif
+
+const struct dev_pm_ops armpmu_dev_pm_ops = {
+	SET_RUNTIME_PM_OPS(armpmu_runtime_suspend, armpmu_runtime_resume, NULL)
+};
+
 static void __init armpmu_init(struct arm_pmu *armpmu)
 {
 	atomic_set(&armpmu->active_events, 0);
@@ -598,174 +513,14 @@ static void __init armpmu_init(struct arm_pmu *armpmu)
 	};
 }
 
-int __init armpmu_register(struct arm_pmu *armpmu, char *name, int type)
+int armpmu_register(struct arm_pmu *armpmu, char *name, int type)
 {
 	armpmu_init(armpmu);
+	pr_info("enabled with %s PMU driver, %d counters available\n",
+			armpmu->name, armpmu->num_events);
 	return perf_pmu_register(&armpmu->pmu, name, type);
 }
 
-/* Include the PMU-specific implementations. */
-#include "perf_event_xscale.c"
-#include "perf_event_v6.c"
-#include "perf_event_v7.c"
-
-/*
- * Ensure the PMU has sane values out of reset.
- * This requires SMP to be available, so exists as a separate initcall.
- */
-static int __init
-cpu_pmu_reset(void)
-{
-	if (cpu_pmu && cpu_pmu->reset)
-		return on_each_cpu(cpu_pmu->reset, NULL, 1);
-	return 0;
-}
-arch_initcall(cpu_pmu_reset);
-
-/*
- * PMU platform driver and devicetree bindings.
- */
-static struct of_device_id armpmu_of_device_ids[] = {
-	{.compatible = "arm,cortex-a9-pmu"},
-	{.compatible = "arm,cortex-a8-pmu"},
-	{.compatible = "arm,arm1136-pmu"},
-	{.compatible = "arm,arm1176-pmu"},
-	{},
-};
-
-static struct platform_device_id armpmu_plat_device_ids[] = {
-	{.name = "arm-pmu"},
-	{},
-};
-
-static int __devinit armpmu_device_probe(struct platform_device *pdev)
-{
-	if (!cpu_pmu)
-		return -ENODEV;
-
-	cpu_pmu->plat_device = pdev;
-	return 0;
-}
-
-static struct platform_driver armpmu_driver = {
-	.driver		= {
-		.name	= "arm-pmu",
-		.of_match_table = armpmu_of_device_ids,
-	},
-	.probe		= armpmu_device_probe,
-	.id_table	= armpmu_plat_device_ids,
-};
-
-static int __init register_pmu_driver(void)
-{
-	return platform_driver_register(&armpmu_driver);
-}
-device_initcall(register_pmu_driver);
-
-static struct pmu_hw_events *armpmu_get_cpu_events(void)
-{
-	return &__get_cpu_var(cpu_hw_events);
-}
-
-static void __init cpu_pmu_init(struct arm_pmu *armpmu)
-{
-	int cpu;
-	for_each_possible_cpu(cpu) {
-		struct pmu_hw_events *events = &per_cpu(cpu_hw_events, cpu);
-		events->events = per_cpu(hw_events, cpu);
-		events->used_mask = per_cpu(used_mask, cpu);
-		raw_spin_lock_init(&events->pmu_lock);
-	}
-	armpmu->get_hw_events = armpmu_get_cpu_events;
-	armpmu->type = ARM_PMU_DEVICE_CPU;
-}
-
-/*
- * PMU hardware loses all context when a CPU goes offline.
- * When a CPU is hotplugged back in, since some hardware registers are
- * UNKNOWN at reset, the PMU must be explicitly reset to avoid reading
- * junk values out of them.
- */
-static int __cpuinit pmu_cpu_notify(struct notifier_block *b,
-					unsigned long action, void *hcpu)
-{
-	if ((action & ~CPU_TASKS_FROZEN) != CPU_STARTING)
-		return NOTIFY_DONE;
-
-	if (cpu_pmu && cpu_pmu->reset)
-		cpu_pmu->reset(NULL);
-
-	return NOTIFY_OK;
-}
-
-static struct notifier_block __cpuinitdata pmu_cpu_notifier = {
-	.notifier_call = pmu_cpu_notify,
-};
-
-/*
- * CPU PMU identification and registration.
- */
-static int __init
-init_hw_perf_events(void)
-{
-	unsigned long cpuid = read_cpuid_id();
-	unsigned long implementor = (cpuid & 0xFF000000) >> 24;
-	unsigned long part_number = (cpuid & 0xFFF0);
-
-	/* ARM Ltd CPUs. */
-	if (0x41 == implementor) {
-		switch (part_number) {
-		case 0xB360:	/* ARM1136 */
-		case 0xB560:	/* ARM1156 */
-		case 0xB760:	/* ARM1176 */
-			cpu_pmu = armv6pmu_init();
-			break;
-		case 0xB020:	/* ARM11mpcore */
-			cpu_pmu = armv6mpcore_pmu_init();
-			break;
-		case 0xC080:	/* Cortex-A8 */
-			cpu_pmu = armv7_a8_pmu_init();
-			break;
-		case 0xC090:	/* Cortex-A9 */
-			cpu_pmu = armv7_a9_pmu_init();
-			break;
-		case 0xC050:	/* Cortex-A5 */
-			cpu_pmu = armv7_a5_pmu_init();
-			break;
-		case 0xC0F0:	/* Cortex-A15 */
-			cpu_pmu = armv7_a15_pmu_init();
-			break;
-		case 0xC070:	/* Cortex-A7 */
-			cpu_pmu = armv7_a7_pmu_init();
-			break;
-		}
-	/* Intel CPUs [xscale]. */
-	} else if (0x69 == implementor) {
-		part_number = (cpuid >> 13) & 0x7;
-		switch (part_number) {
-		case 1:
-			cpu_pmu = xscale1pmu_init();
-			break;
-		case 2:
-			cpu_pmu = xscale2pmu_init();
-			break;
-		}
-	}
-
-	if (cpu_pmu) {
-		pr_info("enabled with %s PMU driver, %d counters available\n",
-			cpu_pmu->name, cpu_pmu->num_events);
-		cpu_pmu_init(cpu_pmu);
-		register_cpu_notifier(&pmu_cpu_notifier);
-		armpmu_register(cpu_pmu, cpu_pmu->name, PERF_TYPE_RAW);
-	} else {
-		pr_info("no hardware support available\n");
-	}
-
-	return 0;
-}
-early_initcall(init_hw_perf_events);
-
 /*
  * Callchain handling code.
  */
diff --git a/arch/arm/kernel/perf_event_cpu.c b/arch/arm/kernel/perf_event_cpu.c
new file mode 100644
index 0000000..8d7d8d4
--- /dev/null
+++ b/arch/arm/kernel/perf_event_cpu.c
@@ -0,0 +1,295 @@
+/*
+ * This program is free software; you can 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.
+ *
+ * Copyright (C) 2012 ARM Limited
+ *
+ * Author: Will Deacon <will.deacon@arm.com>
+ */
+#define pr_fmt(fmt) "CPU PMU: " fmt
+
+#include <linux/bitmap.h>
+#include <linux/export.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+
+#include <asm/cputype.h>
+#include <asm/irq_regs.h>
+#include <asm/pmu.h>
+
+/* Set at runtime when we know what CPU type we are. */
+static struct arm_pmu *cpu_pmu;
+
+static DEFINE_PER_CPU(struct perf_event * [ARMPMU_MAX_HWEVENTS], hw_events);
+static DEFINE_PER_CPU(unsigned long [BITS_TO_LONGS(ARMPMU_MAX_HWEVENTS)], used_mask);
+static DEFINE_PER_CPU(struct pmu_hw_events, cpu_hw_events);
+
+/*
+ * Despite the names, these two functions are CPU-specific and are used
+ * by the OProfile/perf code.
+ */
+const char *perf_pmu_name(void)
+{
+	if (!cpu_pmu)
+		return NULL;
+
+	return cpu_pmu->pmu.name;
+}
+EXPORT_SYMBOL_GPL(perf_pmu_name);
+
+int perf_num_counters(void)
+{
+	int max_events = 0;
+
+	if (cpu_pmu != NULL)
+		max_events = cpu_pmu->num_events;
+
+	return max_events;
+}
+EXPORT_SYMBOL_GPL(perf_num_counters);
+
+/* Include the PMU-specific implementations. */
+#include "perf_event_xscale.c"
+#include "perf_event_v6.c"
+#include "perf_event_v7.c"
+
+static struct pmu_hw_events *cpu_pmu_get_cpu_events(void)
+{
+	return &__get_cpu_var(cpu_hw_events);
+}
+
+static void cpu_pmu_free_irq(void)
+{
+	int i, irq, irqs;
+	struct platform_device *pmu_device = cpu_pmu->plat_device;
+
+	irqs = min(pmu_device->num_resources, num_possible_cpus());
+
+	for (i = 0; i < irqs; ++i) {
+		if (!cpumask_test_and_clear_cpu(i, &cpu_pmu->active_irqs))
+			continue;
+		irq = platform_get_irq(pmu_device, i);
+		if (irq >= 0)
+			free_irq(irq, cpu_pmu);
+	}
+}
+
+static int cpu_pmu_request_irq(irq_handler_t handler)
+{
+	int i, err, irq, irqs;
+	struct platform_device *pmu_device = cpu_pmu->plat_device;
+
+	if (!pmu_device)
+		return -ENODEV;
+
+	irqs = min(pmu_device->num_resources, num_possible_cpus());
+	if (irqs < 1) {
+		pr_err("no irqs for PMUs defined\n");
+		return -ENODEV;
+	}
+
+	for (i = 0; i < irqs; ++i) {
+		err = 0;
+		irq = platform_get_irq(pmu_device, i);
+		if (irq < 0)
+			continue;
+
+		/*
+		 * If we have a single PMU interrupt that we can't shift,
+		 * assume that we're running on a uniprocessor machine and
+		 * continue. Otherwise, continue without this interrupt.
+		 */
+		if (irq_set_affinity(irq, cpumask_of(i)) && irqs > 1) {
+			pr_warning("unable to set irq affinity (irq=%d, cpu=%u)\n",
+				    irq, i);
+			continue;
+		}
+
+		err = request_irq(irq, handler, IRQF_NOBALANCING, "arm-pmu",
+				  cpu_pmu);
+		if (err) {
+			pr_err("unable to request IRQ%d for ARM PMU counters\n",
+				irq);
+			return err;
+		}
+
+		cpumask_set_cpu(i, &cpu_pmu->active_irqs);
+	}
+
+	return 0;
+}
+
+static void __devinit cpu_pmu_init(struct arm_pmu *cpu_pmu)
+{
+	int cpu;
+	for_each_possible_cpu(cpu) {
+		struct pmu_hw_events *events = &per_cpu(cpu_hw_events, cpu);
+		events->events = per_cpu(hw_events, cpu);
+		events->used_mask = per_cpu(used_mask, cpu);
+		raw_spin_lock_init(&events->pmu_lock);
+	}
+
+	cpu_pmu->get_hw_events	= cpu_pmu_get_cpu_events;
+	cpu_pmu->request_irq	= cpu_pmu_request_irq;
+	cpu_pmu->free_irq	= cpu_pmu_free_irq;
+
+	/* Ensure the PMU has sane values out of reset. */
+	if (cpu_pmu && cpu_pmu->reset)
+		on_each_cpu(cpu_pmu->reset, NULL, 1);
+}
+
+/*
+ * PMU hardware loses all context when a CPU goes offline.
+ * When a CPU is hotplugged back in, since some hardware registers are
+ * UNKNOWN at reset, the PMU must be explicitly reset to avoid reading
+ * junk values out of them.
+ */
+static int __cpuinit cpu_pmu_notify(struct notifier_block *b,
+				    unsigned long action, void *hcpu)
+{
+	if ((action & ~CPU_TASKS_FROZEN) != CPU_STARTING)
+		return NOTIFY_DONE;
+
+	if (cpu_pmu && cpu_pmu->reset)
+		cpu_pmu->reset(NULL);
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block __cpuinitdata cpu_pmu_hotplug_notifier = {
+	.notifier_call = cpu_pmu_notify,
+};
+
+/*
+ * PMU platform driver and devicetree bindings.
+ */
+static struct of_device_id __devinitdata cpu_pmu_of_device_ids[] = {
+	{.compatible = "arm,cortex-a15-pmu",	.data = armv7_a15_pmu_init},
+	{.compatible = "arm,cortex-a9-pmu",	.data = armv7_a9_pmu_init},
+	{.compatible = "arm,cortex-a8-pmu",	.data = armv7_a8_pmu_init},
+	{.compatible = "arm,cortex-a7-pmu",	.data = armv7_a7_pmu_init},
+	{.compatible = "arm,cortex-a5-pmu",	.data = armv7_a5_pmu_init},
+	{.compatible = "arm,arm11mpcore-pmu",	.data = armv6mpcore_pmu_init},
+	{.compatible = "arm,arm1176-pmu",	.data = armv6pmu_init},
+	{.compatible = "arm,arm1136-pmu",	.data = armv6pmu_init},
+	{},
+};
+
+static struct platform_device_id __devinitdata cpu_pmu_plat_device_ids[] = {
+	{.name = "arm-pmu"},
+	{},
+};
+
+/*
+ * CPU PMU identification and probing.
+ */
+static struct arm_pmu *__devinit probe_current_pmu(void)
+{
+	struct arm_pmu *pmu = NULL;
+	int cpu = get_cpu();
+	unsigned long cpuid = read_cpuid_id();
+	unsigned long implementor = (cpuid & 0xFF000000) >> 24;
+	unsigned long part_number = (cpuid & 0xFFF0);
+
+	pr_info("probing PMU on CPU %d\n", cpu);
+
+	/* ARM Ltd CPUs. */
+	if (0x41 == implementor) {
+		switch (part_number) {
+		case 0xB360:	/* ARM1136 */
+		case 0xB560:	/* ARM1156 */
+		case 0xB760:	/* ARM1176 */
+			pmu = armv6pmu_init();
+			break;
+		case 0xB020:	/* ARM11mpcore */
+			pmu = armv6mpcore_pmu_init();
+			break;
+		case 0xC080:	/* Cortex-A8 */
+			pmu = armv7_a8_pmu_init();
+			break;
+		case 0xC090:	/* Cortex-A9 */
+			pmu = armv7_a9_pmu_init();
+			break;
+		case 0xC050:	/* Cortex-A5 */
+			pmu = armv7_a5_pmu_init();
+			break;
+		case 0xC0F0:	/* Cortex-A15 */
+			pmu = armv7_a15_pmu_init();
+			break;
+		case 0xC070:	/* Cortex-A7 */
+			pmu = armv7_a7_pmu_init();
+			break;
+		}
+	/* Intel CPUs [xscale]. */
+	} else if (0x69 == implementor) {
+		part_number = (cpuid >> 13) & 0x7;
+		switch (part_number) {
+		case 1:
+			pmu = xscale1pmu_init();
+			break;
+		case 2:
+			pmu = xscale2pmu_init();
+			break;
+		}
+	}
+
+	put_cpu();
+	return pmu;
+}
+
+static int __devinit cpu_pmu_device_probe(struct platform_device *pdev)
+{
+	const struct of_device_id *of_id;
+	struct arm_pmu *(*init_fn)(void);
+	struct device_node *node = pdev->dev.of_node;
+
+	if (cpu_pmu) {
+		pr_info("attempt to register multiple PMU devices!");
+		return -ENOSPC;
+	}
+
+	if (node && (of_id = of_match_node(cpu_pmu_of_device_ids, pdev->dev.of_node))) {
+		init_fn = of_id->data;
+		cpu_pmu = init_fn();
+	} else {
+		cpu_pmu = probe_current_pmu();
+	}
+
+	if (!cpu_pmu)
+		return -ENODEV;
+
+	cpu_pmu->plat_device = pdev;
+	cpu_pmu_init(cpu_pmu);
+	register_cpu_notifier(&cpu_pmu_hotplug_notifier);
+	armpmu_register(cpu_pmu, cpu_pmu->name, PERF_TYPE_RAW);
+
+	return 0;
+}
+
+static struct platform_driver cpu_pmu_driver = {
+	.driver		= {
+		.name	= "arm-pmu",
+		.pm	= &armpmu_dev_pm_ops,
+		.of_match_table = cpu_pmu_of_device_ids,
+	},
+	.probe		= cpu_pmu_device_probe,
+	.id_table	= cpu_pmu_plat_device_ids,
+};
+
+static int __init register_pmu_driver(void)
+{
+	return platform_driver_register(&cpu_pmu_driver);
+}
+device_initcall(register_pmu_driver);
diff --git a/arch/arm/kernel/perf_event_v6.c b/arch/arm/kernel/perf_event_v6.c
index c90fcb2..6ccc079 100644
--- a/arch/arm/kernel/perf_event_v6.c
+++ b/arch/arm/kernel/perf_event_v6.c
@@ -645,7 +645,7 @@ armv6mpcore_pmu_disable_event(struct hw_perf_event *hwc,
 
 static int armv6_map_event(struct perf_event *event)
 {
-	return map_cpu_event(event, &armv6_perf_map,
+	return armpmu_map_event(event, &armv6_perf_map,
 				&armv6_perf_cache_map, 0xFF);
 }
 
@@ -664,7 +664,7 @@ static struct arm_pmu armv6pmu = {
 	.max_period		= (1LLU << 32) - 1,
 };
 
-static struct arm_pmu *__init armv6pmu_init(void)
+static struct arm_pmu *__devinit armv6pmu_init(void)
 {
 	return &armv6pmu;
 }
@@ -679,7 +679,7 @@ static struct arm_pmu *__init armv6pmu_init(void)
 
 static int armv6mpcore_map_event(struct perf_event *event)
 {
-	return map_cpu_event(event, &armv6mpcore_perf_map,
+	return armpmu_map_event(event, &armv6mpcore_perf_map,
 				&armv6mpcore_perf_cache_map, 0xFF);
 }
 
@@ -698,17 +698,17 @@ static struct arm_pmu armv6mpcore_pmu = {
 	.max_period		= (1LLU << 32) - 1,
 };
 
-static struct arm_pmu *__init armv6mpcore_pmu_init(void)
+static struct arm_pmu *__devinit armv6mpcore_pmu_init(void)
 {
 	return &armv6mpcore_pmu;
 }
 #else
-static struct arm_pmu *__init armv6pmu_init(void)
+static struct arm_pmu *__devinit armv6pmu_init(void)
 {
 	return NULL;
 }
 
-static struct arm_pmu *__init armv6mpcore_pmu_init(void)
+static struct arm_pmu *__devinit armv6mpcore_pmu_init(void)
 {
 	return NULL;
 }
diff --git a/arch/arm/kernel/perf_event_v7.c b/arch/arm/kernel/perf_event_v7.c
index f04070b..bd4b090 100644
--- a/arch/arm/kernel/perf_event_v7.c
+++ b/arch/arm/kernel/perf_event_v7.c
@@ -1204,31 +1204,31 @@ static void armv7pmu_reset(void *info)
 
 static int armv7_a8_map_event(struct perf_event *event)
 {
-	return map_cpu_event(event, &armv7_a8_perf_map,
+	return armpmu_map_event(event, &armv7_a8_perf_map,
 				&armv7_a8_perf_cache_map, 0xFF);
 }
 
 static int armv7_a9_map_event(struct perf_event *event)
 {
-	return map_cpu_event(event, &armv7_a9_perf_map,
+	return armpmu_map_event(event, &armv7_a9_perf_map,
 				&armv7_a9_perf_cache_map, 0xFF);
 }
 
 static int armv7_a5_map_event(struct perf_event *event)
 {
-	return map_cpu_event(event, &armv7_a5_perf_map,
+	return armpmu_map_event(event, &armv7_a5_perf_map,
 				&armv7_a5_perf_cache_map, 0xFF);
 }
 
 static int armv7_a15_map_event(struct perf_event *event)
 {
-	return map_cpu_event(event, &armv7_a15_perf_map,
+	return armpmu_map_event(event, &armv7_a15_perf_map,
 				&armv7_a15_perf_cache_map, 0xFF);
 }
 
 static int armv7_a7_map_event(struct perf_event *event)
 {
-	return map_cpu_event(event, &armv7_a7_perf_map,
+	return armpmu_map_event(event, &armv7_a7_perf_map,
 				&armv7_a7_perf_cache_map, 0xFF);
 }
 
@@ -1245,7 +1245,7 @@ static struct arm_pmu armv7pmu = {
 	.max_period		= (1LLU << 32) - 1,
 };
 
-static u32 __init armv7_read_num_pmnc_events(void)
+static u32 __devinit armv7_read_num_pmnc_events(void)
 {
 	u32 nb_cnt;
 
@@ -1256,7 +1256,7 @@ static u32 __init armv7_read_num_pmnc_events(void)
 	return nb_cnt + 1;
 }
 
-static struct arm_pmu *__init armv7_a8_pmu_init(void)
+static struct arm_pmu *__devinit armv7_a8_pmu_init(void)
 {
 	armv7pmu.name		= "ARMv7 Cortex-A8";
 	armv7pmu.map_event	= armv7_a8_map_event;
@@ -1264,7 +1264,7 @@ static struct arm_pmu *__init armv7_a8_pmu_init(void)
 	return &armv7pmu;
 }
 
-static struct arm_pmu *__init armv7_a9_pmu_init(void)
+static struct arm_pmu *__devinit armv7_a9_pmu_init(void)
 {
 	armv7pmu.name		= "ARMv7 Cortex-A9";
 	armv7pmu.map_event	= armv7_a9_map_event;
@@ -1272,7 +1272,7 @@ static struct arm_pmu *__init armv7_a9_pmu_init(void)
 	return &armv7pmu;
 }
 
-static struct arm_pmu *__init armv7_a5_pmu_init(void)
+static struct arm_pmu *__devinit armv7_a5_pmu_init(void)
 {
 	armv7pmu.name		= "ARMv7 Cortex-A5";
 	armv7pmu.map_event	= armv7_a5_map_event;
@@ -1280,7 +1280,7 @@ static struct arm_pmu *__init armv7_a5_pmu_init(void)
 	return &armv7pmu;
 }
 
-static struct arm_pmu *__init armv7_a15_pmu_init(void)
+static struct arm_pmu *__devinit armv7_a15_pmu_init(void)
 {
 	armv7pmu.name		= "ARMv7 Cortex-A15";
 	armv7pmu.map_event	= armv7_a15_map_event;
@@ -1289,7 +1289,7 @@ static struct arm_pmu *__init armv7_a15_pmu_init(void)
 	return &armv7pmu;
 }
 
-static struct arm_pmu *__init armv7_a7_pmu_init(void)
+static struct arm_pmu *__devinit armv7_a7_pmu_init(void)
 {
 	armv7pmu.name		= "ARMv7 Cortex-A7";
 	armv7pmu.map_event	= armv7_a7_map_event;
@@ -1298,27 +1298,27 @@ static struct arm_pmu *__init armv7_a7_pmu_init(void)
 	return &armv7pmu;
 }
 #else
-static struct arm_pmu *__init armv7_a8_pmu_init(void)
+static struct arm_pmu *__devinit armv7_a8_pmu_init(void)
 {
 	return NULL;
 }
 
-static struct arm_pmu *__init armv7_a9_pmu_init(void)
+static struct arm_pmu *__devinit armv7_a9_pmu_init(void)
 {
 	return NULL;
 }
 
-static struct arm_pmu *__init armv7_a5_pmu_init(void)
+static struct arm_pmu *__devinit armv7_a5_pmu_init(void)
 {
 	return NULL;
 }
 
-static struct arm_pmu *__init armv7_a15_pmu_init(void)
+static struct arm_pmu *__devinit armv7_a15_pmu_init(void)
 {
 	return NULL;
 }
 
-static struct arm_pmu *__init armv7_a7_pmu_init(void)
+static struct arm_pmu *__devinit armv7_a7_pmu_init(void)
 {
 	return NULL;
 }
diff --git a/arch/arm/kernel/perf_event_xscale.c b/arch/arm/kernel/perf_event_xscale.c
index f759fe0..426e19f 100644
--- a/arch/arm/kernel/perf_event_xscale.c
+++ b/arch/arm/kernel/perf_event_xscale.c
@@ -430,7 +430,7 @@ xscale1pmu_write_counter(int counter, u32 val)
 
 static int xscale_map_event(struct perf_event *event)
 {
-	return map_cpu_event(event, &xscale_perf_map,
+	return armpmu_map_event(event, &xscale_perf_map,
 				&xscale_perf_cache_map, 0xFF);
 }
 
@@ -449,7 +449,7 @@ static struct arm_pmu xscale1pmu = {
 	.max_period	= (1LLU << 32) - 1,
 };
 
-static struct arm_pmu *__init xscale1pmu_init(void)
+static struct arm_pmu *__devinit xscale1pmu_init(void)
 {
 	return &xscale1pmu;
 }
@@ -816,17 +816,17 @@ static struct arm_pmu xscale2pmu = {
 	.max_period	= (1LLU << 32) - 1,
 };
 
-static struct arm_pmu *__init xscale2pmu_init(void)
+static struct arm_pmu *__devinit xscale2pmu_init(void)
 {
 	return &xscale2pmu;
 }
 #else
-static struct arm_pmu *__init xscale1pmu_init(void)
+static struct arm_pmu *__devinit xscale1pmu_init(void)
 {
 	return NULL;
 }
 
-static struct arm_pmu *__init xscale2pmu_init(void)
+static struct arm_pmu *__devinit xscale2pmu_init(void)
 {
 	return NULL;
 }
diff --git a/arch/arm/kernel/pmu.c b/arch/arm/kernel/pmu.c
deleted file mode 100644
index 2334bf8..0000000
--- a/arch/arm/kernel/pmu.c
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- *  linux/arch/arm/kernel/pmu.c
- *
- *  Copyright (C) 2009 picoChip Designs Ltd, Jamie Iles
- *  Copyright (C) 2010 ARM Ltd, Will Deacon
- *
- * This program is free software; you can 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/err.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-
-#include <asm/pmu.h>
-
-/*
- * PMU locking to ensure mutual exclusion between different subsystems.
- */
-static unsigned long pmu_lock[BITS_TO_LONGS(ARM_NUM_PMU_DEVICES)];
-
-int
-reserve_pmu(enum arm_pmu_type type)
-{
-	return test_and_set_bit_lock(type, pmu_lock) ? -EBUSY : 0;
-}
-EXPORT_SYMBOL_GPL(reserve_pmu);
-
-void
-release_pmu(enum arm_pmu_type type)
-{
-	clear_bit_unlock(type, pmu_lock);
-}
-EXPORT_SYMBOL_GPL(release_pmu);
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index 693b744..f98c17f 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -31,9 +31,9 @@
 #include <linux/random.h>
 #include <linux/hw_breakpoint.h>
 #include <linux/cpuidle.h>
+#include <linux/leds.h>
 
 #include <asm/cacheflush.h>
-#include <asm/leds.h>
 #include <asm/processor.h>
 #include <asm/thread_notify.h>
 #include <asm/stacktrace.h>
@@ -189,7 +189,7 @@ void cpu_idle(void)
 	while (1) {
 		tick_nohz_idle_enter();
 		rcu_idle_enter();
-		leds_event(led_idle_start);
+		ledtrig_cpu(CPU_LED_IDLE_START);
 		while (!need_resched()) {
 #ifdef CONFIG_HOTPLUG_CPU
 			if (cpu_is_offline(smp_processor_id()))
@@ -220,7 +220,7 @@ void cpu_idle(void)
 			} else
 				local_irq_enable();
 		}
-		leds_event(led_idle_end);
+		ledtrig_cpu(CPU_LED_IDLE_END);
 		rcu_idle_exit();
 		tick_nohz_idle_exit();
 		schedule_preempt_disabled();
@@ -373,6 +373,7 @@ void release_thread(struct task_struct *dead_task)
 }
 
 asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
+asmlinkage void ret_from_kernel_thread(void) __asm__("ret_from_kernel_thread");
 
 int
 copy_thread(unsigned long clone_flags, unsigned long stack_start,
@@ -381,13 +382,20 @@ copy_thread(unsigned long clone_flags, unsigned long stack_start,
 	struct thread_info *thread = task_thread_info(p);
 	struct pt_regs *childregs = task_pt_regs(p);
 
-	*childregs = *regs;
-	childregs->ARM_r0 = 0;
-	childregs->ARM_sp = stack_start;
-
 	memset(&thread->cpu_context, 0, sizeof(struct cpu_context_save));
+
+	if (likely(regs)) {
+		*childregs = *regs;
+		childregs->ARM_r0 = 0;
+		childregs->ARM_sp = stack_start;
+		thread->cpu_context.pc = (unsigned long)ret_from_fork;
+	} else {
+		thread->cpu_context.r4 = stk_sz;
+		thread->cpu_context.r5 = stack_start;
+		thread->cpu_context.pc = (unsigned long)ret_from_kernel_thread;
+		childregs->ARM_cpsr = SVC_MODE;
+	}
 	thread->cpu_context.sp = (unsigned long)childregs;
-	thread->cpu_context.pc = (unsigned long)ret_from_fork;
 
 	clear_ptrace_hw_breakpoint(p);
 
@@ -423,63 +431,6 @@ int dump_fpu (struct pt_regs *regs, struct user_fp *fp)
 }
 EXPORT_SYMBOL(dump_fpu);
 
-/*
- * Shuffle the argument into the correct register before calling the
- * thread function.  r4 is the thread argument, r5 is the pointer to
- * the thread function, and r6 points to the exit function.
- */
-extern void kernel_thread_helper(void);
-asm(	".pushsection .text\n"
-"	.align\n"
-"	.type	kernel_thread_helper, #function\n"
-"kernel_thread_helper:\n"
-#ifdef CONFIG_TRACE_IRQFLAGS
-"	bl	trace_hardirqs_on\n"
-#endif
-"	msr	cpsr_c, r7\n"
-"	mov	r0, r4\n"
-"	mov	lr, r6\n"
-"	mov	pc, r5\n"
-"	.size	kernel_thread_helper, . - kernel_thread_helper\n"
-"	.popsection");
-
-#ifdef CONFIG_ARM_UNWIND
-extern void kernel_thread_exit(long code);
-asm(	".pushsection .text\n"
-"	.align\n"
-"	.type	kernel_thread_exit, #function\n"
-"kernel_thread_exit:\n"
-"	.fnstart\n"
-"	.cantunwind\n"
-"	bl	do_exit\n"
-"	nop\n"
-"	.fnend\n"
-"	.size	kernel_thread_exit, . - kernel_thread_exit\n"
-"	.popsection");
-#else
-#define kernel_thread_exit	do_exit
-#endif
-
-/*
- * Create a kernel thread.
- */
-pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
-{
-	struct pt_regs regs;
-
-	memset(&regs, 0, sizeof(regs));
-
-	regs.ARM_r4 = (unsigned long)arg;
-	regs.ARM_r5 = (unsigned long)fn;
-	regs.ARM_r6 = (unsigned long)kernel_thread_exit;
-	regs.ARM_r7 = SVC_MODE | PSR_ENDSTATE | PSR_ISETSTATE;
-	regs.ARM_pc = (unsigned long)kernel_thread_helper;
-	regs.ARM_cpsr = regs.ARM_r7 | PSR_I_BIT;
-
-	return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
-}
-EXPORT_SYMBOL(kernel_thread);
-
 unsigned long get_wchan(struct task_struct *p)
 {
 	struct stackframe frame;
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
index 3e0fc5f..739db3a 100644
--- a/arch/arm/kernel/ptrace.c
+++ b/arch/arm/kernel/ptrace.c
@@ -30,6 +30,9 @@
 #include <asm/pgtable.h>
 #include <asm/traps.h>
 
+#define CREATE_TRACE_POINTS
+#include <trace/events/syscalls.h>
+
 #define REG_PC	15
 #define REG_PSR	16
 /*
@@ -918,11 +921,11 @@ static int ptrace_syscall_trace(struct pt_regs *regs, int scno,
 {
 	unsigned long ip;
 
+	current_thread_info()->syscall = scno;
+
 	if (!test_thread_flag(TIF_SYSCALL_TRACE))
 		return scno;
 
-	current_thread_info()->syscall = scno;
-
 	/*
 	 * IP is used to denote syscall entry/exit:
 	 * IP = 0 -> entry, =1 -> exit
@@ -941,15 +944,19 @@ static int ptrace_syscall_trace(struct pt_regs *regs, int scno,
 
 asmlinkage int syscall_trace_enter(struct pt_regs *regs, int scno)
 {
-	int ret = ptrace_syscall_trace(regs, scno, PTRACE_SYSCALL_ENTER);
+	scno = ptrace_syscall_trace(regs, scno, PTRACE_SYSCALL_ENTER);
+	if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
+		trace_sys_enter(regs, scno);
 	audit_syscall_entry(AUDIT_ARCH_ARM, scno, regs->ARM_r0, regs->ARM_r1,
 			    regs->ARM_r2, regs->ARM_r3);
-	return ret;
+	return scno;
 }
 
 asmlinkage int syscall_trace_exit(struct pt_regs *regs, int scno)
 {
-	int ret = ptrace_syscall_trace(regs, scno, PTRACE_SYSCALL_EXIT);
+	scno = ptrace_syscall_trace(regs, scno, PTRACE_SYSCALL_EXIT);
+	if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
+		trace_sys_exit(regs, scno);
 	audit_syscall_exit(regs);
-	return ret;
+	return scno;
 }
diff --git a/arch/arm/kernel/sched_clock.c b/arch/arm/kernel/sched_clock.c
index f451539..e21bac2 100644
--- a/arch/arm/kernel/sched_clock.c
+++ b/arch/arm/kernel/sched_clock.c
@@ -9,6 +9,7 @@
 #include <linux/init.h>
 #include <linux/jiffies.h>
 #include <linux/kernel.h>
+#include <linux/moduleparam.h>
 #include <linux/sched.h>
 #include <linux/syscore_ops.h>
 #include <linux/timer.h>
@@ -27,6 +28,9 @@ struct clock_data {
 
 static void sched_clock_poll(unsigned long wrap_ticks);
 static DEFINE_TIMER(sched_clock_timer, sched_clock_poll, 0, 0);
+static int irqtime = -1;
+
+core_param(irqtime, irqtime, int, 0400);
 
 static struct clock_data cd = {
 	.mult	= NSEC_PER_SEC / HZ,
@@ -157,6 +161,10 @@ void __init setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate)
 	 */
 	cd.epoch_ns = 0;
 
+	/* Enable IRQ time accounting if we have a fast enough sched_clock */
+	if (irqtime > 0 || (irqtime == -1 && rate >= 1000000))
+		enable_sched_clock_irqtime();
+
 	pr_debug("Registered %pF as sched_clock source\n", read);
 }
 
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index a81dcec..febafa0 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -21,11 +21,9 @@
 #include <linux/init.h>
 #include <linux/kexec.h>
 #include <linux/of_fdt.h>
-#include <linux/root_dev.h>
 #include <linux/cpu.h>
 #include <linux/interrupt.h>
 #include <linux/smp.h>
-#include <linux/fs.h>
 #include <linux/proc_fs.h>
 #include <linux/memblock.h>
 #include <linux/bug.h>
@@ -56,15 +54,9 @@
 #include <asm/unwind.h>
 #include <asm/memblock.h>
 
-#if defined(CONFIG_DEPRECATED_PARAM_STRUCT)
-#include "compat.h"
-#endif
 #include "atags.h"
 #include "tcm.h"
 
-#ifndef MEM_SIZE
-#define MEM_SIZE	(16*1024*1024)
-#endif
 
 #if defined(CONFIG_FPE_NWFPE) || defined(CONFIG_FPE_FASTFPE)
 char fpe_type[8];
@@ -145,7 +137,6 @@ static const char *machine_name;
 static char __initdata cmd_line[COMMAND_LINE_SIZE];
 struct machine_desc *machine_desc __initdata;
 
-static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
 static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '?', '?', 'b' } };
 #define ENDIANNESS ((char)endian_test.l)
 
@@ -583,21 +574,6 @@ static int __init early_mem(char *p)
 }
 early_param("mem", early_mem);
 
-static void __init
-setup_ramdisk(int doload, int prompt, int image_start, unsigned int rd_sz)
-{
-#ifdef CONFIG_BLK_DEV_RAM
-	extern int rd_size, rd_image_start, rd_prompt, rd_doload;
-
-	rd_image_start = image_start;
-	rd_prompt = prompt;
-	rd_doload = doload;
-
-	if (rd_sz)
-		rd_size = rd_sz;
-#endif
-}
-
 static void __init request_standard_resources(struct machine_desc *mdesc)
 {
 	struct memblock_region *region;
@@ -643,35 +619,6 @@ static void __init request_standard_resources(struct machine_desc *mdesc)
 		request_resource(&ioport_resource, &lp2);
 }
 
-/*
- *  Tag parsing.
- *
- * This is the new way of passing data to the kernel at boot time.  Rather
- * than passing a fixed inflexible structure to the kernel, we pass a list
- * of variable-sized tags to the kernel.  The first tag must be a ATAG_CORE
- * tag for the list to be recognised (to distinguish the tagged list from
- * a param_struct).  The list is terminated with a zero-length tag (this tag
- * is not parsed in any way).
- */
-static int __init parse_tag_core(const struct tag *tag)
-{
-	if (tag->hdr.size > 2) {
-		if ((tag->u.core.flags & 1) == 0)
-			root_mountflags &= ~MS_RDONLY;
-		ROOT_DEV = old_decode_dev(tag->u.core.rootdev);
-	}
-	return 0;
-}
-
-__tagtable(ATAG_CORE, parse_tag_core);
-
-static int __init parse_tag_mem32(const struct tag *tag)
-{
-	return arm_add_memory(tag->u.mem.start, tag->u.mem.size);
-}
-
-__tagtable(ATAG_MEM, parse_tag_mem32);
-
 #if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
 struct screen_info screen_info = {
  .orig_video_lines	= 30,
@@ -681,116 +628,7 @@ struct screen_info screen_info = {
  .orig_video_isVGA	= 1,
  .orig_video_points	= 8
 };
-
-static int __init parse_tag_videotext(const struct tag *tag)
-{
-	screen_info.orig_x            = tag->u.videotext.x;
-	screen_info.orig_y            = tag->u.videotext.y;
-	screen_info.orig_video_page   = tag->u.videotext.video_page;
-	screen_info.orig_video_mode   = tag->u.videotext.video_mode;
-	screen_info.orig_video_cols   = tag->u.videotext.video_cols;
-	screen_info.orig_video_ega_bx = tag->u.videotext.video_ega_bx;
-	screen_info.orig_video_lines  = tag->u.videotext.video_lines;
-	screen_info.orig_video_isVGA  = tag->u.videotext.video_isvga;
-	screen_info.orig_video_points = tag->u.videotext.video_points;
-	return 0;
-}
-
-__tagtable(ATAG_VIDEOTEXT, parse_tag_videotext);
-#endif
-
-static int __init parse_tag_ramdisk(const struct tag *tag)
-{
-	setup_ramdisk((tag->u.ramdisk.flags & 1) == 0,
-		      (tag->u.ramdisk.flags & 2) == 0,
-		      tag->u.ramdisk.start, tag->u.ramdisk.size);
-	return 0;
-}
-
-__tagtable(ATAG_RAMDISK, parse_tag_ramdisk);
-
-static int __init parse_tag_serialnr(const struct tag *tag)
-{
-	system_serial_low = tag->u.serialnr.low;
-	system_serial_high = tag->u.serialnr.high;
-	return 0;
-}
-
-__tagtable(ATAG_SERIAL, parse_tag_serialnr);
-
-static int __init parse_tag_revision(const struct tag *tag)
-{
-	system_rev = tag->u.revision.rev;
-	return 0;
-}
-
-__tagtable(ATAG_REVISION, parse_tag_revision);
-
-static int __init parse_tag_cmdline(const struct tag *tag)
-{
-#if defined(CONFIG_CMDLINE_EXTEND)
-	strlcat(default_command_line, " ", COMMAND_LINE_SIZE);
-	strlcat(default_command_line, tag->u.cmdline.cmdline,
-		COMMAND_LINE_SIZE);
-#elif defined(CONFIG_CMDLINE_FORCE)
-	pr_warning("Ignoring tag cmdline (using the default kernel command line)\n");
-#else
-	strlcpy(default_command_line, tag->u.cmdline.cmdline,
-		COMMAND_LINE_SIZE);
 #endif
-	return 0;
-}
-
-__tagtable(ATAG_CMDLINE, parse_tag_cmdline);
-
-/*
- * Scan the tag table for this tag, and call its parse function.
- * The tag table is built by the linker from all the __tagtable
- * declarations.
- */
-static int __init parse_tag(const struct tag *tag)
-{
-	extern struct tagtable __tagtable_begin, __tagtable_end;
-	struct tagtable *t;
-
-	for (t = &__tagtable_begin; t < &__tagtable_end; t++)
-		if (tag->hdr.tag == t->tag) {
-			t->parse(tag);
-			break;
-		}
-
-	return t < &__tagtable_end;
-}
-
-/*
- * Parse all tags in the list, checking both the global and architecture
- * specific tag tables.
- */
-static void __init parse_tags(const struct tag *t)
-{
-	for (; t->hdr.size; t = tag_next(t))
-		if (!parse_tag(t))
-			printk(KERN_WARNING
-				"Ignoring unrecognised tag 0x%08x\n",
-				t->hdr.tag);
-}
-
-/*
- * This holds our defaults.
- */
-static struct init_tags {
-	struct tag_header hdr1;
-	struct tag_core   core;
-	struct tag_header hdr2;
-	struct tag_mem32  mem;
-	struct tag_header hdr3;
-} init_tags __initdata = {
-	{ tag_size(tag_core), ATAG_CORE },
-	{ 1, PAGE_SIZE, 0xff },
-	{ tag_size(tag_mem32), ATAG_MEM },
-	{ MEM_SIZE },
-	{ 0, ATAG_NONE }
-};
 
 static int __init customize_machine(void)
 {
@@ -858,78 +696,6 @@ static void __init reserve_crashkernel(void)
 static inline void reserve_crashkernel(void) {}
 #endif /* CONFIG_KEXEC */
 
-static void __init squash_mem_tags(struct tag *tag)
-{
-	for (; tag->hdr.size; tag = tag_next(tag))
-		if (tag->hdr.tag == ATAG_MEM)
-			tag->hdr.tag = ATAG_NONE;
-}
-
-static struct machine_desc * __init setup_machine_tags(unsigned int nr)
-{
-	struct tag *tags = (struct tag *)&init_tags;
-	struct machine_desc *mdesc = NULL, *p;
-	char *from = default_command_line;
-
-	init_tags.mem.start = PHYS_OFFSET;
-
-	/*
-	 * locate machine in the list of supported machines.
-	 */
-	for_each_machine_desc(p)
-		if (nr == p->nr) {
-			printk("Machine: %s\n", p->name);
-			mdesc = p;
-			break;
-		}
-
-	if (!mdesc) {
-		early_print("\nError: unrecognized/unsupported machine ID"
-			" (r1 = 0x%08x).\n\n", nr);
-		dump_machine_table(); /* does not return */
-	}
-
-	if (__atags_pointer)
-		tags = phys_to_virt(__atags_pointer);
-	else if (mdesc->atag_offset)
-		tags = (void *)(PAGE_OFFSET + mdesc->atag_offset);
-
-#if defined(CONFIG_DEPRECATED_PARAM_STRUCT)
-	/*
-	 * If we have the old style parameters, convert them to
-	 * a tag list.
-	 */
-	if (tags->hdr.tag != ATAG_CORE)
-		convert_to_tag_list(tags);
-#endif
-
-	if (tags->hdr.tag != ATAG_CORE) {
-#if defined(CONFIG_OF)
-		/*
-		 * If CONFIG_OF is set, then assume this is a reasonably
-		 * modern system that should pass boot parameters
-		 */
-		early_print("Warning: Neither atags nor dtb found\n");
-#endif
-		tags = (struct tag *)&init_tags;
-	}
-
-	if (mdesc->fixup)
-		mdesc->fixup(tags, &from, &meminfo);
-
-	if (tags->hdr.tag == ATAG_CORE) {
-		if (meminfo.nr_banks != 0)
-			squash_mem_tags(tags);
-		save_atags(tags);
-		parse_tags(tags);
-	}
-
-	/* parse_early_param needs a boot_command_line */
-	strlcpy(boot_command_line, from, COMMAND_LINE_SIZE);
-
-	return mdesc;
-}
-
 static int __init meminfo_cmp(const void *_a, const void *_b)
 {
 	const struct membank *a = _a, *b = _b;
@@ -944,7 +710,7 @@ void __init setup_arch(char **cmdline_p)
 	setup_processor();
 	mdesc = setup_machine_fdt(__atags_pointer);
 	if (!mdesc)
-		mdesc = setup_machine_tags(machine_arch_type);
+		mdesc = setup_machine_tags(__atags_pointer, machine_arch_type);
 	machine_desc = mdesc;
 	machine_name = mdesc->name;
 
@@ -977,8 +743,10 @@ void __init setup_arch(char **cmdline_p)
 	unflatten_device_tree();
 
 #ifdef CONFIG_SMP
-	if (is_smp())
+	if (is_smp()) {
+		smp_set_ops(mdesc->smp);
 		smp_init_cpus();
+	}
 #endif
 	reserve_crashkernel();
 
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index f27789e..56f72d2 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -10,7 +10,6 @@
 #include <linux/errno.h>
 #include <linux/signal.h>
 #include <linux/personality.h>
-#include <linux/freezer.h>
 #include <linux/uaccess.h>
 #include <linux/tracehook.h>
 
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index ebd8ad2..d100eac 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -19,14 +19,15 @@
 #include <linux/mm.h>
 #include <linux/err.h>
 #include <linux/cpu.h>
-#include <linux/smp.h>
 #include <linux/seq_file.h>
 #include <linux/irq.h>
 #include <linux/percpu.h>
 #include <linux/clockchips.h>
 #include <linux/completion.h>
+#include <linux/cpufreq.h>
 
 #include <linux/atomic.h>
+#include <asm/smp.h>
 #include <asm/cacheflush.h>
 #include <asm/cpu.h>
 #include <asm/cputype.h>
@@ -42,6 +43,7 @@
 #include <asm/ptrace.h>
 #include <asm/localtimer.h>
 #include <asm/smp_plat.h>
+#include <asm/mach/arch.h>
 
 /*
  * as from 2.5, kernels no longer have an init_tasks structure
@@ -50,8 +52,15 @@
  */
 struct secondary_data secondary_data;
 
+/*
+ * control for which core is the next to come out of the secondary
+ * boot "holding pen"
+ */
+volatile int __cpuinitdata pen_release = -1;
+
 enum ipi_msg_type {
-	IPI_TIMER = 2,
+	IPI_WAKEUP,
+	IPI_TIMER,
 	IPI_RESCHEDULE,
 	IPI_CALL_FUNC,
 	IPI_CALL_FUNC_SINGLE,
@@ -60,6 +69,14 @@ enum ipi_msg_type {
 
 static DECLARE_COMPLETION(cpu_running);
 
+static struct smp_operations smp_ops;
+
+void __init smp_set_ops(struct smp_operations *ops)
+{
+	if (ops)
+		smp_ops = *ops;
+};
+
 int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *idle)
 {
 	int ret;
@@ -100,13 +117,64 @@ int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *idle)
 	return ret;
 }
 
+/* platform specific SMP operations */
+void __init smp_init_cpus(void)
+{
+	if (smp_ops.smp_init_cpus)
+		smp_ops.smp_init_cpus();
+}
+
+static void __init platform_smp_prepare_cpus(unsigned int max_cpus)
+{
+	if (smp_ops.smp_prepare_cpus)
+		smp_ops.smp_prepare_cpus(max_cpus);
+}
+
+static void __cpuinit platform_secondary_init(unsigned int cpu)
+{
+	if (smp_ops.smp_secondary_init)
+		smp_ops.smp_secondary_init(cpu);
+}
+
+int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+	if (smp_ops.smp_boot_secondary)
+		return smp_ops.smp_boot_secondary(cpu, idle);
+	return -ENOSYS;
+}
+
 #ifdef CONFIG_HOTPLUG_CPU
 static void percpu_timer_stop(void);
 
+static int platform_cpu_kill(unsigned int cpu)
+{
+	if (smp_ops.cpu_kill)
+		return smp_ops.cpu_kill(cpu);
+	return 1;
+}
+
+static void platform_cpu_die(unsigned int cpu)
+{
+	if (smp_ops.cpu_die)
+		smp_ops.cpu_die(cpu);
+}
+
+static int platform_cpu_disable(unsigned int cpu)
+{
+	if (smp_ops.cpu_disable)
+		return smp_ops.cpu_disable(cpu);
+
+	/*
+	 * By default, allow disabling all CPUs except the first one,
+	 * since this is special on a lot of platforms, e.g. because
+	 * of clock tick interrupts.
+	 */
+	return cpu == 0 ? -EPERM : 0;
+}
 /*
  * __cpu_disable runs on the processor to be shutdown.
  */
-int __cpu_disable(void)
+int __cpuinit __cpu_disable(void)
 {
 	unsigned int cpu = smp_processor_id();
 	int ret;
@@ -149,7 +217,7 @@ static DECLARE_COMPLETION(cpu_died);
  * called on the thread which is asking for a CPU to be shutdown -
  * waits until shutdown has completed, or it is timed out.
  */
-void __cpu_die(unsigned int cpu)
+void __cpuinit __cpu_die(unsigned int cpu)
 {
 	if (!wait_for_completion_timeout(&cpu_died, msecs_to_jiffies(5000))) {
 		pr_err("CPU%u: cpu didn't die\n", cpu);
@@ -347,7 +415,8 @@ void arch_send_call_function_single_ipi(int cpu)
 }
 
 static const char *ipi_types[NR_IPI] = {
-#define S(x,s)	[x - IPI_TIMER] = s
+#define S(x,s)	[x] = s
+	S(IPI_WAKEUP, "CPU wakeup interrupts"),
 	S(IPI_TIMER, "Timer broadcast interrupts"),
 	S(IPI_RESCHEDULE, "Rescheduling interrupts"),
 	S(IPI_CALL_FUNC, "Function call interrupts"),
@@ -500,10 +569,13 @@ void handle_IPI(int ipinr, struct pt_regs *regs)
 	unsigned int cpu = smp_processor_id();
 	struct pt_regs *old_regs = set_irq_regs(regs);
 
-	if (ipinr >= IPI_TIMER && ipinr < IPI_TIMER + NR_IPI)
-		__inc_irq_stat(cpu, ipi_irqs[ipinr - IPI_TIMER]);
+	if (ipinr < NR_IPI)
+		__inc_irq_stat(cpu, ipi_irqs[ipinr]);
 
 	switch (ipinr) {
+	case IPI_WAKEUP:
+		break;
+
 	case IPI_TIMER:
 		irq_enter();
 		ipi_timer();
@@ -584,3 +656,56 @@ int setup_profiling_timer(unsigned int multiplier)
 {
 	return -EINVAL;
 }
+
+#ifdef CONFIG_CPU_FREQ
+
+static DEFINE_PER_CPU(unsigned long, l_p_j_ref);
+static DEFINE_PER_CPU(unsigned long, l_p_j_ref_freq);
+static unsigned long global_l_p_j_ref;
+static unsigned long global_l_p_j_ref_freq;
+
+static int cpufreq_callback(struct notifier_block *nb,
+					unsigned long val, void *data)
+{
+	struct cpufreq_freqs *freq = data;
+	int cpu = freq->cpu;
+
+	if (freq->flags & CPUFREQ_CONST_LOOPS)
+		return NOTIFY_OK;
+
+	if (!per_cpu(l_p_j_ref, cpu)) {
+		per_cpu(l_p_j_ref, cpu) =
+			per_cpu(cpu_data, cpu).loops_per_jiffy;
+		per_cpu(l_p_j_ref_freq, cpu) = freq->old;
+		if (!global_l_p_j_ref) {
+			global_l_p_j_ref = loops_per_jiffy;
+			global_l_p_j_ref_freq = freq->old;
+		}
+	}
+
+	if ((val == CPUFREQ_PRECHANGE  && freq->old < freq->new) ||
+	    (val == CPUFREQ_POSTCHANGE && freq->old > freq->new) ||
+	    (val == CPUFREQ_RESUMECHANGE || val == CPUFREQ_SUSPENDCHANGE)) {
+		loops_per_jiffy = cpufreq_scale(global_l_p_j_ref,
+						global_l_p_j_ref_freq,
+						freq->new);
+		per_cpu(cpu_data, cpu).loops_per_jiffy =
+			cpufreq_scale(per_cpu(l_p_j_ref, cpu),
+					per_cpu(l_p_j_ref_freq, cpu),
+					freq->new);
+	}
+	return NOTIFY_OK;
+}
+
+static struct notifier_block cpufreq_notifier = {
+	.notifier_call  = cpufreq_callback,
+};
+
+static int __init register_cpufreq_notifier(void)
+{
+	return cpufreq_register_notifier(&cpufreq_notifier,
+						CPUFREQ_TRANSITION_NOTIFIER);
+}
+core_initcall(register_cpufreq_notifier);
+
+#endif
diff --git a/arch/arm/kernel/sys_arm.c b/arch/arm/kernel/sys_arm.c
index 76cbb05..c2a898a 100644
--- a/arch/arm/kernel/sys_arm.c
+++ b/arch/arm/kernel/sys_arm.c
@@ -59,69 +59,6 @@ asmlinkage int sys_vfork(struct pt_regs *regs)
 	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->ARM_sp, regs, 0, NULL, NULL);
 }
 
-/* sys_execve() executes a new program.
- * This is called indirectly via a small wrapper
- */
-asmlinkage int sys_execve(const char __user *filenamei,
-			  const char __user *const __user *argv,
-			  const char __user *const __user *envp, struct pt_regs *regs)
-{
-	int error;
-	char * filename;
-
-	filename = getname(filenamei);
-	error = PTR_ERR(filename);
-	if (IS_ERR(filename))
-		goto out;
-	error = do_execve(filename, argv, envp, regs);
-	putname(filename);
-out:
-	return error;
-}
-
-int kernel_execve(const char *filename,
-		  const char *const argv[],
-		  const char *const envp[])
-{
-	struct pt_regs regs;
-	int ret;
-
-	memset(&regs, 0, sizeof(struct pt_regs));
-	ret = do_execve(filename,
-			(const char __user *const __user *)argv,
-			(const char __user *const __user *)envp, &regs);
-	if (ret < 0)
-		goto out;
-
-	/*
-	 * Save argc to the register structure for userspace.
-	 */
-	regs.ARM_r0 = ret;
-
-	/*
-	 * We were successful.  We won't be returning to our caller, but
-	 * instead to user space by manipulating the kernel stack.
-	 */
-	asm(	"add	r0, %0, %1\n\t"
-		"mov	r1, %2\n\t"
-		"mov	r2, %3\n\t"
-		"bl	memmove\n\t"	/* copy regs to top of stack */
-		"mov	r8, #0\n\t"	/* not a syscall */
-		"mov	r9, %0\n\t"	/* thread structure */
-		"mov	sp, r0\n\t"	/* reposition stack pointer */
-		"b	ret_to_user"
-		:
-		: "r" (current_thread_info()),
-		  "Ir" (THREAD_START_SP - sizeof(regs)),
-		  "r" (&regs),
-		  "Ir" (sizeof(regs))
-		: "r0", "r1", "r2", "r3", "r8", "r9", "ip", "lr", "memory");
-
- out:
-	return ret;
-}
-EXPORT_SYMBOL(kernel_execve);
-
 /*
  * Since loff_t is a 64 bit type we avoid a lot of ABI hassle
  * with a different argument ordering.
diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
index af2afb0..09be0c3 100644
--- a/arch/arm/kernel/time.c
+++ b/arch/arm/kernel/time.c
@@ -25,7 +25,6 @@
 #include <linux/timer.h>
 #include <linux/irq.h>
 
-#include <asm/leds.h>
 #include <asm/thread_info.h>
 #include <asm/sched_clock.h>
 #include <asm/stacktrace.h>
@@ -80,21 +79,6 @@ u32 arch_gettimeoffset(void)
 }
 #endif /* CONFIG_ARCH_USES_GETTIMEOFFSET */
 
-#ifdef CONFIG_LEDS_TIMER
-static inline void do_leds(void)
-{
-	static unsigned int count = HZ/2;
-
-	if (--count == 0) {
-		count = HZ/2;
-		leds_event(led_timer);
-	}
-}
-#else
-#define	do_leds()
-#endif
-
-
 #ifndef CONFIG_GENERIC_CLOCKEVENTS
 /*
  * Kernel system timer support.
@@ -102,7 +86,6 @@ static inline void do_leds(void)
 void timer_tick(void)
 {
 	profile_tick(CPU_PROFILING);
-	do_leds();
 	xtime_update(1);
 #ifndef CONFIG_SMP
 	update_process_times(user_mode(get_irq_regs()));
diff --git a/arch/arm/mach-at91/Makefile.boot b/arch/arm/mach-at91/Makefile.boot
index 30bb733..5309f9b 100644
--- a/arch/arm/mach-at91/Makefile.boot
+++ b/arch/arm/mach-at91/Makefile.boot
@@ -12,27 +12,3 @@ else
 params_phys-y	:= 0x20000100
 initrd_phys-y	:= 0x20410000
 endif
-
-# Keep dtb files sorted alphabetically for each SoC
-# sam9260
-dtb-$(CONFIG_MACH_AT91SAM_DT) += aks-cdu.dtb
-dtb-$(CONFIG_MACH_AT91SAM_DT) += ethernut5.dtb
-dtb-$(CONFIG_MACH_AT91SAM_DT) += evk-pro3.dtb
-dtb-$(CONFIG_MACH_AT91SAM_DT) += tny_a9260.dtb
-dtb-$(CONFIG_MACH_AT91SAM_DT) += usb_a9260.dtb
-# sam9263
-dtb-$(CONFIG_MACH_AT91SAM_DT) += at91sam9263ek.dtb
-dtb-$(CONFIG_MACH_AT91SAM_DT) += tny_a9263.dtb
-dtb-$(CONFIG_MACH_AT91SAM_DT) += usb_a9263.dtb
-# sam9g20
-dtb-$(CONFIG_MACH_AT91SAM_DT) += at91sam9g20ek.dtb
-dtb-$(CONFIG_MACH_AT91SAM_DT) += at91sam9g20ek_2mmc.dtb
-dtb-$(CONFIG_MACH_AT91SAM_DT) += kizbox.dtb
-dtb-$(CONFIG_MACH_AT91SAM_DT) += tny_a9g20.dtb
-dtb-$(CONFIG_MACH_AT91SAM_DT) += usb_a9g20.dtb
-# sam9g45
-dtb-$(CONFIG_MACH_AT91SAM_DT) += at91sam9m10g45ek.dtb
-# sam9n12
-dtb-$(CONFIG_MACH_AT91SAM_DT) += at91sam9n12ek.dtb
-# sam9x5
-dtb-$(CONFIG_MACH_AT91SAM_DT) += at91sam9g25ek.dtb
diff --git a/arch/arm/mach-at91/at91rm9200.c b/arch/arm/mach-at91/at91rm9200.c
index 6f50c67..b4f0565 100644
--- a/arch/arm/mach-at91/at91rm9200.c
+++ b/arch/arm/mach-at91/at91rm9200.c
@@ -187,6 +187,7 @@ static struct clk_lookup periph_clocks_lookups[] = {
 	CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
 	CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
 	CLKDEV_CON_DEV_ID("pclk", "ssc.2", &ssc2_clk),
+	CLKDEV_CON_DEV_ID(NULL, "i2c-at91rm9200", &twi_clk),
 	/* fake hclk clock */
 	CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk),
 	CLKDEV_CON_ID("pioA", &pioA_clk),
diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c
index 01fb732..a563189 100644
--- a/arch/arm/mach-at91/at91rm9200_devices.c
+++ b/arch/arm/mach-at91/at91rm9200_devices.c
@@ -294,9 +294,9 @@ void __init at91_add_device_cf(struct at91_cf_data *data) {}
  *  MMC / SD
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_MMC_AT91) || defined(CONFIG_MMC_AT91_MODULE)
+#if IS_ENABLED(CONFIG_MMC_ATMELMCI)
 static u64 mmc_dmamask = DMA_BIT_MASK(32);
-static struct at91_mmc_data mmc_data;
+static struct mci_platform_data mmc_data;
 
 static struct resource mmc_resources[] = {
 	[0] = {
@@ -312,7 +312,7 @@ static struct resource mmc_resources[] = {
 };
 
 static struct platform_device at91rm9200_mmc_device = {
-	.name		= "at91_mci",
+	.name		= "atmel_mci",
 	.id		= -1,
 	.dev		= {
 				.dma_mask		= &mmc_dmamask,
@@ -323,53 +323,69 @@ static struct platform_device at91rm9200_mmc_device = {
 	.num_resources	= ARRAY_SIZE(mmc_resources),
 };
 
-void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data)
+void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data)
 {
+	unsigned int i;
+	unsigned int slot_count = 0;
+
 	if (!data)
 		return;
 
-	/* input/irq */
-	if (gpio_is_valid(data->det_pin)) {
-		at91_set_gpio_input(data->det_pin, 1);
-		at91_set_deglitch(data->det_pin, 1);
-	}
-	if (gpio_is_valid(data->wp_pin))
-		at91_set_gpio_input(data->wp_pin, 1);
-	if (gpio_is_valid(data->vcc_pin))
-		at91_set_gpio_output(data->vcc_pin, 0);
-
-	/* CLK */
-	at91_set_A_periph(AT91_PIN_PA27, 0);
+	for (i = 0; i < ATMCI_MAX_NR_SLOTS; i++) {
 
-	if (data->slot_b) {
-		/* CMD */
-		at91_set_B_periph(AT91_PIN_PA8, 1);
+		if (!data->slot[i].bus_width)
+			continue;
 
-		/* DAT0, maybe DAT1..DAT3 */
-		at91_set_B_periph(AT91_PIN_PA9, 1);
-		if (data->wire4) {
-			at91_set_B_periph(AT91_PIN_PA10, 1);
-			at91_set_B_periph(AT91_PIN_PA11, 1);
-			at91_set_B_periph(AT91_PIN_PA12, 1);
+		/* input/irq */
+		if (gpio_is_valid(data->slot[i].detect_pin)) {
+			at91_set_gpio_input(data->slot[i].detect_pin, 1);
+			at91_set_deglitch(data->slot[i].detect_pin, 1);
 		}
-	} else {
-		/* CMD */
-		at91_set_A_periph(AT91_PIN_PA28, 1);
-
-		/* DAT0, maybe DAT1..DAT3 */
-		at91_set_A_periph(AT91_PIN_PA29, 1);
-		if (data->wire4) {
-			at91_set_B_periph(AT91_PIN_PB3, 1);
-			at91_set_B_periph(AT91_PIN_PB4, 1);
-			at91_set_B_periph(AT91_PIN_PB5, 1);
+		if (gpio_is_valid(data->slot[i].wp_pin))
+			at91_set_gpio_input(data->slot[i].wp_pin, 1);
+
+		switch (i) {
+		case 0:					/* slot A */
+			/* CMD */
+			at91_set_A_periph(AT91_PIN_PA28, 1);
+			/* DAT0, maybe DAT1..DAT3 */
+			at91_set_A_periph(AT91_PIN_PA29, 1);
+			if (data->slot[i].bus_width == 4) {
+				at91_set_B_periph(AT91_PIN_PB3, 1);
+				at91_set_B_periph(AT91_PIN_PB4, 1);
+				at91_set_B_periph(AT91_PIN_PB5, 1);
+			}
+			slot_count++;
+			break;
+		case 1:					/* slot B */
+			/* CMD */
+			at91_set_B_periph(AT91_PIN_PA8, 1);
+			/* DAT0, maybe DAT1..DAT3 */
+			at91_set_B_periph(AT91_PIN_PA9, 1);
+			if (data->slot[i].bus_width == 4) {
+				at91_set_B_periph(AT91_PIN_PA10, 1);
+				at91_set_B_periph(AT91_PIN_PA11, 1);
+				at91_set_B_periph(AT91_PIN_PA12, 1);
+			}
+			slot_count++;
+			break;
+		default:
+			printk(KERN_ERR
+			       "AT91: SD/MMC slot %d not available\n", i);
+			break;
+		}
+		if (slot_count) {
+			/* CLK */
+			at91_set_A_periph(AT91_PIN_PA27, 0);
+
+			mmc_data = *data;
+			platform_device_register(&at91rm9200_mmc_device);
 		}
 	}
 
-	mmc_data = *data;
-	platform_device_register(&at91rm9200_mmc_device);
 }
 #else
-void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {}
+void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data) {}
 #endif
 
 
@@ -495,7 +511,7 @@ static struct resource twi_resources[] = {
 };
 
 static struct platform_device at91rm9200_twi_device = {
-	.name		= "at91_i2c",
+	.name		= "i2c-at91rm9200",
 	.id		= -1,
 	.resource	= twi_resources,
 	.num_resources	= ARRAY_SIZE(twi_resources),
diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c
index 30c7f26..ad29f93 100644
--- a/arch/arm/mach-at91/at91sam9260.c
+++ b/arch/arm/mach-at91/at91sam9260.c
@@ -211,6 +211,8 @@ static struct clk_lookup periph_clocks_lookups[] = {
 	CLKDEV_CON_DEV_ID("t1_clk", "atmel_tcb.1", &tc4_clk),
 	CLKDEV_CON_DEV_ID("t2_clk", "atmel_tcb.1", &tc5_clk),
 	CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc_clk),
+	CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9260", &twi_clk),
+	CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g20", &twi_clk),
 	/* more usart lookup table for DT entries */
 	CLKDEV_CON_DEV_ID("usart", "fffff200.serial", &mck),
 	CLKDEV_CON_DEV_ID("usart", "fffb0000.serial", &usart0_clk),
@@ -219,6 +221,7 @@ static struct clk_lookup periph_clocks_lookups[] = {
 	CLKDEV_CON_DEV_ID("usart", "fffd0000.serial", &usart3_clk),
 	CLKDEV_CON_DEV_ID("usart", "fffd4000.serial", &usart4_clk),
 	CLKDEV_CON_DEV_ID("usart", "fffd8000.serial", &usart5_clk),
+	CLKDEV_CON_DEV_ID(NULL, "fffac000.i2c", &twi_clk),
 	/* more tc lookup table for DT entries */
 	CLKDEV_CON_DEV_ID("t0_clk", "fffa0000.timer", &tc0_clk),
 	CLKDEV_CON_DEV_ID("t1_clk", "fffa0000.timer", &tc1_clk),
diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c
index bce572a..a76b868 100644
--- a/arch/arm/mach-at91/at91sam9260_devices.c
+++ b/arch/arm/mach-at91/at91sam9260_devices.c
@@ -209,92 +209,10 @@ void __init at91_add_device_eth(struct macb_platform_data *data) {}
 
 
 /* --------------------------------------------------------------------
- *  MMC / SD
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_MMC_AT91) || defined(CONFIG_MMC_AT91_MODULE)
-static u64 mmc_dmamask = DMA_BIT_MASK(32);
-static struct at91_mmc_data mmc_data;
-
-static struct resource mmc_resources[] = {
-	[0] = {
-		.start	= AT91SAM9260_BASE_MCI,
-		.end	= AT91SAM9260_BASE_MCI + SZ_16K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= NR_IRQS_LEGACY + AT91SAM9260_ID_MCI,
-		.end	= NR_IRQS_LEGACY + AT91SAM9260_ID_MCI,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device at91sam9260_mmc_device = {
-	.name		= "at91_mci",
-	.id		= -1,
-	.dev		= {
-				.dma_mask		= &mmc_dmamask,
-				.coherent_dma_mask	= DMA_BIT_MASK(32),
-				.platform_data		= &mmc_data,
-	},
-	.resource	= mmc_resources,
-	.num_resources	= ARRAY_SIZE(mmc_resources),
-};
-
-void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data)
-{
-	if (!data)
-		return;
-
-	/* input/irq */
-	if (gpio_is_valid(data->det_pin)) {
-		at91_set_gpio_input(data->det_pin, 1);
-		at91_set_deglitch(data->det_pin, 1);
-	}
-	if (gpio_is_valid(data->wp_pin))
-		at91_set_gpio_input(data->wp_pin, 1);
-	if (gpio_is_valid(data->vcc_pin))
-		at91_set_gpio_output(data->vcc_pin, 0);
-
-	/* CLK */
-	at91_set_A_periph(AT91_PIN_PA8, 0);
-
-	if (data->slot_b) {
-		/* CMD */
-		at91_set_B_periph(AT91_PIN_PA1, 1);
-
-		/* DAT0, maybe DAT1..DAT3 */
-		at91_set_B_periph(AT91_PIN_PA0, 1);
-		if (data->wire4) {
-			at91_set_B_periph(AT91_PIN_PA5, 1);
-			at91_set_B_periph(AT91_PIN_PA4, 1);
-			at91_set_B_periph(AT91_PIN_PA3, 1);
-		}
-	} else {
-		/* CMD */
-		at91_set_A_periph(AT91_PIN_PA7, 1);
-
-		/* DAT0, maybe DAT1..DAT3 */
-		at91_set_A_periph(AT91_PIN_PA6, 1);
-		if (data->wire4) {
-			at91_set_A_periph(AT91_PIN_PA9, 1);
-			at91_set_A_periph(AT91_PIN_PA10, 1);
-			at91_set_A_periph(AT91_PIN_PA11, 1);
-		}
-	}
-
-	mmc_data = *data;
-	platform_device_register(&at91sam9260_mmc_device);
-}
-#else
-void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {}
-#endif
-
-/* --------------------------------------------------------------------
  *  MMC / SD Slot for Atmel MCI Driver
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE)
+#if IS_ENABLED(CONFIG_MMC_ATMELMCI)
 static u64 mmc_dmamask = DMA_BIT_MASK(32);
 static struct mci_platform_data mmc_data;
 
@@ -503,7 +421,6 @@ static struct resource twi_resources[] = {
 };
 
 static struct platform_device at91sam9260_twi_device = {
-	.name		= "at91_i2c",
 	.id		= -1,
 	.resource	= twi_resources,
 	.num_resources	= ARRAY_SIZE(twi_resources),
@@ -511,6 +428,13 @@ static struct platform_device at91sam9260_twi_device = {
 
 void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices)
 {
+	/* IP version is not the same on 9260 and g20 */
+	if (cpu_is_at91sam9g20()) {
+		at91sam9260_twi_device.name = "i2c-at91sam9g20";
+	} else {
+		at91sam9260_twi_device.name = "i2c-at91sam9260";
+	}
+
 	/* pins used for TWI interface */
 	at91_set_A_periph(AT91_PIN_PA23, 0);		/* TWD */
 	at91_set_multi_drive(AT91_PIN_PA23, 1);
diff --git a/arch/arm/mach-at91/at91sam9261.c b/arch/arm/mach-at91/at91sam9261.c
index f40762c..8d999eb 100644
--- a/arch/arm/mach-at91/at91sam9261.c
+++ b/arch/arm/mach-at91/at91sam9261.c
@@ -178,6 +178,8 @@ static struct clk_lookup periph_clocks_lookups[] = {
 	CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
 	CLKDEV_CON_DEV_ID("pclk", "ssc.2", &ssc2_clk),
 	CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &hck0),
+	CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9261", &twi_clk),
+	CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g10", &twi_clk),
 	CLKDEV_CON_ID("pioA", &pioA_clk),
 	CLKDEV_CON_ID("pioB", &pioB_clk),
 	CLKDEV_CON_ID("pioC", &pioC_clk),
diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c
index bc2590d..9752f17 100644
--- a/arch/arm/mach-at91/at91sam9261_devices.c
+++ b/arch/arm/mach-at91/at91sam9261_devices.c
@@ -137,9 +137,9 @@ void __init at91_add_device_udc(struct at91_udc_data *data) {}
  *  MMC / SD
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_MMC_AT91) || defined(CONFIG_MMC_AT91_MODULE)
+#if IS_ENABLED(CONFIG_MMC_ATMELMCI)
 static u64 mmc_dmamask = DMA_BIT_MASK(32);
-static struct at91_mmc_data mmc_data;
+static struct mci_platform_data mmc_data;
 
 static struct resource mmc_resources[] = {
 	[0] = {
@@ -155,7 +155,7 @@ static struct resource mmc_resources[] = {
 };
 
 static struct platform_device at91sam9261_mmc_device = {
-	.name		= "at91_mci",
+	.name		= "atmel_mci",
 	.id		= -1,
 	.dev		= {
 				.dma_mask		= &mmc_dmamask,
@@ -166,40 +166,40 @@ static struct platform_device at91sam9261_mmc_device = {
 	.num_resources	= ARRAY_SIZE(mmc_resources),
 };
 
-void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data)
+void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data)
 {
 	if (!data)
 		return;
 
-	/* input/irq */
-	if (gpio_is_valid(data->det_pin)) {
-		at91_set_gpio_input(data->det_pin, 1);
-		at91_set_deglitch(data->det_pin, 1);
-	}
-	if (gpio_is_valid(data->wp_pin))
-		at91_set_gpio_input(data->wp_pin, 1);
-	if (gpio_is_valid(data->vcc_pin))
-		at91_set_gpio_output(data->vcc_pin, 0);
-
-	/* CLK */
-	at91_set_B_periph(AT91_PIN_PA2, 0);
-
-	/* CMD */
-	at91_set_B_periph(AT91_PIN_PA1, 1);
-
-	/* DAT0, maybe DAT1..DAT3 */
-	at91_set_B_periph(AT91_PIN_PA0, 1);
-	if (data->wire4) {
-		at91_set_B_periph(AT91_PIN_PA4, 1);
-		at91_set_B_periph(AT91_PIN_PA5, 1);
-		at91_set_B_periph(AT91_PIN_PA6, 1);
-	}
+	if (data->slot[0].bus_width) {
+		/* input/irq */
+		if (gpio_is_valid(data->slot[0].detect_pin)) {
+			at91_set_gpio_input(data->slot[0].detect_pin, 1);
+			at91_set_deglitch(data->slot[0].detect_pin, 1);
+		}
+		if (gpio_is_valid(data->slot[0].wp_pin))
+			at91_set_gpio_input(data->slot[0].wp_pin, 1);
+
+		/* CLK */
+		at91_set_B_periph(AT91_PIN_PA2, 0);
+
+		/* CMD */
+		at91_set_B_periph(AT91_PIN_PA1, 1);
+
+		/* DAT0, maybe DAT1..DAT3 */
+		at91_set_B_periph(AT91_PIN_PA0, 1);
+		if (data->slot[0].bus_width == 4) {
+			at91_set_B_periph(AT91_PIN_PA4, 1);
+			at91_set_B_periph(AT91_PIN_PA5, 1);
+			at91_set_B_periph(AT91_PIN_PA6, 1);
+		}
 
-	mmc_data = *data;
-	platform_device_register(&at91sam9261_mmc_device);
+		mmc_data = *data;
+		platform_device_register(&at91sam9261_mmc_device);
+	}
 }
 #else
-void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {}
+void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data) {}
 #endif
 
 
@@ -317,7 +317,6 @@ static struct resource twi_resources[] = {
 };
 
 static struct platform_device at91sam9261_twi_device = {
-	.name		= "at91_i2c",
 	.id		= -1,
 	.resource	= twi_resources,
 	.num_resources	= ARRAY_SIZE(twi_resources),
@@ -325,12 +324,19 @@ static struct platform_device at91sam9261_twi_device = {
 
 void __init at91_add_device_i2c(struct i2c_board_info *devices, int nr_devices)
 {
+	/* IP version is not the same on 9261 and g10 */
+	if (cpu_is_at91sam9g10()) {
+		at91sam9261_twi_device.name = "i2c-at91sam9g10";
+		/* I2C PIO must not be configured as open-drain on this chip */
+	} else {
+		at91sam9261_twi_device.name = "i2c-at91sam9261";
+		at91_set_multi_drive(AT91_PIN_PA7, 1);
+		at91_set_multi_drive(AT91_PIN_PA8, 1);
+	}
+
 	/* pins used for TWI interface */
 	at91_set_A_periph(AT91_PIN_PA7, 0);		/* TWD */
-	at91_set_multi_drive(AT91_PIN_PA7, 1);
-
 	at91_set_A_periph(AT91_PIN_PA8, 0);		/* TWCK */
-	at91_set_multi_drive(AT91_PIN_PA8, 1);
 
 	i2c_register_board_info(0, devices, nr_devices);
 	platform_device_register(&at91sam9261_twi_device);
diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c
index 84b3810..6a01d03 100644
--- a/arch/arm/mach-at91/at91sam9263.c
+++ b/arch/arm/mach-at91/at91sam9263.c
@@ -188,11 +188,12 @@ static struct clk_lookup periph_clocks_lookups[] = {
 	CLKDEV_CON_ID("hclk", &macb_clk),
 	CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
 	CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
-	CLKDEV_CON_DEV_ID("mci_clk", "at91_mci.0", &mmc0_clk),
-	CLKDEV_CON_DEV_ID("mci_clk", "at91_mci.1", &mmc1_clk),
+	CLKDEV_CON_DEV_ID("mci_clk", "atmel_mci.0", &mmc0_clk),
+	CLKDEV_CON_DEV_ID("mci_clk", "atmel_mci.1", &mmc1_clk),
 	CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.0", &spi0_clk),
 	CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.1", &spi1_clk),
 	CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tcb_clk),
+	CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9260", &twi_clk),
 	/* fake hclk clock */
 	CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk),
 	CLKDEV_CON_ID("pioA", &pioA_clk),
@@ -210,6 +211,7 @@ static struct clk_lookup periph_clocks_lookups[] = {
 	CLKDEV_CON_DEV_ID("hclk", "a00000.ohci", &ohci_clk),
 	CLKDEV_CON_DEV_ID("spi_clk", "fffa4000.spi", &spi0_clk),
 	CLKDEV_CON_DEV_ID("spi_clk", "fffa8000.spi", &spi1_clk),
+	CLKDEV_CON_DEV_ID(NULL, "fff88000.i2c", &twi_clk),
 };
 
 static struct clk_lookup usart_clocks_lookups[] = {
diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
index 9b6ca73..8dde220 100644
--- a/arch/arm/mach-at91/at91sam9263_devices.c
+++ b/arch/arm/mach-at91/at91sam9263_devices.c
@@ -218,9 +218,9 @@ void __init at91_add_device_eth(struct macb_platform_data *data) {}
  *  MMC / SD
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_MMC_AT91) || defined(CONFIG_MMC_AT91_MODULE)
+#if IS_ENABLED(CONFIG_MMC_ATMELMCI)
 static u64 mmc_dmamask = DMA_BIT_MASK(32);
-static struct at91_mmc_data mmc0_data, mmc1_data;
+static struct mci_platform_data mmc0_data, mmc1_data;
 
 static struct resource mmc0_resources[] = {
 	[0] = {
@@ -236,7 +236,7 @@ static struct resource mmc0_resources[] = {
 };
 
 static struct platform_device at91sam9263_mmc0_device = {
-	.name		= "at91_mci",
+	.name		= "atmel_mci",
 	.id		= 0,
 	.dev		= {
 				.dma_mask		= &mmc_dmamask,
@@ -261,7 +261,7 @@ static struct resource mmc1_resources[] = {
 };
 
 static struct platform_device at91sam9263_mmc1_device = {
-	.name		= "at91_mci",
+	.name		= "atmel_mci",
 	.id		= 1,
 	.dev		= {
 				.dma_mask		= &mmc_dmamask,
@@ -272,85 +272,110 @@ static struct platform_device at91sam9263_mmc1_device = {
 	.num_resources	= ARRAY_SIZE(mmc1_resources),
 };
 
-void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data)
+void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data)
 {
+	unsigned int i;
+	unsigned int slot_count = 0;
+
 	if (!data)
 		return;
 
-	/* input/irq */
-	if (gpio_is_valid(data->det_pin)) {
-		at91_set_gpio_input(data->det_pin, 1);
-		at91_set_deglitch(data->det_pin, 1);
-	}
-	if (gpio_is_valid(data->wp_pin))
-		at91_set_gpio_input(data->wp_pin, 1);
-	if (gpio_is_valid(data->vcc_pin))
-		at91_set_gpio_output(data->vcc_pin, 0);
+	for (i = 0; i < ATMCI_MAX_NR_SLOTS; i++) {
 
-	if (mmc_id == 0) {		/* MCI0 */
-		/* CLK */
-		at91_set_A_periph(AT91_PIN_PA12, 0);
+		if (!data->slot[i].bus_width)
+			continue;
 
-		if (data->slot_b) {
-			/* CMD */
-			at91_set_A_periph(AT91_PIN_PA16, 1);
+		/* input/irq */
+		if (gpio_is_valid(data->slot[i].detect_pin)) {
+			at91_set_gpio_input(data->slot[i].detect_pin,
+					1);
+			at91_set_deglitch(data->slot[i].detect_pin,
+					1);
+		}
+		if (gpio_is_valid(data->slot[i].wp_pin))
+			at91_set_gpio_input(data->slot[i].wp_pin, 1);
+
+		if (mmc_id == 0) {				/* MCI0 */
+			switch (i) {
+			case 0:					/* slot A */
+				/* CMD */
+				at91_set_A_periph(AT91_PIN_PA1, 1);
+				/* DAT0, maybe DAT1..DAT3 */
+				at91_set_A_periph(AT91_PIN_PA0, 1);
+				if (data->slot[i].bus_width == 4) {
+					at91_set_A_periph(AT91_PIN_PA3, 1);
+					at91_set_A_periph(AT91_PIN_PA4, 1);
+					at91_set_A_periph(AT91_PIN_PA5, 1);
+				}
+				slot_count++;
+				break;
+			case 1:					/* slot B */
+				/* CMD */
+				at91_set_A_periph(AT91_PIN_PA16, 1);
+				/* DAT0, maybe DAT1..DAT3 */
+				at91_set_A_periph(AT91_PIN_PA17, 1);
+				if (data->slot[i].bus_width == 4) {
+					at91_set_A_periph(AT91_PIN_PA18, 1);
+					at91_set_A_periph(AT91_PIN_PA19, 1);
+					at91_set_A_periph(AT91_PIN_PA20, 1);
+				}
+				slot_count++;
+				break;
+			default:
+				printk(KERN_ERR
+				       "AT91: SD/MMC slot %d not available\n", i);
+				break;
+			}
+			if (slot_count) {
+				/* CLK */
+				at91_set_A_periph(AT91_PIN_PA12, 0);
 
-			/* DAT0, maybe DAT1..DAT3 */
-			at91_set_A_periph(AT91_PIN_PA17, 1);
-			if (data->wire4) {
-				at91_set_A_periph(AT91_PIN_PA18, 1);
-				at91_set_A_periph(AT91_PIN_PA19, 1);
-				at91_set_A_periph(AT91_PIN_PA20, 1);
+				mmc0_data = *data;
+				platform_device_register(&at91sam9263_mmc0_device);
 			}
-		} else {
-			/* CMD */
-			at91_set_A_periph(AT91_PIN_PA1, 1);
-
-			/* DAT0, maybe DAT1..DAT3 */
-			at91_set_A_periph(AT91_PIN_PA0, 1);
-			if (data->wire4) {
-				at91_set_A_periph(AT91_PIN_PA3, 1);
-				at91_set_A_periph(AT91_PIN_PA4, 1);
-				at91_set_A_periph(AT91_PIN_PA5, 1);
+		} else if (mmc_id == 1) {			/* MCI1 */
+			switch (i) {
+			case 0:					/* slot A */
+				/* CMD */
+				at91_set_A_periph(AT91_PIN_PA7, 1);
+				/* DAT0, maybe DAT1..DAT3 */
+				at91_set_A_periph(AT91_PIN_PA8, 1);
+				if (data->slot[i].bus_width == 4) {
+					at91_set_A_periph(AT91_PIN_PA9, 1);
+					at91_set_A_periph(AT91_PIN_PA10, 1);
+					at91_set_A_periph(AT91_PIN_PA11, 1);
+				}
+				slot_count++;
+				break;
+			case 1:					/* slot B */
+				/* CMD */
+				at91_set_A_periph(AT91_PIN_PA21, 1);
+				/* DAT0, maybe DAT1..DAT3 */
+				at91_set_A_periph(AT91_PIN_PA22, 1);
+				if (data->slot[i].bus_width == 4) {
+					at91_set_A_periph(AT91_PIN_PA23, 1);
+					at91_set_A_periph(AT91_PIN_PA24, 1);
+					at91_set_A_periph(AT91_PIN_PA25, 1);
+				}
+				slot_count++;
+				break;
+			default:
+				printk(KERN_ERR
+				       "AT91: SD/MMC slot %d not available\n", i);
+				break;
 			}
-		}
+			if (slot_count) {
+				/* CLK */
+				at91_set_A_periph(AT91_PIN_PA6, 0);
 
-		mmc0_data = *data;
-		platform_device_register(&at91sam9263_mmc0_device);
-	} else {			/* MCI1 */
-		/* CLK */
-		at91_set_A_periph(AT91_PIN_PA6, 0);
-
-		if (data->slot_b) {
-			/* CMD */
-			at91_set_A_periph(AT91_PIN_PA21, 1);
-
-			/* DAT0, maybe DAT1..DAT3 */
-			at91_set_A_periph(AT91_PIN_PA22, 1);
-			if (data->wire4) {
-				at91_set_A_periph(AT91_PIN_PA23, 1);
-				at91_set_A_periph(AT91_PIN_PA24, 1);
-				at91_set_A_periph(AT91_PIN_PA25, 1);
-			}
-		} else {
-			/* CMD */
-			at91_set_A_periph(AT91_PIN_PA7, 1);
-
-			/* DAT0, maybe DAT1..DAT3 */
-			at91_set_A_periph(AT91_PIN_PA8, 1);
-			if (data->wire4) {
-				at91_set_A_periph(AT91_PIN_PA9, 1);
-				at91_set_A_periph(AT91_PIN_PA10, 1);
-				at91_set_A_periph(AT91_PIN_PA11, 1);
+				mmc1_data = *data;
+				platform_device_register(&at91sam9263_mmc1_device);
 			}
 		}
-
-		mmc1_data = *data;
-		platform_device_register(&at91sam9263_mmc1_device);
 	}
 }
 #else
-void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {}
+void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data) {}
 #endif
 
 /* --------------------------------------------------------------------
@@ -574,7 +599,7 @@ static struct resource twi_resources[] = {
 };
 
 static struct platform_device at91sam9263_twi_device = {
-	.name		= "at91_i2c",
+	.name		= "i2c-at91sam9260",
 	.id		= -1,
 	.resource	= twi_resources,
 	.num_resources	= ARRAY_SIZE(twi_resources),
diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-at91/at91sam9g45.c
index ef6cedd..84af1b5 100644
--- a/arch/arm/mach-at91/at91sam9g45.c
+++ b/arch/arm/mach-at91/at91sam9g45.c
@@ -237,6 +237,8 @@ static struct clk_lookup periph_clocks_lookups[] = {
 	CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.1", &spi1_clk),
 	CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tcb0_clk),
 	CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.1", &tcb0_clk),
+	CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g10.0", &twi0_clk),
+	CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g10.1", &twi1_clk),
 	CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
 	CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
 	CLKDEV_CON_DEV_ID(NULL, "atmel-trng", &trng_clk),
@@ -254,6 +256,8 @@ static struct clk_lookup periph_clocks_lookups[] = {
 	CLKDEV_CON_DEV_ID("t0_clk", "fffd4000.timer", &tcb0_clk),
 	CLKDEV_CON_DEV_ID("hclk", "700000.ohci", &uhphs_clk),
 	CLKDEV_CON_DEV_ID("ehci_clk", "800000.ehci", &uhphs_clk),
+	CLKDEV_CON_DEV_ID(NULL, "fff84000.i2c", &twi0_clk),
+	CLKDEV_CON_DEV_ID(NULL, "fff88000.i2c", &twi1_clk),
 	/* fake hclk clock */
 	CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &uhphs_clk),
 	CLKDEV_CON_ID("pioA", &pioA_clk),
diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c
index 1b47319..b159607 100644
--- a/arch/arm/mach-at91/at91sam9g45_devices.c
+++ b/arch/arm/mach-at91/at91sam9g45_devices.c
@@ -31,7 +31,7 @@
 #include <mach/at91sam9g45_matrix.h>
 #include <mach/at91_matrix.h>
 #include <mach/at91sam9_smc.h>
-#include <mach/at_hdmac.h>
+#include <linux/platform_data/dma-atmel.h>
 #include <mach/atmel-mci.h>
 
 #include <media/atmel-isi.h>
@@ -653,7 +653,7 @@ static struct resource twi0_resources[] = {
 };
 
 static struct platform_device at91sam9g45_twi0_device = {
-	.name		= "at91_i2c",
+	.name		= "i2c-at91sam9g10",
 	.id		= 0,
 	.resource	= twi0_resources,
 	.num_resources	= ARRAY_SIZE(twi0_resources),
@@ -673,7 +673,7 @@ static struct resource twi1_resources[] = {
 };
 
 static struct platform_device at91sam9g45_twi1_device = {
-	.name		= "at91_i2c",
+	.name		= "i2c-at91sam9g10",
 	.id		= 1,
 	.resource	= twi1_resources,
 	.num_resources	= ARRAY_SIZE(twi1_resources),
@@ -686,18 +686,12 @@ void __init at91_add_device_i2c(short i2c_id, struct i2c_board_info *devices, in
 	/* pins used for TWI interface */
 	if (i2c_id == 0) {
 		at91_set_A_periph(AT91_PIN_PA20, 0);		/* TWD */
-		at91_set_multi_drive(AT91_PIN_PA20, 1);
-
 		at91_set_A_periph(AT91_PIN_PA21, 0);		/* TWCK */
-		at91_set_multi_drive(AT91_PIN_PA21, 1);
 
 		platform_device_register(&at91sam9g45_twi0_device);
 	} else {
 		at91_set_A_periph(AT91_PIN_PB10, 0);		/* TWD */
-		at91_set_multi_drive(AT91_PIN_PB10, 1);
-
 		at91_set_A_periph(AT91_PIN_PB11, 0);		/* TWCK */
-		at91_set_multi_drive(AT91_PIN_PB11, 1);
 
 		platform_device_register(&at91sam9g45_twi1_device);
 	}
diff --git a/arch/arm/mach-at91/at91sam9n12.c b/arch/arm/mach-at91/at91sam9n12.c
index 0849466..732d3d3 100644
--- a/arch/arm/mach-at91/at91sam9n12.c
+++ b/arch/arm/mach-at91/at91sam9n12.c
@@ -169,6 +169,8 @@ static struct clk_lookup periph_clocks_lookups[] = {
 	CLKDEV_CON_DEV_ID("t0_clk", "f8008000.timer", &tcb_clk),
 	CLKDEV_CON_DEV_ID("t0_clk", "f800c000.timer", &tcb_clk),
 	CLKDEV_CON_DEV_ID("dma_clk", "ffffec00.dma-controller", &dma_clk),
+	CLKDEV_CON_DEV_ID(NULL, "f8010000.i2c", &twi0_clk),
+	CLKDEV_CON_DEV_ID(NULL, "f8014000.i2c", &twi1_clk),
 	CLKDEV_CON_ID("pioA", &pioAB_clk),
 	CLKDEV_CON_ID("pioB", &pioAB_clk),
 	CLKDEV_CON_ID("pioC", &pioCD_clk),
diff --git a/arch/arm/mach-at91/at91sam9rl.c b/arch/arm/mach-at91/at91sam9rl.c
index 72ce50a..72e9084 100644
--- a/arch/arm/mach-at91/at91sam9rl.c
+++ b/arch/arm/mach-at91/at91sam9rl.c
@@ -186,6 +186,8 @@ static struct clk_lookup periph_clocks_lookups[] = {
 	CLKDEV_CON_DEV_ID("t2_clk", "atmel_tcb.0", &tc2_clk),
 	CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
 	CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
+	CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g20.0", &twi0_clk),
+	CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g20.1", &twi1_clk),
 	CLKDEV_CON_ID("pioA", &pioA_clk),
 	CLKDEV_CON_ID("pioB", &pioB_clk),
 	CLKDEV_CON_ID("pioC", &pioC_clk),
diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c
index b3d365d..d6ca054 100644
--- a/arch/arm/mach-at91/at91sam9rl_devices.c
+++ b/arch/arm/mach-at91/at91sam9rl_devices.c
@@ -22,7 +22,7 @@
 #include <mach/at91sam9rl_matrix.h>
 #include <mach/at91_matrix.h>
 #include <mach/at91sam9_smc.h>
-#include <mach/at_hdmac.h>
+#include <linux/platform_data/dma-atmel.h>
 
 #include "generic.h"
 
@@ -161,9 +161,9 @@ void __init at91_add_device_usba(struct usba_platform_data *data) {}
  *  MMC / SD
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_MMC_AT91) || defined(CONFIG_MMC_AT91_MODULE)
+#if IS_ENABLED(CONFIG_MMC_ATMELMCI)
 static u64 mmc_dmamask = DMA_BIT_MASK(32);
-static struct at91_mmc_data mmc_data;
+static struct mci_platform_data mmc_data;
 
 static struct resource mmc_resources[] = {
 	[0] = {
@@ -179,7 +179,7 @@ static struct resource mmc_resources[] = {
 };
 
 static struct platform_device at91sam9rl_mmc_device = {
-	.name		= "at91_mci",
+	.name		= "atmel_mci",
 	.id		= -1,
 	.dev		= {
 				.dma_mask		= &mmc_dmamask,
@@ -190,40 +190,40 @@ static struct platform_device at91sam9rl_mmc_device = {
 	.num_resources	= ARRAY_SIZE(mmc_resources),
 };
 
-void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data)
+void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data)
 {
 	if (!data)
 		return;
 
-	/* input/irq */
-	if (gpio_is_valid(data->det_pin)) {
-		at91_set_gpio_input(data->det_pin, 1);
-		at91_set_deglitch(data->det_pin, 1);
-	}
-	if (gpio_is_valid(data->wp_pin))
-		at91_set_gpio_input(data->wp_pin, 1);
-	if (gpio_is_valid(data->vcc_pin))
-		at91_set_gpio_output(data->vcc_pin, 0);
-
-	/* CLK */
-	at91_set_A_periph(AT91_PIN_PA2, 0);
-
-	/* CMD */
-	at91_set_A_periph(AT91_PIN_PA1, 1);
-
-	/* DAT0, maybe DAT1..DAT3 */
-	at91_set_A_periph(AT91_PIN_PA0, 1);
-	if (data->wire4) {
-		at91_set_A_periph(AT91_PIN_PA3, 1);
-		at91_set_A_periph(AT91_PIN_PA4, 1);
-		at91_set_A_periph(AT91_PIN_PA5, 1);
+	if (data->slot[0].bus_width) {
+		/* input/irq */
+		if (gpio_is_valid(data->slot[0].detect_pin)) {
+			at91_set_gpio_input(data->slot[0].detect_pin, 1);
+			at91_set_deglitch(data->slot[0].detect_pin, 1);
+		}
+		if (gpio_is_valid(data->slot[0].wp_pin))
+			at91_set_gpio_input(data->slot[0].wp_pin, 1);
+
+		/* CLK */
+		at91_set_A_periph(AT91_PIN_PA2, 0);
+
+		/* CMD */
+		at91_set_A_periph(AT91_PIN_PA1, 1);
+
+		/* DAT0, maybe DAT1..DAT3 */
+		at91_set_A_periph(AT91_PIN_PA0, 1);
+		if (data->slot[0].bus_width == 4) {
+			at91_set_A_periph(AT91_PIN_PA3, 1);
+			at91_set_A_periph(AT91_PIN_PA4, 1);
+			at91_set_A_periph(AT91_PIN_PA5, 1);
+		}
+
+		mmc_data = *data;
+		platform_device_register(&at91sam9rl_mmc_device);
 	}
-
-	mmc_data = *data;
-	platform_device_register(&at91sam9rl_mmc_device);
 }
 #else
-void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {}
+void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data) {}
 #endif
 
 
@@ -346,7 +346,7 @@ static struct resource twi_resources[] = {
 };
 
 static struct platform_device at91sam9rl_twi_device = {
-	.name		= "at91_i2c",
+	.name		= "i2c-at91sam9g20",
 	.id		= -1,
 	.resource	= twi_resources,
 	.num_resources	= ARRAY_SIZE(twi_resources),
diff --git a/arch/arm/mach-at91/at91sam9x5.c b/arch/arm/mach-at91/at91sam9x5.c
index 477cf9d..e503538 100644
--- a/arch/arm/mach-at91/at91sam9x5.c
+++ b/arch/arm/mach-at91/at91sam9x5.c
@@ -231,6 +231,9 @@ static struct clk_lookup periph_clocks_lookups[] = {
 	CLKDEV_CON_DEV_ID("t0_clk", "f800c000.timer", &tcb0_clk),
 	CLKDEV_CON_DEV_ID("dma_clk", "ffffec00.dma-controller", &dma0_clk),
 	CLKDEV_CON_DEV_ID("dma_clk", "ffffee00.dma-controller", &dma1_clk),
+	CLKDEV_CON_DEV_ID(NULL, "f8010000.i2c", &twi0_clk),
+	CLKDEV_CON_DEV_ID(NULL, "f8014000.i2c", &twi1_clk),
+	CLKDEV_CON_DEV_ID(NULL, "f8018000.i2c", &twi2_clk),
 	CLKDEV_CON_ID("pioA", &pioAB_clk),
 	CLKDEV_CON_ID("pioB", &pioAB_clk),
 	CLKDEV_CON_ID("pioC", &pioCD_clk),
diff --git a/arch/arm/mach-at91/at91x40.c b/arch/arm/mach-at91/at91x40.c
index 46090e6..6bd7300 100644
--- a/arch/arm/mach-at91/at91x40.c
+++ b/arch/arm/mach-at91/at91x40.c
@@ -47,7 +47,7 @@ static void at91x40_idle(void)
 	 * Disable the processor clock.  The processor will be automatically
 	 * re-enabled by an interrupt or by a reset.
 	 */
-	__raw_writel(AT91_PS_CR_CPU, AT91_PS_CR);
+	__raw_writel(AT91_PS_CR_CPU, AT91_IO_P2V(AT91_PS_CR));
 	cpu_do_idle();
 }
 
diff --git a/arch/arm/mach-at91/at91x40_time.c b/arch/arm/mach-at91/at91x40_time.c
index 6ca680a..ee06d7b 100644
--- a/arch/arm/mach-at91/at91x40_time.c
+++ b/arch/arm/mach-at91/at91x40_time.c
@@ -29,10 +29,10 @@
 #include <mach/at91_tc.h>
 
 #define at91_tc_read(field) \
-	__raw_readl(AT91_TC + field)
+	__raw_readl(AT91_IO_P2V(AT91_TC) + field)
 
 #define at91_tc_write(field, value) \
-	__raw_writel(value, AT91_TC + field);
+	__raw_writel(value, AT91_IO_P2V(AT91_TC) + field);
 
 /*
  *	3 counter/timer units present.
diff --git a/arch/arm/mach-at91/board-afeb-9260v1.c b/arch/arm/mach-at91/board-afeb-9260v1.c
index de7be19..93a832f 100644
--- a/arch/arm/mach-at91/board-afeb-9260v1.c
+++ b/arch/arm/mach-at91/board-afeb-9260v1.c
@@ -133,12 +133,12 @@ static struct atmel_nand_data __initdata afeb9260_nand_data = {
 /*
  * MCI (SD/MMC)
  */
-static struct at91_mmc_data __initdata afeb9260_mmc_data = {
-	.det_pin 	= AT91_PIN_PC9,
-	.wp_pin 	= AT91_PIN_PC4,
-	.slot_b		= 1,
-	.wire4		= 1,
-	.vcc_pin	= -EINVAL,
+static struct mci_platform_data __initdata afeb9260_mci0_data = {
+	.slot[1] = {
+		.bus_width	= 4,
+		.detect_pin	= AT91_PIN_PC9,
+		.wp_pin		= AT91_PIN_PC4,
+	},
 };
 
 
@@ -199,7 +199,7 @@ static void __init afeb9260_board_init(void)
 	at91_set_B_periph(AT91_PIN_PA10, 0);	/* ETX2 */
 	at91_set_B_periph(AT91_PIN_PA11, 0);	/* ETX3 */
 	/* MMC */
-	at91_add_device_mmc(0, &afeb9260_mmc_data);
+	at91_add_device_mci(0, &afeb9260_mci0_data);
 	/* I2C */
 	at91_add_device_i2c(afeb9260_i2c_devices,
 			ARRAY_SIZE(afeb9260_i2c_devices));
diff --git a/arch/arm/mach-at91/board-carmeva.c b/arch/arm/mach-at91/board-carmeva.c
index a5b002f..71d8f36 100644
--- a/arch/arm/mach-at91/board-carmeva.c
+++ b/arch/arm/mach-at91/board-carmeva.c
@@ -71,12 +71,12 @@ static struct at91_udc_data __initdata carmeva_udc_data = {
 	// .vcc_pin	= -EINVAL,
 // };
 
-static struct at91_mmc_data __initdata carmeva_mmc_data = {
-	.slot_b		= 0,
-	.wire4		= 1,
-	.det_pin	= AT91_PIN_PB10,
-	.wp_pin		= AT91_PIN_PC14,
-	.vcc_pin	= -EINVAL,
+static struct mci_platform_data __initdata carmeva_mci0_data = {
+	.slot[0] = {
+		.bus_width	= 4,
+		.detect_pin	= AT91_PIN_PB10,
+		.wp_pin		= AT91_PIN_PC14,
+	},
 };
 
 static struct spi_board_info carmeva_spi_devices[] = {
@@ -150,7 +150,7 @@ static void __init carmeva_board_init(void)
 	/* Compact Flash */
 //	at91_add_device_cf(&carmeva_cf_data);
 	/* MMC */
-	at91_add_device_mmc(0, &carmeva_mmc_data);
+	at91_add_device_mci(0, &carmeva_mci0_data);
 	/* LEDs */
 	at91_gpio_leds(carmeva_leds, ARRAY_SIZE(carmeva_leds));
 }
diff --git a/arch/arm/mach-at91/board-cpu9krea.c b/arch/arm/mach-at91/board-cpu9krea.c
index ecbc13b..e71c473 100644
--- a/arch/arm/mach-at91/board-cpu9krea.c
+++ b/arch/arm/mach-at91/board-cpu9krea.c
@@ -254,8 +254,7 @@ static struct gpio_led cpu9krea_leds[] = {
 
 static struct i2c_board_info __initdata cpu9krea_i2c_devices[] = {
 	{
-		I2C_BOARD_INFO("rtc-ds1307", 0x68),
-		.type	= "ds1339",
+		I2C_BOARD_INFO("ds1339", 0x68),
 	},
 };
 
@@ -312,12 +311,12 @@ static void __init cpu9krea_add_device_buttons(void)
 /*
  * MCI (SD/MMC)
  */
-static struct at91_mmc_data __initdata cpu9krea_mmc_data = {
-	.slot_b		= 0,
-	.wire4		= 1,
-	.det_pin	= AT91_PIN_PA29,
-	.wp_pin		= -EINVAL,
-	.vcc_pin	= -EINVAL,
+static struct mci_platform_data __initdata cpu9krea_mci0_data = {
+	.slot[0] = {
+		.bus_width	= 4,
+		.detect_pin	= AT91_PIN_PA29,
+		.wp_pin		= -EINVAL,
+	},
 };
 
 static void __init cpu9krea_board_init(void)
@@ -359,7 +358,7 @@ static void __init cpu9krea_board_init(void)
 	/* Ethernet */
 	at91_add_device_eth(&cpu9krea_macb_data);
 	/* MMC */
-	at91_add_device_mmc(0, &cpu9krea_mmc_data);
+	at91_add_device_mci(0, &cpu9krea_mci0_data);
 	/* I2C */
 	at91_add_device_i2c(cpu9krea_i2c_devices,
 		ARRAY_SIZE(cpu9krea_i2c_devices));
diff --git a/arch/arm/mach-at91/board-cpuat91.c b/arch/arm/mach-at91/board-cpuat91.c
index 2e6d043..2cbd1a2 100644
--- a/arch/arm/mach-at91/board-cpuat91.c
+++ b/arch/arm/mach-at91/board-cpuat91.c
@@ -78,11 +78,12 @@ static struct at91_udc_data __initdata cpuat91_udc_data = {
 	.pullup_pin	= AT91_PIN_PC14,
 };
 
-static struct at91_mmc_data __initdata cpuat91_mmc_data = {
-	.det_pin	= AT91_PIN_PC2,
-	.wire4		= 1,
-	.wp_pin		= -EINVAL,
-	.vcc_pin	= -EINVAL,
+static struct mci_platform_data __initdata cpuat91_mci0_data = {
+	.slot[0] = {
+		.bus_width	= 4,
+		.detect_pin	= AT91_PIN_PC2,
+		.wp_pin		= -EINVAL,
+	},
 };
 
 static struct physmap_flash_data cpuat91_flash_data = {
@@ -168,7 +169,7 @@ static void __init cpuat91_board_init(void)
 	/* USB Device */
 	at91_add_device_udc(&cpuat91_udc_data);
 	/* MMC */
-	at91_add_device_mmc(0, &cpuat91_mmc_data);
+	at91_add_device_mci(0, &cpuat91_mci0_data);
 	/* I2C */
 	at91_add_device_i2c(NULL, 0);
 	/* Platform devices */
diff --git a/arch/arm/mach-at91/board-csb337.c b/arch/arm/mach-at91/board-csb337.c
index 462bc31..3e37437 100644
--- a/arch/arm/mach-at91/board-csb337.c
+++ b/arch/arm/mach-at91/board-csb337.c
@@ -87,12 +87,12 @@ static struct at91_cf_data __initdata csb337_cf_data = {
 	.rst_pin	= AT91_PIN_PD2,
 };
 
-static struct at91_mmc_data __initdata csb337_mmc_data = {
-	.det_pin	= AT91_PIN_PD5,
-	.slot_b		= 0,
-	.wire4		= 1,
-	.wp_pin		= AT91_PIN_PD6,
-	.vcc_pin	= -EINVAL,
+static struct mci_platform_data __initdata csb337_mci0_data = {
+	.slot[0] = {
+		.bus_width	= 4,
+		.detect_pin	= AT91_PIN_PD5,
+		.wp_pin		= AT91_PIN_PD6,
+	},
 };
 
 static struct spi_board_info csb337_spi_devices[] = {
@@ -220,8 +220,6 @@ static struct gpio_led csb_leds[] = {
 
 static void __init csb337_board_init(void)
 {
-	/* Setup the LEDs */
-	at91_init_leds(AT91_PIN_PB0, AT91_PIN_PB1);
 	/* Serial */
 	/* DBGU on ttyS0 */
 	at91_register_uart(0, 0, 0);
@@ -240,7 +238,7 @@ static void __init csb337_board_init(void)
 	/* SPI */
 	at91_add_device_spi(csb337_spi_devices, ARRAY_SIZE(csb337_spi_devices));
 	/* MMC */
-	at91_add_device_mmc(0, &csb337_mmc_data);
+	at91_add_device_mci(0, &csb337_mci0_data);
 	/* NOR flash */
 	platform_device_register(&csb_flash);
 	/* LEDs */
diff --git a/arch/arm/mach-at91/board-eb9200.c b/arch/arm/mach-at91/board-eb9200.c
index d1e1f3f..0cfac16 100644
--- a/arch/arm/mach-at91/board-eb9200.c
+++ b/arch/arm/mach-at91/board-eb9200.c
@@ -70,12 +70,12 @@ static struct at91_cf_data __initdata eb9200_cf_data = {
 	.rst_pin	= AT91_PIN_PC5,
 };
 
-static struct at91_mmc_data __initdata eb9200_mmc_data = {
-	.slot_b		= 0,
-	.wire4		= 1,
-	.det_pin	= -EINVAL,
-	.wp_pin		= -EINVAL,
-	.vcc_pin	= -EINVAL,
+static struct mci_platform_data __initdata eb9200_mci0_data = {
+	.slot[0] = {
+		.bus_width	= 4,
+		.detect_pin	= -EINVAL,
+		.wp_pin		= -EINVAL,
+	},
 };
 
 static struct i2c_board_info __initdata eb9200_i2c_devices[] = {
@@ -113,7 +113,7 @@ static void __init eb9200_board_init(void)
 	at91_add_device_spi(NULL, 0);
 	/* MMC */
 	/* only supports 1 or 4 bit interface, not wired through to SPI */
-	at91_add_device_mmc(0, &eb9200_mmc_data);
+	at91_add_device_mci(0, &eb9200_mci0_data);
 }
 
 MACHINE_START(ATEB9200, "Embest ATEB9200")
diff --git a/arch/arm/mach-at91/board-ecbat91.c b/arch/arm/mach-at91/board-ecbat91.c
index 9c24cb2..3d931ff 100644
--- a/arch/arm/mach-at91/board-ecbat91.c
+++ b/arch/arm/mach-at91/board-ecbat91.c
@@ -64,12 +64,12 @@ static struct at91_usbh_data __initdata ecb_at91usbh_data = {
 	.overcurrent_pin= {-EINVAL, -EINVAL},
 };
 
-static struct at91_mmc_data __initdata ecb_at91mmc_data = {
-	.slot_b		= 0,
-	.wire4		= 1,
-	.det_pin	= -EINVAL,
-	.wp_pin		= -EINVAL,
-	.vcc_pin	= -EINVAL,
+static struct mci_platform_data __initdata ecbat91_mci0_data = {
+	.slot[0] = {
+		.bus_width	= 4,
+		.detect_pin	= -EINVAL,
+		.wp_pin		= -EINVAL,
+	},
 };
 
 
@@ -138,11 +138,20 @@ static struct spi_board_info __initdata ecb_at91spi_devices[] = {
 	},
 };
 
+/*
+ * LEDs
+ */
+static struct gpio_led ecb_leds[] = {
+	{	/* D1 */
+		.name			= "led1",
+		.gpio			= AT91_PIN_PC7,
+		.active_low		= 1,
+		.default_trigger	= "heartbeat",
+	}
+};
+
 static void __init ecb_at91board_init(void)
 {
-	/* Setup the LEDs */
-	at91_init_leds(AT91_PIN_PC7, AT91_PIN_PC7);
-
 	/* Serial */
 	/* DBGU on ttyS0. (Rx & Tx only) */
 	at91_register_uart(0, 0, 0);
@@ -161,10 +170,13 @@ static void __init ecb_at91board_init(void)
 	at91_add_device_i2c(NULL, 0);
 
 	/* MMC */
-	at91_add_device_mmc(0, &ecb_at91mmc_data);
+	at91_add_device_mci(0, &ecbat91_mci0_data);
 
 	/* SPI */
 	at91_add_device_spi(ecb_at91spi_devices, ARRAY_SIZE(ecb_at91spi_devices));
+
+	/* LEDs */
+	at91_gpio_leds(ecb_leds, ARRAY_SIZE(ecb_leds));
 }
 
 MACHINE_START(ECBAT91, "emQbit's ECB_AT91")
diff --git a/arch/arm/mach-at91/board-eco920.c b/arch/arm/mach-at91/board-eco920.c
index 82bdfde..d93658a 100644
--- a/arch/arm/mach-at91/board-eco920.c
+++ b/arch/arm/mach-at91/board-eco920.c
@@ -56,12 +56,12 @@ static struct at91_udc_data __initdata eco920_udc_data = {
 	.pullup_pin	= AT91_PIN_PB13,
 };
 
-static struct at91_mmc_data __initdata eco920_mmc_data = {
-	.slot_b		= 0,
-	.wire4		= 0,
-	.det_pin	= -EINVAL,
-	.wp_pin		= -EINVAL,
-	.vcc_pin	= -EINVAL,
+static struct mci_platform_data __initdata eco920_mci0_data = {
+	.slot[0] = {
+		.bus_width	= 1,
+		.detect_pin	= -EINVAL,
+		.wp_pin		= -EINVAL,
+	},
 };
 
 static struct physmap_flash_data eco920_flash_data = {
@@ -93,10 +93,26 @@ static struct spi_board_info eco920_spi_devices[] = {
 	},
 };
 
+/*
+ * LEDs
+ */
+static struct gpio_led eco920_leds[] = {
+	{       /* D1 */
+		.name                   = "led1",
+		.gpio                   = AT91_PIN_PB0,
+		.active_low             = 1,
+		.default_trigger        = "heartbeat",
+	},
+	{       /* D2 */
+		.name                   = "led2",
+		.gpio                   = AT91_PIN_PB1,
+		.active_low             = 1,
+		.default_trigger        = "timer",
+	}
+};
+
 static void __init eco920_board_init(void)
 {
-	/* Setup the LEDs */
-	at91_init_leds(AT91_PIN_PB0, AT91_PIN_PB1);
 	/* DBGU on ttyS0. (Rx & Tx only */
 	at91_register_uart(0, 0, 0);
 	at91_add_device_serial();
@@ -104,7 +120,7 @@ static void __init eco920_board_init(void)
 	at91_add_device_usbh(&eco920_usbh_data);
 	at91_add_device_udc(&eco920_udc_data);
 
-	at91_add_device_mmc(0, &eco920_mmc_data);
+	at91_add_device_mci(0, &eco920_mci0_data);
 	platform_device_register(&eco920_flash);
 
 	at91_ramc_write(0, AT91_SMC_CSR(7),	AT91_SMC_RWHOLD_(1)
@@ -127,6 +143,8 @@ static void __init eco920_board_init(void)
 	);
 
 	at91_add_device_spi(eco920_spi_devices, ARRAY_SIZE(eco920_spi_devices));
+	/* LEDs */
+	at91_gpio_leds(eco920_leds, ARRAY_SIZE(eco920_leds));
 }
 
 MACHINE_START(ECO920, "eco920")
diff --git a/arch/arm/mach-at91/board-flexibity.c b/arch/arm/mach-at91/board-flexibity.c
index 6cc83a8..fa98aba 100644
--- a/arch/arm/mach-at91/board-flexibity.c
+++ b/arch/arm/mach-at91/board-flexibity.c
@@ -75,12 +75,12 @@ static struct spi_board_info flexibity_spi_devices[] = {
 };
 
 /* MCI (SD/MMC) */
-static struct at91_mmc_data __initdata flexibity_mmc_data = {
-	.slot_b		= 0,
-	.wire4		= 1,
-	.det_pin	= AT91_PIN_PC9,
-	.wp_pin		= AT91_PIN_PC4,
-	.vcc_pin	= -EINVAL,
+static struct mci_platform_data __initdata flexibity_mci0_data = {
+	.slot[0] = {
+		.bus_width	= 4,
+		.detect_pin	= AT91_PIN_PC9,
+		.wp_pin		= AT91_PIN_PC4,
+	},
 };
 
 /* LEDs */
@@ -152,7 +152,7 @@ static void __init flexibity_board_init(void)
 	at91_add_device_spi(flexibity_spi_devices,
 		ARRAY_SIZE(flexibity_spi_devices));
 	/* MMC */
-	at91_add_device_mmc(0, &flexibity_mmc_data);
+	at91_add_device_mci(0, &flexibity_mci0_data);
 	/* LEDs */
 	at91_gpio_leds(flexibity_leds, ARRAY_SIZE(flexibity_leds));
 }
diff --git a/arch/arm/mach-at91/board-foxg20.c b/arch/arm/mach-at91/board-foxg20.c
index 69ab124..6e47071 100644
--- a/arch/arm/mach-at91/board-foxg20.c
+++ b/arch/arm/mach-at91/board-foxg20.c
@@ -86,7 +86,7 @@ static struct at91_udc_data __initdata foxg20_udc_data = {
  * SPI devices.
  */
 static struct spi_board_info foxg20_spi_devices[] = {
-#if !defined(CONFIG_MMC_AT91)
+#if !IS_ENABLED(CONFIG_MMC_ATMELMCI)
 	{
 		.modalias	= "mtd_dataflash",
 		.chip_select	= 1,
@@ -109,12 +109,12 @@ static struct macb_platform_data __initdata foxg20_macb_data = {
  * MCI (SD/MMC)
  * det_pin, wp_pin and vcc_pin are not connected
  */
-static struct at91_mmc_data __initdata foxg20_mmc_data = {
-	.slot_b		= 1,
-	.wire4		= 1,
-	.det_pin	= -EINVAL,
-	.wp_pin		= -EINVAL,
-	.vcc_pin	= -EINVAL,
+static struct mci_platform_data __initdata foxg20_mci0_data = {
+	.slot[1] = {
+		.bus_width	= 4,
+		.detect_pin	= -EINVAL,
+		.wp_pin		= -EINVAL,
+	},
 };
 
 
@@ -247,7 +247,7 @@ static void __init foxg20_board_init(void)
 	/* Ethernet */
 	at91_add_device_eth(&foxg20_macb_data);
 	/* MMC */
-	at91_add_device_mmc(0, &foxg20_mmc_data);
+	at91_add_device_mci(0, &foxg20_mci0_data);
 	/* I2C */
 	at91_add_device_i2c(foxg20_i2c_devices, ARRAY_SIZE(foxg20_i2c_devices));
 	/* LEDs */
diff --git a/arch/arm/mach-at91/board-kafa.c b/arch/arm/mach-at91/board-kafa.c
index 64c1dbf..86050da 100644
--- a/arch/arm/mach-at91/board-kafa.c
+++ b/arch/arm/mach-at91/board-kafa.c
@@ -66,11 +66,20 @@ static struct at91_udc_data __initdata kafa_udc_data = {
 	.pullup_pin	= AT91_PIN_PB7,
 };
 
+/*
+ * LEDs
+ */
+static struct gpio_led kafa_leds[] = {
+	{	/* D1 */
+		.name			= "led1",
+		.gpio			= AT91_PIN_PB4,
+		.active_low		= 1,
+		.default_trigger	= "heartbeat",
+	},
+};
+
 static void __init kafa_board_init(void)
 {
-	/* Set up the LEDs */
-	at91_init_leds(AT91_PIN_PB4, AT91_PIN_PB4);
-
 	/* Serial */
 	/* DBGU on ttyS0. (Rx & Tx only) */
 	at91_register_uart(0, 0, 0);
@@ -88,6 +97,8 @@ static void __init kafa_board_init(void)
 	at91_add_device_i2c(NULL, 0);
 	/* SPI */
 	at91_add_device_spi(NULL, 0);
+	/* LEDs */
+	at91_gpio_leds(kafa_leds, ARRAY_SIZE(kafa_leds));
 }
 
 MACHINE_START(KAFA, "Sperry-Sun KAFA")
diff --git a/arch/arm/mach-at91/board-kb9202.c b/arch/arm/mach-at91/board-kb9202.c
index 5d96cb8..abe9fed 100644
--- a/arch/arm/mach-at91/board-kb9202.c
+++ b/arch/arm/mach-at91/board-kb9202.c
@@ -69,12 +69,12 @@ static struct at91_udc_data __initdata kb9202_udc_data = {
 	.pullup_pin	= AT91_PIN_PB22,
 };
 
-static struct at91_mmc_data __initdata kb9202_mmc_data = {
-	.det_pin	= AT91_PIN_PB2,
-	.slot_b		= 0,
-	.wire4		= 1,
-	.wp_pin		= -EINVAL,
-	.vcc_pin	= -EINVAL,
+static struct mci_platform_data __initdata kb9202_mci0_data = {
+	.slot[0] = {
+		.bus_width	= 4,
+		.detect_pin	= AT91_PIN_PB2,
+		.wp_pin		= -EINVAL,
+	},
 };
 
 static struct mtd_partition __initdata kb9202_nand_partition[] = {
@@ -96,11 +96,26 @@ static struct atmel_nand_data __initdata kb9202_nand_data = {
 	.num_parts	= ARRAY_SIZE(kb9202_nand_partition),
 };
 
+/*
+ * LEDs
+ */
+static struct gpio_led kb9202_leds[] = {
+	{	/* D1 */
+		.name			= "led1",
+		.gpio			= AT91_PIN_PC19,
+		.active_low		= 1,
+		.default_trigger	= "heartbeat",
+	},
+	{	/* D2 */
+		.name			= "led2",
+		.gpio			= AT91_PIN_PC18,
+		.active_low		= 1,
+		.default_trigger	= "timer",
+	}
+};
+
 static void __init kb9202_board_init(void)
 {
-	/* Set up the LEDs */
-	at91_init_leds(AT91_PIN_PC19, AT91_PIN_PC18);
-
 	/* Serial */
 	/* DBGU on ttyS0. (Rx & Tx only) */
 	at91_register_uart(0, 0, 0);
@@ -121,13 +136,15 @@ static void __init kb9202_board_init(void)
 	/* USB Device */
 	at91_add_device_udc(&kb9202_udc_data);
 	/* MMC */
-	at91_add_device_mmc(0, &kb9202_mmc_data);
+	at91_add_device_mci(0, &kb9202_mci0_data);
 	/* I2C */
 	at91_add_device_i2c(NULL, 0);
 	/* SPI */
 	at91_add_device_spi(NULL, 0);
 	/* NAND */
 	at91_add_device_nand(&kb9202_nand_data);
+	/* LEDs */
+	at91_gpio_leds(kb9202_leds, ARRAY_SIZE(kb9202_leds));
 }
 
 MACHINE_START(KB9200, "KB920x")
diff --git a/arch/arm/mach-at91/board-neocore926.c b/arch/arm/mach-at91/board-neocore926.c
index 18103c5d..9cda3fd 100644
--- a/arch/arm/mach-at91/board-neocore926.c
+++ b/arch/arm/mach-at91/board-neocore926.c
@@ -138,11 +138,12 @@ static struct spi_board_info neocore926_spi_devices[] = {
 /*
  * MCI (SD/MMC)
  */
-static struct at91_mmc_data __initdata neocore926_mmc_data = {
-	.wire4		= 1,
-	.det_pin	= AT91_PIN_PE18,
-	.wp_pin		= AT91_PIN_PE19,
-	.vcc_pin	= -EINVAL,
+static struct mci_platform_data __initdata neocore926_mci0_data = {
+	.slot[0] = {
+		.bus_width	= 4,
+		.detect_pin	= AT91_PIN_PE18,
+		.wp_pin		= AT91_PIN_PE19,
+	},
 };
 
 
@@ -354,7 +355,7 @@ static void __init neocore926_board_init(void)
 	neocore926_add_device_ts();
 
 	/* MMC */
-	at91_add_device_mmc(1, &neocore926_mmc_data);
+	at91_add_device_mci(0, &neocore926_mci0_data);
 
 	/* Ethernet */
 	at91_add_device_eth(&neocore926_macb_data);
diff --git a/arch/arm/mach-at91/board-picotux200.c b/arch/arm/mach-at91/board-picotux200.c
index 1270655..f83e1de 100644
--- a/arch/arm/mach-at91/board-picotux200.c
+++ b/arch/arm/mach-at91/board-picotux200.c
@@ -62,12 +62,12 @@ static struct at91_usbh_data __initdata picotux200_usbh_data = {
 	.overcurrent_pin= {-EINVAL, -EINVAL},
 };
 
-static struct at91_mmc_data __initdata picotux200_mmc_data = {
-	.det_pin	= AT91_PIN_PB27,
-	.slot_b		= 0,
-	.wire4		= 1,
-	.wp_pin		= AT91_PIN_PA17,
-	.vcc_pin	= -EINVAL,
+static struct mci_platform_data __initdata picotux200_mci0_data = {
+	.slot[0] = {
+		.bus_width	= 4,
+		.detect_pin	= AT91_PIN_PB27,
+		.wp_pin		= AT91_PIN_PA17,
+	},
 };
 
 #define PICOTUX200_FLASH_BASE	AT91_CHIPSELECT_0
@@ -112,7 +112,7 @@ static void __init picotux200_board_init(void)
 	at91_add_device_i2c(NULL, 0);
 	/* MMC */
 	at91_set_gpio_output(AT91_PIN_PB22, 1);	/* this MMC card slot can optionally use SPI signaling (CS3). */
-	at91_add_device_mmc(0, &picotux200_mmc_data);
+	at91_add_device_mci(0, &picotux200_mci0_data);
 	/* NOR Flash */
 	platform_device_register(&picotux200_flash);
 }
diff --git a/arch/arm/mach-at91/board-qil-a9260.c b/arch/arm/mach-at91/board-qil-a9260.c
index bf351e2..799f214 100644
--- a/arch/arm/mach-at91/board-qil-a9260.c
+++ b/arch/arm/mach-at91/board-qil-a9260.c
@@ -156,12 +156,12 @@ static void __init ek_add_device_nand(void)
 /*
  * MCI (SD/MMC)
  */
-static struct at91_mmc_data __initdata ek_mmc_data = {
-	.slot_b		= 0,
-	.wire4		= 1,
-	.det_pin	= -EINVAL,
-	.wp_pin		= -EINVAL,
-	.vcc_pin	= -EINVAL,
+static struct mci_platform_data __initdata ek_mci0_data = {
+	.slot[0] = {
+		.bus_width	= 4,
+		.detect_pin	= -EINVAL,
+		.wp_pin		= -EINVAL,
+	},
 };
 
 /*
@@ -245,7 +245,7 @@ static void __init ek_board_init(void)
 	/* Ethernet */
 	at91_add_device_eth(&ek_macb_data);
 	/* MMC */
-	at91_add_device_mmc(0, &ek_mmc_data);
+	at91_add_device_mci(0, &ek_mci0_data);
 	/* Push Buttons */
 	ek_add_device_buttons();
 	/* LEDs */
diff --git a/arch/arm/mach-at91/board-rm9200dk.c b/arch/arm/mach-at91/board-rm9200dk.c
index cc2bf97..66338e7 100644
--- a/arch/arm/mach-at91/board-rm9200dk.c
+++ b/arch/arm/mach-at91/board-rm9200dk.c
@@ -77,12 +77,12 @@ static struct at91_cf_data __initdata dk_cf_data = {
 };
 
 #ifndef CONFIG_MTD_AT91_DATAFLASH_CARD
-static struct at91_mmc_data __initdata dk_mmc_data = {
-	.slot_b		= 0,
-	.wire4		= 1,
-	.det_pin	= -EINVAL,
-	.wp_pin		= -EINVAL,
-	.vcc_pin	= -EINVAL,
+static struct mci_platform_data __initdata dk_mci0_data = {
+	.slot[0] = {
+		.bus_width	= 4,
+		.detect_pin	= -EINVAL,
+		.wp_pin		= -EINVAL,
+	},
 };
 #endif
 
@@ -177,9 +177,6 @@ static struct gpio_led dk_leds[] = {
 
 static void __init dk_board_init(void)
 {
-	/* Setup the LEDs */
-	at91_init_leds(AT91_PIN_PB2, AT91_PIN_PB2);
-
 	/* Serial */
 	/* DBGU on ttyS0. (Rx & Tx only) */
 	at91_register_uart(0, 0, 0);
@@ -208,7 +205,7 @@ static void __init dk_board_init(void)
 #else
 	/* MMC */
 	at91_set_gpio_output(AT91_PIN_PB7, 1);	/* this MMC card slot can optionally use SPI signaling (CS3). */
-	at91_add_device_mmc(0, &dk_mmc_data);
+	at91_add_device_mci(0, &dk_mci0_data);
 #endif
 	/* NAND */
 	at91_add_device_nand(&dk_nand_data);
diff --git a/arch/arm/mach-at91/board-rm9200ek.c b/arch/arm/mach-at91/board-rm9200ek.c
index 62e19e6..5d1b572 100644
--- a/arch/arm/mach-at91/board-rm9200ek.c
+++ b/arch/arm/mach-at91/board-rm9200ek.c
@@ -70,12 +70,12 @@ static struct at91_udc_data __initdata ek_udc_data = {
 };
 
 #ifndef CONFIG_MTD_AT91_DATAFLASH_CARD
-static struct at91_mmc_data __initdata ek_mmc_data = {
-	.det_pin	= AT91_PIN_PB27,
-	.slot_b		= 0,
-	.wire4		= 1,
-	.wp_pin		= AT91_PIN_PA17,
-	.vcc_pin	= -EINVAL,
+static struct mci_platform_data __initdata ek_mci0_data = {
+	.slot[0] = {
+		.bus_width	= 4,
+		.detect_pin	= AT91_PIN_PB27,
+		.wp_pin		= AT91_PIN_PA17,
+	}
 };
 #endif
 
@@ -148,9 +148,6 @@ static struct gpio_led ek_leds[] = {
 
 static void __init ek_board_init(void)
 {
-	/* Setup the LEDs */
-	at91_init_leds(AT91_PIN_PB1, AT91_PIN_PB2);
-
 	/* Serial */
 	/* DBGU on ttyS0. (Rx & Tx only) */
 	at91_register_uart(0, 0, 0);
@@ -177,7 +174,7 @@ static void __init ek_board_init(void)
 #else
 	/* MMC */
 	at91_set_gpio_output(AT91_PIN_PB22, 1);	/* this MMC card slot can optionally use SPI signaling (CS3). */
-	at91_add_device_mmc(0, &ek_mmc_data);
+	at91_add_device_mci(0, &ek_mci0_data);
 #endif
 	/* NOR Flash */
 	platform_device_register(&ek_flash);
diff --git a/arch/arm/mach-at91/board-rsi-ews.c b/arch/arm/mach-at91/board-rsi-ews.c
index c3b43ae..a0ecf04 100644
--- a/arch/arm/mach-at91/board-rsi-ews.c
+++ b/arch/arm/mach-at91/board-rsi-ews.c
@@ -58,11 +58,12 @@ static struct at91_usbh_data rsi_ews_usbh_data __initdata = {
 /*
  * SD/MC
  */
-static struct at91_mmc_data rsi_ews_mmc_data __initdata = {
-	.slot_b		= 0,
-	.wire4		= 1,
-	.det_pin	= AT91_PIN_PB27,
-	.wp_pin		= AT91_PIN_PB29,
+static struct mci_platform_data __initdata rsi_ews_mci0_data = {
+	.slot[0] = {
+		.bus_width	= 4,
+		.detect_pin	= AT91_PIN_PB27,
+		.wp_pin		= AT91_PIN_PB29,
+	},
 };
 
 /*
@@ -185,9 +186,6 @@ static struct platform_device rsiews_nor_flash = {
  */
 static void __init rsi_ews_board_init(void)
 {
-	/* Setup the LEDs */
-	at91_init_leds(AT91_PIN_PB6, AT91_PIN_PB9);
-
 	/* Serial */
 	/* DBGU on ttyS0. (Rx & Tx only) */
 	/* This one is for debugging */
@@ -215,7 +213,7 @@ static void __init rsi_ews_board_init(void)
 	at91_add_device_spi(rsi_ews_spi_devices,
 			ARRAY_SIZE(rsi_ews_spi_devices));
 	/* MMC */
-	at91_add_device_mmc(0, &rsi_ews_mmc_data);
+	at91_add_device_mci(0, &rsi_ews_mci0_data);
 	/* NOR Flash */
 	platform_device_register(&rsiews_nor_flash);
 	/* LEDs */
diff --git a/arch/arm/mach-at91/board-sam9-l9260.c b/arch/arm/mach-at91/board-sam9-l9260.c
index 7bf6da7..c5f01ac 100644
--- a/arch/arm/mach-at91/board-sam9-l9260.c
+++ b/arch/arm/mach-at91/board-sam9-l9260.c
@@ -73,7 +73,7 @@ static struct at91_udc_data __initdata ek_udc_data = {
  * SPI devices.
  */
 static struct spi_board_info ek_spi_devices[] = {
-#if !defined(CONFIG_MMC_AT91)
+#if !IS_ENABLED(CONFIG_MMC_ATMELMCI)
 	{	/* DataFlash chip */
 		.modalias	= "mtd_dataflash",
 		.chip_select	= 1,
@@ -158,19 +158,34 @@ static void __init ek_add_device_nand(void)
 /*
  * MCI (SD/MMC)
  */
-static struct at91_mmc_data __initdata ek_mmc_data = {
-	.slot_b		= 1,
-	.wire4		= 1,
-	.det_pin	= AT91_PIN_PC8,
-	.wp_pin		= AT91_PIN_PC4,
-	.vcc_pin	= -EINVAL,
+static struct mci_platform_data __initdata ek_mci0_data = {
+	.slot[1] = {
+		.bus_width	= 4,
+		.detect_pin	= AT91_PIN_PC8,
+		.wp_pin		= AT91_PIN_PC4,
+	},
+};
+
+/*
+ * LEDs
+ */
+static struct gpio_led ek_leds[] = {
+	{	/* D1 */
+		.name			= "led1",
+		.gpio			= AT91_PIN_PA9,
+		.active_low		= 1,
+		.default_trigger	= "heartbeat",
+	},
+	{	/* D2 */
+		.name			= "led2",
+		.gpio			= AT91_PIN_PA6,
+		.active_low		= 1,
+		.default_trigger	= "timer",
+	}
 };
 
 static void __init ek_board_init(void)
 {
-	/* Setup the LEDs */
-	at91_init_leds(AT91_PIN_PA9, AT91_PIN_PA6);
-
 	/* Serial */
 	/* DBGU on ttyS0. (Rx & Tx only) */
 	at91_register_uart(0, 0, 0);
@@ -194,9 +209,11 @@ static void __init ek_board_init(void)
 	/* Ethernet */
 	at91_add_device_eth(&ek_macb_data);
 	/* MMC */
-	at91_add_device_mmc(0, &ek_mmc_data);
+	at91_add_device_mci(0, &ek_mci0_data);
 	/* I2C */
 	at91_add_device_i2c(NULL, 0);
+	/* LEDs */
+	at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds));
 }
 
 MACHINE_START(SAM9_L9260, "Olimex SAM9-L9260")
diff --git a/arch/arm/mach-at91/board-sam9260ek.c b/arch/arm/mach-at91/board-sam9260ek.c
index 889c1bf..8cd6e67 100644
--- a/arch/arm/mach-at91/board-sam9260ek.c
+++ b/arch/arm/mach-at91/board-sam9260ek.c
@@ -108,7 +108,7 @@ static void __init at73c213_set_clk(struct at73c213_board_info *info) {}
  * SPI devices.
  */
 static struct spi_board_info ek_spi_devices[] = {
-#if !defined(CONFIG_MMC_AT91)
+#if !IS_ENABLED(CONFIG_MMC_ATMELMCI)
 	{	/* DataFlash chip */
 		.modalias	= "mtd_dataflash",
 		.chip_select	= 1,
@@ -211,12 +211,12 @@ static void __init ek_add_device_nand(void)
 /*
  * MCI (SD/MMC)
  */
-static struct at91_mmc_data __initdata ek_mmc_data = {
-	.slot_b		= 1,
-	.wire4		= 1,
-	.det_pin	= -EINVAL,
-	.wp_pin		= -EINVAL,
-	.vcc_pin	= -EINVAL,
+static struct mci_platform_data __initdata ek_mci0_data = {
+	.slot[1] = {
+		.bus_width	= 4,
+		.detect_pin	= -EINVAL,
+		.wp_pin		= -EINVAL,
+	},
 };
 
 
@@ -329,7 +329,7 @@ static void __init ek_board_init(void)
 	/* Ethernet */
 	at91_add_device_eth(&ek_macb_data);
 	/* MMC */
-	at91_add_device_mmc(0, &ek_mmc_data);
+	at91_add_device_mci(0, &ek_mci0_data);
 	/* I2C */
 	at91_add_device_i2c(ek_i2c_devices, ARRAY_SIZE(ek_i2c_devices));
 	/* SSC (to AT73C213) */
diff --git a/arch/arm/mach-at91/board-sam9261ek.c b/arch/arm/mach-at91/board-sam9261ek.c
index 2269be5..27b3af1 100644
--- a/arch/arm/mach-at91/board-sam9261ek.c
+++ b/arch/arm/mach-at91/board-sam9261ek.c
@@ -340,11 +340,12 @@ static struct spi_board_info ek_spi_devices[] = {
  * MCI (SD/MMC)
  * det_pin, wp_pin and vcc_pin are not connected
  */
-static struct at91_mmc_data __initdata ek_mmc_data = {
-	.wire4		= 1,
-	.det_pin	= -EINVAL,
-	.wp_pin		= -EINVAL,
-	.vcc_pin	= -EINVAL,
+static struct mci_platform_data __initdata mci0_data = {
+	.slot[0] = {
+		.bus_width	= 4,
+		.detect_pin	= -EINVAL,
+		.wp_pin		= -EINVAL,
+	},
 };
 
 #endif /* CONFIG_SPI_ATMEL_* */
@@ -569,9 +570,6 @@ static struct gpio_led ek_leds[] = {
 
 static void __init ek_board_init(void)
 {
-	/* Setup the LEDs */
-	at91_init_leds(AT91_PIN_PA13, AT91_PIN_PA14);
-
 	/* Serial */
 	/* DBGU on ttyS0. (Rx & Tx only) */
 	at91_register_uart(0, 0, 0);
@@ -598,7 +596,7 @@ static void __init ek_board_init(void)
 	at91_add_device_ssc(AT91SAM9261_ID_SSC1, ATMEL_SSC_TX);
 #else
 	/* MMC */
-	at91_add_device_mmc(0, &ek_mmc_data);
+	at91_add_device_mci(0, &mci0_data);
 #endif
 	/* LCD Controller */
 	at91_add_device_lcdc(&ek_lcdc_data);
diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c
index 82adf58..073e174 100644
--- a/arch/arm/mach-at91/board-sam9263ek.c
+++ b/arch/arm/mach-at91/board-sam9263ek.c
@@ -141,11 +141,12 @@ static struct spi_board_info ek_spi_devices[] = {
 /*
  * MCI (SD/MMC)
  */
-static struct at91_mmc_data __initdata ek_mmc_data = {
-	.wire4		= 1,
-	.det_pin	= AT91_PIN_PE18,
-	.wp_pin		= AT91_PIN_PE19,
-	.vcc_pin	= -EINVAL,
+static struct mci_platform_data __initdata mci1_data = {
+	.slot[0] = {
+		.bus_width	= 4,
+		.detect_pin	= AT91_PIN_PE18,
+		.wp_pin		= AT91_PIN_PE19,
+	},
 };
 
 
@@ -420,7 +421,7 @@ static void __init ek_board_init(void)
 	/* Touchscreen */
 	ek_add_device_ts();
 	/* MMC */
-	at91_add_device_mmc(1, &ek_mmc_data);
+	at91_add_device_mci(1, &mci1_data);
 	/* Ethernet */
 	at91_add_device_eth(&ek_macb_data);
 	/* NAND */
diff --git a/arch/arm/mach-at91/board-sam9g20ek.c b/arch/arm/mach-at91/board-sam9g20ek.c
index 4ea4ee0..3ab2b86 100644
--- a/arch/arm/mach-at91/board-sam9g20ek.c
+++ b/arch/arm/mach-at91/board-sam9g20ek.c
@@ -92,7 +92,7 @@ static struct at91_udc_data __initdata ek_udc_data = {
  * SPI devices.
  */
 static struct spi_board_info ek_spi_devices[] = {
-#if !(defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_AT91))
+#if !IS_ENABLED(CONFIG_MMC_ATMELMCI)
 	{	/* DataFlash chip */
 		.modalias	= "mtd_dataflash",
 		.chip_select	= 1,
@@ -199,7 +199,6 @@ static void __init ek_add_device_nand(void)
  * MCI (SD/MMC)
  * wp_pin and vcc_pin are not connected
  */
-#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE)
 static struct mci_platform_data __initdata ek_mmc_data = {
 	.slot[1] = {
 		.bus_width	= 4,
@@ -208,28 +207,15 @@ static struct mci_platform_data __initdata ek_mmc_data = {
 	},
 
 };
-#else
-static struct at91_mmc_data __initdata ek_mmc_data = {
-	.slot_b		= 1,	/* Only one slot so use slot B */
-	.wire4		= 1,
-	.det_pin	= AT91_PIN_PC9,
-	.wp_pin		= -EINVAL,
-	.vcc_pin	= -EINVAL,
-};
-#endif
 
 static void __init ek_add_device_mmc(void)
 {
-#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE)
 	if (ek_have_2mmc()) {
 		ek_mmc_data.slot[0].bus_width = 4;
 		ek_mmc_data.slot[0].detect_pin = AT91_PIN_PC2;
 		ek_mmc_data.slot[0].wp_pin = -1;
 	}
 	at91_add_device_mci(0, &ek_mmc_data);
-#else
-	at91_add_device_mmc(0, &ek_mmc_data);
-#endif
 }
 
 /*
diff --git a/arch/arm/mach-at91/board-sam9rlek.c b/arch/arm/mach-at91/board-sam9rlek.c
index e7dc3ea..fb89ea9 100644
--- a/arch/arm/mach-at91/board-sam9rlek.c
+++ b/arch/arm/mach-at91/board-sam9rlek.c
@@ -56,11 +56,12 @@ static struct usba_platform_data __initdata ek_usba_udc_data = {
 /*
  * MCI (SD/MMC)
  */
-static struct at91_mmc_data __initdata ek_mmc_data = {
-	.wire4		= 1,
-	.det_pin	= AT91_PIN_PA15,
-	.wp_pin		= -EINVAL,
-	.vcc_pin	= -EINVAL,
+static struct mci_platform_data __initdata mci0_data = {
+	.slot[0] = {
+		.bus_width	= 4,
+		.detect_pin	= AT91_PIN_PA15,
+		.wp_pin		= -EINVAL,
+	},
 };
 
 
@@ -303,7 +304,7 @@ static void __init ek_board_init(void)
 	/* SPI */
 	at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices));
 	/* MMC */
-	at91_add_device_mmc(0, &ek_mmc_data);
+	at91_add_device_mci(0, &mci0_data);
 	/* LCD Controller */
 	at91_add_device_lcdc(&ek_lcdc_data);
 	/* AC97 */
diff --git a/arch/arm/mach-at91/board-stamp9g20.c b/arch/arm/mach-at91/board-stamp9g20.c
index 29eae16..c3fb31d 100644
--- a/arch/arm/mach-at91/board-stamp9g20.c
+++ b/arch/arm/mach-at91/board-stamp9g20.c
@@ -83,7 +83,6 @@ static void __init add_device_nand(void)
  * MCI (SD/MMC)
  * det_pin, wp_pin and vcc_pin are not connected
  */
-#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE)
 static struct mci_platform_data __initdata mmc_data = {
 	.slot[0] = {
 		.bus_width	= 4,
@@ -91,15 +90,6 @@ static struct mci_platform_data __initdata mmc_data = {
 		.wp_pin		= -1,
 	},
 };
-#else
-static struct at91_mmc_data __initdata mmc_data = {
-	.slot_b		= 0,
-	.wire4		= 1,
-	.det_pin	= -EINVAL,
-	.wp_pin		= -EINVAL,
-	.vcc_pin	= -EINVAL,
-};
-#endif
 
 
 /*
@@ -223,11 +213,7 @@ void __init stamp9g20_board_init(void)
 	/* NAND */
 	add_device_nand();
 	/* MMC */
-#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE)
 	at91_add_device_mci(0, &mmc_data);
-#else
-	at91_add_device_mmc(0, &mmc_data);
-#endif
 	/* W1 */
 	add_w1();
 }
diff --git a/arch/arm/mach-at91/board-usb-a926x.c b/arch/arm/mach-at91/board-usb-a926x.c
index c1476b9..6ea069b 100644
--- a/arch/arm/mach-at91/board-usb-a926x.c
+++ b/arch/arm/mach-at91/board-usb-a926x.c
@@ -109,14 +109,12 @@ static struct mmc_spi_platform_data at91_mmc_spi_pdata = {
  * SPI devices.
  */
 static struct spi_board_info usb_a9263_spi_devices[] = {
-#if !defined(CONFIG_MMC_AT91)
 	{	/* DataFlash chip */
 		.modalias	= "mtd_dataflash",
 		.chip_select	= 0,
 		.max_speed_hz	= 15 * 1000 * 1000,
 		.bus_num	= 0,
 	}
-#endif
 };
 
 static struct spi_board_info usb_a9g20_spi_devices[] = {
diff --git a/arch/arm/mach-at91/board-yl-9200.c b/arch/arm/mach-at91/board-yl-9200.c
index 516d340..f162fdf 100644
--- a/arch/arm/mach-at91/board-yl-9200.c
+++ b/arch/arm/mach-at91/board-yl-9200.c
@@ -119,11 +119,12 @@ static struct at91_udc_data __initdata yl9200_udc_data = {
 /*
  * MMC
  */
-static struct at91_mmc_data __initdata yl9200_mmc_data = {
-	.det_pin	= AT91_PIN_PB9,
-	.wire4		= 1,
-	.wp_pin		= -EINVAL,
-	.vcc_pin	= -EINVAL,
+static struct mci_platform_data __initdata yl9200_mci0_data = {
+	.slot[0] = {
+		.bus_width	= 4,
+		.detect_pin	= AT91_PIN_PB9,
+		.wp_pin		= -EINVAL,
+	},
 };
 
 /*
@@ -541,9 +542,6 @@ void __init yl9200_add_device_video(void) {}
 
 static void __init yl9200_board_init(void)
 {
-	/* Setup the LEDs D2=PB17 (timer), D3=PB16 (cpu) */
-	at91_init_leds(AT91_PIN_PB16, AT91_PIN_PB17);
-
 	/* Serial */
 	/* DBGU on ttyS0. (Rx & Tx only) */
 	at91_register_uart(0, 0, 0);
@@ -568,7 +566,7 @@ static void __init yl9200_board_init(void)
 	/* I2C */
 	at91_add_device_i2c(yl9200_i2c_devices, ARRAY_SIZE(yl9200_i2c_devices));
 	/* MMC */
-	at91_add_device_mmc(0, &yl9200_mmc_data);
+	at91_add_device_mci(0, &yl9200_mci0_data);
 	/* NAND */
 	at91_add_device_nand(&yl9200_nand_data);
 	/* NOR Flash */
diff --git a/arch/arm/mach-at91/clock.c b/arch/arm/mach-at91/clock.c
index 188c829..3336150 100644
--- a/arch/arm/mach-at91/clock.c
+++ b/arch/arm/mach-at91/clock.c
@@ -625,7 +625,7 @@ fail:
 	return 0;
 }
 
-static struct clk *const standard_pmc_clocks[] __initdata = {
+static struct clk *const standard_pmc_clocks[] __initconst = {
 	/* four primary clocks */
 	&clk32k,
 	&main_clk,
diff --git a/arch/arm/mach-at91/include/mach/at91_twi.h b/arch/arm/mach-at91/include/mach/at91_twi.h
deleted file mode 100644
index bb2880f..0000000
--- a/arch/arm/mach-at91/include/mach/at91_twi.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * arch/arm/mach-at91/include/mach/at91_twi.h
- *
- * Copyright (C) 2005 Ivan Kokshaysky
- * Copyright (C) SAN People
- *
- * Two-wire Interface (TWI) registers.
- * Based on AT91RM9200 datasheet revision E.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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 AT91_TWI_H
-#define AT91_TWI_H
-
-#define	AT91_TWI_CR		0x00		/* Control Register */
-#define		AT91_TWI_START		(1 <<  0)	/* Send a Start Condition */
-#define		AT91_TWI_STOP		(1 <<  1)	/* Send a Stop Condition */
-#define		AT91_TWI_MSEN		(1 <<  2)	/* Master Transfer Enable */
-#define		AT91_TWI_MSDIS		(1 <<  3)	/* Master Transfer Disable */
-#define		AT91_TWI_SVEN		(1 <<  4)	/* Slave Transfer Enable [SAM9260 only] */
-#define		AT91_TWI_SVDIS		(1 <<  5)	/* Slave Transfer Disable [SAM9260 only] */
-#define		AT91_TWI_SWRST		(1 <<  7)	/* Software Reset */
-
-#define	AT91_TWI_MMR		0x04		/* Master Mode Register */
-#define		AT91_TWI_IADRSZ		(3    <<  8)	/* Internal Device Address Size */
-#define			AT91_TWI_IADRSZ_NO		(0 << 8)
-#define			AT91_TWI_IADRSZ_1		(1 << 8)
-#define			AT91_TWI_IADRSZ_2		(2 << 8)
-#define			AT91_TWI_IADRSZ_3		(3 << 8)
-#define		AT91_TWI_MREAD		(1    << 12)	/* Master Read Direction */
-#define		AT91_TWI_DADR		(0x7f << 16)	/* Device Address */
-
-#define	AT91_TWI_SMR		0x08		/* Slave Mode Register [SAM9260 only] */
-#define		AT91_TWI_SADR		(0x7f << 16)	/* Slave Address */
-
-#define	AT91_TWI_IADR		0x0c		/* Internal Address Register */
-
-#define	AT91_TWI_CWGR		0x10		/* Clock Waveform Generator Register */
-#define		AT91_TWI_CLDIV		(0xff <<  0)	/* Clock Low Divisor */
-#define		AT91_TWI_CHDIV		(0xff <<  8)	/* Clock High Divisor */
-#define		AT91_TWI_CKDIV		(7    << 16)	/* Clock Divider */
-
-#define	AT91_TWI_SR		0x20		/* Status Register */
-#define		AT91_TWI_TXCOMP		(1 <<  0)	/* Transmission Complete */
-#define		AT91_TWI_RXRDY		(1 <<  1)	/* Receive Holding Register Ready */
-#define		AT91_TWI_TXRDY		(1 <<  2)	/* Transmit Holding Register Ready */
-#define		AT91_TWI_SVREAD		(1 <<  3)	/* Slave Read [SAM9260 only] */
-#define		AT91_TWI_SVACC		(1 <<  4)	/* Slave Access [SAM9260 only] */
-#define		AT91_TWI_GACC		(1 <<  5)	/* General Call Access [SAM9260 only] */
-#define		AT91_TWI_OVRE		(1 <<  6)	/* Overrun Error [AT91RM9200 only] */
-#define		AT91_TWI_UNRE		(1 <<  7)	/* Underrun Error [AT91RM9200 only] */
-#define		AT91_TWI_NACK		(1 <<  8)	/* Not Acknowledged */
-#define		AT91_TWI_ARBLST		(1 <<  9)	/* Arbitration Lost [SAM9260 only] */
-#define		AT91_TWI_SCLWS		(1 << 10)	/* Clock Wait State [SAM9260 only] */
-#define		AT91_TWI_EOSACC		(1 << 11)	/* End of Slave Address [SAM9260 only] */
-
-#define	AT91_TWI_IER		0x24		/* Interrupt Enable Register */
-#define	AT91_TWI_IDR		0x28		/* Interrupt Disable Register */
-#define	AT91_TWI_IMR		0x2c		/* Interrupt Mask Register */
-#define	AT91_TWI_RHR		0x30		/* Receive Holding Register */
-#define	AT91_TWI_THR		0x34		/* Transmit Holding Register */
-
-#endif
-
diff --git a/arch/arm/mach-at91/include/mach/at_hdmac.h b/arch/arm/mach-at91/include/mach/at_hdmac.h
deleted file mode 100644
index cab0997..0000000
--- a/arch/arm/mach-at91/include/mach/at_hdmac.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Header file for the Atmel AHB DMA Controller driver
- *
- * Copyright (C) 2008 Atmel Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-#ifndef AT_HDMAC_H
-#define AT_HDMAC_H
-
-#include <linux/dmaengine.h>
-
-/**
- * struct at_dma_platform_data - Controller configuration parameters
- * @nr_channels: Number of channels supported by hardware (max 8)
- * @cap_mask: dma_capability flags supported by the platform
- */
-struct at_dma_platform_data {
-	unsigned int	nr_channels;
-	dma_cap_mask_t  cap_mask;
-};
-
-/**
- * struct at_dma_slave - Controller-specific information about a slave
- * @dma_dev: required DMA master device
- * @cfg: Platform-specific initializer for the CFG register
- */
-struct at_dma_slave {
-	struct device		*dma_dev;
-	u32			cfg;
-};
-
-
-/* Platform-configurable bits in CFG */
-#define	ATC_SRC_PER(h)		(0xFU & (h))	/* Channel src rq associated with periph handshaking ifc h */
-#define	ATC_DST_PER(h)		((0xFU & (h)) <<  4)	/* Channel dst rq associated with periph handshaking ifc h */
-#define	ATC_SRC_REP		(0x1 <<  8)	/* Source Replay Mod */
-#define	ATC_SRC_H2SEL		(0x1 <<  9)	/* Source Handshaking Mod */
-#define		ATC_SRC_H2SEL_SW	(0x0 <<  9)
-#define		ATC_SRC_H2SEL_HW	(0x1 <<  9)
-#define	ATC_DST_REP		(0x1 << 12)	/* Destination Replay Mod */
-#define	ATC_DST_H2SEL		(0x1 << 13)	/* Destination Handshaking Mod */
-#define		ATC_DST_H2SEL_SW	(0x0 << 13)
-#define		ATC_DST_H2SEL_HW	(0x1 << 13)
-#define	ATC_SOD			(0x1 << 16)	/* Stop On Done */
-#define	ATC_LOCK_IF		(0x1 << 20)	/* Interface Lock */
-#define	ATC_LOCK_B		(0x1 << 21)	/* AHB Bus Lock */
-#define	ATC_LOCK_IF_L		(0x1 << 22)	/* Master Interface Arbiter Lock */
-#define		ATC_LOCK_IF_L_CHUNK	(0x0 << 22)
-#define		ATC_LOCK_IF_L_BUFFER	(0x1 << 22)
-#define	ATC_AHB_PROT_MASK	(0x7 << 24)	/* AHB Protection */
-#define	ATC_FIFOCFG_MASK	(0x3 << 28)	/* FIFO Request Configuration */
-#define		ATC_FIFOCFG_LARGESTBURST	(0x0 << 28)
-#define		ATC_FIFOCFG_HALFFIFO		(0x1 << 28)
-#define		ATC_FIFOCFG_ENOUGHSPACE		(0x2 << 28)
-
-
-#endif /* AT_HDMAC_H */
diff --git a/arch/arm/mach-at91/include/mach/atmel-mci.h b/arch/arm/mach-at91/include/mach/atmel-mci.h
index 998cb0c..cd580a1 100644
--- a/arch/arm/mach-at91/include/mach/atmel-mci.h
+++ b/arch/arm/mach-at91/include/mach/atmel-mci.h
@@ -1,7 +1,7 @@
 #ifndef __MACH_ATMEL_MCI_H
 #define __MACH_ATMEL_MCI_H
 
-#include <mach/at_hdmac.h>
+#include <linux/platform_data/dma-atmel.h>
 
 /**
  * struct mci_dma_data - DMA data for MCI interface
diff --git a/arch/arm/mach-at91/include/mach/board.h b/arch/arm/mach-at91/include/mach/board.h
index 369afc2..c55a436 100644
--- a/arch/arm/mach-at91/include/mach/board.h
+++ b/arch/arm/mach-at91/include/mach/board.h
@@ -187,7 +187,6 @@ struct at91_can_data {
 extern void __init at91_add_device_can(struct at91_can_data *data);
 
  /* LEDs */
-extern void __init at91_init_leds(u8 cpu_led, u8 timer_led);
 extern void __init at91_gpio_leds(struct gpio_led *leds, int nr);
 extern void __init at91_pwm_leds(struct gpio_led *leds, int nr);
 
diff --git a/arch/arm/mach-at91/include/mach/hardware.h b/arch/arm/mach-at91/include/mach/hardware.h
index 09242b6..711a789 100644
--- a/arch/arm/mach-at91/include/mach/hardware.h
+++ b/arch/arm/mach-at91/include/mach/hardware.h
@@ -67,13 +67,13 @@
  * to 0xFEF78000 .. 0xFF000000.  (544Kb)
  */
 #define AT91_IO_PHYS_BASE	0xFFF78000
-#define AT91_IO_VIRT_BASE	(0xFF000000 - AT91_IO_SIZE)
+#define AT91_IO_VIRT_BASE	IOMEM(0xFF000000 - AT91_IO_SIZE)
 #else
 /*
  * Identity mapping for the non MMU case.
  */
 #define AT91_IO_PHYS_BASE	AT91_BASE_SYS
-#define AT91_IO_VIRT_BASE	AT91_IO_PHYS_BASE
+#define AT91_IO_VIRT_BASE	IOMEM(AT91_IO_PHYS_BASE)
 #endif
 
 #define AT91_IO_SIZE		(0xFFFFFFFF - AT91_IO_PHYS_BASE + 1)
diff --git a/arch/arm/mach-at91/include/mach/uncompress.h b/arch/arm/mach-at91/include/mach/uncompress.h
index 6f6118d..97ad68a 100644
--- a/arch/arm/mach-at91/include/mach/uncompress.h
+++ b/arch/arm/mach-at91/include/mach/uncompress.h
@@ -94,7 +94,7 @@ static const u32 uarts_sam9x5[] = {
 	0,
 };
 
-static inline const u32* decomp_soc_detect(u32 dbgu_base)
+static inline const u32* decomp_soc_detect(void __iomem *dbgu_base)
 {
 	u32 cidr, socid;
 
@@ -142,10 +142,10 @@ static inline void arch_decomp_setup(void)
 	int i = 0;
 	const u32* usarts;
 
-	usarts = decomp_soc_detect(AT91_BASE_DBGU0);
+	usarts = decomp_soc_detect((void __iomem *)AT91_BASE_DBGU0);
 
 	if (!usarts)
-		usarts = decomp_soc_detect(AT91_BASE_DBGU1);
+		usarts = decomp_soc_detect((void __iomem *)AT91_BASE_DBGU1);
 	if (!usarts) {
 		at91_uart = NULL;
 		return;
diff --git a/arch/arm/mach-at91/leds.c b/arch/arm/mach-at91/leds.c
index 8dfafe7..1b1e62b 100644
--- a/arch/arm/mach-at91/leds.c
+++ b/arch/arm/mach-at91/leds.c
@@ -90,108 +90,3 @@ void __init at91_pwm_leds(struct gpio_led *leds, int nr)
 #else
 void __init at91_pwm_leds(struct gpio_led *leds, int nr){}
 #endif
-
-
-/* ------------------------------------------------------------------------- */
-
-#if defined(CONFIG_LEDS)
-
-#include <asm/leds.h>
-
-/*
- * Old ARM-specific LED framework; not fully functional when generic time is
- * in use.
- */
-
-static u8 at91_leds_cpu;
-static u8 at91_leds_timer;
-
-static inline void at91_led_on(unsigned int led)
-{
-	at91_set_gpio_value(led, 0);
-}
-
-static inline void at91_led_off(unsigned int led)
-{
-	at91_set_gpio_value(led, 1);
-}
-
-static inline void at91_led_toggle(unsigned int led)
-{
-	unsigned long is_off = at91_get_gpio_value(led);
-	if (is_off)
-		at91_led_on(led);
-	else
-		at91_led_off(led);
-}
-
-
-/*
- * Handle LED events.
- */
-static void at91_leds_event(led_event_t evt)
-{
-	unsigned long flags;
-
-	local_irq_save(flags);
-
-	switch(evt) {
-	case led_start:		/* System startup */
-		at91_led_on(at91_leds_cpu);
-		break;
-
-	case led_stop:		/* System stop / suspend */
-		at91_led_off(at91_leds_cpu);
-		break;
-
-#ifdef CONFIG_LEDS_TIMER
-	case led_timer:		/* Every 50 timer ticks */
-		at91_led_toggle(at91_leds_timer);
-		break;
-#endif
-
-#ifdef CONFIG_LEDS_CPU
-	case led_idle_start:	/* Entering idle state */
-		at91_led_off(at91_leds_cpu);
-		break;
-
-	case led_idle_end:	/* Exit idle state */
-		at91_led_on(at91_leds_cpu);
-		break;
-#endif
-
-	default:
-		break;
-	}
-
-	local_irq_restore(flags);
-}
-
-
-static int __init leds_init(void)
-{
-	if (!at91_leds_timer || !at91_leds_cpu)
-		return -ENODEV;
-
-	leds_event = at91_leds_event;
-
-	leds_event(led_start);
-	return 0;
-}
-
-__initcall(leds_init);
-
-
-void __init at91_init_leds(u8 cpu_led, u8 timer_led)
-{
-	/* Enable GPIO to access the LEDs */
-	at91_set_gpio_output(cpu_led, 1);
-	at91_set_gpio_output(timer_led, 1);
-
-	at91_leds_cpu	= cpu_led;
-	at91_leds_timer	= timer_led;
-}
-
-#else
-void __init at91_init_leds(u8 cpu_led, u8 timer_led) {}
-#endif
diff --git a/arch/arm/mach-at91/setup.c b/arch/arm/mach-at91/setup.c
index 944bffb..e6f52de 100644
--- a/arch/arm/mach-at91/setup.c
+++ b/arch/arm/mach-at91/setup.c
@@ -73,7 +73,7 @@ void __init at91_init_sram(int bank, unsigned long base, unsigned int length)
 {
 	struct map_desc *desc = &sram_desc[bank];
 
-	desc->virtual = AT91_IO_VIRT_BASE - length;
+	desc->virtual = (unsigned long)AT91_IO_VIRT_BASE - length;
 	if (bank > 0)
 		desc->virtual -= sram_desc[bank - 1].length;
 
@@ -88,7 +88,7 @@ void __init at91_init_sram(int bank, unsigned long base, unsigned int length)
 }
 
 static struct map_desc at91_io_desc __initdata = {
-	.virtual	= AT91_VA_BASE_SYS,
+	.virtual	= (unsigned long)AT91_VA_BASE_SYS,
 	.pfn		= __phys_to_pfn(AT91_BASE_SYS),
 	.length		= SZ_16K,
 	.type		= MT_DEVICE,
diff --git a/arch/arm/mach-bcm2835/Makefile b/arch/arm/mach-bcm2835/Makefile
new file mode 100644
index 0000000..4c3892f
--- /dev/null
+++ b/arch/arm/mach-bcm2835/Makefile
@@ -0,0 +1 @@
+obj-y += bcm2835.o
diff --git a/arch/arm/mach-bcm2835/Makefile.boot b/arch/arm/mach-bcm2835/Makefile.boot
new file mode 100644
index 0000000..2d30e17
--- /dev/null
+++ b/arch/arm/mach-bcm2835/Makefile.boot
@@ -0,0 +1,3 @@
+   zreladdr-y := 0x00008000
+params_phys-y := 0x00000100
+initrd_phys-y := 0x00800000
diff --git a/arch/arm/mach-bcm2835/bcm2835.c b/arch/arm/mach-bcm2835/bcm2835.c
new file mode 100644
index 0000000..f6fea49
--- /dev/null
+++ b/arch/arm/mach-bcm2835/bcm2835.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2010 Broadcom
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/init.h>
+#include <linux/irqchip/bcm2835.h>
+#include <linux/of_platform.h>
+#include <linux/bcm2835_timer.h>
+#include <linux/clk/bcm2835.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <mach/bcm2835_soc.h>
+
+static struct map_desc io_map __initdata = {
+	.virtual = BCM2835_PERIPH_VIRT,
+	.pfn = __phys_to_pfn(BCM2835_PERIPH_PHYS),
+	.length = BCM2835_PERIPH_SIZE,
+	.type = MT_DEVICE
+};
+
+void __init bcm2835_map_io(void)
+{
+	iotable_init(&io_map, 1);
+}
+
+void __init bcm2835_init(void)
+{
+	int ret;
+
+	bcm2835_init_clocks();
+
+	ret = of_platform_populate(NULL, of_default_bus_match_table, NULL,
+				   NULL);
+	if (ret) {
+		pr_err("of_platform_populate failed: %d\n", ret);
+		BUG();
+	}
+}
+
+static const char * const bcm2835_compat[] = {
+	"brcm,bcm2835",
+	NULL
+};
+
+DT_MACHINE_START(BCM2835, "BCM2835")
+	.map_io = bcm2835_map_io,
+	.init_irq = bcm2835_init_irq,
+	.handle_irq = bcm2835_handle_irq,
+	.init_machine = bcm2835_init,
+	.timer = &bcm2835_timer,
+	.dt_compat = bcm2835_compat
+MACHINE_END
diff --git a/arch/arm/mach-bcm2835/include/mach/bcm2835_soc.h b/arch/arm/mach-bcm2835/include/mach/bcm2835_soc.h
new file mode 100644
index 0000000..d4dfcf7
--- /dev/null
+++ b/arch/arm/mach-bcm2835/include/mach/bcm2835_soc.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2012 Stephen Warren
+ *
+ * Derived from code:
+ * Copyright (C) 2010 Broadcom
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MACH_BCM2835_BCM2835_SOC_H__
+#define __MACH_BCM2835_BCM2835_SOC_H__
+
+#include <asm/sizes.h>
+
+#define BCM2835_PERIPH_PHYS	0x20000000
+#define BCM2835_PERIPH_VIRT	0xf0000000
+#define BCM2835_PERIPH_SIZE	SZ_16M
+#define BCM2835_DEBUG_PHYS	0x20201000
+#define BCM2835_DEBUG_VIRT	0xf0201000
+
+#endif
diff --git a/arch/arm/mach-bcm2835/include/mach/debug-macro.S b/arch/arm/mach-bcm2835/include/mach/debug-macro.S
new file mode 100644
index 0000000..8a161e4
--- /dev/null
+++ b/arch/arm/mach-bcm2835/include/mach/debug-macro.S
@@ -0,0 +1,21 @@
+/*
+ * Debugging macro include header
+ *
+ * Copyright (C) 2010 Broadcom
+ * Copyright (C) 1994-1999 Russell King
+ * Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
+ *
+ * This program is free software; you can 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/bcm2835_soc.h>
+
+	.macro	addruart, rp, rv, tmp
+	ldr	\rp, =BCM2835_DEBUG_PHYS
+	ldr	\rv, =BCM2835_DEBUG_VIRT
+	.endm
+
+#include <asm/hardware/debug-pl01x.S>
diff --git a/arch/arm/mach-bcm2835/include/mach/timex.h b/arch/arm/mach-bcm2835/include/mach/timex.h
new file mode 100644
index 0000000..6d021e1
--- /dev/null
+++ b/arch/arm/mach-bcm2835/include/mach/timex.h
@@ -0,0 +1,26 @@
+/*
+ *  BCM2835 system clock frequency
+ *
+ *  Copyright (C) 2010 Broadcom
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __ASM_ARCH_TIMEX_H
+#define __ASM_ARCH_TIMEX_H
+
+#define CLOCK_TICK_RATE		(1000000)
+
+#endif
diff --git a/arch/arm/mach-bcm2835/include/mach/uncompress.h b/arch/arm/mach-bcm2835/include/mach/uncompress.h
new file mode 100644
index 0000000..cc46dcc
--- /dev/null
+++ b/arch/arm/mach-bcm2835/include/mach/uncompress.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2010 Broadcom
+ * Copyright (C) 2003 ARM Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/io.h>
+#include <linux/amba/serial.h>
+#include <mach/bcm2835_soc.h>
+
+#define UART0_BASE BCM2835_DEBUG_PHYS
+
+#define BCM2835_UART_DR IOMEM(UART0_BASE + UART01x_DR)
+#define BCM2835_UART_FR IOMEM(UART0_BASE + UART01x_FR)
+#define BCM2835_UART_CR IOMEM(UART0_BASE + UART011_CR)
+
+static inline void putc(int c)
+{
+	while (__raw_readl(BCM2835_UART_FR) & UART01x_FR_TXFF)
+		barrier();
+
+	__raw_writel(c, BCM2835_UART_DR);
+}
+
+static inline void flush(void)
+{
+	int fr;
+
+	do {
+		fr = __raw_readl(BCM2835_UART_FR);
+		barrier();
+	} while ((fr & (UART011_FR_TXFE | UART01x_FR_BUSY)) != UART011_FR_TXFE);
+}
+
+#define arch_decomp_setup()
+#define arch_decomp_wdog()
diff --git a/arch/arm/mach-bcmring/arch.c b/arch/arm/mach-bcmring/arch.c
index 45c97b1..c18a504 100644
--- a/arch/arm/mach-bcmring/arch.c
+++ b/arch/arm/mach-bcmring/arch.c
@@ -29,7 +29,6 @@
 #include <asm/setup.h>
 #include <asm/mach-types.h>
 #include <asm/mach/time.h>
-#include <asm/pmu.h>
 
 #include <asm/mach/arch.h>
 #include <mach/dma.h>
@@ -38,7 +37,7 @@
 #include <mach/csp/chipcHw_def.h>
 #include <mach/csp/chipcHw_inline.h>
 
-#include <cfg_global.h>
+#include <mach/cfg_global.h>
 
 #include "core.h"
 
@@ -116,7 +115,7 @@ static struct resource pmu_resource = {
 
 static struct platform_device pmu_device = {
 	.name		= "arm-pmu",
-	.id		= ARM_PMU_DEVICE_CPU,
+	.id		= -1,
 	.resource	= &pmu_resource,
 	.num_resources	= 1,
 };
diff --git a/arch/arm/mach-bcmring/core.c b/arch/arm/mach-bcmring/core.c
index adbfb19..4b50228 100644
--- a/arch/arm/mach-bcmring/core.c
+++ b/arch/arm/mach-bcmring/core.c
@@ -43,11 +43,10 @@
 #include <asm/mach/time.h>
 #include <asm/mach/map.h>
 
-#include <cfg_global.h>
+#include <mach/cfg_global.h>
 
 #include "clock.h"
 
-#include <csp/secHw.h>
 #include <mach/csp/secHw_def.h>
 #include <mach/csp/chipcHw_inline.h>
 #include <mach/csp/tmrHw_reg.h>
diff --git a/arch/arm/mach-bcmring/csp/chipc/chipcHw.c b/arch/arm/mach-bcmring/csp/chipc/chipcHw.c
index 96273ff..5050833 100644
--- a/arch/arm/mach-bcmring/csp/chipc/chipcHw.c
+++ b/arch/arm/mach-bcmring/csp/chipc/chipcHw.c
@@ -26,15 +26,15 @@
 
 /* ---- Include Files ---------------------------------------------------- */
 
-#include <csp/errno.h>
-#include <csp/stdint.h>
-#include <csp/module.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/export.h>
 
 #include <mach/csp/chipcHw_def.h>
 #include <mach/csp/chipcHw_inline.h>
 
-#include <csp/reg.h>
-#include <csp/delay.h>
+#include <mach/csp/reg.h>
+#include <linux/delay.h>
 
 /* ---- Private Constants and Types --------------------------------------- */
 
@@ -61,21 +61,21 @@ static int chipcHw_divide(int num, int denom)
 /****************************************************************************/
 chipcHw_freq chipcHw_getClockFrequency(chipcHw_CLOCK_e clock	/*  [ IN ] Configurable clock */
     ) {
-	volatile uint32_t *pPLLReg = (uint32_t *) 0x0;
-	volatile uint32_t *pClockCtrl = (uint32_t *) 0x0;
-	volatile uint32_t *pDependentClock = (uint32_t *) 0x0;
+	uint32_t __iomem *pPLLReg = NULL;
+	uint32_t __iomem *pClockCtrl = NULL;
+	uint32_t __iomem *pDependentClock = NULL;
 	uint32_t vcoFreqPll1Hz = 0;	/* Effective VCO frequency for PLL1 in Hz */
 	uint32_t vcoFreqPll2Hz = 0;	/* Effective VCO frequency for PLL2 in Hz */
 	uint32_t dependentClockType = 0;
 	uint32_t vcoHz = 0;
 
 	/* Get VCO frequencies */
-	if ((pChipcHw->PLLPreDivider & chipcHw_REG_PLL_PREDIVIDER_NDIV_MODE_MASK) != chipcHw_REG_PLL_PREDIVIDER_NDIV_MODE_INTEGER) {
+	if ((readl(&pChipcHw->PLLPreDivider) & chipcHw_REG_PLL_PREDIVIDER_NDIV_MODE_MASK) != chipcHw_REG_PLL_PREDIVIDER_NDIV_MODE_INTEGER) {
 		uint64_t adjustFreq = 0;
 
 		vcoFreqPll1Hz = chipcHw_XTAL_FREQ_Hz *
 		    chipcHw_divide(chipcHw_REG_PLL_PREDIVIDER_P1, chipcHw_REG_PLL_PREDIVIDER_P2) *
-		    ((pChipcHw->PLLPreDivider & chipcHw_REG_PLL_PREDIVIDER_NDIV_MASK) >>
+		    ((readl(&pChipcHw->PLLPreDivider) & chipcHw_REG_PLL_PREDIVIDER_NDIV_MASK) >>
 		     chipcHw_REG_PLL_PREDIVIDER_NDIV_SHIFT);
 
 		/* Adjusted frequency due to chipcHw_REG_PLL_DIVIDER_NDIV_f_SS */
@@ -86,13 +86,13 @@ chipcHw_freq chipcHw_getClockFrequency(chipcHw_CLOCK_e clock	/*  [ IN ] Configur
 	} else {
 		vcoFreqPll1Hz = chipcHw_XTAL_FREQ_Hz *
 		    chipcHw_divide(chipcHw_REG_PLL_PREDIVIDER_P1, chipcHw_REG_PLL_PREDIVIDER_P2) *
-		    ((pChipcHw->PLLPreDivider & chipcHw_REG_PLL_PREDIVIDER_NDIV_MASK) >>
+		    ((readl(&pChipcHw->PLLPreDivider) & chipcHw_REG_PLL_PREDIVIDER_NDIV_MASK) >>
 		     chipcHw_REG_PLL_PREDIVIDER_NDIV_SHIFT);
 	}
 	vcoFreqPll2Hz =
 	    chipcHw_XTAL_FREQ_Hz *
 		 chipcHw_divide(chipcHw_REG_PLL_PREDIVIDER_P1, chipcHw_REG_PLL_PREDIVIDER_P2) *
-	    ((pChipcHw->PLLPreDivider2 & chipcHw_REG_PLL_PREDIVIDER_NDIV_MASK) >>
+	    ((readl(&pChipcHw->PLLPreDivider2) & chipcHw_REG_PLL_PREDIVIDER_NDIV_MASK) >>
 	     chipcHw_REG_PLL_PREDIVIDER_NDIV_SHIFT);
 
 	switch (clock) {
@@ -187,51 +187,51 @@ chipcHw_freq chipcHw_getClockFrequency(chipcHw_CLOCK_e clock	/*  [ IN ] Configur
 
 	if (pPLLReg) {
 		/* Obtain PLL clock frequency */
-		if (*pPLLReg & chipcHw_REG_PLL_CLOCK_BYPASS_SELECT) {
+		if (readl(pPLLReg) & chipcHw_REG_PLL_CLOCK_BYPASS_SELECT) {
 			/* Return crystal clock frequency when bypassed */
 			return chipcHw_XTAL_FREQ_Hz;
 		} else if (clock == chipcHw_CLOCK_DDR) {
 			/* DDR frequency is configured in PLLDivider register */
-			return chipcHw_divide (vcoHz, (((pChipcHw->PLLDivider & 0xFF000000) >> 24) ? ((pChipcHw->PLLDivider & 0xFF000000) >> 24) : 256));
+			return chipcHw_divide (vcoHz, (((readl(&pChipcHw->PLLDivider) & 0xFF000000) >> 24) ? ((readl(&pChipcHw->PLLDivider) & 0xFF000000) >> 24) : 256));
 		} else {
 			/* From chip revision number B0, LCD clock is internally divided by 2 */
 			if ((pPLLReg == &pChipcHw->LCDClock) && (chipcHw_getChipRevisionNumber() != chipcHw_REV_NUMBER_A0)) {
 				vcoHz >>= 1;
 			}
 			/* Obtain PLL clock frequency using VCO dividers */
-			return chipcHw_divide(vcoHz, ((*pPLLReg & chipcHw_REG_PLL_CLOCK_MDIV_MASK) ? (*pPLLReg & chipcHw_REG_PLL_CLOCK_MDIV_MASK) : 256));
+			return chipcHw_divide(vcoHz, ((readl(pPLLReg) & chipcHw_REG_PLL_CLOCK_MDIV_MASK) ?  (readl(pPLLReg) & chipcHw_REG_PLL_CLOCK_MDIV_MASK) : 256));
 		}
 	} else if (pClockCtrl) {
 		/* Obtain divider clock frequency */
 		uint32_t div;
 		uint32_t freq = 0;
 
-		if (*pClockCtrl & chipcHw_REG_DIV_CLOCK_BYPASS_SELECT) {
+		if (readl(pClockCtrl) & chipcHw_REG_DIV_CLOCK_BYPASS_SELECT) {
 			/* Return crystal clock frequency when bypassed */
 			return chipcHw_XTAL_FREQ_Hz;
 		} else if (pDependentClock) {
 			/* Identify the dependent clock frequency */
 			switch (dependentClockType) {
 			case PLL_CLOCK:
-				if (*pDependentClock & chipcHw_REG_PLL_CLOCK_BYPASS_SELECT) {
+				if (readl(pDependentClock) & chipcHw_REG_PLL_CLOCK_BYPASS_SELECT) {
 					/* Use crystal clock frequency when dependent PLL clock is bypassed */
 					freq = chipcHw_XTAL_FREQ_Hz;
 				} else {
 					/* Obtain PLL clock frequency using VCO dividers */
-					div = *pDependentClock & chipcHw_REG_PLL_CLOCK_MDIV_MASK;
+					div = readl(pDependentClock) & chipcHw_REG_PLL_CLOCK_MDIV_MASK;
 					freq = div ? chipcHw_divide(vcoHz, div) : 0;
 				}
 				break;
 			case NON_PLL_CLOCK:
-				if (pDependentClock == (uint32_t *) &pChipcHw->ACLKClock) {
+				if (pDependentClock == &pChipcHw->ACLKClock) {
 					freq = chipcHw_getClockFrequency (chipcHw_CLOCK_BUS);
 				} else {
-					if (*pDependentClock & chipcHw_REG_DIV_CLOCK_BYPASS_SELECT) {
+					if (readl(pDependentClock) & chipcHw_REG_DIV_CLOCK_BYPASS_SELECT) {
 						/* Use crystal clock frequency when dependent divider clock is bypassed */
 						freq = chipcHw_XTAL_FREQ_Hz;
 					} else {
 						/* Obtain divider clock frequency using XTAL dividers */
-						div = *pDependentClock & chipcHw_REG_DIV_CLOCK_DIV_MASK;
+						div = readl(pDependentClock) & chipcHw_REG_DIV_CLOCK_DIV_MASK;
 						freq = chipcHw_divide (chipcHw_XTAL_FREQ_Hz, (div ? div : 256));
 					}
 				}
@@ -242,7 +242,7 @@ chipcHw_freq chipcHw_getClockFrequency(chipcHw_CLOCK_e clock	/*  [ IN ] Configur
 			freq = chipcHw_XTAL_FREQ_Hz;
 		}
 
-		div = *pClockCtrl & chipcHw_REG_DIV_CLOCK_DIV_MASK;
+		div = readl(pClockCtrl) & chipcHw_REG_DIV_CLOCK_DIV_MASK;
 		return chipcHw_divide(freq, (div ? div : 256));
 	}
 	return 0;
@@ -261,9 +261,9 @@ chipcHw_freq chipcHw_getClockFrequency(chipcHw_CLOCK_e clock	/*  [ IN ] Configur
 chipcHw_freq chipcHw_setClockFrequency(chipcHw_CLOCK_e clock,	/*  [ IN ] Configurable clock */
 				       uint32_t freq	/*  [ IN ] Clock frequency in Hz */
     ) {
-	volatile uint32_t *pPLLReg = (uint32_t *) 0x0;
-	volatile uint32_t *pClockCtrl = (uint32_t *) 0x0;
-	volatile uint32_t *pDependentClock = (uint32_t *) 0x0;
+	uint32_t __iomem *pPLLReg = NULL;
+	uint32_t __iomem *pClockCtrl = NULL;
+	uint32_t __iomem *pDependentClock = NULL;
 	uint32_t vcoFreqPll1Hz = 0;	/* Effective VCO frequency for PLL1 in Hz */
 	uint32_t desVcoFreqPll1Hz = 0;	/* Desired VCO frequency for PLL1 in Hz */
 	uint32_t vcoFreqPll2Hz = 0;	/* Effective VCO frequency for PLL2 in Hz */
@@ -272,12 +272,12 @@ chipcHw_freq chipcHw_setClockFrequency(chipcHw_CLOCK_e clock,	/*  [ IN ] Configu
 	uint32_t desVcoHz = 0;
 
 	/* Get VCO frequencies */
-	if ((pChipcHw->PLLPreDivider & chipcHw_REG_PLL_PREDIVIDER_NDIV_MODE_MASK) != chipcHw_REG_PLL_PREDIVIDER_NDIV_MODE_INTEGER) {
+	if ((readl(&pChipcHw->PLLPreDivider) & chipcHw_REG_PLL_PREDIVIDER_NDIV_MODE_MASK) != chipcHw_REG_PLL_PREDIVIDER_NDIV_MODE_INTEGER) {
 		uint64_t adjustFreq = 0;
 
 		vcoFreqPll1Hz = chipcHw_XTAL_FREQ_Hz *
 		    chipcHw_divide(chipcHw_REG_PLL_PREDIVIDER_P1, chipcHw_REG_PLL_PREDIVIDER_P2) *
-		    ((pChipcHw->PLLPreDivider & chipcHw_REG_PLL_PREDIVIDER_NDIV_MASK) >>
+		    ((readl(&pChipcHw->PLLPreDivider) & chipcHw_REG_PLL_PREDIVIDER_NDIV_MASK) >>
 		     chipcHw_REG_PLL_PREDIVIDER_NDIV_SHIFT);
 
 		/* Adjusted frequency due to chipcHw_REG_PLL_DIVIDER_NDIV_f_SS */
@@ -289,16 +289,16 @@ chipcHw_freq chipcHw_setClockFrequency(chipcHw_CLOCK_e clock,	/*  [ IN ] Configu
 		/* Desired VCO frequency */
 		desVcoFreqPll1Hz = chipcHw_XTAL_FREQ_Hz *
 		    chipcHw_divide(chipcHw_REG_PLL_PREDIVIDER_P1, chipcHw_REG_PLL_PREDIVIDER_P2) *
-		    (((pChipcHw->PLLPreDivider & chipcHw_REG_PLL_PREDIVIDER_NDIV_MASK) >>
+		    (((readl(&pChipcHw->PLLPreDivider) & chipcHw_REG_PLL_PREDIVIDER_NDIV_MASK) >>
 		      chipcHw_REG_PLL_PREDIVIDER_NDIV_SHIFT) + 1);
 	} else {
 		vcoFreqPll1Hz = desVcoFreqPll1Hz = chipcHw_XTAL_FREQ_Hz *
 		    chipcHw_divide(chipcHw_REG_PLL_PREDIVIDER_P1, chipcHw_REG_PLL_PREDIVIDER_P2) *
-		    ((pChipcHw->PLLPreDivider & chipcHw_REG_PLL_PREDIVIDER_NDIV_MASK) >>
+		    ((readl(&pChipcHw->PLLPreDivider) & chipcHw_REG_PLL_PREDIVIDER_NDIV_MASK) >>
 		     chipcHw_REG_PLL_PREDIVIDER_NDIV_SHIFT);
 	}
 	vcoFreqPll2Hz = chipcHw_XTAL_FREQ_Hz * chipcHw_divide(chipcHw_REG_PLL_PREDIVIDER_P1, chipcHw_REG_PLL_PREDIVIDER_P2) *
-	    ((pChipcHw->PLLPreDivider2 & chipcHw_REG_PLL_PREDIVIDER_NDIV_MASK) >>
+	    ((readl(&pChipcHw->PLLPreDivider2) & chipcHw_REG_PLL_PREDIVIDER_NDIV_MASK) >>
 	     chipcHw_REG_PLL_PREDIVIDER_NDIV_SHIFT);
 
 	switch (clock) {
@@ -307,8 +307,7 @@ chipcHw_freq chipcHw_setClockFrequency(chipcHw_CLOCK_e clock,	/*  [ IN ] Configu
 		{
 			REG_LOCAL_IRQ_SAVE;
 			/* Dvide DDR_phy by two to obtain DDR_ctrl clock */
-			pChipcHw->DDRClock = (pChipcHw->DDRClock & ~chipcHw_REG_PLL_CLOCK_TO_BUS_RATIO_MASK) | ((((freq / 2) / chipcHw_getClockFrequency(chipcHw_CLOCK_BUS)) - 1)
-				<< chipcHw_REG_PLL_CLOCK_TO_BUS_RATIO_SHIFT);
+			writel((readl(&pChipcHw->DDRClock) & ~chipcHw_REG_PLL_CLOCK_TO_BUS_RATIO_MASK) | ((((freq / 2) / chipcHw_getClockFrequency(chipcHw_CLOCK_BUS)) - 1) << chipcHw_REG_PLL_CLOCK_TO_BUS_RATIO_SHIFT), &pChipcHw->DDRClock);
 			REG_LOCAL_IRQ_RESTORE;
 		}
 		pPLLReg = &pChipcHw->DDRClock;
@@ -329,8 +328,7 @@ chipcHw_freq chipcHw_setClockFrequency(chipcHw_CLOCK_e clock,	/*  [ IN ] Configu
 		/* Configure the VPM:BUS ratio settings */
 		{
 			REG_LOCAL_IRQ_SAVE;
-			pChipcHw->VPMClock = (pChipcHw->VPMClock & ~chipcHw_REG_PLL_CLOCK_TO_BUS_RATIO_MASK) | ((chipcHw_divide (freq, chipcHw_getClockFrequency(chipcHw_CLOCK_BUS)) - 1)
-				<< chipcHw_REG_PLL_CLOCK_TO_BUS_RATIO_SHIFT);
+			writel((readl(&pChipcHw->VPMClock) & ~chipcHw_REG_PLL_CLOCK_TO_BUS_RATIO_MASK) | ((chipcHw_divide (freq, chipcHw_getClockFrequency(chipcHw_CLOCK_BUS)) - 1) << chipcHw_REG_PLL_CLOCK_TO_BUS_RATIO_SHIFT), &pChipcHw->VPMClock);
 			REG_LOCAL_IRQ_RESTORE;
 		}
 		pPLLReg = &pChipcHw->VPMClock;
@@ -428,9 +426,9 @@ chipcHw_freq chipcHw_setClockFrequency(chipcHw_CLOCK_e clock,	/*  [ IN ] Configu
 		/* For DDR settings use only the PLL divider clock */
 		if (pPLLReg == &pChipcHw->DDRClock) {
 			/* Set M1DIV for PLL1, which controls the DDR clock */
-			reg32_write(&pChipcHw->PLLDivider, (pChipcHw->PLLDivider & 0x00FFFFFF) | ((chipcHw_REG_PLL_DIVIDER_MDIV (desVcoHz, freq)) << 24));
+			reg32_write(&pChipcHw->PLLDivider, (readl(&pChipcHw->PLLDivider) & 0x00FFFFFF) | ((chipcHw_REG_PLL_DIVIDER_MDIV (desVcoHz, freq)) << 24));
 			/* Calculate expected frequency */
-			freq = chipcHw_divide(vcoHz, (((pChipcHw->PLLDivider & 0xFF000000) >> 24) ? ((pChipcHw->PLLDivider & 0xFF000000) >> 24) : 256));
+			freq = chipcHw_divide(vcoHz, (((readl(&pChipcHw->PLLDivider) & 0xFF000000) >> 24) ? ((readl(&pChipcHw->PLLDivider) & 0xFF000000) >> 24) : 256));
 		} else {
 			/* From chip revision number B0, LCD clock is internally divided by 2 */
 			if ((pPLLReg == &pChipcHw->LCDClock) && (chipcHw_getChipRevisionNumber() != chipcHw_REV_NUMBER_A0)) {
@@ -441,7 +439,7 @@ chipcHw_freq chipcHw_setClockFrequency(chipcHw_CLOCK_e clock,	/*  [ IN ] Configu
 			reg32_modify_and(pPLLReg, ~(chipcHw_REG_PLL_CLOCK_MDIV_MASK));
 			reg32_modify_or(pPLLReg, chipcHw_REG_PLL_DIVIDER_MDIV(desVcoHz, freq));
 			/* Calculate expected frequency */
-			freq = chipcHw_divide(vcoHz, ((*(pPLLReg) & chipcHw_REG_PLL_CLOCK_MDIV_MASK) ? (*(pPLLReg) & chipcHw_REG_PLL_CLOCK_MDIV_MASK) : 256));
+			freq = chipcHw_divide(vcoHz, ((readl(pPLLReg) & chipcHw_REG_PLL_CLOCK_MDIV_MASK) ? (readl(pPLLReg) & chipcHw_REG_PLL_CLOCK_MDIV_MASK) : 256));
 		}
 		/* Wait for for atleast 200ns as per the protocol to change frequency */
 		udelay(1);
@@ -460,16 +458,16 @@ chipcHw_freq chipcHw_setClockFrequency(chipcHw_CLOCK_e clock,	/*  [ IN ] Configu
 		if (pDependentClock) {
 			switch (dependentClockType) {
 			case PLL_CLOCK:
-				divider = chipcHw_divide(chipcHw_divide (desVcoHz, (*pDependentClock & chipcHw_REG_PLL_CLOCK_MDIV_MASK)), freq);
+				divider = chipcHw_divide(chipcHw_divide (desVcoHz, (readl(pDependentClock) & chipcHw_REG_PLL_CLOCK_MDIV_MASK)), freq);
 				break;
 			case NON_PLL_CLOCK:
 				{
 					uint32_t sourceClock = 0;
 
-					if (pDependentClock == (uint32_t *) &pChipcHw->ACLKClock) {
+					if (pDependentClock == &pChipcHw->ACLKClock) {
 						sourceClock = chipcHw_getClockFrequency (chipcHw_CLOCK_BUS);
 					} else {
-						uint32_t div = *pDependentClock & chipcHw_REG_DIV_CLOCK_DIV_MASK;
+						uint32_t div = readl(pDependentClock) & chipcHw_REG_DIV_CLOCK_DIV_MASK;
 						sourceClock = chipcHw_divide (chipcHw_XTAL_FREQ_Hz, ((div) ? div : 256));
 					}
 					divider = chipcHw_divide(sourceClock, freq);
@@ -483,7 +481,7 @@ chipcHw_freq chipcHw_setClockFrequency(chipcHw_CLOCK_e clock,	/*  [ IN ] Configu
 		if (divider) {
 			REG_LOCAL_IRQ_SAVE;
 			/* Set the divider to obtain the required frequency */
-			*pClockCtrl = (*pClockCtrl & (~chipcHw_REG_DIV_CLOCK_DIV_MASK)) | (((divider > 256) ? chipcHw_REG_DIV_CLOCK_DIV_256 : divider) & chipcHw_REG_DIV_CLOCK_DIV_MASK);
+			writel((readl(pClockCtrl) & (~chipcHw_REG_DIV_CLOCK_DIV_MASK)) | (((divider > 256) ? chipcHw_REG_DIV_CLOCK_DIV_256 : divider) & chipcHw_REG_DIV_CLOCK_DIV_MASK), pClockCtrl);
 			REG_LOCAL_IRQ_RESTORE;
 			return freq;
 		}
@@ -515,25 +513,26 @@ static int vpmPhaseAlignA0(void)
 	int count = 0;
 
 	for (iter = 0; (iter < MAX_PHASE_ALIGN_ATTEMPTS) && (adjustCount < MAX_PHASE_ADJUST_COUNT); iter++) {
-		phaseControl = (pChipcHw->VPMClock & chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_MASK) >> chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_SHIFT;
+		phaseControl = (readl(&pChipcHw->VPMClock) & chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_MASK) >> chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_SHIFT;
 		phaseValue = 0;
 		prevPhaseComp = 0;
 
 		/* Step 1: Look for falling PH_COMP transition */
 
 		/* Read the contents of VPM Clock resgister */
-		phaseValue = pChipcHw->VPMClock;
+		phaseValue = readl(&pChipcHw->VPMClock);
 		do {
 			/* Store previous value of phase comparator */
 			prevPhaseComp = phaseValue & chipcHw_REG_PLL_CLOCK_PHASE_COMP;
 			/* Change the value of PH_CTRL. */
-			reg32_write(&pChipcHw->VPMClock, (pChipcHw->VPMClock & (~chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_MASK)) | (phaseControl << chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_SHIFT));
+			reg32_write(&pChipcHw->VPMClock,
+			(readl(&pChipcHw->VPMClock) & (~chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_MASK)) | (phaseControl << chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_SHIFT));
 			/* Wait atleast 20 ns */
 			udelay(1);
 			/* Toggle the LOAD_CH after phase control is written. */
-			pChipcHw->VPMClock ^= chipcHw_REG_PLL_CLOCK_PHASE_UPDATE_ENABLE;
+			writel(readl(&pChipcHw->VPMClock) ^ chipcHw_REG_PLL_CLOCK_PHASE_UPDATE_ENABLE, &pChipcHw->VPMClock);
 			/* Read the contents of  VPM Clock resgister. */
-			phaseValue = pChipcHw->VPMClock;
+			phaseValue = readl(&pChipcHw->VPMClock);
 
 			if ((phaseValue & chipcHw_REG_PLL_CLOCK_PHASE_COMP) == 0x0) {
 				phaseControl = (0x3F & (phaseControl - 1));
@@ -557,12 +556,13 @@ static int vpmPhaseAlignA0(void)
 
 		for (count = 0; (count < 5) && ((phaseValue & chipcHw_REG_PLL_CLOCK_PHASE_COMP) == 0); count++) {
 			phaseControl = (0x3F & (phaseControl + 1));
-			reg32_write(&pChipcHw->VPMClock, (pChipcHw->VPMClock & (~chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_MASK)) | (phaseControl << chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_SHIFT));
+			reg32_write(&pChipcHw->VPMClock,
+			(readl(&pChipcHw->VPMClock) & (~chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_MASK)) | (phaseControl << chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_SHIFT));
 			/* Wait atleast 20 ns */
 			udelay(1);
 			/* Toggle the LOAD_CH after phase control is written. */
-			pChipcHw->VPMClock ^= chipcHw_REG_PLL_CLOCK_PHASE_UPDATE_ENABLE;
-			phaseValue = pChipcHw->VPMClock;
+			writel(readl(&pChipcHw->VPMClock) ^ chipcHw_REG_PLL_CLOCK_PHASE_UPDATE_ENABLE, &pChipcHw->VPMClock);
+			phaseValue = readl(&pChipcHw->VPMClock);
 			/* Count number of adjustment made */
 			adjustCount++;
 		}
@@ -581,12 +581,13 @@ static int vpmPhaseAlignA0(void)
 
 		for (count = 0; (count < 3) && ((phaseValue & chipcHw_REG_PLL_CLOCK_PHASE_COMP) == 0); count++) {
 			phaseControl = (0x3F & (phaseControl - 1));
-			reg32_write(&pChipcHw->VPMClock, (pChipcHw->VPMClock & (~chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_MASK)) | (phaseControl << chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_SHIFT));
+			reg32_write(&pChipcHw->VPMClock,
+			(readl(&pChipcHw->VPMClock) & (~chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_MASK)) | (phaseControl << chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_SHIFT));
 			/* Wait atleast 20 ns */
 			udelay(1);
 			/* Toggle the LOAD_CH after phase control is written. */
-			pChipcHw->VPMClock ^= chipcHw_REG_PLL_CLOCK_PHASE_UPDATE_ENABLE;
-			phaseValue = pChipcHw->VPMClock;
+			writel(readl(&pChipcHw->VPMClock) ^ chipcHw_REG_PLL_CLOCK_PHASE_UPDATE_ENABLE, &pChipcHw->VPMClock);
+			phaseValue = readl(&pChipcHw->VPMClock);
 			/* Count number of adjustment made */
 			adjustCount++;
 		}
@@ -605,12 +606,13 @@ static int vpmPhaseAlignA0(void)
 
 		for (count = 0; (count < 5); count++) {
 			phaseControl = (0x3F & (phaseControl - 1));
-			reg32_write(&pChipcHw->VPMClock, (pChipcHw->VPMClock & (~chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_MASK)) | (phaseControl << chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_SHIFT));
+			reg32_write(&pChipcHw->VPMClock,
+			(readl(&pChipcHw->VPMClock) & (~chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_MASK)) | (phaseControl << chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_SHIFT));
 			/* Wait atleast 20 ns */
 			udelay(1);
 			/* Toggle the LOAD_CH after phase control is written. */
-			pChipcHw->VPMClock ^= chipcHw_REG_PLL_CLOCK_PHASE_UPDATE_ENABLE;
-			phaseValue = pChipcHw->VPMClock;
+			writel(readl(&pChipcHw->VPMClock) ^ chipcHw_REG_PLL_CLOCK_PHASE_UPDATE_ENABLE, &pChipcHw->VPMClock);
+			phaseValue = readl(&pChipcHw->VPMClock);
 			/* Count number of adjustment made */
 			adjustCount++;
 		}
@@ -631,14 +633,14 @@ static int vpmPhaseAlignA0(void)
 			/* Store previous value of phase comparator */
 			prevPhaseComp = phaseValue;
 			/* Change the value of PH_CTRL. */
-			reg32_write(&pChipcHw->VPMClock, (pChipcHw->VPMClock & (~chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_MASK)) | (phaseControl << chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_SHIFT));
+			reg32_write(&pChipcHw->VPMClock,
+			(readl(&pChipcHw->VPMClock) & (~chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_MASK)) | (phaseControl << chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_SHIFT));
 			/* Wait atleast 20 ns */
 			udelay(1);
 			/* Toggle the LOAD_CH after phase control is written. */
-			pChipcHw->VPMClock ^=
-			    chipcHw_REG_PLL_CLOCK_PHASE_UPDATE_ENABLE;
+			writel(readl(&pChipcHw->VPMClock) ^ chipcHw_REG_PLL_CLOCK_PHASE_UPDATE_ENABLE, &pChipcHw->VPMClock);
 			/* Read the contents of  VPM Clock resgister. */
-			phaseValue = pChipcHw->VPMClock;
+			phaseValue = readl(&pChipcHw->VPMClock);
 
 			if ((phaseValue & chipcHw_REG_PLL_CLOCK_PHASE_COMP) == 0x0) {
 				phaseControl = (0x3F & (phaseControl - 1));
@@ -661,13 +663,13 @@ static int vpmPhaseAlignA0(void)
 	}
 
 	/* For VPM Phase should be perfectly aligned. */
-	phaseControl = (((pChipcHw->VPMClock >> chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_SHIFT) - 1) & 0x3F);
+	phaseControl = (((readl(&pChipcHw->VPMClock) >> chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_SHIFT) - 1) & 0x3F);
 	{
 		REG_LOCAL_IRQ_SAVE;
 
-		pChipcHw->VPMClock = (pChipcHw->VPMClock & ~chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_MASK) | (phaseControl << chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_SHIFT);
+		writel((readl(&pChipcHw->VPMClock) & ~chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_MASK) | (phaseControl << chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_SHIFT), &pChipcHw->VPMClock);
 		/* Load new phase value */
-		pChipcHw->VPMClock ^= chipcHw_REG_PLL_CLOCK_PHASE_UPDATE_ENABLE;
+		writel(readl(&pChipcHw->VPMClock) ^ chipcHw_REG_PLL_CLOCK_PHASE_UPDATE_ENABLE, &pChipcHw->VPMClock);
 
 		REG_LOCAL_IRQ_RESTORE;
 	}
@@ -697,7 +699,7 @@ int chipcHw_vpmPhaseAlign(void)
 		int adjustCount = 0;
 
 		/* Disable VPM access */
-		pChipcHw->Spare1 &= ~chipcHw_REG_SPARE1_VPM_BUS_ACCESS_ENABLE;
+		writel(readl(&pChipcHw->Spare1) & ~chipcHw_REG_SPARE1_VPM_BUS_ACCESS_ENABLE, &pChipcHw->Spare1);
 		/* Disable HW VPM phase alignment  */
 		chipcHw_vpmHwPhaseAlignDisable();
 		/* Enable SW VPM phase alignment  */
@@ -715,23 +717,24 @@ int chipcHw_vpmPhaseAlign(void)
 				phaseControl--;
 			} else {
 				/* Enable VPM access */
-				pChipcHw->Spare1 |= chipcHw_REG_SPARE1_VPM_BUS_ACCESS_ENABLE;
+				writel(readl(&pChipcHw->Spare1) | chipcHw_REG_SPARE1_VPM_BUS_ACCESS_ENABLE, &pChipcHw->Spare1);
 				/* Return adjust count */
 				return adjustCount;
 			}
 			/* Change the value of PH_CTRL. */
-			reg32_write(&pChipcHw->VPMClock, (pChipcHw->VPMClock & (~chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_MASK)) | (phaseControl << chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_SHIFT));
+			reg32_write(&pChipcHw->VPMClock,
+			(readl(&pChipcHw->VPMClock) & (~chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_MASK)) | (phaseControl << chipcHw_REG_PLL_CLOCK_PHASE_CONTROL_SHIFT));
 			/* Wait atleast 20 ns */
 			udelay(1);
 			/* Toggle the LOAD_CH after phase control is written. */
-			pChipcHw->VPMClock ^= chipcHw_REG_PLL_CLOCK_PHASE_UPDATE_ENABLE;
+			writel(readl(&pChipcHw->VPMClock) ^ chipcHw_REG_PLL_CLOCK_PHASE_UPDATE_ENABLE, &pChipcHw->VPMClock);
 			/* Count adjustment */
 			adjustCount++;
 		}
 	}
 
 	/* Disable VPM access */
-	pChipcHw->Spare1 &= ~chipcHw_REG_SPARE1_VPM_BUS_ACCESS_ENABLE;
+	writel(readl(&pChipcHw->Spare1) & ~chipcHw_REG_SPARE1_VPM_BUS_ACCESS_ENABLE, &pChipcHw->Spare1);
 	return -1;
 }
 
diff --git a/arch/arm/mach-bcmring/csp/chipc/chipcHw_init.c b/arch/arm/mach-bcmring/csp/chipc/chipcHw_init.c
index 367df75..8377d80 100644
--- a/arch/arm/mach-bcmring/csp/chipc/chipcHw_init.c
+++ b/arch/arm/mach-bcmring/csp/chipc/chipcHw_init.c
@@ -26,15 +26,15 @@
 
 /* ---- Include Files ---------------------------------------------------- */
 
-#include <csp/errno.h>
-#include <csp/stdint.h>
-#include <csp/module.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/export.h>
 
 #include <mach/csp/chipcHw_def.h>
 #include <mach/csp/chipcHw_inline.h>
 
-#include <csp/reg.h>
-#include <csp/delay.h>
+#include <mach/csp/reg.h>
+#include <linux/delay.h>
 /* ---- Private Constants and Types --------------------------------------- */
 
 /*
@@ -73,9 +73,9 @@ void chipcHw_pll2Enable(uint32_t vcoFreqHz)
 
 	{
 		REG_LOCAL_IRQ_SAVE;
-		pChipcHw->PLLConfig2 =
-		    chipcHw_REG_PLL_CONFIG_D_RESET |
-		    chipcHw_REG_PLL_CONFIG_A_RESET;
+		writel(chipcHw_REG_PLL_CONFIG_D_RESET |
+		       chipcHw_REG_PLL_CONFIG_A_RESET,
+			&pChipcHw->PLLConfig2);
 
 		pllPreDivider2 = chipcHw_REG_PLL_PREDIVIDER_POWER_DOWN |
 		    chipcHw_REG_PLL_PREDIVIDER_NDIV_MODE_INTEGER |
@@ -87,28 +87,30 @@ void chipcHw_pll2Enable(uint32_t vcoFreqHz)
 		     chipcHw_REG_PLL_PREDIVIDER_P2_SHIFT);
 
 		/* Enable CHIPC registers to control the PLL */
-		pChipcHw->PLLStatus |= chipcHw_REG_PLL_STATUS_CONTROL_ENABLE;
+		writel(readl(&pChipcHw->PLLStatus) | chipcHw_REG_PLL_STATUS_CONTROL_ENABLE, &pChipcHw->PLLStatus);
 
 		/* Set pre divider to get desired VCO frequency */
-		pChipcHw->PLLPreDivider2 = pllPreDivider2;
+		writel(pllPreDivider2, &pChipcHw->PLLPreDivider2);
 		/* Set NDIV Frac */
-		pChipcHw->PLLDivider2 = chipcHw_REG_PLL_DIVIDER_NDIV_f;
+		writel(chipcHw_REG_PLL_DIVIDER_NDIV_f, &pChipcHw->PLLDivider2);
 
 		/* This has to be removed once the default values are fixed for PLL2. */
-		pChipcHw->PLLControl12 = 0x38000700;
-		pChipcHw->PLLControl22 = 0x00000015;
+		writel(0x38000700, &pChipcHw->PLLControl12);
+		writel(0x00000015, &pChipcHw->PLLControl22);
 
 		/* Reset PLL2 */
 		if (vcoFreqHz > chipcHw_REG_PLL_CONFIG_VCO_SPLIT_FREQ) {
-			pChipcHw->PLLConfig2 = chipcHw_REG_PLL_CONFIG_D_RESET |
+			writel(chipcHw_REG_PLL_CONFIG_D_RESET |
 			    chipcHw_REG_PLL_CONFIG_A_RESET |
 			    chipcHw_REG_PLL_CONFIG_VCO_1601_3200 |
-			    chipcHw_REG_PLL_CONFIG_POWER_DOWN;
+			    chipcHw_REG_PLL_CONFIG_POWER_DOWN,
+			    &pChipcHw->PLLConfig2);
 		} else {
-			pChipcHw->PLLConfig2 = chipcHw_REG_PLL_CONFIG_D_RESET |
+			writel(chipcHw_REG_PLL_CONFIG_D_RESET |
 			    chipcHw_REG_PLL_CONFIG_A_RESET |
 			    chipcHw_REG_PLL_CONFIG_VCO_800_1600 |
-			    chipcHw_REG_PLL_CONFIG_POWER_DOWN;
+			    chipcHw_REG_PLL_CONFIG_POWER_DOWN,
+			    &pChipcHw->PLLConfig2);
 		}
 		REG_LOCAL_IRQ_RESTORE;
 	}
@@ -119,22 +121,25 @@ void chipcHw_pll2Enable(uint32_t vcoFreqHz)
 	{
 		REG_LOCAL_IRQ_SAVE;
 		/* Remove analog reset and Power on the PLL */
-		pChipcHw->PLLConfig2 &=
+		writel(readl(&pChipcHw->PLLConfig2) &
 		    ~(chipcHw_REG_PLL_CONFIG_A_RESET |
-		      chipcHw_REG_PLL_CONFIG_POWER_DOWN);
+		      chipcHw_REG_PLL_CONFIG_POWER_DOWN),
+		      &pChipcHw->PLLConfig2);
 
 		REG_LOCAL_IRQ_RESTORE;
 
 	}
 
 	/* Wait until PLL is locked */
-	while (!(pChipcHw->PLLStatus2 & chipcHw_REG_PLL_STATUS_LOCKED))
+	while (!(readl(&pChipcHw->PLLStatus2) & chipcHw_REG_PLL_STATUS_LOCKED))
 		;
 
 	{
 		REG_LOCAL_IRQ_SAVE;
 		/* Remove digital reset */
-		pChipcHw->PLLConfig2 &= ~chipcHw_REG_PLL_CONFIG_D_RESET;
+		writel(readl(&pChipcHw->PLLConfig2) &
+			~chipcHw_REG_PLL_CONFIG_D_RESET,
+			&pChipcHw->PLLConfig2);
 
 		REG_LOCAL_IRQ_RESTORE;
 	}
@@ -157,9 +162,9 @@ void chipcHw_pll1Enable(uint32_t vcoFreqHz, chipcHw_SPREAD_SPECTRUM_e ssSupport)
 	{
 		REG_LOCAL_IRQ_SAVE;
 
-		pChipcHw->PLLConfig =
-		    chipcHw_REG_PLL_CONFIG_D_RESET |
-		    chipcHw_REG_PLL_CONFIG_A_RESET;
+		writel(chipcHw_REG_PLL_CONFIG_D_RESET |
+		    chipcHw_REG_PLL_CONFIG_A_RESET,
+		    &pChipcHw->PLLConfig);
 		/* Setting VCO frequency */
 		if (ssSupport == chipcHw_SPREAD_SPECTRUM_ALLOW) {
 			pllPreDivider =
@@ -182,30 +187,22 @@ void chipcHw_pll1Enable(uint32_t vcoFreqHz, chipcHw_SPREAD_SPECTRUM_e ssSupport)
 		}
 
 		/* Enable CHIPC registers to control the PLL */
-		pChipcHw->PLLStatus |= chipcHw_REG_PLL_STATUS_CONTROL_ENABLE;
+		writel(readl(&pChipcHw->PLLStatus) | chipcHw_REG_PLL_STATUS_CONTROL_ENABLE, &pChipcHw->PLLStatus);
 
 		/* Set pre divider to get desired VCO frequency */
-		pChipcHw->PLLPreDivider = pllPreDivider;
+		writel(pllPreDivider, &pChipcHw->PLLPreDivider);
 		/* Set NDIV Frac */
 		if (ssSupport == chipcHw_SPREAD_SPECTRUM_ALLOW) {
-			pChipcHw->PLLDivider = chipcHw_REG_PLL_DIVIDER_M1DIV |
-			    chipcHw_REG_PLL_DIVIDER_NDIV_f_SS;
+			writel(chipcHw_REG_PLL_DIVIDER_M1DIV | chipcHw_REG_PLL_DIVIDER_NDIV_f_SS, &pChipcHw->PLLDivider);
 		} else {
-			pChipcHw->PLLDivider = chipcHw_REG_PLL_DIVIDER_M1DIV |
-			    chipcHw_REG_PLL_DIVIDER_NDIV_f;
+			writel(chipcHw_REG_PLL_DIVIDER_M1DIV | chipcHw_REG_PLL_DIVIDER_NDIV_f, &pChipcHw->PLLDivider);
 		}
 
 		/* Reset PLL1 */
 		if (vcoFreqHz > chipcHw_REG_PLL_CONFIG_VCO_SPLIT_FREQ) {
-			pChipcHw->PLLConfig = chipcHw_REG_PLL_CONFIG_D_RESET |
-			    chipcHw_REG_PLL_CONFIG_A_RESET |
-			    chipcHw_REG_PLL_CONFIG_VCO_1601_3200 |
-			    chipcHw_REG_PLL_CONFIG_POWER_DOWN;
+			writel(chipcHw_REG_PLL_CONFIG_D_RESET | chipcHw_REG_PLL_CONFIG_A_RESET | chipcHw_REG_PLL_CONFIG_VCO_1601_3200 | chipcHw_REG_PLL_CONFIG_POWER_DOWN, &pChipcHw->PLLConfig);
 		} else {
-			pChipcHw->PLLConfig = chipcHw_REG_PLL_CONFIG_D_RESET |
-			    chipcHw_REG_PLL_CONFIG_A_RESET |
-			    chipcHw_REG_PLL_CONFIG_VCO_800_1600 |
-			    chipcHw_REG_PLL_CONFIG_POWER_DOWN;
+			writel(chipcHw_REG_PLL_CONFIG_D_RESET | chipcHw_REG_PLL_CONFIG_A_RESET | chipcHw_REG_PLL_CONFIG_VCO_800_1600 | chipcHw_REG_PLL_CONFIG_POWER_DOWN, &pChipcHw->PLLConfig);
 		}
 
 		REG_LOCAL_IRQ_RESTORE;
@@ -216,22 +213,19 @@ void chipcHw_pll1Enable(uint32_t vcoFreqHz, chipcHw_SPREAD_SPECTRUM_e ssSupport)
 		{
 			REG_LOCAL_IRQ_SAVE;
 			/* Remove analog reset and Power on the PLL */
-			pChipcHw->PLLConfig &=
-			    ~(chipcHw_REG_PLL_CONFIG_A_RESET |
-			      chipcHw_REG_PLL_CONFIG_POWER_DOWN);
+			writel(readl(&pChipcHw->PLLConfig) & ~(chipcHw_REG_PLL_CONFIG_A_RESET | chipcHw_REG_PLL_CONFIG_POWER_DOWN), &pChipcHw->PLLConfig);
 			REG_LOCAL_IRQ_RESTORE;
 		}
 
 		/* Wait until PLL is locked */
-		while (!(pChipcHw->PLLStatus & chipcHw_REG_PLL_STATUS_LOCKED)
-		       || !(pChipcHw->
-			    PLLStatus2 & chipcHw_REG_PLL_STATUS_LOCKED))
+		while (!(readl(&pChipcHw->PLLStatus) & chipcHw_REG_PLL_STATUS_LOCKED)
+		       || !(readl(&pChipcHw->PLLStatus2) & chipcHw_REG_PLL_STATUS_LOCKED))
 			;
 
 		/* Remove digital reset */
 		{
 			REG_LOCAL_IRQ_SAVE;
-			pChipcHw->PLLConfig &= ~chipcHw_REG_PLL_CONFIG_D_RESET;
+			writel(readl(&pChipcHw->PLLConfig) & ~chipcHw_REG_PLL_CONFIG_D_RESET, &pChipcHw->PLLConfig);
 			REG_LOCAL_IRQ_RESTORE;
 		}
 	}
@@ -267,11 +261,7 @@ void chipcHw_Init(chipcHw_INIT_PARAM_t *initParam	/*  [ IN ] Misc chip initializ
 	chipcHw_clearStickyBits(chipcHw_REG_STICKY_CHIP_SOFT_RESET);
 
 	/* Before configuring the ARM clock, atleast we need to make sure BUS clock maintains the proper ratio with ARM clock */
-	pChipcHw->ACLKClock =
-	    (pChipcHw->
-	     ACLKClock & ~chipcHw_REG_ACLKClock_CLK_DIV_MASK) | (initParam->
-								 armBusRatio &
-								 chipcHw_REG_ACLKClock_CLK_DIV_MASK);
+	writel((readl(&pChipcHw->ACLKClock) & ~chipcHw_REG_ACLKClock_CLK_DIV_MASK) | (initParam-> armBusRatio & chipcHw_REG_ACLKClock_CLK_DIV_MASK), &pChipcHw->ACLKClock);
 
 	/* Set various core component frequencies. The order in which this is done is important for some. */
 	/* The RTBUS (DDR PHY) is derived from the BUS, and the BUS from the ARM, and VPM needs to know BUS */
diff --git a/arch/arm/mach-bcmring/csp/chipc/chipcHw_reset.c b/arch/arm/mach-bcmring/csp/chipc/chipcHw_reset.c
index 2671d88..f95ce91 100644
--- a/arch/arm/mach-bcmring/csp/chipc/chipcHw_reset.c
+++ b/arch/arm/mach-bcmring/csp/chipc/chipcHw_reset.c
@@ -13,11 +13,11 @@
 *****************************************************************************/
 
 /* ---- Include Files ---------------------------------------------------- */
-#include <csp/stdint.h>
+#include <linux/types.h>
 #include <mach/csp/chipcHw_def.h>
 #include <mach/csp/chipcHw_inline.h>
-#include <csp/intcHw.h>
-#include <csp/cache.h>
+#include <mach/csp/intcHw_reg.h>
+#include <asm/cacheflush.h>
 
 /* ---- Private Constants and Types --------------------------------------- */
 /* ---- Private Variables ------------------------------------------------- */
@@ -50,17 +50,18 @@ void chipcHw_reset(uint32_t mask)
 			chipcHw_softReset(chipcHw_REG_SOFT_RESET_CHIP_SOFT);
 		}
 		/* Bypass the PLL clocks before reboot */
-		pChipcHw->UARTClock |= chipcHw_REG_PLL_CLOCK_BYPASS_SELECT;
-		pChipcHw->SPIClock |= chipcHw_REG_PLL_CLOCK_BYPASS_SELECT;
+		writel(readl(&pChipcHw->UARTClock) | chipcHw_REG_PLL_CLOCK_BYPASS_SELECT,
+			&pChipcHw->UARTClock);
+		writel(readl(&pChipcHw->SPIClock) | chipcHw_REG_PLL_CLOCK_BYPASS_SELECT,
+			&pChipcHw->SPIClock);
 
 		/* Copy the chipcHw_warmReset_run_from_aram function into ARAM */
 		do {
-			((uint32_t *) MM_IO_BASE_ARAM)[i] =
-			    ((uint32_t *) &chipcHw_reset_run_from_aram)[i];
+			writel(((uint32_t *) &chipcHw_reset_run_from_aram)[i], ((uint32_t __iomem *) MM_IO_BASE_ARAM) + i);
 			i++;
-		} while (((uint32_t *) MM_IO_BASE_ARAM)[i - 1] != 0xe1a0f00f);	/* 0xe1a0f00f == asm ("mov r15, r15"); */
+		} while (readl(((uint32_t __iomem*) MM_IO_BASE_ARAM) + i - 1) != 0xe1a0f00f);	/* 0xe1a0f00f == asm ("mov r15, r15"); */
 
-		CSP_CACHE_FLUSH_ALL;
+		flush_cache_all();
 
 		/* run the function from ARAM */
 		runFunc();
diff --git a/arch/arm/mach-bcmring/csp/dmac/dmacHw.c b/arch/arm/mach-bcmring/csp/dmac/dmacHw.c
index 6b9be2e..547f746 100644
--- a/arch/arm/mach-bcmring/csp/dmac/dmacHw.c
+++ b/arch/arm/mach-bcmring/csp/dmac/dmacHw.c
@@ -25,11 +25,11 @@
 /****************************************************************************/
 
 /* ---- Include Files ---------------------------------------------------- */
-#include <csp/stdint.h>
-#include <csp/string.h>
-#include <stddef.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/stddef.h>
 
-#include <csp/dmacHw.h>
+#include <mach/csp/dmacHw.h>
 #include <mach/csp/dmacHw_reg.h>
 #include <mach/csp/dmacHw_priv.h>
 #include <mach/csp/chipcHw_inline.h>
@@ -55,33 +55,32 @@ static uint32_t GetFifoSize(dmacHw_HANDLE_t handle	/*   [ IN ] DMA Channel handl
     ) {
 	uint32_t val = 0;
 	dmacHw_CBLK_t *pCblk = dmacHw_HANDLE_TO_CBLK(handle);
-	dmacHw_MISC_t *pMiscReg =
-	    (dmacHw_MISC_t *) dmacHw_REG_MISC_BASE(pCblk->module);
+	dmacHw_MISC_t __iomem *pMiscReg = (void __iomem *)dmacHw_REG_MISC_BASE(pCblk->module);
 
 	switch (pCblk->channel) {
 	case 0:
-		val = (pMiscReg->CompParm2.lo & 0x70000000) >> 28;
+		val = (readl(&pMiscReg->CompParm2.lo) & 0x70000000) >> 28;
 		break;
 	case 1:
-		val = (pMiscReg->CompParm3.hi & 0x70000000) >> 28;
+		val = (readl(&pMiscReg->CompParm3.hi) & 0x70000000) >> 28;
 		break;
 	case 2:
-		val = (pMiscReg->CompParm3.lo & 0x70000000) >> 28;
+		val = (readl(&pMiscReg->CompParm3.lo) & 0x70000000) >> 28;
 		break;
 	case 3:
-		val = (pMiscReg->CompParm4.hi & 0x70000000) >> 28;
+		val = (readl(&pMiscReg->CompParm4.hi) & 0x70000000) >> 28;
 		break;
 	case 4:
-		val = (pMiscReg->CompParm4.lo & 0x70000000) >> 28;
+		val = (readl(&pMiscReg->CompParm4.lo) & 0x70000000) >> 28;
 		break;
 	case 5:
-		val = (pMiscReg->CompParm5.hi & 0x70000000) >> 28;
+		val = (readl(&pMiscReg->CompParm5.hi) & 0x70000000) >> 28;
 		break;
 	case 6:
-		val = (pMiscReg->CompParm5.lo & 0x70000000) >> 28;
+		val = (readl(&pMiscReg->CompParm5.lo) & 0x70000000) >> 28;
 		break;
 	case 7:
-		val = (pMiscReg->CompParm6.hi & 0x70000000) >> 28;
+		val = (readl(&pMiscReg->CompParm6.hi) & 0x70000000) >> 28;
 		break;
 	}
 
diff --git a/arch/arm/mach-bcmring/csp/dmac/dmacHw_extra.c b/arch/arm/mach-bcmring/csp/dmac/dmacHw_extra.c
index a1f3283..fe43869 100644
--- a/arch/arm/mach-bcmring/csp/dmac/dmacHw_extra.c
+++ b/arch/arm/mach-bcmring/csp/dmac/dmacHw_extra.c
@@ -26,10 +26,10 @@
 
 /* ---- Include Files ---------------------------------------------------- */
 
-#include <csp/stdint.h>
-#include <stddef.h>
+#include <linux/types.h>
+#include <linux/stddef.h>
 
-#include <csp/dmacHw.h>
+#include <mach/csp/dmacHw.h>
 #include <mach/csp/dmacHw_reg.h>
 #include <mach/csp/dmacHw_priv.h>
 
diff --git a/arch/arm/mach-bcmring/csp/tmr/tmrHw.c b/arch/arm/mach-bcmring/csp/tmr/tmrHw.c
index 16225e4..dc4137f 100644
--- a/arch/arm/mach-bcmring/csp/tmr/tmrHw.c
+++ b/arch/arm/mach-bcmring/csp/tmr/tmrHw.c
@@ -26,10 +26,10 @@
 
 /* ---- Include Files ---------------------------------------------------- */
 
-#include <csp/errno.h>
-#include <csp/stdint.h>
+#include <linux/errno.h>
+#include <linux/types.h>
 
-#include <csp/tmrHw.h>
+#include <mach/csp/tmrHw.h>
 #include <mach/csp/tmrHw_reg.h>
 
 #define tmrHw_ASSERT(a)                     if (!(a)) *(char *)0 = 0
diff --git a/arch/arm/mach-bcmring/include/cfg_global.h b/arch/arm/mach-bcmring/include/cfg_global.h
deleted file mode 100644
index f01da87..0000000
--- a/arch/arm/mach-bcmring/include/cfg_global.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef _CFG_GLOBAL_H_
-#define _CFG_GLOBAL_H_
-
-#include <cfg_global_defines.h>
-
-#define CFG_GLOBAL_CHIP                         BCM11107
-#define CFG_GLOBAL_CHIP_FAMILY                  CFG_GLOBAL_CHIP_FAMILY_BCMRING
-#define CFG_GLOBAL_CHIP_REV                     0xB0
-#define CFG_GLOBAL_RAM_SIZE                     0x10000000
-#define CFG_GLOBAL_RAM_BASE                     0x00000000
-#define CFG_GLOBAL_RAM_RESERVED_SIZE            0x000000
-
-#endif /* _CFG_GLOBAL_H_ */
diff --git a/arch/arm/mach-bcmring/include/cfg_global_defines.h b/arch/arm/mach-bcmring/include/cfg_global_defines.h
deleted file mode 100644
index b5beb0b..0000000
--- a/arch/arm/mach-bcmring/include/cfg_global_defines.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*****************************************************************************
-* Copyright 2006 - 2008 Broadcom Corporation.  All rights reserved.
-*
-* Unless you and Broadcom execute a separate written software license
-* agreement governing use of this software, this software is licensed to you
-* under the terms of the GNU General Public License version 2, available at
-* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
-*
-* Notwithstanding the above, under no circumstances may you combine this
-* software in any way with any other Broadcom software provided under a
-* license other than the GPL, without Broadcom's express prior written
-* consent.
-*****************************************************************************/
-
-#ifndef CFG_GLOBAL_DEFINES_H
-#define CFG_GLOBAL_DEFINES_H
-
-/* CHIP */
-#define BCM1103 1
-
-#define BCM1191 4
-#define BCM2153 5
-#define BCM2820 6
-
-#define BCM2826 8
-#define FPGA11107 9
-#define BCM11107   10
-#define BCM11109   11
-#define BCM11170   12
-#define BCM11110   13
-#define BCM11211   14
-
-/* CFG_GLOBAL_CHIP_FAMILY types */
-#define CFG_GLOBAL_CHIP_FAMILY_NONE        0
-#define CFG_GLOBAL_CHIP_FAMILY_BCM116X     2
-#define CFG_GLOBAL_CHIP_FAMILY_BCMRING     4
-#define CFG_GLOBAL_CHIP_FAMILY_BCM1103     8
-
-#define IMAGE_HEADER_SIZE_CHECKSUM    4
-#endif
diff --git a/arch/arm/mach-bcmring/include/csp/cache.h b/arch/arm/mach-bcmring/include/csp/cache.h
deleted file mode 100644
index caa20e5..0000000
--- a/arch/arm/mach-bcmring/include/csp/cache.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*****************************************************************************
-* Copyright 2003 - 2008 Broadcom Corporation.  All rights reserved.
-*
-* Unless you and Broadcom execute a separate written software license
-* agreement governing use of this software, this software is licensed to you
-* under the terms of the GNU General Public License version 2, available at
-* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
-*
-* Notwithstanding the above, under no circumstances may you combine this
-* software in any way with any other Broadcom software provided under a
-* license other than the GPL, without Broadcom's express prior written
-* consent.
-*****************************************************************************/
-
-#ifndef CSP_CACHE_H
-#define CSP_CACHE_H
-
-/* ---- Include Files ---------------------------------------------------- */
-
-#include <csp/stdint.h>
-
-/* ---- Public Constants and Types --------------------------------------- */
-
-#if defined(__KERNEL__) && !defined(STANDALONE)
-#include <asm/cacheflush.h>
-
-#define CSP_CACHE_FLUSH_ALL      flush_cache_all()
-
-#else
-
-#define CSP_CACHE_FLUSH_ALL
-
-#endif
-
-#endif /* CSP_CACHE_H */
diff --git a/arch/arm/mach-bcmring/include/csp/delay.h b/arch/arm/mach-bcmring/include/csp/delay.h
deleted file mode 100644
index 8b3d803..0000000
--- a/arch/arm/mach-bcmring/include/csp/delay.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*****************************************************************************
-* Copyright 2003 - 2008 Broadcom Corporation.  All rights reserved.
-*
-* Unless you and Broadcom execute a separate written software license
-* agreement governing use of this software, this software is licensed to you
-* under the terms of the GNU General Public License version 2, available at
-* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
-*
-* Notwithstanding the above, under no circumstances may you combine this
-* software in any way with any other Broadcom software provided under a
-* license other than the GPL, without Broadcom's express prior written
-* consent.
-*****************************************************************************/
-
-
-#ifndef CSP_DELAY_H
-#define CSP_DELAY_H
-
-/* ---- Include Files ---------------------------------------------------- */
-
-/* Some CSP routines require use of the following delay routines. Use the OS */
-/* version if available, otherwise use a CSP specific definition. */
-/* void udelay(unsigned long usecs); */
-/* void mdelay(unsigned long msecs); */
-
-#if defined(__KERNEL__) && !defined(STANDALONE)
-   #include <linux/delay.h>
-#else
-   #include <mach/csp/delay.h>
-#endif
-
-/* ---- Public Constants and Types --------------------------------------- */
-/* ---- Public Variable Externs ------------------------------------------ */
-/* ---- Public Function Prototypes --------------------------------------- */
-
-#endif /*  CSP_DELAY_H */
diff --git a/arch/arm/mach-bcmring/include/csp/dmacHw.h b/arch/arm/mach-bcmring/include/csp/dmacHw.h
deleted file mode 100644
index e6a1dc4..0000000
--- a/arch/arm/mach-bcmring/include/csp/dmacHw.h
+++ /dev/null
@@ -1,596 +0,0 @@
-/*****************************************************************************
-* Copyright 2004 - 2008 Broadcom Corporation.  All rights reserved.
-*
-* Unless you and Broadcom execute a separate written software license
-* agreement governing use of this software, this software is licensed to you
-* under the terms of the GNU General Public License version 2, available at
-* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
-*
-* Notwithstanding the above, under no circumstances may you combine this
-* software in any way with any other Broadcom software provided under a
-* license other than the GPL, without Broadcom's express prior written
-* consent.
-*****************************************************************************/
-
-/****************************************************************************/
-/**
-*  @file    dmacHw.h
-*
-*  @brief   API definitions for low level DMA controller driver
-*
-*/
-/****************************************************************************/
-#ifndef _DMACHW_H
-#define _DMACHW_H
-
-#include <stddef.h>
-
-#include <csp/stdint.h>
-#include <mach/csp/dmacHw_reg.h>
-
-/* Define DMA Channel ID using DMA controller number (m) and channel number (c).
-
-   System specific channel ID should be defined as follows
-
-   For example:
-
-   #include <dmacHw.h>
-   ...
-   #define systemHw_LCD_CHANNEL_ID                dmacHw_MAKE_CHANNEL_ID(0,5)
-   #define systemHw_SWITCH_RX_CHANNEL_ID          dmacHw_MAKE_CHANNEL_ID(0,0)
-   #define systemHw_SWITCH_TX_CHANNEL_ID          dmacHw_MAKE_CHANNEL_ID(0,1)
-   #define systemHw_APM_RX_CHANNEL_ID             dmacHw_MAKE_CHANNEL_ID(0,3)
-   #define systemHw_APM_TX_CHANNEL_ID             dmacHw_MAKE_CHANNEL_ID(0,4)
-   ...
-   #define systemHw_SHARED1_CHANNEL_ID            dmacHw_MAKE_CHANNEL_ID(1,4)
-   #define systemHw_SHARED2_CHANNEL_ID            dmacHw_MAKE_CHANNEL_ID(1,5)
-   #define systemHw_SHARED3_CHANNEL_ID            dmacHw_MAKE_CHANNEL_ID(0,6)
-   ...
-*/
-#define dmacHw_MAKE_CHANNEL_ID(m, c)         (m << 8 | c)
-
-typedef enum {
-	dmacHw_CHANNEL_PRIORITY_0 = dmacHw_REG_CFG_LO_CH_PRIORITY_0,	/* Channel priority 0. Lowest priority DMA channel */
-	dmacHw_CHANNEL_PRIORITY_1 = dmacHw_REG_CFG_LO_CH_PRIORITY_1,	/* Channel priority 1 */
-	dmacHw_CHANNEL_PRIORITY_2 = dmacHw_REG_CFG_LO_CH_PRIORITY_2,	/* Channel priority 2 */
-	dmacHw_CHANNEL_PRIORITY_3 = dmacHw_REG_CFG_LO_CH_PRIORITY_3,	/* Channel priority 3 */
-	dmacHw_CHANNEL_PRIORITY_4 = dmacHw_REG_CFG_LO_CH_PRIORITY_4,	/* Channel priority 4 */
-	dmacHw_CHANNEL_PRIORITY_5 = dmacHw_REG_CFG_LO_CH_PRIORITY_5,	/* Channel priority 5 */
-	dmacHw_CHANNEL_PRIORITY_6 = dmacHw_REG_CFG_LO_CH_PRIORITY_6,	/* Channel priority 6 */
-	dmacHw_CHANNEL_PRIORITY_7 = dmacHw_REG_CFG_LO_CH_PRIORITY_7	/* Channel priority 7. Highest priority DMA channel */
-} dmacHw_CHANNEL_PRIORITY_e;
-
-/* Source destination master interface */
-typedef enum {
-	dmacHw_SRC_MASTER_INTERFACE_1 = dmacHw_REG_CTL_SMS_1,	/* Source DMA master interface 1 */
-	dmacHw_SRC_MASTER_INTERFACE_2 = dmacHw_REG_CTL_SMS_2,	/* Source DMA master interface 2 */
-	dmacHw_DST_MASTER_INTERFACE_1 = dmacHw_REG_CTL_DMS_1,	/* Destination DMA master interface 1 */
-	dmacHw_DST_MASTER_INTERFACE_2 = dmacHw_REG_CTL_DMS_2	/* Destination DMA master interface 2 */
-} dmacHw_MASTER_INTERFACE_e;
-
-typedef enum {
-	dmacHw_SRC_TRANSACTION_WIDTH_8 = dmacHw_REG_CTL_SRC_TR_WIDTH_8,	/* Source 8 bit  (1 byte) per transaction */
-	dmacHw_SRC_TRANSACTION_WIDTH_16 = dmacHw_REG_CTL_SRC_TR_WIDTH_16,	/* Source 16 bit (2 byte) per transaction */
-	dmacHw_SRC_TRANSACTION_WIDTH_32 = dmacHw_REG_CTL_SRC_TR_WIDTH_32,	/* Source 32 bit (4 byte) per transaction */
-	dmacHw_SRC_TRANSACTION_WIDTH_64 = dmacHw_REG_CTL_SRC_TR_WIDTH_64,	/* Source 64 bit (8 byte) per transaction */
-	dmacHw_DST_TRANSACTION_WIDTH_8 = dmacHw_REG_CTL_DST_TR_WIDTH_8,	/* Destination 8 bit  (1 byte) per transaction */
-	dmacHw_DST_TRANSACTION_WIDTH_16 = dmacHw_REG_CTL_DST_TR_WIDTH_16,	/* Destination 16 bit (2 byte) per transaction */
-	dmacHw_DST_TRANSACTION_WIDTH_32 = dmacHw_REG_CTL_DST_TR_WIDTH_32,	/* Destination 32 bit (4 byte) per transaction */
-	dmacHw_DST_TRANSACTION_WIDTH_64 = dmacHw_REG_CTL_DST_TR_WIDTH_64	/* Destination 64 bit (8 byte) per transaction */
-} dmacHw_TRANSACTION_WIDTH_e;
-
-typedef enum {
-	dmacHw_SRC_BURST_WIDTH_0 = dmacHw_REG_CTL_SRC_MSIZE_0,	/* Source No burst */
-	dmacHw_SRC_BURST_WIDTH_4 = dmacHw_REG_CTL_SRC_MSIZE_4,	/* Source 4  X dmacHw_TRANSACTION_WIDTH_xxx bytes per burst */
-	dmacHw_SRC_BURST_WIDTH_8 = dmacHw_REG_CTL_SRC_MSIZE_8,	/* Source 8  X dmacHw_TRANSACTION_WIDTH_xxx bytes per burst */
-	dmacHw_SRC_BURST_WIDTH_16 = dmacHw_REG_CTL_SRC_MSIZE_16,	/* Source 16 X dmacHw_TRANSACTION_WIDTH_xxx bytes per burst */
-	dmacHw_DST_BURST_WIDTH_0 = dmacHw_REG_CTL_DST_MSIZE_0,	/* Destination No burst */
-	dmacHw_DST_BURST_WIDTH_4 = dmacHw_REG_CTL_DST_MSIZE_4,	/* Destination 4  X dmacHw_TRANSACTION_WIDTH_xxx bytes per burst */
-	dmacHw_DST_BURST_WIDTH_8 = dmacHw_REG_CTL_DST_MSIZE_8,	/* Destination 8  X dmacHw_TRANSACTION_WIDTH_xxx bytes per burst */
-	dmacHw_DST_BURST_WIDTH_16 = dmacHw_REG_CTL_DST_MSIZE_16	/* Destination 16 X dmacHw_TRANSACTION_WIDTH_xxx bytes per burst */
-} dmacHw_BURST_WIDTH_e;
-
-typedef enum {
-	dmacHw_TRANSFER_TYPE_MEM_TO_MEM = dmacHw_REG_CTL_TTFC_MM_DMAC,	/* Memory to memory transfer */
-	dmacHw_TRANSFER_TYPE_PERIPHERAL_TO_MEM = dmacHw_REG_CTL_TTFC_PM_DMAC,	/* Peripheral to memory transfer */
-	dmacHw_TRANSFER_TYPE_MEM_TO_PERIPHERAL = dmacHw_REG_CTL_TTFC_MP_DMAC,	/* Memory to peripheral transfer */
-	dmacHw_TRANSFER_TYPE_PERIPHERAL_TO_PERIPHERAL = dmacHw_REG_CTL_TTFC_PP_DMAC	/* Peripheral to peripheral transfer */
-} dmacHw_TRANSFER_TYPE_e;
-
-typedef enum {
-	dmacHw_TRANSFER_MODE_PERREQUEST,	/* Block transfer per DMA request */
-	dmacHw_TRANSFER_MODE_CONTINUOUS,	/* Continuous transfer of streaming data */
-	dmacHw_TRANSFER_MODE_PERIODIC	/* Periodic transfer of streaming data */
-} dmacHw_TRANSFER_MODE_e;
-
-typedef enum {
-	dmacHw_SRC_ADDRESS_UPDATE_MODE_INC = dmacHw_REG_CTL_SINC_INC,	/* Increment source address after every transaction */
-	dmacHw_SRC_ADDRESS_UPDATE_MODE_DEC = dmacHw_REG_CTL_SINC_DEC,	/* Decrement source address after every transaction */
-	dmacHw_DST_ADDRESS_UPDATE_MODE_INC = dmacHw_REG_CTL_DINC_INC,	/* Increment destination address after every transaction */
-	dmacHw_DST_ADDRESS_UPDATE_MODE_DEC = dmacHw_REG_CTL_DINC_DEC,	/* Decrement destination address after every transaction */
-	dmacHw_SRC_ADDRESS_UPDATE_MODE_NC = dmacHw_REG_CTL_SINC_NC,	/* No change in source address after every transaction */
-	dmacHw_DST_ADDRESS_UPDATE_MODE_NC = dmacHw_REG_CTL_DINC_NC	/* No change in destination address after every transaction */
-} dmacHw_ADDRESS_UPDATE_MODE_e;
-
-typedef enum {
-	dmacHw_FLOW_CONTROL_DMA,	/* DMA working as flow controller (default) */
-	dmacHw_FLOW_CONTROL_PERIPHERAL	/* Peripheral working as flow controller */
-} dmacHw_FLOW_CONTROL_e;
-
-typedef enum {
-	dmacHw_TRANSFER_STATUS_BUSY,	/* DMA Transfer ongoing */
-	dmacHw_TRANSFER_STATUS_DONE,	/* DMA Transfer completed */
-	dmacHw_TRANSFER_STATUS_ERROR	/* DMA Transfer error */
-} dmacHw_TRANSFER_STATUS_e;
-
-typedef enum {
-	dmacHw_INTERRUPT_DISABLE,	/* Interrupt disable  */
-	dmacHw_INTERRUPT_ENABLE	/* Interrupt enable */
-} dmacHw_INTERRUPT_e;
-
-typedef enum {
-	dmacHw_INTERRUPT_STATUS_NONE = 0x0,	/* No DMA interrupt */
-	dmacHw_INTERRUPT_STATUS_TRANS = 0x1,	/* End of DMA transfer interrupt */
-	dmacHw_INTERRUPT_STATUS_BLOCK = 0x2,	/* End of block transfer interrupt */
-	dmacHw_INTERRUPT_STATUS_ERROR = 0x4	/* Error interrupt */
-} dmacHw_INTERRUPT_STATUS_e;
-
-typedef enum {
-	dmacHw_CONTROLLER_ATTRIB_CHANNEL_NUM,	/* Number of DMA channel */
-	dmacHw_CONTROLLER_ATTRIB_CHANNEL_MAX_BLOCK_SIZE,	/* Maximum channel burst size */
-	dmacHw_CONTROLLER_ATTRIB_MASTER_INTF_NUM,	/* Number of DMA master interface */
-	dmacHw_CONTROLLER_ATTRIB_CHANNEL_BUS_WIDTH,	/* Channel Data bus width */
-	dmacHw_CONTROLLER_ATTRIB_CHANNEL_FIFO_SIZE	/* Channel FIFO size */
-} dmacHw_CONTROLLER_ATTRIB_e;
-
-typedef unsigned long dmacHw_HANDLE_t;	/* DMA channel handle */
-typedef uint32_t dmacHw_ID_t;	/* DMA channel Id.  Must be created using
-				   "dmacHw_MAKE_CHANNEL_ID" macro
-				 */
-/* DMA channel configuration parameters */
-typedef struct {
-	uint32_t srcPeripheralPort;	/* Source peripheral port */
-	uint32_t dstPeripheralPort;	/* Destination peripheral port */
-	uint32_t srcStatusRegisterAddress;	/* Source status register address */
-	uint32_t dstStatusRegisterAddress;	/* Destination status register address of type  */
-
-	uint32_t srcGatherWidth;	/* Number of bytes gathered before successive gather opearation */
-	uint32_t srcGatherJump;	/* Number of bytes jumpped before successive gather opearation */
-	uint32_t dstScatterWidth;	/* Number of bytes sacattered before successive scatter opearation */
-	uint32_t dstScatterJump;	/* Number of bytes jumpped  before successive scatter opearation */
-	uint32_t maxDataPerBlock;	/* Maximum number of bytes to be transferred per block/descrptor.
-					   0 = Maximum possible.
-					 */
-
-	dmacHw_ADDRESS_UPDATE_MODE_e srcUpdate;	/* Source address update mode */
-	dmacHw_ADDRESS_UPDATE_MODE_e dstUpdate;	/* Destination address update mode */
-	dmacHw_TRANSFER_TYPE_e transferType;	/* DMA transfer type  */
-	dmacHw_TRANSFER_MODE_e transferMode;	/* DMA transfer mode */
-	dmacHw_MASTER_INTERFACE_e srcMasterInterface;	/* DMA source interface  */
-	dmacHw_MASTER_INTERFACE_e dstMasterInterface;	/* DMA destination interface */
-	dmacHw_TRANSACTION_WIDTH_e srcMaxTransactionWidth;	/* Source transaction width   */
-	dmacHw_TRANSACTION_WIDTH_e dstMaxTransactionWidth;	/* Destination transaction width */
-	dmacHw_BURST_WIDTH_e srcMaxBurstWidth;	/* Source burst width */
-	dmacHw_BURST_WIDTH_e dstMaxBurstWidth;	/* Destination burst width */
-	dmacHw_INTERRUPT_e blockTransferInterrupt;	/* Block trsnafer interrupt */
-	dmacHw_INTERRUPT_e completeTransferInterrupt;	/* Complete DMA trsnafer interrupt */
-	dmacHw_INTERRUPT_e errorInterrupt;	/* Error interrupt */
-	dmacHw_CHANNEL_PRIORITY_e channelPriority;	/* Channel priority */
-	dmacHw_FLOW_CONTROL_e flowControler;	/* Data flow controller */
-} dmacHw_CONFIG_t;
-
-/****************************************************************************/
-/**
-*  @brief   Initializes DMA
-*
-*  This function initializes DMA CSP driver
-*
-*  @note
-*     Must be called before using any DMA channel
-*/
-/****************************************************************************/
-void dmacHw_initDma(void);
-
-/****************************************************************************/
-/**
-*  @brief   Exit function for  DMA
-*
-*  This function isolates DMA from the system
-*
-*/
-/****************************************************************************/
-void dmacHw_exitDma(void);
-
-/****************************************************************************/
-/**
-*  @brief   Gets a handle to a DMA channel
-*
-*  This function returns a handle, representing a control block of a particular DMA channel
-*
-*  @return  -1       - On Failure
-*            handle  - On Success, representing a channel control block
-*
-*  @note
-*     None  Channel ID must be created using "dmacHw_MAKE_CHANNEL_ID" macro
-*/
-/****************************************************************************/
-dmacHw_HANDLE_t dmacHw_getChannelHandle(dmacHw_ID_t channelId	/* [ IN ] DMA Channel Id */
-    );
-
-/****************************************************************************/
-/**
-*  @brief   Initializes a DMA channel for use
-*
-*  This function initializes and resets a DMA channel for use
-*
-*  @return  -1     - On Failure
-*            0     - On Success
-*
-*  @note
-*     None
-*/
-/****************************************************************************/
-int dmacHw_initChannel(dmacHw_HANDLE_t handle	/*  [ IN ] DMA Channel handle  */
-    );
-
-/****************************************************************************/
-/**
-*  @brief  Estimates number of descriptor needed to perform certain DMA transfer
-*
-*
-*  @return  On failure : -1
-*           On success : Number of descriptor count
-*
-*
-*/
-/****************************************************************************/
-int dmacHw_calculateDescriptorCount(dmacHw_CONFIG_t *pConfig,	/*   [ IN ] Configuration settings */
-				    void *pSrcAddr,	/*   [ IN ] Source (Peripheral/Memory) address */
-				    void *pDstAddr,	/*   [ IN ] Destination (Peripheral/Memory) address */
-				    size_t dataLen	/*   [ IN ] Data length in bytes */
-    );
-
-/****************************************************************************/
-/**
-*  @brief   Initializes descriptor ring
-*
-*  This function will initializes the descriptor ring of a DMA channel
-*
-*
-*  @return   -1 - On failure
-*             0 - On success
-*  @note
-*     - "len" parameter should be obtained from "dmacHw_descriptorLen"
-*     - Descriptor buffer MUST be 32 bit aligned and uncached as it
-*       is accessed by ARM and DMA
-*/
-/****************************************************************************/
-int dmacHw_initDescriptor(void *pDescriptorVirt,	/*  [ IN ] Virtual address of uncahced buffer allocated to form descriptor ring */
-			  uint32_t descriptorPhyAddr,	/*  [ IN ] Physical address of pDescriptorVirt (descriptor buffer) */
-			  uint32_t len,	/*  [ IN ] Size of the pBuf */
-			  uint32_t num	/*  [ IN ] Number of descriptor in the ring */
-    );
-
-/****************************************************************************/
-/**
-*  @brief  Finds amount of memory required to form a descriptor ring
-*
-*
-*  @return   Number of bytes required to form a descriptor ring
-*
-*
-*  @note
-*     None
-*/
-/****************************************************************************/
-uint32_t dmacHw_descriptorLen(uint32_t descCnt	/*  [ IN ] Number of descriptor in the ring */
-    );
-
-/****************************************************************************/
-/**
-*  @brief   Configure DMA channel
-*
-*  @return  0  : On success
-*           -1 : On failure
-*/
-/****************************************************************************/
-int dmacHw_configChannel(dmacHw_HANDLE_t handle,	/*  [ IN ] DMA Channel handle  */
-			 dmacHw_CONFIG_t *pConfig	/*   [ IN ] Configuration settings */
-    );
-
-/****************************************************************************/
-/**
-*  @brief   Set descriptors for known data length
-*
-*  When DMA has to work as a flow controller, this function prepares the
-*  descriptor chain to transfer data
-*
-*  from:
-*          - Memory to memory
-*          - Peripheral to memory
-*          - Memory to Peripheral
-*          - Peripheral to Peripheral
-*
-*  @return   -1 - On failure
-*             0 - On success
-*
-*/
-/****************************************************************************/
-int dmacHw_setDataDescriptor(dmacHw_CONFIG_t *pConfig,	/*  [ IN ] Configuration settings */
-			     void *pDescriptor,	/*  [ IN ] Descriptor buffer  */
-			     void *pSrcAddr,	/*  [ IN ] Source (Peripheral/Memory) address */
-			     void *pDstAddr,	/*  [ IN ] Destination (Peripheral/Memory) address */
-			     size_t dataLen	/*  [ IN ] Length in bytes   */
-    );
-
-/****************************************************************************/
-/**
-*  @brief   Indicates whether DMA transfer is in progress or completed
-*
-*  @return   DMA transfer status
-*          dmacHw_TRANSFER_STATUS_BUSY:         DMA Transfer ongoing
-*          dmacHw_TRANSFER_STATUS_DONE:         DMA Transfer completed
-*          dmacHw_TRANSFER_STATUS_ERROR:        DMA Transfer error
-*
-*/
-/****************************************************************************/
-dmacHw_TRANSFER_STATUS_e dmacHw_transferCompleted(dmacHw_HANDLE_t handle	/*   [ IN ] DMA Channel handle  */
-    );
-
-/****************************************************************************/
-/**
-*  @brief   Set descriptor carrying control information
-*
-*  This function will be used to send specific control information to the device
-*  using the DMA channel
-*
-*
-*  @return  -1 - On failure
-*            0 - On success
-*
-*  @note
-*     None
-*/
-/****************************************************************************/
-int dmacHw_setControlDescriptor(dmacHw_CONFIG_t *pConfig,	/*  [ IN ] Configuration settings */
-				void *pDescriptor,	/*  [ IN ] Descriptor buffer  */
-				uint32_t ctlAddress,	/*  [ IN ] Address of the device control register  */
-				uint32_t control	/*  [ IN ] Device control information */
-    );
-
-/****************************************************************************/
-/**
-*  @brief   Read data DMA transferred to memory
-*
-*  This function will read data that has been DMAed to memory while transferring from:
-*          - Memory to memory
-*          - Peripheral to memory
-*
-*  @return  0 - No more data is available to read
-*           1 - More data might be available to read
-*
-*/
-/****************************************************************************/
-int dmacHw_readTransferredData(dmacHw_HANDLE_t handle,	/*  [ IN ] DMA Channel handle    */
-			       dmacHw_CONFIG_t *pConfig,	/*  [ IN ]  Configuration settings */
-			       void *pDescriptor,	/*  [ IN ] Descriptor buffer  */
-			       void **ppBbuf,	/*  [ OUT ] Data received */
-			       size_t *pLlen	/*  [ OUT ] Length of the data received */
-    );
-
-/****************************************************************************/
-/**
-*  @brief   Prepares descriptor ring, when source peripheral working as a flow controller
-*
-*  This function will form the descriptor ring by allocating buffers, when source peripheral
-*  has to work as a flow controller to transfer data from:
-*           - Peripheral to memory.
-*
-*  @return  -1 - On failure
-*            0 - On success
-*
-*
-*  @note
-*     None
-*/
-/****************************************************************************/
-int dmacHw_setVariableDataDescriptor(dmacHw_HANDLE_t handle,	/*  [ IN ] DMA Channel handle   */
-				     dmacHw_CONFIG_t *pConfig,	/*  [ IN ] Configuration settings */
-				     void *pDescriptor,	/*  [ IN ] Descriptor buffer  */
-				     uint32_t srcAddr,	/*  [ IN ] Source peripheral address */
-				     void *(*fpAlloc) (int len),	/*  [ IN ] Function pointer  that provides destination memory */
-				     int len,	/*  [ IN ] Number of bytes "fpAlloc" will allocate for destination */
-				     int num	/*  [ IN ] Number of descriptor to set */
-    );
-
-/****************************************************************************/
-/**
-*  @brief   Program channel register to initiate transfer
-*
-*  @return  void
-*
-*
-*  @note
-*     - Descriptor buffer MUST ALWAYS be flushed before calling this function
-*     - This function should also be called from ISR to program the channel with
-*       pending descriptors
-*/
-/****************************************************************************/
-void dmacHw_initiateTransfer(dmacHw_HANDLE_t handle,	/*   [ IN ] DMA Channel handle */
-			     dmacHw_CONFIG_t *pConfig,	/*   [ IN ] Configuration settings */
-			     void *pDescriptor	/*   [ IN ] Descriptor buffer  */
-    );
-
-/****************************************************************************/
-/**
-*  @brief   Resets descriptor control information
-*
-*  @return  void
-*/
-/****************************************************************************/
-void dmacHw_resetDescriptorControl(void *pDescriptor	/*   [ IN ] Descriptor buffer  */
-    );
-
-/****************************************************************************/
-/**
-*  @brief   Program channel register to stop transfer
-*
-*  Ensures the channel is not doing any transfer after calling this function
-*
-*  @return  void
-*
-*/
-/****************************************************************************/
-void dmacHw_stopTransfer(dmacHw_HANDLE_t handle	/*   [ IN ] DMA Channel handle */
-    );
-
-/****************************************************************************/
-/**
-*  @brief   Check the existence of pending descriptor
-*
-*  This function confirmes if there is any pending descriptor in the chain
-*  to program the channel
-*
-*  @return  1 : Channel need to be programmed with pending descriptor
-*           0 : No more pending descriptor to programe the channel
-*
-*  @note
-*     - This function should be called from ISR in case there are pending
-*       descriptor to program the channel.
-*
-*     Example:
-*
-*     dmac_isr ()
-*     {
-*         ...
-*         if (dmacHw_descriptorPending (handle))
-*         {
-*            dmacHw_initiateTransfer (handle);
-*         }
-*     }
-*
-*/
-/****************************************************************************/
-uint32_t dmacHw_descriptorPending(dmacHw_HANDLE_t handle,	/*   [ IN ] DMA Channel handle */
-				  void *pDescriptor	/*   [ IN ] Descriptor buffer */
-    );
-
-/****************************************************************************/
-/**
-*  @brief   Deallocates source or destination memory, allocated
-*
-*  This function can be called to deallocate data memory that was DMAed successfully
-*
-*  @return  -1  - On failure
-*            0  - On success
-*
-*  @note
-*     This function will be called ONLY, when source OR destination address is pointing
-*     to dynamic memory
-*/
-/****************************************************************************/
-int dmacHw_freeMem(dmacHw_CONFIG_t *pConfig,	/*  [ IN ] Configuration settings */
-		   void *pDescriptor,	/*  [ IN ] Descriptor buffer  */
-		   void (*fpFree) (void *)	/*  [ IN ] Function pointer to free data memory */
-    );
-
-/****************************************************************************/
-/**
-*  @brief   Clears the interrupt
-*
-*  This function clears the DMA channel specific interrupt
-*
-*  @return   N/A
-*
-*  @note
-*     Must be called under the context of ISR
-*/
-/****************************************************************************/
-void dmacHw_clearInterrupt(dmacHw_HANDLE_t handle	/*  [ IN ] DMA Channel handle  */
-    );
-
-/****************************************************************************/
-/**
-*  @brief   Returns the cause of channel specific DMA interrupt
-*
-*  This function returns the cause of interrupt
-*
-*  @return  Interrupt status, each bit representing a specific type of interrupt
-*           of type dmacHw_INTERRUPT_STATUS_e
-*  @note
-*           This function should be called under the context of ISR
-*/
-/****************************************************************************/
-dmacHw_INTERRUPT_STATUS_e dmacHw_getInterruptStatus(dmacHw_HANDLE_t handle	/*  [ IN ] DMA Channel handle  */
-    );
-
-/****************************************************************************/
-/**
-*  @brief   Indentifies a DMA channel causing interrupt
-*
-*  This functions returns a channel causing interrupt of type dmacHw_INTERRUPT_STATUS_e
-*
-*  @return  NULL   : No channel causing DMA interrupt
-*           ! NULL : Handle to a channel causing DMA interrupt
-*  @note
-*     dmacHw_clearInterrupt() must be called with a valid handle after calling this function
-*/
-/****************************************************************************/
-dmacHw_HANDLE_t dmacHw_getInterruptSource(void);
-
-/****************************************************************************/
-/**
-*  @brief   Sets channel specific user data
-*
-*  This function associates user data to a specific DMA channel
-*
-*/
-/****************************************************************************/
-void dmacHw_setChannelUserData(dmacHw_HANDLE_t handle,	/*  [ IN ] DMA Channel handle  */
-			       void *userData	/*  [ IN ] User data  */
-    );
-
-/****************************************************************************/
-/**
-*  @brief   Gets channel specific user data
-*
-*  This function returns user data specific to a DMA channel
-*
-*  @return   user data
-*/
-/****************************************************************************/
-void *dmacHw_getChannelUserData(dmacHw_HANDLE_t handle	/*  [ IN ] DMA Channel handle  */
-    );
-
-/****************************************************************************/
-/**
-*  @brief   Displays channel specific registers and other control parameters
-*
-*
-*  @return  void
-*
-*  @note
-*     None
-*/
-/****************************************************************************/
-void dmacHw_printDebugInfo(dmacHw_HANDLE_t handle,	/*  [ IN ] DMA Channel handle  */
-			   void *pDescriptor,	/*  [ IN ] Descriptor buffer  */
-			   int (*fpPrint) (const char *, ...)	/*  [ IN ] Print callback function */
-    );
-
-/****************************************************************************/
-/**
-*  @brief   Provides DMA controller attributes
-*
-*
-*  @return  DMA controller attributes
-*
-*  @note
-*     None
-*/
-/****************************************************************************/
-uint32_t dmacHw_getDmaControllerAttribute(dmacHw_HANDLE_t handle,	/*  [ IN ]  DMA Channel handle  */
-					  dmacHw_CONTROLLER_ATTRIB_e attr	/*  [ IN ]  DMA Controller attribute of type  dmacHw_CONTROLLER_ATTRIB_e */
-    );
-
-#endif /* _DMACHW_H */
diff --git a/arch/arm/mach-bcmring/include/csp/errno.h b/arch/arm/mach-bcmring/include/csp/errno.h
deleted file mode 100644
index 51357dd..0000000
--- a/arch/arm/mach-bcmring/include/csp/errno.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*****************************************************************************
-* Copyright 2003 - 2008 Broadcom Corporation.  All rights reserved.
-*
-* Unless you and Broadcom execute a separate written software license
-* agreement governing use of this software, this software is licensed to you
-* under the terms of the GNU General Public License version 2, available at
-* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
-*
-* Notwithstanding the above, under no circumstances may you combine this
-* software in any way with any other Broadcom software provided under a
-* license other than the GPL, without Broadcom's express prior written
-* consent.
-*****************************************************************************/
-
-#ifndef CSP_ERRNO_H
-#define CSP_ERRNO_H
-
-/* ---- Include Files ---------------------------------------------------- */
-
-#if   defined(__KERNEL__)
-#include <linux/errno.h>
-#elif defined(CSP_SIMULATION)
-#include <asm-generic/errno.h>
-#else
-#include <errno.h>
-#endif
-
-/* ---- Public Constants and Types --------------------------------------- */
-/* ---- Public Variable Externs ------------------------------------------ */
-/* ---- Public Function Prototypes --------------------------------------- */
-
-#endif /* CSP_ERRNO_H */
diff --git a/arch/arm/mach-bcmring/include/csp/intcHw.h b/arch/arm/mach-bcmring/include/csp/intcHw.h
deleted file mode 100644
index 1c639c8..0000000
--- a/arch/arm/mach-bcmring/include/csp/intcHw.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*****************************************************************************
-* Copyright 2003 - 2008 Broadcom Corporation.  All rights reserved.
-*
-* Unless you and Broadcom execute a separate written software license
-* agreement governing use of this software, this software is licensed to you
-* under the terms of the GNU General Public License version 2, available at
-* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
-*
-* Notwithstanding the above, under no circumstances may you combine this
-* software in any way with any other Broadcom software provided under a
-* license other than the GPL, without Broadcom's express prior written
-* consent.
-*****************************************************************************/
-
-
-/****************************************************************************/
-/**
-*  @file    intcHw.h
-*
-*  @brief   generic interrupt controller API
-*
-*  @note
-*     None
-*/
-/****************************************************************************/
-
-#ifndef _INTCHW_H
-#define _INTCHW_H
-
-/* ---- Include Files ---------------------------------------------------- */
-#include <mach/csp/intcHw_reg.h>
-
-/* ---- Public Constants and Types --------------------------------------- */
-/* ---- Public Variable Externs ------------------------------------------ */
-/* ---- Public Function Prototypes --------------------------------------- */
-static inline void intcHw_irq_disable(void *basep, uint32_t mask);
-static inline void intcHw_irq_enable(void *basep, uint32_t mask);
-
-#endif /* _INTCHW_H */
-
diff --git a/arch/arm/mach-bcmring/include/csp/module.h b/arch/arm/mach-bcmring/include/csp/module.h
deleted file mode 100644
index c30d2a5..0000000
--- a/arch/arm/mach-bcmring/include/csp/module.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*****************************************************************************
-* Copyright 2003 - 2008 Broadcom Corporation.  All rights reserved.
-*
-* Unless you and Broadcom execute a separate written software license
-* agreement governing use of this software, this software is licensed to you
-* under the terms of the GNU General Public License version 2, available at
-* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
-*
-* Notwithstanding the above, under no circumstances may you combine this
-* software in any way with any other Broadcom software provided under a
-* license other than the GPL, without Broadcom's express prior written
-* consent.
-*****************************************************************************/
-
-
-#ifndef CSP_MODULE_H
-#define CSP_MODULE_H
-
-/* ---- Include Files ---------------------------------------------------- */
-
-#ifdef __KERNEL__
-    #include <linux/module.h>
-#else
-    #define EXPORT_SYMBOL(symbol)
-#endif
-
-/* ---- Public Constants and Types --------------------------------------- */
-/* ---- Public Variable Externs ------------------------------------------ */
-/* ---- Public Function Prototypes --------------------------------------- */
-
-
-#endif /* CSP_MODULE_H */
diff --git a/arch/arm/mach-bcmring/include/csp/reg.h b/arch/arm/mach-bcmring/include/csp/reg.h
deleted file mode 100644
index 56654d2..0000000
--- a/arch/arm/mach-bcmring/include/csp/reg.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/*****************************************************************************
-* Copyright 2003 - 2008 Broadcom Corporation.  All rights reserved.
-*
-* Unless you and Broadcom execute a separate written software license
-* agreement governing use of this software, this software is licensed to you
-* under the terms of the GNU General Public License version 2, available at
-* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
-*
-* Notwithstanding the above, under no circumstances may you combine this
-* software in any way with any other Broadcom software provided under a
-* license other than the GPL, without Broadcom's express prior written
-* consent.
-*****************************************************************************/
-
-/****************************************************************************/
-/**
-*  @file    reg.h
-*
-*  @brief   Generic register definitions used in CSP
-*/
-/****************************************************************************/
-
-#ifndef CSP_REG_H
-#define CSP_REG_H
-
-/* ---- Include Files ---------------------------------------------------- */
-
-#include <csp/stdint.h>
-
-/* ---- Public Constants and Types --------------------------------------- */
-
-#define __REG32(x)      (*((volatile uint32_t *)(x)))
-#define __REG16(x)      (*((volatile uint16_t *)(x)))
-#define __REG8(x)       (*((volatile uint8_t *) (x)))
-
-/* Macros used to define a sequence of reserved registers. The start / end */
-/* are byte offsets in the particular register definition, with the "end" */
-/* being the offset of the next un-reserved register. E.g. if offsets */
-/* 0x10 through to 0x1f are reserved, then this reserved area could be */
-/* specified as follows. */
-/*  typedef struct */
-/*  { */
-/*      uint32_t reg1;           offset 0x00 */
-/*      uint32_t reg2;           offset 0x04 */
-/*      uint32_t reg3;           offset 0x08 */
-/*      uint32_t reg4;           offset 0x0c */
-/*      REG32_RSVD(0x10, 0x20); */
-/*      uint32_t reg5;           offset 0x20 */
-/*      ... */
-/*  } EXAMPLE_REG_t; */
-#define REG8_RSVD(start, end)   uint8_t rsvd_##start[(end - start) / sizeof(uint8_t)]
-#define REG16_RSVD(start, end)  uint16_t rsvd_##start[(end - start) / sizeof(uint16_t)]
-#define REG32_RSVD(start, end)  uint32_t rsvd_##start[(end - start) / sizeof(uint32_t)]
-
-/* ---- Public Variable Externs ------------------------------------------ */
-/* ---- Public Function Prototypes --------------------------------------- */
-
-/* Note: When protecting multiple statements, the REG_LOCAL_IRQ_SAVE and */
-/* REG_LOCAL_IRQ_RESTORE must be enclosed in { } to allow the  */
-/* flags variable to be declared locally. */
-/* e.g. */
-/*    statement1; */
-/*    { */
-/*       REG_LOCAL_IRQ_SAVE; */
-/*       <multiple statements here> */
-/*       REG_LOCAL_IRQ_RESTORE; */
-/*    } */
-/*    statement2; */
-/*  */
-
-#if defined(__KERNEL__) && !defined(STANDALONE)
-#include <mach/hardware.h>
-#include <linux/interrupt.h>
-
-#define REG_LOCAL_IRQ_SAVE      HW_DECLARE_SPINLOCK(reg32) \
-	unsigned long flags; HW_IRQ_SAVE(reg32, flags)
-
-#define REG_LOCAL_IRQ_RESTORE   HW_IRQ_RESTORE(reg32, flags)
-
-#else
-
-#define REG_LOCAL_IRQ_SAVE
-#define REG_LOCAL_IRQ_RESTORE
-
-#endif
-
-static inline void reg32_modify_and(volatile uint32_t *reg, uint32_t value)
-{
-	REG_LOCAL_IRQ_SAVE;
-	*reg &= value;
-	REG_LOCAL_IRQ_RESTORE;
-}
-
-static inline void reg32_modify_or(volatile uint32_t *reg, uint32_t value)
-{
-	REG_LOCAL_IRQ_SAVE;
-	*reg |= value;
-	REG_LOCAL_IRQ_RESTORE;
-}
-
-static inline void reg32_modify_mask(volatile uint32_t *reg, uint32_t mask,
-				     uint32_t value)
-{
-	REG_LOCAL_IRQ_SAVE;
-	*reg = (*reg & mask) | value;
-	REG_LOCAL_IRQ_RESTORE;
-}
-
-static inline void reg32_write(volatile uint32_t *reg, uint32_t value)
-{
-	*reg = value;
-}
-
-#endif /* CSP_REG_H */
diff --git a/arch/arm/mach-bcmring/include/csp/secHw.h b/arch/arm/mach-bcmring/include/csp/secHw.h
deleted file mode 100644
index b9d7e07..0000000
--- a/arch/arm/mach-bcmring/include/csp/secHw.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*****************************************************************************
-* Copyright 2004 - 2008 Broadcom Corporation.  All rights reserved.
-*
-* Unless you and Broadcom execute a separate written software license
-* agreement governing use of this software, this software is licensed to you
-* under the terms of the GNU General Public License version 2, available at
-* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
-*
-* Notwithstanding the above, under no circumstances may you combine this
-* software in any way with any other Broadcom software provided under a
-* license other than the GPL, without Broadcom's express prior written
-* consent.
-*****************************************************************************/
-
-/****************************************************************************/
-/**
-*  @file    secHw.h
-*
-*  @brief   Definitions for accessing low level security features
-*
-*/
-/****************************************************************************/
-#ifndef SECHW_H
-#define SECHW_H
-
-typedef void (*secHw_FUNC_t) (void);
-
-typedef enum {
-	secHw_MODE_SECURE = 0x0,	/* Switches processor into secure mode */
-	secHw_MODE_NONSECURE = 0x1	/* Switches processor into non-secure mode */
-} secHw_MODE;
-
-/****************************************************************************/
-/**
-*  @brief   Requesting to execute the function in secure mode
-*
-*  This function requests the given function to run in secure mode
-*
-*/
-/****************************************************************************/
-void secHw_RunSecure(secHw_FUNC_t	/* Function to run in secure mode */
-    );
-
-/****************************************************************************/
-/**
-*  @brief   Sets the  mode
-*
-*  his function sets the processor mode (secure/non-secure)
-*
-*/
-/****************************************************************************/
-void secHw_SetMode(secHw_MODE	/* Processor mode */
-    );
-
-/****************************************************************************/
-/**
-*  @brief   Get the current mode
-*
-*  This function retieves the processor mode (secure/non-secure)
-*
-*/
-/****************************************************************************/
-void secHw_GetMode(secHw_MODE *);
-
-#endif /* SECHW_H */
diff --git a/arch/arm/mach-bcmring/include/csp/stdint.h b/arch/arm/mach-bcmring/include/csp/stdint.h
deleted file mode 100644
index 3a8718b..0000000
--- a/arch/arm/mach-bcmring/include/csp/stdint.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*****************************************************************************
-* Copyright 2003 - 2008 Broadcom Corporation.  All rights reserved.
-*
-* Unless you and Broadcom execute a separate written software license
-* agreement governing use of this software, this software is licensed to you
-* under the terms of the GNU General Public License version 2, available at
-* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
-*
-* Notwithstanding the above, under no circumstances may you combine this
-* software in any way with any other Broadcom software provided under a
-* license other than the GPL, without Broadcom's express prior written
-* consent.
-*****************************************************************************/
-
-#ifndef CSP_STDINT_H
-#define CSP_STDINT_H
-
-/* ---- Include Files ---------------------------------------------------- */
-
-#ifdef __KERNEL__
-#include <linux/types.h>
-#else
-#include <stdint.h>
-#endif
-
-/* ---- Public Constants and Types --------------------------------------- */
-/* ---- Public Variable Externs ------------------------------------------ */
-/* ---- Public Function Prototypes --------------------------------------- */
-
-#endif /* CSP_STDINT_H */
diff --git a/arch/arm/mach-bcmring/include/csp/string.h b/arch/arm/mach-bcmring/include/csp/string.h
deleted file mode 100644
index ad9e400..0000000
--- a/arch/arm/mach-bcmring/include/csp/string.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*****************************************************************************
-* Copyright 2003 - 2008 Broadcom Corporation.  All rights reserved.
-*
-* Unless you and Broadcom execute a separate written software license
-* agreement governing use of this software, this software is licensed to you
-* under the terms of the GNU General Public License version 2, available at
-* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
-*
-* Notwithstanding the above, under no circumstances may you combine this
-* software in any way with any other Broadcom software provided under a
-* license other than the GPL, without Broadcom's express prior written
-* consent.
-*****************************************************************************/
-
-
-
-#ifndef CSP_STRING_H
-#define CSP_STRING_H
-
-/* ---- Include Files ---------------------------------------------------- */
-
-#ifdef __KERNEL__
-   #include <linux/string.h>
-#else
-   #include <string.h>
-#endif
-
-/* ---- Public Constants and Types --------------------------------------- */
-/* ---- Public Variable Externs ------------------------------------------ */
-/* ---- Public Function Prototypes --------------------------------------- */
-
-
-#endif /* CSP_STRING_H */
-
diff --git a/arch/arm/mach-bcmring/include/csp/tmrHw.h b/arch/arm/mach-bcmring/include/csp/tmrHw.h
deleted file mode 100644
index 2cbb530..0000000
--- a/arch/arm/mach-bcmring/include/csp/tmrHw.h
+++ /dev/null
@@ -1,263 +0,0 @@
-/*****************************************************************************
-* Copyright 2004 - 2008 Broadcom Corporation.  All rights reserved.
-*
-* Unless you and Broadcom execute a separate written software license
-* agreement governing use of this software, this software is licensed to you
-* under the terms of the GNU General Public License version 2, available at
-* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
-*
-* Notwithstanding the above, under no circumstances may you combine this
-* software in any way with any other Broadcom software provided under a
-* license other than the GPL, without Broadcom's express prior written
-* consent.
-*****************************************************************************/
-
-/****************************************************************************/
-/**
-*  @file    tmrHw.h
-*
-*  @brief   API definitions for low level Timer driver
-*
-*/
-/****************************************************************************/
-#ifndef _TMRHW_H
-#define _TMRHW_H
-
-#include <csp/stdint.h>
-
-typedef uint32_t tmrHw_ID_t;	/* Timer ID */
-typedef uint32_t tmrHw_COUNT_t;	/* Timer count */
-typedef uint32_t tmrHw_INTERVAL_t;	/* Timer interval */
-typedef uint32_t tmrHw_RATE_t;	/* Timer event (count/interrupt) rate */
-
-typedef enum {
-	tmrHw_INTERRUPT_STATUS_SET,	/* Interrupted  */
-	tmrHw_INTERRUPT_STATUS_UNSET	/* No Interrupt */
-} tmrHw_INTERRUPT_STATUS_e;
-
-typedef enum {
-	tmrHw_CAPABILITY_CLOCK,	/* Clock speed in HHz */
-	tmrHw_CAPABILITY_RESOLUTION	/* Timer resolution in bits */
-} tmrHw_CAPABILITY_e;
-
-/****************************************************************************/
-/**
-*  @brief   Get timer capability
-*
-*  This function returns various capabilities/attributes of a timer
-*
-*  @return  Numeric capability
-*
-*/
-/****************************************************************************/
-uint32_t tmrHw_getTimerCapability(tmrHw_ID_t timerId,	/*  [ IN ] Timer Id */
-				  tmrHw_CAPABILITY_e capability	/*  [ IN ] Timer capability */
-);
-
-/****************************************************************************/
-/**
-*  @brief   Configures a periodic timer in terms of timer interrupt rate
-*
-*  This function initializes a periodic timer to generate specific number of
-*  timer interrupt per second
-*
-*  @return   On success: Effective timer frequency
-*            On failure: 0
-*
-*/
-/****************************************************************************/
-tmrHw_RATE_t tmrHw_setPeriodicTimerRate(tmrHw_ID_t timerId,	/*  [ IN ] Timer Id */
-					tmrHw_RATE_t rate	/*  [ IN ] Number of timer interrupt per second */
-);
-
-/****************************************************************************/
-/**
-*  @brief   Configures a periodic timer to generate timer interrupt after
-*           certain time interval
-*
-*  This function initializes a periodic timer to generate timer interrupt
-*  after every time interval in millisecond
-*
-*  @return   On success: Effective interval set in mili-second
-*            On failure: 0
-*
-*/
-/****************************************************************************/
-tmrHw_INTERVAL_t tmrHw_setPeriodicTimerInterval(tmrHw_ID_t timerId,	/*  [ IN ] Timer Id */
-						tmrHw_INTERVAL_t msec	/*  [ IN ] Interval in mili-second */
-);
-
-/****************************************************************************/
-/**
-*  @brief   Configures a periodic timer to generate timer interrupt just once
-*           after certain time interval
-*
-*  This function initializes a periodic timer to generate a single ticks after
-*  certain time interval in millisecond
-*
-*  @return   On success: Effective interval set in mili-second
-*            On failure: 0
-*
-*/
-/****************************************************************************/
-tmrHw_INTERVAL_t tmrHw_setOneshotTimerInterval(tmrHw_ID_t timerId,	/*  [ IN ] Timer Id */
-					       tmrHw_INTERVAL_t msec	/*  [ IN ] Interval in mili-second */
-);
-
-/****************************************************************************/
-/**
-*  @brief   Configures a timer to run as a free running timer
-*
-*  This function initializes a timer to run as a free running timer
-*
-*  @return   Timer resolution (count / sec)
-*
-*/
-/****************************************************************************/
-tmrHw_RATE_t tmrHw_setFreeRunningTimer(tmrHw_ID_t timerId,	/*  [ IN ] Timer Id */
-				       uint32_t divider	/*  [ IN ] Dividing the clock frequency */
-) __attribute__ ((section(".aramtext")));
-
-/****************************************************************************/
-/**
-*  @brief   Starts a timer
-*
-*  This function starts a preconfigured timer
-*
-*  @return  -1     - On Failure
-*            0     - On Success
-*/
-/****************************************************************************/
-int tmrHw_startTimer(tmrHw_ID_t timerId	/*  [ IN ] Timer id */
-) __attribute__ ((section(".aramtext")));
-
-/****************************************************************************/
-/**
-*  @brief   Stops a timer
-*
-*  This function stops a running timer
-*
-*  @return  -1     - On Failure
-*            0     - On Success
-*/
-/****************************************************************************/
-int tmrHw_stopTimer(tmrHw_ID_t timerId	/*  [ IN ] Timer id */
-);
-
-/****************************************************************************/
-/**
-*  @brief   Gets current timer count
-*
-*  This function returns the current timer value
-*
-*  @return  Current downcounting timer value
-*
-*/
-/****************************************************************************/
-tmrHw_COUNT_t tmrHw_GetCurrentCount(tmrHw_ID_t timerId	/*  [ IN ] Timer id */
-) __attribute__ ((section(".aramtext")));
-
-/****************************************************************************/
-/**
-*  @brief   Gets timer count rate
-*
-*  This function returns the number of counts per second
-*
-*  @return  Count rate
-*
-*/
-/****************************************************************************/
-tmrHw_RATE_t tmrHw_getCountRate(tmrHw_ID_t timerId	/*  [ IN ] Timer id */
-) __attribute__ ((section(".aramtext")));
-
-/****************************************************************************/
-/**
-*  @brief   Enables timer interrupt
-*
-*  This function enables the timer interrupt
-*
-*  @return   N/A
-*
-*/
-/****************************************************************************/
-void tmrHw_enableInterrupt(tmrHw_ID_t timerId	/*  [ IN ] Timer id */
-);
-
-/****************************************************************************/
-/**
-*  @brief   Disables timer interrupt
-*
-*  This function disable the timer interrupt
-*
-*  @return   N/A
-*/
-/****************************************************************************/
-void tmrHw_disableInterrupt(tmrHw_ID_t timerId	/*  [ IN ] Timer id */
-);
-
-/****************************************************************************/
-/**
-*  @brief   Clears the interrupt
-*
-*  This function clears the timer interrupt
-*
-*  @return   N/A
-*
-*  @note
-*     Must be called under the context of ISR
-*/
-/****************************************************************************/
-void tmrHw_clearInterrupt(tmrHw_ID_t timerId	/*  [ IN ] Timer id */
-);
-
-/****************************************************************************/
-/**
-*  @brief   Gets the interrupt status
-*
-*  This function returns timer interrupt status
-*
-*  @return   Interrupt status
-*/
-/****************************************************************************/
-tmrHw_INTERRUPT_STATUS_e tmrHw_getInterruptStatus(tmrHw_ID_t timerId	/*  [ IN ] Timer id */
-);
-
-/****************************************************************************/
-/**
-*  @brief   Indentifies a timer causing interrupt
-*
-*  This functions returns a timer causing interrupt
-*
-*  @return  0xFFFFFFFF   : No timer causing an interrupt
-*           ! 0xFFFFFFFF : timer causing an interrupt
-*  @note
-*     tmrHw_clearIntrrupt() must be called with a valid timer id after calling this function
-*/
-/****************************************************************************/
-tmrHw_ID_t tmrHw_getInterruptSource(void);
-
-/****************************************************************************/
-/**
-*  @brief   Displays specific timer registers
-*
-*
-*  @return  void
-*
-*/
-/****************************************************************************/
-void tmrHw_printDebugInfo(tmrHw_ID_t timerId,	/*  [ IN ] Timer id */
-			  int (*fpPrint) (const char *, ...)	/*  [ IN ] Print callback function */
-);
-
-/****************************************************************************/
-/**
-*  @brief   Use a timer to perform a busy wait delay for a number of usecs.
-*
-*  @return   N/A
-*/
-/****************************************************************************/
-void tmrHw_udelay(tmrHw_ID_t timerId,	/*  [ IN ] Timer id */
-		  unsigned long usecs	/*  [ IN ] usec to delay */
-) __attribute__ ((section(".aramtext")));
-
-#endif /* _TMRHW_H */
diff --git a/arch/arm/mach-bcmring/include/mach/cfg_global.h b/arch/arm/mach-bcmring/include/mach/cfg_global.h
new file mode 100644
index 0000000..449133e
--- /dev/null
+++ b/arch/arm/mach-bcmring/include/mach/cfg_global.h
@@ -0,0 +1,51 @@
+/*****************************************************************************
+* Copyright 2006 - 2008 Broadcom Corporation.  All rights reserved.
+*
+* Unless you and Broadcom execute a separate written software license
+* agreement governing use of this software, this software is licensed to you
+* under the terms of the GNU General Public License version 2, available at
+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
+*
+* Notwithstanding the above, under no circumstances may you combine this
+* software in any way with any other Broadcom software provided under a
+* license other than the GPL, without Broadcom's express prior written
+* consent.
+*****************************************************************************/
+
+#ifndef CFG_GLOBAL_DEFINES_H
+#define CFG_GLOBAL_DEFINES_H
+
+/* CHIP */
+#define BCM1103 1
+
+#define BCM1191 4
+#define BCM2153 5
+#define BCM2820 6
+
+#define BCM2826 8
+#define FPGA11107 9
+#define BCM11107   10
+#define BCM11109   11
+#define BCM11170   12
+#define BCM11110   13
+#define BCM11211   14
+
+/* CFG_GLOBAL_CHIP_FAMILY types */
+#define CFG_GLOBAL_CHIP_FAMILY_NONE        0
+#define CFG_GLOBAL_CHIP_FAMILY_BCM116X     2
+#define CFG_GLOBAL_CHIP_FAMILY_BCMRING     4
+#define CFG_GLOBAL_CHIP_FAMILY_BCM1103     8
+
+#define IMAGE_HEADER_SIZE_CHECKSUM    4
+#endif
+#ifndef _CFG_GLOBAL_H_
+#define _CFG_GLOBAL_H_
+
+#define CFG_GLOBAL_CHIP                         BCM11107
+#define CFG_GLOBAL_CHIP_FAMILY                  CFG_GLOBAL_CHIP_FAMILY_BCMRING
+#define CFG_GLOBAL_CHIP_REV                     0xB0
+#define CFG_GLOBAL_RAM_SIZE                     0x10000000
+#define CFG_GLOBAL_RAM_BASE                     0x00000000
+#define CFG_GLOBAL_RAM_RESERVED_SIZE            0x000000
+
+#endif /* _CFG_GLOBAL_H_ */
diff --git a/arch/arm/mach-bcmring/include/mach/csp/cap_inline.h b/arch/arm/mach-bcmring/include/mach/csp/cap_inline.h
index 933ce68..0a89e0c 100644
--- a/arch/arm/mach-bcmring/include/mach/csp/cap_inline.h
+++ b/arch/arm/mach-bcmring/include/mach/csp/cap_inline.h
@@ -17,7 +17,7 @@
 
 /* ---- Include Files ---------------------------------------------------- */
 #include <mach/csp/cap.h>
-#include <cfg_global.h>
+#include <mach/cfg_global.h>
 
 /* ---- Public Constants and Types --------------------------------------- */
 #define CAP_CONFIG0_VPM_DIS          0x00000001
diff --git a/arch/arm/mach-bcmring/include/mach/csp/chipcHw_def.h b/arch/arm/mach-bcmring/include/mach/csp/chipcHw_def.h
index 1619733..39f09cb 100644
--- a/arch/arm/mach-bcmring/include/mach/csp/chipcHw_def.h
+++ b/arch/arm/mach-bcmring/include/mach/csp/chipcHw_def.h
@@ -17,9 +17,9 @@
 
 /* ---- Include Files ----------------------------------------------------- */
 
-#include <csp/stdint.h>
-#include <csp/errno.h>
-#include <csp/reg.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <mach/csp/reg.h>
 #include <mach/csp/chipcHw_reg.h>
 
 /* ---- Public Constants and Types ---------------------------------------- */
diff --git a/arch/arm/mach-bcmring/include/mach/csp/chipcHw_inline.h b/arch/arm/mach-bcmring/include/mach/csp/chipcHw_inline.h
index 03238c2..a66f3f7 100644
--- a/arch/arm/mach-bcmring/include/mach/csp/chipcHw_inline.h
+++ b/arch/arm/mach-bcmring/include/mach/csp/chipcHw_inline.h
@@ -17,8 +17,8 @@
 
 /* ---- Include Files ----------------------------------------------------- */
 
-#include <csp/errno.h>
-#include <csp/reg.h>
+#include <linux/errno.h>
+#include <mach/csp/reg.h>
 #include <mach/csp/chipcHw_reg.h>
 #include <mach/csp/chipcHw_def.h>
 
@@ -47,7 +47,7 @@ static inline void chipcHw_setClock(chipcHw_CLOCK_e clock,
 /****************************************************************************/
 static inline uint32_t chipcHw_getChipId(void)
 {
-	return pChipcHw->ChipId;
+	return readl(&pChipcHw->ChipId);
 }
 
 /****************************************************************************/
@@ -59,15 +59,16 @@ static inline uint32_t chipcHw_getChipId(void)
 /****************************************************************************/
 static inline void chipcHw_enableSpreadSpectrum(void)
 {
-	if ((pChipcHw->
-	     PLLPreDivider & chipcHw_REG_PLL_PREDIVIDER_NDIV_MODE_MASK) !=
+	if ((readl(&pChipcHw->
+	     PLLPreDivider) & chipcHw_REG_PLL_PREDIVIDER_NDIV_MODE_MASK) !=
 	    chipcHw_REG_PLL_PREDIVIDER_NDIV_MODE_INTEGER) {
-		ddrcReg_PHY_ADDR_CTL_REGP->ssCfg =
-		    (0xFFFF << ddrcReg_PHY_ADDR_SS_CFG_NDIV_AMPLITUDE_SHIFT) |
+		writel((0xFFFF << ddrcReg_PHY_ADDR_SS_CFG_NDIV_AMPLITUDE_SHIFT) |
 		    (ddrcReg_PHY_ADDR_SS_CFG_MIN_CYCLE_PER_TICK <<
-		     ddrcReg_PHY_ADDR_SS_CFG_CYCLE_PER_TICK_SHIFT);
-		ddrcReg_PHY_ADDR_CTL_REGP->ssCtl |=
-		    ddrcReg_PHY_ADDR_SS_CTRL_ENABLE;
+		     ddrcReg_PHY_ADDR_SS_CFG_CYCLE_PER_TICK_SHIFT),
+		     &ddrcReg_PHY_ADDR_CTL_REGP->ssCfg);
+		writel(readl(&ddrcReg_PHY_ADDR_CTL_REGP->ssCtl) |
+		    ddrcReg_PHY_ADDR_SS_CTRL_ENABLE,
+		    &ddrcReg_PHY_ADDR_CTL_REGP->ssCtl);
 	}
 }
 
@@ -93,8 +94,8 @@ static inline void chipcHw_disableSpreadSpectrum(void)
 /****************************************************************************/
 static inline uint32_t chipcHw_getChipProductId(void)
 {
-	return (pChipcHw->
-		 ChipId & chipcHw_REG_CHIPID_BASE_MASK) >>
+	return (readl(&pChipcHw->
+		 ChipId) & chipcHw_REG_CHIPID_BASE_MASK) >>
 		chipcHw_REG_CHIPID_BASE_SHIFT;
 }
 
@@ -109,7 +110,7 @@ static inline uint32_t chipcHw_getChipProductId(void)
 /****************************************************************************/
 static inline chipcHw_REV_NUMBER_e chipcHw_getChipRevisionNumber(void)
 {
-	return pChipcHw->ChipId & chipcHw_REG_CHIPID_REV_MASK;
+	return readl(&pChipcHw->ChipId) & chipcHw_REG_CHIPID_REV_MASK;
 }
 
 /****************************************************************************/
@@ -156,7 +157,7 @@ static inline void chipcHw_busInterfaceClockDisable(uint32_t mask)
 /****************************************************************************/
 static inline uint32_t chipcHw_getBusInterfaceClockStatus(void)
 {
-	return pChipcHw->BusIntfClock;
+	return readl(&pChipcHw->BusIntfClock);
 }
 
 /****************************************************************************/
@@ -215,8 +216,9 @@ static inline void chipcHw_softResetDisable(uint64_t mask)
 
 	/* Deassert module soft reset */
 	REG_LOCAL_IRQ_SAVE;
-	pChipcHw->SoftReset1 ^= ctrl1;
-	pChipcHw->SoftReset2 ^= (ctrl2 & (~chipcHw_REG_SOFT_RESET_UNHOLD_MASK));
+	writel(readl(&pChipcHw->SoftReset1) ^ ctrl1, &pChipcHw->SoftReset1);
+	writel(readl(&pChipcHw->SoftReset2) ^ (ctrl2 &
+		(~chipcHw_REG_SOFT_RESET_UNHOLD_MASK)), &pChipcHw->SoftReset2);
 	REG_LOCAL_IRQ_RESTORE;
 }
 
@@ -227,9 +229,10 @@ static inline void chipcHw_softResetEnable(uint64_t mask)
 	uint32_t unhold = 0;
 
 	REG_LOCAL_IRQ_SAVE;
-	pChipcHw->SoftReset1 |= ctrl1;
+	writel(readl(&pChipcHw->SoftReset1) | ctrl1, &pChipcHw->SoftReset1);
 	/* Mask out unhold request bits */
-	pChipcHw->SoftReset2 |= (ctrl2 & (~chipcHw_REG_SOFT_RESET_UNHOLD_MASK));
+	writel(readl(&pChipcHw->SoftReset2) | (ctrl2 &
+		(~chipcHw_REG_SOFT_RESET_UNHOLD_MASK)), &pChipcHw->SoftReset2);
 
 	/* Process unhold requests */
 	if (ctrl2 & chipcHw_REG_SOFT_RESET_VPM_GLOBAL_UNHOLD) {
@@ -246,7 +249,7 @@ static inline void chipcHw_softResetEnable(uint64_t mask)
 
 	if (unhold) {
 		/* Make sure unhold request is effective */
-		pChipcHw->SoftReset1 &= ~unhold;
+		writel(readl(&pChipcHw->SoftReset1) & ~unhold, &pChipcHw->SoftReset1);
 	}
 	REG_LOCAL_IRQ_RESTORE;
 }
@@ -307,7 +310,7 @@ static inline void chipcHw_setOTPOption(uint64_t mask)
 /****************************************************************************/
 static inline uint32_t chipcHw_getStickyBits(void)
 {
-	return pChipcHw->Sticky;
+	return readl(&pChipcHw->Sticky);
 }
 
 /****************************************************************************/
@@ -328,7 +331,7 @@ static inline void chipcHw_setStickyBits(uint32_t mask)
 		bits |= chipcHw_REG_STICKY_POR_BROM;
 	} else {
 		uint32_t sticky;
-		sticky = pChipcHw->Sticky;
+		sticky = readl(pChipcHw->Sticky);
 
 		if ((mask & chipcHw_REG_STICKY_BOOT_DONE)
 		    && (sticky & chipcHw_REG_STICKY_BOOT_DONE) == 0) {
@@ -355,7 +358,7 @@ static inline void chipcHw_setStickyBits(uint32_t mask)
 			bits |= chipcHw_REG_STICKY_GENERAL_5;
 		}
 	}
-	pChipcHw->Sticky = bits;
+	writel(bits, pChipcHw->Sticky);
 	REG_LOCAL_IRQ_RESTORE;
 }
 
@@ -377,7 +380,7 @@ static inline void chipcHw_clearStickyBits(uint32_t mask)
 	    (chipcHw_REG_STICKY_BOOT_DONE | chipcHw_REG_STICKY_GENERAL_1 |
 	     chipcHw_REG_STICKY_GENERAL_2 | chipcHw_REG_STICKY_GENERAL_3 |
 	     chipcHw_REG_STICKY_GENERAL_4 | chipcHw_REG_STICKY_GENERAL_5)) {
-		uint32_t sticky = pChipcHw->Sticky;
+		uint32_t sticky = readl(&pChipcHw->Sticky);
 
 		if ((mask & chipcHw_REG_STICKY_BOOT_DONE)
 		    && (sticky & chipcHw_REG_STICKY_BOOT_DONE)) {
@@ -410,7 +413,7 @@ static inline void chipcHw_clearStickyBits(uint32_t mask)
 			mask &= ~chipcHw_REG_STICKY_GENERAL_5;
 		}
 	}
-	pChipcHw->Sticky = bits | mask;
+	writel(bits | mask, &pChipcHw->Sticky);
 	REG_LOCAL_IRQ_RESTORE;
 }
 
@@ -426,7 +429,7 @@ static inline void chipcHw_clearStickyBits(uint32_t mask)
 /****************************************************************************/
 static inline uint32_t chipcHw_getSoftStraps(void)
 {
-	return pChipcHw->SoftStraps;
+	return readl(&pChipcHw->SoftStraps);
 }
 
 /****************************************************************************/
@@ -456,7 +459,7 @@ static inline void chipcHw_setSoftStraps(uint32_t strapOptions)
 /****************************************************************************/
 static inline uint32_t chipcHw_getPinStraps(void)
 {
-	return pChipcHw->PinStraps;
+	return readl(&pChipcHw->PinStraps);
 }
 
 /****************************************************************************/
@@ -671,9 +674,9 @@ static inline void chipcHw_selectGE3(void)
 /****************************************************************************/
 static inline chipcHw_GPIO_FUNCTION_e chipcHw_getGpioPinFunction(int pin)
 {
-	return (*((uint32_t *) chipcHw_REG_GPIO_MUX(pin)) &
+	return (readl(chipcHw_REG_GPIO_MUX(pin))) &
 		(chipcHw_REG_GPIO_MUX_MASK <<
-		 chipcHw_REG_GPIO_MUX_POSITION(pin))) >>
+		 chipcHw_REG_GPIO_MUX_POSITION(pin)) >>
 	    chipcHw_REG_GPIO_MUX_POSITION(pin);
 }
 
@@ -841,8 +844,8 @@ static inline void chipcHw_setUsbDevice(void)
 static inline void chipcHw_setClock(chipcHw_CLOCK_e clock,
 				    chipcHw_OPTYPE_e type, int mode)
 {
-	volatile uint32_t *pPLLReg = (uint32_t *) 0x0;
-	volatile uint32_t *pClockCtrl = (uint32_t *) 0x0;
+	uint32_t __iomem *pPLLReg = NULL;
+	uint32_t __iomem *pClockCtrl = NULL;
 
 	switch (clock) {
 	case chipcHw_CLOCK_DDR:
@@ -1071,7 +1074,7 @@ static inline void chipcHw_bypassClockDisable(chipcHw_CLOCK_e clock)
 /****************************************************************************/
 static inline int chipcHw_isSoftwareStrapsEnable(void)
 {
-	return pChipcHw->SoftStraps & 0x00000001;
+	return readl(&pChipcHw->SoftStraps) & 0x00000001;
 }
 
 /****************************************************************************/
@@ -1138,7 +1141,7 @@ static inline void chipcHw_pll2TestDisable(void)
 /****************************************************************************/
 static inline int chipcHw_isPllTestEnable(void)
 {
-	return pChipcHw->PLLConfig & chipcHw_REG_PLL_CONFIG_TEST_ENABLE;
+	return readl(&pChipcHw->PLLConfig) & chipcHw_REG_PLL_CONFIG_TEST_ENABLE;
 }
 
 /****************************************************************************/
@@ -1147,7 +1150,7 @@ static inline int chipcHw_isPllTestEnable(void)
 /****************************************************************************/
 static inline int chipcHw_isPll2TestEnable(void)
 {
-	return pChipcHw->PLLConfig2 & chipcHw_REG_PLL_CONFIG_TEST_ENABLE;
+	return readl(&pChipcHw->PLLConfig2) & chipcHw_REG_PLL_CONFIG_TEST_ENABLE;
 }
 
 /****************************************************************************/
@@ -1183,8 +1186,8 @@ static inline void chipcHw_pll2TestSelect(uint32_t val)
 /****************************************************************************/
 static inline uint8_t chipcHw_getPllTestSelected(void)
 {
-	return (uint8_t) ((pChipcHw->
-			   PLLConfig & chipcHw_REG_PLL_CONFIG_TEST_SELECT_MASK)
+	return (uint8_t) ((readl(&pChipcHw->
+			   PLLConfig) & chipcHw_REG_PLL_CONFIG_TEST_SELECT_MASK)
 			  >> chipcHw_REG_PLL_CONFIG_TEST_SELECT_SHIFT);
 }
 
@@ -1194,8 +1197,8 @@ static inline uint8_t chipcHw_getPllTestSelected(void)
 /****************************************************************************/
 static inline uint8_t chipcHw_getPll2TestSelected(void)
 {
-	return (uint8_t) ((pChipcHw->
-			   PLLConfig2 & chipcHw_REG_PLL_CONFIG_TEST_SELECT_MASK)
+	return (uint8_t) ((readl(&pChipcHw->
+			   PLLConfig2) & chipcHw_REG_PLL_CONFIG_TEST_SELECT_MASK)
 			  >> chipcHw_REG_PLL_CONFIG_TEST_SELECT_SHIFT);
 }
 
@@ -1208,7 +1211,8 @@ static inline uint8_t chipcHw_getPll2TestSelected(void)
 static inline void chipcHw_pll1Disable(void)
 {
 	REG_LOCAL_IRQ_SAVE;
-	pChipcHw->PLLConfig |= chipcHw_REG_PLL_CONFIG_POWER_DOWN;
+	writel(readl(&pChipcHw->PLLConfig) | chipcHw_REG_PLL_CONFIG_POWER_DOWN,
+		&pChipcHw->PLLConfig);
 	REG_LOCAL_IRQ_RESTORE;
 }
 
@@ -1221,7 +1225,8 @@ static inline void chipcHw_pll1Disable(void)
 static inline void chipcHw_pll2Disable(void)
 {
 	REG_LOCAL_IRQ_SAVE;
-	pChipcHw->PLLConfig2 |= chipcHw_REG_PLL_CONFIG_POWER_DOWN;
+	writel(readl(&pChipcHw->PLLConfig2) | chipcHw_REG_PLL_CONFIG_POWER_DOWN,
+		&pChipcHw->PLLConfig2);
 	REG_LOCAL_IRQ_RESTORE;
 }
 
@@ -1233,7 +1238,8 @@ static inline void chipcHw_pll2Disable(void)
 static inline void chipcHw_ddrPhaseAlignInterruptEnable(void)
 {
 	REG_LOCAL_IRQ_SAVE;
-	pChipcHw->Spare1 |= chipcHw_REG_SPARE1_DDR_PHASE_INTR_ENABLE;
+	writel(readl(&pChipcHw->Spare1) | chipcHw_REG_SPARE1_DDR_PHASE_INTR_ENABLE,
+		&pChipcHw->Spare1);
 	REG_LOCAL_IRQ_RESTORE;
 }
 
@@ -1245,7 +1251,8 @@ static inline void chipcHw_ddrPhaseAlignInterruptEnable(void)
 static inline void chipcHw_ddrPhaseAlignInterruptDisable(void)
 {
 	REG_LOCAL_IRQ_SAVE;
-	pChipcHw->Spare1 &= ~chipcHw_REG_SPARE1_DDR_PHASE_INTR_ENABLE;
+	writel(readl(&pChipcHw->Spare1) & ~chipcHw_REG_SPARE1_DDR_PHASE_INTR_ENABLE,
+		&pChipcHw->Spare1);
 	REG_LOCAL_IRQ_RESTORE;
 }
 
@@ -1333,7 +1340,8 @@ static inline void chipcHw_ddrHwPhaseAlignDisable(void)
 static inline void chipcHw_vpmSwPhaseAlignEnable(void)
 {
 	REG_LOCAL_IRQ_SAVE;
-	pChipcHw->VPMPhaseCtrl1 |= chipcHw_REG_VPM_SW_PHASE_CTRL_ENABLE;
+	writel(readl(&pChipcHw->VPMPhaseCtrl1) | chipcHw_REG_VPM_SW_PHASE_CTRL_ENABLE,
+			&pChipcHw->VPMPhaseCtrl1);
 	REG_LOCAL_IRQ_RESTORE;
 }
 
@@ -1372,7 +1380,8 @@ static inline void chipcHw_vpmHwPhaseAlignEnable(void)
 static inline void chipcHw_vpmHwPhaseAlignDisable(void)
 {
 	REG_LOCAL_IRQ_SAVE;
-	pChipcHw->VPMPhaseCtrl1 &= ~chipcHw_REG_VPM_HW_PHASE_CTRL_ENABLE;
+	writel(readl(&pChipcHw->VPMPhaseCtrl1) & ~chipcHw_REG_VPM_HW_PHASE_CTRL_ENABLE,
+		&pChipcHw->VPMPhaseCtrl1);
 	REG_LOCAL_IRQ_RESTORE;
 }
 
@@ -1474,8 +1483,8 @@ chipcHw_setVpmHwPhaseAlignMargin(chipcHw_VPM_HW_PHASE_MARGIN_e margin)
 /****************************************************************************/
 static inline uint32_t chipcHw_isDdrHwPhaseAligned(void)
 {
-	return (pChipcHw->
-		PhaseAlignStatus & chipcHw_REG_DDR_PHASE_ALIGNED) ? 1 : 0;
+	return (readl(&pChipcHw->
+		PhaseAlignStatus) & chipcHw_REG_DDR_PHASE_ALIGNED) ? 1 : 0;
 }
 
 /****************************************************************************/
@@ -1488,8 +1497,8 @@ static inline uint32_t chipcHw_isDdrHwPhaseAligned(void)
 /****************************************************************************/
 static inline uint32_t chipcHw_isVpmHwPhaseAligned(void)
 {
-	return (pChipcHw->
-		PhaseAlignStatus & chipcHw_REG_VPM_PHASE_ALIGNED) ? 1 : 0;
+	return (readl(&pChipcHw->
+		PhaseAlignStatus) & chipcHw_REG_VPM_PHASE_ALIGNED) ? 1 : 0;
 }
 
 /****************************************************************************/
@@ -1500,8 +1509,8 @@ static inline uint32_t chipcHw_isVpmHwPhaseAligned(void)
 /****************************************************************************/
 static inline uint32_t chipcHw_getDdrHwPhaseAlignStatus(void)
 {
-	return (pChipcHw->
-		PhaseAlignStatus & chipcHw_REG_DDR_PHASE_STATUS_MASK) >>
+	return (readl(&pChipcHw->
+		PhaseAlignStatus) & chipcHw_REG_DDR_PHASE_STATUS_MASK) >>
 	    chipcHw_REG_DDR_PHASE_STATUS_SHIFT;
 }
 
@@ -1513,8 +1522,8 @@ static inline uint32_t chipcHw_getDdrHwPhaseAlignStatus(void)
 /****************************************************************************/
 static inline uint32_t chipcHw_getVpmHwPhaseAlignStatus(void)
 {
-	return (pChipcHw->
-		PhaseAlignStatus & chipcHw_REG_VPM_PHASE_STATUS_MASK) >>
+	return (readl(&pChipcHw->
+		PhaseAlignStatus) & chipcHw_REG_VPM_PHASE_STATUS_MASK) >>
 	    chipcHw_REG_VPM_PHASE_STATUS_SHIFT;
 }
 
@@ -1526,8 +1535,8 @@ static inline uint32_t chipcHw_getVpmHwPhaseAlignStatus(void)
 /****************************************************************************/
 static inline uint32_t chipcHw_getDdrPhaseControl(void)
 {
-	return (pChipcHw->
-		PhaseAlignStatus & chipcHw_REG_DDR_PHASE_CTRL_MASK) >>
+	return (readl(&pChipcHw->
+		PhaseAlignStatus) & chipcHw_REG_DDR_PHASE_CTRL_MASK) >>
 	    chipcHw_REG_DDR_PHASE_CTRL_SHIFT;
 }
 
@@ -1539,8 +1548,8 @@ static inline uint32_t chipcHw_getDdrPhaseControl(void)
 /****************************************************************************/
 static inline uint32_t chipcHw_getVpmPhaseControl(void)
 {
-	return (pChipcHw->
-		PhaseAlignStatus & chipcHw_REG_VPM_PHASE_CTRL_MASK) >>
+	return (readl(&pChipcHw->
+		PhaseAlignStatus) & chipcHw_REG_VPM_PHASE_CTRL_MASK) >>
 	    chipcHw_REG_VPM_PHASE_CTRL_SHIFT;
 }
 
diff --git a/arch/arm/mach-bcmring/include/mach/csp/chipcHw_reg.h b/arch/arm/mach-bcmring/include/mach/csp/chipcHw_reg.h
index b162448..26f5d0e 100644
--- a/arch/arm/mach-bcmring/include/mach/csp/chipcHw_reg.h
+++ b/arch/arm/mach-bcmring/include/mach/csp/chipcHw_reg.h
@@ -24,7 +24,7 @@
 #define CHIPCHW_REG_H
 
 #include <mach/csp/mm_io.h>
-#include <csp/reg.h>
+#include <mach/csp/reg.h>
 #include <mach/csp/ddrcReg.h>
 
 #define chipcHw_BASE_ADDRESS    MM_IO_BASE_CHIPC
@@ -131,8 +131,8 @@ typedef struct {
 	uint32_t MiscInput_0_15;	/* Input type for MISC 0 - 16 */
 } chipcHw_REG_t;
 
-#define pChipcHw  ((volatile chipcHw_REG_t *) chipcHw_BASE_ADDRESS)
-#define pChipcPhysical  ((volatile chipcHw_REG_t *) MM_ADDR_IO_CHIPC)
+#define pChipcHw  ((chipcHw_REG_t __iomem *) chipcHw_BASE_ADDRESS)
+#define pChipcPhysical  (MM_ADDR_IO_CHIPC)
 
 #define chipcHw_REG_CHIPID_BASE_MASK                    0xFFFFF000
 #define chipcHw_REG_CHIPID_BASE_SHIFT                   12
diff --git a/arch/arm/mach-bcmring/include/mach/csp/ddrcReg.h b/arch/arm/mach-bcmring/include/mach/csp/ddrcReg.h
index f1b68e2..39da2c1 100644
--- a/arch/arm/mach-bcmring/include/mach/csp/ddrcReg.h
+++ b/arch/arm/mach-bcmring/include/mach/csp/ddrcReg.h
@@ -30,8 +30,8 @@ extern "C" {
 
 /* ---- Include Files ---------------------------------------------------- */
 
-#include <csp/reg.h>
-#include <csp/stdint.h>
+#include <mach/csp/reg.h>
+#include <linux/types.h>
 
 #include <mach/csp/mm_io.h>
 
@@ -416,7 +416,7 @@ extern "C" {
 	} ddrcReg_PHY_ADDR_CTL_REG_t;
 
 #define ddrcReg_PHY_ADDR_CTL_REG_OFFSET                 0x0400
-#define ddrcReg_PHY_ADDR_CTL_REGP                       ((volatile ddrcReg_PHY_ADDR_CTL_REG_t *) (MM_IO_BASE_DDRC + ddrcReg_PHY_ADDR_CTL_REG_OFFSET))
+#define ddrcReg_PHY_ADDR_CTL_REGP                       ((volatile ddrcReg_PHY_ADDR_CTL_REG_t __iomem*) (MM_IO_BASE_DDRC + ddrcReg_PHY_ADDR_CTL_REG_OFFSET))
 
 /* @todo These SS definitions are duplicates of ones below */
 
diff --git a/arch/arm/mach-bcmring/include/mach/csp/dmacHw.h b/arch/arm/mach-bcmring/include/mach/csp/dmacHw.h
new file mode 100644
index 0000000..9dc90f4
--- /dev/null
+++ b/arch/arm/mach-bcmring/include/mach/csp/dmacHw.h
@@ -0,0 +1,596 @@
+/*****************************************************************************
+* Copyright 2004 - 2008 Broadcom Corporation.  All rights reserved.
+*
+* Unless you and Broadcom execute a separate written software license
+* agreement governing use of this software, this software is licensed to you
+* under the terms of the GNU General Public License version 2, available at
+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
+*
+* Notwithstanding the above, under no circumstances may you combine this
+* software in any way with any other Broadcom software provided under a
+* license other than the GPL, without Broadcom's express prior written
+* consent.
+*****************************************************************************/
+
+/****************************************************************************/
+/**
+*  @file    dmacHw.h
+*
+*  @brief   API definitions for low level DMA controller driver
+*
+*/
+/****************************************************************************/
+#ifndef _DMACHW_H
+#define _DMACHW_H
+
+#include <linux/stddef.h>
+
+#include <linux/types.h>
+#include <mach/csp/dmacHw_reg.h>
+
+/* Define DMA Channel ID using DMA controller number (m) and channel number (c).
+
+   System specific channel ID should be defined as follows
+
+   For example:
+
+   #include <dmacHw.h>
+   ...
+   #define systemHw_LCD_CHANNEL_ID                dmacHw_MAKE_CHANNEL_ID(0,5)
+   #define systemHw_SWITCH_RX_CHANNEL_ID          dmacHw_MAKE_CHANNEL_ID(0,0)
+   #define systemHw_SWITCH_TX_CHANNEL_ID          dmacHw_MAKE_CHANNEL_ID(0,1)
+   #define systemHw_APM_RX_CHANNEL_ID             dmacHw_MAKE_CHANNEL_ID(0,3)
+   #define systemHw_APM_TX_CHANNEL_ID             dmacHw_MAKE_CHANNEL_ID(0,4)
+   ...
+   #define systemHw_SHARED1_CHANNEL_ID            dmacHw_MAKE_CHANNEL_ID(1,4)
+   #define systemHw_SHARED2_CHANNEL_ID            dmacHw_MAKE_CHANNEL_ID(1,5)
+   #define systemHw_SHARED3_CHANNEL_ID            dmacHw_MAKE_CHANNEL_ID(0,6)
+   ...
+*/
+#define dmacHw_MAKE_CHANNEL_ID(m, c)         (m << 8 | c)
+
+typedef enum {
+	dmacHw_CHANNEL_PRIORITY_0 = dmacHw_REG_CFG_LO_CH_PRIORITY_0,	/* Channel priority 0. Lowest priority DMA channel */
+	dmacHw_CHANNEL_PRIORITY_1 = dmacHw_REG_CFG_LO_CH_PRIORITY_1,	/* Channel priority 1 */
+	dmacHw_CHANNEL_PRIORITY_2 = dmacHw_REG_CFG_LO_CH_PRIORITY_2,	/* Channel priority 2 */
+	dmacHw_CHANNEL_PRIORITY_3 = dmacHw_REG_CFG_LO_CH_PRIORITY_3,	/* Channel priority 3 */
+	dmacHw_CHANNEL_PRIORITY_4 = dmacHw_REG_CFG_LO_CH_PRIORITY_4,	/* Channel priority 4 */
+	dmacHw_CHANNEL_PRIORITY_5 = dmacHw_REG_CFG_LO_CH_PRIORITY_5,	/* Channel priority 5 */
+	dmacHw_CHANNEL_PRIORITY_6 = dmacHw_REG_CFG_LO_CH_PRIORITY_6,	/* Channel priority 6 */
+	dmacHw_CHANNEL_PRIORITY_7 = dmacHw_REG_CFG_LO_CH_PRIORITY_7	/* Channel priority 7. Highest priority DMA channel */
+} dmacHw_CHANNEL_PRIORITY_e;
+
+/* Source destination master interface */
+typedef enum {
+	dmacHw_SRC_MASTER_INTERFACE_1 = dmacHw_REG_CTL_SMS_1,	/* Source DMA master interface 1 */
+	dmacHw_SRC_MASTER_INTERFACE_2 = dmacHw_REG_CTL_SMS_2,	/* Source DMA master interface 2 */
+	dmacHw_DST_MASTER_INTERFACE_1 = dmacHw_REG_CTL_DMS_1,	/* Destination DMA master interface 1 */
+	dmacHw_DST_MASTER_INTERFACE_2 = dmacHw_REG_CTL_DMS_2	/* Destination DMA master interface 2 */
+} dmacHw_MASTER_INTERFACE_e;
+
+typedef enum {
+	dmacHw_SRC_TRANSACTION_WIDTH_8 = dmacHw_REG_CTL_SRC_TR_WIDTH_8,	/* Source 8 bit  (1 byte) per transaction */
+	dmacHw_SRC_TRANSACTION_WIDTH_16 = dmacHw_REG_CTL_SRC_TR_WIDTH_16,	/* Source 16 bit (2 byte) per transaction */
+	dmacHw_SRC_TRANSACTION_WIDTH_32 = dmacHw_REG_CTL_SRC_TR_WIDTH_32,	/* Source 32 bit (4 byte) per transaction */
+	dmacHw_SRC_TRANSACTION_WIDTH_64 = dmacHw_REG_CTL_SRC_TR_WIDTH_64,	/* Source 64 bit (8 byte) per transaction */
+	dmacHw_DST_TRANSACTION_WIDTH_8 = dmacHw_REG_CTL_DST_TR_WIDTH_8,	/* Destination 8 bit  (1 byte) per transaction */
+	dmacHw_DST_TRANSACTION_WIDTH_16 = dmacHw_REG_CTL_DST_TR_WIDTH_16,	/* Destination 16 bit (2 byte) per transaction */
+	dmacHw_DST_TRANSACTION_WIDTH_32 = dmacHw_REG_CTL_DST_TR_WIDTH_32,	/* Destination 32 bit (4 byte) per transaction */
+	dmacHw_DST_TRANSACTION_WIDTH_64 = dmacHw_REG_CTL_DST_TR_WIDTH_64	/* Destination 64 bit (8 byte) per transaction */
+} dmacHw_TRANSACTION_WIDTH_e;
+
+typedef enum {
+	dmacHw_SRC_BURST_WIDTH_0 = dmacHw_REG_CTL_SRC_MSIZE_0,	/* Source No burst */
+	dmacHw_SRC_BURST_WIDTH_4 = dmacHw_REG_CTL_SRC_MSIZE_4,	/* Source 4  X dmacHw_TRANSACTION_WIDTH_xxx bytes per burst */
+	dmacHw_SRC_BURST_WIDTH_8 = dmacHw_REG_CTL_SRC_MSIZE_8,	/* Source 8  X dmacHw_TRANSACTION_WIDTH_xxx bytes per burst */
+	dmacHw_SRC_BURST_WIDTH_16 = dmacHw_REG_CTL_SRC_MSIZE_16,	/* Source 16 X dmacHw_TRANSACTION_WIDTH_xxx bytes per burst */
+	dmacHw_DST_BURST_WIDTH_0 = dmacHw_REG_CTL_DST_MSIZE_0,	/* Destination No burst */
+	dmacHw_DST_BURST_WIDTH_4 = dmacHw_REG_CTL_DST_MSIZE_4,	/* Destination 4  X dmacHw_TRANSACTION_WIDTH_xxx bytes per burst */
+	dmacHw_DST_BURST_WIDTH_8 = dmacHw_REG_CTL_DST_MSIZE_8,	/* Destination 8  X dmacHw_TRANSACTION_WIDTH_xxx bytes per burst */
+	dmacHw_DST_BURST_WIDTH_16 = dmacHw_REG_CTL_DST_MSIZE_16	/* Destination 16 X dmacHw_TRANSACTION_WIDTH_xxx bytes per burst */
+} dmacHw_BURST_WIDTH_e;
+
+typedef enum {
+	dmacHw_TRANSFER_TYPE_MEM_TO_MEM = dmacHw_REG_CTL_TTFC_MM_DMAC,	/* Memory to memory transfer */
+	dmacHw_TRANSFER_TYPE_PERIPHERAL_TO_MEM = dmacHw_REG_CTL_TTFC_PM_DMAC,	/* Peripheral to memory transfer */
+	dmacHw_TRANSFER_TYPE_MEM_TO_PERIPHERAL = dmacHw_REG_CTL_TTFC_MP_DMAC,	/* Memory to peripheral transfer */
+	dmacHw_TRANSFER_TYPE_PERIPHERAL_TO_PERIPHERAL = dmacHw_REG_CTL_TTFC_PP_DMAC	/* Peripheral to peripheral transfer */
+} dmacHw_TRANSFER_TYPE_e;
+
+typedef enum {
+	dmacHw_TRANSFER_MODE_PERREQUEST,	/* Block transfer per DMA request */
+	dmacHw_TRANSFER_MODE_CONTINUOUS,	/* Continuous transfer of streaming data */
+	dmacHw_TRANSFER_MODE_PERIODIC	/* Periodic transfer of streaming data */
+} dmacHw_TRANSFER_MODE_e;
+
+typedef enum {
+	dmacHw_SRC_ADDRESS_UPDATE_MODE_INC = dmacHw_REG_CTL_SINC_INC,	/* Increment source address after every transaction */
+	dmacHw_SRC_ADDRESS_UPDATE_MODE_DEC = dmacHw_REG_CTL_SINC_DEC,	/* Decrement source address after every transaction */
+	dmacHw_DST_ADDRESS_UPDATE_MODE_INC = dmacHw_REG_CTL_DINC_INC,	/* Increment destination address after every transaction */
+	dmacHw_DST_ADDRESS_UPDATE_MODE_DEC = dmacHw_REG_CTL_DINC_DEC,	/* Decrement destination address after every transaction */
+	dmacHw_SRC_ADDRESS_UPDATE_MODE_NC = dmacHw_REG_CTL_SINC_NC,	/* No change in source address after every transaction */
+	dmacHw_DST_ADDRESS_UPDATE_MODE_NC = dmacHw_REG_CTL_DINC_NC	/* No change in destination address after every transaction */
+} dmacHw_ADDRESS_UPDATE_MODE_e;
+
+typedef enum {
+	dmacHw_FLOW_CONTROL_DMA,	/* DMA working as flow controller (default) */
+	dmacHw_FLOW_CONTROL_PERIPHERAL	/* Peripheral working as flow controller */
+} dmacHw_FLOW_CONTROL_e;
+
+typedef enum {
+	dmacHw_TRANSFER_STATUS_BUSY,	/* DMA Transfer ongoing */
+	dmacHw_TRANSFER_STATUS_DONE,	/* DMA Transfer completed */
+	dmacHw_TRANSFER_STATUS_ERROR	/* DMA Transfer error */
+} dmacHw_TRANSFER_STATUS_e;
+
+typedef enum {
+	dmacHw_INTERRUPT_DISABLE,	/* Interrupt disable  */
+	dmacHw_INTERRUPT_ENABLE	/* Interrupt enable */
+} dmacHw_INTERRUPT_e;
+
+typedef enum {
+	dmacHw_INTERRUPT_STATUS_NONE = 0x0,	/* No DMA interrupt */
+	dmacHw_INTERRUPT_STATUS_TRANS = 0x1,	/* End of DMA transfer interrupt */
+	dmacHw_INTERRUPT_STATUS_BLOCK = 0x2,	/* End of block transfer interrupt */
+	dmacHw_INTERRUPT_STATUS_ERROR = 0x4	/* Error interrupt */
+} dmacHw_INTERRUPT_STATUS_e;
+
+typedef enum {
+	dmacHw_CONTROLLER_ATTRIB_CHANNEL_NUM,	/* Number of DMA channel */
+	dmacHw_CONTROLLER_ATTRIB_CHANNEL_MAX_BLOCK_SIZE,	/* Maximum channel burst size */
+	dmacHw_CONTROLLER_ATTRIB_MASTER_INTF_NUM,	/* Number of DMA master interface */
+	dmacHw_CONTROLLER_ATTRIB_CHANNEL_BUS_WIDTH,	/* Channel Data bus width */
+	dmacHw_CONTROLLER_ATTRIB_CHANNEL_FIFO_SIZE	/* Channel FIFO size */
+} dmacHw_CONTROLLER_ATTRIB_e;
+
+typedef unsigned long dmacHw_HANDLE_t;	/* DMA channel handle */
+typedef uint32_t dmacHw_ID_t;	/* DMA channel Id.  Must be created using
+				   "dmacHw_MAKE_CHANNEL_ID" macro
+				 */
+/* DMA channel configuration parameters */
+typedef struct {
+	uint32_t srcPeripheralPort;	/* Source peripheral port */
+	uint32_t dstPeripheralPort;	/* Destination peripheral port */
+	uint32_t srcStatusRegisterAddress;	/* Source status register address */
+	uint32_t dstStatusRegisterAddress;	/* Destination status register address of type  */
+
+	uint32_t srcGatherWidth;	/* Number of bytes gathered before successive gather opearation */
+	uint32_t srcGatherJump;	/* Number of bytes jumpped before successive gather opearation */
+	uint32_t dstScatterWidth;	/* Number of bytes sacattered before successive scatter opearation */
+	uint32_t dstScatterJump;	/* Number of bytes jumpped  before successive scatter opearation */
+	uint32_t maxDataPerBlock;	/* Maximum number of bytes to be transferred per block/descrptor.
+					   0 = Maximum possible.
+					 */
+
+	dmacHw_ADDRESS_UPDATE_MODE_e srcUpdate;	/* Source address update mode */
+	dmacHw_ADDRESS_UPDATE_MODE_e dstUpdate;	/* Destination address update mode */
+	dmacHw_TRANSFER_TYPE_e transferType;	/* DMA transfer type  */
+	dmacHw_TRANSFER_MODE_e transferMode;	/* DMA transfer mode */
+	dmacHw_MASTER_INTERFACE_e srcMasterInterface;	/* DMA source interface  */
+	dmacHw_MASTER_INTERFACE_e dstMasterInterface;	/* DMA destination interface */
+	dmacHw_TRANSACTION_WIDTH_e srcMaxTransactionWidth;	/* Source transaction width   */
+	dmacHw_TRANSACTION_WIDTH_e dstMaxTransactionWidth;	/* Destination transaction width */
+	dmacHw_BURST_WIDTH_e srcMaxBurstWidth;	/* Source burst width */
+	dmacHw_BURST_WIDTH_e dstMaxBurstWidth;	/* Destination burst width */
+	dmacHw_INTERRUPT_e blockTransferInterrupt;	/* Block trsnafer interrupt */
+	dmacHw_INTERRUPT_e completeTransferInterrupt;	/* Complete DMA trsnafer interrupt */
+	dmacHw_INTERRUPT_e errorInterrupt;	/* Error interrupt */
+	dmacHw_CHANNEL_PRIORITY_e channelPriority;	/* Channel priority */
+	dmacHw_FLOW_CONTROL_e flowControler;	/* Data flow controller */
+} dmacHw_CONFIG_t;
+
+/****************************************************************************/
+/**
+*  @brief   Initializes DMA
+*
+*  This function initializes DMA CSP driver
+*
+*  @note
+*     Must be called before using any DMA channel
+*/
+/****************************************************************************/
+void dmacHw_initDma(void);
+
+/****************************************************************************/
+/**
+*  @brief   Exit function for  DMA
+*
+*  This function isolates DMA from the system
+*
+*/
+/****************************************************************************/
+void dmacHw_exitDma(void);
+
+/****************************************************************************/
+/**
+*  @brief   Gets a handle to a DMA channel
+*
+*  This function returns a handle, representing a control block of a particular DMA channel
+*
+*  @return  -1       - On Failure
+*            handle  - On Success, representing a channel control block
+*
+*  @note
+*     None  Channel ID must be created using "dmacHw_MAKE_CHANNEL_ID" macro
+*/
+/****************************************************************************/
+dmacHw_HANDLE_t dmacHw_getChannelHandle(dmacHw_ID_t channelId	/* [ IN ] DMA Channel Id */
+    );
+
+/****************************************************************************/
+/**
+*  @brief   Initializes a DMA channel for use
+*
+*  This function initializes and resets a DMA channel for use
+*
+*  @return  -1     - On Failure
+*            0     - On Success
+*
+*  @note
+*     None
+*/
+/****************************************************************************/
+int dmacHw_initChannel(dmacHw_HANDLE_t handle	/*  [ IN ] DMA Channel handle  */
+    );
+
+/****************************************************************************/
+/**
+*  @brief  Estimates number of descriptor needed to perform certain DMA transfer
+*
+*
+*  @return  On failure : -1
+*           On success : Number of descriptor count
+*
+*
+*/
+/****************************************************************************/
+int dmacHw_calculateDescriptorCount(dmacHw_CONFIG_t *pConfig,	/*   [ IN ] Configuration settings */
+				    void *pSrcAddr,	/*   [ IN ] Source (Peripheral/Memory) address */
+				    void *pDstAddr,	/*   [ IN ] Destination (Peripheral/Memory) address */
+				    size_t dataLen	/*   [ IN ] Data length in bytes */
+    );
+
+/****************************************************************************/
+/**
+*  @brief   Initializes descriptor ring
+*
+*  This function will initializes the descriptor ring of a DMA channel
+*
+*
+*  @return   -1 - On failure
+*             0 - On success
+*  @note
+*     - "len" parameter should be obtained from "dmacHw_descriptorLen"
+*     - Descriptor buffer MUST be 32 bit aligned and uncached as it
+*       is accessed by ARM and DMA
+*/
+/****************************************************************************/
+int dmacHw_initDescriptor(void *pDescriptorVirt,	/*  [ IN ] Virtual address of uncahced buffer allocated to form descriptor ring */
+			  uint32_t descriptorPhyAddr,	/*  [ IN ] Physical address of pDescriptorVirt (descriptor buffer) */
+			  uint32_t len,	/*  [ IN ] Size of the pBuf */
+			  uint32_t num	/*  [ IN ] Number of descriptor in the ring */
+    );
+
+/****************************************************************************/
+/**
+*  @brief  Finds amount of memory required to form a descriptor ring
+*
+*
+*  @return   Number of bytes required to form a descriptor ring
+*
+*
+*  @note
+*     None
+*/
+/****************************************************************************/
+uint32_t dmacHw_descriptorLen(uint32_t descCnt	/*  [ IN ] Number of descriptor in the ring */
+    );
+
+/****************************************************************************/
+/**
+*  @brief   Configure DMA channel
+*
+*  @return  0  : On success
+*           -1 : On failure
+*/
+/****************************************************************************/
+int dmacHw_configChannel(dmacHw_HANDLE_t handle,	/*  [ IN ] DMA Channel handle  */
+			 dmacHw_CONFIG_t *pConfig	/*   [ IN ] Configuration settings */
+    );
+
+/****************************************************************************/
+/**
+*  @brief   Set descriptors for known data length
+*
+*  When DMA has to work as a flow controller, this function prepares the
+*  descriptor chain to transfer data
+*
+*  from:
+*          - Memory to memory
+*          - Peripheral to memory
+*          - Memory to Peripheral
+*          - Peripheral to Peripheral
+*
+*  @return   -1 - On failure
+*             0 - On success
+*
+*/
+/****************************************************************************/
+int dmacHw_setDataDescriptor(dmacHw_CONFIG_t *pConfig,	/*  [ IN ] Configuration settings */
+			     void *pDescriptor,	/*  [ IN ] Descriptor buffer  */
+			     void *pSrcAddr,	/*  [ IN ] Source (Peripheral/Memory) address */
+			     void *pDstAddr,	/*  [ IN ] Destination (Peripheral/Memory) address */
+			     size_t dataLen	/*  [ IN ] Length in bytes   */
+    );
+
+/****************************************************************************/
+/**
+*  @brief   Indicates whether DMA transfer is in progress or completed
+*
+*  @return   DMA transfer status
+*          dmacHw_TRANSFER_STATUS_BUSY:         DMA Transfer ongoing
+*          dmacHw_TRANSFER_STATUS_DONE:         DMA Transfer completed
+*          dmacHw_TRANSFER_STATUS_ERROR:        DMA Transfer error
+*
+*/
+/****************************************************************************/
+dmacHw_TRANSFER_STATUS_e dmacHw_transferCompleted(dmacHw_HANDLE_t handle	/*   [ IN ] DMA Channel handle  */
+    );
+
+/****************************************************************************/
+/**
+*  @brief   Set descriptor carrying control information
+*
+*  This function will be used to send specific control information to the device
+*  using the DMA channel
+*
+*
+*  @return  -1 - On failure
+*            0 - On success
+*
+*  @note
+*     None
+*/
+/****************************************************************************/
+int dmacHw_setControlDescriptor(dmacHw_CONFIG_t *pConfig,	/*  [ IN ] Configuration settings */
+				void *pDescriptor,	/*  [ IN ] Descriptor buffer  */
+				uint32_t ctlAddress,	/*  [ IN ] Address of the device control register  */
+				uint32_t control	/*  [ IN ] Device control information */
+    );
+
+/****************************************************************************/
+/**
+*  @brief   Read data DMA transferred to memory
+*
+*  This function will read data that has been DMAed to memory while transferring from:
+*          - Memory to memory
+*          - Peripheral to memory
+*
+*  @return  0 - No more data is available to read
+*           1 - More data might be available to read
+*
+*/
+/****************************************************************************/
+int dmacHw_readTransferredData(dmacHw_HANDLE_t handle,	/*  [ IN ] DMA Channel handle    */
+			       dmacHw_CONFIG_t *pConfig,	/*  [ IN ]  Configuration settings */
+			       void *pDescriptor,	/*  [ IN ] Descriptor buffer  */
+			       void **ppBbuf,	/*  [ OUT ] Data received */
+			       size_t *pLlen	/*  [ OUT ] Length of the data received */
+    );
+
+/****************************************************************************/
+/**
+*  @brief   Prepares descriptor ring, when source peripheral working as a flow controller
+*
+*  This function will form the descriptor ring by allocating buffers, when source peripheral
+*  has to work as a flow controller to transfer data from:
+*           - Peripheral to memory.
+*
+*  @return  -1 - On failure
+*            0 - On success
+*
+*
+*  @note
+*     None
+*/
+/****************************************************************************/
+int dmacHw_setVariableDataDescriptor(dmacHw_HANDLE_t handle,	/*  [ IN ] DMA Channel handle   */
+				     dmacHw_CONFIG_t *pConfig,	/*  [ IN ] Configuration settings */
+				     void *pDescriptor,	/*  [ IN ] Descriptor buffer  */
+				     uint32_t srcAddr,	/*  [ IN ] Source peripheral address */
+				     void *(*fpAlloc) (int len),	/*  [ IN ] Function pointer  that provides destination memory */
+				     int len,	/*  [ IN ] Number of bytes "fpAlloc" will allocate for destination */
+				     int num	/*  [ IN ] Number of descriptor to set */
+    );
+
+/****************************************************************************/
+/**
+*  @brief   Program channel register to initiate transfer
+*
+*  @return  void
+*
+*
+*  @note
+*     - Descriptor buffer MUST ALWAYS be flushed before calling this function
+*     - This function should also be called from ISR to program the channel with
+*       pending descriptors
+*/
+/****************************************************************************/
+void dmacHw_initiateTransfer(dmacHw_HANDLE_t handle,	/*   [ IN ] DMA Channel handle */
+			     dmacHw_CONFIG_t *pConfig,	/*   [ IN ] Configuration settings */
+			     void *pDescriptor	/*   [ IN ] Descriptor buffer  */
+    );
+
+/****************************************************************************/
+/**
+*  @brief   Resets descriptor control information
+*
+*  @return  void
+*/
+/****************************************************************************/
+void dmacHw_resetDescriptorControl(void *pDescriptor	/*   [ IN ] Descriptor buffer  */
+    );
+
+/****************************************************************************/
+/**
+*  @brief   Program channel register to stop transfer
+*
+*  Ensures the channel is not doing any transfer after calling this function
+*
+*  @return  void
+*
+*/
+/****************************************************************************/
+void dmacHw_stopTransfer(dmacHw_HANDLE_t handle	/*   [ IN ] DMA Channel handle */
+    );
+
+/****************************************************************************/
+/**
+*  @brief   Check the existence of pending descriptor
+*
+*  This function confirmes if there is any pending descriptor in the chain
+*  to program the channel
+*
+*  @return  1 : Channel need to be programmed with pending descriptor
+*           0 : No more pending descriptor to programe the channel
+*
+*  @note
+*     - This function should be called from ISR in case there are pending
+*       descriptor to program the channel.
+*
+*     Example:
+*
+*     dmac_isr ()
+*     {
+*         ...
+*         if (dmacHw_descriptorPending (handle))
+*         {
+*            dmacHw_initiateTransfer (handle);
+*         }
+*     }
+*
+*/
+/****************************************************************************/
+uint32_t dmacHw_descriptorPending(dmacHw_HANDLE_t handle,	/*   [ IN ] DMA Channel handle */
+				  void *pDescriptor	/*   [ IN ] Descriptor buffer */
+    );
+
+/****************************************************************************/
+/**
+*  @brief   Deallocates source or destination memory, allocated
+*
+*  This function can be called to deallocate data memory that was DMAed successfully
+*
+*  @return  -1  - On failure
+*            0  - On success
+*
+*  @note
+*     This function will be called ONLY, when source OR destination address is pointing
+*     to dynamic memory
+*/
+/****************************************************************************/
+int dmacHw_freeMem(dmacHw_CONFIG_t *pConfig,	/*  [ IN ] Configuration settings */
+		   void *pDescriptor,	/*  [ IN ] Descriptor buffer  */
+		   void (*fpFree) (void *)	/*  [ IN ] Function pointer to free data memory */
+    );
+
+/****************************************************************************/
+/**
+*  @brief   Clears the interrupt
+*
+*  This function clears the DMA channel specific interrupt
+*
+*  @return   N/A
+*
+*  @note
+*     Must be called under the context of ISR
+*/
+/****************************************************************************/
+void dmacHw_clearInterrupt(dmacHw_HANDLE_t handle	/*  [ IN ] DMA Channel handle  */
+    );
+
+/****************************************************************************/
+/**
+*  @brief   Returns the cause of channel specific DMA interrupt
+*
+*  This function returns the cause of interrupt
+*
+*  @return  Interrupt status, each bit representing a specific type of interrupt
+*           of type dmacHw_INTERRUPT_STATUS_e
+*  @note
+*           This function should be called under the context of ISR
+*/
+/****************************************************************************/
+dmacHw_INTERRUPT_STATUS_e dmacHw_getInterruptStatus(dmacHw_HANDLE_t handle	/*  [ IN ] DMA Channel handle  */
+    );
+
+/****************************************************************************/
+/**
+*  @brief   Indentifies a DMA channel causing interrupt
+*
+*  This functions returns a channel causing interrupt of type dmacHw_INTERRUPT_STATUS_e
+*
+*  @return  NULL   : No channel causing DMA interrupt
+*           ! NULL : Handle to a channel causing DMA interrupt
+*  @note
+*     dmacHw_clearInterrupt() must be called with a valid handle after calling this function
+*/
+/****************************************************************************/
+dmacHw_HANDLE_t dmacHw_getInterruptSource(void);
+
+/****************************************************************************/
+/**
+*  @brief   Sets channel specific user data
+*
+*  This function associates user data to a specific DMA channel
+*
+*/
+/****************************************************************************/
+void dmacHw_setChannelUserData(dmacHw_HANDLE_t handle,	/*  [ IN ] DMA Channel handle  */
+			       void *userData	/*  [ IN ] User data  */
+    );
+
+/****************************************************************************/
+/**
+*  @brief   Gets channel specific user data
+*
+*  This function returns user data specific to a DMA channel
+*
+*  @return   user data
+*/
+/****************************************************************************/
+void *dmacHw_getChannelUserData(dmacHw_HANDLE_t handle	/*  [ IN ] DMA Channel handle  */
+    );
+
+/****************************************************************************/
+/**
+*  @brief   Displays channel specific registers and other control parameters
+*
+*
+*  @return  void
+*
+*  @note
+*     None
+*/
+/****************************************************************************/
+void dmacHw_printDebugInfo(dmacHw_HANDLE_t handle,	/*  [ IN ] DMA Channel handle  */
+			   void *pDescriptor,	/*  [ IN ] Descriptor buffer  */
+			   int (*fpPrint) (const char *, ...)	/*  [ IN ] Print callback function */
+    );
+
+/****************************************************************************/
+/**
+*  @brief   Provides DMA controller attributes
+*
+*
+*  @return  DMA controller attributes
+*
+*  @note
+*     None
+*/
+/****************************************************************************/
+uint32_t dmacHw_getDmaControllerAttribute(dmacHw_HANDLE_t handle,	/*  [ IN ]  DMA Channel handle  */
+					  dmacHw_CONTROLLER_ATTRIB_e attr	/*  [ IN ]  DMA Controller attribute of type  dmacHw_CONTROLLER_ATTRIB_e */
+    );
+
+#endif /* _DMACHW_H */
diff --git a/arch/arm/mach-bcmring/include/mach/csp/dmacHw_priv.h b/arch/arm/mach-bcmring/include/mach/csp/dmacHw_priv.h
index d67e2f8..9d9455e 100644
--- a/arch/arm/mach-bcmring/include/mach/csp/dmacHw_priv.h
+++ b/arch/arm/mach-bcmring/include/mach/csp/dmacHw_priv.h
@@ -24,7 +24,7 @@
 #ifndef _DMACHW_PRIV_H
 #define _DMACHW_PRIV_H
 
-#include <csp/stdint.h>
+#include <linux/types.h>
 
 /* Data type for DMA Link List Item */
 typedef struct {
diff --git a/arch/arm/mach-bcmring/include/mach/csp/dmacHw_reg.h b/arch/arm/mach-bcmring/include/mach/csp/dmacHw_reg.h
index f1ecf96..7cd0aaf 100644
--- a/arch/arm/mach-bcmring/include/mach/csp/dmacHw_reg.h
+++ b/arch/arm/mach-bcmring/include/mach/csp/dmacHw_reg.h
@@ -24,7 +24,7 @@
 #ifndef _DMACHW_REG_H
 #define _DMACHW_REG_H
 
-#include <csp/stdint.h>
+#include <linux/types.h>
 #include <mach/csp/mm_io.h>
 
 /* Data type for 64 bit little endian register */
@@ -121,75 +121,75 @@ typedef struct {
 } dmacHw_MISC_t;
 
 /* Base registers */
-#define dmacHw_0_MODULE_BASE_ADDR        (char *) MM_IO_BASE_DMA0	/* DMAC 0 module's base address */
-#define dmacHw_1_MODULE_BASE_ADDR        (char *) MM_IO_BASE_DMA1	/* DMAC 1 module's base address */
+#define dmacHw_0_MODULE_BASE_ADDR        (char __iomem*) MM_IO_BASE_DMA0	/* DMAC 0 module's base address */
+#define dmacHw_1_MODULE_BASE_ADDR        (char __iomem*) MM_IO_BASE_DMA1	/* DMAC 1 module's base address */
 
 extern uint32_t dmaChannelCount_0;
 extern uint32_t dmaChannelCount_1;
 
 /* Define channel specific registers */
-#define dmacHw_CHAN_BASE(module, chan)          ((dmacHw_CH_REG_t *) ((char *)((module) ? dmacHw_1_MODULE_BASE_ADDR : dmacHw_0_MODULE_BASE_ADDR) + ((chan) * sizeof(dmacHw_CH_REG_t))))
+#define dmacHw_CHAN_BASE(module, chan)          ((dmacHw_CH_REG_t __iomem*) ((char __iomem*)((module) ? dmacHw_1_MODULE_BASE_ADDR : dmacHw_0_MODULE_BASE_ADDR) + ((chan) * sizeof(dmacHw_CH_REG_t))))
 
 /* Raw interrupt status registers */
-#define dmacHw_REG_INT_RAW_BASE(module)         ((char *)dmacHw_CHAN_BASE((module), ((module) ? dmaChannelCount_1 : dmaChannelCount_0)))
-#define dmacHw_REG_INT_RAW_TRAN(module)         (((dmacHw_INT_RAW_t *) dmacHw_REG_INT_RAW_BASE((module)))->RawTfr.lo)
-#define dmacHw_REG_INT_RAW_BLOCK(module)        (((dmacHw_INT_RAW_t *) dmacHw_REG_INT_RAW_BASE((module)))->RawBlock.lo)
-#define dmacHw_REG_INT_RAW_STRAN(module)        (((dmacHw_INT_RAW_t *) dmacHw_REG_INT_RAW_BASE((module)))->RawSrcTran.lo)
-#define dmacHw_REG_INT_RAW_DTRAN(module)        (((dmacHw_INT_RAW_t *) dmacHw_REG_INT_RAW_BASE((module)))->RawDstTran.lo)
-#define dmacHw_REG_INT_RAW_ERROR(module)        (((dmacHw_INT_RAW_t *) dmacHw_REG_INT_RAW_BASE((module)))->RawErr.lo)
+#define dmacHw_REG_INT_RAW_BASE(module)         ((char __iomem *)dmacHw_CHAN_BASE((module), ((module) ? dmaChannelCount_1 : dmaChannelCount_0)))
+#define dmacHw_REG_INT_RAW_TRAN(module)         (((dmacHw_INT_RAW_t __iomem *) dmacHw_REG_INT_RAW_BASE((module)))->RawTfr.lo)
+#define dmacHw_REG_INT_RAW_BLOCK(module)        (((dmacHw_INT_RAW_t __iomem *) dmacHw_REG_INT_RAW_BASE((module)))->RawBlock.lo)
+#define dmacHw_REG_INT_RAW_STRAN(module)        (((dmacHw_INT_RAW_t __iomem *) dmacHw_REG_INT_RAW_BASE((module)))->RawSrcTran.lo)
+#define dmacHw_REG_INT_RAW_DTRAN(module)        (((dmacHw_INT_RAW_t __iomem *) dmacHw_REG_INT_RAW_BASE((module)))->RawDstTran.lo)
+#define dmacHw_REG_INT_RAW_ERROR(module)        (((dmacHw_INT_RAW_t __iomem *) dmacHw_REG_INT_RAW_BASE((module)))->RawErr.lo)
 
 /* Interrupt status registers */
-#define dmacHw_REG_INT_STAT_BASE(module)        ((char *)(dmacHw_REG_INT_RAW_BASE((module)) + sizeof(dmacHw_INT_RAW_t)))
-#define dmacHw_REG_INT_STAT_TRAN(module)        (((dmacHw_INT_STATUS_t *) dmacHw_REG_INT_STAT_BASE((module)))->StatusTfr.lo)
-#define dmacHw_REG_INT_STAT_BLOCK(module)       (((dmacHw_INT_STATUS_t *) dmacHw_REG_INT_STAT_BASE((module)))->StatusBlock.lo)
-#define dmacHw_REG_INT_STAT_STRAN(module)       (((dmacHw_INT_STATUS_t *) dmacHw_REG_INT_STAT_BASE((module)))->StatusSrcTran.lo)
-#define dmacHw_REG_INT_STAT_DTRAN(module)       (((dmacHw_INT_STATUS_t *) dmacHw_REG_INT_STAT_BASE((module)))->StatusDstTran.lo)
-#define dmacHw_REG_INT_STAT_ERROR(module)       (((dmacHw_INT_STATUS_t *) dmacHw_REG_INT_STAT_BASE((module)))->StatusErr.lo)
+#define dmacHw_REG_INT_STAT_BASE(module)        ((char __iomem*)(dmacHw_REG_INT_RAW_BASE((module)) + sizeof(dmacHw_INT_RAW_t)))
+#define dmacHw_REG_INT_STAT_TRAN(module)        (((dmacHw_INT_STATUS_t __iomem *) dmacHw_REG_INT_STAT_BASE((module)))->StatusTfr.lo)
+#define dmacHw_REG_INT_STAT_BLOCK(module)       (((dmacHw_INT_STATUS_t __iomem *) dmacHw_REG_INT_STAT_BASE((module)))->StatusBlock.lo)
+#define dmacHw_REG_INT_STAT_STRAN(module)       (((dmacHw_INT_STATUS_t __iomem *) dmacHw_REG_INT_STAT_BASE((module)))->StatusSrcTran.lo)
+#define dmacHw_REG_INT_STAT_DTRAN(module)       (((dmacHw_INT_STATUS_t __iomem *) dmacHw_REG_INT_STAT_BASE((module)))->StatusDstTran.lo)
+#define dmacHw_REG_INT_STAT_ERROR(module)       (((dmacHw_INT_STATUS_t __iomem *) dmacHw_REG_INT_STAT_BASE((module)))->StatusErr.lo)
 
 /* Interrupt status registers */
-#define dmacHw_REG_INT_MASK_BASE(module)        ((char *)(dmacHw_REG_INT_STAT_BASE((module)) + sizeof(dmacHw_INT_STATUS_t)))
-#define dmacHw_REG_INT_MASK_TRAN(module)        (((dmacHw_INT_MASK_t *) dmacHw_REG_INT_MASK_BASE((module)))->MaskTfr.lo)
-#define dmacHw_REG_INT_MASK_BLOCK(module)       (((dmacHw_INT_MASK_t *) dmacHw_REG_INT_MASK_BASE((module)))->MaskBlock.lo)
-#define dmacHw_REG_INT_MASK_STRAN(module)       (((dmacHw_INT_MASK_t *) dmacHw_REG_INT_MASK_BASE((module)))->MaskSrcTran.lo)
-#define dmacHw_REG_INT_MASK_DTRAN(module)       (((dmacHw_INT_MASK_t *) dmacHw_REG_INT_MASK_BASE((module)))->MaskDstTran.lo)
-#define dmacHw_REG_INT_MASK_ERROR(module)       (((dmacHw_INT_MASK_t *) dmacHw_REG_INT_MASK_BASE((module)))->MaskErr.lo)
+#define dmacHw_REG_INT_MASK_BASE(module)        ((char __iomem*)(dmacHw_REG_INT_STAT_BASE((module)) + sizeof(dmacHw_INT_STATUS_t)))
+#define dmacHw_REG_INT_MASK_TRAN(module)        (((dmacHw_INT_MASK_t __iomem *) dmacHw_REG_INT_MASK_BASE((module)))->MaskTfr.lo)
+#define dmacHw_REG_INT_MASK_BLOCK(module)       (((dmacHw_INT_MASK_t __iomem *) dmacHw_REG_INT_MASK_BASE((module)))->MaskBlock.lo)
+#define dmacHw_REG_INT_MASK_STRAN(module)       (((dmacHw_INT_MASK_t __iomem *) dmacHw_REG_INT_MASK_BASE((module)))->MaskSrcTran.lo)
+#define dmacHw_REG_INT_MASK_DTRAN(module)       (((dmacHw_INT_MASK_t __iomem *) dmacHw_REG_INT_MASK_BASE((module)))->MaskDstTran.lo)
+#define dmacHw_REG_INT_MASK_ERROR(module)       (((dmacHw_INT_MASK_t __iomem *) dmacHw_REG_INT_MASK_BASE((module)))->MaskErr.lo)
 
 /* Interrupt clear registers */
-#define dmacHw_REG_INT_CLEAR_BASE(module)       ((char *)(dmacHw_REG_INT_MASK_BASE((module)) + sizeof(dmacHw_INT_MASK_t)))
-#define dmacHw_REG_INT_CLEAR_TRAN(module)       (((dmacHw_INT_CLEAR_t *) dmacHw_REG_INT_CLEAR_BASE((module)))->ClearTfr.lo)
-#define dmacHw_REG_INT_CLEAR_BLOCK(module)      (((dmacHw_INT_CLEAR_t *) dmacHw_REG_INT_CLEAR_BASE((module)))->ClearBlock.lo)
-#define dmacHw_REG_INT_CLEAR_STRAN(module)      (((dmacHw_INT_CLEAR_t *) dmacHw_REG_INT_CLEAR_BASE((module)))->ClearSrcTran.lo)
-#define dmacHw_REG_INT_CLEAR_DTRAN(module)      (((dmacHw_INT_CLEAR_t *) dmacHw_REG_INT_CLEAR_BASE((module)))->ClearDstTran.lo)
-#define dmacHw_REG_INT_CLEAR_ERROR(module)      (((dmacHw_INT_CLEAR_t *) dmacHw_REG_INT_CLEAR_BASE((module)))->ClearErr.lo)
-#define dmacHw_REG_INT_STATUS(module)           (((dmacHw_INT_CLEAR_t *) dmacHw_REG_INT_CLEAR_BASE((module)))->StatusInt.lo)
+#define dmacHw_REG_INT_CLEAR_BASE(module)       ((char __iomem*)(dmacHw_REG_INT_MASK_BASE((module)) + sizeof(dmacHw_INT_MASK_t)))
+#define dmacHw_REG_INT_CLEAR_TRAN(module)       (((dmacHw_INT_CLEAR_t __iomem *) dmacHw_REG_INT_CLEAR_BASE((module)))->ClearTfr.lo)
+#define dmacHw_REG_INT_CLEAR_BLOCK(module)      (((dmacHw_INT_CLEAR_t __iomem *) dmacHw_REG_INT_CLEAR_BASE((module)))->ClearBlock.lo)
+#define dmacHw_REG_INT_CLEAR_STRAN(module)      (((dmacHw_INT_CLEAR_t __iomem *) dmacHw_REG_INT_CLEAR_BASE((module)))->ClearSrcTran.lo)
+#define dmacHw_REG_INT_CLEAR_DTRAN(module)      (((dmacHw_INT_CLEAR_t __iomem *) dmacHw_REG_INT_CLEAR_BASE((module)))->ClearDstTran.lo)
+#define dmacHw_REG_INT_CLEAR_ERROR(module)      (((dmacHw_INT_CLEAR_t __iomem *) dmacHw_REG_INT_CLEAR_BASE((module)))->ClearErr.lo)
+#define dmacHw_REG_INT_STATUS(module)           (((dmacHw_INT_CLEAR_t __iomem *) dmacHw_REG_INT_CLEAR_BASE((module)))->StatusInt.lo)
 
 /* Software handshaking registers */
-#define dmacHw_REG_SW_HS_BASE(module)           ((char *)(dmacHw_REG_INT_CLEAR_BASE((module)) + sizeof(dmacHw_INT_CLEAR_t)))
-#define dmacHw_REG_SW_HS_SRC_REQ(module)        (((dmacHw_SW_HANDSHAKE_t *) dmacHw_REG_SW_HS_BASE((module)))->ReqSrcReg.lo)
-#define dmacHw_REG_SW_HS_DST_REQ(module)        (((dmacHw_SW_HANDSHAKE_t *) dmacHw_REG_SW_HS_BASE((module)))->ReqDstReg.lo)
-#define dmacHw_REG_SW_HS_SRC_SGL_REQ(module)    (((dmacHw_SW_HANDSHAKE_t *) dmacHw_REG_SW_HS_BASE((module)))->SglReqSrcReg.lo)
-#define dmacHw_REG_SW_HS_DST_SGL_REQ(module)    (((dmacHw_SW_HANDSHAKE_t *) dmacHw_REG_SW_HS_BASE((module)))->SglReqDstReg.lo)
-#define dmacHw_REG_SW_HS_SRC_LST_REQ(module)    (((dmacHw_SW_HANDSHAKE_t *) dmacHw_REG_SW_HS_BASE((module)))->LstSrcReg.lo)
-#define dmacHw_REG_SW_HS_DST_LST_REQ(module)    (((dmacHw_SW_HANDSHAKE_t *) dmacHw_REG_SW_HS_BASE((module)))->LstDstReg.lo)
+#define dmacHw_REG_SW_HS_BASE(module)           ((char __iomem*)(dmacHw_REG_INT_CLEAR_BASE((module)) + sizeof(dmacHw_INT_CLEAR_t)))
+#define dmacHw_REG_SW_HS_SRC_REQ(module)        (((dmacHw_SW_HANDSHAKE_t __iomem *) dmacHw_REG_SW_HS_BASE((module)))->ReqSrcReg.lo)
+#define dmacHw_REG_SW_HS_DST_REQ(module)        (((dmacHw_SW_HANDSHAKE_t __iomem *) dmacHw_REG_SW_HS_BASE((module)))->ReqDstReg.lo)
+#define dmacHw_REG_SW_HS_SRC_SGL_REQ(module)    (((dmacHw_SW_HANDSHAKE_t __iomem *) dmacHw_REG_SW_HS_BASE((module)))->SglReqSrcReg.lo)
+#define dmacHw_REG_SW_HS_DST_SGL_REQ(module)    (((dmacHw_SW_HANDSHAKE_t __iomem *) dmacHw_REG_SW_HS_BASE((module)))->SglReqDstReg.lo)
+#define dmacHw_REG_SW_HS_SRC_LST_REQ(module)    (((dmacHw_SW_HANDSHAKE_t __iomem *) dmacHw_REG_SW_HS_BASE((module)))->LstSrcReg.lo)
+#define dmacHw_REG_SW_HS_DST_LST_REQ(module)    (((dmacHw_SW_HANDSHAKE_t __iomem *) dmacHw_REG_SW_HS_BASE((module)))->LstDstReg.lo)
 
 /* Miscellaneous registers */
-#define dmacHw_REG_MISC_BASE(module)            ((char *)(dmacHw_REG_SW_HS_BASE((module)) + sizeof(dmacHw_SW_HANDSHAKE_t)))
-#define dmacHw_REG_MISC_CFG(module)             (((dmacHw_MISC_t *) dmacHw_REG_MISC_BASE((module)))->DmaCfgReg.lo)
-#define dmacHw_REG_MISC_CH_ENABLE(module)       (((dmacHw_MISC_t *) dmacHw_REG_MISC_BASE((module)))->ChEnReg.lo)
-#define dmacHw_REG_MISC_ID(module)              (((dmacHw_MISC_t *) dmacHw_REG_MISC_BASE((module)))->DmaIdReg.lo)
-#define dmacHw_REG_MISC_TEST(module)            (((dmacHw_MISC_t *) dmacHw_REG_MISC_BASE((module)))->DmaTestReg.lo)
-#define dmacHw_REG_MISC_COMP_PARAM1_LO(module)  (((dmacHw_MISC_t *) dmacHw_REG_MISC_BASE((module)))->CompParm1.lo)
-#define dmacHw_REG_MISC_COMP_PARAM1_HI(module)  (((dmacHw_MISC_t *) dmacHw_REG_MISC_BASE((module)))->CompParm1.hi)
-#define dmacHw_REG_MISC_COMP_PARAM2_LO(module)  (((dmacHw_MISC_t *) dmacHw_REG_MISC_BASE((module)))->CompParm2.lo)
-#define dmacHw_REG_MISC_COMP_PARAM2_HI(module)  (((dmacHw_MISC_t *) dmacHw_REG_MISC_BASE((module)))->CompParm2.hi)
-#define dmacHw_REG_MISC_COMP_PARAM3_LO(module)  (((dmacHw_MISC_t *) dmacHw_REG_MISC_BASE((module)))->CompParm3.lo)
-#define dmacHw_REG_MISC_COMP_PARAM3_HI(module)  (((dmacHw_MISC_t *) dmacHw_REG_MISC_BASE((module)))->CompParm3.hi)
-#define dmacHw_REG_MISC_COMP_PARAM4_LO(module)  (((dmacHw_MISC_t *) dmacHw_REG_MISC_BASE((module)))->CompParm4.lo)
-#define dmacHw_REG_MISC_COMP_PARAM4_HI(module)  (((dmacHw_MISC_t *) dmacHw_REG_MISC_BASE((module)))->CompParm4.hi)
-#define dmacHw_REG_MISC_COMP_PARAM5_LO(module)  (((dmacHw_MISC_t *) dmacHw_REG_MISC_BASE((module)))->CompParm5.lo)
-#define dmacHw_REG_MISC_COMP_PARAM5_HI(module)  (((dmacHw_MISC_t *) dmacHw_REG_MISC_BASE((module)))->CompParm5.hi)
-#define dmacHw_REG_MISC_COMP_PARAM6_LO(module)  (((dmacHw_MISC_t *) dmacHw_REG_MISC_BASE((module)))->CompParm6.lo)
-#define dmacHw_REG_MISC_COMP_PARAM6_HI(module)  (((dmacHw_MISC_t *) dmacHw_REG_MISC_BASE((module)))->CompParm6.hi)
+#define dmacHw_REG_MISC_BASE(module)            ((char __iomem*)(dmacHw_REG_SW_HS_BASE((module)) + sizeof(dmacHw_SW_HANDSHAKE_t)))
+#define dmacHw_REG_MISC_CFG(module)             (((dmacHw_MISC_t __iomem*) dmacHw_REG_MISC_BASE((module)))->DmaCfgReg.lo)
+#define dmacHw_REG_MISC_CH_ENABLE(module)       (((dmacHw_MISC_t __iomem*) dmacHw_REG_MISC_BASE((module)))->ChEnReg.lo)
+#define dmacHw_REG_MISC_ID(module)              (((dmacHw_MISC_t __iomem*) dmacHw_REG_MISC_BASE((module)))->DmaIdReg.lo)
+#define dmacHw_REG_MISC_TEST(module)            (((dmacHw_MISC_t __iomem*) dmacHw_REG_MISC_BASE((module)))->DmaTestReg.lo)
+#define dmacHw_REG_MISC_COMP_PARAM1_LO(module)  (((dmacHw_MISC_t __iomem*) dmacHw_REG_MISC_BASE((module)))->CompParm1.lo)
+#define dmacHw_REG_MISC_COMP_PARAM1_HI(module)  (((dmacHw_MISC_t __iomem*) dmacHw_REG_MISC_BASE((module)))->CompParm1.hi)
+#define dmacHw_REG_MISC_COMP_PARAM2_LO(module)  (((dmacHw_MISC_t __iomem*) dmacHw_REG_MISC_BASE((module)))->CompParm2.lo)
+#define dmacHw_REG_MISC_COMP_PARAM2_HI(module)  (((dmacHw_MISC_t __iomem*) dmacHw_REG_MISC_BASE((module)))->CompParm2.hi)
+#define dmacHw_REG_MISC_COMP_PARAM3_LO(module)  (((dmacHw_MISC_t __iomem*) dmacHw_REG_MISC_BASE((module)))->CompParm3.lo)
+#define dmacHw_REG_MISC_COMP_PARAM3_HI(module)  (((dmacHw_MISC_t __iomem*) dmacHw_REG_MISC_BASE((module)))->CompParm3.hi)
+#define dmacHw_REG_MISC_COMP_PARAM4_LO(module)  (((dmacHw_MISC_t __iomem*) dmacHw_REG_MISC_BASE((module)))->CompParm4.lo)
+#define dmacHw_REG_MISC_COMP_PARAM4_HI(module)  (((dmacHw_MISC_t __iomem*) dmacHw_REG_MISC_BASE((module)))->CompParm4.hi)
+#define dmacHw_REG_MISC_COMP_PARAM5_LO(module)  (((dmacHw_MISC_t __iomem*) dmacHw_REG_MISC_BASE((module)))->CompParm5.lo)
+#define dmacHw_REG_MISC_COMP_PARAM5_HI(module)  (((dmacHw_MISC_t __iomem*) dmacHw_REG_MISC_BASE((module)))->CompParm5.hi)
+#define dmacHw_REG_MISC_COMP_PARAM6_LO(module)  (((dmacHw_MISC_t __iomem*) dmacHw_REG_MISC_BASE((module)))->CompParm6.lo)
+#define dmacHw_REG_MISC_COMP_PARAM6_HI(module)  (((dmacHw_MISC_t __iomem*) dmacHw_REG_MISC_BASE((module)))->CompParm6.hi)
 
 /* Channel control registers */
 #define dmacHw_REG_SAR(module, chan)            (dmacHw_CHAN_BASE((module), (chan))->ChannelSar.lo)
diff --git a/arch/arm/mach-bcmring/include/mach/csp/hw_cfg.h b/arch/arm/mach-bcmring/include/mach/csp/hw_cfg.h
index cfa91be..27f59dd 100644
--- a/arch/arm/mach-bcmring/include/mach/csp/hw_cfg.h
+++ b/arch/arm/mach-bcmring/include/mach/csp/hw_cfg.h
@@ -18,7 +18,7 @@
 
 /* ---- Include Files ---------------------------------------------------- */
 
-#include <cfg_global.h>
+#include <mach/cfg_global.h>
 #include <mach/csp/cap_inline.h>
 
 #if defined(__KERNEL__)
diff --git a/arch/arm/mach-bcmring/include/mach/csp/intcHw_reg.h b/arch/arm/mach-bcmring/include/mach/csp/intcHw_reg.h
index 0aeb6a6..f59db25 100644
--- a/arch/arm/mach-bcmring/include/mach/csp/intcHw_reg.h
+++ b/arch/arm/mach-bcmring/include/mach/csp/intcHw_reg.h
@@ -27,8 +27,8 @@
 #define _INTCHW_REG_H
 
 /* ---- Include Files ---------------------------------------------------- */
-#include <csp/stdint.h>
-#include <csp/reg.h>
+#include <linux/types.h>
+#include <mach/csp/reg.h>
 #include <mach/csp/mm_io.h>
 
 /* ---- Public Constants and Types --------------------------------------- */
@@ -37,9 +37,9 @@
 #define INTCHW_NUM_INTC           3
 
 /* Defines for interrupt controllers. This simplifies and cleans up the function calls. */
-#define INTCHW_INTC0    ((void *)MM_IO_BASE_INTC0)
-#define INTCHW_INTC1    ((void *)MM_IO_BASE_INTC1)
-#define INTCHW_SINTC    ((void *)MM_IO_BASE_SINTC)
+#define INTCHW_INTC0    (MM_IO_BASE_INTC0)
+#define INTCHW_INTC1    (MM_IO_BASE_INTC1)
+#define INTCHW_SINTC    (MM_IO_BASE_SINTC)
 
 /* INTC0 - interrupt controller 0 */
 #define INTCHW_INTC0_PIF_BITNUM           31	/* Peripheral interface interrupt */
@@ -232,15 +232,15 @@
 /* ---- Public Variable Externs ------------------------------------------ */
 /* ---- Public Function Prototypes --------------------------------------- */
 /* Clear one or more IRQ interrupts. */
-static inline void intcHw_irq_disable(void *basep, uint32_t mask)
+static inline void intcHw_irq_disable(void __iomem *basep, uint32_t mask)
 {
-	__REG32(basep + INTCHW_INTENCLEAR) = mask;
+	writel(mask, basep + INTCHW_INTENCLEAR);
 }
 
 /* Enables one or more IRQ interrupts. */
-static inline void intcHw_irq_enable(void *basep, uint32_t mask)
+static inline void intcHw_irq_enable(void __iomem *basep, uint32_t mask)
 {
-	__REG32(basep + INTCHW_INTENABLE) = mask;
+	writel(mask, basep + INTCHW_INTENABLE);
 }
 
 #endif /* _INTCHW_REG_H */
diff --git a/arch/arm/mach-bcmring/include/mach/csp/mm_addr.h b/arch/arm/mach-bcmring/include/mach/csp/mm_addr.h
index ad58cf8..d571962 100644
--- a/arch/arm/mach-bcmring/include/mach/csp/mm_addr.h
+++ b/arch/arm/mach-bcmring/include/mach/csp/mm_addr.h
@@ -29,7 +29,7 @@
 /* ---- Include Files ---------------------------------------------------- */
 
 #if !defined(CSP_SIMULATION)
-#include <cfg_global.h>
+#include <mach/cfg_global.h>
 #endif
 
 /* ---- Public Constants and Types --------------------------------------- */
diff --git a/arch/arm/mach-bcmring/include/mach/csp/mm_io.h b/arch/arm/mach-bcmring/include/mach/csp/mm_io.h
index de92ec6..47450c2 100644
--- a/arch/arm/mach-bcmring/include/mach/csp/mm_io.h
+++ b/arch/arm/mach-bcmring/include/mach/csp/mm_io.h
@@ -30,7 +30,7 @@
 #include <mach/csp/mm_addr.h>
 
 #if !defined(CSP_SIMULATION)
-#include <cfg_global.h>
+#include <mach/cfg_global.h>
 #endif
 
 /* ---- Public Constants and Types --------------------------------------- */
@@ -49,7 +49,7 @@
 #ifdef __ASSEMBLY__
 #define MM_IO_PHYS_TO_VIRT(phys)       (0xF0000000 | (((phys) >> 4) & 0x0F000000) | ((phys) & 0xFFFFFF))
 #else
-#define MM_IO_PHYS_TO_VIRT(phys)       (((phys) == MM_ADDR_IO_VPM_EXTMEM_RSVD) ? 0xF0000000 : \
+#define MM_IO_PHYS_TO_VIRT(phys)       (void __iomem *)(((phys) == MM_ADDR_IO_VPM_EXTMEM_RSVD) ? 0xF0000000 : \
 			(0xF0000000 | (((phys) >> 4) & 0x0F000000) | ((phys) & 0xFFFFFF)))
 #endif
 #endif
@@ -60,8 +60,8 @@
 #ifdef __ASSEMBLY__
 #define MM_IO_VIRT_TO_PHYS(virt)       ((((virt) & 0x0F000000) << 4) | ((virt) & 0xFFFFFF))
 #else
-#define MM_IO_VIRT_TO_PHYS(virt)       (((virt) == 0xF0000000) ? MM_ADDR_IO_VPM_EXTMEM_RSVD : \
-			((((virt) & 0x0F000000) << 4) | ((virt) & 0xFFFFFF)))
+#define MM_IO_VIRT_TO_PHYS(virt)       (((unsigned long)(virt) == 0xF0000000) ? MM_ADDR_IO_VPM_EXTMEM_RSVD : \
+			((((unsigned long)(virt) & 0x0F000000) << 4) | ((unsigned long)(virt) & 0xFFFFFF)))
 #endif
 #endif
 
diff --git a/arch/arm/mach-bcmring/include/mach/csp/reg.h b/arch/arm/mach-bcmring/include/mach/csp/reg.h
new file mode 100644
index 0000000..d9cbdca
--- /dev/null
+++ b/arch/arm/mach-bcmring/include/mach/csp/reg.h
@@ -0,0 +1,115 @@
+/*****************************************************************************
+* Copyright 2003 - 2008 Broadcom Corporation.  All rights reserved.
+*
+* Unless you and Broadcom execute a separate written software license
+* agreement governing use of this software, this software is licensed to you
+* under the terms of the GNU General Public License version 2, available at
+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
+*
+* Notwithstanding the above, under no circumstances may you combine this
+* software in any way with any other Broadcom software provided under a
+* license other than the GPL, without Broadcom's express prior written
+* consent.
+*****************************************************************************/
+
+/****************************************************************************/
+/**
+*  @file    reg.h
+*
+*  @brief   Generic register definitions used in CSP
+*/
+/****************************************************************************/
+
+#ifndef CSP_REG_H
+#define CSP_REG_H
+
+/* ---- Include Files ---------------------------------------------------- */
+
+#include <linux/types.h>
+#include <linux/io.h>
+
+/* ---- Public Constants and Types --------------------------------------- */
+
+#define __REG32(x)      (*((volatile uint32_t __iomem *)(x)))
+#define __REG16(x)      (*((volatile uint16_t __iomem *)(x)))
+#define __REG8(x)       (*((volatile uint8_t __iomem *) (x)))
+
+/* Macros used to define a sequence of reserved registers. The start / end */
+/* are byte offsets in the particular register definition, with the "end" */
+/* being the offset of the next un-reserved register. E.g. if offsets */
+/* 0x10 through to 0x1f are reserved, then this reserved area could be */
+/* specified as follows. */
+/*  typedef struct */
+/*  { */
+/*      uint32_t reg1;           offset 0x00 */
+/*      uint32_t reg2;           offset 0x04 */
+/*      uint32_t reg3;           offset 0x08 */
+/*      uint32_t reg4;           offset 0x0c */
+/*      REG32_RSVD(0x10, 0x20); */
+/*      uint32_t reg5;           offset 0x20 */
+/*      ... */
+/*  } EXAMPLE_REG_t; */
+#define REG8_RSVD(start, end)   uint8_t rsvd_##start[(end - start) / sizeof(uint8_t)]
+#define REG16_RSVD(start, end)  uint16_t rsvd_##start[(end - start) / sizeof(uint16_t)]
+#define REG32_RSVD(start, end)  uint32_t rsvd_##start[(end - start) / sizeof(uint32_t)]
+
+/* ---- Public Variable Externs ------------------------------------------ */
+/* ---- Public Function Prototypes --------------------------------------- */
+
+/* Note: When protecting multiple statements, the REG_LOCAL_IRQ_SAVE and */
+/* REG_LOCAL_IRQ_RESTORE must be enclosed in { } to allow the  */
+/* flags variable to be declared locally. */
+/* e.g. */
+/*    statement1; */
+/*    { */
+/*       REG_LOCAL_IRQ_SAVE; */
+/*       <multiple statements here> */
+/*       REG_LOCAL_IRQ_RESTORE; */
+/*    } */
+/*    statement2; */
+/*  */
+
+#if defined(__KERNEL__) && !defined(STANDALONE)
+#include <mach/hardware.h>
+#include <linux/interrupt.h>
+
+#define REG_LOCAL_IRQ_SAVE      HW_DECLARE_SPINLOCK(reg32) \
+	unsigned long flags; HW_IRQ_SAVE(reg32, flags)
+
+#define REG_LOCAL_IRQ_RESTORE   HW_IRQ_RESTORE(reg32, flags)
+
+#else
+
+#define REG_LOCAL_IRQ_SAVE
+#define REG_LOCAL_IRQ_RESTORE
+
+#endif
+
+static inline void reg32_modify_and(volatile uint32_t __iomem *reg, uint32_t value)
+{
+	REG_LOCAL_IRQ_SAVE;
+	__raw_writel(__raw_readl(reg) & value, reg);
+	REG_LOCAL_IRQ_RESTORE;
+}
+
+static inline void reg32_modify_or(volatile uint32_t __iomem *reg, uint32_t value)
+{
+	REG_LOCAL_IRQ_SAVE;
+	__raw_writel(__raw_readl(reg) | value, reg);
+	REG_LOCAL_IRQ_RESTORE;
+}
+
+static inline void reg32_modify_mask(volatile uint32_t __iomem *reg, uint32_t mask,
+				     uint32_t value)
+{
+	REG_LOCAL_IRQ_SAVE;
+	__raw_writel((__raw_readl(reg) & mask) | value, reg);
+	REG_LOCAL_IRQ_RESTORE;
+}
+
+static inline void reg32_write(volatile uint32_t __iomem *reg, uint32_t value)
+{
+	__raw_writel(value, reg);
+}
+
+#endif /* CSP_REG_H */
diff --git a/arch/arm/mach-bcmring/include/mach/csp/secHw_inline.h b/arch/arm/mach-bcmring/include/mach/csp/secHw_inline.h
index 9cd6a03..55d3cd4 100644
--- a/arch/arm/mach-bcmring/include/mach/csp/secHw_inline.h
+++ b/arch/arm/mach-bcmring/include/mach/csp/secHw_inline.h
@@ -34,7 +34,7 @@
 /****************************************************************************/
 static inline void secHw_setSecure(uint32_t mask	/*  mask of type secHw_BLK_MASK_XXXXXX */
     ) {
-	secHw_REGS_t *regp = (secHw_REGS_t *) MM_IO_BASE_TZPC;
+	secHw_REGS_t __iomem *regp = MM_IO_BASE_TZPC;
 
 	if (mask & 0x0000FFFF) {
 		regp->reg[secHw_IDX_LS].setSecure = mask & 0x0000FFFF;
@@ -53,13 +53,13 @@ static inline void secHw_setSecure(uint32_t mask	/*  mask of type secHw_BLK_MASK
 /****************************************************************************/
 static inline void secHw_setUnsecure(uint32_t mask	/*  mask of type secHw_BLK_MASK_XXXXXX */
     ) {
-	secHw_REGS_t *regp = (secHw_REGS_t *) MM_IO_BASE_TZPC;
+	secHw_REGS_t __iomem *regp = MM_IO_BASE_TZPC;
 
 	if (mask & 0x0000FFFF) {
-		regp->reg[secHw_IDX_LS].setUnsecure = mask & 0x0000FFFF;
+		writel(mask & 0x0000FFFF, &regp->reg[secHw_IDX_LS].setUnsecure);
 	}
 	if (mask & 0xFFFF0000) {
-		regp->reg[secHw_IDX_MS].setUnsecure = mask >> 16;
+		writel(mask >> 16, &regp->reg[secHw_IDX_MS].setUnsecure);
 	}
 }
 
@@ -71,7 +71,7 @@ static inline void secHw_setUnsecure(uint32_t mask	/*  mask of type secHw_BLK_MA
 /****************************************************************************/
 static inline uint32_t secHw_getStatus(void)
 {
-	secHw_REGS_t *regp = (secHw_REGS_t *) MM_IO_BASE_TZPC;
+	secHw_REGS_t __iomem *regp = MM_IO_BASE_TZPC;
 
 	return (regp->reg[1].status << 16) + regp->reg[0].status;
 }
diff --git a/arch/arm/mach-bcmring/include/mach/csp/tmrHw.h b/arch/arm/mach-bcmring/include/mach/csp/tmrHw.h
new file mode 100644
index 0000000..1cc882a
--- /dev/null
+++ b/arch/arm/mach-bcmring/include/mach/csp/tmrHw.h
@@ -0,0 +1,263 @@
+/*****************************************************************************
+* Copyright 2004 - 2008 Broadcom Corporation.  All rights reserved.
+*
+* Unless you and Broadcom execute a separate written software license
+* agreement governing use of this software, this software is licensed to you
+* under the terms of the GNU General Public License version 2, available at
+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
+*
+* Notwithstanding the above, under no circumstances may you combine this
+* software in any way with any other Broadcom software provided under a
+* license other than the GPL, without Broadcom's express prior written
+* consent.
+*****************************************************************************/
+
+/****************************************************************************/
+/**
+*  @file    tmrHw.h
+*
+*  @brief   API definitions for low level Timer driver
+*
+*/
+/****************************************************************************/
+#ifndef _TMRHW_H
+#define _TMRHW_H
+
+#include <linux/types.h>
+
+typedef uint32_t tmrHw_ID_t;	/* Timer ID */
+typedef uint32_t tmrHw_COUNT_t;	/* Timer count */
+typedef uint32_t tmrHw_INTERVAL_t;	/* Timer interval */
+typedef uint32_t tmrHw_RATE_t;	/* Timer event (count/interrupt) rate */
+
+typedef enum {
+	tmrHw_INTERRUPT_STATUS_SET,	/* Interrupted  */
+	tmrHw_INTERRUPT_STATUS_UNSET	/* No Interrupt */
+} tmrHw_INTERRUPT_STATUS_e;
+
+typedef enum {
+	tmrHw_CAPABILITY_CLOCK,	/* Clock speed in HHz */
+	tmrHw_CAPABILITY_RESOLUTION	/* Timer resolution in bits */
+} tmrHw_CAPABILITY_e;
+
+/****************************************************************************/
+/**
+*  @brief   Get timer capability
+*
+*  This function returns various capabilities/attributes of a timer
+*
+*  @return  Numeric capability
+*
+*/
+/****************************************************************************/
+uint32_t tmrHw_getTimerCapability(tmrHw_ID_t timerId,	/*  [ IN ] Timer Id */
+				  tmrHw_CAPABILITY_e capability	/*  [ IN ] Timer capability */
+);
+
+/****************************************************************************/
+/**
+*  @brief   Configures a periodic timer in terms of timer interrupt rate
+*
+*  This function initializes a periodic timer to generate specific number of
+*  timer interrupt per second
+*
+*  @return   On success: Effective timer frequency
+*            On failure: 0
+*
+*/
+/****************************************************************************/
+tmrHw_RATE_t tmrHw_setPeriodicTimerRate(tmrHw_ID_t timerId,	/*  [ IN ] Timer Id */
+					tmrHw_RATE_t rate	/*  [ IN ] Number of timer interrupt per second */
+);
+
+/****************************************************************************/
+/**
+*  @brief   Configures a periodic timer to generate timer interrupt after
+*           certain time interval
+*
+*  This function initializes a periodic timer to generate timer interrupt
+*  after every time interval in millisecond
+*
+*  @return   On success: Effective interval set in mili-second
+*            On failure: 0
+*
+*/
+/****************************************************************************/
+tmrHw_INTERVAL_t tmrHw_setPeriodicTimerInterval(tmrHw_ID_t timerId,	/*  [ IN ] Timer Id */
+						tmrHw_INTERVAL_t msec	/*  [ IN ] Interval in mili-second */
+);
+
+/****************************************************************************/
+/**
+*  @brief   Configures a periodic timer to generate timer interrupt just once
+*           after certain time interval
+*
+*  This function initializes a periodic timer to generate a single ticks after
+*  certain time interval in millisecond
+*
+*  @return   On success: Effective interval set in mili-second
+*            On failure: 0
+*
+*/
+/****************************************************************************/
+tmrHw_INTERVAL_t tmrHw_setOneshotTimerInterval(tmrHw_ID_t timerId,	/*  [ IN ] Timer Id */
+					       tmrHw_INTERVAL_t msec	/*  [ IN ] Interval in mili-second */
+);
+
+/****************************************************************************/
+/**
+*  @brief   Configures a timer to run as a free running timer
+*
+*  This function initializes a timer to run as a free running timer
+*
+*  @return   Timer resolution (count / sec)
+*
+*/
+/****************************************************************************/
+tmrHw_RATE_t tmrHw_setFreeRunningTimer(tmrHw_ID_t timerId,	/*  [ IN ] Timer Id */
+				       uint32_t divider	/*  [ IN ] Dividing the clock frequency */
+) __attribute__ ((section(".aramtext")));
+
+/****************************************************************************/
+/**
+*  @brief   Starts a timer
+*
+*  This function starts a preconfigured timer
+*
+*  @return  -1     - On Failure
+*            0     - On Success
+*/
+/****************************************************************************/
+int tmrHw_startTimer(tmrHw_ID_t timerId	/*  [ IN ] Timer id */
+) __attribute__ ((section(".aramtext")));
+
+/****************************************************************************/
+/**
+*  @brief   Stops a timer
+*
+*  This function stops a running timer
+*
+*  @return  -1     - On Failure
+*            0     - On Success
+*/
+/****************************************************************************/
+int tmrHw_stopTimer(tmrHw_ID_t timerId	/*  [ IN ] Timer id */
+);
+
+/****************************************************************************/
+/**
+*  @brief   Gets current timer count
+*
+*  This function returns the current timer value
+*
+*  @return  Current downcounting timer value
+*
+*/
+/****************************************************************************/
+tmrHw_COUNT_t tmrHw_GetCurrentCount(tmrHw_ID_t timerId	/*  [ IN ] Timer id */
+) __attribute__ ((section(".aramtext")));
+
+/****************************************************************************/
+/**
+*  @brief   Gets timer count rate
+*
+*  This function returns the number of counts per second
+*
+*  @return  Count rate
+*
+*/
+/****************************************************************************/
+tmrHw_RATE_t tmrHw_getCountRate(tmrHw_ID_t timerId	/*  [ IN ] Timer id */
+) __attribute__ ((section(".aramtext")));
+
+/****************************************************************************/
+/**
+*  @brief   Enables timer interrupt
+*
+*  This function enables the timer interrupt
+*
+*  @return   N/A
+*
+*/
+/****************************************************************************/
+void tmrHw_enableInterrupt(tmrHw_ID_t timerId	/*  [ IN ] Timer id */
+);
+
+/****************************************************************************/
+/**
+*  @brief   Disables timer interrupt
+*
+*  This function disable the timer interrupt
+*
+*  @return   N/A
+*/
+/****************************************************************************/
+void tmrHw_disableInterrupt(tmrHw_ID_t timerId	/*  [ IN ] Timer id */
+);
+
+/****************************************************************************/
+/**
+*  @brief   Clears the interrupt
+*
+*  This function clears the timer interrupt
+*
+*  @return   N/A
+*
+*  @note
+*     Must be called under the context of ISR
+*/
+/****************************************************************************/
+void tmrHw_clearInterrupt(tmrHw_ID_t timerId	/*  [ IN ] Timer id */
+);
+
+/****************************************************************************/
+/**
+*  @brief   Gets the interrupt status
+*
+*  This function returns timer interrupt status
+*
+*  @return   Interrupt status
+*/
+/****************************************************************************/
+tmrHw_INTERRUPT_STATUS_e tmrHw_getInterruptStatus(tmrHw_ID_t timerId	/*  [ IN ] Timer id */
+);
+
+/****************************************************************************/
+/**
+*  @brief   Indentifies a timer causing interrupt
+*
+*  This functions returns a timer causing interrupt
+*
+*  @return  0xFFFFFFFF   : No timer causing an interrupt
+*           ! 0xFFFFFFFF : timer causing an interrupt
+*  @note
+*     tmrHw_clearIntrrupt() must be called with a valid timer id after calling this function
+*/
+/****************************************************************************/
+tmrHw_ID_t tmrHw_getInterruptSource(void);
+
+/****************************************************************************/
+/**
+*  @brief   Displays specific timer registers
+*
+*
+*  @return  void
+*
+*/
+/****************************************************************************/
+void tmrHw_printDebugInfo(tmrHw_ID_t timerId,	/*  [ IN ] Timer id */
+			  int (*fpPrint) (const char *, ...)	/*  [ IN ] Print callback function */
+);
+
+/****************************************************************************/
+/**
+*  @brief   Use a timer to perform a busy wait delay for a number of usecs.
+*
+*  @return   N/A
+*/
+/****************************************************************************/
+void tmrHw_udelay(tmrHw_ID_t timerId,	/*  [ IN ] Timer id */
+		  unsigned long usecs	/*  [ IN ] usec to delay */
+) __attribute__ ((section(".aramtext")));
+
+#endif /* _TMRHW_H */
diff --git a/arch/arm/mach-bcmring/include/mach/dma.h b/arch/arm/mach-bcmring/include/mach/dma.h
index 7254378..13e0138 100644
--- a/arch/arm/mach-bcmring/include/mach/dma.h
+++ b/arch/arm/mach-bcmring/include/mach/dma.h
@@ -27,7 +27,7 @@
 
 #include <linux/kernel.h>
 #include <linux/semaphore.h>
-#include <csp/dmacHw.h>
+#include <mach/csp/dmacHw.h>
 #include <mach/timer.h>
 
 /* ---- Constants and Types ---------------------------------------------- */
diff --git a/arch/arm/mach-bcmring/include/mach/hardware.h b/arch/arm/mach-bcmring/include/mach/hardware.h
index 6ae20a6..a0c92b4 100644
--- a/arch/arm/mach-bcmring/include/mach/hardware.h
+++ b/arch/arm/mach-bcmring/include/mach/hardware.h
@@ -22,7 +22,7 @@
 #define __ASM_ARCH_HARDWARE_H
 
 #include <asm/sizes.h>
-#include <cfg_global.h>
+#include <mach/cfg_global.h>
 #include <mach/csp/mm_io.h>
 
 /* Hardware addresses of major areas.
diff --git a/arch/arm/mach-bcmring/include/mach/reg_nand.h b/arch/arm/mach-bcmring/include/mach/reg_nand.h
index 387376f..f8d51a8 100644
--- a/arch/arm/mach-bcmring/include/mach/reg_nand.h
+++ b/arch/arm/mach-bcmring/include/mach/reg_nand.h
@@ -30,7 +30,7 @@
 #define __ASM_ARCH_REG_NAND_H
 
 /* ---- Include Files ---------------------------------------------------- */
-#include <csp/reg.h>
+#include <mach/csp/reg.h>
 #include <mach/reg_umi.h>
 
 /* ---- Constants and Types ---------------------------------------------- */
diff --git a/arch/arm/mach-bcmring/include/mach/reg_umi.h b/arch/arm/mach-bcmring/include/mach/reg_umi.h
index 0992842..56dd9de 100644
--- a/arch/arm/mach-bcmring/include/mach/reg_umi.h
+++ b/arch/arm/mach-bcmring/include/mach/reg_umi.h
@@ -30,7 +30,7 @@
 #define __ASM_ARCH_REG_UMI_H
 
 /* ---- Include Files ---------------------------------------------------- */
-#include <csp/reg.h>
+#include <mach/csp/reg.h>
 #include <mach/csp/mm_io.h>
 
 /* ---- Constants and Types ---------------------------------------------- */
@@ -233,5 +233,5 @@
 #define REG_UMI_BCH_ERR_LOC_WORD              0x00000018
 /* location within a page (512 byte) */
 #define REG_UMI_BCH_ERR_LOC_PAGE              0x00001FE0
-#define REG_UMI_BCH_ERR_LOC_ADDR(index)     (__REG32(HW_UMI_BASE + 0x64 + (index / 2)*4) >> ((index % 2) * 16))
+#define REG_UMI_BCH_ERR_LOC_ADDR(index)     (readl(HW_UMI_BASE + 0x64 + (index / 2)*4) >> ((index % 2) * 16))
 #endif
diff --git a/arch/arm/mach-bcmring/mm.c b/arch/arm/mach-bcmring/mm.c
index 1adec78e..33824a8 100644
--- a/arch/arm/mach-bcmring/mm.c
+++ b/arch/arm/mach-bcmring/mm.c
@@ -20,12 +20,12 @@
 #include <mach/hardware.h>
 #include <mach/csp/mm_io.h>
 
-#define IO_DESC(va, sz) { .virtual = va, \
+#define IO_DESC(va, sz) { .virtual = (unsigned long)va, \
 	.pfn = __phys_to_pfn(HW_IO_VIRT_TO_PHYS(va)), \
 	.length = sz, \
 	.type = MT_DEVICE }
 
-#define MEM_DESC(va, sz) { .virtual = va, \
+#define MEM_DESC(va, sz) { .virtual = (unsigned long)va, \
 	.pfn = __phys_to_pfn(HW_IO_VIRT_TO_PHYS(va)), \
 	.length = sz, \
 	.type = MT_MEMORY }
diff --git a/arch/arm/mach-bcmring/timer.c b/arch/arm/mach-bcmring/timer.c
index af9c3d7..5941290 100644
--- a/arch/arm/mach-bcmring/timer.c
+++ b/arch/arm/mach-bcmring/timer.c
@@ -14,7 +14,7 @@
 
 #include <linux/types.h>
 #include <linux/module.h>
-#include <csp/tmrHw.h>
+#include <mach/csp/tmrHw.h>
 
 #include <mach/timer.h>
 /* The core.c file initializes timers 1 and 3 as a linux clocksource. */
diff --git a/arch/arm/mach-clps711x/Makefile b/arch/arm/mach-clps711x/Makefile
index f2f0256..5872b49 100644
--- a/arch/arm/mach-clps711x/Makefile
+++ b/arch/arm/mach-clps711x/Makefile
@@ -16,5 +16,3 @@ obj-$(CONFIG_ARCH_CLEP7312) += clep7312.o
 obj-$(CONFIG_ARCH_EDB7211)  += edb7211-arch.o edb7211-mm.o
 obj-$(CONFIG_ARCH_FORTUNET) += fortunet.o
 obj-$(CONFIG_ARCH_P720T)    += p720t.o
-leds-$(CONFIG_ARCH_P720T)   += p720t-leds.o
-obj-$(CONFIG_LEDS)          += $(leds-y)
diff --git a/arch/arm/mach-clps711x/autcpu12.c b/arch/arm/mach-clps711x/autcpu12.c
index 3fb79a1..3287191 100644
--- a/arch/arm/mach-clps711x/autcpu12.c
+++ b/arch/arm/mach-clps711x/autcpu12.c
@@ -23,6 +23,8 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
 
 #include <mach/hardware.h>
 #include <asm/sizes.h>
@@ -62,9 +64,26 @@ void __init autcpu12_map_io(void)
         iotable_init(autcpu12_io_desc, ARRAY_SIZE(autcpu12_io_desc));
 }
 
+static struct resource autcpu12_nvram_resource[] __initdata = {
+	DEFINE_RES_MEM_NAMED(AUTCPU12_PHYS_NVRAM, SZ_128K, "SRAM"),
+};
+
+static struct platform_device autcpu12_nvram_pdev __initdata = {
+	.name		= "autcpu12_nvram",
+	.id		= -1,
+	.resource	= autcpu12_nvram_resource,
+	.num_resources	= ARRAY_SIZE(autcpu12_nvram_resource),
+};
+
+static void __init autcpu12_init(void)
+{
+	platform_device_register(&autcpu12_nvram_pdev);
+}
+
 MACHINE_START(AUTCPU12, "autronix autcpu12")
 	/* Maintainer: Thomas Gleixner */
 	.atag_offset	= 0x20000,
+	.init_machine	= autcpu12_init,
 	.map_io		= autcpu12_map_io,
 	.init_irq	= clps711x_init_irq,
 	.timer		= &clps711x_timer,
diff --git a/arch/arm/mach-clps711x/common.c b/arch/arm/mach-clps711x/common.c
index f15293b..3a4af00 100644
--- a/arch/arm/mach-clps711x/common.c
+++ b/arch/arm/mach-clps711x/common.c
@@ -30,7 +30,6 @@
 #include <asm/sizes.h>
 #include <mach/hardware.h>
 #include <asm/irq.h>
-#include <asm/leds.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
 #include <asm/mach/map.h>
diff --git a/arch/arm/mach-clps711x/p720t-leds.c b/arch/arm/mach-clps711x/p720t-leds.c
deleted file mode 100644
index bbc449f..0000000
--- a/arch/arm/mach-clps711x/p720t-leds.c
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- *  linux/arch/arm/mach-clps711x/leds.c
- *
- *  Integrator LED control routines
- *
- *  Copyright (C) 2000 Deep Blue Solutions Ltd
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <asm/leds.h>
-#include <asm/mach-types.h>
-
-static void p720t_leds_event(led_event_t ledevt)
-{
-	unsigned long flags;
-	u32 pddr;
-
-	local_irq_save(flags);
-	switch(ledevt) {
-	case led_idle_start:
-		break;
-
-	case led_idle_end:
-		break;
-
-	case led_timer:
-		pddr = clps_readb(PDDR);
-		clps_writeb(pddr ^ 1, PDDR);
-		break;
-
-	default:
-		break;
-	}
-
-	local_irq_restore(flags);
-}
-
-static int __init leds_init(void)
-{
-	if (machine_is_p720t())
-		leds_event = p720t_leds_event;
-
-	return 0;
-}
-
-arch_initcall(leds_init);
diff --git a/arch/arm/mach-clps711x/p720t.c b/arch/arm/mach-clps711x/p720t.c
index f266d90..b752b58 100644
--- a/arch/arm/mach-clps711x/p720t.c
+++ b/arch/arm/mach-clps711x/p720t.c
@@ -23,6 +23,8 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/leds.h>
 
 #include <mach/hardware.h>
 #include <asm/pgtable.h>
@@ -34,6 +36,8 @@
 #include <asm/mach/map.h>
 #include <mach/syspld.h>
 
+#include <asm/hardware/clps7111.h>
+
 #include "common.h"
 
 /*
@@ -107,6 +111,64 @@ static void __init p720t_init_early(void)
 	}
 }
 
+/*
+ * LED controled by CPLD
+ */
+#if defined(CONFIG_NEW_LEDS) && defined(CONFIG_LEDS_CLASS)
+static void p720t_led_set(struct led_classdev *cdev,
+			      enum led_brightness b)
+{
+	u8 reg = clps_readb(PDDR);
+
+	if (b != LED_OFF)
+		reg |= 0x1;
+	else
+		reg &= ~0x1;
+
+	clps_writeb(reg, PDDR);
+}
+
+static enum led_brightness p720t_led_get(struct led_classdev *cdev)
+{
+	u8 reg = clps_readb(PDDR);
+
+	return (reg & 0x1) ? LED_FULL : LED_OFF;
+}
+
+static int __init p720t_leds_init(void)
+{
+
+	struct led_classdev *cdev;
+	int ret;
+
+	if (!machine_is_p720t())
+		return -ENODEV;
+
+	cdev = kzalloc(sizeof(*cdev), GFP_KERNEL);
+	if (!cdev)
+		return -ENOMEM;
+
+	cdev->name = "p720t:0";
+	cdev->brightness_set = p720t_led_set;
+	cdev->brightness_get = p720t_led_get;
+	cdev->default_trigger = "heartbeat";
+
+	ret = led_classdev_register(NULL, cdev);
+	if (ret	< 0) {
+		kfree(cdev);
+		return ret;
+	}
+
+	return 0;
+}
+
+/*
+ * Since we may have triggers on any subsystem, defer registration
+ * until after subsystem_init.
+ */
+fs_initcall(p720t_leds_init);
+#endif
+
 MACHINE_START(P720T, "ARM-Prospector720T")
 	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
 	.atag_offset	= 0x100,
diff --git a/arch/arm/mach-davinci/aemif.c b/arch/arm/mach-davinci/aemif.c
index 1ce70a9..f091a90 100644
--- a/arch/arm/mach-davinci/aemif.c
+++ b/arch/arm/mach-davinci/aemif.c
@@ -15,7 +15,7 @@
 #include <linux/module.h>
 #include <linux/time.h>
 
-#include <mach/aemif.h>
+#include <linux/platform_data/mtd-davinci-aemif.h>
 
 /* Timing value configuration */
 
diff --git a/arch/arm/mach-davinci/asp.h b/arch/arm/mach-davinci/asp.h
new file mode 100644
index 0000000..d9b2acd
--- /dev/null
+++ b/arch/arm/mach-davinci/asp.h
@@ -0,0 +1,49 @@
+/*
+ * TI DaVinci Audio definitions
+ */
+#ifndef __ASM_ARCH_DAVINCI_ASP_H
+#define __ASM_ARCH_DAVINCI_ASP_H
+
+/* Bases of dm644x and dm355 register banks */
+#define DAVINCI_ASP0_BASE	0x01E02000
+#define DAVINCI_ASP1_BASE	0x01E04000
+
+/* Bases of dm365 register banks */
+#define DAVINCI_DM365_ASP0_BASE	0x01D02000
+
+/* Bases of dm646x register banks */
+#define DAVINCI_DM646X_MCASP0_REG_BASE		0x01D01000
+#define DAVINCI_DM646X_MCASP1_REG_BASE		0x01D01800
+
+/* Bases of da850/da830 McASP0  register banks */
+#define DAVINCI_DA8XX_MCASP0_REG_BASE	0x01D00000
+
+/* Bases of da830 McASP1 register banks */
+#define DAVINCI_DA830_MCASP1_REG_BASE	0x01D04000
+
+/* EDMA channels of dm644x and dm355 */
+#define DAVINCI_DMA_ASP0_TX	2
+#define DAVINCI_DMA_ASP0_RX	3
+#define DAVINCI_DMA_ASP1_TX	8
+#define DAVINCI_DMA_ASP1_RX	9
+
+/* EDMA channels of dm646x */
+#define DAVINCI_DM646X_DMA_MCASP0_AXEVT0	6
+#define DAVINCI_DM646X_DMA_MCASP0_AREVT0	9
+#define DAVINCI_DM646X_DMA_MCASP1_AXEVT1	12
+
+/* EDMA channels of da850/da830 McASP0 */
+#define DAVINCI_DA8XX_DMA_MCASP0_AREVT	0
+#define DAVINCI_DA8XX_DMA_MCASP0_AXEVT	1
+
+/* EDMA channels of da830 McASP1 */
+#define DAVINCI_DA830_DMA_MCASP1_AREVT	2
+#define DAVINCI_DA830_DMA_MCASP1_AXEVT	3
+
+/* Interrupts */
+#define DAVINCI_ASP0_RX_INT	IRQ_MBRINT
+#define DAVINCI_ASP0_TX_INT	IRQ_MBXINT
+#define DAVINCI_ASP1_RX_INT	IRQ_MBRINT
+#define DAVINCI_ASP1_TX_INT	IRQ_MBXINT
+
+#endif /* __ASM_ARCH_DAVINCI_ASP_H */
diff --git a/arch/arm/mach-davinci/board-da830-evm.c b/arch/arm/mach-davinci/board-da830-evm.c
index 0031864..95b5e10 100644
--- a/arch/arm/mach-davinci/board-da830-evm.c
+++ b/arch/arm/mach-davinci/board-da830-evm.c
@@ -28,11 +28,11 @@
 
 #include <mach/cp_intc.h>
 #include <mach/mux.h>
-#include <mach/nand.h>
+#include <linux/platform_data/mtd-davinci.h>
 #include <mach/da8xx.h>
-#include <mach/usb.h>
-#include <mach/aemif.h>
-#include <mach/spi.h>
+#include <linux/platform_data/usb-davinci.h>
+#include <linux/platform_data/mtd-davinci-aemif.h>
+#include <linux/platform_data/spi-davinci.h>
 
 #define DA830_EVM_PHY_ID		""
 /*
diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c
index 0149fb4..1295e61 100644
--- a/arch/arm/mach-davinci/board-da850-evm.c
+++ b/arch/arm/mach-davinci/board-da850-evm.c
@@ -40,10 +40,10 @@
 
 #include <mach/cp_intc.h>
 #include <mach/da8xx.h>
-#include <mach/nand.h>
+#include <linux/platform_data/mtd-davinci.h>
 #include <mach/mux.h>
-#include <mach/aemif.h>
-#include <mach/spi.h>
+#include <linux/platform_data/mtd-davinci-aemif.h>
+#include <linux/platform_data/spi-davinci.h>
 
 #define DA850_EVM_PHY_ID		"davinci_mdio-0:00"
 #define DA850_LCD_PWR_PIN		GPIO_TO_PIN(2, 8)
diff --git a/arch/arm/mach-davinci/board-dm355-evm.c b/arch/arm/mach-davinci/board-dm355-evm.c
index 1c7b1f4..88ebea8 100644
--- a/arch/arm/mach-davinci/board-dm355-evm.c
+++ b/arch/arm/mach-davinci/board-dm355-evm.c
@@ -26,11 +26,11 @@
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
-#include <mach/i2c.h>
+#include <linux/platform_data/i2c-davinci.h>
 #include <mach/serial.h>
-#include <mach/nand.h>
-#include <mach/mmc.h>
-#include <mach/usb.h>
+#include <linux/platform_data/mtd-davinci.h>
+#include <linux/platform_data/mmc-davinci.h>
+#include <linux/platform_data/usb-davinci.h>
 
 #include "davinci.h"
 
diff --git a/arch/arm/mach-davinci/board-dm355-leopard.c b/arch/arm/mach-davinci/board-dm355-leopard.c
index 8e77032..2f88103 100644
--- a/arch/arm/mach-davinci/board-dm355-leopard.c
+++ b/arch/arm/mach-davinci/board-dm355-leopard.c
@@ -23,11 +23,11 @@
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
-#include <mach/i2c.h>
+#include <linux/platform_data/i2c-davinci.h>
 #include <mach/serial.h>
-#include <mach/nand.h>
-#include <mach/mmc.h>
-#include <mach/usb.h>
+#include <linux/platform_data/mtd-davinci.h>
+#include <linux/platform_data/mmc-davinci.h>
+#include <linux/platform_data/usb-davinci.h>
 
 #include "davinci.h"
 
diff --git a/arch/arm/mach-davinci/board-dm365-evm.c b/arch/arm/mach-davinci/board-dm365-evm.c
index 688a9c5..1b4a8ad 100644
--- a/arch/arm/mach-davinci/board-dm365-evm.c
+++ b/arch/arm/mach-davinci/board-dm365-evm.c
@@ -33,11 +33,11 @@
 
 #include <mach/mux.h>
 #include <mach/common.h>
-#include <mach/i2c.h>
+#include <linux/platform_data/i2c-davinci.h>
 #include <mach/serial.h>
-#include <mach/mmc.h>
-#include <mach/nand.h>
-#include <mach/keyscan.h>
+#include <linux/platform_data/mmc-davinci.h>
+#include <linux/platform_data/mtd-davinci.h>
+#include <linux/platform_data/keyscan-davinci.h>
 
 #include <media/tvp514x.h>
 
diff --git a/arch/arm/mach-davinci/board-dm644x-evm.c b/arch/arm/mach-davinci/board-dm644x-evm.c
index d34ed55..ca72fc4 100644
--- a/arch/arm/mach-davinci/board-dm644x-evm.c
+++ b/arch/arm/mach-davinci/board-dm644x-evm.c
@@ -31,13 +31,13 @@
 #include <asm/mach/arch.h>
 
 #include <mach/common.h>
-#include <mach/i2c.h>
+#include <linux/platform_data/i2c-davinci.h>
 #include <mach/serial.h>
 #include <mach/mux.h>
-#include <mach/nand.h>
-#include <mach/mmc.h>
-#include <mach/usb.h>
-#include <mach/aemif.h>
+#include <linux/platform_data/mtd-davinci.h>
+#include <linux/platform_data/mmc-davinci.h>
+#include <linux/platform_data/usb-davinci.h>
+#include <linux/platform_data/mtd-davinci-aemif.h>
 
 #include "davinci.h"
 
diff --git a/arch/arm/mach-davinci/board-dm646x-evm.c b/arch/arm/mach-davinci/board-dm646x-evm.c
index 958679a..9944367 100644
--- a/arch/arm/mach-davinci/board-dm646x-evm.c
+++ b/arch/arm/mach-davinci/board-dm646x-evm.c
@@ -38,11 +38,11 @@
 
 #include <mach/common.h>
 #include <mach/serial.h>
-#include <mach/i2c.h>
-#include <mach/nand.h>
+#include <linux/platform_data/i2c-davinci.h>
+#include <linux/platform_data/mtd-davinci.h>
 #include <mach/clock.h>
 #include <mach/cdce949.h>
-#include <mach/aemif.h>
+#include <linux/platform_data/mtd-davinci-aemif.h>
 
 #include "davinci.h"
 #include "clock.h"
diff --git a/arch/arm/mach-davinci/board-mityomapl138.c b/arch/arm/mach-davinci/board-mityomapl138.c
index beecde3..43e4a0d 100644
--- a/arch/arm/mach-davinci/board-mityomapl138.c
+++ b/arch/arm/mach-davinci/board-mityomapl138.c
@@ -26,9 +26,9 @@
 #include <mach/common.h>
 #include <mach/cp_intc.h>
 #include <mach/da8xx.h>
-#include <mach/nand.h>
+#include <linux/platform_data/mtd-davinci.h>
 #include <mach/mux.h>
-#include <mach/spi.h>
+#include <linux/platform_data/spi-davinci.h>
 
 #define MITYOMAPL138_PHY_ID		""
 
diff --git a/arch/arm/mach-davinci/board-neuros-osd2.c b/arch/arm/mach-davinci/board-neuros-osd2.c
index f6b9fc7..144bf31 100644
--- a/arch/arm/mach-davinci/board-neuros-osd2.c
+++ b/arch/arm/mach-davinci/board-neuros-osd2.c
@@ -31,12 +31,12 @@
 #include <asm/mach/arch.h>
 
 #include <mach/common.h>
-#include <mach/i2c.h>
+#include <linux/platform_data/i2c-davinci.h>
 #include <mach/serial.h>
 #include <mach/mux.h>
-#include <mach/nand.h>
-#include <mach/mmc.h>
-#include <mach/usb.h>
+#include <linux/platform_data/mtd-davinci.h>
+#include <linux/platform_data/mmc-davinci.h>
+#include <linux/platform_data/usb-davinci.h>
 
 #include "davinci.h"
 
diff --git a/arch/arm/mach-davinci/board-sffsdr.c b/arch/arm/mach-davinci/board-sffsdr.c
index 9078acf..6957787 100644
--- a/arch/arm/mach-davinci/board-sffsdr.c
+++ b/arch/arm/mach-davinci/board-sffsdr.c
@@ -36,10 +36,10 @@
 #include <asm/mach/flash.h>
 
 #include <mach/common.h>
-#include <mach/i2c.h>
+#include <linux/platform_data/i2c-davinci.h>
 #include <mach/serial.h>
 #include <mach/mux.h>
-#include <mach/usb.h>
+#include <linux/platform_data/usb-davinci.h>
 
 #include "davinci.h"
 
diff --git a/arch/arm/mach-davinci/board-tnetv107x-evm.c b/arch/arm/mach-davinci/board-tnetv107x-evm.c
index ac4e003..be30997 100644
--- a/arch/arm/mach-davinci/board-tnetv107x-evm.c
+++ b/arch/arm/mach-davinci/board-tnetv107x-evm.c
@@ -88,7 +88,7 @@ static struct davinci_mmc_config mmc_config = {
 	.version	= MMC_CTLR_VERSION_1,
 };
 
-static const short sdio1_pins[] __initdata = {
+static const short sdio1_pins[] __initconst = {
 	TNETV107X_SDIO1_CLK_1,		TNETV107X_SDIO1_CMD_1,
 	TNETV107X_SDIO1_DATA0_1,	TNETV107X_SDIO1_DATA1_1,
 	TNETV107X_SDIO1_DATA2_1,	TNETV107X_SDIO1_DATA3_1,
@@ -96,12 +96,12 @@ static const short sdio1_pins[] __initdata = {
 	-1
 };
 
-static const short uart1_pins[] __initdata = {
+static const short uart1_pins[] __initconst = {
 	TNETV107X_UART1_RD,		TNETV107X_UART1_TD,
 	-1
 };
 
-static const short ssp_pins[] __initdata = {
+static const short ssp_pins[] __initconst = {
 	TNETV107X_SSP0_0, TNETV107X_SSP0_1, TNETV107X_SSP0_2,
 	TNETV107X_SSP1_0, TNETV107X_SSP1_1, TNETV107X_SSP1_2,
 	TNETV107X_SSP1_3, -1
diff --git a/arch/arm/mach-davinci/da830.c b/arch/arm/mach-davinci/da830.c
index deee5c2..510648e 100644
--- a/arch/arm/mach-davinci/da830.c
+++ b/arch/arm/mach-davinci/da830.c
@@ -838,7 +838,7 @@ static const struct mux_config da830_pins[] = {
 #endif
 };
 
-const short da830_emif25_pins[] __initdata = {
+const short da830_emif25_pins[] __initconst = {
 	DA830_EMA_D_0, DA830_EMA_D_1, DA830_EMA_D_2, DA830_EMA_D_3,
 	DA830_EMA_D_4, DA830_EMA_D_5, DA830_EMA_D_6, DA830_EMA_D_7,
 	DA830_EMA_D_8, DA830_EMA_D_9, DA830_EMA_D_10, DA830_EMA_D_11,
@@ -853,19 +853,19 @@ const short da830_emif25_pins[] __initdata = {
 	-1
 };
 
-const short da830_spi0_pins[] __initdata = {
+const short da830_spi0_pins[] __initconst = {
 	DA830_SPI0_SOMI_0, DA830_SPI0_SIMO_0, DA830_SPI0_CLK, DA830_NSPI0_ENA,
 	DA830_NSPI0_SCS_0,
 	-1
 };
 
-const short da830_spi1_pins[] __initdata = {
+const short da830_spi1_pins[] __initconst = {
 	DA830_SPI1_SOMI_0, DA830_SPI1_SIMO_0, DA830_SPI1_CLK, DA830_NSPI1_ENA,
 	DA830_NSPI1_SCS_0,
 	-1
 };
 
-const short da830_mmc_sd_pins[] __initdata = {
+const short da830_mmc_sd_pins[] __initconst = {
 	DA830_MMCSD_DAT_0, DA830_MMCSD_DAT_1, DA830_MMCSD_DAT_2,
 	DA830_MMCSD_DAT_3, DA830_MMCSD_DAT_4, DA830_MMCSD_DAT_5,
 	DA830_MMCSD_DAT_6, DA830_MMCSD_DAT_7, DA830_MMCSD_CLK,
@@ -873,32 +873,32 @@ const short da830_mmc_sd_pins[] __initdata = {
 	-1
 };
 
-const short da830_uart0_pins[] __initdata = {
+const short da830_uart0_pins[] __initconst = {
 	DA830_NUART0_CTS, DA830_NUART0_RTS, DA830_UART0_RXD, DA830_UART0_TXD,
 	-1
 };
 
-const short da830_uart1_pins[] __initdata = {
+const short da830_uart1_pins[] __initconst = {
 	DA830_UART1_RXD, DA830_UART1_TXD,
 	-1
 };
 
-const short da830_uart2_pins[] __initdata = {
+const short da830_uart2_pins[] __initconst = {
 	DA830_UART2_RXD, DA830_UART2_TXD,
 	-1
 };
 
-const short da830_usb20_pins[] __initdata = {
+const short da830_usb20_pins[] __initconst = {
 	DA830_USB0_DRVVBUS, DA830_USB_REFCLKIN,
 	-1
 };
 
-const short da830_usb11_pins[] __initdata = {
+const short da830_usb11_pins[] __initconst = {
 	DA830_USB_REFCLKIN,
 	-1
 };
 
-const short da830_uhpi_pins[] __initdata = {
+const short da830_uhpi_pins[] __initconst = {
 	DA830_UHPI_HD_0, DA830_UHPI_HD_1, DA830_UHPI_HD_2, DA830_UHPI_HD_3,
 	DA830_UHPI_HD_4, DA830_UHPI_HD_5, DA830_UHPI_HD_6, DA830_UHPI_HD_7,
 	DA830_UHPI_HD_8, DA830_UHPI_HD_9, DA830_UHPI_HD_10, DA830_UHPI_HD_11,
@@ -909,14 +909,14 @@ const short da830_uhpi_pins[] __initdata = {
 	-1
 };
 
-const short da830_cpgmac_pins[] __initdata = {
+const short da830_cpgmac_pins[] __initconst = {
 	DA830_RMII_TXD_0, DA830_RMII_TXD_1, DA830_RMII_TXEN, DA830_RMII_CRS_DV,
 	DA830_RMII_RXD_0, DA830_RMII_RXD_1, DA830_RMII_RXER, DA830_MDIO_CLK,
 	DA830_MDIO_D,
 	-1
 };
 
-const short da830_emif3c_pins[] __initdata = {
+const short da830_emif3c_pins[] __initconst = {
 	DA830_EMB_SDCKE, DA830_EMB_CLK_GLUE, DA830_EMB_CLK, DA830_NEMB_CS_0,
 	DA830_NEMB_CAS, DA830_NEMB_RAS, DA830_NEMB_WE, DA830_EMB_BA_1,
 	DA830_EMB_BA_0, DA830_EMB_A_0, DA830_EMB_A_1, DA830_EMB_A_2,
@@ -935,7 +935,7 @@ const short da830_emif3c_pins[] __initdata = {
 	-1
 };
 
-const short da830_mcasp0_pins[] __initdata = {
+const short da830_mcasp0_pins[] __initconst = {
 	DA830_AHCLKX0, DA830_ACLKX0, DA830_AFSX0,
 	DA830_AHCLKR0, DA830_ACLKR0, DA830_AFSR0, DA830_AMUTE0,
 	DA830_AXR0_0, DA830_AXR0_1, DA830_AXR0_2, DA830_AXR0_3,
@@ -945,7 +945,7 @@ const short da830_mcasp0_pins[] __initdata = {
 	-1
 };
 
-const short da830_mcasp1_pins[] __initdata = {
+const short da830_mcasp1_pins[] __initconst = {
 	DA830_AHCLKX1, DA830_ACLKX1, DA830_AFSX1,
 	DA830_AHCLKR1, DA830_ACLKR1, DA830_AFSR1, DA830_AMUTE1,
 	DA830_AXR1_0, DA830_AXR1_1, DA830_AXR1_2, DA830_AXR1_3,
@@ -954,24 +954,24 @@ const short da830_mcasp1_pins[] __initdata = {
 	-1
 };
 
-const short da830_mcasp2_pins[] __initdata = {
+const short da830_mcasp2_pins[] __initconst = {
 	DA830_AHCLKX2, DA830_ACLKX2, DA830_AFSX2,
 	DA830_AHCLKR2, DA830_ACLKR2, DA830_AFSR2, DA830_AMUTE2,
 	DA830_AXR2_0, DA830_AXR2_1, DA830_AXR2_2, DA830_AXR2_3,
 	-1
 };
 
-const short da830_i2c0_pins[] __initdata = {
+const short da830_i2c0_pins[] __initconst = {
 	DA830_I2C0_SDA, DA830_I2C0_SCL,
 	-1
 };
 
-const short da830_i2c1_pins[] __initdata = {
+const short da830_i2c1_pins[] __initconst = {
 	DA830_I2C1_SCL, DA830_I2C1_SDA,
 	-1
 };
 
-const short da830_lcdcntl_pins[] __initdata = {
+const short da830_lcdcntl_pins[] __initconst = {
 	DA830_LCD_D_0, DA830_LCD_D_1, DA830_LCD_D_2, DA830_LCD_D_3,
 	DA830_LCD_D_4, DA830_LCD_D_5, DA830_LCD_D_6, DA830_LCD_D_7,
 	DA830_LCD_D_8, DA830_LCD_D_9, DA830_LCD_D_10, DA830_LCD_D_11,
@@ -981,34 +981,34 @@ const short da830_lcdcntl_pins[] __initdata = {
 	-1
 };
 
-const short da830_pwm_pins[] __initdata = {
+const short da830_pwm_pins[] __initconst = {
 	DA830_ECAP0_APWM0, DA830_ECAP1_APWM1, DA830_EPWM0B, DA830_EPWM0A,
 	DA830_EPWMSYNCI, DA830_EPWMSYNC0, DA830_ECAP2_APWM2, DA830_EHRPWMGLUETZ,
 	DA830_EPWM2B, DA830_EPWM2A, DA830_EPWM1B, DA830_EPWM1A,
 	-1
 };
 
-const short da830_ecap0_pins[] __initdata = {
+const short da830_ecap0_pins[] __initconst = {
 	DA830_ECAP0_APWM0,
 	-1
 };
 
-const short da830_ecap1_pins[] __initdata = {
+const short da830_ecap1_pins[] __initconst = {
 	DA830_ECAP1_APWM1,
 	-1
 };
 
-const short da830_ecap2_pins[] __initdata = {
+const short da830_ecap2_pins[] __initconst = {
 	DA830_ECAP2_APWM2,
 	-1
 };
 
-const short da830_eqep0_pins[] __initdata = {
+const short da830_eqep0_pins[] __initconst = {
 	DA830_EQEP0I, DA830_EQEP0S, DA830_EQEP0A, DA830_EQEP0B,
 	-1
 };
 
-const short da830_eqep1_pins[] __initdata = {
+const short da830_eqep1_pins[] __initconst = {
 	DA830_EQEP1I, DA830_EQEP1S, DA830_EQEP1A, DA830_EQEP1B,
 	-1
 };
diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c
index b44dc84..6676dee 100644
--- a/arch/arm/mach-davinci/da850.c
+++ b/arch/arm/mach-davinci/da850.c
@@ -576,17 +576,17 @@ static const struct mux_config da850_pins[] = {
 #endif
 };
 
-const short da850_i2c0_pins[] __initdata = {
+const short da850_i2c0_pins[] __initconst = {
 	DA850_I2C0_SDA, DA850_I2C0_SCL,
 	-1
 };
 
-const short da850_i2c1_pins[] __initdata = {
+const short da850_i2c1_pins[] __initconst = {
 	DA850_I2C1_SCL, DA850_I2C1_SDA,
 	-1
 };
 
-const short da850_lcdcntl_pins[] __initdata = {
+const short da850_lcdcntl_pins[] __initconst = {
 	DA850_LCD_D_0, DA850_LCD_D_1, DA850_LCD_D_2, DA850_LCD_D_3,
 	DA850_LCD_D_4, DA850_LCD_D_5, DA850_LCD_D_6, DA850_LCD_D_7,
 	DA850_LCD_D_8, DA850_LCD_D_9, DA850_LCD_D_10, DA850_LCD_D_11,
diff --git a/arch/arm/mach-davinci/davinci.h b/arch/arm/mach-davinci/davinci.h
index 8db0fc6..acb545a 100644
--- a/arch/arm/mach-davinci/davinci.h
+++ b/arch/arm/mach-davinci/davinci.h
@@ -22,10 +22,11 @@
 #include <linux/davinci_emac.h>
 #include <linux/platform_device.h>
 #include <linux/spi/spi.h>
+#include <linux/platform_data/davinci_asp.h>
 
-#include <mach/asp.h>
-#include <mach/keyscan.h>
+#include <linux/platform_data/keyscan-davinci.h>
 #include <mach/hardware.h>
+#include <mach/edma.h>
 
 #include <media/davinci/vpfe_capture.h>
 #include <media/davinci/vpif_types.h>
diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c
index 783eab6..bd2f72b 100644
--- a/arch/arm/mach-davinci/devices-da8xx.c
+++ b/arch/arm/mach-davinci/devices-da8xx.c
@@ -24,6 +24,7 @@
 #include <mach/cpuidle.h>
 
 #include "clock.h"
+#include "asp.h"
 
 #define DA8XX_TPCC_BASE			0x01c00000
 #define DA8XX_TPTC0_BASE		0x01c08000
@@ -505,15 +506,8 @@ static struct platform_device da850_mcasp_device = {
 	.resource	= da850_mcasp_resources,
 };
 
-static struct platform_device davinci_pcm_device = {
-	.name	= "davinci-pcm-audio",
-	.id	= -1,
-};
-
 void __init da8xx_register_mcasp(int id, struct snd_platform_data *pdata)
 {
-	platform_device_register(&davinci_pcm_device);
-
 	/* DA830/OMAP-L137 has 3 instances of McASP */
 	if (cpu_is_davinci_da830() && id == 1) {
 		da830_mcasp1_device.dev.platform_data = pdata;
diff --git a/arch/arm/mach-davinci/devices.c b/arch/arm/mach-davinci/devices.c
index d2f96662..4c48a36 100644
--- a/arch/arm/mach-davinci/devices.c
+++ b/arch/arm/mach-davinci/devices.c
@@ -15,12 +15,12 @@
 #include <linux/io.h>
 
 #include <mach/hardware.h>
-#include <mach/i2c.h>
+#include <linux/platform_data/i2c-davinci.h>
 #include <mach/irqs.h>
 #include <mach/cputype.h>
 #include <mach/mux.h>
 #include <mach/edma.h>
-#include <mach/mmc.h>
+#include <linux/platform_data/mmc-davinci.h>
 #include <mach/time.h>
 
 #include "davinci.h"
@@ -313,16 +313,6 @@ static void davinci_init_wdt(void)
 
 /*-------------------------------------------------------------------------*/
 
-static struct platform_device davinci_pcm_device = {
-	.name		= "davinci-pcm-audio",
-	.id		= -1,
-};
-
-static void davinci_init_pcm(void)
-{
-	platform_device_register(&davinci_pcm_device);
-}
-
 /*-------------------------------------------------------------------------*/
 
 struct davinci_timer_instance davinci_timer_instance[2] = {
@@ -345,7 +335,6 @@ static int __init davinci_init_devices(void)
 	/* please keep these calls, and their implementations above,
 	 * in alphabetical order so they're easier to sort through.
 	 */
-	davinci_init_pcm();
 	davinci_init_wdt();
 
 	return 0;
diff --git a/arch/arm/mach-davinci/dm355.c b/arch/arm/mach-davinci/dm355.c
index 678cd99..a255434 100644
--- a/arch/arm/mach-davinci/dm355.c
+++ b/arch/arm/mach-davinci/dm355.c
@@ -26,13 +26,13 @@
 #include <mach/time.h>
 #include <mach/serial.h>
 #include <mach/common.h>
-#include <mach/asp.h>
-#include <mach/spi.h>
+#include <linux/platform_data/spi-davinci.h>
 #include <mach/gpio-davinci.h>
 
 #include "davinci.h"
 #include "clock.h"
 #include "mux.h"
+#include "asp.h"
 
 #define DM355_UART2_BASE	(IO_PHYS + 0x206000)
 
diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c
index a50d49de..b680c83 100644
--- a/arch/arm/mach-davinci/dm365.c
+++ b/arch/arm/mach-davinci/dm365.c
@@ -29,14 +29,14 @@
 #include <mach/time.h>
 #include <mach/serial.h>
 #include <mach/common.h>
-#include <mach/asp.h>
-#include <mach/keyscan.h>
-#include <mach/spi.h>
+#include <linux/platform_data/keyscan-davinci.h>
+#include <linux/platform_data/spi-davinci.h>
 #include <mach/gpio-davinci.h>
 
 #include "davinci.h"
 #include "clock.h"
 #include "mux.h"
+#include "asp.h"
 
 #define DM365_REF_FREQ		24000000	/* 24 MHz on the DM365 EVM */
 
diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c
index c8b8666..0755d46 100644
--- a/arch/arm/mach-davinci/dm644x.c
+++ b/arch/arm/mach-davinci/dm644x.c
@@ -23,12 +23,12 @@
 #include <mach/time.h>
 #include <mach/serial.h>
 #include <mach/common.h>
-#include <mach/asp.h>
 #include <mach/gpio-davinci.h>
 
 #include "davinci.h"
 #include "clock.h"
 #include "mux.h"
+#include "asp.h"
 
 /*
  * Device specific clocks
diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c
index 9eb87c1..97c0f8e 100644
--- a/arch/arm/mach-davinci/dm646x.c
+++ b/arch/arm/mach-davinci/dm646x.c
@@ -24,12 +24,12 @@
 #include <mach/time.h>
 #include <mach/serial.h>
 #include <mach/common.h>
-#include <mach/asp.h>
 #include <mach/gpio-davinci.h>
 
 #include "davinci.h"
 #include "clock.h"
 #include "mux.h"
+#include "asp.h"
 
 #define DAVINCI_VPIF_BASE       (0x01C12000)
 
diff --git a/arch/arm/mach-davinci/include/mach/aemif.h b/arch/arm/mach-davinci/include/mach/aemif.h
deleted file mode 100644
index 05b2934..0000000
--- a/arch/arm/mach-davinci/include/mach/aemif.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * TI DaVinci AEMIF support
- *
- * Copyright 2010 (C) Texas Instruments, Inc. http://www.ti.com/
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2. This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
- */
-#ifndef _MACH_DAVINCI_AEMIF_H
-#define _MACH_DAVINCI_AEMIF_H
-
-#define NRCSR_OFFSET		0x00
-#define AWCCR_OFFSET		0x04
-#define A1CR_OFFSET		0x10
-
-#define ACR_ASIZE_MASK		0x3
-#define ACR_EW_MASK		BIT(30)
-#define ACR_SS_MASK		BIT(31)
-
-/* All timings in nanoseconds */
-struct davinci_aemif_timing {
-	u8	wsetup;
-	u8	wstrobe;
-	u8	whold;
-
-	u8	rsetup;
-	u8	rstrobe;
-	u8	rhold;
-
-	u8	ta;
-};
-
-int davinci_aemif_setup_timing(struct davinci_aemif_timing *t,
-					void __iomem *base, unsigned cs);
-#endif
diff --git a/arch/arm/mach-davinci/include/mach/asp.h b/arch/arm/mach-davinci/include/mach/asp.h
deleted file mode 100644
index 9aa2409..0000000
--- a/arch/arm/mach-davinci/include/mach/asp.h
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * <mach/asp.h> - DaVinci Audio Serial Port support
- */
-#ifndef __ASM_ARCH_DAVINCI_ASP_H
-#define __ASM_ARCH_DAVINCI_ASP_H
-
-#include <mach/irqs.h>
-#include <mach/edma.h>
-
-/* Bases of dm644x and dm355 register banks */
-#define DAVINCI_ASP0_BASE	0x01E02000
-#define DAVINCI_ASP1_BASE	0x01E04000
-
-/* Bases of dm365 register banks */
-#define DAVINCI_DM365_ASP0_BASE	0x01D02000
-
-/* Bases of dm646x register banks */
-#define	DAVINCI_DM646X_MCASP0_REG_BASE		0x01D01000
-#define DAVINCI_DM646X_MCASP1_REG_BASE		0x01D01800
-
-/* Bases of da850/da830 McASP0  register banks */
-#define DAVINCI_DA8XX_MCASP0_REG_BASE	0x01D00000
-
-/* Bases of da830 McASP1 register banks */
-#define DAVINCI_DA830_MCASP1_REG_BASE	0x01D04000
-
-/* EDMA channels of dm644x and dm355 */
-#define DAVINCI_DMA_ASP0_TX	2
-#define DAVINCI_DMA_ASP0_RX	3
-#define DAVINCI_DMA_ASP1_TX	8
-#define DAVINCI_DMA_ASP1_RX	9
-
-/* EDMA channels of dm646x */
-#define	DAVINCI_DM646X_DMA_MCASP0_AXEVT0	6
-#define	DAVINCI_DM646X_DMA_MCASP0_AREVT0	9
-#define	DAVINCI_DM646X_DMA_MCASP1_AXEVT1	12
-
-/* EDMA channels of da850/da830 McASP0 */
-#define	DAVINCI_DA8XX_DMA_MCASP0_AREVT	0
-#define	DAVINCI_DA8XX_DMA_MCASP0_AXEVT	1
-
-/* EDMA channels of da830 McASP1 */
-#define	DAVINCI_DA830_DMA_MCASP1_AREVT	2
-#define	DAVINCI_DA830_DMA_MCASP1_AXEVT	3
-
-/* Interrupts */
-#define DAVINCI_ASP0_RX_INT	IRQ_MBRINT
-#define DAVINCI_ASP0_TX_INT	IRQ_MBXINT
-#define DAVINCI_ASP1_RX_INT	IRQ_MBRINT
-#define DAVINCI_ASP1_TX_INT	IRQ_MBXINT
-
-struct snd_platform_data {
-	u32 tx_dma_offset;
-	u32 rx_dma_offset;
-	enum dma_event_q asp_chan_q;	/* event queue number for ASP channel */
-	enum dma_event_q ram_chan_q;	/* event queue number for RAM channel */
-	unsigned int codec_fmt;
-	/*
-	 * Allowing this is more efficient and eliminates left and right swaps
-	 * caused by underruns, but will swap the left and right channels
-	 * when compared to previous behavior.
-	 */
-	unsigned enable_channel_combine:1;
-	unsigned sram_size_playback;
-	unsigned sram_size_capture;
-
-	/*
-	 * If McBSP peripheral gets the clock from an external pin,
-	 * there are three chooses, that are MCBSP_CLKX, MCBSP_CLKR
-	 * and MCBSP_CLKS.
-	 * Depending on different hardware connections it is possible
-	 * to use this setting to change the behaviour of McBSP
-	 * driver. The dm365_clk_input_pin enum is available for dm365
-	 */
-	int clk_input_pin;
-
-	/*
-	 * This flag works when both clock and FS are outputs for the cpu
-	 * and makes clock more accurate (FS is not symmetrical and the
-	 * clock is very fast.
-	 * The clock becoming faster is named
-	 * i2s continuous serial clock (I2S_SCK) and it is an externally
-	 * visible bit clock.
-	 *
-	 * first line : WordSelect
-	 * second line : ContinuousSerialClock
-	 * third line: SerialData
-	 *
-	 * SYMMETRICAL APPROACH:
-	 *   _______________________          LEFT
-	 * _|         RIGHT         |______________________|
-	 *     _   _         _   _   _   _         _   _
-	 *   _| |_| |_ x16 _| |_| |_| |_| |_ x16 _| |_| |_
-	 *     _   _         _   _   _   _         _   _
-	 *   _/ \_/ \_ ... _/ \_/ \_/ \_/ \_ ... _/ \_/ \_
-	 *    \_/ \_/       \_/ \_/ \_/ \_/       \_/ \_/
-	 *
-	 * ACCURATE CLOCK APPROACH:
-	 *   ______________          LEFT
-	 * _|     RIGHT    |_______________________________|
-	 *     _         _   _         _   _   _   _   _   _
-	 *   _| |_ x16 _| |_| |_ x16 _| |_| |_| |_| |_| |_| |
-	 *     _         _   _          _      dummy cycles
-	 *   _/ \_ ... _/ \_/ \_  ... _/ \__________________
-	 *    \_/       \_/ \_/        \_/
-	 *
-	 */
-	bool i2s_accurate_sck;
-
-	/* McASP specific fields */
-	int tdm_slots;
-	u8 op_mode;
-	u8 num_serializer;
-	u8 *serial_dir;
-	u8 version;
-	u8 txnumevt;
-	u8 rxnumevt;
-};
-
-enum {
-	MCASP_VERSION_1 = 0,	/* DM646x */
-	MCASP_VERSION_2,	/* DA8xx/OMAPL1x */
-};
-
-enum dm365_clk_input_pin {
-	MCBSP_CLKR = 0,		/* DM365 */
-	MCBSP_CLKS,
-};
-
-#define INACTIVE_MODE	0
-#define TX_MODE		1
-#define RX_MODE		2
-
-#define DAVINCI_MCASP_IIS_MODE	0
-#define DAVINCI_MCASP_DIT_MODE	1
-
-#endif /* __ASM_ARCH_DAVINCI_ASP_H */
diff --git a/arch/arm/mach-davinci/include/mach/da8xx.h b/arch/arm/mach-davinci/include/mach/da8xx.h
index a2f1f27..c9ee723 100644
--- a/arch/arm/mach-davinci/include/mach/da8xx.h
+++ b/arch/arm/mach-davinci/include/mach/da8xx.h
@@ -16,15 +16,15 @@
 #include <linux/platform_device.h>
 #include <linux/davinci_emac.h>
 #include <linux/spi/spi.h>
+#include <linux/platform_data/davinci_asp.h>
 
 #include <mach/serial.h>
 #include <mach/edma.h>
-#include <mach/i2c.h>
-#include <mach/asp.h>
-#include <mach/mmc.h>
-#include <mach/usb.h>
 #include <mach/pm.h>
-#include <mach/spi.h>
+#include <linux/platform_data/i2c-davinci.h>
+#include <linux/platform_data/mmc-davinci.h>
+#include <linux/platform_data/usb-davinci.h>
+#include <linux/platform_data/spi-davinci.h>
 
 extern void __iomem *da8xx_syscfg0_base;
 extern void __iomem *da8xx_syscfg1_base;
diff --git a/arch/arm/mach-davinci/include/mach/i2c.h b/arch/arm/mach-davinci/include/mach/i2c.h
deleted file mode 100644
index 2312d19..0000000
--- a/arch/arm/mach-davinci/include/mach/i2c.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * DaVinci I2C controller platform_device info
- *
- * Author: Vladimir Barinov, MontaVista Software, Inc. <source@mvista.com>
- *
- * 2007 (c) MontaVista Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
-*/
-
-#ifndef __ASM_ARCH_I2C_H
-#define __ASM_ARCH_I2C_H
-
-/* All frequencies are expressed in kHz */
-struct davinci_i2c_platform_data {
-	unsigned int	bus_freq;	/* standard bus frequency (kHz) */
-	unsigned int	bus_delay;	/* post-transaction delay (usec) */
-	unsigned int    sda_pin;        /* GPIO pin ID to use for SDA */
-	unsigned int    scl_pin;        /* GPIO pin ID to use for SCL */
-};
-
-/* for board setup code */
-void davinci_init_i2c(struct davinci_i2c_platform_data *);
-
-#endif /* __ASM_ARCH_I2C_H */
diff --git a/arch/arm/mach-davinci/include/mach/keyscan.h b/arch/arm/mach-davinci/include/mach/keyscan.h
deleted file mode 100644
index 7a560e0..0000000
--- a/arch/arm/mach-davinci/include/mach/keyscan.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2009 Texas Instruments, Inc
- *
- * Author: Miguel Aguilar <miguel.aguilar@ridgerun.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public 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 DAVINCI_KEYSCAN_H
-#define DAVINCI_KEYSCAN_H
-
-#include <linux/io.h>
-
-enum davinci_matrix_types {
-	DAVINCI_KEYSCAN_MATRIX_4X4,
-	DAVINCI_KEYSCAN_MATRIX_5X3,
-};
-
-struct davinci_ks_platform_data {
-	int		(*device_enable)(struct device *dev);
-	unsigned short	*keymap;
-	u32		keymapsize;
-	u8		rep:1;
-	u8		strobe;
-	u8		interval;
-	u8		matrix_type;
-};
-
-#endif
-
diff --git a/arch/arm/mach-davinci/include/mach/mmc.h b/arch/arm/mach-davinci/include/mach/mmc.h
deleted file mode 100644
index 5ba6b22..0000000
--- a/arch/arm/mach-davinci/include/mach/mmc.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- *  Board-specific MMC configuration
- */
-
-#ifndef _DAVINCI_MMC_H
-#define _DAVINCI_MMC_H
-
-#include <linux/types.h>
-#include <linux/mmc/host.h>
-
-struct davinci_mmc_config {
-	/* get_cd()/get_wp() may sleep */
-	int	(*get_cd)(int module);
-	int	(*get_ro)(int module);
-
-	void	(*set_power)(int module, bool on);
-
-	/* wires == 0 is equivalent to wires == 4 (4-bit parallel) */
-	u8	wires;
-
-	u32     max_freq;
-
-	/* any additional host capabilities: OR'd in to mmc->f_caps */
-	u32     caps;
-
-	/* Version of the MMC/SD controller */
-	u8	version;
-
-	/* Number of sg segments */
-	u8	nr_sg;
-};
-void davinci_setup_mmc(int module, struct davinci_mmc_config *config);
-
-enum {
-	MMC_CTLR_VERSION_1 = 0,	/* DM644x and DM355 */
-	MMC_CTLR_VERSION_2,	/* DA830 */
-};
-
-#endif
diff --git a/arch/arm/mach-davinci/include/mach/nand.h b/arch/arm/mach-davinci/include/mach/nand.h
deleted file mode 100644
index 1cf555a..0000000
--- a/arch/arm/mach-davinci/include/mach/nand.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * mach-davinci/nand.h
- *
- * Copyright © 2006 Texas Instruments.
- *
- * Ported to 2.6.23 Copyright © 2008 by
- *   Sander Huijsen <Shuijsen@optelecom-nkf.com>
- *   Troy Kisky <troy.kisky@boundarydevices.com>
- *   Dirk Behme <Dirk.Behme@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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef __ARCH_ARM_DAVINCI_NAND_H
-#define __ARCH_ARM_DAVINCI_NAND_H
-
-#include <linux/mtd/nand.h>
-
-#define NANDFCR_OFFSET		0x60
-#define NANDFSR_OFFSET		0x64
-#define NANDF1ECC_OFFSET	0x70
-
-/* 4-bit ECC syndrome registers */
-#define NAND_4BIT_ECC_LOAD_OFFSET	0xbc
-#define NAND_4BIT_ECC1_OFFSET		0xc0
-#define NAND_4BIT_ECC2_OFFSET		0xc4
-#define NAND_4BIT_ECC3_OFFSET		0xc8
-#define NAND_4BIT_ECC4_OFFSET		0xcc
-#define NAND_ERR_ADD1_OFFSET		0xd0
-#define NAND_ERR_ADD2_OFFSET		0xd4
-#define NAND_ERR_ERRVAL1_OFFSET		0xd8
-#define NAND_ERR_ERRVAL2_OFFSET		0xdc
-
-/* NOTE:  boards don't need to use these address bits
- * for ALE/CLE unless they support booting from NAND.
- * They're used unless platform data overrides them.
- */
-#define	MASK_ALE		0x08
-#define	MASK_CLE		0x10
-
-struct davinci_nand_pdata {		/* platform_data */
-	uint32_t		mask_ale;
-	uint32_t		mask_cle;
-
-	/* for packages using two chipselects */
-	uint32_t		mask_chipsel;
-
-	/* board's default static partition info */
-	struct mtd_partition	*parts;
-	unsigned		nr_parts;
-
-	/* none  == NAND_ECC_NONE (strongly *not* advised!!)
-	 * soft  == NAND_ECC_SOFT
-	 * else  == NAND_ECC_HW, according to ecc_bits
-	 *
-	 * All DaVinci-family chips support 1-bit hardware ECC.
-	 * Newer ones also support 4-bit ECC, but are awkward
-	 * using it with large page chips.
-	 */
-	nand_ecc_modes_t	ecc_mode;
-	u8			ecc_bits;
-
-	/* e.g. NAND_BUSWIDTH_16 */
-	unsigned		options;
-	/* e.g. NAND_BBT_USE_FLASH */
-	unsigned		bbt_options;
-
-	/* Main and mirror bbt descriptor overrides */
-	struct nand_bbt_descr	*bbt_td;
-	struct nand_bbt_descr	*bbt_md;
-
-	/* Access timings */
-	struct davinci_aemif_timing	*timing;
-};
-
-#endif	/* __ARCH_ARM_DAVINCI_NAND_H */
diff --git a/arch/arm/mach-davinci/include/mach/spi.h b/arch/arm/mach-davinci/include/mach/spi.h
deleted file mode 100644
index 7af305b..0000000
--- a/arch/arm/mach-davinci/include/mach/spi.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright 2009 Texas Instruments.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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 __ARCH_ARM_DAVINCI_SPI_H
-#define __ARCH_ARM_DAVINCI_SPI_H
-
-#include <mach/edma.h>
-
-#define SPI_INTERN_CS	0xFF
-
-enum {
-	SPI_VERSION_1, /* For DM355/DM365/DM6467 */
-	SPI_VERSION_2, /* For DA8xx */
-};
-
-/**
- * davinci_spi_platform_data - Platform data for SPI master device on DaVinci
- *
- * @version:	version of the SPI IP. Different DaVinci devices have slightly
- *		varying versions of the same IP.
- * @num_chipselect: number of chipselects supported by this SPI master
- * @intr_line:	interrupt line used to connect the SPI IP to the ARM interrupt
- *		controller withn the SoC. Possible values are 0 and 1.
- * @chip_sel:	list of GPIOs which can act as chip-selects for the SPI.
- *		SPI_INTERN_CS denotes internal SPI chip-select. Not necessary
- *		to populate if all chip-selects are internal.
- * @cshold_bug:	set this to true if the SPI controller on your chip requires
- *		a write to CSHOLD bit in between transfers (like in DM355).
- * @dma_event_q: DMA event queue to use if SPI_IO_TYPE_DMA is used for any
- *		device on the bus.
- */
-struct davinci_spi_platform_data {
-	u8			version;
-	u8			num_chipselect;
-	u8			intr_line;
-	u8			*chip_sel;
-	bool			cshold_bug;
-	enum dma_event_q	dma_event_q;
-};
-
-/**
- * davinci_spi_config - Per-chip-select configuration for SPI slave devices
- *
- * @wdelay:	amount of delay between transmissions. Measured in number of
- *		SPI module clocks.
- * @odd_parity:	polarity of parity flag at the end of transmit data stream.
- *		0 - odd parity, 1 - even parity.
- * @parity_enable: enable transmission of parity at end of each transmit
- *		data stream.
- * @io_type:	type of IO transfer. Choose between polled, interrupt and DMA.
- * @timer_disable: disable chip-select timers (setup and hold)
- * @c2tdelay:	chip-select setup time. Measured in number of SPI module clocks.
- * @t2cdelay:	chip-select hold time. Measured in number of SPI module clocks.
- * @t2edelay:	transmit data finished to SPI ENAn pin inactive time. Measured
- *		in number of SPI clocks.
- * @c2edelay:	chip-select active to SPI ENAn signal active time. Measured in
- *		number of SPI clocks.
- */
-struct davinci_spi_config {
-	u8	wdelay;
-	u8	odd_parity;
-	u8	parity_enable;
-#define SPI_IO_TYPE_INTR	0
-#define SPI_IO_TYPE_POLL	1
-#define SPI_IO_TYPE_DMA		2
-	u8	io_type;
-	u8	timer_disable;
-	u8	c2tdelay;
-	u8	t2cdelay;
-	u8	t2edelay;
-	u8	c2edelay;
-};
-
-#endif	/* __ARCH_ARM_DAVINCI_SPI_H */
diff --git a/arch/arm/mach-davinci/include/mach/tnetv107x.h b/arch/arm/mach-davinci/include/mach/tnetv107x.h
index 83e5926..1656a02 100644
--- a/arch/arm/mach-davinci/include/mach/tnetv107x.h
+++ b/arch/arm/mach-davinci/include/mach/tnetv107x.h
@@ -36,8 +36,8 @@
 #include <linux/input/matrix_keypad.h>
 #include <linux/mfd/ti_ssp.h>
 
-#include <mach/mmc.h>
-#include <mach/nand.h>
+#include <linux/platform_data/mmc-davinci.h>
+#include <linux/platform_data/mtd-davinci.h>
 #include <mach/serial.h>
 
 struct tnetv107x_device_info {
diff --git a/arch/arm/mach-davinci/include/mach/usb.h b/arch/arm/mach-davinci/include/mach/usb.h
deleted file mode 100644
index e0bc4ab..0000000
--- a/arch/arm/mach-davinci/include/mach/usb.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * USB related definitions
- *
- * Copyright (C) 2009 MontaVista Software, Inc. <source@mvista.com>
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2. This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
- */
-
-#ifndef __ASM_ARCH_USB_H
-#define __ASM_ARCH_USB_H
-
-/* DA8xx CFGCHIP2 (USB 2.0 PHY Control) register bits */
-#define CFGCHIP2_PHYCLKGD	(1 << 17)
-#define CFGCHIP2_VBUSSENSE	(1 << 16)
-#define CFGCHIP2_RESET		(1 << 15)
-#define CFGCHIP2_OTGMODE	(3 << 13)
-#define CFGCHIP2_NO_OVERRIDE	(0 << 13)
-#define CFGCHIP2_FORCE_HOST	(1 << 13)
-#define CFGCHIP2_FORCE_DEVICE 	(2 << 13)
-#define CFGCHIP2_FORCE_HOST_VBUS_LOW (3 << 13)
-#define CFGCHIP2_USB1PHYCLKMUX	(1 << 12)
-#define CFGCHIP2_USB2PHYCLKMUX	(1 << 11)
-#define CFGCHIP2_PHYPWRDN	(1 << 10)
-#define CFGCHIP2_OTGPWRDN	(1 << 9)
-#define CFGCHIP2_DATPOL 	(1 << 8)
-#define CFGCHIP2_USB1SUSPENDM	(1 << 7)
-#define CFGCHIP2_PHY_PLLON	(1 << 6)	/* override PLL suspend */
-#define CFGCHIP2_SESENDEN	(1 << 5)	/* Vsess_end comparator */
-#define CFGCHIP2_VBDTCTEN	(1 << 4)	/* Vbus comparator */
-#define CFGCHIP2_REFFREQ	(0xf << 0)
-#define CFGCHIP2_REFFREQ_12MHZ	(1 << 0)
-#define CFGCHIP2_REFFREQ_24MHZ	(2 << 0)
-#define CFGCHIP2_REFFREQ_48MHZ	(3 << 0)
-
-struct	da8xx_ohci_root_hub;
-
-typedef void (*da8xx_ocic_handler_t)(struct da8xx_ohci_root_hub *hub,
-				     unsigned port);
-
-/* Passed as the platform data to the OHCI driver */
-struct	da8xx_ohci_root_hub {
-	/* Switch the port power on/off */
-	int	(*set_power)(unsigned port, int on);
-	/* Read the port power status */
-	int	(*get_power)(unsigned port);
-	/* Read the port over-current indicator */
-	int	(*get_oci)(unsigned port);
-	/* Over-current indicator change notification (pass NULL to disable) */
-	int	(*ocic_notify)(da8xx_ocic_handler_t handler);
-
-	/* Time from power on to power good (in 2 ms units) */
-	u8	potpgt;
-};
-
-void davinci_setup_usb(unsigned mA, unsigned potpgt_ms);
-
-#endif	/* ifndef __ASM_ARCH_USB_H */
diff --git a/arch/arm/mach-davinci/usb.c b/arch/arm/mach-davinci/usb.c
index 23d2b6d..f77b953 100644
--- a/arch/arm/mach-davinci/usb.c
+++ b/arch/arm/mach-davinci/usb.c
@@ -10,7 +10,7 @@
 #include <mach/common.h>
 #include <mach/irqs.h>
 #include <mach/cputype.h>
-#include <mach/usb.h>
+#include <linux/platform_data/usb-davinci.h>
 
 #define DAVINCI_USB_OTG_BASE	0x01c64000
 
diff --git a/arch/arm/mach-dove/Kconfig b/arch/arm/mach-dove/Kconfig
index dd937c5..00154e7 100644
--- a/arch/arm/mach-dove/Kconfig
+++ b/arch/arm/mach-dove/Kconfig
@@ -15,6 +15,13 @@ config MACH_CM_A510
 	  Say 'Y' here if you want your kernel to support the
 	  CompuLab CM-A510 Board.
 
+config MACH_DOVE_DT
+	bool "Marvell Dove Flattened Device Tree"
+	select USE_OF
+	help
+	  Say 'Y' here if you want your kernel to support the
+	  Marvell Dove using flattened device tree.
+
 endmenu
 
 endif
diff --git a/arch/arm/mach-dove/Makefile b/arch/arm/mach-dove/Makefile
index fa0f018..5e683ba 100644
--- a/arch/arm/mach-dove/Makefile
+++ b/arch/arm/mach-dove/Makefile
@@ -1,4 +1,4 @@
-obj-y				+= common.o addr-map.o irq.o pcie.o mpp.o
-
+obj-y				+= common.o addr-map.o irq.o mpp.o
+obj-$(CONFIG_PCI)		+= pcie.o
 obj-$(CONFIG_MACH_DOVE_DB)	+= dove-db-setup.o
 obj-$(CONFIG_MACH_CM_A510)	+= cm-a510.o
diff --git a/arch/arm/mach-dove/common.c b/arch/arm/mach-dove/common.c
index 6321567..b37bef1 100644
--- a/arch/arm/mach-dove/common.c
+++ b/arch/arm/mach-dove/common.c
@@ -16,6 +16,8 @@
 #include <linux/clk-provider.h>
 #include <linux/ata_platform.h>
 #include <linux/gpio.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
 #include <asm/page.h>
 #include <asm/setup.h>
 #include <asm/timex.h>
@@ -24,41 +26,30 @@
 #include <asm/mach/time.h>
 #include <asm/mach/pci.h>
 #include <mach/dove.h>
+#include <mach/pm.h>
 #include <mach/bridge-regs.h>
 #include <asm/mach/arch.h>
 #include <linux/irq.h>
 #include <plat/time.h>
-#include <plat/ehci-orion.h>
+#include <linux/platform_data/usb-ehci-orion.h>
 #include <plat/common.h>
 #include <plat/addr-map.h>
 #include "common.h"
 
-static int get_tclk(void);
-
 /*****************************************************************************
  * I/O Address Mapping
  ****************************************************************************/
 static struct map_desc dove_io_desc[] __initdata = {
 	{
-		.virtual	= DOVE_SB_REGS_VIRT_BASE,
+		.virtual	= (unsigned long) DOVE_SB_REGS_VIRT_BASE,
 		.pfn		= __phys_to_pfn(DOVE_SB_REGS_PHYS_BASE),
 		.length		= DOVE_SB_REGS_SIZE,
 		.type		= MT_DEVICE,
 	}, {
-		.virtual	= DOVE_NB_REGS_VIRT_BASE,
+		.virtual	= (unsigned long) DOVE_NB_REGS_VIRT_BASE,
 		.pfn		= __phys_to_pfn(DOVE_NB_REGS_PHYS_BASE),
 		.length		= DOVE_NB_REGS_SIZE,
 		.type		= MT_DEVICE,
-	}, {
-		.virtual	= DOVE_PCIE0_IO_VIRT_BASE,
-		.pfn		= __phys_to_pfn(DOVE_PCIE0_IO_PHYS_BASE),
-		.length		= DOVE_PCIE0_IO_SIZE,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= DOVE_PCIE1_IO_VIRT_BASE,
-		.pfn		= __phys_to_pfn(DOVE_PCIE1_IO_PHYS_BASE),
-		.length		= DOVE_PCIE1_IO_SIZE,
-		.type		= MT_DEVICE,
 	},
 };
 
@@ -70,14 +61,69 @@ void __init dove_map_io(void)
 /*****************************************************************************
  * CLK tree
  ****************************************************************************/
+static int dove_tclk;
+
+static DEFINE_SPINLOCK(gating_lock);
 static struct clk *tclk;
 
-static void __init clk_init(void)
+static struct clk __init *dove_register_gate(const char *name,
+					     const char *parent, u8 bit_idx)
 {
-	tclk = clk_register_fixed_rate(NULL, "tclk", NULL, CLK_IS_ROOT,
-				       get_tclk());
+	return clk_register_gate(NULL, name, parent, 0,
+				 (void __iomem *)CLOCK_GATING_CONTROL,
+				 bit_idx, 0, &gating_lock);
+}
 
-	orion_clkdev_init(tclk);
+static void __init dove_clk_init(void)
+{
+	struct clk *usb0, *usb1, *sata, *pex0, *pex1, *sdio0, *sdio1;
+	struct clk *nand, *camera, *i2s0, *i2s1, *crypto, *ac97, *pdma;
+	struct clk *xor0, *xor1, *ge, *gephy;
+
+	tclk = clk_register_fixed_rate(NULL, "tclk", NULL, CLK_IS_ROOT,
+				       dove_tclk);
+
+	usb0 = dove_register_gate("usb0", "tclk", CLOCK_GATING_BIT_USB0);
+	usb1 = dove_register_gate("usb1", "tclk", CLOCK_GATING_BIT_USB1);
+	sata = dove_register_gate("sata", "tclk", CLOCK_GATING_BIT_SATA);
+	pex0 = dove_register_gate("pex0", "tclk", CLOCK_GATING_BIT_PCIE0);
+	pex1 = dove_register_gate("pex1", "tclk", CLOCK_GATING_BIT_PCIE1);
+	sdio0 = dove_register_gate("sdio0", "tclk", CLOCK_GATING_BIT_SDIO0);
+	sdio1 = dove_register_gate("sdio1", "tclk", CLOCK_GATING_BIT_SDIO1);
+	nand = dove_register_gate("nand", "tclk", CLOCK_GATING_BIT_NAND);
+	camera = dove_register_gate("camera", "tclk", CLOCK_GATING_BIT_CAMERA);
+	i2s0 = dove_register_gate("i2s0", "tclk", CLOCK_GATING_BIT_I2S0);
+	i2s1 = dove_register_gate("i2s1", "tclk", CLOCK_GATING_BIT_I2S1);
+	crypto = dove_register_gate("crypto", "tclk", CLOCK_GATING_BIT_CRYPTO);
+	ac97 = dove_register_gate("ac97", "tclk", CLOCK_GATING_BIT_AC97);
+	pdma = dove_register_gate("pdma", "tclk", CLOCK_GATING_BIT_PDMA);
+	xor0 = dove_register_gate("xor0", "tclk", CLOCK_GATING_BIT_XOR0);
+	xor1 = dove_register_gate("xor1", "tclk", CLOCK_GATING_BIT_XOR1);
+	gephy = dove_register_gate("gephy", "tclk", CLOCK_GATING_BIT_GIGA_PHY);
+	ge = dove_register_gate("ge", "gephy", CLOCK_GATING_BIT_GBE);
+
+	orion_clkdev_add(NULL, "orion_spi.0", tclk);
+	orion_clkdev_add(NULL, "orion_spi.1", tclk);
+	orion_clkdev_add(NULL, "orion_wdt", tclk);
+	orion_clkdev_add(NULL, "mv64xxx_i2c.0", tclk);
+
+	orion_clkdev_add(NULL, "orion-ehci.0", usb0);
+	orion_clkdev_add(NULL, "orion-ehci.1", usb1);
+	orion_clkdev_add(NULL, "mv643xx_eth.0", ge);
+	orion_clkdev_add("0", "sata_mv.0", sata);
+	orion_clkdev_add("0", "pcie", pex0);
+	orion_clkdev_add("1", "pcie", pex1);
+	orion_clkdev_add(NULL, "sdhci-dove.0", sdio0);
+	orion_clkdev_add(NULL, "sdhci-dove.1", sdio1);
+	orion_clkdev_add(NULL, "orion_nand", nand);
+	orion_clkdev_add(NULL, "cafe1000-ccic.0", camera);
+	orion_clkdev_add(NULL, "kirkwood-i2s.0", i2s0);
+	orion_clkdev_add(NULL, "kirkwood-i2s.1", i2s1);
+	orion_clkdev_add(NULL, "mv_crypto", crypto);
+	orion_clkdev_add(NULL, "dove-ac97", ac97);
+	orion_clkdev_add(NULL, "dove-pdma", pdma);
+	orion_clkdev_add(NULL, "mv_xor_shared.0", xor0);
+	orion_clkdev_add(NULL, "mv_xor_shared.1", xor1);
 }
 
 /*****************************************************************************
@@ -188,16 +234,16 @@ void __init dove_init_early(void)
 	orion_time_set_base(TIMER_VIRT_BASE);
 }
 
-static int get_tclk(void)
+static int __init dove_find_tclk(void)
 {
-	/* use DOVE_RESET_SAMPLE_HI/LO to detect tclk */
 	return 166666667;
 }
 
 static void __init dove_timer_init(void)
 {
+	dove_tclk = dove_find_tclk();
 	orion_time_init(BRIDGE_VIRT_BASE, BRIDGE_INT_TIMER1_CLR,
-			IRQ_DOVE_BRIDGE, get_tclk());
+			IRQ_DOVE_BRIDGE, dove_tclk);
 }
 
 struct sys_timer dove_timer = {
@@ -205,6 +251,15 @@ struct sys_timer dove_timer = {
 };
 
 /*****************************************************************************
+ * Cryptographic Engines and Security Accelerator (CESA)
+ ****************************************************************************/
+void __init dove_crypto_init(void)
+{
+	orion_crypto_init(DOVE_CRYPT_PHYS_BASE, DOVE_CESA_PHYS_BASE,
+			  DOVE_CESA_SIZE, IRQ_DOVE_CRYPTO);
+}
+
+/*****************************************************************************
  * XOR 0
  ****************************************************************************/
 void __init dove_xor0_init(void)
@@ -285,16 +340,16 @@ void __init dove_sdio1_init(void)
 
 void __init dove_init(void)
 {
-	printk(KERN_INFO "Dove 88AP510 SoC, ");
-	printk(KERN_INFO "TCLK = %dMHz\n", (get_tclk() + 499999) / 1000000);
+	pr_info("Dove 88AP510 SoC, TCLK = %d MHz.\n",
+		(dove_tclk + 499999) / 1000000);
 
 #ifdef CONFIG_CACHE_TAUROS2
-	tauros2_init();
+	tauros2_init(0);
 #endif
 	dove_setup_cpu_mbus();
 
 	/* Setup root of clk tree */
-	clk_init();
+	dove_clk_init();
 
 	/* internal devices that every board has */
 	dove_rtc_init();
@@ -317,3 +372,67 @@ void dove_restart(char mode, const char *cmd)
 	while (1)
 		;
 }
+
+#if defined(CONFIG_MACH_DOVE_DT)
+/*
+ * Auxdata required until real OF clock provider
+ */
+struct of_dev_auxdata dove_auxdata_lookup[] __initdata = {
+	OF_DEV_AUXDATA("marvell,orion-spi", 0xf1010600, "orion_spi.0", NULL),
+	OF_DEV_AUXDATA("marvell,orion-spi", 0xf1014600, "orion_spi.1", NULL),
+	OF_DEV_AUXDATA("marvell,orion-wdt", 0xf1020300, "orion_wdt", NULL),
+	OF_DEV_AUXDATA("marvell,mv64xxx-i2c", 0xf1011000, "mv64xxx_i2c.0",
+		       NULL),
+	OF_DEV_AUXDATA("marvell,orion-sata", 0xf10a0000, "sata_mv.0", NULL),
+	OF_DEV_AUXDATA("marvell,dove-sdhci", 0xf1092000, "sdhci-dove.0", NULL),
+	OF_DEV_AUXDATA("marvell,dove-sdhci", 0xf1090000, "sdhci-dove.1", NULL),
+	{},
+};
+
+static struct mv643xx_eth_platform_data dove_dt_ge00_data = {
+	.phy_addr = MV643XX_ETH_PHY_ADDR_DEFAULT,
+};
+
+static void __init dove_dt_init(void)
+{
+	pr_info("Dove 88AP510 SoC, TCLK = %d MHz.\n",
+		(dove_tclk + 499999) / 1000000);
+
+#ifdef CONFIG_CACHE_TAUROS2
+	tauros2_init();
+#endif
+	dove_setup_cpu_mbus();
+
+	/* Setup root of clk tree */
+	dove_clk_init();
+
+	/* Internal devices not ported to DT yet */
+	dove_rtc_init();
+	dove_xor0_init();
+	dove_xor1_init();
+
+	dove_ge00_init(&dove_dt_ge00_data);
+	dove_ehci0_init();
+	dove_ehci1_init();
+	dove_pcie_init(1, 1);
+	dove_crypto_init();
+
+	of_platform_populate(NULL, of_default_bus_match_table,
+			     dove_auxdata_lookup, NULL);
+}
+
+static const char * const dove_dt_board_compat[] = {
+	"marvell,dove",
+	NULL
+};
+
+DT_MACHINE_START(DOVE_DT, "Marvell Dove (Flattened Device Tree)")
+	.map_io		= dove_map_io,
+	.init_early	= dove_init_early,
+	.init_irq	= orion_dt_init_irq,
+	.timer		= &dove_timer,
+	.init_machine	= dove_dt_init,
+	.restart	= dove_restart,
+	.dt_compat	= dove_dt_board_compat,
+MACHINE_END
+#endif
diff --git a/arch/arm/mach-dove/common.h b/arch/arm/mach-dove/common.h
index 6432a3b..1a23340 100644
--- a/arch/arm/mach-dove/common.h
+++ b/arch/arm/mach-dove/common.h
@@ -26,7 +26,11 @@ void dove_init_irq(void);
 void dove_setup_cpu_mbus(void);
 void dove_ge00_init(struct mv643xx_eth_platform_data *eth_data);
 void dove_sata_init(struct mv_sata_platform_data *sata_data);
+#ifdef CONFIG_PCI
 void dove_pcie_init(int init_port0, int init_port1);
+#else
+static inline void dove_pcie_init(int init_port0, int init_port1) { }
+#endif
 void dove_ehci0_init(void);
 void dove_ehci1_init(void);
 void dove_uart0_init(void);
diff --git a/arch/arm/mach-dove/include/mach/bridge-regs.h b/arch/arm/mach-dove/include/mach/bridge-regs.h
index f953bb5..99f259e 100644
--- a/arch/arm/mach-dove/include/mach/bridge-regs.h
+++ b/arch/arm/mach-dove/include/mach/bridge-regs.h
@@ -13,22 +13,22 @@
 
 #include <mach/dove.h>
 
-#define CPU_CONFIG		(BRIDGE_VIRT_BASE | 0x0000)
+#define CPU_CONFIG		(BRIDGE_VIRT_BASE + 0x0000)
 
-#define CPU_CONTROL		(BRIDGE_VIRT_BASE | 0x0104)
+#define CPU_CONTROL		(BRIDGE_VIRT_BASE + 0x0104)
 #define  CPU_CTRL_PCIE0_LINK	0x00000001
 #define  CPU_RESET		0x00000002
 #define  CPU_CTRL_PCIE1_LINK	0x00000008
 
-#define RSTOUTn_MASK		(BRIDGE_VIRT_BASE | 0x0108)
+#define RSTOUTn_MASK		(BRIDGE_VIRT_BASE + 0x0108)
 #define  SOFT_RESET_OUT_EN	0x00000004
 
-#define SYSTEM_SOFT_RESET	(BRIDGE_VIRT_BASE | 0x010c)
+#define SYSTEM_SOFT_RESET	(BRIDGE_VIRT_BASE + 0x010c)
 #define  SOFT_RESET		0x00000001
 
 #define  BRIDGE_INT_TIMER1_CLR	(~0x0004)
 
-#define IRQ_VIRT_BASE		(BRIDGE_VIRT_BASE | 0x0200)
+#define IRQ_VIRT_BASE		(BRIDGE_VIRT_BASE + 0x0200)
 #define IRQ_CAUSE_LOW_OFF	0x0000
 #define IRQ_MASK_LOW_OFF	0x0004
 #define FIQ_MASK_LOW_OFF	0x0008
@@ -47,9 +47,9 @@
 #define ENDPOINT_MASK_HIGH	(IRQ_VIRT_BASE + ENDPOINT_MASK_HIGH_OFF)
 #define PCIE_INTERRUPT_MASK	(IRQ_VIRT_BASE + PCIE_INTERRUPT_MASK_OFF)
 
-#define POWER_MANAGEMENT	(BRIDGE_VIRT_BASE | 0x011c)
+#define POWER_MANAGEMENT	(BRIDGE_VIRT_BASE + 0x011c)
 
-#define TIMER_VIRT_BASE		(BRIDGE_VIRT_BASE | 0x0300)
-#define TIMER_PHYS_BASE         (BRIDGE_PHYS_BASE | 0x0300)
+#define TIMER_VIRT_BASE		(BRIDGE_VIRT_BASE + 0x0300)
+#define TIMER_PHYS_BASE         (BRIDGE_PHYS_BASE + 0x0300)
 
 #endif
diff --git a/arch/arm/mach-dove/include/mach/dove.h b/arch/arm/mach-dove/include/mach/dove.h
index d52b0ef..661725e 100644
--- a/arch/arm/mach-dove/include/mach/dove.h
+++ b/arch/arm/mach-dove/include/mach/dove.h
@@ -25,7 +25,7 @@
  */
 
 #define DOVE_CESA_PHYS_BASE		0xc8000000
-#define DOVE_CESA_VIRT_BASE		0xfdb00000
+#define DOVE_CESA_VIRT_BASE		IOMEM(0xfdb00000)
 #define DOVE_CESA_SIZE			SZ_1M
 
 #define DOVE_PCIE0_MEM_PHYS_BASE	0xe0000000
@@ -38,101 +38,99 @@
 #define DOVE_BOOTROM_SIZE		SZ_128M
 
 #define DOVE_SCRATCHPAD_PHYS_BASE	0xf0000000
-#define DOVE_SCRATCHPAD_VIRT_BASE	0xfdd00000
+#define DOVE_SCRATCHPAD_VIRT_BASE	IOMEM(0xfdd00000)
 #define DOVE_SCRATCHPAD_SIZE		SZ_1M
 
 #define DOVE_SB_REGS_PHYS_BASE		0xf1000000
-#define DOVE_SB_REGS_VIRT_BASE		0xfde00000
+#define DOVE_SB_REGS_VIRT_BASE		IOMEM(0xfde00000)
 #define DOVE_SB_REGS_SIZE		SZ_8M
 
 #define DOVE_NB_REGS_PHYS_BASE		0xf1800000
-#define DOVE_NB_REGS_VIRT_BASE		0xfe600000
+#define DOVE_NB_REGS_VIRT_BASE		IOMEM(0xfe600000)
 #define DOVE_NB_REGS_SIZE		SZ_8M
 
 #define DOVE_PCIE0_IO_PHYS_BASE		0xf2000000
-#define DOVE_PCIE0_IO_VIRT_BASE		0xfee00000
 #define DOVE_PCIE0_IO_BUS_BASE		0x00000000
-#define DOVE_PCIE0_IO_SIZE		SZ_1M
+#define DOVE_PCIE0_IO_SIZE		SZ_64K
 
 #define DOVE_PCIE1_IO_PHYS_BASE		0xf2100000
-#define DOVE_PCIE1_IO_VIRT_BASE		0xfef00000
-#define DOVE_PCIE1_IO_BUS_BASE		0x00100000
-#define DOVE_PCIE1_IO_SIZE		SZ_1M
+#define DOVE_PCIE1_IO_BUS_BASE		0x00010000
+#define DOVE_PCIE1_IO_SIZE		SZ_64K
 
 /*
  * Dove Core Registers Map
  */
 
 /* SPI, I2C, UART */
-#define DOVE_I2C_PHYS_BASE	(DOVE_SB_REGS_PHYS_BASE | 0x11000)
-#define DOVE_UART0_PHYS_BASE	(DOVE_SB_REGS_PHYS_BASE | 0x12000)
-#define DOVE_UART0_VIRT_BASE	(DOVE_SB_REGS_VIRT_BASE | 0x12000)
-#define DOVE_UART1_PHYS_BASE	(DOVE_SB_REGS_PHYS_BASE | 0x12100)
-#define DOVE_UART1_VIRT_BASE	(DOVE_SB_REGS_VIRT_BASE | 0x12100)
-#define DOVE_UART2_PHYS_BASE	(DOVE_SB_REGS_PHYS_BASE | 0x12200)
-#define DOVE_UART2_VIRT_BASE	(DOVE_SB_REGS_VIRT_BASE | 0x12200)
-#define DOVE_UART3_PHYS_BASE	(DOVE_SB_REGS_PHYS_BASE | 0x12300)
-#define DOVE_UART3_VIRT_BASE	(DOVE_SB_REGS_VIRT_BASE | 0x12300)
-#define DOVE_SPI0_PHYS_BASE	(DOVE_SB_REGS_PHYS_BASE | 0x10600)
-#define DOVE_SPI1_PHYS_BASE	(DOVE_SB_REGS_PHYS_BASE | 0x14600)
+#define DOVE_I2C_PHYS_BASE	(DOVE_SB_REGS_PHYS_BASE + 0x11000)
+#define DOVE_UART0_PHYS_BASE	(DOVE_SB_REGS_PHYS_BASE + 0x12000)
+#define DOVE_UART0_VIRT_BASE	(DOVE_SB_REGS_VIRT_BASE + 0x12000)
+#define DOVE_UART1_PHYS_BASE	(DOVE_SB_REGS_PHYS_BASE + 0x12100)
+#define DOVE_UART1_VIRT_BASE	(DOVE_SB_REGS_VIRT_BASE + 0x12100)
+#define DOVE_UART2_PHYS_BASE	(DOVE_SB_REGS_PHYS_BASE + 0x12200)
+#define DOVE_UART2_VIRT_BASE	(DOVE_SB_REGS_VIRT_BASE + 0x12200)
+#define DOVE_UART3_PHYS_BASE	(DOVE_SB_REGS_PHYS_BASE + 0x12300)
+#define DOVE_UART3_VIRT_BASE	(DOVE_SB_REGS_VIRT_BASE + 0x12300)
+#define DOVE_SPI0_PHYS_BASE	(DOVE_SB_REGS_PHYS_BASE + 0x10600)
+#define DOVE_SPI1_PHYS_BASE	(DOVE_SB_REGS_PHYS_BASE + 0x14600)
 
 /* North-South Bridge */
-#define BRIDGE_VIRT_BASE	(DOVE_SB_REGS_VIRT_BASE | 0x20000)
-#define BRIDGE_PHYS_BASE	(DOVE_SB_REGS_PHYS_BASE | 0x20000)
+#define BRIDGE_VIRT_BASE	(DOVE_SB_REGS_VIRT_BASE + 0x20000)
+#define BRIDGE_PHYS_BASE	(DOVE_SB_REGS_PHYS_BASE + 0x20000)
 
 /* Cryptographic Engine */
-#define DOVE_CRYPT_PHYS_BASE	(DOVE_SB_REGS_PHYS_BASE | 0x30000)
+#define DOVE_CRYPT_PHYS_BASE	(DOVE_SB_REGS_PHYS_BASE + 0x30000)
 
 /* PCIe 0 */
-#define DOVE_PCIE0_VIRT_BASE	(DOVE_SB_REGS_VIRT_BASE | 0x40000)
+#define DOVE_PCIE0_VIRT_BASE	(DOVE_SB_REGS_VIRT_BASE + 0x40000)
 
 /* USB */
-#define DOVE_USB0_PHYS_BASE	(DOVE_SB_REGS_PHYS_BASE | 0x50000)
-#define DOVE_USB1_PHYS_BASE	(DOVE_SB_REGS_PHYS_BASE | 0x51000)
+#define DOVE_USB0_PHYS_BASE	(DOVE_SB_REGS_PHYS_BASE + 0x50000)
+#define DOVE_USB1_PHYS_BASE	(DOVE_SB_REGS_PHYS_BASE + 0x51000)
 
 /* XOR 0 Engine */
-#define DOVE_XOR0_PHYS_BASE	(DOVE_SB_REGS_PHYS_BASE | 0x60800)
-#define DOVE_XOR0_VIRT_BASE	(DOVE_SB_REGS_VIRT_BASE | 0x60800)
-#define DOVE_XOR0_HIGH_PHYS_BASE	(DOVE_SB_REGS_PHYS_BASE | 0x60A00)
-#define DOVE_XOR0_HIGH_VIRT_BASE	(DOVE_SB_REGS_VIRT_BASE | 0x60A00)
+#define DOVE_XOR0_PHYS_BASE	(DOVE_SB_REGS_PHYS_BASE + 0x60800)
+#define DOVE_XOR0_VIRT_BASE	(DOVE_SB_REGS_VIRT_BASE + 0x60800)
+#define DOVE_XOR0_HIGH_PHYS_BASE	(DOVE_SB_REGS_PHYS_BASE + 0x60A00)
+#define DOVE_XOR0_HIGH_VIRT_BASE	(DOVE_SB_REGS_VIRT_BASE + 0x60A00)
 
 /* XOR 1 Engine */
-#define DOVE_XOR1_PHYS_BASE	(DOVE_SB_REGS_PHYS_BASE | 0x60900)
-#define DOVE_XOR1_VIRT_BASE	(DOVE_SB_REGS_VIRT_BASE | 0x60900)
-#define DOVE_XOR1_HIGH_PHYS_BASE	(DOVE_SB_REGS_PHYS_BASE | 0x60B00)
-#define DOVE_XOR1_HIGH_VIRT_BASE	(DOVE_SB_REGS_VIRT_BASE | 0x60B00)
+#define DOVE_XOR1_PHYS_BASE	(DOVE_SB_REGS_PHYS_BASE + 0x60900)
+#define DOVE_XOR1_VIRT_BASE	(DOVE_SB_REGS_VIRT_BASE + 0x60900)
+#define DOVE_XOR1_HIGH_PHYS_BASE	(DOVE_SB_REGS_PHYS_BASE + 0x60B00)
+#define DOVE_XOR1_HIGH_VIRT_BASE	(DOVE_SB_REGS_VIRT_BASE + 0x60B00)
 
 /* Gigabit Ethernet */
-#define DOVE_GE00_PHYS_BASE	(DOVE_SB_REGS_PHYS_BASE | 0x70000)
+#define DOVE_GE00_PHYS_BASE	(DOVE_SB_REGS_PHYS_BASE + 0x70000)
 
 /* PCIe 1 */
-#define DOVE_PCIE1_VIRT_BASE	(DOVE_SB_REGS_VIRT_BASE | 0x80000)
+#define DOVE_PCIE1_VIRT_BASE	(DOVE_SB_REGS_VIRT_BASE + 0x80000)
 
 /* CAFE */
-#define DOVE_SDIO0_PHYS_BASE	(DOVE_SB_REGS_PHYS_BASE | 0x92000)
-#define DOVE_SDIO1_PHYS_BASE	(DOVE_SB_REGS_PHYS_BASE | 0x90000)
-#define DOVE_CAM_PHYS_BASE	(DOVE_SB_REGS_PHYS_BASE | 0x94000)
-#define DOVE_CAFE_WIN_PHYS_BASE	(DOVE_SB_REGS_PHYS_BASE | 0x98000)
+#define DOVE_SDIO0_PHYS_BASE	(DOVE_SB_REGS_PHYS_BASE + 0x92000)
+#define DOVE_SDIO1_PHYS_BASE	(DOVE_SB_REGS_PHYS_BASE + 0x90000)
+#define DOVE_CAM_PHYS_BASE	(DOVE_SB_REGS_PHYS_BASE + 0x94000)
+#define DOVE_CAFE_WIN_PHYS_BASE	(DOVE_SB_REGS_PHYS_BASE + 0x98000)
 
 /* SATA */
-#define DOVE_SATA_PHYS_BASE	(DOVE_SB_REGS_PHYS_BASE | 0xa0000)
+#define DOVE_SATA_PHYS_BASE	(DOVE_SB_REGS_PHYS_BASE + 0xa0000)
 
 /* I2S/SPDIF */
-#define DOVE_AUD0_PHYS_BASE	(DOVE_SB_REGS_PHYS_BASE | 0xb0000)
-#define DOVE_AUD1_PHYS_BASE	(DOVE_SB_REGS_PHYS_BASE | 0xb4000)
+#define DOVE_AUD0_PHYS_BASE	(DOVE_SB_REGS_PHYS_BASE + 0xb0000)
+#define DOVE_AUD1_PHYS_BASE	(DOVE_SB_REGS_PHYS_BASE + 0xb4000)
 
 /* NAND Flash Controller */
-#define DOVE_NFC_PHYS_BASE	(DOVE_SB_REGS_PHYS_BASE | 0xc0000)
+#define DOVE_NFC_PHYS_BASE	(DOVE_SB_REGS_PHYS_BASE + 0xc0000)
 
 /* MPP, GPIO, Reset Sampling */
-#define DOVE_MPP_VIRT_BASE	(DOVE_SB_REGS_VIRT_BASE | 0xd0200)
+#define DOVE_MPP_VIRT_BASE	(DOVE_SB_REGS_VIRT_BASE + 0xd0200)
 #define DOVE_PMU_MPP_GENERAL_CTRL (DOVE_MPP_VIRT_BASE + 0x10)
-#define DOVE_RESET_SAMPLE_LO	(DOVE_MPP_VIRT_BASE | 0x014)
-#define DOVE_RESET_SAMPLE_HI	(DOVE_MPP_VIRT_BASE | 0x018)
-#define DOVE_GPIO_LO_VIRT_BASE	(DOVE_SB_REGS_VIRT_BASE | 0xd0400)
-#define DOVE_GPIO_HI_VIRT_BASE	(DOVE_SB_REGS_VIRT_BASE | 0xd0420)
-#define DOVE_GPIO2_VIRT_BASE    (DOVE_SB_REGS_VIRT_BASE | 0xe8400)
-#define DOVE_MPP_GENERAL_VIRT_BASE	(DOVE_SB_REGS_VIRT_BASE | 0xe803c)
+#define DOVE_RESET_SAMPLE_LO	(DOVE_MPP_VIRT_BASE + 0x014)
+#define DOVE_RESET_SAMPLE_HI	(DOVE_MPP_VIRT_BASE + 0x018)
+#define DOVE_GPIO_LO_VIRT_BASE	(DOVE_SB_REGS_VIRT_BASE + 0xd0400)
+#define DOVE_GPIO_HI_VIRT_BASE	(DOVE_SB_REGS_VIRT_BASE + 0xd0420)
+#define DOVE_GPIO2_VIRT_BASE    (DOVE_SB_REGS_VIRT_BASE + 0xe8400)
+#define DOVE_MPP_GENERAL_VIRT_BASE	(DOVE_SB_REGS_VIRT_BASE + 0xe803c)
 #define  DOVE_AU1_SPDIFO_GPIO_EN	(1 << 1)
 #define  DOVE_NAND_GPIO_EN		(1 << 0)
 #define DOVE_MPP_CTRL4_VIRT_BASE	(DOVE_GPIO_LO_VIRT_BASE + 0x40)
@@ -144,44 +142,44 @@
 #define  DOVE_SD0_GPIO_SEL		(1 << 0)
 
 /* Power Management */
-#define DOVE_PMU_VIRT_BASE	(DOVE_SB_REGS_VIRT_BASE | 0xd0000)
+#define DOVE_PMU_VIRT_BASE	(DOVE_SB_REGS_VIRT_BASE + 0xd0000)
 #define DOVE_PMU_SIG_CTRL	(DOVE_PMU_VIRT_BASE + 0x802c)
 
 /* Real Time Clock */
-#define DOVE_RTC_PHYS_BASE	(DOVE_SB_REGS_PHYS_BASE | 0xd8500)
+#define DOVE_RTC_PHYS_BASE	(DOVE_SB_REGS_PHYS_BASE + 0xd8500)
 
 /* AC97 */
-#define DOVE_AC97_PHYS_BASE	(DOVE_SB_REGS_PHYS_BASE | 0xe0000)
-#define DOVE_AC97_VIRT_BASE	(DOVE_SB_REGS_VIRT_BASE | 0xe0000)
+#define DOVE_AC97_PHYS_BASE	(DOVE_SB_REGS_PHYS_BASE + 0xe0000)
+#define DOVE_AC97_VIRT_BASE	(DOVE_SB_REGS_VIRT_BASE + 0xe0000)
 
 /* Peripheral DMA */
-#define DOVE_PDMA_PHYS_BASE	(DOVE_SB_REGS_PHYS_BASE | 0xe4000)
-#define DOVE_PDMA_VIRT_BASE	(DOVE_SB_REGS_VIRT_BASE | 0xe4000)
+#define DOVE_PDMA_PHYS_BASE	(DOVE_SB_REGS_PHYS_BASE + 0xe4000)
+#define DOVE_PDMA_VIRT_BASE	(DOVE_SB_REGS_VIRT_BASE + 0xe4000)
 
-#define DOVE_GLOBAL_CONFIG_1	(DOVE_SB_REGS_VIRT_BASE | 0xe802C)
+#define DOVE_GLOBAL_CONFIG_1	(DOVE_SB_REGS_VIRT_BASE + 0xe802C)
 #define  DOVE_TWSI_ENABLE_OPTION1	(1 << 7)
-#define DOVE_GLOBAL_CONFIG_2	(DOVE_SB_REGS_VIRT_BASE | 0xe8030)
+#define DOVE_GLOBAL_CONFIG_2	(DOVE_SB_REGS_VIRT_BASE + 0xe8030)
 #define  DOVE_TWSI_ENABLE_OPTION2	(1 << 20)
 #define  DOVE_TWSI_ENABLE_OPTION3	(1 << 21)
 #define  DOVE_TWSI_OPTION3_GPIO		(1 << 22)
-#define DOVE_SSP_PHYS_BASE	(DOVE_SB_REGS_PHYS_BASE | 0xec000)
-#define DOVE_SSP_CTRL_STATUS_1	(DOVE_SB_REGS_VIRT_BASE | 0xe8034)
+#define DOVE_SSP_PHYS_BASE	(DOVE_SB_REGS_PHYS_BASE + 0xec000)
+#define DOVE_SSP_CTRL_STATUS_1	(DOVE_SB_REGS_VIRT_BASE + 0xe8034)
 #define  DOVE_SSP_ON_AU1		(1 << 0)
 #define  DOVE_SSP_CLOCK_ENABLE		(1 << 1)
 #define  DOVE_SSP_BPB_CLOCK_SRC_SSP	(1 << 11)
 /* Memory Controller */
-#define DOVE_MC_VIRT_BASE	(DOVE_NB_REGS_VIRT_BASE | 0x00000)
+#define DOVE_MC_VIRT_BASE	(DOVE_NB_REGS_VIRT_BASE + 0x00000)
 
 /* LCD Controller */
-#define DOVE_LCD_PHYS_BASE	(DOVE_NB_REGS_PHYS_BASE | 0x10000)
-#define DOVE_LCD1_PHYS_BASE	(DOVE_NB_REGS_PHYS_BASE | 0x20000)
-#define DOVE_LCD2_PHYS_BASE	(DOVE_NB_REGS_PHYS_BASE | 0x10000)
-#define DOVE_LCD_DCON_PHYS_BASE	(DOVE_NB_REGS_PHYS_BASE | 0x30000)
+#define DOVE_LCD_PHYS_BASE	(DOVE_NB_REGS_PHYS_BASE + 0x10000)
+#define DOVE_LCD1_PHYS_BASE	(DOVE_NB_REGS_PHYS_BASE + 0x20000)
+#define DOVE_LCD2_PHYS_BASE	(DOVE_NB_REGS_PHYS_BASE + 0x10000)
+#define DOVE_LCD_DCON_PHYS_BASE	(DOVE_NB_REGS_PHYS_BASE + 0x30000)
 
 /* Graphic Engine */
-#define DOVE_GPU_PHYS_BASE	(DOVE_NB_REGS_PHYS_BASE | 0x40000)
+#define DOVE_GPU_PHYS_BASE	(DOVE_NB_REGS_PHYS_BASE + 0x40000)
 
 /* Video Engine */
-#define DOVE_VPU_PHYS_BASE	(DOVE_NB_REGS_PHYS_BASE | 0x400000)
+#define DOVE_VPU_PHYS_BASE	(DOVE_NB_REGS_PHYS_BASE + 0x400000)
 
 #endif
diff --git a/arch/arm/mach-dove/include/mach/gpio.h b/arch/arm/mach-dove/include/mach/gpio.h
deleted file mode 100644
index e7e5101..0000000
--- a/arch/arm/mach-dove/include/mach/gpio.h
+++ /dev/null
@@ -1,9 +0,0 @@
-/*
- * arch/arm/mach-dove/include/mach/gpio.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.
- */
-
-#include <plat/gpio.h>
diff --git a/arch/arm/mach-dove/include/mach/io.h b/arch/arm/mach-dove/include/mach/io.h
deleted file mode 100644
index 29c8b85..0000000
--- a/arch/arm/mach-dove/include/mach/io.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * arch/arm/mach-dove/include/mach/io.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 __ASM_ARCH_IO_H
-#define __ASM_ARCH_IO_H
-
-#include "dove.h"
-
-#define IO_SPACE_LIMIT		0xffffffff
-
-#define __io(a)  	((void __iomem *)(((a) - DOVE_PCIE0_IO_BUS_BASE) + \
-						 DOVE_PCIE0_IO_VIRT_BASE))
-
-#endif
diff --git a/arch/arm/mach-dove/include/mach/pm.h b/arch/arm/mach-dove/include/mach/pm.h
index 3ad9f94..7bcd0df 100644
--- a/arch/arm/mach-dove/include/mach/pm.h
+++ b/arch/arm/mach-dove/include/mach/pm.h
@@ -13,24 +13,42 @@
 #include <mach/irqs.h>
 
 #define CLOCK_GATING_CONTROL	(DOVE_PMU_VIRT_BASE + 0x38)
-#define  CLOCK_GATING_USB0_MASK		(1 << 0)
-#define  CLOCK_GATING_USB1_MASK		(1 << 1)
-#define  CLOCK_GATING_GBE_MASK		(1 << 2)
-#define  CLOCK_GATING_SATA_MASK		(1 << 3)
-#define  CLOCK_GATING_PCIE0_MASK	(1 << 4)
-#define  CLOCK_GATING_PCIE1_MASK	(1 << 5)
-#define  CLOCK_GATING_SDIO0_MASK	(1 << 8)
-#define  CLOCK_GATING_SDIO1_MASK	(1 << 9)
-#define  CLOCK_GATING_NAND_MASK		(1 << 10)
-#define  CLOCK_GATING_CAMERA_MASK	(1 << 11)
-#define  CLOCK_GATING_I2S0_MASK		(1 << 12)
-#define  CLOCK_GATING_I2S1_MASK		(1 << 13)
-#define  CLOCK_GATING_CRYPTO_MASK	(1 << 15)
-#define  CLOCK_GATING_AC97_MASK		(1 << 21)
-#define  CLOCK_GATING_PDMA_MASK		(1 << 22)
-#define  CLOCK_GATING_XOR0_MASK		(1 << 23)
-#define  CLOCK_GATING_XOR1_MASK		(1 << 24)
-#define  CLOCK_GATING_GIGA_PHY_MASK	(1 << 30)
+#define  CLOCK_GATING_BIT_USB0		0
+#define  CLOCK_GATING_BIT_USB1		1
+#define  CLOCK_GATING_BIT_GBE		2
+#define  CLOCK_GATING_BIT_SATA		3
+#define  CLOCK_GATING_BIT_PCIE0		4
+#define  CLOCK_GATING_BIT_PCIE1		5
+#define  CLOCK_GATING_BIT_SDIO0		8
+#define  CLOCK_GATING_BIT_SDIO1		9
+#define  CLOCK_GATING_BIT_NAND		10
+#define  CLOCK_GATING_BIT_CAMERA	11
+#define  CLOCK_GATING_BIT_I2S0		12
+#define  CLOCK_GATING_BIT_I2S1		13
+#define  CLOCK_GATING_BIT_CRYPTO	15
+#define  CLOCK_GATING_BIT_AC97		21
+#define  CLOCK_GATING_BIT_PDMA		22
+#define  CLOCK_GATING_BIT_XOR0		23
+#define  CLOCK_GATING_BIT_XOR1		24
+#define  CLOCK_GATING_BIT_GIGA_PHY	30
+#define  CLOCK_GATING_USB0_MASK		(1 << CLOCK_GATING_BIT_USB0)
+#define  CLOCK_GATING_USB1_MASK		(1 << CLOCK_GATING_BIT_USB1)
+#define  CLOCK_GATING_GBE_MASK		(1 << CLOCK_GATING_BIT_GBE)
+#define  CLOCK_GATING_SATA_MASK		(1 << CLOCK_GATING_BIT_SATA)
+#define  CLOCK_GATING_PCIE0_MASK	(1 << CLOCK_GATING_BIT_PCIE0)
+#define  CLOCK_GATING_PCIE1_MASK	(1 << CLOCK_GATING_BIT_PCIE1)
+#define  CLOCK_GATING_SDIO0_MASK	(1 << CLOCK_GATING_BIT_SDIO0)
+#define  CLOCK_GATING_SDIO1_MASK	(1 << CLOCK_GATING_BIT_SDIO1)
+#define  CLOCK_GATING_NAND_MASK		(1 << CLOCK_GATING_BIT_NAND)
+#define  CLOCK_GATING_CAMERA_MASK	(1 << CLOCK_GATING_BIT_CAMERA)
+#define  CLOCK_GATING_I2S0_MASK		(1 << CLOCK_GATING_BIT_I2S0)
+#define  CLOCK_GATING_I2S1_MASK		(1 << CLOCK_GATING_BIT_I2S1)
+#define  CLOCK_GATING_CRYPTO_MASK	(1 << CLOCK_GATING_BIT_CRYPTO)
+#define  CLOCK_GATING_AC97_MASK		(1 << CLOCK_GATING_BIT_AC97)
+#define  CLOCK_GATING_PDMA_MASK		(1 << CLOCK_GATING_BIT_PDMA)
+#define  CLOCK_GATING_XOR0_MASK		(1 << CLOCK_GATING_BIT_XOR0)
+#define  CLOCK_GATING_XOR1_MASK		(1 << CLOCK_GATING_BIT_XOR1)
+#define  CLOCK_GATING_GIGA_PHY_MASK	(1 << CLOCK_GATING_BIT_GIGA_PHY)
 
 #define PMU_INTERRUPT_CAUSE	(DOVE_PMU_VIRT_BASE + 0x50)
 #define PMU_INTERRUPT_MASK	(DOVE_PMU_VIRT_BASE + 0x54)
diff --git a/arch/arm/mach-dove/irq.c b/arch/arm/mach-dove/irq.c
index 9bc97a5..0877115 100644
--- a/arch/arm/mach-dove/irq.c
+++ b/arch/arm/mach-dove/irq.c
@@ -18,6 +18,7 @@
 #include <asm/mach/irq.h>
 #include <mach/pm.h>
 #include <mach/bridge-regs.h>
+#include <plat/orion-gpio.h>
 #include "common.h"
 
 static void pmu_irq_mask(struct irq_data *d)
@@ -99,19 +100,19 @@ void __init dove_init_irq(void)
 {
 	int i;
 
-	orion_irq_init(0, (void __iomem *)(IRQ_VIRT_BASE + IRQ_MASK_LOW_OFF));
-	orion_irq_init(32, (void __iomem *)(IRQ_VIRT_BASE + IRQ_MASK_HIGH_OFF));
+	orion_irq_init(0, IRQ_VIRT_BASE + IRQ_MASK_LOW_OFF);
+	orion_irq_init(32, IRQ_VIRT_BASE + IRQ_MASK_HIGH_OFF);
 
 	/*
 	 * Initialize gpiolib for GPIOs 0-71.
 	 */
-	orion_gpio_init(NULL, 0, 32, (void __iomem *)DOVE_GPIO_LO_VIRT_BASE, 0,
+	orion_gpio_init(NULL, 0, 32, DOVE_GPIO_LO_VIRT_BASE, 0,
 			IRQ_DOVE_GPIO_START, gpio0_irqs);
 
-	orion_gpio_init(NULL, 32, 32, (void __iomem *)DOVE_GPIO_HI_VIRT_BASE, 0,
+	orion_gpio_init(NULL, 32, 32, DOVE_GPIO_HI_VIRT_BASE, 0,
 			IRQ_DOVE_GPIO_START + 32, gpio1_irqs);
 
-	orion_gpio_init(NULL, 64, 8, (void __iomem *)DOVE_GPIO2_VIRT_BASE, 0,
+	orion_gpio_init(NULL, 64, 8, DOVE_GPIO2_VIRT_BASE, 0,
 			IRQ_DOVE_GPIO_START + 64, gpio2_irqs);
 
 	/*
diff --git a/arch/arm/mach-dove/mpp.c b/arch/arm/mach-dove/mpp.c
index 7f70afc..60bd729 100644
--- a/arch/arm/mach-dove/mpp.c
+++ b/arch/arm/mach-dove/mpp.c
@@ -13,6 +13,7 @@
 #include <linux/io.h>
 #include <plat/mpp.h>
 #include <mach/dove.h>
+#include <plat/orion-gpio.h>
 #include "mpp.h"
 
 struct dove_mpp_grp {
diff --git a/arch/arm/mach-dove/pcie.c b/arch/arm/mach-dove/pcie.c
index 47921b0..bb15b26 100644
--- a/arch/arm/mach-dove/pcie.c
+++ b/arch/arm/mach-dove/pcie.c
@@ -26,9 +26,8 @@ struct pcie_port {
 	u8			root_bus_nr;
 	void __iomem		*base;
 	spinlock_t		conf_lock;
-	char			io_space_name[16];
 	char			mem_space_name[16];
-	struct resource		res[2];
+	struct resource		res;
 };
 
 static struct pcie_port pcie_port[2];
@@ -53,24 +52,10 @@ static int __init dove_pcie_setup(int nr, struct pci_sys_data *sys)
 
 	orion_pcie_setup(pp->base);
 
-	/*
-	 * IORESOURCE_IO
-	 */
-	snprintf(pp->io_space_name, sizeof(pp->io_space_name),
-		 "PCIe %d I/O", pp->index);
-	pp->io_space_name[sizeof(pp->io_space_name) - 1] = 0;
-	pp->res[0].name = pp->io_space_name;
-	if (pp->index == 0) {
-		pp->res[0].start = DOVE_PCIE0_IO_PHYS_BASE;
-		pp->res[0].end = pp->res[0].start + DOVE_PCIE0_IO_SIZE - 1;
-	} else {
-		pp->res[0].start = DOVE_PCIE1_IO_PHYS_BASE;
-		pp->res[0].end = pp->res[0].start + DOVE_PCIE1_IO_SIZE - 1;
-	}
-	pp->res[0].flags = IORESOURCE_IO;
-	if (request_resource(&ioport_resource, &pp->res[0]))
-		panic("Request PCIe IO resource failed\n");
-	pci_add_resource_offset(&sys->resources, &pp->res[0], sys->io_offset);
+	if (pp->index == 0)
+		pci_ioremap_io(sys->busnr * SZ_64K, DOVE_PCIE0_IO_PHYS_BASE);
+	else
+		pci_ioremap_io(sys->busnr * SZ_64K, DOVE_PCIE1_IO_PHYS_BASE);
 
 	/*
 	 * IORESOURCE_MEM
@@ -78,18 +63,18 @@ static int __init dove_pcie_setup(int nr, struct pci_sys_data *sys)
 	snprintf(pp->mem_space_name, sizeof(pp->mem_space_name),
 		 "PCIe %d MEM", pp->index);
 	pp->mem_space_name[sizeof(pp->mem_space_name) - 1] = 0;
-	pp->res[1].name = pp->mem_space_name;
+	pp->res.name = pp->mem_space_name;
 	if (pp->index == 0) {
-		pp->res[1].start = DOVE_PCIE0_MEM_PHYS_BASE;
-		pp->res[1].end = pp->res[1].start + DOVE_PCIE0_MEM_SIZE - 1;
+		pp->res.start = DOVE_PCIE0_MEM_PHYS_BASE;
+		pp->res.end = pp->res.start + DOVE_PCIE0_MEM_SIZE - 1;
 	} else {
-		pp->res[1].start = DOVE_PCIE1_MEM_PHYS_BASE;
-		pp->res[1].end = pp->res[1].start + DOVE_PCIE1_MEM_SIZE - 1;
+		pp->res.start = DOVE_PCIE1_MEM_PHYS_BASE;
+		pp->res.end = pp->res.start + DOVE_PCIE1_MEM_SIZE - 1;
 	}
-	pp->res[1].flags = IORESOURCE_MEM;
-	if (request_resource(&iomem_resource, &pp->res[1]))
+	pp->res.flags = IORESOURCE_MEM;
+	if (request_resource(&iomem_resource, &pp->res))
 		panic("Request PCIe Memory resource failed\n");
-	pci_add_resource_offset(&sys->resources, &pp->res[1], sys->mem_offset);
+	pci_add_resource_offset(&sys->resources, &pp->res, sys->mem_offset);
 
 	return 1;
 }
@@ -197,20 +182,20 @@ static struct hw_pci dove_pci __initdata = {
 	.map_irq	= dove_pcie_map_irq,
 };
 
-static void __init add_pcie_port(int index, unsigned long base)
+static void __init add_pcie_port(int index, void __iomem *base)
 {
 	printk(KERN_INFO "Dove PCIe port %d: ", index);
 
-	if (orion_pcie_link_up((void __iomem *)base)) {
+	if (orion_pcie_link_up(base)) {
 		struct pcie_port *pp = &pcie_port[num_pcie_ports++];
 
 		printk(KERN_INFO "link up\n");
 
 		pp->index = index;
 		pp->root_bus_nr = -1;
-		pp->base = (void __iomem *)base;
+		pp->base = base;
 		spin_lock_init(&pp->conf_lock);
-		memset(pp->res, 0, sizeof(pp->res));
+		memset(&pp->res, 0, sizeof(pp->res));
 	} else {
 		printk(KERN_INFO "link down, ignoring\n");
 	}
diff --git a/arch/arm/mach-ebsa110/Makefile b/arch/arm/mach-ebsa110/Makefile
index 6520ac8..935e4af 100644
--- a/arch/arm/mach-ebsa110/Makefile
+++ b/arch/arm/mach-ebsa110/Makefile
@@ -4,9 +4,7 @@
 
 # Object file lists.
 
-obj-y			:= core.o io.o
+obj-y			:= core.o io.o leds.o
 obj-m			:=
 obj-n			:=
 obj-			:=
-
-obj-$(CONFIG_LEDS)	+= leds.o
diff --git a/arch/arm/mach-ebsa110/core.c b/arch/arm/mach-ebsa110/core.c
index 6f80686..f0fe6b5 100644
--- a/arch/arm/mach-ebsa110/core.c
+++ b/arch/arm/mach-ebsa110/core.c
@@ -74,22 +74,22 @@ static struct map_desc ebsa110_io_desc[] __initdata = {
 	 * sparse external-decode ISAIO space
 	 */
 	{	/* IRQ_STAT/IRQ_MCLR */
-		.virtual	= IRQ_STAT,
+		.virtual	= (unsigned long)IRQ_STAT,
 		.pfn		= __phys_to_pfn(TRICK4_PHYS),
 		.length		= TRICK4_SIZE,
 		.type		= MT_DEVICE
 	}, {	/* IRQ_MASK/IRQ_MSET */
-		.virtual	= IRQ_MASK,
+		.virtual	= (unsigned long)IRQ_MASK,
 		.pfn		= __phys_to_pfn(TRICK3_PHYS),
 		.length		= TRICK3_SIZE,
 		.type		= MT_DEVICE
 	}, {	/* SOFT_BASE */
-		.virtual	= SOFT_BASE,
+		.virtual	= (unsigned long)SOFT_BASE,
 		.pfn		= __phys_to_pfn(TRICK1_PHYS),
 		.length		= TRICK1_SIZE,
 		.type		= MT_DEVICE
 	}, {	/* PIT_BASE */
-		.virtual	= PIT_BASE,
+		.virtual	= (unsigned long)PIT_BASE,
 		.pfn		= __phys_to_pfn(TRICK0_PHYS),
 		.length		= TRICK0_SIZE,
 		.type		= MT_DEVICE
diff --git a/arch/arm/mach-ebsa110/core.h b/arch/arm/mach-ebsa110/core.h
index c93c9e4..afe137e 100644
--- a/arch/arm/mach-ebsa110/core.h
+++ b/arch/arm/mach-ebsa110/core.h
@@ -31,11 +31,11 @@
 #define TRICK7_PHYS		0xf3c00000
 
 /* Virtual addresses */
-#define PIT_BASE		0xfc000000	/* trick 0 */
-#define SOFT_BASE		0xfd000000	/* trick 1 */
-#define IRQ_MASK		0xfe000000	/* trick 3 - read */
-#define IRQ_MSET		0xfe000000	/* trick 3 - write */
-#define IRQ_STAT		0xff000000	/* trick 4 - read */
-#define IRQ_MCLR		0xff000000	/* trick 4 - write */
+#define PIT_BASE		IOMEM(0xfc000000)	/* trick 0 */
+#define SOFT_BASE		IOMEM(0xfd000000)	/* trick 1 */
+#define IRQ_MASK		IOMEM(0xfe000000)	/* trick 3 - read */
+#define IRQ_MSET		IOMEM(0xfe000000)	/* trick 3 - write */
+#define IRQ_STAT		IOMEM(0xff000000)	/* trick 4 - read */
+#define IRQ_MCLR		IOMEM(0xff000000)	/* trick 4 - write */
 
 #endif
diff --git a/arch/arm/mach-ebsa110/leds.c b/arch/arm/mach-ebsa110/leds.c
index 99e14e3..0398258 100644
--- a/arch/arm/mach-ebsa110/leds.c
+++ b/arch/arm/mach-ebsa110/leds.c
@@ -1,52 +1,71 @@
 /*
- *  linux/arch/arm/mach-ebsa110/leds.c
+ * Driver for the LED found on the EBSA110 machine
+ * Based on Versatile and RealView machine LED code
  *
- *  Copyright (C) 1998 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- *  EBSA-110 LED control routines.  We use the led as follows:
- *
- *   - Red - toggles state every 50 timer interrupts
+ * License terms: GNU General Public License (GPL) version 2
+ * Author: Bryan Wu <bryan.wu@canonical.com>
  */
-#include <linux/module.h>
-#include <linux/spinlock.h>
+#include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/leds.h>
 
-#include <mach/hardware.h>
-#include <asm/leds.h>
 #include <asm/mach-types.h>
 
 #include "core.h"
 
-static spinlock_t leds_lock;
-
-static void ebsa110_leds_event(led_event_t ledevt)
+#if defined(CONFIG_NEW_LEDS) && defined(CONFIG_LEDS_CLASS)
+static void ebsa110_led_set(struct led_classdev *cdev,
+			      enum led_brightness b)
 {
-	unsigned long flags;
+	u8 reg = __raw_readb(SOFT_BASE);
 
-	spin_lock_irqsave(&leds_lock, flags);
+	if (b != LED_OFF)
+		reg |= 0x80;
+	else
+		reg &= ~0x80;
 
-	switch(ledevt) {
-	case led_timer:
-		*(volatile unsigned char *)SOFT_BASE ^= 128;
-		break;
+	__raw_writeb(reg, SOFT_BASE);
+}
 
-	default:
-		break;
-	}
+static enum led_brightness ebsa110_led_get(struct led_classdev *cdev)
+{
+	u8 reg = __raw_readb(SOFT_BASE);
 
-	spin_unlock_irqrestore(&leds_lock, flags);
+	return (reg & 0x80) ? LED_FULL : LED_OFF;
 }
 
-static int __init leds_init(void)
+static int __init ebsa110_leds_init(void)
 {
-	if (machine_is_ebsa110())
-		leds_event = ebsa110_leds_event;
+
+	struct led_classdev *cdev;
+	int ret;
+
+	if (!machine_is_ebsa110())
+		return -ENODEV;
+
+	cdev = kzalloc(sizeof(*cdev), GFP_KERNEL);
+	if (!cdev)
+		return -ENOMEM;
+
+	cdev->name = "ebsa110:0";
+	cdev->brightness_set = ebsa110_led_set;
+	cdev->brightness_get = ebsa110_led_get;
+	cdev->default_trigger = "heartbeat";
+
+	ret = led_classdev_register(NULL, cdev);
+	if (ret	< 0) {
+		kfree(cdev);
+		return ret;
+	}
 
 	return 0;
 }
 
-__initcall(leds_init);
+/*
+ * Since we may have triggers on any subsystem, defer registration
+ * until after subsystem_init.
+ */
+fs_initcall(ebsa110_leds_init);
+#endif
diff --git a/arch/arm/mach-ep93xx/adssphere.c b/arch/arm/mach-ep93xx/adssphere.c
index a472777..41383bf 100644
--- a/arch/arm/mach-ep93xx/adssphere.c
+++ b/arch/arm/mach-ep93xx/adssphere.c
@@ -13,6 +13,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
+#include <linux/sizes.h>
 
 #include <mach/hardware.h>
 
diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c
index 4afe52a..e85bf17 100644
--- a/arch/arm/mach-ep93xx/core.c
+++ b/arch/arm/mach-ep93xx/core.c
@@ -36,9 +36,9 @@
 #include <linux/export.h>
 
 #include <mach/hardware.h>
-#include <mach/fb.h>
-#include <mach/ep93xx_keypad.h>
-#include <mach/ep93xx_spi.h>
+#include <linux/platform_data/video-ep93xx.h>
+#include <linux/platform_data/keypad-ep93xx.h>
+#include <linux/platform_data/spi-ep93xx.h>
 #include <mach/gpio-ep93xx.h>
 
 #include <asm/mach/map.h>
diff --git a/arch/arm/mach-ep93xx/dma.c b/arch/arm/mach-ep93xx/dma.c
index 16976d7..d8bfd02 100644
--- a/arch/arm/mach-ep93xx/dma.c
+++ b/arch/arm/mach-ep93xx/dma.c
@@ -25,7 +25,7 @@
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 
-#include <mach/dma.h>
+#include <linux/platform_data/dma-ep93xx.h>
 #include <mach/hardware.h>
 
 #include "soc.h"
diff --git a/arch/arm/mach-ep93xx/edb93xx.c b/arch/arm/mach-ep93xx/edb93xx.c
index 337ab7c..b8f53d5 100644
--- a/arch/arm/mach-ep93xx/edb93xx.c
+++ b/arch/arm/mach-ep93xx/edb93xx.c
@@ -35,8 +35,8 @@
 #include <sound/cs4271.h>
 
 #include <mach/hardware.h>
-#include <mach/fb.h>
-#include <mach/ep93xx_spi.h>
+#include <linux/platform_data/video-ep93xx.h>
+#include <linux/platform_data/spi-ep93xx.h>
 #include <mach/gpio-ep93xx.h>
 
 #include <asm/hardware/vic.h>
diff --git a/arch/arm/mach-ep93xx/gesbc9312.c b/arch/arm/mach-ep93xx/gesbc9312.c
index 437c341..7fd705b 100644
--- a/arch/arm/mach-ep93xx/gesbc9312.c
+++ b/arch/arm/mach-ep93xx/gesbc9312.c
@@ -13,6 +13,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
+#include <linux/sizes.h>
 
 #include <mach/hardware.h>
 
diff --git a/arch/arm/mach-ep93xx/include/mach/dma.h b/arch/arm/mach-ep93xx/include/mach/dma.h
deleted file mode 100644
index e82c642..0000000
--- a/arch/arm/mach-ep93xx/include/mach/dma.h
+++ /dev/null
@@ -1,93 +0,0 @@
-#ifndef __ASM_ARCH_DMA_H
-#define __ASM_ARCH_DMA_H
-
-#include <linux/types.h>
-#include <linux/dmaengine.h>
-#include <linux/dma-mapping.h>
-
-/*
- * M2P channels.
- *
- * Note that these values are also directly used for setting the PPALLOC
- * register.
- */
-#define EP93XX_DMA_I2S1		0
-#define EP93XX_DMA_I2S2		1
-#define EP93XX_DMA_AAC1		2
-#define EP93XX_DMA_AAC2		3
-#define EP93XX_DMA_AAC3		4
-#define EP93XX_DMA_I2S3		5
-#define EP93XX_DMA_UART1	6
-#define EP93XX_DMA_UART2	7
-#define EP93XX_DMA_UART3	8
-#define EP93XX_DMA_IRDA		9
-/* M2M channels */
-#define EP93XX_DMA_SSP		10
-#define EP93XX_DMA_IDE		11
-
-/**
- * struct ep93xx_dma_data - configuration data for the EP93xx dmaengine
- * @port: peripheral which is requesting the channel
- * @direction: TX/RX channel
- * @name: optional name for the channel, this is displayed in /proc/interrupts
- *
- * This information is passed as private channel parameter in a filter
- * function. Note that this is only needed for slave/cyclic channels.  For
- * memcpy channels %NULL data should be passed.
- */
-struct ep93xx_dma_data {
-	int				port;
-	enum dma_transfer_direction	direction;
-	const char			*name;
-};
-
-/**
- * struct ep93xx_dma_chan_data - platform specific data for a DMA channel
- * @name: name of the channel, used for getting the right clock for the channel
- * @base: mapped registers
- * @irq: interrupt number used by this channel
- */
-struct ep93xx_dma_chan_data {
-	const char			*name;
-	void __iomem			*base;
-	int				irq;
-};
-
-/**
- * struct ep93xx_dma_platform_data - platform data for the dmaengine driver
- * @channels: array of channels which are passed to the driver
- * @num_channels: number of channels in the array
- *
- * This structure is passed to the DMA engine driver via platform data. For
- * M2P channels, contract is that even channels are for TX and odd for RX.
- * There is no requirement for the M2M channels.
- */
-struct ep93xx_dma_platform_data {
-	struct ep93xx_dma_chan_data	*channels;
-	size_t				num_channels;
-};
-
-static inline bool ep93xx_dma_chan_is_m2p(struct dma_chan *chan)
-{
-	return !strcmp(dev_name(chan->device->dev), "ep93xx-dma-m2p");
-}
-
-/**
- * ep93xx_dma_chan_direction - returns direction the channel can be used
- * @chan: channel
- *
- * This function can be used in filter functions to find out whether the
- * channel supports given DMA direction. Only M2P channels have such
- * limitation, for M2M channels the direction is configurable.
- */
-static inline enum dma_transfer_direction
-ep93xx_dma_chan_direction(struct dma_chan *chan)
-{
-	if (!ep93xx_dma_chan_is_m2p(chan))
-		return DMA_NONE;
-
-	/* even channels are for TX, odd for RX */
-	return (chan->chan_id % 2 == 0) ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM;
-}
-
-#endif /* __ASM_ARCH_DMA_H */
diff --git a/arch/arm/mach-ep93xx/include/mach/ep93xx_keypad.h b/arch/arm/mach-ep93xx/include/mach/ep93xx_keypad.h
deleted file mode 100644
index 1e2f4e9..0000000
--- a/arch/arm/mach-ep93xx/include/mach/ep93xx_keypad.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * arch/arm/mach-ep93xx/include/mach/ep93xx_keypad.h
- */
-
-#ifndef __ASM_ARCH_EP93XX_KEYPAD_H
-#define __ASM_ARCH_EP93XX_KEYPAD_H
-
-struct matrix_keymap_data;
-
-/* flags for the ep93xx_keypad driver */
-#define EP93XX_KEYPAD_DISABLE_3_KEY	(1<<0)	/* disable 3-key reset */
-#define EP93XX_KEYPAD_DIAG_MODE		(1<<1)	/* diagnostic mode */
-#define EP93XX_KEYPAD_BACK_DRIVE	(1<<2)	/* back driving mode */
-#define EP93XX_KEYPAD_TEST_MODE		(1<<3)	/* scan only column 0 */
-#define EP93XX_KEYPAD_KDIV		(1<<4)	/* 1/4 clock or 1/16 clock */
-#define EP93XX_KEYPAD_AUTOREPEAT	(1<<5)	/* enable key autorepeat */
-
-/**
- * struct ep93xx_keypad_platform_data - platform specific device structure
- * @keymap_data:	pointer to &matrix_keymap_data
- * @debounce:		debounce start count; terminal count is 0xff
- * @prescale:		row/column counter pre-scaler load value
- * @flags:		see above
- */
-struct ep93xx_keypad_platform_data {
-	struct matrix_keymap_data *keymap_data;
-	unsigned int	debounce;
-	unsigned int	prescale;
-	unsigned int	flags;
-};
-
-#define EP93XX_MATRIX_ROWS		(8)
-#define EP93XX_MATRIX_COLS		(8)
-
-#endif	/* __ASM_ARCH_EP93XX_KEYPAD_H */
diff --git a/arch/arm/mach-ep93xx/include/mach/ep93xx_spi.h b/arch/arm/mach-ep93xx/include/mach/ep93xx_spi.h
deleted file mode 100644
index 9bb63ac..0000000
--- a/arch/arm/mach-ep93xx/include/mach/ep93xx_spi.h
+++ /dev/null
@@ -1,29 +0,0 @@
-#ifndef __ASM_MACH_EP93XX_SPI_H
-#define __ASM_MACH_EP93XX_SPI_H
-
-struct spi_device;
-
-/**
- * struct ep93xx_spi_info - EP93xx specific SPI descriptor
- * @num_chipselect: number of chip selects on this board, must be
- *                  at least one
- * @use_dma: use DMA for the transfers
- */
-struct ep93xx_spi_info {
-	int	num_chipselect;
-	bool	use_dma;
-};
-
-/**
- * struct ep93xx_spi_chip_ops - operation callbacks for SPI slave device
- * @setup: setup the chip select mechanism
- * @cleanup: cleanup the chip select mechanism
- * @cs_control: control the device chip select
- */
-struct ep93xx_spi_chip_ops {
-	int	(*setup)(struct spi_device *spi);
-	void	(*cleanup)(struct spi_device *spi);
-	void	(*cs_control)(struct spi_device *spi, int value);
-};
-
-#endif /* __ASM_MACH_EP93XX_SPI_H */
diff --git a/arch/arm/mach-ep93xx/include/mach/fb.h b/arch/arm/mach-ep93xx/include/mach/fb.h
deleted file mode 100644
index d5ae11d..0000000
--- a/arch/arm/mach-ep93xx/include/mach/fb.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * arch/arm/mach-ep93xx/include/mach/fb.h
- */
-
-#ifndef __ASM_ARCH_EP93XXFB_H
-#define __ASM_ARCH_EP93XXFB_H
-
-struct platform_device;
-struct fb_videomode;
-struct fb_info;
-
-#define EP93XXFB_USE_MODEDB		0
-
-/* VideoAttributes flags */
-#define EP93XXFB_STATE_MACHINE_ENABLE	(1 << 0)
-#define EP93XXFB_PIXEL_CLOCK_ENABLE	(1 << 1)
-#define EP93XXFB_VSYNC_ENABLE		(1 << 2)
-#define EP93XXFB_PIXEL_DATA_ENABLE	(1 << 3)
-#define EP93XXFB_COMPOSITE_SYNC		(1 << 4)
-#define EP93XXFB_SYNC_VERT_HIGH		(1 << 5)
-#define EP93XXFB_SYNC_HORIZ_HIGH	(1 << 6)
-#define EP93XXFB_SYNC_BLANK_HIGH	(1 << 7)
-#define EP93XXFB_PCLK_FALLING		(1 << 8)
-#define EP93XXFB_ENABLE_AC		(1 << 9)
-#define EP93XXFB_ENABLE_LCD		(1 << 10)
-#define EP93XXFB_ENABLE_CCIR		(1 << 12)
-#define EP93XXFB_USE_PARALLEL_INTERFACE	(1 << 13)
-#define EP93XXFB_ENABLE_INTERRUPT	(1 << 14)
-#define EP93XXFB_USB_INTERLACE		(1 << 16)
-#define EP93XXFB_USE_EQUALIZATION	(1 << 17)
-#define EP93XXFB_USE_DOUBLE_HORZ	(1 << 18)
-#define EP93XXFB_USE_DOUBLE_VERT	(1 << 19)
-#define EP93XXFB_USE_BLANK_PIXEL	(1 << 20)
-#define EP93XXFB_USE_SDCSN0		(0 << 21)
-#define EP93XXFB_USE_SDCSN1		(1 << 21)
-#define EP93XXFB_USE_SDCSN2		(2 << 21)
-#define EP93XXFB_USE_SDCSN3		(3 << 21)
-
-#define EP93XXFB_ENABLE			(EP93XXFB_STATE_MACHINE_ENABLE	| \
-					 EP93XXFB_PIXEL_CLOCK_ENABLE	| \
-					 EP93XXFB_VSYNC_ENABLE		| \
-					 EP93XXFB_PIXEL_DATA_ENABLE)
-
-struct ep93xxfb_mach_info {
-	unsigned int			num_modes;
-	const struct fb_videomode	*modes;
-	const struct fb_videomode	*default_mode;
-	int				bpp;
-	unsigned int			flags;
-
-	int	(*setup)(struct platform_device *pdev);
-	void	(*teardown)(struct platform_device *pdev);
-	void	(*blank)(int blank_mode, struct fb_info *info);
-};
-
-#endif /* __ASM_ARCH_EP93XXFB_H */
diff --git a/arch/arm/mach-ep93xx/include/mach/gpio.h b/arch/arm/mach-ep93xx/include/mach/gpio.h
deleted file mode 100644
index 40a8c17..0000000
--- a/arch/arm/mach-ep93xx/include/mach/gpio.h
+++ /dev/null
@@ -1 +0,0 @@
-/* empty */
diff --git a/arch/arm/mach-ep93xx/include/mach/ts72xx.h b/arch/arm/mach-ep93xx/include/mach/ts72xx.h
deleted file mode 100644
index f1397a1..0000000
--- a/arch/arm/mach-ep93xx/include/mach/ts72xx.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * arch/arm/mach-ep93xx/include/mach/ts72xx.h
- */
-
-/*
- * TS72xx memory map:
- *
- * virt		phys		size
- * febff000	22000000	4K	model number register (bits 0-2)
- * febfe000	22400000	4K	options register
- * febfd000	22800000	4K	options register #2
- * febf9000	10800000	4K	TS-5620 RTC index register
- * febf8000	11700000	4K	TS-5620 RTC data register
- */
-
-#define TS72XX_MODEL_PHYS_BASE		0x22000000
-#define TS72XX_MODEL_VIRT_BASE		0xfebff000
-#define TS72XX_MODEL_SIZE		0x00001000
-
-#define TS72XX_MODEL_TS7200		0x00
-#define TS72XX_MODEL_TS7250		0x01
-#define TS72XX_MODEL_TS7260		0x02
-#define TS72XX_MODEL_TS7300		0x03
-#define TS72XX_MODEL_TS7400		0x04
-#define TS72XX_MODEL_MASK		0x07
-
-
-#define TS72XX_OPTIONS_PHYS_BASE	0x22400000
-#define TS72XX_OPTIONS_VIRT_BASE	0xfebfe000
-#define TS72XX_OPTIONS_SIZE		0x00001000
-
-#define TS72XX_OPTIONS_COM2_RS485	0x02
-#define TS72XX_OPTIONS_MAX197		0x01
-
-
-#define TS72XX_OPTIONS2_PHYS_BASE	0x22800000
-#define TS72XX_OPTIONS2_VIRT_BASE	0xfebfd000
-#define TS72XX_OPTIONS2_SIZE		0x00001000
-
-#define TS72XX_OPTIONS2_TS9420		0x04
-#define TS72XX_OPTIONS2_TS9420_BOOT	0x02
-
-
-#define TS72XX_RTC_INDEX_VIRT_BASE	0xfebf9000
-#define TS72XX_RTC_INDEX_PHYS_BASE	0x10800000
-#define TS72XX_RTC_INDEX_SIZE		0x00001000
-
-#define TS72XX_RTC_DATA_VIRT_BASE	0xfebf8000
-#define TS72XX_RTC_DATA_PHYS_BASE	0x11700000
-#define TS72XX_RTC_DATA_SIZE		0x00001000
-
-#define TS72XX_WDT_CONTROL_PHYS_BASE	0x23800000
-#define TS72XX_WDT_FEED_PHYS_BASE	0x23c00000
-
-#ifndef __ASSEMBLY__
-
-static inline int ts72xx_model(void)
-{
-	return __raw_readb(TS72XX_MODEL_VIRT_BASE) & TS72XX_MODEL_MASK;
-}
-
-static inline int board_is_ts7200(void)
-{
-	return ts72xx_model() == TS72XX_MODEL_TS7200;
-}
-
-static inline int board_is_ts7250(void)
-{
-	return ts72xx_model() == TS72XX_MODEL_TS7250;
-}
-
-static inline int board_is_ts7260(void)
-{
-	return ts72xx_model() == TS72XX_MODEL_TS7260;
-}
-
-static inline int board_is_ts7300(void)
-{
-	return ts72xx_model()  == TS72XX_MODEL_TS7300;
-}
-
-static inline int board_is_ts7400(void)
-{
-	return ts72xx_model() == TS72XX_MODEL_TS7400;
-}
-
-static inline int is_max197_installed(void)
-{
-	return !!(__raw_readb(TS72XX_OPTIONS_VIRT_BASE) &
-					TS72XX_OPTIONS_MAX197);
-}
-
-static inline int is_ts9420_installed(void)
-{
-	return !!(__raw_readb(TS72XX_OPTIONS2_VIRT_BASE) &
-					TS72XX_OPTIONS2_TS9420);
-}
-#endif
diff --git a/arch/arm/mach-ep93xx/simone.c b/arch/arm/mach-ep93xx/simone.c
index 33dc079..0eb3f17 100644
--- a/arch/arm/mach-ep93xx/simone.c
+++ b/arch/arm/mach-ep93xx/simone.c
@@ -22,7 +22,7 @@
 #include <linux/i2c-gpio.h>
 
 #include <mach/hardware.h>
-#include <mach/fb.h>
+#include <linux/platform_data/video-ep93xx.h>
 #include <mach/gpio-ep93xx.h>
 
 #include <asm/hardware/vic.h>
diff --git a/arch/arm/mach-ep93xx/snappercl15.c b/arch/arm/mach-ep93xx/snappercl15.c
index 01abd35..50043ee 100644
--- a/arch/arm/mach-ep93xx/snappercl15.c
+++ b/arch/arm/mach-ep93xx/snappercl15.c
@@ -28,7 +28,7 @@
 #include <linux/mtd/nand.h>
 
 #include <mach/hardware.h>
-#include <mach/fb.h>
+#include <linux/platform_data/video-ep93xx.h>
 #include <mach/gpio-ep93xx.h>
 
 #include <asm/hardware/vic.h>
diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c
index 75cab2d..3c4c233 100644
--- a/arch/arm/mach-ep93xx/ts72xx.c
+++ b/arch/arm/mach-ep93xx/ts72xx.c
@@ -21,7 +21,6 @@
 #include <linux/mtd/partitions.h>
 
 #include <mach/hardware.h>
-#include <mach/ts72xx.h>
 
 #include <asm/hardware/vic.h>
 #include <asm/mach-types.h>
@@ -29,30 +28,31 @@
 #include <asm/mach/arch.h>
 
 #include "soc.h"
+#include "ts72xx.h"
 
 static struct map_desc ts72xx_io_desc[] __initdata = {
 	{
-		.virtual	= TS72XX_MODEL_VIRT_BASE,
+		.virtual	= (unsigned long)TS72XX_MODEL_VIRT_BASE,
 		.pfn		= __phys_to_pfn(TS72XX_MODEL_PHYS_BASE),
 		.length		= TS72XX_MODEL_SIZE,
 		.type		= MT_DEVICE,
 	}, {
-		.virtual	= TS72XX_OPTIONS_VIRT_BASE,
+		.virtual	= (unsigned long)TS72XX_OPTIONS_VIRT_BASE,
 		.pfn		= __phys_to_pfn(TS72XX_OPTIONS_PHYS_BASE),
 		.length		= TS72XX_OPTIONS_SIZE,
 		.type		= MT_DEVICE,
 	}, {
-		.virtual	= TS72XX_OPTIONS2_VIRT_BASE,
+		.virtual	= (unsigned long)TS72XX_OPTIONS2_VIRT_BASE,
 		.pfn		= __phys_to_pfn(TS72XX_OPTIONS2_PHYS_BASE),
 		.length		= TS72XX_OPTIONS2_SIZE,
 		.type		= MT_DEVICE,
 	}, {
-		.virtual	= TS72XX_RTC_INDEX_VIRT_BASE,
+		.virtual	= (unsigned long)TS72XX_RTC_INDEX_VIRT_BASE,
 		.pfn		= __phys_to_pfn(TS72XX_RTC_INDEX_PHYS_BASE),
 		.length		= TS72XX_RTC_INDEX_SIZE,
 		.type		= MT_DEVICE,
 	}, {
-		.virtual	= TS72XX_RTC_DATA_VIRT_BASE,
+		.virtual	= (unsigned long)TS72XX_RTC_DATA_VIRT_BASE,
 		.pfn		= __phys_to_pfn(TS72XX_RTC_DATA_PHYS_BASE),
 		.length		= TS72XX_RTC_DATA_SIZE,
 		.type		= MT_DEVICE,
diff --git a/arch/arm/mach-ep93xx/ts72xx.h b/arch/arm/mach-ep93xx/ts72xx.h
new file mode 100644
index 0000000..071feaa
--- /dev/null
+++ b/arch/arm/mach-ep93xx/ts72xx.h
@@ -0,0 +1,98 @@
+/*
+ * arch/arm/mach-ep93xx/include/mach/ts72xx.h
+ */
+
+/*
+ * TS72xx memory map:
+ *
+ * virt		phys		size
+ * febff000	22000000	4K	model number register (bits 0-2)
+ * febfe000	22400000	4K	options register
+ * febfd000	22800000	4K	options register #2
+ * febf9000	10800000	4K	TS-5620 RTC index register
+ * febf8000	11700000	4K	TS-5620 RTC data register
+ */
+
+#define TS72XX_MODEL_PHYS_BASE		0x22000000
+#define TS72XX_MODEL_VIRT_BASE		IOMEM(0xfebff000)
+#define TS72XX_MODEL_SIZE		0x00001000
+
+#define TS72XX_MODEL_TS7200		0x00
+#define TS72XX_MODEL_TS7250		0x01
+#define TS72XX_MODEL_TS7260		0x02
+#define TS72XX_MODEL_TS7300		0x03
+#define TS72XX_MODEL_TS7400		0x04
+#define TS72XX_MODEL_MASK		0x07
+
+
+#define TS72XX_OPTIONS_PHYS_BASE	0x22400000
+#define TS72XX_OPTIONS_VIRT_BASE	IOMEM(0xfebfe000)
+#define TS72XX_OPTIONS_SIZE		0x00001000
+
+#define TS72XX_OPTIONS_COM2_RS485	0x02
+#define TS72XX_OPTIONS_MAX197		0x01
+
+
+#define TS72XX_OPTIONS2_PHYS_BASE	0x22800000
+#define TS72XX_OPTIONS2_VIRT_BASE	IOMEM(0xfebfd000)
+#define TS72XX_OPTIONS2_SIZE		0x00001000
+
+#define TS72XX_OPTIONS2_TS9420		0x04
+#define TS72XX_OPTIONS2_TS9420_BOOT	0x02
+
+
+#define TS72XX_RTC_INDEX_VIRT_BASE	IOMEM(0xfebf9000)
+#define TS72XX_RTC_INDEX_PHYS_BASE	0x10800000
+#define TS72XX_RTC_INDEX_SIZE		0x00001000
+
+#define TS72XX_RTC_DATA_VIRT_BASE	IOMEM(0xfebf8000)
+#define TS72XX_RTC_DATA_PHYS_BASE	0x11700000
+#define TS72XX_RTC_DATA_SIZE		0x00001000
+
+#define TS72XX_WDT_CONTROL_PHYS_BASE	0x23800000
+#define TS72XX_WDT_FEED_PHYS_BASE	0x23c00000
+
+#ifndef __ASSEMBLY__
+
+static inline int ts72xx_model(void)
+{
+	return __raw_readb(TS72XX_MODEL_VIRT_BASE) & TS72XX_MODEL_MASK;
+}
+
+static inline int board_is_ts7200(void)
+{
+	return ts72xx_model() == TS72XX_MODEL_TS7200;
+}
+
+static inline int board_is_ts7250(void)
+{
+	return ts72xx_model() == TS72XX_MODEL_TS7250;
+}
+
+static inline int board_is_ts7260(void)
+{
+	return ts72xx_model() == TS72XX_MODEL_TS7260;
+}
+
+static inline int board_is_ts7300(void)
+{
+	return ts72xx_model()  == TS72XX_MODEL_TS7300;
+}
+
+static inline int board_is_ts7400(void)
+{
+	return ts72xx_model() == TS72XX_MODEL_TS7400;
+}
+
+static inline int is_max197_installed(void)
+{
+	return !!(__raw_readb(TS72XX_OPTIONS_VIRT_BASE) &
+					TS72XX_OPTIONS_MAX197);
+}
+
+static inline int is_ts9420_installed(void)
+{
+	return !!(__raw_readb(TS72XX_OPTIONS2_VIRT_BASE) &
+					TS72XX_OPTIONS2_TS9420);
+}
+#endif
diff --git a/arch/arm/mach-ep93xx/vision_ep9307.c b/arch/arm/mach-ep93xx/vision_ep9307.c
index 2905a49..ba92e25 100644
--- a/arch/arm/mach-ep93xx/vision_ep9307.c
+++ b/arch/arm/mach-ep93xx/vision_ep9307.c
@@ -30,8 +30,8 @@
 #include <linux/mmc/host.h>
 
 #include <mach/hardware.h>
-#include <mach/fb.h>
-#include <mach/ep93xx_spi.h>
+#include <linux/platform_data/video-ep93xx.h>
+#include <linux/platform_data/spi-ep93xx.h>
 #include <mach/gpio-ep93xx.h>
 
 #include <asm/hardware/vic.h>
diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig
index b5b4c8c..4372075 100644
--- a/arch/arm/mach-exynos/Kconfig
+++ b/arch/arm/mach-exynos/Kconfig
@@ -221,6 +221,7 @@ config MACH_SMDKV310
 	select EXYNOS4_SETUP_KEYPAD
 	select EXYNOS4_SETUP_SDHCI
 	select EXYNOS4_SETUP_USB_PHY
+	select S3C24XX_PWM
 	help
 	  Machine support for Samsung SMDKV310
 
@@ -348,6 +349,7 @@ config MACH_ORIGEN
 	select EXYNOS4_SETUP_FIMD0
 	select EXYNOS4_SETUP_SDHCI
 	select EXYNOS4_SETUP_USB_PHY
+	select S3C24XX_PWM
 	help
 	  Machine support for ORIGEN based on Samsung EXYNOS4210
 
@@ -383,6 +385,7 @@ config MACH_SMDK4212
 	select EXYNOS4_SETUP_KEYPAD
 	select EXYNOS4_SETUP_SDHCI
 	select EXYNOS4_SETUP_USB_PHY
+	select S3C24XX_PWM
 	help
 	  Machine support for Samsung SMDK4212
 
@@ -405,6 +408,8 @@ config MACH_EXYNOS4_DT
 	select USE_OF
 	select ARM_AMBA
 	select HAVE_SAMSUNG_KEYPAD if INPUT_KEYBOARD
+	select PINCTRL
+	select PINCTRL_EXYNOS4
 	help
 	  Machine support for Samsung Exynos4 machine with device tree enabled.
 	  Select this if a fdt blob is available for the Exynos4 SoC based board.
@@ -418,8 +423,8 @@ config MACH_EXYNOS5_DT
 	select USE_OF
 	select ARM_AMBA
 	help
-	  Machine support for Samsung Exynos4 machine with device tree enabled.
-	  Select this if a fdt blob is available for the EXYNOS4 SoC based board.
+	  Machine support for Samsung EXYNOS5 machine with device tree enabled.
+	  Select this if a fdt blob is available for the EXYNOS5 SoC based board.
 
 if ARCH_EXYNOS4
 
diff --git a/arch/arm/mach-exynos/Makefile.boot b/arch/arm/mach-exynos/Makefile.boot
index 31bd181..b9862e2 100644
--- a/arch/arm/mach-exynos/Makefile.boot
+++ b/arch/arm/mach-exynos/Makefile.boot
@@ -1,5 +1,2 @@
    zreladdr-y	+= 0x40008000
 params_phys-y	:= 0x40000100
-
-dtb-$(CONFIG_MACH_EXYNOS4_DT) += exynos4210-origen.dtb exynos4210-smdkv310.dtb
-dtb-$(CONFIG_MACH_EXYNOS5_DT) += exynos5250-smdk5250.dtb
diff --git a/arch/arm/mach-exynos/clock-exynos4.c b/arch/arm/mach-exynos/clock-exynos4.c
index 2f51293..6a45c9a 100644
--- a/arch/arm/mach-exynos/clock-exynos4.c
+++ b/arch/arm/mach-exynos/clock-exynos4.c
@@ -501,6 +501,10 @@ static struct clk exynos4_init_clocks_off[] = {
 		.enable		= exynos4_clk_ip_cam_ctrl,
 		.ctrlbit	= (1 << 3),
 	}, {
+		.name		= "tsi",
+		.enable		= exynos4_clk_ip_fsys_ctrl,
+		.ctrlbit	= (1 << 4),
+	}, {
 		.name		= "hsmmc",
 		.devname	= "exynos4-sdhci.0",
 		.parent		= &exynos4_clk_aclk_133.clk,
@@ -530,6 +534,14 @@ static struct clk exynos4_init_clocks_off[] = {
 		.enable		= exynos4_clk_ip_fsys_ctrl,
 		.ctrlbit	= (1 << 9),
 	}, {
+		.name		= "onenand",
+		.enable		= exynos4_clk_ip_fsys_ctrl,
+		.ctrlbit	= (1 << 15),
+	}, {
+		.name		= "nfcon",
+		.enable		= exynos4_clk_ip_fsys_ctrl,
+		.ctrlbit	= (1 << 16),
+	}, {
 		.name		= "dac",
 		.devname	= "s5p-sdo",
 		.enable		= exynos4_clk_ip_tv_ctrl,
@@ -615,6 +627,25 @@ static struct clk exynos4_init_clocks_off[] = {
 		.enable		= exynos4_clk_ip_peril_ctrl,
 		.ctrlbit	= (1 << 21),
 	}, {
+		.name		= "pcm",
+		.devname	= "samsung-pcm.1",
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 22),
+	}, {
+		.name		= "pcm",
+		.devname	= "samsung-pcm.2",
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 23),
+	}, {
+		.name		= "slimbus",
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 25),
+	}, {
+		.name		= "spdif",
+		.devname	= "samsung-spdif",
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 26),
+	}, {
 		.name		= "ac97",
 		.devname	= "samsung-ac97",
 		.enable		= exynos4_clk_ip_peril_ctrl,
diff --git a/arch/arm/mach-exynos/clock-exynos5.c b/arch/arm/mach-exynos/clock-exynos5.c
index 774533c..f3171c3 100644
--- a/arch/arm/mach-exynos/clock-exynos5.c
+++ b/arch/arm/mach-exynos/clock-exynos5.c
@@ -166,11 +166,6 @@ static int exynos5_clk_ip_gen_ctrl(struct clk *clk, int enable)
 	return s5p_gatectrl(EXYNOS5_CLKGATE_IP_GEN, clk, enable);
 }
 
-static int exynos5_clk_ip_gps_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(EXYNOS5_CLKGATE_IP_GPS, clk, enable);
-}
-
 static int exynos5_clk_ip_mfc_ctrl(struct clk *clk, int enable)
 {
 	return s5p_gatectrl(EXYNOS5_CLKGATE_IP_MFC, clk, enable);
@@ -552,6 +547,68 @@ static struct clksrc_clk exynos5_clk_aclk_66 = {
 	.reg_div = { .reg = EXYNOS5_CLKDIV_TOP0, .shift = 0, .size = 3 },
 };
 
+static struct clksrc_clk exynos5_clk_mout_aclk_300_gscl_mid = {
+	.clk	= {
+		.name		= "mout_aclk_300_gscl_mid",
+	},
+	.sources = &exynos5_clkset_aclk,
+	.reg_src = { .reg = EXYNOS5_CLKSRC_TOP0, .shift = 24, .size = 1 },
+};
+
+static struct clk *exynos5_clkset_aclk_300_mid1_list[] = {
+	[0] = &exynos5_clk_sclk_vpll.clk,
+	[1] = &exynos5_clk_mout_cpll.clk,
+};
+
+static struct clksrc_sources exynos5_clkset_aclk_300_gscl_mid1 = {
+	.sources	= exynos5_clkset_aclk_300_mid1_list,
+	.nr_sources	= ARRAY_SIZE(exynos5_clkset_aclk_300_mid1_list),
+};
+
+static struct clksrc_clk exynos5_clk_mout_aclk_300_gscl_mid1 = {
+	.clk	= {
+		.name		= "mout_aclk_300_gscl_mid1",
+	},
+	.sources = &exynos5_clkset_aclk_300_gscl_mid1,
+	.reg_src = { .reg = EXYNOS5_CLKSRC_TOP1, .shift = 12, .size = 1 },
+};
+
+static struct clk *exynos5_clkset_aclk_300_gscl_list[] = {
+	[0] = &exynos5_clk_mout_aclk_300_gscl_mid.clk,
+	[1] = &exynos5_clk_mout_aclk_300_gscl_mid1.clk,
+};
+
+static struct clksrc_sources exynos5_clkset_aclk_300_gscl = {
+	.sources	= exynos5_clkset_aclk_300_gscl_list,
+	.nr_sources	= ARRAY_SIZE(exynos5_clkset_aclk_300_gscl_list),
+};
+
+static struct clksrc_clk exynos5_clk_mout_aclk_300_gscl = {
+	.clk	= {
+		.name		= "mout_aclk_300_gscl",
+	},
+	.sources = &exynos5_clkset_aclk_300_gscl,
+	.reg_src = { .reg = EXYNOS5_CLKSRC_TOP0, .shift = 25, .size = 1 },
+};
+
+static struct clk *exynos5_clk_src_gscl_300_list[] = {
+	[0] = &clk_ext_xtal_mux,
+	[1] = &exynos5_clk_mout_aclk_300_gscl.clk,
+};
+
+static struct clksrc_sources exynos5_clk_src_gscl_300 = {
+	.sources	= exynos5_clk_src_gscl_300_list,
+	.nr_sources	= ARRAY_SIZE(exynos5_clk_src_gscl_300_list),
+};
+
+static struct clksrc_clk exynos5_clk_aclk_300_gscl = {
+	.clk	= {
+		.name		= "aclk_300_gscl",
+	},
+	.sources = &exynos5_clk_src_gscl_300,
+	.reg_src = { .reg = EXYNOS5_CLKSRC_TOP3, .shift = 10, .size = 1 },
+};
+
 static struct clk exynos5_init_clocks_off[] = {
 	{
 		.name		= "timers",
@@ -672,10 +729,6 @@ static struct clk exynos5_init_clocks_off[] = {
 		.enable		= exynos5_clk_ip_fsys_ctrl,
 		.ctrlbit	= (1 << 7),
 	}, {
-		.name		= "gps",
-		.enable		= exynos5_clk_ip_gps_ctrl,
-		.ctrlbit	= ((1 << 3) | (1 << 2) | (1 << 0)),
-	}, {
 		.name		= "nfcon",
 		.enable		= exynos5_clk_ip_fsys_ctrl,
 		.ctrlbit	= (1 << 22),
@@ -764,6 +817,26 @@ static struct clk exynos5_init_clocks_off[] = {
 		.enable		= exynos5_clk_ip_peric_ctrl,
 		.ctrlbit	= (1 << 18),
 	}, {
+		.name		= "gscl",
+		.devname	= "exynos-gsc.0",
+		.enable		= exynos5_clk_ip_gscl_ctrl,
+		.ctrlbit	= (1 << 0),
+	}, {
+		.name		= "gscl",
+		.devname	= "exynos-gsc.1",
+		.enable		= exynos5_clk_ip_gscl_ctrl,
+		.ctrlbit	= (1 << 1),
+	}, {
+		.name		= "gscl",
+		.devname	= "exynos-gsc.2",
+		.enable		= exynos5_clk_ip_gscl_ctrl,
+		.ctrlbit	= (1 << 2),
+	}, {
+		.name		= "gscl",
+		.devname	= "exynos-gsc.3",
+		.enable		= exynos5_clk_ip_gscl_ctrl,
+		.ctrlbit	= (1 << 3),
+	}, {
 		.name		= SYSMMU_CLOCK_NAME,
 		.devname	= SYSMMU_CLOCK_DEVNAME(mfc_l, 0),
 		.enable		= &exynos5_clk_ip_mfc_ctrl,
@@ -891,6 +964,13 @@ static struct clk exynos5_clk_mdma1 = {
 	.ctrlbit	= (1 << 4),
 };
 
+static struct clk exynos5_clk_fimd1 = {
+	.name		= "fimd",
+	.devname	= "exynos5-fb.1",
+	.enable		= exynos5_clk_ip_disp1_ctrl,
+	.ctrlbit	= (1 << 0),
+};
+
 struct clk *exynos5_clkset_group_list[] = {
 	[0] = &clk_ext_xtal_mux,
 	[1] = NULL,
@@ -1120,6 +1200,18 @@ static struct clksrc_clk exynos5_clk_sclk_spi2 = {
 	.reg_div = { .reg = EXYNOS5_CLKDIV_PERIC2, .shift = 8, .size = 8 },
 };
 
+struct clksrc_clk exynos5_clk_sclk_fimd1 = {
+	.clk	= {
+		.name		= "sclk_fimd",
+		.devname	= "exynos5-fb.1",
+		.enable		= exynos5_clksrc_mask_disp1_0_ctrl,
+		.ctrlbit	= (1 << 0),
+	},
+	.sources = &exynos5_clkset_group,
+	.reg_src = { .reg = EXYNOS5_CLKSRC_DISP1_0, .shift = 0, .size = 4 },
+	.reg_div = { .reg = EXYNOS5_CLKDIV_DISP1_0, .shift = 0, .size = 4 },
+};
+
 static struct clksrc_clk exynos5_clksrcs[] = {
 	{
 		.clk	= {
@@ -1131,16 +1223,6 @@ static struct clksrc_clk exynos5_clksrcs[] = {
 		.reg_div = { .reg = EXYNOS5_CLKDIV_FSYS3, .shift = 8, .size = 8 },
 	}, {
 		.clk	= {
-			.name		= "sclk_fimd",
-			.devname	= "s3cfb.1",
-			.enable		= exynos5_clksrc_mask_disp1_0_ctrl,
-			.ctrlbit	= (1 << 0),
-		},
-		.sources = &exynos5_clkset_group,
-		.reg_src = { .reg = EXYNOS5_CLKSRC_DISP1_0, .shift = 0, .size = 4 },
-		.reg_div = { .reg = EXYNOS5_CLKDIV_DISP1_0, .shift = 0, .size = 4 },
-	}, {
-		.clk	= {
 			.name		= "aclk_266_gscl",
 		},
 		.sources = &clk_src_gscl_266,
@@ -1225,6 +1307,10 @@ static struct clksrc_clk *exynos5_sysclks[] = {
 	&exynos5_clk_aclk_266,
 	&exynos5_clk_aclk_200,
 	&exynos5_clk_aclk_166,
+	&exynos5_clk_aclk_300_gscl,
+	&exynos5_clk_mout_aclk_300_gscl,
+	&exynos5_clk_mout_aclk_300_gscl_mid,
+	&exynos5_clk_mout_aclk_300_gscl_mid1,
 	&exynos5_clk_aclk_66_pre,
 	&exynos5_clk_aclk_66,
 	&exynos5_clk_dout_mmc0,
@@ -1240,12 +1326,14 @@ static struct clksrc_clk *exynos5_sysclks[] = {
 	&exynos5_clk_mdout_spi0,
 	&exynos5_clk_mdout_spi1,
 	&exynos5_clk_mdout_spi2,
+	&exynos5_clk_sclk_fimd1,
 };
 
 static struct clk *exynos5_clk_cdev[] = {
 	&exynos5_clk_pdma0,
 	&exynos5_clk_pdma1,
 	&exynos5_clk_mdma1,
+	&exynos5_clk_fimd1,
 };
 
 static struct clksrc_clk *exynos5_clksrc_cdev[] = {
@@ -1274,6 +1362,7 @@ static struct clk_lookup exynos5_clk_lookup[] = {
 	CLKDEV_INIT("dma-pl330.0", "apb_pclk", &exynos5_clk_pdma0),
 	CLKDEV_INIT("dma-pl330.1", "apb_pclk", &exynos5_clk_pdma1),
 	CLKDEV_INIT("dma-pl330.2", "apb_pclk", &exynos5_clk_mdma1),
+	CLKDEV_INIT("exynos5-fb.1", "lcd", &exynos5_clk_fimd1),
 };
 
 static unsigned long exynos5_epll_get_rate(struct clk *clk)
diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c
index 4eb39cd..715b690 100644
--- a/arch/arm/mach-exynos/common.c
+++ b/arch/arm/mach-exynos/common.c
@@ -980,6 +980,32 @@ static int __init exynos_init_irq_eint(void)
 {
 	int irq;
 
+#ifdef CONFIG_PINCTRL_SAMSUNG
+	/*
+	 * The Samsung pinctrl driver provides an integrated gpio/pinmux/pinconf
+	 * functionality along with support for external gpio and wakeup
+	 * interrupts. If the samsung pinctrl driver is enabled and includes
+	 * the wakeup interrupt support, then the setting up external wakeup
+	 * interrupts here can be skipped. This check here is temporary to
+	 * allow exynos4 platforms that do not use Samsung pinctrl driver to
+	 * co-exist with platforms that do. When all of the Samsung Exynos4
+	 * platforms switch over to using the pinctrl driver, the wakeup
+	 * interrupt support code here can be completely removed.
+	 */
+	struct device_node *pctrl_np, *wkup_np;
+	const char *pctrl_compat = "samsung,pinctrl-exynos4210";
+	const char *wkup_compat = "samsung,exynos4210-wakeup-eint";
+
+	for_each_compatible_node(pctrl_np, NULL, pctrl_compat) {
+		if (of_device_is_available(pctrl_np)) {
+			wkup_np = of_find_compatible_node(pctrl_np, NULL,
+							wkup_compat);
+			if (wkup_np)
+				return -ENODEV;
+		}
+	}
+#endif
+
 	if (soc_is_exynos5250())
 		exynos_eint_base = ioremap(EXYNOS5_PA_GPIO1, SZ_4K);
 	else
diff --git a/arch/arm/mach-exynos/common.h b/arch/arm/mach-exynos/common.h
index aed2eeb..dac146d 100644
--- a/arch/arm/mach-exynos/common.h
+++ b/arch/arm/mach-exynos/common.h
@@ -14,6 +14,7 @@
 
 extern struct sys_timer exynos4_timer;
 
+struct map_desc;
 void exynos_init_io(struct map_desc *mach_desc, int size);
 void exynos4_init_irq(void);
 void exynos5_init_irq(void);
@@ -59,4 +60,8 @@ void exynos4212_register_clocks(void);
 #define exynos4212_register_clocks()
 #endif
 
+extern struct smp_operations exynos_smp_ops;
+
+extern void exynos_cpu_die(unsigned int cpu);
+
 #endif /* __ARCH_ARM_MACH_EXYNOS_COMMON_H */
diff --git a/arch/arm/mach-exynos/dev-audio.c b/arch/arm/mach-exynos/dev-audio.c
index b33a5b6..ae321c7 100644
--- a/arch/arm/mach-exynos/dev-audio.c
+++ b/arch/arm/mach-exynos/dev-audio.c
@@ -16,7 +16,7 @@
 #include <linux/gpio.h>
 
 #include <plat/gpio-cfg.h>
-#include <plat/audio.h>
+#include <linux/platform_data/asoc-s3c.h>
 
 #include <mach/map.h>
 #include <mach/dma.h>
diff --git a/arch/arm/mach-exynos/dev-ohci.c b/arch/arm/mach-exynos/dev-ohci.c
index b8e7530..14ed795 100644
--- a/arch/arm/mach-exynos/dev-ohci.c
+++ b/arch/arm/mach-exynos/dev-ohci.c
@@ -15,7 +15,7 @@
 
 #include <mach/irqs.h>
 #include <mach/map.h>
-#include <mach/ohci.h>
+#include <linux/platform_data/usb-exynos.h>
 
 #include <plat/devs.h>
 #include <plat/usb-phy.h>
diff --git a/arch/arm/mach-exynos/dma.c b/arch/arm/mach-exynos/dma.c
index f60b66d..21d568b 100644
--- a/arch/arm/mach-exynos/dma.c
+++ b/arch/arm/mach-exynos/dma.c
@@ -303,10 +303,12 @@ static int __init exynos_dma_init(void)
 
 	dma_cap_set(DMA_SLAVE, exynos_pdma0_pdata.cap_mask);
 	dma_cap_set(DMA_CYCLIC, exynos_pdma0_pdata.cap_mask);
+	dma_cap_set(DMA_PRIVATE, exynos_pdma0_pdata.cap_mask);
 	amba_device_register(&exynos_pdma0_device, &iomem_resource);
 
 	dma_cap_set(DMA_SLAVE, exynos_pdma1_pdata.cap_mask);
 	dma_cap_set(DMA_CYCLIC, exynos_pdma1_pdata.cap_mask);
+	dma_cap_set(DMA_PRIVATE, exynos_pdma1_pdata.cap_mask);
 	amba_device_register(&exynos_pdma1_device, &iomem_resource);
 
 	dma_cap_set(DMA_MEMCPY, exynos_mdma1_pdata.cap_mask);
diff --git a/arch/arm/mach-exynos/hotplug.c b/arch/arm/mach-exynos/hotplug.c
index 9c17a0a..f4d7dd2 100644
--- a/arch/arm/mach-exynos/hotplug.c
+++ b/arch/arm/mach-exynos/hotplug.c
@@ -21,7 +21,7 @@
 
 #include <mach/regs-pmu.h>
 
-extern volatile int pen_release;
+#include "common.h"
 
 static inline void cpu_enter_lowpower(void)
 {
@@ -95,17 +95,12 @@ static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
 	}
 }
 
-int platform_cpu_kill(unsigned int cpu)
-{
-	return 1;
-}
-
 /*
  * platform-specific code to shutdown a CPU
  *
  * Called with IRQs disabled
  */
-void platform_cpu_die(unsigned int cpu)
+void __ref exynos_cpu_die(unsigned int cpu)
 {
 	int spurious = 0;
 
@@ -124,12 +119,3 @@ void platform_cpu_die(unsigned int cpu)
 	if (spurious)
 		pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
 }
-
-int platform_cpu_disable(unsigned int cpu)
-{
-	/*
-	 * we don't allow CPU 0 to be shutdown (it is still too special
-	 * e.g. clock tick interrupts)
-	 */
-	return cpu == 0 ? -EPERM : 0;
-}
diff --git a/arch/arm/mach-exynos/include/mach/map.h b/arch/arm/mach-exynos/include/mach/map.h
index c72b675..5aa77f9 100644
--- a/arch/arm/mach-exynos/include/mach/map.h
+++ b/arch/arm/mach-exynos/include/mach/map.h
@@ -89,7 +89,7 @@
 #define EXYNOS4_PA_L2CC			0x10502000
 
 #define EXYNOS4_PA_MDMA0		0x10810000
-#define EXYNOS4_PA_MDMA1		0x12840000
+#define EXYNOS4_PA_MDMA1		0x12850000
 #define EXYNOS4_PA_PDMA0		0x12680000
 #define EXYNOS4_PA_PDMA1		0x12690000
 #define EXYNOS5_PA_MDMA0		0x10800000
@@ -121,6 +121,11 @@
 #define EXYNOS4_PA_SYSMMU_MFC_L		0x13620000
 #define EXYNOS4_PA_SYSMMU_MFC_R		0x13630000
 
+#define EXYNOS5_PA_GSC0			0x13E00000
+#define EXYNOS5_PA_GSC1			0x13E10000
+#define EXYNOS5_PA_GSC2			0x13E20000
+#define EXYNOS5_PA_GSC3			0x13E30000
+
 #define EXYNOS5_PA_SYSMMU_MDMA1		0x10A40000
 #define EXYNOS5_PA_SYSMMU_SSS		0x10A50000
 #define EXYNOS5_PA_SYSMMU_2D		0x10A60000
@@ -131,7 +136,6 @@
 #define EXYNOS5_PA_SYSMMU_JPEG		0x11F20000
 #define EXYNOS5_PA_SYSMMU_IOP		0x12360000
 #define EXYNOS5_PA_SYSMMU_RTIC		0x12370000
-#define EXYNOS5_PA_SYSMMU_GPS		0x12630000
 #define EXYNOS5_PA_SYSMMU_ISP		0x13260000
 #define EXYNOS5_PA_SYSMMU_DRC		0x12370000
 #define EXYNOS5_PA_SYSMMU_SCALERC	0x13280000
diff --git a/arch/arm/mach-exynos/include/mach/ohci.h b/arch/arm/mach-exynos/include/mach/ohci.h
deleted file mode 100644
index c256c59..0000000
--- a/arch/arm/mach-exynos/include/mach/ohci.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 2011 Samsung Electronics Co.Ltd
- *		http://www.samsung.com/
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-
-#ifndef __MACH_EXYNOS_OHCI_H
-#define __MACH_EXYNOS_OHCI_H
-
-struct exynos4_ohci_platdata {
-	int (*phy_init)(struct platform_device *pdev, int type);
-	int (*phy_exit)(struct platform_device *pdev, int type);
-};
-
-extern void exynos4_ohci_set_platdata(struct exynos4_ohci_platdata *pd);
-
-#endif /* __MACH_EXYNOS_OHCI_H */
diff --git a/arch/arm/mach-exynos/include/mach/sysmmu.h b/arch/arm/mach-exynos/include/mach/sysmmu.h
index 998daf2..88a4543 100644
--- a/arch/arm/mach-exynos/include/mach/sysmmu.h
+++ b/arch/arm/mach-exynos/include/mach/sysmmu.h
@@ -58,7 +58,7 @@ static inline void platform_set_sysmmu(
 #endif
 
 #else /* !CONFIG_EXYNOS_DEV_SYSMMU */
-#define platform_set_sysmmu(dev, sysmmu) do { } while (0)
+#define platform_set_sysmmu(sysmmu, dev) do { } while (0)
 #endif
 
 #define SYSMMU_CLOCK_DEVNAME(ipname, id) (SYSMMU_DEVNAME_BASE "." #id)
diff --git a/arch/arm/mach-exynos/mach-armlex4210.c b/arch/arm/mach-exynos/mach-armlex4210.c
index 5a3daa0..3f37a5e 100644
--- a/arch/arm/mach-exynos/mach-armlex4210.c
+++ b/arch/arm/mach-exynos/mach-armlex4210.c
@@ -199,6 +199,7 @@ static void __init armlex4210_machine_init(void)
 MACHINE_START(ARMLEX4210, "ARMLEX4210")
 	/* Maintainer: Alim Akhtar <alim.akhtar@samsung.com> */
 	.atag_offset	= 0x100,
+	.smp		= smp_ops(exynos_smp_ops),
 	.init_irq	= exynos4_init_irq,
 	.map_io		= armlex4210_map_io,
 	.handle_irq	= gic_handle_irq,
diff --git a/arch/arm/mach-exynos/mach-exynos4-dt.c b/arch/arm/mach-exynos/mach-exynos4-dt.c
index b2b5d5f..e58d786 100644
--- a/arch/arm/mach-exynos/mach-exynos4-dt.c
+++ b/arch/arm/mach-exynos/mach-exynos4-dt.c
@@ -1,5 +1,5 @@
 /*
- * Samsung's Exynos4210 flattened device tree enabled machine
+ * Samsung's EXYNOS4 flattened device tree enabled machine
  *
  * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
  *		http://www.samsung.com
@@ -36,7 +36,7 @@
  * at some point, the drivers should be capable of parsing all the platform
  * data from the device tree.
  */
-static const struct of_dev_auxdata exynos4210_auxdata_lookup[] __initconst = {
+static const struct of_dev_auxdata exynos4_auxdata_lookup[] __initconst = {
 	OF_DEV_AUXDATA("samsung,exynos4210-uart", EXYNOS4_PA_UART0,
 				"exynos4210-uart.0", NULL),
 	OF_DEV_AUXDATA("samsung,exynos4210-uart", EXYNOS4_PA_UART1,
@@ -55,6 +55,20 @@ static const struct of_dev_auxdata exynos4210_auxdata_lookup[] __initconst = {
 				"exynos4-sdhci.3", NULL),
 	OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS4_PA_IIC(0),
 				"s3c2440-i2c.0", NULL),
+	OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS4_PA_IIC(1),
+				"s3c2440-i2c.1", NULL),
+	OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS4_PA_IIC(2),
+				"s3c2440-i2c.2", NULL),
+	OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS4_PA_IIC(3),
+				"s3c2440-i2c.3", NULL),
+	OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS4_PA_IIC(4),
+				"s3c2440-i2c.4", NULL),
+	OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS4_PA_IIC(5),
+				"s3c2440-i2c.5", NULL),
+	OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS4_PA_IIC(6),
+				"s3c2440-i2c.6", NULL),
+	OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS4_PA_IIC(7),
+				"s3c2440-i2c.7", NULL),
 	OF_DEV_AUXDATA("samsung,exynos4210-spi", EXYNOS4_PA_SPI0,
 				"exynos4210-spi.0", NULL),
 	OF_DEV_AUXDATA("samsung,exynos4210-spi", EXYNOS4_PA_SPI1,
@@ -66,19 +80,19 @@ static const struct of_dev_auxdata exynos4210_auxdata_lookup[] __initconst = {
 	{},
 };
 
-static void __init exynos4210_dt_map_io(void)
+static void __init exynos4_dt_map_io(void)
 {
 	exynos_init_io(NULL, 0);
 	s3c24xx_init_clocks(24000000);
 }
 
-static void __init exynos4210_dt_machine_init(void)
+static void __init exynos4_dt_machine_init(void)
 {
 	of_platform_populate(NULL, of_default_bus_match_table,
-				exynos4210_auxdata_lookup, NULL);
+				exynos4_auxdata_lookup, NULL);
 }
 
-static char const *exynos4210_dt_compat[] __initdata = {
+static char const *exynos4_dt_compat[] __initdata = {
 	"samsung,exynos4210",
 	NULL
 };
@@ -86,11 +100,11 @@ static char const *exynos4210_dt_compat[] __initdata = {
 DT_MACHINE_START(EXYNOS4210_DT, "Samsung Exynos4 (Flattened Device Tree)")
 	/* Maintainer: Thomas Abraham <thomas.abraham@linaro.org> */
 	.init_irq	= exynos4_init_irq,
-	.map_io		= exynos4210_dt_map_io,
+	.map_io		= exynos4_dt_map_io,
 	.handle_irq	= gic_handle_irq,
-	.init_machine	= exynos4210_dt_machine_init,
+	.init_machine	= exynos4_dt_machine_init,
 	.init_late	= exynos_init_late,
 	.timer		= &exynos4_timer,
-	.dt_compat	= exynos4210_dt_compat,
+	.dt_compat	= exynos4_dt_compat,
 	.restart        = exynos4_restart,
 MACHINE_END
diff --git a/arch/arm/mach-exynos/mach-exynos5-dt.c b/arch/arm/mach-exynos/mach-exynos5-dt.c
index ef770bc..45808fb 100644
--- a/arch/arm/mach-exynos/mach-exynos5-dt.c
+++ b/arch/arm/mach-exynos/mach-exynos5-dt.c
@@ -56,6 +56,14 @@ static const struct of_dev_auxdata exynos5250_auxdata_lookup[] __initconst = {
 	OF_DEV_AUXDATA("arm,pl330", EXYNOS5_PA_PDMA0, "dma-pl330.0", NULL),
 	OF_DEV_AUXDATA("arm,pl330", EXYNOS5_PA_PDMA1, "dma-pl330.1", NULL),
 	OF_DEV_AUXDATA("arm,pl330", EXYNOS5_PA_MDMA1, "dma-pl330.2", NULL),
+	OF_DEV_AUXDATA("samsung,exynos5-gsc", EXYNOS5_PA_GSC0,
+				"exynos-gsc.0", NULL),
+	OF_DEV_AUXDATA("samsung,exynos5-gsc", EXYNOS5_PA_GSC1,
+				"exynos-gsc.1", NULL),
+	OF_DEV_AUXDATA("samsung,exynos5-gsc", EXYNOS5_PA_GSC2,
+				"exynos-gsc.2", NULL),
+	OF_DEV_AUXDATA("samsung,exynos5-gsc", EXYNOS5_PA_GSC3,
+				"exynos-gsc.3", NULL),
 	{},
 };
 
@@ -79,6 +87,7 @@ static char const *exynos5250_dt_compat[] __initdata = {
 DT_MACHINE_START(EXYNOS5_DT, "SAMSUNG EXYNOS5 (Flattened Device Tree)")
 	/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
 	.init_irq	= exynos5_init_irq,
+	.smp		= smp_ops(exynos_smp_ops),
 	.map_io		= exynos5250_dt_map_io,
 	.handle_irq	= gic_handle_irq,
 	.init_machine	= exynos5250_dt_machine_init,
diff --git a/arch/arm/mach-exynos/mach-nuri.c b/arch/arm/mach-exynos/mach-nuri.c
index ea785fc..85fc2fe 100644
--- a/arch/arm/mach-exynos/mach-nuri.c
+++ b/arch/arm/mach-exynos/mach-nuri.c
@@ -29,6 +29,7 @@
 #include <drm/exynos_drm.h>
 
 #include <video/platform_lcd.h>
+#include <video/samsung_fimd.h>
 #include <media/m5mols.h>
 #include <media/s5k6aa.h>
 #include <media/s5p_fimc.h>
@@ -39,20 +40,19 @@
 #include <asm/mach-types.h>
 
 #include <plat/adc.h>
-#include <plat/regs-fb-v4.h>
 #include <plat/regs-serial.h>
 #include <plat/cpu.h>
 #include <plat/devs.h>
 #include <plat/fb.h>
 #include <plat/sdhci.h>
-#include <plat/ehci.h>
+#include <linux/platform_data/usb-ehci-s5p.h>
 #include <plat/clock.h>
 #include <plat/gpio-cfg.h>
-#include <plat/iic.h>
+#include <linux/platform_data/i2c-s3c2410.h>
 #include <plat/mfc.h>
 #include <plat/fimc-core.h>
 #include <plat/camport.h>
-#include <plat/mipi_csis.h>
+#include <linux/platform_data/mipi-csis.h>
 
 #include <mach/map.h>
 
@@ -1383,6 +1383,7 @@ static void __init nuri_machine_init(void)
 MACHINE_START(NURI, "NURI")
 	/* Maintainer: Kyungmin Park <kyungmin.park@samsung.com> */
 	.atag_offset	= 0x100,
+	.smp		= smp_ops(exynos_smp_ops),
 	.init_irq	= exynos4_init_irq,
 	.map_io		= nuri_map_io,
 	.handle_irq	= gic_handle_irq,
diff --git a/arch/arm/mach-exynos/mach-origen.c b/arch/arm/mach-exynos/mach-origen.c
index 4e574c2..c11a62e 100644
--- a/arch/arm/mach-exynos/mach-origen.c
+++ b/arch/arm/mach-exynos/mach-origen.c
@@ -15,6 +15,7 @@
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/input.h>
+#include <linux/pwm.h>
 #include <linux/pwm_backlight.h>
 #include <linux/gpio_keys.h>
 #include <linux/i2c.h>
@@ -29,14 +30,14 @@
 #include <asm/mach-types.h>
 
 #include <video/platform_lcd.h>
+#include <video/samsung_fimd.h>
 
 #include <plat/regs-serial.h>
-#include <plat/regs-fb-v4.h>
 #include <plat/cpu.h>
 #include <plat/devs.h>
 #include <plat/sdhci.h>
-#include <plat/iic.h>
-#include <plat/ehci.h>
+#include <linux/platform_data/i2c-s3c2410.h>
+#include <linux/platform_data/usb-ehci-s5p.h>
 #include <plat/clock.h>
 #include <plat/gpio-cfg.h>
 #include <plat/backlight.h>
@@ -44,7 +45,7 @@
 #include <plat/mfc.h>
 #include <plat/hdmi.h>
 
-#include <mach/ohci.h>
+#include <linux/platform_data/usb-exynos.h>
 #include <mach/map.h>
 
 #include <drm/exynos_drm.h>
@@ -614,6 +615,10 @@ static struct platform_device origen_lcd_hv070wsa = {
 	.dev.platform_data	= &origen_lcd_hv070wsa_data,
 };
 
+static struct pwm_lookup origen_pwm_lookup[] = {
+	PWM_LOOKUP("s3c24xx-pwm.0", 0, "pwm-backlight.0", NULL),
+};
+
 #ifdef CONFIG_DRM_EXYNOS
 static struct exynos_drm_fimd_pdata drm_fimd_pdata = {
 	.panel	= {
@@ -798,6 +803,7 @@ static void __init origen_machine_init(void)
 
 	platform_add_devices(origen_devices, ARRAY_SIZE(origen_devices));
 
+	pwm_add_table(origen_pwm_lookup, ARRAY_SIZE(origen_pwm_lookup));
 	samsung_bl_set(&origen_bl_gpio_info, &origen_bl_data);
 
 	origen_bt_setup();
@@ -806,6 +812,7 @@ static void __init origen_machine_init(void)
 MACHINE_START(ORIGEN, "ORIGEN")
 	/* Maintainer: JeongHyeon Kim <jhkim@insignal.co.kr> */
 	.atag_offset	= 0x100,
+	.smp		= smp_ops(exynos_smp_ops),
 	.init_irq	= exynos4_init_irq,
 	.map_io		= origen_map_io,
 	.handle_irq	= gic_handle_irq,
diff --git a/arch/arm/mach-exynos/mach-smdk4x12.c b/arch/arm/mach-exynos/mach-smdk4x12.c
index b26beb1..730f1ac 100644
--- a/arch/arm/mach-exynos/mach-smdk4x12.c
+++ b/arch/arm/mach-exynos/mach-smdk4x12.c
@@ -17,6 +17,7 @@
 #include <linux/mfd/max8997.h>
 #include <linux/mmc/host.h>
 #include <linux/platform_device.h>
+#include <linux/pwm.h>
 #include <linux/pwm_backlight.h>
 #include <linux/regulator/machine.h>
 #include <linux/serial_core.h>
@@ -26,16 +27,16 @@
 #include <asm/hardware/gic.h>
 #include <asm/mach-types.h>
 
+#include <video/samsung_fimd.h>
 #include <plat/backlight.h>
 #include <plat/clock.h>
 #include <plat/cpu.h>
 #include <plat/devs.h>
 #include <plat/fb.h>
 #include <plat/gpio-cfg.h>
-#include <plat/iic.h>
+#include <linux/platform_data/i2c-s3c2410.h>
 #include <plat/keypad.h>
 #include <plat/mfc.h>
-#include <plat/regs-fb.h>
 #include <plat/regs-serial.h>
 #include <plat/sdhci.h>
 
@@ -222,6 +223,10 @@ static struct platform_pwm_backlight_data smdk4x12_bl_data = {
 	.pwm_period_ns  = 1000,
 };
 
+static struct pwm_lookup smdk4x12_pwm_lookup[] = {
+	PWM_LOOKUP("s3c24xx-pwm.1", 0, "pwm-backlight.0", NULL),
+};
+
 static uint32_t smdk4x12_keymap[] __initdata = {
 	/* KEY(row, col, keycode) */
 	KEY(1, 3, KEY_1), KEY(1, 4, KEY_2), KEY(1, 5, KEY_3),
@@ -349,6 +354,7 @@ static void __init smdk4x12_machine_init(void)
 				ARRAY_SIZE(smdk4x12_i2c_devs7));
 
 	samsung_bl_set(&smdk4x12_bl_gpio_info, &smdk4x12_bl_data);
+	pwm_add_table(smdk4x12_pwm_lookup, ARRAY_SIZE(smdk4x12_pwm_lookup));
 
 	samsung_keypad_set_platdata(&smdk4x12_keypad_data);
 
@@ -370,6 +376,7 @@ static void __init smdk4x12_machine_init(void)
 MACHINE_START(SMDK4212, "SMDK4212")
 	/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
 	.atag_offset	= 0x100,
+	.smp		= smp_ops(exynos_smp_ops),
 	.init_irq	= exynos4_init_irq,
 	.map_io		= smdk4x12_map_io,
 	.handle_irq	= gic_handle_irq,
@@ -383,6 +390,7 @@ MACHINE_START(SMDK4412, "SMDK4412")
 	/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
 	/* Maintainer: Changhwan Youn <chaos.youn@samsung.com> */
 	.atag_offset	= 0x100,
+	.smp		= smp_ops(exynos_smp_ops),
 	.init_irq	= exynos4_init_irq,
 	.map_io		= smdk4x12_map_io,
 	.handle_irq	= gic_handle_irq,
diff --git a/arch/arm/mach-exynos/mach-smdkv310.c b/arch/arm/mach-exynos/mach-smdkv310.c
index 73f2bce..ee4fb1a 100644
--- a/arch/arm/mach-exynos/mach-smdkv310.c
+++ b/arch/arm/mach-exynos/mach-smdkv310.c
@@ -18,6 +18,7 @@
 #include <linux/io.h>
 #include <linux/i2c.h>
 #include <linux/input.h>
+#include <linux/pwm.h>
 #include <linux/pwm_backlight.h>
 #include <linux/platform_data/s3c-hsotg.h>
 
@@ -26,24 +27,24 @@
 #include <asm/mach-types.h>
 
 #include <video/platform_lcd.h>
+#include <video/samsung_fimd.h>
 #include <plat/regs-serial.h>
 #include <plat/regs-srom.h>
-#include <plat/regs-fb-v4.h>
 #include <plat/cpu.h>
 #include <plat/devs.h>
 #include <plat/fb.h>
 #include <plat/keypad.h>
 #include <plat/sdhci.h>
-#include <plat/iic.h>
+#include <linux/platform_data/i2c-s3c2410.h>
 #include <plat/gpio-cfg.h>
 #include <plat/backlight.h>
 #include <plat/mfc.h>
-#include <plat/ehci.h>
+#include <linux/platform_data/usb-ehci-s5p.h>
 #include <plat/clock.h>
 #include <plat/hdmi.h>
 
 #include <mach/map.h>
-#include <mach/ohci.h>
+#include <linux/platform_data/usb-exynos.h>
 
 #include <drm/exynos_drm.h>
 #include "common.h"
@@ -360,6 +361,10 @@ static struct i2c_board_info hdmiphy_info = {
 	I2C_BOARD_INFO("hdmiphy-exynos4210", 0x38),
 };
 
+static struct pwm_lookup smdkv310_pwm_lookup[] = {
+	PWM_LOOKUP("s3c24xx-pwm.1", 0, "pwm-backlight.0", NULL),
+};
+
 static void s5p_tv_setup(void)
 {
 	/* direct HPD to HDMI chip */
@@ -399,6 +404,8 @@ static void __init smdkv310_machine_init(void)
 	samsung_keypad_set_platdata(&smdkv310_keypad_data);
 
 	samsung_bl_set(&smdkv310_bl_gpio_info, &smdkv310_bl_data);
+	pwm_add_table(smdkv310_pwm_lookup, ARRAY_SIZE(smdkv310_pwm_lookup));
+
 #ifdef CONFIG_DRM_EXYNOS
 	s5p_device_fimd0.dev.platform_data = &drm_fimd_pdata;
 	exynos4_fimd0_gpio_setup_24bpp();
@@ -417,6 +424,7 @@ MACHINE_START(SMDKV310, "SMDKV310")
 	/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
 	/* Maintainer: Changhwan Youn <chaos.youn@samsung.com> */
 	.atag_offset	= 0x100,
+	.smp		= smp_ops(exynos_smp_ops),
 	.init_irq	= exynos4_init_irq,
 	.map_io		= smdkv310_map_io,
 	.handle_irq	= gic_handle_irq,
@@ -429,6 +437,7 @@ MACHINE_END
 MACHINE_START(SMDKC210, "SMDKC210")
 	/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
 	.atag_offset	= 0x100,
+	.smp		= smp_ops(exynos_smp_ops),
 	.init_irq	= exynos4_init_irq,
 	.map_io		= smdkv310_map_io,
 	.handle_irq	= gic_handle_irq,
diff --git a/arch/arm/mach-exynos/mach-universal_c210.c b/arch/arm/mach-exynos/mach-universal_c210.c
index 4d1f40d..08b81fd 100644
--- a/arch/arm/mach-exynos/mach-universal_c210.c
+++ b/arch/arm/mach-exynos/mach-universal_c210.c
@@ -30,20 +30,20 @@
 #include <asm/hardware/gic.h>
 #include <asm/mach-types.h>
 
+#include <video/samsung_fimd.h>
 #include <plat/regs-serial.h>
 #include <plat/clock.h>
 #include <plat/cpu.h>
 #include <plat/devs.h>
-#include <plat/iic.h>
+#include <linux/platform_data/i2c-s3c2410.h>
 #include <plat/gpio-cfg.h>
 #include <plat/fb.h>
 #include <plat/mfc.h>
 #include <plat/sdhci.h>
-#include <plat/regs-fb-v4.h>
 #include <plat/fimc-core.h>
 #include <plat/s5p-time.h>
 #include <plat/camport.h>
-#include <plat/mipi_csis.h>
+#include <linux/platform_data/mipi-csis.h>
 
 #include <mach/map.h>
 
@@ -1155,6 +1155,7 @@ static void __init universal_machine_init(void)
 MACHINE_START(UNIVERSAL_C210, "UNIVERSAL_C210")
 	/* Maintainer: Kyungmin Park <kyungmin.park@samsung.com> */
 	.atag_offset	= 0x100,
+	.smp		= smp_ops(exynos_smp_ops),
 	.init_irq	= exynos4_init_irq,
 	.map_io		= universal_map_io,
 	.handle_irq	= gic_handle_irq,
diff --git a/arch/arm/mach-exynos/platsmp.c b/arch/arm/mach-exynos/platsmp.c
index 36c3984..f93d820 100644
--- a/arch/arm/mach-exynos/platsmp.c
+++ b/arch/arm/mach-exynos/platsmp.c
@@ -32,19 +32,14 @@
 
 #include <plat/cpu.h>
 
+#include "common.h"
+
 extern void exynos4_secondary_startup(void);
 
 #define CPU1_BOOT_REG		(samsung_rev() == EXYNOS4210_REV_1_1 ? \
 				S5P_INFORM5 : S5P_VA_SYSRAM)
 
 /*
- * control for which core is the next to come out of the secondary
- * boot "holding pen"
- */
-
-volatile int __cpuinitdata pen_release = -1;
-
-/*
  * Write pen_release in a way that is guaranteed to be visible to all
  * observers, irrespective of whether they're taking part in coherency
  * or not.  This is necessary for the hotplug code to work reliably.
@@ -64,7 +59,7 @@ static void __iomem *scu_base_addr(void)
 
 static DEFINE_SPINLOCK(boot_lock);
 
-void __cpuinit platform_secondary_init(unsigned int cpu)
+static void __cpuinit exynos_secondary_init(unsigned int cpu)
 {
 	/*
 	 * if any interrupts are already enabled for the primary
@@ -86,7 +81,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
 	spin_unlock(&boot_lock);
 }
 
-int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
+static int __cpuinit exynos_boot_secondary(unsigned int cpu, struct task_struct *idle)
 {
 	unsigned long timeout;
 
@@ -139,7 +134,7 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
 
 		__raw_writel(virt_to_phys(exynos4_secondary_startup),
 			CPU1_BOOT_REG);
-		gic_raise_softirq(cpumask_of(cpu), 1);
+		gic_raise_softirq(cpumask_of(cpu), 0);
 
 		if (pen_release == -1)
 			break;
@@ -161,7 +156,7 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
  * which may be present or become present in the system.
  */
 
-void __init smp_init_cpus(void)
+static void __init exynos_smp_init_cpus(void)
 {
 	void __iomem *scu_base = scu_base_addr();
 	unsigned int i, ncores;
@@ -184,7 +179,7 @@ void __init smp_init_cpus(void)
 	set_smp_cross_call(gic_raise_softirq);
 }
 
-void __init platform_smp_prepare_cpus(unsigned int max_cpus)
+static void __init exynos_smp_prepare_cpus(unsigned int max_cpus)
 {
 	if (!soc_is_exynos5250())
 		scu_enable(scu_base_addr());
@@ -198,3 +193,13 @@ void __init platform_smp_prepare_cpus(unsigned int max_cpus)
 	__raw_writel(virt_to_phys(exynos4_secondary_startup),
 			CPU1_BOOT_REG);
 }
+
+struct smp_operations exynos_smp_ops __initdata = {
+	.smp_init_cpus		= exynos_smp_init_cpus,
+	.smp_prepare_cpus	= exynos_smp_prepare_cpus,
+	.smp_secondary_init	= exynos_secondary_init,
+	.smp_boot_secondary	= exynos_boot_secondary,
+#ifdef CONFIG_HOTPLUG_CPU
+	.cpu_die		= exynos_cpu_die,
+#endif
+};
diff --git a/arch/arm/mach-exynos/setup-fimd0.c b/arch/arm/mach-exynos/setup-fimd0.c
index 07a6dbe..5665bb4 100644
--- a/arch/arm/mach-exynos/setup-fimd0.c
+++ b/arch/arm/mach-exynos/setup-fimd0.c
@@ -13,8 +13,8 @@
 #include <linux/fb.h>
 #include <linux/gpio.h>
 
+#include <video/samsung_fimd.h>
 #include <plat/gpio-cfg.h>
-#include <plat/regs-fb-v4.h>
 
 #include <mach/map.h>
 
diff --git a/arch/arm/mach-exynos/setup-i2c0.c b/arch/arm/mach-exynos/setup-i2c0.c
index b90d94c..5700f23 100644
--- a/arch/arm/mach-exynos/setup-i2c0.c
+++ b/arch/arm/mach-exynos/setup-i2c0.c
@@ -14,7 +14,7 @@
 struct platform_device; /* don't need the contents */
 
 #include <linux/gpio.h>
-#include <plat/iic.h>
+#include <linux/platform_data/i2c-s3c2410.h>
 #include <plat/gpio-cfg.h>
 #include <plat/cpu.h>
 
diff --git a/arch/arm/mach-exynos/setup-i2c1.c b/arch/arm/mach-exynos/setup-i2c1.c
index fd7235a..8d2279c 100644
--- a/arch/arm/mach-exynos/setup-i2c1.c
+++ b/arch/arm/mach-exynos/setup-i2c1.c
@@ -13,7 +13,7 @@
 struct platform_device; /* don't need the contents */
 
 #include <linux/gpio.h>
-#include <plat/iic.h>
+#include <linux/platform_data/i2c-s3c2410.h>
 #include <plat/gpio-cfg.h>
 
 void s3c_i2c1_cfg_gpio(struct platform_device *dev)
diff --git a/arch/arm/mach-exynos/setup-i2c2.c b/arch/arm/mach-exynos/setup-i2c2.c
index 2694b19..0ed62fc 100644
--- a/arch/arm/mach-exynos/setup-i2c2.c
+++ b/arch/arm/mach-exynos/setup-i2c2.c
@@ -13,7 +13,7 @@
 struct platform_device; /* don't need the contents */
 
 #include <linux/gpio.h>
-#include <plat/iic.h>
+#include <linux/platform_data/i2c-s3c2410.h>
 #include <plat/gpio-cfg.h>
 
 void s3c_i2c2_cfg_gpio(struct platform_device *dev)
diff --git a/arch/arm/mach-exynos/setup-i2c3.c b/arch/arm/mach-exynos/setup-i2c3.c
index 379bd30..7787fd2 100644
--- a/arch/arm/mach-exynos/setup-i2c3.c
+++ b/arch/arm/mach-exynos/setup-i2c3.c
@@ -13,7 +13,7 @@
 struct platform_device; /* don't need the contents */
 
 #include <linux/gpio.h>
-#include <plat/iic.h>
+#include <linux/platform_data/i2c-s3c2410.h>
 #include <plat/gpio-cfg.h>
 
 void s3c_i2c3_cfg_gpio(struct platform_device *dev)
diff --git a/arch/arm/mach-exynos/setup-i2c4.c b/arch/arm/mach-exynos/setup-i2c4.c
index 9f3c048..edc847f 100644
--- a/arch/arm/mach-exynos/setup-i2c4.c
+++ b/arch/arm/mach-exynos/setup-i2c4.c
@@ -13,7 +13,7 @@
 struct platform_device; /* don't need the contents */
 
 #include <linux/gpio.h>
-#include <plat/iic.h>
+#include <linux/platform_data/i2c-s3c2410.h>
 #include <plat/gpio-cfg.h>
 
 void s3c_i2c4_cfg_gpio(struct platform_device *dev)
diff --git a/arch/arm/mach-exynos/setup-i2c5.c b/arch/arm/mach-exynos/setup-i2c5.c
index 77e1a1e..d88af7f 100644
--- a/arch/arm/mach-exynos/setup-i2c5.c
+++ b/arch/arm/mach-exynos/setup-i2c5.c
@@ -13,7 +13,7 @@
 struct platform_device; /* don't need the contents */
 
 #include <linux/gpio.h>
-#include <plat/iic.h>
+#include <linux/platform_data/i2c-s3c2410.h>
 #include <plat/gpio-cfg.h>
 
 void s3c_i2c5_cfg_gpio(struct platform_device *dev)
diff --git a/arch/arm/mach-exynos/setup-i2c6.c b/arch/arm/mach-exynos/setup-i2c6.c
index 284d12b..c590286 100644
--- a/arch/arm/mach-exynos/setup-i2c6.c
+++ b/arch/arm/mach-exynos/setup-i2c6.c
@@ -13,7 +13,7 @@
 struct platform_device; /* don't need the contents */
 
 #include <linux/gpio.h>
-#include <plat/iic.h>
+#include <linux/platform_data/i2c-s3c2410.h>
 #include <plat/gpio-cfg.h>
 
 void s3c_i2c6_cfg_gpio(struct platform_device *dev)
diff --git a/arch/arm/mach-exynos/setup-i2c7.c b/arch/arm/mach-exynos/setup-i2c7.c
index b7611ee..1bba755 100644
--- a/arch/arm/mach-exynos/setup-i2c7.c
+++ b/arch/arm/mach-exynos/setup-i2c7.c
@@ -13,7 +13,7 @@
 struct platform_device; /* don't need the contents */
 
 #include <linux/gpio.h>
-#include <plat/iic.h>
+#include <linux/platform_data/i2c-s3c2410.h>
 #include <plat/gpio-cfg.h>
 
 void s3c_i2c7_cfg_gpio(struct platform_device *dev)
diff --git a/arch/arm/mach-footbridge/Makefile b/arch/arm/mach-footbridge/Makefile
index 3afb1b2..0b64dd4 100644
--- a/arch/arm/mach-footbridge/Makefile
+++ b/arch/arm/mach-footbridge/Makefile
@@ -14,15 +14,11 @@ pci-$(CONFIG_ARCH_EBSA285_HOST) += ebsa285-pci.o
 pci-$(CONFIG_ARCH_NETWINDER) += netwinder-pci.o
 pci-$(CONFIG_ARCH_PERSONAL_SERVER) += personal-pci.o
 
-leds-$(CONFIG_ARCH_EBSA285) += ebsa285-leds.o
-leds-$(CONFIG_ARCH_NETWINDER) += netwinder-leds.o
-
 obj-$(CONFIG_ARCH_CATS) += cats-hw.o isa-timer.o
 obj-$(CONFIG_ARCH_EBSA285) += ebsa285.o dc21285-timer.o
 obj-$(CONFIG_ARCH_NETWINDER) += netwinder-hw.o isa-timer.o
 obj-$(CONFIG_ARCH_PERSONAL_SERVER) += personal.o dc21285-timer.o
 
 obj-$(CONFIG_PCI)	+=$(pci-y)
-obj-$(CONFIG_LEDS)	+=$(leds-y)
 
 obj-$(CONFIG_ISA)	+= isa.o isa-rtc.o
diff --git a/arch/arm/mach-footbridge/common.c b/arch/arm/mach-footbridge/common.c
index 3e6aaa6..a42b369 100644
--- a/arch/arm/mach-footbridge/common.c
+++ b/arch/arm/mach-footbridge/common.c
@@ -15,7 +15,7 @@
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/spinlock.h>
- 
+
 #include <asm/pgtable.h>
 #include <asm/page.h>
 #include <asm/irq.h>
@@ -26,6 +26,7 @@
 
 #include <asm/mach/irq.h>
 #include <asm/mach/map.h>
+#include <asm/mach/pci.h>
 
 #include "common.h"
 
@@ -175,11 +176,6 @@ static struct map_desc ebsa285_host_io_desc[] __initdata = {
 		.pfn		= __phys_to_pfn(DC21285_PCI_IACK),
 		.length		= PCIIACK_SIZE,
 		.type		= MT_DEVICE,
-	}, {
-		.virtual	= PCIO_BASE,
-		.pfn		= __phys_to_pfn(DC21285_PCI_IO),
-		.length		= PCIO_SIZE,
-		.type		= MT_DEVICE,
 	},
 #endif
 };
@@ -196,8 +192,10 @@ void __init footbridge_map_io(void)
 	 * Now, work out what we've got to map in addition on this
 	 * platform.
 	 */
-	if (footbridge_cfn_mode())
+	if (footbridge_cfn_mode()) {
 		iotable_init(ebsa285_host_io_desc, ARRAY_SIZE(ebsa285_host_io_desc));
+		pci_map_io_early(__phys_to_pfn(DC21285_PCI_IO));
+	}
 }
 
 void footbridge_restart(char mode, const char *cmd)
diff --git a/arch/arm/mach-footbridge/dc21285.c b/arch/arm/mach-footbridge/dc21285.c
index 9d62e33..a7cd2cf 100644
--- a/arch/arm/mach-footbridge/dc21285.c
+++ b/arch/arm/mach-footbridge/dc21285.c
@@ -276,8 +276,8 @@ int __init dc21285_setup(int nr, struct pci_sys_data *sys)
 
 	sys->mem_offset  = DC21285_PCI_MEM;
 
-	pci_add_resource_offset(&sys->resources,
-				&ioport_resource, sys->io_offset);
+	pci_ioremap_io(0, DC21285_PCI_IO);
+
 	pci_add_resource_offset(&sys->resources, &res[0], sys->mem_offset);
 	pci_add_resource_offset(&sys->resources, &res[1], sys->mem_offset);
 
@@ -298,7 +298,7 @@ void __init dc21285_preinit(void)
 	mem_size = (unsigned int)high_memory - PAGE_OFFSET;
 	for (mem_mask = 0x00100000; mem_mask < 0x10000000; mem_mask <<= 1)
 		if (mem_mask >= mem_size)
-			break;		
+			break;
 
 	/*
 	 * These registers need to be set up whether we're the
@@ -350,14 +350,6 @@ void __init dc21285_preinit(void)
 			    "PCI data parity", NULL);
 
 	if (cfn_mode) {
-		static struct resource csrio;
-
-		csrio.flags  = IORESOURCE_IO;
-		csrio.name   = "Footbridge";
-
-		allocate_resource(&ioport_resource, &csrio, 128,
-				  0xff00, 0xffff, 128, NULL, NULL);
-
 		/*
 		 * Map our SDRAM at a known address in PCI space, just in case
 		 * the firmware had other ideas.  Using a nonzero base is
@@ -365,7 +357,7 @@ void __init dc21285_preinit(void)
 		 * in the range 0x000a0000 to 0x000c0000. (eg, S3 cards).
 		 */
 		*CSR_PCICSRBASE       = 0xf4000000;
-		*CSR_PCICSRIOBASE     = csrio.start;
+		*CSR_PCICSRIOBASE     = 0;
 		*CSR_PCISDRAMBASE     = __virt_to_bus(PAGE_OFFSET);
 		*CSR_PCIROMBASE       = 0;
 		*CSR_PCICMD = PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
diff --git a/arch/arm/mach-footbridge/ebsa285-leds.c b/arch/arm/mach-footbridge/ebsa285-leds.c
deleted file mode 100644
index 5bd2667..0000000
--- a/arch/arm/mach-footbridge/ebsa285-leds.c
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- *  linux/arch/arm/mach-footbridge/ebsa285-leds.c
- *
- *  Copyright (C) 1998-1999 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- * EBSA-285 control routines.
- *
- * The EBSA-285 uses the leds as follows:
- *  - Green - toggles state every 50 timer interrupts
- *  - Amber - On if system is not idle
- *  - Red   - currently unused
- *
- * Changelog:
- *   02-05-1999	RMK	Various cleanups
- */
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-
-#include <mach/hardware.h>
-#include <asm/leds.h>
-#include <asm/mach-types.h>
-
-#define LED_STATE_ENABLED	1
-#define LED_STATE_CLAIMED	2
-static char led_state;
-static char hw_led_state;
-
-static DEFINE_SPINLOCK(leds_lock);
-
-static void ebsa285_leds_event(led_event_t evt)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&leds_lock, flags);
-
-	switch (evt) {
-	case led_start:
-		hw_led_state = XBUS_LED_RED | XBUS_LED_GREEN;
-#ifndef CONFIG_LEDS_CPU
-		hw_led_state |= XBUS_LED_AMBER;
-#endif
-		led_state |= LED_STATE_ENABLED;
-		break;
-
-	case led_stop:
-		led_state &= ~LED_STATE_ENABLED;
-		break;
-
-	case led_claim:
-		led_state |= LED_STATE_CLAIMED;
-		hw_led_state = XBUS_LED_RED | XBUS_LED_GREEN | XBUS_LED_AMBER;
-		break;
-
-	case led_release:
-		led_state &= ~LED_STATE_CLAIMED;
-		hw_led_state = XBUS_LED_RED | XBUS_LED_GREEN | XBUS_LED_AMBER;
-		break;
-
-#ifdef CONFIG_LEDS_TIMER
-	case led_timer:
-		if (!(led_state & LED_STATE_CLAIMED))
-			hw_led_state ^= XBUS_LED_GREEN;
-		break;
-#endif
-
-#ifdef CONFIG_LEDS_CPU
-	case led_idle_start:
-		if (!(led_state & LED_STATE_CLAIMED))
-			hw_led_state |= XBUS_LED_AMBER;
-		break;
-
-	case led_idle_end:
-		if (!(led_state & LED_STATE_CLAIMED))
-			hw_led_state &= ~XBUS_LED_AMBER;
-		break;
-#endif
-
-	case led_halted:
-		if (!(led_state & LED_STATE_CLAIMED))
-			hw_led_state &= ~XBUS_LED_RED;
-		break;
-
-	case led_green_on:
-		if (led_state & LED_STATE_CLAIMED)
-			hw_led_state &= ~XBUS_LED_GREEN;
-		break;
-
-	case led_green_off:
-		if (led_state & LED_STATE_CLAIMED)
-			hw_led_state |= XBUS_LED_GREEN;
-		break;
-
-	case led_amber_on:
-		if (led_state & LED_STATE_CLAIMED)
-			hw_led_state &= ~XBUS_LED_AMBER;
-		break;
-
-	case led_amber_off:
-		if (led_state & LED_STATE_CLAIMED)
-			hw_led_state |= XBUS_LED_AMBER;
-		break;
-
-	case led_red_on:
-		if (led_state & LED_STATE_CLAIMED)
-			hw_led_state &= ~XBUS_LED_RED;
-		break;
-
-	case led_red_off:
-		if (led_state & LED_STATE_CLAIMED)
-			hw_led_state |= XBUS_LED_RED;
-		break;
-
-	default:
-		break;
-	}
-
-	if  (led_state & LED_STATE_ENABLED)
-		*XBUS_LEDS = hw_led_state;
-
-	spin_unlock_irqrestore(&leds_lock, flags);
-}
-
-static int __init leds_init(void)
-{
-	if (machine_is_ebsa285())
-		leds_event = ebsa285_leds_event;
-
-	leds_event(led_start);
-
-	return 0;
-}
-
-__initcall(leds_init);
diff --git a/arch/arm/mach-footbridge/ebsa285.c b/arch/arm/mach-footbridge/ebsa285.c
index 27716a7..b09551e 100644
--- a/arch/arm/mach-footbridge/ebsa285.c
+++ b/arch/arm/mach-footbridge/ebsa285.c
@@ -5,6 +5,8 @@
  */
 #include <linux/init.h>
 #include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/leds.h>
 
 #include <asm/hardware/dec21285.h>
 #include <asm/mach-types.h>
@@ -13,6 +15,85 @@
 
 #include "common.h"
 
+/* LEDs */
+#if defined(CONFIG_NEW_LEDS) && defined(CONFIG_LEDS_CLASS)
+struct ebsa285_led {
+	struct led_classdev     cdev;
+	u8                      mask;
+};
+
+/*
+ * The triggers lines up below will only be used if the
+ * LED triggers are compiled in.
+ */
+static const struct {
+	const char *name;
+	const char *trigger;
+} ebsa285_leds[] = {
+	{ "ebsa285:amber", "heartbeat", },
+	{ "ebsa285:green", "cpu0", },
+	{ "ebsa285:red",},
+};
+
+static void ebsa285_led_set(struct led_classdev *cdev,
+		enum led_brightness b)
+{
+	struct ebsa285_led *led = container_of(cdev,
+			struct ebsa285_led, cdev);
+
+	if (b != LED_OFF)
+		*XBUS_LEDS |= led->mask;
+	else
+		*XBUS_LEDS &= ~led->mask;
+}
+
+static enum led_brightness ebsa285_led_get(struct led_classdev *cdev)
+{
+	struct ebsa285_led *led = container_of(cdev,
+			struct ebsa285_led, cdev);
+
+	return (*XBUS_LEDS & led->mask) ? LED_FULL : LED_OFF;
+}
+
+static int __init ebsa285_leds_init(void)
+{
+	int i;
+
+	if (machine_is_ebsa285())
+		return -ENODEV;
+
+	/* 3 LEDS All ON */
+	*XBUS_LEDS |= XBUS_LED_AMBER | XBUS_LED_GREEN | XBUS_LED_RED;
+
+	for (i = 0; i < ARRAY_SIZE(ebsa285_leds); i++) {
+		struct ebsa285_led *led;
+
+		led = kzalloc(sizeof(*led), GFP_KERNEL);
+		if (!led)
+			break;
+
+		led->cdev.name = ebsa285_leds[i].name;
+		led->cdev.brightness_set = ebsa285_led_set;
+		led->cdev.brightness_get = ebsa285_led_get;
+		led->cdev.default_trigger = ebsa285_leds[i].trigger;
+		led->mask = BIT(i);
+
+		if (led_classdev_register(NULL, &led->cdev) < 0) {
+			kfree(led);
+			break;
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * Since we may have triggers on any subsystem, defer registration
+ * until after subsystem_init.
+ */
+fs_initcall(ebsa285_leds_init);
+#endif
+
 MACHINE_START(EBSA285, "EBSA285")
 	/* Maintainer: Russell King */
 	.atag_offset	= 0x100,
diff --git a/arch/arm/mach-footbridge/include/mach/debug-macro.S b/arch/arm/mach-footbridge/include/mach/debug-macro.S
index e5acde2..c169f0c 100644
--- a/arch/arm/mach-footbridge/include/mach/debug-macro.S
+++ b/arch/arm/mach-footbridge/include/mach/debug-macro.S
@@ -17,7 +17,8 @@
 	/* For NetWinder debugging */
 		.macro	addruart, rp, rv, tmp
 		mov	\rp, #0x000003f8
-		orr	\rv, \rp, #0xff000000	@ virtual
+		orr	\rv, \rp, #0xfe000000	@ virtual
+		orr	\rv, \rv, #0x00e00000	@ virtual
 		orr	\rp, \rp, #0x7c000000	@ physical
 		.endm
 
diff --git a/arch/arm/mach-footbridge/include/mach/io.h b/arch/arm/mach-footbridge/include/mach/io.h
index aba531ee..aba4638 100644
--- a/arch/arm/mach-footbridge/include/mach/io.h
+++ b/arch/arm/mach-footbridge/include/mach/io.h
@@ -14,18 +14,10 @@
 #ifndef __ASM_ARM_ARCH_IO_H
 #define __ASM_ARM_ARCH_IO_H
 
-#ifdef CONFIG_MMU
-#define MMU_IO(a, b)	(a)
-#else
-#define MMU_IO(a, b)	(b)
-#endif
-
-#define PCIO_SIZE       0x00100000
-#define PCIO_BASE       MMU_IO(0xff000000, 0x7c000000)
-
 /*
- * Translation of various region addresses to virtual addresses
+ * Translation of various i/o addresses to host addresses for !CONFIG_MMU
  */
+#define PCIO_BASE       0x7c000000
 #define __io(a)			((void __iomem *)(PCIO_BASE + (a)))
 
 #endif
diff --git a/arch/arm/mach-footbridge/netwinder-hw.c b/arch/arm/mach-footbridge/netwinder-hw.c
index cac9f67..d2d1433 100644
--- a/arch/arm/mach-footbridge/netwinder-hw.c
+++ b/arch/arm/mach-footbridge/netwinder-hw.c
@@ -12,9 +12,10 @@
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/leds.h>
 
 #include <asm/hardware/dec21285.h>
-#include <asm/leds.h>
 #include <asm/mach-types.h>
 #include <asm/setup.h>
 #include <asm/system_misc.h>
@@ -27,13 +28,6 @@
 #define GP1_IO_BASE		0x338
 #define GP2_IO_BASE		0x33a
 
-
-#ifdef CONFIG_LEDS
-#define DEFAULT_LEDS	0
-#else
-#define DEFAULT_LEDS	GPIO_GREEN_LED
-#endif
-
 /*
  * Winbond WB83977F accessibility stuff
  */
@@ -611,15 +605,9 @@ static void __init rwa010_init(void)
 static int __init nw_hw_init(void)
 {
 	if (machine_is_netwinder()) {
-		unsigned long flags;
-
 		wb977_init();
 		cpld_init();
 		rwa010_init();
-
-		raw_spin_lock_irqsave(&nw_gpio_lock, flags);
-		nw_gpio_modify_op(GPIO_RED_LED|GPIO_GREEN_LED, DEFAULT_LEDS);
-		raw_spin_unlock_irqrestore(&nw_gpio_lock, flags);
 	}
 	return 0;
 }
@@ -672,6 +660,102 @@ static void netwinder_restart(char mode, const char *cmd)
 	}
 }
 
+/* LEDs */
+#if defined(CONFIG_NEW_LEDS) && defined(CONFIG_LEDS_CLASS)
+struct netwinder_led {
+	struct led_classdev     cdev;
+	u8                      mask;
+};
+
+/*
+ * The triggers lines up below will only be used if the
+ * LED triggers are compiled in.
+ */
+static const struct {
+	const char *name;
+	const char *trigger;
+} netwinder_leds[] = {
+	{ "netwinder:green", "heartbeat", },
+	{ "netwinder:red", "cpu0", },
+};
+
+/*
+ * The LED control in Netwinder is reversed:
+ *  - setting bit means turn off LED
+ *  - clearing bit means turn on LED
+ */
+static void netwinder_led_set(struct led_classdev *cdev,
+		enum led_brightness b)
+{
+	struct netwinder_led *led = container_of(cdev,
+			struct netwinder_led, cdev);
+	unsigned long flags;
+	u32 reg;
+
+	spin_lock_irqsave(&nw_gpio_lock, flags);
+	reg = nw_gpio_read();
+	if (b != LED_OFF)
+		reg &= ~led->mask;
+	else
+		reg |= led->mask;
+	nw_gpio_modify_op(led->mask, reg);
+	spin_unlock_irqrestore(&nw_gpio_lock, flags);
+}
+
+static enum led_brightness netwinder_led_get(struct led_classdev *cdev)
+{
+	struct netwinder_led *led = container_of(cdev,
+			struct netwinder_led, cdev);
+	unsigned long flags;
+	u32 reg;
+
+	spin_lock_irqsave(&nw_gpio_lock, flags);
+	reg = nw_gpio_read();
+	spin_unlock_irqrestore(&nw_gpio_lock, flags);
+
+	return (reg & led->mask) ? LED_OFF : LED_FULL;
+}
+
+static int __init netwinder_leds_init(void)
+{
+	int i;
+
+	if (!machine_is_netwinder())
+		return -ENODEV;
+
+	for (i = 0; i < ARRAY_SIZE(netwinder_leds); i++) {
+		struct netwinder_led *led;
+
+		led = kzalloc(sizeof(*led), GFP_KERNEL);
+		if (!led)
+			break;
+
+		led->cdev.name = netwinder_leds[i].name;
+		led->cdev.brightness_set = netwinder_led_set;
+		led->cdev.brightness_get = netwinder_led_get;
+		led->cdev.default_trigger = netwinder_leds[i].trigger;
+
+		if (i == 0)
+			led->mask = GPIO_GREEN_LED;
+		else
+			led->mask = GPIO_RED_LED;
+
+		if (led_classdev_register(NULL, &led->cdev) < 0) {
+			kfree(led);
+			break;
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * Since we may have triggers on any subsystem, defer registration
+ * until after subsystem_init.
+ */
+fs_initcall(netwinder_leds_init);
+#endif
+
 MACHINE_START(NETWINDER, "Rebel-NetWinder")
 	/* Maintainer: Russell King/Rebel.com */
 	.atag_offset	= 0x100,
diff --git a/arch/arm/mach-footbridge/netwinder-leds.c b/arch/arm/mach-footbridge/netwinder-leds.c
deleted file mode 100644
index 5a2bd89..0000000
--- a/arch/arm/mach-footbridge/netwinder-leds.c
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- *  linux/arch/arm/mach-footbridge/netwinder-leds.c
- *
- *  Copyright (C) 1998-1999 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * NetWinder LED control routines.
- *
- * The Netwinder uses the leds as follows:
- *  - Green - toggles state every 50 timer interrupts
- *  - Red   - On if the system is not idle
- *
- * Changelog:
- *   02-05-1999	RMK	Various cleanups
- */
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-
-#include <mach/hardware.h>
-#include <asm/leds.h>
-#include <asm/mach-types.h>
-
-#define LED_STATE_ENABLED	1
-#define LED_STATE_CLAIMED	2
-static char led_state;
-static char hw_led_state;
-
-static DEFINE_RAW_SPINLOCK(leds_lock);
-
-static void netwinder_leds_event(led_event_t evt)
-{
-	unsigned long flags;
-
-	raw_spin_lock_irqsave(&leds_lock, flags);
-
-	switch (evt) {
-	case led_start:
-		led_state |= LED_STATE_ENABLED;
-		hw_led_state = GPIO_GREEN_LED;
-		break;
-
-	case led_stop:
-		led_state &= ~LED_STATE_ENABLED;
-		break;
-
-	case led_claim:
-		led_state |= LED_STATE_CLAIMED;
-		hw_led_state = 0;
-		break;
-
-	case led_release:
-		led_state &= ~LED_STATE_CLAIMED;
-		hw_led_state = 0;
-		break;
-
-#ifdef CONFIG_LEDS_TIMER
-	case led_timer:
-		if (!(led_state & LED_STATE_CLAIMED))
-			hw_led_state ^= GPIO_GREEN_LED;
-		break;
-#endif
-
-#ifdef CONFIG_LEDS_CPU
-	case led_idle_start:
-		if (!(led_state & LED_STATE_CLAIMED))
-			hw_led_state &= ~GPIO_RED_LED;
-		break;
-
-	case led_idle_end:
-		if (!(led_state & LED_STATE_CLAIMED))
-			hw_led_state |= GPIO_RED_LED;
-		break;
-#endif
-
-	case led_halted:
-		if (!(led_state & LED_STATE_CLAIMED))
-			hw_led_state |= GPIO_RED_LED;
-		break;
-
-	case led_green_on:
-		if (led_state & LED_STATE_CLAIMED)
-			hw_led_state |= GPIO_GREEN_LED;
-		break;
-
-	case led_green_off:
-		if (led_state & LED_STATE_CLAIMED)
-			hw_led_state &= ~GPIO_GREEN_LED;
-		break;
-
-	case led_amber_on:
-		if (led_state & LED_STATE_CLAIMED)
-			hw_led_state |= GPIO_GREEN_LED | GPIO_RED_LED;
-		break;
-
-	case led_amber_off:
-		if (led_state & LED_STATE_CLAIMED)
-			hw_led_state &= ~(GPIO_GREEN_LED | GPIO_RED_LED);
-		break;
-
-	case led_red_on:
-		if (led_state & LED_STATE_CLAIMED)
-			hw_led_state |= GPIO_RED_LED;
-		break;
-
-	case led_red_off:
-		if (led_state & LED_STATE_CLAIMED)
-			hw_led_state &= ~GPIO_RED_LED;
-		break;
-
-	default:
-		break;
-	}
-
-	raw_spin_unlock_irqrestore(&leds_lock, flags);
-
-	if  (led_state & LED_STATE_ENABLED) {
-		raw_spin_lock_irqsave(&nw_gpio_lock, flags);
-		nw_gpio_modify_op(GPIO_RED_LED | GPIO_GREEN_LED, hw_led_state);
-		raw_spin_unlock_irqrestore(&nw_gpio_lock, flags);
-	}
-}
-
-static int __init leds_init(void)
-{
-	if (machine_is_netwinder())
-		leds_event = netwinder_leds_event;
-
-	leds_event(led_start);
-
-	return 0;
-}
-
-__initcall(leds_init);
diff --git a/arch/arm/mach-highbank/Kconfig b/arch/arm/mach-highbank/Kconfig
new file mode 100644
index 0000000..0e1d0a4
--- /dev/null
+++ b/arch/arm/mach-highbank/Kconfig
@@ -0,0 +1,15 @@
+config ARCH_HIGHBANK
+	bool "Calxeda ECX-1000 (Highbank)" if ARCH_MULTI_V7
+	select ARCH_WANT_OPTIONAL_GPIOLIB
+	select ARM_AMBA
+	select ARM_GIC
+	select ARM_TIMER_SP804
+	select CACHE_L2X0
+	select CLKDEV_LOOKUP
+	select COMMON_CLK
+	select CPU_V7
+	select GENERIC_CLOCKEVENTS
+	select HAVE_ARM_SCU
+	select HAVE_SMP
+	select SPARSE_IRQ
+	select USE_OF
diff --git a/arch/arm/mach-highbank/Makefile.boot b/arch/arm/mach-highbank/Makefile.boot
deleted file mode 100644
index dae9661..0000000
--- a/arch/arm/mach-highbank/Makefile.boot
+++ /dev/null
@@ -1 +0,0 @@
-zreladdr-y	:= 0x00008000
diff --git a/arch/arm/mach-highbank/core.h b/arch/arm/mach-highbank/core.h
index 141ed51..286ec82 100644
--- a/arch/arm/mach-highbank/core.h
+++ b/arch/arm/mach-highbank/core.h
@@ -8,4 +8,13 @@ extern void highbank_lluart_map_io(void);
 static inline void highbank_lluart_map_io(void) {}
 #endif
 
+#ifdef CONFIG_PM_SLEEP
+extern void highbank_pm_init(void);
+#else
+static inline void highbank_pm_init(void) {}
+#endif
+
 extern void highbank_smc1(int fn, int arg);
+extern void highbank_cpu_die(unsigned int cpu);
+
+extern struct smp_operations highbank_smp_ops;
diff --git a/arch/arm/mach-highbank/highbank.c b/arch/arm/mach-highbank/highbank.c
index d75b0a7..40e36a5 100644
--- a/arch/arm/mach-highbank/highbank.c
+++ b/arch/arm/mach-highbank/highbank.c
@@ -15,6 +15,7 @@
  */
 #include <linux/clk.h>
 #include <linux/clkdev.h>
+#include <linux/dma-mapping.h>
 #include <linux/io.h>
 #include <linux/irq.h>
 #include <linux/irqdomain.h>
@@ -23,6 +24,7 @@
 #include <linux/of_platform.h>
 #include <linux/of_address.h>
 #include <linux/smp.h>
+#include <linux/amba/bus.h>
 
 #include <asm/cacheflush.h>
 #include <asm/smp_plat.h>
@@ -149,9 +151,60 @@ static void highbank_power_off(void)
 		cpu_do_idle();
 }
 
+static int highbank_platform_notifier(struct notifier_block *nb,
+				  unsigned long event, void *__dev)
+{
+	struct resource *res;
+	int reg = -1;
+	struct device *dev = __dev;
+
+	if (event != BUS_NOTIFY_ADD_DEVICE)
+		return NOTIFY_DONE;
+
+	if (of_device_is_compatible(dev->of_node, "calxeda,hb-ahci"))
+		reg = 0xc;
+	else if (of_device_is_compatible(dev->of_node, "calxeda,hb-sdhci"))
+		reg = 0x18;
+	else if (of_device_is_compatible(dev->of_node, "arm,pl330"))
+		reg = 0x20;
+	else if (of_device_is_compatible(dev->of_node, "calxeda,hb-xgmac")) {
+		res = platform_get_resource(to_platform_device(dev),
+					    IORESOURCE_MEM, 0);
+		if (res) {
+			if (res->start == 0xfff50000)
+				reg = 0;
+			else if (res->start == 0xfff51000)
+				reg = 4;
+		}
+	}
+
+	if (reg < 0)
+		return NOTIFY_DONE;
+
+	if (of_property_read_bool(dev->of_node, "dma-coherent")) {
+		writel(0xff31, sregs_base + reg);
+		set_dma_ops(dev, &arm_coherent_dma_ops);
+	} else
+		writel(0, sregs_base + reg);
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block highbank_amba_nb = {
+	.notifier_call = highbank_platform_notifier,
+};
+
+static struct notifier_block highbank_platform_nb = {
+	.notifier_call = highbank_platform_notifier,
+};
+
 static void __init highbank_init(void)
 {
 	pm_power_off = highbank_power_off;
+	highbank_pm_init();
+
+	bus_register_notifier(&platform_bus_type, &highbank_platform_nb);
+	bus_register_notifier(&amba_bustype, &highbank_amba_nb);
 
 	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
@@ -162,6 +215,7 @@ static const char *highbank_match[] __initconst = {
 };
 
 DT_MACHINE_START(HIGHBANK, "Highbank")
+	.smp		= smp_ops(highbank_smp_ops),
 	.map_io		= highbank_map_io,
 	.init_irq	= highbank_init_irq,
 	.timer		= &highbank_timer,
diff --git a/arch/arm/mach-highbank/hotplug.c b/arch/arm/mach-highbank/hotplug.c
index 977cebb..2c1b8c3 100644
--- a/arch/arm/mach-highbank/hotplug.c
+++ b/arch/arm/mach-highbank/hotplug.c
@@ -24,16 +24,11 @@
 
 extern void secondary_startup(void);
 
-int platform_cpu_kill(unsigned int cpu)
-{
-	return 1;
-}
-
 /*
  * platform-specific code to shutdown a CPU
  *
  */
-void platform_cpu_die(unsigned int cpu)
+void __ref highbank_cpu_die(unsigned int cpu)
 {
 	flush_cache_all();
 
@@ -45,12 +40,3 @@ void platform_cpu_die(unsigned int cpu)
 	/* We should never return from idle */
 	panic("highbank: cpu %d unexpectedly exit from shutdown\n", cpu);
 }
-
-int platform_cpu_disable(unsigned int cpu)
-{
-	/*
-	 * CPU0 should not be shut down via hotplug.  cpu_idle can WFI
-	 * or a proper shutdown or hibernate should be used.
-	 */
-	return cpu == 0 ? -EPERM : 0;
-}
diff --git a/arch/arm/mach-highbank/include/mach/debug-macro.S b/arch/arm/mach-highbank/include/mach/debug-macro.S
deleted file mode 100644
index cb57fe5..0000000
--- a/arch/arm/mach-highbank/include/mach/debug-macro.S
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Debugging macro include header
- *
- *  Copyright (C) 1994-1999 Russell King
- *  Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-		.macro	addruart,rp,rv,tmp
-		movw	\rv, #0x6000
-		movt	\rv, #0xfee3
-		movw	\rp, #0x6000
-		movt	\rp, #0xfff3
-		.endm
-
-#include <asm/hardware/debug-pl01x.S>
diff --git a/arch/arm/mach-highbank/include/mach/gpio.h b/arch/arm/mach-highbank/include/mach/gpio.h
deleted file mode 100644
index 40a8c17..0000000
--- a/arch/arm/mach-highbank/include/mach/gpio.h
+++ /dev/null
@@ -1 +0,0 @@
-/* empty */
diff --git a/arch/arm/mach-highbank/include/mach/timex.h b/arch/arm/mach-highbank/include/mach/timex.h
deleted file mode 100644
index 88dac7a..0000000
--- a/arch/arm/mach-highbank/include/mach/timex.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __MACH_TIMEX_H
-#define __MACH_TIMEX_H
-
-#define CLOCK_TICK_RATE		1000000
-
-#endif
diff --git a/arch/arm/mach-highbank/include/mach/uncompress.h b/arch/arm/mach-highbank/include/mach/uncompress.h
deleted file mode 100644
index bbe20e6..0000000
--- a/arch/arm/mach-highbank/include/mach/uncompress.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef __MACH_UNCOMPRESS_H
-#define __MACH_UNCOMPRESS_H
-
-#define putc(c)
-#define flush()
-#define arch_decomp_setup()
-#define arch_decomp_wdog()
-
-#endif
diff --git a/arch/arm/mach-highbank/platsmp.c b/arch/arm/mach-highbank/platsmp.c
index d01364c..fa9560e 100644
--- a/arch/arm/mach-highbank/platsmp.c
+++ b/arch/arm/mach-highbank/platsmp.c
@@ -25,12 +25,12 @@
 
 extern void secondary_startup(void);
 
-void __cpuinit platform_secondary_init(unsigned int cpu)
+static void __cpuinit highbank_secondary_init(unsigned int cpu)
 {
 	gic_secondary_init(0);
 }
 
-int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
+static int __cpuinit highbank_boot_secondary(unsigned int cpu, struct task_struct *idle)
 {
 	gic_raise_softirq(cpumask_of(cpu), 0);
 	return 0;
@@ -40,7 +40,7 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
  * Initialise the CPU possible map early - this describes the CPUs
  * which may be present or become present in the system.
  */
-void __init smp_init_cpus(void)
+static void __init highbank_smp_init_cpus(void)
 {
 	unsigned int i, ncores;
 
@@ -61,7 +61,7 @@ void __init smp_init_cpus(void)
 	set_smp_cross_call(gic_raise_softirq);
 }
 
-void __init platform_smp_prepare_cpus(unsigned int max_cpus)
+static void __init highbank_smp_prepare_cpus(unsigned int max_cpus)
 {
 	int i;
 
@@ -76,3 +76,13 @@ void __init platform_smp_prepare_cpus(unsigned int max_cpus)
 	for (i = 1; i < max_cpus; i++)
 		highbank_set_cpu_jump(i, secondary_startup);
 }
+
+struct smp_operations highbank_smp_ops __initdata = {
+	.smp_init_cpus		= highbank_smp_init_cpus,
+	.smp_prepare_cpus	= highbank_smp_prepare_cpus,
+	.smp_secondary_init	= highbank_secondary_init,
+	.smp_boot_secondary	= highbank_boot_secondary,
+#ifdef CONFIG_HOTPLUG_CPU
+	.cpu_die		= highbank_cpu_die,
+#endif
+};
diff --git a/arch/arm/mach-highbank/pm.c b/arch/arm/mach-highbank/pm.c
index 33b3beb..de866f2 100644
--- a/arch/arm/mach-highbank/pm.c
+++ b/arch/arm/mach-highbank/pm.c
@@ -47,9 +47,7 @@ static const struct platform_suspend_ops highbank_pm_ops = {
 	.valid = suspend_valid_only_mem,
 };
 
-static int __init highbank_pm_init(void)
+void __init highbank_pm_init(void)
 {
 	suspend_set_ops(&highbank_pm_ops);
-	return 0;
 }
-module_init(highbank_pm_init);
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index afd542a..32197c1 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -101,13 +101,8 @@ config	SOC_IMX51
 	select SOC_IMX5
 	select ARCH_MX5
 	select ARCH_MX51
-
-config	SOC_IMX53
-	bool
-	select SOC_IMX5
-	select ARCH_MX5
-	select ARCH_MX53
-	select HAVE_CAN_FLEXCAN if CAN
+	select PINCTRL
+	select PINCTRL_IMX51
 
 if ARCH_IMX_V4_V5
 
@@ -303,6 +298,7 @@ config MACH_MX27_3DS
 	select IMX_HAVE_PLATFORM_IMX_FB
 	select IMX_HAVE_PLATFORM_IMX_I2C
 	select IMX_HAVE_PLATFORM_IMX_KEYPAD
+	select IMX_HAVE_PLATFORM_IMX_SSI
 	select IMX_HAVE_PLATFORM_IMX_UART
 	select IMX_HAVE_PLATFORM_MX2_CAMERA
 	select IMX_HAVE_PLATFORM_MXC_EHCI
@@ -561,7 +557,6 @@ config MACH_BUG
 config MACH_IMX31_DT
 	bool "Support i.MX31 platforms from device tree"
 	select SOC_IMX31
-	select USE_OF
 	help
 	  Include support for Freescale i.MX31 based platforms
 	  using the device tree for discovery.
@@ -737,95 +732,19 @@ config MACH_EUKREA_MBIMXSD51_BASEBOARD
 
 endchoice
 
-config MX51_EFIKA_COMMON
-	bool
-	select SOC_IMX51
-	select IMX_HAVE_PLATFORM_IMX_UART
-	select IMX_HAVE_PLATFORM_MXC_EHCI
-	select IMX_HAVE_PLATFORM_PATA_IMX
-	select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
-	select IMX_HAVE_PLATFORM_SPI_IMX
-	select MXC_ULPI if USB_ULPI
+comment "Device tree only"
 
-config MACH_MX51_EFIKAMX
-	bool "Support MX51 Genesi Efika MX nettop"
-	select LEDS_GPIO_REGISTER
-	select MX51_EFIKA_COMMON
-	help
-	  Include support for Genesi Efika MX nettop. This includes specific
-	  configurations for the board and its peripherals.
-
-config MACH_MX51_EFIKASB
-	bool "Support MX51 Genesi Efika Smartbook"
-	select LEDS_GPIO_REGISTER
-	select MX51_EFIKA_COMMON
-	help
-	  Include support for Genesi Efika Smartbook. This includes specific
-	  configurations for the board and its peripherals.
-
-comment "i.MX53 machines:"
-
-config MACH_IMX53_DT
-	bool "Support i.MX53 platforms from device tree"
-	select SOC_IMX53
-	select MACH_MX53_ARD
-	select MACH_MX53_EVK
-	select MACH_MX53_LOCO
-	select MACH_MX53_SMD
-	help
-	  Include support for Freescale i.MX53 based platforms
-	  using the device tree for discovery
-
-config MACH_MX53_EVK
-	bool "Support MX53 EVK platforms"
-	select SOC_IMX53
-	select IMX_HAVE_PLATFORM_IMX2_WDT
-	select IMX_HAVE_PLATFORM_IMX_UART
-	select IMX_HAVE_PLATFORM_IMX_I2C
-	select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
-	select IMX_HAVE_PLATFORM_SPI_IMX
-	select LEDS_GPIO_REGISTER
-	help
-	  Include support for MX53 EVK platform. This includes specific
-	  configurations for the board and its peripherals.
-
-config MACH_MX53_SMD
-	bool "Support MX53 SMD platforms"
-	select SOC_IMX53
-	select IMX_HAVE_PLATFORM_IMX2_WDT
-	select IMX_HAVE_PLATFORM_IMX_I2C
-	select IMX_HAVE_PLATFORM_IMX_UART
-	select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
-	help
-	  Include support for MX53 SMD platform. This includes specific
-	  configurations for the board and its peripherals.
-
-config MACH_MX53_LOCO
-	bool "Support MX53 LOCO platforms"
-	select SOC_IMX53
-	select IMX_HAVE_PLATFORM_IMX2_WDT
-	select IMX_HAVE_PLATFORM_IMX_I2C
-	select IMX_HAVE_PLATFORM_IMX_UART
-	select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
-	select IMX_HAVE_PLATFORM_GPIO_KEYS
-	select LEDS_GPIO_REGISTER
-	help
-	  Include support for MX53 LOCO platform. This includes specific
-	  configurations for the board and its peripherals.
+config	SOC_IMX53
+	bool "i.MX53 support"
+	select SOC_IMX5
+	select ARCH_MX5
+	select ARCH_MX53
+	select HAVE_CAN_FLEXCAN if CAN
+	select PINCTRL
+	select PINCTRL_IMX53
 
-config MACH_MX53_ARD
-	bool "Support MX53 ARD platforms"
-	select SOC_IMX53
-	select IMX_HAVE_PLATFORM_IMX2_WDT
-	select IMX_HAVE_PLATFORM_IMX_I2C
-	select IMX_HAVE_PLATFORM_IMX_UART
-	select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
-	select IMX_HAVE_PLATFORM_GPIO_KEYS
 	help
-	  Include support for MX53 ARD platform. This includes specific
-	  configurations for the board and its peripherals.
-
-comment "i.MX6 family:"
+	  This enables support for Freescale i.MX53 processor.
 
 config SOC_IMX6Q
 	bool "i.MX6 Quad support"
@@ -839,7 +758,7 @@ config SOC_IMX6Q
 	select HAVE_IMX_MMDC
 	select HAVE_IMX_SRC
 	select HAVE_SMP
-	select MFD_ANATOP
+	select MFD_SYSCON
 	select PINCTRL
 	select PINCTRL_IMX6Q
 
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index d004d37..895754a 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -13,7 +13,7 @@ imx5-pm-$(CONFIG_PM) += pm-imx5.o
 obj-$(CONFIG_SOC_IMX5) += cpu-imx5.o mm-imx5.o clk-imx51-imx53.o ehci-imx5.o $(imx5-pm-y) cpu_op-mx51.o
 
 obj-$(CONFIG_COMMON_CLK) += clk-pllv1.o clk-pllv2.o clk-pllv3.o clk-gate2.o \
-			    clk-pfd.o clk-busy.o
+			    clk-pfd.o clk-busy.o clk.o
 
 # Support for CMOS sensor interface
 obj-$(CONFIG_MX1_VIDEO) += mx1-camera-fiq.o mx1-camera-fiq-ksym.o
@@ -83,16 +83,9 @@ endif
 # i.MX5 based machines
 obj-$(CONFIG_MACH_MX51_BABBAGE) += mach-mx51_babbage.o
 obj-$(CONFIG_MACH_MX51_3DS) += mach-mx51_3ds.o
-obj-$(CONFIG_MACH_MX53_EVK) += mach-mx53_evk.o
-obj-$(CONFIG_MACH_MX53_SMD) += mach-mx53_smd.o
-obj-$(CONFIG_MACH_MX53_LOCO) += mach-mx53_loco.o
-obj-$(CONFIG_MACH_MX53_ARD) += mach-mx53_ard.o
 obj-$(CONFIG_MACH_EUKREA_CPUIMX51SD) += mach-cpuimx51sd.o
 obj-$(CONFIG_MACH_EUKREA_MBIMXSD51_BASEBOARD) += eukrea_mbimxsd51-baseboard.o
-obj-$(CONFIG_MX51_EFIKA_COMMON) += mx51_efika.o
-obj-$(CONFIG_MACH_MX51_EFIKAMX) += mach-mx51_efikamx.o
-obj-$(CONFIG_MACH_MX51_EFIKASB) += mach-mx51_efikasb.o
 obj-$(CONFIG_MACH_MX50_RDP) += mach-mx50_rdp.o
 
 obj-$(CONFIG_MACH_IMX51_DT) += imx51-dt.o
-obj-$(CONFIG_MACH_IMX53_DT) += imx53-dt.o
+obj-$(CONFIG_SOC_IMX53) += mach-imx53.o
diff --git a/arch/arm/mach-imx/Makefile.boot b/arch/arm/mach-imx/Makefile.boot
index 05541cf..b27815d 100644
--- a/arch/arm/mach-imx/Makefile.boot
+++ b/arch/arm/mach-imx/Makefile.boot
@@ -37,10 +37,3 @@ initrd_phys-$(CONFIG_SOC_IMX53)	:= 0x70800000
 zreladdr-$(CONFIG_SOC_IMX6Q)	+= 0x10008000
 params_phys-$(CONFIG_SOC_IMX6Q)	:= 0x10000100
 initrd_phys-$(CONFIG_SOC_IMX6Q)	:= 0x10800000
-
-dtb-$(CONFIG_MACH_IMX51_DT) += imx51-babbage.dtb
-dtb-$(CONFIG_MACH_IMX53_DT) += imx53-ard.dtb imx53-evk.dtb \
-			       imx53-qsb.dtb imx53-smd.dtb
-dtb-$(CONFIG_SOC_IMX6Q)	+= imx6q-arm2.dtb \
-			   imx6q-sabrelite.dtb \
-			   imx6q-sabresd.dtb \
diff --git a/arch/arm/mach-imx/clk-imx21.c b/arch/arm/mach-imx/clk-imx21.c
index ea13e61..cf65148 100644
--- a/arch/arm/mach-imx/clk-imx21.c
+++ b/arch/arm/mach-imx/clk-imx21.c
@@ -23,7 +23,6 @@
 #include <linux/clk-provider.h>
 #include <linux/io.h>
 #include <linux/module.h>
-#include <linux/clkdev.h>
 #include <linux/err.h>
 
 #include <mach/hardware.h>
diff --git a/arch/arm/mach-imx/clk-imx27.c b/arch/arm/mach-imx/clk-imx27.c
index f69ca46..3b6b640 100644
--- a/arch/arm/mach-imx/clk-imx27.c
+++ b/arch/arm/mach-imx/clk-imx27.c
@@ -239,8 +239,8 @@ int __init mx27_clocks_init(unsigned long fref)
 	clk_register_clkdev(clk[ssi1_ipg_gate], NULL, "imx-ssi.0");
 	clk_register_clkdev(clk[ssi2_ipg_gate], NULL, "imx-ssi.1");
 	clk_register_clkdev(clk[nfc_baud_gate], NULL, "mxc_nand.0");
-	clk_register_clkdev(clk[vpu_baud_gate], "per", "imx-vpu");
-	clk_register_clkdev(clk[vpu_ahb_gate], "ahb", "imx-vpu");
+	clk_register_clkdev(clk[vpu_baud_gate], "per", "coda-imx27.0");
+	clk_register_clkdev(clk[vpu_ahb_gate], "ahb", "coda-imx27.0");
 	clk_register_clkdev(clk[dma_ahb_gate], "ahb", "imx-dma");
 	clk_register_clkdev(clk[dma_ipg_gate], "ipg", "imx-dma");
 	clk_register_clkdev(clk[fec_ipg_gate], "ipg", "imx27-fec.0");
diff --git a/arch/arm/mach-imx/clk-imx35.c b/arch/arm/mach-imx/clk-imx35.c
index 65fb8bc..177259b 100644
--- a/arch/arm/mach-imx/clk-imx35.c
+++ b/arch/arm/mach-imx/clk-imx35.c
@@ -62,8 +62,8 @@ enum mx35_clks {
 	kpp_gate, mlb_gate, mshc_gate, owire_gate, pwm_gate, rngc_gate,
 	rtc_gate, rtic_gate, scc_gate, sdma_gate, spba_gate, spdif_gate,
 	ssi1_gate, ssi2_gate, uart1_gate, uart2_gate, uart3_gate, usbotg_gate,
-	wdog_gate, max_gate, admux_gate, csi_gate, iim_gate, gpu2d_gate,
-	clk_max
+	wdog_gate, max_gate, admux_gate, csi_gate, csi_div, csi_sel, iim_gate,
+	gpu2d_gate, clk_max
 };
 
 static struct clk *clk[clk_max];
@@ -142,6 +142,9 @@ int __init mx35_clocks_init()
 
 	clk[nfc_div] = imx_clk_divider("nfc_div", "ahb", base + MX35_CCM_PDR4, 28, 4);
 
+	clk[csi_sel] = imx_clk_mux("csi_sel", base + MX35_CCM_PDR2, 7, 1, std_sel, ARRAY_SIZE(std_sel));
+	clk[csi_div] = imx_clk_divider("csi_div", "csi_sel", base + MX35_CCM_PDR2, 16, 6);
+
 	clk[asrc_gate] = imx_clk_gate2("asrc_gate", "ipg", base + MX35_CCM_CGR0,  0);
 	clk[pata_gate] = imx_clk_gate2("pata_gate", "ipg", base + MX35_CCM_CGR0,  2);
 	clk[audmux_gate] = imx_clk_gate2("audmux_gate", "ipg", base + MX35_CCM_CGR0,  4);
@@ -192,7 +195,7 @@ int __init mx35_clocks_init()
 	clk[max_gate] = imx_clk_gate2("max_gate", "dummy", base + MX35_CCM_CGR2, 26);
 	clk[admux_gate] = imx_clk_gate2("admux_gate", "ipg", base + MX35_CCM_CGR2, 30);
 
-	clk[csi_gate] = imx_clk_gate2("csi_gate", "ipg", base + MX35_CCM_CGR3,  0);
+	clk[csi_gate] = imx_clk_gate2("csi_gate", "csi_div", base + MX35_CCM_CGR3,  0);
 	clk[iim_gate] = imx_clk_gate2("iim_gate", "ipg", base + MX35_CCM_CGR3,  2);
 	clk[gpu2d_gate] = imx_clk_gate2("gpu2d_gate", "ahb", base + MX35_CCM_CGR3,  4);
 
@@ -228,6 +231,7 @@ int __init mx35_clocks_init()
 	clk_register_clkdev(clk[i2c3_gate], NULL, "imx-i2c.2");
 	clk_register_clkdev(clk[ipu_gate], NULL, "ipu-core");
 	clk_register_clkdev(clk[ipu_gate], NULL, "mx3_sdc_fb");
+	clk_register_clkdev(clk[kpp_gate], NULL, "imx-keypad");
 	clk_register_clkdev(clk[owire_gate], NULL, "mxc_w1");
 	clk_register_clkdev(clk[sdma_gate], NULL, "imx35-sdma");
 	clk_register_clkdev(clk[ssi1_gate], NULL, "imx-ssi.0");
@@ -253,6 +257,7 @@ int __init mx35_clocks_init()
 	clk_register_clkdev(clk[usbotg_gate], "ahb", "fsl-usb2-udc");
 	clk_register_clkdev(clk[wdog_gate], NULL, "imx2-wdt.0");
 	clk_register_clkdev(clk[nfc_div], NULL, "mxc_nand.0");
+	clk_register_clkdev(clk[csi_gate], NULL, "mx3-camera.0");
 
 	clk_prepare_enable(clk[spba_gate]);
 	clk_prepare_enable(clk[gpio1_gate]);
diff --git a/arch/arm/mach-imx/clk-imx51-imx53.c b/arch/arm/mach-imx/clk-imx51-imx53.c
index 4bdcaa9..a0bf848 100644
--- a/arch/arm/mach-imx/clk-imx51-imx53.c
+++ b/arch/arm/mach-imx/clk-imx51-imx53.c
@@ -39,16 +39,17 @@ static const char *ssi_ext2_com_sels[] = { "ssi_ext2_podf", "ssi2_root_gate", };
 static const char *emi_slow_sel[] = { "main_bus", "ahb", };
 static const char *usb_phy_sel_str[] = { "osc", "usb_phy_podf", };
 static const char *mx51_ipu_di0_sel[] = { "di_pred", "osc", "ckih1", "tve_di", };
-static const char *mx53_ipu_di0_sel[] = { "di_pred", "osc", "ckih1", "di_pll4_podf", "dummy", "ldb_di0", };
+static const char *mx53_ipu_di0_sel[] = { "di_pred", "osc", "ckih1", "di_pll4_podf", "dummy", "ldb_di0_gate", };
 static const char *mx53_ldb_di0_sel[] = { "pll3_sw", "pll4_sw", };
 static const char *mx51_ipu_di1_sel[] = { "di_pred", "osc", "ckih1", "tve_di", "ipp_di1", };
-static const char *mx53_ipu_di1_sel[] = { "di_pred", "osc", "ckih1", "tve_di", "ipp_di1", "ldb_di1", };
+static const char *mx53_ipu_di1_sel[] = { "di_pred", "osc", "ckih1", "tve_di", "ipp_di1", "ldb_di1_gate", };
 static const char *mx53_ldb_di1_sel[] = { "pll3_sw", "pll4_sw", };
 static const char *mx51_tve_ext_sel[] = { "osc", "ckih1", };
 static const char *mx53_tve_ext_sel[] = { "pll4_sw", "ckih1", };
 static const char *tve_sel[] = { "tve_pred", "tve_ext_sel", };
 static const char *ipu_sel[] = { "axi_a", "axi_b", "emi_slow_gate", "ahb", };
 static const char *vpu_sel[] = { "axi_a", "axi_b", "emi_slow_gate", "ahb", };
+static const char *mx53_can_sel[] = { "ipg", "ckih1", "ckih2", "lp_apm", };
 
 enum imx5_clks {
 	dummy, ckil, osc, ckih1, ckih2, ahb, ipg, axi_a, axi_b, uart_pred,
@@ -82,6 +83,7 @@ enum imx5_clks {
 	ssi_ext1_podf, ssi_ext2_pred, ssi_ext2_podf, ssi1_root_gate,
 	ssi2_root_gate, ssi3_root_gate, ssi_ext1_gate, ssi_ext2_gate,
 	epit1_ipg_gate, epit1_hf_gate, epit2_ipg_gate, epit2_hf_gate,
+	can_sel, can1_serial_gate, can1_ipg_gate,
 	clk_max
 };
 
@@ -367,6 +369,7 @@ int __init mx51_clocks_init(unsigned long rate_ckil, unsigned long rate_osc,
 	clk_register_clkdev(clk[ssi1_ipg_gate], NULL, "83fcc000.ssi");
 	clk_register_clkdev(clk[ssi2_ipg_gate], NULL, "70014000.ssi");
 	clk_register_clkdev(clk[ssi3_ipg_gate], NULL, "83fe8000.ssi");
+	clk_register_clkdev(clk[nfc_gate], NULL, "83fdb000.nand");
 
 	/* set the usboh3 parent to pll2_sw */
 	clk_set_parent(clk[usboh3_sel], clk[pll2_sw]);
@@ -421,8 +424,12 @@ int __init mx53_clocks_init(unsigned long rate_ckil, unsigned long rate_osc,
 	clk[esdhc4_per_gate] = imx_clk_gate2("esdhc4_per_gate", "esdhc_d_sel", MXC_CCM_CCGR3, 14);
 	clk[usb_phy1_gate] = imx_clk_gate2("usb_phy1_gate", "usb_phy_sel", MXC_CCM_CCGR4, 10);
 	clk[usb_phy2_gate] = imx_clk_gate2("usb_phy2_gate", "usb_phy_sel", MXC_CCM_CCGR4, 12);
-	clk[can2_serial_gate] = imx_clk_gate2("can2_serial_gate", "ipg", MXC_CCM_CCGR4, 6);
-	clk[can2_ipg_gate] = imx_clk_gate2("can2_ipg_gate", "ipg", MXC_CCM_CCGR4, 8);
+	clk[can_sel] = imx_clk_mux("can_sel", MXC_CCM_CSCMR2, 6, 2,
+				mx53_can_sel, ARRAY_SIZE(mx53_can_sel));
+	clk[can1_serial_gate] = imx_clk_gate2("can1_serial_gate", "can_sel", MXC_CCM_CCGR6, 22);
+	clk[can1_ipg_gate] = imx_clk_gate2("can1_ipg_gate", "ipg", MXC_CCM_CCGR6, 20);
+	clk[can2_serial_gate] = imx_clk_gate2("can2_serial_gate", "can_sel", MXC_CCM_CCGR4, 8);
+	clk[can2_ipg_gate] = imx_clk_gate2("can2_ipg_gate", "ipg", MXC_CCM_CCGR4, 6);
 	clk[i2c3_gate] = imx_clk_gate2("i2c3_gate", "per_root", MXC_CCM_CCGR1, 22);
 
 	for (i = 0; i < ARRAY_SIZE(clk); i++)
@@ -455,6 +462,11 @@ int __init mx53_clocks_init(unsigned long rate_ckil, unsigned long rate_osc,
 	clk_register_clkdev(clk[ssi1_ipg_gate], NULL, "63fcc000.ssi");
 	clk_register_clkdev(clk[ssi2_ipg_gate], NULL, "50014000.ssi");
 	clk_register_clkdev(clk[ssi3_ipg_gate], NULL, "63fd0000.ssi");
+	clk_register_clkdev(clk[nfc_gate], NULL, "63fdb000.nand");
+	clk_register_clkdev(clk[can1_ipg_gate], "ipg", "53fc8000.can");
+	clk_register_clkdev(clk[can1_serial_gate], "per", "53fc8000.can");
+	clk_register_clkdev(clk[can2_ipg_gate], "ipg", "53fcc000.can");
+	clk_register_clkdev(clk[can2_serial_gate], "per", "53fcc000.can");
 
 	/* set SDHC root clock to 200MHZ*/
 	clk_set_rate(clk[esdhc_a_podf], 200000000);
diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c
index 4233d9e..3ec242f 100644
--- a/arch/arm/mach-imx/clk-imx6q.c
+++ b/arch/arm/mach-imx/clk-imx6q.c
@@ -157,6 +157,7 @@ enum mx6q_clks {
 };
 
 static struct clk *clk[clk_max];
+static struct clk_onecell_data clk_data;
 
 static enum mx6q_clks const clks_init_on[] __initconst = {
 	mmdc_ch0_axi, rom,
@@ -394,52 +395,24 @@ int __init mx6q_clocks_init(void)
 			pr_err("i.MX6q clk %d: register failed with %ld\n",
 				i, PTR_ERR(clk[i]));
 
+	clk_data.clks = clk;
+	clk_data.clk_num = ARRAY_SIZE(clk);
+	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+
 	clk_register_clkdev(clk[gpt_ipg], "ipg", "imx-gpt.0");
 	clk_register_clkdev(clk[gpt_ipg_per], "per", "imx-gpt.0");
 	clk_register_clkdev(clk[twd], NULL, "smp_twd");
-	clk_register_clkdev(clk[apbh_dma], NULL, "110000.dma-apbh");
-	clk_register_clkdev(clk[per1_bch], "per1_bch", "112000.gpmi-nand");
-	clk_register_clkdev(clk[gpmi_bch_apb], "gpmi_bch_apb", "112000.gpmi-nand");
-	clk_register_clkdev(clk[gpmi_bch], "gpmi_bch", "112000.gpmi-nand");
-	clk_register_clkdev(clk[gpmi_apb], "gpmi_apb", "112000.gpmi-nand");
-	clk_register_clkdev(clk[gpmi_io], "gpmi_io", "112000.gpmi-nand");
-	clk_register_clkdev(clk[usboh3], NULL, "2184000.usb");
-	clk_register_clkdev(clk[usboh3], NULL, "2184200.usb");
-	clk_register_clkdev(clk[usboh3], NULL, "2184400.usb");
-	clk_register_clkdev(clk[usboh3], NULL, "2184600.usb");
-	clk_register_clkdev(clk[usbphy1], NULL, "20c9000.usbphy");
-	clk_register_clkdev(clk[usbphy2], NULL, "20ca000.usbphy");
-	clk_register_clkdev(clk[uart_serial], "per", "2020000.serial");
-	clk_register_clkdev(clk[uart_ipg], "ipg", "2020000.serial");
-	clk_register_clkdev(clk[uart_serial], "per", "21e8000.serial");
-	clk_register_clkdev(clk[uart_ipg], "ipg", "21e8000.serial");
-	clk_register_clkdev(clk[uart_serial], "per", "21ec000.serial");
-	clk_register_clkdev(clk[uart_ipg], "ipg", "21ec000.serial");
-	clk_register_clkdev(clk[uart_serial], "per", "21f0000.serial");
-	clk_register_clkdev(clk[uart_ipg], "ipg", "21f0000.serial");
-	clk_register_clkdev(clk[uart_serial], "per", "21f4000.serial");
-	clk_register_clkdev(clk[uart_ipg], "ipg", "21f4000.serial");
-	clk_register_clkdev(clk[enet], NULL, "2188000.ethernet");
-	clk_register_clkdev(clk[usdhc1], NULL, "2190000.usdhc");
-	clk_register_clkdev(clk[usdhc2], NULL, "2194000.usdhc");
-	clk_register_clkdev(clk[usdhc3], NULL, "2198000.usdhc");
-	clk_register_clkdev(clk[usdhc4], NULL, "219c000.usdhc");
-	clk_register_clkdev(clk[i2c1], NULL, "21a0000.i2c");
-	clk_register_clkdev(clk[i2c2], NULL, "21a4000.i2c");
-	clk_register_clkdev(clk[i2c3], NULL, "21a8000.i2c");
-	clk_register_clkdev(clk[ecspi1], NULL, "2008000.ecspi");
-	clk_register_clkdev(clk[ecspi2], NULL, "200c000.ecspi");
-	clk_register_clkdev(clk[ecspi3], NULL, "2010000.ecspi");
-	clk_register_clkdev(clk[ecspi4], NULL, "2014000.ecspi");
-	clk_register_clkdev(clk[ecspi5], NULL, "2018000.ecspi");
-	clk_register_clkdev(clk[sdma], NULL, "20ec000.sdma");
-	clk_register_clkdev(clk[dummy], NULL, "20bc000.wdog");
-	clk_register_clkdev(clk[dummy], NULL, "20c0000.wdog");
-	clk_register_clkdev(clk[ssi1_ipg], NULL, "2028000.ssi");
 	clk_register_clkdev(clk[cko1_sel], "cko1_sel", NULL);
 	clk_register_clkdev(clk[ahb], "ahb", NULL);
 	clk_register_clkdev(clk[cko1], "cko1", NULL);
 
+	/*
+	 * The gpmi needs 100MHz frequency in the EDO/Sync mode,
+	 * We can not get the 100MHz from the pll2_pfd0_352m.
+	 * So choose pll2_pfd2_396m as enfc_sel's parent.
+	 */
+	clk_set_parent(clk[enfc_sel], clk[pll2_pfd2_396m]);
+
 	for (i = 0; i < ARRAY_SIZE(clks_init_on); i++)
 		clk_prepare_enable(clk[clks_init_on[i]]);
 
diff --git a/arch/arm/mach-imx/clk-pllv1.c b/arch/arm/mach-imx/clk-pllv1.c
index 2d856f9..02be731 100644
--- a/arch/arm/mach-imx/clk-pllv1.c
+++ b/arch/arm/mach-imx/clk-pllv1.c
@@ -6,7 +6,7 @@
 #include <linux/err.h>
 #include <mach/common.h>
 #include <mach/hardware.h>
-#include <mach/clock.h>
+
 #include "clk.h"
 
 /**
@@ -29,8 +29,53 @@ static unsigned long clk_pllv1_recalc_rate(struct clk_hw *hw,
 		unsigned long parent_rate)
 {
 	struct clk_pllv1 *pll = to_clk_pllv1(hw);
+	long long ll;
+	int mfn_abs;
+	unsigned int mfi, mfn, mfd, pd;
+	u32 reg;
+	unsigned long rate;
+
+	reg = readl(pll->base);
+
+	/*
+	 * Get the resulting clock rate from a PLL register value and the input
+	 * frequency. PLLs with this register layout can be found on i.MX1,
+	 * i.MX21, i.MX27 and i,MX31
+	 *
+	 *                  mfi + mfn / (mfd + 1)
+	 *  f = 2 * f_ref * --------------------
+	 *                        pd + 1
+	 */
+
+	mfi = (reg >> 10) & 0xf;
+	mfn = reg & 0x3ff;
+	mfd = (reg >> 16) & 0x3ff;
+	pd =  (reg >> 26) & 0xf;
+
+	mfi = mfi <= 5 ? 5 : mfi;
+
+	mfn_abs = mfn;
+
+	/*
+	 * On all i.MXs except i.MX1 and i.MX21 mfn is a 10bit
+	 * 2's complements number
+	 */
+	if (!cpu_is_mx1() && !cpu_is_mx21() && mfn >= 0x200)
+		mfn_abs = 0x400 - mfn;
+
+	rate = parent_rate * 2;
+	rate /= pd + 1;
+
+	ll = (unsigned long long)rate * mfn_abs;
+
+	do_div(ll, mfd + 1);
+
+	if (!cpu_is_mx1() && !cpu_is_mx21() && mfn >= 0x200)
+		ll = -ll;
+
+	ll = (rate * mfi) + ll;
 
-	return mxc_decode_pll(readl(pll->base), parent_rate);
+	return ll;
 }
 
 struct clk_ops clk_pllv1_ops = {
diff --git a/arch/arm/mach-imx/clk.c b/arch/arm/mach-imx/clk.c
new file mode 100644
index 0000000..f5e8be8
--- /dev/null
+++ b/arch/arm/mach-imx/clk.c
@@ -0,0 +1,3 @@
+#include <linux/spinlock.h>
+
+DEFINE_SPINLOCK(imx_ccm_lock);
diff --git a/arch/arm/mach-imx/clk.h b/arch/arm/mach-imx/clk.h
index 1bf64fe..5f2d8ac 100644
--- a/arch/arm/mach-imx/clk.h
+++ b/arch/arm/mach-imx/clk.h
@@ -3,7 +3,8 @@
 
 #include <linux/spinlock.h>
 #include <linux/clk-provider.h>
-#include <mach/clock.h>
+
+extern spinlock_t imx_ccm_lock;
 
 struct clk *imx_clk_pllv1(const char *name, const char *parent,
 		void __iomem *base);
diff --git a/arch/arm/mach-imx/devices-imx27.h b/arch/arm/mach-imx/devices-imx27.h
index 436c572..0482293 100644
--- a/arch/arm/mach-imx/devices-imx27.h
+++ b/arch/arm/mach-imx/devices-imx27.h
@@ -17,6 +17,10 @@ extern const struct imx_fsl_usb2_udc_data imx27_fsl_usb2_udc_data;
 #define imx27_add_fsl_usb2_udc(pdata)	\
 	imx_add_fsl_usb2_udc(&imx27_fsl_usb2_udc_data, pdata)
 
+extern const struct imx_imx27_coda_data imx27_coda_data;
+#define imx27_add_coda()	\
+	imx_add_imx27_coda(&imx27_coda_data)
+
 extern const struct imx_imx2_wdt_data imx27_imx2_wdt_data;
 #define imx27_add_imx2_wdt()	\
 	imx_add_imx2_wdt(&imx27_imx2_wdt_data)
diff --git a/arch/arm/mach-imx/devices-imx53.h b/arch/arm/mach-imx/devices-imx53.h
deleted file mode 100644
index 77e0db9..0000000
--- a/arch/arm/mach-imx/devices-imx53.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2010 Yong Shen. <Yong.Shen@linaro.org>
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License version 2 as published by the
- * Free Software Foundation.
- */
-#include <mach/mx53.h>
-#include <mach/devices-common.h>
-
-extern const struct imx_fec_data imx53_fec_data;
-#define imx53_add_fec(pdata)   \
-	imx_add_fec(&imx53_fec_data, pdata)
-
-extern const struct imx_imx_uart_1irq_data imx53_imx_uart_data[];
-#define imx53_add_imx_uart(id, pdata)	\
-	imx_add_imx_uart_1irq(&imx53_imx_uart_data[id], pdata)
-
-
-extern const struct imx_imx_i2c_data imx53_imx_i2c_data[];
-#define imx53_add_imx_i2c(id, pdata)	\
-	imx_add_imx_i2c(&imx53_imx_i2c_data[id], pdata)
-
-extern const struct imx_sdhci_esdhc_imx_data imx53_sdhci_esdhc_imx_data[];
-#define imx53_add_sdhci_esdhc_imx(id, pdata)	\
-	imx_add_sdhci_esdhc_imx(&imx53_sdhci_esdhc_imx_data[id], pdata)
-
-extern const struct imx_spi_imx_data imx53_ecspi_data[];
-#define imx53_add_ecspi(id, pdata)	\
-	imx_add_spi_imx(&imx53_ecspi_data[id], pdata)
-
-extern const struct imx_imx2_wdt_data imx53_imx2_wdt_data[];
-#define imx53_add_imx2_wdt(id)	\
-	imx_add_imx2_wdt(&imx53_imx2_wdt_data[id])
-
-extern const struct imx_imx_ssi_data imx53_imx_ssi_data[];
-#define imx53_add_imx_ssi(id, pdata)	\
-	imx_add_imx_ssi(&imx53_imx_ssi_data[id], pdata)
-
-extern const struct imx_imx_keypad_data imx53_imx_keypad_data;
-#define imx53_add_imx_keypad(pdata)	\
-	imx_add_imx_keypad(&imx53_imx_keypad_data, pdata)
-
-extern const struct imx_pata_imx_data imx53_pata_imx_data;
-#define imx53_add_pata_imx() \
-	imx_add_pata_imx(&imx53_pata_imx_data)
-
-extern struct platform_device *__init imx53_add_ahci_imx(void);
diff --git a/arch/arm/mach-imx/efika.h b/arch/arm/mach-imx/efika.h
deleted file mode 100644
index 014aa98..0000000
--- a/arch/arm/mach-imx/efika.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef _EFIKA_H
-#define _EFIKA_H
-
-#define EFIKA_WLAN_EN		IMX_GPIO_NR(2, 16)
-#define EFIKA_WLAN_RESET	IMX_GPIO_NR(2, 10)
-#define EFIKA_USB_PHY_RESET	IMX_GPIO_NR(2, 9)
-
-void __init efika_board_common_init(void);
-
-#endif
diff --git a/arch/arm/mach-imx/ehci-imx25.c b/arch/arm/mach-imx/ehci-imx25.c
index 05bb41d..412c583 100644
--- a/arch/arm/mach-imx/ehci-imx25.c
+++ b/arch/arm/mach-imx/ehci-imx25.c
@@ -17,7 +17,7 @@
 #include <linux/io.h>
 
 #include <mach/hardware.h>
-#include <mach/mxc_ehci.h>
+#include <linux/platform_data/usb-ehci-mxc.h>
 
 #define USBCTRL_OTGBASE_OFFSET	0x600
 
diff --git a/arch/arm/mach-imx/ehci-imx27.c b/arch/arm/mach-imx/ehci-imx27.c
index fa69419..cd6e1f8 100644
--- a/arch/arm/mach-imx/ehci-imx27.c
+++ b/arch/arm/mach-imx/ehci-imx27.c
@@ -17,7 +17,7 @@
 #include <linux/io.h>
 
 #include <mach/hardware.h>
-#include <mach/mxc_ehci.h>
+#include <linux/platform_data/usb-ehci-mxc.h>
 
 #define USBCTRL_OTGBASE_OFFSET	0x600
 
diff --git a/arch/arm/mach-imx/ehci-imx31.c b/arch/arm/mach-imx/ehci-imx31.c
index faad0f1..9a880c7 100644
--- a/arch/arm/mach-imx/ehci-imx31.c
+++ b/arch/arm/mach-imx/ehci-imx31.c
@@ -17,7 +17,7 @@
 #include <linux/io.h>
 
 #include <mach/hardware.h>
-#include <mach/mxc_ehci.h>
+#include <linux/platform_data/usb-ehci-mxc.h>
 
 #define USBCTRL_OTGBASE_OFFSET	0x600
 
diff --git a/arch/arm/mach-imx/ehci-imx35.c b/arch/arm/mach-imx/ehci-imx35.c
index 73574c3..779e16e 100644
--- a/arch/arm/mach-imx/ehci-imx35.c
+++ b/arch/arm/mach-imx/ehci-imx35.c
@@ -17,7 +17,7 @@
 #include <linux/io.h>
 
 #include <mach/hardware.h>
-#include <mach/mxc_ehci.h>
+#include <linux/platform_data/usb-ehci-mxc.h>
 
 #define USBCTRL_OTGBASE_OFFSET	0x600
 
diff --git a/arch/arm/mach-imx/ehci-imx5.c b/arch/arm/mach-imx/ehci-imx5.c
index a6a4afb..cf8d00e 100644
--- a/arch/arm/mach-imx/ehci-imx5.c
+++ b/arch/arm/mach-imx/ehci-imx5.c
@@ -17,7 +17,7 @@
 #include <linux/io.h>
 
 #include <mach/hardware.h>
-#include <mach/mxc_ehci.h>
+#include <linux/platform_data/usb-ehci-mxc.h>
 
 #define MXC_OTG_OFFSET			0
 #define MXC_H1_OFFSET			0x200
diff --git a/arch/arm/mach-imx/hotplug.c b/arch/arm/mach-imx/hotplug.c
index f8f7437..b07b778 100644
--- a/arch/arm/mach-imx/hotplug.c
+++ b/arch/arm/mach-imx/hotplug.c
@@ -15,11 +15,6 @@
 #include <asm/cp15.h>
 #include <mach/common.h>
 
-int platform_cpu_kill(unsigned int cpu)
-{
-	return 1;
-}
-
 static inline void cpu_enter_lowpower(void)
 {
 	unsigned int v;
@@ -47,7 +42,7 @@ static inline void cpu_enter_lowpower(void)
  *
  * Called with IRQs disabled
  */
-void platform_cpu_die(unsigned int cpu)
+void imx_cpu_die(unsigned int cpu)
 {
 	cpu_enter_lowpower();
 	imx_enable_cpu(cpu, false);
@@ -56,12 +51,3 @@ void platform_cpu_die(unsigned int cpu)
 	while (1)
 		;
 }
-
-int platform_cpu_disable(unsigned int cpu)
-{
-	/*
-	 * we don't allow CPU 0 to be shutdown (it is still too special
-	 * e.g. clock tick interrupts)
-	 */
-	return cpu == 0 ? -EPERM : 0;
-}
diff --git a/arch/arm/mach-imx/imx51-dt.c b/arch/arm/mach-imx/imx51-dt.c
index d4067fe..f233b4b 100644
--- a/arch/arm/mach-imx/imx51-dt.c
+++ b/arch/arm/mach-imx/imx51-dt.c
@@ -13,7 +13,6 @@
 #include <linux/irq.h>
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
-#include <linux/pinctrl/machine.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 #include <mach/common.h>
@@ -44,27 +43,8 @@ static const struct of_dev_auxdata imx51_auxdata_lookup[] __initconst = {
 	{ /* sentinel */ }
 };
 
-static const struct of_device_id imx51_iomuxc_of_match[] __initconst = {
-	{ .compatible = "fsl,imx51-iomuxc-babbage", .data = imx51_babbage_common_init, },
-	{ /* sentinel */ }
-};
-
 static void __init imx51_dt_init(void)
 {
-	struct device_node *node;
-	const struct of_device_id *of_id;
-	void (*func)(void);
-
-	pinctrl_provide_dummies();
-
-	node = of_find_matching_node(NULL, imx51_iomuxc_of_match);
-	if (node) {
-		of_id = of_match_node(imx51_iomuxc_of_match, node);
-		func = of_id->data;
-		func();
-		of_node_put(node);
-	}
-
 	of_platform_populate(NULL, of_default_bus_match_table,
 			     imx51_auxdata_lookup, NULL);
 }
@@ -79,7 +59,6 @@ static struct sys_timer imx51_timer = {
 };
 
 static const char *imx51_dt_board_compat[] __initdata = {
-	"fsl,imx51-babbage",
 	"fsl,imx51",
 	NULL
 };
diff --git a/arch/arm/mach-imx/imx53-dt.c b/arch/arm/mach-imx/imx53-dt.c
deleted file mode 100644
index 1b7a2fc..0000000
--- a/arch/arm/mach-imx/imx53-dt.c
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright 2011 Linaro Ltd.
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/clk.h>
-#include <linux/clkdev.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/irq.h>
-#include <linux/of_irq.h>
-#include <linux/of_platform.h>
-#include <linux/pinctrl/machine.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-#include <mach/common.h>
-#include <mach/mx53.h>
-
-/*
- * Lookup table for attaching a specific name and platform_data pointer to
- * devices as they get created by of_platform_populate().  Ideally this table
- * would not exist, but the current clock implementation depends on some devices
- * having a specific name.
- */
-static const struct of_dev_auxdata imx53_auxdata_lookup[] __initconst = {
-	OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART1_BASE_ADDR, "imx21-uart.0", NULL),
-	OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART2_BASE_ADDR, "imx21-uart.1", NULL),
-	OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART3_BASE_ADDR, "imx21-uart.2", NULL),
-	OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART4_BASE_ADDR, "imx21-uart.3", NULL),
-	OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART5_BASE_ADDR, "imx21-uart.4", NULL),
-	OF_DEV_AUXDATA("fsl,imx53-fec", MX53_FEC_BASE_ADDR, "imx25-fec.0", NULL),
-	OF_DEV_AUXDATA("fsl,imx53-esdhc", MX53_ESDHC1_BASE_ADDR, "sdhci-esdhc-imx53.0", NULL),
-	OF_DEV_AUXDATA("fsl,imx53-esdhc", MX53_ESDHC2_BASE_ADDR, "sdhci-esdhc-imx53.1", NULL),
-	OF_DEV_AUXDATA("fsl,imx53-esdhc", MX53_ESDHC3_BASE_ADDR, "sdhci-esdhc-imx53.2", NULL),
-	OF_DEV_AUXDATA("fsl,imx53-esdhc", MX53_ESDHC4_BASE_ADDR, "sdhci-esdhc-imx53.3", NULL),
-	OF_DEV_AUXDATA("fsl,imx53-ecspi", MX53_ECSPI1_BASE_ADDR, "imx51-ecspi.0", NULL),
-	OF_DEV_AUXDATA("fsl,imx53-ecspi", MX53_ECSPI2_BASE_ADDR, "imx51-ecspi.1", NULL),
-	OF_DEV_AUXDATA("fsl,imx53-cspi", MX53_CSPI_BASE_ADDR, "imx35-cspi.0", NULL),
-	OF_DEV_AUXDATA("fsl,imx53-i2c", MX53_I2C1_BASE_ADDR, "imx-i2c.0", NULL),
-	OF_DEV_AUXDATA("fsl,imx53-i2c", MX53_I2C2_BASE_ADDR, "imx-i2c.1", NULL),
-	OF_DEV_AUXDATA("fsl,imx53-i2c", MX53_I2C3_BASE_ADDR, "imx-i2c.2", NULL),
-	OF_DEV_AUXDATA("fsl,imx53-sdma", MX53_SDMA_BASE_ADDR, "imx35-sdma", NULL),
-	OF_DEV_AUXDATA("fsl,imx53-wdt", MX53_WDOG1_BASE_ADDR, "imx2-wdt.0", NULL),
-	{ /* sentinel */ }
-};
-
-static const struct of_device_id imx53_iomuxc_of_match[] __initconst = {
-	{ .compatible = "fsl,imx53-iomuxc-ard", .data = imx53_ard_common_init, },
-	{ .compatible = "fsl,imx53-iomuxc-evk", .data = imx53_evk_common_init, },
-	{ .compatible = "fsl,imx53-iomuxc-qsb", .data = imx53_qsb_common_init, },
-	{ .compatible = "fsl,imx53-iomuxc-smd", .data = imx53_smd_common_init, },
-	{ /* sentinel */ }
-};
-
-static void __init imx53_qsb_init(void)
-{
-	struct clk *clk;
-
-	clk = clk_get_sys(NULL, "ssi_ext1");
-	if (IS_ERR(clk)) {
-		pr_err("failed to get clk ssi_ext1\n");
-		return;
-	}
-
-	clk_register_clkdev(clk, NULL, "0-000a");
-}
-
-static void __init imx53_dt_init(void)
-{
-	struct device_node *node;
-	const struct of_device_id *of_id;
-	void (*func)(void);
-
-	pinctrl_provide_dummies();
-
-	node = of_find_matching_node(NULL, imx53_iomuxc_of_match);
-	if (node) {
-		of_id = of_match_node(imx53_iomuxc_of_match, node);
-		func = of_id->data;
-		func();
-		of_node_put(node);
-	}
-
-	if (of_machine_is_compatible("fsl,imx53-qsb"))
-		imx53_qsb_init();
-
-	of_platform_populate(NULL, of_default_bus_match_table,
-			     imx53_auxdata_lookup, NULL);
-}
-
-static void __init imx53_timer_init(void)
-{
-	mx53_clocks_init_dt();
-}
-
-static struct sys_timer imx53_timer = {
-	.init = imx53_timer_init,
-};
-
-static const char *imx53_dt_board_compat[] __initdata = {
-	"fsl,imx53-ard",
-	"fsl,imx53-evk",
-	"fsl,imx53-qsb",
-	"fsl,imx53-smd",
-	"fsl,imx53",
-	NULL
-};
-
-DT_MACHINE_START(IMX53_DT, "Freescale i.MX53 (Device Tree Support)")
-	.map_io		= mx53_map_io,
-	.init_early	= imx53_init_early,
-	.init_irq	= mx53_init_irq,
-	.handle_irq	= imx53_handle_irq,
-	.timer		= &imx53_timer,
-	.init_machine	= imx53_dt_init,
-	.init_late	= imx53_init_late,
-	.dt_compat	= imx53_dt_board_compat,
-	.restart	= mxc_restart,
-MACHINE_END
diff --git a/arch/arm/mach-imx/mach-imx27_visstrim_m10.c b/arch/arm/mach-imx/mach-imx27_visstrim_m10.c
index f264ddd..141756f 100644
--- a/arch/arm/mach-imx/mach-imx27_visstrim_m10.c
+++ b/arch/arm/mach-imx/mach-imx27_visstrim_m10.c
@@ -32,13 +32,14 @@
 #include <linux/delay.h>
 #include <linux/dma-mapping.h>
 #include <linux/leds.h>
-#include <linux/memblock.h>
+#include <linux/platform_data/asoc-mx27vis.h>
 #include <media/soc_camera.h>
 #include <sound/tlv320aic32x4.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 #include <asm/system_info.h>
+#include <asm/memblock.h>
 #include <mach/common.h>
 #include <mach/hardware.h>
 #include <mach/iomux-mx27.h>
@@ -58,6 +59,11 @@
 #define EXPBOARD_BIT1		(GPIO_PORTD + 27)
 #define EXPBOARD_BIT0		(GPIO_PORTD + 28)
 
+#define AMP_GAIN_0		(GPIO_PORTF + 9)
+#define AMP_GAIN_1		(GPIO_PORTF + 8)
+#define AMP_MUTE_SDL		(GPIO_PORTE + 5)
+#define AMP_MUTE_SDR		(GPIO_PORTF + 7)
+
 static const int visstrim_m10_pins[] __initconst = {
 	/* UART1 (console) */
 	PE12_PF_UART1_TXD,
@@ -139,6 +145,11 @@ static const int visstrim_m10_pins[] __initconst = {
 	EXPBOARD_BIT2 | GPIO_GPIO | GPIO_IN | GPIO_PUEN,
 	EXPBOARD_BIT1 | GPIO_GPIO | GPIO_IN | GPIO_PUEN,
 	EXPBOARD_BIT0 | GPIO_GPIO | GPIO_IN | GPIO_PUEN,
+	/* Audio AMP control */
+	AMP_GAIN_0 | GPIO_GPIO | GPIO_OUT,
+	AMP_GAIN_1 | GPIO_GPIO | GPIO_OUT,
+	AMP_MUTE_SDL | GPIO_GPIO | GPIO_OUT,
+	AMP_MUTE_SDR | GPIO_GPIO | GPIO_OUT,
 };
 
 static struct gpio visstrim_m10_version_gpios[] = {
@@ -166,6 +177,26 @@ static const struct gpio visstrim_m10_gpios[] __initconst = {
 		.flags = GPIOF_DIR_OUT | GPIOF_INIT_LOW,
 		.label = "usbotg_cs",
 	},
+	{
+		.gpio = AMP_GAIN_0,
+		.flags = GPIOF_DIR_OUT,
+		.label = "amp-gain-0",
+	},
+	{
+		.gpio = AMP_GAIN_1,
+		.flags = GPIOF_DIR_OUT,
+		.label = "amp-gain-1",
+	},
+	{
+		.gpio = AMP_MUTE_SDL,
+		.flags = GPIOF_DIR_OUT,
+		.label = "amp-mute-sdl",
+	},
+	{
+		.gpio = AMP_MUTE_SDR,
+		.flags = GPIOF_DIR_OUT,
+		.label = "amp-mute-sdr",
+	},
 };
 
 /* Camera */
@@ -233,10 +264,8 @@ static void __init visstrim_camera_init(void)
 static void __init visstrim_reserve(void)
 {
 	/* reserve 4 MiB for mx2-camera */
-	mx2_camera_base = memblock_alloc(MX2_CAMERA_BUF_SIZE,
+	mx2_camera_base = arm_memblock_steal(3 * MX2_CAMERA_BUF_SIZE,
 			MX2_CAMERA_BUF_SIZE);
-	memblock_free(mx2_camera_base, MX2_CAMERA_BUF_SIZE);
-	memblock_remove(mx2_camera_base, MX2_CAMERA_BUF_SIZE);
 }
 
 /* GPIOs used as events for applications */
@@ -405,6 +434,55 @@ static const struct imx_ssi_platform_data visstrim_m10_ssi_pdata __initconst = {
 	.flags			= IMX_SSI_DMA | IMX_SSI_SYN,
 };
 
+/* coda */
+
+static void __init visstrim_coda_init(void)
+{
+	struct platform_device *pdev;
+	int dma;
+
+	pdev = imx27_add_coda();
+	dma = dma_declare_coherent_memory(&pdev->dev,
+					  mx2_camera_base + MX2_CAMERA_BUF_SIZE,
+					  mx2_camera_base + MX2_CAMERA_BUF_SIZE,
+					  MX2_CAMERA_BUF_SIZE,
+					  DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE);
+	if (!(dma & DMA_MEMORY_MAP))
+		return;
+}
+
+/* DMA deinterlace */
+static struct platform_device visstrim_deinterlace = {
+	.name = "m2m-deinterlace",
+	.id = 0,
+};
+
+static void __init visstrim_deinterlace_init(void)
+{
+	int ret = -ENOMEM;
+	struct platform_device *pdev = &visstrim_deinterlace;
+	int dma;
+
+	ret = platform_device_register(pdev);
+
+	dma = dma_declare_coherent_memory(&pdev->dev,
+					  mx2_camera_base + 2 * MX2_CAMERA_BUF_SIZE,
+					  mx2_camera_base + 2 * MX2_CAMERA_BUF_SIZE,
+					  MX2_CAMERA_BUF_SIZE,
+					  DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE);
+	if (!(dma & DMA_MEMORY_MAP))
+		return;
+}
+
+
+/* Audio */
+static const struct snd_mx27vis_platform_data snd_mx27vis_pdata __initconst = {
+	.amp_gain0_gpio = AMP_GAIN_0,
+	.amp_gain1_gpio = AMP_GAIN_1,
+	.amp_mutel_gpio = AMP_MUTE_SDL,
+	.amp_muter_gpio = AMP_MUTE_SDR,
+};
+
 static void __init visstrim_m10_revision(void)
 {
 	int exp_version = 0;
@@ -463,11 +541,14 @@ static void __init visstrim_m10_board_init(void)
 	imx27_add_fec(NULL);
 	imx_add_gpio_keys(&visstrim_gpio_keys_platform_data);
 	platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
-	imx_add_platform_device("mx27vis", 0, NULL, 0, NULL, 0);
+	imx_add_platform_device("mx27vis", 0, NULL, 0, &snd_mx27vis_pdata,
+				sizeof(snd_mx27vis_pdata));
 	platform_device_register_resndata(NULL, "soc-camera-pdrv", 0, NULL, 0,
 				      &iclink_tvp5150, sizeof(iclink_tvp5150));
 	gpio_led_register_device(0, &visstrim_m10_led_data);
+	visstrim_deinterlace_init();
 	visstrim_camera_init();
+	visstrim_coda_init();
 }
 
 static void __init visstrim_m10_timer_init(void)
diff --git a/arch/arm/mach-imx/mach-imx53.c b/arch/arm/mach-imx/mach-imx53.c
new file mode 100644
index 0000000..29711e9
--- /dev/null
+++ b/arch/arm/mach-imx/mach-imx53.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <mach/common.h>
+#include <mach/mx53.h>
+
+/*
+ * Lookup table for attaching a specific name and platform_data pointer to
+ * devices as they get created by of_platform_populate().  Ideally this table
+ * would not exist, but the current clock implementation depends on some devices
+ * having a specific name.
+ */
+static const struct of_dev_auxdata imx53_auxdata_lookup[] __initconst = {
+	OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART1_BASE_ADDR, "imx21-uart.0", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART2_BASE_ADDR, "imx21-uart.1", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART3_BASE_ADDR, "imx21-uart.2", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART4_BASE_ADDR, "imx21-uart.3", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-uart", MX53_UART5_BASE_ADDR, "imx21-uart.4", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-fec", MX53_FEC_BASE_ADDR, "imx25-fec.0", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-esdhc", MX53_ESDHC1_BASE_ADDR, "sdhci-esdhc-imx53.0", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-esdhc", MX53_ESDHC2_BASE_ADDR, "sdhci-esdhc-imx53.1", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-esdhc", MX53_ESDHC3_BASE_ADDR, "sdhci-esdhc-imx53.2", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-esdhc", MX53_ESDHC4_BASE_ADDR, "sdhci-esdhc-imx53.3", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-ecspi", MX53_ECSPI1_BASE_ADDR, "imx51-ecspi.0", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-ecspi", MX53_ECSPI2_BASE_ADDR, "imx51-ecspi.1", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-cspi", MX53_CSPI_BASE_ADDR, "imx35-cspi.0", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-i2c", MX53_I2C1_BASE_ADDR, "imx-i2c.0", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-i2c", MX53_I2C2_BASE_ADDR, "imx-i2c.1", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-i2c", MX53_I2C3_BASE_ADDR, "imx-i2c.2", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-sdma", MX53_SDMA_BASE_ADDR, "imx35-sdma", NULL),
+	OF_DEV_AUXDATA("fsl,imx53-wdt", MX53_WDOG1_BASE_ADDR, "imx2-wdt.0", NULL),
+	{ /* sentinel */ }
+};
+
+static void __init imx53_qsb_init(void)
+{
+	struct clk *clk;
+
+	clk = clk_get_sys(NULL, "ssi_ext1");
+	if (IS_ERR(clk)) {
+		pr_err("failed to get clk ssi_ext1\n");
+		return;
+	}
+
+	clk_register_clkdev(clk, NULL, "0-000a");
+}
+
+static void __init imx53_dt_init(void)
+{
+	if (of_machine_is_compatible("fsl,imx53-qsb"))
+		imx53_qsb_init();
+
+	of_platform_populate(NULL, of_default_bus_match_table,
+			     imx53_auxdata_lookup, NULL);
+}
+
+static void __init imx53_timer_init(void)
+{
+	mx53_clocks_init_dt();
+}
+
+static struct sys_timer imx53_timer = {
+	.init = imx53_timer_init,
+};
+
+static const char *imx53_dt_board_compat[] __initdata = {
+	"fsl,imx53",
+	NULL
+};
+
+DT_MACHINE_START(IMX53_DT, "Freescale i.MX53 (Device Tree Support)")
+	.map_io		= mx53_map_io,
+	.init_early	= imx53_init_early,
+	.init_irq	= mx53_init_irq,
+	.handle_irq	= imx53_handle_irq,
+	.timer		= &imx53_timer,
+	.init_machine	= imx53_dt_init,
+	.init_late	= imx53_init_late,
+	.dt_compat	= imx53_dt_board_compat,
+	.restart	= mxc_restart,
+MACHINE_END
diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c
index 045b3f6..47c91f7 100644
--- a/arch/arm/mach-imx/mach-imx6q.c
+++ b/arch/arm/mach-imx/mach-imx6q.c
@@ -22,10 +22,10 @@
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
-#include <linux/pinctrl/machine.h>
 #include <linux/phy.h>
+#include <linux/regmap.h>
 #include <linux/micrel_phy.h>
-#include <linux/mfd/anatop.h>
+#include <linux/mfd/syscon.h>
 #include <asm/cpuidle.h>
 #include <asm/smp_twd.h>
 #include <asm/hardware/cache-l2x0.h>
@@ -100,7 +100,6 @@ static void __init imx6q_sabrelite_cko1_setup(void)
 	clk_set_parent(cko1_sel, ahb);
 	rate = clk_round_rate(cko1, 16000000);
 	clk_set_rate(cko1, rate);
-	clk_register_clkdev(cko1, NULL, "0-000a");
 put_clk:
 	if (!IS_ERR(cko1_sel))
 		clk_put(cko1_sel);
@@ -120,20 +119,7 @@ static void __init imx6q_sabrelite_init(void)
 
 static void __init imx6q_usb_init(void)
 {
-	struct device_node *np;
-	struct platform_device *pdev = NULL;
-	struct anatop *adata = NULL;
-
-	np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-anatop");
-	if (np)
-		pdev = of_find_device_by_node(np);
-	if (pdev)
-		adata = platform_get_drvdata(pdev);
-	if (!adata) {
-		if (np)
-			of_node_put(np);
-		return;
-	}
+	struct regmap *anatop;
 
 #define HW_ANADIG_USB1_CHRG_DETECT		0x000001b0
 #define HW_ANADIG_USB2_CHRG_DETECT		0x00000210
@@ -141,30 +127,25 @@ static void __init imx6q_usb_init(void)
 #define BM_ANADIG_USB_CHRG_DETECT_EN_B		0x00100000
 #define BM_ANADIG_USB_CHRG_DETECT_CHK_CHRG_B	0x00080000
 
-	/*
-	 * The external charger detector needs to be disabled,
-	 * or the signal at DP will be poor
-	 */
-	anatop_write_reg(adata, HW_ANADIG_USB1_CHRG_DETECT,
-			BM_ANADIG_USB_CHRG_DETECT_EN_B
-			| BM_ANADIG_USB_CHRG_DETECT_CHK_CHRG_B,
-			~0);
-	anatop_write_reg(adata, HW_ANADIG_USB2_CHRG_DETECT,
-			BM_ANADIG_USB_CHRG_DETECT_EN_B |
-			BM_ANADIG_USB_CHRG_DETECT_CHK_CHRG_B,
-			~0);
-
-	of_node_put(np);
+	anatop = syscon_regmap_lookup_by_compatible("fsl,imx6q-anatop");
+	if (!IS_ERR(anatop)) {
+		/*
+		 * The external charger detector needs to be disabled,
+		 * or the signal at DP will be poor
+		 */
+		regmap_write(anatop, HW_ANADIG_USB1_CHRG_DETECT,
+				BM_ANADIG_USB_CHRG_DETECT_EN_B
+				| BM_ANADIG_USB_CHRG_DETECT_CHK_CHRG_B);
+		regmap_write(anatop, HW_ANADIG_USB2_CHRG_DETECT,
+				BM_ANADIG_USB_CHRG_DETECT_EN_B |
+				BM_ANADIG_USB_CHRG_DETECT_CHK_CHRG_B);
+	} else {
+		pr_warn("failed to find fsl,imx6q-anatop regmap\n");
+	}
 }
 
 static void __init imx6q_init_machine(void)
 {
-	/*
-	 * This should be removed when all imx6q boards have pinctrl
-	 * states for devices defined in device tree.
-	 */
-	pinctrl_provide_dummies();
-
 	if (of_machine_is_compatible("fsl,imx6q-sabrelite"))
 		imx6q_sabrelite_init();
 
@@ -218,14 +199,12 @@ static struct sys_timer imx6q_timer = {
 };
 
 static const char *imx6q_dt_compat[] __initdata = {
-	"fsl,imx6q-arm2",
-	"fsl,imx6q-sabrelite",
-	"fsl,imx6q-sabresd",
 	"fsl,imx6q",
 	NULL,
 };
 
 DT_MACHINE_START(IMX6Q, "Freescale i.MX6 Quad (Device Tree)")
+	.smp		= smp_ops(imx_smp_ops),
 	.map_io		= imx6q_map_io,
 	.init_irq	= imx6q_init_irq,
 	.handle_irq	= imx6q_handle_irq,
diff --git a/arch/arm/mach-imx/mach-kzm_arm11_01.c b/arch/arm/mach-imx/mach-kzm_arm11_01.c
index 5d08533..0330078 100644
--- a/arch/arm/mach-imx/mach-kzm_arm11_01.c
+++ b/arch/arm/mach-imx/mach-kzm_arm11_01.c
@@ -36,7 +36,6 @@
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
 
-#include <mach/clock.h>
 #include <mach/common.h>
 #include <mach/hardware.h>
 #include <mach/iomux-mx3.h>
@@ -259,13 +258,13 @@ static void __init kzm_board_init(void)
  */
 static struct map_desc kzm_io_desc[] __initdata = {
 	{
-		.virtual	= MX31_CS4_BASE_ADDR_VIRT,
+		.virtual	= (unsigned long)MX31_CS4_BASE_ADDR_VIRT,
 		.pfn		= __phys_to_pfn(MX31_CS4_BASE_ADDR),
 		.length		= MX31_CS4_SIZE,
 		.type		= MT_DEVICE
 	},
 	{
-		.virtual	= MX31_CS5_BASE_ADDR_VIRT,
+		.virtual	= (unsigned long)MX31_CS5_BASE_ADDR_VIRT,
 		.pfn		= __phys_to_pfn(MX31_CS5_BASE_ADDR),
 		.length		= MX31_CS5_SIZE,
 		.type		= MT_DEVICE
diff --git a/arch/arm/mach-imx/mach-mx27_3ds.c b/arch/arm/mach-imx/mach-mx27_3ds.c
index 58c24c1..05996f3 100644
--- a/arch/arm/mach-imx/mach-mx27_3ds.c
+++ b/arch/arm/mach-imx/mach-mx27_3ds.c
@@ -158,6 +158,11 @@ static const int mx27pdk_pins[] __initconst = {
 	PB21_PF_CSI_HSYNC,
 	CSI_PWRDWN | GPIO_GPIO | GPIO_OUT,
 	CSI_RESET | GPIO_GPIO | GPIO_OUT,
+	/* SSI4 */
+	PC16_PF_SSI4_FS,
+	PC17_PF_SSI4_RXD,
+	PC18_PF_SSI4_TXD,
+	PC19_PF_SSI4_CLK,
 };
 
 static struct gpio mx27_3ds_camera_gpios[] = {
@@ -329,13 +334,24 @@ static struct mc13xxx_regulator_init_data mx27_3ds_regulators[] = {
 };
 
 /* MC13783 */
+static struct mc13xxx_codec_platform_data mx27_3ds_codec = {
+	.dac_ssi_port = MC13783_SSI1_PORT,
+	.adc_ssi_port = MC13783_SSI1_PORT,
+};
+
 static struct mc13xxx_platform_data mc13783_pdata = {
 	.regulators = {
 		.regulators = mx27_3ds_regulators,
 		.num_regulators = ARRAY_SIZE(mx27_3ds_regulators),
 
 	},
-	.flags  = MC13XXX_USE_TOUCHSCREEN | MC13XXX_USE_RTC,
+	.flags  = MC13XXX_USE_TOUCHSCREEN | MC13XXX_USE_RTC |
+						MC13XXX_USE_CODEC,
+	.codec = &mx27_3ds_codec,
+};
+
+static struct imx_ssi_platform_data mx27_3ds_ssi_pdata = {
+	.flags = IMX_SSI_DMA | IMX_SSI_NET,
 };
 
 /* SPI */
@@ -512,6 +528,9 @@ static void __init mx27pdk_init(void)
 	}
 
 	imx27_add_mx2_camera(&mx27_3ds_cam_pdata);
+	imx27_add_imx_ssi(0, &mx27_3ds_ssi_pdata);
+
+	imx_add_platform_device("imx_mc13783", 0, NULL, 0, NULL, 0);
 }
 
 static void __init mx27pdk_timer_init(void)
diff --git a/arch/arm/mach-imx/mach-mx31ads.c b/arch/arm/mach-imx/mach-mx31ads.c
index d37f480..e774b07 100644
--- a/arch/arm/mach-imx/mach-mx31ads.c
+++ b/arch/arm/mach-imx/mach-mx31ads.c
@@ -540,7 +540,7 @@ static void __init mxc_init_audio(void)
  */
 static struct map_desc mx31ads_io_desc[] __initdata = {
 	{
-		.virtual	= MX31_CS4_BASE_ADDR_VIRT,
+		.virtual	= (unsigned long)MX31_CS4_BASE_ADDR_VIRT,
 		.pfn		= __phys_to_pfn(MX31_CS4_BASE_ADDR),
 		.length		= CS4_CS8900_MMIO_START,
 		.type		= MT_DEVICE
diff --git a/arch/arm/mach-imx/mach-mx31lite.c b/arch/arm/mach-imx/mach-mx31lite.c
index c8785b3..ef57cff 100644
--- a/arch/arm/mach-imx/mach-mx31lite.c
+++ b/arch/arm/mach-imx/mach-mx31lite.c
@@ -207,7 +207,7 @@ static struct platform_device physmap_flash_device = {
  */
 static struct map_desc mx31lite_io_desc[] __initdata = {
 	{
-		.virtual = MX31_CS4_BASE_ADDR_VIRT,
+		.virtual = (unsigned long)MX31_CS4_BASE_ADDR_VIRT,
 		.pfn = __phys_to_pfn(MX31_CS4_BASE_ADDR),
 		.length = MX31_CS4_SIZE,
 		.type = MT_DEVICE
diff --git a/arch/arm/mach-imx/mach-mx31moboard.c b/arch/arm/mach-imx/mach-mx31moboard.c
index d46290b..459e754 100644
--- a/arch/arm/mach-imx/mach-mx31moboard.c
+++ b/arch/arm/mach-imx/mach-mx31moboard.c
@@ -47,7 +47,7 @@
 #include <mach/hardware.h>
 #include <mach/iomux-mx3.h>
 #include <mach/ulpi.h>
-#include <mach/ssi.h>
+#include <linux/platform_data/asoc-imx-ssi.h>
 
 #include "devices-imx31.h"
 
diff --git a/arch/arm/mach-imx/mach-mx51_efikamx.c b/arch/arm/mach-imx/mach-mx51_efikamx.c
deleted file mode 100644
index 8d09c01..0000000
--- a/arch/arm/mach-imx/mach-mx51_efikamx.c
+++ /dev/null
@@ -1,300 +0,0 @@
-/*
- * Copyright (C) 2010 Linaro Limited
- *
- * based on code from the following
- * Copyright 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright 2009-2010 Pegatron Corporation. All Rights Reserved.
- * Copyright 2009-2010 Genesi USA, Inc. All Rights Reserved.
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/i2c.h>
-#include <linux/gpio.h>
-#include <linux/leds.h>
-#include <linux/input.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/spi/flash.h>
-#include <linux/spi/spi.h>
-#include <linux/mfd/mc13892.h>
-#include <linux/regulator/machine.h>
-#include <linux/regulator/consumer.h>
-
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx51.h>
-
-#include <asm/setup.h>
-#include <asm/system_info.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-
-#include "devices-imx51.h"
-#include "efika.h"
-
-#define EFIKAMX_PCBID0		IMX_GPIO_NR(3, 16)
-#define EFIKAMX_PCBID1		IMX_GPIO_NR(3, 17)
-#define EFIKAMX_PCBID2		IMX_GPIO_NR(3, 11)
-
-#define EFIKAMX_BLUE_LED	IMX_GPIO_NR(3, 13)
-#define EFIKAMX_GREEN_LED	IMX_GPIO_NR(3, 14)
-#define EFIKAMX_RED_LED		IMX_GPIO_NR(3, 15)
-
-#define EFIKAMX_POWER_KEY	IMX_GPIO_NR(2, 31)
-
-/* board 1.1 doesn't have same reset gpio */
-#define EFIKAMX_RESET1_1	IMX_GPIO_NR(3, 2)
-#define EFIKAMX_RESET		IMX_GPIO_NR(1, 4)
-
-#define EFIKAMX_POWEROFF	IMX_GPIO_NR(4, 13)
-
-#define EFIKAMX_PMIC		IMX_GPIO_NR(1, 6)
-
-/* the pci ids pin have pull up. they're driven low according to board id */
-#define MX51_PAD_PCBID0	IOMUX_PAD(0x518, 0x130, 3, 0x0,   0, PAD_CTL_PUS_100K_UP)
-#define MX51_PAD_PCBID1	IOMUX_PAD(0x51C, 0x134, 3, 0x0,   0, PAD_CTL_PUS_100K_UP)
-#define MX51_PAD_PCBID2	IOMUX_PAD(0x504, 0x128, 3, 0x0,   0, PAD_CTL_PUS_100K_UP)
-#define MX51_PAD_PWRKEY	IOMUX_PAD(0x48c, 0x0f8, 1, 0x0,   0, PAD_CTL_PUS_100K_UP | PAD_CTL_PKE)
-
-static iomux_v3_cfg_t mx51efikamx_pads[] = {
-	/* board id */
-	MX51_PAD_PCBID0,
-	MX51_PAD_PCBID1,
-	MX51_PAD_PCBID2,
-
-	/* leds */
-	MX51_PAD_CSI1_D9__GPIO3_13,
-	MX51_PAD_CSI1_VSYNC__GPIO3_14,
-	MX51_PAD_CSI1_HSYNC__GPIO3_15,
-
-	/* power key */
-	MX51_PAD_PWRKEY,
-
-	/* reset */
-	MX51_PAD_DI1_PIN13__GPIO3_2,
-	MX51_PAD_GPIO1_4__GPIO1_4,
-
-	/* power off */
-	MX51_PAD_CSI2_VSYNC__GPIO4_13,
-};
-
-/*   PCBID2  PCBID1 PCBID0  STATE
-	1       1      1    ER1:rev1.1
-	1       1      0    ER2:rev1.2
-	1       0      1    ER3:rev1.3
-	1       0      0    ER4:rev1.4
-*/
-static void __init mx51_efikamx_board_id(void)
-{
-	int id;
-
-	/* things are taking time to settle */
-	msleep(150);
-
-	gpio_request(EFIKAMX_PCBID0, "pcbid0");
-	gpio_direction_input(EFIKAMX_PCBID0);
-	gpio_request(EFIKAMX_PCBID1, "pcbid1");
-	gpio_direction_input(EFIKAMX_PCBID1);
-	gpio_request(EFIKAMX_PCBID2, "pcbid2");
-	gpio_direction_input(EFIKAMX_PCBID2);
-
-	id = gpio_get_value(EFIKAMX_PCBID0) ? 1 : 0;
-	id |= (gpio_get_value(EFIKAMX_PCBID1) ? 1 : 0) << 1;
-	id |= (gpio_get_value(EFIKAMX_PCBID2) ? 1 : 0) << 2;
-
-	switch (id) {
-	case 7:
-		system_rev = 0x11;
-		break;
-	case 6:
-		system_rev = 0x12;
-		break;
-	case 5:
-		system_rev = 0x13;
-		break;
-	case 4:
-		system_rev = 0x14;
-		break;
-	default:
-		system_rev = 0x10;
-		break;
-	}
-
-	if ((system_rev == 0x10)
-		|| (system_rev == 0x12)
-		|| (system_rev == 0x14)) {
-		printk(KERN_WARNING
-			"EfikaMX: Unsupported board revision 1.%u!\n",
-			system_rev & 0xf);
-	}
-}
-
-static struct gpio_led mx51_efikamx_leds[] __initdata = {
-	{
-		.name = "efikamx:green",
-		.default_trigger = "default-on",
-		.gpio = EFIKAMX_GREEN_LED,
-	},
-	{
-		.name = "efikamx:red",
-		.default_trigger = "ide-disk",
-		.gpio = EFIKAMX_RED_LED,
-	},
-	{
-		.name = "efikamx:blue",
-		.default_trigger = "mmc0",
-		.gpio = EFIKAMX_BLUE_LED,
-	},
-};
-
-static const struct gpio_led_platform_data
-		mx51_efikamx_leds_data __initconst = {
-	.leds = mx51_efikamx_leds,
-	.num_leds = ARRAY_SIZE(mx51_efikamx_leds),
-};
-
-static struct esdhc_platform_data sd_pdata = {
-	.cd_type = ESDHC_CD_CONTROLLER,
-	.wp_type = ESDHC_WP_CONTROLLER,
-};
-
-static struct gpio_keys_button mx51_efikamx_powerkey[] = {
-	{
-		.code = KEY_POWER,
-		.gpio = EFIKAMX_POWER_KEY,
-		.type = EV_PWR,
-		.desc = "Power Button (CM)",
-		.wakeup = 1,
-		.debounce_interval = 10, /* ms */
-	},
-};
-
-static const struct gpio_keys_platform_data mx51_efikamx_powerkey_data __initconst = {
-	.buttons = mx51_efikamx_powerkey,
-	.nbuttons = ARRAY_SIZE(mx51_efikamx_powerkey),
-};
-
-static void mx51_efikamx_restart(char mode, const char *cmd)
-{
-	if (system_rev == 0x11)
-		gpio_direction_output(EFIKAMX_RESET1_1, 0);
-	else
-		gpio_direction_output(EFIKAMX_RESET, 0);
-}
-
-static struct regulator *pwgt1, *pwgt2, *coincell;
-
-static void mx51_efikamx_power_off(void)
-{
-	if (!IS_ERR(coincell))
-		regulator_disable(coincell);
-
-	if (!IS_ERR(pwgt1) && !IS_ERR(pwgt2)) {
-		regulator_disable(pwgt2);
-		regulator_disable(pwgt1);
-	}
-	gpio_direction_output(EFIKAMX_POWEROFF, 1);
-}
-
-static int __init mx51_efikamx_power_init(void)
-{
-	pwgt1 = regulator_get(NULL, "pwgt1");
-	pwgt2 = regulator_get(NULL, "pwgt2");
-	if (!IS_ERR(pwgt1) && !IS_ERR(pwgt2)) {
-		regulator_enable(pwgt1);
-		regulator_enable(pwgt2);
-	}
-	gpio_request(EFIKAMX_POWEROFF, "poweroff");
-	pm_power_off = mx51_efikamx_power_off;
-
-	/* enable coincell charger. maybe need a small power driver ? */
-	coincell = regulator_get(NULL, "coincell");
-	if (!IS_ERR(coincell)) {
-		regulator_set_voltage(coincell, 3000000, 3000000);
-		regulator_enable(coincell);
-	}
-
-	regulator_has_full_constraints();
-
-	return 0;
-}
-
-static void __init mx51_efikamx_init_late(void)
-{
-	imx51_init_late();
-	mx51_efikamx_power_init();
-}
-
-static void __init mx51_efikamx_init(void)
-{
-	imx51_soc_init();
-
-	mxc_iomux_v3_setup_multiple_pads(mx51efikamx_pads,
-					ARRAY_SIZE(mx51efikamx_pads));
-	efika_board_common_init();
-
-	mx51_efikamx_board_id();
-
-	/* on < 1.2 boards both SD controllers are used */
-	if (system_rev < 0x12) {
-		imx51_add_sdhci_esdhc_imx(0, NULL);
-		imx51_add_sdhci_esdhc_imx(1, &sd_pdata);
-		mx51_efikamx_leds[2].default_trigger = "mmc1";
-	} else
-		imx51_add_sdhci_esdhc_imx(0, &sd_pdata);
-
-	gpio_led_register_device(-1, &mx51_efikamx_leds_data);
-	imx_add_gpio_keys(&mx51_efikamx_powerkey_data);
-
-	if (system_rev == 0x11) {
-		gpio_request(EFIKAMX_RESET1_1, "reset");
-		gpio_direction_output(EFIKAMX_RESET1_1, 1);
-	} else {
-		gpio_request(EFIKAMX_RESET, "reset");
-		gpio_direction_output(EFIKAMX_RESET, 1);
-	}
-
-	/*
-	 * enable wifi by default only on mx
-	 * sb and mx have same wlan pin but the value to enable it are
-	 * different :/
-	 */
-	gpio_request(EFIKA_WLAN_EN, "wlan_en");
-	gpio_direction_output(EFIKA_WLAN_EN, 0);
-	msleep(10);
-
-	gpio_request(EFIKA_WLAN_RESET, "wlan_rst");
-	gpio_direction_output(EFIKA_WLAN_RESET, 0);
-	msleep(10);
-	gpio_set_value(EFIKA_WLAN_RESET, 1);
-}
-
-static void __init mx51_efikamx_timer_init(void)
-{
-	mx51_clocks_init(32768, 24000000, 22579200, 24576000);
-}
-
-static struct sys_timer mx51_efikamx_timer = {
-	.init = mx51_efikamx_timer_init,
-};
-
-MACHINE_START(MX51_EFIKAMX, "Genesi Efika MX (Smarttop)")
-	.atag_offset = 0x100,
-	.map_io = mx51_map_io,
-	.init_early = imx51_init_early,
-	.init_irq = mx51_init_irq,
-	.handle_irq = imx51_handle_irq,
-	.timer = &mx51_efikamx_timer,
-	.init_machine = mx51_efikamx_init,
-	.init_late = mx51_efikamx_init_late,
-	.restart = mx51_efikamx_restart,
-MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mx51_efikasb.c b/arch/arm/mach-imx/mach-mx51_efikasb.c
deleted file mode 100644
index fdbd181..0000000
--- a/arch/arm/mach-imx/mach-mx51_efikasb.c
+++ /dev/null
@@ -1,296 +0,0 @@
-/*
- * Copyright (C) Arnaud Patard <arnaud.patard@rtp-net.org>
- *
- * based on code from the following
- * Copyright 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright 2009-2010 Pegatron Corporation. All Rights Reserved.
- * Copyright 2009-2010 Genesi USA, Inc. All Rights Reserved.
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/i2c.h>
-#include <linux/gpio.h>
-#include <linux/leds.h>
-#include <linux/input.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/spi/flash.h>
-#include <linux/spi/spi.h>
-#include <linux/mfd/mc13892.h>
-#include <linux/regulator/machine.h>
-#include <linux/regulator/consumer.h>
-#include <linux/usb/otg.h>
-#include <linux/usb/ulpi.h>
-#include <mach/ulpi.h>
-
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx51.h>
-
-#include <asm/setup.h>
-#include <asm/system_info.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-
-#include "devices-imx51.h"
-#include "efika.h"
-
-#define EFIKASB_USBH2_STP	IMX_GPIO_NR(2, 20)
-#define EFIKASB_GREEN_LED	IMX_GPIO_NR(1, 3)
-#define EFIKASB_WHITE_LED	IMX_GPIO_NR(2, 25)
-#define EFIKASB_PCBID0		IMX_GPIO_NR(2, 28)
-#define EFIKASB_PCBID1		IMX_GPIO_NR(2, 29)
-#define EFIKASB_PWRKEY		IMX_GPIO_NR(2, 31)
-#define EFIKASB_LID		IMX_GPIO_NR(3, 14)
-#define EFIKASB_POWEROFF	IMX_GPIO_NR(4, 13)
-#define EFIKASB_RFKILL		IMX_GPIO_NR(3, 1)
-
-#define MX51_PAD_PWRKEY IOMUX_PAD(0x48c, 0x0f8, 1, 0x0,   0, PAD_CTL_PUS_100K_UP | PAD_CTL_PKE)
-#define MX51_PAD_SD1_CD	IOMUX_PAD(0x47c, 0x0e8, 1, __NA_, 0, MX51_ESDHC_PAD_CTRL)
-
-static iomux_v3_cfg_t mx51efikasb_pads[] = {
-	/* USB HOST2 */
-	MX51_PAD_EIM_D16__USBH2_DATA0,
-	MX51_PAD_EIM_D17__USBH2_DATA1,
-	MX51_PAD_EIM_D18__USBH2_DATA2,
-	MX51_PAD_EIM_D19__USBH2_DATA3,
-	MX51_PAD_EIM_D20__USBH2_DATA4,
-	MX51_PAD_EIM_D21__USBH2_DATA5,
-	MX51_PAD_EIM_D22__USBH2_DATA6,
-	MX51_PAD_EIM_D23__USBH2_DATA7,
-	MX51_PAD_EIM_A24__USBH2_CLK,
-	MX51_PAD_EIM_A25__USBH2_DIR,
-	MX51_PAD_EIM_A26__USBH2_STP,
-	MX51_PAD_EIM_A27__USBH2_NXT,
-
-	/* leds */
-	MX51_PAD_EIM_CS0__GPIO2_25,
-	MX51_PAD_GPIO1_3__GPIO1_3,
-
-	/* pcb id */
-	MX51_PAD_EIM_CS3__GPIO2_28,
-	MX51_PAD_EIM_CS4__GPIO2_29,
-
-	/* lid */
-	MX51_PAD_CSI1_VSYNC__GPIO3_14,
-
-	/* power key*/
-	MX51_PAD_PWRKEY,
-
-	/* wifi/bt button */
-	MX51_PAD_DI1_PIN12__GPIO3_1,
-
-	/* power off */
-	MX51_PAD_CSI2_VSYNC__GPIO4_13,
-
-	/* wdog reset */
-	MX51_PAD_GPIO1_4__WDOG1_WDOG_B,
-
-	/* BT */
-	MX51_PAD_EIM_A17__GPIO2_11,
-
-	MX51_PAD_SD1_CD,
-};
-
-static int initialize_usbh2_port(struct platform_device *pdev)
-{
-	iomux_v3_cfg_t usbh2stp = MX51_PAD_EIM_A26__USBH2_STP;
-	iomux_v3_cfg_t usbh2gpio = MX51_PAD_EIM_A26__GPIO2_20;
-
-	mxc_iomux_v3_setup_pad(usbh2gpio);
-	gpio_request(EFIKASB_USBH2_STP, "usbh2_stp");
-	gpio_direction_output(EFIKASB_USBH2_STP, 0);
-	msleep(1);
-	gpio_set_value(EFIKASB_USBH2_STP, 1);
-	msleep(1);
-
-	gpio_free(EFIKASB_USBH2_STP);
-	mxc_iomux_v3_setup_pad(usbh2stp);
-
-	mdelay(10);
-
-	return mx51_initialize_usb_hw(pdev->id, MXC_EHCI_ITC_NO_THRESHOLD);
-}
-
-static struct mxc_usbh_platform_data usbh2_config __initdata = {
-	.init   = initialize_usbh2_port,
-	.portsc = MXC_EHCI_MODE_ULPI,
-};
-
-static void __init mx51_efikasb_usb(void)
-{
-	usbh2_config.otg = imx_otg_ulpi_create(ULPI_OTG_DRVVBUS |
-			ULPI_OTG_DRVVBUS_EXT | ULPI_OTG_EXTVBUSIND);
-	if (usbh2_config.otg)
-		imx51_add_mxc_ehci_hs(2, &usbh2_config);
-}
-
-static const struct gpio_led mx51_efikasb_leds[] __initconst = {
-	{
-		.name = "efikasb:green",
-		.default_trigger = "default-on",
-		.gpio = EFIKASB_GREEN_LED,
-		.active_low = 1,
-	},
-	{
-		.name = "efikasb:white",
-		.default_trigger = "caps",
-		.gpio = EFIKASB_WHITE_LED,
-	},
-};
-
-static const struct gpio_led_platform_data
-		mx51_efikasb_leds_data __initconst = {
-	.leds = mx51_efikasb_leds,
-	.num_leds = ARRAY_SIZE(mx51_efikasb_leds),
-};
-
-static struct gpio_keys_button mx51_efikasb_keys[] = {
-	{
-		.code = KEY_POWER,
-		.gpio = EFIKASB_PWRKEY,
-		.type = EV_KEY,
-		.desc = "Power Button",
-		.wakeup = 1,
-		.active_low = 1,
-	},
-	{
-		.code = SW_LID,
-		.gpio = EFIKASB_LID,
-		.type = EV_SW,
-		.desc = "Lid Switch",
-		.active_low = 1,
-	},
-	{
-		.code = KEY_RFKILL,
-		.gpio = EFIKASB_RFKILL,
-		.type = EV_KEY,
-		.desc = "rfkill",
-		.active_low = 1,
-	},
-};
-
-static const struct gpio_keys_platform_data mx51_efikasb_keys_data __initconst = {
-	.buttons = mx51_efikasb_keys,
-	.nbuttons = ARRAY_SIZE(mx51_efikasb_keys),
-};
-
-static struct esdhc_platform_data sd0_pdata = {
-#define EFIKASB_SD1_CD	IMX_GPIO_NR(2, 27)
-	.cd_gpio = EFIKASB_SD1_CD,
-	.cd_type = ESDHC_CD_GPIO,
-	.wp_type = ESDHC_WP_CONTROLLER,
-};
-
-static struct esdhc_platform_data sd1_pdata = {
-	.cd_type = ESDHC_CD_CONTROLLER,
-	.wp_type = ESDHC_WP_CONTROLLER,
-};
-
-static struct regulator *pwgt1, *pwgt2;
-
-static void mx51_efikasb_power_off(void)
-{
-	gpio_set_value(EFIKA_USB_PHY_RESET, 0);
-
-	if (!IS_ERR(pwgt1) && !IS_ERR(pwgt2)) {
-		regulator_disable(pwgt2);
-		regulator_disable(pwgt1);
-	}
-	gpio_direction_output(EFIKASB_POWEROFF, 1);
-}
-
-static int __init mx51_efikasb_power_init(void)
-{
-	pwgt1 = regulator_get(NULL, "pwgt1");
-	pwgt2 = regulator_get(NULL, "pwgt2");
-	if (!IS_ERR(pwgt1) && !IS_ERR(pwgt2)) {
-		regulator_enable(pwgt1);
-		regulator_enable(pwgt2);
-	}
-	gpio_request(EFIKASB_POWEROFF, "poweroff");
-	pm_power_off = mx51_efikasb_power_off;
-
-	regulator_has_full_constraints();
-
-	return 0;
-}
-
-static void __init mx51_efikasb_init_late(void)
-{
-	imx51_init_late();
-	mx51_efikasb_power_init();
-}
-
-/* 01     R1.3 board
-   10     R2.0 board */
-static void __init mx51_efikasb_board_id(void)
-{
-	int id;
-
-	gpio_request(EFIKASB_PCBID0, "pcb id0");
-	gpio_direction_input(EFIKASB_PCBID0);
-	gpio_request(EFIKASB_PCBID1, "pcb id1");
-	gpio_direction_input(EFIKASB_PCBID1);
-
-	id = gpio_get_value(EFIKASB_PCBID0) ? 1 : 0;
-	id |= (gpio_get_value(EFIKASB_PCBID1) ? 1 : 0) << 1;
-
-	switch (id) {
-	default:
-		break;
-	case 1:
-		system_rev = 0x13;
-		break;
-	case 2:
-		system_rev = 0x20;
-		break;
-	}
-}
-
-static void __init efikasb_board_init(void)
-{
-	imx51_soc_init();
-
-	mxc_iomux_v3_setup_multiple_pads(mx51efikasb_pads,
-					ARRAY_SIZE(mx51efikasb_pads));
-	efika_board_common_init();
-
-	mx51_efikasb_board_id();
-	mx51_efikasb_usb();
-	imx51_add_sdhci_esdhc_imx(0, &sd0_pdata);
-	imx51_add_sdhci_esdhc_imx(1, &sd1_pdata);
-
-	gpio_led_register_device(-1, &mx51_efikasb_leds_data);
-	imx_add_gpio_keys(&mx51_efikasb_keys_data);
-}
-
-static void __init mx51_efikasb_timer_init(void)
-{
-	mx51_clocks_init(32768, 24000000, 22579200, 24576000);
-}
-
-static struct sys_timer mx51_efikasb_timer = {
-	.init	= mx51_efikasb_timer_init,
-};
-
-MACHINE_START(MX51_EFIKASB, "Genesi Efika MX (Smartbook)")
-	.atag_offset = 0x100,
-	.map_io = mx51_map_io,
-	.init_early = imx51_init_early,
-	.init_irq = mx51_init_irq,
-	.handle_irq = imx51_handle_irq,
-	.init_machine =  efikasb_board_init,
-	.init_late = mx51_efikasb_init_late,
-	.timer = &mx51_efikasb_timer,
-	.restart	= mxc_restart,
-MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mx53_ard.c b/arch/arm/mach-imx/mach-mx53_ard.c
deleted file mode 100644
index 6c28e65..0000000
--- a/arch/arm/mach-imx/mach-mx53_ard.c
+++ /dev/null
@@ -1,272 +0,0 @@
-/*
- * Copyright (C) 2011 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 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/init.h>
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/gpio.h>
-#include <linux/smsc911x.h>
-#include <linux/regulator/machine.h>
-#include <linux/regulator/fixed.h>
-
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx53.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-
-#include "devices-imx53.h"
-
-#define ARD_ETHERNET_INT_B	IMX_GPIO_NR(2, 31)
-#define ARD_SD1_CD		IMX_GPIO_NR(1, 1)
-#define ARD_SD1_WP		IMX_GPIO_NR(1, 9)
-#define ARD_I2CPORTEXP_B	IMX_GPIO_NR(2, 3)
-#define ARD_VOLUMEDOWN		IMX_GPIO_NR(4, 0)
-#define ARD_HOME			IMX_GPIO_NR(5, 10)
-#define ARD_BACK			IMX_GPIO_NR(5, 11)
-#define ARD_PROG			IMX_GPIO_NR(5, 12)
-#define ARD_VOLUMEUP		IMX_GPIO_NR(5, 13)
-
-static iomux_v3_cfg_t mx53_ard_pads[] = {
-	/* UART1 */
-	MX53_PAD_PATA_DIOW__UART1_TXD_MUX,
-	MX53_PAD_PATA_DMACK__UART1_RXD_MUX,
-	/* WEIM for CS1 */
-	MX53_PAD_EIM_EB3__GPIO2_31, /* ETHERNET_INT_B */
-	MX53_PAD_EIM_D16__EMI_WEIM_D_16,
-	MX53_PAD_EIM_D17__EMI_WEIM_D_17,
-	MX53_PAD_EIM_D18__EMI_WEIM_D_18,
-	MX53_PAD_EIM_D19__EMI_WEIM_D_19,
-	MX53_PAD_EIM_D20__EMI_WEIM_D_20,
-	MX53_PAD_EIM_D21__EMI_WEIM_D_21,
-	MX53_PAD_EIM_D22__EMI_WEIM_D_22,
-	MX53_PAD_EIM_D23__EMI_WEIM_D_23,
-	MX53_PAD_EIM_D24__EMI_WEIM_D_24,
-	MX53_PAD_EIM_D25__EMI_WEIM_D_25,
-	MX53_PAD_EIM_D26__EMI_WEIM_D_26,
-	MX53_PAD_EIM_D27__EMI_WEIM_D_27,
-	MX53_PAD_EIM_D28__EMI_WEIM_D_28,
-	MX53_PAD_EIM_D29__EMI_WEIM_D_29,
-	MX53_PAD_EIM_D30__EMI_WEIM_D_30,
-	MX53_PAD_EIM_D31__EMI_WEIM_D_31,
-	MX53_PAD_EIM_DA0__EMI_NAND_WEIM_DA_0,
-	MX53_PAD_EIM_DA1__EMI_NAND_WEIM_DA_1,
-	MX53_PAD_EIM_DA2__EMI_NAND_WEIM_DA_2,
-	MX53_PAD_EIM_DA3__EMI_NAND_WEIM_DA_3,
-	MX53_PAD_EIM_DA4__EMI_NAND_WEIM_DA_4,
-	MX53_PAD_EIM_DA5__EMI_NAND_WEIM_DA_5,
-	MX53_PAD_EIM_DA6__EMI_NAND_WEIM_DA_6,
-	MX53_PAD_EIM_OE__EMI_WEIM_OE,
-	MX53_PAD_EIM_RW__EMI_WEIM_RW,
-	MX53_PAD_EIM_CS1__EMI_WEIM_CS_1,
-	/* SDHC1 */
-	MX53_PAD_SD1_CMD__ESDHC1_CMD,
-	MX53_PAD_SD1_CLK__ESDHC1_CLK,
-	MX53_PAD_SD1_DATA0__ESDHC1_DAT0,
-	MX53_PAD_SD1_DATA1__ESDHC1_DAT1,
-	MX53_PAD_SD1_DATA2__ESDHC1_DAT2,
-	MX53_PAD_SD1_DATA3__ESDHC1_DAT3,
-	MX53_PAD_PATA_DATA8__ESDHC1_DAT4,
-	MX53_PAD_PATA_DATA9__ESDHC1_DAT5,
-	MX53_PAD_PATA_DATA10__ESDHC1_DAT6,
-	MX53_PAD_PATA_DATA11__ESDHC1_DAT7,
-	MX53_PAD_GPIO_1__GPIO1_1,
-	MX53_PAD_GPIO_9__GPIO1_9,
-	/* I2C2 */
-	MX53_PAD_EIM_EB2__I2C2_SCL,
-	MX53_PAD_KEY_ROW3__I2C2_SDA,
-	/* I2C3 */
-	MX53_PAD_GPIO_3__I2C3_SCL,
-	MX53_PAD_GPIO_16__I2C3_SDA,
-	/* GPIO */
-	MX53_PAD_DISP0_DAT16__GPIO5_10,	/* home */
-	MX53_PAD_DISP0_DAT17__GPIO5_11,	/* back */
-	MX53_PAD_DISP0_DAT18__GPIO5_12,	/* prog */
-	MX53_PAD_DISP0_DAT19__GPIO5_13,	/* vol up */
-	MX53_PAD_GPIO_10__GPIO4_0,		/* vol down */
-};
-
-#define GPIO_BUTTON(gpio_num, ev_code, act_low, descr, wake)	\
-{							\
-	.gpio		= gpio_num,				\
-	.type		= EV_KEY,				\
-	.code		= ev_code,				\
-	.active_low	= act_low,				\
-	.desc		= "btn " descr,			\
-	.wakeup		= wake,					\
-}
-
-static struct gpio_keys_button ard_buttons[] = {
-	GPIO_BUTTON(ARD_HOME, KEY_HOME, 1, "home", 0),
-	GPIO_BUTTON(ARD_BACK, KEY_BACK, 1, "back", 0),
-	GPIO_BUTTON(ARD_PROG, KEY_PROGRAM, 1, "program", 0),
-	GPIO_BUTTON(ARD_VOLUMEUP, KEY_VOLUMEUP, 1, "volume-up", 0),
-	GPIO_BUTTON(ARD_VOLUMEDOWN, KEY_VOLUMEDOWN, 1, "volume-down", 0),
-};
-
-static const struct gpio_keys_platform_data ard_button_data __initconst = {
-	.buttons        = ard_buttons,
-	.nbuttons       = ARRAY_SIZE(ard_buttons),
-};
-
-static struct resource ard_smsc911x_resources[] = {
-	{
-		.start = MX53_CS1_64MB_BASE_ADDR,
-		.end = MX53_CS1_64MB_BASE_ADDR + SZ_32M - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		/* irq number is run-time assigned */
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-struct smsc911x_platform_config ard_smsc911x_config = {
-	.irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
-	.irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL,
-	.flags = SMSC911X_USE_32BIT,
-};
-
-static struct platform_device ard_smsc_lan9220_device = {
-	.name = "smsc911x",
-	.id = -1,
-	.num_resources = ARRAY_SIZE(ard_smsc911x_resources),
-	.resource = ard_smsc911x_resources,
-	.dev = {
-		.platform_data = &ard_smsc911x_config,
-	},
-};
-
-static const struct esdhc_platform_data mx53_ard_sd1_data __initconst = {
-	.cd_gpio = ARD_SD1_CD,
-	.wp_gpio = ARD_SD1_WP,
-};
-
-static struct imxi2c_platform_data mx53_ard_i2c2_data = {
-	.bitrate = 50000,
-};
-
-static struct imxi2c_platform_data mx53_ard_i2c3_data = {
-	.bitrate = 400000,
-};
-
-static void __init mx53_ard_io_init(void)
-{
-	gpio_request(ARD_ETHERNET_INT_B, "eth-int-b");
-	gpio_direction_input(ARD_ETHERNET_INT_B);
-
-	gpio_request(ARD_I2CPORTEXP_B, "i2cptexp-rst");
-	gpio_direction_output(ARD_I2CPORTEXP_B, 1);
-}
-
-/* Config CS1 settings for ethernet controller */
-static int weim_cs_config(void)
-{
-	u32 reg;
-	void __iomem *weim_base, *iomuxc_base;
-
-	weim_base = ioremap(MX53_WEIM_BASE_ADDR, SZ_4K);
-	if (!weim_base)
-		return -ENOMEM;
-
-	iomuxc_base = ioremap(MX53_IOMUXC_BASE_ADDR, SZ_4K);
-	if (!iomuxc_base) {
-		iounmap(weim_base);
-		return -ENOMEM;
-	}
-
-	/* CS1 timings for LAN9220 */
-	writel(0x20001, (weim_base + 0x18));
-	writel(0x0, (weim_base + 0x1C));
-	writel(0x16000202, (weim_base + 0x20));
-	writel(0x00000002, (weim_base + 0x24));
-	writel(0x16002082, (weim_base + 0x28));
-	writel(0x00000000, (weim_base + 0x2C));
-	writel(0x00000000, (weim_base + 0x90));
-
-	/* specify 64 MB on CS1 and CS0 on GPR1 */
-	reg = readl(iomuxc_base + 0x4);
-	reg &= ~0x3F;
-	reg |= 0x1B;
-	writel(reg, (iomuxc_base + 0x4));
-
-	iounmap(iomuxc_base);
-	iounmap(weim_base);
-
-	return 0;
-}
-
-static struct regulator_consumer_supply dummy_supplies[] = {
-	REGULATOR_SUPPLY("vdd33a", "smsc911x"),
-	REGULATOR_SUPPLY("vddvario", "smsc911x"),
-};
-
-void __init imx53_ard_common_init(void)
-{
-	mxc_iomux_v3_setup_multiple_pads(mx53_ard_pads,
-					 ARRAY_SIZE(mx53_ard_pads));
-	weim_cs_config();
-}
-
-static struct platform_device *devices[] __initdata = {
-	&ard_smsc_lan9220_device,
-};
-
-static void __init mx53_ard_board_init(void)
-{
-	imx53_soc_init();
-	imx53_add_imx_uart(0, NULL);
-
-	imx53_ard_common_init();
-	mx53_ard_io_init();
-	regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
-	ard_smsc911x_resources[1].start = gpio_to_irq(ARD_ETHERNET_INT_B);
-	ard_smsc911x_resources[1].end = gpio_to_irq(ARD_ETHERNET_INT_B);
-	platform_add_devices(devices, ARRAY_SIZE(devices));
-
-	imx53_add_sdhci_esdhc_imx(0, &mx53_ard_sd1_data);
-	imx53_add_imx2_wdt(0);
-	imx53_add_imx_i2c(1, &mx53_ard_i2c2_data);
-	imx53_add_imx_i2c(2, &mx53_ard_i2c3_data);
-	imx_add_gpio_keys(&ard_button_data);
-	imx53_add_ahci_imx();
-}
-
-static void __init mx53_ard_timer_init(void)
-{
-	mx53_clocks_init(32768, 24000000, 22579200, 0);
-}
-
-static struct sys_timer mx53_ard_timer = {
-	.init	= mx53_ard_timer_init,
-};
-
-MACHINE_START(MX53_ARD, "Freescale MX53 ARD Board")
-	.map_io = mx53_map_io,
-	.init_early = imx53_init_early,
-	.init_irq = mx53_init_irq,
-	.handle_irq = imx53_handle_irq,
-	.timer = &mx53_ard_timer,
-	.init_machine = mx53_ard_board_init,
-	.init_late	= imx53_init_late,
-	.restart	= mxc_restart,
-MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mx53_evk.c b/arch/arm/mach-imx/mach-mx53_evk.c
deleted file mode 100644
index 09fe219..0000000
--- a/arch/arm/mach-imx/mach-mx53_evk.c
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright (C) 2010 Yong Shen. <Yong.Shen@linaro.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.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <linux/init.h>
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/gpio.h>
-#include <linux/spi/flash.h>
-#include <linux/spi/spi.h>
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-#include <mach/iomux-mx53.h>
-
-#define MX53_EVK_FEC_PHY_RST	IMX_GPIO_NR(7, 6)
-#define EVK_ECSPI1_CS0		IMX_GPIO_NR(2, 30)
-#define EVK_ECSPI1_CS1		IMX_GPIO_NR(3, 19)
-#define MX53EVK_LED		IMX_GPIO_NR(7, 7)
-
-#include "devices-imx53.h"
-
-static iomux_v3_cfg_t mx53_evk_pads[] = {
-	MX53_PAD_CSI0_DAT10__UART1_TXD_MUX,
-	MX53_PAD_CSI0_DAT11__UART1_RXD_MUX,
-
-	MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX,
-	MX53_PAD_PATA_DMARQ__UART2_TXD_MUX,
-	MX53_PAD_PATA_DIOR__UART2_RTS,
-	MX53_PAD_PATA_INTRQ__UART2_CTS,
-
-	MX53_PAD_PATA_CS_0__UART3_TXD_MUX,
-	MX53_PAD_PATA_CS_1__UART3_RXD_MUX,
-
-	MX53_PAD_EIM_D16__ECSPI1_SCLK,
-	MX53_PAD_EIM_D17__ECSPI1_MISO,
-	MX53_PAD_EIM_D18__ECSPI1_MOSI,
-
-	/* ecspi chip select lines */
-	MX53_PAD_EIM_EB2__GPIO2_30,
-	MX53_PAD_EIM_D19__GPIO3_19,
-	/* LED */
-	MX53_PAD_PATA_DA_1__GPIO7_7,
-};
-
-static const struct imxuart_platform_data mx53_evk_uart_pdata __initconst = {
-	.flags = IMXUART_HAVE_RTSCTS,
-};
-
-static const struct gpio_led mx53evk_leds[] __initconst = {
-	{
-		.name			= "green",
-		.default_trigger	= "heartbeat",
-		.gpio			= MX53EVK_LED,
-	},
-};
-
-static const struct gpio_led_platform_data mx53evk_leds_data __initconst = {
-	.leds		= mx53evk_leds,
-	.num_leds	= ARRAY_SIZE(mx53evk_leds),
-};
-
-static inline void mx53_evk_init_uart(void)
-{
-	imx53_add_imx_uart(0, NULL);
-	imx53_add_imx_uart(1, &mx53_evk_uart_pdata);
-	imx53_add_imx_uart(2, NULL);
-}
-
-static const struct imxi2c_platform_data mx53_evk_i2c_data __initconst = {
-	.bitrate = 100000,
-};
-
-static inline void mx53_evk_fec_reset(void)
-{
-	int ret;
-
-	/* reset FEC PHY */
-	ret = gpio_request_one(MX53_EVK_FEC_PHY_RST, GPIOF_OUT_INIT_LOW,
-							"fec-phy-reset");
-	if (ret) {
-		printk(KERN_ERR"failed to get GPIO_FEC_PHY_RESET: %d\n", ret);
-		return;
-	}
-	msleep(1);
-	gpio_set_value(MX53_EVK_FEC_PHY_RST, 1);
-}
-
-static const struct fec_platform_data mx53_evk_fec_pdata __initconst = {
-	.phy = PHY_INTERFACE_MODE_RMII,
-};
-
-static struct spi_board_info mx53_evk_spi_board_info[] __initdata = {
-	{
-		.modalias = "mtd_dataflash",
-		.max_speed_hz = 25000000,
-		.bus_num = 0,
-		.chip_select = 1,
-		.mode = SPI_MODE_0,
-		.platform_data = NULL,
-	},
-};
-
-static int mx53_evk_spi_cs[] = {
-	EVK_ECSPI1_CS0,
-	EVK_ECSPI1_CS1,
-};
-
-static const struct spi_imx_master mx53_evk_spi_data __initconst = {
-	.chipselect     = mx53_evk_spi_cs,
-	.num_chipselect = ARRAY_SIZE(mx53_evk_spi_cs),
-};
-
-void __init imx53_evk_common_init(void)
-{
-	mxc_iomux_v3_setup_multiple_pads(mx53_evk_pads,
-					 ARRAY_SIZE(mx53_evk_pads));
-}
-
-static void __init mx53_evk_board_init(void)
-{
-	imx53_soc_init();
-	imx53_evk_common_init();
-
-	mx53_evk_init_uart();
-	mx53_evk_fec_reset();
-	imx53_add_fec(&mx53_evk_fec_pdata);
-
-	imx53_add_imx_i2c(0, &mx53_evk_i2c_data);
-	imx53_add_imx_i2c(1, &mx53_evk_i2c_data);
-
-	imx53_add_sdhci_esdhc_imx(0, NULL);
-	imx53_add_sdhci_esdhc_imx(1, NULL);
-
-	spi_register_board_info(mx53_evk_spi_board_info,
-		ARRAY_SIZE(mx53_evk_spi_board_info));
-	imx53_add_ecspi(0, &mx53_evk_spi_data);
-	imx53_add_imx2_wdt(0);
-	gpio_led_register_device(-1, &mx53evk_leds_data);
-}
-
-static void __init mx53_evk_timer_init(void)
-{
-	mx53_clocks_init(32768, 24000000, 22579200, 0);
-}
-
-static struct sys_timer mx53_evk_timer = {
-	.init	= mx53_evk_timer_init,
-};
-
-MACHINE_START(MX53_EVK, "Freescale MX53 EVK Board")
-	.map_io = mx53_map_io,
-	.init_early = imx53_init_early,
-	.init_irq = mx53_init_irq,
-	.handle_irq = imx53_handle_irq,
-	.timer = &mx53_evk_timer,
-	.init_machine = mx53_evk_board_init,
-	.init_late	= imx53_init_late,
-	.restart	= mxc_restart,
-MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mx53_loco.c b/arch/arm/mach-imx/mach-mx53_loco.c
deleted file mode 100644
index 8abe23c..0000000
--- a/arch/arm/mach-imx/mach-mx53_loco.c
+++ /dev/null
@@ -1,321 +0,0 @@
-/*
- * Copyright (C) 2011 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 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/init.h>
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/gpio.h>
-#include <linux/i2c.h>
-
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx53.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-
-#include "devices-imx53.h"
-
-#define MX53_LOCO_POWER			IMX_GPIO_NR(1, 8)
-#define MX53_LOCO_UI1			IMX_GPIO_NR(2, 14)
-#define MX53_LOCO_UI2			IMX_GPIO_NR(2, 15)
-#define LOCO_FEC_PHY_RST		IMX_GPIO_NR(7, 6)
-#define LOCO_LED			IMX_GPIO_NR(7, 7)
-#define LOCO_SD3_CD			IMX_GPIO_NR(3, 11)
-#define LOCO_SD3_WP			IMX_GPIO_NR(3, 12)
-#define LOCO_SD1_CD			IMX_GPIO_NR(3, 13)
-#define LOCO_ACCEL_EN			IMX_GPIO_NR(6, 14)
-
-static iomux_v3_cfg_t mx53_loco_pads[] = {
-	/* FEC */
-	MX53_PAD_FEC_MDC__FEC_MDC,
-	MX53_PAD_FEC_MDIO__FEC_MDIO,
-	MX53_PAD_FEC_REF_CLK__FEC_TX_CLK,
-	MX53_PAD_FEC_RX_ER__FEC_RX_ER,
-	MX53_PAD_FEC_CRS_DV__FEC_RX_DV,
-	MX53_PAD_FEC_RXD1__FEC_RDATA_1,
-	MX53_PAD_FEC_RXD0__FEC_RDATA_0,
-	MX53_PAD_FEC_TX_EN__FEC_TX_EN,
-	MX53_PAD_FEC_TXD1__FEC_TDATA_1,
-	MX53_PAD_FEC_TXD0__FEC_TDATA_0,
-	/* FEC_nRST */
-	MX53_PAD_PATA_DA_0__GPIO7_6,
-	/* FEC_nINT */
-	MX53_PAD_PATA_DATA4__GPIO2_4,
-	/* AUDMUX5 */
-	MX53_PAD_KEY_COL0__AUDMUX_AUD5_TXC,
-	MX53_PAD_KEY_ROW0__AUDMUX_AUD5_TXD,
-	MX53_PAD_KEY_COL1__AUDMUX_AUD5_TXFS,
-	MX53_PAD_KEY_ROW1__AUDMUX_AUD5_RXD,
-	/* I2C1 */
-	MX53_PAD_CSI0_DAT8__I2C1_SDA,
-	MX53_PAD_CSI0_DAT9__I2C1_SCL,
-	MX53_PAD_NANDF_CS1__GPIO6_14,	/* Accelerometer Enable */
-	/* I2C2 */
-	MX53_PAD_KEY_COL3__I2C2_SCL,
-	MX53_PAD_KEY_ROW3__I2C2_SDA,
-	/* SD1 */
-	MX53_PAD_SD1_CMD__ESDHC1_CMD,
-	MX53_PAD_SD1_CLK__ESDHC1_CLK,
-	MX53_PAD_SD1_DATA0__ESDHC1_DAT0,
-	MX53_PAD_SD1_DATA1__ESDHC1_DAT1,
-	MX53_PAD_SD1_DATA2__ESDHC1_DAT2,
-	MX53_PAD_SD1_DATA3__ESDHC1_DAT3,
-	/* SD1_CD */
-	MX53_PAD_EIM_DA13__GPIO3_13,
-	/* SD3 */
-	MX53_PAD_PATA_DATA8__ESDHC3_DAT0,
-	MX53_PAD_PATA_DATA9__ESDHC3_DAT1,
-	MX53_PAD_PATA_DATA10__ESDHC3_DAT2,
-	MX53_PAD_PATA_DATA11__ESDHC3_DAT3,
-	MX53_PAD_PATA_DATA0__ESDHC3_DAT4,
-	MX53_PAD_PATA_DATA1__ESDHC3_DAT5,
-	MX53_PAD_PATA_DATA2__ESDHC3_DAT6,
-	MX53_PAD_PATA_DATA3__ESDHC3_DAT7,
-	MX53_PAD_PATA_IORDY__ESDHC3_CLK,
-	MX53_PAD_PATA_RESET_B__ESDHC3_CMD,
-	/* SD3_CD */
-	MX53_PAD_EIM_DA11__GPIO3_11,
-	/* SD3_WP */
-	MX53_PAD_EIM_DA12__GPIO3_12,
-	/* VGA */
-	MX53_PAD_EIM_OE__IPU_DI1_PIN7,
-	MX53_PAD_EIM_RW__IPU_DI1_PIN8,
-	/* DISPLB */
-	MX53_PAD_EIM_D20__IPU_SER_DISP0_CS,
-	MX53_PAD_EIM_D21__IPU_DISPB0_SER_CLK,
-	MX53_PAD_EIM_D22__IPU_DISPB0_SER_DIN,
-	MX53_PAD_EIM_D23__IPU_DI0_D0_CS,
-	/* DISP0_POWER_EN */
-	MX53_PAD_EIM_D24__GPIO3_24,
-	/* DISP0 DET INT */
-	MX53_PAD_EIM_D31__GPIO3_31,
-	/* LVDS */
-	MX53_PAD_LVDS0_TX3_P__LDB_LVDS0_TX3,
-	MX53_PAD_LVDS0_CLK_P__LDB_LVDS0_CLK,
-	MX53_PAD_LVDS0_TX2_P__LDB_LVDS0_TX2,
-	MX53_PAD_LVDS0_TX1_P__LDB_LVDS0_TX1,
-	MX53_PAD_LVDS0_TX0_P__LDB_LVDS0_TX0,
-	MX53_PAD_LVDS1_TX3_P__LDB_LVDS1_TX3,
-	MX53_PAD_LVDS1_TX2_P__LDB_LVDS1_TX2,
-	MX53_PAD_LVDS1_CLK_P__LDB_LVDS1_CLK,
-	MX53_PAD_LVDS1_TX1_P__LDB_LVDS1_TX1,
-	MX53_PAD_LVDS1_TX0_P__LDB_LVDS1_TX0,
-	/* I2C1 */
-	MX53_PAD_CSI0_DAT8__I2C1_SDA,
-	MX53_PAD_CSI0_DAT9__I2C1_SCL,
-	/* UART1 */
-	MX53_PAD_CSI0_DAT10__UART1_TXD_MUX,
-	MX53_PAD_CSI0_DAT11__UART1_RXD_MUX,
-	/* CSI0 */
-	MX53_PAD_CSI0_DAT12__IPU_CSI0_D_12,
-	MX53_PAD_CSI0_DAT13__IPU_CSI0_D_13,
-	MX53_PAD_CSI0_DAT14__IPU_CSI0_D_14,
-	MX53_PAD_CSI0_DAT15__IPU_CSI0_D_15,
-	MX53_PAD_CSI0_DAT16__IPU_CSI0_D_16,
-	MX53_PAD_CSI0_DAT17__IPU_CSI0_D_17,
-	MX53_PAD_CSI0_DAT18__IPU_CSI0_D_18,
-	MX53_PAD_CSI0_DAT19__IPU_CSI0_D_19,
-	MX53_PAD_CSI0_VSYNC__IPU_CSI0_VSYNC,
-	MX53_PAD_CSI0_MCLK__IPU_CSI0_HSYNC,
-	MX53_PAD_CSI0_PIXCLK__IPU_CSI0_PIXCLK,
-	/* DISPLAY */
-	MX53_PAD_DI0_DISP_CLK__IPU_DI0_DISP_CLK,
-	MX53_PAD_DI0_PIN15__IPU_DI0_PIN15,
-	MX53_PAD_DI0_PIN2__IPU_DI0_PIN2,
-	MX53_PAD_DI0_PIN3__IPU_DI0_PIN3,
-	MX53_PAD_DISP0_DAT0__IPU_DISP0_DAT_0,
-	MX53_PAD_DISP0_DAT1__IPU_DISP0_DAT_1,
-	MX53_PAD_DISP0_DAT2__IPU_DISP0_DAT_2,
-	MX53_PAD_DISP0_DAT3__IPU_DISP0_DAT_3,
-	MX53_PAD_DISP0_DAT4__IPU_DISP0_DAT_4,
-	MX53_PAD_DISP0_DAT5__IPU_DISP0_DAT_5,
-	MX53_PAD_DISP0_DAT6__IPU_DISP0_DAT_6,
-	MX53_PAD_DISP0_DAT7__IPU_DISP0_DAT_7,
-	MX53_PAD_DISP0_DAT8__IPU_DISP0_DAT_8,
-	MX53_PAD_DISP0_DAT9__IPU_DISP0_DAT_9,
-	MX53_PAD_DISP0_DAT10__IPU_DISP0_DAT_10,
-	MX53_PAD_DISP0_DAT11__IPU_DISP0_DAT_11,
-	MX53_PAD_DISP0_DAT12__IPU_DISP0_DAT_12,
-	MX53_PAD_DISP0_DAT13__IPU_DISP0_DAT_13,
-	MX53_PAD_DISP0_DAT14__IPU_DISP0_DAT_14,
-	MX53_PAD_DISP0_DAT15__IPU_DISP0_DAT_15,
-	MX53_PAD_DISP0_DAT16__IPU_DISP0_DAT_16,
-	MX53_PAD_DISP0_DAT17__IPU_DISP0_DAT_17,
-	MX53_PAD_DISP0_DAT18__IPU_DISP0_DAT_18,
-	MX53_PAD_DISP0_DAT19__IPU_DISP0_DAT_19,
-	MX53_PAD_DISP0_DAT20__IPU_DISP0_DAT_20,
-	MX53_PAD_DISP0_DAT21__IPU_DISP0_DAT_21,
-	MX53_PAD_DISP0_DAT22__IPU_DISP0_DAT_22,
-	MX53_PAD_DISP0_DAT23__IPU_DISP0_DAT_23,
-	/* Audio CLK*/
-	MX53_PAD_GPIO_0__CCM_SSI_EXT1_CLK,
-	/* PWM */
-	MX53_PAD_GPIO_1__PWM2_PWMO,
-	/* SPDIF */
-	MX53_PAD_GPIO_7__SPDIF_PLOCK,
-	MX53_PAD_GPIO_17__SPDIF_OUT1,
-	/* GPIO */
-	MX53_PAD_PATA_DA_1__GPIO7_7,		/* LED */
-	MX53_PAD_PATA_DA_2__GPIO7_8,
-	MX53_PAD_PATA_DATA5__GPIO2_5,
-	MX53_PAD_PATA_DATA6__GPIO2_6,
-	MX53_PAD_PATA_DATA14__GPIO2_14,
-	MX53_PAD_PATA_DATA15__GPIO2_15,
-	MX53_PAD_PATA_INTRQ__GPIO7_2,
-	MX53_PAD_EIM_WAIT__GPIO5_0,
-	MX53_PAD_NANDF_WP_B__GPIO6_9,
-	MX53_PAD_NANDF_RB0__GPIO6_10,
-	MX53_PAD_NANDF_CS1__GPIO6_14,
-	MX53_PAD_NANDF_CS2__GPIO6_15,
-	MX53_PAD_NANDF_CS3__GPIO6_16,
-	MX53_PAD_GPIO_5__GPIO1_5,
-	MX53_PAD_GPIO_16__GPIO7_11,
-	MX53_PAD_GPIO_8__GPIO1_8,
-};
-
-#define GPIO_BUTTON(gpio_num, ev_code, act_low, descr, wake)	\
-{								\
-	.gpio		= gpio_num,				\
-	.type		= EV_KEY,				\
-	.code		= ev_code,				\
-	.active_low	= act_low,				\
-	.desc		= "btn " descr,				\
-	.wakeup		= wake,					\
-}
-
-static struct gpio_keys_button loco_buttons[] = {
-	GPIO_BUTTON(MX53_LOCO_POWER, KEY_POWER, 1, "power", 0),
-	GPIO_BUTTON(MX53_LOCO_UI1, KEY_VOLUMEUP, 1, "volume-up", 0),
-	GPIO_BUTTON(MX53_LOCO_UI2, KEY_VOLUMEDOWN, 1, "volume-down", 0),
-};
-
-static const struct gpio_keys_platform_data loco_button_data __initconst = {
-	.buttons        = loco_buttons,
-	.nbuttons       = ARRAY_SIZE(loco_buttons),
-};
-
-static const struct esdhc_platform_data mx53_loco_sd1_data __initconst = {
-	.cd_gpio = LOCO_SD1_CD,
-	.cd_type = ESDHC_CD_GPIO,
-	.wp_type = ESDHC_WP_NONE,
-};
-
-static const struct esdhc_platform_data mx53_loco_sd3_data __initconst = {
-	.cd_gpio = LOCO_SD3_CD,
-	.wp_gpio = LOCO_SD3_WP,
-	.cd_type = ESDHC_CD_GPIO,
-	.wp_type = ESDHC_WP_GPIO,
-};
-
-static inline void mx53_loco_fec_reset(void)
-{
-	int ret;
-
-	/* reset FEC PHY */
-	ret = gpio_request(LOCO_FEC_PHY_RST, "fec-phy-reset");
-	if (ret) {
-		printk(KERN_ERR"failed to get GPIO_FEC_PHY_RESET: %d\n", ret);
-		return;
-	}
-	gpio_direction_output(LOCO_FEC_PHY_RST, 0);
-	msleep(1);
-	gpio_set_value(LOCO_FEC_PHY_RST, 1);
-}
-
-static const struct fec_platform_data mx53_loco_fec_data __initconst = {
-	.phy = PHY_INTERFACE_MODE_RMII,
-};
-
-static const struct imxi2c_platform_data mx53_loco_i2c_data __initconst = {
-	.bitrate = 100000,
-};
-
-static const struct gpio_led mx53loco_leds[] __initconst = {
-	{
-		.name			= "green",
-		.default_trigger	= "heartbeat",
-		.gpio			= LOCO_LED,
-	},
-};
-
-static const struct gpio_led_platform_data mx53loco_leds_data __initconst = {
-	.leds		= mx53loco_leds,
-	.num_leds	= ARRAY_SIZE(mx53loco_leds),
-};
-
-void __init imx53_qsb_common_init(void)
-{
-	mxc_iomux_v3_setup_multiple_pads(mx53_loco_pads,
-					 ARRAY_SIZE(mx53_loco_pads));
-}
-
-static struct i2c_board_info mx53loco_i2c_devices[] = {
-	{
-		I2C_BOARD_INFO("mma8450", 0x1C),
-	},
-};
-
-static void __init mx53_loco_board_init(void)
-{
-	int ret;
-	imx53_soc_init();
-	imx53_qsb_common_init();
-
-	imx53_add_imx_uart(0, NULL);
-	mx53_loco_fec_reset();
-	imx53_add_fec(&mx53_loco_fec_data);
-	imx53_add_imx2_wdt(0);
-
-	ret = gpio_request_one(LOCO_ACCEL_EN, GPIOF_OUT_INIT_HIGH, "accel_en");
-	if (ret)
-		pr_err("Cannot request ACCEL_EN pin: %d\n", ret);
-
-	i2c_register_board_info(0, mx53loco_i2c_devices,
-				ARRAY_SIZE(mx53loco_i2c_devices));
-	imx53_add_imx_i2c(0, &mx53_loco_i2c_data);
-	imx53_add_imx_i2c(1, &mx53_loco_i2c_data);
-	imx53_add_sdhci_esdhc_imx(0, &mx53_loco_sd1_data);
-	imx53_add_sdhci_esdhc_imx(2, &mx53_loco_sd3_data);
-	imx_add_gpio_keys(&loco_button_data);
-	gpio_led_register_device(-1, &mx53loco_leds_data);
-	imx53_add_ahci_imx();
-}
-
-static void __init mx53_loco_timer_init(void)
-{
-	mx53_clocks_init(32768, 24000000, 0, 0);
-}
-
-static struct sys_timer mx53_loco_timer = {
-	.init	= mx53_loco_timer_init,
-};
-
-MACHINE_START(MX53_LOCO, "Freescale MX53 LOCO Board")
-	.map_io = mx53_map_io,
-	.init_early = imx53_init_early,
-	.init_irq = mx53_init_irq,
-	.handle_irq = imx53_handle_irq,
-	.timer = &mx53_loco_timer,
-	.init_machine = mx53_loco_board_init,
-	.init_late	= imx53_init_late,
-	.restart	= mxc_restart,
-MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mx53_smd.c b/arch/arm/mach-imx/mach-mx53_smd.c
deleted file mode 100644
index b15d6a6..0000000
--- a/arch/arm/mach-imx/mach-mx53_smd.c
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * Copyright (C) 2011 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 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/init.h>
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/gpio.h>
-
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx53.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-
-#include "devices-imx53.h"
-
-#define SMD_FEC_PHY_RST		IMX_GPIO_NR(7, 6)
-#define MX53_SMD_SATA_PWR_EN    IMX_GPIO_NR(3, 3)
-
-static iomux_v3_cfg_t mx53_smd_pads[] = {
-	MX53_PAD_CSI0_DAT10__UART1_TXD_MUX,
-	MX53_PAD_CSI0_DAT11__UART1_RXD_MUX,
-
-	MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX,
-	MX53_PAD_PATA_DMARQ__UART2_TXD_MUX,
-
-	MX53_PAD_PATA_CS_0__UART3_TXD_MUX,
-	MX53_PAD_PATA_CS_1__UART3_RXD_MUX,
-	MX53_PAD_PATA_DA_1__UART3_CTS,
-	MX53_PAD_PATA_DA_2__UART3_RTS,
-	/* I2C1 */
-	MX53_PAD_CSI0_DAT8__I2C1_SDA,
-	MX53_PAD_CSI0_DAT9__I2C1_SCL,
-	/* SD1 */
-	MX53_PAD_SD1_CMD__ESDHC1_CMD,
-	MX53_PAD_SD1_CLK__ESDHC1_CLK,
-	MX53_PAD_SD1_DATA0__ESDHC1_DAT0,
-	MX53_PAD_SD1_DATA1__ESDHC1_DAT1,
-	MX53_PAD_SD1_DATA2__ESDHC1_DAT2,
-	MX53_PAD_SD1_DATA3__ESDHC1_DAT3,
-	/* SD2 */
-	MX53_PAD_SD2_CMD__ESDHC2_CMD,
-	MX53_PAD_SD2_CLK__ESDHC2_CLK,
-	MX53_PAD_SD2_DATA0__ESDHC2_DAT0,
-	MX53_PAD_SD2_DATA1__ESDHC2_DAT1,
-	MX53_PAD_SD2_DATA2__ESDHC2_DAT2,
-	MX53_PAD_SD2_DATA3__ESDHC2_DAT3,
-	/* SD3 */
-	MX53_PAD_PATA_DATA8__ESDHC3_DAT0,
-	MX53_PAD_PATA_DATA9__ESDHC3_DAT1,
-	MX53_PAD_PATA_DATA10__ESDHC3_DAT2,
-	MX53_PAD_PATA_DATA11__ESDHC3_DAT3,
-	MX53_PAD_PATA_DATA0__ESDHC3_DAT4,
-	MX53_PAD_PATA_DATA1__ESDHC3_DAT5,
-	MX53_PAD_PATA_DATA2__ESDHC3_DAT6,
-	MX53_PAD_PATA_DATA3__ESDHC3_DAT7,
-	MX53_PAD_PATA_IORDY__ESDHC3_CLK,
-	MX53_PAD_PATA_RESET_B__ESDHC3_CMD,
-};
-
-static const struct imxuart_platform_data mx53_smd_uart_data __initconst = {
-	.flags = IMXUART_HAVE_RTSCTS,
-};
-
-static inline void mx53_smd_init_uart(void)
-{
-	imx53_add_imx_uart(0, NULL);
-	imx53_add_imx_uart(1, NULL);
-	imx53_add_imx_uart(2, &mx53_smd_uart_data);
-}
-
-static inline void mx53_smd_fec_reset(void)
-{
-	int ret;
-
-	/* reset FEC PHY */
-	ret = gpio_request(SMD_FEC_PHY_RST, "fec-phy-reset");
-	if (ret) {
-		printk(KERN_ERR"failed to get GPIO_FEC_PHY_RESET: %d\n", ret);
-		return;
-	}
-	gpio_direction_output(SMD_FEC_PHY_RST, 0);
-	msleep(1);
-	gpio_set_value(SMD_FEC_PHY_RST, 1);
-}
-
-static const struct fec_platform_data mx53_smd_fec_data __initconst = {
-	.phy = PHY_INTERFACE_MODE_RMII,
-};
-
-static const struct imxi2c_platform_data mx53_smd_i2c_data __initconst = {
-	.bitrate = 100000,
-};
-
-static inline void mx53_smd_ahci_pwr_on(void)
-{
-	int ret;
-
-	/* Enable SATA PWR */
-	ret = gpio_request_one(MX53_SMD_SATA_PWR_EN,
-			GPIOF_DIR_OUT | GPIOF_INIT_HIGH, "ahci-sata-pwr");
-	if (ret) {
-		pr_err("failed to enable SATA_PWR_EN: %d\n", ret);
-		return;
-	}
-}
-
-void __init imx53_smd_common_init(void)
-{
-	mxc_iomux_v3_setup_multiple_pads(mx53_smd_pads,
-					 ARRAY_SIZE(mx53_smd_pads));
-}
-
-static void __init mx53_smd_board_init(void)
-{
-	imx53_soc_init();
-	imx53_smd_common_init();
-
-	mx53_smd_init_uart();
-	mx53_smd_fec_reset();
-	imx53_add_fec(&mx53_smd_fec_data);
-	imx53_add_imx2_wdt(0);
-	imx53_add_imx_i2c(0, &mx53_smd_i2c_data);
-	imx53_add_sdhci_esdhc_imx(0, NULL);
-	imx53_add_sdhci_esdhc_imx(1, NULL);
-	imx53_add_sdhci_esdhc_imx(2, NULL);
-	mx53_smd_ahci_pwr_on();
-	imx53_add_ahci_imx();
-}
-
-static void __init mx53_smd_timer_init(void)
-{
-	mx53_clocks_init(32768, 24000000, 22579200, 0);
-}
-
-static struct sys_timer mx53_smd_timer = {
-	.init	= mx53_smd_timer_init,
-};
-
-MACHINE_START(MX53_SMD, "Freescale MX53 SMD Board")
-	.map_io = mx53_map_io,
-	.init_early = imx53_init_early,
-	.init_irq = mx53_init_irq,
-	.handle_irq = imx53_handle_irq,
-	.timer = &mx53_smd_timer,
-	.init_machine = mx53_smd_board_init,
-	.init_late	= imx53_init_late,
-	.restart	= mxc_restart,
-MACHINE_END
diff --git a/arch/arm/mach-imx/mm-imx5.c b/arch/arm/mach-imx/mm-imx5.c
index 52d8f53..acb0aad 100644
--- a/arch/arm/mach-imx/mm-imx5.c
+++ b/arch/arm/mach-imx/mm-imx5.c
@@ -128,25 +128,6 @@ static struct sdma_platform_data imx51_sdma_pdata __initdata = {
 	.script_addrs = &imx51_sdma_script,
 };
 
-static struct sdma_script_start_addrs imx53_sdma_script __initdata = {
-	.ap_2_ap_addr = 642,
-	.app_2_mcu_addr = 683,
-	.mcu_2_app_addr = 747,
-	.uart_2_mcu_addr = 817,
-	.shp_2_mcu_addr = 891,
-	.mcu_2_shp_addr = 960,
-	.uartsh_2_mcu_addr = 1032,
-	.spdif_2_mcu_addr = 1100,
-	.mcu_2_spdif_addr = 1134,
-	.firi_2_mcu_addr = 1193,
-	.mcu_2_firi_addr = 1290,
-};
-
-static struct sdma_platform_data imx53_sdma_pdata __initdata = {
-	.fw_name = "sdma-imx53.bin",
-	.script_addrs = &imx53_sdma_script,
-};
-
 static const struct resource imx50_audmux_res[] __initconst = {
 	DEFINE_RES_MEM(MX50_AUDMUX_BASE_ADDR, SZ_16K),
 };
@@ -155,10 +136,6 @@ static const struct resource imx51_audmux_res[] __initconst = {
 	DEFINE_RES_MEM(MX51_AUDMUX_BASE_ADDR, SZ_16K),
 };
 
-static const struct resource imx53_audmux_res[] __initconst = {
-	DEFINE_RES_MEM(MX53_AUDMUX_BASE_ADDR, SZ_16K),
-};
-
 void __init imx50_soc_init(void)
 {
 	/* i.mx50 has the i.mx35 type gpio */
@@ -196,30 +173,6 @@ void __init imx51_soc_init(void)
 					ARRAY_SIZE(imx51_audmux_res));
 }
 
-void __init imx53_soc_init(void)
-{
-	/* i.mx53 has the i.mx35 type gpio */
-	mxc_register_gpio("imx35-gpio", 0, MX53_GPIO1_BASE_ADDR, SZ_16K, MX53_INT_GPIO1_LOW, MX53_INT_GPIO1_HIGH);
-	mxc_register_gpio("imx35-gpio", 1, MX53_GPIO2_BASE_ADDR, SZ_16K, MX53_INT_GPIO2_LOW, MX53_INT_GPIO2_HIGH);
-	mxc_register_gpio("imx35-gpio", 2, MX53_GPIO3_BASE_ADDR, SZ_16K, MX53_INT_GPIO3_LOW, MX53_INT_GPIO3_HIGH);
-	mxc_register_gpio("imx35-gpio", 3, MX53_GPIO4_BASE_ADDR, SZ_16K, MX53_INT_GPIO4_LOW, MX53_INT_GPIO4_HIGH);
-	mxc_register_gpio("imx35-gpio", 4, MX53_GPIO5_BASE_ADDR, SZ_16K, MX53_INT_GPIO5_LOW, MX53_INT_GPIO5_HIGH);
-	mxc_register_gpio("imx35-gpio", 5, MX53_GPIO6_BASE_ADDR, SZ_16K, MX53_INT_GPIO6_LOW, MX53_INT_GPIO6_HIGH);
-	mxc_register_gpio("imx35-gpio", 6, MX53_GPIO7_BASE_ADDR, SZ_16K, MX53_INT_GPIO7_LOW, MX53_INT_GPIO7_HIGH);
-
-	pinctrl_provide_dummies();
-	/* i.mx53 has the i.mx35 type sdma */
-	imx_add_imx_sdma("imx35-sdma", MX53_SDMA_BASE_ADDR, MX53_INT_SDMA, &imx53_sdma_pdata);
-
-	/* Setup AIPS registers */
-	imx_set_aips(MX53_IO_ADDRESS(MX53_AIPS1_BASE_ADDR));
-	imx_set_aips(MX53_IO_ADDRESS(MX53_AIPS2_BASE_ADDR));
-
-	/* i.mx53 has the i.mx31 type audmux */
-	platform_device_register_simple("imx31-audmux", 0, imx53_audmux_res,
-					ARRAY_SIZE(imx53_audmux_res));
-}
-
 void __init imx51_init_late(void)
 {
 	mx51_neon_fixup();
diff --git a/arch/arm/mach-imx/mx1-camera-fiq-ksym.c b/arch/arm/mach-imx/mx1-camera-fiq-ksym.c
index b09ee12..fb38436 100644
--- a/arch/arm/mach-imx/mx1-camera-fiq-ksym.c
+++ b/arch/arm/mach-imx/mx1-camera-fiq-ksym.c
@@ -11,7 +11,7 @@
 #include <linux/platform_device.h>
 #include <linux/module.h>
 
-#include <mach/mx1_camera.h>
+#include <linux/platform_data/camera-mx1.h>
 
 /* IMX camera FIQ handler */
 EXPORT_SYMBOL(mx1_camera_sof_fiq_start);
diff --git a/arch/arm/mach-imx/mx51_efika.c b/arch/arm/mach-imx/mx51_efika.c
deleted file mode 100644
index ee870c4..0000000
--- a/arch/arm/mach-imx/mx51_efika.c
+++ /dev/null
@@ -1,633 +0,0 @@
-/*
- * based on code from the following
- * Copyright 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright 2009-2010 Pegatron Corporation. All Rights Reserved.
- * Copyright 2009-2010 Genesi USA, Inc. All Rights Reserved.
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/i2c.h>
-#include <linux/gpio.h>
-#include <linux/leds.h>
-#include <linux/input.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/spi/flash.h>
-#include <linux/spi/spi.h>
-#include <linux/mfd/mc13892.h>
-#include <linux/regulator/machine.h>
-#include <linux/regulator/consumer.h>
-
-#include <mach/common.h>
-#include <mach/hardware.h>
-#include <mach/iomux-mx51.h>
-
-#include <linux/usb/otg.h>
-#include <linux/usb/ulpi.h>
-#include <mach/ulpi.h>
-
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-
-#include "devices-imx51.h"
-#include "efika.h"
-#include "cpu_op-mx51.h"
-
-#define MX51_USB_CTRL_1_OFFSET          0x10
-#define MX51_USB_CTRL_UH1_EXT_CLK_EN    (1 << 25)
-#define	MX51_USB_PLL_DIV_19_2_MHZ	0x01
-
-#define EFIKAMX_USB_HUB_RESET	IMX_GPIO_NR(1, 5)
-#define EFIKAMX_USBH1_STP	IMX_GPIO_NR(1, 27)
-
-#define EFIKAMX_SPI_CS0		IMX_GPIO_NR(4, 24)
-#define EFIKAMX_SPI_CS1		IMX_GPIO_NR(4, 25)
-
-#define EFIKAMX_PMIC		IMX_GPIO_NR(1, 6)
-
-static iomux_v3_cfg_t mx51efika_pads[] = {
-	/* UART1 */
-	MX51_PAD_UART1_RXD__UART1_RXD,
-	MX51_PAD_UART1_TXD__UART1_TXD,
-	MX51_PAD_UART1_RTS__UART1_RTS,
-	MX51_PAD_UART1_CTS__UART1_CTS,
-
-	/* SD 1 */
-	MX51_PAD_SD1_CMD__SD1_CMD,
-	MX51_PAD_SD1_CLK__SD1_CLK,
-	MX51_PAD_SD1_DATA0__SD1_DATA0,
-	MX51_PAD_SD1_DATA1__SD1_DATA1,
-	MX51_PAD_SD1_DATA2__SD1_DATA2,
-	MX51_PAD_SD1_DATA3__SD1_DATA3,
-
-	/* SD 2 */
-	MX51_PAD_SD2_CMD__SD2_CMD,
-	MX51_PAD_SD2_CLK__SD2_CLK,
-	MX51_PAD_SD2_DATA0__SD2_DATA0,
-	MX51_PAD_SD2_DATA1__SD2_DATA1,
-	MX51_PAD_SD2_DATA2__SD2_DATA2,
-	MX51_PAD_SD2_DATA3__SD2_DATA3,
-
-	/* SD/MMC WP/CD */
-	MX51_PAD_GPIO1_0__SD1_CD,
-	MX51_PAD_GPIO1_1__SD1_WP,
-	MX51_PAD_GPIO1_7__SD2_WP,
-	MX51_PAD_GPIO1_8__SD2_CD,
-
-	/* spi */
-	MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI,
-	MX51_PAD_CSPI1_MISO__ECSPI1_MISO,
-	MX51_PAD_CSPI1_SS0__GPIO4_24,
-	MX51_PAD_CSPI1_SS1__GPIO4_25,
-	MX51_PAD_CSPI1_RDY__ECSPI1_RDY,
-	MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK,
-	MX51_PAD_GPIO1_6__GPIO1_6,
-
-	/* USB HOST1 */
-	MX51_PAD_USBH1_CLK__USBH1_CLK,
-	MX51_PAD_USBH1_DIR__USBH1_DIR,
-	MX51_PAD_USBH1_NXT__USBH1_NXT,
-	MX51_PAD_USBH1_DATA0__USBH1_DATA0,
-	MX51_PAD_USBH1_DATA1__USBH1_DATA1,
-	MX51_PAD_USBH1_DATA2__USBH1_DATA2,
-	MX51_PAD_USBH1_DATA3__USBH1_DATA3,
-	MX51_PAD_USBH1_DATA4__USBH1_DATA4,
-	MX51_PAD_USBH1_DATA5__USBH1_DATA5,
-	MX51_PAD_USBH1_DATA6__USBH1_DATA6,
-	MX51_PAD_USBH1_DATA7__USBH1_DATA7,
-
-	/* USB HUB RESET */
-	MX51_PAD_GPIO1_5__GPIO1_5,
-
-	/* WLAN */
-	MX51_PAD_EIM_A22__GPIO2_16,
-	MX51_PAD_EIM_A16__GPIO2_10,
-
-	/* USB PHY RESET */
-	MX51_PAD_EIM_D27__GPIO2_9,
-};
-
-/* Serial ports */
-static const struct imxuart_platform_data uart_pdata = {
-	.flags = IMXUART_HAVE_RTSCTS,
-};
-
-/* This function is board specific as the bit mask for the plldiv will also
- * be different for other Freescale SoCs, thus a common bitmask is not
- * possible and cannot get place in /plat-mxc/ehci.c.
- */
-static int initialize_otg_port(struct platform_device *pdev)
-{
-	u32 v;
-	void __iomem *usb_base;
-	void __iomem *usbother_base;
-	usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
-	if (!usb_base)
-		return -ENOMEM;
-	usbother_base = (void __iomem *)(usb_base + MX5_USBOTHER_REGS_OFFSET);
-
-	/* Set the PHY clock to 19.2MHz */
-	v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
-	v &= ~MX5_USB_UTMI_PHYCTRL1_PLLDIV_MASK;
-	v |= MX51_USB_PLL_DIV_19_2_MHZ;
-	__raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
-	iounmap(usb_base);
-
-	mdelay(10);
-
-	return mx51_initialize_usb_hw(pdev->id, MXC_EHCI_INTERNAL_PHY);
-}
-
-static const struct mxc_usbh_platform_data dr_utmi_config __initconst = {
-	.init   = initialize_otg_port,
-	.portsc = MXC_EHCI_UTMI_16BIT,
-};
-
-static int initialize_usbh1_port(struct platform_device *pdev)
-{
-	iomux_v3_cfg_t usbh1stp = MX51_PAD_USBH1_STP__USBH1_STP;
-	iomux_v3_cfg_t usbh1gpio = MX51_PAD_USBH1_STP__GPIO1_27;
-	u32 v;
-	void __iomem *usb_base;
-	void __iomem *socregs_base;
-
-	mxc_iomux_v3_setup_pad(usbh1gpio);
-	gpio_request(EFIKAMX_USBH1_STP, "usbh1_stp");
-	gpio_direction_output(EFIKAMX_USBH1_STP, 0);
-	msleep(1);
-	gpio_set_value(EFIKAMX_USBH1_STP, 1);
-	msleep(1);
-
-	usb_base = ioremap(MX51_USB_OTG_BASE_ADDR, SZ_4K);
-	socregs_base = (void __iomem *)(usb_base + MX5_USBOTHER_REGS_OFFSET);
-
-	/* The clock for the USBH1 ULPI port will come externally */
-	/* from the PHY. */
-	v = __raw_readl(socregs_base + MX51_USB_CTRL_1_OFFSET);
-	__raw_writel(v | MX51_USB_CTRL_UH1_EXT_CLK_EN,
-			socregs_base + MX51_USB_CTRL_1_OFFSET);
-
-	iounmap(usb_base);
-
-	gpio_free(EFIKAMX_USBH1_STP);
-	mxc_iomux_v3_setup_pad(usbh1stp);
-
-	mdelay(10);
-
-	return mx51_initialize_usb_hw(pdev->id, MXC_EHCI_ITC_NO_THRESHOLD);
-}
-
-static struct mxc_usbh_platform_data usbh1_config __initdata = {
-	.init   = initialize_usbh1_port,
-	.portsc = MXC_EHCI_MODE_ULPI,
-};
-
-static void mx51_efika_hubreset(void)
-{
-	gpio_request(EFIKAMX_USB_HUB_RESET, "usb_hub_rst");
-	gpio_direction_output(EFIKAMX_USB_HUB_RESET, 1);
-	msleep(1);
-	gpio_set_value(EFIKAMX_USB_HUB_RESET, 0);
-	msleep(1);
-	gpio_set_value(EFIKAMX_USB_HUB_RESET, 1);
-}
-
-static void __init mx51_efika_usb(void)
-{
-	mx51_efika_hubreset();
-
-	/* pulling it low, means no USB at all... */
-	gpio_request(EFIKA_USB_PHY_RESET, "usb_phy_reset");
-	gpio_direction_output(EFIKA_USB_PHY_RESET, 0);
-	msleep(1);
-	gpio_set_value(EFIKA_USB_PHY_RESET, 1);
-
-	usbh1_config.otg = imx_otg_ulpi_create(ULPI_OTG_DRVVBUS |
-			ULPI_OTG_DRVVBUS_EXT | ULPI_OTG_EXTVBUSIND);
-
-	imx51_add_mxc_ehci_otg(&dr_utmi_config);
-	if (usbh1_config.otg)
-		imx51_add_mxc_ehci_hs(1, &usbh1_config);
-}
-
-static struct mtd_partition mx51_efika_spi_nor_partitions[] = {
-	{
-	 .name = "u-boot",
-	 .offset = 0,
-	 .size = SZ_256K,
-	},
-	{
-	  .name = "config",
-	  .offset = MTDPART_OFS_APPEND,
-	  .size = SZ_64K,
-	},
-};
-
-static struct flash_platform_data mx51_efika_spi_flash_data = {
-	.name		= "spi_flash",
-	.parts		= mx51_efika_spi_nor_partitions,
-	.nr_parts	= ARRAY_SIZE(mx51_efika_spi_nor_partitions),
-	.type		= "sst25vf032b",
-};
-
-static struct regulator_consumer_supply sw1_consumers[] = {
-	{
-		.supply = "cpu_vcc",
-	}
-};
-
-static struct regulator_consumer_supply vdig_consumers[] = {
-	/* sgtl5000 */
-	REGULATOR_SUPPLY("VDDA", "1-000a"),
-	REGULATOR_SUPPLY("VDDD", "1-000a"),
-};
-
-static struct regulator_consumer_supply vvideo_consumers[] = {
-	/* sgtl5000 */
-	REGULATOR_SUPPLY("VDDIO", "1-000a"),
-};
-
-static struct regulator_consumer_supply vsd_consumers[] = {
-	REGULATOR_SUPPLY("vmmc", "sdhci-esdhc-imx51.0"),
-	REGULATOR_SUPPLY("vmmc", "sdhci-esdhc-imx51.1"),
-};
-
-static struct regulator_consumer_supply pwgt1_consumer[] = {
-	{
-		.supply = "pwgt1",
-	}
-};
-
-static struct regulator_consumer_supply pwgt2_consumer[] = {
-	{
-		.supply = "pwgt2",
-	}
-};
-
-static struct regulator_consumer_supply coincell_consumer[] = {
-	{
-		.supply = "coincell",
-	}
-};
-
-static struct regulator_init_data sw1_init = {
-	.constraints = {
-		.name = "SW1",
-		.min_uV = 600000,
-		.max_uV = 1375000,
-		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
-		.valid_modes_mask = 0,
-		.always_on = 1,
-		.boot_on = 1,
-		.state_mem = {
-			.uV = 850000,
-			.mode = REGULATOR_MODE_NORMAL,
-			.enabled = 1,
-		},
-	},
-	.num_consumer_supplies = ARRAY_SIZE(sw1_consumers),
-	.consumer_supplies = sw1_consumers,
-};
-
-static struct regulator_init_data sw2_init = {
-	.constraints = {
-		.name = "SW2",
-		.min_uV = 900000,
-		.max_uV = 1850000,
-		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
-		.always_on = 1,
-		.boot_on = 1,
-		.state_mem = {
-			.uV = 950000,
-			.mode = REGULATOR_MODE_NORMAL,
-			.enabled = 1,
-		},
-	}
-};
-
-static struct regulator_init_data sw3_init = {
-	.constraints = {
-		.name = "SW3",
-		.min_uV = 1100000,
-		.max_uV = 1850000,
-		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
-		.always_on = 1,
-		.boot_on = 1,
-	}
-};
-
-static struct regulator_init_data sw4_init = {
-	.constraints = {
-		.name = "SW4",
-		.min_uV = 1100000,
-		.max_uV = 1850000,
-		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
-		.always_on = 1,
-		.boot_on = 1,
-	}
-};
-
-static struct regulator_init_data viohi_init = {
-	.constraints = {
-		.name = "VIOHI",
-		.boot_on = 1,
-		.always_on = 1,
-	}
-};
-
-static struct regulator_init_data vusb_init = {
-	.constraints = {
-		.name = "VUSB",
-		.boot_on = 1,
-		.always_on = 1,
-	}
-};
-
-static struct regulator_init_data swbst_init = {
-	.constraints = {
-		.name = "SWBST",
-	}
-};
-
-static struct regulator_init_data vdig_init = {
-	.constraints = {
-		.name = "VDIG",
-		.min_uV = 1050000,
-		.max_uV = 1800000,
-		.valid_ops_mask =
-			REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
-		.boot_on = 1,
-		.always_on = 1,
-	},
-	.num_consumer_supplies = ARRAY_SIZE(vdig_consumers),
-	.consumer_supplies = vdig_consumers,
-};
-
-static struct regulator_init_data vpll_init = {
-	.constraints = {
-		.name = "VPLL",
-		.min_uV = 1050000,
-		.max_uV = 1800000,
-		.valid_ops_mask =
-			REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
-		.boot_on = 1,
-		.always_on = 1,
-	}
-};
-
-static struct regulator_init_data vusb2_init = {
-	.constraints = {
-		.name = "VUSB2",
-		.min_uV = 2400000,
-		.max_uV = 2775000,
-		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
-		.boot_on = 1,
-		.always_on = 1,
-	}
-};
-
-static struct regulator_init_data vvideo_init = {
-	.constraints = {
-		.name = "VVIDEO",
-		.min_uV = 2775000,
-		.max_uV = 2775000,
-		.valid_ops_mask =
-			REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
-		.boot_on = 1,
-		.apply_uV = 1,
-	},
-	.num_consumer_supplies = ARRAY_SIZE(vvideo_consumers),
-	.consumer_supplies = vvideo_consumers,
-};
-
-static struct regulator_init_data vaudio_init = {
-	.constraints = {
-		.name = "VAUDIO",
-		.min_uV = 2300000,
-		.max_uV = 3000000,
-		.valid_ops_mask =
-			REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
-		.boot_on = 1,
-	}
-};
-
-static struct regulator_init_data vsd_init = {
-	.constraints = {
-		.name = "VSD",
-		.min_uV = 1800000,
-		.max_uV = 3150000,
-		.valid_ops_mask =
-			REGULATOR_CHANGE_VOLTAGE,
-		.boot_on = 1,
-	},
-	.num_consumer_supplies = ARRAY_SIZE(vsd_consumers),
-	.consumer_supplies = vsd_consumers,
-};
-
-static struct regulator_init_data vcam_init = {
-	.constraints = {
-		.name = "VCAM",
-		.min_uV = 2500000,
-		.max_uV = 3000000,
-		.valid_ops_mask =
-			REGULATOR_CHANGE_VOLTAGE |
-			REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS,
-		.valid_modes_mask = REGULATOR_MODE_FAST | REGULATOR_MODE_NORMAL,
-		.boot_on = 1,
-	}
-};
-
-static struct regulator_init_data vgen1_init = {
-	.constraints = {
-		.name = "VGEN1",
-		.min_uV = 1200000,
-		.max_uV = 3150000,
-		.valid_ops_mask =
-			REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
-		.boot_on = 1,
-		.always_on = 1,
-	}
-};
-
-static struct regulator_init_data vgen2_init = {
-	.constraints = {
-		.name = "VGEN2",
-		.min_uV = 1200000,
-		.max_uV = 3150000,
-		.valid_ops_mask =
-			REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
-		.boot_on = 1,
-		.always_on = 1,
-	}
-};
-
-static struct regulator_init_data vgen3_init = {
-	.constraints = {
-		.name = "VGEN3",
-		.min_uV = 1800000,
-		.max_uV = 2900000,
-		.valid_ops_mask =
-			REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
-		.boot_on = 1,
-		.always_on = 1,
-	}
-};
-
-static struct regulator_init_data gpo1_init = {
-	.constraints = {
-		.name = "GPO1",
-	}
-};
-
-static struct regulator_init_data gpo2_init = {
-	.constraints = {
-		.name = "GPO2",
-	}
-};
-
-static struct regulator_init_data gpo3_init = {
-	.constraints = {
-		.name = "GPO3",
-	}
-};
-
-static struct regulator_init_data gpo4_init = {
-	.constraints = {
-		.name = "GPO4",
-	}
-};
-
-static struct regulator_init_data pwgt1_init = {
-	.constraints = {
-		.valid_ops_mask = REGULATOR_CHANGE_STATUS,
-		.boot_on        = 1,
-	},
-	.num_consumer_supplies = ARRAY_SIZE(pwgt1_consumer),
-	.consumer_supplies = pwgt1_consumer,
-};
-
-static struct regulator_init_data pwgt2_init = {
-	.constraints = {
-		.valid_ops_mask = REGULATOR_CHANGE_STATUS,
-		.boot_on        = 1,
-	},
-	.num_consumer_supplies = ARRAY_SIZE(pwgt2_consumer),
-	.consumer_supplies = pwgt2_consumer,
-};
-
-static struct regulator_init_data vcoincell_init = {
-	.constraints = {
-		.name = "COINCELL",
-		.min_uV = 3000000,
-		.max_uV = 3000000,
-		.valid_ops_mask =
-			REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
-	},
-	.num_consumer_supplies = ARRAY_SIZE(coincell_consumer),
-	.consumer_supplies = coincell_consumer,
-};
-
-static struct mc13xxx_regulator_init_data mx51_efika_regulators[] = {
-	{ .id = MC13892_SW1,		.init_data =  &sw1_init },
-	{ .id = MC13892_SW2,		.init_data =  &sw2_init },
-	{ .id = MC13892_SW3,		.init_data =  &sw3_init },
-	{ .id = MC13892_SW4,		.init_data =  &sw4_init },
-	{ .id = MC13892_SWBST,		.init_data =  &swbst_init },
-	{ .id = MC13892_VIOHI,		.init_data =  &viohi_init },
-	{ .id = MC13892_VPLL,		.init_data =  &vpll_init },
-	{ .id = MC13892_VDIG,		.init_data =  &vdig_init },
-	{ .id = MC13892_VSD,		.init_data =  &vsd_init },
-	{ .id = MC13892_VUSB2,		.init_data =  &vusb2_init },
-	{ .id = MC13892_VVIDEO,		.init_data =  &vvideo_init },
-	{ .id = MC13892_VAUDIO,		.init_data =  &vaudio_init },
-	{ .id = MC13892_VCAM,		.init_data =  &vcam_init },
-	{ .id = MC13892_VGEN1,		.init_data =  &vgen1_init },
-	{ .id = MC13892_VGEN2,		.init_data =  &vgen2_init },
-	{ .id = MC13892_VGEN3,		.init_data =  &vgen3_init },
-	{ .id = MC13892_VUSB,		.init_data =  &vusb_init },
-	{ .id = MC13892_GPO1,		.init_data =  &gpo1_init },
-	{ .id = MC13892_GPO2,		.init_data =  &gpo2_init },
-	{ .id = MC13892_GPO3,		.init_data =  &gpo3_init },
-	{ .id = MC13892_GPO4,		.init_data =  &gpo4_init },
-	{ .id = MC13892_PWGT1SPI,	.init_data = &pwgt1_init },
-	{ .id = MC13892_PWGT2SPI,	.init_data = &pwgt2_init },
-	{ .id = MC13892_VCOINCELL,	.init_data = &vcoincell_init },
-};
-
-static struct mc13xxx_platform_data mx51_efika_mc13892_data = {
-	.flags = MC13XXX_USE_RTC,
-	.regulators = {
-		.num_regulators = ARRAY_SIZE(mx51_efika_regulators),
-		.regulators = mx51_efika_regulators,
-	},
-};
-
-static struct spi_board_info mx51_efika_spi_board_info[] __initdata = {
-	{
-		.modalias = "m25p80",
-		.max_speed_hz = 25000000,
-		.bus_num = 0,
-		.chip_select = 1,
-		.platform_data = &mx51_efika_spi_flash_data,
-		.irq = -1,
-	},
-	{
-		.modalias = "mc13892",
-		.max_speed_hz = 1000000,
-		.bus_num = 0,
-		.chip_select = 0,
-		.platform_data = &mx51_efika_mc13892_data,
-		/* irq number is run-time assigned */
-	},
-};
-
-static int mx51_efika_spi_cs[] = {
-	EFIKAMX_SPI_CS0,
-	EFIKAMX_SPI_CS1,
-};
-
-static const struct spi_imx_master mx51_efika_spi_pdata __initconst = {
-	.chipselect     = mx51_efika_spi_cs,
-	.num_chipselect = ARRAY_SIZE(mx51_efika_spi_cs),
-};
-
-void __init efika_board_common_init(void)
-{
-	mxc_iomux_v3_setup_multiple_pads(mx51efika_pads,
-					ARRAY_SIZE(mx51efika_pads));
-	imx51_add_imx_uart(0, &uart_pdata);
-	mx51_efika_usb();
-
-	/* FIXME: comes from original code. check this. */
-	if (mx51_revision() < IMX_CHIP_REVISION_2_0)
-		sw2_init.constraints.state_mem.uV = 1100000;
-	else if (mx51_revision() == IMX_CHIP_REVISION_2_0) {
-		sw2_init.constraints.state_mem.uV = 1250000;
-		sw1_init.constraints.state_mem.uV = 1000000;
-	}
-	if (machine_is_mx51_efikasb())
-		vgen1_init.constraints.max_uV = 1200000;
-
-	gpio_request(EFIKAMX_PMIC, "pmic irq");
-	gpio_direction_input(EFIKAMX_PMIC);
-	mx51_efika_spi_board_info[1].irq = gpio_to_irq(EFIKAMX_PMIC);
-	spi_register_board_info(mx51_efika_spi_board_info,
-		ARRAY_SIZE(mx51_efika_spi_board_info));
-	imx51_add_ecspi(0, &mx51_efika_spi_pdata);
-
-	imx51_add_pata_imx();
-
-#if defined(CONFIG_CPU_FREQ_IMX)
-	get_cpu_op = mx51_get_cpu_op;
-#endif
-}
diff --git a/arch/arm/mach-imx/platsmp.c b/arch/arm/mach-imx/platsmp.c
index ab98c6f..2ac43e1 100644
--- a/arch/arm/mach-imx/platsmp.c
+++ b/arch/arm/mach-imx/platsmp.c
@@ -41,7 +41,7 @@ void __init imx_scu_map_io(void)
 	scu_base = IMX_IO_ADDRESS(base);
 }
 
-void __cpuinit platform_secondary_init(unsigned int cpu)
+static void __cpuinit imx_secondary_init(unsigned int cpu)
 {
 	/*
 	 * if any interrupts are already enabled for the primary
@@ -51,7 +51,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
 	gic_secondary_init(0);
 }
 
-int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
+static int __cpuinit imx_boot_secondary(unsigned int cpu, struct task_struct *idle)
 {
 	imx_set_cpu_jump(cpu, v7_secondary_startup);
 	imx_enable_cpu(cpu, true);
@@ -62,7 +62,7 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
  * Initialise the CPU possible map early - this describes the CPUs
  * which may be present or become present in the system.
  */
-void __init smp_init_cpus(void)
+static void __init imx_smp_init_cpus(void)
 {
 	int i, ncores;
 
@@ -79,7 +79,17 @@ void imx_smp_prepare(void)
 	scu_enable(scu_base);
 }
 
-void __init platform_smp_prepare_cpus(unsigned int max_cpus)
+static void __init imx_smp_prepare_cpus(unsigned int max_cpus)
 {
 	imx_smp_prepare();
 }
+
+struct smp_operations  imx_smp_ops __initdata = {
+	.smp_init_cpus		= imx_smp_init_cpus,
+	.smp_prepare_cpus	= imx_smp_prepare_cpus,
+	.smp_secondary_init	= imx_secondary_init,
+	.smp_boot_secondary	= imx_boot_secondary,
+#ifdef CONFIG_HOTPLUG_CPU
+	.cpu_die		= imx_cpu_die,
+#endif
+};
diff --git a/arch/arm/mach-integrator/Makefile b/arch/arm/mach-integrator/Makefile
index ebeef96..5521d18 100644
--- a/arch/arm/mach-integrator/Makefile
+++ b/arch/arm/mach-integrator/Makefile
@@ -4,11 +4,10 @@
 
 # Object file lists.
 
-obj-y					:= core.o lm.o
+obj-y					:= core.o lm.o leds.o
 obj-$(CONFIG_ARCH_INTEGRATOR_AP)	+= integrator_ap.o
 obj-$(CONFIG_ARCH_INTEGRATOR_CP)	+= integrator_cp.o
 
-obj-$(CONFIG_LEDS)			+= leds.o
 obj-$(CONFIG_PCI)			+= pci_v3.o pci.o
 obj-$(CONFIG_CPU_FREQ_INTEGRATOR)	+= cpu.o
 obj-$(CONFIG_INTEGRATOR_IMPD1)		+= impd1.o
diff --git a/arch/arm/mach-integrator/common.h b/arch/arm/mach-integrator/common.h
index 899561d..c3ff21b 100644
--- a/arch/arm/mach-integrator/common.h
+++ b/arch/arm/mach-integrator/common.h
@@ -1,3 +1,6 @@
+#include <linux/amba/serial.h>
+extern struct amba_pl010_data integrator_uart_data;
 void integrator_init_early(void);
+int integrator_init(bool is_cp);
 void integrator_reserve(void);
 void integrator_restart(char, const char *);
diff --git a/arch/arm/mach-integrator/core.c b/arch/arm/mach-integrator/core.c
index 3fa6c51..ea22a17 100644
--- a/arch/arm/mach-integrator/core.c
+++ b/arch/arm/mach-integrator/core.c
@@ -28,12 +28,13 @@
 #include <mach/cm.h>
 #include <mach/irqs.h>
 
-#include <asm/leds.h>
 #include <asm/mach-types.h>
 #include <asm/mach/time.h>
 #include <asm/pgtable.h>
 
-static struct amba_pl010_data integrator_uart_data;
+#include "common.h"
+
+#ifdef CONFIG_ATAGS
 
 #define INTEGRATOR_RTC_IRQ	{ IRQ_RTCINT }
 #define INTEGRATOR_UART0_IRQ	{ IRQ_UARTINT0 }
@@ -61,7 +62,7 @@ static struct amba_device *amba_devs[] __initdata = {
 	&kmi1_device,
 };
 
-static int __init integrator_init(void)
+int __init integrator_init(bool is_cp)
 {
 	int i;
 
@@ -70,7 +71,7 @@ static int __init integrator_init(void)
 	 * hard-code them. The Integator/CP and forward have proper cell IDs.
 	 * Else we leave them undefined to the bus driver can autoprobe them.
 	 */
-	if (machine_is_integrator()) {
+	if (!is_cp) {
 		rtc_device.periphid	= 0x00041030;
 		uart0_device.periphid	= 0x00041010;
 		uart1_device.periphid	= 0x00041010;
@@ -86,7 +87,7 @@ static int __init integrator_init(void)
 	return 0;
 }
 
-arch_initcall(integrator_init);
+#endif
 
 /*
  * On the Integrator platform, the port RTS and DTR are provided by
@@ -95,17 +96,20 @@ arch_initcall(integrator_init);
  *  UART0  7    6
  *  UART1  5    4
  */
-#define SC_CTRLC	IO_ADDRESS(INTEGRATOR_SC_CTRLC)
-#define SC_CTRLS	IO_ADDRESS(INTEGRATOR_SC_CTRLS)
+#define SC_CTRLC	__io_address(INTEGRATOR_SC_CTRLC)
+#define SC_CTRLS	__io_address(INTEGRATOR_SC_CTRLS)
 
 static void integrator_uart_set_mctrl(struct amba_device *dev, void __iomem *base, unsigned int mctrl)
 {
 	unsigned int ctrls = 0, ctrlc = 0, rts_mask, dtr_mask;
+	u32 phybase = dev->res.start;
 
-	if (dev == &uart0_device) {
+	if (phybase == INTEGRATOR_UART0_BASE) {
+		/* UART0 */
 		rts_mask = 1 << 4;
 		dtr_mask = 1 << 5;
 	} else {
+		/* UART1 */
 		rts_mask = 1 << 6;
 		dtr_mask = 1 << 7;
 	}
@@ -124,12 +128,10 @@ static void integrator_uart_set_mctrl(struct amba_device *dev, void __iomem *bas
 	__raw_writel(ctrlc, SC_CTRLC);
 }
 
-static struct amba_pl010_data integrator_uart_data = {
+struct amba_pl010_data integrator_uart_data = {
 	.set_mctrl = integrator_uart_set_mctrl,
 };
 
-#define CM_CTRL	IO_ADDRESS(INTEGRATOR_HDR_CTRL)
-
 static DEFINE_RAW_SPINLOCK(cm_lock);
 
 /**
diff --git a/arch/arm/mach-integrator/cpu.c b/arch/arm/mach-integrator/cpu.c
index fbb4577..590c192 100644
--- a/arch/arm/mach-integrator/cpu.c
+++ b/arch/arm/mach-integrator/cpu.c
@@ -25,10 +25,10 @@
 
 static struct cpufreq_driver integrator_driver;
 
-#define CM_ID  	IO_ADDRESS(INTEGRATOR_HDR_ID)
-#define CM_OSC	IO_ADDRESS(INTEGRATOR_HDR_OSC)
-#define CM_STAT IO_ADDRESS(INTEGRATOR_HDR_STAT)
-#define CM_LOCK IO_ADDRESS(INTEGRATOR_HDR_LOCK)
+#define CM_ID  	__io_address(INTEGRATOR_HDR_ID)
+#define CM_OSC	__io_address(INTEGRATOR_HDR_OSC)
+#define CM_STAT __io_address(INTEGRATOR_HDR_STAT)
+#define CM_LOCK __io_address(INTEGRATOR_HDR_LOCK)
 
 static const struct icst_params lclk_params = {
 	.ref		= 24000000,
diff --git a/arch/arm/mach-integrator/include/mach/cm.h b/arch/arm/mach-integrator/include/mach/cm.h
index 445d57a..1a78692e 100644
--- a/arch/arm/mach-integrator/include/mach/cm.h
+++ b/arch/arm/mach-integrator/include/mach/cm.h
@@ -3,6 +3,8 @@
  */
 void cm_control(u32, u32);
 
+#define CM_CTRL	IO_ADDRESS(INTEGRATOR_HDR_CTRL)
+
 #define CM_CTRL_LED			(1 << 0)
 #define CM_CTRL_nMBDET			(1 << 1)
 #define CM_CTRL_REMAP			(1 << 2)
diff --git a/arch/arm/mach-integrator/include/mach/io.h b/arch/arm/mach-integrator/include/mach/io.h
deleted file mode 100644
index 8de70de..0000000
--- a/arch/arm/mach-integrator/include/mach/io.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- *  arch/arm/mach-integrator/include/mach/io.h
- *
- *  Copyright (C) 1999 ARM Limited
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#ifndef __ASM_ARM_ARCH_IO_H
-#define __ASM_ARM_ARCH_IO_H
-
-/*
- * WARNING: this has to mirror definitions in platform.h
- */
-#define PCI_MEMORY_VADDR        0xe8000000
-#define PCI_CONFIG_VADDR        0xec000000
-#define PCI_V3_VADDR            0xed000000
-#define PCI_IO_VADDR            0xee000000
-
-#define __io(a)			((void __iomem *)(PCI_IO_VADDR + (a)))
-
-#endif
diff --git a/arch/arm/mach-integrator/include/mach/platform.h b/arch/arm/mach-integrator/include/mach/platform.h
index ec467ba..4c03475 100644
--- a/arch/arm/mach-integrator/include/mach/platform.h
+++ b/arch/arm/mach-integrator/include/mach/platform.h
@@ -324,6 +324,10 @@
  */
 #define PHYS_PCI_V3_BASE                0x62000000
 
+#define PCI_MEMORY_VADDR		0xe8000000
+#define PCI_CONFIG_VADDR		0xec000000
+#define PCI_V3_VADDR			0xed000000
+
 /* ------------------------------------------------------------------------
  *  Integrator Interrupt Controllers
  * ------------------------------------------------------------------------
diff --git a/arch/arm/mach-integrator/integrator_ap.c b/arch/arm/mach-integrator/integrator_ap.c
index 3b22675..d5b5435a 100644
--- a/arch/arm/mach-integrator/integrator_ap.c
+++ b/arch/arm/mach-integrator/integrator_ap.c
@@ -34,6 +34,9 @@
 #include <linux/mtd/physmap.h>
 #include <linux/clk.h>
 #include <linux/platform_data/clk-integrator.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
 #include <video/vga.h>
 
 #include <mach/hardware.h>
@@ -50,6 +53,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/irq.h>
 #include <asm/mach/map.h>
+#include <asm/mach/pci.h>
 #include <asm/mach/time.h>
 
 #include <plat/fpga-irq.h>
@@ -73,7 +77,7 @@
  * e8000000	40000000	PCI memory		PHYS_PCI_MEM_BASE	(max 512M)
  * ec000000	61000000	PCI config space	PHYS_PCI_CONFIG_BASE	(max 16M)
  * ed000000	62000000	PCI V3 regs		PHYS_PCI_V3_BASE	(max 64k)
- * ee000000	60000000	PCI IO			PHYS_PCI_IO_BASE	(max 16M)
+ * fee00000	60000000	PCI IO			PHYS_PCI_IO_BASE	(max 16M)
  * ef000000			Cache flush
  * f1000000	10000000	Core module registers
  * f1100000	11000000	System controller registers
@@ -133,25 +137,20 @@ static struct map_desc ap_io_desc[] __initdata = {
 		.length		= SZ_4K,
 		.type		= MT_DEVICE
 	}, {
-		.virtual	= PCI_MEMORY_VADDR,
+		.virtual	= (unsigned long)PCI_MEMORY_VADDR,
 		.pfn		= __phys_to_pfn(PHYS_PCI_MEM_BASE),
 		.length		= SZ_16M,
 		.type		= MT_DEVICE
 	}, {
-		.virtual	= PCI_CONFIG_VADDR,
+		.virtual	= (unsigned long)PCI_CONFIG_VADDR,
 		.pfn		= __phys_to_pfn(PHYS_PCI_CONFIG_BASE),
 		.length		= SZ_16M,
 		.type		= MT_DEVICE
 	}, {
-		.virtual	= PCI_V3_VADDR,
+		.virtual	= (unsigned long)PCI_V3_VADDR,
 		.pfn		= __phys_to_pfn(PHYS_PCI_V3_BASE),
 		.length		= SZ_64K,
 		.type		= MT_DEVICE
-	}, {
-		.virtual	= PCI_IO_VADDR,
-		.pfn		= __phys_to_pfn(PHYS_PCI_IO_BASE),
-		.length		= SZ_64K,
-		.type		= MT_DEVICE
 	}
 };
 
@@ -159,23 +158,7 @@ static void __init ap_map_io(void)
 {
 	iotable_init(ap_io_desc, ARRAY_SIZE(ap_io_desc));
 	vga_base = PCI_MEMORY_VADDR;
-}
-
-#define INTEGRATOR_SC_VALID_INT	0x003fffff
-
-static void __init ap_init_irq(void)
-{
-	/* Disable all interrupts initially. */
-	/* Do the core module ones */
-	writel(-1, VA_CMIC_BASE + IRQ_ENABLE_CLEAR);
-
-	/* do the header card stuff next */
-	writel(-1, VA_IC_BASE + IRQ_ENABLE_CLEAR);
-	writel(-1, VA_IC_BASE + FIQ_ENABLE_CLEAR);
-
-	fpga_irq_init(VA_IC_BASE, "SC", IRQ_PIC_START,
-		-1, INTEGRATOR_SC_VALID_INT, NULL);
-	integrator_clk_init(false);
+	pci_map_io_early(__phys_to_pfn(PHYS_PCI_IO_BASE));
 }
 
 #ifdef CONFIG_PM
@@ -270,56 +253,12 @@ static struct physmap_flash_data ap_flash_data = {
 	.set_vpp	= ap_flash_set_vpp,
 };
 
-static struct resource cfi_flash_resource = {
-	.start		= INTEGRATOR_FLASH_BASE,
-	.end		= INTEGRATOR_FLASH_BASE + INTEGRATOR_FLASH_SIZE - 1,
-	.flags		= IORESOURCE_MEM,
-};
-
-static struct platform_device cfi_flash_device = {
-	.name		= "physmap-flash",
-	.id		= 0,
-	.dev		= {
-		.platform_data	= &ap_flash_data,
-	},
-	.num_resources	= 1,
-	.resource	= &cfi_flash_resource,
-};
-
-static void __init ap_init(void)
-{
-	unsigned long sc_dec;
-	int i;
-
-	platform_device_register(&cfi_flash_device);
-
-	sc_dec = readl(VA_SC_BASE + INTEGRATOR_SC_DEC_OFFSET);
-	for (i = 0; i < 4; i++) {
-		struct lm_device *lmdev;
-
-		if ((sc_dec & (16 << i)) == 0)
-			continue;
-
-		lmdev = kzalloc(sizeof(struct lm_device), GFP_KERNEL);
-		if (!lmdev)
-			continue;
-
-		lmdev->resource.start = 0xc0000000 + 0x10000000 * i;
-		lmdev->resource.end = lmdev->resource.start + 0x0fffffff;
-		lmdev->resource.flags = IORESOURCE_MEM;
-		lmdev->irq = IRQ_AP_EXPINT0 + i;
-		lmdev->id = i;
-
-		lm_device_register(lmdev);
-	}
-}
-
 /*
  * Where is the timer (VA)?
  */
-#define TIMER0_VA_BASE IO_ADDRESS(INTEGRATOR_TIMER0_BASE)
-#define TIMER1_VA_BASE IO_ADDRESS(INTEGRATOR_TIMER1_BASE)
-#define TIMER2_VA_BASE IO_ADDRESS(INTEGRATOR_TIMER2_BASE)
+#define TIMER0_VA_BASE __io_address(INTEGRATOR_TIMER0_BASE)
+#define TIMER1_VA_BASE __io_address(INTEGRATOR_TIMER1_BASE)
+#define TIMER2_VA_BASE __io_address(INTEGRATOR_TIMER2_BASE)
 
 static unsigned long timer_reload;
 
@@ -328,9 +267,9 @@ static u32 notrace integrator_read_sched_clock(void)
 	return -readl((void __iomem *) TIMER2_VA_BASE + TIMER_VALUE);
 }
 
-static void integrator_clocksource_init(unsigned long inrate)
+static void integrator_clocksource_init(unsigned long inrate,
+					void __iomem *base)
 {
-	void __iomem *base = (void __iomem *)TIMER2_VA_BASE;
 	u32 ctrl = TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC;
 	unsigned long rate = inrate;
 
@@ -347,7 +286,7 @@ static void integrator_clocksource_init(unsigned long inrate)
 	setup_sched_clock(integrator_read_sched_clock, 16, rate);
 }
 
-static void __iomem * const clkevt_base = (void __iomem *)TIMER1_VA_BASE;
+static void __iomem * clkevt_base;
 
 /*
  * IRQ handler for the timer
@@ -419,11 +358,13 @@ static struct irqaction integrator_timer_irq = {
 	.dev_id		= &integrator_clockevent,
 };
 
-static void integrator_clockevent_init(unsigned long inrate)
+static void integrator_clockevent_init(unsigned long inrate,
+				void __iomem *base, int irq)
 {
 	unsigned long rate = inrate;
 	unsigned int ctrl = 0;
 
+	clkevt_base = base;
 	/* Calculate and program a divisor */
 	if (rate > 0x100000 * HZ) {
 		rate /= 256;
@@ -435,7 +376,7 @@ static void integrator_clockevent_init(unsigned long inrate)
 	timer_reload = rate / HZ;
 	writel(ctrl, clkevt_base + TIMER_CTRL);
 
-	setup_irq(IRQ_TIMERINT1, &integrator_timer_irq);
+	setup_irq(irq, &integrator_timer_irq);
 	clockevents_config_and_register(&integrator_clockevent,
 					rate,
 					1,
@@ -446,9 +387,153 @@ void __init ap_init_early(void)
 {
 }
 
+#ifdef CONFIG_OF
+
+static void __init ap_init_timer_of(void)
+{
+	struct device_node *node;
+	const char *path;
+	void __iomem *base;
+	int err;
+	int irq;
+	struct clk *clk;
+	unsigned long rate;
+
+	clk = clk_get_sys("ap_timer", NULL);
+	BUG_ON(IS_ERR(clk));
+	clk_prepare_enable(clk);
+	rate = clk_get_rate(clk);
+
+	err = of_property_read_string(of_aliases,
+				"arm,timer-primary", &path);
+	if (WARN_ON(err))
+		return;
+	node = of_find_node_by_path(path);
+	base = of_iomap(node, 0);
+	if (WARN_ON(!base))
+		return;
+	writel(0, base + TIMER_CTRL);
+	integrator_clocksource_init(rate, base);
+
+	err = of_property_read_string(of_aliases,
+				"arm,timer-secondary", &path);
+	if (WARN_ON(err))
+		return;
+	node = of_find_node_by_path(path);
+	base = of_iomap(node, 0);
+	if (WARN_ON(!base))
+		return;
+	irq = irq_of_parse_and_map(node, 0);
+	writel(0, base + TIMER_CTRL);
+	integrator_clockevent_init(rate, base, irq);
+}
+
+static struct sys_timer ap_of_timer = {
+	.init		= ap_init_timer_of,
+};
+
+static const struct of_device_id fpga_irq_of_match[] __initconst = {
+	{ .compatible = "arm,versatile-fpga-irq", .data = fpga_irq_of_init, },
+	{ /* Sentinel */ }
+};
+
+static void __init ap_init_irq_of(void)
+{
+	/* disable core module IRQs */
+	writel(0xffffffffU, VA_CMIC_BASE + IRQ_ENABLE_CLEAR);
+	of_irq_init(fpga_irq_of_match);
+	integrator_clk_init(false);
+}
+
+/* For the Device Tree, add in the UART callbacks as AUXDATA */
+static struct of_dev_auxdata ap_auxdata_lookup[] __initdata = {
+	OF_DEV_AUXDATA("arm,primecell", INTEGRATOR_RTC_BASE,
+		"rtc", NULL),
+	OF_DEV_AUXDATA("arm,primecell", INTEGRATOR_UART0_BASE,
+		"uart0", &integrator_uart_data),
+	OF_DEV_AUXDATA("arm,primecell", INTEGRATOR_UART1_BASE,
+		"uart1", &integrator_uart_data),
+	OF_DEV_AUXDATA("arm,primecell", KMI0_BASE,
+		"kmi0", NULL),
+	OF_DEV_AUXDATA("arm,primecell", KMI1_BASE,
+		"kmi1", NULL),
+	OF_DEV_AUXDATA("cfi-flash", INTEGRATOR_FLASH_BASE,
+		"physmap-flash", &ap_flash_data),
+	{ /* sentinel */ },
+};
+
+static void __init ap_init_of(void)
+{
+	unsigned long sc_dec;
+	int i;
+
+	of_platform_populate(NULL, of_default_bus_match_table,
+			ap_auxdata_lookup, NULL);
+
+	sc_dec = readl(VA_SC_BASE + INTEGRATOR_SC_DEC_OFFSET);
+	for (i = 0; i < 4; i++) {
+		struct lm_device *lmdev;
+
+		if ((sc_dec & (16 << i)) == 0)
+			continue;
+
+		lmdev = kzalloc(sizeof(struct lm_device), GFP_KERNEL);
+		if (!lmdev)
+			continue;
+
+		lmdev->resource.start = 0xc0000000 + 0x10000000 * i;
+		lmdev->resource.end = lmdev->resource.start + 0x0fffffff;
+		lmdev->resource.flags = IORESOURCE_MEM;
+		lmdev->irq = IRQ_AP_EXPINT0 + i;
+		lmdev->id = i;
+
+		lm_device_register(lmdev);
+	}
+}
+
+static const char * ap_dt_board_compat[] = {
+	"arm,integrator-ap",
+	NULL,
+};
+
+DT_MACHINE_START(INTEGRATOR_AP_DT, "ARM Integrator/AP (Device Tree)")
+	.reserve	= integrator_reserve,
+	.map_io		= ap_map_io,
+	.nr_irqs	= NR_IRQS_INTEGRATOR_AP,
+	.init_early	= ap_init_early,
+	.init_irq	= ap_init_irq_of,
+	.handle_irq	= fpga_handle_irq,
+	.timer		= &ap_of_timer,
+	.init_machine	= ap_init_of,
+	.restart	= integrator_restart,
+	.dt_compat      = ap_dt_board_compat,
+MACHINE_END
+
+#endif
+
+#ifdef CONFIG_ATAGS
+
 /*
- * Set up timer(s).
+ * This is where non-devicetree initialization code is collected and stashed
+ * for eventual deletion.
  */
+
+static struct resource cfi_flash_resource = {
+	.start		= INTEGRATOR_FLASH_BASE,
+	.end		= INTEGRATOR_FLASH_BASE + INTEGRATOR_FLASH_SIZE - 1,
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device cfi_flash_device = {
+	.name		= "physmap-flash",
+	.id		= 0,
+	.dev		= {
+		.platform_data	= &ap_flash_data,
+	},
+	.num_resources	= 1,
+	.resource	= &cfi_flash_resource,
+};
+
 static void __init ap_init_timer(void)
 {
 	struct clk *clk;
@@ -463,14 +548,62 @@ static void __init ap_init_timer(void)
 	writel(0, TIMER1_VA_BASE + TIMER_CTRL);
 	writel(0, TIMER2_VA_BASE + TIMER_CTRL);
 
-	integrator_clocksource_init(rate);
-	integrator_clockevent_init(rate);
+	integrator_clocksource_init(rate, (void __iomem *)TIMER2_VA_BASE);
+	integrator_clockevent_init(rate, (void __iomem *)TIMER1_VA_BASE,
+				IRQ_TIMERINT1);
 }
 
 static struct sys_timer ap_timer = {
 	.init		= ap_init_timer,
 };
 
+#define INTEGRATOR_SC_VALID_INT	0x003fffff
+
+static void __init ap_init_irq(void)
+{
+	/* Disable all interrupts initially. */
+	/* Do the core module ones */
+	writel(-1, VA_CMIC_BASE + IRQ_ENABLE_CLEAR);
+
+	/* do the header card stuff next */
+	writel(-1, VA_IC_BASE + IRQ_ENABLE_CLEAR);
+	writel(-1, VA_IC_BASE + FIQ_ENABLE_CLEAR);
+
+	fpga_irq_init(VA_IC_BASE, "SC", IRQ_PIC_START,
+		-1, INTEGRATOR_SC_VALID_INT, NULL);
+	integrator_clk_init(false);
+}
+
+static void __init ap_init(void)
+{
+	unsigned long sc_dec;
+	int i;
+
+	platform_device_register(&cfi_flash_device);
+
+	sc_dec = readl(VA_SC_BASE + INTEGRATOR_SC_DEC_OFFSET);
+	for (i = 0; i < 4; i++) {
+		struct lm_device *lmdev;
+
+		if ((sc_dec & (16 << i)) == 0)
+			continue;
+
+		lmdev = kzalloc(sizeof(struct lm_device), GFP_KERNEL);
+		if (!lmdev)
+			continue;
+
+		lmdev->resource.start = 0xc0000000 + 0x10000000 * i;
+		lmdev->resource.end = lmdev->resource.start + 0x0fffffff;
+		lmdev->resource.flags = IORESOURCE_MEM;
+		lmdev->irq = IRQ_AP_EXPINT0 + i;
+		lmdev->id = i;
+
+		lm_device_register(lmdev);
+	}
+
+	integrator_init(false);
+}
+
 MACHINE_START(INTEGRATOR, "ARM-Integrator")
 	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
 	.atag_offset	= 0x100,
@@ -484,3 +617,5 @@ MACHINE_START(INTEGRATOR, "ARM-Integrator")
 	.init_machine	= ap_init,
 	.restart	= integrator_restart,
 MACHINE_END
+
+#endif
diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c
index 82d5c83..6870a1f 100644
--- a/arch/arm/mach-integrator/integrator_cp.c
+++ b/arch/arm/mach-integrator/integrator_cp.c
@@ -23,6 +23,9 @@
 #include <linux/gfp.h>
 #include <linux/mtd/physmap.h>
 #include <linux/platform_data/clk-integrator.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
 
 #include <mach/hardware.h>
 #include <mach/platform.h>
@@ -49,17 +52,10 @@
 #include "common.h"
 
 #define INTCP_PA_FLASH_BASE		0x24000000
-#define INTCP_FLASH_SIZE		SZ_32M
 
 #define INTCP_PA_CLCD_BASE		0xc0000000
 
-#define INTCP_VA_CIC_BASE		__io_address(INTEGRATOR_HDR_BASE + 0x40)
-#define INTCP_VA_PIC_BASE		__io_address(INTEGRATOR_IC_BASE)
-#define INTCP_VA_SIC_BASE		__io_address(INTEGRATOR_CP_SIC_BASE)
-
-#define INTCP_ETH_SIZE			0x10
-
-#define INTCP_VA_CTRL_BASE		IO_ADDRESS(INTEGRATOR_CP_CTL_BASE)
+#define INTCP_VA_CTRL_BASE		__io_address(INTEGRATOR_CP_CTL_BASE)
 #define INTCP_FLASHPROG			0x04
 #define CINTEGRATOR_FLASHPROG_FLVPPEN	(1 << 0)
 #define CINTEGRATOR_FLASHPROG_FLWREN	(1 << 1)
@@ -143,37 +139,6 @@ static void __init intcp_map_io(void)
 	iotable_init(intcp_io_desc, ARRAY_SIZE(intcp_io_desc));
 }
 
-static void __init intcp_init_irq(void)
-{
-	u32 pic_mask, cic_mask, sic_mask;
-
-	/* These masks are for the HW IRQ registers */
-	pic_mask = ~((~0u) << (11 - IRQ_PIC_START));
-	pic_mask |= (~((~0u) << (29 - 22))) << 22;
-	cic_mask = ~((~0u) << (1 + IRQ_CIC_END - IRQ_CIC_START));
-	sic_mask = ~((~0u) << (1 + IRQ_SIC_END - IRQ_SIC_START));
-
-	/*
-	 * Disable all interrupt sources
-	 */
-	writel(0xffffffff, INTCP_VA_PIC_BASE + IRQ_ENABLE_CLEAR);
-	writel(0xffffffff, INTCP_VA_PIC_BASE + FIQ_ENABLE_CLEAR);
-	writel(0xffffffff, INTCP_VA_CIC_BASE + IRQ_ENABLE_CLEAR);
-	writel(0xffffffff, INTCP_VA_CIC_BASE + FIQ_ENABLE_CLEAR);
-	writel(sic_mask, INTCP_VA_SIC_BASE + IRQ_ENABLE_CLEAR);
-	writel(sic_mask, INTCP_VA_SIC_BASE + FIQ_ENABLE_CLEAR);
-
-	fpga_irq_init(INTCP_VA_PIC_BASE, "PIC", IRQ_PIC_START,
-		      -1, pic_mask, NULL);
-
-	fpga_irq_init(INTCP_VA_CIC_BASE, "CIC", IRQ_CIC_START,
-		      -1, cic_mask, NULL);
-
-	fpga_irq_init(INTCP_VA_SIC_BASE, "SIC", IRQ_SIC_START,
-		      IRQ_CP_CPPLDINT, sic_mask, NULL);
-	integrator_clk_init(true);
-}
-
 /*
  * Flash handling.
  */
@@ -216,47 +181,6 @@ static struct physmap_flash_data intcp_flash_data = {
 	.set_vpp	= intcp_flash_set_vpp,
 };
 
-static struct resource intcp_flash_resource = {
-	.start		= INTCP_PA_FLASH_BASE,
-	.end		= INTCP_PA_FLASH_BASE + INTCP_FLASH_SIZE - 1,
-	.flags		= IORESOURCE_MEM,
-};
-
-static struct platform_device intcp_flash_device = {
-	.name		= "physmap-flash",
-	.id		= 0,
-	.dev		= {
-		.platform_data	= &intcp_flash_data,
-	},
-	.num_resources	= 1,
-	.resource	= &intcp_flash_resource,
-};
-
-static struct resource smc91x_resources[] = {
-	[0] = {
-		.start	= INTEGRATOR_CP_ETH_BASE,
-		.end	= INTEGRATOR_CP_ETH_BASE + INTCP_ETH_SIZE - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_CP_ETHINT,
-		.end	= IRQ_CP_ETHINT,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device smc91x_device = {
-	.name		= "smc91x",
-	.id		= 0,
-	.num_resources	= ARRAY_SIZE(smc91x_resources),
-	.resource	= smc91x_resources,
-};
-
-static struct platform_device *intcp_devs[] __initdata = {
-	&intcp_flash_device,
-	&smc91x_device,
-};
-
 /*
  * It seems that the card insertion interrupt remains active after
  * we've acknowledged it.  We therefore ignore the interrupt, and
@@ -265,8 +189,8 @@ static struct platform_device *intcp_devs[] __initdata = {
  */
 static unsigned int mmc_status(struct device *dev)
 {
-	unsigned int status = readl(IO_ADDRESS(0xca000000 + 4));
-	writel(8, IO_ADDRESS(INTEGRATOR_CP_CTL_BASE + 8));
+	unsigned int status = readl(__io_address(0xca000000 + 4));
+	writel(8, __io_address(INTEGRATOR_CP_CTL_BASE + 8));
 
 	return status & 8;
 }
@@ -278,16 +202,6 @@ static struct mmci_platform_data mmc_data = {
 	.gpio_cd	= -1,
 };
 
-#define INTEGRATOR_CP_MMC_IRQS	{ IRQ_CP_MMCIINT0, IRQ_CP_MMCIINT1 }
-#define INTEGRATOR_CP_AACI_IRQS	{ IRQ_CP_AACIINT }
-
-static AMBA_APB_DEVICE(mmc, "mmci", 0, INTEGRATOR_CP_MMC_BASE,
-	INTEGRATOR_CP_MMC_IRQS, &mmc_data);
-
-static AMBA_APB_DEVICE(aaci, "aaci", 0, INTEGRATOR_CP_AACI_BASE,
-	INTEGRATOR_CP_AACI_IRQS, NULL);
-
-
 /*
  * CLCD support
  */
@@ -338,15 +252,6 @@ static struct clcd_board clcd_data = {
 	.remove		= versatile_clcd_remove_dma,
 };
 
-static AMBA_AHB_DEVICE(clcd, "clcd", 0, INTCP_PA_CLCD_BASE,
-	{ IRQ_CP_CLCDCINT }, &clcd_data);
-
-static struct amba_device *amba_devs[] __initdata = {
-	&mmc_device,
-	&aaci_device,
-	&clcd_device,
-};
-
 #define REFCOUNTER (__io_address(INTEGRATOR_HDR_BASE) + 0x28)
 
 static void __init intcp_init_early(void)
@@ -356,16 +261,193 @@ static void __init intcp_init_early(void)
 #endif
 }
 
-static void __init intcp_init(void)
+static void __init intcp_timer_init_of(void)
 {
-	int i;
+	struct device_node *node;
+	const char *path;
+	void __iomem *base;
+	int err;
+	int irq;
+
+	err = of_property_read_string(of_aliases,
+				"arm,timer-primary", &path);
+	if (WARN_ON(err))
+		return;
+	node = of_find_node_by_path(path);
+	base = of_iomap(node, 0);
+	if (WARN_ON(!base))
+		return;
+	writel(0, base + TIMER_CTRL);
+	sp804_clocksource_init(base, node->name);
+
+	err = of_property_read_string(of_aliases,
+				"arm,timer-secondary", &path);
+	if (WARN_ON(err))
+		return;
+	node = of_find_node_by_path(path);
+	base = of_iomap(node, 0);
+	if (WARN_ON(!base))
+		return;
+	irq = irq_of_parse_and_map(node, 0);
+	writel(0, base + TIMER_CTRL);
+	sp804_clockevents_init(base, irq, node->name);
+}
 
-	platform_add_devices(intcp_devs, ARRAY_SIZE(intcp_devs));
+static struct sys_timer cp_of_timer = {
+	.init		= intcp_timer_init_of,
+};
 
-	for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
-		struct amba_device *d = amba_devs[i];
-		amba_device_register(d, &iomem_resource);
-	}
+#ifdef CONFIG_OF
+
+static const struct of_device_id fpga_irq_of_match[] __initconst = {
+	{ .compatible = "arm,versatile-fpga-irq", .data = fpga_irq_of_init, },
+	{ /* Sentinel */ }
+};
+
+static void __init intcp_init_irq_of(void)
+{
+	of_irq_init(fpga_irq_of_match);
+	integrator_clk_init(true);
+}
+
+/*
+ * For the Device Tree, add in the UART, MMC and CLCD specifics as AUXDATA
+ * and enforce the bus names since these are used for clock lookups.
+ */
+static struct of_dev_auxdata intcp_auxdata_lookup[] __initdata = {
+	OF_DEV_AUXDATA("arm,primecell", INTEGRATOR_RTC_BASE,
+		"rtc", NULL),
+	OF_DEV_AUXDATA("arm,primecell", INTEGRATOR_UART0_BASE,
+		"uart0", &integrator_uart_data),
+	OF_DEV_AUXDATA("arm,primecell", INTEGRATOR_UART1_BASE,
+		"uart1", &integrator_uart_data),
+	OF_DEV_AUXDATA("arm,primecell", KMI0_BASE,
+		"kmi0", NULL),
+	OF_DEV_AUXDATA("arm,primecell", KMI1_BASE,
+		"kmi1", NULL),
+	OF_DEV_AUXDATA("arm,primecell", INTEGRATOR_CP_MMC_BASE,
+		"mmci", &mmc_data),
+	OF_DEV_AUXDATA("arm,primecell", INTEGRATOR_CP_AACI_BASE,
+		"aaci", &mmc_data),
+	OF_DEV_AUXDATA("arm,primecell", INTCP_PA_CLCD_BASE,
+		"clcd", &clcd_data),
+	OF_DEV_AUXDATA("cfi-flash", INTCP_PA_FLASH_BASE,
+		"physmap-flash", &intcp_flash_data),
+	{ /* sentinel */ },
+};
+
+static void __init intcp_init_of(void)
+{
+	of_platform_populate(NULL, of_default_bus_match_table,
+			intcp_auxdata_lookup, NULL);
+}
+
+static const char * intcp_dt_board_compat[] = {
+	"arm,integrator-cp",
+	NULL,
+};
+
+DT_MACHINE_START(INTEGRATOR_CP_DT, "ARM Integrator/CP (Device Tree)")
+	.reserve	= integrator_reserve,
+	.map_io		= intcp_map_io,
+	.nr_irqs	= NR_IRQS_INTEGRATOR_CP,
+	.init_early	= intcp_init_early,
+	.init_irq	= intcp_init_irq_of,
+	.handle_irq	= fpga_handle_irq,
+	.timer		= &cp_of_timer,
+	.init_machine	= intcp_init_of,
+	.restart	= integrator_restart,
+	.dt_compat      = intcp_dt_board_compat,
+MACHINE_END
+
+#endif
+
+#ifdef CONFIG_ATAGS
+
+/*
+ * This is where non-devicetree initialization code is collected and stashed
+ * for eventual deletion.
+ */
+
+#define INTCP_FLASH_SIZE		SZ_32M
+
+static struct resource intcp_flash_resource = {
+	.start		= INTCP_PA_FLASH_BASE,
+	.end		= INTCP_PA_FLASH_BASE + INTCP_FLASH_SIZE - 1,
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device intcp_flash_device = {
+	.name		= "physmap-flash",
+	.id		= 0,
+	.dev		= {
+		.platform_data	= &intcp_flash_data,
+	},
+	.num_resources	= 1,
+	.resource	= &intcp_flash_resource,
+};
+
+#define INTCP_ETH_SIZE			0x10
+
+static struct resource smc91x_resources[] = {
+	[0] = {
+		.start	= INTEGRATOR_CP_ETH_BASE,
+		.end	= INTEGRATOR_CP_ETH_BASE + INTCP_ETH_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_CP_ETHINT,
+		.end	= IRQ_CP_ETHINT,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device smc91x_device = {
+	.name		= "smc91x",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(smc91x_resources),
+	.resource	= smc91x_resources,
+};
+
+static struct platform_device *intcp_devs[] __initdata = {
+	&intcp_flash_device,
+	&smc91x_device,
+};
+
+#define INTCP_VA_CIC_BASE		__io_address(INTEGRATOR_HDR_BASE + 0x40)
+#define INTCP_VA_PIC_BASE		__io_address(INTEGRATOR_IC_BASE)
+#define INTCP_VA_SIC_BASE		__io_address(INTEGRATOR_CP_SIC_BASE)
+
+static void __init intcp_init_irq(void)
+{
+	u32 pic_mask, cic_mask, sic_mask;
+
+	/* These masks are for the HW IRQ registers */
+	pic_mask = ~((~0u) << (11 - IRQ_PIC_START));
+	pic_mask |= (~((~0u) << (29 - 22))) << 22;
+	cic_mask = ~((~0u) << (1 + IRQ_CIC_END - IRQ_CIC_START));
+	sic_mask = ~((~0u) << (1 + IRQ_SIC_END - IRQ_SIC_START));
+
+	/*
+	 * Disable all interrupt sources
+	 */
+	writel(0xffffffff, INTCP_VA_PIC_BASE + IRQ_ENABLE_CLEAR);
+	writel(0xffffffff, INTCP_VA_PIC_BASE + FIQ_ENABLE_CLEAR);
+	writel(0xffffffff, INTCP_VA_CIC_BASE + IRQ_ENABLE_CLEAR);
+	writel(0xffffffff, INTCP_VA_CIC_BASE + FIQ_ENABLE_CLEAR);
+	writel(sic_mask, INTCP_VA_SIC_BASE + IRQ_ENABLE_CLEAR);
+	writel(sic_mask, INTCP_VA_SIC_BASE + FIQ_ENABLE_CLEAR);
+
+	fpga_irq_init(INTCP_VA_PIC_BASE, "PIC", IRQ_PIC_START,
+		      -1, pic_mask, NULL);
+
+	fpga_irq_init(INTCP_VA_CIC_BASE, "CIC", IRQ_CIC_START,
+		      -1, cic_mask, NULL);
+
+	fpga_irq_init(INTCP_VA_SIC_BASE, "SIC", IRQ_SIC_START,
+		      IRQ_CP_CPPLDINT, sic_mask, NULL);
+
+	integrator_clk_init(true);
 }
 
 #define TIMER0_VA_BASE __io_address(INTEGRATOR_TIMER0_BASE)
@@ -386,6 +468,37 @@ static struct sys_timer cp_timer = {
 	.init		= intcp_timer_init,
 };
 
+#define INTEGRATOR_CP_MMC_IRQS	{ IRQ_CP_MMCIINT0, IRQ_CP_MMCIINT1 }
+#define INTEGRATOR_CP_AACI_IRQS	{ IRQ_CP_AACIINT }
+
+static AMBA_APB_DEVICE(mmc, "mmci", 0, INTEGRATOR_CP_MMC_BASE,
+	INTEGRATOR_CP_MMC_IRQS, &mmc_data);
+
+static AMBA_APB_DEVICE(aaci, "aaci", 0, INTEGRATOR_CP_AACI_BASE,
+	INTEGRATOR_CP_AACI_IRQS, NULL);
+
+static AMBA_AHB_DEVICE(clcd, "clcd", 0, INTCP_PA_CLCD_BASE,
+	{ IRQ_CP_CLCDCINT }, &clcd_data);
+
+static struct amba_device *amba_devs[] __initdata = {
+	&mmc_device,
+	&aaci_device,
+	&clcd_device,
+};
+
+static void __init intcp_init(void)
+{
+	int i;
+
+	platform_add_devices(intcp_devs, ARRAY_SIZE(intcp_devs));
+
+	for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
+		struct amba_device *d = amba_devs[i];
+		amba_device_register(d, &iomem_resource);
+	}
+	integrator_init(true);
+}
+
 MACHINE_START(CINTEGRATOR, "ARM-IntegratorCP")
 	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
 	.atag_offset	= 0x100,
@@ -399,3 +512,5 @@ MACHINE_START(CINTEGRATOR, "ARM-IntegratorCP")
 	.init_machine	= intcp_init,
 	.restart	= integrator_restart,
 MACHINE_END
+
+#endif
diff --git a/arch/arm/mach-integrator/leds.c b/arch/arm/mach-integrator/leds.c
index 466defa..7a7f6d3 100644
--- a/arch/arm/mach-integrator/leds.c
+++ b/arch/arm/mach-integrator/leds.c
@@ -1,90 +1,125 @@
 /*
- *  linux/arch/arm/mach-integrator/leds.c
+ * Driver for the 4 user LEDs found on the Integrator AP/CP baseboard
+ * Based on Versatile and RealView machine LED code
  *
- *  Integrator/AP and Integrator/CP LED control routines
- *
- *  Copyright (C) 1999 ARM Limited
- *  Copyright (C) 2000 Deep Blue Solutions Ltd
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * License terms: GNU General Public License (GPL) version 2
+ * Author: Bryan Wu <bryan.wu@canonical.com>
  */
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/smp.h>
-#include <linux/spinlock.h>
 #include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/leds.h>
 
+#include <mach/cm.h>
 #include <mach/hardware.h>
 #include <mach/platform.h>
-#include <asm/leds.h>
-#include <asm/mach-types.h>
-#include <mach/cm.h>
 
-static int saved_leds;
+#if defined(CONFIG_NEW_LEDS) && defined(CONFIG_LEDS_CLASS)
+
+#define ALPHA_REG __io_address(INTEGRATOR_DBG_BASE)
+#define LEDREG	(__io_address(INTEGRATOR_DBG_BASE) + INTEGRATOR_DBG_LEDS_OFFSET)
 
-static void integrator_leds_event(led_event_t ledevt)
+struct integrator_led {
+	struct led_classdev	cdev;
+	u8			mask;
+};
+
+/*
+ * The triggers lines up below will only be used if the
+ * LED triggers are compiled in.
+ */
+static const struct {
+	const char *name;
+	const char *trigger;
+} integrator_leds[] = {
+	{ "integrator:green0", "heartbeat", },
+	{ "integrator:yellow", },
+	{ "integrator:red", },
+	{ "integrator:green1", },
+	{ "integrator:core_module", "cpu0", },
+};
+
+static void integrator_led_set(struct led_classdev *cdev,
+			      enum led_brightness b)
 {
-	unsigned long flags;
-	const unsigned int dbg_base = IO_ADDRESS(INTEGRATOR_DBG_BASE);
-	unsigned int update_alpha_leds;
+	struct integrator_led *led = container_of(cdev,
+						 struct integrator_led, cdev);
+	u32 reg = __raw_readl(LEDREG);
 
-	// yup, change the LEDs
-	local_irq_save(flags);
-	update_alpha_leds = 0;
+	if (b != LED_OFF)
+		reg |= led->mask;
+	else
+		reg &= ~led->mask;
 
-	switch(ledevt) {
-	case led_idle_start:
-		cm_control(CM_CTRL_LED, 0);
-		break;
+	while (__raw_readl(ALPHA_REG) & 1)
+		cpu_relax();
 
-	case led_idle_end:
-		cm_control(CM_CTRL_LED, CM_CTRL_LED);
-		break;
+	__raw_writel(reg, LEDREG);
+}
 
-	case led_timer:
-		saved_leds ^= GREEN_LED;
-		update_alpha_leds = 1;
-		break;
+static enum led_brightness integrator_led_get(struct led_classdev *cdev)
+{
+	struct integrator_led *led = container_of(cdev,
+						 struct integrator_led, cdev);
+	u32 reg = __raw_readl(LEDREG);
 
-	case led_red_on:
-		saved_leds |= RED_LED;
-		update_alpha_leds = 1;
-		break;
+	return (reg & led->mask) ? LED_FULL : LED_OFF;
+}
 
-	case led_red_off:
-		saved_leds &= ~RED_LED;
-		update_alpha_leds = 1;
-		break;
+static void cm_led_set(struct led_classdev *cdev,
+			      enum led_brightness b)
+{
+	if (b != LED_OFF)
+		cm_control(CM_CTRL_LED, CM_CTRL_LED);
+	else
+		cm_control(CM_CTRL_LED, 0);
+}
 
-	default:
-		break;
-	}
+static enum led_brightness cm_led_get(struct led_classdev *cdev)
+{
+	u32 reg = readl(CM_CTRL);
 
-	if (update_alpha_leds) {
-		while (__raw_readl(dbg_base + INTEGRATOR_DBG_ALPHA_OFFSET) & 1);
-		__raw_writel(saved_leds, dbg_base + INTEGRATOR_DBG_LEDS_OFFSET);
-	}
-	local_irq_restore(flags);
+	return (reg & CM_CTRL_LED) ? LED_FULL : LED_OFF;
 }
 
-static int __init leds_init(void)
+static int __init integrator_leds_init(void)
 {
-	if (machine_is_integrator() || machine_is_cintegrator())
-		leds_event = integrator_leds_event;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(integrator_leds); i++) {
+		struct integrator_led *led;
+
+		led = kzalloc(sizeof(*led), GFP_KERNEL);
+		if (!led)
+			break;
+
+
+		led->cdev.name = integrator_leds[i].name;
+
+		if (i == 4) { /* Setting for LED in core module */
+			led->cdev.brightness_set = cm_led_set;
+			led->cdev.brightness_get = cm_led_get;
+		} else {
+			led->cdev.brightness_set = integrator_led_set;
+			led->cdev.brightness_get = integrator_led_get;
+		}
+
+		led->cdev.default_trigger = integrator_leds[i].trigger;
+		led->mask = BIT(i);
+
+		if (led_classdev_register(NULL, &led->cdev) < 0) {
+			kfree(led);
+			break;
+		}
+	}
 
 	return 0;
 }
 
-core_initcall(leds_init);
+/*
+ * Since we may have triggers on any subsystem, defer registration
+ * until after subsystem_init.
+ */
+fs_initcall(integrator_leds_init);
+#endif
diff --git a/arch/arm/mach-integrator/pci_v3.c b/arch/arm/mach-integrator/pci_v3.c
index b866880..bbeca59 100644
--- a/arch/arm/mach-integrator/pci_v3.c
+++ b/arch/arm/mach-integrator/pci_v3.c
@@ -41,61 +41,61 @@
 /*
  * The V3 PCI interface chip in Integrator provides several windows from
  * local bus memory into the PCI memory areas.   Unfortunately, there
- * are not really enough windows for our usage, therefore we reuse 
+ * are not really enough windows for our usage, therefore we reuse
  * one of the windows for access to PCI configuration space.  The
  * memory map is as follows:
- * 
+ *
  * Local Bus Memory         Usage
- * 
+ *
  * 40000000 - 4FFFFFFF      PCI memory.  256M non-prefetchable
  * 50000000 - 5FFFFFFF      PCI memory.  256M prefetchable
  * 60000000 - 60FFFFFF      PCI IO.  16M
  * 61000000 - 61FFFFFF      PCI Configuration. 16M
- * 
+ *
  * There are three V3 windows, each described by a pair of V3 registers.
  * These are LB_BASE0/LB_MAP0, LB_BASE1/LB_MAP1 and LB_BASE2/LB_MAP2.
  * Base0 and Base1 can be used for any type of PCI memory access.   Base2
  * can be used either for PCI I/O or for I20 accesses.  By default, uHAL
  * uses this only for PCI IO space.
- * 
+ *
  * Normally these spaces are mapped using the following base registers:
- * 
+ *
  * Usage Local Bus Memory         Base/Map registers used
- * 
+ *
  * Mem   40000000 - 4FFFFFFF      LB_BASE0/LB_MAP0
  * Mem   50000000 - 5FFFFFFF      LB_BASE1/LB_MAP1
  * IO    60000000 - 60FFFFFF      LB_BASE2/LB_MAP2
  * Cfg   61000000 - 61FFFFFF
- * 
+ *
  * This means that I20 and PCI configuration space accesses will fail.
- * When PCI configuration accesses are needed (via the uHAL PCI 
+ * When PCI configuration accesses are needed (via the uHAL PCI
  * configuration space primitives) we must remap the spaces as follows:
- * 
+ *
  * Usage Local Bus Memory         Base/Map registers used
- * 
+ *
  * Mem   40000000 - 4FFFFFFF      LB_BASE0/LB_MAP0
  * Mem   50000000 - 5FFFFFFF      LB_BASE0/LB_MAP0
  * IO    60000000 - 60FFFFFF      LB_BASE2/LB_MAP2
  * Cfg   61000000 - 61FFFFFF      LB_BASE1/LB_MAP1
- * 
+ *
  * To make this work, the code depends on overlapping windows working.
- * The V3 chip translates an address by checking its range within 
+ * The V3 chip translates an address by checking its range within
  * each of the BASE/MAP pairs in turn (in ascending register number
  * order).  It will use the first matching pair.   So, for example,
  * if the same address is mapped by both LB_BASE0/LB_MAP0 and
- * LB_BASE1/LB_MAP1, the V3 will use the translation from 
+ * LB_BASE1/LB_MAP1, the V3 will use the translation from
  * LB_BASE0/LB_MAP0.
- * 
+ *
  * To allow PCI Configuration space access, the code enlarges the
  * window mapped by LB_BASE0/LB_MAP0 from 256M to 512M.  This occludes
  * the windows currently mapped by LB_BASE1/LB_MAP1 so that it can
  * be remapped for use by configuration cycles.
- * 
- * At the end of the PCI Configuration space accesses, 
+ *
+ * At the end of the PCI Configuration space accesses,
  * LB_BASE1/LB_MAP1 is reset to map PCI Memory.  Finally the window
  * mapped by LB_BASE0/LB_MAP0 is reduced in size from 512M to 256M to
  * reveal the now restored LB_BASE1/LB_MAP1 window.
- * 
+ *
  * NOTE: We do not set up I2O mapping.  I suspect that this is only
  * for an intelligent (target) device.  Using I2O disables most of
  * the mappings into PCI memory.
@@ -127,8 +127,8 @@
  *
  * returns:	configuration address to play on the PCI bus
  *
- * To generate the appropriate PCI configuration cycles in the PCI 
- * configuration address space, you present the V3 with the following pattern 
+ * To generate the appropriate PCI configuration cycles in the PCI
+ * configuration address space, you present the V3 with the following pattern
  * (which is very nearly a type 1 (except that the lower two bits are 00 and
  * not 01).   In order for this mapping to work you need to set up one of
  * the local to PCI aperatures to 16Mbytes in length translating to
@@ -138,7 +138,7 @@
  *
  * Type 0:
  *
- *  3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1 
+ *  3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1
  *  3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0
  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  * | | |D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|0|
@@ -150,7 +150,7 @@
  *
  * Type 1:
  *
- *  3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1 
+ *  3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1
  *  3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0
  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  * | | | | | | | | | | |B|B|B|B|B|B|B|B|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|1|
@@ -161,7 +161,7 @@
  *	15:11	Device number (5 bits)
  *	10:8	function number
  *	 7:2	register number
- *  
+ *
  */
 static DEFINE_RAW_SPINLOCK(v3_lock);
 
@@ -181,7 +181,7 @@ static DEFINE_RAW_SPINLOCK(v3_lock);
 #undef V3_LB_BASE_PREFETCH
 #define V3_LB_BASE_PREFETCH 0
 
-static unsigned long v3_open_config_window(struct pci_bus *bus,
+static void __iomem *v3_open_config_window(struct pci_bus *bus,
 					   unsigned int devfn, int offset)
 {
 	unsigned int address, mapaddress, busnr;
@@ -280,7 +280,7 @@ static void v3_close_config_window(void)
 static int v3_read_config(struct pci_bus *bus, unsigned int devfn, int where,
 			  int size, u32 *val)
 {
-	unsigned long addr;
+	void __iomem *addr;
 	unsigned long flags;
 	u32 v;
 
@@ -311,7 +311,7 @@ static int v3_read_config(struct pci_bus *bus, unsigned int devfn, int where,
 static int v3_write_config(struct pci_bus *bus, unsigned int devfn, int where,
 			   int size, u32 val)
 {
-	unsigned long addr;
+	void __iomem *addr;
 	unsigned long flags;
 
 	raw_spin_lock_irqsave(&v3_lock, flags);
@@ -374,12 +374,9 @@ static int __init pci_v3_setup_resources(struct pci_sys_data *sys)
 	}
 
 	/*
-	 * the IO resource for this bus
 	 * the mem resource for this bus
 	 * the prefetch mem resource for this bus
 	 */
-	pci_add_resource_offset(&sys->resources,
-				&ioport_resource, sys->io_offset);
 	pci_add_resource_offset(&sys->resources, &non_mem, sys->mem_offset);
 	pci_add_resource_offset(&sys->resources, &pre_mem, sys->mem_offset);
 
@@ -391,9 +388,9 @@ static int __init pci_v3_setup_resources(struct pci_sys_data *sys)
  * means I can't get additional information on the reason for the pm2fb
  * problems.  I suppose I'll just have to mind-meld with the machine. ;)
  */
-#define SC_PCI     IO_ADDRESS(INTEGRATOR_SC_PCIENABLE)
-#define SC_LBFADDR IO_ADDRESS(INTEGRATOR_SC_BASE + 0x20)
-#define SC_LBFCODE IO_ADDRESS(INTEGRATOR_SC_BASE + 0x24)
+#define SC_PCI     __io_address(INTEGRATOR_SC_PCIENABLE)
+#define SC_LBFADDR __io_address(INTEGRATOR_SC_BASE + 0x20)
+#define SC_LBFCODE __io_address(INTEGRATOR_SC_BASE + 0x24)
 
 static int
 v3_pci_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
@@ -498,7 +495,6 @@ void __init pci_v3_preinit(void)
 	unsigned int temp;
 	int ret;
 
-	pcibios_min_io = 0x6000;
 	pcibios_min_mem = 0x00100000;
 
 	/*
diff --git a/arch/arm/mach-iop13xx/include/mach/io.h b/arch/arm/mach-iop13xx/include/mach/io.h
deleted file mode 100644
index f131885..0000000
--- a/arch/arm/mach-iop13xx/include/mach/io.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * iop13xx custom ioremap implementation
- * Copyright (c) 2005-2006, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- */
-#ifndef __ASM_ARM_ARCH_IO_H
-#define __ASM_ARM_ARCH_IO_H
-
-#define IO_SPACE_LIMIT 0xffffffff
-
-#define __io(a) __iop13xx_io(a)
-
-extern void __iomem * __iop13xx_io(unsigned long io_addr);
-
-#endif
diff --git a/arch/arm/mach-iop13xx/include/mach/iop13xx.h b/arch/arm/mach-iop13xx/include/mach/iop13xx.h
index e190dcd..7480f58 100644
--- a/arch/arm/mach-iop13xx/include/mach/iop13xx.h
+++ b/arch/arm/mach-iop13xx/include/mach/iop13xx.h
@@ -69,21 +69,11 @@ extern unsigned long get_iop_tick_rate(void);
  * 0x8000.0000 + 928M	0x2.8000.0000   (ioremap)	PCIE outbound memory window
  *
  * IO MAP
- * 0x1000 + 64K	0x0.fffb.1000	0xfec6.1000	PCIX outbound i/o window
- * 0x1000 + 64K	0x0.fffd.1000	0xfed7.1000	PCIE outbound i/o window
+ * 0x00000 + 64K	0x0.fffb.0000	0xfee0.0000	PCIX outbound i/o window
+ * 0x10000 + 64K	0x0.fffd.0000	0xfee1.0000	PCIE outbound i/o window
  */
-#define IOP13XX_PCIX_IO_WINDOW_SIZE   0x10000UL
 #define IOP13XX_PCIX_LOWER_IO_PA      0xfffb0000UL
-#define IOP13XX_PCIX_LOWER_IO_VA      0xfec60000UL
 #define IOP13XX_PCIX_LOWER_IO_BA      0x0UL /* OIOTVR */
-#define IOP13XX_PCIX_IO_BUS_OFFSET    0x1000UL
-#define IOP13XX_PCIX_UPPER_IO_PA      (IOP13XX_PCIX_LOWER_IO_PA +\
-				       IOP13XX_PCIX_IO_WINDOW_SIZE - 1)
-#define IOP13XX_PCIX_UPPER_IO_VA      (IOP13XX_PCIX_LOWER_IO_VA +\
-				       IOP13XX_PCIX_IO_WINDOW_SIZE - 1)
-#define IOP13XX_PCIX_IO_PHYS_TO_VIRT(addr) (u32) ((u32) addr -\
-					   (IOP13XX_PCIX_LOWER_IO_PA\
-					   - IOP13XX_PCIX_LOWER_IO_VA))
 
 #define IOP13XX_PCIX_MEM_PHYS_OFFSET  0x100000000ULL
 #define IOP13XX_PCIX_MEM_WINDOW_SIZE  0x3a000000UL
@@ -103,20 +93,8 @@ extern unsigned long get_iop_tick_rate(void);
 					IOP13XX_PCIX_LOWER_MEM_BA)
 
 /* PCI-E ranges */
-#define IOP13XX_PCIE_IO_WINDOW_SIZE   	 0x10000UL
 #define IOP13XX_PCIE_LOWER_IO_PA      	 0xfffd0000UL
-#define IOP13XX_PCIE_LOWER_IO_VA      	 0xfed70000UL
-#define IOP13XX_PCIE_LOWER_IO_BA      	 0x0UL  /* OIOTVR */
-#define IOP13XX_PCIE_IO_BUS_OFFSET	 0x1000UL
-#define IOP13XX_PCIE_UPPER_IO_PA      	 (IOP13XX_PCIE_LOWER_IO_PA +\
-					 IOP13XX_PCIE_IO_WINDOW_SIZE - 1)
-#define IOP13XX_PCIE_UPPER_IO_VA      	 (IOP13XX_PCIE_LOWER_IO_VA +\
-					 IOP13XX_PCIE_IO_WINDOW_SIZE - 1)
-#define IOP13XX_PCIE_UPPER_IO_BA      	 (IOP13XX_PCIE_LOWER_IO_BA +\
-					 IOP13XX_PCIE_IO_WINDOW_SIZE - 1)
-#define IOP13XX_PCIE_IO_PHYS_TO_VIRT(addr) (u32) ((u32) addr -\
-					   (IOP13XX_PCIE_LOWER_IO_PA\
-					   - IOP13XX_PCIE_LOWER_IO_VA))
+#define IOP13XX_PCIE_LOWER_IO_BA	 0x10000UL  /* OIOTVR */
 
 #define IOP13XX_PCIE_MEM_PHYS_OFFSET  	 0x200000000ULL
 #define IOP13XX_PCIE_MEM_WINDOW_SIZE  	 0x3a000000UL
@@ -148,18 +126,16 @@ extern unsigned long get_iop_tick_rate(void);
  * IOP13XX chipset registers
  */
 #define IOP13XX_PMMR_PHYS_MEM_BASE	   0xffd80000UL  /* PMMR phys. address */
-#define IOP13XX_PMMR_VIRT_MEM_BASE	   0xfee80000UL  /* PMMR phys. address */
+#define IOP13XX_PMMR_VIRT_MEM_BASE	   (void __iomem *)(0xfee80000UL)  /* PMMR phys. address */
 #define IOP13XX_PMMR_MEM_WINDOW_SIZE	   0x80000
 #define IOP13XX_PMMR_UPPER_MEM_VA	   (IOP13XX_PMMR_VIRT_MEM_BASE +\
 					   IOP13XX_PMMR_MEM_WINDOW_SIZE - 1)
 #define IOP13XX_PMMR_UPPER_MEM_PA	   (IOP13XX_PMMR_PHYS_MEM_BASE +\
 					   IOP13XX_PMMR_MEM_WINDOW_SIZE - 1)
-#define IOP13XX_PMMR_VIRT_TO_PHYS(addr)   (u32) ((u32) addr +\
-					   (IOP13XX_PMMR_PHYS_MEM_BASE\
-					   - IOP13XX_PMMR_VIRT_MEM_BASE))
-#define IOP13XX_PMMR_PHYS_TO_VIRT(addr)   (u32) ((u32) addr -\
-					   (IOP13XX_PMMR_PHYS_MEM_BASE\
-					   - IOP13XX_PMMR_VIRT_MEM_BASE))
+#define IOP13XX_PMMR_VIRT_TO_PHYS(addr)   (((addr) - IOP13XX_PMMR_VIRT_MEM_BASE)\
+					   + IOP13XX_PMMR_PHYS_MEM_BASE)
+#define IOP13XX_PMMR_PHYS_TO_VIRT(addr)   (((addr) - IOP13XX_PMMR_PHYS_MEM_BASE)\
+					   + IOP13XX_PMMR_VIRT_MEM_BASE)
 #define IOP13XX_REG_ADDR32(reg)     	   (IOP13XX_PMMR_VIRT_MEM_BASE + (reg))
 #define IOP13XX_REG_ADDR16(reg)     	   (IOP13XX_PMMR_VIRT_MEM_BASE + (reg))
 #define IOP13XX_REG_ADDR8(reg)      	   (IOP13XX_PMMR_VIRT_MEM_BASE + (reg))
@@ -169,10 +145,10 @@ extern unsigned long get_iop_tick_rate(void);
 #define IOP13XX_PMMR_SIZE		   0x00080000
 
 /*=================== Defines for Platform Devices =====================*/
-#define IOP13XX_UART0_PHYS  (IOP13XX_PMMR_PHYS_MEM_BASE | 0x00002300)
-#define IOP13XX_UART1_PHYS  (IOP13XX_PMMR_PHYS_MEM_BASE | 0x00002340)
-#define IOP13XX_UART0_VIRT  (IOP13XX_PMMR_VIRT_MEM_BASE | 0x00002300)
-#define IOP13XX_UART1_VIRT  (IOP13XX_PMMR_VIRT_MEM_BASE | 0x00002340)
+#define IOP13XX_UART0_PHYS  (IOP13XX_PMMR_PHYS_MEM_BASE + 0x00002300)
+#define IOP13XX_UART1_PHYS  (IOP13XX_PMMR_PHYS_MEM_BASE + 0x00002340)
+#define IOP13XX_UART0_VIRT  (IOP13XX_PMMR_VIRT_MEM_BASE + 0x00002300)
+#define IOP13XX_UART1_VIRT  (IOP13XX_PMMR_VIRT_MEM_BASE + 0x00002340)
 
 #define IOP13XX_I2C0_PHYS   (IOP13XX_PMMR_PHYS_MEM_BASE | 0x00002500)
 #define IOP13XX_I2C1_PHYS   (IOP13XX_PMMR_PHYS_MEM_BASE | 0x00002520)
diff --git a/arch/arm/mach-iop13xx/include/mach/memory.h b/arch/arm/mach-iop13xx/include/mach/memory.h
index 1afa99e..7c032d0 100644
--- a/arch/arm/mach-iop13xx/include/mach/memory.h
+++ b/arch/arm/mach-iop13xx/include/mach/memory.h
@@ -16,12 +16,12 @@
 #define IOP13XX_PMMR_P_START (IOP13XX_PMMR_PHYS_MEM_BASE)
 #define IOP13XX_PMMR_P_END   (IOP13XX_PMMR_PHYS_MEM_BASE + IOP13XX_PMMR_SIZE)
 
-static inline dma_addr_t __virt_to_lbus(unsigned long x)
+static inline dma_addr_t __virt_to_lbus(void __iomem *x)
 {
 	return x + IOP13XX_PMMR_PHYS_MEM_BASE - IOP13XX_PMMR_VIRT_MEM_BASE;
 }
 
-static inline unsigned long __lbus_to_virt(dma_addr_t x)
+static inline void __iomem *__lbus_to_virt(dma_addr_t x)
 {
 	return x + IOP13XX_PMMR_VIRT_MEM_BASE - IOP13XX_PMMR_PHYS_MEM_BASE;
 }
@@ -38,23 +38,23 @@ static inline unsigned long __lbus_to_virt(dma_addr_t x)
 
 #define __arch_dma_to_virt(dev, addr)					\
 	({								\
-		unsigned long __virt;					\
+		void * __virt;						\
 		dma_addr_t __dma = addr;				\
 		if (is_lbus_device(dev) && __is_lbus_dma(__dma))	\
 			__virt = __lbus_to_virt(__dma);			\
 		else							\
-			__virt = __phys_to_virt(__dma);			\
-		(void *)__virt;						\
+			__virt = (void *)__phys_to_virt(__dma);		\
+		__virt;							\
 	})
 
 #define __arch_virt_to_dma(dev, addr)					\
 	({								\
-		unsigned long __virt = (unsigned long)addr;		\
+		void * __virt = addr;					\
 		dma_addr_t __dma;					\
 		if (is_lbus_device(dev) && __is_lbus_virt(__virt))	\
 			__dma = __virt_to_lbus(__virt);			\
 		else							\
-			__dma = __virt_to_phys(__virt);			\
+			__dma = __virt_to_phys((unsigned long)__virt);	\
 		__dma;							\
 	})
 
diff --git a/arch/arm/mach-iop13xx/io.c b/arch/arm/mach-iop13xx/io.c
index 3c36419..183dc8b 100644
--- a/arch/arm/mach-iop13xx/io.c
+++ b/arch/arm/mach-iop13xx/io.c
@@ -23,25 +23,6 @@
 
 #include "pci.h"
 
-void * __iomem __iop13xx_io(unsigned long io_addr)
-{
-	void __iomem * io_virt;
-
-	switch (io_addr) {
-	case IOP13XX_PCIE_LOWER_IO_PA ... IOP13XX_PCIE_UPPER_IO_PA:
-		io_virt = (void *) IOP13XX_PCIE_IO_PHYS_TO_VIRT(io_addr);
-		break;
-	case IOP13XX_PCIX_LOWER_IO_PA ... IOP13XX_PCIX_UPPER_IO_PA:
-		io_virt = (void *) IOP13XX_PCIX_IO_PHYS_TO_VIRT(io_addr);
-		break;
-	default:
-		BUG();
-	}
-
-	return io_virt;
-}
-EXPORT_SYMBOL(__iop13xx_io);
-
 static void __iomem *__iop13xx_ioremap_caller(unsigned long cookie,
 	size_t size, unsigned int mtype, void *caller)
 {
@@ -52,14 +33,14 @@ static void __iomem *__iop13xx_ioremap_caller(unsigned long cookie,
 		if (unlikely(!iop13xx_atux_mem_base))
 			retval = NULL;
 		else
-			retval = (void *)(iop13xx_atux_mem_base +
+			retval = (iop13xx_atux_mem_base +
 			         (cookie - IOP13XX_PCIX_LOWER_MEM_RA));
 		break;
 	case IOP13XX_PCIE_LOWER_MEM_RA ... IOP13XX_PCIE_UPPER_MEM_RA:
 		if (unlikely(!iop13xx_atue_mem_base))
 			retval = NULL;
 		else
-			retval = (void *)(iop13xx_atue_mem_base +
+			retval = (iop13xx_atue_mem_base +
 			         (cookie - IOP13XX_PCIE_LOWER_MEM_RA));
 		break;
 	case IOP13XX_PBI_LOWER_MEM_RA ... IOP13XX_PBI_UPPER_MEM_RA:
@@ -67,14 +48,8 @@ static void __iomem *__iop13xx_ioremap_caller(unsigned long cookie,
 				       (cookie - IOP13XX_PBI_LOWER_MEM_RA),
 				       size, mtype, __builtin_return_address(0));
 		break;
-	case IOP13XX_PCIE_LOWER_IO_PA ... IOP13XX_PCIE_UPPER_IO_PA:
-		retval = (void *) IOP13XX_PCIE_IO_PHYS_TO_VIRT(cookie);
-		break;
-	case IOP13XX_PCIX_LOWER_IO_PA ... IOP13XX_PCIX_UPPER_IO_PA:
-		retval = (void *) IOP13XX_PCIX_IO_PHYS_TO_VIRT(cookie);
-		break;
 	case IOP13XX_PMMR_PHYS_MEM_BASE ... IOP13XX_PMMR_UPPER_MEM_PA:
-		retval = (void *) IOP13XX_PMMR_PHYS_TO_VIRT(cookie);
+		retval = IOP13XX_PMMR_PHYS_TO_VIRT(cookie);
 		break;
 	default:
 		retval = __arm_ioremap_caller(cookie, size, mtype,
@@ -99,9 +74,7 @@ static void __iop13xx_iounmap(volatile void __iomem *addr)
 		    goto skip;
 
 	switch ((u32) addr) {
-	case IOP13XX_PCIE_LOWER_IO_VA ... IOP13XX_PCIE_UPPER_IO_VA:
-	case IOP13XX_PCIX_LOWER_IO_VA ... IOP13XX_PCIX_UPPER_IO_VA:
-	case IOP13XX_PMMR_VIRT_MEM_BASE ... IOP13XX_PMMR_UPPER_MEM_VA:
+	case (u32)IOP13XX_PMMR_VIRT_MEM_BASE ... (u32)IOP13XX_PMMR_UPPER_MEM_VA:
 		goto skip;
 	}
 	__iounmap(addr);
diff --git a/arch/arm/mach-iop13xx/pci.c b/arch/arm/mach-iop13xx/pci.c
index 861cb12..9082b84 100644
--- a/arch/arm/mach-iop13xx/pci.c
+++ b/arch/arm/mach-iop13xx/pci.c
@@ -36,8 +36,8 @@ u32 iop13xx_atux_pmmr_offset; /* This offset can change based on strapping */
 u32 iop13xx_atue_pmmr_offset; /* This offset can change based on strapping */
 static struct pci_bus *pci_bus_atux = 0;
 static struct pci_bus *pci_bus_atue = 0;
-u32 iop13xx_atue_mem_base;
-u32 iop13xx_atux_mem_base;
+void __iomem *iop13xx_atue_mem_base;
+void __iomem *iop13xx_atux_mem_base;
 size_t iop13xx_atue_mem_size;
 size_t iop13xx_atux_mem_size;
 
@@ -88,8 +88,7 @@ void iop13xx_map_pci_memory(void)
 				}
 
 				if (end) {
-					iop13xx_atux_mem_base =
-					(u32) __arm_ioremap_pfn(
+					iop13xx_atux_mem_base = __arm_ioremap_pfn(
 					__phys_to_pfn(IOP13XX_PCIX_LOWER_MEM_PA)
 					, 0, iop13xx_atux_mem_size, MT_DEVICE);
 					if (!iop13xx_atux_mem_base) {
@@ -99,7 +98,7 @@ void iop13xx_map_pci_memory(void)
 					}
 				} else
 					iop13xx_atux_mem_size = 0;
-				PRINTK("%s: atu: %d bus_size: %d mem_base: %x\n",
+				PRINTK("%s: atu: %d bus_size: %d mem_base: %p\n",
 				__func__, atu, iop13xx_atux_mem_size,
 				iop13xx_atux_mem_base);
 				break;
@@ -114,8 +113,7 @@ void iop13xx_map_pci_memory(void)
 				}
 
 				if (end) {
-					iop13xx_atue_mem_base =
-					(u32) __arm_ioremap_pfn(
+					iop13xx_atue_mem_base = __arm_ioremap_pfn(
 					__phys_to_pfn(IOP13XX_PCIE_LOWER_MEM_PA)
 					, 0, iop13xx_atue_mem_size, MT_DEVICE);
 					if (!iop13xx_atue_mem_base) {
@@ -125,13 +123,13 @@ void iop13xx_map_pci_memory(void)
 					}
 				} else
 					iop13xx_atue_mem_size = 0;
-				PRINTK("%s: atu: %d bus_size: %d mem_base: %x\n",
+				PRINTK("%s: atu: %d bus_size: %d mem_base: %p\n",
 				__func__, atu, iop13xx_atue_mem_size,
 				iop13xx_atue_mem_base);
 				break;
 			}
 
-			printk("%s: Initialized (%uM @ resource/virtual: %08lx/%08x)\n",
+			printk("%s: Initialized (%uM @ resource/virtual: %08lx/%p)\n",
 			atu ? "ATUE" : "ATUX",
 			(atu ? iop13xx_atue_mem_size : iop13xx_atux_mem_size) /
 			SZ_1M,
@@ -970,7 +968,6 @@ void __init iop13xx_pci_init(void)
 	__raw_writel(__raw_readl(IOP13XX_XBG_BECSR) & 3, IOP13XX_XBG_BECSR);
 
 	/* Setup the Min Address for PCI memory... */
-	pcibios_min_io = 0;
 	pcibios_min_mem = IOP13XX_PCIX_LOWER_MEM_BA;
 
 	/* if Linux is given control of an ATU
@@ -1003,7 +1000,7 @@ int iop13xx_pci_setup(int nr, struct pci_sys_data *sys)
 	if (nr > 1)
 		return 0;
 
-	res = kcalloc(2, sizeof(struct resource), GFP_KERNEL);
+	res = kzalloc(sizeof(struct resource), GFP_KERNEL);
 	if (!res)
 		panic("PCI: unable to alloc resources");
 
@@ -1042,17 +1039,13 @@ int iop13xx_pci_setup(int nr, struct pci_sys_data *sys)
 				  << IOP13XX_ATUX_PCIXSR_FUNC_NUM;
 		__raw_writel(pcixsr, IOP13XX_ATUX_PCIXSR);
 
-		res[0].start = IOP13XX_PCIX_LOWER_IO_PA + IOP13XX_PCIX_IO_BUS_OFFSET;
-		res[0].end   = IOP13XX_PCIX_UPPER_IO_PA;
-		res[0].name  = "IQ81340 ATUX PCI I/O Space";
-		res[0].flags = IORESOURCE_IO;
+		pci_ioremap_io(0, IOP13XX_PCIX_LOWER_IO_PA);
 
-		res[1].start = IOP13XX_PCIX_LOWER_MEM_RA;
-		res[1].end   = IOP13XX_PCIX_UPPER_MEM_RA;
-		res[1].name  = "IQ81340 ATUX PCI Memory Space";
-		res[1].flags = IORESOURCE_MEM;
+		res->start = IOP13XX_PCIX_LOWER_MEM_RA;
+		res->end   = IOP13XX_PCIX_UPPER_MEM_RA;
+		res->name  = "IQ81340 ATUX PCI Memory Space";
+		res->flags = IORESOURCE_MEM;
 		sys->mem_offset = IOP13XX_PCIX_MEM_OFFSET;
-		sys->io_offset = IOP13XX_PCIX_LOWER_IO_PA;
 		break;
 	case IOP13XX_INIT_ATU_ATUE:
 		/* Note: the function number field in the PCSR is ro */
@@ -1063,17 +1056,13 @@ int iop13xx_pci_setup(int nr, struct pci_sys_data *sys)
 
 		__raw_writel(pcsr, IOP13XX_ATUE_PCSR);
 
-		res[0].start = IOP13XX_PCIE_LOWER_IO_PA + IOP13XX_PCIE_IO_BUS_OFFSET;
-		res[0].end   = IOP13XX_PCIE_UPPER_IO_PA;
-		res[0].name  = "IQ81340 ATUE PCI I/O Space";
-		res[0].flags = IORESOURCE_IO;
+		pci_ioremap_io(SZ_64K, IOP13XX_PCIE_LOWER_IO_PA);
 
-		res[1].start = IOP13XX_PCIE_LOWER_MEM_RA;
-		res[1].end   = IOP13XX_PCIE_UPPER_MEM_RA;
-		res[1].name  = "IQ81340 ATUE PCI Memory Space";
-		res[1].flags = IORESOURCE_MEM;
+		res->start = IOP13XX_PCIE_LOWER_MEM_RA;
+		res->end   = IOP13XX_PCIE_UPPER_MEM_RA;
+		res->name  = "IQ81340 ATUE PCI Memory Space";
+		res->flags = IORESOURCE_MEM;
 		sys->mem_offset = IOP13XX_PCIE_MEM_OFFSET;
-		sys->io_offset = IOP13XX_PCIE_LOWER_IO_PA;
 		sys->map_irq = iop13xx_pcie_map_irq;
 		break;
 	default:
@@ -1081,11 +1070,9 @@ int iop13xx_pci_setup(int nr, struct pci_sys_data *sys)
 		return 0;
 	}
 
-	request_resource(&ioport_resource, &res[0]);
-	request_resource(&iomem_resource, &res[1]);
+	request_resource(&iomem_resource, res);
 
-	pci_add_resource_offset(&sys->resources, &res[0], sys->io_offset);
-	pci_add_resource_offset(&sys->resources, &res[1], sys->mem_offset);
+	pci_add_resource_offset(&sys->resources, res, sys->mem_offset);
 
 	return 1;
 }
diff --git a/arch/arm/mach-iop13xx/pci.h b/arch/arm/mach-iop13xx/pci.h
index c70cf5b..d45a80b 100644
--- a/arch/arm/mach-iop13xx/pci.h
+++ b/arch/arm/mach-iop13xx/pci.h
@@ -1,6 +1,6 @@
 #include <linux/types.h>
 
-extern u32 iop13xx_atue_mem_base;
-extern u32 iop13xx_atux_mem_base;
+extern void __iomem *iop13xx_atue_mem_base;
+extern void __iomem *iop13xx_atux_mem_base;
 extern size_t iop13xx_atue_mem_size;
 extern size_t iop13xx_atux_mem_size;
diff --git a/arch/arm/mach-iop13xx/setup.c b/arch/arm/mach-iop13xx/setup.c
index daabb1f..3181f61 100644
--- a/arch/arm/mach-iop13xx/setup.c
+++ b/arch/arm/mach-iop13xx/setup.c
@@ -36,20 +36,10 @@
  */
 static struct map_desc iop13xx_std_desc[] __initdata = {
 	{    /* mem mapped registers */
-		.virtual = IOP13XX_PMMR_VIRT_MEM_BASE,
+		.virtual = (unsigned long)IOP13XX_PMMR_VIRT_MEM_BASE,
 		.pfn 	 = __phys_to_pfn(IOP13XX_PMMR_PHYS_MEM_BASE),
 		.length  = IOP13XX_PMMR_SIZE,
 		.type	 = MT_DEVICE,
-	}, { /* PCIE IO space */
-		.virtual = IOP13XX_PCIE_LOWER_IO_VA,
-		.pfn 	 = __phys_to_pfn(IOP13XX_PCIE_LOWER_IO_PA),
-		.length  = IOP13XX_PCIX_IO_WINDOW_SIZE,
-		.type	 = MT_DEVICE,
-	}, { /* PCIX IO space */
-		.virtual = IOP13XX_PCIX_LOWER_IO_VA,
-		.pfn 	 = __phys_to_pfn(IOP13XX_PCIX_LOWER_IO_PA),
-		.length  = IOP13XX_PCIX_IO_WINDOW_SIZE,
-		.type	 = MT_DEVICE,
 	},
 };
 
@@ -81,8 +71,8 @@ static struct resource iop13xx_uart1_resources[] = {
 
 static struct plat_serial8250_port iop13xx_uart0_data[] = {
 	{
-       .membase     = (char*)(IOP13XX_UART0_VIRT),
-       .mapbase     = (IOP13XX_UART0_PHYS),
+       .membase     = IOP13XX_UART0_VIRT,
+       .mapbase     = IOP13XX_UART0_PHYS,
        .irq         = IRQ_IOP13XX_UART0,
        .uartclk     = IOP13XX_UART_XTAL,
        .regshift    = 2,
@@ -94,8 +84,8 @@ static struct plat_serial8250_port iop13xx_uart0_data[] = {
 
 static struct plat_serial8250_port iop13xx_uart1_data[] = {
 	{
-       .membase     = (char*)(IOP13XX_UART1_VIRT),
-       .mapbase     = (IOP13XX_UART1_PHYS),
+       .membase     = IOP13XX_UART1_VIRT,
+       .mapbase     = IOP13XX_UART1_PHYS,
        .irq         = IRQ_IOP13XX_UART1,
        .uartclk     = IOP13XX_UART_XTAL,
        .regshift    = 2,
diff --git a/arch/arm/mach-iop32x/glantank.c b/arch/arm/mach-iop32x/glantank.c
index c15a100..02e20c3 100644
--- a/arch/arm/mach-iop32x/glantank.c
+++ b/arch/arm/mach-iop32x/glantank.c
@@ -183,7 +183,7 @@ static struct i2c_board_info __initdata glantank_i2c_devices[] = {
 
 static void glantank_power_off(void)
 {
-	__raw_writeb(0x01, 0xfe8d0004);
+	__raw_writeb(0x01, IOMEM(0xfe8d0004));
 
 	while (1)
 		;
diff --git a/arch/arm/mach-iop32x/include/mach/io.h b/arch/arm/mach-iop32x/include/mach/io.h
deleted file mode 100644
index e2ada26..0000000
--- a/arch/arm/mach-iop32x/include/mach/io.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * arch/arm/mach-iop32x/include/mach/io.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 version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __IO_H
-#define __IO_H
-
-#include <asm/hardware/iop3xx.h>
-
-#define IO_SPACE_LIMIT		0xffffffff
-#define __io(p)		((void __iomem *)IOP3XX_PCI_IO_PHYS_TO_VIRT(p))
-
-#endif
diff --git a/arch/arm/mach-iop33x/include/mach/io.h b/arch/arm/mach-iop33x/include/mach/io.h
deleted file mode 100644
index f7c1b65..0000000
--- a/arch/arm/mach-iop33x/include/mach/io.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * arch/arm/mach-iop33x/include/mach/io.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 version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __IO_H
-#define __IO_H
-
-#include <asm/hardware/iop3xx.h>
-
-#define IO_SPACE_LIMIT		0xffffffff
-#define __io(p)		((void __iomem *)IOP3XX_PCI_IO_PHYS_TO_VIRT(p))
-
-#endif
diff --git a/arch/arm/mach-ixp4xx/common-pci.c b/arch/arm/mach-ixp4xx/common-pci.c
index 1694f01..6d6bde3 100644
--- a/arch/arm/mach-ixp4xx/common-pci.c
+++ b/arch/arm/mach-ixp4xx/common-pci.c
@@ -410,6 +410,7 @@ void __init ixp4xx_pci_preinit(void)
 		 * Enable the IO window to be way up high, at 0xfffffc00
 		 */
 		local_write_config(PCI_BASE_ADDRESS_5, 4, 0xfffffc01);
+		local_write_config(0x40, 4, 0x000080FF); /* No TRDY time limit */
 	} else {
 		printk("PCI: IXP4xx is target - No bus scan performed\n");
 	}
diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c
index a9f8094..8c0c0e2 100644
--- a/arch/arm/mach-ixp4xx/common.c
+++ b/arch/arm/mach-ixp4xx/common.c
@@ -53,29 +53,26 @@ static struct clock_event_device clockevent_ixp4xx;
  *************************************************************************/
 static struct map_desc ixp4xx_io_desc[] __initdata = {
 	{	/* UART, Interrupt ctrl, GPIO, timers, NPEs, MACs, USB .... */
-		.virtual	= IXP4XX_PERIPHERAL_BASE_VIRT,
+		.virtual	= (unsigned long)IXP4XX_PERIPHERAL_BASE_VIRT,
 		.pfn		= __phys_to_pfn(IXP4XX_PERIPHERAL_BASE_PHYS),
 		.length		= IXP4XX_PERIPHERAL_REGION_SIZE,
 		.type		= MT_DEVICE
 	}, {	/* Expansion Bus Config Registers */
-		.virtual	= IXP4XX_EXP_CFG_BASE_VIRT,
+		.virtual	= (unsigned long)IXP4XX_EXP_CFG_BASE_VIRT,
 		.pfn		= __phys_to_pfn(IXP4XX_EXP_CFG_BASE_PHYS),
 		.length		= IXP4XX_EXP_CFG_REGION_SIZE,
 		.type		= MT_DEVICE
 	}, {	/* PCI Registers */
-		.virtual	= IXP4XX_PCI_CFG_BASE_VIRT,
+		.virtual	= (unsigned long)IXP4XX_PCI_CFG_BASE_VIRT,
 		.pfn		= __phys_to_pfn(IXP4XX_PCI_CFG_BASE_PHYS),
 		.length		= IXP4XX_PCI_CFG_REGION_SIZE,
 		.type		= MT_DEVICE
-	},
-#ifdef CONFIG_DEBUG_LL
-	{	/* Debug UART mapping */
-		.virtual	= IXP4XX_DEBUG_UART_BASE_VIRT,
-		.pfn		= __phys_to_pfn(IXP4XX_DEBUG_UART_BASE_PHYS),
-		.length		= IXP4XX_DEBUG_UART_REGION_SIZE,
+	}, {	/* Queue Manager */
+		.virtual	= (unsigned long)IXP4XX_QMGR_BASE_VIRT,
+		.pfn		= __phys_to_pfn(IXP4XX_QMGR_BASE_PHYS),
+		.length		= IXP4XX_QMGR_REGION_SIZE,
 		.type		= MT_DEVICE
-	}
-#endif
+	},
 };
 
 void __init ixp4xx_map_io(void)
diff --git a/arch/arm/mach-ixp4xx/goramo_mlr.c b/arch/arm/mach-ixp4xx/goramo_mlr.c
index b800a03..53b8348 100644
--- a/arch/arm/mach-ixp4xx/goramo_mlr.c
+++ b/arch/arm/mach-ixp4xx/goramo_mlr.c
@@ -15,6 +15,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/flash.h>
 #include <asm/mach/pci.h>
+#include <asm/system_info.h>
 
 #define SLOT_ETHA		0x0B	/* IDSEL = AD21 */
 #define SLOT_ETHB		0x0C	/* IDSEL = AD20 */
@@ -329,7 +330,7 @@ static struct platform_device device_hss_tab[] = {
 };
 
 
-static struct platform_device *device_tab[6] __initdata = {
+static struct platform_device *device_tab[7] __initdata = {
 	&device_flash,		/* index 0 */
 };
 
diff --git a/arch/arm/mach-ixp4xx/include/mach/cpu.h b/arch/arm/mach-ixp4xx/include/mach/cpu.h
index b2ef65d..ebc0ba3 100644
--- a/arch/arm/mach-ixp4xx/include/mach/cpu.h
+++ b/arch/arm/mach-ixp4xx/include/mach/cpu.h
@@ -14,6 +14,7 @@
 #ifndef __ASM_ARCH_CPU_H__
 #define __ASM_ARCH_CPU_H__
 
+#include <linux/io.h>
 #include <asm/cputype.h>
 
 /* Processor id value in CP15 Register 0 */
@@ -37,7 +38,7 @@
 
 static inline u32 ixp4xx_read_feature_bits(void)
 {
-	u32 val = ~*IXP4XX_EXP_CFG2;
+	u32 val = ~__raw_readl(IXP4XX_EXP_CFG2);
 
 	if (cpu_is_ixp42x_rev_a0())
 		return IXP42X_FEATURE_MASK & ~(IXP4XX_FEATURE_RCOMP |
@@ -51,7 +52,7 @@ static inline u32 ixp4xx_read_feature_bits(void)
 
 static inline void ixp4xx_write_feature_bits(u32 value)
 {
-	*IXP4XX_EXP_CFG2 = ~value;
+	__raw_writel(~value, IXP4XX_EXP_CFG2);
 }
 
 #endif  /* _ASM_ARCH_CPU_H */
diff --git a/arch/arm/mach-ixp4xx/include/mach/debug-macro.S b/arch/arm/mach-ixp4xx/include/mach/debug-macro.S
index 8c9f8d5..ff686cb 100644
--- a/arch/arm/mach-ixp4xx/include/mach/debug-macro.S
+++ b/arch/arm/mach-ixp4xx/include/mach/debug-macro.S
@@ -17,8 +17,8 @@
 #else
 		mov	\rp, #0
 #endif
-                orr     \rv, \rp, #0xff000000	@ virtual
-		orr	\rv, \rv, #0x00b00000
+		orr	\rv, \rp, #0xfe000000	@ virtual
+		orr	\rv, \rv, #0x00f00000
                 orr     \rp, \rp, #0xc8000000	@ physical
                 .endm
 
diff --git a/arch/arm/mach-ixp4xx/include/mach/gpio.h b/arch/arm/mach-ixp4xx/include/mach/gpio.h
deleted file mode 100644
index ef37f26..0000000
--- a/arch/arm/mach-ixp4xx/include/mach/gpio.h
+++ /dev/null
@@ -1,2 +0,0 @@
-/* empty */
-
diff --git a/arch/arm/mach-ixp4xx/include/mach/ixp4xx-regs.h b/arch/arm/mach-ixp4xx/include/mach/ixp4xx-regs.h
index 97c530f..c5bae9c 100644
--- a/arch/arm/mach-ixp4xx/include/mach/ixp4xx-regs.h
+++ b/arch/arm/mach-ixp4xx/include/mach/ixp4xx-regs.h
@@ -30,51 +30,43 @@
  *
  * 0x50000000	0x10000000	ioremap'd	EXP BUS
  *
- * 0x6000000	0x00004000	ioremap'd	QMgr
+ * 0xC8000000	0x00013000	0xFEF00000	On-Chip Peripherals
  *
- * 0xC0000000	0x00001000	0xffbff000	PCI CFG
+ * 0xC0000000	0x00001000	0xFEF13000	PCI CFG
  *
- * 0xC4000000	0x00001000	0xffbfe000	EXP CFG
+ * 0xC4000000	0x00001000	0xFEF14000	EXP CFG
  *
- * 0xC8000000	0x00013000	0xffbeb000	On-Chip Peripherals
+ * 0x60000000	0x00004000	0xFEF15000	QMgr
  */
 
 /*
  * Queue Manager
  */
-#define IXP4XX_QMGR_BASE_PHYS		(0x60000000)
-#define IXP4XX_QMGR_REGION_SIZE		(0x00004000)
+#define IXP4XX_QMGR_BASE_PHYS		0x60000000
+#define IXP4XX_QMGR_BASE_VIRT		IOMEM(0xFEF15000)
+#define IXP4XX_QMGR_REGION_SIZE		0x00004000
 
 /*
- * Expansion BUS Configuration registers
+ * Peripheral space, including debug UART. Must be section-aligned so that
+ * it can be used with the low-level debug code.
  */
-#define IXP4XX_EXP_CFG_BASE_PHYS	(0xC4000000)
-#define IXP4XX_EXP_CFG_BASE_VIRT	(0xFFBFE000)
-#define IXP4XX_EXP_CFG_REGION_SIZE	(0x00001000)
+#define IXP4XX_PERIPHERAL_BASE_PHYS	0xC8000000
+#define IXP4XX_PERIPHERAL_BASE_VIRT	IOMEM(0xFEF00000)
+#define IXP4XX_PERIPHERAL_REGION_SIZE	0x00013000
 
 /*
  * PCI Config registers
  */
-#define IXP4XX_PCI_CFG_BASE_PHYS	(0xC0000000)
-#define	IXP4XX_PCI_CFG_BASE_VIRT	(0xFFBFF000)
-#define IXP4XX_PCI_CFG_REGION_SIZE	(0x00001000)
-
-/*
- * Peripheral space
- */
-#define IXP4XX_PERIPHERAL_BASE_PHYS	(0xC8000000)
-#define IXP4XX_PERIPHERAL_BASE_VIRT	(0xFFBEB000)
-#define IXP4XX_PERIPHERAL_REGION_SIZE	(0x00013000)
+#define IXP4XX_PCI_CFG_BASE_PHYS	0xC0000000
+#define IXP4XX_PCI_CFG_BASE_VIRT	IOMEM(0xFEF13000)
+#define IXP4XX_PCI_CFG_REGION_SIZE	0x00001000
 
 /*
- * Debug UART
- *
- * This is basically a remap of UART1 into a region that is section
- * aligned so that it * can be used with the low-level debug code.
+ * Expansion BUS Configuration registers
  */
-#define	IXP4XX_DEBUG_UART_BASE_PHYS	(0xC8000000)
-#define	IXP4XX_DEBUG_UART_BASE_VIRT	(0xffb00000)
-#define	IXP4XX_DEBUG_UART_REGION_SIZE	(0x00001000)
+#define IXP4XX_EXP_CFG_BASE_PHYS	0xC4000000
+#define IXP4XX_EXP_CFG_BASE_VIRT	0xFEF14000
+#define IXP4XX_EXP_CFG_REGION_SIZE	0x00001000
 
 #define IXP4XX_EXP_CS0_OFFSET	0x00
 #define IXP4XX_EXP_CS1_OFFSET   0x04
@@ -92,7 +84,7 @@
 /*
  * Expansion Bus Controller registers.
  */
-#define IXP4XX_EXP_REG(x) ((volatile u32 *)(IXP4XX_EXP_CFG_BASE_VIRT+(x)))
+#define IXP4XX_EXP_REG(x) ((volatile u32 __iomem *)(IXP4XX_EXP_CFG_BASE_VIRT+(x)))
 
 #define IXP4XX_EXP_CS0      IXP4XX_EXP_REG(IXP4XX_EXP_CS0_OFFSET)
 #define IXP4XX_EXP_CS1      IXP4XX_EXP_REG(IXP4XX_EXP_CS1_OFFSET)
diff --git a/arch/arm/mach-ixp4xx/include/mach/qmgr.h b/arch/arm/mach-ixp4xx/include/mach/qmgr.h
index 9e7cad2..0a88d3b 100644
--- a/arch/arm/mach-ixp4xx/include/mach/qmgr.h
+++ b/arch/arm/mach-ixp4xx/include/mach/qmgr.h
@@ -86,7 +86,7 @@ void qmgr_release_queue(unsigned int queue);
 
 static inline void qmgr_put_entry(unsigned int queue, u32 val)
 {
-	extern struct qmgr_regs __iomem *qmgr_regs;
+	const struct qmgr_regs __iomem *qmgr_regs = (void __iomem *)IXP4XX_QMGR_BASE_VIRT;
 #if DEBUG_QMGR
 	BUG_ON(!qmgr_queue_descs[queue]); /* not yet requested */
 
@@ -99,7 +99,7 @@ static inline void qmgr_put_entry(unsigned int queue, u32 val)
 static inline u32 qmgr_get_entry(unsigned int queue)
 {
 	u32 val;
-	extern struct qmgr_regs __iomem *qmgr_regs;
+	const struct qmgr_regs __iomem *qmgr_regs = (void __iomem *)IXP4XX_QMGR_BASE_VIRT;
 	val = __raw_readl(&qmgr_regs->acc[queue][0]);
 #if DEBUG_QMGR
 	BUG_ON(!qmgr_queue_descs[queue]); /* not yet requested */
@@ -112,14 +112,14 @@ static inline u32 qmgr_get_entry(unsigned int queue)
 
 static inline int __qmgr_get_stat1(unsigned int queue)
 {
-	extern struct qmgr_regs __iomem *qmgr_regs;
+	const struct qmgr_regs __iomem *qmgr_regs = (void __iomem *)IXP4XX_QMGR_BASE_VIRT;
 	return (__raw_readl(&qmgr_regs->stat1[queue >> 3])
 		>> ((queue & 7) << 2)) & 0xF;
 }
 
 static inline int __qmgr_get_stat2(unsigned int queue)
 {
-	extern struct qmgr_regs __iomem *qmgr_regs;
+	const struct qmgr_regs __iomem *qmgr_regs = (void __iomem *)IXP4XX_QMGR_BASE_VIRT;
 	BUG_ON(queue >= HALF_QUEUES);
 	return (__raw_readl(&qmgr_regs->stat2[queue >> 4])
 		>> ((queue & 0xF) << 1)) & 0x3;
@@ -145,7 +145,7 @@ static inline int qmgr_stat_empty(unsigned int queue)
  */
 static inline int qmgr_stat_below_low_watermark(unsigned int queue)
 {
-	extern struct qmgr_regs __iomem *qmgr_regs;
+	const struct qmgr_regs __iomem *qmgr_regs = (void __iomem *)IXP4XX_QMGR_BASE_VIRT;
 	if (queue >= HALF_QUEUES)
 		return (__raw_readl(&qmgr_regs->statne_h) >>
 			(queue - HALF_QUEUES)) & 0x01;
@@ -172,7 +172,7 @@ static inline int qmgr_stat_above_high_watermark(unsigned int queue)
  */
 static inline int qmgr_stat_full(unsigned int queue)
 {
-	extern struct qmgr_regs __iomem *qmgr_regs;
+	const struct qmgr_regs __iomem *qmgr_regs = (void __iomem *)IXP4XX_QMGR_BASE_VIRT;
 	if (queue >= HALF_QUEUES)
 		return (__raw_readl(&qmgr_regs->statf_h) >>
 			(queue - HALF_QUEUES)) & 0x01;
diff --git a/arch/arm/mach-ixp4xx/ixp4xx_npe.c b/arch/arm/mach-ixp4xx/ixp4xx_npe.c
index a17ed79..d4eb09a 100644
--- a/arch/arm/mach-ixp4xx/ixp4xx_npe.c
+++ b/arch/arm/mach-ixp4xx/ixp4xx_npe.c
@@ -116,7 +116,11 @@
 /* NPE mailbox_status value for reset */
 #define RESET_MBOX_STAT			0x0000F0F0
 
-const char *npe_names[] = { "NPE-A", "NPE-B", "NPE-C" };
+#define NPE_A_FIRMWARE "NPE-A"
+#define NPE_B_FIRMWARE "NPE-B"
+#define NPE_C_FIRMWARE "NPE-C"
+
+const char *npe_names[] = { NPE_A_FIRMWARE, NPE_B_FIRMWARE, NPE_C_FIRMWARE };
 
 #define print_npe(pri, npe, fmt, ...)					\
 	printk(pri "%s: " fmt, npe_name(npe), ## __VA_ARGS__)
@@ -724,6 +728,9 @@ module_exit(npe_cleanup_module);
 
 MODULE_AUTHOR("Krzysztof Halasa");
 MODULE_LICENSE("GPL v2");
+MODULE_FIRMWARE(NPE_A_FIRMWARE);
+MODULE_FIRMWARE(NPE_B_FIRMWARE);
+MODULE_FIRMWARE(NPE_C_FIRMWARE);
 
 EXPORT_SYMBOL(npe_names);
 EXPORT_SYMBOL(npe_running);
diff --git a/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c b/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c
index 852f7c9..7c0584e 100644
--- a/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c
+++ b/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c
@@ -14,7 +14,7 @@
 #include <linux/module.h>
 #include <mach/qmgr.h>
 
-struct qmgr_regs __iomem *qmgr_regs;
+static const struct qmgr_regs __iomem *qmgr_regs = (void __iomem *)IXP4XX_QMGR_BASE_VIRT;
 static struct resource *mem_res;
 static spinlock_t qmgr_lock;
 static u32 used_sram_bitmap[4]; /* 128 16-dword pages */
@@ -32,7 +32,7 @@ void qmgr_set_irq(unsigned int queue, int src,
 
 	spin_lock_irqsave(&qmgr_lock, flags);
 	if (queue < HALF_QUEUES) {
-		u32 __iomem *reg;
+		const u32 __iomem *reg;
 		int bit;
 		BUG_ON(src > QUEUE_IRQ_SRC_NOT_FULL);
 		reg = &qmgr_regs->irqsrc[queue >> 3]; /* 8 queues per u32 */
@@ -293,12 +293,6 @@ static int qmgr_init(void)
 	if (mem_res == NULL)
 		return -EBUSY;
 
-	qmgr_regs = ioremap(IXP4XX_QMGR_BASE_PHYS, IXP4XX_QMGR_REGION_SIZE);
-	if (qmgr_regs == NULL) {
-		err = -ENOMEM;
-		goto error_map;
-	}
-
 	/* reset qmgr registers */
 	for (i = 0; i < 4; i++) {
 		__raw_writel(0x33333333, &qmgr_regs->stat1[i]);
@@ -347,8 +341,6 @@ static int qmgr_init(void)
 error_irq2:
 	free_irq(IRQ_IXP4XX_QM1, NULL);
 error_irq:
-	iounmap(qmgr_regs);
-error_map:
 	release_mem_region(IXP4XX_QMGR_BASE_PHYS, IXP4XX_QMGR_REGION_SIZE);
 	return err;
 }
@@ -359,7 +351,6 @@ static void qmgr_remove(void)
 	free_irq(IRQ_IXP4XX_QM2, NULL);
 	synchronize_irq(IRQ_IXP4XX_QM1);
 	synchronize_irq(IRQ_IXP4XX_QM2);
-	iounmap(qmgr_regs);
 	release_mem_region(IXP4XX_QMGR_BASE_PHYS, IXP4XX_QMGR_REGION_SIZE);
 }
 
@@ -369,7 +360,6 @@ module_exit(qmgr_remove);
 MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Krzysztof Halasa");
 
-EXPORT_SYMBOL(qmgr_regs);
 EXPORT_SYMBOL(qmgr_set_irq);
 EXPORT_SYMBOL(qmgr_enable_irq);
 EXPORT_SYMBOL(qmgr_disable_irq);
diff --git a/arch/arm/mach-kirkwood/Kconfig b/arch/arm/mach-kirkwood/Kconfig
index ca5c15a..50bca50 100644
--- a/arch/arm/mach-kirkwood/Kconfig
+++ b/arch/arm/mach-kirkwood/Kconfig
@@ -94,6 +94,13 @@ config MACH_TS219_DT
 	  or MV6282. If you have the wrong one, the buttons will not
 	  work.
 
+config MACH_DOCKSTAR_DT
+	bool "Seagate FreeAgent Dockstar (Flattened Device Tree)"
+	select ARCH_KIRKWOOD_DT
+	help
+	  Say 'Y' here if you want your kernel to support the
+	  Seagate FreeAgent Dockstar (Flattened Device Tree).
+
 config MACH_GOFLEXNET_DT
 	bool "Seagate GoFlex Net (Flattened Device Tree)"
 	select ARCH_KIRKWOOD_DT
@@ -109,6 +116,20 @@ config MACH_LSXL_DT
 	  Buffalo Linkstation LS-XHL & LS-CHLv2 devices, using
 	  Flattened Device Tree.
 
+config MACH_IOMEGA_IX2_200_DT
+	bool "Iomega StorCenter ix2-200 (Flattened Device Tree)"
+	select ARCH_KIRKWOOD_DT
+	help
+	  Say 'Y' here if you want your kernel to support the
+	  Iomega StorCenter ix2-200 (Flattened Device Tree).
+
+config MACH_KM_KIRKWOOD_DT
+	bool "Keymile Kirkwood Reference Design (Flattened Device Tree)"
+	select ARCH_KIRKWOOD_DT
+	help
+	  Say 'Y' here if you want your kernel to support the
+	  Keymile Kirkwood Reference Desgin, using Flattened Device Tree.
+
 config MACH_TS219
 	bool "QNAP TS-110, TS-119, TS-119P+, TS-210, TS-219, TS-219P and TS-219P+ Turbo NAS"
 	help
diff --git a/arch/arm/mach-kirkwood/Makefile b/arch/arm/mach-kirkwood/Makefile
index 055c85a..294779f 100644
--- a/arch/arm/mach-kirkwood/Makefile
+++ b/arch/arm/mach-kirkwood/Makefile
@@ -26,5 +26,8 @@ obj-$(CONFIG_MACH_ICONNECT_DT)		+= board-iconnect.o
 obj-$(CONFIG_MACH_DLINK_KIRKWOOD_DT)	+= board-dnskw.o
 obj-$(CONFIG_MACH_IB62X0_DT)		+= board-ib62x0.o
 obj-$(CONFIG_MACH_TS219_DT)		+= board-ts219.o tsx1x-common.o
+obj-$(CONFIG_MACH_DOCKSTAR_DT)		+= board-dockstar.o
 obj-$(CONFIG_MACH_GOFLEXNET_DT)		+= board-goflexnet.o
 obj-$(CONFIG_MACH_LSXL_DT)		+= board-lsxl.o
+obj-$(CONFIG_MACH_IOMEGA_IX2_200_DT)	+= board-iomega_ix2_200.o
+obj-$(CONFIG_MACH_KM_KIRKWOOD_DT)	+= board-km_kirkwood.o
diff --git a/arch/arm/mach-kirkwood/Makefile.boot b/arch/arm/mach-kirkwood/Makefile.boot
index a13299d..760a0ef 100644
--- a/arch/arm/mach-kirkwood/Makefile.boot
+++ b/arch/arm/mach-kirkwood/Makefile.boot
@@ -1,14 +1,3 @@
    zreladdr-y	+= 0x00008000
 params_phys-y	:= 0x00000100
 initrd_phys-y	:= 0x00800000
-
-dtb-$(CONFIG_MACH_DREAMPLUG_DT) += kirkwood-dreamplug.dtb
-dtb-$(CONFIG_MACH_DLINK_KIRKWOOD_DT) += kirkwood-dns320.dtb
-dtb-$(CONFIG_MACH_DLINK_KIRKWOOD_DT) += kirkwood-dns325.dtb
-dtb-$(CONFIG_MACH_ICONNECT_DT) += kirkwood-iconnect.dtb
-dtb-$(CONFIG_MACH_IB62X0_DT) += kirkwood-ib62x0.dtb
-dtb-$(CONFIG_MACH_TS219_DT)	+= kirkwood-ts219-6281.dtb
-dtb-$(CONFIG_MACH_TS219_DT)	+= kirkwood-ts219-6282.dtb
-dtb-$(CONFIG_MACH_GOFLEXNET_DT) += kirkwood-goflexnet.dtb
-dtb-$(CONFIG_MACH_LSXL_DT) += kirkwood-lschlv2.dtb
-dtb-$(CONFIG_MACH_LSXL_DT) += kirkwood-lsxhl.dtb
diff --git a/arch/arm/mach-kirkwood/addr-map.c b/arch/arm/mach-kirkwood/addr-map.c
index e9a7180..8f0d162 100644
--- a/arch/arm/mach-kirkwood/addr-map.c
+++ b/arch/arm/mach-kirkwood/addr-map.c
@@ -86,5 +86,6 @@ void __init kirkwood_setup_cpu_mbus(void)
 	/*
 	 * Setup MBUS dram target info.
 	 */
-	orion_setup_cpu_mbus_target(&addr_map_cfg, DDR_WINDOW_CPU_BASE);
+	orion_setup_cpu_mbus_target(&addr_map_cfg,
+				    (void __iomem *) DDR_WINDOW_CPU_BASE);
 }
diff --git a/arch/arm/mach-kirkwood/board-dnskw.c b/arch/arm/mach-kirkwood/board-dnskw.c
index 4ab3506..43d16d6 100644
--- a/arch/arm/mach-kirkwood/board-dnskw.c
+++ b/arch/arm/mach-kirkwood/board-dnskw.c
@@ -14,18 +14,8 @@
 #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/of.h>
 #include <linux/gpio.h>
-#include <linux/input.h>
-#include <linux/gpio-fan.h>
-#include <linux/leds.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <mach/kirkwood.h>
-#include <mach/bridge-regs.h>
 #include "common.h"
 #include "mpp.h"
 
@@ -67,29 +57,6 @@ static unsigned int dnskw_mpp_config[] __initdata = {
 	0
 };
 
-/* Fan: ADDA AD045HB-G73 40mm 6000rpm@5v */
-static struct gpio_fan_speed dnskw_fan_speed[] = {
-	{    0,  0 },
-	{ 3000,	 1 },
-	{ 6000,	 2 },
-};
-static unsigned dnskw_fan_pins[] = {46, 45};
-
-static struct gpio_fan_platform_data dnskw_fan_data = {
-	.num_ctrl	= ARRAY_SIZE(dnskw_fan_pins),
-	.ctrl		= dnskw_fan_pins,
-	.num_speed	= ARRAY_SIZE(dnskw_fan_speed),
-	.speed		= dnskw_fan_speed,
-};
-
-static struct platform_device dnskw_fan_device = {
-	.name	= "gpio-fan",
-	.id	= -1,
-	.dev	= {
-		.platform_data	= &dnskw_fan_data,
-	},
-};
-
 static void dnskw_power_off(void)
 {
 	gpio_set_value(36, 1);
@@ -114,8 +81,6 @@ void __init dnskw_init(void)
 	kirkwood_ehci_init();
 	kirkwood_ge00_init(&dnskw_ge00_data);
 
-	platform_device_register(&dnskw_fan_device);
-
 	/* Register power-off GPIO. */
 	if (gpio_request(36, "dnskw:power:off") == 0
 	    && gpio_direction_output(36, 0) == 0)
diff --git a/arch/arm/mach-kirkwood/board-dockstar.c b/arch/arm/mach-kirkwood/board-dockstar.c
new file mode 100644
index 0000000..f2fbb02
--- /dev/null
+++ b/arch/arm/mach-kirkwood/board-dockstar.c
@@ -0,0 +1,61 @@
+/*
+ * arch/arm/mach-kirkwood/board-dockstar.c
+ *
+ * Seagate FreeAgent Dockstar Board Init for drivers not converted to
+ * flattened device tree yet.
+ *
+ * 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.
+ *
+ * Copied and modified for Seagate GoFlex Net support by
+ * Joshua Coombs <josh.coombs@gmail.com> based on ArchLinux ARM's
+ * GoFlex kernel patches.
+ *
+ */
+
+#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/of.h>
+#include <linux/of_address.h>
+#include <linux/of_fdt.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/gpio.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <mach/kirkwood.h>
+#include <mach/bridge-regs.h>
+#include <linux/platform_data/mmc-mvsdio.h>
+#include "common.h"
+#include "mpp.h"
+
+static struct mv643xx_eth_platform_data dockstar_ge00_data = {
+	.phy_addr	= MV643XX_ETH_PHY_ADDR(0),
+};
+
+static unsigned int dockstar_mpp_config[] __initdata = {
+	MPP29_GPIO,	/* USB Power Enable */
+	MPP46_GPIO,	/* LED green */
+	MPP47_GPIO,	/* LED orange */
+	0
+};
+
+void __init dockstar_dt_init(void)
+{
+	/*
+	 * Basic setup. Needs to be called early.
+	 */
+	kirkwood_mpp_conf(dockstar_mpp_config);
+
+	if (gpio_request(29, "USB Power Enable") != 0 ||
+	    gpio_direction_output(29, 1) != 0)
+		pr_err("can't setup GPIO 29 (USB Power Enable)\n");
+	kirkwood_ehci_init();
+
+	kirkwood_ge00_init(&dockstar_ge00_data);
+}
diff --git a/arch/arm/mach-kirkwood/board-dreamplug.c b/arch/arm/mach-kirkwood/board-dreamplug.c
index aeb234d..20af53a 100644
--- a/arch/arm/mach-kirkwood/board-dreamplug.c
+++ b/arch/arm/mach-kirkwood/board-dreamplug.c
@@ -30,7 +30,7 @@
 #include <asm/mach/map.h>
 #include <mach/kirkwood.h>
 #include <mach/bridge-regs.h>
-#include <plat/mvsdio.h>
+#include <linux/platform_data/mmc-mvsdio.h>
 #include "common.h"
 #include "mpp.h"
 
diff --git a/arch/arm/mach-kirkwood/board-dt.c b/arch/arm/mach-kirkwood/board-dt.c
index e4eb450..70c5a28 100644
--- a/arch/arm/mach-kirkwood/board-dt.c
+++ b/arch/arm/mach-kirkwood/board-dt.c
@@ -33,6 +33,7 @@ struct of_dev_auxdata kirkwood_auxdata_lookup[] __initdata = {
 	OF_DEV_AUXDATA("marvell,orion-wdt", 0xf1020300, "orion_wdt", NULL),
 	OF_DEV_AUXDATA("marvell,orion-sata", 0xf1080000, "sata_mv.0", NULL),
 	OF_DEV_AUXDATA("marvell,orion-nand", 0xf4000000, "orion_nand", NULL),
+	OF_DEV_AUXDATA("marvell,orion-crypto", 0xf1030000, "mv_crypto", NULL),
 	{},
 };
 
@@ -60,7 +61,6 @@ static void __init kirkwood_dt_init(void)
 	/* internal devices that every board has */
 	kirkwood_xor0_init();
 	kirkwood_xor1_init();
-	kirkwood_crypto_init();
 
 #ifdef CONFIG_KEXEC
 	kexec_reinit = kirkwood_enable_pcie;
@@ -81,12 +81,21 @@ static void __init kirkwood_dt_init(void)
 	if (of_machine_is_compatible("qnap,ts219"))
 		qnap_dt_ts219_init();
 
+	if (of_machine_is_compatible("seagate,dockstar"))
+		dockstar_dt_init();
+
 	if (of_machine_is_compatible("seagate,goflexnet"))
 		goflexnet_init();
 
 	if (of_machine_is_compatible("buffalo,lsxl"))
 		lsxl_init();
 
+	if (of_machine_is_compatible("iom,ix2-200"))
+		iomega_ix2_200_init();
+
+	if (of_machine_is_compatible("keymile,km_kirkwood"))
+		km_kirkwood_init();
+
 	of_platform_populate(NULL, kirkwood_dt_match_table,
 			     kirkwood_auxdata_lookup, NULL);
 }
@@ -98,8 +107,11 @@ static const char *kirkwood_dt_board_compat[] = {
 	"iom,iconnect",
 	"raidsonic,ib-nas62x0",
 	"qnap,ts219",
+	"seagate,dockstar",
 	"seagate,goflexnet",
 	"buffalo,lsxl",
+	"iom,ix2-200",
+	"keymile,km_kirkwood",
 	NULL
 };
 
diff --git a/arch/arm/mach-kirkwood/board-goflexnet.c b/arch/arm/mach-kirkwood/board-goflexnet.c
index 413e2c8..001ca8c 100644
--- a/arch/arm/mach-kirkwood/board-goflexnet.c
+++ b/arch/arm/mach-kirkwood/board-goflexnet.c
@@ -32,7 +32,7 @@
 #include <asm/mach/map.h>
 #include <mach/kirkwood.h>
 #include <mach/bridge-regs.h>
-#include <plat/mvsdio.h>
+#include <linux/platform_data/mmc-mvsdio.h>
 #include "common.h"
 #include "mpp.h"
 
diff --git a/arch/arm/mach-kirkwood/board-iconnect.c b/arch/arm/mach-kirkwood/board-iconnect.c
index d7a9198..d084b1e 100644
--- a/arch/arm/mach-kirkwood/board-iconnect.c
+++ b/arch/arm/mach-kirkwood/board-iconnect.c
@@ -16,11 +16,8 @@
 #include <linux/of_fdt.h>
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
-#include <linux/mtd/partitions.h>
 #include <linux/mv643xx_eth.h>
 #include <linux/gpio.h>
-#include <linux/input.h>
-#include <linux/gpio_keys.h>
 #include <asm/mach/arch.h>
 #include <mach/kirkwood.h>
 #include "common.h"
@@ -44,57 +41,12 @@ static unsigned int iconnect_mpp_config[] __initdata = {
 	0
 };
 
-static struct mtd_partition iconnect_nand_parts[] = {
-	{
-		.name = "flash",
-		.offset = 0,
-		.size = MTDPART_SIZ_FULL,
-	},
-};
-
-/* yikes... theses are the original input buttons */
-/* but I'm not convinced by the sw event choices  */
-static struct gpio_keys_button iconnect_buttons[] = {
-	{
-		.type		= EV_SW,
-		.code		= SW_LID,
-		.gpio		= 12,
-		.desc		= "Reset Button",
-		.active_low	= 1,
-		.debounce_interval = 100,
-	}, {
-		.type		= EV_SW,
-		.code		= SW_TABLET_MODE,
-		.gpio		= 35,
-		.desc		= "OTB Button",
-		.active_low	= 1,
-		.debounce_interval = 100,
-	},
-};
-
-static struct gpio_keys_platform_data iconnect_button_data = {
-	.buttons	= iconnect_buttons,
-	.nbuttons	= ARRAY_SIZE(iconnect_buttons),
-};
-
-static struct platform_device iconnect_button_device = {
-	.name		= "gpio-keys",
-	.id		= -1,
-	.num_resources	= 0,
-	.dev        = {
-		.platform_data  = &iconnect_button_data,
-	},
-};
-
 void __init iconnect_init(void)
 {
 	kirkwood_mpp_conf(iconnect_mpp_config);
-	kirkwood_nand_init(ARRAY_AND_SIZE(iconnect_nand_parts), 25);
 
 	kirkwood_ehci_init();
 	kirkwood_ge00_init(&iconnect_ge00_data);
-
-	platform_device_register(&iconnect_button_device);
 }
 
 static int __init iconnect_pci_init(void)
diff --git a/arch/arm/mach-kirkwood/board-iomega_ix2_200.c b/arch/arm/mach-kirkwood/board-iomega_ix2_200.c
new file mode 100644
index 0000000..158fb97
--- /dev/null
+++ b/arch/arm/mach-kirkwood/board-iomega_ix2_200.c
@@ -0,0 +1,57 @@
+/*
+ * arch/arm/mach-kirkwood/board-iomega_ix2_200.c
+ *
+ * Iomega StorCenter ix2-200
+ *
+ * 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/mv643xx_eth.h>
+#include <linux/ethtool.h>
+#include <mach/kirkwood.h>
+#include "common.h"
+#include "mpp.h"
+
+static struct mv643xx_eth_platform_data iomega_ix2_200_ge00_data = {
+	.phy_addr       = MV643XX_ETH_PHY_NONE,
+	.speed          = SPEED_1000,
+	.duplex         = DUPLEX_FULL,
+};
+
+static unsigned int iomega_ix2_200_mpp_config[] __initdata = {
+	MPP12_GPIO,			/* Reset Button */
+	MPP14_GPIO,			/* Power Button */
+	MPP15_GPIO,			/* Backup LED (blue) */
+	MPP16_GPIO,			/* Power LED (white) */
+	MPP35_GPIO,			/* OTB Button */
+	MPP36_GPIO,			/* Rebuild LED (white) */
+	MPP37_GPIO,			/* Health LED (red) */
+	MPP38_GPIO,			/* SATA LED brightness control 1 */
+	MPP39_GPIO,			/* SATA LED brightness control 2 */
+	MPP40_GPIO,			/* Backup LED brightness control 1 */
+	MPP41_GPIO,			/* Backup LED brightness control 2 */
+	MPP42_GPIO,			/* Power LED brightness control 1 */
+	MPP43_GPIO,			/* Power LED brightness control 2 */
+	MPP44_GPIO,			/* Health LED brightness control 1 */
+	MPP45_GPIO,			/* Health LED brightness control 2 */
+	MPP46_GPIO,			/* Rebuild LED brightness control 1 */
+	MPP47_GPIO,			/* Rebuild LED brightness control 2 */
+	0
+};
+
+void __init iomega_ix2_200_init(void)
+{
+	/*
+	 * Basic setup. Needs to be called early.
+	 */
+	kirkwood_mpp_conf(iomega_ix2_200_mpp_config);
+
+	kirkwood_ehci_init();
+
+	kirkwood_ge01_init(&iomega_ix2_200_ge00_data);
+}
diff --git a/arch/arm/mach-kirkwood/board-km_kirkwood.c b/arch/arm/mach-kirkwood/board-km_kirkwood.c
new file mode 100644
index 0000000..f7d3283
--- /dev/null
+++ b/arch/arm/mach-kirkwood/board-km_kirkwood.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2012 2012 KEYMILE AG, CH-3097 Bern
+ * Valentin Longchamp <valentin.longchamp@keymile.com>
+ *
+ * arch/arm/mach-kirkwood/board-km_kirkwood.c
+ *
+ * Keymile km_kirkwood Reference Desing Init for drivers not converted to
+ * flattened device tree yet.
+ *
+ * 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/mv643xx_eth.h>
+#include <linux/clk.h>
+#include <linux/clk-private.h>
+#include "common.h"
+#include "mpp.h"
+
+static struct mv643xx_eth_platform_data km_kirkwood_ge00_data = {
+	.phy_addr	= MV643XX_ETH_PHY_ADDR(0),
+};
+
+static unsigned int km_kirkwood_mpp_config[] __initdata = {
+	MPP8_GPIO,	/* I2C SDA */
+	MPP9_GPIO,	/* I2C SCL */
+	0
+};
+
+void __init km_kirkwood_init(void)
+{
+	struct clk *sata_clk;
+	/*
+	 * Basic setup. Needs to be called early.
+	 */
+	kirkwood_mpp_conf(km_kirkwood_mpp_config);
+
+	/*
+	 * Our variant of kirkwood (integrated in the Bobcat) hangs on accessing
+	 * SATA bits (14-15) of the Clock Gating Control Register. Since these
+	 * devices are also not present in this variant, their clocks get
+	 * disabled because unused when clk_disable_unused() gets called.
+	 * That's why we change the flags to these clocks to CLK_IGNORE_UNUSED
+	 */
+	sata_clk = clk_get_sys("sata_mv.0", "0");
+	if (!IS_ERR(sata_clk))
+		sata_clk->flags |= CLK_IGNORE_UNUSED;
+	sata_clk = clk_get_sys("sata_mv.0", "1");
+	if (!IS_ERR(sata_clk))
+		sata_clk->flags |= CLK_IGNORE_UNUSED;
+
+	kirkwood_ehci_init();
+	kirkwood_ge00_init(&km_kirkwood_ge00_data);
+}
diff --git a/arch/arm/mach-kirkwood/common.c b/arch/arm/mach-kirkwood/common.c
index 1201191..3991077 100644
--- a/arch/arm/mach-kirkwood/common.c
+++ b/arch/arm/mach-kirkwood/common.c
@@ -26,15 +26,15 @@
 #include <asm/mach/time.h>
 #include <mach/kirkwood.h>
 #include <mach/bridge-regs.h>
-#include <plat/audio.h>
+#include <linux/platform_data/asoc-kirkwood.h>
 #include <plat/cache-feroceon-l2.h>
-#include <plat/mvsdio.h>
-#include <plat/orion_nand.h>
-#include <plat/ehci-orion.h>
+#include <linux/platform_data/mmc-mvsdio.h>
+#include <linux/platform_data/mtd-orion_nand.h>
+#include <linux/platform_data/usb-ehci-orion.h>
 #include <plat/common.h>
 #include <plat/time.h>
 #include <plat/addr-map.h>
-#include <plat/mv_xor.h>
+#include <linux/platform_data/dma-mv_xor.h>
 #include "common.h"
 
 /*****************************************************************************
@@ -42,17 +42,7 @@
  ****************************************************************************/
 static struct map_desc kirkwood_io_desc[] __initdata = {
 	{
-		.virtual	= KIRKWOOD_PCIE_IO_VIRT_BASE,
-		.pfn		= __phys_to_pfn(KIRKWOOD_PCIE_IO_PHYS_BASE),
-		.length		= KIRKWOOD_PCIE_IO_SIZE,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= KIRKWOOD_PCIE1_IO_VIRT_BASE,
-		.pfn		= __phys_to_pfn(KIRKWOOD_PCIE1_IO_PHYS_BASE),
-		.length		= KIRKWOOD_PCIE1_IO_SIZE,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= KIRKWOOD_REGS_VIRT_BASE,
+		.virtual	= (unsigned long) KIRKWOOD_REGS_VIRT_BASE,
 		.pfn		= __phys_to_pfn(KIRKWOOD_REGS_PHYS_BASE),
 		.length		= KIRKWOOD_REGS_SIZE,
 		.type		= MT_DEVICE,
@@ -215,8 +205,7 @@ static struct clk *tclk;
 
 static struct clk __init *kirkwood_register_gate(const char *name, u8 bit_idx)
 {
-	return clk_register_gate(NULL, name, "tclk", 0,
-				 (void __iomem *)CLOCK_GATING_CTRL,
+	return clk_register_gate(NULL, name, "tclk", 0, CLOCK_GATING_CTRL,
 				 bit_idx, 0, &gating_lock);
 }
 
@@ -225,8 +214,7 @@ static struct clk __init *kirkwood_register_gate_fn(const char *name,
 						    void (*fn_en)(void),
 						    void (*fn_dis)(void))
 {
-	return clk_register_gate_fn(NULL, name, "tclk", 0,
-				    (void __iomem *)CLOCK_GATING_CTRL,
+	return clk_register_gate_fn(NULL, name, "tclk", 0, CLOCK_GATING_CTRL,
 				    bit_idx, 0, &gating_lock, fn_en, fn_dis);
 }
 
diff --git a/arch/arm/mach-kirkwood/common.h b/arch/arm/mach-kirkwood/common.h
index 304dd1a..bcffd7c 100644
--- a/arch/arm/mach-kirkwood/common.h
+++ b/arch/arm/mach-kirkwood/common.h
@@ -82,6 +82,12 @@ void ib62x0_init(void);
 static inline void ib62x0_init(void) {};
 #endif
 
+#ifdef CONFIG_MACH_DOCKSTAR_DT
+void dockstar_dt_init(void);
+#else
+static inline void dockstar_dt_init(void) {};
+#endif
+
 #ifdef CONFIG_MACH_GOFLEXNET_DT
 void goflexnet_init(void);
 #else
@@ -94,6 +100,18 @@ void lsxl_init(void);
 static inline void lsxl_init(void) {};
 #endif
 
+#ifdef CONFIG_MACH_IOMEGA_IX2_200_DT
+void iomega_ix2_200_init(void);
+#else
+static inline void iomega_ix2_200_init(void) {};
+#endif
+
+#ifdef CONFIG_MACH_KM_KIRKWOOD_DT
+void km_kirkwood_init(void);
+#else
+static inline void km_kirkwood_init(void) {};
+#endif
+
 /* early init functions not converted to fdt yet */
 char *kirkwood_id(void);
 void kirkwood_l2_init(void);
diff --git a/arch/arm/mach-kirkwood/d2net_v2-setup.c b/arch/arm/mach-kirkwood/d2net_v2-setup.c
index 6e1bac9..2c1a453 100644
--- a/arch/arm/mach-kirkwood/d2net_v2-setup.c
+++ b/arch/arm/mach-kirkwood/d2net_v2-setup.c
@@ -32,7 +32,7 @@
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <mach/kirkwood.h>
-#include <mach/leds-ns2.h>
+#include <linux/platform_data/leds-kirkwood-ns2.h>
 #include "common.h"
 #include "mpp.h"
 #include "lacie_v2-common.h"
diff --git a/arch/arm/mach-kirkwood/db88f6281-bp-setup.c b/arch/arm/mach-kirkwood/db88f6281-bp-setup.c
index be90b7d..c49b177 100644
--- a/arch/arm/mach-kirkwood/db88f6281-bp-setup.c
+++ b/arch/arm/mach-kirkwood/db88f6281-bp-setup.c
@@ -18,7 +18,7 @@
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <mach/kirkwood.h>
-#include <plat/mvsdio.h>
+#include <linux/platform_data/mmc-mvsdio.h>
 #include "common.h"
 #include "mpp.h"
 
diff --git a/arch/arm/mach-kirkwood/dockstar-setup.c b/arch/arm/mach-kirkwood/dockstar-setup.c
index 61d9a55..23dcb19 100644
--- a/arch/arm/mach-kirkwood/dockstar-setup.c
+++ b/arch/arm/mach-kirkwood/dockstar-setup.c
@@ -19,7 +19,7 @@
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <mach/kirkwood.h>
-#include <plat/mvsdio.h>
+#include <linux/platform_data/mmc-mvsdio.h>
 #include "common.h"
 #include "mpp.h"
 
diff --git a/arch/arm/mach-kirkwood/guruplug-setup.c b/arch/arm/mach-kirkwood/guruplug-setup.c
index bdaed38..7cb55f9 100644
--- a/arch/arm/mach-kirkwood/guruplug-setup.c
+++ b/arch/arm/mach-kirkwood/guruplug-setup.c
@@ -19,7 +19,7 @@
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <mach/kirkwood.h>
-#include <plat/mvsdio.h>
+#include <linux/platform_data/mmc-mvsdio.h>
 #include "common.h"
 #include "mpp.h"
 
diff --git a/arch/arm/mach-kirkwood/include/mach/bridge-regs.h b/arch/arm/mach-kirkwood/include/mach/bridge-regs.h
index a115142..5c82b7d 100644
--- a/arch/arm/mach-kirkwood/include/mach/bridge-regs.h
+++ b/arch/arm/mach-kirkwood/include/mach/bridge-regs.h
@@ -13,37 +13,37 @@
 
 #include <mach/kirkwood.h>
 
-#define CPU_CONFIG		(BRIDGE_VIRT_BASE | 0x0100)
+#define CPU_CONFIG		(BRIDGE_VIRT_BASE + 0x0100)
 #define CPU_CONFIG_ERROR_PROP	0x00000004
 
-#define CPU_CONTROL		(BRIDGE_VIRT_BASE | 0x0104)
+#define CPU_CONTROL		(BRIDGE_VIRT_BASE + 0x0104)
 #define CPU_RESET		0x00000002
 
-#define RSTOUTn_MASK		(BRIDGE_VIRT_BASE | 0x0108)
+#define RSTOUTn_MASK		(BRIDGE_VIRT_BASE + 0x0108)
 #define WDT_RESET_OUT_EN	0x00000002
 #define SOFT_RESET_OUT_EN	0x00000004
 
-#define SYSTEM_SOFT_RESET	(BRIDGE_VIRT_BASE | 0x010c)
+#define SYSTEM_SOFT_RESET	(BRIDGE_VIRT_BASE + 0x010c)
 #define SOFT_RESET		0x00000001
 
-#define BRIDGE_CAUSE		(BRIDGE_VIRT_BASE | 0x0110)
+#define BRIDGE_CAUSE		(BRIDGE_VIRT_BASE + 0x0110)
 #define WDT_INT_REQ		0x0008
 
 #define BRIDGE_INT_TIMER1_CLR	(~0x0004)
 
-#define IRQ_VIRT_BASE		(BRIDGE_VIRT_BASE | 0x0200)
+#define IRQ_VIRT_BASE		(BRIDGE_VIRT_BASE + 0x0200)
 #define IRQ_CAUSE_LOW_OFF	0x0000
 #define IRQ_MASK_LOW_OFF	0x0004
 #define IRQ_CAUSE_HIGH_OFF	0x0010
 #define IRQ_MASK_HIGH_OFF	0x0014
 
-#define TIMER_VIRT_BASE		(BRIDGE_VIRT_BASE | 0x0300)
-#define TIMER_PHYS_BASE		(BRIDGE_PHYS_BASE | 0x0300)
+#define TIMER_VIRT_BASE		(BRIDGE_VIRT_BASE + 0x0300)
+#define TIMER_PHYS_BASE		(BRIDGE_PHYS_BASE + 0x0300)
 
-#define L2_CONFIG_REG		(BRIDGE_VIRT_BASE | 0x0128)
+#define L2_CONFIG_REG		(BRIDGE_VIRT_BASE + 0x0128)
 #define L2_WRITETHROUGH		0x00000010
 
-#define CLOCK_GATING_CTRL	(BRIDGE_VIRT_BASE | 0x11c)
+#define CLOCK_GATING_CTRL	(BRIDGE_VIRT_BASE + 0x11c)
 #define CGC_BIT_GE0		(0)
 #define CGC_BIT_PEX0		(2)
 #define CGC_BIT_USB0		(3)
diff --git a/arch/arm/mach-kirkwood/include/mach/gpio.h b/arch/arm/mach-kirkwood/include/mach/gpio.h
deleted file mode 100644
index 84f340b..0000000
--- a/arch/arm/mach-kirkwood/include/mach/gpio.h
+++ /dev/null
@@ -1,9 +0,0 @@
-/*
- * arch/asm-arm/mach-kirkwood/include/mach/gpio.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.
- */
-
-#include <plat/gpio.h>
diff --git a/arch/arm/mach-kirkwood/include/mach/io.h b/arch/arm/mach-kirkwood/include/mach/io.h
deleted file mode 100644
index 5d0ab61..0000000
--- a/arch/arm/mach-kirkwood/include/mach/io.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * arch/arm/mach-kirkwood/include/mach/io.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 __ASM_ARCH_IO_H
-#define __ASM_ARCH_IO_H
-
-#include "kirkwood.h"
-
-#define IO_SPACE_LIMIT		0xffffffff
-
-static inline void __iomem *__io(unsigned long addr)
-{
-	return (void __iomem *)((addr - KIRKWOOD_PCIE_IO_BUS_BASE)
-					+ KIRKWOOD_PCIE_IO_VIRT_BASE);
-}
-
-#define __io(a)			__io(a)
-
-#endif
diff --git a/arch/arm/mach-kirkwood/include/mach/kirkwood.h b/arch/arm/mach-kirkwood/include/mach/kirkwood.h
index c5b6851..041653a 100644
--- a/arch/arm/mach-kirkwood/include/mach/kirkwood.h
+++ b/arch/arm/mach-kirkwood/include/mach/kirkwood.h
@@ -37,17 +37,15 @@
 #define KIRKWOOD_NAND_MEM_SIZE		SZ_1K
 
 #define KIRKWOOD_PCIE1_IO_PHYS_BASE	0xf3000000
-#define KIRKWOOD_PCIE1_IO_VIRT_BASE	0xfef00000
-#define KIRKWOOD_PCIE1_IO_BUS_BASE	0x00100000
-#define KIRKWOOD_PCIE1_IO_SIZE		SZ_1M
+#define KIRKWOOD_PCIE1_IO_BUS_BASE	0x00010000
+#define KIRKWOOD_PCIE1_IO_SIZE		SZ_64K
 
 #define KIRKWOOD_PCIE_IO_PHYS_BASE	0xf2000000
-#define KIRKWOOD_PCIE_IO_VIRT_BASE	0xfee00000
 #define KIRKWOOD_PCIE_IO_BUS_BASE	0x00000000
-#define KIRKWOOD_PCIE_IO_SIZE		SZ_1M
+#define KIRKWOOD_PCIE_IO_SIZE		SZ_64K
 
 #define KIRKWOOD_REGS_PHYS_BASE		0xf1000000
-#define KIRKWOOD_REGS_VIRT_BASE		0xfed00000
+#define KIRKWOOD_REGS_VIRT_BASE		IOMEM(0xfed00000)
 #define KIRKWOOD_REGS_SIZE		SZ_1M
 
 #define KIRKWOOD_PCIE_MEM_PHYS_BASE	0xe0000000
@@ -61,61 +59,61 @@
 /*
  * Register Map
  */
-#define DDR_VIRT_BASE		(KIRKWOOD_REGS_VIRT_BASE | 0x00000)
-#define  DDR_WINDOW_CPU_BASE	(DDR_VIRT_BASE | 0x1500)
-#define DDR_OPERATION_BASE	(DDR_VIRT_BASE | 0x1418)
-
-#define DEV_BUS_PHYS_BASE	(KIRKWOOD_REGS_PHYS_BASE | 0x10000)
-#define DEV_BUS_VIRT_BASE	(KIRKWOOD_REGS_VIRT_BASE | 0x10000)
-#define  SAMPLE_AT_RESET	(DEV_BUS_VIRT_BASE | 0x0030)
-#define  DEVICE_ID		(DEV_BUS_VIRT_BASE | 0x0034)
-#define  GPIO_LOW_VIRT_BASE	(DEV_BUS_VIRT_BASE | 0x0100)
-#define  GPIO_HIGH_VIRT_BASE	(DEV_BUS_VIRT_BASE | 0x0140)
-#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)
-#define  UART1_VIRT_BASE	(DEV_BUS_VIRT_BASE | 0x2100)
-
-#define BRIDGE_VIRT_BASE	(KIRKWOOD_REGS_VIRT_BASE | 0x20000)
-#define BRIDGE_PHYS_BASE	(KIRKWOOD_REGS_PHYS_BASE | 0x20000)
-
-#define CRYPTO_PHYS_BASE	(KIRKWOOD_REGS_PHYS_BASE | 0x30000)
-
-#define PCIE_VIRT_BASE		(KIRKWOOD_REGS_VIRT_BASE | 0x40000)
-#define PCIE_LINK_CTRL		(PCIE_VIRT_BASE | 0x70)
-#define PCIE_STATUS		(PCIE_VIRT_BASE | 0x1a04)
-#define PCIE1_VIRT_BASE		(KIRKWOOD_REGS_VIRT_BASE | 0x44000)
-#define PCIE1_LINK_CTRL		(PCIE1_VIRT_BASE | 0x70)
-#define PCIE1_STATUS		(PCIE1_VIRT_BASE | 0x1a04)
-
-#define USB_PHYS_BASE		(KIRKWOOD_REGS_PHYS_BASE | 0x50000)
-
-#define XOR0_PHYS_BASE		(KIRKWOOD_REGS_PHYS_BASE | 0x60800)
-#define XOR0_VIRT_BASE		(KIRKWOOD_REGS_VIRT_BASE | 0x60800)
-#define XOR1_PHYS_BASE		(KIRKWOOD_REGS_PHYS_BASE | 0x60900)
-#define XOR1_VIRT_BASE		(KIRKWOOD_REGS_VIRT_BASE | 0x60900)
-#define XOR0_HIGH_PHYS_BASE	(KIRKWOOD_REGS_PHYS_BASE | 0x60A00)
-#define XOR0_HIGH_VIRT_BASE	(KIRKWOOD_REGS_VIRT_BASE | 0x60A00)
-#define XOR1_HIGH_PHYS_BASE	(KIRKWOOD_REGS_PHYS_BASE | 0x60B00)
-#define XOR1_HIGH_VIRT_BASE	(KIRKWOOD_REGS_VIRT_BASE | 0x60B00)
-
-#define GE00_PHYS_BASE		(KIRKWOOD_REGS_PHYS_BASE | 0x70000)
-#define GE01_PHYS_BASE		(KIRKWOOD_REGS_PHYS_BASE | 0x74000)
-
-#define SATA_PHYS_BASE		(KIRKWOOD_REGS_PHYS_BASE | 0x80000)
-#define SATA_VIRT_BASE		(KIRKWOOD_REGS_VIRT_BASE | 0x80000)
-#define SATA0_IF_CTRL		(SATA_VIRT_BASE | 0x2050)
-#define SATA0_PHY_MODE_2	(SATA_VIRT_BASE | 0x2330)
-#define SATA1_IF_CTRL		(SATA_VIRT_BASE | 0x4050)
-#define SATA1_PHY_MODE_2	(SATA_VIRT_BASE | 0x4330)
-
-#define SDIO_PHYS_BASE		(KIRKWOOD_REGS_PHYS_BASE | 0x90000)
-
-#define AUDIO_PHYS_BASE		(KIRKWOOD_REGS_PHYS_BASE | 0xA0000)
-#define AUDIO_VIRT_BASE		(KIRKWOOD_REGS_VIRT_BASE | 0xA0000)
+#define DDR_VIRT_BASE		(KIRKWOOD_REGS_VIRT_BASE + 0x00000)
+#define  DDR_WINDOW_CPU_BASE	(DDR_VIRT_BASE + 0x1500)
+#define DDR_OPERATION_BASE	(DDR_VIRT_BASE + 0x1418)
+
+#define DEV_BUS_PHYS_BASE	(KIRKWOOD_REGS_PHYS_BASE + 0x10000)
+#define DEV_BUS_VIRT_BASE	(KIRKWOOD_REGS_VIRT_BASE + 0x10000)
+#define  SAMPLE_AT_RESET	(DEV_BUS_VIRT_BASE + 0x0030)
+#define  DEVICE_ID		(DEV_BUS_VIRT_BASE + 0x0034)
+#define  GPIO_LOW_VIRT_BASE	(DEV_BUS_VIRT_BASE + 0x0100)
+#define  GPIO_HIGH_VIRT_BASE	(DEV_BUS_VIRT_BASE + 0x0140)
+#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)
+#define  UART1_VIRT_BASE	(DEV_BUS_VIRT_BASE + 0x2100)
+
+#define BRIDGE_VIRT_BASE	(KIRKWOOD_REGS_VIRT_BASE + 0x20000)
+#define BRIDGE_PHYS_BASE	(KIRKWOOD_REGS_PHYS_BASE + 0x20000)
+
+#define CRYPTO_PHYS_BASE	(KIRKWOOD_REGS_PHYS_BASE + 0x30000)
+
+#define PCIE_VIRT_BASE		(KIRKWOOD_REGS_VIRT_BASE + 0x40000)
+#define PCIE_LINK_CTRL		(PCIE_VIRT_BASE + 0x70)
+#define PCIE_STATUS		(PCIE_VIRT_BASE + 0x1a04)
+#define PCIE1_VIRT_BASE		(KIRKWOOD_REGS_VIRT_BASE + 0x44000)
+#define PCIE1_LINK_CTRL		(PCIE1_VIRT_BASE + 0x70)
+#define PCIE1_STATUS		(PCIE1_VIRT_BASE + 0x1a04)
+
+#define USB_PHYS_BASE		(KIRKWOOD_REGS_PHYS_BASE + 0x50000)
+
+#define XOR0_PHYS_BASE		(KIRKWOOD_REGS_PHYS_BASE + 0x60800)
+#define XOR0_VIRT_BASE		(KIRKWOOD_REGS_VIRT_BASE + 0x60800)
+#define XOR1_PHYS_BASE		(KIRKWOOD_REGS_PHYS_BASE + 0x60900)
+#define XOR1_VIRT_BASE		(KIRKWOOD_REGS_VIRT_BASE + 0x60900)
+#define XOR0_HIGH_PHYS_BASE	(KIRKWOOD_REGS_PHYS_BASE + 0x60A00)
+#define XOR0_HIGH_VIRT_BASE	(KIRKWOOD_REGS_VIRT_BASE + 0x60A00)
+#define XOR1_HIGH_PHYS_BASE	(KIRKWOOD_REGS_PHYS_BASE + 0x60B00)
+#define XOR1_HIGH_VIRT_BASE	(KIRKWOOD_REGS_VIRT_BASE + 0x60B00)
+
+#define GE00_PHYS_BASE		(KIRKWOOD_REGS_PHYS_BASE + 0x70000)
+#define GE01_PHYS_BASE		(KIRKWOOD_REGS_PHYS_BASE + 0x74000)
+
+#define SATA_PHYS_BASE		(KIRKWOOD_REGS_PHYS_BASE + 0x80000)
+#define SATA_VIRT_BASE		(KIRKWOOD_REGS_VIRT_BASE + 0x80000)
+#define SATA0_IF_CTRL		(SATA_VIRT_BASE + 0x2050)
+#define SATA0_PHY_MODE_2	(SATA_VIRT_BASE + 0x2330)
+#define SATA1_IF_CTRL		(SATA_VIRT_BASE + 0x4050)
+#define SATA1_PHY_MODE_2	(SATA_VIRT_BASE + 0x4330)
+
+#define SDIO_PHYS_BASE		(KIRKWOOD_REGS_PHYS_BASE + 0x90000)
+
+#define AUDIO_PHYS_BASE		(KIRKWOOD_REGS_PHYS_BASE + 0xA0000)
+#define AUDIO_VIRT_BASE		(KIRKWOOD_REGS_VIRT_BASE + 0xA0000)
 
 /*
  * Supported devices and revisions.
diff --git a/arch/arm/mach-kirkwood/include/mach/leds-netxbig.h b/arch/arm/mach-kirkwood/include/mach/leds-netxbig.h
deleted file mode 100644
index 24b536e..0000000
--- a/arch/arm/mach-kirkwood/include/mach/leds-netxbig.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * arch/arm/mach-kirkwood/include/mach/leds-netxbig.h
- *
- * Platform data structure for netxbig LED driver
- *
- * 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_LEDS_NETXBIG_H
-#define __MACH_LEDS_NETXBIG_H
-
-struct netxbig_gpio_ext {
-	unsigned	*addr;
-	int		num_addr;
-	unsigned	*data;
-	int		num_data;
-	unsigned	enable;
-};
-
-enum netxbig_led_mode {
-	NETXBIG_LED_OFF,
-	NETXBIG_LED_ON,
-	NETXBIG_LED_SATA,
-	NETXBIG_LED_TIMER1,
-	NETXBIG_LED_TIMER2,
-	NETXBIG_LED_MODE_NUM,
-};
-
-#define NETXBIG_LED_INVALID_MODE NETXBIG_LED_MODE_NUM
-
-struct netxbig_led_timer {
-	unsigned long		delay_on;
-	unsigned long		delay_off;
-	enum netxbig_led_mode	mode;
-};
-
-struct netxbig_led {
-	const char	*name;
-	const char	*default_trigger;
-	int		mode_addr;
-	int		*mode_val;
-	int		bright_addr;
-};
-
-struct netxbig_led_platform_data {
-	struct netxbig_gpio_ext	*gpio_ext;
-	struct netxbig_led_timer *timer;
-	int			num_timer;
-	struct netxbig_led	*leds;
-	int			num_leds;
-};
-
-#endif /* __MACH_LEDS_NETXBIG_H */
diff --git a/arch/arm/mach-kirkwood/include/mach/leds-ns2.h b/arch/arm/mach-kirkwood/include/mach/leds-ns2.h
deleted file mode 100644
index e21272e..0000000
--- a/arch/arm/mach-kirkwood/include/mach/leds-ns2.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * arch/arm/mach-kirkwood/include/mach/leds-ns2.h
- *
- * Platform data structure for Network Space v2 LED driver
- *
- * 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_LEDS_NS2_H
-#define __MACH_LEDS_NS2_H
-
-struct ns2_led {
-	const char	*name;
-	const char	*default_trigger;
-	unsigned	cmd;
-	unsigned	slow;
-};
-
-struct ns2_led_platform_data {
-	int		num_leds;
-	struct ns2_led	*leds;
-};
-
-#endif /* __MACH_LEDS_NS2_H */
diff --git a/arch/arm/mach-kirkwood/irq.c b/arch/arm/mach-kirkwood/irq.c
index 720063f..8847035 100644
--- a/arch/arm/mach-kirkwood/irq.c
+++ b/arch/arm/mach-kirkwood/irq.c
@@ -10,7 +10,9 @@
 #include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/irq.h>
+#include <linux/io.h>
 #include <mach/bridge-regs.h>
+#include <plat/orion-gpio.h>
 #include <plat/irq.h>
 
 static int __initdata gpio0_irqs[4] = {
@@ -29,14 +31,14 @@ static int __initdata gpio1_irqs[4] = {
 
 void __init kirkwood_init_irq(void)
 {
-	orion_irq_init(0, (void __iomem *)(IRQ_VIRT_BASE + IRQ_MASK_LOW_OFF));
-	orion_irq_init(32, (void __iomem *)(IRQ_VIRT_BASE + IRQ_MASK_HIGH_OFF));
+	orion_irq_init(0, IRQ_VIRT_BASE + IRQ_MASK_LOW_OFF);
+	orion_irq_init(32, IRQ_VIRT_BASE + IRQ_MASK_HIGH_OFF);
 
 	/*
 	 * Initialize gpiolib for GPIOs 0-49.
 	 */
-	orion_gpio_init(NULL, 0, 32, (void __iomem *)GPIO_LOW_VIRT_BASE, 0,
+	orion_gpio_init(NULL, 0, 32, GPIO_LOW_VIRT_BASE, 0,
 			IRQ_KIRKWOOD_GPIO_START, gpio0_irqs);
-	orion_gpio_init(NULL, 32, 18, (void __iomem *)GPIO_HIGH_VIRT_BASE, 0,
+	orion_gpio_init(NULL, 32, 18, GPIO_HIGH_VIRT_BASE, 0,
 			IRQ_KIRKWOOD_GPIO_START + 32, gpio1_irqs);
 }
diff --git a/arch/arm/mach-kirkwood/netspace_v2-setup.c b/arch/arm/mach-kirkwood/netspace_v2-setup.c
index e6bba01..88b0788 100644
--- a/arch/arm/mach-kirkwood/netspace_v2-setup.c
+++ b/arch/arm/mach-kirkwood/netspace_v2-setup.c
@@ -34,7 +34,7 @@
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <mach/kirkwood.h>
-#include <mach/leds-ns2.h>
+#include <linux/platform_data/leds-kirkwood-ns2.h>
 #include "common.h"
 #include "mpp.h"
 #include "lacie_v2-common.h"
diff --git a/arch/arm/mach-kirkwood/netxbig_v2-setup.c b/arch/arm/mach-kirkwood/netxbig_v2-setup.c
index 31ae8de..a3b0914 100644
--- a/arch/arm/mach-kirkwood/netxbig_v2-setup.c
+++ b/arch/arm/mach-kirkwood/netxbig_v2-setup.c
@@ -32,7 +32,7 @@
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <mach/kirkwood.h>
-#include <mach/leds-netxbig.h>
+#include <linux/platform_data/leds-kirkwood-netxbig.h>
 #include "common.h"
 #include "mpp.h"
 #include "lacie_v2-common.h"
diff --git a/arch/arm/mach-kirkwood/openrd-setup.c b/arch/arm/mach-kirkwood/openrd-setup.c
index 7e99c3f..134ef50 100644
--- a/arch/arm/mach-kirkwood/openrd-setup.c
+++ b/arch/arm/mach-kirkwood/openrd-setup.c
@@ -20,7 +20,7 @@
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <mach/kirkwood.h>
-#include <plat/mvsdio.h>
+#include <linux/platform_data/mmc-mvsdio.h>
 #include "common.h"
 #include "mpp.h"
 
diff --git a/arch/arm/mach-kirkwood/pcie.c b/arch/arm/mach-kirkwood/pcie.c
index 6e8b2ef..ec54491 100644
--- a/arch/arm/mach-kirkwood/pcie.c
+++ b/arch/arm/mach-kirkwood/pcie.c
@@ -47,8 +47,8 @@ void kirkwood_enable_pcie(void)
 void kirkwood_pcie_id(u32 *dev, u32 *rev)
 {
 	kirkwood_enable_pcie();
-	*dev = orion_pcie_dev_id((void __iomem *)PCIE_VIRT_BASE);
-	*rev = orion_pcie_rev((void __iomem *)PCIE_VIRT_BASE);
+	*dev = orion_pcie_dev_id(PCIE_VIRT_BASE);
+	*rev = orion_pcie_rev(PCIE_VIRT_BASE);
 }
 
 struct pcie_port {
@@ -56,7 +56,7 @@ struct pcie_port {
 	void __iomem		*base;
 	spinlock_t		conf_lock;
 	int			irq;
-	struct resource		res[2];
+	struct resource		res;
 };
 
 static int pcie_port_map[2];
@@ -133,46 +133,30 @@ static struct pci_ops pcie_ops = {
 
 static void __init pcie0_ioresources_init(struct pcie_port *pp)
 {
-	pp->base = (void __iomem *)PCIE_VIRT_BASE;
+	pp->base = PCIE_VIRT_BASE;
 	pp->irq	= IRQ_KIRKWOOD_PCIE;
 
 	/*
-	 * IORESOURCE_IO
-	 */
-	pp->res[0].name = "PCIe 0 I/O Space";
-	pp->res[0].start = KIRKWOOD_PCIE_IO_BUS_BASE;
-	pp->res[0].end = pp->res[0].start + KIRKWOOD_PCIE_IO_SIZE - 1;
-	pp->res[0].flags = IORESOURCE_IO;
-
-	/*
 	 * IORESOURCE_MEM
 	 */
-	pp->res[1].name = "PCIe 0 MEM";
-	pp->res[1].start = KIRKWOOD_PCIE_MEM_PHYS_BASE;
-	pp->res[1].end = pp->res[1].start + KIRKWOOD_PCIE_MEM_SIZE - 1;
-	pp->res[1].flags = IORESOURCE_MEM;
+	pp->res.name = "PCIe 0 MEM";
+	pp->res.start = KIRKWOOD_PCIE_MEM_PHYS_BASE;
+	pp->res.end = pp->res.start + KIRKWOOD_PCIE_MEM_SIZE - 1;
+	pp->res.flags = IORESOURCE_MEM;
 }
 
 static void __init pcie1_ioresources_init(struct pcie_port *pp)
 {
-	pp->base = (void __iomem *)PCIE1_VIRT_BASE;
+	pp->base = PCIE1_VIRT_BASE;
 	pp->irq	= IRQ_KIRKWOOD_PCIE1;
 
 	/*
-	 * IORESOURCE_IO
-	 */
-	pp->res[0].name = "PCIe 1 I/O Space";
-	pp->res[0].start = KIRKWOOD_PCIE1_IO_BUS_BASE;
-	pp->res[0].end = pp->res[0].start + KIRKWOOD_PCIE1_IO_SIZE - 1;
-	pp->res[0].flags = IORESOURCE_IO;
-
-	/*
 	 * IORESOURCE_MEM
 	 */
-	pp->res[1].name = "PCIe 1 MEM";
-	pp->res[1].start = KIRKWOOD_PCIE1_MEM_PHYS_BASE;
-	pp->res[1].end = pp->res[1].start + KIRKWOOD_PCIE1_MEM_SIZE - 1;
-	pp->res[1].flags = IORESOURCE_MEM;
+	pp->res.name = "PCIe 1 MEM";
+	pp->res.start = KIRKWOOD_PCIE1_MEM_PHYS_BASE;
+	pp->res.end = pp->res.start + KIRKWOOD_PCIE1_MEM_SIZE - 1;
+	pp->res.flags = IORESOURCE_MEM;
 }
 
 static int __init kirkwood_pcie_setup(int nr, struct pci_sys_data *sys)
@@ -197,23 +181,21 @@ static int __init kirkwood_pcie_setup(int nr, struct pci_sys_data *sys)
 	case 0:
 		kirkwood_enable_pcie_clk("0");
 		pcie0_ioresources_init(pp);
+		pci_ioremap_io(SZ_64K * sys->busnr, KIRKWOOD_PCIE_IO_PHYS_BASE);
 		break;
 	case 1:
 		kirkwood_enable_pcie_clk("1");
 		pcie1_ioresources_init(pp);
+		pci_ioremap_io(SZ_64K * sys->busnr, KIRKWOOD_PCIE1_IO_PHYS_BASE);
 		break;
 	default:
 		panic("PCIe setup: invalid controller %d", index);
 	}
 
-	if (request_resource(&ioport_resource, &pp->res[0]))
-		panic("Request PCIe%d IO resource failed\n", index);
-	if (request_resource(&iomem_resource, &pp->res[1]))
+	if (request_resource(&iomem_resource, &pp->res))
 		panic("Request PCIe%d Memory resource failed\n", index);
 
-	sys->io_offset = 0;
-	pci_add_resource_offset(&sys->resources, &pp->res[0], sys->io_offset);
-	pci_add_resource_offset(&sys->resources, &pp->res[1], sys->mem_offset);
+	pci_add_resource_offset(&sys->resources, &pp->res, sys->mem_offset);
 
 	/*
 	 * Generic PCIe unit setup.
@@ -273,11 +255,11 @@ static struct hw_pci kirkwood_pci __initdata = {
 	.map_irq	= kirkwood_pcie_map_irq,
 };
 
-static void __init add_pcie_port(int index, unsigned long base)
+static void __init add_pcie_port(int index, void __iomem *base)
 {
 	printk(KERN_INFO "Kirkwood PCIe port %d: ", index);
 
-	if (orion_pcie_link_up((void __iomem *)base)) {
+	if (orion_pcie_link_up(base)) {
 		printk(KERN_INFO "link up\n");
 		pcie_port_map[num_pcie_ports++] = index;
 	} else
diff --git a/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c b/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c
index f742a66..19072c8 100644
--- a/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c
+++ b/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c
@@ -19,6 +19,7 @@
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <mach/kirkwood.h>
+#include <plat/orion-gpio.h>
 #include "common.h"
 
 #define RD88F6192_GPIO_USB_VBUS		10
diff --git a/arch/arm/mach-kirkwood/rd88f6281-setup.c b/arch/arm/mach-kirkwood/rd88f6281-setup.c
index ef92207..9717101 100644
--- a/arch/arm/mach-kirkwood/rd88f6281-setup.c
+++ b/arch/arm/mach-kirkwood/rd88f6281-setup.c
@@ -20,7 +20,7 @@
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <mach/kirkwood.h>
-#include <plat/mvsdio.h>
+#include <linux/platform_data/mmc-mvsdio.h>
 #include "common.h"
 #include "mpp.h"
 
diff --git a/arch/arm/mach-kirkwood/sheevaplug-setup.c b/arch/arm/mach-kirkwood/sheevaplug-setup.c
index 4ea70e5..28d0aba 100644
--- a/arch/arm/mach-kirkwood/sheevaplug-setup.c
+++ b/arch/arm/mach-kirkwood/sheevaplug-setup.c
@@ -19,7 +19,7 @@
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <mach/kirkwood.h>
-#include <plat/mvsdio.h>
+#include <linux/platform_data/mmc-mvsdio.h>
 #include "common.h"
 #include "mpp.h"
 
diff --git a/arch/arm/mach-kirkwood/ts41x-setup.c b/arch/arm/mach-kirkwood/ts41x-setup.c
index 5bbca26..367a940 100644
--- a/arch/arm/mach-kirkwood/ts41x-setup.c
+++ b/arch/arm/mach-kirkwood/ts41x-setup.c
@@ -20,6 +20,7 @@
 #include <linux/gpio.h>
 #include <linux/gpio_keys.h>
 #include <linux/input.h>
+#include <linux/io.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <mach/kirkwood.h>
@@ -161,7 +162,7 @@ static int __init ts41x_pci_init(void)
 		 * (Marvell 88sx7042/sata_mv) is known to stop working
 		 * after a few minutes.
 		 */
-		orion_pcie_reset((void __iomem *)PCIE_VIRT_BASE);
+		orion_pcie_reset(PCIE_VIRT_BASE);
 
 		kirkwood_pcie_id(&dev, &rev);
 		if (dev == MV88F6282_DEV_ID)
diff --git a/arch/arm/mach-ks8695/Kconfig b/arch/arm/mach-ks8695/Kconfig
index f5c39a8..a545976 100644
--- a/arch/arm/mach-ks8695/Kconfig
+++ b/arch/arm/mach-ks8695/Kconfig
@@ -21,6 +21,67 @@ config MACH_ACS5K
 	  say 'Y' here if you want your kernel to run on the Brivo
 	  Systems LLC, ACS-5000 Master board.
 
+config MACH_LITE300
+	bool "SecureComputing SG300"
+	help
+	  Say 'Y' here if you want your kernel to support the
+	  SecureComputing / SnapGear SG300 VPN Internet Router.
+	  See http://www.securecomputing.com for more details.
+
+config MACH_SG310
+	bool "McAfee SG310"
+	help
+	  Say 'Y' here if you want your kernel to support the
+	  McAfee / SnapGear SG310 VPN Internet Router.
+	  See http://www.mcafee.com for more details.
+
+config MACH_SE4200
+	bool "SecureComputing SE4200"
+	help
+	  Say 'Y' here if you want your kernel to support the
+	  SecureComputing / SnapGear SE4200 Secure Wireless VPN
+	  Internet Router.
+	  See http://www.securecomputing.com for more details.
+
+config MACH_CM4002
+	bool "OpenGear CM4002"
+	help
+	  Say 'Y' here if you want your kernel to support the OpenGear
+	  CM4002 Secure Access Server. See http://www.opengear.com for
+	  more details.
+
+config MACH_CM4008
+	bool "OpenGear CM4008"
+	select MIGHT_HAVE_PCI
+	help
+	  Say 'Y' here if you want your kernel to support the OpenGear
+	  CM4008 Console Server. See http://www.opengear.com for more
+	  details.
+
+config MACH_CM41xx
+	bool "OpenGear CM41xx"
+	select MIGHT_HAVE_PCI
+	help
+	  Say 'Y' here if you want your kernel to support the OpenGear
+	  CM4016 or CM4048 Console Servers. See http://www.opengear.com for
+	  more details.
+
+config MACH_IM4004
+	bool "OpenGear IM4004"
+	select MIGHT_HAVE_PCI
+	help
+	  Say 'Y' here if you want your kernel to support the OpenGear
+	  IM4004 Secure Access Server. See http://www.opengear.com for
+	  more details.
+
+config MACH_IM42xx
+	bool "OpenGear IM42xx"
+	select MIGHT_HAVE_PCI
+	help
+	  Say 'Y' here if you want your kernel to support the OpenGear
+	  IM4216 or IM4248 Console Servers. See http://www.opengear.com for
+	  more details.
+
 endmenu
 
 endif
diff --git a/arch/arm/mach-ks8695/Makefile b/arch/arm/mach-ks8695/Makefile
index 853efd9..e370caf 100644
--- a/arch/arm/mach-ks8695/Makefile
+++ b/arch/arm/mach-ks8695/Makefile
@@ -11,10 +11,15 @@ obj-				:=
 # PCI support is optional
 obj-$(CONFIG_PCI)		+= pci.o
 
-# LEDs
-obj-$(CONFIG_LEDS)		+= leds.o
-
 # Board-specific support
 obj-$(CONFIG_MACH_KS8695)	+= board-micrel.o
 obj-$(CONFIG_MACH_DSM320)	+= board-dsm320.o
 obj-$(CONFIG_MACH_ACS5K)	+= board-acs5k.o
+obj-$(CONFIG_MACH_LITE300)	+= board-sg.o
+obj-$(CONFIG_MACH_SG310)	+= board-sg.o
+obj-$(CONFIG_MACH_SE4200)	+= board-sg.o
+obj-$(CONFIG_MACH_CM4002)	+= board-og.o
+obj-$(CONFIG_MACH_CM4008)	+= board-og.o
+obj-$(CONFIG_MACH_CM41xx)	+= board-og.o
+obj-$(CONFIG_MACH_IM4004)	+= board-og.o
+obj-$(CONFIG_MACH_IM42xx)	+= board-og.o
diff --git a/arch/arm/mach-ks8695/board-og.c b/arch/arm/mach-ks8695/board-og.c
new file mode 100644
index 0000000..1623ba4
--- /dev/null
+++ b/arch/arm/mach-ks8695/board-og.c
@@ -0,0 +1,199 @@
+/*
+ * board-og.c -- support for the OpenGear KS8695 based boards.
+ *
+ * This program is free software; you can 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/delay.h>
+#include <linux/platform_device.h>
+#include <linux/serial_8250.h>
+#include <linux/gpio.h>
+#include <linux/irq.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <mach/devices.h>
+#include <mach/regs-gpio.h>
+#include <mach/gpio-ks8695.h>
+#include "generic.h"
+
+static int og_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+{
+	if (machine_is_im4004() && (slot == 8))
+		return KS8695_IRQ_EXTERN1;
+	return KS8695_IRQ_EXTERN0;
+}
+
+static struct ks8695_pci_cfg __initdata og_pci = {
+	.mode		= KS8695_MODE_PCI,
+	.map_irq	= og_pci_map_irq,
+};
+
+static void __init og_register_pci(void)
+{
+	/* Initialize the GPIO lines for interrupt mode */
+	ks8695_gpio_interrupt(KS8695_GPIO_0, IRQ_TYPE_LEVEL_LOW);
+
+	/* Cardbus Slot */
+	if (machine_is_im4004())
+		ks8695_gpio_interrupt(KS8695_GPIO_1, IRQ_TYPE_LEVEL_LOW);
+
+	ks8695_init_pci(&og_pci);
+}
+
+/*
+ * The PCI bus reset is driven by a dedicated GPIO line. Toggle it here
+ * and bring the PCI bus out of reset.
+ */
+static void __init og_pci_bus_reset(void)
+{
+	unsigned int rstline = 1;
+
+	/* Some boards use a different GPIO as the PCI reset line */
+	if (machine_is_im4004())
+		rstline = 2;
+	else if (machine_is_im42xx())
+		rstline = 0;
+
+	gpio_request(rstline, "PCI reset");
+	gpio_direction_output(rstline, 0);
+
+	/* Drive a reset on the PCI reset line */
+	gpio_set_value(rstline, 1);
+	gpio_set_value(rstline, 0);
+	mdelay(100);
+	gpio_set_value(rstline, 1);
+	mdelay(100);
+}
+
+/*
+ * Direct connect serial ports (non-PCI that is).
+ */
+#define	S8250_PHYS	0x03800000
+#define	S8250_VIRT	0xf4000000
+#define	S8250_SIZE	0x00100000
+
+static struct __initdata map_desc og_io_desc[] = {
+	{
+		.virtual	= S8250_VIRT,
+		.pfn		= __phys_to_pfn(S8250_PHYS),
+		.length		= S8250_SIZE,
+		.type		= MT_DEVICE,
+	}
+};
+
+static struct resource og_uart_resources[] = {
+	{
+		.start		= S8250_VIRT,
+		.end		= S8250_VIRT + S8250_SIZE,
+		.flags		= IORESOURCE_MEM
+	},
+};
+
+static struct plat_serial8250_port og_uart_data[] = {
+	{
+		.mapbase	= S8250_VIRT,
+		.membase	= (char *) S8250_VIRT,
+		.irq		= 3,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+		.iotype		= UPIO_MEM,
+		.regshift	= 2,
+		.uartclk	= 115200 * 16,
+	},
+	{ },
+};
+
+static struct platform_device og_uart = {
+	.name			= "serial8250",
+	.id			= 0,
+	.dev.platform_data	= og_uart_data,
+	.num_resources		= 1,
+	.resource		= og_uart_resources
+};
+
+static struct platform_device *og_devices[] __initdata = {
+	&og_uart
+};
+
+static void __init og_init(void)
+{
+	ks8695_register_gpios();
+
+	if (machine_is_cm4002()) {
+		ks8695_gpio_interrupt(KS8695_GPIO_1, IRQ_TYPE_LEVEL_HIGH);
+		iotable_init(og_io_desc, ARRAY_SIZE(og_io_desc));
+		platform_add_devices(og_devices, ARRAY_SIZE(og_devices));
+	} else {
+		og_pci_bus_reset();
+		og_register_pci();
+	}
+
+	ks8695_add_device_lan();
+	ks8695_add_device_wan();
+}
+
+#ifdef CONFIG_MACH_CM4002
+MACHINE_START(CM4002, "OpenGear/CM4002")
+	/* OpenGear Inc. */
+	.atag_offset	= 0x100,
+	.map_io		= ks8695_map_io,
+	.init_irq	= ks8695_init_irq,
+	.init_machine	= og_init,
+	.timer		= &ks8695_timer,
+	.restart        = ks8695_restart,
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_CM4008
+MACHINE_START(CM4008, "OpenGear/CM4008")
+	/* OpenGear Inc. */
+	.atag_offset	= 0x100,
+	.map_io		= ks8695_map_io,
+	.init_irq	= ks8695_init_irq,
+	.init_machine	= og_init,
+	.timer		= &ks8695_timer,
+	.restart        = ks8695_restart,
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_CM41xx
+MACHINE_START(CM41XX, "OpenGear/CM41xx")
+	/* OpenGear Inc. */
+	.atag_offset	= 0x100,
+	.map_io		= ks8695_map_io,
+	.init_irq	= ks8695_init_irq,
+	.init_machine	= og_init,
+	.timer		= &ks8695_timer,
+	.restart        = ks8695_restart,
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_IM4004
+MACHINE_START(IM4004, "OpenGear/IM4004")
+	/* OpenGear Inc. */
+	.atag_offset	= 0x100,
+	.map_io		= ks8695_map_io,
+	.init_irq	= ks8695_init_irq,
+	.init_machine	= og_init,
+	.timer		= &ks8695_timer,
+	.restart        = ks8695_restart,
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_IM42xx
+MACHINE_START(IM42XX, "OpenGear/IM42xx")
+	/* OpenGear Inc. */
+	.atag_offset	= 0x100,
+	.map_io		= ks8695_map_io,
+	.init_irq	= ks8695_init_irq,
+	.init_machine	= og_init,
+	.timer		= &ks8695_timer,
+	.restart        = ks8695_restart,
+MACHINE_END
+#endif
diff --git a/arch/arm/mach-ks8695/board-sg.c b/arch/arm/mach-ks8695/board-sg.c
new file mode 100644
index 0000000..f35b98b
--- /dev/null
+++ b/arch/arm/mach-ks8695/board-sg.c
@@ -0,0 +1,121 @@
+/*
+ * board-sg.c -- support for the SnapGear KS8695 based boards
+ *
+ * This program is free software; you can 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/init.h>
+#include <linux/platform_device.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 <mach/devices.h>
+#include "generic.h"
+
+/*
+ * The SG310 machine type is fitted with a conventional 8MB Strataflash
+ * device. Define its partitioning.
+ */
+#define	FL_BASE		0x02000000
+#define	FL_SIZE		SZ_8M
+
+static struct mtd_partition sg_mtd_partitions[] = {
+	[0] = {
+		.name	= "SnapGear Boot Loader",
+		.size	= SZ_128K,
+	},
+	[1] = {
+		.name	= "SnapGear non-volatile configuration",
+		.size	= SZ_512K,
+		.offset	= SZ_256K,
+	},
+	[2] = {
+		.name	= "SnapGear image",
+		.offset	= SZ_512K + SZ_256K,
+	},
+	[3] = {
+		.name	= "SnapGear StrataFlash",
+	},
+	[4] = {
+		.name	= "SnapGear Boot Tags",
+		.size	= SZ_128K,
+		.offset	= SZ_128K,
+	},
+};
+
+static struct physmap_flash_data sg_mtd_pdata = {
+	.width		= 1,
+	.nr_parts	= ARRAY_SIZE(sg_mtd_partitions),
+	.parts		= sg_mtd_partitions,
+};
+
+
+static struct resource sg_mtd_resource[] = {
+	[0] = {
+		.start = FL_BASE,
+		.end   = FL_BASE + FL_SIZE - 1,
+		.flags = IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device sg_mtd_device = {
+	.name		= "physmap-flash",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(sg_mtd_resource),
+	.resource	= sg_mtd_resource,
+	.dev		= {
+		.platform_data = &sg_mtd_pdata,
+	},
+};
+
+static void __init sg_init(void)
+{
+	ks8695_add_device_lan();
+	ks8695_add_device_wan();
+
+	if (machine_is_sg310())
+		platform_device_register(&sg_mtd_device);
+}
+
+#ifdef CONFIG_MACH_LITE300
+MACHINE_START(LITE300, "SecureComputing/SG300")
+	/* SnapGear */
+	.atag_offset	= 0x100,
+	.map_io		= ks8695_map_io,
+	.init_irq	= ks8695_init_irq,
+	.init_machine	= sg_init,
+	.timer		= &ks8695_timer,
+	.restart	= ks8695_restart,
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_SG310
+MACHINE_START(SG310, "McAfee/SG310")
+	/* SnapGear */
+	.atag_offset	= 0x100,
+	.map_io		= ks8695_map_io,
+	.init_irq	= ks8695_init_irq,
+	.init_machine	= sg_init,
+	.timer		= &ks8695_timer,
+	.restart	= ks8695_restart,
+MACHINE_END
+#endif
+
+#ifdef CONFIG_MACH_SE4200
+MACHINE_START(SE4200, "SecureComputing/SE4200")
+	/* SnapGear */
+	.atag_offset	= 0x100,
+	.map_io		= ks8695_map_io,
+	.init_irq	= ks8695_init_irq,
+	.init_machine	= sg_init,
+	.timer		= &ks8695_timer,
+	.restart	= ks8695_restart,
+MACHINE_END
+#endif
diff --git a/arch/arm/mach-ks8695/cpu.c b/arch/arm/mach-ks8695/cpu.c
index 7f3f240..ddb2422 100644
--- a/arch/arm/mach-ks8695/cpu.c
+++ b/arch/arm/mach-ks8695/cpu.c
@@ -36,7 +36,7 @@
 
 static struct __initdata map_desc ks8695_io_desc[] = {
 	{
-		.virtual	= KS8695_IO_VA,
+		.virtual	= (unsigned long)KS8695_IO_VA,
 		.pfn		= __phys_to_pfn(KS8695_IO_PA),
 		.length		= KS8695_IO_SIZE,
 		.type		= MT_DEVICE,
diff --git a/arch/arm/mach-ks8695/devices.c b/arch/arm/mach-ks8695/devices.c
index 73bd638..47399bc 100644
--- a/arch/arm/mach-ks8695/devices.c
+++ b/arch/arm/mach-ks8695/devices.c
@@ -182,27 +182,6 @@ static void __init ks8695_add_device_watchdog(void)
 }
 
 
-/* --------------------------------------------------------------------
- *  LEDs
- * -------------------------------------------------------------------- */
-
-#if defined(CONFIG_LEDS)
-short ks8695_leds_cpu = -1;
-short ks8695_leds_timer = -1;
-
-void __init ks8695_init_leds(u8 cpu_led, u8 timer_led)
-{
-	/* Enable GPIO to access the LEDs */
-	gpio_direction_output(cpu_led, 1);
-	gpio_direction_output(timer_led, 1);
-
-	ks8695_leds_cpu	  = cpu_led;
-	ks8695_leds_timer = timer_led;
-}
-#else
-void __init ks8695_init_leds(u8 cpu_led, u8 timer_led) {}
-#endif
-
 /* -------------------------------------------------------------------- */
 
 /*
diff --git a/arch/arm/mach-ks8695/include/mach/devices.h b/arch/arm/mach-ks8695/include/mach/devices.h
index 85a3c9a..1e6594a 100644
--- a/arch/arm/mach-ks8695/include/mach/devices.h
+++ b/arch/arm/mach-ks8695/include/mach/devices.h
@@ -18,11 +18,6 @@ extern void __init ks8695_add_device_wan(void);
 extern void __init ks8695_add_device_lan(void);
 extern void __init ks8695_add_device_hpna(void);
 
- /* LEDs */
-extern short ks8695_leds_cpu;
-extern short ks8695_leds_timer;
-extern void __init ks8695_init_leds(u8 cpu_led, u8 timer_led);
-
  /* PCI */
 #define KS8695_MODE_PCI		0
 #define KS8695_MODE_MINIPCI	1
diff --git a/arch/arm/mach-ks8695/include/mach/hardware.h b/arch/arm/mach-ks8695/include/mach/hardware.h
index 5e0c388..5090338 100644
--- a/arch/arm/mach-ks8695/include/mach/hardware.h
+++ b/arch/arm/mach-ks8695/include/mach/hardware.h
@@ -33,7 +33,7 @@
  * head debug code as the initial MMU setup only deals in L1 sections.
  */
 #define KS8695_IO_PA		0x03F00000
-#define KS8695_IO_VA		0xF0000000
+#define KS8695_IO_VA		IOMEM(0xF0000000)
 #define KS8695_IO_SIZE		SZ_1M
 
 #define KS8695_PCIMEM_PA	0x60000000
diff --git a/arch/arm/mach-ks8695/include/mach/regs-timer.h b/arch/arm/mach-ks8695/include/mach/regs-timer.h
deleted file mode 100644
index e620cda..0000000
--- a/arch/arm/mach-ks8695/include/mach/regs-timer.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * arch/arm/mach-ks8695/include/mach/regs-timer.h
- *
- * Copyright (C) 2006 Ben Dooks <ben@simtec.co.uk>
- * Copyright (C) 2006 Simtec Electronics
- *
- * KS8695 - Timer registers and bit definitions.
- *
- * 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 KS8695_TIMER_H
-#define KS8695_TIMER_H
-
-#define KS8695_TMR_OFFSET	(0xF0000 + 0xE400)
-#define KS8695_TMR_VA		(KS8695_IO_VA + KS8695_TMR_OFFSET)
-#define KS8695_TMR_PA		(KS8695_IO_PA + KS8695_TMR_OFFSET)
-
-
-/*
- * Timer registers
- */
-#define KS8695_TMCON		(0x00)		/* Timer Control Register */
-#define KS8695_T1TC		(0x04)		/* Timer 1 Timeout Count Register */
-#define KS8695_T0TC		(0x08)		/* Timer 0 Timeout Count Register */
-#define KS8695_T1PD		(0x0C)		/* Timer 1 Pulse Count Register */
-#define KS8695_T0PD		(0x10)		/* Timer 0 Pulse Count Register */
-
-
-/* Timer Control Register */
-#define TMCON_T1EN		(1 << 1)	/* Timer 1 Enable */
-#define TMCON_T0EN		(1 << 0)	/* Timer 0 Enable */
-
-/* Timer0 Timeout Counter Register */
-#define T0TC_WATCHDOG		(0xff)		/* Enable watchdog mode */
-
-
-#endif
diff --git a/arch/arm/mach-ks8695/include/mach/uncompress.h b/arch/arm/mach-ks8695/include/mach/uncompress.h
index 9495cb4..8879d61 100644
--- a/arch/arm/mach-ks8695/include/mach/uncompress.h
+++ b/arch/arm/mach-ks8695/include/mach/uncompress.h
@@ -19,15 +19,15 @@
 
 static void putc(char c)
 {
-	while (!(__raw_readl(KS8695_UART_PA + KS8695_URLS) & URLS_URTHRE))
+	while (!(__raw_readl((void __iomem*)KS8695_UART_PA + KS8695_URLS) & URLS_URTHRE))
 		barrier();
 
-	__raw_writel(c, KS8695_UART_PA + KS8695_URTH);
+	__raw_writel(c, (void __iomem*)KS8695_UART_PA + KS8695_URTH);
 }
 
 static inline void flush(void)
 {
-	while (!(__raw_readl(KS8695_UART_PA + KS8695_URLS) & URLS_URTE))
+	while (!(__raw_readl((void __iomem*)KS8695_UART_PA + KS8695_URLS) & URLS_URTE))
 		barrier();
 }
 
diff --git a/arch/arm/mach-ks8695/leds.c b/arch/arm/mach-ks8695/leds.c
deleted file mode 100644
index 4bd7075..0000000
--- a/arch/arm/mach-ks8695/leds.c
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * LED driver for KS8695-based boards.
- *
- * Copyright (C) Andrew Victor
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <linux/gpio.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-
-#include <asm/leds.h>
-#include <mach/devices.h>
-
-
-static inline void ks8695_led_on(unsigned int led)
-{
-	gpio_set_value(led, 0);
-}
-
-static inline void ks8695_led_off(unsigned int led)
-{
-	gpio_set_value(led, 1);
-}
-
-static inline void ks8695_led_toggle(unsigned int led)
-{
-	unsigned long is_off = gpio_get_value(led);
-	if (is_off)
-		ks8695_led_on(led);
-	else
-		ks8695_led_off(led);
-}
-
-
-/*
- * Handle LED events.
- */
-static void ks8695_leds_event(led_event_t evt)
-{
-	unsigned long flags;
-
-	local_irq_save(flags);
-
-	switch(evt) {
-	case led_start:		/* System startup */
-		ks8695_led_on(ks8695_leds_cpu);
-		break;
-
-	case led_stop:		/* System stop / suspend */
-		ks8695_led_off(ks8695_leds_cpu);
-		break;
-
-#ifdef CONFIG_LEDS_TIMER
-	case led_timer:		/* Every 50 timer ticks */
-		ks8695_led_toggle(ks8695_leds_timer);
-		break;
-#endif
-
-#ifdef CONFIG_LEDS_CPU
-	case led_idle_start:	/* Entering idle state */
-		ks8695_led_off(ks8695_leds_cpu);
-		break;
-
-	case led_idle_end:	/* Exit idle state */
-		ks8695_led_on(ks8695_leds_cpu);
-		break;
-#endif
-
-	default:
-		break;
-	}
-
-	local_irq_restore(flags);
-}
-
-
-static int __init leds_init(void)
-{
-	if ((ks8695_leds_timer == -1) || (ks8695_leds_cpu == -1))
-		return -ENODEV;
-
-	leds_event = ks8695_leds_event;
-
-	leds_event(led_start);
-	return 0;
-}
-
-__initcall(leds_init);
diff --git a/arch/arm/mach-ks8695/time.c b/arch/arm/mach-ks8695/time.c
index ec783a3..46c84bc 100644
--- a/arch/arm/mach-ks8695/time.c
+++ b/arch/arm/mach-ks8695/time.c
@@ -25,53 +25,98 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/io.h>
+#include <linux/clockchips.h>
 
 #include <asm/mach/time.h>
 #include <asm/system_misc.h>
 
-#include <mach/regs-timer.h>
 #include <mach/regs-irq.h>
 
 #include "generic.h"
 
+#define KS8695_TMR_OFFSET	(0xF0000 + 0xE400)
+#define KS8695_TMR_VA		(KS8695_IO_VA + KS8695_TMR_OFFSET)
+#define KS8695_TMR_PA		(KS8695_IO_PA + KS8695_TMR_OFFSET)
+
 /*
- * Returns number of ms since last clock interrupt.  Note that interrupts
- * will have been disabled by do_gettimeoffset()
+ * Timer registers
  */
-static unsigned long ks8695_gettimeoffset (void)
+#define KS8695_TMCON		(0x00)		/* Timer Control Register */
+#define KS8695_T1TC		(0x04)		/* Timer 1 Timeout Count Register */
+#define KS8695_T0TC		(0x08)		/* Timer 0 Timeout Count Register */
+#define KS8695_T1PD		(0x0C)		/* Timer 1 Pulse Count Register */
+#define KS8695_T0PD		(0x10)		/* Timer 0 Pulse Count Register */
+
+/* Timer Control Register */
+#define TMCON_T1EN		(1 << 1)	/* Timer 1 Enable */
+#define TMCON_T0EN		(1 << 0)	/* Timer 0 Enable */
+
+/* Timer0 Timeout Counter Register */
+#define T0TC_WATCHDOG		(0xff)		/* Enable watchdog mode */
+
+static void ks8695_set_mode(enum clock_event_mode mode,
+			    struct clock_event_device *evt)
 {
-	unsigned long elapsed, tick2, intpending;
+	u32 tmcon;
 
-	/*
-	 * Get the current number of ticks.  Note that there is a race
-	 * condition between us reading the timer and checking for an
-	 * interrupt.  We solve this by ensuring that the counter has not
-	 * reloaded between our two reads.
-	 */
-	elapsed = __raw_readl(KS8695_TMR_VA + KS8695_T1TC) + __raw_readl(KS8695_TMR_VA + KS8695_T1PD);
-	do {
-		tick2 = elapsed;
-		intpending = __raw_readl(KS8695_IRQ_VA + KS8695_INTST) & (1 << KS8695_IRQ_TIMER1);
-		elapsed = __raw_readl(KS8695_TMR_VA + KS8695_T1TC) + __raw_readl(KS8695_TMR_VA + KS8695_T1PD);
-	} while (elapsed > tick2);
-
-	/* Convert to number of ticks expired (not remaining) */
-	elapsed = (CLOCK_TICK_RATE / HZ) - elapsed;
-
-	/* Is interrupt pending?  If so, then timer has been reloaded already. */
-	if (intpending)
-		elapsed += (CLOCK_TICK_RATE / HZ);
-
-	/* Convert ticks to usecs */
-	return (unsigned long)(elapsed * (tick_nsec / 1000)) / LATCH;
+	if (mode == CLOCK_EVT_FEAT_PERIODIC) {
+		u32 rate = DIV_ROUND_CLOSEST(KS8695_CLOCK_RATE, HZ);
+		u32 half = DIV_ROUND_CLOSEST(rate, 2);
+
+		/* Disable timer 1 */
+		tmcon = readl_relaxed(KS8695_TMR_VA + KS8695_TMCON);
+		tmcon &= ~TMCON_T1EN;
+		writel_relaxed(tmcon, KS8695_TMR_VA + KS8695_TMCON);
+
+		/* Both registers need to count down */
+		writel_relaxed(half, KS8695_TMR_VA + KS8695_T1TC);
+		writel_relaxed(half, KS8695_TMR_VA + KS8695_T1PD);
+
+		/* Re-enable timer1 */
+		tmcon |= TMCON_T1EN;
+		writel_relaxed(tmcon, KS8695_TMR_VA + KS8695_TMCON);
+	}
 }
 
+static int ks8695_set_next_event(unsigned long cycles,
+				 struct clock_event_device *evt)
+
+{
+	u32 half = DIV_ROUND_CLOSEST(cycles, 2);
+	u32 tmcon;
+
+	/* Disable timer 1 */
+	tmcon = readl_relaxed(KS8695_TMR_VA + KS8695_TMCON);
+	tmcon &= ~TMCON_T1EN;
+	writel_relaxed(tmcon, KS8695_TMR_VA + KS8695_TMCON);
+
+	/* Both registers need to count down */
+	writel_relaxed(half, KS8695_TMR_VA + KS8695_T1TC);
+	writel_relaxed(half, KS8695_TMR_VA + KS8695_T1PD);
+
+	/* Re-enable timer1 */
+	tmcon |= TMCON_T1EN;
+	writel_relaxed(tmcon, KS8695_TMR_VA + KS8695_TMCON);
+
+	return 0;
+}
+
+static struct clock_event_device clockevent_ks8695 = {
+	.name		= "ks8695_t1tc",
+	.rating		= 300, /* Reasonably fast and accurate clock event */
+	.features	= CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC,
+	.set_next_event	= ks8695_set_next_event,
+	.set_mode	= ks8695_set_mode,
+};
+
 /*
  * IRQ handler for the timer.
  */
 static irqreturn_t ks8695_timer_interrupt(int irq, void *dev_id)
 {
-	timer_tick();
+	struct clock_event_device *evt = &clockevent_ks8695;
+
+	evt->event_handler(evt);
 	return IRQ_HANDLED;
 }
 
@@ -83,18 +128,22 @@ static struct irqaction ks8695_timer_irq = {
 
 static void ks8695_timer_setup(void)
 {
-	unsigned long tmout = CLOCK_TICK_RATE / HZ;
 	unsigned long tmcon;
 
-	/* disable timer1 */
-	tmcon = __raw_readl(KS8695_TMR_VA + KS8695_TMCON);
-	__raw_writel(tmcon & ~TMCON_T1EN, KS8695_TMR_VA + KS8695_TMCON);
-
-	__raw_writel(tmout / 2, KS8695_TMR_VA + KS8695_T1TC);
-	__raw_writel(tmout / 2, KS8695_TMR_VA + KS8695_T1PD);
+	/* Disable timer 0 and 1 */
+	tmcon = readl_relaxed(KS8695_TMR_VA + KS8695_TMCON);
+	tmcon &= ~TMCON_T0EN;
+	tmcon &= ~TMCON_T1EN;
+	writel_relaxed(tmcon, KS8695_TMR_VA + KS8695_TMCON);
 
-	/* re-enable timer1 */
-	__raw_writel(tmcon | TMCON_T1EN, KS8695_TMR_VA + KS8695_TMCON);
+	/*
+	 * Use timer 1 to fire IRQs on the timeline, minimum 2 cycles
+	 * (one on each counter) maximum 2*2^32, but the API will only
+	 * accept up to a 32bit full word (0xFFFFFFFFU).
+	 */
+	clockevents_config_and_register(&clockevent_ks8695,
+					KS8695_CLOCK_RATE, 2,
+					0xFFFFFFFFU);
 }
 
 static void __init ks8695_timer_init (void)
@@ -107,8 +156,6 @@ static void __init ks8695_timer_init (void)
 
 struct sys_timer ks8695_timer = {
 	.init		= ks8695_timer_init,
-	.offset		= ks8695_gettimeoffset,
-	.resume		= ks8695_timer_setup,
 };
 
 void ks8695_restart(char mode, const char *cmd)
@@ -119,12 +166,12 @@ void ks8695_restart(char mode, const char *cmd)
 		soft_restart(0);
 
 	/* disable timer0 */
-	reg = __raw_readl(KS8695_TMR_VA + KS8695_TMCON);
-	__raw_writel(reg & ~TMCON_T0EN, KS8695_TMR_VA + KS8695_TMCON);
+	reg = readl_relaxed(KS8695_TMR_VA + KS8695_TMCON);
+	writel_relaxed(reg & ~TMCON_T0EN, KS8695_TMR_VA + KS8695_TMCON);
 
 	/* enable watchdog mode */
-	__raw_writel((10 << 8) | T0TC_WATCHDOG, KS8695_TMR_VA + KS8695_T0TC);
+	writel_relaxed((10 << 8) | T0TC_WATCHDOG, KS8695_TMR_VA + KS8695_T0TC);
 
 	/* re-enable timer0 */
-	__raw_writel(reg | TMCON_T0EN, KS8695_TMR_VA + KS8695_TMCON);
+	writel_relaxed(reg | TMCON_T0EN, KS8695_TMR_VA + KS8695_TMCON);
 }
diff --git a/arch/arm/mach-lpc32xx/Makefile.boot b/arch/arm/mach-lpc32xx/Makefile.boot
index 697323b..d7392a4 100644
--- a/arch/arm/mach-lpc32xx/Makefile.boot
+++ b/arch/arm/mach-lpc32xx/Makefile.boot
@@ -1,5 +1,3 @@
    zreladdr-y	+= 0x80008000
 params_phys-y	:= 0x80000100
 initrd_phys-y	:= 0x82000000
-
-dtb-$(CONFIG_ARCH_LPC32XX) += ea3250.dtb phy3250.dtb
diff --git a/arch/arm/mach-lpc32xx/common.c b/arch/arm/mach-lpc32xx/common.c
index a48dc2d..0d4db8c 100644
--- a/arch/arm/mach-lpc32xx/common.c
+++ b/arch/arm/mach-lpc32xx/common.c
@@ -177,25 +177,25 @@ u32 clk_get_pclk_div(void)
 
 static struct map_desc lpc32xx_io_desc[] __initdata = {
 	{
-		.virtual	= IO_ADDRESS(LPC32XX_AHB0_START),
+		.virtual	= (unsigned long)IO_ADDRESS(LPC32XX_AHB0_START),
 		.pfn		= __phys_to_pfn(LPC32XX_AHB0_START),
 		.length		= LPC32XX_AHB0_SIZE,
 		.type		= MT_DEVICE
 	},
 	{
-		.virtual	= IO_ADDRESS(LPC32XX_AHB1_START),
+		.virtual	= (unsigned long)IO_ADDRESS(LPC32XX_AHB1_START),
 		.pfn		= __phys_to_pfn(LPC32XX_AHB1_START),
 		.length		= LPC32XX_AHB1_SIZE,
 		.type		= MT_DEVICE
 	},
 	{
-		.virtual	= IO_ADDRESS(LPC32XX_FABAPB_START),
+		.virtual	= (unsigned long)IO_ADDRESS(LPC32XX_FABAPB_START),
 		.pfn		= __phys_to_pfn(LPC32XX_FABAPB_START),
 		.length		= LPC32XX_FABAPB_SIZE,
 		.type		= MT_DEVICE
 	},
 	{
-		.virtual	= IO_ADDRESS(LPC32XX_IRAM_BASE),
+		.virtual	= (unsigned long)IO_ADDRESS(LPC32XX_IRAM_BASE),
 		.pfn		= __phys_to_pfn(LPC32XX_IRAM_BASE),
 		.length		= (LPC32XX_IRAM_BANK_SIZE * 2),
 		.type		= MT_DEVICE
diff --git a/arch/arm/mach-lpc32xx/include/mach/hardware.h b/arch/arm/mach-lpc32xx/include/mach/hardware.h
index 33e1dde..69065de 100644
--- a/arch/arm/mach-lpc32xx/include/mach/hardware.h
+++ b/arch/arm/mach-lpc32xx/include/mach/hardware.h
@@ -25,7 +25,7 @@
 /*
  * This macro relies on fact that for all HW i/o addresses bits 20-23 are 0
  */
-#define IO_ADDRESS(x)	(((((x) & 0xff000000) >> 4) | ((x) & 0xfffff)) |\
+#define IO_ADDRESS(x)	IOMEM(((((x) & 0xff000000) >> 4) | ((x) & 0xfffff)) |\
 			 IO_BASE)
 
 #define io_p2v(x)	((void __iomem *) (unsigned long) IO_ADDRESS(x))
diff --git a/arch/arm/mach-lpc32xx/irq.c b/arch/arm/mach-lpc32xx/irq.c
index 5b1cc35..3c63327 100644
--- a/arch/arm/mach-lpc32xx/irq.c
+++ b/arch/arm/mach-lpc32xx/irq.c
@@ -283,21 +283,25 @@ static int lpc32xx_set_irq_type(struct irq_data *d, unsigned int type)
 	case IRQ_TYPE_EDGE_RISING:
 		/* Rising edge sensitive */
 		__lpc32xx_set_irq_type(d->hwirq, 1, 1);
+		__irq_set_handler_locked(d->hwirq, handle_edge_irq);
 		break;
 
 	case IRQ_TYPE_EDGE_FALLING:
 		/* Falling edge sensitive */
 		__lpc32xx_set_irq_type(d->hwirq, 0, 1);
+		__irq_set_handler_locked(d->hwirq, handle_edge_irq);
 		break;
 
 	case IRQ_TYPE_LEVEL_LOW:
 		/* Low level sensitive */
 		__lpc32xx_set_irq_type(d->hwirq, 0, 0);
+		__irq_set_handler_locked(d->hwirq, handle_level_irq);
 		break;
 
 	case IRQ_TYPE_LEVEL_HIGH:
 		/* High level sensitive */
 		__lpc32xx_set_irq_type(d->hwirq, 1, 0);
+		__irq_set_handler_locked(d->hwirq, handle_level_irq);
 		break;
 
 	/* Other modes are not supported */
@@ -305,9 +309,6 @@ static int lpc32xx_set_irq_type(struct irq_data *d, unsigned int type)
 		return -EINVAL;
 	}
 
-	/* Ok to use the level handler for all types */
-	irq_set_handler(d->hwirq, handle_level_irq);
-
 	return 0;
 }
 
diff --git a/arch/arm/mach-lpc32xx/phy3250.c b/arch/arm/mach-lpc32xx/phy3250.c
index b07dcc9..8f2a2f8 100644
--- a/arch/arm/mach-lpc32xx/phy3250.c
+++ b/arch/arm/mach-lpc32xx/phy3250.c
@@ -37,6 +37,8 @@
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/clk.h>
+#include <linux/mtd/lpc32xx_slc.h>
+#include <linux/mtd/lpc32xx_mlc.h>
 
 #include <asm/setup.h>
 #include <asm/mach-types.h>
@@ -223,6 +225,14 @@ static struct mmci_platform_data lpc32xx_mmci_data = {
 	 * gather, and the MMCI driver doesn't do it this way */
 };
 
+static struct lpc32xx_slc_platform_data lpc32xx_slc_data = {
+	.dma_filter = pl08x_filter_id,
+};
+
+static struct lpc32xx_mlc_platform_data lpc32xx_mlc_data = {
+	.dma_filter = pl08x_filter_id,
+};
+
 static const struct of_dev_auxdata lpc32xx_auxdata_lookup[] __initconst = {
 	OF_DEV_AUXDATA("arm,pl022", 0x20084000, "dev:ssp0", &lpc32xx_ssp0_data),
 	OF_DEV_AUXDATA("arm,pl022", 0x2008C000, "dev:ssp1", &lpc32xx_ssp1_data),
@@ -230,6 +240,10 @@ static const struct of_dev_auxdata lpc32xx_auxdata_lookup[] __initconst = {
 	OF_DEV_AUXDATA("arm,pl080", 0x31000000, "pl08xdmac", &pl08x_pd),
 	OF_DEV_AUXDATA("arm,pl18x", 0x20098000, "20098000.sd",
 		       &lpc32xx_mmci_data),
+	OF_DEV_AUXDATA("nxp,lpc3220-slc", 0x20020000, "20020000.flash",
+		       &lpc32xx_slc_data),
+	OF_DEV_AUXDATA("nxp,lpc3220-mlc", 0x200a8000, "200a8000.flash",
+		       &lpc32xx_mlc_data),
 	{ }
 };
 
@@ -253,12 +267,6 @@ static void __init lpc3250_machine_init(void)
 
 	of_platform_populate(NULL, of_default_bus_match_table,
 			     lpc32xx_auxdata_lookup, NULL);
-
-	/* Register GPIOs used on this board */
-	if (gpio_request(MMC_PWR_ENABLE_GPIO, "mmc_power_en"))
-		pr_err("Error requesting gpio %u", MMC_PWR_ENABLE_GPIO);
-	else if (gpio_direction_output(MMC_PWR_ENABLE_GPIO, 1))
-		pr_err("Error setting gpio %u to output", MMC_PWR_ENABLE_GPIO);
 }
 
 static char const *lpc32xx_dt_compat[] __initdata = {
diff --git a/arch/arm/mach-mmp/Kconfig b/arch/arm/mach-mmp/Kconfig
index 7fddd01..d697d07 100644
--- a/arch/arm/mach-mmp/Kconfig
+++ b/arch/arm/mach-mmp/Kconfig
@@ -108,18 +108,21 @@ endmenu
 config CPU_PXA168
 	bool
 	select CPU_MOHAWK
+	select COMMON_CLK
 	help
 	  Select code specific to PXA168
 
 config CPU_PXA910
 	bool
 	select CPU_MOHAWK
+	select COMMON_CLK
 	help
 	  Select code specific to PXA910
 
 config CPU_MMP2
 	bool
 	select CPU_PJ4
+	select COMMON_CLK
 	help
 	  Select code specific to MMP2. MMP2 is ARMv7 compatible.
 
diff --git a/arch/arm/mach-mmp/Makefile b/arch/arm/mach-mmp/Makefile
index b786f7e..095c155 100644
--- a/arch/arm/mach-mmp/Makefile
+++ b/arch/arm/mach-mmp/Makefile
@@ -2,13 +2,19 @@
 # Makefile for Marvell's PXA168 processors line
 #
 
-obj-y				+= common.o clock.o devices.o time.o irq.o
+obj-y				+= common.o devices.o time.o irq.o
 
 # SoC support
 obj-$(CONFIG_CPU_PXA168)	+= pxa168.o
 obj-$(CONFIG_CPU_PXA910)	+= pxa910.o
 obj-$(CONFIG_CPU_MMP2)		+= mmp2.o sram.o
 
+ifeq ($(CONFIG_COMMON_CLK), )
+obj-y				+= clock.o
+obj-$(CONFIG_CPU_PXA168)	+= clock-pxa168.o
+obj-$(CONFIG_CPU_PXA910)	+= clock-pxa910.o
+obj-$(CONFIG_CPU_MMP2)		+= clock-mmp2.o
+endif
 ifeq ($(CONFIG_PM),y)
 obj-$(CONFIG_CPU_PXA910)	+= pm-pxa910.o
 obj-$(CONFIG_CPU_MMP2)		+= pm-mmp2.o
diff --git a/arch/arm/mach-mmp/aspenite.c b/arch/arm/mach-mmp/aspenite.c
index 223090b..e5dba9c 100644
--- a/arch/arm/mach-mmp/aspenite.c
+++ b/arch/arm/mach-mmp/aspenite.c
@@ -27,7 +27,7 @@
 #include <mach/irqs.h>
 #include <video/pxa168fb.h>
 #include <linux/input.h>
-#include <plat/pxa27x_keypad.h>
+#include <linux/platform_data/keypad-pxa27x.h>
 
 #include "common.h"
 
diff --git a/arch/arm/mach-mmp/clock-mmp2.c b/arch/arm/mach-mmp/clock-mmp2.c
new file mode 100644
index 0000000..21d2200
--- /dev/null
+++ b/arch/arm/mach-mmp/clock-mmp2.c
@@ -0,0 +1,111 @@
+#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 <mach/addr-map.h>
+
+#include "common.h"
+#include "clock.h"
+
+/*
+ * APB Clock register offsets for MMP2
+ */
+#define APBC_RTC	APBC_REG(0x000)
+#define APBC_TWSI1	APBC_REG(0x004)
+#define APBC_TWSI2	APBC_REG(0x008)
+#define APBC_TWSI3	APBC_REG(0x00c)
+#define APBC_TWSI4	APBC_REG(0x010)
+#define APBC_KPC	APBC_REG(0x018)
+#define APBC_UART1	APBC_REG(0x02c)
+#define APBC_UART2	APBC_REG(0x030)
+#define APBC_UART3	APBC_REG(0x034)
+#define APBC_GPIO	APBC_REG(0x038)
+#define APBC_PWM0	APBC_REG(0x03c)
+#define APBC_PWM1	APBC_REG(0x040)
+#define APBC_PWM2	APBC_REG(0x044)
+#define APBC_PWM3	APBC_REG(0x048)
+#define APBC_SSP0	APBC_REG(0x04c)
+#define APBC_SSP1	APBC_REG(0x050)
+#define APBC_SSP2	APBC_REG(0x054)
+#define APBC_SSP3	APBC_REG(0x058)
+#define APBC_SSP4	APBC_REG(0x05c)
+#define APBC_SSP5	APBC_REG(0x060)
+#define APBC_TWSI5	APBC_REG(0x07c)
+#define APBC_TWSI6	APBC_REG(0x080)
+#define APBC_UART4	APBC_REG(0x088)
+
+#define APMU_USB	APMU_REG(0x05c)
+#define APMU_NAND	APMU_REG(0x060)
+#define APMU_SDH0	APMU_REG(0x054)
+#define APMU_SDH1	APMU_REG(0x058)
+#define APMU_SDH2	APMU_REG(0x0e8)
+#define APMU_SDH3	APMU_REG(0x0ec)
+
+static void sdhc_clk_enable(struct clk *clk)
+{
+	uint32_t clk_rst;
+
+	clk_rst  =  __raw_readl(clk->clk_rst);
+	clk_rst |= clk->enable_val;
+	__raw_writel(clk_rst, clk->clk_rst);
+}
+
+static void sdhc_clk_disable(struct clk *clk)
+{
+	uint32_t clk_rst;
+
+	clk_rst  =  __raw_readl(clk->clk_rst);
+	clk_rst &= ~clk->enable_val;
+	__raw_writel(clk_rst, clk->clk_rst);
+}
+
+struct clkops sdhc_clk_ops = {
+	.enable		= sdhc_clk_enable,
+	.disable	= sdhc_clk_disable,
+};
+
+/* APB peripheral clocks */
+static APBC_CLK(uart1, UART1, 1, 26000000);
+static APBC_CLK(uart2, UART2, 1, 26000000);
+static APBC_CLK(uart3, UART3, 1, 26000000);
+static APBC_CLK(uart4, UART4, 1, 26000000);
+static APBC_CLK(twsi1, TWSI1, 0, 26000000);
+static APBC_CLK(twsi2, TWSI2, 0, 26000000);
+static APBC_CLK(twsi3, TWSI3, 0, 26000000);
+static APBC_CLK(twsi4, TWSI4, 0, 26000000);
+static APBC_CLK(twsi5, TWSI5, 0, 26000000);
+static APBC_CLK(twsi6, TWSI6, 0, 26000000);
+static APBC_CLK(gpio, GPIO, 0, 26000000);
+
+static APMU_CLK(nand, NAND, 0xbf, 100000000);
+static APMU_CLK_OPS(sdh0, SDH0, 0x1b, 200000000, &sdhc_clk_ops);
+static APMU_CLK_OPS(sdh1, SDH1, 0x1b, 200000000, &sdhc_clk_ops);
+static APMU_CLK_OPS(sdh2, SDH2, 0x1b, 200000000, &sdhc_clk_ops);
+static APMU_CLK_OPS(sdh3, SDH3, 0x1b, 200000000, &sdhc_clk_ops);
+
+static struct clk_lookup mmp2_clkregs[] = {
+	INIT_CLKREG(&clk_uart1, "pxa2xx-uart.0", NULL),
+	INIT_CLKREG(&clk_uart2, "pxa2xx-uart.1", NULL),
+	INIT_CLKREG(&clk_uart3, "pxa2xx-uart.2", NULL),
+	INIT_CLKREG(&clk_uart4, "pxa2xx-uart.3", NULL),
+	INIT_CLKREG(&clk_twsi1, "pxa2xx-i2c.0", NULL),
+	INIT_CLKREG(&clk_twsi2, "pxa2xx-i2c.1", NULL),
+	INIT_CLKREG(&clk_twsi3, "pxa2xx-i2c.2", NULL),
+	INIT_CLKREG(&clk_twsi4, "pxa2xx-i2c.3", NULL),
+	INIT_CLKREG(&clk_twsi5, "pxa2xx-i2c.4", NULL),
+	INIT_CLKREG(&clk_twsi6, "pxa2xx-i2c.5", NULL),
+	INIT_CLKREG(&clk_nand, "pxa3xx-nand", NULL),
+	INIT_CLKREG(&clk_gpio, "pxa-gpio", NULL),
+	INIT_CLKREG(&clk_sdh0, "sdhci-pxav3.0", "PXA-SDHCLK"),
+	INIT_CLKREG(&clk_sdh1, "sdhci-pxav3.1", "PXA-SDHCLK"),
+	INIT_CLKREG(&clk_sdh2, "sdhci-pxav3.2", "PXA-SDHCLK"),
+	INIT_CLKREG(&clk_sdh3, "sdhci-pxav3.3", "PXA-SDHCLK"),
+};
+
+void __init mmp2_clk_init(void)
+{
+	clkdev_add_table(ARRAY_AND_SIZE(mmp2_clkregs));
+}
diff --git a/arch/arm/mach-mmp/clock-pxa168.c b/arch/arm/mach-mmp/clock-pxa168.c
new file mode 100644
index 0000000..5e6c18c
--- /dev/null
+++ b/arch/arm/mach-mmp/clock-pxa168.c
@@ -0,0 +1,91 @@
+#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 <mach/addr-map.h>
+
+#include "common.h"
+#include "clock.h"
+
+/*
+ * APB clock register offsets for PXA168
+ */
+#define APBC_UART1	APBC_REG(0x000)
+#define APBC_UART2	APBC_REG(0x004)
+#define APBC_GPIO	APBC_REG(0x008)
+#define APBC_PWM1	APBC_REG(0x00c)
+#define APBC_PWM2	APBC_REG(0x010)
+#define APBC_PWM3	APBC_REG(0x014)
+#define APBC_PWM4	APBC_REG(0x018)
+#define APBC_RTC	APBC_REG(0x028)
+#define APBC_TWSI0	APBC_REG(0x02c)
+#define APBC_KPC	APBC_REG(0x030)
+#define APBC_TWSI1	APBC_REG(0x06c)
+#define APBC_UART3	APBC_REG(0x070)
+#define APBC_SSP1	APBC_REG(0x81c)
+#define APBC_SSP2	APBC_REG(0x820)
+#define APBC_SSP3	APBC_REG(0x84c)
+#define APBC_SSP4	APBC_REG(0x858)
+#define APBC_SSP5	APBC_REG(0x85c)
+
+#define APMU_NAND	APMU_REG(0x060)
+#define APMU_LCD	APMU_REG(0x04c)
+#define APMU_ETH	APMU_REG(0x0fc)
+#define APMU_USB	APMU_REG(0x05c)
+
+/* APB peripheral clocks */
+static APBC_CLK(uart1, UART1, 1, 14745600);
+static APBC_CLK(uart2, UART2, 1, 14745600);
+static APBC_CLK(uart3, UART3, 1, 14745600);
+static APBC_CLK(twsi0, TWSI0, 1, 33000000);
+static APBC_CLK(twsi1, TWSI1, 1, 33000000);
+static APBC_CLK(pwm1, PWM1, 1, 13000000);
+static APBC_CLK(pwm2, PWM2, 1, 13000000);
+static APBC_CLK(pwm3, PWM3, 1, 13000000);
+static APBC_CLK(pwm4, PWM4, 1, 13000000);
+static APBC_CLK(ssp1, SSP1, 4, 0);
+static APBC_CLK(ssp2, SSP2, 4, 0);
+static APBC_CLK(ssp3, SSP3, 4, 0);
+static APBC_CLK(ssp4, SSP4, 4, 0);
+static APBC_CLK(ssp5, SSP5, 4, 0);
+static APBC_CLK(gpio, GPIO, 0, 13000000);
+static APBC_CLK(keypad, KPC, 0, 32000);
+static APBC_CLK(rtc, RTC, 8, 32768);
+
+static APMU_CLK(nand, NAND, 0x19b, 156000000);
+static APMU_CLK(lcd, LCD, 0x7f, 312000000);
+static APMU_CLK(eth, ETH, 0x09, 0);
+static APMU_CLK(usb, USB, 0x12, 0);
+
+/* 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),
+	INIT_CLKREG(&clk_uart3, "pxa2xx-uart.2", NULL),
+	INIT_CLKREG(&clk_twsi0, "pxa2xx-i2c.0", NULL),
+	INIT_CLKREG(&clk_twsi1, "pxa2xx-i2c.1", NULL),
+	INIT_CLKREG(&clk_pwm1, "pxa168-pwm.0", NULL),
+	INIT_CLKREG(&clk_pwm2, "pxa168-pwm.1", NULL),
+	INIT_CLKREG(&clk_pwm3, "pxa168-pwm.2", NULL),
+	INIT_CLKREG(&clk_pwm4, "pxa168-pwm.3", NULL),
+	INIT_CLKREG(&clk_ssp1, "pxa168-ssp.0", NULL),
+	INIT_CLKREG(&clk_ssp2, "pxa168-ssp.1", NULL),
+	INIT_CLKREG(&clk_ssp3, "pxa168-ssp.2", NULL),
+	INIT_CLKREG(&clk_ssp4, "pxa168-ssp.3", NULL),
+	INIT_CLKREG(&clk_ssp5, "pxa168-ssp.4", NULL),
+	INIT_CLKREG(&clk_nand, "pxa3xx-nand", NULL),
+	INIT_CLKREG(&clk_lcd, "pxa168-fb", NULL),
+	INIT_CLKREG(&clk_gpio, "pxa-gpio", NULL),
+	INIT_CLKREG(&clk_keypad, "pxa27x-keypad", NULL),
+	INIT_CLKREG(&clk_eth, "pxa168-eth", "MFUCLK"),
+	INIT_CLKREG(&clk_usb, NULL, "PXA168-USBCLK"),
+	INIT_CLKREG(&clk_rtc, "sa1100-rtc", NULL),
+};
+
+void __init pxa168_clk_init(void)
+{
+	clkdev_add_table(ARRAY_AND_SIZE(pxa168_clkregs));
+}
diff --git a/arch/arm/mach-mmp/clock-pxa910.c b/arch/arm/mach-mmp/clock-pxa910.c
new file mode 100644
index 0000000..933ea71
--- /dev/null
+++ b/arch/arm/mach-mmp/clock-pxa910.c
@@ -0,0 +1,67 @@
+#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 <mach/addr-map.h>
+
+#include "common.h"
+#include "clock.h"
+
+/*
+ * APB Clock register offsets for PXA910
+ */
+#define APBC_UART0	APBC_REG(0x000)
+#define APBC_UART1	APBC_REG(0x004)
+#define APBC_GPIO	APBC_REG(0x008)
+#define APBC_PWM1	APBC_REG(0x00c)
+#define APBC_PWM2	APBC_REG(0x010)
+#define APBC_PWM3	APBC_REG(0x014)
+#define APBC_PWM4	APBC_REG(0x018)
+#define APBC_SSP1	APBC_REG(0x01c)
+#define APBC_SSP2	APBC_REG(0x020)
+#define APBC_RTC	APBC_REG(0x028)
+#define APBC_TWSI0	APBC_REG(0x02c)
+#define APBC_KPC	APBC_REG(0x030)
+#define APBC_SSP3	APBC_REG(0x04c)
+#define APBC_TWSI1	APBC_REG(0x06c)
+
+#define APMU_NAND	APMU_REG(0x060)
+#define APMU_USB	APMU_REG(0x05c)
+
+static APBC_CLK(uart1, UART0, 1, 14745600);
+static APBC_CLK(uart2, UART1, 1, 14745600);
+static APBC_CLK(twsi0, TWSI0, 1, 33000000);
+static APBC_CLK(twsi1, TWSI1, 1, 33000000);
+static APBC_CLK(pwm1, PWM1, 1, 13000000);
+static APBC_CLK(pwm2, PWM2, 1, 13000000);
+static APBC_CLK(pwm3, PWM3, 1, 13000000);
+static APBC_CLK(pwm4, PWM4, 1, 13000000);
+static APBC_CLK(gpio, GPIO, 0, 13000000);
+static APBC_CLK(rtc, RTC, 8, 32768);
+
+static APMU_CLK(nand, NAND, 0x19b, 156000000);
+static APMU_CLK(u2o, USB, 0x1b, 480000000);
+
+/* 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),
+	INIT_CLKREG(&clk_twsi0, "pxa2xx-i2c.0", NULL),
+	INIT_CLKREG(&clk_twsi1, "pxa2xx-i2c.1", NULL),
+	INIT_CLKREG(&clk_pwm1, "pxa910-pwm.0", NULL),
+	INIT_CLKREG(&clk_pwm2, "pxa910-pwm.1", NULL),
+	INIT_CLKREG(&clk_pwm3, "pxa910-pwm.2", NULL),
+	INIT_CLKREG(&clk_pwm4, "pxa910-pwm.3", NULL),
+	INIT_CLKREG(&clk_nand, "pxa3xx-nand", NULL),
+	INIT_CLKREG(&clk_gpio, "pxa-gpio", NULL),
+	INIT_CLKREG(&clk_u2o, NULL, "U2OCLK"),
+	INIT_CLKREG(&clk_rtc, "sa1100-rtc", NULL),
+};
+
+void __init pxa910_clk_init(void)
+{
+	clkdev_add_table(ARRAY_AND_SIZE(pxa910_clkregs));
+}
diff --git a/arch/arm/mach-mmp/common.h b/arch/arm/mach-mmp/common.h
index 1c9d6c1..bd45327 100644
--- a/arch/arm/mach-mmp/common.h
+++ b/arch/arm/mach-mmp/common.h
@@ -7,3 +7,6 @@ extern void timer_init(int irq);
 extern void __init icu_init_irq(void);
 extern void __init mmp_map_io(void);
 extern void mmp_restart(char, const char *);
+extern void __init pxa168_clk_init(void);
+extern void __init pxa910_clk_init(void);
+extern void __init mmp2_clk_init(void);
diff --git a/arch/arm/mach-mmp/include/mach/debug-macro.S b/arch/arm/mach-mmp/include/mach/debug-macro.S
index b6f14d2..5c3cc29 100644
--- a/arch/arm/mach-mmp/include/mach/debug-macro.S
+++ b/arch/arm/mach-mmp/include/mach/debug-macro.S
@@ -9,13 +9,21 @@
  * published by the Free Software Foundation.
  */
 
+#if defined(CONFIG_DEBUG_MMP_UART2)
+#define MMP_UART_OFFSET	0x00017000
+#elif defined(CONFIG_DEBUG_MMP_UART3)
+#define MMP_UART_OFFSET	0x00018000
+#else
+#error "Select uart for DEBUG_LL"
+#endif
+
 #include <mach/addr-map.h>
 
 		.macro	addruart, rp, rv, tmp
 		ldr	\rp, =APB_PHYS_BASE		@ physical
 		ldr	\rv, =APB_VIRT_BASE		@ virtual
-		orr	\rp, \rp, #0x00017000
-		orr	\rv, \rv, #0x00017000
+		orr	\rp, \rp, #MMP_UART_OFFSET
+		orr	\rv, \rv, #MMP_UART_OFFSET
 		.endm
 
 #define UART_SHIFT	2
diff --git a/arch/arm/mach-mmp/include/mach/mmp2.h b/arch/arm/mach-mmp/include/mach/mmp2.h
index cba22fe..c4ca4d1 100644
--- a/arch/arm/mach-mmp/include/mach/mmp2.h
+++ b/arch/arm/mach-mmp/include/mach/mmp2.h
@@ -13,7 +13,7 @@ extern void mmp2_clear_pmic_int(void);
 #include <linux/i2c.h>
 #include <linux/i2c/pxa-i2c.h>
 #include <mach/devices.h>
-#include <mach/sram.h>
+#include <linux/platform_data/dma-mmp_tdma.h>
 
 extern struct pxa_device_desc mmp2_device_uart1;
 extern struct pxa_device_desc mmp2_device_uart2;
diff --git a/arch/arm/mach-mmp/include/mach/pxa168.h b/arch/arm/mach-mmp/include/mach/pxa168.h
index 09dcd6e..37632d9 100644
--- a/arch/arm/mach-mmp/include/mach/pxa168.h
+++ b/arch/arm/mach-mmp/include/mach/pxa168.h
@@ -11,9 +11,9 @@ extern void pxa168_clear_keypad_wakeup(void);
 #include <linux/i2c.h>
 #include <linux/i2c/pxa-i2c.h>
 #include <mach/devices.h>
-#include <plat/pxa3xx_nand.h>
+#include <linux/platform_data/mtd-nand-pxa3xx.h>
 #include <video/pxa168fb.h>
-#include <plat/pxa27x_keypad.h>
+#include <linux/platform_data/keypad-pxa27x.h>
 #include <mach/cputype.h>
 #include <linux/pxa168_eth.h>
 #include <linux/platform_data/mv_usb.h>
diff --git a/arch/arm/mach-mmp/include/mach/pxa910.h b/arch/arm/mach-mmp/include/mach/pxa910.h
index 793634c..3b58a3b 100644
--- a/arch/arm/mach-mmp/include/mach/pxa910.h
+++ b/arch/arm/mach-mmp/include/mach/pxa910.h
@@ -9,7 +9,7 @@ extern void __init pxa910_init_irq(void);
 #include <linux/i2c.h>
 #include <linux/i2c/pxa-i2c.h>
 #include <mach/devices.h>
-#include <plat/pxa3xx_nand.h>
+#include <linux/platform_data/mtd-nand-pxa3xx.h>
 
 extern struct pxa_device_desc pxa910_device_uart1;
 extern struct pxa_device_desc pxa910_device_uart2;
diff --git a/arch/arm/mach-mmp/include/mach/regs-apbc.h b/arch/arm/mach-mmp/include/mach/regs-apbc.h
index 68b0c93..ddc812f 100644
--- a/arch/arm/mach-mmp/include/mach/regs-apbc.h
+++ b/arch/arm/mach-mmp/include/mach/regs-apbc.h
@@ -13,101 +13,6 @@
 
 #include <mach/addr-map.h>
 
-/*
- * 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_PWM1	APBC_REG(0x00c)
-#define APBC_PXA168_PWM2	APBC_REG(0x010)
-#define APBC_PXA168_PWM3	APBC_REG(0x014)
-#define APBC_PXA168_PWM4	APBC_REG(0x018)
-#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_ASFAR	APBC_REG(0x050)
-#define APBC_PXA168_ASSAR	APBC_REG(0x054)
-#define APBC_PXA168_TWSI1	APBC_REG(0x06c)
-#define APBC_PXA168_UART3	APBC_REG(0x070)
-#define APBC_PXA168_AC97	APBC_REG(0x084)
-#define APBC_PXA168_SSP1	APBC_REG(0x81c)
-#define APBC_PXA168_SSP2	APBC_REG(0x820)
-#define APBC_PXA168_SSP3	APBC_REG(0x84c)
-#define APBC_PXA168_SSP4	APBC_REG(0x858)
-#define APBC_PXA168_SSP5	APBC_REG(0x85c)
-
-/*
- * 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_PWM1	APBC_REG(0x00c)
-#define APBC_PXA910_PWM2	APBC_REG(0x010)
-#define APBC_PXA910_PWM3	APBC_REG(0x014)
-#define APBC_PXA910_PWM4	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_RTC		APBC_REG(0x028)
-#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)
-
-/*
- * APB Clock register offsets for MMP2
- */
-#define APBC_MMP2_RTC		APBC_REG(0x000)
-#define APBC_MMP2_TWSI1		APBC_REG(0x004)
-#define APBC_MMP2_TWSI2		APBC_REG(0x008)
-#define APBC_MMP2_TWSI3		APBC_REG(0x00c)
-#define APBC_MMP2_TWSI4		APBC_REG(0x010)
-#define APBC_MMP2_ONEWIRE	APBC_REG(0x014)
-#define APBC_MMP2_KPC		APBC_REG(0x018)
-#define APBC_MMP2_TB_ROTARY	APBC_REG(0x01c)
-#define APBC_MMP2_SW_JTAG	APBC_REG(0x020)
-#define APBC_MMP2_TIMERS	APBC_REG(0x024)
-#define APBC_MMP2_UART1		APBC_REG(0x02c)
-#define APBC_MMP2_UART2		APBC_REG(0x030)
-#define APBC_MMP2_UART3		APBC_REG(0x034)
-#define APBC_MMP2_GPIO		APBC_REG(0x038)
-#define APBC_MMP2_PWM0		APBC_REG(0x03c)
-#define APBC_MMP2_PWM1		APBC_REG(0x040)
-#define APBC_MMP2_PWM2		APBC_REG(0x044)
-#define APBC_MMP2_PWM3		APBC_REG(0x048)
-#define APBC_MMP2_SSP0		APBC_REG(0x04c)
-#define APBC_MMP2_SSP1		APBC_REG(0x050)
-#define APBC_MMP2_SSP2		APBC_REG(0x054)
-#define APBC_MMP2_SSP3		APBC_REG(0x058)
-#define APBC_MMP2_SSP4		APBC_REG(0x05c)
-#define APBC_MMP2_SSP5		APBC_REG(0x060)
-#define APBC_MMP2_AIB		APBC_REG(0x064)
-#define APBC_MMP2_ASFAR		APBC_REG(0x068)
-#define APBC_MMP2_ASSAR		APBC_REG(0x06c)
-#define APBC_MMP2_USIM		APBC_REG(0x070)
-#define APBC_MMP2_MPMU		APBC_REG(0x074)
-#define APBC_MMP2_IPC		APBC_REG(0x078)
-#define APBC_MMP2_TWSI5		APBC_REG(0x07c)
-#define APBC_MMP2_TWSI6		APBC_REG(0x080)
-#define APBC_MMP2_TWSI_INTSTS	APBC_REG(0x084)
-#define APBC_MMP2_UART4		APBC_REG(0x088)
-#define APBC_MMP2_RIPC		APBC_REG(0x08c)
-#define APBC_MMP2_THSENS1	APBC_REG(0x090)	/* Thermal Sensor */
-#define APBC_MMP2_THSENS_INTSTS	APBC_REG(0x0a4)
-
 /* Common APB clock register bit definitions */
 #define APBC_APBCLK	(1 << 0)  /* APB Bus Clock Enable */
 #define APBC_FNCLK	(1 << 1)  /* Functional Clock Enable */
diff --git a/arch/arm/mach-mmp/include/mach/regs-apmu.h b/arch/arm/mach-mmp/include/mach/regs-apmu.h
index 7af8deb..93c8d0e 100644
--- a/arch/arm/mach-mmp/include/mach/regs-apmu.h
+++ b/arch/arm/mach-mmp/include/mach/regs-apmu.h
@@ -13,21 +13,6 @@
 
 #include <mach/addr-map.h>
 
-/* 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_SDH2	APMU_REG(0x0e8)
-#define APMU_SDH3	APMU_REG(0x0ec)
-#define APMU_ETH	APMU_REG(0x0fc)
-
 #define APMU_FNCLK_EN	(1 << 4)
 #define APMU_AXICLK_EN	(1 << 3)
 #define APMU_FNRST_DIS	(1 << 1)
diff --git a/arch/arm/mach-mmp/include/mach/sram.h b/arch/arm/mach-mmp/include/mach/sram.h
deleted file mode 100644
index 239e0fc..0000000
--- a/arch/arm/mach-mmp/include/mach/sram.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- *  linux/arch/arm/mach-mmp/include/mach/sram.h
- *
- *  SRAM Memory Management
- *
- *  Copyright (c) 2011 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.
- *
- */
-
-#ifndef __ASM_ARCH_SRAM_H
-#define __ASM_ARCH_SRAM_H
-
-#include <linux/genalloc.h>
-
-/* ARBITRARY:  SRAM allocations are multiples of this 2^N size */
-#define SRAM_GRANULARITY	512
-
-enum sram_type {
-	MMP_SRAM_UNDEFINED = 0,
-	MMP_ASRAM,
-	MMP_ISRAM,
-};
-
-struct sram_platdata {
-	char *pool_name;
-	int granularity;
-};
-
-extern struct gen_pool *sram_get_gpool(char *pool_name);
-
-#endif /* __ASM_ARCH_SRAM_H */
diff --git a/arch/arm/mach-mmp/irq.c b/arch/arm/mach-mmp/irq.c
index e60c7d9..3c71246 100644
--- a/arch/arm/mach-mmp/irq.c
+++ b/arch/arm/mach-mmp/irq.c
@@ -153,10 +153,8 @@ static void icu_mux_irq_demux(unsigned int irq, struct irq_desc *desc)
 		status = readl_relaxed(data->reg_status) & ~mask;
 		if (status == 0)
 			break;
-		n = find_first_bit(&status, BITS_PER_LONG);
-		while (n < BITS_PER_LONG) {
+		for_each_set_bit(n, &status, BITS_PER_LONG) {
 			generic_handle_irq(icu_data[i].virq_base + n);
-			n = find_next_bit(&status, BITS_PER_LONG, n + 1);
 		}
 	}
 }
diff --git a/arch/arm/mach-mmp/mmp2.c b/arch/arm/mach-mmp/mmp2.c
index c709a24..3a3768c 100644
--- a/arch/arm/mach-mmp/mmp2.c
+++ b/arch/arm/mach-mmp/mmp2.c
@@ -20,7 +20,6 @@
 #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/dma.h>
@@ -29,7 +28,6 @@
 #include <mach/mmp2.h>
 
 #include "common.h"
-#include "clock.h"
 
 #define MFPR_VIRT_BASE	(APB_VIRT_BASE + 0x1e000)
 
@@ -98,95 +96,36 @@ void __init mmp2_init_irq(void)
 	mmp2_init_icu();
 }
 
-static void sdhc_clk_enable(struct clk *clk)
-{
-	uint32_t clk_rst;
-
-	clk_rst  =  __raw_readl(clk->clk_rst);
-	clk_rst |= clk->enable_val;
-	__raw_writel(clk_rst, clk->clk_rst);
-}
-
-static void sdhc_clk_disable(struct clk *clk)
-{
-	uint32_t clk_rst;
-
-	clk_rst  =  __raw_readl(clk->clk_rst);
-	clk_rst &= ~clk->enable_val;
-	__raw_writel(clk_rst, clk->clk_rst);
-}
-
-struct clkops sdhc_clk_ops = {
-	.enable		= sdhc_clk_enable,
-	.disable	= sdhc_clk_disable,
-};
-
-/* APB peripheral clocks */
-static APBC_CLK(uart1, MMP2_UART1, 1, 26000000);
-static APBC_CLK(uart2, MMP2_UART2, 1, 26000000);
-static APBC_CLK(uart3, MMP2_UART3, 1, 26000000);
-static APBC_CLK(uart4, MMP2_UART4, 1, 26000000);
-static APBC_CLK(twsi1, MMP2_TWSI1, 0, 26000000);
-static APBC_CLK(twsi2, MMP2_TWSI2, 0, 26000000);
-static APBC_CLK(twsi3, MMP2_TWSI3, 0, 26000000);
-static APBC_CLK(twsi4, MMP2_TWSI4, 0, 26000000);
-static APBC_CLK(twsi5, MMP2_TWSI5, 0, 26000000);
-static APBC_CLK(twsi6, MMP2_TWSI6, 0, 26000000);
-static APBC_CLK(gpio, MMP2_GPIO, 0, 26000000);
-
-static APMU_CLK(nand, NAND, 0xbf, 100000000);
-static APMU_CLK_OPS(sdh0, SDH0, 0x1b, 200000000, &sdhc_clk_ops);
-static APMU_CLK_OPS(sdh1, SDH1, 0x1b, 200000000, &sdhc_clk_ops);
-static APMU_CLK_OPS(sdh2, SDH2, 0x1b, 200000000, &sdhc_clk_ops);
-static APMU_CLK_OPS(sdh3, SDH3, 0x1b, 200000000, &sdhc_clk_ops);
-
-static struct clk_lookup mmp2_clkregs[] = {
-	INIT_CLKREG(&clk_uart1, "pxa2xx-uart.0", NULL),
-	INIT_CLKREG(&clk_uart2, "pxa2xx-uart.1", NULL),
-	INIT_CLKREG(&clk_uart3, "pxa2xx-uart.2", NULL),
-	INIT_CLKREG(&clk_uart4, "pxa2xx-uart.3", NULL),
-	INIT_CLKREG(&clk_twsi1, "pxa2xx-i2c.0", NULL),
-	INIT_CLKREG(&clk_twsi2, "pxa2xx-i2c.1", NULL),
-	INIT_CLKREG(&clk_twsi3, "pxa2xx-i2c.2", NULL),
-	INIT_CLKREG(&clk_twsi4, "pxa2xx-i2c.3", NULL),
-	INIT_CLKREG(&clk_twsi5, "pxa2xx-i2c.4", NULL),
-	INIT_CLKREG(&clk_twsi6, "pxa2xx-i2c.5", NULL),
-	INIT_CLKREG(&clk_nand, "pxa3xx-nand", NULL),
-	INIT_CLKREG(&clk_gpio, "pxa-gpio", NULL),
-	INIT_CLKREG(&clk_sdh0, "sdhci-pxav3.0", "PXA-SDHCLK"),
-	INIT_CLKREG(&clk_sdh1, "sdhci-pxav3.1", "PXA-SDHCLK"),
-	INIT_CLKREG(&clk_sdh2, "sdhci-pxav3.2", "PXA-SDHCLK"),
-	INIT_CLKREG(&clk_sdh3, "sdhci-pxav3.3", "PXA-SDHCLK"),
-};
-
 static int __init mmp2_init(void)
 {
 	if (cpu_is_mmp2()) {
 #ifdef CONFIG_CACHE_TAUROS2
-		tauros2_init();
+		tauros2_init(0);
 #endif
 		mfp_init_base(MFPR_VIRT_BASE);
 		mfp_init_addr(mmp2_addr_map);
 		pxa_init_dma(IRQ_MMP2_DMA_RIQ, 16);
-		clkdev_add_table(ARRAY_AND_SIZE(mmp2_clkregs));
+		mmp2_clk_init();
 	}
 
 	return 0;
 }
 postcore_initcall(mmp2_init);
 
+#define APBC_TIMERS	APBC_REG(0x024)
+
 static void __init mmp2_timer_init(void)
 {
 	unsigned long clk_rst;
 
-	__raw_writel(APBC_APBCLK | APBC_RST, APBC_MMP2_TIMERS);
+	__raw_writel(APBC_APBCLK | APBC_RST, APBC_TIMERS);
 
 	/*
 	 * enable bus/functional clock, enable 6.5MHz (divider 4),
 	 * release reset
 	 */
 	clk_rst = APBC_APBCLK | APBC_FNCLK | APBC_FNCLKSEL(1);
-	__raw_writel(clk_rst, APBC_MMP2_TIMERS);
+	__raw_writel(clk_rst, APBC_TIMERS);
 
 	timer_init(IRQ_MMP2_TIMER1);
 }
diff --git a/arch/arm/mach-mmp/pxa168.c b/arch/arm/mach-mmp/pxa168.c
index 62d787c..b7f074f 100644
--- a/arch/arm/mach-mmp/pxa168.c
+++ b/arch/arm/mach-mmp/pxa168.c
@@ -18,8 +18,8 @@
 
 #include <asm/mach/time.h>
 #include <asm/system_misc.h>
-#include <mach/addr-map.h>
 #include <mach/cputype.h>
+#include <mach/addr-map.h>
 #include <mach/regs-apbc.h>
 #include <mach/regs-apmu.h>
 #include <mach/irqs.h>
@@ -50,62 +50,13 @@ void __init pxa168_init_irq(void)
 	icu_init_irq();
 }
 
-/* APB peripheral clocks */
-static APBC_CLK(uart1, PXA168_UART1, 1, 14745600);
-static APBC_CLK(uart2, PXA168_UART2, 1, 14745600);
-static APBC_CLK(uart3, PXA168_UART3, 1, 14745600);
-static APBC_CLK(twsi0, PXA168_TWSI0, 1, 33000000);
-static APBC_CLK(twsi1, PXA168_TWSI1, 1, 33000000);
-static APBC_CLK(pwm1, PXA168_PWM1, 1, 13000000);
-static APBC_CLK(pwm2, PXA168_PWM2, 1, 13000000);
-static APBC_CLK(pwm3, PXA168_PWM3, 1, 13000000);
-static APBC_CLK(pwm4, PXA168_PWM4, 1, 13000000);
-static APBC_CLK(ssp1, PXA168_SSP1, 4, 0);
-static APBC_CLK(ssp2, PXA168_SSP2, 4, 0);
-static APBC_CLK(ssp3, PXA168_SSP3, 4, 0);
-static APBC_CLK(ssp4, PXA168_SSP4, 4, 0);
-static APBC_CLK(ssp5, PXA168_SSP5, 4, 0);
-static APBC_CLK(gpio, PXA168_GPIO, 0, 13000000);
-static APBC_CLK(keypad, PXA168_KPC, 0, 32000);
-static APBC_CLK(rtc, PXA168_RTC, 8, 32768);
-
-static APMU_CLK(nand, NAND, 0x19b, 156000000);
-static APMU_CLK(lcd, LCD, 0x7f, 312000000);
-static APMU_CLK(eth, ETH, 0x09, 0);
-static APMU_CLK(usb, USB, 0x12, 0);
-
-/* 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),
-	INIT_CLKREG(&clk_uart3, "pxa2xx-uart.2", NULL),
-	INIT_CLKREG(&clk_twsi0, "pxa2xx-i2c.0", NULL),
-	INIT_CLKREG(&clk_twsi1, "pxa2xx-i2c.1", NULL),
-	INIT_CLKREG(&clk_pwm1, "pxa168-pwm.0", NULL),
-	INIT_CLKREG(&clk_pwm2, "pxa168-pwm.1", NULL),
-	INIT_CLKREG(&clk_pwm3, "pxa168-pwm.2", NULL),
-	INIT_CLKREG(&clk_pwm4, "pxa168-pwm.3", NULL),
-	INIT_CLKREG(&clk_ssp1, "pxa168-ssp.0", NULL),
-	INIT_CLKREG(&clk_ssp2, "pxa168-ssp.1", NULL),
-	INIT_CLKREG(&clk_ssp3, "pxa168-ssp.2", NULL),
-	INIT_CLKREG(&clk_ssp4, "pxa168-ssp.3", NULL),
-	INIT_CLKREG(&clk_ssp5, "pxa168-ssp.4", NULL),
-	INIT_CLKREG(&clk_nand, "pxa3xx-nand", NULL),
-	INIT_CLKREG(&clk_lcd, "pxa168-fb", NULL),
-	INIT_CLKREG(&clk_gpio, "pxa-gpio", NULL),
-	INIT_CLKREG(&clk_keypad, "pxa27x-keypad", NULL),
-	INIT_CLKREG(&clk_eth, "pxa168-eth", "MFUCLK"),
-	INIT_CLKREG(&clk_usb, NULL, "PXA168-USBCLK"),
-	INIT_CLKREG(&clk_rtc, "sa1100-rtc", 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);
-		clkdev_add_table(ARRAY_AND_SIZE(pxa168_clkregs));
+		pxa168_clk_init();
 	}
 
 	return 0;
@@ -114,6 +65,7 @@ postcore_initcall(pxa168_init);
 
 /* system timer - clock enabled, 3.25MHz */
 #define TIMER_CLK_RST	(APBC_APBCLK | APBC_FNCLK | APBC_FNCLKSEL(3))
+#define APBC_TIMERS	APBC_REG(0x34)
 
 static void __init pxa168_timer_init(void)
 {
@@ -121,10 +73,10 @@ static void __init pxa168_timer_init(void)
 	 * 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);
+	__raw_writel(APBC_APBCLK | APBC_RST, APBC_TIMERS);
 
 	/* 3.25MHz, bus/functional clock enabled, release reset */
-	__raw_writel(TIMER_CLK_RST, APBC_PXA168_TIMERS);
+	__raw_writel(TIMER_CLK_RST, APBC_TIMERS);
 
 	timer_init(IRQ_PXA168_TIMER1);
 }
diff --git a/arch/arm/mach-mmp/pxa910.c b/arch/arm/mach-mmp/pxa910.c
index 6da52e9..8b1e16f 100644
--- a/arch/arm/mach-mmp/pxa910.c
+++ b/arch/arm/mach-mmp/pxa910.c
@@ -14,10 +14,10 @@
 #include <linux/io.h>
 #include <linux/platform_device.h>
 
+#include <asm/hardware/cache-tauros2.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/dma.h>
@@ -25,7 +25,6 @@
 #include <mach/devices.h>
 
 #include "common.h"
-#include "clock.h"
 
 #define MFPR_VIRT_BASE	(APB_VIRT_BASE + 0x1e000)
 
@@ -82,44 +81,16 @@ void __init pxa910_init_irq(void)
 	icu_init_irq();
 }
 
-/* APB peripheral clocks */
-static APBC_CLK(uart1, PXA910_UART0, 1, 14745600);
-static APBC_CLK(uart2, PXA910_UART1, 1, 14745600);
-static APBC_CLK(twsi0, PXA168_TWSI0, 1, 33000000);
-static APBC_CLK(twsi1, PXA168_TWSI1, 1, 33000000);
-static APBC_CLK(pwm1, PXA910_PWM1, 1, 13000000);
-static APBC_CLK(pwm2, PXA910_PWM2, 1, 13000000);
-static APBC_CLK(pwm3, PXA910_PWM3, 1, 13000000);
-static APBC_CLK(pwm4, PXA910_PWM4, 1, 13000000);
-static APBC_CLK(gpio, PXA910_GPIO, 0, 13000000);
-static APBC_CLK(rtc, PXA910_RTC, 8, 32768);
-
-static APMU_CLK(nand, NAND, 0x19b, 156000000);
-static APMU_CLK(u2o, USB, 0x1b, 480000000);
-
-/* 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),
-	INIT_CLKREG(&clk_twsi0, "pxa2xx-i2c.0", NULL),
-	INIT_CLKREG(&clk_twsi1, "pxa2xx-i2c.1", NULL),
-	INIT_CLKREG(&clk_pwm1, "pxa910-pwm.0", NULL),
-	INIT_CLKREG(&clk_pwm2, "pxa910-pwm.1", NULL),
-	INIT_CLKREG(&clk_pwm3, "pxa910-pwm.2", NULL),
-	INIT_CLKREG(&clk_pwm4, "pxa910-pwm.3", NULL),
-	INIT_CLKREG(&clk_nand, "pxa3xx-nand", NULL),
-	INIT_CLKREG(&clk_gpio, "pxa-gpio", NULL),
-	INIT_CLKREG(&clk_u2o, NULL, "U2OCLK"),
-	INIT_CLKREG(&clk_rtc, "sa1100-rtc", NULL),
-};
-
 static int __init pxa910_init(void)
 {
 	if (cpu_is_pxa910()) {
+#ifdef CONFIG_CACHE_TAUROS2
+		tauros2_init(0);
+#endif
 		mfp_init_base(MFPR_VIRT_BASE);
 		mfp_init_addr(pxa910_mfp_addr_map);
 		pxa_init_dma(IRQ_PXA910_DMA_INT0, 32);
-		clkdev_add_table(ARRAY_AND_SIZE(pxa910_clkregs));
+		pxa910_clk_init();
 	}
 
 	return 0;
@@ -128,12 +99,13 @@ postcore_initcall(pxa910_init);
 
 /* system timer - clock enabled, 3.25MHz */
 #define TIMER_CLK_RST	(APBC_APBCLK | APBC_FNCLK | APBC_FNCLKSEL(3))
+#define APBC_TIMERS	APBC_REG(0x34)
 
 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);
+	__raw_writel(APBC_APBCLK | APBC_RST, APBC_TIMERS);
+	__raw_writel(TIMER_CLK_RST, APBC_TIMERS);
 
 	timer_init(IRQ_PXA910_AP1_TIMER1);
 }
diff --git a/arch/arm/mach-mmp/sram.c b/arch/arm/mach-mmp/sram.c
index 7e8a5a2..a6c08ed 100644
--- a/arch/arm/mach-mmp/sram.c
+++ b/arch/arm/mach-mmp/sram.c
@@ -22,7 +22,7 @@
 #include <linux/slab.h>
 #include <linux/genalloc.h>
 
-#include <mach/sram.h>
+#include <linux/platform_data/dma-mmp_tdma.h>
 
 struct sram_bank_info {
 	char *pool_name;
diff --git a/arch/arm/mach-mmp/teton_bga.c b/arch/arm/mach-mmp/teton_bga.c
index 42bef66..dd30ea7 100644
--- a/arch/arm/mach-mmp/teton_bga.c
+++ b/arch/arm/mach-mmp/teton_bga.c
@@ -17,7 +17,7 @@
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
 #include <linux/input.h>
-#include <plat/pxa27x_keypad.h>
+#include <linux/platform_data/keypad-pxa27x.h>
 #include <linux/i2c.h>
 
 #include <asm/mach-types.h>
diff --git a/arch/arm/mach-mmp/ttc_dkb.c b/arch/arm/mach-mmp/ttc_dkb.c
index 7a7de2b..ce55fd8 100644
--- a/arch/arm/mach-mmp/ttc_dkb.c
+++ b/arch/arm/mach-mmp/ttc_dkb.c
@@ -177,12 +177,22 @@ static struct mv_usb_platform_data ttc_usb_pdata = {
 #endif
 #endif
 
+#ifdef CONFIG_MTD_NAND_PXA3xx
+static struct pxa3xx_nand_platform_data dkb_nand_info = {
+	.enable_arbiter = 1,
+	.num_cs = 1,
+};
+#endif
+
 static void __init ttc_dkb_init(void)
 {
 	mfp_config(ARRAY_AND_SIZE(ttc_dkb_pin_config));
 
 	/* on-chip devices */
 	pxa910_add_uart(1);
+#ifdef CONFIG_MTD_NAND_PXA3xx
+	pxa910_add_nand(&dkb_nand_info);
+#endif
 
 	/* off-chip devices */
 	pxa910_add_twsi(0, NULL, ARRAY_AND_SIZE(ttc_dkb_i2c_info));
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 1cd40ad..7902de15 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -1,8 +1,12 @@
 if ARCH_MSM
 
+comment "Qualcomm MSM SoC Type"
+	depends on (ARCH_MSM8X60 || ARCH_MSM8960)
+
 choice
 	prompt "Qualcomm MSM SoC Type"
 	default ARCH_MSM7X00A
+	depends on !(ARCH_MSM8X60 || ARCH_MSM8960)
 
 config ARCH_MSM7X00A
 	bool "MSM7x00A / MSM7x01A"
@@ -36,10 +40,10 @@ config ARCH_QSD8X50
 	select GPIO_MSM_V1
 	select MSM_PROC_COMM
 
+endchoice
+
 config ARCH_MSM8X60
 	bool "MSM8X60"
-	select MACH_MSM8X60_SURF if (!MACH_MSM8X60_RUMI3 && !MACH_MSM8X60_SIM \
-				  && !MACH_MSM8X60_FFA)
 	select ARCH_MSM_SCORPIONMP
 	select ARM_GIC
 	select CPU_V7
@@ -47,18 +51,17 @@ config ARCH_MSM8X60
 	select GPIO_MSM_V2
 	select MSM_GPIOMUX
 	select MSM_SCM if SMP
+	select USE_OF
 
 config ARCH_MSM8960
 	bool "MSM8960"
 	select ARCH_MSM_SCORPIONMP
-	select MACH_MSM8960_SIM if (!MACH_MSM8960_RUMI3)
 	select ARM_GIC
 	select CPU_V7
 	select MSM_V2_TLMM
 	select MSM_GPIOMUX
 	select MSM_SCM if SMP
-
-endchoice
+	select USE_OF
 
 config MSM_HAS_DEBUG_UART_HS
 	bool
@@ -112,42 +115,6 @@ config MACH_QSD8X50A_ST1_5
 	help
 	  Support for the Qualcomm ST1.5.
 
-config MACH_MSM8X60_RUMI3
-	depends on ARCH_MSM8X60
-	bool "MSM8x60 RUMI3"
-	help
-	  Support for the Qualcomm MSM8x60 RUMI3 emulator.
-
-config MACH_MSM8X60_SURF
-	depends on ARCH_MSM8X60
-	bool "MSM8x60 SURF"
-	help
-	  Support for the Qualcomm MSM8x60 SURF eval board.
-
-config MACH_MSM8X60_SIM
-	depends on ARCH_MSM8X60
-	bool "MSM8x60 Simulator"
-	help
-	  Support for the Qualcomm MSM8x60 simulator.
-
-config MACH_MSM8X60_FFA
-	depends on ARCH_MSM8X60
-	bool "MSM8x60 FFA"
-	help
-	  Support for the Qualcomm MSM8x60 FFA eval board.
-
-config MACH_MSM8960_SIM
-	depends on ARCH_MSM8960
-	bool "MSM8960 Simulator"
-	help
-	  Support for the Qualcomm MSM8960 simulator.
-
-config MACH_MSM8960_RUMI3
-	depends on ARCH_MSM8960
-	bool "MSM8960 RUMI3"
-	help
-	  Support for the Qualcomm MSM8960 RUMI3 emulator.
-
 endmenu
 
 config MSM_SMD_PKG3
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 4ad3969..17519fa 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -1,11 +1,11 @@
-obj-y += io.o idle.o timer.o
+obj-y += io.o timer.o
 obj-y += clock.o
 obj-$(CONFIG_DEBUG_FS) += clock-debug.o
 
 obj-$(CONFIG_MSM_VIC) += irq-vic.o
 obj-$(CONFIG_MSM_IOMMU) += devices-iommu.o
 
-obj-$(CONFIG_ARCH_MSM7X00A) += dma.o irq.o acpuclock-arm11.o
+obj-$(CONFIG_ARCH_MSM7X00A) += dma.o irq.o
 obj-$(CONFIG_ARCH_MSM7X30) += dma.o
 obj-$(CONFIG_ARCH_QSD8X50) += dma.o sirc.o
 
@@ -25,8 +25,8 @@ obj-$(CONFIG_MACH_TROUT) += board-trout.o board-trout-gpio.o board-trout-mmc.o b
 obj-$(CONFIG_MACH_HALIBUT) += board-halibut.o devices-msm7x00.o
 obj-$(CONFIG_ARCH_MSM7X30) += board-msm7x30.o devices-msm7x30.o
 obj-$(CONFIG_ARCH_QSD8X50) += board-qsd8x50.o devices-qsd8x50.o
-obj-$(CONFIG_ARCH_MSM8X60) += board-msm8x60.o
-obj-$(CONFIG_ARCH_MSM8960) += board-msm8960.o devices-msm8960.o
+obj-$(CONFIG_ARCH_MSM8X60) += board-dt-8660.o
+obj-$(CONFIG_ARCH_MSM8960) += board-dt-8960.o
 
 obj-$(CONFIG_ARCH_MSM7X30) += gpiomux-v1.o gpiomux.o
 obj-$(CONFIG_ARCH_QSD8X50) += gpiomux-8x50.o gpiomux-v1.o gpiomux.o
diff --git a/arch/arm/mach-msm/Makefile.boot b/arch/arm/mach-msm/Makefile.boot
index 9b803a5..f7d6ae9 100644
--- a/arch/arm/mach-msm/Makefile.boot
+++ b/arch/arm/mach-msm/Makefile.boot
@@ -1,3 +1,6 @@
   zreladdr-y		+= 0x10008000
 params_phys-y		:= 0x10000100
 initrd_phys-y		:= 0x10800000
+
+dtb-$(CONFIG_ARCH_MSM8X60) += msm8660-surf.dtb
+dtb-$(CONFIG_ARCH_MSM8960) += msm8960-cdp.dtb
diff --git a/arch/arm/mach-msm/acpuclock-arm11.c b/arch/arm/mach-msm/acpuclock-arm11.c
deleted file mode 100644
index 805d4ee..0000000
--- a/arch/arm/mach-msm/acpuclock-arm11.c
+++ /dev/null
@@ -1,525 +0,0 @@
-/* arch/arm/mach-msm/acpuclock.c
- *
- * MSM architecture clock driver
- *
- * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2007 QUALCOMM Incorporated
- * Author: San Mehat <san@android.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/delay.h>
-#include <linux/clk.h>
-#include <linux/cpufreq.h>
-#include <linux/mutex.h>
-#include <linux/io.h>
-#include <mach/board.h>
-#include <mach/msm_iomap.h>
-
-#include "proc_comm.h"
-#include "acpuclock.h"
-
-
-#define A11S_CLK_CNTL_ADDR (MSM_CSR_BASE + 0x100)
-#define A11S_CLK_SEL_ADDR (MSM_CSR_BASE + 0x104)
-#define A11S_VDD_SVS_PLEVEL_ADDR (MSM_CSR_BASE + 0x124)
-
-/*
- * ARM11 clock configuration for specific ACPU speeds
- */
-
-#define ACPU_PLL_TCXO	-1
-#define ACPU_PLL_0	0
-#define ACPU_PLL_1	1
-#define ACPU_PLL_2	2
-#define ACPU_PLL_3	3
-
-#define PERF_SWITCH_DEBUG 0
-#define PERF_SWITCH_STEP_DEBUG 0
-
-struct clock_state
-{
-	struct clkctl_acpu_speed	*current_speed;
-	struct mutex			lock;
-	uint32_t			acpu_switch_time_us;
-	uint32_t			max_speed_delta_khz;
-	uint32_t			vdd_switch_time_us;
-	unsigned long			power_collapse_khz;
-	unsigned long			wait_for_irq_khz;
-};
-
-static struct clk *ebi1_clk;
-static struct clock_state drv_state = { 0 };
-
-static void __init acpuclk_init(void);
-
-/* MSM7201A Levels 3-6 all correspond to 1.2V, level 7 corresponds to 1.325V. */
-enum {
-	VDD_0 = 0,
-	VDD_1 = 1,
-	VDD_2 = 2,
-	VDD_3 = 3,
-	VDD_4 = 3,
-	VDD_5 = 3,
-	VDD_6 = 3,
-	VDD_7 = 7,
-	VDD_END
-};
-
-struct clkctl_acpu_speed {
-	unsigned int	a11clk_khz;
-	int		pll;
-	unsigned int	a11clk_src_sel;
-	unsigned int	a11clk_src_div;
-	unsigned int	ahbclk_khz;
-	unsigned int	ahbclk_div;
-	int		vdd;
-	unsigned int 	axiclk_khz;
-	unsigned long	lpj; /* loops_per_jiffy */
-/* Index in acpu_freq_tbl[] for steppings. */
-	short		down;
-	short		up;
-};
-
-/*
- * ACPU speed table. Complete table is shown but certain speeds are commented
- * out to optimized speed switching. Initialize loops_per_jiffy to 0.
- *
- * Table stepping up/down is optimized for 256mhz jumps while staying on the
- * same PLL.
- */
-#if (0)
-static struct clkctl_acpu_speed  acpu_freq_tbl[] = {
-	{ 19200, ACPU_PLL_TCXO, 0, 0, 19200, 0, VDD_0, 30720, 0, 0, 8 },
-	{ 61440, ACPU_PLL_0,  4, 3, 61440,  0, VDD_0, 30720,  0, 0, 8 },
-	{ 81920, ACPU_PLL_0,  4, 2, 40960,  1, VDD_0, 61440,  0, 0, 8 },
-	{ 96000, ACPU_PLL_1,  1, 7, 48000,  1, VDD_0, 61440,  0, 0, 9 },
-	{ 122880, ACPU_PLL_0, 4, 1, 61440,  1, VDD_3, 61440,  0, 0, 8 },
-	{ 128000, ACPU_PLL_1, 1, 5, 64000,  1, VDD_3, 61440,  0, 0, 12 },
-	{ 176000, ACPU_PLL_2, 2, 5, 88000,  1, VDD_3, 61440,  0, 0, 11 },
-	{ 192000, ACPU_PLL_1, 1, 3, 64000,  2, VDD_3, 61440,  0, 0, 12 },
-	{ 245760, ACPU_PLL_0, 4, 0, 81920,  2, VDD_4, 61440,  0, 0, 12 },
-	{ 256000, ACPU_PLL_1, 1, 2, 128000, 2, VDD_5, 128000, 0, 0, 12 },
-	{ 264000, ACPU_PLL_2, 2, 3, 88000,  2, VDD_5, 128000, 0, 6, 13 },
-	{ 352000, ACPU_PLL_2, 2, 2, 88000,  3, VDD_5, 128000, 0, 6, 13 },
-	{ 384000, ACPU_PLL_1, 1, 1, 128000, 2, VDD_6, 128000, 0, 5, -1 },
-	{ 528000, ACPU_PLL_2, 2, 1, 132000, 3, VDD_7, 128000, 0, 11, -1 },
-	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
-};
-#else /* Table of freq we currently use. */
-static struct clkctl_acpu_speed  acpu_freq_tbl[] = {
-	{ 19200, ACPU_PLL_TCXO, 0, 0, 19200, 0, VDD_0, 30720, 0, 0, 4 },
-	{ 122880, ACPU_PLL_0, 4, 1, 61440, 1, VDD_3, 61440, 0, 0, 4 },
-	{ 128000, ACPU_PLL_1, 1, 5, 64000, 1, VDD_3, 61440, 0, 0, 6 },
-	{ 176000, ACPU_PLL_2, 2, 5, 88000, 1, VDD_3, 61440, 0, 0, 5 },
-	{ 245760, ACPU_PLL_0, 4, 0, 81920, 2, VDD_4, 61440, 0, 0, 5 },
-	{ 352000, ACPU_PLL_2, 2, 2, 88000, 3, VDD_5, 128000, 0, 3, 7 },
-	{ 384000, ACPU_PLL_1, 1, 1, 128000, 2, VDD_6, 128000, 0, 2, -1 },
-	{ 528000, ACPU_PLL_2, 2, 1, 132000, 3, VDD_7, 128000, 0, 5, -1 },
-	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
-};
-#endif
-
-
-#ifdef CONFIG_CPU_FREQ_TABLE
-static struct cpufreq_frequency_table freq_table[] = {
-	{ 0, 122880 },
-	{ 1, 128000 },
-	{ 2, 245760 },
-	{ 3, 384000 },
-	{ 4, 528000 },
-	{ 5, CPUFREQ_TABLE_END },
-};
-#endif
-
-static int pc_pll_request(unsigned id, unsigned on)
-{
-	int res;
-	on = !!on;
-
-#if PERF_SWITCH_DEBUG
-	if (on)
-		printk(KERN_DEBUG "Enabling PLL %d\n", id);
-	else
-		printk(KERN_DEBUG "Disabling PLL %d\n", id);
-#endif
-
-	res = msm_proc_comm(PCOM_CLKCTL_RPC_PLL_REQUEST, &id, &on);
-	if (res < 0)
-		return res;
-
-#if PERF_SWITCH_DEBUG
-	if (on)
-		printk(KERN_DEBUG "PLL %d enabled\n", id);
-	else
-		printk(KERN_DEBUG "PLL %d disabled\n", id);
-#endif
-	return res;
-}
-
-
-/*----------------------------------------------------------------------------
- * ARM11 'owned' clock control
- *---------------------------------------------------------------------------*/
-
-unsigned long acpuclk_power_collapse(void) {
-	int ret = acpuclk_get_rate();
-	ret *= 1000;
-	if (ret > drv_state.power_collapse_khz)
-		acpuclk_set_rate(drv_state.power_collapse_khz, 1);
-	return ret;
-}
-
-unsigned long acpuclk_get_wfi_rate(void)
-{
-	return drv_state.wait_for_irq_khz;
-}
-
-unsigned long acpuclk_wait_for_irq(void) {
-	int ret = acpuclk_get_rate();
-	ret *= 1000;
-	if (ret > drv_state.wait_for_irq_khz)
-		acpuclk_set_rate(drv_state.wait_for_irq_khz, 1);
-	return ret;
-}
-
-static int acpuclk_set_vdd_level(int vdd)
-{
-	uint32_t current_vdd;
-
-	current_vdd = readl(A11S_VDD_SVS_PLEVEL_ADDR) & 0x07;
-
-#if PERF_SWITCH_DEBUG
-	printk(KERN_DEBUG "acpuclock: Switching VDD from %u -> %d\n",
-	       current_vdd, vdd);
-#endif
-	writel((1 << 7) | (vdd << 3), A11S_VDD_SVS_PLEVEL_ADDR);
-	udelay(drv_state.vdd_switch_time_us);
-	if ((readl(A11S_VDD_SVS_PLEVEL_ADDR) & 0x7) != vdd) {
-#if PERF_SWITCH_DEBUG
-		printk(KERN_ERR "acpuclock: VDD set failed\n");
-#endif
-		return -EIO;
-	}
-
-#if PERF_SWITCH_DEBUG
-	printk(KERN_DEBUG "acpuclock: VDD switched\n");
-#endif
-	return 0;
-}
-
-/* Set proper dividers for the given clock speed. */
-static void acpuclk_set_div(const struct clkctl_acpu_speed *hunt_s) {
-	uint32_t reg_clkctl, reg_clksel, clk_div;
-
-	/* AHB_CLK_DIV */
-	clk_div = (readl(A11S_CLK_SEL_ADDR) >> 1) & 0x03;
-	/*
-	 * If the new clock divider is higher than the previous, then
-	 * program the divider before switching the clock
-	 */
-	if (hunt_s->ahbclk_div > clk_div) {
-		reg_clksel = readl(A11S_CLK_SEL_ADDR);
-		reg_clksel &= ~(0x3 << 1);
-		reg_clksel |= (hunt_s->ahbclk_div << 1);
-		writel(reg_clksel, A11S_CLK_SEL_ADDR);
-	}
-	if ((readl(A11S_CLK_SEL_ADDR) & 0x01) == 0) {
-		/* SRC0 */
-
-		/* Program clock source */
-		reg_clkctl = readl(A11S_CLK_CNTL_ADDR);
-		reg_clkctl &= ~(0x07 << 4);
-		reg_clkctl |= (hunt_s->a11clk_src_sel << 4);
-		writel(reg_clkctl, A11S_CLK_CNTL_ADDR);
-
-		/* Program clock divider */
-		reg_clkctl = readl(A11S_CLK_CNTL_ADDR);
-		reg_clkctl &= ~0xf;
-		reg_clkctl |= hunt_s->a11clk_src_div;
-		writel(reg_clkctl, A11S_CLK_CNTL_ADDR);
-
-		/* Program clock source selection */
-		reg_clksel = readl(A11S_CLK_SEL_ADDR);
-		reg_clksel |= 1; /* CLK_SEL_SRC1NO  == SRC1 */
-		writel(reg_clksel, A11S_CLK_SEL_ADDR);
-	} else {
-		/* SRC1 */
-
-		/* Program clock source */
-		reg_clkctl = readl(A11S_CLK_CNTL_ADDR);
-		reg_clkctl &= ~(0x07 << 12);
-		reg_clkctl |= (hunt_s->a11clk_src_sel << 12);
-		writel(reg_clkctl, A11S_CLK_CNTL_ADDR);
-
-		/* Program clock divider */
-		reg_clkctl = readl(A11S_CLK_CNTL_ADDR);
-		reg_clkctl &= ~(0xf << 8);
-		reg_clkctl |= (hunt_s->a11clk_src_div << 8);
-		writel(reg_clkctl, A11S_CLK_CNTL_ADDR);
-
-		/* Program clock source selection */
-		reg_clksel = readl(A11S_CLK_SEL_ADDR);
-		reg_clksel &= ~1; /* CLK_SEL_SRC1NO  == SRC0 */
-		writel(reg_clksel, A11S_CLK_SEL_ADDR);
-	}
-
-	/*
-	 * If the new clock divider is lower than the previous, then
-	 * program the divider after switching the clock
-	 */
-	if (hunt_s->ahbclk_div < clk_div) {
-		reg_clksel = readl(A11S_CLK_SEL_ADDR);
-		reg_clksel &= ~(0x3 << 1);
-		reg_clksel |= (hunt_s->ahbclk_div << 1);
-		writel(reg_clksel, A11S_CLK_SEL_ADDR);
-	}
-}
-
-int acpuclk_set_rate(unsigned long rate, int for_power_collapse)
-{
-	uint32_t reg_clkctl;
-	struct clkctl_acpu_speed *cur_s, *tgt_s, *strt_s;
-	int rc = 0;
-	unsigned int plls_enabled = 0, pll;
-
-	strt_s = cur_s = drv_state.current_speed;
-
-	WARN_ONCE(cur_s == NULL, "acpuclk_set_rate: not initialized\n");
-	if (cur_s == NULL)
-		return -ENOENT;
-
-	if (rate == (cur_s->a11clk_khz * 1000))
-		return 0;
-
-	for (tgt_s = acpu_freq_tbl; tgt_s->a11clk_khz != 0; tgt_s++) {
-		if (tgt_s->a11clk_khz == (rate / 1000))
-			break;
-	}
-
-	if (tgt_s->a11clk_khz == 0)
-		return -EINVAL;
-
-	/* Choose the highest speed speed at or below 'rate' with same PLL. */
-	if (for_power_collapse && tgt_s->a11clk_khz < cur_s->a11clk_khz) {
-		while (tgt_s->pll != ACPU_PLL_TCXO && tgt_s->pll != cur_s->pll)
-			tgt_s--;
-	}
-
-	if (strt_s->pll != ACPU_PLL_TCXO)
-		plls_enabled |= 1 << strt_s->pll;
-
-	if (!for_power_collapse) {
-		mutex_lock(&drv_state.lock);
-		if (strt_s->pll != tgt_s->pll && tgt_s->pll != ACPU_PLL_TCXO) {
-			rc = pc_pll_request(tgt_s->pll, 1);
-			if (rc < 0) {
-				pr_err("PLL%d enable failed (%d)\n",
-					tgt_s->pll, rc);
-				goto out;
-			}
-			plls_enabled |= 1 << tgt_s->pll;
-		}
-		/* Increase VDD if needed. */
-		if (tgt_s->vdd > cur_s->vdd) {
-			if ((rc = acpuclk_set_vdd_level(tgt_s->vdd)) < 0) {
-				printk(KERN_ERR "Unable to switch ACPU vdd\n");
-				goto out;
-			}
-		}
-	}
-
-	/* Set wait states for CPU between frequency changes */
-	reg_clkctl = readl(A11S_CLK_CNTL_ADDR);
-	reg_clkctl |= (100 << 16); /* set WT_ST_CNT */
-	writel(reg_clkctl, A11S_CLK_CNTL_ADDR);
-
-#if PERF_SWITCH_DEBUG
-	printk(KERN_INFO "acpuclock: Switching from ACPU rate %u -> %u\n",
-	       strt_s->a11clk_khz * 1000, tgt_s->a11clk_khz * 1000);
-#endif
-
-	while (cur_s != tgt_s) {
-		/*
-		 * Always jump to target freq if within 256mhz, regulardless of
-		 * PLL. If differnece is greater, use the predefinied
-		 * steppings in the table.
-		 */
-		int d = abs((int)(cur_s->a11clk_khz - tgt_s->a11clk_khz));
-		if (d > drv_state.max_speed_delta_khz) {
-			/* Step up or down depending on target vs current. */
-			int clk_index = tgt_s->a11clk_khz > cur_s->a11clk_khz ?
-				cur_s->up : cur_s->down;
-			if (clk_index < 0) { /* This should not happen. */
-				printk(KERN_ERR "cur:%u target: %u\n",
-					cur_s->a11clk_khz, tgt_s->a11clk_khz);
-				rc = -EINVAL;
-				goto out;
-			}
-			cur_s = &acpu_freq_tbl[clk_index];
-		} else {
-			cur_s = tgt_s;
-		}
-#if PERF_SWITCH_STEP_DEBUG
-		printk(KERN_DEBUG "%s: STEP khz = %u, pll = %d\n",
-			__FUNCTION__, cur_s->a11clk_khz, cur_s->pll);
-#endif
-		if (!for_power_collapse&& cur_s->pll != ACPU_PLL_TCXO
-		    && !(plls_enabled & (1 << cur_s->pll))) {
-			rc = pc_pll_request(cur_s->pll, 1);
-			if (rc < 0) {
-				pr_err("PLL%d enable failed (%d)\n",
-					cur_s->pll, rc);
-				goto out;
-			}
-			plls_enabled |= 1 << cur_s->pll;
-		}
-
-		acpuclk_set_div(cur_s);
-		drv_state.current_speed = cur_s;
-		/* Re-adjust lpj for the new clock speed. */
-		loops_per_jiffy = cur_s->lpj;
-		udelay(drv_state.acpu_switch_time_us);
-	}
-
-	/* Nothing else to do for power collapse. */
-	if (for_power_collapse)
-		return 0;
-
-	/* Disable PLLs we are not using anymore. */
-	plls_enabled &= ~(1 << tgt_s->pll);
-	for (pll = ACPU_PLL_0; pll <= ACPU_PLL_2; pll++)
-		if (plls_enabled & (1 << pll)) {
-			rc = pc_pll_request(pll, 0);
-			if (rc < 0) {
-				pr_err("PLL%d disable failed (%d)\n", pll, rc);
-				goto out;
-			}
-		}
-
-	/* Change the AXI bus frequency if we can. */
-	if (strt_s->axiclk_khz != tgt_s->axiclk_khz) {
-		rc = clk_set_rate(ebi1_clk, tgt_s->axiclk_khz * 1000);
-		if (rc < 0)
-			pr_err("Setting AXI min rate failed!\n");
-	}
-
-	/* Drop VDD level if we can. */
-	if (tgt_s->vdd < strt_s->vdd) {
-		if (acpuclk_set_vdd_level(tgt_s->vdd) < 0)
-			printk(KERN_ERR "acpuclock: Unable to drop ACPU vdd\n");
-	}
-
-#if PERF_SWITCH_DEBUG
-	printk(KERN_DEBUG "%s: ACPU speed change complete\n", __FUNCTION__);
-#endif
-out:
-	if (!for_power_collapse)
-		mutex_unlock(&drv_state.lock);
-	return rc;
-}
-
-static void __init acpuclk_init(void)
-{
-	struct clkctl_acpu_speed *speed;
-	uint32_t div, sel;
-	int rc;
-
-	/*
-	 * Determine the rate of ACPU clock
-	 */
-
-	if (!(readl(A11S_CLK_SEL_ADDR) & 0x01)) { /* CLK_SEL_SRC1N0 */
-		/* CLK_SRC0_SEL */
-		sel = (readl(A11S_CLK_CNTL_ADDR) >> 12) & 0x7;
-		/* CLK_SRC0_DIV */
-		div = (readl(A11S_CLK_CNTL_ADDR) >> 8) & 0x0f;
-	} else {
-		/* CLK_SRC1_SEL */
-		sel = (readl(A11S_CLK_CNTL_ADDR) >> 4) & 0x07;
-		/* CLK_SRC1_DIV */
-		div = readl(A11S_CLK_CNTL_ADDR) & 0x0f;
-	}
-
-	for (speed = acpu_freq_tbl; speed->a11clk_khz != 0; speed++) {
-		if (speed->a11clk_src_sel == sel
-		 && (speed->a11clk_src_div == div))
-			break;
-	}
-	if (speed->a11clk_khz == 0) {
-		printk(KERN_WARNING "Warning - ACPU clock reports invalid speed\n");
-		return;
-	}
-
-	drv_state.current_speed = speed;
-
-	rc = clk_set_rate(ebi1_clk, speed->axiclk_khz * 1000);
-	if (rc < 0)
-		pr_err("Setting AXI min rate failed!\n");
-
-	printk(KERN_INFO "ACPU running at %d KHz\n", speed->a11clk_khz);
-}
-
-unsigned long acpuclk_get_rate(void)
-{
-	WARN_ONCE(drv_state.current_speed == NULL,
-		  "acpuclk_get_rate: not initialized\n");
-	if (drv_state.current_speed)
-		return drv_state.current_speed->a11clk_khz;
-	else
-		return 0;
-}
-
-uint32_t acpuclk_get_switch_time(void)
-{
-	return drv_state.acpu_switch_time_us;
-}
-
-/*----------------------------------------------------------------------------
- * Clock driver initialization
- *---------------------------------------------------------------------------*/
-
-/* Initialize the lpj field in the acpu_freq_tbl. */
-static void __init lpj_init(void)
-{
-	int i;
-	const struct clkctl_acpu_speed *base_clk = drv_state.current_speed;
-	for (i = 0; acpu_freq_tbl[i].a11clk_khz; i++) {
-		acpu_freq_tbl[i].lpj = cpufreq_scale(loops_per_jiffy,
-						base_clk->a11clk_khz,
-						acpu_freq_tbl[i].a11clk_khz);
-	}
-}
-
-void __init msm_acpu_clock_init(struct msm_acpu_clock_platform_data *clkdata)
-{
-	pr_info("acpu_clock_init()\n");
-
-	ebi1_clk = clk_get(NULL, "ebi1_clk");
-
-	mutex_init(&drv_state.lock);
-	drv_state.acpu_switch_time_us = clkdata->acpu_switch_time_us;
-	drv_state.max_speed_delta_khz = clkdata->max_speed_delta_khz;
-	drv_state.vdd_switch_time_us = clkdata->vdd_switch_time_us;
-	drv_state.power_collapse_khz = clkdata->power_collapse_khz;
-	drv_state.wait_for_irq_khz = clkdata->wait_for_irq_khz;
-	acpuclk_init();
-	lpj_init();
-#ifdef CONFIG_CPU_FREQ_TABLE
-	cpufreq_frequency_table_get_attr(freq_table, smp_processor_id());
-#endif
-}
diff --git a/arch/arm/mach-msm/acpuclock.h b/arch/arm/mach-msm/acpuclock.h
deleted file mode 100644
index 415de2e..0000000
--- a/arch/arm/mach-msm/acpuclock.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/* arch/arm/mach-msm/acpuclock.h
- *
- * MSM architecture clock driver header
- *
- * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2007 QUALCOMM Incorporated
- * Author: San Mehat <san@android.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef __ARCH_ARM_MACH_MSM_ACPUCLOCK_H
-#define __ARCH_ARM_MACH_MSM_ACPUCLOCK_H
-
-int acpuclk_set_rate(unsigned long rate, int for_power_collapse);
-unsigned long acpuclk_get_rate(void);
-uint32_t acpuclk_get_switch_time(void);
-unsigned long acpuclk_wait_for_irq(void);
-unsigned long acpuclk_power_collapse(void);
-unsigned long acpuclk_get_wfi_rate(void);
-
-
-#endif
-
diff --git a/arch/arm/mach-msm/board-dt-8660.c b/arch/arm/mach-msm/board-dt-8660.c
new file mode 100644
index 0000000..b5b4de2
--- /dev/null
+++ b/arch/arm/mach-msm/board-dt-8660.c
@@ -0,0 +1,64 @@
+/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/init.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+
+#include <asm/mach/arch.h>
+#include <asm/hardware/gic.h>
+
+#include <mach/board.h>
+#include "common.h"
+
+static const struct of_device_id msm_dt_gic_match[] __initconst = {
+	{ .compatible = "qcom,msm-8660-qgic", .data = gic_of_init },
+	{}
+};
+
+static void __init msm8x60_init_irq(void)
+{
+	of_irq_init(msm_dt_gic_match);
+}
+
+static void __init msm8x60_init_late(void)
+{
+	smd_debugfs_init();
+}
+
+static struct of_dev_auxdata msm_auxdata_lookup[] __initdata = {
+	{}
+};
+
+static void __init msm8x60_dt_init(void)
+{
+	of_platform_populate(NULL, of_default_bus_match_table,
+			msm_auxdata_lookup, NULL);
+}
+
+static const char *msm8x60_fluid_match[] __initdata = {
+	"qcom,msm8660-fluid",
+	"qcom,msm8660-surf",
+	NULL
+};
+
+DT_MACHINE_START(MSM_DT, "Qualcomm MSM (Flattened Device Tree)")
+	.smp = smp_ops(msm_smp_ops),
+	.map_io = msm_map_msm8x60_io,
+	.init_irq = msm8x60_init_irq,
+	.handle_irq = gic_handle_irq,
+	.init_machine = msm8x60_dt_init,
+	.init_late = msm8x60_init_late,
+	.timer = &msm_dt_timer,
+	.dt_compat = msm8x60_fluid_match,
+MACHINE_END
diff --git a/arch/arm/mach-msm/board-dt-8960.c b/arch/arm/mach-msm/board-dt-8960.c
new file mode 100644
index 0000000..4490edb
--- /dev/null
+++ b/arch/arm/mach-msm/board-dt-8960.c
@@ -0,0 +1,50 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/init.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+
+#include <asm/hardware/gic.h>
+#include <asm/mach/arch.h>
+
+#include "common.h"
+
+static const struct of_device_id msm_dt_gic_match[] __initconst = {
+	{ .compatible = "qcom,msm-qgic2", .data = gic_of_init },
+	{ }
+};
+
+static void __init msm_dt_init_irq(void)
+{
+	of_irq_init(msm_dt_gic_match);
+}
+
+static void __init msm_dt_init(void)
+{
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+}
+
+static const char * const msm8960_dt_match[] __initconst = {
+	"qcom,msm8960-cdp",
+	NULL
+};
+
+DT_MACHINE_START(MSM8960_DT, "Qualcomm MSM (Flattened Device Tree)")
+	.smp = smp_ops(msm_smp_ops),
+	.map_io = msm_map_msm8960_io,
+	.init_irq = msm_dt_init_irq,
+	.timer = &msm_dt_timer,
+	.init_machine = msm_dt_init,
+	.dt_compat = msm8960_dt_match,
+	.handle_irq = gic_handle_irq,
+MACHINE_END
diff --git a/arch/arm/mach-msm/board-halibut.c b/arch/arm/mach-msm/board-halibut.c
index 4fa3e99..6ce542e 100644
--- a/arch/arm/mach-msm/board-halibut.c
+++ b/arch/arm/mach-msm/board-halibut.c
@@ -36,6 +36,7 @@
 #include <linux/mtd/partitions.h>
 
 #include "devices.h"
+#include "common.h"
 
 static struct resource smc91x_resources[] = {
 	[0] = {
@@ -66,8 +67,6 @@ static struct platform_device *devices[] __initdata = {
 	&smc91x_device,
 };
 
-extern struct sys_timer msm_timer;
-
 static void __init halibut_init_early(void)
 {
 	arch_ioremap_caller = __msm_ioremap_caller;
@@ -107,5 +106,5 @@ MACHINE_START(HALIBUT, "Halibut Board (QCT SURF7200A)")
 	.init_irq	= halibut_init_irq,
 	.init_machine	= halibut_init,
 	.init_late	= halibut_init_late,
-	.timer		= &msm_timer,
+	.timer		= &msm7x01_timer,
 MACHINE_END
diff --git a/arch/arm/mach-msm/board-mahimahi.c b/arch/arm/mach-msm/board-mahimahi.c
index cf1f89a..df00bc0 100644
--- a/arch/arm/mach-msm/board-mahimahi.c
+++ b/arch/arm/mach-msm/board-mahimahi.c
@@ -30,7 +30,6 @@
 
 #include <mach/board.h>
 #include <mach/hardware.h>
-#include <mach/system.h>
 
 #include "board-mahimahi.h"
 #include "devices.h"
diff --git a/arch/arm/mach-msm/board-msm7x27.c b/arch/arm/mach-msm/board-msm7x27.c
deleted file mode 100644
index 451ab1d..0000000
--- a/arch/arm/mach-msm/board-msm7x27.c
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
- * Author: Brian Swetland <swetland@google.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-#include <linux/gpio.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/input.h>
-#include <linux/io.h>
-#include <linux/delay.h>
-#include <linux/power_supply.h>
-
-#include <mach/hardware.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/flash.h>
-#include <asm/setup.h>
-#ifdef CONFIG_CACHE_L2X0
-#include <asm/hardware/cache-l2x0.h>
-#endif
-
-#include <mach/vreg.h>
-#include <mach/mpp.h>
-#include <mach/board.h>
-#include <mach/msm_iomap.h>
-
-#include <linux/mtd/nand.h>
-#include <linux/mtd/partitions.h>
-
-#include "devices.h"
-#include "socinfo.h"
-#include "clock.h"
-
-static struct resource smc91x_resources[] = {
-	[0] = {
-		.start	= 0x9C004300,
-		.end	= 0x9C0043ff,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= MSM_GPIO_TO_INT(132),
-		.end	= MSM_GPIO_TO_INT(132),
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device smc91x_device = {
-	.name		= "smc91x",
-	.id		= 0,
-	.num_resources	= ARRAY_SIZE(smc91x_resources),
-	.resource	= smc91x_resources,
-};
-
-static struct platform_device *devices[] __initdata = {
-	&msm_device_uart3,
-	&msm_device_smd,
-	&msm_device_dmov,
-	&msm_device_nand,
-	&smc91x_device,
-};
-
-extern struct sys_timer msm_timer;
-
-static void __init msm7x2x_init_irq(void)
-{
-	msm_init_irq();
-}
-
-static void __init msm7x2x_init(void)
-{
-	if (socinfo_init() < 0)
-		BUG();
-
-	if (machine_is_msm7x25_ffa() || machine_is_msm7x27_ffa()) {
-		smc91x_resources[0].start = 0x98000300;
-		smc91x_resources[0].end = 0x980003ff;
-		smc91x_resources[1].start = MSM_GPIO_TO_INT(85);
-		smc91x_resources[1].end = MSM_GPIO_TO_INT(85);
-		if (gpio_tlmm_config(GPIO_CFG(85, 0,
-					      GPIO_INPUT,
-					      GPIO_PULL_DOWN,
-					      GPIO_2MA),
-				     GPIO_ENABLE)) {
-			printk(KERN_ERR
-			       "%s: Err: Config GPIO-85 INT\n",
-				__func__);
-		}
-	}
-
-	platform_add_devices(devices, ARRAY_SIZE(devices));
-}
-
-static void __init msm7x2x_map_io(void)
-{
-	msm_map_common_io();
-	/* Technically dependent on the SoC but using machine_is
-	 * macros since socinfo is not available this early and there
-	 * are plans to restructure the code which will eliminate the
-	 * need for socinfo.
-	 */
-	if (machine_is_msm7x27_surf() || machine_is_msm7x27_ffa())
-		msm_clock_init(msm_clocks_7x27, msm_num_clocks_7x27);
-
-	if (machine_is_msm7x25_surf() || machine_is_msm7x25_ffa())
-		msm_clock_init(msm_clocks_7x25, msm_num_clocks_7x25);
-
-#ifdef CONFIG_CACHE_L2X0
-	if (machine_is_msm7x27_surf() || machine_is_msm7x27_ffa()) {
-		/* 7x27 has 256KB L2 cache:
-			64Kb/Way and 4-Way Associativity;
-			R/W latency: 3 cycles;
-			evmon/parity/share disabled. */
-		l2x0_init(MSM_L2CC_BASE, 0x00068012, 0xfe000000);
-	}
-#endif
-}
-
-static void __init msm7x2x_init_late(void)
-{
-	smd_debugfs_init();
-}
-
-MACHINE_START(MSM7X27_SURF, "QCT MSM7x27 SURF")
-	.atag_offset	= 0x100,
-	.map_io		= msm7x2x_map_io,
-	.init_irq	= msm7x2x_init_irq,
-	.init_machine	= msm7x2x_init,
-	.init_late	= msm7x2x_init_late,
-	.timer		= &msm_timer,
-MACHINE_END
-
-MACHINE_START(MSM7X27_FFA, "QCT MSM7x27 FFA")
-	.atag_offset	= 0x100,
-	.map_io		= msm7x2x_map_io,
-	.init_irq	= msm7x2x_init_irq,
-	.init_machine	= msm7x2x_init,
-	.init_late	= msm7x2x_init_late,
-	.timer		= &msm_timer,
-MACHINE_END
-
-MACHINE_START(MSM7X25_SURF, "QCT MSM7x25 SURF")
-	.atag_offset	= 0x100,
-	.map_io		= msm7x2x_map_io,
-	.init_irq	= msm7x2x_init_irq,
-	.init_machine	= msm7x2x_init,
-	.init_late	= msm7x2x_init_late,
-	.timer		= &msm_timer,
-MACHINE_END
-
-MACHINE_START(MSM7X25_FFA, "QCT MSM7x25 FFA")
-	.atag_offset	= 0x100,
-	.map_io		= msm7x2x_map_io,
-	.init_irq	= msm7x2x_init_irq,
-	.init_machine	= msm7x2x_init,
-	.init_late	= msm7x2x_init_late,
-	.timer		= &msm_timer,
-MACHINE_END
diff --git a/arch/arm/mach-msm/board-msm7x30.c b/arch/arm/mach-msm/board-msm7x30.c
index a500137..effa6f4 100644
--- a/arch/arm/mach-msm/board-msm7x30.c
+++ b/arch/arm/mach-msm/board-msm7x30.c
@@ -38,8 +38,7 @@
 #include "devices.h"
 #include "gpiomux.h"
 #include "proc_comm.h"
-
-extern struct sys_timer msm_timer;
+#include "common.h"
 
 static void __init msm7x30_fixup(struct tag *tag, char **cmdline,
 		struct meminfo *mi)
@@ -132,7 +131,7 @@ MACHINE_START(MSM7X30_SURF, "QCT MSM7X30 SURF")
 	.init_irq = msm7x30_init_irq,
 	.init_machine = msm7x30_init,
 	.init_late = msm7x30_init_late,
-	.timer = &msm_timer,
+	.timer = &msm7x30_timer,
 MACHINE_END
 
 MACHINE_START(MSM7X30_FFA, "QCT MSM7X30 FFA")
@@ -143,7 +142,7 @@ MACHINE_START(MSM7X30_FFA, "QCT MSM7X30 FFA")
 	.init_irq = msm7x30_init_irq,
 	.init_machine = msm7x30_init,
 	.init_late = msm7x30_init_late,
-	.timer = &msm_timer,
+	.timer = &msm7x30_timer,
 MACHINE_END
 
 MACHINE_START(MSM7X30_FLUID, "QCT MSM7X30 FLUID")
@@ -154,5 +153,5 @@ MACHINE_START(MSM7X30_FLUID, "QCT MSM7X30 FLUID")
 	.init_irq = msm7x30_init_irq,
 	.init_machine = msm7x30_init,
 	.init_late = msm7x30_init_late,
-	.timer = &msm_timer,
+	.timer = &msm7x30_timer,
 MACHINE_END
diff --git a/arch/arm/mach-msm/board-msm8960.c b/arch/arm/mach-msm/board-msm8960.c
deleted file mode 100644
index 65f4a1d..0000000
--- a/arch/arm/mach-msm/board-msm8960.c
+++ /dev/null
@@ -1,122 +0,0 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- */
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/irq.h>
-#include <linux/clkdev.h>
-#include <linux/memblock.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/hardware/gic.h>
-#include <asm/setup.h>
-
-#include <mach/board.h>
-#include <mach/msm_iomap.h>
-
-#include "devices.h"
-
-static void __init msm8960_fixup(struct tag *tag, char **cmdline,
-		struct meminfo *mi)
-{
-	for (; tag->hdr.size; tag = tag_next(tag))
-		if (tag->hdr.tag == ATAG_MEM &&
-				tag->u.mem.start == 0x40200000) {
-			tag->u.mem.start = 0x40000000;
-			tag->u.mem.size += SZ_2M;
-		}
-}
-
-static void __init msm8960_reserve(void)
-{
-	memblock_remove(0x40000000, SZ_2M);
-}
-
-static void __init msm8960_map_io(void)
-{
-	msm_map_msm8960_io();
-}
-
-static void __init msm8960_init_irq(void)
-{
-	unsigned int i;
-	gic_init(0, GIC_PPI_START, MSM_QGIC_DIST_BASE,
-		 (void *)MSM_QGIC_CPU_BASE);
-
-	/* Edge trigger PPIs except AVS_SVICINT and AVS_SVICINTSWDONE */
-	writel(0xFFFFD7FF, MSM_QGIC_DIST_BASE + GIC_DIST_CONFIG + 4);
-
-	if (machine_is_msm8960_rumi3())
-		writel(0x0000FFFF, MSM_QGIC_DIST_BASE + GIC_DIST_ENABLE_SET);
-
-	/* FIXME: Not installing AVS_SVICINT and AVS_SVICINTSWDONE yet
-	 * as they are configured as level, which does not play nice with
-	 * handle_percpu_irq.
-	 */
-	for (i = GIC_PPI_START; i < GIC_SPI_START; i++) {
-		if (i != AVS_SVICINT && i != AVS_SVICINTSWDONE)
-			irq_set_handler(i, handle_percpu_irq);
-	}
-}
-
-static struct platform_device *sim_devices[] __initdata = {
-	&msm8960_device_uart_gsbi2,
-};
-
-static struct platform_device *rumi3_devices[] __initdata = {
-	&msm8960_device_uart_gsbi5,
-};
-
-static void __init msm8960_sim_init(void)
-{
-	platform_add_devices(sim_devices, ARRAY_SIZE(sim_devices));
-}
-
-static void __init msm8960_rumi3_init(void)
-{
-	platform_add_devices(rumi3_devices, ARRAY_SIZE(rumi3_devices));
-}
-
-static void __init msm8960_init_late(void)
-{
-	smd_debugfs_init();
-}
-
-MACHINE_START(MSM8960_SIM, "QCT MSM8960 SIMULATOR")
-	.fixup = msm8960_fixup,
-	.reserve = msm8960_reserve,
-	.map_io = msm8960_map_io,
-	.init_irq = msm8960_init_irq,
-	.timer = &msm_timer,
-	.handle_irq = gic_handle_irq,
-	.init_machine = msm8960_sim_init,
-	.init_late = msm8960_init_late,
-MACHINE_END
-
-MACHINE_START(MSM8960_RUMI3, "QCT MSM8960 RUMI3")
-	.fixup = msm8960_fixup,
-	.reserve = msm8960_reserve,
-	.map_io = msm8960_map_io,
-	.init_irq = msm8960_init_irq,
-	.timer = &msm_timer,
-	.handle_irq = gic_handle_irq,
-	.init_machine = msm8960_rumi3_init,
-	.init_late = msm8960_init_late,
-MACHINE_END
-
diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c
deleted file mode 100644
index e37a724..0000000
--- a/arch/arm/mach-msm/board-msm8x60.c
+++ /dev/null
@@ -1,166 +0,0 @@
-/* Copyright (c) 2010, 2011, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/irq.h>
-#include <linux/irqdomain.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/of_irq.h>
-#include <linux/of_platform.h>
-#include <linux/memblock.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/hardware/gic.h>
-#include <asm/setup.h>
-
-#include <mach/board.h>
-#include <mach/msm_iomap.h>
-
-static void __init msm8x60_fixup(struct tag *tag, char **cmdline,
-		struct meminfo *mi)
-{
-	for (; tag->hdr.size; tag = tag_next(tag))
-		if (tag->hdr.tag == ATAG_MEM &&
-				tag->u.mem.start == 0x40200000) {
-			tag->u.mem.start = 0x40000000;
-			tag->u.mem.size += SZ_2M;
-		}
-}
-
-static void __init msm8x60_reserve(void)
-{
-	memblock_remove(0x40000000, SZ_2M);
-}
-
-static void __init msm8x60_map_io(void)
-{
-	msm_map_msm8x60_io();
-}
-
-#ifdef CONFIG_OF
-static struct of_device_id msm_dt_gic_match[] __initdata = {
-	{ .compatible = "qcom,msm-8660-qgic", .data = gic_of_init },
-	{}
-};
-#endif
-
-static void __init msm8x60_init_irq(void)
-{
-	if (!of_have_populated_dt())
-		gic_init(0, GIC_PPI_START, MSM_QGIC_DIST_BASE,
-			 (void *)MSM_QGIC_CPU_BASE);
-#ifdef CONFIG_OF
-	else
-		of_irq_init(msm_dt_gic_match);
-#endif
-
-	/* Edge trigger PPIs except AVS_SVICINT and AVS_SVICINTSWDONE */
-	writel(0xFFFFD7FF, MSM_QGIC_DIST_BASE + GIC_DIST_CONFIG + 4);
-
-	/* RUMI does not adhere to GIC spec by enabling STIs by default.
-	 * Enable/clear is supposed to be RO for STIs, but is RW on RUMI.
-	 */
-	if (!machine_is_msm8x60_sim())
-		writel(0x0000FFFF, MSM_QGIC_DIST_BASE + GIC_DIST_ENABLE_SET);
-}
-
-static void __init msm8x60_init(void)
-{
-}
-
-static void __init msm8x60_init_late(void)
-{
-	smd_debugfs_init();
-}
-
-#ifdef CONFIG_OF
-static struct of_dev_auxdata msm_auxdata_lookup[] __initdata = {
-	{}
-};
-
-static void __init msm8x60_dt_init(void)
-{
-	if (of_machine_is_compatible("qcom,msm8660-surf")) {
-		printk(KERN_INFO "Init surf UART registers\n");
-		msm8x60_init_uart12dm();
-	}
-
-	of_platform_populate(NULL, of_default_bus_match_table,
-			msm_auxdata_lookup, NULL);
-}
-
-static const char *msm8x60_fluid_match[] __initdata = {
-	"qcom,msm8660-fluid",
-	"qcom,msm8660-surf",
-	NULL
-};
-#endif /* CONFIG_OF */
-
-MACHINE_START(MSM8X60_RUMI3, "QCT MSM8X60 RUMI3")
-	.fixup = msm8x60_fixup,
-	.reserve = msm8x60_reserve,
-	.map_io = msm8x60_map_io,
-	.init_irq = msm8x60_init_irq,
-	.handle_irq = gic_handle_irq,
-	.init_machine = msm8x60_init,
-	.init_late = msm8x60_init_late,
-	.timer = &msm_timer,
-MACHINE_END
-
-MACHINE_START(MSM8X60_SURF, "QCT MSM8X60 SURF")
-	.fixup = msm8x60_fixup,
-	.reserve = msm8x60_reserve,
-	.map_io = msm8x60_map_io,
-	.init_irq = msm8x60_init_irq,
-	.handle_irq = gic_handle_irq,
-	.init_machine = msm8x60_init,
-	.init_late = msm8x60_init_late,
-	.timer = &msm_timer,
-MACHINE_END
-
-MACHINE_START(MSM8X60_SIM, "QCT MSM8X60 SIMULATOR")
-	.fixup = msm8x60_fixup,
-	.reserve = msm8x60_reserve,
-	.map_io = msm8x60_map_io,
-	.init_irq = msm8x60_init_irq,
-	.handle_irq = gic_handle_irq,
-	.init_machine = msm8x60_init,
-	.init_late = msm8x60_init_late,
-	.timer = &msm_timer,
-MACHINE_END
-
-MACHINE_START(MSM8X60_FFA, "QCT MSM8X60 FFA")
-	.fixup = msm8x60_fixup,
-	.reserve = msm8x60_reserve,
-	.map_io = msm8x60_map_io,
-	.init_irq = msm8x60_init_irq,
-	.handle_irq = gic_handle_irq,
-	.init_machine = msm8x60_init,
-	.init_late = msm8x60_init_late,
-	.timer = &msm_timer,
-MACHINE_END
-
-#ifdef CONFIG_OF
-/* TODO: General device tree support for all MSM. */
-DT_MACHINE_START(MSM_DT, "Qualcomm MSM (Flattened Device Tree)")
-	.map_io = msm8x60_map_io,
-	.init_irq = msm8x60_init_irq,
-	.init_machine = msm8x60_dt_init,
-	.init_late = msm8x60_init_late,
-	.timer = &msm_timer,
-	.dt_compat = msm8x60_fluid_match,
-MACHINE_END
-#endif /* CONFIG_OF */
diff --git a/arch/arm/mach-msm/board-qsd8x50.c b/arch/arm/mach-msm/board-qsd8x50.c
index c8fe0ed..2448fcf 100644
--- a/arch/arm/mach-msm/board-qsd8x50.c
+++ b/arch/arm/mach-msm/board-qsd8x50.c
@@ -32,14 +32,13 @@
 #include <mach/irqs.h>
 #include <mach/sirc.h>
 #include <mach/vreg.h>
-#include <mach/mmc.h>
+#include <linux/platform_data/mmc-msm_sdcc.h>
 
 #include "devices.h"
+#include "common.h"
 
-extern struct sys_timer msm_timer;
-
-static const resource_size_t qsd8x50_surf_smc91x_base __initdata = 0x70000300;
-static const unsigned        qsd8x50_surf_smc91x_gpio __initdata = 156;
+static const resource_size_t qsd8x50_surf_smc91x_base __initconst = 0x70000300;
+static const unsigned        qsd8x50_surf_smc91x_gpio __initconst = 156;
 
 /* Leave smc91x resources empty here, as we'll fill them in
  * at run-time: they vary from board to board, and the true
@@ -201,7 +200,7 @@ MACHINE_START(QSD8X50_SURF, "QCT QSD8X50 SURF")
 	.init_irq = qsd8x50_init_irq,
 	.init_machine = qsd8x50_init,
 	.init_late = qsd8x50_init_late,
-	.timer = &msm_timer,
+	.timer = &qsd8x50_timer,
 MACHINE_END
 
 MACHINE_START(QSD8X50A_ST1_5, "QCT QSD8X50A ST1.5")
@@ -210,5 +209,5 @@ MACHINE_START(QSD8X50A_ST1_5, "QCT QSD8X50A ST1.5")
 	.init_irq = qsd8x50_init_irq,
 	.init_machine = qsd8x50_init,
 	.init_late = qsd8x50_init_late,
-	.timer = &msm_timer,
+	.timer = &qsd8x50_timer,
 MACHINE_END
diff --git a/arch/arm/mach-msm/board-sapphire.c b/arch/arm/mach-msm/board-sapphire.c
index 2e569ab..b7b0fc7 100644
--- a/arch/arm/mach-msm/board-sapphire.c
+++ b/arch/arm/mach-msm/board-sapphire.c
@@ -27,7 +27,6 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/flash.h>
-#include <mach/system.h>
 #include <mach/vreg.h>
 #include <mach/board.h>
 
diff --git a/arch/arm/mach-msm/board-trout-mmc.c b/arch/arm/mach-msm/board-trout-mmc.c
index 8650342..3723e55 100644
--- a/arch/arm/mach-msm/board-trout-mmc.c
+++ b/arch/arm/mach-msm/board-trout-mmc.c
@@ -15,7 +15,7 @@
 
 #include <mach/vreg.h>
 
-#include <mach/mmc.h>
+#include <linux/platform_data/mmc-msm_sdcc.h>
 
 #include "devices.h"
 
diff --git a/arch/arm/mach-msm/board-trout-panel.c b/arch/arm/mach-msm/board-trout-panel.c
index 89bf6b4..f9a5db6 100644
--- a/arch/arm/mach-msm/board-trout-panel.c
+++ b/arch/arm/mach-msm/board-trout-panel.c
@@ -14,7 +14,7 @@
 #include <asm/mach-types.h>
 #include <asm/system_info.h>
 
-#include <mach/msm_fb.h>
+#include <linux/platform_data/video-msm_fb.h>
 #include <mach/vreg.h>
 
 #include "board-trout.h"
diff --git a/arch/arm/mach-msm/board-trout.c b/arch/arm/mach-msm/board-trout.c
index bbe13f1..4ba0800 100644
--- a/arch/arm/mach-msm/board-trout.c
+++ b/arch/arm/mach-msm/board-trout.c
@@ -31,6 +31,7 @@
 
 #include "devices.h"
 #include "board-trout.h"
+#include "common.h"
 
 extern int trout_init_mmc(unsigned int);
 
@@ -42,8 +43,6 @@ static struct platform_device *devices[] __initdata = {
 	&msm_device_i2c,
 };
 
-extern struct sys_timer msm_timer;
-
 static void __init trout_init_early(void)
 {
 	arch_ioremap_caller = __msm_ioremap_caller;
@@ -111,5 +110,5 @@ MACHINE_START(TROUT, "HTC Dream")
 	.init_irq	= trout_init_irq,
 	.init_machine	= trout_init,
 	.init_late	= trout_init_late,
-	.timer		= &msm_timer,
+	.timer		= &msm7x01_timer,
 MACHINE_END
diff --git a/arch/arm/mach-msm/clock-pcom.c b/arch/arm/mach-msm/clock-pcom.c
index 63b7113..a52c970 100644
--- a/arch/arm/mach-msm/clock-pcom.c
+++ b/arch/arm/mach-msm/clock-pcom.c
@@ -25,7 +25,7 @@
 /*
  * glue for the proc_comm interface
  */
-int pc_clk_enable(unsigned id)
+static int pc_clk_enable(unsigned id)
 {
 	int rc = msm_proc_comm(PCOM_CLKCTL_RPC_ENABLE, &id, NULL);
 	if (rc < 0)
@@ -34,7 +34,7 @@ int pc_clk_enable(unsigned id)
 		return (int)id < 0 ? -EINVAL : 0;
 }
 
-void pc_clk_disable(unsigned id)
+static void pc_clk_disable(unsigned id)
 {
 	msm_proc_comm(PCOM_CLKCTL_RPC_DISABLE, &id, NULL);
 }
@@ -54,7 +54,7 @@ int pc_clk_reset(unsigned id, enum clk_reset_action action)
 		return (int)id < 0 ? -EINVAL : 0;
 }
 
-int pc_clk_set_rate(unsigned id, unsigned rate)
+static int pc_clk_set_rate(unsigned id, unsigned rate)
 {
 	/* The rate _might_ be rounded off to the nearest KHz value by the
 	 * remote function. So a return value of 0 doesn't necessarily mean
@@ -67,7 +67,7 @@ int pc_clk_set_rate(unsigned id, unsigned rate)
 		return (int)id < 0 ? -EINVAL : 0;
 }
 
-int pc_clk_set_min_rate(unsigned id, unsigned rate)
+static int pc_clk_set_min_rate(unsigned id, unsigned rate)
 {
 	int rc = msm_proc_comm(PCOM_CLKCTL_RPC_MIN_RATE, &id, &rate);
 	if (rc < 0)
@@ -76,7 +76,7 @@ int pc_clk_set_min_rate(unsigned id, unsigned rate)
 		return (int)id < 0 ? -EINVAL : 0;
 }
 
-int pc_clk_set_max_rate(unsigned id, unsigned rate)
+static int pc_clk_set_max_rate(unsigned id, unsigned rate)
 {
 	int rc = msm_proc_comm(PCOM_CLKCTL_RPC_MAX_RATE, &id, &rate);
 	if (rc < 0)
@@ -85,7 +85,7 @@ int pc_clk_set_max_rate(unsigned id, unsigned rate)
 		return (int)id < 0 ? -EINVAL : 0;
 }
 
-int pc_clk_set_flags(unsigned id, unsigned flags)
+static int pc_clk_set_flags(unsigned id, unsigned flags)
 {
 	int rc = msm_proc_comm(PCOM_CLKCTL_RPC_SET_FLAGS, &id, &flags);
 	if (rc < 0)
@@ -94,7 +94,7 @@ int pc_clk_set_flags(unsigned id, unsigned flags)
 		return (int)id < 0 ? -EINVAL : 0;
 }
 
-unsigned pc_clk_get_rate(unsigned id)
+static unsigned pc_clk_get_rate(unsigned id)
 {
 	if (msm_proc_comm(PCOM_CLKCTL_RPC_RATE, &id, NULL))
 		return 0;
@@ -102,7 +102,7 @@ unsigned pc_clk_get_rate(unsigned id)
 		return id;
 }
 
-unsigned pc_clk_is_enabled(unsigned id)
+static unsigned pc_clk_is_enabled(unsigned id)
 {
 	if (msm_proc_comm(PCOM_CLKCTL_RPC_ENABLED, &id, NULL))
 		return 0;
@@ -110,7 +110,7 @@ unsigned pc_clk_is_enabled(unsigned id)
 		return id;
 }
 
-long pc_clk_round_rate(unsigned id, unsigned rate)
+static long pc_clk_round_rate(unsigned id, unsigned rate)
 {
 
 	/* Not really supported; pc_clk_set_rate() does rounding on it's own. */
diff --git a/arch/arm/mach-msm/common.h b/arch/arm/mach-msm/common.h
new file mode 100644
index 0000000..633a7159
--- /dev/null
+++ b/arch/arm/mach-msm/common.h
@@ -0,0 +1,32 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#ifndef __MACH_COMMON_H
+#define __MACH_COMMON_H
+
+extern struct sys_timer msm7x01_timer;
+extern struct sys_timer msm7x30_timer;
+extern struct sys_timer msm_dt_timer;
+extern struct sys_timer qsd8x50_timer;
+
+extern void msm_map_common_io(void);
+extern void msm_map_msm7x30_io(void);
+extern void msm_map_msm8x60_io(void);
+extern void msm_map_msm8960_io(void);
+extern void msm_map_qsd8x50_io(void);
+
+extern void __iomem *__msm_ioremap_caller(unsigned long phys_addr, size_t size,
+					  unsigned int mtype, void *caller);
+
+extern struct smp_operations msm_smp_ops;
+extern void msm_cpu_die(unsigned int cpu);
+
+#endif
diff --git a/arch/arm/mach-msm/core.h b/arch/arm/mach-msm/core.h
new file mode 100644
index 0000000..a9bab53
--- /dev/null
+++ b/arch/arm/mach-msm/core.h
@@ -0,0 +1,2 @@
+extern struct smp_operations msm_smp_ops;
+extern void msm_cpu_die(unsigned int cpu);
diff --git a/arch/arm/mach-msm/devices-msm7x00.c b/arch/arm/mach-msm/devices-msm7x00.c
index 993780f..f66ee6e 100644
--- a/arch/arm/mach-msm/devices-msm7x00.c
+++ b/arch/arm/mach-msm/devices-msm7x00.c
@@ -27,7 +27,7 @@
 
 #include "clock.h"
 #include "clock-pcom.h"
-#include <mach/mmc.h>
+#include <linux/platform_data/mmc-msm_sdcc.h>
 
 static struct resource resources_uart1[] = {
 	{
diff --git a/arch/arm/mach-msm/devices-msm7x30.c b/arch/arm/mach-msm/devices-msm7x30.c
index 09b4f14..e90ab59 100644
--- a/arch/arm/mach-msm/devices-msm7x30.c
+++ b/arch/arm/mach-msm/devices-msm7x30.c
@@ -31,7 +31,7 @@
 #include "clock-pcom.h"
 #include "clock-7x30.h"
 
-#include <mach/mmc.h>
+#include <linux/platform_data/mmc-msm_sdcc.h>
 
 static struct resource resources_uart2[] = {
 	{
diff --git a/arch/arm/mach-msm/devices-msm8960.c b/arch/arm/mach-msm/devices-msm8960.c
deleted file mode 100644
index d9e1f26..0000000
--- a/arch/arm/mach-msm/devices-msm8960.c
+++ /dev/null
@@ -1,85 +0,0 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-
-#include <linux/dma-mapping.h>
-#include <mach/irqs-8960.h>
-#include <mach/board.h>
-
-#include "devices.h"
-
-#define MSM_GSBI2_PHYS		0x16100000
-#define MSM_UART2DM_PHYS	(MSM_GSBI2_PHYS + 0x40000)
-
-#define MSM_GSBI5_PHYS		0x16400000
-#define MSM_UART5DM_PHYS	(MSM_GSBI5_PHYS + 0x40000)
-
-static struct resource resources_uart_gsbi2[] = {
-	{
-		.start	= GSBI2_UARTDM_IRQ,
-		.end	= GSBI2_UARTDM_IRQ,
-		.flags	= IORESOURCE_IRQ,
-	},
-	{
-		.start	= MSM_UART2DM_PHYS,
-		.end	= MSM_UART2DM_PHYS + PAGE_SIZE - 1,
-		.name	= "uart_resource",
-		.flags	= IORESOURCE_MEM,
-	},
-	{
-		.start	= MSM_GSBI2_PHYS,
-		.end	= MSM_GSBI2_PHYS + PAGE_SIZE - 1,
-		.name	= "gsbi_resource",
-		.flags	= IORESOURCE_MEM,
-	},
-};
-
-struct platform_device msm8960_device_uart_gsbi2 = {
-	.name	= "msm_serial",
-	.id	= 0,
-	.num_resources	= ARRAY_SIZE(resources_uart_gsbi2),
-	.resource	= resources_uart_gsbi2,
-};
-
-static struct resource resources_uart_gsbi5[] = {
-	{
-		.start	= GSBI5_UARTDM_IRQ,
-		.end	= GSBI5_UARTDM_IRQ,
-		.flags	= IORESOURCE_IRQ,
-	},
-	{
-		.start	= MSM_UART5DM_PHYS,
-		.end	= MSM_UART5DM_PHYS + PAGE_SIZE - 1,
-		.name	= "uart_resource",
-		.flags	= IORESOURCE_MEM,
-	},
-	{
-		.start	= MSM_GSBI5_PHYS,
-		.end	= MSM_GSBI5_PHYS + PAGE_SIZE - 1,
-		.name	= "gsbi_resource",
-		.flags	= IORESOURCE_MEM,
-	},
-};
-
-struct platform_device msm8960_device_uart_gsbi5 = {
-	.name	= "msm_serial",
-	.id	= 0,
-	.num_resources	= ARRAY_SIZE(resources_uart_gsbi5),
-	.resource	= resources_uart_gsbi5,
-};
diff --git a/arch/arm/mach-msm/devices-qsd8x50.c b/arch/arm/mach-msm/devices-qsd8x50.c
index 131633b..4db61d5 100644
--- a/arch/arm/mach-msm/devices-qsd8x50.c
+++ b/arch/arm/mach-msm/devices-qsd8x50.c
@@ -27,7 +27,7 @@
 
 #include <asm/mach/flash.h>
 
-#include <mach/mmc.h>
+#include <linux/platform_data/mmc-msm_sdcc.h>
 #include "clock-pcom.h"
 
 static struct resource resources_uart3[] = {
diff --git a/arch/arm/mach-msm/dma.c b/arch/arm/mach-msm/dma.c
index 02cae5e..354b91d 100644
--- a/arch/arm/mach-msm/dma.c
+++ b/arch/arm/mach-msm/dma.c
@@ -223,8 +223,7 @@ static irqreturn_t msm_datamover_irq_handler(int irq, void *dev_id)
 			PRINT_FLOW("msm_datamover_irq_handler id %d, status %x\n", id, ch_status);
 			if ((ch_status & DMOV_STATUS_CMD_PTR_RDY) && !list_empty(&ready_commands[id])) {
 				cmd = list_entry(ready_commands[id].next, typeof(*cmd), list);
-				list_del(&cmd->list);
-				list_add_tail(&cmd->list, &active_commands[id]);
+				list_move_tail(&cmd->list, &active_commands[id]);
 				if (cmd->execute_func)
 					cmd->execute_func(cmd);
 				PRINT_FLOW("msm_datamover_irq_handler id %d, start command\n", id);
diff --git a/arch/arm/mach-msm/hotplug.c b/arch/arm/mach-msm/hotplug.c
index a446fc1..750446f 100644
--- a/arch/arm/mach-msm/hotplug.c
+++ b/arch/arm/mach-msm/hotplug.c
@@ -13,7 +13,7 @@
 #include <asm/cacheflush.h>
 #include <asm/smp_plat.h>
 
-extern volatile int pen_release;
+#include "common.h"
 
 static inline void cpu_enter_lowpower(void)
 {
@@ -57,17 +57,12 @@ static inline void platform_do_lowpower(unsigned int cpu)
 	}
 }
 
-int platform_cpu_kill(unsigned int cpu)
-{
-	return 1;
-}
-
 /*
  * platform-specific code to shutdown a CPU
  *
  * Called with IRQs disabled
  */
-void platform_cpu_die(unsigned int cpu)
+void __ref msm_cpu_die(unsigned int cpu)
 {
 	/*
 	 * we're ready for shutdown now, so do it
@@ -81,12 +76,3 @@ void platform_cpu_die(unsigned int cpu)
 	 */
 	cpu_leave_lowpower();
 }
-
-int platform_cpu_disable(unsigned int cpu)
-{
-	/*
-	 * we don't allow CPU 0 to be shutdown (it is still too special
-	 * e.g. clock tick interrupts)
-	 */
-	return cpu == 0 ? -EPERM : 0;
-}
diff --git a/arch/arm/mach-msm/idle.c b/arch/arm/mach-msm/idle.c
deleted file mode 100644
index 0c9e13c..0000000
--- a/arch/arm/mach-msm/idle.c
+++ /dev/null
@@ -1,49 +0,0 @@
-/* arch/arm/mach-msm/idle.c
- *
- * Idle processing for MSM7K - work around bugs with SWFI.
- *
- * Copyright (c) 2007 QUALCOMM Incorporated.
- * Copyright (C) 2007 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/init.h>
-#include <asm/system.h>
-
-static void msm_idle(void)
-{
-#ifdef CONFIG_MSM7X00A_IDLE
-	asm volatile (
-
-	"mrc     p15, 0, r1, c1, c0, 0    /* read current CR    */ \n\t"
-	"bic     r0, r1, #(1 << 2)        /* clear dcache bit   */ \n\t"
-	"bic     r0, r0, #(1 << 12)       /* clear icache bit   */ \n\t"
-	"mcr     p15, 0, r0, c1, c0, 0    /* disable d/i cache  */ \n\t"
-
-	"mov     r0, #0                   /* prepare wfi value  */ \n\t"
-	"mcr     p15, 0, r0, c7, c10, 0   /* flush the cache    */ \n\t"
-	"mcr     p15, 0, r0, c7, c10, 4   /* memory barrier     */ \n\t"
-	"mcr     p15, 0, r0, c7, c0, 4    /* wait for interrupt */ \n\t"
-
-	"mcr     p15, 0, r1, c1, c0, 0    /* restore d/i cache  */ \n\t"
-
-	: : : "r0","r1" );
-#endif
-}
-
-static int __init msm_idle_init(void)
-{
-	arm_pm_idle = msm_idle;
-	return 0;
-}
-
-arch_initcall(msm_idle_init);
diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h
index 435f8ed..8cebedb 100644
--- a/arch/arm/mach-msm/include/mach/board.h
+++ b/arch/arm/mach-msm/include/mach/board.h
@@ -18,31 +18,18 @@
 #define __ASM_ARCH_MSM_BOARD_H
 
 #include <linux/types.h>
-#include <mach/mmc.h>
+#include <linux/platform_data/mmc-msm_sdcc.h>
 
 /* platform device data structures */
 
-struct msm_acpu_clock_platform_data
-{
-	uint32_t acpu_switch_time_us;
-	uint32_t max_speed_delta_khz;
-	uint32_t vdd_switch_time_us;
-	unsigned long power_collapse_khz;
-	unsigned long wait_for_irq_khz;
-};
-
 struct clk_lookup;
 
-extern struct sys_timer msm_timer;
-
 /* common init routines for use by arch/arm/mach-msm/board-*.c */
 
 void __init msm_add_devices(void);
-void __init msm_map_common_io(void);
 void __init msm_init_irq(void);
 void __init msm_init_gpio(void);
 void __init msm_clock_init(struct clk_lookup *clock_tbl, unsigned num_clocks);
-void __init msm_acpu_clock_init(struct msm_acpu_clock_platform_data *);
 int __init msm_add_sdcc(unsigned int controller,
 			struct msm_mmc_platform_data *plat,
 			unsigned int stat_irq, unsigned long stat_irq_flags);
diff --git a/arch/arm/mach-msm/include/mach/gpio.h b/arch/arm/mach-msm/include/mach/gpio.h
deleted file mode 100644
index 40a8c17..0000000
--- a/arch/arm/mach-msm/include/mach/gpio.h
+++ /dev/null
@@ -1 +0,0 @@
-/* empty */
diff --git a/arch/arm/mach-msm/include/mach/mmc.h b/arch/arm/mach-msm/include/mach/mmc.h
deleted file mode 100644
index ffcd9e3..0000000
--- a/arch/arm/mach-msm/include/mach/mmc.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- *  arch/arm/include/asm/mach/mmc.h
- */
-#ifndef ASMARM_MACH_MMC_H
-#define ASMARM_MACH_MMC_H
-
-#include <linux/mmc/host.h>
-#include <linux/mmc/card.h>
-#include <linux/mmc/sdio_func.h>
-
-struct msm_mmc_gpio {
-	unsigned no;
-	const char *name;
-};
-
-struct msm_mmc_gpio_data {
-	struct msm_mmc_gpio *gpio;
-	u8 size;
-};
-
-struct msm_mmc_platform_data {
-	unsigned int ocr_mask;			/* available voltages */
-	u32 (*translate_vdd)(struct device *, unsigned int);
-	unsigned int (*status)(struct device *);
-	int (*register_status_notify)(void (*callback)(int card_present, void *dev_id), void *dev_id);
-	struct msm_mmc_gpio_data *gpio_data;
-	void (*init_card)(struct mmc_card *card);
-};
-
-#endif
diff --git a/arch/arm/mach-msm/include/mach/msm_fb.h b/arch/arm/mach-msm/include/mach/msm_fb.h
deleted file mode 100644
index 1f4fc81..0000000
--- a/arch/arm/mach-msm/include/mach/msm_fb.h
+++ /dev/null
@@ -1,147 +0,0 @@
-/* arch/arm/mach-msm/include/mach/msm_fb.h
- *
- * Internal shared definitions for various MSM framebuffer parts.
- *
- * Copyright (C) 2007 Google Incorporated
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#ifndef _MSM_FB_H_
-#define _MSM_FB_H_
-
-#include <linux/device.h>
-
-struct mddi_info;
-
-struct msm_fb_data {
-	int xres;	/* x resolution in pixels */
-	int yres;	/* y resolution in pixels */
-	int width;	/* disply width in mm */
-	int height;	/* display height in mm */
-	unsigned output_format;
-};
-
-struct msmfb_callback {
-	void (*func)(struct msmfb_callback *);
-};
-
-enum {
-	MSM_MDDI_PMDH_INTERFACE,
-	MSM_MDDI_EMDH_INTERFACE,
-	MSM_EBI2_INTERFACE,
-};
-
-#define MSMFB_CAP_PARTIAL_UPDATES	(1 << 0)
-
-struct msm_panel_data {
-	/* turns off the fb memory */
-	int (*suspend)(struct msm_panel_data *);
-	/* turns on the fb memory */
-	int (*resume)(struct msm_panel_data *);
-	/* turns off the panel */
-	int (*blank)(struct msm_panel_data *);
-	/* turns on the panel */
-	int (*unblank)(struct msm_panel_data *);
-	void (*wait_vsync)(struct msm_panel_data *);
-	void (*request_vsync)(struct msm_panel_data *, struct msmfb_callback *);
-	void (*clear_vsync)(struct msm_panel_data *);
-	/* from the enum above */
-	unsigned interface_type;
-	/* data to be passed to the fb driver */
-	struct msm_fb_data *fb_data;
-
-	/* capabilities supported by the panel */
-	uint32_t caps;
-};
-
-struct msm_mddi_client_data {
-	void (*suspend)(struct msm_mddi_client_data *);
-	void (*resume)(struct msm_mddi_client_data *);
-	void (*activate_link)(struct msm_mddi_client_data *);
-	void (*remote_write)(struct msm_mddi_client_data *, uint32_t val,
-			     uint32_t reg);
-	uint32_t (*remote_read)(struct msm_mddi_client_data *, uint32_t reg);
-	void (*auto_hibernate)(struct msm_mddi_client_data *, int);
-	/* custom data that needs to be passed from the board file to a 
-	 * particular client */
-	void *private_client_data;
-	struct resource *fb_resource;
-	/* from the list above */
-	unsigned interface_type;
-};
-
-struct msm_mddi_platform_data {
-	unsigned int clk_rate;
-	void (*power_client)(struct msm_mddi_client_data *, int on);
-
-	/* fixup the mfr name, product id */
-	void (*fixup)(uint16_t *mfr_name, uint16_t *product_id);
-
-	struct resource *fb_resource; /*optional*/
-	/* number of clients in the list that follows */
-	int num_clients;
-	/* array of client information of clients */
-	struct {
-		unsigned product_id; /* mfr id in top 16 bits, product id
-				      * in lower 16 bits
-				      */
-		char *name;	/* the device name will be the platform
-				 * device name registered for the client,
-				 * it should match the name of the associated
-				 * driver
-				 */
-		unsigned id;	/* id for mddi client device node, will also
-				 * be used as device id of panel devices, if
-				 * the client device will have multiple panels
-				 * space must be left here for them
-				 */
-		void *client_data;	/* required private client data */
-		unsigned int clk_rate;	/* optional: if the client requires a
-					* different mddi clk rate
-					*/
-	} client_platform_data[];
-};
-
-struct mdp_blit_req;
-struct fb_info;
-struct mdp_device {
-	struct device dev;
-	void (*dma)(struct mdp_device *mpd, uint32_t addr,
-		    uint32_t stride, uint32_t w, uint32_t h, uint32_t x,
-		    uint32_t y, struct msmfb_callback *callback, int interface);
-	void (*dma_wait)(struct mdp_device *mdp);
-	int (*blit)(struct mdp_device *mdp, struct fb_info *fb,
-		    struct mdp_blit_req *req);
-	void (*set_grp_disp)(struct mdp_device *mdp, uint32_t disp_id);
-};
-
-struct class_interface;
-int register_mdp_client(struct class_interface *class_intf);
-
-/**** private client data structs go below this line ***/
-
-struct msm_mddi_bridge_platform_data {
-	/* from board file */
-	int (*init)(struct msm_mddi_bridge_platform_data *,
-		    struct msm_mddi_client_data *);
-	int (*uninit)(struct msm_mddi_bridge_platform_data *,
-		      struct msm_mddi_client_data *);
-	/* passed to panel for use by the fb driver */
-	int (*blank)(struct msm_mddi_bridge_platform_data *,
-		     struct msm_mddi_client_data *);
-	int (*unblank)(struct msm_mddi_bridge_platform_data *,
-		       struct msm_mddi_client_data *);
-	struct msm_fb_data fb_data;
-};
-
-
-
-#endif
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-7x00.h b/arch/arm/mach-msm/include/mach/msm_iomap-7x00.h
index 6c4046c..67dc0e9 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-7x00.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-7x00.h
@@ -105,11 +105,4 @@
 #define MSM_AD5_PHYS          0xAC000000
 #define MSM_AD5_SIZE          (SZ_1M*13)
 
-#ifndef __ASSEMBLY__
-
-extern void __iomem *__msm_ioremap_caller(unsigned long phys_addr, size_t size,
-					  unsigned int mtype, void *caller);
-
-#endif
-
 #endif
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-7x30.h b/arch/arm/mach-msm/include/mach/msm_iomap-7x30.h
index f944fe6..198202c 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-7x30.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-7x30.h
@@ -100,8 +100,4 @@
 #define MSM_HSUSB_PHYS        0xA3600000
 #define MSM_HSUSB_SIZE        SZ_1K
 
-#ifndef __ASSEMBLY__
-extern void msm_map_msm7x30_io(void);
-#endif
-
 #endif
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8960.h b/arch/arm/mach-msm/include/mach/msm_iomap-8960.h
index a1752c0..9819a55 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-8960.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-8960.h
@@ -46,12 +46,8 @@
 #define MSM8960_TMR0_SIZE	SZ_4K
 
 #ifdef CONFIG_DEBUG_MSM8960_UART
-#define MSM_DEBUG_UART_BASE	0xE1040000
+#define MSM_DEBUG_UART_BASE	0xF0040000
 #define MSM_DEBUG_UART_PHYS	0x16440000
 #endif
 
-#ifndef __ASSEMBLY__
-extern void msm_map_msm8960_io(void);
-#endif
-
 #endif
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8x50.h b/arch/arm/mach-msm/include/mach/msm_iomap-8x50.h
index da77cc1..0faa894 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-8x50.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-8x50.h
@@ -122,8 +122,4 @@
 #define MSM_SDC4_PHYS          0xA0600000
 #define MSM_SDC4_SIZE          SZ_4K
 
-#ifndef __ASSEMBLY__
-extern void msm_map_qsd8x50_io(void);
-#endif
-
 #endif
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8x60.h b/arch/arm/mach-msm/include/mach/msm_iomap-8x60.h
index 5aed57d..199372e 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-8x60.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-8x60.h
@@ -41,21 +41,10 @@
 #define MSM8X60_QGIC_CPU_PHYS	0x02081000
 #define MSM8X60_QGIC_CPU_SIZE	SZ_4K
 
-#define MSM_ACC_BASE		IOMEM(0xF0002000)
-#define MSM_ACC_PHYS		0x02001000
-#define MSM_ACC_SIZE		SZ_4K
-
-#define MSM_GCC_BASE		IOMEM(0xF0003000)
-#define MSM_GCC_PHYS		0x02082000
-#define MSM_GCC_SIZE		SZ_4K
-
 #define MSM_TLMM_BASE		IOMEM(0xF0004000)
 #define MSM_TLMM_PHYS		0x00800000
 #define MSM_TLMM_SIZE		SZ_16K
 
-#define MSM_SHARED_RAM_BASE	IOMEM(0xF0100000)
-#define MSM_SHARED_RAM_SIZE	SZ_1M
-
 #define MSM8X60_TMR_PHYS	0x02000000
 #define MSM8X60_TMR_SIZE	SZ_4K
 
@@ -63,12 +52,8 @@
 #define MSM8X60_TMR0_SIZE	SZ_4K
 
 #ifdef CONFIG_DEBUG_MSM8660_UART
-#define MSM_DEBUG_UART_BASE	0xE1040000
+#define MSM_DEBUG_UART_BASE	0xF0040000
 #define MSM_DEBUG_UART_PHYS	0x19C40000
 #endif
 
-#ifndef __ASSEMBLY__
-extern void msm_map_msm8x60_io(void);
-#endif
-
 #endif
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap.h b/arch/arm/mach-msm/include/mach/msm_iomap.h
index 00afdfb..2ab7cf0 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap.h
@@ -41,12 +41,11 @@
 #include "msm_iomap-7x30.h"
 #elif defined(CONFIG_ARCH_QSD8X50)
 #include "msm_iomap-8x50.h"
-#elif defined(CONFIG_ARCH_MSM8X60)
-#include "msm_iomap-8x60.h"
 #else
 #include "msm_iomap-7x00.h"
 #endif
 
+#include "msm_iomap-8x60.h"
 #include "msm_iomap-8960.h"
 
 #define MSM_DEBUG_UART_SIZE	SZ_4K
diff --git a/arch/arm/mach-msm/include/mach/system.h b/arch/arm/mach-msm/include/mach/system.h
deleted file mode 100644
index f5fb2ec..0000000
--- a/arch/arm/mach-msm/include/mach/system.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/* arch/arm/mach-msm/include/mach/system.h
- *
- * Copyright (C) 2007 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-/* low level hardware reset hook -- for example, hitting the
- * PSHOLD line on the PMIC to hard reset the system
- */
-extern void (*msm_hw_reset_hook)(void);
diff --git a/arch/arm/mach-msm/io.c b/arch/arm/mach-msm/io.c
index a1e7b11..123ef9c 100644
--- a/arch/arm/mach-msm/io.c
+++ b/arch/arm/mach-msm/io.c
@@ -29,30 +29,32 @@
 
 #include <mach/board.h>
 
-#define MSM_CHIP_DEVICE(name, chip) {			      \
+#include "common.h"
+
+#define MSM_CHIP_DEVICE_TYPE(name, chip, mem_type) {			      \
 		.virtual = (unsigned long) MSM_##name##_BASE, \
 		.pfn = __phys_to_pfn(chip##_##name##_PHYS), \
 		.length = chip##_##name##_SIZE, \
-		.type = MT_DEVICE_NONSHARED, \
+		.type = mem_type, \
 	 }
 
+#define MSM_DEVICE_TYPE(name, mem_type) \
+		MSM_CHIP_DEVICE_TYPE(name, MSM, mem_type)
+#define MSM_CHIP_DEVICE(name, chip) \
+		MSM_CHIP_DEVICE_TYPE(name, chip, MT_DEVICE)
 #define MSM_DEVICE(name) MSM_CHIP_DEVICE(name, MSM)
 
-#if defined(CONFIG_ARCH_MSM7X00A) || defined(CONFIG_ARCH_MSM7X27) \
-	|| defined(CONFIG_ARCH_MSM7X25)
+#if defined(CONFIG_ARCH_MSM7X00A)
 static struct map_desc msm_io_desc[] __initdata = {
-	MSM_DEVICE(VIC),
-	MSM_CHIP_DEVICE(CSR, MSM7X00),
-	MSM_DEVICE(DMOV),
-	MSM_CHIP_DEVICE(GPIO1, MSM7X00),
-	MSM_CHIP_DEVICE(GPIO2, MSM7X00),
-	MSM_DEVICE(CLK_CTL),
+	MSM_DEVICE_TYPE(VIC, MT_DEVICE_NONSHARED),
+	MSM_CHIP_DEVICE_TYPE(CSR, MSM7X00, MT_DEVICE_NONSHARED),
+	MSM_DEVICE_TYPE(DMOV, MT_DEVICE_NONSHARED),
+	MSM_CHIP_DEVICE_TYPE(GPIO1, MSM7X00, MT_DEVICE_NONSHARED),
+	MSM_CHIP_DEVICE_TYPE(GPIO2, MSM7X00, MT_DEVICE_NONSHARED),
+	MSM_DEVICE_TYPE(CLK_CTL, MT_DEVICE_NONSHARED),
 #if defined(CONFIG_DEBUG_MSM_UART1) || defined(CONFIG_DEBUG_MSM_UART2) || \
 	defined(CONFIG_DEBUG_MSM_UART3)
-	MSM_DEVICE(DEBUG_UART),
-#endif
-#ifdef CONFIG_ARCH_MSM7X30
-	MSM_DEVICE(GCC),
+	MSM_DEVICE_TYPE(DEBUG_UART, MT_DEVICE_NONSHARED),
 #endif
 	{
 		.virtual =  (unsigned long) MSM_SHARED_RAM_BASE,
@@ -109,8 +111,6 @@ static struct map_desc msm8x60_io_desc[] __initdata = {
 	MSM_CHIP_DEVICE(QGIC_CPU, MSM8X60),
 	MSM_CHIP_DEVICE(TMR, MSM8X60),
 	MSM_CHIP_DEVICE(TMR0, MSM8X60),
-	MSM_DEVICE(ACC),
-	MSM_DEVICE(GCC),
 #ifdef CONFIG_DEBUG_MSM8660_UART
 	MSM_DEVICE(DEBUG_UART),
 #endif
diff --git a/arch/arm/mach-msm/platsmp.c b/arch/arm/mach-msm/platsmp.c
index e012dc8..7ed69b69 100644
--- a/arch/arm/mach-msm/platsmp.c
+++ b/arch/arm/mach-msm/platsmp.c
@@ -22,23 +22,14 @@
 #include <asm/mach-types.h>
 #include <asm/smp_plat.h>
 
-#include <mach/msm_iomap.h>
-
 #include "scm-boot.h"
+#include "common.h"
 
 #define VDD_SC1_ARRAY_CLAMP_GFS_CTL 0x15A0
 #define SCSS_CPU1CORE_RESET 0xD80
 #define SCSS_DBG_STATUS_CORE_PWRDUP 0xE64
 
-/* Mask for edge trigger PPIs except AVS_SVICINT and AVS_SVICINTSWDONE */
-#define GIC_PPI_EDGE_MASK 0xFFFFD7FF
-
 extern void msm_secondary_startup(void);
-/*
- * control for which core is the next to come out of the secondary
- * boot "holding pen".
- */
-volatile int pen_release = -1;
 
 static DEFINE_SPINLOCK(boot_lock);
 
@@ -48,11 +39,8 @@ static inline int get_core_count(void)
 	return ((read_cpuid_id() >> 4) & 3) + 1;
 }
 
-void __cpuinit platform_secondary_init(unsigned int cpu)
+static void __cpuinit msm_secondary_init(unsigned int cpu)
 {
-	/* Configure edge-triggered PPIs */
-	writel(GIC_PPI_EDGE_MASK, MSM_QGIC_DIST_BASE + GIC_DIST_CONFIG + 4);
-
 	/*
 	 * if any interrupts are already enabled for the primary
 	 * core (e.g. timer irq), then they will not have been enabled
@@ -93,7 +81,7 @@ static __cpuinit void prepare_cold_cpu(unsigned int cpu)
 				  "address\n");
 }
 
-int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
+static int __cpuinit msm_boot_secondary(unsigned int cpu, struct task_struct *idle)
 {
 	unsigned long timeout;
 	static int cold_boot_done;
@@ -153,7 +141,7 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
  * does not support the ARM SCU, so just set the possible cpu mask to
  * NR_CPUS.
  */
-void __init smp_init_cpus(void)
+static void __init msm_smp_init_cpus(void)
 {
 	unsigned int i, ncores = get_core_count();
 
@@ -169,6 +157,16 @@ void __init smp_init_cpus(void)
         set_smp_cross_call(gic_raise_softirq);
 }
 
-void __init platform_smp_prepare_cpus(unsigned int max_cpus)
+static void __init msm_smp_prepare_cpus(unsigned int max_cpus)
 {
 }
+
+struct smp_operations msm_smp_ops __initdata = {
+	.smp_init_cpus		= msm_smp_init_cpus,
+	.smp_prepare_cpus	= msm_smp_prepare_cpus,
+	.smp_secondary_init	= msm_secondary_init,
+	.smp_boot_secondary	= msm_boot_secondary,
+#ifdef CONFIG_HOTPLUG_CPU
+	.cpu_die		= msm_cpu_die,
+#endif
+};
diff --git a/arch/arm/mach-msm/proc_comm.c b/arch/arm/mach-msm/proc_comm.c
index 9980dc7..8f1eecd 100644
--- a/arch/arm/mach-msm/proc_comm.c
+++ b/arch/arm/mach-msm/proc_comm.c
@@ -19,7 +19,6 @@
 #include <linux/io.h>
 #include <linux/spinlock.h>
 #include <mach/msm_iomap.h>
-#include <mach/system.h>
 
 #include "proc_comm.h"
 
diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c
index 657be73..c5a2edd 100644
--- a/arch/arm/mach-msm/smd.c
+++ b/arch/arm/mach-msm/smd.c
@@ -30,7 +30,6 @@
 #include <linux/delay.h>
 
 #include <mach/msm_smd.h>
-#include <mach/system.h>
 
 #include "smd_private.h"
 #include "proc_comm.h"
@@ -39,8 +38,6 @@
 #define CONFIG_QDSP6 1
 #endif
 
-void (*msm_hw_reset_hook)(void);
-
 #define MODULE_NAME "msm_smd"
 
 enum {
@@ -52,13 +49,14 @@ static int msm_smd_debug_mask;
 
 struct shared_info {
 	int ready;
-	unsigned state;
+	void __iomem *state;
 };
 
 static unsigned dummy_state[SMSM_STATE_COUNT];
 
 static struct shared_info smd_info = {
-	.state = (unsigned) &dummy_state,
+	/* FIXME: not a real __iomem pointer */
+	.state = &dummy_state,
 };
 
 module_param_named(debug_mask, msm_smd_debug_mask,
@@ -101,10 +99,6 @@ static void handle_modem_crash(void)
 	pr_err("ARM9 has CRASHED\n");
 	smd_diag();
 
-	/* hard reboot if possible */
-	if (msm_hw_reset_hook)
-		msm_hw_reset_hook();
-
 	/* in this case the modem or watchdog should reboot us */
 	for (;;)
 		;
@@ -796,22 +790,22 @@ void *smem_alloc(unsigned id, unsigned size)
 	return smem_find(id, size);
 }
 
-void *smem_item(unsigned id, unsigned *size)
+void __iomem *smem_item(unsigned id, unsigned *size)
 {
 	struct smem_shared *shared = (void *) MSM_SHARED_RAM_BASE;
 	struct smem_heap_entry *toc = shared->heap_toc;
 
 	if (id >= SMEM_NUM_ITEMS)
-		return 0;
+		return NULL;
 
 	if (toc[id].allocated) {
 		*size = toc[id].size;
-		return (void *) (MSM_SHARED_RAM_BASE + toc[id].offset);
+		return (MSM_SHARED_RAM_BASE + toc[id].offset);
 	} else {
 		*size = 0;
 	}
 
-	return 0;
+	return NULL;
 }
 
 void *smem_find(unsigned id, unsigned size_in)
@@ -857,7 +851,7 @@ static irqreturn_t smsm_irq_handler(int irq, void *data)
 int smsm_change_state(enum smsm_state_item item,
 		      uint32_t clear_mask, uint32_t set_mask)
 {
-	unsigned long addr = smd_info.state + item * 4;
+	void __iomem *addr = smd_info.state + item * 4;
 	unsigned long flags;
 	unsigned state;
 
@@ -943,10 +937,10 @@ int smd_core_init(void)
 	/* wait for essential items to be initialized */
 	for (;;) {
 		unsigned size;
-		void *state;
+		void __iomem *state;
 		state = smem_item(SMEM_SMSM_SHARED_STATE, &size);
 		if (size == SMSM_V1_SIZE || size == SMSM_V2_SIZE) {
-			smd_info.state = (unsigned)state;
+			smd_info.state = state;
 			break;
 		}
 	}
diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c
index 81280825..476549a 100644
--- a/arch/arm/mach-msm/timer.c
+++ b/arch/arm/mach-msm/timer.c
@@ -1,7 +1,7 @@
 /*
  *
  * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2012, The Linux Foundation. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -20,15 +20,16 @@
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 
 #include <asm/mach/time.h>
 #include <asm/hardware/gic.h>
 #include <asm/localtimer.h>
 #include <asm/sched_clock.h>
 
-#include <mach/msm_iomap.h>
-#include <mach/cpu.h>
-#include <mach/board.h>
+#include "common.h"
 
 #define TIMER_MATCH_VAL         0x0000
 #define TIMER_COUNT_VAL         0x0004
@@ -36,7 +37,6 @@
 #define TIMER_ENABLE_CLR_ON_MATCH_EN    BIT(1)
 #define TIMER_ENABLE_EN                 BIT(0)
 #define TIMER_CLEAR             0x000C
-#define DGT_CLK_CTL             0x0034
 #define DGT_CLK_CTL_DIV_4	0x3
 
 #define GPT_HZ 32768
@@ -101,7 +101,7 @@ static struct clock_event_device msm_clockevent = {
 
 static union {
 	struct clock_event_device *evt;
-	struct clock_event_device __percpu **percpu_evt;
+	struct clock_event_device * __percpu *percpu_evt;
 } msm_evt;
 
 static void __iomem *source_base;
@@ -151,7 +151,7 @@ static int __cpuinit msm_local_timer_setup(struct clock_event_device *evt)
 
 	*__this_cpu_ptr(msm_evt.percpu_evt) = evt;
 	clockevents_register_device(evt);
-	enable_percpu_irq(evt->irq, 0);
+	enable_percpu_irq(evt->irq, IRQ_TYPE_EDGE_RISING);
 	return 0;
 }
 
@@ -172,44 +172,21 @@ static notrace u32 msm_sched_clock_read(void)
 	return msm_clocksource.read(&msm_clocksource);
 }
 
-static void __init msm_timer_init(void)
+static void __init msm_timer_init(u32 dgt_hz, int sched_bits, int irq,
+				  bool percpu)
 {
 	struct clock_event_device *ce = &msm_clockevent;
 	struct clocksource *cs = &msm_clocksource;
 	int res;
-	u32 dgt_hz;
-
-	if (cpu_is_msm7x01()) {
-		event_base = MSM_CSR_BASE;
-		source_base = MSM_CSR_BASE + 0x10;
-		dgt_hz = 19200000 >> MSM_DGT_SHIFT; /* 600 KHz */
-		cs->read = msm_read_timer_count_shift;
-		cs->mask = CLOCKSOURCE_MASK((32 - MSM_DGT_SHIFT));
-	} else if (cpu_is_msm7x30()) {
-		event_base = MSM_CSR_BASE + 0x04;
-		source_base = MSM_CSR_BASE + 0x24;
-		dgt_hz = 24576000 / 4;
-	} else if (cpu_is_qsd8x50()) {
-		event_base = MSM_CSR_BASE;
-		source_base = MSM_CSR_BASE + 0x10;
-		dgt_hz = 19200000 / 4;
-	} else if (cpu_is_msm8x60() || cpu_is_msm8960()) {
-		event_base = MSM_TMR_BASE + 0x04;
-		/* Use CPU0's timer as the global clock source. */
-		source_base = MSM_TMR0_BASE + 0x24;
-		dgt_hz = 27000000 / 4;
-		writel_relaxed(DGT_CLK_CTL_DIV_4, MSM_TMR_BASE + DGT_CLK_CTL);
-	} else
-		BUG();
 
 	writel_relaxed(0, event_base + TIMER_ENABLE);
 	writel_relaxed(0, event_base + TIMER_CLEAR);
 	writel_relaxed(~0, event_base + TIMER_MATCH_VAL);
 	ce->cpumask = cpumask_of(0);
+	ce->irq = irq;
 
-	ce->irq = INT_GP_TIMER_EXP;
 	clockevents_config_and_register(ce, GPT_HZ, 4, 0xffffffff);
-	if (cpu_is_msm8x60() || cpu_is_msm8960()) {
+	if (percpu) {
 		msm_evt.percpu_evt = alloc_percpu(struct clock_event_device *);
 		if (!msm_evt.percpu_evt) {
 			pr_err("memory allocation failed for %s\n", ce->name);
@@ -219,7 +196,7 @@ static void __init msm_timer_init(void)
 		res = request_percpu_irq(ce->irq, msm_timer_interrupt,
 					 ce->name, msm_evt.percpu_evt);
 		if (!res) {
-			enable_percpu_irq(ce->irq, 0);
+			enable_percpu_irq(ce->irq, IRQ_TYPE_EDGE_RISING);
 #ifdef CONFIG_LOCAL_TIMERS
 			local_timer_register(&msm_local_timer_ops);
 #endif
@@ -238,10 +215,143 @@ err:
 	res = clocksource_register_hz(cs, dgt_hz);
 	if (res)
 		pr_err("clocksource_register failed\n");
-	setup_sched_clock(msm_sched_clock_read,
-			cpu_is_msm7x01() ? 32 - MSM_DGT_SHIFT : 32, dgt_hz);
+	setup_sched_clock(msm_sched_clock_read, sched_bits, dgt_hz);
 }
 
-struct sys_timer msm_timer = {
-	.init = msm_timer_init
+#ifdef CONFIG_OF
+static const struct of_device_id msm_dgt_match[] __initconst = {
+	{ .compatible = "qcom,msm-dgt" },
+	{ },
+};
+
+static const struct of_device_id msm_gpt_match[] __initconst = {
+	{ .compatible = "qcom,msm-gpt" },
+	{ },
+};
+
+static void __init msm_dt_timer_init(void)
+{
+	struct device_node *np;
+	u32 freq;
+	int irq;
+	struct resource res;
+	u32 percpu_offset;
+	void __iomem *dgt_clk_ctl;
+
+	np = of_find_matching_node(NULL, msm_gpt_match);
+	if (!np) {
+		pr_err("Can't find GPT DT node\n");
+		return;
+	}
+
+	event_base = of_iomap(np, 0);
+	if (!event_base) {
+		pr_err("Failed to map event base\n");
+		return;
+	}
+
+	irq = irq_of_parse_and_map(np, 0);
+	if (irq <= 0) {
+		pr_err("Can't get irq\n");
+		return;
+	}
+	of_node_put(np);
+
+	np = of_find_matching_node(NULL, msm_dgt_match);
+	if (!np) {
+		pr_err("Can't find DGT DT node\n");
+		return;
+	}
+
+	if (of_property_read_u32(np, "cpu-offset", &percpu_offset))
+		percpu_offset = 0;
+
+	if (of_address_to_resource(np, 0, &res)) {
+		pr_err("Failed to parse DGT resource\n");
+		return;
+	}
+
+	source_base = ioremap(res.start + percpu_offset, resource_size(&res));
+	if (!source_base) {
+		pr_err("Failed to map source base\n");
+		return;
+	}
+
+	if (!of_address_to_resource(np, 1, &res)) {
+		dgt_clk_ctl = ioremap(res.start + percpu_offset,
+				      resource_size(&res));
+		if (!dgt_clk_ctl) {
+			pr_err("Failed to map DGT control base\n");
+			return;
+		}
+		writel_relaxed(DGT_CLK_CTL_DIV_4, dgt_clk_ctl);
+		iounmap(dgt_clk_ctl);
+	}
+
+	if (of_property_read_u32(np, "clock-frequency", &freq)) {
+		pr_err("Unknown frequency\n");
+		return;
+	}
+	of_node_put(np);
+
+	msm_timer_init(freq, 32, irq, !!percpu_offset);
+}
+
+struct sys_timer msm_dt_timer = {
+	.init = msm_dt_timer_init
+};
+#endif
+
+static int __init msm_timer_map(phys_addr_t event, phys_addr_t source)
+{
+	event_base = ioremap(event, SZ_64);
+	if (!event_base) {
+		pr_err("Failed to map event base\n");
+		return 1;
+	}
+	source_base = ioremap(source, SZ_64);
+	if (!source_base) {
+		pr_err("Failed to map source base\n");
+		return 1;
+	}
+	return 0;
+}
+
+static void __init msm7x01_timer_init(void)
+{
+	struct clocksource *cs = &msm_clocksource;
+
+	if (msm_timer_map(0xc0100000, 0xc0100010))
+		return;
+	cs->read = msm_read_timer_count_shift;
+	cs->mask = CLOCKSOURCE_MASK((32 - MSM_DGT_SHIFT));
+	/* 600 KHz */
+	msm_timer_init(19200000 >> MSM_DGT_SHIFT, 32 - MSM_DGT_SHIFT, 7,
+			false);
+}
+
+struct sys_timer msm7x01_timer = {
+	.init = msm7x01_timer_init
+};
+
+static void __init msm7x30_timer_init(void)
+{
+	if (msm_timer_map(0xc0100004, 0xc0100024))
+		return;
+	msm_timer_init(24576000 / 4, 32, 1, false);
+}
+
+struct sys_timer msm7x30_timer = {
+	.init = msm7x30_timer_init
+};
+
+static void __init qsd8x50_timer_init(void)
+{
+	if (msm_timer_map(0xAC100000, 0xAC100010))
+		return;
+	msm_timer_init(19200000 / 4, 32, 7, false);
+}
+
+struct sys_timer qsd8x50_timer = {
+	.init = qsd8x50_timer_init
 };
diff --git a/arch/arm/mach-mv78xx0/addr-map.c b/arch/arm/mach-mv78xx0/addr-map.c
index a9bc841..343c435 100644
--- a/arch/arm/mach-mv78xx0/addr-map.c
+++ b/arch/arm/mach-mv78xx0/addr-map.c
@@ -13,6 +13,7 @@
 #include <linux/mbus.h>
 #include <linux/io.h>
 #include <plat/addr-map.h>
+#include <mach/mv78xx0.h>
 #include "common.h"
 
 /*
@@ -47,7 +48,7 @@ static void __init __iomem *win_cfg_base(const struct orion_addr_map_cfg *cfg, i
 	 * so we don't need to take that into account here.
 	 */
 
-	return (void __iomem *)((win < 8) ? WIN0_OFF(win) : WIN8_OFF(win));
+	return (win < 8) ? WIN0_OFF(win) : WIN8_OFF(win);
 }
 
 /*
@@ -71,17 +72,17 @@ void __init mv78xx0_setup_cpu_mbus(void)
 	 */
 	if (mv78xx0_core_index() == 0)
 		orion_setup_cpu_mbus_target(&addr_map_cfg,
-					    DDR_WINDOW_CPU0_BASE);
+					    (void __iomem *) DDR_WINDOW_CPU0_BASE);
 	else
 		orion_setup_cpu_mbus_target(&addr_map_cfg,
-					    DDR_WINDOW_CPU1_BASE);
+					    (void __iomem *) DDR_WINDOW_CPU1_BASE);
 }
 
 void __init mv78xx0_setup_pcie_io_win(int window, u32 base, u32 size,
 				      int maj, int min)
 {
 	orion_setup_cpu_win(&addr_map_cfg, window, base, size,
-			    TARGET_PCIE(maj), ATTR_PCIE_IO(min), -1);
+			    TARGET_PCIE(maj), ATTR_PCIE_IO(min), 0);
 }
 
 void __init mv78xx0_setup_pcie_mem_win(int window, u32 base, u32 size,
diff --git a/arch/arm/mach-mv78xx0/common.c b/arch/arm/mach-mv78xx0/common.c
index 3057f7d..131cd48 100644
--- a/arch/arm/mach-mv78xx0/common.c
+++ b/arch/arm/mach-mv78xx0/common.c
@@ -20,8 +20,8 @@
 #include <mach/mv78xx0.h>
 #include <mach/bridge-regs.h>
 #include <plat/cache-feroceon-l2.h>
-#include <plat/ehci-orion.h>
-#include <plat/orion_nand.h>
+#include <linux/platform_data/usb-ehci-orion.h>
+#include <linux/platform_data/mtd-orion_nand.h>
 #include <plat/time.h>
 #include <plat/common.h>
 #include <plat/addr-map.h>
@@ -130,17 +130,12 @@ static int get_tclk(void)
  ****************************************************************************/
 static struct map_desc mv78xx0_io_desc[] __initdata = {
 	{
-		.virtual	= MV78XX0_CORE_REGS_VIRT_BASE,
+		.virtual	= (unsigned long) MV78XX0_CORE_REGS_VIRT_BASE,
 		.pfn		= 0,
 		.length		= MV78XX0_CORE_REGS_SIZE,
 		.type		= MT_DEVICE,
 	}, {
-		.virtual	= MV78XX0_PCIE_IO_VIRT_BASE(0),
-		.pfn		= __phys_to_pfn(MV78XX0_PCIE_IO_PHYS_BASE(0)),
-		.length		= MV78XX0_PCIE_IO_SIZE * 8,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= MV78XX0_REGS_VIRT_BASE,
+		.virtual	= (unsigned long) MV78XX0_REGS_VIRT_BASE,
 		.pfn		= __phys_to_pfn(MV78XX0_REGS_PHYS_BASE),
 		.length		= MV78XX0_REGS_SIZE,
 		.type		= MT_DEVICE,
diff --git a/arch/arm/mach-mv78xx0/include/mach/bridge-regs.h b/arch/arm/mach-mv78xx0/include/mach/bridge-regs.h
index eb187e0..5f03484 100644
--- a/arch/arm/mach-mv78xx0/include/mach/bridge-regs.h
+++ b/arch/arm/mach-mv78xx0/include/mach/bridge-regs.h
@@ -11,18 +11,18 @@
 
 #include <mach/mv78xx0.h>
 
-#define CPU_CONTROL		(BRIDGE_VIRT_BASE | 0x0104)
+#define CPU_CONTROL		(BRIDGE_VIRT_BASE + 0x0104)
 #define L2_WRITETHROUGH		0x00020000
 
-#define RSTOUTn_MASK		(BRIDGE_VIRT_BASE | 0x0108)
+#define RSTOUTn_MASK		(BRIDGE_VIRT_BASE + 0x0108)
 #define SOFT_RESET_OUT_EN	0x00000004
 
-#define SYSTEM_SOFT_RESET	(BRIDGE_VIRT_BASE | 0x010c)
+#define SYSTEM_SOFT_RESET	(BRIDGE_VIRT_BASE + 0x010c)
 #define SOFT_RESET		0x00000001
 
 #define BRIDGE_INT_TIMER1_CLR	(~0x0004)
 
-#define IRQ_VIRT_BASE		(BRIDGE_VIRT_BASE | 0x0200)
+#define IRQ_VIRT_BASE		(BRIDGE_VIRT_BASE + 0x0200)
 #define IRQ_CAUSE_ERR_OFF	0x0000
 #define IRQ_CAUSE_LOW_OFF	0x0004
 #define IRQ_CAUSE_HIGH_OFF	0x0008
@@ -30,7 +30,7 @@
 #define IRQ_MASK_LOW_OFF	0x0010
 #define IRQ_MASK_HIGH_OFF	0x0014
 
-#define TIMER_VIRT_BASE		(BRIDGE_VIRT_BASE | 0x0300)
-#define TIMER_PHYS_BASE		(BRIDGE_PHYS_BASE | 0x0300)
+#define TIMER_VIRT_BASE		(BRIDGE_VIRT_BASE + 0x0300)
+#define TIMER_PHYS_BASE		(BRIDGE_PHYS_BASE + 0x0300)
 
 #endif
diff --git a/arch/arm/mach-mv78xx0/include/mach/io.h b/arch/arm/mach-mv78xx0/include/mach/io.h
deleted file mode 100644
index c7d9d00..0000000
--- a/arch/arm/mach-mv78xx0/include/mach/io.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * arch/arm/mach-mv78xx0/include/mach/io.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 __ASM_ARCH_IO_H
-#define __ASM_ARCH_IO_H
-
-#include "mv78xx0.h"
-
-#define IO_SPACE_LIMIT		0xffffffff
-
-static inline void __iomem *__io(unsigned long addr)
-{
-	return (void __iomem *)((addr - MV78XX0_PCIE_IO_PHYS_BASE(0))
-					+ MV78XX0_PCIE_IO_VIRT_BASE(0));
-}
-
-#define __io(a)			__io(a)
-
-#endif
diff --git a/arch/arm/mach-mv78xx0/include/mach/mv78xx0.h b/arch/arm/mach-mv78xx0/include/mach/mv78xx0.h
index e807c4c..46200a1 100644
--- a/arch/arm/mach-mv78xx0/include/mach/mv78xx0.h
+++ b/arch/arm/mach-mv78xx0/include/mach/mv78xx0.h
@@ -29,28 +29,27 @@
  *
  * virt		phys		size
  * fe400000	f102x000	16K	core-specific peripheral registers
- * fe700000	f0800000	1M	PCIe #0 I/O space
- * fe800000	f0900000	1M	PCIe #1 I/O space
- * fe900000	f0a00000	1M	PCIe #2 I/O space
- * fea00000	f0b00000	1M	PCIe #3 I/O space
- * feb00000	f0c00000	1M	PCIe #4 I/O space
- * fec00000	f0d00000	1M	PCIe #5 I/O space
- * fed00000	f0e00000	1M	PCIe #6 I/O space
- * fee00000	f0f00000	1M	PCIe #7 I/O space
- * fef00000	f1000000	1M	on-chip peripheral registers
+ * fee00000	f0800000	64K	PCIe #0 I/O space
+ * fee10000	f0900000	64K	PCIe #1 I/O space
+ * fee20000	f0a00000	64K	PCIe #2 I/O space
+ * fee30000	f0b00000	64K	PCIe #3 I/O space
+ * fee40000	f0c00000	64K	PCIe #4 I/O space
+ * fee50000	f0d00000	64K	PCIe #5 I/O space
+ * fee60000	f0e00000	64K	PCIe #6 I/O space
+ * fee70000	f0f00000	64K	PCIe #7 I/O space
+ * fd000000	f1000000	1M	on-chip peripheral registers
  */
 #define MV78XX0_CORE0_REGS_PHYS_BASE	0xf1020000
 #define MV78XX0_CORE1_REGS_PHYS_BASE	0xf1024000
-#define MV78XX0_CORE_REGS_VIRT_BASE	0xfe400000
+#define MV78XX0_CORE_REGS_VIRT_BASE	IOMEM(0xfe400000)
 #define MV78XX0_CORE_REGS_PHYS_BASE	0xfe400000
 #define MV78XX0_CORE_REGS_SIZE		SZ_16K
 
 #define MV78XX0_PCIE_IO_PHYS_BASE(i)	(0xf0800000 + ((i) << 20))
-#define MV78XX0_PCIE_IO_VIRT_BASE(i)	(0xfe700000 + ((i) << 20))
 #define MV78XX0_PCIE_IO_SIZE		SZ_1M
 
 #define MV78XX0_REGS_PHYS_BASE		0xf1000000
-#define MV78XX0_REGS_VIRT_BASE		0xfef00000
+#define MV78XX0_REGS_VIRT_BASE		IOMEM(0xfd000000)
 #define MV78XX0_REGS_SIZE		SZ_1M
 
 #define MV78XX0_PCIE_MEM_PHYS_BASE	0xc0000000
@@ -65,47 +64,47 @@
 /*
  * Register Map
  */
-#define DDR_VIRT_BASE		(MV78XX0_REGS_VIRT_BASE | 0x00000)
-#define  DDR_WINDOW_CPU0_BASE	(DDR_VIRT_BASE | 0x1500)
-#define  DDR_WINDOW_CPU1_BASE	(DDR_VIRT_BASE | 0x1570)
-
-#define DEV_BUS_PHYS_BASE	(MV78XX0_REGS_PHYS_BASE | 0x10000)
-#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  GPIO_VIRT_BASE		(DEV_BUS_VIRT_BASE | 0x0100)
-#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)
-#define  UART1_VIRT_BASE	(DEV_BUS_VIRT_BASE | 0x2100)
-#define  UART2_PHYS_BASE	(DEV_BUS_PHYS_BASE | 0x2200)
-#define  UART2_VIRT_BASE	(DEV_BUS_VIRT_BASE | 0x2200)
-#define  UART3_PHYS_BASE	(DEV_BUS_PHYS_BASE | 0x2300)
-#define  UART3_VIRT_BASE	(DEV_BUS_VIRT_BASE | 0x2300)
-
-#define GE10_PHYS_BASE		(MV78XX0_REGS_PHYS_BASE | 0x30000)
-#define GE11_PHYS_BASE		(MV78XX0_REGS_PHYS_BASE | 0x34000)
-
-#define PCIE00_VIRT_BASE	(MV78XX0_REGS_VIRT_BASE | 0x40000)
-#define PCIE01_VIRT_BASE	(MV78XX0_REGS_VIRT_BASE | 0x44000)
-#define PCIE02_VIRT_BASE	(MV78XX0_REGS_VIRT_BASE | 0x48000)
-#define PCIE03_VIRT_BASE	(MV78XX0_REGS_VIRT_BASE | 0x4c000)
-
-#define USB0_PHYS_BASE		(MV78XX0_REGS_PHYS_BASE | 0x50000)
-#define USB1_PHYS_BASE		(MV78XX0_REGS_PHYS_BASE | 0x51000)
-#define USB2_PHYS_BASE		(MV78XX0_REGS_PHYS_BASE | 0x52000)
-
-#define GE00_PHYS_BASE		(MV78XX0_REGS_PHYS_BASE | 0x70000)
-#define GE01_PHYS_BASE		(MV78XX0_REGS_PHYS_BASE | 0x74000)
-
-#define PCIE10_VIRT_BASE	(MV78XX0_REGS_VIRT_BASE | 0x80000)
-#define PCIE11_VIRT_BASE	(MV78XX0_REGS_VIRT_BASE | 0x84000)
-#define PCIE12_VIRT_BASE	(MV78XX0_REGS_VIRT_BASE | 0x88000)
-#define PCIE13_VIRT_BASE	(MV78XX0_REGS_VIRT_BASE | 0x8c000)
-
-#define SATA_PHYS_BASE		(MV78XX0_REGS_PHYS_BASE | 0xa0000)
+#define DDR_VIRT_BASE		(MV78XX0_REGS_VIRT_BASE + 0x00000)
+#define  DDR_WINDOW_CPU0_BASE	(DDR_VIRT_BASE + 0x1500)
+#define  DDR_WINDOW_CPU1_BASE	(DDR_VIRT_BASE + 0x1570)
+
+#define DEV_BUS_PHYS_BASE	(MV78XX0_REGS_PHYS_BASE + 0x10000)
+#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  GPIO_VIRT_BASE		(DEV_BUS_VIRT_BASE + 0x0100)
+#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)
+#define  UART1_VIRT_BASE	(DEV_BUS_VIRT_BASE + 0x2100)
+#define  UART2_PHYS_BASE	(DEV_BUS_PHYS_BASE + 0x2200)
+#define  UART2_VIRT_BASE	(DEV_BUS_VIRT_BASE + 0x2200)
+#define  UART3_PHYS_BASE	(DEV_BUS_PHYS_BASE + 0x2300)
+#define  UART3_VIRT_BASE	(DEV_BUS_VIRT_BASE + 0x2300)
+
+#define GE10_PHYS_BASE		(MV78XX0_REGS_PHYS_BASE + 0x30000)
+#define GE11_PHYS_BASE		(MV78XX0_REGS_PHYS_BASE + 0x34000)
+
+#define PCIE00_VIRT_BASE	(MV78XX0_REGS_VIRT_BASE + 0x40000)
+#define PCIE01_VIRT_BASE	(MV78XX0_REGS_VIRT_BASE + 0x44000)
+#define PCIE02_VIRT_BASE	(MV78XX0_REGS_VIRT_BASE + 0x48000)
+#define PCIE03_VIRT_BASE	(MV78XX0_REGS_VIRT_BASE + 0x4c000)
+
+#define USB0_PHYS_BASE		(MV78XX0_REGS_PHYS_BASE + 0x50000)
+#define USB1_PHYS_BASE		(MV78XX0_REGS_PHYS_BASE + 0x51000)
+#define USB2_PHYS_BASE		(MV78XX0_REGS_PHYS_BASE + 0x52000)
+
+#define GE00_PHYS_BASE		(MV78XX0_REGS_PHYS_BASE + 0x70000)
+#define GE01_PHYS_BASE		(MV78XX0_REGS_PHYS_BASE + 0x74000)
+
+#define PCIE10_VIRT_BASE	(MV78XX0_REGS_VIRT_BASE + 0x80000)
+#define PCIE11_VIRT_BASE	(MV78XX0_REGS_VIRT_BASE + 0x84000)
+#define PCIE12_VIRT_BASE	(MV78XX0_REGS_VIRT_BASE + 0x88000)
+#define PCIE13_VIRT_BASE	(MV78XX0_REGS_VIRT_BASE + 0x8c000)
+
+#define SATA_PHYS_BASE		(MV78XX0_REGS_PHYS_BASE + 0xa0000)
 
 /*
  * Supported devices and revisions.
diff --git a/arch/arm/mach-mv78xx0/irq.c b/arch/arm/mach-mv78xx0/irq.c
index eff9a75..3207344 100644
--- a/arch/arm/mach-mv78xx0/irq.c
+++ b/arch/arm/mach-mv78xx0/irq.c
@@ -10,7 +10,9 @@
 #include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/irq.h>
+#include <linux/io.h>
 #include <mach/bridge-regs.h>
+#include <plat/orion-gpio.h>
 #include <plat/irq.h>
 #include "common.h"
 
@@ -23,16 +25,16 @@ static int __initdata gpio0_irqs[4] = {
 
 void __init mv78xx0_init_irq(void)
 {
-	orion_irq_init(0, (void __iomem *)(IRQ_VIRT_BASE + IRQ_MASK_LOW_OFF));
-	orion_irq_init(32, (void __iomem *)(IRQ_VIRT_BASE + IRQ_MASK_HIGH_OFF));
-	orion_irq_init(64, (void __iomem *)(IRQ_VIRT_BASE + IRQ_MASK_ERR_OFF));
+	orion_irq_init(0, IRQ_VIRT_BASE + IRQ_MASK_LOW_OFF);
+	orion_irq_init(32, IRQ_VIRT_BASE + IRQ_MASK_HIGH_OFF);
+	orion_irq_init(64, IRQ_VIRT_BASE + IRQ_MASK_ERR_OFF);
 
 	/*
 	 * Initialize gpiolib for GPIOs 0-31.  (The GPIO interrupt mask
 	 * registers for core #1 are at an offset of 0x18 from those of
 	 * core #0.)
 	 */
-	orion_gpio_init(NULL, 0, 32, (void __iomem *)GPIO_VIRT_BASE,
+	orion_gpio_init(NULL, 0, 32, GPIO_VIRT_BASE,
 			mv78xx0_core_index() ? 0x18 : 0,
 			IRQ_MV78XX0_GPIO_START, gpio0_irqs);
 }
diff --git a/arch/arm/mach-mv78xx0/pcie.c b/arch/arm/mach-mv78xx0/pcie.c
index 2e56e86..a9a154a 100644
--- a/arch/arm/mach-mv78xx0/pcie.c
+++ b/arch/arm/mach-mv78xx0/pcie.c
@@ -15,6 +15,7 @@
 #include <asm/mach/pci.h>
 #include <plat/pcie.h>
 #include <plat/addr-map.h>
+#include <mach/mv78xx0.h>
 #include "common.h"
 
 struct pcie_port {
@@ -23,119 +24,73 @@ struct pcie_port {
 	u8			root_bus_nr;
 	void __iomem		*base;
 	spinlock_t		conf_lock;
-	char			io_space_name[16];
 	char			mem_space_name[16];
-	struct resource		res[2];
+	struct resource		res;
 };
 
 static struct pcie_port pcie_port[8];
 static int num_pcie_ports;
 static struct resource pcie_io_space;
-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);
+	*dev = orion_pcie_dev_id(PCIE00_VIRT_BASE);
+	*rev = orion_pcie_rev(PCIE00_VIRT_BASE);
 }
 
+u32 pcie_port_size[8] = {
+	0,
+	0x30000000,
+	0x10000000,
+	0x10000000,
+	0x08000000,
+	0x08000000,
+	0x08000000,
+	0x04000000,
+};
+
 static void __init mv78xx0_pcie_preinit(void)
 {
 	int i;
 	u32 size_each;
 	u32 start;
-	int win;
+	int win = 0;
 
 	pcie_io_space.name = "PCIe I/O Space";
 	pcie_io_space.start = MV78XX0_PCIE_IO_PHYS_BASE(0);
 	pcie_io_space.end =
 		MV78XX0_PCIE_IO_PHYS_BASE(0) + MV78XX0_PCIE_IO_SIZE * 8 - 1;
-	pcie_io_space.flags = IORESOURCE_IO;
+	pcie_io_space.flags = IORESOURCE_MEM;
 	if (request_resource(&iomem_resource, &pcie_io_space))
 		panic("can't allocate PCIe I/O space");
 
-	pcie_mem_space.name = "PCIe MEM Space";
-	pcie_mem_space.start = MV78XX0_PCIE_MEM_PHYS_BASE;
-	pcie_mem_space.end =
-		MV78XX0_PCIE_MEM_PHYS_BASE + MV78XX0_PCIE_MEM_SIZE - 1;
-	pcie_mem_space.flags = IORESOURCE_MEM;
-	if (request_resource(&iomem_resource, &pcie_mem_space))
-		panic("can't allocate PCIe MEM space");
+	if (num_pcie_ports > 7)
+		panic("invalid number of PCIe ports");
+
+	size_each = pcie_port_size[num_pcie_ports];
 
+	start = MV78XX0_PCIE_MEM_PHYS_BASE;
 	for (i = 0; i < num_pcie_ports; i++) {
 		struct pcie_port *pp = pcie_port + i;
 
-		snprintf(pp->io_space_name, sizeof(pp->io_space_name),
-			"PCIe %d.%d I/O", pp->maj, pp->min);
-		pp->io_space_name[sizeof(pp->io_space_name) - 1] = 0;
-		pp->res[0].name = pp->io_space_name;
-		pp->res[0].start = MV78XX0_PCIE_IO_PHYS_BASE(i);
-		pp->res[0].end = pp->res[0].start + MV78XX0_PCIE_IO_SIZE - 1;
-		pp->res[0].flags = IORESOURCE_IO;
-
 		snprintf(pp->mem_space_name, sizeof(pp->mem_space_name),
 			"PCIe %d.%d MEM", pp->maj, pp->min);
 		pp->mem_space_name[sizeof(pp->mem_space_name) - 1] = 0;
-		pp->res[1].name = pp->mem_space_name;
-		pp->res[1].flags = IORESOURCE_MEM;
-	}
-
-	switch (num_pcie_ports) {
-	case 0:
-		size_each = 0;
-		break;
-
-	case 1:
-		size_each = 0x30000000;
-		break;
-
-	case 2 ... 3:
-		size_each = 0x10000000;
-		break;
-
-	case 4 ... 6:
-		size_each = 0x08000000;
-		break;
-
-	case 7:
-		size_each = 0x04000000;
-		break;
-
-	default:
-		panic("invalid number of PCIe ports");
-	}
-
-	start = MV78XX0_PCIE_MEM_PHYS_BASE;
-	for (i = 0; i < num_pcie_ports; i++) {
-		struct pcie_port *pp = pcie_port + i;
-
-		pp->res[1].start = start;
-		pp->res[1].end = start + size_each - 1;
+		pp->res.name = pp->mem_space_name;
+		pp->res.flags = IORESOURCE_MEM;
+		pp->res.start = start;
+		pp->res.end = start + size_each - 1;
 		start += size_each;
-	}
-
-	for (i = 0; i < num_pcie_ports; i++) {
-		struct pcie_port *pp = pcie_port + i;
 
-		if (request_resource(&pcie_io_space, &pp->res[0]))
-			panic("can't allocate PCIe I/O sub-space");
-
-		if (request_resource(&pcie_mem_space, &pp->res[1]))
+		if (request_resource(&iomem_resource, &pp->res))
 			panic("can't allocate PCIe MEM sub-space");
-	}
 
-	win = 0;
-	for (i = 0; i < num_pcie_ports; i++) {
-		struct pcie_port *pp = pcie_port + i;
+		mv78xx0_setup_pcie_mem_win(win + i + 8, pp->res.start,
+					   resource_size(&pp->res),
+					   pp->maj, pp->min);
 
-		mv78xx0_setup_pcie_io_win(win++, pp->res[0].start,
-					  resource_size(&pp->res[0]),
+		mv78xx0_setup_pcie_io_win(win + i, i * SZ_64K, SZ_64K,
 					  pp->maj, pp->min);
-
-		mv78xx0_setup_pcie_mem_win(win++, pp->res[1].start,
-					   resource_size(&pp->res[1]),
-					   pp->maj, pp->min);
 	}
 }
 
@@ -156,8 +111,9 @@ static int __init mv78xx0_pcie_setup(int nr, struct pci_sys_data *sys)
 	orion_pcie_set_local_bus_nr(pp->base, sys->busnr);
 	orion_pcie_setup(pp->base);
 
-	pci_add_resource_offset(&sys->resources, &pp->res[0], sys->io_offset);
-	pci_add_resource_offset(&sys->resources, &pp->res[1], sys->mem_offset);
+	pci_ioremap_io(nr * SZ_64K, MV78XX0_PCIE_IO_PHYS_BASE(nr));
+
+	pci_add_resource_offset(&sys->resources, &pp->res, sys->mem_offset);
 
 	return 1;
 }
@@ -267,11 +223,11 @@ static struct hw_pci mv78xx0_pci __initdata = {
 	.map_irq	= mv78xx0_pcie_map_irq,
 };
 
-static void __init add_pcie_port(int maj, int min, unsigned long base)
+static void __init add_pcie_port(int maj, int min, void __iomem *base)
 {
 	printk(KERN_INFO "MV78xx0 PCIe port %d.%d: ", maj, min);
 
-	if (orion_pcie_link_up((void __iomem *)base)) {
+	if (orion_pcie_link_up(base)) {
 		struct pcie_port *pp = &pcie_port[num_pcie_ports++];
 
 		printk("link up\n");
@@ -279,9 +235,9 @@ static void __init add_pcie_port(int maj, int min, unsigned long base)
 		pp->maj = maj;
 		pp->min = min;
 		pp->root_bus_nr = -1;
-		pp->base = (void __iomem *)base;
+		pp->base = base;
 		spin_lock_init(&pp->conf_lock);
-		memset(pp->res, 0, sizeof(pp->res));
+		memset(&pp->res, 0, sizeof(pp->res));
 	} else {
 		printk("link down, ignoring\n");
 	}
@@ -293,7 +249,7 @@ void __init mv78xx0_pcie_init(int init_port0, int init_port1)
 
 	if (init_port0) {
 		add_pcie_port(0, 0, PCIE00_VIRT_BASE);
-		if (!orion_pcie_x4_mode((void __iomem *)PCIE00_VIRT_BASE)) {
+		if (!orion_pcie_x4_mode(PCIE00_VIRT_BASE)) {
 			add_pcie_port(0, 1, PCIE01_VIRT_BASE);
 			add_pcie_port(0, 2, PCIE02_VIRT_BASE);
 			add_pcie_port(0, 3, PCIE03_VIRT_BASE);
diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig
index caa2c5e..26a817d 100644
--- a/arch/arm/mach-mvebu/Kconfig
+++ b/arch/arm/mach-mvebu/Kconfig
@@ -1,15 +1,37 @@
+config ARCH_MVEBU
+	bool "Marvell SOCs with Device Tree support" if ARCH_MULTI_V7
+	select CLKSRC_MMIO
+	select COMMON_CLK
+	select GENERIC_CLOCKEVENTS
+	select GENERIC_IRQ_CHIP
+	select IRQ_DOMAIN
+	select MULTI_IRQ_HANDLER
+	select SPARSE_IRQ
+
 if ARCH_MVEBU
 
 menu "Marvell SOC with device tree"
 
 config MACH_ARMADA_370_XP
-	bool "Marvell Armada 370 and Aramada XP boards"
+	bool
 	select ARMADA_370_XP_TIMER
 	select CPU_V7
+
+config MACH_ARMADA_370
+	bool "Marvell Armada 370 boards"
+	select MACH_ARMADA_370_XP
+	select PINCTRL_ARMADA_370
 	help
+	  Say 'Y' here if you want your kernel to support boards based
+	  on the Marvell Armada 370 SoC with device tree.
 
-	  Say 'Y' here if you want your kernel to support boards based on
-	  Marvell Armada 370 or Armada XP with device tree.
+config MACH_ARMADA_XP
+	bool "Marvell Armada XP boards"
+	select MACH_ARMADA_370_XP
+	select PINCTRL_ARMADA_XP
+	help
+	  Say 'Y' here if you want your kernel to support boards based
+	  on the Marvell Armada XP SoC with device tree.
 
 endmenu
 
diff --git a/arch/arm/mach-mvebu/Makefile b/arch/arm/mach-mvebu/Makefile
index e61d2b8..cbe5664 100644
--- a/arch/arm/mach-mvebu/Makefile
+++ b/arch/arm/mach-mvebu/Makefile
@@ -1,2 +1,4 @@
+ccflags-$(ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include
+
 obj-y += system-controller.o
-obj-$(CONFIG_MACH_ARMADA_370_XP) += armada-370-xp.o irq-armada-370-xp.o
+obj-$(CONFIG_MACH_ARMADA_370_XP) += armada-370-xp.o irq-armada-370-xp.o addr-map.o
diff --git a/arch/arm/mach-mvebu/Makefile.boot b/arch/arm/mach-mvebu/Makefile.boot
deleted file mode 100644
index 2579a2f..0000000
--- a/arch/arm/mach-mvebu/Makefile.boot
+++ /dev/null
@@ -1,3 +0,0 @@
-zreladdr-y := 0x00008000
-dtb-$(CONFIG_MACH_ARMADA_370_XP) += armada-370-db.dtb
-dtb-$(CONFIG_MACH_ARMADA_370_XP) += armada-xp-db.dtb
diff --git a/arch/arm/mach-mvebu/addr-map.c b/arch/arm/mach-mvebu/addr-map.c
new file mode 100644
index 0000000..fe454a4
--- /dev/null
+++ b/arch/arm/mach-mvebu/addr-map.c
@@ -0,0 +1,134 @@
+/*
+ * Address map functions for Marvell 370 / XP SoCs
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/mbus.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <plat/addr-map.h>
+
+/*
+ * Generic Address Decode Windows bit settings
+ */
+#define ARMADA_XP_TARGET_DEV_BUS	1
+#define   ARMADA_XP_ATTR_DEV_BOOTROM    0x1D
+#define ARMADA_XP_TARGET_ETH1		3
+#define ARMADA_XP_TARGET_PCIE_0_2	4
+#define ARMADA_XP_TARGET_ETH0		7
+#define ARMADA_XP_TARGET_PCIE_1_3	8
+
+#define ARMADA_370_TARGET_DEV_BUS       1
+#define   ARMADA_370_ATTR_DEV_BOOTROM   0x1D
+#define ARMADA_370_TARGET_PCIE_0        4
+#define ARMADA_370_TARGET_PCIE_1        8
+
+#define ARMADA_WINDOW_8_PLUS_OFFSET       0x90
+#define ARMADA_SDRAM_ADDR_DECODING_OFFSET 0x180
+
+static const struct __initdata orion_addr_map_info
+armada_xp_addr_map_info[] = {
+	/*
+	 * Window for the BootROM, needed for SMP on Armada XP
+	 */
+	{ 0, 0xfff00000, SZ_1M, ARMADA_XP_TARGET_DEV_BUS,
+	  ARMADA_XP_ATTR_DEV_BOOTROM, -1 },
+	/* End marker */
+	{ -1, 0, 0, 0, 0, 0 },
+};
+
+static const struct __initdata orion_addr_map_info
+armada_370_addr_map_info[] = {
+	/* End marker */
+	{ -1, 0, 0, 0, 0, 0 },
+};
+
+static struct of_device_id of_addr_decoding_controller_table[] = {
+	{ .compatible = "marvell,armada-addr-decoding-controller" },
+	{ /* end of list */ },
+};
+
+static void __iomem *
+armada_cfg_base(const struct orion_addr_map_cfg *cfg, int win)
+{
+	unsigned int offset;
+
+	/* The register layout is a bit annoying and the below code
+	 * tries to cope with it.
+	 * - At offset 0x0, there are the registers for the first 8
+	 *   windows, with 4 registers of 32 bits per window (ctrl,
+	 *   base, remap low, remap high)
+	 * - Then at offset 0x80, there is a hole of 0x10 bytes for
+	 *   the internal registers base address and internal units
+	 *   sync barrier register.
+	 * - Then at offset 0x90, there the registers for 12
+	 *   windows, with only 2 registers of 32 bits per window
+	 *   (ctrl, base).
+	 */
+	if (win < 8)
+		offset = (win << 4);
+	else
+		offset = ARMADA_WINDOW_8_PLUS_OFFSET + (win << 3);
+
+	return cfg->bridge_virt_base + offset;
+}
+
+static struct __initdata orion_addr_map_cfg addr_map_cfg = {
+	.num_wins = 20,
+	.remappable_wins = 8,
+	.win_cfg_base = armada_cfg_base,
+};
+
+static int __init armada_setup_cpu_mbus(void)
+{
+	struct device_node *np;
+	void __iomem *mbus_unit_addr_decoding_base;
+	void __iomem *sdram_addr_decoding_base;
+
+	np = of_find_matching_node(NULL, of_addr_decoding_controller_table);
+	if (!np)
+		return -ENODEV;
+
+	mbus_unit_addr_decoding_base = of_iomap(np, 0);
+	BUG_ON(!mbus_unit_addr_decoding_base);
+
+	sdram_addr_decoding_base =
+		mbus_unit_addr_decoding_base +
+		ARMADA_SDRAM_ADDR_DECODING_OFFSET;
+
+	addr_map_cfg.bridge_virt_base = mbus_unit_addr_decoding_base;
+
+	/*
+	 * Disable, clear and configure windows.
+	 */
+	if (of_machine_is_compatible("marvell,armadaxp"))
+		orion_config_wins(&addr_map_cfg, armada_xp_addr_map_info);
+	else if (of_machine_is_compatible("marvell,armada370"))
+		orion_config_wins(&addr_map_cfg, armada_370_addr_map_info);
+	else {
+		pr_err("Unsupported SoC\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * Setup MBUS dram target info.
+	 */
+	orion_setup_cpu_mbus_target(&addr_map_cfg,
+				    sdram_addr_decoding_base);
+	return 0;
+}
+
+/* Using a early_initcall is needed so that this initialization gets
+ * done before the SMP initialization, which requires the BootROM to
+ * be remapped. */
+early_initcall(armada_setup_cpu_mbus);
diff --git a/arch/arm/mach-mvebu/armada-370-xp.c b/arch/arm/mach-mvebu/armada-370-xp.c
index 4ef923b..49d7915 100644
--- a/arch/arm/mach-mvebu/armada-370-xp.c
+++ b/arch/arm/mach-mvebu/armada-370-xp.c
@@ -20,12 +20,12 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
-#include <mach/armada-370-xp.h>
+#include "armada-370-xp.h"
 #include "common.h"
 
 static struct map_desc armada_370_xp_io_desc[] __initdata = {
 	{
-		.virtual	= ARMADA_370_XP_REGS_VIRT_BASE,
+		.virtual	= (unsigned long) ARMADA_370_XP_REGS_VIRT_BASE,
 		.pfn		= __phys_to_pfn(ARMADA_370_XP_REGS_PHYS_BASE),
 		.length		= ARMADA_370_XP_REGS_SIZE,
 		.type		= MT_DEVICE,
diff --git a/arch/arm/mach-mvebu/armada-370-xp.h b/arch/arm/mach-mvebu/armada-370-xp.h
new file mode 100644
index 0000000..aac9beb
--- /dev/null
+++ b/arch/arm/mach-mvebu/armada-370-xp.h
@@ -0,0 +1,22 @@
+/*
+ * Generic definitions for Marvell Armada_370_XP SoCs
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Lior Amsalem <alior@marvell.com>
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef __MACH_ARMADA_370_XP_H
+#define __MACH_ARMADA_370_XP_H
+
+#define ARMADA_370_XP_REGS_PHYS_BASE	0xd0000000
+#define ARMADA_370_XP_REGS_VIRT_BASE	IOMEM(0xfeb00000)
+#define ARMADA_370_XP_REGS_SIZE		SZ_1M
+
+#endif /* __MACH_ARMADA_370_XP_H */
diff --git a/arch/arm/mach-mvebu/include/mach/armada-370-xp.h b/arch/arm/mach-mvebu/include/mach/armada-370-xp.h
deleted file mode 100644
index 25f0ca8..0000000
--- a/arch/arm/mach-mvebu/include/mach/armada-370-xp.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Generic definitions for Marvell Armada_370_XP SoCs
- *
- * Copyright (C) 2012 Marvell
- *
- * Lior Amsalem <alior@marvell.com>
- * Gregory CLEMENT <gregory.clement@free-electrons.com>
- * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2.  This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#ifndef __MACH_ARMADA_370_XP_H
-#define __MACH_ARMADA_370_XP_H
-
-#define ARMADA_370_XP_REGS_PHYS_BASE	0xd0000000
-#define ARMADA_370_XP_REGS_VIRT_BASE	0xfeb00000
-#define ARMADA_370_XP_REGS_SIZE		SZ_1M
-
-#endif /* __MACH_ARMADA_370_XP_H */
diff --git a/arch/arm/mach-mvebu/include/mach/debug-macro.S b/arch/arm/mach-mvebu/include/mach/debug-macro.S
deleted file mode 100644
index 2282576..0000000
--- a/arch/arm/mach-mvebu/include/mach/debug-macro.S
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Early serial output macro for Marvell  SoC
- *
- * Copyright (C) 2012 Marvell
- *
- * Lior Amsalem <alior@marvell.com>
- * Gregory Clement <gregory.clement@free-electrons.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <mach/armada-370-xp.h>
-
-	.macro	addruart, rp, rv, tmp
-	ldr	\rp, =ARMADA_370_XP_REGS_PHYS_BASE
-	ldr	\rv, =ARMADA_370_XP_REGS_VIRT_BASE
-	orr	\rp, \rp, #0x00012000
-	orr	\rv, \rv, #0x00012000
-	.endm
-
-#define UART_SHIFT	2
-#include <asm/hardware/debug-8250.S>
diff --git a/arch/arm/mach-mvebu/include/mach/gpio.h b/arch/arm/mach-mvebu/include/mach/gpio.h
new file mode 100644
index 0000000..40a8c17
--- /dev/null
+++ b/arch/arm/mach-mvebu/include/mach/gpio.h
@@ -0,0 +1 @@
+/* empty */
diff --git a/arch/arm/mach-mvebu/include/mach/timex.h b/arch/arm/mach-mvebu/include/mach/timex.h
deleted file mode 100644
index ab324a3..0000000
--- a/arch/arm/mach-mvebu/include/mach/timex.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * Marvell Armada SoC time definitions
- *
- * Copyright (C) 2012 Marvell
- *
- * Lior Amsalem <alior@marvell.com>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2.  This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#define CLOCK_TICK_RATE		(100 * HZ)
diff --git a/arch/arm/mach-mvebu/include/mach/uncompress.h b/arch/arm/mach-mvebu/include/mach/uncompress.h
deleted file mode 100644
index d6a100c..0000000
--- a/arch/arm/mach-mvebu/include/mach/uncompress.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Marvell Armada SoC kernel uncompression UART routines
- *
- * Copyright (C) 2012 Marvell
- *
- * Lior Amsalem <alior@marvell.com>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2.  This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <mach/armada-370-xp.h>
-
-#define UART_THR ((volatile unsigned char *)(ARMADA_370_XP_REGS_PHYS_BASE\
-								+ 0x12000))
-#define UART_LSR ((volatile unsigned char *)(ARMADA_370_XP_REGS_PHYS_BASE\
-								+ 0x12014))
-
-#define LSR_THRE	0x20
-
-static void putc(const char c)
-{
-	int i;
-
-	for (i = 0; i < 0x1000; i++) {
-		/* Transmit fifo not full? */
-		if (*UART_LSR & LSR_THRE)
-			break;
-	}
-
-	*UART_THR = c;
-}
-
-static void flush(void)
-{
-}
-
-/*
- * nothing to do
- */
-#define arch_decomp_setup()
-#define arch_decomp_wdog()
diff --git a/arch/arm/mach-mxs/Kconfig b/arch/arm/mach-mxs/Kconfig
index 9a8bbda..ecc4319 100644
--- a/arch/arm/mach-mxs/Kconfig
+++ b/arch/arm/mach-mxs/Kconfig
@@ -1,7 +1,5 @@
 if ARCH_MXS
 
-source "arch/arm/mach-mxs/devices/Kconfig"
-
 config SOC_IMX23
 	bool
 	select ARM_AMBA
@@ -27,91 +25,4 @@ config MACH_MXS_DT
 	  Include support for Freescale MXS platforms(i.MX23 and i.MX28)
 	  using the device tree for discovery
 
-config MACH_STMP378X_DEVB
-	bool "Support STMP378x_devb Platform"
-	select SOC_IMX23
-	select MXS_HAVE_AMBA_DUART
-	select MXS_HAVE_PLATFORM_AUART
-	select MXS_HAVE_PLATFORM_MXS_MMC
-	select MXS_HAVE_PLATFORM_RTC_STMP3XXX
-	help
-	  Include support for STMP378x-devb platform. This includes specific
-	  configurations for the board and its peripherals.
-
-config MACH_MX23EVK
-	bool "Support MX23EVK Platform"
-	select SOC_IMX23
-	select MXS_HAVE_AMBA_DUART
-	select MXS_HAVE_PLATFORM_AUART
-	select MXS_HAVE_PLATFORM_MXS_MMC
-	select MXS_HAVE_PLATFORM_MXSFB
-	select MXS_HAVE_PLATFORM_RTC_STMP3XXX
-	help
-	  Include support for MX23EVK platform. This includes specific
-	  configurations for the board and its peripherals.
-
-config MACH_MX28EVK
-	bool "Support MX28EVK Platform"
-	select SOC_IMX28
-	select LEDS_GPIO_REGISTER
-	select MXS_HAVE_AMBA_DUART
-	select MXS_HAVE_PLATFORM_AUART
-	select MXS_HAVE_PLATFORM_FEC
-	select MXS_HAVE_PLATFORM_FLEXCAN
-	select MXS_HAVE_PLATFORM_MXS_MMC
-	select MXS_HAVE_PLATFORM_MXSFB
-	select MXS_HAVE_PLATFORM_MXS_SAIF
-	select MXS_HAVE_PLATFORM_MXS_I2C
-	select MXS_HAVE_PLATFORM_RTC_STMP3XXX
-	help
-	  Include support for MX28EVK platform. This includes specific
-	  configurations for the board and its peripherals.
-
-config MODULE_TX28
-	bool
-	select SOC_IMX28
-	select LEDS_GPIO_REGISTER
-	select MXS_HAVE_AMBA_DUART
-	select MXS_HAVE_PLATFORM_AUART
-	select MXS_HAVE_PLATFORM_FEC
-	select MXS_HAVE_PLATFORM_MXS_I2C
-	select MXS_HAVE_PLATFORM_MXS_MMC
-	select MXS_HAVE_PLATFORM_MXS_PWM
-	select MXS_HAVE_PLATFORM_RTC_STMP3XXX
-
-config MODULE_M28
-	bool
-	select SOC_IMX28
-	select LEDS_GPIO_REGISTER
-	select MXS_HAVE_AMBA_DUART
-	select MXS_HAVE_PLATFORM_AUART
-	select MXS_HAVE_PLATFORM_FEC
-	select MXS_HAVE_PLATFORM_FLEXCAN
-	select MXS_HAVE_PLATFORM_MXS_I2C
-	select MXS_HAVE_PLATFORM_MXS_MMC
-	select MXS_HAVE_PLATFORM_MXSFB
-
-config MODULE_APX4
-	bool
-	select SOC_IMX28
-	select LEDS_GPIO_REGISTER
-	select MXS_HAVE_AMBA_DUART
-	select MXS_HAVE_PLATFORM_AUART
-	select MXS_HAVE_PLATFORM_FEC
-	select MXS_HAVE_PLATFORM_MXS_I2C
-	select MXS_HAVE_PLATFORM_MXS_MMC
-	select MXS_HAVE_PLATFORM_MXS_SAIF
-
-config MACH_TX28
-	bool "Ka-Ro TX28 module"
-	select MODULE_TX28
-
-config MACH_M28EVK
-	bool "Support DENX M28EVK Platform"
-	select MODULE_M28
-
-config MACH_APX4DEVKIT
-	bool "Support Bluegiga APX4 Development Kit"
-	select MODULE_APX4
-
 endif
diff --git a/arch/arm/mach-mxs/Makefile b/arch/arm/mach-mxs/Makefile
index fed3695..3d3c8a9 100644
--- a/arch/arm/mach-mxs/Makefile
+++ b/arch/arm/mach-mxs/Makefile
@@ -1,15 +1,6 @@
 # Common support
-obj-y := devices.o icoll.o iomux.o ocotp.o system.o timer.o mm.o
+obj-y := icoll.o ocotp.o system.o timer.o mm.o
 
 obj-$(CONFIG_PM) += pm.o
 
 obj-$(CONFIG_MACH_MXS_DT) += mach-mxs.o
-obj-$(CONFIG_MACH_STMP378X_DEVB) += mach-stmp378x_devb.o
-obj-$(CONFIG_MACH_MX23EVK) += mach-mx23evk.o
-obj-$(CONFIG_MACH_MX28EVK) += mach-mx28evk.o
-obj-$(CONFIG_MACH_M28EVK)    += mach-m28evk.o
-obj-$(CONFIG_MACH_APX4DEVKIT) += mach-apx4devkit.o
-obj-$(CONFIG_MODULE_TX28) += module-tx28.o
-obj-$(CONFIG_MACH_TX28)    += mach-tx28.o
-
-obj-y += devices/
diff --git a/arch/arm/mach-mxs/Makefile.boot b/arch/arm/mach-mxs/Makefile.boot
index 4582999..07b11fe 100644
--- a/arch/arm/mach-mxs/Makefile.boot
+++ b/arch/arm/mach-mxs/Makefile.boot
@@ -1,10 +1 @@
 zreladdr-y += 0x40008000
-
-dtb-y += imx23-evk.dtb \
-	 imx23-olinuxino.dtb \
-	 imx23-stmp378x_devb.dtb \
-	 imx28-apx4devkit.dtb \
-	 imx28-cfa10036.dtb \
-	 imx28-evk.dtb \
-	 imx28-m28evk.dtb \
-	 imx28-tx28.dtb \
diff --git a/arch/arm/mach-mxs/devices-mx23.h b/arch/arm/mach-mxs/devices-mx23.h
deleted file mode 100644
index 9ee5ced..0000000
--- a/arch/arm/mach-mxs/devices-mx23.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2010 Pengutronix
- * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
- *
- * Copyright 2010 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License version 2 as published by the
- * Free Software Foundation.
- */
-#include <mach/mx23.h>
-#include <mach/devices-common.h>
-#include <linux/mxsfb.h>
-#include <linux/amba/bus.h>
-
-static inline int mx23_add_duart(void)
-{
-	struct amba_device *d;
-
-	d = amba_ahb_device_add(NULL, "duart", MX23_DUART_BASE_ADDR, SZ_8K,
-				MX23_INT_DUART, 0, 0, 0);
-	return IS_ERR(d) ? PTR_ERR(d) : 0;
-}
-
-extern const struct mxs_auart_data mx23_auart_data[] __initconst;
-#define mx23_add_auart(id)	mxs_add_auart(&mx23_auart_data[id])
-#define mx23_add_auart0()		mx23_add_auart(0)
-#define mx23_add_auart1()		mx23_add_auart(1)
-
-extern const struct mxs_gpmi_nand_data mx23_gpmi_nand_data __initconst;
-#define mx23_add_gpmi_nand(pdata)	\
-	mxs_add_gpmi_nand(pdata, &mx23_gpmi_nand_data)
-
-extern const struct mxs_mxs_mmc_data mx23_mxs_mmc_data[] __initconst;
-#define mx23_add_mxs_mmc(id, pdata) \
-	mxs_add_mxs_mmc(&mx23_mxs_mmc_data[id], pdata)
-
-#define mx23_add_mxs_pwm(id)		mxs_add_mxs_pwm(MX23_PWM_BASE_ADDR, id)
-
-struct platform_device *__init mx23_add_mxsfb(
-		const struct mxsfb_platform_data *pdata);
-
-struct platform_device *__init mx23_add_rtc_stmp3xxx(void);
diff --git a/arch/arm/mach-mxs/devices-mx28.h b/arch/arm/mach-mxs/devices-mx28.h
deleted file mode 100644
index fcab431..0000000
--- a/arch/arm/mach-mxs/devices-mx28.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2010 Pengutronix
- * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
- *
- * Copyright 2010 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License version 2 as published by the
- * Free Software Foundation.
- */
-#include <mach/mx28.h>
-#include <mach/devices-common.h>
-#include <linux/mxsfb.h>
-#include <linux/amba/bus.h>
-
-static inline int mx28_add_duart(void)
-{
-	struct amba_device *d;
-
-	d = amba_ahb_device_add(NULL, "duart", MX28_DUART_BASE_ADDR, SZ_8K,
-				MX28_INT_DUART, 0, 0, 0);
-	return IS_ERR(d) ? PTR_ERR(d) : 0;
-}
-
-extern const struct mxs_auart_data mx28_auart_data[] __initconst;
-#define mx28_add_auart(id)	mxs_add_auart(&mx28_auart_data[id])
-#define mx28_add_auart0()		mx28_add_auart(0)
-#define mx28_add_auart1()		mx28_add_auart(1)
-#define mx28_add_auart2()		mx28_add_auart(2)
-#define mx28_add_auart3()		mx28_add_auart(3)
-#define mx28_add_auart4()		mx28_add_auart(4)
-
-extern const struct mxs_fec_data mx28_fec_data[] __initconst;
-#define mx28_add_fec(id, pdata) \
-	mxs_add_fec(&mx28_fec_data[id], pdata)
-
-extern const struct mxs_flexcan_data mx28_flexcan_data[] __initconst;
-#define mx28_add_flexcan(id, pdata)	\
-	mxs_add_flexcan(&mx28_flexcan_data[id], pdata)
-#define mx28_add_flexcan0(pdata)	mx28_add_flexcan(0, pdata)
-#define mx28_add_flexcan1(pdata)	mx28_add_flexcan(1, pdata)
-
-extern const struct mxs_gpmi_nand_data mx28_gpmi_nand_data __initconst;
-#define mx28_add_gpmi_nand(pdata)	\
-	mxs_add_gpmi_nand(pdata, &mx28_gpmi_nand_data)
-
-extern const struct mxs_mxs_i2c_data mx28_mxs_i2c_data[] __initconst;
-#define mx28_add_mxs_i2c(id)		mxs_add_mxs_i2c(&mx28_mxs_i2c_data[id])
-
-extern const struct mxs_mxs_mmc_data mx28_mxs_mmc_data[] __initconst;
-#define mx28_add_mxs_mmc(id, pdata) \
-	mxs_add_mxs_mmc(&mx28_mxs_mmc_data[id], pdata)
-
-#define mx28_add_mxs_pwm(id)		mxs_add_mxs_pwm(MX28_PWM_BASE_ADDR, id)
-
-struct platform_device *__init mx28_add_mxsfb(
-		const struct mxsfb_platform_data *pdata);
-
-extern const struct mxs_saif_data mx28_saif_data[] __initconst;
-#define mx28_add_saif(id, pdata) \
-	mxs_add_saif(&mx28_saif_data[id], pdata)
-
-struct platform_device *__init mx28_add_rtc_stmp3xxx(void);
diff --git a/arch/arm/mach-mxs/devices.c b/arch/arm/mach-mxs/devices.c
deleted file mode 100644
index cf50b5a..0000000
--- a/arch/arm/mach-mxs/devices.c
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright 2008 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.
- */
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/amba/bus.h>
-
-struct platform_device *__init mxs_add_platform_device_dmamask(
-		const char *name, int id,
-		const struct resource *res, unsigned int num_resources,
-		const void *data, size_t size_data, u64 dmamask)
-{
-	int ret = -ENOMEM;
-	struct platform_device *pdev;
-
-	pdev = platform_device_alloc(name, id);
-	if (!pdev)
-		goto err;
-
-	if (dmamask) {
-		/*
-		 * This memory isn't freed when the device is put,
-		 * I don't have a nice idea for that though.  Conceptually
-		 * dma_mask in struct device should not be a pointer.
-		 * See http://thread.gmane.org/gmane.linux.kernel.pci/9081
-		 */
-		pdev->dev.dma_mask =
-			kmalloc(sizeof(*pdev->dev.dma_mask), GFP_KERNEL);
-		if (!pdev->dev.dma_mask)
-			/* ret is still -ENOMEM; */
-			goto err;
-
-		*pdev->dev.dma_mask = dmamask;
-		pdev->dev.coherent_dma_mask = dmamask;
-	}
-
-	if (res) {
-		ret = platform_device_add_resources(pdev, res, num_resources);
-		if (ret)
-			goto err;
-	}
-
-	if (data) {
-		ret = platform_device_add_data(pdev, data, size_data);
-		if (ret)
-			goto err;
-	}
-
-	ret = platform_device_add(pdev);
-	if (ret) {
-err:
-		if (dmamask)
-			kfree(pdev->dev.dma_mask);
-		platform_device_put(pdev);
-		return ERR_PTR(ret);
-	}
-
-	return pdev;
-}
-
-struct device mxs_apbh_bus = {
-	.init_name	= "mxs_apbh",
-	.parent         = &platform_bus,
-};
-
-static int __init mxs_device_init(void)
-{
-	return device_register(&mxs_apbh_bus);
-}
-core_initcall(mxs_device_init);
diff --git a/arch/arm/mach-mxs/devices/Kconfig b/arch/arm/mach-mxs/devices/Kconfig
deleted file mode 100644
index 19659de..0000000
--- a/arch/arm/mach-mxs/devices/Kconfig
+++ /dev/null
@@ -1,33 +0,0 @@
-config MXS_HAVE_AMBA_DUART
-	bool
-
-config MXS_HAVE_PLATFORM_AUART
-	bool
-
-config MXS_HAVE_PLATFORM_FEC
-	bool
-
-config MXS_HAVE_PLATFORM_FLEXCAN
-	select HAVE_CAN_FLEXCAN if CAN
-	bool
-
-config MXS_HAVE_PLATFORM_GPMI_NAND
-	bool
-
-config MXS_HAVE_PLATFORM_MXS_I2C
-	bool
-
-config MXS_HAVE_PLATFORM_MXS_MMC
-	bool
-
-config MXS_HAVE_PLATFORM_MXS_PWM
-	bool
-
-config MXS_HAVE_PLATFORM_MXSFB
-	bool
-
-config MXS_HAVE_PLATFORM_MXS_SAIF
-	bool
-
-config MXS_HAVE_PLATFORM_RTC_STMP3XXX
-	bool
diff --git a/arch/arm/mach-mxs/devices/Makefile b/arch/arm/mach-mxs/devices/Makefile
deleted file mode 100644
index 5f72d97..0000000
--- a/arch/arm/mach-mxs/devices/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-obj-$(CONFIG_MXS_HAVE_PLATFORM_AUART) += platform-auart.o
-obj-y += platform-dma.o
-obj-$(CONFIG_MXS_HAVE_PLATFORM_FEC) += platform-fec.o
-obj-$(CONFIG_MXS_HAVE_PLATFORM_FLEXCAN) += platform-flexcan.o
-obj-$(CONFIG_MXS_HAVE_PLATFORM_GPMI_NAND) += platform-gpmi-nand.o
-obj-$(CONFIG_MXS_HAVE_PLATFORM_MXS_I2C) += platform-mxs-i2c.o
-obj-$(CONFIG_MXS_HAVE_PLATFORM_MXS_MMC) += platform-mxs-mmc.o
-obj-$(CONFIG_MXS_HAVE_PLATFORM_MXS_PWM) += platform-mxs-pwm.o
-obj-y += platform-gpio-mxs.o
-obj-$(CONFIG_MXS_HAVE_PLATFORM_MXSFB) += platform-mxsfb.o
-obj-$(CONFIG_MXS_HAVE_PLATFORM_MXS_SAIF) += platform-mxs-saif.o
-obj-$(CONFIG_MXS_HAVE_PLATFORM_RTC_STMP3XXX) += platform-rtc-stmp3xxx.o
diff --git a/arch/arm/mach-mxs/devices/platform-auart.c b/arch/arm/mach-mxs/devices/platform-auart.c
deleted file mode 100644
index 27608f5..0000000
--- a/arch/arm/mach-mxs/devices/platform-auart.c
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2010 Pengutronix
- * Sascha Hauer <s.hauer@pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License version 2 as published by the
- * Free Software Foundation.
- */
-#include <linux/dma-mapping.h>
-#include <asm/sizes.h>
-#include <mach/mx23.h>
-#include <mach/mx28.h>
-#include <mach/devices-common.h>
-
-#define mxs_auart_data_entry_single(soc, _id, hwid)			\
-	{								\
-		.id = _id,						\
-		.iobase = soc ## _AUART ## hwid ## _BASE_ADDR,		\
-		.irq = soc ## _INT_AUART ## hwid,			\
-	}
-
-#define mxs_auart_data_entry(soc, _id, hwid)				\
-	[_id] = mxs_auart_data_entry_single(soc, _id, hwid)
-
-#ifdef CONFIG_SOC_IMX23
-const struct mxs_auart_data mx23_auart_data[] __initconst = {
-#define mx23_auart_data_entry(_id, hwid)				\
-	mxs_auart_data_entry(MX23, _id, hwid)
-	mx23_auart_data_entry(0, 1),
-	mx23_auart_data_entry(1, 2),
-};
-#endif
-
-#ifdef CONFIG_SOC_IMX28
-const struct mxs_auart_data mx28_auart_data[] __initconst = {
-#define mx28_auart_data_entry(_id)					\
-	mxs_auart_data_entry(MX28, _id, _id)
-	mx28_auart_data_entry(0),
-	mx28_auart_data_entry(1),
-	mx28_auart_data_entry(2),
-	mx28_auart_data_entry(3),
-	mx28_auart_data_entry(4),
-};
-#endif
-
-struct platform_device *__init mxs_add_auart(
-		const struct mxs_auart_data *data)
-{
-	struct resource res[] = {
-		{
-			.start = data->iobase,
-			.end = data->iobase + SZ_8K - 1,
-			.flags = IORESOURCE_MEM,
-		}, {
-			.start = data->irq,
-			.end = data->irq,
-			.flags = IORESOURCE_IRQ,
-		},
-	};
-
-	return mxs_add_platform_device_dmamask("mxs-auart", data->id,
-					res, ARRAY_SIZE(res), NULL, 0,
-					DMA_BIT_MASK(32));
-}
-
diff --git a/arch/arm/mach-mxs/devices/platform-dma.c b/arch/arm/mach-mxs/devices/platform-dma.c
deleted file mode 100644
index 4682450..0000000
--- a/arch/arm/mach-mxs/devices/platform-dma.c
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License version 2 as published by the
- * Free Software Foundation.
- */
-#include <linux/compiler.h>
-#include <linux/dma-mapping.h>
-#include <linux/err.h>
-#include <linux/init.h>
-
-#include <mach/mx23.h>
-#include <mach/mx28.h>
-#include <mach/devices-common.h>
-
-struct platform_device *__init mxs_add_dma(const char *devid,
-						resource_size_t base)
-{
-	struct resource res[] = {
-		{
-			.start = base,
-			.end = base + SZ_8K - 1,
-			.flags = IORESOURCE_MEM,
-		}
-	};
-
-	return mxs_add_platform_device_dmamask(devid, -1,
-				res, ARRAY_SIZE(res), NULL, 0,
-				DMA_BIT_MASK(32));
-}
diff --git a/arch/arm/mach-mxs/devices/platform-fec.c b/arch/arm/mach-mxs/devices/platform-fec.c
deleted file mode 100644
index ae96a4f..0000000
--- a/arch/arm/mach-mxs/devices/platform-fec.c
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2010 Pengutronix
- * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License version 2 as published by the
- * Free Software Foundation.
- */
-#include <linux/dma-mapping.h>
-#include <asm/sizes.h>
-#include <mach/mx28.h>
-#include <mach/devices-common.h>
-
-#define mxs_fec_data_entry_single(soc, _id)				\
-	{								\
-		.id = _id,						\
-		.iobase = soc ## _ENET_MAC ## _id ## _BASE_ADDR,	\
-		.irq = soc ## _INT_ENET_MAC ## _id,			\
-	}
-
-#define mxs_fec_data_entry(soc, _id)					\
-	[_id] = mxs_fec_data_entry_single(soc, _id)
-
-#ifdef CONFIG_SOC_IMX28
-const struct mxs_fec_data mx28_fec_data[] __initconst = {
-#define mx28_fec_data_entry(_id)					\
-	mxs_fec_data_entry(MX28, _id)
-	mx28_fec_data_entry(0),
-	mx28_fec_data_entry(1),
-};
-#endif
-
-struct platform_device *__init mxs_add_fec(
-		const struct mxs_fec_data *data,
-		const struct fec_platform_data *pdata)
-{
-	struct resource res[] = {
-		{
-			.start = data->iobase,
-			.end = data->iobase + SZ_16K - 1,
-			.flags = IORESOURCE_MEM,
-		}, {
-			.start = data->irq,
-			.end = data->irq,
-			.flags = IORESOURCE_IRQ,
-		},
-	};
-
-	return mxs_add_platform_device_dmamask("imx28-fec", data->id,
-			res, ARRAY_SIZE(res), pdata, sizeof(*pdata),
-			DMA_BIT_MASK(32));
-}
diff --git a/arch/arm/mach-mxs/devices/platform-flexcan.c b/arch/arm/mach-mxs/devices/platform-flexcan.c
deleted file mode 100644
index 43a6b4b..0000000
--- a/arch/arm/mach-mxs/devices/platform-flexcan.c
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2010, 2011 Pengutronix,
- *                          Marc Kleine-Budde <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 version 2 as published by the
- * Free Software Foundation.
- */
-#include <asm/sizes.h>
-#include <mach/mx28.h>
-#include <mach/devices-common.h>
-
-#define mxs_flexcan_data_entry_single(soc, _id, _hwid, _size)		\
-	{								\
-		.id = _id,						\
-		.iobase = soc ## _CAN ## _hwid ## _BASE_ADDR,		\
-		.iosize = _size,					\
-		.irq = soc ## _INT_CAN ## _hwid,			\
-	}
-
-#define mxs_flexcan_data_entry(soc, _id, _hwid, _size)			\
-	[_id] = mxs_flexcan_data_entry_single(soc, _id, _hwid, _size)
-
-#ifdef CONFIG_SOC_IMX28
-const struct mxs_flexcan_data mx28_flexcan_data[] __initconst = {
-#define mx28_flexcan_data_entry(_id, _hwid)				\
-	mxs_flexcan_data_entry_single(MX28, _id, _hwid, SZ_8K)
-	mx28_flexcan_data_entry(0, 0),
-	mx28_flexcan_data_entry(1, 1),
-};
-#endif /* ifdef CONFIG_SOC_IMX28 */
-
-struct platform_device *__init mxs_add_flexcan(
-		const struct mxs_flexcan_data *data,
-		const struct flexcan_platform_data *pdata)
-{
-	struct resource res[] = {
-		{
-			.start = data->iobase,
-			.end = data->iobase + data->iosize - 1,
-			.flags = IORESOURCE_MEM,
-		}, {
-			.start = data->irq,
-			.end = data->irq,
-			.flags = IORESOURCE_IRQ,
-		},
-	};
-
-	return mxs_add_platform_device("flexcan", data->id,
-			res, ARRAY_SIZE(res), pdata, sizeof(*pdata));
-}
diff --git a/arch/arm/mach-mxs/devices/platform-gpio-mxs.c b/arch/arm/mach-mxs/devices/platform-gpio-mxs.c
deleted file mode 100644
index cd99f19..0000000
--- a/arch/arm/mach-mxs/devices/platform-gpio-mxs.c
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License version 2 as published by the
- * Free Software Foundation.
- */
-#include <linux/compiler.h>
-#include <linux/err.h>
-#include <linux/init.h>
-
-#include <mach/mx23.h>
-#include <mach/mx28.h>
-#include <mach/devices-common.h>
-
-struct platform_device *__init mxs_add_gpio(
-	char *name, int id, resource_size_t iobase, int irq)
-{
-	struct resource res[] = {
-		{
-			.start = iobase,
-			.end = iobase + SZ_8K - 1,
-			.flags = IORESOURCE_MEM,
-		}, {
-			.start = irq,
-			.end = irq,
-			.flags = IORESOURCE_IRQ,
-		},
-	};
-
-	return platform_device_register_resndata(&mxs_apbh_bus,
-			name, id, res, ARRAY_SIZE(res), NULL, 0);
-}
diff --git a/arch/arm/mach-mxs/devices/platform-gpmi-nand.c b/arch/arm/mach-mxs/devices/platform-gpmi-nand.c
deleted file mode 100644
index 3e22df5..0000000
--- a/arch/arm/mach-mxs/devices/platform-gpmi-nand.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (C) 2011 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 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 <asm/sizes.h>
-#include <mach/mx23.h>
-#include <mach/mx28.h>
-#include <mach/devices-common.h>
-#include <linux/dma-mapping.h>
-
-#ifdef CONFIG_SOC_IMX23
-const struct mxs_gpmi_nand_data mx23_gpmi_nand_data __initconst = {
-	.devid = "imx23-gpmi-nand",
-	.res = {
-		/* GPMI */
-		DEFINE_RES_MEM_NAMED(MX23_GPMI_BASE_ADDR, SZ_8K,
-					GPMI_NAND_GPMI_REGS_ADDR_RES_NAME),
-		DEFINE_RES_IRQ_NAMED(MX23_INT_GPMI_ATTENTION,
-					GPMI_NAND_GPMI_INTERRUPT_RES_NAME),
-		/* BCH */
-		DEFINE_RES_MEM_NAMED(MX23_BCH_BASE_ADDR, SZ_8K,
-					GPMI_NAND_BCH_REGS_ADDR_RES_NAME),
-		DEFINE_RES_IRQ_NAMED(MX23_INT_BCH,
-					GPMI_NAND_BCH_INTERRUPT_RES_NAME),
-		/* DMA */
-		DEFINE_RES_NAMED(MX23_DMA_GPMI0,
-					MX23_DMA_GPMI3 - MX23_DMA_GPMI0 + 1,
-					GPMI_NAND_DMA_CHANNELS_RES_NAME,
-					IORESOURCE_DMA),
-		DEFINE_RES_IRQ_NAMED(MX23_INT_GPMI_DMA,
-					GPMI_NAND_DMA_INTERRUPT_RES_NAME),
-	},
-};
-#endif
-
-#ifdef CONFIG_SOC_IMX28
-const struct mxs_gpmi_nand_data mx28_gpmi_nand_data __initconst = {
-	.devid = "imx28-gpmi-nand",
-	.res = {
-		/* GPMI */
-		DEFINE_RES_MEM_NAMED(MX28_GPMI_BASE_ADDR, SZ_8K,
-					GPMI_NAND_GPMI_REGS_ADDR_RES_NAME),
-		DEFINE_RES_IRQ_NAMED(MX28_INT_GPMI,
-					GPMI_NAND_GPMI_INTERRUPT_RES_NAME),
-		/* BCH */
-		DEFINE_RES_MEM_NAMED(MX28_BCH_BASE_ADDR, SZ_8K,
-					GPMI_NAND_BCH_REGS_ADDR_RES_NAME),
-		DEFINE_RES_IRQ_NAMED(MX28_INT_BCH,
-					GPMI_NAND_BCH_INTERRUPT_RES_NAME),
-		/* DMA */
-		DEFINE_RES_NAMED(MX28_DMA_GPMI0,
-					MX28_DMA_GPMI7 - MX28_DMA_GPMI0 + 1,
-					GPMI_NAND_DMA_CHANNELS_RES_NAME,
-					IORESOURCE_DMA),
-		DEFINE_RES_IRQ_NAMED(MX28_INT_GPMI_DMA,
-					GPMI_NAND_DMA_INTERRUPT_RES_NAME),
-	},
-};
-#endif
-
-struct platform_device *__init
-mxs_add_gpmi_nand(const struct gpmi_nand_platform_data *pdata,
-		const struct mxs_gpmi_nand_data *data)
-{
-	return mxs_add_platform_device_dmamask(data->devid, -1,
-				data->res, GPMI_NAND_RES_SIZE,
-				pdata, sizeof(*pdata), DMA_BIT_MASK(32));
-}
diff --git a/arch/arm/mach-mxs/devices/platform-mxs-i2c.c b/arch/arm/mach-mxs/devices/platform-mxs-i2c.c
deleted file mode 100644
index 79222ec..0000000
--- a/arch/arm/mach-mxs/devices/platform-mxs-i2c.c
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2011 Pengutronix
- * 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 version 2 as published by the
- * Free Software Foundation.
- */
-#include <asm/sizes.h>
-#include <mach/mx28.h>
-#include <mach/devices-common.h>
-
-#define mxs_i2c_data_entry_single(soc, _id)				\
-	{								\
-		.id = _id,						\
-		.iobase = soc ## _I2C ## _id ## _BASE_ADDR,		\
-		.errirq = soc ## _INT_I2C ## _id ## _ERROR,		\
-		.dmairq = soc ## _INT_I2C ## _id ## _DMA,		\
-	}
-
-#define mxs_i2c_data_entry(soc, _id)					\
-	[_id] = mxs_i2c_data_entry_single(soc, _id)
-
-#ifdef CONFIG_SOC_IMX28
-const struct mxs_mxs_i2c_data mx28_mxs_i2c_data[] __initconst = {
-	mxs_i2c_data_entry(MX28, 0),
-	mxs_i2c_data_entry(MX28, 1),
-};
-#endif
-
-struct platform_device *__init mxs_add_mxs_i2c(
-		const struct mxs_mxs_i2c_data *data)
-{
-	struct resource res[] = {
-		{
-			.start = data->iobase,
-			.end = data->iobase + SZ_8K - 1,
-			.flags = IORESOURCE_MEM,
-		}, {
-			.start = data->errirq,
-			.end = data->errirq,
-			.flags = IORESOURCE_IRQ,
-		}, {
-			.start = data->dmairq,
-			.end = data->dmairq,
-			.flags = IORESOURCE_IRQ,
-		},
-	};
-
-	return mxs_add_platform_device("mxs-i2c", data->id, res,
-					ARRAY_SIZE(res), NULL, 0);
-}
diff --git a/arch/arm/mach-mxs/devices/platform-mxs-mmc.c b/arch/arm/mach-mxs/devices/platform-mxs-mmc.c
deleted file mode 100644
index b33c9d0..0000000
--- a/arch/arm/mach-mxs/devices/platform-mxs-mmc.c
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2010 Pengutronix
- * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
- *
- * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License version 2 as published by the
- * Free Software Foundation.
- */
-
-#include <linux/compiler.h>
-#include <linux/err.h>
-#include <linux/init.h>
-
-#include <mach/mx23.h>
-#include <mach/mx28.h>
-#include <mach/devices-common.h>
-
-#define mxs_mxs_mmc_data_entry_single(soc, _devid, _id, hwid)		\
-	{								\
-		.devid = _devid,					\
-		.id = _id,						\
-		.iobase = soc ## _SSP ## hwid ## _BASE_ADDR,		\
-		.dma = soc ## _DMA_SSP ## hwid,				\
-		.irq_err = soc ## _INT_SSP ## hwid ## _ERROR,		\
-		.irq_dma = soc ## _INT_SSP ## hwid ## _DMA,		\
-	}
-
-#define mxs_mxs_mmc_data_entry(soc, _devid, _id, hwid)			\
-	[_id] = mxs_mxs_mmc_data_entry_single(soc, _devid, _id, hwid)
-
-
-#ifdef CONFIG_SOC_IMX23
-const struct mxs_mxs_mmc_data mx23_mxs_mmc_data[] __initconst = {
-	mxs_mxs_mmc_data_entry(MX23, "imx23-mmc", 0, 1),
-	mxs_mxs_mmc_data_entry(MX23, "imx23-mmc", 1, 2),
-};
-#endif
-
-#ifdef CONFIG_SOC_IMX28
-const struct mxs_mxs_mmc_data mx28_mxs_mmc_data[] __initconst = {
-	mxs_mxs_mmc_data_entry(MX28, "imx28-mmc", 0, 0),
-	mxs_mxs_mmc_data_entry(MX28, "imx28-mmc", 1, 1),
-	mxs_mxs_mmc_data_entry(MX28, "imx28-mmc", 2, 2),
-	mxs_mxs_mmc_data_entry(MX28, "imx28-mmc", 3, 3),
-};
-#endif
-
-struct platform_device *__init mxs_add_mxs_mmc(
-		const struct mxs_mxs_mmc_data *data,
-		const struct mxs_mmc_platform_data *pdata)
-{
-	struct resource res[] = {
-		{
-			.start	= data->iobase,
-			.end	= data->iobase + SZ_8K - 1,
-			.flags	= IORESOURCE_MEM,
-		}, {
-			.start	= data->dma,
-			.end	= data->dma,
-			.flags	= IORESOURCE_DMA,
-		}, {
-			.start	= data->irq_err,
-			.end	= data->irq_err,
-			.flags	= IORESOURCE_IRQ,
-		}, {
-			.start	= data->irq_dma,
-			.end	= data->irq_dma,
-			.flags	= IORESOURCE_IRQ,
-		},
-	};
-
-	return mxs_add_platform_device(data->devid, data->id,
-			res, ARRAY_SIZE(res), pdata, sizeof(*pdata));
-}
diff --git a/arch/arm/mach-mxs/devices/platform-mxs-pwm.c b/arch/arm/mach-mxs/devices/platform-mxs-pwm.c
deleted file mode 100644
index 680f5a9..0000000
--- a/arch/arm/mach-mxs/devices/platform-mxs-pwm.c
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2010 Pengutronix
- * Sascha Hauer <s.hauer@pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License version 2 as published by the
- * Free Software Foundation.
- */
-#include <asm/sizes.h>
-#include <mach/devices-common.h>
-
-struct platform_device *__init mxs_add_mxs_pwm(resource_size_t iobase, int id)
-{
-	struct resource res = {
-		.flags = IORESOURCE_MEM,
-	};
-
-	res.start = iobase + 0x10 + 0x20 * id;
-	res.end = res.start + 0x1f;
-
-	return mxs_add_platform_device("mxs-pwm", id, &res, 1, NULL, 0);
-}
diff --git a/arch/arm/mach-mxs/devices/platform-mxs-saif.c b/arch/arm/mach-mxs/devices/platform-mxs-saif.c
deleted file mode 100644
index f6e3a60..0000000
--- a/arch/arm/mach-mxs/devices/platform-mxs-saif.c
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License version 2 as published by the
- * Free Software Foundation.
- */
-#include <linux/compiler.h>
-#include <linux/err.h>
-#include <linux/init.h>
-
-#include <mach/mx23.h>
-#include <mach/mx28.h>
-#include <mach/devices-common.h>
-
-#define mxs_saif_data_entry_single(soc, _id)				\
-	{								\
-		.id = _id,						\
-		.iobase = soc ## _SAIF ## _id ## _BASE_ADDR,		\
-		.irq = soc ## _INT_SAIF ## _id,				\
-		.dma = soc ## _DMA_SAIF ## _id,				\
-		.dmairq = soc ## _INT_SAIF ## _id ##_DMA,		\
-	}
-
-#define mxs_saif_data_entry(soc, _id)					\
-	[_id] = mxs_saif_data_entry_single(soc, _id)
-
-#ifdef CONFIG_SOC_IMX28
-const struct mxs_saif_data mx28_saif_data[] __initconst = {
-	mxs_saif_data_entry(MX28, 0),
-	mxs_saif_data_entry(MX28, 1),
-};
-#endif
-
-struct platform_device *__init mxs_add_saif(const struct mxs_saif_data *data,
-				const struct mxs_saif_platform_data *pdata)
-{
-	struct resource res[] = {
-		{
-			.start = data->iobase,
-			.end = data->iobase + SZ_4K - 1,
-			.flags = IORESOURCE_MEM,
-		}, {
-			.start = data->irq,
-			.end = data->irq,
-			.flags = IORESOURCE_IRQ,
-		}, {
-			.start = data->dma,
-			.end = data->dma,
-			.flags = IORESOURCE_DMA,
-		}, {
-			.start = data->dmairq,
-			.end = data->dmairq,
-			.flags = IORESOURCE_IRQ,
-		},
-
-	};
-
-	return mxs_add_platform_device("mxs-saif", data->id, res,
-				ARRAY_SIZE(res), pdata, sizeof(*pdata));
-}
diff --git a/arch/arm/mach-mxs/devices/platform-mxsfb.c b/arch/arm/mach-mxs/devices/platform-mxsfb.c
deleted file mode 100644
index 76b53f73..0000000
--- a/arch/arm/mach-mxs/devices/platform-mxsfb.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2011 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License version 2 as published by the
- * Free Software Foundation.
- */
-#include <linux/dma-mapping.h>
-#include <asm/sizes.h>
-#include <mach/mx23.h>
-#include <mach/mx28.h>
-#include <mach/devices-common.h>
-#include <linux/mxsfb.h>
-
-#ifdef CONFIG_SOC_IMX23
-struct platform_device *__init mx23_add_mxsfb(
-		const struct mxsfb_platform_data *pdata)
-{
-	struct resource res[] = {
-		{
-			.start = MX23_LCDIF_BASE_ADDR,
-			.end = MX23_LCDIF_BASE_ADDR + SZ_8K - 1,
-			.flags = IORESOURCE_MEM,
-		},
-	};
-
-	return mxs_add_platform_device_dmamask("imx23-fb", -1,
-			res, ARRAY_SIZE(res), pdata, sizeof(*pdata), DMA_BIT_MASK(32));
-}
-#endif /* ifdef CONFIG_SOC_IMX23 */
-
-#ifdef CONFIG_SOC_IMX28
-struct platform_device *__init mx28_add_mxsfb(
-		const struct mxsfb_platform_data *pdata)
-{
-	struct resource res[] = {
-		{
-			.start = MX28_LCDIF_BASE_ADDR,
-			.end = MX28_LCDIF_BASE_ADDR + SZ_8K - 1,
-			.flags = IORESOURCE_MEM,
-		},
-	};
-
-	return mxs_add_platform_device_dmamask("imx28-fb", -1,
-			res, ARRAY_SIZE(res), pdata, sizeof(*pdata), DMA_BIT_MASK(32));
-}
-#endif /* ifdef CONFIG_SOC_IMX28 */
diff --git a/arch/arm/mach-mxs/devices/platform-rtc-stmp3xxx.c b/arch/arm/mach-mxs/devices/platform-rtc-stmp3xxx.c
deleted file mode 100644
index 639eaee..0000000
--- a/arch/arm/mach-mxs/devices/platform-rtc-stmp3xxx.c
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2011 Pengutronix, 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 version 2 as published by the
- * Free Software Foundation.
- */
-#include <asm/sizes.h>
-#include <mach/mx23.h>
-#include <mach/mx28.h>
-#include <mach/devices-common.h>
-
-#ifdef CONFIG_SOC_IMX23
-struct platform_device *__init mx23_add_rtc_stmp3xxx(void)
-{
-	struct resource res[] = {
-		{
-			.start = MX23_RTC_BASE_ADDR,
-			.end = MX23_RTC_BASE_ADDR + SZ_8K - 1,
-			.flags = IORESOURCE_MEM,
-		}, {
-			.start = MX23_INT_RTC_ALARM,
-			.end = MX23_INT_RTC_ALARM,
-			.flags = IORESOURCE_IRQ,
-		},
-	};
-
-	return mxs_add_platform_device("stmp3xxx-rtc", 0, res, ARRAY_SIZE(res),
-					NULL, 0);
-}
-#endif /* CONFIG_SOC_IMX23 */
-
-#ifdef CONFIG_SOC_IMX28
-struct platform_device *__init mx28_add_rtc_stmp3xxx(void)
-{
-	struct resource res[] = {
-		{
-			.start = MX28_RTC_BASE_ADDR,
-			.end = MX28_RTC_BASE_ADDR + SZ_8K - 1,
-			.flags = IORESOURCE_MEM,
-		}, {
-			.start = MX28_INT_RTC_ALARM,
-			.end = MX28_INT_RTC_ALARM,
-			.flags = IORESOURCE_IRQ,
-		},
-	};
-
-	return mxs_add_platform_device("stmp3xxx-rtc", 0, res, ARRAY_SIZE(res),
-					NULL, 0);
-}
-#endif /* CONFIG_SOC_IMX28 */
diff --git a/arch/arm/mach-mxs/icoll.c b/arch/arm/mach-mxs/icoll.c
index 23ca9d0..8fb23af 100644
--- a/arch/arm/mach-mxs/icoll.c
+++ b/arch/arm/mach-mxs/icoll.c
@@ -19,20 +19,27 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/irq.h>
+#include <linux/irqdomain.h>
 #include <linux/io.h>
-
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <asm/exception.h>
 #include <mach/mxs.h>
 #include <mach/common.h>
 
 #define HW_ICOLL_VECTOR				0x0000
 #define HW_ICOLL_LEVELACK			0x0010
 #define HW_ICOLL_CTRL				0x0020
+#define HW_ICOLL_STAT_OFFSET			0x0070
 #define HW_ICOLL_INTERRUPTn_SET(n)		(0x0124 + (n) * 0x10)
 #define HW_ICOLL_INTERRUPTn_CLR(n)		(0x0128 + (n) * 0x10)
 #define BM_ICOLL_INTERRUPTn_ENABLE		0x00000004
 #define BV_ICOLL_LEVELACK_IRQLEVELACK__LEVEL0	0x1
 
+#define ICOLL_NUM_IRQS		128
+
 static void __iomem *icoll_base = MXS_IO_ADDRESS(MXS_ICOLL_BASE_ADDR);
+static struct irq_domain *icoll_domain;
 
 static void icoll_ack_irq(struct irq_data *d)
 {
@@ -48,13 +55,13 @@ static void icoll_ack_irq(struct irq_data *d)
 static void icoll_mask_irq(struct irq_data *d)
 {
 	__raw_writel(BM_ICOLL_INTERRUPTn_ENABLE,
-			icoll_base + HW_ICOLL_INTERRUPTn_CLR(d->irq));
+			icoll_base + HW_ICOLL_INTERRUPTn_CLR(d->hwirq));
 }
 
 static void icoll_unmask_irq(struct irq_data *d)
 {
 	__raw_writel(BM_ICOLL_INTERRUPTn_ENABLE,
-			icoll_base + HW_ICOLL_INTERRUPTn_SET(d->irq));
+			icoll_base + HW_ICOLL_INTERRUPTn_SET(d->hwirq));
 }
 
 static struct irq_chip mxs_icoll_chip = {
@@ -63,18 +70,56 @@ static struct irq_chip mxs_icoll_chip = {
 	.irq_unmask = icoll_unmask_irq,
 };
 
-void __init icoll_init_irq(void)
+asmlinkage void __exception_irq_entry icoll_handle_irq(struct pt_regs *regs)
 {
-	int i;
+	u32 irqnr;
+
+	do {
+		irqnr = __raw_readl(icoll_base + HW_ICOLL_STAT_OFFSET);
+		if (irqnr != 0x7f) {
+			__raw_writel(irqnr, icoll_base + HW_ICOLL_VECTOR);
+			irqnr = irq_find_mapping(icoll_domain, irqnr);
+			handle_IRQ(irqnr, regs);
+			continue;
+		}
+		break;
+	} while (1);
+}
+
+static int icoll_irq_domain_map(struct irq_domain *d, unsigned int virq,
+				irq_hw_number_t hw)
+{
+	irq_set_chip_and_handler(virq, &mxs_icoll_chip, handle_level_irq);
+	set_irq_flags(virq, IRQF_VALID);
+
+	return 0;
+}
 
+static struct irq_domain_ops icoll_irq_domain_ops = {
+	.map = icoll_irq_domain_map,
+	.xlate = irq_domain_xlate_onecell,
+};
+
+void __init icoll_of_init(struct device_node *np,
+			  struct device_node *interrupt_parent)
+{
 	/*
 	 * Interrupt Collector reset, which initializes the priority
 	 * for each irq to level 0.
 	 */
 	mxs_reset_block(icoll_base + HW_ICOLL_CTRL);
 
-	for (i = 0; i < MXS_INTERNAL_IRQS; i++) {
-		irq_set_chip_and_handler(i, &mxs_icoll_chip, handle_level_irq);
-		set_irq_flags(i, IRQF_VALID);
-	}
+	icoll_domain = irq_domain_add_linear(np, ICOLL_NUM_IRQS,
+					     &icoll_irq_domain_ops, NULL);
+	WARN_ON(!icoll_domain);
+}
+
+static const struct of_device_id icoll_of_match[] __initconst = {
+	{.compatible = "fsl,icoll", .data = icoll_of_init},
+	{ /* sentinel */ }
+};
+
+void __init icoll_init_irq(void)
+{
+	of_irq_init(icoll_of_match);
 }
diff --git a/arch/arm/mach-mxs/include/mach/common.h b/arch/arm/mach-mxs/include/mach/common.h
index de6c7ba..be5a9c9 100644
--- a/arch/arm/mach-mxs/include/mach/common.h
+++ b/arch/arm/mach-mxs/include/mach/common.h
@@ -13,25 +13,17 @@
 
 extern const u32 *mxs_get_ocotp(void);
 extern int mxs_reset_block(void __iomem *);
-extern void mxs_timer_init(int);
+extern void mxs_timer_init(void);
 extern void mxs_restart(char, const char *);
 extern int mxs_saif_clkmux_select(unsigned int clkmux);
 
-extern void mx23_soc_init(void);
 extern int mx23_clocks_init(void);
 extern void mx23_map_io(void);
-extern void mx23_init_irq(void);
 
-extern void mx28_soc_init(void);
 extern int mx28_clocks_init(void);
 extern void mx28_map_io(void);
-extern void mx28_init_irq(void);
 
 extern void icoll_init_irq(void);
-
-extern struct platform_device *mxs_add_dma(const char *devid,
-						resource_size_t base);
-extern struct platform_device *mxs_add_gpio(char *name, int id,
-					    resource_size_t iobase, int irq);
+extern void icoll_handle_irq(struct pt_regs *);
 
 #endif /* __MACH_MXS_COMMON_H__ */
diff --git a/arch/arm/mach-mxs/include/mach/devices-common.h b/arch/arm/mach-mxs/include/mach/devices-common.h
deleted file mode 100644
index e8b1d95..0000000
--- a/arch/arm/mach-mxs/include/mach/devices-common.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (C) 2009-2010 Pengutronix
- * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License version 2 as published by the
- * Free Software Foundation.
- */
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/init.h>
-#include <linux/amba/bus.h>
-
-extern struct device mxs_apbh_bus;
-
-struct platform_device *mxs_add_platform_device_dmamask(
-		const char *name, int id,
-		const struct resource *res, unsigned int num_resources,
-		const void *data, size_t size_data, u64 dmamask);
-
-static inline struct platform_device *mxs_add_platform_device(
-		const char *name, int id,
-		const struct resource *res, unsigned int num_resources,
-		const void *data, size_t size_data)
-{
-	return mxs_add_platform_device_dmamask(
-			name, id, res, num_resources, data, size_data, 0);
-}
-
-/* auart */
-struct mxs_auart_data {
-	int id;
-	resource_size_t iobase;
-	resource_size_t iosize;
-	resource_size_t irq;
-};
-struct platform_device *__init mxs_add_auart(
-		const struct mxs_auart_data *data);
-
-/* fec */
-#include <linux/fec.h>
-struct mxs_fec_data {
-	int id;
-	resource_size_t iobase;
-	resource_size_t iosize;
-	resource_size_t irq;
-};
-struct platform_device *__init mxs_add_fec(
-		const struct mxs_fec_data *data,
-		const struct fec_platform_data *pdata);
-
-/* flexcan */
-#include <linux/can/platform/flexcan.h>
-struct mxs_flexcan_data {
-	int id;
-	resource_size_t iobase;
-	resource_size_t iosize;
-	resource_size_t irq;
-};
-struct platform_device *__init mxs_add_flexcan(
-		const struct mxs_flexcan_data *data,
-		const struct flexcan_platform_data *pdata);
-
-/* gpmi-nand */
-#include <linux/mtd/gpmi-nand.h>
-struct mxs_gpmi_nand_data {
-	const char *devid;
-	const struct resource res[GPMI_NAND_RES_SIZE];
-};
-struct platform_device *__init
-mxs_add_gpmi_nand(const struct gpmi_nand_platform_data *pdata,
-		const struct mxs_gpmi_nand_data *data);
-
-/* i2c */
-struct mxs_mxs_i2c_data {
-	int id;
-	resource_size_t iobase;
-	resource_size_t errirq;
-	resource_size_t dmairq;
-};
-struct platform_device * __init mxs_add_mxs_i2c(
-		const struct mxs_mxs_i2c_data *data);
-
-/* mmc */
-#include <linux/mmc/mxs-mmc.h>
-struct mxs_mxs_mmc_data {
-	const char *devid;
-	int id;
-	resource_size_t iobase;
-	resource_size_t dma;
-	resource_size_t irq_err;
-	resource_size_t irq_dma;
-};
-struct platform_device *__init mxs_add_mxs_mmc(
-		const struct mxs_mxs_mmc_data *data,
-		const struct mxs_mmc_platform_data *pdata);
-
-/* pwm */
-struct platform_device *__init mxs_add_mxs_pwm(
-		resource_size_t iobase, int id);
-
-/* saif */
-#include <sound/saif.h>
-struct mxs_saif_data {
-	int id;
-	resource_size_t iobase;
-	resource_size_t irq;
-	resource_size_t dma;
-	resource_size_t dmairq;
-};
-
-struct platform_device *__init mxs_add_saif(
-		const struct mxs_saif_data *data,
-		const struct mxs_saif_platform_data *pdata);
diff --git a/arch/arm/mach-mxs/include/mach/entry-macro.S b/arch/arm/mach-mxs/include/mach/entry-macro.S
deleted file mode 100644
index 0c14259..0000000
--- a/arch/arm/mach-mxs/include/mach/entry-macro.S
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Low-level IRQ helper macros for Freescale MXS-based
- *
- * Copyright (C) 2009-2010 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 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 <mach/mxs.h>
-
-#define MXS_ICOLL_VBASE		MXS_IO_ADDRESS(MXS_ICOLL_BASE_ADDR)
-#define HW_ICOLL_STAT_OFFSET	0x70
-
-	.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
-	ldr	\irqnr, [\base, #HW_ICOLL_STAT_OFFSET]
-	cmp	\irqnr, #0x7F
-	strne	\irqnr, [\base]
-	moveqs	\irqnr, #0
-	.endm
-
-	.macro  get_irqnr_preamble, base, tmp
-	ldr	\base, =MXS_ICOLL_VBASE
-	.endm
diff --git a/arch/arm/mach-mxs/include/mach/gpio.h b/arch/arm/mach-mxs/include/mach/gpio.h
deleted file mode 100644
index 40a8c17..0000000
--- a/arch/arm/mach-mxs/include/mach/gpio.h
+++ /dev/null
@@ -1 +0,0 @@
-/* empty */
diff --git a/arch/arm/mach-mxs/include/mach/iomux-mx23.h b/arch/arm/mach-mxs/include/mach/iomux-mx23.h
deleted file mode 100644
index b0190a4..0000000
--- a/arch/arm/mach-mxs/include/mach/iomux-mx23.h
+++ /dev/null
@@ -1,355 +0,0 @@
-/*
- * Copyright (C) 2009-2010 Amit Kucheria <amit.kucheria@canonical.com>
- * Copyright (C) 2010 Freescale Semiconductor, Inc.
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#ifndef __MACH_IOMUX_MX23_H__
-#define __MACH_IOMUX_MX23_H__
-
-#include <mach/iomux.h>
-
-/*
- * The naming convention for the pad modes is MX23_PAD_<padname>__<padmode>
- * If <padname> or <padmode> refers to a GPIO, it is named GPIO_<unit>_<num>
- * See also iomux.h
- *
- *									BANK	PIN	MUX
- */
-/* MUXSEL_0 */
-#define MX23_PAD_GPMI_D00__GPMI_D00		MXS_IOMUX_PAD_NAKED(0,  0, PAD_MUXSEL_0)
-#define MX23_PAD_GPMI_D01__GPMI_D01		MXS_IOMUX_PAD_NAKED(0,  1, PAD_MUXSEL_0)
-#define MX23_PAD_GPMI_D02__GPMI_D02		MXS_IOMUX_PAD_NAKED(0,  2, PAD_MUXSEL_0)
-#define MX23_PAD_GPMI_D03__GPMI_D03		MXS_IOMUX_PAD_NAKED(0,  3, PAD_MUXSEL_0)
-#define MX23_PAD_GPMI_D04__GPMI_D04		MXS_IOMUX_PAD_NAKED(0,  4, PAD_MUXSEL_0)
-#define MX23_PAD_GPMI_D05__GPMI_D05		MXS_IOMUX_PAD_NAKED(0,  5, PAD_MUXSEL_0)
-#define MX23_PAD_GPMI_D06__GPMI_D06		MXS_IOMUX_PAD_NAKED(0,  6, PAD_MUXSEL_0)
-#define MX23_PAD_GPMI_D07__GPMI_D07		MXS_IOMUX_PAD_NAKED(0,  7, PAD_MUXSEL_0)
-#define MX23_PAD_GPMI_D08__GPMI_D08		MXS_IOMUX_PAD_NAKED(0,  8, PAD_MUXSEL_0)
-#define MX23_PAD_GPMI_D09__GPMI_D09		MXS_IOMUX_PAD_NAKED(0,  9, PAD_MUXSEL_0)
-#define MX23_PAD_GPMI_D10__GPMI_D10		MXS_IOMUX_PAD_NAKED(0, 10, PAD_MUXSEL_0)
-#define MX23_PAD_GPMI_D11__GPMI_D11		MXS_IOMUX_PAD_NAKED(0, 11, PAD_MUXSEL_0)
-#define MX23_PAD_GPMI_D12__GPMI_D12		MXS_IOMUX_PAD_NAKED(0, 12, PAD_MUXSEL_0)
-#define MX23_PAD_GPMI_D13__GPMI_D13		MXS_IOMUX_PAD_NAKED(0, 13, PAD_MUXSEL_0)
-#define MX23_PAD_GPMI_D14__GPMI_D14		MXS_IOMUX_PAD_NAKED(0, 14, PAD_MUXSEL_0)
-#define MX23_PAD_GPMI_D15__GPMI_D15		MXS_IOMUX_PAD_NAKED(0, 15, PAD_MUXSEL_0)
-#define MX23_PAD_GPMI_CLE__GPMI_CLE		MXS_IOMUX_PAD_NAKED(0, 16, PAD_MUXSEL_0)
-#define MX23_PAD_GPMI_ALE__GPMI_ALE		MXS_IOMUX_PAD_NAKED(0, 17, PAD_MUXSEL_0)
-#define MX23_PAD_GPMI_CE2N__GPMI_CE2N		MXS_IOMUX_PAD_NAKED(0, 18, PAD_MUXSEL_0)
-#define MX23_PAD_GPMI_RDY0__GPMI_RDY0		MXS_IOMUX_PAD_NAKED(0, 19, PAD_MUXSEL_0)
-#define MX23_PAD_GPMI_RDY1__GPMI_RDY1		MXS_IOMUX_PAD_NAKED(0, 20, PAD_MUXSEL_0)
-#define MX23_PAD_GPMI_RDY2__GPMI_RDY2		MXS_IOMUX_PAD_NAKED(0, 21, PAD_MUXSEL_0)
-#define MX23_PAD_GPMI_RDY3__GPMI_RDY3		MXS_IOMUX_PAD_NAKED(0, 22, PAD_MUXSEL_0)
-#define MX23_PAD_GPMI_WPN__GPMI_WPN		MXS_IOMUX_PAD_NAKED(0, 23, PAD_MUXSEL_0)
-#define MX23_PAD_GPMI_WRN__GPMI_WRN		MXS_IOMUX_PAD_NAKED(0, 24, PAD_MUXSEL_0)
-#define MX23_PAD_GPMI_RDN__GPMI_RDN		MXS_IOMUX_PAD_NAKED(0, 25, PAD_MUXSEL_0)
-#define MX23_PAD_AUART1_CTS__AUART1_CTS		MXS_IOMUX_PAD_NAKED(0, 26, PAD_MUXSEL_0)
-#define MX23_PAD_AUART1_RTS__AUART1_RTS		MXS_IOMUX_PAD_NAKED(0, 27, PAD_MUXSEL_0)
-#define MX23_PAD_AUART1_RX__AUART1_RX		MXS_IOMUX_PAD_NAKED(0, 28, PAD_MUXSEL_0)
-#define MX23_PAD_AUART1_TX__AUART1_TX		MXS_IOMUX_PAD_NAKED(0, 29, PAD_MUXSEL_0)
-#define MX23_PAD_I2C_SCL__I2C_SCL		MXS_IOMUX_PAD_NAKED(0, 30, PAD_MUXSEL_0)
-#define MX23_PAD_I2C_SDA__I2C_SDA		MXS_IOMUX_PAD_NAKED(0, 31, PAD_MUXSEL_0)
-
-#define MX23_PAD_LCD_D00__LCD_D00		MXS_IOMUX_PAD_NAKED(1,  0, PAD_MUXSEL_0)
-#define MX23_PAD_LCD_D01__LCD_D01		MXS_IOMUX_PAD_NAKED(1,  1, PAD_MUXSEL_0)
-#define MX23_PAD_LCD_D02__LCD_D02		MXS_IOMUX_PAD_NAKED(1,  2, PAD_MUXSEL_0)
-#define MX23_PAD_LCD_D03__LCD_D03		MXS_IOMUX_PAD_NAKED(1,  3, PAD_MUXSEL_0)
-#define MX23_PAD_LCD_D04__LCD_D04		MXS_IOMUX_PAD_NAKED(1,  4, PAD_MUXSEL_0)
-#define MX23_PAD_LCD_D05__LCD_D05		MXS_IOMUX_PAD_NAKED(1,  5, PAD_MUXSEL_0)
-#define MX23_PAD_LCD_D06__LCD_D06		MXS_IOMUX_PAD_NAKED(1,  6, PAD_MUXSEL_0)
-#define MX23_PAD_LCD_D07__LCD_D07		MXS_IOMUX_PAD_NAKED(1,  7, PAD_MUXSEL_0)
-#define MX23_PAD_LCD_D08__LCD_D08		MXS_IOMUX_PAD_NAKED(1,  8, PAD_MUXSEL_0)
-#define MX23_PAD_LCD_D09__LCD_D09		MXS_IOMUX_PAD_NAKED(1,  9, PAD_MUXSEL_0)
-#define MX23_PAD_LCD_D10__LCD_D10		MXS_IOMUX_PAD_NAKED(1, 10, PAD_MUXSEL_0)
-#define MX23_PAD_LCD_D11__LCD_D11		MXS_IOMUX_PAD_NAKED(1, 11, PAD_MUXSEL_0)
-#define MX23_PAD_LCD_D12__LCD_D12		MXS_IOMUX_PAD_NAKED(1, 12, PAD_MUXSEL_0)
-#define MX23_PAD_LCD_D13__LCD_D13		MXS_IOMUX_PAD_NAKED(1, 13, PAD_MUXSEL_0)
-#define MX23_PAD_LCD_D14__LCD_D14		MXS_IOMUX_PAD_NAKED(1, 14, PAD_MUXSEL_0)
-#define MX23_PAD_LCD_D15__LCD_D15		MXS_IOMUX_PAD_NAKED(1, 15, PAD_MUXSEL_0)
-#define MX23_PAD_LCD_D16__LCD_D16		MXS_IOMUX_PAD_NAKED(1, 16, PAD_MUXSEL_0)
-#define MX23_PAD_LCD_D17__LCD_D17		MXS_IOMUX_PAD_NAKED(1, 17, PAD_MUXSEL_0)
-#define MX23_PAD_LCD_RESET__LCD_RESET		MXS_IOMUX_PAD_NAKED(1, 18, PAD_MUXSEL_0)
-#define MX23_PAD_LCD_RS__LCD_RS			MXS_IOMUX_PAD_NAKED(1, 19, PAD_MUXSEL_0)
-#define MX23_PAD_LCD_WR__LCD_WR			MXS_IOMUX_PAD_NAKED(1, 20, PAD_MUXSEL_0)
-#define MX23_PAD_LCD_CS__LCD_CS			MXS_IOMUX_PAD_NAKED(1, 21, PAD_MUXSEL_0)
-#define MX23_PAD_LCD_DOTCK__LCD_DOTCK		MXS_IOMUX_PAD_NAKED(1, 22, PAD_MUXSEL_0)
-#define MX23_PAD_LCD_ENABLE__LCD_ENABLE		MXS_IOMUX_PAD_NAKED(1, 23, PAD_MUXSEL_0)
-#define MX23_PAD_LCD_HSYNC__LCD_HSYNC		MXS_IOMUX_PAD_NAKED(1, 24, PAD_MUXSEL_0)
-#define MX23_PAD_LCD_VSYNC__LCD_VSYNC		MXS_IOMUX_PAD_NAKED(1, 25, PAD_MUXSEL_0)
-#define MX23_PAD_PWM0__PWM0			MXS_IOMUX_PAD_NAKED(1, 26, PAD_MUXSEL_0)
-#define MX23_PAD_PWM1__PWM1			MXS_IOMUX_PAD_NAKED(1, 27, PAD_MUXSEL_0)
-#define MX23_PAD_PWM2__PWM2			MXS_IOMUX_PAD_NAKED(1, 28, PAD_MUXSEL_0)
-#define MX23_PAD_PWM3__PWM3			MXS_IOMUX_PAD_NAKED(1, 29, PAD_MUXSEL_0)
-#define MX23_PAD_PWM4__PWM4			MXS_IOMUX_PAD_NAKED(1, 30, PAD_MUXSEL_0)
-
-#define MX23_PAD_SSP1_CMD__SSP1_CMD		MXS_IOMUX_PAD_NAKED(2,  0, PAD_MUXSEL_0)
-#define MX23_PAD_SSP1_DETECT__SSP1_DETECT	MXS_IOMUX_PAD_NAKED(2,  1, PAD_MUXSEL_0)
-#define MX23_PAD_SSP1_DATA0__SSP1_DATA0		MXS_IOMUX_PAD_NAKED(2,  2, PAD_MUXSEL_0)
-#define MX23_PAD_SSP1_DATA1__SSP1_DATA1		MXS_IOMUX_PAD_NAKED(2,  3, PAD_MUXSEL_0)
-#define MX23_PAD_SSP1_DATA2__SSP1_DATA2		MXS_IOMUX_PAD_NAKED(2,  4, PAD_MUXSEL_0)
-#define MX23_PAD_SSP1_DATA3__SSP1_DATA3		MXS_IOMUX_PAD_NAKED(2,  5, PAD_MUXSEL_0)
-#define MX23_PAD_SSP1_SCK__SSP1_SCK		MXS_IOMUX_PAD_NAKED(2,  6, PAD_MUXSEL_0)
-#define MX23_PAD_ROTARYA__ROTARYA		MXS_IOMUX_PAD_NAKED(2,  7, PAD_MUXSEL_0)
-#define MX23_PAD_ROTARYB__ROTARYB		MXS_IOMUX_PAD_NAKED(2,  8, PAD_MUXSEL_0)
-#define MX23_PAD_EMI_A00__EMI_A00		MXS_IOMUX_PAD_NAKED(2,  9, PAD_MUXSEL_0)
-#define MX23_PAD_EMI_A01__EMI_A01		MXS_IOMUX_PAD_NAKED(2, 10, PAD_MUXSEL_0)
-#define MX23_PAD_EMI_A02__EMI_A02		MXS_IOMUX_PAD_NAKED(2, 11, PAD_MUXSEL_0)
-#define MX23_PAD_EMI_A03__EMI_A03		MXS_IOMUX_PAD_NAKED(2, 12, PAD_MUXSEL_0)
-#define MX23_PAD_EMI_A04__EMI_A04		MXS_IOMUX_PAD_NAKED(2, 13, PAD_MUXSEL_0)
-#define MX23_PAD_EMI_A05__EMI_A05		MXS_IOMUX_PAD_NAKED(2, 14, PAD_MUXSEL_0)
-#define MX23_PAD_EMI_A06__EMI_A06		MXS_IOMUX_PAD_NAKED(2, 15, PAD_MUXSEL_0)
-#define MX23_PAD_EMI_A07__EMI_A07		MXS_IOMUX_PAD_NAKED(2, 16, PAD_MUXSEL_0)
-#define MX23_PAD_EMI_A08__EMI_A08		MXS_IOMUX_PAD_NAKED(2, 17, PAD_MUXSEL_0)
-#define MX23_PAD_EMI_A09__EMI_A09		MXS_IOMUX_PAD_NAKED(2, 18, PAD_MUXSEL_0)
-#define MX23_PAD_EMI_A10__EMI_A10		MXS_IOMUX_PAD_NAKED(2, 19, PAD_MUXSEL_0)
-#define MX23_PAD_EMI_A11__EMI_A11		MXS_IOMUX_PAD_NAKED(2, 20, PAD_MUXSEL_0)
-#define MX23_PAD_EMI_A12__EMI_A12		MXS_IOMUX_PAD_NAKED(2, 21, PAD_MUXSEL_0)
-#define MX23_PAD_EMI_BA0__EMI_BA0		MXS_IOMUX_PAD_NAKED(2, 22, PAD_MUXSEL_0)
-#define MX23_PAD_EMI_BA1__EMI_BA1		MXS_IOMUX_PAD_NAKED(2, 23, PAD_MUXSEL_0)
-#define MX23_PAD_EMI_CASN__EMI_CASN		MXS_IOMUX_PAD_NAKED(2, 24, PAD_MUXSEL_0)
-#define MX23_PAD_EMI_CE0N__EMI_CE0N		MXS_IOMUX_PAD_NAKED(2, 25, PAD_MUXSEL_0)
-#define MX23_PAD_EMI_CE1N__EMI_CE1N		MXS_IOMUX_PAD_NAKED(2, 26, PAD_MUXSEL_0)
-#define MX23_PAD_GPMI_CE1N__GPMI_CE1N		MXS_IOMUX_PAD_NAKED(2, 27, PAD_MUXSEL_0)
-#define MX23_PAD_GPMI_CE0N__GPMI_CE0N		MXS_IOMUX_PAD_NAKED(2, 28, PAD_MUXSEL_0)
-#define MX23_PAD_EMI_CKE__EMI_CKE		MXS_IOMUX_PAD_NAKED(2, 29, PAD_MUXSEL_0)
-#define MX23_PAD_EMI_RASN__EMI_RASN		MXS_IOMUX_PAD_NAKED(2, 30, PAD_MUXSEL_0)
-#define MX23_PAD_EMI_WEN__EMI_WEN		MXS_IOMUX_PAD_NAKED(2, 31, PAD_MUXSEL_0)
-
-#define MX23_PAD_EMI_D00__EMI_D00		MXS_IOMUX_PAD_NAKED(3,  0, PAD_MUXSEL_0)
-#define MX23_PAD_EMI_D01__EMI_D01		MXS_IOMUX_PAD_NAKED(3,  1, PAD_MUXSEL_0)
-#define MX23_PAD_EMI_D02__EMI_D02		MXS_IOMUX_PAD_NAKED(3,  2, PAD_MUXSEL_0)
-#define MX23_PAD_EMI_D03__EMI_D03		MXS_IOMUX_PAD_NAKED(3,  3, PAD_MUXSEL_0)
-#define MX23_PAD_EMI_D04__EMI_D04		MXS_IOMUX_PAD_NAKED(3,  4, PAD_MUXSEL_0)
-#define MX23_PAD_EMI_D05__EMI_D05		MXS_IOMUX_PAD_NAKED(3,  5, PAD_MUXSEL_0)
-#define MX23_PAD_EMI_D06__EMI_D06		MXS_IOMUX_PAD_NAKED(3,  6, PAD_MUXSEL_0)
-#define MX23_PAD_EMI_D07__EMI_D07		MXS_IOMUX_PAD_NAKED(3,  7, PAD_MUXSEL_0)
-#define MX23_PAD_EMI_D08__EMI_D08		MXS_IOMUX_PAD_NAKED(3,  8, PAD_MUXSEL_0)
-#define MX23_PAD_EMI_D09__EMI_D09		MXS_IOMUX_PAD_NAKED(3,  9, PAD_MUXSEL_0)
-#define MX23_PAD_EMI_D10__EMI_D10		MXS_IOMUX_PAD_NAKED(3, 10, PAD_MUXSEL_0)
-#define MX23_PAD_EMI_D11__EMI_D11		MXS_IOMUX_PAD_NAKED(3, 11, PAD_MUXSEL_0)
-#define MX23_PAD_EMI_D12__EMI_D12		MXS_IOMUX_PAD_NAKED(3, 12, PAD_MUXSEL_0)
-#define MX23_PAD_EMI_D13__EMI_D13		MXS_IOMUX_PAD_NAKED(3, 13, PAD_MUXSEL_0)
-#define MX23_PAD_EMI_D14__EMI_D14		MXS_IOMUX_PAD_NAKED(3, 14, PAD_MUXSEL_0)
-#define MX23_PAD_EMI_D15__EMI_D15		MXS_IOMUX_PAD_NAKED(3, 15, PAD_MUXSEL_0)
-#define MX23_PAD_EMI_DQM0__EMI_DQM0		MXS_IOMUX_PAD_NAKED(3, 16, PAD_MUXSEL_0)
-#define MX23_PAD_EMI_DQM1__EMI_DQM1		MXS_IOMUX_PAD_NAKED(3, 17, PAD_MUXSEL_0)
-#define MX23_PAD_EMI_DQS0__EMI_DQS0		MXS_IOMUX_PAD_NAKED(3, 18, PAD_MUXSEL_0)
-#define MX23_PAD_EMI_DQS1__EMI_DQS1		MXS_IOMUX_PAD_NAKED(3, 19, PAD_MUXSEL_0)
-#define MX23_PAD_EMI_CLK__EMI_CLK		MXS_IOMUX_PAD_NAKED(3, 20, PAD_MUXSEL_0)
-#define MX23_PAD_EMI_CLKN__EMI_CLKN		MXS_IOMUX_PAD_NAKED(3, 21, PAD_MUXSEL_0)
-
-/* MUXSEL_1 */
-#define MX23_PAD_GPMI_D00__LCD_D8		MXS_IOMUX_PAD_NAKED(0,  0, PAD_MUXSEL_1)
-#define MX23_PAD_GPMI_D01__LCD_D9		MXS_IOMUX_PAD_NAKED(0,  1, PAD_MUXSEL_1)
-#define MX23_PAD_GPMI_D02__LCD_D10		MXS_IOMUX_PAD_NAKED(0,  2, PAD_MUXSEL_1)
-#define MX23_PAD_GPMI_D03__LCD_D11		MXS_IOMUX_PAD_NAKED(0,  3, PAD_MUXSEL_1)
-#define MX23_PAD_GPMI_D04__LCD_D12		MXS_IOMUX_PAD_NAKED(0,  4, PAD_MUXSEL_1)
-#define MX23_PAD_GPMI_D05__LCD_D13		MXS_IOMUX_PAD_NAKED(0,  5, PAD_MUXSEL_1)
-#define MX23_PAD_GPMI_D06__LCD_D14		MXS_IOMUX_PAD_NAKED(0,  6, PAD_MUXSEL_1)
-#define MX23_PAD_GPMI_D07__LCD_D15		MXS_IOMUX_PAD_NAKED(0,  7, PAD_MUXSEL_1)
-#define MX23_PAD_GPMI_D08__LCD_D18		MXS_IOMUX_PAD_NAKED(0,  8, PAD_MUXSEL_1)
-#define MX23_PAD_GPMI_D09__LCD_D19		MXS_IOMUX_PAD_NAKED(0,  9, PAD_MUXSEL_1)
-#define MX23_PAD_GPMI_D10__LCD_D20		MXS_IOMUX_PAD_NAKED(0, 10, PAD_MUXSEL_1)
-#define MX23_PAD_GPMI_D11__LCD_D21		MXS_IOMUX_PAD_NAKED(0, 11, PAD_MUXSEL_1)
-#define MX23_PAD_GPMI_D12__LCD_D22		MXS_IOMUX_PAD_NAKED(0, 12, PAD_MUXSEL_1)
-#define MX23_PAD_GPMI_D13__LCD_D23		MXS_IOMUX_PAD_NAKED(0, 13, PAD_MUXSEL_1)
-#define MX23_PAD_GPMI_D14__AUART2_RX		MXS_IOMUX_PAD_NAKED(0, 14, PAD_MUXSEL_1)
-#define MX23_PAD_GPMI_D15__AUART2_TX		MXS_IOMUX_PAD_NAKED(0, 15, PAD_MUXSEL_1)
-#define MX23_PAD_GPMI_CLE__LCD_D16		MXS_IOMUX_PAD_NAKED(0, 16, PAD_MUXSEL_1)
-#define MX23_PAD_GPMI_ALE__LCD_D17		MXS_IOMUX_PAD_NAKED(0, 17, PAD_MUXSEL_1)
-#define MX23_PAD_GPMI_CE2N__ATA_A2		MXS_IOMUX_PAD_NAKED(0, 18, PAD_MUXSEL_1)
-#define MX23_PAD_AUART1_RTS__IR_CLK		MXS_IOMUX_PAD_NAKED(0, 27, PAD_MUXSEL_1)
-#define MX23_PAD_AUART1_RX__IR_RX		MXS_IOMUX_PAD_NAKED(0, 28, PAD_MUXSEL_1)
-#define MX23_PAD_AUART1_TX__IR_TX		MXS_IOMUX_PAD_NAKED(0, 29, PAD_MUXSEL_1)
-#define MX23_PAD_I2C_SCL__GPMI_RDY2		MXS_IOMUX_PAD_NAKED(0, 30, PAD_MUXSEL_1)
-#define MX23_PAD_I2C_SDA__GPMI_CE2N		MXS_IOMUX_PAD_NAKED(0, 31, PAD_MUXSEL_1)
-
-#define MX23_PAD_LCD_D00__ETM_DA8		MXS_IOMUX_PAD_NAKED(1,  0, PAD_MUXSEL_1)
-#define MX23_PAD_LCD_D01__ETM_DA9		MXS_IOMUX_PAD_NAKED(1,  1, PAD_MUXSEL_1)
-#define MX23_PAD_LCD_D02__ETM_DA10		MXS_IOMUX_PAD_NAKED(1,  2, PAD_MUXSEL_1)
-#define MX23_PAD_LCD_D03__ETM_DA11		MXS_IOMUX_PAD_NAKED(1,  3, PAD_MUXSEL_1)
-#define MX23_PAD_LCD_D04__ETM_DA12		MXS_IOMUX_PAD_NAKED(1,  4, PAD_MUXSEL_1)
-#define MX23_PAD_LCD_D05__ETM_DA13		MXS_IOMUX_PAD_NAKED(1,  5, PAD_MUXSEL_1)
-#define MX23_PAD_LCD_D06__ETM_DA14		MXS_IOMUX_PAD_NAKED(1,  6, PAD_MUXSEL_1)
-#define MX23_PAD_LCD_D07__ETM_DA15		MXS_IOMUX_PAD_NAKED(1,  7, PAD_MUXSEL_1)
-#define MX23_PAD_LCD_D08__ETM_DA0		MXS_IOMUX_PAD_NAKED(1,  8, PAD_MUXSEL_1)
-#define MX23_PAD_LCD_D09__ETM_DA1		MXS_IOMUX_PAD_NAKED(1,  9, PAD_MUXSEL_1)
-#define MX23_PAD_LCD_D10__ETM_DA2		MXS_IOMUX_PAD_NAKED(1, 10, PAD_MUXSEL_1)
-#define MX23_PAD_LCD_D11__ETM_DA3		MXS_IOMUX_PAD_NAKED(1, 11, PAD_MUXSEL_1)
-#define MX23_PAD_LCD_D12__ETM_DA4		MXS_IOMUX_PAD_NAKED(1, 12, PAD_MUXSEL_1)
-#define MX23_PAD_LCD_D13__ETM_DA5		MXS_IOMUX_PAD_NAKED(1, 13, PAD_MUXSEL_1)
-#define MX23_PAD_LCD_D14__ETM_DA6		MXS_IOMUX_PAD_NAKED(1, 14, PAD_MUXSEL_1)
-#define MX23_PAD_LCD_D15__ETM_DA7		MXS_IOMUX_PAD_NAKED(1, 15, PAD_MUXSEL_1)
-#define MX23_PAD_LCD_RESET__ETM_TCTL		MXS_IOMUX_PAD_NAKED(1, 18, PAD_MUXSEL_1)
-#define MX23_PAD_LCD_RS__ETM_TCLK		MXS_IOMUX_PAD_NAKED(1, 19, PAD_MUXSEL_1)
-#define MX23_PAD_LCD_DOTCK__GPMI_RDY3		MXS_IOMUX_PAD_NAKED(1, 22, PAD_MUXSEL_1)
-#define MX23_PAD_LCD_ENABLE__I2C_SCL		MXS_IOMUX_PAD_NAKED(1, 23, PAD_MUXSEL_1)
-#define MX23_PAD_LCD_HSYNC__I2C_SDA		MXS_IOMUX_PAD_NAKED(1, 24, PAD_MUXSEL_1)
-#define MX23_PAD_LCD_VSYNC__LCD_BUSY		MXS_IOMUX_PAD_NAKED(1, 25, PAD_MUXSEL_1)
-#define MX23_PAD_PWM0__ROTARYA			MXS_IOMUX_PAD_NAKED(1, 26, PAD_MUXSEL_1)
-#define MX23_PAD_PWM1__ROTARYB			MXS_IOMUX_PAD_NAKED(1, 27, PAD_MUXSEL_1)
-#define MX23_PAD_PWM2__GPMI_RDY3		MXS_IOMUX_PAD_NAKED(1, 28, PAD_MUXSEL_1)
-#define MX23_PAD_PWM3__ETM_TCTL			MXS_IOMUX_PAD_NAKED(1, 29, PAD_MUXSEL_1)
-#define MX23_PAD_PWM4__ETM_TCLK			MXS_IOMUX_PAD_NAKED(1, 30, PAD_MUXSEL_1)
-
-#define MX23_PAD_SSP1_DETECT__GPMI_CE3N		MXS_IOMUX_PAD_NAKED(2,  1, PAD_MUXSEL_1)
-#define MX23_PAD_SSP1_DATA1__I2C_SCL		MXS_IOMUX_PAD_NAKED(2,  3, PAD_MUXSEL_1)
-#define MX23_PAD_SSP1_DATA2__I2C_SDA		MXS_IOMUX_PAD_NAKED(2,  4, PAD_MUXSEL_1)
-#define MX23_PAD_ROTARYA__AUART2_RTS		MXS_IOMUX_PAD_NAKED(2,  7, PAD_MUXSEL_1)
-#define MX23_PAD_ROTARYB__AUART2_CTS		MXS_IOMUX_PAD_NAKED(2,  8, PAD_MUXSEL_1)
-
-/* MUXSEL_2 */
-#define MX23_PAD_GPMI_D00__SSP2_DATA0		MXS_IOMUX_PAD_NAKED(0,  0, PAD_MUXSEL_2)
-#define MX23_PAD_GPMI_D01__SSP2_DATA1		MXS_IOMUX_PAD_NAKED(0,  1, PAD_MUXSEL_2)
-#define MX23_PAD_GPMI_D02__SSP2_DATA2		MXS_IOMUX_PAD_NAKED(0,  2, PAD_MUXSEL_2)
-#define MX23_PAD_GPMI_D03__SSP2_DATA3		MXS_IOMUX_PAD_NAKED(0,  3, PAD_MUXSEL_2)
-#define MX23_PAD_GPMI_D04__SSP2_DATA4		MXS_IOMUX_PAD_NAKED(0,  4, PAD_MUXSEL_2)
-#define MX23_PAD_GPMI_D05__SSP2_DATA5		MXS_IOMUX_PAD_NAKED(0,  5, PAD_MUXSEL_2)
-#define MX23_PAD_GPMI_D06__SSP2_DATA6		MXS_IOMUX_PAD_NAKED(0,  6, PAD_MUXSEL_2)
-#define MX23_PAD_GPMI_D07__SSP2_DATA7		MXS_IOMUX_PAD_NAKED(0,  7, PAD_MUXSEL_2)
-#define MX23_PAD_GPMI_D08__SSP1_DATA4		MXS_IOMUX_PAD_NAKED(0,  8, PAD_MUXSEL_2)
-#define MX23_PAD_GPMI_D09__SSP1_DATA5		MXS_IOMUX_PAD_NAKED(0,  9, PAD_MUXSEL_2)
-#define MX23_PAD_GPMI_D10__SSP1_DATA6		MXS_IOMUX_PAD_NAKED(0, 10, PAD_MUXSEL_2)
-#define MX23_PAD_GPMI_D11__SSP1_DATA7		MXS_IOMUX_PAD_NAKED(0, 11, PAD_MUXSEL_2)
-#define MX23_PAD_GPMI_D15__GPMI_CE3N		MXS_IOMUX_PAD_NAKED(0, 15, PAD_MUXSEL_2)
-#define MX23_PAD_GPMI_RDY0__SSP2_DETECT		MXS_IOMUX_PAD_NAKED(0, 19, PAD_MUXSEL_2)
-#define MX23_PAD_GPMI_RDY1__SSP2_CMD		MXS_IOMUX_PAD_NAKED(0, 20, PAD_MUXSEL_2)
-#define MX23_PAD_GPMI_WRN__SSP2_SCK		MXS_IOMUX_PAD_NAKED(0, 24, PAD_MUXSEL_2)
-#define MX23_PAD_AUART1_CTS__SSP1_DATA4		MXS_IOMUX_PAD_NAKED(0, 26, PAD_MUXSEL_2)
-#define MX23_PAD_AUART1_RTS__SSP1_DATA5		MXS_IOMUX_PAD_NAKED(0, 27, PAD_MUXSEL_2)
-#define MX23_PAD_AUART1_RX__SSP1_DATA6		MXS_IOMUX_PAD_NAKED(0, 28, PAD_MUXSEL_2)
-#define MX23_PAD_AUART1_TX__SSP1_DATA7		MXS_IOMUX_PAD_NAKED(0, 29, PAD_MUXSEL_2)
-#define MX23_PAD_I2C_SCL__AUART1_TX		MXS_IOMUX_PAD_NAKED(0, 30, PAD_MUXSEL_2)
-#define MX23_PAD_I2C_SDA__AUART1_RX		MXS_IOMUX_PAD_NAKED(0, 31, PAD_MUXSEL_2)
-
-#define MX23_PAD_LCD_D08__SAIF2_SDATA0		MXS_IOMUX_PAD_NAKED(1,  8, PAD_MUXSEL_2)
-#define MX23_PAD_LCD_D09__SAIF1_SDATA0		MXS_IOMUX_PAD_NAKED(1,  9, PAD_MUXSEL_2)
-#define MX23_PAD_LCD_D10__SAIF_MCLK_BITCLK	MXS_IOMUX_PAD_NAKED(1, 10, PAD_MUXSEL_2)
-#define MX23_PAD_LCD_D11__SAIF_LRCLK		MXS_IOMUX_PAD_NAKED(1, 11, PAD_MUXSEL_2)
-#define MX23_PAD_LCD_D12__SAIF2_SDATA1		MXS_IOMUX_PAD_NAKED(1, 12, PAD_MUXSEL_2)
-#define MX23_PAD_LCD_D13__SAIF2_SDATA2		MXS_IOMUX_PAD_NAKED(1, 13, PAD_MUXSEL_2)
-#define MX23_PAD_LCD_D14__SAIF1_SDATA2		MXS_IOMUX_PAD_NAKED(1, 14, PAD_MUXSEL_2)
-#define MX23_PAD_LCD_D15__SAIF1_SDATA1		MXS_IOMUX_PAD_NAKED(1, 15, PAD_MUXSEL_2)
-#define MX23_PAD_LCD_D16__SAIF_ALT_BITCLK	MXS_IOMUX_PAD_NAKED(1, 16, PAD_MUXSEL_2)
-#define MX23_PAD_LCD_RESET__GPMI_CE3N		MXS_IOMUX_PAD_NAKED(1, 18, PAD_MUXSEL_2)
-#define MX23_PAD_PWM0__DUART_RX			MXS_IOMUX_PAD_NAKED(1, 26, PAD_MUXSEL_2)
-#define MX23_PAD_PWM1__DUART_TX			MXS_IOMUX_PAD_NAKED(1, 27, PAD_MUXSEL_2)
-#define MX23_PAD_PWM3__AUART1_CTS		MXS_IOMUX_PAD_NAKED(1, 29, PAD_MUXSEL_2)
-#define MX23_PAD_PWM4__AUART1_RTS		MXS_IOMUX_PAD_NAKED(1, 30, PAD_MUXSEL_2)
-
-#define MX23_PAD_SSP1_CMD__JTAG_TDO		MXS_IOMUX_PAD_NAKED(2,  0, PAD_MUXSEL_2)
-#define MX23_PAD_SSP1_DETECT__USB_OTG_ID	MXS_IOMUX_PAD_NAKED(2,  1, PAD_MUXSEL_2)
-#define MX23_PAD_SSP1_DATA0__JTAG_TDI		MXS_IOMUX_PAD_NAKED(2,  2, PAD_MUXSEL_2)
-#define MX23_PAD_SSP1_DATA1__JTAG_TCLK		MXS_IOMUX_PAD_NAKED(2,  3, PAD_MUXSEL_2)
-#define MX23_PAD_SSP1_DATA2__JTAG_RTCK		MXS_IOMUX_PAD_NAKED(2,  4, PAD_MUXSEL_2)
-#define MX23_PAD_SSP1_DATA3__JTAG_TMS		MXS_IOMUX_PAD_NAKED(2,  5, PAD_MUXSEL_2)
-#define MX23_PAD_SSP1_SCK__JTAG_TRST		MXS_IOMUX_PAD_NAKED(2,  6, PAD_MUXSEL_2)
-#define MX23_PAD_ROTARYA__SPDIF			MXS_IOMUX_PAD_NAKED(2,  7, PAD_MUXSEL_2)
-#define MX23_PAD_ROTARYB__GPMI_CE3N		MXS_IOMUX_PAD_NAKED(2,  8, PAD_MUXSEL_2)
-
-/* MUXSEL_GPIO */
-#define MX23_PAD_GPMI_D00__GPIO_0_0		MXS_IOMUX_PAD_NAKED(0,  0, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_D01__GPIO_0_1		MXS_IOMUX_PAD_NAKED(0,  1, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_D02__GPIO_0_2		MXS_IOMUX_PAD_NAKED(0,  2, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_D03__GPIO_0_3		MXS_IOMUX_PAD_NAKED(0,  3, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_D04__GPIO_0_4		MXS_IOMUX_PAD_NAKED(0,  4, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_D05__GPIO_0_5		MXS_IOMUX_PAD_NAKED(0,  5, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_D06__GPIO_0_6		MXS_IOMUX_PAD_NAKED(0,  6, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_D07__GPIO_0_7		MXS_IOMUX_PAD_NAKED(0,  7, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_D08__GPIO_0_8		MXS_IOMUX_PAD_NAKED(0,  8, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_D09__GPIO_0_9		MXS_IOMUX_PAD_NAKED(0,  9, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_D10__GPIO_0_10		MXS_IOMUX_PAD_NAKED(0, 10, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_D11__GPIO_0_11		MXS_IOMUX_PAD_NAKED(0, 11, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_D12__GPIO_0_12		MXS_IOMUX_PAD_NAKED(0, 12, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_D13__GPIO_0_13		MXS_IOMUX_PAD_NAKED(0, 13, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_D14__GPIO_0_14		MXS_IOMUX_PAD_NAKED(0, 14, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_D15__GPIO_0_15		MXS_IOMUX_PAD_NAKED(0, 15, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_CLE__GPIO_0_16		MXS_IOMUX_PAD_NAKED(0, 16, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_ALE__GPIO_0_17		MXS_IOMUX_PAD_NAKED(0, 17, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_CE2N__GPIO_0_18		MXS_IOMUX_PAD_NAKED(0, 18, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_RDY0__GPIO_0_19		MXS_IOMUX_PAD_NAKED(0, 19, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_RDY1__GPIO_0_20		MXS_IOMUX_PAD_NAKED(0, 20, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_RDY2__GPIO_0_21		MXS_IOMUX_PAD_NAKED(0, 21, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_RDY3__GPIO_0_22		MXS_IOMUX_PAD_NAKED(0, 22, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_WPN__GPIO_0_23		MXS_IOMUX_PAD_NAKED(0, 23, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_WRN__GPIO_0_24		MXS_IOMUX_PAD_NAKED(0, 24, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_RDN__GPIO_0_25		MXS_IOMUX_PAD_NAKED(0, 25, PAD_MUXSEL_GPIO)
-#define MX23_PAD_AUART1_CTS__GPIO_0_26		MXS_IOMUX_PAD_NAKED(0, 26, PAD_MUXSEL_GPIO)
-#define MX23_PAD_AUART1_RTS__GPIO_0_27		MXS_IOMUX_PAD_NAKED(0, 27, PAD_MUXSEL_GPIO)
-#define MX23_PAD_AUART1_RX__GPIO_0_28		MXS_IOMUX_PAD_NAKED(0, 28, PAD_MUXSEL_GPIO)
-#define MX23_PAD_AUART1_TX__GPIO_0_29		MXS_IOMUX_PAD_NAKED(0, 29, PAD_MUXSEL_GPIO)
-#define MX23_PAD_I2C_SCL__GPIO_0_30		MXS_IOMUX_PAD_NAKED(0, 30, PAD_MUXSEL_GPIO)
-#define MX23_PAD_I2C_SDA__GPIO_0_31		MXS_IOMUX_PAD_NAKED(0, 31, PAD_MUXSEL_GPIO)
-
-#define MX23_PAD_LCD_D00__GPIO_1_0		MXS_IOMUX_PAD_NAKED(1,  0, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D01__GPIO_1_1		MXS_IOMUX_PAD_NAKED(1,  1, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D02__GPIO_1_2		MXS_IOMUX_PAD_NAKED(1,  2, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D03__GPIO_1_3		MXS_IOMUX_PAD_NAKED(1,  3, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D04__GPIO_1_4		MXS_IOMUX_PAD_NAKED(1,  4, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D05__GPIO_1_5		MXS_IOMUX_PAD_NAKED(1,  5, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D06__GPIO_1_6		MXS_IOMUX_PAD_NAKED(1,  6, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D07__GPIO_1_7		MXS_IOMUX_PAD_NAKED(1,  7, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D08__GPIO_1_8		MXS_IOMUX_PAD_NAKED(1,  8, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D09__GPIO_1_9		MXS_IOMUX_PAD_NAKED(1,  9, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D10__GPIO_1_10		MXS_IOMUX_PAD_NAKED(1, 10, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D11__GPIO_1_11		MXS_IOMUX_PAD_NAKED(1, 11, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D12__GPIO_1_12		MXS_IOMUX_PAD_NAKED(1, 12, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D13__GPIO_1_13		MXS_IOMUX_PAD_NAKED(1, 13, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D14__GPIO_1_14		MXS_IOMUX_PAD_NAKED(1, 14, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D15__GPIO_1_15		MXS_IOMUX_PAD_NAKED(1, 15, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D16__GPIO_1_16		MXS_IOMUX_PAD_NAKED(1, 16, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D17__GPIO_1_17		MXS_IOMUX_PAD_NAKED(1, 17, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_RESET__GPIO_1_18		MXS_IOMUX_PAD_NAKED(1, 18, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_RS__GPIO_1_19		MXS_IOMUX_PAD_NAKED(1, 19, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_WR__GPIO_1_20		MXS_IOMUX_PAD_NAKED(1, 20, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_CS__GPIO_1_21		MXS_IOMUX_PAD_NAKED(1, 21, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_DOTCK__GPIO_1_22		MXS_IOMUX_PAD_NAKED(1, 22, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_ENABLE__GPIO_1_23		MXS_IOMUX_PAD_NAKED(1, 23, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_HSYNC__GPIO_1_24		MXS_IOMUX_PAD_NAKED(1, 24, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_VSYNC__GPIO_1_25		MXS_IOMUX_PAD_NAKED(1, 25, PAD_MUXSEL_GPIO)
-#define MX23_PAD_PWM0__GPIO_1_26		MXS_IOMUX_PAD_NAKED(1, 26, PAD_MUXSEL_GPIO)
-#define MX23_PAD_PWM1__GPIO_1_27		MXS_IOMUX_PAD_NAKED(1, 27, PAD_MUXSEL_GPIO)
-#define MX23_PAD_PWM2__GPIO_1_28		MXS_IOMUX_PAD_NAKED(1, 28, PAD_MUXSEL_GPIO)
-#define MX23_PAD_PWM3__GPIO_1_29		MXS_IOMUX_PAD_NAKED(1, 29, PAD_MUXSEL_GPIO)
-#define MX23_PAD_PWM4__GPIO_1_30		MXS_IOMUX_PAD_NAKED(1, 30, PAD_MUXSEL_GPIO)
-
-#define MX23_PAD_SSP1_CMD__GPIO_2_0		MXS_IOMUX_PAD_NAKED(2,  0, PAD_MUXSEL_GPIO)
-#define MX23_PAD_SSP1_DETECT__GPIO_2_1		MXS_IOMUX_PAD_NAKED(2,  1, PAD_MUXSEL_GPIO)
-#define MX23_PAD_SSP1_DATA0__GPIO_2_2		MXS_IOMUX_PAD_NAKED(2,  2, PAD_MUXSEL_GPIO)
-#define MX23_PAD_SSP1_DATA1__GPIO_2_3		MXS_IOMUX_PAD_NAKED(2,  3, PAD_MUXSEL_GPIO)
-#define MX23_PAD_SSP1_DATA2__GPIO_2_4		MXS_IOMUX_PAD_NAKED(2,  4, PAD_MUXSEL_GPIO)
-#define MX23_PAD_SSP1_DATA3__GPIO_2_5		MXS_IOMUX_PAD_NAKED(2,  5, PAD_MUXSEL_GPIO)
-#define MX23_PAD_SSP1_SCK__GPIO_2_6		MXS_IOMUX_PAD_NAKED(2,  6, PAD_MUXSEL_GPIO)
-#define MX23_PAD_ROTARYA__GPIO_2_7		MXS_IOMUX_PAD_NAKED(2,  7, PAD_MUXSEL_GPIO)
-#define MX23_PAD_ROTARYB__GPIO_2_8		MXS_IOMUX_PAD_NAKED(2,  8, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_A00__GPIO_2_9		MXS_IOMUX_PAD_NAKED(2,  9, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_A01__GPIO_2_10		MXS_IOMUX_PAD_NAKED(2, 10, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_A02__GPIO_2_11		MXS_IOMUX_PAD_NAKED(2, 11, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_A03__GPIO_2_12		MXS_IOMUX_PAD_NAKED(2, 12, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_A04__GPIO_2_13		MXS_IOMUX_PAD_NAKED(2, 13, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_A05__GPIO_2_14		MXS_IOMUX_PAD_NAKED(2, 14, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_A06__GPIO_2_15		MXS_IOMUX_PAD_NAKED(2, 15, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_A07__GPIO_2_16		MXS_IOMUX_PAD_NAKED(2, 16, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_A08__GPIO_2_17		MXS_IOMUX_PAD_NAKED(2, 17, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_A09__GPIO_2_18		MXS_IOMUX_PAD_NAKED(2, 18, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_A10__GPIO_2_19		MXS_IOMUX_PAD_NAKED(2, 19, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_A11__GPIO_2_20		MXS_IOMUX_PAD_NAKED(2, 20, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_A12__GPIO_2_21		MXS_IOMUX_PAD_NAKED(2, 21, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_BA0__GPIO_2_22		MXS_IOMUX_PAD_NAKED(2, 22, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_BA1__GPIO_2_23		MXS_IOMUX_PAD_NAKED(2, 23, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_CASN__GPIO_2_24		MXS_IOMUX_PAD_NAKED(2, 24, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_CE0N__GPIO_2_25		MXS_IOMUX_PAD_NAKED(2, 25, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_CE1N__GPIO_2_26		MXS_IOMUX_PAD_NAKED(2, 26, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_CE1N__GPIO_2_27		MXS_IOMUX_PAD_NAKED(2, 27, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_CE0N__GPIO_2_28		MXS_IOMUX_PAD_NAKED(2, 28, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_CKE__GPIO_2_29		MXS_IOMUX_PAD_NAKED(2, 29, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_RASN__GPIO_2_30		MXS_IOMUX_PAD_NAKED(2, 30, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_WEN__GPIO_2_31		MXS_IOMUX_PAD_NAKED(2, 31, PAD_MUXSEL_GPIO)
-
-#endif /* __MACH_IOMUX_MX23_H__ */
diff --git a/arch/arm/mach-mxs/include/mach/iomux-mx28.h b/arch/arm/mach-mxs/include/mach/iomux-mx28.h
deleted file mode 100644
index f50fefd..0000000
--- a/arch/arm/mach-mxs/include/mach/iomux-mx28.h
+++ /dev/null
@@ -1,537 +0,0 @@
-/*
- * Copyright (C) 2009-2010 Amit Kucheria <amit.kucheria@canonical.com>
- * Copyright (C) 2010 Freescale Semiconductor, Inc.
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#ifndef __MACH_IOMUX_MX28_H__
-#define __MACH_IOMUX_MX28_H__
-
-#include <mach/iomux.h>
-
-/*
- * The naming convention for the pad modes is MX28_PAD_<padname>__<padmode>
- * If <padname> or <padmode> refers to a GPIO, it is named GPIO_<unit>_<num>
- * See also iomux.h
- *
- *									BANK	PIN	MUX
- */
-/* MUXSEL_0 */
-#define MX28_PAD_GPMI_D00__GPMI_D0			MXS_IOMUX_PAD_NAKED(0,  0, PAD_MUXSEL_0)
-#define MX28_PAD_GPMI_D01__GPMI_D1			MXS_IOMUX_PAD_NAKED(0,  1, PAD_MUXSEL_0)
-#define MX28_PAD_GPMI_D02__GPMI_D2			MXS_IOMUX_PAD_NAKED(0,  2, PAD_MUXSEL_0)
-#define MX28_PAD_GPMI_D03__GPMI_D3			MXS_IOMUX_PAD_NAKED(0,  3, PAD_MUXSEL_0)
-#define MX28_PAD_GPMI_D04__GPMI_D4			MXS_IOMUX_PAD_NAKED(0,  4, PAD_MUXSEL_0)
-#define MX28_PAD_GPMI_D05__GPMI_D5			MXS_IOMUX_PAD_NAKED(0,  5, PAD_MUXSEL_0)
-#define MX28_PAD_GPMI_D06__GPMI_D6			MXS_IOMUX_PAD_NAKED(0,  6, PAD_MUXSEL_0)
-#define MX28_PAD_GPMI_D07__GPMI_D7			MXS_IOMUX_PAD_NAKED(0,  7, PAD_MUXSEL_0)
-#define MX28_PAD_GPMI_CE0N__GPMI_CE0N			MXS_IOMUX_PAD_NAKED(0, 16, PAD_MUXSEL_0)
-#define MX28_PAD_GPMI_CE1N__GPMI_CE1N			MXS_IOMUX_PAD_NAKED(0, 17, PAD_MUXSEL_0)
-#define MX28_PAD_GPMI_CE2N__GPMI_CE2N			MXS_IOMUX_PAD_NAKED(0, 18, PAD_MUXSEL_0)
-#define MX28_PAD_GPMI_CE3N__GPMI_CE3N			MXS_IOMUX_PAD_NAKED(0, 19, PAD_MUXSEL_0)
-#define MX28_PAD_GPMI_RDY0__GPMI_READY0			MXS_IOMUX_PAD_NAKED(0, 20, PAD_MUXSEL_0)
-#define MX28_PAD_GPMI_RDY1__GPMI_READY1			MXS_IOMUX_PAD_NAKED(0, 21, PAD_MUXSEL_0)
-#define MX28_PAD_GPMI_RDY2__GPMI_READY2			MXS_IOMUX_PAD_NAKED(0, 22, PAD_MUXSEL_0)
-#define MX28_PAD_GPMI_RDY3__GPMI_READY3			MXS_IOMUX_PAD_NAKED(0, 23, PAD_MUXSEL_0)
-#define MX28_PAD_GPMI_RDN__GPMI_RDN			MXS_IOMUX_PAD_NAKED(0, 24, PAD_MUXSEL_0)
-#define MX28_PAD_GPMI_WRN__GPMI_WRN			MXS_IOMUX_PAD_NAKED(0, 25, PAD_MUXSEL_0)
-#define MX28_PAD_GPMI_ALE__GPMI_ALE			MXS_IOMUX_PAD_NAKED(0, 26, PAD_MUXSEL_0)
-#define MX28_PAD_GPMI_CLE__GPMI_CLE			MXS_IOMUX_PAD_NAKED(0, 27, PAD_MUXSEL_0)
-#define MX28_PAD_GPMI_RESETN__GPMI_RESETN		MXS_IOMUX_PAD_NAKED(0, 28, PAD_MUXSEL_0)
-
-#define MX28_PAD_LCD_D00__LCD_D0			MXS_IOMUX_PAD_NAKED(1,  0, PAD_MUXSEL_0)
-#define MX28_PAD_LCD_D01__LCD_D1			MXS_IOMUX_PAD_NAKED(1,  1, PAD_MUXSEL_0)
-#define MX28_PAD_LCD_D02__LCD_D2			MXS_IOMUX_PAD_NAKED(1,  2, PAD_MUXSEL_0)
-#define MX28_PAD_LCD_D03__LCD_D3			MXS_IOMUX_PAD_NAKED(1,  3, PAD_MUXSEL_0)
-#define MX28_PAD_LCD_D04__LCD_D4			MXS_IOMUX_PAD_NAKED(1,  4, PAD_MUXSEL_0)
-#define MX28_PAD_LCD_D05__LCD_D5			MXS_IOMUX_PAD_NAKED(1,  5, PAD_MUXSEL_0)
-#define MX28_PAD_LCD_D06__LCD_D6			MXS_IOMUX_PAD_NAKED(1,  6, PAD_MUXSEL_0)
-#define MX28_PAD_LCD_D07__LCD_D7			MXS_IOMUX_PAD_NAKED(1,  7, PAD_MUXSEL_0)
-#define MX28_PAD_LCD_D08__LCD_D8			MXS_IOMUX_PAD_NAKED(1,  8, PAD_MUXSEL_0)
-#define MX28_PAD_LCD_D09__LCD_D9			MXS_IOMUX_PAD_NAKED(1,  9, PAD_MUXSEL_0)
-#define MX28_PAD_LCD_D10__LCD_D10			MXS_IOMUX_PAD_NAKED(1, 10, PAD_MUXSEL_0)
-#define MX28_PAD_LCD_D11__LCD_D11			MXS_IOMUX_PAD_NAKED(1, 11, PAD_MUXSEL_0)
-#define MX28_PAD_LCD_D12__LCD_D12			MXS_IOMUX_PAD_NAKED(1, 12, PAD_MUXSEL_0)
-#define MX28_PAD_LCD_D13__LCD_D13			MXS_IOMUX_PAD_NAKED(1, 13, PAD_MUXSEL_0)
-#define MX28_PAD_LCD_D14__LCD_D14			MXS_IOMUX_PAD_NAKED(1, 14, PAD_MUXSEL_0)
-#define MX28_PAD_LCD_D15__LCD_D15			MXS_IOMUX_PAD_NAKED(1, 15, PAD_MUXSEL_0)
-#define MX28_PAD_LCD_D16__LCD_D16			MXS_IOMUX_PAD_NAKED(1, 16, PAD_MUXSEL_0)
-#define MX28_PAD_LCD_D17__LCD_D17			MXS_IOMUX_PAD_NAKED(1, 17, PAD_MUXSEL_0)
-#define MX28_PAD_LCD_D18__LCD_D18			MXS_IOMUX_PAD_NAKED(1, 18, PAD_MUXSEL_0)
-#define MX28_PAD_LCD_D19__LCD_D19			MXS_IOMUX_PAD_NAKED(1, 19, PAD_MUXSEL_0)
-#define MX28_PAD_LCD_D20__LCD_D20			MXS_IOMUX_PAD_NAKED(1, 20, PAD_MUXSEL_0)
-#define MX28_PAD_LCD_D21__LCD_D21			MXS_IOMUX_PAD_NAKED(1, 21, PAD_MUXSEL_0)
-#define MX28_PAD_LCD_D22__LCD_D22			MXS_IOMUX_PAD_NAKED(1, 22, PAD_MUXSEL_0)
-#define MX28_PAD_LCD_D23__LCD_D23			MXS_IOMUX_PAD_NAKED(1, 23, PAD_MUXSEL_0)
-#define MX28_PAD_LCD_RD_E__LCD_RD_E			MXS_IOMUX_PAD_NAKED(1, 24, PAD_MUXSEL_0)
-#define MX28_PAD_LCD_WR_RWN__LCD_WR_RWN			MXS_IOMUX_PAD_NAKED(1, 25, PAD_MUXSEL_0)
-#define MX28_PAD_LCD_RS__LCD_RS				MXS_IOMUX_PAD_NAKED(1, 26, PAD_MUXSEL_0)
-#define MX28_PAD_LCD_CS__LCD_CS				MXS_IOMUX_PAD_NAKED(1, 27, PAD_MUXSEL_0)
-#define MX28_PAD_LCD_VSYNC__LCD_VSYNC			MXS_IOMUX_PAD_NAKED(1, 28, PAD_MUXSEL_0)
-#define MX28_PAD_LCD_HSYNC__LCD_HSYNC			MXS_IOMUX_PAD_NAKED(1, 29, PAD_MUXSEL_0)
-#define MX28_PAD_LCD_DOTCLK__LCD_DOTCLK			MXS_IOMUX_PAD_NAKED(1, 30, PAD_MUXSEL_0)
-#define MX28_PAD_LCD_ENABLE__LCD_ENABLE			MXS_IOMUX_PAD_NAKED(1, 31, PAD_MUXSEL_0)
-
-#define MX28_PAD_SSP0_DATA0__SSP0_D0			MXS_IOMUX_PAD_NAKED(2,  0, PAD_MUXSEL_0)
-#define MX28_PAD_SSP0_DATA1__SSP0_D1			MXS_IOMUX_PAD_NAKED(2,  1, PAD_MUXSEL_0)
-#define MX28_PAD_SSP0_DATA2__SSP0_D2			MXS_IOMUX_PAD_NAKED(2,  2, PAD_MUXSEL_0)
-#define MX28_PAD_SSP0_DATA3__SSP0_D3			MXS_IOMUX_PAD_NAKED(2,  3, PAD_MUXSEL_0)
-#define MX28_PAD_SSP0_DATA4__SSP0_D4			MXS_IOMUX_PAD_NAKED(2,  4, PAD_MUXSEL_0)
-#define MX28_PAD_SSP0_DATA5__SSP0_D5			MXS_IOMUX_PAD_NAKED(2,  5, PAD_MUXSEL_0)
-#define MX28_PAD_SSP0_DATA6__SSP0_D6			MXS_IOMUX_PAD_NAKED(2,  6, PAD_MUXSEL_0)
-#define MX28_PAD_SSP0_DATA7__SSP0_D7			MXS_IOMUX_PAD_NAKED(2,  7, PAD_MUXSEL_0)
-#define MX28_PAD_SSP0_CMD__SSP0_CMD			MXS_IOMUX_PAD_NAKED(2,  8, PAD_MUXSEL_0)
-#define MX28_PAD_SSP0_DETECT__SSP0_CARD_DETECT		MXS_IOMUX_PAD_NAKED(2,  9, PAD_MUXSEL_0)
-#define MX28_PAD_SSP0_SCK__SSP0_SCK			MXS_IOMUX_PAD_NAKED(2, 10, PAD_MUXSEL_0)
-#define MX28_PAD_SSP1_SCK__SSP1_SCK			MXS_IOMUX_PAD_NAKED(2, 12, PAD_MUXSEL_0)
-#define MX28_PAD_SSP1_CMD__SSP1_CMD			MXS_IOMUX_PAD_NAKED(2, 13, PAD_MUXSEL_0)
-#define MX28_PAD_SSP1_DATA0__SSP1_D0			MXS_IOMUX_PAD_NAKED(2, 14, PAD_MUXSEL_0)
-#define MX28_PAD_SSP1_DATA3__SSP1_D3			MXS_IOMUX_PAD_NAKED(2, 15, PAD_MUXSEL_0)
-#define MX28_PAD_SSP2_SCK__SSP2_SCK			MXS_IOMUX_PAD_NAKED(2, 16, PAD_MUXSEL_0)
-#define MX28_PAD_SSP2_MOSI__SSP2_CMD			MXS_IOMUX_PAD_NAKED(2, 17, PAD_MUXSEL_0)
-#define MX28_PAD_SSP2_MISO__SSP2_D0			MXS_IOMUX_PAD_NAKED(2, 18, PAD_MUXSEL_0)
-#define MX28_PAD_SSP2_SS0__SSP2_D3			MXS_IOMUX_PAD_NAKED(2, 19, PAD_MUXSEL_0)
-#define MX28_PAD_SSP2_SS1__SSP2_D4			MXS_IOMUX_PAD_NAKED(2, 20, PAD_MUXSEL_0)
-#define MX28_PAD_SSP2_SS2__SSP2_D5			MXS_IOMUX_PAD_NAKED(2, 21, PAD_MUXSEL_0)
-#define MX28_PAD_SSP3_SCK__SSP3_SCK			MXS_IOMUX_PAD_NAKED(2, 24, PAD_MUXSEL_0)
-#define MX28_PAD_SSP3_MOSI__SSP3_CMD			MXS_IOMUX_PAD_NAKED(2, 25, PAD_MUXSEL_0)
-#define MX28_PAD_SSP3_MISO__SSP3_D0			MXS_IOMUX_PAD_NAKED(2, 26, PAD_MUXSEL_0)
-#define MX28_PAD_SSP3_SS0__SSP3_D3			MXS_IOMUX_PAD_NAKED(2, 27, PAD_MUXSEL_0)
-
-#define MX28_PAD_AUART0_RX__AUART0_RX			MXS_IOMUX_PAD_NAKED(3,  0, PAD_MUXSEL_0)
-#define MX28_PAD_AUART0_TX__AUART0_TX			MXS_IOMUX_PAD_NAKED(3,  1, PAD_MUXSEL_0)
-#define MX28_PAD_AUART0_CTS__AUART0_CTS			MXS_IOMUX_PAD_NAKED(3,  2, PAD_MUXSEL_0)
-#define MX28_PAD_AUART0_RTS__AUART0_RTS			MXS_IOMUX_PAD_NAKED(3,  3, PAD_MUXSEL_0)
-#define MX28_PAD_AUART1_RX__AUART1_RX			MXS_IOMUX_PAD_NAKED(3,  4, PAD_MUXSEL_0)
-#define MX28_PAD_AUART1_TX__AUART1_TX			MXS_IOMUX_PAD_NAKED(3,  5, PAD_MUXSEL_0)
-#define MX28_PAD_AUART1_CTS__AUART1_CTS			MXS_IOMUX_PAD_NAKED(3,  6, PAD_MUXSEL_0)
-#define MX28_PAD_AUART1_RTS__AUART1_RTS			MXS_IOMUX_PAD_NAKED(3,  7, PAD_MUXSEL_0)
-#define MX28_PAD_AUART2_RX__AUART2_RX			MXS_IOMUX_PAD_NAKED(3,  8, PAD_MUXSEL_0)
-#define MX28_PAD_AUART2_TX__AUART2_TX			MXS_IOMUX_PAD_NAKED(3,  9, PAD_MUXSEL_0)
-#define MX28_PAD_AUART2_CTS__AUART2_CTS			MXS_IOMUX_PAD_NAKED(3, 10, PAD_MUXSEL_0)
-#define MX28_PAD_AUART2_RTS__AUART2_RTS			MXS_IOMUX_PAD_NAKED(3, 11, PAD_MUXSEL_0)
-#define MX28_PAD_AUART3_RX__AUART3_RX			MXS_IOMUX_PAD_NAKED(3, 12, PAD_MUXSEL_0)
-#define MX28_PAD_AUART3_TX__AUART3_TX			MXS_IOMUX_PAD_NAKED(3, 13, PAD_MUXSEL_0)
-#define MX28_PAD_AUART3_CTS__AUART3_CTS			MXS_IOMUX_PAD_NAKED(3, 14, PAD_MUXSEL_0)
-#define MX28_PAD_AUART3_RTS__AUART3_RTS			MXS_IOMUX_PAD_NAKED(3, 15, PAD_MUXSEL_0)
-#define MX28_PAD_PWM0__PWM_0				MXS_IOMUX_PAD_NAKED(3, 16, PAD_MUXSEL_0)
-#define MX28_PAD_PWM1__PWM_1				MXS_IOMUX_PAD_NAKED(3, 17, PAD_MUXSEL_0)
-#define MX28_PAD_PWM2__PWM_2				MXS_IOMUX_PAD_NAKED(3, 18, PAD_MUXSEL_0)
-#define MX28_PAD_SAIF0_MCLK__SAIF0_MCLK			MXS_IOMUX_PAD_NAKED(3, 20, PAD_MUXSEL_0)
-#define MX28_PAD_SAIF0_LRCLK__SAIF0_LRCLK		MXS_IOMUX_PAD_NAKED(3, 21, PAD_MUXSEL_0)
-#define MX28_PAD_SAIF0_BITCLK__SAIF0_BITCLK		MXS_IOMUX_PAD_NAKED(3, 22, PAD_MUXSEL_0)
-#define MX28_PAD_SAIF0_SDATA0__SAIF0_SDATA0		MXS_IOMUX_PAD_NAKED(3, 23, PAD_MUXSEL_0)
-#define MX28_PAD_I2C0_SCL__I2C0_SCL			MXS_IOMUX_PAD_NAKED(3, 24, PAD_MUXSEL_0)
-#define MX28_PAD_I2C0_SDA__I2C0_SDA			MXS_IOMUX_PAD_NAKED(3, 25, PAD_MUXSEL_0)
-#define MX28_PAD_SAIF1_SDATA0__SAIF1_SDATA0		MXS_IOMUX_PAD_NAKED(3, 26, PAD_MUXSEL_0)
-#define MX28_PAD_SPDIF__SPDIF_TX			MXS_IOMUX_PAD_NAKED(3, 27, PAD_MUXSEL_0)
-#define MX28_PAD_PWM3__PWM_3				MXS_IOMUX_PAD_NAKED(3, 28, PAD_MUXSEL_0)
-#define MX28_PAD_PWM4__PWM_4				MXS_IOMUX_PAD_NAKED(3, 29, PAD_MUXSEL_0)
-#define MX28_PAD_LCD_RESET__LCD_RESET			MXS_IOMUX_PAD_NAKED(3, 30, PAD_MUXSEL_0)
-
-#define MX28_PAD_ENET0_MDC__ENET0_MDC			MXS_IOMUX_PAD_NAKED(4,  0, PAD_MUXSEL_0)
-#define MX28_PAD_ENET0_MDIO__ENET0_MDIO			MXS_IOMUX_PAD_NAKED(4,  1, PAD_MUXSEL_0)
-#define MX28_PAD_ENET0_RX_EN__ENET0_RX_EN		MXS_IOMUX_PAD_NAKED(4,  2, PAD_MUXSEL_0)
-#define MX28_PAD_ENET0_RXD0__ENET0_RXD0			MXS_IOMUX_PAD_NAKED(4,  3, PAD_MUXSEL_0)
-#define MX28_PAD_ENET0_RXD1__ENET0_RXD1			MXS_IOMUX_PAD_NAKED(4,  4, PAD_MUXSEL_0)
-#define MX28_PAD_ENET0_TX_CLK__ENET0_TX_CLK		MXS_IOMUX_PAD_NAKED(4,  5, PAD_MUXSEL_0)
-#define MX28_PAD_ENET0_TX_EN__ENET0_TX_EN		MXS_IOMUX_PAD_NAKED(4,  6, PAD_MUXSEL_0)
-#define MX28_PAD_ENET0_TXD0__ENET0_TXD0			MXS_IOMUX_PAD_NAKED(4,  7, PAD_MUXSEL_0)
-#define MX28_PAD_ENET0_TXD1__ENET0_TXD1			MXS_IOMUX_PAD_NAKED(4,  8, PAD_MUXSEL_0)
-#define MX28_PAD_ENET0_RXD2__ENET0_RXD2			MXS_IOMUX_PAD_NAKED(4,  9, PAD_MUXSEL_0)
-#define MX28_PAD_ENET0_RXD3__ENET0_RXD3			MXS_IOMUX_PAD_NAKED(4, 10, PAD_MUXSEL_0)
-#define MX28_PAD_ENET0_TXD2__ENET0_TXD2			MXS_IOMUX_PAD_NAKED(4, 11, PAD_MUXSEL_0)
-#define MX28_PAD_ENET0_TXD3__ENET0_TXD3			MXS_IOMUX_PAD_NAKED(4, 12, PAD_MUXSEL_0)
-#define MX28_PAD_ENET0_RX_CLK__ENET0_RX_CLK		MXS_IOMUX_PAD_NAKED(4, 13, PAD_MUXSEL_0)
-#define MX28_PAD_ENET0_COL__ENET0_COL			MXS_IOMUX_PAD_NAKED(4, 14, PAD_MUXSEL_0)
-#define MX28_PAD_ENET0_CRS__ENET0_CRS			MXS_IOMUX_PAD_NAKED(4, 15, PAD_MUXSEL_0)
-#define MX28_PAD_ENET_CLK__CLKCTRL_ENET			MXS_IOMUX_PAD_NAKED(4, 16, PAD_MUXSEL_0)
-#define MX28_PAD_JTAG_RTCK__JTAG_RTCK			MXS_IOMUX_PAD_NAKED(4, 20, PAD_MUXSEL_0)
-
-#define MX28_PAD_EMI_D00__EMI_DATA0			MXS_IOMUX_PAD_NAKED(5,  0, PAD_MUXSEL_0)
-#define MX28_PAD_EMI_D01__EMI_DATA1			MXS_IOMUX_PAD_NAKED(5,  1, PAD_MUXSEL_0)
-#define MX28_PAD_EMI_D02__EMI_DATA2			MXS_IOMUX_PAD_NAKED(5,  2, PAD_MUXSEL_0)
-#define MX28_PAD_EMI_D03__EMI_DATA3			MXS_IOMUX_PAD_NAKED(5,  3, PAD_MUXSEL_0)
-#define MX28_PAD_EMI_D04__EMI_DATA4			MXS_IOMUX_PAD_NAKED(5,  4, PAD_MUXSEL_0)
-#define MX28_PAD_EMI_D05__EMI_DATA5			MXS_IOMUX_PAD_NAKED(5,  5, PAD_MUXSEL_0)
-#define MX28_PAD_EMI_D06__EMI_DATA6			MXS_IOMUX_PAD_NAKED(5,  6, PAD_MUXSEL_0)
-#define MX28_PAD_EMI_D07__EMI_DATA7			MXS_IOMUX_PAD_NAKED(5,  7, PAD_MUXSEL_0)
-#define MX28_PAD_EMI_D08__EMI_DATA8			MXS_IOMUX_PAD_NAKED(5,  8, PAD_MUXSEL_0)
-#define MX28_PAD_EMI_D09__EMI_DATA9			MXS_IOMUX_PAD_NAKED(5,  9, PAD_MUXSEL_0)
-#define MX28_PAD_EMI_D10__EMI_DATA10			MXS_IOMUX_PAD_NAKED(5, 10, PAD_MUXSEL_0)
-#define MX28_PAD_EMI_D11__EMI_DATA11			MXS_IOMUX_PAD_NAKED(5, 11, PAD_MUXSEL_0)
-#define MX28_PAD_EMI_D12__EMI_DATA12			MXS_IOMUX_PAD_NAKED(5, 12, PAD_MUXSEL_0)
-#define MX28_PAD_EMI_D13__EMI_DATA13			MXS_IOMUX_PAD_NAKED(5, 13, PAD_MUXSEL_0)
-#define MX28_PAD_EMI_D14__EMI_DATA14			MXS_IOMUX_PAD_NAKED(5, 14, PAD_MUXSEL_0)
-#define MX28_PAD_EMI_D15__EMI_DATA15			MXS_IOMUX_PAD_NAKED(5, 15, PAD_MUXSEL_0)
-#define MX28_PAD_EMI_ODT0__EMI_ODT0			MXS_IOMUX_PAD_NAKED(5, 16, PAD_MUXSEL_0)
-#define MX28_PAD_EMI_DQM0__EMI_DQM0			MXS_IOMUX_PAD_NAKED(5, 17, PAD_MUXSEL_0)
-#define MX28_PAD_EMI_ODT1__EMI_ODT1			MXS_IOMUX_PAD_NAKED(5, 18, PAD_MUXSEL_0)
-#define MX28_PAD_EMI_DQM1__EMI_DQM1			MXS_IOMUX_PAD_NAKED(5, 19, PAD_MUXSEL_0)
-#define MX28_PAD_EMI_DDR_OPEN_FB__EMI_DDR_OPEN_FEEDBACK	MXS_IOMUX_PAD_NAKED(5, 20, PAD_MUXSEL_0)
-#define MX28_PAD_EMI_CLK__EMI_CLK			MXS_IOMUX_PAD_NAKED(5, 21, PAD_MUXSEL_0)
-#define MX28_PAD_EMI_DQS0__EMI_DQS0			MXS_IOMUX_PAD_NAKED(5, 22, PAD_MUXSEL_0)
-#define MX28_PAD_EMI_DQS1__EMI_DQS1			MXS_IOMUX_PAD_NAKED(5, 23, PAD_MUXSEL_0)
-#define MX28_PAD_EMI_DDR_OPEN__EMI_DDR_OPEN		MXS_IOMUX_PAD_NAKED(5, 26, PAD_MUXSEL_0)
-
-#define MX28_PAD_EMI_A00__EMI_ADDR0			MXS_IOMUX_PAD_NAKED(6,  0, PAD_MUXSEL_0)
-#define MX28_PAD_EMI_A01__EMI_ADDR1			MXS_IOMUX_PAD_NAKED(6,  1, PAD_MUXSEL_0)
-#define MX28_PAD_EMI_A02__EMI_ADDR2			MXS_IOMUX_PAD_NAKED(6,  2, PAD_MUXSEL_0)
-#define MX28_PAD_EMI_A03__EMI_ADDR3			MXS_IOMUX_PAD_NAKED(6,  3, PAD_MUXSEL_0)
-#define MX28_PAD_EMI_A04__EMI_ADDR4			MXS_IOMUX_PAD_NAKED(6,  4, PAD_MUXSEL_0)
-#define MX28_PAD_EMI_A05__EMI_ADDR5			MXS_IOMUX_PAD_NAKED(6,  5, PAD_MUXSEL_0)
-#define MX28_PAD_EMI_A06__EMI_ADDR6			MXS_IOMUX_PAD_NAKED(6,  6, PAD_MUXSEL_0)
-#define MX28_PAD_EMI_A07__EMI_ADDR7			MXS_IOMUX_PAD_NAKED(6,  7, PAD_MUXSEL_0)
-#define MX28_PAD_EMI_A08__EMI_ADDR8			MXS_IOMUX_PAD_NAKED(6,  8, PAD_MUXSEL_0)
-#define MX28_PAD_EMI_A09__EMI_ADDR9			MXS_IOMUX_PAD_NAKED(6,  9, PAD_MUXSEL_0)
-#define MX28_PAD_EMI_A10__EMI_ADDR10			MXS_IOMUX_PAD_NAKED(6, 10, PAD_MUXSEL_0)
-#define MX28_PAD_EMI_A11__EMI_ADDR11			MXS_IOMUX_PAD_NAKED(6, 11, PAD_MUXSEL_0)
-#define MX28_PAD_EMI_A12__EMI_ADDR12			MXS_IOMUX_PAD_NAKED(6, 12, PAD_MUXSEL_0)
-#define MX28_PAD_EMI_A13__EMI_ADDR13			MXS_IOMUX_PAD_NAKED(6, 13, PAD_MUXSEL_0)
-#define MX28_PAD_EMI_A14__EMI_ADDR14			MXS_IOMUX_PAD_NAKED(6, 14, PAD_MUXSEL_0)
-#define MX28_PAD_EMI_BA0__EMI_BA0			MXS_IOMUX_PAD_NAKED(6, 16, PAD_MUXSEL_0)
-#define MX28_PAD_EMI_BA1__EMI_BA1			MXS_IOMUX_PAD_NAKED(6, 17, PAD_MUXSEL_0)
-#define MX28_PAD_EMI_BA2__EMI_BA2			MXS_IOMUX_PAD_NAKED(6, 18, PAD_MUXSEL_0)
-#define MX28_PAD_EMI_CASN__EMI_CASN			MXS_IOMUX_PAD_NAKED(6, 19, PAD_MUXSEL_0)
-#define MX28_PAD_EMI_RASN__EMI_RASN			MXS_IOMUX_PAD_NAKED(6, 20, PAD_MUXSEL_0)
-#define MX28_PAD_EMI_WEN__EMI_WEN			MXS_IOMUX_PAD_NAKED(6, 21, PAD_MUXSEL_0)
-#define MX28_PAD_EMI_CE0N__EMI_CE0N			MXS_IOMUX_PAD_NAKED(6, 22, PAD_MUXSEL_0)
-#define MX28_PAD_EMI_CE1N__EMI_CE1N			MXS_IOMUX_PAD_NAKED(6, 23, PAD_MUXSEL_0)
-#define MX28_PAD_EMI_CKE__EMI_CKE			MXS_IOMUX_PAD_NAKED(6, 24, PAD_MUXSEL_0)
-
-/* MUXSEL_1 */
-#define MX28_PAD_GPMI_D00__SSP1_D0			MXS_IOMUX_PAD_NAKED(0,  0, PAD_MUXSEL_1)
-#define MX28_PAD_GPMI_D01__SSP1_D1			MXS_IOMUX_PAD_NAKED(0,  1, PAD_MUXSEL_1)
-#define MX28_PAD_GPMI_D02__SSP1_D2			MXS_IOMUX_PAD_NAKED(0,  2, PAD_MUXSEL_1)
-#define MX28_PAD_GPMI_D03__SSP1_D3			MXS_IOMUX_PAD_NAKED(0,  3, PAD_MUXSEL_1)
-#define MX28_PAD_GPMI_D04__SSP1_D4			MXS_IOMUX_PAD_NAKED(0,  4, PAD_MUXSEL_1)
-#define MX28_PAD_GPMI_D05__SSP1_D5			MXS_IOMUX_PAD_NAKED(0,  5, PAD_MUXSEL_1)
-#define MX28_PAD_GPMI_D06__SSP1_D6			MXS_IOMUX_PAD_NAKED(0,  6, PAD_MUXSEL_1)
-#define MX28_PAD_GPMI_D07__SSP1_D7			MXS_IOMUX_PAD_NAKED(0,  7, PAD_MUXSEL_1)
-#define MX28_PAD_GPMI_CE0N__SSP3_D0			MXS_IOMUX_PAD_NAKED(0, 16, PAD_MUXSEL_1)
-#define MX28_PAD_GPMI_CE1N__SSP3_D3			MXS_IOMUX_PAD_NAKED(0, 17, PAD_MUXSEL_1)
-#define MX28_PAD_GPMI_CE2N__CAN1_TX			MXS_IOMUX_PAD_NAKED(0, 18, PAD_MUXSEL_1)
-#define MX28_PAD_GPMI_CE3N__CAN1_RX			MXS_IOMUX_PAD_NAKED(0, 19, PAD_MUXSEL_1)
-#define MX28_PAD_GPMI_RDY0__SSP1_CARD_DETECT		MXS_IOMUX_PAD_NAKED(0, 20, PAD_MUXSEL_1)
-#define MX28_PAD_GPMI_RDY1__SSP1_CMD			MXS_IOMUX_PAD_NAKED(0, 21, PAD_MUXSEL_1)
-#define MX28_PAD_GPMI_RDY2__CAN0_TX			MXS_IOMUX_PAD_NAKED(0, 22, PAD_MUXSEL_1)
-#define MX28_PAD_GPMI_RDY3__CAN0_RX			MXS_IOMUX_PAD_NAKED(0, 23, PAD_MUXSEL_1)
-#define MX28_PAD_GPMI_RDN__SSP3_SCK			MXS_IOMUX_PAD_NAKED(0, 24, PAD_MUXSEL_1)
-#define MX28_PAD_GPMI_WRN__SSP1_SCK			MXS_IOMUX_PAD_NAKED(0, 25, PAD_MUXSEL_1)
-#define MX28_PAD_GPMI_ALE__SSP3_D1			MXS_IOMUX_PAD_NAKED(0, 26, PAD_MUXSEL_1)
-#define MX28_PAD_GPMI_CLE__SSP3_D2			MXS_IOMUX_PAD_NAKED(0, 27, PAD_MUXSEL_1)
-#define MX28_PAD_GPMI_RESETN__SSP3_CMD			MXS_IOMUX_PAD_NAKED(0, 28, PAD_MUXSEL_1)
-
-#define MX28_PAD_LCD_D03__ETM_DA8			MXS_IOMUX_PAD_NAKED(1,  3, PAD_MUXSEL_1)
-#define MX28_PAD_LCD_D04__ETM_DA9			MXS_IOMUX_PAD_NAKED(1,  4, PAD_MUXSEL_1)
-#define MX28_PAD_LCD_D08__ETM_DA3			MXS_IOMUX_PAD_NAKED(1,  8, PAD_MUXSEL_1)
-#define MX28_PAD_LCD_D09__ETM_DA4			MXS_IOMUX_PAD_NAKED(1,  9, PAD_MUXSEL_1)
-#define MX28_PAD_LCD_D20__ENET1_1588_EVENT2_OUT		MXS_IOMUX_PAD_NAKED(1, 20, PAD_MUXSEL_1)
-#define MX28_PAD_LCD_D21__ENET1_1588_EVENT2_IN		MXS_IOMUX_PAD_NAKED(1, 21, PAD_MUXSEL_1)
-#define MX28_PAD_LCD_D22__ENET1_1588_EVENT3_OUT		MXS_IOMUX_PAD_NAKED(1, 22, PAD_MUXSEL_1)
-#define MX28_PAD_LCD_D23__ENET1_1588_EVENT3_IN		MXS_IOMUX_PAD_NAKED(1, 23, PAD_MUXSEL_1)
-#define MX28_PAD_LCD_RD_E__LCD_VSYNC			MXS_IOMUX_PAD_NAKED(1, 24, PAD_MUXSEL_1)
-#define MX28_PAD_LCD_WR_RWN__LCD_HSYNC			MXS_IOMUX_PAD_NAKED(1, 25, PAD_MUXSEL_1)
-#define MX28_PAD_LCD_RS__LCD_DOTCLK			MXS_IOMUX_PAD_NAKED(1, 26, PAD_MUXSEL_1)
-#define MX28_PAD_LCD_CS__LCD_ENABLE			MXS_IOMUX_PAD_NAKED(1, 27, PAD_MUXSEL_1)
-#define MX28_PAD_LCD_VSYNC__SAIF1_SDATA0		MXS_IOMUX_PAD_NAKED(1, 28, PAD_MUXSEL_1)
-#define MX28_PAD_LCD_HSYNC__SAIF1_SDATA1		MXS_IOMUX_PAD_NAKED(1, 29, PAD_MUXSEL_1)
-#define MX28_PAD_LCD_DOTCLK__SAIF1_MCLK			MXS_IOMUX_PAD_NAKED(1, 30, PAD_MUXSEL_1)
-
-#define MX28_PAD_SSP0_DATA4__SSP2_D0			MXS_IOMUX_PAD_NAKED(2,  4, PAD_MUXSEL_1)
-#define MX28_PAD_SSP0_DATA5__SSP2_D3			MXS_IOMUX_PAD_NAKED(2,  5, PAD_MUXSEL_1)
-#define MX28_PAD_SSP0_DATA6__SSP2_CMD			MXS_IOMUX_PAD_NAKED(2,  6, PAD_MUXSEL_1)
-#define MX28_PAD_SSP0_DATA7__SSP2_SCK			MXS_IOMUX_PAD_NAKED(2,  7, PAD_MUXSEL_1)
-#define MX28_PAD_SSP1_SCK__SSP2_D1			MXS_IOMUX_PAD_NAKED(2, 12, PAD_MUXSEL_1)
-#define MX28_PAD_SSP1_CMD__SSP2_D2			MXS_IOMUX_PAD_NAKED(2, 13, PAD_MUXSEL_1)
-#define MX28_PAD_SSP1_DATA0__SSP2_D6			MXS_IOMUX_PAD_NAKED(2, 14, PAD_MUXSEL_1)
-#define MX28_PAD_SSP1_DATA3__SSP2_D7			MXS_IOMUX_PAD_NAKED(2, 15, PAD_MUXSEL_1)
-#define MX28_PAD_SSP2_SCK__AUART2_RX			MXS_IOMUX_PAD_NAKED(2, 16, PAD_MUXSEL_1)
-#define MX28_PAD_SSP2_MOSI__AUART2_TX			MXS_IOMUX_PAD_NAKED(2, 17, PAD_MUXSEL_1)
-#define MX28_PAD_SSP2_MISO__AUART3_RX			MXS_IOMUX_PAD_NAKED(2, 18, PAD_MUXSEL_1)
-#define MX28_PAD_SSP2_SS0__AUART3_TX			MXS_IOMUX_PAD_NAKED(2, 19, PAD_MUXSEL_1)
-#define MX28_PAD_SSP2_SS1__SSP2_D1			MXS_IOMUX_PAD_NAKED(2, 20, PAD_MUXSEL_1)
-#define MX28_PAD_SSP2_SS2__SSP2_D2			MXS_IOMUX_PAD_NAKED(2, 21, PAD_MUXSEL_1)
-#define MX28_PAD_SSP3_SCK__AUART4_TX			MXS_IOMUX_PAD_NAKED(2, 24, PAD_MUXSEL_1)
-#define MX28_PAD_SSP3_MOSI__AUART4_RX			MXS_IOMUX_PAD_NAKED(2, 25, PAD_MUXSEL_1)
-#define MX28_PAD_SSP3_MISO__AUART4_RTS			MXS_IOMUX_PAD_NAKED(2, 26, PAD_MUXSEL_1)
-#define MX28_PAD_SSP3_SS0__AUART4_CTS			MXS_IOMUX_PAD_NAKED(2, 27, PAD_MUXSEL_1)
-
-#define MX28_PAD_AUART0_RX__I2C0_SCL			MXS_IOMUX_PAD_NAKED(3,  0, PAD_MUXSEL_1)
-#define MX28_PAD_AUART0_TX__I2C0_SDA			MXS_IOMUX_PAD_NAKED(3,  1, PAD_MUXSEL_1)
-#define MX28_PAD_AUART0_CTS__AUART4_RX			MXS_IOMUX_PAD_NAKED(3,  2, PAD_MUXSEL_1)
-#define MX28_PAD_AUART0_RTS__AUART4_TX			MXS_IOMUX_PAD_NAKED(3,  3, PAD_MUXSEL_1)
-#define MX28_PAD_AUART1_RX__SSP2_CARD_DETECT		MXS_IOMUX_PAD_NAKED(3,  4, PAD_MUXSEL_1)
-#define MX28_PAD_AUART1_TX__SSP3_CARD_DETECT		MXS_IOMUX_PAD_NAKED(3,  5, PAD_MUXSEL_1)
-#define MX28_PAD_AUART1_CTS__USB0_OVERCURRENT		MXS_IOMUX_PAD_NAKED(3,  6, PAD_MUXSEL_1)
-#define MX28_PAD_AUART1_RTS__USB0_ID			MXS_IOMUX_PAD_NAKED(3,  7, PAD_MUXSEL_1)
-#define MX28_PAD_AUART2_RX__SSP3_D1			MXS_IOMUX_PAD_NAKED(3,  8, PAD_MUXSEL_1)
-#define MX28_PAD_AUART2_TX__SSP3_D2			MXS_IOMUX_PAD_NAKED(3,  9, PAD_MUXSEL_1)
-#define MX28_PAD_AUART2_CTS__I2C1_SCL			MXS_IOMUX_PAD_NAKED(3, 10, PAD_MUXSEL_1)
-#define MX28_PAD_AUART2_RTS__I2C1_SDA			MXS_IOMUX_PAD_NAKED(3, 11, PAD_MUXSEL_1)
-#define MX28_PAD_AUART3_RX__CAN0_TX			MXS_IOMUX_PAD_NAKED(3, 12, PAD_MUXSEL_1)
-#define MX28_PAD_AUART3_TX__CAN0_RX			MXS_IOMUX_PAD_NAKED(3, 13, PAD_MUXSEL_1)
-#define MX28_PAD_AUART3_CTS__CAN1_TX			MXS_IOMUX_PAD_NAKED(3, 14, PAD_MUXSEL_1)
-#define MX28_PAD_AUART3_RTS__CAN1_RX			MXS_IOMUX_PAD_NAKED(3, 15, PAD_MUXSEL_1)
-#define MX28_PAD_PWM0__I2C1_SCL				MXS_IOMUX_PAD_NAKED(3, 16, PAD_MUXSEL_1)
-#define MX28_PAD_PWM1__I2C1_SDA				MXS_IOMUX_PAD_NAKED(3, 17, PAD_MUXSEL_1)
-#define MX28_PAD_PWM2__USB0_ID				MXS_IOMUX_PAD_NAKED(3, 18, PAD_MUXSEL_1)
-#define MX28_PAD_SAIF0_MCLK__PWM_3			MXS_IOMUX_PAD_NAKED(3, 20, PAD_MUXSEL_1)
-#define MX28_PAD_SAIF0_LRCLK__PWM_4			MXS_IOMUX_PAD_NAKED(3, 21, PAD_MUXSEL_1)
-#define MX28_PAD_SAIF0_BITCLK__PWM_5			MXS_IOMUX_PAD_NAKED(3, 22, PAD_MUXSEL_1)
-#define MX28_PAD_SAIF0_SDATA0__PWM_6			MXS_IOMUX_PAD_NAKED(3, 23, PAD_MUXSEL_1)
-#define MX28_PAD_I2C0_SCL__TIMROT_ROTARYA		MXS_IOMUX_PAD_NAKED(3, 24, PAD_MUXSEL_1)
-#define MX28_PAD_I2C0_SDA__TIMROT_ROTARYB		MXS_IOMUX_PAD_NAKED(3, 25, PAD_MUXSEL_1)
-#define MX28_PAD_SAIF1_SDATA0__PWM_7			MXS_IOMUX_PAD_NAKED(3, 26, PAD_MUXSEL_1)
-#define MX28_PAD_LCD_RESET__LCD_VSYNC			MXS_IOMUX_PAD_NAKED(3, 30, PAD_MUXSEL_1)
-
-#define MX28_PAD_ENET0_MDC__GPMI_CE4N			MXS_IOMUX_PAD_NAKED(4,  0, PAD_MUXSEL_1)
-#define MX28_PAD_ENET0_MDIO__GPMI_CE5N			MXS_IOMUX_PAD_NAKED(4,  1, PAD_MUXSEL_1)
-#define MX28_PAD_ENET0_RX_EN__GPMI_CE6N			MXS_IOMUX_PAD_NAKED(4,  2, PAD_MUXSEL_1)
-#define MX28_PAD_ENET0_RXD0__GPMI_CE7N			MXS_IOMUX_PAD_NAKED(4,  3, PAD_MUXSEL_1)
-#define MX28_PAD_ENET0_RXD1__GPMI_READY4		MXS_IOMUX_PAD_NAKED(4,  4, PAD_MUXSEL_1)
-#define MX28_PAD_ENET0_TX_CLK__HSADC_TRIGGER		MXS_IOMUX_PAD_NAKED(4,  5, PAD_MUXSEL_1)
-#define MX28_PAD_ENET0_TX_EN__GPMI_READY5		MXS_IOMUX_PAD_NAKED(4,  6, PAD_MUXSEL_1)
-#define MX28_PAD_ENET0_TXD0__GPMI_READY6		MXS_IOMUX_PAD_NAKED(4,  7, PAD_MUXSEL_1)
-#define MX28_PAD_ENET0_TXD1__GPMI_READY7		MXS_IOMUX_PAD_NAKED(4,  8, PAD_MUXSEL_1)
-#define MX28_PAD_ENET0_RXD2__ENET1_RXD0			MXS_IOMUX_PAD_NAKED(4,  9, PAD_MUXSEL_1)
-#define MX28_PAD_ENET0_RXD3__ENET1_RXD1			MXS_IOMUX_PAD_NAKED(4, 10, PAD_MUXSEL_1)
-#define MX28_PAD_ENET0_TXD2__ENET1_TXD0			MXS_IOMUX_PAD_NAKED(4, 11, PAD_MUXSEL_1)
-#define MX28_PAD_ENET0_TXD3__ENET1_TXD1			MXS_IOMUX_PAD_NAKED(4, 12, PAD_MUXSEL_1)
-#define MX28_PAD_ENET0_RX_CLK__ENET0_RX_ER		MXS_IOMUX_PAD_NAKED(4, 13, PAD_MUXSEL_1)
-#define MX28_PAD_ENET0_COL__ENET1_TX_EN			MXS_IOMUX_PAD_NAKED(4, 14, PAD_MUXSEL_1)
-#define MX28_PAD_ENET0_CRS__ENET1_RX_EN			MXS_IOMUX_PAD_NAKED(4, 15, PAD_MUXSEL_1)
-
-/* MUXSEL_2 */
-#define MX28_PAD_GPMI_CE2N__ENET0_RX_ER			MXS_IOMUX_PAD_NAKED(0, 18, PAD_MUXSEL_2)
-#define MX28_PAD_GPMI_CE3N__SAIF1_MCLK			MXS_IOMUX_PAD_NAKED(0, 19, PAD_MUXSEL_2)
-#define MX28_PAD_GPMI_RDY0__USB0_ID			MXS_IOMUX_PAD_NAKED(0, 20, PAD_MUXSEL_2)
-#define MX28_PAD_GPMI_RDY2__ENET0_TX_ER			MXS_IOMUX_PAD_NAKED(0, 22, PAD_MUXSEL_2)
-#define MX28_PAD_GPMI_RDY3__HSADC_TRIGGER		MXS_IOMUX_PAD_NAKED(0, 23, PAD_MUXSEL_2)
-#define MX28_PAD_GPMI_ALE__SSP3_D4			MXS_IOMUX_PAD_NAKED(0, 26, PAD_MUXSEL_2)
-#define MX28_PAD_GPMI_CLE__SSP3_D5			MXS_IOMUX_PAD_NAKED(0, 27, PAD_MUXSEL_2)
-
-#define MX28_PAD_LCD_D00__ETM_DA0			MXS_IOMUX_PAD_NAKED(1,  0, PAD_MUXSEL_2)
-#define MX28_PAD_LCD_D01__ETM_DA1			MXS_IOMUX_PAD_NAKED(1,  1, PAD_MUXSEL_2)
-#define MX28_PAD_LCD_D02__ETM_DA2			MXS_IOMUX_PAD_NAKED(1,  2, PAD_MUXSEL_2)
-#define MX28_PAD_LCD_D03__ETM_DA3			MXS_IOMUX_PAD_NAKED(1,  3, PAD_MUXSEL_2)
-#define MX28_PAD_LCD_D04__ETM_DA4			MXS_IOMUX_PAD_NAKED(1,  4, PAD_MUXSEL_2)
-#define MX28_PAD_LCD_D05__ETM_DA5			MXS_IOMUX_PAD_NAKED(1,  5, PAD_MUXSEL_2)
-#define MX28_PAD_LCD_D06__ETM_DA6			MXS_IOMUX_PAD_NAKED(1,  6, PAD_MUXSEL_2)
-#define MX28_PAD_LCD_D07__ETM_DA7			MXS_IOMUX_PAD_NAKED(1,  7, PAD_MUXSEL_2)
-#define MX28_PAD_LCD_D08__ETM_DA8			MXS_IOMUX_PAD_NAKED(1,  8, PAD_MUXSEL_2)
-#define MX28_PAD_LCD_D09__ETM_DA9			MXS_IOMUX_PAD_NAKED(1,  9, PAD_MUXSEL_2)
-#define MX28_PAD_LCD_D10__ETM_DA10			MXS_IOMUX_PAD_NAKED(1, 10, PAD_MUXSEL_2)
-#define MX28_PAD_LCD_D11__ETM_DA11			MXS_IOMUX_PAD_NAKED(1, 11, PAD_MUXSEL_2)
-#define MX28_PAD_LCD_D12__ETM_DA12			MXS_IOMUX_PAD_NAKED(1, 12, PAD_MUXSEL_2)
-#define MX28_PAD_LCD_D13__ETM_DA13			MXS_IOMUX_PAD_NAKED(1, 13, PAD_MUXSEL_2)
-#define MX28_PAD_LCD_D14__ETM_DA14			MXS_IOMUX_PAD_NAKED(1, 14, PAD_MUXSEL_2)
-#define MX28_PAD_LCD_D15__ETM_DA15			MXS_IOMUX_PAD_NAKED(1, 15, PAD_MUXSEL_2)
-#define MX28_PAD_LCD_D16__ETM_DA7			MXS_IOMUX_PAD_NAKED(1, 16, PAD_MUXSEL_2)
-#define MX28_PAD_LCD_D17__ETM_DA6			MXS_IOMUX_PAD_NAKED(1, 17, PAD_MUXSEL_2)
-#define MX28_PAD_LCD_D18__ETM_DA5			MXS_IOMUX_PAD_NAKED(1, 18, PAD_MUXSEL_2)
-#define MX28_PAD_LCD_D19__ETM_DA4			MXS_IOMUX_PAD_NAKED(1, 19, PAD_MUXSEL_2)
-#define MX28_PAD_LCD_D20__ETM_DA3			MXS_IOMUX_PAD_NAKED(1, 20, PAD_MUXSEL_2)
-#define MX28_PAD_LCD_D21__ETM_DA2			MXS_IOMUX_PAD_NAKED(1, 21, PAD_MUXSEL_2)
-#define MX28_PAD_LCD_D22__ETM_DA1			MXS_IOMUX_PAD_NAKED(1, 22, PAD_MUXSEL_2)
-#define MX28_PAD_LCD_D23__ETM_DA0			MXS_IOMUX_PAD_NAKED(1, 23, PAD_MUXSEL_2)
-#define MX28_PAD_LCD_RD_E__ETM_TCTL			MXS_IOMUX_PAD_NAKED(1, 24, PAD_MUXSEL_2)
-#define MX28_PAD_LCD_WR_RWN__ETM_TCLK			MXS_IOMUX_PAD_NAKED(1, 25, PAD_MUXSEL_2)
-#define MX28_PAD_LCD_HSYNC__ETM_TCTL			MXS_IOMUX_PAD_NAKED(1, 29, PAD_MUXSEL_2)
-#define MX28_PAD_LCD_DOTCLK__ETM_TCLK			MXS_IOMUX_PAD_NAKED(1, 30, PAD_MUXSEL_2)
-
-#define MX28_PAD_SSP1_SCK__ENET0_1588_EVENT2_OUT	MXS_IOMUX_PAD_NAKED(2, 12, PAD_MUXSEL_2)
-#define MX28_PAD_SSP1_CMD__ENET0_1588_EVENT2_IN		MXS_IOMUX_PAD_NAKED(2, 13, PAD_MUXSEL_2)
-#define MX28_PAD_SSP1_DATA0__ENET0_1588_EVENT3_OUT	MXS_IOMUX_PAD_NAKED(2, 14, PAD_MUXSEL_2)
-#define MX28_PAD_SSP1_DATA3__ENET0_1588_EVENT3_IN	MXS_IOMUX_PAD_NAKED(2, 15, PAD_MUXSEL_2)
-#define MX28_PAD_SSP2_SCK__SAIF0_SDATA1			MXS_IOMUX_PAD_NAKED(2, 16, PAD_MUXSEL_2)
-#define MX28_PAD_SSP2_MOSI__SAIF0_SDATA2		MXS_IOMUX_PAD_NAKED(2, 17, PAD_MUXSEL_2)
-#define MX28_PAD_SSP2_MISO__SAIF1_SDATA1		MXS_IOMUX_PAD_NAKED(2, 18, PAD_MUXSEL_2)
-#define MX28_PAD_SSP2_SS0__SAIF1_SDATA2			MXS_IOMUX_PAD_NAKED(2, 19, PAD_MUXSEL_2)
-#define MX28_PAD_SSP2_SS1__USB1_OVERCURRENT		MXS_IOMUX_PAD_NAKED(2, 20, PAD_MUXSEL_2)
-#define MX28_PAD_SSP2_SS2__USB0_OVERCURRENT		MXS_IOMUX_PAD_NAKED(2, 21, PAD_MUXSEL_2)
-#define MX28_PAD_SSP3_SCK__ENET1_1588_EVENT0_OUT	MXS_IOMUX_PAD_NAKED(2, 24, PAD_MUXSEL_2)
-#define MX28_PAD_SSP3_MOSI__ENET1_1588_EVENT0_IN	MXS_IOMUX_PAD_NAKED(2, 25, PAD_MUXSEL_2)
-#define MX28_PAD_SSP3_MISO__ENET1_1588_EVENT1_OUT	MXS_IOMUX_PAD_NAKED(2, 26, PAD_MUXSEL_2)
-#define MX28_PAD_SSP3_SS0__ENET1_1588_EVENT1_IN		MXS_IOMUX_PAD_NAKED(2, 27, PAD_MUXSEL_2)
-
-#define MX28_PAD_AUART0_RX__DUART_CTS			MXS_IOMUX_PAD_NAKED(3,  0, PAD_MUXSEL_2)
-#define MX28_PAD_AUART0_TX__DUART_RTS			MXS_IOMUX_PAD_NAKED(3,  1, PAD_MUXSEL_2)
-#define MX28_PAD_AUART0_CTS__DUART_RX			MXS_IOMUX_PAD_NAKED(3,  2, PAD_MUXSEL_2)
-#define MX28_PAD_AUART0_RTS__DUART_TX			MXS_IOMUX_PAD_NAKED(3,  3, PAD_MUXSEL_2)
-#define MX28_PAD_AUART1_RX__PWM_0			MXS_IOMUX_PAD_NAKED(3,  4, PAD_MUXSEL_2)
-#define MX28_PAD_AUART1_TX__PWM_1			MXS_IOMUX_PAD_NAKED(3,  5, PAD_MUXSEL_2)
-#define MX28_PAD_AUART1_CTS__TIMROT_ROTARYA		MXS_IOMUX_PAD_NAKED(3,  6, PAD_MUXSEL_2)
-#define MX28_PAD_AUART1_RTS__TIMROT_ROTARYB		MXS_IOMUX_PAD_NAKED(3,  7, PAD_MUXSEL_2)
-#define MX28_PAD_AUART2_RX__SSP3_D4			MXS_IOMUX_PAD_NAKED(3,  8, PAD_MUXSEL_2)
-#define MX28_PAD_AUART2_TX__SSP3_D5			MXS_IOMUX_PAD_NAKED(3,  9, PAD_MUXSEL_2)
-#define MX28_PAD_AUART2_CTS__SAIF1_BITCLK		MXS_IOMUX_PAD_NAKED(3, 10, PAD_MUXSEL_2)
-#define MX28_PAD_AUART2_RTS__SAIF1_LRCLK		MXS_IOMUX_PAD_NAKED(3, 11, PAD_MUXSEL_2)
-#define MX28_PAD_AUART3_RX__ENET0_1588_EVENT0_OUT	MXS_IOMUX_PAD_NAKED(3, 12, PAD_MUXSEL_2)
-#define MX28_PAD_AUART3_TX__ENET0_1588_EVENT0_IN	MXS_IOMUX_PAD_NAKED(3, 13, PAD_MUXSEL_2)
-#define MX28_PAD_AUART3_CTS__ENET0_1588_EVENT1_OUT	MXS_IOMUX_PAD_NAKED(3, 14, PAD_MUXSEL_2)
-#define MX28_PAD_AUART3_RTS__ENET0_1588_EVENT1_IN	MXS_IOMUX_PAD_NAKED(3, 15, PAD_MUXSEL_2)
-#define MX28_PAD_PWM0__DUART_RX				MXS_IOMUX_PAD_NAKED(3, 16, PAD_MUXSEL_2)
-#define MX28_PAD_PWM1__DUART_TX				MXS_IOMUX_PAD_NAKED(3, 17, PAD_MUXSEL_2)
-#define MX28_PAD_PWM2__USB1_OVERCURRENT			MXS_IOMUX_PAD_NAKED(3, 18, PAD_MUXSEL_2)
-#define MX28_PAD_SAIF0_MCLK__AUART4_CTS			MXS_IOMUX_PAD_NAKED(3, 20, PAD_MUXSEL_2)
-#define MX28_PAD_SAIF0_LRCLK__AUART4_RTS		MXS_IOMUX_PAD_NAKED(3, 21, PAD_MUXSEL_2)
-#define MX28_PAD_SAIF0_BITCLK__AUART4_RX		MXS_IOMUX_PAD_NAKED(3, 22, PAD_MUXSEL_2)
-#define MX28_PAD_SAIF0_SDATA0__AUART4_TX		MXS_IOMUX_PAD_NAKED(3, 23, PAD_MUXSEL_2)
-#define MX28_PAD_I2C0_SCL__DUART_RX			MXS_IOMUX_PAD_NAKED(3, 24, PAD_MUXSEL_2)
-#define MX28_PAD_I2C0_SDA__DUART_TX			MXS_IOMUX_PAD_NAKED(3, 25, PAD_MUXSEL_2)
-#define MX28_PAD_SAIF1_SDATA0__SAIF0_SDATA1		MXS_IOMUX_PAD_NAKED(3, 26, PAD_MUXSEL_2)
-#define MX28_PAD_SPDIF__ENET1_RX_ER			MXS_IOMUX_PAD_NAKED(3, 27, PAD_MUXSEL_2)
-
-#define MX28_PAD_ENET0_MDC__SAIF0_SDATA1		MXS_IOMUX_PAD_NAKED(4,  0, PAD_MUXSEL_2)
-#define MX28_PAD_ENET0_MDIO__SAIF0_SDATA2		MXS_IOMUX_PAD_NAKED(4,  1, PAD_MUXSEL_2)
-#define MX28_PAD_ENET0_RX_EN__SAIF1_SDATA1		MXS_IOMUX_PAD_NAKED(4,  2, PAD_MUXSEL_2)
-#define MX28_PAD_ENET0_RXD0__SAIF1_SDATA2		MXS_IOMUX_PAD_NAKED(4,  3, PAD_MUXSEL_2)
-#define MX28_PAD_ENET0_TX_CLK__ENET0_1588_EVENT2_OUT	MXS_IOMUX_PAD_NAKED(4,  5, PAD_MUXSEL_2)
-#define MX28_PAD_ENET0_RXD2__ENET0_1588_EVENT0_OUT	MXS_IOMUX_PAD_NAKED(4,  9, PAD_MUXSEL_2)
-#define MX28_PAD_ENET0_RXD3__ENET0_1588_EVENT0_IN	MXS_IOMUX_PAD_NAKED(4, 10, PAD_MUXSEL_2)
-#define MX28_PAD_ENET0_TXD2__ENET0_1588_EVENT1_OUT	MXS_IOMUX_PAD_NAKED(4, 11, PAD_MUXSEL_2)
-#define MX28_PAD_ENET0_TXD3__ENET0_1588_EVENT1_IN	MXS_IOMUX_PAD_NAKED(4, 12, PAD_MUXSEL_2)
-#define MX28_PAD_ENET0_RX_CLK__ENET0_1588_EVENT2_IN	MXS_IOMUX_PAD_NAKED(4, 13, PAD_MUXSEL_2)
-#define MX28_PAD_ENET0_COL__ENET0_1588_EVENT3_OUT	MXS_IOMUX_PAD_NAKED(4, 14, PAD_MUXSEL_2)
-#define MX28_PAD_ENET0_CRS__ENET0_1588_EVENT3_IN	MXS_IOMUX_PAD_NAKED(4, 15, PAD_MUXSEL_2)
-
-/* MUXSEL_GPIO */
-#define MX28_PAD_GPMI_D00__GPIO_0_0			MXS_IOMUX_PAD_NAKED(0,  0, PAD_MUXSEL_GPIO)
-#define MX28_PAD_GPMI_D01__GPIO_0_1			MXS_IOMUX_PAD_NAKED(0,  1, PAD_MUXSEL_GPIO)
-#define MX28_PAD_GPMI_D02__GPIO_0_2			MXS_IOMUX_PAD_NAKED(0,  2, PAD_MUXSEL_GPIO)
-#define MX28_PAD_GPMI_D03__GPIO_0_3			MXS_IOMUX_PAD_NAKED(0,  3, PAD_MUXSEL_GPIO)
-#define MX28_PAD_GPMI_D04__GPIO_0_4			MXS_IOMUX_PAD_NAKED(0,  4, PAD_MUXSEL_GPIO)
-#define MX28_PAD_GPMI_D05__GPIO_0_5			MXS_IOMUX_PAD_NAKED(0,  5, PAD_MUXSEL_GPIO)
-#define MX28_PAD_GPMI_D06__GPIO_0_6			MXS_IOMUX_PAD_NAKED(0,  6, PAD_MUXSEL_GPIO)
-#define MX28_PAD_GPMI_D07__GPIO_0_7			MXS_IOMUX_PAD_NAKED(0,  7, PAD_MUXSEL_GPIO)
-#define MX28_PAD_GPMI_CE0N__GPIO_0_16			MXS_IOMUX_PAD_NAKED(0, 16, PAD_MUXSEL_GPIO)
-#define MX28_PAD_GPMI_CE1N__GPIO_0_17			MXS_IOMUX_PAD_NAKED(0, 17, PAD_MUXSEL_GPIO)
-#define MX28_PAD_GPMI_CE2N__GPIO_0_18			MXS_IOMUX_PAD_NAKED(0, 18, PAD_MUXSEL_GPIO)
-#define MX28_PAD_GPMI_CE3N__GPIO_0_19			MXS_IOMUX_PAD_NAKED(0, 19, PAD_MUXSEL_GPIO)
-#define MX28_PAD_GPMI_RDY0__GPIO_0_20			MXS_IOMUX_PAD_NAKED(0, 20, PAD_MUXSEL_GPIO)
-#define MX28_PAD_GPMI_RDY1__GPIO_0_21			MXS_IOMUX_PAD_NAKED(0, 21, PAD_MUXSEL_GPIO)
-#define MX28_PAD_GPMI_RDY2__GPIO_0_22			MXS_IOMUX_PAD_NAKED(0, 22, PAD_MUXSEL_GPIO)
-#define MX28_PAD_GPMI_RDY3__GPIO_0_23			MXS_IOMUX_PAD_NAKED(0, 23, PAD_MUXSEL_GPIO)
-#define MX28_PAD_GPMI_RDN__GPIO_0_24			MXS_IOMUX_PAD_NAKED(0, 24, PAD_MUXSEL_GPIO)
-#define MX28_PAD_GPMI_WRN__GPIO_0_25			MXS_IOMUX_PAD_NAKED(0, 25, PAD_MUXSEL_GPIO)
-#define MX28_PAD_GPMI_ALE__GPIO_0_26			MXS_IOMUX_PAD_NAKED(0, 26, PAD_MUXSEL_GPIO)
-#define MX28_PAD_GPMI_CLE__GPIO_0_27			MXS_IOMUX_PAD_NAKED(0, 27, PAD_MUXSEL_GPIO)
-#define MX28_PAD_GPMI_RESETN__GPIO_0_28			MXS_IOMUX_PAD_NAKED(0, 28, PAD_MUXSEL_GPIO)
-
-#define MX28_PAD_LCD_D00__GPIO_1_0			MXS_IOMUX_PAD_NAKED(1,  0, PAD_MUXSEL_GPIO)
-#define MX28_PAD_LCD_D01__GPIO_1_1			MXS_IOMUX_PAD_NAKED(1,  1, PAD_MUXSEL_GPIO)
-#define MX28_PAD_LCD_D02__GPIO_1_2			MXS_IOMUX_PAD_NAKED(1,  2, PAD_MUXSEL_GPIO)
-#define MX28_PAD_LCD_D03__GPIO_1_3			MXS_IOMUX_PAD_NAKED(1,  3, PAD_MUXSEL_GPIO)
-#define MX28_PAD_LCD_D04__GPIO_1_4			MXS_IOMUX_PAD_NAKED(1,  4, PAD_MUXSEL_GPIO)
-#define MX28_PAD_LCD_D05__GPIO_1_5			MXS_IOMUX_PAD_NAKED(1,  5, PAD_MUXSEL_GPIO)
-#define MX28_PAD_LCD_D06__GPIO_1_6			MXS_IOMUX_PAD_NAKED(1,  6, PAD_MUXSEL_GPIO)
-#define MX28_PAD_LCD_D07__GPIO_1_7			MXS_IOMUX_PAD_NAKED(1,  7, PAD_MUXSEL_GPIO)
-#define MX28_PAD_LCD_D08__GPIO_1_8			MXS_IOMUX_PAD_NAKED(1,  8, PAD_MUXSEL_GPIO)
-#define MX28_PAD_LCD_D09__GPIO_1_9			MXS_IOMUX_PAD_NAKED(1,  9, PAD_MUXSEL_GPIO)
-#define MX28_PAD_LCD_D10__GPIO_1_10			MXS_IOMUX_PAD_NAKED(1, 10, PAD_MUXSEL_GPIO)
-#define MX28_PAD_LCD_D11__GPIO_1_11			MXS_IOMUX_PAD_NAKED(1, 11, PAD_MUXSEL_GPIO)
-#define MX28_PAD_LCD_D12__GPIO_1_12			MXS_IOMUX_PAD_NAKED(1, 12, PAD_MUXSEL_GPIO)
-#define MX28_PAD_LCD_D13__GPIO_1_13			MXS_IOMUX_PAD_NAKED(1, 13, PAD_MUXSEL_GPIO)
-#define MX28_PAD_LCD_D14__GPIO_1_14			MXS_IOMUX_PAD_NAKED(1, 14, PAD_MUXSEL_GPIO)
-#define MX28_PAD_LCD_D15__GPIO_1_15			MXS_IOMUX_PAD_NAKED(1, 15, PAD_MUXSEL_GPIO)
-#define MX28_PAD_LCD_D16__GPIO_1_16			MXS_IOMUX_PAD_NAKED(1, 16, PAD_MUXSEL_GPIO)
-#define MX28_PAD_LCD_D17__GPIO_1_17			MXS_IOMUX_PAD_NAKED(1, 17, PAD_MUXSEL_GPIO)
-#define MX28_PAD_LCD_D18__GPIO_1_18			MXS_IOMUX_PAD_NAKED(1, 18, PAD_MUXSEL_GPIO)
-#define MX28_PAD_LCD_D19__GPIO_1_19			MXS_IOMUX_PAD_NAKED(1, 19, PAD_MUXSEL_GPIO)
-#define MX28_PAD_LCD_D20__GPIO_1_20			MXS_IOMUX_PAD_NAKED(1, 20, PAD_MUXSEL_GPIO)
-#define MX28_PAD_LCD_D21__GPIO_1_21			MXS_IOMUX_PAD_NAKED(1, 21, PAD_MUXSEL_GPIO)
-#define MX28_PAD_LCD_D22__GPIO_1_22			MXS_IOMUX_PAD_NAKED(1, 22, PAD_MUXSEL_GPIO)
-#define MX28_PAD_LCD_D23__GPIO_1_23			MXS_IOMUX_PAD_NAKED(1, 23, PAD_MUXSEL_GPIO)
-#define MX28_PAD_LCD_RD_E__GPIO_1_24			MXS_IOMUX_PAD_NAKED(1, 24, PAD_MUXSEL_GPIO)
-#define MX28_PAD_LCD_WR_RWN__GPIO_1_25			MXS_IOMUX_PAD_NAKED(1, 25, PAD_MUXSEL_GPIO)
-#define MX28_PAD_LCD_RS__GPIO_1_26			MXS_IOMUX_PAD_NAKED(1, 26, PAD_MUXSEL_GPIO)
-#define MX28_PAD_LCD_CS__GPIO_1_27			MXS_IOMUX_PAD_NAKED(1, 27, PAD_MUXSEL_GPIO)
-#define MX28_PAD_LCD_VSYNC__GPIO_1_28			MXS_IOMUX_PAD_NAKED(1, 28, PAD_MUXSEL_GPIO)
-#define MX28_PAD_LCD_HSYNC__GPIO_1_29			MXS_IOMUX_PAD_NAKED(1, 29, PAD_MUXSEL_GPIO)
-#define MX28_PAD_LCD_DOTCLK__GPIO_1_30			MXS_IOMUX_PAD_NAKED(1, 30, PAD_MUXSEL_GPIO)
-#define MX28_PAD_LCD_ENABLE__GPIO_1_31			MXS_IOMUX_PAD_NAKED(1, 31, PAD_MUXSEL_GPIO)
-
-#define MX28_PAD_SSP0_DATA0__GPIO_2_0			MXS_IOMUX_PAD_NAKED(2,  0, PAD_MUXSEL_GPIO)
-#define MX28_PAD_SSP0_DATA1__GPIO_2_1			MXS_IOMUX_PAD_NAKED(2,  1, PAD_MUXSEL_GPIO)
-#define MX28_PAD_SSP0_DATA2__GPIO_2_2			MXS_IOMUX_PAD_NAKED(2,  2, PAD_MUXSEL_GPIO)
-#define MX28_PAD_SSP0_DATA3__GPIO_2_3			MXS_IOMUX_PAD_NAKED(2,  3, PAD_MUXSEL_GPIO)
-#define MX28_PAD_SSP0_DATA4__GPIO_2_4			MXS_IOMUX_PAD_NAKED(2,  4, PAD_MUXSEL_GPIO)
-#define MX28_PAD_SSP0_DATA5__GPIO_2_5			MXS_IOMUX_PAD_NAKED(2,  5, PAD_MUXSEL_GPIO)
-#define MX28_PAD_SSP0_DATA6__GPIO_2_6			MXS_IOMUX_PAD_NAKED(2,  6, PAD_MUXSEL_GPIO)
-#define MX28_PAD_SSP0_DATA7__GPIO_2_7			MXS_IOMUX_PAD_NAKED(2,  7, PAD_MUXSEL_GPIO)
-#define MX28_PAD_SSP0_CMD__GPIO_2_8			MXS_IOMUX_PAD_NAKED(2,  8, PAD_MUXSEL_GPIO)
-#define MX28_PAD_SSP0_DETECT__GPIO_2_9			MXS_IOMUX_PAD_NAKED(2,  9, PAD_MUXSEL_GPIO)
-#define MX28_PAD_SSP0_SCK__GPIO_2_10			MXS_IOMUX_PAD_NAKED(2, 10, PAD_MUXSEL_GPIO)
-#define MX28_PAD_SSP1_SCK__GPIO_2_12			MXS_IOMUX_PAD_NAKED(2, 12, PAD_MUXSEL_GPIO)
-#define MX28_PAD_SSP1_CMD__GPIO_2_13			MXS_IOMUX_PAD_NAKED(2, 13, PAD_MUXSEL_GPIO)
-#define MX28_PAD_SSP1_DATA0__GPIO_2_14			MXS_IOMUX_PAD_NAKED(2, 14, PAD_MUXSEL_GPIO)
-#define MX28_PAD_SSP1_DATA3__GPIO_2_15			MXS_IOMUX_PAD_NAKED(2, 15, PAD_MUXSEL_GPIO)
-#define MX28_PAD_SSP2_SCK__GPIO_2_16			MXS_IOMUX_PAD_NAKED(2, 16, PAD_MUXSEL_GPIO)
-#define MX28_PAD_SSP2_MOSI__GPIO_2_17			MXS_IOMUX_PAD_NAKED(2, 17, PAD_MUXSEL_GPIO)
-#define MX28_PAD_SSP2_MISO__GPIO_2_18			MXS_IOMUX_PAD_NAKED(2, 18, PAD_MUXSEL_GPIO)
-#define MX28_PAD_SSP2_SS0__GPIO_2_19			MXS_IOMUX_PAD_NAKED(2, 19, PAD_MUXSEL_GPIO)
-#define MX28_PAD_SSP2_SS1__GPIO_2_20			MXS_IOMUX_PAD_NAKED(2, 20, PAD_MUXSEL_GPIO)
-#define MX28_PAD_SSP2_SS2__GPIO_2_21			MXS_IOMUX_PAD_NAKED(2, 21, PAD_MUXSEL_GPIO)
-#define MX28_PAD_SSP3_SCK__GPIO_2_24			MXS_IOMUX_PAD_NAKED(2, 24, PAD_MUXSEL_GPIO)
-#define MX28_PAD_SSP3_MOSI__GPIO_2_25			MXS_IOMUX_PAD_NAKED(2, 25, PAD_MUXSEL_GPIO)
-#define MX28_PAD_SSP3_MISO__GPIO_2_26			MXS_IOMUX_PAD_NAKED(2, 26, PAD_MUXSEL_GPIO)
-#define MX28_PAD_SSP3_SS0__GPIO_2_27			MXS_IOMUX_PAD_NAKED(2, 27, PAD_MUXSEL_GPIO)
-
-#define MX28_PAD_AUART0_RX__GPIO_3_0			MXS_IOMUX_PAD_NAKED(3,  0, PAD_MUXSEL_GPIO)
-#define MX28_PAD_AUART0_TX__GPIO_3_1			MXS_IOMUX_PAD_NAKED(3,  1, PAD_MUXSEL_GPIO)
-#define MX28_PAD_AUART0_CTS__GPIO_3_2			MXS_IOMUX_PAD_NAKED(3,  2, PAD_MUXSEL_GPIO)
-#define MX28_PAD_AUART0_RTS__GPIO_3_3			MXS_IOMUX_PAD_NAKED(3,  3, PAD_MUXSEL_GPIO)
-#define MX28_PAD_AUART1_RX__GPIO_3_4			MXS_IOMUX_PAD_NAKED(3,  4, PAD_MUXSEL_GPIO)
-#define MX28_PAD_AUART1_TX__GPIO_3_5			MXS_IOMUX_PAD_NAKED(3,  5, PAD_MUXSEL_GPIO)
-#define MX28_PAD_AUART1_CTS__GPIO_3_6			MXS_IOMUX_PAD_NAKED(3,  6, PAD_MUXSEL_GPIO)
-#define MX28_PAD_AUART1_RTS__GPIO_3_7			MXS_IOMUX_PAD_NAKED(3,  7, PAD_MUXSEL_GPIO)
-#define MX28_PAD_AUART2_RX__GPIO_3_8			MXS_IOMUX_PAD_NAKED(3,  8, PAD_MUXSEL_GPIO)
-#define MX28_PAD_AUART2_TX__GPIO_3_9			MXS_IOMUX_PAD_NAKED(3,  9, PAD_MUXSEL_GPIO)
-#define MX28_PAD_AUART2_CTS__GPIO_3_10			MXS_IOMUX_PAD_NAKED(3, 10, PAD_MUXSEL_GPIO)
-#define MX28_PAD_AUART2_RTS__GPIO_3_11			MXS_IOMUX_PAD_NAKED(3, 11, PAD_MUXSEL_GPIO)
-#define MX28_PAD_AUART3_RX__GPIO_3_12			MXS_IOMUX_PAD_NAKED(3, 12, PAD_MUXSEL_GPIO)
-#define MX28_PAD_AUART3_TX__GPIO_3_13			MXS_IOMUX_PAD_NAKED(3, 13, PAD_MUXSEL_GPIO)
-#define MX28_PAD_AUART3_CTS__GPIO_3_14			MXS_IOMUX_PAD_NAKED(3, 14, PAD_MUXSEL_GPIO)
-#define MX28_PAD_AUART3_RTS__GPIO_3_15			MXS_IOMUX_PAD_NAKED(3, 15, PAD_MUXSEL_GPIO)
-#define MX28_PAD_PWM0__GPIO_3_16			MXS_IOMUX_PAD_NAKED(3, 16, PAD_MUXSEL_GPIO)
-#define MX28_PAD_PWM1__GPIO_3_17			MXS_IOMUX_PAD_NAKED(3, 17, PAD_MUXSEL_GPIO)
-#define MX28_PAD_PWM2__GPIO_3_18			MXS_IOMUX_PAD_NAKED(3, 18, PAD_MUXSEL_GPIO)
-#define MX28_PAD_SAIF0_MCLK__GPIO_3_20			MXS_IOMUX_PAD_NAKED(3, 20, PAD_MUXSEL_GPIO)
-#define MX28_PAD_SAIF0_LRCLK__GPIO_3_21			MXS_IOMUX_PAD_NAKED(3, 21, PAD_MUXSEL_GPIO)
-#define MX28_PAD_SAIF0_BITCLK__GPIO_3_22		MXS_IOMUX_PAD_NAKED(3, 22, PAD_MUXSEL_GPIO)
-#define MX28_PAD_SAIF0_SDATA0__GPIO_3_23		MXS_IOMUX_PAD_NAKED(3, 23, PAD_MUXSEL_GPIO)
-#define MX28_PAD_I2C0_SCL__GPIO_3_24			MXS_IOMUX_PAD_NAKED(3, 24, PAD_MUXSEL_GPIO)
-#define MX28_PAD_I2C0_SDA__GPIO_3_25			MXS_IOMUX_PAD_NAKED(3, 25, PAD_MUXSEL_GPIO)
-#define MX28_PAD_SAIF1_SDATA0__GPIO_3_26		MXS_IOMUX_PAD_NAKED(3, 26, PAD_MUXSEL_GPIO)
-#define MX28_PAD_SPDIF__GPIO_3_27			MXS_IOMUX_PAD_NAKED(3, 27, PAD_MUXSEL_GPIO)
-#define MX28_PAD_PWM3__GPIO_3_28			MXS_IOMUX_PAD_NAKED(3, 28, PAD_MUXSEL_GPIO)
-#define MX28_PAD_PWM4__GPIO_3_29			MXS_IOMUX_PAD_NAKED(3, 29, PAD_MUXSEL_GPIO)
-#define MX28_PAD_LCD_RESET__GPIO_3_30			MXS_IOMUX_PAD_NAKED(3, 30, PAD_MUXSEL_GPIO)
-
-#define MX28_PAD_ENET0_MDC__GPIO_4_0			MXS_IOMUX_PAD_NAKED(4,  0, PAD_MUXSEL_GPIO)
-#define MX28_PAD_ENET0_MDIO__GPIO_4_1			MXS_IOMUX_PAD_NAKED(4,  1, PAD_MUXSEL_GPIO)
-#define MX28_PAD_ENET0_RX_EN__GPIO_4_2			MXS_IOMUX_PAD_NAKED(4,  2, PAD_MUXSEL_GPIO)
-#define MX28_PAD_ENET0_RXD0__GPIO_4_3			MXS_IOMUX_PAD_NAKED(4,  3, PAD_MUXSEL_GPIO)
-#define MX28_PAD_ENET0_RXD1__GPIO_4_4			MXS_IOMUX_PAD_NAKED(4,  4, PAD_MUXSEL_GPIO)
-#define MX28_PAD_ENET0_TX_CLK__GPIO_4_5			MXS_IOMUX_PAD_NAKED(4,  5, PAD_MUXSEL_GPIO)
-#define MX28_PAD_ENET0_TX_EN__GPIO_4_6			MXS_IOMUX_PAD_NAKED(4,  6, PAD_MUXSEL_GPIO)
-#define MX28_PAD_ENET0_TXD0__GPIO_4_7			MXS_IOMUX_PAD_NAKED(4,  7, PAD_MUXSEL_GPIO)
-#define MX28_PAD_ENET0_TXD1__GPIO_4_8			MXS_IOMUX_PAD_NAKED(4,  8, PAD_MUXSEL_GPIO)
-#define MX28_PAD_ENET0_RXD2__GPIO_4_9			MXS_IOMUX_PAD_NAKED(4,  9, PAD_MUXSEL_GPIO)
-#define MX28_PAD_ENET0_RXD3__GPIO_4_10			MXS_IOMUX_PAD_NAKED(4, 10, PAD_MUXSEL_GPIO)
-#define MX28_PAD_ENET0_TXD2__GPIO_4_11			MXS_IOMUX_PAD_NAKED(4, 11, PAD_MUXSEL_GPIO)
-#define MX28_PAD_ENET0_TXD3__GPIO_4_12			MXS_IOMUX_PAD_NAKED(4, 12, PAD_MUXSEL_GPIO)
-#define MX28_PAD_ENET0_RX_CLK__GPIO_4_13		MXS_IOMUX_PAD_NAKED(4, 13, PAD_MUXSEL_GPIO)
-#define MX28_PAD_ENET0_COL__GPIO_4_14			MXS_IOMUX_PAD_NAKED(4, 14, PAD_MUXSEL_GPIO)
-#define MX28_PAD_ENET0_CRS__GPIO_4_15			MXS_IOMUX_PAD_NAKED(4, 15, PAD_MUXSEL_GPIO)
-#define MX28_PAD_ENET_CLK__GPIO_4_16			MXS_IOMUX_PAD_NAKED(4, 16, PAD_MUXSEL_GPIO)
-#define MX28_PAD_JTAG_RTCK__GPIO_4_20			MXS_IOMUX_PAD_NAKED(4, 20, PAD_MUXSEL_GPIO)
-
-#endif /* __MACH_IOMUX_MX28_H__ */
diff --git a/arch/arm/mach-mxs/include/mach/iomux.h b/arch/arm/mach-mxs/include/mach/iomux.h
deleted file mode 100644
index 7abdf58..0000000
--- a/arch/arm/mach-mxs/include/mach/iomux.h
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * Copyright (C) 2009 by Jan Weitzel Phytec Messtechnik GmbH,
- *			<armlinux@phytec.de>
- * Copyright (C) 2010 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
- * 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 __MACH_MXS_IOMUX_H__
-#define __MACH_MXS_IOMUX_H__
-
-/*
- * IOMUX/PAD Bit field definitions
- *
- * PAD_BANK:		 0..2	(3)
- * PAD_PIN:		 3..7	(5)
- * PAD_MUXSEL:		 8..9	(2)
- * PAD_MA:		10..11	(2)
- * PAD_MA_VALID:	12	(1)
- * PAD_VOL:		13	(1)
- * PAD_VOL_VALID:	14	(1)
- * PAD_PULL:		15	(1)
- * PAD_PULL_VALID:	16	(1)
- * RESERVED:		17..31	(15)
- */
-typedef u32 iomux_cfg_t;
-
-#define MXS_PAD_BANK_SHIFT	0
-#define MXS_PAD_BANK_MASK	((iomux_cfg_t)0x7 << MXS_PAD_BANK_SHIFT)
-#define MXS_PAD_PIN_SHIFT	3
-#define MXS_PAD_PIN_MASK	((iomux_cfg_t)0x1f << MXS_PAD_PIN_SHIFT)
-#define MXS_PAD_MUXSEL_SHIFT	8
-#define MXS_PAD_MUXSEL_MASK	((iomux_cfg_t)0x3 << MXS_PAD_MUXSEL_SHIFT)
-#define MXS_PAD_MA_SHIFT	10
-#define MXS_PAD_MA_MASK		((iomux_cfg_t)0x3 << MXS_PAD_MA_SHIFT)
-#define MXS_PAD_MA_VALID_SHIFT	12
-#define MXS_PAD_MA_VALID_MASK	((iomux_cfg_t)0x1 << MXS_PAD_MA_VALID_SHIFT)
-#define MXS_PAD_VOL_SHIFT	13
-#define MXS_PAD_VOL_MASK	((iomux_cfg_t)0x1 << MXS_PAD_VOL_SHIFT)
-#define MXS_PAD_VOL_VALID_SHIFT	14
-#define MXS_PAD_VOL_VALID_MASK	((iomux_cfg_t)0x1 << MXS_PAD_VOL_VALID_SHIFT)
-#define MXS_PAD_PULL_SHIFT	15
-#define MXS_PAD_PULL_MASK	((iomux_cfg_t)0x1 << MXS_PAD_PULL_SHIFT)
-#define MXS_PAD_PULL_VALID_SHIFT 16
-#define MXS_PAD_PULL_VALID_MASK	((iomux_cfg_t)0x1 << MXS_PAD_PULL_VALID_SHIFT)
-
-#define PAD_MUXSEL_0		0
-#define PAD_MUXSEL_1		1
-#define PAD_MUXSEL_2		2
-#define PAD_MUXSEL_GPIO		3
-
-#define PAD_4MA			0
-#define PAD_8MA			1
-#define PAD_12MA		2
-#define PAD_16MA		3
-
-#define PAD_1V8			0
-#define PAD_3V3			1
-
-#define PAD_NOPULL		0
-#define PAD_PULLUP		1
-
-#define MXS_PAD_4MA	((PAD_4MA << MXS_PAD_MA_SHIFT) | \
-					MXS_PAD_MA_VALID_MASK)
-#define MXS_PAD_8MA	((PAD_8MA << MXS_PAD_MA_SHIFT) | \
-					MXS_PAD_MA_VALID_MASK)
-#define MXS_PAD_12MA	((PAD_12MA << MXS_PAD_MA_SHIFT) | \
-					MXS_PAD_MA_VALID_MASK)
-#define MXS_PAD_16MA	((PAD_16MA << MXS_PAD_MA_SHIFT) | \
-					MXS_PAD_MA_VALID_MASK)
-
-#define MXS_PAD_1V8	((PAD_1V8 << MXS_PAD_VOL_SHIFT) | \
-					MXS_PAD_VOL_VALID_MASK)
-#define MXS_PAD_3V3	((PAD_3V3 << MXS_PAD_VOL_SHIFT) | \
-					MXS_PAD_VOL_VALID_MASK)
-
-#define MXS_PAD_NOPULL	((PAD_NOPULL << MXS_PAD_PULL_SHIFT) | \
-					MXS_PAD_PULL_VALID_MASK)
-#define MXS_PAD_PULLUP	((PAD_PULLUP << MXS_PAD_PULL_SHIFT) | \
-					MXS_PAD_PULL_VALID_MASK)
-
-/* generic pad control used in most cases */
-#define MXS_PAD_CTRL	(MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL)
-
-#define MXS_IOMUX_PAD(_bank, _pin, _muxsel, _ma, _vol, _pull)		\
-		(((iomux_cfg_t)(_bank) << MXS_PAD_BANK_SHIFT) |		\
-		((iomux_cfg_t)(_pin) << MXS_PAD_PIN_SHIFT) |		\
-		((iomux_cfg_t)(_muxsel) << MXS_PAD_MUXSEL_SHIFT) |	\
-		((iomux_cfg_t)(_ma) << MXS_PAD_MA_SHIFT) |		\
-		((iomux_cfg_t)(_vol) << MXS_PAD_VOL_SHIFT) |		\
-		((iomux_cfg_t)(_pull) << MXS_PAD_PULL_SHIFT))
-
-/*
- * A pad becomes naked, when none of mA, vol or pull
- * validity bits is set.
- */
-#define MXS_IOMUX_PAD_NAKED(_bank, _pin, _muxsel) \
-		MXS_IOMUX_PAD(_bank, _pin, _muxsel, 0, 0, 0)
-
-static inline unsigned int PAD_BANK(iomux_cfg_t pad)
-{
-	return (pad & MXS_PAD_BANK_MASK) >> MXS_PAD_BANK_SHIFT;
-}
-
-static inline unsigned int PAD_PIN(iomux_cfg_t pad)
-{
-	return (pad & MXS_PAD_PIN_MASK) >> MXS_PAD_PIN_SHIFT;
-}
-
-static inline unsigned int PAD_MUXSEL(iomux_cfg_t pad)
-{
-	return (pad & MXS_PAD_MUXSEL_MASK) >> MXS_PAD_MUXSEL_SHIFT;
-}
-
-static inline unsigned int PAD_MA(iomux_cfg_t pad)
-{
-	return (pad & MXS_PAD_MA_MASK) >> MXS_PAD_MA_SHIFT;
-}
-
-static inline unsigned int PAD_MA_VALID(iomux_cfg_t pad)
-{
-	return (pad & MXS_PAD_MA_VALID_MASK) >> MXS_PAD_MA_VALID_SHIFT;
-}
-
-static inline unsigned int PAD_VOL(iomux_cfg_t pad)
-{
-	return (pad & MXS_PAD_VOL_MASK) >> MXS_PAD_VOL_SHIFT;
-}
-
-static inline unsigned int PAD_VOL_VALID(iomux_cfg_t pad)
-{
-	return (pad & MXS_PAD_VOL_VALID_MASK) >> MXS_PAD_VOL_VALID_SHIFT;
-}
-
-static inline unsigned int PAD_PULL(iomux_cfg_t pad)
-{
-	return (pad & MXS_PAD_PULL_MASK) >> MXS_PAD_PULL_SHIFT;
-}
-
-static inline unsigned int PAD_PULL_VALID(iomux_cfg_t pad)
-{
-	return (pad & MXS_PAD_PULL_VALID_MASK) >> MXS_PAD_PULL_VALID_SHIFT;
-}
-
-/*
- * configures a single pad in the iomuxer
- */
-int mxs_iomux_setup_pad(iomux_cfg_t pad);
-
-/*
- * configures multiple pads
- * convenient way to call the above function with tables
- */
-int mxs_iomux_setup_multiple_pads(const iomux_cfg_t *pad_list, unsigned count);
-
-#endif /* __MACH_MXS_IOMUX_H__*/
diff --git a/arch/arm/mach-mxs/include/mach/irqs.h b/arch/arm/mach-mxs/include/mach/irqs.h
deleted file mode 100644
index f771039..0000000
--- a/arch/arm/mach-mxs/include/mach/irqs.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- *  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 __MACH_MXS_IRQS_H__
-#define __MACH_MXS_IRQS_H__
-
-#define MXS_INTERNAL_IRQS	128
-
-#define MXS_GPIO_IRQ_START	MXS_INTERNAL_IRQS
-
-/* the maximum for MXS-based */
-#define MXS_GPIO_IRQS		(32 * 5)
-
-/*
- * The next 16 interrupts are for board specific purposes.  Since
- * the kernel can only run on one machine at a time, we can re-use
- * these.  If you need more, increase MXS_BOARD_IRQS, but keep it
- * within sensible limits.
- */
-#define MXS_BOARD_IRQ_START	(MXS_GPIO_IRQ_START + MXS_GPIO_IRQS)
-#define MXS_BOARD_IRQS		16
-
-#define NR_IRQS			(MXS_BOARD_IRQ_START + MXS_BOARD_IRQS)
-
-#endif /* __MACH_MXS_IRQS_H__ */
diff --git a/arch/arm/mach-mxs/iomux.c b/arch/arm/mach-mxs/iomux.c
deleted file mode 100644
index 0e804e2..0000000
--- a/arch/arm/mach-mxs/iomux.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright 2004-2006,2010 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright (C) 2008 by Sascha Hauer <kernel@pengutronix.de>
- * Copyright (C) 2009 by Jan Weitzel Phytec Messtechnik GmbH,
- *                       <armlinux@phytec.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.
- */
-
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/gpio.h>
-
-#include <asm/mach/map.h>
-
-#include <mach/mxs.h>
-#include <mach/iomux.h>
-
-/*
- * configures a single pad in the iomuxer
- */
-int mxs_iomux_setup_pad(iomux_cfg_t pad)
-{
-	u32 reg, ofs, bp, bm;
-	void __iomem *iomux_base = MXS_IO_ADDRESS(MXS_PINCTRL_BASE_ADDR);
-
-	/* muxsel */
-	ofs = 0x100;
-	ofs += PAD_BANK(pad) * 0x20 + PAD_PIN(pad) / 16 * 0x10;
-	bp = PAD_PIN(pad) % 16 * 2;
-	bm = 0x3 << bp;
-	reg = __raw_readl(iomux_base + ofs);
-	reg &= ~bm;
-	reg |= PAD_MUXSEL(pad) << bp;
-	__raw_writel(reg, iomux_base + ofs);
-
-	/* drive */
-	ofs = cpu_is_mx23() ? 0x200 : 0x300;
-	ofs += PAD_BANK(pad) * 0x40 + PAD_PIN(pad) / 8 * 0x10;
-	/* mA */
-	if (PAD_MA_VALID(pad)) {
-		bp = PAD_PIN(pad) % 8 * 4;
-		bm = 0x3 << bp;
-		reg = __raw_readl(iomux_base + ofs);
-		reg &= ~bm;
-		reg |= PAD_MA(pad) << bp;
-		__raw_writel(reg, iomux_base + ofs);
-	}
-	/* vol */
-	if (PAD_VOL_VALID(pad)) {
-		bp = PAD_PIN(pad) % 8 * 4 + 2;
-		if (PAD_VOL(pad))
-			__mxs_setl(1 << bp, iomux_base + ofs);
-		else
-			__mxs_clrl(1 << bp, iomux_base + ofs);
-	}
-
-	/* pull */
-	if (PAD_PULL_VALID(pad)) {
-		ofs = cpu_is_mx23() ? 0x400 : 0x600;
-		ofs += PAD_BANK(pad) * 0x10;
-		bp = PAD_PIN(pad);
-		if (PAD_PULL(pad))
-			__mxs_setl(1 << bp, iomux_base + ofs);
-		else
-			__mxs_clrl(1 << bp, iomux_base + ofs);
-	}
-
-	return 0;
-}
-
-int mxs_iomux_setup_multiple_pads(const iomux_cfg_t *pad_list, unsigned count)
-{
-	const iomux_cfg_t *p = pad_list;
-	int i;
-	int ret;
-
-	for (i = 0; i < count; i++) {
-		ret = mxs_iomux_setup_pad(*p);
-		if (ret)
-			return ret;
-		p++;
-	}
-
-	return 0;
-}
diff --git a/arch/arm/mach-mxs/mach-apx4devkit.c b/arch/arm/mach-mxs/mach-apx4devkit.c
deleted file mode 100644
index f5f0617..0000000
--- a/arch/arm/mach-mxs/mach-apx4devkit.c
+++ /dev/null
@@ -1,273 +0,0 @@
-/*
- * Copyright (C) 2011-2012
- * Lauri Hintsala, Bluegiga, <lauri.hintsala@bluegiga.com>
- * Veli-Pekka Peltola, Bluegiga, <veli-pekka.peltola@bluegiga.com>
- *
- * based on: mach-mx28evk.c
- * Copyright 2010 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 as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/delay.h>
-#include <linux/platform_device.h>
-#include <linux/gpio.h>
-#include <linux/leds.h>
-#include <linux/clk.h>
-#include <linux/i2c.h>
-#include <linux/regulator/machine.h>
-#include <linux/regulator/fixed.h>
-#include <linux/micrel_phy.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-
-#include <mach/common.h>
-#include <mach/digctl.h>
-#include <mach/iomux-mx28.h>
-
-#include "devices-mx28.h"
-
-#define APX4DEVKIT_GPIO_USERLED	MXS_GPIO_NR(3, 28)
-
-static const iomux_cfg_t apx4devkit_pads[] __initconst = {
-	/* duart */
-	MX28_PAD_PWM0__DUART_RX | MXS_PAD_CTRL,
-	MX28_PAD_PWM1__DUART_TX | MXS_PAD_CTRL,
-
-	/* auart0 */
-	MX28_PAD_AUART0_RX__AUART0_RX | MXS_PAD_CTRL,
-	MX28_PAD_AUART0_TX__AUART0_TX | MXS_PAD_CTRL,
-	MX28_PAD_AUART0_CTS__AUART0_CTS | MXS_PAD_CTRL,
-	MX28_PAD_AUART0_RTS__AUART0_RTS | MXS_PAD_CTRL,
-
-	/* auart1 */
-	MX28_PAD_AUART1_RX__AUART1_RX | MXS_PAD_CTRL,
-	MX28_PAD_AUART1_TX__AUART1_TX | MXS_PAD_CTRL,
-
-	/* auart2 */
-	MX28_PAD_SSP2_SCK__AUART2_RX | MXS_PAD_CTRL,
-	MX28_PAD_SSP2_MOSI__AUART2_TX | MXS_PAD_CTRL,
-
-	/* auart3 */
-	MX28_PAD_SSP2_MISO__AUART3_RX | MXS_PAD_CTRL,
-	MX28_PAD_SSP2_SS0__AUART3_TX | MXS_PAD_CTRL,
-
-#define MXS_PAD_FEC	(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP)
-	/* fec0 */
-	MX28_PAD_ENET0_MDC__ENET0_MDC | MXS_PAD_FEC,
-	MX28_PAD_ENET0_MDIO__ENET0_MDIO | MXS_PAD_FEC,
-	MX28_PAD_ENET0_RX_EN__ENET0_RX_EN | MXS_PAD_FEC,
-	MX28_PAD_ENET0_RXD0__ENET0_RXD0 | MXS_PAD_FEC,
-	MX28_PAD_ENET0_RXD1__ENET0_RXD1 | MXS_PAD_FEC,
-	MX28_PAD_ENET0_TX_EN__ENET0_TX_EN | MXS_PAD_FEC,
-	MX28_PAD_ENET0_TXD0__ENET0_TXD0 | MXS_PAD_FEC,
-	MX28_PAD_ENET0_TXD1__ENET0_TXD1 | MXS_PAD_FEC,
-	MX28_PAD_ENET_CLK__CLKCTRL_ENET | MXS_PAD_FEC,
-
-	/* i2c */
-	MX28_PAD_I2C0_SCL__I2C0_SCL,
-	MX28_PAD_I2C0_SDA__I2C0_SDA,
-
-	/* mmc0 */
-	MX28_PAD_SSP0_DATA0__SSP0_D0 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_SSP0_DATA1__SSP0_D1 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_SSP0_DATA2__SSP0_D2 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_SSP0_DATA3__SSP0_D3 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_SSP0_DATA4__SSP0_D4 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_SSP0_DATA5__SSP0_D5 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_SSP0_DATA6__SSP0_D6 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_SSP0_DATA7__SSP0_D7 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_SSP0_CMD__SSP0_CMD |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_SSP0_DETECT__SSP0_CARD_DETECT |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
-	MX28_PAD_SSP0_SCK__SSP0_SCK |
-		(MXS_PAD_12MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
-
-	/* led */
-	MX28_PAD_PWM3__GPIO_3_28 | MXS_PAD_CTRL,
-
-	/* saif0 & saif1 */
-	MX28_PAD_SAIF0_MCLK__SAIF0_MCLK |
-		(MXS_PAD_12MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_SAIF0_LRCLK__SAIF0_LRCLK |
-		(MXS_PAD_12MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_SAIF0_BITCLK__SAIF0_BITCLK |
-		(MXS_PAD_12MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_SAIF0_SDATA0__SAIF0_SDATA0 |
-		(MXS_PAD_12MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_SAIF1_SDATA0__SAIF1_SDATA0 |
-		(MXS_PAD_12MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-};
-
-/* led */
-static const struct gpio_led apx4devkit_leds[] __initconst = {
-	{
-		.name = "user-led",
-		.default_trigger = "heartbeat",
-		.gpio = APX4DEVKIT_GPIO_USERLED,
-	},
-};
-
-static const struct gpio_led_platform_data apx4devkit_led_data __initconst = {
-	.leds = apx4devkit_leds,
-	.num_leds = ARRAY_SIZE(apx4devkit_leds),
-};
-
-static const struct fec_platform_data mx28_fec_pdata __initconst = {
-	.phy = PHY_INTERFACE_MODE_RMII,
-};
-
-static const struct mxs_mmc_platform_data apx4devkit_mmc_pdata __initconst = {
-	.wp_gpio = -EINVAL,
-	.flags = SLOTF_4_BIT_CAPABLE,
-};
-
-static const struct i2c_board_info apx4devkit_i2c_boardinfo[] __initconst = {
-	{ I2C_BOARD_INFO("sgtl5000", 0x0a) }, /* ASoC */
-	{ I2C_BOARD_INFO("pcf8563", 0x51) }, /* RTC */
-};
-
-#if defined(CONFIG_REGULATOR_FIXED_VOLTAGE) || \
-		defined(CONFIG_REGULATOR_FIXED_VOLTAGE_MODULE)
-static struct regulator_consumer_supply apx4devkit_audio_consumer_supplies[] = {
-	REGULATOR_SUPPLY("VDDA", "0-000a"),
-	REGULATOR_SUPPLY("VDDIO", "0-000a"),
-};
-
-static struct regulator_init_data apx4devkit_vdd_reg_init_data = {
-	.constraints	= {
-		.name	= "3V3",
-		.always_on = 1,
-	},
-	.consumer_supplies = apx4devkit_audio_consumer_supplies,
-	.num_consumer_supplies = ARRAY_SIZE(apx4devkit_audio_consumer_supplies),
-};
-
-static struct fixed_voltage_config apx4devkit_vdd_pdata = {
-	.supply_name	= "board-3V3",
-	.microvolts	= 3300000,
-	.gpio		= -EINVAL,
-	.enabled_at_boot = 1,
-	.init_data	= &apx4devkit_vdd_reg_init_data,
-};
-
-static struct platform_device apx4devkit_voltage_regulator = {
-	.name		= "reg-fixed-voltage",
-	.id		= -1,
-	.num_resources	= 0,
-	.dev		= {
-		.platform_data	= &apx4devkit_vdd_pdata,
-	},
-};
-
-static void __init apx4devkit_add_regulators(void)
-{
-	platform_device_register(&apx4devkit_voltage_regulator);
-}
-#else
-static void __init apx4devkit_add_regulators(void) {}
-#endif
-
-static const struct mxs_saif_platform_data
-			apx4devkit_mxs_saif_pdata[] __initconst = {
-	/* working on EXTMSTR0 mode (saif0 master, saif1 slave) */
-	{
-		.master_mode = 1,
-		.master_id = 0,
-	}, {
-		.master_mode = 0,
-		.master_id = 0,
-	},
-};
-
-static int apx4devkit_phy_fixup(struct phy_device *phy)
-{
-	phy->dev_flags |= MICREL_PHY_50MHZ_CLK;
-	return 0;
-}
-
-static void __init apx4devkit_fec_phy_clk_enable(void)
-{
-	struct clk *clk;
-
-	/* Enable fec phy clock */
-	clk = clk_get_sys("enet_out", NULL);
-	if (!IS_ERR(clk))
-		clk_prepare_enable(clk);
-}
-
-static void __init apx4devkit_init(void)
-{
-	mx28_soc_init();
-
-	mxs_iomux_setup_multiple_pads(apx4devkit_pads,
-			ARRAY_SIZE(apx4devkit_pads));
-
-	mx28_add_duart();
-	mx28_add_auart0();
-	mx28_add_auart1();
-	mx28_add_auart2();
-	mx28_add_auart3();
-
-	/*
-	 * Register fixup for the Micrel KS8031 PHY clock
-	 * (shares same ID with KS8051)
-	 */
-	phy_register_fixup_for_uid(PHY_ID_KS8051, MICREL_PHY_ID_MASK,
-			apx4devkit_phy_fixup);
-
-	apx4devkit_fec_phy_clk_enable();
-	mx28_add_fec(0, &mx28_fec_pdata);
-
-	mx28_add_mxs_mmc(0, &apx4devkit_mmc_pdata);
-
-	gpio_led_register_device(0, &apx4devkit_led_data);
-
-	mxs_saif_clkmux_select(MXS_DIGCTL_SAIF_CLKMUX_EXTMSTR0);
-	mx28_add_saif(0, &apx4devkit_mxs_saif_pdata[0]);
-	mx28_add_saif(1, &apx4devkit_mxs_saif_pdata[1]);
-
-	apx4devkit_add_regulators();
-
-	mx28_add_mxs_i2c(0);
-	i2c_register_board_info(0, apx4devkit_i2c_boardinfo,
-			ARRAY_SIZE(apx4devkit_i2c_boardinfo));
-
-	mxs_add_platform_device("mxs-sgtl5000", 0, NULL, 0, NULL, 0);
-}
-
-static void __init apx4devkit_timer_init(void)
-{
-	mx28_clocks_init();
-}
-
-static struct sys_timer apx4devkit_timer = {
-	.init	= apx4devkit_timer_init,
-};
-
-MACHINE_START(APX4DEVKIT, "Bluegiga APX4 Development Kit")
-	.map_io		= mx28_map_io,
-	.init_irq	= mx28_init_irq,
-	.timer		= &apx4devkit_timer,
-	.init_machine	= apx4devkit_init,
-	.restart	= mxs_restart,
-MACHINE_END
diff --git a/arch/arm/mach-mxs/mach-m28evk.c b/arch/arm/mach-mxs/mach-m28evk.c
deleted file mode 100644
index 4c00c87..0000000
--- a/arch/arm/mach-mxs/mach-m28evk.c
+++ /dev/null
@@ -1,366 +0,0 @@
-/*
- * Copyright (C) 2011
- * Stefano Babic, DENX Software Engineering, <sbabic@denx.de>
- *
- * based on: mach-mx28_evk.c
- * Copyright 2010 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 as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/delay.h>
-#include <linux/platform_device.h>
-#include <linux/gpio.h>
-#include <linux/leds.h>
-#include <linux/irq.h>
-#include <linux/clk.h>
-#include <linux/i2c.h>
-#include <linux/i2c/at24.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-
-#include <mach/common.h>
-#include <mach/iomux-mx28.h>
-
-#include "devices-mx28.h"
-
-#define M28EVK_GPIO_USERLED1	MXS_GPIO_NR(3, 16)
-#define M28EVK_GPIO_USERLED2	MXS_GPIO_NR(3, 17)
-
-#define MX28EVK_BL_ENABLE	MXS_GPIO_NR(3, 18)
-#define M28EVK_LCD_ENABLE	MXS_GPIO_NR(3, 28)
-
-#define MX28EVK_MMC0_WRITE_PROTECT	MXS_GPIO_NR(2, 12)
-#define MX28EVK_MMC1_WRITE_PROTECT	MXS_GPIO_NR(0, 28)
-
-static const iomux_cfg_t m28evk_pads[] __initconst = {
-	/* duart */
-	MX28_PAD_AUART0_CTS__DUART_RX | MXS_PAD_CTRL,
-	MX28_PAD_AUART0_RTS__DUART_TX | MXS_PAD_CTRL,
-
-	/* auart0 */
-	MX28_PAD_AUART0_RX__AUART0_RX | MXS_PAD_CTRL,
-	MX28_PAD_AUART0_TX__AUART0_TX | MXS_PAD_CTRL,
-
-	/* auart3 */
-	MX28_PAD_AUART3_RX__AUART3_RX | MXS_PAD_CTRL,
-	MX28_PAD_AUART3_TX__AUART3_TX | MXS_PAD_CTRL,
-	MX28_PAD_AUART3_CTS__AUART3_CTS | MXS_PAD_CTRL,
-	MX28_PAD_AUART3_RTS__AUART3_RTS | MXS_PAD_CTRL,
-
-#define MXS_PAD_FEC	(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP)
-	/* fec0 */
-	MX28_PAD_ENET0_MDC__ENET0_MDC | MXS_PAD_FEC,
-	MX28_PAD_ENET0_MDIO__ENET0_MDIO | MXS_PAD_FEC,
-	MX28_PAD_ENET0_RX_EN__ENET0_RX_EN | MXS_PAD_FEC,
-	MX28_PAD_ENET0_RXD0__ENET0_RXD0 | MXS_PAD_FEC,
-	MX28_PAD_ENET0_RXD1__ENET0_RXD1 | MXS_PAD_FEC,
-	MX28_PAD_ENET0_TX_EN__ENET0_TX_EN | MXS_PAD_FEC,
-	MX28_PAD_ENET0_TXD0__ENET0_TXD0 | MXS_PAD_FEC,
-	MX28_PAD_ENET0_TXD1__ENET0_TXD1 | MXS_PAD_FEC,
-	MX28_PAD_ENET_CLK__CLKCTRL_ENET | MXS_PAD_FEC,
-	/* fec1 */
-	MX28_PAD_ENET0_CRS__ENET1_RX_EN | MXS_PAD_FEC,
-	MX28_PAD_ENET0_RXD2__ENET1_RXD0 | MXS_PAD_FEC,
-	MX28_PAD_ENET0_RXD3__ENET1_RXD1 | MXS_PAD_FEC,
-	MX28_PAD_ENET0_COL__ENET1_TX_EN | MXS_PAD_FEC,
-	MX28_PAD_ENET0_TXD2__ENET1_TXD0 | MXS_PAD_FEC,
-	MX28_PAD_ENET0_TXD3__ENET1_TXD1 | MXS_PAD_FEC,
-
-	/* flexcan0 */
-	MX28_PAD_GPMI_RDY2__CAN0_TX,
-	MX28_PAD_GPMI_RDY3__CAN0_RX,
-
-	/* flexcan1 */
-	MX28_PAD_GPMI_CE2N__CAN1_TX,
-	MX28_PAD_GPMI_CE3N__CAN1_RX,
-
-	/* I2C */
-	MX28_PAD_I2C0_SCL__I2C0_SCL,
-	MX28_PAD_I2C0_SDA__I2C0_SDA,
-
-	/* mxsfb (lcdif) */
-	MX28_PAD_LCD_D00__LCD_D0 | MXS_PAD_CTRL,
-	MX28_PAD_LCD_D01__LCD_D1 | MXS_PAD_CTRL,
-	MX28_PAD_LCD_D02__LCD_D2 | MXS_PAD_CTRL,
-	MX28_PAD_LCD_D03__LCD_D3 | MXS_PAD_CTRL,
-	MX28_PAD_LCD_D04__LCD_D4 | MXS_PAD_CTRL,
-	MX28_PAD_LCD_D05__LCD_D5 | MXS_PAD_CTRL,
-	MX28_PAD_LCD_D06__LCD_D6 | MXS_PAD_CTRL,
-	MX28_PAD_LCD_D07__LCD_D7 | MXS_PAD_CTRL,
-	MX28_PAD_LCD_D08__LCD_D8 | MXS_PAD_CTRL,
-	MX28_PAD_LCD_D09__LCD_D9 | MXS_PAD_CTRL,
-	MX28_PAD_LCD_D10__LCD_D10 | MXS_PAD_CTRL,
-	MX28_PAD_LCD_D11__LCD_D11 | MXS_PAD_CTRL,
-	MX28_PAD_LCD_D12__LCD_D12 | MXS_PAD_CTRL,
-	MX28_PAD_LCD_D13__LCD_D13 | MXS_PAD_CTRL,
-	MX28_PAD_LCD_D14__LCD_D14 | MXS_PAD_CTRL,
-	MX28_PAD_LCD_D15__LCD_D15 | MXS_PAD_CTRL,
-	MX28_PAD_LCD_D16__LCD_D16 | MXS_PAD_CTRL,
-	MX28_PAD_LCD_D17__LCD_D17 | MXS_PAD_CTRL,
-	MX28_PAD_LCD_D18__LCD_D18 | MXS_PAD_CTRL,
-	MX28_PAD_LCD_D19__LCD_D19 | MXS_PAD_CTRL,
-	MX28_PAD_LCD_D20__LCD_D20 | MXS_PAD_CTRL,
-	MX28_PAD_LCD_D21__LCD_D21 | MXS_PAD_CTRL,
-	MX28_PAD_LCD_D22__LCD_D22 | MXS_PAD_CTRL,
-	MX28_PAD_LCD_D23__LCD_D23 | MXS_PAD_CTRL,
-
-	MX28_PAD_LCD_ENABLE__LCD_ENABLE	| MXS_PAD_CTRL,
-	MX28_PAD_LCD_DOTCLK__LCD_DOTCLK | MXS_PAD_CTRL,
-
-	/* mmc0 */
-	MX28_PAD_SSP0_DATA0__SSP0_D0 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_SSP0_DATA1__SSP0_D1 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_SSP0_DATA2__SSP0_D2 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_SSP0_DATA3__SSP0_D3 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_SSP0_DATA4__SSP0_D4 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_SSP0_DATA5__SSP0_D5 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_SSP0_DATA6__SSP0_D6 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_SSP0_DATA7__SSP0_D7 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_SSP0_CMD__SSP0_CMD |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_SSP0_DETECT__SSP0_CARD_DETECT |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
-	MX28_PAD_SSP0_SCK__SSP0_SCK |
-		(MXS_PAD_12MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
-
-	/* mmc1 */
-	MX28_PAD_GPMI_D00__SSP1_D0 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_GPMI_D01__SSP1_D1 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_GPMI_D02__SSP1_D2 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_GPMI_D03__SSP1_D3 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_GPMI_D04__SSP1_D4 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_GPMI_D05__SSP1_D5 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_GPMI_D06__SSP1_D6 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_GPMI_D07__SSP1_D7 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_GPMI_RDY1__SSP1_CMD |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_GPMI_RDY0__SSP1_CARD_DETECT |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
-	MX28_PAD_GPMI_WRN__SSP1_SCK |
-		(MXS_PAD_12MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
-	/* write protect */
-	MX28_PAD_GPMI_RESETN__GPIO_0_28 |
-		(MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
-	/* slot power enable */
-	MX28_PAD_PWM4__GPIO_3_29 |
-		(MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
-
-	/* led */
-	MX28_PAD_PWM0__GPIO_3_16 | MXS_PAD_CTRL,
-	MX28_PAD_PWM1__GPIO_3_17 | MXS_PAD_CTRL,
-
-	/* nand */
-	MX28_PAD_GPMI_D00__GPMI_D0 |
-		(MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_NOPULL),
-	MX28_PAD_GPMI_D01__GPMI_D1 |
-		(MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_NOPULL),
-	MX28_PAD_GPMI_D02__GPMI_D2 |
-		(MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_NOPULL),
-	MX28_PAD_GPMI_D03__GPMI_D3 |
-		(MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_NOPULL),
-	MX28_PAD_GPMI_D04__GPMI_D4 |
-		(MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_NOPULL),
-	MX28_PAD_GPMI_D05__GPMI_D5 |
-		(MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_NOPULL),
-	MX28_PAD_GPMI_D06__GPMI_D6 |
-		(MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_NOPULL),
-	MX28_PAD_GPMI_D07__GPMI_D7 |
-		(MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_NOPULL),
-	MX28_PAD_GPMI_CE0N__GPMI_CE0N |
-		(MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_NOPULL),
-	MX28_PAD_GPMI_RDY0__GPMI_READY0 |
-		(MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_NOPULL),
-	MX28_PAD_GPMI_RDN__GPMI_RDN |
-		(MXS_PAD_12MA | MXS_PAD_1V8 | MXS_PAD_PULLUP),
-	MX28_PAD_GPMI_WRN__GPMI_WRN |
-		(MXS_PAD_12MA | MXS_PAD_1V8 | MXS_PAD_PULLUP),
-	MX28_PAD_GPMI_ALE__GPMI_ALE |
-		(MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_PULLUP),
-	MX28_PAD_GPMI_CLE__GPMI_CLE |
-		(MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_PULLUP),
-	MX28_PAD_GPMI_RESETN__GPMI_RESETN |
-		(MXS_PAD_12MA | MXS_PAD_1V8 | MXS_PAD_PULLUP),
-
-	/* Backlight */
-	MX28_PAD_PWM3__GPIO_3_28 | MXS_PAD_CTRL,
-};
-
-/* led */
-static const struct gpio_led m28evk_leds[] __initconst = {
-	{
-		.name = "user-led1",
-		.default_trigger = "heartbeat",
-		.gpio = M28EVK_GPIO_USERLED1,
-	},
-	{
-		.name = "user-led2",
-		.default_trigger = "heartbeat",
-		.gpio = M28EVK_GPIO_USERLED2,
-	},
-};
-
-static const struct gpio_led_platform_data m28evk_led_data __initconst = {
-	.leds = m28evk_leds,
-	.num_leds = ARRAY_SIZE(m28evk_leds),
-};
-
-static struct fec_platform_data mx28_fec_pdata[] __initdata = {
-	{
-		/* fec0 */
-		.phy = PHY_INTERFACE_MODE_RMII,
-	}, {
-		/* fec1 */
-		.phy = PHY_INTERFACE_MODE_RMII,
-	},
-};
-
-static int __init m28evk_fec_get_mac(void)
-{
-	int i;
-	u32 val;
-	const u32 *ocotp = mxs_get_ocotp();
-
-	if (!ocotp)
-		return -ETIMEDOUT;
-
-	/*
-	 * OCOTP only stores the last 4 octets for each mac address,
-	 * so hard-code DENX OUI (C0:E5:4E) here.
-	 */
-	for (i = 0; i < 2; i++) {
-		val = ocotp[i];
-		mx28_fec_pdata[i].mac[0] = 0xC0;
-		mx28_fec_pdata[i].mac[1] = 0xE5;
-		mx28_fec_pdata[i].mac[2] = 0x4E;
-		mx28_fec_pdata[i].mac[3] = (val >> 16) & 0xff;
-		mx28_fec_pdata[i].mac[4] = (val >> 8) & 0xff;
-		mx28_fec_pdata[i].mac[5] = (val >> 0) & 0xff;
-	}
-
-	return 0;
-}
-
-/* mxsfb (lcdif) */
-static struct fb_videomode m28evk_video_modes[] = {
-	{
-		.name		= "Ampire AM-800480R2TMQW-T01H",
-		.refresh	= 60,
-		.xres		= 800,
-		.yres		= 480,
-		.pixclock	= 30066, /* picosecond (33.26 MHz) */
-		.left_margin	= 0,
-		.right_margin	= 256,
-		.upper_margin	= 0,
-		.lower_margin	= 45,
-		.hsync_len	= 1,
-		.vsync_len	= 1,
-		.sync		= FB_SYNC_DATA_ENABLE_HIGH_ACT,
-	},
-};
-
-static const struct mxsfb_platform_data m28evk_mxsfb_pdata __initconst = {
-	.mode_list	= m28evk_video_modes,
-	.mode_count	= ARRAY_SIZE(m28evk_video_modes),
-	.default_bpp	= 16,
-	.ld_intf_width	= STMLCDIF_18BIT,
-};
-
-static struct at24_platform_data m28evk_eeprom = {
-	.byte_len = 16384,
-	.page_size = 32,
-	.flags = AT24_FLAG_ADDR16,
-};
-
-static struct i2c_board_info m28_stk5v3_i2c_boardinfo[] __initdata = {
-	{
-		I2C_BOARD_INFO("at24", 0x51),	/* E0=1, E1=0, E2=0 */
-		.platform_data = &m28evk_eeprom,
-	},
-};
-
-static struct mxs_mmc_platform_data m28evk_mmc_pdata[] __initdata = {
-	{
-		/* mmc0 */
-		.wp_gpio = MX28EVK_MMC0_WRITE_PROTECT,
-		.flags = SLOTF_8_BIT_CAPABLE,
-	}, {
-		/* mmc1 */
-		.wp_gpio = MX28EVK_MMC1_WRITE_PROTECT,
-		.flags = SLOTF_8_BIT_CAPABLE,
-	},
-};
-
-static void __init m28evk_init(void)
-{
-	mx28_soc_init();
-
-	mxs_iomux_setup_multiple_pads(m28evk_pads, ARRAY_SIZE(m28evk_pads));
-
-	mx28_add_duart();
-	mx28_add_auart0();
-	mx28_add_auart3();
-
-	if (!m28evk_fec_get_mac()) {
-		mx28_add_fec(0, &mx28_fec_pdata[0]);
-		mx28_add_fec(1, &mx28_fec_pdata[1]);
-	}
-
-	mx28_add_flexcan(0, NULL);
-	mx28_add_flexcan(1, NULL);
-
-	mx28_add_mxsfb(&m28evk_mxsfb_pdata);
-
-	mx28_add_mxs_mmc(0, &m28evk_mmc_pdata[0]);
-	mx28_add_mxs_mmc(1, &m28evk_mmc_pdata[1]);
-
-	gpio_led_register_device(0, &m28evk_led_data);
-
-	/* I2C */
-	mx28_add_mxs_i2c(0);
-	i2c_register_board_info(0, m28_stk5v3_i2c_boardinfo,
-			ARRAY_SIZE(m28_stk5v3_i2c_boardinfo));
-}
-
-static void __init m28evk_timer_init(void)
-{
-	mx28_clocks_init();
-}
-
-static struct sys_timer m28evk_timer = {
-	.init	= m28evk_timer_init,
-};
-
-MACHINE_START(M28EVK, "DENX M28 EVK")
-	.map_io		= mx28_map_io,
-	.init_irq	= mx28_init_irq,
-	.timer		= &m28evk_timer,
-	.init_machine	= m28evk_init,
-	.restart	= mxs_restart,
-MACHINE_END
diff --git a/arch/arm/mach-mxs/mach-mx23evk.c b/arch/arm/mach-mxs/mach-mx23evk.c
deleted file mode 100644
index e7272a4..0000000
--- a/arch/arm/mach-mxs/mach-mx23evk.c
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * Copyright 2010 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 as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/delay.h>
-#include <linux/platform_device.h>
-#include <linux/gpio.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-
-#include <mach/common.h>
-#include <mach/iomux-mx23.h>
-
-#include "devices-mx23.h"
-
-#define MX23EVK_LCD_ENABLE	MXS_GPIO_NR(1, 18)
-#define MX23EVK_BL_ENABLE	MXS_GPIO_NR(1, 28)
-#define MX23EVK_MMC0_WRITE_PROTECT	MXS_GPIO_NR(1, 30)
-#define MX23EVK_MMC0_SLOT_POWER		MXS_GPIO_NR(1, 29)
-
-static const iomux_cfg_t mx23evk_pads[] __initconst = {
-	/* duart */
-	MX23_PAD_PWM0__DUART_RX | MXS_PAD_CTRL,
-	MX23_PAD_PWM1__DUART_TX | MXS_PAD_CTRL,
-
-	/* auart */
-	MX23_PAD_AUART1_RX__AUART1_RX | MXS_PAD_CTRL,
-	MX23_PAD_AUART1_TX__AUART1_TX | MXS_PAD_CTRL,
-	MX23_PAD_AUART1_CTS__AUART1_CTS | MXS_PAD_CTRL,
-	MX23_PAD_AUART1_RTS__AUART1_RTS | MXS_PAD_CTRL,
-
-	/* mxsfb (lcdif) */
-	MX23_PAD_LCD_D00__LCD_D00 | MXS_PAD_CTRL,
-	MX23_PAD_LCD_D01__LCD_D01 | MXS_PAD_CTRL,
-	MX23_PAD_LCD_D02__LCD_D02 | MXS_PAD_CTRL,
-	MX23_PAD_LCD_D03__LCD_D03 | MXS_PAD_CTRL,
-	MX23_PAD_LCD_D04__LCD_D04 | MXS_PAD_CTRL,
-	MX23_PAD_LCD_D05__LCD_D05 | MXS_PAD_CTRL,
-	MX23_PAD_LCD_D06__LCD_D06 | MXS_PAD_CTRL,
-	MX23_PAD_LCD_D07__LCD_D07 | MXS_PAD_CTRL,
-	MX23_PAD_LCD_D08__LCD_D08 | MXS_PAD_CTRL,
-	MX23_PAD_LCD_D09__LCD_D09 | MXS_PAD_CTRL,
-	MX23_PAD_LCD_D10__LCD_D10 | MXS_PAD_CTRL,
-	MX23_PAD_LCD_D11__LCD_D11 | MXS_PAD_CTRL,
-	MX23_PAD_LCD_D12__LCD_D12 | MXS_PAD_CTRL,
-	MX23_PAD_LCD_D13__LCD_D13 | MXS_PAD_CTRL,
-	MX23_PAD_LCD_D14__LCD_D14 | MXS_PAD_CTRL,
-	MX23_PAD_LCD_D15__LCD_D15 | MXS_PAD_CTRL,
-	MX23_PAD_LCD_D16__LCD_D16 | MXS_PAD_CTRL,
-	MX23_PAD_LCD_D17__LCD_D17 | MXS_PAD_CTRL,
-	MX23_PAD_GPMI_D08__LCD_D18 | MXS_PAD_CTRL,
-	MX23_PAD_GPMI_D09__LCD_D19 | MXS_PAD_CTRL,
-	MX23_PAD_GPMI_D10__LCD_D20 | MXS_PAD_CTRL,
-	MX23_PAD_GPMI_D11__LCD_D21 | MXS_PAD_CTRL,
-	MX23_PAD_GPMI_D12__LCD_D22 | MXS_PAD_CTRL,
-	MX23_PAD_GPMI_D13__LCD_D23 | MXS_PAD_CTRL,
-	MX23_PAD_LCD_VSYNC__LCD_VSYNC | MXS_PAD_CTRL,
-	MX23_PAD_LCD_HSYNC__LCD_HSYNC | MXS_PAD_CTRL,
-	MX23_PAD_LCD_DOTCK__LCD_DOTCK | MXS_PAD_CTRL,
-	MX23_PAD_LCD_ENABLE__LCD_ENABLE | MXS_PAD_CTRL,
-	/* LCD panel enable */
-	MX23_PAD_LCD_RESET__GPIO_1_18 | MXS_PAD_CTRL,
-	/* backlight control */
-	MX23_PAD_PWM2__GPIO_1_28 | MXS_PAD_CTRL,
-
-	/* mmc */
-	MX23_PAD_SSP1_DATA0__SSP1_DATA0 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX23_PAD_SSP1_DATA1__SSP1_DATA1 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX23_PAD_SSP1_DATA2__SSP1_DATA2 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX23_PAD_SSP1_DATA3__SSP1_DATA3 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX23_PAD_GPMI_D08__SSP1_DATA4 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX23_PAD_GPMI_D09__SSP1_DATA5 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX23_PAD_GPMI_D10__SSP1_DATA6 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX23_PAD_GPMI_D11__SSP1_DATA7 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX23_PAD_SSP1_CMD__SSP1_CMD |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX23_PAD_SSP1_DETECT__SSP1_DETECT |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
-	MX23_PAD_SSP1_SCK__SSP1_SCK |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
-	/* write protect */
-	MX23_PAD_PWM4__GPIO_1_30 |
-		(MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
-	/* slot power enable */
-	MX23_PAD_PWM3__GPIO_1_29 |
-		(MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
-};
-
-/* mxsfb (lcdif) */
-static struct fb_videomode mx23evk_video_modes[] = {
-	{
-		.name		= "Samsung-LMS430HF02",
-		.refresh	= 60,
-		.xres		= 480,
-		.yres		= 272,
-		.pixclock	= 108096, /* picosecond (9.2 MHz) */
-		.left_margin	= 15,
-		.right_margin	= 8,
-		.upper_margin	= 12,
-		.lower_margin	= 4,
-		.hsync_len	= 1,
-		.vsync_len	= 1,
-		.sync		= FB_SYNC_DATA_ENABLE_HIGH_ACT |
-				  FB_SYNC_DOTCLK_FAILING_ACT,
-	},
-};
-
-static const struct mxsfb_platform_data mx23evk_mxsfb_pdata __initconst = {
-	.mode_list	= mx23evk_video_modes,
-	.mode_count	= ARRAY_SIZE(mx23evk_video_modes),
-	.default_bpp	= 32,
-	.ld_intf_width	= STMLCDIF_24BIT,
-};
-
-static struct mxs_mmc_platform_data mx23evk_mmc_pdata __initdata = {
-	.wp_gpio = MX23EVK_MMC0_WRITE_PROTECT,
-	.flags = SLOTF_8_BIT_CAPABLE,
-};
-
-static void __init mx23evk_init(void)
-{
-	int ret;
-
-	mx23_soc_init();
-
-	mxs_iomux_setup_multiple_pads(mx23evk_pads, ARRAY_SIZE(mx23evk_pads));
-
-	mx23_add_duart();
-	mx23_add_auart0();
-
-	/* power on mmc slot by writing 0 to the gpio */
-	ret = gpio_request_one(MX23EVK_MMC0_SLOT_POWER, GPIOF_OUT_INIT_LOW,
-			       "mmc0-slot-power");
-	if (ret)
-		pr_warn("failed to request gpio mmc0-slot-power: %d\n", ret);
-	mx23_add_mxs_mmc(0, &mx23evk_mmc_pdata);
-
-	ret = gpio_request_one(MX23EVK_LCD_ENABLE, GPIOF_DIR_OUT, "lcd-enable");
-	if (ret)
-		pr_warn("failed to request gpio lcd-enable: %d\n", ret);
-	else
-		gpio_set_value(MX23EVK_LCD_ENABLE, 1);
-
-	ret = gpio_request_one(MX23EVK_BL_ENABLE, GPIOF_DIR_OUT, "bl-enable");
-	if (ret)
-		pr_warn("failed to request gpio bl-enable: %d\n", ret);
-	else
-		gpio_set_value(MX23EVK_BL_ENABLE, 1);
-
-	mx23_add_mxsfb(&mx23evk_mxsfb_pdata);
-	mx23_add_rtc_stmp3xxx();
-}
-
-static void __init mx23evk_timer_init(void)
-{
-	mx23_clocks_init();
-}
-
-static struct sys_timer mx23evk_timer = {
-	.init	= mx23evk_timer_init,
-};
-
-MACHINE_START(MX23EVK, "Freescale MX23 EVK")
-	/* Maintainer: Freescale Semiconductor, Inc. */
-	.map_io		= mx23_map_io,
-	.init_irq	= mx23_init_irq,
-	.timer		= &mx23evk_timer,
-	.init_machine	= mx23evk_init,
-	.restart	= mxs_restart,
-MACHINE_END
diff --git a/arch/arm/mach-mxs/mach-mx28evk.c b/arch/arm/mach-mxs/mach-mx28evk.c
deleted file mode 100644
index dafd48e..0000000
--- a/arch/arm/mach-mxs/mach-mx28evk.c
+++ /dev/null
@@ -1,477 +0,0 @@
-/*
- * Copyright 2010 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 as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/delay.h>
-#include <linux/platform_device.h>
-#include <linux/gpio.h>
-#include <linux/leds.h>
-#include <linux/clk.h>
-#include <linux/i2c.h>
-#include <linux/regulator/machine.h>
-#include <linux/regulator/fixed.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-
-#include <mach/common.h>
-#include <mach/iomux-mx28.h>
-#include <mach/digctl.h>
-
-#include "devices-mx28.h"
-
-#define MX28EVK_FLEXCAN_SWITCH	MXS_GPIO_NR(2, 13)
-#define MX28EVK_FEC_PHY_POWER	MXS_GPIO_NR(2, 15)
-#define MX28EVK_GPIO_LED	MXS_GPIO_NR(3, 5)
-#define MX28EVK_BL_ENABLE	MXS_GPIO_NR(3, 18)
-#define MX28EVK_LCD_ENABLE	MXS_GPIO_NR(3, 30)
-#define MX28EVK_FEC_PHY_RESET	MXS_GPIO_NR(4, 13)
-
-#define MX28EVK_MMC0_WRITE_PROTECT	MXS_GPIO_NR(2, 12)
-#define MX28EVK_MMC1_WRITE_PROTECT	MXS_GPIO_NR(0, 28)
-#define MX28EVK_MMC0_SLOT_POWER		MXS_GPIO_NR(3, 28)
-#define MX28EVK_MMC1_SLOT_POWER		MXS_GPIO_NR(3, 29)
-
-static const iomux_cfg_t mx28evk_pads[] __initconst = {
-	/* duart */
-	MX28_PAD_PWM0__DUART_RX | MXS_PAD_CTRL,
-	MX28_PAD_PWM1__DUART_TX | MXS_PAD_CTRL,
-
-	/* auart0 */
-	MX28_PAD_AUART0_RX__AUART0_RX | MXS_PAD_CTRL,
-	MX28_PAD_AUART0_TX__AUART0_TX | MXS_PAD_CTRL,
-	MX28_PAD_AUART0_CTS__AUART0_CTS | MXS_PAD_CTRL,
-	MX28_PAD_AUART0_RTS__AUART0_RTS | MXS_PAD_CTRL,
-	/* auart3 */
-	MX28_PAD_AUART3_RX__AUART3_RX | MXS_PAD_CTRL,
-	MX28_PAD_AUART3_TX__AUART3_TX | MXS_PAD_CTRL,
-	MX28_PAD_AUART3_CTS__AUART3_CTS | MXS_PAD_CTRL,
-	MX28_PAD_AUART3_RTS__AUART3_RTS | MXS_PAD_CTRL,
-
-#define MXS_PAD_FEC	(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP)
-	/* fec0 */
-	MX28_PAD_ENET0_MDC__ENET0_MDC | MXS_PAD_FEC,
-	MX28_PAD_ENET0_MDIO__ENET0_MDIO | MXS_PAD_FEC,
-	MX28_PAD_ENET0_RX_EN__ENET0_RX_EN | MXS_PAD_FEC,
-	MX28_PAD_ENET0_RXD0__ENET0_RXD0 | MXS_PAD_FEC,
-	MX28_PAD_ENET0_RXD1__ENET0_RXD1 | MXS_PAD_FEC,
-	MX28_PAD_ENET0_TX_EN__ENET0_TX_EN | MXS_PAD_FEC,
-	MX28_PAD_ENET0_TXD0__ENET0_TXD0 | MXS_PAD_FEC,
-	MX28_PAD_ENET0_TXD1__ENET0_TXD1 | MXS_PAD_FEC,
-	MX28_PAD_ENET_CLK__CLKCTRL_ENET | MXS_PAD_FEC,
-	/* fec1 */
-	MX28_PAD_ENET0_CRS__ENET1_RX_EN | MXS_PAD_FEC,
-	MX28_PAD_ENET0_RXD2__ENET1_RXD0 | MXS_PAD_FEC,
-	MX28_PAD_ENET0_RXD3__ENET1_RXD1 | MXS_PAD_FEC,
-	MX28_PAD_ENET0_COL__ENET1_TX_EN | MXS_PAD_FEC,
-	MX28_PAD_ENET0_TXD2__ENET1_TXD0 | MXS_PAD_FEC,
-	MX28_PAD_ENET0_TXD3__ENET1_TXD1 | MXS_PAD_FEC,
-	/* phy power line */
-	MX28_PAD_SSP1_DATA3__GPIO_2_15 | MXS_PAD_CTRL,
-	/* phy reset line */
-	MX28_PAD_ENET0_RX_CLK__GPIO_4_13 | MXS_PAD_CTRL,
-
-	/* flexcan0 */
-	MX28_PAD_GPMI_RDY2__CAN0_TX,
-	MX28_PAD_GPMI_RDY3__CAN0_RX,
-	/* flexcan1 */
-	MX28_PAD_GPMI_CE2N__CAN1_TX,
-	MX28_PAD_GPMI_CE3N__CAN1_RX,
-	/* transceiver power control */
-	MX28_PAD_SSP1_CMD__GPIO_2_13,
-
-	/* mxsfb (lcdif) */
-	MX28_PAD_LCD_D00__LCD_D0 | MXS_PAD_CTRL,
-	MX28_PAD_LCD_D01__LCD_D1 | MXS_PAD_CTRL,
-	MX28_PAD_LCD_D02__LCD_D2 | MXS_PAD_CTRL,
-	MX28_PAD_LCD_D03__LCD_D3 | MXS_PAD_CTRL,
-	MX28_PAD_LCD_D04__LCD_D4 | MXS_PAD_CTRL,
-	MX28_PAD_LCD_D05__LCD_D5 | MXS_PAD_CTRL,
-	MX28_PAD_LCD_D06__LCD_D6 | MXS_PAD_CTRL,
-	MX28_PAD_LCD_D07__LCD_D7 | MXS_PAD_CTRL,
-	MX28_PAD_LCD_D08__LCD_D8 | MXS_PAD_CTRL,
-	MX28_PAD_LCD_D09__LCD_D9 | MXS_PAD_CTRL,
-	MX28_PAD_LCD_D10__LCD_D10 | MXS_PAD_CTRL,
-	MX28_PAD_LCD_D11__LCD_D11 | MXS_PAD_CTRL,
-	MX28_PAD_LCD_D12__LCD_D12 | MXS_PAD_CTRL,
-	MX28_PAD_LCD_D13__LCD_D13 | MXS_PAD_CTRL,
-	MX28_PAD_LCD_D14__LCD_D14 | MXS_PAD_CTRL,
-	MX28_PAD_LCD_D15__LCD_D15 | MXS_PAD_CTRL,
-	MX28_PAD_LCD_D16__LCD_D16 | MXS_PAD_CTRL,
-	MX28_PAD_LCD_D17__LCD_D17 | MXS_PAD_CTRL,
-	MX28_PAD_LCD_D18__LCD_D18 | MXS_PAD_CTRL,
-	MX28_PAD_LCD_D19__LCD_D19 | MXS_PAD_CTRL,
-	MX28_PAD_LCD_D20__LCD_D20 | MXS_PAD_CTRL,
-	MX28_PAD_LCD_D21__LCD_D21 | MXS_PAD_CTRL,
-	MX28_PAD_LCD_D22__LCD_D22 | MXS_PAD_CTRL,
-	MX28_PAD_LCD_D23__LCD_D23 | MXS_PAD_CTRL,
-	MX28_PAD_LCD_RD_E__LCD_VSYNC | MXS_PAD_CTRL,
-	MX28_PAD_LCD_WR_RWN__LCD_HSYNC | MXS_PAD_CTRL,
-	MX28_PAD_LCD_RS__LCD_DOTCLK | MXS_PAD_CTRL,
-	MX28_PAD_LCD_CS__LCD_ENABLE | MXS_PAD_CTRL,
-	/* LCD panel enable */
-	MX28_PAD_LCD_RESET__GPIO_3_30 | MXS_PAD_CTRL,
-	/* backlight control */
-	MX28_PAD_PWM2__GPIO_3_18 | MXS_PAD_CTRL,
-	/* mmc0 */
-	MX28_PAD_SSP0_DATA0__SSP0_D0 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_SSP0_DATA1__SSP0_D1 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_SSP0_DATA2__SSP0_D2 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_SSP0_DATA3__SSP0_D3 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_SSP0_DATA4__SSP0_D4 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_SSP0_DATA5__SSP0_D5 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_SSP0_DATA6__SSP0_D6 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_SSP0_DATA7__SSP0_D7 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_SSP0_CMD__SSP0_CMD |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_SSP0_DETECT__SSP0_CARD_DETECT |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
-	MX28_PAD_SSP0_SCK__SSP0_SCK |
-		(MXS_PAD_12MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
-	/* write protect */
-	MX28_PAD_SSP1_SCK__GPIO_2_12 |
-		(MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
-	/* slot power enable */
-	MX28_PAD_PWM3__GPIO_3_28 |
-		(MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
-
-	/* mmc1 */
-	MX28_PAD_GPMI_D00__SSP1_D0 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_GPMI_D01__SSP1_D1 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_GPMI_D02__SSP1_D2 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_GPMI_D03__SSP1_D3 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_GPMI_D04__SSP1_D4 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_GPMI_D05__SSP1_D5 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_GPMI_D06__SSP1_D6 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_GPMI_D07__SSP1_D7 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_GPMI_RDY1__SSP1_CMD |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_GPMI_RDY0__SSP1_CARD_DETECT |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
-	MX28_PAD_GPMI_WRN__SSP1_SCK |
-		(MXS_PAD_12MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
-	/* write protect */
-	MX28_PAD_GPMI_RESETN__GPIO_0_28 |
-		(MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
-	/* slot power enable */
-	MX28_PAD_PWM4__GPIO_3_29 |
-		(MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
-
-	/* led */
-	MX28_PAD_AUART1_TX__GPIO_3_5 | MXS_PAD_CTRL,
-
-	/* I2C */
-	MX28_PAD_I2C0_SCL__I2C0_SCL |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_I2C0_SDA__I2C0_SDA |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-
-	/* saif0 & saif1 */
-	MX28_PAD_SAIF0_MCLK__SAIF0_MCLK |
-		(MXS_PAD_12MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_SAIF0_LRCLK__SAIF0_LRCLK |
-		(MXS_PAD_12MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_SAIF0_BITCLK__SAIF0_BITCLK |
-		(MXS_PAD_12MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_SAIF0_SDATA0__SAIF0_SDATA0 |
-		(MXS_PAD_12MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_SAIF1_SDATA0__SAIF1_SDATA0 |
-		(MXS_PAD_12MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-};
-
-/* led */
-static const struct gpio_led mx28evk_leds[] __initconst = {
-	{
-		.name = "GPIO-LED",
-		.default_trigger = "heartbeat",
-		.gpio = MX28EVK_GPIO_LED,
-	},
-};
-
-static const struct gpio_led_platform_data mx28evk_led_data __initconst = {
-	.leds = mx28evk_leds,
-	.num_leds = ARRAY_SIZE(mx28evk_leds),
-};
-
-/* fec */
-static void __init mx28evk_fec_reset(void)
-{
-	struct clk *clk;
-
-	/* Enable fec phy clock */
-	clk = clk_get_sys("enet_out", NULL);
-	if (!IS_ERR(clk))
-		clk_prepare_enable(clk);
-
-	gpio_set_value(MX28EVK_FEC_PHY_RESET, 0);
-	mdelay(1);
-	gpio_set_value(MX28EVK_FEC_PHY_RESET, 1);
-}
-
-static struct fec_platform_data mx28_fec_pdata[] __initdata = {
-	{
-		/* fec0 */
-		.phy = PHY_INTERFACE_MODE_RMII,
-	}, {
-		/* fec1 */
-		.phy = PHY_INTERFACE_MODE_RMII,
-	},
-};
-
-static int __init mx28evk_fec_get_mac(void)
-{
-	int i;
-	u32 val;
-	const u32 *ocotp = mxs_get_ocotp();
-
-	if (!ocotp)
-		return -ETIMEDOUT;
-
-	/*
-	 * OCOTP only stores the last 4 octets for each mac address,
-	 * so hard-code Freescale OUI (00:04:9f) here.
-	 */
-	for (i = 0; i < 2; i++) {
-		val = ocotp[i];
-		mx28_fec_pdata[i].mac[0] = 0x00;
-		mx28_fec_pdata[i].mac[1] = 0x04;
-		mx28_fec_pdata[i].mac[2] = 0x9f;
-		mx28_fec_pdata[i].mac[3] = (val >> 16) & 0xff;
-		mx28_fec_pdata[i].mac[4] = (val >> 8) & 0xff;
-		mx28_fec_pdata[i].mac[5] = (val >> 0) & 0xff;
-	}
-
-	return 0;
-}
-
-/*
- * MX28EVK_FLEXCAN_SWITCH is shared between both flexcan controllers
- */
-static int flexcan0_en, flexcan1_en;
-
-static void mx28evk_flexcan_switch(void)
-{
-	if (flexcan0_en || flexcan1_en)
-		gpio_set_value(MX28EVK_FLEXCAN_SWITCH, 1);
-	else
-		gpio_set_value(MX28EVK_FLEXCAN_SWITCH, 0);
-}
-
-static void mx28evk_flexcan0_switch(int enable)
-{
-	flexcan0_en = enable;
-	mx28evk_flexcan_switch();
-}
-
-static void mx28evk_flexcan1_switch(int enable)
-{
-	flexcan1_en = enable;
-	mx28evk_flexcan_switch();
-}
-
-static const struct flexcan_platform_data
-		mx28evk_flexcan_pdata[] __initconst = {
-	{
-		.transceiver_switch = mx28evk_flexcan0_switch,
-	}, {
-		.transceiver_switch = mx28evk_flexcan1_switch,
-	}
-};
-
-/* mxsfb (lcdif) */
-static struct fb_videomode mx28evk_video_modes[] = {
-	{
-		.name		= "Seiko-43WVF1G",
-		.refresh	= 60,
-		.xres		= 800,
-		.yres		= 480,
-		.pixclock	= 29851, /* picosecond (33.5 MHz) */
-		.left_margin	= 89,
-		.right_margin	= 164,
-		.upper_margin	= 23,
-		.lower_margin	= 10,
-		.hsync_len	= 10,
-		.vsync_len	= 10,
-		.sync		= FB_SYNC_DATA_ENABLE_HIGH_ACT |
-				  FB_SYNC_DOTCLK_FAILING_ACT,
-	},
-};
-
-static const struct mxsfb_platform_data mx28evk_mxsfb_pdata __initconst = {
-	.mode_list	= mx28evk_video_modes,
-	.mode_count	= ARRAY_SIZE(mx28evk_video_modes),
-	.default_bpp	= 32,
-	.ld_intf_width	= STMLCDIF_24BIT,
-};
-
-static struct mxs_mmc_platform_data mx28evk_mmc_pdata[] __initdata = {
-	{
-		/* mmc0 */
-		.wp_gpio = MX28EVK_MMC0_WRITE_PROTECT,
-		.flags = SLOTF_8_BIT_CAPABLE,
-	}, {
-		/* mmc1 */
-		.wp_gpio = MX28EVK_MMC1_WRITE_PROTECT,
-		.flags = SLOTF_8_BIT_CAPABLE,
-	},
-};
-
-static struct i2c_board_info mxs_i2c0_board_info[] __initdata = {
-	{
-		I2C_BOARD_INFO("sgtl5000", 0x0a),
-	},
-};
-
-#if defined(CONFIG_REGULATOR_FIXED_VOLTAGE) || defined(CONFIG_REGULATOR_FIXED_VOLTAGE_MODULE)
-static struct regulator_consumer_supply mx28evk_audio_consumer_supplies[] = {
-	REGULATOR_SUPPLY("VDDA", "0-000a"),
-	REGULATOR_SUPPLY("VDDIO", "0-000a"),
-};
-
-static struct regulator_init_data mx28evk_vdd_reg_init_data = {
-	.constraints	= {
-		.name	= "3V3",
-		.always_on = 1,
-	},
-	.consumer_supplies = mx28evk_audio_consumer_supplies,
-	.num_consumer_supplies = ARRAY_SIZE(mx28evk_audio_consumer_supplies),
-};
-
-static struct fixed_voltage_config mx28evk_vdd_pdata = {
-	.supply_name	= "board-3V3",
-	.microvolts	= 3300000,
-	.gpio		= -EINVAL,
-	.enabled_at_boot = 1,
-	.init_data	= &mx28evk_vdd_reg_init_data,
-};
-static struct platform_device mx28evk_voltage_regulator = {
-	.name		= "reg-fixed-voltage",
-	.id		= -1,
-	.num_resources	= 0,
-	.dev		= {
-		.platform_data	= &mx28evk_vdd_pdata,
-	},
-};
-static void __init mx28evk_add_regulators(void)
-{
-	platform_device_register(&mx28evk_voltage_regulator);
-}
-#else
-static void __init mx28evk_add_regulators(void) {}
-#endif
-
-static const struct gpio mx28evk_gpios[] __initconst = {
-	{ MX28EVK_LCD_ENABLE, GPIOF_OUT_INIT_HIGH, "lcd-enable" },
-	{ MX28EVK_BL_ENABLE, GPIOF_OUT_INIT_HIGH, "bl-enable" },
-	{ MX28EVK_FLEXCAN_SWITCH, GPIOF_DIR_OUT, "flexcan-switch" },
-	{ MX28EVK_MMC0_SLOT_POWER, GPIOF_OUT_INIT_LOW, "mmc0-slot-power" },
-	{ MX28EVK_MMC1_SLOT_POWER, GPIOF_OUT_INIT_LOW, "mmc1-slot-power" },
-	{ MX28EVK_FEC_PHY_POWER, GPIOF_OUT_INIT_LOW, "fec-phy-power" },
-	{ MX28EVK_FEC_PHY_RESET, GPIOF_DIR_OUT, "fec-phy-reset" },
-};
-
-static const struct mxs_saif_platform_data
-			mx28evk_mxs_saif_pdata[] __initconst = {
-	/* working on EXTMSTR0 mode (saif0 master, saif1 slave) */
-	{
-		.master_mode = 1,
-		.master_id = 0,
-	}, {
-		.master_mode = 0,
-		.master_id = 0,
-	},
-};
-
-static void __init mx28evk_init(void)
-{
-	int ret;
-
-	mx28_soc_init();
-
-	mxs_iomux_setup_multiple_pads(mx28evk_pads, ARRAY_SIZE(mx28evk_pads));
-
-	mx28_add_duart();
-	mx28_add_auart0();
-	mx28_add_auart3();
-
-	if (mx28evk_fec_get_mac())
-		pr_warn("%s: failed on fec mac setup\n", __func__);
-
-	ret = gpio_request_array(mx28evk_gpios, ARRAY_SIZE(mx28evk_gpios));
-	if (ret)
-		pr_err("One or more GPIOs failed to be requested: %d\n", ret);
-
-	mx28evk_fec_reset();
-	mx28_add_fec(0, &mx28_fec_pdata[0]);
-	mx28_add_fec(1, &mx28_fec_pdata[1]);
-
-	mx28_add_flexcan(0, &mx28evk_flexcan_pdata[0]);
-	mx28_add_flexcan(1, &mx28evk_flexcan_pdata[1]);
-
-	mx28_add_mxsfb(&mx28evk_mxsfb_pdata);
-
-	mxs_saif_clkmux_select(MXS_DIGCTL_SAIF_CLKMUX_EXTMSTR0);
-	mx28_add_saif(0, &mx28evk_mxs_saif_pdata[0]);
-	mx28_add_saif(1, &mx28evk_mxs_saif_pdata[1]);
-
-	mx28_add_mxs_i2c(0);
-	i2c_register_board_info(0, mxs_i2c0_board_info,
-				ARRAY_SIZE(mxs_i2c0_board_info));
-
-	mx28evk_add_regulators();
-
-	mxs_add_platform_device("mxs-sgtl5000", 0, NULL, 0,
-			NULL, 0);
-
-	mx28_add_mxs_mmc(0, &mx28evk_mmc_pdata[0]);
-	mx28_add_mxs_mmc(1, &mx28evk_mmc_pdata[1]);
-
-	mx28_add_rtc_stmp3xxx();
-
-	gpio_led_register_device(0, &mx28evk_led_data);
-}
-
-static void __init mx28evk_timer_init(void)
-{
-	mx28_clocks_init();
-}
-
-static struct sys_timer mx28evk_timer = {
-	.init	= mx28evk_timer_init,
-};
-
-MACHINE_START(MX28EVK, "Freescale MX28 EVK")
-	/* Maintainer: Freescale Semiconductor, Inc. */
-	.map_io		= mx28_map_io,
-	.init_irq	= mx28_init_irq,
-	.timer		= &mx28evk_timer,
-	.init_machine	= mx28evk_init,
-	.restart	= mxs_restart,
-MACHINE_END
diff --git a/arch/arm/mach-mxs/mach-mxs.c b/arch/arm/mach-mxs/mach-mxs.c
index 8dabfe8..4748ec5 100644
--- a/arch/arm/mach-mxs/mach-mxs.c
+++ b/arch/arm/mach-mxs/mach-mxs.c
@@ -12,18 +12,21 @@
 
 #include <linux/clk.h>
 #include <linux/clkdev.h>
+#include <linux/can/platform/flexcan.h>
+#include <linux/delay.h>
 #include <linux/err.h>
+#include <linux/gpio.h>
 #include <linux/init.h>
-#include <linux/init.h>
-#include <linux/irqdomain.h>
 #include <linux/micrel_phy.h>
 #include <linux/mxsfb.h>
-#include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/phy.h>
+#include <linux/pinctrl/consumer.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 #include <mach/common.h>
+#include <mach/digctl.h>
+#include <mach/mxs.h>
 
 static struct fb_videomode mx23evk_video_modes[] = {
 	{
@@ -99,43 +102,43 @@ static struct fb_videomode apx4devkit_video_modes[] = {
 
 static struct mxsfb_platform_data mxsfb_pdata __initdata;
 
-static struct of_dev_auxdata mxs_auxdata_lookup[] __initdata = {
-	OF_DEV_AUXDATA("fsl,imx23-lcdif", 0x80030000, NULL, &mxsfb_pdata),
-	OF_DEV_AUXDATA("fsl,imx28-lcdif", 0x80030000, NULL, &mxsfb_pdata),
-	{ /* sentinel */ }
-};
+/*
+ * MX28EVK_FLEXCAN_SWITCH is shared between both flexcan controllers
+ */
+#define MX28EVK_FLEXCAN_SWITCH	MXS_GPIO_NR(2, 13)
 
-static int __init mxs_icoll_add_irq_domain(struct device_node *np,
-				struct device_node *interrupt_parent)
-{
-	irq_domain_add_legacy(np, 128, 0, 0, &irq_domain_simple_ops, NULL);
+static int flexcan0_en, flexcan1_en;
 
-	return 0;
+static void mx28evk_flexcan_switch(void)
+{
+	if (flexcan0_en || flexcan1_en)
+		gpio_set_value(MX28EVK_FLEXCAN_SWITCH, 1);
+	else
+		gpio_set_value(MX28EVK_FLEXCAN_SWITCH, 0);
 }
 
-static int __init mxs_gpio_add_irq_domain(struct device_node *np,
-				struct device_node *interrupt_parent)
+static void mx28evk_flexcan0_switch(int enable)
 {
-	static int gpio_irq_base = MXS_GPIO_IRQ_START;
-
-	irq_domain_add_legacy(np, 32, gpio_irq_base, 0, &irq_domain_simple_ops, NULL);
-	gpio_irq_base += 32;
+	flexcan0_en = enable;
+	mx28evk_flexcan_switch();
+}
 
-	return 0;
+static void mx28evk_flexcan1_switch(int enable)
+{
+	flexcan1_en = enable;
+	mx28evk_flexcan_switch();
 }
 
-static const struct of_device_id mxs_irq_match[] __initconst = {
-	{ .compatible = "fsl,mxs-icoll", .data = mxs_icoll_add_irq_domain, },
-	{ .compatible = "fsl,mxs-gpio", .data = mxs_gpio_add_irq_domain, },
+static struct flexcan_platform_data flexcan_pdata[2];
+
+static struct of_dev_auxdata mxs_auxdata_lookup[] __initdata = {
+	OF_DEV_AUXDATA("fsl,imx23-lcdif", 0x80030000, NULL, &mxsfb_pdata),
+	OF_DEV_AUXDATA("fsl,imx28-lcdif", 0x80030000, NULL, &mxsfb_pdata),
+	OF_DEV_AUXDATA("fsl,imx28-flexcan", 0x80032000, NULL, &flexcan_pdata[0]),
+	OF_DEV_AUXDATA("fsl,imx28-flexcan", 0x80034000, NULL, &flexcan_pdata[1]),
 	{ /* sentinel */ }
 };
 
-static void __init mxs_dt_init_irq(void)
-{
-	icoll_init_irq();
-	of_irq_init(mxs_irq_match);
-}
-
 static void __init imx23_timer_init(void)
 {
 	mx23_clocks_init();
@@ -237,13 +240,21 @@ static void __init imx28_evk_init(void)
 	mxsfb_pdata.mode_count = ARRAY_SIZE(mx28evk_video_modes);
 	mxsfb_pdata.default_bpp = 32;
 	mxsfb_pdata.ld_intf_width = STMLCDIF_24BIT;
+
+	mxs_saif_clkmux_select(MXS_DIGCTL_SAIF_CLKMUX_EXTMSTR0);
 }
 
-static void __init m28evk_init(void)
+static void __init imx28_evk_post_init(void)
 {
-	enable_clk_enet_out();
-	update_fec_mac_prop(OUI_DENX);
+	if (!gpio_request_one(MX28EVK_FLEXCAN_SWITCH, GPIOF_DIR_OUT,
+			      "flexcan-switch")) {
+		flexcan_pdata[0].transceiver_switch = mx28evk_flexcan0_switch;
+		flexcan_pdata[1].transceiver_switch = mx28evk_flexcan1_switch;
+	}
+}
 
+static void __init m28evk_init(void)
+{
 	mxsfb_pdata.mode_list = m28evk_video_modes;
 	mxsfb_pdata.mode_count = ARRAY_SIZE(m28evk_video_modes);
 	mxsfb_pdata.default_bpp = 16;
@@ -261,7 +272,7 @@ static void __init apx4devkit_init(void)
 	enable_clk_enet_out();
 
 	if (IS_BUILTIN(CONFIG_PHYLIB))
-		phy_register_fixup_for_uid(PHY_ID_KS8051, MICREL_PHY_ID_MASK,
+		phy_register_fixup_for_uid(PHY_ID_KSZ8051, MICREL_PHY_ID_MASK,
 					   apx4devkit_phy_fixup);
 
 	mxsfb_pdata.mode_list = apx4devkit_video_modes;
@@ -270,6 +281,80 @@ static void __init apx4devkit_init(void)
 	mxsfb_pdata.ld_intf_width = STMLCDIF_24BIT;
 }
 
+#define ENET0_MDC__GPIO_4_0	MXS_GPIO_NR(4, 0)
+#define ENET0_MDIO__GPIO_4_1	MXS_GPIO_NR(4, 1)
+#define ENET0_RX_EN__GPIO_4_2	MXS_GPIO_NR(4, 2)
+#define ENET0_RXD0__GPIO_4_3	MXS_GPIO_NR(4, 3)
+#define ENET0_RXD1__GPIO_4_4	MXS_GPIO_NR(4, 4)
+#define ENET0_TX_EN__GPIO_4_6	MXS_GPIO_NR(4, 6)
+#define ENET0_TXD0__GPIO_4_7	MXS_GPIO_NR(4, 7)
+#define ENET0_TXD1__GPIO_4_8	MXS_GPIO_NR(4, 8)
+#define ENET_CLK__GPIO_4_16	MXS_GPIO_NR(4, 16)
+
+#define TX28_FEC_PHY_POWER	MXS_GPIO_NR(3, 29)
+#define TX28_FEC_PHY_RESET	MXS_GPIO_NR(4, 13)
+#define TX28_FEC_nINT		MXS_GPIO_NR(4, 5)
+
+static const struct gpio tx28_gpios[] __initconst = {
+	{ ENET0_MDC__GPIO_4_0, GPIOF_OUT_INIT_LOW, "GPIO_4_0" },
+	{ ENET0_MDIO__GPIO_4_1, GPIOF_OUT_INIT_LOW, "GPIO_4_1" },
+	{ ENET0_RX_EN__GPIO_4_2, GPIOF_OUT_INIT_LOW, "GPIO_4_2" },
+	{ ENET0_RXD0__GPIO_4_3, GPIOF_OUT_INIT_LOW, "GPIO_4_3" },
+	{ ENET0_RXD1__GPIO_4_4, GPIOF_OUT_INIT_LOW, "GPIO_4_4" },
+	{ ENET0_TX_EN__GPIO_4_6, GPIOF_OUT_INIT_LOW, "GPIO_4_6" },
+	{ ENET0_TXD0__GPIO_4_7, GPIOF_OUT_INIT_LOW, "GPIO_4_7" },
+	{ ENET0_TXD1__GPIO_4_8, GPIOF_OUT_INIT_LOW, "GPIO_4_8" },
+	{ ENET_CLK__GPIO_4_16, GPIOF_OUT_INIT_LOW, "GPIO_4_16" },
+	{ TX28_FEC_PHY_POWER, GPIOF_OUT_INIT_LOW, "fec-phy-power" },
+	{ TX28_FEC_PHY_RESET, GPIOF_OUT_INIT_LOW, "fec-phy-reset" },
+	{ TX28_FEC_nINT, GPIOF_DIR_IN, "fec-int" },
+};
+
+static void __init tx28_post_init(void)
+{
+	struct device_node *np;
+	struct platform_device *pdev;
+	struct pinctrl *pctl;
+	int ret;
+
+	enable_clk_enet_out();
+
+	np = of_find_compatible_node(NULL, NULL, "fsl,imx28-fec");
+	pdev = of_find_device_by_node(np);
+	if (!pdev) {
+		pr_err("%s: failed to find fec device\n", __func__);
+		return;
+	}
+
+	pctl = pinctrl_get_select(&pdev->dev, "gpio_mode");
+	if (IS_ERR(pctl)) {
+		pr_err("%s: failed to get pinctrl state\n", __func__);
+		return;
+	}
+
+	ret = gpio_request_array(tx28_gpios, ARRAY_SIZE(tx28_gpios));
+	if (ret) {
+		pr_err("%s: failed to request gpios: %d\n", __func__, ret);
+		return;
+	}
+
+	/* Power up fec phy */
+	gpio_set_value(TX28_FEC_PHY_POWER, 1);
+	msleep(26); /* 25ms according to data sheet */
+
+	/* Mode strap pins */
+	gpio_set_value(ENET0_RX_EN__GPIO_4_2, 1);
+	gpio_set_value(ENET0_RXD0__GPIO_4_3, 1);
+	gpio_set_value(ENET0_RXD1__GPIO_4_4, 1);
+
+	udelay(100); /* minimum assertion time for nRST */
+
+	/* Deasserting FEC PHY RESET */
+	gpio_set_value(TX28_FEC_PHY_RESET, 1);
+
+	pinctrl_put(pctl);
+}
+
 static void __init mxs_machine_init(void)
 {
 	if (of_machine_is_compatible("fsl,imx28-evk"))
@@ -283,29 +368,28 @@ static void __init mxs_machine_init(void)
 
 	of_platform_populate(NULL, of_default_bus_match_table,
 			     mxs_auxdata_lookup, NULL);
+
+	if (of_machine_is_compatible("karo,tx28"))
+		tx28_post_init();
+
+	if (of_machine_is_compatible("fsl,imx28-evk"))
+		imx28_evk_post_init();
 }
 
 static const char *imx23_dt_compat[] __initdata = {
-	"fsl,imx23-evk",
-	"fsl,stmp378x_devb"
-	"olimex,imx23-olinuxino",
 	"fsl,imx23",
 	NULL,
 };
 
 static const char *imx28_dt_compat[] __initdata = {
-	"bluegiga,apx4devkit",
-	"crystalfontz,cfa10036",
-	"denx,m28evk",
-	"fsl,imx28-evk",
-	"karo,tx28",
 	"fsl,imx28",
 	NULL,
 };
 
 DT_MACHINE_START(IMX23, "Freescale i.MX23 (Device Tree)")
 	.map_io		= mx23_map_io,
-	.init_irq	= mxs_dt_init_irq,
+	.init_irq	= icoll_init_irq,
+	.handle_irq	= icoll_handle_irq,
 	.timer		= &imx23_timer,
 	.init_machine	= mxs_machine_init,
 	.dt_compat	= imx23_dt_compat,
@@ -314,7 +398,8 @@ MACHINE_END
 
 DT_MACHINE_START(IMX28, "Freescale i.MX28 (Device Tree)")
 	.map_io		= mx28_map_io,
-	.init_irq	= mxs_dt_init_irq,
+	.init_irq	= icoll_init_irq,
+	.handle_irq	= icoll_handle_irq,
 	.timer		= &imx28_timer,
 	.init_machine	= mxs_machine_init,
 	.dt_compat	= imx28_dt_compat,
diff --git a/arch/arm/mach-mxs/mach-stmp378x_devb.c b/arch/arm/mach-mxs/mach-stmp378x_devb.c
deleted file mode 100644
index 6548965..0000000
--- a/arch/arm/mach-mxs/mach-stmp378x_devb.c
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * board setup for STMP378x-Development-Board
- *
- * based on mx23evk board setup and information gained form the original
- * plat-stmp based board setup, now converted to mach-mxs.
- *
- * Copyright 2010 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright (C) 2011 Wolfram Sang, Pengutronix e.K.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/platform_device.h>
-#include <linux/gpio.h>
-#include <linux/spi/spi.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-
-#include <mach/common.h>
-#include <mach/iomux-mx23.h>
-
-#include "devices-mx23.h"
-
-#define STMP378X_DEVB_MMC0_WRITE_PROTECT	MXS_GPIO_NR(1, 30)
-#define STMP378X_DEVB_MMC0_SLOT_POWER		MXS_GPIO_NR(1, 29)
-
-#define STMP378X_DEVB_PAD_AUART (MXS_PAD_4MA | MXS_PAD_1V8 | MXS_PAD_NOPULL)
-
-static const iomux_cfg_t stmp378x_dvb_pads[] __initconst = {
-	/* duart (extended setup missing in old boardcode, too */
-	MX23_PAD_PWM0__DUART_RX,
-	MX23_PAD_PWM1__DUART_TX,
-
-	/* auart */
-	MX23_PAD_AUART1_RX__AUART1_RX | STMP378X_DEVB_PAD_AUART,
-	MX23_PAD_AUART1_TX__AUART1_TX | STMP378X_DEVB_PAD_AUART,
-	MX23_PAD_AUART1_CTS__AUART1_CTS | STMP378X_DEVB_PAD_AUART,
-	MX23_PAD_AUART1_RTS__AUART1_RTS | STMP378X_DEVB_PAD_AUART,
-
-	/* mmc */
-	MX23_PAD_SSP1_DATA0__SSP1_DATA0 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX23_PAD_SSP1_DATA1__SSP1_DATA1 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX23_PAD_SSP1_DATA2__SSP1_DATA2 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX23_PAD_SSP1_DATA3__SSP1_DATA3 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX23_PAD_SSP1_CMD__SSP1_CMD |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX23_PAD_SSP1_DETECT__SSP1_DETECT |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
-	MX23_PAD_SSP1_SCK__SSP1_SCK |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
-	MX23_PAD_PWM4__GPIO_1_30 | MXS_PAD_CTRL, /* write protect */
-	MX23_PAD_PWM3__GPIO_1_29 | MXS_PAD_CTRL, /* power enable */
-};
-
-static struct mxs_mmc_platform_data stmp378x_dvb_mmc_pdata __initdata = {
-	.wp_gpio = STMP378X_DEVB_MMC0_WRITE_PROTECT,
-};
-
-static struct spi_board_info spi_board_info[] __initdata = {
-#if defined(CONFIG_ENC28J60) || defined(CONFIG_ENC28J60_MODULE)
-	{
-		.modalias       = "enc28j60",
-		.max_speed_hz   = 6 * 1000 * 1000,
-		.bus_num	= 1,
-		.chip_select    = 0,
-		.platform_data  = NULL,
-	},
-#endif
-};
-
-static void __init stmp378x_dvb_init(void)
-{
-	int ret;
-
-	mx23_soc_init();
-
-	mxs_iomux_setup_multiple_pads(stmp378x_dvb_pads,
-			ARRAY_SIZE(stmp378x_dvb_pads));
-
-	mx23_add_duart();
-	mx23_add_auart0();
-	mx23_add_rtc_stmp3xxx();
-
-	/* power on mmc slot */
-	ret = gpio_request_one(STMP378X_DEVB_MMC0_SLOT_POWER,
-		GPIOF_OUT_INIT_LOW, "mmc0-slot-power");
-	if (ret)
-		pr_warn("could not power mmc (%d)\n", ret);
-
-	mx23_add_mxs_mmc(0, &stmp378x_dvb_mmc_pdata);
-
-	spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
-}
-
-static void __init stmp378x_dvb_timer_init(void)
-{
-	mx23_clocks_init();
-}
-
-static struct sys_timer stmp378x_dvb_timer = {
-	.init	= stmp378x_dvb_timer_init,
-};
-
-MACHINE_START(STMP378X, "STMP378X")
-	.map_io		= mx23_map_io,
-	.init_irq	= mx23_init_irq,
-	.timer		= &stmp378x_dvb_timer,
-	.init_machine	= stmp378x_dvb_init,
-	.restart	= mxs_restart,
-MACHINE_END
diff --git a/arch/arm/mach-mxs/mach-tx28.c b/arch/arm/mach-mxs/mach-tx28.c
deleted file mode 100644
index 8837029..0000000
--- a/arch/arm/mach-mxs/mach-tx28.c
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright (C) 2010 <LW@KARO-electronics.de>
- *
- * based on: mach-mx28_evk.c
- * Copyright 2010 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation
- */
-#include <linux/kernel.h>
-#include <linux/gpio.h>
-#include <linux/leds.h>
-#include <linux/platform_device.h>
-#include <linux/spi/spi.h>
-#include <linux/spi/spi_gpio.h>
-#include <linux/i2c.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-
-#include <mach/common.h>
-#include <mach/iomux-mx28.h>
-
-#include "devices-mx28.h"
-#include "module-tx28.h"
-
-#define TX28_STK5_GPIO_LED		MXS_GPIO_NR(4, 10)
-
-static const iomux_cfg_t tx28_stk5v3_pads[] __initconst = {
-	/* LED */
-	MX28_PAD_ENET0_RXD3__GPIO_4_10 |
-		MXS_PAD_3V3 | MXS_PAD_4MA | MXS_PAD_NOPULL,
-
-	/* framebuffer */
-#define LCD_MODE (MXS_PAD_3V3 | MXS_PAD_4MA)
-	MX28_PAD_LCD_D00__LCD_D0 | LCD_MODE,
-	MX28_PAD_LCD_D01__LCD_D1 | LCD_MODE,
-	MX28_PAD_LCD_D02__LCD_D2 | LCD_MODE,
-	MX28_PAD_LCD_D03__LCD_D3 | LCD_MODE,
-	MX28_PAD_LCD_D04__LCD_D4 | LCD_MODE,
-	MX28_PAD_LCD_D05__LCD_D5 | LCD_MODE,
-	MX28_PAD_LCD_D06__LCD_D6 | LCD_MODE,
-	MX28_PAD_LCD_D07__LCD_D7 | LCD_MODE,
-	MX28_PAD_LCD_D08__LCD_D8 | LCD_MODE,
-	MX28_PAD_LCD_D09__LCD_D9 | LCD_MODE,
-	MX28_PAD_LCD_D10__LCD_D10 | LCD_MODE,
-	MX28_PAD_LCD_D11__LCD_D11 | LCD_MODE,
-	MX28_PAD_LCD_D12__LCD_D12 | LCD_MODE,
-	MX28_PAD_LCD_D13__LCD_D13 | LCD_MODE,
-	MX28_PAD_LCD_D14__LCD_D14 | LCD_MODE,
-	MX28_PAD_LCD_D15__LCD_D15 | LCD_MODE,
-	MX28_PAD_LCD_D16__LCD_D16 | LCD_MODE,
-	MX28_PAD_LCD_D17__LCD_D17 | LCD_MODE,
-	MX28_PAD_LCD_D18__LCD_D18 | LCD_MODE,
-	MX28_PAD_LCD_D19__LCD_D19 | LCD_MODE,
-	MX28_PAD_LCD_D20__LCD_D20 | LCD_MODE,
-	MX28_PAD_LCD_D21__LCD_D21 | LCD_MODE,
-	MX28_PAD_LCD_D22__LCD_D22 | LCD_MODE,
-	MX28_PAD_LCD_D23__LCD_D23 | LCD_MODE,
-	MX28_PAD_LCD_RD_E__LCD_VSYNC | LCD_MODE,
-	MX28_PAD_LCD_WR_RWN__LCD_HSYNC | LCD_MODE,
-	MX28_PAD_LCD_RS__LCD_DOTCLK | LCD_MODE,
-	MX28_PAD_LCD_CS__LCD_CS | LCD_MODE,
-	MX28_PAD_LCD_VSYNC__LCD_VSYNC | LCD_MODE,
-	MX28_PAD_LCD_HSYNC__LCD_HSYNC | LCD_MODE,
-	MX28_PAD_LCD_DOTCLK__LCD_DOTCLK | LCD_MODE,
-	MX28_PAD_LCD_ENABLE__GPIO_1_31 | LCD_MODE,
-	MX28_PAD_LCD_RESET__GPIO_3_30 | LCD_MODE,
-	MX28_PAD_PWM0__PWM_0 | LCD_MODE,
-
-	/* UART1 */
-	MX28_PAD_AUART0_CTS__DUART_RX,
-	MX28_PAD_AUART0_RTS__DUART_TX,
-	MX28_PAD_AUART0_TX__DUART_RTS,
-	MX28_PAD_AUART0_RX__DUART_CTS,
-
-	/* UART2 */
-	MX28_PAD_AUART1_RX__AUART1_RX,
-	MX28_PAD_AUART1_TX__AUART1_TX,
-	MX28_PAD_AUART1_RTS__AUART1_RTS,
-	MX28_PAD_AUART1_CTS__AUART1_CTS,
-
-	/* CAN */
-	MX28_PAD_GPMI_RDY2__CAN0_TX,
-	MX28_PAD_GPMI_RDY3__CAN0_RX,
-
-	/* I2C */
-	MX28_PAD_I2C0_SCL__I2C0_SCL,
-	MX28_PAD_I2C0_SDA__I2C0_SDA,
-
-	/* TSC2007 */
-	MX28_PAD_SAIF0_MCLK__GPIO_3_20 | MXS_PAD_3V3 | MXS_PAD_4MA | MXS_PAD_PULLUP,
-
-	/* MMC0 */
-	MX28_PAD_SSP0_DATA0__SSP0_D0 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_SSP0_DATA1__SSP0_D1 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_SSP0_DATA2__SSP0_D2 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_SSP0_DATA3__SSP0_D3 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_SSP0_CMD__SSP0_CMD |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_SSP0_DETECT__SSP0_CARD_DETECT |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
-	MX28_PAD_SSP0_SCK__SSP0_SCK |
-		(MXS_PAD_12MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
-};
-
-static const struct gpio_led tx28_stk5v3_leds[] __initconst = {
-	{
-		.name = "GPIO-LED",
-		.default_trigger = "heartbeat",
-		.gpio = TX28_STK5_GPIO_LED,
-	},
-};
-
-static const struct gpio_led_platform_data tx28_stk5v3_led_data __initconst = {
-	.leds = tx28_stk5v3_leds,
-	.num_leds = ARRAY_SIZE(tx28_stk5v3_leds),
-};
-
-static struct spi_board_info tx28_spi_board_info[] = {
-	{
-		.modalias = "spidev",
-		.max_speed_hz = 20000000,
-		.bus_num = 0,
-		.chip_select = 1,
-		.controller_data = (void *)SPI_GPIO_NO_CHIPSELECT,
-		.mode = SPI_MODE_0,
-	},
-};
-
-static struct i2c_board_info tx28_stk5v3_i2c_boardinfo[] __initdata = {
-	{
-		I2C_BOARD_INFO("ds1339", 0x68),
-	},
-};
-
-static struct mxs_mmc_platform_data tx28_mmc0_pdata __initdata = {
-       .wp_gpio = -EINVAL,
-       .flags = SLOTF_4_BIT_CAPABLE,
-};
-
-static void __init tx28_stk5v3_init(void)
-{
-	mx28_soc_init();
-
-	mxs_iomux_setup_multiple_pads(tx28_stk5v3_pads,
-			ARRAY_SIZE(tx28_stk5v3_pads));
-
-	mx28_add_duart(); /* UART1 */
-	mx28_add_auart(1); /* UART2 */
-
-	tx28_add_fec0();
-	/* spi via ssp will be added when available */
-	spi_register_board_info(tx28_spi_board_info,
-			ARRAY_SIZE(tx28_spi_board_info));
-	gpio_led_register_device(0, &tx28_stk5v3_led_data);
-	mx28_add_mxs_i2c(0);
-	i2c_register_board_info(0, tx28_stk5v3_i2c_boardinfo,
-			ARRAY_SIZE(tx28_stk5v3_i2c_boardinfo));
-	mx28_add_mxs_mmc(0, &tx28_mmc0_pdata);
-	mx28_add_rtc_stmp3xxx();
-}
-
-static void __init tx28_timer_init(void)
-{
-	mx28_clocks_init();
-}
-
-static struct sys_timer tx28_timer = {
-	.init = tx28_timer_init,
-};
-
-MACHINE_START(TX28, "Ka-Ro electronics TX28 module")
-	.map_io = mx28_map_io,
-	.init_irq = mx28_init_irq,
-	.timer = &tx28_timer,
-	.init_machine = tx28_stk5v3_init,
-	.restart	= mxs_restart,
-MACHINE_END
diff --git a/arch/arm/mach-mxs/mm.c b/arch/arm/mach-mxs/mm.c
index dccb67a..a4294aa 100644
--- a/arch/arm/mach-mxs/mm.c
+++ b/arch/arm/mach-mxs/mm.c
@@ -13,14 +13,11 @@
 
 #include <linux/mm.h>
 #include <linux/init.h>
-#include <linux/pinctrl/machine.h>
 
 #include <asm/mach/map.h>
 
 #include <mach/mx23.h>
 #include <mach/mx28.h>
-#include <mach/common.h>
-#include <mach/iomux.h>
 
 /*
  * Define the MX23 memory map.
@@ -48,43 +45,7 @@ void __init mx23_map_io(void)
 	iotable_init(mx23_io_desc, ARRAY_SIZE(mx23_io_desc));
 }
 
-void __init mx23_init_irq(void)
-{
-	icoll_init_irq();
-}
-
 void __init mx28_map_io(void)
 {
 	iotable_init(mx28_io_desc, ARRAY_SIZE(mx28_io_desc));
 }
-
-void __init mx28_init_irq(void)
-{
-	icoll_init_irq();
-}
-
-void __init mx23_soc_init(void)
-{
-	pinctrl_provide_dummies();
-
-	mxs_add_dma("imx23-dma-apbh", MX23_APBH_DMA_BASE_ADDR);
-	mxs_add_dma("imx23-dma-apbx", MX23_APBX_DMA_BASE_ADDR);
-
-	mxs_add_gpio("imx23-gpio", 0, MX23_PINCTRL_BASE_ADDR, MX23_INT_GPIO0);
-	mxs_add_gpio("imx23-gpio", 1, MX23_PINCTRL_BASE_ADDR, MX23_INT_GPIO1);
-	mxs_add_gpio("imx23-gpio", 2, MX23_PINCTRL_BASE_ADDR, MX23_INT_GPIO2);
-}
-
-void __init mx28_soc_init(void)
-{
-	pinctrl_provide_dummies();
-
-	mxs_add_dma("imx28-dma-apbh", MX23_APBH_DMA_BASE_ADDR);
-	mxs_add_dma("imx28-dma-apbx", MX23_APBX_DMA_BASE_ADDR);
-
-	mxs_add_gpio("imx28-gpio", 0, MX28_PINCTRL_BASE_ADDR, MX28_INT_GPIO0);
-	mxs_add_gpio("imx28-gpio", 1, MX28_PINCTRL_BASE_ADDR, MX28_INT_GPIO1);
-	mxs_add_gpio("imx28-gpio", 2, MX28_PINCTRL_BASE_ADDR, MX28_INT_GPIO2);
-	mxs_add_gpio("imx28-gpio", 3, MX28_PINCTRL_BASE_ADDR, MX28_INT_GPIO3);
-	mxs_add_gpio("imx28-gpio", 4, MX28_PINCTRL_BASE_ADDR, MX28_INT_GPIO4);
-}
diff --git a/arch/arm/mach-mxs/module-tx28.c b/arch/arm/mach-mxs/module-tx28.c
deleted file mode 100644
index 0f71f82..0000000
--- a/arch/arm/mach-mxs/module-tx28.c
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * Copyright (C) 2010 <LW@KARO-electronics.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/delay.h>
-#include <linux/fec.h>
-#include <linux/gpio.h>
-
-#include <mach/iomux-mx28.h>
-#include "devices-mx28.h"
-
-#include "module-tx28.h"
-
-#define TX28_FEC_PHY_POWER	MXS_GPIO_NR(3, 29)
-#define TX28_FEC_PHY_RESET	MXS_GPIO_NR(4, 13)
-
-static const iomux_cfg_t tx28_fec_gpio_pads[] __initconst = {
-	/* PHY POWER */
-	MX28_PAD_PWM4__GPIO_3_29 |
-		MXS_PAD_4MA | MXS_PAD_NOPULL | MXS_PAD_3V3,
-	/* PHY RESET */
-	MX28_PAD_ENET0_RX_CLK__GPIO_4_13 |
-		MXS_PAD_4MA | MXS_PAD_NOPULL | MXS_PAD_3V3,
-	/* Mode strap pins 0-2 */
-	MX28_PAD_ENET0_RXD0__GPIO_4_3 |
-		MXS_PAD_8MA | MXS_PAD_PULLUP | MXS_PAD_3V3,
-	MX28_PAD_ENET0_RXD1__GPIO_4_4 |
-		MXS_PAD_8MA | MXS_PAD_PULLUP | MXS_PAD_3V3,
-	MX28_PAD_ENET0_RX_EN__GPIO_4_2 |
-		MXS_PAD_8MA | MXS_PAD_PULLUP | MXS_PAD_3V3,
-	/* nINT */
-	MX28_PAD_ENET0_TX_CLK__GPIO_4_5 |
-		MXS_PAD_4MA | MXS_PAD_NOPULL | MXS_PAD_3V3,
-
-	MX28_PAD_ENET0_MDC__GPIO_4_0,
-	MX28_PAD_ENET0_MDIO__GPIO_4_1,
-	MX28_PAD_ENET0_TX_EN__GPIO_4_6,
-	MX28_PAD_ENET0_TXD0__GPIO_4_7,
-	MX28_PAD_ENET0_TXD1__GPIO_4_8,
-	MX28_PAD_ENET_CLK__GPIO_4_16,
-};
-
-#define FEC_MODE (MXS_PAD_8MA | MXS_PAD_PULLUP | MXS_PAD_3V3)
-static const iomux_cfg_t tx28_fec0_pads[] __initconst = {
-	MX28_PAD_ENET0_MDC__ENET0_MDC | FEC_MODE,
-	MX28_PAD_ENET0_MDIO__ENET0_MDIO | FEC_MODE,
-	MX28_PAD_ENET0_RX_EN__ENET0_RX_EN | FEC_MODE,
-	MX28_PAD_ENET0_RXD0__ENET0_RXD0 | FEC_MODE,
-	MX28_PAD_ENET0_RXD1__ENET0_RXD1 | FEC_MODE,
-	MX28_PAD_ENET0_TX_EN__ENET0_TX_EN | FEC_MODE,
-	MX28_PAD_ENET0_TXD0__ENET0_TXD0 | FEC_MODE,
-	MX28_PAD_ENET0_TXD1__ENET0_TXD1 | FEC_MODE,
-	MX28_PAD_ENET_CLK__CLKCTRL_ENET | FEC_MODE,
-};
-
-static const iomux_cfg_t tx28_fec1_pads[] __initconst = {
-	MX28_PAD_ENET0_RXD2__ENET1_RXD0,
-	MX28_PAD_ENET0_RXD3__ENET1_RXD1,
-	MX28_PAD_ENET0_TXD2__ENET1_TXD0,
-	MX28_PAD_ENET0_TXD3__ENET1_TXD1,
-	MX28_PAD_ENET0_COL__ENET1_TX_EN,
-	MX28_PAD_ENET0_CRS__ENET1_RX_EN,
-};
-
-static const struct fec_platform_data tx28_fec0_data __initconst = {
-	.phy = PHY_INTERFACE_MODE_RMII,
-};
-
-static const struct fec_platform_data tx28_fec1_data __initconst = {
-	.phy = PHY_INTERFACE_MODE_RMII,
-};
-
-int __init tx28_add_fec0(void)
-{
-	int i, ret;
-
-	pr_debug("%s: Switching FEC PHY power off\n", __func__);
-	ret = mxs_iomux_setup_multiple_pads(tx28_fec_gpio_pads,
-			ARRAY_SIZE(tx28_fec_gpio_pads));
-	for (i = 0; i < ARRAY_SIZE(tx28_fec_gpio_pads); i++) {
-		unsigned int gpio = MXS_GPIO_NR(PAD_BANK(tx28_fec_gpio_pads[i]),
-			PAD_PIN(tx28_fec_gpio_pads[i]));
-
-		ret = gpio_request(gpio, "FEC");
-		if (ret) {
-			pr_err("Failed to request GPIO_%d_%d: %d\n",
-				PAD_BANK(tx28_fec_gpio_pads[i]),
-				PAD_PIN(tx28_fec_gpio_pads[i]), ret);
-			goto free_gpios;
-		}
-		ret = gpio_direction_output(gpio, 0);
-		if (ret) {
-			pr_err("Failed to set direction of GPIO_%d_%d to output: %d\n",
-					gpio / 32 + 1, gpio % 32, ret);
-			goto free_gpios;
-		}
-	}
-
-	/* Power up fec phy */
-	pr_debug("%s: Switching FEC PHY power on\n", __func__);
-	ret = gpio_direction_output(TX28_FEC_PHY_POWER, 1);
-	if (ret) {
-		pr_err("Failed to power on PHY: %d\n", ret);
-		goto free_gpios;
-	}
-	mdelay(26); /* 25ms according to data sheet */
-
-	/* nINT */
-	gpio_direction_input(MXS_GPIO_NR(4, 5));
-	/* Mode strap pins */
-	gpio_direction_output(MXS_GPIO_NR(4, 2), 1);
-	gpio_direction_output(MXS_GPIO_NR(4, 3), 1);
-	gpio_direction_output(MXS_GPIO_NR(4, 4), 1);
-
-	udelay(100); /* minimum assertion time for nRST */
-
-	pr_debug("%s: Deasserting FEC PHY RESET\n", __func__);
-	gpio_set_value(TX28_FEC_PHY_RESET, 1);
-
-	ret = mxs_iomux_setup_multiple_pads(tx28_fec0_pads,
-			ARRAY_SIZE(tx28_fec0_pads));
-	if (ret) {
-		pr_debug("%s: mxs_iomux_setup_multiple_pads() failed with rc: %d\n",
-				__func__, ret);
-		goto free_gpios;
-	}
-	pr_debug("%s: Registering FEC0 device\n", __func__);
-	mx28_add_fec(0, &tx28_fec0_data);
-	return 0;
-
-free_gpios:
-	while (--i >= 0) {
-		unsigned int gpio = MXS_GPIO_NR(PAD_BANK(tx28_fec_gpio_pads[i]),
-			PAD_PIN(tx28_fec_gpio_pads[i]));
-
-		gpio_free(gpio);
-	}
-
-	return ret;
-}
-
-int __init tx28_add_fec1(void)
-{
-	int ret;
-
-	ret = mxs_iomux_setup_multiple_pads(tx28_fec1_pads,
-			ARRAY_SIZE(tx28_fec1_pads));
-	if (ret) {
-		pr_debug("%s: mxs_iomux_setup_multiple_pads() failed with rc: %d\n",
-				__func__, ret);
-		return ret;
-	}
-	pr_debug("%s: Registering FEC1 device\n", __func__);
-	mx28_add_fec(1, &tx28_fec1_data);
-	return 0;
-}
diff --git a/arch/arm/mach-mxs/module-tx28.h b/arch/arm/mach-mxs/module-tx28.h
deleted file mode 100644
index 8ed4254..0000000
--- a/arch/arm/mach-mxs/module-tx28.h
+++ /dev/null
@@ -1,10 +0,0 @@
-/*
- * Copyright (C) 2010 Pengutronix
- *   Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License version 2 as published by the
- * Free Software Foundation.
- */
-int __init tx28_add_fec0(void);
-int __init tx28_add_fec1(void);
diff --git a/arch/arm/mach-mxs/timer.c b/arch/arm/mach-mxs/timer.c
index 02d36de..7c37926 100644
--- a/arch/arm/mach-mxs/timer.c
+++ b/arch/arm/mach-mxs/timer.c
@@ -25,6 +25,8 @@
 #include <linux/irq.h>
 #include <linux/clockchips.h>
 #include <linux/clk.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
 
 #include <asm/mach/time.h>
 #include <mach/mxs.h>
@@ -244,9 +246,17 @@ static int __init mxs_clocksource_init(struct clk *timer_clk)
 	return 0;
 }
 
-void __init mxs_timer_init(int irq)
+void __init mxs_timer_init(void)
 {
+	struct device_node *np;
 	struct clk *timer_clk;
+	int irq;
+
+	np = of_find_compatible_node(NULL, NULL, "fsl,timrot");
+	if (!np) {
+		pr_err("%s: failed find timrot node\n", __func__);
+		return;
+	}
 
 	timer_clk = clk_get_sys("timrot", NULL);
 	if (IS_ERR(timer_clk)) {
@@ -295,5 +305,6 @@ void __init mxs_timer_init(int irq)
 	mxs_clockevent_init(timer_clk);
 
 	/* Make irqs happen */
+	irq = irq_of_parse_and_map(np, 0);
 	setup_irq(irq, &mxs_timer_irq);
 }
diff --git a/arch/arm/mach-netx/include/mach/eth.h b/arch/arm/mach-netx/include/mach/eth.h
deleted file mode 100644
index 88af1ac..0000000
--- a/arch/arm/mach-netx/include/mach/eth.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * arch/arm/mach-netx/include/mach/eth.h
- *
- * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#ifndef ASMARM_ARCH_ETH_H
-#define ASMARM_ARCH_ETH_H
-
-struct netxeth_platform_data {
-	unsigned int xcno;	/* number of xmac/xpec engine this eth uses */
-};
-
-#endif
diff --git a/arch/arm/mach-netx/nxdb500.c b/arch/arm/mach-netx/nxdb500.c
index 180ea89..8b781ff 100644
--- a/arch/arm/mach-netx/nxdb500.c
+++ b/arch/arm/mach-netx/nxdb500.c
@@ -30,7 +30,7 @@
 #include <asm/mach/arch.h>
 #include <asm/hardware/vic.h>
 #include <mach/netx-regs.h>
-#include <mach/eth.h>
+#include <linux/platform_data/eth-netx.h>
 
 #include "generic.h"
 #include "fb.h"
diff --git a/arch/arm/mach-netx/nxdkn.c b/arch/arm/mach-netx/nxdkn.c
index 58009e2..b26dbce 100644
--- a/arch/arm/mach-netx/nxdkn.c
+++ b/arch/arm/mach-netx/nxdkn.c
@@ -30,7 +30,7 @@
 #include <asm/mach/arch.h>
 #include <asm/hardware/vic.h>
 #include <mach/netx-regs.h>
-#include <mach/eth.h>
+#include <linux/platform_data/eth-netx.h>
 
 #include "generic.h"
 
diff --git a/arch/arm/mach-netx/nxeb500hmi.c b/arch/arm/mach-netx/nxeb500hmi.c
index 122e998..257382e 100644
--- a/arch/arm/mach-netx/nxeb500hmi.c
+++ b/arch/arm/mach-netx/nxeb500hmi.c
@@ -30,7 +30,7 @@
 #include <asm/mach/arch.h>
 #include <asm/hardware/vic.h>
 #include <mach/netx-regs.h>
-#include <mach/eth.h>
+#include <linux/platform_data/eth-netx.h>
 
 #include "generic.h"
 #include "fb.h"
diff --git a/arch/arm/mach-nomadik/board-nhk8815.c b/arch/arm/mach-nomadik/board-nhk8815.c
index f4535a7..b71789a 100644
--- a/arch/arm/mach-nomadik/board-nhk8815.c
+++ b/arch/arm/mach-nomadik/board-nhk8815.c
@@ -23,6 +23,7 @@
 #include <linux/mtd/partitions.h>
 #include <linux/i2c.h>
 #include <linux/io.h>
+#include <linux/pinctrl/machine.h>
 #include <asm/hardware/vic.h>
 #include <asm/sizes.h>
 #include <asm/mach-types.h>
@@ -33,8 +34,9 @@
 
 #include <plat/gpio-nomadik.h>
 #include <plat/mtu.h>
+#include <plat/pincfg.h>
 
-#include <mach/nand.h>
+#include <linux/platform_data/mtd-nomadik-nand.h>
 #include <mach/fsmc.h>
 
 #include "cpu-8815.h"
@@ -291,8 +293,42 @@ static struct i2c_board_info __initdata nhk8815_i2c2_devices[] = {
 	},
 };
 
+static unsigned long out_low[] = { PIN_OUTPUT_LOW };
+static unsigned long out_high[] = { PIN_OUTPUT_HIGH };
+static unsigned long in_nopull[] = { PIN_INPUT_NOPULL };
+static unsigned long in_pullup[] = { PIN_INPUT_PULLUP };
+
+static struct pinctrl_map __initdata nhk8815_pinmap[] = {
+	PIN_MAP_MUX_GROUP_DEFAULT("uart0", "pinctrl-stn8815", "u0_a_1", "u0"),
+	PIN_MAP_MUX_GROUP_DEFAULT("uart1", "pinctrl-stn8815", "u1_a_1", "u1"),
+	/* Hog in MMC/SD card mux */
+	PIN_MAP_MUX_GROUP_HOG_DEFAULT("pinctrl-stn8815", "mmcsd_a_1", "mmcsd"),
+	/* MCCLK */
+	PIN_MAP_CONFIGS_PIN_HOG_DEFAULT("pinctrl-stn8815", "GPIO8_B10", out_low),
+	/* MCCMD */
+	PIN_MAP_CONFIGS_PIN_HOG_DEFAULT("pinctrl-stn8815", "GPIO9_A10", in_pullup),
+	/* MCCMDDIR */
+	PIN_MAP_CONFIGS_PIN_HOG_DEFAULT("pinctrl-stn8815", "GPIO10_C11", out_high),
+	/* MCDAT3-0 */
+	PIN_MAP_CONFIGS_PIN_HOG_DEFAULT("pinctrl-stn8815", "GPIO11_B11", in_pullup),
+	PIN_MAP_CONFIGS_PIN_HOG_DEFAULT("pinctrl-stn8815", "GPIO12_A11", in_pullup),
+	PIN_MAP_CONFIGS_PIN_HOG_DEFAULT("pinctrl-stn8815", "GPIO13_C12", in_pullup),
+	PIN_MAP_CONFIGS_PIN_HOG_DEFAULT("pinctrl-stn8815", "GPIO14_B12", in_pullup),
+	/* MCDAT0DIR */
+	PIN_MAP_CONFIGS_PIN_HOG_DEFAULT("pinctrl-stn8815", "GPIO15_A12", out_high),
+	/* MCDAT31DIR */
+	PIN_MAP_CONFIGS_PIN_HOG_DEFAULT("pinctrl-stn8815", "GPIO16_C13", out_high),
+	/* MCMSFBCLK */
+	PIN_MAP_CONFIGS_PIN_HOG_DEFAULT("pinctrl-stn8815", "GPIO24_C15", in_pullup),
+	/* CD input GPIO */
+	PIN_MAP_CONFIGS_PIN_HOG_DEFAULT("pinctrl-stn8815", "GPIO111_H21", in_nopull),
+	/* CD bias drive */
+	PIN_MAP_CONFIGS_PIN_HOG_DEFAULT("pinctrl-stn8815", "GPIO112_J21", out_low),
+};
+
 static void __init nhk8815_platform_init(void)
 {
+	pinctrl_register_mappings(nhk8815_pinmap, ARRAY_SIZE(nhk8815_pinmap));
 	cpu8815_platform_init();
 	nhk8815_onenand_init();
 	platform_add_devices(nhk8815_platform_devices,
diff --git a/arch/arm/mach-nomadik/cpu-8815.c b/arch/arm/mach-nomadik/cpu-8815.c
index 6fd8e46..b617eae 100644
--- a/arch/arm/mach-nomadik/cpu-8815.c
+++ b/arch/arm/mach-nomadik/cpu-8815.c
@@ -83,6 +83,18 @@ void cpu8815_add_gpios(resource_size_t *base, int num, int irq,
 	}
 }
 
+static inline void
+cpu8815_add_pinctrl(struct device *parent, const char *name)
+{
+	struct platform_device_info pdevinfo = {
+		.parent = parent,
+		.name = name,
+		.id = -1,
+	};
+
+	platform_device_register_full(&pdevinfo);
+}
+
 static int __init cpu8815_init(void)
 {
 	struct nmk_gpio_platform_data pdata = {
@@ -91,6 +103,7 @@ static int __init cpu8815_init(void)
 
 	cpu8815_add_gpios(cpu8815_gpio_base, ARRAY_SIZE(cpu8815_gpio_base),
 			  IRQ_GPIO0, &pdata);
+	cpu8815_add_pinctrl(NULL, "pinctrl-stn8815");
 	amba_apb_device_add(NULL, "rng", NOMADIK_RNG_BASE, SZ_4K, 0, 0, NULL, 0);
 	amba_apb_device_add(NULL, "rtc-pl031", NOMADIK_RTC_BASE, SZ_4K, IRQ_RTC_RTT, 0, NULL, 0);
 	return 0;
diff --git a/arch/arm/mach-nomadik/include/mach/gpio.h b/arch/arm/mach-nomadik/include/mach/gpio.h
deleted file mode 100644
index efdde0a..0000000
--- a/arch/arm/mach-nomadik/include/mach/gpio.h
+++ /dev/null
@@ -1,4 +0,0 @@
-#ifndef __ASM_ARCH_GPIO_H
-#define __ASM_ARCH_GPIO_H
-
-#endif /* __ASM_ARCH_GPIO_H */
diff --git a/arch/arm/mach-nomadik/include/mach/hardware.h b/arch/arm/mach-nomadik/include/mach/hardware.h
index 6316dba..02035e4 100644
--- a/arch/arm/mach-nomadik/include/mach/hardware.h
+++ b/arch/arm/mach-nomadik/include/mach/hardware.h
@@ -30,7 +30,7 @@
 			- NOMADIK_IO_VIRTUAL + NOMADIK_IO_PHYSICAL)
 
 /* used in asm code, so no casts */
-#define IO_ADDRESS(x) ((x) - NOMADIK_IO_PHYSICAL + NOMADIK_IO_VIRTUAL)
+#define IO_ADDRESS(x) IOMEM((x) - NOMADIK_IO_PHYSICAL + NOMADIK_IO_VIRTUAL)
 
 /*
  *   Base address defination for Nomadik Onchip Logic Block
diff --git a/arch/arm/mach-nomadik/include/mach/nand.h b/arch/arm/mach-nomadik/include/mach/nand.h
deleted file mode 100644
index c3c8254..0000000
--- a/arch/arm/mach-nomadik/include/mach/nand.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef __ASM_ARCH_NAND_H
-#define __ASM_ARCH_NAND_H
-
-struct nomadik_nand_platform_data {
-	struct mtd_partition *parts;
-	int nparts;
-	int options;
-	int (*init) (void);
-	int (*exit) (void);
-};
-
-#define NAND_IO_DATA	0x40000000
-#define NAND_IO_CMD	0x40800000
-#define NAND_IO_ADDR	0x41000000
-
-#endif				/* __ASM_ARCH_NAND_H */
diff --git a/arch/arm/mach-nomadik/include/mach/uncompress.h b/arch/arm/mach-nomadik/include/mach/uncompress.h
index 071003b..7d4687e 100644
--- a/arch/arm/mach-nomadik/include/mach/uncompress.h
+++ b/arch/arm/mach-nomadik/include/mach/uncompress.h
@@ -27,10 +27,10 @@
 struct amba_device;
 #include <linux/amba/serial.h>
 
-#define NOMADIK_UART_DR		0x101FB000
-#define NOMADIK_UART_LCRH	0x101FB02c
-#define NOMADIK_UART_CR		0x101FB030
-#define NOMADIK_UART_FR		0x101FB018
+#define NOMADIK_UART_DR		(void __iomem *)0x101FB000
+#define NOMADIK_UART_LCRH	(void __iomem *)0x101FB02c
+#define NOMADIK_UART_CR		(void __iomem *)0x101FB030
+#define NOMADIK_UART_FR		(void __iomem *)0x101FB018
 
 static void putc(const char c)
 {
diff --git a/arch/arm/mach-omap1/Makefile b/arch/arm/mach-omap1/Makefile
index 398e9e5..cd169c3 100644
--- a/arch/arm/mach-omap1/Makefile
+++ b/arch/arm/mach-omap1/Makefile
@@ -61,14 +61,6 @@ obj-$(CONFIG_ARCH_OMAP850)		+= gpio7xx.o
 obj-$(CONFIG_ARCH_OMAP15XX)		+= gpio15xx.o
 obj-$(CONFIG_ARCH_OMAP16XX)		+= gpio16xx.o
 
-# LEDs support
-led-$(CONFIG_MACH_OMAP_H2)		+= leds-h2p2-debug.o
-led-$(CONFIG_MACH_OMAP_H3)		+= leds-h2p2-debug.o
-led-$(CONFIG_MACH_OMAP_INNOVATOR)	+= leds-innovator.o
-led-$(CONFIG_MACH_OMAP_PERSEUS2)	+= leds-h2p2-debug.o
-led-$(CONFIG_MACH_OMAP_OSK)		+= leds-osk.o
-obj-$(CONFIG_LEDS)			+= $(led-y)
-
 ifneq ($(CONFIG_FB_OMAP),)
 obj-y += lcd_dma.o
 endif
diff --git a/arch/arm/mach-omap1/ams-delta-fiq-handler.S b/arch/arm/mach-omap1/ams-delta-fiq-handler.S
index a051cb8..3d1e1c2 100644
--- a/arch/arm/mach-omap1/ams-delta-fiq-handler.S
+++ b/arch/arm/mach-omap1/ams-delta-fiq-handler.S
@@ -16,8 +16,9 @@
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 
-#include <plat/board-ams-delta.h>
+#include <mach/board-ams-delta.h>
 
+#include <mach/irqs.h>
 #include <mach/ams-delta-fiq.h>
 
 #include "iomap.h"
diff --git a/arch/arm/mach-omap1/ams-delta-fiq.c b/arch/arm/mach-omap1/ams-delta-fiq.c
index 68e8e56..f12a12a 100644
--- a/arch/arm/mach-omap1/ams-delta-fiq.c
+++ b/arch/arm/mach-omap1/ams-delta-fiq.c
@@ -19,7 +19,7 @@
 #include <linux/module.h>
 #include <linux/io.h>
 
-#include <plat/board-ams-delta.h>
+#include <mach/board-ams-delta.h>
 
 #include <asm/fiq.h>
 
diff --git a/arch/arm/mach-omap1/board-ams-delta.c b/arch/arm/mach-omap1/board-ams-delta.c
index c534698..9518bf5 100644
--- a/arch/arm/mach-omap1/board-ams-delta.c
+++ b/arch/arm/mach-omap1/board-ams-delta.c
@@ -26,6 +26,7 @@
 #include <linux/export.h>
 #include <linux/omapfb.h>
 #include <linux/io.h>
+#include <linux/platform_data/gpio-omap.h>
 
 #include <media/soc_camera.h>
 
@@ -34,10 +35,9 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include <plat/board-ams-delta.h>
-#include <plat/keypad.h>
-#include <plat/mux.h>
-#include <plat/board.h>
+#include <mach/board-ams-delta.h>
+#include <linux/platform_data/keypad-omap.h>
+#include <mach/mux.h>
 
 #include <mach/hardware.h>
 #include <mach/ams-delta-fiq.h>
diff --git a/arch/arm/mach-omap1/board-fsample.c b/arch/arm/mach-omap1/board-fsample.c
index 6872f3f..4b6de70 100644
--- a/arch/arm/mach-omap1/board-fsample.c
+++ b/arch/arm/mach-omap1/board-fsample.c
@@ -28,11 +28,10 @@
 #include <asm/mach/map.h>
 
 #include <plat/tc.h>
-#include <plat/mux.h>
-#include <plat/flash.h>
+#include <mach/mux.h>
+#include <mach/flash.h>
 #include <plat/fpga.h>
-#include <plat/keypad.h>
-#include <plat/board.h>
+#include <linux/platform_data/keypad-omap.h>
 
 #include <mach/hardware.h>
 
diff --git a/arch/arm/mach-omap1/board-generic.c b/arch/arm/mach-omap1/board-generic.c
index 6ec385e..4ec579f 100644
--- a/arch/arm/mach-omap1/board-generic.c
+++ b/arch/arm/mach-omap1/board-generic.c
@@ -22,8 +22,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include <plat/mux.h>
-#include <plat/board.h>
+#include <mach/mux.h>
 
 #include <mach/usb.h>
 
@@ -52,9 +51,6 @@ static struct omap_usb_config generic1610_usb_config __initdata = {
 };
 #endif
 
-static struct omap_board_config_kernel generic_config[] __initdata = {
-};
-
 static void __init omap_generic_init(void)
 {
 #ifdef CONFIG_ARCH_OMAP15XX
@@ -76,8 +72,6 @@ static void __init omap_generic_init(void)
 	}
 #endif
 
-	omap_board_config = generic_config;
-	omap_board_config_size = ARRAY_SIZE(generic_config);
 	omap_serial_init();
 	omap_register_i2c_bus(1, 100, NULL, 0);
 }
diff --git a/arch/arm/mach-omap1/board-h2.c b/arch/arm/mach-omap1/board-h2.c
index 44a4ab1..a2e53e1 100644
--- a/arch/arm/mach-omap1/board-h2.c
+++ b/arch/arm/mach-omap1/board-h2.c
@@ -31,17 +31,19 @@
 #include <linux/i2c/tps65010.h>
 #include <linux/smc91x.h>
 #include <linux/omapfb.h>
+#include <linux/leds.h>
+#include <linux/platform_data/gpio-omap.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include <plat/mux.h>
+#include <mach/mux.h>
 #include <plat/dma.h>
 #include <plat/tc.h>
-#include <plat/irda.h>
-#include <plat/keypad.h>
-#include <plat/flash.h>
+#include <mach/irda.h>
+#include <linux/platform_data/keypad-omap.h>
+#include <mach/flash.h>
 
 #include <mach/hardware.h>
 #include <mach/usb.h>
@@ -306,12 +308,39 @@ static struct platform_device h2_irda_device = {
 	.resource	= h2_irda_resources,
 };
 
+static struct gpio_led h2_gpio_led_pins[] = {
+	{
+		.name		= "h2:red",
+		.default_trigger = "heartbeat",
+		.gpio		= 3,
+	},
+	{
+		.name		= "h2:green",
+		.default_trigger = "cpu0",
+		.gpio		= OMAP_MPUIO(4),
+	},
+};
+
+static struct gpio_led_platform_data h2_gpio_led_data = {
+	.leds		= h2_gpio_led_pins,
+	.num_leds	= ARRAY_SIZE(h2_gpio_led_pins),
+};
+
+static struct platform_device h2_gpio_leds = {
+	.name	= "leds-gpio",
+	.id	= -1,
+	.dev	= {
+		.platform_data = &h2_gpio_led_data,
+	},
+};
+
 static struct platform_device *h2_devices[] __initdata = {
 	&h2_nor_device,
 	&h2_nand_device,
 	&h2_smc91x_device,
 	&h2_irda_device,
 	&h2_kp_device,
+	&h2_gpio_leds,
 };
 
 static void __init h2_init_smc91x(void)
@@ -406,6 +435,10 @@ static void __init h2_init(void)
 	omap_cfg_reg(E19_1610_KBR4);
 	omap_cfg_reg(N19_1610_KBR5);
 
+	/* GPIO based LEDs */
+	omap_cfg_reg(P18_1610_GPIO3);
+	omap_cfg_reg(MPUIO4);
+
 	h2_smc91x_resources[1].start = gpio_to_irq(0);
 	h2_smc91x_resources[1].end = gpio_to_irq(0);
 	platform_add_devices(h2_devices, ARRAY_SIZE(h2_devices));
diff --git a/arch/arm/mach-omap1/board-h3.c b/arch/arm/mach-omap1/board-h3.c
index 86cb5a0..fa98327 100644
--- a/arch/arm/mach-omap1/board-h3.c
+++ b/arch/arm/mach-omap1/board-h3.c
@@ -31,6 +31,8 @@
 #include <linux/i2c/tps65010.h>
 #include <linux/smc91x.h>
 #include <linux/omapfb.h>
+#include <linux/leds.h>
+#include <linux/platform_data/gpio-omap.h>
 
 #include <asm/setup.h>
 #include <asm/page.h>
@@ -38,11 +40,11 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include <plat/mux.h>
+#include <mach/mux.h>
 #include <plat/tc.h>
-#include <plat/keypad.h>
+#include <linux/platform_data/keypad-omap.h>
 #include <plat/dma.h>
-#include <plat/flash.h>
+#include <mach/flash.h>
 
 #include <mach/hardware.h>
 #include <mach/irqs.h>
@@ -324,6 +326,32 @@ static struct spi_board_info h3_spi_board_info[] __initdata = {
 	},
 };
 
+static struct gpio_led h3_gpio_led_pins[] = {
+	{
+		.name		= "h3:red",
+		.default_trigger = "heartbeat",
+		.gpio		= 3,
+	},
+	{
+		.name		= "h3:green",
+		.default_trigger = "cpu0",
+		.gpio		= OMAP_MPUIO(4),
+	},
+};
+
+static struct gpio_led_platform_data h3_gpio_led_data = {
+	.leds		= h3_gpio_led_pins,
+	.num_leds	= ARRAY_SIZE(h3_gpio_led_pins),
+};
+
+static struct platform_device h3_gpio_leds = {
+	.name	= "leds-gpio",
+	.id	= -1,
+	.dev	= {
+		.platform_data = &h3_gpio_led_data,
+	},
+};
+
 static struct platform_device *devices[] __initdata = {
 	&nor_device,
 	&nand_device,
@@ -331,6 +359,7 @@ static struct platform_device *devices[] __initdata = {
 	&intlat_device,
 	&h3_kp_device,
 	&h3_lcd_device,
+	&h3_gpio_leds,
 };
 
 static struct omap_usb_config h3_usb_config __initdata = {
@@ -398,6 +427,10 @@ static void __init h3_init(void)
 	omap_cfg_reg(E19_1610_KBR4);
 	omap_cfg_reg(N19_1610_KBR5);
 
+	/* GPIO based LEDs */
+	omap_cfg_reg(P18_1610_GPIO3);
+	omap_cfg_reg(MPUIO4);
+
 	smc91x_resources[1].start = gpio_to_irq(40);
 	smc91x_resources[1].end = gpio_to_irq(40);
 	platform_add_devices(devices, ARRAY_SIZE(devices));
diff --git a/arch/arm/mach-omap1/board-htcherald.c b/arch/arm/mach-omap1/board-htcherald.c
index b3f6e94..87ab208 100644
--- a/arch/arm/mach-omap1/board-htcherald.c
+++ b/arch/arm/mach-omap1/board-htcherald.c
@@ -37,13 +37,12 @@
 #include <linux/spi/spi.h>
 #include <linux/spi/ads7846.h>
 #include <linux/omapfb.h>
+#include <linux/platform_data/keypad-omap.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
-#include <plat/omap7xx.h>
-#include <plat/board.h>
-#include <plat/keypad.h>
+#include <mach/omap7xx.h>
 #include <plat/mmc.h>
 
 #include <mach/irqs.h>
@@ -476,8 +475,7 @@ static void __init htcherald_lcd_init(void)
 				break;
 		}
 		if (!tries)
-			printk(KERN_WARNING "Timeout waiting for end of frame "
-			       "-- LCD may not be available\n");
+			pr_err("Timeout waiting for end of frame -- LCD may not be available\n");
 
 		/* turn off DMA */
 		reg = omap_readw(OMAP_DMA_LCD_CCR);
diff --git a/arch/arm/mach-omap1/board-innovator.c b/arch/arm/mach-omap1/board-innovator.c
index f21c296..db5f7d2 100644
--- a/arch/arm/mach-omap1/board-innovator.c
+++ b/arch/arm/mach-omap1/board-innovator.c
@@ -31,11 +31,11 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include <plat/mux.h>
-#include <plat/flash.h>
+#include <mach/mux.h>
+#include <mach/flash.h>
 #include <plat/fpga.h>
 #include <plat/tc.h>
-#include <plat/keypad.h>
+#include <linux/platform_data/keypad-omap.h>
 #include <plat/mmc.h>
 
 #include <mach/hardware.h>
diff --git a/arch/arm/mach-omap1/board-nokia770.c b/arch/arm/mach-omap1/board-nokia770.c
index 2c0ca8f..7d5c06d 100644
--- a/arch/arm/mach-omap1/board-nokia770.c
+++ b/arch/arm/mach-omap1/board-nokia770.c
@@ -21,14 +21,14 @@
 #include <linux/workqueue.h>
 #include <linux/delay.h>
 
+#include <linux/platform_data/keypad-omap.h>
+#include <linux/platform_data/lcd-mipid.h>
+
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include <plat/mux.h>
-#include <plat/board.h>
-#include <plat/keypad.h>
-#include <plat/lcd_mipid.h>
+#include <mach/mux.h>
 #include <plat/mmc.h>
 #include <plat/clock.h>
 
diff --git a/arch/arm/mach-omap1/board-osk.c b/arch/arm/mach-omap1/board-osk.c
index 8784705..5973945 100644
--- a/arch/arm/mach-omap1/board-osk.c
+++ b/arch/arm/mach-omap1/board-osk.c
@@ -39,13 +39,15 @@
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/physmap.h>
 #include <linux/i2c/tps65010.h>
+#include <linux/platform_data/gpio-omap.h>
+#include <linux/platform_data/omap1_bl.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include <plat/flash.h>
-#include <plat/mux.h>
+#include <mach/flash.h>
+#include <mach/mux.h>
 #include <plat/tc.h>
 
 #include <mach/hardware.h>
@@ -302,7 +304,7 @@ static struct omap_lcd_config osk_lcd_config __initdata = {
 #include <linux/spi/spi.h>
 #include <linux/spi/ads7846.h>
 
-#include <plat/keypad.h>
+#include <linux/platform_data/keypad-omap.h>
 
 static struct at24_platform_data at24c04 = {
 	.byte_len	= SZ_4K / 8,
@@ -380,10 +382,37 @@ static struct platform_device osk5912_lcd_device = {
 	.id		= -1,
 };
 
+static struct gpio_led mistral_gpio_led_pins[] = {
+	{
+		.name		= "mistral:red",
+		.default_trigger = "heartbeat",
+		.gpio		= 3,
+	},
+	{
+		.name		= "mistral:green",
+		.default_trigger = "cpu0",
+		.gpio		= OMAP_MPUIO(4),
+	},
+};
+
+static struct gpio_led_platform_data mistral_gpio_led_data = {
+	.leds		= mistral_gpio_led_pins,
+	.num_leds	= ARRAY_SIZE(mistral_gpio_led_pins),
+};
+
+static struct platform_device mistral_gpio_leds = {
+	.name	= "leds-gpio",
+	.id	= -1,
+	.dev	= {
+		.platform_data = &mistral_gpio_led_data,
+	},
+};
+
 static struct platform_device *mistral_devices[] __initdata = {
 	&osk5912_kp_device,
 	&mistral_bl_device,
 	&osk5912_lcd_device,
+	&mistral_gpio_leds,
 };
 
 static int mistral_get_pendown_state(void)
@@ -508,6 +537,12 @@ static void __init osk_mistral_init(void)
 	if (gpio_request(2, "lcd_pwr") == 0)
 		gpio_direction_output(2, 1);
 
+	/*
+	 * GPIO based LEDs
+	 */
+	omap_cfg_reg(P18_1610_GPIO3);
+	omap_cfg_reg(MPUIO4);
+
 	i2c_register_board_info(1, mistral_i2c_board_info,
 			ARRAY_SIZE(mistral_i2c_board_info));
 
diff --git a/arch/arm/mach-omap1/board-palmte.c b/arch/arm/mach-omap1/board-palmte.c
index 26bcb9d..1c578d5 100644
--- a/arch/arm/mach-omap1/board-palmte.c
+++ b/arch/arm/mach-omap1/board-palmte.c
@@ -28,18 +28,18 @@
 #include <linux/interrupt.h>
 #include <linux/apm-emulation.h>
 #include <linux/omapfb.h>
+#include <linux/platform_data/omap1_bl.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include <plat/flash.h>
-#include <plat/mux.h>
+#include <mach/flash.h>
+#include <mach/mux.h>
 #include <plat/tc.h>
 #include <plat/dma.h>
-#include <plat/board.h>
-#include <plat/irda.h>
-#include <plat/keypad.h>
+#include <mach/irda.h>
+#include <linux/platform_data/keypad-omap.h>
 
 #include <mach/hardware.h>
 #include <mach/usb.h>
diff --git a/arch/arm/mach-omap1/board-palmtt.c b/arch/arm/mach-omap1/board-palmtt.c
index 4d09944..9715809 100644
--- a/arch/arm/mach-omap1/board-palmtt.c
+++ b/arch/arm/mach-omap1/board-palmtt.c
@@ -27,19 +27,19 @@
 #include <linux/omapfb.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/ads7846.h>
+#include <linux/platform_data/omap1_bl.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
 #include <plat/led.h>
-#include <plat/flash.h>
-#include <plat/mux.h>
+#include <mach/flash.h>
+#include <mach/mux.h>
 #include <plat/dma.h>
 #include <plat/tc.h>
-#include <plat/board.h>
-#include <plat/irda.h>
-#include <plat/keypad.h>
+#include <mach/irda.h>
+#include <linux/platform_data/keypad-omap.h>
 
 #include <mach/hardware.h>
 #include <mach/usb.h>
diff --git a/arch/arm/mach-omap1/board-palmz71.c b/arch/arm/mach-omap1/board-palmz71.c
index 3559803..e311032 100644
--- a/arch/arm/mach-omap1/board-palmz71.c
+++ b/arch/arm/mach-omap1/board-palmz71.c
@@ -30,18 +30,18 @@
 #include <linux/omapfb.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/ads7846.h>
+#include <linux/platform_data/omap1_bl.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include <plat/flash.h>
-#include <plat/mux.h>
+#include <mach/flash.h>
+#include <mach/mux.h>
 #include <plat/dma.h>
 #include <plat/tc.h>
-#include <plat/board.h>
-#include <plat/irda.h>
-#include <plat/keypad.h>
+#include <mach/irda.h>
+#include <linux/platform_data/keypad-omap.h>
 
 #include <mach/hardware.h>
 #include <mach/usb.h>
diff --git a/arch/arm/mach-omap1/board-perseus2.c b/arch/arm/mach-omap1/board-perseus2.c
index 703d55e..198b054 100644
--- a/arch/arm/mach-omap1/board-perseus2.c
+++ b/arch/arm/mach-omap1/board-perseus2.c
@@ -22,17 +22,16 @@
 #include <linux/input.h>
 #include <linux/smc91x.h>
 #include <linux/omapfb.h>
+#include <linux/platform_data/keypad-omap.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
 #include <plat/tc.h>
-#include <plat/mux.h>
+#include <mach/mux.h>
 #include <plat/fpga.h>
-#include <plat/flash.h>
-#include <plat/keypad.h>
-#include <plat/board.h>
+#include <mach/flash.h>
 
 #include <mach/hardware.h>
 
diff --git a/arch/arm/mach-omap1/board-sx1-mmc.c b/arch/arm/mach-omap1/board-sx1-mmc.c
index b59f788..5932d56 100644
--- a/arch/arm/mach-omap1/board-sx1-mmc.c
+++ b/arch/arm/mach-omap1/board-sx1-mmc.c
@@ -17,7 +17,7 @@
 
 #include <mach/hardware.h>
 #include <plat/mmc.h>
-#include <plat/board-sx1.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 8c665bd..13bf2cc 100644
--- a/arch/arm/mach-omap1/board-sx1.c
+++ b/arch/arm/mach-omap1/board-sx1.c
@@ -28,19 +28,18 @@
 #include <linux/errno.h>
 #include <linux/export.h>
 #include <linux/omapfb.h>
+#include <linux/platform_data/keypad-omap.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include <plat/flash.h>
-#include <plat/mux.h>
+#include <mach/flash.h>
+#include <mach/mux.h>
 #include <plat/dma.h>
-#include <plat/irda.h>
+#include <mach/irda.h>
 #include <plat/tc.h>
-#include <plat/board.h>
-#include <plat/keypad.h>
-#include <plat/board-sx1.h>
+#include <mach/board-sx1.h>
 
 #include <mach/hardware.h>
 #include <mach/usb.h>
diff --git a/arch/arm/mach-omap1/board-voiceblue.c b/arch/arm/mach-omap1/board-voiceblue.c
index 3497769..ad75e34 100644
--- a/arch/arm/mach-omap1/board-voiceblue.c
+++ b/arch/arm/mach-omap1/board-voiceblue.c
@@ -31,11 +31,10 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include <plat/board-voiceblue.h>
-#include <plat/flash.h>
-#include <plat/mux.h>
+#include <mach/board-voiceblue.h>
+#include <mach/flash.h>
+#include <mach/mux.h>
 #include <plat/tc.h>
-#include <plat/board.h>
 
 #include <mach/hardware.h>
 #include <mach/usb.h>
@@ -155,9 +154,6 @@ static struct omap_usb_config voiceblue_usb_config __initdata = {
 	.pins[2]	= 6,
 };
 
-static struct omap_board_config_kernel voiceblue_config[] = {
-};
-
 #define MACHINE_PANICED		1
 #define MACHINE_REBOOTING	2
 #define MACHINE_REBOOT		4
@@ -275,8 +271,6 @@ static void __init voiceblue_init(void)
 	voiceblue_smc91x_resources[1].start = gpio_to_irq(8);
 	voiceblue_smc91x_resources[1].end = gpio_to_irq(8);
 	platform_add_devices(voiceblue_devices, ARRAY_SIZE(voiceblue_devices));
-	omap_board_config = voiceblue_config;
-	omap_board_config_size = ARRAY_SIZE(voiceblue_config);
 	omap_serial_init();
 	omap1_usb_init(&voiceblue_usb_config);
 	omap_register_i2c_bus(1, 100, NULL, 0);
diff --git a/arch/arm/mach-omap1/clock.c b/arch/arm/mach-omap1/clock.c
index a9ee06b..638f407 100644
--- a/arch/arm/mach-omap1/clock.c
+++ b/arch/arm/mach-omap1/clock.c
@@ -587,8 +587,8 @@ void omap1_clk_disable_unused(struct clk *clk)
 	/* Clocks in the DSP domain need api_ck. Just assume bootloader
 	 * has not enabled any DSP clocks */
 	if (clk->enable_reg == DSP_IDLECT2) {
-		printk(KERN_INFO "Skipping reset check for DSP domain "
-		       "clock \"%s\"\n", clk->name);
+		pr_info("Skipping reset check for DSP domain clock \"%s\"\n",
+			clk->name);
 		return;
 	}
 
diff --git a/arch/arm/mach-omap1/clock_data.c b/arch/arm/mach-omap1/clock_data.c
index c007d80..9b45f4b 100644
--- a/arch/arm/mach-omap1/clock_data.c
+++ b/arch/arm/mach-omap1/clock_data.c
@@ -25,7 +25,6 @@
 #include <plat/clock.h>
 #include <plat/cpu.h>
 #include <plat/clkdev_omap.h>
-#include <plat/board.h>
 #include <plat/sram.h>	/* for omap_sram_reprogram_clock() */
 
 #include <mach/hardware.h>
@@ -776,11 +775,10 @@ static struct clk_functions omap1_clk_functions = {
 
 static void __init omap1_show_rates(void)
 {
-	pr_notice("Clocking rate (xtal/DPLL1/MPU): "
-			"%ld.%01ld/%ld.%01ld/%ld.%01ld MHz\n",
-		ck_ref.rate / 1000000, (ck_ref.rate / 100000) % 10,
-		ck_dpll1.rate / 1000000, (ck_dpll1.rate / 100000) % 10,
-		arm_ck.rate / 1000000, (arm_ck.rate / 100000) % 10);
+	pr_notice("Clocking rate (xtal/DPLL1/MPU): %ld.%01ld/%ld.%01ld/%ld.%01ld MHz\n",
+		  ck_ref.rate / 1000000, (ck_ref.rate / 100000) % 10,
+		  ck_dpll1.rate / 1000000, (ck_dpll1.rate / 100000) % 10,
+		  arm_ck.rate / 1000000, (arm_ck.rate / 100000) % 10);
 }
 
 u32 cpu_mask;
@@ -788,7 +786,6 @@ u32 cpu_mask;
 int __init omap1_clk_init(void)
 {
 	struct omap_clk *c;
-	const struct omap_clock_config *info;
 	int crystal_type = 0; /* Default 12 MHz */
 	u32 reg;
 
@@ -837,19 +834,13 @@ int __init omap1_clk_init(void)
 	ck_dpll1_p = clk_get(NULL, "ck_dpll1");
 	ck_ref_p = clk_get(NULL, "ck_ref");
 
-	info = omap_get_config(OMAP_TAG_CLOCK, struct omap_clock_config);
-	if (info != NULL) {
-		if (!cpu_is_omap15xx())
-			crystal_type = info->system_clock_type;
-	}
-
 	if (cpu_is_omap7xx())
 		ck_ref.rate = 13000000;
 	if (cpu_is_omap16xx() && crystal_type == 2)
 		ck_ref.rate = 19200000;
 
-	pr_info("Clocks: ARM_SYSST: 0x%04x DPLL_CTL: 0x%04x ARM_CKCTL: "
-		"0x%04x\n", omap_readw(ARM_SYSST), omap_readw(DPLL_CTL),
+	pr_info("Clocks: ARM_SYSST: 0x%04x DPLL_CTL: 0x%04x ARM_CKCTL: 0x%04x\n",
+		omap_readw(ARM_SYSST), omap_readw(DPLL_CTL),
 		omap_readw(ARM_CKCTL));
 
 	/* We want to be in syncronous scalable mode */
diff --git a/arch/arm/mach-omap1/devices.c b/arch/arm/mach-omap1/devices.c
index fa1fa4d..0cc54dd 100644
--- a/arch/arm/mach-omap1/devices.c
+++ b/arch/arm/mach-omap1/devices.c
@@ -20,12 +20,11 @@
 #include <asm/mach/map.h>
 
 #include <plat/tc.h>
-#include <plat/board.h>
-#include <plat/mux.h>
+#include <mach/mux.h>
 #include <plat/dma.h>
 #include <plat/mmc.h>
-#include <plat/omap7xx.h>
 
+#include <mach/omap7xx.h>
 #include <mach/camera.h>
 #include <mach/hardware.h>
 
diff --git a/arch/arm/mach-omap1/dma.c b/arch/arm/mach-omap1/dma.c
index 3ef7d52..29007fe 100644
--- a/arch/arm/mach-omap1/dma.c
+++ b/arch/arm/mach-omap1/dma.c
@@ -27,7 +27,8 @@
 
 #include <plat/dma.h>
 #include <plat/tc.h>
-#include <plat/irqs.h>
+
+#include <mach/irqs.h>
 
 #define OMAP1_DMA_BASE			(0xfffed800)
 #define OMAP1_LOGICAL_DMA_CH_COUNT	17
@@ -330,8 +331,9 @@ static int __init omap1_system_dma_init(void)
 	d->chan = kzalloc(sizeof(struct omap_dma_lch) *
 					(d->lch_count), GFP_KERNEL);
 	if (!d->chan) {
-		dev_err(&pdev->dev, "%s: Memory allocation failed"
-					"for d->chan!!!\n", __func__);
+		dev_err(&pdev->dev,
+			"%s: Memory allocation failed for d->chan!\n",
+			__func__);
 		goto exit_release_d;
 	}
 
diff --git a/arch/arm/mach-omap1/flash.c b/arch/arm/mach-omap1/flash.c
index 401eb3c..73ae616 100644
--- a/arch/arm/mach-omap1/flash.c
+++ b/arch/arm/mach-omap1/flash.c
@@ -11,7 +11,7 @@
 #include <linux/mtd/map.h>
 
 #include <plat/tc.h>
-#include <plat/flash.h>
+#include <mach/flash.h>
 
 #include <mach/hardware.h>
 
diff --git a/arch/arm/mach-omap1/gpio15xx.c b/arch/arm/mach-omap1/gpio15xx.c
index ebef15e..98e6f39 100644
--- a/arch/arm/mach-omap1/gpio15xx.c
+++ b/arch/arm/mach-omap1/gpio15xx.c
@@ -17,6 +17,7 @@
  */
 
 #include <linux/gpio.h>
+#include <linux/platform_data/gpio-omap.h>
 
 #define OMAP1_MPUIO_VBASE		OMAP1_MPUIO_BASE
 #define OMAP1510_GPIO_BASE		0xFFFCE000
diff --git a/arch/arm/mach-omap1/gpio16xx.c b/arch/arm/mach-omap1/gpio16xx.c
index 2a48cd2..33f4192 100644
--- a/arch/arm/mach-omap1/gpio16xx.c
+++ b/arch/arm/mach-omap1/gpio16xx.c
@@ -17,6 +17,7 @@
  */
 
 #include <linux/gpio.h>
+#include <linux/platform_data/gpio-omap.h>
 
 #define OMAP1610_GPIO1_BASE		0xfffbe400
 #define OMAP1610_GPIO2_BASE		0xfffbec00
diff --git a/arch/arm/mach-omap1/gpio7xx.c b/arch/arm/mach-omap1/gpio7xx.c
index acf12b7..958ce9a 100644
--- a/arch/arm/mach-omap1/gpio7xx.c
+++ b/arch/arm/mach-omap1/gpio7xx.c
@@ -17,6 +17,7 @@
  */
 
 #include <linux/gpio.h>
+#include <linux/platform_data/gpio-omap.h>
 
 #define OMAP7XX_GPIO1_BASE		0xfffbc000
 #define OMAP7XX_GPIO2_BASE		0xfffbc800
diff --git a/arch/arm/mach-omap1/i2c.c b/arch/arm/mach-omap1/i2c.c
index 5446c99..a0551a6 100644
--- a/arch/arm/mach-omap1/i2c.c
+++ b/arch/arm/mach-omap1/i2c.c
@@ -20,7 +20,7 @@
  */
 
 #include <plat/i2c.h>
-#include <plat/mux.h>
+#include <mach/mux.h>
 #include <plat/cpu.h>
 
 void __init omap1_i2c_mux_pins(int bus_id)
diff --git a/arch/arm/mach-omap1/include/mach/ams-delta-fiq.h b/arch/arm/mach-omap1/include/mach/ams-delta-fiq.h
index 23eed00..adb5e76 100644
--- a/arch/arm/mach-omap1/include/mach/ams-delta-fiq.h
+++ b/arch/arm/mach-omap1/include/mach/ams-delta-fiq.h
@@ -14,8 +14,6 @@
 #ifndef __AMS_DELTA_FIQ_H
 #define __AMS_DELTA_FIQ_H
 
-#include <plat/irqs.h>
-
 /*
  * Interrupt number used for passing control from FIQ to IRQ.
  * IRQ12, described as reserved, has been selected.
diff --git a/arch/arm/mach-omap1/include/mach/board-ams-delta.h b/arch/arm/mach-omap1/include/mach/board-ams-delta.h
new file mode 100644
index 0000000..ad6f865
--- /dev/null
+++ b/arch/arm/mach-omap1/include/mach/board-ams-delta.h
@@ -0,0 +1,71 @@
+/*
+ * arch/arm/plat-omap/include/mach/board-ams-delta.h
+ *
+ * Copyright (C) 2006 Jonathan McDowell <noodles@earth.li>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS 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_AMS_DELTA_H
+#define __ASM_ARCH_OMAP_AMS_DELTA_H
+
+#if defined (CONFIG_MACH_AMS_DELTA)
+
+#define AMD_DELTA_LATCH2_SCARD_RSTIN	0x0400
+#define AMD_DELTA_LATCH2_SCARD_CMDVCC	0x0800
+#define AMS_DELTA_LATCH2_MODEM_CODEC	0x2000
+
+#define AMS_DELTA_GPIO_PIN_KEYBRD_DATA	0
+#define AMS_DELTA_GPIO_PIN_KEYBRD_CLK	1
+#define AMS_DELTA_GPIO_PIN_MODEM_IRQ	2
+#define AMS_DELTA_GPIO_PIN_HOOK_SWITCH	4
+#define AMS_DELTA_GPIO_PIN_SCARD_NOFF	6
+#define AMS_DELTA_GPIO_PIN_SCARD_IO	7
+#define AMS_DELTA_GPIO_PIN_CONFIG	11
+#define AMS_DELTA_GPIO_PIN_NAND_RB	12
+
+#define AMS_DELTA_GPIO_PIN_LCD_VBLEN		240
+#define AMS_DELTA_GPIO_PIN_LCD_NDISP		241
+#define AMS_DELTA_GPIO_PIN_NAND_NCE		242
+#define AMS_DELTA_GPIO_PIN_NAND_NRE		243
+#define AMS_DELTA_GPIO_PIN_NAND_NWP		244
+#define AMS_DELTA_GPIO_PIN_NAND_NWE		245
+#define AMS_DELTA_GPIO_PIN_NAND_ALE		246
+#define AMS_DELTA_GPIO_PIN_NAND_CLE		247
+#define AMS_DELTA_GPIO_PIN_KEYBRD_PWR		248
+#define AMS_DELTA_GPIO_PIN_KEYBRD_DATAOUT	249
+#define AMS_DELTA_GPIO_PIN_SCARD_RSTIN		250
+#define AMS_DELTA_GPIO_PIN_SCARD_CMDVCC		251
+#define AMS_DELTA_GPIO_PIN_MODEM_NRESET		252
+#define AMS_DELTA_GPIO_PIN_MODEM_CODEC		253
+
+#define AMS_DELTA_LATCH2_GPIO_BASE	AMS_DELTA_GPIO_PIN_LCD_VBLEN
+#define AMS_DELTA_LATCH2_NGPIO		16
+
+#ifndef __ASSEMBLY__
+void ams_delta_latch_write(int base, int ngpio, u16 mask, u16 value);
+#define ams_delta_latch2_write(mask, value) \
+	ams_delta_latch_write(AMS_DELTA_LATCH2_GPIO_BASE, \
+			AMS_DELTA_LATCH2_NGPIO, (mask), (value))
+#endif
+
+#endif /* CONFIG_MACH_AMS_DELTA */
+
+#endif /* __ASM_ARCH_OMAP_AMS_DELTA_H */
diff --git a/arch/arm/mach-omap1/include/mach/board-sx1.h b/arch/arm/mach-omap1/include/mach/board-sx1.h
new file mode 100644
index 0000000..355adbd
--- /dev/null
+++ b/arch/arm/mach-omap1/include/mach/board-sx1.h
@@ -0,0 +1,52 @@
+/*
+ * Siemens SX1 board definitions
+ *
+ * Copyright: Vovan888 at gmail com
+ *
+ * This package is free software; you can 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 PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef __ASM_ARCH_SX1_I2C_CHIPS_H
+#define __ASM_ARCH_SX1_I2C_CHIPS_H
+
+#define SOFIA_MAX_LIGHT_VAL	0x2B
+
+#define SOFIA_I2C_ADDR		0x32
+/* Sofia reg 3 bits masks */
+#define SOFIA_POWER1_REG	0x03
+
+#define	SOFIA_USB_POWER		0x01
+#define	SOFIA_MMC_POWER		0x04
+#define	SOFIA_BLUETOOTH_POWER	0x08
+#define	SOFIA_MMILIGHT_POWER	0x20
+
+#define SOFIA_POWER2_REG	0x04
+#define SOFIA_BACKLIGHT_REG	0x06
+#define SOFIA_KEYLIGHT_REG	0x07
+#define SOFIA_DIMMING_REG	0x09
+
+
+/* Function Prototypes for SX1 devices control on I2C bus */
+
+int sx1_setbacklight(u8 backlight);
+int sx1_getbacklight(u8 *backlight);
+int sx1_setkeylight(u8 keylight);
+int sx1_getkeylight(u8 *keylight);
+
+int sx1_setmmipower(u8 onoff);
+int sx1_setusbpower(u8 onoff);
+int sx1_i2c_read_byte(u8 devaddr, u8 regoffset, u8 *value);
+int sx1_i2c_write_byte(u8 devaddr, u8 regoffset, u8 value);
+
+/* MMC prototypes */
+
+extern void sx1_mmc_init(void);
+extern void sx1_mmc_slot_cover_handler(void *arg, int state);
+
+#endif /* __ASM_ARCH_SX1_I2C_CHIPS_H */
diff --git a/arch/arm/mach-omap1/include/mach/board-voiceblue.h b/arch/arm/mach-omap1/include/mach/board-voiceblue.h
new file mode 100644
index 0000000..27916b2
--- /dev/null
+++ b/arch/arm/mach-omap1/include/mach/board-voiceblue.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2004 2N Telekomunikace, Ladislav Michl <michl@2n.cz>
+ *
+ * Hardware definitions for OMAP5910 based VoiceBlue board.
+ *
+ * This program is free software; you can 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_VOICEBLUE_H
+#define __ASM_ARCH_VOICEBLUE_H
+
+extern void voiceblue_wdt_enable(void);
+extern void voiceblue_wdt_disable(void);
+extern void voiceblue_wdt_ping(void);
+
+#endif /*  __ASM_ARCH_VOICEBLUE_H */
+
diff --git a/arch/arm/mach-omap1/include/mach/flash.h b/arch/arm/mach-omap1/include/mach/flash.h
new file mode 100644
index 0000000..0d88499
--- /dev/null
+++ b/arch/arm/mach-omap1/include/mach/flash.h
@@ -0,0 +1,17 @@
+/*
+ * Flash support for OMAP1
+ *
+ * This program is free software; you can 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_FLASH_H
+#define __OMAP_FLASH_H
+
+#include <linux/mtd/map.h>
+
+struct platform_device;
+extern void omap1_set_vpp(struct platform_device *pdev, int enable);
+
+#endif
diff --git a/arch/arm/mach-omap1/include/mach/gpio.h b/arch/arm/mach-omap1/include/mach/gpio.h
index e737706..ebf86c0 100644
--- a/arch/arm/mach-omap1/include/mach/gpio.h
+++ b/arch/arm/mach-omap1/include/mach/gpio.h
@@ -1,5 +1,3 @@
 /*
  * arch/arm/mach-omap1/include/mach/gpio.h
  */
-
-#include <plat/gpio.h>
diff --git a/arch/arm/mach-omap1/include/mach/hardware.h b/arch/arm/mach-omap1/include/mach/hardware.h
index 01e35fa..84248d2 100644
--- a/arch/arm/mach-omap1/include/mach/hardware.h
+++ b/arch/arm/mach-omap1/include/mach/hardware.h
@@ -1,11 +1,46 @@
 /*
  * arch/arm/mach-omap1/include/mach/hardware.h
+ *
+ * Hardware definitions for TI OMAP processors and boards
+ *
+ * NOTE: Please put device driver specific defines into a separate header
+ *	 file for each driver.
+ *
+ * Copyright (C) 2001 RidgeRun, Inc.
+ * Author: RidgeRun, Inc. Greg Lonnon <glonnon@ridgerun.com>
+ *
+ * Reorganized for Linux-2.6 by Tony Lindgren <tony@atomide.com>
+ *                          and 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 __MACH_HARDWARE_H
-#define __MACH_HARDWARE_H
+#ifndef __ASM_ARCH_OMAP_HARDWARE_H
+#define __ASM_ARCH_OMAP_HARDWARE_H
 
+#include <asm/sizes.h>
 #ifndef __ASSEMBLER__
+#include <asm/types.h>
+#include <plat/cpu.h>
+
 /*
  * NOTE: Please use ioremap + __raw_read/write where possible instead of these
  */
@@ -35,7 +70,249 @@ static inline u32 omap_cs3_phys(void)
 			? 0 : OMAP_CS3_PHYS;
 }
 
+#endif	/* ifndef __ASSEMBLER__ */
+
+#include <plat/serial.h>
+
+/*
+ * ---------------------------------------------------------------------------
+ * Common definitions for all OMAP processors
+ * NOTE: Put all processor or board specific parts to the special header
+ *	 files.
+ * ---------------------------------------------------------------------------
+ */
+
+/*
+ * ----------------------------------------------------------------------------
+ * Timers
+ * ----------------------------------------------------------------------------
+ */
+#define OMAP_MPU_TIMER1_BASE	(0xfffec500)
+#define OMAP_MPU_TIMER2_BASE	(0xfffec600)
+#define OMAP_MPU_TIMER3_BASE	(0xfffec700)
+#define MPU_TIMER_FREE		(1 << 6)
+#define MPU_TIMER_CLOCK_ENABLE	(1 << 5)
+#define MPU_TIMER_AR		(1 << 1)
+#define MPU_TIMER_ST		(1 << 0)
+
+/*
+ * ----------------------------------------------------------------------------
+ * Clocks
+ * ----------------------------------------------------------------------------
+ */
+#define CLKGEN_REG_BASE		(0xfffece00)
+#define ARM_CKCTL		(CLKGEN_REG_BASE + 0x0)
+#define ARM_IDLECT1		(CLKGEN_REG_BASE + 0x4)
+#define ARM_IDLECT2		(CLKGEN_REG_BASE + 0x8)
+#define ARM_EWUPCT		(CLKGEN_REG_BASE + 0xC)
+#define ARM_RSTCT1		(CLKGEN_REG_BASE + 0x10)
+#define ARM_RSTCT2		(CLKGEN_REG_BASE + 0x14)
+#define ARM_SYSST		(CLKGEN_REG_BASE + 0x18)
+#define ARM_IDLECT3		(CLKGEN_REG_BASE + 0x24)
+
+#define CK_RATEF		1
+#define CK_IDLEF		2
+#define CK_ENABLEF		4
+#define CK_SELECTF		8
+#define SETARM_IDLE_SHIFT
+
+/* DPLL control registers */
+#define DPLL_CTL		(0xfffecf00)
+
+/* DSP clock control. Must use __raw_readw() and __raw_writew() with these */
+#define DSP_CONFIG_REG_BASE     IOMEM(0xe1008000)
+#define DSP_CKCTL		(DSP_CONFIG_REG_BASE + 0x0)
+#define DSP_IDLECT1		(DSP_CONFIG_REG_BASE + 0x4)
+#define DSP_IDLECT2		(DSP_CONFIG_REG_BASE + 0x8)
+#define DSP_RSTCT2		(DSP_CONFIG_REG_BASE + 0x14)
+
+/*
+ * ---------------------------------------------------------------------------
+ * UPLD
+ * ---------------------------------------------------------------------------
+ */
+#define ULPD_REG_BASE		(0xfffe0800)
+#define ULPD_IT_STATUS		(ULPD_REG_BASE + 0x14)
+#define ULPD_SETUP_ANALOG_CELL_3	(ULPD_REG_BASE + 0x24)
+#define ULPD_CLOCK_CTRL		(ULPD_REG_BASE + 0x30)
+#	define DIS_USB_PVCI_CLK		(1 << 5)	/* no USB/FAC synch */
+#	define USB_MCLK_EN		(1 << 4)	/* enable W4_USB_CLKO */
+#define ULPD_SOFT_REQ		(ULPD_REG_BASE + 0x34)
+#	define SOFT_UDC_REQ		(1 << 4)
+#	define SOFT_USB_CLK_REQ		(1 << 3)
+#	define SOFT_DPLL_REQ		(1 << 0)
+#define ULPD_DPLL_CTRL		(ULPD_REG_BASE + 0x3c)
+#define ULPD_STATUS_REQ		(ULPD_REG_BASE + 0x40)
+#define ULPD_APLL_CTRL		(ULPD_REG_BASE + 0x4c)
+#define ULPD_POWER_CTRL		(ULPD_REG_BASE + 0x50)
+#define ULPD_SOFT_DISABLE_REQ_REG	(ULPD_REG_BASE + 0x68)
+#	define DIS_MMC2_DPLL_REQ	(1 << 11)
+#	define DIS_MMC1_DPLL_REQ	(1 << 10)
+#	define DIS_UART3_DPLL_REQ	(1 << 9)
+#	define DIS_UART2_DPLL_REQ	(1 << 8)
+#	define DIS_UART1_DPLL_REQ	(1 << 7)
+#	define DIS_USB_HOST_DPLL_REQ	(1 << 6)
+#define ULPD_SDW_CLK_DIV_CTRL_SEL	(ULPD_REG_BASE + 0x74)
+#define ULPD_CAM_CLK_CTRL	(ULPD_REG_BASE + 0x7c)
+
+/*
+ * ---------------------------------------------------------------------------
+ * Watchdog timer
+ * ---------------------------------------------------------------------------
+ */
+
+/* Watchdog timer within the OMAP3.2 gigacell */
+#define OMAP_MPU_WATCHDOG_BASE	(0xfffec800)
+#define OMAP_WDT_TIMER		(OMAP_MPU_WATCHDOG_BASE + 0x0)
+#define OMAP_WDT_LOAD_TIM	(OMAP_MPU_WATCHDOG_BASE + 0x4)
+#define OMAP_WDT_READ_TIM	(OMAP_MPU_WATCHDOG_BASE + 0x4)
+#define OMAP_WDT_TIMER_MODE	(OMAP_MPU_WATCHDOG_BASE + 0x8)
+
+/*
+ * ---------------------------------------------------------------------------
+ * Interrupts
+ * ---------------------------------------------------------------------------
+ */
+#ifdef CONFIG_ARCH_OMAP1
+
+/*
+ * XXX: These probably want to be moved to arch/arm/mach-omap/omap1/irq.c
+ * or something similar.. -- PFM.
+ */
+
+#define OMAP_IH1_BASE		0xfffecb00
+#define OMAP_IH2_BASE		0xfffe0000
+
+#define OMAP_IH1_ITR		(OMAP_IH1_BASE + 0x00)
+#define OMAP_IH1_MIR		(OMAP_IH1_BASE + 0x04)
+#define OMAP_IH1_SIR_IRQ	(OMAP_IH1_BASE + 0x10)
+#define OMAP_IH1_SIR_FIQ	(OMAP_IH1_BASE + 0x14)
+#define OMAP_IH1_CONTROL	(OMAP_IH1_BASE + 0x18)
+#define OMAP_IH1_ILR0		(OMAP_IH1_BASE + 0x1c)
+#define OMAP_IH1_ISR		(OMAP_IH1_BASE + 0x9c)
+
+#define OMAP_IH2_ITR		(OMAP_IH2_BASE + 0x00)
+#define OMAP_IH2_MIR		(OMAP_IH2_BASE + 0x04)
+#define OMAP_IH2_SIR_IRQ	(OMAP_IH2_BASE + 0x10)
+#define OMAP_IH2_SIR_FIQ	(OMAP_IH2_BASE + 0x14)
+#define OMAP_IH2_CONTROL	(OMAP_IH2_BASE + 0x18)
+#define OMAP_IH2_ILR0		(OMAP_IH2_BASE + 0x1c)
+#define OMAP_IH2_ISR		(OMAP_IH2_BASE + 0x9c)
+
+#define IRQ_ITR_REG_OFFSET	0x00
+#define IRQ_MIR_REG_OFFSET	0x04
+#define IRQ_SIR_IRQ_REG_OFFSET	0x10
+#define IRQ_SIR_FIQ_REG_OFFSET	0x14
+#define IRQ_CONTROL_REG_OFFSET	0x18
+#define IRQ_ISR_REG_OFFSET	0x9c
+#define IRQ_ILR0_REG_OFFSET	0x1c
+#define IRQ_GMR_REG_OFFSET	0xa0
+
 #endif
-#endif
 
-#include <plat/hardware.h>
+/*
+ * ----------------------------------------------------------------------------
+ * System control registers
+ * ----------------------------------------------------------------------------
+ */
+#define MOD_CONF_CTRL_0		0xfffe1080
+#define MOD_CONF_CTRL_1		0xfffe1110
+
+/*
+ * ----------------------------------------------------------------------------
+ * Pin multiplexing registers
+ * ----------------------------------------------------------------------------
+ */
+#define FUNC_MUX_CTRL_0		0xfffe1000
+#define FUNC_MUX_CTRL_1		0xfffe1004
+#define FUNC_MUX_CTRL_2		0xfffe1008
+#define COMP_MODE_CTRL_0	0xfffe100c
+#define FUNC_MUX_CTRL_3		0xfffe1010
+#define FUNC_MUX_CTRL_4		0xfffe1014
+#define FUNC_MUX_CTRL_5		0xfffe1018
+#define FUNC_MUX_CTRL_6		0xfffe101C
+#define FUNC_MUX_CTRL_7		0xfffe1020
+#define FUNC_MUX_CTRL_8		0xfffe1024
+#define FUNC_MUX_CTRL_9		0xfffe1028
+#define FUNC_MUX_CTRL_A		0xfffe102C
+#define FUNC_MUX_CTRL_B		0xfffe1030
+#define FUNC_MUX_CTRL_C		0xfffe1034
+#define FUNC_MUX_CTRL_D		0xfffe1038
+#define PULL_DWN_CTRL_0		0xfffe1040
+#define PULL_DWN_CTRL_1		0xfffe1044
+#define PULL_DWN_CTRL_2		0xfffe1048
+#define PULL_DWN_CTRL_3		0xfffe104c
+#define PULL_DWN_CTRL_4		0xfffe10ac
+
+/* OMAP-1610 specific multiplexing registers */
+#define FUNC_MUX_CTRL_E		0xfffe1090
+#define FUNC_MUX_CTRL_F		0xfffe1094
+#define FUNC_MUX_CTRL_10	0xfffe1098
+#define FUNC_MUX_CTRL_11	0xfffe109c
+#define FUNC_MUX_CTRL_12	0xfffe10a0
+#define PU_PD_SEL_0		0xfffe10b4
+#define PU_PD_SEL_1		0xfffe10b8
+#define PU_PD_SEL_2		0xfffe10bc
+#define PU_PD_SEL_3		0xfffe10c0
+#define PU_PD_SEL_4		0xfffe10c4
+
+/* Timer32K for 1610 and 1710*/
+#define OMAP_TIMER32K_BASE	0xFFFBC400
+
+/*
+ * ---------------------------------------------------------------------------
+ * TIPB bus interface
+ * ---------------------------------------------------------------------------
+ */
+#define TIPB_PUBLIC_CNTL_BASE		0xfffed300
+#define MPU_PUBLIC_TIPB_CNTL		(TIPB_PUBLIC_CNTL_BASE + 0x8)
+#define TIPB_PRIVATE_CNTL_BASE		0xfffeca00
+#define MPU_PRIVATE_TIPB_CNTL		(TIPB_PRIVATE_CNTL_BASE + 0x8)
+
+/*
+ * ----------------------------------------------------------------------------
+ * MPUI interface
+ * ----------------------------------------------------------------------------
+ */
+#define MPUI_BASE			(0xfffec900)
+#define MPUI_CTRL			(MPUI_BASE + 0x0)
+#define MPUI_DEBUG_ADDR			(MPUI_BASE + 0x4)
+#define MPUI_DEBUG_DATA			(MPUI_BASE + 0x8)
+#define MPUI_DEBUG_FLAG			(MPUI_BASE + 0xc)
+#define MPUI_STATUS_REG			(MPUI_BASE + 0x10)
+#define MPUI_DSP_STATUS			(MPUI_BASE + 0x14)
+#define MPUI_DSP_BOOT_CONFIG		(MPUI_BASE + 0x18)
+#define MPUI_DSP_API_CONFIG		(MPUI_BASE + 0x1c)
+
+/*
+ * ----------------------------------------------------------------------------
+ * LED Pulse Generator
+ * ----------------------------------------------------------------------------
+ */
+#define OMAP_LPG1_BASE			0xfffbd000
+#define OMAP_LPG2_BASE			0xfffbd800
+#define OMAP_LPG1_LCR			(OMAP_LPG1_BASE + 0x00)
+#define OMAP_LPG1_PMR			(OMAP_LPG1_BASE + 0x04)
+#define OMAP_LPG2_LCR			(OMAP_LPG2_BASE + 0x00)
+#define OMAP_LPG2_PMR			(OMAP_LPG2_BASE + 0x04)
+
+/*
+ * ----------------------------------------------------------------------------
+ * Pulse-Width Light
+ * ----------------------------------------------------------------------------
+ */
+#define OMAP_PWL_BASE			0xfffb5800
+#define OMAP_PWL_ENABLE			(OMAP_PWL_BASE + 0x00)
+#define OMAP_PWL_CLK_ENABLE		(OMAP_PWL_BASE + 0x04)
+
+/*
+ * ---------------------------------------------------------------------------
+ * Processor specific defines
+ * ---------------------------------------------------------------------------
+ */
+
+#include "omap7xx.h"
+#include "omap1510.h"
+#include "omap16xx.h"
+
+#endif	/* __ASM_ARCH_OMAP_HARDWARE_H */
diff --git a/arch/arm/mach-omap1/include/mach/irda.h b/arch/arm/mach-omap1/include/mach/irda.h
new file mode 100644
index 0000000..40f6033
--- /dev/null
+++ b/arch/arm/mach-omap1/include/mach/irda.h
@@ -0,0 +1,33 @@
+/*
+ *  arch/arm/plat-omap/include/mach/irda.h
+ *
+ *  Copyright (C) 2005-2006 Komal Shah <komal_shah802003@yahoo.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 ASMARM_ARCH_IRDA_H
+#define ASMARM_ARCH_IRDA_H
+
+/* board specific transceiver capabilities */
+
+#define IR_SEL		1	/* Selects IrDA */
+#define IR_SIRMODE	2
+#define IR_FIRMODE	4
+#define IR_MIRMODE	8
+
+struct omap_irda_config {
+	int transceiver_cap;
+	int (*transceiver_mode)(struct device *dev, int mode);
+	int (*select_irda)(struct device *dev, int state);
+	int rx_channel;
+	int tx_channel;
+	unsigned long dest_start;
+	unsigned long src_start;
+	int tx_trigger;
+	int rx_trigger;
+	int mode;
+};
+
+#endif
diff --git a/arch/arm/mach-omap1/include/mach/irqs.h b/arch/arm/mach-omap1/include/mach/irqs.h
index 9292fdc..729992d 100644
--- a/arch/arm/mach-omap1/include/mach/irqs.h
+++ b/arch/arm/mach-omap1/include/mach/irqs.h
@@ -1,5 +1,268 @@
 /*
- * arch/arm/mach-omap1/include/mach/irqs.h
+ *  arch/arm/plat-omap/include/mach/irqs.h
+ *
+ *  Copyright (C) Greg Lonnon 2001
+ *  Updated for OMAP-1610 by Tony Lindgren <tony@atomide.com>
+ *
+ * Copyright (C) 2009 Texas Instruments
+ * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * NOTE: The interrupt vectors for the OMAP-1509, OMAP-1510, and OMAP-1610
+ *	 are different.
  */
 
-#include <plat/irqs.h>
+#ifndef __ASM_ARCH_OMAP15XX_IRQS_H
+#define __ASM_ARCH_OMAP15XX_IRQS_H
+
+/*
+ * IRQ numbers for interrupt handler 1
+ *
+ * NOTE: See also the OMAP-1510 and 1610 specific IRQ numbers below
+ *
+ */
+#define INT_CAMERA		1
+#define INT_FIQ			3
+#define INT_RTDX		6
+#define INT_DSP_MMU_ABORT	7
+#define INT_HOST		8
+#define INT_ABORT		9
+#define INT_BRIDGE_PRIV		13
+#define INT_GPIO_BANK1		14
+#define INT_UART3		15
+#define INT_TIMER3		16
+#define INT_DMA_CH0_6		19
+#define INT_DMA_CH1_7		20
+#define INT_DMA_CH2_8		21
+#define INT_DMA_CH3		22
+#define INT_DMA_CH4		23
+#define INT_DMA_CH5		24
+#define INT_TIMER1		26
+#define INT_WD_TIMER		27
+#define INT_BRIDGE_PUB		28
+#define INT_TIMER2		30
+#define INT_LCD_CTRL		31
+
+/*
+ * OMAP-1510 specific IRQ numbers for interrupt handler 1
+ */
+#define INT_1510_IH2_IRQ	0
+#define INT_1510_RES2		2
+#define INT_1510_SPI_TX		4
+#define INT_1510_SPI_RX		5
+#define INT_1510_DSP_MAILBOX1	10
+#define INT_1510_DSP_MAILBOX2	11
+#define INT_1510_RES12		12
+#define INT_1510_LB_MMU		17
+#define INT_1510_RES18		18
+#define INT_1510_LOCAL_BUS	29
+
+/*
+ * OMAP-1610 specific IRQ numbers for interrupt handler 1
+ */
+#define INT_1610_IH2_IRQ	INT_1510_IH2_IRQ
+#define INT_1610_IH2_FIQ	2
+#define INT_1610_McBSP2_TX	4
+#define INT_1610_McBSP2_RX	5
+#define INT_1610_DSP_MAILBOX1	10
+#define INT_1610_DSP_MAILBOX2	11
+#define INT_1610_LCD_LINE	12
+#define INT_1610_GPTIMER1	17
+#define INT_1610_GPTIMER2	18
+#define INT_1610_SSR_FIFO_0	29
+
+/*
+ * OMAP-7xx specific IRQ numbers for interrupt handler 1
+ */
+#define INT_7XX_IH2_FIQ		0
+#define INT_7XX_IH2_IRQ		1
+#define INT_7XX_USB_NON_ISO	2
+#define INT_7XX_USB_ISO		3
+#define INT_7XX_ICR		4
+#define INT_7XX_EAC		5
+#define INT_7XX_GPIO_BANK1	6
+#define INT_7XX_GPIO_BANK2	7
+#define INT_7XX_GPIO_BANK3	8
+#define INT_7XX_McBSP2TX	10
+#define INT_7XX_McBSP2RX	11
+#define INT_7XX_McBSP2RX_OVF	12
+#define INT_7XX_LCD_LINE	14
+#define INT_7XX_GSM_PROTECT	15
+#define INT_7XX_TIMER3		16
+#define INT_7XX_GPIO_BANK5	17
+#define INT_7XX_GPIO_BANK6	18
+#define INT_7XX_SPGIO_WR	29
+
+/*
+ * IRQ numbers for interrupt handler 2
+ *
+ * NOTE: See also the OMAP-1510 and 1610 specific IRQ numbers below
+ */
+#define IH2_BASE		32
+
+#define INT_KEYBOARD		(1 + IH2_BASE)
+#define INT_uWireTX		(2 + IH2_BASE)
+#define INT_uWireRX		(3 + IH2_BASE)
+#define INT_I2C			(4 + IH2_BASE)
+#define INT_MPUIO		(5 + IH2_BASE)
+#define INT_USB_HHC_1		(6 + IH2_BASE)
+#define INT_McBSP3TX		(10 + IH2_BASE)
+#define INT_McBSP3RX		(11 + IH2_BASE)
+#define INT_McBSP1TX		(12 + IH2_BASE)
+#define INT_McBSP1RX		(13 + IH2_BASE)
+#define INT_UART1		(14 + IH2_BASE)
+#define INT_UART2		(15 + IH2_BASE)
+#define INT_BT_MCSI1TX		(16 + IH2_BASE)
+#define INT_BT_MCSI1RX		(17 + IH2_BASE)
+#define INT_SOSSI_MATCH		(19 + IH2_BASE)
+#define INT_USB_W2FC		(20 + IH2_BASE)
+#define INT_1WIRE		(21 + IH2_BASE)
+#define INT_OS_TIMER		(22 + IH2_BASE)
+#define INT_MMC			(23 + IH2_BASE)
+#define INT_GAUGE_32K		(24 + IH2_BASE)
+#define INT_RTC_TIMER		(25 + IH2_BASE)
+#define INT_RTC_ALARM		(26 + IH2_BASE)
+#define INT_MEM_STICK		(27 + IH2_BASE)
+
+/*
+ * OMAP-1510 specific IRQ numbers for interrupt handler 2
+ */
+#define INT_1510_DSP_MMU	(28 + IH2_BASE)
+#define INT_1510_COM_SPI_RO	(31 + IH2_BASE)
+
+/*
+ * OMAP-1610 specific IRQ numbers for interrupt handler 2
+ */
+#define INT_1610_FAC		(0 + IH2_BASE)
+#define INT_1610_USB_HHC_2	(7 + IH2_BASE)
+#define INT_1610_USB_OTG	(8 + IH2_BASE)
+#define INT_1610_SoSSI		(9 + IH2_BASE)
+#define INT_1610_SoSSI_MATCH	(19 + IH2_BASE)
+#define INT_1610_DSP_MMU	(28 + IH2_BASE)
+#define INT_1610_McBSP2RX_OF	(31 + IH2_BASE)
+#define INT_1610_STI		(32 + IH2_BASE)
+#define INT_1610_STI_WAKEUP	(33 + IH2_BASE)
+#define INT_1610_GPTIMER3	(34 + IH2_BASE)
+#define INT_1610_GPTIMER4	(35 + IH2_BASE)
+#define INT_1610_GPTIMER5	(36 + IH2_BASE)
+#define INT_1610_GPTIMER6	(37 + IH2_BASE)
+#define INT_1610_GPTIMER7	(38 + IH2_BASE)
+#define INT_1610_GPTIMER8	(39 + IH2_BASE)
+#define INT_1610_GPIO_BANK2	(40 + IH2_BASE)
+#define INT_1610_GPIO_BANK3	(41 + IH2_BASE)
+#define INT_1610_MMC2		(42 + IH2_BASE)
+#define INT_1610_CF		(43 + IH2_BASE)
+#define INT_1610_WAKE_UP_REQ	(46 + IH2_BASE)
+#define INT_1610_GPIO_BANK4	(48 + IH2_BASE)
+#define INT_1610_SPI		(49 + IH2_BASE)
+#define INT_1610_DMA_CH6	(53 + IH2_BASE)
+#define INT_1610_DMA_CH7	(54 + IH2_BASE)
+#define INT_1610_DMA_CH8	(55 + IH2_BASE)
+#define INT_1610_DMA_CH9	(56 + IH2_BASE)
+#define INT_1610_DMA_CH10	(57 + IH2_BASE)
+#define INT_1610_DMA_CH11	(58 + IH2_BASE)
+#define INT_1610_DMA_CH12	(59 + IH2_BASE)
+#define INT_1610_DMA_CH13	(60 + IH2_BASE)
+#define INT_1610_DMA_CH14	(61 + IH2_BASE)
+#define INT_1610_DMA_CH15	(62 + IH2_BASE)
+#define INT_1610_NAND		(63 + IH2_BASE)
+#define INT_1610_SHA1MD5	(91 + IH2_BASE)
+
+/*
+ * OMAP-7xx specific IRQ numbers for interrupt handler 2
+ */
+#define INT_7XX_HW_ERRORS	(0 + IH2_BASE)
+#define INT_7XX_NFIQ_PWR_FAIL	(1 + IH2_BASE)
+#define INT_7XX_CFCD		(2 + IH2_BASE)
+#define INT_7XX_CFIREQ		(3 + IH2_BASE)
+#define INT_7XX_I2C		(4 + IH2_BASE)
+#define INT_7XX_PCC		(5 + IH2_BASE)
+#define INT_7XX_MPU_EXT_NIRQ	(6 + IH2_BASE)
+#define INT_7XX_SPI_100K_1	(7 + IH2_BASE)
+#define INT_7XX_SYREN_SPI	(8 + IH2_BASE)
+#define INT_7XX_VLYNQ		(9 + IH2_BASE)
+#define INT_7XX_GPIO_BANK4	(10 + IH2_BASE)
+#define INT_7XX_McBSP1TX	(11 + IH2_BASE)
+#define INT_7XX_McBSP1RX	(12 + IH2_BASE)
+#define INT_7XX_McBSP1RX_OF	(13 + IH2_BASE)
+#define INT_7XX_UART_MODEM_IRDA_2 (14 + IH2_BASE)
+#define INT_7XX_UART_MODEM_1	(15 + IH2_BASE)
+#define INT_7XX_MCSI		(16 + IH2_BASE)
+#define INT_7XX_uWireTX		(17 + IH2_BASE)
+#define INT_7XX_uWireRX		(18 + IH2_BASE)
+#define INT_7XX_SMC_CD		(19 + IH2_BASE)
+#define INT_7XX_SMC_IREQ	(20 + IH2_BASE)
+#define INT_7XX_HDQ_1WIRE	(21 + IH2_BASE)
+#define INT_7XX_TIMER32K	(22 + IH2_BASE)
+#define INT_7XX_MMC_SDIO	(23 + IH2_BASE)
+#define INT_7XX_UPLD		(24 + IH2_BASE)
+#define INT_7XX_USB_HHC_1	(27 + IH2_BASE)
+#define INT_7XX_USB_HHC_2	(28 + IH2_BASE)
+#define INT_7XX_USB_GENI	(29 + IH2_BASE)
+#define INT_7XX_USB_OTG		(30 + IH2_BASE)
+#define INT_7XX_CAMERA_IF	(31 + IH2_BASE)
+#define INT_7XX_RNG		(32 + IH2_BASE)
+#define INT_7XX_DUAL_MODE_TIMER (33 + IH2_BASE)
+#define INT_7XX_DBB_RF_EN	(34 + IH2_BASE)
+#define INT_7XX_MPUIO_KEYPAD	(35 + IH2_BASE)
+#define INT_7XX_SHA1_MD5	(36 + IH2_BASE)
+#define INT_7XX_SPI_100K_2	(37 + IH2_BASE)
+#define INT_7XX_RNG_IDLE	(38 + IH2_BASE)
+#define INT_7XX_MPUIO		(39 + IH2_BASE)
+#define INT_7XX_LLPC_LCD_CTRL_CAN_BE_OFF	(40 + IH2_BASE)
+#define INT_7XX_LLPC_OE_FALLING (41 + IH2_BASE)
+#define INT_7XX_LLPC_OE_RISING	(42 + IH2_BASE)
+#define INT_7XX_LLPC_VSYNC	(43 + IH2_BASE)
+#define INT_7XX_WAKE_UP_REQ	(46 + IH2_BASE)
+#define INT_7XX_DMA_CH6		(53 + IH2_BASE)
+#define INT_7XX_DMA_CH7		(54 + IH2_BASE)
+#define INT_7XX_DMA_CH8		(55 + IH2_BASE)
+#define INT_7XX_DMA_CH9		(56 + IH2_BASE)
+#define INT_7XX_DMA_CH10	(57 + IH2_BASE)
+#define INT_7XX_DMA_CH11	(58 + IH2_BASE)
+#define INT_7XX_DMA_CH12	(59 + IH2_BASE)
+#define INT_7XX_DMA_CH13	(60 + IH2_BASE)
+#define INT_7XX_DMA_CH14	(61 + IH2_BASE)
+#define INT_7XX_DMA_CH15	(62 + IH2_BASE)
+#define INT_7XX_NAND		(63 + IH2_BASE)
+
+/* 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)
+#define IH_MPUIO_BASE		(OMAP_MAX_GPIO_LINES + IH_GPIO_BASE)
+#define OMAP_IRQ_END		(IH_MPUIO_BASE + 16)
+
+/* External FPGA handles interrupts on Innovator boards */
+#define	OMAP_FPGA_IRQ_BASE	(OMAP_IRQ_END)
+#ifdef	CONFIG_MACH_OMAP_INNOVATOR
+#define OMAP_FPGA_NR_IRQS	24
+#else
+#define OMAP_FPGA_NR_IRQS	0
+#endif
+#define OMAP_FPGA_IRQ_END	(OMAP_FPGA_IRQ_BASE + OMAP_FPGA_NR_IRQS)
+
+#define NR_IRQS			OMAP_FPGA_IRQ_END
+
+#define OMAP_IRQ_BIT(irq)	(1 << ((irq) % 32))
+
+#include <mach/hardware.h>
+
+#ifdef CONFIG_FIQ
+#define FIQ_START		1024
+#endif
+
+#endif
diff --git a/arch/arm/mach-omap1/include/mach/mux.h b/arch/arm/mach-omap1/include/mach/mux.h
new file mode 100644
index 0000000..3239489
--- /dev/null
+++ b/arch/arm/mach-omap1/include/mach/mux.h
@@ -0,0 +1,454 @@
+/*
+ * arch/arm/plat-omap/include/mach/mux.h
+ *
+ * Table of the Omap register configurations for the FUNC_MUX and
+ * PULL_DWN combinations.
+ *
+ * Copyright (C) 2004 - 2008 Texas Instruments Inc.
+ * Copyright (C) 2003 - 2008 Nokia Corporation
+ *
+ * Written by Tony Lindgren
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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
+ *
+ * NOTE: Please use the following naming style for new pin entries.
+ *	 For example, W8_1610_MMC2_DAT0, where:
+ *	 - W8	     = ball
+ *	 - 1610	     = 1510 or 1610, none if common for both 1510 and 1610
+ *	 - MMC2_DAT0 = function
+ */
+
+#ifndef __ASM_ARCH_MUX_H
+#define __ASM_ARCH_MUX_H
+
+#define PU_PD_SEL_NA		0	/* No pu_pd reg available */
+#define PULL_DWN_CTRL_NA	0	/* No pull-down control needed */
+
+#ifdef	CONFIG_OMAP_MUX_DEBUG
+#define MUX_REG(reg, mode_offset, mode) .mux_reg_name = "FUNC_MUX_CTRL_"#reg, \
+					.mux_reg = FUNC_MUX_CTRL_##reg, \
+					.mask_offset = mode_offset, \
+					.mask = mode,
+
+#define PULL_REG(reg, bit, status)	.pull_name = "PULL_DWN_CTRL_"#reg, \
+					.pull_reg = PULL_DWN_CTRL_##reg, \
+					.pull_bit = bit, \
+					.pull_val = status,
+
+#define PU_PD_REG(reg, status)		.pu_pd_name = "PU_PD_SEL_"#reg, \
+					.pu_pd_reg = PU_PD_SEL_##reg, \
+					.pu_pd_val = status,
+
+#define MUX_REG_7XX(reg, mode_offset, mode) .mux_reg_name = "OMAP7XX_IO_CONF_"#reg, \
+					.mux_reg = OMAP7XX_IO_CONF_##reg, \
+					.mask_offset = mode_offset, \
+					.mask = mode,
+
+#define PULL_REG_7XX(reg, bit, status)	.pull_name = "OMAP7XX_IO_CONF_"#reg, \
+					.pull_reg = OMAP7XX_IO_CONF_##reg, \
+					.pull_bit = bit, \
+					.pull_val = status,
+
+#else
+
+#define MUX_REG(reg, mode_offset, mode) .mux_reg = FUNC_MUX_CTRL_##reg, \
+					.mask_offset = mode_offset, \
+					.mask = mode,
+
+#define PULL_REG(reg, bit, status)	.pull_reg = PULL_DWN_CTRL_##reg, \
+					.pull_bit = bit, \
+					.pull_val = status,
+
+#define PU_PD_REG(reg, status)		.pu_pd_reg = PU_PD_SEL_##reg, \
+					.pu_pd_val = status,
+
+#define MUX_REG_7XX(reg, mode_offset, mode) \
+					.mux_reg = OMAP7XX_IO_CONF_##reg, \
+					.mask_offset = mode_offset, \
+					.mask = mode,
+
+#define PULL_REG_7XX(reg, bit, status)	.pull_reg = OMAP7XX_IO_CONF_##reg, \
+					.pull_bit = bit, \
+					.pull_val = status,
+
+#endif /* CONFIG_OMAP_MUX_DEBUG */
+
+#define MUX_CFG(desc, mux_reg, mode_offset, mode,	\
+		pull_reg, pull_bit, pull_status,	\
+		pu_pd_reg, pu_pd_status, debug_status)	\
+{							\
+	.name =	 desc,					\
+	.debug = debug_status,				\
+	MUX_REG(mux_reg, mode_offset, mode)		\
+	PULL_REG(pull_reg, pull_bit, pull_status)	\
+	PU_PD_REG(pu_pd_reg, pu_pd_status)		\
+},
+
+
+/*
+ * OMAP730/850 has a slightly different config for the pin mux.
+ * - config regs are the OMAP7XX_IO_CONF_x regs (see omap7xx.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
+ *   as mux config
+ */
+#define MUX_CFG_7XX(desc, mux_reg, mode_offset, mode,	\
+		   pull_bit, pull_status, debug_status)\
+{							\
+	.name =	 desc,					\
+	.debug = debug_status,				\
+	MUX_REG_7XX(mux_reg, mode_offset, mode)		\
+	PULL_REG_7XX(mux_reg, pull_bit, pull_status)	\
+	PU_PD_REG(NA, 0)		\
+},
+
+struct pin_config {
+	char 			*name;
+	const unsigned int 	mux_reg;
+	unsigned char		debug;
+
+	const unsigned char mask_offset;
+	const unsigned char mask;
+
+	const char *pull_name;
+	const unsigned int pull_reg;
+	const unsigned char pull_val;
+	const unsigned char pull_bit;
+
+	const char *pu_pd_name;
+	const unsigned int pu_pd_reg;
+	const unsigned char pu_pd_val;
+
+#if	defined(CONFIG_OMAP_MUX_DEBUG) || defined(CONFIG_OMAP_MUX_WARNINGS)
+	const char *mux_reg_name;
+#endif
+
+};
+
+enum omap7xx_index {
+	/* OMAP 730 keyboard */
+	E2_7XX_KBR0,
+	J7_7XX_KBR1,
+	E1_7XX_KBR2,
+	F3_7XX_KBR3,
+	D2_7XX_KBR4,
+	C2_7XX_KBC0,
+	D3_7XX_KBC1,
+	E4_7XX_KBC2,
+	F4_7XX_KBC3,
+	E3_7XX_KBC4,
+
+	/* USB */
+	AA17_7XX_USB_DM,
+	W16_7XX_USB_PU_EN,
+	W17_7XX_USB_VBUSI,
+	W18_7XX_USB_DMCK_OUT,
+	W19_7XX_USB_DCRST,
+
+	/* MMC */
+	MMC_7XX_CMD,
+	MMC_7XX_CLK,
+	MMC_7XX_DAT0,
+
+	/* I2C */
+	I2C_7XX_SCL,
+	I2C_7XX_SDA,
+
+	/* SPI */
+	SPI_7XX_1,
+	SPI_7XX_2,
+	SPI_7XX_3,
+	SPI_7XX_4,
+	SPI_7XX_5,
+	SPI_7XX_6,
+
+	/* UART */
+	UART_7XX_1,
+	UART_7XX_2,
+};
+
+enum omap1xxx_index {
+	/* UART1 (BT_UART_GATING)*/
+	UART1_TX = 0,
+	UART1_RTS,
+
+	/* UART2 (COM_UART_GATING)*/
+	UART2_TX,
+	UART2_RX,
+	UART2_CTS,
+	UART2_RTS,
+
+	/* UART3 (GIGA_UART_GATING) */
+	UART3_TX,
+	UART3_RX,
+	UART3_CTS,
+	UART3_RTS,
+	UART3_CLKREQ,
+	UART3_BCLK,	/* 12MHz clock out */
+	Y15_1610_UART3_RTS,
+
+	/* PWT & PWL */
+	PWT,
+	PWL,
+
+	/* USB master generic */
+	R18_USB_VBUS,
+	R18_1510_USB_GPIO0,
+	W4_USB_PUEN,
+	W4_USB_CLKO,
+	W4_USB_HIGHZ,
+	W4_GPIO58,
+
+	/* USB1 master */
+	USB1_SUSP,
+	USB1_SEO,
+	W13_1610_USB1_SE0,
+	USB1_TXEN,
+	USB1_TXD,
+	USB1_VP,
+	USB1_VM,
+	USB1_RCV,
+	USB1_SPEED,
+	R13_1610_USB1_SPEED,
+	R13_1710_USB1_SE0,
+
+	/* USB2 master */
+	USB2_SUSP,
+	USB2_VP,
+	USB2_TXEN,
+	USB2_VM,
+	USB2_RCV,
+	USB2_SEO,
+	USB2_TXD,
+
+	/* OMAP-1510 GPIO */
+	R18_1510_GPIO0,
+	R19_1510_GPIO1,
+	M14_1510_GPIO2,
+
+	/* OMAP1610 GPIO */
+	P18_1610_GPIO3,
+	Y15_1610_GPIO17,
+
+	/* OMAP-1710 GPIO */
+	R18_1710_GPIO0,
+	V2_1710_GPIO10,
+	N21_1710_GPIO14,
+	W15_1710_GPIO40,
+
+	/* MPUIO */
+	MPUIO2,
+	N15_1610_MPUIO2,
+	MPUIO4,
+	MPUIO5,
+	T20_1610_MPUIO5,
+	W11_1610_MPUIO6,
+	V10_1610_MPUIO7,
+	W11_1610_MPUIO9,
+	V10_1610_MPUIO10,
+	W10_1610_MPUIO11,
+	E20_1610_MPUIO13,
+	U20_1610_MPUIO14,
+	E19_1610_MPUIO15,
+
+	/* MCBSP2 */
+	MCBSP2_CLKR,
+	MCBSP2_CLKX,
+	MCBSP2_DR,
+	MCBSP2_DX,
+	MCBSP2_FSR,
+	MCBSP2_FSX,
+
+	/* MCBSP3 */
+	MCBSP3_CLKX,
+
+	/* Misc ballouts */
+	BALLOUT_V8_ARMIO3,
+	N20_HDQ,
+
+	/* OMAP-1610 MMC2 */
+	W8_1610_MMC2_DAT0,
+	V8_1610_MMC2_DAT1,
+	W15_1610_MMC2_DAT2,
+	R10_1610_MMC2_DAT3,
+	Y10_1610_MMC2_CLK,
+	Y8_1610_MMC2_CMD,
+	V9_1610_MMC2_CMDDIR,
+	V5_1610_MMC2_DATDIR0,
+	W19_1610_MMC2_DATDIR1,
+	R18_1610_MMC2_CLKIN,
+
+	/* OMAP-1610 External Trace Interface */
+	M19_1610_ETM_PSTAT0,
+	L15_1610_ETM_PSTAT1,
+	L18_1610_ETM_PSTAT2,
+	L19_1610_ETM_D0,
+	J19_1610_ETM_D6,
+	J18_1610_ETM_D7,
+
+	/* OMAP16XX GPIO */
+	P20_1610_GPIO4,
+	V9_1610_GPIO7,
+	W8_1610_GPIO9,
+	N20_1610_GPIO11,
+	N19_1610_GPIO13,
+	P10_1610_GPIO22,
+	V5_1610_GPIO24,
+	AA20_1610_GPIO_41,
+	W19_1610_GPIO48,
+	M7_1610_GPIO62,
+	V14_16XX_GPIO37,
+	R9_16XX_GPIO18,
+	L14_16XX_GPIO49,
+
+	/* OMAP-1610 uWire */
+	V19_1610_UWIRE_SCLK,
+	U18_1610_UWIRE_SDI,
+	W21_1610_UWIRE_SDO,
+	N14_1610_UWIRE_CS0,
+	P15_1610_UWIRE_CS3,
+	N15_1610_UWIRE_CS1,
+
+	/* OMAP-1610 SPI */
+	U19_1610_SPIF_SCK,
+	U18_1610_SPIF_DIN,
+	P20_1610_SPIF_DIN,
+	W21_1610_SPIF_DOUT,
+	R18_1610_SPIF_DOUT,
+	N14_1610_SPIF_CS0,
+	N15_1610_SPIF_CS1,
+	T19_1610_SPIF_CS2,
+	P15_1610_SPIF_CS3,
+
+	/* OMAP-1610 Flash */
+	L3_1610_FLASH_CS2B_OE,
+	M8_1610_FLASH_CS2B_WE,
+
+	/* First MMC */
+	MMC_CMD,
+	MMC_DAT1,
+	MMC_DAT2,
+	MMC_DAT0,
+	MMC_CLK,
+	MMC_DAT3,
+
+	/* OMAP-1710 MMC CMDDIR and DATDIR0 */
+	M15_1710_MMC_CLKI,
+	P19_1710_MMC_CMDDIR,
+	P20_1710_MMC_DATDIR0,
+
+	/* OMAP-1610 USB0 alternate pin configuration */
+	W9_USB0_TXEN,
+	AA9_USB0_VP,
+	Y5_USB0_RCV,
+	R9_USB0_VM,
+	V6_USB0_TXD,
+	W5_USB0_SE0,
+	V9_USB0_SPEED,
+	V9_USB0_SUSP,
+
+	/* USB2 */
+	W9_USB2_TXEN,
+	AA9_USB2_VP,
+	Y5_USB2_RCV,
+	R9_USB2_VM,
+	V6_USB2_TXD,
+	W5_USB2_SE0,
+
+	/* 16XX UART */
+	R13_1610_UART1_TX,
+	V14_16XX_UART1_RX,
+	R14_1610_UART1_CTS,
+	AA15_1610_UART1_RTS,
+	R9_16XX_UART2_RX,
+	L14_16XX_UART3_RX,
+
+	/* I2C OMAP-1610 */
+	I2C_SCL,
+	I2C_SDA,
+
+	/* Keypad */
+	F18_1610_KBC0,
+	D20_1610_KBC1,
+	D19_1610_KBC2,
+	E18_1610_KBC3,
+	C21_1610_KBC4,
+	G18_1610_KBR0,
+	F19_1610_KBR1,
+	H14_1610_KBR2,
+	E20_1610_KBR3,
+	E19_1610_KBR4,
+	N19_1610_KBR5,
+
+	/* Power management */
+	T20_1610_LOW_PWR,
+
+	/* MCLK Settings */
+	V5_1710_MCLK_ON,
+	V5_1710_MCLK_OFF,
+	R10_1610_MCLK_ON,
+	R10_1610_MCLK_OFF,
+
+	/* CompactFlash controller */
+	P11_1610_CF_CD2,
+	R11_1610_CF_IOIS16,
+	V10_1610_CF_IREQ,
+	W10_1610_CF_RESET,
+	W11_1610_CF_CD1,
+
+	/* parallel camera */
+	J15_1610_CAM_LCLK,
+	J18_1610_CAM_D7,
+	J19_1610_CAM_D6,
+	J14_1610_CAM_D5,
+	K18_1610_CAM_D4,
+	K19_1610_CAM_D3,
+	K15_1610_CAM_D2,
+	K14_1610_CAM_D1,
+	L19_1610_CAM_D0,
+	L18_1610_CAM_VS,
+	L15_1610_CAM_HS,
+	M19_1610_CAM_RSTZ,
+	Y15_1610_CAM_OUTCLK,
+
+	/* serial camera */
+	H19_1610_CAM_EXCLK,
+	Y12_1610_CCP_CLKP,
+	W13_1610_CCP_CLKM,
+	W14_1610_CCP_DATAP,
+	Y14_1610_CCP_DATAM,
+
+};
+
+struct omap_mux_cfg {
+	struct pin_config	*pins;
+	unsigned long		size;
+	int			(*cfg_reg)(const struct pin_config *cfg);
+};
+
+#ifdef	CONFIG_OMAP_MUX
+/* setup pin muxing in Linux */
+extern int omap1_mux_init(void);
+extern int omap_mux_register(struct omap_mux_cfg *);
+extern int omap_cfg_reg(unsigned long reg_cfg);
+#else
+/* boot loader does it all (no warnings from CONFIG_OMAP_MUX_WARNINGS) */
+static inline int omap1_mux_init(void) { return 0; }
+static inline int omap_cfg_reg(unsigned long reg_cfg) { return 0; }
+#endif
+
+extern int omap2_mux_init(void);
+
+#endif
diff --git a/arch/arm/mach-omap1/include/mach/omap1510.h b/arch/arm/mach-omap1/include/mach/omap1510.h
new file mode 100644
index 0000000..8fe05d6
--- /dev/null
+++ b/arch/arm/mach-omap1/include/mach/omap1510.h
@@ -0,0 +1,49 @@
+/*
+ * Hardware definitions for TI OMAP1510 processor.
+ *
+ * Cleanup for Linux-2.6 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_OMAP15XX_H
+#define __ASM_ARCH_OMAP15XX_H
+
+/*
+ * ----------------------------------------------------------------------------
+ * Base addresses
+ * ----------------------------------------------------------------------------
+ */
+
+/* Syntax: XX_BASE = Virtual base address, XX_START = Physical base address */
+
+#define OMAP1510_DSP_BASE	0xE0000000
+#define OMAP1510_DSP_SIZE	0x28000
+#define OMAP1510_DSP_START	0xE0000000
+
+#define OMAP1510_DSPREG_BASE	0xE1000000
+#define OMAP1510_DSPREG_SIZE	SZ_128K
+#define OMAP1510_DSPREG_START	0xE1000000
+
+#define OMAP1510_DSP_MMU_BASE	(0xfffed200)
+
+#endif /*  __ASM_ARCH_OMAP15XX_H */
+
diff --git a/arch/arm/mach-omap1/include/mach/omap16xx.h b/arch/arm/mach-omap1/include/mach/omap16xx.h
new file mode 100644
index 0000000..cd1c724
--- /dev/null
+++ b/arch/arm/mach-omap1/include/mach/omap16xx.h
@@ -0,0 +1,201 @@
+/*
+ * Hardware definitions for TI OMAP1610/5912/1710 processors.
+ *
+ * Cleanup for Linux-2.6 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_OMAP16XX_H
+#define __ASM_ARCH_OMAP16XX_H
+
+/*
+ * ----------------------------------------------------------------------------
+ * Base addresses
+ * ----------------------------------------------------------------------------
+ */
+
+/* Syntax: XX_BASE = Virtual base address, XX_START = Physical base address */
+
+#define OMAP16XX_DSP_BASE	0xE0000000
+#define OMAP16XX_DSP_SIZE	0x28000
+#define OMAP16XX_DSP_START	0xE0000000
+
+#define OMAP16XX_DSPREG_BASE	0xE1000000
+#define OMAP16XX_DSPREG_SIZE	SZ_128K
+#define OMAP16XX_DSPREG_START	0xE1000000
+
+#define OMAP16XX_SEC_BASE	0xFFFE4000
+#define OMAP16XX_SEC_DES	(OMAP16XX_SEC_BASE + 0x0000)
+#define OMAP16XX_SEC_SHA1MD5	(OMAP16XX_SEC_BASE + 0x0800)
+#define OMAP16XX_SEC_RNG	(OMAP16XX_SEC_BASE + 0x1000)
+
+/*
+ * ---------------------------------------------------------------------------
+ * Interrupts
+ * ---------------------------------------------------------------------------
+ */
+#define OMAP_IH2_0_BASE		(0xfffe0000)
+#define OMAP_IH2_1_BASE		(0xfffe0100)
+#define OMAP_IH2_2_BASE		(0xfffe0200)
+#define OMAP_IH2_3_BASE		(0xfffe0300)
+
+#define OMAP_IH2_0_ITR		(OMAP_IH2_0_BASE + 0x00)
+#define OMAP_IH2_0_MIR		(OMAP_IH2_0_BASE + 0x04)
+#define OMAP_IH2_0_SIR_IRQ	(OMAP_IH2_0_BASE + 0x10)
+#define OMAP_IH2_0_SIR_FIQ	(OMAP_IH2_0_BASE + 0x14)
+#define OMAP_IH2_0_CONTROL	(OMAP_IH2_0_BASE + 0x18)
+#define OMAP_IH2_0_ILR0		(OMAP_IH2_0_BASE + 0x1c)
+#define OMAP_IH2_0_ISR		(OMAP_IH2_0_BASE + 0x9c)
+
+#define OMAP_IH2_1_ITR		(OMAP_IH2_1_BASE + 0x00)
+#define OMAP_IH2_1_MIR		(OMAP_IH2_1_BASE + 0x04)
+#define OMAP_IH2_1_SIR_IRQ	(OMAP_IH2_1_BASE + 0x10)
+#define OMAP_IH2_1_SIR_FIQ	(OMAP_IH2_1_BASE + 0x14)
+#define OMAP_IH2_1_CONTROL	(OMAP_IH2_1_BASE + 0x18)
+#define OMAP_IH2_1_ILR1		(OMAP_IH2_1_BASE + 0x1c)
+#define OMAP_IH2_1_ISR		(OMAP_IH2_1_BASE + 0x9c)
+
+#define OMAP_IH2_2_ITR		(OMAP_IH2_2_BASE + 0x00)
+#define OMAP_IH2_2_MIR		(OMAP_IH2_2_BASE + 0x04)
+#define OMAP_IH2_2_SIR_IRQ	(OMAP_IH2_2_BASE + 0x10)
+#define OMAP_IH2_2_SIR_FIQ	(OMAP_IH2_2_BASE + 0x14)
+#define OMAP_IH2_2_CONTROL	(OMAP_IH2_2_BASE + 0x18)
+#define OMAP_IH2_2_ILR2		(OMAP_IH2_2_BASE + 0x1c)
+#define OMAP_IH2_2_ISR		(OMAP_IH2_2_BASE + 0x9c)
+
+#define OMAP_IH2_3_ITR		(OMAP_IH2_3_BASE + 0x00)
+#define OMAP_IH2_3_MIR		(OMAP_IH2_3_BASE + 0x04)
+#define OMAP_IH2_3_SIR_IRQ	(OMAP_IH2_3_BASE + 0x10)
+#define OMAP_IH2_3_SIR_FIQ	(OMAP_IH2_3_BASE + 0x14)
+#define OMAP_IH2_3_CONTROL	(OMAP_IH2_3_BASE + 0x18)
+#define OMAP_IH2_3_ILR3		(OMAP_IH2_3_BASE + 0x1c)
+#define OMAP_IH2_3_ISR		(OMAP_IH2_3_BASE + 0x9c)
+
+/*
+ * ----------------------------------------------------------------------------
+ * Clocks
+ * ----------------------------------------------------------------------------
+ */
+#define OMAP16XX_ARM_IDLECT3	(CLKGEN_REG_BASE + 0x24)
+
+/*
+ * ----------------------------------------------------------------------------
+ * Pin configuration registers
+ * ----------------------------------------------------------------------------
+ */
+#define OMAP16XX_CONF_VOLTAGE_VDDSHV6	(1 << 8)
+#define OMAP16XX_CONF_VOLTAGE_VDDSHV7	(1 << 9)
+#define OMAP16XX_CONF_VOLTAGE_VDDSHV8	(1 << 10)
+#define OMAP16XX_CONF_VOLTAGE_VDDSHV9	(1 << 11)
+#define OMAP16XX_SUBLVDS_CONF_VALID	(1 << 13)
+
+/*
+ * ----------------------------------------------------------------------------
+ * System control registers
+ * ----------------------------------------------------------------------------
+ */
+#define OMAP1610_RESET_CONTROL  0xfffe1140
+
+/*
+ * ---------------------------------------------------------------------------
+ * TIPB bus interface
+ * ---------------------------------------------------------------------------
+ */
+#define TIPB_SWITCH_BASE		 (0xfffbc800)
+#define OMAP16XX_MMCSD2_SSW_MPU_CONF	(TIPB_SWITCH_BASE + 0x160)
+
+/* UART3 Registers Mapping through MPU bus */
+#define UART3_RHR               (OMAP1_UART3_BASE + 0)
+#define UART3_THR               (OMAP1_UART3_BASE + 0)
+#define UART3_DLL               (OMAP1_UART3_BASE + 0)
+#define UART3_IER               (OMAP1_UART3_BASE + 4)
+#define UART3_DLH               (OMAP1_UART3_BASE + 4)
+#define UART3_IIR               (OMAP1_UART3_BASE + 8)
+#define UART3_FCR               (OMAP1_UART3_BASE + 8)
+#define UART3_EFR               (OMAP1_UART3_BASE + 8)
+#define UART3_LCR               (OMAP1_UART3_BASE + 0x0C)
+#define UART3_MCR               (OMAP1_UART3_BASE + 0x10)
+#define UART3_XON1_ADDR1        (OMAP1_UART3_BASE + 0x10)
+#define UART3_XON2_ADDR2        (OMAP1_UART3_BASE + 0x14)
+#define UART3_LSR               (OMAP1_UART3_BASE + 0x14)
+#define UART3_TCR               (OMAP1_UART3_BASE + 0x18)
+#define UART3_MSR               (OMAP1_UART3_BASE + 0x18)
+#define UART3_XOFF1             (OMAP1_UART3_BASE + 0x18)
+#define UART3_XOFF2             (OMAP1_UART3_BASE + 0x1C)
+#define UART3_SPR               (OMAP1_UART3_BASE + 0x1C)
+#define UART3_TLR               (OMAP1_UART3_BASE + 0x1C)
+#define UART3_MDR1              (OMAP1_UART3_BASE + 0x20)
+#define UART3_MDR2              (OMAP1_UART3_BASE + 0x24)
+#define UART3_SFLSR             (OMAP1_UART3_BASE + 0x28)
+#define UART3_TXFLL             (OMAP1_UART3_BASE + 0x28)
+#define UART3_RESUME            (OMAP1_UART3_BASE + 0x2C)
+#define UART3_TXFLH             (OMAP1_UART3_BASE + 0x2C)
+#define UART3_SFREGL            (OMAP1_UART3_BASE + 0x30)
+#define UART3_RXFLL             (OMAP1_UART3_BASE + 0x30)
+#define UART3_SFREGH            (OMAP1_UART3_BASE + 0x34)
+#define UART3_RXFLH             (OMAP1_UART3_BASE + 0x34)
+#define UART3_BLR               (OMAP1_UART3_BASE + 0x38)
+#define UART3_ACREG             (OMAP1_UART3_BASE + 0x3C)
+#define UART3_DIV16             (OMAP1_UART3_BASE + 0x3C)
+#define UART3_SCR               (OMAP1_UART3_BASE + 0x40)
+#define UART3_SSR               (OMAP1_UART3_BASE + 0x44)
+#define UART3_EBLR              (OMAP1_UART3_BASE + 0x48)
+#define UART3_OSC_12M_SEL       (OMAP1_UART3_BASE + 0x4C)
+#define UART3_MVR               (OMAP1_UART3_BASE + 0x50)
+
+/*
+ * ---------------------------------------------------------------------------
+ * Watchdog timer
+ * ---------------------------------------------------------------------------
+ */
+
+/* 32-bit Watchdog timer in OMAP 16XX */
+#define OMAP_16XX_WATCHDOG_BASE        (0xfffeb000)
+#define OMAP_16XX_WIDR         (OMAP_16XX_WATCHDOG_BASE + 0x00)
+#define OMAP_16XX_WD_SYSCONFIG (OMAP_16XX_WATCHDOG_BASE + 0x10)
+#define OMAP_16XX_WD_SYSSTATUS (OMAP_16XX_WATCHDOG_BASE + 0x14)
+#define OMAP_16XX_WCLR         (OMAP_16XX_WATCHDOG_BASE + 0x24)
+#define OMAP_16XX_WCRR         (OMAP_16XX_WATCHDOG_BASE + 0x28)
+#define OMAP_16XX_WLDR         (OMAP_16XX_WATCHDOG_BASE + 0x2c)
+#define OMAP_16XX_WTGR         (OMAP_16XX_WATCHDOG_BASE + 0x30)
+#define OMAP_16XX_WWPS         (OMAP_16XX_WATCHDOG_BASE + 0x34)
+#define OMAP_16XX_WSPR         (OMAP_16XX_WATCHDOG_BASE + 0x48)
+
+#define WCLR_PRE_SHIFT         5
+#define WCLR_PTV_SHIFT         2
+
+#define WWPS_W_PEND_WSPR       (1 << 4)
+#define WWPS_W_PEND_WTGR       (1 << 3)
+#define WWPS_W_PEND_WLDR       (1 << 2)
+#define WWPS_W_PEND_WCRR       (1 << 1)
+#define WWPS_W_PEND_WCLR       (1 << 0)
+
+#define WSPR_ENABLE_0          (0x0000bbbb)
+#define WSPR_ENABLE_1          (0x00004444)
+#define WSPR_DISABLE_0         (0x0000aaaa)
+#define WSPR_DISABLE_1         (0x00005555)
+
+#define OMAP16XX_DSP_MMU_BASE	(0xfffed200)
+#define OMAP16XX_MAILBOX_BASE	(0xfffcf000)
+
+#endif /*  __ASM_ARCH_OMAP16XX_H */
+
diff --git a/arch/arm/mach-omap1/include/mach/omap7xx.h b/arch/arm/mach-omap1/include/mach/omap7xx.h
new file mode 100644
index 0000000..63da994
--- /dev/null
+++ b/arch/arm/mach-omap1/include/mach/omap7xx.h
@@ -0,0 +1,106 @@
+/*
+ * Hardware definitions for TI OMAP7XX processor.
+ *
+ * Cleanup for Linux-2.6 by Dirk Behme <dirk.behme@de.bosch.com>
+ * Adapted for omap850 by Zebediah C. McClure <zmc@lurian.net>
+ * Adapted for omap7xx by Alistair Buxton <a.j.buxton@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 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_OMAP7XX_H
+#define __ASM_ARCH_OMAP7XX_H
+
+/*
+ * ----------------------------------------------------------------------------
+ * Base addresses
+ * ----------------------------------------------------------------------------
+ */
+
+/* Syntax: XX_BASE = Virtual base address, XX_START = Physical base address */
+
+#define OMAP7XX_DSP_BASE	0xE0000000
+#define OMAP7XX_DSP_SIZE	0x50000
+#define OMAP7XX_DSP_START	0xE0000000
+
+#define OMAP7XX_DSPREG_BASE	0xE1000000
+#define OMAP7XX_DSPREG_SIZE	SZ_128K
+#define OMAP7XX_DSPREG_START	0xE1000000
+
+#define OMAP7XX_SPI1_BASE	0xfffc0800
+#define OMAP7XX_SPI2_BASE	0xfffc1000
+
+/*
+ * ----------------------------------------------------------------------------
+ * OMAP7XX specific configuration registers
+ * ----------------------------------------------------------------------------
+ */
+#define OMAP7XX_CONFIG_BASE	0xfffe1000
+#define OMAP7XX_IO_CONF_0	0xfffe1070
+#define OMAP7XX_IO_CONF_1	0xfffe1074
+#define OMAP7XX_IO_CONF_2	0xfffe1078
+#define OMAP7XX_IO_CONF_3	0xfffe107c
+#define OMAP7XX_IO_CONF_4	0xfffe1080
+#define OMAP7XX_IO_CONF_5	0xfffe1084
+#define OMAP7XX_IO_CONF_6	0xfffe1088
+#define OMAP7XX_IO_CONF_7	0xfffe108c
+#define OMAP7XX_IO_CONF_8	0xfffe1090
+#define OMAP7XX_IO_CONF_9	0xfffe1094
+#define OMAP7XX_IO_CONF_10	0xfffe1098
+#define OMAP7XX_IO_CONF_11	0xfffe109c
+#define OMAP7XX_IO_CONF_12	0xfffe10a0
+#define OMAP7XX_IO_CONF_13	0xfffe10a4
+
+#define OMAP7XX_MODE_1		0xfffe1010
+#define OMAP7XX_MODE_2		0xfffe1014
+
+/* CSMI specials: in terms of base + offset */
+#define OMAP7XX_MODE2_OFFSET	0x14
+
+/*
+ * ----------------------------------------------------------------------------
+ * OMAP7XX traffic controller configuration registers
+ * ----------------------------------------------------------------------------
+ */
+#define OMAP7XX_FLASH_CFG_0	0xfffecc10
+#define OMAP7XX_FLASH_ACFG_0	0xfffecc50
+#define OMAP7XX_FLASH_CFG_1	0xfffecc14
+#define OMAP7XX_FLASH_ACFG_1	0xfffecc54
+
+/*
+ * ----------------------------------------------------------------------------
+ * OMAP7XX DSP control registers
+ * ----------------------------------------------------------------------------
+ */
+#define OMAP7XX_ICR_BASE	0xfffbb800
+#define OMAP7XX_DSP_M_CTL	0xfffbb804
+#define OMAP7XX_DSP_MMU_BASE	0xfffed200
+
+/*
+ * ----------------------------------------------------------------------------
+ * OMAP7XX PCC_UPLD configuration registers
+ * ----------------------------------------------------------------------------
+ */
+#define OMAP7XX_PCC_UPLD_CTRL_BASE	(0xfffe0900)
+#define OMAP7XX_PCC_UPLD_CTRL		(OMAP7XX_PCC_UPLD_CTRL_BASE + 0x00)
+
+#endif /*  __ASM_ARCH_OMAP7XX_H */
+
diff --git a/arch/arm/mach-omap1/include/mach/smp.h b/arch/arm/mach-omap1/include/mach/smp.h
deleted file mode 100644
index 80a371c..0000000
--- a/arch/arm/mach-omap1/include/mach/smp.h
+++ /dev/null
@@ -1,5 +0,0 @@
-/*
- * arch/arm/mach-omap1/include/mach/smp.h
- */
-
-#include <plat/smp.h>
diff --git a/arch/arm/mach-omap1/io.c b/arch/arm/mach-omap1/io.c
index 6c95a59..6a5baab 100644
--- a/arch/arm/mach-omap1/io.c
+++ b/arch/arm/mach-omap1/io.c
@@ -16,7 +16,7 @@
 #include <asm/tlb.h>
 #include <asm/mach/map.h>
 
-#include <plat/mux.h>
+#include <mach/mux.h>
 #include <plat/tc.h>
 #include <plat/dma.h>
 
diff --git a/arch/arm/mach-omap1/lcd_dma.c b/arch/arm/mach-omap1/lcd_dma.c
index 5769c71..ed42628 100644
--- a/arch/arm/mach-omap1/lcd_dma.c
+++ b/arch/arm/mach-omap1/lcd_dma.c
@@ -113,8 +113,7 @@ EXPORT_SYMBOL(omap_set_lcd_dma_b1_mirror);
 void omap_set_lcd_dma_b1_vxres(unsigned long vxres)
 {
 	if (cpu_is_omap15xx()) {
-		printk(KERN_ERR "DMA virtual resolution is not supported "
-				"in 1510 mode\n");
+		pr_err("DMA virtual resolution is not supported in 1510 mode\n");
 		BUG();
 	}
 	lcd_dma.vxres = vxres;
@@ -437,8 +436,7 @@ static int __init omap_init_lcd_dma(void)
 	r = request_irq(INT_DMA_LCD, lcd_dma_irq_handler, 0,
 			"LCD DMA", NULL);
 	if (r != 0)
-		printk(KERN_ERR "unable to request IRQ for LCD DMA "
-			       "(error %d)\n", r);
+		pr_err("unable to request IRQ for LCD DMA (error %d)\n", r);
 
 	return r;
 }
diff --git a/arch/arm/mach-omap1/leds-h2p2-debug.c b/arch/arm/mach-omap1/leds-h2p2-debug.c
deleted file mode 100644
index f6b14a1..0000000
--- a/arch/arm/mach-omap1/leds-h2p2-debug.c
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * linux/arch/arm/mach-omap1/leds-h2p2-debug.c
- *
- * Copyright 2003 by Texas Instruments Incorporated
- *
- * There are 16 LEDs on the debug board (all green); four may be used
- * for logical 'green', 'amber', 'red', and 'blue' (after "claiming").
- *
- * The "surfer" expansion board and H2 sample board also have two-color
- * green+red LEDs (in parallel), used here for timer and idle indicators.
- */
-#include <linux/gpio.h>
-#include <linux/init.h>
-#include <linux/kernel_stat.h>
-#include <linux/sched.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <asm/leds.h>
-#include <asm/mach-types.h>
-
-#include <plat/fpga.h>
-
-#include "leds.h"
-
-
-#define GPIO_LED_RED		3
-#define GPIO_LED_GREEN		OMAP_MPUIO(4)
-
-
-#define LED_STATE_ENABLED	0x01
-#define LED_STATE_CLAIMED	0x02
-#define LED_TIMER_ON		0x04
-
-#define GPIO_IDLE		GPIO_LED_GREEN
-#define GPIO_TIMER		GPIO_LED_RED
-
-
-void h2p2_dbg_leds_event(led_event_t evt)
-{
-	unsigned long flags;
-
-	static struct h2p2_dbg_fpga __iomem *fpga;
-	static u16 led_state, hw_led_state;
-
-	local_irq_save(flags);
-
-	if (!(led_state & LED_STATE_ENABLED) && evt != led_start)
-		goto done;
-
-	switch (evt) {
-	case led_start:
-		if (!fpga)
-			fpga = ioremap(H2P2_DBG_FPGA_START,
-						H2P2_DBG_FPGA_SIZE);
-		if (fpga) {
-			led_state |= LED_STATE_ENABLED;
-			__raw_writew(~0, &fpga->leds);
-		}
-		break;
-
-	case led_stop:
-	case led_halted:
-		/* all leds off during suspend or shutdown */
-
-		if (! machine_is_omap_perseus2()) {
-			gpio_set_value(GPIO_TIMER, 0);
-			gpio_set_value(GPIO_IDLE, 0);
-		}
-
-		__raw_writew(~0, &fpga->leds);
-		led_state &= ~LED_STATE_ENABLED;
-		if (evt == led_halted) {
-			iounmap(fpga);
-			fpga = NULL;
-		}
-
-		goto done;
-
-	case led_claim:
-		led_state |= LED_STATE_CLAIMED;
-		hw_led_state = 0;
-		break;
-
-	case led_release:
-		led_state &= ~LED_STATE_CLAIMED;
-		break;
-
-#ifdef CONFIG_LEDS_TIMER
-	case led_timer:
-		led_state ^= LED_TIMER_ON;
-
-		if (machine_is_omap_perseus2())
-			hw_led_state ^= H2P2_DBG_FPGA_P2_LED_TIMER;
-		else {
-			gpio_set_value(GPIO_TIMER, led_state & LED_TIMER_ON);
-			goto done;
-		}
-
-		break;
-#endif
-
-#ifdef CONFIG_LEDS_CPU
-	case led_idle_start:
-		if (machine_is_omap_perseus2())
-			hw_led_state |= H2P2_DBG_FPGA_P2_LED_IDLE;
-		else {
-			gpio_set_value(GPIO_IDLE, 1);
-			goto done;
-		}
-
-		break;
-
-	case led_idle_end:
-		if (machine_is_omap_perseus2())
-			hw_led_state &= ~H2P2_DBG_FPGA_P2_LED_IDLE;
-		else {
-			gpio_set_value(GPIO_IDLE, 0);
-			goto done;
-		}
-
-		break;
-#endif
-
-	case led_green_on:
-		hw_led_state |= H2P2_DBG_FPGA_LED_GREEN;
-		break;
-	case led_green_off:
-		hw_led_state &= ~H2P2_DBG_FPGA_LED_GREEN;
-		break;
-
-	case led_amber_on:
-		hw_led_state |= H2P2_DBG_FPGA_LED_AMBER;
-		break;
-	case led_amber_off:
-		hw_led_state &= ~H2P2_DBG_FPGA_LED_AMBER;
-		break;
-
-	case led_red_on:
-		hw_led_state |= H2P2_DBG_FPGA_LED_RED;
-		break;
-	case led_red_off:
-		hw_led_state &= ~H2P2_DBG_FPGA_LED_RED;
-		break;
-
-	case led_blue_on:
-		hw_led_state |= H2P2_DBG_FPGA_LED_BLUE;
-		break;
-	case led_blue_off:
-		hw_led_state &= ~H2P2_DBG_FPGA_LED_BLUE;
-		break;
-
-	default:
-		break;
-	}
-
-
-	/*
-	 *  Actually burn the LEDs
-	 */
-	if (led_state & LED_STATE_ENABLED)
-		__raw_writew(~hw_led_state, &fpga->leds);
-
-done:
-	local_irq_restore(flags);
-}
diff --git a/arch/arm/mach-omap1/leds-innovator.c b/arch/arm/mach-omap1/leds-innovator.c
deleted file mode 100644
index 3a066ee..0000000
--- a/arch/arm/mach-omap1/leds-innovator.c
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * linux/arch/arm/mach-omap1/leds-innovator.c
- */
-#include <linux/init.h>
-
-#include <mach/hardware.h>
-#include <asm/leds.h>
-
-#include "leds.h"
-
-
-#define LED_STATE_ENABLED	1
-#define LED_STATE_CLAIMED	2
-
-static unsigned int led_state;
-static unsigned int hw_led_state;
-
-void innovator_leds_event(led_event_t evt)
-{
-	unsigned long flags;
-
-	local_irq_save(flags);
-
-	switch (evt) {
-	case led_start:
-		hw_led_state = 0;
-		led_state = LED_STATE_ENABLED;
-		break;
-
-	case led_stop:
-		led_state &= ~LED_STATE_ENABLED;
-		hw_led_state = 0;
-		break;
-
-	case led_claim:
-		led_state |= LED_STATE_CLAIMED;
-		hw_led_state = 0;
-		break;
-
-	case led_release:
-		led_state &= ~LED_STATE_CLAIMED;
-		hw_led_state = 0;
-		break;
-
-#ifdef CONFIG_LEDS_TIMER
-	case led_timer:
-		if (!(led_state & LED_STATE_CLAIMED))
-			hw_led_state ^= 0;
-		break;
-#endif
-
-#ifdef CONFIG_LEDS_CPU
-	case led_idle_start:
-		if (!(led_state & LED_STATE_CLAIMED))
-			hw_led_state |= 0;
-		break;
-
-	case led_idle_end:
-		if (!(led_state & LED_STATE_CLAIMED))
-			hw_led_state &= ~0;
-		break;
-#endif
-
-	case led_halted:
-		break;
-
-	case led_green_on:
-		if (led_state & LED_STATE_CLAIMED)
-			hw_led_state &= ~0;
-		break;
-
-	case led_green_off:
-		if (led_state & LED_STATE_CLAIMED)
-			hw_led_state |= 0;
-		break;
-
-	case led_amber_on:
-		break;
-
-	case led_amber_off:
-		break;
-
-	case led_red_on:
-		if (led_state & LED_STATE_CLAIMED)
-			hw_led_state &= ~0;
-		break;
-
-	case led_red_off:
-		if (led_state & LED_STATE_CLAIMED)
-			hw_led_state |= 0;
-		break;
-
-	default:
-		break;
-	}
-
-	local_irq_restore(flags);
-}
diff --git a/arch/arm/mach-omap1/leds-osk.c b/arch/arm/mach-omap1/leds-osk.c
deleted file mode 100644
index 936ed42..0000000
--- a/arch/arm/mach-omap1/leds-osk.c
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * linux/arch/arm/mach-omap1/leds-osk.c
- *
- * LED driver for OSK with optional Mistral QVGA board
- */
-#include <linux/gpio.h>
-#include <linux/init.h>
-
-#include <mach/hardware.h>
-#include <asm/leds.h>
-
-#include "leds.h"
-
-
-#define LED_STATE_ENABLED	(1 << 0)
-#define LED_STATE_CLAIMED	(1 << 1)
-static u8 led_state;
-
-#define	TIMER_LED		(1 << 3)	/* Mistral board */
-#define	IDLE_LED		(1 << 4)	/* Mistral board */
-static u8 hw_led_state;
-
-
-#ifdef	CONFIG_OMAP_OSK_MISTRAL
-
-/* For now, all system indicators require the Mistral board, since that
- * LED can be manipulated without a task context.  This LED is either red,
- * or green, but not both; it can't give the full "disco led" effect.
- */
-
-#define GPIO_LED_RED		3
-#define GPIO_LED_GREEN		OMAP_MPUIO(4)
-
-static void mistral_setled(void)
-{
-	int	red = 0;
-	int	green = 0;
-
-	if (hw_led_state & TIMER_LED)
-		red = 1;
-	else if (hw_led_state & IDLE_LED)
-		green = 1;
-	/* else both sides are disabled */
-
-	gpio_set_value(GPIO_LED_GREEN, green);
-	gpio_set_value(GPIO_LED_RED, red);
-}
-
-#endif
-
-void osk_leds_event(led_event_t evt)
-{
-	unsigned long	flags;
-	u16		leds;
-
-	local_irq_save(flags);
-
-	if (!(led_state & LED_STATE_ENABLED) && evt != led_start)
-		goto done;
-
-	leds = hw_led_state;
-	switch (evt) {
-	case led_start:
-		led_state |= LED_STATE_ENABLED;
-		hw_led_state = 0;
-		leds = ~0;
-		break;
-
-	case led_halted:
-	case led_stop:
-		led_state &= ~LED_STATE_ENABLED;
-		hw_led_state = 0;
-		break;
-
-	case led_claim:
-		led_state |= LED_STATE_CLAIMED;
-		hw_led_state = 0;
-		leds = ~0;
-		break;
-
-	case led_release:
-		led_state &= ~LED_STATE_CLAIMED;
-		hw_led_state = 0;
-		break;
-
-#ifdef	CONFIG_OMAP_OSK_MISTRAL
-
-	case led_timer:
-		hw_led_state ^= TIMER_LED;
-		mistral_setled();
-		break;
-
-	case led_idle_start:	/* idle == off */
-		hw_led_state &= ~IDLE_LED;
-		mistral_setled();
-		break;
-
-	case led_idle_end:
-		hw_led_state |= IDLE_LED;
-		mistral_setled();
-		break;
-
-#endif	/* CONFIG_OMAP_OSK_MISTRAL */
-
-	default:
-		break;
-	}
-
-	leds ^= hw_led_state;
-
-done:
-	local_irq_restore(flags);
-}
diff --git a/arch/arm/mach-omap1/leds.c b/arch/arm/mach-omap1/leds.c
deleted file mode 100644
index ae6dd93..0000000
--- a/arch/arm/mach-omap1/leds.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * linux/arch/arm/mach-omap1/leds.c
- *
- * OMAP LEDs dispatcher
- */
-#include <linux/gpio.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-
-#include <asm/leds.h>
-#include <asm/mach-types.h>
-
-#include <plat/mux.h>
-
-#include "leds.h"
-
-static int __init
-omap_leds_init(void)
-{
-	if (!cpu_class_is_omap1())
-		return -ENODEV;
-
-	if (machine_is_omap_innovator())
-		leds_event = innovator_leds_event;
-
-	else if (machine_is_omap_h2()
-			|| machine_is_omap_h3()
-			|| machine_is_omap_perseus2())
-		leds_event = h2p2_dbg_leds_event;
-
-	else if (machine_is_omap_osk())
-		leds_event = osk_leds_event;
-
-	else
-		return -1;
-
-	if (machine_is_omap_h2()
-			|| machine_is_omap_h3()
-#ifdef	CONFIG_OMAP_OSK_MISTRAL
-			|| machine_is_omap_osk()
-#endif
-			) {
-
-		/* LED1/LED2 pins can be used as GPIO (as done here), or by
-		 * the LPG (works even in deep sleep!), to drive a bicolor
-		 * LED on the H2 sample board, and another on the H2/P2
-		 * "surfer" expansion board.
-		 *
-		 * The same pins drive a LED on the OSK Mistral board, but
-		 * that's a different kind of LED (just one color at a time).
-		 */
-		omap_cfg_reg(P18_1610_GPIO3);
-		if (gpio_request(3, "LED red") == 0)
-			gpio_direction_output(3, 1);
-		else
-			printk(KERN_WARNING "LED: can't get GPIO3/red?\n");
-
-		omap_cfg_reg(MPUIO4);
-		if (gpio_request(OMAP_MPUIO(4), "LED green") == 0)
-			gpio_direction_output(OMAP_MPUIO(4), 1);
-		else
-			printk(KERN_WARNING "LED: can't get MPUIO4/green?\n");
-	}
-
-	leds_event(led_start);
-	return 0;
-}
-
-__initcall(omap_leds_init);
diff --git a/arch/arm/mach-omap1/leds.h b/arch/arm/mach-omap1/leds.h
deleted file mode 100644
index a1e9fed..0000000
--- a/arch/arm/mach-omap1/leds.h
+++ /dev/null
@@ -1,3 +0,0 @@
-extern void innovator_leds_event(led_event_t evt);
-extern void h2p2_dbg_leds_event(led_event_t evt);
-extern void osk_leds_event(led_event_t evt);
diff --git a/arch/arm/mach-omap1/mcbsp.c b/arch/arm/mach-omap1/mcbsp.c
index adf0097..bdc2e75 100644
--- a/arch/arm/mach-omap1/mcbsp.c
+++ b/arch/arm/mach-omap1/mcbsp.c
@@ -20,9 +20,9 @@
 #include <linux/slab.h>
 
 #include <plat/dma.h>
-#include <plat/mux.h>
+#include <mach/mux.h>
 #include <plat/cpu.h>
-#include <plat/mcbsp.h>
+#include <linux/platform_data/asoc-ti-mcbsp.h>
 
 #include <mach/irqs.h>
 
diff --git a/arch/arm/mach-omap1/mux.c b/arch/arm/mach-omap1/mux.c
index e9cc52d..667ce50 100644
--- a/arch/arm/mach-omap1/mux.c
+++ b/arch/arm/mach-omap1/mux.c
@@ -29,7 +29,7 @@
 
 #include <mach/hardware.h>
 
-#include <plat/mux.h>
+#include <mach/mux.h>
 
 #ifdef CONFIG_OMAP_MUX
 
@@ -451,6 +451,56 @@ static int __init_or_module omap1_cfg_reg(const struct pin_config *cfg)
 #endif
 }
 
+static struct omap_mux_cfg *mux_cfg;
+
+int __init omap_mux_register(struct omap_mux_cfg *arch_mux_cfg)
+{
+	if (!arch_mux_cfg || !arch_mux_cfg->pins || arch_mux_cfg->size == 0
+			|| !arch_mux_cfg->cfg_reg) {
+		printk(KERN_ERR "Invalid pin table\n");
+		return -EINVAL;
+	}
+
+	mux_cfg = arch_mux_cfg;
+
+	return 0;
+}
+
+/*
+ * Sets the Omap MUX and PULL_DWN registers based on the table
+ */
+int __init_or_module omap_cfg_reg(const unsigned long index)
+{
+	struct pin_config *reg;
+
+	if (!cpu_class_is_omap1()) {
+		printk(KERN_ERR "mux: Broken omap_cfg_reg(%lu) entry\n",
+				index);
+		WARN_ON(1);
+		return -EINVAL;
+	}
+
+	if (mux_cfg == NULL) {
+		printk(KERN_ERR "Pin mux table not initialized\n");
+		return -ENODEV;
+	}
+
+	if (index >= mux_cfg->size) {
+		printk(KERN_ERR "Invalid pin mux index: %lu (%lu)\n",
+		       index, mux_cfg->size);
+		dump_stack();
+		return -ENODEV;
+	}
+
+	reg = &mux_cfg->pins[index];
+
+	if (!mux_cfg->cfg_reg)
+		return -ENODEV;
+
+	return mux_cfg->cfg_reg(reg);
+}
+EXPORT_SYMBOL(omap_cfg_reg);
+
 int __init omap1_mux_init(void)
 {
 	if (cpu_is_omap7xx()) {
@@ -468,4 +518,8 @@ int __init omap1_mux_init(void)
 	return omap_mux_register(&arch_mux_cfg);
 }
 
-#endif
+#else
+#define omap_mux_init() do {} while(0)
+#define omap_cfg_reg(x)	do {} while(0)
+#endif	/* CONFIG_OMAP_MUX */
+
diff --git a/arch/arm/mach-omap1/pm.c b/arch/arm/mach-omap1/pm.c
index b2560d3..47ec161 100644
--- a/arch/arm/mach-omap1/pm.c
+++ b/arch/arm/mach-omap1/pm.c
@@ -53,7 +53,7 @@
 #include <plat/clock.h>
 #include <plat/sram.h>
 #include <plat/tc.h>
-#include <plat/mux.h>
+#include <mach/mux.h>
 #include <plat/dma.h>
 #include <plat/dmtimer.h>
 
diff --git a/arch/arm/mach-omap1/serial.c b/arch/arm/mach-omap1/serial.c
index 6809c9e..b9d6834 100644
--- a/arch/arm/mach-omap1/serial.c
+++ b/arch/arm/mach-omap1/serial.c
@@ -22,8 +22,7 @@
 
 #include <asm/mach-types.h>
 
-#include <plat/board.h>
-#include <plat/mux.h>
+#include <mach/mux.h>
 #include <plat/fpga.h>
 
 #include "pm.h"
diff --git a/arch/arm/mach-omap1/time.c b/arch/arm/mach-omap1/time.c
index 4062480..4d4816f 100644
--- a/arch/arm/mach-omap1/time.c
+++ b/arch/arm/mach-omap1/time.c
@@ -44,7 +44,6 @@
 #include <linux/clockchips.h>
 #include <linux/io.h>
 
-#include <asm/leds.h>
 #include <asm/irq.h>
 #include <asm/sched_clock.h>
 
diff --git a/arch/arm/mach-omap1/timer32k.c b/arch/arm/mach-omap1/timer32k.c
index eae49c3..7452954 100644
--- a/arch/arm/mach-omap1/timer32k.c
+++ b/arch/arm/mach-omap1/timer32k.c
@@ -46,7 +46,6 @@
 #include <linux/clockchips.h>
 #include <linux/io.h>
 
-#include <asm/leds.h>
 #include <asm/irq.h>
 #include <asm/mach/irq.h>
 #include <asm/mach/time.h>
diff --git a/arch/arm/mach-omap1/usb.c b/arch/arm/mach-omap1/usb.c
index 65f8817..84267ed 100644
--- a/arch/arm/mach-omap1/usb.c
+++ b/arch/arm/mach-omap1/usb.c
@@ -26,7 +26,7 @@
 
 #include <asm/irq.h>
 
-#include <plat/mux.h>
+#include <mach/mux.h>
 
 #include <mach/usb.h>
 
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index 346fd26..d8dcfe6 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -18,6 +18,7 @@ config ARCH_OMAP2PLUS_TYPICAL
 	select TWL4030_CORE if ARCH_OMAP3 || ARCH_OMAP4
 	select TWL4030_POWER if ARCH_OMAP3 || ARCH_OMAP4
 	select HIGHMEM
+	select PINCTRL
 	help
 	  Compile a kernel suitable for booting most boards
 
@@ -44,6 +45,7 @@ config ARCH_OMAP3
 	select ARM_CPU_SUSPEND if PM
 	select MULTI_IRQ_HANDLER
 	select SOC_HAS_OMAP2_SDRC
+	select OMAP_INTERCONNECT
 
 config ARCH_OMAP4
 	bool "TI OMAP4"
@@ -63,6 +65,7 @@ config ARCH_OMAP4
 	select USB_ARCH_HAS_EHCI if USB_SUPPORT
 	select ARM_CPU_SUSPEND if PM
 	select ARCH_NEEDS_CPU_IDLE_COUPLED if SMP
+	select OMAP_INTERCONNECT
 
 config SOC_OMAP5
 	bool "TI OMAP5"
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index 34c2c7f..7d6abda 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -4,36 +4,30 @@
 
 # Common support
 obj-y := id.o io.o control.o mux.o devices.o serial.o gpmc.o timer.o pm.o \
-	 common.o gpio.o dma.o wd_timer.o display.o i2c.o hdq1w.o
+	 common.o gpio.o dma.o wd_timer.o display.o i2c.o hdq1w.o omap_hwmod.o
 
-omap-2-3-common				= irq.o
-hwmod-common				= omap_hwmod.o \
-					  omap_hwmod_common_data.o
-clock-common				= clock.o clock_common_data.o \
-					  clkt_dpll.o clkt_clksel.o
-secure-common				= omap-smc.o omap-secure.o
+# INTCPS IP block support - XXX should be moved to drivers/
+obj-$(CONFIG_ARCH_OMAP2)		+= irq.o
+obj-$(CONFIG_ARCH_OMAP3)		+= irq.o
+obj-$(CONFIG_SOC_AM33XX)		+= irq.o
 
-obj-$(CONFIG_ARCH_OMAP2) += $(omap-2-3-common) $(hwmod-common)
-obj-$(CONFIG_ARCH_OMAP3) += $(omap-2-3-common) $(hwmod-common) $(secure-common)
-obj-$(CONFIG_ARCH_OMAP4) += prm44xx.o $(hwmod-common) $(secure-common)
-obj-$(CONFIG_SOC_AM33XX) += irq.o $(hwmod-common)
-obj-$(CONFIG_SOC_OMAP5)	 += prm44xx.o $(hwmod-common) $(secure-common)
+# Secure monitor API support
+obj-$(CONFIG_ARCH_OMAP3)		+= omap-smc.o omap-secure.o
+obj-$(CONFIG_ARCH_OMAP4)		+= omap-smc.o omap-secure.o
+obj-$(CONFIG_SOC_OMAP5)			+= omap-smc.o omap-secure.o
 
 ifneq ($(CONFIG_SND_OMAP_SOC_MCBSP),)
 obj-y += mcbsp.o
 endif
 
-obj-$(CONFIG_TWL4030_CORE) += omap_twl.o
-obj-$(CONFIG_SOC_HAS_OMAP2_SDRC)	+= sdrc.o
+obj-$(CONFIG_TWL4030_CORE)		+= omap_twl.o
 
 # SMP support ONLY available for OMAP4
 
 obj-$(CONFIG_SMP)			+= omap-smp.o omap-headsmp.o
 obj-$(CONFIG_HOTPLUG_CPU)		+= omap-hotplug.o
-omap-4-5-common				=  omap4-common.o omap-wakeupgen.o \
-					   sleep44xx.o
-obj-$(CONFIG_ARCH_OMAP4)		+= $(omap-4-5-common)
-obj-$(CONFIG_SOC_OMAP5)			+= $(omap-4-5-common)
+obj-$(CONFIG_ARCH_OMAP4)		+= omap4-common.o omap-wakeupgen.o
+obj-$(CONFIG_SOC_OMAP5)			+= omap4-common.o omap-wakeupgen.o
 
 plus_sec := $(call as-instr,.arch_extension sec,+sec)
 AFLAGS_omap-headsmp.o			:=-Wa,-march=armv7-a$(plus_sec)
@@ -58,6 +52,7 @@ obj-$(CONFIG_ARCH_OMAP4)		+= mux44xx.o
 # SMS/SDRC
 obj-$(CONFIG_ARCH_OMAP2)		+= sdrc2xxx.o
 # obj-$(CONFIG_ARCH_OMAP3)		+= sdrc3xxx.o
+obj-$(CONFIG_SOC_HAS_OMAP2_SDRC)	+= sdrc.o
 
 # OPP table initialization
 ifeq ($(CONFIG_PM_OPP),y)
@@ -68,15 +63,15 @@ endif
 
 # Power Management
 ifeq ($(CONFIG_PM),y)
-obj-$(CONFIG_ARCH_OMAP2)		+= pm24xx.o
-obj-$(CONFIG_ARCH_OMAP2)		+= sleep24xx.o
+obj-$(CONFIG_ARCH_OMAP2)		+= pm24xx.o sleep24xx.o
 obj-$(CONFIG_ARCH_OMAP3)		+= pm34xx.o sleep34xx.o
 obj-$(CONFIG_ARCH_OMAP4)		+= pm44xx.o omap-mpuss-lowpower.o
-obj-$(CONFIG_SOC_OMAP5)			+= omap-mpuss-lowpower.o
+obj-$(CONFIG_ARCH_OMAP4)		+= sleep44xx.o
+obj-$(CONFIG_SOC_OMAP5)			+= omap-mpuss-lowpower.o sleep44xx.o
 obj-$(CONFIG_PM_DEBUG)			+= pm-debug.o
 
 obj-$(CONFIG_POWER_AVS_OMAP)		+= sr_device.o
-obj-$(CONFIG_POWER_AVS_OMAP_CLASS3)    += smartreflex-class3.o
+obj-$(CONFIG_POWER_AVS_OMAP_CLASS3)	+= smartreflex-class3.o
 
 AFLAGS_sleep24xx.o			:=-Wa,-march=armv6
 AFLAGS_sleep34xx.o			:=-Wa,-march=armv7-a$(plus_sec)
@@ -88,92 +83,76 @@ endif
 endif
 
 ifeq ($(CONFIG_CPU_IDLE),y)
-obj-$(CONFIG_ARCH_OMAP3)                += cpuidle34xx.o
-obj-$(CONFIG_ARCH_OMAP4)                += cpuidle44xx.o
+obj-$(CONFIG_ARCH_OMAP3)		+= cpuidle34xx.o
+obj-$(CONFIG_ARCH_OMAP4)		+= cpuidle44xx.o
 endif
 
 # PRCM
-omap-prcm-4-5-common			=  prcm.o cminst44xx.o cm44xx.o \
-					   prcm_mpu44xx.o prminst44xx.o \
-					   vc44xx_data.o vp44xx_data.o
-obj-y					+= prm_common.o
-obj-$(CONFIG_ARCH_OMAP2)		+= prcm.o cm2xxx_3xxx.o prm2xxx_3xxx.o
-obj-$(CONFIG_ARCH_OMAP3)		+= prcm.o cm2xxx_3xxx.o prm2xxx_3xxx.o
+obj-y					+= prcm.o prm_common.o
+obj-$(CONFIG_ARCH_OMAP2)		+= cm2xxx_3xxx.o prm2xxx_3xxx.o
+obj-$(CONFIG_ARCH_OMAP3)		+= cm2xxx_3xxx.o prm2xxx_3xxx.o
 obj-$(CONFIG_ARCH_OMAP3)		+= vc3xxx_data.o vp3xxx_data.o
-obj-$(CONFIG_SOC_AM33XX)		+= prcm.o prm33xx.o cm33xx.o
-obj-$(CONFIG_ARCH_OMAP4)		+= $(omap-prcm-4-5-common) prm44xx.o
+obj-$(CONFIG_SOC_AM33XX)		+= prm33xx.o cm33xx.o
+omap-prcm-4-5-common			=  cminst44xx.o cm44xx.o prm44xx.o \
+					   prcm_mpu44xx.o prminst44xx.o \
+					   vc44xx_data.o vp44xx_data.o \
+					   prm44xx.o
+obj-$(CONFIG_ARCH_OMAP4)		+= $(omap-prcm-4-5-common)
 obj-$(CONFIG_SOC_OMAP5)			+= $(omap-prcm-4-5-common)
 
 # OMAP voltage domains
-voltagedomain-common			:= voltage.o vc.o vp.o
-obj-$(CONFIG_ARCH_OMAP2)		+= $(voltagedomain-common)
+obj-y					+= voltage.o vc.o vp.o
 obj-$(CONFIG_ARCH_OMAP2)		+= voltagedomains2xxx_data.o
-obj-$(CONFIG_ARCH_OMAP3)		+= $(voltagedomain-common)
 obj-$(CONFIG_ARCH_OMAP3)		+= voltagedomains3xxx_data.o
-obj-$(CONFIG_ARCH_OMAP4)		+= $(voltagedomain-common)
 obj-$(CONFIG_ARCH_OMAP4)		+= voltagedomains44xx_data.o
-obj-$(CONFIG_SOC_AM33XX)		+= $(voltagedomain-common)
-obj-$(CONFIG_SOC_AM33XX)                += voltagedomains33xx_data.o
-obj-$(CONFIG_SOC_OMAP5)			+= $(voltagedomain-common)
+obj-$(CONFIG_SOC_AM33XX)		+= voltagedomains33xx_data.o
 
 # OMAP powerdomain framework
-powerdomain-common			+= powerdomain.o powerdomain-common.o
-obj-$(CONFIG_ARCH_OMAP2)		+= $(powerdomain-common)
+obj-y					+= powerdomain.o powerdomain-common.o
 obj-$(CONFIG_ARCH_OMAP2)		+= powerdomains2xxx_data.o
 obj-$(CONFIG_ARCH_OMAP2)		+= powerdomain2xxx_3xxx.o
 obj-$(CONFIG_ARCH_OMAP2)		+= powerdomains2xxx_3xxx_data.o
-obj-$(CONFIG_ARCH_OMAP3)		+= $(powerdomain-common)
 obj-$(CONFIG_ARCH_OMAP3)		+= powerdomain2xxx_3xxx.o
 obj-$(CONFIG_ARCH_OMAP3)		+= powerdomains3xxx_data.o
 obj-$(CONFIG_ARCH_OMAP3)		+= powerdomains2xxx_3xxx_data.o
-obj-$(CONFIG_ARCH_OMAP4)		+= $(powerdomain-common)
 obj-$(CONFIG_ARCH_OMAP4)		+= powerdomain44xx.o
 obj-$(CONFIG_ARCH_OMAP4)		+= powerdomains44xx_data.o
-obj-$(CONFIG_SOC_AM33XX)		+= $(powerdomain-common)
 obj-$(CONFIG_SOC_AM33XX)		+= powerdomain33xx.o
 obj-$(CONFIG_SOC_AM33XX)		+= powerdomains33xx_data.o
-obj-$(CONFIG_SOC_OMAP5)			+= $(powerdomain-common)
 obj-$(CONFIG_SOC_OMAP5)			+= powerdomain44xx.o
 
 # PRCM clockdomain control
-clockdomain-common			+= clockdomain.o
-obj-$(CONFIG_ARCH_OMAP2)		+= $(clockdomain-common)
+obj-y					+= clockdomain.o
 obj-$(CONFIG_ARCH_OMAP2)		+= clockdomain2xxx_3xxx.o
 obj-$(CONFIG_ARCH_OMAP2)		+= clockdomains2xxx_3xxx_data.o
 obj-$(CONFIG_SOC_OMAP2420)		+= clockdomains2420_data.o
 obj-$(CONFIG_SOC_OMAP2430)		+= clockdomains2430_data.o
-obj-$(CONFIG_ARCH_OMAP3)		+= $(clockdomain-common)
 obj-$(CONFIG_ARCH_OMAP3)		+= clockdomain2xxx_3xxx.o
 obj-$(CONFIG_ARCH_OMAP3)		+= clockdomains2xxx_3xxx_data.o
 obj-$(CONFIG_ARCH_OMAP3)		+= clockdomains3xxx_data.o
-obj-$(CONFIG_ARCH_OMAP4)		+= $(clockdomain-common)
 obj-$(CONFIG_ARCH_OMAP4)		+= clockdomain44xx.o
 obj-$(CONFIG_ARCH_OMAP4)		+= clockdomains44xx_data.o
-obj-$(CONFIG_SOC_AM33XX)		+= $(clockdomain-common)
 obj-$(CONFIG_SOC_AM33XX)		+= clockdomain33xx.o
 obj-$(CONFIG_SOC_AM33XX)		+= clockdomains33xx_data.o
-obj-$(CONFIG_SOC_OMAP5)			+= $(clockdomain-common)
 obj-$(CONFIG_SOC_OMAP5)			+= clockdomain44xx.o
 
 # Clock framework
-obj-$(CONFIG_ARCH_OMAP2)		+= $(clock-common) clock2xxx.o
-obj-$(CONFIG_ARCH_OMAP2)		+= clkt2xxx_sys.o
-obj-$(CONFIG_ARCH_OMAP2)		+= clkt2xxx_dpllcore.o
+obj-y					+= clock.o clock_common_data.o \
+					   clkt_dpll.o clkt_clksel.o
+obj-$(CONFIG_ARCH_OMAP2)		+= clock2xxx.o
+obj-$(CONFIG_ARCH_OMAP2)		+= clkt2xxx_dpllcore.o clkt2xxx_sys.o
 obj-$(CONFIG_ARCH_OMAP2)		+= clkt2xxx_virt_prcm_set.o
 obj-$(CONFIG_ARCH_OMAP2)		+= clkt2xxx_apll.o clkt2xxx_osc.o
 obj-$(CONFIG_ARCH_OMAP2)		+= clkt2xxx_dpll.o clkt_iclk.o
 obj-$(CONFIG_SOC_OMAP2420)		+= clock2420_data.o
 obj-$(CONFIG_SOC_OMAP2430)		+= clock2430.o clock2430_data.o
-obj-$(CONFIG_ARCH_OMAP3)		+= $(clock-common) clock3xxx.o
+obj-$(CONFIG_ARCH_OMAP3)		+= clock3xxx.o
 obj-$(CONFIG_ARCH_OMAP3)		+= clock34xx.o clkt34xx_dpll3m2.o
-obj-$(CONFIG_ARCH_OMAP3)		+= clock3517.o clock36xx.o
+obj-$(CONFIG_ARCH_OMAP3)		+= clock3517.o clock36xx.o clkt_iclk.o
 obj-$(CONFIG_ARCH_OMAP3)		+= dpll3xxx.o clock3xxx_data.o
-obj-$(CONFIG_ARCH_OMAP3)		+= clkt_iclk.o
-obj-$(CONFIG_ARCH_OMAP4)		+= $(clock-common) clock44xx_data.o
+obj-$(CONFIG_ARCH_OMAP4)		+= clock44xx_data.o
 obj-$(CONFIG_ARCH_OMAP4)		+= dpll3xxx.o dpll44xx.o
-obj-$(CONFIG_SOC_AM33XX)		+= $(clock-common) dpll3xxx.o
-obj-$(CONFIG_SOC_AM33XX)		+= clock33xx_data.o
-obj-$(CONFIG_SOC_OMAP5)			+= $(clock-common)
+obj-$(CONFIG_SOC_AM33XX)		+= dpll3xxx.o clock33xx_data.o
 obj-$(CONFIG_SOC_OMAP5)			+= dpll3xxx.o dpll44xx.o
 
 # OMAP2 clock rate set data (old "OPP" data)
@@ -181,6 +160,7 @@ obj-$(CONFIG_SOC_OMAP2420)		+= opp2420_data.o
 obj-$(CONFIG_SOC_OMAP2430)		+= opp2430_data.o
 
 # hwmod data
+obj-y					+= omap_hwmod_common_data.o
 obj-$(CONFIG_SOC_OMAP2420)		+= omap_hwmod_2xxx_ipblock_data.o
 obj-$(CONFIG_SOC_OMAP2420)		+= omap_hwmod_2xxx_3xxx_ipblock_data.o
 obj-$(CONFIG_SOC_OMAP2420)		+= omap_hwmod_2xxx_interconnect_data.o
@@ -194,16 +174,12 @@ obj-$(CONFIG_SOC_OMAP2430)		+= omap_hwmod_2430_data.o
 obj-$(CONFIG_ARCH_OMAP3)		+= omap_hwmod_2xxx_3xxx_ipblock_data.o
 obj-$(CONFIG_ARCH_OMAP3)		+= omap_hwmod_2xxx_3xxx_interconnect_data.o
 obj-$(CONFIG_ARCH_OMAP3)		+= omap_hwmod_3xxx_data.o
+obj-$(CONFIG_SOC_AM33XX)		+= omap_hwmod_33xx_data.o
 obj-$(CONFIG_ARCH_OMAP4)		+= omap_hwmod_44xx_data.o
 
 # EMU peripherals
 obj-$(CONFIG_OMAP3_EMU)			+= emu.o
 
-# L3 interconnect
-obj-$(CONFIG_ARCH_OMAP3)		+= omap_l3_smx.o
-obj-$(CONFIG_ARCH_OMAP4)		+= omap_l3_noc.o
-obj-$(CONFIG_SOC_OMAP5)			+= omap_l3_noc.o
-
 obj-$(CONFIG_OMAP_MBOX_FWK)		+= mailbox_mach.o
 mailbox_mach-objs			:= mailbox.o
 
@@ -229,10 +205,10 @@ obj-$(CONFIG_MACH_OMAP_H4)		+= board-h4.o
 obj-$(CONFIG_MACH_OMAP_2430SDP)		+= board-2430sdp.o
 obj-$(CONFIG_MACH_OMAP_APOLLON)		+= board-apollon.o
 obj-$(CONFIG_MACH_OMAP3_BEAGLE)		+= board-omap3beagle.o
-obj-$(CONFIG_MACH_DEVKIT8000)     	+= board-devkit8000.o
+obj-$(CONFIG_MACH_DEVKIT8000)		+= board-devkit8000.o
 obj-$(CONFIG_MACH_OMAP_LDP)		+= board-ldp.o
-obj-$(CONFIG_MACH_OMAP3530_LV_SOM)      += board-omap3logic.o
-obj-$(CONFIG_MACH_OMAP3_TORPEDO)        += board-omap3logic.o
+obj-$(CONFIG_MACH_OMAP3530_LV_SOM)	+= board-omap3logic.o
+obj-$(CONFIG_MACH_OMAP3_TORPEDO)	+= board-omap3logic.o
 obj-$(CONFIG_MACH_ENCORE)		+= board-omap3encore.o
 obj-$(CONFIG_MACH_OVERO)		+= board-overo.o
 obj-$(CONFIG_MACH_OMAP3EVM)		+= board-omap3evm.o
diff --git a/arch/arm/mach-omap2/am33xx.h b/arch/arm/mach-omap2/am33xx.h
new file mode 100644
index 0000000..06c19bb
--- /dev/null
+++ b/arch/arm/mach-omap2/am33xx.h
@@ -0,0 +1,25 @@
+/*
+ * This file contains the address info for various AM33XX modules.
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc. - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __ASM_ARCH_AM33XX_H
+#define __ASM_ARCH_AM33XX_H
+
+#define L4_SLOW_AM33XX_BASE	0x48000000
+
+#define AM33XX_SCM_BASE		0x44E10000
+#define AM33XX_CTRL_BASE	AM33XX_SCM_BASE
+#define AM33XX_PRCM_BASE	0x44E00000
+
+#endif /* __ASM_ARCH_AM33XX_H */
diff --git a/arch/arm/mach-omap2/am35xx-emac.c b/arch/arm/mach-omap2/am35xx-emac.c
index 2c90ac6..d0c54c5 100644
--- a/arch/arm/mach-omap2/am35xx-emac.c
+++ b/arch/arm/mach-omap2/am35xx-emac.c
@@ -19,7 +19,7 @@
 #include <linux/davinci_emac.h>
 #include <asm/system.h>
 #include <plat/omap_device.h>
-#include <mach/am35xx.h>
+#include "am35xx.h"
 #include "control.h"
 #include "am35xx-emac.h"
 
diff --git a/arch/arm/mach-omap2/am35xx.h b/arch/arm/mach-omap2/am35xx.h
new file mode 100644
index 0000000..9559449
--- /dev/null
+++ b/arch/arm/mach-omap2/am35xx.h
@@ -0,0 +1,46 @@
+/*:
+ * Address mappings and base address for AM35XX specific interconnects
+ * and peripherals.
+ *
+ * Copyright (C) 2009 Texas Instruments
+ *
+ * Author: Sriramakrishnan <srk@ti.com>
+ *	   Vaibhav Hiremath <hvaibhav@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.
+ */
+#ifndef __ASM_ARCH_AM35XX_H
+#define __ASM_ARCH_AM35XX_H
+
+/*
+ * Base addresses
+ *	Note: OMAP3430 IVA2 memory space is being used for AM35xx IPSS modules
+ */
+#define AM35XX_IPSS_EMAC_BASE		0x5C000000
+#define AM35XX_IPSS_USBOTGSS_BASE	0x5C040000
+#define AM35XX_IPSS_HECC_BASE		0x5C050000
+#define AM35XX_IPSS_VPFE_BASE		0x5C060000
+
+
+/* HECC module specifc offset definitions */
+#define AM35XX_HECC_SCC_HECC_OFFSET	(0x0)
+#define AM35XX_HECC_SCC_RAM_OFFSET	(0x3000)
+#define AM35XX_HECC_RAM_OFFSET		(0x3000)
+#define AM35XX_HECC_MBOX_OFFSET		(0x2000)
+#define AM35XX_HECC_INT_LINE		(0x0)
+#define AM35XX_HECC_VERSION		(0x1)
+
+#define AM35XX_EMAC_CNTRL_OFFSET	(0x10000)
+#define AM35XX_EMAC_CNTRL_MOD_OFFSET	(0x0)
+#define AM35XX_EMAC_CNTRL_RAM_OFFSET	(0x20000)
+#define AM35XX_EMAC_MDIO_OFFSET		(0x30000)
+#define AM35XX_IPSS_MDIO_BASE		(AM35XX_IPSS_EMAC_BASE + \
+						AM35XX_EMAC_MDIO_OFFSET)
+#define AM35XX_EMAC_CNTRL_RAM_SIZE	(0x2000)
+#define AM35XX_EMAC_RAM_ADDR		(AM3517_EMAC_BASE + \
+						AM3517_EMAC_CNTRL_RAM_OFFSET)
+#define AM35XX_EMAC_HW_RAM_ADDR		(0x01E20000)
+
+#endif  /*  __ASM_ARCH_AM35XX_H */
diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c
index 9511584..95b384d 100644
--- a/arch/arm/mach-omap2/board-2430sdp.c
+++ b/arch/arm/mach-omap2/board-2430sdp.c
@@ -33,11 +33,10 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include <plat/board.h>
 #include "common.h"
 #include <plat/gpmc.h>
 #include <plat/usb.h>
-#include <plat/gpmc-smc91x.h>
+#include "gpmc-smc91x.h"
 
 #include <video/omapdss.h>
 #include <video/omap-panel-generic-dpi.h>
@@ -212,9 +211,6 @@ static struct regulator_init_data sdp2430_vmmc1 = {
 };
 
 static struct twl4030_gpio_platform_data sdp2430_gpio_data = {
-	.gpio_base	= OMAP_MAX_GPIO_LINES,
-	.irq_base	= TWL4030_GPIO_IRQ_BASE,
-	.irq_end	= TWL4030_GPIO_IRQ_END,
 };
 
 static struct twl4030_platform_data sdp2430_twldata = {
@@ -235,7 +231,7 @@ static int __init omap2430_i2c_init(void)
 	sdp2430_i2c1_boardinfo[0].irq = gpio_to_irq(78);
 	omap_register_i2c_bus(1, 100, sdp2430_i2c1_boardinfo,
 			ARRAY_SIZE(sdp2430_i2c1_boardinfo));
-	omap_pmic_init(2, 100, "twl4030", INT_24XX_SYS_NIRQ,
+	omap_pmic_init(2, 100, "twl4030", 7 + OMAP_INTC_START,
 			&sdp2430_twldata);
 	return 0;
 }
diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
index a98c688..96cd369 100644
--- a/arch/arm/mach-omap2/board-3430sdp.c
+++ b/arch/arm/mach-omap2/board-3430sdp.c
@@ -24,14 +24,12 @@
 #include <linux/io.h>
 #include <linux/gpio.h>
 #include <linux/mmc/host.h>
+#include <linux/platform_data/spi-omap2-mcspi.h>
 
-#include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include <plat/mcspi.h>
-#include <plat/board.h>
 #include <plat/usb.h>
 #include "common.h"
 #include <plat/dma.h>
@@ -39,7 +37,7 @@
 #include <video/omapdss.h>
 #include <video/omap-panel-tfp410.h>
 
-#include <plat/gpmc-smc91x.h>
+#include "gpmc-smc91x.h"
 
 #include "board-flash.h"
 #include "mux.h"
@@ -191,9 +189,6 @@ static struct omap_dss_board_info sdp3430_dss_data = {
 	.default_device	= &sdp3430_lcd_device,
 };
 
-static struct omap_board_config_kernel sdp3430_config[] __initdata = {
-};
-
 static struct omap2_hsmmc_info mmc[] = {
 	{
 		.mmc		= 1,
@@ -233,9 +228,6 @@ static int sdp3430_twl_gpio_setup(struct device *dev,
 }
 
 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,
@@ -576,8 +568,6 @@ static void __init omap_3430sdp_init(void)
 	int gpio_pendown;
 
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
-	omap_board_config = sdp3430_config;
-	omap_board_config_size = ARRAY_SIZE(sdp3430_config);
 	omap_hsmmc_init(mmc);
 	omap3430_i2c_init();
 	omap_display_init(&sdp3430_dss_data);
diff --git a/arch/arm/mach-omap2/board-3630sdp.c b/arch/arm/mach-omap2/board-3630sdp.c
index 2dc9ba5..fc224ad 100644
--- a/arch/arm/mach-omap2/board-3630sdp.c
+++ b/arch/arm/mach-omap2/board-3630sdp.c
@@ -17,8 +17,7 @@
 #include <asm/mach/arch.h>
 
 #include "common.h"
-#include <plat/board.h>
-#include <plat/gpmc-smc91x.h>
+#include "gpmc-smc91x.h"
 #include <plat/usb.h>
 
 #include <mach/board-zoom.h>
@@ -67,9 +66,6 @@ static const struct usbhs_omap_board_data usbhs_bdata __initconst = {
 	.reset_gpio_port[2]  = -EINVAL
 };
 
-static struct omap_board_config_kernel sdp_config[] __initdata = {
-};
-
 #ifdef CONFIG_OMAP_MUX
 static struct omap_board_mux board_mux[] __initdata = {
 	{ .reg_offset = OMAP_MUX_TERMINATOR },
@@ -197,8 +193,6 @@ static struct flash_partitions sdp_flash_partitions[] = {
 static void __init omap_sdp_init(void)
 {
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBP);
-	omap_board_config = sdp_config;
-	omap_board_config_size = ARRAY_SIZE(sdp_config);
 	zoom_peripherals_init();
 	omap_sdrc_init(h8mbx00u0mer0em_sdrc_params,
 				  h8mbx00u0mer0em_sdrc_params);
diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c
index ad8a7d9..09644af 100644
--- a/arch/arm/mach-omap2/board-4430sdp.c
+++ b/arch/arm/mach-omap2/board-4430sdp.c
@@ -28,23 +28,22 @@
 #include <linux/leds_pwm.h>
 #include <linux/platform_data/omap4-keypad.h>
 
-#include <mach/hardware.h>
 #include <asm/hardware/gic.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include <plat/board.h>
 #include "common.h"
 #include <plat/usb.h>
 #include <plat/mmc.h>
-#include <plat/omap4-keypad.h>
+#include "omap4-keypad.h"
 #include <video/omapdss.h>
 #include <video/omap-panel-nokia-dsi.h>
 #include <video/omap-panel-picodlp.h>
 #include <linux/wl12xx.h>
 #include <linux/platform_data/omap-abe-twl6040.h>
 
+#include "soc.h"
 #include "mux.h"
 #include "hsmmc.h"
 #include "control.h"
@@ -544,7 +543,6 @@ static struct twl6040_platform_data twl6040_data = {
 	.codec		= &twl6040_codec,
 	.vibra		= &twl6040_vibra,
 	.audpwron_gpio	= 127,
-	.irq_base	= TWL6040_CODEC_IRQ_BASE,
 };
 
 static struct twl4030_platform_data sdp4430_twldata = {
@@ -581,7 +579,7 @@ static int __init omap4_i2c_init(void)
 			TWL_COMMON_REGULATOR_V1V8 |
 			TWL_COMMON_REGULATOR_V2V1);
 	omap4_pmic_init("twl6030", &sdp4430_twldata,
-			&twl6040_data, OMAP44XX_IRQ_SYS_2N);
+			&twl6040_data, 119 + OMAP44XX_IRQ_GIC_START);
 	omap_register_i2c_bus(2, 400, NULL, 0);
 	omap_register_i2c_bus(3, 400, sdp4430_i2c_3_boardinfo,
 				ARRAY_SIZE(sdp4430_i2c_3_boardinfo));
@@ -601,29 +599,6 @@ static void __init omap_sfh7741prox_init(void)
 			__func__, OMAP4_SFH7741_ENABLE_GPIO, error);
 }
 
-static struct gpio sdp4430_hdmi_gpios[] = {
-	{ HDMI_GPIO_CT_CP_HPD, GPIOF_OUT_INIT_HIGH, "hdmi_gpio_ct_cp_hpd" },
-	{ HDMI_GPIO_LS_OE,	GPIOF_OUT_INIT_HIGH,	"hdmi_gpio_ls_oe" },
-	{ HDMI_GPIO_HPD, GPIOF_DIR_IN, "hdmi_gpio_hpd" },
-};
-
-static int sdp4430_panel_enable_hdmi(struct omap_dss_device *dssdev)
-{
-	int status;
-
-	status = gpio_request_array(sdp4430_hdmi_gpios,
-				    ARRAY_SIZE(sdp4430_hdmi_gpios));
-	if (status)
-		pr_err("%s: Cannot request HDMI GPIOs\n", __func__);
-
-	return status;
-}
-
-static void sdp4430_panel_disable_hdmi(struct omap_dss_device *dssdev)
-{
-	gpio_free_array(sdp4430_hdmi_gpios, ARRAY_SIZE(sdp4430_hdmi_gpios));
-}
-
 static struct nokia_dsi_panel_data dsi1_panel = {
 		.name		= "taal",
 		.reset_gpio	= 102,
@@ -644,29 +619,6 @@ static struct omap_dss_device sdp4430_lcd_device = {
 	.phy.dsi		= {
 		.module		= 0,
 	},
-
-	.clocks = {
-		.dispc = {
-			.channel = {
-				/* Logic Clock = 172.8 MHz */
-				.lck_div	= 1,
-				/* Pixel Clock = 34.56 MHz */
-				.pck_div	= 5,
-				.lcd_clk_src	= OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC,
-			},
-			.dispc_fclk_src	= OMAP_DSS_CLK_SRC_FCK,
-		},
-
-		.dsi = {
-			.regn		= 16,	/* Fint = 2.4 MHz */
-			.regm		= 180,	/* DDR Clock = 216 MHz */
-			.regm_dispc	= 5,	/* PLL1_CLK1 = 172.8 MHz */
-			.regm_dsi	= 5,	/* PLL1_CLK2 = 172.8 MHz */
-
-			.lp_clk_div	= 10,	/* LP Clock = 8.64 MHz */
-			.dsi_fclk_src	= OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI,
-		},
-	},
 	.channel		= OMAP_DSS_CHANNEL_LCD,
 };
 
@@ -691,33 +643,12 @@ static struct omap_dss_device sdp4430_lcd2_device = {
 
 		.module		= 1,
 	},
-
-	.clocks = {
-		.dispc = {
-			.channel = {
-				/* Logic Clock = 172.8 MHz */
-				.lck_div	= 1,
-				/* Pixel Clock = 34.56 MHz */
-				.pck_div	= 5,
-				.lcd_clk_src	= OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC,
-			},
-			.dispc_fclk_src	= OMAP_DSS_CLK_SRC_FCK,
-		},
-
-		.dsi = {
-			.regn		= 16,	/* Fint = 2.4 MHz */
-			.regm		= 180,	/* DDR Clock = 216 MHz */
-			.regm_dispc	= 5,	/* PLL1_CLK1 = 172.8 MHz */
-			.regm_dsi	= 5,	/* PLL1_CLK2 = 172.8 MHz */
-
-			.lp_clk_div	= 10,	/* LP Clock = 8.64 MHz */
-			.dsi_fclk_src	= OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI,
-		},
-	},
 	.channel		= OMAP_DSS_CHANNEL_LCD2,
 };
 
 static struct omap_dss_hdmi_data sdp4430_hdmi_data = {
+	.ct_cp_hpd_gpio = HDMI_GPIO_CT_CP_HPD,
+	.ls_oe_gpio = HDMI_GPIO_LS_OE,
 	.hpd_gpio = HDMI_GPIO_HPD,
 };
 
@@ -725,8 +656,6 @@ static struct omap_dss_device sdp4430_hdmi_device = {
 	.name = "hdmi",
 	.driver_name = "hdmi_panel",
 	.type = OMAP_DISPLAY_TYPE_HDMI,
-	.platform_enable = sdp4430_panel_enable_hdmi,
-	.platform_disable = sdp4430_panel_disable_hdmi,
 	.channel = OMAP_DSS_CHANNEL_DIGIT,
 	.data = &sdp4430_hdmi_data,
 };
@@ -909,6 +838,7 @@ static void __init omap_4430sdp_init(void)
 MACHINE_START(OMAP_4430SDP, "OMAP4430 4430SDP board")
 	/* Maintainer: Santosh Shilimkar - Texas Instruments Inc */
 	.atag_offset	= 0x100,
+	.smp		= smp_ops(omap4_smp_ops),
 	.reserve	= omap_reserve,
 	.map_io		= omap4_map_io,
 	.init_early	= omap4430_init_early,
diff --git a/arch/arm/mach-omap2/board-am3517crane.c b/arch/arm/mach-omap2/board-am3517crane.c
index 92432c2..318fead 100644
--- a/arch/arm/mach-omap2/board-am3517crane.c
+++ b/arch/arm/mach-omap2/board-am3517crane.c
@@ -21,12 +21,10 @@
 #include <linux/init.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 <plat/board.h>
 #include "common.h"
 #include <plat/usb.h>
 
@@ -37,11 +35,6 @@
 #define GPIO_USB_POWER		35
 #define GPIO_USB_NRESET		38
 
-
-/* Board initialization */
-static struct omap_board_config_kernel am3517_crane_config[] __initdata = {
-};
-
 #ifdef CONFIG_OMAP_MUX
 static struct omap_board_mux board_mux[] __initdata = {
 	{ .reg_offset = OMAP_MUX_TERMINATOR },
@@ -67,9 +60,6 @@ static void __init am3517_crane_init(void)
 	omap_serial_init();
 	omap_sdrc_init(NULL, NULL);
 
-	omap_board_config = am3517_crane_config;
-	omap_board_config_size = ARRAY_SIZE(am3517_crane_config);
-
 	/* Configure GPIO for EHCI port */
 	if (omap_mux_init_gpio(GPIO_USB_NRESET, OMAP_PIN_OUTPUT)) {
 		pr_err("Can not configure mux for GPIO_USB_NRESET %d\n",
diff --git a/arch/arm/mach-omap2/board-am3517evm.c b/arch/arm/mach-omap2/board-am3517evm.c
index 18f6010..e162897 100644
--- a/arch/arm/mach-omap2/board-am3517evm.c
+++ b/arch/arm/mach-omap2/board-am3517evm.c
@@ -25,14 +25,13 @@
 #include <linux/can/platform/ti_hecc.h>
 #include <linux/davinci_emac.h>
 #include <linux/mmc/host.h>
+#include <linux/platform_data/gpio-omap.h>
 
-#include <mach/hardware.h>
-#include <mach/am35xx.h>
+#include "am35xx.h"
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include <plat/board.h>
 #include "common.h"
 #include <plat/usb.h>
 #include <video/omapdss.h>
@@ -264,6 +263,16 @@ static __init void am3517_evm_musb_init(void)
 	usb_musb_init(&musb_board_data);
 }
 
+static __init void am3517_evm_mcbsp1_init(void)
+{
+	u32 devconf0;
+
+	/* McBSP1 CLKR/FSR signal to be connected to CLKX/FSX pin */
+	devconf0 = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0);
+	devconf0 |=  OMAP2_MCBSP1_CLKR_MASK | OMAP2_MCBSP1_FSR_MASK;
+	omap_ctrl_writel(devconf0, OMAP2_CONTROL_DEVCONF0);
+}
+
 static const struct usbhs_omap_board_data usbhs_bdata __initconst = {
 	.port_mode[0] = OMAP_EHCI_PORT_MODE_PHY,
 #if defined(CONFIG_PANEL_SHARP_LQ043T1DG01) || \
@@ -296,8 +305,7 @@ static struct resource am3517_hecc_resources[] = {
 		.flags	= IORESOURCE_MEM,
 	},
 	{
-		.start	= INT_35XX_HECC0_IRQ,
-		.end	= INT_35XX_HECC0_IRQ,
+		.start	= 24 + OMAP_INTC_START,
 		.flags	= IORESOURCE_IRQ,
 	},
 };
@@ -324,9 +332,6 @@ static void am3517_evm_hecc_init(struct ti_hecc_platform_data *pdata)
 	platform_device_register(&am3517_hecc_device);
 }
 
-static struct omap_board_config_kernel am3517_evm_config[] __initdata = {
-};
-
 static struct omap2_hsmmc_info mmc[] = {
 	{
 		.mmc		= 1,
@@ -346,8 +351,6 @@ static struct omap2_hsmmc_info mmc[] = {
 
 static void __init am3517_evm_init(void)
 {
-	omap_board_config = am3517_evm_config;
-	omap_board_config_size = ARRAY_SIZE(am3517_evm_config);
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
 
 	am3517_evm_i2c_init();
@@ -373,6 +376,9 @@ static void __init am3517_evm_init(void)
 	/* MUSB */
 	am3517_evm_musb_init();
 
+	/* McBSP1 */
+	am3517_evm_mcbsp1_init();
+
 	/* MMC init function */
 	omap_hsmmc_init(mmc);
 }
diff --git a/arch/arm/mach-omap2/board-apollon.c b/arch/arm/mach-omap2/board-apollon.c
index e5fa46b..3e2d76f 100644
--- a/arch/arm/mach-omap2/board-apollon.c
+++ b/arch/arm/mach-omap2/board-apollon.c
@@ -29,13 +29,11 @@
 #include <linux/smc91x.h>
 #include <linux/gpio.h>
 
-#include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/flash.h>
 
 #include <plat/led.h>
-#include <plat/board.h>
 #include "common.h"
 #include <plat/gpmc.h>
 
diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c
index 97d7190..376d26e 100644
--- a/arch/arm/mach-omap2/board-cm-t35.c
+++ b/arch/arm/mach-omap2/board-cm-t35.c
@@ -23,6 +23,7 @@
 #include <linux/input/matrix_keypad.h>
 #include <linux/delay.h>
 #include <linux/gpio.h>
+#include <linux/platform_data/gpio-omap.h>
 
 #include <linux/i2c/at24.h>
 #include <linux/i2c/twl.h>
@@ -37,15 +38,14 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include <plat/board.h>
 #include "common.h"
-#include <plat/nand.h>
+#include <linux/platform_data/mtd-nand-omap2.h>
 #include <plat/gpmc.h>
 #include <plat/usb.h>
 #include <video/omapdss.h>
 #include <video/omap-panel-generic-dpi.h>
 #include <video/omap-panel-tfp410.h>
-#include <plat/mcspi.h>
+#include <linux/platform_data/spi-omap2-mcspi.h>
 
 #include <mach/hardware.h>
 
@@ -64,7 +64,7 @@
 
 #if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)
 #include <linux/smsc911x.h>
-#include <plat/gpmc-smsc911x.h>
+#include "gpmc-smsc911x.h"
 
 static struct omap_smsc911x_platform_data cm_t35_smsc911x_cfg = {
 	.id		= 0,
@@ -470,9 +470,6 @@ static int cm_t35_twl_gpio_setup(struct device *dev, unsigned gpio,
 }
 
 static struct twl4030_gpio_platform_data cm_t35_gpio_data = {
-	.gpio_base	= OMAP_MAX_GPIO_LINES,
-	.irq_base	= TWL4030_GPIO_IRQ_BASE,
-	.irq_end	= TWL4030_GPIO_IRQ_END,
 	.setup          = cm_t35_twl_gpio_setup,
 };
 
@@ -714,13 +711,8 @@ static inline void cm_t35_init_mux(void) {}
 static inline void cm_t3730_init_mux(void) {}
 #endif
 
-static struct omap_board_config_kernel cm_t35_config[] __initdata = {
-};
-
 static void __init cm_t3x_common_init(void)
 {
-	omap_board_config = cm_t35_config;
-	omap_board_config_size = ARRAY_SIZE(cm_t35_config);
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CUS);
 	omap_serial_init();
 	omap_sdrc_init(mt46h32m32lf6_sdrc_params,
@@ -731,6 +723,7 @@ static void __init cm_t3x_common_init(void)
 	cm_t35_init_ethernet();
 	cm_t35_init_led();
 	cm_t35_init_display();
+	omap_twl4030_audio_init("cm-t3x");
 
 	usb_musb_init(NULL);
 	cm_t35_init_usbh();
diff --git a/arch/arm/mach-omap2/board-cm-t3517.c b/arch/arm/mach-omap2/board-cm-t3517.c
index a33ad46..59c0a45 100644
--- a/arch/arm/mach-omap2/board-cm-t3517.c
+++ b/arch/arm/mach-omap2/board-cm-t3517.c
@@ -38,13 +38,12 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include <plat/board.h>
 #include "common.h"
 #include <plat/usb.h>
-#include <plat/nand.h>
+#include <linux/platform_data/mtd-nand-omap2.h>
 #include <plat/gpmc.h>
 
-#include <mach/am35xx.h>
+#include "am35xx.h"
 
 #include "mux.h"
 #include "control.h"
@@ -90,8 +89,7 @@ static struct resource cm_t3517_hecc_resources[] = {
 		.flags	= IORESOURCE_MEM,
 	},
 	{
-		.start	= INT_35XX_HECC0_IRQ,
-		.end	= INT_35XX_HECC0_IRQ,
+		.start	= 24 + OMAP_INTC_START,
 		.flags	= IORESOURCE_IRQ,
 	},
 };
@@ -249,9 +247,6 @@ static void __init cm_t3517_init_nand(void)
 static inline void cm_t3517_init_nand(void) {}
 #endif
 
-static struct omap_board_config_kernel cm_t3517_config[] __initdata = {
-};
-
 #ifdef CONFIG_OMAP_MUX
 static struct omap_board_mux board_mux[] __initdata = {
 	/* GPIO186 - Green LED */
@@ -285,8 +280,6 @@ static void __init cm_t3517_init(void)
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
 	omap_serial_init();
 	omap_sdrc_init(NULL, NULL);
-	omap_board_config = cm_t3517_config;
-	omap_board_config_size = ARRAY_SIZE(cm_t3517_config);
 	cm_t3517_init_leds();
 	cm_t3517_init_nand();
 	cm_t3517_init_rtc();
diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c
index 6567c1c..1fd161e 100644
--- a/arch/arm/mach-omap2/board-devkit8000.c
+++ b/arch/arm/mach-omap2/board-devkit8000.c
@@ -32,31 +32,27 @@
 
 #include <linux/regulator/machine.h>
 #include <linux/i2c/twl.h>
-
-#include <mach/hardware.h>
-#include <mach/id.h>
+#include "id.h"
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/flash.h>
 
-#include <plat/board.h>
 #include "common.h"
 #include <plat/gpmc.h>
-#include <plat/nand.h>
+#include <linux/platform_data/mtd-nand-omap2.h>
 #include <plat/usb.h>
 #include <video/omapdss.h>
 #include <video/omap-panel-generic-dpi.h>
 #include <video/omap-panel-tfp410.h>
 
-#include <plat/mcspi.h>
+#include <linux/platform_data/spi-omap2-mcspi.h>
 #include <linux/input/matrix_keypad.h>
 #include <linux/spi/spi.h>
 #include <linux/dm9000.h>
 #include <linux/interrupt.h>
 
 #include "sdram-micron-mt46h32m32lf-6.h"
-
 #include "mux.h"
 #include "hsmmc.h"
 #include "common-board-devices.h"
@@ -236,9 +232,6 @@ static int devkit8000_twl_gpio_setup(struct device *dev,
 }
 
 static struct twl4030_gpio_platform_data devkit8000_gpio_data = {
-	.gpio_base	= OMAP_MAX_GPIO_LINES,
-	.irq_base	= TWL4030_GPIO_IRQ_BASE,
-	.irq_end	= TWL4030_GPIO_IRQ_END,
 	.use_leds	= true,
 	.pulldowns	= BIT(1) | BIT(2) | BIT(6) | BIT(8) | BIT(13)
 				| BIT(15) | BIT(16) | BIT(17),
@@ -630,6 +623,7 @@ static void __init devkit8000_init(void)
 	usbhs_init(&usbhs_bdata);
 	omap_nand_flash_init(NAND_BUSWIDTH_16, devkit8000_nand_partitions,
 			     ARRAY_SIZE(devkit8000_nand_partitions));
+	omap_twl4030_audio_init("omap3beagle");
 
 	/* Ensure SDRC pins are mux'd for self-refresh */
 	omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT);
diff --git a/arch/arm/mach-omap2/board-flash.c b/arch/arm/mach-omap2/board-flash.c
index 53c39d2..0cabe61 100644
--- a/arch/arm/mach-omap2/board-flash.c
+++ b/arch/arm/mach-omap2/board-flash.c
@@ -16,13 +16,14 @@
 #include <linux/platform_device.h>
 #include <linux/mtd/physmap.h>
 #include <linux/io.h>
-#include <plat/irqs.h>
 
+#include <plat/cpu.h>
 #include <plat/gpmc.h>
-#include <plat/nand.h>
-#include <plat/onenand.h>
+#include <linux/platform_data/mtd-nand-omap2.h>
+#include <linux/platform_data/mtd-onenand-omap2.h>
 #include <plat/tc.h>
 
+#include "common.h"
 #include "board-flash.h"
 
 #define REG_FPGA_REV			0x10
@@ -140,7 +141,6 @@ __init board_nand_init(struct mtd_partition *nand_parts,
 	board_nand_data.devsize		= nand_type;
 
 	board_nand_data.ecc_opt = OMAP_ECC_HAMMING_CODE_DEFAULT;
-	board_nand_data.gpmc_irq = OMAP_GPMC_IRQ_BASE + cs;
 	gpmc_nand_init(&board_nand_data);
 }
 #endif /* CONFIG_MTD_NAND_OMAP2 || CONFIG_MTD_NAND_OMAP2_MODULE */
diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c
index 6f93a20..601ecdf 100644
--- a/arch/arm/mach-omap2/board-generic.c
+++ b/arch/arm/mach-omap2/board-generic.c
@@ -16,11 +16,9 @@
 #include <linux/of_platform.h>
 #include <linux/irqdomain.h>
 
-#include <mach/hardware.h>
 #include <asm/hardware/gic.h>
 #include <asm/mach/arch.h>
 
-#include <plat/board.h>
 #include "common.h"
 #include "common-board-devices.h"
 
@@ -127,6 +125,7 @@ static const char *omap4_boards_compat[] __initdata = {
 
 DT_MACHINE_START(OMAP4_DT, "Generic OMAP4 (Flattened Device Tree)")
 	.reserve	= omap_reserve,
+	.smp		= smp_ops(omap4_smp_ops),
 	.map_io		= omap4_map_io,
 	.init_early	= omap4430_init_early,
 	.init_irq	= omap_gic_of_init,
@@ -147,6 +146,7 @@ static const char *omap5_boards_compat[] __initdata = {
 
 DT_MACHINE_START(OMAP5_DT, "Generic OMAP5 (Flattened Device Tree)")
 	.reserve	= omap_reserve,
+	.smp		= smp_ops(omap4_smp_ops),
 	.map_io		= omap5_map_io,
 	.init_early	= omap5_init_early,
 	.init_irq	= omap_gic_of_init,
diff --git a/arch/arm/mach-omap2/board-h4.c b/arch/arm/mach-omap2/board-h4.c
index ace2048..f6c48dd 100644
--- a/arch/arm/mach-omap2/board-h4.c
+++ b/arch/arm/mach-omap2/board-h4.c
@@ -27,20 +27,19 @@
 #include <linux/io.h>
 #include <linux/input/matrix_keypad.h>
 
-#include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include <plat/board.h>
-#include "common.h"
 #include <plat/menelaus.h>
 #include <plat/dma.h>
 #include <plat/gpmc.h>
+#include "debug-devices.h"
 
 #include <video/omapdss.h>
 #include <video/omap-panel-generic-dpi.h>
 
+#include "common.h"
 #include "mux.h"
 #include "control.h"
 
diff --git a/arch/arm/mach-omap2/board-igep0020.c b/arch/arm/mach-omap2/board-igep0020.c
index 2821448..48d5e41 100644
--- a/arch/arm/mach-omap2/board-igep0020.c
+++ b/arch/arm/mach-omap2/board-igep0020.c
@@ -29,13 +29,13 @@
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
-#include <plat/board.h>
 #include "common.h"
 #include <plat/gpmc.h>
 #include <plat/usb.h>
+
 #include <video/omapdss.h>
 #include <video/omap-panel-tfp410.h>
-#include <plat/onenand.h>
+#include <linux/platform_data/mtd-onenand-omap2.h>
 
 #include "mux.h"
 #include "hsmmc.h"
@@ -192,7 +192,7 @@ static void __init igep_flash_init(void) {}
 #if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)
 
 #include <linux/smsc911x.h>
-#include <plat/gpmc-smsc911x.h>
+#include "gpmc-smsc911x.h"
 
 static struct omap_smsc911x_platform_data smsc911x_cfg = {
 	.cs             = IGEP2_SMSC911X_CS,
@@ -425,9 +425,6 @@ static int igep_twl_gpio_setup(struct device *dev,
 };
 
 static struct twl4030_gpio_platform_data igep_twl4030_gpio_pdata = {
-	.gpio_base	= OMAP_MAX_GPIO_LINES,
-	.irq_base	= TWL4030_GPIO_IRQ_BASE,
-	.irq_end	= TWL4030_GPIO_IRQ_END,
 	.use_leds	= true,
 	.setup		= igep_twl_gpio_setup,
 };
@@ -628,6 +625,7 @@ static void __init igep_init(void)
 
 	igep_flash_init();
 	igep_leds_init();
+	omap_twl4030_audio_init("igep2");
 
 	/*
 	 * WLAN-BT combo module from MuRata which has a Marvell WLAN
diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c
index ef9e829..ee8c3cf 100644
--- a/arch/arm/mach-omap2/board-ldp.c
+++ b/arch/arm/mach-omap2/board-ldp.c
@@ -28,21 +28,17 @@
 #include <linux/io.h>
 #include <linux/smsc911x.h>
 #include <linux/mmc/host.h>
+#include <linux/platform_data/spi-omap2-mcspi.h>
 
-#include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include <plat/mcspi.h>
-#include <plat/board.h>
 #include "common.h"
 #include <plat/gpmc.h>
 #include <mach/board-zoom.h>
-
-#include <asm/delay.h>
 #include <plat/usb.h>
-#include <plat/gpmc-smsc911x.h>
+#include "gpmc-smsc911x.h"
 
 #include <video/omapdss.h>
 #include <video/omap-panel-generic-dpi.h>
@@ -275,9 +271,6 @@ static int ldp_twl_gpio_setup(struct device *dev, unsigned gpio, unsigned ngpio)
 }
 
 static struct twl4030_gpio_platform_data ldp_gpio_data = {
-	.gpio_base	= OMAP_MAX_GPIO_LINES,
-	.irq_base	= TWL4030_GPIO_IRQ_BASE,
-	.irq_end	= TWL4030_GPIO_IRQ_END,
 	.setup		= ldp_twl_gpio_setup,
 };
 
diff --git a/arch/arm/mach-omap2/board-n8x0.c b/arch/arm/mach-omap2/board-n8x0.c
index 677357f..d95f727 100644
--- a/arch/arm/mach-omap2/board-n8x0.c
+++ b/arch/arm/mach-omap2/board-n8x0.c
@@ -20,19 +20,16 @@
 #include <linux/i2c.h>
 #include <linux/spi/spi.h>
 #include <linux/usb/musb.h>
+#include <linux/platform_data/spi-omap2-mcspi.h>
+#include <linux/platform_data/mtd-onenand-omap2.h>
 #include <sound/tlv320aic3x.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 
-#include <plat/board.h>
 #include "common.h"
 #include <plat/menelaus.h>
-#include <mach/irqs.h>
-#include <plat/mcspi.h>
-#include <plat/onenand.h>
 #include <plat/mmc.h>
-#include <plat/serial.h>
 
 #include "mux.h"
 
@@ -553,8 +550,8 @@ static int n8x0_auto_sleep_regulators(void)
 
 	ret = menelaus_set_regulator_sleep(1, val);
 	if (ret < 0) {
-		printk(KERN_ERR "Could not set regulators to sleep on "
-			"menelaus: %u\n", ret);
+		pr_err("Could not set regulators to sleep on menelaus: %u\n",
+		       ret);
 		return ret;
 	}
 	return 0;
@@ -566,8 +563,7 @@ static int n8x0_auto_voltage_scale(void)
 
 	ret = menelaus_set_vcore_hw(1400, 1050);
 	if (ret < 0) {
-		printk(KERN_ERR "Could not set VCORE voltage on "
-			"menelaus: %u\n", ret);
+		pr_err("Could not set VCORE voltage on menelaus: %u\n", ret);
 		return ret;
 	}
 	return 0;
@@ -600,7 +596,7 @@ static struct menelaus_platform_data n8x0_menelaus_platform_data __initdata = {
 static struct i2c_board_info __initdata n8x0_i2c_board_info_1[] __initdata = {
 	{
 		I2C_BOARD_INFO("menelaus", 0x72),
-		.irq = INT_24XX_SYS_NIRQ,
+		.irq = 7 + OMAP_INTC_START,
 		.platform_data = &n8x0_menelaus_platform_data,
 	},
 };
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index 6202fc7..a08bebc 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -33,18 +33,16 @@
 #include <linux/regulator/machine.h>
 #include <linux/i2c/twl.h>
 
-#include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/flash.h>
 
-#include <plat/board.h>
 #include "common.h"
 #include <video/omapdss.h>
 #include <video/omap-panel-tfp410.h>
 #include <plat/gpmc.h>
-#include <plat/nand.h>
+#include <linux/platform_data/mtd-nand-omap2.h>
 #include <plat/usb.h>
 #include <plat/omap_device.h>
 
@@ -297,9 +295,6 @@ static int beagle_twl_gpio_setup(struct device *dev,
 }
 
 static struct twl4030_gpio_platform_data beagle_gpio_data = {
-	.gpio_base	= OMAP_MAX_GPIO_LINES,
-	.irq_base	= TWL4030_GPIO_IRQ_BASE,
-	.irq_end	= TWL4030_GPIO_IRQ_END,
 	.use_leds	= true,
 	.pullups	= BIT(1),
 	.pulldowns	= BIT(2) | BIT(6) | BIT(7) | BIT(8) | BIT(13)
@@ -519,6 +514,7 @@ static void __init omap3_beagle_init(void)
 	usbhs_init(&usbhs_bdata);
 	omap_nand_flash_init(NAND_BUSWIDTH_16, omap3beagle_nand_partitions,
 			     ARRAY_SIZE(omap3beagle_nand_partitions));
+	omap_twl4030_audio_init("omap3beagle");
 
 	/* Ensure msecure is mux'd to be able to set the RTC. */
 	omap_mux_init_signal("sys_drm_msecure", OMAP_PIN_OFF_OUTPUT_HIGH);
diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c
index 0d362e9..a3959de 100644
--- a/arch/arm/mach-omap2/board-omap3evm.c
+++ b/arch/arm/mach-omap2/board-omap3evm.c
@@ -32,6 +32,7 @@
 #include <linux/spi/ads7846.h>
 #include <linux/i2c/twl.h>
 #include <linux/usb/otg.h>
+#include <linux/usb/nop-usb-xceiv.h>
 #include <linux/smsc911x.h>
 
 #include <linux/wl12xx.h>
@@ -40,16 +41,14 @@
 #include <linux/mmc/host.h>
 #include <linux/export.h>
 
-#include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include <plat/board.h>
 #include <plat/usb.h>
-#include <plat/nand.h>
+#include <linux/platform_data/mtd-nand-omap2.h>
 #include "common.h"
-#include <plat/mcspi.h>
+#include <linux/platform_data/spi-omap2-mcspi.h>
 #include <video/omapdss.h>
 #include <video/omap-panel-tfp410.h>
 
@@ -75,6 +74,18 @@
 #define OMAP3EVM_GEN1_ETHR_GPIO_RST	64
 #define OMAP3EVM_GEN2_ETHR_GPIO_RST	7
 
+/*
+ * OMAP35x EVM revision
+ * Run time detection of EVM revision is done by reading Ethernet
+ * PHY ID -
+ *	GEN_1	= 0x01150000
+ *	GEN_2	= 0x92200000
+ */
+enum {
+	OMAP3EVM_BOARD_GEN_1 = 0,	/* EVM Rev between  A - D */
+	OMAP3EVM_BOARD_GEN_2,		/* EVM Rev >= Rev E */
+};
+
 static u8 omap3_evm_version;
 
 u8 get_omap3_evm_rev(void)
@@ -108,7 +119,7 @@ static void __init omap3_evm_get_revision(void)
 }
 
 #if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)
-#include <plat/gpmc-smsc911x.h>
+#include "gpmc-smsc911x.h"
 
 static struct omap_smsc911x_platform_data smsc911x_cfg = {
 	.cs             = OMAP3EVM_SMSC911X_CS,
@@ -377,9 +388,6 @@ static int omap3evm_twl_gpio_setup(struct device *dev,
 }
 
 static struct twl4030_gpio_platform_data omap3evm_gpio_data = {
-	.gpio_base	= OMAP_MAX_GPIO_LINES,
-	.irq_base	= TWL4030_GPIO_IRQ_BASE,
-	.irq_end	= TWL4030_GPIO_IRQ_END,
 	.use_leds	= true,
 	.setup		= omap3evm_twl_gpio_setup,
 };
@@ -526,9 +534,6 @@ static int __init omap3_evm_i2c_init(void)
 	return 0;
 }
 
-static struct omap_board_config_kernel omap3_evm_config[] __initdata = {
-};
-
 static struct usbhs_omap_board_data usbhs_bdata __initdata = {
 
 	.port_mode[0] = OMAP_USBHS_PORT_MODE_UNUSED,
@@ -688,9 +693,6 @@ static void __init omap3_evm_init(void)
 	obm = (cpu_is_omap3630()) ? omap36x_board_mux : omap35x_board_mux;
 	omap3_mux_init(obm, OMAP_PACKAGE_CBB);
 
-	omap_board_config = omap3_evm_config;
-	omap_board_config_size = ARRAY_SIZE(omap3_evm_config);
-
 	omap_mux_init_gpio(63, OMAP_PIN_INPUT);
 	omap_hsmmc_init(mmc);
 
@@ -737,6 +739,7 @@ static void __init omap3_evm_init(void)
 	omap3evm_init_smsc911x();
 	omap3_evm_display_init();
 	omap3_evm_wl12xx_init();
+	omap_twl4030_audio_init("omap3evm");
 }
 
 MACHINE_START(OMAP3EVM, "OMAP3 EVM")
diff --git a/arch/arm/mach-omap2/board-omap3logic.c b/arch/arm/mach-omap2/board-omap3logic.c
index fca93d1..7bd8253 100644
--- a/arch/arm/mach-omap2/board-omap3logic.c
+++ b/arch/arm/mach-omap2/board-omap3logic.c
@@ -30,24 +30,21 @@
 #include <linux/i2c/twl.h>
 #include <linux/mmc/host.h>
 
-#include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
+#include "gpmc-smsc911x.h"
+#include <plat/gpmc.h>
+#include <plat/sdrc.h>
+#include <plat/usb.h>
+
+#include "common.h"
 #include "mux.h"
 #include "hsmmc.h"
 #include "control.h"
 #include "common-board-devices.h"
 
-#include <plat/mux.h>
-#include <plat/board.h>
-#include "common.h"
-#include <plat/gpmc-smsc911x.h>
-#include <plat/gpmc.h>
-#include <plat/sdrc.h>
-#include <plat/usb.h>
-
 #define OMAP3LOGIC_SMSC911X_CS			1
 
 #define OMAP3530_LV_SOM_MMC_GPIO_CD		110
@@ -78,9 +75,6 @@ static struct regulator_init_data omap3logic_vmmc1 = {
 };
 
 static struct twl4030_gpio_platform_data omap3logic_gpio_data = {
-	.gpio_base	= OMAP_MAX_GPIO_LINES,
-	.irq_base	= TWL4030_GPIO_IRQ_BASE,
-	.irq_end	= TWL4030_GPIO_IRQ_END,
 	.use_leds	= true,
 	.pullups	= BIT(1),
 	.pulldowns	= BIT(2)  | BIT(6)  | BIT(7)  | BIT(8)
diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c
index 57aebee..00a1f4a 100644
--- a/arch/arm/mach-omap2/board-omap3pandora.c
+++ b/arch/arm/mach-omap2/board-omap3pandora.c
@@ -35,18 +35,16 @@
 #include <linux/mmc/host.h>
 #include <linux/mmc/card.h>
 #include <linux/regulator/fixed.h>
+#include <linux/platform_data/spi-omap2-mcspi.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include <plat/board.h>
 #include "common.h"
-#include <mach/hardware.h>
-#include <plat/mcspi.h>
 #include <plat/usb.h>
 #include <video/omapdss.h>
-#include <plat/nand.h>
+#include <linux/platform_data/mtd-nand-omap2.h>
 
 #include "mux.h"
 #include "sdram-micron-mt46h32m32lf-6.h"
@@ -321,9 +319,6 @@ static int omap3pandora_twl_gpio_setup(struct device *dev,
 }
 
 static struct twl4030_gpio_platform_data omap3pandora_gpio_data = {
-	.gpio_base	= OMAP_MAX_GPIO_LINES,
-	.irq_base	= TWL4030_GPIO_IRQ_BASE,
-	.irq_end	= TWL4030_GPIO_IRQ_END,
 	.setup		= omap3pandora_twl_gpio_setup,
 };
 
diff --git a/arch/arm/mach-omap2/board-omap3stalker.c b/arch/arm/mach-omap2/board-omap3stalker.c
index b318f56..c7f3d02 100644
--- a/arch/arm/mach-omap2/board-omap3stalker.c
+++ b/arch/arm/mach-omap2/board-omap3stalker.c
@@ -28,23 +28,26 @@
 #include <linux/regulator/machine.h>
 #include <linux/i2c/twl.h>
 #include <linux/mmc/host.h>
+#include <linux/input/matrix_keypad.h>
+#include <linux/spi/spi.h>
+#include <linux/interrupt.h>
+#include <linux/smsc911x.h>
+#include <linux/i2c/at24.h>
 
-#include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/flash.h>
 
-#include <plat/board.h>
 #include "common.h"
 #include <plat/gpmc.h>
-#include <plat/nand.h>
+#include <linux/platform_data/mtd-nand-omap2.h>
 #include <plat/usb.h>
 #include <video/omapdss.h>
 #include <video/omap-panel-generic-dpi.h>
 #include <video/omap-panel-tfp410.h>
 
-#include <plat/mcspi.h>
+#include <linux/platform_data/spi-omap2-mcspi.h>
 #include <linux/input/matrix_keypad.h>
 #include <linux/spi/spi.h>
 #include <linux/interrupt.h>
@@ -57,7 +60,7 @@
 #include "common-board-devices.h"
 
 #if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)
-#include <plat/gpmc-smsc911x.h>
+#include "gpmc-smsc911x.h"
 
 #define OMAP3STALKER_ETHR_START	0x2c000000
 #define OMAP3STALKER_ETHR_SIZE	1024
@@ -279,9 +282,6 @@ omap3stalker_twl_gpio_setup(struct device *dev,
 }
 
 static struct twl4030_gpio_platform_data omap3stalker_gpio_data = {
-	.gpio_base	= OMAP_MAX_GPIO_LINES,
-	.irq_base	= TWL4030_GPIO_IRQ_BASE,
-	.irq_end	= TWL4030_GPIO_IRQ_END,
 	.use_leds	= true,
 	.setup		= omap3stalker_twl_gpio_setup,
 };
@@ -362,9 +362,6 @@ static int __init omap3_stalker_i2c_init(void)
 
 #define OMAP3_STALKER_TS_GPIO	175
 
-static struct omap_board_config_kernel omap3_stalker_config[] __initdata = {
-};
-
 static struct platform_device *omap3_stalker_devices[] __initdata = {
 	&keys_gpio,
 };
@@ -399,8 +396,6 @@ static void __init omap3_stalker_init(void)
 {
 	regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CUS);
-	omap_board_config = omap3_stalker_config;
-	omap_board_config_size = ARRAY_SIZE(omap3_stalker_config);
 
 	omap_mux_init_gpio(23, OMAP_PIN_INPUT);
 	omap_hsmmc_init(mmc);
diff --git a/arch/arm/mach-omap2/board-omap3touchbook.c b/arch/arm/mach-omap2/board-omap3touchbook.c
index 485d14d..944ffc4 100644
--- a/arch/arm/mach-omap2/board-omap3touchbook.c
+++ b/arch/arm/mach-omap2/board-omap3touchbook.c
@@ -29,7 +29,7 @@
 #include <linux/mtd/nand.h>
 #include <linux/mmc/host.h>
 
-#include <plat/mcspi.h>
+#include <linux/platform_data/spi-omap2-mcspi.h>
 #include <linux/spi/spi.h>
 
 #include <linux/spi/ads7846.h>
@@ -37,17 +37,15 @@
 #include <linux/regulator/machine.h>
 #include <linux/i2c/twl.h>
 
-#include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/flash.h>
 #include <asm/system_info.h>
 
-#include <plat/board.h>
 #include "common.h"
 #include <plat/gpmc.h>
-#include <plat/nand.h>
+#include <linux/platform_data/mtd-nand-omap2.h>
 #include <plat/usb.h>
 
 #include "mux.h"
@@ -139,9 +137,6 @@ static int touchbook_twl_gpio_setup(struct device *dev,
 }
 
 static struct twl4030_gpio_platform_data touchbook_gpio_data = {
-	.gpio_base	= OMAP_MAX_GPIO_LINES,
-	.irq_base	= TWL4030_GPIO_IRQ_BASE,
-	.irq_end	= TWL4030_GPIO_IRQ_END,
 	.use_leds	= true,
 	.pullups	= BIT(1),
 	.pulldowns	= BIT(2) | BIT(6) | BIT(7) | BIT(8) | BIT(13)
diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c
index 70f6d1d..57d217a 100644
--- a/arch/arm/mach-omap2/board-omap4panda.c
+++ b/arch/arm/mach-omap2/board-omap4panda.c
@@ -32,19 +32,18 @@
 #include <linux/wl12xx.h>
 #include <linux/platform_data/omap-abe-twl6040.h>
 
-#include <mach/hardware.h>
 #include <asm/hardware/gic.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <video/omapdss.h>
 
-#include <plat/board.h>
 #include "common.h"
 #include <plat/usb.h>
 #include <plat/mmc.h>
 #include <video/omap-panel-tfp410.h>
 
+#include "soc.h"
 #include "hsmmc.h"
 #include "control.h"
 #include "mux.h"
@@ -263,7 +262,6 @@ static struct twl6040_codec_data twl6040_codec = {
 static struct twl6040_platform_data twl6040_data = {
 	.codec		= &twl6040_codec,
 	.audpwron_gpio	= 127,
-	.irq_base	= TWL6040_CODEC_IRQ_BASE,
 };
 
 /* Panda board uses the common PMIC configuration */
@@ -294,7 +292,7 @@ static int __init omap4_panda_i2c_init(void)
 			TWL_COMMON_REGULATOR_V1V8 |
 			TWL_COMMON_REGULATOR_V2V1);
 	omap4_pmic_init("twl6030", &omap4_panda_twldata,
-			&twl6040_data, OMAP44XX_IRQ_SYS_2N);
+			&twl6040_data, 119 + OMAP44XX_IRQ_GIC_START);
 	omap_register_i2c_bus(2, 400, NULL, 0);
 	/*
 	 * Bus 3 is attached to the DVI port where devices like the pico DLP
@@ -408,30 +406,9 @@ static struct omap_dss_device omap4_panda_dvi_device = {
 	.channel		= OMAP_DSS_CHANNEL_LCD2,
 };
 
-static struct gpio panda_hdmi_gpios[] = {
-	{ HDMI_GPIO_CT_CP_HPD, GPIOF_OUT_INIT_HIGH, "hdmi_gpio_ct_cp_hpd" },
-	{ HDMI_GPIO_LS_OE,	GPIOF_OUT_INIT_HIGH, "hdmi_gpio_ls_oe" },
-	{ HDMI_GPIO_HPD, GPIOF_DIR_IN, "hdmi_gpio_hpd" },
-};
-
-static int omap4_panda_panel_enable_hdmi(struct omap_dss_device *dssdev)
-{
-	int status;
-
-	status = gpio_request_array(panda_hdmi_gpios,
-				    ARRAY_SIZE(panda_hdmi_gpios));
-	if (status)
-		pr_err("Cannot request HDMI GPIOs\n");
-
-	return status;
-}
-
-static void omap4_panda_panel_disable_hdmi(struct omap_dss_device *dssdev)
-{
-	gpio_free_array(panda_hdmi_gpios, ARRAY_SIZE(panda_hdmi_gpios));
-}
-
 static struct omap_dss_hdmi_data omap4_panda_hdmi_data = {
+	.ct_cp_hpd_gpio = HDMI_GPIO_CT_CP_HPD,
+	.ls_oe_gpio = HDMI_GPIO_LS_OE,
 	.hpd_gpio = HDMI_GPIO_HPD,
 };
 
@@ -439,8 +416,6 @@ static struct omap_dss_device  omap4_panda_hdmi_device = {
 	.name = "hdmi",
 	.driver_name = "hdmi_panel",
 	.type = OMAP_DISPLAY_TYPE_HDMI,
-	.platform_enable = omap4_panda_panel_enable_hdmi,
-	.platform_disable = omap4_panda_panel_disable_hdmi,
 	.channel = OMAP_DSS_CHANNEL_DIGIT,
 	.data = &omap4_panda_hdmi_data,
 };
@@ -518,6 +493,7 @@ static void __init omap4_panda_init(void)
 MACHINE_START(OMAP4_PANDA, "OMAP4 Panda board")
 	/* Maintainer: David Anders - Texas Instruments Inc */
 	.atag_offset	= 0x100,
+	.smp		= smp_ops(omap4_smp_ops),
 	.reserve	= omap_reserve,
 	.map_io		= omap4_map_io,
 	.init_early	= omap4430_init_early,
diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
index 779734d..b700685 100644
--- a/arch/arm/mach-omap2/board-overo.c
+++ b/arch/arm/mach-omap2/board-overo.c
@@ -37,21 +37,19 @@
 #include <linux/mtd/partitions.h>
 #include <linux/mmc/host.h>
 
+#include <linux/platform_data/mtd-nand-omap2.h>
+#include <linux/platform_data/spi-omap2-mcspi.h>
+
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/flash.h>
 #include <asm/mach/map.h>
 
-#include <plat/board.h>
 #include "common.h"
 #include <video/omapdss.h>
 #include <video/omap-panel-generic-dpi.h>
 #include <video/omap-panel-tfp410.h>
 #include <plat/gpmc.h>
-#include <mach/hardware.h>
-#include <plat/nand.h>
-#include <plat/mcspi.h>
-#include <plat/mux.h>
 #include <plat/usb.h>
 
 #include "mux.h"
@@ -116,7 +114,7 @@ static inline void __init overo_ads7846_init(void) { return; }
 #if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)
 
 #include <linux/smsc911x.h>
-#include <plat/gpmc-smsc911x.h>
+#include "gpmc-smsc911x.h"
 
 static struct omap_smsc911x_platform_data smsc911x_cfg = {
 	.id		= 0,
@@ -399,9 +397,6 @@ static int overo_twl_gpio_setup(struct device *dev,
 }
 
 static struct twl4030_gpio_platform_data overo_gpio_data = {
-	.gpio_base	= OMAP_MAX_GPIO_LINES,
-	.irq_base	= TWL4030_GPIO_IRQ_BASE,
-	.irq_end	= TWL4030_GPIO_IRQ_END,
 	.use_leds	= true,
 	.setup		= overo_twl_gpio_setup,
 };
@@ -509,6 +504,7 @@ static void __init overo_init(void)
 	overo_display_init();
 	overo_init_led();
 	overo_init_keys();
+	omap_twl4030_audio_init("overo");
 
 	/* Ensure SDRC pins are mux'd for self-refresh */
 	omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT);
@@ -522,8 +518,7 @@ static void __init overo_init(void)
 		udelay(10);
 		gpio_set_value(OVERO_GPIO_W2W_NRESET, 1);
 	} else {
-		printk(KERN_ERR "could not obtain gpio for "
-					"OVERO_GPIO_W2W_NRESET\n");
+		pr_err("could not obtain gpio for OVERO_GPIO_W2W_NRESET\n");
 	}
 
 	ret = gpio_request_array(overo_bt_gpios, ARRAY_SIZE(overo_bt_gpios));
@@ -542,8 +537,7 @@ static void __init overo_init(void)
 	if (ret == 0)
 		gpio_export(OVERO_GPIO_USBH_CPEN, 0);
 	else
-		printk(KERN_ERR "could not obtain gpio for "
-					"OVERO_GPIO_USBH_CPEN\n");
+		pr_err("could not obtain gpio for OVERO_GPIO_USBH_CPEN\n");
 }
 
 MACHINE_START(OVERO, "Gumstix Overo")
diff --git a/arch/arm/mach-omap2/board-rm680.c b/arch/arm/mach-omap2/board-rm680.c
index 0ad1bb3b..45997bf 100644
--- a/arch/arm/mach-omap2/board-rm680.c
+++ b/arch/arm/mach-omap2/board-rm680.c
@@ -17,6 +17,7 @@
 #include <linux/regulator/fixed.h>
 #include <linux/regulator/machine.h>
 #include <linux/regulator/consumer.h>
+#include <linux/platform_data/mtd-onenand-omap2.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
@@ -26,7 +27,7 @@
 #include <plat/usb.h>
 #include <plat/gpmc.h>
 #include "common.h"
-#include <plat/onenand.h>
+#include <plat/serial.h>
 
 #include "mux.h"
 #include "hsmmc.h"
@@ -72,9 +73,6 @@ static struct platform_device *rm680_peripherals_devices[] __initdata = {
 
 /* TWL */
 static struct twl4030_gpio_platform_data rm680_gpio_data = {
-	.gpio_base		= OMAP_MAX_GPIO_LINES,
-	.irq_base		= TWL4030_GPIO_IRQ_BASE,
-	.irq_end		= TWL4030_GPIO_IRQ_END,
 	.pullups		= BIT(0),
 	.pulldowns		= BIT(1) | BIT(2) | BIT(8) | BIT(15),
 };
@@ -87,7 +85,7 @@ static struct twl4030_platform_data rm680_twl_data = {
 static void __init rm680_i2c_init(void)
 {
 	omap3_pmic_get_config(&rm680_twl_data, TWL_COMMON_PDATA_USB, 0);
-	omap_pmic_init(1, 2900, "twl5031", INT_34XX_SYS_NIRQ, &rm680_twl_data);
+	omap_pmic_init(1, 2900, "twl5031", 7 + OMAP_INTC_START, &rm680_twl_data);
 	omap_register_i2c_bus(2, 400, NULL, 0);
 	omap_register_i2c_bus(3, 400, NULL, 0);
 }
diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c
index df2534d..ed85fb8 100644
--- a/arch/arm/mach-omap2/board-rx51-peripherals.c
+++ b/arch/arm/mach-omap2/board-rx51-peripherals.c
@@ -25,17 +25,18 @@
 #include <linux/gpio_keys.h>
 #include <linux/mmc/host.h>
 #include <linux/power/isp1704_charger.h>
+#include <linux/platform_data/spi-omap2-mcspi.h>
+#include <linux/platform_data/mtd-onenand-omap2.h>
+
 #include <asm/system_info.h>
 
-#include <plat/mcspi.h>
-#include <plat/board.h>
 #include "common.h"
 #include <plat/dma.h>
 #include <plat/gpmc.h>
-#include <plat/onenand.h>
-#include <plat/gpmc-smc91x.h>
+#include <plat/omap-pm.h>
+#include "gpmc-smc91x.h"
 
-#include <mach/board-rx51.h>
+#include "board-rx51.h"
 
 #include <sound/tlv320aic3x.h>
 #include <sound/tpa6130a2-plat.h>
@@ -46,6 +47,10 @@
 #include <../drivers/staging/iio/light/tsl2563.h>
 #include <linux/lis3lv02d.h>
 
+#if defined(CONFIG_IR_RX51) || defined(CONFIG_IR_RX51_MODULE)
+#include <media/ir-rx51.h>
+#endif
+
 #include "mux.h"
 #include "hsmmc.h"
 #include "common-board-devices.h"
@@ -774,9 +779,6 @@ static int rx51_twlgpio_setup(struct device *dev, unsigned gpio, unsigned n)
 }
 
 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)
@@ -1051,7 +1053,7 @@ static int __init rx51_i2c_init(void)
 	rx51_twldata.vdac->constraints.apply_uV = true;
 	rx51_twldata.vdac->constraints.name = "VDAC";
 
-	omap_pmic_init(1, 2200, "twl5030", INT_34XX_SYS_NIRQ, &rx51_twldata);
+	omap_pmic_init(1, 2200, "twl5030", 7 + OMAP_INTC_START, &rx51_twldata);
 	omap_register_i2c_bus(2, 100, rx51_peripherals_i2c_board_info_2,
 			      ARRAY_SIZE(rx51_peripherals_i2c_board_info_2));
 #if defined(CONFIG_SENSORS_LIS3_I2C) || defined(CONFIG_SENSORS_LIS3_I2C_MODULE)
@@ -1220,6 +1222,30 @@ static void __init rx51_init_tsc2005(void)
 				gpio_to_irq(RX51_TSC2005_IRQ_GPIO);
 }
 
+#if defined(CONFIG_IR_RX51) || defined(CONFIG_IR_RX51_MODULE)
+static struct lirc_rx51_platform_data rx51_lirc_data = {
+	.set_max_mpu_wakeup_lat = omap_pm_set_max_mpu_wakeup_lat,
+	.pwm_timer = 9, /* Use GPT 9 for CIR */
+};
+
+static struct platform_device rx51_lirc_device = {
+	.name           = "lirc_rx51",
+	.id             = -1,
+	.dev            = {
+		.platform_data = &rx51_lirc_data,
+	},
+};
+
+static void __init rx51_init_lirc(void)
+{
+	platform_device_register(&rx51_lirc_device);
+}
+#else
+static void __init rx51_init_lirc(void)
+{
+}
+#endif
+
 void __init rx51_peripherals_init(void)
 {
 	rx51_i2c_init();
@@ -1230,6 +1256,7 @@ void __init rx51_peripherals_init(void)
 	rx51_init_wl1251();
 	rx51_init_tsc2005();
 	rx51_init_si4713();
+	rx51_init_lirc();
 	spi_register_board_info(rx51_peripherals_spi_board_info,
 				ARRAY_SIZE(rx51_peripherals_spi_board_info));
 
diff --git a/arch/arm/mach-omap2/board-rx51-video.c b/arch/arm/mach-omap2/board-rx51-video.c
index 2c1289b..c22e111 100644
--- a/arch/arm/mach-omap2/board-rx51-video.c
+++ b/arch/arm/mach-omap2/board-rx51-video.c
@@ -17,9 +17,9 @@
 #include <asm/mach-types.h>
 #include <video/omapdss.h>
 #include <plat/vram.h>
-#include <plat/mcspi.h>
+#include <linux/platform_data/spi-omap2-mcspi.h>
 
-#include <mach/board-rx51.h>
+#include "board-rx51.h"
 
 #include "mux.h"
 
diff --git a/arch/arm/mach-omap2/board-rx51.c b/arch/arm/mach-omap2/board-rx51.c
index 345dd93..7bbb05d 100644
--- a/arch/arm/mach-omap2/board-rx51.c
+++ b/arch/arm/mach-omap2/board-rx51.c
@@ -17,14 +17,12 @@
 #include <linux/io.h>
 #include <linux/gpio.h>
 #include <linux/leds.h>
+#include <linux/platform_data/spi-omap2-mcspi.h>
 
-#include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include <plat/mcspi.h>
-#include <plat/board.h>
 #include "common.h"
 #include <plat/dma.h>
 #include <plat/gpmc.h>
diff --git a/arch/arm/mach-omap2/board-rx51.h b/arch/arm/mach-omap2/board-rx51.h
new file mode 100644
index 0000000..b76f49e
--- /dev/null
+++ b/arch/arm/mach-omap2/board-rx51.h
@@ -0,0 +1,11 @@
+/*
+ * Defines for rx51 boards
+ */
+
+#ifndef _OMAP_BOARD_RX51_H
+#define _OMAP_BOARD_RX51_H
+
+extern void __init rx51_peripherals_init(void);
+extern void __init rx51_video_mem_init(void);
+
+#endif
diff --git a/arch/arm/mach-omap2/board-ti8168evm.c b/arch/arm/mach-omap2/board-ti8168evm.c
index d4c8392..c4f8833 100644
--- a/arch/arm/mach-omap2/board-ti8168evm.c
+++ b/arch/arm/mach-omap2/board-ti8168evm.c
@@ -15,13 +15,10 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 
-#include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include <plat/irqs.h>
-#include <plat/board.h>
 #include "common.h"
 #include <plat/usb.h>
 
@@ -32,15 +29,10 @@ static struct omap_musb_board_data musb_board_data = {
 	.power		= 500,
 };
 
-static struct omap_board_config_kernel ti81xx_evm_config[] __initdata = {
-};
-
 static void __init ti81xx_evm_init(void)
 {
 	omap_serial_init();
 	omap_sdrc_init(NULL, NULL);
-	omap_board_config = ti81xx_evm_config;
-	omap_board_config_size = ARRAY_SIZE(ti81xx_evm_config);
 	usb_musb_init(&musb_board_data);
 }
 
diff --git a/arch/arm/mach-omap2/board-zoom-debugboard.c b/arch/arm/mach-omap2/board-zoom-debugboard.c
index f64f441..afb2278 100644
--- a/arch/arm/mach-omap2/board-zoom-debugboard.c
+++ b/arch/arm/mach-omap2/board-zoom-debugboard.c
@@ -18,10 +18,13 @@
 #include <linux/regulator/machine.h>
 
 #include <plat/gpmc.h>
-#include <plat/gpmc-smsc911x.h>
+#include "gpmc-smsc911x.h"
 
 #include <mach/board-zoom.h>
 
+#include "soc.h"
+#include "common.h"
+
 #define ZOOM_SMSC911X_CS	7
 #define ZOOM_SMSC911X_GPIO	158
 #define ZOOM_QUADUART_CS	3
@@ -81,8 +84,7 @@ static inline void __init zoom_init_quaduart(void)
 	quart_cs = ZOOM_QUADUART_CS;
 
 	if (gpmc_cs_request(quart_cs, SZ_1M, &cs_mem_base) < 0) {
-		printk(KERN_ERR "Failed to request GPMC mem"
-				"for Quad UART(TL16CP754C)\n");
+		pr_err("Failed to request GPMC mem for Quad UART(TL16CP754C)\n");
 		return;
 	}
 
@@ -104,8 +106,8 @@ static inline int omap_zoom_debugboard_detect(void)
 
 	if (gpio_request_one(debug_board_detect, GPIOF_IN,
 			     "Zoom debug board detect") < 0) {
-		printk(KERN_ERR "Failed to request GPIO%d for Zoom debug"
-		"board detect\n", debug_board_detect);
+		pr_err("Failed to request GPIO%d for Zoom debug board detect\n",
+		       debug_board_detect);
 		return 0;
 	}
 
diff --git a/arch/arm/mach-omap2/board-zoom-display.c b/arch/arm/mach-omap2/board-zoom-display.c
index 28187f1..b940ab2 100644
--- a/arch/arm/mach-omap2/board-zoom-display.c
+++ b/arch/arm/mach-omap2/board-zoom-display.c
@@ -14,10 +14,12 @@
 #include <linux/gpio.h>
 #include <linux/i2c/twl.h>
 #include <linux/spi/spi.h>
-#include <plat/mcspi.h>
+#include <linux/platform_data/spi-omap2-mcspi.h>
 #include <video/omapdss.h>
 #include <mach/board-zoom.h>
 
+#include "common.h"
+
 #define LCD_PANEL_RESET_GPIO_PROD	96
 #define LCD_PANEL_RESET_GPIO_PILOT	55
 #define LCD_PANEL_QVGA_GPIO		56
diff --git a/arch/arm/mach-omap2/board-zoom-peripherals.c b/arch/arm/mach-omap2/board-zoom-peripherals.c
index b797cb2..67f8540 100644
--- a/arch/arm/mach-omap2/board-zoom-peripherals.c
+++ b/arch/arm/mach-omap2/board-zoom-peripherals.c
@@ -19,6 +19,7 @@
 #include <linux/regulator/fixed.h>
 #include <linux/wl12xx.h>
 #include <linux/mmc/host.h>
+#include <linux/platform_data/gpio-omap.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -34,6 +35,7 @@
 #include "common-board-devices.h"
 
 #define OMAP_ZOOM_WLAN_PMENA_GPIO	(101)
+#define ZOOM2_HEADSET_EXTMUTE_GPIO	(153)
 #define OMAP_ZOOM_WLAN_IRQ_GPIO		(162)
 
 #define LCD_PANEL_ENABLE_GPIO		(7 + OMAP_MAX_GPIO_LINES)
@@ -244,16 +246,7 @@ static int zoom_twl_gpio_setup(struct device *dev,
 	return ret;
 }
 
-/* EXTMUTE callback function */
-static void zoom2_set_hs_extmute(int mute)
-{
-	gpio_set_value(ZOOM2_HEADSET_EXTMUTE_GPIO, mute);
-}
-
 static struct twl4030_gpio_platform_data zoom_gpio_data = {
-	.gpio_base	= OMAP_MAX_GPIO_LINES,
-	.irq_base	= TWL4030_GPIO_IRQ_BASE,
-	.irq_end	= TWL4030_GPIO_IRQ_END,
 	.setup		= zoom_twl_gpio_setup,
 };
 
@@ -279,9 +272,9 @@ static int __init omap_i2c_init(void)
 
 		codec_data->ramp_delay_value = 3;	/* 161 ms */
 		codec_data->hs_extmute = 1;
-		codec_data->set_hs_extmute = zoom2_set_hs_extmute;
+		codec_data->hs_extmute_gpio = ZOOM2_HEADSET_EXTMUTE_GPIO;
 	}
-	omap_pmic_init(1, 2400, "twl5030", INT_34XX_SYS_NIRQ, &zoom_twldata);
+	omap_pmic_init(1, 2400, "twl5030", 7 + OMAP_INTC_START, &zoom_twldata);
 	omap_register_i2c_bus(2, 400, NULL, 0);
 	omap_register_i2c_bus(3, 400, NULL, 0);
 	return 0;
diff --git a/arch/arm/mach-omap2/board-zoom.c b/arch/arm/mach-omap2/board-zoom.c
index 4e7e561..4994438 100644
--- a/arch/arm/mach-omap2/board-zoom.c
+++ b/arch/arm/mach-omap2/board-zoom.c
@@ -22,7 +22,6 @@
 #include <asm/mach/arch.h>
 
 #include "common.h"
-#include <plat/board.h>
 #include <plat/usb.h>
 
 #include <mach/board-zoom.h>
diff --git a/arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c b/arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c
index 3d9d746..cabcfdb 100644
--- a/arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c
+++ b/arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c
@@ -33,11 +33,11 @@
 #include <linux/cpufreq.h>
 #include <linux/slab.h>
 
-#include <plat/cpu.h>
 #include <plat/clock.h>
 #include <plat/sram.h>
 #include <plat/sdrc.h>
 
+#include "soc.h"
 #include "clock.h"
 #include "clock2xxx.h"
 #include "opp2xxx.h"
diff --git a/arch/arm/mach-omap2/clkt34xx_dpll3m2.c b/arch/arm/mach-omap2/clkt34xx_dpll3m2.c
index d6e34dd..298887b 100644
--- a/arch/arm/mach-omap2/clkt34xx_dpll3m2.c
+++ b/arch/arm/mach-omap2/clkt34xx_dpll3m2.c
@@ -92,15 +92,13 @@ int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate)
 
 	pr_debug("clock: changing CORE DPLL rate from %lu to %lu\n", clk->rate,
 		 validrate);
-	pr_debug("clock: SDRC CS0 timing params used:"
-		 " RFR %08x CTRLA %08x CTRLB %08x MR %08x\n",
+	pr_debug("clock: SDRC CS0 timing params used: RFR %08x CTRLA %08x CTRLB %08x MR %08x\n",
 		 sdrc_cs0->rfr_ctrl, sdrc_cs0->actim_ctrla,
 		 sdrc_cs0->actim_ctrlb, sdrc_cs0->mr);
 	if (sdrc_cs1)
-		pr_debug("clock: SDRC CS1 timing params used: "
-		 " RFR %08x CTRLA %08x CTRLB %08x MR %08x\n",
-		 sdrc_cs1->rfr_ctrl, sdrc_cs1->actim_ctrla,
-		 sdrc_cs1->actim_ctrlb, sdrc_cs1->mr);
+		pr_debug("clock: SDRC CS1 timing params used: RFR %08x CTRLA %08x CTRLB %08x MR %08x\n",
+			 sdrc_cs1->rfr_ctrl, sdrc_cs1->actim_ctrla,
+			 sdrc_cs1->actim_ctrlb, sdrc_cs1->mr);
 
 	if (sdrc_cs1)
 		omap3_configure_core_dpll(
diff --git a/arch/arm/mach-omap2/clkt_clksel.c b/arch/arm/mach-omap2/clkt_clksel.c
index 04d551b..19a9809 100644
--- a/arch/arm/mach-omap2/clkt_clksel.c
+++ b/arch/arm/mach-omap2/clkt_clksel.c
@@ -71,8 +71,8 @@ static const struct clksel *_get_clksel_by_parent(struct clk *clk,
 
 	if (!clks->parent) {
 		/* This indicates a data problem */
-		WARN(1, "clock: Could not find parent clock %s in clksel array "
-		     "of clock %s\n", src_clk->name, clk->name);
+		WARN(1, "clock: %s: could not find parent clock %s in clksel array\n",
+		     clk->name, src_clk->name);
 		return NULL;
 	}
 
@@ -126,8 +126,8 @@ static u8 _get_div_and_fieldval(struct clk *src_clk, struct clk *clk,
 
 	if (max_div == 0) {
 		/* This indicates an error in the clksel data */
-		WARN(1, "clock: Could not find divisor for clock %s parent %s"
-		     "\n", clk->name, src_clk->parent->name);
+		WARN(1, "clock: %s: could not find divisor for parent %s\n",
+		     clk->name, src_clk->parent->name);
 		return 0;
 	}
 
@@ -191,8 +191,8 @@ static u32 _clksel_to_divisor(struct clk *clk, u32 field_val)
 
 	if (!clkr->div) {
 		/* This indicates a data error */
-		WARN(1, "clock: Could not find fieldval %d for clock %s parent "
-		     "%s\n", field_val, clk->name, clk->parent->name);
+		WARN(1, "clock: %s: could not find fieldval %d parent %s\n",
+		     clk->name, field_val, clk->parent->name);
 		return 0;
 	}
 
@@ -230,8 +230,8 @@ static u32 _divisor_to_clksel(struct clk *clk, u32 div)
 	}
 
 	if (!clkr->div) {
-		pr_err("clock: Could not find divisor %d for clock %s parent "
-		       "%s\n", div, clk->name, clk->parent->name);
+		pr_err("clock: %s: could not find divisor %d parent %s\n",
+		       clk->name, div, clk->parent->name);
 		return ~0;
 	}
 
@@ -300,8 +300,8 @@ u32 omap2_clksel_round_rate_div(struct clk *clk, unsigned long target_rate,
 
 		/* Sanity check */
 		if (clkr->div <= last_div)
-			pr_err("clock: clksel_rate table not sorted "
-			       "for clock %s", clk->name);
+			pr_err("clock: %s: clksel_rate table not sorted",
+			       clk->name);
 
 		last_div = clkr->div;
 
@@ -312,9 +312,8 @@ u32 omap2_clksel_round_rate_div(struct clk *clk, unsigned long target_rate,
 	}
 
 	if (!clkr->div) {
-		pr_err("clock: Could not find divisor for target "
-		       "rate %ld for clock %s parent %s\n", target_rate,
-		       clk->name, clk->parent->name);
+		pr_err("clock: %s: could not find divisor for target rate %ld parent %s\n",
+		       clk->name, target_rate, clk->parent->name);
 		return ~0;
 	}
 
@@ -359,8 +358,7 @@ void omap2_init_clksel_parent(struct clk *clk)
 
 			if (clkr->val == r) {
 				if (clk->parent != clks->parent) {
-					pr_debug("clock: inited %s parent "
-						 "to %s (was %s)\n",
+					pr_debug("clock: %s: inited parent to %s (was %s)\n",
 						 clk->name, clks->parent->name,
 						 ((clk->parent) ?
 						  clk->parent->name : "NULL"));
diff --git a/arch/arm/mach-omap2/clkt_dpll.c b/arch/arm/mach-omap2/clkt_dpll.c
index cd7fd0f..83b658b 100644
--- a/arch/arm/mach-omap2/clkt_dpll.c
+++ b/arch/arm/mach-omap2/clkt_dpll.c
@@ -22,8 +22,8 @@
 #include <asm/div64.h>
 
 #include <plat/clock.h>
-#include <plat/cpu.h>
 
+#include "soc.h"
 #include "clock.h"
 #include "cm-regbits-24xx.h"
 #include "cm-regbits-34xx.h"
@@ -105,13 +105,13 @@ static int _dpll_test_fint(struct clk *clk, u8 n)
 	}
 
 	if (fint < fint_min) {
-		pr_debug("rejecting n=%d due to Fint failure, "
-			 "lowering max_divider\n", n);
+		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 > fint_max) {
-		pr_debug("rejecting n=%d due to Fint failure, "
-			 "boosting min_divider\n", n);
+		pr_debug("rejecting n=%d due to Fint failure, boosting min_divider\n",
+			 n);
 		dd->min_divider = n;
 		ret = DPLL_FINT_INVALID;
 	} else if (cpu_is_omap3430() && fint > OMAP3430_DPLL_FINT_BAND1_MAX &&
@@ -211,7 +211,7 @@ void omap2_init_dpll_parent(struct clk *clk)
 		if (v == OMAP3XXX_EN_DPLL_LPBYPASS ||
 		    v == OMAP3XXX_EN_DPLL_FRBYPASS)
 			clk_reparent(clk, dd->clk_bypass);
-	} else if (cpu_is_omap44xx()) {
+	} else if (soc_is_am33xx() || cpu_is_omap44xx()) {
 		if (v == OMAP4XXX_EN_DPLL_LPBYPASS ||
 		    v == OMAP4XXX_EN_DPLL_FRBYPASS ||
 		    v == OMAP4XXX_EN_DPLL_MNBYPASS)
@@ -257,7 +257,7 @@ u32 omap2_get_dpll_rate(struct clk *clk)
 		if (v == OMAP3XXX_EN_DPLL_LPBYPASS ||
 		    v == OMAP3XXX_EN_DPLL_FRBYPASS)
 			return dd->clk_bypass->rate;
-	} else if (cpu_is_omap44xx()) {
+	} else if (soc_is_am33xx() || cpu_is_omap44xx()) {
 		if (v == OMAP4XXX_EN_DPLL_LPBYPASS ||
 		    v == OMAP4XXX_EN_DPLL_FRBYPASS ||
 		    v == OMAP4XXX_EN_DPLL_MNBYPASS)
diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
index ea3f565..e97f98f 100644
--- a/arch/arm/mach-omap2/clock.c
+++ b/arch/arm/mach-omap2/clock.c
@@ -22,14 +22,16 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/bitops.h>
-#include <trace/events/power.h>
 
 #include <asm/cpu.h>
+
 #include <plat/clock.h>
-#include "clockdomain.h"
-#include <plat/cpu.h>
 #include <plat/prcm.h>
 
+#include <trace/events/power.h>
+
+#include "soc.h"
+#include "clockdomain.h"
 #include "clock.h"
 #include "cm2xxx_3xxx.h"
 #include "cm-regbits-24xx.h"
@@ -102,8 +104,8 @@ void omap2_init_clk_clkdm(struct clk *clk)
 			 clk->name, clk->clkdm_name);
 		clk->clkdm = clkdm;
 	} else {
-		pr_debug("clock: could not associate clk %s to "
-			 "clkdm %s\n", clk->name, clk->clkdm_name);
+		pr_debug("clock: could not associate clk %s to clkdm %s\n",
+			 clk->name, clk->clkdm_name);
 	}
 }
 
@@ -226,8 +228,7 @@ void omap2_dflt_clk_disable(struct clk *clk)
 		 * 'Independent' here refers to a clock which is not
 		 * controlled by its parent.
 		 */
-		printk(KERN_ERR "clock: clk_disable called on independent "
-		       "clock %s which has no enable_reg\n", clk->name);
+		pr_err("clock: clk_disable called on independent clock %s which has no enable_reg\n", clk->name);
 		return;
 	}
 
@@ -270,8 +271,7 @@ const struct clkops clkops_omap2_dflt = {
 void omap2_clk_disable(struct clk *clk)
 {
 	if (clk->usecount == 0) {
-		WARN(1, "clock: %s: omap2_clk_disable() called, but usecount "
-		     "already 0?", clk->name);
+		WARN(1, "clock: %s: omap2_clk_disable() called, but usecount already 0?", clk->name);
 		return;
 	}
 
@@ -332,8 +332,8 @@ int omap2_clk_enable(struct clk *clk)
 	if (clkdm_control && clk->clkdm) {
 		ret = clkdm_clk_enable(clk->clkdm, clk);
 		if (ret) {
-			WARN(1, "clock: %s: could not enable clockdomain %s: "
-			     "%d\n", clk->name, clk->clkdm->name, ret);
+			WARN(1, "clock: %s: could not enable clockdomain %s: %d\n",
+			     clk->name, clk->clkdm->name, ret);
 			goto oce_err2;
 		}
 	}
@@ -501,10 +501,8 @@ void __init omap2_clk_print_new_rates(const char *hfclkin_ck_name,
 
 	hfclkin_rate = clk_get_rate(hfclkin_ck);
 
-	pr_info("Switched to new clocking rate (Crystal/Core/MPU): "
-		"%ld.%01ld/%ld/%ld MHz\n",
-		(hfclkin_rate / 1000000),
-		((hfclkin_rate / 100000) % 10),
+	pr_info("Switched to new clocking rate (Crystal/Core/MPU): %ld.%01ld/%ld/%ld MHz\n",
+		(hfclkin_rate / 1000000), ((hfclkin_rate / 100000) % 10),
 		(clk_get_rate(core_ck) / 1000000),
 		(clk_get_rate(mpu_ck) / 1000000));
 }
diff --git a/arch/arm/mach-omap2/clock2420_data.c b/arch/arm/mach-omap2/clock2420_data.c
index 0027451..12c178d 100644
--- a/arch/arm/mach-omap2/clock2420_data.c
+++ b/arch/arm/mach-omap2/clock2420_data.c
@@ -18,9 +18,9 @@
 #include <linux/clk.h>
 #include <linux/list.h>
 
-#include <plat/hardware.h>
 #include <plat/clkdev_omap.h>
 
+#include "soc.h"
 #include "iomap.h"
 #include "clock.h"
 #include "clock2xxx.h"
diff --git a/arch/arm/mach-omap2/clock2430.c b/arch/arm/mach-omap2/clock2430.c
index dfda9a3..a8e3261 100644
--- a/arch/arm/mach-omap2/clock2430.c
+++ b/arch/arm/mach-omap2/clock2430.c
@@ -21,9 +21,9 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 
-#include <plat/hardware.h>
 #include <plat/clock.h>
 
+#include "soc.h"
 #include "iomap.h"
 #include "clock.h"
 #include "clock2xxx.h"
diff --git a/arch/arm/mach-omap2/clock2430_data.c b/arch/arm/mach-omap2/clock2430_data.c
index cacabb0..7ea9139 100644
--- a/arch/arm/mach-omap2/clock2430_data.c
+++ b/arch/arm/mach-omap2/clock2430_data.c
@@ -17,9 +17,9 @@
 #include <linux/clk.h>
 #include <linux/list.h>
 
-#include <plat/hardware.h>
 #include <plat/clkdev_omap.h>
 
+#include "soc.h"
 #include "iomap.h"
 #include "clock.h"
 #include "clock2xxx.h"
@@ -1856,6 +1856,7 @@ static struct omap_clk omap2430_clks[] = {
 	CLK(NULL,	"func_32k_ck",	&func_32k_ck,	CK_243X),
 	CLK(NULL,	"secure_32k_ck", &secure_32k_ck, CK_243X),
 	CLK(NULL,	"osc_ck",	&osc_ck,	CK_243X),
+	CLK("twl",	"fck",		&osc_ck,	CK_243X),
 	CLK(NULL,	"sys_ck",	&sys_ck,	CK_243X),
 	CLK(NULL,	"alt_ck",	&alt_ck,	CK_243X),
 	CLK(NULL,	"mcbsp_clks",	&mcbsp_clks,	CK_243X),
diff --git a/arch/arm/mach-omap2/clock2xxx.c b/arch/arm/mach-omap2/clock2xxx.c
index 1250009..e92be1fc 100644
--- a/arch/arm/mach-omap2/clock2xxx.c
+++ b/arch/arm/mach-omap2/clock2xxx.c
@@ -22,9 +22,9 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 
-#include <plat/cpu.h>
 #include <plat/clock.h>
 
+#include "soc.h"
 #include "clock.h"
 #include "clock2xxx.h"
 #include "cm.h"
diff --git a/arch/arm/mach-omap2/clock33xx_data.c b/arch/arm/mach-omap2/clock33xx_data.c
index ae27de8..2026311 100644
--- a/arch/arm/mach-omap2/clock33xx_data.c
+++ b/arch/arm/mach-omap2/clock33xx_data.c
@@ -18,8 +18,8 @@
 #include <linux/list.h>
 #include <linux/clk.h>
 #include <plat/clkdev_omap.h>
-#include <plat/am33xx.h>
 
+#include "am33xx.h"
 #include "iomap.h"
 #include "control.h"
 #include "clock.h"
@@ -1027,7 +1027,9 @@ static struct omap_clk am33xx_clks[] = {
 	CLK(NULL,	"cefuse_fck",		&cefuse_fck,	CK_AM33XX),
 	CLK(NULL,	"clkdiv32k_ick",	&clkdiv32k_ick,	CK_AM33XX),
 	CLK(NULL,	"dcan0_fck",		&dcan0_fck,	CK_AM33XX),
+	CLK("481cc000.d_can",	NULL,		&dcan0_fck,	CK_AM33XX),
 	CLK(NULL,	"dcan1_fck",		&dcan1_fck,	CK_AM33XX),
+	CLK("481d0000.d_can",	NULL,		&dcan1_fck,	CK_AM33XX),
 	CLK(NULL,	"debugss_ick",		&debugss_ick,	CK_AM33XX),
 	CLK(NULL,	"pruss_ocp_gclk",	&pruss_ocp_gclk,	CK_AM33XX),
 	CLK("davinci-mcasp.0",  NULL,           &mcasp0_fck,    CK_AM33XX),
diff --git a/arch/arm/mach-omap2/clock3xxx.c b/arch/arm/mach-omap2/clock3xxx.c
index 794d827..15cdc647 100644
--- a/arch/arm/mach-omap2/clock3xxx.c
+++ b/arch/arm/mach-omap2/clock3xxx.c
@@ -21,9 +21,9 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 
-#include <plat/hardware.h>
 #include <plat/clock.h>
 
+#include "soc.h"
 #include "clock.h"
 #include "clock3xxx.h"
 #include "prm2xxx_3xxx.h"
@@ -49,8 +49,7 @@ int omap3_dpll4_set_rate(struct clk *clk, unsigned long rate)
 	 * on DPLL4.
 	 */
 	if (omap_rev() == OMAP3430_REV_ES1_0) {
-		pr_err("clock: DPLL4 cannot change rate due to "
-		       "silicon 'Limitation 2.5' on 3430ES1.\n");
+		pr_err("clock: DPLL4 cannot change rate due to silicon 'Limitation 2.5' on 3430ES1.\n");
 		return -EINVAL;
 	}
 
diff --git a/arch/arm/mach-omap2/clock3xxx_data.c b/arch/arm/mach-omap2/clock3xxx_data.c
index 83bed9a..700317a 100644
--- a/arch/arm/mach-omap2/clock3xxx_data.c
+++ b/arch/arm/mach-omap2/clock3xxx_data.c
@@ -21,9 +21,9 @@
 #include <linux/list.h>
 #include <linux/io.h>
 
-#include <plat/hardware.h>
 #include <plat/clkdev_omap.h>
 
+#include "soc.h"
 #include "iomap.h"
 #include "clock.h"
 #include "clock3xxx.h"
@@ -3226,6 +3226,7 @@ static struct omap_clk omap3xxx_clks[] = {
 	CLK(NULL,	"virt_26000000_ck",	&virt_26000000_ck,	CK_3XXX),
 	CLK(NULL,	"virt_38_4m_ck", &virt_38_4m_ck, CK_3XXX),
 	CLK(NULL,	"osc_sys_ck",	&osc_sys_ck,	CK_3XXX),
+	CLK("twl",	"fck",		&osc_sys_ck,	CK_3XXX),
 	CLK(NULL,	"sys_ck",	&sys_ck,	CK_3XXX),
 	CLK(NULL,	"sys_altclk",	&sys_altclk,	CK_3XXX),
 	CLK(NULL,	"mcbsp_clks",	&mcbsp_clks,	CK_3XXX),
diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c
index d7f55e4..500682c 100644
--- a/arch/arm/mach-omap2/clock44xx_data.c
+++ b/arch/arm/mach-omap2/clock44xx_data.c
@@ -28,9 +28,9 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 
-#include <plat/hardware.h>
 #include <plat/clkdev_omap.h>
 
+#include "soc.h"
 #include "iomap.h"
 #include "clock.h"
 #include "clock44xx.h"
diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c
index 8664f5a..a155562 100644
--- a/arch/arm/mach-omap2/clockdomain.c
+++ b/arch/arm/mach-omap2/clockdomain.c
@@ -174,9 +174,8 @@ void _clkdm_add_autodeps(struct clockdomain *clkdm)
 		if (IS_ERR(autodep->clkdm.ptr))
 			continue;
 
-		pr_debug("clockdomain: adding %s sleepdep/wkdep for "
-			 "clkdm %s\n", autodep->clkdm.ptr->name,
-			 clkdm->name);
+		pr_debug("clockdomain: %s: adding %s sleepdep/wkdep\n",
+			 clkdm->name, autodep->clkdm.ptr->name);
 
 		clkdm_add_sleepdep(clkdm, autodep->clkdm.ptr);
 		clkdm_add_wkdep(clkdm, autodep->clkdm.ptr);
@@ -205,9 +204,8 @@ void _clkdm_del_autodeps(struct clockdomain *clkdm)
 		if (IS_ERR(autodep->clkdm.ptr))
 			continue;
 
-		pr_debug("clockdomain: removing %s sleepdep/wkdep for "
-			 "clkdm %s\n", autodep->clkdm.ptr->name,
-			 clkdm->name);
+		pr_debug("clockdomain: %s: removing %s sleepdep/wkdep\n",
+			 clkdm->name, autodep->clkdm.ptr->name);
 
 		clkdm_del_sleepdep(clkdm, autodep->clkdm.ptr);
 		clkdm_del_wkdep(clkdm, autodep->clkdm.ptr);
@@ -469,14 +467,14 @@ int clkdm_add_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
 		ret = -EINVAL;
 
 	if (ret) {
-		pr_debug("clockdomain: hardware cannot set/clear wake up of "
-			 "%s when %s wakes up\n", clkdm1->name, clkdm2->name);
+		pr_debug("clockdomain: hardware cannot set/clear wake up of %s when %s wakes up\n",
+			 clkdm1->name, clkdm2->name);
 		return ret;
 	}
 
 	if (atomic_inc_return(&cd->wkdep_usecount) == 1) {
-		pr_debug("clockdomain: hardware will wake up %s when %s wakes "
-			 "up\n", clkdm1->name, clkdm2->name);
+		pr_debug("clockdomain: hardware will wake up %s when %s wakes up\n",
+			 clkdm1->name, clkdm2->name);
 
 		ret = arch_clkdm->clkdm_add_wkdep(clkdm1, clkdm2);
 	}
@@ -510,14 +508,14 @@ int clkdm_del_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
 		ret = -EINVAL;
 
 	if (ret) {
-		pr_debug("clockdomain: hardware cannot set/clear wake up of "
-			 "%s when %s wakes up\n", clkdm1->name, clkdm2->name);
+		pr_debug("clockdomain: hardware cannot set/clear wake up of %s when %s wakes up\n",
+			 clkdm1->name, clkdm2->name);
 		return ret;
 	}
 
 	if (atomic_dec_return(&cd->wkdep_usecount) == 0) {
-		pr_debug("clockdomain: hardware will no longer wake up %s "
-			 "after %s wakes up\n", clkdm1->name, clkdm2->name);
+		pr_debug("clockdomain: hardware will no longer wake up %s after %s wakes up\n",
+			 clkdm1->name, clkdm2->name);
 
 		ret = arch_clkdm->clkdm_del_wkdep(clkdm1, clkdm2);
 	}
@@ -555,8 +553,8 @@ int clkdm_read_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
 		ret = -EINVAL;
 
 	if (ret) {
-		pr_debug("clockdomain: hardware cannot set/clear wake up of "
-			 "%s when %s wakes up\n", clkdm1->name, clkdm2->name);
+		pr_debug("clockdomain: hardware cannot set/clear wake up of %s when %s wakes up\n",
+			 clkdm1->name, clkdm2->name);
 		return ret;
 	}
 
@@ -613,15 +611,14 @@ int clkdm_add_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
 		ret = -EINVAL;
 
 	if (ret) {
-		pr_debug("clockdomain: hardware cannot set/clear sleep "
-			 "dependency affecting %s from %s\n", clkdm1->name,
-			 clkdm2->name);
+		pr_debug("clockdomain: hardware cannot set/clear sleep dependency affecting %s from %s\n",
+			 clkdm1->name, clkdm2->name);
 		return ret;
 	}
 
 	if (atomic_inc_return(&cd->sleepdep_usecount) == 1) {
-		pr_debug("clockdomain: will prevent %s from sleeping if %s "
-			 "is active\n", clkdm1->name, clkdm2->name);
+		pr_debug("clockdomain: will prevent %s from sleeping if %s is active\n",
+			 clkdm1->name, clkdm2->name);
 
 		ret = arch_clkdm->clkdm_add_sleepdep(clkdm1, clkdm2);
 	}
@@ -657,16 +654,14 @@ int clkdm_del_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
 		ret = -EINVAL;
 
 	if (ret) {
-		pr_debug("clockdomain: hardware cannot set/clear sleep "
-			 "dependency affecting %s from %s\n", clkdm1->name,
-			 clkdm2->name);
+		pr_debug("clockdomain: hardware cannot set/clear sleep dependency affecting %s from %s\n",
+			 clkdm1->name, clkdm2->name);
 		return ret;
 	}
 
 	if (atomic_dec_return(&cd->sleepdep_usecount) == 0) {
-		pr_debug("clockdomain: will no longer prevent %s from "
-			 "sleeping if %s is active\n", clkdm1->name,
-			 clkdm2->name);
+		pr_debug("clockdomain: will no longer prevent %s from sleeping if %s is active\n",
+			 clkdm1->name, clkdm2->name);
 
 		ret = arch_clkdm->clkdm_del_sleepdep(clkdm1, clkdm2);
 	}
@@ -706,9 +701,8 @@ int clkdm_read_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
 		ret = -EINVAL;
 
 	if (ret) {
-		pr_debug("clockdomain: hardware cannot set/clear sleep "
-			 "dependency affecting %s from %s\n", clkdm1->name,
-			 clkdm2->name);
+		pr_debug("clockdomain: hardware cannot set/clear sleep dependency affecting %s from %s\n",
+			 clkdm1->name, clkdm2->name);
 		return ret;
 	}
 
@@ -755,8 +749,8 @@ int clkdm_sleep(struct clockdomain *clkdm)
 		return -EINVAL;
 
 	if (!(clkdm->flags & CLKDM_CAN_FORCE_SLEEP)) {
-		pr_debug("clockdomain: %s does not support forcing "
-			 "sleep via software\n", clkdm->name);
+		pr_debug("clockdomain: %s does not support forcing sleep via software\n",
+			 clkdm->name);
 		return -EINVAL;
 	}
 
@@ -790,8 +784,8 @@ int clkdm_wakeup(struct clockdomain *clkdm)
 		return -EINVAL;
 
 	if (!(clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)) {
-		pr_debug("clockdomain: %s does not support forcing "
-			 "wakeup via software\n", clkdm->name);
+		pr_debug("clockdomain: %s does not support forcing wakeup via software\n",
+			 clkdm->name);
 		return -EINVAL;
 	}
 
@@ -826,8 +820,8 @@ void clkdm_allow_idle(struct clockdomain *clkdm)
 		return;
 
 	if (!(clkdm->flags & CLKDM_CAN_ENABLE_AUTO)) {
-		pr_debug("clock: automatic idle transitions cannot be enabled "
-			 "on clockdomain %s\n", clkdm->name);
+		pr_debug("clock: %s: automatic idle transitions cannot be enabled\n",
+			 clkdm->name);
 		return;
 	}
 
@@ -861,8 +855,8 @@ void clkdm_deny_idle(struct clockdomain *clkdm)
 		return;
 
 	if (!(clkdm->flags & CLKDM_CAN_DISABLE_AUTO)) {
-		pr_debug("clockdomain: automatic idle transitions cannot be "
-			 "disabled on %s\n", clkdm->name);
+		pr_debug("clockdomain: %s: automatic idle transitions cannot be disabled\n",
+			 clkdm->name);
 		return;
 	}
 
@@ -927,7 +921,7 @@ static int _clkdm_clk_hwmod_enable(struct clockdomain *clkdm)
 	pwrdm_state_switch(clkdm->pwrdm.ptr);
 	spin_unlock_irqrestore(&clkdm->lock, flags);
 
-	pr_debug("clockdomain: clkdm %s: enabled\n", clkdm->name);
+	pr_debug("clockdomain: %s: enabled\n", clkdm->name);
 
 	return 0;
 }
@@ -952,7 +946,7 @@ static int _clkdm_clk_hwmod_disable(struct clockdomain *clkdm)
 	pwrdm_state_switch(clkdm->pwrdm.ptr);
 	spin_unlock_irqrestore(&clkdm->lock, flags);
 
-	pr_debug("clockdomain: clkdm %s: disabled\n", clkdm->name);
+	pr_debug("clockdomain: %s: disabled\n", clkdm->name);
 
 	return 0;
 }
diff --git a/arch/arm/mach-omap2/cm2xxx_3xxx.c b/arch/arm/mach-omap2/cm2xxx_3xxx.c
index 389f9f8..a911e76 100644
--- a/arch/arm/mach-omap2/cm2xxx_3xxx.c
+++ b/arch/arm/mach-omap2/cm2xxx_3xxx.c
@@ -18,8 +18,7 @@
 #include <linux/err.h>
 #include <linux/io.h>
 
-#include <plat/hardware.h>
-
+#include "soc.h"
 #include "iomap.h"
 #include "common.h"
 #include "cm.h"
diff --git a/arch/arm/mach-omap2/common-board-devices.c b/arch/arm/mach-omap2/common-board-devices.c
index c187586..48daac2 100644
--- a/arch/arm/mach-omap2/common-board-devices.c
+++ b/arch/arm/mach-omap2/common-board-devices.c
@@ -24,9 +24,10 @@
 #include <linux/spi/spi.h>
 #include <linux/spi/ads7846.h>
 
-#include <plat/mcspi.h>
-#include <plat/nand.h>
+#include <linux/platform_data/spi-omap2-mcspi.h>
+#include <linux/platform_data/mtd-nand-omap2.h>
 
+#include "common.h"
 #include "common-board-devices.h"
 
 #if defined(CONFIG_TOUCHSCREEN_ADS7846) || \
@@ -119,8 +120,7 @@ void __init omap_nand_flash_init(int options, struct mtd_partition *parts,
 	}
 
 	if (nandcs > GPMC_CS_NUM) {
-		printk(KERN_INFO "NAND: Unable to find configuration "
-				 "in GPMC\n ");
+		pr_info("NAND: Unable to find configuration in GPMC\n");
 		return;
 	}
 
diff --git a/arch/arm/mach-omap2/common.c b/arch/arm/mach-omap2/common.c
index 069f972..17950c6 100644
--- a/arch/arm/mach-omap2/common.c
+++ b/arch/arm/mach-omap2/common.c
@@ -17,11 +17,9 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 
-#include <plat/hardware.h>
-#include <plat/board.h>
-#include <plat/mux.h>
 #include <plat/clock.h>
 
+#include "soc.h"
 #include "iomap.h"
 #include "common.h"
 #include "sdrc.h"
diff --git a/arch/arm/mach-omap2/common.h b/arch/arm/mach-omap2/common.h
index 1f65b18..7045e4d 100644
--- a/arch/arm/mach-omap2/common.h
+++ b/arch/arm/mach-omap2/common.h
@@ -26,11 +26,18 @@
 #define __ARCH_ARM_MACH_OMAP2PLUS_COMMON_H
 #ifndef __ASSEMBLER__
 
+#include <linux/irq.h>
 #include <linux/delay.h>
 #include <linux/i2c/twl.h>
-#include <plat/common.h>
+
 #include <asm/proc-fns.h>
 
+#include <plat/cpu.h>
+#include <plat/serial.h>
+#include <plat/common.h>
+
+#define OMAP_INTC_START		NR_IRQS
+
 #ifdef CONFIG_SOC_OMAP2420
 extern void omap242x_map_common_io(void);
 #else
@@ -278,6 +285,11 @@ extern void omap_secondary_startup(void);
 extern u32 omap_modify_auxcoreboot0(u32 set_mask, u32 clear_mask);
 extern void omap_auxcoreboot_addr(u32 cpu_addr);
 extern u32 omap_read_auxcoreboot0(void);
+
+extern void omap4_cpu_die(unsigned int cpu);
+
+extern struct smp_operations omap4_smp_ops;
+
 extern void omap5_secondary_startup(void);
 #endif
 
diff --git a/arch/arm/mach-omap2/control.c b/arch/arm/mach-omap2/control.c
index 3223b81..d1ff839 100644
--- a/arch/arm/mach-omap2/control.c
+++ b/arch/arm/mach-omap2/control.c
@@ -15,9 +15,9 @@
 #include <linux/kernel.h>
 #include <linux/io.h>
 
-#include <plat/hardware.h>
 #include <plat/sdrc.h>
 
+#include "soc.h"
 #include "iomap.h"
 #include "common.h"
 #include "cm-regbits-34xx.h"
diff --git a/arch/arm/mach-omap2/control.h b/arch/arm/mach-omap2/control.h
index b8cdc85..123186a 100644
--- a/arch/arm/mach-omap2/control.h
+++ b/arch/arm/mach-omap2/control.h
@@ -16,12 +16,12 @@
 #ifndef __ARCH_ARM_MACH_OMAP2_CONTROL_H
 #define __ARCH_ARM_MACH_OMAP2_CONTROL_H
 
-#include <mach/ctrl_module_core_44xx.h>
-#include <mach/ctrl_module_wkup_44xx.h>
-#include <mach/ctrl_module_pad_core_44xx.h>
-#include <mach/ctrl_module_pad_wkup_44xx.h>
+#include "ctrl_module_core_44xx.h"
+#include "ctrl_module_wkup_44xx.h"
+#include "ctrl_module_pad_core_44xx.h"
+#include "ctrl_module_pad_wkup_44xx.h"
 
-#include <plat/am33xx.h>
+#include "am33xx.h"
 
 #ifndef __ASSEMBLY__
 #define OMAP242X_CTRL_REGADDR(reg)					\
diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c
index f2a49a4..bc27569 100644
--- a/arch/arm/mach-omap2/cpuidle34xx.c
+++ b/arch/arm/mach-omap2/cpuidle34xx.c
@@ -28,7 +28,6 @@
 #include <linux/cpu_pm.h>
 
 #include <plat/prcm.h>
-#include <plat/irqs.h>
 #include "powerdomain.h"
 #include "clockdomain.h"
 
diff --git a/arch/arm/mach-omap2/ctrl_module_core_44xx.h b/arch/arm/mach-omap2/ctrl_module_core_44xx.h
new file mode 100644
index 0000000..0197082
--- /dev/null
+++ b/arch/arm/mach-omap2/ctrl_module_core_44xx.h
@@ -0,0 +1,392 @@
+/*
+ * OMAP44xx CTRL_MODULE_CORE registers and bitfields
+ *
+ * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ *
+ * Benoit Cousson (b-cousson@ti.com)
+ * Santosh Shilimkar (santosh.shilimkar@ti.com)
+ *
+ * This file is automatically generated from the OMAP hardware databases.
+ * We respectfully ask that any modifications to this file be coordinated
+ * with the public linux-omap@vger.kernel.org mailing list and the
+ * authors above to ensure that the autogeneration scripts are kept
+ * up-to-date with the file contents.
+ *
+ * This program is free software; you can 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_CTRL_MODULE_CORE_44XX_H
+#define __ARCH_ARM_MACH_OMAP2_CTRL_MODULE_CORE_44XX_H
+
+
+/* Base address */
+#define OMAP4_CTRL_MODULE_CORE					0x4a002000
+
+/* Registers offset */
+#define OMAP4_CTRL_MODULE_CORE_IP_REVISION			0x0000
+#define OMAP4_CTRL_MODULE_CORE_IP_HWINFO			0x0004
+#define OMAP4_CTRL_MODULE_CORE_IP_SYSCONFIG			0x0010
+#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_DIE_ID_0		0x0200
+#define OMAP4_CTRL_MODULE_CORE_ID_CODE				0x0204
+#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_DIE_ID_1		0x0208
+#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_DIE_ID_2		0x020c
+#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_DIE_ID_3		0x0210
+#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_PROD_ID_0		0x0214
+#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_PROD_ID_1		0x0218
+#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_USB_CONF		0x021c
+#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_OPP_VDD_WKUP		0x0228
+#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_OPP_BGAP		0x0260
+#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_OPP_DPLL_0		0x0264
+#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_OPP_DPLL_1		0x0268
+#define OMAP4_CTRL_MODULE_CORE_STATUS				0x02c4
+#define OMAP4_CTRL_MODULE_CORE_DEV_CONF				0x0300
+#define OMAP4_CTRL_MODULE_CORE_DSP_BOOTADDR			0x0304
+#define OMAP4_CTRL_MODULE_CORE_LDOVBB_IVA_VOLTAGE_CTRL		0x0314
+#define OMAP4_CTRL_MODULE_CORE_LDOVBB_MPU_VOLTAGE_CTRL		0x0318
+#define OMAP4_CTRL_MODULE_CORE_LDOSRAM_IVA_VOLTAGE_CTRL		0x0320
+#define OMAP4_CTRL_MODULE_CORE_LDOSRAM_MPU_VOLTAGE_CTRL		0x0324
+#define OMAP4_CTRL_MODULE_CORE_LDOSRAM_CORE_VOLTAGE_CTRL	0x0328
+#define OMAP4_CTRL_MODULE_CORE_TEMP_SENSOR			0x032c
+#define OMAP4_CTRL_MODULE_CORE_DPLL_NWELL_TRIM_0		0x0330
+#define OMAP4_CTRL_MODULE_CORE_DPLL_NWELL_TRIM_1		0x0334
+#define OMAP4_CTRL_MODULE_CORE_USBOTGHS_CONTROL			0x033c
+#define OMAP4_CTRL_MODULE_CORE_DSS_CONTROL			0x0340
+#define OMAP4_CTRL_MODULE_CORE_HWOBS_CONTROL			0x0350
+#define OMAP4_CTRL_MODULE_CORE_DEBOBS_FINAL_MUX_SEL		0x0400
+#define OMAP4_CTRL_MODULE_CORE_DEBOBS_MMR_MPU			0x0408
+#define OMAP4_CTRL_MODULE_CORE_CONF_SDMA_REQ_SEL0		0x042c
+#define OMAP4_CTRL_MODULE_CORE_CONF_SDMA_REQ_SEL1		0x0430
+#define OMAP4_CTRL_MODULE_CORE_CONF_SDMA_REQ_SEL2		0x0434
+#define OMAP4_CTRL_MODULE_CORE_CONF_SDMA_REQ_SEL3		0x0438
+#define OMAP4_CTRL_MODULE_CORE_CONF_CLK_SEL0			0x0440
+#define OMAP4_CTRL_MODULE_CORE_CONF_CLK_SEL1			0x0444
+#define OMAP4_CTRL_MODULE_CORE_CONF_CLK_SEL2			0x0448
+#define OMAP4_CTRL_MODULE_CORE_CONF_DPLL_FREQLOCK_SEL		0x044c
+#define OMAP4_CTRL_MODULE_CORE_CONF_DPLL_TINITZ_SEL		0x0450
+#define OMAP4_CTRL_MODULE_CORE_CONF_DPLL_PHASELOCK_SEL		0x0454
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_0		0x0480
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_1		0x0484
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_2		0x0488
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_3		0x048c
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_4		0x0490
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_5		0x0494
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_6		0x0498
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_7		0x049c
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_8		0x04a0
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_9		0x04a4
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_10		0x04a8
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_11		0x04ac
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_12		0x04b0
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_13		0x04b4
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_14		0x04b8
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_15		0x04bc
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_16		0x04c0
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_17		0x04c4
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_18		0x04c8
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_19		0x04cc
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_20		0x04d0
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_21		0x04d4
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_22		0x04d8
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_23		0x04dc
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_24		0x04e0
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_25		0x04e4
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_26		0x04e8
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_27		0x04ec
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_28		0x04f0
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_29		0x04f4
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_30		0x04f8
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_31		0x04fc
+
+/* Registers shifts and masks */
+
+/* IP_REVISION */
+#define OMAP4_IP_REV_SCHEME_SHIFT			30
+#define OMAP4_IP_REV_SCHEME_MASK			(0x3 << 30)
+#define OMAP4_IP_REV_FUNC_SHIFT				16
+#define OMAP4_IP_REV_FUNC_MASK				(0xfff << 16)
+#define OMAP4_IP_REV_RTL_SHIFT				11
+#define OMAP4_IP_REV_RTL_MASK				(0x1f << 11)
+#define OMAP4_IP_REV_MAJOR_SHIFT			8
+#define OMAP4_IP_REV_MAJOR_MASK				(0x7 << 8)
+#define OMAP4_IP_REV_CUSTOM_SHIFT			6
+#define OMAP4_IP_REV_CUSTOM_MASK			(0x3 << 6)
+#define OMAP4_IP_REV_MINOR_SHIFT			0
+#define OMAP4_IP_REV_MINOR_MASK				(0x3f << 0)
+
+/* IP_HWINFO */
+#define OMAP4_IP_HWINFO_SHIFT				0
+#define OMAP4_IP_HWINFO_MASK				(0xffffffff << 0)
+
+/* IP_SYSCONFIG */
+#define OMAP4_IP_SYSCONFIG_IDLEMODE_SHIFT		2
+#define OMAP4_IP_SYSCONFIG_IDLEMODE_MASK		(0x3 << 2)
+
+/* STD_FUSE_DIE_ID_0 */
+#define OMAP4_STD_FUSE_DIE_ID_0_SHIFT			0
+#define OMAP4_STD_FUSE_DIE_ID_0_MASK			(0xffffffff << 0)
+
+/* ID_CODE */
+#define OMAP4_STD_FUSE_IDCODE_SHIFT			0
+#define OMAP4_STD_FUSE_IDCODE_MASK			(0xffffffff << 0)
+
+/* STD_FUSE_DIE_ID_1 */
+#define OMAP4_STD_FUSE_DIE_ID_1_SHIFT			0
+#define OMAP4_STD_FUSE_DIE_ID_1_MASK			(0xffffffff << 0)
+
+/* STD_FUSE_DIE_ID_2 */
+#define OMAP4_STD_FUSE_DIE_ID_2_SHIFT			0
+#define OMAP4_STD_FUSE_DIE_ID_2_MASK			(0xffffffff << 0)
+
+/* STD_FUSE_DIE_ID_3 */
+#define OMAP4_STD_FUSE_DIE_ID_3_SHIFT			0
+#define OMAP4_STD_FUSE_DIE_ID_3_MASK			(0xffffffff << 0)
+
+/* STD_FUSE_PROD_ID_0 */
+#define OMAP4_STD_FUSE_PROD_ID_0_SHIFT			0
+#define OMAP4_STD_FUSE_PROD_ID_0_MASK			(0xffffffff << 0)
+
+/* STD_FUSE_PROD_ID_1 */
+#define OMAP4_STD_FUSE_PROD_ID_1_SHIFT			0
+#define OMAP4_STD_FUSE_PROD_ID_1_MASK			(0xffffffff << 0)
+
+/* STD_FUSE_USB_CONF */
+#define OMAP4_USB_PROD_ID_SHIFT				16
+#define OMAP4_USB_PROD_ID_MASK				(0xffff << 16)
+#define OMAP4_USB_VENDOR_ID_SHIFT			0
+#define OMAP4_USB_VENDOR_ID_MASK			(0xffff << 0)
+
+/* STD_FUSE_OPP_VDD_WKUP */
+#define OMAP4_STD_FUSE_OPP_VDD_WKUP_SHIFT		0
+#define OMAP4_STD_FUSE_OPP_VDD_WKUP_MASK		(0xffffffff << 0)
+
+/* STD_FUSE_OPP_BGAP */
+#define OMAP4_STD_FUSE_OPP_BGAP_SHIFT			0
+#define OMAP4_STD_FUSE_OPP_BGAP_MASK			(0xffffffff << 0)
+
+/* STD_FUSE_OPP_DPLL_0 */
+#define OMAP4_STD_FUSE_OPP_DPLL_0_SHIFT			0
+#define OMAP4_STD_FUSE_OPP_DPLL_0_MASK			(0xffffffff << 0)
+
+/* STD_FUSE_OPP_DPLL_1 */
+#define OMAP4_STD_FUSE_OPP_DPLL_1_SHIFT			0
+#define OMAP4_STD_FUSE_OPP_DPLL_1_MASK			(0xffffffff << 0)
+
+/* STATUS */
+#define OMAP4_ATTILA_CONF_SHIFT				11
+#define OMAP4_ATTILA_CONF_MASK				(0x3 << 11)
+#define OMAP4_DEVICE_TYPE_SHIFT				8
+#define OMAP4_DEVICE_TYPE_MASK				(0x7 << 8)
+#define OMAP4_SYS_BOOT_SHIFT				0
+#define OMAP4_SYS_BOOT_MASK				(0xff << 0)
+
+/* DEV_CONF */
+#define OMAP4_DEV_CONF_SHIFT				1
+#define OMAP4_DEV_CONF_MASK				(0x7fffffff << 1)
+#define OMAP4_USBPHY_PD_SHIFT				0
+#define OMAP4_USBPHY_PD_MASK				(1 << 0)
+
+/* LDOVBB_IVA_VOLTAGE_CTRL */
+#define OMAP4_LDOVBBIVA_RBB_MUX_CTRL_SHIFT		26
+#define OMAP4_LDOVBBIVA_RBB_MUX_CTRL_MASK		(1 << 26)
+#define OMAP4_LDOVBBIVA_RBB_VSET_IN_SHIFT		21
+#define OMAP4_LDOVBBIVA_RBB_VSET_IN_MASK		(0x1f << 21)
+#define OMAP4_LDOVBBIVA_RBB_VSET_OUT_SHIFT		16
+#define OMAP4_LDOVBBIVA_RBB_VSET_OUT_MASK		(0x1f << 16)
+#define OMAP4_LDOVBBIVA_FBB_MUX_CTRL_SHIFT		10
+#define OMAP4_LDOVBBIVA_FBB_MUX_CTRL_MASK		(1 << 10)
+#define OMAP4_LDOVBBIVA_FBB_VSET_IN_SHIFT		5
+#define OMAP4_LDOVBBIVA_FBB_VSET_IN_MASK		(0x1f << 5)
+#define OMAP4_LDOVBBIVA_FBB_VSET_OUT_SHIFT		0
+#define OMAP4_LDOVBBIVA_FBB_VSET_OUT_MASK		(0x1f << 0)
+
+/* LDOVBB_MPU_VOLTAGE_CTRL */
+#define OMAP4_LDOVBBMPU_RBB_MUX_CTRL_SHIFT		26
+#define OMAP4_LDOVBBMPU_RBB_MUX_CTRL_MASK		(1 << 26)
+#define OMAP4_LDOVBBMPU_RBB_VSET_IN_SHIFT		21
+#define OMAP4_LDOVBBMPU_RBB_VSET_IN_MASK		(0x1f << 21)
+#define OMAP4_LDOVBBMPU_RBB_VSET_OUT_SHIFT		16
+#define OMAP4_LDOVBBMPU_RBB_VSET_OUT_MASK		(0x1f << 16)
+#define OMAP4_LDOVBBMPU_FBB_MUX_CTRL_SHIFT		10
+#define OMAP4_LDOVBBMPU_FBB_MUX_CTRL_MASK		(1 << 10)
+#define OMAP4_LDOVBBMPU_FBB_VSET_IN_SHIFT		5
+#define OMAP4_LDOVBBMPU_FBB_VSET_IN_MASK		(0x1f << 5)
+#define OMAP4_LDOVBBMPU_FBB_VSET_OUT_SHIFT		0
+#define OMAP4_LDOVBBMPU_FBB_VSET_OUT_MASK		(0x1f << 0)
+
+/* LDOSRAM_IVA_VOLTAGE_CTRL */
+#define OMAP4_LDOSRAMIVA_RETMODE_MUX_CTRL_SHIFT		26
+#define OMAP4_LDOSRAMIVA_RETMODE_MUX_CTRL_MASK		(1 << 26)
+#define OMAP4_LDOSRAMIVA_RETMODE_VSET_IN_SHIFT		21
+#define OMAP4_LDOSRAMIVA_RETMODE_VSET_IN_MASK		(0x1f << 21)
+#define OMAP4_LDOSRAMIVA_RETMODE_VSET_OUT_SHIFT		16
+#define OMAP4_LDOSRAMIVA_RETMODE_VSET_OUT_MASK		(0x1f << 16)
+#define OMAP4_LDOSRAMIVA_ACTMODE_MUX_CTRL_SHIFT		10
+#define OMAP4_LDOSRAMIVA_ACTMODE_MUX_CTRL_MASK		(1 << 10)
+#define OMAP4_LDOSRAMIVA_ACTMODE_VSET_IN_SHIFT		5
+#define OMAP4_LDOSRAMIVA_ACTMODE_VSET_IN_MASK		(0x1f << 5)
+#define OMAP4_LDOSRAMIVA_ACTMODE_VSET_OUT_SHIFT		0
+#define OMAP4_LDOSRAMIVA_ACTMODE_VSET_OUT_MASK		(0x1f << 0)
+
+/* LDOSRAM_MPU_VOLTAGE_CTRL */
+#define OMAP4_LDOSRAMMPU_RETMODE_MUX_CTRL_SHIFT		26
+#define OMAP4_LDOSRAMMPU_RETMODE_MUX_CTRL_MASK		(1 << 26)
+#define OMAP4_LDOSRAMMPU_RETMODE_VSET_IN_SHIFT		21
+#define OMAP4_LDOSRAMMPU_RETMODE_VSET_IN_MASK		(0x1f << 21)
+#define OMAP4_LDOSRAMMPU_RETMODE_VSET_OUT_SHIFT		16
+#define OMAP4_LDOSRAMMPU_RETMODE_VSET_OUT_MASK		(0x1f << 16)
+#define OMAP4_LDOSRAMMPU_ACTMODE_MUX_CTRL_SHIFT		10
+#define OMAP4_LDOSRAMMPU_ACTMODE_MUX_CTRL_MASK		(1 << 10)
+#define OMAP4_LDOSRAMMPU_ACTMODE_VSET_IN_SHIFT		5
+#define OMAP4_LDOSRAMMPU_ACTMODE_VSET_IN_MASK		(0x1f << 5)
+#define OMAP4_LDOSRAMMPU_ACTMODE_VSET_OUT_SHIFT		0
+#define OMAP4_LDOSRAMMPU_ACTMODE_VSET_OUT_MASK		(0x1f << 0)
+
+/* LDOSRAM_CORE_VOLTAGE_CTRL */
+#define OMAP4_LDOSRAMCORE_RETMODE_MUX_CTRL_SHIFT	26
+#define OMAP4_LDOSRAMCORE_RETMODE_MUX_CTRL_MASK		(1 << 26)
+#define OMAP4_LDOSRAMCORE_RETMODE_VSET_IN_SHIFT		21
+#define OMAP4_LDOSRAMCORE_RETMODE_VSET_IN_MASK		(0x1f << 21)
+#define OMAP4_LDOSRAMCORE_RETMODE_VSET_OUT_SHIFT	16
+#define OMAP4_LDOSRAMCORE_RETMODE_VSET_OUT_MASK		(0x1f << 16)
+#define OMAP4_LDOSRAMCORE_ACTMODE_MUX_CTRL_SHIFT	10
+#define OMAP4_LDOSRAMCORE_ACTMODE_MUX_CTRL_MASK		(1 << 10)
+#define OMAP4_LDOSRAMCORE_ACTMODE_VSET_IN_SHIFT		5
+#define OMAP4_LDOSRAMCORE_ACTMODE_VSET_IN_MASK		(0x1f << 5)
+#define OMAP4_LDOSRAMCORE_ACTMODE_VSET_OUT_SHIFT	0
+#define OMAP4_LDOSRAMCORE_ACTMODE_VSET_OUT_MASK		(0x1f << 0)
+
+/* TEMP_SENSOR */
+#define OMAP4_BGAP_TEMPSOFF_SHIFT			12
+#define OMAP4_BGAP_TEMPSOFF_MASK			(1 << 12)
+#define OMAP4_BGAP_TSHUT_SHIFT				11
+#define OMAP4_BGAP_TSHUT_MASK				(1 << 11)
+#define OMAP4_BGAP_TEMP_SENSOR_CONTCONV_SHIFT		10
+#define OMAP4_BGAP_TEMP_SENSOR_CONTCONV_MASK		(1 << 10)
+#define OMAP4_BGAP_TEMP_SENSOR_SOC_SHIFT		9
+#define OMAP4_BGAP_TEMP_SENSOR_SOC_MASK			(1 << 9)
+#define OMAP4_BGAP_TEMP_SENSOR_EOCZ_SHIFT		8
+#define OMAP4_BGAP_TEMP_SENSOR_EOCZ_MASK		(1 << 8)
+#define OMAP4_BGAP_TEMP_SENSOR_DTEMP_SHIFT		0
+#define OMAP4_BGAP_TEMP_SENSOR_DTEMP_MASK		(0xff << 0)
+
+/* DPLL_NWELL_TRIM_0 */
+#define OMAP4_DPLL_ABE_NWELL_TRIM_MUX_CTRL_SHIFT	29
+#define OMAP4_DPLL_ABE_NWELL_TRIM_MUX_CTRL_MASK		(1 << 29)
+#define OMAP4_DPLL_ABE_NWELL_TRIM_SHIFT			24
+#define OMAP4_DPLL_ABE_NWELL_TRIM_MASK			(0x1f << 24)
+#define OMAP4_DPLL_PER_NWELL_TRIM_MUX_CTRL_SHIFT	23
+#define OMAP4_DPLL_PER_NWELL_TRIM_MUX_CTRL_MASK		(1 << 23)
+#define OMAP4_DPLL_PER_NWELL_TRIM_SHIFT			18
+#define OMAP4_DPLL_PER_NWELL_TRIM_MASK			(0x1f << 18)
+#define OMAP4_DPLL_CORE_NWELL_TRIM_MUX_CTRL_SHIFT	17
+#define OMAP4_DPLL_CORE_NWELL_TRIM_MUX_CTRL_MASK	(1 << 17)
+#define OMAP4_DPLL_CORE_NWELL_TRIM_SHIFT		12
+#define OMAP4_DPLL_CORE_NWELL_TRIM_MASK			(0x1f << 12)
+#define OMAP4_DPLL_IVA_NWELL_TRIM_MUX_CTRL_SHIFT	11
+#define OMAP4_DPLL_IVA_NWELL_TRIM_MUX_CTRL_MASK		(1 << 11)
+#define OMAP4_DPLL_IVA_NWELL_TRIM_SHIFT			6
+#define OMAP4_DPLL_IVA_NWELL_TRIM_MASK			(0x1f << 6)
+#define OMAP4_DPLL_MPU_NWELL_TRIM_MUX_CTRL_SHIFT	5
+#define OMAP4_DPLL_MPU_NWELL_TRIM_MUX_CTRL_MASK		(1 << 5)
+#define OMAP4_DPLL_MPU_NWELL_TRIM_SHIFT			0
+#define OMAP4_DPLL_MPU_NWELL_TRIM_MASK			(0x1f << 0)
+
+/* DPLL_NWELL_TRIM_1 */
+#define OMAP4_DPLL_UNIPRO_NWELL_TRIM_MUX_CTRL_SHIFT	29
+#define OMAP4_DPLL_UNIPRO_NWELL_TRIM_MUX_CTRL_MASK	(1 << 29)
+#define OMAP4_DPLL_UNIPRO_NWELL_TRIM_SHIFT		24
+#define OMAP4_DPLL_UNIPRO_NWELL_TRIM_MASK		(0x1f << 24)
+#define OMAP4_DPLL_USB_NWELL_TRIM_MUX_CTRL_SHIFT	23
+#define OMAP4_DPLL_USB_NWELL_TRIM_MUX_CTRL_MASK		(1 << 23)
+#define OMAP4_DPLL_USB_NWELL_TRIM_SHIFT			18
+#define OMAP4_DPLL_USB_NWELL_TRIM_MASK			(0x1f << 18)
+#define OMAP4_DPLL_HDMI_NWELL_TRIM_MUX_CTRL_SHIFT	17
+#define OMAP4_DPLL_HDMI_NWELL_TRIM_MUX_CTRL_MASK	(1 << 17)
+#define OMAP4_DPLL_HDMI_NWELL_TRIM_SHIFT		12
+#define OMAP4_DPLL_HDMI_NWELL_TRIM_MASK			(0x1f << 12)
+#define OMAP4_DPLL_DSI2_NWELL_TRIM_MUX_CTRL_SHIFT	11
+#define OMAP4_DPLL_DSI2_NWELL_TRIM_MUX_CTRL_MASK	(1 << 11)
+#define OMAP4_DPLL_DSI2_NWELL_TRIM_SHIFT		6
+#define OMAP4_DPLL_DSI2_NWELL_TRIM_MASK			(0x1f << 6)
+#define OMAP4_DPLL_DSI1_NWELL_TRIM_MUX_CTRL_SHIFT	5
+#define OMAP4_DPLL_DSI1_NWELL_TRIM_MUX_CTRL_MASK	(1 << 5)
+#define OMAP4_DPLL_DSI1_NWELL_TRIM_SHIFT		0
+#define OMAP4_DPLL_DSI1_NWELL_TRIM_MASK			(0x1f << 0)
+
+/* USBOTGHS_CONTROL */
+#define OMAP4_DISCHRGVBUS_SHIFT				8
+#define OMAP4_DISCHRGVBUS_MASK				(1 << 8)
+#define OMAP4_CHRGVBUS_SHIFT				7
+#define OMAP4_CHRGVBUS_MASK				(1 << 7)
+#define OMAP4_DRVVBUS_SHIFT				6
+#define OMAP4_DRVVBUS_MASK				(1 << 6)
+#define OMAP4_IDPULLUP_SHIFT				5
+#define OMAP4_IDPULLUP_MASK				(1 << 5)
+#define OMAP4_IDDIG_SHIFT				4
+#define OMAP4_IDDIG_MASK				(1 << 4)
+#define OMAP4_SESSEND_SHIFT				3
+#define OMAP4_SESSEND_MASK				(1 << 3)
+#define OMAP4_VBUSVALID_SHIFT				2
+#define OMAP4_VBUSVALID_MASK				(1 << 2)
+#define OMAP4_BVALID_SHIFT				1
+#define OMAP4_BVALID_MASK				(1 << 1)
+#define OMAP4_AVALID_SHIFT				0
+#define OMAP4_AVALID_MASK				(1 << 0)
+
+/* DSS_CONTROL */
+#define OMAP4_DSS_MUX6_SELECT_SHIFT			0
+#define OMAP4_DSS_MUX6_SELECT_MASK			(1 << 0)
+
+/* HWOBS_CONTROL */
+#define OMAP4_HWOBS_CLKDIV_SEL_SHIFT			3
+#define OMAP4_HWOBS_CLKDIV_SEL_MASK			(0x1f << 3)
+#define OMAP4_HWOBS_ALL_ZERO_MODE_SHIFT			2
+#define OMAP4_HWOBS_ALL_ZERO_MODE_MASK			(1 << 2)
+#define OMAP4_HWOBS_ALL_ONE_MODE_SHIFT			1
+#define OMAP4_HWOBS_ALL_ONE_MODE_MASK			(1 << 1)
+#define OMAP4_HWOBS_MACRO_ENABLE_SHIFT			0
+#define OMAP4_HWOBS_MACRO_ENABLE_MASK			(1 << 0)
+
+/* DEBOBS_FINAL_MUX_SEL */
+#define OMAP4_SELECT_SHIFT				0
+#define OMAP4_SELECT_MASK				(0xffffffff << 0)
+
+/* DEBOBS_MMR_MPU */
+#define OMAP4_SELECT_DEBOBS_MMR_MPU_SHIFT		0
+#define OMAP4_SELECT_DEBOBS_MMR_MPU_MASK		(0xf << 0)
+
+/* CONF_SDMA_REQ_SEL0 */
+#define OMAP4_MULT_SHIFT				0
+#define OMAP4_MULT_MASK					(0x7f << 0)
+
+/* CONF_CLK_SEL0 */
+#define OMAP4_MULT_CONF_CLK_SEL0_SHIFT			0
+#define OMAP4_MULT_CONF_CLK_SEL0_MASK			(0x7 << 0)
+
+/* CONF_CLK_SEL1 */
+#define OMAP4_MULT_CONF_CLK_SEL1_SHIFT			0
+#define OMAP4_MULT_CONF_CLK_SEL1_MASK			(0x7 << 0)
+
+/* CONF_CLK_SEL2 */
+#define OMAP4_MULT_CONF_CLK_SEL2_SHIFT			0
+#define OMAP4_MULT_CONF_CLK_SEL2_MASK			(0x7 << 0)
+
+/* CONF_DPLL_FREQLOCK_SEL */
+#define OMAP4_MULT_CONF_DPLL_FREQLOCK_SEL_SHIFT		0
+#define OMAP4_MULT_CONF_DPLL_FREQLOCK_SEL_MASK		(0x7 << 0)
+
+/* CONF_DPLL_TINITZ_SEL */
+#define OMAP4_MULT_CONF_DPLL_TINITZ_SEL_SHIFT		0
+#define OMAP4_MULT_CONF_DPLL_TINITZ_SEL_MASK		(0x7 << 0)
+
+/* CONF_DPLL_PHASELOCK_SEL */
+#define OMAP4_MULT_CONF_DPLL_PHASELOCK_SEL_SHIFT	0
+#define OMAP4_MULT_CONF_DPLL_PHASELOCK_SEL_MASK		(0x7 << 0)
+
+/* CONF_DEBUG_SEL_TST_0 */
+#define OMAP4_MODE_SHIFT				0
+#define OMAP4_MODE_MASK					(0xf << 0)
+
+#endif
diff --git a/arch/arm/mach-omap2/ctrl_module_pad_core_44xx.h b/arch/arm/mach-omap2/ctrl_module_pad_core_44xx.h
new file mode 100644
index 0000000..c88420d
--- /dev/null
+++ b/arch/arm/mach-omap2/ctrl_module_pad_core_44xx.h
@@ -0,0 +1,1409 @@
+/*
+ * OMAP44xx CTRL_MODULE_PAD_CORE registers and bitfields
+ *
+ * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ *
+ * Benoit Cousson (b-cousson@ti.com)
+ * Santosh Shilimkar (santosh.shilimkar@ti.com)
+ *
+ * This file is automatically generated from the OMAP hardware databases.
+ * We respectfully ask that any modifications to this file be coordinated
+ * with the public linux-omap@vger.kernel.org mailing list and the
+ * authors above to ensure that the autogeneration scripts are kept
+ * up-to-date with the file contents.
+ *
+ * This program is free software; you can 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_CTRL_MODULE_PAD_CORE_44XX_H
+#define __ARCH_ARM_MACH_OMAP2_CTRL_MODULE_PAD_CORE_44XX_H
+
+
+/* Base address */
+#define OMAP4_CTRL_MODULE_PAD_CORE				0x4a100000
+
+/* Registers offset */
+#define OMAP4_CTRL_MODULE_PAD_CORE_IP_REVISION			0x0000
+#define OMAP4_CTRL_MODULE_PAD_CORE_IP_HWINFO			0x0004
+#define OMAP4_CTRL_MODULE_PAD_CORE_IP_SYSCONFIG			0x0010
+#define OMAP4_CTRL_MODULE_PAD_CORE_PADCONF_WAKEUPEVENT_0	0x01d8
+#define OMAP4_CTRL_MODULE_PAD_CORE_PADCONF_WAKEUPEVENT_1	0x01dc
+#define OMAP4_CTRL_MODULE_PAD_CORE_PADCONF_WAKEUPEVENT_2	0x01e0
+#define OMAP4_CTRL_MODULE_PAD_CORE_PADCONF_WAKEUPEVENT_3	0x01e4
+#define OMAP4_CTRL_MODULE_PAD_CORE_PADCONF_WAKEUPEVENT_4	0x01e8
+#define OMAP4_CTRL_MODULE_PAD_CORE_PADCONF_WAKEUPEVENT_5	0x01ec
+#define OMAP4_CTRL_MODULE_PAD_CORE_PADCONF_WAKEUPEVENT_6	0x01f0
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_PADCONF_GLOBAL	0x05a0
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_PADCONF_MODE		0x05a4
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_SMART1IO_PADCONF_0	0x05a8
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_SMART1IO_PADCONF_1	0x05ac
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_SMART2IO_PADCONF_0	0x05b0
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_SMART2IO_PADCONF_1	0x05b4
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_SMART3IO_PADCONF_0	0x05b8
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_SMART3IO_PADCONF_1	0x05bc
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_SMART3IO_PADCONF_2	0x05c0
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_USBB_HSIC		0x05c4
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_SLIMBUS		0x05c8
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_PBIASLITE		0x0600
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_I2C_0		0x0604
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_CAMERA_RX		0x0608
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_AVDAC		0x060c
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_HDMI_TX_PHY		0x0610
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_MMC2			0x0614
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_DSIPHY		0x0618
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_MCBSPLP		0x061c
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_USB2PHYCORE		0x0620
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_I2C_1		0x0624
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_MMC1			0x0628
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_HSI			0x062c
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_USB			0x0630
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_HDQ			0x0634
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO1_0		0x0638
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO1_1		0x063c
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO1_2		0x0640
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO1_3		0x0644
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO2_0		0x0648
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO2_1		0x064c
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO2_2		0x0650
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO2_3		0x0654
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_BUS_HOLD		0x0658
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_C2C			0x065c
+#define OMAP4_CTRL_MODULE_PAD_CORE_CORE_CONTROL_SPARE_RW	0x0660
+#define OMAP4_CTRL_MODULE_PAD_CORE_CORE_CONTROL_SPARE_R		0x0664
+#define OMAP4_CTRL_MODULE_PAD_CORE_CORE_CONTROL_SPARE_R_C0	0x0668
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_EFUSE_1		0x0700
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_EFUSE_2		0x0704
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_EFUSE_3		0x0708
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_EFUSE_4		0x070c
+
+/* Registers shifts and masks */
+
+/* IP_REVISION */
+#define OMAP4_IP_REV_SCHEME_SHIFT				30
+#define OMAP4_IP_REV_SCHEME_MASK				(0x3 << 30)
+#define OMAP4_IP_REV_FUNC_SHIFT					16
+#define OMAP4_IP_REV_FUNC_MASK					(0xfff << 16)
+#define OMAP4_IP_REV_RTL_SHIFT					11
+#define OMAP4_IP_REV_RTL_MASK					(0x1f << 11)
+#define OMAP4_IP_REV_MAJOR_SHIFT				8
+#define OMAP4_IP_REV_MAJOR_MASK					(0x7 << 8)
+#define OMAP4_IP_REV_CUSTOM_SHIFT				6
+#define OMAP4_IP_REV_CUSTOM_MASK				(0x3 << 6)
+#define OMAP4_IP_REV_MINOR_SHIFT				0
+#define OMAP4_IP_REV_MINOR_MASK					(0x3f << 0)
+
+/* IP_HWINFO */
+#define OMAP4_IP_HWINFO_SHIFT					0
+#define OMAP4_IP_HWINFO_MASK					(0xffffffff << 0)
+
+/* IP_SYSCONFIG */
+#define OMAP4_IP_SYSCONFIG_IDLEMODE_SHIFT			2
+#define OMAP4_IP_SYSCONFIG_IDLEMODE_MASK			(0x3 << 2)
+
+/* PADCONF_WAKEUPEVENT_0 */
+#define OMAP4_GPMC_CLK_DUPLICATEWAKEUPEVENT_SHIFT		31
+#define OMAP4_GPMC_CLK_DUPLICATEWAKEUPEVENT_MASK		(1 << 31)
+#define OMAP4_GPMC_NWP_DUPLICATEWAKEUPEVENT_SHIFT		30
+#define OMAP4_GPMC_NWP_DUPLICATEWAKEUPEVENT_MASK		(1 << 30)
+#define OMAP4_GPMC_NCS3_DUPLICATEWAKEUPEVENT_SHIFT		29
+#define OMAP4_GPMC_NCS3_DUPLICATEWAKEUPEVENT_MASK		(1 << 29)
+#define OMAP4_GPMC_NCS2_DUPLICATEWAKEUPEVENT_SHIFT		28
+#define OMAP4_GPMC_NCS2_DUPLICATEWAKEUPEVENT_MASK		(1 << 28)
+#define OMAP4_GPMC_NCS1_DUPLICATEWAKEUPEVENT_SHIFT		27
+#define OMAP4_GPMC_NCS1_DUPLICATEWAKEUPEVENT_MASK		(1 << 27)
+#define OMAP4_GPMC_NCS0_DUPLICATEWAKEUPEVENT_SHIFT		26
+#define OMAP4_GPMC_NCS0_DUPLICATEWAKEUPEVENT_MASK		(1 << 26)
+#define OMAP4_GPMC_A25_DUPLICATEWAKEUPEVENT_SHIFT		25
+#define OMAP4_GPMC_A25_DUPLICATEWAKEUPEVENT_MASK		(1 << 25)
+#define OMAP4_GPMC_A24_DUPLICATEWAKEUPEVENT_SHIFT		24
+#define OMAP4_GPMC_A24_DUPLICATEWAKEUPEVENT_MASK		(1 << 24)
+#define OMAP4_GPMC_A23_DUPLICATEWAKEUPEVENT_SHIFT		23
+#define OMAP4_GPMC_A23_DUPLICATEWAKEUPEVENT_MASK		(1 << 23)
+#define OMAP4_GPMC_A22_DUPLICATEWAKEUPEVENT_SHIFT		22
+#define OMAP4_GPMC_A22_DUPLICATEWAKEUPEVENT_MASK		(1 << 22)
+#define OMAP4_GPMC_A21_DUPLICATEWAKEUPEVENT_SHIFT		21
+#define OMAP4_GPMC_A21_DUPLICATEWAKEUPEVENT_MASK		(1 << 21)
+#define OMAP4_GPMC_A20_DUPLICATEWAKEUPEVENT_SHIFT		20
+#define OMAP4_GPMC_A20_DUPLICATEWAKEUPEVENT_MASK		(1 << 20)
+#define OMAP4_GPMC_A19_DUPLICATEWAKEUPEVENT_SHIFT		19
+#define OMAP4_GPMC_A19_DUPLICATEWAKEUPEVENT_MASK		(1 << 19)
+#define OMAP4_GPMC_A18_DUPLICATEWAKEUPEVENT_SHIFT		18
+#define OMAP4_GPMC_A18_DUPLICATEWAKEUPEVENT_MASK		(1 << 18)
+#define OMAP4_GPMC_A17_DUPLICATEWAKEUPEVENT_SHIFT		17
+#define OMAP4_GPMC_A17_DUPLICATEWAKEUPEVENT_MASK		(1 << 17)
+#define OMAP4_GPMC_A16_DUPLICATEWAKEUPEVENT_SHIFT		16
+#define OMAP4_GPMC_A16_DUPLICATEWAKEUPEVENT_MASK		(1 << 16)
+#define OMAP4_GPMC_AD15_DUPLICATEWAKEUPEVENT_SHIFT		15
+#define OMAP4_GPMC_AD15_DUPLICATEWAKEUPEVENT_MASK		(1 << 15)
+#define OMAP4_GPMC_AD14_DUPLICATEWAKEUPEVENT_SHIFT		14
+#define OMAP4_GPMC_AD14_DUPLICATEWAKEUPEVENT_MASK		(1 << 14)
+#define OMAP4_GPMC_AD13_DUPLICATEWAKEUPEVENT_SHIFT		13
+#define OMAP4_GPMC_AD13_DUPLICATEWAKEUPEVENT_MASK		(1 << 13)
+#define OMAP4_GPMC_AD12_DUPLICATEWAKEUPEVENT_SHIFT		12
+#define OMAP4_GPMC_AD12_DUPLICATEWAKEUPEVENT_MASK		(1 << 12)
+#define OMAP4_GPMC_AD11_DUPLICATEWAKEUPEVENT_SHIFT		11
+#define OMAP4_GPMC_AD11_DUPLICATEWAKEUPEVENT_MASK		(1 << 11)
+#define OMAP4_GPMC_AD10_DUPLICATEWAKEUPEVENT_SHIFT		10
+#define OMAP4_GPMC_AD10_DUPLICATEWAKEUPEVENT_MASK		(1 << 10)
+#define OMAP4_GPMC_AD9_DUPLICATEWAKEUPEVENT_SHIFT		9
+#define OMAP4_GPMC_AD9_DUPLICATEWAKEUPEVENT_MASK		(1 << 9)
+#define OMAP4_GPMC_AD8_DUPLICATEWAKEUPEVENT_SHIFT		8
+#define OMAP4_GPMC_AD8_DUPLICATEWAKEUPEVENT_MASK		(1 << 8)
+#define OMAP4_GPMC_AD7_DUPLICATEWAKEUPEVENT_SHIFT		7
+#define OMAP4_GPMC_AD7_DUPLICATEWAKEUPEVENT_MASK		(1 << 7)
+#define OMAP4_GPMC_AD6_DUPLICATEWAKEUPEVENT_SHIFT		6
+#define OMAP4_GPMC_AD6_DUPLICATEWAKEUPEVENT_MASK		(1 << 6)
+#define OMAP4_GPMC_AD5_DUPLICATEWAKEUPEVENT_SHIFT		5
+#define OMAP4_GPMC_AD5_DUPLICATEWAKEUPEVENT_MASK		(1 << 5)
+#define OMAP4_GPMC_AD4_DUPLICATEWAKEUPEVENT_SHIFT		4
+#define OMAP4_GPMC_AD4_DUPLICATEWAKEUPEVENT_MASK		(1 << 4)
+#define OMAP4_GPMC_AD3_DUPLICATEWAKEUPEVENT_SHIFT		3
+#define OMAP4_GPMC_AD3_DUPLICATEWAKEUPEVENT_MASK		(1 << 3)
+#define OMAP4_GPMC_AD2_DUPLICATEWAKEUPEVENT_SHIFT		2
+#define OMAP4_GPMC_AD2_DUPLICATEWAKEUPEVENT_MASK		(1 << 2)
+#define OMAP4_GPMC_AD1_DUPLICATEWAKEUPEVENT_SHIFT		1
+#define OMAP4_GPMC_AD1_DUPLICATEWAKEUPEVENT_MASK		(1 << 1)
+#define OMAP4_GPMC_AD0_DUPLICATEWAKEUPEVENT_SHIFT		0
+#define OMAP4_GPMC_AD0_DUPLICATEWAKEUPEVENT_MASK		(1 << 0)
+
+/* PADCONF_WAKEUPEVENT_1 */
+#define OMAP4_CAM_STROBE_DUPLICATEWAKEUPEVENT_SHIFT		31
+#define OMAP4_CAM_STROBE_DUPLICATEWAKEUPEVENT_MASK		(1 << 31)
+#define OMAP4_CAM_SHUTTER_DUPLICATEWAKEUPEVENT_SHIFT		30
+#define OMAP4_CAM_SHUTTER_DUPLICATEWAKEUPEVENT_MASK		(1 << 30)
+#define OMAP4_CSI22_DY1_DUPLICATEWAKEUPEVENT_SHIFT		29
+#define OMAP4_CSI22_DY1_DUPLICATEWAKEUPEVENT_MASK		(1 << 29)
+#define OMAP4_CSI22_DX1_DUPLICATEWAKEUPEVENT_SHIFT		28
+#define OMAP4_CSI22_DX1_DUPLICATEWAKEUPEVENT_MASK		(1 << 28)
+#define OMAP4_CSI22_DY0_DUPLICATEWAKEUPEVENT_SHIFT		27
+#define OMAP4_CSI22_DY0_DUPLICATEWAKEUPEVENT_MASK		(1 << 27)
+#define OMAP4_CSI22_DX0_DUPLICATEWAKEUPEVENT_SHIFT		26
+#define OMAP4_CSI22_DX0_DUPLICATEWAKEUPEVENT_MASK		(1 << 26)
+#define OMAP4_CSI21_DY4_DUPLICATEWAKEUPEVENT_SHIFT		25
+#define OMAP4_CSI21_DY4_DUPLICATEWAKEUPEVENT_MASK		(1 << 25)
+#define OMAP4_CSI21_DX4_DUPLICATEWAKEUPEVENT_SHIFT		24
+#define OMAP4_CSI21_DX4_DUPLICATEWAKEUPEVENT_MASK		(1 << 24)
+#define OMAP4_CSI21_DY3_DUPLICATEWAKEUPEVENT_SHIFT		23
+#define OMAP4_CSI21_DY3_DUPLICATEWAKEUPEVENT_MASK		(1 << 23)
+#define OMAP4_CSI21_DX3_DUPLICATEWAKEUPEVENT_SHIFT		22
+#define OMAP4_CSI21_DX3_DUPLICATEWAKEUPEVENT_MASK		(1 << 22)
+#define OMAP4_CSI21_DY2_DUPLICATEWAKEUPEVENT_SHIFT		21
+#define OMAP4_CSI21_DY2_DUPLICATEWAKEUPEVENT_MASK		(1 << 21)
+#define OMAP4_CSI21_DX2_DUPLICATEWAKEUPEVENT_SHIFT		20
+#define OMAP4_CSI21_DX2_DUPLICATEWAKEUPEVENT_MASK		(1 << 20)
+#define OMAP4_CSI21_DY1_DUPLICATEWAKEUPEVENT_SHIFT		19
+#define OMAP4_CSI21_DY1_DUPLICATEWAKEUPEVENT_MASK		(1 << 19)
+#define OMAP4_CSI21_DX1_DUPLICATEWAKEUPEVENT_SHIFT		18
+#define OMAP4_CSI21_DX1_DUPLICATEWAKEUPEVENT_MASK		(1 << 18)
+#define OMAP4_CSI21_DY0_DUPLICATEWAKEUPEVENT_SHIFT		17
+#define OMAP4_CSI21_DY0_DUPLICATEWAKEUPEVENT_MASK		(1 << 17)
+#define OMAP4_CSI21_DX0_DUPLICATEWAKEUPEVENT_SHIFT		16
+#define OMAP4_CSI21_DX0_DUPLICATEWAKEUPEVENT_MASK		(1 << 16)
+#define OMAP4_HDMI_DDC_SDA_DUPLICATEWAKEUPEVENT_SHIFT		15
+#define OMAP4_HDMI_DDC_SDA_DUPLICATEWAKEUPEVENT_MASK		(1 << 15)
+#define OMAP4_HDMI_DDC_SCL_DUPLICATEWAKEUPEVENT_SHIFT		14
+#define OMAP4_HDMI_DDC_SCL_DUPLICATEWAKEUPEVENT_MASK		(1 << 14)
+#define OMAP4_HDMI_CEC_DUPLICATEWAKEUPEVENT_SHIFT		13
+#define OMAP4_HDMI_CEC_DUPLICATEWAKEUPEVENT_MASK		(1 << 13)
+#define OMAP4_HDMI_HPD_DUPLICATEWAKEUPEVENT_SHIFT		12
+#define OMAP4_HDMI_HPD_DUPLICATEWAKEUPEVENT_MASK		(1 << 12)
+#define OMAP4_C2C_DATA15_DUPLICATEWAKEUPEVENT_SHIFT		11
+#define OMAP4_C2C_DATA15_DUPLICATEWAKEUPEVENT_MASK		(1 << 11)
+#define OMAP4_C2C_DATA14_DUPLICATEWAKEUPEVENT_SHIFT		10
+#define OMAP4_C2C_DATA14_DUPLICATEWAKEUPEVENT_MASK		(1 << 10)
+#define OMAP4_C2C_DATA13_DUPLICATEWAKEUPEVENT_SHIFT		9
+#define OMAP4_C2C_DATA13_DUPLICATEWAKEUPEVENT_MASK		(1 << 9)
+#define OMAP4_C2C_DATA12_DUPLICATEWAKEUPEVENT_SHIFT		8
+#define OMAP4_C2C_DATA12_DUPLICATEWAKEUPEVENT_MASK		(1 << 8)
+#define OMAP4_C2C_DATA11_DUPLICATEWAKEUPEVENT_SHIFT		7
+#define OMAP4_C2C_DATA11_DUPLICATEWAKEUPEVENT_MASK		(1 << 7)
+#define OMAP4_GPMC_WAIT1_DUPLICATEWAKEUPEVENT_SHIFT		6
+#define OMAP4_GPMC_WAIT1_DUPLICATEWAKEUPEVENT_MASK		(1 << 6)
+#define OMAP4_GPMC_WAIT0_DUPLICATEWAKEUPEVENT_SHIFT		5
+#define OMAP4_GPMC_WAIT0_DUPLICATEWAKEUPEVENT_MASK		(1 << 5)
+#define OMAP4_GPMC_NBE1_DUPLICATEWAKEUPEVENT_SHIFT		4
+#define OMAP4_GPMC_NBE1_DUPLICATEWAKEUPEVENT_MASK		(1 << 4)
+#define OMAP4_GPMC_NBE0_CLE_DUPLICATEWAKEUPEVENT_SHIFT		3
+#define OMAP4_GPMC_NBE0_CLE_DUPLICATEWAKEUPEVENT_MASK		(1 << 3)
+#define OMAP4_GPMC_NWE_DUPLICATEWAKEUPEVENT_SHIFT		2
+#define OMAP4_GPMC_NWE_DUPLICATEWAKEUPEVENT_MASK		(1 << 2)
+#define OMAP4_GPMC_NOE_DUPLICATEWAKEUPEVENT_SHIFT		1
+#define OMAP4_GPMC_NOE_DUPLICATEWAKEUPEVENT_MASK		(1 << 1)
+#define OMAP4_GPMC_NADV_ALE_DUPLICATEWAKEUPEVENT_SHIFT		0
+#define OMAP4_GPMC_NADV_ALE_DUPLICATEWAKEUPEVENT_MASK		(1 << 0)
+
+/* PADCONF_WAKEUPEVENT_2 */
+#define OMAP4_ABE_MCBSP1_CLKX_DUPLICATEWAKEUPEVENT_SHIFT	31
+#define OMAP4_ABE_MCBSP1_CLKX_DUPLICATEWAKEUPEVENT_MASK		(1 << 31)
+#define OMAP4_ABE_MCBSP2_FSX_DUPLICATEWAKEUPEVENT_SHIFT		30
+#define OMAP4_ABE_MCBSP2_FSX_DUPLICATEWAKEUPEVENT_MASK		(1 << 30)
+#define OMAP4_ABE_MCBSP2_DX_DUPLICATEWAKEUPEVENT_SHIFT		29
+#define OMAP4_ABE_MCBSP2_DX_DUPLICATEWAKEUPEVENT_MASK		(1 << 29)
+#define OMAP4_ABE_MCBSP2_DR_DUPLICATEWAKEUPEVENT_SHIFT		28
+#define OMAP4_ABE_MCBSP2_DR_DUPLICATEWAKEUPEVENT_MASK		(1 << 28)
+#define OMAP4_ABE_MCBSP2_CLKX_DUPLICATEWAKEUPEVENT_SHIFT	27
+#define OMAP4_ABE_MCBSP2_CLKX_DUPLICATEWAKEUPEVENT_MASK		(1 << 27)
+#define OMAP4_SDMMC1_DAT7_DUPLICATEWAKEUPEVENT_SHIFT		26
+#define OMAP4_SDMMC1_DAT7_DUPLICATEWAKEUPEVENT_MASK		(1 << 26)
+#define OMAP4_SDMMC1_DAT6_DUPLICATEWAKEUPEVENT_SHIFT		25
+#define OMAP4_SDMMC1_DAT6_DUPLICATEWAKEUPEVENT_MASK		(1 << 25)
+#define OMAP4_SDMMC1_DAT5_DUPLICATEWAKEUPEVENT_SHIFT		24
+#define OMAP4_SDMMC1_DAT5_DUPLICATEWAKEUPEVENT_MASK		(1 << 24)
+#define OMAP4_SDMMC1_DAT4_DUPLICATEWAKEUPEVENT_SHIFT		23
+#define OMAP4_SDMMC1_DAT4_DUPLICATEWAKEUPEVENT_MASK		(1 << 23)
+#define OMAP4_SDMMC1_DAT3_DUPLICATEWAKEUPEVENT_SHIFT		22
+#define OMAP4_SDMMC1_DAT3_DUPLICATEWAKEUPEVENT_MASK		(1 << 22)
+#define OMAP4_SDMMC1_DAT2_DUPLICATEWAKEUPEVENT_SHIFT		21
+#define OMAP4_SDMMC1_DAT2_DUPLICATEWAKEUPEVENT_MASK		(1 << 21)
+#define OMAP4_SDMMC1_DAT1_DUPLICATEWAKEUPEVENT_SHIFT		20
+#define OMAP4_SDMMC1_DAT1_DUPLICATEWAKEUPEVENT_MASK		(1 << 20)
+#define OMAP4_SDMMC1_DAT0_DUPLICATEWAKEUPEVENT_SHIFT		19
+#define OMAP4_SDMMC1_DAT0_DUPLICATEWAKEUPEVENT_MASK		(1 << 19)
+#define OMAP4_SDMMC1_CMD_DUPLICATEWAKEUPEVENT_SHIFT		18
+#define OMAP4_SDMMC1_CMD_DUPLICATEWAKEUPEVENT_MASK		(1 << 18)
+#define OMAP4_SDMMC1_CLK_DUPLICATEWAKEUPEVENT_SHIFT		17
+#define OMAP4_SDMMC1_CLK_DUPLICATEWAKEUPEVENT_MASK		(1 << 17)
+#define OMAP4_USBC1_ICUSB_DM_DUPLICATEWAKEUPEVENT_SHIFT		16
+#define OMAP4_USBC1_ICUSB_DM_DUPLICATEWAKEUPEVENT_MASK		(1 << 16)
+#define OMAP4_USBC1_ICUSB_DP_DUPLICATEWAKEUPEVENT_SHIFT		15
+#define OMAP4_USBC1_ICUSB_DP_DUPLICATEWAKEUPEVENT_MASK		(1 << 15)
+#define OMAP4_USBB1_HSIC_STROBE_DUPLICATEWAKEUPEVENT_SHIFT	14
+#define OMAP4_USBB1_HSIC_STROBE_DUPLICATEWAKEUPEVENT_MASK	(1 << 14)
+#define OMAP4_USBB1_HSIC_DATA_DUPLICATEWAKEUPEVENT_SHIFT	13
+#define OMAP4_USBB1_HSIC_DATA_DUPLICATEWAKEUPEVENT_MASK		(1 << 13)
+#define OMAP4_USBB1_ULPITLL_DAT7_DUPLICATEWAKEUPEVENT_SHIFT	12
+#define OMAP4_USBB1_ULPITLL_DAT7_DUPLICATEWAKEUPEVENT_MASK	(1 << 12)
+#define OMAP4_USBB1_ULPITLL_DAT6_DUPLICATEWAKEUPEVENT_SHIFT	11
+#define OMAP4_USBB1_ULPITLL_DAT6_DUPLICATEWAKEUPEVENT_MASK	(1 << 11)
+#define OMAP4_USBB1_ULPITLL_DAT5_DUPLICATEWAKEUPEVENT_SHIFT	10
+#define OMAP4_USBB1_ULPITLL_DAT5_DUPLICATEWAKEUPEVENT_MASK	(1 << 10)
+#define OMAP4_USBB1_ULPITLL_DAT4_DUPLICATEWAKEUPEVENT_SHIFT	9
+#define OMAP4_USBB1_ULPITLL_DAT4_DUPLICATEWAKEUPEVENT_MASK	(1 << 9)
+#define OMAP4_USBB1_ULPITLL_DAT3_DUPLICATEWAKEUPEVENT_SHIFT	8
+#define OMAP4_USBB1_ULPITLL_DAT3_DUPLICATEWAKEUPEVENT_MASK	(1 << 8)
+#define OMAP4_USBB1_ULPITLL_DAT2_DUPLICATEWAKEUPEVENT_SHIFT	7
+#define OMAP4_USBB1_ULPITLL_DAT2_DUPLICATEWAKEUPEVENT_MASK	(1 << 7)
+#define OMAP4_USBB1_ULPITLL_DAT1_DUPLICATEWAKEUPEVENT_SHIFT	6
+#define OMAP4_USBB1_ULPITLL_DAT1_DUPLICATEWAKEUPEVENT_MASK	(1 << 6)
+#define OMAP4_USBB1_ULPITLL_DAT0_DUPLICATEWAKEUPEVENT_SHIFT	5
+#define OMAP4_USBB1_ULPITLL_DAT0_DUPLICATEWAKEUPEVENT_MASK	(1 << 5)
+#define OMAP4_USBB1_ULPITLL_NXT_DUPLICATEWAKEUPEVENT_SHIFT	4
+#define OMAP4_USBB1_ULPITLL_NXT_DUPLICATEWAKEUPEVENT_MASK	(1 << 4)
+#define OMAP4_USBB1_ULPITLL_DIR_DUPLICATEWAKEUPEVENT_SHIFT	3
+#define OMAP4_USBB1_ULPITLL_DIR_DUPLICATEWAKEUPEVENT_MASK	(1 << 3)
+#define OMAP4_USBB1_ULPITLL_STP_DUPLICATEWAKEUPEVENT_SHIFT	2
+#define OMAP4_USBB1_ULPITLL_STP_DUPLICATEWAKEUPEVENT_MASK	(1 << 2)
+#define OMAP4_USBB1_ULPITLL_CLK_DUPLICATEWAKEUPEVENT_SHIFT	1
+#define OMAP4_USBB1_ULPITLL_CLK_DUPLICATEWAKEUPEVENT_MASK	(1 << 1)
+#define OMAP4_CAM_GLOBALRESET_DUPLICATEWAKEUPEVENT_SHIFT	0
+#define OMAP4_CAM_GLOBALRESET_DUPLICATEWAKEUPEVENT_MASK		(1 << 0)
+
+/* PADCONF_WAKEUPEVENT_3 */
+#define OMAP4_MCSPI1_CS3_DUPLICATEWAKEUPEVENT_SHIFT		31
+#define OMAP4_MCSPI1_CS3_DUPLICATEWAKEUPEVENT_MASK		(1 << 31)
+#define OMAP4_MCSPI1_CS2_DUPLICATEWAKEUPEVENT_SHIFT		30
+#define OMAP4_MCSPI1_CS2_DUPLICATEWAKEUPEVENT_MASK		(1 << 30)
+#define OMAP4_MCSPI1_CS1_DUPLICATEWAKEUPEVENT_SHIFT		29
+#define OMAP4_MCSPI1_CS1_DUPLICATEWAKEUPEVENT_MASK		(1 << 29)
+#define OMAP4_MCSPI1_CS0_DUPLICATEWAKEUPEVENT_SHIFT		28
+#define OMAP4_MCSPI1_CS0_DUPLICATEWAKEUPEVENT_MASK		(1 << 28)
+#define OMAP4_MCSPI1_SIMO_DUPLICATEWAKEUPEVENT_SHIFT		27
+#define OMAP4_MCSPI1_SIMO_DUPLICATEWAKEUPEVENT_MASK		(1 << 27)
+#define OMAP4_MCSPI1_SOMI_DUPLICATEWAKEUPEVENT_SHIFT		26
+#define OMAP4_MCSPI1_SOMI_DUPLICATEWAKEUPEVENT_MASK		(1 << 26)
+#define OMAP4_MCSPI1_CLK_DUPLICATEWAKEUPEVENT_SHIFT		25
+#define OMAP4_MCSPI1_CLK_DUPLICATEWAKEUPEVENT_MASK		(1 << 25)
+#define OMAP4_I2C4_SDA_DUPLICATEWAKEUPEVENT_SHIFT		24
+#define OMAP4_I2C4_SDA_DUPLICATEWAKEUPEVENT_MASK		(1 << 24)
+#define OMAP4_I2C4_SCL_DUPLICATEWAKEUPEVENT_SHIFT		23
+#define OMAP4_I2C4_SCL_DUPLICATEWAKEUPEVENT_MASK		(1 << 23)
+#define OMAP4_I2C3_SDA_DUPLICATEWAKEUPEVENT_SHIFT		22
+#define OMAP4_I2C3_SDA_DUPLICATEWAKEUPEVENT_MASK		(1 << 22)
+#define OMAP4_I2C3_SCL_DUPLICATEWAKEUPEVENT_SHIFT		21
+#define OMAP4_I2C3_SCL_DUPLICATEWAKEUPEVENT_MASK		(1 << 21)
+#define OMAP4_I2C2_SDA_DUPLICATEWAKEUPEVENT_SHIFT		20
+#define OMAP4_I2C2_SDA_DUPLICATEWAKEUPEVENT_MASK		(1 << 20)
+#define OMAP4_I2C2_SCL_DUPLICATEWAKEUPEVENT_SHIFT		19
+#define OMAP4_I2C2_SCL_DUPLICATEWAKEUPEVENT_MASK		(1 << 19)
+#define OMAP4_I2C1_SDA_DUPLICATEWAKEUPEVENT_SHIFT		18
+#define OMAP4_I2C1_SDA_DUPLICATEWAKEUPEVENT_MASK		(1 << 18)
+#define OMAP4_I2C1_SCL_DUPLICATEWAKEUPEVENT_SHIFT		17
+#define OMAP4_I2C1_SCL_DUPLICATEWAKEUPEVENT_MASK		(1 << 17)
+#define OMAP4_HDQ_SIO_DUPLICATEWAKEUPEVENT_SHIFT		16
+#define OMAP4_HDQ_SIO_DUPLICATEWAKEUPEVENT_MASK			(1 << 16)
+#define OMAP4_UART2_TX_DUPLICATEWAKEUPEVENT_SHIFT		15
+#define OMAP4_UART2_TX_DUPLICATEWAKEUPEVENT_MASK		(1 << 15)
+#define OMAP4_UART2_RX_DUPLICATEWAKEUPEVENT_SHIFT		14
+#define OMAP4_UART2_RX_DUPLICATEWAKEUPEVENT_MASK		(1 << 14)
+#define OMAP4_UART2_RTS_DUPLICATEWAKEUPEVENT_SHIFT		13
+#define OMAP4_UART2_RTS_DUPLICATEWAKEUPEVENT_MASK		(1 << 13)
+#define OMAP4_UART2_CTS_DUPLICATEWAKEUPEVENT_SHIFT		12
+#define OMAP4_UART2_CTS_DUPLICATEWAKEUPEVENT_MASK		(1 << 12)
+#define OMAP4_ABE_DMIC_DIN3_DUPLICATEWAKEUPEVENT_SHIFT		11
+#define OMAP4_ABE_DMIC_DIN3_DUPLICATEWAKEUPEVENT_MASK		(1 << 11)
+#define OMAP4_ABE_DMIC_DIN2_DUPLICATEWAKEUPEVENT_SHIFT		10
+#define OMAP4_ABE_DMIC_DIN2_DUPLICATEWAKEUPEVENT_MASK		(1 << 10)
+#define OMAP4_ABE_DMIC_DIN1_DUPLICATEWAKEUPEVENT_SHIFT		9
+#define OMAP4_ABE_DMIC_DIN1_DUPLICATEWAKEUPEVENT_MASK		(1 << 9)
+#define OMAP4_ABE_DMIC_CLK1_DUPLICATEWAKEUPEVENT_SHIFT		8
+#define OMAP4_ABE_DMIC_CLK1_DUPLICATEWAKEUPEVENT_MASK		(1 << 8)
+#define OMAP4_ABE_CLKS_DUPLICATEWAKEUPEVENT_SHIFT		7
+#define OMAP4_ABE_CLKS_DUPLICATEWAKEUPEVENT_MASK		(1 << 7)
+#define OMAP4_ABE_PDM_LB_CLK_DUPLICATEWAKEUPEVENT_SHIFT		6
+#define OMAP4_ABE_PDM_LB_CLK_DUPLICATEWAKEUPEVENT_MASK		(1 << 6)
+#define OMAP4_ABE_PDM_FRAME_DUPLICATEWAKEUPEVENT_SHIFT		5
+#define OMAP4_ABE_PDM_FRAME_DUPLICATEWAKEUPEVENT_MASK		(1 << 5)
+#define OMAP4_ABE_PDM_DL_DATA_DUPLICATEWAKEUPEVENT_SHIFT	4
+#define OMAP4_ABE_PDM_DL_DATA_DUPLICATEWAKEUPEVENT_MASK		(1 << 4)
+#define OMAP4_ABE_PDM_UL_DATA_DUPLICATEWAKEUPEVENT_SHIFT	3
+#define OMAP4_ABE_PDM_UL_DATA_DUPLICATEWAKEUPEVENT_MASK		(1 << 3)
+#define OMAP4_ABE_MCBSP1_FSX_DUPLICATEWAKEUPEVENT_SHIFT		2
+#define OMAP4_ABE_MCBSP1_FSX_DUPLICATEWAKEUPEVENT_MASK		(1 << 2)
+#define OMAP4_ABE_MCBSP1_DX_DUPLICATEWAKEUPEVENT_SHIFT		1
+#define OMAP4_ABE_MCBSP1_DX_DUPLICATEWAKEUPEVENT_MASK		(1 << 1)
+#define OMAP4_ABE_MCBSP1_DR_DUPLICATEWAKEUPEVENT_SHIFT		0
+#define OMAP4_ABE_MCBSP1_DR_DUPLICATEWAKEUPEVENT_MASK		(1 << 0)
+
+/* PADCONF_WAKEUPEVENT_4 */
+#define OMAP4_UNIPRO_TY0_DUPLICATEWAKEUPEVENT_SHIFT		31
+#define OMAP4_UNIPRO_TY0_DUPLICATEWAKEUPEVENT_MASK		(1 << 31)
+#define OMAP4_UNIPRO_TX0_DUPLICATEWAKEUPEVENT_SHIFT		30
+#define OMAP4_UNIPRO_TX0_DUPLICATEWAKEUPEVENT_MASK		(1 << 30)
+#define OMAP4_USBB2_HSIC_STROBE_DUPLICATEWAKEUPEVENT_SHIFT	29
+#define OMAP4_USBB2_HSIC_STROBE_DUPLICATEWAKEUPEVENT_MASK	(1 << 29)
+#define OMAP4_USBB2_HSIC_DATA_DUPLICATEWAKEUPEVENT_SHIFT	28
+#define OMAP4_USBB2_HSIC_DATA_DUPLICATEWAKEUPEVENT_MASK		(1 << 28)
+#define OMAP4_USBB2_ULPITLL_DAT7_DUPLICATEWAKEUPEVENT_SHIFT	27
+#define OMAP4_USBB2_ULPITLL_DAT7_DUPLICATEWAKEUPEVENT_MASK	(1 << 27)
+#define OMAP4_USBB2_ULPITLL_DAT6_DUPLICATEWAKEUPEVENT_SHIFT	26
+#define OMAP4_USBB2_ULPITLL_DAT6_DUPLICATEWAKEUPEVENT_MASK	(1 << 26)
+#define OMAP4_USBB2_ULPITLL_DAT5_DUPLICATEWAKEUPEVENT_SHIFT	25
+#define OMAP4_USBB2_ULPITLL_DAT5_DUPLICATEWAKEUPEVENT_MASK	(1 << 25)
+#define OMAP4_USBB2_ULPITLL_DAT4_DUPLICATEWAKEUPEVENT_SHIFT	24
+#define OMAP4_USBB2_ULPITLL_DAT4_DUPLICATEWAKEUPEVENT_MASK	(1 << 24)
+#define OMAP4_USBB2_ULPITLL_DAT3_DUPLICATEWAKEUPEVENT_SHIFT	23
+#define OMAP4_USBB2_ULPITLL_DAT3_DUPLICATEWAKEUPEVENT_MASK	(1 << 23)
+#define OMAP4_USBB2_ULPITLL_DAT2_DUPLICATEWAKEUPEVENT_SHIFT	22
+#define OMAP4_USBB2_ULPITLL_DAT2_DUPLICATEWAKEUPEVENT_MASK	(1 << 22)
+#define OMAP4_USBB2_ULPITLL_DAT1_DUPLICATEWAKEUPEVENT_SHIFT	21
+#define OMAP4_USBB2_ULPITLL_DAT1_DUPLICATEWAKEUPEVENT_MASK	(1 << 21)
+#define OMAP4_USBB2_ULPITLL_DAT0_DUPLICATEWAKEUPEVENT_SHIFT	20
+#define OMAP4_USBB2_ULPITLL_DAT0_DUPLICATEWAKEUPEVENT_MASK	(1 << 20)
+#define OMAP4_USBB2_ULPITLL_NXT_DUPLICATEWAKEUPEVENT_SHIFT	19
+#define OMAP4_USBB2_ULPITLL_NXT_DUPLICATEWAKEUPEVENT_MASK	(1 << 19)
+#define OMAP4_USBB2_ULPITLL_DIR_DUPLICATEWAKEUPEVENT_SHIFT	18
+#define OMAP4_USBB2_ULPITLL_DIR_DUPLICATEWAKEUPEVENT_MASK	(1 << 18)
+#define OMAP4_USBB2_ULPITLL_STP_DUPLICATEWAKEUPEVENT_SHIFT	17
+#define OMAP4_USBB2_ULPITLL_STP_DUPLICATEWAKEUPEVENT_MASK	(1 << 17)
+#define OMAP4_USBB2_ULPITLL_CLK_DUPLICATEWAKEUPEVENT_SHIFT	16
+#define OMAP4_USBB2_ULPITLL_CLK_DUPLICATEWAKEUPEVENT_MASK	(1 << 16)
+#define OMAP4_UART4_TX_DUPLICATEWAKEUPEVENT_SHIFT		15
+#define OMAP4_UART4_TX_DUPLICATEWAKEUPEVENT_MASK		(1 << 15)
+#define OMAP4_UART4_RX_DUPLICATEWAKEUPEVENT_SHIFT		14
+#define OMAP4_UART4_RX_DUPLICATEWAKEUPEVENT_MASK		(1 << 14)
+#define OMAP4_MCSPI4_CS0_DUPLICATEWAKEUPEVENT_SHIFT		13
+#define OMAP4_MCSPI4_CS0_DUPLICATEWAKEUPEVENT_MASK		(1 << 13)
+#define OMAP4_MCSPI4_SOMI_DUPLICATEWAKEUPEVENT_SHIFT		12
+#define OMAP4_MCSPI4_SOMI_DUPLICATEWAKEUPEVENT_MASK		(1 << 12)
+#define OMAP4_MCSPI4_SIMO_DUPLICATEWAKEUPEVENT_SHIFT		11
+#define OMAP4_MCSPI4_SIMO_DUPLICATEWAKEUPEVENT_MASK		(1 << 11)
+#define OMAP4_MCSPI4_CLK_DUPLICATEWAKEUPEVENT_SHIFT		10
+#define OMAP4_MCSPI4_CLK_DUPLICATEWAKEUPEVENT_MASK		(1 << 10)
+#define OMAP4_SDMMC5_DAT3_DUPLICATEWAKEUPEVENT_SHIFT		9
+#define OMAP4_SDMMC5_DAT3_DUPLICATEWAKEUPEVENT_MASK		(1 << 9)
+#define OMAP4_SDMMC5_DAT2_DUPLICATEWAKEUPEVENT_SHIFT		8
+#define OMAP4_SDMMC5_DAT2_DUPLICATEWAKEUPEVENT_MASK		(1 << 8)
+#define OMAP4_SDMMC5_DAT1_DUPLICATEWAKEUPEVENT_SHIFT		7
+#define OMAP4_SDMMC5_DAT1_DUPLICATEWAKEUPEVENT_MASK		(1 << 7)
+#define OMAP4_SDMMC5_DAT0_DUPLICATEWAKEUPEVENT_SHIFT		6
+#define OMAP4_SDMMC5_DAT0_DUPLICATEWAKEUPEVENT_MASK		(1 << 6)
+#define OMAP4_SDMMC5_CMD_DUPLICATEWAKEUPEVENT_SHIFT		5
+#define OMAP4_SDMMC5_CMD_DUPLICATEWAKEUPEVENT_MASK		(1 << 5)
+#define OMAP4_SDMMC5_CLK_DUPLICATEWAKEUPEVENT_SHIFT		4
+#define OMAP4_SDMMC5_CLK_DUPLICATEWAKEUPEVENT_MASK		(1 << 4)
+#define OMAP4_UART3_TX_IRTX_DUPLICATEWAKEUPEVENT_SHIFT		3
+#define OMAP4_UART3_TX_IRTX_DUPLICATEWAKEUPEVENT_MASK		(1 << 3)
+#define OMAP4_UART3_RX_IRRX_DUPLICATEWAKEUPEVENT_SHIFT		2
+#define OMAP4_UART3_RX_IRRX_DUPLICATEWAKEUPEVENT_MASK		(1 << 2)
+#define OMAP4_UART3_RTS_SD_DUPLICATEWAKEUPEVENT_SHIFT		1
+#define OMAP4_UART3_RTS_SD_DUPLICATEWAKEUPEVENT_MASK		(1 << 1)
+#define OMAP4_UART3_CTS_RCTX_DUPLICATEWAKEUPEVENT_SHIFT		0
+#define OMAP4_UART3_CTS_RCTX_DUPLICATEWAKEUPEVENT_MASK		(1 << 0)
+
+/* PADCONF_WAKEUPEVENT_5 */
+#define OMAP4_DPM_EMU11_DUPLICATEWAKEUPEVENT_SHIFT		31
+#define OMAP4_DPM_EMU11_DUPLICATEWAKEUPEVENT_MASK		(1 << 31)
+#define OMAP4_DPM_EMU10_DUPLICATEWAKEUPEVENT_SHIFT		30
+#define OMAP4_DPM_EMU10_DUPLICATEWAKEUPEVENT_MASK		(1 << 30)
+#define OMAP4_DPM_EMU9_DUPLICATEWAKEUPEVENT_SHIFT		29
+#define OMAP4_DPM_EMU9_DUPLICATEWAKEUPEVENT_MASK		(1 << 29)
+#define OMAP4_DPM_EMU8_DUPLICATEWAKEUPEVENT_SHIFT		28
+#define OMAP4_DPM_EMU8_DUPLICATEWAKEUPEVENT_MASK		(1 << 28)
+#define OMAP4_DPM_EMU7_DUPLICATEWAKEUPEVENT_SHIFT		27
+#define OMAP4_DPM_EMU7_DUPLICATEWAKEUPEVENT_MASK		(1 << 27)
+#define OMAP4_DPM_EMU6_DUPLICATEWAKEUPEVENT_SHIFT		26
+#define OMAP4_DPM_EMU6_DUPLICATEWAKEUPEVENT_MASK		(1 << 26)
+#define OMAP4_DPM_EMU5_DUPLICATEWAKEUPEVENT_SHIFT		25
+#define OMAP4_DPM_EMU5_DUPLICATEWAKEUPEVENT_MASK		(1 << 25)
+#define OMAP4_DPM_EMU4_DUPLICATEWAKEUPEVENT_SHIFT		24
+#define OMAP4_DPM_EMU4_DUPLICATEWAKEUPEVENT_MASK		(1 << 24)
+#define OMAP4_DPM_EMU3_DUPLICATEWAKEUPEVENT_SHIFT		23
+#define OMAP4_DPM_EMU3_DUPLICATEWAKEUPEVENT_MASK		(1 << 23)
+#define OMAP4_DPM_EMU2_DUPLICATEWAKEUPEVENT_SHIFT		22
+#define OMAP4_DPM_EMU2_DUPLICATEWAKEUPEVENT_MASK		(1 << 22)
+#define OMAP4_DPM_EMU1_DUPLICATEWAKEUPEVENT_SHIFT		21
+#define OMAP4_DPM_EMU1_DUPLICATEWAKEUPEVENT_MASK		(1 << 21)
+#define OMAP4_DPM_EMU0_DUPLICATEWAKEUPEVENT_SHIFT		20
+#define OMAP4_DPM_EMU0_DUPLICATEWAKEUPEVENT_MASK		(1 << 20)
+#define OMAP4_SYS_BOOT5_DUPLICATEWAKEUPEVENT_SHIFT		19
+#define OMAP4_SYS_BOOT5_DUPLICATEWAKEUPEVENT_MASK		(1 << 19)
+#define OMAP4_SYS_BOOT4_DUPLICATEWAKEUPEVENT_SHIFT		18
+#define OMAP4_SYS_BOOT4_DUPLICATEWAKEUPEVENT_MASK		(1 << 18)
+#define OMAP4_SYS_BOOT3_DUPLICATEWAKEUPEVENT_SHIFT		17
+#define OMAP4_SYS_BOOT3_DUPLICATEWAKEUPEVENT_MASK		(1 << 17)
+#define OMAP4_SYS_BOOT2_DUPLICATEWAKEUPEVENT_SHIFT		16
+#define OMAP4_SYS_BOOT2_DUPLICATEWAKEUPEVENT_MASK		(1 << 16)
+#define OMAP4_SYS_BOOT1_DUPLICATEWAKEUPEVENT_SHIFT		15
+#define OMAP4_SYS_BOOT1_DUPLICATEWAKEUPEVENT_MASK		(1 << 15)
+#define OMAP4_SYS_BOOT0_DUPLICATEWAKEUPEVENT_SHIFT		14
+#define OMAP4_SYS_BOOT0_DUPLICATEWAKEUPEVENT_MASK		(1 << 14)
+#define OMAP4_SYS_NIRQ2_DUPLICATEWAKEUPEVENT_SHIFT		13
+#define OMAP4_SYS_NIRQ2_DUPLICATEWAKEUPEVENT_MASK		(1 << 13)
+#define OMAP4_SYS_NIRQ1_DUPLICATEWAKEUPEVENT_SHIFT		12
+#define OMAP4_SYS_NIRQ1_DUPLICATEWAKEUPEVENT_MASK		(1 << 12)
+#define OMAP4_FREF_CLK2_OUT_DUPLICATEWAKEUPEVENT_SHIFT		11
+#define OMAP4_FREF_CLK2_OUT_DUPLICATEWAKEUPEVENT_MASK		(1 << 11)
+#define OMAP4_FREF_CLK1_OUT_DUPLICATEWAKEUPEVENT_SHIFT		10
+#define OMAP4_FREF_CLK1_OUT_DUPLICATEWAKEUPEVENT_MASK		(1 << 10)
+#define OMAP4_UNIPRO_RY2_DUPLICATEWAKEUPEVENT_SHIFT		9
+#define OMAP4_UNIPRO_RY2_DUPLICATEWAKEUPEVENT_MASK		(1 << 9)
+#define OMAP4_UNIPRO_RX2_DUPLICATEWAKEUPEVENT_SHIFT		8
+#define OMAP4_UNIPRO_RX2_DUPLICATEWAKEUPEVENT_MASK		(1 << 8)
+#define OMAP4_UNIPRO_RY1_DUPLICATEWAKEUPEVENT_SHIFT		7
+#define OMAP4_UNIPRO_RY1_DUPLICATEWAKEUPEVENT_MASK		(1 << 7)
+#define OMAP4_UNIPRO_RX1_DUPLICATEWAKEUPEVENT_SHIFT		6
+#define OMAP4_UNIPRO_RX1_DUPLICATEWAKEUPEVENT_MASK		(1 << 6)
+#define OMAP4_UNIPRO_RY0_DUPLICATEWAKEUPEVENT_SHIFT		5
+#define OMAP4_UNIPRO_RY0_DUPLICATEWAKEUPEVENT_MASK		(1 << 5)
+#define OMAP4_UNIPRO_RX0_DUPLICATEWAKEUPEVENT_SHIFT		4
+#define OMAP4_UNIPRO_RX0_DUPLICATEWAKEUPEVENT_MASK		(1 << 4)
+#define OMAP4_UNIPRO_TY2_DUPLICATEWAKEUPEVENT_SHIFT		3
+#define OMAP4_UNIPRO_TY2_DUPLICATEWAKEUPEVENT_MASK		(1 << 3)
+#define OMAP4_UNIPRO_TX2_DUPLICATEWAKEUPEVENT_SHIFT		2
+#define OMAP4_UNIPRO_TX2_DUPLICATEWAKEUPEVENT_MASK		(1 << 2)
+#define OMAP4_UNIPRO_TY1_DUPLICATEWAKEUPEVENT_SHIFT		1
+#define OMAP4_UNIPRO_TY1_DUPLICATEWAKEUPEVENT_MASK		(1 << 1)
+#define OMAP4_UNIPRO_TX1_DUPLICATEWAKEUPEVENT_SHIFT		0
+#define OMAP4_UNIPRO_TX1_DUPLICATEWAKEUPEVENT_MASK		(1 << 0)
+
+/* PADCONF_WAKEUPEVENT_6 */
+#define OMAP4_DPM_EMU19_DUPLICATEWAKEUPEVENT_SHIFT		7
+#define OMAP4_DPM_EMU19_DUPLICATEWAKEUPEVENT_MASK		(1 << 7)
+#define OMAP4_DPM_EMU18_DUPLICATEWAKEUPEVENT_SHIFT		6
+#define OMAP4_DPM_EMU18_DUPLICATEWAKEUPEVENT_MASK		(1 << 6)
+#define OMAP4_DPM_EMU17_DUPLICATEWAKEUPEVENT_SHIFT		5
+#define OMAP4_DPM_EMU17_DUPLICATEWAKEUPEVENT_MASK		(1 << 5)
+#define OMAP4_DPM_EMU16_DUPLICATEWAKEUPEVENT_SHIFT		4
+#define OMAP4_DPM_EMU16_DUPLICATEWAKEUPEVENT_MASK		(1 << 4)
+#define OMAP4_DPM_EMU15_DUPLICATEWAKEUPEVENT_SHIFT		3
+#define OMAP4_DPM_EMU15_DUPLICATEWAKEUPEVENT_MASK		(1 << 3)
+#define OMAP4_DPM_EMU14_DUPLICATEWAKEUPEVENT_SHIFT		2
+#define OMAP4_DPM_EMU14_DUPLICATEWAKEUPEVENT_MASK		(1 << 2)
+#define OMAP4_DPM_EMU13_DUPLICATEWAKEUPEVENT_SHIFT		1
+#define OMAP4_DPM_EMU13_DUPLICATEWAKEUPEVENT_MASK		(1 << 1)
+#define OMAP4_DPM_EMU12_DUPLICATEWAKEUPEVENT_SHIFT		0
+#define OMAP4_DPM_EMU12_DUPLICATEWAKEUPEVENT_MASK		(1 << 0)
+
+/* CONTROL_PADCONF_GLOBAL */
+#define OMAP4_FORCE_OFFMODE_EN_SHIFT				31
+#define OMAP4_FORCE_OFFMODE_EN_MASK				(1 << 31)
+
+/* CONTROL_PADCONF_MODE */
+#define OMAP4_VDDS_DV_BANK0_SHIFT				31
+#define OMAP4_VDDS_DV_BANK0_MASK				(1 << 31)
+#define OMAP4_VDDS_DV_BANK1_SHIFT				30
+#define OMAP4_VDDS_DV_BANK1_MASK				(1 << 30)
+#define OMAP4_VDDS_DV_BANK3_SHIFT				29
+#define OMAP4_VDDS_DV_BANK3_MASK				(1 << 29)
+#define OMAP4_VDDS_DV_BANK4_SHIFT				28
+#define OMAP4_VDDS_DV_BANK4_MASK				(1 << 28)
+#define OMAP4_VDDS_DV_BANK5_SHIFT				27
+#define OMAP4_VDDS_DV_BANK5_MASK				(1 << 27)
+#define OMAP4_VDDS_DV_BANK6_SHIFT				26
+#define OMAP4_VDDS_DV_BANK6_MASK				(1 << 26)
+#define OMAP4_VDDS_DV_C2C_SHIFT					25
+#define OMAP4_VDDS_DV_C2C_MASK					(1 << 25)
+#define OMAP4_VDDS_DV_CAM_SHIFT					24
+#define OMAP4_VDDS_DV_CAM_MASK					(1 << 24)
+#define OMAP4_VDDS_DV_GPMC_SHIFT				23
+#define OMAP4_VDDS_DV_GPMC_MASK					(1 << 23)
+#define OMAP4_VDDS_DV_SDMMC2_SHIFT				22
+#define OMAP4_VDDS_DV_SDMMC2_MASK				(1 << 22)
+
+/* CONTROL_SMART1IO_PADCONF_0 */
+#define OMAP4_ABE_DR0_SC_SHIFT					30
+#define OMAP4_ABE_DR0_SC_MASK					(0x3 << 30)
+#define OMAP4_CAM_DR0_SC_SHIFT					28
+#define OMAP4_CAM_DR0_SC_MASK					(0x3 << 28)
+#define OMAP4_FREF_DR2_SC_SHIFT					26
+#define OMAP4_FREF_DR2_SC_MASK					(0x3 << 26)
+#define OMAP4_FREF_DR3_SC_SHIFT					24
+#define OMAP4_FREF_DR3_SC_MASK					(0x3 << 24)
+#define OMAP4_GPIO_DR8_SC_SHIFT					22
+#define OMAP4_GPIO_DR8_SC_MASK					(0x3 << 22)
+#define OMAP4_GPIO_DR9_SC_SHIFT					20
+#define OMAP4_GPIO_DR9_SC_MASK					(0x3 << 20)
+#define OMAP4_GPMC_DR2_SC_SHIFT					18
+#define OMAP4_GPMC_DR2_SC_MASK					(0x3 << 18)
+#define OMAP4_GPMC_DR3_SC_SHIFT					16
+#define OMAP4_GPMC_DR3_SC_MASK					(0x3 << 16)
+#define OMAP4_GPMC_DR6_SC_SHIFT					14
+#define OMAP4_GPMC_DR6_SC_MASK					(0x3 << 14)
+#define OMAP4_HDMI_DR0_SC_SHIFT					12
+#define OMAP4_HDMI_DR0_SC_MASK					(0x3 << 12)
+#define OMAP4_MCSPI1_DR0_SC_SHIFT				10
+#define OMAP4_MCSPI1_DR0_SC_MASK				(0x3 << 10)
+#define OMAP4_UART1_DR0_SC_SHIFT				8
+#define OMAP4_UART1_DR0_SC_MASK					(0x3 << 8)
+#define OMAP4_UART3_DR0_SC_SHIFT				6
+#define OMAP4_UART3_DR0_SC_MASK					(0x3 << 6)
+#define OMAP4_UART3_DR1_SC_SHIFT				4
+#define OMAP4_UART3_DR1_SC_MASK					(0x3 << 4)
+#define OMAP4_UNIPRO_DR0_SC_SHIFT				2
+#define OMAP4_UNIPRO_DR0_SC_MASK				(0x3 << 2)
+#define OMAP4_UNIPRO_DR1_SC_SHIFT				0
+#define OMAP4_UNIPRO_DR1_SC_MASK				(0x3 << 0)
+
+/* CONTROL_SMART1IO_PADCONF_1 */
+#define OMAP4_ABE_DR0_LB_SHIFT					30
+#define OMAP4_ABE_DR0_LB_MASK					(0x3 << 30)
+#define OMAP4_CAM_DR0_LB_SHIFT					28
+#define OMAP4_CAM_DR0_LB_MASK					(0x3 << 28)
+#define OMAP4_FREF_DR2_LB_SHIFT					26
+#define OMAP4_FREF_DR2_LB_MASK					(0x3 << 26)
+#define OMAP4_FREF_DR3_LB_SHIFT					24
+#define OMAP4_FREF_DR3_LB_MASK					(0x3 << 24)
+#define OMAP4_GPIO_DR8_LB_SHIFT					22
+#define OMAP4_GPIO_DR8_LB_MASK					(0x3 << 22)
+#define OMAP4_GPIO_DR9_LB_SHIFT					20
+#define OMAP4_GPIO_DR9_LB_MASK					(0x3 << 20)
+#define OMAP4_GPMC_DR2_LB_SHIFT					18
+#define OMAP4_GPMC_DR2_LB_MASK					(0x3 << 18)
+#define OMAP4_GPMC_DR3_LB_SHIFT					16
+#define OMAP4_GPMC_DR3_LB_MASK					(0x3 << 16)
+#define OMAP4_GPMC_DR6_LB_SHIFT					14
+#define OMAP4_GPMC_DR6_LB_MASK					(0x3 << 14)
+#define OMAP4_HDMI_DR0_LB_SHIFT					12
+#define OMAP4_HDMI_DR0_LB_MASK					(0x3 << 12)
+#define OMAP4_MCSPI1_DR0_LB_SHIFT				10
+#define OMAP4_MCSPI1_DR0_LB_MASK				(0x3 << 10)
+#define OMAP4_UART1_DR0_LB_SHIFT				8
+#define OMAP4_UART1_DR0_LB_MASK					(0x3 << 8)
+#define OMAP4_UART3_DR0_LB_SHIFT				6
+#define OMAP4_UART3_DR0_LB_MASK					(0x3 << 6)
+#define OMAP4_UART3_DR1_LB_SHIFT				4
+#define OMAP4_UART3_DR1_LB_MASK					(0x3 << 4)
+#define OMAP4_UNIPRO_DR0_LB_SHIFT				2
+#define OMAP4_UNIPRO_DR0_LB_MASK				(0x3 << 2)
+#define OMAP4_UNIPRO_DR1_LB_SHIFT				0
+#define OMAP4_UNIPRO_DR1_LB_MASK				(0x3 << 0)
+
+/* CONTROL_SMART2IO_PADCONF_0 */
+#define OMAP4_C2C_DR0_LB_SHIFT					31
+#define OMAP4_C2C_DR0_LB_MASK					(1 << 31)
+#define OMAP4_DPM_DR1_LB_SHIFT					30
+#define OMAP4_DPM_DR1_LB_MASK					(1 << 30)
+#define OMAP4_DPM_DR2_LB_SHIFT					29
+#define OMAP4_DPM_DR2_LB_MASK					(1 << 29)
+#define OMAP4_DPM_DR3_LB_SHIFT					28
+#define OMAP4_DPM_DR3_LB_MASK					(1 << 28)
+#define OMAP4_GPIO_DR0_LB_SHIFT					27
+#define OMAP4_GPIO_DR0_LB_MASK					(1 << 27)
+#define OMAP4_GPIO_DR1_LB_SHIFT					26
+#define OMAP4_GPIO_DR1_LB_MASK					(1 << 26)
+#define OMAP4_GPIO_DR10_LB_SHIFT				25
+#define OMAP4_GPIO_DR10_LB_MASK					(1 << 25)
+#define OMAP4_GPIO_DR2_LB_SHIFT					24
+#define OMAP4_GPIO_DR2_LB_MASK					(1 << 24)
+#define OMAP4_GPMC_DR0_LB_SHIFT					23
+#define OMAP4_GPMC_DR0_LB_MASK					(1 << 23)
+#define OMAP4_GPMC_DR1_LB_SHIFT					22
+#define OMAP4_GPMC_DR1_LB_MASK					(1 << 22)
+#define OMAP4_GPMC_DR4_LB_SHIFT					21
+#define OMAP4_GPMC_DR4_LB_MASK					(1 << 21)
+#define OMAP4_GPMC_DR5_LB_SHIFT					20
+#define OMAP4_GPMC_DR5_LB_MASK					(1 << 20)
+#define OMAP4_GPMC_DR7_LB_SHIFT					19
+#define OMAP4_GPMC_DR7_LB_MASK					(1 << 19)
+#define OMAP4_HSI2_DR0_LB_SHIFT					18
+#define OMAP4_HSI2_DR0_LB_MASK					(1 << 18)
+#define OMAP4_HSI2_DR1_LB_SHIFT					17
+#define OMAP4_HSI2_DR1_LB_MASK					(1 << 17)
+#define OMAP4_HSI2_DR2_LB_SHIFT					16
+#define OMAP4_HSI2_DR2_LB_MASK					(1 << 16)
+#define OMAP4_KPD_DR0_LB_SHIFT					15
+#define OMAP4_KPD_DR0_LB_MASK					(1 << 15)
+#define OMAP4_KPD_DR1_LB_SHIFT					14
+#define OMAP4_KPD_DR1_LB_MASK					(1 << 14)
+#define OMAP4_PDM_DR0_LB_SHIFT					13
+#define OMAP4_PDM_DR0_LB_MASK					(1 << 13)
+#define OMAP4_SDMMC2_DR0_LB_SHIFT				12
+#define OMAP4_SDMMC2_DR0_LB_MASK				(1 << 12)
+#define OMAP4_SDMMC3_DR0_LB_SHIFT				11
+#define OMAP4_SDMMC3_DR0_LB_MASK				(1 << 11)
+#define OMAP4_SDMMC4_DR0_LB_SHIFT				10
+#define OMAP4_SDMMC4_DR0_LB_MASK				(1 << 10)
+#define OMAP4_SDMMC4_DR1_LB_SHIFT				9
+#define OMAP4_SDMMC4_DR1_LB_MASK				(1 << 9)
+#define OMAP4_SPI3_DR0_LB_SHIFT					8
+#define OMAP4_SPI3_DR0_LB_MASK					(1 << 8)
+#define OMAP4_SPI3_DR1_LB_SHIFT					7
+#define OMAP4_SPI3_DR1_LB_MASK					(1 << 7)
+#define OMAP4_UART3_DR2_LB_SHIFT				6
+#define OMAP4_UART3_DR2_LB_MASK					(1 << 6)
+#define OMAP4_UART3_DR3_LB_SHIFT				5
+#define OMAP4_UART3_DR3_LB_MASK					(1 << 5)
+#define OMAP4_UART3_DR4_LB_SHIFT				4
+#define OMAP4_UART3_DR4_LB_MASK					(1 << 4)
+#define OMAP4_UART3_DR5_LB_SHIFT				3
+#define OMAP4_UART3_DR5_LB_MASK					(1 << 3)
+#define OMAP4_USBA0_DR1_LB_SHIFT				2
+#define OMAP4_USBA0_DR1_LB_MASK					(1 << 2)
+#define OMAP4_USBA_DR2_LB_SHIFT					1
+#define OMAP4_USBA_DR2_LB_MASK					(1 << 1)
+
+/* CONTROL_SMART2IO_PADCONF_1 */
+#define OMAP4_USBB1_DR0_LB_SHIFT				31
+#define OMAP4_USBB1_DR0_LB_MASK					(1 << 31)
+#define OMAP4_USBB2_DR0_LB_SHIFT				30
+#define OMAP4_USBB2_DR0_LB_MASK					(1 << 30)
+#define OMAP4_USBA0_DR0_LB_SHIFT				29
+#define OMAP4_USBA0_DR0_LB_MASK					(1 << 29)
+
+/* CONTROL_SMART3IO_PADCONF_0 */
+#define OMAP4_DMIC_DR0_MB_SHIFT					30
+#define OMAP4_DMIC_DR0_MB_MASK					(0x3 << 30)
+#define OMAP4_GPIO_DR3_MB_SHIFT					28
+#define OMAP4_GPIO_DR3_MB_MASK					(0x3 << 28)
+#define OMAP4_GPIO_DR4_MB_SHIFT					26
+#define OMAP4_GPIO_DR4_MB_MASK					(0x3 << 26)
+#define OMAP4_GPIO_DR5_MB_SHIFT					24
+#define OMAP4_GPIO_DR5_MB_MASK					(0x3 << 24)
+#define OMAP4_GPIO_DR6_MB_SHIFT					22
+#define OMAP4_GPIO_DR6_MB_MASK					(0x3 << 22)
+#define OMAP4_HSI_DR1_MB_SHIFT					20
+#define OMAP4_HSI_DR1_MB_MASK					(0x3 << 20)
+#define OMAP4_HSI_DR2_MB_SHIFT					18
+#define OMAP4_HSI_DR2_MB_MASK					(0x3 << 18)
+#define OMAP4_HSI_DR3_MB_SHIFT					16
+#define OMAP4_HSI_DR3_MB_MASK					(0x3 << 16)
+#define OMAP4_MCBSP2_DR0_MB_SHIFT				14
+#define OMAP4_MCBSP2_DR0_MB_MASK				(0x3 << 14)
+#define OMAP4_MCSPI4_DR0_MB_SHIFT				12
+#define OMAP4_MCSPI4_DR0_MB_MASK				(0x3 << 12)
+#define OMAP4_MCSPI4_DR1_MB_SHIFT				10
+#define OMAP4_MCSPI4_DR1_MB_MASK				(0x3 << 10)
+#define OMAP4_SDMMC3_DR0_MB_SHIFT				8
+#define OMAP4_SDMMC3_DR0_MB_MASK				(0x3 << 8)
+#define OMAP4_SPI2_DR0_MB_SHIFT					0
+#define OMAP4_SPI2_DR0_MB_MASK					(0x3 << 0)
+
+/* CONTROL_SMART3IO_PADCONF_1 */
+#define OMAP4_SPI2_DR1_MB_SHIFT					30
+#define OMAP4_SPI2_DR1_MB_MASK					(0x3 << 30)
+#define OMAP4_SPI2_DR2_MB_SHIFT					28
+#define OMAP4_SPI2_DR2_MB_MASK					(0x3 << 28)
+#define OMAP4_UART2_DR0_MB_SHIFT				26
+#define OMAP4_UART2_DR0_MB_MASK					(0x3 << 26)
+#define OMAP4_UART2_DR1_MB_SHIFT				24
+#define OMAP4_UART2_DR1_MB_MASK					(0x3 << 24)
+#define OMAP4_UART4_DR0_MB_SHIFT				22
+#define OMAP4_UART4_DR0_MB_MASK					(0x3 << 22)
+#define OMAP4_HSI_DR0_MB_SHIFT					20
+#define OMAP4_HSI_DR0_MB_MASK					(0x3 << 20)
+
+/* CONTROL_SMART3IO_PADCONF_2 */
+#define OMAP4_DMIC_DR0_LB_SHIFT					31
+#define OMAP4_DMIC_DR0_LB_MASK					(1 << 31)
+#define OMAP4_GPIO_DR3_LB_SHIFT					30
+#define OMAP4_GPIO_DR3_LB_MASK					(1 << 30)
+#define OMAP4_GPIO_DR4_LB_SHIFT					29
+#define OMAP4_GPIO_DR4_LB_MASK					(1 << 29)
+#define OMAP4_GPIO_DR5_LB_SHIFT					28
+#define OMAP4_GPIO_DR5_LB_MASK					(1 << 28)
+#define OMAP4_GPIO_DR6_LB_SHIFT					27
+#define OMAP4_GPIO_DR6_LB_MASK					(1 << 27)
+#define OMAP4_HSI_DR1_LB_SHIFT					26
+#define OMAP4_HSI_DR1_LB_MASK					(1 << 26)
+#define OMAP4_HSI_DR2_LB_SHIFT					25
+#define OMAP4_HSI_DR2_LB_MASK					(1 << 25)
+#define OMAP4_HSI_DR3_LB_SHIFT					24
+#define OMAP4_HSI_DR3_LB_MASK					(1 << 24)
+#define OMAP4_MCBSP2_DR0_LB_SHIFT				23
+#define OMAP4_MCBSP2_DR0_LB_MASK				(1 << 23)
+#define OMAP4_MCSPI4_DR0_LB_SHIFT				22
+#define OMAP4_MCSPI4_DR0_LB_MASK				(1 << 22)
+#define OMAP4_MCSPI4_DR1_LB_SHIFT				21
+#define OMAP4_MCSPI4_DR1_LB_MASK				(1 << 21)
+#define OMAP4_SLIMBUS2_DR0_LB_SHIFT				18
+#define OMAP4_SLIMBUS2_DR0_LB_MASK				(1 << 18)
+#define OMAP4_SPI2_DR0_LB_SHIFT					16
+#define OMAP4_SPI2_DR0_LB_MASK					(1 << 16)
+#define OMAP4_SPI2_DR1_LB_SHIFT					15
+#define OMAP4_SPI2_DR1_LB_MASK					(1 << 15)
+#define OMAP4_SPI2_DR2_LB_SHIFT					14
+#define OMAP4_SPI2_DR2_LB_MASK					(1 << 14)
+#define OMAP4_UART2_DR0_LB_SHIFT				13
+#define OMAP4_UART2_DR0_LB_MASK					(1 << 13)
+#define OMAP4_UART2_DR1_LB_SHIFT				12
+#define OMAP4_UART2_DR1_LB_MASK					(1 << 12)
+#define OMAP4_UART4_DR0_LB_SHIFT				11
+#define OMAP4_UART4_DR0_LB_MASK					(1 << 11)
+#define OMAP4_HSI_DR0_LB_SHIFT					10
+#define OMAP4_HSI_DR0_LB_MASK					(1 << 10)
+
+/* CONTROL_USBB_HSIC */
+#define OMAP4_USBB2_DR1_SR_SHIFT				30
+#define OMAP4_USBB2_DR1_SR_MASK					(0x3 << 30)
+#define OMAP4_USBB2_DR1_I_SHIFT					27
+#define OMAP4_USBB2_DR1_I_MASK					(0x7 << 27)
+#define OMAP4_USBB1_DR1_SR_SHIFT				25
+#define OMAP4_USBB1_DR1_SR_MASK					(0x3 << 25)
+#define OMAP4_USBB1_DR1_I_SHIFT					22
+#define OMAP4_USBB1_DR1_I_MASK					(0x7 << 22)
+#define OMAP4_USBB1_HSIC_DATA_WD_SHIFT				20
+#define OMAP4_USBB1_HSIC_DATA_WD_MASK				(0x3 << 20)
+#define OMAP4_USBB1_HSIC_STROBE_WD_SHIFT			18
+#define OMAP4_USBB1_HSIC_STROBE_WD_MASK				(0x3 << 18)
+#define OMAP4_USBB2_HSIC_DATA_WD_SHIFT				16
+#define OMAP4_USBB2_HSIC_DATA_WD_MASK				(0x3 << 16)
+#define OMAP4_USBB2_HSIC_STROBE_WD_SHIFT			14
+#define OMAP4_USBB2_HSIC_STROBE_WD_MASK				(0x3 << 14)
+#define OMAP4_USBB1_HSIC_DATA_OFFMODE_WD_ENABLE_SHIFT		13
+#define OMAP4_USBB1_HSIC_DATA_OFFMODE_WD_ENABLE_MASK		(1 << 13)
+#define OMAP4_USBB1_HSIC_DATA_OFFMODE_WD_SHIFT			11
+#define OMAP4_USBB1_HSIC_DATA_OFFMODE_WD_MASK			(0x3 << 11)
+#define OMAP4_USBB1_HSIC_STROBE_OFFMODE_WD_ENABLE_SHIFT		10
+#define OMAP4_USBB1_HSIC_STROBE_OFFMODE_WD_ENABLE_MASK		(1 << 10)
+#define OMAP4_USBB1_HSIC_STROBE_OFFMODE_WD_SHIFT		8
+#define OMAP4_USBB1_HSIC_STROBE_OFFMODE_WD_MASK			(0x3 << 8)
+#define OMAP4_USBB2_HSIC_DATA_OFFMODE_WD_ENABLE_SHIFT		7
+#define OMAP4_USBB2_HSIC_DATA_OFFMODE_WD_ENABLE_MASK		(1 << 7)
+#define OMAP4_USBB2_HSIC_DATA_OFFMODE_WD_SHIFT			5
+#define OMAP4_USBB2_HSIC_DATA_OFFMODE_WD_MASK			(0x3 << 5)
+#define OMAP4_USBB2_HSIC_STROBE_OFFMODE_WD_ENABLE_SHIFT		4
+#define OMAP4_USBB2_HSIC_STROBE_OFFMODE_WD_ENABLE_MASK		(1 << 4)
+#define OMAP4_USBB2_HSIC_STROBE_OFFMODE_WD_SHIFT		2
+#define OMAP4_USBB2_HSIC_STROBE_OFFMODE_WD_MASK			(0x3 << 2)
+
+/* CONTROL_SLIMBUS */
+#define OMAP4_SLIMBUS1_DR0_MB_SHIFT				30
+#define OMAP4_SLIMBUS1_DR0_MB_MASK				(0x3 << 30)
+#define OMAP4_SLIMBUS1_DR1_MB_SHIFT				28
+#define OMAP4_SLIMBUS1_DR1_MB_MASK				(0x3 << 28)
+#define OMAP4_SLIMBUS2_DR0_MB_SHIFT				26
+#define OMAP4_SLIMBUS2_DR0_MB_MASK				(0x3 << 26)
+#define OMAP4_SLIMBUS2_DR1_MB_SHIFT				24
+#define OMAP4_SLIMBUS2_DR1_MB_MASK				(0x3 << 24)
+#define OMAP4_SLIMBUS2_DR2_MB_SHIFT				22
+#define OMAP4_SLIMBUS2_DR2_MB_MASK				(0x3 << 22)
+#define OMAP4_SLIMBUS2_DR3_MB_SHIFT				20
+#define OMAP4_SLIMBUS2_DR3_MB_MASK				(0x3 << 20)
+#define OMAP4_SLIMBUS1_DR0_LB_SHIFT				19
+#define OMAP4_SLIMBUS1_DR0_LB_MASK				(1 << 19)
+#define OMAP4_SLIMBUS2_DR1_LB_SHIFT				18
+#define OMAP4_SLIMBUS2_DR1_LB_MASK				(1 << 18)
+
+/* CONTROL_PBIASLITE */
+#define OMAP4_USIM_PBIASLITE_HIZ_MODE_SHIFT			31
+#define OMAP4_USIM_PBIASLITE_HIZ_MODE_MASK			(1 << 31)
+#define OMAP4_USIM_PBIASLITE_SUPPLY_HI_OUT_SHIFT		30
+#define OMAP4_USIM_PBIASLITE_SUPPLY_HI_OUT_MASK			(1 << 30)
+#define OMAP4_USIM_PBIASLITE_VMODE_ERROR_SHIFT			29
+#define OMAP4_USIM_PBIASLITE_VMODE_ERROR_MASK			(1 << 29)
+#define OMAP4_USIM_PBIASLITE_PWRDNZ_SHIFT			28
+#define OMAP4_USIM_PBIASLITE_PWRDNZ_MASK			(1 << 28)
+#define OMAP4_USIM_PBIASLITE_VMODE_SHIFT			27
+#define OMAP4_USIM_PBIASLITE_VMODE_MASK				(1 << 27)
+#define OMAP4_MMC1_PWRDNZ_SHIFT					26
+#define OMAP4_MMC1_PWRDNZ_MASK					(1 << 26)
+#define OMAP4_MMC1_PBIASLITE_HIZ_MODE_SHIFT			25
+#define OMAP4_MMC1_PBIASLITE_HIZ_MODE_MASK			(1 << 25)
+#define OMAP4_MMC1_PBIASLITE_SUPPLY_HI_OUT_SHIFT		24
+#define OMAP4_MMC1_PBIASLITE_SUPPLY_HI_OUT_MASK			(1 << 24)
+#define OMAP4_MMC1_PBIASLITE_VMODE_ERROR_SHIFT			23
+#define OMAP4_MMC1_PBIASLITE_VMODE_ERROR_MASK			(1 << 23)
+#define OMAP4_MMC1_PBIASLITE_PWRDNZ_SHIFT			22
+#define OMAP4_MMC1_PBIASLITE_PWRDNZ_MASK			(1 << 22)
+#define OMAP4_MMC1_PBIASLITE_VMODE_SHIFT			21
+#define OMAP4_MMC1_PBIASLITE_VMODE_MASK				(1 << 21)
+#define OMAP4_USBC1_ICUSB_PWRDNZ_SHIFT				20
+#define OMAP4_USBC1_ICUSB_PWRDNZ_MASK				(1 << 20)
+
+/* CONTROL_I2C_0 */
+#define OMAP4_I2C4_SDA_GLFENB_SHIFT				31
+#define OMAP4_I2C4_SDA_GLFENB_MASK				(1 << 31)
+#define OMAP4_I2C4_SDA_LOAD_BITS_SHIFT				29
+#define OMAP4_I2C4_SDA_LOAD_BITS_MASK				(0x3 << 29)
+#define OMAP4_I2C4_SDA_PULLUPRESX_SHIFT				28
+#define OMAP4_I2C4_SDA_PULLUPRESX_MASK				(1 << 28)
+#define OMAP4_I2C3_SDA_GLFENB_SHIFT				27
+#define OMAP4_I2C3_SDA_GLFENB_MASK				(1 << 27)
+#define OMAP4_I2C3_SDA_LOAD_BITS_SHIFT				25
+#define OMAP4_I2C3_SDA_LOAD_BITS_MASK				(0x3 << 25)
+#define OMAP4_I2C3_SDA_PULLUPRESX_SHIFT				24
+#define OMAP4_I2C3_SDA_PULLUPRESX_MASK				(1 << 24)
+#define OMAP4_I2C2_SDA_GLFENB_SHIFT				23
+#define OMAP4_I2C2_SDA_GLFENB_MASK				(1 << 23)
+#define OMAP4_I2C2_SDA_LOAD_BITS_SHIFT				21
+#define OMAP4_I2C2_SDA_LOAD_BITS_MASK				(0x3 << 21)
+#define OMAP4_I2C2_SDA_PULLUPRESX_SHIFT				20
+#define OMAP4_I2C2_SDA_PULLUPRESX_MASK				(1 << 20)
+#define OMAP4_I2C1_SDA_GLFENB_SHIFT				19
+#define OMAP4_I2C1_SDA_GLFENB_MASK				(1 << 19)
+#define OMAP4_I2C1_SDA_LOAD_BITS_SHIFT				17
+#define OMAP4_I2C1_SDA_LOAD_BITS_MASK				(0x3 << 17)
+#define OMAP4_I2C1_SDA_PULLUPRESX_SHIFT				16
+#define OMAP4_I2C1_SDA_PULLUPRESX_MASK				(1 << 16)
+#define OMAP4_I2C4_SCL_GLFENB_SHIFT				15
+#define OMAP4_I2C4_SCL_GLFENB_MASK				(1 << 15)
+#define OMAP4_I2C4_SCL_LOAD_BITS_SHIFT				13
+#define OMAP4_I2C4_SCL_LOAD_BITS_MASK				(0x3 << 13)
+#define OMAP4_I2C4_SCL_PULLUPRESX_SHIFT				12
+#define OMAP4_I2C4_SCL_PULLUPRESX_MASK				(1 << 12)
+#define OMAP4_I2C3_SCL_GLFENB_SHIFT				11
+#define OMAP4_I2C3_SCL_GLFENB_MASK				(1 << 11)
+#define OMAP4_I2C3_SCL_LOAD_BITS_SHIFT				9
+#define OMAP4_I2C3_SCL_LOAD_BITS_MASK				(0x3 << 9)
+#define OMAP4_I2C3_SCL_PULLUPRESX_SHIFT				8
+#define OMAP4_I2C3_SCL_PULLUPRESX_MASK				(1 << 8)
+#define OMAP4_I2C2_SCL_GLFENB_SHIFT				7
+#define OMAP4_I2C2_SCL_GLFENB_MASK				(1 << 7)
+#define OMAP4_I2C2_SCL_LOAD_BITS_SHIFT				5
+#define OMAP4_I2C2_SCL_LOAD_BITS_MASK				(0x3 << 5)
+#define OMAP4_I2C2_SCL_PULLUPRESX_SHIFT				4
+#define OMAP4_I2C2_SCL_PULLUPRESX_MASK				(1 << 4)
+#define OMAP4_I2C1_SCL_GLFENB_SHIFT				3
+#define OMAP4_I2C1_SCL_GLFENB_MASK				(1 << 3)
+#define OMAP4_I2C1_SCL_LOAD_BITS_SHIFT				1
+#define OMAP4_I2C1_SCL_LOAD_BITS_MASK				(0x3 << 1)
+#define OMAP4_I2C1_SCL_PULLUPRESX_SHIFT				0
+#define OMAP4_I2C1_SCL_PULLUPRESX_MASK				(1 << 0)
+
+/* CONTROL_CAMERA_RX */
+#define OMAP4_CAMERARX_UNIPRO_CTRLCLKEN_SHIFT			31
+#define OMAP4_CAMERARX_UNIPRO_CTRLCLKEN_MASK			(1 << 31)
+#define OMAP4_CAMERARX_CSI22_LANEENABLE_SHIFT			29
+#define OMAP4_CAMERARX_CSI22_LANEENABLE_MASK			(0x3 << 29)
+#define OMAP4_CAMERARX_CSI21_LANEENABLE_SHIFT			24
+#define OMAP4_CAMERARX_CSI21_LANEENABLE_MASK			(0x1f << 24)
+#define OMAP4_CAMERARX_UNIPRO_CAMMODE_SHIFT			22
+#define OMAP4_CAMERARX_UNIPRO_CAMMODE_MASK			(0x3 << 22)
+#define OMAP4_CAMERARX_CSI22_CTRLCLKEN_SHIFT			21
+#define OMAP4_CAMERARX_CSI22_CTRLCLKEN_MASK			(1 << 21)
+#define OMAP4_CAMERARX_CSI22_CAMMODE_SHIFT			19
+#define OMAP4_CAMERARX_CSI22_CAMMODE_MASK			(0x3 << 19)
+#define OMAP4_CAMERARX_CSI21_CTRLCLKEN_SHIFT			18
+#define OMAP4_CAMERARX_CSI21_CTRLCLKEN_MASK			(1 << 18)
+#define OMAP4_CAMERARX_CSI21_CAMMODE_SHIFT			16
+#define OMAP4_CAMERARX_CSI21_CAMMODE_MASK			(0x3 << 16)
+
+/* CONTROL_AVDAC */
+#define OMAP4_AVDAC_ACEN_SHIFT					31
+#define OMAP4_AVDAC_ACEN_MASK					(1 << 31)
+#define OMAP4_AVDAC_TVOUTBYPASS_SHIFT				30
+#define OMAP4_AVDAC_TVOUTBYPASS_MASK				(1 << 30)
+#define OMAP4_AVDAC_INPUTINV_SHIFT				29
+#define OMAP4_AVDAC_INPUTINV_MASK				(1 << 29)
+#define OMAP4_AVDAC_CTL_SHIFT					13
+#define OMAP4_AVDAC_CTL_MASK					(0xffff << 13)
+#define OMAP4_AVDAC_CTL_WR_ACK_SHIFT				12
+#define OMAP4_AVDAC_CTL_WR_ACK_MASK				(1 << 12)
+
+/* CONTROL_HDMI_TX_PHY */
+#define OMAP4_HDMITXPHY_PADORDER_SHIFT				31
+#define OMAP4_HDMITXPHY_PADORDER_MASK				(1 << 31)
+#define OMAP4_HDMITXPHY_TXVALID_SHIFT				30
+#define OMAP4_HDMITXPHY_TXVALID_MASK				(1 << 30)
+#define OMAP4_HDMITXPHY_ENBYPASSCLK_SHIFT			29
+#define OMAP4_HDMITXPHY_ENBYPASSCLK_MASK			(1 << 29)
+#define OMAP4_HDMITXPHY_PD_PULLUPDET_SHIFT			28
+#define OMAP4_HDMITXPHY_PD_PULLUPDET_MASK			(1 << 28)
+
+/* CONTROL_MMC2 */
+#define OMAP4_MMC2_FEEDBACK_CLK_SEL_SHIFT			31
+#define OMAP4_MMC2_FEEDBACK_CLK_SEL_MASK			(1 << 31)
+
+/* CONTROL_DSIPHY */
+#define OMAP4_DSI2_LANEENABLE_SHIFT				29
+#define OMAP4_DSI2_LANEENABLE_MASK				(0x7 << 29)
+#define OMAP4_DSI1_LANEENABLE_SHIFT				24
+#define OMAP4_DSI1_LANEENABLE_MASK				(0x1f << 24)
+#define OMAP4_DSI1_PIPD_SHIFT					19
+#define OMAP4_DSI1_PIPD_MASK					(0x1f << 19)
+#define OMAP4_DSI2_PIPD_SHIFT					14
+#define OMAP4_DSI2_PIPD_MASK					(0x1f << 14)
+
+/* CONTROL_MCBSPLP */
+#define OMAP4_ALBCTRLRX_FSX_SHIFT				31
+#define OMAP4_ALBCTRLRX_FSX_MASK				(1 << 31)
+#define OMAP4_ALBCTRLRX_CLKX_SHIFT				30
+#define OMAP4_ALBCTRLRX_CLKX_MASK				(1 << 30)
+#define OMAP4_ABE_MCBSP1_DR_EN_SHIFT				29
+#define OMAP4_ABE_MCBSP1_DR_EN_MASK				(1 << 29)
+
+/* CONTROL_USB2PHYCORE */
+#define OMAP4_USB2PHY_AUTORESUME_EN_SHIFT			31
+#define OMAP4_USB2PHY_AUTORESUME_EN_MASK			(1 << 31)
+#define OMAP4_USB2PHY_DISCHGDET_SHIFT				30
+#define OMAP4_USB2PHY_DISCHGDET_MASK				(1 << 30)
+#define OMAP4_USB2PHY_GPIOMODE_SHIFT				29
+#define OMAP4_USB2PHY_GPIOMODE_MASK				(1 << 29)
+#define OMAP4_USB2PHY_CHG_DET_EXT_CTL_SHIFT			28
+#define OMAP4_USB2PHY_CHG_DET_EXT_CTL_MASK			(1 << 28)
+#define OMAP4_USB2PHY_RDM_PD_CHGDET_EN_SHIFT			27
+#define OMAP4_USB2PHY_RDM_PD_CHGDET_EN_MASK			(1 << 27)
+#define OMAP4_USB2PHY_RDP_PU_CHGDET_EN_SHIFT			26
+#define OMAP4_USB2PHY_RDP_PU_CHGDET_EN_MASK			(1 << 26)
+#define OMAP4_USB2PHY_CHG_VSRC_EN_SHIFT				25
+#define OMAP4_USB2PHY_CHG_VSRC_EN_MASK				(1 << 25)
+#define OMAP4_USB2PHY_CHG_ISINK_EN_SHIFT			24
+#define OMAP4_USB2PHY_CHG_ISINK_EN_MASK				(1 << 24)
+#define OMAP4_USB2PHY_CHG_DET_STATUS_SHIFT			21
+#define OMAP4_USB2PHY_CHG_DET_STATUS_MASK			(0x7 << 21)
+#define OMAP4_USB2PHY_CHG_DET_DM_COMP_SHIFT			20
+#define OMAP4_USB2PHY_CHG_DET_DM_COMP_MASK			(1 << 20)
+#define OMAP4_USB2PHY_CHG_DET_DP_COMP_SHIFT			19
+#define OMAP4_USB2PHY_CHG_DET_DP_COMP_MASK			(1 << 19)
+#define OMAP4_USB2PHY_DATADET_SHIFT				18
+#define OMAP4_USB2PHY_DATADET_MASK				(1 << 18)
+#define OMAP4_USB2PHY_SINKONDP_SHIFT				17
+#define OMAP4_USB2PHY_SINKONDP_MASK				(1 << 17)
+#define OMAP4_USB2PHY_SRCONDM_SHIFT				16
+#define OMAP4_USB2PHY_SRCONDM_MASK				(1 << 16)
+#define OMAP4_USB2PHY_RESTARTCHGDET_SHIFT			15
+#define OMAP4_USB2PHY_RESTARTCHGDET_MASK			(1 << 15)
+#define OMAP4_USB2PHY_CHGDETDONE_SHIFT				14
+#define OMAP4_USB2PHY_CHGDETDONE_MASK				(1 << 14)
+#define OMAP4_USB2PHY_CHGDETECTED_SHIFT				13
+#define OMAP4_USB2PHY_CHGDETECTED_MASK				(1 << 13)
+#define OMAP4_USB2PHY_MCPCPUEN_SHIFT				12
+#define OMAP4_USB2PHY_MCPCPUEN_MASK				(1 << 12)
+#define OMAP4_USB2PHY_MCPCMODEEN_SHIFT				11
+#define OMAP4_USB2PHY_MCPCMODEEN_MASK				(1 << 11)
+#define OMAP4_USB2PHY_RESETDONEMCLK_SHIFT			10
+#define OMAP4_USB2PHY_RESETDONEMCLK_MASK			(1 << 10)
+#define OMAP4_USB2PHY_UTMIRESETDONE_SHIFT			9
+#define OMAP4_USB2PHY_UTMIRESETDONE_MASK			(1 << 9)
+#define OMAP4_USB2PHY_TXBITSTUFFENABLE_SHIFT			8
+#define OMAP4_USB2PHY_TXBITSTUFFENABLE_MASK			(1 << 8)
+#define OMAP4_USB2PHY_DATAPOLARITYN_SHIFT			7
+#define OMAP4_USB2PHY_DATAPOLARITYN_MASK			(1 << 7)
+#define OMAP4_USBDPLL_FREQLOCK_SHIFT				6
+#define OMAP4_USBDPLL_FREQLOCK_MASK				(1 << 6)
+#define OMAP4_USB2PHY_RESETDONETCLK_SHIFT			5
+#define OMAP4_USB2PHY_RESETDONETCLK_MASK			(1 << 5)
+
+/* CONTROL_I2C_1 */
+#define OMAP4_HDMI_DDC_SDA_GLFENB_SHIFT				31
+#define OMAP4_HDMI_DDC_SDA_GLFENB_MASK				(1 << 31)
+#define OMAP4_HDMI_DDC_SDA_LOAD_BITS_SHIFT			29
+#define OMAP4_HDMI_DDC_SDA_LOAD_BITS_MASK			(0x3 << 29)
+#define OMAP4_HDMI_DDC_SDA_PULLUPRESX_SHIFT			28
+#define OMAP4_HDMI_DDC_SDA_PULLUPRESX_MASK			(1 << 28)
+#define OMAP4_HDMI_DDC_SCL_GLFENB_SHIFT				27
+#define OMAP4_HDMI_DDC_SCL_GLFENB_MASK				(1 << 27)
+#define OMAP4_HDMI_DDC_SCL_LOAD_BITS_SHIFT			25
+#define OMAP4_HDMI_DDC_SCL_LOAD_BITS_MASK			(0x3 << 25)
+#define OMAP4_HDMI_DDC_SCL_PULLUPRESX_SHIFT			24
+#define OMAP4_HDMI_DDC_SCL_PULLUPRESX_MASK			(1 << 24)
+#define OMAP4_HDMI_DDC_SDA_HSMODE_SHIFT				23
+#define OMAP4_HDMI_DDC_SDA_HSMODE_MASK				(1 << 23)
+#define OMAP4_HDMI_DDC_SDA_NMODE_SHIFT				22
+#define OMAP4_HDMI_DDC_SDA_NMODE_MASK				(1 << 22)
+#define OMAP4_HDMI_DDC_SCL_HSMODE_SHIFT				21
+#define OMAP4_HDMI_DDC_SCL_HSMODE_MASK				(1 << 21)
+#define OMAP4_HDMI_DDC_SCL_NMODE_SHIFT				20
+#define OMAP4_HDMI_DDC_SCL_NMODE_MASK				(1 << 20)
+
+/* CONTROL_MMC1 */
+#define OMAP4_SDMMC1_PUSTRENGTH_GRP0_SHIFT			31
+#define OMAP4_SDMMC1_PUSTRENGTH_GRP0_MASK			(1 << 31)
+#define OMAP4_SDMMC1_PUSTRENGTH_GRP1_SHIFT			30
+#define OMAP4_SDMMC1_PUSTRENGTH_GRP1_MASK			(1 << 30)
+#define OMAP4_SDMMC1_PUSTRENGTH_GRP2_SHIFT			29
+#define OMAP4_SDMMC1_PUSTRENGTH_GRP2_MASK			(1 << 29)
+#define OMAP4_SDMMC1_PUSTRENGTH_GRP3_SHIFT			28
+#define OMAP4_SDMMC1_PUSTRENGTH_GRP3_MASK			(1 << 28)
+#define OMAP4_SDMMC1_DR0_SPEEDCTRL_SHIFT			27
+#define OMAP4_SDMMC1_DR0_SPEEDCTRL_MASK				(1 << 27)
+#define OMAP4_SDMMC1_DR1_SPEEDCTRL_SHIFT			26
+#define OMAP4_SDMMC1_DR1_SPEEDCTRL_MASK				(1 << 26)
+#define OMAP4_SDMMC1_DR2_SPEEDCTRL_SHIFT			25
+#define OMAP4_SDMMC1_DR2_SPEEDCTRL_MASK				(1 << 25)
+#define OMAP4_USBC1_DR0_SPEEDCTRL_SHIFT				24
+#define OMAP4_USBC1_DR0_SPEEDCTRL_MASK				(1 << 24)
+#define OMAP4_USB_FD_CDEN_SHIFT					23
+#define OMAP4_USB_FD_CDEN_MASK					(1 << 23)
+#define OMAP4_USBC1_ICUSB_DP_PDDIS_SHIFT			22
+#define OMAP4_USBC1_ICUSB_DP_PDDIS_MASK				(1 << 22)
+#define OMAP4_USBC1_ICUSB_DM_PDDIS_SHIFT			21
+#define OMAP4_USBC1_ICUSB_DM_PDDIS_MASK				(1 << 21)
+
+/* CONTROL_HSI */
+#define OMAP4_HSI1_CALLOOP_SEL_SHIFT				31
+#define OMAP4_HSI1_CALLOOP_SEL_MASK				(1 << 31)
+#define OMAP4_HSI1_CALMUX_SEL_SHIFT				30
+#define OMAP4_HSI1_CALMUX_SEL_MASK				(1 << 30)
+#define OMAP4_HSI2_CALLOOP_SEL_SHIFT				29
+#define OMAP4_HSI2_CALLOOP_SEL_MASK				(1 << 29)
+#define OMAP4_HSI2_CALMUX_SEL_SHIFT				28
+#define OMAP4_HSI2_CALMUX_SEL_MASK				(1 << 28)
+
+/* CONTROL_USB */
+#define OMAP4_CARKIT_USBA0_ULPIPHY_DAT0_AUTO_EN_SHIFT		31
+#define OMAP4_CARKIT_USBA0_ULPIPHY_DAT0_AUTO_EN_MASK		(1 << 31)
+#define OMAP4_CARKIT_USBA0_ULPIPHY_DAT1_AUTO_EN_SHIFT		30
+#define OMAP4_CARKIT_USBA0_ULPIPHY_DAT1_AUTO_EN_MASK		(1 << 30)
+
+/* CONTROL_HDQ */
+#define OMAP4_HDQ_SIO_PWRDNZ_SHIFT				31
+#define OMAP4_HDQ_SIO_PWRDNZ_MASK				(1 << 31)
+
+/* CONTROL_LPDDR2IO1_0 */
+#define OMAP4_LPDDR2IO1_GR4_SR_SHIFT				30
+#define OMAP4_LPDDR2IO1_GR4_SR_MASK				(0x3 << 30)
+#define OMAP4_LPDDR2IO1_GR4_I_SHIFT				27
+#define OMAP4_LPDDR2IO1_GR4_I_MASK				(0x7 << 27)
+#define OMAP4_LPDDR2IO1_GR4_WD_SHIFT				25
+#define OMAP4_LPDDR2IO1_GR4_WD_MASK				(0x3 << 25)
+#define OMAP4_LPDDR2IO1_GR3_SR_SHIFT				22
+#define OMAP4_LPDDR2IO1_GR3_SR_MASK				(0x3 << 22)
+#define OMAP4_LPDDR2IO1_GR3_I_SHIFT				19
+#define OMAP4_LPDDR2IO1_GR3_I_MASK				(0x7 << 19)
+#define OMAP4_LPDDR2IO1_GR3_WD_SHIFT				17
+#define OMAP4_LPDDR2IO1_GR3_WD_MASK				(0x3 << 17)
+#define OMAP4_LPDDR2IO1_GR2_SR_SHIFT				14
+#define OMAP4_LPDDR2IO1_GR2_SR_MASK				(0x3 << 14)
+#define OMAP4_LPDDR2IO1_GR2_I_SHIFT				11
+#define OMAP4_LPDDR2IO1_GR2_I_MASK				(0x7 << 11)
+#define OMAP4_LPDDR2IO1_GR2_WD_SHIFT				9
+#define OMAP4_LPDDR2IO1_GR2_WD_MASK				(0x3 << 9)
+#define OMAP4_LPDDR2IO1_GR1_SR_SHIFT				6
+#define OMAP4_LPDDR2IO1_GR1_SR_MASK				(0x3 << 6)
+#define OMAP4_LPDDR2IO1_GR1_I_SHIFT				3
+#define OMAP4_LPDDR2IO1_GR1_I_MASK				(0x7 << 3)
+#define OMAP4_LPDDR2IO1_GR1_WD_SHIFT				1
+#define OMAP4_LPDDR2IO1_GR1_WD_MASK				(0x3 << 1)
+
+/* CONTROL_LPDDR2IO1_1 */
+#define OMAP4_LPDDR2IO1_GR8_SR_SHIFT				30
+#define OMAP4_LPDDR2IO1_GR8_SR_MASK				(0x3 << 30)
+#define OMAP4_LPDDR2IO1_GR8_I_SHIFT				27
+#define OMAP4_LPDDR2IO1_GR8_I_MASK				(0x7 << 27)
+#define OMAP4_LPDDR2IO1_GR8_WD_SHIFT				25
+#define OMAP4_LPDDR2IO1_GR8_WD_MASK				(0x3 << 25)
+#define OMAP4_LPDDR2IO1_GR7_SR_SHIFT				22
+#define OMAP4_LPDDR2IO1_GR7_SR_MASK				(0x3 << 22)
+#define OMAP4_LPDDR2IO1_GR7_I_SHIFT				19
+#define OMAP4_LPDDR2IO1_GR7_I_MASK				(0x7 << 19)
+#define OMAP4_LPDDR2IO1_GR7_WD_SHIFT				17
+#define OMAP4_LPDDR2IO1_GR7_WD_MASK				(0x3 << 17)
+#define OMAP4_LPDDR2IO1_GR6_SR_SHIFT				14
+#define OMAP4_LPDDR2IO1_GR6_SR_MASK				(0x3 << 14)
+#define OMAP4_LPDDR2IO1_GR6_I_SHIFT				11
+#define OMAP4_LPDDR2IO1_GR6_I_MASK				(0x7 << 11)
+#define OMAP4_LPDDR2IO1_GR6_WD_SHIFT				9
+#define OMAP4_LPDDR2IO1_GR6_WD_MASK				(0x3 << 9)
+#define OMAP4_LPDDR2IO1_GR5_SR_SHIFT				6
+#define OMAP4_LPDDR2IO1_GR5_SR_MASK				(0x3 << 6)
+#define OMAP4_LPDDR2IO1_GR5_I_SHIFT				3
+#define OMAP4_LPDDR2IO1_GR5_I_MASK				(0x7 << 3)
+#define OMAP4_LPDDR2IO1_GR5_WD_SHIFT				1
+#define OMAP4_LPDDR2IO1_GR5_WD_MASK				(0x3 << 1)
+
+/* CONTROL_LPDDR2IO1_2 */
+#define OMAP4_LPDDR2IO1_GR11_SR_SHIFT				30
+#define OMAP4_LPDDR2IO1_GR11_SR_MASK				(0x3 << 30)
+#define OMAP4_LPDDR2IO1_GR11_I_SHIFT				27
+#define OMAP4_LPDDR2IO1_GR11_I_MASK				(0x7 << 27)
+#define OMAP4_LPDDR2IO1_GR11_WD_SHIFT				25
+#define OMAP4_LPDDR2IO1_GR11_WD_MASK				(0x3 << 25)
+#define OMAP4_LPDDR2IO1_GR10_SR_SHIFT				22
+#define OMAP4_LPDDR2IO1_GR10_SR_MASK				(0x3 << 22)
+#define OMAP4_LPDDR2IO1_GR10_I_SHIFT				19
+#define OMAP4_LPDDR2IO1_GR10_I_MASK				(0x7 << 19)
+#define OMAP4_LPDDR2IO1_GR10_WD_SHIFT				17
+#define OMAP4_LPDDR2IO1_GR10_WD_MASK				(0x3 << 17)
+#define OMAP4_LPDDR2IO1_GR9_SR_SHIFT				14
+#define OMAP4_LPDDR2IO1_GR9_SR_MASK				(0x3 << 14)
+#define OMAP4_LPDDR2IO1_GR9_I_SHIFT				11
+#define OMAP4_LPDDR2IO1_GR9_I_MASK				(0x7 << 11)
+#define OMAP4_LPDDR2IO1_GR9_WD_SHIFT				9
+#define OMAP4_LPDDR2IO1_GR9_WD_MASK				(0x3 << 9)
+
+/* CONTROL_LPDDR2IO1_3 */
+#define OMAP4_LPDDR21_VREF_CA_CCAP0_SHIFT			31
+#define OMAP4_LPDDR21_VREF_CA_CCAP0_MASK			(1 << 31)
+#define OMAP4_LPDDR21_VREF_CA_CCAP1_SHIFT			30
+#define OMAP4_LPDDR21_VREF_CA_CCAP1_MASK			(1 << 30)
+#define OMAP4_LPDDR21_VREF_CA_INT_CCAP0_SHIFT			29
+#define OMAP4_LPDDR21_VREF_CA_INT_CCAP0_MASK			(1 << 29)
+#define OMAP4_LPDDR21_VREF_CA_INT_CCAP1_SHIFT			28
+#define OMAP4_LPDDR21_VREF_CA_INT_CCAP1_MASK			(1 << 28)
+#define OMAP4_LPDDR21_VREF_CA_INT_TAP0_SHIFT			27
+#define OMAP4_LPDDR21_VREF_CA_INT_TAP0_MASK			(1 << 27)
+#define OMAP4_LPDDR21_VREF_CA_INT_TAP1_SHIFT			26
+#define OMAP4_LPDDR21_VREF_CA_INT_TAP1_MASK			(1 << 26)
+#define OMAP4_LPDDR21_VREF_CA_TAP0_SHIFT			25
+#define OMAP4_LPDDR21_VREF_CA_TAP0_MASK				(1 << 25)
+#define OMAP4_LPDDR21_VREF_CA_TAP1_SHIFT			24
+#define OMAP4_LPDDR21_VREF_CA_TAP1_MASK				(1 << 24)
+#define OMAP4_LPDDR21_VREF_DQ0_INT_CCAP0_SHIFT			23
+#define OMAP4_LPDDR21_VREF_DQ0_INT_CCAP0_MASK			(1 << 23)
+#define OMAP4_LPDDR21_VREF_DQ0_INT_CCAP1_SHIFT			22
+#define OMAP4_LPDDR21_VREF_DQ0_INT_CCAP1_MASK			(1 << 22)
+#define OMAP4_LPDDR21_VREF_DQ0_INT_TAP0_SHIFT			21
+#define OMAP4_LPDDR21_VREF_DQ0_INT_TAP0_MASK			(1 << 21)
+#define OMAP4_LPDDR21_VREF_DQ0_INT_TAP1_SHIFT			20
+#define OMAP4_LPDDR21_VREF_DQ0_INT_TAP1_MASK			(1 << 20)
+#define OMAP4_LPDDR21_VREF_DQ1_INT_CCAP0_SHIFT			19
+#define OMAP4_LPDDR21_VREF_DQ1_INT_CCAP0_MASK			(1 << 19)
+#define OMAP4_LPDDR21_VREF_DQ1_INT_CCAP1_SHIFT			18
+#define OMAP4_LPDDR21_VREF_DQ1_INT_CCAP1_MASK			(1 << 18)
+#define OMAP4_LPDDR21_VREF_DQ1_INT_TAP0_SHIFT			17
+#define OMAP4_LPDDR21_VREF_DQ1_INT_TAP0_MASK			(1 << 17)
+#define OMAP4_LPDDR21_VREF_DQ1_INT_TAP1_SHIFT			16
+#define OMAP4_LPDDR21_VREF_DQ1_INT_TAP1_MASK			(1 << 16)
+#define OMAP4_LPDDR21_VREF_DQ_CCAP0_SHIFT			15
+#define OMAP4_LPDDR21_VREF_DQ_CCAP0_MASK			(1 << 15)
+#define OMAP4_LPDDR21_VREF_DQ_CCAP1_SHIFT			14
+#define OMAP4_LPDDR21_VREF_DQ_CCAP1_MASK			(1 << 14)
+#define OMAP4_LPDDR21_VREF_DQ_TAP0_SHIFT			13
+#define OMAP4_LPDDR21_VREF_DQ_TAP0_MASK				(1 << 13)
+#define OMAP4_LPDDR21_VREF_DQ_TAP1_SHIFT			12
+#define OMAP4_LPDDR21_VREF_DQ_TAP1_MASK				(1 << 12)
+
+/* CONTROL_LPDDR2IO2_0 */
+#define OMAP4_LPDDR2IO2_GR4_SR_SHIFT				30
+#define OMAP4_LPDDR2IO2_GR4_SR_MASK				(0x3 << 30)
+#define OMAP4_LPDDR2IO2_GR4_I_SHIFT				27
+#define OMAP4_LPDDR2IO2_GR4_I_MASK				(0x7 << 27)
+#define OMAP4_LPDDR2IO2_GR4_WD_SHIFT				25
+#define OMAP4_LPDDR2IO2_GR4_WD_MASK				(0x3 << 25)
+#define OMAP4_LPDDR2IO2_GR3_SR_SHIFT				22
+#define OMAP4_LPDDR2IO2_GR3_SR_MASK				(0x3 << 22)
+#define OMAP4_LPDDR2IO2_GR3_I_SHIFT				19
+#define OMAP4_LPDDR2IO2_GR3_I_MASK				(0x7 << 19)
+#define OMAP4_LPDDR2IO2_GR3_WD_SHIFT				17
+#define OMAP4_LPDDR2IO2_GR3_WD_MASK				(0x3 << 17)
+#define OMAP4_LPDDR2IO2_GR2_SR_SHIFT				14
+#define OMAP4_LPDDR2IO2_GR2_SR_MASK				(0x3 << 14)
+#define OMAP4_LPDDR2IO2_GR2_I_SHIFT				11
+#define OMAP4_LPDDR2IO2_GR2_I_MASK				(0x7 << 11)
+#define OMAP4_LPDDR2IO2_GR2_WD_SHIFT				9
+#define OMAP4_LPDDR2IO2_GR2_WD_MASK				(0x3 << 9)
+#define OMAP4_LPDDR2IO2_GR1_SR_SHIFT				6
+#define OMAP4_LPDDR2IO2_GR1_SR_MASK				(0x3 << 6)
+#define OMAP4_LPDDR2IO2_GR1_I_SHIFT				3
+#define OMAP4_LPDDR2IO2_GR1_I_MASK				(0x7 << 3)
+#define OMAP4_LPDDR2IO2_GR1_WD_SHIFT				1
+#define OMAP4_LPDDR2IO2_GR1_WD_MASK				(0x3 << 1)
+
+/* CONTROL_LPDDR2IO2_1 */
+#define OMAP4_LPDDR2IO2_GR8_SR_SHIFT				30
+#define OMAP4_LPDDR2IO2_GR8_SR_MASK				(0x3 << 30)
+#define OMAP4_LPDDR2IO2_GR8_I_SHIFT				27
+#define OMAP4_LPDDR2IO2_GR8_I_MASK				(0x7 << 27)
+#define OMAP4_LPDDR2IO2_GR8_WD_SHIFT				25
+#define OMAP4_LPDDR2IO2_GR8_WD_MASK				(0x3 << 25)
+#define OMAP4_LPDDR2IO2_GR7_SR_SHIFT				22
+#define OMAP4_LPDDR2IO2_GR7_SR_MASK				(0x3 << 22)
+#define OMAP4_LPDDR2IO2_GR7_I_SHIFT				19
+#define OMAP4_LPDDR2IO2_GR7_I_MASK				(0x7 << 19)
+#define OMAP4_LPDDR2IO2_GR7_WD_SHIFT				17
+#define OMAP4_LPDDR2IO2_GR7_WD_MASK				(0x3 << 17)
+#define OMAP4_LPDDR2IO2_GR6_SR_SHIFT				14
+#define OMAP4_LPDDR2IO2_GR6_SR_MASK				(0x3 << 14)
+#define OMAP4_LPDDR2IO2_GR6_I_SHIFT				11
+#define OMAP4_LPDDR2IO2_GR6_I_MASK				(0x7 << 11)
+#define OMAP4_LPDDR2IO2_GR6_WD_SHIFT				9
+#define OMAP4_LPDDR2IO2_GR6_WD_MASK				(0x3 << 9)
+#define OMAP4_LPDDR2IO2_GR5_SR_SHIFT				6
+#define OMAP4_LPDDR2IO2_GR5_SR_MASK				(0x3 << 6)
+#define OMAP4_LPDDR2IO2_GR5_I_SHIFT				3
+#define OMAP4_LPDDR2IO2_GR5_I_MASK				(0x7 << 3)
+#define OMAP4_LPDDR2IO2_GR5_WD_SHIFT				1
+#define OMAP4_LPDDR2IO2_GR5_WD_MASK				(0x3 << 1)
+
+/* CONTROL_LPDDR2IO2_2 */
+#define OMAP4_LPDDR2IO2_GR11_SR_SHIFT				30
+#define OMAP4_LPDDR2IO2_GR11_SR_MASK				(0x3 << 30)
+#define OMAP4_LPDDR2IO2_GR11_I_SHIFT				27
+#define OMAP4_LPDDR2IO2_GR11_I_MASK				(0x7 << 27)
+#define OMAP4_LPDDR2IO2_GR11_WD_SHIFT				25
+#define OMAP4_LPDDR2IO2_GR11_WD_MASK				(0x3 << 25)
+#define OMAP4_LPDDR2IO2_GR10_SR_SHIFT				22
+#define OMAP4_LPDDR2IO2_GR10_SR_MASK				(0x3 << 22)
+#define OMAP4_LPDDR2IO2_GR10_I_SHIFT				19
+#define OMAP4_LPDDR2IO2_GR10_I_MASK				(0x7 << 19)
+#define OMAP4_LPDDR2IO2_GR10_WD_SHIFT				17
+#define OMAP4_LPDDR2IO2_GR10_WD_MASK				(0x3 << 17)
+#define OMAP4_LPDDR2IO2_GR9_SR_SHIFT				14
+#define OMAP4_LPDDR2IO2_GR9_SR_MASK				(0x3 << 14)
+#define OMAP4_LPDDR2IO2_GR9_I_SHIFT				11
+#define OMAP4_LPDDR2IO2_GR9_I_MASK				(0x7 << 11)
+#define OMAP4_LPDDR2IO2_GR9_WD_SHIFT				9
+#define OMAP4_LPDDR2IO2_GR9_WD_MASK				(0x3 << 9)
+
+/* CONTROL_LPDDR2IO2_3 */
+#define OMAP4_LPDDR22_VREF_CA_CCAP0_SHIFT			31
+#define OMAP4_LPDDR22_VREF_CA_CCAP0_MASK			(1 << 31)
+#define OMAP4_LPDDR22_VREF_CA_CCAP1_SHIFT			30
+#define OMAP4_LPDDR22_VREF_CA_CCAP1_MASK			(1 << 30)
+#define OMAP4_LPDDR22_VREF_CA_INT_CCAP0_SHIFT			29
+#define OMAP4_LPDDR22_VREF_CA_INT_CCAP0_MASK			(1 << 29)
+#define OMAP4_LPDDR22_VREF_CA_INT_CCAP1_SHIFT			28
+#define OMAP4_LPDDR22_VREF_CA_INT_CCAP1_MASK			(1 << 28)
+#define OMAP4_LPDDR22_VREF_CA_INT_TAP0_SHIFT			27
+#define OMAP4_LPDDR22_VREF_CA_INT_TAP0_MASK			(1 << 27)
+#define OMAP4_LPDDR22_VREF_CA_INT_TAP1_SHIFT			26
+#define OMAP4_LPDDR22_VREF_CA_INT_TAP1_MASK			(1 << 26)
+#define OMAP4_LPDDR22_VREF_CA_TAP0_SHIFT			25
+#define OMAP4_LPDDR22_VREF_CA_TAP0_MASK				(1 << 25)
+#define OMAP4_LPDDR22_VREF_CA_TAP1_SHIFT			24
+#define OMAP4_LPDDR22_VREF_CA_TAP1_MASK				(1 << 24)
+#define OMAP4_LPDDR22_VREF_DQ0_INT_CCAP0_SHIFT			23
+#define OMAP4_LPDDR22_VREF_DQ0_INT_CCAP0_MASK			(1 << 23)
+#define OMAP4_LPDDR22_VREF_DQ0_INT_CCAP1_SHIFT			22
+#define OMAP4_LPDDR22_VREF_DQ0_INT_CCAP1_MASK			(1 << 22)
+#define OMAP4_LPDDR22_VREF_DQ0_INT_TAP0_SHIFT			21
+#define OMAP4_LPDDR22_VREF_DQ0_INT_TAP0_MASK			(1 << 21)
+#define OMAP4_LPDDR22_VREF_DQ0_INT_TAP1_SHIFT			20
+#define OMAP4_LPDDR22_VREF_DQ0_INT_TAP1_MASK			(1 << 20)
+#define OMAP4_LPDDR22_VREF_DQ1_INT_CCAP0_SHIFT			19
+#define OMAP4_LPDDR22_VREF_DQ1_INT_CCAP0_MASK			(1 << 19)
+#define OMAP4_LPDDR22_VREF_DQ1_INT_CCAP1_SHIFT			18
+#define OMAP4_LPDDR22_VREF_DQ1_INT_CCAP1_MASK			(1 << 18)
+#define OMAP4_LPDDR22_VREF_DQ1_INT_TAP0_SHIFT			17
+#define OMAP4_LPDDR22_VREF_DQ1_INT_TAP0_MASK			(1 << 17)
+#define OMAP4_LPDDR22_VREF_DQ1_INT_TAP1_SHIFT			16
+#define OMAP4_LPDDR22_VREF_DQ1_INT_TAP1_MASK			(1 << 16)
+#define OMAP4_LPDDR22_VREF_DQ_CCAP0_SHIFT			15
+#define OMAP4_LPDDR22_VREF_DQ_CCAP0_MASK			(1 << 15)
+#define OMAP4_LPDDR22_VREF_DQ_CCAP1_SHIFT			14
+#define OMAP4_LPDDR22_VREF_DQ_CCAP1_MASK			(1 << 14)
+#define OMAP4_LPDDR22_VREF_DQ_TAP0_SHIFT			13
+#define OMAP4_LPDDR22_VREF_DQ_TAP0_MASK				(1 << 13)
+#define OMAP4_LPDDR22_VREF_DQ_TAP1_SHIFT			12
+#define OMAP4_LPDDR22_VREF_DQ_TAP1_MASK				(1 << 12)
+
+/* CONTROL_BUS_HOLD */
+#define OMAP4_ABE_DMIC_DIN3_EN_SHIFT				31
+#define OMAP4_ABE_DMIC_DIN3_EN_MASK				(1 << 31)
+#define OMAP4_MCSPI1_CS3_EN_SHIFT				30
+#define OMAP4_MCSPI1_CS3_EN_MASK				(1 << 30)
+
+/* CONTROL_C2C */
+#define OMAP4_MIRROR_MODE_EN_SHIFT				31
+#define OMAP4_MIRROR_MODE_EN_MASK				(1 << 31)
+#define OMAP4_C2C_SPARE_SHIFT					24
+#define OMAP4_C2C_SPARE_MASK					(0x7f << 24)
+
+/* CORE_CONTROL_SPARE_RW */
+#define OMAP4_CORE_CONTROL_SPARE_RW_SHIFT			0
+#define OMAP4_CORE_CONTROL_SPARE_RW_MASK			(0xffffffff << 0)
+
+/* CORE_CONTROL_SPARE_R */
+#define OMAP4_CORE_CONTROL_SPARE_R_SHIFT			0
+#define OMAP4_CORE_CONTROL_SPARE_R_MASK				(0xffffffff << 0)
+
+/* CORE_CONTROL_SPARE_R_C0 */
+#define OMAP4_CORE_CONTROL_SPARE_R_C0_SHIFT			31
+#define OMAP4_CORE_CONTROL_SPARE_R_C0_MASK			(1 << 31)
+#define OMAP4_CORE_CONTROL_SPARE_R_C1_SHIFT			30
+#define OMAP4_CORE_CONTROL_SPARE_R_C1_MASK			(1 << 30)
+#define OMAP4_CORE_CONTROL_SPARE_R_C2_SHIFT			29
+#define OMAP4_CORE_CONTROL_SPARE_R_C2_MASK			(1 << 29)
+#define OMAP4_CORE_CONTROL_SPARE_R_C3_SHIFT			28
+#define OMAP4_CORE_CONTROL_SPARE_R_C3_MASK			(1 << 28)
+#define OMAP4_CORE_CONTROL_SPARE_R_C4_SHIFT			27
+#define OMAP4_CORE_CONTROL_SPARE_R_C4_MASK			(1 << 27)
+#define OMAP4_CORE_CONTROL_SPARE_R_C5_SHIFT			26
+#define OMAP4_CORE_CONTROL_SPARE_R_C5_MASK			(1 << 26)
+#define OMAP4_CORE_CONTROL_SPARE_R_C6_SHIFT			25
+#define OMAP4_CORE_CONTROL_SPARE_R_C6_MASK			(1 << 25)
+#define OMAP4_CORE_CONTROL_SPARE_R_C7_SHIFT			24
+#define OMAP4_CORE_CONTROL_SPARE_R_C7_MASK			(1 << 24)
+
+/* CONTROL_EFUSE_1 */
+#define OMAP4_AVDAC_TRIM_BYTE3_SHIFT				24
+#define OMAP4_AVDAC_TRIM_BYTE3_MASK				(0x7f << 24)
+#define OMAP4_AVDAC_TRIM_BYTE2_SHIFT				16
+#define OMAP4_AVDAC_TRIM_BYTE2_MASK				(0xff << 16)
+#define OMAP4_AVDAC_TRIM_BYTE1_SHIFT				8
+#define OMAP4_AVDAC_TRIM_BYTE1_MASK				(0xff << 8)
+#define OMAP4_AVDAC_TRIM_BYTE0_SHIFT				0
+#define OMAP4_AVDAC_TRIM_BYTE0_MASK				(0xff << 0)
+
+/* CONTROL_EFUSE_2 */
+#define OMAP4_EFUSE_SMART2TEST_P0_SHIFT				31
+#define OMAP4_EFUSE_SMART2TEST_P0_MASK				(1 << 31)
+#define OMAP4_EFUSE_SMART2TEST_P1_SHIFT				30
+#define OMAP4_EFUSE_SMART2TEST_P1_MASK				(1 << 30)
+#define OMAP4_EFUSE_SMART2TEST_P2_SHIFT				29
+#define OMAP4_EFUSE_SMART2TEST_P2_MASK				(1 << 29)
+#define OMAP4_EFUSE_SMART2TEST_P3_SHIFT				28
+#define OMAP4_EFUSE_SMART2TEST_P3_MASK				(1 << 28)
+#define OMAP4_EFUSE_SMART2TEST_N0_SHIFT				27
+#define OMAP4_EFUSE_SMART2TEST_N0_MASK				(1 << 27)
+#define OMAP4_EFUSE_SMART2TEST_N1_SHIFT				26
+#define OMAP4_EFUSE_SMART2TEST_N1_MASK				(1 << 26)
+#define OMAP4_EFUSE_SMART2TEST_N2_SHIFT				25
+#define OMAP4_EFUSE_SMART2TEST_N2_MASK				(1 << 25)
+#define OMAP4_EFUSE_SMART2TEST_N3_SHIFT				24
+#define OMAP4_EFUSE_SMART2TEST_N3_MASK				(1 << 24)
+#define OMAP4_LPDDR2_PTV_N1_SHIFT				23
+#define OMAP4_LPDDR2_PTV_N1_MASK				(1 << 23)
+#define OMAP4_LPDDR2_PTV_N2_SHIFT				22
+#define OMAP4_LPDDR2_PTV_N2_MASK				(1 << 22)
+#define OMAP4_LPDDR2_PTV_N3_SHIFT				21
+#define OMAP4_LPDDR2_PTV_N3_MASK				(1 << 21)
+#define OMAP4_LPDDR2_PTV_N4_SHIFT				20
+#define OMAP4_LPDDR2_PTV_N4_MASK				(1 << 20)
+#define OMAP4_LPDDR2_PTV_N5_SHIFT				19
+#define OMAP4_LPDDR2_PTV_N5_MASK				(1 << 19)
+#define OMAP4_LPDDR2_PTV_P1_SHIFT				18
+#define OMAP4_LPDDR2_PTV_P1_MASK				(1 << 18)
+#define OMAP4_LPDDR2_PTV_P2_SHIFT				17
+#define OMAP4_LPDDR2_PTV_P2_MASK				(1 << 17)
+#define OMAP4_LPDDR2_PTV_P3_SHIFT				16
+#define OMAP4_LPDDR2_PTV_P3_MASK				(1 << 16)
+#define OMAP4_LPDDR2_PTV_P4_SHIFT				15
+#define OMAP4_LPDDR2_PTV_P4_MASK				(1 << 15)
+#define OMAP4_LPDDR2_PTV_P5_SHIFT				14
+#define OMAP4_LPDDR2_PTV_P5_MASK				(1 << 14)
+
+/* CONTROL_EFUSE_3 */
+#define OMAP4_STD_FUSE_SPARE_1_SHIFT				24
+#define OMAP4_STD_FUSE_SPARE_1_MASK				(0xff << 24)
+#define OMAP4_STD_FUSE_SPARE_2_SHIFT				16
+#define OMAP4_STD_FUSE_SPARE_2_MASK				(0xff << 16)
+#define OMAP4_STD_FUSE_SPARE_3_SHIFT				8
+#define OMAP4_STD_FUSE_SPARE_3_MASK				(0xff << 8)
+#define OMAP4_STD_FUSE_SPARE_4_SHIFT				0
+#define OMAP4_STD_FUSE_SPARE_4_MASK				(0xff << 0)
+
+/* CONTROL_EFUSE_4 */
+#define OMAP4_STD_FUSE_SPARE_5_SHIFT				24
+#define OMAP4_STD_FUSE_SPARE_5_MASK				(0xff << 24)
+#define OMAP4_STD_FUSE_SPARE_6_SHIFT				16
+#define OMAP4_STD_FUSE_SPARE_6_MASK				(0xff << 16)
+#define OMAP4_STD_FUSE_SPARE_7_SHIFT				8
+#define OMAP4_STD_FUSE_SPARE_7_MASK				(0xff << 8)
+#define OMAP4_STD_FUSE_SPARE_8_SHIFT				0
+#define OMAP4_STD_FUSE_SPARE_8_MASK				(0xff << 0)
+
+#endif
diff --git a/arch/arm/mach-omap2/ctrl_module_pad_wkup_44xx.h b/arch/arm/mach-omap2/ctrl_module_pad_wkup_44xx.h
new file mode 100644
index 0000000..17c9b37
--- /dev/null
+++ b/arch/arm/mach-omap2/ctrl_module_pad_wkup_44xx.h
@@ -0,0 +1,236 @@
+/*
+ * OMAP44xx CTRL_MODULE_PAD_WKUP registers and bitfields
+ *
+ * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ *
+ * Benoit Cousson (b-cousson@ti.com)
+ * Santosh Shilimkar (santosh.shilimkar@ti.com)
+ *
+ * This file is automatically generated from the OMAP hardware databases.
+ * We respectfully ask that any modifications to this file be coordinated
+ * with the public linux-omap@vger.kernel.org mailing list and the
+ * authors above to ensure that the autogeneration scripts are kept
+ * up-to-date with the file contents.
+ *
+ * This program is free software; you can 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_CTRL_MODULE_PAD_WKUP_44XX_H
+#define __ARCH_ARM_MACH_OMAP2_CTRL_MODULE_PAD_WKUP_44XX_H
+
+
+/* Base address */
+#define OMAP4_CTRL_MODULE_PAD_WKUP					0x4a31e000
+
+/* Registers offset */
+#define OMAP4_CTRL_MODULE_PAD_WKUP_IP_REVISION				0x0000
+#define OMAP4_CTRL_MODULE_PAD_WKUP_IP_HWINFO				0x0004
+#define OMAP4_CTRL_MODULE_PAD_WKUP_IP_SYSCONFIG				0x0010
+#define OMAP4_CTRL_MODULE_PAD_WKUP_PADCONF_WAKEUPEVENT_0		0x007c
+#define OMAP4_CTRL_MODULE_PAD_WKUP_CONTROL_SMART1NOPMIO_PADCONF_0	0x05a0
+#define OMAP4_CTRL_MODULE_PAD_WKUP_CONTROL_SMART1NOPMIO_PADCONF_1	0x05a4
+#define OMAP4_CTRL_MODULE_PAD_WKUP_CONTROL_PADCONF_MODE			0x05a8
+#define OMAP4_CTRL_MODULE_PAD_WKUP_CONTROL_XTAL_OSCILLATOR		0x05ac
+#define OMAP4_CTRL_MODULE_PAD_WKUP_CONTROL_USIMIO			0x0600
+#define OMAP4_CTRL_MODULE_PAD_WKUP_CONTROL_I2C_2			0x0604
+#define OMAP4_CTRL_MODULE_PAD_WKUP_CONTROL_JTAG				0x0608
+#define OMAP4_CTRL_MODULE_PAD_WKUP_CONTROL_SYS				0x060c
+#define OMAP4_CTRL_MODULE_PAD_WKUP_WKUP_CONTROL_SPARE_RW		0x0614
+#define OMAP4_CTRL_MODULE_PAD_WKUP_WKUP_CONTROL_SPARE_R			0x0618
+#define OMAP4_CTRL_MODULE_PAD_WKUP_WKUP_CONTROL_SPARE_R_C0		0x061c
+
+/* Registers shifts and masks */
+
+/* IP_REVISION */
+#define OMAP4_IP_REV_SCHEME_SHIFT				30
+#define OMAP4_IP_REV_SCHEME_MASK				(0x3 << 30)
+#define OMAP4_IP_REV_FUNC_SHIFT					16
+#define OMAP4_IP_REV_FUNC_MASK					(0xfff << 16)
+#define OMAP4_IP_REV_RTL_SHIFT					11
+#define OMAP4_IP_REV_RTL_MASK					(0x1f << 11)
+#define OMAP4_IP_REV_MAJOR_SHIFT				8
+#define OMAP4_IP_REV_MAJOR_MASK					(0x7 << 8)
+#define OMAP4_IP_REV_CUSTOM_SHIFT				6
+#define OMAP4_IP_REV_CUSTOM_MASK				(0x3 << 6)
+#define OMAP4_IP_REV_MINOR_SHIFT				0
+#define OMAP4_IP_REV_MINOR_MASK					(0x3f << 0)
+
+/* IP_HWINFO */
+#define OMAP4_IP_HWINFO_SHIFT					0
+#define OMAP4_IP_HWINFO_MASK					(0xffffffff << 0)
+
+/* IP_SYSCONFIG */
+#define OMAP4_IP_SYSCONFIG_IDLEMODE_SHIFT			2
+#define OMAP4_IP_SYSCONFIG_IDLEMODE_MASK			(0x3 << 2)
+
+/* PADCONF_WAKEUPEVENT_0 */
+#define OMAP4_JTAG_TDO_DUPLICATEWAKEUPEVENT_SHIFT		24
+#define OMAP4_JTAG_TDO_DUPLICATEWAKEUPEVENT_MASK		(1 << 24)
+#define OMAP4_JTAG_TDI_DUPLICATEWAKEUPEVENT_SHIFT		23
+#define OMAP4_JTAG_TDI_DUPLICATEWAKEUPEVENT_MASK		(1 << 23)
+#define OMAP4_JTAG_TMS_TMSC_DUPLICATEWAKEUPEVENT_SHIFT		22
+#define OMAP4_JTAG_TMS_TMSC_DUPLICATEWAKEUPEVENT_MASK		(1 << 22)
+#define OMAP4_JTAG_RTCK_DUPLICATEWAKEUPEVENT_SHIFT		21
+#define OMAP4_JTAG_RTCK_DUPLICATEWAKEUPEVENT_MASK		(1 << 21)
+#define OMAP4_JTAG_TCK_DUPLICATEWAKEUPEVENT_SHIFT		20
+#define OMAP4_JTAG_TCK_DUPLICATEWAKEUPEVENT_MASK		(1 << 20)
+#define OMAP4_JTAG_NTRST_DUPLICATEWAKEUPEVENT_SHIFT		19
+#define OMAP4_JTAG_NTRST_DUPLICATEWAKEUPEVENT_MASK		(1 << 19)
+#define OMAP4_SYS_BOOT7_DUPLICATEWAKEUPEVENT_SHIFT		18
+#define OMAP4_SYS_BOOT7_DUPLICATEWAKEUPEVENT_MASK		(1 << 18)
+#define OMAP4_SYS_BOOT6_DUPLICATEWAKEUPEVENT_SHIFT		17
+#define OMAP4_SYS_BOOT6_DUPLICATEWAKEUPEVENT_MASK		(1 << 17)
+#define OMAP4_SYS_PWRON_RESET_OUT_DUPLICATEWAKEUPEVENT_SHIFT	16
+#define OMAP4_SYS_PWRON_RESET_OUT_DUPLICATEWAKEUPEVENT_MASK	(1 << 16)
+#define OMAP4_SYS_PWR_REQ_DUPLICATEWAKEUPEVENT_SHIFT		15
+#define OMAP4_SYS_PWR_REQ_DUPLICATEWAKEUPEVENT_MASK		(1 << 15)
+#define OMAP4_SYS_NRESWARM_DUPLICATEWAKEUPEVENT_SHIFT		14
+#define OMAP4_SYS_NRESWARM_DUPLICATEWAKEUPEVENT_MASK		(1 << 14)
+#define OMAP4_SYS_32K_DUPLICATEWAKEUPEVENT_SHIFT		13
+#define OMAP4_SYS_32K_DUPLICATEWAKEUPEVENT_MASK			(1 << 13)
+#define OMAP4_FREF_CLK4_OUT_DUPLICATEWAKEUPEVENT_SHIFT		12
+#define OMAP4_FREF_CLK4_OUT_DUPLICATEWAKEUPEVENT_MASK		(1 << 12)
+#define OMAP4_FREF_CLK4_REQ_DUPLICATEWAKEUPEVENT_SHIFT		11
+#define OMAP4_FREF_CLK4_REQ_DUPLICATEWAKEUPEVENT_MASK		(1 << 11)
+#define OMAP4_FREF_CLK3_OUT_DUPLICATEWAKEUPEVENT_SHIFT		10
+#define OMAP4_FREF_CLK3_OUT_DUPLICATEWAKEUPEVENT_MASK		(1 << 10)
+#define OMAP4_FREF_CLK3_REQ_DUPLICATEWAKEUPEVENT_SHIFT		9
+#define OMAP4_FREF_CLK3_REQ_DUPLICATEWAKEUPEVENT_MASK		(1 << 9)
+#define OMAP4_FREF_CLK0_OUT_DUPLICATEWAKEUPEVENT_SHIFT		8
+#define OMAP4_FREF_CLK0_OUT_DUPLICATEWAKEUPEVENT_MASK		(1 << 8)
+#define OMAP4_FREF_CLK_IOREQ_DUPLICATEWAKEUPEVENT_SHIFT		7
+#define OMAP4_FREF_CLK_IOREQ_DUPLICATEWAKEUPEVENT_MASK		(1 << 7)
+#define OMAP4_SR_SDA_DUPLICATEWAKEUPEVENT_SHIFT			6
+#define OMAP4_SR_SDA_DUPLICATEWAKEUPEVENT_MASK			(1 << 6)
+#define OMAP4_SR_SCL_DUPLICATEWAKEUPEVENT_SHIFT			5
+#define OMAP4_SR_SCL_DUPLICATEWAKEUPEVENT_MASK			(1 << 5)
+#define OMAP4_SIM_PWRCTRL_DUPLICATEWAKEUPEVENT_SHIFT		4
+#define OMAP4_SIM_PWRCTRL_DUPLICATEWAKEUPEVENT_MASK		(1 << 4)
+#define OMAP4_SIM_CD_DUPLICATEWAKEUPEVENT_SHIFT			3
+#define OMAP4_SIM_CD_DUPLICATEWAKEUPEVENT_MASK			(1 << 3)
+#define OMAP4_SIM_RESET_DUPLICATEWAKEUPEVENT_SHIFT		2
+#define OMAP4_SIM_RESET_DUPLICATEWAKEUPEVENT_MASK		(1 << 2)
+#define OMAP4_SIM_CLK_DUPLICATEWAKEUPEVENT_SHIFT		1
+#define OMAP4_SIM_CLK_DUPLICATEWAKEUPEVENT_MASK			(1 << 1)
+#define OMAP4_SIM_IO_DUPLICATEWAKEUPEVENT_SHIFT			0
+#define OMAP4_SIM_IO_DUPLICATEWAKEUPEVENT_MASK			(1 << 0)
+
+/* CONTROL_SMART1NOPMIO_PADCONF_0 */
+#define OMAP4_FREF_DR0_SC_SHIFT					30
+#define OMAP4_FREF_DR0_SC_MASK					(0x3 << 30)
+#define OMAP4_FREF_DR1_SC_SHIFT					28
+#define OMAP4_FREF_DR1_SC_MASK					(0x3 << 28)
+#define OMAP4_FREF_DR4_SC_SHIFT					26
+#define OMAP4_FREF_DR4_SC_MASK					(0x3 << 26)
+#define OMAP4_FREF_DR5_SC_SHIFT					24
+#define OMAP4_FREF_DR5_SC_MASK					(0x3 << 24)
+#define OMAP4_FREF_DR6_SC_SHIFT					22
+#define OMAP4_FREF_DR6_SC_MASK					(0x3 << 22)
+#define OMAP4_FREF_DR7_SC_SHIFT					20
+#define OMAP4_FREF_DR7_SC_MASK					(0x3 << 20)
+#define OMAP4_GPIO_DR7_SC_SHIFT					18
+#define OMAP4_GPIO_DR7_SC_MASK					(0x3 << 18)
+#define OMAP4_DPM_DR0_SC_SHIFT					14
+#define OMAP4_DPM_DR0_SC_MASK					(0x3 << 14)
+#define OMAP4_SIM_DR0_SC_SHIFT					12
+#define OMAP4_SIM_DR0_SC_MASK					(0x3 << 12)
+
+/* CONTROL_SMART1NOPMIO_PADCONF_1 */
+#define OMAP4_FREF_DR0_LB_SHIFT					30
+#define OMAP4_FREF_DR0_LB_MASK					(0x3 << 30)
+#define OMAP4_FREF_DR1_LB_SHIFT					28
+#define OMAP4_FREF_DR1_LB_MASK					(0x3 << 28)
+#define OMAP4_FREF_DR4_LB_SHIFT					26
+#define OMAP4_FREF_DR4_LB_MASK					(0x3 << 26)
+#define OMAP4_FREF_DR5_LB_SHIFT					24
+#define OMAP4_FREF_DR5_LB_MASK					(0x3 << 24)
+#define OMAP4_FREF_DR6_LB_SHIFT					22
+#define OMAP4_FREF_DR6_LB_MASK					(0x3 << 22)
+#define OMAP4_FREF_DR7_LB_SHIFT					20
+#define OMAP4_FREF_DR7_LB_MASK					(0x3 << 20)
+#define OMAP4_GPIO_DR7_LB_SHIFT					18
+#define OMAP4_GPIO_DR7_LB_MASK					(0x3 << 18)
+#define OMAP4_DPM_DR0_LB_SHIFT					14
+#define OMAP4_DPM_DR0_LB_MASK					(0x3 << 14)
+#define OMAP4_SIM_DR0_LB_SHIFT					12
+#define OMAP4_SIM_DR0_LB_MASK					(0x3 << 12)
+
+/* CONTROL_PADCONF_MODE */
+#define OMAP4_VDDS_DV_FREF_SHIFT				31
+#define OMAP4_VDDS_DV_FREF_MASK					(1 << 31)
+#define OMAP4_VDDS_DV_BANK2_SHIFT				30
+#define OMAP4_VDDS_DV_BANK2_MASK				(1 << 30)
+
+/* CONTROL_XTAL_OSCILLATOR */
+#define OMAP4_OSCILLATOR_BOOST_SHIFT				31
+#define OMAP4_OSCILLATOR_BOOST_MASK				(1 << 31)
+#define OMAP4_OSCILLATOR_OS_OUT_SHIFT				30
+#define OMAP4_OSCILLATOR_OS_OUT_MASK				(1 << 30)
+
+/* CONTROL_USIMIO */
+#define OMAP4_PAD_USIM_CLK_LOW_SHIFT				31
+#define OMAP4_PAD_USIM_CLK_LOW_MASK				(1 << 31)
+#define OMAP4_PAD_USIM_RST_LOW_SHIFT				29
+#define OMAP4_PAD_USIM_RST_LOW_MASK				(1 << 29)
+#define OMAP4_USIM_PWRDNZ_SHIFT					28
+#define OMAP4_USIM_PWRDNZ_MASK					(1 << 28)
+
+/* CONTROL_I2C_2 */
+#define OMAP4_SR_SDA_GLFENB_SHIFT				31
+#define OMAP4_SR_SDA_GLFENB_MASK				(1 << 31)
+#define OMAP4_SR_SDA_LOAD_BITS_SHIFT				29
+#define OMAP4_SR_SDA_LOAD_BITS_MASK				(0x3 << 29)
+#define OMAP4_SR_SDA_PULLUPRESX_SHIFT				28
+#define OMAP4_SR_SDA_PULLUPRESX_MASK				(1 << 28)
+#define OMAP4_SR_SCL_GLFENB_SHIFT				27
+#define OMAP4_SR_SCL_GLFENB_MASK				(1 << 27)
+#define OMAP4_SR_SCL_LOAD_BITS_SHIFT				25
+#define OMAP4_SR_SCL_LOAD_BITS_MASK				(0x3 << 25)
+#define OMAP4_SR_SCL_PULLUPRESX_SHIFT				24
+#define OMAP4_SR_SCL_PULLUPRESX_MASK				(1 << 24)
+
+/* CONTROL_JTAG */
+#define OMAP4_JTAG_NTRST_EN_SHIFT				31
+#define OMAP4_JTAG_NTRST_EN_MASK				(1 << 31)
+#define OMAP4_JTAG_TCK_EN_SHIFT					30
+#define OMAP4_JTAG_TCK_EN_MASK					(1 << 30)
+#define OMAP4_JTAG_RTCK_EN_SHIFT				29
+#define OMAP4_JTAG_RTCK_EN_MASK					(1 << 29)
+#define OMAP4_JTAG_TDI_EN_SHIFT					28
+#define OMAP4_JTAG_TDI_EN_MASK					(1 << 28)
+#define OMAP4_JTAG_TDO_EN_SHIFT					27
+#define OMAP4_JTAG_TDO_EN_MASK					(1 << 27)
+
+/* CONTROL_SYS */
+#define OMAP4_SYS_NRESWARM_PIPU_SHIFT				31
+#define OMAP4_SYS_NRESWARM_PIPU_MASK				(1 << 31)
+
+/* WKUP_CONTROL_SPARE_RW */
+#define OMAP4_WKUP_CONTROL_SPARE_RW_SHIFT			0
+#define OMAP4_WKUP_CONTROL_SPARE_RW_MASK			(0xffffffff << 0)
+
+/* WKUP_CONTROL_SPARE_R */
+#define OMAP4_WKUP_CONTROL_SPARE_R_SHIFT			0
+#define OMAP4_WKUP_CONTROL_SPARE_R_MASK				(0xffffffff << 0)
+
+/* WKUP_CONTROL_SPARE_R_C0 */
+#define OMAP4_WKUP_CONTROL_SPARE_R_C0_SHIFT			31
+#define OMAP4_WKUP_CONTROL_SPARE_R_C0_MASK			(1 << 31)
+#define OMAP4_WKUP_CONTROL_SPARE_R_C1_SHIFT			30
+#define OMAP4_WKUP_CONTROL_SPARE_R_C1_MASK			(1 << 30)
+#define OMAP4_WKUP_CONTROL_SPARE_R_C2_SHIFT			29
+#define OMAP4_WKUP_CONTROL_SPARE_R_C2_MASK			(1 << 29)
+#define OMAP4_WKUP_CONTROL_SPARE_R_C3_SHIFT			28
+#define OMAP4_WKUP_CONTROL_SPARE_R_C3_MASK			(1 << 28)
+#define OMAP4_WKUP_CONTROL_SPARE_R_C4_SHIFT			27
+#define OMAP4_WKUP_CONTROL_SPARE_R_C4_MASK			(1 << 27)
+#define OMAP4_WKUP_CONTROL_SPARE_R_C5_SHIFT			26
+#define OMAP4_WKUP_CONTROL_SPARE_R_C5_MASK			(1 << 26)
+#define OMAP4_WKUP_CONTROL_SPARE_R_C6_SHIFT			25
+#define OMAP4_WKUP_CONTROL_SPARE_R_C6_MASK			(1 << 25)
+#define OMAP4_WKUP_CONTROL_SPARE_R_C7_SHIFT			24
+#define OMAP4_WKUP_CONTROL_SPARE_R_C7_MASK			(1 << 24)
+
+#endif
diff --git a/arch/arm/mach-omap2/ctrl_module_wkup_44xx.h b/arch/arm/mach-omap2/ctrl_module_wkup_44xx.h
new file mode 100644
index 0000000..a0af9ba
--- /dev/null
+++ b/arch/arm/mach-omap2/ctrl_module_wkup_44xx.h
@@ -0,0 +1,92 @@
+/*
+ * OMAP44xx CTRL_MODULE_WKUP registers and bitfields
+ *
+ * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ *
+ * Benoit Cousson (b-cousson@ti.com)
+ * Santosh Shilimkar (santosh.shilimkar@ti.com)
+ *
+ * This file is automatically generated from the OMAP hardware databases.
+ * We respectfully ask that any modifications to this file be coordinated
+ * with the public linux-omap@vger.kernel.org mailing list and the
+ * authors above to ensure that the autogeneration scripts are kept
+ * up-to-date with the file contents.
+ *
+ * This program is free software; you can 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_CTRL_MODULE_WKUP_44XX_H
+#define __ARCH_ARM_MACH_OMAP2_CTRL_MODULE_WKUP_44XX_H
+
+
+/* Base address */
+#define OMAP4_CTRL_MODULE_WKUP				0x4a30c000
+
+/* Registers offset */
+#define OMAP4_CTRL_MODULE_WKUP_IP_REVISION		0x0000
+#define OMAP4_CTRL_MODULE_WKUP_IP_HWINFO		0x0004
+#define OMAP4_CTRL_MODULE_WKUP_IP_SYSCONFIG		0x0010
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_0	0x0460
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_1	0x0464
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_2	0x0468
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_3	0x046c
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_4	0x0470
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_5	0x0474
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_6	0x0478
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_7	0x047c
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_8	0x0480
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_9	0x0484
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_10	0x0488
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_11	0x048c
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_12	0x0490
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_13	0x0494
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_14	0x0498
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_15	0x049c
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_16	0x04a0
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_17	0x04a4
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_18	0x04a8
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_19	0x04ac
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_20	0x04b0
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_21	0x04b4
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_22	0x04b8
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_23	0x04bc
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_24	0x04c0
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_25	0x04c4
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_26	0x04c8
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_27	0x04cc
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_28	0x04d0
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_29	0x04d4
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_30	0x04d8
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_31	0x04dc
+
+/* Registers shifts and masks */
+
+/* IP_REVISION */
+#define OMAP4_IP_REV_SCHEME_SHIFT		30
+#define OMAP4_IP_REV_SCHEME_MASK		(0x3 << 30)
+#define OMAP4_IP_REV_FUNC_SHIFT			16
+#define OMAP4_IP_REV_FUNC_MASK			(0xfff << 16)
+#define OMAP4_IP_REV_RTL_SHIFT			11
+#define OMAP4_IP_REV_RTL_MASK			(0x1f << 11)
+#define OMAP4_IP_REV_MAJOR_SHIFT		8
+#define OMAP4_IP_REV_MAJOR_MASK			(0x7 << 8)
+#define OMAP4_IP_REV_CUSTOM_SHIFT		6
+#define OMAP4_IP_REV_CUSTOM_MASK		(0x3 << 6)
+#define OMAP4_IP_REV_MINOR_SHIFT		0
+#define OMAP4_IP_REV_MINOR_MASK			(0x3f << 0)
+
+/* IP_HWINFO */
+#define OMAP4_IP_HWINFO_SHIFT			0
+#define OMAP4_IP_HWINFO_MASK			(0xffffffff << 0)
+
+/* IP_SYSCONFIG */
+#define OMAP4_IP_SYSCONFIG_IDLEMODE_SHIFT	2
+#define OMAP4_IP_SYSCONFIG_IDLEMODE_MASK	(0x3 << 2)
+
+/* CONF_DEBUG_SEL_TST_0 */
+#define OMAP4_WKUP_MODE_SHIFT			0
+#define OMAP4_WKUP_MODE_MASK				(1 << 0)
+
+#endif
diff --git a/arch/arm/mach-omap2/debug-devices.h b/arch/arm/mach-omap2/debug-devices.h
new file mode 100644
index 0000000..a4edbd2
--- /dev/null
+++ b/arch/arm/mach-omap2/debug-devices.h
@@ -0,0 +1,9 @@
+#ifndef _OMAP_DEBUG_DEVICES_H
+#define _OMAP_DEBUG_DEVICES_H
+
+#include <linux/types.h>
+
+/* for TI reference platforms sharing the same debug card */
+extern int debug_card_init(u32 addr, unsigned gpio);
+
+#endif
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
index c00c689..d092d2a8 100644
--- a/arch/arm/mach-omap2/devices.c
+++ b/arch/arm/mach-omap2/devices.c
@@ -17,21 +17,20 @@
 #include <linux/err.h>
 #include <linux/slab.h>
 #include <linux/of.h>
+#include <linux/pinctrl/machine.h>
 #include <linux/platform_data/omap4-keypad.h>
 
-#include <mach/hardware.h>
-#include <mach/irqs.h>
 #include <asm/mach-types.h>
 #include <asm/mach/map.h>
-#include <asm/pmu.h>
 
 #include "iomap.h"
-#include <plat/board.h>
 #include <plat/dma.h>
 #include <plat/omap_hwmod.h>
 #include <plat/omap_device.h>
-#include <plat/omap4-keypad.h>
+#include "omap4-keypad.h"
 
+#include "soc.h"
+#include "common.h"
 #include "mux.h"
 #include "control.h"
 #include "devices.h"
@@ -112,7 +111,7 @@ static struct resource omap2cam_resources[] = {
 		.flags		= IORESOURCE_MEM,
 	},
 	{
-		.start		= INT_24XX_CAM_IRQ,
+		.start		= 24 + OMAP_INTC_START,
 		.flags		= IORESOURCE_IRQ,
 	}
 };
@@ -201,7 +200,7 @@ static struct resource omap3isp_resources[] = {
 		.flags		= IORESOURCE_MEM,
 	},
 	{
-		.start		= INT_34XX_CAM_IRQ,
+		.start		= 24 + OMAP_INTC_START,
 		.flags		= IORESOURCE_IRQ,
 	}
 };
@@ -385,7 +384,7 @@ static inline void omap_init_hdmi_audio(void) {}
 
 #if defined(CONFIG_SPI_OMAP24XX) || defined(CONFIG_SPI_OMAP24XX_MODULE)
 
-#include <plat/mcspi.h>
+#include <linux/platform_data/spi-omap2-mcspi.h>
 
 static int __init omap_mcspi_init(struct omap_hwmod *oh, void *unused)
 {
@@ -435,20 +434,18 @@ static inline void omap_init_mcspi(void) {}
 #endif
 
 static struct resource omap2_pmu_resource = {
-	.start	= 3,
-	.end	= 3,
+	.start	= 3 + OMAP_INTC_START,
 	.flags	= IORESOURCE_IRQ,
 };
 
 static struct resource omap3_pmu_resource = {
-	.start	= INT_34XX_BENCH_MPU_EMUL,
-	.end	= INT_34XX_BENCH_MPU_EMUL,
+	.start	= 3 + OMAP_INTC_START,
 	.flags	= IORESOURCE_IRQ,
 };
 
 static struct platform_device omap_pmu_device = {
 	.name		= "arm-pmu",
-	.id		= ARM_PMU_DEVICE_CPU,
+	.id		= -1,
 	.num_resources	= 1,
 };
 
@@ -475,7 +472,7 @@ static struct resource omap2_sham_resources[] = {
 		.flags	= IORESOURCE_MEM,
 	},
 	{
-		.start	= INT_24XX_SHA1MD5,
+		.start	= 51 + OMAP_INTC_START,
 		.flags	= IORESOURCE_IRQ,
 	}
 };
@@ -493,7 +490,7 @@ static struct resource omap3_sham_resources[] = {
 		.flags	= IORESOURCE_MEM,
 	},
 	{
-		.start	= INT_34XX_SHA1MD52_IRQ,
+		.start	= 49 + OMAP_INTC_START,
 		.flags	= IORESOURCE_IRQ,
 	},
 	{
@@ -631,6 +628,10 @@ static inline void omap_init_vout(void) {}
 
 static int __init omap2_init_devices(void)
 {
+	/* Enable dummy states for those platforms without pinctrl support */
+	if (!of_have_populated_dt())
+		pinctrl_provide_dummies();
+
 	/*
 	 * please keep these calls, and their implementations above,
 	 * in alphabetical order so they're easier to sort through.
diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c
index af1ed7d..4875b4e 100644
--- a/arch/arm/mach-omap2/display.c
+++ b/arch/arm/mach-omap2/display.c
@@ -76,14 +76,14 @@ struct omap_dss_hwmod_data {
 	const int id;
 };
 
-static const struct omap_dss_hwmod_data omap2_dss_hwmod_data[] __initdata = {
+static const struct omap_dss_hwmod_data omap2_dss_hwmod_data[] __initconst = {
 	{ "dss_core", "omapdss_dss", -1 },
 	{ "dss_dispc", "omapdss_dispc", -1 },
 	{ "dss_rfbi", "omapdss_rfbi", -1 },
 	{ "dss_venc", "omapdss_venc", -1 },
 };
 
-static const struct omap_dss_hwmod_data omap3_dss_hwmod_data[] __initdata = {
+static const struct omap_dss_hwmod_data omap3_dss_hwmod_data[] __initconst = {
 	{ "dss_core", "omapdss_dss", -1 },
 	{ "dss_dispc", "omapdss_dispc", -1 },
 	{ "dss_rfbi", "omapdss_rfbi", -1 },
@@ -91,11 +91,10 @@ static const struct omap_dss_hwmod_data omap3_dss_hwmod_data[] __initdata = {
 	{ "dss_dsi1", "omapdss_dsi", 0 },
 };
 
-static const struct omap_dss_hwmod_data omap4_dss_hwmod_data[] __initdata = {
+static const struct omap_dss_hwmod_data omap4_dss_hwmod_data[] __initconst = {
 	{ "dss_core", "omapdss_dss", -1 },
 	{ "dss_dispc", "omapdss_dispc", -1 },
 	{ "dss_rfbi", "omapdss_rfbi", -1 },
-	{ "dss_venc", "omapdss_venc", -1 },
 	{ "dss_dsi1", "omapdss_dsi", 0 },
 	{ "dss_dsi2", "omapdss_dsi", 1 },
 	{ "dss_hdmi", "omapdss_hdmi", -1 },
diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c
index b9c8d2f..27d79de 100644
--- a/arch/arm/mach-omap2/dpll3xxx.c
+++ b/arch/arm/mach-omap2/dpll3xxx.c
@@ -28,9 +28,9 @@
 #include <linux/bitops.h>
 #include <linux/clkdev.h>
 
-#include <plat/cpu.h>
 #include <plat/clock.h>
 
+#include "soc.h"
 #include "clock.h"
 #include "cm2xxx_3xxx.h"
 #include "cm-regbits-34xx.h"
@@ -311,7 +311,7 @@ static int omap3_noncore_dpll_program(struct clk *clk, u16 m, u8 n, u16 freqsel)
 	 * Set jitter correction. No jitter correction for OMAP4 and 3630
 	 * since freqsel field is no longer present
 	 */
-	if (!cpu_is_omap44xx() && !cpu_is_omap3630()) {
+	if (!soc_is_am33xx() && !cpu_is_omap44xx() && !cpu_is_omap3630()) {
 		v = __raw_readl(dd->control_reg);
 		v &= ~dd->freqsel_mask;
 		v |= freqsel << __ffs(dd->freqsel_mask);
@@ -471,7 +471,7 @@ int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate)
 			return -EINVAL;
 
 		/* No freqsel on OMAP4 and OMAP3630 */
-		if (!cpu_is_omap44xx() && !cpu_is_omap3630()) {
+		if (!soc_is_am33xx() && !cpu_is_omap44xx() && !cpu_is_omap3630()) {
 			freqsel = _omap3_dpll_compute_freqsel(clk,
 						dd->last_rounded_n);
 			if (!freqsel)
@@ -623,8 +623,11 @@ unsigned long omap3_clkoutx2_recalc(struct clk *clk)
 	while (pclk && !pclk->dpll_data)
 		pclk = pclk->parent;
 
-	/* clk does not have a DPLL as a parent? */
-	WARN_ON(!pclk);
+	/* clk does not have a DPLL as a parent?  error in the clock data */
+	if (!pclk) {
+		WARN_ON(1);
+		return 0;
+	}
 
 	dd = pclk->dpll_data;
 
diff --git a/arch/arm/mach-omap2/dpll44xx.c b/arch/arm/mach-omap2/dpll44xx.c
index 9c6a296..09d0ccc 100644
--- a/arch/arm/mach-omap2/dpll44xx.c
+++ b/arch/arm/mach-omap2/dpll44xx.c
@@ -15,9 +15,9 @@
 #include <linux/io.h>
 #include <linux/bitops.h>
 
-#include <plat/cpu.h>
 #include <plat/clock.h>
 
+#include "soc.h"
 #include "clock.h"
 #include "clock44xx.h"
 #include "cm-regbits-44xx.h"
diff --git a/arch/arm/mach-omap2/dsp.c b/arch/arm/mach-omap2/dsp.c
index a636ebc..9838810 100644
--- a/arch/arm/mach-omap2/dsp.c
+++ b/arch/arm/mach-omap2/dsp.c
@@ -30,7 +30,7 @@
 #include <plat/omap-pm.h>
 #endif
 
-#include <plat/dsp.h>
+#include <linux/platform_data/dsp-omap.h>
 
 static struct platform_device *omap_dsp_pdev;
 
diff --git a/arch/arm/mach-omap2/emu.c b/arch/arm/mach-omap2/emu.c
index e28e761..b3566f6 100644
--- a/arch/arm/mach-omap2/emu.c
+++ b/arch/arm/mach-omap2/emu.c
@@ -21,8 +21,7 @@
 #include <linux/clk.h>
 #include <linux/err.h>
 
-#include <mach/hardware.h>
-
+#include "soc.h"
 #include "iomap.h"
 
 MODULE_LICENSE("GPL");
diff --git a/arch/arm/mach-omap2/gpio.c b/arch/arm/mach-omap2/gpio.c
index 9ad7d48..d1058f1 100644
--- a/arch/arm/mach-omap2/gpio.c
+++ b/arch/arm/mach-omap2/gpio.c
@@ -21,6 +21,7 @@
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/of.h>
+#include <linux/platform_data/gpio-omap.h>
 
 #include <plat/omap_hwmod.h>
 #include <plat/omap_device.h>
@@ -60,6 +61,7 @@ static int __init omap2_gpio_dev_init(struct omap_hwmod *oh, void *unused)
 	pdata->regs = kzalloc(sizeof(struct omap_gpio_reg_offs), GFP_KERNEL);
 	if (!pdata->regs) {
 		pr_err("gpio%d: Memory allocation failed\n", id);
+		kfree(pdata);
 		return -ENOMEM;
 	}
 
@@ -121,6 +123,7 @@ static int __init omap2_gpio_dev_init(struct omap_hwmod *oh, void *unused)
 		break;
 	default:
 		WARN(1, "Invalid gpio bank_type\n");
+		kfree(pdata->regs);
 		kfree(pdata);
 		return -EINVAL;
 	}
diff --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c
index 386dec8..4acf497 100644
--- a/arch/arm/mach-omap2/gpmc-nand.c
+++ b/arch/arm/mach-omap2/gpmc-nand.c
@@ -13,23 +13,31 @@
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/mtd/nand.h>
+#include <linux/platform_data/mtd-nand-omap2.h>
 
 #include <asm/mach/flash.h>
 
-#include <plat/cpu.h>
-#include <plat/nand.h>
-#include <plat/board.h>
 #include <plat/gpmc.h>
 
-static struct resource gpmc_nand_resource = {
-	.flags		= IORESOURCE_MEM,
+#include "soc.h"
+
+static struct resource gpmc_nand_resource[] = {
+	{
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+		.flags		= IORESOURCE_IRQ,
+	},
+	{
+		.flags		= IORESOURCE_IRQ,
+	},
 };
 
 static struct platform_device gpmc_nand_device = {
 	.name		= "omap2-nand",
 	.id		= 0,
-	.num_resources	= 1,
-	.resource	= &gpmc_nand_resource,
+	.num_resources	= ARRAY_SIZE(gpmc_nand_resource),
+	.resource	= gpmc_nand_resource,
 };
 
 static int omap2_nand_gpmc_retime(struct omap_nand_platform_data *gpmc_nand_data)
@@ -75,6 +83,7 @@ static int omap2_nand_gpmc_retime(struct omap_nand_platform_data *gpmc_nand_data
 		gpmc_cs_configure(gpmc_nand_data->cs, GPMC_CONFIG_DEV_SIZE, 0);
 	gpmc_cs_configure(gpmc_nand_data->cs,
 			GPMC_CONFIG_DEV_TYPE, GPMC_DEVICETYPE_NAND);
+	gpmc_cs_configure(gpmc_nand_data->cs, GPMC_CONFIG_WP, 0);
 	err = gpmc_cs_set_timings(gpmc_nand_data->cs, &t);
 	if (err)
 		return err;
@@ -90,12 +99,19 @@ int __init gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data)
 	gpmc_nand_device.dev.platform_data = gpmc_nand_data;
 
 	err = gpmc_cs_request(gpmc_nand_data->cs, NAND_IO_SIZE,
-				&gpmc_nand_data->phys_base);
+				(unsigned long *)&gpmc_nand_resource[0].start);
 	if (err < 0) {
 		dev_err(dev, "Cannot request GPMC CS\n");
 		return err;
 	}
 
+	gpmc_nand_resource[0].end = gpmc_nand_resource[0].start +
+							NAND_IO_SIZE - 1;
+
+	gpmc_nand_resource[1].start =
+				gpmc_get_client_irq(GPMC_IRQ_FIFOEVENTENABLE);
+	gpmc_nand_resource[2].start =
+				gpmc_get_client_irq(GPMC_IRQ_COUNT_EVENT);
 	 /* Set timings in GPMC */
 	err = omap2_nand_gpmc_retime(gpmc_nand_data);
 	if (err < 0) {
@@ -108,6 +124,8 @@ int __init gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data)
 		gpmc_cs_configure(gpmc_nand_data->cs, GPMC_CONFIG_RDY_BSY, 1);
 	}
 
+	gpmc_update_nand_reg(&gpmc_nand_data->reg, gpmc_nand_data->cs);
+
 	err = platform_device_register(&gpmc_nand_device);
 	if (err < 0) {
 		dev_err(dev, "Unable to register NAND device\n");
diff --git a/arch/arm/mach-omap2/gpmc-onenand.c b/arch/arm/mach-omap2/gpmc-onenand.c
index a0fa9bb..916716e 100644
--- a/arch/arm/mach-omap2/gpmc-onenand.c
+++ b/arch/arm/mach-omap2/gpmc-onenand.c
@@ -15,19 +15,27 @@
 #include <linux/platform_device.h>
 #include <linux/mtd/onenand_regs.h>
 #include <linux/io.h>
+#include <linux/platform_data/mtd-onenand-omap2.h>
 
 #include <asm/mach/flash.h>
 
-#include <plat/cpu.h>
-#include <plat/onenand.h>
-#include <plat/board.h>
 #include <plat/gpmc.h>
 
+#include "soc.h"
+
+#define	ONENAND_IO_SIZE	SZ_128K
+
 static struct omap_onenand_platform_data *gpmc_onenand_data;
 
+static struct resource gpmc_onenand_resource = {
+	.flags		= IORESOURCE_MEM,
+};
+
 static struct platform_device gpmc_onenand_device = {
 	.name		= "omap2-onenand",
 	.id		= -1,
+	.num_resources	= 1,
+	.resource	= &gpmc_onenand_resource,
 };
 
 static int omap2_onenand_set_async_mode(int cs, void __iomem *onenand_base)
@@ -390,6 +398,8 @@ static int gpmc_onenand_setup(void __iomem *onenand_base, int *freq_ptr)
 
 void __init gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data)
 {
+	int err;
+
 	gpmc_onenand_data = _onenand_data;
 	gpmc_onenand_data->onenand_setup = gpmc_onenand_setup;
 	gpmc_onenand_device.dev.platform_data = gpmc_onenand_data;
@@ -401,8 +411,19 @@ void __init gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data)
 		gpmc_onenand_data->flags |= ONENAND_SYNC_READ;
 	}
 
+	err = gpmc_cs_request(gpmc_onenand_data->cs, ONENAND_IO_SIZE,
+				(unsigned long *)&gpmc_onenand_resource.start);
+	if (err < 0) {
+		pr_err("%s: Cannot request GPMC CS\n", __func__);
+		return;
+	}
+
+	gpmc_onenand_resource.end = gpmc_onenand_resource.start +
+							ONENAND_IO_SIZE - 1;
+
 	if (platform_device_register(&gpmc_onenand_device) < 0) {
-		printk(KERN_ERR "Unable to register OneNAND device\n");
+		pr_err("%s: Unable to register OneNAND device\n", __func__);
+		gpmc_cs_free(gpmc_onenand_data->cs);
 		return;
 	}
 }
diff --git a/arch/arm/mach-omap2/gpmc-smc91x.c b/arch/arm/mach-omap2/gpmc-smc91x.c
index ba10c24..5654753 100644
--- a/arch/arm/mach-omap2/gpmc-smc91x.c
+++ b/arch/arm/mach-omap2/gpmc-smc91x.c
@@ -17,9 +17,10 @@
 #include <linux/io.h>
 #include <linux/smc91x.h>
 
-#include <plat/board.h>
 #include <plat/gpmc.h>
-#include <plat/gpmc-smc91x.h>
+#include "gpmc-smc91x.h"
+
+#include "soc.h"
 
 static struct omap_smc91x_platform_data *gpmc_cfg;
 
diff --git a/arch/arm/mach-omap2/gpmc-smc91x.h b/arch/arm/mach-omap2/gpmc-smc91x.h
new file mode 100644
index 0000000..b64fbee
--- /dev/null
+++ b/arch/arm/mach-omap2/gpmc-smc91x.h
@@ -0,0 +1,42 @@
+/*
+ * arch/arm/plat-omap/include/mach/gpmc-smc91x.h
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARCH_OMAP_GPMC_SMC91X_H__
+
+#define GPMC_TIMINGS_SMC91C96	(1 << 4)
+#define GPMC_MUX_ADD_DATA	(1 << 5) /* GPMC_CONFIG1_MUXADDDATA */
+#define GPMC_READ_MON		(1 << 6) /* GPMC_CONFIG1_WAIT_READ_MON */
+#define GPMC_WRITE_MON		(1 << 7) /* GPMC_CONFIG1_WAIT_WRITE_MON */
+
+struct omap_smc91x_platform_data {
+	int	cs;
+	int	gpio_irq;
+	int	gpio_pwrdwn;
+	int	gpio_reset;
+	int	wait_pin;	/* Optional GPMC_CONFIG1_WAITPINSELECT */
+	u32	flags;
+	int	(*retime)(void);
+};
+
+#if defined(CONFIG_SMC91X) || \
+	defined(CONFIG_SMC91X_MODULE)
+
+extern void gpmc_smc91x_init(struct omap_smc91x_platform_data *d);
+
+#else
+
+#define board_smc91x_data	NULL
+
+static inline void gpmc_smc91x_init(struct omap_smc91x_platform_data *d)
+{
+}
+
+#endif
+#endif
diff --git a/arch/arm/mach-omap2/gpmc-smsc911x.c b/arch/arm/mach-omap2/gpmc-smsc911x.c
index b6c77be..249a0b4 100644
--- a/arch/arm/mach-omap2/gpmc-smsc911x.c
+++ b/arch/arm/mach-omap2/gpmc-smsc911x.c
@@ -20,9 +20,8 @@
 #include <linux/io.h>
 #include <linux/smsc911x.h>
 
-#include <plat/board.h>
 #include <plat/gpmc.h>
-#include <plat/gpmc-smsc911x.h>
+#include "gpmc-smsc911x.h"
 
 static struct resource gpmc_smsc911x_resources[] = {
 	[0] = {
diff --git a/arch/arm/mach-omap2/gpmc-smsc911x.h b/arch/arm/mach-omap2/gpmc-smsc911x.h
new file mode 100644
index 0000000..ea6c9c8
--- /dev/null
+++ b/arch/arm/mach-omap2/gpmc-smsc911x.h
@@ -0,0 +1,35 @@
+/*
+ * arch/arm/plat-omap/include/plat/gpmc-smsc911x.h
+ *
+ * Copyright (C) 2009 Li-Pro.Net
+ * Stephan Linz <linz@li-pro.net>
+ *
+ * Modified from arch/arm/plat-omap/include/plat/gpmc-smc91x.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARCH_OMAP_GPMC_SMSC911X_H__
+
+struct omap_smsc911x_platform_data {
+	int	id;
+	int	cs;
+	int	gpio_irq;
+	int	gpio_reset;
+	u32	flags;
+};
+
+#if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)
+
+extern void gpmc_smsc911x_init(struct omap_smsc911x_platform_data *d);
+
+#else
+
+static inline void gpmc_smsc911x_init(struct omap_smsc911x_platform_data *d)
+{
+}
+
+#endif
+#endif
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index b2b5759..72428bd 100644
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -28,8 +28,13 @@
 #include <asm/mach-types.h>
 #include <plat/gpmc.h>
 
+#include <plat/cpu.h>
+#include <plat/gpmc.h>
 #include <plat/sdrc.h>
 
+#include "soc.h"
+#include "common.h"
+
 /* GPMC register offsets */
 #define GPMC_REVISION		0x00
 #define GPMC_SYSCONFIG		0x10
@@ -78,6 +83,15 @@
 #define ENABLE_PREFETCH		(0x1 << 7)
 #define DMA_MPU_MODE		2
 
+/* XXX: Only NAND irq has been considered,currently these are the only ones used
+ */
+#define	GPMC_NR_IRQ		2
+
+struct gpmc_client_irq	{
+	unsigned		irq;
+	u32			bitmask;
+};
+
 /* Structure to save gpmc cs context */
 struct gpmc_cs_config {
 	u32 config1;
@@ -105,6 +119,10 @@ struct omap3_gpmc_regs {
 	struct gpmc_cs_config cs_context[GPMC_CS_NUM];
 };
 
+static struct gpmc_client_irq gpmc_client_irq[GPMC_NR_IRQ];
+static struct irq_chip gpmc_irq_chip;
+static unsigned gpmc_irq_start;
+
 static struct resource	gpmc_mem_root;
 static struct resource	gpmc_cs_mem[GPMC_CS_NUM];
 static DEFINE_SPINLOCK(gpmc_mem_lock);
@@ -279,7 +297,7 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t)
 
 	div = gpmc_cs_calc_divider(cs, t->sync_clk);
 	if (div < 0)
-		return -1;
+		return div;
 
 	GPMC_SET_ONE(GPMC_CS_CONFIG2,  0,  3, cs_on);
 	GPMC_SET_ONE(GPMC_CS_CONFIG2,  8, 12, cs_rd_off);
@@ -682,6 +700,117 @@ int gpmc_prefetch_reset(int cs)
 }
 EXPORT_SYMBOL(gpmc_prefetch_reset);
 
+void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs)
+{
+	reg->gpmc_status = gpmc_base + GPMC_STATUS;
+	reg->gpmc_nand_command = gpmc_base + GPMC_CS0_OFFSET +
+				GPMC_CS_NAND_COMMAND + GPMC_CS_SIZE * cs;
+	reg->gpmc_nand_address = gpmc_base + GPMC_CS0_OFFSET +
+				GPMC_CS_NAND_ADDRESS + GPMC_CS_SIZE * cs;
+	reg->gpmc_nand_data = gpmc_base + GPMC_CS0_OFFSET +
+				GPMC_CS_NAND_DATA + GPMC_CS_SIZE * cs;
+	reg->gpmc_prefetch_config1 = gpmc_base + GPMC_PREFETCH_CONFIG1;
+	reg->gpmc_prefetch_config2 = gpmc_base + GPMC_PREFETCH_CONFIG2;
+	reg->gpmc_prefetch_control = gpmc_base + GPMC_PREFETCH_CONTROL;
+	reg->gpmc_prefetch_status = gpmc_base + GPMC_PREFETCH_STATUS;
+	reg->gpmc_ecc_config = gpmc_base + GPMC_ECC_CONFIG;
+	reg->gpmc_ecc_control = gpmc_base + GPMC_ECC_CONTROL;
+	reg->gpmc_ecc_size_config = gpmc_base + GPMC_ECC_SIZE_CONFIG;
+	reg->gpmc_ecc1_result = gpmc_base + GPMC_ECC1_RESULT;
+	reg->gpmc_bch_result0 = gpmc_base + GPMC_ECC_BCH_RESULT_0;
+}
+
+int gpmc_get_client_irq(unsigned irq_config)
+{
+	int i;
+
+	if (hweight32(irq_config) > 1)
+		return 0;
+
+	for (i = 0; i < GPMC_NR_IRQ; i++)
+		if (gpmc_client_irq[i].bitmask & irq_config)
+			return gpmc_client_irq[i].irq;
+
+	return 0;
+}
+
+static int gpmc_irq_endis(unsigned irq, bool endis)
+{
+	int i;
+	u32 regval;
+
+	for (i = 0; i < GPMC_NR_IRQ; i++)
+		if (irq == gpmc_client_irq[i].irq) {
+			regval = gpmc_read_reg(GPMC_IRQENABLE);
+			if (endis)
+				regval |= gpmc_client_irq[i].bitmask;
+			else
+				regval &= ~gpmc_client_irq[i].bitmask;
+			gpmc_write_reg(GPMC_IRQENABLE, regval);
+			break;
+		}
+
+	return 0;
+}
+
+static void gpmc_irq_disable(struct irq_data *p)
+{
+	gpmc_irq_endis(p->irq, false);
+}
+
+static void gpmc_irq_enable(struct irq_data *p)
+{
+	gpmc_irq_endis(p->irq, true);
+}
+
+static void gpmc_irq_noop(struct irq_data *data) { }
+
+static unsigned int gpmc_irq_noop_ret(struct irq_data *data) { return 0; }
+
+static int gpmc_setup_irq(int gpmc_irq)
+{
+	int i;
+	u32 regval;
+
+	if (!gpmc_irq)
+		return -EINVAL;
+
+	gpmc_irq_start = irq_alloc_descs(-1, 0, GPMC_NR_IRQ, 0);
+	if (IS_ERR_VALUE(gpmc_irq_start)) {
+		pr_err("irq_alloc_descs failed\n");
+		return gpmc_irq_start;
+	}
+
+	gpmc_irq_chip.name = "gpmc";
+	gpmc_irq_chip.irq_startup = gpmc_irq_noop_ret;
+	gpmc_irq_chip.irq_enable = gpmc_irq_enable;
+	gpmc_irq_chip.irq_disable = gpmc_irq_disable;
+	gpmc_irq_chip.irq_shutdown = gpmc_irq_noop;
+	gpmc_irq_chip.irq_ack = gpmc_irq_noop;
+	gpmc_irq_chip.irq_mask = gpmc_irq_noop;
+	gpmc_irq_chip.irq_unmask = gpmc_irq_noop;
+
+	gpmc_client_irq[0].bitmask = GPMC_IRQ_FIFOEVENTENABLE;
+	gpmc_client_irq[1].bitmask = GPMC_IRQ_COUNT_EVENT;
+
+	for (i = 0; i < GPMC_NR_IRQ; i++) {
+		gpmc_client_irq[i].irq = gpmc_irq_start + i;
+		irq_set_chip_and_handler(gpmc_client_irq[i].irq,
+					&gpmc_irq_chip, handle_simple_irq);
+		set_irq_flags(gpmc_client_irq[i].irq,
+				IRQF_VALID | IRQF_NOAUTOEN);
+	}
+
+	/* Disable interrupts */
+	gpmc_write_reg(GPMC_IRQENABLE, 0);
+
+	/* clear interrupts */
+	regval = gpmc_read_reg(GPMC_IRQSTATUS);
+	gpmc_write_reg(GPMC_IRQSTATUS, regval);
+
+	return request_irq(gpmc_irq, gpmc_handle_irq, 0, "gpmc", NULL);
+}
+
 static void __init gpmc_mem_init(void)
 {
 	int cs;
@@ -711,8 +840,8 @@ static void __init gpmc_mem_init(void)
 
 static int __init gpmc_init(void)
 {
-	u32 l, irq;
-	int cs, ret = -EINVAL;
+	u32 l;
+	int ret = -EINVAL;
 	int gpmc_irq;
 	char *ck = NULL;
 
@@ -722,16 +851,16 @@ static int __init gpmc_init(void)
 			l = OMAP2420_GPMC_BASE;
 		else
 			l = OMAP34XX_GPMC_BASE;
-		gpmc_irq = INT_34XX_GPMC_IRQ;
+		gpmc_irq = 20 + OMAP_INTC_START;
 	} else if (cpu_is_omap34xx()) {
 		ck = "gpmc_fck";
 		l = OMAP34XX_GPMC_BASE;
-		gpmc_irq = INT_34XX_GPMC_IRQ;
+		gpmc_irq = 20 + OMAP_INTC_START;
 	} else if (cpu_is_omap44xx() || soc_is_omap54xx()) {
 		/* Base address and irq number are same for OMAP4/5 */
 		ck = "gpmc_ck";
 		l = OMAP44XX_GPMC_BASE;
-		gpmc_irq = OMAP44XX_IRQ_GPMC;
+		gpmc_irq = 20 + OMAP44XX_IRQ_GIC_START;
 	}
 
 	if (WARN_ON(!ck))
@@ -761,16 +890,7 @@ static int __init gpmc_init(void)
 	gpmc_write_reg(GPMC_SYSCONFIG, l);
 	gpmc_mem_init();
 
-	/* initalize the irq_chained */
-	irq = OMAP_GPMC_IRQ_BASE;
-	for (cs = 0; cs < GPMC_CS_NUM; cs++) {
-		irq_set_chip_and_handler(irq, &dummy_irq_chip,
-						handle_simple_irq);
-		set_irq_flags(irq, IRQF_VALID);
-		irq++;
-	}
-
-	ret = request_irq(gpmc_irq, gpmc_handle_irq, IRQF_SHARED, "gpmc", NULL);
+	ret = gpmc_setup_irq(gpmc_irq);
 	if (ret)
 		pr_err("gpmc: irq-%d could not claim: err %d\n",
 						gpmc_irq, ret);
@@ -780,12 +900,19 @@ postcore_initcall(gpmc_init);
 
 static irqreturn_t gpmc_handle_irq(int irq, void *dev)
 {
-	u8 cs;
+	int i;
+	u32 regval;
+
+	regval = gpmc_read_reg(GPMC_IRQSTATUS);
+
+	if (!regval)
+		return IRQ_NONE;
+
+	for (i = 0; i < GPMC_NR_IRQ; i++)
+		if (regval & gpmc_client_irq[i].bitmask)
+			generic_handle_irq(gpmc_client_irq[i].irq);
 
-	/* check cs to invoke the irq */
-	cs = ((gpmc_read_reg(GPMC_PREFETCH_CONFIG1)) >> CS_NUM_SHIFT) & 0x7;
-	if (OMAP_GPMC_IRQ_BASE+cs <= OMAP_GPMC_IRQ_END)
-		generic_handle_irq(OMAP_GPMC_IRQ_BASE+cs);
+	gpmc_write_reg(GPMC_IRQSTATUS, regval);
 
 	return IRQ_HANDLED;
 }
diff --git a/arch/arm/mach-omap2/hdq1w.c b/arch/arm/mach-omap2/hdq1w.c
index cdd6dda..e003f2b 100644
--- a/arch/arm/mach-omap2/hdq1w.c
+++ b/arch/arm/mach-omap2/hdq1w.c
@@ -29,7 +29,7 @@
 
 #include <plat/omap_hwmod.h>
 #include <plat/omap_device.h>
-#include <plat/hdq1w.h>
+#include "hdq1w.h"
 
 #include "common.h"
 
diff --git a/arch/arm/mach-omap2/hdq1w.h b/arch/arm/mach-omap2/hdq1w.h
new file mode 100644
index 0000000..0c1efc8
--- /dev/null
+++ b/arch/arm/mach-omap2/hdq1w.h
@@ -0,0 +1,36 @@
+/*
+ * Shared macros and function prototypes for the HDQ1W/1-wire IP block
+ *
+ * Copyright (C) 2012 Texas Instruments, Inc.
+ * Paul Walmsley
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+#ifndef ARCH_ARM_MACH_OMAP2_HDQ1W_H
+#define ARCH_ARM_MACH_OMAP2_HDQ1W_H
+
+#include <plat/omap_hwmod.h>
+
+/*
+ * XXX A future cleanup patch should modify
+ * drivers/w1/masters/omap_hdq.c to use these macros
+ */
+#define HDQ_CTRL_STATUS_OFFSET			0x0c
+#define HDQ_CTRL_STATUS_CLOCKENABLE_SHIFT	5
+
+
+extern int omap_hdq1w_reset(struct omap_hwmod *oh);
+
+#endif
diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c
index a9675d8..03ebf47 100644
--- a/arch/arm/mach-omap2/hsmmc.c
+++ b/arch/arm/mach-omap2/hsmmc.c
@@ -15,9 +15,10 @@
 #include <linux/delay.h>
 #include <linux/gpio.h>
 #include <mach/hardware.h>
+#include <linux/platform_data/gpio-omap.h>
+
 #include <plat/mmc.h>
 #include <plat/omap-pm.h>
-#include <plat/mux.h>
 #include <plat/omap_device.h>
 
 #include "mux.h"
diff --git a/arch/arm/mach-omap2/i2c.c b/arch/arm/mach-omap2/i2c.c
index a12e224..fc57e67 100644
--- a/arch/arm/mach-omap2/i2c.c
+++ b/arch/arm/mach-omap2/i2c.c
@@ -19,7 +19,6 @@
  *
  */
 
-#include <plat/cpu.h>
 #include <plat/i2c.h>
 #include "common.h"
 #include <plat/omap_hwmod.h>
diff --git a/arch/arm/mach-omap2/id.c b/arch/arm/mach-omap2/id.c
index 40373db..cf2362c 100644
--- a/arch/arm/mach-omap2/id.c
+++ b/arch/arm/mach-omap2/id.c
@@ -22,10 +22,10 @@
 #include <asm/cputype.h>
 
 #include "common.h"
-#include <plat/cpu.h>
 
-#include <mach/id.h>
+#include "id.h"
 
+#include "soc.h"
 #include "control.h"
 
 static unsigned int omap_revision;
@@ -161,9 +161,8 @@ void __init omap2xxx_check_revision(void)
 	}
 
 	if (j == ARRAY_SIZE(omap_ids)) {
-		printk(KERN_ERR "Unknown OMAP device type. "
-				"Handling it as OMAP%04x\n",
-				omap_ids[i].type >> 16);
+		pr_err("Unknown OMAP device type. Handling it as OMAP%04x\n",
+		       omap_ids[i].type >> 16);
 		j = i;
 	}
 
diff --git a/arch/arm/mach-omap2/id.h b/arch/arm/mach-omap2/id.h
new file mode 100644
index 0000000..02ed3aa
--- /dev/null
+++ b/arch/arm/mach-omap2/id.h
@@ -0,0 +1,22 @@
+/*
+ * OMAP2 CPU identification code
+ *
+ * Copyright (C) 2010 Kan-Ru Chen <kanru@0xlab.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef OMAP2_ARCH_ID_H
+#define OMAP2_ARCH_ID_H
+
+struct omap_die_id {
+	u32 id_0;
+	u32 id_1;
+	u32 id_2;
+	u32 id_3;
+};
+
+void omap_get_die_id(struct omap_die_id *odi);
+
+#endif
diff --git a/arch/arm/mach-omap2/include/mach/am35xx.h b/arch/arm/mach-omap2/include/mach/am35xx.h
deleted file mode 100644
index 9559449..0000000
--- a/arch/arm/mach-omap2/include/mach/am35xx.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*:
- * Address mappings and base address for AM35XX specific interconnects
- * and peripherals.
- *
- * Copyright (C) 2009 Texas Instruments
- *
- * Author: Sriramakrishnan <srk@ti.com>
- *	   Vaibhav Hiremath <hvaibhav@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.
- */
-#ifndef __ASM_ARCH_AM35XX_H
-#define __ASM_ARCH_AM35XX_H
-
-/*
- * Base addresses
- *	Note: OMAP3430 IVA2 memory space is being used for AM35xx IPSS modules
- */
-#define AM35XX_IPSS_EMAC_BASE		0x5C000000
-#define AM35XX_IPSS_USBOTGSS_BASE	0x5C040000
-#define AM35XX_IPSS_HECC_BASE		0x5C050000
-#define AM35XX_IPSS_VPFE_BASE		0x5C060000
-
-
-/* HECC module specifc offset definitions */
-#define AM35XX_HECC_SCC_HECC_OFFSET	(0x0)
-#define AM35XX_HECC_SCC_RAM_OFFSET	(0x3000)
-#define AM35XX_HECC_RAM_OFFSET		(0x3000)
-#define AM35XX_HECC_MBOX_OFFSET		(0x2000)
-#define AM35XX_HECC_INT_LINE		(0x0)
-#define AM35XX_HECC_VERSION		(0x1)
-
-#define AM35XX_EMAC_CNTRL_OFFSET	(0x10000)
-#define AM35XX_EMAC_CNTRL_MOD_OFFSET	(0x0)
-#define AM35XX_EMAC_CNTRL_RAM_OFFSET	(0x20000)
-#define AM35XX_EMAC_MDIO_OFFSET		(0x30000)
-#define AM35XX_IPSS_MDIO_BASE		(AM35XX_IPSS_EMAC_BASE + \
-						AM35XX_EMAC_MDIO_OFFSET)
-#define AM35XX_EMAC_CNTRL_RAM_SIZE	(0x2000)
-#define AM35XX_EMAC_RAM_ADDR		(AM3517_EMAC_BASE + \
-						AM3517_EMAC_CNTRL_RAM_OFFSET)
-#define AM35XX_EMAC_HW_RAM_ADDR		(0x01E20000)
-
-#endif  /*  __ASM_ARCH_AM35XX_H */
diff --git a/arch/arm/mach-omap2/include/mach/board-rx51.h b/arch/arm/mach-omap2/include/mach/board-rx51.h
deleted file mode 100644
index b76f49e..0000000
--- a/arch/arm/mach-omap2/include/mach/board-rx51.h
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * Defines for rx51 boards
- */
-
-#ifndef _OMAP_BOARD_RX51_H
-#define _OMAP_BOARD_RX51_H
-
-extern void __init rx51_peripherals_init(void);
-extern void __init rx51_video_mem_init(void);
-
-#endif
diff --git a/arch/arm/mach-omap2/include/mach/board-zoom.h b/arch/arm/mach-omap2/include/mach/board-zoom.h
index 775fdc3..2e94869 100644
--- a/arch/arm/mach-omap2/include/mach/board-zoom.h
+++ b/arch/arm/mach-omap2/include/mach/board-zoom.h
@@ -8,5 +8,3 @@
 extern int __init zoom_debugboard_init(void);
 extern void __init zoom_peripherals_init(void);
 extern void __init zoom_display_init(void);
-
-#define ZOOM2_HEADSET_EXTMUTE_GPIO	153
diff --git a/arch/arm/mach-omap2/include/mach/ctrl_module_core_44xx.h b/arch/arm/mach-omap2/include/mach/ctrl_module_core_44xx.h
deleted file mode 100644
index 0197082..0000000
--- a/arch/arm/mach-omap2/include/mach/ctrl_module_core_44xx.h
+++ /dev/null
@@ -1,392 +0,0 @@
-/*
- * OMAP44xx CTRL_MODULE_CORE registers and bitfields
- *
- * Copyright (C) 2009-2010 Texas Instruments, Inc.
- *
- * Benoit Cousson (b-cousson@ti.com)
- * Santosh Shilimkar (santosh.shilimkar@ti.com)
- *
- * This file is automatically generated from the OMAP hardware databases.
- * We respectfully ask that any modifications to this file be coordinated
- * with the public linux-omap@vger.kernel.org mailing list and the
- * authors above to ensure that the autogeneration scripts are kept
- * up-to-date with the file contents.
- *
- * This program is free software; you can 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_CTRL_MODULE_CORE_44XX_H
-#define __ARCH_ARM_MACH_OMAP2_CTRL_MODULE_CORE_44XX_H
-
-
-/* Base address */
-#define OMAP4_CTRL_MODULE_CORE					0x4a002000
-
-/* Registers offset */
-#define OMAP4_CTRL_MODULE_CORE_IP_REVISION			0x0000
-#define OMAP4_CTRL_MODULE_CORE_IP_HWINFO			0x0004
-#define OMAP4_CTRL_MODULE_CORE_IP_SYSCONFIG			0x0010
-#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_DIE_ID_0		0x0200
-#define OMAP4_CTRL_MODULE_CORE_ID_CODE				0x0204
-#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_DIE_ID_1		0x0208
-#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_DIE_ID_2		0x020c
-#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_DIE_ID_3		0x0210
-#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_PROD_ID_0		0x0214
-#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_PROD_ID_1		0x0218
-#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_USB_CONF		0x021c
-#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_OPP_VDD_WKUP		0x0228
-#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_OPP_BGAP		0x0260
-#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_OPP_DPLL_0		0x0264
-#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_OPP_DPLL_1		0x0268
-#define OMAP4_CTRL_MODULE_CORE_STATUS				0x02c4
-#define OMAP4_CTRL_MODULE_CORE_DEV_CONF				0x0300
-#define OMAP4_CTRL_MODULE_CORE_DSP_BOOTADDR			0x0304
-#define OMAP4_CTRL_MODULE_CORE_LDOVBB_IVA_VOLTAGE_CTRL		0x0314
-#define OMAP4_CTRL_MODULE_CORE_LDOVBB_MPU_VOLTAGE_CTRL		0x0318
-#define OMAP4_CTRL_MODULE_CORE_LDOSRAM_IVA_VOLTAGE_CTRL		0x0320
-#define OMAP4_CTRL_MODULE_CORE_LDOSRAM_MPU_VOLTAGE_CTRL		0x0324
-#define OMAP4_CTRL_MODULE_CORE_LDOSRAM_CORE_VOLTAGE_CTRL	0x0328
-#define OMAP4_CTRL_MODULE_CORE_TEMP_SENSOR			0x032c
-#define OMAP4_CTRL_MODULE_CORE_DPLL_NWELL_TRIM_0		0x0330
-#define OMAP4_CTRL_MODULE_CORE_DPLL_NWELL_TRIM_1		0x0334
-#define OMAP4_CTRL_MODULE_CORE_USBOTGHS_CONTROL			0x033c
-#define OMAP4_CTRL_MODULE_CORE_DSS_CONTROL			0x0340
-#define OMAP4_CTRL_MODULE_CORE_HWOBS_CONTROL			0x0350
-#define OMAP4_CTRL_MODULE_CORE_DEBOBS_FINAL_MUX_SEL		0x0400
-#define OMAP4_CTRL_MODULE_CORE_DEBOBS_MMR_MPU			0x0408
-#define OMAP4_CTRL_MODULE_CORE_CONF_SDMA_REQ_SEL0		0x042c
-#define OMAP4_CTRL_MODULE_CORE_CONF_SDMA_REQ_SEL1		0x0430
-#define OMAP4_CTRL_MODULE_CORE_CONF_SDMA_REQ_SEL2		0x0434
-#define OMAP4_CTRL_MODULE_CORE_CONF_SDMA_REQ_SEL3		0x0438
-#define OMAP4_CTRL_MODULE_CORE_CONF_CLK_SEL0			0x0440
-#define OMAP4_CTRL_MODULE_CORE_CONF_CLK_SEL1			0x0444
-#define OMAP4_CTRL_MODULE_CORE_CONF_CLK_SEL2			0x0448
-#define OMAP4_CTRL_MODULE_CORE_CONF_DPLL_FREQLOCK_SEL		0x044c
-#define OMAP4_CTRL_MODULE_CORE_CONF_DPLL_TINITZ_SEL		0x0450
-#define OMAP4_CTRL_MODULE_CORE_CONF_DPLL_PHASELOCK_SEL		0x0454
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_0		0x0480
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_1		0x0484
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_2		0x0488
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_3		0x048c
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_4		0x0490
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_5		0x0494
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_6		0x0498
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_7		0x049c
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_8		0x04a0
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_9		0x04a4
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_10		0x04a8
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_11		0x04ac
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_12		0x04b0
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_13		0x04b4
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_14		0x04b8
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_15		0x04bc
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_16		0x04c0
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_17		0x04c4
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_18		0x04c8
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_19		0x04cc
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_20		0x04d0
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_21		0x04d4
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_22		0x04d8
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_23		0x04dc
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_24		0x04e0
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_25		0x04e4
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_26		0x04e8
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_27		0x04ec
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_28		0x04f0
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_29		0x04f4
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_30		0x04f8
-#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_31		0x04fc
-
-/* Registers shifts and masks */
-
-/* IP_REVISION */
-#define OMAP4_IP_REV_SCHEME_SHIFT			30
-#define OMAP4_IP_REV_SCHEME_MASK			(0x3 << 30)
-#define OMAP4_IP_REV_FUNC_SHIFT				16
-#define OMAP4_IP_REV_FUNC_MASK				(0xfff << 16)
-#define OMAP4_IP_REV_RTL_SHIFT				11
-#define OMAP4_IP_REV_RTL_MASK				(0x1f << 11)
-#define OMAP4_IP_REV_MAJOR_SHIFT			8
-#define OMAP4_IP_REV_MAJOR_MASK				(0x7 << 8)
-#define OMAP4_IP_REV_CUSTOM_SHIFT			6
-#define OMAP4_IP_REV_CUSTOM_MASK			(0x3 << 6)
-#define OMAP4_IP_REV_MINOR_SHIFT			0
-#define OMAP4_IP_REV_MINOR_MASK				(0x3f << 0)
-
-/* IP_HWINFO */
-#define OMAP4_IP_HWINFO_SHIFT				0
-#define OMAP4_IP_HWINFO_MASK				(0xffffffff << 0)
-
-/* IP_SYSCONFIG */
-#define OMAP4_IP_SYSCONFIG_IDLEMODE_SHIFT		2
-#define OMAP4_IP_SYSCONFIG_IDLEMODE_MASK		(0x3 << 2)
-
-/* STD_FUSE_DIE_ID_0 */
-#define OMAP4_STD_FUSE_DIE_ID_0_SHIFT			0
-#define OMAP4_STD_FUSE_DIE_ID_0_MASK			(0xffffffff << 0)
-
-/* ID_CODE */
-#define OMAP4_STD_FUSE_IDCODE_SHIFT			0
-#define OMAP4_STD_FUSE_IDCODE_MASK			(0xffffffff << 0)
-
-/* STD_FUSE_DIE_ID_1 */
-#define OMAP4_STD_FUSE_DIE_ID_1_SHIFT			0
-#define OMAP4_STD_FUSE_DIE_ID_1_MASK			(0xffffffff << 0)
-
-/* STD_FUSE_DIE_ID_2 */
-#define OMAP4_STD_FUSE_DIE_ID_2_SHIFT			0
-#define OMAP4_STD_FUSE_DIE_ID_2_MASK			(0xffffffff << 0)
-
-/* STD_FUSE_DIE_ID_3 */
-#define OMAP4_STD_FUSE_DIE_ID_3_SHIFT			0
-#define OMAP4_STD_FUSE_DIE_ID_3_MASK			(0xffffffff << 0)
-
-/* STD_FUSE_PROD_ID_0 */
-#define OMAP4_STD_FUSE_PROD_ID_0_SHIFT			0
-#define OMAP4_STD_FUSE_PROD_ID_0_MASK			(0xffffffff << 0)
-
-/* STD_FUSE_PROD_ID_1 */
-#define OMAP4_STD_FUSE_PROD_ID_1_SHIFT			0
-#define OMAP4_STD_FUSE_PROD_ID_1_MASK			(0xffffffff << 0)
-
-/* STD_FUSE_USB_CONF */
-#define OMAP4_USB_PROD_ID_SHIFT				16
-#define OMAP4_USB_PROD_ID_MASK				(0xffff << 16)
-#define OMAP4_USB_VENDOR_ID_SHIFT			0
-#define OMAP4_USB_VENDOR_ID_MASK			(0xffff << 0)
-
-/* STD_FUSE_OPP_VDD_WKUP */
-#define OMAP4_STD_FUSE_OPP_VDD_WKUP_SHIFT		0
-#define OMAP4_STD_FUSE_OPP_VDD_WKUP_MASK		(0xffffffff << 0)
-
-/* STD_FUSE_OPP_BGAP */
-#define OMAP4_STD_FUSE_OPP_BGAP_SHIFT			0
-#define OMAP4_STD_FUSE_OPP_BGAP_MASK			(0xffffffff << 0)
-
-/* STD_FUSE_OPP_DPLL_0 */
-#define OMAP4_STD_FUSE_OPP_DPLL_0_SHIFT			0
-#define OMAP4_STD_FUSE_OPP_DPLL_0_MASK			(0xffffffff << 0)
-
-/* STD_FUSE_OPP_DPLL_1 */
-#define OMAP4_STD_FUSE_OPP_DPLL_1_SHIFT			0
-#define OMAP4_STD_FUSE_OPP_DPLL_1_MASK			(0xffffffff << 0)
-
-/* STATUS */
-#define OMAP4_ATTILA_CONF_SHIFT				11
-#define OMAP4_ATTILA_CONF_MASK				(0x3 << 11)
-#define OMAP4_DEVICE_TYPE_SHIFT				8
-#define OMAP4_DEVICE_TYPE_MASK				(0x7 << 8)
-#define OMAP4_SYS_BOOT_SHIFT				0
-#define OMAP4_SYS_BOOT_MASK				(0xff << 0)
-
-/* DEV_CONF */
-#define OMAP4_DEV_CONF_SHIFT				1
-#define OMAP4_DEV_CONF_MASK				(0x7fffffff << 1)
-#define OMAP4_USBPHY_PD_SHIFT				0
-#define OMAP4_USBPHY_PD_MASK				(1 << 0)
-
-/* LDOVBB_IVA_VOLTAGE_CTRL */
-#define OMAP4_LDOVBBIVA_RBB_MUX_CTRL_SHIFT		26
-#define OMAP4_LDOVBBIVA_RBB_MUX_CTRL_MASK		(1 << 26)
-#define OMAP4_LDOVBBIVA_RBB_VSET_IN_SHIFT		21
-#define OMAP4_LDOVBBIVA_RBB_VSET_IN_MASK		(0x1f << 21)
-#define OMAP4_LDOVBBIVA_RBB_VSET_OUT_SHIFT		16
-#define OMAP4_LDOVBBIVA_RBB_VSET_OUT_MASK		(0x1f << 16)
-#define OMAP4_LDOVBBIVA_FBB_MUX_CTRL_SHIFT		10
-#define OMAP4_LDOVBBIVA_FBB_MUX_CTRL_MASK		(1 << 10)
-#define OMAP4_LDOVBBIVA_FBB_VSET_IN_SHIFT		5
-#define OMAP4_LDOVBBIVA_FBB_VSET_IN_MASK		(0x1f << 5)
-#define OMAP4_LDOVBBIVA_FBB_VSET_OUT_SHIFT		0
-#define OMAP4_LDOVBBIVA_FBB_VSET_OUT_MASK		(0x1f << 0)
-
-/* LDOVBB_MPU_VOLTAGE_CTRL */
-#define OMAP4_LDOVBBMPU_RBB_MUX_CTRL_SHIFT		26
-#define OMAP4_LDOVBBMPU_RBB_MUX_CTRL_MASK		(1 << 26)
-#define OMAP4_LDOVBBMPU_RBB_VSET_IN_SHIFT		21
-#define OMAP4_LDOVBBMPU_RBB_VSET_IN_MASK		(0x1f << 21)
-#define OMAP4_LDOVBBMPU_RBB_VSET_OUT_SHIFT		16
-#define OMAP4_LDOVBBMPU_RBB_VSET_OUT_MASK		(0x1f << 16)
-#define OMAP4_LDOVBBMPU_FBB_MUX_CTRL_SHIFT		10
-#define OMAP4_LDOVBBMPU_FBB_MUX_CTRL_MASK		(1 << 10)
-#define OMAP4_LDOVBBMPU_FBB_VSET_IN_SHIFT		5
-#define OMAP4_LDOVBBMPU_FBB_VSET_IN_MASK		(0x1f << 5)
-#define OMAP4_LDOVBBMPU_FBB_VSET_OUT_SHIFT		0
-#define OMAP4_LDOVBBMPU_FBB_VSET_OUT_MASK		(0x1f << 0)
-
-/* LDOSRAM_IVA_VOLTAGE_CTRL */
-#define OMAP4_LDOSRAMIVA_RETMODE_MUX_CTRL_SHIFT		26
-#define OMAP4_LDOSRAMIVA_RETMODE_MUX_CTRL_MASK		(1 << 26)
-#define OMAP4_LDOSRAMIVA_RETMODE_VSET_IN_SHIFT		21
-#define OMAP4_LDOSRAMIVA_RETMODE_VSET_IN_MASK		(0x1f << 21)
-#define OMAP4_LDOSRAMIVA_RETMODE_VSET_OUT_SHIFT		16
-#define OMAP4_LDOSRAMIVA_RETMODE_VSET_OUT_MASK		(0x1f << 16)
-#define OMAP4_LDOSRAMIVA_ACTMODE_MUX_CTRL_SHIFT		10
-#define OMAP4_LDOSRAMIVA_ACTMODE_MUX_CTRL_MASK		(1 << 10)
-#define OMAP4_LDOSRAMIVA_ACTMODE_VSET_IN_SHIFT		5
-#define OMAP4_LDOSRAMIVA_ACTMODE_VSET_IN_MASK		(0x1f << 5)
-#define OMAP4_LDOSRAMIVA_ACTMODE_VSET_OUT_SHIFT		0
-#define OMAP4_LDOSRAMIVA_ACTMODE_VSET_OUT_MASK		(0x1f << 0)
-
-/* LDOSRAM_MPU_VOLTAGE_CTRL */
-#define OMAP4_LDOSRAMMPU_RETMODE_MUX_CTRL_SHIFT		26
-#define OMAP4_LDOSRAMMPU_RETMODE_MUX_CTRL_MASK		(1 << 26)
-#define OMAP4_LDOSRAMMPU_RETMODE_VSET_IN_SHIFT		21
-#define OMAP4_LDOSRAMMPU_RETMODE_VSET_IN_MASK		(0x1f << 21)
-#define OMAP4_LDOSRAMMPU_RETMODE_VSET_OUT_SHIFT		16
-#define OMAP4_LDOSRAMMPU_RETMODE_VSET_OUT_MASK		(0x1f << 16)
-#define OMAP4_LDOSRAMMPU_ACTMODE_MUX_CTRL_SHIFT		10
-#define OMAP4_LDOSRAMMPU_ACTMODE_MUX_CTRL_MASK		(1 << 10)
-#define OMAP4_LDOSRAMMPU_ACTMODE_VSET_IN_SHIFT		5
-#define OMAP4_LDOSRAMMPU_ACTMODE_VSET_IN_MASK		(0x1f << 5)
-#define OMAP4_LDOSRAMMPU_ACTMODE_VSET_OUT_SHIFT		0
-#define OMAP4_LDOSRAMMPU_ACTMODE_VSET_OUT_MASK		(0x1f << 0)
-
-/* LDOSRAM_CORE_VOLTAGE_CTRL */
-#define OMAP4_LDOSRAMCORE_RETMODE_MUX_CTRL_SHIFT	26
-#define OMAP4_LDOSRAMCORE_RETMODE_MUX_CTRL_MASK		(1 << 26)
-#define OMAP4_LDOSRAMCORE_RETMODE_VSET_IN_SHIFT		21
-#define OMAP4_LDOSRAMCORE_RETMODE_VSET_IN_MASK		(0x1f << 21)
-#define OMAP4_LDOSRAMCORE_RETMODE_VSET_OUT_SHIFT	16
-#define OMAP4_LDOSRAMCORE_RETMODE_VSET_OUT_MASK		(0x1f << 16)
-#define OMAP4_LDOSRAMCORE_ACTMODE_MUX_CTRL_SHIFT	10
-#define OMAP4_LDOSRAMCORE_ACTMODE_MUX_CTRL_MASK		(1 << 10)
-#define OMAP4_LDOSRAMCORE_ACTMODE_VSET_IN_SHIFT		5
-#define OMAP4_LDOSRAMCORE_ACTMODE_VSET_IN_MASK		(0x1f << 5)
-#define OMAP4_LDOSRAMCORE_ACTMODE_VSET_OUT_SHIFT	0
-#define OMAP4_LDOSRAMCORE_ACTMODE_VSET_OUT_MASK		(0x1f << 0)
-
-/* TEMP_SENSOR */
-#define OMAP4_BGAP_TEMPSOFF_SHIFT			12
-#define OMAP4_BGAP_TEMPSOFF_MASK			(1 << 12)
-#define OMAP4_BGAP_TSHUT_SHIFT				11
-#define OMAP4_BGAP_TSHUT_MASK				(1 << 11)
-#define OMAP4_BGAP_TEMP_SENSOR_CONTCONV_SHIFT		10
-#define OMAP4_BGAP_TEMP_SENSOR_CONTCONV_MASK		(1 << 10)
-#define OMAP4_BGAP_TEMP_SENSOR_SOC_SHIFT		9
-#define OMAP4_BGAP_TEMP_SENSOR_SOC_MASK			(1 << 9)
-#define OMAP4_BGAP_TEMP_SENSOR_EOCZ_SHIFT		8
-#define OMAP4_BGAP_TEMP_SENSOR_EOCZ_MASK		(1 << 8)
-#define OMAP4_BGAP_TEMP_SENSOR_DTEMP_SHIFT		0
-#define OMAP4_BGAP_TEMP_SENSOR_DTEMP_MASK		(0xff << 0)
-
-/* DPLL_NWELL_TRIM_0 */
-#define OMAP4_DPLL_ABE_NWELL_TRIM_MUX_CTRL_SHIFT	29
-#define OMAP4_DPLL_ABE_NWELL_TRIM_MUX_CTRL_MASK		(1 << 29)
-#define OMAP4_DPLL_ABE_NWELL_TRIM_SHIFT			24
-#define OMAP4_DPLL_ABE_NWELL_TRIM_MASK			(0x1f << 24)
-#define OMAP4_DPLL_PER_NWELL_TRIM_MUX_CTRL_SHIFT	23
-#define OMAP4_DPLL_PER_NWELL_TRIM_MUX_CTRL_MASK		(1 << 23)
-#define OMAP4_DPLL_PER_NWELL_TRIM_SHIFT			18
-#define OMAP4_DPLL_PER_NWELL_TRIM_MASK			(0x1f << 18)
-#define OMAP4_DPLL_CORE_NWELL_TRIM_MUX_CTRL_SHIFT	17
-#define OMAP4_DPLL_CORE_NWELL_TRIM_MUX_CTRL_MASK	(1 << 17)
-#define OMAP4_DPLL_CORE_NWELL_TRIM_SHIFT		12
-#define OMAP4_DPLL_CORE_NWELL_TRIM_MASK			(0x1f << 12)
-#define OMAP4_DPLL_IVA_NWELL_TRIM_MUX_CTRL_SHIFT	11
-#define OMAP4_DPLL_IVA_NWELL_TRIM_MUX_CTRL_MASK		(1 << 11)
-#define OMAP4_DPLL_IVA_NWELL_TRIM_SHIFT			6
-#define OMAP4_DPLL_IVA_NWELL_TRIM_MASK			(0x1f << 6)
-#define OMAP4_DPLL_MPU_NWELL_TRIM_MUX_CTRL_SHIFT	5
-#define OMAP4_DPLL_MPU_NWELL_TRIM_MUX_CTRL_MASK		(1 << 5)
-#define OMAP4_DPLL_MPU_NWELL_TRIM_SHIFT			0
-#define OMAP4_DPLL_MPU_NWELL_TRIM_MASK			(0x1f << 0)
-
-/* DPLL_NWELL_TRIM_1 */
-#define OMAP4_DPLL_UNIPRO_NWELL_TRIM_MUX_CTRL_SHIFT	29
-#define OMAP4_DPLL_UNIPRO_NWELL_TRIM_MUX_CTRL_MASK	(1 << 29)
-#define OMAP4_DPLL_UNIPRO_NWELL_TRIM_SHIFT		24
-#define OMAP4_DPLL_UNIPRO_NWELL_TRIM_MASK		(0x1f << 24)
-#define OMAP4_DPLL_USB_NWELL_TRIM_MUX_CTRL_SHIFT	23
-#define OMAP4_DPLL_USB_NWELL_TRIM_MUX_CTRL_MASK		(1 << 23)
-#define OMAP4_DPLL_USB_NWELL_TRIM_SHIFT			18
-#define OMAP4_DPLL_USB_NWELL_TRIM_MASK			(0x1f << 18)
-#define OMAP4_DPLL_HDMI_NWELL_TRIM_MUX_CTRL_SHIFT	17
-#define OMAP4_DPLL_HDMI_NWELL_TRIM_MUX_CTRL_MASK	(1 << 17)
-#define OMAP4_DPLL_HDMI_NWELL_TRIM_SHIFT		12
-#define OMAP4_DPLL_HDMI_NWELL_TRIM_MASK			(0x1f << 12)
-#define OMAP4_DPLL_DSI2_NWELL_TRIM_MUX_CTRL_SHIFT	11
-#define OMAP4_DPLL_DSI2_NWELL_TRIM_MUX_CTRL_MASK	(1 << 11)
-#define OMAP4_DPLL_DSI2_NWELL_TRIM_SHIFT		6
-#define OMAP4_DPLL_DSI2_NWELL_TRIM_MASK			(0x1f << 6)
-#define OMAP4_DPLL_DSI1_NWELL_TRIM_MUX_CTRL_SHIFT	5
-#define OMAP4_DPLL_DSI1_NWELL_TRIM_MUX_CTRL_MASK	(1 << 5)
-#define OMAP4_DPLL_DSI1_NWELL_TRIM_SHIFT		0
-#define OMAP4_DPLL_DSI1_NWELL_TRIM_MASK			(0x1f << 0)
-
-/* USBOTGHS_CONTROL */
-#define OMAP4_DISCHRGVBUS_SHIFT				8
-#define OMAP4_DISCHRGVBUS_MASK				(1 << 8)
-#define OMAP4_CHRGVBUS_SHIFT				7
-#define OMAP4_CHRGVBUS_MASK				(1 << 7)
-#define OMAP4_DRVVBUS_SHIFT				6
-#define OMAP4_DRVVBUS_MASK				(1 << 6)
-#define OMAP4_IDPULLUP_SHIFT				5
-#define OMAP4_IDPULLUP_MASK				(1 << 5)
-#define OMAP4_IDDIG_SHIFT				4
-#define OMAP4_IDDIG_MASK				(1 << 4)
-#define OMAP4_SESSEND_SHIFT				3
-#define OMAP4_SESSEND_MASK				(1 << 3)
-#define OMAP4_VBUSVALID_SHIFT				2
-#define OMAP4_VBUSVALID_MASK				(1 << 2)
-#define OMAP4_BVALID_SHIFT				1
-#define OMAP4_BVALID_MASK				(1 << 1)
-#define OMAP4_AVALID_SHIFT				0
-#define OMAP4_AVALID_MASK				(1 << 0)
-
-/* DSS_CONTROL */
-#define OMAP4_DSS_MUX6_SELECT_SHIFT			0
-#define OMAP4_DSS_MUX6_SELECT_MASK			(1 << 0)
-
-/* HWOBS_CONTROL */
-#define OMAP4_HWOBS_CLKDIV_SEL_SHIFT			3
-#define OMAP4_HWOBS_CLKDIV_SEL_MASK			(0x1f << 3)
-#define OMAP4_HWOBS_ALL_ZERO_MODE_SHIFT			2
-#define OMAP4_HWOBS_ALL_ZERO_MODE_MASK			(1 << 2)
-#define OMAP4_HWOBS_ALL_ONE_MODE_SHIFT			1
-#define OMAP4_HWOBS_ALL_ONE_MODE_MASK			(1 << 1)
-#define OMAP4_HWOBS_MACRO_ENABLE_SHIFT			0
-#define OMAP4_HWOBS_MACRO_ENABLE_MASK			(1 << 0)
-
-/* DEBOBS_FINAL_MUX_SEL */
-#define OMAP4_SELECT_SHIFT				0
-#define OMAP4_SELECT_MASK				(0xffffffff << 0)
-
-/* DEBOBS_MMR_MPU */
-#define OMAP4_SELECT_DEBOBS_MMR_MPU_SHIFT		0
-#define OMAP4_SELECT_DEBOBS_MMR_MPU_MASK		(0xf << 0)
-
-/* CONF_SDMA_REQ_SEL0 */
-#define OMAP4_MULT_SHIFT				0
-#define OMAP4_MULT_MASK					(0x7f << 0)
-
-/* CONF_CLK_SEL0 */
-#define OMAP4_MULT_CONF_CLK_SEL0_SHIFT			0
-#define OMAP4_MULT_CONF_CLK_SEL0_MASK			(0x7 << 0)
-
-/* CONF_CLK_SEL1 */
-#define OMAP4_MULT_CONF_CLK_SEL1_SHIFT			0
-#define OMAP4_MULT_CONF_CLK_SEL1_MASK			(0x7 << 0)
-
-/* CONF_CLK_SEL2 */
-#define OMAP4_MULT_CONF_CLK_SEL2_SHIFT			0
-#define OMAP4_MULT_CONF_CLK_SEL2_MASK			(0x7 << 0)
-
-/* CONF_DPLL_FREQLOCK_SEL */
-#define OMAP4_MULT_CONF_DPLL_FREQLOCK_SEL_SHIFT		0
-#define OMAP4_MULT_CONF_DPLL_FREQLOCK_SEL_MASK		(0x7 << 0)
-
-/* CONF_DPLL_TINITZ_SEL */
-#define OMAP4_MULT_CONF_DPLL_TINITZ_SEL_SHIFT		0
-#define OMAP4_MULT_CONF_DPLL_TINITZ_SEL_MASK		(0x7 << 0)
-
-/* CONF_DPLL_PHASELOCK_SEL */
-#define OMAP4_MULT_CONF_DPLL_PHASELOCK_SEL_SHIFT	0
-#define OMAP4_MULT_CONF_DPLL_PHASELOCK_SEL_MASK		(0x7 << 0)
-
-/* CONF_DEBUG_SEL_TST_0 */
-#define OMAP4_MODE_SHIFT				0
-#define OMAP4_MODE_MASK					(0xf << 0)
-
-#endif
diff --git a/arch/arm/mach-omap2/include/mach/ctrl_module_pad_core_44xx.h b/arch/arm/mach-omap2/include/mach/ctrl_module_pad_core_44xx.h
deleted file mode 100644
index c88420d..0000000
--- a/arch/arm/mach-omap2/include/mach/ctrl_module_pad_core_44xx.h
+++ /dev/null
@@ -1,1409 +0,0 @@
-/*
- * OMAP44xx CTRL_MODULE_PAD_CORE registers and bitfields
- *
- * Copyright (C) 2009-2010 Texas Instruments, Inc.
- *
- * Benoit Cousson (b-cousson@ti.com)
- * Santosh Shilimkar (santosh.shilimkar@ti.com)
- *
- * This file is automatically generated from the OMAP hardware databases.
- * We respectfully ask that any modifications to this file be coordinated
- * with the public linux-omap@vger.kernel.org mailing list and the
- * authors above to ensure that the autogeneration scripts are kept
- * up-to-date with the file contents.
- *
- * This program is free software; you can 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_CTRL_MODULE_PAD_CORE_44XX_H
-#define __ARCH_ARM_MACH_OMAP2_CTRL_MODULE_PAD_CORE_44XX_H
-
-
-/* Base address */
-#define OMAP4_CTRL_MODULE_PAD_CORE				0x4a100000
-
-/* Registers offset */
-#define OMAP4_CTRL_MODULE_PAD_CORE_IP_REVISION			0x0000
-#define OMAP4_CTRL_MODULE_PAD_CORE_IP_HWINFO			0x0004
-#define OMAP4_CTRL_MODULE_PAD_CORE_IP_SYSCONFIG			0x0010
-#define OMAP4_CTRL_MODULE_PAD_CORE_PADCONF_WAKEUPEVENT_0	0x01d8
-#define OMAP4_CTRL_MODULE_PAD_CORE_PADCONF_WAKEUPEVENT_1	0x01dc
-#define OMAP4_CTRL_MODULE_PAD_CORE_PADCONF_WAKEUPEVENT_2	0x01e0
-#define OMAP4_CTRL_MODULE_PAD_CORE_PADCONF_WAKEUPEVENT_3	0x01e4
-#define OMAP4_CTRL_MODULE_PAD_CORE_PADCONF_WAKEUPEVENT_4	0x01e8
-#define OMAP4_CTRL_MODULE_PAD_CORE_PADCONF_WAKEUPEVENT_5	0x01ec
-#define OMAP4_CTRL_MODULE_PAD_CORE_PADCONF_WAKEUPEVENT_6	0x01f0
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_PADCONF_GLOBAL	0x05a0
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_PADCONF_MODE		0x05a4
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_SMART1IO_PADCONF_0	0x05a8
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_SMART1IO_PADCONF_1	0x05ac
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_SMART2IO_PADCONF_0	0x05b0
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_SMART2IO_PADCONF_1	0x05b4
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_SMART3IO_PADCONF_0	0x05b8
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_SMART3IO_PADCONF_1	0x05bc
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_SMART3IO_PADCONF_2	0x05c0
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_USBB_HSIC		0x05c4
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_SLIMBUS		0x05c8
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_PBIASLITE		0x0600
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_I2C_0		0x0604
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_CAMERA_RX		0x0608
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_AVDAC		0x060c
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_HDMI_TX_PHY		0x0610
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_MMC2			0x0614
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_DSIPHY		0x0618
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_MCBSPLP		0x061c
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_USB2PHYCORE		0x0620
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_I2C_1		0x0624
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_MMC1			0x0628
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_HSI			0x062c
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_USB			0x0630
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_HDQ			0x0634
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO1_0		0x0638
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO1_1		0x063c
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO1_2		0x0640
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO1_3		0x0644
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO2_0		0x0648
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO2_1		0x064c
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO2_2		0x0650
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO2_3		0x0654
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_BUS_HOLD		0x0658
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_C2C			0x065c
-#define OMAP4_CTRL_MODULE_PAD_CORE_CORE_CONTROL_SPARE_RW	0x0660
-#define OMAP4_CTRL_MODULE_PAD_CORE_CORE_CONTROL_SPARE_R		0x0664
-#define OMAP4_CTRL_MODULE_PAD_CORE_CORE_CONTROL_SPARE_R_C0	0x0668
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_EFUSE_1		0x0700
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_EFUSE_2		0x0704
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_EFUSE_3		0x0708
-#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_EFUSE_4		0x070c
-
-/* Registers shifts and masks */
-
-/* IP_REVISION */
-#define OMAP4_IP_REV_SCHEME_SHIFT				30
-#define OMAP4_IP_REV_SCHEME_MASK				(0x3 << 30)
-#define OMAP4_IP_REV_FUNC_SHIFT					16
-#define OMAP4_IP_REV_FUNC_MASK					(0xfff << 16)
-#define OMAP4_IP_REV_RTL_SHIFT					11
-#define OMAP4_IP_REV_RTL_MASK					(0x1f << 11)
-#define OMAP4_IP_REV_MAJOR_SHIFT				8
-#define OMAP4_IP_REV_MAJOR_MASK					(0x7 << 8)
-#define OMAP4_IP_REV_CUSTOM_SHIFT				6
-#define OMAP4_IP_REV_CUSTOM_MASK				(0x3 << 6)
-#define OMAP4_IP_REV_MINOR_SHIFT				0
-#define OMAP4_IP_REV_MINOR_MASK					(0x3f << 0)
-
-/* IP_HWINFO */
-#define OMAP4_IP_HWINFO_SHIFT					0
-#define OMAP4_IP_HWINFO_MASK					(0xffffffff << 0)
-
-/* IP_SYSCONFIG */
-#define OMAP4_IP_SYSCONFIG_IDLEMODE_SHIFT			2
-#define OMAP4_IP_SYSCONFIG_IDLEMODE_MASK			(0x3 << 2)
-
-/* PADCONF_WAKEUPEVENT_0 */
-#define OMAP4_GPMC_CLK_DUPLICATEWAKEUPEVENT_SHIFT		31
-#define OMAP4_GPMC_CLK_DUPLICATEWAKEUPEVENT_MASK		(1 << 31)
-#define OMAP4_GPMC_NWP_DUPLICATEWAKEUPEVENT_SHIFT		30
-#define OMAP4_GPMC_NWP_DUPLICATEWAKEUPEVENT_MASK		(1 << 30)
-#define OMAP4_GPMC_NCS3_DUPLICATEWAKEUPEVENT_SHIFT		29
-#define OMAP4_GPMC_NCS3_DUPLICATEWAKEUPEVENT_MASK		(1 << 29)
-#define OMAP4_GPMC_NCS2_DUPLICATEWAKEUPEVENT_SHIFT		28
-#define OMAP4_GPMC_NCS2_DUPLICATEWAKEUPEVENT_MASK		(1 << 28)
-#define OMAP4_GPMC_NCS1_DUPLICATEWAKEUPEVENT_SHIFT		27
-#define OMAP4_GPMC_NCS1_DUPLICATEWAKEUPEVENT_MASK		(1 << 27)
-#define OMAP4_GPMC_NCS0_DUPLICATEWAKEUPEVENT_SHIFT		26
-#define OMAP4_GPMC_NCS0_DUPLICATEWAKEUPEVENT_MASK		(1 << 26)
-#define OMAP4_GPMC_A25_DUPLICATEWAKEUPEVENT_SHIFT		25
-#define OMAP4_GPMC_A25_DUPLICATEWAKEUPEVENT_MASK		(1 << 25)
-#define OMAP4_GPMC_A24_DUPLICATEWAKEUPEVENT_SHIFT		24
-#define OMAP4_GPMC_A24_DUPLICATEWAKEUPEVENT_MASK		(1 << 24)
-#define OMAP4_GPMC_A23_DUPLICATEWAKEUPEVENT_SHIFT		23
-#define OMAP4_GPMC_A23_DUPLICATEWAKEUPEVENT_MASK		(1 << 23)
-#define OMAP4_GPMC_A22_DUPLICATEWAKEUPEVENT_SHIFT		22
-#define OMAP4_GPMC_A22_DUPLICATEWAKEUPEVENT_MASK		(1 << 22)
-#define OMAP4_GPMC_A21_DUPLICATEWAKEUPEVENT_SHIFT		21
-#define OMAP4_GPMC_A21_DUPLICATEWAKEUPEVENT_MASK		(1 << 21)
-#define OMAP4_GPMC_A20_DUPLICATEWAKEUPEVENT_SHIFT		20
-#define OMAP4_GPMC_A20_DUPLICATEWAKEUPEVENT_MASK		(1 << 20)
-#define OMAP4_GPMC_A19_DUPLICATEWAKEUPEVENT_SHIFT		19
-#define OMAP4_GPMC_A19_DUPLICATEWAKEUPEVENT_MASK		(1 << 19)
-#define OMAP4_GPMC_A18_DUPLICATEWAKEUPEVENT_SHIFT		18
-#define OMAP4_GPMC_A18_DUPLICATEWAKEUPEVENT_MASK		(1 << 18)
-#define OMAP4_GPMC_A17_DUPLICATEWAKEUPEVENT_SHIFT		17
-#define OMAP4_GPMC_A17_DUPLICATEWAKEUPEVENT_MASK		(1 << 17)
-#define OMAP4_GPMC_A16_DUPLICATEWAKEUPEVENT_SHIFT		16
-#define OMAP4_GPMC_A16_DUPLICATEWAKEUPEVENT_MASK		(1 << 16)
-#define OMAP4_GPMC_AD15_DUPLICATEWAKEUPEVENT_SHIFT		15
-#define OMAP4_GPMC_AD15_DUPLICATEWAKEUPEVENT_MASK		(1 << 15)
-#define OMAP4_GPMC_AD14_DUPLICATEWAKEUPEVENT_SHIFT		14
-#define OMAP4_GPMC_AD14_DUPLICATEWAKEUPEVENT_MASK		(1 << 14)
-#define OMAP4_GPMC_AD13_DUPLICATEWAKEUPEVENT_SHIFT		13
-#define OMAP4_GPMC_AD13_DUPLICATEWAKEUPEVENT_MASK		(1 << 13)
-#define OMAP4_GPMC_AD12_DUPLICATEWAKEUPEVENT_SHIFT		12
-#define OMAP4_GPMC_AD12_DUPLICATEWAKEUPEVENT_MASK		(1 << 12)
-#define OMAP4_GPMC_AD11_DUPLICATEWAKEUPEVENT_SHIFT		11
-#define OMAP4_GPMC_AD11_DUPLICATEWAKEUPEVENT_MASK		(1 << 11)
-#define OMAP4_GPMC_AD10_DUPLICATEWAKEUPEVENT_SHIFT		10
-#define OMAP4_GPMC_AD10_DUPLICATEWAKEUPEVENT_MASK		(1 << 10)
-#define OMAP4_GPMC_AD9_DUPLICATEWAKEUPEVENT_SHIFT		9
-#define OMAP4_GPMC_AD9_DUPLICATEWAKEUPEVENT_MASK		(1 << 9)
-#define OMAP4_GPMC_AD8_DUPLICATEWAKEUPEVENT_SHIFT		8
-#define OMAP4_GPMC_AD8_DUPLICATEWAKEUPEVENT_MASK		(1 << 8)
-#define OMAP4_GPMC_AD7_DUPLICATEWAKEUPEVENT_SHIFT		7
-#define OMAP4_GPMC_AD7_DUPLICATEWAKEUPEVENT_MASK		(1 << 7)
-#define OMAP4_GPMC_AD6_DUPLICATEWAKEUPEVENT_SHIFT		6
-#define OMAP4_GPMC_AD6_DUPLICATEWAKEUPEVENT_MASK		(1 << 6)
-#define OMAP4_GPMC_AD5_DUPLICATEWAKEUPEVENT_SHIFT		5
-#define OMAP4_GPMC_AD5_DUPLICATEWAKEUPEVENT_MASK		(1 << 5)
-#define OMAP4_GPMC_AD4_DUPLICATEWAKEUPEVENT_SHIFT		4
-#define OMAP4_GPMC_AD4_DUPLICATEWAKEUPEVENT_MASK		(1 << 4)
-#define OMAP4_GPMC_AD3_DUPLICATEWAKEUPEVENT_SHIFT		3
-#define OMAP4_GPMC_AD3_DUPLICATEWAKEUPEVENT_MASK		(1 << 3)
-#define OMAP4_GPMC_AD2_DUPLICATEWAKEUPEVENT_SHIFT		2
-#define OMAP4_GPMC_AD2_DUPLICATEWAKEUPEVENT_MASK		(1 << 2)
-#define OMAP4_GPMC_AD1_DUPLICATEWAKEUPEVENT_SHIFT		1
-#define OMAP4_GPMC_AD1_DUPLICATEWAKEUPEVENT_MASK		(1 << 1)
-#define OMAP4_GPMC_AD0_DUPLICATEWAKEUPEVENT_SHIFT		0
-#define OMAP4_GPMC_AD0_DUPLICATEWAKEUPEVENT_MASK		(1 << 0)
-
-/* PADCONF_WAKEUPEVENT_1 */
-#define OMAP4_CAM_STROBE_DUPLICATEWAKEUPEVENT_SHIFT		31
-#define OMAP4_CAM_STROBE_DUPLICATEWAKEUPEVENT_MASK		(1 << 31)
-#define OMAP4_CAM_SHUTTER_DUPLICATEWAKEUPEVENT_SHIFT		30
-#define OMAP4_CAM_SHUTTER_DUPLICATEWAKEUPEVENT_MASK		(1 << 30)
-#define OMAP4_CSI22_DY1_DUPLICATEWAKEUPEVENT_SHIFT		29
-#define OMAP4_CSI22_DY1_DUPLICATEWAKEUPEVENT_MASK		(1 << 29)
-#define OMAP4_CSI22_DX1_DUPLICATEWAKEUPEVENT_SHIFT		28
-#define OMAP4_CSI22_DX1_DUPLICATEWAKEUPEVENT_MASK		(1 << 28)
-#define OMAP4_CSI22_DY0_DUPLICATEWAKEUPEVENT_SHIFT		27
-#define OMAP4_CSI22_DY0_DUPLICATEWAKEUPEVENT_MASK		(1 << 27)
-#define OMAP4_CSI22_DX0_DUPLICATEWAKEUPEVENT_SHIFT		26
-#define OMAP4_CSI22_DX0_DUPLICATEWAKEUPEVENT_MASK		(1 << 26)
-#define OMAP4_CSI21_DY4_DUPLICATEWAKEUPEVENT_SHIFT		25
-#define OMAP4_CSI21_DY4_DUPLICATEWAKEUPEVENT_MASK		(1 << 25)
-#define OMAP4_CSI21_DX4_DUPLICATEWAKEUPEVENT_SHIFT		24
-#define OMAP4_CSI21_DX4_DUPLICATEWAKEUPEVENT_MASK		(1 << 24)
-#define OMAP4_CSI21_DY3_DUPLICATEWAKEUPEVENT_SHIFT		23
-#define OMAP4_CSI21_DY3_DUPLICATEWAKEUPEVENT_MASK		(1 << 23)
-#define OMAP4_CSI21_DX3_DUPLICATEWAKEUPEVENT_SHIFT		22
-#define OMAP4_CSI21_DX3_DUPLICATEWAKEUPEVENT_MASK		(1 << 22)
-#define OMAP4_CSI21_DY2_DUPLICATEWAKEUPEVENT_SHIFT		21
-#define OMAP4_CSI21_DY2_DUPLICATEWAKEUPEVENT_MASK		(1 << 21)
-#define OMAP4_CSI21_DX2_DUPLICATEWAKEUPEVENT_SHIFT		20
-#define OMAP4_CSI21_DX2_DUPLICATEWAKEUPEVENT_MASK		(1 << 20)
-#define OMAP4_CSI21_DY1_DUPLICATEWAKEUPEVENT_SHIFT		19
-#define OMAP4_CSI21_DY1_DUPLICATEWAKEUPEVENT_MASK		(1 << 19)
-#define OMAP4_CSI21_DX1_DUPLICATEWAKEUPEVENT_SHIFT		18
-#define OMAP4_CSI21_DX1_DUPLICATEWAKEUPEVENT_MASK		(1 << 18)
-#define OMAP4_CSI21_DY0_DUPLICATEWAKEUPEVENT_SHIFT		17
-#define OMAP4_CSI21_DY0_DUPLICATEWAKEUPEVENT_MASK		(1 << 17)
-#define OMAP4_CSI21_DX0_DUPLICATEWAKEUPEVENT_SHIFT		16
-#define OMAP4_CSI21_DX0_DUPLICATEWAKEUPEVENT_MASK		(1 << 16)
-#define OMAP4_HDMI_DDC_SDA_DUPLICATEWAKEUPEVENT_SHIFT		15
-#define OMAP4_HDMI_DDC_SDA_DUPLICATEWAKEUPEVENT_MASK		(1 << 15)
-#define OMAP4_HDMI_DDC_SCL_DUPLICATEWAKEUPEVENT_SHIFT		14
-#define OMAP4_HDMI_DDC_SCL_DUPLICATEWAKEUPEVENT_MASK		(1 << 14)
-#define OMAP4_HDMI_CEC_DUPLICATEWAKEUPEVENT_SHIFT		13
-#define OMAP4_HDMI_CEC_DUPLICATEWAKEUPEVENT_MASK		(1 << 13)
-#define OMAP4_HDMI_HPD_DUPLICATEWAKEUPEVENT_SHIFT		12
-#define OMAP4_HDMI_HPD_DUPLICATEWAKEUPEVENT_MASK		(1 << 12)
-#define OMAP4_C2C_DATA15_DUPLICATEWAKEUPEVENT_SHIFT		11
-#define OMAP4_C2C_DATA15_DUPLICATEWAKEUPEVENT_MASK		(1 << 11)
-#define OMAP4_C2C_DATA14_DUPLICATEWAKEUPEVENT_SHIFT		10
-#define OMAP4_C2C_DATA14_DUPLICATEWAKEUPEVENT_MASK		(1 << 10)
-#define OMAP4_C2C_DATA13_DUPLICATEWAKEUPEVENT_SHIFT		9
-#define OMAP4_C2C_DATA13_DUPLICATEWAKEUPEVENT_MASK		(1 << 9)
-#define OMAP4_C2C_DATA12_DUPLICATEWAKEUPEVENT_SHIFT		8
-#define OMAP4_C2C_DATA12_DUPLICATEWAKEUPEVENT_MASK		(1 << 8)
-#define OMAP4_C2C_DATA11_DUPLICATEWAKEUPEVENT_SHIFT		7
-#define OMAP4_C2C_DATA11_DUPLICATEWAKEUPEVENT_MASK		(1 << 7)
-#define OMAP4_GPMC_WAIT1_DUPLICATEWAKEUPEVENT_SHIFT		6
-#define OMAP4_GPMC_WAIT1_DUPLICATEWAKEUPEVENT_MASK		(1 << 6)
-#define OMAP4_GPMC_WAIT0_DUPLICATEWAKEUPEVENT_SHIFT		5
-#define OMAP4_GPMC_WAIT0_DUPLICATEWAKEUPEVENT_MASK		(1 << 5)
-#define OMAP4_GPMC_NBE1_DUPLICATEWAKEUPEVENT_SHIFT		4
-#define OMAP4_GPMC_NBE1_DUPLICATEWAKEUPEVENT_MASK		(1 << 4)
-#define OMAP4_GPMC_NBE0_CLE_DUPLICATEWAKEUPEVENT_SHIFT		3
-#define OMAP4_GPMC_NBE0_CLE_DUPLICATEWAKEUPEVENT_MASK		(1 << 3)
-#define OMAP4_GPMC_NWE_DUPLICATEWAKEUPEVENT_SHIFT		2
-#define OMAP4_GPMC_NWE_DUPLICATEWAKEUPEVENT_MASK		(1 << 2)
-#define OMAP4_GPMC_NOE_DUPLICATEWAKEUPEVENT_SHIFT		1
-#define OMAP4_GPMC_NOE_DUPLICATEWAKEUPEVENT_MASK		(1 << 1)
-#define OMAP4_GPMC_NADV_ALE_DUPLICATEWAKEUPEVENT_SHIFT		0
-#define OMAP4_GPMC_NADV_ALE_DUPLICATEWAKEUPEVENT_MASK		(1 << 0)
-
-/* PADCONF_WAKEUPEVENT_2 */
-#define OMAP4_ABE_MCBSP1_CLKX_DUPLICATEWAKEUPEVENT_SHIFT	31
-#define OMAP4_ABE_MCBSP1_CLKX_DUPLICATEWAKEUPEVENT_MASK		(1 << 31)
-#define OMAP4_ABE_MCBSP2_FSX_DUPLICATEWAKEUPEVENT_SHIFT		30
-#define OMAP4_ABE_MCBSP2_FSX_DUPLICATEWAKEUPEVENT_MASK		(1 << 30)
-#define OMAP4_ABE_MCBSP2_DX_DUPLICATEWAKEUPEVENT_SHIFT		29
-#define OMAP4_ABE_MCBSP2_DX_DUPLICATEWAKEUPEVENT_MASK		(1 << 29)
-#define OMAP4_ABE_MCBSP2_DR_DUPLICATEWAKEUPEVENT_SHIFT		28
-#define OMAP4_ABE_MCBSP2_DR_DUPLICATEWAKEUPEVENT_MASK		(1 << 28)
-#define OMAP4_ABE_MCBSP2_CLKX_DUPLICATEWAKEUPEVENT_SHIFT	27
-#define OMAP4_ABE_MCBSP2_CLKX_DUPLICATEWAKEUPEVENT_MASK		(1 << 27)
-#define OMAP4_SDMMC1_DAT7_DUPLICATEWAKEUPEVENT_SHIFT		26
-#define OMAP4_SDMMC1_DAT7_DUPLICATEWAKEUPEVENT_MASK		(1 << 26)
-#define OMAP4_SDMMC1_DAT6_DUPLICATEWAKEUPEVENT_SHIFT		25
-#define OMAP4_SDMMC1_DAT6_DUPLICATEWAKEUPEVENT_MASK		(1 << 25)
-#define OMAP4_SDMMC1_DAT5_DUPLICATEWAKEUPEVENT_SHIFT		24
-#define OMAP4_SDMMC1_DAT5_DUPLICATEWAKEUPEVENT_MASK		(1 << 24)
-#define OMAP4_SDMMC1_DAT4_DUPLICATEWAKEUPEVENT_SHIFT		23
-#define OMAP4_SDMMC1_DAT4_DUPLICATEWAKEUPEVENT_MASK		(1 << 23)
-#define OMAP4_SDMMC1_DAT3_DUPLICATEWAKEUPEVENT_SHIFT		22
-#define OMAP4_SDMMC1_DAT3_DUPLICATEWAKEUPEVENT_MASK		(1 << 22)
-#define OMAP4_SDMMC1_DAT2_DUPLICATEWAKEUPEVENT_SHIFT		21
-#define OMAP4_SDMMC1_DAT2_DUPLICATEWAKEUPEVENT_MASK		(1 << 21)
-#define OMAP4_SDMMC1_DAT1_DUPLICATEWAKEUPEVENT_SHIFT		20
-#define OMAP4_SDMMC1_DAT1_DUPLICATEWAKEUPEVENT_MASK		(1 << 20)
-#define OMAP4_SDMMC1_DAT0_DUPLICATEWAKEUPEVENT_SHIFT		19
-#define OMAP4_SDMMC1_DAT0_DUPLICATEWAKEUPEVENT_MASK		(1 << 19)
-#define OMAP4_SDMMC1_CMD_DUPLICATEWAKEUPEVENT_SHIFT		18
-#define OMAP4_SDMMC1_CMD_DUPLICATEWAKEUPEVENT_MASK		(1 << 18)
-#define OMAP4_SDMMC1_CLK_DUPLICATEWAKEUPEVENT_SHIFT		17
-#define OMAP4_SDMMC1_CLK_DUPLICATEWAKEUPEVENT_MASK		(1 << 17)
-#define OMAP4_USBC1_ICUSB_DM_DUPLICATEWAKEUPEVENT_SHIFT		16
-#define OMAP4_USBC1_ICUSB_DM_DUPLICATEWAKEUPEVENT_MASK		(1 << 16)
-#define OMAP4_USBC1_ICUSB_DP_DUPLICATEWAKEUPEVENT_SHIFT		15
-#define OMAP4_USBC1_ICUSB_DP_DUPLICATEWAKEUPEVENT_MASK		(1 << 15)
-#define OMAP4_USBB1_HSIC_STROBE_DUPLICATEWAKEUPEVENT_SHIFT	14
-#define OMAP4_USBB1_HSIC_STROBE_DUPLICATEWAKEUPEVENT_MASK	(1 << 14)
-#define OMAP4_USBB1_HSIC_DATA_DUPLICATEWAKEUPEVENT_SHIFT	13
-#define OMAP4_USBB1_HSIC_DATA_DUPLICATEWAKEUPEVENT_MASK		(1 << 13)
-#define OMAP4_USBB1_ULPITLL_DAT7_DUPLICATEWAKEUPEVENT_SHIFT	12
-#define OMAP4_USBB1_ULPITLL_DAT7_DUPLICATEWAKEUPEVENT_MASK	(1 << 12)
-#define OMAP4_USBB1_ULPITLL_DAT6_DUPLICATEWAKEUPEVENT_SHIFT	11
-#define OMAP4_USBB1_ULPITLL_DAT6_DUPLICATEWAKEUPEVENT_MASK	(1 << 11)
-#define OMAP4_USBB1_ULPITLL_DAT5_DUPLICATEWAKEUPEVENT_SHIFT	10
-#define OMAP4_USBB1_ULPITLL_DAT5_DUPLICATEWAKEUPEVENT_MASK	(1 << 10)
-#define OMAP4_USBB1_ULPITLL_DAT4_DUPLICATEWAKEUPEVENT_SHIFT	9
-#define OMAP4_USBB1_ULPITLL_DAT4_DUPLICATEWAKEUPEVENT_MASK	(1 << 9)
-#define OMAP4_USBB1_ULPITLL_DAT3_DUPLICATEWAKEUPEVENT_SHIFT	8
-#define OMAP4_USBB1_ULPITLL_DAT3_DUPLICATEWAKEUPEVENT_MASK	(1 << 8)
-#define OMAP4_USBB1_ULPITLL_DAT2_DUPLICATEWAKEUPEVENT_SHIFT	7
-#define OMAP4_USBB1_ULPITLL_DAT2_DUPLICATEWAKEUPEVENT_MASK	(1 << 7)
-#define OMAP4_USBB1_ULPITLL_DAT1_DUPLICATEWAKEUPEVENT_SHIFT	6
-#define OMAP4_USBB1_ULPITLL_DAT1_DUPLICATEWAKEUPEVENT_MASK	(1 << 6)
-#define OMAP4_USBB1_ULPITLL_DAT0_DUPLICATEWAKEUPEVENT_SHIFT	5
-#define OMAP4_USBB1_ULPITLL_DAT0_DUPLICATEWAKEUPEVENT_MASK	(1 << 5)
-#define OMAP4_USBB1_ULPITLL_NXT_DUPLICATEWAKEUPEVENT_SHIFT	4
-#define OMAP4_USBB1_ULPITLL_NXT_DUPLICATEWAKEUPEVENT_MASK	(1 << 4)
-#define OMAP4_USBB1_ULPITLL_DIR_DUPLICATEWAKEUPEVENT_SHIFT	3
-#define OMAP4_USBB1_ULPITLL_DIR_DUPLICATEWAKEUPEVENT_MASK	(1 << 3)
-#define OMAP4_USBB1_ULPITLL_STP_DUPLICATEWAKEUPEVENT_SHIFT	2
-#define OMAP4_USBB1_ULPITLL_STP_DUPLICATEWAKEUPEVENT_MASK	(1 << 2)
-#define OMAP4_USBB1_ULPITLL_CLK_DUPLICATEWAKEUPEVENT_SHIFT	1
-#define OMAP4_USBB1_ULPITLL_CLK_DUPLICATEWAKEUPEVENT_MASK	(1 << 1)
-#define OMAP4_CAM_GLOBALRESET_DUPLICATEWAKEUPEVENT_SHIFT	0
-#define OMAP4_CAM_GLOBALRESET_DUPLICATEWAKEUPEVENT_MASK		(1 << 0)
-
-/* PADCONF_WAKEUPEVENT_3 */
-#define OMAP4_MCSPI1_CS3_DUPLICATEWAKEUPEVENT_SHIFT		31
-#define OMAP4_MCSPI1_CS3_DUPLICATEWAKEUPEVENT_MASK		(1 << 31)
-#define OMAP4_MCSPI1_CS2_DUPLICATEWAKEUPEVENT_SHIFT		30
-#define OMAP4_MCSPI1_CS2_DUPLICATEWAKEUPEVENT_MASK		(1 << 30)
-#define OMAP4_MCSPI1_CS1_DUPLICATEWAKEUPEVENT_SHIFT		29
-#define OMAP4_MCSPI1_CS1_DUPLICATEWAKEUPEVENT_MASK		(1 << 29)
-#define OMAP4_MCSPI1_CS0_DUPLICATEWAKEUPEVENT_SHIFT		28
-#define OMAP4_MCSPI1_CS0_DUPLICATEWAKEUPEVENT_MASK		(1 << 28)
-#define OMAP4_MCSPI1_SIMO_DUPLICATEWAKEUPEVENT_SHIFT		27
-#define OMAP4_MCSPI1_SIMO_DUPLICATEWAKEUPEVENT_MASK		(1 << 27)
-#define OMAP4_MCSPI1_SOMI_DUPLICATEWAKEUPEVENT_SHIFT		26
-#define OMAP4_MCSPI1_SOMI_DUPLICATEWAKEUPEVENT_MASK		(1 << 26)
-#define OMAP4_MCSPI1_CLK_DUPLICATEWAKEUPEVENT_SHIFT		25
-#define OMAP4_MCSPI1_CLK_DUPLICATEWAKEUPEVENT_MASK		(1 << 25)
-#define OMAP4_I2C4_SDA_DUPLICATEWAKEUPEVENT_SHIFT		24
-#define OMAP4_I2C4_SDA_DUPLICATEWAKEUPEVENT_MASK		(1 << 24)
-#define OMAP4_I2C4_SCL_DUPLICATEWAKEUPEVENT_SHIFT		23
-#define OMAP4_I2C4_SCL_DUPLICATEWAKEUPEVENT_MASK		(1 << 23)
-#define OMAP4_I2C3_SDA_DUPLICATEWAKEUPEVENT_SHIFT		22
-#define OMAP4_I2C3_SDA_DUPLICATEWAKEUPEVENT_MASK		(1 << 22)
-#define OMAP4_I2C3_SCL_DUPLICATEWAKEUPEVENT_SHIFT		21
-#define OMAP4_I2C3_SCL_DUPLICATEWAKEUPEVENT_MASK		(1 << 21)
-#define OMAP4_I2C2_SDA_DUPLICATEWAKEUPEVENT_SHIFT		20
-#define OMAP4_I2C2_SDA_DUPLICATEWAKEUPEVENT_MASK		(1 << 20)
-#define OMAP4_I2C2_SCL_DUPLICATEWAKEUPEVENT_SHIFT		19
-#define OMAP4_I2C2_SCL_DUPLICATEWAKEUPEVENT_MASK		(1 << 19)
-#define OMAP4_I2C1_SDA_DUPLICATEWAKEUPEVENT_SHIFT		18
-#define OMAP4_I2C1_SDA_DUPLICATEWAKEUPEVENT_MASK		(1 << 18)
-#define OMAP4_I2C1_SCL_DUPLICATEWAKEUPEVENT_SHIFT		17
-#define OMAP4_I2C1_SCL_DUPLICATEWAKEUPEVENT_MASK		(1 << 17)
-#define OMAP4_HDQ_SIO_DUPLICATEWAKEUPEVENT_SHIFT		16
-#define OMAP4_HDQ_SIO_DUPLICATEWAKEUPEVENT_MASK			(1 << 16)
-#define OMAP4_UART2_TX_DUPLICATEWAKEUPEVENT_SHIFT		15
-#define OMAP4_UART2_TX_DUPLICATEWAKEUPEVENT_MASK		(1 << 15)
-#define OMAP4_UART2_RX_DUPLICATEWAKEUPEVENT_SHIFT		14
-#define OMAP4_UART2_RX_DUPLICATEWAKEUPEVENT_MASK		(1 << 14)
-#define OMAP4_UART2_RTS_DUPLICATEWAKEUPEVENT_SHIFT		13
-#define OMAP4_UART2_RTS_DUPLICATEWAKEUPEVENT_MASK		(1 << 13)
-#define OMAP4_UART2_CTS_DUPLICATEWAKEUPEVENT_SHIFT		12
-#define OMAP4_UART2_CTS_DUPLICATEWAKEUPEVENT_MASK		(1 << 12)
-#define OMAP4_ABE_DMIC_DIN3_DUPLICATEWAKEUPEVENT_SHIFT		11
-#define OMAP4_ABE_DMIC_DIN3_DUPLICATEWAKEUPEVENT_MASK		(1 << 11)
-#define OMAP4_ABE_DMIC_DIN2_DUPLICATEWAKEUPEVENT_SHIFT		10
-#define OMAP4_ABE_DMIC_DIN2_DUPLICATEWAKEUPEVENT_MASK		(1 << 10)
-#define OMAP4_ABE_DMIC_DIN1_DUPLICATEWAKEUPEVENT_SHIFT		9
-#define OMAP4_ABE_DMIC_DIN1_DUPLICATEWAKEUPEVENT_MASK		(1 << 9)
-#define OMAP4_ABE_DMIC_CLK1_DUPLICATEWAKEUPEVENT_SHIFT		8
-#define OMAP4_ABE_DMIC_CLK1_DUPLICATEWAKEUPEVENT_MASK		(1 << 8)
-#define OMAP4_ABE_CLKS_DUPLICATEWAKEUPEVENT_SHIFT		7
-#define OMAP4_ABE_CLKS_DUPLICATEWAKEUPEVENT_MASK		(1 << 7)
-#define OMAP4_ABE_PDM_LB_CLK_DUPLICATEWAKEUPEVENT_SHIFT		6
-#define OMAP4_ABE_PDM_LB_CLK_DUPLICATEWAKEUPEVENT_MASK		(1 << 6)
-#define OMAP4_ABE_PDM_FRAME_DUPLICATEWAKEUPEVENT_SHIFT		5
-#define OMAP4_ABE_PDM_FRAME_DUPLICATEWAKEUPEVENT_MASK		(1 << 5)
-#define OMAP4_ABE_PDM_DL_DATA_DUPLICATEWAKEUPEVENT_SHIFT	4
-#define OMAP4_ABE_PDM_DL_DATA_DUPLICATEWAKEUPEVENT_MASK		(1 << 4)
-#define OMAP4_ABE_PDM_UL_DATA_DUPLICATEWAKEUPEVENT_SHIFT	3
-#define OMAP4_ABE_PDM_UL_DATA_DUPLICATEWAKEUPEVENT_MASK		(1 << 3)
-#define OMAP4_ABE_MCBSP1_FSX_DUPLICATEWAKEUPEVENT_SHIFT		2
-#define OMAP4_ABE_MCBSP1_FSX_DUPLICATEWAKEUPEVENT_MASK		(1 << 2)
-#define OMAP4_ABE_MCBSP1_DX_DUPLICATEWAKEUPEVENT_SHIFT		1
-#define OMAP4_ABE_MCBSP1_DX_DUPLICATEWAKEUPEVENT_MASK		(1 << 1)
-#define OMAP4_ABE_MCBSP1_DR_DUPLICATEWAKEUPEVENT_SHIFT		0
-#define OMAP4_ABE_MCBSP1_DR_DUPLICATEWAKEUPEVENT_MASK		(1 << 0)
-
-/* PADCONF_WAKEUPEVENT_4 */
-#define OMAP4_UNIPRO_TY0_DUPLICATEWAKEUPEVENT_SHIFT		31
-#define OMAP4_UNIPRO_TY0_DUPLICATEWAKEUPEVENT_MASK		(1 << 31)
-#define OMAP4_UNIPRO_TX0_DUPLICATEWAKEUPEVENT_SHIFT		30
-#define OMAP4_UNIPRO_TX0_DUPLICATEWAKEUPEVENT_MASK		(1 << 30)
-#define OMAP4_USBB2_HSIC_STROBE_DUPLICATEWAKEUPEVENT_SHIFT	29
-#define OMAP4_USBB2_HSIC_STROBE_DUPLICATEWAKEUPEVENT_MASK	(1 << 29)
-#define OMAP4_USBB2_HSIC_DATA_DUPLICATEWAKEUPEVENT_SHIFT	28
-#define OMAP4_USBB2_HSIC_DATA_DUPLICATEWAKEUPEVENT_MASK		(1 << 28)
-#define OMAP4_USBB2_ULPITLL_DAT7_DUPLICATEWAKEUPEVENT_SHIFT	27
-#define OMAP4_USBB2_ULPITLL_DAT7_DUPLICATEWAKEUPEVENT_MASK	(1 << 27)
-#define OMAP4_USBB2_ULPITLL_DAT6_DUPLICATEWAKEUPEVENT_SHIFT	26
-#define OMAP4_USBB2_ULPITLL_DAT6_DUPLICATEWAKEUPEVENT_MASK	(1 << 26)
-#define OMAP4_USBB2_ULPITLL_DAT5_DUPLICATEWAKEUPEVENT_SHIFT	25
-#define OMAP4_USBB2_ULPITLL_DAT5_DUPLICATEWAKEUPEVENT_MASK	(1 << 25)
-#define OMAP4_USBB2_ULPITLL_DAT4_DUPLICATEWAKEUPEVENT_SHIFT	24
-#define OMAP4_USBB2_ULPITLL_DAT4_DUPLICATEWAKEUPEVENT_MASK	(1 << 24)
-#define OMAP4_USBB2_ULPITLL_DAT3_DUPLICATEWAKEUPEVENT_SHIFT	23
-#define OMAP4_USBB2_ULPITLL_DAT3_DUPLICATEWAKEUPEVENT_MASK	(1 << 23)
-#define OMAP4_USBB2_ULPITLL_DAT2_DUPLICATEWAKEUPEVENT_SHIFT	22
-#define OMAP4_USBB2_ULPITLL_DAT2_DUPLICATEWAKEUPEVENT_MASK	(1 << 22)
-#define OMAP4_USBB2_ULPITLL_DAT1_DUPLICATEWAKEUPEVENT_SHIFT	21
-#define OMAP4_USBB2_ULPITLL_DAT1_DUPLICATEWAKEUPEVENT_MASK	(1 << 21)
-#define OMAP4_USBB2_ULPITLL_DAT0_DUPLICATEWAKEUPEVENT_SHIFT	20
-#define OMAP4_USBB2_ULPITLL_DAT0_DUPLICATEWAKEUPEVENT_MASK	(1 << 20)
-#define OMAP4_USBB2_ULPITLL_NXT_DUPLICATEWAKEUPEVENT_SHIFT	19
-#define OMAP4_USBB2_ULPITLL_NXT_DUPLICATEWAKEUPEVENT_MASK	(1 << 19)
-#define OMAP4_USBB2_ULPITLL_DIR_DUPLICATEWAKEUPEVENT_SHIFT	18
-#define OMAP4_USBB2_ULPITLL_DIR_DUPLICATEWAKEUPEVENT_MASK	(1 << 18)
-#define OMAP4_USBB2_ULPITLL_STP_DUPLICATEWAKEUPEVENT_SHIFT	17
-#define OMAP4_USBB2_ULPITLL_STP_DUPLICATEWAKEUPEVENT_MASK	(1 << 17)
-#define OMAP4_USBB2_ULPITLL_CLK_DUPLICATEWAKEUPEVENT_SHIFT	16
-#define OMAP4_USBB2_ULPITLL_CLK_DUPLICATEWAKEUPEVENT_MASK	(1 << 16)
-#define OMAP4_UART4_TX_DUPLICATEWAKEUPEVENT_SHIFT		15
-#define OMAP4_UART4_TX_DUPLICATEWAKEUPEVENT_MASK		(1 << 15)
-#define OMAP4_UART4_RX_DUPLICATEWAKEUPEVENT_SHIFT		14
-#define OMAP4_UART4_RX_DUPLICATEWAKEUPEVENT_MASK		(1 << 14)
-#define OMAP4_MCSPI4_CS0_DUPLICATEWAKEUPEVENT_SHIFT		13
-#define OMAP4_MCSPI4_CS0_DUPLICATEWAKEUPEVENT_MASK		(1 << 13)
-#define OMAP4_MCSPI4_SOMI_DUPLICATEWAKEUPEVENT_SHIFT		12
-#define OMAP4_MCSPI4_SOMI_DUPLICATEWAKEUPEVENT_MASK		(1 << 12)
-#define OMAP4_MCSPI4_SIMO_DUPLICATEWAKEUPEVENT_SHIFT		11
-#define OMAP4_MCSPI4_SIMO_DUPLICATEWAKEUPEVENT_MASK		(1 << 11)
-#define OMAP4_MCSPI4_CLK_DUPLICATEWAKEUPEVENT_SHIFT		10
-#define OMAP4_MCSPI4_CLK_DUPLICATEWAKEUPEVENT_MASK		(1 << 10)
-#define OMAP4_SDMMC5_DAT3_DUPLICATEWAKEUPEVENT_SHIFT		9
-#define OMAP4_SDMMC5_DAT3_DUPLICATEWAKEUPEVENT_MASK		(1 << 9)
-#define OMAP4_SDMMC5_DAT2_DUPLICATEWAKEUPEVENT_SHIFT		8
-#define OMAP4_SDMMC5_DAT2_DUPLICATEWAKEUPEVENT_MASK		(1 << 8)
-#define OMAP4_SDMMC5_DAT1_DUPLICATEWAKEUPEVENT_SHIFT		7
-#define OMAP4_SDMMC5_DAT1_DUPLICATEWAKEUPEVENT_MASK		(1 << 7)
-#define OMAP4_SDMMC5_DAT0_DUPLICATEWAKEUPEVENT_SHIFT		6
-#define OMAP4_SDMMC5_DAT0_DUPLICATEWAKEUPEVENT_MASK		(1 << 6)
-#define OMAP4_SDMMC5_CMD_DUPLICATEWAKEUPEVENT_SHIFT		5
-#define OMAP4_SDMMC5_CMD_DUPLICATEWAKEUPEVENT_MASK		(1 << 5)
-#define OMAP4_SDMMC5_CLK_DUPLICATEWAKEUPEVENT_SHIFT		4
-#define OMAP4_SDMMC5_CLK_DUPLICATEWAKEUPEVENT_MASK		(1 << 4)
-#define OMAP4_UART3_TX_IRTX_DUPLICATEWAKEUPEVENT_SHIFT		3
-#define OMAP4_UART3_TX_IRTX_DUPLICATEWAKEUPEVENT_MASK		(1 << 3)
-#define OMAP4_UART3_RX_IRRX_DUPLICATEWAKEUPEVENT_SHIFT		2
-#define OMAP4_UART3_RX_IRRX_DUPLICATEWAKEUPEVENT_MASK		(1 << 2)
-#define OMAP4_UART3_RTS_SD_DUPLICATEWAKEUPEVENT_SHIFT		1
-#define OMAP4_UART3_RTS_SD_DUPLICATEWAKEUPEVENT_MASK		(1 << 1)
-#define OMAP4_UART3_CTS_RCTX_DUPLICATEWAKEUPEVENT_SHIFT		0
-#define OMAP4_UART3_CTS_RCTX_DUPLICATEWAKEUPEVENT_MASK		(1 << 0)
-
-/* PADCONF_WAKEUPEVENT_5 */
-#define OMAP4_DPM_EMU11_DUPLICATEWAKEUPEVENT_SHIFT		31
-#define OMAP4_DPM_EMU11_DUPLICATEWAKEUPEVENT_MASK		(1 << 31)
-#define OMAP4_DPM_EMU10_DUPLICATEWAKEUPEVENT_SHIFT		30
-#define OMAP4_DPM_EMU10_DUPLICATEWAKEUPEVENT_MASK		(1 << 30)
-#define OMAP4_DPM_EMU9_DUPLICATEWAKEUPEVENT_SHIFT		29
-#define OMAP4_DPM_EMU9_DUPLICATEWAKEUPEVENT_MASK		(1 << 29)
-#define OMAP4_DPM_EMU8_DUPLICATEWAKEUPEVENT_SHIFT		28
-#define OMAP4_DPM_EMU8_DUPLICATEWAKEUPEVENT_MASK		(1 << 28)
-#define OMAP4_DPM_EMU7_DUPLICATEWAKEUPEVENT_SHIFT		27
-#define OMAP4_DPM_EMU7_DUPLICATEWAKEUPEVENT_MASK		(1 << 27)
-#define OMAP4_DPM_EMU6_DUPLICATEWAKEUPEVENT_SHIFT		26
-#define OMAP4_DPM_EMU6_DUPLICATEWAKEUPEVENT_MASK		(1 << 26)
-#define OMAP4_DPM_EMU5_DUPLICATEWAKEUPEVENT_SHIFT		25
-#define OMAP4_DPM_EMU5_DUPLICATEWAKEUPEVENT_MASK		(1 << 25)
-#define OMAP4_DPM_EMU4_DUPLICATEWAKEUPEVENT_SHIFT		24
-#define OMAP4_DPM_EMU4_DUPLICATEWAKEUPEVENT_MASK		(1 << 24)
-#define OMAP4_DPM_EMU3_DUPLICATEWAKEUPEVENT_SHIFT		23
-#define OMAP4_DPM_EMU3_DUPLICATEWAKEUPEVENT_MASK		(1 << 23)
-#define OMAP4_DPM_EMU2_DUPLICATEWAKEUPEVENT_SHIFT		22
-#define OMAP4_DPM_EMU2_DUPLICATEWAKEUPEVENT_MASK		(1 << 22)
-#define OMAP4_DPM_EMU1_DUPLICATEWAKEUPEVENT_SHIFT		21
-#define OMAP4_DPM_EMU1_DUPLICATEWAKEUPEVENT_MASK		(1 << 21)
-#define OMAP4_DPM_EMU0_DUPLICATEWAKEUPEVENT_SHIFT		20
-#define OMAP4_DPM_EMU0_DUPLICATEWAKEUPEVENT_MASK		(1 << 20)
-#define OMAP4_SYS_BOOT5_DUPLICATEWAKEUPEVENT_SHIFT		19
-#define OMAP4_SYS_BOOT5_DUPLICATEWAKEUPEVENT_MASK		(1 << 19)
-#define OMAP4_SYS_BOOT4_DUPLICATEWAKEUPEVENT_SHIFT		18
-#define OMAP4_SYS_BOOT4_DUPLICATEWAKEUPEVENT_MASK		(1 << 18)
-#define OMAP4_SYS_BOOT3_DUPLICATEWAKEUPEVENT_SHIFT		17
-#define OMAP4_SYS_BOOT3_DUPLICATEWAKEUPEVENT_MASK		(1 << 17)
-#define OMAP4_SYS_BOOT2_DUPLICATEWAKEUPEVENT_SHIFT		16
-#define OMAP4_SYS_BOOT2_DUPLICATEWAKEUPEVENT_MASK		(1 << 16)
-#define OMAP4_SYS_BOOT1_DUPLICATEWAKEUPEVENT_SHIFT		15
-#define OMAP4_SYS_BOOT1_DUPLICATEWAKEUPEVENT_MASK		(1 << 15)
-#define OMAP4_SYS_BOOT0_DUPLICATEWAKEUPEVENT_SHIFT		14
-#define OMAP4_SYS_BOOT0_DUPLICATEWAKEUPEVENT_MASK		(1 << 14)
-#define OMAP4_SYS_NIRQ2_DUPLICATEWAKEUPEVENT_SHIFT		13
-#define OMAP4_SYS_NIRQ2_DUPLICATEWAKEUPEVENT_MASK		(1 << 13)
-#define OMAP4_SYS_NIRQ1_DUPLICATEWAKEUPEVENT_SHIFT		12
-#define OMAP4_SYS_NIRQ1_DUPLICATEWAKEUPEVENT_MASK		(1 << 12)
-#define OMAP4_FREF_CLK2_OUT_DUPLICATEWAKEUPEVENT_SHIFT		11
-#define OMAP4_FREF_CLK2_OUT_DUPLICATEWAKEUPEVENT_MASK		(1 << 11)
-#define OMAP4_FREF_CLK1_OUT_DUPLICATEWAKEUPEVENT_SHIFT		10
-#define OMAP4_FREF_CLK1_OUT_DUPLICATEWAKEUPEVENT_MASK		(1 << 10)
-#define OMAP4_UNIPRO_RY2_DUPLICATEWAKEUPEVENT_SHIFT		9
-#define OMAP4_UNIPRO_RY2_DUPLICATEWAKEUPEVENT_MASK		(1 << 9)
-#define OMAP4_UNIPRO_RX2_DUPLICATEWAKEUPEVENT_SHIFT		8
-#define OMAP4_UNIPRO_RX2_DUPLICATEWAKEUPEVENT_MASK		(1 << 8)
-#define OMAP4_UNIPRO_RY1_DUPLICATEWAKEUPEVENT_SHIFT		7
-#define OMAP4_UNIPRO_RY1_DUPLICATEWAKEUPEVENT_MASK		(1 << 7)
-#define OMAP4_UNIPRO_RX1_DUPLICATEWAKEUPEVENT_SHIFT		6
-#define OMAP4_UNIPRO_RX1_DUPLICATEWAKEUPEVENT_MASK		(1 << 6)
-#define OMAP4_UNIPRO_RY0_DUPLICATEWAKEUPEVENT_SHIFT		5
-#define OMAP4_UNIPRO_RY0_DUPLICATEWAKEUPEVENT_MASK		(1 << 5)
-#define OMAP4_UNIPRO_RX0_DUPLICATEWAKEUPEVENT_SHIFT		4
-#define OMAP4_UNIPRO_RX0_DUPLICATEWAKEUPEVENT_MASK		(1 << 4)
-#define OMAP4_UNIPRO_TY2_DUPLICATEWAKEUPEVENT_SHIFT		3
-#define OMAP4_UNIPRO_TY2_DUPLICATEWAKEUPEVENT_MASK		(1 << 3)
-#define OMAP4_UNIPRO_TX2_DUPLICATEWAKEUPEVENT_SHIFT		2
-#define OMAP4_UNIPRO_TX2_DUPLICATEWAKEUPEVENT_MASK		(1 << 2)
-#define OMAP4_UNIPRO_TY1_DUPLICATEWAKEUPEVENT_SHIFT		1
-#define OMAP4_UNIPRO_TY1_DUPLICATEWAKEUPEVENT_MASK		(1 << 1)
-#define OMAP4_UNIPRO_TX1_DUPLICATEWAKEUPEVENT_SHIFT		0
-#define OMAP4_UNIPRO_TX1_DUPLICATEWAKEUPEVENT_MASK		(1 << 0)
-
-/* PADCONF_WAKEUPEVENT_6 */
-#define OMAP4_DPM_EMU19_DUPLICATEWAKEUPEVENT_SHIFT		7
-#define OMAP4_DPM_EMU19_DUPLICATEWAKEUPEVENT_MASK		(1 << 7)
-#define OMAP4_DPM_EMU18_DUPLICATEWAKEUPEVENT_SHIFT		6
-#define OMAP4_DPM_EMU18_DUPLICATEWAKEUPEVENT_MASK		(1 << 6)
-#define OMAP4_DPM_EMU17_DUPLICATEWAKEUPEVENT_SHIFT		5
-#define OMAP4_DPM_EMU17_DUPLICATEWAKEUPEVENT_MASK		(1 << 5)
-#define OMAP4_DPM_EMU16_DUPLICATEWAKEUPEVENT_SHIFT		4
-#define OMAP4_DPM_EMU16_DUPLICATEWAKEUPEVENT_MASK		(1 << 4)
-#define OMAP4_DPM_EMU15_DUPLICATEWAKEUPEVENT_SHIFT		3
-#define OMAP4_DPM_EMU15_DUPLICATEWAKEUPEVENT_MASK		(1 << 3)
-#define OMAP4_DPM_EMU14_DUPLICATEWAKEUPEVENT_SHIFT		2
-#define OMAP4_DPM_EMU14_DUPLICATEWAKEUPEVENT_MASK		(1 << 2)
-#define OMAP4_DPM_EMU13_DUPLICATEWAKEUPEVENT_SHIFT		1
-#define OMAP4_DPM_EMU13_DUPLICATEWAKEUPEVENT_MASK		(1 << 1)
-#define OMAP4_DPM_EMU12_DUPLICATEWAKEUPEVENT_SHIFT		0
-#define OMAP4_DPM_EMU12_DUPLICATEWAKEUPEVENT_MASK		(1 << 0)
-
-/* CONTROL_PADCONF_GLOBAL */
-#define OMAP4_FORCE_OFFMODE_EN_SHIFT				31
-#define OMAP4_FORCE_OFFMODE_EN_MASK				(1 << 31)
-
-/* CONTROL_PADCONF_MODE */
-#define OMAP4_VDDS_DV_BANK0_SHIFT				31
-#define OMAP4_VDDS_DV_BANK0_MASK				(1 << 31)
-#define OMAP4_VDDS_DV_BANK1_SHIFT				30
-#define OMAP4_VDDS_DV_BANK1_MASK				(1 << 30)
-#define OMAP4_VDDS_DV_BANK3_SHIFT				29
-#define OMAP4_VDDS_DV_BANK3_MASK				(1 << 29)
-#define OMAP4_VDDS_DV_BANK4_SHIFT				28
-#define OMAP4_VDDS_DV_BANK4_MASK				(1 << 28)
-#define OMAP4_VDDS_DV_BANK5_SHIFT				27
-#define OMAP4_VDDS_DV_BANK5_MASK				(1 << 27)
-#define OMAP4_VDDS_DV_BANK6_SHIFT				26
-#define OMAP4_VDDS_DV_BANK6_MASK				(1 << 26)
-#define OMAP4_VDDS_DV_C2C_SHIFT					25
-#define OMAP4_VDDS_DV_C2C_MASK					(1 << 25)
-#define OMAP4_VDDS_DV_CAM_SHIFT					24
-#define OMAP4_VDDS_DV_CAM_MASK					(1 << 24)
-#define OMAP4_VDDS_DV_GPMC_SHIFT				23
-#define OMAP4_VDDS_DV_GPMC_MASK					(1 << 23)
-#define OMAP4_VDDS_DV_SDMMC2_SHIFT				22
-#define OMAP4_VDDS_DV_SDMMC2_MASK				(1 << 22)
-
-/* CONTROL_SMART1IO_PADCONF_0 */
-#define OMAP4_ABE_DR0_SC_SHIFT					30
-#define OMAP4_ABE_DR0_SC_MASK					(0x3 << 30)
-#define OMAP4_CAM_DR0_SC_SHIFT					28
-#define OMAP4_CAM_DR0_SC_MASK					(0x3 << 28)
-#define OMAP4_FREF_DR2_SC_SHIFT					26
-#define OMAP4_FREF_DR2_SC_MASK					(0x3 << 26)
-#define OMAP4_FREF_DR3_SC_SHIFT					24
-#define OMAP4_FREF_DR3_SC_MASK					(0x3 << 24)
-#define OMAP4_GPIO_DR8_SC_SHIFT					22
-#define OMAP4_GPIO_DR8_SC_MASK					(0x3 << 22)
-#define OMAP4_GPIO_DR9_SC_SHIFT					20
-#define OMAP4_GPIO_DR9_SC_MASK					(0x3 << 20)
-#define OMAP4_GPMC_DR2_SC_SHIFT					18
-#define OMAP4_GPMC_DR2_SC_MASK					(0x3 << 18)
-#define OMAP4_GPMC_DR3_SC_SHIFT					16
-#define OMAP4_GPMC_DR3_SC_MASK					(0x3 << 16)
-#define OMAP4_GPMC_DR6_SC_SHIFT					14
-#define OMAP4_GPMC_DR6_SC_MASK					(0x3 << 14)
-#define OMAP4_HDMI_DR0_SC_SHIFT					12
-#define OMAP4_HDMI_DR0_SC_MASK					(0x3 << 12)
-#define OMAP4_MCSPI1_DR0_SC_SHIFT				10
-#define OMAP4_MCSPI1_DR0_SC_MASK				(0x3 << 10)
-#define OMAP4_UART1_DR0_SC_SHIFT				8
-#define OMAP4_UART1_DR0_SC_MASK					(0x3 << 8)
-#define OMAP4_UART3_DR0_SC_SHIFT				6
-#define OMAP4_UART3_DR0_SC_MASK					(0x3 << 6)
-#define OMAP4_UART3_DR1_SC_SHIFT				4
-#define OMAP4_UART3_DR1_SC_MASK					(0x3 << 4)
-#define OMAP4_UNIPRO_DR0_SC_SHIFT				2
-#define OMAP4_UNIPRO_DR0_SC_MASK				(0x3 << 2)
-#define OMAP4_UNIPRO_DR1_SC_SHIFT				0
-#define OMAP4_UNIPRO_DR1_SC_MASK				(0x3 << 0)
-
-/* CONTROL_SMART1IO_PADCONF_1 */
-#define OMAP4_ABE_DR0_LB_SHIFT					30
-#define OMAP4_ABE_DR0_LB_MASK					(0x3 << 30)
-#define OMAP4_CAM_DR0_LB_SHIFT					28
-#define OMAP4_CAM_DR0_LB_MASK					(0x3 << 28)
-#define OMAP4_FREF_DR2_LB_SHIFT					26
-#define OMAP4_FREF_DR2_LB_MASK					(0x3 << 26)
-#define OMAP4_FREF_DR3_LB_SHIFT					24
-#define OMAP4_FREF_DR3_LB_MASK					(0x3 << 24)
-#define OMAP4_GPIO_DR8_LB_SHIFT					22
-#define OMAP4_GPIO_DR8_LB_MASK					(0x3 << 22)
-#define OMAP4_GPIO_DR9_LB_SHIFT					20
-#define OMAP4_GPIO_DR9_LB_MASK					(0x3 << 20)
-#define OMAP4_GPMC_DR2_LB_SHIFT					18
-#define OMAP4_GPMC_DR2_LB_MASK					(0x3 << 18)
-#define OMAP4_GPMC_DR3_LB_SHIFT					16
-#define OMAP4_GPMC_DR3_LB_MASK					(0x3 << 16)
-#define OMAP4_GPMC_DR6_LB_SHIFT					14
-#define OMAP4_GPMC_DR6_LB_MASK					(0x3 << 14)
-#define OMAP4_HDMI_DR0_LB_SHIFT					12
-#define OMAP4_HDMI_DR0_LB_MASK					(0x3 << 12)
-#define OMAP4_MCSPI1_DR0_LB_SHIFT				10
-#define OMAP4_MCSPI1_DR0_LB_MASK				(0x3 << 10)
-#define OMAP4_UART1_DR0_LB_SHIFT				8
-#define OMAP4_UART1_DR0_LB_MASK					(0x3 << 8)
-#define OMAP4_UART3_DR0_LB_SHIFT				6
-#define OMAP4_UART3_DR0_LB_MASK					(0x3 << 6)
-#define OMAP4_UART3_DR1_LB_SHIFT				4
-#define OMAP4_UART3_DR1_LB_MASK					(0x3 << 4)
-#define OMAP4_UNIPRO_DR0_LB_SHIFT				2
-#define OMAP4_UNIPRO_DR0_LB_MASK				(0x3 << 2)
-#define OMAP4_UNIPRO_DR1_LB_SHIFT				0
-#define OMAP4_UNIPRO_DR1_LB_MASK				(0x3 << 0)
-
-/* CONTROL_SMART2IO_PADCONF_0 */
-#define OMAP4_C2C_DR0_LB_SHIFT					31
-#define OMAP4_C2C_DR0_LB_MASK					(1 << 31)
-#define OMAP4_DPM_DR1_LB_SHIFT					30
-#define OMAP4_DPM_DR1_LB_MASK					(1 << 30)
-#define OMAP4_DPM_DR2_LB_SHIFT					29
-#define OMAP4_DPM_DR2_LB_MASK					(1 << 29)
-#define OMAP4_DPM_DR3_LB_SHIFT					28
-#define OMAP4_DPM_DR3_LB_MASK					(1 << 28)
-#define OMAP4_GPIO_DR0_LB_SHIFT					27
-#define OMAP4_GPIO_DR0_LB_MASK					(1 << 27)
-#define OMAP4_GPIO_DR1_LB_SHIFT					26
-#define OMAP4_GPIO_DR1_LB_MASK					(1 << 26)
-#define OMAP4_GPIO_DR10_LB_SHIFT				25
-#define OMAP4_GPIO_DR10_LB_MASK					(1 << 25)
-#define OMAP4_GPIO_DR2_LB_SHIFT					24
-#define OMAP4_GPIO_DR2_LB_MASK					(1 << 24)
-#define OMAP4_GPMC_DR0_LB_SHIFT					23
-#define OMAP4_GPMC_DR0_LB_MASK					(1 << 23)
-#define OMAP4_GPMC_DR1_LB_SHIFT					22
-#define OMAP4_GPMC_DR1_LB_MASK					(1 << 22)
-#define OMAP4_GPMC_DR4_LB_SHIFT					21
-#define OMAP4_GPMC_DR4_LB_MASK					(1 << 21)
-#define OMAP4_GPMC_DR5_LB_SHIFT					20
-#define OMAP4_GPMC_DR5_LB_MASK					(1 << 20)
-#define OMAP4_GPMC_DR7_LB_SHIFT					19
-#define OMAP4_GPMC_DR7_LB_MASK					(1 << 19)
-#define OMAP4_HSI2_DR0_LB_SHIFT					18
-#define OMAP4_HSI2_DR0_LB_MASK					(1 << 18)
-#define OMAP4_HSI2_DR1_LB_SHIFT					17
-#define OMAP4_HSI2_DR1_LB_MASK					(1 << 17)
-#define OMAP4_HSI2_DR2_LB_SHIFT					16
-#define OMAP4_HSI2_DR2_LB_MASK					(1 << 16)
-#define OMAP4_KPD_DR0_LB_SHIFT					15
-#define OMAP4_KPD_DR0_LB_MASK					(1 << 15)
-#define OMAP4_KPD_DR1_LB_SHIFT					14
-#define OMAP4_KPD_DR1_LB_MASK					(1 << 14)
-#define OMAP4_PDM_DR0_LB_SHIFT					13
-#define OMAP4_PDM_DR0_LB_MASK					(1 << 13)
-#define OMAP4_SDMMC2_DR0_LB_SHIFT				12
-#define OMAP4_SDMMC2_DR0_LB_MASK				(1 << 12)
-#define OMAP4_SDMMC3_DR0_LB_SHIFT				11
-#define OMAP4_SDMMC3_DR0_LB_MASK				(1 << 11)
-#define OMAP4_SDMMC4_DR0_LB_SHIFT				10
-#define OMAP4_SDMMC4_DR0_LB_MASK				(1 << 10)
-#define OMAP4_SDMMC4_DR1_LB_SHIFT				9
-#define OMAP4_SDMMC4_DR1_LB_MASK				(1 << 9)
-#define OMAP4_SPI3_DR0_LB_SHIFT					8
-#define OMAP4_SPI3_DR0_LB_MASK					(1 << 8)
-#define OMAP4_SPI3_DR1_LB_SHIFT					7
-#define OMAP4_SPI3_DR1_LB_MASK					(1 << 7)
-#define OMAP4_UART3_DR2_LB_SHIFT				6
-#define OMAP4_UART3_DR2_LB_MASK					(1 << 6)
-#define OMAP4_UART3_DR3_LB_SHIFT				5
-#define OMAP4_UART3_DR3_LB_MASK					(1 << 5)
-#define OMAP4_UART3_DR4_LB_SHIFT				4
-#define OMAP4_UART3_DR4_LB_MASK					(1 << 4)
-#define OMAP4_UART3_DR5_LB_SHIFT				3
-#define OMAP4_UART3_DR5_LB_MASK					(1 << 3)
-#define OMAP4_USBA0_DR1_LB_SHIFT				2
-#define OMAP4_USBA0_DR1_LB_MASK					(1 << 2)
-#define OMAP4_USBA_DR2_LB_SHIFT					1
-#define OMAP4_USBA_DR2_LB_MASK					(1 << 1)
-
-/* CONTROL_SMART2IO_PADCONF_1 */
-#define OMAP4_USBB1_DR0_LB_SHIFT				31
-#define OMAP4_USBB1_DR0_LB_MASK					(1 << 31)
-#define OMAP4_USBB2_DR0_LB_SHIFT				30
-#define OMAP4_USBB2_DR0_LB_MASK					(1 << 30)
-#define OMAP4_USBA0_DR0_LB_SHIFT				29
-#define OMAP4_USBA0_DR0_LB_MASK					(1 << 29)
-
-/* CONTROL_SMART3IO_PADCONF_0 */
-#define OMAP4_DMIC_DR0_MB_SHIFT					30
-#define OMAP4_DMIC_DR0_MB_MASK					(0x3 << 30)
-#define OMAP4_GPIO_DR3_MB_SHIFT					28
-#define OMAP4_GPIO_DR3_MB_MASK					(0x3 << 28)
-#define OMAP4_GPIO_DR4_MB_SHIFT					26
-#define OMAP4_GPIO_DR4_MB_MASK					(0x3 << 26)
-#define OMAP4_GPIO_DR5_MB_SHIFT					24
-#define OMAP4_GPIO_DR5_MB_MASK					(0x3 << 24)
-#define OMAP4_GPIO_DR6_MB_SHIFT					22
-#define OMAP4_GPIO_DR6_MB_MASK					(0x3 << 22)
-#define OMAP4_HSI_DR1_MB_SHIFT					20
-#define OMAP4_HSI_DR1_MB_MASK					(0x3 << 20)
-#define OMAP4_HSI_DR2_MB_SHIFT					18
-#define OMAP4_HSI_DR2_MB_MASK					(0x3 << 18)
-#define OMAP4_HSI_DR3_MB_SHIFT					16
-#define OMAP4_HSI_DR3_MB_MASK					(0x3 << 16)
-#define OMAP4_MCBSP2_DR0_MB_SHIFT				14
-#define OMAP4_MCBSP2_DR0_MB_MASK				(0x3 << 14)
-#define OMAP4_MCSPI4_DR0_MB_SHIFT				12
-#define OMAP4_MCSPI4_DR0_MB_MASK				(0x3 << 12)
-#define OMAP4_MCSPI4_DR1_MB_SHIFT				10
-#define OMAP4_MCSPI4_DR1_MB_MASK				(0x3 << 10)
-#define OMAP4_SDMMC3_DR0_MB_SHIFT				8
-#define OMAP4_SDMMC3_DR0_MB_MASK				(0x3 << 8)
-#define OMAP4_SPI2_DR0_MB_SHIFT					0
-#define OMAP4_SPI2_DR0_MB_MASK					(0x3 << 0)
-
-/* CONTROL_SMART3IO_PADCONF_1 */
-#define OMAP4_SPI2_DR1_MB_SHIFT					30
-#define OMAP4_SPI2_DR1_MB_MASK					(0x3 << 30)
-#define OMAP4_SPI2_DR2_MB_SHIFT					28
-#define OMAP4_SPI2_DR2_MB_MASK					(0x3 << 28)
-#define OMAP4_UART2_DR0_MB_SHIFT				26
-#define OMAP4_UART2_DR0_MB_MASK					(0x3 << 26)
-#define OMAP4_UART2_DR1_MB_SHIFT				24
-#define OMAP4_UART2_DR1_MB_MASK					(0x3 << 24)
-#define OMAP4_UART4_DR0_MB_SHIFT				22
-#define OMAP4_UART4_DR0_MB_MASK					(0x3 << 22)
-#define OMAP4_HSI_DR0_MB_SHIFT					20
-#define OMAP4_HSI_DR0_MB_MASK					(0x3 << 20)
-
-/* CONTROL_SMART3IO_PADCONF_2 */
-#define OMAP4_DMIC_DR0_LB_SHIFT					31
-#define OMAP4_DMIC_DR0_LB_MASK					(1 << 31)
-#define OMAP4_GPIO_DR3_LB_SHIFT					30
-#define OMAP4_GPIO_DR3_LB_MASK					(1 << 30)
-#define OMAP4_GPIO_DR4_LB_SHIFT					29
-#define OMAP4_GPIO_DR4_LB_MASK					(1 << 29)
-#define OMAP4_GPIO_DR5_LB_SHIFT					28
-#define OMAP4_GPIO_DR5_LB_MASK					(1 << 28)
-#define OMAP4_GPIO_DR6_LB_SHIFT					27
-#define OMAP4_GPIO_DR6_LB_MASK					(1 << 27)
-#define OMAP4_HSI_DR1_LB_SHIFT					26
-#define OMAP4_HSI_DR1_LB_MASK					(1 << 26)
-#define OMAP4_HSI_DR2_LB_SHIFT					25
-#define OMAP4_HSI_DR2_LB_MASK					(1 << 25)
-#define OMAP4_HSI_DR3_LB_SHIFT					24
-#define OMAP4_HSI_DR3_LB_MASK					(1 << 24)
-#define OMAP4_MCBSP2_DR0_LB_SHIFT				23
-#define OMAP4_MCBSP2_DR0_LB_MASK				(1 << 23)
-#define OMAP4_MCSPI4_DR0_LB_SHIFT				22
-#define OMAP4_MCSPI4_DR0_LB_MASK				(1 << 22)
-#define OMAP4_MCSPI4_DR1_LB_SHIFT				21
-#define OMAP4_MCSPI4_DR1_LB_MASK				(1 << 21)
-#define OMAP4_SLIMBUS2_DR0_LB_SHIFT				18
-#define OMAP4_SLIMBUS2_DR0_LB_MASK				(1 << 18)
-#define OMAP4_SPI2_DR0_LB_SHIFT					16
-#define OMAP4_SPI2_DR0_LB_MASK					(1 << 16)
-#define OMAP4_SPI2_DR1_LB_SHIFT					15
-#define OMAP4_SPI2_DR1_LB_MASK					(1 << 15)
-#define OMAP4_SPI2_DR2_LB_SHIFT					14
-#define OMAP4_SPI2_DR2_LB_MASK					(1 << 14)
-#define OMAP4_UART2_DR0_LB_SHIFT				13
-#define OMAP4_UART2_DR0_LB_MASK					(1 << 13)
-#define OMAP4_UART2_DR1_LB_SHIFT				12
-#define OMAP4_UART2_DR1_LB_MASK					(1 << 12)
-#define OMAP4_UART4_DR0_LB_SHIFT				11
-#define OMAP4_UART4_DR0_LB_MASK					(1 << 11)
-#define OMAP4_HSI_DR0_LB_SHIFT					10
-#define OMAP4_HSI_DR0_LB_MASK					(1 << 10)
-
-/* CONTROL_USBB_HSIC */
-#define OMAP4_USBB2_DR1_SR_SHIFT				30
-#define OMAP4_USBB2_DR1_SR_MASK					(0x3 << 30)
-#define OMAP4_USBB2_DR1_I_SHIFT					27
-#define OMAP4_USBB2_DR1_I_MASK					(0x7 << 27)
-#define OMAP4_USBB1_DR1_SR_SHIFT				25
-#define OMAP4_USBB1_DR1_SR_MASK					(0x3 << 25)
-#define OMAP4_USBB1_DR1_I_SHIFT					22
-#define OMAP4_USBB1_DR1_I_MASK					(0x7 << 22)
-#define OMAP4_USBB1_HSIC_DATA_WD_SHIFT				20
-#define OMAP4_USBB1_HSIC_DATA_WD_MASK				(0x3 << 20)
-#define OMAP4_USBB1_HSIC_STROBE_WD_SHIFT			18
-#define OMAP4_USBB1_HSIC_STROBE_WD_MASK				(0x3 << 18)
-#define OMAP4_USBB2_HSIC_DATA_WD_SHIFT				16
-#define OMAP4_USBB2_HSIC_DATA_WD_MASK				(0x3 << 16)
-#define OMAP4_USBB2_HSIC_STROBE_WD_SHIFT			14
-#define OMAP4_USBB2_HSIC_STROBE_WD_MASK				(0x3 << 14)
-#define OMAP4_USBB1_HSIC_DATA_OFFMODE_WD_ENABLE_SHIFT		13
-#define OMAP4_USBB1_HSIC_DATA_OFFMODE_WD_ENABLE_MASK		(1 << 13)
-#define OMAP4_USBB1_HSIC_DATA_OFFMODE_WD_SHIFT			11
-#define OMAP4_USBB1_HSIC_DATA_OFFMODE_WD_MASK			(0x3 << 11)
-#define OMAP4_USBB1_HSIC_STROBE_OFFMODE_WD_ENABLE_SHIFT		10
-#define OMAP4_USBB1_HSIC_STROBE_OFFMODE_WD_ENABLE_MASK		(1 << 10)
-#define OMAP4_USBB1_HSIC_STROBE_OFFMODE_WD_SHIFT		8
-#define OMAP4_USBB1_HSIC_STROBE_OFFMODE_WD_MASK			(0x3 << 8)
-#define OMAP4_USBB2_HSIC_DATA_OFFMODE_WD_ENABLE_SHIFT		7
-#define OMAP4_USBB2_HSIC_DATA_OFFMODE_WD_ENABLE_MASK		(1 << 7)
-#define OMAP4_USBB2_HSIC_DATA_OFFMODE_WD_SHIFT			5
-#define OMAP4_USBB2_HSIC_DATA_OFFMODE_WD_MASK			(0x3 << 5)
-#define OMAP4_USBB2_HSIC_STROBE_OFFMODE_WD_ENABLE_SHIFT		4
-#define OMAP4_USBB2_HSIC_STROBE_OFFMODE_WD_ENABLE_MASK		(1 << 4)
-#define OMAP4_USBB2_HSIC_STROBE_OFFMODE_WD_SHIFT		2
-#define OMAP4_USBB2_HSIC_STROBE_OFFMODE_WD_MASK			(0x3 << 2)
-
-/* CONTROL_SLIMBUS */
-#define OMAP4_SLIMBUS1_DR0_MB_SHIFT				30
-#define OMAP4_SLIMBUS1_DR0_MB_MASK				(0x3 << 30)
-#define OMAP4_SLIMBUS1_DR1_MB_SHIFT				28
-#define OMAP4_SLIMBUS1_DR1_MB_MASK				(0x3 << 28)
-#define OMAP4_SLIMBUS2_DR0_MB_SHIFT				26
-#define OMAP4_SLIMBUS2_DR0_MB_MASK				(0x3 << 26)
-#define OMAP4_SLIMBUS2_DR1_MB_SHIFT				24
-#define OMAP4_SLIMBUS2_DR1_MB_MASK				(0x3 << 24)
-#define OMAP4_SLIMBUS2_DR2_MB_SHIFT				22
-#define OMAP4_SLIMBUS2_DR2_MB_MASK				(0x3 << 22)
-#define OMAP4_SLIMBUS2_DR3_MB_SHIFT				20
-#define OMAP4_SLIMBUS2_DR3_MB_MASK				(0x3 << 20)
-#define OMAP4_SLIMBUS1_DR0_LB_SHIFT				19
-#define OMAP4_SLIMBUS1_DR0_LB_MASK				(1 << 19)
-#define OMAP4_SLIMBUS2_DR1_LB_SHIFT				18
-#define OMAP4_SLIMBUS2_DR1_LB_MASK				(1 << 18)
-
-/* CONTROL_PBIASLITE */
-#define OMAP4_USIM_PBIASLITE_HIZ_MODE_SHIFT			31
-#define OMAP4_USIM_PBIASLITE_HIZ_MODE_MASK			(1 << 31)
-#define OMAP4_USIM_PBIASLITE_SUPPLY_HI_OUT_SHIFT		30
-#define OMAP4_USIM_PBIASLITE_SUPPLY_HI_OUT_MASK			(1 << 30)
-#define OMAP4_USIM_PBIASLITE_VMODE_ERROR_SHIFT			29
-#define OMAP4_USIM_PBIASLITE_VMODE_ERROR_MASK			(1 << 29)
-#define OMAP4_USIM_PBIASLITE_PWRDNZ_SHIFT			28
-#define OMAP4_USIM_PBIASLITE_PWRDNZ_MASK			(1 << 28)
-#define OMAP4_USIM_PBIASLITE_VMODE_SHIFT			27
-#define OMAP4_USIM_PBIASLITE_VMODE_MASK				(1 << 27)
-#define OMAP4_MMC1_PWRDNZ_SHIFT					26
-#define OMAP4_MMC1_PWRDNZ_MASK					(1 << 26)
-#define OMAP4_MMC1_PBIASLITE_HIZ_MODE_SHIFT			25
-#define OMAP4_MMC1_PBIASLITE_HIZ_MODE_MASK			(1 << 25)
-#define OMAP4_MMC1_PBIASLITE_SUPPLY_HI_OUT_SHIFT		24
-#define OMAP4_MMC1_PBIASLITE_SUPPLY_HI_OUT_MASK			(1 << 24)
-#define OMAP4_MMC1_PBIASLITE_VMODE_ERROR_SHIFT			23
-#define OMAP4_MMC1_PBIASLITE_VMODE_ERROR_MASK			(1 << 23)
-#define OMAP4_MMC1_PBIASLITE_PWRDNZ_SHIFT			22
-#define OMAP4_MMC1_PBIASLITE_PWRDNZ_MASK			(1 << 22)
-#define OMAP4_MMC1_PBIASLITE_VMODE_SHIFT			21
-#define OMAP4_MMC1_PBIASLITE_VMODE_MASK				(1 << 21)
-#define OMAP4_USBC1_ICUSB_PWRDNZ_SHIFT				20
-#define OMAP4_USBC1_ICUSB_PWRDNZ_MASK				(1 << 20)
-
-/* CONTROL_I2C_0 */
-#define OMAP4_I2C4_SDA_GLFENB_SHIFT				31
-#define OMAP4_I2C4_SDA_GLFENB_MASK				(1 << 31)
-#define OMAP4_I2C4_SDA_LOAD_BITS_SHIFT				29
-#define OMAP4_I2C4_SDA_LOAD_BITS_MASK				(0x3 << 29)
-#define OMAP4_I2C4_SDA_PULLUPRESX_SHIFT				28
-#define OMAP4_I2C4_SDA_PULLUPRESX_MASK				(1 << 28)
-#define OMAP4_I2C3_SDA_GLFENB_SHIFT				27
-#define OMAP4_I2C3_SDA_GLFENB_MASK				(1 << 27)
-#define OMAP4_I2C3_SDA_LOAD_BITS_SHIFT				25
-#define OMAP4_I2C3_SDA_LOAD_BITS_MASK				(0x3 << 25)
-#define OMAP4_I2C3_SDA_PULLUPRESX_SHIFT				24
-#define OMAP4_I2C3_SDA_PULLUPRESX_MASK				(1 << 24)
-#define OMAP4_I2C2_SDA_GLFENB_SHIFT				23
-#define OMAP4_I2C2_SDA_GLFENB_MASK				(1 << 23)
-#define OMAP4_I2C2_SDA_LOAD_BITS_SHIFT				21
-#define OMAP4_I2C2_SDA_LOAD_BITS_MASK				(0x3 << 21)
-#define OMAP4_I2C2_SDA_PULLUPRESX_SHIFT				20
-#define OMAP4_I2C2_SDA_PULLUPRESX_MASK				(1 << 20)
-#define OMAP4_I2C1_SDA_GLFENB_SHIFT				19
-#define OMAP4_I2C1_SDA_GLFENB_MASK				(1 << 19)
-#define OMAP4_I2C1_SDA_LOAD_BITS_SHIFT				17
-#define OMAP4_I2C1_SDA_LOAD_BITS_MASK				(0x3 << 17)
-#define OMAP4_I2C1_SDA_PULLUPRESX_SHIFT				16
-#define OMAP4_I2C1_SDA_PULLUPRESX_MASK				(1 << 16)
-#define OMAP4_I2C4_SCL_GLFENB_SHIFT				15
-#define OMAP4_I2C4_SCL_GLFENB_MASK				(1 << 15)
-#define OMAP4_I2C4_SCL_LOAD_BITS_SHIFT				13
-#define OMAP4_I2C4_SCL_LOAD_BITS_MASK				(0x3 << 13)
-#define OMAP4_I2C4_SCL_PULLUPRESX_SHIFT				12
-#define OMAP4_I2C4_SCL_PULLUPRESX_MASK				(1 << 12)
-#define OMAP4_I2C3_SCL_GLFENB_SHIFT				11
-#define OMAP4_I2C3_SCL_GLFENB_MASK				(1 << 11)
-#define OMAP4_I2C3_SCL_LOAD_BITS_SHIFT				9
-#define OMAP4_I2C3_SCL_LOAD_BITS_MASK				(0x3 << 9)
-#define OMAP4_I2C3_SCL_PULLUPRESX_SHIFT				8
-#define OMAP4_I2C3_SCL_PULLUPRESX_MASK				(1 << 8)
-#define OMAP4_I2C2_SCL_GLFENB_SHIFT				7
-#define OMAP4_I2C2_SCL_GLFENB_MASK				(1 << 7)
-#define OMAP4_I2C2_SCL_LOAD_BITS_SHIFT				5
-#define OMAP4_I2C2_SCL_LOAD_BITS_MASK				(0x3 << 5)
-#define OMAP4_I2C2_SCL_PULLUPRESX_SHIFT				4
-#define OMAP4_I2C2_SCL_PULLUPRESX_MASK				(1 << 4)
-#define OMAP4_I2C1_SCL_GLFENB_SHIFT				3
-#define OMAP4_I2C1_SCL_GLFENB_MASK				(1 << 3)
-#define OMAP4_I2C1_SCL_LOAD_BITS_SHIFT				1
-#define OMAP4_I2C1_SCL_LOAD_BITS_MASK				(0x3 << 1)
-#define OMAP4_I2C1_SCL_PULLUPRESX_SHIFT				0
-#define OMAP4_I2C1_SCL_PULLUPRESX_MASK				(1 << 0)
-
-/* CONTROL_CAMERA_RX */
-#define OMAP4_CAMERARX_UNIPRO_CTRLCLKEN_SHIFT			31
-#define OMAP4_CAMERARX_UNIPRO_CTRLCLKEN_MASK			(1 << 31)
-#define OMAP4_CAMERARX_CSI22_LANEENABLE_SHIFT			29
-#define OMAP4_CAMERARX_CSI22_LANEENABLE_MASK			(0x3 << 29)
-#define OMAP4_CAMERARX_CSI21_LANEENABLE_SHIFT			24
-#define OMAP4_CAMERARX_CSI21_LANEENABLE_MASK			(0x1f << 24)
-#define OMAP4_CAMERARX_UNIPRO_CAMMODE_SHIFT			22
-#define OMAP4_CAMERARX_UNIPRO_CAMMODE_MASK			(0x3 << 22)
-#define OMAP4_CAMERARX_CSI22_CTRLCLKEN_SHIFT			21
-#define OMAP4_CAMERARX_CSI22_CTRLCLKEN_MASK			(1 << 21)
-#define OMAP4_CAMERARX_CSI22_CAMMODE_SHIFT			19
-#define OMAP4_CAMERARX_CSI22_CAMMODE_MASK			(0x3 << 19)
-#define OMAP4_CAMERARX_CSI21_CTRLCLKEN_SHIFT			18
-#define OMAP4_CAMERARX_CSI21_CTRLCLKEN_MASK			(1 << 18)
-#define OMAP4_CAMERARX_CSI21_CAMMODE_SHIFT			16
-#define OMAP4_CAMERARX_CSI21_CAMMODE_MASK			(0x3 << 16)
-
-/* CONTROL_AVDAC */
-#define OMAP4_AVDAC_ACEN_SHIFT					31
-#define OMAP4_AVDAC_ACEN_MASK					(1 << 31)
-#define OMAP4_AVDAC_TVOUTBYPASS_SHIFT				30
-#define OMAP4_AVDAC_TVOUTBYPASS_MASK				(1 << 30)
-#define OMAP4_AVDAC_INPUTINV_SHIFT				29
-#define OMAP4_AVDAC_INPUTINV_MASK				(1 << 29)
-#define OMAP4_AVDAC_CTL_SHIFT					13
-#define OMAP4_AVDAC_CTL_MASK					(0xffff << 13)
-#define OMAP4_AVDAC_CTL_WR_ACK_SHIFT				12
-#define OMAP4_AVDAC_CTL_WR_ACK_MASK				(1 << 12)
-
-/* CONTROL_HDMI_TX_PHY */
-#define OMAP4_HDMITXPHY_PADORDER_SHIFT				31
-#define OMAP4_HDMITXPHY_PADORDER_MASK				(1 << 31)
-#define OMAP4_HDMITXPHY_TXVALID_SHIFT				30
-#define OMAP4_HDMITXPHY_TXVALID_MASK				(1 << 30)
-#define OMAP4_HDMITXPHY_ENBYPASSCLK_SHIFT			29
-#define OMAP4_HDMITXPHY_ENBYPASSCLK_MASK			(1 << 29)
-#define OMAP4_HDMITXPHY_PD_PULLUPDET_SHIFT			28
-#define OMAP4_HDMITXPHY_PD_PULLUPDET_MASK			(1 << 28)
-
-/* CONTROL_MMC2 */
-#define OMAP4_MMC2_FEEDBACK_CLK_SEL_SHIFT			31
-#define OMAP4_MMC2_FEEDBACK_CLK_SEL_MASK			(1 << 31)
-
-/* CONTROL_DSIPHY */
-#define OMAP4_DSI2_LANEENABLE_SHIFT				29
-#define OMAP4_DSI2_LANEENABLE_MASK				(0x7 << 29)
-#define OMAP4_DSI1_LANEENABLE_SHIFT				24
-#define OMAP4_DSI1_LANEENABLE_MASK				(0x1f << 24)
-#define OMAP4_DSI1_PIPD_SHIFT					19
-#define OMAP4_DSI1_PIPD_MASK					(0x1f << 19)
-#define OMAP4_DSI2_PIPD_SHIFT					14
-#define OMAP4_DSI2_PIPD_MASK					(0x1f << 14)
-
-/* CONTROL_MCBSPLP */
-#define OMAP4_ALBCTRLRX_FSX_SHIFT				31
-#define OMAP4_ALBCTRLRX_FSX_MASK				(1 << 31)
-#define OMAP4_ALBCTRLRX_CLKX_SHIFT				30
-#define OMAP4_ALBCTRLRX_CLKX_MASK				(1 << 30)
-#define OMAP4_ABE_MCBSP1_DR_EN_SHIFT				29
-#define OMAP4_ABE_MCBSP1_DR_EN_MASK				(1 << 29)
-
-/* CONTROL_USB2PHYCORE */
-#define OMAP4_USB2PHY_AUTORESUME_EN_SHIFT			31
-#define OMAP4_USB2PHY_AUTORESUME_EN_MASK			(1 << 31)
-#define OMAP4_USB2PHY_DISCHGDET_SHIFT				30
-#define OMAP4_USB2PHY_DISCHGDET_MASK				(1 << 30)
-#define OMAP4_USB2PHY_GPIOMODE_SHIFT				29
-#define OMAP4_USB2PHY_GPIOMODE_MASK				(1 << 29)
-#define OMAP4_USB2PHY_CHG_DET_EXT_CTL_SHIFT			28
-#define OMAP4_USB2PHY_CHG_DET_EXT_CTL_MASK			(1 << 28)
-#define OMAP4_USB2PHY_RDM_PD_CHGDET_EN_SHIFT			27
-#define OMAP4_USB2PHY_RDM_PD_CHGDET_EN_MASK			(1 << 27)
-#define OMAP4_USB2PHY_RDP_PU_CHGDET_EN_SHIFT			26
-#define OMAP4_USB2PHY_RDP_PU_CHGDET_EN_MASK			(1 << 26)
-#define OMAP4_USB2PHY_CHG_VSRC_EN_SHIFT				25
-#define OMAP4_USB2PHY_CHG_VSRC_EN_MASK				(1 << 25)
-#define OMAP4_USB2PHY_CHG_ISINK_EN_SHIFT			24
-#define OMAP4_USB2PHY_CHG_ISINK_EN_MASK				(1 << 24)
-#define OMAP4_USB2PHY_CHG_DET_STATUS_SHIFT			21
-#define OMAP4_USB2PHY_CHG_DET_STATUS_MASK			(0x7 << 21)
-#define OMAP4_USB2PHY_CHG_DET_DM_COMP_SHIFT			20
-#define OMAP4_USB2PHY_CHG_DET_DM_COMP_MASK			(1 << 20)
-#define OMAP4_USB2PHY_CHG_DET_DP_COMP_SHIFT			19
-#define OMAP4_USB2PHY_CHG_DET_DP_COMP_MASK			(1 << 19)
-#define OMAP4_USB2PHY_DATADET_SHIFT				18
-#define OMAP4_USB2PHY_DATADET_MASK				(1 << 18)
-#define OMAP4_USB2PHY_SINKONDP_SHIFT				17
-#define OMAP4_USB2PHY_SINKONDP_MASK				(1 << 17)
-#define OMAP4_USB2PHY_SRCONDM_SHIFT				16
-#define OMAP4_USB2PHY_SRCONDM_MASK				(1 << 16)
-#define OMAP4_USB2PHY_RESTARTCHGDET_SHIFT			15
-#define OMAP4_USB2PHY_RESTARTCHGDET_MASK			(1 << 15)
-#define OMAP4_USB2PHY_CHGDETDONE_SHIFT				14
-#define OMAP4_USB2PHY_CHGDETDONE_MASK				(1 << 14)
-#define OMAP4_USB2PHY_CHGDETECTED_SHIFT				13
-#define OMAP4_USB2PHY_CHGDETECTED_MASK				(1 << 13)
-#define OMAP4_USB2PHY_MCPCPUEN_SHIFT				12
-#define OMAP4_USB2PHY_MCPCPUEN_MASK				(1 << 12)
-#define OMAP4_USB2PHY_MCPCMODEEN_SHIFT				11
-#define OMAP4_USB2PHY_MCPCMODEEN_MASK				(1 << 11)
-#define OMAP4_USB2PHY_RESETDONEMCLK_SHIFT			10
-#define OMAP4_USB2PHY_RESETDONEMCLK_MASK			(1 << 10)
-#define OMAP4_USB2PHY_UTMIRESETDONE_SHIFT			9
-#define OMAP4_USB2PHY_UTMIRESETDONE_MASK			(1 << 9)
-#define OMAP4_USB2PHY_TXBITSTUFFENABLE_SHIFT			8
-#define OMAP4_USB2PHY_TXBITSTUFFENABLE_MASK			(1 << 8)
-#define OMAP4_USB2PHY_DATAPOLARITYN_SHIFT			7
-#define OMAP4_USB2PHY_DATAPOLARITYN_MASK			(1 << 7)
-#define OMAP4_USBDPLL_FREQLOCK_SHIFT				6
-#define OMAP4_USBDPLL_FREQLOCK_MASK				(1 << 6)
-#define OMAP4_USB2PHY_RESETDONETCLK_SHIFT			5
-#define OMAP4_USB2PHY_RESETDONETCLK_MASK			(1 << 5)
-
-/* CONTROL_I2C_1 */
-#define OMAP4_HDMI_DDC_SDA_GLFENB_SHIFT				31
-#define OMAP4_HDMI_DDC_SDA_GLFENB_MASK				(1 << 31)
-#define OMAP4_HDMI_DDC_SDA_LOAD_BITS_SHIFT			29
-#define OMAP4_HDMI_DDC_SDA_LOAD_BITS_MASK			(0x3 << 29)
-#define OMAP4_HDMI_DDC_SDA_PULLUPRESX_SHIFT			28
-#define OMAP4_HDMI_DDC_SDA_PULLUPRESX_MASK			(1 << 28)
-#define OMAP4_HDMI_DDC_SCL_GLFENB_SHIFT				27
-#define OMAP4_HDMI_DDC_SCL_GLFENB_MASK				(1 << 27)
-#define OMAP4_HDMI_DDC_SCL_LOAD_BITS_SHIFT			25
-#define OMAP4_HDMI_DDC_SCL_LOAD_BITS_MASK			(0x3 << 25)
-#define OMAP4_HDMI_DDC_SCL_PULLUPRESX_SHIFT			24
-#define OMAP4_HDMI_DDC_SCL_PULLUPRESX_MASK			(1 << 24)
-#define OMAP4_HDMI_DDC_SDA_HSMODE_SHIFT				23
-#define OMAP4_HDMI_DDC_SDA_HSMODE_MASK				(1 << 23)
-#define OMAP4_HDMI_DDC_SDA_NMODE_SHIFT				22
-#define OMAP4_HDMI_DDC_SDA_NMODE_MASK				(1 << 22)
-#define OMAP4_HDMI_DDC_SCL_HSMODE_SHIFT				21
-#define OMAP4_HDMI_DDC_SCL_HSMODE_MASK				(1 << 21)
-#define OMAP4_HDMI_DDC_SCL_NMODE_SHIFT				20
-#define OMAP4_HDMI_DDC_SCL_NMODE_MASK				(1 << 20)
-
-/* CONTROL_MMC1 */
-#define OMAP4_SDMMC1_PUSTRENGTH_GRP0_SHIFT			31
-#define OMAP4_SDMMC1_PUSTRENGTH_GRP0_MASK			(1 << 31)
-#define OMAP4_SDMMC1_PUSTRENGTH_GRP1_SHIFT			30
-#define OMAP4_SDMMC1_PUSTRENGTH_GRP1_MASK			(1 << 30)
-#define OMAP4_SDMMC1_PUSTRENGTH_GRP2_SHIFT			29
-#define OMAP4_SDMMC1_PUSTRENGTH_GRP2_MASK			(1 << 29)
-#define OMAP4_SDMMC1_PUSTRENGTH_GRP3_SHIFT			28
-#define OMAP4_SDMMC1_PUSTRENGTH_GRP3_MASK			(1 << 28)
-#define OMAP4_SDMMC1_DR0_SPEEDCTRL_SHIFT			27
-#define OMAP4_SDMMC1_DR0_SPEEDCTRL_MASK				(1 << 27)
-#define OMAP4_SDMMC1_DR1_SPEEDCTRL_SHIFT			26
-#define OMAP4_SDMMC1_DR1_SPEEDCTRL_MASK				(1 << 26)
-#define OMAP4_SDMMC1_DR2_SPEEDCTRL_SHIFT			25
-#define OMAP4_SDMMC1_DR2_SPEEDCTRL_MASK				(1 << 25)
-#define OMAP4_USBC1_DR0_SPEEDCTRL_SHIFT				24
-#define OMAP4_USBC1_DR0_SPEEDCTRL_MASK				(1 << 24)
-#define OMAP4_USB_FD_CDEN_SHIFT					23
-#define OMAP4_USB_FD_CDEN_MASK					(1 << 23)
-#define OMAP4_USBC1_ICUSB_DP_PDDIS_SHIFT			22
-#define OMAP4_USBC1_ICUSB_DP_PDDIS_MASK				(1 << 22)
-#define OMAP4_USBC1_ICUSB_DM_PDDIS_SHIFT			21
-#define OMAP4_USBC1_ICUSB_DM_PDDIS_MASK				(1 << 21)
-
-/* CONTROL_HSI */
-#define OMAP4_HSI1_CALLOOP_SEL_SHIFT				31
-#define OMAP4_HSI1_CALLOOP_SEL_MASK				(1 << 31)
-#define OMAP4_HSI1_CALMUX_SEL_SHIFT				30
-#define OMAP4_HSI1_CALMUX_SEL_MASK				(1 << 30)
-#define OMAP4_HSI2_CALLOOP_SEL_SHIFT				29
-#define OMAP4_HSI2_CALLOOP_SEL_MASK				(1 << 29)
-#define OMAP4_HSI2_CALMUX_SEL_SHIFT				28
-#define OMAP4_HSI2_CALMUX_SEL_MASK				(1 << 28)
-
-/* CONTROL_USB */
-#define OMAP4_CARKIT_USBA0_ULPIPHY_DAT0_AUTO_EN_SHIFT		31
-#define OMAP4_CARKIT_USBA0_ULPIPHY_DAT0_AUTO_EN_MASK		(1 << 31)
-#define OMAP4_CARKIT_USBA0_ULPIPHY_DAT1_AUTO_EN_SHIFT		30
-#define OMAP4_CARKIT_USBA0_ULPIPHY_DAT1_AUTO_EN_MASK		(1 << 30)
-
-/* CONTROL_HDQ */
-#define OMAP4_HDQ_SIO_PWRDNZ_SHIFT				31
-#define OMAP4_HDQ_SIO_PWRDNZ_MASK				(1 << 31)
-
-/* CONTROL_LPDDR2IO1_0 */
-#define OMAP4_LPDDR2IO1_GR4_SR_SHIFT				30
-#define OMAP4_LPDDR2IO1_GR4_SR_MASK				(0x3 << 30)
-#define OMAP4_LPDDR2IO1_GR4_I_SHIFT				27
-#define OMAP4_LPDDR2IO1_GR4_I_MASK				(0x7 << 27)
-#define OMAP4_LPDDR2IO1_GR4_WD_SHIFT				25
-#define OMAP4_LPDDR2IO1_GR4_WD_MASK				(0x3 << 25)
-#define OMAP4_LPDDR2IO1_GR3_SR_SHIFT				22
-#define OMAP4_LPDDR2IO1_GR3_SR_MASK				(0x3 << 22)
-#define OMAP4_LPDDR2IO1_GR3_I_SHIFT				19
-#define OMAP4_LPDDR2IO1_GR3_I_MASK				(0x7 << 19)
-#define OMAP4_LPDDR2IO1_GR3_WD_SHIFT				17
-#define OMAP4_LPDDR2IO1_GR3_WD_MASK				(0x3 << 17)
-#define OMAP4_LPDDR2IO1_GR2_SR_SHIFT				14
-#define OMAP4_LPDDR2IO1_GR2_SR_MASK				(0x3 << 14)
-#define OMAP4_LPDDR2IO1_GR2_I_SHIFT				11
-#define OMAP4_LPDDR2IO1_GR2_I_MASK				(0x7 << 11)
-#define OMAP4_LPDDR2IO1_GR2_WD_SHIFT				9
-#define OMAP4_LPDDR2IO1_GR2_WD_MASK				(0x3 << 9)
-#define OMAP4_LPDDR2IO1_GR1_SR_SHIFT				6
-#define OMAP4_LPDDR2IO1_GR1_SR_MASK				(0x3 << 6)
-#define OMAP4_LPDDR2IO1_GR1_I_SHIFT				3
-#define OMAP4_LPDDR2IO1_GR1_I_MASK				(0x7 << 3)
-#define OMAP4_LPDDR2IO1_GR1_WD_SHIFT				1
-#define OMAP4_LPDDR2IO1_GR1_WD_MASK				(0x3 << 1)
-
-/* CONTROL_LPDDR2IO1_1 */
-#define OMAP4_LPDDR2IO1_GR8_SR_SHIFT				30
-#define OMAP4_LPDDR2IO1_GR8_SR_MASK				(0x3 << 30)
-#define OMAP4_LPDDR2IO1_GR8_I_SHIFT				27
-#define OMAP4_LPDDR2IO1_GR8_I_MASK				(0x7 << 27)
-#define OMAP4_LPDDR2IO1_GR8_WD_SHIFT				25
-#define OMAP4_LPDDR2IO1_GR8_WD_MASK				(0x3 << 25)
-#define OMAP4_LPDDR2IO1_GR7_SR_SHIFT				22
-#define OMAP4_LPDDR2IO1_GR7_SR_MASK				(0x3 << 22)
-#define OMAP4_LPDDR2IO1_GR7_I_SHIFT				19
-#define OMAP4_LPDDR2IO1_GR7_I_MASK				(0x7 << 19)
-#define OMAP4_LPDDR2IO1_GR7_WD_SHIFT				17
-#define OMAP4_LPDDR2IO1_GR7_WD_MASK				(0x3 << 17)
-#define OMAP4_LPDDR2IO1_GR6_SR_SHIFT				14
-#define OMAP4_LPDDR2IO1_GR6_SR_MASK				(0x3 << 14)
-#define OMAP4_LPDDR2IO1_GR6_I_SHIFT				11
-#define OMAP4_LPDDR2IO1_GR6_I_MASK				(0x7 << 11)
-#define OMAP4_LPDDR2IO1_GR6_WD_SHIFT				9
-#define OMAP4_LPDDR2IO1_GR6_WD_MASK				(0x3 << 9)
-#define OMAP4_LPDDR2IO1_GR5_SR_SHIFT				6
-#define OMAP4_LPDDR2IO1_GR5_SR_MASK				(0x3 << 6)
-#define OMAP4_LPDDR2IO1_GR5_I_SHIFT				3
-#define OMAP4_LPDDR2IO1_GR5_I_MASK				(0x7 << 3)
-#define OMAP4_LPDDR2IO1_GR5_WD_SHIFT				1
-#define OMAP4_LPDDR2IO1_GR5_WD_MASK				(0x3 << 1)
-
-/* CONTROL_LPDDR2IO1_2 */
-#define OMAP4_LPDDR2IO1_GR11_SR_SHIFT				30
-#define OMAP4_LPDDR2IO1_GR11_SR_MASK				(0x3 << 30)
-#define OMAP4_LPDDR2IO1_GR11_I_SHIFT				27
-#define OMAP4_LPDDR2IO1_GR11_I_MASK				(0x7 << 27)
-#define OMAP4_LPDDR2IO1_GR11_WD_SHIFT				25
-#define OMAP4_LPDDR2IO1_GR11_WD_MASK				(0x3 << 25)
-#define OMAP4_LPDDR2IO1_GR10_SR_SHIFT				22
-#define OMAP4_LPDDR2IO1_GR10_SR_MASK				(0x3 << 22)
-#define OMAP4_LPDDR2IO1_GR10_I_SHIFT				19
-#define OMAP4_LPDDR2IO1_GR10_I_MASK				(0x7 << 19)
-#define OMAP4_LPDDR2IO1_GR10_WD_SHIFT				17
-#define OMAP4_LPDDR2IO1_GR10_WD_MASK				(0x3 << 17)
-#define OMAP4_LPDDR2IO1_GR9_SR_SHIFT				14
-#define OMAP4_LPDDR2IO1_GR9_SR_MASK				(0x3 << 14)
-#define OMAP4_LPDDR2IO1_GR9_I_SHIFT				11
-#define OMAP4_LPDDR2IO1_GR9_I_MASK				(0x7 << 11)
-#define OMAP4_LPDDR2IO1_GR9_WD_SHIFT				9
-#define OMAP4_LPDDR2IO1_GR9_WD_MASK				(0x3 << 9)
-
-/* CONTROL_LPDDR2IO1_3 */
-#define OMAP4_LPDDR21_VREF_CA_CCAP0_SHIFT			31
-#define OMAP4_LPDDR21_VREF_CA_CCAP0_MASK			(1 << 31)
-#define OMAP4_LPDDR21_VREF_CA_CCAP1_SHIFT			30
-#define OMAP4_LPDDR21_VREF_CA_CCAP1_MASK			(1 << 30)
-#define OMAP4_LPDDR21_VREF_CA_INT_CCAP0_SHIFT			29
-#define OMAP4_LPDDR21_VREF_CA_INT_CCAP0_MASK			(1 << 29)
-#define OMAP4_LPDDR21_VREF_CA_INT_CCAP1_SHIFT			28
-#define OMAP4_LPDDR21_VREF_CA_INT_CCAP1_MASK			(1 << 28)
-#define OMAP4_LPDDR21_VREF_CA_INT_TAP0_SHIFT			27
-#define OMAP4_LPDDR21_VREF_CA_INT_TAP0_MASK			(1 << 27)
-#define OMAP4_LPDDR21_VREF_CA_INT_TAP1_SHIFT			26
-#define OMAP4_LPDDR21_VREF_CA_INT_TAP1_MASK			(1 << 26)
-#define OMAP4_LPDDR21_VREF_CA_TAP0_SHIFT			25
-#define OMAP4_LPDDR21_VREF_CA_TAP0_MASK				(1 << 25)
-#define OMAP4_LPDDR21_VREF_CA_TAP1_SHIFT			24
-#define OMAP4_LPDDR21_VREF_CA_TAP1_MASK				(1 << 24)
-#define OMAP4_LPDDR21_VREF_DQ0_INT_CCAP0_SHIFT			23
-#define OMAP4_LPDDR21_VREF_DQ0_INT_CCAP0_MASK			(1 << 23)
-#define OMAP4_LPDDR21_VREF_DQ0_INT_CCAP1_SHIFT			22
-#define OMAP4_LPDDR21_VREF_DQ0_INT_CCAP1_MASK			(1 << 22)
-#define OMAP4_LPDDR21_VREF_DQ0_INT_TAP0_SHIFT			21
-#define OMAP4_LPDDR21_VREF_DQ0_INT_TAP0_MASK			(1 << 21)
-#define OMAP4_LPDDR21_VREF_DQ0_INT_TAP1_SHIFT			20
-#define OMAP4_LPDDR21_VREF_DQ0_INT_TAP1_MASK			(1 << 20)
-#define OMAP4_LPDDR21_VREF_DQ1_INT_CCAP0_SHIFT			19
-#define OMAP4_LPDDR21_VREF_DQ1_INT_CCAP0_MASK			(1 << 19)
-#define OMAP4_LPDDR21_VREF_DQ1_INT_CCAP1_SHIFT			18
-#define OMAP4_LPDDR21_VREF_DQ1_INT_CCAP1_MASK			(1 << 18)
-#define OMAP4_LPDDR21_VREF_DQ1_INT_TAP0_SHIFT			17
-#define OMAP4_LPDDR21_VREF_DQ1_INT_TAP0_MASK			(1 << 17)
-#define OMAP4_LPDDR21_VREF_DQ1_INT_TAP1_SHIFT			16
-#define OMAP4_LPDDR21_VREF_DQ1_INT_TAP1_MASK			(1 << 16)
-#define OMAP4_LPDDR21_VREF_DQ_CCAP0_SHIFT			15
-#define OMAP4_LPDDR21_VREF_DQ_CCAP0_MASK			(1 << 15)
-#define OMAP4_LPDDR21_VREF_DQ_CCAP1_SHIFT			14
-#define OMAP4_LPDDR21_VREF_DQ_CCAP1_MASK			(1 << 14)
-#define OMAP4_LPDDR21_VREF_DQ_TAP0_SHIFT			13
-#define OMAP4_LPDDR21_VREF_DQ_TAP0_MASK				(1 << 13)
-#define OMAP4_LPDDR21_VREF_DQ_TAP1_SHIFT			12
-#define OMAP4_LPDDR21_VREF_DQ_TAP1_MASK				(1 << 12)
-
-/* CONTROL_LPDDR2IO2_0 */
-#define OMAP4_LPDDR2IO2_GR4_SR_SHIFT				30
-#define OMAP4_LPDDR2IO2_GR4_SR_MASK				(0x3 << 30)
-#define OMAP4_LPDDR2IO2_GR4_I_SHIFT				27
-#define OMAP4_LPDDR2IO2_GR4_I_MASK				(0x7 << 27)
-#define OMAP4_LPDDR2IO2_GR4_WD_SHIFT				25
-#define OMAP4_LPDDR2IO2_GR4_WD_MASK				(0x3 << 25)
-#define OMAP4_LPDDR2IO2_GR3_SR_SHIFT				22
-#define OMAP4_LPDDR2IO2_GR3_SR_MASK				(0x3 << 22)
-#define OMAP4_LPDDR2IO2_GR3_I_SHIFT				19
-#define OMAP4_LPDDR2IO2_GR3_I_MASK				(0x7 << 19)
-#define OMAP4_LPDDR2IO2_GR3_WD_SHIFT				17
-#define OMAP4_LPDDR2IO2_GR3_WD_MASK				(0x3 << 17)
-#define OMAP4_LPDDR2IO2_GR2_SR_SHIFT				14
-#define OMAP4_LPDDR2IO2_GR2_SR_MASK				(0x3 << 14)
-#define OMAP4_LPDDR2IO2_GR2_I_SHIFT				11
-#define OMAP4_LPDDR2IO2_GR2_I_MASK				(0x7 << 11)
-#define OMAP4_LPDDR2IO2_GR2_WD_SHIFT				9
-#define OMAP4_LPDDR2IO2_GR2_WD_MASK				(0x3 << 9)
-#define OMAP4_LPDDR2IO2_GR1_SR_SHIFT				6
-#define OMAP4_LPDDR2IO2_GR1_SR_MASK				(0x3 << 6)
-#define OMAP4_LPDDR2IO2_GR1_I_SHIFT				3
-#define OMAP4_LPDDR2IO2_GR1_I_MASK				(0x7 << 3)
-#define OMAP4_LPDDR2IO2_GR1_WD_SHIFT				1
-#define OMAP4_LPDDR2IO2_GR1_WD_MASK				(0x3 << 1)
-
-/* CONTROL_LPDDR2IO2_1 */
-#define OMAP4_LPDDR2IO2_GR8_SR_SHIFT				30
-#define OMAP4_LPDDR2IO2_GR8_SR_MASK				(0x3 << 30)
-#define OMAP4_LPDDR2IO2_GR8_I_SHIFT				27
-#define OMAP4_LPDDR2IO2_GR8_I_MASK				(0x7 << 27)
-#define OMAP4_LPDDR2IO2_GR8_WD_SHIFT				25
-#define OMAP4_LPDDR2IO2_GR8_WD_MASK				(0x3 << 25)
-#define OMAP4_LPDDR2IO2_GR7_SR_SHIFT				22
-#define OMAP4_LPDDR2IO2_GR7_SR_MASK				(0x3 << 22)
-#define OMAP4_LPDDR2IO2_GR7_I_SHIFT				19
-#define OMAP4_LPDDR2IO2_GR7_I_MASK				(0x7 << 19)
-#define OMAP4_LPDDR2IO2_GR7_WD_SHIFT				17
-#define OMAP4_LPDDR2IO2_GR7_WD_MASK				(0x3 << 17)
-#define OMAP4_LPDDR2IO2_GR6_SR_SHIFT				14
-#define OMAP4_LPDDR2IO2_GR6_SR_MASK				(0x3 << 14)
-#define OMAP4_LPDDR2IO2_GR6_I_SHIFT				11
-#define OMAP4_LPDDR2IO2_GR6_I_MASK				(0x7 << 11)
-#define OMAP4_LPDDR2IO2_GR6_WD_SHIFT				9
-#define OMAP4_LPDDR2IO2_GR6_WD_MASK				(0x3 << 9)
-#define OMAP4_LPDDR2IO2_GR5_SR_SHIFT				6
-#define OMAP4_LPDDR2IO2_GR5_SR_MASK				(0x3 << 6)
-#define OMAP4_LPDDR2IO2_GR5_I_SHIFT				3
-#define OMAP4_LPDDR2IO2_GR5_I_MASK				(0x7 << 3)
-#define OMAP4_LPDDR2IO2_GR5_WD_SHIFT				1
-#define OMAP4_LPDDR2IO2_GR5_WD_MASK				(0x3 << 1)
-
-/* CONTROL_LPDDR2IO2_2 */
-#define OMAP4_LPDDR2IO2_GR11_SR_SHIFT				30
-#define OMAP4_LPDDR2IO2_GR11_SR_MASK				(0x3 << 30)
-#define OMAP4_LPDDR2IO2_GR11_I_SHIFT				27
-#define OMAP4_LPDDR2IO2_GR11_I_MASK				(0x7 << 27)
-#define OMAP4_LPDDR2IO2_GR11_WD_SHIFT				25
-#define OMAP4_LPDDR2IO2_GR11_WD_MASK				(0x3 << 25)
-#define OMAP4_LPDDR2IO2_GR10_SR_SHIFT				22
-#define OMAP4_LPDDR2IO2_GR10_SR_MASK				(0x3 << 22)
-#define OMAP4_LPDDR2IO2_GR10_I_SHIFT				19
-#define OMAP4_LPDDR2IO2_GR10_I_MASK				(0x7 << 19)
-#define OMAP4_LPDDR2IO2_GR10_WD_SHIFT				17
-#define OMAP4_LPDDR2IO2_GR10_WD_MASK				(0x3 << 17)
-#define OMAP4_LPDDR2IO2_GR9_SR_SHIFT				14
-#define OMAP4_LPDDR2IO2_GR9_SR_MASK				(0x3 << 14)
-#define OMAP4_LPDDR2IO2_GR9_I_SHIFT				11
-#define OMAP4_LPDDR2IO2_GR9_I_MASK				(0x7 << 11)
-#define OMAP4_LPDDR2IO2_GR9_WD_SHIFT				9
-#define OMAP4_LPDDR2IO2_GR9_WD_MASK				(0x3 << 9)
-
-/* CONTROL_LPDDR2IO2_3 */
-#define OMAP4_LPDDR22_VREF_CA_CCAP0_SHIFT			31
-#define OMAP4_LPDDR22_VREF_CA_CCAP0_MASK			(1 << 31)
-#define OMAP4_LPDDR22_VREF_CA_CCAP1_SHIFT			30
-#define OMAP4_LPDDR22_VREF_CA_CCAP1_MASK			(1 << 30)
-#define OMAP4_LPDDR22_VREF_CA_INT_CCAP0_SHIFT			29
-#define OMAP4_LPDDR22_VREF_CA_INT_CCAP0_MASK			(1 << 29)
-#define OMAP4_LPDDR22_VREF_CA_INT_CCAP1_SHIFT			28
-#define OMAP4_LPDDR22_VREF_CA_INT_CCAP1_MASK			(1 << 28)
-#define OMAP4_LPDDR22_VREF_CA_INT_TAP0_SHIFT			27
-#define OMAP4_LPDDR22_VREF_CA_INT_TAP0_MASK			(1 << 27)
-#define OMAP4_LPDDR22_VREF_CA_INT_TAP1_SHIFT			26
-#define OMAP4_LPDDR22_VREF_CA_INT_TAP1_MASK			(1 << 26)
-#define OMAP4_LPDDR22_VREF_CA_TAP0_SHIFT			25
-#define OMAP4_LPDDR22_VREF_CA_TAP0_MASK				(1 << 25)
-#define OMAP4_LPDDR22_VREF_CA_TAP1_SHIFT			24
-#define OMAP4_LPDDR22_VREF_CA_TAP1_MASK				(1 << 24)
-#define OMAP4_LPDDR22_VREF_DQ0_INT_CCAP0_SHIFT			23
-#define OMAP4_LPDDR22_VREF_DQ0_INT_CCAP0_MASK			(1 << 23)
-#define OMAP4_LPDDR22_VREF_DQ0_INT_CCAP1_SHIFT			22
-#define OMAP4_LPDDR22_VREF_DQ0_INT_CCAP1_MASK			(1 << 22)
-#define OMAP4_LPDDR22_VREF_DQ0_INT_TAP0_SHIFT			21
-#define OMAP4_LPDDR22_VREF_DQ0_INT_TAP0_MASK			(1 << 21)
-#define OMAP4_LPDDR22_VREF_DQ0_INT_TAP1_SHIFT			20
-#define OMAP4_LPDDR22_VREF_DQ0_INT_TAP1_MASK			(1 << 20)
-#define OMAP4_LPDDR22_VREF_DQ1_INT_CCAP0_SHIFT			19
-#define OMAP4_LPDDR22_VREF_DQ1_INT_CCAP0_MASK			(1 << 19)
-#define OMAP4_LPDDR22_VREF_DQ1_INT_CCAP1_SHIFT			18
-#define OMAP4_LPDDR22_VREF_DQ1_INT_CCAP1_MASK			(1 << 18)
-#define OMAP4_LPDDR22_VREF_DQ1_INT_TAP0_SHIFT			17
-#define OMAP4_LPDDR22_VREF_DQ1_INT_TAP0_MASK			(1 << 17)
-#define OMAP4_LPDDR22_VREF_DQ1_INT_TAP1_SHIFT			16
-#define OMAP4_LPDDR22_VREF_DQ1_INT_TAP1_MASK			(1 << 16)
-#define OMAP4_LPDDR22_VREF_DQ_CCAP0_SHIFT			15
-#define OMAP4_LPDDR22_VREF_DQ_CCAP0_MASK			(1 << 15)
-#define OMAP4_LPDDR22_VREF_DQ_CCAP1_SHIFT			14
-#define OMAP4_LPDDR22_VREF_DQ_CCAP1_MASK			(1 << 14)
-#define OMAP4_LPDDR22_VREF_DQ_TAP0_SHIFT			13
-#define OMAP4_LPDDR22_VREF_DQ_TAP0_MASK				(1 << 13)
-#define OMAP4_LPDDR22_VREF_DQ_TAP1_SHIFT			12
-#define OMAP4_LPDDR22_VREF_DQ_TAP1_MASK				(1 << 12)
-
-/* CONTROL_BUS_HOLD */
-#define OMAP4_ABE_DMIC_DIN3_EN_SHIFT				31
-#define OMAP4_ABE_DMIC_DIN3_EN_MASK				(1 << 31)
-#define OMAP4_MCSPI1_CS3_EN_SHIFT				30
-#define OMAP4_MCSPI1_CS3_EN_MASK				(1 << 30)
-
-/* CONTROL_C2C */
-#define OMAP4_MIRROR_MODE_EN_SHIFT				31
-#define OMAP4_MIRROR_MODE_EN_MASK				(1 << 31)
-#define OMAP4_C2C_SPARE_SHIFT					24
-#define OMAP4_C2C_SPARE_MASK					(0x7f << 24)
-
-/* CORE_CONTROL_SPARE_RW */
-#define OMAP4_CORE_CONTROL_SPARE_RW_SHIFT			0
-#define OMAP4_CORE_CONTROL_SPARE_RW_MASK			(0xffffffff << 0)
-
-/* CORE_CONTROL_SPARE_R */
-#define OMAP4_CORE_CONTROL_SPARE_R_SHIFT			0
-#define OMAP4_CORE_CONTROL_SPARE_R_MASK				(0xffffffff << 0)
-
-/* CORE_CONTROL_SPARE_R_C0 */
-#define OMAP4_CORE_CONTROL_SPARE_R_C0_SHIFT			31
-#define OMAP4_CORE_CONTROL_SPARE_R_C0_MASK			(1 << 31)
-#define OMAP4_CORE_CONTROL_SPARE_R_C1_SHIFT			30
-#define OMAP4_CORE_CONTROL_SPARE_R_C1_MASK			(1 << 30)
-#define OMAP4_CORE_CONTROL_SPARE_R_C2_SHIFT			29
-#define OMAP4_CORE_CONTROL_SPARE_R_C2_MASK			(1 << 29)
-#define OMAP4_CORE_CONTROL_SPARE_R_C3_SHIFT			28
-#define OMAP4_CORE_CONTROL_SPARE_R_C3_MASK			(1 << 28)
-#define OMAP4_CORE_CONTROL_SPARE_R_C4_SHIFT			27
-#define OMAP4_CORE_CONTROL_SPARE_R_C4_MASK			(1 << 27)
-#define OMAP4_CORE_CONTROL_SPARE_R_C5_SHIFT			26
-#define OMAP4_CORE_CONTROL_SPARE_R_C5_MASK			(1 << 26)
-#define OMAP4_CORE_CONTROL_SPARE_R_C6_SHIFT			25
-#define OMAP4_CORE_CONTROL_SPARE_R_C6_MASK			(1 << 25)
-#define OMAP4_CORE_CONTROL_SPARE_R_C7_SHIFT			24
-#define OMAP4_CORE_CONTROL_SPARE_R_C7_MASK			(1 << 24)
-
-/* CONTROL_EFUSE_1 */
-#define OMAP4_AVDAC_TRIM_BYTE3_SHIFT				24
-#define OMAP4_AVDAC_TRIM_BYTE3_MASK				(0x7f << 24)
-#define OMAP4_AVDAC_TRIM_BYTE2_SHIFT				16
-#define OMAP4_AVDAC_TRIM_BYTE2_MASK				(0xff << 16)
-#define OMAP4_AVDAC_TRIM_BYTE1_SHIFT				8
-#define OMAP4_AVDAC_TRIM_BYTE1_MASK				(0xff << 8)
-#define OMAP4_AVDAC_TRIM_BYTE0_SHIFT				0
-#define OMAP4_AVDAC_TRIM_BYTE0_MASK				(0xff << 0)
-
-/* CONTROL_EFUSE_2 */
-#define OMAP4_EFUSE_SMART2TEST_P0_SHIFT				31
-#define OMAP4_EFUSE_SMART2TEST_P0_MASK				(1 << 31)
-#define OMAP4_EFUSE_SMART2TEST_P1_SHIFT				30
-#define OMAP4_EFUSE_SMART2TEST_P1_MASK				(1 << 30)
-#define OMAP4_EFUSE_SMART2TEST_P2_SHIFT				29
-#define OMAP4_EFUSE_SMART2TEST_P2_MASK				(1 << 29)
-#define OMAP4_EFUSE_SMART2TEST_P3_SHIFT				28
-#define OMAP4_EFUSE_SMART2TEST_P3_MASK				(1 << 28)
-#define OMAP4_EFUSE_SMART2TEST_N0_SHIFT				27
-#define OMAP4_EFUSE_SMART2TEST_N0_MASK				(1 << 27)
-#define OMAP4_EFUSE_SMART2TEST_N1_SHIFT				26
-#define OMAP4_EFUSE_SMART2TEST_N1_MASK				(1 << 26)
-#define OMAP4_EFUSE_SMART2TEST_N2_SHIFT				25
-#define OMAP4_EFUSE_SMART2TEST_N2_MASK				(1 << 25)
-#define OMAP4_EFUSE_SMART2TEST_N3_SHIFT				24
-#define OMAP4_EFUSE_SMART2TEST_N3_MASK				(1 << 24)
-#define OMAP4_LPDDR2_PTV_N1_SHIFT				23
-#define OMAP4_LPDDR2_PTV_N1_MASK				(1 << 23)
-#define OMAP4_LPDDR2_PTV_N2_SHIFT				22
-#define OMAP4_LPDDR2_PTV_N2_MASK				(1 << 22)
-#define OMAP4_LPDDR2_PTV_N3_SHIFT				21
-#define OMAP4_LPDDR2_PTV_N3_MASK				(1 << 21)
-#define OMAP4_LPDDR2_PTV_N4_SHIFT				20
-#define OMAP4_LPDDR2_PTV_N4_MASK				(1 << 20)
-#define OMAP4_LPDDR2_PTV_N5_SHIFT				19
-#define OMAP4_LPDDR2_PTV_N5_MASK				(1 << 19)
-#define OMAP4_LPDDR2_PTV_P1_SHIFT				18
-#define OMAP4_LPDDR2_PTV_P1_MASK				(1 << 18)
-#define OMAP4_LPDDR2_PTV_P2_SHIFT				17
-#define OMAP4_LPDDR2_PTV_P2_MASK				(1 << 17)
-#define OMAP4_LPDDR2_PTV_P3_SHIFT				16
-#define OMAP4_LPDDR2_PTV_P3_MASK				(1 << 16)
-#define OMAP4_LPDDR2_PTV_P4_SHIFT				15
-#define OMAP4_LPDDR2_PTV_P4_MASK				(1 << 15)
-#define OMAP4_LPDDR2_PTV_P5_SHIFT				14
-#define OMAP4_LPDDR2_PTV_P5_MASK				(1 << 14)
-
-/* CONTROL_EFUSE_3 */
-#define OMAP4_STD_FUSE_SPARE_1_SHIFT				24
-#define OMAP4_STD_FUSE_SPARE_1_MASK				(0xff << 24)
-#define OMAP4_STD_FUSE_SPARE_2_SHIFT				16
-#define OMAP4_STD_FUSE_SPARE_2_MASK				(0xff << 16)
-#define OMAP4_STD_FUSE_SPARE_3_SHIFT				8
-#define OMAP4_STD_FUSE_SPARE_3_MASK				(0xff << 8)
-#define OMAP4_STD_FUSE_SPARE_4_SHIFT				0
-#define OMAP4_STD_FUSE_SPARE_4_MASK				(0xff << 0)
-
-/* CONTROL_EFUSE_4 */
-#define OMAP4_STD_FUSE_SPARE_5_SHIFT				24
-#define OMAP4_STD_FUSE_SPARE_5_MASK				(0xff << 24)
-#define OMAP4_STD_FUSE_SPARE_6_SHIFT				16
-#define OMAP4_STD_FUSE_SPARE_6_MASK				(0xff << 16)
-#define OMAP4_STD_FUSE_SPARE_7_SHIFT				8
-#define OMAP4_STD_FUSE_SPARE_7_MASK				(0xff << 8)
-#define OMAP4_STD_FUSE_SPARE_8_SHIFT				0
-#define OMAP4_STD_FUSE_SPARE_8_MASK				(0xff << 0)
-
-#endif
diff --git a/arch/arm/mach-omap2/include/mach/ctrl_module_pad_wkup_44xx.h b/arch/arm/mach-omap2/include/mach/ctrl_module_pad_wkup_44xx.h
deleted file mode 100644
index 17c9b37..0000000
--- a/arch/arm/mach-omap2/include/mach/ctrl_module_pad_wkup_44xx.h
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- * OMAP44xx CTRL_MODULE_PAD_WKUP registers and bitfields
- *
- * Copyright (C) 2009-2010 Texas Instruments, Inc.
- *
- * Benoit Cousson (b-cousson@ti.com)
- * Santosh Shilimkar (santosh.shilimkar@ti.com)
- *
- * This file is automatically generated from the OMAP hardware databases.
- * We respectfully ask that any modifications to this file be coordinated
- * with the public linux-omap@vger.kernel.org mailing list and the
- * authors above to ensure that the autogeneration scripts are kept
- * up-to-date with the file contents.
- *
- * This program is free software; you can 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_CTRL_MODULE_PAD_WKUP_44XX_H
-#define __ARCH_ARM_MACH_OMAP2_CTRL_MODULE_PAD_WKUP_44XX_H
-
-
-/* Base address */
-#define OMAP4_CTRL_MODULE_PAD_WKUP					0x4a31e000
-
-/* Registers offset */
-#define OMAP4_CTRL_MODULE_PAD_WKUP_IP_REVISION				0x0000
-#define OMAP4_CTRL_MODULE_PAD_WKUP_IP_HWINFO				0x0004
-#define OMAP4_CTRL_MODULE_PAD_WKUP_IP_SYSCONFIG				0x0010
-#define OMAP4_CTRL_MODULE_PAD_WKUP_PADCONF_WAKEUPEVENT_0		0x007c
-#define OMAP4_CTRL_MODULE_PAD_WKUP_CONTROL_SMART1NOPMIO_PADCONF_0	0x05a0
-#define OMAP4_CTRL_MODULE_PAD_WKUP_CONTROL_SMART1NOPMIO_PADCONF_1	0x05a4
-#define OMAP4_CTRL_MODULE_PAD_WKUP_CONTROL_PADCONF_MODE			0x05a8
-#define OMAP4_CTRL_MODULE_PAD_WKUP_CONTROL_XTAL_OSCILLATOR		0x05ac
-#define OMAP4_CTRL_MODULE_PAD_WKUP_CONTROL_USIMIO			0x0600
-#define OMAP4_CTRL_MODULE_PAD_WKUP_CONTROL_I2C_2			0x0604
-#define OMAP4_CTRL_MODULE_PAD_WKUP_CONTROL_JTAG				0x0608
-#define OMAP4_CTRL_MODULE_PAD_WKUP_CONTROL_SYS				0x060c
-#define OMAP4_CTRL_MODULE_PAD_WKUP_WKUP_CONTROL_SPARE_RW		0x0614
-#define OMAP4_CTRL_MODULE_PAD_WKUP_WKUP_CONTROL_SPARE_R			0x0618
-#define OMAP4_CTRL_MODULE_PAD_WKUP_WKUP_CONTROL_SPARE_R_C0		0x061c
-
-/* Registers shifts and masks */
-
-/* IP_REVISION */
-#define OMAP4_IP_REV_SCHEME_SHIFT				30
-#define OMAP4_IP_REV_SCHEME_MASK				(0x3 << 30)
-#define OMAP4_IP_REV_FUNC_SHIFT					16
-#define OMAP4_IP_REV_FUNC_MASK					(0xfff << 16)
-#define OMAP4_IP_REV_RTL_SHIFT					11
-#define OMAP4_IP_REV_RTL_MASK					(0x1f << 11)
-#define OMAP4_IP_REV_MAJOR_SHIFT				8
-#define OMAP4_IP_REV_MAJOR_MASK					(0x7 << 8)
-#define OMAP4_IP_REV_CUSTOM_SHIFT				6
-#define OMAP4_IP_REV_CUSTOM_MASK				(0x3 << 6)
-#define OMAP4_IP_REV_MINOR_SHIFT				0
-#define OMAP4_IP_REV_MINOR_MASK					(0x3f << 0)
-
-/* IP_HWINFO */
-#define OMAP4_IP_HWINFO_SHIFT					0
-#define OMAP4_IP_HWINFO_MASK					(0xffffffff << 0)
-
-/* IP_SYSCONFIG */
-#define OMAP4_IP_SYSCONFIG_IDLEMODE_SHIFT			2
-#define OMAP4_IP_SYSCONFIG_IDLEMODE_MASK			(0x3 << 2)
-
-/* PADCONF_WAKEUPEVENT_0 */
-#define OMAP4_JTAG_TDO_DUPLICATEWAKEUPEVENT_SHIFT		24
-#define OMAP4_JTAG_TDO_DUPLICATEWAKEUPEVENT_MASK		(1 << 24)
-#define OMAP4_JTAG_TDI_DUPLICATEWAKEUPEVENT_SHIFT		23
-#define OMAP4_JTAG_TDI_DUPLICATEWAKEUPEVENT_MASK		(1 << 23)
-#define OMAP4_JTAG_TMS_TMSC_DUPLICATEWAKEUPEVENT_SHIFT		22
-#define OMAP4_JTAG_TMS_TMSC_DUPLICATEWAKEUPEVENT_MASK		(1 << 22)
-#define OMAP4_JTAG_RTCK_DUPLICATEWAKEUPEVENT_SHIFT		21
-#define OMAP4_JTAG_RTCK_DUPLICATEWAKEUPEVENT_MASK		(1 << 21)
-#define OMAP4_JTAG_TCK_DUPLICATEWAKEUPEVENT_SHIFT		20
-#define OMAP4_JTAG_TCK_DUPLICATEWAKEUPEVENT_MASK		(1 << 20)
-#define OMAP4_JTAG_NTRST_DUPLICATEWAKEUPEVENT_SHIFT		19
-#define OMAP4_JTAG_NTRST_DUPLICATEWAKEUPEVENT_MASK		(1 << 19)
-#define OMAP4_SYS_BOOT7_DUPLICATEWAKEUPEVENT_SHIFT		18
-#define OMAP4_SYS_BOOT7_DUPLICATEWAKEUPEVENT_MASK		(1 << 18)
-#define OMAP4_SYS_BOOT6_DUPLICATEWAKEUPEVENT_SHIFT		17
-#define OMAP4_SYS_BOOT6_DUPLICATEWAKEUPEVENT_MASK		(1 << 17)
-#define OMAP4_SYS_PWRON_RESET_OUT_DUPLICATEWAKEUPEVENT_SHIFT	16
-#define OMAP4_SYS_PWRON_RESET_OUT_DUPLICATEWAKEUPEVENT_MASK	(1 << 16)
-#define OMAP4_SYS_PWR_REQ_DUPLICATEWAKEUPEVENT_SHIFT		15
-#define OMAP4_SYS_PWR_REQ_DUPLICATEWAKEUPEVENT_MASK		(1 << 15)
-#define OMAP4_SYS_NRESWARM_DUPLICATEWAKEUPEVENT_SHIFT		14
-#define OMAP4_SYS_NRESWARM_DUPLICATEWAKEUPEVENT_MASK		(1 << 14)
-#define OMAP4_SYS_32K_DUPLICATEWAKEUPEVENT_SHIFT		13
-#define OMAP4_SYS_32K_DUPLICATEWAKEUPEVENT_MASK			(1 << 13)
-#define OMAP4_FREF_CLK4_OUT_DUPLICATEWAKEUPEVENT_SHIFT		12
-#define OMAP4_FREF_CLK4_OUT_DUPLICATEWAKEUPEVENT_MASK		(1 << 12)
-#define OMAP4_FREF_CLK4_REQ_DUPLICATEWAKEUPEVENT_SHIFT		11
-#define OMAP4_FREF_CLK4_REQ_DUPLICATEWAKEUPEVENT_MASK		(1 << 11)
-#define OMAP4_FREF_CLK3_OUT_DUPLICATEWAKEUPEVENT_SHIFT		10
-#define OMAP4_FREF_CLK3_OUT_DUPLICATEWAKEUPEVENT_MASK		(1 << 10)
-#define OMAP4_FREF_CLK3_REQ_DUPLICATEWAKEUPEVENT_SHIFT		9
-#define OMAP4_FREF_CLK3_REQ_DUPLICATEWAKEUPEVENT_MASK		(1 << 9)
-#define OMAP4_FREF_CLK0_OUT_DUPLICATEWAKEUPEVENT_SHIFT		8
-#define OMAP4_FREF_CLK0_OUT_DUPLICATEWAKEUPEVENT_MASK		(1 << 8)
-#define OMAP4_FREF_CLK_IOREQ_DUPLICATEWAKEUPEVENT_SHIFT		7
-#define OMAP4_FREF_CLK_IOREQ_DUPLICATEWAKEUPEVENT_MASK		(1 << 7)
-#define OMAP4_SR_SDA_DUPLICATEWAKEUPEVENT_SHIFT			6
-#define OMAP4_SR_SDA_DUPLICATEWAKEUPEVENT_MASK			(1 << 6)
-#define OMAP4_SR_SCL_DUPLICATEWAKEUPEVENT_SHIFT			5
-#define OMAP4_SR_SCL_DUPLICATEWAKEUPEVENT_MASK			(1 << 5)
-#define OMAP4_SIM_PWRCTRL_DUPLICATEWAKEUPEVENT_SHIFT		4
-#define OMAP4_SIM_PWRCTRL_DUPLICATEWAKEUPEVENT_MASK		(1 << 4)
-#define OMAP4_SIM_CD_DUPLICATEWAKEUPEVENT_SHIFT			3
-#define OMAP4_SIM_CD_DUPLICATEWAKEUPEVENT_MASK			(1 << 3)
-#define OMAP4_SIM_RESET_DUPLICATEWAKEUPEVENT_SHIFT		2
-#define OMAP4_SIM_RESET_DUPLICATEWAKEUPEVENT_MASK		(1 << 2)
-#define OMAP4_SIM_CLK_DUPLICATEWAKEUPEVENT_SHIFT		1
-#define OMAP4_SIM_CLK_DUPLICATEWAKEUPEVENT_MASK			(1 << 1)
-#define OMAP4_SIM_IO_DUPLICATEWAKEUPEVENT_SHIFT			0
-#define OMAP4_SIM_IO_DUPLICATEWAKEUPEVENT_MASK			(1 << 0)
-
-/* CONTROL_SMART1NOPMIO_PADCONF_0 */
-#define OMAP4_FREF_DR0_SC_SHIFT					30
-#define OMAP4_FREF_DR0_SC_MASK					(0x3 << 30)
-#define OMAP4_FREF_DR1_SC_SHIFT					28
-#define OMAP4_FREF_DR1_SC_MASK					(0x3 << 28)
-#define OMAP4_FREF_DR4_SC_SHIFT					26
-#define OMAP4_FREF_DR4_SC_MASK					(0x3 << 26)
-#define OMAP4_FREF_DR5_SC_SHIFT					24
-#define OMAP4_FREF_DR5_SC_MASK					(0x3 << 24)
-#define OMAP4_FREF_DR6_SC_SHIFT					22
-#define OMAP4_FREF_DR6_SC_MASK					(0x3 << 22)
-#define OMAP4_FREF_DR7_SC_SHIFT					20
-#define OMAP4_FREF_DR7_SC_MASK					(0x3 << 20)
-#define OMAP4_GPIO_DR7_SC_SHIFT					18
-#define OMAP4_GPIO_DR7_SC_MASK					(0x3 << 18)
-#define OMAP4_DPM_DR0_SC_SHIFT					14
-#define OMAP4_DPM_DR0_SC_MASK					(0x3 << 14)
-#define OMAP4_SIM_DR0_SC_SHIFT					12
-#define OMAP4_SIM_DR0_SC_MASK					(0x3 << 12)
-
-/* CONTROL_SMART1NOPMIO_PADCONF_1 */
-#define OMAP4_FREF_DR0_LB_SHIFT					30
-#define OMAP4_FREF_DR0_LB_MASK					(0x3 << 30)
-#define OMAP4_FREF_DR1_LB_SHIFT					28
-#define OMAP4_FREF_DR1_LB_MASK					(0x3 << 28)
-#define OMAP4_FREF_DR4_LB_SHIFT					26
-#define OMAP4_FREF_DR4_LB_MASK					(0x3 << 26)
-#define OMAP4_FREF_DR5_LB_SHIFT					24
-#define OMAP4_FREF_DR5_LB_MASK					(0x3 << 24)
-#define OMAP4_FREF_DR6_LB_SHIFT					22
-#define OMAP4_FREF_DR6_LB_MASK					(0x3 << 22)
-#define OMAP4_FREF_DR7_LB_SHIFT					20
-#define OMAP4_FREF_DR7_LB_MASK					(0x3 << 20)
-#define OMAP4_GPIO_DR7_LB_SHIFT					18
-#define OMAP4_GPIO_DR7_LB_MASK					(0x3 << 18)
-#define OMAP4_DPM_DR0_LB_SHIFT					14
-#define OMAP4_DPM_DR0_LB_MASK					(0x3 << 14)
-#define OMAP4_SIM_DR0_LB_SHIFT					12
-#define OMAP4_SIM_DR0_LB_MASK					(0x3 << 12)
-
-/* CONTROL_PADCONF_MODE */
-#define OMAP4_VDDS_DV_FREF_SHIFT				31
-#define OMAP4_VDDS_DV_FREF_MASK					(1 << 31)
-#define OMAP4_VDDS_DV_BANK2_SHIFT				30
-#define OMAP4_VDDS_DV_BANK2_MASK				(1 << 30)
-
-/* CONTROL_XTAL_OSCILLATOR */
-#define OMAP4_OSCILLATOR_BOOST_SHIFT				31
-#define OMAP4_OSCILLATOR_BOOST_MASK				(1 << 31)
-#define OMAP4_OSCILLATOR_OS_OUT_SHIFT				30
-#define OMAP4_OSCILLATOR_OS_OUT_MASK				(1 << 30)
-
-/* CONTROL_USIMIO */
-#define OMAP4_PAD_USIM_CLK_LOW_SHIFT				31
-#define OMAP4_PAD_USIM_CLK_LOW_MASK				(1 << 31)
-#define OMAP4_PAD_USIM_RST_LOW_SHIFT				29
-#define OMAP4_PAD_USIM_RST_LOW_MASK				(1 << 29)
-#define OMAP4_USIM_PWRDNZ_SHIFT					28
-#define OMAP4_USIM_PWRDNZ_MASK					(1 << 28)
-
-/* CONTROL_I2C_2 */
-#define OMAP4_SR_SDA_GLFENB_SHIFT				31
-#define OMAP4_SR_SDA_GLFENB_MASK				(1 << 31)
-#define OMAP4_SR_SDA_LOAD_BITS_SHIFT				29
-#define OMAP4_SR_SDA_LOAD_BITS_MASK				(0x3 << 29)
-#define OMAP4_SR_SDA_PULLUPRESX_SHIFT				28
-#define OMAP4_SR_SDA_PULLUPRESX_MASK				(1 << 28)
-#define OMAP4_SR_SCL_GLFENB_SHIFT				27
-#define OMAP4_SR_SCL_GLFENB_MASK				(1 << 27)
-#define OMAP4_SR_SCL_LOAD_BITS_SHIFT				25
-#define OMAP4_SR_SCL_LOAD_BITS_MASK				(0x3 << 25)
-#define OMAP4_SR_SCL_PULLUPRESX_SHIFT				24
-#define OMAP4_SR_SCL_PULLUPRESX_MASK				(1 << 24)
-
-/* CONTROL_JTAG */
-#define OMAP4_JTAG_NTRST_EN_SHIFT				31
-#define OMAP4_JTAG_NTRST_EN_MASK				(1 << 31)
-#define OMAP4_JTAG_TCK_EN_SHIFT					30
-#define OMAP4_JTAG_TCK_EN_MASK					(1 << 30)
-#define OMAP4_JTAG_RTCK_EN_SHIFT				29
-#define OMAP4_JTAG_RTCK_EN_MASK					(1 << 29)
-#define OMAP4_JTAG_TDI_EN_SHIFT					28
-#define OMAP4_JTAG_TDI_EN_MASK					(1 << 28)
-#define OMAP4_JTAG_TDO_EN_SHIFT					27
-#define OMAP4_JTAG_TDO_EN_MASK					(1 << 27)
-
-/* CONTROL_SYS */
-#define OMAP4_SYS_NRESWARM_PIPU_SHIFT				31
-#define OMAP4_SYS_NRESWARM_PIPU_MASK				(1 << 31)
-
-/* WKUP_CONTROL_SPARE_RW */
-#define OMAP4_WKUP_CONTROL_SPARE_RW_SHIFT			0
-#define OMAP4_WKUP_CONTROL_SPARE_RW_MASK			(0xffffffff << 0)
-
-/* WKUP_CONTROL_SPARE_R */
-#define OMAP4_WKUP_CONTROL_SPARE_R_SHIFT			0
-#define OMAP4_WKUP_CONTROL_SPARE_R_MASK				(0xffffffff << 0)
-
-/* WKUP_CONTROL_SPARE_R_C0 */
-#define OMAP4_WKUP_CONTROL_SPARE_R_C0_SHIFT			31
-#define OMAP4_WKUP_CONTROL_SPARE_R_C0_MASK			(1 << 31)
-#define OMAP4_WKUP_CONTROL_SPARE_R_C1_SHIFT			30
-#define OMAP4_WKUP_CONTROL_SPARE_R_C1_MASK			(1 << 30)
-#define OMAP4_WKUP_CONTROL_SPARE_R_C2_SHIFT			29
-#define OMAP4_WKUP_CONTROL_SPARE_R_C2_MASK			(1 << 29)
-#define OMAP4_WKUP_CONTROL_SPARE_R_C3_SHIFT			28
-#define OMAP4_WKUP_CONTROL_SPARE_R_C3_MASK			(1 << 28)
-#define OMAP4_WKUP_CONTROL_SPARE_R_C4_SHIFT			27
-#define OMAP4_WKUP_CONTROL_SPARE_R_C4_MASK			(1 << 27)
-#define OMAP4_WKUP_CONTROL_SPARE_R_C5_SHIFT			26
-#define OMAP4_WKUP_CONTROL_SPARE_R_C5_MASK			(1 << 26)
-#define OMAP4_WKUP_CONTROL_SPARE_R_C6_SHIFT			25
-#define OMAP4_WKUP_CONTROL_SPARE_R_C6_MASK			(1 << 25)
-#define OMAP4_WKUP_CONTROL_SPARE_R_C7_SHIFT			24
-#define OMAP4_WKUP_CONTROL_SPARE_R_C7_MASK			(1 << 24)
-
-#endif
diff --git a/arch/arm/mach-omap2/include/mach/ctrl_module_wkup_44xx.h b/arch/arm/mach-omap2/include/mach/ctrl_module_wkup_44xx.h
deleted file mode 100644
index a0af9ba..0000000
--- a/arch/arm/mach-omap2/include/mach/ctrl_module_wkup_44xx.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * OMAP44xx CTRL_MODULE_WKUP registers and bitfields
- *
- * Copyright (C) 2009-2010 Texas Instruments, Inc.
- *
- * Benoit Cousson (b-cousson@ti.com)
- * Santosh Shilimkar (santosh.shilimkar@ti.com)
- *
- * This file is automatically generated from the OMAP hardware databases.
- * We respectfully ask that any modifications to this file be coordinated
- * with the public linux-omap@vger.kernel.org mailing list and the
- * authors above to ensure that the autogeneration scripts are kept
- * up-to-date with the file contents.
- *
- * This program is free software; you can 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_CTRL_MODULE_WKUP_44XX_H
-#define __ARCH_ARM_MACH_OMAP2_CTRL_MODULE_WKUP_44XX_H
-
-
-/* Base address */
-#define OMAP4_CTRL_MODULE_WKUP				0x4a30c000
-
-/* Registers offset */
-#define OMAP4_CTRL_MODULE_WKUP_IP_REVISION		0x0000
-#define OMAP4_CTRL_MODULE_WKUP_IP_HWINFO		0x0004
-#define OMAP4_CTRL_MODULE_WKUP_IP_SYSCONFIG		0x0010
-#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_0	0x0460
-#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_1	0x0464
-#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_2	0x0468
-#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_3	0x046c
-#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_4	0x0470
-#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_5	0x0474
-#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_6	0x0478
-#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_7	0x047c
-#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_8	0x0480
-#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_9	0x0484
-#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_10	0x0488
-#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_11	0x048c
-#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_12	0x0490
-#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_13	0x0494
-#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_14	0x0498
-#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_15	0x049c
-#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_16	0x04a0
-#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_17	0x04a4
-#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_18	0x04a8
-#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_19	0x04ac
-#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_20	0x04b0
-#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_21	0x04b4
-#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_22	0x04b8
-#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_23	0x04bc
-#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_24	0x04c0
-#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_25	0x04c4
-#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_26	0x04c8
-#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_27	0x04cc
-#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_28	0x04d0
-#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_29	0x04d4
-#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_30	0x04d8
-#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_31	0x04dc
-
-/* Registers shifts and masks */
-
-/* IP_REVISION */
-#define OMAP4_IP_REV_SCHEME_SHIFT		30
-#define OMAP4_IP_REV_SCHEME_MASK		(0x3 << 30)
-#define OMAP4_IP_REV_FUNC_SHIFT			16
-#define OMAP4_IP_REV_FUNC_MASK			(0xfff << 16)
-#define OMAP4_IP_REV_RTL_SHIFT			11
-#define OMAP4_IP_REV_RTL_MASK			(0x1f << 11)
-#define OMAP4_IP_REV_MAJOR_SHIFT		8
-#define OMAP4_IP_REV_MAJOR_MASK			(0x7 << 8)
-#define OMAP4_IP_REV_CUSTOM_SHIFT		6
-#define OMAP4_IP_REV_CUSTOM_MASK		(0x3 << 6)
-#define OMAP4_IP_REV_MINOR_SHIFT		0
-#define OMAP4_IP_REV_MINOR_MASK			(0x3f << 0)
-
-/* IP_HWINFO */
-#define OMAP4_IP_HWINFO_SHIFT			0
-#define OMAP4_IP_HWINFO_MASK			(0xffffffff << 0)
-
-/* IP_SYSCONFIG */
-#define OMAP4_IP_SYSCONFIG_IDLEMODE_SHIFT	2
-#define OMAP4_IP_SYSCONFIG_IDLEMODE_MASK	(0x3 << 2)
-
-/* CONF_DEBUG_SEL_TST_0 */
-#define OMAP4_WKUP_MODE_SHIFT			0
-#define OMAP4_WKUP_MODE_MASK				(1 << 0)
-
-#endif
diff --git a/arch/arm/mach-omap2/include/mach/gpio.h b/arch/arm/mach-omap2/include/mach/gpio.h
index be4d290..5621cc5 100644
--- a/arch/arm/mach-omap2/include/mach/gpio.h
+++ b/arch/arm/mach-omap2/include/mach/gpio.h
@@ -1,5 +1,3 @@
 /*
  * arch/arm/mach-omap2/include/mach/gpio.h
  */
-
-#include <plat/gpio.h>
diff --git a/arch/arm/mach-omap2/include/mach/hardware.h b/arch/arm/mach-omap2/include/mach/hardware.h
index 78edf9d..54492db 100644
--- a/arch/arm/mach-omap2/include/mach/hardware.h
+++ b/arch/arm/mach-omap2/include/mach/hardware.h
@@ -1,5 +1,3 @@
 /*
  * arch/arm/mach-omap2/include/mach/hardware.h
  */
-
-#include <plat/hardware.h>
diff --git a/arch/arm/mach-omap2/include/mach/id.h b/arch/arm/mach-omap2/include/mach/id.h
deleted file mode 100644
index 02ed3aa..0000000
--- a/arch/arm/mach-omap2/include/mach/id.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * OMAP2 CPU identification code
- *
- * Copyright (C) 2010 Kan-Ru Chen <kanru@0xlab.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#ifndef OMAP2_ARCH_ID_H
-#define OMAP2_ARCH_ID_H
-
-struct omap_die_id {
-	u32 id_0;
-	u32 id_1;
-	u32 id_2;
-	u32 id_3;
-};
-
-void omap_get_die_id(struct omap_die_id *odi);
-
-#endif
diff --git a/arch/arm/mach-omap2/include/mach/irqs.h b/arch/arm/mach-omap2/include/mach/irqs.h
index 44dab77..ba5282c 100644
--- a/arch/arm/mach-omap2/include/mach/irqs.h
+++ b/arch/arm/mach-omap2/include/mach/irqs.h
@@ -1,5 +1,3 @@
 /*
  * arch/arm/mach-omap2/include/mach/irqs.h
  */
-
-#include <plat/irqs.h>
diff --git a/arch/arm/mach-omap2/include/mach/omap-secure.h b/arch/arm/mach-omap2/include/mach/omap-secure.h
deleted file mode 100644
index c90a435..0000000
--- a/arch/arm/mach-omap2/include/mach/omap-secure.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * omap-secure.h: OMAP Secure infrastructure header.
- *
- * Copyright (C) 2011 Texas Instruments, Inc.
- *	Santosh Shilimkar <santosh.shilimkar@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.
- */
-#ifndef OMAP_ARCH_OMAP_SECURE_H
-#define OMAP_ARCH_OMAP_SECURE_H
-
-/* Monitor error code */
-#define  API_HAL_RET_VALUE_NS2S_CONVERSION_ERROR	0xFFFFFFFE
-#define  API_HAL_RET_VALUE_SERVICE_UNKNWON		0xFFFFFFFF
-
-/* HAL API error codes */
-#define  API_HAL_RET_VALUE_OK		0x00
-#define  API_HAL_RET_VALUE_FAIL		0x01
-
-/* Secure HAL API flags */
-#define FLAG_START_CRITICAL		0x4
-#define FLAG_IRQFIQ_MASK		0x3
-#define FLAG_IRQ_ENABLE			0x2
-#define FLAG_FIQ_ENABLE			0x1
-#define NO_FLAG				0x0
-
-/* Maximum Secure memory storage size */
-#define OMAP_SECURE_RAM_STORAGE	(88 * SZ_1K)
-
-/* Secure low power HAL API index */
-#define OMAP4_HAL_SAVESECURERAM_INDEX	0x1a
-#define OMAP4_HAL_SAVEHW_INDEX		0x1b
-#define OMAP4_HAL_SAVEALL_INDEX		0x1c
-#define OMAP4_HAL_SAVEGIC_INDEX		0x1d
-
-/* Secure Monitor mode APIs */
-#define OMAP4_MON_SCU_PWR_INDEX		0x108
-#define OMAP4_MON_L2X0_DBG_CTRL_INDEX	0x100
-#define OMAP4_MON_L2X0_CTRL_INDEX	0x102
-#define OMAP4_MON_L2X0_AUXCTRL_INDEX	0x109
-#define OMAP4_MON_L2X0_PREFETCH_INDEX	0x113
-
-/* Secure PPA(Primary Protected Application) APIs */
-#define OMAP4_PPA_L2_POR_INDEX		0x23
-#define OMAP4_PPA_CPU_ACTRL_SMP_INDEX	0x25
-
-#ifndef __ASSEMBLER__
-
-extern u32 omap_secure_dispatcher(u32 idx, u32 flag, u32 nargs,
-				u32 arg1, u32 arg2, u32 arg3, u32 arg4);
-extern u32 omap_smc2(u32 id, u32 falg, u32 pargs);
-extern phys_addr_t omap_secure_ram_mempool_base(void);
-
-#endif /* __ASSEMBLER__ */
-#endif /* OMAP_ARCH_OMAP_SECURE_H */
diff --git a/arch/arm/mach-omap2/include/mach/omap-wakeupgen.h b/arch/arm/mach-omap2/include/mach/omap-wakeupgen.h
deleted file mode 100644
index b0fd16f..0000000
--- a/arch/arm/mach-omap2/include/mach/omap-wakeupgen.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * OMAP WakeupGen header file
- *
- * Copyright (C) 2011 Texas Instruments, Inc.
- *	Santosh Shilimkar <santosh.shilimkar@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.
- */
-#ifndef OMAP_ARCH_WAKEUPGEN_H
-#define OMAP_ARCH_WAKEUPGEN_H
-
-/* OMAP4 and OMAP5 has same base address */
-#define OMAP_WKUPGEN_BASE			0x48281000
-
-#define OMAP_WKG_CONTROL_0			0x00
-#define OMAP_WKG_ENB_A_0			0x10
-#define OMAP_WKG_ENB_B_0			0x14
-#define OMAP_WKG_ENB_C_0			0x18
-#define OMAP_WKG_ENB_D_0			0x1c
-#define OMAP_WKG_ENB_E_0			0x20
-#define OMAP_WKG_ENB_A_1			0x410
-#define OMAP_WKG_ENB_B_1			0x414
-#define OMAP_WKG_ENB_C_1			0x418
-#define OMAP_WKG_ENB_D_1			0x41c
-#define OMAP_WKG_ENB_E_1			0x420
-#define OMAP_AUX_CORE_BOOT_0			0x800
-#define OMAP_AUX_CORE_BOOT_1			0x804
-#define OMAP_PTMSYNCREQ_MASK			0xc00
-#define OMAP_PTMSYNCREQ_EN			0xc04
-#define OMAP_TIMESTAMPCYCLELO			0xc08
-#define OMAP_TIMESTAMPCYCLEHI			0xc0c
-
-extern int __init omap_wakeupgen_init(void);
-extern void __iomem *omap_get_wakeupgen_base(void);
-extern int omap_secure_apis_support(void);
-#endif
diff --git a/arch/arm/mach-omap2/include/mach/smp.h b/arch/arm/mach-omap2/include/mach/smp.h
deleted file mode 100644
index 323675f..0000000
--- a/arch/arm/mach-omap2/include/mach/smp.h
+++ /dev/null
@@ -1,5 +0,0 @@
-/*
- * arch/arm/mach-omap2/include/mach/smp.h
- */
-
-#include <plat/smp.h>
diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
index 4d2d981..4234d28 100644
--- a/arch/arm/mach-omap2/io.c
+++ b/arch/arm/mach-omap2/io.c
@@ -33,6 +33,7 @@
 #include <plat/multi.h>
 #include <plat/dma.h>
 
+#include "soc.h"
 #include "iomap.h"
 #include "voltage.h"
 #include "powerdomain.h"
@@ -523,6 +524,8 @@ void __init am33xx_init_early(void)
 	am33xx_voltagedomains_init();
 	am33xx_powerdomains_init();
 	am33xx_clockdomains_init();
+	am33xx_hwmod_init();
+	omap_hwmod_init_postsetup();
 	am33xx_clk_init();
 }
 #endif
diff --git a/arch/arm/mach-omap2/irq.c b/arch/arm/mach-omap2/irq.c
index bcd83db..3926f37 100644
--- a/arch/arm/mach-omap2/irq.c
+++ b/arch/arm/mach-omap2/irq.c
@@ -23,8 +23,7 @@
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 
-#include <mach/hardware.h>
-
+#include "soc.h"
 #include "iomap.h"
 #include "common.h"
 
@@ -49,6 +48,8 @@
 #define OMAP3_IRQ_BASE		OMAP2_L4_IO_ADDRESS(OMAP34XX_IC_BASE)
 #define INTCPS_SIR_IRQ_OFFSET	0x0040	/* omap2/3 active interrupt offset */
 #define ACTIVEIRQ_MASK		0x7f	/* omap2/3 active interrupt bits */
+#define INTCPS_NR_MIR_REGS	3
+#define INTCPS_NR_IRQS		96
 
 /*
  * OMAP2 has a number of different interrupt controllers, each interrupt
@@ -107,9 +108,8 @@ static void __init omap_irq_bank_init_one(struct omap_irq_bank *bank)
 	unsigned long tmp;
 
 	tmp = intc_bank_read_reg(bank, INTC_REVISION) & 0xff;
-	printk(KERN_INFO "IRQ: Found an INTC at 0x%p "
-			 "(revision %ld.%ld) with %d interrupts\n",
-			 bank->base_reg, tmp >> 4, tmp & 0xf, bank->nr_irqs);
+	pr_info("IRQ: Found an INTC at 0x%p (revision %ld.%ld) with %d interrupts\n",
+		bank->base_reg, tmp >> 4, tmp & 0xf, bank->nr_irqs);
 
 	tmp = intc_bank_read_reg(bank, INTC_SYSCONFIG);
 	tmp |= 1 << 1;	/* soft reset */
diff --git a/arch/arm/mach-omap2/l3_2xxx.h b/arch/arm/mach-omap2/l3_2xxx.h
new file mode 100644
index 0000000..b8b5641
--- /dev/null
+++ b/arch/arm/mach-omap2/l3_2xxx.h
@@ -0,0 +1,20 @@
+/*
+ * arch/arm/plat-omap/include/plat/l3_2xxx.h - L3 firewall definitions
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ *	Sumit Semwal
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_L3_2XXX_H
+#define __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_L3_2XXX_H
+
+/* L3 CONNIDs */
+/* Display Sub system (DSS) */
+#define OMAP2_L3_CORE_FW_CONNID_DSS			8
+
+#endif
diff --git a/arch/arm/mach-omap2/l3_3xxx.h b/arch/arm/mach-omap2/l3_3xxx.h
new file mode 100644
index 0000000..cde1938
--- /dev/null
+++ b/arch/arm/mach-omap2/l3_3xxx.h
@@ -0,0 +1,20 @@
+/*
+ * arch/arm/plat-omap/include/plat/l3_3xxx.h - L3 firewall definitions
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ *	Sumit Semwal
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_L3_3XXX_H
+#define __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_L3_3XXX_H
+
+/* L3 Initiator IDs */
+/* Display Sub system (DSS) */
+#define OMAP3_L3_CORE_FW_INIT_ID_DSS			29
+
+#endif
diff --git a/arch/arm/mach-omap2/l4_2xxx.h b/arch/arm/mach-omap2/l4_2xxx.h
new file mode 100644
index 0000000..3f39cf8
--- /dev/null
+++ b/arch/arm/mach-omap2/l4_2xxx.h
@@ -0,0 +1,24 @@
+/*
+ * arch/arm/plat-omap/include/plat/l4_2xxx.h - L4 firewall definitions
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ *	Sumit Semwal
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_L4_2XXX_H
+#define __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_L4_2XXX_H
+
+/* L4 CORE */
+/* Display Sub system (DSS) */
+#define OMAP2420_L4_CORE_FW_DSS_CORE_REGION			28
+#define OMAP2420_L4_CORE_FW_DSS_DISPC_REGION			29
+#define OMAP2420_L4_CORE_FW_DSS_RFBI_REGION			30
+#define OMAP2420_L4_CORE_FW_DSS_VENC_REGION			31
+#define OMAP2420_L4_CORE_FW_DSS_TA_REGION			32
+
+#endif
diff --git a/arch/arm/mach-omap2/l4_3xxx.h b/arch/arm/mach-omap2/l4_3xxx.h
new file mode 100644
index 0000000..881a858
--- /dev/null
+++ b/arch/arm/mach-omap2/l4_3xxx.h
@@ -0,0 +1,34 @@
+/*
+ * arch/arm/plat-omap/include/mach/l4_3xxx.h - L4 firewall definitions
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ * Paul Walmsley
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 __ARCH_ARM_PLAT_OMAP_INCLUDE_MACH_L4_3XXX_H
+#define __ARCH_ARM_PLAT_OMAP_INCLUDE_MACH_L4_3XXX_H
+
+/* L4 CORE */
+#define OMAP3_L4_CORE_FW_I2C1_REGION				21
+#define OMAP3_L4_CORE_FW_I2C1_TA_REGION				22
+#define OMAP3_L4_CORE_FW_I2C2_REGION				23
+#define OMAP3_L4_CORE_FW_I2C2_TA_REGION				24
+#define OMAP3_L4_CORE_FW_I2C3_REGION				73
+#define OMAP3_L4_CORE_FW_I2C3_TA_REGION				74
+
+/* Display Sub system (DSS) */
+#define OMAP3_L4_CORE_FW_DSS_PROT_GROUP				2
+
+#define OMAP3_L4_CORE_FW_DSS_DSI_REGION				104
+#define OMAP3ES1_L4_CORE_FW_DSS_CORE_REGION			3
+#define OMAP3_L4_CORE_FW_DSS_CORE_REGION			4
+#define OMAP3_L4_CORE_FW_DSS_DISPC_REGION			4
+#define OMAP3_L4_CORE_FW_DSS_RFBI_REGION			5
+#define OMAP3_L4_CORE_FW_DSS_VENC_REGION			6
+#define OMAP3_L4_CORE_FW_DSS_TA_REGION				7
+#endif
diff --git a/arch/arm/mach-omap2/mailbox.c b/arch/arm/mach-omap2/mailbox.c
index 6875be8..0d97456 100644
--- a/arch/arm/mach-omap2/mailbox.c
+++ b/arch/arm/mach-omap2/mailbox.c
@@ -16,8 +16,10 @@
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/pm_runtime.h>
+
 #include <plat/mailbox.h>
-#include <mach/irqs.h>
+
+#include "soc.h"
 
 #define MAILBOX_REVISION		0x000
 #define MAILBOX_MESSAGE(m)		(0x040 + 4 * (m))
diff --git a/arch/arm/mach-omap2/mcbsp.c b/arch/arm/mach-omap2/mcbsp.c
index 577cb77..37f8f94 100644
--- a/arch/arm/mach-omap2/mcbsp.c
+++ b/arch/arm/mach-omap2/mcbsp.c
@@ -15,18 +15,15 @@
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/io.h>
+#include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
+#include <linux/platform_data/asoc-ti-mcbsp.h>
 
-#include <mach/irqs.h>
 #include <plat/dma.h>
-#include <plat/cpu.h>
-#include <plat/mcbsp.h>
 #include <plat/omap_device.h>
 #include <linux/pm_runtime.h>
 
-#include "control.h"
-
 /*
  * FIXME: Find a mechanism to enable/disable runtime the McBSP ICLK autoidle.
  * Sidetone needs non-gated ICLK and sidetone autoidle is broken.
@@ -34,112 +31,6 @@
 #include "cm2xxx_3xxx.h"
 #include "cm-regbits-34xx.h"
 
-/* McBSP1 internal signal muxing function for OMAP2/3 */
-static int omap2_mcbsp1_mux_rx_clk(struct device *dev, const char *signal,
-				   const char *src)
-{
-	u32 v;
-
-	v = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0);
-
-	if (!strcmp(signal, "clkr")) {
-		if (!strcmp(src, "clkr"))
-			v &= ~OMAP2_MCBSP1_CLKR_MASK;
-		else if (!strcmp(src, "clkx"))
-			v |= OMAP2_MCBSP1_CLKR_MASK;
-		else
-			return -EINVAL;
-	} else if (!strcmp(signal, "fsr")) {
-		if (!strcmp(src, "fsr"))
-			v &= ~OMAP2_MCBSP1_FSR_MASK;
-		else if (!strcmp(src, "fsx"))
-			v |= OMAP2_MCBSP1_FSR_MASK;
-		else
-			return -EINVAL;
-	} else {
-		return -EINVAL;
-	}
-
-	omap_ctrl_writel(v, OMAP2_CONTROL_DEVCONF0);
-
-	return 0;
-}
-
-/* McBSP4 internal signal muxing function for OMAP4 */
-#define OMAP4_CONTROL_MCBSPLP_ALBCTRLRX_FSX	(1 << 31)
-#define OMAP4_CONTROL_MCBSPLP_ALBCTRLRX_CLKX	(1 << 30)
-static int omap4_mcbsp4_mux_rx_clk(struct device *dev, const char *signal,
-				   const char *src)
-{
-	u32 v;
-
-	/*
-	 * In CONTROL_MCBSPLP register only bit 30 (CLKR mux), and bit 31 (FSR
-	 * mux) is used */
-	v = omap4_ctrl_pad_readl(OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_MCBSPLP);
-
-	if (!strcmp(signal, "clkr")) {
-		if (!strcmp(src, "clkr"))
-			v &= ~OMAP4_CONTROL_MCBSPLP_ALBCTRLRX_CLKX;
-		else if (!strcmp(src, "clkx"))
-			v |= OMAP4_CONTROL_MCBSPLP_ALBCTRLRX_CLKX;
-		else
-			return -EINVAL;
-	} else if (!strcmp(signal, "fsr")) {
-		if (!strcmp(src, "fsr"))
-			v &= ~OMAP4_CONTROL_MCBSPLP_ALBCTRLRX_FSX;
-		else if (!strcmp(src, "fsx"))
-			v |= OMAP4_CONTROL_MCBSPLP_ALBCTRLRX_FSX;
-		else
-			return -EINVAL;
-	} else {
-		return -EINVAL;
-	}
-
-	omap4_ctrl_pad_writel(v, OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_MCBSPLP);
-
-	return 0;
-}
-
-/* McBSP CLKS source switching function */
-static int omap2_mcbsp_set_clk_src(struct device *dev, struct clk *clk,
-				   const char *src)
-{
-	struct clk *fck_src;
-	char *fck_src_name;
-	int r;
-
-	if (!strcmp(src, "clks_ext"))
-		fck_src_name = "pad_fck";
-	else if (!strcmp(src, "clks_fclk"))
-		fck_src_name = "prcm_fck";
-	else
-		return -EINVAL;
-
-	fck_src = clk_get(dev, fck_src_name);
-	if (IS_ERR_OR_NULL(fck_src)) {
-		pr_err("omap-mcbsp: %s: could not clk_get() %s\n", "clks",
-		       fck_src_name);
-		return -EINVAL;
-	}
-
-	pm_runtime_put_sync(dev);
-
-	r = clk_set_parent(clk, fck_src);
-	if (IS_ERR_VALUE(r)) {
-		pr_err("omap-mcbsp: %s: could not clk_set_parent() to %s\n",
-		       "clks", fck_src_name);
-		clk_put(fck_src);
-		return -EINVAL;
-	}
-
-	pm_runtime_get_sync(dev);
-
-	clk_put(fck_src);
-
-	return 0;
-}
-
 static int omap3_enable_st_clock(unsigned int id, bool enable)
 {
 	unsigned int w;
@@ -181,17 +72,11 @@ static int __init omap_init_mcbsp(struct omap_hwmod *oh, void *unused)
 		pdata->reg_size = 4;
 		pdata->has_ccr = true;
 	}
-	pdata->set_clk_src = omap2_mcbsp_set_clk_src;
-
-	/* On OMAP2/3 the McBSP1 port has 6 pin configuration */
-	if (id == 1 && oh->class->rev < MCBSP_CONFIG_TYPE4)
-		pdata->mux_signal = omap2_mcbsp1_mux_rx_clk;
 
-	/* On OMAP4 the McBSP4 port has 6 pin configuration */
-	if (id == 4 && oh->class->rev == MCBSP_CONFIG_TYPE4)
-		pdata->mux_signal = omap4_mcbsp4_mux_rx_clk;
-
-	if (oh->class->rev == MCBSP_CONFIG_TYPE3) {
+	if (oh->class->rev == MCBSP_CONFIG_TYPE2) {
+		/* The FIFO has 128 locations */
+		pdata->buffer_size = 0x80;
+	} else if (oh->class->rev == MCBSP_CONFIG_TYPE3) {
 		if (id == 2)
 			/* The FIFO has 1024 + 256 locations */
 			pdata->buffer_size = 0x500;
@@ -227,7 +112,8 @@ static int __init omap_init_mcbsp(struct omap_hwmod *oh, void *unused)
 
 static int __init omap2_mcbsp_init(void)
 {
-	omap_hwmod_for_each_by_class("mcbsp", omap_init_mcbsp, NULL);
+	if (!of_have_populated_dt())
+		omap_hwmod_for_each_by_class("mcbsp", omap_init_mcbsp, NULL);
 
 	return 0;
 }
diff --git a/arch/arm/mach-omap2/msdi.c b/arch/arm/mach-omap2/msdi.c
index fb5bc6c..9e57b4a 100644
--- a/arch/arm/mach-omap2/msdi.c
+++ b/arch/arm/mach-omap2/msdi.c
@@ -23,6 +23,7 @@
 
 #include <linux/kernel.h>
 #include <linux/err.h>
+#include <linux/platform_data/gpio-omap.h>
 
 #include <plat/omap_hwmod.h>
 #include <plat/omap_device.h>
diff --git a/arch/arm/mach-omap2/omap-hotplug.c b/arch/arm/mach-omap2/omap-hotplug.c
index 414083b..e712d17 100644
--- a/arch/arm/mach-omap2/omap-hotplug.c
+++ b/arch/arm/mach-omap2/omap-hotplug.c
@@ -20,22 +20,17 @@
 #include <linux/io.h>
 
 #include <asm/cacheflush.h>
-#include <mach/omap-wakeupgen.h>
+#include "omap-wakeupgen.h"
 
 #include "common.h"
 
 #include "powerdomain.h"
 
-int platform_cpu_kill(unsigned int cpu)
-{
-	return 1;
-}
-
 /*
  * platform-specific code to shutdown a CPU
  * Called with IRQs disabled
  */
-void __ref platform_cpu_die(unsigned int cpu)
+void __ref omap4_cpu_die(unsigned int cpu)
 {
 	unsigned int boot_cpu = 0;
 	void __iomem *base = omap_get_wakeupgen_base();
@@ -75,12 +70,3 @@ void __ref platform_cpu_die(unsigned int cpu)
 		pr_debug("CPU%u: spurious wakeup call\n", cpu);
 	}
 }
-
-int platform_cpu_disable(unsigned int cpu)
-{
-	/*
-	 * we don't allow CPU 0 to be shutdown (it is still too special
-	 * e.g. clock tick interrupts)
-	 */
-	return cpu == 0 ? -EPERM : 0;
-}
diff --git a/arch/arm/mach-omap2/omap-iommu.c b/arch/arm/mach-omap2/omap-iommu.c
index 1be8bcb..df298d4 100644
--- a/arch/arm/mach-omap2/omap-iommu.c
+++ b/arch/arm/mach-omap2/omap-iommu.c
@@ -14,7 +14,9 @@
 #include <linux/platform_device.h>
 
 #include <plat/iommu.h>
-#include <plat/irqs.h>
+
+#include "soc.h"
+#include "common.h"
 
 struct iommu_device {
 	resource_size_t base;
@@ -29,7 +31,7 @@ static int num_iommu_devices;
 static struct iommu_device omap3_devices[] = {
 	{
 		.base = 0x480bd400,
-		.irq = 24,
+		.irq = 24 + OMAP_INTC_START,
 		.pdata = {
 			.name = "isp",
 			.nr_tlb_entries = 8,
@@ -41,7 +43,7 @@ static struct iommu_device omap3_devices[] = {
 #if defined(CONFIG_OMAP_IOMMU_IVA2)
 	{
 		.base = 0x5d000000,
-		.irq = 28,
+		.irq = 28 + OMAP_INTC_START,
 		.pdata = {
 			.name = "iva2",
 			.nr_tlb_entries = 32,
@@ -64,7 +66,7 @@ static struct platform_device *omap3_iommu_pdev[NR_OMAP3_IOMMU_DEVICES];
 static struct iommu_device omap4_devices[] = {
 	{
 		.base = OMAP4_MMU1_BASE,
-		.irq = OMAP44XX_IRQ_DUCATI_MMU,
+		.irq = 100 + OMAP44XX_IRQ_GIC_START,
 		.pdata = {
 			.name = "ducati",
 			.nr_tlb_entries = 32,
@@ -75,7 +77,7 @@ static struct iommu_device omap4_devices[] = {
 	},
 	{
 		.base = OMAP4_MMU2_BASE,
-		.irq = OMAP44XX_IRQ_TESLA_MMU,
+		.irq = 28 + OMAP44XX_IRQ_GIC_START,
 		.pdata = {
 			.name = "tesla",
 			.nr_tlb_entries = 32,
diff --git a/arch/arm/mach-omap2/omap-mpuss-lowpower.c b/arch/arm/mach-omap2/omap-mpuss-lowpower.c
index 637a1bd..ff4e6a0 100644
--- a/arch/arm/mach-omap2/omap-mpuss-lowpower.c
+++ b/arch/arm/mach-omap2/omap-mpuss-lowpower.c
@@ -50,9 +50,8 @@
 #include <asm/suspend.h>
 #include <asm/hardware/cache-l2x0.h>
 
-#include <plat/omap44xx.h>
-
 #include "common.h"
+#include "omap44xx.h"
 #include "omap4-sar-layout.h"
 #include "pm.h"
 #include "prcm_mpu44xx.h"
diff --git a/arch/arm/mach-omap2/omap-secure.c b/arch/arm/mach-omap2/omap-secure.c
index d9ae4a5..a004cb9 100644
--- a/arch/arm/mach-omap2/omap-secure.c
+++ b/arch/arm/mach-omap2/omap-secure.c
@@ -19,7 +19,7 @@
 #include <asm/memblock.h>
 
 #include <plat/omap-secure.h>
-#include <mach/omap-secure.h>
+#include "omap-secure.h"
 
 static phys_addr_t omap_secure_memblock_base;
 
diff --git a/arch/arm/mach-omap2/omap-secure.h b/arch/arm/mach-omap2/omap-secure.h
new file mode 100644
index 0000000..c90a435
--- /dev/null
+++ b/arch/arm/mach-omap2/omap-secure.h
@@ -0,0 +1,57 @@
+/*
+ * omap-secure.h: OMAP Secure infrastructure header.
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ *	Santosh Shilimkar <santosh.shilimkar@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.
+ */
+#ifndef OMAP_ARCH_OMAP_SECURE_H
+#define OMAP_ARCH_OMAP_SECURE_H
+
+/* Monitor error code */
+#define  API_HAL_RET_VALUE_NS2S_CONVERSION_ERROR	0xFFFFFFFE
+#define  API_HAL_RET_VALUE_SERVICE_UNKNWON		0xFFFFFFFF
+
+/* HAL API error codes */
+#define  API_HAL_RET_VALUE_OK		0x00
+#define  API_HAL_RET_VALUE_FAIL		0x01
+
+/* Secure HAL API flags */
+#define FLAG_START_CRITICAL		0x4
+#define FLAG_IRQFIQ_MASK		0x3
+#define FLAG_IRQ_ENABLE			0x2
+#define FLAG_FIQ_ENABLE			0x1
+#define NO_FLAG				0x0
+
+/* Maximum Secure memory storage size */
+#define OMAP_SECURE_RAM_STORAGE	(88 * SZ_1K)
+
+/* Secure low power HAL API index */
+#define OMAP4_HAL_SAVESECURERAM_INDEX	0x1a
+#define OMAP4_HAL_SAVEHW_INDEX		0x1b
+#define OMAP4_HAL_SAVEALL_INDEX		0x1c
+#define OMAP4_HAL_SAVEGIC_INDEX		0x1d
+
+/* Secure Monitor mode APIs */
+#define OMAP4_MON_SCU_PWR_INDEX		0x108
+#define OMAP4_MON_L2X0_DBG_CTRL_INDEX	0x100
+#define OMAP4_MON_L2X0_CTRL_INDEX	0x102
+#define OMAP4_MON_L2X0_AUXCTRL_INDEX	0x109
+#define OMAP4_MON_L2X0_PREFETCH_INDEX	0x113
+
+/* Secure PPA(Primary Protected Application) APIs */
+#define OMAP4_PPA_L2_POR_INDEX		0x23
+#define OMAP4_PPA_CPU_ACTRL_SMP_INDEX	0x25
+
+#ifndef __ASSEMBLER__
+
+extern u32 omap_secure_dispatcher(u32 idx, u32 flag, u32 nargs,
+				u32 arg1, u32 arg2, u32 arg3, u32 arg4);
+extern u32 omap_smc2(u32 id, u32 falg, u32 pargs);
+extern phys_addr_t omap_secure_ram_mempool_base(void);
+
+#endif /* __ASSEMBLER__ */
+#endif /* OMAP_ARCH_OMAP_SECURE_H */
diff --git a/arch/arm/mach-omap2/omap-smp.c b/arch/arm/mach-omap2/omap-smp.c
index 9a35adf..4d05fa8 100644
--- a/arch/arm/mach-omap2/omap-smp.c
+++ b/arch/arm/mach-omap2/omap-smp.c
@@ -24,11 +24,11 @@
 #include <asm/hardware/gic.h>
 #include <asm/smp_scu.h>
 
-#include <mach/hardware.h>
-#include <mach/omap-secure.h>
-#include <mach/omap-wakeupgen.h>
+#include "omap-secure.h"
+#include "omap-wakeupgen.h"
 #include <asm/cputype.h>
 
+#include "soc.h"
 #include "iomap.h"
 #include "common.h"
 #include "clockdomain.h"
@@ -49,7 +49,7 @@ void __iomem *omap4_get_scu_base(void)
 	return scu_base;
 }
 
-void __cpuinit platform_secondary_init(unsigned int cpu)
+static void __cpuinit omap4_secondary_init(unsigned int cpu)
 {
 	/*
 	 * Configure ACTRL and enable NS SMP bit access on CPU1 on HS device.
@@ -77,7 +77,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
 	spin_unlock(&boot_lock);
 }
 
-int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
+static int __cpuinit omap4_boot_secondary(unsigned int cpu, struct task_struct *idle)
 {
 	static struct clockdomain *cpu1_clkdm;
 	static bool booted;
@@ -165,7 +165,7 @@ static void __init wakeup_secondary(void)
  * Initialise the CPU possible map early - this describes the CPUs
  * which may be present or become present in the system.
  */
-void __init smp_init_cpus(void)
+static void __init omap4_smp_init_cpus(void)
 {
 	unsigned int i = 0, ncores = 1, cpu_id;
 
@@ -196,7 +196,7 @@ void __init smp_init_cpus(void)
 	set_smp_cross_call(gic_raise_softirq);
 }
 
-void __init platform_smp_prepare_cpus(unsigned int max_cpus)
+static void __init omap4_smp_prepare_cpus(unsigned int max_cpus)
 {
 
 	/*
@@ -207,3 +207,13 @@ void __init platform_smp_prepare_cpus(unsigned int max_cpus)
 		scu_enable(scu_base);
 	wakeup_secondary();
 }
+
+struct smp_operations omap4_smp_ops __initdata = {
+	.smp_init_cpus		= omap4_smp_init_cpus,
+	.smp_prepare_cpus	= omap4_smp_prepare_cpus,
+	.smp_secondary_init	= omap4_secondary_init,
+	.smp_boot_secondary	= omap4_boot_secondary,
+#ifdef CONFIG_HOTPLUG_CPU
+	.cpu_die		= omap4_cpu_die,
+#endif
+};
diff --git a/arch/arm/mach-omap2/omap-wakeupgen.c b/arch/arm/mach-omap2/omap-wakeupgen.c
index 330d4c6..5d3b4f4 100644
--- a/arch/arm/mach-omap2/omap-wakeupgen.c
+++ b/arch/arm/mach-omap2/omap-wakeupgen.c
@@ -27,9 +27,10 @@
 
 #include <asm/hardware/gic.h>
 
-#include <mach/omap-wakeupgen.h>
-#include <mach/omap-secure.h>
+#include "omap-wakeupgen.h"
+#include "omap-secure.h"
 
+#include "soc.h"
 #include "omap4-sar-layout.h"
 #include "common.h"
 
@@ -229,13 +230,7 @@ static inline void omap4_irq_save_context(void)
 	/* Save AuxBoot* registers */
 	val = __raw_readl(wakeupgen_base + OMAP_AUX_CORE_BOOT_0);
 	__raw_writel(val, sar_base + AUXCOREBOOT0_OFFSET);
-	val = __raw_readl(wakeupgen_base + OMAP_AUX_CORE_BOOT_0);
-	__raw_writel(val, sar_base + AUXCOREBOOT1_OFFSET);
-
-	/* Save SyncReq generation logic */
-	val = __raw_readl(wakeupgen_base + OMAP_AUX_CORE_BOOT_0);
-	__raw_writel(val, sar_base + AUXCOREBOOT0_OFFSET);
-	val = __raw_readl(wakeupgen_base + OMAP_AUX_CORE_BOOT_0);
+	val = __raw_readl(wakeupgen_base + OMAP_AUX_CORE_BOOT_1);
 	__raw_writel(val, sar_base + AUXCOREBOOT1_OFFSET);
 
 	/* Save SyncReq generation logic */
diff --git a/arch/arm/mach-omap2/omap-wakeupgen.h b/arch/arm/mach-omap2/omap-wakeupgen.h
new file mode 100644
index 0000000..b0fd16f
--- /dev/null
+++ b/arch/arm/mach-omap2/omap-wakeupgen.h
@@ -0,0 +1,38 @@
+/*
+ * OMAP WakeupGen header file
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ *	Santosh Shilimkar <santosh.shilimkar@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.
+ */
+#ifndef OMAP_ARCH_WAKEUPGEN_H
+#define OMAP_ARCH_WAKEUPGEN_H
+
+/* OMAP4 and OMAP5 has same base address */
+#define OMAP_WKUPGEN_BASE			0x48281000
+
+#define OMAP_WKG_CONTROL_0			0x00
+#define OMAP_WKG_ENB_A_0			0x10
+#define OMAP_WKG_ENB_B_0			0x14
+#define OMAP_WKG_ENB_C_0			0x18
+#define OMAP_WKG_ENB_D_0			0x1c
+#define OMAP_WKG_ENB_E_0			0x20
+#define OMAP_WKG_ENB_A_1			0x410
+#define OMAP_WKG_ENB_B_1			0x414
+#define OMAP_WKG_ENB_C_1			0x418
+#define OMAP_WKG_ENB_D_1			0x41c
+#define OMAP_WKG_ENB_E_1			0x420
+#define OMAP_AUX_CORE_BOOT_0			0x800
+#define OMAP_AUX_CORE_BOOT_1			0x804
+#define OMAP_PTMSYNCREQ_MASK			0xc00
+#define OMAP_PTMSYNCREQ_EN			0xc04
+#define OMAP_TIMESTAMPCYCLELO			0xc08
+#define OMAP_TIMESTAMPCYCLEHI			0xc0c
+
+extern int __init omap_wakeupgen_init(void);
+extern void __iomem *omap_get_wakeupgen_base(void);
+extern int omap_secure_apis_support(void);
+#endif
diff --git a/arch/arm/mach-omap2/omap24xx.h b/arch/arm/mach-omap2/omap24xx.h
new file mode 100644
index 0000000..641a2c8
--- /dev/null
+++ b/arch/arm/mach-omap2/omap24xx.h
@@ -0,0 +1,87 @@
+/*
+ * This file contains the processor specific definitions
+ * of the TI OMAP24XX.
+ *
+ * Copyright (C) 2007 Texas Instruments.
+ * Copyright (C) 2007 Nokia Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __ASM_ARCH_OMAP2_H
+#define __ASM_ARCH_OMAP2_H
+
+/*
+ * Please place only base defines here and put the rest in device
+ * specific headers. Note also that some of these defines are needed
+ * for omap1 to compile without adding ifdefs.
+ */
+
+#define L4_24XX_BASE		0x48000000
+#define L4_WK_243X_BASE		0x49000000
+#define L3_24XX_BASE		0x68000000
+
+/* interrupt controller */
+#define OMAP24XX_IC_BASE	(L4_24XX_BASE + 0xfe000)
+#define OMAP24XX_IVA_INTC_BASE	0x40000000
+
+#define OMAP242X_CTRL_BASE	L4_24XX_BASE
+#define OMAP2420_32KSYNCT_BASE	(L4_24XX_BASE + 0x4000)
+#define OMAP2420_PRCM_BASE	(L4_24XX_BASE + 0x8000)
+#define OMAP2420_CM_BASE	(L4_24XX_BASE + 0x8000)
+#define OMAP2420_PRM_BASE	OMAP2420_CM_BASE
+#define OMAP2420_SDRC_BASE	(L3_24XX_BASE + 0x9000)
+#define OMAP2420_SMS_BASE	0x68008000
+#define OMAP2420_GPMC_BASE	0x6800a000
+
+#define OMAP2430_32KSYNCT_BASE	(L4_WK_243X_BASE + 0x20000)
+#define OMAP2430_PRCM_BASE	(L4_WK_243X_BASE + 0x6000)
+#define OMAP2430_CM_BASE	(L4_WK_243X_BASE + 0x6000)
+#define OMAP2430_PRM_BASE	OMAP2430_CM_BASE
+
+#define OMAP243X_SMS_BASE	0x6C000000
+#define OMAP243X_SDRC_BASE	0x6D000000
+#define OMAP243X_GPMC_BASE	0x6E000000
+#define OMAP243X_SCM_BASE	(L4_WK_243X_BASE + 0x2000)
+#define OMAP243X_CTRL_BASE	OMAP243X_SCM_BASE
+#define OMAP243X_HS_BASE	(L4_24XX_BASE + 0x000ac000)
+
+/* DSP SS */
+#define OMAP2420_DSP_BASE	0x58000000
+#define OMAP2420_DSP_MEM_BASE	(OMAP2420_DSP_BASE + 0x0)
+#define OMAP2420_DSP_IPI_BASE	(OMAP2420_DSP_BASE + 0x1000000)
+#define OMAP2420_DSP_MMU_BASE	(OMAP2420_DSP_BASE + 0x2000000)
+
+#define OMAP243X_DSP_BASE	0x5C000000
+#define OMAP243X_DSP_MEM_BASE	(OMAP243X_DSP_BASE + 0x0)
+#define OMAP243X_DSP_MMU_BASE	(OMAP243X_DSP_BASE + 0x1000000)
+
+/* Mailbox */
+#define OMAP24XX_MAILBOX_BASE	(L4_24XX_BASE + 0x94000)
+
+/* Camera */
+#define OMAP24XX_CAMERA_BASE	(L4_24XX_BASE + 0x52000)
+
+/* Security */
+#define OMAP24XX_SEC_BASE	(L4_24XX_BASE + 0xA0000)
+#define OMAP24XX_SEC_RNG_BASE	(OMAP24XX_SEC_BASE + 0x0000)
+#define OMAP24XX_SEC_DES_BASE	(OMAP24XX_SEC_BASE + 0x2000)
+#define OMAP24XX_SEC_SHA1MD5_BASE (OMAP24XX_SEC_BASE + 0x4000)
+#define OMAP24XX_SEC_AES_BASE	(OMAP24XX_SEC_BASE + 0x6000)
+#define OMAP24XX_SEC_PKA_BASE	(OMAP24XX_SEC_BASE + 0x8000)
+
+#endif /* __ASM_ARCH_OMAP2_H */
+
diff --git a/arch/arm/mach-omap2/omap34xx.h b/arch/arm/mach-omap2/omap34xx.h
new file mode 100644
index 0000000..c0d1b4b
--- /dev/null
+++ b/arch/arm/mach-omap2/omap34xx.h
@@ -0,0 +1,99 @@
+/*
+ * This file contains the processor specific definitions of the TI OMAP34XX.
+ *
+ * Copyright (C) 2007 Texas Instruments.
+ * Copyright (C) 2007 Nokia Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __ASM_ARCH_OMAP3_H
+#define __ASM_ARCH_OMAP3_H
+
+/*
+ * Please place only base defines here and put the rest in device
+ * specific headers.
+ */
+
+#define L4_34XX_BASE		0x48000000
+#define L4_WK_34XX_BASE		0x48300000
+#define L4_PER_34XX_BASE	0x49000000
+#define L4_EMU_34XX_BASE	0x54000000
+#define L3_34XX_BASE		0x68000000
+
+#define L4_WK_AM33XX_BASE	0x44C00000
+
+#define OMAP3430_32KSYNCT_BASE	0x48320000
+#define OMAP3430_CM_BASE	0x48004800
+#define OMAP3430_PRM_BASE	0x48306800
+#define OMAP343X_SMS_BASE	0x6C000000
+#define OMAP343X_SDRC_BASE	0x6D000000
+#define OMAP34XX_GPMC_BASE	0x6E000000
+#define OMAP343X_SCM_BASE	0x48002000
+#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_REGS1_BASE	(OMAP3430_ISP_BASE + 0x1800)
+#define OMAP3430_ISP_CSIPHY2_BASE	(OMAP3430_ISP_BASE + 0x1970)
+#define OMAP3630_ISP_CSI2A_REGS2_BASE	(OMAP3430_ISP_BASE + 0x19C0)
+#define OMAP3630_ISP_CSI2C_REGS1_BASE	(OMAP3430_ISP_BASE + 0x1C00)
+#define OMAP3630_ISP_CSIPHY1_BASE	(OMAP3430_ISP_BASE + 0x1D70)
+#define OMAP3630_ISP_CSI2C_REGS2_BASE	(OMAP3430_ISP_BASE + 0x1DC0)
+
+#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_REGS1_END	(OMAP3430_ISP_CSI2A_REGS1_BASE + 0x16F)
+#define OMAP3430_ISP_CSIPHY2_END	(OMAP3430_ISP_CSIPHY2_BASE + 0x00B)
+#define OMAP3630_ISP_CSI2A_REGS2_END	(OMAP3630_ISP_CSI2A_REGS2_BASE + 0x3F)
+#define OMAP3630_ISP_CSI2C_REGS1_END	(OMAP3630_ISP_CSI2C_REGS1_BASE + 0x16F)
+#define OMAP3630_ISP_CSIPHY1_END	(OMAP3630_ISP_CSIPHY1_BASE + 0x00B)
+#define OMAP3630_ISP_CSI2C_REGS2_END	(OMAP3630_ISP_CSI2C_REGS2_BASE + 0x3F)
+
+#define OMAP34XX_HSUSB_OTG_BASE	(L4_34XX_BASE + 0xAB000)
+#define OMAP34XX_USBTLL_BASE	(L4_34XX_BASE + 0x62000)
+#define OMAP34XX_UHH_CONFIG_BASE	(L4_34XX_BASE + 0x64000)
+#define OMAP34XX_OHCI_BASE	(L4_34XX_BASE + 0x64400)
+#define OMAP34XX_EHCI_BASE	(L4_34XX_BASE + 0x64800)
+#define OMAP34XX_SR1_BASE	0x480C9000
+#define OMAP34XX_SR2_BASE	0x480CB000
+
+#define OMAP34XX_MAILBOX_BASE		(L4_34XX_BASE + 0x94000)
+
+/* Security */
+#define OMAP34XX_SEC_BASE	(L4_34XX_BASE + 0xA0000)
+#define OMAP34XX_SEC_SHA1MD5_BASE	(OMAP34XX_SEC_BASE + 0x23000)
+#define OMAP34XX_SEC_AES_BASE	(OMAP34XX_SEC_BASE + 0x25000)
+
+#endif /* __ASM_ARCH_OMAP3_H */
+
diff --git a/arch/arm/mach-omap2/omap4-common.c b/arch/arm/mach-omap2/omap4-common.c
index c29dee9..e1f2897 100644
--- a/arch/arm/mach-omap2/omap4-common.c
+++ b/arch/arm/mach-omap2/omap4-common.c
@@ -16,26 +16,25 @@
 #include <linux/io.h>
 #include <linux/platform_device.h>
 #include <linux/memblock.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/export.h>
 
 #include <asm/hardware/gic.h>
 #include <asm/hardware/cache-l2x0.h>
 #include <asm/mach/map.h>
 #include <asm/memblock.h>
-#include <linux/of_irq.h>
-#include <linux/of_platform.h>
 
-#include <plat/irqs.h>
 #include <plat/sram.h>
 #include <plat/omap-secure.h>
 #include <plat/mmc.h>
 
-#include <mach/hardware.h>
-#include <mach/omap-wakeupgen.h>
+#include "omap-wakeupgen.h"
 
+#include "soc.h"
 #include "common.h"
 #include "hsmmc.h"
 #include "omap4-sar-layout.h"
-#include <linux/export.h>
 
 #ifdef CONFIG_CACHE_L2X0
 static void __iomem *l2cache_base;
@@ -171,7 +170,10 @@ static int __init omap_l2_cache_init(void)
 	/* Enable PL310 L2 Cache controller */
 	omap_smc1(0x102, 0x1);
 
-	l2x0_init(l2cache_base, aux_ctrl, L2X0_AUX_CTRL_MASK);
+	if (of_have_populated_dt())
+		l2x0_of_init(aux_ctrl, L2X0_AUX_CTRL_MASK);
+	else
+		l2x0_init(l2cache_base, aux_ctrl, L2X0_AUX_CTRL_MASK);
 
 	/*
 	 * Override default outer_cache.disable with a OMAP4
diff --git a/arch/arm/mach-omap2/omap4-keypad.h b/arch/arm/mach-omap2/omap4-keypad.h
new file mode 100644
index 0000000..20de0d5
--- /dev/null
+++ b/arch/arm/mach-omap2/omap4-keypad.h
@@ -0,0 +1,8 @@
+#ifndef ARCH_ARM_PLAT_OMAP4_KEYPAD_H
+#define ARCH_ARM_PLAT_OMAP4_KEYPAD_H
+
+struct omap_board_data;
+
+extern int omap4_keyboard_init(struct omap4_keypad_platform_data *,
+				struct omap_board_data *);
+#endif
diff --git a/arch/arm/mach-omap2/omap44xx.h b/arch/arm/mach-omap2/omap44xx.h
new file mode 100644
index 0000000..43b927b
--- /dev/null
+++ b/arch/arm/mach-omap2/omap44xx.h
@@ -0,0 +1,62 @@
+/*:
+ * Address mappings and base address for OMAP4 interconnects
+ * and peripherals.
+ *
+ * Copyright (C) 2009 Texas Instruments
+ *
+ * Author: Santosh Shilimkar <santosh.shilimkar@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.
+ */
+#ifndef __ASM_ARCH_OMAP44XX_H
+#define __ASM_ARCH_OMAP44XX_H
+
+/*
+ * Please place only base defines here and put the rest in device
+ * specific headers.
+ */
+#define L4_44XX_BASE			0x4a000000
+#define L4_WK_44XX_BASE			0x4a300000
+#define L4_PER_44XX_BASE		0x48000000
+#define L4_EMU_44XX_BASE		0x54000000
+#define L3_44XX_BASE			0x44000000
+#define OMAP44XX_EMIF1_BASE		0x4c000000
+#define OMAP44XX_EMIF2_BASE		0x4d000000
+#define OMAP44XX_DMM_BASE		0x4e000000
+#define OMAP4430_32KSYNCT_BASE		0x4a304000
+#define OMAP4430_CM1_BASE		0x4a004000
+#define OMAP4430_CM_BASE		OMAP4430_CM1_BASE
+#define OMAP4430_CM2_BASE		0x4a008000
+#define OMAP4430_PRM_BASE		0x4a306000
+#define OMAP4430_PRCM_MPU_BASE		0x48243000
+#define OMAP44XX_GPMC_BASE		0x50000000
+#define OMAP443X_SCM_BASE		0x4a002000
+#define OMAP443X_CTRL_BASE		0x4a100000
+#define OMAP44XX_IC_BASE		0x48200000
+#define OMAP44XX_IVA_INTC_BASE		0x40000000
+#define IRQ_SIR_IRQ			0x0040
+#define OMAP44XX_GIC_DIST_BASE		0x48241000
+#define OMAP44XX_GIC_CPU_BASE		0x48240100
+#define OMAP44XX_IRQ_GIC_START		32
+#define OMAP44XX_SCU_BASE		0x48240000
+#define OMAP44XX_LOCAL_TWD_BASE		0x48240600
+#define OMAP44XX_L2CACHE_BASE		0x48242000
+#define OMAP44XX_WKUPGEN_BASE		0x48281000
+#define OMAP44XX_MCPDM_BASE		0x40132000
+#define OMAP44XX_SAR_RAM_BASE		0x4a326000
+
+#define OMAP44XX_MAILBOX_BASE		(L4_44XX_BASE + 0xF4000)
+#define OMAP44XX_HSUSB_OTG_BASE		(L4_44XX_BASE + 0xAB000)
+
+#define OMAP4_MMU1_BASE			0x55082000
+#define OMAP4_MMU2_BASE			0x4A066000
+
+#define OMAP44XX_USBTLL_BASE		(L4_44XX_BASE + 0x62000)
+#define OMAP44XX_UHH_CONFIG_BASE	(L4_44XX_BASE + 0x64000)
+#define OMAP44XX_HSUSB_OHCI_BASE	(L4_44XX_BASE + 0x64800)
+#define OMAP44XX_HSUSB_EHCI_BASE	(L4_44XX_BASE + 0x64C00)
+
+#endif /* __ASM_ARCH_OMAP44XX_H */
+
diff --git a/arch/arm/mach-omap2/omap54xx.h b/arch/arm/mach-omap2/omap54xx.h
new file mode 100644
index 0000000..a2582bb
--- /dev/null
+++ b/arch/arm/mach-omap2/omap54xx.h
@@ -0,0 +1,32 @@
+/*:
+ * Address mappings and base address for OMAP5 interconnects
+ * and peripherals.
+ *
+ * Copyright (C) 2012 Texas Instruments
+ *	Santosh Shilimkar <santosh.shilimkar@ti.com>
+ *	Sricharan <r.sricharan@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.
+ */
+#ifndef __ASM_SOC_OMAP54XX_H
+#define __ASM_SOC_OMAP54XX_H
+
+/*
+ * Please place only base defines here and put the rest in device
+ * specific headers.
+ */
+#define L4_54XX_BASE			0x4a000000
+#define L4_WK_54XX_BASE			0x4ae00000
+#define L4_PER_54XX_BASE		0x48000000
+#define L3_54XX_BASE			0x44000000
+#define OMAP54XX_32KSYNCT_BASE		0x4ae04000
+#define OMAP54XX_CM_CORE_AON_BASE	0x4a004000
+#define OMAP54XX_CM_CORE_BASE		0x4a008000
+#define OMAP54XX_PRM_BASE		0x4ae06000
+#define OMAP54XX_PRCM_MPU_BASE		0x48243000
+#define OMAP54XX_SCM_BASE		0x4a002000
+#define OMAP54XX_CTRL_BASE		0x4a002800
+
+#endif /* __ASM_SOC_OMAP555554XX_H */
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index 37afbd1..00c0066 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -139,18 +139,20 @@
 #include <linux/slab.h>
 #include <linux/bootmem.h>
 
-#include "common.h"
-#include <plat/cpu.h>
-#include "clockdomain.h"
-#include "powerdomain.h"
 #include <plat/clock.h>
 #include <plat/omap_hwmod.h>
 #include <plat/prcm.h>
 
+#include "soc.h"
+#include "common.h"
+#include "clockdomain.h"
+#include "powerdomain.h"
 #include "cm2xxx_3xxx.h"
 #include "cminst44xx.h"
+#include "cm33xx.h"
 #include "prm2xxx_3xxx.h"
 #include "prm44xx.h"
+#include "prm33xx.h"
 #include "prminst44xx.h"
 #include "mux.h"
 #include "pm.h"
@@ -868,6 +870,26 @@ static void _omap4_enable_module(struct omap_hwmod *oh)
 }
 
 /**
+ * _am33xx_enable_module - enable CLKCTRL modulemode on AM33XX
+ * @oh: struct omap_hwmod *
+ *
+ * Enables the PRCM module mode related to the hwmod @oh.
+ * No return value.
+ */
+static void _am33xx_enable_module(struct omap_hwmod *oh)
+{
+	if (!oh->clkdm || !oh->prcm.omap4.modulemode)
+		return;
+
+	pr_debug("omap_hwmod: %s: %s: %d\n",
+		 oh->name, __func__, oh->prcm.omap4.modulemode);
+
+	am33xx_cm_module_enable(oh->prcm.omap4.modulemode, oh->clkdm->cm_inst,
+				oh->clkdm->clkdm_offs,
+				oh->prcm.omap4.clkctrl_offs);
+}
+
+/**
  * _omap4_wait_target_disable - wait for a module to be disabled on OMAP4
  * @oh: struct omap_hwmod *
  *
@@ -894,6 +916,31 @@ static int _omap4_wait_target_disable(struct omap_hwmod *oh)
 }
 
 /**
+ * _am33xx_wait_target_disable - wait for a module to be disabled on AM33XX
+ * @oh: struct omap_hwmod *
+ *
+ * Wait for a module @oh to enter slave idle.  Returns 0 if the module
+ * does not have an IDLEST bit or if the module successfully enters
+ * slave idle; otherwise, pass along the return value of the
+ * appropriate *_cm*_wait_module_idle() function.
+ */
+static int _am33xx_wait_target_disable(struct omap_hwmod *oh)
+{
+	if (!oh)
+		return -EINVAL;
+
+	if (oh->_int_flags & _HWMOD_NO_MPU_PORT)
+		return 0;
+
+	if (oh->flags & HWMOD_NO_IDLEST)
+		return 0;
+
+	return am33xx_cm_wait_module_idle(oh->clkdm->cm_inst,
+					     oh->clkdm->clkdm_offs,
+					     oh->prcm.omap4.clkctrl_offs);
+}
+
+/**
  * _count_mpu_irqs - count the number of MPU IRQ lines associated with @oh
  * @oh: struct omap_hwmod *oh
  *
@@ -1438,8 +1485,8 @@ static int _init_clocks(struct omap_hwmod *oh, void *data)
  * Return the bit position of the reset line that match the
  * input name. Return -ENOENT if not found.
  */
-static u8 _lookup_hardreset(struct omap_hwmod *oh, const char *name,
-			    struct omap_hwmod_rst_info *ohri)
+static int _lookup_hardreset(struct omap_hwmod *oh, const char *name,
+			     struct omap_hwmod_rst_info *ohri)
 {
 	int i;
 
@@ -1475,7 +1522,7 @@ static u8 _lookup_hardreset(struct omap_hwmod *oh, const char *name,
 static int _assert_hardreset(struct omap_hwmod *oh, const char *name)
 {
 	struct omap_hwmod_rst_info ohri;
-	u8 ret = -EINVAL;
+	int ret = -EINVAL;
 
 	if (!oh)
 		return -EINVAL;
@@ -1484,7 +1531,7 @@ static int _assert_hardreset(struct omap_hwmod *oh, const char *name)
 		return -ENOSYS;
 
 	ret = _lookup_hardreset(oh, name, &ohri);
-	if (IS_ERR_VALUE(ret))
+	if (ret < 0)
 		return ret;
 
 	ret = soc_ops.assert_hardreset(oh, &ohri);
@@ -1542,7 +1589,7 @@ static int _deassert_hardreset(struct omap_hwmod *oh, const char *name)
 static int _read_hardreset(struct omap_hwmod *oh, const char *name)
 {
 	struct omap_hwmod_rst_info ohri;
-	u8 ret = -EINVAL;
+	int ret = -EINVAL;
 
 	if (!oh)
 		return -EINVAL;
@@ -1551,7 +1598,7 @@ static int _read_hardreset(struct omap_hwmod *oh, const char *name)
 		return -ENOSYS;
 
 	ret = _lookup_hardreset(oh, name, &ohri);
-	if (IS_ERR_VALUE(ret))
+	if (ret < 0)
 		return ret;
 
 	return soc_ops.is_hardreset_asserted(oh, &ohri);
@@ -1614,6 +1661,36 @@ static int _omap4_disable_module(struct omap_hwmod *oh)
 }
 
 /**
+ * _am33xx_disable_module - enable CLKCTRL modulemode on AM33XX
+ * @oh: struct omap_hwmod *
+ *
+ * Disable the PRCM module mode related to the hwmod @oh.
+ * Return EINVAL if the modulemode is not supported and 0 in case of success.
+ */
+static int _am33xx_disable_module(struct omap_hwmod *oh)
+{
+	int v;
+
+	if (!oh->clkdm || !oh->prcm.omap4.modulemode)
+		return -EINVAL;
+
+	pr_debug("omap_hwmod: %s: %s\n", oh->name, __func__);
+
+	am33xx_cm_module_disable(oh->clkdm->cm_inst, oh->clkdm->clkdm_offs,
+				 oh->prcm.omap4.clkctrl_offs);
+
+	if (_are_any_hardreset_lines_asserted(oh))
+		return 0;
+
+	v = _am33xx_wait_target_disable(oh);
+	if (v)
+		pr_warn("omap_hwmod: %s: _wait_target_disable failed\n",
+			oh->name);
+
+	return 0;
+}
+
+/**
  * _ocp_softreset - reset an omap_hwmod via the OCP_SYSCONFIG bit
  * @oh: struct omap_hwmod *
  *
@@ -1641,8 +1718,8 @@ static int _ocp_softreset(struct omap_hwmod *oh)
 
 	/* clocks must be on for this operation */
 	if (oh->_state != _HWMOD_STATE_ENABLED) {
-		pr_warning("omap_hwmod: %s: reset can only be entered from "
-			   "enabled state\n", oh->name);
+		pr_warn("omap_hwmod: %s: reset can only be entered from enabled state\n",
+			oh->name);
 		return -EINVAL;
 	}
 
@@ -2549,6 +2626,33 @@ static int _omap4_wait_target_ready(struct omap_hwmod *oh)
 }
 
 /**
+ * _am33xx_wait_target_ready - wait for a module to leave slave idle
+ * @oh: struct omap_hwmod *
+ *
+ * Wait for a module @oh to leave slave idle.  Returns 0 if the module
+ * does not have an IDLEST bit or if the module successfully leaves
+ * slave idle; otherwise, pass along the return value of the
+ * appropriate *_cm*_wait_module_ready() function.
+ */
+static int _am33xx_wait_target_ready(struct omap_hwmod *oh)
+{
+	if (!oh || !oh->clkdm)
+		return -EINVAL;
+
+	if (oh->flags & HWMOD_NO_IDLEST)
+		return 0;
+
+	if (!_find_mpu_rt_port(oh))
+		return 0;
+
+	/* XXX check module SIDLEMODE, hardreset status */
+
+	return am33xx_cm_wait_module_ready(oh->clkdm->cm_inst,
+					      oh->clkdm->clkdm_offs,
+					      oh->prcm.omap4.clkctrl_offs);
+}
+
+/**
  * _omap2_assert_hardreset - call OMAP2 PRM hardreset fn with hwmod args
  * @oh: struct omap_hwmod * to assert hardreset
  * @ohri: hardreset line data
@@ -2679,6 +2783,72 @@ static int _omap4_is_hardreset_asserted(struct omap_hwmod *oh,
 				oh->prcm.omap4.rstctrl_offs);
 }
 
+/**
+ * _am33xx_assert_hardreset - call AM33XX PRM hardreset fn with hwmod args
+ * @oh: struct omap_hwmod * to assert hardreset
+ * @ohri: hardreset line data
+ *
+ * Call am33xx_prminst_assert_hardreset() with parameters extracted
+ * from the hwmod @oh and the hardreset line data @ohri.  Only
+ * intended for use as an soc_ops function pointer.  Passes along the
+ * return value from am33xx_prminst_assert_hardreset().  XXX This
+ * function is scheduled for removal when the PRM code is moved into
+ * drivers/.
+ */
+static int _am33xx_assert_hardreset(struct omap_hwmod *oh,
+				   struct omap_hwmod_rst_info *ohri)
+
+{
+	return am33xx_prm_assert_hardreset(ohri->rst_shift,
+				oh->clkdm->pwrdm.ptr->prcm_offs,
+				oh->prcm.omap4.rstctrl_offs);
+}
+
+/**
+ * _am33xx_deassert_hardreset - call AM33XX PRM hardreset fn with hwmod args
+ * @oh: struct omap_hwmod * to deassert hardreset
+ * @ohri: hardreset line data
+ *
+ * Call am33xx_prminst_deassert_hardreset() with parameters extracted
+ * from the hwmod @oh and the hardreset line data @ohri.  Only
+ * intended for use as an soc_ops function pointer.  Passes along the
+ * return value from am33xx_prminst_deassert_hardreset().  XXX This
+ * function is scheduled for removal when the PRM code is moved into
+ * drivers/.
+ */
+static int _am33xx_deassert_hardreset(struct omap_hwmod *oh,
+				     struct omap_hwmod_rst_info *ohri)
+{
+	if (ohri->st_shift)
+		pr_err("omap_hwmod: %s: %s: hwmod data error: OMAP4 does not support st_shift\n",
+		       oh->name, ohri->name);
+
+	return am33xx_prm_deassert_hardreset(ohri->rst_shift,
+				oh->clkdm->pwrdm.ptr->prcm_offs,
+				oh->prcm.omap4.rstctrl_offs,
+				oh->prcm.omap4.rstst_offs);
+}
+
+/**
+ * _am33xx_is_hardreset_asserted - call AM33XX PRM hardreset fn with hwmod args
+ * @oh: struct omap_hwmod * to test hardreset
+ * @ohri: hardreset line data
+ *
+ * Call am33xx_prminst_is_hardreset_asserted() with parameters
+ * extracted from the hwmod @oh and the hardreset line data @ohri.
+ * Only intended for use as an soc_ops function pointer.  Passes along
+ * the return value from am33xx_prminst_is_hardreset_asserted().  XXX
+ * This function is scheduled for removal when the PRM code is moved
+ * into drivers/.
+ */
+static int _am33xx_is_hardreset_asserted(struct omap_hwmod *oh,
+					struct omap_hwmod_rst_info *ohri)
+{
+	return am33xx_prm_is_hardreset_asserted(ohri->rst_shift,
+				oh->clkdm->pwrdm.ptr->prcm_offs,
+				oh->prcm.omap4.rstctrl_offs);
+}
+
 /* Public functions */
 
 u32 omap_hwmod_read(struct omap_hwmod *oh, u16 reg_offs)
@@ -3159,6 +3329,33 @@ int omap_hwmod_fill_resources(struct omap_hwmod *oh, struct resource *res)
 }
 
 /**
+ * omap_hwmod_fill_dma_resources - fill struct resource array with dma data
+ * @oh: struct omap_hwmod *
+ * @res: pointer to the array of struct resource to fill
+ *
+ * Fill the struct resource array @res with dma resource data from the
+ * omap_hwmod @oh.  Intended to be called by code that registers
+ * omap_devices.  See also omap_hwmod_count_resources().  Returns the
+ * number of array elements filled.
+ */
+int omap_hwmod_fill_dma_resources(struct omap_hwmod *oh, struct resource *res)
+{
+	int i, sdma_reqs_cnt;
+	int r = 0;
+
+	sdma_reqs_cnt = _count_sdma_reqs(oh);
+	for (i = 0; i < sdma_reqs_cnt; i++) {
+		(res + r)->name = (oh->sdma_reqs + i)->name;
+		(res + r)->start = (oh->sdma_reqs + i)->dma_req;
+		(res + r)->end = (oh->sdma_reqs + i)->dma_req;
+		(res + r)->flags = IORESOURCE_DMA;
+		r++;
+	}
+
+	return r;
+}
+
+/**
  * omap_hwmod_get_resource_byname - fetch IP block integration data by name
  * @oh: struct omap_hwmod * to operate on
  * @type: one of the IORESOURCE_* constants from include/linux/ioport.h
@@ -3678,6 +3875,14 @@ void __init omap_hwmod_init(void)
 		soc_ops.deassert_hardreset = _omap4_deassert_hardreset;
 		soc_ops.is_hardreset_asserted = _omap4_is_hardreset_asserted;
 		soc_ops.init_clkdm = _init_clkdm;
+	} else if (soc_is_am33xx()) {
+		soc_ops.enable_module = _am33xx_enable_module;
+		soc_ops.disable_module = _am33xx_disable_module;
+		soc_ops.wait_target_ready = _am33xx_wait_target_ready;
+		soc_ops.assert_hardreset = _am33xx_assert_hardreset;
+		soc_ops.deassert_hardreset = _am33xx_deassert_hardreset;
+		soc_ops.is_hardreset_asserted = _am33xx_is_hardreset_asserted;
+		soc_ops.init_clkdm = _init_clkdm;
 	} else {
 		WARN(1, "omap_hwmod: unknown SoC type\n");
 	}
diff --git a/arch/arm/mach-omap2/omap_hwmod_2420_data.c b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
index 50cfab6..10575a1 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2420_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
@@ -12,17 +12,15 @@
  * XXX handle crossbar/shared link difference for L3?
  * XXX these should be marked initdata for multi-OMAP kernels
  */
+#include <linux/platform_data/spi-omap2-mcspi.h>
+
 #include <plat/omap_hwmod.h>
-#include <mach/irqs.h>
-#include <plat/cpu.h>
 #include <plat/dma.h>
 #include <plat/serial.h>
 #include <plat/i2c.h>
-#include <plat/gpio.h>
-#include <plat/mcspi.h>
 #include <plat/dmtimer.h>
-#include <plat/l3_2xxx.h>
-#include <plat/l4_2xxx.h>
+#include "l3_2xxx.h"
+#include "l4_2xxx.h"
 #include <plat/mmc.h>
 
 #include "omap_hwmod_common_data.h"
@@ -162,9 +160,9 @@ static struct omap_hwmod omap2420_dma_system_hwmod = {
 
 /* mailbox */
 static struct omap_hwmod_irq_info omap2420_mailbox_irqs[] = {
-	{ .name = "dsp", .irq = 26 },
-	{ .name = "iva", .irq = 34 },
-	{ .irq = -1 }
+	{ .name = "dsp", .irq = 26 + OMAP_INTC_START, },
+	{ .name = "iva", .irq = 34 + OMAP_INTC_START, },
+	{ .irq = -1 },
 };
 
 static struct omap_hwmod omap2420_mailbox_hwmod = {
@@ -199,9 +197,9 @@ static struct omap_hwmod_opt_clk mcbsp_opt_clks[] = {
 
 /* mcbsp1 */
 static struct omap_hwmod_irq_info omap2420_mcbsp1_irqs[] = {
-	{ .name = "tx", .irq = 59 },
-	{ .name = "rx", .irq = 60 },
-	{ .irq = -1 }
+	{ .name = "tx", .irq = 59 + OMAP_INTC_START, },
+	{ .name = "rx", .irq = 60 + OMAP_INTC_START, },
+	{ .irq = -1 },
 };
 
 static struct omap_hwmod omap2420_mcbsp1_hwmod = {
@@ -225,9 +223,9 @@ static struct omap_hwmod omap2420_mcbsp1_hwmod = {
 
 /* mcbsp2 */
 static struct omap_hwmod_irq_info omap2420_mcbsp2_irqs[] = {
-	{ .name = "tx", .irq = 62 },
-	{ .name = "rx", .irq = 63 },
-	{ .irq = -1 }
+	{ .name = "tx", .irq = 62 + OMAP_INTC_START, },
+	{ .name = "rx", .irq = 63 + OMAP_INTC_START, },
+	{ .irq = -1 },
 };
 
 static struct omap_hwmod omap2420_mcbsp2_hwmod = {
@@ -265,8 +263,8 @@ static struct omap_hwmod_class omap2420_msdi_hwmod_class = {
 
 /* msdi1 */
 static struct omap_hwmod_irq_info omap2420_msdi1_irqs[] = {
-	{ .irq = 83 },
-	{ .irq = -1 }
+	{ .irq = 83 + OMAP_INTC_START, },
+	{ .irq = -1 },
 };
 
 static struct omap_hwmod_dma_info omap2420_msdi1_sdma_reqs[] = {
diff --git a/arch/arm/mach-omap2/omap_hwmod_2430_data.c b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
index 58b5bc1..60de70f 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
@@ -12,21 +12,19 @@
  * XXX handle crossbar/shared link difference for L3?
  * XXX these should be marked initdata for multi-OMAP kernels
  */
+#include <linux/platform_data/asoc-ti-mcbsp.h>
+#include <linux/platform_data/spi-omap2-mcspi.h>
+
 #include <plat/omap_hwmod.h>
-#include <mach/irqs.h>
-#include <plat/cpu.h>
 #include <plat/dma.h>
 #include <plat/serial.h>
 #include <plat/i2c.h>
-#include <plat/gpio.h>
-#include <plat/mcbsp.h>
-#include <plat/mcspi.h>
 #include <plat/dmtimer.h>
 #include <plat/mmc.h>
-#include <plat/l3_2xxx.h>
+#include "l3_2xxx.h"
 
+#include "soc.h"
 #include "omap_hwmod_common_data.h"
-
 #include "prm-regbits-24xx.h"
 #include "cm-regbits-24xx.h"
 #include "wd_timer.h"
@@ -133,8 +131,8 @@ static struct omap_hwmod omap2430_i2c2_hwmod = {
 
 /* gpio5 */
 static struct omap_hwmod_irq_info omap243x_gpio5_irqs[] = {
-	{ .irq = 33 }, /* INT_24XX_GPIO_BANK5 */
-	{ .irq = -1 }
+	{ .irq = 33 + OMAP_INTC_START, }, /* INT_24XX_GPIO_BANK5 */
+	{ .irq = -1 },
 };
 
 static struct omap_hwmod omap2430_gpio5_hwmod = {
@@ -173,8 +171,8 @@ static struct omap_hwmod omap2430_dma_system_hwmod = {
 
 /* mailbox */
 static struct omap_hwmod_irq_info omap2430_mailbox_irqs[] = {
-	{ .irq = 26 },
-	{ .irq = -1 }
+	{ .irq = 26 + OMAP_INTC_START, },
+	{ .irq = -1 },
 };
 
 static struct omap_hwmod omap2430_mailbox_hwmod = {
@@ -195,8 +193,8 @@ static struct omap_hwmod omap2430_mailbox_hwmod = {
 
 /* mcspi3 */
 static struct omap_hwmod_irq_info omap2430_mcspi3_mpu_irqs[] = {
-	{ .irq = 91 },
-	{ .irq = -1 }
+	{ .irq = 91 + OMAP_INTC_START, },
+	{ .irq = -1 },
 };
 
 static struct omap_hwmod_dma_info omap2430_mcspi3_sdma_reqs[] = {
@@ -250,9 +248,9 @@ static struct omap_hwmod_class usbotg_class = {
 /* usb_otg_hs */
 static struct omap_hwmod_irq_info omap2430_usbhsotg_mpu_irqs[] = {
 
-	{ .name = "mc", .irq = 92 },
-	{ .name = "dma", .irq = 93 },
-	{ .irq = -1 }
+	{ .name = "mc", .irq = 92 + OMAP_INTC_START, },
+	{ .name = "dma", .irq = 93 + OMAP_INTC_START, },
+	{ .irq = -1 },
 };
 
 static struct omap_hwmod omap2430_usbhsotg_hwmod = {
@@ -303,11 +301,11 @@ static struct omap_hwmod_opt_clk mcbsp_opt_clks[] = {
 
 /* mcbsp1 */
 static struct omap_hwmod_irq_info omap2430_mcbsp1_irqs[] = {
-	{ .name = "tx",		.irq = 59 },
-	{ .name = "rx",		.irq = 60 },
-	{ .name = "ovr",	.irq = 61 },
-	{ .name = "common",	.irq = 64 },
-	{ .irq = -1 }
+	{ .name = "tx",		.irq = 59 + OMAP_INTC_START, },
+	{ .name = "rx",		.irq = 60 + OMAP_INTC_START, },
+	{ .name = "ovr",	.irq = 61 + OMAP_INTC_START, },
+	{ .name = "common",	.irq = 64 + OMAP_INTC_START, },
+	{ .irq = -1 },
 };
 
 static struct omap_hwmod omap2430_mcbsp1_hwmod = {
@@ -331,10 +329,10 @@ static struct omap_hwmod omap2430_mcbsp1_hwmod = {
 
 /* mcbsp2 */
 static struct omap_hwmod_irq_info omap2430_mcbsp2_irqs[] = {
-	{ .name = "tx",		.irq = 62 },
-	{ .name = "rx",		.irq = 63 },
-	{ .name = "common",	.irq = 16 },
-	{ .irq = -1 }
+	{ .name = "tx",		.irq = 62 + OMAP_INTC_START, },
+	{ .name = "rx",		.irq = 63 + OMAP_INTC_START, },
+	{ .name = "common",	.irq = 16 + OMAP_INTC_START, },
+	{ .irq = -1 },
 };
 
 static struct omap_hwmod omap2430_mcbsp2_hwmod = {
@@ -358,10 +356,10 @@ static struct omap_hwmod omap2430_mcbsp2_hwmod = {
 
 /* mcbsp3 */
 static struct omap_hwmod_irq_info omap2430_mcbsp3_irqs[] = {
-	{ .name = "tx",		.irq = 89 },
-	{ .name = "rx",		.irq = 90 },
-	{ .name = "common",	.irq = 17 },
-	{ .irq = -1 }
+	{ .name = "tx",		.irq = 89 + OMAP_INTC_START, },
+	{ .name = "rx",		.irq = 90 + OMAP_INTC_START, },
+	{ .name = "common",	.irq = 17 + OMAP_INTC_START, },
+	{ .irq = -1 },
 };
 
 static struct omap_hwmod omap2430_mcbsp3_hwmod = {
@@ -385,10 +383,10 @@ static struct omap_hwmod omap2430_mcbsp3_hwmod = {
 
 /* mcbsp4 */
 static struct omap_hwmod_irq_info omap2430_mcbsp4_irqs[] = {
-	{ .name = "tx",		.irq = 54 },
-	{ .name = "rx",		.irq = 55 },
-	{ .name = "common",	.irq = 18 },
-	{ .irq = -1 }
+	{ .name = "tx",		.irq = 54 + OMAP_INTC_START, },
+	{ .name = "rx",		.irq = 55 + OMAP_INTC_START, },
+	{ .name = "common",	.irq = 18 + OMAP_INTC_START, },
+	{ .irq = -1 },
 };
 
 static struct omap_hwmod_dma_info omap2430_mcbsp4_sdma_chs[] = {
@@ -418,10 +416,10 @@ static struct omap_hwmod omap2430_mcbsp4_hwmod = {
 
 /* mcbsp5 */
 static struct omap_hwmod_irq_info omap2430_mcbsp5_irqs[] = {
-	{ .name = "tx",		.irq = 81 },
-	{ .name = "rx",		.irq = 82 },
-	{ .name = "common",	.irq = 19 },
-	{ .irq = -1 }
+	{ .name = "tx",		.irq = 81 + OMAP_INTC_START, },
+	{ .name = "rx",		.irq = 82 + OMAP_INTC_START, },
+	{ .name = "common",	.irq = 19 + OMAP_INTC_START, },
+	{ .irq = -1 },
 };
 
 static struct omap_hwmod_dma_info omap2430_mcbsp5_sdma_chs[] = {
@@ -468,8 +466,8 @@ static struct omap_hwmod_class omap2430_mmc_class = {
 
 /* MMC/SD/SDIO1 */
 static struct omap_hwmod_irq_info omap2430_mmc1_mpu_irqs[] = {
-	{ .irq = 83 },
-	{ .irq = -1 }
+	{ .irq = 83 + OMAP_INTC_START, },
+	{ .irq = -1 },
 };
 
 static struct omap_hwmod_dma_info omap2430_mmc1_sdma_reqs[] = {
@@ -509,8 +507,8 @@ static struct omap_hwmod omap2430_mmc1_hwmod = {
 
 /* MMC/SD/SDIO2 */
 static struct omap_hwmod_irq_info omap2430_mmc2_mpu_irqs[] = {
-	{ .irq = 86 },
-	{ .irq = -1 }
+	{ .irq = 86 + OMAP_INTC_START, },
+	{ .irq = -1 },
 };
 
 static struct omap_hwmod_dma_info omap2430_mmc2_sdma_reqs[] = {
diff --git a/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c b/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c
index 102d76e..8851bbb 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c
@@ -13,9 +13,7 @@
 #include <plat/serial.h>
 #include <plat/dma.h>
 #include <plat/common.h>
-#include <plat/hdq1w.h>
-
-#include <mach/irqs.h>
+#include "hdq1w.h"
 
 #include "omap_hwmod_common_data.h"
 
@@ -182,126 +180,126 @@ struct omap_hwmod_class iva_hwmod_class = {
 /* Common MPU IRQ line data */
 
 struct omap_hwmod_irq_info omap2_timer1_mpu_irqs[] = {
-	{ .irq = 37, },
-	{ .irq = -1 }
+	{ .irq = 37 + OMAP_INTC_START, },
+	{ .irq = -1 },
 };
 
 struct omap_hwmod_irq_info omap2_timer2_mpu_irqs[] = {
-	{ .irq = 38, },
-	{ .irq = -1 }
+	{ .irq = 38 + OMAP_INTC_START, },
+	{ .irq = -1 },
 };
 
 struct omap_hwmod_irq_info omap2_timer3_mpu_irqs[] = {
-	{ .irq = 39, },
-	{ .irq = -1 }
+	{ .irq = 39 + OMAP_INTC_START, },
+	{ .irq = -1 },
 };
 
 struct omap_hwmod_irq_info omap2_timer4_mpu_irqs[] = {
-	{ .irq = 40, },
-	{ .irq = -1 }
+	{ .irq = 40 + OMAP_INTC_START, },
+	{ .irq = -1 },
 };
 
 struct omap_hwmod_irq_info omap2_timer5_mpu_irqs[] = {
-	{ .irq = 41, },
-	{ .irq = -1 }
+	{ .irq = 41 + OMAP_INTC_START, },
+	{ .irq = -1 },
 };
 
 struct omap_hwmod_irq_info omap2_timer6_mpu_irqs[] = {
-	{ .irq = 42, },
-	{ .irq = -1 }
+	{ .irq = 42 + OMAP_INTC_START, },
+	{ .irq = -1 },
 };
 
 struct omap_hwmod_irq_info omap2_timer7_mpu_irqs[] = {
-	{ .irq = 43, },
-	{ .irq = -1 }
+	{ .irq = 43 + OMAP_INTC_START, },
+	{ .irq = -1 },
 };
 
 struct omap_hwmod_irq_info omap2_timer8_mpu_irqs[] = {
-	{ .irq = 44, },
-	{ .irq = -1 }
+	{ .irq = 44 + OMAP_INTC_START, },
+	{ .irq = -1 },
 };
 
 struct omap_hwmod_irq_info omap2_timer9_mpu_irqs[] = {
-	{ .irq = 45, },
-	{ .irq = -1 }
+	{ .irq = 45 + OMAP_INTC_START, },
+	{ .irq = -1 },
 };
 
 struct omap_hwmod_irq_info omap2_timer10_mpu_irqs[] = {
-	{ .irq = 46, },
-	{ .irq = -1 }
+	{ .irq = 46 + OMAP_INTC_START, },
+	{ .irq = -1 },
 };
 
 struct omap_hwmod_irq_info omap2_timer11_mpu_irqs[] = {
-	{ .irq = 47, },
-	{ .irq = -1 }
+	{ .irq = 47 + OMAP_INTC_START, },
+	{ .irq = -1 },
 };
 
 struct omap_hwmod_irq_info omap2_uart1_mpu_irqs[] = {
-	{ .irq = INT_24XX_UART1_IRQ, },
-	{ .irq = -1 }
+	{ .irq = 72 + OMAP_INTC_START, },
+	{ .irq = -1 },
 };
 
 struct omap_hwmod_irq_info omap2_uart2_mpu_irqs[] = {
-	{ .irq = INT_24XX_UART2_IRQ, },
-	{ .irq = -1 }
+	{ .irq = 73 + OMAP_INTC_START, },
+	{ .irq = -1 },
 };
 
 struct omap_hwmod_irq_info omap2_uart3_mpu_irqs[] = {
-	{ .irq = INT_24XX_UART3_IRQ, },
-	{ .irq = -1 }
+	{ .irq = 74 + OMAP_INTC_START, },
+	{ .irq = -1 },
 };
 
 struct omap_hwmod_irq_info omap2_dispc_irqs[] = {
-	{ .irq = 25 },
-	{ .irq = -1 }
+	{ .irq = 25 + OMAP_INTC_START, },
+	{ .irq = -1 },
 };
 
 struct omap_hwmod_irq_info omap2_i2c1_mpu_irqs[] = {
-	{ .irq = INT_24XX_I2C1_IRQ, },
-	{ .irq = -1 }
+	{ .irq = 56 + OMAP_INTC_START, },
+	{ .irq = -1 },
 };
 
 struct omap_hwmod_irq_info omap2_i2c2_mpu_irqs[] = {
-	{ .irq = INT_24XX_I2C2_IRQ, },
-	{ .irq = -1 }
+	{ .irq = 57 + OMAP_INTC_START, },
+	{ .irq = -1 },
 };
 
 struct omap_hwmod_irq_info omap2_gpio1_irqs[] = {
-	{ .irq = 29 }, /* INT_24XX_GPIO_BANK1 */
-	{ .irq = -1 }
+	{ .irq = 29 + OMAP_INTC_START, }, /* INT_24XX_GPIO_BANK1 */
+	{ .irq = -1 },
 };
 
 struct omap_hwmod_irq_info omap2_gpio2_irqs[] = {
-	{ .irq = 30 }, /* INT_24XX_GPIO_BANK2 */
-	{ .irq = -1 }
+	{ .irq = 30 + OMAP_INTC_START, }, /* INT_24XX_GPIO_BANK2 */
+	{ .irq = -1 },
 };
 
 struct omap_hwmod_irq_info omap2_gpio3_irqs[] = {
-	{ .irq = 31 }, /* INT_24XX_GPIO_BANK3 */
-	{ .irq = -1 }
+	{ .irq = 31 + OMAP_INTC_START, }, /* INT_24XX_GPIO_BANK3 */
+	{ .irq = -1 },
 };
 
 struct omap_hwmod_irq_info omap2_gpio4_irqs[] = {
-	{ .irq = 32 }, /* INT_24XX_GPIO_BANK4 */
-	{ .irq = -1 }
+	{ .irq = 32 + OMAP_INTC_START, }, /* INT_24XX_GPIO_BANK4 */
+	{ .irq = -1 },
 };
 
 struct omap_hwmod_irq_info omap2_dma_system_irqs[] = {
-	{ .name = "0", .irq = 12 }, /* INT_24XX_SDMA_IRQ0 */
-	{ .name = "1", .irq = 13 }, /* INT_24XX_SDMA_IRQ1 */
-	{ .name = "2", .irq = 14 }, /* INT_24XX_SDMA_IRQ2 */
-	{ .name = "3", .irq = 15 }, /* INT_24XX_SDMA_IRQ3 */
-	{ .irq = -1 }
+	{ .name = "0", .irq = 12 + OMAP_INTC_START, }, /* INT_24XX_SDMA_IRQ0 */
+	{ .name = "1", .irq = 13 + OMAP_INTC_START, }, /* INT_24XX_SDMA_IRQ1 */
+	{ .name = "2", .irq = 14 + OMAP_INTC_START, }, /* INT_24XX_SDMA_IRQ2 */
+	{ .name = "3", .irq = 15 + OMAP_INTC_START, }, /* INT_24XX_SDMA_IRQ3 */
+	{ .irq = -1 },
 };
 
 struct omap_hwmod_irq_info omap2_mcspi1_mpu_irqs[] = {
-	{ .irq = 65 },
-	{ .irq = -1 }
+	{ .irq = 65 + OMAP_INTC_START, },
+	{ .irq = -1 },
 };
 
 struct omap_hwmod_irq_info omap2_mcspi2_mpu_irqs[] = {
-	{ .irq = 66 },
-	{ .irq = -1 }
+	{ .irq = 66 + OMAP_INTC_START, },
+	{ .irq = -1 },
 };
 
 struct omap_hwmod_class_sysconfig omap2_hdq1w_sysc = {
@@ -320,7 +318,7 @@ struct omap_hwmod_class omap2_hdq1w_class = {
 };
 
 struct omap_hwmod_irq_info omap2_hdq1w_mpu_irqs[] = {
-	{ .irq = 58, },
-	{ .irq = -1 }
+	{ .irq = 58 + OMAP_INTC_START, },
+	{ .irq = -1 },
 };
 
diff --git a/arch/arm/mach-omap2/omap_hwmod_2xxx_interconnect_data.c b/arch/arm/mach-omap2/omap_hwmod_2xxx_interconnect_data.c
index 5178e40..f853a0b 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2xxx_interconnect_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_interconnect_data.c
@@ -15,8 +15,8 @@
 
 #include <plat/omap_hwmod.h>
 #include <plat/serial.h>
-#include <plat/l3_2xxx.h>
-#include <plat/l4_2xxx.h>
+#include "l3_2xxx.h"
+#include "l4_2xxx.h"
 
 #include "omap_hwmod_common_data.h"
 
diff --git a/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c b/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
index afad69c..feeb401 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
@@ -10,12 +10,10 @@
  */
 #include <plat/omap_hwmod.h>
 #include <plat/serial.h>
-#include <plat/gpio.h>
+#include <linux/platform_data/gpio-omap.h>
 #include <plat/dma.h>
 #include <plat/dmtimer.h>
-#include <plat/mcspi.h>
-
-#include <mach/irqs.h>
+#include <linux/platform_data/spi-omap2-mcspi.h>
 
 #include "omap_hwmod_common_data.h"
 #include "cm-regbits-24xx.h"
@@ -23,8 +21,8 @@
 #include "wd_timer.h"
 
 struct omap_hwmod_irq_info omap2xxx_timer12_mpu_irqs[] = {
-	{ .irq = 48, },
-	{ .irq = -1 }
+	{ .irq = 48 + OMAP_INTC_START, },
+	{ .irq = -1 },
 };
 
 struct omap_hwmod_dma_info omap2xxx_dss_sdma_chs[] = {
diff --git a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
new file mode 100644
index 0000000..59d5c1c
--- /dev/null
+++ b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
@@ -0,0 +1,3381 @@
+/*
+ * omap_hwmod_33xx_data.c: Hardware modules present on the AM33XX chips
+ *
+ * Copyright (C) {2012} Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This file is automatically generated from the AM33XX hardware databases.
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <plat/omap_hwmod.h>
+#include <plat/cpu.h>
+#include <linux/platform_data/gpio-omap.h>
+#include <linux/platform_data/spi-omap2-mcspi.h>
+#include <plat/dma.h>
+#include <plat/mmc.h>
+#include <plat/i2c.h>
+
+#include "omap_hwmod_common_data.h"
+
+#include "control.h"
+#include "cm33xx.h"
+#include "prm33xx.h"
+#include "prm-regbits-33xx.h"
+
+/*
+ * IP blocks
+ */
+
+/*
+ * 'emif_fw' class
+ * instance(s): emif_fw
+ */
+static struct omap_hwmod_class am33xx_emif_fw_hwmod_class = {
+	.name		= "emif_fw",
+};
+
+/* emif_fw */
+static struct omap_hwmod am33xx_emif_fw_hwmod = {
+	.name		= "emif_fw",
+	.class		= &am33xx_emif_fw_hwmod_class,
+	.clkdm_name	= "l4fw_clkdm",
+	.main_clk	= "l4fw_gclk",
+	.flags		= (HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET),
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_PER_EMIF_FW_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/*
+ * 'emif' class
+ * instance(s): emif
+ */
+static struct omap_hwmod_class_sysconfig am33xx_emif_sysc = {
+	.rev_offs	= 0x0000,
+};
+
+static struct omap_hwmod_class am33xx_emif_hwmod_class = {
+	.name		= "emif",
+	.sysc		= &am33xx_emif_sysc,
+};
+
+static struct omap_hwmod_irq_info am33xx_emif_irqs[] = {
+	{ .name = "ddrerr0", .irq = 101 + OMAP_INTC_START, },
+	{ .irq = -1 },
+};
+
+/* emif */
+static struct omap_hwmod am33xx_emif_hwmod = {
+	.name		= "emif",
+	.class		= &am33xx_emif_hwmod_class,
+	.clkdm_name	= "l3_clkdm",
+	.flags		= (HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET),
+	.mpu_irqs	= am33xx_emif_irqs,
+	.main_clk	= "dpll_ddr_m2_div2_ck",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_PER_EMIF_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/*
+ * 'l3' class
+ * instance(s): l3_main, l3_s, l3_instr
+ */
+static struct omap_hwmod_class am33xx_l3_hwmod_class = {
+	.name		= "l3",
+};
+
+/* l3_main (l3_fast) */
+static struct omap_hwmod_irq_info am33xx_l3_main_irqs[] = {
+	{ .name = "l3debug", .irq = 9 + OMAP_INTC_START, },
+	{ .name = "l3appint", .irq = 10 + OMAP_INTC_START, },
+	{ .irq = -1 },
+};
+
+static struct omap_hwmod am33xx_l3_main_hwmod = {
+	.name		= "l3_main",
+	.class		= &am33xx_l3_hwmod_class,
+	.clkdm_name	= "l3_clkdm",
+	.flags		= (HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET),
+	.mpu_irqs	= am33xx_l3_main_irqs,
+	.main_clk	= "l3_gclk",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_PER_L3_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/* l3_s */
+static struct omap_hwmod am33xx_l3_s_hwmod = {
+	.name		= "l3_s",
+	.class		= &am33xx_l3_hwmod_class,
+	.clkdm_name	= "l3s_clkdm",
+};
+
+/* l3_instr */
+static struct omap_hwmod am33xx_l3_instr_hwmod = {
+	.name		= "l3_instr",
+	.class		= &am33xx_l3_hwmod_class,
+	.clkdm_name	= "l3_clkdm",
+	.flags		= (HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET),
+	.main_clk	= "l3_gclk",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_PER_L3_INSTR_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/*
+ * 'l4' class
+ * instance(s): l4_ls, l4_hs, l4_wkup, l4_fw
+ */
+static struct omap_hwmod_class am33xx_l4_hwmod_class = {
+	.name		= "l4",
+};
+
+/* l4_ls */
+static struct omap_hwmod am33xx_l4_ls_hwmod = {
+	.name		= "l4_ls",
+	.class		= &am33xx_l4_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.flags		= (HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET),
+	.main_clk	= "l4ls_gclk",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_PER_L4LS_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/* l4_hs */
+static struct omap_hwmod am33xx_l4_hs_hwmod = {
+	.name		= "l4_hs",
+	.class		= &am33xx_l4_hwmod_class,
+	.clkdm_name	= "l4hs_clkdm",
+	.flags		= (HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET),
+	.main_clk	= "l4hs_gclk",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_PER_L4HS_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+
+/* l4_wkup */
+static struct omap_hwmod am33xx_l4_wkup_hwmod = {
+	.name		= "l4_wkup",
+	.class		= &am33xx_l4_hwmod_class,
+	.clkdm_name	= "l4_wkup_clkdm",
+	.flags		= (HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET),
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_WKUP_L4WKUP_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/* l4_fw */
+static struct omap_hwmod am33xx_l4_fw_hwmod = {
+	.name		= "l4_fw",
+	.class		= &am33xx_l4_hwmod_class,
+	.clkdm_name	= "l4fw_clkdm",
+	.flags		= (HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET),
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_PER_L4FW_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/*
+ * 'mpu' class
+ */
+static struct omap_hwmod_class am33xx_mpu_hwmod_class = {
+	.name	= "mpu",
+};
+
+/* mpu */
+static struct omap_hwmod_irq_info am33xx_mpu_irqs[] = {
+	{ .name = "emuint", .irq = 0 + OMAP_INTC_START, },
+	{ .name = "commtx", .irq = 1 + OMAP_INTC_START, },
+	{ .name = "commrx", .irq = 2 + OMAP_INTC_START, },
+	{ .name = "bench", .irq = 3 + OMAP_INTC_START, },
+	{ .irq = -1 },
+};
+
+static struct omap_hwmod am33xx_mpu_hwmod = {
+	.name		= "mpu",
+	.class		= &am33xx_mpu_hwmod_class,
+	.clkdm_name	= "mpu_clkdm",
+	.flags		= (HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET),
+	.mpu_irqs	= am33xx_mpu_irqs,
+	.main_clk	= "dpll_mpu_m2_ck",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_MPU_MPU_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/*
+ * 'wakeup m3' class
+ * Wakeup controller sub-system under wakeup domain
+ */
+static struct omap_hwmod_class am33xx_wkup_m3_hwmod_class = {
+	.name		= "wkup_m3",
+};
+
+static struct omap_hwmod_rst_info am33xx_wkup_m3_resets[] = {
+	{ .name = "wkup_m3", .rst_shift = 3, .st_shift = 5 },
+};
+
+static struct omap_hwmod_irq_info am33xx_wkup_m3_irqs[] = {
+	{ .name = "txev", .irq = 78 + OMAP_INTC_START, },
+	{ .irq = -1 },
+};
+
+/* wkup_m3  */
+static struct omap_hwmod am33xx_wkup_m3_hwmod = {
+	.name		= "wkup_m3",
+	.class		= &am33xx_wkup_m3_hwmod_class,
+	.clkdm_name	= "l4_wkup_aon_clkdm",
+	.flags		= HWMOD_INIT_NO_RESET,	/* Keep hardreset asserted */
+	.mpu_irqs	= am33xx_wkup_m3_irqs,
+	.main_clk	= "dpll_core_m4_div2_ck",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_WKUP_WKUP_M3_CLKCTRL_OFFSET,
+			.rstctrl_offs	= AM33XX_RM_WKUP_RSTCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+	.rst_lines	= am33xx_wkup_m3_resets,
+	.rst_lines_cnt	= ARRAY_SIZE(am33xx_wkup_m3_resets),
+};
+
+/*
+ * 'pru-icss' class
+ * Programmable Real-Time Unit and Industrial Communication Subsystem
+ */
+static struct omap_hwmod_class am33xx_pruss_hwmod_class = {
+	.name	= "pruss",
+};
+
+static struct omap_hwmod_rst_info am33xx_pruss_resets[] = {
+	{ .name = "pruss", .rst_shift = 1 },
+};
+
+static struct omap_hwmod_irq_info am33xx_pruss_irqs[] = {
+	{ .name = "evtout0", .irq = 20 + OMAP_INTC_START, },
+	{ .name = "evtout1", .irq = 21 + OMAP_INTC_START, },
+	{ .name = "evtout2", .irq = 22 + OMAP_INTC_START, },
+	{ .name = "evtout3", .irq = 23 + OMAP_INTC_START, },
+	{ .name = "evtout4", .irq = 24 + OMAP_INTC_START, },
+	{ .name = "evtout5", .irq = 25 + OMAP_INTC_START, },
+	{ .name = "evtout6", .irq = 26 + OMAP_INTC_START, },
+	{ .name = "evtout7", .irq = 27 + OMAP_INTC_START, },
+	{ .irq = -1 },
+};
+
+/* pru-icss */
+/* Pseudo hwmod for reset control purpose only */
+static struct omap_hwmod am33xx_pruss_hwmod = {
+	.name		= "pruss",
+	.class		= &am33xx_pruss_hwmod_class,
+	.clkdm_name	= "pruss_ocp_clkdm",
+	.mpu_irqs	= am33xx_pruss_irqs,
+	.main_clk	= "pruss_ocp_gclk",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_PER_PRUSS_CLKCTRL_OFFSET,
+			.rstctrl_offs	= AM33XX_RM_PER_RSTCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+	.rst_lines	= am33xx_pruss_resets,
+	.rst_lines_cnt	= ARRAY_SIZE(am33xx_pruss_resets),
+};
+
+/* gfx */
+/* Pseudo hwmod for reset control purpose only */
+static struct omap_hwmod_class am33xx_gfx_hwmod_class = {
+	.name	= "gfx",
+};
+
+static struct omap_hwmod_rst_info am33xx_gfx_resets[] = {
+	{ .name = "gfx", .rst_shift = 0 },
+};
+
+static struct omap_hwmod_irq_info am33xx_gfx_irqs[] = {
+	{ .name = "gfxint", .irq = 37 + OMAP_INTC_START, },
+	{ .irq = -1 },
+};
+
+static struct omap_hwmod am33xx_gfx_hwmod = {
+	.name		= "gfx",
+	.class		= &am33xx_gfx_hwmod_class,
+	.clkdm_name	= "gfx_l3_clkdm",
+	.mpu_irqs	= am33xx_gfx_irqs,
+	.main_clk	= "gfx_fck_div_ck",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_GFX_GFX_CLKCTRL_OFFSET,
+			.rstctrl_offs	= AM33XX_RM_GFX_RSTCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+	.rst_lines	= am33xx_gfx_resets,
+	.rst_lines_cnt	= ARRAY_SIZE(am33xx_gfx_resets),
+};
+
+/*
+ * 'prcm' class
+ * power and reset manager (whole prcm infrastructure)
+ */
+static struct omap_hwmod_class am33xx_prcm_hwmod_class = {
+	.name	= "prcm",
+};
+
+/* prcm */
+static struct omap_hwmod am33xx_prcm_hwmod = {
+	.name		= "prcm",
+	.class		= &am33xx_prcm_hwmod_class,
+	.clkdm_name	= "l4_wkup_clkdm",
+};
+
+/*
+ * 'adc/tsc' class
+ * TouchScreen Controller (Anolog-To-Digital Converter)
+ */
+static struct omap_hwmod_class_sysconfig am33xx_adc_tsc_sysc = {
+	.rev_offs	= 0x00,
+	.sysc_offs	= 0x10,
+	.sysc_flags	= SYSC_HAS_SIDLEMODE,
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			SIDLE_SMART_WKUP),
+	.sysc_fields	= &omap_hwmod_sysc_type2,
+};
+
+static struct omap_hwmod_class am33xx_adc_tsc_hwmod_class = {
+	.name		= "adc_tsc",
+	.sysc		= &am33xx_adc_tsc_sysc,
+};
+
+static struct omap_hwmod_irq_info am33xx_adc_tsc_irqs[] = {
+	{ .irq = 16 + OMAP_INTC_START, },
+	{ .irq = -1 },
+};
+
+static struct omap_hwmod am33xx_adc_tsc_hwmod = {
+	.name		= "adc_tsc",
+	.class		= &am33xx_adc_tsc_hwmod_class,
+	.clkdm_name	= "l4_wkup_clkdm",
+	.mpu_irqs	= am33xx_adc_tsc_irqs,
+	.main_clk	= "adc_tsc_fck",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_WKUP_ADC_TSC_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/*
+ * Modules omap_hwmod structures
+ *
+ * The following IPs are excluded for the moment because:
+ * - They do not need an explicit SW control using omap_hwmod API.
+ * - They still need to be validated with the driver
+ *   properly adapted to omap_hwmod / omap_device
+ *
+ *    - cEFUSE (doesn't fall under any ocp_if)
+ *    - clkdiv32k
+ *    - debugss
+ *    - ocmc ram
+ *    - ocp watch point
+ *    - aes0
+ *    - sha0
+ */
+#if 0
+/*
+ * 'cefuse' class
+ */
+static struct omap_hwmod_class am33xx_cefuse_hwmod_class = {
+	.name		= "cefuse",
+};
+
+static struct omap_hwmod am33xx_cefuse_hwmod = {
+	.name		= "cefuse",
+	.class		= &am33xx_cefuse_hwmod_class,
+	.clkdm_name	= "l4_cefuse_clkdm",
+	.main_clk	= "cefuse_fck",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_CEFUSE_CEFUSE_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/*
+ * 'clkdiv32k' class
+ */
+static struct omap_hwmod_class am33xx_clkdiv32k_hwmod_class = {
+	.name		= "clkdiv32k",
+};
+
+static struct omap_hwmod am33xx_clkdiv32k_hwmod = {
+	.name		= "clkdiv32k",
+	.class		= &am33xx_clkdiv32k_hwmod_class,
+	.clkdm_name	= "clk_24mhz_clkdm",
+	.main_clk	= "clkdiv32k_ick",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_PER_CLKDIV32K_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/*
+ * 'debugss' class
+ * debug sub system
+ */
+static struct omap_hwmod_class am33xx_debugss_hwmod_class = {
+	.name		= "debugss",
+};
+
+static struct omap_hwmod am33xx_debugss_hwmod = {
+	.name		= "debugss",
+	.class		= &am33xx_debugss_hwmod_class,
+	.clkdm_name	= "l3_aon_clkdm",
+	.main_clk	= "debugss_ick",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_WKUP_DEBUGSS_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/* ocmcram */
+static struct omap_hwmod_class am33xx_ocmcram_hwmod_class = {
+	.name = "ocmcram",
+};
+
+static struct omap_hwmod am33xx_ocmcram_hwmod = {
+	.name		= "ocmcram",
+	.class		= &am33xx_ocmcram_hwmod_class,
+	.clkdm_name	= "l3_clkdm",
+	.flags		= (HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET),
+	.main_clk	= "l3_gclk",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_PER_OCMCRAM_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/* ocpwp */
+static struct omap_hwmod_class am33xx_ocpwp_hwmod_class = {
+	.name		= "ocpwp",
+};
+
+static struct omap_hwmod am33xx_ocpwp_hwmod = {
+	.name		= "ocpwp",
+	.class		= &am33xx_ocpwp_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.main_clk	= "l4ls_gclk",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_PER_OCPWP_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/*
+ * 'aes' class
+ */
+static struct omap_hwmod_class am33xx_aes_hwmod_class = {
+	.name		= "aes",
+};
+
+static struct omap_hwmod_irq_info am33xx_aes0_irqs[] = {
+	{ .irq = 102 + OMAP_INTC_START, },
+	{ .irq = -1 },
+};
+
+static struct omap_hwmod am33xx_aes0_hwmod = {
+	.name		= "aes0",
+	.class		= &am33xx_aes_hwmod_class,
+	.clkdm_name	= "l3_clkdm",
+	.mpu_irqs	= am33xx_aes0_irqs,
+	.main_clk	= "l3_gclk",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_PER_AES0_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/* sha0 */
+static struct omap_hwmod_class am33xx_sha0_hwmod_class = {
+	.name		= "sha0",
+};
+
+static struct omap_hwmod_irq_info am33xx_sha0_irqs[] = {
+	{ .irq = 108 + OMAP_INTC_START, },
+	{ .irq = -1 },
+};
+
+static struct omap_hwmod am33xx_sha0_hwmod = {
+	.name		= "sha0",
+	.class		= &am33xx_sha0_hwmod_class,
+	.clkdm_name	= "l3_clkdm",
+	.mpu_irqs	= am33xx_sha0_irqs,
+	.main_clk	= "l3_gclk",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_PER_SHA0_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+#endif
+
+/* 'smartreflex' class */
+static struct omap_hwmod_class am33xx_smartreflex_hwmod_class = {
+	.name		= "smartreflex",
+};
+
+/* smartreflex0 */
+static struct omap_hwmod_irq_info am33xx_smartreflex0_irqs[] = {
+	{ .irq = 120 + OMAP_INTC_START, },
+	{ .irq = -1 },
+};
+
+static struct omap_hwmod am33xx_smartreflex0_hwmod = {
+	.name		= "smartreflex0",
+	.class		= &am33xx_smartreflex_hwmod_class,
+	.clkdm_name	= "l4_wkup_clkdm",
+	.mpu_irqs	= am33xx_smartreflex0_irqs,
+	.main_clk	= "smartreflex0_fck",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_WKUP_SMARTREFLEX0_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/* smartreflex1 */
+static struct omap_hwmod_irq_info am33xx_smartreflex1_irqs[] = {
+	{ .irq = 121 + OMAP_INTC_START, },
+	{ .irq = -1 },
+};
+
+static struct omap_hwmod am33xx_smartreflex1_hwmod = {
+	.name		= "smartreflex1",
+	.class		= &am33xx_smartreflex_hwmod_class,
+	.clkdm_name	= "l4_wkup_clkdm",
+	.mpu_irqs	= am33xx_smartreflex1_irqs,
+	.main_clk	= "smartreflex1_fck",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_WKUP_SMARTREFLEX1_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/*
+ * 'control' module class
+ */
+static struct omap_hwmod_class am33xx_control_hwmod_class = {
+	.name		= "control",
+};
+
+static struct omap_hwmod_irq_info am33xx_control_irqs[] = {
+	{ .irq = 8 + OMAP_INTC_START, },
+	{ .irq = -1 },
+};
+
+static struct omap_hwmod am33xx_control_hwmod = {
+	.name		= "control",
+	.class		= &am33xx_control_hwmod_class,
+	.clkdm_name	= "l4_wkup_clkdm",
+	.flags		= (HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET),
+	.mpu_irqs	= am33xx_control_irqs,
+	.main_clk	= "dpll_core_m4_div2_ck",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_WKUP_CONTROL_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/*
+ * 'cpgmac' class
+ * cpsw/cpgmac sub system
+ */
+static struct omap_hwmod_class_sysconfig am33xx_cpgmac_sysc = {
+	.rev_offs	= 0x0,
+	.sysc_offs	= 0x8,
+	.syss_offs	= 0x4,
+	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_MIDLEMODE |
+			   SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | MSTANDBY_FORCE |
+			   MSTANDBY_NO),
+	.sysc_fields	= &omap_hwmod_sysc_type3,
+};
+
+static struct omap_hwmod_class am33xx_cpgmac0_hwmod_class = {
+	.name		= "cpgmac0",
+	.sysc		= &am33xx_cpgmac_sysc,
+};
+
+static struct omap_hwmod_irq_info am33xx_cpgmac0_irqs[] = {
+	{ .name = "c0_rx_thresh_pend", .irq = 40 + OMAP_INTC_START, },
+	{ .name = "c0_rx_pend", .irq = 41 + OMAP_INTC_START, },
+	{ .name = "c0_tx_pend", .irq = 42 + OMAP_INTC_START, },
+	{ .name = "c0_misc_pend", .irq = 43 + OMAP_INTC_START, },
+	{ .irq = -1 },
+};
+
+static struct omap_hwmod am33xx_cpgmac0_hwmod = {
+	.name		= "cpgmac0",
+	.class		= &am33xx_cpgmac0_hwmod_class,
+	.clkdm_name	= "cpsw_125mhz_clkdm",
+	.mpu_irqs	= am33xx_cpgmac0_irqs,
+	.main_clk	= "cpsw_125mhz_gclk",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_PER_CPGMAC0_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/*
+ * dcan class
+ */
+static struct omap_hwmod_class am33xx_dcan_hwmod_class = {
+	.name = "d_can",
+};
+
+/* dcan0 */
+static struct omap_hwmod_irq_info am33xx_dcan0_irqs[] = {
+	{ .name = "d_can_ms", .irq = 52 + OMAP_INTC_START, },
+	{ .name = "d_can_mo", .irq = 53 + OMAP_INTC_START, },
+	{ .irq = -1 },
+};
+
+static struct omap_hwmod am33xx_dcan0_hwmod = {
+	.name		= "d_can0",
+	.class		= &am33xx_dcan_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.mpu_irqs	= am33xx_dcan0_irqs,
+	.main_clk	= "dcan0_fck",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_PER_DCAN0_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/* dcan1 */
+static struct omap_hwmod_irq_info am33xx_dcan1_irqs[] = {
+	{ .name = "d_can_ms", .irq = 55 + OMAP_INTC_START, },
+	{ .name = "d_can_mo", .irq = 56 + OMAP_INTC_START, },
+	{ .irq = -1 },
+};
+static struct omap_hwmod am33xx_dcan1_hwmod = {
+	.name		= "d_can1",
+	.class		= &am33xx_dcan_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.mpu_irqs	= am33xx_dcan1_irqs,
+	.main_clk	= "dcan1_fck",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_PER_DCAN1_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/* elm */
+static struct omap_hwmod_class_sysconfig am33xx_elm_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_SIDLEMODE |
+			SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE |
+			SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class am33xx_elm_hwmod_class = {
+	.name		= "elm",
+	.sysc		= &am33xx_elm_sysc,
+};
+
+static struct omap_hwmod_irq_info am33xx_elm_irqs[] = {
+	{ .irq = 4 + OMAP_INTC_START, },
+	{ .irq = -1 },
+};
+
+static struct omap_hwmod am33xx_elm_hwmod = {
+	.name		= "elm",
+	.class		= &am33xx_elm_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.mpu_irqs	= am33xx_elm_irqs,
+	.main_clk	= "l4ls_gclk",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_PER_ELM_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/*
+ * 'epwmss' class: ecap0,1,2,  ehrpwm0,1,2
+ */
+static struct omap_hwmod_class_sysconfig am33xx_epwmss_sysc = {
+	.rev_offs	= 0x0,
+	.sysc_offs	= 0x4,
+	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_MIDLEMODE),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			SIDLE_SMART_WKUP | MSTANDBY_FORCE | MSTANDBY_NO |
+			MSTANDBY_SMART | MSTANDBY_SMART_WKUP),
+	.sysc_fields	= &omap_hwmod_sysc_type2,
+};
+
+static struct omap_hwmod_class am33xx_epwmss_hwmod_class = {
+	.name		= "epwmss",
+	.sysc		= &am33xx_epwmss_sysc,
+};
+
+/* ehrpwm0 */
+static struct omap_hwmod_irq_info am33xx_ehrpwm0_irqs[] = {
+	{ .name = "int", .irq = 86 + OMAP_INTC_START, },
+	{ .name = "tzint", .irq = 58 + OMAP_INTC_START, },
+	{ .irq = -1 },
+};
+
+static struct omap_hwmod am33xx_ehrpwm0_hwmod = {
+	.name		= "ehrpwm0",
+	.class		= &am33xx_epwmss_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.mpu_irqs	= am33xx_ehrpwm0_irqs,
+	.main_clk	= "l4ls_gclk",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_PER_EPWMSS0_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/* ehrpwm1 */
+static struct omap_hwmod_irq_info am33xx_ehrpwm1_irqs[] = {
+	{ .name = "int", .irq = 87 + OMAP_INTC_START, },
+	{ .name = "tzint", .irq = 59 + OMAP_INTC_START, },
+	{ .irq = -1 },
+};
+
+static struct omap_hwmod am33xx_ehrpwm1_hwmod = {
+	.name		= "ehrpwm1",
+	.class		= &am33xx_epwmss_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.mpu_irqs	= am33xx_ehrpwm1_irqs,
+	.main_clk	= "l4ls_gclk",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_PER_EPWMSS1_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/* ehrpwm2 */
+static struct omap_hwmod_irq_info am33xx_ehrpwm2_irqs[] = {
+	{ .name = "int", .irq = 39 + OMAP_INTC_START, },
+	{ .name = "tzint", .irq = 60 + OMAP_INTC_START, },
+	{ .irq = -1 },
+};
+
+static struct omap_hwmod am33xx_ehrpwm2_hwmod = {
+	.name		= "ehrpwm2",
+	.class		= &am33xx_epwmss_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.mpu_irqs	= am33xx_ehrpwm2_irqs,
+	.main_clk	= "l4ls_gclk",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_PER_EPWMSS2_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/* ecap0 */
+static struct omap_hwmod_irq_info am33xx_ecap0_irqs[] = {
+	{ .irq = 31 + OMAP_INTC_START, },
+	{ .irq = -1 },
+};
+
+static struct omap_hwmod am33xx_ecap0_hwmod = {
+	.name		= "ecap0",
+	.class		= &am33xx_epwmss_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.mpu_irqs	= am33xx_ecap0_irqs,
+	.main_clk	= "l4ls_gclk",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_PER_EPWMSS0_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/* ecap1 */
+static struct omap_hwmod_irq_info am33xx_ecap1_irqs[] = {
+	{ .irq = 47 + OMAP_INTC_START, },
+	{ .irq = -1 },
+};
+
+static struct omap_hwmod am33xx_ecap1_hwmod = {
+	.name		= "ecap1",
+	.class		= &am33xx_epwmss_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.mpu_irqs	= am33xx_ecap1_irqs,
+	.main_clk	= "l4ls_gclk",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_PER_EPWMSS1_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/* ecap2 */
+static struct omap_hwmod_irq_info am33xx_ecap2_irqs[] = {
+	{ .irq = 61 + OMAP_INTC_START, },
+	{ .irq = -1 },
+};
+
+static struct omap_hwmod am33xx_ecap2_hwmod = {
+	.name		= "ecap2",
+	.mpu_irqs	= am33xx_ecap2_irqs,
+	.class		= &am33xx_epwmss_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.main_clk	= "l4ls_gclk",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_PER_EPWMSS2_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/*
+ * 'gpio' class: for gpio 0,1,2,3
+ */
+static struct omap_hwmod_class_sysconfig am33xx_gpio_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0114,
+	.sysc_flags	= (SYSC_HAS_AUTOIDLE | SYSC_HAS_ENAWAKEUP |
+			  SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
+			  SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			  SIDLE_SMART_WKUP),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class am33xx_gpio_hwmod_class = {
+	.name		= "gpio",
+	.sysc		= &am33xx_gpio_sysc,
+	.rev		= 2,
+};
+
+static struct omap_gpio_dev_attr gpio_dev_attr = {
+	.bank_width	= 32,
+	.dbck_flag	= true,
+};
+
+/* gpio0 */
+static struct omap_hwmod_opt_clk gpio0_opt_clks[] = {
+	{ .role = "dbclk", .clk = "gpio0_dbclk" },
+};
+
+static struct omap_hwmod_irq_info am33xx_gpio0_irqs[] = {
+	{ .irq = 96 + OMAP_INTC_START, },
+	{ .irq = -1 },
+};
+
+static struct omap_hwmod am33xx_gpio0_hwmod = {
+	.name		= "gpio1",
+	.class		= &am33xx_gpio_hwmod_class,
+	.clkdm_name	= "l4_wkup_clkdm",
+	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
+	.mpu_irqs	= am33xx_gpio0_irqs,
+	.main_clk	= "dpll_core_m4_div2_ck",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_WKUP_GPIO0_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+	.opt_clks	= gpio0_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(gpio0_opt_clks),
+	.dev_attr	= &gpio_dev_attr,
+};
+
+/* gpio1 */
+static struct omap_hwmod_irq_info am33xx_gpio1_irqs[] = {
+	{ .irq = 98 + OMAP_INTC_START, },
+	{ .irq = -1 },
+};
+
+static struct omap_hwmod_opt_clk gpio1_opt_clks[] = {
+	{ .role = "dbclk", .clk = "gpio1_dbclk" },
+};
+
+static struct omap_hwmod am33xx_gpio1_hwmod = {
+	.name		= "gpio2",
+	.class		= &am33xx_gpio_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
+	.mpu_irqs	= am33xx_gpio1_irqs,
+	.main_clk	= "l4ls_gclk",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_PER_GPIO1_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+	.opt_clks	= gpio1_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(gpio1_opt_clks),
+	.dev_attr	= &gpio_dev_attr,
+};
+
+/* gpio2 */
+static struct omap_hwmod_irq_info am33xx_gpio2_irqs[] = {
+	{ .irq = 32 + OMAP_INTC_START, },
+	{ .irq = -1 },
+};
+
+static struct omap_hwmod_opt_clk gpio2_opt_clks[] = {
+	{ .role = "dbclk", .clk = "gpio2_dbclk" },
+};
+
+static struct omap_hwmod am33xx_gpio2_hwmod = {
+	.name		= "gpio3",
+	.class		= &am33xx_gpio_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
+	.mpu_irqs	= am33xx_gpio2_irqs,
+	.main_clk	= "l4ls_gclk",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_PER_GPIO2_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+	.opt_clks	= gpio2_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(gpio2_opt_clks),
+	.dev_attr	= &gpio_dev_attr,
+};
+
+/* gpio3 */
+static struct omap_hwmod_irq_info am33xx_gpio3_irqs[] = {
+	{ .irq = 62 + OMAP_INTC_START, },
+	{ .irq = -1 },
+};
+
+static struct omap_hwmod_opt_clk gpio3_opt_clks[] = {
+	{ .role = "dbclk", .clk = "gpio3_dbclk" },
+};
+
+static struct omap_hwmod am33xx_gpio3_hwmod = {
+	.name		= "gpio4",
+	.class		= &am33xx_gpio_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
+	.mpu_irqs	= am33xx_gpio3_irqs,
+	.main_clk	= "l4ls_gclk",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_PER_GPIO3_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+	.opt_clks	= gpio3_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(gpio3_opt_clks),
+	.dev_attr	= &gpio_dev_attr,
+};
+
+/* gpmc */
+static struct omap_hwmod_class_sysconfig gpmc_sysc = {
+	.rev_offs	= 0x0,
+	.sysc_offs	= 0x10,
+	.syss_offs	= 0x14,
+	.sysc_flags	= (SYSC_HAS_AUTOIDLE | SYSC_HAS_SIDLEMODE |
+			SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class am33xx_gpmc_hwmod_class = {
+	.name		= "gpmc",
+	.sysc		= &gpmc_sysc,
+};
+
+static struct omap_hwmod_irq_info am33xx_gpmc_irqs[] = {
+	{ .irq = 100 + OMAP_INTC_START, },
+	{ .irq = -1 },
+};
+
+static struct omap_hwmod am33xx_gpmc_hwmod = {
+	.name		= "gpmc",
+	.class		= &am33xx_gpmc_hwmod_class,
+	.clkdm_name	= "l3s_clkdm",
+	.flags		= (HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET),
+	.mpu_irqs	= am33xx_gpmc_irqs,
+	.main_clk	= "l3s_gclk",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_PER_GPMC_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/* 'i2c' class */
+static struct omap_hwmod_class_sysconfig am33xx_i2c_sysc = {
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0090,
+	.sysc_flags	= (SYSC_HAS_AUTOIDLE | SYSC_HAS_CLOCKACTIVITY |
+			  SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE |
+			  SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			  SIDLE_SMART_WKUP),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class i2c_class = {
+	.name		= "i2c",
+	.sysc		= &am33xx_i2c_sysc,
+	.rev		= OMAP_I2C_IP_VERSION_2,
+	.reset		= &omap_i2c_reset,
+};
+
+static struct omap_i2c_dev_attr i2c_dev_attr = {
+	.flags = OMAP_I2C_FLAG_BUS_SHIFT_NONE |
+		  OMAP_I2C_FLAG_RESET_REGS_POSTIDLE,
+};
+
+/* i2c1 */
+static struct omap_hwmod_irq_info i2c1_mpu_irqs[] = {
+	{ .irq = 70 + OMAP_INTC_START, },
+	{ .irq = -1 },
+};
+
+static struct omap_hwmod_dma_info i2c1_edma_reqs[] = {
+	{ .name = "tx", .dma_req = 0, },
+	{ .name = "rx", .dma_req = 0, },
+	{ .dma_req = -1 }
+};
+
+static struct omap_hwmod am33xx_i2c1_hwmod = {
+	.name		= "i2c1",
+	.class		= &i2c_class,
+	.clkdm_name	= "l4_wkup_clkdm",
+	.mpu_irqs	= i2c1_mpu_irqs,
+	.sdma_reqs	= i2c1_edma_reqs,
+	.flags		= HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT,
+	.main_clk	= "dpll_per_m2_div4_wkupdm_ck",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_WKUP_I2C0_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+	.dev_attr	= &i2c_dev_attr,
+};
+
+/* i2c1 */
+static struct omap_hwmod_irq_info i2c2_mpu_irqs[] = {
+	{ .irq = 71 + OMAP_INTC_START, },
+	{ .irq = -1 },
+};
+
+static struct omap_hwmod_dma_info i2c2_edma_reqs[] = {
+	{ .name = "tx", .dma_req = 0, },
+	{ .name = "rx", .dma_req = 0, },
+	{ .dma_req = -1 }
+};
+
+static struct omap_hwmod am33xx_i2c2_hwmod = {
+	.name		= "i2c2",
+	.class		= &i2c_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.mpu_irqs	= i2c2_mpu_irqs,
+	.sdma_reqs	= i2c2_edma_reqs,
+	.flags		= HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT,
+	.main_clk	= "dpll_per_m2_div4_ck",
+	.prcm		= {
+		.omap4 = {
+			.clkctrl_offs	= AM33XX_CM_PER_I2C1_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+	.dev_attr	= &i2c_dev_attr,
+};
+
+/* i2c3 */
+static struct omap_hwmod_dma_info i2c3_edma_reqs[] = {
+	{ .name = "tx", .dma_req = 0, },
+	{ .name = "rx", .dma_req = 0, },
+	{ .dma_req = -1 }
+};
+
+static struct omap_hwmod_irq_info i2c3_mpu_irqs[] = {
+	{ .irq = 30 + OMAP_INTC_START, },
+	{ .irq = -1 },
+};
+
+static struct omap_hwmod am33xx_i2c3_hwmod = {
+	.name		= "i2c3",
+	.class		= &i2c_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.mpu_irqs	= i2c3_mpu_irqs,
+	.sdma_reqs	= i2c3_edma_reqs,
+	.flags		= HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT,
+	.main_clk	= "dpll_per_m2_div4_ck",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_PER_I2C2_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+	.dev_attr	= &i2c_dev_attr,
+};
+
+
+/* lcdc */
+static struct omap_hwmod_class_sysconfig lcdc_sysc = {
+	.rev_offs	= 0x0,
+	.sysc_offs	= 0x54,
+	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_MIDLEMODE),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type2,
+};
+
+static struct omap_hwmod_class am33xx_lcdc_hwmod_class = {
+	.name		= "lcdc",
+	.sysc		= &lcdc_sysc,
+};
+
+static struct omap_hwmod_irq_info am33xx_lcdc_irqs[] = {
+	{ .irq = 36 + OMAP_INTC_START, },
+	{ .irq = -1 },
+};
+
+static struct omap_hwmod am33xx_lcdc_hwmod = {
+	.name		= "lcdc",
+	.class		= &am33xx_lcdc_hwmod_class,
+	.clkdm_name	= "lcdc_clkdm",
+	.mpu_irqs	= am33xx_lcdc_irqs,
+	.flags		= HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY,
+	.main_clk	= "lcd_gclk",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_PER_LCDC_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/*
+ * 'mailbox' class
+ * mailbox module allowing communication between the on-chip processors using a
+ * queued mailbox-interrupt mechanism.
+ */
+static struct omap_hwmod_class_sysconfig am33xx_mailbox_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.sysc_flags	= (SYSC_HAS_RESET_STATUS | SYSC_HAS_SIDLEMODE |
+			  SYSC_HAS_SOFTRESET),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type2,
+};
+
+static struct omap_hwmod_class am33xx_mailbox_hwmod_class = {
+	.name	= "mailbox",
+	.sysc	= &am33xx_mailbox_sysc,
+};
+
+static struct omap_hwmod_irq_info am33xx_mailbox_irqs[] = {
+	{ .irq = 77 + OMAP_INTC_START, },
+	{ .irq = -1 },
+};
+
+static struct omap_hwmod am33xx_mailbox_hwmod = {
+	.name		= "mailbox",
+	.class		= &am33xx_mailbox_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.mpu_irqs	= am33xx_mailbox_irqs,
+	.main_clk	= "l4ls_gclk",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_offs	= AM33XX_CM_PER_MAILBOX0_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/*
+ * 'mcasp' class
+ */
+static struct omap_hwmod_class_sysconfig am33xx_mcasp_sysc = {
+	.rev_offs	= 0x0,
+	.sysc_offs	= 0x4,
+	.sysc_flags	= SYSC_HAS_SIDLEMODE,
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type3,
+};
+
+static struct omap_hwmod_class am33xx_mcasp_hwmod_class = {
+	.name		= "mcasp",
+	.sysc		= &am33xx_mcasp_sysc,
+};
+
+/* mcasp0 */
+static struct omap_hwmod_irq_info am33xx_mcasp0_irqs[] = {
+	{ .name = "ax", .irq = 80 + OMAP_INTC_START, },
+	{ .name = "ar", .irq = 81 + OMAP_INTC_START, },
+	{ .irq = -1 },
+};
+
+static struct omap_hwmod_dma_info am33xx_mcasp0_edma_reqs[] = {
+	{ .name = "tx", .dma_req = 8, },
+	{ .name = "rx", .dma_req = 9, },
+	{ .dma_req = -1 }
+};
+
+static struct omap_hwmod am33xx_mcasp0_hwmod = {
+	.name		= "mcasp0",
+	.class		= &am33xx_mcasp_hwmod_class,
+	.clkdm_name	= "l3s_clkdm",
+	.mpu_irqs	= am33xx_mcasp0_irqs,
+	.sdma_reqs	= am33xx_mcasp0_edma_reqs,
+	.main_clk	= "mcasp0_fck",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_PER_MCASP0_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/* mcasp1 */
+static struct omap_hwmod_irq_info am33xx_mcasp1_irqs[] = {
+	{ .name = "ax", .irq = 82 + OMAP_INTC_START, },
+	{ .name = "ar", .irq = 83 + OMAP_INTC_START, },
+	{ .irq = -1 },
+};
+
+static struct omap_hwmod_dma_info am33xx_mcasp1_edma_reqs[] = {
+	{ .name = "tx", .dma_req = 10, },
+	{ .name = "rx", .dma_req = 11, },
+	{ .dma_req = -1 }
+};
+
+static struct omap_hwmod am33xx_mcasp1_hwmod = {
+	.name		= "mcasp1",
+	.class		= &am33xx_mcasp_hwmod_class,
+	.clkdm_name	= "l3s_clkdm",
+	.mpu_irqs	= am33xx_mcasp1_irqs,
+	.sdma_reqs	= am33xx_mcasp1_edma_reqs,
+	.main_clk	= "mcasp1_fck",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_PER_MCASP1_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/* 'mmc' class */
+static struct omap_hwmod_class_sysconfig am33xx_mmc_sysc = {
+	.rev_offs	= 0x1fc,
+	.sysc_offs	= 0x10,
+	.syss_offs	= 0x14,
+	.sysc_flags	= (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_SIDLEMODE |
+			  SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
+			  SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class am33xx_mmc_hwmod_class = {
+	.name		= "mmc",
+	.sysc		= &am33xx_mmc_sysc,
+};
+
+/* mmc0 */
+static struct omap_hwmod_irq_info am33xx_mmc0_irqs[] = {
+	{ .irq = 64 + OMAP_INTC_START, },
+	{ .irq = -1 },
+};
+
+static struct omap_hwmod_dma_info am33xx_mmc0_edma_reqs[] = {
+	{ .name = "tx", .dma_req = 24, },
+	{ .name = "rx", .dma_req = 25, },
+	{ .dma_req = -1 }
+};
+
+static struct omap_mmc_dev_attr am33xx_mmc0_dev_attr = {
+	.flags		= OMAP_HSMMC_SUPPORTS_DUAL_VOLT,
+};
+
+static struct omap_hwmod am33xx_mmc0_hwmod = {
+	.name		= "mmc1",
+	.class		= &am33xx_mmc_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.mpu_irqs	= am33xx_mmc0_irqs,
+	.sdma_reqs	= am33xx_mmc0_edma_reqs,
+	.main_clk	= "mmc_clk",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_PER_MMC0_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+	.dev_attr	= &am33xx_mmc0_dev_attr,
+};
+
+/* mmc1 */
+static struct omap_hwmod_irq_info am33xx_mmc1_irqs[] = {
+	{ .irq = 28 + OMAP_INTC_START, },
+	{ .irq = -1 },
+};
+
+static struct omap_hwmod_dma_info am33xx_mmc1_edma_reqs[] = {
+	{ .name = "tx", .dma_req = 2, },
+	{ .name = "rx", .dma_req = 3, },
+	{ .dma_req = -1 }
+};
+
+static struct omap_mmc_dev_attr am33xx_mmc1_dev_attr = {
+	.flags		= OMAP_HSMMC_SUPPORTS_DUAL_VOLT,
+};
+
+static struct omap_hwmod am33xx_mmc1_hwmod = {
+	.name		= "mmc2",
+	.class		= &am33xx_mmc_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.mpu_irqs	= am33xx_mmc1_irqs,
+	.sdma_reqs	= am33xx_mmc1_edma_reqs,
+	.main_clk	= "mmc_clk",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_PER_MMC1_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+	.dev_attr	= &am33xx_mmc1_dev_attr,
+};
+
+/* mmc2 */
+static struct omap_hwmod_irq_info am33xx_mmc2_irqs[] = {
+	{ .irq = 29 + OMAP_INTC_START, },
+	{ .irq = -1 },
+};
+
+static struct omap_hwmod_dma_info am33xx_mmc2_edma_reqs[] = {
+	{ .name = "tx", .dma_req = 64, },
+	{ .name = "rx", .dma_req = 65, },
+	{ .dma_req = -1 }
+};
+
+static struct omap_mmc_dev_attr am33xx_mmc2_dev_attr = {
+	.flags		= OMAP_HSMMC_SUPPORTS_DUAL_VOLT,
+};
+static struct omap_hwmod am33xx_mmc2_hwmod = {
+	.name		= "mmc3",
+	.class		= &am33xx_mmc_hwmod_class,
+	.clkdm_name	= "l3s_clkdm",
+	.mpu_irqs	= am33xx_mmc2_irqs,
+	.sdma_reqs	= am33xx_mmc2_edma_reqs,
+	.main_clk	= "mmc_clk",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_PER_MMC2_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+	.dev_attr	= &am33xx_mmc2_dev_attr,
+};
+
+/*
+ * 'rtc' class
+ * rtc subsystem
+ */
+static struct omap_hwmod_class_sysconfig am33xx_rtc_sysc = {
+	.rev_offs	= 0x0074,
+	.sysc_offs	= 0x0078,
+	.sysc_flags	= SYSC_HAS_SIDLEMODE,
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO |
+			  SIDLE_SMART | SIDLE_SMART_WKUP),
+	.sysc_fields	= &omap_hwmod_sysc_type3,
+};
+
+static struct omap_hwmod_class am33xx_rtc_hwmod_class = {
+	.name		= "rtc",
+	.sysc		= &am33xx_rtc_sysc,
+};
+
+static struct omap_hwmod_irq_info am33xx_rtc_irqs[] = {
+	{ .name = "rtcint", .irq = 75 + OMAP_INTC_START, },
+	{ .name = "rtcalarmint", .irq = 76 + OMAP_INTC_START, },
+	{ .irq = -1 },
+};
+
+static struct omap_hwmod am33xx_rtc_hwmod = {
+	.name		= "rtc",
+	.class		= &am33xx_rtc_hwmod_class,
+	.clkdm_name	= "l4_rtc_clkdm",
+	.mpu_irqs	= am33xx_rtc_irqs,
+	.main_clk	= "clk_32768_ck",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_RTC_RTC_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/* 'spi' class */
+static struct omap_hwmod_class_sysconfig am33xx_mcspi_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0110,
+	.syss_offs	= 0x0114,
+	.sysc_flags	= (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_SIDLEMODE |
+			  SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE |
+			  SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class am33xx_spi_hwmod_class = {
+	.name		= "mcspi",
+	.sysc		= &am33xx_mcspi_sysc,
+	.rev		= OMAP4_MCSPI_REV,
+};
+
+/* spi0 */
+static struct omap_hwmod_irq_info am33xx_spi0_irqs[] = {
+	{ .irq = 65 + OMAP_INTC_START, },
+	{ .irq = -1 },
+};
+
+static struct omap_hwmod_dma_info am33xx_mcspi0_edma_reqs[] = {
+	{ .name = "rx0", .dma_req = 17 },
+	{ .name = "tx0", .dma_req = 16 },
+	{ .name = "rx1", .dma_req = 19 },
+	{ .name = "tx1", .dma_req = 18 },
+	{ .dma_req = -1 }
+};
+
+static struct omap2_mcspi_dev_attr mcspi_attrib = {
+	.num_chipselect	= 2,
+};
+static struct omap_hwmod am33xx_spi0_hwmod = {
+	.name		= "spi0",
+	.class		= &am33xx_spi_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.mpu_irqs	= am33xx_spi0_irqs,
+	.sdma_reqs	= am33xx_mcspi0_edma_reqs,
+	.main_clk	= "dpll_per_m2_div4_ck",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_PER_SPI0_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+	.dev_attr	= &mcspi_attrib,
+};
+
+/* spi1 */
+static struct omap_hwmod_irq_info am33xx_spi1_irqs[] = {
+	{ .irq = 125 + OMAP_INTC_START, },
+	{ .irq = -1 },
+};
+
+static struct omap_hwmod_dma_info am33xx_mcspi1_edma_reqs[] = {
+	{ .name = "rx0", .dma_req = 43 },
+	{ .name = "tx0", .dma_req = 42 },
+	{ .name = "rx1", .dma_req = 45 },
+	{ .name = "tx1", .dma_req = 44 },
+	{ .dma_req = -1 }
+};
+
+static struct omap_hwmod am33xx_spi1_hwmod = {
+	.name		= "spi1",
+	.class		= &am33xx_spi_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.mpu_irqs	= am33xx_spi1_irqs,
+	.sdma_reqs	= am33xx_mcspi1_edma_reqs,
+	.main_clk	= "dpll_per_m2_div4_ck",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_PER_SPI1_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+	.dev_attr	= &mcspi_attrib,
+};
+
+/*
+ * 'spinlock' class
+ * spinlock provides hardware assistance for synchronizing the
+ * processes running on multiple processors
+ */
+static struct omap_hwmod_class am33xx_spinlock_hwmod_class = {
+	.name		= "spinlock",
+};
+
+static struct omap_hwmod am33xx_spinlock_hwmod = {
+	.name		= "spinlock",
+	.class		= &am33xx_spinlock_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.main_clk	= "l4ls_gclk",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_PER_SPINLOCK_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/* 'timer 2-7' class */
+static struct omap_hwmod_class_sysconfig am33xx_timer_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			  SIDLE_SMART_WKUP),
+	.sysc_fields	= &omap_hwmod_sysc_type2,
+};
+
+static struct omap_hwmod_class am33xx_timer_hwmod_class = {
+	.name		= "timer",
+	.sysc		= &am33xx_timer_sysc,
+};
+
+/* timer1 1ms */
+static struct omap_hwmod_class_sysconfig am33xx_timer1ms_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_SIDLEMODE |
+			SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE |
+			SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class am33xx_timer1ms_hwmod_class = {
+	.name		= "timer",
+	.sysc		= &am33xx_timer1ms_sysc,
+};
+
+static struct omap_hwmod_irq_info am33xx_timer1_irqs[] = {
+	{ .irq = 67 + OMAP_INTC_START, },
+	{ .irq = -1 },
+};
+
+static struct omap_hwmod am33xx_timer1_hwmod = {
+	.name		= "timer1",
+	.class		= &am33xx_timer1ms_hwmod_class,
+	.clkdm_name	= "l4_wkup_clkdm",
+	.mpu_irqs	= am33xx_timer1_irqs,
+	.main_clk	= "timer1_fck",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_WKUP_TIMER1_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+static struct omap_hwmod_irq_info am33xx_timer2_irqs[] = {
+	{ .irq = 68 + OMAP_INTC_START, },
+	{ .irq = -1 },
+};
+
+static struct omap_hwmod am33xx_timer2_hwmod = {
+	.name		= "timer2",
+	.class		= &am33xx_timer_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.mpu_irqs	= am33xx_timer2_irqs,
+	.main_clk	= "timer2_fck",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_PER_TIMER2_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+static struct omap_hwmod_irq_info am33xx_timer3_irqs[] = {
+	{ .irq = 69 + OMAP_INTC_START, },
+	{ .irq = -1 },
+};
+
+static struct omap_hwmod am33xx_timer3_hwmod = {
+	.name		= "timer3",
+	.class		= &am33xx_timer_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.mpu_irqs	= am33xx_timer3_irqs,
+	.main_clk	= "timer3_fck",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_PER_TIMER3_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+static struct omap_hwmod_irq_info am33xx_timer4_irqs[] = {
+	{ .irq = 92 + OMAP_INTC_START, },
+	{ .irq = -1 },
+};
+
+static struct omap_hwmod am33xx_timer4_hwmod = {
+	.name		= "timer4",
+	.class		= &am33xx_timer_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.mpu_irqs	= am33xx_timer4_irqs,
+	.main_clk	= "timer4_fck",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_PER_TIMER4_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+static struct omap_hwmod_irq_info am33xx_timer5_irqs[] = {
+	{ .irq = 93 + OMAP_INTC_START, },
+	{ .irq = -1 },
+};
+
+static struct omap_hwmod am33xx_timer5_hwmod = {
+	.name		= "timer5",
+	.class		= &am33xx_timer_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.mpu_irqs	= am33xx_timer5_irqs,
+	.main_clk	= "timer5_fck",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_PER_TIMER5_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+static struct omap_hwmod_irq_info am33xx_timer6_irqs[] = {
+	{ .irq = 94 + OMAP_INTC_START, },
+	{ .irq = -1 },
+};
+
+static struct omap_hwmod am33xx_timer6_hwmod = {
+	.name		= "timer6",
+	.class		= &am33xx_timer_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.mpu_irqs	= am33xx_timer6_irqs,
+	.main_clk	= "timer6_fck",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_PER_TIMER6_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+static struct omap_hwmod_irq_info am33xx_timer7_irqs[] = {
+	{ .irq = 95 + OMAP_INTC_START, },
+	{ .irq = -1 },
+};
+
+static struct omap_hwmod am33xx_timer7_hwmod = {
+	.name		= "timer7",
+	.class		= &am33xx_timer_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.mpu_irqs	= am33xx_timer7_irqs,
+	.main_clk	= "timer7_fck",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_PER_TIMER7_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/* tpcc */
+static struct omap_hwmod_class am33xx_tpcc_hwmod_class = {
+	.name		= "tpcc",
+};
+
+static struct omap_hwmod_irq_info am33xx_tpcc_irqs[] = {
+	{ .name	= "edma0", .irq = 12 + OMAP_INTC_START, },
+	{ .name = "edma0_mperr", .irq = 13 + OMAP_INTC_START, },
+	{ .name	= "edma0_err", .irq = 14 + OMAP_INTC_START, },
+	{ .irq = -1 },
+};
+
+static struct omap_hwmod am33xx_tpcc_hwmod = {
+	.name		= "tpcc",
+	.class		= &am33xx_tpcc_hwmod_class,
+	.clkdm_name	= "l3_clkdm",
+	.mpu_irqs	= am33xx_tpcc_irqs,
+	.main_clk	= "l3_gclk",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_PER_TPCC_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+static struct omap_hwmod_class_sysconfig am33xx_tptc_sysc = {
+	.rev_offs	= 0x0,
+	.sysc_offs	= 0x10,
+	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
+			  SYSC_HAS_MIDLEMODE),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_SMART | MSTANDBY_FORCE),
+	.sysc_fields	= &omap_hwmod_sysc_type2,
+};
+
+/* 'tptc' class */
+static struct omap_hwmod_class am33xx_tptc_hwmod_class = {
+	.name		= "tptc",
+	.sysc		= &am33xx_tptc_sysc,
+};
+
+/* tptc0 */
+static struct omap_hwmod_irq_info am33xx_tptc0_irqs[] = {
+	{ .irq = 112 + OMAP_INTC_START, },
+	{ .irq = -1 },
+};
+
+static struct omap_hwmod am33xx_tptc0_hwmod = {
+	.name		= "tptc0",
+	.class		= &am33xx_tptc_hwmod_class,
+	.clkdm_name	= "l3_clkdm",
+	.mpu_irqs	= am33xx_tptc0_irqs,
+	.main_clk	= "l3_gclk",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_PER_TPTC0_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/* tptc1 */
+static struct omap_hwmod_irq_info am33xx_tptc1_irqs[] = {
+	{ .irq = 113 + OMAP_INTC_START, },
+	{ .irq = -1 },
+};
+
+static struct omap_hwmod am33xx_tptc1_hwmod = {
+	.name		= "tptc1",
+	.class		= &am33xx_tptc_hwmod_class,
+	.clkdm_name	= "l3_clkdm",
+	.mpu_irqs	= am33xx_tptc1_irqs,
+	.flags		= (HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY),
+	.main_clk	= "l3_gclk",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_PER_TPTC1_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/* tptc2 */
+static struct omap_hwmod_irq_info am33xx_tptc2_irqs[] = {
+	{ .irq = 114 + OMAP_INTC_START, },
+	{ .irq = -1 },
+};
+
+static struct omap_hwmod am33xx_tptc2_hwmod = {
+	.name		= "tptc2",
+	.class		= &am33xx_tptc_hwmod_class,
+	.clkdm_name	= "l3_clkdm",
+	.mpu_irqs	= am33xx_tptc2_irqs,
+	.flags		= (HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY),
+	.main_clk	= "l3_gclk",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_PER_TPTC2_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/* 'uart' class */
+static struct omap_hwmod_class_sysconfig uart_sysc = {
+	.rev_offs	= 0x50,
+	.sysc_offs	= 0x54,
+	.syss_offs	= 0x58,
+	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_ENAWAKEUP |
+			  SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			  SIDLE_SMART_WKUP),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class uart_class = {
+	.name		= "uart",
+	.sysc		= &uart_sysc,
+};
+
+/* uart1 */
+static struct omap_hwmod_dma_info uart1_edma_reqs[] = {
+	{ .name = "tx",	.dma_req = 26, },
+	{ .name = "rx",	.dma_req = 27, },
+	{ .dma_req = -1 }
+};
+
+static struct omap_hwmod_irq_info am33xx_uart1_irqs[] = {
+	{ .irq = 72 + OMAP_INTC_START, },
+	{ .irq = -1 },
+};
+
+static struct omap_hwmod am33xx_uart1_hwmod = {
+	.name		= "uart1",
+	.class		= &uart_class,
+	.clkdm_name	= "l4_wkup_clkdm",
+	.mpu_irqs	= am33xx_uart1_irqs,
+	.sdma_reqs	= uart1_edma_reqs,
+	.main_clk	= "dpll_per_m2_div4_wkupdm_ck",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_WKUP_UART0_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+static struct omap_hwmod_irq_info am33xx_uart2_irqs[] = {
+	{ .irq = 73 + OMAP_INTC_START, },
+	{ .irq = -1 },
+};
+
+static struct omap_hwmod am33xx_uart2_hwmod = {
+	.name		= "uart2",
+	.class		= &uart_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.mpu_irqs	= am33xx_uart2_irqs,
+	.sdma_reqs	= uart1_edma_reqs,
+	.main_clk	= "dpll_per_m2_div4_ck",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_PER_UART1_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/* uart3 */
+static struct omap_hwmod_dma_info uart3_edma_reqs[] = {
+	{ .name = "tx",	.dma_req = 30, },
+	{ .name = "rx",	.dma_req = 31, },
+	{ .dma_req = -1 }
+};
+
+static struct omap_hwmod_irq_info am33xx_uart3_irqs[] = {
+	{ .irq = 74 + OMAP_INTC_START, },
+	{ .irq = -1 },
+};
+
+static struct omap_hwmod am33xx_uart3_hwmod = {
+	.name		= "uart3",
+	.class		= &uart_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.mpu_irqs	= am33xx_uart3_irqs,
+	.sdma_reqs	= uart3_edma_reqs,
+	.main_clk	= "dpll_per_m2_div4_ck",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_PER_UART2_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+static struct omap_hwmod_irq_info am33xx_uart4_irqs[] = {
+	{ .irq = 44 + OMAP_INTC_START, },
+	{ .irq = -1 },
+};
+
+static struct omap_hwmod am33xx_uart4_hwmod = {
+	.name		= "uart4",
+	.class		= &uart_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.mpu_irqs	= am33xx_uart4_irqs,
+	.sdma_reqs	= uart1_edma_reqs,
+	.main_clk	= "dpll_per_m2_div4_ck",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_PER_UART3_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+static struct omap_hwmod_irq_info am33xx_uart5_irqs[] = {
+	{ .irq = 45 + OMAP_INTC_START, },
+	{ .irq = -1 },
+};
+
+static struct omap_hwmod am33xx_uart5_hwmod = {
+	.name		= "uart5",
+	.class		= &uart_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.mpu_irqs	= am33xx_uart5_irqs,
+	.sdma_reqs	= uart1_edma_reqs,
+	.main_clk	= "dpll_per_m2_div4_ck",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_PER_UART4_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+static struct omap_hwmod_irq_info am33xx_uart6_irqs[] = {
+	{ .irq = 46 + OMAP_INTC_START, },
+	{ .irq = -1 },
+};
+
+static struct omap_hwmod am33xx_uart6_hwmod = {
+	.name		= "uart6",
+	.class		= &uart_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.mpu_irqs	= am33xx_uart6_irqs,
+	.sdma_reqs	= uart1_edma_reqs,
+	.main_clk	= "dpll_per_m2_div4_ck",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_PER_UART5_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/* 'wd_timer' class */
+static struct omap_hwmod_class am33xx_wd_timer_hwmod_class = {
+	.name		= "wd_timer",
+};
+
+/*
+ * XXX: device.c file uses hardcoded name for watchdog timer
+ * driver "wd_timer2, so we are also using same name as of now...
+ */
+static struct omap_hwmod am33xx_wd_timer1_hwmod = {
+	.name		= "wd_timer2",
+	.class		= &am33xx_wd_timer_hwmod_class,
+	.clkdm_name	= "l4_wkup_clkdm",
+	.main_clk	= "wdt1_fck",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_WKUP_WDT1_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+/*
+ * 'usb_otg' class
+ * high-speed on-the-go universal serial bus (usb_otg) controller
+ */
+static struct omap_hwmod_class_sysconfig am33xx_usbhsotg_sysc = {
+	.rev_offs	= 0x0,
+	.sysc_offs	= 0x10,
+	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_MIDLEMODE),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			  MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type2,
+};
+
+static struct omap_hwmod_class am33xx_usbotg_class = {
+	.name		= "usbotg",
+	.sysc		= &am33xx_usbhsotg_sysc,
+};
+
+static struct omap_hwmod_irq_info am33xx_usbss_mpu_irqs[] = {
+	{ .name = "usbss-irq", .irq = 17 + OMAP_INTC_START, },
+	{ .name = "musb0-irq", .irq = 18 + OMAP_INTC_START, },
+	{ .name = "musb1-irq", .irq = 19 + OMAP_INTC_START, },
+	{ .irq = -1 + OMAP_INTC_START, },
+};
+
+static struct omap_hwmod am33xx_usbss_hwmod = {
+	.name		= "usb_otg_hs",
+	.class		= &am33xx_usbotg_class,
+	.clkdm_name	= "l3s_clkdm",
+	.mpu_irqs	= am33xx_usbss_mpu_irqs,
+	.flags		= HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY,
+	.main_clk	= "usbotg_fck",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM33XX_CM_PER_USB0_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
+
+/*
+ * Interfaces
+ */
+
+/* l4 fw -> emif fw */
+static struct omap_hwmod_ocp_if am33xx_l4_fw__emif_fw = {
+	.master		= &am33xx_l4_fw_hwmod,
+	.slave		= &am33xx_emif_fw_hwmod,
+	.clk		= "l4fw_gclk",
+	.user		= OCP_USER_MPU,
+};
+
+static struct omap_hwmod_addr_space am33xx_emif_addrs[] = {
+	{
+		.pa_start	= 0x4c000000,
+		.pa_end		= 0x4c000fff,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+/* l3 main -> emif */
+static struct omap_hwmod_ocp_if am33xx_l3_main__emif = {
+	.master		= &am33xx_l3_main_hwmod,
+	.slave		= &am33xx_emif_hwmod,
+	.clk		= "dpll_core_m4_ck",
+	.addr		= am33xx_emif_addrs,
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mpu -> l3 main */
+static struct omap_hwmod_ocp_if am33xx_mpu__l3_main = {
+	.master		= &am33xx_mpu_hwmod,
+	.slave		= &am33xx_l3_main_hwmod,
+	.clk		= "dpll_mpu_m2_ck",
+	.user		= OCP_USER_MPU,
+};
+
+/* l3 main -> l4 hs */
+static struct omap_hwmod_ocp_if am33xx_l3_main__l4_hs = {
+	.master		= &am33xx_l3_main_hwmod,
+	.slave		= &am33xx_l4_hs_hwmod,
+	.clk		= "l3s_gclk",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l3 main -> l3 s */
+static struct omap_hwmod_ocp_if am33xx_l3_main__l3_s = {
+	.master		= &am33xx_l3_main_hwmod,
+	.slave		= &am33xx_l3_s_hwmod,
+	.clk		= "l3s_gclk",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l3 s -> l4 per/ls */
+static struct omap_hwmod_ocp_if am33xx_l3_s__l4_ls = {
+	.master		= &am33xx_l3_s_hwmod,
+	.slave		= &am33xx_l4_ls_hwmod,
+	.clk		= "l3s_gclk",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l3 s -> l4 wkup */
+static struct omap_hwmod_ocp_if am33xx_l3_s__l4_wkup = {
+	.master		= &am33xx_l3_s_hwmod,
+	.slave		= &am33xx_l4_wkup_hwmod,
+	.clk		= "l3s_gclk",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l3 s -> l4 fw */
+static struct omap_hwmod_ocp_if am33xx_l3_s__l4_fw = {
+	.master		= &am33xx_l3_s_hwmod,
+	.slave		= &am33xx_l4_fw_hwmod,
+	.clk		= "l3s_gclk",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l3 main -> l3 instr */
+static struct omap_hwmod_ocp_if am33xx_l3_main__l3_instr = {
+	.master		= &am33xx_l3_main_hwmod,
+	.slave		= &am33xx_l3_instr_hwmod,
+	.clk		= "l3s_gclk",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mpu -> prcm */
+static struct omap_hwmod_ocp_if am33xx_mpu__prcm = {
+	.master		= &am33xx_mpu_hwmod,
+	.slave		= &am33xx_prcm_hwmod,
+	.clk		= "dpll_mpu_m2_ck",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l3 s -> l3 main*/
+static struct omap_hwmod_ocp_if am33xx_l3_s__l3_main = {
+	.master		= &am33xx_l3_s_hwmod,
+	.slave		= &am33xx_l3_main_hwmod,
+	.clk		= "l3s_gclk",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* pru-icss -> l3 main */
+static struct omap_hwmod_ocp_if am33xx_pruss__l3_main = {
+	.master		= &am33xx_pruss_hwmod,
+	.slave		= &am33xx_l3_main_hwmod,
+	.clk		= "l3_gclk",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* wkup m3 -> l4 wkup */
+static struct omap_hwmod_ocp_if am33xx_wkup_m3__l4_wkup = {
+	.master		= &am33xx_wkup_m3_hwmod,
+	.slave		= &am33xx_l4_wkup_hwmod,
+	.clk		= "dpll_core_m4_div2_ck",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* gfx -> l3 main */
+static struct omap_hwmod_ocp_if am33xx_gfx__l3_main = {
+	.master		= &am33xx_gfx_hwmod,
+	.slave		= &am33xx_l3_main_hwmod,
+	.clk		= "dpll_core_m4_ck",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4 wkup -> wkup m3 */
+static struct omap_hwmod_addr_space am33xx_wkup_m3_addrs[] = {
+	{
+		.name		= "umem",
+		.pa_start	= 0x44d00000,
+		.pa_end		= 0x44d00000 + SZ_16K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{
+		.name		= "dmem",
+		.pa_start	= 0x44d80000,
+		.pa_end		= 0x44d80000 + SZ_8K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if am33xx_l4_wkup__wkup_m3 = {
+	.master		= &am33xx_l4_wkup_hwmod,
+	.slave		= &am33xx_wkup_m3_hwmod,
+	.clk		= "dpll_core_m4_div2_ck",
+	.addr		= am33xx_wkup_m3_addrs,
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4 hs -> pru-icss */
+static struct omap_hwmod_addr_space am33xx_pruss_addrs[] = {
+	{
+		.pa_start	= 0x4a300000,
+		.pa_end		= 0x4a300000 + SZ_512K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if am33xx_l4_hs__pruss = {
+	.master		= &am33xx_l4_hs_hwmod,
+	.slave		= &am33xx_pruss_hwmod,
+	.clk		= "dpll_core_m4_ck",
+	.addr		= am33xx_pruss_addrs,
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l3 main -> gfx */
+static struct omap_hwmod_addr_space am33xx_gfx_addrs[] = {
+	{
+		.pa_start	= 0x56000000,
+		.pa_end		= 0x56000000 + SZ_16M - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if am33xx_l3_main__gfx = {
+	.master		= &am33xx_l3_main_hwmod,
+	.slave		= &am33xx_gfx_hwmod,
+	.clk		= "dpll_core_m4_ck",
+	.addr		= am33xx_gfx_addrs,
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4 wkup -> smartreflex0 */
+static struct omap_hwmod_addr_space am33xx_smartreflex0_addrs[] = {
+	{
+		.pa_start	= 0x44e37000,
+		.pa_end		= 0x44e37000 + SZ_4K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if am33xx_l4_wkup__smartreflex0 = {
+	.master		= &am33xx_l4_wkup_hwmod,
+	.slave		= &am33xx_smartreflex0_hwmod,
+	.clk		= "dpll_core_m4_div2_ck",
+	.addr		= am33xx_smartreflex0_addrs,
+	.user		= OCP_USER_MPU,
+};
+
+/* l4 wkup -> smartreflex1 */
+static struct omap_hwmod_addr_space am33xx_smartreflex1_addrs[] = {
+	{
+		.pa_start	= 0x44e39000,
+		.pa_end		= 0x44e39000 + SZ_4K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if am33xx_l4_wkup__smartreflex1 = {
+	.master		= &am33xx_l4_wkup_hwmod,
+	.slave		= &am33xx_smartreflex1_hwmod,
+	.clk		= "dpll_core_m4_div2_ck",
+	.addr		= am33xx_smartreflex1_addrs,
+	.user		= OCP_USER_MPU,
+};
+
+/* l4 wkup -> control */
+static struct omap_hwmod_addr_space am33xx_control_addrs[] = {
+	{
+		.pa_start	= 0x44e10000,
+		.pa_end		= 0x44e10000 + SZ_8K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if am33xx_l4_wkup__control = {
+	.master		= &am33xx_l4_wkup_hwmod,
+	.slave		= &am33xx_control_hwmod,
+	.clk		= "dpll_core_m4_div2_ck",
+	.addr		= am33xx_control_addrs,
+	.user		= OCP_USER_MPU,
+};
+
+/* l4 wkup -> rtc */
+static struct omap_hwmod_addr_space am33xx_rtc_addrs[] = {
+	{
+		.pa_start	= 0x44e3e000,
+		.pa_end		= 0x44e3e000 + SZ_4K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if am33xx_l4_wkup__rtc = {
+	.master		= &am33xx_l4_wkup_hwmod,
+	.slave		= &am33xx_rtc_hwmod,
+	.clk		= "clkdiv32k_ick",
+	.addr		= am33xx_rtc_addrs,
+	.user		= OCP_USER_MPU,
+};
+
+/* l4 per/ls -> DCAN0 */
+static struct omap_hwmod_addr_space am33xx_dcan0_addrs[] = {
+	{
+		.pa_start	= 0x481CC000,
+		.pa_end		= 0x481CC000 + SZ_4K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if am33xx_l4_per__dcan0 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_dcan0_hwmod,
+	.clk		= "l4ls_gclk",
+	.addr		= am33xx_dcan0_addrs,
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4 per/ls -> DCAN1 */
+static struct omap_hwmod_addr_space am33xx_dcan1_addrs[] = {
+	{
+		.pa_start	= 0x481D0000,
+		.pa_end		= 0x481D0000 + SZ_4K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if am33xx_l4_per__dcan1 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_dcan1_hwmod,
+	.clk		= "l4ls_gclk",
+	.addr		= am33xx_dcan1_addrs,
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4 per/ls -> GPIO2 */
+static struct omap_hwmod_addr_space am33xx_gpio1_addrs[] = {
+	{
+		.pa_start	= 0x4804C000,
+		.pa_end		= 0x4804C000 + SZ_4K - 1,
+		.flags		= ADDR_TYPE_RT,
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if am33xx_l4_per__gpio1 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_gpio1_hwmod,
+	.clk		= "l4ls_gclk",
+	.addr		= am33xx_gpio1_addrs,
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4 per/ls -> gpio3 */
+static struct omap_hwmod_addr_space am33xx_gpio2_addrs[] = {
+	{
+		.pa_start	= 0x481AC000,
+		.pa_end		= 0x481AC000 + SZ_4K - 1,
+		.flags		= ADDR_TYPE_RT,
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if am33xx_l4_per__gpio2 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_gpio2_hwmod,
+	.clk		= "l4ls_gclk",
+	.addr		= am33xx_gpio2_addrs,
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4 per/ls -> gpio4 */
+static struct omap_hwmod_addr_space am33xx_gpio3_addrs[] = {
+	{
+		.pa_start	= 0x481AE000,
+		.pa_end		= 0x481AE000 + SZ_4K - 1,
+		.flags		= ADDR_TYPE_RT,
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if am33xx_l4_per__gpio3 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_gpio3_hwmod,
+	.clk		= "l4ls_gclk",
+	.addr		= am33xx_gpio3_addrs,
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* L4 WKUP -> I2C1 */
+static struct omap_hwmod_addr_space am33xx_i2c1_addr_space[] = {
+	{
+		.pa_start	= 0x44E0B000,
+		.pa_end		= 0x44E0B000 + SZ_4K - 1,
+		.flags		= ADDR_TYPE_RT,
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if am33xx_l4_wkup__i2c1 = {
+	.master		= &am33xx_l4_wkup_hwmod,
+	.slave		= &am33xx_i2c1_hwmod,
+	.clk		= "dpll_core_m4_div2_ck",
+	.addr		= am33xx_i2c1_addr_space,
+	.user		= OCP_USER_MPU,
+};
+
+/* L4 WKUP -> GPIO1 */
+static struct omap_hwmod_addr_space am33xx_gpio0_addrs[] = {
+	{
+		.pa_start	= 0x44E07000,
+		.pa_end		= 0x44E07000 + SZ_4K - 1,
+		.flags		= ADDR_TYPE_RT,
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if am33xx_l4_wkup__gpio0 = {
+	.master		= &am33xx_l4_wkup_hwmod,
+	.slave		= &am33xx_gpio0_hwmod,
+	.clk		= "dpll_core_m4_div2_ck",
+	.addr		= am33xx_gpio0_addrs,
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* L4 WKUP -> ADC_TSC */
+static struct omap_hwmod_addr_space am33xx_adc_tsc_addrs[] = {
+	{
+		.pa_start	= 0x44E0D000,
+		.pa_end		= 0x44E0D000 + SZ_8K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if am33xx_l4_wkup__adc_tsc = {
+	.master		= &am33xx_l4_wkup_hwmod,
+	.slave		= &am33xx_adc_tsc_hwmod,
+	.clk		= "dpll_core_m4_div2_ck",
+	.addr		= am33xx_adc_tsc_addrs,
+	.user		= OCP_USER_MPU,
+};
+
+static struct omap_hwmod_addr_space am33xx_cpgmac0_addr_space[] = {
+	/* cpsw ss */
+	{
+		.pa_start	= 0x4a100000,
+		.pa_end		= 0x4a100000 + SZ_2K - 1,
+		.flags		= ADDR_TYPE_RT,
+	},
+	/* cpsw wr */
+	{
+		.pa_start	= 0x4a101200,
+		.pa_end		= 0x4a101200 + SZ_256 - 1,
+		.flags		= ADDR_TYPE_RT,
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if am33xx_l4_hs__cpgmac0 = {
+	.master		= &am33xx_l4_hs_hwmod,
+	.slave		= &am33xx_cpgmac0_hwmod,
+	.clk		= "cpsw_125mhz_gclk",
+	.addr		= am33xx_cpgmac0_addr_space,
+	.user		= OCP_USER_MPU,
+};
+
+static struct omap_hwmod_addr_space am33xx_elm_addr_space[] = {
+	{
+		.pa_start	= 0x48080000,
+		.pa_end		= 0x48080000 + SZ_8K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if am33xx_l4_ls__elm = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_elm_hwmod,
+	.clk		= "l4ls_gclk",
+	.addr		= am33xx_elm_addr_space,
+	.user		= OCP_USER_MPU,
+};
+
+/*
+ * Splitting the resources to handle access of PWMSS config space
+ * and module specific part independently
+ */
+static struct omap_hwmod_addr_space am33xx_ehrpwm0_addr_space[] = {
+	{
+		.pa_start	= 0x48300000,
+		.pa_end		= 0x48300000 + SZ_16 - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{
+		.pa_start	= 0x48300200,
+		.pa_end		= 0x48300200 + SZ_256 - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if am33xx_l4_ls__ehrpwm0 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_ehrpwm0_hwmod,
+	.clk		= "l4ls_gclk",
+	.addr		= am33xx_ehrpwm0_addr_space,
+	.user		= OCP_USER_MPU,
+};
+
+/*
+ * Splitting the resources to handle access of PWMSS config space
+ * and module specific part independently
+ */
+static struct omap_hwmod_addr_space am33xx_ehrpwm1_addr_space[] = {
+	{
+		.pa_start	= 0x48302000,
+		.pa_end		= 0x48302000 + SZ_16 - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{
+		.pa_start	= 0x48302200,
+		.pa_end		= 0x48302200 + SZ_256 - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if am33xx_l4_ls__ehrpwm1 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_ehrpwm1_hwmod,
+	.clk		= "l4ls_gclk",
+	.addr		= am33xx_ehrpwm1_addr_space,
+	.user		= OCP_USER_MPU,
+};
+
+/*
+ * Splitting the resources to handle access of PWMSS config space
+ * and module specific part independently
+ */
+static struct omap_hwmod_addr_space am33xx_ehrpwm2_addr_space[] = {
+	{
+		.pa_start	= 0x48304000,
+		.pa_end		= 0x48304000 + SZ_16 - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{
+		.pa_start	= 0x48304200,
+		.pa_end		= 0x48304200 + SZ_256 - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if am33xx_l4_ls__ehrpwm2 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_ehrpwm2_hwmod,
+	.clk		= "l4ls_gclk",
+	.addr		= am33xx_ehrpwm2_addr_space,
+	.user		= OCP_USER_MPU,
+};
+
+/*
+ * Splitting the resources to handle access of PWMSS config space
+ * and module specific part independently
+ */
+static struct omap_hwmod_addr_space am33xx_ecap0_addr_space[] = {
+	{
+		.pa_start	= 0x48300000,
+		.pa_end		= 0x48300000 + SZ_16 - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{
+		.pa_start	= 0x48300100,
+		.pa_end		= 0x48300100 + SZ_256 - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if am33xx_l4_ls__ecap0 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_ecap0_hwmod,
+	.clk		= "l4ls_gclk",
+	.addr		= am33xx_ecap0_addr_space,
+	.user		= OCP_USER_MPU,
+};
+
+/*
+ * Splitting the resources to handle access of PWMSS config space
+ * and module specific part independently
+ */
+static struct omap_hwmod_addr_space am33xx_ecap1_addr_space[] = {
+	{
+		.pa_start	= 0x48302000,
+		.pa_end		= 0x48302000 + SZ_16 - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{
+		.pa_start	= 0x48302100,
+		.pa_end		= 0x48302100 + SZ_256 - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if am33xx_l4_ls__ecap1 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_ecap1_hwmod,
+	.clk		= "l4ls_gclk",
+	.addr		= am33xx_ecap1_addr_space,
+	.user		= OCP_USER_MPU,
+};
+
+/*
+ * Splitting the resources to handle access of PWMSS config space
+ * and module specific part independently
+ */
+static struct omap_hwmod_addr_space am33xx_ecap2_addr_space[] = {
+	{
+		.pa_start	= 0x48304000,
+		.pa_end		= 0x48304000 + SZ_16 - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{
+		.pa_start	= 0x48304100,
+		.pa_end		= 0x48304100 + SZ_256 - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if am33xx_l4_ls__ecap2 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_ecap2_hwmod,
+	.clk		= "l4ls_gclk",
+	.addr		= am33xx_ecap2_addr_space,
+	.user		= OCP_USER_MPU,
+};
+
+/* l3s cfg -> gpmc */
+static struct omap_hwmod_addr_space am33xx_gpmc_addr_space[] = {
+	{
+		.pa_start	= 0x50000000,
+		.pa_end		= 0x50000000 + SZ_8K - 1,
+		.flags		= ADDR_TYPE_RT,
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if am33xx_l3_s__gpmc = {
+	.master		= &am33xx_l3_s_hwmod,
+	.slave		= &am33xx_gpmc_hwmod,
+	.clk		= "l3s_gclk",
+	.addr		= am33xx_gpmc_addr_space,
+	.user		= OCP_USER_MPU,
+};
+
+/* i2c2 */
+static struct omap_hwmod_addr_space am33xx_i2c2_addr_space[] = {
+	{
+		.pa_start	= 0x4802A000,
+		.pa_end		= 0x4802A000 + SZ_4K - 1,
+		.flags		= ADDR_TYPE_RT,
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if am33xx_l4_per__i2c2 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_i2c2_hwmod,
+	.clk		= "l4ls_gclk",
+	.addr		= am33xx_i2c2_addr_space,
+	.user		= OCP_USER_MPU,
+};
+
+static struct omap_hwmod_addr_space am33xx_i2c3_addr_space[] = {
+	{
+		.pa_start	= 0x4819C000,
+		.pa_end		= 0x4819C000 + SZ_4K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if am33xx_l4_per__i2c3 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_i2c3_hwmod,
+	.clk		= "l4ls_gclk",
+	.addr		= am33xx_i2c3_addr_space,
+	.user		= OCP_USER_MPU,
+};
+
+static struct omap_hwmod_addr_space am33xx_lcdc_addr_space[] = {
+	{
+		.pa_start	= 0x4830E000,
+		.pa_end		= 0x4830E000 + SZ_8K - 1,
+		.flags		= ADDR_TYPE_RT,
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if am33xx_l3_main__lcdc = {
+	.master		= &am33xx_l3_main_hwmod,
+	.slave		= &am33xx_lcdc_hwmod,
+	.clk		= "dpll_core_m4_ck",
+	.addr		= am33xx_lcdc_addr_space,
+	.user		= OCP_USER_MPU,
+};
+
+static struct omap_hwmod_addr_space am33xx_mailbox_addrs[] = {
+	{
+		.pa_start	= 0x480C8000,
+		.pa_end		= 0x480C8000 + (SZ_4K - 1),
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+/* l4 ls -> mailbox */
+static struct omap_hwmod_ocp_if am33xx_l4_per__mailbox = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_mailbox_hwmod,
+	.clk		= "l4ls_gclk",
+	.addr		= am33xx_mailbox_addrs,
+	.user		= OCP_USER_MPU,
+};
+
+/* l4 ls -> spinlock */
+static struct omap_hwmod_addr_space am33xx_spinlock_addrs[] = {
+	{
+		.pa_start	= 0x480Ca000,
+		.pa_end		= 0x480Ca000 + SZ_4K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if am33xx_l4_ls__spinlock = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_spinlock_hwmod,
+	.clk		= "l4ls_gclk",
+	.addr		= am33xx_spinlock_addrs,
+	.user		= OCP_USER_MPU,
+};
+
+/* l4 ls -> mcasp0 */
+static struct omap_hwmod_addr_space am33xx_mcasp0_addr_space[] = {
+	{
+		.pa_start	= 0x48038000,
+		.pa_end		= 0x48038000 + SZ_8K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if am33xx_l4_ls__mcasp0 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_mcasp0_hwmod,
+	.clk		= "l4ls_gclk",
+	.addr		= am33xx_mcasp0_addr_space,
+	.user		= OCP_USER_MPU,
+};
+
+/* l3 s -> mcasp0 data */
+static struct omap_hwmod_addr_space am33xx_mcasp0_data_addr_space[] = {
+	{
+		.pa_start	= 0x46000000,
+		.pa_end		= 0x46000000 + SZ_4M - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if am33xx_l3_s__mcasp0_data = {
+	.master		= &am33xx_l3_s_hwmod,
+	.slave		= &am33xx_mcasp0_hwmod,
+	.clk		= "l3s_gclk",
+	.addr		= am33xx_mcasp0_data_addr_space,
+	.user		= OCP_USER_SDMA,
+};
+
+/* l4 ls -> mcasp1 */
+static struct omap_hwmod_addr_space am33xx_mcasp1_addr_space[] = {
+	{
+		.pa_start	= 0x4803C000,
+		.pa_end		= 0x4803C000 + SZ_8K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if am33xx_l4_ls__mcasp1 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_mcasp1_hwmod,
+	.clk		= "l4ls_gclk",
+	.addr		= am33xx_mcasp1_addr_space,
+	.user		= OCP_USER_MPU,
+};
+
+/* l3 s -> mcasp1 data */
+static struct omap_hwmod_addr_space am33xx_mcasp1_data_addr_space[] = {
+	{
+		.pa_start	= 0x46400000,
+		.pa_end		= 0x46400000 + SZ_4M - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if am33xx_l3_s__mcasp1_data = {
+	.master		= &am33xx_l3_s_hwmod,
+	.slave		= &am33xx_mcasp1_hwmod,
+	.clk		= "l3s_gclk",
+	.addr		= am33xx_mcasp1_data_addr_space,
+	.user		= OCP_USER_SDMA,
+};
+
+/* l4 ls -> mmc0 */
+static struct omap_hwmod_addr_space am33xx_mmc0_addr_space[] = {
+	{
+		.pa_start	= 0x48060100,
+		.pa_end		= 0x48060100 + SZ_4K - 1,
+		.flags		= ADDR_TYPE_RT,
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if am33xx_l4_ls__mmc0 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_mmc0_hwmod,
+	.clk		= "l4ls_gclk",
+	.addr		= am33xx_mmc0_addr_space,
+	.user		= OCP_USER_MPU,
+};
+
+/* l4 ls -> mmc1 */
+static struct omap_hwmod_addr_space am33xx_mmc1_addr_space[] = {
+	{
+		.pa_start	= 0x481d8100,
+		.pa_end		= 0x481d8100 + SZ_4K - 1,
+		.flags		= ADDR_TYPE_RT,
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if am33xx_l4_ls__mmc1 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_mmc1_hwmod,
+	.clk		= "l4ls_gclk",
+	.addr		= am33xx_mmc1_addr_space,
+	.user		= OCP_USER_MPU,
+};
+
+/* l3 s -> mmc2 */
+static struct omap_hwmod_addr_space am33xx_mmc2_addr_space[] = {
+	{
+		.pa_start	= 0x47810100,
+		.pa_end		= 0x47810100 + SZ_64K - 1,
+		.flags		= ADDR_TYPE_RT,
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if am33xx_l3_s__mmc2 = {
+	.master		= &am33xx_l3_s_hwmod,
+	.slave		= &am33xx_mmc2_hwmod,
+	.clk		= "l3s_gclk",
+	.addr		= am33xx_mmc2_addr_space,
+	.user		= OCP_USER_MPU,
+};
+
+/* l4 ls -> mcspi0 */
+static struct omap_hwmod_addr_space am33xx_mcspi0_addr_space[] = {
+	{
+		.pa_start	= 0x48030000,
+		.pa_end		= 0x48030000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT,
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if am33xx_l4_ls__mcspi0 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_spi0_hwmod,
+	.clk		= "l4ls_gclk",
+	.addr		= am33xx_mcspi0_addr_space,
+	.user		= OCP_USER_MPU,
+};
+
+/* l4 ls -> mcspi1 */
+static struct omap_hwmod_addr_space am33xx_mcspi1_addr_space[] = {
+	{
+		.pa_start	= 0x481A0000,
+		.pa_end		= 0x481A0000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT,
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if am33xx_l4_ls__mcspi1 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_spi1_hwmod,
+	.clk		= "l4ls_gclk",
+	.addr		= am33xx_mcspi1_addr_space,
+	.user		= OCP_USER_MPU,
+};
+
+/* l4 wkup -> timer1 */
+static struct omap_hwmod_addr_space am33xx_timer1_addr_space[] = {
+	{
+		.pa_start	= 0x44E31000,
+		.pa_end		= 0x44E31000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if am33xx_l4_wkup__timer1 = {
+	.master		= &am33xx_l4_wkup_hwmod,
+	.slave		= &am33xx_timer1_hwmod,
+	.clk		= "dpll_core_m4_div2_ck",
+	.addr		= am33xx_timer1_addr_space,
+	.user		= OCP_USER_MPU,
+};
+
+/* l4 per -> timer2 */
+static struct omap_hwmod_addr_space am33xx_timer2_addr_space[] = {
+	{
+		.pa_start	= 0x48040000,
+		.pa_end		= 0x48040000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if am33xx_l4_ls__timer2 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_timer2_hwmod,
+	.clk		= "l4ls_gclk",
+	.addr		= am33xx_timer2_addr_space,
+	.user		= OCP_USER_MPU,
+};
+
+/* l4 per -> timer3 */
+static struct omap_hwmod_addr_space am33xx_timer3_addr_space[] = {
+	{
+		.pa_start	= 0x48042000,
+		.pa_end		= 0x48042000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if am33xx_l4_ls__timer3 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_timer3_hwmod,
+	.clk		= "l4ls_gclk",
+	.addr		= am33xx_timer3_addr_space,
+	.user		= OCP_USER_MPU,
+};
+
+/* l4 per -> timer4 */
+static struct omap_hwmod_addr_space am33xx_timer4_addr_space[] = {
+	{
+		.pa_start	= 0x48044000,
+		.pa_end		= 0x48044000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if am33xx_l4_ls__timer4 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_timer4_hwmod,
+	.clk		= "l4ls_gclk",
+	.addr		= am33xx_timer4_addr_space,
+	.user		= OCP_USER_MPU,
+};
+
+/* l4 per -> timer5 */
+static struct omap_hwmod_addr_space am33xx_timer5_addr_space[] = {
+	{
+		.pa_start	= 0x48046000,
+		.pa_end		= 0x48046000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if am33xx_l4_ls__timer5 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_timer5_hwmod,
+	.clk		= "l4ls_gclk",
+	.addr		= am33xx_timer5_addr_space,
+	.user		= OCP_USER_MPU,
+};
+
+/* l4 per -> timer6 */
+static struct omap_hwmod_addr_space am33xx_timer6_addr_space[] = {
+	{
+		.pa_start	= 0x48048000,
+		.pa_end		= 0x48048000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if am33xx_l4_ls__timer6 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_timer6_hwmod,
+	.clk		= "l4ls_gclk",
+	.addr		= am33xx_timer6_addr_space,
+	.user		= OCP_USER_MPU,
+};
+
+/* l4 per -> timer7 */
+static struct omap_hwmod_addr_space am33xx_timer7_addr_space[] = {
+	{
+		.pa_start	= 0x4804A000,
+		.pa_end		= 0x4804A000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if am33xx_l4_ls__timer7 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_timer7_hwmod,
+	.clk		= "l4ls_gclk",
+	.addr		= am33xx_timer7_addr_space,
+	.user		= OCP_USER_MPU,
+};
+
+/* l3 main -> tpcc */
+static struct omap_hwmod_addr_space am33xx_tpcc_addr_space[] = {
+	{
+		.pa_start	= 0x49000000,
+		.pa_end		= 0x49000000 + SZ_32K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if am33xx_l3_main__tpcc = {
+	.master		= &am33xx_l3_main_hwmod,
+	.slave		= &am33xx_tpcc_hwmod,
+	.clk		= "l3_gclk",
+	.addr		= am33xx_tpcc_addr_space,
+	.user		= OCP_USER_MPU,
+};
+
+/* l3 main -> tpcc0 */
+static struct omap_hwmod_addr_space am33xx_tptc0_addr_space[] = {
+	{
+		.pa_start	= 0x49800000,
+		.pa_end		= 0x49800000 + SZ_8K - 1,
+		.flags		= ADDR_TYPE_RT,
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if am33xx_l3_main__tptc0 = {
+	.master		= &am33xx_l3_main_hwmod,
+	.slave		= &am33xx_tptc0_hwmod,
+	.clk		= "l3_gclk",
+	.addr		= am33xx_tptc0_addr_space,
+	.user		= OCP_USER_MPU,
+};
+
+/* l3 main -> tpcc1 */
+static struct omap_hwmod_addr_space am33xx_tptc1_addr_space[] = {
+	{
+		.pa_start	= 0x49900000,
+		.pa_end		= 0x49900000 + SZ_8K - 1,
+		.flags		= ADDR_TYPE_RT,
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if am33xx_l3_main__tptc1 = {
+	.master		= &am33xx_l3_main_hwmod,
+	.slave		= &am33xx_tptc1_hwmod,
+	.clk		= "l3_gclk",
+	.addr		= am33xx_tptc1_addr_space,
+	.user		= OCP_USER_MPU,
+};
+
+/* l3 main -> tpcc2 */
+static struct omap_hwmod_addr_space am33xx_tptc2_addr_space[] = {
+	{
+		.pa_start	= 0x49a00000,
+		.pa_end		= 0x49a00000 + SZ_8K - 1,
+		.flags		= ADDR_TYPE_RT,
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if am33xx_l3_main__tptc2 = {
+	.master		= &am33xx_l3_main_hwmod,
+	.slave		= &am33xx_tptc2_hwmod,
+	.clk		= "l3_gclk",
+	.addr		= am33xx_tptc2_addr_space,
+	.user		= OCP_USER_MPU,
+};
+
+/* l4 wkup -> uart1 */
+static struct omap_hwmod_addr_space am33xx_uart1_addr_space[] = {
+	{
+		.pa_start	= 0x44E09000,
+		.pa_end		= 0x44E09000 + SZ_8K - 1,
+		.flags		= ADDR_TYPE_RT,
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if am33xx_l4_wkup__uart1 = {
+	.master		= &am33xx_l4_wkup_hwmod,
+	.slave		= &am33xx_uart1_hwmod,
+	.clk		= "dpll_core_m4_div2_ck",
+	.addr		= am33xx_uart1_addr_space,
+	.user		= OCP_USER_MPU,
+};
+
+/* l4 ls -> uart2 */
+static struct omap_hwmod_addr_space am33xx_uart2_addr_space[] = {
+	{
+		.pa_start	= 0x48022000,
+		.pa_end		= 0x48022000 + SZ_8K - 1,
+		.flags		= ADDR_TYPE_RT,
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if am33xx_l4_ls__uart2 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_uart2_hwmod,
+	.clk		= "l4ls_gclk",
+	.addr		= am33xx_uart2_addr_space,
+	.user		= OCP_USER_MPU,
+};
+
+/* l4 ls -> uart3 */
+static struct omap_hwmod_addr_space am33xx_uart3_addr_space[] = {
+	{
+		.pa_start	= 0x48024000,
+		.pa_end		= 0x48024000 + SZ_8K - 1,
+		.flags		= ADDR_TYPE_RT,
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if am33xx_l4_ls__uart3 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_uart3_hwmod,
+	.clk		= "l4ls_gclk",
+	.addr		= am33xx_uart3_addr_space,
+	.user		= OCP_USER_MPU,
+};
+
+/* l4 ls -> uart4 */
+static struct omap_hwmod_addr_space am33xx_uart4_addr_space[] = {
+	{
+		.pa_start	= 0x481A6000,
+		.pa_end		= 0x481A6000 + SZ_8K - 1,
+		.flags		= ADDR_TYPE_RT,
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if am33xx_l4_ls__uart4 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_uart4_hwmod,
+	.clk		= "l4ls_gclk",
+	.addr		= am33xx_uart4_addr_space,
+	.user		= OCP_USER_MPU,
+};
+
+/* l4 ls -> uart5 */
+static struct omap_hwmod_addr_space am33xx_uart5_addr_space[] = {
+	{
+		.pa_start	= 0x481A8000,
+		.pa_end		= 0x481A8000 + SZ_8K - 1,
+		.flags		= ADDR_TYPE_RT,
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if am33xx_l4_ls__uart5 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_uart5_hwmod,
+	.clk		= "l4ls_gclk",
+	.addr		= am33xx_uart5_addr_space,
+	.user		= OCP_USER_MPU,
+};
+
+/* l4 ls -> uart6 */
+static struct omap_hwmod_addr_space am33xx_uart6_addr_space[] = {
+	{
+		.pa_start	= 0x481aa000,
+		.pa_end		= 0x481aa000 + SZ_8K - 1,
+		.flags		= ADDR_TYPE_RT,
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if am33xx_l4_ls__uart6 = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_uart6_hwmod,
+	.clk		= "l4ls_gclk",
+	.addr		= am33xx_uart6_addr_space,
+	.user		= OCP_USER_MPU,
+};
+
+/* l4 wkup -> wd_timer1 */
+static struct omap_hwmod_addr_space am33xx_wd_timer1_addrs[] = {
+	{
+		.pa_start	= 0x44e35000,
+		.pa_end		= 0x44e35000 + SZ_4K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if am33xx_l4_wkup__wd_timer1 = {
+	.master		= &am33xx_l4_wkup_hwmod,
+	.slave		= &am33xx_wd_timer1_hwmod,
+	.clk		= "dpll_core_m4_div2_ck",
+	.addr		= am33xx_wd_timer1_addrs,
+	.user		= OCP_USER_MPU,
+};
+
+/* usbss */
+/* l3 s -> USBSS interface */
+static struct omap_hwmod_addr_space am33xx_usbss_addr_space[] = {
+	{
+		.name		= "usbss",
+		.pa_start	= 0x47400000,
+		.pa_end		= 0x47400000 + SZ_4K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{
+		.name		= "musb0",
+		.pa_start	= 0x47401000,
+		.pa_end		= 0x47401000 + SZ_2K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{
+		.name		= "musb1",
+		.pa_start	= 0x47401800,
+		.pa_end		= 0x47401800 + SZ_2K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if am33xx_l3_s__usbss = {
+	.master		= &am33xx_l3_s_hwmod,
+	.slave		= &am33xx_usbss_hwmod,
+	.clk		= "l3s_gclk",
+	.addr		= am33xx_usbss_addr_space,
+	.user		= OCP_USER_MPU,
+	.flags		= OCPIF_SWSUP_IDLE,
+};
+
+static struct omap_hwmod_ocp_if *am33xx_hwmod_ocp_ifs[] __initdata = {
+	&am33xx_l4_fw__emif_fw,
+	&am33xx_l3_main__emif,
+	&am33xx_mpu__l3_main,
+	&am33xx_mpu__prcm,
+	&am33xx_l3_s__l4_ls,
+	&am33xx_l3_s__l4_wkup,
+	&am33xx_l3_s__l4_fw,
+	&am33xx_l3_main__l4_hs,
+	&am33xx_l3_main__l3_s,
+	&am33xx_l3_main__l3_instr,
+	&am33xx_l3_main__gfx,
+	&am33xx_l3_s__l3_main,
+	&am33xx_pruss__l3_main,
+	&am33xx_wkup_m3__l4_wkup,
+	&am33xx_gfx__l3_main,
+	&am33xx_l4_wkup__wkup_m3,
+	&am33xx_l4_wkup__control,
+	&am33xx_l4_wkup__smartreflex0,
+	&am33xx_l4_wkup__smartreflex1,
+	&am33xx_l4_wkup__uart1,
+	&am33xx_l4_wkup__timer1,
+	&am33xx_l4_wkup__rtc,
+	&am33xx_l4_wkup__i2c1,
+	&am33xx_l4_wkup__gpio0,
+	&am33xx_l4_wkup__adc_tsc,
+	&am33xx_l4_wkup__wd_timer1,
+	&am33xx_l4_hs__pruss,
+	&am33xx_l4_per__dcan0,
+	&am33xx_l4_per__dcan1,
+	&am33xx_l4_per__gpio1,
+	&am33xx_l4_per__gpio2,
+	&am33xx_l4_per__gpio3,
+	&am33xx_l4_per__i2c2,
+	&am33xx_l4_per__i2c3,
+	&am33xx_l4_per__mailbox,
+	&am33xx_l4_ls__mcasp0,
+	&am33xx_l3_s__mcasp0_data,
+	&am33xx_l4_ls__mcasp1,
+	&am33xx_l3_s__mcasp1_data,
+	&am33xx_l4_ls__mmc0,
+	&am33xx_l4_ls__mmc1,
+	&am33xx_l3_s__mmc2,
+	&am33xx_l4_ls__timer2,
+	&am33xx_l4_ls__timer3,
+	&am33xx_l4_ls__timer4,
+	&am33xx_l4_ls__timer5,
+	&am33xx_l4_ls__timer6,
+	&am33xx_l4_ls__timer7,
+	&am33xx_l3_main__tpcc,
+	&am33xx_l4_ls__uart2,
+	&am33xx_l4_ls__uart3,
+	&am33xx_l4_ls__uart4,
+	&am33xx_l4_ls__uart5,
+	&am33xx_l4_ls__uart6,
+	&am33xx_l4_ls__spinlock,
+	&am33xx_l4_ls__elm,
+	&am33xx_l4_ls__ehrpwm0,
+	&am33xx_l4_ls__ehrpwm1,
+	&am33xx_l4_ls__ehrpwm2,
+	&am33xx_l4_ls__ecap0,
+	&am33xx_l4_ls__ecap1,
+	&am33xx_l4_ls__ecap2,
+	&am33xx_l3_s__gpmc,
+	&am33xx_l3_main__lcdc,
+	&am33xx_l4_ls__mcspi0,
+	&am33xx_l4_ls__mcspi1,
+	&am33xx_l3_main__tptc0,
+	&am33xx_l3_main__tptc1,
+	&am33xx_l3_main__tptc2,
+	&am33xx_l3_s__usbss,
+	&am33xx_l4_hs__cpgmac0,
+	NULL,
+};
+
+int __init am33xx_hwmod_init(void)
+{
+	omap_hwmod_init();
+	return omap_hwmod_register_links(am33xx_hwmod_ocp_ifs);
+}
diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
index ce7e606..94b38af 100644
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
@@ -15,26 +15,26 @@
  * XXX these should be marked initdata for multi-OMAP kernels
  */
 #include <linux/power/smartreflex.h>
+#include <linux/platform_data/gpio-omap.h>
 
 #include <plat/omap_hwmod.h>
-#include <mach/irqs.h>
-#include <plat/cpu.h>
 #include <plat/dma.h>
 #include <plat/serial.h>
-#include <plat/l3_3xxx.h>
-#include <plat/l4_3xxx.h>
+#include "l3_3xxx.h"
+#include "l4_3xxx.h"
 #include <plat/i2c.h>
-#include <plat/gpio.h>
 #include <plat/mmc.h>
-#include <plat/mcbsp.h>
-#include <plat/mcspi.h>
+#include <linux/platform_data/asoc-ti-mcbsp.h>
+#include <linux/platform_data/spi-omap2-mcspi.h>
 #include <plat/dmtimer.h>
 
+#include "am35xx.h"
+
+#include "soc.h"
 #include "omap_hwmod_common_data.h"
 #include "prm-regbits-34xx.h"
 #include "cm-regbits-34xx.h"
 #include "wd_timer.h"
-#include <mach/am35xx.h>
 
 /*
  * OMAP3xxx hardware module integration data
@@ -51,9 +51,9 @@
 
 /* L3 */
 static struct omap_hwmod_irq_info omap3xxx_l3_main_irqs[] = {
-	{ .irq = INT_34XX_L3_DBG_IRQ },
-	{ .irq = INT_34XX_L3_APP_IRQ },
-	{ .irq = -1 }
+	{ .irq = 9 + OMAP_INTC_START, },
+	{ .irq = 10 + OMAP_INTC_START, },
+	{ .irq = -1 },
 };
 
 static struct omap_hwmod omap3xxx_l3_main_hwmod = {
@@ -364,8 +364,8 @@ static struct omap_hwmod omap3xxx_timer11_hwmod = {
 
 /* timer12 */
 static struct omap_hwmod_irq_info omap3xxx_timer12_mpu_irqs[] = {
-	{ .irq = 95, },
-	{ .irq = -1 }
+	{ .irq = 95 + OMAP_INTC_START, },
+	{ .irq = -1 },
 };
 
 static struct omap_hwmod omap3xxx_timer12_hwmod = {
@@ -499,8 +499,8 @@ static struct omap_hwmod omap3xxx_uart3_hwmod = {
 
 /* UART4 */
 static struct omap_hwmod_irq_info uart4_mpu_irqs[] = {
-	{ .irq = INT_36XX_UART4_IRQ, },
-	{ .irq = -1 }
+	{ .irq = 80 + OMAP_INTC_START, },
+	{ .irq = -1 },
 };
 
 static struct omap_hwmod_dma_info uart4_sdma_reqs[] = {
@@ -527,8 +527,8 @@ static struct omap_hwmod omap36xx_uart4_hwmod = {
 };
 
 static struct omap_hwmod_irq_info am35xx_uart4_mpu_irqs[] = {
-	{ .irq = INT_35XX_UART4_IRQ, },
-	{ .irq = -1 }
+	{ .irq = 84 + OMAP_INTC_START, },
+	{ .irq = -1 },
 };
 
 static struct omap_hwmod_dma_info am35xx_uart4_sdma_reqs[] = {
@@ -683,8 +683,8 @@ static struct omap_hwmod_class omap3xxx_dsi_hwmod_class = {
 };
 
 static struct omap_hwmod_irq_info omap3xxx_dsi1_irqs[] = {
-	{ .irq = 25 },
-	{ .irq = -1 }
+	{ .irq = 25 + OMAP_INTC_START, },
+	{ .irq = -1 },
 };
 
 /* dss_dsi1 */
@@ -813,8 +813,8 @@ static struct omap_i2c_dev_attr i2c3_dev_attr = {
 };
 
 static struct omap_hwmod_irq_info i2c3_mpu_irqs[] = {
-	{ .irq = INT_34XX_I2C3_IRQ, },
-	{ .irq = -1 }
+	{ .irq = 61 + OMAP_INTC_START, },
+	{ .irq = -1 },
 };
 
 static struct omap_hwmod_dma_info i2c3_sdma_reqs[] = {
@@ -972,8 +972,8 @@ static struct omap_hwmod omap3xxx_gpio4_hwmod = {
 
 /* gpio5 */
 static struct omap_hwmod_irq_info omap3xxx_gpio5_irqs[] = {
-	{ .irq = 33 }, /* INT_34XX_GPIO_BANK5 */
-	{ .irq = -1 }
+	{ .irq = 33 + OMAP_INTC_START, }, /* INT_34XX_GPIO_BANK5 */
+	{ .irq = -1 },
 };
 
 static struct omap_hwmod_opt_clk gpio5_opt_clks[] = {
@@ -1002,8 +1002,8 @@ static struct omap_hwmod omap3xxx_gpio5_hwmod = {
 
 /* gpio6 */
 static struct omap_hwmod_irq_info omap3xxx_gpio6_irqs[] = {
-	{ .irq = 34 }, /* INT_34XX_GPIO_BANK6 */
-	{ .irq = -1 }
+	{ .irq = 34 + OMAP_INTC_START, }, /* INT_34XX_GPIO_BANK6 */
+	{ .irq = -1 },
 };
 
 static struct omap_hwmod_opt_clk gpio6_opt_clks[] = {
@@ -1107,10 +1107,10 @@ static struct omap_hwmod_opt_clk mcbsp234_opt_clks[] = {
 
 /* mcbsp1 */
 static struct omap_hwmod_irq_info omap3xxx_mcbsp1_irqs[] = {
-	{ .name = "common", .irq = 16 },
-	{ .name = "tx", .irq = 59 },
-	{ .name = "rx", .irq = 60 },
-	{ .irq = -1 }
+	{ .name = "common", .irq = 16 + OMAP_INTC_START, },
+	{ .name = "tx", .irq = 59 + OMAP_INTC_START, },
+	{ .name = "rx", .irq = 60 + OMAP_INTC_START, },
+	{ .irq = -1 },
 };
 
 static struct omap_hwmod omap3xxx_mcbsp1_hwmod = {
@@ -1134,10 +1134,10 @@ static struct omap_hwmod omap3xxx_mcbsp1_hwmod = {
 
 /* mcbsp2 */
 static struct omap_hwmod_irq_info omap3xxx_mcbsp2_irqs[] = {
-	{ .name = "common", .irq = 17 },
-	{ .name = "tx", .irq = 62 },
-	{ .name = "rx", .irq = 63 },
-	{ .irq = -1 }
+	{ .name = "common", .irq = 17 + OMAP_INTC_START, },
+	{ .name = "tx", .irq = 62 + OMAP_INTC_START, },
+	{ .name = "rx", .irq = 63 + OMAP_INTC_START, },
+	{ .irq = -1 },
 };
 
 static struct omap_mcbsp_dev_attr omap34xx_mcbsp2_dev_attr = {
@@ -1166,10 +1166,10 @@ static struct omap_hwmod omap3xxx_mcbsp2_hwmod = {
 
 /* mcbsp3 */
 static struct omap_hwmod_irq_info omap3xxx_mcbsp3_irqs[] = {
-	{ .name = "common", .irq = 22 },
-	{ .name = "tx", .irq = 89 },
-	{ .name = "rx", .irq = 90 },
-	{ .irq = -1 }
+	{ .name = "common", .irq = 22 + OMAP_INTC_START, },
+	{ .name = "tx", .irq = 89 + OMAP_INTC_START, },
+	{ .name = "rx", .irq = 90 + OMAP_INTC_START, },
+	{ .irq = -1 },
 };
 
 static struct omap_mcbsp_dev_attr omap34xx_mcbsp3_dev_attr = {
@@ -1198,10 +1198,10 @@ static struct omap_hwmod omap3xxx_mcbsp3_hwmod = {
 
 /* mcbsp4 */
 static struct omap_hwmod_irq_info omap3xxx_mcbsp4_irqs[] = {
-	{ .name = "common", .irq = 23 },
-	{ .name = "tx", .irq = 54 },
-	{ .name = "rx", .irq = 55 },
-	{ .irq = -1 }
+	{ .name = "common", .irq = 23 + OMAP_INTC_START, },
+	{ .name = "tx", .irq = 54 + OMAP_INTC_START, },
+	{ .name = "rx", .irq = 55 + OMAP_INTC_START, },
+	{ .irq = -1 },
 };
 
 static struct omap_hwmod_dma_info omap3xxx_mcbsp4_sdma_chs[] = {
@@ -1231,10 +1231,10 @@ static struct omap_hwmod omap3xxx_mcbsp4_hwmod = {
 
 /* mcbsp5 */
 static struct omap_hwmod_irq_info omap3xxx_mcbsp5_irqs[] = {
-	{ .name = "common", .irq = 27 },
-	{ .name = "tx", .irq = 81 },
-	{ .name = "rx", .irq = 82 },
-	{ .irq = -1 }
+	{ .name = "common", .irq = 27 + OMAP_INTC_START, },
+	{ .name = "tx", .irq = 81 + OMAP_INTC_START, },
+	{ .name = "rx", .irq = 82 + OMAP_INTC_START, },
+	{ .irq = -1 },
 };
 
 static struct omap_hwmod_dma_info omap3xxx_mcbsp5_sdma_chs[] = {
@@ -1276,8 +1276,8 @@ static struct omap_hwmod_class omap3xxx_mcbsp_sidetone_hwmod_class = {
 
 /* mcbsp2_sidetone */
 static struct omap_hwmod_irq_info omap3xxx_mcbsp2_sidetone_irqs[] = {
-	{ .name = "irq", .irq = 4 },
-	{ .irq = -1 }
+	{ .name = "irq", .irq = 4 + OMAP_INTC_START, },
+	{ .irq = -1 },
 };
 
 static struct omap_hwmod omap3xxx_mcbsp2_sidetone_hwmod = {
@@ -1298,8 +1298,8 @@ static struct omap_hwmod omap3xxx_mcbsp2_sidetone_hwmod = {
 
 /* mcbsp3_sidetone */
 static struct omap_hwmod_irq_info omap3xxx_mcbsp3_sidetone_irqs[] = {
-	{ .name = "irq", .irq = 5 },
-	{ .irq = -1 }
+	{ .name = "irq", .irq = 5 + OMAP_INTC_START, },
+	{ .irq = -1 },
 };
 
 static struct omap_hwmod omap3xxx_mcbsp3_sidetone_hwmod = {
@@ -1361,8 +1361,8 @@ static struct omap_smartreflex_dev_attr sr1_dev_attr = {
 };
 
 static struct omap_hwmod_irq_info omap3_smartreflex_mpu_irqs[] = {
-	{ .irq = 18 },
-	{ .irq = -1 }
+	{ .irq = 18 + OMAP_INTC_START, },
+	{ .irq = -1 },
 };
 
 static struct omap_hwmod omap34xx_sr1_hwmod = {
@@ -1406,8 +1406,8 @@ static struct omap_smartreflex_dev_attr sr2_dev_attr = {
 };
 
 static struct omap_hwmod_irq_info omap3_smartreflex_core_irqs[] = {
-	{ .irq = 19 },
-	{ .irq = -1 }
+	{ .irq = 19 + OMAP_INTC_START, },
+	{ .irq = -1 },
 };
 
 static struct omap_hwmod omap34xx_sr2_hwmod = {
@@ -1467,8 +1467,8 @@ static struct omap_hwmod_class omap3xxx_mailbox_hwmod_class = {
 };
 
 static struct omap_hwmod_irq_info omap3xxx_mailbox_irqs[] = {
-	{ .irq = 26 },
-	{ .irq = -1 }
+	{ .irq = 26 + OMAP_INTC_START, },
+	{ .irq = -1 },
 };
 
 static struct omap_hwmod omap3xxx_mailbox_hwmod = {
@@ -1558,8 +1558,8 @@ static struct omap_hwmod omap34xx_mcspi2 = {
 
 /* mcspi3 */
 static struct omap_hwmod_irq_info omap34xx_mcspi3_mpu_irqs[] = {
-	{ .name = "irq", .irq = 91 }, /* 91 */
-	{ .irq = -1 }
+	{ .name = "irq", .irq = 91 + OMAP_INTC_START, }, /* 91 */
+	{ .irq = -1 },
 };
 
 static struct omap_hwmod_dma_info omap34xx_mcspi3_sdma_reqs[] = {
@@ -1594,8 +1594,8 @@ static struct omap_hwmod omap34xx_mcspi3 = {
 
 /* mcspi4 */
 static struct omap_hwmod_irq_info omap34xx_mcspi4_mpu_irqs[] = {
-	{ .name = "irq", .irq = INT_34XX_SPI4_IRQ }, /* 48 */
-	{ .irq = -1 }
+	{ .name = "irq", .irq = 48 + OMAP_INTC_START, },
+	{ .irq = -1 },
 };
 
 static struct omap_hwmod_dma_info omap34xx_mcspi4_sdma_reqs[] = {
@@ -1647,9 +1647,9 @@ static struct omap_hwmod_class usbotg_class = {
 /* usb_otg_hs */
 static struct omap_hwmod_irq_info omap3xxx_usbhsotg_mpu_irqs[] = {
 
-	{ .name = "mc", .irq = 92 },
-	{ .name = "dma", .irq = 93 },
-	{ .irq = -1 }
+	{ .name = "mc", .irq = 92 + OMAP_INTC_START, },
+	{ .name = "dma", .irq = 93 + OMAP_INTC_START, },
+	{ .irq = -1 },
 };
 
 static struct omap_hwmod omap3xxx_usbhsotg_hwmod = {
@@ -1679,8 +1679,8 @@ static struct omap_hwmod omap3xxx_usbhsotg_hwmod = {
 
 /* usb_otg_hs */
 static struct omap_hwmod_irq_info am35xx_usbhsotg_mpu_irqs[] = {
-	{ .name = "mc", .irq = 71 },
-	{ .irq = -1 }
+	{ .name = "mc", .irq = 71 + OMAP_INTC_START, },
+	{ .irq = -1 },
 };
 
 static struct omap_hwmod_class am35xx_usbotg_class = {
@@ -1715,8 +1715,8 @@ static struct omap_hwmod_class omap34xx_mmc_class = {
 /* MMC/SD/SDIO1 */
 
 static struct omap_hwmod_irq_info omap34xx_mmc1_mpu_irqs[] = {
-	{ .irq = 83, },
-	{ .irq = -1 }
+	{ .irq = 83 + OMAP_INTC_START, },
+	{ .irq = -1 },
 };
 
 static struct omap_hwmod_dma_info omap34xx_mmc1_sdma_reqs[] = {
@@ -1782,8 +1782,8 @@ static struct omap_hwmod omap3xxx_es3plus_mmc1_hwmod = {
 /* MMC/SD/SDIO2 */
 
 static struct omap_hwmod_irq_info omap34xx_mmc2_mpu_irqs[] = {
-	{ .irq = INT_24XX_MMC2_IRQ, },
-	{ .irq = -1 }
+	{ .irq = 86 + OMAP_INTC_START, },
+	{ .irq = -1 },
 };
 
 static struct omap_hwmod_dma_info omap34xx_mmc2_sdma_reqs[] = {
@@ -1843,8 +1843,8 @@ static struct omap_hwmod omap3xxx_es3plus_mmc2_hwmod = {
 /* MMC/SD/SDIO3 */
 
 static struct omap_hwmod_irq_info omap34xx_mmc3_mpu_irqs[] = {
-	{ .irq = 94, },
-	{ .irq = -1 }
+	{ .irq = 94 + OMAP_INTC_START, },
+	{ .irq = -1 },
 };
 
 static struct omap_hwmod_dma_info omap34xx_mmc3_sdma_reqs[] = {
@@ -1902,9 +1902,9 @@ static struct omap_hwmod_opt_clk omap3xxx_usb_host_hs_opt_clks[] = {
 };
 
 static struct omap_hwmod_irq_info omap3xxx_usb_host_hs_irqs[] = {
-	{ .name = "ohci-irq", .irq = 76 },
-	{ .name = "ehci-irq", .irq = 77 },
-	{ .irq = -1 }
+	{ .name = "ohci-irq", .irq = 76 + OMAP_INTC_START, },
+	{ .name = "ehci-irq", .irq = 77 + OMAP_INTC_START, },
+	{ .irq = -1 },
 };
 
 static struct omap_hwmod omap3xxx_usb_host_hs_hwmod = {
@@ -1996,8 +1996,8 @@ static struct omap_hwmod_class omap3xxx_usb_tll_hs_hwmod_class = {
 };
 
 static struct omap_hwmod_irq_info omap3xxx_usb_tll_hs_irqs[] = {
-	{ .name = "tll-irq", .irq = 78 },
-	{ .irq = -1 }
+	{ .name = "tll-irq", .irq = 78 + OMAP_INTC_START, },
+	{ .irq = -1 },
 };
 
 static struct omap_hwmod omap3xxx_usb_tll_hs_hwmod = {
@@ -3223,11 +3223,11 @@ static struct omap_hwmod_ocp_if am35xx_l4_core__mdio = {
 };
 
 static struct omap_hwmod_irq_info am35xx_emac_mpu_irqs[] = {
-	{ .name = "rxthresh",	.irq = INT_35XX_EMAC_C0_RXTHRESH_IRQ },
-	{ .name = "rx_pulse",	.irq = INT_35XX_EMAC_C0_RX_PULSE_IRQ },
-	{ .name = "tx_pulse",	.irq = INT_35XX_EMAC_C0_TX_PULSE_IRQ },
-	{ .name = "misc_pulse",	.irq = INT_35XX_EMAC_C0_MISC_PULSE_IRQ },
-	{ .irq = -1 }
+	{ .name = "rxthresh",	.irq = 67 + OMAP_INTC_START, },
+	{ .name = "rx_pulse",	.irq = 68 + OMAP_INTC_START, },
+	{ .name = "tx_pulse",	.irq = 69 + OMAP_INTC_START },
+	{ .name = "misc_pulse",	.irq = 70 + OMAP_INTC_START },
+	{ .irq = -1 },
 };
 
 static struct omap_hwmod_class am35xx_emac_class = {
diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index afb6091..4c92f23 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -19,15 +19,14 @@
  */
 
 #include <linux/io.h>
+#include <linux/platform_data/gpio-omap.h>
 #include <linux/power/smartreflex.h>
 
 #include <plat/omap_hwmod.h>
-#include <plat/cpu.h>
 #include <plat/i2c.h>
-#include <plat/gpio.h>
 #include <plat/dma.h>
-#include <plat/mcspi.h>
-#include <plat/mcbsp.h>
+#include <linux/platform_data/spi-omap2-mcspi.h>
+#include <linux/platform_data/asoc-ti-mcbsp.h>
 #include <plat/mmc.h>
 #include <plat/dmtimer.h>
 #include <plat/common.h>
@@ -5059,6 +5058,7 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__mcbsp4 = {
 
 static struct omap_hwmod_addr_space omap44xx_mcpdm_addrs[] = {
 	{
+		.name		= "mpu",
 		.pa_start	= 0x40132000,
 		.pa_end		= 0x4013207f,
 		.flags		= ADDR_TYPE_RT
@@ -5077,6 +5077,7 @@ static struct omap_hwmod_ocp_if omap44xx_l4_abe__mcpdm = {
 
 static struct omap_hwmod_addr_space omap44xx_mcpdm_dma_addrs[] = {
 	{
+		.name		= "dma",
 		.pa_start	= 0x49032000,
 		.pa_end		= 0x4903207f,
 		.flags		= ADDR_TYPE_RT
@@ -5890,6 +5891,12 @@ static struct omap_hwmod_addr_space omap44xx_usb_otg_hs_addrs[] = {
 		.pa_end		= 0x4a0ab003,
 		.flags		= ADDR_TYPE_RT
 	},
+	{
+		/* XXX: Remove this once control module driver is in place */
+		.pa_start	= 0x4a00233c,
+		.pa_end		= 0x4a00233f,
+		.flags		= ADDR_TYPE_RT
+	},
 	{ }
 };
 
diff --git a/arch/arm/mach-omap2/omap_hwmod_common_data.h b/arch/arm/mach-omap2/omap_hwmod_common_data.h
index e7e8eea..dddb677 100644
--- a/arch/arm/mach-omap2/omap_hwmod_common_data.h
+++ b/arch/arm/mach-omap2/omap_hwmod_common_data.h
@@ -16,6 +16,7 @@
 
 #include <plat/omap_hwmod.h>
 
+#include "common.h"
 #include "display.h"
 
 /* Common address space across OMAP2xxx */
diff --git a/arch/arm/mach-omap2/omap_l3_noc.c b/arch/arm/mach-omap2/omap_l3_noc.c
deleted file mode 100644
index d15225f..0000000
--- a/arch/arm/mach-omap2/omap_l3_noc.c
+++ /dev/null
@@ -1,266 +0,0 @@
-/*
- * OMAP4XXX L3 Interconnect error handling driver
- *
- * Copyright (C) 2011 Texas Corporation
- *	Santosh Shilimkar <santosh.shilimkar@ti.com>
- *	Sricharan <r.sricharan@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 program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- * USA
- */
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-
-#include "omap_l3_noc.h"
-
-/*
- * Interrupt Handler for L3 error detection.
- *	1) Identify the L3 clockdomain partition to which the error belongs to.
- *	2) Identify the slave where the error information is logged
- *	3) Print the logged information.
- *	4) Add dump stack to provide kernel trace.
- *
- * Two Types of errors :
- *	1) Custom errors in L3 :
- *		Target like DMM/FW/EMIF generates SRESP=ERR error
- *	2) Standard L3 error:
- *		- Unsupported CMD.
- *			L3 tries to access target while it is idle
- *		- OCP disconnect.
- *		- Address hole error:
- *			If DSS/ISS/FDIF/USBHOSTFS access a target where they
- *			do not have connectivity, the error is logged in
- *			their default target which is DMM2.
- *
- *	On High Secure devices, firewall errors are possible and those
- *	can be trapped as well. But the trapping is implemented as part
- *	secure software and hence need not be implemented here.
- */
-static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
-{
-
-	struct omap4_l3 *l3 = _l3;
-	int inttype, i, k;
-	int err_src = 0;
-	u32 std_err_main, err_reg, clear, masterid;
-	void __iomem *base, *l3_targ_base;
-	char *target_name, *master_name = "UN IDENTIFIED";
-
-	/* Get the Type of interrupt */
-	inttype = irq == l3->app_irq ? L3_APPLICATION_ERROR : L3_DEBUG_ERROR;
-
-	for (i = 0; i < L3_MODULES; i++) {
-		/*
-		 * Read the regerr register of the clock domain
-		 * to determine the source
-		 */
-		base = l3->l3_base[i];
-		err_reg = __raw_readl(base + l3_flagmux[i] +
-					+ L3_FLAGMUX_REGERR0 + (inttype << 3));
-
-		/* Get the corresponding error and analyse */
-		if (err_reg) {
-			/* Identify the source from control status register */
-			err_src = __ffs(err_reg);
-
-			/* Read the stderrlog_main_source from clk domain */
-			l3_targ_base = base + *(l3_targ[i] + err_src);
-			std_err_main =  __raw_readl(l3_targ_base +
-					L3_TARG_STDERRLOG_MAIN);
-			masterid = __raw_readl(l3_targ_base +
-					L3_TARG_STDERRLOG_MSTADDR);
-
-			switch (std_err_main & CUSTOM_ERROR) {
-			case STANDARD_ERROR:
-				target_name =
-					l3_targ_inst_name[i][err_src];
-				WARN(true, "L3 standard error: TARGET:%s at address 0x%x\n",
-					target_name,
-					__raw_readl(l3_targ_base +
-						L3_TARG_STDERRLOG_SLVOFSLSB));
-				/* clear the std error log*/
-				clear = std_err_main | CLEAR_STDERR_LOG;
-				writel(clear, l3_targ_base +
-					L3_TARG_STDERRLOG_MAIN);
-				break;
-
-			case CUSTOM_ERROR:
-				target_name =
-					l3_targ_inst_name[i][err_src];
-				for (k = 0; k < NUM_OF_L3_MASTERS; k++) {
-					if (masterid == l3_masters[k].id)
-						master_name =
-							l3_masters[k].name;
-				}
-				WARN(true, "L3 custom error: MASTER:%s TARGET:%s\n",
-					master_name, target_name);
-				/* clear the std error log*/
-				clear = std_err_main | CLEAR_STDERR_LOG;
-				writel(clear, l3_targ_base +
-					L3_TARG_STDERRLOG_MAIN);
-				break;
-
-			default:
-				/* Nothing to be handled here as of now */
-				break;
-			}
-		/* Error found so break the for loop */
-		break;
-		}
-	}
-	return IRQ_HANDLED;
-}
-
-static int __devinit omap4_l3_probe(struct platform_device *pdev)
-{
-	static struct omap4_l3 *l3;
-	struct resource	*res;
-	int ret;
-
-	l3 = kzalloc(sizeof(*l3), GFP_KERNEL);
-	if (!l3)
-		return -ENOMEM;
-
-	platform_set_drvdata(pdev, l3);
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_err(&pdev->dev, "couldn't find resource 0\n");
-		ret = -ENODEV;
-		goto err0;
-	}
-
-	l3->l3_base[0] = ioremap(res->start, resource_size(res));
-	if (!l3->l3_base[0]) {
-		dev_err(&pdev->dev, "ioremap failed\n");
-		ret = -ENOMEM;
-		goto err0;
-	}
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-	if (!res) {
-		dev_err(&pdev->dev, "couldn't find resource 1\n");
-		ret = -ENODEV;
-		goto err1;
-	}
-
-	l3->l3_base[1] = ioremap(res->start, resource_size(res));
-	if (!l3->l3_base[1]) {
-		dev_err(&pdev->dev, "ioremap failed\n");
-		ret = -ENOMEM;
-		goto err1;
-	}
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
-	if (!res) {
-		dev_err(&pdev->dev, "couldn't find resource 2\n");
-		ret = -ENODEV;
-		goto err2;
-	}
-
-	l3->l3_base[2] = ioremap(res->start, resource_size(res));
-	if (!l3->l3_base[2]) {
-		dev_err(&pdev->dev, "ioremap failed\n");
-		ret = -ENOMEM;
-		goto err2;
-	}
-
-	/*
-	 * Setup interrupt Handlers
-	 */
-	l3->debug_irq = platform_get_irq(pdev, 0);
-	ret = request_irq(l3->debug_irq,
-			l3_interrupt_handler,
-			IRQF_DISABLED, "l3-dbg-irq", l3);
-	if (ret) {
-		pr_crit("L3: request_irq failed to register for 0x%x\n",
-						OMAP44XX_IRQ_L3_DBG);
-		goto err3;
-	}
-
-	l3->app_irq = platform_get_irq(pdev, 1);
-	ret = request_irq(l3->app_irq,
-			l3_interrupt_handler,
-			IRQF_DISABLED, "l3-app-irq", l3);
-	if (ret) {
-		pr_crit("L3: request_irq failed to register for 0x%x\n",
-						OMAP44XX_IRQ_L3_APP);
-		goto err4;
-	}
-
-	return 0;
-
-err4:
-	free_irq(l3->debug_irq, l3);
-err3:
-	iounmap(l3->l3_base[2]);
-err2:
-	iounmap(l3->l3_base[1]);
-err1:
-	iounmap(l3->l3_base[0]);
-err0:
-	kfree(l3);
-	return ret;
-}
-
-static int __devexit omap4_l3_remove(struct platform_device *pdev)
-{
-	struct omap4_l3 *l3 = platform_get_drvdata(pdev);
-
-	free_irq(l3->app_irq, l3);
-	free_irq(l3->debug_irq, l3);
-	iounmap(l3->l3_base[0]);
-	iounmap(l3->l3_base[1]);
-	iounmap(l3->l3_base[2]);
-	kfree(l3);
-
-	return 0;
-}
-
-#if defined(CONFIG_OF)
-static const struct of_device_id l3_noc_match[] = {
-	{.compatible = "ti,omap4-l3-noc", },
-	{},
-};
-MODULE_DEVICE_TABLE(of, l3_noc_match);
-#else
-#define l3_noc_match NULL
-#endif
-
-static struct platform_driver omap4_l3_driver = {
-	.probe		= omap4_l3_probe,
-	.remove		= __devexit_p(omap4_l3_remove),
-	.driver		= {
-		.name		= "omap_l3_noc",
-		.owner		= THIS_MODULE,
-		.of_match_table = l3_noc_match,
-	},
-};
-
-static int __init omap4_l3_init(void)
-{
-	return platform_driver_register(&omap4_l3_driver);
-}
-postcore_initcall_sync(omap4_l3_init);
-
-static void __exit omap4_l3_exit(void)
-{
-	platform_driver_unregister(&omap4_l3_driver);
-}
-module_exit(omap4_l3_exit);
diff --git a/arch/arm/mach-omap2/omap_l3_noc.h b/arch/arm/mach-omap2/omap_l3_noc.h
deleted file mode 100644
index a6ce34d..0000000
--- a/arch/arm/mach-omap2/omap_l3_noc.h
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * OMAP4XXX L3 Interconnect  error handling driver header
- *
- * Copyright (C) 2011 Texas Corporation
- *	Santosh Shilimkar <santosh.shilimkar@ti.com>
- *	sricharan <r.sricharan@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 program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public 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 __ARCH_ARM_MACH_OMAP2_L3_INTERCONNECT_3XXX_H
-#define __ARCH_ARM_MACH_OMAP2_L3_INTERCONNECT_3XXX_H
-
-#define L3_MODULES			3
-#define CLEAR_STDERR_LOG		(1 << 31)
-#define CUSTOM_ERROR			0x2
-#define STANDARD_ERROR			0x0
-#define INBAND_ERROR			0x0
-#define L3_APPLICATION_ERROR		0x0
-#define L3_DEBUG_ERROR			0x1
-
-/* L3 TARG register offsets */
-#define L3_TARG_STDERRLOG_MAIN		0x48
-#define L3_TARG_STDERRLOG_SLVOFSLSB	0x5c
-#define L3_TARG_STDERRLOG_MSTADDR	0x68
-#define L3_FLAGMUX_REGERR0		0xc
-
-#define NUM_OF_L3_MASTERS	(sizeof(l3_masters)/sizeof(l3_masters[0]))
-
-static u32 l3_flagmux[L3_MODULES] = {
-	0x500,
-	0x1000,
-	0X0200
-};
-
-/* L3 Target standard Error register offsets */
-static u32 l3_targ_inst_clk1[] = {
-	0x100, /* DMM1 */
-	0x200, /* DMM2 */
-	0x300, /* ABE */
-	0x400, /* L4CFG */
-	0x600,  /* CLK2 PWR DISC */
-	0x0,	/* Host CLK1 */
-	0x900	/* L4 Wakeup */
-};
-
-static u32 l3_targ_inst_clk2[] = {
-	0x500, /* CORTEX M3 */
-	0x300, /* DSS */
-	0x100, /* GPMC */
-	0x400, /* ISS */
-	0x700, /* IVAHD */
-	0xD00, /* missing in TRM  corresponds to AES1*/
-	0x900, /* L4 PER0*/
-	0x200, /* OCMRAM */
-	0x100, /* missing in TRM corresponds to GPMC sERROR*/
-	0x600, /* SGX */
-	0x800, /* SL2 */
-	0x1600, /* C2C */
-	0x1100,	/* missing in TRM corresponds PWR DISC CLK1*/
-	0xF00, /* missing in TRM corrsponds to SHA1*/
-	0xE00, /* missing in TRM corresponds to AES2*/
-	0xC00, /* L4 PER3 */
-	0xA00, /* L4 PER1*/
-	0xB00, /* L4 PER2*/
-	0x0, /* HOST CLK2 */
-	0x1800, /* CAL */
-	0x1700 /* LLI */
-};
-
-static u32 l3_targ_inst_clk3[] = {
-	0x0100	/* EMUSS */,
-	0x0300, /* DEBUGSS_CT_TBR */
-	0x0 /* HOST CLK3 */
-};
-
-static struct l3_masters_data {
-	u32 id;
-	char name[10];
-} l3_masters[] = {
-	{ 0x0 , "MPU"},
-	{ 0x10, "CS_ADP"},
-	{ 0x14, "xxx"},
-	{ 0x20, "DSP"},
-	{ 0x30, "IVAHD"},
-	{ 0x40, "ISS"},
-	{ 0x44, "DucatiM3"},
-	{ 0x48, "FaceDetect"},
-	{ 0x50, "SDMA_Rd"},
-	{ 0x54, "SDMA_Wr"},
-	{ 0x58, "xxx"},
-	{ 0x5C, "xxx"},
-	{ 0x60, "SGX"},
-	{ 0x70, "DSS"},
-	{ 0x80, "C2C"},
-	{ 0x88, "xxx"},
-	{ 0x8C, "xxx"},
-	{ 0x90, "HSI"},
-	{ 0xA0, "MMC1"},
-	{ 0xA4, "MMC2"},
-	{ 0xA8, "MMC6"},
-	{ 0xB0, "UNIPRO1"},
-	{ 0xC0, "USBHOSTHS"},
-	{ 0xC4, "USBOTGHS"},
-	{ 0xC8, "USBHOSTFS"}
-};
-
-static char *l3_targ_inst_name[L3_MODULES][21] = {
-	{
-		"DMM1",
-		"DMM2",
-		"ABE",
-		"L4CFG",
-		"CLK2 PWR DISC",
-		"HOST CLK1",
-		"L4 WAKEUP"
-	},
-	{
-		"CORTEX M3" ,
-		"DSS ",
-		"GPMC ",
-		"ISS ",
-		"IVAHD ",
-		"AES1",
-		"L4 PER0",
-		"OCMRAM ",
-		"GPMC sERROR",
-		"SGX ",
-		"SL2 ",
-		"C2C ",
-		"PWR DISC CLK1",
-		"SHA1",
-		"AES2",
-		"L4 PER3",
-		"L4 PER1",
-		"L4 PER2",
-		"HOST CLK2",
-		"CAL",
-		"LLI"
-	},
-	{
-		"EMUSS",
-		"DEBUG SOURCE",
-		"HOST CLK3"
-	},
-};
-
-static u32 *l3_targ[L3_MODULES] = {
-	l3_targ_inst_clk1,
-	l3_targ_inst_clk2,
-	l3_targ_inst_clk3,
-};
-
-struct omap4_l3 {
-	struct device *dev;
-	struct clk *ick;
-
-	/* memory base */
-	void __iomem *l3_base[L3_MODULES];
-
-	int debug_irq;
-	int app_irq;
-};
-#endif
diff --git a/arch/arm/mach-omap2/omap_l3_smx.c b/arch/arm/mach-omap2/omap_l3_smx.c
deleted file mode 100644
index acc2164..0000000
--- a/arch/arm/mach-omap2/omap_l3_smx.c
+++ /dev/null
@@ -1,297 +0,0 @@
-/*
- * OMAP3XXX L3 Interconnect Driver
- *
- * Copyright (C) 2011 Texas Corporation
- *	Felipe Balbi <balbi@ti.com>
- *	Santosh Shilimkar <santosh.shilimkar@ti.com>
- *	Sricharan <r.sricharan@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 program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public 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 <linux/slab.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include "omap_l3_smx.h"
-
-static inline u64 omap3_l3_readll(void __iomem *base, u16 reg)
-{
-	return __raw_readll(base + reg);
-}
-
-static inline void omap3_l3_writell(void __iomem *base, u16 reg, u64 value)
-{
-	__raw_writell(value, base + reg);
-}
-
-static inline enum omap3_l3_code omap3_l3_decode_error_code(u64 error)
-{
-	return (error & 0x0f000000) >> L3_ERROR_LOG_CODE;
-}
-
-static inline u32 omap3_l3_decode_addr(u64 error_addr)
-{
-	return error_addr & 0xffffffff;
-}
-
-static inline unsigned omap3_l3_decode_cmd(u64 error)
-{
-	return (error & 0x07) >> L3_ERROR_LOG_CMD;
-}
-
-static inline enum omap3_l3_initiator_id omap3_l3_decode_initid(u64 error)
-{
-	return (error & 0xff00) >> L3_ERROR_LOG_INITID;
-}
-
-static inline unsigned omap3_l3_decode_req_info(u64 error)
-{
-	return (error >> 32) & 0xffff;
-}
-
-static char *omap3_l3_code_string(u8 code)
-{
-	switch (code) {
-	case OMAP_L3_CODE_NOERROR:
-		return "No Error";
-	case OMAP_L3_CODE_UNSUP_CMD:
-		return "Unsupported Command";
-	case OMAP_L3_CODE_ADDR_HOLE:
-		return "Address Hole";
-	case OMAP_L3_CODE_PROTECT_VIOLATION:
-		return "Protection Violation";
-	case OMAP_L3_CODE_IN_BAND_ERR:
-		return "In-band Error";
-	case OMAP_L3_CODE_REQ_TOUT_NOT_ACCEPT:
-		return "Request Timeout Not Accepted";
-	case OMAP_L3_CODE_REQ_TOUT_NO_RESP:
-		return "Request Timeout, no response";
-	default:
-		return "UNKNOWN error";
-	}
-}
-
-static char *omap3_l3_initiator_string(u8 initid)
-{
-	switch (initid) {
-	case OMAP_L3_LCD:
-		return "LCD";
-	case OMAP_L3_SAD2D:
-		return "SAD2D";
-	case OMAP_L3_IA_MPU_SS_1:
-	case OMAP_L3_IA_MPU_SS_2:
-	case OMAP_L3_IA_MPU_SS_3:
-	case OMAP_L3_IA_MPU_SS_4:
-	case OMAP_L3_IA_MPU_SS_5:
-		return "MPU";
-	case OMAP_L3_IA_IVA_SS_1:
-	case OMAP_L3_IA_IVA_SS_2:
-	case OMAP_L3_IA_IVA_SS_3:
-		return "IVA_SS";
-	case OMAP_L3_IA_IVA_SS_DMA_1:
-	case OMAP_L3_IA_IVA_SS_DMA_2:
-	case OMAP_L3_IA_IVA_SS_DMA_3:
-	case OMAP_L3_IA_IVA_SS_DMA_4:
-	case OMAP_L3_IA_IVA_SS_DMA_5:
-	case OMAP_L3_IA_IVA_SS_DMA_6:
-		return "IVA_SS_DMA";
-	case OMAP_L3_IA_SGX:
-		return "SGX";
-	case OMAP_L3_IA_CAM_1:
-	case OMAP_L3_IA_CAM_2:
-	case OMAP_L3_IA_CAM_3:
-		return "CAM";
-	case OMAP_L3_IA_DAP:
-		return "DAP";
-	case OMAP_L3_SDMA_WR_1:
-	case OMAP_L3_SDMA_WR_2:
-		return "SDMA_WR";
-	case OMAP_L3_SDMA_RD_1:
-	case OMAP_L3_SDMA_RD_2:
-	case OMAP_L3_SDMA_RD_3:
-	case OMAP_L3_SDMA_RD_4:
-		return "SDMA_RD";
-	case OMAP_L3_USBOTG:
-		return "USB_OTG";
-	case OMAP_L3_USBHOST:
-		return "USB_HOST";
-	default:
-		return "UNKNOWN Initiator";
-	}
-}
-
-/*
- * omap3_l3_block_irq - handles a register block's irq
- * @l3: struct omap3_l3 *
- * @base: register block base address
- * @error: L3_ERROR_LOG register of our block
- *
- * Called in hard-irq context. Caller should take care of locking
- *
- * OMAP36xx TRM gives, on page 2001, Figure 9-10, the Typical Error
- * Analysis Sequence, we are following that sequence here, please
- * refer to that Figure for more information on the subject.
- */
-static irqreturn_t omap3_l3_block_irq(struct omap3_l3 *l3,
-					u64 error, int error_addr)
-{
-	u8 code = omap3_l3_decode_error_code(error);
-	u8 initid = omap3_l3_decode_initid(error);
-	u8 multi = error & L3_ERROR_LOG_MULTI;
-	u32 address = omap3_l3_decode_addr(error_addr);
-
-	pr_err("%s seen by %s %s at address %x\n",
-			omap3_l3_code_string(code),
-			omap3_l3_initiator_string(initid),
-			multi ? "Multiple Errors" : "", address);
-	WARN_ON(1);
-
-	return IRQ_HANDLED;
-}
-
-static irqreturn_t omap3_l3_app_irq(int irq, void *_l3)
-{
-	struct omap3_l3 *l3 = _l3;
-	u64 status, clear;
-	u64 error;
-	u64 error_addr;
-	u64 err_source = 0;
-	void __iomem *base;
-	int int_type;
-	irqreturn_t ret = IRQ_NONE;
-
-	int_type = irq == l3->app_irq ? L3_APPLICATION_ERROR : L3_DEBUG_ERROR;
-	if (!int_type) {
-		status = omap3_l3_readll(l3->rt, L3_SI_FLAG_STATUS_0);
-		/*
-		 * if we have a timeout error, there's nothing we can
-		 * do besides rebooting the board. So let's BUG on any
-		 * of such errors and handle the others. timeout error
-		 * is severe and not expected to occur.
-		 */
-		BUG_ON(status & L3_STATUS_0_TIMEOUT_MASK);
-	} else {
-		status = omap3_l3_readll(l3->rt, L3_SI_FLAG_STATUS_1);
-		/* No timeout error for debug sources */
-	}
-
-	/* identify the error source */
-	err_source = __ffs(status);
-
-	base = l3->rt + omap3_l3_bases[int_type][err_source];
-	error = omap3_l3_readll(base, L3_ERROR_LOG);
-	if (error) {
-		error_addr = omap3_l3_readll(base, L3_ERROR_LOG_ADDR);
-		ret |= omap3_l3_block_irq(l3, error, error_addr);
-	}
-
-	/* Clear the status register */
-	clear = (L3_AGENT_STATUS_CLEAR_IA << int_type) |
-		L3_AGENT_STATUS_CLEAR_TA;
-	omap3_l3_writell(base, L3_AGENT_STATUS, clear);
-
-	/* clear the error log register */
-	omap3_l3_writell(base, L3_ERROR_LOG, error);
-
-	return ret;
-}
-
-static int __init omap3_l3_probe(struct platform_device *pdev)
-{
-	struct omap3_l3 *l3;
-	struct resource *res;
-	int ret;
-
-	l3 = kzalloc(sizeof(*l3), GFP_KERNEL);
-	if (!l3)
-		return -ENOMEM;
-
-	platform_set_drvdata(pdev, l3);
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_err(&pdev->dev, "couldn't find resource\n");
-		ret = -ENODEV;
-		goto err0;
-	}
-	l3->rt = ioremap(res->start, resource_size(res));
-	if (!l3->rt) {
-		dev_err(&pdev->dev, "ioremap failed\n");
-		ret = -ENOMEM;
-		goto err0;
-	}
-
-	l3->debug_irq = platform_get_irq(pdev, 0);
-	ret = request_irq(l3->debug_irq, omap3_l3_app_irq,
-		IRQF_DISABLED | IRQF_TRIGGER_RISING,
-		"l3-debug-irq", l3);
-	if (ret) {
-		dev_err(&pdev->dev, "couldn't request debug irq\n");
-		goto err1;
-	}
-
-	l3->app_irq = platform_get_irq(pdev, 1);
-	ret = request_irq(l3->app_irq, omap3_l3_app_irq,
-		IRQF_DISABLED | IRQF_TRIGGER_RISING,
-		"l3-app-irq", l3);
-	if (ret) {
-		dev_err(&pdev->dev, "couldn't request app irq\n");
-		goto err2;
-	}
-
-	return 0;
-
-err2:
-	free_irq(l3->debug_irq, l3);
-err1:
-	iounmap(l3->rt);
-err0:
-	kfree(l3);
-	return ret;
-}
-
-static int __exit omap3_l3_remove(struct platform_device *pdev)
-{
-	struct omap3_l3         *l3 = platform_get_drvdata(pdev);
-
-	free_irq(l3->app_irq, l3);
-	free_irq(l3->debug_irq, l3);
-	iounmap(l3->rt);
-	kfree(l3);
-
-	return 0;
-}
-
-static struct platform_driver omap3_l3_driver = {
-	.remove         = __exit_p(omap3_l3_remove),
-	.driver         = {
-	.name   = "omap_l3_smx",
-	},
-};
-
-static int __init omap3_l3_init(void)
-{
-	return platform_driver_probe(&omap3_l3_driver, omap3_l3_probe);
-}
-postcore_initcall_sync(omap3_l3_init);
-
-static void __exit omap3_l3_exit(void)
-{
-	platform_driver_unregister(&omap3_l3_driver);
-}
-module_exit(omap3_l3_exit);
diff --git a/arch/arm/mach-omap2/omap_l3_smx.h b/arch/arm/mach-omap2/omap_l3_smx.h
deleted file mode 100644
index 4f3cebc..0000000
--- a/arch/arm/mach-omap2/omap_l3_smx.h
+++ /dev/null
@@ -1,338 +0,0 @@
-/*
- * OMAP3XXX L3 Interconnect Driver header
- *
- * Copyright (C) 2011 Texas Corporation
- *	Felipe Balbi <balbi@ti.com>
- *	Santosh Shilimkar <santosh.shilimkar@ti.com>
- *	sricharan <r.sricharan@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 program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public 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 __ARCH_ARM_MACH_OMAP2_L3_INTERCONNECT_3XXX_H
-#define __ARCH_ARM_MACH_OMAP2_L3_INTERCONNECT_3XXX_H
-
-/* Register definitions. All 64-bit wide */
-#define L3_COMPONENT			0x000
-#define L3_CORE				0x018
-#define L3_AGENT_CONTROL		0x020
-#define L3_AGENT_STATUS			0x028
-#define L3_ERROR_LOG			0x058
-
-#define L3_ERROR_LOG_MULTI		(1 << 31)
-#define L3_ERROR_LOG_SECONDARY		(1 << 30)
-
-#define L3_ERROR_LOG_ADDR		0x060
-
-/* Register definitions for Sideband Interconnect */
-#define L3_SI_CONTROL			0x020
-#define L3_SI_FLAG_STATUS_0		0x510
-
-static const u64 shift = 1;
-
-#define L3_STATUS_0_MPUIA_BRST		(shift << 0)
-#define L3_STATUS_0_MPUIA_RSP		(shift << 1)
-#define L3_STATUS_0_MPUIA_INBAND	(shift << 2)
-#define L3_STATUS_0_IVAIA_BRST		(shift << 6)
-#define L3_STATUS_0_IVAIA_RSP		(shift << 7)
-#define L3_STATUS_0_IVAIA_INBAND	(shift << 8)
-#define L3_STATUS_0_SGXIA_BRST		(shift << 9)
-#define L3_STATUS_0_SGXIA_RSP		(shift << 10)
-#define L3_STATUS_0_SGXIA_MERROR	(shift << 11)
-#define L3_STATUS_0_CAMIA_BRST		(shift << 12)
-#define L3_STATUS_0_CAMIA_RSP		(shift << 13)
-#define L3_STATUS_0_CAMIA_INBAND	(shift << 14)
-#define L3_STATUS_0_DISPIA_BRST		(shift << 15)
-#define L3_STATUS_0_DISPIA_RSP		(shift << 16)
-#define L3_STATUS_0_DMARDIA_BRST	(shift << 18)
-#define L3_STATUS_0_DMARDIA_RSP		(shift << 19)
-#define L3_STATUS_0_DMAWRIA_BRST	(shift << 21)
-#define L3_STATUS_0_DMAWRIA_RSP		(shift << 22)
-#define L3_STATUS_0_USBOTGIA_BRST	(shift << 24)
-#define L3_STATUS_0_USBOTGIA_RSP	(shift << 25)
-#define L3_STATUS_0_USBOTGIA_INBAND	(shift << 26)
-#define L3_STATUS_0_USBHOSTIA_BRST	(shift << 27)
-#define L3_STATUS_0_USBHOSTIA_INBAND	(shift << 28)
-#define L3_STATUS_0_SMSTA_REQ		(shift << 48)
-#define L3_STATUS_0_GPMCTA_REQ		(shift << 49)
-#define L3_STATUS_0_OCMRAMTA_REQ	(shift << 50)
-#define L3_STATUS_0_OCMROMTA_REQ	(shift << 51)
-#define L3_STATUS_0_IVATA_REQ		(shift << 54)
-#define L3_STATUS_0_SGXTA_REQ		(shift << 55)
-#define L3_STATUS_0_SGXTA_SERROR	(shift << 56)
-#define L3_STATUS_0_GPMCTA_SERROR	(shift << 57)
-#define L3_STATUS_0_L4CORETA_REQ	(shift << 58)
-#define L3_STATUS_0_L4PERTA_REQ		(shift << 59)
-#define L3_STATUS_0_L4EMUTA_REQ		(shift << 60)
-#define L3_STATUS_0_MAD2DTA_REQ		(shift << 61)
-
-#define L3_STATUS_0_TIMEOUT_MASK	(L3_STATUS_0_MPUIA_BRST		\
-					| L3_STATUS_0_MPUIA_RSP		\
-					| L3_STATUS_0_IVAIA_BRST	\
-					| L3_STATUS_0_IVAIA_RSP		\
-					| L3_STATUS_0_SGXIA_BRST	\
-					| L3_STATUS_0_SGXIA_RSP		\
-					| L3_STATUS_0_CAMIA_BRST	\
-					| L3_STATUS_0_CAMIA_RSP		\
-					| L3_STATUS_0_DISPIA_BRST	\
-					| L3_STATUS_0_DISPIA_RSP	\
-					| L3_STATUS_0_DMARDIA_BRST	\
-					| L3_STATUS_0_DMARDIA_RSP	\
-					| L3_STATUS_0_DMAWRIA_BRST	\
-					| L3_STATUS_0_DMAWRIA_RSP	\
-					| L3_STATUS_0_USBOTGIA_BRST	\
-					| L3_STATUS_0_USBOTGIA_RSP	\
-					| L3_STATUS_0_USBHOSTIA_BRST	\
-					| L3_STATUS_0_SMSTA_REQ		\
-					| L3_STATUS_0_GPMCTA_REQ	\
-					| L3_STATUS_0_OCMRAMTA_REQ	\
-					| L3_STATUS_0_OCMROMTA_REQ	\
-					| L3_STATUS_0_IVATA_REQ		\
-					| L3_STATUS_0_SGXTA_REQ		\
-					| L3_STATUS_0_L4CORETA_REQ	\
-					| L3_STATUS_0_L4PERTA_REQ	\
-					| L3_STATUS_0_L4EMUTA_REQ	\
-					| L3_STATUS_0_MAD2DTA_REQ)
-
-#define L3_SI_FLAG_STATUS_1		0x530
-
-#define L3_STATUS_1_MPU_DATAIA		(1 << 0)
-#define L3_STATUS_1_DAPIA0		(1 << 3)
-#define L3_STATUS_1_DAPIA1		(1 << 4)
-#define L3_STATUS_1_IVAIA		(1 << 6)
-
-#define L3_PM_ERROR_LOG			0x020
-#define L3_PM_CONTROL			0x028
-#define L3_PM_ERROR_CLEAR_SINGLE	0x030
-#define L3_PM_ERROR_CLEAR_MULTI		0x038
-#define L3_PM_REQ_INFO_PERMISSION(n)	(0x048 + (0x020 * n))
-#define L3_PM_READ_PERMISSION(n)	(0x050 + (0x020 * n))
-#define L3_PM_WRITE_PERMISSION(n)	(0x058 + (0x020 * n))
-#define L3_PM_ADDR_MATCH(n)		(0x060 + (0x020 * n))
-
-/* L3 error log bit fields. Common for IA and TA */
-#define L3_ERROR_LOG_CODE		24
-#define L3_ERROR_LOG_INITID		8
-#define L3_ERROR_LOG_CMD		0
-
-/* L3 agent status bit fields. */
-#define L3_AGENT_STATUS_CLEAR_IA	0x10000000
-#define L3_AGENT_STATUS_CLEAR_TA	0x01000000
-
-#define OMAP34xx_IRQ_L3_APP		10
-#define L3_APPLICATION_ERROR		0x0
-#define L3_DEBUG_ERROR			0x1
-
-enum omap3_l3_initiator_id {
-	/* LCD has 1 ID */
-	OMAP_L3_LCD = 29,
-	/* SAD2D has 1 ID */
-	OMAP_L3_SAD2D = 28,
-	/* MPU has 5 IDs */
-	OMAP_L3_IA_MPU_SS_1 = 27,
-	OMAP_L3_IA_MPU_SS_2 = 26,
-	OMAP_L3_IA_MPU_SS_3 = 25,
-	OMAP_L3_IA_MPU_SS_4 = 24,
-	OMAP_L3_IA_MPU_SS_5 = 23,
-	/* IVA2.2 SS has 3 IDs*/
-	OMAP_L3_IA_IVA_SS_1 = 22,
-	OMAP_L3_IA_IVA_SS_2 = 21,
-	OMAP_L3_IA_IVA_SS_3 = 20,
-	/* IVA 2.2 SS DMA has 6 IDS */
-	OMAP_L3_IA_IVA_SS_DMA_1 = 19,
-	OMAP_L3_IA_IVA_SS_DMA_2 = 18,
-	OMAP_L3_IA_IVA_SS_DMA_3 = 17,
-	OMAP_L3_IA_IVA_SS_DMA_4 = 16,
-	OMAP_L3_IA_IVA_SS_DMA_5 = 15,
-	OMAP_L3_IA_IVA_SS_DMA_6 = 14,
-	/* SGX has 1 ID */
-	OMAP_L3_IA_SGX = 13,
-	/* CAM has 3 ID */
-	OMAP_L3_IA_CAM_1 = 12,
-	OMAP_L3_IA_CAM_2 = 11,
-	OMAP_L3_IA_CAM_3 = 10,
-	/* DAP has 1 ID */
-	OMAP_L3_IA_DAP = 9,
-	/* SDMA WR has 2 IDs */
-	OMAP_L3_SDMA_WR_1 = 8,
-	OMAP_L3_SDMA_WR_2 = 7,
-	/* SDMA RD has 4 IDs */
-	OMAP_L3_SDMA_RD_1 = 6,
-	OMAP_L3_SDMA_RD_2 = 5,
-	OMAP_L3_SDMA_RD_3 = 4,
-	OMAP_L3_SDMA_RD_4 = 3,
-	/* HSUSB OTG has 1 ID */
-	OMAP_L3_USBOTG = 2,
-	/* HSUSB HOST has 1 ID */
-	OMAP_L3_USBHOST = 1,
-};
-
-enum omap3_l3_code {
-	OMAP_L3_CODE_NOERROR = 0,
-	OMAP_L3_CODE_UNSUP_CMD = 1,
-	OMAP_L3_CODE_ADDR_HOLE = 2,
-	OMAP_L3_CODE_PROTECT_VIOLATION = 3,
-	OMAP_L3_CODE_IN_BAND_ERR = 4,
-	/* codes 5 and 6 are reserved */
-	OMAP_L3_CODE_REQ_TOUT_NOT_ACCEPT = 7,
-	OMAP_L3_CODE_REQ_TOUT_NO_RESP = 8,
-	/* codes 9 - 15 are also reserved */
-};
-
-struct omap3_l3 {
-	struct device *dev;
-	struct clk *ick;
-
-	/* memory base*/
-	void __iomem *rt;
-
-	int debug_irq;
-	int app_irq;
-
-	/* true when and inband functional error occurs */
-	unsigned inband:1;
-};
-
-/* offsets for l3 agents in order with the Flag status register */
-static unsigned int omap3_l3_app_bases[] = {
-	/* MPU IA */
-	0x1400,
-	0x1400,
-	0x1400,
-	/* RESERVED */
-	0,
-	0,
-	0,
-	/* IVA 2.2 IA */
-	0x1800,
-	0x1800,
-	0x1800,
-	/* SGX IA */
-	0x1c00,
-	0x1c00,
-	/* RESERVED */
-	0,
-	/* CAMERA IA */
-	0x5800,
-	0x5800,
-	0x5800,
-	/* DISPLAY IA */
-	0x5400,
-	0x5400,
-	/* RESERVED */
-	0,
-	/*SDMA RD IA */
-	0x4c00,
-	0x4c00,
-	/* RESERVED */
-	0,
-	/* SDMA WR IA */
-	0x5000,
-	0x5000,
-	/* RESERVED */
-	0,
-	/* USB OTG IA */
-	0x4400,
-	0x4400,
-	0x4400,
-	/* USB HOST IA */
-	0x4000,
-	0x4000,
-	/* RESERVED */
-	0,
-	0,
-	0,
-	0,
-	/* SAD2D IA */
-	0x3000,
-	0x3000,
-	0x3000,
-	/* RESERVED */
-	0,
-	0,
-	0,
-	0,
-	0,
-	0,
-	0,
-	0,
-	0,
-	0,
-	0,
-	0,
-	/* SMA TA */
-	0x2000,
-	/* GPMC TA */
-	0x2400,
-	/* OCM RAM TA */
-	0x2800,
-	/* OCM ROM TA */
-	0x2C00,
-	/* L4 CORE TA */
-	0x6800,
-	/* L4 PER TA */
-	0x6c00,
-	/* IVA 2.2 TA */
-	0x6000,
-	/* SGX TA */
-	0x6400,
-	/* L4 EMU TA */
-	0x7000,
-	/* GPMC TA */
-	0x2400,
-	/* L4 CORE TA */
-	0x6800,
-	/* L4 PER TA */
-	0x6c00,
-	/* L4 EMU TA */
-	0x7000,
-	/* MAD2D TA */
-	0x3400,
-	/* RESERVED */
-	0,
-	0,
-};
-
-static unsigned int omap3_l3_debug_bases[] = {
-	/* MPU DATA IA */
-	0x1400,
-	/* RESERVED */
-	0,
-	0,
-	/* DAP IA */
-	0x5c00,
-	0x5c00,
-	/* RESERVED */
-	0,
-	/* IVA 2.2 IA */
-	0x1800,
-	/* REST RESERVED */
-};
-
-static u32 *omap3_l3_bases[] = {
-	omap3_l3_app_bases,
-	omap3_l3_debug_bases,
-};
-
-/*
- * REVISIT define __raw_readll/__raw_writell here, but move them to
- * <asm/io.h> at some point
- */
-#define __raw_writell(v, a)	(__chk_io_ptr(a), \
-				*(volatile u64 __force *)(a) = (v))
-#define __raw_readll(a)		(__chk_io_ptr(a), \
-				*(volatile u64 __force *)(a))
-
-#endif
diff --git a/arch/arm/mach-omap2/omap_phy_internal.c b/arch/arm/mach-omap2/omap_phy_internal.c
index d52651a..d992db8 100644
--- a/arch/arm/mach-omap2/omap_phy_internal.c
+++ b/arch/arm/mach-omap2/omap_phy_internal.c
@@ -29,145 +29,9 @@
 #include <linux/usb.h>
 
 #include <plat/usb.h>
-#include "control.h"
-
-/* OMAP control module register for UTMI PHY */
-#define CONTROL_DEV_CONF		0x300
-#define PHY_PD				0x1
-
-#define USBOTGHS_CONTROL		0x33c
-#define	AVALID				BIT(0)
-#define	BVALID				BIT(1)
-#define	VBUSVALID			BIT(2)
-#define	SESSEND				BIT(3)
-#define	IDDIG				BIT(4)
-
-static struct clk *phyclk, *clk48m, *clk32k;
-static void __iomem *ctrl_base;
-static int usbotghs_control;
-
-int omap4430_phy_init(struct device *dev)
-{
-	ctrl_base = ioremap(OMAP443X_SCM_BASE, SZ_1K);
-	if (!ctrl_base) {
-		pr_err("control module ioremap failed\n");
-		return -ENOMEM;
-	}
-	/* Power down the phy */
-	__raw_writel(PHY_PD, ctrl_base + CONTROL_DEV_CONF);
-
-	if (!dev) {
-		iounmap(ctrl_base);
-		return 0;
-	}
-
-	phyclk = clk_get(dev, "ocp2scp_usb_phy_ick");
-	if (IS_ERR(phyclk)) {
-		dev_err(dev, "cannot clk_get ocp2scp_usb_phy_ick\n");
-		iounmap(ctrl_base);
-		return PTR_ERR(phyclk);
-	}
-
-	clk48m = clk_get(dev, "ocp2scp_usb_phy_phy_48m");
-	if (IS_ERR(clk48m)) {
-		dev_err(dev, "cannot clk_get ocp2scp_usb_phy_phy_48m\n");
-		clk_put(phyclk);
-		iounmap(ctrl_base);
-		return PTR_ERR(clk48m);
-	}
-
-	clk32k = clk_get(dev, "usb_phy_cm_clk32k");
-	if (IS_ERR(clk32k)) {
-		dev_err(dev, "cannot clk_get usb_phy_cm_clk32k\n");
-		clk_put(phyclk);
-		clk_put(clk48m);
-		iounmap(ctrl_base);
-		return PTR_ERR(clk32k);
-	}
-	return 0;
-}
-
-int omap4430_phy_set_clk(struct device *dev, int on)
-{
-	static int state;
-
-	if (on && !state) {
-		/* Enable the phy clocks */
-		clk_enable(phyclk);
-		clk_enable(clk48m);
-		clk_enable(clk32k);
-		state = 1;
-	} else if (state) {
-		/* Disable the phy clocks */
-		clk_disable(phyclk);
-		clk_disable(clk48m);
-		clk_disable(clk32k);
-		state = 0;
-	}
-	return 0;
-}
-
-int omap4430_phy_power(struct device *dev, int ID, int on)
-{
-	if (on) {
-		if (ID)
-			/* enable VBUS valid, IDDIG groung */
-			__raw_writel(AVALID | VBUSVALID, ctrl_base +
-							USBOTGHS_CONTROL);
-		else
-			/*
-			 * Enable VBUS Valid, AValid and IDDIG
-			 * high impedance
-			 */
-			__raw_writel(IDDIG | AVALID | VBUSVALID,
-						ctrl_base + USBOTGHS_CONTROL);
-	} else {
-		/* Enable session END and IDIG to high impedance. */
-		__raw_writel(SESSEND | IDDIG, ctrl_base +
-					USBOTGHS_CONTROL);
-	}
-	return 0;
-}
-
-int omap4430_phy_suspend(struct device *dev, int suspend)
-{
-	if (suspend) {
-		/* Disable the clocks */
-		omap4430_phy_set_clk(dev, 0);
-		/* Power down the phy */
-		__raw_writel(PHY_PD, ctrl_base + CONTROL_DEV_CONF);
-
-		/* save the context */
-		usbotghs_control = __raw_readl(ctrl_base + USBOTGHS_CONTROL);
-	} else {
-		/* Enable the internel phy clcoks */
-		omap4430_phy_set_clk(dev, 1);
-		/* power on the phy */
-		if (__raw_readl(ctrl_base + CONTROL_DEV_CONF) & PHY_PD) {
-			__raw_writel(~PHY_PD, ctrl_base + CONTROL_DEV_CONF);
-			mdelay(200);
-		}
-
-		/* restore the context */
-		__raw_writel(usbotghs_control, ctrl_base + USBOTGHS_CONTROL);
-	}
-
-	return 0;
-}
-
-int omap4430_phy_exit(struct device *dev)
-{
-	if (ctrl_base)
-		iounmap(ctrl_base);
-	if (phyclk)
-		clk_put(phyclk);
-	if (clk48m)
-		clk_put(clk48m);
-	if (clk32k)
-		clk_put(clk32k);
 
-	return 0;
-}
+#include "soc.h"
+#include "control.h"
 
 void am35x_musb_reset(void)
 {
diff --git a/arch/arm/mach-omap2/opp.c b/arch/arm/mach-omap2/opp.c
index d8f6dbf..45ad7f7 100644
--- a/arch/arm/mach-omap2/opp.c
+++ b/arch/arm/mach-omap2/opp.c
@@ -64,25 +64,22 @@ int __init omap_init_opp_table(struct omap_opp_def *opp_def,
 		}
 		oh = omap_hwmod_lookup(opp_def->hwmod_name);
 		if (!oh || !oh->od) {
-			pr_debug("%s: no hwmod or odev for %s, [%d] "
-				"cannot add OPPs.\n", __func__,
-				opp_def->hwmod_name, i);
+			pr_debug("%s: no hwmod or odev for %s, [%d] cannot add OPPs.\n",
+				 __func__, opp_def->hwmod_name, i);
 			continue;
 		}
 		dev = &oh->od->pdev->dev;
 
 		r = opp_add(dev, opp_def->freq, opp_def->u_volt);
 		if (r) {
-			dev_err(dev, "%s: add OPP %ld failed for %s [%d] "
-				"result=%d\n",
-			       __func__, opp_def->freq,
-			       opp_def->hwmod_name, i, r);
+			dev_err(dev, "%s: add OPP %ld failed for %s [%d] result=%d\n",
+				__func__, opp_def->freq,
+				opp_def->hwmod_name, i, r);
 		} else {
 			if (!opp_def->default_available)
 				r = opp_disable(dev, opp_def->freq);
 			if (r)
-				dev_err(dev, "%s: disable %ld failed for %s "
-					"[%d] result=%d\n",
+				dev_err(dev, "%s: disable %ld failed for %s [%d] result=%d\n",
 					__func__, opp_def->freq,
 					opp_def->hwmod_name, i, r);
 		}
diff --git a/arch/arm/mach-omap2/opp2420_data.c b/arch/arm/mach-omap2/opp2420_data.c
index 5037e76..a9e8cf2 100644
--- a/arch/arm/mach-omap2/opp2420_data.c
+++ b/arch/arm/mach-omap2/opp2420_data.c
@@ -28,7 +28,7 @@
  *     http://repository.maemo.org/pool/diablo/free/k/kernel-source-diablo/
  */
 
-#include <plat/hardware.h>
+#include <linux/kernel.h>
 
 #include "opp2xxx.h"
 #include "sdrc.h"
diff --git a/arch/arm/mach-omap2/opp2430_data.c b/arch/arm/mach-omap2/opp2430_data.c
index 750805c..0e75ec3 100644
--- a/arch/arm/mach-omap2/opp2430_data.c
+++ b/arch/arm/mach-omap2/opp2430_data.c
@@ -26,7 +26,7 @@
  * This is technically part of the OMAP2xxx clock code.
  */
 
-#include <plat/hardware.h>
+#include <linux/kernel.h>
 
 #include "opp2xxx.h"
 #include "sdrc.h"
diff --git a/arch/arm/mach-omap2/opp3xxx_data.c b/arch/arm/mach-omap2/opp3xxx_data.c
index d95f3f9..75cef5f 100644
--- a/arch/arm/mach-omap2/opp3xxx_data.c
+++ b/arch/arm/mach-omap2/opp3xxx_data.c
@@ -19,8 +19,6 @@
  */
 #include <linux/module.h>
 
-#include <plat/cpu.h>
-
 #include "control.h"
 #include "omap_opp_data.h"
 #include "pm.h"
diff --git a/arch/arm/mach-omap2/opp4xxx_data.c b/arch/arm/mach-omap2/opp4xxx_data.c
index c95415d..a9fd6d5 100644
--- a/arch/arm/mach-omap2/opp4xxx_data.c
+++ b/arch/arm/mach-omap2/opp4xxx_data.c
@@ -20,8 +20,7 @@
  */
 #include <linux/module.h>
 
-#include <plat/cpu.h>
-
+#include "soc.h"
 #include "control.h"
 #include "omap_opp_data.h"
 #include "pm.h"
diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c
index 814bcd9..3e1345f 100644
--- a/arch/arm/mach-omap2/pm-debug.c
+++ b/arch/arm/mach-omap2/pm-debug.c
@@ -28,7 +28,6 @@
 #include <linux/slab.h>
 
 #include <plat/clock.h>
-#include <plat/board.h>
 #include "powerdomain.h"
 #include "clockdomain.h"
 #include <plat/dmtimer.h>
diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
index 9cb5ced..939bd6f 100644
--- a/arch/arm/mach-omap2/pm.c
+++ b/arch/arm/mach-omap2/pm.c
@@ -203,8 +203,8 @@ static int __init omap2_set_init_voltage(char *vdd_name, char *clk_name,
 	bootup_volt = opp_get_voltage(opp);
 	rcu_read_unlock();
 	if (!bootup_volt) {
-		pr_err("%s: unable to find voltage corresponding "
-			"to the bootup OPP for vdd_%s\n", __func__, vdd_name);
+		pr_err("%s: unable to find voltage corresponding to the bootup OPP for vdd_%s\n",
+		       __func__, vdd_name);
 		goto exit;
 	}
 
diff --git a/arch/arm/mach-omap2/pm24xx.c b/arch/arm/mach-omap2/pm24xx.c
index 2edeffc..8af6cd6 100644
--- a/arch/arm/mach-omap2/pm24xx.c
+++ b/arch/arm/mach-omap2/pm24xx.c
@@ -29,6 +29,7 @@
 #include <linux/irq.h>
 #include <linux/time.h>
 #include <linux/gpio.h>
+#include <linux/platform_data/gpio-omap.h>
 
 #include <asm/mach/time.h>
 #include <asm/mach/irq.h>
@@ -38,9 +39,6 @@
 #include <plat/clock.h>
 #include <plat/sram.h>
 #include <plat/dma.h>
-#include <plat/board.h>
-
-#include <mach/irqs.h>
 
 #include "common.h"
 #include "prm2xxx_3xxx.h"
@@ -352,16 +350,6 @@ int __init omap2_pm_init(void)
 
 	prcm_setup_regs();
 
-	/* Hack to prevent MPU retention when STI console is enabled. */
-	{
-		const struct omap_sti_console_config *sti;
-
-		sti = omap_get_config(OMAP_TAG_STI_CONSOLE,
-				      struct omap_sti_console_config);
-		if (sti != NULL && sti->enable)
-			sti_console_enabled = 1;
-	}
-
 	/*
 	 * We copy the assembler sleep/wakeup routines to SRAM.
 	 * These routines need to be in SRAM as that's the only
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 05bd8f0..ba670db 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -28,6 +28,8 @@
 #include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
+#include <linux/platform_data/gpio-omap.h>
+
 #include <trace/events/power.h>
 
 #include <asm/suspend.h>
@@ -389,9 +391,8 @@ restore:
 	list_for_each_entry(pwrst, &pwrst_list, node) {
 		state = pwrdm_read_prev_pwrst(pwrst->pwrdm);
 		if (state > pwrst->next_state) {
-			pr_info("Powerdomain (%s) didn't enter "
-				"target state %d\n",
-			       pwrst->pwrdm->name, pwrst->next_state);
+			pr_info("Powerdomain (%s) didn't enter target state %d\n",
+				pwrst->pwrdm->name, pwrst->next_state);
 			ret = -1;
 		}
 		omap_set_pwrdm_state(pwrst->pwrdm, pwrst->saved_state);
@@ -731,8 +732,7 @@ int __init omap3_pm_init(void)
 		omap3_secure_ram_storage =
 			kmalloc(0x803F, GFP_KERNEL);
 		if (!omap3_secure_ram_storage)
-			pr_err("Memory allocation failed when "
-			       "allocating for secure sram context\n");
+			pr_err("Memory allocation failed when allocating for secure sram context\n");
 
 		local_irq_disable();
 		local_fiq_disable();
diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c
index ea24174..04922d1 100644
--- a/arch/arm/mach-omap2/pm44xx.c
+++ b/arch/arm/mach-omap2/pm44xx.c
@@ -69,9 +69,8 @@ static int omap4_pm_suspend(void)
 	list_for_each_entry(pwrst, &pwrst_list, node) {
 		state = pwrdm_read_prev_pwrst(pwrst->pwrdm);
 		if (state > pwrst->next_state) {
-			pr_info("Powerdomain (%s) didn't enter "
-			       "target state %d\n",
-			       pwrst->pwrdm->name, pwrst->next_state);
+			pr_info("Powerdomain (%s) didn't enter target state %d\n",
+				pwrst->pwrdm->name, pwrst->next_state);
 			ret = -1;
 		}
 		omap_set_pwrdm_state(pwrst->pwrdm, pwrst->saved_state);
@@ -189,8 +188,7 @@ int __init omap4_pm_init(void)
 	ret |= clkdm_add_wkdep(ducati_clkdm, l3_1_clkdm);
 	ret |= clkdm_add_wkdep(ducati_clkdm, l3_2_clkdm);
 	if (ret) {
-		pr_err("Failed to add MPUSS -> L3/EMIF/L4PER, DUCATI -> L3 "
-				"wakeup dependency\n");
+		pr_err("Failed to add MPUSS -> L3/EMIF/L4PER, DUCATI -> L3 wakeup dependency\n");
 		goto err2;
 	}
 
diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
index 69b36e1..1678a32 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -28,11 +28,13 @@
 #include "prm44xx.h"
 
 #include <asm/cpu.h>
-#include <plat/cpu.h>
+
+#include <plat/prcm.h>
+
 #include "powerdomain.h"
 #include "clockdomain.h"
-#include <plat/prcm.h>
 
+#include "soc.h"
 #include "pm.h"
 
 #define PWRDM_TRACE_STATES_FLAG	(1<<31)
@@ -339,8 +341,8 @@ int pwrdm_add_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm)
 	if (!pwrdm || !clkdm)
 		return -EINVAL;
 
-	pr_debug("powerdomain: associating clockdomain %s with powerdomain "
-		 "%s\n", clkdm->name, pwrdm->name);
+	pr_debug("powerdomain: %s: associating clockdomain %s\n",
+		 pwrdm->name, clkdm->name);
 
 	for (i = 0; i < PWRDM_MAX_CLKDMS; i++) {
 		if (!pwrdm->pwrdm_clkdms[i])
@@ -354,8 +356,8 @@ int pwrdm_add_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm)
 	}
 
 	if (i == PWRDM_MAX_CLKDMS) {
-		pr_debug("powerdomain: increase PWRDM_MAX_CLKDMS for "
-			 "pwrdm %s clkdm %s\n", pwrdm->name, clkdm->name);
+		pr_debug("powerdomain: %s: increase PWRDM_MAX_CLKDMS for clkdm %s\n",
+			 pwrdm->name, clkdm->name);
 		WARN_ON(1);
 		ret = -ENOMEM;
 		goto pac_exit;
@@ -387,16 +389,16 @@ int pwrdm_del_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm)
 	if (!pwrdm || !clkdm)
 		return -EINVAL;
 
-	pr_debug("powerdomain: dissociating clockdomain %s from powerdomain "
-		 "%s\n", clkdm->name, pwrdm->name);
+	pr_debug("powerdomain: %s: dissociating clockdomain %s\n",
+		 pwrdm->name, clkdm->name);
 
 	for (i = 0; i < PWRDM_MAX_CLKDMS; i++)
 		if (pwrdm->pwrdm_clkdms[i] == clkdm)
 			break;
 
 	if (i == PWRDM_MAX_CLKDMS) {
-		pr_debug("powerdomain: clkdm %s not associated with pwrdm "
-			 "%s ?!\n", clkdm->name, pwrdm->name);
+		pr_debug("powerdomain: %s: clkdm %s not associated?!\n",
+			 pwrdm->name, clkdm->name);
 		ret = -ENOENT;
 		goto pdc_exit;
 	}
@@ -485,7 +487,7 @@ int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
 	if (!(pwrdm->pwrsts & (1 << pwrst)))
 		return -EINVAL;
 
-	pr_debug("powerdomain: setting next powerstate for %s to %0x\n",
+	pr_debug("powerdomain: %s: setting next powerstate to %0x\n",
 		 pwrdm->name, pwrst);
 
 	if (arch_pwrdm && arch_pwrdm->pwrdm_set_next_pwrst) {
@@ -587,7 +589,7 @@ int pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst)
 	if (!(pwrdm->pwrsts_logic_ret & (1 << pwrst)))
 		return -EINVAL;
 
-	pr_debug("powerdomain: setting next logic powerstate for %s to %0x\n",
+	pr_debug("powerdomain: %s: setting next logic powerstate to %0x\n",
 		 pwrdm->name, pwrst);
 
 	if (arch_pwrdm && arch_pwrdm->pwrdm_set_logic_retst)
@@ -624,8 +626,8 @@ int pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, u8 pwrst)
 	if (!(pwrdm->pwrsts_mem_on[bank] & (1 << pwrst)))
 		return -EINVAL;
 
-	pr_debug("powerdomain: setting next memory powerstate for domain %s "
-		 "bank %0x while pwrdm-ON to %0x\n", pwrdm->name, bank, pwrst);
+	pr_debug("powerdomain: %s: setting next memory powerstate for bank %0x while pwrdm-ON to %0x\n",
+		 pwrdm->name, bank, pwrst);
 
 	if (arch_pwrdm && arch_pwrdm->pwrdm_set_mem_onst)
 		ret = arch_pwrdm->pwrdm_set_mem_onst(pwrdm, bank, pwrst);
@@ -662,8 +664,8 @@ int pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank, u8 pwrst)
 	if (!(pwrdm->pwrsts_mem_ret[bank] & (1 << pwrst)))
 		return -EINVAL;
 
-	pr_debug("powerdomain: setting next memory powerstate for domain %s "
-		 "bank %0x while pwrdm-RET to %0x\n", pwrdm->name, bank, pwrst);
+	pr_debug("powerdomain: %s: setting next memory powerstate for bank %0x while pwrdm-RET to %0x\n",
+		 pwrdm->name, bank, pwrst);
 
 	if (arch_pwrdm && arch_pwrdm->pwrdm_set_mem_retst)
 		ret = arch_pwrdm->pwrdm_set_mem_retst(pwrdm, bank, pwrst);
@@ -841,7 +843,7 @@ int pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm)
 	 * warn & fail if it is not ON.
 	 */
 
-	pr_debug("powerdomain: clearing previous power state reg for %s\n",
+	pr_debug("powerdomain: %s: clearing previous power state reg\n",
 		 pwrdm->name);
 
 	if (arch_pwrdm && arch_pwrdm->pwrdm_clear_all_prev_pwrst)
@@ -871,8 +873,7 @@ int pwrdm_enable_hdwr_sar(struct powerdomain *pwrdm)
 	if (!(pwrdm->flags & PWRDM_HAS_HDWR_SAR))
 		return ret;
 
-	pr_debug("powerdomain: %s: setting SAVEANDRESTORE bit\n",
-		 pwrdm->name);
+	pr_debug("powerdomain: %s: setting SAVEANDRESTORE bit\n", pwrdm->name);
 
 	if (arch_pwrdm && arch_pwrdm->pwrdm_enable_hdwr_sar)
 		ret = arch_pwrdm->pwrdm_enable_hdwr_sar(pwrdm);
@@ -901,8 +902,7 @@ int pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm)
 	if (!(pwrdm->flags & PWRDM_HAS_HDWR_SAR))
 		return ret;
 
-	pr_debug("powerdomain: %s: clearing SAVEANDRESTORE bit\n",
-		 pwrdm->name);
+	pr_debug("powerdomain: %s: clearing SAVEANDRESTORE bit\n", pwrdm->name);
 
 	if (arch_pwrdm && arch_pwrdm->pwrdm_disable_hdwr_sar)
 		ret = arch_pwrdm->pwrdm_disable_hdwr_sar(pwrdm);
diff --git a/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c b/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c
index 0f0a9f1..3950ccf 100644
--- a/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c
+++ b/arch/arm/mach-omap2/powerdomain2xxx_3xxx.c
@@ -122,8 +122,8 @@ static int omap2_pwrdm_wait_transition(struct powerdomain *pwrdm)
 			udelay(1);
 
 	if (c > PWRDM_TRANSITION_BAILOUT) {
-		printk(KERN_ERR "powerdomain: waited too long for "
-			"powerdomain %s to complete transition\n", pwrdm->name);
+		pr_err("powerdomain: %s: waited too long to complete transition\n",
+		       pwrdm->name);
 		return -EAGAIN;
 	}
 
diff --git a/arch/arm/mach-omap2/powerdomain44xx.c b/arch/arm/mach-omap2/powerdomain44xx.c
index 601325b..aeac6f3 100644
--- a/arch/arm/mach-omap2/powerdomain44xx.c
+++ b/arch/arm/mach-omap2/powerdomain44xx.c
@@ -198,8 +198,8 @@ static int omap4_pwrdm_wait_transition(struct powerdomain *pwrdm)
 		udelay(1);
 
 	if (c > PWRDM_TRANSITION_BAILOUT) {
-		printk(KERN_ERR "powerdomain: waited too long for "
-		       "powerdomain %s to complete transition\n", pwrdm->name);
+		pr_err("powerdomain: %s: waited too long to complete transition\n",
+		       pwrdm->name);
 		return -EAGAIN;
 	}
 
diff --git a/arch/arm/mach-omap2/powerdomains3xxx_data.c b/arch/arm/mach-omap2/powerdomains3xxx_data.c
index bb883e4..8b23d23 100644
--- a/arch/arm/mach-omap2/powerdomains3xxx_data.c
+++ b/arch/arm/mach-omap2/powerdomains3xxx_data.c
@@ -15,11 +15,9 @@
 #include <linux/init.h>
 #include <linux/bug.h>
 
-#include <plat/cpu.h>
-
+#include "soc.h"
 #include "powerdomain.h"
 #include "powerdomains2xxx_3xxx_data.h"
-
 #include "prcm-common.h"
 #include "prm2xxx_3xxx.h"
 #include "prm-regbits-34xx.h"
diff --git a/arch/arm/mach-omap2/prcm.c b/arch/arm/mach-omap2/prcm.c
index 053e24e..0f51e03 100644
--- a/arch/arm/mach-omap2/prcm.c
+++ b/arch/arm/mach-omap2/prcm.c
@@ -27,7 +27,6 @@
 
 #include "common.h"
 #include <plat/prcm.h>
-#include <plat/irqs.h>
 
 #include "clock.h"
 #include "clock2xxx.h"
@@ -140,11 +139,11 @@ int omap2_cm_wait_idlest(void __iomem *reg, u32 mask, u8 idlest,
 			  MAX_MODULE_ENABLE_WAIT, i);
 
 	if (i < MAX_MODULE_ENABLE_WAIT)
-		pr_debug("cm: Module associated with clock %s ready after %d "
-			 "loops\n", name, i);
+		pr_debug("cm: Module associated with clock %s ready after %d loops\n",
+			 name, i);
 	else
-		pr_err("cm: Module associated with clock %s didn't enable in "
-		       "%d tries\n", name, MAX_MODULE_ENABLE_WAIT);
+		pr_err("cm: Module associated with clock %s didn't enable in %d tries\n",
+		       name, MAX_MODULE_ENABLE_WAIT);
 
 	return (i < MAX_MODULE_ENABLE_WAIT) ? 1 : 0;
 };
diff --git a/arch/arm/mach-omap2/prm2xxx_3xxx.c b/arch/arm/mach-omap2/prm2xxx_3xxx.c
index a0309de..9529984 100644
--- a/arch/arm/mach-omap2/prm2xxx_3xxx.c
+++ b/arch/arm/mach-omap2/prm2xxx_3xxx.c
@@ -17,11 +17,10 @@
 #include <linux/io.h>
 #include <linux/irq.h>
 
-#include "common.h"
-#include <plat/cpu.h>
 #include <plat/prcm.h>
-#include <plat/irqs.h>
 
+#include "soc.h"
+#include "common.h"
 #include "vp.h"
 
 #include "prm2xxx_3xxx.h"
@@ -40,7 +39,7 @@ static struct omap_prcm_irq_setup omap3_prcm_irq_setup = {
 	.nr_regs		= 1,
 	.irqs			= omap3_prcm_irqs,
 	.nr_irqs		= ARRAY_SIZE(omap3_prcm_irqs),
-	.irq			= INT_34XX_PRCM_MPU_IRQ,
+	.irq			= 11 + OMAP_INTC_START,
 	.read_pending_irqs	= &omap3xxx_prm_read_pending_irqs,
 	.ocp_barrier		= &omap3xxx_prm_ocp_barrier,
 	.save_and_clear_irqen	= &omap3xxx_prm_save_and_clear_irqen,
diff --git a/arch/arm/mach-omap2/prm44xx.c b/arch/arm/mach-omap2/prm44xx.c
index bb727c2..f0c4d5f 100644
--- a/arch/arm/mach-omap2/prm44xx.c
+++ b/arch/arm/mach-omap2/prm44xx.c
@@ -17,10 +17,9 @@
 #include <linux/err.h>
 #include <linux/io.h>
 
-#include <plat/cpu.h>
-#include <plat/irqs.h>
 #include <plat/prcm.h>
 
+#include "soc.h"
 #include "iomap.h"
 #include "common.h"
 #include "vp.h"
@@ -40,7 +39,7 @@ static struct omap_prcm_irq_setup omap4_prcm_irq_setup = {
 	.nr_regs		= 2,
 	.irqs			= omap4_prcm_irqs,
 	.nr_irqs		= ARRAY_SIZE(omap4_prcm_irqs),
-	.irq			= OMAP44XX_IRQ_PRCM,
+	.irq			= 11 + OMAP44XX_IRQ_GIC_START,
 	.read_pending_irqs	= &omap44xx_prm_read_pending_irqs,
 	.ocp_barrier		= &omap44xx_prm_ocp_barrier,
 	.save_and_clear_irqen	= &omap44xx_prm_save_and_clear_irqen,
diff --git a/arch/arm/mach-omap2/prm_common.c b/arch/arm/mach-omap2/prm_common.c
index 03b126d..6b4d332 100644
--- a/arch/arm/mach-omap2/prm_common.c
+++ b/arch/arm/mach-omap2/prm_common.c
@@ -26,7 +26,6 @@
 
 #include <plat/common.h>
 #include <plat/prcm.h>
-#include <plat/irqs.h>
 
 #include "prm2xxx_3xxx.h"
 #include "prm44xx.h"
diff --git a/arch/arm/mach-omap2/sdrc2xxx.c b/arch/arm/mach-omap2/sdrc2xxx.c
index 1133bb2..73e55e4 100644
--- a/arch/arm/mach-omap2/sdrc2xxx.c
+++ b/arch/arm/mach-omap2/sdrc2xxx.c
@@ -24,11 +24,11 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 
-#include <plat/hardware.h>
 #include <plat/clock.h>
 #include <plat/sram.h>
 #include <plat/sdrc.h>
 
+#include "soc.h"
 #include "iomap.h"
 #include "common.h"
 #include "prm2xxx_3xxx.h"
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index c1b93c7..0405c81 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -29,11 +29,11 @@
 
 #include <plat/omap-serial.h>
 #include "common.h"
-#include <plat/board.h>
 #include <plat/dma.h>
 #include <plat/omap_hwmod.h>
 #include <plat/omap_device.h>
 #include <plat/omap-pm.h>
+#include <plat/serial.h>
 
 #include "prm2xxx_3xxx.h"
 #include "pm.h"
@@ -81,8 +81,9 @@ static struct omap_uart_port_info omap_serial_default_info[] __initdata = {
 };
 
 #ifdef CONFIG_PM
-static void omap_uart_enable_wakeup(struct platform_device *pdev, bool enable)
+static void omap_uart_enable_wakeup(struct device *dev, bool enable)
 {
+	struct platform_device *pdev = to_platform_device(dev);
 	struct omap_device *od = to_omap_device(pdev);
 
 	if (!od)
@@ -99,15 +100,17 @@ static void omap_uart_enable_wakeup(struct platform_device *pdev, bool enable)
  * in Smartidle Mode When Configured for DMA Operations.
  * WA: configure uart in force idle mode.
  */
-static void omap_uart_set_noidle(struct platform_device *pdev)
+static void omap_uart_set_noidle(struct device *dev)
 {
+	struct platform_device *pdev = to_platform_device(dev);
 	struct omap_device *od = to_omap_device(pdev);
 
 	omap_hwmod_set_slave_idlemode(od->hwmods[0], HWMOD_IDLEMODE_NO);
 }
 
-static void omap_uart_set_smartidle(struct platform_device *pdev)
+static void omap_uart_set_smartidle(struct device *dev)
 {
+	struct platform_device *pdev = to_platform_device(dev);
 	struct omap_device *od = to_omap_device(pdev);
 	u8 idlemode;
 
@@ -120,10 +123,10 @@ static void omap_uart_set_smartidle(struct platform_device *pdev)
 }
 
 #else
-static void omap_uart_enable_wakeup(struct platform_device *pdev, bool enable)
+static void omap_uart_enable_wakeup(struct device *dev, bool enable)
 {}
-static void omap_uart_set_noidle(struct platform_device *pdev) {}
-static void omap_uart_set_smartidle(struct platform_device *pdev) {}
+static void omap_uart_set_noidle(struct device *dev) {}
+static void omap_uart_set_smartidle(struct device *dev) {}
 #endif /* CONFIG_PM */
 
 #ifdef CONFIG_OMAP_MUX
@@ -229,9 +232,8 @@ static int __init omap_serial_early_init(void)
 
 			if (console_loglevel >= 10) {
 				uart_debug = true;
-				pr_info("%s used as console in debug mode"
-						" uart%d clocks will not be"
-						" gated", uart_name, uart->num);
+				pr_info("%s used as console in debug mode: uart%d clocks will not be gated",
+					uart_name, uart->num);
 			}
 
 			if (cmdline_find_option("no_console_suspend"))
@@ -304,6 +306,9 @@ void __init omap_serial_init_port(struct omap_board_data *bdata,
 	omap_up.dma_rx_timeout = info->dma_rx_timeout;
 	omap_up.dma_rx_poll_rate = info->dma_rx_poll_rate;
 	omap_up.autosuspend_timeout = info->autosuspend_timeout;
+	omap_up.DTR_gpio = info->DTR_gpio;
+	omap_up.DTR_inverted = info->DTR_inverted;
+	omap_up.DTR_present = info->DTR_present;
 
 	pdata = &omap_up;
 	pdata_size = sizeof(struct omap_uart_port_info);
@@ -313,8 +318,11 @@ void __init omap_serial_init_port(struct omap_board_data *bdata,
 
 	pdev = omap_device_build(name, uart->num, oh, pdata, pdata_size,
 				 NULL, 0, false);
-	WARN(IS_ERR(pdev), "Could not build omap_device for %s: %s.\n",
-	     name, oh->name);
+	if (IS_ERR(pdev)) {
+		WARN(1, "Could not build omap_device for %s: %s.\n", name,
+		     oh->name);
+		return;
+	}
 
 	if ((console_uart_id == bdata->id) && no_console_suspend)
 		omap_device_disable_idle_on_suspend(pdev);
diff --git a/arch/arm/mach-omap2/sleep24xx.S b/arch/arm/mach-omap2/sleep24xx.S
index d4bf904..ce0ccd2 100644
--- a/arch/arm/mach-omap2/sleep24xx.S
+++ b/arch/arm/mach-omap2/sleep24xx.S
@@ -28,8 +28,7 @@
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 
-#include <plat/omap24xx.h>
-
+#include "omap24xx.h"
 #include "sdrc.h"
 
 /* First address of reserved address space?  apparently valid for OMAP2 & 3 */
diff --git a/arch/arm/mach-omap2/sleep34xx.S b/arch/arm/mach-omap2/sleep34xx.S
index 1f62f23..5069879 100644
--- a/arch/arm/mach-omap2/sleep34xx.S
+++ b/arch/arm/mach-omap2/sleep34xx.S
@@ -26,9 +26,9 @@
 
 #include <asm/assembler.h>
 
-#include <plat/hardware.h>
 #include <plat/sram.h>
 
+#include "omap34xx.h"
 #include "iomap.h"
 #include "cm2xxx_3xxx.h"
 #include "prm2xxx_3xxx.h"
diff --git a/arch/arm/mach-omap2/sleep44xx.S b/arch/arm/mach-omap2/sleep44xx.S
index 91e71d8..88ff83a 100644
--- a/arch/arm/mach-omap2/sleep44xx.S
+++ b/arch/arm/mach-omap2/sleep44xx.S
@@ -14,10 +14,10 @@
 #include <asm/memory.h>
 #include <asm/hardware/cache-l2x0.h>
 
-#include <plat/omap44xx.h>
-#include <mach/omap-secure.h>
+#include "omap-secure.h"
 
 #include "common.h"
+#include "omap44xx.h"
 #include "omap4-sar-layout.h"
 
 #if defined(CONFIG_SMP) && defined(CONFIG_PM)
diff --git a/arch/arm/mach-omap2/soc.h b/arch/arm/mach-omap2/soc.h
new file mode 100644
index 0000000..fc9b96d
--- /dev/null
+++ b/arch/arm/mach-omap2/soc.h
@@ -0,0 +1,7 @@
+#include <plat/cpu.h>
+#include "omap24xx.h"
+#include "omap34xx.h"
+#include "omap44xx.h"
+#include "ti81xx.h"
+#include "am33xx.h"
+#include "omap54xx.h"
diff --git a/arch/arm/mach-omap2/sr_device.c b/arch/arm/mach-omap2/sr_device.c
index d033a65..cbeae56 100644
--- a/arch/arm/mach-omap2/sr_device.c
+++ b/arch/arm/mach-omap2/sr_device.c
@@ -104,16 +104,15 @@ static int __init sr_dev_init(struct omap_hwmod *oh, void *user)
 
 	sr_data = kzalloc(sizeof(struct omap_sr_data), GFP_KERNEL);
 	if (!sr_data) {
-		pr_err("%s: Unable to allocate memory for %s sr_data.Error!\n",
-			__func__, oh->name);
+		pr_err("%s: Unable to allocate memory for %s sr_data\n",
+		       __func__, oh->name);
 		return -ENOMEM;
 	}
 
 	sr_dev_attr = (struct omap_smartreflex_dev_attr *)oh->dev_attr;
 	if (!sr_dev_attr || !sr_dev_attr->sensor_voltdm_name) {
-		pr_err("%s: No voltage domain specified for %s."
-				"Cannot initialize\n", __func__,
-					oh->name);
+		pr_err("%s: No voltage domain specified for %s. Cannot initialize\n",
+		       __func__, oh->name);
 		goto exit;
 	}
 
@@ -131,8 +130,8 @@ static int __init sr_dev_init(struct omap_hwmod *oh, void *user)
 
 	omap_voltage_get_volttable(sr_data->voltdm, &volt_data);
 	if (!volt_data) {
-		pr_warning("%s: No Voltage table registered fo VDD%d."
-			"Something really wrong\n\n", __func__, i + 1);
+		pr_err("%s: No Voltage table registered for VDD%d\n",
+		       __func__, i + 1);
 		goto exit;
 	}
 
diff --git a/arch/arm/mach-omap2/sram242x.S b/arch/arm/mach-omap2/sram242x.S
index ee0bfcc..8f7326c 100644
--- a/arch/arm/mach-omap2/sram242x.S
+++ b/arch/arm/mach-omap2/sram242x.S
@@ -32,8 +32,7 @@
 
 #include <asm/assembler.h>
 
-#include <mach/hardware.h>
-
+#include "soc.h"
 #include "iomap.h"
 #include "prm2xxx_3xxx.h"
 #include "cm2xxx_3xxx.h"
diff --git a/arch/arm/mach-omap2/sram243x.S b/arch/arm/mach-omap2/sram243x.S
index d4d39ef..b140d65 100644
--- a/arch/arm/mach-omap2/sram243x.S
+++ b/arch/arm/mach-omap2/sram243x.S
@@ -32,8 +32,7 @@
 
 #include <asm/assembler.h>
 
-#include <mach/hardware.h>
-
+#include "soc.h"
 #include "iomap.h"
 #include "prm2xxx_3xxx.h"
 #include "cm2xxx_3xxx.h"
diff --git a/arch/arm/mach-omap2/sram34xx.S b/arch/arm/mach-omap2/sram34xx.S
index df5a213..2d0ceaa 100644
--- a/arch/arm/mach-omap2/sram34xx.S
+++ b/arch/arm/mach-omap2/sram34xx.S
@@ -29,8 +29,7 @@
 
 #include <asm/assembler.h>
 
-#include <mach/hardware.h>
-
+#include "soc.h"
 #include "iomap.h"
 #include "sdrc.h"
 #include "cm2xxx_3xxx.h"
diff --git a/arch/arm/mach-omap2/ti81xx.h b/arch/arm/mach-omap2/ti81xx.h
new file mode 100644
index 0000000..8f9843f
--- /dev/null
+++ b/arch/arm/mach-omap2/ti81xx.h
@@ -0,0 +1,27 @@
+/*
+ * This file contains the address data for various TI81XX modules.
+ *
+ * Copyright (C) 2010 Texas Instruments, Inc. - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __ASM_ARCH_TI81XX_H
+#define __ASM_ARCH_TI81XX_H
+
+#define L4_SLOW_TI81XX_BASE	0x48000000
+
+#define TI81XX_SCM_BASE		0x48140000
+#define TI81XX_CTRL_BASE	TI81XX_SCM_BASE
+#define TI81XX_PRCM_BASE	0x48180000
+
+#define TI81XX_ARM_INTC_BASE	0x48200000
+
+#endif /* __ASM_ARCH_TI81XX_H */
diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
index 2ba4f57..810aa1a 100644
--- a/arch/arm/mach-omap2/timer.c
+++ b/arch/arm/mach-omap2/timer.c
@@ -36,16 +36,19 @@
 #include <linux/clocksource.h>
 #include <linux/clockchips.h>
 #include <linux/slab.h>
+#include <linux/of.h>
 
 #include <asm/mach/time.h>
-#include <plat/dmtimer.h>
 #include <asm/smp_twd.h>
 #include <asm/sched_clock.h>
-#include "common.h"
+
 #include <plat/omap_hwmod.h>
 #include <plat/omap_device.h>
+#include <plat/dmtimer.h>
 #include <plat/omap-pm.h>
 
+#include "soc.h"
+#include "common.h"
 #include "powerdomain.h"
 
 /* Parent clocks, eventually these will come from the clock framework */
@@ -211,7 +214,7 @@ static void __init omap2_gp_clockevent_init(int gptimer_id,
 	res = omap_dm_timer_init_one(&clkev, gptimer_id, fck_source);
 	BUG_ON(res);
 
-	omap2_gp_timer_irq.dev_id = (void *)&clkev;
+	omap2_gp_timer_irq.dev_id = &clkev;
 	setup_irq(clkev.irq, &omap2_gp_timer_irq);
 
 	__omap_dm_timer_int_enable(&clkev, OMAP_TIMER_INT_OVERFLOW);
@@ -380,8 +383,7 @@ OMAP_SYS_TIMER(3_am33xx)
 #ifdef CONFIG_ARCH_OMAP4
 #ifdef CONFIG_LOCAL_TIMERS
 static DEFINE_TWD_LOCAL_TIMER(twd_local_timer,
-			      OMAP44XX_LOCAL_TWD_BASE,
-			      OMAP44XX_IRQ_LOCALTIMER);
+			      OMAP44XX_LOCAL_TWD_BASE, 29 + OMAP_INTC_START);
 #endif
 
 static void __init omap4_timer_init(void)
@@ -393,6 +395,11 @@ static void __init omap4_timer_init(void)
 	if (omap_rev() != OMAP4430_REV_ES1_0) {
 		int err;
 
+		if (of_have_populated_dt()) {
+			twd_local_timer_of_register();
+			return;
+		}
+
 		err = twd_local_timer_register(&twd_local_timer);
 		if (err)
 			pr_err("twd_local_timer_register failed %d\n", err);
diff --git a/arch/arm/mach-omap2/twl-common.c b/arch/arm/mach-omap2/twl-common.c
index db5ff66..d280761 100644
--- a/arch/arm/mach-omap2/twl-common.c
+++ b/arch/arm/mach-omap2/twl-common.c
@@ -29,6 +29,7 @@
 #include <plat/i2c.h>
 #include <plat/usb.h>
 
+#include "soc.h"
 #include "twl-common.h"
 #include "pm.h"
 #include "voltage.h"
@@ -84,7 +85,7 @@ void __init omap4_pmic_init(const char *pmic_type,
 	omap_mux_init_signal("sys_nirq1", OMAP_PIN_INPUT_PULLUP | OMAP_PIN_OFF_WAKEUPENABLE);
 	strncpy(omap4_i2c1_board_info[0].type, pmic_type,
 		sizeof(omap4_i2c1_board_info[0].type));
-	omap4_i2c1_board_info[0].irq = OMAP44XX_IRQ_SYS_1N;
+	omap4_i2c1_board_info[0].irq = 7 + OMAP44XX_IRQ_GIC_START;
 	omap4_i2c1_board_info[0].platform_data = pmic_data;
 
 	/* TWL6040 audio IC part */
@@ -251,11 +252,10 @@ void __init omap3_pmic_get_config(struct twl4030_platform_data *pmic_data,
 
 #if defined(CONFIG_ARCH_OMAP4)
 static struct twl4030_usb_data omap4_usb_pdata = {
-	.phy_init	= omap4430_phy_init,
-	.phy_exit	= omap4430_phy_exit,
-	.phy_power	= omap4430_phy_power,
-	.phy_set_clock	= omap4430_phy_set_clk,
-	.phy_suspend	= omap4430_phy_suspend,
+};
+
+static struct regulator_consumer_supply omap4_vdda_hdmi_dac_supplies[] = {
+	REGULATOR_SUPPLY("vdda_hdmi_dac", "omapdss_hdmi"),
 };
 
 static struct regulator_init_data omap4_vdac_idata = {
@@ -267,6 +267,8 @@ static struct regulator_init_data omap4_vdac_idata = {
 		.valid_ops_mask		= REGULATOR_CHANGE_MODE
 					| REGULATOR_CHANGE_STATUS,
 	},
+	.num_consumer_supplies	= ARRAY_SIZE(omap4_vdda_hdmi_dac_supplies),
+	.consumer_supplies	= omap4_vdda_hdmi_dac_supplies,
 	.supply_regulator	= "V2V1",
 };
 
@@ -538,3 +540,30 @@ void __init omap4_pmic_get_config(struct twl4030_platform_data *pmic_data,
 		pmic_data->v2v1 = &omap4_v2v1_idata;
 }
 #endif /* CONFIG_ARCH_OMAP4 */
+
+#if defined(CONFIG_SND_OMAP_SOC_OMAP_TWL4030) || \
+	defined(CONFIG_SND_OMAP_SOC_OMAP_TWL4030_MODULE)
+#include <linux/platform_data/omap-twl4030.h>
+
+static struct omap_tw4030_pdata omap_twl4030_audio_data;
+
+static struct platform_device audio_device = {
+	.name		= "omap-twl4030",
+	.id		= -1,
+	.dev = {
+		.platform_data = &omap_twl4030_audio_data,
+	},
+};
+
+void __init omap_twl4030_audio_init(char *card_name)
+{
+	omap_twl4030_audio_data.card_name = card_name;
+	platform_device_register(&audio_device);
+}
+
+#else /* SOC_OMAP_TWL4030 */
+void __init omap_twl4030_audio_init(char *card_name)
+{
+	return;
+}
+#endif /* SOC_OMAP_TWL4030 */
diff --git a/arch/arm/mach-omap2/twl-common.h b/arch/arm/mach-omap2/twl-common.h
index 8fe71cf..342db0e 100644
--- a/arch/arm/mach-omap2/twl-common.h
+++ b/arch/arm/mach-omap2/twl-common.h
@@ -1,7 +1,7 @@
 #ifndef __OMAP_PMIC_COMMON__
 #define __OMAP_PMIC_COMMON__
 
-#include <plat/irqs.h>
+#include "common.h"
 
 #define TWL_COMMON_PDATA_USB		(1 << 0)
 #define TWL_COMMON_PDATA_BCI		(1 << 1)
@@ -40,13 +40,13 @@ void omap_pmic_late_init(void);
 static inline void omap2_pmic_init(const char *pmic_type,
 				   struct twl4030_platform_data *pmic_data)
 {
-	omap_pmic_init(2, 2600, pmic_type, INT_24XX_SYS_NIRQ, pmic_data);
+	omap_pmic_init(2, 2600, pmic_type, 7 + OMAP_INTC_START, pmic_data);
 }
 
 static inline void omap3_pmic_init(const char *pmic_type,
 				   struct twl4030_platform_data *pmic_data)
 {
-	omap_pmic_init(1, 2600, pmic_type, INT_34XX_SYS_NIRQ, pmic_data);
+	omap_pmic_init(1, 2600, pmic_type, 7 + OMAP_INTC_START, pmic_data);
 }
 
 void omap4_pmic_init(const char *pmic_type,
@@ -59,4 +59,6 @@ void omap3_pmic_get_config(struct twl4030_platform_data *pmic_data,
 void omap4_pmic_get_config(struct twl4030_platform_data *pmic_data,
 			   u32 pdata_flags, u32 regulators_flags);
 
+void omap_twl4030_audio_init(char *card_name);
+
 #endif /* __OMAP_PMIC_COMMON__ */
diff --git a/arch/arm/mach-omap2/usb-host.c b/arch/arm/mach-omap2/usb-host.c
index dde8a11..3c43449 100644
--- a/arch/arm/mach-omap2/usb-host.c
+++ b/arch/arm/mach-omap2/usb-host.c
@@ -25,8 +25,6 @@
 
 #include <asm/io.h>
 
-#include <mach/hardware.h>
-#include <mach/irqs.h>
 #include <plat/usb.h>
 #include <plat/omap_device.h>
 
@@ -35,10 +33,12 @@
 #ifdef CONFIG_MFD_OMAP_USB_HOST
 
 #define OMAP_USBHS_DEVICE	"usbhs_omap"
+#define OMAP_USBTLL_DEVICE	"usbhs_tll"
 #define	USBHS_UHH_HWMODNAME	"usb_host_hs"
 #define USBHS_TLL_HWMODNAME	"usb_tll_hs"
 
 static struct usbhs_omap_platform_data		usbhs_data;
+static struct usbtll_omap_platform_data		usbtll_data;
 static struct ehci_hcd_omap_platform_data	ehci_data;
 static struct ohci_hcd_omap_platform_data	ohci_data;
 
@@ -487,13 +487,14 @@ void __init setup_4430ohci_io_mux(const enum usbhs_omap_port_mode *port_mode)
 
 void __init usbhs_init(const struct usbhs_omap_board_data *pdata)
 {
-	struct omap_hwmod	*oh[2];
+	struct omap_hwmod	*uhh_hwm, *tll_hwm;
 	struct platform_device	*pdev;
 	int			bus_id = -1;
 	int			i;
 
 	for (i = 0; i < OMAP3_HS_USB_PORTS; i++) {
 		usbhs_data.port_mode[i] = pdata->port_mode[i];
+		usbtll_data.port_mode[i] = pdata->port_mode[i];
 		ohci_data.port_mode[i] = pdata->port_mode[i];
 		ehci_data.port_mode[i] = pdata->port_mode[i];
 		ehci_data.reset_gpio_port[i] = pdata->reset_gpio_port[i];
@@ -512,25 +513,35 @@ void __init usbhs_init(const struct usbhs_omap_board_data *pdata)
 		setup_4430ohci_io_mux(pdata->port_mode);
 	}
 
-	oh[0] = omap_hwmod_lookup(USBHS_UHH_HWMODNAME);
-	if (!oh[0]) {
+	uhh_hwm = omap_hwmod_lookup(USBHS_UHH_HWMODNAME);
+	if (!uhh_hwm) {
 		pr_err("Could not look up %s\n", USBHS_UHH_HWMODNAME);
 		return;
 	}
 
-	oh[1] = omap_hwmod_lookup(USBHS_TLL_HWMODNAME);
-	if (!oh[1]) {
+	tll_hwm = omap_hwmod_lookup(USBHS_TLL_HWMODNAME);
+	if (!tll_hwm) {
 		pr_err("Could not look up %s\n", USBHS_TLL_HWMODNAME);
 		return;
 	}
 
-	pdev = omap_device_build_ss(OMAP_USBHS_DEVICE, bus_id, oh, 2,
-				(void *)&usbhs_data, sizeof(usbhs_data),
+	pdev = omap_device_build(OMAP_USBTLL_DEVICE, bus_id, tll_hwm,
+				&usbtll_data, sizeof(usbtll_data),
 				omap_uhhtll_latency,
 				ARRAY_SIZE(omap_uhhtll_latency), false);
 	if (IS_ERR(pdev)) {
-		pr_err("Could not build hwmod devices %s,%s\n",
-			USBHS_UHH_HWMODNAME, USBHS_TLL_HWMODNAME);
+		pr_err("Could not build hwmod device %s\n",
+		       USBHS_TLL_HWMODNAME);
+		return;
+	}
+
+	pdev = omap_device_build(OMAP_USBHS_DEVICE, bus_id, uhh_hwm,
+				&usbhs_data, sizeof(usbhs_data),
+				omap_uhhtll_latency,
+				ARRAY_SIZE(omap_uhhtll_latency), false);
+	if (IS_ERR(pdev)) {
+		pr_err("Could not build hwmod devices %s\n",
+		       USBHS_UHH_HWMODNAME);
 		return;
 	}
 }
diff --git a/arch/arm/mach-omap2/usb-musb.c b/arch/arm/mach-omap2/usb-musb.c
index c4a5768..51da21c 100644
--- a/arch/arm/mach-omap2/usb-musb.c
+++ b/arch/arm/mach-omap2/usb-musb.c
@@ -23,14 +23,13 @@
 #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/am35xx.h>
 #include <plat/usb.h>
 #include <plat/omap_device.h>
+
+#include "am35xx.h"
+
 #include "mux.h"
 
 static struct musb_hdrc_config musb_config = {
@@ -117,7 +116,4 @@ void __init usb_musb_init(struct omap_musb_board_data *musb_board_data)
 	dev->dma_mask = &musb_dmamask;
 	dev->coherent_dma_mask = musb_dmamask;
 	put_device(dev);
-
-	if (cpu_is_omap44xx())
-		omap4430_phy_init(dev);
 }
diff --git a/arch/arm/mach-omap2/vc.c b/arch/arm/mach-omap2/vc.c
index 84da34f..880249b 100644
--- a/arch/arm/mach-omap2/vc.c
+++ b/arch/arm/mach-omap2/vc.c
@@ -12,8 +12,7 @@
 #include <linux/init.h>
 #include <linux/bug.h>
 
-#include <plat/cpu.h>
-
+#include "soc.h"
 #include "voltage.h"
 #include "vc.h"
 #include "prm-regbits-34xx.h"
@@ -116,9 +115,8 @@ int omap_vc_pre_scale(struct voltagedomain *voltdm,
 	}
 
 	if (!voltdm->pmic->uv_to_vsel) {
-		pr_err("%s: PMIC function to convert voltage in uV to"
-			"vsel not registered. Hence unable to scale voltage"
-			"for vdd_%s\n", __func__, voltdm->name);
+		pr_err("%s: PMIC function to convert voltage in uV to vsel not registered. Hence unable to scale voltage for vdd_%s\n",
+		       __func__, voltdm->name);
 		return -ENODATA;
 	}
 
diff --git a/arch/arm/mach-omap2/voltage.c b/arch/arm/mach-omap2/voltage.c
index 4dc60e8..3ac8fe1 100644
--- a/arch/arm/mach-omap2/voltage.c
+++ b/arch/arm/mach-omap2/voltage.c
@@ -195,8 +195,8 @@ struct omap_volt_data *omap_voltage_get_voltdata(struct voltagedomain *voltdm,
 			return &voltdm->volt_data[i];
 	}
 
-	pr_notice("%s: Unable to match the current voltage with the voltage"
-		"table for vdd_%s\n", __func__, voltdm->name);
+	pr_notice("%s: Unable to match the current voltage with the voltage table for vdd_%s\n",
+		  __func__, voltdm->name);
 
 	return ERR_PTR(-ENODATA);
 }
@@ -249,8 +249,8 @@ void omap_change_voltscale_method(struct voltagedomain *voltdm,
 		voltdm->scale = omap_vc_bypass_scale;
 		return;
 	default:
-		pr_warning("%s: Trying to change the method of voltage scaling"
-			"to an unsupported one!\n", __func__);
+		pr_warn("%s: Trying to change the method of voltage scaling to an unsupported one!\n",
+			__func__);
 	}
 }
 
@@ -331,8 +331,8 @@ int voltdm_add_pwrdm(struct voltagedomain *voltdm, struct powerdomain *pwrdm)
 	if (!voltdm || !pwrdm)
 		return -EINVAL;
 
-	pr_debug("voltagedomain: associating powerdomain %s with voltagedomain "
-		 "%s\n", pwrdm->name, voltdm->name);
+	pr_debug("voltagedomain: %s: associating powerdomain %s\n",
+		 voltdm->name, pwrdm->name);
 
 	list_add(&pwrdm->voltdm_node, &voltdm->pwrdm_list);
 
diff --git a/arch/arm/mach-omap2/voltage.h b/arch/arm/mach-omap2/voltage.h
index 0ac2caf..7283b7e 100644
--- a/arch/arm/mach-omap2/voltage.h
+++ b/arch/arm/mach-omap2/voltage.h
@@ -16,7 +16,7 @@
 
 #include <linux/err.h>
 
-#include <plat/voltage.h>
+#include <linux/platform_data/voltage-omap.h>
 
 #include "vc.h"
 #include "vp.h"
diff --git a/arch/arm/mach-omap2/voltagedomains3xxx_data.c b/arch/arm/mach-omap2/voltagedomains3xxx_data.c
index d0103c8..63afbfe 100644
--- a/arch/arm/mach-omap2/voltagedomains3xxx_data.c
+++ b/arch/arm/mach-omap2/voltagedomains3xxx_data.c
@@ -18,9 +18,8 @@
 #include <linux/err.h>
 #include <linux/init.h>
 
+#include "soc.h"
 #include "common.h"
-#include <plat/cpu.h>
-
 #include "prm-regbits-34xx.h"
 #include "omap_opp_data.h"
 #include "voltage.h"
diff --git a/arch/arm/mach-omap2/vp.c b/arch/arm/mach-omap2/vp.c
index f95c1ba..85241b8 100644
--- a/arch/arm/mach-omap2/vp.c
+++ b/arch/arm/mach-omap2/vp.c
@@ -138,8 +138,8 @@ int omap_vp_forceupdate_scale(struct voltagedomain *voltdm,
 		udelay(1);
 	}
 	if (timeout >= VP_TRANXDONE_TIMEOUT) {
-		pr_warning("%s: vdd_%s TRANXDONE timeout exceeded."
-			"Voltage change aborted", __func__, voltdm->name);
+		pr_warn("%s: vdd_%s TRANXDONE timeout exceeded. Voltage change aborted",
+			__func__, voltdm->name);
 		return -ETIMEDOUT;
 	}
 
@@ -157,9 +157,8 @@ int omap_vp_forceupdate_scale(struct voltagedomain *voltdm,
 	omap_test_timeout(vp->common->ops->check_txdone(vp->id),
 			  VP_TRANXDONE_TIMEOUT, timeout);
 	if (timeout >= VP_TRANXDONE_TIMEOUT)
-		pr_err("%s: vdd_%s TRANXDONE timeout exceeded."
-			"TRANXDONE never got set after the voltage update\n",
-			__func__, voltdm->name);
+		pr_err("%s: vdd_%s TRANXDONE timeout exceeded. TRANXDONE never got set after the voltage update\n",
+		       __func__, voltdm->name);
 
 	omap_vc_post_scale(voltdm, target_volt, target_vsel, current_vsel);
 
@@ -176,8 +175,7 @@ int omap_vp_forceupdate_scale(struct voltagedomain *voltdm,
 	}
 
 	if (timeout >= VP_TRANXDONE_TIMEOUT)
-		pr_warning("%s: vdd_%s TRANXDONE timeout exceeded while trying"
-			"to clear the TRANXDONE status\n",
+		pr_warn("%s: vdd_%s TRANXDONE timeout exceeded while trying to clear the TRANXDONE status\n",
 			__func__, voltdm->name);
 
 	/* Clear force bit */
@@ -257,8 +255,8 @@ void omap_vp_disable(struct voltagedomain *voltdm)
 
 	/* If VP is already disabled, do nothing. Return */
 	if (!vp->enabled) {
-		pr_warning("%s: Trying to disable VP for vdd_%s when"
-			"it is already disabled\n", __func__, voltdm->name);
+		pr_warn("%s: Trying to disable VP for vdd_%s when it is already disabled\n",
+			__func__, voltdm->name);
 		return;
 	}
 
diff --git a/arch/arm/mach-orion5x/addr-map.c b/arch/arm/mach-orion5x/addr-map.c
index eaac83d..b5efc0f 100644
--- a/arch/arm/mach-orion5x/addr-map.c
+++ b/arch/arm/mach-orion5x/addr-map.c
@@ -113,7 +113,8 @@ void __init orion5x_setup_cpu_mbus_bridge(void)
 	/*
 	 * Setup MBUS dram target info.
 	 */
-	orion_setup_cpu_mbus_target(&addr_map_cfg, ORION5X_DDR_WINDOW_CPU_BASE);
+	orion_setup_cpu_mbus_target(&addr_map_cfg,
+				    (void __iomem *) ORION5X_DDR_WINDOW_CPU_BASE);
 }
 
 void __init orion5x_setup_dev_boot_win(u32 base, u32 size)
diff --git a/arch/arm/mach-orion5x/common.c b/arch/arm/mach-orion5x/common.c
index 410291c..3e07f52 100644
--- a/arch/arm/mach-orion5x/common.c
+++ b/arch/arm/mach-orion5x/common.c
@@ -30,8 +30,8 @@
 #include <mach/bridge-regs.h>
 #include <mach/hardware.h>
 #include <mach/orion5x.h>
-#include <plat/orion_nand.h>
-#include <plat/ehci-orion.h>
+#include <linux/platform_data/mtd-orion_nand.h>
+#include <linux/platform_data/usb-ehci-orion.h>
 #include <plat/time.h>
 #include <plat/common.h>
 #include <plat/addr-map.h>
@@ -42,22 +42,12 @@
  ****************************************************************************/
 static struct map_desc orion5x_io_desc[] __initdata = {
 	{
-		.virtual	= ORION5X_REGS_VIRT_BASE,
+		.virtual	= (unsigned long) ORION5X_REGS_VIRT_BASE,
 		.pfn		= __phys_to_pfn(ORION5X_REGS_PHYS_BASE),
 		.length		= ORION5X_REGS_SIZE,
 		.type		= MT_DEVICE,
 	}, {
-		.virtual	= ORION5X_PCIE_IO_VIRT_BASE,
-		.pfn		= __phys_to_pfn(ORION5X_PCIE_IO_PHYS_BASE),
-		.length		= ORION5X_PCIE_IO_SIZE,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= ORION5X_PCI_IO_VIRT_BASE,
-		.pfn		= __phys_to_pfn(ORION5X_PCI_IO_PHYS_BASE),
-		.length		= ORION5X_PCI_IO_SIZE,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= ORION5X_PCIE_WA_VIRT_BASE,
+		.virtual	= (unsigned long) ORION5X_PCIE_WA_VIRT_BASE,
 		.pfn		= __phys_to_pfn(ORION5X_PCIE_WA_PHYS_BASE),
 		.length		= ORION5X_PCIE_WA_SIZE,
 		.type		= MT_DEVICE,
diff --git a/arch/arm/mach-orion5x/d2net-setup.c b/arch/arm/mach-orion5x/d2net-setup.c
index d75dcfa..e3629c0 100644
--- a/arch/arm/mach-orion5x/d2net-setup.c
+++ b/arch/arm/mach-orion5x/d2net-setup.c
@@ -27,6 +27,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/pci.h>
 #include <mach/orion5x.h>
+#include <plat/orion-gpio.h>
 #include "common.h"
 #include "mpp.h"
 
diff --git a/arch/arm/mach-orion5x/db88f5281-setup.c b/arch/arm/mach-orion5x/db88f5281-setup.c
index 49a3fd6..41fe2b1 100644
--- a/arch/arm/mach-orion5x/db88f5281-setup.c
+++ b/arch/arm/mach-orion5x/db88f5281-setup.c
@@ -24,7 +24,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/pci.h>
 #include <mach/orion5x.h>
-#include <plat/orion_nand.h>
+#include <linux/platform_data/mtd-orion_nand.h>
 #include "common.h"
 #include "mpp.h"
 
diff --git a/arch/arm/mach-orion5x/dns323-setup.c b/arch/arm/mach-orion5x/dns323-setup.c
index d470864..e533588 100644
--- a/arch/arm/mach-orion5x/dns323-setup.c
+++ b/arch/arm/mach-orion5x/dns323-setup.c
@@ -34,6 +34,7 @@
 #include <asm/mach/pci.h>
 #include <asm/system_info.h>
 #include <mach/orion5x.h>
+#include <plat/orion-gpio.h>
 #include "common.h"
 #include "mpp.h"
 
@@ -700,7 +701,7 @@ static void __init dns323_init(void)
 		 * Note: AFAIK, rev B1 needs the same treatement but I'll let
 		 * somebody else test it.
 		 */
-		writel(0x5, ORION5X_SATA_VIRT_BASE | 0x2c);
+		writel(0x5, ORION5X_SATA_VIRT_BASE + 0x2c);
 		break;
 	}
 }
diff --git a/arch/arm/mach-orion5x/include/mach/bridge-regs.h b/arch/arm/mach-orion5x/include/mach/bridge-regs.h
index 11a3c1e..461fd69 100644
--- a/arch/arm/mach-orion5x/include/mach/bridge-regs.h
+++ b/arch/arm/mach-orion5x/include/mach/bridge-regs.h
@@ -13,27 +13,27 @@
 
 #include <mach/orion5x.h>
 
-#define CPU_CONF		(ORION5X_BRIDGE_VIRT_BASE | 0x100)
+#define CPU_CONF		(ORION5X_BRIDGE_VIRT_BASE + 0x100)
 
-#define CPU_CTRL		(ORION5X_BRIDGE_VIRT_BASE | 0x104)
+#define CPU_CTRL		(ORION5X_BRIDGE_VIRT_BASE + 0x104)
 
-#define RSTOUTn_MASK		(ORION5X_BRIDGE_VIRT_BASE | 0x108)
+#define RSTOUTn_MASK		(ORION5X_BRIDGE_VIRT_BASE + 0x108)
 #define WDT_RESET_OUT_EN	0x0002
 
-#define CPU_SOFT_RESET		(ORION5X_BRIDGE_VIRT_BASE | 0x10c)
+#define CPU_SOFT_RESET		(ORION5X_BRIDGE_VIRT_BASE + 0x10c)
 
-#define BRIDGE_CAUSE		(ORION5X_BRIDGE_VIRT_BASE | 0x110)
+#define BRIDGE_CAUSE		(ORION5X_BRIDGE_VIRT_BASE + 0x110)
 
-#define POWER_MNG_CTRL_REG	(ORION5X_BRIDGE_VIRT_BASE | 0x11C)
+#define POWER_MNG_CTRL_REG	(ORION5X_BRIDGE_VIRT_BASE + 0x11C)
 
 #define WDT_INT_REQ		0x0008
 
 #define BRIDGE_INT_TIMER1_CLR	(~0x0004)
 
-#define MAIN_IRQ_CAUSE		(ORION5X_BRIDGE_VIRT_BASE | 0x200)
+#define MAIN_IRQ_CAUSE		(ORION5X_BRIDGE_VIRT_BASE + 0x200)
 
-#define MAIN_IRQ_MASK		(ORION5X_BRIDGE_VIRT_BASE | 0x204)
+#define MAIN_IRQ_MASK		(ORION5X_BRIDGE_VIRT_BASE + 0x204)
 
-#define TIMER_VIRT_BASE		(ORION5X_BRIDGE_VIRT_BASE | 0x300)
-#define TIMER_PHYS_BASE		(ORION5X_BRIDGE_PHYS_BASE | 0x300)
+#define TIMER_VIRT_BASE		(ORION5X_BRIDGE_VIRT_BASE + 0x300)
+#define TIMER_PHYS_BASE		(ORION5X_BRIDGE_PHYS_BASE + 0x300)
 #endif
diff --git a/arch/arm/mach-orion5x/include/mach/gpio.h b/arch/arm/mach-orion5x/include/mach/gpio.h
deleted file mode 100644
index a1d0b78..0000000
--- a/arch/arm/mach-orion5x/include/mach/gpio.h
+++ /dev/null
@@ -1,9 +0,0 @@
-/*
- * arch/arm/mach-orion5x/include/mach/gpio.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.
- */
-
-#include <plat/gpio.h>
diff --git a/arch/arm/mach-orion5x/include/mach/io.h b/arch/arm/mach-orion5x/include/mach/io.h
deleted file mode 100644
index 1aa5d0a..0000000
--- a/arch/arm/mach-orion5x/include/mach/io.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * arch/arm/mach-orion5x/include/mach/io.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 __ASM_ARCH_IO_H
-#define __ASM_ARCH_IO_H
-
-#include <mach/orion5x.h>
-#include <asm/sizes.h>
-
-#define IO_SPACE_LIMIT		SZ_2M
-static inline void __iomem *__io(unsigned long addr)
-{
-	return (void __iomem *)(addr + ORION5X_PCIE_IO_VIRT_BASE);
-}
-
-#define __io(a)			 __io(a)
-#endif
diff --git a/arch/arm/mach-orion5x/include/mach/orion5x.h b/arch/arm/mach-orion5x/include/mach/orion5x.h
index 683e085..d265f54 100644
--- a/arch/arm/mach-orion5x/include/mach/orion5x.h
+++ b/arch/arm/mach-orion5x/include/mach/orion5x.h
@@ -31,31 +31,29 @@
  * fc000000	device bus mappings (cs0/cs1)
  *
  * virt		phys		size
- * fdd00000	f1000000	1M	on-chip peripheral registers
- * fde00000	f2000000	1M	PCIe I/O space
- * fdf00000	f2100000	1M	PCI I/O space
- * fe000000	f0000000	16M	PCIe WA space (Orion-1/Orion-NAS only)
+ * fe000000	f1000000	1M	on-chip peripheral registers
+ * fee00000	f2000000	64K	PCIe I/O space
+ * fee10000	f2100000	64K	PCI I/O space
+ * fd000000	f0000000	16M	PCIe WA space (Orion-1/Orion-NAS only)
  ****************************************************************************/
 #define ORION5X_REGS_PHYS_BASE		0xf1000000
-#define ORION5X_REGS_VIRT_BASE		0xfdd00000
+#define ORION5X_REGS_VIRT_BASE		IOMEM(0xfe000000)
 #define ORION5X_REGS_SIZE		SZ_1M
 
 #define ORION5X_PCIE_IO_PHYS_BASE	0xf2000000
-#define ORION5X_PCIE_IO_VIRT_BASE	0xfde00000
 #define ORION5X_PCIE_IO_BUS_BASE	0x00000000
-#define ORION5X_PCIE_IO_SIZE		SZ_1M
+#define ORION5X_PCIE_IO_SIZE		SZ_64K
 
 #define ORION5X_PCI_IO_PHYS_BASE	0xf2100000
-#define ORION5X_PCI_IO_VIRT_BASE	0xfdf00000
-#define ORION5X_PCI_IO_BUS_BASE		0x00100000
-#define ORION5X_PCI_IO_SIZE		SZ_1M
+#define ORION5X_PCI_IO_BUS_BASE		0x00010000
+#define ORION5X_PCI_IO_SIZE		SZ_64K
 
 #define ORION5X_SRAM_PHYS_BASE		(0xf2200000)
 #define ORION5X_SRAM_SIZE		SZ_8K
 
 /* Relevant only for Orion-1/Orion-NAS */
 #define ORION5X_PCIE_WA_PHYS_BASE	0xf0000000
-#define ORION5X_PCIE_WA_VIRT_BASE	0xfe000000
+#define ORION5X_PCIE_WA_VIRT_BASE	IOMEM(0xfd000000)
 #define ORION5X_PCIE_WA_SIZE		SZ_16M
 
 #define ORION5X_PCIE_MEM_PHYS_BASE	0xe0000000
@@ -68,42 +66,42 @@
  * Orion Registers Map
  ******************************************************************************/
 
-#define ORION5X_DDR_VIRT_BASE		(ORION5X_REGS_VIRT_BASE | 0x00000)
-#define  ORION5X_DDR_WINDOW_CPU_BASE    (ORION5X_DDR_VIRT_BASE | 0x1500)
-#define ORION5X_DEV_BUS_PHYS_BASE	(ORION5X_REGS_PHYS_BASE | 0x10000)
-#define ORION5X_DEV_BUS_VIRT_BASE	(ORION5X_REGS_VIRT_BASE | 0x10000)
-#define ORION5X_DEV_BUS_REG(x)		(ORION5X_DEV_BUS_VIRT_BASE | (x))
+#define ORION5X_DDR_VIRT_BASE		(ORION5X_REGS_VIRT_BASE + 0x00000)
+#define  ORION5X_DDR_WINDOW_CPU_BASE    (ORION5X_DDR_VIRT_BASE + 0x1500)
+#define ORION5X_DEV_BUS_PHYS_BASE	(ORION5X_REGS_PHYS_BASE + 0x10000)
+#define ORION5X_DEV_BUS_VIRT_BASE	(ORION5X_REGS_VIRT_BASE + 0x10000)
+#define ORION5X_DEV_BUS_REG(x)		(ORION5X_DEV_BUS_VIRT_BASE + (x))
 #define  GPIO_VIRT_BASE			ORION5X_DEV_BUS_REG(0x0100)
-#define  SPI_PHYS_BASE			(ORION5X_DEV_BUS_PHYS_BASE | 0x0600)
-#define  I2C_PHYS_BASE			(ORION5X_DEV_BUS_PHYS_BASE | 0x1000)
-#define  UART0_PHYS_BASE		(ORION5X_DEV_BUS_PHYS_BASE | 0x2000)
-#define  UART0_VIRT_BASE		(ORION5X_DEV_BUS_VIRT_BASE | 0x2000)
-#define  UART1_PHYS_BASE		(ORION5X_DEV_BUS_PHYS_BASE | 0x2100)
-#define  UART1_VIRT_BASE		(ORION5X_DEV_BUS_VIRT_BASE | 0x2100)
+#define  SPI_PHYS_BASE			(ORION5X_DEV_BUS_PHYS_BASE + 0x0600)
+#define  I2C_PHYS_BASE			(ORION5X_DEV_BUS_PHYS_BASE + 0x1000)
+#define  UART0_PHYS_BASE		(ORION5X_DEV_BUS_PHYS_BASE + 0x2000)
+#define  UART0_VIRT_BASE		(ORION5X_DEV_BUS_VIRT_BASE + 0x2000)
+#define  UART1_PHYS_BASE		(ORION5X_DEV_BUS_PHYS_BASE + 0x2100)
+#define  UART1_VIRT_BASE		(ORION5X_DEV_BUS_VIRT_BASE + 0x2100)
 
-#define ORION5X_BRIDGE_VIRT_BASE	(ORION5X_REGS_VIRT_BASE | 0x20000)
-#define ORION5X_BRIDGE_PHYS_BASE	(ORION5X_REGS_PHYS_BASE | 0x20000)
+#define ORION5X_BRIDGE_VIRT_BASE	(ORION5X_REGS_VIRT_BASE + 0x20000)
+#define ORION5X_BRIDGE_PHYS_BASE	(ORION5X_REGS_PHYS_BASE + 0x20000)
 
-#define ORION5X_PCI_VIRT_BASE		(ORION5X_REGS_VIRT_BASE | 0x30000)
+#define ORION5X_PCI_VIRT_BASE		(ORION5X_REGS_VIRT_BASE + 0x30000)
 
-#define ORION5X_PCIE_VIRT_BASE		(ORION5X_REGS_VIRT_BASE | 0x40000)
+#define ORION5X_PCIE_VIRT_BASE		(ORION5X_REGS_VIRT_BASE + 0x40000)
 
-#define ORION5X_USB0_PHYS_BASE		(ORION5X_REGS_PHYS_BASE | 0x50000)
-#define ORION5X_USB0_VIRT_BASE		(ORION5X_REGS_VIRT_BASE | 0x50000)
+#define ORION5X_USB0_PHYS_BASE		(ORION5X_REGS_PHYS_BASE + 0x50000)
+#define ORION5X_USB0_VIRT_BASE		(ORION5X_REGS_VIRT_BASE + 0x50000)
 
-#define ORION5X_XOR_PHYS_BASE		(ORION5X_REGS_PHYS_BASE | 0x60900)
-#define ORION5X_XOR_VIRT_BASE		(ORION5X_REGS_VIRT_BASE | 0x60900)
+#define ORION5X_XOR_PHYS_BASE		(ORION5X_REGS_PHYS_BASE + 0x60900)
+#define ORION5X_XOR_VIRT_BASE		(ORION5X_REGS_VIRT_BASE + 0x60900)
 
-#define ORION5X_ETH_PHYS_BASE		(ORION5X_REGS_PHYS_BASE | 0x70000)
-#define ORION5X_ETH_VIRT_BASE		(ORION5X_REGS_VIRT_BASE | 0x70000)
+#define ORION5X_ETH_PHYS_BASE		(ORION5X_REGS_PHYS_BASE + 0x70000)
+#define ORION5X_ETH_VIRT_BASE		(ORION5X_REGS_VIRT_BASE + 0x70000)
 
-#define ORION5X_SATA_PHYS_BASE		(ORION5X_REGS_PHYS_BASE | 0x80000)
-#define ORION5X_SATA_VIRT_BASE		(ORION5X_REGS_VIRT_BASE | 0x80000)
+#define ORION5X_SATA_PHYS_BASE		(ORION5X_REGS_PHYS_BASE + 0x80000)
+#define ORION5X_SATA_VIRT_BASE		(ORION5X_REGS_VIRT_BASE + 0x80000)
 
-#define ORION5X_CRYPTO_PHYS_BASE	(ORION5X_REGS_PHYS_BASE | 0x90000)
+#define ORION5X_CRYPTO_PHYS_BASE	(ORION5X_REGS_PHYS_BASE + 0x90000)
 
-#define ORION5X_USB1_PHYS_BASE		(ORION5X_REGS_PHYS_BASE | 0xa0000)
-#define ORION5X_USB1_VIRT_BASE		(ORION5X_REGS_VIRT_BASE | 0xa0000)
+#define ORION5X_USB1_PHYS_BASE		(ORION5X_REGS_PHYS_BASE + 0xa0000)
+#define ORION5X_USB1_VIRT_BASE		(ORION5X_REGS_VIRT_BASE + 0xa0000)
 
 /*******************************************************************************
  * Device Bus Registers
diff --git a/arch/arm/mach-orion5x/irq.c b/arch/arm/mach-orion5x/irq.c
index 17da709..30a192b 100644
--- a/arch/arm/mach-orion5x/irq.c
+++ b/arch/arm/mach-orion5x/irq.c
@@ -12,7 +12,9 @@
 #include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/irq.h>
+#include <linux/io.h>
 #include <mach/bridge-regs.h>
+#include <plat/orion-gpio.h>
 #include <plat/irq.h>
 
 static int __initdata gpio0_irqs[4] = {
@@ -24,11 +26,11 @@ static int __initdata gpio0_irqs[4] = {
 
 void __init orion5x_init_irq(void)
 {
-	orion_irq_init(0, (void __iomem *)MAIN_IRQ_MASK);
+	orion_irq_init(0, MAIN_IRQ_MASK);
 
 	/*
 	 * Initialize gpiolib for GPIOs 0-31.
 	 */
-	orion_gpio_init(NULL, 0, 32, (void __iomem *)GPIO_VIRT_BASE, 0,
+	orion_gpio_init(NULL, 0, 32, GPIO_VIRT_BASE, 0,
 			IRQ_ORION5X_GPIO_START, gpio0_irqs);
 }
diff --git a/arch/arm/mach-orion5x/kurobox_pro-setup.c b/arch/arm/mach-orion5x/kurobox_pro-setup.c
index 1e458ef..f1ae10a 100644
--- a/arch/arm/mach-orion5x/kurobox_pro-setup.c
+++ b/arch/arm/mach-orion5x/kurobox_pro-setup.c
@@ -24,7 +24,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/pci.h>
 #include <mach/orion5x.h>
-#include <plat/orion_nand.h>
+#include <linux/platform_data/mtd-orion_nand.h>
 #include "common.h"
 #include "mpp.h"
 
diff --git a/arch/arm/mach-orion5x/net2big-setup.c b/arch/arm/mach-orion5x/net2big-setup.c
index 0180c39..3506f16 100644
--- a/arch/arm/mach-orion5x/net2big-setup.c
+++ b/arch/arm/mach-orion5x/net2big-setup.c
@@ -25,6 +25,7 @@
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <mach/orion5x.h>
+#include <plat/orion-gpio.h>
 #include "common.h"
 #include "mpp.h"
 
diff --git a/arch/arm/mach-orion5x/pci.c b/arch/arm/mach-orion5x/pci.c
index cb19e16..cd50e32 100644
--- a/arch/arm/mach-orion5x/pci.c
+++ b/arch/arm/mach-orion5x/pci.c
@@ -38,7 +38,7 @@
 /*****************************************************************************
  * PCIe controller
  ****************************************************************************/
-#define PCIE_BASE	((void __iomem *)ORION5X_PCIE_VIRT_BASE)
+#define PCIE_BASE	(ORION5X_PCIE_VIRT_BASE)
 
 void __init orion5x_pcie_id(u32 *dev, u32 *rev)
 {
@@ -111,7 +111,7 @@ static int pcie_rd_conf_wa(struct pci_bus *bus, u32 devfn,
 		return PCIBIOS_DEVICE_NOT_FOUND;
 	}
 
-	ret = orion_pcie_rd_conf_wa((void __iomem *)ORION5X_PCIE_WA_VIRT_BASE,
+	ret = orion_pcie_rd_conf_wa(ORION5X_PCIE_WA_VIRT_BASE,
 				    bus, devfn, where, size, val);
 
 	return ret;
@@ -162,35 +162,25 @@ static int __init pcie_setup(struct pci_sys_data *sys)
 		pcie_ops.read = pcie_rd_conf_wa;
 	}
 
+	pci_ioremap_io(sys->busnr * SZ_64K, ORION5X_PCIE_IO_PHYS_BASE);
+
 	/*
 	 * Request resources.
 	 */
-	res = kzalloc(sizeof(struct resource) * 2, GFP_KERNEL);
+	res = kzalloc(sizeof(struct resource), GFP_KERNEL);
 	if (!res)
 		panic("pcie_setup unable to alloc resources");
 
 	/*
-	 * IORESOURCE_IO
-	 */
-	sys->io_offset = 0;
-	res[0].name = "PCIe I/O Space";
-	res[0].flags = IORESOURCE_IO;
-	res[0].start = ORION5X_PCIE_IO_BUS_BASE;
-	res[0].end = res[0].start + ORION5X_PCIE_IO_SIZE - 1;
-	if (request_resource(&ioport_resource, &res[0]))
-		panic("Request PCIe IO resource failed\n");
-	pci_add_resource_offset(&sys->resources, &res[0], sys->io_offset);
-
-	/*
 	 * IORESOURCE_MEM
 	 */
-	res[1].name = "PCIe Memory Space";
-	res[1].flags = IORESOURCE_MEM;
-	res[1].start = ORION5X_PCIE_MEM_PHYS_BASE;
-	res[1].end = res[1].start + ORION5X_PCIE_MEM_SIZE - 1;
-	if (request_resource(&iomem_resource, &res[1]))
+	res->name = "PCIe Memory Space";
+	res->flags = IORESOURCE_MEM;
+	res->start = ORION5X_PCIE_MEM_PHYS_BASE;
+	res->end = res->start + ORION5X_PCIE_MEM_SIZE - 1;
+	if (request_resource(&iomem_resource, res))
 		panic("Request PCIe Memory resource failed\n");
-	pci_add_resource_offset(&sys->resources, &res[1], sys->mem_offset);
+	pci_add_resource_offset(&sys->resources, res, sys->mem_offset);
 
 	return 1;
 }
@@ -198,7 +188,7 @@ static int __init pcie_setup(struct pci_sys_data *sys)
 /*****************************************************************************
  * PCI controller
  ****************************************************************************/
-#define ORION5X_PCI_REG(x)	(ORION5X_PCI_VIRT_BASE | (x))
+#define ORION5X_PCI_REG(x)	(ORION5X_PCI_VIRT_BASE + (x))
 #define PCI_MODE		ORION5X_PCI_REG(0xd00)
 #define PCI_CMD			ORION5X_PCI_REG(0xc00)
 #define PCI_P2P_CONF		ORION5X_PCI_REG(0x1d14)
@@ -489,35 +479,25 @@ static int __init pci_setup(struct pci_sys_data *sys)
 	 */
 	orion5x_setbits(PCI_CMD, PCI_CMD_HOST_REORDER);
 
+	pci_ioremap_io(sys->busnr * SZ_64K, ORION5X_PCI_IO_PHYS_BASE);
+
 	/*
 	 * Request resources
 	 */
-	res = kzalloc(sizeof(struct resource) * 2, GFP_KERNEL);
+	res = kzalloc(sizeof(struct resource), GFP_KERNEL);
 	if (!res)
 		panic("pci_setup unable to alloc resources");
 
 	/*
-	 * IORESOURCE_IO
-	 */
-	sys->io_offset = 0;
-	res[0].name = "PCI I/O Space";
-	res[0].flags = IORESOURCE_IO;
-	res[0].start = ORION5X_PCI_IO_BUS_BASE;
-	res[0].end = res[0].start + ORION5X_PCI_IO_SIZE - 1;
-	if (request_resource(&ioport_resource, &res[0]))
-		panic("Request PCI IO resource failed\n");
-	pci_add_resource_offset(&sys->resources, &res[0], sys->io_offset);
-
-	/*
 	 * IORESOURCE_MEM
 	 */
-	res[1].name = "PCI Memory Space";
-	res[1].flags = IORESOURCE_MEM;
-	res[1].start = ORION5X_PCI_MEM_PHYS_BASE;
-	res[1].end = res[1].start + ORION5X_PCI_MEM_SIZE - 1;
-	if (request_resource(&iomem_resource, &res[1]))
+	res->name = "PCI Memory Space";
+	res->flags = IORESOURCE_MEM;
+	res->start = ORION5X_PCI_MEM_PHYS_BASE;
+	res->end = res->start + ORION5X_PCI_MEM_SIZE - 1;
+	if (request_resource(&iomem_resource, res))
 		panic("Request PCI Memory resource failed\n");
-	pci_add_resource_offset(&sys->resources, &res[1], sys->mem_offset);
+	pci_add_resource_offset(&sys->resources, res, sys->mem_offset);
 
 	return 1;
 }
diff --git a/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c b/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c
index 78a6a11..9b1c953 100644
--- a/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c
+++ b/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c
@@ -18,7 +18,6 @@
 #include <linux/ethtool.h>
 #include <net/dsa.h>
 #include <asm/mach-types.h>
-#include <asm/leds.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/pci.h>
 #include <mach/orion5x.h>
diff --git a/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c b/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c
index 2f5dc54..51ba2b8 100644
--- a/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c
+++ b/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c
@@ -19,7 +19,6 @@
 #include <linux/i2c.h>
 #include <net/dsa.h>
 #include <asm/mach-types.h>
-#include <asm/leds.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/pci.h>
 #include <mach/orion5x.h>
diff --git a/arch/arm/mach-orion5x/rd88f5182-setup.c b/arch/arm/mach-orion5x/rd88f5182-setup.c
index 399130f..0a56b94 100644
--- a/arch/arm/mach-orion5x/rd88f5182-setup.c
+++ b/arch/arm/mach-orion5x/rd88f5182-setup.c
@@ -19,8 +19,8 @@
 #include <linux/mv643xx_eth.h>
 #include <linux/ata_platform.h>
 #include <linux/i2c.h>
+#include <linux/leds.h>
 #include <asm/mach-types.h>
-#include <asm/leds.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/pci.h>
 #include <mach/orion5x.h>
@@ -53,12 +53,6 @@
 #define RD88F5182_PCI_SLOT0_IRQ_A_PIN	7
 #define RD88F5182_PCI_SLOT0_IRQ_B_PIN	6
 
-/*
- * GPIO Debug LED
- */
-
-#define RD88F5182_GPIO_DBG_LED		0
-
 /*****************************************************************************
  * 16M NOR Flash on Device bus CS1
  ****************************************************************************/
@@ -83,55 +77,32 @@ static struct platform_device rd88f5182_nor_flash = {
 	.resource		= &rd88f5182_nor_flash_resource,
 };
 
-#ifdef CONFIG_LEDS
-
 /*****************************************************************************
- * Use GPIO debug led as CPU active indication
+ * Use GPIO LED as CPU active indication
  ****************************************************************************/
 
-static void rd88f5182_dbgled_event(led_event_t evt)
-{
-	int val;
-
-	if (evt == led_idle_end)
-		val = 1;
-	else if (evt == led_idle_start)
-		val = 0;
-	else
-		return;
-
-	gpio_set_value(RD88F5182_GPIO_DBG_LED, val);
-}
-
-static int __init rd88f5182_dbgled_init(void)
-{
-	int pin;
-
-	if (machine_is_rd88f5182()) {
-		pin = RD88F5182_GPIO_DBG_LED;
+#define RD88F5182_GPIO_LED		0
 
-		if (gpio_request(pin, "DBGLED") == 0) {
-			if (gpio_direction_output(pin, 0) != 0) {
-				printk(KERN_ERR "rd88f5182_dbgled_init failed "
-						"to set output pin %d\n", pin);
-				gpio_free(pin);
-				return 0;
-			}
-		} else {
-			printk(KERN_ERR "rd88f5182_dbgled_init failed "
-					"to request gpio %d\n", pin);
-			return 0;
-		}
-
-		leds_event = rd88f5182_dbgled_event;
-	}
-
-	return 0;
-}
+static struct gpio_led rd88f5182_gpio_led_pins[] = {
+	{
+		.name		= "rd88f5182:cpu",
+		.default_trigger = "cpu0",
+		.gpio		= RD88F5182_GPIO_LED,
+	},
+};
 
-__initcall(rd88f5182_dbgled_init);
+static struct gpio_led_platform_data rd88f5182_gpio_led_data = {
+	.leds		= rd88f5182_gpio_led_pins,
+	.num_leds	= ARRAY_SIZE(rd88f5182_gpio_led_pins),
+};
 
-#endif
+static struct platform_device rd88f5182_gpio_leds = {
+	.name	= "leds-gpio",
+	.id	= -1,
+	.dev	= {
+		.platform_data = &rd88f5182_gpio_led_data,
+	},
+};
 
 /*****************************************************************************
  * PCI
@@ -298,6 +269,7 @@ static void __init rd88f5182_init(void)
 
 	orion5x_setup_dev1_win(RD88F5182_NOR_BASE, RD88F5182_NOR_SIZE);
 	platform_device_register(&rd88f5182_nor_flash);
+	platform_device_register(&rd88f5182_gpio_leds);
 
 	i2c_register_board_info(0, &rd88f5182_i2c_rtc, 1);
 }
diff --git a/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c b/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c
index 92df49c..ed50910 100644
--- a/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c
+++ b/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c
@@ -20,7 +20,6 @@
 #include <linux/ethtool.h>
 #include <net/dsa.h>
 #include <asm/mach-types.h>
-#include <asm/leds.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/pci.h>
 #include <mach/orion5x.h>
diff --git a/arch/arm/mach-picoxcell/Kconfig b/arch/arm/mach-picoxcell/Kconfig
new file mode 100644
index 0000000..868796f
--- /dev/null
+++ b/arch/arm/mach-picoxcell/Kconfig
@@ -0,0 +1,14 @@
+config ARCH_PICOXCELL
+	bool "Picochip PicoXcell" if ARCH_MULTI_V6
+	select ARCH_REQUIRE_GPIOLIB
+	select ARM_PATCH_PHYS_VIRT
+	select ARM_VIC
+	select CPU_V6K
+	select DW_APB_TIMER
+	select DW_APB_TIMER_OF
+	select GENERIC_CLOCKEVENTS
+	select GENERIC_GPIO
+	select HAVE_TCM
+	select NO_IOPORT
+	select SPARSE_IRQ
+	select USE_OF
diff --git a/arch/arm/mach-picoxcell/Makefile.boot b/arch/arm/mach-picoxcell/Makefile.boot
deleted file mode 100644
index b327175..0000000
--- a/arch/arm/mach-picoxcell/Makefile.boot
+++ /dev/null
@@ -1 +0,0 @@
-zreladdr-y := 0x00008000
diff --git a/arch/arm/mach-picoxcell/common.c b/arch/arm/mach-picoxcell/common.c
index 8f9a0b4..f6c0849 100644
--- a/arch/arm/mach-picoxcell/common.c
+++ b/arch/arm/mach-picoxcell/common.c
@@ -20,14 +20,15 @@
 #include <asm/hardware/vic.h>
 #include <asm/mach/map.h>
 
-#include <mach/map.h>
-#include <mach/picoxcell_soc.h>
-
 #include "common.h"
 
-#define WDT_CTRL_REG_EN_MASK	(1 << 0)
-#define WDT_CTRL_REG_OFFS	(0x00)
-#define WDT_TIMEOUT_REG_OFFS	(0x04)
+#define PHYS_TO_IO(x)			(((x) & 0x00ffffff) | 0xfe000000)
+#define PICOXCELL_PERIPH_BASE		0x80000000
+#define PICOXCELL_PERIPH_LENGTH		SZ_4M
+
+#define WDT_CTRL_REG_EN_MASK		(1 << 0)
+#define WDT_CTRL_REG_OFFS		(0x00)
+#define WDT_TIMEOUT_REG_OFFS		(0x04)
 static void __iomem *wdt_regs;
 
 /*
diff --git a/arch/arm/mach-picoxcell/include/mach/debug-macro.S b/arch/arm/mach-picoxcell/include/mach/debug-macro.S
deleted file mode 100644
index 58d4ee3..0000000
--- a/arch/arm/mach-picoxcell/include/mach/debug-macro.S
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2011 Picochip Ltd., Jamie Iles
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Derived from arch/arm/mach-davinci/include/mach/debug-macro.S to use 32-bit
- * accesses to the 8250.
- */
-#include <linux/serial_reg.h>
-#include <mach/hardware.h>
-#include <mach/map.h>
-
-#define UART_SHIFT 2
-
-		.macro	addruart, rp, rv, tmp
-		ldr	\rv, =PHYS_TO_IO(PICOXCELL_UART1_BASE)
-		ldr	\rp, =PICOXCELL_UART1_BASE
-		.endm
-
-		.macro	senduart,rd,rx
-		str	\rd, [\rx, #UART_TX << UART_SHIFT]
-		.endm
-
-		.macro	busyuart,rd,rx
-1002:		ldr	\rd, [\rx, #UART_LSR << UART_SHIFT]
-		and	\rd, \rd, #UART_LSR_TEMT | UART_LSR_THRE
-		teq	\rd, #UART_LSR_TEMT | UART_LSR_THRE
-		bne	1002b
-		.endm
-
-		/* The UART's don't have any flow control IO's wired up. */
-		.macro	waituart,rd,rx
-		.endm
diff --git a/arch/arm/mach-picoxcell/include/mach/gpio.h b/arch/arm/mach-picoxcell/include/mach/gpio.h
deleted file mode 100644
index 40a8c17..0000000
--- a/arch/arm/mach-picoxcell/include/mach/gpio.h
+++ /dev/null
@@ -1 +0,0 @@
-/* empty */
diff --git a/arch/arm/mach-picoxcell/include/mach/hardware.h b/arch/arm/mach-picoxcell/include/mach/hardware.h
deleted file mode 100644
index 70ff581..0000000
--- a/arch/arm/mach-picoxcell/include/mach/hardware.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (c) 2011 Picochip Ltd., Jamie Iles
- *
- * This file contains the hardware definitions of the picoXcell SoC devices.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-#ifndef __ASM_ARCH_HARDWARE_H
-#define __ASM_ARCH_HARDWARE_H
-
-#include <mach/picoxcell_soc.h>
-
-#endif
diff --git a/arch/arm/mach-picoxcell/include/mach/map.h b/arch/arm/mach-picoxcell/include/mach/map.h
deleted file mode 100644
index c06afad..0000000
--- a/arch/arm/mach-picoxcell/include/mach/map.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (c) 2011 Picochip Ltd., Jamie Iles
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-#ifndef __PICOXCELL_MAP_H__
-#define __PICOXCELL_MAP_H__
-
-#define PHYS_TO_IO(x)		(((x) & 0x00ffffff) | 0xfe000000)
-
-#ifdef __ASSEMBLY__
-#define IO_ADDRESS(x)		PHYS_TO_IO((x))
-#else
-#define IO_ADDRESS(x)		(void __iomem __force *)(PHYS_TO_IO((x)))
-#endif
-
-#endif /* __PICOXCELL_MAP_H__ */
diff --git a/arch/arm/mach-picoxcell/include/mach/picoxcell_soc.h b/arch/arm/mach-picoxcell/include/mach/picoxcell_soc.h
deleted file mode 100644
index 5566fc8..0000000
--- a/arch/arm/mach-picoxcell/include/mach/picoxcell_soc.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (c) 2011 Picochip Ltd., Jamie Iles
- *
- * This file contains the hardware definitions of the picoXcell SoC devices.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-#ifndef __PICOXCELL_SOC_H__
-#define __PICOXCELL_SOC_H__
-
-#define PICOXCELL_UART1_BASE		0x80230000
-#define PICOXCELL_PERIPH_BASE		0x80000000
-#define PICOXCELL_PERIPH_LENGTH		SZ_4M
-#define PICOXCELL_VIC0_BASE		0x80060000
-#define PICOXCELL_VIC1_BASE		0x80064000
-
-#endif /* __PICOXCELL_SOC_H__ */
diff --git a/arch/arm/mach-picoxcell/include/mach/timex.h b/arch/arm/mach-picoxcell/include/mach/timex.h
deleted file mode 100644
index 6c540a6..0000000
--- a/arch/arm/mach-picoxcell/include/mach/timex.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (c) 2011 Picochip Ltd., Jamie Iles
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#ifndef __TIMEX_H__
-#define __TIMEX_H__
-
-/* Bogus value to allow the kernel to compile. */
-#define CLOCK_TICK_RATE		1000000
-
-#endif /* __TIMEX_H__ */
-
diff --git a/arch/arm/mach-picoxcell/include/mach/uncompress.h b/arch/arm/mach-picoxcell/include/mach/uncompress.h
deleted file mode 100644
index b60b19d..0000000
--- a/arch/arm/mach-picoxcell/include/mach/uncompress.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (c) 2011 Picochip Ltd., Jamie Iles
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#define putc(c)
-#define flush()
-#define arch_decomp_setup()
-#define arch_decomp_wdog()
diff --git a/arch/arm/mach-pnx4008/Makefile b/arch/arm/mach-pnx4008/Makefile
deleted file mode 100644
index 777564c..0000000
--- a/arch/arm/mach-pnx4008/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-#
-# Makefile for the linux kernel.
-#
-
-obj-y			:= core.o irq.o time.o clock.o gpio.o serial.o dma.o i2c.o
-obj-m			:=
-obj-n			:=
-obj-			:=
-
-# Power Management
-obj-$(CONFIG_PM) += pm.o sleep.o
-
diff --git a/arch/arm/mach-pnx4008/Makefile.boot b/arch/arm/mach-pnx4008/Makefile.boot
deleted file mode 100644
index 9fa19ba..0000000
--- a/arch/arm/mach-pnx4008/Makefile.boot
+++ /dev/null
@@ -1,4 +0,0 @@
-   zreladdr-y		+= 0x80008000
-params_phys-y		:= 0x80000100
-initrd_phys-y		:= 0x80800000
-
diff --git a/arch/arm/mach-pnx4008/clock.c b/arch/arm/mach-pnx4008/clock.c
deleted file mode 100644
index a4a3819..0000000
--- a/arch/arm/mach-pnx4008/clock.c
+++ /dev/null
@@ -1,1001 +0,0 @@
-/*
- * arch/arm/mach-pnx4008/clock.c
- *
- * Clock control driver for PNX4008
- *
- * Authors: Vitaly Wool, Dmitry Chigirev <source@mvista.com>
- * Generic clock management functions are partially based on:
- *  linux/arch/arm/mach-omap/clock.c
- *
- * 2005-2006 (c) MontaVista Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/device.h>
-#include <linux/err.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/clkdev.h>
-
-#include <mach/hardware.h>
-#include <mach/clock.h>
-#include "clock.h"
-
-/*forward declaration*/
-static struct clk per_ck;
-static struct clk hclk_ck;
-static struct clk ck_1MHz;
-static struct clk ck_13MHz;
-static struct clk ck_pll1;
-static int local_set_rate(struct clk *clk, u32 rate);
-
-static inline void clock_lock(void)
-{
-	local_irq_disable();
-}
-
-static inline void clock_unlock(void)
-{
-	local_irq_enable();
-}
-
-static void propagate_rate(struct clk *clk)
-{
-	struct clk *tmp_clk;
-
-	tmp_clk = clk;
-	while (tmp_clk->propagate_next) {
-		tmp_clk = tmp_clk->propagate_next;
-		local_set_rate(tmp_clk, tmp_clk->user_rate);
-	}
-}
-
-static void clk_reg_disable(struct clk *clk)
-{
-	if (clk->enable_reg)
-		__raw_writel(__raw_readl(clk->enable_reg) &
-			     ~(1 << clk->enable_shift), clk->enable_reg);
-}
-
-static int clk_reg_enable(struct clk *clk)
-{
-	if (clk->enable_reg)
-		__raw_writel(__raw_readl(clk->enable_reg) |
-			     (1 << clk->enable_shift), clk->enable_reg);
-	return 0;
-}
-
-static inline void clk_reg_disable1(struct clk *clk)
-{
-	if (clk->enable_reg1)
-		__raw_writel(__raw_readl(clk->enable_reg1) &
-			     ~(1 << clk->enable_shift1), clk->enable_reg1);
-}
-
-static inline void clk_reg_enable1(struct clk *clk)
-{
-	if (clk->enable_reg1)
-		__raw_writel(__raw_readl(clk->enable_reg1) |
-			     (1 << clk->enable_shift1), clk->enable_reg1);
-}
-
-static int clk_wait_for_pll_lock(struct clk *clk)
-{
-	int i;
-	i = 0;
-	while (i++ < 0xFFF && !(__raw_readl(clk->scale_reg) & 1)) ;	/*wait for PLL to lock */
-
-	if (!(__raw_readl(clk->scale_reg) & 1)) {
-		printk(KERN_ERR
-		       "%s ERROR: failed to lock, scale reg data: %x\n",
-		       clk->name, __raw_readl(clk->scale_reg));
-		return -1;
-	}
-	return 0;
-}
-
-static int switch_to_dirty_13mhz(struct clk *clk)
-{
-	int i;
-	int ret;
-	u32 tmp_reg;
-
-	ret = 0;
-
-	if (!clk->rate)
-		clk_reg_enable1(clk);
-
-	tmp_reg = __raw_readl(clk->parent_switch_reg);
-	/*if 13Mhz clock selected, select 13'MHz (dirty) source from OSC */
-	if (!(tmp_reg & 1)) {
-		tmp_reg |= (1 << 1);	/* Trigger switch to 13'MHz (dirty) clock */
-		__raw_writel(tmp_reg, clk->parent_switch_reg);
-		i = 0;
-		while (i++ < 0xFFF && !(__raw_readl(clk->parent_switch_reg) & 1)) ;	/*wait for 13'MHz selection status */
-
-		if (!(__raw_readl(clk->parent_switch_reg) & 1)) {
-			printk(KERN_ERR
-			       "%s ERROR: failed to select 13'MHz, parent sw reg data: %x\n",
-			       clk->name, __raw_readl(clk->parent_switch_reg));
-			ret = -1;
-		}
-	}
-
-	if (!clk->rate)
-		clk_reg_disable1(clk);
-
-	return ret;
-}
-
-static int switch_to_clean_13mhz(struct clk *clk)
-{
-	int i;
-	int ret;
-	u32 tmp_reg;
-
-	ret = 0;
-
-	if (!clk->rate)
-		clk_reg_enable1(clk);
-
-	tmp_reg = __raw_readl(clk->parent_switch_reg);
-	/*if 13'Mhz clock selected, select 13MHz (clean) source from OSC */
-	if (tmp_reg & 1) {
-		tmp_reg &= ~(1 << 1);	/* Trigger switch to 13MHz (clean) clock */
-		__raw_writel(tmp_reg, clk->parent_switch_reg);
-		i = 0;
-		while (i++ < 0xFFF && (__raw_readl(clk->parent_switch_reg) & 1)) ;	/*wait for 13MHz selection status */
-
-		if (__raw_readl(clk->parent_switch_reg) & 1) {
-			printk(KERN_ERR
-			       "%s ERROR: failed to select 13MHz, parent sw reg data: %x\n",
-			       clk->name, __raw_readl(clk->parent_switch_reg));
-			ret = -1;
-		}
-	}
-
-	if (!clk->rate)
-		clk_reg_disable1(clk);
-
-	return ret;
-}
-
-static int set_13MHz_parent(struct clk *clk, struct clk *parent)
-{
-	int ret = -EINVAL;
-
-	if (parent == &ck_13MHz)
-		ret = switch_to_clean_13mhz(clk);
-	else if (parent == &ck_pll1)
-		ret = switch_to_dirty_13mhz(clk);
-
-	return ret;
-}
-
-#define PLL160_MIN_FCCO 156000
-#define PLL160_MAX_FCCO 320000
-
-/*
- * Calculate pll160 settings.
- * Possible input: up to 320MHz with step of clk->parent->rate.
- * In PNX4008 parent rate for pll160s may be either 1 or 13MHz.
- * Ignored paths: "feedback" (bit 13 set), "div-by-N".
- * Setting ARM PLL4 rate to 0 will put CPU into direct run mode.
- * Setting PLL5 and PLL3 rate to 0 will disable USB and DSP clock input.
- * Please refer to PNX4008 IC manual for details.
- */
-
-static int pll160_set_rate(struct clk *clk, u32 rate)
-{
-	u32 tmp_reg, tmp_m, tmp_2p, i;
-	u32 parent_rate;
-	int ret = -EINVAL;
-
-	parent_rate = clk->parent->rate;
-
-	if (!parent_rate)
-		goto out;
-
-	/* set direct run for ARM or disable output for others  */
-	clk_reg_disable(clk);
-
-	/* disable source input as well (ignored for ARM) */
-	clk_reg_disable1(clk);
-
-	tmp_reg = __raw_readl(clk->scale_reg);
-	tmp_reg &= ~0x1ffff;	/*clear all settings, power down */
-	__raw_writel(tmp_reg, clk->scale_reg);
-
-	rate -= rate % parent_rate;	/*round down the input */
-
-	if (rate > PLL160_MAX_FCCO)
-		rate = PLL160_MAX_FCCO;
-
-	if (!rate) {
-		clk->rate = 0;
-		ret = 0;
-		goto out;
-	}
-
-	clk_reg_enable1(clk);
-	tmp_reg = __raw_readl(clk->scale_reg);
-
-	if (rate == parent_rate) {
-		/*enter direct bypass mode */
-		tmp_reg |= ((1 << 14) | (1 << 15));
-		__raw_writel(tmp_reg, clk->scale_reg);
-		clk->rate = parent_rate;
-		clk_reg_enable(clk);
-		ret = 0;
-		goto out;
-	}
-
-	i = 0;
-	for (tmp_2p = 1; tmp_2p < 16; tmp_2p <<= 1) {
-		if (rate * tmp_2p >= PLL160_MIN_FCCO)
-			break;
-		i++;
-	}
-
-	if (tmp_2p > 1)
-		tmp_reg |= ((i - 1) << 11);
-	else
-		tmp_reg |= (1 << 14);	/*direct mode, no divide */
-
-	tmp_m = rate * tmp_2p;
-	tmp_m /= parent_rate;
-
-	tmp_reg |= (tmp_m - 1) << 1;	/*calculate M */
-	tmp_reg |= (1 << 16);	/*power up PLL */
-	__raw_writel(tmp_reg, clk->scale_reg);
-
-	if (clk_wait_for_pll_lock(clk) < 0) {
-		clk_reg_disable(clk);
-		clk_reg_disable1(clk);
-
-		tmp_reg = __raw_readl(clk->scale_reg);
-		tmp_reg &= ~0x1ffff;	/*clear all settings, power down */
-		__raw_writel(tmp_reg, clk->scale_reg);
-		clk->rate = 0;
-		ret = -EFAULT;
-		goto out;
-	}
-
-	clk->rate = (tmp_m * parent_rate) / tmp_2p;
-
-	if (clk->flags & RATE_PROPAGATES)
-		propagate_rate(clk);
-
-	clk_reg_enable(clk);
-	ret = 0;
-
-out:
-	return ret;
-}
-
-/*configure PER_CLK*/
-static int per_clk_set_rate(struct clk *clk, u32 rate)
-{
-	u32 tmp;
-
-	tmp = __raw_readl(clk->scale_reg);
-	tmp &= ~(0x1f << 2);
-	tmp |= ((clk->parent->rate / clk->rate) - 1) << 2;
-	__raw_writel(tmp, clk->scale_reg);
-	clk->rate = rate;
-	return 0;
-}
-
-/*configure HCLK*/
-static int hclk_set_rate(struct clk *clk, u32 rate)
-{
-	u32 tmp;
-	tmp = __raw_readl(clk->scale_reg);
-	tmp = tmp & ~0x3;
-	switch (rate) {
-	case 1:
-		break;
-	case 2:
-		tmp |= 1;
-		break;
-	case 4:
-		tmp |= 2;
-		break;
-	}
-
-	__raw_writel(tmp, clk->scale_reg);
-	clk->rate = rate;
-	return 0;
-}
-
-static u32 hclk_round_rate(struct clk *clk, u32 rate)
-{
-	switch (rate) {
-	case 1:
-	case 4:
-		return rate;
-	}
-	return 2;
-}
-
-static u32 per_clk_round_rate(struct clk *clk, u32 rate)
-{
-	return CLK_RATE_13MHZ;
-}
-
-static int on_off_set_rate(struct clk *clk, u32 rate)
-{
-	if (rate) {
-		clk_reg_enable(clk);
-		clk->rate = 1;
-	} else {
-		clk_reg_disable(clk);
-		clk->rate = 0;
-	}
-	return 0;
-}
-
-static int on_off_inv_set_rate(struct clk *clk, u32 rate)
-{
-	if (rate) {
-		clk_reg_disable(clk);	/*enable bit is inverted */
-		clk->rate = 1;
-	} else {
-		clk_reg_enable(clk);
-		clk->rate = 0;
-	}
-	return 0;
-}
-
-static u32 on_off_round_rate(struct clk *clk, u32 rate)
-{
-	return (rate ? 1 : 0);
-}
-
-static u32 pll4_round_rate(struct clk *clk, u32 rate)
-{
-	if (rate > CLK_RATE_208MHZ)
-		rate = CLK_RATE_208MHZ;
-	if (rate == CLK_RATE_208MHZ && hclk_ck.user_rate == 1)
-		rate = CLK_RATE_208MHZ - CLK_RATE_13MHZ;
-	return (rate - (rate % (hclk_ck.user_rate * CLK_RATE_13MHZ)));
-}
-
-static u32 pll3_round_rate(struct clk *clk, u32 rate)
-{
-	if (rate > CLK_RATE_208MHZ)
-		rate = CLK_RATE_208MHZ;
-	return (rate - rate % CLK_RATE_13MHZ);
-}
-
-static u32 pll5_round_rate(struct clk *clk, u32 rate)
-{
-	return (rate ? CLK_RATE_48MHZ : 0);
-}
-
-static u32 ck_13MHz_round_rate(struct clk *clk, u32 rate)
-{
-	return (rate ? CLK_RATE_13MHZ : 0);
-}
-
-static int ck_13MHz_set_rate(struct clk *clk, u32 rate)
-{
-	if (rate) {
-		clk_reg_disable(clk);	/*enable bit is inverted */
-		udelay(500);
-		clk->rate = CLK_RATE_13MHZ;
-		ck_1MHz.rate = CLK_RATE_1MHZ;
-	} else {
-		clk_reg_enable(clk);
-		clk->rate = 0;
-		ck_1MHz.rate = 0;
-	}
-	return 0;
-}
-
-static int pll1_set_rate(struct clk *clk, u32 rate)
-{
-#if 0 /* doesn't work on some boards, probably a HW BUG */
-	if (rate) {
-		clk_reg_disable(clk);	/*enable bit is inverted */
-		if (!clk_wait_for_pll_lock(clk)) {
-			clk->rate = CLK_RATE_13MHZ;
-		} else {
-			clk_reg_enable(clk);
-			clk->rate = 0;
-		}
-
-	} else {
-		clk_reg_enable(clk);
-		clk->rate = 0;
-	}
-#endif
-	return 0;
-}
-
-/* Clock sources */
-
-static struct clk osc_13MHz = {
-	.name = "osc_13MHz",
-	.flags = FIXED_RATE,
-	.rate = CLK_RATE_13MHZ,
-};
-
-static struct clk ck_13MHz = {
-	.name = "ck_13MHz",
-	.parent = &osc_13MHz,
-	.flags = NEEDS_INITIALIZATION,
-	.round_rate = &ck_13MHz_round_rate,
-	.set_rate = &ck_13MHz_set_rate,
-	.enable_reg = OSC13CTRL_REG,
-	.enable_shift = 0,
-	.rate = CLK_RATE_13MHZ,
-};
-
-static struct clk osc_32KHz = {
-	.name = "osc_32KHz",
-	.flags = FIXED_RATE,
-	.rate = CLK_RATE_32KHZ,
-};
-
-/*attached to PLL5*/
-static struct clk ck_1MHz = {
-	.name = "ck_1MHz",
-	.flags = FIXED_RATE | PARENT_SET_RATE,
-	.parent = &ck_13MHz,
-};
-
-/* PLL1 (397) - provides 13' MHz clock */
-static struct clk ck_pll1 = {
-	.name = "ck_pll1",
-	.parent = &osc_32KHz,
-	.flags = NEEDS_INITIALIZATION,
-	.round_rate = &ck_13MHz_round_rate,
-	.set_rate = &pll1_set_rate,
-	.enable_reg = PLLCTRL_REG,
-	.enable_shift = 1,
-	.scale_reg = PLLCTRL_REG,
-	.rate = CLK_RATE_13MHZ,
-};
-
-/* CPU/Bus PLL */
-static struct clk ck_pll4 = {
-	.name = "ck_pll4",
-	.parent = &ck_pll1,
-	.flags = RATE_PROPAGATES | NEEDS_INITIALIZATION,
-	.propagate_next = &per_ck,
-	.round_rate = &pll4_round_rate,
-	.set_rate = &pll160_set_rate,
-	.rate = CLK_RATE_208MHZ,
-	.scale_reg = HCLKPLLCTRL_REG,
-	.enable_reg = PWRCTRL_REG,
-	.enable_shift = 2,
-	.parent_switch_reg = SYSCLKCTRL_REG,
-	.set_parent = &set_13MHz_parent,
-};
-
-/* USB PLL */
-static struct clk ck_pll5 = {
-	.name = "ck_pll5",
-	.parent = &ck_1MHz,
-	.flags = NEEDS_INITIALIZATION,
-	.round_rate = &pll5_round_rate,
-	.set_rate = &pll160_set_rate,
-	.scale_reg = USBCTRL_REG,
-	.enable_reg = USBCTRL_REG,
-	.enable_shift = 18,
-	.enable_reg1 = USBCTRL_REG,
-	.enable_shift1 = 17,
-};
-
-/* XPERTTeak DSP PLL */
-static struct clk ck_pll3 = {
-	.name = "ck_pll3",
-	.parent = &ck_pll1,
-	.flags = NEEDS_INITIALIZATION,
-	.round_rate = &pll3_round_rate,
-	.set_rate = &pll160_set_rate,
-	.scale_reg = DSPPLLCTRL_REG,
-	.enable_reg = DSPCLKCTRL_REG,
-	.enable_shift = 3,
-	.enable_reg1 = DSPCLKCTRL_REG,
-	.enable_shift1 = 2,
-	.parent_switch_reg = DSPCLKCTRL_REG,
-	.set_parent = &set_13MHz_parent,
-};
-
-static struct clk hclk_ck = {
-	.name = "hclk_ck",
-	.parent = &ck_pll4,
-	.flags = PARENT_SET_RATE,
-	.set_rate = &hclk_set_rate,
-	.round_rate = &hclk_round_rate,
-	.scale_reg = HCLKDIVCTRL_REG,
-	.rate = 2,
-	.user_rate = 2,
-};
-
-static struct clk per_ck = {
-	.name = "per_ck",
-	.parent = &ck_pll4,
-	.flags = FIXED_RATE,
-	.propagate_next = &hclk_ck,
-	.set_rate = &per_clk_set_rate,
-	.round_rate = &per_clk_round_rate,
-	.scale_reg = HCLKDIVCTRL_REG,
-	.rate = CLK_RATE_13MHZ,
-	.user_rate = CLK_RATE_13MHZ,
-};
-
-static struct clk m2hclk_ck = {
-	.name = "m2hclk_ck",
-	.parent = &hclk_ck,
-	.flags = NEEDS_INITIALIZATION,
-	.round_rate = &on_off_round_rate,
-	.set_rate = &on_off_inv_set_rate,
-	.rate = 1,
-	.enable_shift = 6,
-	.enable_reg = PWRCTRL_REG,
-};
-
-static struct clk vfp9_ck = {
-	.name = "vfp9_ck",
-	.parent = &ck_pll4,
-	.flags = NEEDS_INITIALIZATION,
-	.round_rate = &on_off_round_rate,
-	.set_rate = &on_off_set_rate,
-	.rate = 1,
-	.enable_shift = 4,
-	.enable_reg = VFP9CLKCTRL_REG,
-};
-
-static struct clk keyscan_ck = {
-	.name = "keyscan_ck",
-	.parent = &osc_32KHz,
-	.flags = NEEDS_INITIALIZATION,
-	.round_rate = &on_off_round_rate,
-	.set_rate = &on_off_set_rate,
-	.enable_shift = 0,
-	.enable_reg = KEYCLKCTRL_REG,
-};
-
-static struct clk touch_ck = {
-	.name = "touch_ck",
-	.parent = &osc_32KHz,
-	.flags = NEEDS_INITIALIZATION,
-	.round_rate = &on_off_round_rate,
-	.set_rate = &on_off_set_rate,
-	.enable_shift = 0,
-	.enable_reg = TSCLKCTRL_REG,
-};
-
-static struct clk pwm1_ck = {
-	.name = "pwm1_ck",
-	.parent = &osc_32KHz,
-	.flags = NEEDS_INITIALIZATION,
-	.round_rate = &on_off_round_rate,
-	.set_rate = &on_off_set_rate,
-	.enable_shift = 0,
-	.enable_reg = PWMCLKCTRL_REG,
-};
-
-static struct clk pwm2_ck = {
-	.name = "pwm2_ck",
-	.parent = &osc_32KHz,
-	.flags = NEEDS_INITIALIZATION,
-	.round_rate = &on_off_round_rate,
-	.set_rate = &on_off_set_rate,
-	.enable_shift = 2,
-	.enable_reg = PWMCLKCTRL_REG,
-};
-
-static struct clk jpeg_ck = {
-	.name = "jpeg_ck",
-	.parent = &hclk_ck,
-	.flags = NEEDS_INITIALIZATION,
-	.round_rate = &on_off_round_rate,
-	.set_rate = &on_off_set_rate,
-	.enable_shift = 0,
-	.enable_reg = JPEGCLKCTRL_REG,
-};
-
-static struct clk ms_ck = {
-	.name = "ms_ck",
-	.parent = &ck_pll4,
-	.flags = NEEDS_INITIALIZATION,
-	.round_rate = &on_off_round_rate,
-	.set_rate = &on_off_set_rate,
-	.enable_shift = 5,
-	.enable_reg = MSCTRL_REG,
-};
-
-static struct clk dum_ck = {
-	.name = "dum_ck",
-	.parent = &hclk_ck,
-	.flags = NEEDS_INITIALIZATION,
-	.round_rate = &on_off_round_rate,
-	.set_rate = &on_off_set_rate,
-	.enable_shift = 0,
-	.enable_reg = DUMCLKCTRL_REG,
-};
-
-static struct clk flash_ck = {
-	.name = "flash_ck",
-	.parent = &hclk_ck,
-	.round_rate = &on_off_round_rate,
-	.set_rate = &on_off_set_rate,
-	.enable_shift = 1,	/* Only MLC clock supported */
-	.enable_reg = FLASHCLKCTRL_REG,
-};
-
-static struct clk i2c0_ck = {
-	.name = "i2c0_ck",
-	.parent = &per_ck,
-	.flags = NEEDS_INITIALIZATION | FIXED_RATE,
-	.enable_shift = 0,
-	.enable_reg = I2CCLKCTRL_REG,
-	.rate = 13000000,
-	.enable = clk_reg_enable,
-	.disable = clk_reg_disable,
-};
-
-static struct clk i2c1_ck = {
-	.name = "i2c1_ck",
-	.parent = &per_ck,
-	.flags = NEEDS_INITIALIZATION | FIXED_RATE,
-	.enable_shift = 1,
-	.enable_reg = I2CCLKCTRL_REG,
-	.rate = 13000000,
-	.enable = clk_reg_enable,
-	.disable = clk_reg_disable,
-};
-
-static struct clk i2c2_ck = {
-	.name = "i2c2_ck",
-	.parent = &per_ck,
-	.flags = NEEDS_INITIALIZATION | FIXED_RATE,
-	.enable_shift = 2,
-	.enable_reg = USB_OTG_CLKCTRL_REG,
-	.rate = 13000000,
-	.enable = clk_reg_enable,
-	.disable = clk_reg_disable,
-};
-
-static struct clk spi0_ck = {
-	.name = "spi0_ck",
-	.parent = &hclk_ck,
-	.flags = NEEDS_INITIALIZATION,
-	.round_rate = &on_off_round_rate,
-	.set_rate = &on_off_set_rate,
-	.enable_shift = 0,
-	.enable_reg = SPICTRL_REG,
-};
-
-static struct clk spi1_ck = {
-	.name = "spi1_ck",
-	.parent = &hclk_ck,
-	.flags = NEEDS_INITIALIZATION,
-	.round_rate = &on_off_round_rate,
-	.set_rate = &on_off_set_rate,
-	.enable_shift = 4,
-	.enable_reg = SPICTRL_REG,
-};
-
-static struct clk dma_ck = {
-	.name = "dma_ck",
-	.parent = &hclk_ck,
-	.round_rate = &on_off_round_rate,
-	.set_rate = &on_off_set_rate,
-	.enable_shift = 0,
-	.enable_reg = DMACLKCTRL_REG,
-};
-
-static struct clk uart3_ck = {
-	.name = "uart3_ck",
-	.parent = &per_ck,
-	.flags = NEEDS_INITIALIZATION,
-	.round_rate = &on_off_round_rate,
-	.set_rate = &on_off_set_rate,
-	.rate = 1,
-	.enable_shift = 0,
-	.enable_reg = UARTCLKCTRL_REG,
-};
-
-static struct clk uart4_ck = {
-	.name = "uart4_ck",
-	.parent = &per_ck,
-	.flags = NEEDS_INITIALIZATION,
-	.round_rate = &on_off_round_rate,
-	.set_rate = &on_off_set_rate,
-	.enable_shift = 1,
-	.enable_reg = UARTCLKCTRL_REG,
-};
-
-static struct clk uart5_ck = {
-	.name = "uart5_ck",
-	.parent = &per_ck,
-	.flags = NEEDS_INITIALIZATION,
-	.round_rate = &on_off_round_rate,
-	.set_rate = &on_off_set_rate,
-	.rate = 1,
-	.enable_shift = 2,
-	.enable_reg = UARTCLKCTRL_REG,
-};
-
-static struct clk uart6_ck = {
-	.name = "uart6_ck",
-	.parent = &per_ck,
-	.flags = NEEDS_INITIALIZATION,
-	.round_rate = &on_off_round_rate,
-	.set_rate = &on_off_set_rate,
-	.enable_shift = 3,
-	.enable_reg = UARTCLKCTRL_REG,
-};
-
-static struct clk wdt_ck = {
-	.name = "wdt_ck",
-	.parent = &per_ck,
-	.flags = NEEDS_INITIALIZATION,
-	.enable_shift = 0,
-	.enable_reg = TIMCLKCTRL_REG,
-	.enable = clk_reg_enable,
-	.disable = clk_reg_disable,
-};
-
-/* These clocks are visible outside this module
- * and can be initialized
- */
-static struct clk *onchip_clks[] __initdata = {
-	&ck_13MHz,
-	&ck_pll1,
-	&ck_pll4,
-	&ck_pll5,
-	&ck_pll3,
-	&vfp9_ck,
-	&m2hclk_ck,
-	&hclk_ck,
-	&dma_ck,
-	&flash_ck,
-	&dum_ck,
-	&keyscan_ck,
-	&pwm1_ck,
-	&pwm2_ck,
-	&jpeg_ck,
-	&ms_ck,
-	&touch_ck,
-	&i2c0_ck,
-	&i2c1_ck,
-	&i2c2_ck,
-	&spi0_ck,
-	&spi1_ck,
-	&uart3_ck,
-	&uart4_ck,
-	&uart5_ck,
-	&uart6_ck,
-	&wdt_ck,
-};
-
-static struct clk_lookup onchip_clkreg[] = {
-	{ .clk = &ck_13MHz,	.con_id = "ck_13MHz"	},
-	{ .clk = &ck_pll1,	.con_id = "ck_pll1"	},
-	{ .clk = &ck_pll4,	.con_id = "ck_pll4"	},
-	{ .clk = &ck_pll5,	.con_id = "ck_pll5"	},
-	{ .clk = &ck_pll3,	.con_id = "ck_pll3"	},
-	{ .clk = &vfp9_ck,	.con_id = "vfp9_ck"	},
-	{ .clk = &m2hclk_ck,	.con_id = "m2hclk_ck"	},
-	{ .clk = &hclk_ck,	.con_id = "hclk_ck"	},
-	{ .clk = &dma_ck,	.con_id = "dma_ck"	},
-	{ .clk = &flash_ck,	.con_id = "flash_ck"	},
-	{ .clk = &dum_ck,	.con_id = "dum_ck"	},
-	{ .clk = &keyscan_ck,	.con_id = "keyscan_ck"	},
-	{ .clk = &pwm1_ck,	.con_id = "pwm1_ck"	},
-	{ .clk = &pwm2_ck,	.con_id = "pwm2_ck"	},
-	{ .clk = &jpeg_ck,	.con_id = "jpeg_ck"	},
-	{ .clk = &ms_ck,	.con_id = "ms_ck"	},
-	{ .clk = &touch_ck,	.con_id = "touch_ck"	},
-	{ .clk = &i2c0_ck,	.dev_id = "pnx-i2c.0"	},
-	{ .clk = &i2c1_ck,	.dev_id = "pnx-i2c.1"	},
-	{ .clk = &i2c2_ck,	.dev_id = "pnx-i2c.2"	},
-	{ .clk = &spi0_ck,	.con_id = "spi0_ck"	},
-	{ .clk = &spi1_ck,	.con_id = "spi1_ck"	},
-	{ .clk = &uart3_ck,	.con_id = "uart3_ck"	},
-	{ .clk = &uart4_ck,	.con_id = "uart4_ck"	},
-	{ .clk = &uart5_ck,	.con_id = "uart5_ck"	},
-	{ .clk = &uart6_ck,	.con_id = "uart6_ck"	},
-	{ .clk = &wdt_ck,	.dev_id = "pnx4008-watchdog" },
-};
-
-static void local_clk_disable(struct clk *clk)
-{
-	if (WARN_ON(clk->usecount == 0))
-		return;
-
-	if (!(--clk->usecount)) {
-		if (clk->disable)
-			clk->disable(clk);
-		else if (!(clk->flags & FIXED_RATE) && clk->rate && clk->set_rate)
-			clk->set_rate(clk, 0);
-		if (clk->parent)
-			local_clk_disable(clk->parent);
-	}
-}
-
-static int local_clk_enable(struct clk *clk)
-{
-	int ret = 0;
-
-	if (clk->usecount == 0) {
-		if (clk->parent) {
-			ret = local_clk_enable(clk->parent);
-			if (ret != 0)
-				goto out;
-		}
-
-		if (clk->enable)
-			ret = clk->enable(clk);
-		else if (!(clk->flags & FIXED_RATE) && !clk->rate && clk->set_rate
-			    && clk->user_rate)
-			ret = clk->set_rate(clk, clk->user_rate);
-
-		if (ret != 0 && clk->parent) {
-			local_clk_disable(clk->parent);
-			goto out;
-		}
-
-		clk->usecount++;
-	}
-out:
-	return ret;
-}
-
-static int local_set_rate(struct clk *clk, u32 rate)
-{
-	int ret = -EINVAL;
-	if (clk->set_rate) {
-
-		if (clk->user_rate == clk->rate && clk->parent->rate) {
-			/* if clock enabled or rate not set */
-			clk->user_rate = clk->round_rate(clk, rate);
-			ret = clk->set_rate(clk, clk->user_rate);
-		} else
-			clk->user_rate = clk->round_rate(clk, rate);
-		ret = 0;
-	}
-	return ret;
-}
-
-int clk_set_rate(struct clk *clk, unsigned long rate)
-{
-	int ret = -EINVAL;
-
-	if (clk->flags & FIXED_RATE)
-		goto out;
-
-	clock_lock();
-	if ((clk->flags & PARENT_SET_RATE) && clk->parent) {
-
-		clk->user_rate = clk->round_rate(clk, rate);
-		/* parent clock needs to be refreshed
-		   for the setting to take effect */
-	} else {
-		ret = local_set_rate(clk, rate);
-	}
-	ret = 0;
-	clock_unlock();
-
-out:
-	return ret;
-}
-
-EXPORT_SYMBOL(clk_set_rate);
-
-unsigned long clk_get_rate(struct clk *clk)
-{
-	unsigned long ret;
-	clock_lock();
-	ret = clk->rate;
-	clock_unlock();
-	return ret;
-}
-EXPORT_SYMBOL(clk_get_rate);
-
-int clk_enable(struct clk *clk)
-{
-	int ret;
-
-	clock_lock();
-	ret = local_clk_enable(clk);
-	clock_unlock();
-	return ret;
-}
-
-EXPORT_SYMBOL(clk_enable);
-
-void clk_disable(struct clk *clk)
-{
-	clock_lock();
-	local_clk_disable(clk);
-	clock_unlock();
-}
-
-EXPORT_SYMBOL(clk_disable);
-
-long clk_round_rate(struct clk *clk, unsigned long rate)
-{
-	long ret;
-	clock_lock();
-	if (clk->round_rate)
-		ret = clk->round_rate(clk, rate);
-	else
-		ret = clk->rate;
-	clock_unlock();
-	return ret;
-}
-
-EXPORT_SYMBOL(clk_round_rate);
-
-int clk_set_parent(struct clk *clk, struct clk *parent)
-{
-	int ret = -ENODEV;
-	if (!clk->set_parent)
-		goto out;
-
-	clock_lock();
-	ret = clk->set_parent(clk, parent);
-	if (!ret)
-		clk->parent = parent;
-	clock_unlock();
-
-out:
-	return ret;
-}
-
-EXPORT_SYMBOL(clk_set_parent);
-
-static int __init clk_init(void)
-{
-	struct clk **clkp;
-
-	/* Disable autoclocking, as it doesn't seem to work */
-	__raw_writel(0xff, AUTOCLK_CTRL);
-
-	for (clkp = onchip_clks; clkp < onchip_clks + ARRAY_SIZE(onchip_clks);
-	     clkp++) {
-		struct clk *clk = *clkp;
-		if (clk->flags & NEEDS_INITIALIZATION) {
-			if (clk->set_rate) {
-				clk->user_rate = clk->rate;
-				local_set_rate(clk, clk->user_rate);
-				if (clk->set_parent)
-					clk->set_parent(clk, clk->parent);
-			}
-			if (clk->enable && clk->usecount)
-				clk->enable(clk);
-			if (clk->disable && !clk->usecount)
-				clk->disable(clk);
-		}
-		pr_debug("%s: clock %s, rate %ld\n",
-			__func__, clk->name, clk->rate);
-	}
-
-	local_clk_enable(&ck_pll4);
-
-	/* if ck_13MHz is not used, disable it. */
-	if (ck_13MHz.usecount == 0)
-		local_clk_disable(&ck_13MHz);
-
-	/* Disable autoclocking */
-	__raw_writeb(0xff, AUTOCLK_CTRL);
-
-	clkdev_add_table(onchip_clkreg, ARRAY_SIZE(onchip_clkreg));
-
-	return 0;
-}
-
-arch_initcall(clk_init);
diff --git a/arch/arm/mach-pnx4008/clock.h b/arch/arm/mach-pnx4008/clock.h
deleted file mode 100644
index 39720d6..0000000
--- a/arch/arm/mach-pnx4008/clock.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * arch/arm/mach-pnx4008/clock.h
- *
- * Clock control driver for PNX4008 - internal header file
- *
- * Author: Vitaly Wool <source@mvista.com>
- *
- * 2006 (c) MontaVista Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-#ifndef __ARCH_ARM_PNX4008_CLOCK_H__
-#define __ARCH_ARM_PNX4008_CLOCK_H__
-
-struct clk {
-	const char *name;
-	struct clk *parent;
-	struct clk *propagate_next;
-	u32 rate;
-	u32 user_rate;
-	s8 usecount;
-	u32 flags;
-	u32 scale_reg;
-	u8 enable_shift;
-	u32 enable_reg;
-	u8 enable_shift1;
-	u32 enable_reg1;
-	u32 parent_switch_reg;
-	u32(*round_rate) (struct clk *, u32);
-	int (*set_rate) (struct clk *, u32);
-	int (*set_parent) (struct clk * clk, struct clk * parent);
-	int (*enable)(struct clk *);
-	void (*disable)(struct clk *);
-};
-
-/* Flags */
-#define RATE_PROPAGATES      (1<<0)
-#define NEEDS_INITIALIZATION (1<<1)
-#define PARENT_SET_RATE      (1<<2)
-#define FIXED_RATE           (1<<3)
-
-#endif
diff --git a/arch/arm/mach-pnx4008/core.c b/arch/arm/mach-pnx4008/core.c
deleted file mode 100644
index a00d2f1..0000000
--- a/arch/arm/mach-pnx4008/core.c
+++ /dev/null
@@ -1,290 +0,0 @@
-/*
- * arch/arm/mach-pnx4008/core.c
- *
- * PNX4008 core startup code
- *
- * Authors: Vitaly Wool, Dmitry Chigirev,
- * Grigory Tolstolytkin, Dmitry Pervushin <source@mvista.com>
- *
- * Based on reference code received from Philips:
- * Copyright (C) 2003 Philips Semiconductors
- *
- * 2005 (c) MontaVista Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/list.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/serial_8250.h>
-#include <linux/device.h>
-#include <linux/spi/spi.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
-#include <asm/system_misc.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/time.h>
-
-#include <mach/irq.h>
-#include <mach/clock.h>
-#include <mach/dma.h>
-
-struct resource spipnx_0_resources[] = {
-	{
-		.start = PNX4008_SPI1_BASE,
-		.end = PNX4008_SPI1_BASE + SZ_4K,
-		.flags = IORESOURCE_MEM,
-	}, {
-		.start = PER_SPI1_REC_XMIT,
-		.flags = IORESOURCE_DMA,
-	}, {
-		.start = SPI1_INT,
-		.flags = IORESOURCE_IRQ,
-	}, {
-		.flags = 0,
-	},
-};
-
-struct resource spipnx_1_resources[] = {
-	{
-		.start = PNX4008_SPI2_BASE,
-		.end = PNX4008_SPI2_BASE + SZ_4K,
-		.flags = IORESOURCE_MEM,
-	}, {
-		.start = PER_SPI2_REC_XMIT,
-		.flags = IORESOURCE_DMA,
-	}, {
-		.start = SPI2_INT,
-		.flags = IORESOURCE_IRQ,
-	}, {
-		.flags = 0,
-	}
-};
-
-static struct spi_board_info spi_board_info[] __initdata = {
-	{
-		.modalias	= "m25p80",
-		.max_speed_hz	= 1000000,
-		.bus_num	= 1,
-		.chip_select	= 0,
-	},
-};
-
-static struct platform_device spipnx_1 = {
-	.name = "spipnx",
-	.id = 1,
-	.num_resources = ARRAY_SIZE(spipnx_0_resources),
-	.resource = spipnx_0_resources,
-	.dev = {
-		.coherent_dma_mask = 0xFFFFFFFF,
-		},
-};
-
-static struct platform_device spipnx_2 = {
-	.name = "spipnx",
-	.id = 2,
-	.num_resources = ARRAY_SIZE(spipnx_1_resources),
-	.resource = spipnx_1_resources,
-	.dev = {
-		.coherent_dma_mask = 0xFFFFFFFF,
-		},
-};
-
-static struct plat_serial8250_port platform_serial_ports[] = {
-	{
-		.membase = (void *)__iomem(IO_ADDRESS(PNX4008_UART5_BASE)),
-		.mapbase = (unsigned long)PNX4008_UART5_BASE,
-		.irq = IIR5_INT,
-		.uartclk = PNX4008_UART_CLK,
-		.regshift = 2,
-		.iotype = UPIO_MEM,
-		.flags = UPF_BOOT_AUTOCONF | UPF_BUGGY_UART | UPF_SKIP_TEST,
-	},
-	{
-		.membase = (void *)__iomem(IO_ADDRESS(PNX4008_UART3_BASE)),
-		.mapbase = (unsigned long)PNX4008_UART3_BASE,
-		.irq = IIR3_INT,
-		.uartclk = PNX4008_UART_CLK,
-		.regshift = 2,
-		.iotype = UPIO_MEM,
-		.flags = UPF_BOOT_AUTOCONF | UPF_BUGGY_UART | UPF_SKIP_TEST,
-	 },
-	{}
-};
-
-static struct platform_device serial_device = {
-	.name = "serial8250",
-	.id = PLAT8250_DEV_PLATFORM,
-	.dev = {
-		.platform_data = &platform_serial_ports,
-	},
-};
-
-static struct platform_device nand_flash_device = {
-	.name = "pnx4008-flash",
-	.id = -1,
-	.dev = {
-		.coherent_dma_mask = 0xFFFFFFFF,
-	},
-};
-
-/* The dmamask must be set for OHCI to work */
-static u64 ohci_dmamask = ~(u32) 0;
-
-static struct resource ohci_resources[] = {
-	{
-		.start = IO_ADDRESS(PNX4008_USB_CONFIG_BASE),
-		.end = IO_ADDRESS(PNX4008_USB_CONFIG_BASE + 0x100),
-		.flags = IORESOURCE_MEM,
-	}, {
-		.start = USB_HOST_INT,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device ohci_device = {
-	.name = "pnx4008-usb-ohci",
-	.id = -1,
-	.dev = {
-		.dma_mask = &ohci_dmamask,
-		.coherent_dma_mask = 0xffffffff,
-		},
-	.num_resources = ARRAY_SIZE(ohci_resources),
-	.resource = ohci_resources,
-};
-
-static struct platform_device sdum_device = {
-	.name = "pnx4008-sdum",
-	.id = 0,
-	.dev = {
-		.coherent_dma_mask = 0xffffffff,
-	},
-};
-
-static struct platform_device rgbfb_device = {
-	.name = "pnx4008-rgbfb",
-	.id = 0,
-	.dev = {
-		.coherent_dma_mask = 0xffffffff,
-	}
-};
-
-struct resource watchdog_resources[] = {
-	{
-		.start = PNX4008_WDOG_BASE,
-		.end = PNX4008_WDOG_BASE + SZ_4K - 1,
-		.flags = IORESOURCE_MEM,
-	},
-};
-
-static struct platform_device watchdog_device = {
-	.name = "pnx4008-watchdog",
-	.id = -1,
-	.num_resources = ARRAY_SIZE(watchdog_resources),
-	.resource = watchdog_resources,
-};
-
-static struct platform_device *devices[] __initdata = {
-	&spipnx_1,
-	&spipnx_2,
-	&serial_device,
-	&ohci_device,
-	&nand_flash_device,
-	&sdum_device,
-	&rgbfb_device,
-	&watchdog_device,
-};
-
-
-extern void pnx4008_uart_init(void);
-
-static void __init pnx4008_init(void)
-{
-	/*disable all START interrupt sources,
-	   and clear all START interrupt flags */
-	__raw_writel(0, START_INT_ER_REG(SE_PIN_BASE_INT));
-	__raw_writel(0, START_INT_ER_REG(SE_INT_BASE_INT));
-	__raw_writel(0xffffffff, START_INT_RSR_REG(SE_PIN_BASE_INT));
-	__raw_writel(0xffffffff, START_INT_RSR_REG(SE_INT_BASE_INT));
-
-	platform_add_devices(devices, ARRAY_SIZE(devices));
-	spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
-	/* Switch on the UART clocks */
-	pnx4008_uart_init();
-}
-
-static struct map_desc pnx4008_io_desc[] __initdata = {
-	{
-		.virtual 	= IO_ADDRESS(PNX4008_IRAM_BASE),
-		.pfn 		= __phys_to_pfn(PNX4008_IRAM_BASE),
-		.length		= SZ_64K,
-		.type 		= MT_DEVICE,
-	}, {
-		.virtual 	= IO_ADDRESS(PNX4008_NDF_FLASH_BASE),
-		.pfn 		= __phys_to_pfn(PNX4008_NDF_FLASH_BASE),
-		.length		= SZ_1M - SZ_128K,
-		.type 		= MT_DEVICE,
-	}, {
-		.virtual 	= IO_ADDRESS(PNX4008_JPEG_CONFIG_BASE),
-		.pfn 		= __phys_to_pfn(PNX4008_JPEG_CONFIG_BASE),
-		.length		= SZ_128K * 3,
-		.type 		= MT_DEVICE,
-	}, {
-		.virtual 	= IO_ADDRESS(PNX4008_DMA_CONFIG_BASE),
-		.pfn 		= __phys_to_pfn(PNX4008_DMA_CONFIG_BASE),
-		.length		= SZ_1M,
-		.type 		= MT_DEVICE,
-	}, {
-		.virtual 	= IO_ADDRESS(PNX4008_AHB2FAB_BASE),
-		.pfn 		= __phys_to_pfn(PNX4008_AHB2FAB_BASE),
-		.length		= SZ_1M,
-		.type 		= MT_DEVICE,
-	},
-};
-
-void __init pnx4008_map_io(void)
-{
-	iotable_init(pnx4008_io_desc, ARRAY_SIZE(pnx4008_io_desc));
-}
-
-static void pnx4008_restart(char mode, const char *cmd)
-{
-	soft_restart(0);
-}
-
-#ifdef CONFIG_PM
-extern int pnx4008_pm_init(void);
-#else
-static inline int pnx4008_pm_init(void) { return 0; }
-#endif
-
-void __init pnx4008_init_late(void)
-{
-	pnx4008_pm_init();
-}
-
-extern struct sys_timer pnx4008_timer;
-
-MACHINE_START(PNX4008, "Philips PNX4008")
-	/* Maintainer: MontaVista Software Inc. */
-	.atag_offset		= 0x100,
-	.map_io 		= pnx4008_map_io,
-	.init_irq 		= pnx4008_init_irq,
-	.init_machine 		= pnx4008_init,
-	.init_late		= pnx4008_init_late,
-	.timer 			= &pnx4008_timer,
-	.restart		= pnx4008_restart,
-MACHINE_END
diff --git a/arch/arm/mach-pnx4008/dma.c b/arch/arm/mach-pnx4008/dma.c
deleted file mode 100644
index a4739e9..0000000
--- a/arch/arm/mach-pnx4008/dma.c
+++ /dev/null
@@ -1,1105 +0,0 @@
-/*
- *  linux/arch/arm/mach-pnx4008/dma.c
- *
- *  PNX4008 DMA registration and IRQ dispatching
- *
- *  Author:	Vitaly Wool
- *  Copyright:	MontaVista Software Inc. (c) 2005
- *
- *  Based on the code from Nicolas Pitre
- *
- *  This program is free software; you can 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/init.h>
-#include <linux/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/dma-mapping.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/gfp.h>
-
-#include <mach/hardware.h>
-#include <mach/dma.h>
-#include <asm/dma-mapping.h>
-#include <mach/clock.h>
-
-static struct dma_channel {
-	char *name;
-	void (*irq_handler) (int, int, void *);
-	void *data;
-	struct pnx4008_dma_ll *ll;
-	u32 ll_dma;
-	void *target_addr;
-	int target_id;
-} dma_channels[MAX_DMA_CHANNELS];
-
-static struct ll_pool {
-	void *vaddr;
-	void *cur;
-	dma_addr_t dma_addr;
-	int count;
-} ll_pool;
-
-static DEFINE_SPINLOCK(ll_lock);
-
-struct pnx4008_dma_ll *pnx4008_alloc_ll_entry(dma_addr_t * ll_dma)
-{
-	struct pnx4008_dma_ll *ll = NULL;
-	unsigned long flags;
-
-	spin_lock_irqsave(&ll_lock, flags);
-	if (ll_pool.count > 4) { /* can give one more */
-		ll = *(struct pnx4008_dma_ll **) ll_pool.cur;
-		*ll_dma = ll_pool.dma_addr + ((void *)ll - ll_pool.vaddr);
-		*(void **)ll_pool.cur = **(void ***)ll_pool.cur;
-		memset(ll, 0, sizeof(*ll));
-		ll_pool.count--;
-	}
-	spin_unlock_irqrestore(&ll_lock, flags);
-
-	return ll;
-}
-
-EXPORT_SYMBOL_GPL(pnx4008_alloc_ll_entry);
-
-void pnx4008_free_ll_entry(struct pnx4008_dma_ll * ll, dma_addr_t ll_dma)
-{
-	unsigned long flags;
-
-	if (ll) {
-		if ((unsigned long)((long)ll - (long)ll_pool.vaddr) > 0x4000) {
-			printk(KERN_ERR "Trying to free entry not allocated by DMA\n");
-			BUG();
-		}
-
-		if (ll->flags & DMA_BUFFER_ALLOCATED)
-			ll->free(ll->alloc_data);
-
-		spin_lock_irqsave(&ll_lock, flags);
-		*(long *)ll = *(long *)ll_pool.cur;
-		*(long *)ll_pool.cur = (long)ll;
-		ll_pool.count++;
-		spin_unlock_irqrestore(&ll_lock, flags);
-	}
-}
-
-EXPORT_SYMBOL_GPL(pnx4008_free_ll_entry);
-
-void pnx4008_free_ll(u32 ll_dma, struct pnx4008_dma_ll * ll)
-{
-	struct pnx4008_dma_ll *ptr;
-	u32 dma;
-
-	while (ll) {
-		dma = ll->next_dma;
-		ptr = ll->next;
-		pnx4008_free_ll_entry(ll, ll_dma);
-
-		ll_dma = dma;
-		ll = ptr;
-	}
-}
-
-EXPORT_SYMBOL_GPL(pnx4008_free_ll);
-
-static int dma_channels_requested = 0;
-
-static inline void dma_increment_usage(void)
-{
-	if (!dma_channels_requested++) {
-		struct clk *clk = clk_get(0, "dma_ck");
-		if (!IS_ERR(clk)) {
-			clk_set_rate(clk, 1);
-			clk_put(clk);
-		}
-		pnx4008_config_dma(-1, -1, 1);
-	}
-}
-static inline void dma_decrement_usage(void)
-{
-	if (!--dma_channels_requested) {
-		struct clk *clk = clk_get(0, "dma_ck");
-		if (!IS_ERR(clk)) {
-			clk_set_rate(clk, 0);
-			clk_put(clk);
-		}
-		pnx4008_config_dma(-1, -1, 0);
-
-	}
-}
-
-static DEFINE_SPINLOCK(dma_lock);
-
-static inline void pnx4008_dma_lock(void)
-{
-	spin_lock_irq(&dma_lock);
-}
-
-static inline void pnx4008_dma_unlock(void)
-{
-	spin_unlock_irq(&dma_lock);
-}
-
-#define VALID_CHANNEL(c)	(((c) >= 0) && ((c) < MAX_DMA_CHANNELS))
-
-int pnx4008_request_channel(char *name, int ch,
-			    void (*irq_handler) (int, int, void *), void *data)
-{
-	int i, found = 0;
-
-	/* basic sanity checks */
-	if (!name || (ch != -1 && !VALID_CHANNEL(ch)))
-		return -EINVAL;
-
-	pnx4008_dma_lock();
-
-	/* try grabbing a DMA channel with the requested priority */
-	for (i = MAX_DMA_CHANNELS - 1; i >= 0; i--) {
-		if (!dma_channels[i].name && (ch == -1 || ch == i)) {
-			found = 1;
-			break;
-		}
-	}
-
-	if (found) {
-		dma_increment_usage();
-		dma_channels[i].name = name;
-		dma_channels[i].irq_handler = irq_handler;
-		dma_channels[i].data = data;
-		dma_channels[i].ll = NULL;
-		dma_channels[i].ll_dma = 0;
-	} else {
-		printk(KERN_WARNING "No more available DMA channels for %s\n",
-		       name);
-		i = -ENODEV;
-	}
-
-	pnx4008_dma_unlock();
-	return i;
-}
-
-EXPORT_SYMBOL_GPL(pnx4008_request_channel);
-
-void pnx4008_free_channel(int ch)
-{
-	if (!dma_channels[ch].name) {
-		printk(KERN_CRIT
-		       "%s: trying to free channel %d which is already freed\n",
-		       __func__, ch);
-		return;
-	}
-
-	pnx4008_dma_lock();
-	pnx4008_free_ll(dma_channels[ch].ll_dma, dma_channels[ch].ll);
-	dma_channels[ch].ll = NULL;
-	dma_decrement_usage();
-
-	dma_channels[ch].name = NULL;
-	pnx4008_dma_unlock();
-}
-
-EXPORT_SYMBOL_GPL(pnx4008_free_channel);
-
-int pnx4008_config_dma(int ahb_m1_be, int ahb_m2_be, int enable)
-{
-	unsigned long dma_cfg = __raw_readl(DMAC_CONFIG);
-
-	switch (ahb_m1_be) {
-	case 0:
-		dma_cfg &= ~(1 << 1);
-		break;
-	case 1:
-		dma_cfg |= (1 << 1);
-		break;
-	default:
-		break;
-	}
-
-	switch (ahb_m2_be) {
-	case 0:
-		dma_cfg &= ~(1 << 2);
-		break;
-	case 1:
-		dma_cfg |= (1 << 2);
-		break;
-	default:
-		break;
-	}
-
-	switch (enable) {
-	case 0:
-		dma_cfg &= ~(1 << 0);
-		break;
-	case 1:
-		dma_cfg |= (1 << 0);
-		break;
-	default:
-		break;
-	}
-
-	pnx4008_dma_lock();
-	__raw_writel(dma_cfg, DMAC_CONFIG);
-	pnx4008_dma_unlock();
-
-	return 0;
-}
-
-EXPORT_SYMBOL_GPL(pnx4008_config_dma);
-
-int pnx4008_dma_pack_control(const struct pnx4008_dma_ch_ctrl * ch_ctrl,
-			     unsigned long *ctrl)
-{
-	int i = 0, dbsize, sbsize, err = 0;
-
-	if (!ctrl || !ch_ctrl) {
-		err = -EINVAL;
-		goto out;
-	}
-
-	*ctrl = 0;
-
-	switch (ch_ctrl->tc_mask) {
-	case 0:
-		break;
-	case 1:
-		*ctrl |= (1 << 31);
-		break;
-
-	default:
-		err = -EINVAL;
-		goto out;
-	}
-
-	switch (ch_ctrl->cacheable) {
-	case 0:
-		break;
-	case 1:
-		*ctrl |= (1 << 30);
-		break;
-
-	default:
-		err = -EINVAL;
-		goto out;
-	}
-	switch (ch_ctrl->bufferable) {
-	case 0:
-		break;
-	case 1:
-		*ctrl |= (1 << 29);
-		break;
-
-	default:
-		err = -EINVAL;
-		goto out;
-	}
-	switch (ch_ctrl->priv_mode) {
-	case 0:
-		break;
-	case 1:
-		*ctrl |= (1 << 28);
-		break;
-
-	default:
-		err = -EINVAL;
-		goto out;
-	}
-	switch (ch_ctrl->di) {
-	case 0:
-		break;
-	case 1:
-		*ctrl |= (1 << 27);
-		break;
-
-	default:
-		err = -EINVAL;
-		goto out;
-	}
-	switch (ch_ctrl->si) {
-	case 0:
-		break;
-	case 1:
-		*ctrl |= (1 << 26);
-		break;
-
-	default:
-		err = -EINVAL;
-		goto out;
-	}
-	switch (ch_ctrl->dest_ahb1) {
-	case 0:
-		break;
-	case 1:
-		*ctrl |= (1 << 25);
-		break;
-
-	default:
-		err = -EINVAL;
-		goto out;
-	}
-	switch (ch_ctrl->src_ahb1) {
-	case 0:
-		break;
-	case 1:
-		*ctrl |= (1 << 24);
-		break;
-
-	default:
-		err = -EINVAL;
-		goto out;
-	}
-	switch (ch_ctrl->dwidth) {
-	case WIDTH_BYTE:
-		*ctrl &= ~(7 << 21);
-		break;
-	case WIDTH_HWORD:
-		*ctrl &= ~(7 << 21);
-		*ctrl |= (1 << 21);
-		break;
-	case WIDTH_WORD:
-		*ctrl &= ~(7 << 21);
-		*ctrl |= (2 << 21);
-		break;
-
-	default:
-		err = -EINVAL;
-		goto out;
-	}
-	switch (ch_ctrl->swidth) {
-	case WIDTH_BYTE:
-		*ctrl &= ~(7 << 18);
-		break;
-	case WIDTH_HWORD:
-		*ctrl &= ~(7 << 18);
-		*ctrl |= (1 << 18);
-		break;
-	case WIDTH_WORD:
-		*ctrl &= ~(7 << 18);
-		*ctrl |= (2 << 18);
-		break;
-
-	default:
-		err = -EINVAL;
-		goto out;
-	}
-	dbsize = ch_ctrl->dbsize;
-	while (!(dbsize & 1)) {
-		i++;
-		dbsize >>= 1;
-	}
-	if (ch_ctrl->dbsize != 1 || i > 8 || i == 1) {
-		err = -EINVAL;
-		goto out;
-	} else if (i > 1)
-		i--;
-	*ctrl &= ~(7 << 15);
-	*ctrl |= (i << 15);
-
-	sbsize = ch_ctrl->sbsize;
-	while (!(sbsize & 1)) {
-		i++;
-		sbsize >>= 1;
-	}
-	if (ch_ctrl->sbsize != 1 || i > 8 || i == 1) {
-		err = -EINVAL;
-		goto out;
-	} else if (i > 1)
-		i--;
-	*ctrl &= ~(7 << 12);
-	*ctrl |= (i << 12);
-
-	if (ch_ctrl->tr_size > 0x7ff) {
-		err = -E2BIG;
-		goto out;
-	}
-	*ctrl &= ~0x7ff;
-	*ctrl |= ch_ctrl->tr_size & 0x7ff;
-
-out:
-	return err;
-}
-
-EXPORT_SYMBOL_GPL(pnx4008_dma_pack_control);
-
-int pnx4008_dma_parse_control(unsigned long ctrl,
-			      struct pnx4008_dma_ch_ctrl * ch_ctrl)
-{
-	int err = 0;
-
-	if (!ch_ctrl) {
-		err = -EINVAL;
-		goto out;
-	}
-
-	ch_ctrl->tr_size = ctrl & 0x7ff;
-	ctrl >>= 12;
-
-	ch_ctrl->sbsize = 1 << (ctrl & 7);
-	if (ch_ctrl->sbsize > 1)
-		ch_ctrl->sbsize <<= 1;
-	ctrl >>= 3;
-
-	ch_ctrl->dbsize = 1 << (ctrl & 7);
-	if (ch_ctrl->dbsize > 1)
-		ch_ctrl->dbsize <<= 1;
-	ctrl >>= 3;
-
-	switch (ctrl & 7) {
-	case 0:
-		ch_ctrl->swidth = WIDTH_BYTE;
-		break;
-	case 1:
-		ch_ctrl->swidth = WIDTH_HWORD;
-		break;
-	case 2:
-		ch_ctrl->swidth = WIDTH_WORD;
-		break;
-	default:
-		err = -EINVAL;
-		goto out;
-	}
-	ctrl >>= 3;
-
-	switch (ctrl & 7) {
-	case 0:
-		ch_ctrl->dwidth = WIDTH_BYTE;
-		break;
-	case 1:
-		ch_ctrl->dwidth = WIDTH_HWORD;
-		break;
-	case 2:
-		ch_ctrl->dwidth = WIDTH_WORD;
-		break;
-	default:
-		err = -EINVAL;
-		goto out;
-	}
-	ctrl >>= 3;
-
-	ch_ctrl->src_ahb1 = ctrl & 1;
-	ctrl >>= 1;
-
-	ch_ctrl->dest_ahb1 = ctrl & 1;
-	ctrl >>= 1;
-
-	ch_ctrl->si = ctrl & 1;
-	ctrl >>= 1;
-
-	ch_ctrl->di = ctrl & 1;
-	ctrl >>= 1;
-
-	ch_ctrl->priv_mode = ctrl & 1;
-	ctrl >>= 1;
-
-	ch_ctrl->bufferable = ctrl & 1;
-	ctrl >>= 1;
-
-	ch_ctrl->cacheable = ctrl & 1;
-	ctrl >>= 1;
-
-	ch_ctrl->tc_mask = ctrl & 1;
-
-out:
-	return err;
-}
-
-EXPORT_SYMBOL_GPL(pnx4008_dma_parse_control);
-
-int pnx4008_dma_pack_config(const struct pnx4008_dma_ch_config * ch_cfg,
-			    unsigned long *cfg)
-{
-	int err = 0;
-
-	if (!cfg || !ch_cfg) {
-		err = -EINVAL;
-		goto out;
-	}
-
-	*cfg = 0;
-
-	switch (ch_cfg->halt) {
-	case 0:
-		break;
-	case 1:
-		*cfg |= (1 << 18);
-		break;
-
-	default:
-		err = -EINVAL;
-		goto out;
-	}
-	switch (ch_cfg->active) {
-	case 0:
-		break;
-	case 1:
-		*cfg |= (1 << 17);
-		break;
-
-	default:
-		err = -EINVAL;
-		goto out;
-	}
-	switch (ch_cfg->lock) {
-	case 0:
-		break;
-	case 1:
-		*cfg |= (1 << 16);
-		break;
-
-	default:
-		err = -EINVAL;
-		goto out;
-	}
-	switch (ch_cfg->itc) {
-	case 0:
-		break;
-	case 1:
-		*cfg |= (1 << 15);
-		break;
-
-	default:
-		err = -EINVAL;
-		goto out;
-	}
-	switch (ch_cfg->ie) {
-	case 0:
-		break;
-	case 1:
-		*cfg |= (1 << 14);
-		break;
-
-	default:
-		err = -EINVAL;
-		goto out;
-	}
-	switch (ch_cfg->flow_cntrl) {
-	case FC_MEM2MEM_DMA:
-		*cfg &= ~(7 << 11);
-		break;
-	case FC_MEM2PER_DMA:
-		*cfg &= ~(7 << 11);
-		*cfg |= (1 << 11);
-		break;
-	case FC_PER2MEM_DMA:
-		*cfg &= ~(7 << 11);
-		*cfg |= (2 << 11);
-		break;
-	case FC_PER2PER_DMA:
-		*cfg &= ~(7 << 11);
-		*cfg |= (3 << 11);
-		break;
-	case FC_PER2PER_DPER:
-		*cfg &= ~(7 << 11);
-		*cfg |= (4 << 11);
-		break;
-	case FC_MEM2PER_PER:
-		*cfg &= ~(7 << 11);
-		*cfg |= (5 << 11);
-		break;
-	case FC_PER2MEM_PER:
-		*cfg &= ~(7 << 11);
-		*cfg |= (6 << 11);
-		break;
-	case FC_PER2PER_SPER:
-		*cfg |= (7 << 11);
-		break;
-
-	default:
-		err = -EINVAL;
-		goto out;
-	}
-	*cfg &= ~(0x1f << 6);
-	*cfg |= ((ch_cfg->dest_per & 0x1f) << 6);
-
-	*cfg &= ~(0x1f << 1);
-	*cfg |= ((ch_cfg->src_per & 0x1f) << 1);
-
-out:
-	return err;
-}
-
-EXPORT_SYMBOL_GPL(pnx4008_dma_pack_config);
-
-int pnx4008_dma_parse_config(unsigned long cfg,
-			     struct pnx4008_dma_ch_config * ch_cfg)
-{
-	int err = 0;
-
-	if (!ch_cfg) {
-		err = -EINVAL;
-		goto out;
-	}
-
-	cfg >>= 1;
-
-	ch_cfg->src_per = cfg & 0x1f;
-	cfg >>= 5;
-
-	ch_cfg->dest_per = cfg & 0x1f;
-	cfg >>= 5;
-
-	switch (cfg & 7) {
-	case 0:
-		ch_cfg->flow_cntrl = FC_MEM2MEM_DMA;
-		break;
-	case 1:
-		ch_cfg->flow_cntrl = FC_MEM2PER_DMA;
-		break;
-	case 2:
-		ch_cfg->flow_cntrl = FC_PER2MEM_DMA;
-		break;
-	case 3:
-		ch_cfg->flow_cntrl = FC_PER2PER_DMA;
-		break;
-	case 4:
-		ch_cfg->flow_cntrl = FC_PER2PER_DPER;
-		break;
-	case 5:
-		ch_cfg->flow_cntrl = FC_MEM2PER_PER;
-		break;
-	case 6:
-		ch_cfg->flow_cntrl = FC_PER2MEM_PER;
-		break;
-	case 7:
-		ch_cfg->flow_cntrl = FC_PER2PER_SPER;
-	}
-	cfg >>= 3;
-
-	ch_cfg->ie = cfg & 1;
-	cfg >>= 1;
-
-	ch_cfg->itc = cfg & 1;
-	cfg >>= 1;
-
-	ch_cfg->lock = cfg & 1;
-	cfg >>= 1;
-
-	ch_cfg->active = cfg & 1;
-	cfg >>= 1;
-
-	ch_cfg->halt = cfg & 1;
-
-out:
-	return err;
-}
-
-EXPORT_SYMBOL_GPL(pnx4008_dma_parse_config);
-
-void pnx4008_dma_split_head_entry(struct pnx4008_dma_config * config,
-				  struct pnx4008_dma_ch_ctrl * ctrl)
-{
-	int new_len = ctrl->tr_size, num_entries = 0;
-	int old_len = new_len;
-	int src_width, dest_width, count = 1;
-
-	switch (ctrl->swidth) {
-	case WIDTH_BYTE:
-		src_width = 1;
-		break;
-	case WIDTH_HWORD:
-		src_width = 2;
-		break;
-	case WIDTH_WORD:
-		src_width = 4;
-		break;
-	default:
-		return;
-	}
-
-	switch (ctrl->dwidth) {
-	case WIDTH_BYTE:
-		dest_width = 1;
-		break;
-	case WIDTH_HWORD:
-		dest_width = 2;
-		break;
-	case WIDTH_WORD:
-		dest_width = 4;
-		break;
-	default:
-		return;
-	}
-
-	while (new_len > 0x7FF) {
-		num_entries++;
-		new_len = (ctrl->tr_size + num_entries) / (num_entries + 1);
-	}
-	if (num_entries != 0) {
-		struct pnx4008_dma_ll *ll = NULL;
-		config->ch_ctrl &= ~0x7ff;
-		config->ch_ctrl |= new_len;
-		if (!config->is_ll) {
-			config->is_ll = 1;
-			while (num_entries) {
-				if (!ll) {
-					config->ll =
-					    pnx4008_alloc_ll_entry(&config->
-								   ll_dma);
-					ll = config->ll;
-				} else {
-					ll->next =
-					    pnx4008_alloc_ll_entry(&ll->
-								   next_dma);
-					ll = ll->next;
-				}
-
-				if (ctrl->si)
-					ll->src_addr =
-					    config->src_addr +
-					    src_width * new_len * count;
-				else
-					ll->src_addr = config->src_addr;
-				if (ctrl->di)
-					ll->dest_addr =
-					    config->dest_addr +
-					    dest_width * new_len * count;
-				else
-					ll->dest_addr = config->dest_addr;
-				ll->ch_ctrl = config->ch_ctrl & 0x7fffffff;
-				ll->next_dma = 0;
-				ll->next = NULL;
-				num_entries--;
-				count++;
-			}
-		} else {
-			struct pnx4008_dma_ll *ll_old = config->ll;
-			unsigned long ll_dma_old = config->ll_dma;
-			while (num_entries) {
-				if (!ll) {
-					config->ll =
-					    pnx4008_alloc_ll_entry(&config->
-								   ll_dma);
-					ll = config->ll;
-				} else {
-					ll->next =
-					    pnx4008_alloc_ll_entry(&ll->
-								   next_dma);
-					ll = ll->next;
-				}
-
-				if (ctrl->si)
-					ll->src_addr =
-					    config->src_addr +
-					    src_width * new_len * count;
-				else
-					ll->src_addr = config->src_addr;
-				if (ctrl->di)
-					ll->dest_addr =
-					    config->dest_addr +
-					    dest_width * new_len * count;
-				else
-					ll->dest_addr = config->dest_addr;
-				ll->ch_ctrl = config->ch_ctrl & 0x7fffffff;
-				ll->next_dma = 0;
-				ll->next = NULL;
-				num_entries--;
-				count++;
-			}
-			ll->next_dma = ll_dma_old;
-			ll->next = ll_old;
-		}
-		/* adjust last length/tc */
-		ll->ch_ctrl = config->ch_ctrl & (~0x7ff);
-		ll->ch_ctrl |= old_len - new_len * (count - 1);
-		config->ch_ctrl &= 0x7fffffff;
-	}
-}
-
-EXPORT_SYMBOL_GPL(pnx4008_dma_split_head_entry);
-
-void pnx4008_dma_split_ll_entry(struct pnx4008_dma_ll * cur_ll,
-				struct pnx4008_dma_ch_ctrl * ctrl)
-{
-	int new_len = ctrl->tr_size, num_entries = 0;
-	int old_len = new_len;
-	int src_width, dest_width, count = 1;
-
-	switch (ctrl->swidth) {
-	case WIDTH_BYTE:
-		src_width = 1;
-		break;
-	case WIDTH_HWORD:
-		src_width = 2;
-		break;
-	case WIDTH_WORD:
-		src_width = 4;
-		break;
-	default:
-		return;
-	}
-
-	switch (ctrl->dwidth) {
-	case WIDTH_BYTE:
-		dest_width = 1;
-		break;
-	case WIDTH_HWORD:
-		dest_width = 2;
-		break;
-	case WIDTH_WORD:
-		dest_width = 4;
-		break;
-	default:
-		return;
-	}
-
-	while (new_len > 0x7FF) {
-		num_entries++;
-		new_len = (ctrl->tr_size + num_entries) / (num_entries + 1);
-	}
-	if (num_entries != 0) {
-		struct pnx4008_dma_ll *ll = NULL;
-		cur_ll->ch_ctrl &= ~0x7ff;
-		cur_ll->ch_ctrl |= new_len;
-		if (!cur_ll->next) {
-			while (num_entries) {
-				if (!ll) {
-					cur_ll->next =
-					    pnx4008_alloc_ll_entry(&cur_ll->
-								   next_dma);
-					ll = cur_ll->next;
-				} else {
-					ll->next =
-					    pnx4008_alloc_ll_entry(&ll->
-								   next_dma);
-					ll = ll->next;
-				}
-
-				if (ctrl->si)
-					ll->src_addr =
-					    cur_ll->src_addr +
-					    src_width * new_len * count;
-				else
-					ll->src_addr = cur_ll->src_addr;
-				if (ctrl->di)
-					ll->dest_addr =
-					    cur_ll->dest_addr +
-					    dest_width * new_len * count;
-				else
-					ll->dest_addr = cur_ll->dest_addr;
-				ll->ch_ctrl = cur_ll->ch_ctrl & 0x7fffffff;
-				ll->next_dma = 0;
-				ll->next = NULL;
-				num_entries--;
-				count++;
-			}
-		} else {
-			struct pnx4008_dma_ll *ll_old = cur_ll->next;
-			unsigned long ll_dma_old = cur_ll->next_dma;
-			while (num_entries) {
-				if (!ll) {
-					cur_ll->next =
-					    pnx4008_alloc_ll_entry(&cur_ll->
-								   next_dma);
-					ll = cur_ll->next;
-				} else {
-					ll->next =
-					    pnx4008_alloc_ll_entry(&ll->
-								   next_dma);
-					ll = ll->next;
-				}
-
-				if (ctrl->si)
-					ll->src_addr =
-					    cur_ll->src_addr +
-					    src_width * new_len * count;
-				else
-					ll->src_addr = cur_ll->src_addr;
-				if (ctrl->di)
-					ll->dest_addr =
-					    cur_ll->dest_addr +
-					    dest_width * new_len * count;
-				else
-					ll->dest_addr = cur_ll->dest_addr;
-				ll->ch_ctrl = cur_ll->ch_ctrl & 0x7fffffff;
-				ll->next_dma = 0;
-				ll->next = NULL;
-				num_entries--;
-				count++;
-			}
-
-			ll->next_dma = ll_dma_old;
-			ll->next = ll_old;
-		}
-		/* adjust last length/tc */
-		ll->ch_ctrl = cur_ll->ch_ctrl & (~0x7ff);
-		ll->ch_ctrl |= old_len - new_len * (count - 1);
-		cur_ll->ch_ctrl &= 0x7fffffff;
-	}
-}
-
-EXPORT_SYMBOL_GPL(pnx4008_dma_split_ll_entry);
-
-int pnx4008_config_channel(int ch, struct pnx4008_dma_config * config)
-{
-	if (!VALID_CHANNEL(ch) || !dma_channels[ch].name)
-		return -EINVAL;
-
-	pnx4008_dma_lock();
-	__raw_writel(config->src_addr, DMAC_Cx_SRC_ADDR(ch));
-	__raw_writel(config->dest_addr, DMAC_Cx_DEST_ADDR(ch));
-
-	if (config->is_ll)
-		__raw_writel(config->ll_dma, DMAC_Cx_LLI(ch));
-	else
-		__raw_writel(0, DMAC_Cx_LLI(ch));
-
-	__raw_writel(config->ch_ctrl, DMAC_Cx_CONTROL(ch));
-	__raw_writel(config->ch_cfg, DMAC_Cx_CONFIG(ch));
-	pnx4008_dma_unlock();
-
-	return 0;
-
-}
-
-EXPORT_SYMBOL_GPL(pnx4008_config_channel);
-
-int pnx4008_channel_get_config(int ch, struct pnx4008_dma_config * config)
-{
-	if (!VALID_CHANNEL(ch) || !dma_channels[ch].name || !config)
-		return -EINVAL;
-
-	pnx4008_dma_lock();
-	config->ch_cfg = __raw_readl(DMAC_Cx_CONFIG(ch));
-	config->ch_ctrl = __raw_readl(DMAC_Cx_CONTROL(ch));
-
-	config->ll_dma = __raw_readl(DMAC_Cx_LLI(ch));
-	config->is_ll = config->ll_dma ? 1 : 0;
-
-	config->src_addr = __raw_readl(DMAC_Cx_SRC_ADDR(ch));
-	config->dest_addr = __raw_readl(DMAC_Cx_DEST_ADDR(ch));
-	pnx4008_dma_unlock();
-
-	return 0;
-}
-
-EXPORT_SYMBOL_GPL(pnx4008_channel_get_config);
-
-int pnx4008_dma_ch_enable(int ch)
-{
-	unsigned long ch_cfg;
-
-	if (!VALID_CHANNEL(ch) || !dma_channels[ch].name)
-		return -EINVAL;
-
-	pnx4008_dma_lock();
-	ch_cfg = __raw_readl(DMAC_Cx_CONFIG(ch));
-	ch_cfg |= 1;
-	__raw_writel(ch_cfg, DMAC_Cx_CONFIG(ch));
-	pnx4008_dma_unlock();
-
-	return 0;
-}
-
-EXPORT_SYMBOL_GPL(pnx4008_dma_ch_enable);
-
-int pnx4008_dma_ch_disable(int ch)
-{
-	unsigned long ch_cfg;
-
-	if (!VALID_CHANNEL(ch) || !dma_channels[ch].name)
-		return -EINVAL;
-
-	pnx4008_dma_lock();
-	ch_cfg = __raw_readl(DMAC_Cx_CONFIG(ch));
-	ch_cfg &= ~1;
-	__raw_writel(ch_cfg, DMAC_Cx_CONFIG(ch));
-	pnx4008_dma_unlock();
-
-	return 0;
-}
-
-EXPORT_SYMBOL_GPL(pnx4008_dma_ch_disable);
-
-int pnx4008_dma_ch_enabled(int ch)
-{
-	unsigned long ch_cfg;
-
-	if (!VALID_CHANNEL(ch) || !dma_channels[ch].name)
-		return -EINVAL;
-
-	pnx4008_dma_lock();
-	ch_cfg = __raw_readl(DMAC_Cx_CONFIG(ch));
-	pnx4008_dma_unlock();
-
-	return ch_cfg & 1;
-}
-
-EXPORT_SYMBOL_GPL(pnx4008_dma_ch_enabled);
-
-static irqreturn_t dma_irq_handler(int irq, void *dev_id)
-{
-	int i;
-	unsigned long dint = __raw_readl(DMAC_INT_STAT);
-	unsigned long tcint = __raw_readl(DMAC_INT_TC_STAT);
-	unsigned long eint = __raw_readl(DMAC_INT_ERR_STAT);
-	unsigned long i_bit;
-
-	for (i = MAX_DMA_CHANNELS - 1; i >= 0; i--) {
-		i_bit = 1 << i;
-		if (dint & i_bit) {
-			struct dma_channel *channel = &dma_channels[i];
-
-			if (channel->name && channel->irq_handler) {
-				int cause = 0;
-
-				if (eint & i_bit)
-					cause |= DMA_ERR_INT;
-				if (tcint & i_bit)
-					cause |= DMA_TC_INT;
-				channel->irq_handler(i, cause, channel->data);
-			} else {
-				/*
-				 * IRQ for an unregistered DMA channel
-				 */
-				printk(KERN_WARNING
-				       "spurious IRQ for DMA channel %d\n", i);
-			}
-			if (tcint & i_bit)
-				__raw_writel(i_bit, DMAC_INT_TC_CLEAR);
-			if (eint & i_bit)
-				__raw_writel(i_bit, DMAC_INT_ERR_CLEAR);
-		}
-	}
-	return IRQ_HANDLED;
-}
-
-static int __init pnx4008_dma_init(void)
-{
-	int ret, i;
-
-	ret = request_irq(DMA_INT, dma_irq_handler, 0, "DMA", NULL);
-	if (ret) {
-		printk(KERN_CRIT "Wow!  Can't register IRQ for DMA\n");
-		goto out;
-	}
-
-	ll_pool.count = 0x4000 / sizeof(struct pnx4008_dma_ll);
-	ll_pool.cur = ll_pool.vaddr =
-	    dma_alloc_coherent(NULL, ll_pool.count * sizeof(struct pnx4008_dma_ll),
-			       &ll_pool.dma_addr, GFP_KERNEL);
-
-	if (!ll_pool.vaddr) {
-		ret = -ENOMEM;
-		free_irq(DMA_INT, NULL);
-		goto out;
-	}
-
-	for (i = 0; i < ll_pool.count - 1; i++) {
-		void **addr = ll_pool.vaddr + i * sizeof(struct pnx4008_dma_ll);
-		*addr = (void *)addr + sizeof(struct pnx4008_dma_ll);
-	}
-	*(long *)(ll_pool.vaddr +
-		  (ll_pool.count - 1) * sizeof(struct pnx4008_dma_ll)) =
-	    (long)ll_pool.vaddr;
-
-	__raw_writel(1, DMAC_CONFIG);
-
-out:
-	return ret;
-}
-arch_initcall(pnx4008_dma_init);
diff --git a/arch/arm/mach-pnx4008/gpio.c b/arch/arm/mach-pnx4008/gpio.c
deleted file mode 100644
index d3e71d3..0000000
--- a/arch/arm/mach-pnx4008/gpio.c
+++ /dev/null
@@ -1,328 +0,0 @@
-/*
- * arch/arm/mach-pnx4008/gpio.c
- *
- * PNX4008 GPIO driver
- *
- * Author: Dmitry Chigirev <source@mvista.com>
- *
- * Based on reference code by Iwo Mergler and Z.Tabaaloute from Philips:
- * Copyright (c) 2005 Koninklijke Philips Electronics N.V.
- *
- * 2005 (c) MontaVista Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/io.h>
-#include <mach/hardware.h>
-#include <mach/platform.h>
-#include <mach/gpio-pnx4008.h>
-
-/* register definitions */
-#define PIO_VA_BASE	IO_ADDRESS(PNX4008_PIO_BASE)
-
-#define PIO_INP_STATE	(0x00U)
-#define PIO_OUTP_SET	(0x04U)
-#define PIO_OUTP_CLR	(0x08U)
-#define PIO_OUTP_STATE	(0x0CU)
-#define PIO_DRV_SET	(0x10U)
-#define PIO_DRV_CLR	(0x14U)
-#define PIO_DRV_STATE	(0x18U)
-#define PIO_SDINP_STATE	(0x1CU)
-#define PIO_SDOUTP_SET	(0x20U)
-#define PIO_SDOUTP_CLR	(0x24U)
-#define PIO_MUX_SET	(0x28U)
-#define PIO_MUX_CLR	(0x2CU)
-#define PIO_MUX_STATE	(0x30U)
-
-static inline void gpio_lock(void)
-{
-	local_irq_disable();
-}
-
-static inline void gpio_unlock(void)
-{
-	local_irq_enable();
-}
-
-/* Inline functions */
-static inline int gpio_read_bit(u32 reg, int gpio)
-{
-	u32 bit, val;
-	int ret = -EFAULT;
-
-	if (gpio < 0)
-		goto out;
-
-	bit = GPIO_BIT(gpio);
-	if (bit) {
-		val = __raw_readl(PIO_VA_BASE + reg);
-		ret = (val & bit) ? 1 : 0;
-	}
-out:
-	return ret;
-}
-
-static inline int gpio_set_bit(u32 reg, int gpio)
-{
-	u32 bit, val;
-	int ret = -EFAULT;
-
-	if (gpio < 0)
-		goto out;
-
-	bit = GPIO_BIT(gpio);
-	if (bit) {
-		val = __raw_readl(PIO_VA_BASE + reg);
-		val |= bit;
-		__raw_writel(val, PIO_VA_BASE + reg);
-		ret = 0;
-	}
-out:
-	return ret;
-}
-
-/* Very simple access control, bitmap for allocated/free */
-static unsigned long access_map[4];
-#define INP_INDEX	0
-#define OUTP_INDEX	1
-#define GPIO_INDEX	2
-#define MUX_INDEX	3
-
-/*GPIO to Input Mapping */
-static short gpio_to_inp_map[32] = {
-	-1, -1, -1, -1, -1, -1, -1, -1,
-	-1, -1, -1, -1, -1, -1, -1, -1,
-	-1, -1, -1, -1, -1, -1, -1, -1,
-	-1, 10, 11, 12, 13, 14, 24, -1
-};
-
-/*GPIO to Mux Mapping */
-static short gpio_to_mux_map[32] = {
-	-1, -1, -1, -1, -1, -1, -1, -1,
-	-1, -1, -1, -1, -1, -1, -1, -1,
-	-1, -1, -1, -1, -1, -1, -1, -1,
-	-1, -1, -1, 0, 1, 4, 5, -1
-};
-
-/*Output to Mux Mapping */
-static short outp_to_mux_map[32] = {
-	-1, -1, -1, 6, -1, -1, -1, -1,
-	-1, -1, -1, -1, -1, -1, -1, -1,
-	-1, -1, -1, -1, -1, 2, -1, -1,
-	-1, -1, -1, -1, -1, -1, -1, -1
-};
-
-int pnx4008_gpio_register_pin(unsigned short pin)
-{
-	unsigned long bit = GPIO_BIT(pin);
-	int ret = -EBUSY;	/* Already in use */
-
-	gpio_lock();
-
-	if (GPIO_ISBID(pin)) {
-		if (access_map[GPIO_INDEX] & bit)
-			goto out;
-		access_map[GPIO_INDEX] |= bit;
-
-	} else if (GPIO_ISRAM(pin)) {
-		if (access_map[GPIO_INDEX] & bit)
-			goto out;
-		access_map[GPIO_INDEX] |= bit;
-
-	} else if (GPIO_ISMUX(pin)) {
-		if (access_map[MUX_INDEX] & bit)
-			goto out;
-		access_map[MUX_INDEX] |= bit;
-
-	} else if (GPIO_ISOUT(pin)) {
-		if (access_map[OUTP_INDEX] & bit)
-			goto out;
-		access_map[OUTP_INDEX] |= bit;
-
-	} else if (GPIO_ISIN(pin)) {
-		if (access_map[INP_INDEX] & bit)
-			goto out;
-		access_map[INP_INDEX] |= bit;
-	} else
-		goto out;
-	ret = 0;
-
-out:
-	gpio_unlock();
-	return ret;
-}
-
-EXPORT_SYMBOL(pnx4008_gpio_register_pin);
-
-int pnx4008_gpio_unregister_pin(unsigned short pin)
-{
-	unsigned long bit = GPIO_BIT(pin);
-	int ret = -EFAULT;	/* Not registered */
-
-	gpio_lock();
-
-	if (GPIO_ISBID(pin)) {
-		if (~access_map[GPIO_INDEX] & bit)
-			goto out;
-		access_map[GPIO_INDEX] &= ~bit;
-	} else if (GPIO_ISRAM(pin)) {
-		if (~access_map[GPIO_INDEX] & bit)
-			goto out;
-		access_map[GPIO_INDEX] &= ~bit;
-	} else if (GPIO_ISMUX(pin)) {
-		if (~access_map[MUX_INDEX] & bit)
-			goto out;
-		access_map[MUX_INDEX] &= ~bit;
-	} else if (GPIO_ISOUT(pin)) {
-		if (~access_map[OUTP_INDEX] & bit)
-			goto out;
-		access_map[OUTP_INDEX] &= ~bit;
-	} else if (GPIO_ISIN(pin)) {
-		if (~access_map[INP_INDEX] & bit)
-			goto out;
-		access_map[INP_INDEX] &= ~bit;
-	} else
-		goto out;
-	ret = 0;
-
-out:
-	gpio_unlock();
-	return ret;
-}
-
-EXPORT_SYMBOL(pnx4008_gpio_unregister_pin);
-
-unsigned long pnx4008_gpio_read_pin(unsigned short pin)
-{
-	unsigned long ret = -EFAULT;
-	int gpio = GPIO_BIT_MASK(pin);
-	gpio_lock();
-	if (GPIO_ISOUT(pin)) {
-		ret = gpio_read_bit(PIO_OUTP_STATE, gpio);
-	} else if (GPIO_ISRAM(pin)) {
-		if (gpio_read_bit(PIO_DRV_STATE, gpio) == 0) {
-			ret = gpio_read_bit(PIO_SDINP_STATE, gpio);
-		}
-	} else if (GPIO_ISBID(pin)) {
-		ret = gpio_read_bit(PIO_DRV_STATE, gpio);
-		if (ret > 0)
-			ret = gpio_read_bit(PIO_OUTP_STATE, gpio);
-		else if (ret == 0)
-			ret =
-			    gpio_read_bit(PIO_INP_STATE, gpio_to_inp_map[gpio]);
-	} else if (GPIO_ISIN(pin)) {
-		ret = gpio_read_bit(PIO_INP_STATE, gpio);
-	}
-	gpio_unlock();
-	return ret;
-}
-
-EXPORT_SYMBOL(pnx4008_gpio_read_pin);
-
-/* Write Value to output */
-int pnx4008_gpio_write_pin(unsigned short pin, int output)
-{
-	int gpio = GPIO_BIT_MASK(pin);
-	int ret = -EFAULT;
-
-	gpio_lock();
-	if (GPIO_ISOUT(pin)) {
-		printk( "writing '%x' to '%x'\n",
-				gpio, output ? PIO_OUTP_SET : PIO_OUTP_CLR );
-		ret = gpio_set_bit(output ? PIO_OUTP_SET : PIO_OUTP_CLR, gpio);
-	} else if (GPIO_ISRAM(pin)) {
-		if (gpio_read_bit(PIO_DRV_STATE, gpio) > 0)
-			ret = gpio_set_bit(output ? PIO_SDOUTP_SET :
-					   PIO_SDOUTP_CLR, gpio);
-	} else if (GPIO_ISBID(pin)) {
-		if (gpio_read_bit(PIO_DRV_STATE, gpio) > 0)
-			ret = gpio_set_bit(output ? PIO_OUTP_SET :
-					   PIO_OUTP_CLR, gpio);
-	}
-	gpio_unlock();
-	return ret;
-}
-
-EXPORT_SYMBOL(pnx4008_gpio_write_pin);
-
-/* Value = 1 : Set GPIO pin as output */
-/* Value = 0 : Set GPIO pin as input */
-int pnx4008_gpio_set_pin_direction(unsigned short pin, int output)
-{
-	int gpio = GPIO_BIT_MASK(pin);
-	int ret = -EFAULT;
-
-	gpio_lock();
-	if (GPIO_ISBID(pin) || GPIO_ISRAM(pin)) {
-		ret = gpio_set_bit(output ? PIO_DRV_SET : PIO_DRV_CLR, gpio);
-	}
-	gpio_unlock();
-	return ret;
-}
-
-EXPORT_SYMBOL(pnx4008_gpio_set_pin_direction);
-
-/* Read GPIO pin direction: 0= pin used as input, 1= pin used as output*/
-int pnx4008_gpio_read_pin_direction(unsigned short pin)
-{
-	int gpio = GPIO_BIT_MASK(pin);
-	int ret = -EFAULT;
-
-	gpio_lock();
-	if (GPIO_ISBID(pin) || GPIO_ISRAM(pin)) {
-		ret = gpio_read_bit(PIO_DRV_STATE, gpio);
-	}
-	gpio_unlock();
-	return ret;
-}
-
-EXPORT_SYMBOL(pnx4008_gpio_read_pin_direction);
-
-/* Value = 1 : Set pin to muxed function  */
-/* Value = 0 : Set pin as GPIO */
-int pnx4008_gpio_set_pin_mux(unsigned short pin, int output)
-{
-	int gpio = GPIO_BIT_MASK(pin);
-	int ret = -EFAULT;
-
-	gpio_lock();
-	if (GPIO_ISBID(pin)) {
-		ret =
-		    gpio_set_bit(output ? PIO_MUX_SET : PIO_MUX_CLR,
-				 gpio_to_mux_map[gpio]);
-	} else if (GPIO_ISOUT(pin)) {
-		ret =
-		    gpio_set_bit(output ? PIO_MUX_SET : PIO_MUX_CLR,
-				 outp_to_mux_map[gpio]);
-	} else if (GPIO_ISMUX(pin)) {
-		ret = gpio_set_bit(output ? PIO_MUX_SET : PIO_MUX_CLR, gpio);
-	}
-	gpio_unlock();
-	return ret;
-}
-
-EXPORT_SYMBOL(pnx4008_gpio_set_pin_mux);
-
-/* Read pin mux function: 0= pin used as GPIO, 1= pin used for muxed function*/
-int pnx4008_gpio_read_pin_mux(unsigned short pin)
-{
-	int gpio = GPIO_BIT_MASK(pin);
-	int ret = -EFAULT;
-
-	gpio_lock();
-	if (GPIO_ISBID(pin)) {
-		ret = gpio_read_bit(PIO_MUX_STATE, gpio_to_mux_map[gpio]);
-	} else if (GPIO_ISOUT(pin)) {
-		ret = gpio_read_bit(PIO_MUX_STATE, outp_to_mux_map[gpio]);
-	} else if (GPIO_ISMUX(pin)) {
-		ret = gpio_read_bit(PIO_MUX_STATE, gpio);
-	}
-	gpio_unlock();
-	return ret;
-}
-
-EXPORT_SYMBOL(pnx4008_gpio_read_pin_mux);
diff --git a/arch/arm/mach-pnx4008/i2c.c b/arch/arm/mach-pnx4008/i2c.c
deleted file mode 100644
index 550cfc2..0000000
--- a/arch/arm/mach-pnx4008/i2c.c
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * I2C initialization for PNX4008.
- *
- * Author: Vitaly Wool <vitalywool@gmail.com>
- *
- * 2005-2006 (c) MontaVista Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-
-#include <linux/clk.h>
-#include <linux/i2c.h>
-#include <linux/i2c-pnx.h>
-#include <linux/platform_device.h>
-#include <linux/err.h>
-#include <mach/platform.h>
-#include <mach/irqs.h>
-
-static struct resource i2c0_resources[] = {
-	{
-		.start = PNX4008_I2C1_BASE,
-		.end = PNX4008_I2C1_BASE + SZ_4K - 1,
-		.flags = IORESOURCE_MEM,
-	}, {
-		.start = I2C_1_INT,
-		.end = I2C_1_INT,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-static struct resource i2c1_resources[] = {
-	{
-		.start = PNX4008_I2C2_BASE,
-		.end = PNX4008_I2C2_BASE + SZ_4K - 1,
-		.flags = IORESOURCE_MEM,
-	}, {
-		.start = I2C_2_INT,
-		.end = I2C_2_INT,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-static struct resource i2c2_resources[] = {
-	{
-		.start = PNX4008_USB_CONFIG_BASE + 0x300,
-		.end = PNX4008_USB_CONFIG_BASE + 0x300 + SZ_4K - 1,
-		.flags = IORESOURCE_MEM,
-	}, {
-		.start = USB_I2C_INT,
-		.end = USB_I2C_INT,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device i2c0_device = {
-	.name = "pnx-i2c.0",
-	.id = 0,
-	.resource = i2c0_resources,
-	.num_resources = ARRAY_SIZE(i2c0_resources),
-};
-
-static struct platform_device i2c1_device = {
-	.name = "pnx-i2c.1",
-	.id = 1,
-	.resource = i2c1_resources,
-	.num_resources = ARRAY_SIZE(i2c1_resources),
-};
-
-static struct platform_device i2c2_device = {
-	.name = "pnx-i2c.2",
-	.id = 2,
-	.resource = i2c2_resources,
-	.num_resources = ARRAY_SIZE(i2c2_resources),
-};
-
-static struct platform_device *devices[] __initdata = {
-	&i2c0_device,
-	&i2c1_device,
-	&i2c2_device,
-};
-
-void __init pnx4008_register_i2c_devices(void)
-{
-	platform_add_devices(devices, ARRAY_SIZE(devices));
-}
diff --git a/arch/arm/mach-pnx4008/include/mach/clock.h b/arch/arm/mach-pnx4008/include/mach/clock.h
deleted file mode 100644
index 8d2a5ef..0000000
--- a/arch/arm/mach-pnx4008/include/mach/clock.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * arch/arm/mach-pnx4008/include/mach/clock.h
- *
- * Clock control driver for PNX4008 - header file
- *
- * Authors: Vitaly Wool, Dmitry Chigirev <source@mvista.com>
- *
- * 2005 (c) MontaVista Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-#ifndef __PNX4008_CLOCK_H__
-#define __PNX4008_CLOCK_H__
-
-struct module;
-struct clk;
-
-#define PWRMAN_VA_BASE		IO_ADDRESS(PNX4008_PWRMAN_BASE)
-#define HCLKDIVCTRL_REG		(PWRMAN_VA_BASE + 0x40)
-#define PWRCTRL_REG		(PWRMAN_VA_BASE + 0x44)
-#define PLLCTRL_REG		(PWRMAN_VA_BASE + 0x48)
-#define OSC13CTRL_REG		(PWRMAN_VA_BASE + 0x4c)
-#define SYSCLKCTRL_REG		(PWRMAN_VA_BASE + 0x50)
-#define HCLKPLLCTRL_REG		(PWRMAN_VA_BASE + 0x58)
-#define USBCTRL_REG		(PWRMAN_VA_BASE + 0x64)
-#define SDRAMCLKCTRL_REG	(PWRMAN_VA_BASE + 0x68)
-#define MSCTRL_REG		(PWRMAN_VA_BASE + 0x80)
-#define BTCLKCTRL		(PWRMAN_VA_BASE + 0x84)
-#define DUMCLKCTRL_REG		(PWRMAN_VA_BASE + 0x90)
-#define I2CCLKCTRL_REG		(PWRMAN_VA_BASE + 0xac)
-#define KEYCLKCTRL_REG		(PWRMAN_VA_BASE + 0xb0)
-#define TSCLKCTRL_REG		(PWRMAN_VA_BASE + 0xb4)
-#define PWMCLKCTRL_REG		(PWRMAN_VA_BASE + 0xb8)
-#define TIMCLKCTRL_REG		(PWRMAN_VA_BASE + 0xbc)
-#define SPICTRL_REG		(PWRMAN_VA_BASE + 0xc4)
-#define FLASHCLKCTRL_REG	(PWRMAN_VA_BASE + 0xc8)
-#define UART3CLK_REG		(PWRMAN_VA_BASE + 0xd0)
-#define UARTCLKCTRL_REG		(PWRMAN_VA_BASE + 0xe4)
-#define DMACLKCTRL_REG		(PWRMAN_VA_BASE + 0xe8)
-#define AUTOCLK_CTRL		(PWRMAN_VA_BASE + 0xec)
-#define JPEGCLKCTRL_REG		(PWRMAN_VA_BASE + 0xfc)
-
-#define AUDIOCONFIG_VA_BASE	IO_ADDRESS(PNX4008_AUDIOCONFIG_BASE)
-#define DSPPLLCTRL_REG		(AUDIOCONFIG_VA_BASE + 0x60)
-#define DSPCLKCTRL_REG		(AUDIOCONFIG_VA_BASE + 0x64)
-#define AUDIOCLKCTRL_REG	(AUDIOCONFIG_VA_BASE + 0x68)
-#define AUDIOPLLCTRL_REG	(AUDIOCONFIG_VA_BASE + 0x6C)
-
-#define USB_OTG_CLKCTRL_REG	IO_ADDRESS(PNX4008_USB_CONFIG_BASE + 0xff4)
-
-#define VFP9CLKCTRL_REG		IO_ADDRESS(PNX4008_DEBUG_BASE)
-
-#define CLK_RATE_13MHZ 13000
-#define CLK_RATE_1MHZ 1000
-#define CLK_RATE_208MHZ 208000
-#define CLK_RATE_48MHZ 48000
-#define CLK_RATE_32KHZ 32
-
-#define PNX4008_UART_CLK CLK_RATE_13MHZ * 1000 /* in MHz */
-
-#endif
diff --git a/arch/arm/mach-pnx4008/include/mach/debug-macro.S b/arch/arm/mach-pnx4008/include/mach/debug-macro.S
deleted file mode 100644
index 469d60d..0000000
--- a/arch/arm/mach-pnx4008/include/mach/debug-macro.S
+++ /dev/null
@@ -1,21 +0,0 @@
-/* arch/arm/mach-pnx4008/include/mach/debug-macro.S
- *
- * Debugging macro include header
- *
- *  Copyright (C) 1994-1999 Russell King
- *  Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
-*/
-
-		.macro	addruart, rp, rv, tmp
-		mov	\rp, #0x00090000
-		add	\rv, \rp, #0xf4000000	@ virtual
-		add	\rp, \rp, #0x40000000	@ physical
-		.endm
-
-#define UART_SHIFT	2
-#include <asm/hardware/debug-8250.S>
diff --git a/arch/arm/mach-pnx4008/include/mach/dma.h b/arch/arm/mach-pnx4008/include/mach/dma.h
deleted file mode 100644
index f094bf8..0000000
--- a/arch/arm/mach-pnx4008/include/mach/dma.h
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- *  arch/arm/mach-pnx4008/include/mach/dma.h
- *
- *  PNX4008 DMA header file
- *
- *  Author:	Vitaly Wool
- *  Copyright:	MontaVista Software Inc. (c) 2005
- *
- *  This program is free software; you can 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_DMA_H
-#define __ASM_ARCH_DMA_H
-
-#include "platform.h"
-
-#define MAX_DMA_CHANNELS	8
-
-#define DMAC_BASE		IO_ADDRESS(PNX4008_DMA_CONFIG_BASE)
-#define DMAC_INT_STAT		(DMAC_BASE + 0x0000)
-#define DMAC_INT_TC_STAT	(DMAC_BASE + 0x0004)
-#define DMAC_INT_TC_CLEAR	(DMAC_BASE + 0x0008)
-#define DMAC_INT_ERR_STAT	(DMAC_BASE + 0x000c)
-#define DMAC_INT_ERR_CLEAR	(DMAC_BASE + 0x0010)
-#define DMAC_SOFT_SREQ		(DMAC_BASE + 0x0024)
-#define DMAC_CONFIG		(DMAC_BASE + 0x0030)
-#define DMAC_Cx_SRC_ADDR(c)	(DMAC_BASE + 0x0100 + (c) * 0x20)
-#define DMAC_Cx_DEST_ADDR(c)	(DMAC_BASE + 0x0104 + (c) * 0x20)
-#define DMAC_Cx_LLI(c)		(DMAC_BASE + 0x0108 + (c) * 0x20)
-#define DMAC_Cx_CONTROL(c)	(DMAC_BASE + 0x010c + (c) * 0x20)
-#define DMAC_Cx_CONFIG(c)	(DMAC_BASE + 0x0110 + (c) * 0x20)
-
-enum {
-	WIDTH_BYTE = 0,
-	WIDTH_HWORD,
-	WIDTH_WORD
-};
-
-enum {
-	FC_MEM2MEM_DMA,
-	FC_MEM2PER_DMA,
-	FC_PER2MEM_DMA,
-	FC_PER2PER_DMA,
-	FC_PER2PER_DPER,
-	FC_MEM2PER_PER,
-	FC_PER2MEM_PER,
-	FC_PER2PER_SPER
-};
-
-enum {
-	DMA_INT_UNKNOWN = 0,
-	DMA_ERR_INT = 1,
-	DMA_TC_INT = 2,
-};
-
-enum {
-	DMA_BUFFER_ALLOCATED = 1,
-	DMA_HAS_LL = 2,
-};
-
-enum {
-	PER_CAM_DMA_1 = 0,
-	PER_NDF_FLASH = 1,
-	PER_MBX_SLAVE_FIFO = 2,
-	PER_SPI2_REC_XMIT = 3,
-	PER_MS_SD_RX_XMIT = 4,
-	PER_HS_UART_1_XMIT = 5,
-	PER_HS_UART_1_RX = 6,
-	PER_HS_UART_2_XMIT = 7,
-	PER_HS_UART_2_RX = 8,
-	PER_HS_UART_7_XMIT = 9,
-	PER_HS_UART_7_RX = 10,
-	PER_SPI1_REC_XMIT = 11,
-	PER_MLC_NDF_SREC = 12,
-	PER_CAM_DMA_2 = 13,
-	PER_PRNG_INFIFO = 14,
-	PER_PRNG_OUTFIFO = 15,
-};
-
-struct pnx4008_dma_ch_ctrl {
-	int tc_mask;
-	int cacheable;
-	int bufferable;
-	int priv_mode;
-	int di;
-	int si;
-	int dest_ahb1;
-	int src_ahb1;
-	int dwidth;
-	int swidth;
-	int dbsize;
-	int sbsize;
-	int tr_size;
-};
-
-struct pnx4008_dma_ch_config {
-	int halt;
-	int active;
-	int lock;
-	int itc;
-	int ie;
-	int flow_cntrl;
-	int dest_per;
-	int src_per;
-};
-
-struct pnx4008_dma_ll {
-	unsigned long src_addr;
-	unsigned long dest_addr;
-	u32 next_dma;
-	unsigned long ch_ctrl;
-	struct pnx4008_dma_ll *next;
-	int flags;
-	void *alloc_data;
-	int (*free) (void *);
-};
-
-struct pnx4008_dma_config {
-	int is_ll;
-	unsigned long src_addr;
-	unsigned long dest_addr;
-	unsigned long ch_ctrl;
-	unsigned long ch_cfg;
-	struct pnx4008_dma_ll *ll;
-	u32 ll_dma;
-	int flags;
-	void *alloc_data;
-	int (*free) (void *);
-};
-
-extern struct pnx4008_dma_ll *pnx4008_alloc_ll_entry(dma_addr_t *);
-extern void pnx4008_free_ll_entry(struct pnx4008_dma_ll *, dma_addr_t);
-extern void pnx4008_free_ll(u32 ll_dma, struct pnx4008_dma_ll *);
-
-extern int pnx4008_request_channel(char *, int,
-				   void (*)(int, int, void *),
-				   void *);
-extern void pnx4008_free_channel(int);
-extern int pnx4008_config_dma(int, int, int);
-extern int pnx4008_dma_pack_control(const struct pnx4008_dma_ch_ctrl *,
-				    unsigned long *);
-extern int pnx4008_dma_parse_control(unsigned long,
-				     struct pnx4008_dma_ch_ctrl *);
-extern int pnx4008_dma_pack_config(const struct pnx4008_dma_ch_config *,
-				   unsigned long *);
-extern int pnx4008_dma_parse_config(unsigned long,
-				    struct pnx4008_dma_ch_config *);
-extern int pnx4008_config_channel(int, struct pnx4008_dma_config *);
-extern int pnx4008_channel_get_config(int, struct pnx4008_dma_config *);
-extern int pnx4008_dma_ch_enable(int);
-extern int pnx4008_dma_ch_disable(int);
-extern int pnx4008_dma_ch_enabled(int);
-extern void pnx4008_dma_split_head_entry(struct pnx4008_dma_config *,
-					 struct pnx4008_dma_ch_ctrl *);
-extern void pnx4008_dma_split_ll_entry(struct pnx4008_dma_ll *,
-				       struct pnx4008_dma_ch_ctrl *);
-
-#endif				/* _ASM_ARCH_DMA_H */
diff --git a/arch/arm/mach-pnx4008/include/mach/entry-macro.S b/arch/arm/mach-pnx4008/include/mach/entry-macro.S
deleted file mode 100644
index 77a5558..0000000
--- a/arch/arm/mach-pnx4008/include/mach/entry-macro.S
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * arch/arm/mach-pnx4008/include/mach/entry-macro.S
- *
- * Low-level IRQ helper macros for PNX4008-based platforms
- *
- * 2005-2006 (c) MontaVista Software, Inc.
- * Author: Vitaly Wool <vwool@ru.mvista.com>
- * This file is licensed under  the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include "platform.h"
-
-#define IO_BASE         0xF0000000
-#define IO_ADDRESS(x)  (((((x) & 0xff000000) >> 4) | ((x) & 0xfffff)) | IO_BASE)
-
-#define INTRC_MASK			0x00
-#define INTRC_RAW_STAT			0x04
-#define INTRC_STAT			0x08
-#define INTRC_POLAR			0x0C
-#define INTRC_ACT_TYPE			0x10
-#define INTRC_TYPE			0x14
-
-#define SIC1_BASE_INT   32
-#define SIC2_BASE_INT   64
-
-		.macro  get_irqnr_preamble, base, tmp
-		.endm
-
-		.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
-/* decode the MIC interrupt numbers */
-		ldr	\base, =IO_ADDRESS(PNX4008_INTCTRLMIC_BASE)
-		ldr	\irqstat, [\base, #INTRC_STAT]
-
-		cmp	\irqstat,#1<<16
-		movhs	\irqnr,#16
-		movlo	\irqnr,#0
-		movhs	\irqstat,\irqstat,lsr#16
-		cmp	\irqstat,#1<<8
-		addhs	\irqnr,\irqnr,#8
-		movhs	\irqstat,\irqstat,lsr#8
-		cmp	\irqstat,#1<<4
-		addhs	\irqnr,\irqnr,#4
-		movhs	\irqstat,\irqstat,lsr#4
-		cmp	\irqstat,#1<<2
-		addhs	\irqnr,\irqnr,#2
-		movhs	\irqstat,\irqstat,lsr#2
-		cmp	\irqstat,#1<<1
-		addhs	\irqnr,\irqnr,#1
-
-/* was there an interrupt ? if not then drop out with EQ status */
-		teq	\irqstat,#0
-		beq	1003f
-
-/* and now check for extended IRQ reasons */
-		cmp	\irqnr,#1
-		bls	1003f
-		cmp	\irqnr,#30
-		blo	1002f
-
-/* IRQ 31,30  : High priority cascade IRQ handle */
-/* read the correct SIC */
-/* decoding status after compare : eq is 30 (SIC1) , ne is 31 (SIC2) */
-/* set the base IRQ number */
-		ldreq	\base, =IO_ADDRESS(PNX4008_INTCTRLSIC1_BASE)
-		moveq  \irqnr,#SIC1_BASE_INT
-		ldrne	\base, =IO_ADDRESS(PNX4008_INTCTRLSIC2_BASE)
-		movne   \irqnr,#SIC2_BASE_INT
-		ldr	\irqstat, [\base, #INTRC_STAT]
-		ldr	\tmp,	  [\base, #INTRC_TYPE]
-/* and with inverted mask : low priority interrupts  */
-		and	\irqstat,\irqstat,\tmp
-		b	1004f
-
-1003:
-/* IRQ 1,0  : Low priority cascade IRQ handle */
-/* read the correct SIC */
-/* decoding status after compare : eq is 1 (SIC2) , ne is 0 (SIC1)*/
-/* read the correct SIC */
-/* set the base IRQ number  */
-		ldrne	\base, =IO_ADDRESS(PNX4008_INTCTRLSIC1_BASE)
-		movne   \irqnr,#SIC1_BASE_INT
-		ldreq	\base, =IO_ADDRESS(PNX4008_INTCTRLSIC2_BASE)
-		moveq   \irqnr,#SIC2_BASE_INT
-		ldr	\irqstat, [\base, #INTRC_STAT]
-		ldr	\tmp,	  [\base, #INTRC_TYPE]
-/* and with inverted mask : low priority interrupts  */
-		bic	\irqstat,\irqstat,\tmp
-
-1004:
-
-		cmp	\irqstat,#1<<16
-		addhs	\irqnr,\irqnr,#16
-		movhs	\irqstat,\irqstat,lsr#16
-		cmp	\irqstat,#1<<8
-		addhs	\irqnr,\irqnr,#8
-		movhs	\irqstat,\irqstat,lsr#8
-		cmp	\irqstat,#1<<4
-		addhs	\irqnr,\irqnr,#4
-		movhs	\irqstat,\irqstat,lsr#4
-		cmp	\irqstat,#1<<2
-		addhs	\irqnr,\irqnr,#2
-		movhs	\irqstat,\irqstat,lsr#2
-		cmp	\irqstat,#1<<1
-		addhs	\irqnr,\irqnr,#1
-
-
-/* is irqstat not zero */
-
-1002:
-/* we assert that irqstat is not equal to zero and return ne status if true*/
-		teq	\irqstat,#0
-1003:
-		.endm
-
diff --git a/arch/arm/mach-pnx4008/include/mach/gpio-pnx4008.h b/arch/arm/mach-pnx4008/include/mach/gpio-pnx4008.h
deleted file mode 100644
index 41027dd..0000000
--- a/arch/arm/mach-pnx4008/include/mach/gpio-pnx4008.h
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * arch/arm/mach-pnx4008/include/mach/gpio-pnx4008.h
- *
- * PNX4008 GPIO driver - header file
- *
- * Author: Dmitry Chigirev <source@mvista.com>
- *
- * Based on reference code by Iwo Mergler and Z.Tabaaloute from Philips:
- * Copyright (c) 2005 Koninklijke Philips Electronics N.V.
- *
- * 2005 (c) MontaVista Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-
-#ifndef _PNX4008_GPIO_H_
-#define _PNX4008_GPIO_H_
-
-
-/* Block numbers */
-#define GPIO_IN		(0)
-#define GPIO_OUT		(0x100)
-#define GPIO_BID		(0x200)
-#define GPIO_RAM		(0x300)
-#define GPIO_MUX		(0x400)
-
-#define GPIO_TYPE_MASK(K) ((K) & 0x700)
-
-/* INPUT GPIOs */
-/* GPI */
-#define GPI_00		(GPIO_IN | 0)
-#define GPI_01		(GPIO_IN | 1)
-#define GPI_02   	(GPIO_IN | 2)
-#define GPI_03 	 	(GPIO_IN | 3)
-#define GPI_04   	(GPIO_IN | 4)
-#define GPI_05   	(GPIO_IN | 5)
-#define GPI_06   	(GPIO_IN | 6)
-#define GPI_07   	(GPIO_IN | 7)
-#define GPI_08   	(GPIO_IN | 8)
-#define GPI_09   	(GPIO_IN | 9)
-#define U1_RX 		(GPIO_IN | 15)
-#define U2_HTCS 	(GPIO_IN | 16)
-#define U2_RX	 	(GPIO_IN | 17)
-#define U3_RX		(GPIO_IN | 18)
-#define U4_RX		(GPIO_IN | 19)
-#define U5_RX		(GPIO_IN | 20)
-#define U6_IRRX 	(GPIO_IN | 21)
-#define U7_HCTS 	(GPIO_IN | 22)
-#define U7_RX		(GPIO_IN | 23)
-/* MISC IN */
-#define SPI1_DATIN	(GPIO_IN | 25)
-#define DISP_SYNC	(GPIO_IN | 26)
-#define SPI2_DATIN	(GPIO_IN | 27)
-#define GPI_11  	(GPIO_IN | 28)
-
-#define GPIO_IN_MASK   0x1eff83ff
-
-/* OUTPUT GPIOs */
-/* GPO */
-#define GPO_00		(GPIO_OUT | 0)
-#define GPO_01   	(GPIO_OUT | 1)
-#define GPO_02   	(GPIO_OUT | 2)
-#define GPO_03 	 	(GPIO_OUT | 3)
-#define GPO_04   	(GPIO_OUT | 4)
-#define GPO_05   	(GPIO_OUT | 5)
-#define GPO_06   	(GPIO_OUT | 6)
-#define GPO_07   	(GPIO_OUT | 7)
-#define GPO_08		(GPIO_OUT | 8)
-#define GPO_09   	(GPIO_OUT | 9)
-#define GPO_10   	(GPIO_OUT | 10)
-#define GPO_11 	 	(GPIO_OUT | 11)
-#define GPO_12   	(GPIO_OUT | 12)
-#define GPO_13   	(GPIO_OUT | 13)
-#define GPO_14   	(GPIO_OUT | 14)
-#define GPO_15   	(GPIO_OUT | 15)
-#define GPO_16  	(GPIO_OUT | 16)
-#define GPO_17 	 	(GPIO_OUT | 17)
-#define GPO_18   	(GPIO_OUT | 18)
-#define GPO_19   	(GPIO_OUT | 19)
-#define GPO_20   	(GPIO_OUT | 20)
-#define GPO_21   	(GPIO_OUT | 21)
-#define GPO_22   	(GPIO_OUT | 22)
-#define GPO_23   	(GPIO_OUT | 23)
-
-#define GPIO_OUT_MASK   0xffffff
-
-/* BIDIRECTIONAL GPIOs */
-/* RAM pins */
-#define RAM_D19		(GPIO_RAM | 0)
-#define RAM_D20  	(GPIO_RAM | 1)
-#define RAM_D21  	(GPIO_RAM | 2)
-#define RAM_D22 	(GPIO_RAM | 3)
-#define RAM_D23  	(GPIO_RAM | 4)
-#define RAM_D24  	(GPIO_RAM | 5)
-#define RAM_D25  	(GPIO_RAM | 6)
-#define RAM_D26  	(GPIO_RAM | 7)
-#define RAM_D27		(GPIO_RAM | 8)
-#define RAM_D28  	(GPIO_RAM | 9)
-#define RAM_D29  	(GPIO_RAM | 10)
-#define RAM_D30 	(GPIO_RAM | 11)
-#define RAM_D31  	(GPIO_RAM | 12)
-
-#define GPIO_RAM_MASK   0x1fff
-
-/* I/O pins */
-#define GPIO_00  	(GPIO_BID | 25)
-#define GPIO_01 	(GPIO_BID | 26)
-#define GPIO_02  	(GPIO_BID | 27)
-#define GPIO_03  	(GPIO_BID | 28)
-#define GPIO_04 	(GPIO_BID | 29)
-#define GPIO_05  	(GPIO_BID | 30)
-
-#define GPIO_BID_MASK   0x7e000000
-
-/* Non-GPIO multiplexed PIOs. For multiplexing with GPIO, please use GPIO macros */
-#define GPIO_SDRAM_SEL 	(GPIO_MUX | 3)
-
-#define GPIO_MUX_MASK   0x8
-
-/* Extraction/assembly macros */
-#define GPIO_BIT_MASK(K) ((K) & 0x1F)
-#define GPIO_BIT(K) (1 << GPIO_BIT_MASK(K))
-#define GPIO_ISMUX(K) ((GPIO_TYPE_MASK(K) == GPIO_MUX) && (GPIO_BIT(K) & GPIO_MUX_MASK))
-#define GPIO_ISRAM(K) ((GPIO_TYPE_MASK(K) == GPIO_RAM) && (GPIO_BIT(K) & GPIO_RAM_MASK))
-#define GPIO_ISBID(K) ((GPIO_TYPE_MASK(K) == GPIO_BID) && (GPIO_BIT(K) & GPIO_BID_MASK))
-#define GPIO_ISOUT(K) ((GPIO_TYPE_MASK(K) == GPIO_OUT) && (GPIO_BIT(K) & GPIO_OUT_MASK))
-#define GPIO_ISIN(K)  ((GPIO_TYPE_MASK(K) == GPIO_IN) && (GPIO_BIT(K) & GPIO_IN_MASK))
-
-/* Start Enable Pin Interrupts - table 58 page 66 */
-
-#define SE_PIN_BASE_INT   32
-
-#define SE_U7_RX_INT            63
-#define SE_U7_HCTS_INT          62
-#define SE_BT_CLKREQ_INT        61
-#define SE_U6_IRRX_INT          60
-/*59 unused*/
-#define SE_U5_RX_INT            58
-#define SE_GPI_11_INT           57
-#define SE_U3_RX_INT            56
-#define SE_U2_HCTS_INT          55
-#define SE_U2_RX_INT            54
-#define SE_U1_RX_INT            53
-#define SE_DISP_SYNC_INT        52
-/*51 unused*/
-#define SE_SDIO_INT_N           50
-#define SE_MSDIO_START_INT      49
-#define SE_GPI_06_INT           48
-#define SE_GPI_05_INT           47
-#define SE_GPI_04_INT           46
-#define SE_GPI_03_INT           45
-#define SE_GPI_02_INT           44
-#define SE_GPI_01_INT           43
-#define SE_GPI_00_INT           42
-#define SE_SYSCLKEN_PIN_INT     41
-#define SE_SPI1_DATAIN_INT      40
-#define SE_GPI_07_INT           39
-#define SE_SPI2_DATAIN_INT      38
-#define SE_GPI_10_INT           37
-#define SE_GPI_09_INT           36
-#define SE_GPI_08_INT           35
-/*34-32 unused*/
-
-/* Start Enable Internal Interrupts - table 57 page 65 */
-
-#define SE_INT_BASE_INT   0
-
-#define SE_TS_IRQ               31
-#define SE_TS_P_INT             30
-#define SE_TS_AUX_INT           29
-/*27-28 unused*/
-#define SE_USB_AHB_NEED_CLK_INT 26
-#define SE_MSTIMER_INT          25
-#define SE_RTC_INT              24
-#define SE_USB_NEED_CLK_INT     23
-#define SE_USB_INT              22
-#define SE_USB_I2C_INT          21
-#define SE_USB_OTG_TIMER_INT    20
-#define SE_USB_OTG_ATX_INT_N    19
-/*18 unused*/
-#define SE_DSP_GPIO4_INT        17
-#define SE_KEY_IRQ              16
-#define SE_DSP_SLAVEPORT_INT    15
-#define SE_DSP_GPIO1_INT        14
-#define SE_DSP_GPIO0_INT        13
-#define SE_DSP_AHB_INT          12
-/*11-6 unused*/
-#define SE_GPIO_05_INT          5
-#define SE_GPIO_04_INT          4
-#define SE_GPIO_03_INT          3
-#define SE_GPIO_02_INT          2
-#define SE_GPIO_01_INT          1
-#define SE_GPIO_00_INT          0
-
-#define START_INT_REG_BIT(irq) (1<<((irq)&0x1F))
-
-#define START_INT_ER_REG(irq)     IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x20 + (((irq)&(0x1<<5))>>1)))
-#define START_INT_RSR_REG(irq)    IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x24 + (((irq)&(0x1<<5))>>1)))
-#define START_INT_SR_REG(irq)     IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x28 + (((irq)&(0x1<<5))>>1)))
-#define START_INT_APR_REG(irq)    IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x2C + (((irq)&(0x1<<5))>>1)))
-
-extern int pnx4008_gpio_register_pin(unsigned short pin);
-extern int pnx4008_gpio_unregister_pin(unsigned short pin);
-extern unsigned long pnx4008_gpio_read_pin(unsigned short pin);
-extern int pnx4008_gpio_write_pin(unsigned short pin, int output);
-extern int pnx4008_gpio_set_pin_direction(unsigned short pin, int output);
-extern int pnx4008_gpio_read_pin_direction(unsigned short pin);
-extern int pnx4008_gpio_set_pin_mux(unsigned short pin, int output);
-extern int pnx4008_gpio_read_pin_mux(unsigned short pin);
-
-static inline void start_int_umask(u8 irq)
-{
-	__raw_writel(__raw_readl(START_INT_ER_REG(irq)) |
-		     START_INT_REG_BIT(irq), START_INT_ER_REG(irq));
-}
-
-static inline void start_int_mask(u8 irq)
-{
-	__raw_writel(__raw_readl(START_INT_ER_REG(irq)) &
-		     ~START_INT_REG_BIT(irq), START_INT_ER_REG(irq));
-}
-
-static inline void start_int_ack(u8 irq)
-{
-	__raw_writel(START_INT_REG_BIT(irq), START_INT_RSR_REG(irq));
-}
-
-static inline void start_int_set_falling_edge(u8 irq)
-{
-	__raw_writel(__raw_readl(START_INT_APR_REG(irq)) &
-		     ~START_INT_REG_BIT(irq), START_INT_APR_REG(irq));
-}
-
-static inline void start_int_set_rising_edge(u8 irq)
-{
-	__raw_writel(__raw_readl(START_INT_APR_REG(irq)) |
-		     START_INT_REG_BIT(irq), START_INT_APR_REG(irq));
-}
-
-#endif				/* _PNX4008_GPIO_H_ */
diff --git a/arch/arm/mach-pnx4008/include/mach/hardware.h b/arch/arm/mach-pnx4008/include/mach/hardware.h
deleted file mode 100644
index 7b98b82..0000000
--- a/arch/arm/mach-pnx4008/include/mach/hardware.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * arch/arm/mach-pnx4008/include/mach/hardware.h
- *
- * Copyright (c) 2005 MontaVista Software, Inc. <source@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 Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#ifndef __ASM_ARCH_HARDWARE_H
-#define __ASM_ARCH_HARDWARE_H
-
-#include <asm/sizes.h>
-#include <mach/platform.h>
-
-/* Start of virtual addresses for IO devices */
-#define IO_BASE         0xF0000000
-
-/* This macro relies on fact that for all HW i/o addresses bits 20-23 are 0 */
-#define IO_ADDRESS(x)  (((((x) & 0xff000000) >> 4) | ((x) & 0xfffff)) | IO_BASE)
-
-#endif
diff --git a/arch/arm/mach-pnx4008/include/mach/irq.h b/arch/arm/mach-pnx4008/include/mach/irq.h
deleted file mode 100644
index 2a690ca..0000000
--- a/arch/arm/mach-pnx4008/include/mach/irq.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * arch/arm/mach-pnx4008/include/mach/irq.h
- *
- * PNX4008 IRQ controller driver - header file
- * this one is used in entry-arnv.S as well so it cannot contain C code
- *
- * Copyright (c) 2005 Philips Semiconductors
- * Copyright (c) 2005 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 __PNX4008_IRQ_H__
-#define __PNX4008_IRQ_H__
-
-#define MIC_VA_BASE             IO_ADDRESS(PNX4008_INTCTRLMIC_BASE)
-#define SIC1_VA_BASE            IO_ADDRESS(PNX4008_INTCTRLSIC1_BASE)
-#define SIC2_VA_BASE            IO_ADDRESS(PNX4008_INTCTRLSIC2_BASE)
-
-/* Manual: Chapter 20, page 195 */
-
-#define INTC_BIT(irq) (1<< ((irq) & 0x1F))
-
-#define INTC_ER(irq)    IO_ADDRESS((PNX4008_INTCTRLMIC_BASE + 0x0 + (((irq)&(0x3<<5))<<9)))
-#define INTC_RSR(irq)   IO_ADDRESS((PNX4008_INTCTRLMIC_BASE + 0x4 + (((irq)&(0x3<<5))<<9)))
-#define INTC_SR(irq)    IO_ADDRESS((PNX4008_INTCTRLMIC_BASE + 0x8 + (((irq)&(0x3<<5))<<9)))
-#define INTC_APR(irq)   IO_ADDRESS((PNX4008_INTCTRLMIC_BASE + 0xC + (((irq)&(0x3<<5))<<9)))
-#define INTC_ATR(irq)   IO_ADDRESS((PNX4008_INTCTRLMIC_BASE + 0x10 + (((irq)&(0x3<<5))<<9)))
-#define INTC_ITR(irq)   IO_ADDRESS((PNX4008_INTCTRLMIC_BASE + 0x14 + (((irq)&(0x3<<5))<<9)))
-
-#define START_INT_REG_BIT(irq) (1<<((irq)&0x1F))
-
-#define START_INT_ER_REG(irq)     IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x20 + (((irq)&(0x1<<5))>>1)))
-#define START_INT_RSR_REG(irq)    IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x24 + (((irq)&(0x1<<5))>>1)))
-#define START_INT_SR_REG(irq)     IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x28 + (((irq)&(0x1<<5))>>1)))
-#define START_INT_APR_REG(irq)    IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x2C + (((irq)&(0x1<<5))>>1)))
-
-extern void __init pnx4008_init_irq(void);
-
-#endif /* __PNX4008_IRQ_H__ */
diff --git a/arch/arm/mach-pnx4008/include/mach/irqs.h b/arch/arm/mach-pnx4008/include/mach/irqs.h
deleted file mode 100644
index f6b33cf..0000000
--- a/arch/arm/mach-pnx4008/include/mach/irqs.h
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- * arch/arm/mach-pnx4008/include/mach/irqs.h
- *
- * PNX4008 IRQ controller driver - header file
- *
- * Author: Dmitry Chigirev <source@mvista.com>
- *
- * 2005 (c) MontaVista Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-#ifndef __PNX4008_IRQS_h__
-#define __PNX4008_IRQS_h__
-
-#define NR_IRQS         96
-
-/*Manual: table 259, page 199*/
-
-/*SUB2 Interrupt Routing (SIC2)*/
-
-#define SIC2_BASE_INT   64
-
-#define CLK_SWITCH_ARM_INT 95	/*manual: Clkswitch ARM  */
-#define CLK_SWITCH_DSP_INT 94	/*manual: ClkSwitch DSP  */
-#define CLK_SWITCH_AUD_INT 93	/*manual: Clkswitch AUD  */
-#define GPI_06_INT         92
-#define GPI_05_INT         91
-#define GPI_04_INT         90
-#define GPI_03_INT         89
-#define GPI_02_INT         88
-#define GPI_01_INT         87
-#define GPI_00_INT         86
-#define BT_CLKREQ_INT      85
-#define SPI1_DATIN_INT     84
-#define U5_RX_INT          83
-#define SDIO_INT_N         82
-#define CAM_HS_INT         81
-#define CAM_VS_INT         80
-#define GPI_07_INT         79
-#define DISP_SYNC_INT      78
-#define DSP_INT8           77
-#define U7_HCTS_INT        76
-#define GPI_10_INT         75
-#define GPI_09_INT         74
-#define GPI_08_INT         73
-#define DSP_INT7           72
-#define U2_HCTS_INT        71
-#define SPI2_DATIN_INT     70
-#define GPIO_05_INT        69
-#define GPIO_04_INT        68
-#define GPIO_03_INT        67
-#define GPIO_02_INT        66
-#define GPIO_01_INT        65
-#define GPIO_00_INT        64
-
-/*Manual: table 258, page 198*/
-
-/*SUB1 Interrupt Routing (SIC1)*/
-
-#define SIC1_BASE_INT   32
-
-#define USB_I2C_INT        63
-#define USB_DEV_HP_INT     62
-#define USB_DEV_LP_INT     61
-#define USB_DEV_DMA_INT    60
-#define USB_HOST_INT       59
-#define USB_OTG_ATX_INT_N  58
-#define USB_OTG_TIMER_INT  57
-#define SW_INT             56
-#define SPI1_INT           55
-#define KEY_IRQ            54
-#define DSP_M_INT          53
-#define RTC_INT            52
-#define I2C_1_INT          51
-#define I2C_2_INT          50
-#define PLL1_LOCK_INT      49
-#define PLL2_LOCK_INT      48
-#define PLL3_LOCK_INT      47
-#define PLL4_LOCK_INT      46
-#define PLL5_LOCK_INT      45
-#define SPI2_INT           44
-#define DSP_INT1           43
-#define DSP_INT2           42
-#define DSP_TDM_INT2       41
-#define TS_AUX_INT         40
-#define TS_IRQ             39
-#define TS_P_INT           38
-#define UOUT1_TO_PAD_INT   37
-#define GPI_11_INT         36
-#define DSP_INT4           35
-#define JTAG_COMM_RX_INT   34
-#define JTAG_COMM_TX_INT   33
-#define DSP_INT3           32
-
-/*Manual: table 257, page 197*/
-
-/*MAIN Interrupt Routing*/
-
-#define MAIN_BASE_INT   0
-
-#define SUB2_FIQ_N         31	/*active low */
-#define SUB1_FIQ_N         30	/*active low */
-#define JPEG_INT           29
-#define DMA_INT            28
-#define MSTIMER_INT        27
-#define IIR1_INT           26
-#define IIR2_INT           25
-#define IIR7_INT           24
-#define DSP_TDM_INT0       23
-#define DSP_TDM_INT1       22
-#define DSP_P_INT          21
-#define DSP_INT0           20
-#define DUM_INT            19
-#define UOUT0_TO_PAD_INT   18
-#define MP4_ENC_INT        17
-#define MP4_DEC_INT        16
-#define SD0_INT            15
-#define MBX_INT            14
-#define SD1_INT            13
-#define MS_INT_N           12
-#define FLASH_INT          11 /*NAND*/
-#define IIR6_INT           10
-#define IIR5_INT           9
-#define IIR4_INT           8
-#define IIR3_INT           7
-#define WATCH_INT          6
-#define HSTIMER_INT        5
-#define ARCH_TIMER_IRQ     HSTIMER_INT
-#define CAM_INT            4
-#define PRNG_INT           3
-#define CRYPTO_INT         2
-#define SUB2_IRQ_N         1	/*active low */
-#define SUB1_IRQ_N         0	/*active low */
-
-#define PNX4008_IRQ_TYPES \
-{                                           /*IRQ #'s: */         \
-IRQ_TYPE_LEVEL_LOW,  IRQ_TYPE_LEVEL_LOW,  IRQ_TYPE_LEVEL_LOW,  IRQ_TYPE_LEVEL_HIGH, /*  0, 1, 2, 3 */     \
-IRQ_TYPE_LEVEL_LOW,  IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, /*  4, 5, 6, 7 */     \
-IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, /*  8, 9,10,11 */     \
-IRQ_TYPE_LEVEL_LOW,  IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, /* 12,13,14,15 */     \
-IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, /* 16,17,18,19 */     \
-IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, /* 20,21,22,23 */     \
-IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, /* 24,25,26,27 */     \
-IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_LOW,  IRQ_TYPE_LEVEL_LOW,  /* 28,29,30,31 */     \
-IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_LOW,  IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, /* 32,33,34,35 */     \
-IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_EDGE_FALLING, IRQ_TYPE_LEVEL_HIGH, /* 36,37,38,39 */  \
-IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, /* 40,41,42,43 */     \
-IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, /* 44,45,46,47 */     \
-IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_LOW,  IRQ_TYPE_LEVEL_LOW,  /* 48,49,50,51 */     \
-IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, /* 52,53,54,55 */     \
-IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_LOW,  IRQ_TYPE_LEVEL_HIGH, /* 56,57,58,59 */     \
-IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, /* 60,61,62,63 */     \
-IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, /* 64,65,66,67 */     \
-IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, /* 68,69,70,71 */     \
-IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, /* 72,73,74,75 */     \
-IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, /* 76,77,78,79 */     \
-IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, /* 80,81,82,83 */     \
-IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, /* 84,85,86,87 */     \
-IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, /* 88,89,90,91 */     \
-IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_HIGH, /* 92,93,94,95 */     \
-}
-
-/* Start Enable Pin Interrupts - table 58 page 66 */
-
-#define SE_PIN_BASE_INT   32
-
-#define SE_U7_RX_INT            63
-#define SE_U7_HCTS_INT          62
-#define SE_BT_CLKREQ_INT        61
-#define SE_U6_IRRX_INT          60
-/*59 unused*/
-#define SE_U5_RX_INT            58
-#define SE_GPI_11_INT           57
-#define SE_U3_RX_INT            56
-#define SE_U2_HCTS_INT          55
-#define SE_U2_RX_INT            54
-#define SE_U1_RX_INT            53
-#define SE_DISP_SYNC_INT        52
-/*51 unused*/
-#define SE_SDIO_INT_N           50
-#define SE_MSDIO_START_INT      49
-#define SE_GPI_06_INT           48
-#define SE_GPI_05_INT           47
-#define SE_GPI_04_INT           46
-#define SE_GPI_03_INT           45
-#define SE_GPI_02_INT           44
-#define SE_GPI_01_INT           43
-#define SE_GPI_00_INT           42
-#define SE_SYSCLKEN_PIN_INT     41
-#define SE_SPI1_DATAIN_INT      40
-#define SE_GPI_07_INT           39
-#define SE_SPI2_DATAIN_INT      38
-#define SE_GPI_10_INT           37
-#define SE_GPI_09_INT           36
-#define SE_GPI_08_INT           35
-/*34-32 unused*/
-
-/* Start Enable Internal Interrupts - table 57 page 65 */
-
-#define SE_INT_BASE_INT   0
-
-#define SE_TS_IRQ               31
-#define SE_TS_P_INT             30
-#define SE_TS_AUX_INT           29
-/*27-28 unused*/
-#define SE_USB_AHB_NEED_CLK_INT 26
-#define SE_MSTIMER_INT          25
-#define SE_RTC_INT              24
-#define SE_USB_NEED_CLK_INT     23
-#define SE_USB_INT              22
-#define SE_USB_I2C_INT          21
-#define SE_USB_OTG_TIMER_INT    20
-
-#endif /* __PNX4008_IRQS_h__ */
diff --git a/arch/arm/mach-pnx4008/include/mach/param.h b/arch/arm/mach-pnx4008/include/mach/param.h
deleted file mode 100644
index 6ea02f2..0000000
--- a/arch/arm/mach-pnx4008/include/mach/param.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- *  arch/arm/mach-pnx4008/include/mach/param.h
- *
- *  Copyright (C) 1999 ARM Limited
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#define HZ 100
diff --git a/arch/arm/mach-pnx4008/include/mach/platform.h b/arch/arm/mach-pnx4008/include/mach/platform.h
deleted file mode 100644
index 368c2c1..0000000
--- a/arch/arm/mach-pnx4008/include/mach/platform.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * arch/arm/mach-pnx4008/include/mach/platform.h
- *
- * PNX4008 Base addresses - header file
- *
- * Author: Dmitry Chigirev <source@mvista.com>
- *
- * Based on reference code received from Philips:
- * Copyright (C) 2003 Philips Semiconductors
- *
- * 2005 (c) MontaVista Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-
-
-#ifndef __ASM_ARCH_PLATFORM_H__
-#define __ASM_ARCH_PLATFORM_H__
-
-#define PNX4008_IRAM_BASE		0x08000000
-#define PNX4008_IRAM_SIZE		0x00010000
-#define PNX4008_YUV_SLAVE_BASE		0x10000000
-#define PNX4008_DUM_SLAVE_BASE		0x18000000
-#define PNX4008_NDF_FLASH_BASE		0x20020000
-#define PNX4008_SPI1_BASE		0x20088000
-#define PNX4008_SPI2_BASE		0x20090000
-#define PNX4008_SD_CONFIG_BASE		0x20098000
-#define PNX4008_FLASH_DATA		0x200B0000
-#define PNX4008_MLC_FLASH_BASE		0x200B8000
-#define PNX4008_JPEG_CONFIG_BASE	0x300A0000
-#define PNX4008_DMA_CONFIG_BASE		0x31000000
-#define PNX4008_USB_CONFIG_BASE		0x31020000
-#define PNX4008_SDRAM_CFG_BASE		0x31080000
-#define PNX4008_AHB2FAB_BASE		0x40000000
-#define PNX4008_PWRMAN_BASE		0x40004000
-#define PNX4008_INTCTRLMIC_BASE		0x40008000
-#define PNX4008_INTCTRLSIC1_BASE	0x4000C000
-#define PNX4008_INTCTRLSIC2_BASE	0x40010000
-#define PNX4008_HSUART1_BASE		0x40014000
-#define PNX4008_HSUART2_BASE		0x40018000
-#define PNX4008_HSUART7_BASE		0x4001C000
-#define PNX4008_RTC_BASE		0x40024000
-#define PNX4008_PIO_BASE		0x40028000
-#define PNX4008_MSTIMER_BASE		0x40034000
-#define PNX4008_HSTIMER_BASE		0x40038000
-#define PNX4008_WDOG_BASE		0x4003C000
-#define PNX4008_DEBUG_BASE		0x40040000
-#define PNX4008_TOUCH1_BASE		0x40048000
-#define PNX4008_KEYSCAN_BASE		0x40050000
-#define PNX4008_UARTCTRL_BASE		0x40054000
-#define PNX4008_PWM_BASE		0x4005C000
-#define PNX4008_UART3_BASE		0x40080000
-#define PNX4008_UART4_BASE		0x40088000
-#define PNX4008_UART5_BASE		0x40090000
-#define PNX4008_UART6_BASE		0x40098000
-#define PNX4008_I2C1_BASE		0x400A0000
-#define PNX4008_I2C2_BASE		0x400A8000
-#define PNX4008_MAGICGATE_BASE		0x400B0000
-#define PNX4008_DUMCONF_BASE		0x400B8000
-#define PNX4008_DUM_MAINCFG_BASE       	0x400BC000
-#define PNX4008_DSP_BASE		0x400C0000
-#define PNX4008_PROFCOUNTER_BASE	0x400C8000
-#define PNX4008_CRYPTO_BASE		0x400D0000
-#define PNX4008_CAMIFCONF_BASE		0x400D8000
-#define PNX4008_YUV2RGB_BASE		0x400E0000
-#define PNX4008_AUDIOCONFIG_BASE	0x400E8000
-
-#endif
diff --git a/arch/arm/mach-pnx4008/include/mach/pm.h b/arch/arm/mach-pnx4008/include/mach/pm.h
deleted file mode 100644
index 2fa685b..0000000
--- a/arch/arm/mach-pnx4008/include/mach/pm.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * arch/arm/mach-pnx4008/include/mach/pm.h
- *
- * PNX4008 Power Management Routiness - header file
- *
- * Authors: Vitaly Wool, Dmitry Chigirev <source@mvista.com>
- *
- * 2005 (c) MontaVista Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-
-#ifndef __ASM_ARCH_PNX4008_PM_H
-#define __ASM_ARCH_PNX4008_PM_H
-
-#ifndef __ASSEMBLER__
-#include "irq.h"
-#include "irqs.h"
-#include "clock.h"
-
-extern void pnx4008_pm_idle(void);
-extern void pnx4008_pm_suspend(void);
-extern unsigned int pnx4008_cpu_suspend_sz;
-extern void pnx4008_cpu_suspend(void);
-extern unsigned int pnx4008_cpu_standby_sz;
-extern void pnx4008_cpu_standby(void);
-
-extern int pnx4008_startup_pll(struct clk *);
-extern int pnx4008_shutdown_pll(struct clk *);
-
-#endif				/* ASSEMBLER */
-#endif				/* __ASM_ARCH_PNX4008_PM_H */
diff --git a/arch/arm/mach-pnx4008/include/mach/timex.h b/arch/arm/mach-pnx4008/include/mach/timex.h
deleted file mode 100644
index b383c7d..0000000
--- a/arch/arm/mach-pnx4008/include/mach/timex.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * arch/arm/mach-pnx4008/include/mach/timex.h
- *
- * PNX4008 timers header file
- *
- * Author: Dmitry Chigirev <source@mvista.com>
- *
- * 2005 (c) MontaVista Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-
-#ifndef __PNX4008_TIMEX_H
-#define __PNX4008_TIMEX_H
-
-#define CLOCK_TICK_RATE		1000000
-
-#endif
diff --git a/arch/arm/mach-pnx4008/include/mach/uncompress.h b/arch/arm/mach-pnx4008/include/mach/uncompress.h
deleted file mode 100644
index bb4751e..0000000
--- a/arch/arm/mach-pnx4008/include/mach/uncompress.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- *  arch/arm/mach-pnx4008/include/mach/uncompress.h
- *
- *  Copyright (C) 1999 ARM Limited
- *  Copyright (C) 2006 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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public 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 UART5_BASE 0x40090000
-
-#define UART5_DR    (*(volatile unsigned char *) (UART5_BASE))
-#define UART5_FR    (*(volatile unsigned char *) (UART5_BASE + 18))
-
-static __inline__ void putc(char c)
-{
-	while (UART5_FR & (1 << 5))
-		barrier();
-
-	UART5_DR = 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-pnx4008/irq.c b/arch/arm/mach-pnx4008/irq.c
deleted file mode 100644
index 41e4201..0000000
--- a/arch/arm/mach-pnx4008/irq.c
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * arch/arm/mach-pnx4008/irq.c
- *
- * PNX4008 IRQ controller driver
- *
- * Author: Dmitry Chigirev <source@mvista.com>
- *
- * Based on reference code received from Philips:
- * Copyright (C) 2003 Philips Semiconductors
- *
- * 2005 (c) MontaVista Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/list.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/device.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <mach/hardware.h>
-#include <asm/setup.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/irq.h>
-#include <asm/mach/map.h>
-#include <mach/irq.h>
-
-static u8 pnx4008_irq_type[NR_IRQS] = PNX4008_IRQ_TYPES;
-
-static void pnx4008_mask_irq(struct irq_data *d)
-{
-	__raw_writel(__raw_readl(INTC_ER(d->irq)) & ~INTC_BIT(d->irq), INTC_ER(d->irq));	/* mask interrupt */
-}
-
-static void pnx4008_unmask_irq(struct irq_data *d)
-{
-	__raw_writel(__raw_readl(INTC_ER(d->irq)) | INTC_BIT(d->irq), INTC_ER(d->irq));	/* unmask interrupt */
-}
-
-static void pnx4008_mask_ack_irq(struct irq_data *d)
-{
-	__raw_writel(__raw_readl(INTC_ER(d->irq)) & ~INTC_BIT(d->irq), INTC_ER(d->irq));	/* mask interrupt */
-	__raw_writel(INTC_BIT(d->irq), INTC_SR(d->irq));	/* clear interrupt status */
-}
-
-static int pnx4008_set_irq_type(struct irq_data *d, unsigned int type)
-{
-	switch (type) {
-	case IRQ_TYPE_EDGE_RISING:
-		__raw_writel(__raw_readl(INTC_ATR(d->irq)) | INTC_BIT(d->irq), INTC_ATR(d->irq));	/*edge sensitive */
-		__raw_writel(__raw_readl(INTC_APR(d->irq)) | INTC_BIT(d->irq), INTC_APR(d->irq));	/*rising edge */
-		irq_set_handler(d->irq, handle_edge_irq);
-		break;
-	case IRQ_TYPE_EDGE_FALLING:
-		__raw_writel(__raw_readl(INTC_ATR(d->irq)) | INTC_BIT(d->irq), INTC_ATR(d->irq));	/*edge sensitive */
-		__raw_writel(__raw_readl(INTC_APR(d->irq)) & ~INTC_BIT(d->irq), INTC_APR(d->irq));	/*falling edge */
-		irq_set_handler(d->irq, handle_edge_irq);
-		break;
-	case IRQ_TYPE_LEVEL_LOW:
-		__raw_writel(__raw_readl(INTC_ATR(d->irq)) & ~INTC_BIT(d->irq), INTC_ATR(d->irq));	/*level sensitive */
-		__raw_writel(__raw_readl(INTC_APR(d->irq)) & ~INTC_BIT(d->irq), INTC_APR(d->irq));	/*low level */
-		irq_set_handler(d->irq, handle_level_irq);
-		break;
-	case IRQ_TYPE_LEVEL_HIGH:
-		__raw_writel(__raw_readl(INTC_ATR(d->irq)) & ~INTC_BIT(d->irq), INTC_ATR(d->irq));	/*level sensitive */
-		__raw_writel(__raw_readl(INTC_APR(d->irq)) | INTC_BIT(d->irq), INTC_APR(d->irq));	/* high level */
-		irq_set_handler(d->irq, handle_level_irq);
-		break;
-
-	/* IRQ_TYPE_EDGE_BOTH is not supported */
-	default:
-		printk(KERN_ERR "PNX4008 IRQ: Unsupported irq type %d\n", type);
-		return -1;
-	}
-	return 0;
-}
-
-static struct irq_chip pnx4008_irq_chip = {
-	.irq_ack = pnx4008_mask_ack_irq,
-	.irq_mask = pnx4008_mask_irq,
-	.irq_unmask = pnx4008_unmask_irq,
-	.irq_set_type = pnx4008_set_irq_type,
-};
-
-void __init pnx4008_init_irq(void)
-{
-	unsigned int i;
-
-	/* configure IRQ's */
-	for (i = 0; i < NR_IRQS; i++) {
-		set_irq_flags(i, IRQF_VALID);
-		irq_set_chip(i, &pnx4008_irq_chip);
-		pnx4008_set_irq_type(irq_get_irq_data(i), pnx4008_irq_type[i]);
-	}
-
-	/* configure and enable IRQ 0,1,30,31 (cascade interrupts) */
-	pnx4008_set_irq_type(irq_get_irq_data(SUB1_IRQ_N),
-			     pnx4008_irq_type[SUB1_IRQ_N]);
-	pnx4008_set_irq_type(irq_get_irq_data(SUB2_IRQ_N),
-			     pnx4008_irq_type[SUB2_IRQ_N]);
-	pnx4008_set_irq_type(irq_get_irq_data(SUB1_FIQ_N),
-			     pnx4008_irq_type[SUB1_FIQ_N]);
-	pnx4008_set_irq_type(irq_get_irq_data(SUB2_FIQ_N),
-			     pnx4008_irq_type[SUB2_FIQ_N]);
-
-	/* mask all others */
-	__raw_writel((1 << SUB2_FIQ_N) | (1 << SUB1_FIQ_N) |
-			(1 << SUB2_IRQ_N) | (1 << SUB1_IRQ_N),
-		INTC_ER(MAIN_BASE_INT));
-	__raw_writel(0, INTC_ER(SIC1_BASE_INT));
-	__raw_writel(0, INTC_ER(SIC2_BASE_INT));
-}
-
diff --git a/arch/arm/mach-pnx4008/pm.c b/arch/arm/mach-pnx4008/pm.c
deleted file mode 100644
index 26f8d06..0000000
--- a/arch/arm/mach-pnx4008/pm.c
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * arch/arm/mach-pnx4008/pm.c
- *
- * Power Management driver for PNX4008
- *
- * Authors: Vitaly Wool, Dmitry Chigirev <source@mvista.com>
- *
- * 2005 (c) MontaVista Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-
-#include <linux/pm.h>
-#include <linux/rtc.h>
-#include <linux/sched.h>
-#include <linux/proc_fs.h>
-#include <linux/suspend.h>
-#include <linux/delay.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-
-#include <asm/cacheflush.h>
-
-#include <mach/hardware.h>
-#include <mach/pm.h>
-#include <mach/clock.h>
-
-#define SRAM_VA IO_ADDRESS(PNX4008_IRAM_BASE)
-
-static void *saved_sram;
-
-static struct clk *pll4_clk;
-
-static inline void pnx4008_standby(void)
-{
-	void (*pnx4008_cpu_standby_ptr) (void);
-
-	local_irq_disable();
-	local_fiq_disable();
-
-	clk_disable(pll4_clk);
-
-	/*saving portion of SRAM to be used by suspend function. */
-	memcpy(saved_sram, (void *)SRAM_VA, pnx4008_cpu_standby_sz);
-
-	/*make sure SRAM copy gets physically written into SDRAM.
-	   SDRAM will be placed into self-refresh during power down */
-	flush_cache_all();
-
-	/*copy suspend function into SRAM */
-	memcpy((void *)SRAM_VA, pnx4008_cpu_standby, pnx4008_cpu_standby_sz);
-
-	/*do suspend */
-	pnx4008_cpu_standby_ptr = (void *)SRAM_VA;
-	pnx4008_cpu_standby_ptr();
-
-	/*restoring portion of SRAM that was used by suspend function */
-	memcpy((void *)SRAM_VA, saved_sram, pnx4008_cpu_standby_sz);
-
-	clk_enable(pll4_clk);
-
-	local_fiq_enable();
-	local_irq_enable();
-}
-
-static inline void pnx4008_suspend(void)
-{
-	void (*pnx4008_cpu_suspend_ptr) (void);
-
-	local_irq_disable();
-	local_fiq_disable();
-
-	clk_disable(pll4_clk);
-
-	__raw_writel(0xffffffff, START_INT_RSR_REG(SE_PIN_BASE_INT));
-	__raw_writel(0xffffffff, START_INT_RSR_REG(SE_INT_BASE_INT));
-
-	/*saving portion of SRAM to be used by suspend function. */
-	memcpy(saved_sram, (void *)SRAM_VA, pnx4008_cpu_suspend_sz);
-
-	/*make sure SRAM copy gets physically written into SDRAM.
-	   SDRAM will be placed into self-refresh during power down */
-	flush_cache_all();
-
-	/*copy suspend function into SRAM */
-	memcpy((void *)SRAM_VA, pnx4008_cpu_suspend, pnx4008_cpu_suspend_sz);
-
-	/*do suspend */
-	pnx4008_cpu_suspend_ptr = (void *)SRAM_VA;
-	pnx4008_cpu_suspend_ptr();
-
-	/*restoring portion of SRAM that was used by suspend function */
-	memcpy((void *)SRAM_VA, saved_sram, pnx4008_cpu_suspend_sz);
-
-	clk_enable(pll4_clk);
-
-	local_fiq_enable();
-	local_irq_enable();
-}
-
-static int pnx4008_pm_enter(suspend_state_t state)
-{
-	switch (state) {
-	case PM_SUSPEND_STANDBY:
-		pnx4008_standby();
-		break;
-	case PM_SUSPEND_MEM:
-		pnx4008_suspend();
-		break;
-	}
-	return 0;
-}
-
-static int pnx4008_pm_valid(suspend_state_t state)
-{
-	return (state == PM_SUSPEND_STANDBY) ||
-	       (state == PM_SUSPEND_MEM);
-}
-
-static const struct platform_suspend_ops pnx4008_pm_ops = {
-	.enter = pnx4008_pm_enter,
-	.valid = pnx4008_pm_valid,
-};
-
-int __init pnx4008_pm_init(void)
-{
-	u32 sram_size_to_allocate;
-
-	pll4_clk = clk_get(0, "ck_pll4");
-	if (IS_ERR(pll4_clk)) {
-		printk(KERN_ERR
-		       "PM Suspend cannot acquire ARM(PLL4) clock control\n");
-		return PTR_ERR(pll4_clk);
-	}
-
-	if (pnx4008_cpu_standby_sz > pnx4008_cpu_suspend_sz)
-		sram_size_to_allocate = pnx4008_cpu_standby_sz;
-	else
-		sram_size_to_allocate = pnx4008_cpu_suspend_sz;
-
-	saved_sram = kmalloc(sram_size_to_allocate, GFP_ATOMIC);
-	if (!saved_sram) {
-		printk(KERN_ERR
-		       "PM Suspend: cannot allocate memory to save portion of SRAM\n");
-		clk_put(pll4_clk);
-		return -ENOMEM;
-	}
-
-	suspend_set_ops(&pnx4008_pm_ops);
-	return 0;
-}
diff --git a/arch/arm/mach-pnx4008/serial.c b/arch/arm/mach-pnx4008/serial.c
deleted file mode 100644
index 374c138..0000000
--- a/arch/arm/mach-pnx4008/serial.c
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- *  linux/arch/arm/mach-pnx4008/serial.c
- *
- *  PNX4008 UART initialization
- *
- *  Copyright:	MontaVista Software Inc. (c) 2005
- *
- *  This program is free software; you can 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/io.h>
-
-#include <mach/platform.h>
-#include <mach/hardware.h>
-
-#include <linux/serial_core.h>
-#include <linux/serial_reg.h>
-
-#include <mach/gpio-pnx4008.h>
-#include <mach/clock.h>
-
-#define UART_3		0
-#define UART_4		1
-#define UART_5		2
-#define UART_6		3
-#define UART_UNKNOWN	(-1)
-
-#define UART3_BASE_VA	IO_ADDRESS(PNX4008_UART3_BASE)
-#define UART4_BASE_VA	IO_ADDRESS(PNX4008_UART4_BASE)
-#define UART5_BASE_VA	IO_ADDRESS(PNX4008_UART5_BASE)
-#define UART6_BASE_VA	IO_ADDRESS(PNX4008_UART6_BASE)
-
-#define UART_FCR_OFFSET		8
-#define UART_FIFO_SIZE		64
-
-void pnx4008_uart_init(void)
-{
-	u32 tmp;
-	int i = UART_FIFO_SIZE;
-
-	__raw_writel(0xC1, UART5_BASE_VA + UART_FCR_OFFSET);
-	__raw_writel(0xC1, UART3_BASE_VA + UART_FCR_OFFSET);
-
-	/* Send a NULL to fix the UART HW bug */
-	__raw_writel(0x00, UART5_BASE_VA);
-	__raw_writel(0x00, UART3_BASE_VA);
-
-	while (i--) {
-		tmp = __raw_readl(UART5_BASE_VA);
-		tmp = __raw_readl(UART3_BASE_VA);
-	}
-	__raw_writel(0, UART5_BASE_VA + UART_FCR_OFFSET);
-	__raw_writel(0, UART3_BASE_VA + UART_FCR_OFFSET);
-
-	/* setup wakeup interrupt */
-	start_int_set_rising_edge(SE_U3_RX_INT);
-	start_int_ack(SE_U3_RX_INT);
-	start_int_umask(SE_U3_RX_INT);
-
-	start_int_set_rising_edge(SE_U5_RX_INT);
-	start_int_ack(SE_U5_RX_INT);
-	start_int_umask(SE_U5_RX_INT);
-}
-
diff --git a/arch/arm/mach-pnx4008/sleep.S b/arch/arm/mach-pnx4008/sleep.S
deleted file mode 100644
index f4eed49..0000000
--- a/arch/arm/mach-pnx4008/sleep.S
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * linux/arch/arm/mach-pnx4008/sleep.S
- *
- * PNX4008 support for STOP mode and SDRAM self-refresh
- *
- * Authors: Dmitry Chigirev, Vitaly Wool <source@mvista.com>
- *
- * 2005 (c) MontaVista Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-
-#include <linux/linkage.h>
-#include <asm/assembler.h>
-#include <mach/hardware.h>
-
-#define PWRMAN_VA_BASE IO_ADDRESS(PNX4008_PWRMAN_BASE)
-#define PWR_CTRL_REG_OFFS 0x44
-
-#define SDRAM_CFG_VA_BASE IO_ADDRESS(PNX4008_SDRAM_CFG_BASE)
-#define MPMC_STATUS_REG_OFFS 0x4
-
-		.text
-
-ENTRY(pnx4008_cpu_suspend)
-	@this function should be entered in Direct run mode.
-
-	@ save registers on stack
-	stmfd	sp!, {r0 - r6, lr}
-
-	@ setup Power Manager base address in r4
-	@ and put it's value in r5
-	mov	r4, #(PWRMAN_VA_BASE & 0xff000000)
-	orr	r4, r4, #(PWRMAN_VA_BASE & 0x00ff0000)
-	orr	r4, r4, #(PWRMAN_VA_BASE & 0x0000ff00)
-	orr	r4, r4, #(PWRMAN_VA_BASE & 0x000000ff)
-	ldr	r5, [r4, #PWR_CTRL_REG_OFFS]
-
-	@ setup SDRAM controller base address in r2
-	@ and put it's value in r3
-	mov	r2, #(SDRAM_CFG_VA_BASE & 0xff000000)
-	orr	r2, r2, #(SDRAM_CFG_VA_BASE & 0x00ff0000)
-	orr	r2, r2, #(SDRAM_CFG_VA_BASE & 0x0000ff00)
-	orr	r2, r2, #(SDRAM_CFG_VA_BASE & 0x000000ff)
-	ldr	r3, [r2, #MPMC_STATUS_REG_OFFS] @extra read - HW bug workaround
-
-	@ clear SDRAM self-refresh bit latch
-	and	r5, r5, #(~(1 << 8))
-	@ clear SDRAM self-refresh bit
-	and	r5, r5, #(~(1 << 9))
-	str	r5, [r4, #PWR_CTRL_REG_OFFS]
-
-	@ do save current bit settings in r1
-	mov	r1, r5
-
-	@ set SDRAM self-refresh bit
-	orr	r5, r5, #(1 << 9)
-	str	r5, [r4, #PWR_CTRL_REG_OFFS]
-
-	@ set SDRAM self-refresh bit latch
-	orr	r5, r5, #(1 << 8)
-	str	r5, [r4, #PWR_CTRL_REG_OFFS]
-
-	@ clear SDRAM self-refresh bit latch
-	and	r5, r5, #(~(1 << 8))
-	str	r5, [r4, #PWR_CTRL_REG_OFFS]
-
-	@ clear SDRAM self-refresh bit
-	and	r5, r5, #(~(1 << 9))
-	str	r5, [r4, #PWR_CTRL_REG_OFFS]
-
-	@ wait for SDRAM to get into self-refresh mode
-2:	ldr	r3, [r2, #MPMC_STATUS_REG_OFFS]
-	tst	r3, #(1 << 2)
-	beq	2b
-
-	@ to prepare SDRAM to get out of self-refresh mode after wakeup
-	orr	r5, r5, #(1 << 7)
-	str	r5, [r4, #PWR_CTRL_REG_OFFS]
-
-	@ do enter stop mode
-	orr	r5, r5, #(1 << 0)
-	str	r5, [r4, #PWR_CTRL_REG_OFFS]
-	nop
-	nop
-	nop
-	nop
-	nop
-	nop
-	nop
-	nop
-	nop
-
-	@ sleeping now...
-
-	@ coming out of STOP mode into Direct Run mode
-	@ clear STOP mode and SDRAM self-refresh bits
-	str	r1, [r4, #PWR_CTRL_REG_OFFS]
-
-	@ wait for SDRAM to get out self-refresh mode
-3:	ldr	r3, [r2, #MPMC_STATUS_REG_OFFS]
-	tst	r3, #5
-	bne	3b
-
-	@ restore regs and return
-	ldmfd   sp!, {r0 - r6, pc}
-
-ENTRY(pnx4008_cpu_suspend_sz)
-	.word	. - pnx4008_cpu_suspend
-
-ENTRY(pnx4008_cpu_standby)
-	@ save registers on stack
-	stmfd	sp!, {r0 - r6, lr}
-
-	@ setup Power Manager base address in r4
-	@ and put it's value in r5
-	mov	r4, #(PWRMAN_VA_BASE & 0xff000000)
-	orr	r4, r4, #(PWRMAN_VA_BASE & 0x00ff0000)
-	orr	r4, r4, #(PWRMAN_VA_BASE & 0x0000ff00)
-	orr	r4, r4, #(PWRMAN_VA_BASE & 0x000000ff)
-	ldr	r5, [r4, #PWR_CTRL_REG_OFFS]
-
-	@ setup SDRAM controller base address in r2
-	@ and put it's value in r3
-	mov	r2, #(SDRAM_CFG_VA_BASE & 0xff000000)
-	orr	r2, r2, #(SDRAM_CFG_VA_BASE & 0x00ff0000)
-	orr	r2, r2, #(SDRAM_CFG_VA_BASE & 0x0000ff00)
-	orr	r2, r2, #(SDRAM_CFG_VA_BASE & 0x000000ff)
-	ldr	r3, [r2, #MPMC_STATUS_REG_OFFS] @extra read - HW bug workaround
-
-	@ clear SDRAM self-refresh bit latch
-	and	r5, r5, #(~(1 << 8))
-	@ clear SDRAM self-refresh bit
-	and	r5, r5, #(~(1 << 9))
-	str	r5, [r4, #PWR_CTRL_REG_OFFS]
-
-	@ do save current bit settings in r1
-	mov	r1, r5
-
-	@ set SDRAM self-refresh bit
-	orr	r5, r5, #(1 << 9)
-	str	r5, [r4, #PWR_CTRL_REG_OFFS]
-
-	@ set SDRAM self-refresh bit latch
-	orr	r5, r5, #(1 << 8)
-	str	r5, [r4, #PWR_CTRL_REG_OFFS]
-
-	@ clear SDRAM self-refresh bit latch
-	and	r5, r5, #(~(1 << 8))
-	str	r5, [r4, #PWR_CTRL_REG_OFFS]
-
-	@ clear SDRAM self-refresh bit
-	and	r5, r5, #(~(1 << 9))
-	str	r5, [r4, #PWR_CTRL_REG_OFFS]
-
-	@ wait for SDRAM to get into self-refresh mode
-2:	ldr	r3, [r2, #MPMC_STATUS_REG_OFFS]
-	tst	r3, #(1 << 2)
-	beq	2b
-
-	@ set 'get out of self-refresh mode after wakeup' bit
-	orr	r5, r5, #(1 << 7)
-	str	r5, [r4, #PWR_CTRL_REG_OFFS]
-
-	mcr     p15, 0, r0, c7, c0, 4	@ kinda sleeping now...
-
-	@ set SDRAM self-refresh bit latch
-	orr	r5, r5, #(1 << 8)
-	str	r5, [r4, #PWR_CTRL_REG_OFFS]
-
-	@ clear SDRAM self-refresh bit latch
-	and	r5, r5, #(~(1 << 8))
-	str	r5, [r4, #PWR_CTRL_REG_OFFS]
-
-	@ wait for SDRAM to get out self-refresh mode
-3:	ldr	r3, [r2, #MPMC_STATUS_REG_OFFS]
-	tst	r3, #5
-	bne	3b
-
-	@ restore regs and return
-	ldmfd   sp!, {r0 - r6, pc}
-
-ENTRY(pnx4008_cpu_standby_sz)
-	.word	. - pnx4008_cpu_standby
-
-ENTRY(pnx4008_cache_clean_invalidate)
-	stmfd	sp!, {r0 - r6, lr}
-#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
-	mcr	p15, 0, ip, c7, c6, 0		@ invalidate D cache
-#else
-1:	mrc	p15, 0, r15, c7, c14, 3		@ test,clean,invalidate
-	bne     1b
-#endif
-	ldmfd   sp!, {r0 - r6, pc}
diff --git a/arch/arm/mach-pnx4008/time.c b/arch/arm/mach-pnx4008/time.c
deleted file mode 100644
index 0cfe8af..0000000
--- a/arch/arm/mach-pnx4008/time.c
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * arch/arm/mach-pnx4008/time.c
- *
- * PNX4008 Timers
- *
- * Authors: Vitaly Wool, Dmitry Chigirev, Grigory Tolstolytkin <source@mvista.com>
- *
- * 2005 (c) MontaVista Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/sched.h>
-#include <linux/spinlock.h>
-#include <linux/module.h>
-#include <linux/kallsyms.h>
-#include <linux/time.h>
-#include <linux/timex.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <asm/leds.h>
-#include <asm/mach/time.h>
-#include <asm/errno.h>
-
-#include "time.h"
-
-/*! Note: all timers are UPCOUNTING */
-
-/*!
- * Returns number of us since last clock interrupt.  Note that interrupts
- * will have been disabled by do_gettimeoffset()
- */
-static unsigned long pnx4008_gettimeoffset(void)
-{
-	u32 ticks_to_match =
-	    __raw_readl(HSTIM_MATCH0) - __raw_readl(HSTIM_COUNTER);
-	u32 elapsed = LATCH - ticks_to_match;
-	return (elapsed * (tick_nsec / 1000)) / LATCH;
-}
-
-/*!
- * IRQ handler for the timer
- */
-static irqreturn_t pnx4008_timer_interrupt(int irq, void *dev_id)
-{
-	if (__raw_readl(HSTIM_INT) & MATCH0_INT) {
-
-		do {
-			timer_tick();
-
-			/*
-			 * this algorithm takes care of possible delay
-			 * for this interrupt handling longer than a normal
-			 * timer period
-			 */
-			__raw_writel(__raw_readl(HSTIM_MATCH0) + LATCH,
-				     HSTIM_MATCH0);
-			__raw_writel(MATCH0_INT, HSTIM_INT);	/* clear interrupt */
-
-			/*
-			 * The goal is to keep incrementing HSTIM_MATCH0
-			 * register until HSTIM_MATCH0 indicates time after
-			 * what HSTIM_COUNTER indicates.
-			 */
-		} while ((signed)
-			 (__raw_readl(HSTIM_MATCH0) -
-			  __raw_readl(HSTIM_COUNTER)) < 0);
-	}
-
-	return IRQ_HANDLED;
-}
-
-static struct irqaction pnx4008_timer_irq = {
-	.name = "PNX4008 Tick Timer",
-	.flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
-	.handler = pnx4008_timer_interrupt
-};
-
-/*!
- * Set up timer and timer interrupt.
- */
-static __init void pnx4008_setup_timer(void)
-{
-	__raw_writel(RESET_COUNT, MSTIM_CTRL);
-	while (__raw_readl(MSTIM_COUNTER)) ;	/* wait for reset to complete. 100% guarantee event */
-	__raw_writel(0, MSTIM_CTRL);	/* stop the timer */
-	__raw_writel(0, MSTIM_MCTRL);
-
-	__raw_writel(RESET_COUNT, HSTIM_CTRL);
-	while (__raw_readl(HSTIM_COUNTER)) ;	/* wait for reset to complete. 100% guarantee event */
-	__raw_writel(0, HSTIM_CTRL);
-	__raw_writel(0, HSTIM_MCTRL);
-	__raw_writel(0, HSTIM_CCR);
-	__raw_writel(12, HSTIM_PMATCH);	/* scale down to 1 MHZ */
-	__raw_writel(LATCH, HSTIM_MATCH0);
-	__raw_writel(MR0_INT, HSTIM_MCTRL);
-
-	setup_irq(HSTIMER_INT, &pnx4008_timer_irq);
-
-	__raw_writel(COUNT_ENAB | DEBUG_EN, HSTIM_CTRL);	/*start timer, stop when JTAG active */
-}
-
-/* Timer Clock Control in PM register */
-#define TIMCLK_CTRL_REG  IO_ADDRESS((PNX4008_PWRMAN_BASE + 0xBC))
-#define WATCHDOG_CLK_EN                   1
-#define TIMER_CLK_EN                      2	/* HS and MS timers? */
-
-static u32 timclk_ctrl_reg_save;
-
-void pnx4008_timer_suspend(void)
-{
-	timclk_ctrl_reg_save = __raw_readl(TIMCLK_CTRL_REG);
-	__raw_writel(0, TIMCLK_CTRL_REG);	/* disable timers */
-}
-
-void pnx4008_timer_resume(void)
-{
-	__raw_writel(timclk_ctrl_reg_save, TIMCLK_CTRL_REG);	/* enable timers */
-}
-
-struct sys_timer pnx4008_timer = {
-	.init = pnx4008_setup_timer,
-	.offset = pnx4008_gettimeoffset,
-	.suspend = pnx4008_timer_suspend,
-	.resume = pnx4008_timer_resume,
-};
-
diff --git a/arch/arm/mach-pnx4008/time.h b/arch/arm/mach-pnx4008/time.h
deleted file mode 100644
index 75e88c5..0000000
--- a/arch/arm/mach-pnx4008/time.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * arch/arm/mach-pnx4008/include/mach/timex.h
- *
- * PNX4008 timers header file
- *
- * Author: Dmitry Chigirev <source@mvista.com>
- *
- * 2005 (c) MontaVista Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-#ifndef PNX_TIME_H
-#define PNX_TIME_H
-
-#include <linux/io.h>
-#include <mach/hardware.h>
-
-#define TICKS2USECS(x)	(x)
-
-/* MilliSecond Timer - Chapter 21 Page 202 */
-
-#define MSTIM_INT     IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x0))
-#define MSTIM_CTRL    IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x4))
-#define MSTIM_COUNTER IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x8))
-#define MSTIM_MCTRL   IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x14))
-#define MSTIM_MATCH0  IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x18))
-#define MSTIM_MATCH1  IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x1c))
-
-/* High Speed Timer - Chpater 22, Page 205 */
-
-#define HSTIM_INT     IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x0))
-#define HSTIM_CTRL    IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x4))
-#define HSTIM_COUNTER IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x8))
-#define HSTIM_PMATCH  IO_ADDRESS((PNX4008_HSTIMER_BASE + 0xC))
-#define HSTIM_PCOUNT  IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x10))
-#define HSTIM_MCTRL   IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x14))
-#define HSTIM_MATCH0  IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x18))
-#define HSTIM_MATCH1  IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x1c))
-#define HSTIM_MATCH2  IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x20))
-#define HSTIM_CCR     IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x28))
-#define HSTIM_CR0     IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x2C))
-#define HSTIM_CR1     IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x30))
-
-/* IMPORTANT: both timers are UPCOUNTING */
-
-/* xSTIM_MCTRL bit definitions */
-#define MR0_INT        1
-#define RESET_COUNT0   (1<<1)
-#define STOP_COUNT0    (1<<2)
-#define MR1_INT        (1<<3)
-#define RESET_COUNT1   (1<<4)
-#define STOP_COUNT1    (1<<5)
-#define MR2_INT        (1<<6)
-#define RESET_COUNT2   (1<<7)
-#define STOP_COUNT2    (1<<8)
-
-/* xSTIM_CTRL bit definitions */
-#define COUNT_ENAB     1
-#define RESET_COUNT    (1<<1)
-#define DEBUG_EN       (1<<2)
-
-/* xSTIM_INT bit definitions */
-#define MATCH0_INT     1
-#define MATCH1_INT     (1<<1)
-#define MATCH2_INT     (1<<2)
-#define RTC_TICK0      (1<<4)
-#define RTC_TICK1      (1<<5)
-
-#endif
diff --git a/arch/arm/mach-prima2/Kconfig b/arch/arm/mach-prima2/Kconfig
new file mode 100644
index 0000000..41fc853
--- /dev/null
+++ b/arch/arm/mach-prima2/Kconfig
@@ -0,0 +1,19 @@
+if ARCH_SIRF
+
+menu "CSR SiRF primaII/Marco/Polo Specific Features"
+
+config ARCH_PRIMA2
+	bool "CSR SiRFSoC PRIMA2 ARM Cortex A9 Platform"
+	default y
+	select CPU_V7
+	select ZONE_DMA
+	select SIRF_IRQ
+	help
+          Support for CSR SiRFSoC ARM Cortex A9 Platform
+
+endmenu
+
+config SIRF_IRQ
+	bool
+
+endif
diff --git a/arch/arm/mach-prima2/Makefile b/arch/arm/mach-prima2/Makefile
index 13dd160..fc9ce22 100644
--- a/arch/arm/mach-prima2/Makefile
+++ b/arch/arm/mach-prima2/Makefile
@@ -1,9 +1,8 @@
 obj-y := timer.o
-obj-y += irq.o
-obj-y += clock.o
 obj-y += rstc.o
-obj-y += prima2.o
+obj-y += common.o
 obj-y += rtciobrg.o
 obj-$(CONFIG_DEBUG_LL) += lluart.o
 obj-$(CONFIG_CACHE_L2X0) += l2x0.o
 obj-$(CONFIG_SUSPEND) += pm.o sleep.o
+obj-$(CONFIG_SIRF_IRQ) += irq.o
diff --git a/arch/arm/mach-prima2/clock.c b/arch/arm/mach-prima2/clock.c
deleted file mode 100644
index aebad7e..0000000
--- a/arch/arm/mach-prima2/clock.c
+++ /dev/null
@@ -1,510 +0,0 @@
-/*
- * Clock tree for CSR SiRFprimaII
- *
- * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
- *
- * Licensed under GPLv2 or later.
- */
-
-#include <linux/module.h>
-#include <linux/bitops.h>
-#include <linux/err.h>
-#include <linux/errno.h>
-#include <linux/io.h>
-#include <linux/clkdev.h>
-#include <linux/clk.h>
-#include <linux/spinlock.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <asm/mach/map.h>
-#include <mach/map.h>
-
-#define SIRFSOC_CLKC_CLK_EN0    0x0000
-#define SIRFSOC_CLKC_CLK_EN1    0x0004
-#define SIRFSOC_CLKC_REF_CFG    0x0014
-#define SIRFSOC_CLKC_CPU_CFG    0x0018
-#define SIRFSOC_CLKC_MEM_CFG    0x001c
-#define SIRFSOC_CLKC_SYS_CFG    0x0020
-#define SIRFSOC_CLKC_IO_CFG     0x0024
-#define SIRFSOC_CLKC_DSP_CFG    0x0028
-#define SIRFSOC_CLKC_GFX_CFG    0x002c
-#define SIRFSOC_CLKC_MM_CFG     0x0030
-#define SIRFSOC_LKC_LCD_CFG     0x0034
-#define SIRFSOC_CLKC_MMC_CFG    0x0038
-#define SIRFSOC_CLKC_PLL1_CFG0  0x0040
-#define SIRFSOC_CLKC_PLL2_CFG0  0x0044
-#define SIRFSOC_CLKC_PLL3_CFG0  0x0048
-#define SIRFSOC_CLKC_PLL1_CFG1  0x004c
-#define SIRFSOC_CLKC_PLL2_CFG1  0x0050
-#define SIRFSOC_CLKC_PLL3_CFG1  0x0054
-#define SIRFSOC_CLKC_PLL1_CFG2  0x0058
-#define SIRFSOC_CLKC_PLL2_CFG2  0x005c
-#define SIRFSOC_CLKC_PLL3_CFG2  0x0060
-
-#define SIRFSOC_CLOCK_VA_BASE		SIRFSOC_VA(0x005000)
-
-#define KHZ     1000
-#define MHZ     (KHZ * KHZ)
-
-struct clk_ops {
-	unsigned long (*get_rate)(struct clk *clk);
-	long (*round_rate)(struct clk *clk, unsigned long rate);
-	int (*set_rate)(struct clk *clk, unsigned long rate);
-	int (*enable)(struct clk *clk);
-	int (*disable)(struct clk *clk);
-	struct clk *(*get_parent)(struct clk *clk);
-	int (*set_parent)(struct clk *clk, struct clk *parent);
-};
-
-struct clk {
-	struct clk *parent;     /* parent clk */
-	unsigned long rate;     /* clock rate in Hz */
-	signed char usage;      /* clock enable count */
-	signed char enable_bit; /* enable bit: 0 ~ 63 */
-	unsigned short regofs;  /* register offset */
-	struct clk_ops *ops;    /* clock operation */
-};
-
-static DEFINE_SPINLOCK(clocks_lock);
-
-static inline unsigned long clkc_readl(unsigned reg)
-{
-	return readl(SIRFSOC_CLOCK_VA_BASE + reg);
-}
-
-static inline void clkc_writel(u32 val, unsigned reg)
-{
-	writel(val, SIRFSOC_CLOCK_VA_BASE + reg);
-}
-
-/*
- * osc_rtc - real time oscillator - 32.768KHz
- * osc_sys - high speed oscillator - 26MHz
- */
-
-static struct clk clk_rtc = {
-	.rate = 32768,
-};
-
-static struct clk clk_osc = {
-	.rate = 26 * MHZ,
-};
-
-/*
- * std pll
- */
-static unsigned long std_pll_get_rate(struct clk *clk)
-{
-	unsigned long fin = clk_get_rate(clk->parent);
-	u32 regcfg2 = clk->regofs + SIRFSOC_CLKC_PLL1_CFG2 -
-		SIRFSOC_CLKC_PLL1_CFG0;
-
-	if (clkc_readl(regcfg2) & BIT(2)) {
-		/* pll bypass mode */
-		clk->rate = fin;
-	} else {
-		/* fout = fin * nf / nr / od */
-		u32 cfg0 = clkc_readl(clk->regofs);
-		u32 nf = (cfg0 & (BIT(13) - 1)) + 1;
-		u32 nr = ((cfg0 >> 13) & (BIT(6) - 1)) + 1;
-		u32 od = ((cfg0 >> 19) & (BIT(4) - 1)) + 1;
-		WARN_ON(fin % MHZ);
-		clk->rate = fin / MHZ * nf / nr / od * MHZ;
-	}
-
-	return clk->rate;
-}
-
-static int std_pll_set_rate(struct clk *clk, unsigned long rate)
-{
-	unsigned long fin, nf, nr, od, reg;
-
-	/*
-	 * fout = fin * nf / (nr * od);
-	 * set od = 1, nr = fin/MHz, so fout = nf * MHz
-	 */
-
-	nf = rate / MHZ;
-	if (unlikely((rate % MHZ) || nf > BIT(13) || nf < 1))
-		return -EINVAL;
-
-	fin = clk_get_rate(clk->parent);
-	BUG_ON(fin < MHZ);
-
-	nr = fin / MHZ;
-	BUG_ON((fin % MHZ) || nr > BIT(6));
-
-	od = 1;
-
-	reg = (nf - 1) | ((nr - 1) << 13) | ((od - 1) << 19);
-	clkc_writel(reg, clk->regofs);
-
-	reg = clk->regofs + SIRFSOC_CLKC_PLL1_CFG1 - SIRFSOC_CLKC_PLL1_CFG0;
-	clkc_writel((nf >> 1) - 1, reg);
-
-	reg = clk->regofs + SIRFSOC_CLKC_PLL1_CFG2 - SIRFSOC_CLKC_PLL1_CFG0;
-	while (!(clkc_readl(reg) & BIT(6)))
-		cpu_relax();
-
-	clk->rate = 0; /* set to zero will force recalculation */
-	return 0;
-}
-
-static struct clk_ops std_pll_ops = {
-	.get_rate = std_pll_get_rate,
-	.set_rate = std_pll_set_rate,
-};
-
-static struct clk clk_pll1 = {
-	.parent = &clk_osc,
-	.regofs = SIRFSOC_CLKC_PLL1_CFG0,
-	.ops = &std_pll_ops,
-};
-
-static struct clk clk_pll2 = {
-	.parent = &clk_osc,
-	.regofs = SIRFSOC_CLKC_PLL2_CFG0,
-	.ops = &std_pll_ops,
-};
-
-static struct clk clk_pll3 = {
-	.parent = &clk_osc,
-	.regofs = SIRFSOC_CLKC_PLL3_CFG0,
-	.ops = &std_pll_ops,
-};
-
-/*
- * clock domains - cpu, mem, sys/io
- */
-
-static struct clk clk_mem;
-
-static struct clk *dmn_get_parent(struct clk *clk)
-{
-	struct clk *clks[] = {
-		&clk_osc, &clk_rtc, &clk_pll1, &clk_pll2, &clk_pll3
-	};
-	u32 cfg = clkc_readl(clk->regofs);
-	WARN_ON((cfg & (BIT(3) - 1)) > 4);
-	return clks[cfg & (BIT(3) - 1)];
-}
-
-static int dmn_set_parent(struct clk *clk, struct clk *parent)
-{
-	const struct clk *clks[] = {
-		&clk_osc, &clk_rtc, &clk_pll1, &clk_pll2, &clk_pll3
-	};
-	u32 cfg = clkc_readl(clk->regofs);
-	int i;
-	for (i = 0; i < ARRAY_SIZE(clks); i++) {
-		if (clks[i] == parent) {
-			cfg &= ~(BIT(3) - 1);
-			clkc_writel(cfg | i, clk->regofs);
-			/* BIT(3) - switching status: 1 - busy, 0 - done */
-			while (clkc_readl(clk->regofs) & BIT(3))
-				cpu_relax();
-			return 0;
-		}
-	}
-	return -EINVAL;
-}
-
-static unsigned long dmn_get_rate(struct clk *clk)
-{
-	unsigned long fin = clk_get_rate(clk->parent);
-	u32 cfg = clkc_readl(clk->regofs);
-	if (cfg & BIT(24)) {
-		/* fcd bypass mode */
-		clk->rate = fin;
-	} else {
-		/*
-		 * wait count: bit[19:16], hold count: bit[23:20]
-		 */
-		u32 wait = (cfg >> 16) & (BIT(4) - 1);
-		u32 hold = (cfg >> 20) & (BIT(4) - 1);
-
-		clk->rate = fin / (wait + hold + 2);
-	}
-
-	return clk->rate;
-}
-
-static int dmn_set_rate(struct clk *clk, unsigned long rate)
-{
-	unsigned long fin;
-	unsigned ratio, wait, hold, reg;
-	unsigned bits = (clk == &clk_mem) ? 3 : 4;
-
-	fin = clk_get_rate(clk->parent);
-	ratio = fin / rate;
-
-	if (unlikely(ratio < 2 || ratio > BIT(bits + 1)))
-		return -EINVAL;
-
-	WARN_ON(fin % rate);
-
-	wait = (ratio >> 1) - 1;
-	hold = ratio - wait - 2;
-
-	reg = clkc_readl(clk->regofs);
-	reg &= ~(((BIT(bits) - 1) << 16) | ((BIT(bits) - 1) << 20));
-	reg |= (wait << 16) | (hold << 20) | BIT(25);
-	clkc_writel(reg, clk->regofs);
-
-	/* waiting FCD been effective */
-	while (clkc_readl(clk->regofs) & BIT(25))
-		cpu_relax();
-
-	clk->rate = 0; /* set to zero will force recalculation */
-
-	return 0;
-}
-
-/*
- * cpu clock has no FCD register in Prima2, can only change pll
- */
-static int cpu_set_rate(struct clk *clk, unsigned long rate)
-{
-	int ret1, ret2;
-	struct clk *cur_parent, *tmp_parent;
-
-	cur_parent = dmn_get_parent(clk);
-	BUG_ON(cur_parent == NULL || cur_parent->usage > 1);
-
-	/* switch to tmp pll before setting parent clock's rate */
-	tmp_parent = cur_parent == &clk_pll1 ? &clk_pll2 : &clk_pll1;
-	ret1 = dmn_set_parent(clk, tmp_parent);
-	BUG_ON(ret1);
-
-	ret2 = clk_set_rate(cur_parent, rate);
-
-	ret1 = dmn_set_parent(clk, cur_parent);
-
-	clk->rate = 0; /* set to zero will force recalculation */
-
-	return ret2 ? ret2 : ret1;
-}
-
-static struct clk_ops cpu_ops = {
-	.get_parent = dmn_get_parent,
-	.set_parent = dmn_set_parent,
-	.set_rate = cpu_set_rate,
-};
-
-static struct clk clk_cpu = {
-	.parent = &clk_pll1,
-	.regofs = SIRFSOC_CLKC_CPU_CFG,
-	.ops = &cpu_ops,
-};
-
-
-static struct clk_ops msi_ops = {
-	.set_rate = dmn_set_rate,
-	.get_rate = dmn_get_rate,
-	.set_parent = dmn_set_parent,
-	.get_parent = dmn_get_parent,
-};
-
-static struct clk clk_mem = {
-	.parent = &clk_pll2,
-	.regofs = SIRFSOC_CLKC_MEM_CFG,
-	.ops = &msi_ops,
-};
-
-static struct clk clk_sys = {
-	.parent = &clk_pll3,
-	.regofs = SIRFSOC_CLKC_SYS_CFG,
-	.ops = &msi_ops,
-};
-
-static struct clk clk_io = {
-	.parent = &clk_pll3,
-	.regofs = SIRFSOC_CLKC_IO_CFG,
-	.ops = &msi_ops,
-};
-
-/*
- * on-chip clock sets
- */
-static struct clk_lookup onchip_clks[] = {
-	{
-		.dev_id = "rtc",
-		.clk = &clk_rtc,
-	}, {
-		.dev_id = "osc",
-		.clk = &clk_osc,
-	}, {
-		.dev_id = "pll1",
-		.clk = &clk_pll1,
-	}, {
-		.dev_id = "pll2",
-		.clk = &clk_pll2,
-	}, {
-		.dev_id = "pll3",
-		.clk = &clk_pll3,
-	}, {
-		.dev_id = "cpu",
-		.clk = &clk_cpu,
-	}, {
-		.dev_id = "mem",
-		.clk = &clk_mem,
-	}, {
-		.dev_id = "sys",
-		.clk = &clk_sys,
-	}, {
-		.dev_id = "io",
-		.clk = &clk_io,
-	},
-};
-
-int clk_enable(struct clk *clk)
-{
-	unsigned long flags;
-
-	if (unlikely(IS_ERR_OR_NULL(clk)))
-		return -EINVAL;
-
-	if (clk->parent)
-		clk_enable(clk->parent);
-
-	spin_lock_irqsave(&clocks_lock, flags);
-	if (!clk->usage++ && clk->ops && clk->ops->enable)
-		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;
-
-	if (unlikely(IS_ERR_OR_NULL(clk)))
-		return;
-
-	WARN_ON(!clk->usage);
-
-	spin_lock_irqsave(&clocks_lock, flags);
-	if (--clk->usage == 0 && clk->ops && clk->ops->disable)
-		clk->ops->disable(clk);
-	spin_unlock_irqrestore(&clocks_lock, flags);
-
-	if (clk->parent)
-		clk_disable(clk->parent);
-}
-EXPORT_SYMBOL(clk_disable);
-
-unsigned long clk_get_rate(struct clk *clk)
-{
-	if (unlikely(IS_ERR_OR_NULL(clk)))
-		return 0;
-
-	if (clk->rate)
-		return clk->rate;
-
-	if (clk->ops && clk->ops->get_rate)
-		return clk->ops->get_rate(clk);
-
-	return clk_get_rate(clk->parent);
-}
-EXPORT_SYMBOL(clk_get_rate);
-
-long clk_round_rate(struct clk *clk, unsigned long rate)
-{
-	if (unlikely(IS_ERR_OR_NULL(clk)))
-		return 0;
-
-	if (clk->ops && clk->ops->round_rate)
-		return clk->ops->round_rate(clk, rate);
-
-	return 0;
-}
-EXPORT_SYMBOL(clk_round_rate);
-
-int clk_set_rate(struct clk *clk, unsigned long rate)
-{
-	if (unlikely(IS_ERR_OR_NULL(clk)))
-		return -EINVAL;
-
-	if (!clk->ops || !clk->ops->set_rate)
-		return -EINVAL;
-
-	return clk->ops->set_rate(clk, rate);
-}
-EXPORT_SYMBOL(clk_set_rate);
-
-int clk_set_parent(struct clk *clk, struct clk *parent)
-{
-	int ret;
-	unsigned long flags;
-
-	if (unlikely(IS_ERR_OR_NULL(clk)))
-		return -EINVAL;
-
-	if (!clk->ops || !clk->ops->set_parent)
-		return -EINVAL;
-
-	spin_lock_irqsave(&clocks_lock, flags);
-	ret = clk->ops->set_parent(clk, parent);
-	if (!ret) {
-		parent->usage += clk->usage;
-		clk->parent->usage -= clk->usage;
-		BUG_ON(clk->parent->usage < 0);
-		clk->parent = parent;
-	}
-	spin_unlock_irqrestore(&clocks_lock, flags);
-	return ret;
-}
-EXPORT_SYMBOL(clk_set_parent);
-
-struct clk *clk_get_parent(struct clk *clk)
-{
-	unsigned long flags;
-
-	if (unlikely(IS_ERR_OR_NULL(clk)))
-		return NULL;
-
-	if (!clk->ops || !clk->ops->get_parent)
-		return clk->parent;
-
-	spin_lock_irqsave(&clocks_lock, flags);
-	clk->parent = clk->ops->get_parent(clk);
-	spin_unlock_irqrestore(&clocks_lock, flags);
-	return clk->parent;
-}
-EXPORT_SYMBOL(clk_get_parent);
-
-static void __init sirfsoc_clk_init(void)
-{
-	clkdev_add_table(onchip_clks, ARRAY_SIZE(onchip_clks));
-}
-
-static struct of_device_id clkc_ids[] = {
-	{ .compatible = "sirf,prima2-clkc" },
-	{},
-};
-
-void __init sirfsoc_of_clk_init(void)
-{
-	struct device_node *np;
-	struct resource res;
-	struct map_desc sirfsoc_clkc_iodesc = {
-		.virtual = SIRFSOC_CLOCK_VA_BASE,
-		.type    = MT_DEVICE,
-	};
-
-	np = of_find_matching_node(NULL, clkc_ids);
-	if (!np)
-		panic("unable to find compatible clkc node in dtb\n");
-
-	if (of_address_to_resource(np, 0, &res))
-		panic("unable to find clkc range in dtb");
-	of_node_put(np);
-
-	sirfsoc_clkc_iodesc.pfn = __phys_to_pfn(res.start);
-	sirfsoc_clkc_iodesc.length = 1 + res.end - res.start;
-
-	iotable_init(&sirfsoc_clkc_iodesc, 1);
-
-	sirfsoc_clk_init();
-}
diff --git a/arch/arm/mach-prima2/common.c b/arch/arm/mach-prima2/common.c
new file mode 100644
index 0000000..f25a541
--- /dev/null
+++ b/arch/arm/mach-prima2/common.c
@@ -0,0 +1,50 @@
+/*
+ * Defines machines for CSR SiRFprimaII
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <asm/sizes.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include "common.h"
+
+static struct of_device_id sirfsoc_of_bus_ids[] __initdata = {
+	{ .compatible = "simple-bus", },
+	{},
+};
+
+void __init sirfsoc_mach_init(void)
+{
+	of_platform_bus_probe(NULL, sirfsoc_of_bus_ids, NULL);
+}
+
+void __init sirfsoc_init_late(void)
+{
+	sirfsoc_pm_init();
+}
+
+#ifdef CONFIG_ARCH_PRIMA2
+static const char *prima2_dt_match[] __initdata = {
+       "sirf,prima2",
+       NULL
+};
+
+DT_MACHINE_START(PRIMA2_DT, "Generic PRIMA2 (Flattened Device Tree)")
+	/* Maintainer: Barry Song <baohua.song@csr.com> */
+	.map_io         = sirfsoc_map_lluart,
+	.init_irq	= sirfsoc_of_irq_init,
+	.timer		= &sirfsoc_timer,
+	.dma_zone_size	= SZ_256M,
+	.init_machine	= sirfsoc_mach_init,
+	.init_late	= sirfsoc_init_late,
+	.dt_compat      = prima2_dt_match,
+	.restart	= sirfsoc_restart,
+MACHINE_END
+#endif
diff --git a/arch/arm/mach-prima2/include/mach/uncompress.h b/arch/arm/mach-prima2/include/mach/uncompress.h
index 83125c6..0c898fc 100644
--- a/arch/arm/mach-prima2/include/mach/uncompress.h
+++ b/arch/arm/mach-prima2/include/mach/uncompress.h
@@ -25,11 +25,11 @@ static __inline__ void putc(char c)
 	 * during kernel decompression, all mappings are flat:
 	 *  virt_addr == phys_addr
 	 */
-	while (__raw_readl(SIRFSOC_UART1_PA_BASE + SIRFSOC_UART_TXFIFO_STATUS)
+	while (__raw_readl((void __iomem *)SIRFSOC_UART1_PA_BASE + SIRFSOC_UART_TXFIFO_STATUS)
 		& SIRFSOC_UART1_TXFIFO_FULL)
 		barrier();
 
-	__raw_writel(c, SIRFSOC_UART1_PA_BASE + SIRFSOC_UART_TXFIFO_DATA);
+	__raw_writel(c, (void __iomem *)SIRFSOC_UART1_PA_BASE + SIRFSOC_UART_TXFIFO_DATA);
 }
 
 static inline void flush(void)
diff --git a/arch/arm/mach-prima2/irq.c b/arch/arm/mach-prima2/irq.c
index a7b9415..7dee917 100644
--- a/arch/arm/mach-prima2/irq.c
+++ b/arch/arm/mach-prima2/irq.c
@@ -63,7 +63,7 @@ void __init sirfsoc_of_irq_init(void)
 
 	np = of_find_matching_node(NULL, intc_ids);
 	if (!np)
-		panic("unable to find compatible intc node in dtb\n");
+		return;
 
 	sirfsoc_intc_base = of_iomap(np, 0);
 	if (!sirfsoc_intc_base)
diff --git a/arch/arm/mach-prima2/prima2.c b/arch/arm/mach-prima2/prima2.c
deleted file mode 100644
index 8f0429d..0000000
--- a/arch/arm/mach-prima2/prima2.c
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Defines machines for CSR SiRFprimaII
- *
- * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
- *
- * Licensed under GPLv2 or later.
- */
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <asm/sizes.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <linux/of.h>
-#include <linux/of_platform.h>
-#include "common.h"
-
-static struct of_device_id sirfsoc_of_bus_ids[] __initdata = {
-	{ .compatible = "simple-bus", },
-	{},
-};
-
-void __init sirfsoc_mach_init(void)
-{
-	of_platform_bus_probe(NULL, sirfsoc_of_bus_ids, NULL);
-}
-
-void __init sirfsoc_init_late(void)
-{
-	sirfsoc_pm_init();
-}
-
-static const char *prima2cb_dt_match[] __initdata = {
-       "sirf,prima2-cb",
-       NULL
-};
-
-MACHINE_START(PRIMA2_EVB, "prima2cb")
-	/* Maintainer: Barry Song <baohua.song@csr.com> */
-	.atag_offset	= 0x100,
-	.init_early     = sirfsoc_of_clk_init,
-	.map_io         = sirfsoc_map_lluart,
-	.init_irq	= sirfsoc_of_irq_init,
-	.timer		= &sirfsoc_timer,
-	.dma_zone_size	= SZ_256M,
-	.init_machine	= sirfsoc_mach_init,
-	.init_late	= sirfsoc_init_late,
-	.dt_compat      = prima2cb_dt_match,
-	.restart	= sirfsoc_restart,
-MACHINE_END
diff --git a/arch/arm/mach-prima2/timer.c b/arch/arm/mach-prima2/timer.c
index f224107..d95bf25 100644
--- a/arch/arm/mach-prima2/timer.c
+++ b/arch/arm/mach-prima2/timer.c
@@ -21,6 +21,8 @@
 #include <asm/sched_clock.h>
 #include <asm/mach/time.h>
 
+#include "common.h"
+
 #define SIRFSOC_TIMER_COUNTER_LO	0x0000
 #define SIRFSOC_TIMER_COUNTER_HI	0x0004
 #define SIRFSOC_TIMER_MATCH_0		0x0008
@@ -188,9 +190,13 @@ static void __init sirfsoc_clockevent_init(void)
 static void __init sirfsoc_timer_init(void)
 {
 	unsigned long rate;
+	struct clk *clk;
+
+	/* initialize clocking early, we want to set the OS timer */
+	sirfsoc_of_clk_init();
 
 	/* timer's input clock is io clock */
-	struct clk *clk = clk_get_sys("io", NULL);
+	clk = clk_get_sys("io", NULL);
 
 	BUG_ON(IS_ERR(clk));
 
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index fe2d1f8..8e6288d 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -25,6 +25,18 @@ config PXA_V7_MACH_AUTO
 if !ARCH_PXA_V7
 comment "Intel/Marvell Dev Platforms (sorted by hardware release time)"
 
+config MACH_PXA3XX_DT
+	bool "Support PXA3xx platforms from device tree"
+	select PXA3xx
+	select CPU_PXA300
+	select POWER_SUPPLY
+	select HAVE_PWM
+	select USE_OF
+	help
+	  Include support for Marvell PXA3xx based platforms using
+	  the device tree. Needn't select any other machine while
+	  MACH_PXA3XX_DT is enabled.
+
 config ARCH_LUBBOCK
 	bool "Intel DBPXA250 Development Platform (aka Lubbock)"
 	select PXA25x
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index be0f7df..ee88d6e 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -26,6 +26,9 @@ obj-$(CONFIG_CPU_PXA930)	+= pxa930.o
 
 # NOTE: keep the order of boards in accordance to their order in Kconfig
 
+# Device Tree support
+obj-$(CONFIG_MACH_PXA3XX_DT)	+= pxa-dt.o
+
 # Intel/Marvell Dev Platforms
 obj-$(CONFIG_ARCH_LUBBOCK)	+= lubbock.o
 obj-$(CONFIG_MACH_MAINSTONE)	+= mainstone.o
@@ -95,12 +98,4 @@ obj-$(CONFIG_MACH_RAUMFELD_CONNECTOR)	+= raumfeld.o
 obj-$(CONFIG_MACH_RAUMFELD_SPEAKER)	+= raumfeld.o
 obj-$(CONFIG_MACH_ZIPIT2)	+= z2.o
 
-# Support for blinky lights
-led-y := leds.o
-led-$(CONFIG_ARCH_LUBBOCK)	+= leds-lubbock.o
-led-$(CONFIG_MACH_MAINSTONE)	+= leds-mainstone.o
-led-$(CONFIG_ARCH_PXA_IDP)	+= leds-idp.o
-
-obj-$(CONFIG_LEDS)		+= $(led-y)
-
 obj-$(CONFIG_TOSA_BT)		+= tosa-bt.o
diff --git a/arch/arm/mach-pxa/am200epd.c b/arch/arm/mach-pxa/am200epd.c
index ccdac4b..ffa6d81 100644
--- a/arch/arm/mach-pxa/am200epd.c
+++ b/arch/arm/mach-pxa/am200epd.c
@@ -32,7 +32,7 @@
 
 #include <mach/pxa25x.h>
 #include <mach/gumstix.h>
-#include <mach/pxafb.h>
+#include <linux/platform_data/video-pxafb.h>
 
 #include "generic.h"
 
diff --git a/arch/arm/mach-pxa/am300epd.c b/arch/arm/mach-pxa/am300epd.c
index 76c4b94..3dfec1e 100644
--- a/arch/arm/mach-pxa/am300epd.c
+++ b/arch/arm/mach-pxa/am300epd.c
@@ -30,7 +30,7 @@
 
 #include <mach/gumstix.h>
 #include <mach/mfp-pxa25x.h>
-#include <mach/pxafb.h>
+#include <linux/platform_data/video-pxafb.h>
 
 #include "generic.h"
 
diff --git a/arch/arm/mach-pxa/balloon3.c b/arch/arm/mach-pxa/balloon3.c
index 9244493..2082293 100644
--- a/arch/arm/mach-pxa/balloon3.c
+++ b/arch/arm/mach-pxa/balloon3.c
@@ -45,12 +45,12 @@
 #include <mach/pxa27x.h>
 #include <mach/balloon3.h>
 #include <mach/audio.h>
-#include <mach/pxafb.h>
-#include <mach/mmc.h>
+#include <linux/platform_data/video-pxafb.h>
+#include <linux/platform_data/mmc-pxamci.h>
 #include <mach/udc.h>
 #include <mach/pxa27x-udc.h>
-#include <mach/irda.h>
-#include <mach/ohci.h>
+#include <linux/platform_data/irda-pxaficp.h>
+#include <linux/platform_data/usb-ohci-pxa27x.h>
 
 #include "generic.h"
 #include "devices.h"
diff --git a/arch/arm/mach-pxa/clock-pxa3xx.c b/arch/arm/mach-pxa/clock-pxa3xx.c
index 2a37a9a..d4e9499 100644
--- a/arch/arm/mach-pxa/clock-pxa3xx.c
+++ b/arch/arm/mach-pxa/clock-pxa3xx.c
@@ -127,8 +127,10 @@ void clk_pxa3xx_cken_enable(struct clk *clk)
 
 	if (clk->cken < 32)
 		CKENA |= mask;
-	else
+	else if (clk->cken < 64)
 		CKENB |= mask;
+	else
+		CKENC |= mask;
 }
 
 void clk_pxa3xx_cken_disable(struct clk *clk)
@@ -137,8 +139,10 @@ void clk_pxa3xx_cken_disable(struct clk *clk)
 
 	if (clk->cken < 32)
 		CKENA &= ~mask;
-	else
+	else if (clk->cken < 64)
 		CKENB &= ~mask;
+	else
+		CKENC &= ~mask;
 }
 
 const struct clkops clk_pxa3xx_cken_ops = {
diff --git a/arch/arm/mach-pxa/cm-x270.c b/arch/arm/mach-pxa/cm-x270.c
index 431ef56..2503db9 100644
--- a/arch/arm/mach-pxa/cm-x270.c
+++ b/arch/arm/mach-pxa/cm-x270.c
@@ -22,8 +22,8 @@
 #include <linux/spi/libertas_spi.h>
 
 #include <mach/pxa27x.h>
-#include <mach/ohci.h>
-#include <mach/mmc.h>
+#include <linux/platform_data/usb-ohci-pxa27x.h>
+#include <linux/platform_data/mmc-pxamci.h>
 
 #include "generic.h"
 
diff --git a/arch/arm/mach-pxa/cm-x2xx.c b/arch/arm/mach-pxa/cm-x2xx.c
index 8fa4ad2..fc3afc7 100644
--- a/arch/arm/mach-pxa/cm-x2xx.c
+++ b/arch/arm/mach-pxa/cm-x2xx.c
@@ -24,7 +24,7 @@
 #include <mach/pxa25x.h>
 #include <mach/pxa27x.h>
 #include <mach/audio.h>
-#include <mach/pxafb.h>
+#include <linux/platform_data/video-pxafb.h>
 #include <mach/smemc.h>
 
 #include <asm/hardware/it8152.h>
diff --git a/arch/arm/mach-pxa/cm-x300.c b/arch/arm/mach-pxa/cm-x300.c
index 3e4e9fe..cc2b23a 100644
--- a/arch/arm/mach-pxa/cm-x300.c
+++ b/arch/arm/mach-pxa/cm-x300.c
@@ -48,12 +48,12 @@
 
 #include <mach/pxa300.h>
 #include <mach/pxa27x-udc.h>
-#include <mach/pxafb.h>
-#include <mach/mmc.h>
-#include <mach/ohci.h>
-#include <plat/pxa3xx_nand.h>
+#include <linux/platform_data/video-pxafb.h>
+#include <linux/platform_data/mmc-pxamci.h>
+#include <linux/platform_data/usb-ohci-pxa27x.h>
+#include <linux/platform_data/mtd-nand-pxa3xx.h>
 #include <mach/audio.h>
-#include <mach/pxa3xx-u2d.h>
+#include <linux/platform_data/usb-pxa3xx-ulpi.h>
 
 #include <asm/mach/map.h>
 
diff --git a/arch/arm/mach-pxa/colibri-evalboard.c b/arch/arm/mach-pxa/colibri-evalboard.c
index d28e802..8404b24 100644
--- a/arch/arm/mach-pxa/colibri-evalboard.c
+++ b/arch/arm/mach-pxa/colibri-evalboard.c
@@ -23,8 +23,8 @@
 
 #include <mach/pxa27x.h>
 #include <mach/colibri.h>
-#include <mach/mmc.h>
-#include <mach/ohci.h>
+#include <linux/platform_data/mmc-pxamci.h>
+#include <linux/platform_data/usb-ohci-pxa27x.h>
 #include <mach/pxa27x-udc.h>
 
 #include "generic.h"
diff --git a/arch/arm/mach-pxa/colibri-pxa270-income.c b/arch/arm/mach-pxa/colibri-pxa270-income.c
index 248804b..2d4a7b4 100644
--- a/arch/arm/mach-pxa/colibri-pxa270-income.c
+++ b/arch/arm/mach-pxa/colibri-pxa270-income.c
@@ -27,11 +27,11 @@
 #include <asm/mach-types.h>
 
 #include <mach/hardware.h>
-#include <mach/mmc.h>
-#include <mach/ohci.h>
+#include <linux/platform_data/mmc-pxamci.h>
+#include <linux/platform_data/usb-ohci-pxa27x.h>
 #include <mach/pxa27x.h>
 #include <mach/pxa27x-udc.h>
-#include <mach/pxafb.h>
+#include <linux/platform_data/video-pxafb.h>
 
 #include "devices.h"
 #include "generic.h"
diff --git a/arch/arm/mach-pxa/colibri-pxa300.c b/arch/arm/mach-pxa/colibri-pxa300.c
index bb6def8..a9c9c16 100644
--- a/arch/arm/mach-pxa/colibri-pxa300.c
+++ b/arch/arm/mach-pxa/colibri-pxa300.c
@@ -24,8 +24,8 @@
 
 #include <mach/pxa300.h>
 #include <mach/colibri.h>
-#include <mach/ohci.h>
-#include <mach/pxafb.h>
+#include <linux/platform_data/usb-ohci-pxa27x.h>
+#include <linux/platform_data/video-pxafb.h>
 #include <mach/audio.h>
 
 #include "generic.h"
diff --git a/arch/arm/mach-pxa/colibri-pxa320.c b/arch/arm/mach-pxa/colibri-pxa320.c
index d88e7b3..25515cd 100644
--- a/arch/arm/mach-pxa/colibri-pxa320.c
+++ b/arch/arm/mach-pxa/colibri-pxa320.c
@@ -25,8 +25,8 @@
 
 #include <mach/pxa320.h>
 #include <mach/colibri.h>
-#include <mach/pxafb.h>
-#include <mach/ohci.h>
+#include <linux/platform_data/video-pxafb.h>
+#include <linux/platform_data/usb-ohci-pxa27x.h>
 #include <mach/audio.h>
 #include <mach/pxa27x-udc.h>
 #include <mach/udc.h>
diff --git a/arch/arm/mach-pxa/colibri-pxa3xx.c b/arch/arm/mach-pxa/colibri-pxa3xx.c
index 68cc75f..8240291 100644
--- a/arch/arm/mach-pxa/colibri-pxa3xx.c
+++ b/arch/arm/mach-pxa/colibri-pxa3xx.c
@@ -24,9 +24,9 @@
 #include <mach/pxa3xx-regs.h>
 #include <mach/mfp-pxa300.h>
 #include <mach/colibri.h>
-#include <mach/mmc.h>
-#include <mach/pxafb.h>
-#include <plat/pxa3xx_nand.h>
+#include <linux/platform_data/mmc-pxamci.h>
+#include <linux/platform_data/video-pxafb.h>
+#include <linux/platform_data/mtd-nand-pxa3xx.h>
 
 #include "generic.h"
 #include "devices.h"
diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c
index c1fe32d..7c83f52 100644
--- a/arch/arm/mach-pxa/corgi.c
+++ b/arch/arm/mach-pxa/corgi.c
@@ -46,8 +46,8 @@
 #include <asm/mach/irq.h>
 
 #include <mach/pxa25x.h>
-#include <mach/irda.h>
-#include <mach/mmc.h>
+#include <linux/platform_data/irda-pxaficp.h>
+#include <linux/platform_data/mmc-pxamci.h>
 #include <mach/udc.h>
 #include <mach/corgi.h>
 #include <mach/sharpsl_pm.h>
diff --git a/arch/arm/mach-pxa/csb726.c b/arch/arm/mach-pxa/csb726.c
index 67f0de3..7039f44 100644
--- a/arch/arm/mach-pxa/csb726.c
+++ b/arch/arm/mach-pxa/csb726.c
@@ -23,8 +23,8 @@
 #include <asm/mach/arch.h>
 #include <mach/csb726.h>
 #include <mach/pxa27x.h>
-#include <mach/mmc.h>
-#include <mach/ohci.h>
+#include <linux/platform_data/mmc-pxamci.h>
+#include <linux/platform_data/usb-ohci-pxa27x.h>
 #include <mach/audio.h>
 #include <mach/smemc.h>
 
diff --git a/arch/arm/mach-pxa/devices.c b/arch/arm/mach-pxa/devices.c
index 166eee5..ddaa04d 100644
--- a/arch/arm/mach-pxa/devices.c
+++ b/arch/arm/mach-pxa/devices.c
@@ -6,19 +6,18 @@
 #include <linux/spi/pxa2xx_spi.h>
 #include <linux/i2c/pxa-i2c.h>
 
-#include <asm/pmu.h>
 #include <mach/udc.h>
-#include <mach/pxa3xx-u2d.h>
-#include <mach/pxafb.h>
-#include <mach/mmc.h>
-#include <mach/irda.h>
+#include <linux/platform_data/usb-pxa3xx-ulpi.h>
+#include <linux/platform_data/video-pxafb.h>
+#include <linux/platform_data/mmc-pxamci.h>
+#include <linux/platform_data/irda-pxaficp.h>
 #include <mach/irqs.h>
-#include <mach/ohci.h>
-#include <plat/pxa27x_keypad.h>
-#include <mach/camera.h>
+#include <linux/platform_data/usb-ohci-pxa27x.h>
+#include <linux/platform_data/keypad-pxa27x.h>
+#include <linux/platform_data/camera-pxa.h>
 #include <mach/audio.h>
 #include <mach/hardware.h>
-#include <plat/pxa3xx_nand.h>
+#include <linux/platform_data/mtd-nand-pxa3xx.h>
 
 #include "devices.h"
 #include "generic.h"
@@ -42,7 +41,7 @@ static struct resource pxa_resource_pmu = {
 
 struct platform_device pxa_device_pmu = {
 	.name		= "arm-pmu",
-	.id		= ARM_PMU_DEVICE_CPU,
+	.id		= -1,
 	.resource	= &pxa_resource_pmu,
 	.num_resources	= 1,
 };
@@ -384,9 +383,24 @@ struct platform_device pxa_device_asoc_platform = {
 
 static u64 pxaficp_dmamask = ~(u32)0;
 
+static struct resource pxa_ir_resources[] = {
+	[0] = {
+		.start  = IRQ_STUART,
+		.end    = IRQ_STUART,
+		.flags  = IORESOURCE_IRQ,
+	},
+	[1] = {
+		.start  = IRQ_ICP,
+		.end    = IRQ_ICP,
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
 struct platform_device pxa_device_ficp = {
 	.name		= "pxa2xx-ir",
 	.id		= -1,
+	.num_resources	= ARRAY_SIZE(pxa_ir_resources),
+	.resource	= pxa_ir_resources,
 	.dev		= {
 		.dma_mask = &pxaficp_dmamask,
 		.coherent_dma_mask = 0xffffffff,
diff --git a/arch/arm/mach-pxa/em-x270.c b/arch/arm/mach-pxa/em-x270.c
index 97f82ad..1b64114 100644
--- a/arch/arm/mach-pxa/em-x270.c
+++ b/arch/arm/mach-pxa/em-x270.c
@@ -42,11 +42,11 @@
 #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 <plat/pxa27x_keypad.h>
-#include <mach/camera.h>
+#include <linux/platform_data/video-pxafb.h>
+#include <linux/platform_data/usb-ohci-pxa27x.h>
+#include <linux/platform_data/mmc-pxamci.h>
+#include <linux/platform_data/keypad-pxa27x.h>
+#include <linux/platform_data/camera-pxa.h>
 
 #include "generic.h"
 #include "devices.h"
diff --git a/arch/arm/mach-pxa/eseries.c b/arch/arm/mach-pxa/eseries.c
index 4cb2391..be2ee9b 100644
--- a/arch/arm/mach-pxa/eseries.c
+++ b/arch/arm/mach-pxa/eseries.c
@@ -32,9 +32,9 @@
 #include <mach/eseries-gpio.h>
 #include <mach/eseries-irq.h>
 #include <mach/audio.h>
-#include <mach/pxafb.h>
+#include <linux/platform_data/video-pxafb.h>
 #include <mach/udc.h>
-#include <mach/irda.h>
+#include <linux/platform_data/irda-pxaficp.h>
 
 #include "devices.h"
 #include "generic.h"
diff --git a/arch/arm/mach-pxa/ezx.c b/arch/arm/mach-pxa/ezx.c
index 15ab253..dc58fa0 100644
--- a/arch/arm/mach-pxa/ezx.c
+++ b/arch/arm/mach-pxa/ezx.c
@@ -29,11 +29,11 @@
 #include <asm/mach/arch.h>
 
 #include <mach/pxa27x.h>
-#include <mach/pxafb.h>
-#include <mach/ohci.h>
+#include <linux/platform_data/video-pxafb.h>
+#include <linux/platform_data/usb-ohci-pxa27x.h>
 #include <mach/hardware.h>
-#include <plat/pxa27x_keypad.h>
-#include <mach/camera.h>
+#include <linux/platform_data/keypad-pxa27x.h>
+#include <linux/platform_data/camera-pxa.h>
 
 #include "devices.h"
 #include "generic.h"
diff --git a/arch/arm/mach-pxa/gumstix.c b/arch/arm/mach-pxa/gumstix.c
index e529a35..60755a6 100644
--- a/arch/arm/mach-pxa/gumstix.c
+++ b/arch/arm/mach-pxa/gumstix.c
@@ -41,7 +41,7 @@
 #include <asm/mach/flash.h>
 
 #include <mach/pxa25x.h>
-#include <mach/mmc.h>
+#include <linux/platform_data/mmc-pxamci.h>
 #include <mach/udc.h>
 #include <mach/gumstix.h>
 
diff --git a/arch/arm/mach-pxa/hx4700.c b/arch/arm/mach-pxa/hx4700.c
index e631198..5ecbd17 100644
--- a/arch/arm/mach-pxa/hx4700.c
+++ b/arch/arm/mach-pxa/hx4700.c
@@ -45,7 +45,7 @@
 
 #include <mach/pxa27x.h>
 #include <mach/hx4700.h>
-#include <mach/irda.h>
+#include <linux/platform_data/irda-pxaficp.h>
 
 #include <sound/ak4641.h>
 #include <video/platform_lcd.h>
diff --git a/arch/arm/mach-pxa/idp.c b/arch/arm/mach-pxa/idp.c
index 6ff466b..64507cd 100644
--- a/arch/arm/mach-pxa/idp.c
+++ b/arch/arm/mach-pxa/idp.c
@@ -33,9 +33,9 @@
 
 #include <mach/pxa25x.h>
 #include <mach/idp.h>
-#include <mach/pxafb.h>
+#include <linux/platform_data/video-pxafb.h>
 #include <mach/bitfield.h>
-#include <mach/mmc.h>
+#include <linux/platform_data/mmc-pxamci.h>
 
 #include "generic.h"
 #include "devices.h"
@@ -191,6 +191,87 @@ static void __init idp_map_io(void)
 	iotable_init(idp_io_desc, ARRAY_SIZE(idp_io_desc));
 }
 
+/* LEDs */
+#if defined(CONFIG_NEW_LEDS) && defined(CONFIG_LEDS_CLASS)
+struct idp_led {
+	struct led_classdev     cdev;
+	u8                      mask;
+};
+
+/*
+ * The triggers lines up below will only be used if the
+ * LED triggers are compiled in.
+ */
+static const struct {
+	const char *name;
+	const char *trigger;
+} idp_leds[] = {
+	{ "idp:green", "heartbeat", },
+	{ "idp:red", "cpu0", },
+};
+
+static void idp_led_set(struct led_classdev *cdev,
+		enum led_brightness b)
+{
+	struct idp_led *led = container_of(cdev,
+			struct idp_led, cdev);
+	u32 reg = IDP_CPLD_LED_CONTROL;
+
+	if (b != LED_OFF)
+		reg &= ~led->mask;
+	else
+		reg |= led->mask;
+
+	IDP_CPLD_LED_CONTROL = reg;
+}
+
+static enum led_brightness idp_led_get(struct led_classdev *cdev)
+{
+	struct idp_led *led = container_of(cdev,
+			struct idp_led, cdev);
+
+	return (IDP_CPLD_LED_CONTROL & led->mask) ? LED_OFF : LED_FULL;
+}
+
+static int __init idp_leds_init(void)
+{
+	int i;
+
+	if (!machine_is_pxa_idp())
+		return -ENODEV;
+
+	for (i = 0; i < ARRAY_SIZE(idp_leds); i++) {
+		struct idp_led *led;
+
+		led = kzalloc(sizeof(*led), GFP_KERNEL);
+		if (!led)
+			break;
+
+		led->cdev.name = idp_leds[i].name;
+		led->cdev.brightness_set = idp_led_set;
+		led->cdev.brightness_get = idp_led_get;
+		led->cdev.default_trigger = idp_leds[i].trigger;
+
+		if (i == 0)
+			led->mask = IDP_HB_LED;
+		else
+			led->mask = IDP_BUSY_LED;
+
+		if (led_classdev_register(NULL, &led->cdev) < 0) {
+			kfree(led);
+			break;
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * Since we may have triggers on any subsystem, defer registration
+ * until after subsystem_init.
+ */
+fs_initcall(idp_leds_init);
+#endif
 
 MACHINE_START(PXA_IDP, "Vibren PXA255 IDP")
 	/* Maintainer: Vibren Technologies */
diff --git a/arch/arm/mach-pxa/include/mach/arcom-pcmcia.h b/arch/arm/mach-pxa/include/mach/arcom-pcmcia.h
deleted file mode 100644
index d428be4..0000000
--- a/arch/arm/mach-pxa/include/mach/arcom-pcmcia.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef __ARCOM_PCMCIA_H
-#define __ARCOM_PCMCIA_H
-
-struct arcom_pcmcia_pdata {
-	int	cd_gpio;
-	int	rdy_gpio;
-	int	pwr_gpio;
-	void	(*reset)(int state);
-};
-
-#endif
diff --git a/arch/arm/mach-pxa/include/mach/camera.h b/arch/arm/mach-pxa/include/mach/camera.h
deleted file mode 100644
index 6709b1c..0000000
--- a/arch/arm/mach-pxa/include/mach/camera.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
-    camera.h - PXA camera driver header file
-
-    Copyright (C) 2003, Intel Corporation
-    Copyright (C) 2008, Guennadi Liakhovetski <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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#ifndef __ASM_ARCH_CAMERA_H_
-#define __ASM_ARCH_CAMERA_H_
-
-#define PXA_CAMERA_MASTER	1
-#define PXA_CAMERA_DATAWIDTH_4	2
-#define PXA_CAMERA_DATAWIDTH_5	4
-#define PXA_CAMERA_DATAWIDTH_8	8
-#define PXA_CAMERA_DATAWIDTH_9	0x10
-#define PXA_CAMERA_DATAWIDTH_10	0x20
-#define PXA_CAMERA_PCLK_EN	0x40
-#define PXA_CAMERA_MCLK_EN	0x80
-#define PXA_CAMERA_PCP		0x100
-#define PXA_CAMERA_HSP		0x200
-#define PXA_CAMERA_VSP		0x400
-
-struct pxacamera_platform_data {
-	unsigned long flags;
-	unsigned long mclk_10khz;
-};
-
-extern void pxa_set_camera_info(struct pxacamera_platform_data *);
-
-#endif /* __ASM_ARCH_CAMERA_H_ */
diff --git a/arch/arm/mach-pxa/include/mach/irda.h b/arch/arm/mach-pxa/include/mach/irda.h
deleted file mode 100644
index 3cd41f7..0000000
--- a/arch/arm/mach-pxa/include/mach/irda.h
+++ /dev/null
@@ -1,25 +0,0 @@
-#ifndef ASMARM_ARCH_IRDA_H
-#define ASMARM_ARCH_IRDA_H
-
-/* board specific transceiver capabilities */
-
-#define IR_OFF		1
-#define IR_SIRMODE	2
-#define IR_FIRMODE	4
-
-struct pxaficp_platform_data {
-	int transceiver_cap;
-	void (*transceiver_mode)(struct device *dev, int mode);
-	int (*startup)(struct device *dev);
-	void (*shutdown)(struct device *dev);
-	int gpio_pwdown;		/* powerdown GPIO for the IrDA chip */
-	bool gpio_pwdown_inverted;	/* gpio_pwdown is inverted */
-};
-
-extern void pxa_set_ficp_info(struct pxaficp_platform_data *info);
-
-#if defined(CONFIG_PXA25x) || defined(CONFIG_PXA27x)
-void pxa2xx_transceiver_mode(struct device *dev, int mode);
-#endif
-
-#endif
diff --git a/arch/arm/mach-pxa/include/mach/mmc.h b/arch/arm/mach-pxa/include/mach/mmc.h
deleted file mode 100644
index 9eb515b..0000000
--- a/arch/arm/mach-pxa/include/mach/mmc.h
+++ /dev/null
@@ -1,28 +0,0 @@
-#ifndef ASMARM_ARCH_MMC_H
-#define ASMARM_ARCH_MMC_H
-
-#include <linux/mmc/host.h>
-#include <linux/interrupt.h>
-
-struct device;
-struct mmc_host;
-
-struct pxamci_platform_data {
-	unsigned int ocr_mask;			/* available voltages */
-	unsigned long detect_delay_ms;		/* delay in millisecond before detecting cards after interrupt */
-	int (*init)(struct device *, irq_handler_t , void *);
-	int (*get_ro)(struct device *);
-	void (*setpower)(struct device *, unsigned int);
-	void (*exit)(struct device *, void *);
-	int gpio_card_detect;			/* gpio detecting card insertion */
-	int gpio_card_ro;			/* gpio detecting read only toggle */
-	bool gpio_card_ro_invert;		/* gpio ro is inverted */
-	int gpio_power;				/* gpio powering up MMC bus */
-	bool gpio_power_invert;			/* gpio power is inverted */
-};
-
-extern void pxa_set_mci_info(struct pxamci_platform_data *info);
-extern void pxa3xx_set_mci2_info(struct pxamci_platform_data *info);
-extern void pxa3xx_set_mci3_info(struct pxamci_platform_data *info);
-
-#endif
diff --git a/arch/arm/mach-pxa/include/mach/ohci.h b/arch/arm/mach-pxa/include/mach/ohci.h
deleted file mode 100644
index 95b6e2a..0000000
--- a/arch/arm/mach-pxa/include/mach/ohci.h
+++ /dev/null
@@ -1,36 +0,0 @@
-#ifndef ASMARM_ARCH_OHCI_H
-#define ASMARM_ARCH_OHCI_H
-
-struct device;
-
-struct pxaohci_platform_data {
-	int (*init)(struct device *);
-	void (*exit)(struct device *);
-
-	unsigned long flags;
-#define ENABLE_PORT1		(1 << 0)
-#define ENABLE_PORT2		(1 << 1)
-#define ENABLE_PORT3		(1 << 2)
-#define ENABLE_PORT_ALL		(ENABLE_PORT1 | ENABLE_PORT2 | ENABLE_PORT3)
-
-#define POWER_SENSE_LOW		(1 << 3)
-#define POWER_CONTROL_LOW	(1 << 4)
-#define NO_OC_PROTECTION	(1 << 5)
-#define OC_MODE_GLOBAL		(0 << 6)
-#define OC_MODE_PERPORT		(1 << 6)
-
-	int power_on_delay;	/* Power On to Power Good time - in ms
-				 * HCD must wait for this duration before
-				 * accessing a powered on port
-				 */
-	int port_mode;
-#define PMM_NPS_MODE           1
-#define PMM_GLOBAL_MODE        2
-#define PMM_PERPORT_MODE       3
-
-	int power_budget;
-};
-
-extern void pxa_set_ohci_info(struct pxaohci_platform_data *info);
-
-#endif
diff --git a/arch/arm/mach-pxa/include/mach/palmasoc.h b/arch/arm/mach-pxa/include/mach/palmasoc.h
deleted file mode 100644
index 58afb30..0000000
--- a/arch/arm/mach-pxa/include/mach/palmasoc.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef _INCLUDE_PALMASOC_H_
-#define _INCLUDE_PALMASOC_H_
-
-struct palm27x_asoc_info {
-	int	jack_gpio;
-};
-
-#endif
diff --git a/arch/arm/mach-pxa/include/mach/pata_pxa.h b/arch/arm/mach-pxa/include/mach/pata_pxa.h
deleted file mode 100644
index 6cf7df1..0000000
--- a/arch/arm/mach-pxa/include/mach/pata_pxa.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Generic PXA PATA driver
- *
- * Copyright (C) 2010 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 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; see the file COPYING.  If not, write to
- *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef	__MACH_PATA_PXA_H__
-#define	__MACH_PATA_PXA_H__
-
-struct pata_pxa_pdata {
-	/* PXA DMA DREQ<0:2> pin */
-	uint32_t	dma_dreq;
-	/* Register shift */
-	uint32_t	reg_shift;
-	/* IRQ flags */
-	uint32_t	irq_flags;
-};
-
-#endif	/* __MACH_PATA_PXA_H__ */
diff --git a/arch/arm/mach-pxa/include/mach/pxa3xx-regs.h b/arch/arm/mach-pxa/include/mach/pxa3xx-regs.h
index 207ecb4..f4d48d2 100644
--- a/arch/arm/mach-pxa/include/mach/pxa3xx-regs.h
+++ b/arch/arm/mach-pxa/include/mach/pxa3xx-regs.h
@@ -131,6 +131,7 @@
 #define AICSR		__REG(0x41340008)	/* Application Subsystem Interrupt Control/Status Register */
 #define CKENA		__REG(0x4134000C)	/* A Clock Enable Register */
 #define CKENB		__REG(0x41340010)	/* B Clock Enable Register */
+#define CKENC		__REG(0x41340024)	/* C Clock Enable Register */
 #define AC97_DIV	__REG(0x41340014)	/* AC97 clock divisor value register */
 
 #define ACCR_XPDIS		(1 << 31)	/* Core PLL Output Disable */
diff --git a/arch/arm/mach-pxa/include/mach/pxa3xx-u2d.h b/arch/arm/mach-pxa/include/mach/pxa3xx-u2d.h
deleted file mode 100644
index 9d82cb6..0000000
--- a/arch/arm/mach-pxa/include/mach/pxa3xx-u2d.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * PXA3xx U2D header
- *
- * Copyright (C) 2010 CompuLab Ltd.
- *
- * Igor Grinberg <grinberg@compulab.co.il>
- *
- * This program is free software; you can 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 __PXA310_U2D__
-#define __PXA310_U2D__
-
-#include <linux/usb/ulpi.h>
-
-struct pxa3xx_u2d_platform_data {
-
-#define ULPI_SER_6PIN	(1 << 0)
-#define ULPI_SER_3PIN	(1 << 1)
-	unsigned int ulpi_mode;
-
-	int (*init)(struct device *);
-	void (*exit)(struct device *);
-};
-
-
-/* Start PXA3xx U2D host */
-int pxa3xx_u2d_start_hc(struct usb_bus *host);
-/* Stop PXA3xx U2D host */
-void pxa3xx_u2d_stop_hc(struct usb_bus *host);
-
-extern void pxa3xx_set_u2d_info(struct pxa3xx_u2d_platform_data *info);
-
-#endif /* __PXA310_U2D__ */
diff --git a/arch/arm/mach-pxa/include/mach/pxa930_rotary.h b/arch/arm/mach-pxa/include/mach/pxa930_rotary.h
deleted file mode 100644
index 053587c..0000000
--- a/arch/arm/mach-pxa/include/mach/pxa930_rotary.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef __ASM_ARCH_PXA930_ROTARY_H
-#define __ASM_ARCH_PXA930_ROTARY_H
-
-/* NOTE:
- *
- * rotary can be either interpreted as a ralative input event (e.g.
- * REL_WHEEL or REL_HWHEEL) or a specific key event (e.g. UP/DOWN
- * or LEFT/RIGHT), depending on if up_key & down_key are assigned
- * or rel_code is assigned a non-zero value. When all are non-zero,
- * up_key and down_key will be preferred.
- */
-struct pxa930_rotary_platform_data {
-	int	up_key;
-	int	down_key;
-	int	rel_code;
-};
-
-void __init pxa930_set_rotarykey_info(struct pxa930_rotary_platform_data *info);
-
-#endif /* __ASM_ARCH_PXA930_ROTARY_H */
diff --git a/arch/arm/mach-pxa/include/mach/pxa930_trkball.h b/arch/arm/mach-pxa/include/mach/pxa930_trkball.h
deleted file mode 100644
index 5e0789b..0000000
--- a/arch/arm/mach-pxa/include/mach/pxa930_trkball.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef __ASM_ARCH_PXA930_TRKBALL_H
-#define __ASM_ARCH_PXA930_TRKBALL_H
-
-struct pxa930_trkball_platform_data {
-	int x_filter;
-	int y_filter;
-};
-
-#endif /* __ASM_ARCH_PXA930_TRKBALL_H */
-
diff --git a/arch/arm/mach-pxa/include/mach/pxafb.h b/arch/arm/mach-pxa/include/mach/pxafb.h
deleted file mode 100644
index 486b4c5..0000000
--- a/arch/arm/mach-pxa/include/mach/pxafb.h
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- *  arch/arm/mach-pxa/include/mach/pxafb.h
- *
- *  Support for the xscale frame buffer.
- *
- *  Author:     Jean-Frederic Clere
- *  Created:    Sep 22, 2003
- *  Copyright:  jfclere@sinix.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/fb.h>
-#include <mach/regs-lcd.h>
-
-/*
- * Supported LCD connections
- *
- * bits 0 - 3: for LCD panel type:
- *
- *   STN  - for passive matrix
- *   DSTN - for dual scan passive matrix
- *   TFT  - for active matrix
- *
- * bits 4 - 9 : for bus width
- * bits 10-17 : for AC Bias Pin Frequency
- * bit     18 : for output enable polarity
- * bit     19 : for pixel clock edge
- * bit     20 : for output pixel format when base is RGBT16
- */
-#define LCD_CONN_TYPE(_x)	((_x) & 0x0f)
-#define LCD_CONN_WIDTH(_x)	(((_x) >> 4) & 0x1f)
-
-#define LCD_TYPE_MASK		0xf
-#define LCD_TYPE_UNKNOWN	0
-#define LCD_TYPE_MONO_STN	1
-#define LCD_TYPE_MONO_DSTN	2
-#define LCD_TYPE_COLOR_STN	3
-#define LCD_TYPE_COLOR_DSTN	4
-#define LCD_TYPE_COLOR_TFT	5
-#define LCD_TYPE_SMART_PANEL	6
-#define LCD_TYPE_MAX		7
-
-#define LCD_MONO_STN_4BPP	((4  << 4) | LCD_TYPE_MONO_STN)
-#define LCD_MONO_STN_8BPP	((8  << 4) | LCD_TYPE_MONO_STN)
-#define LCD_MONO_DSTN_8BPP	((8  << 4) | LCD_TYPE_MONO_DSTN)
-#define LCD_COLOR_STN_8BPP	((8  << 4) | LCD_TYPE_COLOR_STN)
-#define LCD_COLOR_DSTN_16BPP	((16 << 4) | LCD_TYPE_COLOR_DSTN)
-#define LCD_COLOR_TFT_8BPP	((8  << 4) | LCD_TYPE_COLOR_TFT)
-#define LCD_COLOR_TFT_16BPP	((16 << 4) | LCD_TYPE_COLOR_TFT)
-#define LCD_COLOR_TFT_18BPP	((18 << 4) | LCD_TYPE_COLOR_TFT)
-#define LCD_SMART_PANEL_8BPP	((8  << 4) | LCD_TYPE_SMART_PANEL)
-#define LCD_SMART_PANEL_16BPP	((16 << 4) | LCD_TYPE_SMART_PANEL)
-#define LCD_SMART_PANEL_18BPP	((18 << 4) | LCD_TYPE_SMART_PANEL)
-
-#define LCD_AC_BIAS_FREQ(x)	(((x) & 0xff) << 10)
-#define LCD_BIAS_ACTIVE_HIGH	(0 << 18)
-#define LCD_BIAS_ACTIVE_LOW	(1 << 18)
-#define LCD_PCLK_EDGE_RISE	(0 << 19)
-#define LCD_PCLK_EDGE_FALL	(1 << 19)
-#define LCD_ALTERNATE_MAPPING	(1 << 20)
-
-/*
- * This structure describes the machine which we are running on.
- * It is set in linux/arch/arm/mach-pxa/machine_name.c and used in the probe routine
- * of linux/drivers/video/pxafb.c
- */
-struct pxafb_mode_info {
-	u_long		pixclock;
-
-	u_short		xres;
-	u_short		yres;
-
-	u_char		bpp;
-	u_int		cmap_greyscale:1,
-			depth:8,
-			transparency:1,
-			unused:22;
-
-	/* Parallel Mode Timing */
-	u_char		hsync_len;
-	u_char		left_margin;
-	u_char		right_margin;
-
-	u_char		vsync_len;
-	u_char		upper_margin;
-	u_char		lower_margin;
-	u_char		sync;
-
-	/* Smart Panel Mode Timing - see PXA27x DM 7.4.15.0.3 for details
-	 * Note:
-	 * 1. all parameters in nanosecond (ns)
-	 * 2. a0cs{rd,wr}_set_hld are controlled by the same register bits
-	 *    in pxa27x and pxa3xx, initialize them to the same value or
-	 *    the larger one will be used
-	 * 3. same to {rd,wr}_pulse_width
-	 *
-	 * 4. LCD_PCLK_EDGE_{RISE,FALL} controls the L_PCLK_WR polarity
-	 * 5. sync & FB_SYNC_HOR_HIGH_ACT controls the L_LCLK_A0
-	 * 6. sync & FB_SYNC_VERT_HIGH_ACT controls the L_LCLK_RD
-	 */
-	unsigned	a0csrd_set_hld;	/* A0 and CS Setup/Hold Time before/after L_FCLK_RD */
-	unsigned	a0cswr_set_hld;	/* A0 and CS Setup/Hold Time before/after L_PCLK_WR */
-	unsigned	wr_pulse_width;	/* L_PCLK_WR pulse width */
-	unsigned	rd_pulse_width;	/* L_FCLK_RD pulse width */
-	unsigned	cmd_inh_time;	/* Command Inhibit time between two writes */
-	unsigned	op_hold_time;	/* Output Hold time from L_FCLK_RD negation */
-};
-
-struct pxafb_mach_info {
-	struct pxafb_mode_info *modes;
-	unsigned int num_modes;
-
-	unsigned int	lcd_conn;
-	unsigned long	video_mem_size;
-
-	u_int		fixed_modes:1,
-			cmap_inverse:1,
-			cmap_static:1,
-			acceleration_enabled:1,
-			unused:28;
-
-	/* The following should be defined in LCCR0
-	 *      LCCR0_Act or LCCR0_Pas          Active or Passive
-	 *      LCCR0_Sngl or LCCR0_Dual        Single/Dual panel
-	 *      LCCR0_Mono or LCCR0_Color       Mono/Color
-	 *      LCCR0_4PixMono or LCCR0_8PixMono (in mono single mode)
-	 *      LCCR0_DMADel(Tcpu) (optional)   DMA request delay
-	 *
-	 * The following should not be defined in LCCR0:
-	 *      LCCR0_OUM, LCCR0_BM, LCCR0_QDM, LCCR0_DIS, LCCR0_EFM
-	 *      LCCR0_IUM, LCCR0_SFM, LCCR0_LDM, LCCR0_ENB
-	 */
-	u_int		lccr0;
-	/* The following should be defined in LCCR3
-	 *      LCCR3_OutEnH or LCCR3_OutEnL    Output enable polarity
-	 *      LCCR3_PixRsEdg or LCCR3_PixFlEdg Pixel clock edge type
-	 *      LCCR3_Acb(X)                    AB Bias pin frequency
-	 *      LCCR3_DPC (optional)            Double Pixel Clock mode (untested)
-	 *
-	 * The following should not be defined in LCCR3
-	 *      LCCR3_HSP, LCCR3_VSP, LCCR0_Pcd(x), LCCR3_Bpp
-	 */
-	u_int		lccr3;
-	/* The following should be defined in LCCR4
-	 *	LCCR4_PAL_FOR_0 or LCCR4_PAL_FOR_1 or LCCR4_PAL_FOR_2
-	 *
-	 * All other bits in LCCR4 should be left alone.
-	 */
-	u_int		lccr4;
-	void (*pxafb_backlight_power)(int);
-	void (*pxafb_lcd_power)(int, struct fb_var_screeninfo *);
-	void (*smart_update)(struct fb_info *);
-};
-
-void pxa_set_fb_info(struct device *, struct pxafb_mach_info *);
-unsigned long pxafb_get_hsync_time(struct device *dev);
-
-#ifdef CONFIG_FB_PXA_SMARTPANEL
-extern int pxafb_smart_queue(struct fb_info *info, uint16_t *cmds, int);
-extern int pxafb_smart_flush(struct fb_info *info);
-#else
-static inline int pxafb_smart_queue(struct fb_info *info,
-				    uint16_t *cmds, int n)
-{
-	return 0;
-}
-
-static inline int pxafb_smart_flush(struct fb_info *info)
-{
-	return 0;
-}
-#endif
diff --git a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c
index 5dae15e..b6cc181 100644
--- a/arch/arm/mach-pxa/irq.c
+++ b/arch/arm/mach-pxa/irq.c
@@ -17,6 +17,8 @@
 #include <linux/syscore_ops.h>
 #include <linux/io.h>
 #include <linux/irq.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 
 #include <asm/exception.h>
 
@@ -25,8 +27,6 @@
 
 #include "generic.h"
 
-#define IRQ_BASE		io_p2v(0x40d00000)
-
 #define ICIP			(0x000)
 #define ICMR			(0x004)
 #define ICLR			(0x008)
@@ -48,22 +48,19 @@
  * This is for peripheral IRQs internal to the PXA chip.
  */
 
+static void __iomem *pxa_irq_base;
 static int pxa_internal_irq_nr;
-
-static inline int cpu_has_ipr(void)
-{
-	return !cpu_is_pxa25x();
-}
+static bool cpu_has_ipr;
 
 static inline void __iomem *irq_base(int i)
 {
-	static unsigned long phys_base[] = {
-		0x40d00000,
-		0x40d0009c,
-		0x40d00130,
+	static unsigned long phys_base_offset[] = {
+		0x0,
+		0x9c,
+		0x130,
 	};
 
-	return io_p2v(phys_base[i]);
+	return pxa_irq_base + phys_base_offset[i];
 }
 
 void pxa_mask_irq(struct irq_data *d)
@@ -96,8 +93,8 @@ asmlinkage void __exception_irq_entry icip_handle_irq(struct pt_regs *regs)
 	uint32_t icip, icmr, mask;
 
 	do {
-		icip = __raw_readl(IRQ_BASE + ICIP);
-		icmr = __raw_readl(IRQ_BASE + ICMR);
+		icip = __raw_readl(pxa_irq_base + ICIP);
+		icmr = __raw_readl(pxa_irq_base + ICMR);
 		mask = icip & icmr;
 
 		if (mask == 0)
@@ -128,6 +125,8 @@ void __init pxa_init_irq(int irq_nr, int (*fn)(struct irq_data *, unsigned int))
 	BUG_ON(irq_nr > MAX_INTERNAL_IRQS);
 
 	pxa_internal_irq_nr = irq_nr;
+	cpu_has_ipr = !cpu_is_pxa25x();
+	pxa_irq_base = io_p2v(0x40d00000);
 
 	for (n = 0; n < irq_nr; n += 32) {
 		void __iomem *base = irq_base(n >> 5);
@@ -136,8 +135,8 @@ void __init pxa_init_irq(int irq_nr, int (*fn)(struct irq_data *, unsigned int))
 		__raw_writel(0, base + ICLR);	/* all IRQs are IRQ, not FIQ */
 		for (i = n; (i < (n + 32)) && (i < irq_nr); i++) {
 			/* initialize interrupt priority */
-			if (cpu_has_ipr())
-				__raw_writel(i | IPR_VALID, IRQ_BASE + IPR(i));
+			if (cpu_has_ipr)
+				__raw_writel(i | IPR_VALID, pxa_irq_base + IPR(i));
 
 			irq = PXA_IRQ(i);
 			irq_set_chip_and_handler(irq, &pxa_internal_irq_chip,
@@ -168,9 +167,9 @@ static int pxa_irq_suspend(void)
 		__raw_writel(0, base + ICMR);
 	}
 
-	if (cpu_has_ipr()) {
+	if (cpu_has_ipr) {
 		for (i = 0; i < pxa_internal_irq_nr; i++)
-			saved_ipr[i] = __raw_readl(IRQ_BASE + IPR(i));
+			saved_ipr[i] = __raw_readl(pxa_irq_base + IPR(i));
 	}
 
 	return 0;
@@ -187,11 +186,11 @@ static void pxa_irq_resume(void)
 		__raw_writel(0, base + ICLR);
 	}
 
-	if (cpu_has_ipr())
+	if (cpu_has_ipr)
 		for (i = 0; i < pxa_internal_irq_nr; i++)
-			__raw_writel(saved_ipr[i], IRQ_BASE + IPR(i));
+			__raw_writel(saved_ipr[i], pxa_irq_base + IPR(i));
 
-	__raw_writel(1, IRQ_BASE + ICCR);
+	__raw_writel(1, pxa_irq_base + ICCR);
 }
 #else
 #define pxa_irq_suspend		NULL
@@ -202,3 +201,93 @@ struct syscore_ops pxa_irq_syscore_ops = {
 	.suspend	= pxa_irq_suspend,
 	.resume		= pxa_irq_resume,
 };
+
+#ifdef CONFIG_OF
+static struct irq_domain *pxa_irq_domain;
+
+static int pxa_irq_map(struct irq_domain *h, unsigned int virq,
+		       irq_hw_number_t hw)
+{
+	void __iomem *base = irq_base(hw / 32);
+
+	/* initialize interrupt priority */
+	if (cpu_has_ipr)
+		__raw_writel(hw | IPR_VALID, pxa_irq_base + IPR(hw));
+
+	irq_set_chip_and_handler(hw, &pxa_internal_irq_chip,
+				 handle_level_irq);
+	irq_set_chip_data(hw, base);
+	set_irq_flags(hw, IRQF_VALID);
+
+	return 0;
+}
+
+static struct irq_domain_ops pxa_irq_ops = {
+	.map    = pxa_irq_map,
+	.xlate  = irq_domain_xlate_onecell,
+};
+
+static const struct of_device_id intc_ids[] __initconst = {
+	{ .compatible = "marvell,pxa-intc", },
+	{}
+};
+
+void __init pxa_dt_irq_init(int (*fn)(struct irq_data *, unsigned int))
+{
+	struct device_node *node;
+	const struct of_device_id *of_id;
+	struct pxa_intc_conf *conf;
+	struct resource res;
+	int n, ret;
+
+	node = of_find_matching_node(NULL, intc_ids);
+	if (!node) {
+		pr_err("Failed to find interrupt controller in arch-pxa\n");
+		return;
+	}
+	of_id = of_match_node(intc_ids, node);
+	conf = of_id->data;
+
+	ret = of_property_read_u32(node, "marvell,intc-nr-irqs",
+				   &pxa_internal_irq_nr);
+	if (ret) {
+		pr_err("Not found marvell,intc-nr-irqs property\n");
+		return;
+	}
+
+	ret = of_address_to_resource(node, 0, &res);
+	if (ret < 0) {
+		pr_err("No registers defined for node\n");
+		return;
+	}
+	pxa_irq_base = io_p2v(res.start);
+
+	if (of_find_property(node, "marvell,intc-priority", NULL))
+		cpu_has_ipr = 1;
+
+	ret = irq_alloc_descs(-1, 0, pxa_internal_irq_nr, 0);
+	if (ret < 0) {
+		pr_err("Failed to allocate IRQ numbers\n");
+		return;
+	}
+
+	pxa_irq_domain = irq_domain_add_legacy(node, pxa_internal_irq_nr, 0, 0,
+					       &pxa_irq_ops, NULL);
+	if (!pxa_irq_domain)
+		panic("Unable to add PXA IRQ domain\n");
+
+	irq_set_default_host(pxa_irq_domain);
+
+	for (n = 0; n < pxa_internal_irq_nr; n += 32) {
+		void __iomem *base = irq_base(n >> 5);
+
+		__raw_writel(0, base + ICMR);	/* disable all IRQs */
+		__raw_writel(0, base + ICLR);	/* all IRQs are IRQ, not FIQ */
+	}
+
+	/* only unmasked interrupts kick us out of idle */
+	__raw_writel(1, irq_base(0) + ICCR);
+
+	pxa_internal_irq_chip.irq_set_wake = fn;
+}
+#endif /* CONFIG_OF */
diff --git a/arch/arm/mach-pxa/leds-idp.c b/arch/arm/mach-pxa/leds-idp.c
deleted file mode 100644
index 06b0600..0000000
--- a/arch/arm/mach-pxa/leds-idp.c
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * linux/arch/arm/mach-pxa/leds-idp.c
- *
- * Copyright (C) 2000 John Dorsey <john+@cs.cmu.edu>
- *
- * Copyright (c) 2001 Jeff Sutherland <jeffs@accelent.com>
- *
- * Original (leds-footbridge.c) by Russell King
- *
- * Macros for actual LED manipulation should be in machine specific
- * files in this 'mach' directory.
- */
-
-
-#include <linux/init.h>
-
-#include <mach/hardware.h>
-#include <asm/leds.h>
-
-#include <mach/pxa25x.h>
-#include <mach/idp.h>
-
-#include "leds.h"
-
-#define LED_STATE_ENABLED	1
-#define LED_STATE_CLAIMED	2
-
-static unsigned int led_state;
-static unsigned int hw_led_state;
-
-void idp_leds_event(led_event_t evt)
-{
-	unsigned long flags;
-
-	local_irq_save(flags);
-
-	switch (evt) {
-	case led_start:
-		hw_led_state = IDP_HB_LED | IDP_BUSY_LED;
-		led_state = LED_STATE_ENABLED;
-		break;
-
-	case led_stop:
-		led_state &= ~LED_STATE_ENABLED;
-		break;
-
-	case led_claim:
-		led_state |= LED_STATE_CLAIMED;
-		hw_led_state = IDP_HB_LED | IDP_BUSY_LED;
-		break;
-
-	case led_release:
-		led_state &= ~LED_STATE_CLAIMED;
-		hw_led_state = IDP_HB_LED | IDP_BUSY_LED;
-		break;
-
-#ifdef CONFIG_LEDS_TIMER
-	case led_timer:
-		if (!(led_state & LED_STATE_CLAIMED))
-			hw_led_state ^= IDP_HB_LED;
-		break;
-#endif
-
-#ifdef CONFIG_LEDS_CPU
-	case led_idle_start:
-		if (!(led_state & LED_STATE_CLAIMED))
-			hw_led_state &= ~IDP_BUSY_LED;
-		break;
-
-	case led_idle_end:
-		if (!(led_state & LED_STATE_CLAIMED))
-			hw_led_state |= IDP_BUSY_LED;
-		break;
-#endif
-
-	case led_halted:
-		break;
-
-	case led_green_on:
-		if (led_state & LED_STATE_CLAIMED)
-			hw_led_state |= IDP_HB_LED;
-		break;
-
-	case led_green_off:
-		if (led_state & LED_STATE_CLAIMED)
-			hw_led_state &= ~IDP_HB_LED;
-		break;
-
-	case led_amber_on:
-		break;
-
-	case led_amber_off:
-		break;
-
-	case led_red_on:
-		if (led_state & LED_STATE_CLAIMED)
-			hw_led_state |= IDP_BUSY_LED;
-		break;
-
-	case led_red_off:
-		if (led_state & LED_STATE_CLAIMED)
-			hw_led_state &= ~IDP_BUSY_LED;
-		break;
-
-	default:
-		break;
-	}
-
-	if  (led_state & LED_STATE_ENABLED)
-		IDP_CPLD_LED_CONTROL = ( (IDP_CPLD_LED_CONTROL | IDP_LEDS_MASK) & ~hw_led_state);
-	else
-		IDP_CPLD_LED_CONTROL |= IDP_LEDS_MASK;
-
-	local_irq_restore(flags);
-}
diff --git a/arch/arm/mach-pxa/leds-lubbock.c b/arch/arm/mach-pxa/leds-lubbock.c
deleted file mode 100644
index 0bd85c8..0000000
--- a/arch/arm/mach-pxa/leds-lubbock.c
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * linux/arch/arm/mach-pxa/leds-lubbock.c
- *
- * Copyright (C) 2000 John Dorsey <john+@cs.cmu.edu>
- *
- * Copyright (c) 2001 Jeff Sutherland <jeffs@accelent.com>
- *
- * Original (leds-footbridge.c) by Russell King
- *
- * Major surgery on April 2004 by Nicolas Pitre for less global
- * namespace collision.  Mostly adapted the Mainstone version.
- */
-
-#include <linux/init.h>
-
-#include <mach/hardware.h>
-#include <asm/leds.h>
-#include <mach/pxa25x.h>
-#include <mach/lubbock.h>
-
-#include "leds.h"
-
-/*
- * 8 discrete leds available for general use:
- *
- * Note: bits [15-8] are used to enable/blank the 8 7 segment hex displays
- * so be sure to not monkey with them here.
- */
-
-#define D28			(1 << 0)
-#define D27			(1 << 1)
-#define D26			(1 << 2)
-#define D25			(1 << 3)
-#define D24			(1 << 4)
-#define D23			(1 << 5)
-#define D22			(1 << 6)
-#define D21			(1 << 7)
-
-#define LED_STATE_ENABLED	1
-#define LED_STATE_CLAIMED	2
-
-static unsigned int led_state;
-static unsigned int hw_led_state;
-
-void lubbock_leds_event(led_event_t evt)
-{
-	unsigned long flags;
-
-	local_irq_save(flags);
-
-	switch (evt) {
-	case led_start:
-		hw_led_state = 0;
-		led_state = LED_STATE_ENABLED;
-		break;
-
-	case led_stop:
-		led_state &= ~LED_STATE_ENABLED;
-		break;
-
-	case led_claim:
-		led_state |= LED_STATE_CLAIMED;
-		hw_led_state = 0;
-		break;
-
-	case led_release:
-		led_state &= ~LED_STATE_CLAIMED;
-		hw_led_state = 0;
-		break;
-
-#ifdef CONFIG_LEDS_TIMER
-	case led_timer:
-		hw_led_state ^= D26;
-		break;
-#endif
-
-#ifdef CONFIG_LEDS_CPU
-	case led_idle_start:
-		hw_led_state &= ~D27;
-		break;
-
-	case led_idle_end:
-		hw_led_state |= D27;
-		break;
-#endif
-
-	case led_halted:
-		break;
-
-	case led_green_on:
-		hw_led_state |= D21;
-		break;
-
-	case led_green_off:
-		hw_led_state &= ~D21;
-		break;
-
-	case led_amber_on:
-		hw_led_state |= D22;
-		break;
-
-	case led_amber_off:
-		hw_led_state &= ~D22;
-		break;
-
-	case led_red_on:
-		hw_led_state |= D23;
-		break;
-
-	case led_red_off:
-		hw_led_state &= ~D23;
-		break;
-
-	default:
-		break;
-	}
-
-	if  (led_state & LED_STATE_ENABLED)
-		LUB_DISC_BLNK_LED = (LUB_DISC_BLNK_LED | 0xff) & ~hw_led_state;
-	else
-		LUB_DISC_BLNK_LED |= 0xff;
-
-	local_irq_restore(flags);
-}
diff --git a/arch/arm/mach-pxa/leds-mainstone.c b/arch/arm/mach-pxa/leds-mainstone.c
deleted file mode 100644
index 4058ab3..0000000
--- a/arch/arm/mach-pxa/leds-mainstone.c
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * linux/arch/arm/mach-pxa/leds-mainstone.c
- *
- * Author:     Nicolas Pitre
- * Created:    Nov 05, 2002
- * 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 <mach/hardware.h>
-#include <asm/leds.h>
-
-#include <mach/pxa27x.h>
-#include <mach/mainstone.h>
-
-#include "leds.h"
-
-
-/* 8 discrete leds available for general use: */
-#define D28			(1 << 0)
-#define D27			(1 << 1)
-#define D26			(1 << 2)
-#define D25			(1 << 3)
-#define D24			(1 << 4)
-#define D23			(1 << 5)
-#define D22			(1 << 6)
-#define D21			(1 << 7)
-
-#define LED_STATE_ENABLED	1
-#define LED_STATE_CLAIMED	2
-
-static unsigned int led_state;
-static unsigned int hw_led_state;
-
-void mainstone_leds_event(led_event_t evt)
-{
-	unsigned long flags;
-
-	local_irq_save(flags);
-
-	switch (evt) {
-	case led_start:
-		hw_led_state = 0;
-		led_state = LED_STATE_ENABLED;
-		break;
-
-	case led_stop:
-		led_state &= ~LED_STATE_ENABLED;
-		break;
-
-	case led_claim:
-		led_state |= LED_STATE_CLAIMED;
-		hw_led_state = 0;
-		break;
-
-	case led_release:
-		led_state &= ~LED_STATE_CLAIMED;
-		hw_led_state = 0;
-		break;
-
-#ifdef CONFIG_LEDS_TIMER
-	case led_timer:
-		hw_led_state ^= D26;
-		break;
-#endif
-
-#ifdef CONFIG_LEDS_CPU
-	case led_idle_start:
-		hw_led_state &= ~D27;
-		break;
-
-	case led_idle_end:
-		hw_led_state |= D27;
-		break;
-#endif
-
-	case led_halted:
-		break;
-
-	case led_green_on:
-		hw_led_state |= D21;
-		break;
-
-	case led_green_off:
-		hw_led_state &= ~D21;
-		break;
-
-	case led_amber_on:
-		hw_led_state |= D22;
-		break;
-
-	case led_amber_off:
-		hw_led_state &= ~D22;
-		break;
-
-	case led_red_on:
-		hw_led_state |= D23;
-		break;
-
-	case led_red_off:
-		hw_led_state &= ~D23;
-		break;
-
-	default:
-		break;
-	}
-
-	if  (led_state & LED_STATE_ENABLED)
-		MST_LEDCTRL = (MST_LEDCTRL | 0xff) & ~hw_led_state;
-	else
-		MST_LEDCTRL |= 0xff;
-
-	local_irq_restore(flags);
-}
diff --git a/arch/arm/mach-pxa/leds.c b/arch/arm/mach-pxa/leds.c
deleted file mode 100644
index bbe4d5f..0000000
--- a/arch/arm/mach-pxa/leds.c
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * linux/arch/arm/mach-pxa/leds.c
- *
- * xscale LEDs dispatcher
- *
- * Copyright (C) 2001 Nicolas Pitre
- *
- * Copyright (c) 2001 Jeff Sutherland, Accelent Systems Inc.
- */
-#include <linux/compiler.h>
-#include <linux/init.h>
-
-#include <asm/leds.h>
-#include <asm/mach-types.h>
-
-#include "leds.h"
-
-static int __init
-pxa_leds_init(void)
-{
-	if (machine_is_lubbock())
-		leds_event = lubbock_leds_event;
-	if (machine_is_mainstone())
-		leds_event = mainstone_leds_event;
-	if (machine_is_pxa_idp())
-		leds_event = idp_leds_event;
-
-	leds_event(led_start);
-	return 0;
-}
-
-core_initcall(pxa_leds_init);
diff --git a/arch/arm/mach-pxa/leds.h b/arch/arm/mach-pxa/leds.h
deleted file mode 100644
index 7f0dfe0..0000000
--- a/arch/arm/mach-pxa/leds.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * arch/arm/mach-pxa/leds.h
- *
- * Copyright (c) 2001 Jeff Sutherland, Accelent Systems Inc.
- *
- * blinky lights for various PXA-based systems:
- *
- */
-
-extern void idp_leds_event(led_event_t evt);
-extern void lubbock_leds_event(led_event_t evt);
-extern void mainstone_leds_event(led_event_t evt);
-extern void trizeps4_leds_event(led_event_t evt);
diff --git a/arch/arm/mach-pxa/littleton.c b/arch/arm/mach-pxa/littleton.c
index 1fb86ed..402874f 100644
--- a/arch/arm/mach-pxa/littleton.c
+++ b/arch/arm/mach-pxa/littleton.c
@@ -42,11 +42,11 @@
 #include <asm/mach/irq.h>
 
 #include <mach/pxa300.h>
-#include <mach/pxafb.h>
-#include <mach/mmc.h>
-#include <plat/pxa27x_keypad.h>
+#include <linux/platform_data/video-pxafb.h>
+#include <linux/platform_data/mmc-pxamci.h>
+#include <linux/platform_data/keypad-pxa27x.h>
 #include <mach/littleton.h>
-#include <plat/pxa3xx_nand.h>
+#include <linux/platform_data/mtd-nand-pxa3xx.h>
 
 #include "generic.h"
 
diff --git a/arch/arm/mach-pxa/lpd270.c b/arch/arm/mach-pxa/lpd270.c
index cee9ce2..1a63eaa 100644
--- a/arch/arm/mach-pxa/lpd270.c
+++ b/arch/arm/mach-pxa/lpd270.c
@@ -41,10 +41,10 @@
 #include <mach/pxa27x.h>
 #include <mach/lpd270.h>
 #include <mach/audio.h>
-#include <mach/pxafb.h>
-#include <mach/mmc.h>
-#include <mach/irda.h>
-#include <mach/ohci.h>
+#include <linux/platform_data/video-pxafb.h>
+#include <linux/platform_data/mmc-pxamci.h>
+#include <linux/platform_data/irda-pxaficp.h>
+#include <linux/platform_data/usb-ohci-pxa27x.h>
 #include <mach/smemc.h>
 
 #include "generic.h"
diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c
index 0ca0db7..553056d 100644
--- a/arch/arm/mach-pxa/lubbock.c
+++ b/arch/arm/mach-pxa/lubbock.c
@@ -15,6 +15,7 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/io.h>
 #include <linux/platform_device.h>
 #include <linux/syscore_ops.h>
 #include <linux/major.h>
@@ -23,6 +24,8 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <linux/smc91x.h>
+#include <linux/slab.h>
+#include <linux/leds.h>
 
 #include <linux/spi/spi.h>
 #include <linux/spi/ads7846.h>
@@ -46,9 +49,9 @@
 #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 <linux/platform_data/irda-pxaficp.h>
+#include <linux/platform_data/video-pxafb.h>
+#include <linux/platform_data/mmc-pxamci.h>
 #include <mach/pm.h>
 #include <mach/smemc.h>
 
@@ -549,6 +552,98 @@ static void __init lubbock_map_io(void)
 	PCFR |= PCFR_OPDE;
 }
 
+/*
+ * Driver for the 8 discrete LEDs available for general use:
+ * Note: bits [15-8] are used to enable/blank the 8 7 segment hex displays
+ * so be sure to not monkey with them here.
+ */
+
+#if defined(CONFIG_NEW_LEDS) && defined(CONFIG_LEDS_CLASS)
+struct lubbock_led {
+	struct led_classdev	cdev;
+	u8			mask;
+};
+
+/*
+ * The triggers lines up below will only be used if the
+ * LED triggers are compiled in.
+ */
+static const struct {
+	const char *name;
+	const char *trigger;
+} lubbock_leds[] = {
+	{ "lubbock:D28", "default-on", },
+	{ "lubbock:D27", "cpu0", },
+	{ "lubbock:D26", "heartbeat" },
+	{ "lubbock:D25", },
+	{ "lubbock:D24", },
+	{ "lubbock:D23", },
+	{ "lubbock:D22", },
+	{ "lubbock:D21", },
+};
+
+static void lubbock_led_set(struct led_classdev *cdev,
+			      enum led_brightness b)
+{
+	struct lubbock_led *led = container_of(cdev,
+					 struct lubbock_led, cdev);
+	u32 reg = LUB_DISC_BLNK_LED;
+
+	if (b != LED_OFF)
+		reg |= led->mask;
+	else
+		reg &= ~led->mask;
+
+	LUB_DISC_BLNK_LED = reg;
+}
+
+static enum led_brightness lubbock_led_get(struct led_classdev *cdev)
+{
+	struct lubbock_led *led = container_of(cdev,
+					 struct lubbock_led, cdev);
+	u32 reg = LUB_DISC_BLNK_LED;
+
+	return (reg & led->mask) ? LED_FULL : LED_OFF;
+}
+
+static int __init lubbock_leds_init(void)
+{
+	int i;
+
+	if (!machine_is_lubbock())
+		return -ENODEV;
+
+	/* All ON */
+	LUB_DISC_BLNK_LED |= 0xff;
+	for (i = 0; i < ARRAY_SIZE(lubbock_leds); i++) {
+		struct lubbock_led *led;
+
+		led = kzalloc(sizeof(*led), GFP_KERNEL);
+		if (!led)
+			break;
+
+		led->cdev.name = lubbock_leds[i].name;
+		led->cdev.brightness_set = lubbock_led_set;
+		led->cdev.brightness_get = lubbock_led_get;
+		led->cdev.default_trigger = lubbock_leds[i].trigger;
+		led->mask = BIT(i);
+
+		if (led_classdev_register(NULL, &led->cdev) < 0) {
+			kfree(led);
+			break;
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * Since we may have triggers on any subsystem, defer registration
+ * until after subsystem_init.
+ */
+fs_initcall(lubbock_leds_init);
+#endif
+
 MACHINE_START(LUBBOCK, "Intel DBPXA250 Development Platform (aka Lubbock)")
 	/* Maintainer: MontaVista Software Inc. */
 	.map_io		= lubbock_map_io,
diff --git a/arch/arm/mach-pxa/magician.c b/arch/arm/mach-pxa/magician.c
index 39561dc..f792240 100644
--- a/arch/arm/mach-pxa/magician.c
+++ b/arch/arm/mach-pxa/magician.c
@@ -38,10 +38,10 @@
 
 #include <mach/pxa27x.h>
 #include <mach/magician.h>
-#include <mach/pxafb.h>
-#include <mach/mmc.h>
-#include <mach/irda.h>
-#include <mach/ohci.h>
+#include <linux/platform_data/video-pxafb.h>
+#include <linux/platform_data/mmc-pxamci.h>
+#include <linux/platform_data/irda-pxaficp.h>
+#include <linux/platform_data/usb-ohci-pxa27x.h>
 
 #include "devices.h"
 #include "generic.h"
diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c
index 1aebaf7..f27a61e 100644
--- a/arch/arm/mach-pxa/mainstone.c
+++ b/arch/arm/mach-pxa/mainstone.c
@@ -28,6 +28,8 @@
 #include <linux/pwm_backlight.h>
 #include <linux/smc91x.h>
 #include <linux/i2c/pxa-i2c.h>
+#include <linux/slab.h>
+#include <linux/leds.h>
 
 #include <asm/types.h>
 #include <asm/setup.h>
@@ -45,11 +47,11 @@
 #include <mach/pxa27x.h>
 #include <mach/mainstone.h>
 #include <mach/audio.h>
-#include <mach/pxafb.h>
-#include <mach/mmc.h>
-#include <mach/irda.h>
-#include <mach/ohci.h>
-#include <plat/pxa27x_keypad.h>
+#include <linux/platform_data/video-pxafb.h>
+#include <linux/platform_data/mmc-pxamci.h>
+#include <linux/platform_data/irda-pxaficp.h>
+#include <linux/platform_data/usb-ohci-pxa27x.h>
+#include <linux/platform_data/keypad-pxa27x.h>
 #include <mach/smemc.h>
 
 #include "generic.h"
@@ -613,6 +615,98 @@ static void __init mainstone_map_io(void)
  	PCFR = 0x66;
 }
 
+/*
+ * Driver for the 8 discrete LEDs available for general use:
+ * Note: bits [15-8] are used to enable/blank the 8 7 segment hex displays
+ * so be sure to not monkey with them here.
+ */
+
+#if defined(CONFIG_NEW_LEDS) && defined(CONFIG_LEDS_CLASS)
+struct mainstone_led {
+	struct led_classdev	cdev;
+	u8			mask;
+};
+
+/*
+ * The triggers lines up below will only be used if the
+ * LED triggers are compiled in.
+ */
+static const struct {
+	const char *name;
+	const char *trigger;
+} mainstone_leds[] = {
+	{ "mainstone:D28", "default-on", },
+	{ "mainstone:D27", "cpu0", },
+	{ "mainstone:D26", "heartbeat" },
+	{ "mainstone:D25", },
+	{ "mainstone:D24", },
+	{ "mainstone:D23", },
+	{ "mainstone:D22", },
+	{ "mainstone:D21", },
+};
+
+static void mainstone_led_set(struct led_classdev *cdev,
+			      enum led_brightness b)
+{
+	struct mainstone_led *led = container_of(cdev,
+					 struct mainstone_led, cdev);
+	u32 reg = MST_LEDCTRL;
+
+	if (b != LED_OFF)
+		reg |= led->mask;
+	else
+		reg &= ~led->mask;
+
+	MST_LEDCTRL = reg;
+}
+
+static enum led_brightness mainstone_led_get(struct led_classdev *cdev)
+{
+	struct mainstone_led *led = container_of(cdev,
+					 struct mainstone_led, cdev);
+	u32 reg = MST_LEDCTRL;
+
+	return (reg & led->mask) ? LED_FULL : LED_OFF;
+}
+
+static int __init mainstone_leds_init(void)
+{
+	int i;
+
+	if (!machine_is_mainstone())
+		return -ENODEV;
+
+	/* All ON */
+	MST_LEDCTRL |= 0xff;
+	for (i = 0; i < ARRAY_SIZE(mainstone_leds); i++) {
+		struct mainstone_led *led;
+
+		led = kzalloc(sizeof(*led), GFP_KERNEL);
+		if (!led)
+			break;
+
+		led->cdev.name = mainstone_leds[i].name;
+		led->cdev.brightness_set = mainstone_led_set;
+		led->cdev.brightness_get = mainstone_led_get;
+		led->cdev.default_trigger = mainstone_leds[i].trigger;
+		led->mask = BIT(i);
+
+		if (led_classdev_register(NULL, &led->cdev) < 0) {
+			kfree(led);
+			break;
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * Since we may have triggers on any subsystem, defer registration
+ * until after subsystem_init.
+ */
+fs_initcall(mainstone_leds_init);
+#endif
+
 MACHINE_START(MAINSTONE, "Intel HCDDBBVA0 Development Platform (aka Mainstone)")
 	/* Maintainer: MontaVista Software Inc. */
 	.atag_offset	= 0x100,	/* BLOB boot parameter setting */
diff --git a/arch/arm/mach-pxa/mioa701.c b/arch/arm/mach-pxa/mioa701.c
index bf99022..2831308 100644
--- a/arch/arm/mach-pxa/mioa701.c
+++ b/arch/arm/mach-pxa/mioa701.c
@@ -46,12 +46,12 @@
 
 #include <mach/pxa27x.h>
 #include <mach/regs-rtc.h>
-#include <plat/pxa27x_keypad.h>
-#include <mach/pxafb.h>
-#include <mach/mmc.h>
+#include <linux/platform_data/keypad-pxa27x.h>
+#include <linux/platform_data/video-pxafb.h>
+#include <linux/platform_data/mmc-pxamci.h>
 #include <mach/udc.h>
 #include <mach/pxa27x-udc.h>
-#include <mach/camera.h>
+#include <linux/platform_data/camera-pxa.h>
 #include <mach/audio.h>
 #include <mach/smemc.h>
 #include <media/soc_camera.h>
diff --git a/arch/arm/mach-pxa/mxm8x10.c b/arch/arm/mach-pxa/mxm8x10.c
index 83570a7..d04ed49 100644
--- a/arch/arm/mach-pxa/mxm8x10.c
+++ b/arch/arm/mach-pxa/mxm8x10.c
@@ -24,11 +24,11 @@
 #include <linux/gpio.h>
 #include <linux/i2c/pxa-i2c.h>
 
-#include <plat/pxa3xx_nand.h>
+#include <linux/platform_data/mtd-nand-pxa3xx.h>
 
-#include <mach/pxafb.h>
-#include <mach/mmc.h>
-#include <mach/ohci.h>
+#include <linux/platform_data/video-pxafb.h>
+#include <linux/platform_data/mmc-pxamci.h>
+#include <linux/platform_data/usb-ohci-pxa27x.h>
 #include <mach/pxa320.h>
 
 #include <mach/mxm8x10.h>
diff --git a/arch/arm/mach-pxa/palm27x.c b/arch/arm/mach-pxa/palm27x.c
index dad71cf..17d4c53 100644
--- a/arch/arm/mach-pxa/palm27x.c
+++ b/arch/arm/mach-pxa/palm27x.c
@@ -29,11 +29,11 @@
 
 #include <mach/pxa27x.h>
 #include <mach/audio.h>
-#include <mach/mmc.h>
-#include <mach/pxafb.h>
-#include <mach/irda.h>
+#include <linux/platform_data/mmc-pxamci.h>
+#include <linux/platform_data/video-pxafb.h>
+#include <linux/platform_data/irda-pxaficp.h>
 #include <mach/udc.h>
-#include <mach/palmasoc.h>
+#include <linux/platform_data/asoc-palm27x.h>
 #include <mach/palm27x.h>
 
 #include "generic.h"
diff --git a/arch/arm/mach-pxa/palmld.c b/arch/arm/mach-pxa/palmld.c
index 31e0433..8bcc96e 100644
--- a/arch/arm/mach-pxa/palmld.c
+++ b/arch/arm/mach-pxa/palmld.c
@@ -35,11 +35,11 @@
 #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 <plat/pxa27x_keypad.h>
-#include <mach/palmasoc.h>
+#include <linux/platform_data/mmc-pxamci.h>
+#include <linux/platform_data/video-pxafb.h>
+#include <linux/platform_data/irda-pxaficp.h>
+#include <linux/platform_data/keypad-pxa27x.h>
+#include <linux/platform_data/asoc-palm27x.h>
 #include <mach/palm27x.h>
 
 #include "generic.h"
diff --git a/arch/arm/mach-pxa/palmt5.c b/arch/arm/mach-pxa/palmt5.c
index 0f6bd4f..5ca7b90 100644
--- a/arch/arm/mach-pxa/palmt5.c
+++ b/arch/arm/mach-pxa/palmt5.c
@@ -36,12 +36,12 @@
 #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 <plat/pxa27x_keypad.h>
+#include <linux/platform_data/mmc-pxamci.h>
+#include <linux/platform_data/video-pxafb.h>
+#include <linux/platform_data/irda-pxaficp.h>
+#include <linux/platform_data/keypad-pxa27x.h>
 #include <mach/udc.h>
-#include <mach/palmasoc.h>
+#include <linux/platform_data/asoc-palm27x.h>
 #include <mach/palm27x.h>
 
 #include "generic.h"
diff --git a/arch/arm/mach-pxa/palmtc.c b/arch/arm/mach-pxa/palmtc.c
index e2d97ee..ca924cf 100644
--- a/arch/arm/mach-pxa/palmtc.c
+++ b/arch/arm/mach-pxa/palmtc.c
@@ -34,9 +34,9 @@
 #include <mach/pxa25x.h>
 #include <mach/audio.h>
 #include <mach/palmtc.h>
-#include <mach/mmc.h>
-#include <mach/pxafb.h>
-#include <mach/irda.h>
+#include <linux/platform_data/mmc-pxamci.h>
+#include <linux/platform_data/video-pxafb.h>
+#include <linux/platform_data/irda-pxaficp.h>
 #include <mach/udc.h>
 
 #include "generic.h"
diff --git a/arch/arm/mach-pxa/palmte2.c b/arch/arm/mach-pxa/palmte2.c
index c054827..997e6da 100644
--- a/arch/arm/mach-pxa/palmte2.c
+++ b/arch/arm/mach-pxa/palmte2.c
@@ -34,11 +34,11 @@
 #include <mach/pxa25x.h>
 #include <mach/audio.h>
 #include <mach/palmte2.h>
-#include <mach/mmc.h>
-#include <mach/pxafb.h>
-#include <mach/irda.h>
+#include <linux/platform_data/mmc-pxamci.h>
+#include <linux/platform_data/video-pxafb.h>
+#include <linux/platform_data/irda-pxaficp.h>
 #include <mach/udc.h>
-#include <mach/palmasoc.h>
+#include <linux/platform_data/asoc-palm27x.h>
 
 #include "generic.h"
 #include "devices.h"
diff --git a/arch/arm/mach-pxa/palmtreo.c b/arch/arm/mach-pxa/palmtreo.c
index fbdebee..3f3c48f 100644
--- a/arch/arm/mach-pxa/palmtreo.c
+++ b/arch/arm/mach-pxa/palmtreo.c
@@ -35,15 +35,15 @@
 #include <mach/pxa27x-udc.h>
 #include <mach/audio.h>
 #include <mach/palmtreo.h>
-#include <mach/mmc.h>
-#include <mach/pxafb.h>
-#include <mach/irda.h>
-#include <plat/pxa27x_keypad.h>
+#include <linux/platform_data/mmc-pxamci.h>
+#include <linux/platform_data/video-pxafb.h>
+#include <linux/platform_data/irda-pxaficp.h>
+#include <linux/platform_data/keypad-pxa27x.h>
 #include <mach/udc.h>
-#include <mach/ohci.h>
+#include <linux/platform_data/usb-ohci-pxa27x.h>
 #include <mach/pxa2xx-regs.h>
-#include <mach/palmasoc.h>
-#include <mach/camera.h>
+#include <linux/platform_data/asoc-palm27x.h>
+#include <linux/platform_data/camera-pxa.h>
 #include <mach/palm27x.h>
 
 #include <sound/pxa2xx-lib.h>
diff --git a/arch/arm/mach-pxa/palmtx.c b/arch/arm/mach-pxa/palmtx.c
index 0da35dc..8b43666 100644
--- a/arch/arm/mach-pxa/palmtx.c
+++ b/arch/arm/mach-pxa/palmtx.c
@@ -40,12 +40,12 @@
 #include <mach/pxa27x.h>
 #include <mach/audio.h>
 #include <mach/palmtx.h>
-#include <mach/mmc.h>
-#include <mach/pxafb.h>
-#include <mach/irda.h>
-#include <plat/pxa27x_keypad.h>
+#include <linux/platform_data/mmc-pxamci.h>
+#include <linux/platform_data/video-pxafb.h>
+#include <linux/platform_data/irda-pxaficp.h>
+#include <linux/platform_data/keypad-pxa27x.h>
 #include <mach/udc.h>
-#include <mach/palmasoc.h>
+#include <linux/platform_data/asoc-palm27x.h>
 #include <mach/palm27x.h>
 
 #include "generic.h"
diff --git a/arch/arm/mach-pxa/palmz72.c b/arch/arm/mach-pxa/palmz72.c
index a97b599..8cdd4f5 100644
--- a/arch/arm/mach-pxa/palmz72.c
+++ b/arch/arm/mach-pxa/palmz72.c
@@ -40,16 +40,16 @@
 #include <mach/pxa27x.h>
 #include <mach/audio.h>
 #include <mach/palmz72.h>
-#include <mach/mmc.h>
-#include <mach/pxafb.h>
-#include <mach/irda.h>
-#include <plat/pxa27x_keypad.h>
+#include <linux/platform_data/mmc-pxamci.h>
+#include <linux/platform_data/video-pxafb.h>
+#include <linux/platform_data/irda-pxaficp.h>
+#include <linux/platform_data/keypad-pxa27x.h>
 #include <mach/udc.h>
-#include <mach/palmasoc.h>
+#include <linux/platform_data/asoc-palm27x.h>
 #include <mach/palm27x.h>
 
 #include <mach/pm.h>
-#include <mach/camera.h>
+#include <linux/platform_data/camera-pxa.h>
 
 #include <media/soc_camera.h>
 
diff --git a/arch/arm/mach-pxa/pcm990-baseboard.c b/arch/arm/mach-pxa/pcm990-baseboard.c
index cb723e8..113c57a 100644
--- a/arch/arm/mach-pxa/pcm990-baseboard.c
+++ b/arch/arm/mach-pxa/pcm990-baseboard.c
@@ -28,14 +28,14 @@
 
 #include <media/soc_camera.h>
 
-#include <mach/camera.h>
+#include <linux/platform_data/camera-pxa.h>
 #include <asm/mach/map.h>
 #include <mach/pxa27x.h>
 #include <mach/audio.h>
-#include <mach/mmc.h>
-#include <mach/ohci.h>
+#include <linux/platform_data/mmc-pxamci.h>
+#include <linux/platform_data/usb-ohci-pxa27x.h>
 #include <mach/pcm990_baseboard.h>
-#include <mach/pxafb.h>
+#include <linux/platform_data/video-pxafb.h>
 
 #include "devices.h"
 #include "generic.h"
diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c
index 89d98c8..2910bb9 100644
--- a/arch/arm/mach-pxa/poodle.c
+++ b/arch/arm/mach-pxa/poodle.c
@@ -40,11 +40,11 @@
 #include <asm/mach/irq.h>
 
 #include <mach/pxa25x.h>
-#include <mach/mmc.h>
+#include <linux/platform_data/mmc-pxamci.h>
 #include <mach/udc.h>
-#include <mach/irda.h>
+#include <linux/platform_data/irda-pxaficp.h>
 #include <mach/poodle.h>
-#include <mach/pxafb.h>
+#include <linux/platform_data/video-pxafb.h>
 
 #include <asm/hardware/scoop.h>
 #include <asm/hardware/locomo.h>
diff --git a/arch/arm/mach-pxa/pxa-dt.c b/arch/arm/mach-pxa/pxa-dt.c
new file mode 100644
index 0000000..c9192ce
--- /dev/null
+++ b/arch/arm/mach-pxa/pxa-dt.c
@@ -0,0 +1,63 @@
+/*
+ *  linux/arch/arm/mach-pxa/pxa-dt.c
+ *
+ *  Copyright (C) 2012 Daniel Mack
+ *
+ *  This 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/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <mach/irqs.h>
+#include <mach/pxa3xx.h>
+
+#include "generic.h"
+
+#ifdef CONFIG_PXA3xx
+extern void __init pxa3xx_dt_init_irq(void);
+
+static const struct of_dev_auxdata pxa3xx_auxdata_lookup[] __initconst = {
+	OF_DEV_AUXDATA("mrvl,pxa-uart",		0x40100000, "pxa2xx-uart.0", NULL),
+	OF_DEV_AUXDATA("mrvl,pxa-uart",		0x40200000, "pxa2xx-uart.1", NULL),
+	OF_DEV_AUXDATA("mrvl,pxa-uart",		0x40700000, "pxa2xx-uart.2", NULL),
+	OF_DEV_AUXDATA("mrvl,pxa-uart",		0x41600000, "pxa2xx-uart.3", NULL),
+	OF_DEV_AUXDATA("marvell,pxa-mmc",	0x41100000, "pxa2xx-mci.0", NULL),
+	OF_DEV_AUXDATA("mrvl,pxa-gpio",		0x40e00000, "pxa-gpio", NULL),
+	OF_DEV_AUXDATA("marvell,pxa-ohci",	0x4c000000, "pxa27x-ohci", NULL),
+	OF_DEV_AUXDATA("mrvl,pxa-i2c",		0x40301680, "pxa2xx-i2c.0", NULL),
+	OF_DEV_AUXDATA("mrvl,pwri2c",		0x40f500c0, "pxa3xx-i2c.1", NULL),
+	OF_DEV_AUXDATA("marvell,pxa3xx-nand",	0x43100000, "pxa3xx-nand", NULL),
+	{}
+};
+
+static void __init pxa3xx_dt_init(void)
+{
+	of_platform_populate(NULL, of_default_bus_match_table,
+			     pxa3xx_auxdata_lookup, NULL);
+}
+
+static const char *pxa3xx_dt_board_compat[] __initdata = {
+	"marvell,pxa300",
+	"marvell,pxa310",
+	"marvell,pxa320",
+	NULL,
+};
+#endif
+
+#ifdef CONFIG_PXA3xx
+DT_MACHINE_START(PXA_DT, "Marvell PXA3xx (Device Tree Support)")
+	.map_io		= pxa3xx_map_io,
+	.init_irq	= pxa3xx_dt_init_irq,
+	.handle_irq	= pxa3xx_handle_irq,
+	.timer		= &pxa_timer,
+	.restart	= pxa_restart,
+	.init_machine	= pxa3xx_dt_init,
+	.dt_compat	= pxa3xx_dt_board_compat,
+MACHINE_END
+#endif
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c
index 4726c24..8047ee0 100644
--- a/arch/arm/mach-pxa/pxa27x.c
+++ b/arch/arm/mach-pxa/pxa27x.c
@@ -30,7 +30,7 @@
 #include <mach/irqs.h>
 #include <mach/pxa27x.h>
 #include <mach/reset.h>
-#include <mach/ohci.h>
+#include <linux/platform_data/usb-ohci-pxa27x.h>
 #include <mach/pm.h>
 #include <mach/dma.h>
 #include <mach/smemc.h>
diff --git a/arch/arm/mach-pxa/pxa2xx.c b/arch/arm/mach-pxa/pxa2xx.c
index f8ec854..447dcbb 100644
--- a/arch/arm/mach-pxa/pxa2xx.c
+++ b/arch/arm/mach-pxa/pxa2xx.c
@@ -19,7 +19,7 @@
 #include <mach/pxa2xx-regs.h>
 #include <mach/mfp-pxa25x.h>
 #include <mach/reset.h>
-#include <mach/irda.h>
+#include <linux/platform_data/irda-pxaficp.h>
 
 void pxa2xx_clear_reset_status(unsigned int mask)
 {
diff --git a/arch/arm/mach-pxa/pxa3xx-ulpi.c b/arch/arm/mach-pxa/pxa3xx-ulpi.c
index 5ead6d4..7dbe3cc 100644
--- a/arch/arm/mach-pxa/pxa3xx-ulpi.c
+++ b/arch/arm/mach-pxa/pxa3xx-ulpi.c
@@ -27,7 +27,7 @@
 
 #include <mach/hardware.h>
 #include <mach/regs-u2d.h>
-#include <mach/pxa3xx-u2d.h>
+#include <linux/platform_data/usb-pxa3xx-ulpi.h>
 
 struct pxa3xx_u2d_ulpi {
 	struct clk		*clk;
diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c
index dffb7e8..656a1bb 100644
--- a/arch/arm/mach-pxa/pxa3xx.c
+++ b/arch/arm/mach-pxa/pxa3xx.c
@@ -19,6 +19,7 @@
 #include <linux/platform_device.h>
 #include <linux/irq.h>
 #include <linux/io.h>
+#include <linux/of.h>
 #include <linux/syscore_ops.h>
 #include <linux/i2c/pxa-i2c.h>
 
@@ -27,7 +28,7 @@
 #include <mach/hardware.h>
 #include <mach/pxa3xx-regs.h>
 #include <mach/reset.h>
-#include <mach/ohci.h>
+#include <linux/platform_data/usb-ohci-pxa27x.h>
 #include <mach/pm.h>
 #include <mach/dma.h>
 #include <mach/smemc.h>
@@ -40,6 +41,8 @@
 #define PECR_IE(n)	((1 << ((n) * 2)) << 28)
 #define PECR_IS(n)	((1 << ((n) * 2)) << 29)
 
+extern void __init pxa_dt_irq_init(int (*fn)(struct irq_data *, unsigned int));
+
 static DEFINE_PXA3_CKEN(pxa3xx_ffuart, FFUART, 14857000, 1);
 static DEFINE_PXA3_CKEN(pxa3xx_btuart, BTUART, 14857000, 1);
 static DEFINE_PXA3_CKEN(pxa3xx_stuart, STUART, 14857000, 1);
@@ -382,7 +385,7 @@ static void __init pxa_init_ext_wakeup_irq(int (*fn)(struct irq_data *,
 	pxa_ext_wakeup_chip.irq_set_wake = fn;
 }
 
-void __init pxa3xx_init_irq(void)
+static void __init __pxa3xx_init_irq(void)
 {
 	/* enable CP6 access */
 	u32 value;
@@ -390,10 +393,23 @@ void __init pxa3xx_init_irq(void)
 	value |= (1 << 6);
 	__asm__ __volatile__("mcr p15, 0, %0, c15, c1, 0\n": :"r"(value));
 
-	pxa_init_irq(56, pxa3xx_set_wake);
 	pxa_init_ext_wakeup_irq(pxa3xx_set_wake);
 }
 
+void __init pxa3xx_init_irq(void)
+{
+	__pxa3xx_init_irq();
+	pxa_init_irq(56, pxa3xx_set_wake);
+}
+
+#ifdef CONFIG_OF
+void __init pxa3xx_dt_init_irq(void)
+{
+	__pxa3xx_init_irq();
+	pxa_dt_irq_init(pxa3xx_set_wake);
+}
+#endif	/* CONFIG_OF */
+
 static struct map_desc pxa3xx_io_desc[] __initdata = {
 	{	/* Mem Ctl */
 		.virtual	= (unsigned long)SMEMC_VIRT,
@@ -466,7 +482,8 @@ static int __init pxa3xx_init(void)
 		register_syscore_ops(&pxa3xx_mfp_syscore_ops);
 		register_syscore_ops(&pxa3xx_clock_syscore_ops);
 
-		ret = platform_add_devices(devices, ARRAY_SIZE(devices));
+		if (!of_have_populated_dt())
+			ret = platform_add_devices(devices, ARRAY_SIZE(devices));
 	}
 
 	return ret;
diff --git a/arch/arm/mach-pxa/raumfeld.c b/arch/arm/mach-pxa/raumfeld.c
index d89d87ae..25b08bf 100644
--- a/arch/arm/mach-pxa/raumfeld.c
+++ b/arch/arm/mach-pxa/raumfeld.c
@@ -49,10 +49,10 @@
 #include <asm/mach/arch.h>
 
 #include <mach/pxa300.h>
-#include <mach/ohci.h>
-#include <mach/pxafb.h>
-#include <mach/mmc.h>
-#include <plat/pxa3xx_nand.h>
+#include <linux/platform_data/usb-ohci-pxa27x.h>
+#include <linux/platform_data/video-pxafb.h>
+#include <linux/platform_data/mmc-pxamci.h>
+#include <linux/platform_data/mtd-nand-pxa3xx.h>
 
 #include "generic.h"
 #include "devices.h"
diff --git a/arch/arm/mach-pxa/saar.c b/arch/arm/mach-pxa/saar.c
index 86c95a5..08d87a5 100644
--- a/arch/arm/mach-pxa/saar.c
+++ b/arch/arm/mach-pxa/saar.c
@@ -32,7 +32,7 @@
 #include <asm/mach/flash.h>
 
 #include <mach/pxa930.h>
-#include <mach/pxafb.h>
+#include <linux/platform_data/video-pxafb.h>
 
 #include "devices.h"
 #include "generic.h"
diff --git a/arch/arm/mach-pxa/sharpsl_pm.c b/arch/arm/mach-pxa/sharpsl_pm.c
index bdf4cb8..5a406f7 100644
--- a/arch/arm/mach-pxa/sharpsl_pm.c
+++ b/arch/arm/mach-pxa/sharpsl_pm.c
@@ -579,8 +579,8 @@ static int sharpsl_ac_check(void)
 static int sharpsl_pm_suspend(struct platform_device *pdev, pm_message_t state)
 {
 	sharpsl_pm.flags |= SHARPSL_SUSPENDED;
-	flush_delayed_work_sync(&toggle_charger);
-	flush_delayed_work_sync(&sharpsl_bat);
+	flush_delayed_work(&toggle_charger);
+	flush_delayed_work(&sharpsl_bat);
 
 	if (sharpsl_pm.charge_mode == CHRG_ON)
 		sharpsl_pm.flags |= SHARPSL_DO_OFFLINE_CHRG;
@@ -879,7 +879,7 @@ static const struct platform_suspend_ops sharpsl_pm_ops = {
 
 static int __devinit sharpsl_pm_probe(struct platform_device *pdev)
 {
-	int ret;
+	int ret, irq;
 
 	if (!pdev->dev.platform_data)
 		return -EINVAL;
@@ -907,24 +907,28 @@ static int __devinit sharpsl_pm_probe(struct platform_device *pdev)
 	gpio_direction_input(sharpsl_pm.machinfo->gpio_batlock);
 
 	/* Register interrupt handlers */
-	if (request_irq(PXA_GPIO_TO_IRQ(sharpsl_pm.machinfo->gpio_acin), sharpsl_ac_isr, IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "AC Input Detect", sharpsl_ac_isr)) {
-		dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", PXA_GPIO_TO_IRQ(sharpsl_pm.machinfo->gpio_acin));
+	irq = gpio_to_irq(sharpsl_pm.machinfo->gpio_acin);
+	if (request_irq(irq, sharpsl_ac_isr, IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "AC Input Detect", sharpsl_ac_isr)) {
+		dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", irq);
 	}
 
-	if (request_irq(PXA_GPIO_TO_IRQ(sharpsl_pm.machinfo->gpio_batlock), sharpsl_fatal_isr, IRQF_DISABLED | IRQF_TRIGGER_FALLING, "Battery Cover", sharpsl_fatal_isr)) {
-		dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", PXA_GPIO_TO_IRQ(sharpsl_pm.machinfo->gpio_batlock));
+	irq = gpio_to_irq(sharpsl_pm.machinfo->gpio_batlock);
+	if (request_irq(irq, sharpsl_fatal_isr, IRQF_DISABLED | IRQF_TRIGGER_FALLING, "Battery Cover", sharpsl_fatal_isr)) {
+		dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", irq);
 	}
 
 	if (sharpsl_pm.machinfo->gpio_fatal) {
-		if (request_irq(PXA_GPIO_TO_IRQ(sharpsl_pm.machinfo->gpio_fatal), sharpsl_fatal_isr, IRQF_DISABLED | IRQF_TRIGGER_FALLING, "Fatal Battery", sharpsl_fatal_isr)) {
-			dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", PXA_GPIO_TO_IRQ(sharpsl_pm.machinfo->gpio_fatal));
+		irq = gpio_to_irq(sharpsl_pm.machinfo->gpio_fatal);
+		if (request_irq(irq, sharpsl_fatal_isr, IRQF_DISABLED | IRQF_TRIGGER_FALLING, "Fatal Battery", sharpsl_fatal_isr)) {
+			dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", irq);
 		}
 	}
 
 	if (sharpsl_pm.machinfo->batfull_irq) {
 		/* Register interrupt handler. */
-		if (request_irq(PXA_GPIO_TO_IRQ(sharpsl_pm.machinfo->gpio_batfull), sharpsl_chrg_full_isr, IRQF_DISABLED | IRQF_TRIGGER_RISING, "CO", sharpsl_chrg_full_isr)) {
-			dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", PXA_GPIO_TO_IRQ(sharpsl_pm.machinfo->gpio_batfull));
+		irq = gpio_to_irq(sharpsl_pm.machinfo->gpio_batfull);
+		if (request_irq(irq, sharpsl_chrg_full_isr, IRQF_DISABLED | IRQF_TRIGGER_RISING, "CO", sharpsl_chrg_full_isr)) {
+			dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", irq);
 		}
 	}
 
@@ -953,14 +957,14 @@ static int sharpsl_pm_remove(struct platform_device *pdev)
 
 	led_trigger_unregister_simple(sharpsl_charge_led_trigger);
 
-	free_irq(PXA_GPIO_TO_IRQ(sharpsl_pm.machinfo->gpio_acin), sharpsl_ac_isr);
-	free_irq(PXA_GPIO_TO_IRQ(sharpsl_pm.machinfo->gpio_batlock), sharpsl_fatal_isr);
+	free_irq(gpio_to_irq(sharpsl_pm.machinfo->gpio_acin), sharpsl_ac_isr);
+	free_irq(gpio_to_irq(sharpsl_pm.machinfo->gpio_batlock), sharpsl_fatal_isr);
 
 	if (sharpsl_pm.machinfo->gpio_fatal)
-		free_irq(PXA_GPIO_TO_IRQ(sharpsl_pm.machinfo->gpio_fatal), sharpsl_fatal_isr);
+		free_irq(gpio_to_irq(sharpsl_pm.machinfo->gpio_fatal), sharpsl_fatal_isr);
 
 	if (sharpsl_pm.machinfo->batfull_irq)
-		free_irq(PXA_GPIO_TO_IRQ(sharpsl_pm.machinfo->gpio_batfull), sharpsl_chrg_full_isr);
+		free_irq(gpio_to_irq(sharpsl_pm.machinfo->gpio_batfull), sharpsl_chrg_full_isr);
 
 	gpio_free(sharpsl_pm.machinfo->gpio_batlock);
 	gpio_free(sharpsl_pm.machinfo->gpio_batfull);
diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c
index 363d91b..2073f0e 100644
--- a/arch/arm/mach-pxa/spitz.c
+++ b/arch/arm/mach-pxa/spitz.c
@@ -41,10 +41,10 @@
 #include <mach/pxa27x.h>
 #include <mach/pxa27x-udc.h>
 #include <mach/reset.h>
-#include <mach/irda.h>
-#include <mach/mmc.h>
-#include <mach/ohci.h>
-#include <mach/pxafb.h>
+#include <linux/platform_data/irda-pxaficp.h>
+#include <linux/platform_data/mmc-pxamci.h>
+#include <linux/platform_data/usb-ohci-pxa27x.h>
+#include <linux/platform_data/video-pxafb.h>
 #include <mach/spitz.h>
 #include <mach/sharpsl_pm.h>
 #include <mach/smemc.h>
diff --git a/arch/arm/mach-pxa/stargate2.c b/arch/arm/mach-pxa/stargate2.c
index 30b1b0b..456560b 100644
--- a/arch/arm/mach-pxa/stargate2.c
+++ b/arch/arm/mach-pxa/stargate2.c
@@ -44,7 +44,7 @@
 #include <asm/mach/flash.h>
 
 #include <mach/pxa27x.h>
-#include <mach/mmc.h>
+#include <linux/platform_data/mmc-pxamci.h>
 #include <mach/udc.h>
 #include <mach/pxa27x-udc.h>
 #include <mach/smemc.h>
@@ -52,7 +52,7 @@
 #include <linux/spi/spi.h>
 #include <linux/spi/pxa2xx_spi.h>
 #include <linux/mfd/da903x.h>
-#include <linux/sht15.h>
+#include <linux/platform_data/sht15.h>
 
 #include "devices.h"
 #include "generic.h"
diff --git a/arch/arm/mach-pxa/tavorevb.c b/arch/arm/mach-pxa/tavorevb.c
index 736bfdc..1a25f8a 100644
--- a/arch/arm/mach-pxa/tavorevb.c
+++ b/arch/arm/mach-pxa/tavorevb.c
@@ -24,8 +24,8 @@
 #include <asm/mach/arch.h>
 
 #include <mach/pxa930.h>
-#include <mach/pxafb.h>
-#include <plat/pxa27x_keypad.h>
+#include <linux/platform_data/video-pxafb.h>
+#include <linux/platform_data/keypad-pxa27x.h>
 
 #include "devices.h"
 #include "generic.h"
diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c
index 4d4eb60..233629e 100644
--- a/arch/arm/mach-pxa/tosa.c
+++ b/arch/arm/mach-pxa/tosa.c
@@ -42,8 +42,8 @@
 
 #include <mach/pxa25x.h>
 #include <mach/reset.h>
-#include <mach/irda.h>
-#include <mach/mmc.h>
+#include <linux/platform_data/irda-pxaficp.h>
+#include <linux/platform_data/mmc-pxamci.h>
 #include <mach/udc.h>
 #include <mach/tosa_bt.h>
 #include <mach/audio.h>
diff --git a/arch/arm/mach-pxa/trizeps4.c b/arch/arm/mach-pxa/trizeps4.c
index 166dd32..fbbcbed 100644
--- a/arch/arm/mach-pxa/trizeps4.c
+++ b/arch/arm/mach-pxa/trizeps4.c
@@ -43,10 +43,10 @@
 #include <mach/pxa27x.h>
 #include <mach/trizeps4.h>
 #include <mach/audio.h>
-#include <mach/pxafb.h>
-#include <mach/mmc.h>
-#include <mach/irda.h>
-#include <mach/ohci.h>
+#include <linux/platform_data/video-pxafb.h>
+#include <linux/platform_data/mmc-pxamci.h>
+#include <linux/platform_data/irda-pxaficp.h>
+#include <linux/platform_data/usb-ohci-pxa27x.h>
 #include <mach/smemc.h>
 
 #include "generic.h"
diff --git a/arch/arm/mach-pxa/viper.c b/arch/arm/mach-pxa/viper.c
index 130379f..392412c 100644
--- a/arch/arm/mach-pxa/viper.c
+++ b/arch/arm/mach-pxa/viper.c
@@ -48,9 +48,9 @@
 
 #include <mach/pxa25x.h>
 #include <mach/audio.h>
-#include <mach/pxafb.h>
+#include <linux/platform_data/video-pxafb.h>
 #include <mach/regs-uart.h>
-#include <mach/arcom-pcmcia.h>
+#include <linux/platform_data/pcmcia-pxa2xx_viper.h>
 #include <mach/viper.h>
 
 #include <asm/setup.h>
diff --git a/arch/arm/mach-pxa/vpac270.c b/arch/arm/mach-pxa/vpac270.c
index e1740ac..491b6c9 100644
--- a/arch/arm/mach-pxa/vpac270.c
+++ b/arch/arm/mach-pxa/vpac270.c
@@ -33,12 +33,12 @@
 #include <mach/pxa27x.h>
 #include <mach/audio.h>
 #include <mach/vpac270.h>
-#include <mach/mmc.h>
-#include <mach/pxafb.h>
-#include <mach/ohci.h>
+#include <linux/platform_data/mmc-pxamci.h>
+#include <linux/platform_data/video-pxafb.h>
+#include <linux/platform_data/usb-ohci-pxa27x.h>
 #include <mach/pxa27x-udc.h>
 #include <mach/udc.h>
-#include <mach/pata_pxa.h>
+#include <linux/platform_data/ata-pxa.h>
 
 #include "generic.h"
 #include "devices.h"
diff --git a/arch/arm/mach-pxa/z2.c b/arch/arm/mach-pxa/z2.c
index b9320cb..97529fa 100644
--- a/arch/arm/mach-pxa/z2.c
+++ b/arch/arm/mach-pxa/z2.c
@@ -37,9 +37,9 @@
 #include <mach/pxa27x.h>
 #include <mach/mfp-pxa27x.h>
 #include <mach/z2.h>
-#include <mach/pxafb.h>
-#include <mach/mmc.h>
-#include <plat/pxa27x_keypad.h>
+#include <linux/platform_data/video-pxafb.h>
+#include <linux/platform_data/mmc-pxamci.h>
+#include <linux/platform_data/keypad-pxa27x.h>
 #include <mach/pm.h>
 
 #include "generic.h"
diff --git a/arch/arm/mach-pxa/zeus.c b/arch/arm/mach-pxa/zeus.c
index af3d4f7..abd3aa1 100644
--- a/arch/arm/mach-pxa/zeus.c
+++ b/arch/arm/mach-pxa/zeus.c
@@ -38,14 +38,14 @@
 
 #include <mach/pxa27x.h>
 #include <mach/regs-uart.h>
-#include <mach/ohci.h>
-#include <mach/mmc.h>
+#include <linux/platform_data/usb-ohci-pxa27x.h>
+#include <linux/platform_data/mmc-pxamci.h>
 #include <mach/pxa27x-udc.h>
 #include <mach/udc.h>
-#include <mach/pxafb.h>
+#include <linux/platform_data/video-pxafb.h>
 #include <mach/pm.h>
 #include <mach/audio.h>
-#include <mach/arcom-pcmcia.h>
+#include <linux/platform_data/pcmcia-pxa2xx_viper.h>
 #include <mach/zeus.h>
 #include <mach/smemc.h>
 
diff --git a/arch/arm/mach-pxa/zylonite.c b/arch/arm/mach-pxa/zylonite.c
index 98eec80..226279f 100644
--- a/arch/arm/mach-pxa/zylonite.c
+++ b/arch/arm/mach-pxa/zylonite.c
@@ -26,12 +26,12 @@
 #include <asm/mach/arch.h>
 #include <mach/pxa3xx.h>
 #include <mach/audio.h>
-#include <mach/pxafb.h>
+#include <linux/platform_data/video-pxafb.h>
 #include <mach/zylonite.h>
-#include <mach/mmc.h>
-#include <mach/ohci.h>
-#include <plat/pxa27x_keypad.h>
-#include <plat/pxa3xx_nand.h>
+#include <linux/platform_data/mmc-pxamci.h>
+#include <linux/platform_data/usb-ohci-pxa27x.h>
+#include <linux/platform_data/keypad-pxa27x.h>
+#include <linux/platform_data/mtd-nand-pxa3xx.h>
 
 #include "devices.h"
 #include "generic.h"
diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c
index 45868bb..6824674 100644
--- a/arch/arm/mach-realview/core.c
+++ b/arch/arm/mach-realview/core.c
@@ -30,12 +30,10 @@
 #include <linux/ata_platform.h>
 #include <linux/amba/mmci.h>
 #include <linux/gfp.h>
-#include <linux/clkdev.h>
 #include <linux/mtd/physmap.h>
 
 #include <mach/hardware.h>
 #include <asm/irq.h>
-#include <asm/leds.h>
 #include <asm/mach-types.h>
 #include <asm/hardware/arm_timer.h>
 #include <asm/hardware/icst.h>
@@ -226,115 +224,10 @@ struct mmci_platform_data realview_mmc1_plat_data = {
 	.cd_invert	= true,
 };
 
-/*
- * Clock handling
- */
-static const struct icst_params realview_oscvco_params = {
-	.ref		= 24000000,
-	.vco_max	= ICST307_VCO_MAX,
-	.vco_min	= ICST307_VCO_MIN,
-	.vd_min		= 4 + 8,
-	.vd_max		= 511 + 8,
-	.rd_min		= 1 + 2,
-	.rd_max		= 127 + 2,
-	.s2div		= icst307_s2div,
-	.idx2s		= icst307_idx2s,
-};
-
-static void realview_oscvco_set(struct clk *clk, struct icst_vco vco)
-{
-	void __iomem *sys_lock = __io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_LOCK_OFFSET;
-	u32 val;
-
-	val = readl(clk->vcoreg) & ~0x7ffff;
-	val |= vco.v | (vco.r << 9) | (vco.s << 16);
-
-	writel(0xa05f, sys_lock);
-	writel(val, clk->vcoreg);
-	writel(0, sys_lock);
-}
-
-static const struct clk_ops oscvco_clk_ops = {
-	.round	= icst_clk_round,
-	.set	= icst_clk_set,
-	.setvco	= realview_oscvco_set,
-};
-
-static struct clk oscvco_clk = {
-	.ops	= &oscvco_clk_ops,
-	.params	= &realview_oscvco_params,
-};
-
-/*
- * These are fixed clocks.
- */
-static struct clk ref24_clk = {
-	.rate	= 24000000,
-};
-
-static struct clk sp804_clk = {
-	.rate	= 1000000,
-};
-
-static struct clk dummy_apb_pclk;
-
-static struct clk_lookup lookups[] = {
-	{	/* Bus clock */
-		.con_id		= "apb_pclk",
-		.clk		= &dummy_apb_pclk,
-	}, {	/* UART0 */
-		.dev_id		= "dev:uart0",
-		.clk		= &ref24_clk,
-	}, {	/* UART1 */
-		.dev_id		= "dev:uart1",
-		.clk		= &ref24_clk,
-	}, {	/* UART2 */
-		.dev_id		= "dev:uart2",
-		.clk		= &ref24_clk,
-	}, {	/* UART3 */
-		.dev_id		= "fpga:uart3",
-		.clk		= &ref24_clk,
-	}, {	/* UART3 is on the dev chip in PB1176 */
-		.dev_id		= "dev:uart3",
-		.clk		= &ref24_clk,
-	}, {	/* UART4 only exists in PB1176 */
-		.dev_id		= "fpga:uart4",
-		.clk		= &ref24_clk,
-	}, {	/* KMI0 */
-		.dev_id		= "fpga:kmi0",
-		.clk		= &ref24_clk,
-	}, {	/* KMI1 */
-		.dev_id		= "fpga:kmi1",
-		.clk		= &ref24_clk,
-	}, {	/* MMC0 */
-		.dev_id		= "fpga:mmc0",
-		.clk		= &ref24_clk,
-	}, {	/* CLCD is in the PB1176 and EB DevChip */
-		.dev_id		= "dev:clcd",
-		.clk		= &oscvco_clk,
-	}, {	/* PB:CLCD */
-		.dev_id		= "issp:clcd",
-		.clk		= &oscvco_clk,
-	}, {	/* SSP */
-		.dev_id		= "dev:ssp0",
-		.clk		= &ref24_clk,
-	}, {	/* SP804 timers */
-		.dev_id		= "sp804",
-		.clk		= &sp804_clk,
-	},
-};
-
 void __init realview_init_early(void)
 {
 	void __iomem *sys = __io_address(REALVIEW_SYS_BASE);
 
-	if (machine_is_realview_pb1176())
-		oscvco_clk.vcoreg = sys + REALVIEW_SYS_OSC0_OFFSET;
-	else
-		oscvco_clk.vcoreg = sys + REALVIEW_SYS_OSC4_OFFSET;
-
-	clkdev_add_table(lookups, ARRAY_SIZE(lookups));
-
 	versatile_sched_clock_init(sys + REALVIEW_SYS_24MHz_OFFSET, 24000000);
 }
 
@@ -436,44 +329,6 @@ struct clcd_board clcd_plat_data = {
 	.remove		= versatile_clcd_remove_dma,
 };
 
-#ifdef CONFIG_LEDS
-#define VA_LEDS_BASE (__io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_LED_OFFSET)
-
-void realview_leds_event(led_event_t ledevt)
-{
-	unsigned long flags;
-	u32 val;
-	u32 led = 1 << smp_processor_id();
-
-	local_irq_save(flags);
-	val = readl(VA_LEDS_BASE);
-
-	switch (ledevt) {
-	case led_idle_start:
-		val = val & ~led;
-		break;
-
-	case led_idle_end:
-		val = val | led;
-		break;
-
-	case led_timer:
-		val = val ^ REALVIEW_SYS_LED7;
-		break;
-
-	case led_halted:
-		val = 0;
-		break;
-
-	default:
-		break;
-	}
-
-	writel(val, VA_LEDS_BASE);
-	local_irq_restore(flags);
-}
-#endif	/* CONFIG_LEDS */
-
 /*
  * Where is the timer (VA)?
  */
diff --git a/arch/arm/mach-realview/core.h b/arch/arm/mach-realview/core.h
index f8f2c0a..602ca5e 100644
--- a/arch/arm/mach-realview/core.h
+++ b/arch/arm/mach-realview/core.h
@@ -26,7 +26,6 @@
 #include <linux/io.h>
 
 #include <asm/setup.h>
-#include <asm/leds.h>
 
 #define APB_DEVICE(name, busid, base, plat)			\
 static AMBA_APB_DEVICE(name, busid, 0, REALVIEW_##base##_BASE, base##_IRQ, plat)
@@ -47,7 +46,6 @@ extern void __iomem *timer1_va_base;
 extern void __iomem *timer2_va_base;
 extern void __iomem *timer3_va_base;
 
-extern void realview_leds_event(led_event_t ledevt);
 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);
@@ -56,4 +54,7 @@ extern void realview_init_early(void);
 extern void realview_fixup(struct tag *tags, char **from,
 			   struct meminfo *meminfo);
 
+extern struct smp_operations realview_smp_ops;
+extern void realview_cpu_die(unsigned int cpu);
+
 #endif
diff --git a/arch/arm/mach-realview/hotplug.c b/arch/arm/mach-realview/hotplug.c
index 57d9efb..53818e5 100644
--- a/arch/arm/mach-realview/hotplug.c
+++ b/arch/arm/mach-realview/hotplug.c
@@ -16,8 +16,6 @@
 #include <asm/cp15.h>
 #include <asm/smp_plat.h>
 
-extern volatile int pen_release;
-
 static inline void cpu_enter_lowpower(void)
 {
 	unsigned int v;
@@ -89,17 +87,12 @@ static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
 	}
 }
 
-int platform_cpu_kill(unsigned int cpu)
-{
-	return 1;
-}
-
 /*
  * platform-specific code to shutdown a CPU
  *
  * Called with IRQs disabled
  */
-void platform_cpu_die(unsigned int cpu)
+void __ref realview_cpu_die(unsigned int cpu)
 {
 	int spurious = 0;
 
@@ -118,12 +111,3 @@ void platform_cpu_die(unsigned int cpu)
 	if (spurious)
 		pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
 }
-
-int platform_cpu_disable(unsigned int cpu)
-{
-	/*
-	 * we don't allow CPU 0 to be shutdown (it is still too special
-	 * e.g. clock tick interrupts)
-	 */
-	return cpu == 0 ? -EPERM : 0;
-}
diff --git a/arch/arm/mach-realview/include/mach/clkdev.h b/arch/arm/mach-realview/include/mach/clkdev.h
deleted file mode 100644
index e58d077..0000000
--- a/arch/arm/mach-realview/include/mach/clkdev.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef __ASM_MACH_CLKDEV_H
-#define __ASM_MACH_CLKDEV_H
-
-#include <plat/clock.h>
-
-struct clk {
-	unsigned long		rate;
-	const struct clk_ops	*ops;
-	const struct icst_params *params;
-	void __iomem		*vcoreg;
-};
-
-#define __clk_get(clk) ({ 1; })
-#define __clk_put(clk) do { } while (0)
-
-#endif
diff --git a/arch/arm/mach-realview/include/mach/gpio.h b/arch/arm/mach-realview/include/mach/gpio.h
deleted file mode 100644
index 40a8c17..0000000
--- a/arch/arm/mach-realview/include/mach/gpio.h
+++ /dev/null
@@ -1 +0,0 @@
-/* empty */
diff --git a/arch/arm/mach-realview/platsmp.c b/arch/arm/mach-realview/platsmp.c
index 17c878d..300f706 100644
--- a/arch/arm/mach-realview/platsmp.c
+++ b/arch/arm/mach-realview/platsmp.c
@@ -22,9 +22,9 @@
 #include <mach/board-pb11mp.h>
 #include <mach/board-pbx.h>
 
-#include "core.h"
+#include <plat/platsmp.h>
 
-extern void versatile_secondary_startup(void);
+#include "core.h"
 
 static void __iomem *scu_base_addr(void)
 {
@@ -43,7 +43,7 @@ static void __iomem *scu_base_addr(void)
  * Initialise the CPU possible map early - this describes the CPUs
  * which may be present or become present in the system.
  */
-void __init smp_init_cpus(void)
+static void __init realview_smp_init_cpus(void)
 {
 	void __iomem *scu_base = scu_base_addr();
 	unsigned int i, ncores;
@@ -63,7 +63,7 @@ void __init smp_init_cpus(void)
 	set_smp_cross_call(gic_raise_softirq);
 }
 
-void __init platform_smp_prepare_cpus(unsigned int max_cpus)
+static void __init realview_smp_prepare_cpus(unsigned int max_cpus)
 {
 
 	scu_enable(scu_base_addr());
@@ -77,3 +77,13 @@ void __init platform_smp_prepare_cpus(unsigned int max_cpus)
 	__raw_writel(virt_to_phys(versatile_secondary_startup),
 		     __io_address(REALVIEW_SYS_FLAGSSET));
 }
+
+struct smp_operations realview_smp_ops __initdata = {
+	.smp_init_cpus		= realview_smp_init_cpus,
+	.smp_prepare_cpus	= realview_smp_prepare_cpus,
+	.smp_secondary_init	= versatile_secondary_init,
+	.smp_boot_secondary	= versatile_boot_secondary,
+#ifdef CONFIG_HOTPLUG_CPU
+	.cpu_die		= realview_cpu_die,
+#endif
+};
diff --git a/arch/arm/mach-realview/realview_eb.c b/arch/arm/mach-realview/realview_eb.c
index baf382c..d3b3cd2 100644
--- a/arch/arm/mach-realview/realview_eb.c
+++ b/arch/arm/mach-realview/realview_eb.c
@@ -27,12 +27,11 @@
 #include <linux/amba/mmci.h>
 #include <linux/amba/pl022.h>
 #include <linux/io.h>
+#include <linux/platform_data/clk-realview.h>
 
 #include <mach/hardware.h>
 #include <asm/irq.h>
-#include <asm/leds.h>
 #include <asm/mach-types.h>
-#include <asm/pmu.h>
 #include <asm/pgtable.h>
 #include <asm/hardware/gic.h>
 #include <asm/hardware/cache-l2x0.h>
@@ -297,7 +296,7 @@ static struct resource pmu_resources[] = {
 
 static struct platform_device pmu_device = {
 	.name			= "arm-pmu",
-	.id			= ARM_PMU_DEVICE_CPU,
+	.id			= -1,
 	.num_resources		= ARRAY_SIZE(pmu_resources),
 	.resource		= pmu_resources,
 };
@@ -414,6 +413,7 @@ static void __init realview_eb_timer_init(void)
 	else
 		timer_irq = IRQ_EB_TIMER0_1;
 
+	realview_clk_init(__io_address(REALVIEW_SYS_BASE), false);
 	realview_timer_init(timer_irq);
 	realview_eb_twd_init();
 }
@@ -462,10 +462,6 @@ static void __init realview_eb_init(void)
 		struct amba_device *d = amba_devs[i];
 		amba_device_register(d, &iomem_resource);
 	}
-
-#ifdef CONFIG_LEDS
-	leds_event = realview_leds_event;
-#endif
 }
 
 MACHINE_START(REALVIEW_EB, "ARM-RealView EB")
diff --git a/arch/arm/mach-realview/realview_pb1176.c b/arch/arm/mach-realview/realview_pb1176.c
index b1d7caf..07d6672 100644
--- a/arch/arm/mach-realview/realview_pb1176.c
+++ b/arch/arm/mach-realview/realview_pb1176.c
@@ -29,12 +29,11 @@
 #include <linux/mtd/physmap.h>
 #include <linux/mtd/partitions.h>
 #include <linux/io.h>
+#include <linux/platform_data/clk-realview.h>
 
 #include <mach/hardware.h>
 #include <asm/irq.h>
-#include <asm/leds.h>
 #include <asm/mach-types.h>
-#include <asm/pmu.h>
 #include <asm/pgtable.h>
 #include <asm/hardware/gic.h>
 #include <asm/hardware/cache-l2x0.h>
@@ -280,7 +279,7 @@ static struct resource pmu_resource = {
 
 static struct platform_device pmu_device = {
 	.name			= "arm-pmu",
-	.id			= ARM_PMU_DEVICE_CPU,
+	.id			= -1,
 	.num_resources		= 1,
 	.resource		= &pmu_resource,
 };
@@ -326,6 +325,7 @@ static void __init realview_pb1176_timer_init(void)
 	timer2_va_base = __io_address(REALVIEW_PB1176_TIMER2_3_BASE);
 	timer3_va_base = __io_address(REALVIEW_PB1176_TIMER2_3_BASE) + 0x20;
 
+	realview_clk_init(__io_address(REALVIEW_SYS_BASE), true);
 	realview_timer_init(IRQ_DC1176_TIMER0);
 }
 
@@ -375,10 +375,6 @@ static void __init realview_pb1176_init(void)
 		struct amba_device *d = amba_devs[i];
 		amba_device_register(d, &iomem_resource);
 	}
-
-#ifdef CONFIG_LEDS
-	leds_event = realview_leds_event;
-#endif
 }
 
 MACHINE_START(REALVIEW_PB1176, "ARM-RealView PB1176")
diff --git a/arch/arm/mach-realview/realview_pb11mp.c b/arch/arm/mach-realview/realview_pb11mp.c
index a98c536..7ed53d7 100644
--- a/arch/arm/mach-realview/realview_pb11mp.c
+++ b/arch/arm/mach-realview/realview_pb11mp.c
@@ -27,12 +27,11 @@
 #include <linux/amba/mmci.h>
 #include <linux/amba/pl022.h>
 #include <linux/io.h>
+#include <linux/platform_data/clk-realview.h>
 
 #include <mach/hardware.h>
 #include <asm/irq.h>
-#include <asm/leds.h>
 #include <asm/mach-types.h>
-#include <asm/pmu.h>
 #include <asm/pgtable.h>
 #include <asm/hardware/gic.h>
 #include <asm/hardware/cache-l2x0.h>
@@ -263,7 +262,7 @@ static struct resource pmu_resources[] = {
 
 static struct platform_device pmu_device = {
 	.name			= "arm-pmu",
-	.id			= ARM_PMU_DEVICE_CPU,
+	.id			= -1,
 	.num_resources		= ARRAY_SIZE(pmu_resources),
 	.resource		= pmu_resources,
 };
@@ -312,6 +311,7 @@ static void __init realview_pb11mp_timer_init(void)
 	timer2_va_base = __io_address(REALVIEW_PB11MP_TIMER2_3_BASE);
 	timer3_va_base = __io_address(REALVIEW_PB11MP_TIMER2_3_BASE) + 0x20;
 
+	realview_clk_init(__io_address(REALVIEW_SYS_BASE), false);
 	realview_timer_init(IRQ_TC11MP_TIMER0_1);
 	realview_pb11mp_twd_init();
 }
@@ -357,15 +357,12 @@ static void __init realview_pb11mp_init(void)
 		struct amba_device *d = amba_devs[i];
 		amba_device_register(d, &iomem_resource);
 	}
-
-#ifdef CONFIG_LEDS
-	leds_event = realview_leds_event;
-#endif
 }
 
 MACHINE_START(REALVIEW_PB11MP, "ARM-RealView PB11MPCore")
 	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
 	.atag_offset	= 0x100,
+	.smp		= smp_ops(realview_smp_ops),
 	.fixup		= realview_fixup,
 	.map_io		= realview_pb11mp_map_io,
 	.init_early	= realview_init_early,
diff --git a/arch/arm/mach-realview/realview_pba8.c b/arch/arm/mach-realview/realview_pba8.c
index 5965017..9992431 100644
--- a/arch/arm/mach-realview/realview_pba8.c
+++ b/arch/arm/mach-realview/realview_pba8.c
@@ -27,11 +27,10 @@
 #include <linux/amba/mmci.h>
 #include <linux/amba/pl022.h>
 #include <linux/io.h>
+#include <linux/platform_data/clk-realview.h>
 
 #include <asm/irq.h>
-#include <asm/leds.h>
 #include <asm/mach-types.h>
-#include <asm/pmu.h>
 #include <asm/pgtable.h>
 #include <asm/hardware/gic.h>
 
@@ -241,7 +240,7 @@ static struct resource pmu_resource = {
 
 static struct platform_device pmu_device = {
 	.name			= "arm-pmu",
-	.id			= ARM_PMU_DEVICE_CPU,
+	.id			= -1,
 	.num_resources		= 1,
 	.resource		= &pmu_resource,
 };
@@ -261,6 +260,7 @@ static void __init realview_pba8_timer_init(void)
 	timer2_va_base = __io_address(REALVIEW_PBA8_TIMER2_3_BASE);
 	timer3_va_base = __io_address(REALVIEW_PBA8_TIMER2_3_BASE) + 0x20;
 
+	realview_clk_init(__io_address(REALVIEW_SYS_BASE), false);
 	realview_timer_init(IRQ_PBA8_TIMER0_1);
 }
 
@@ -299,10 +299,6 @@ static void __init realview_pba8_init(void)
 		struct amba_device *d = amba_devs[i];
 		amba_device_register(d, &iomem_resource);
 	}
-
-#ifdef CONFIG_LEDS
-	leds_event = realview_leds_event;
-#endif
 }
 
 MACHINE_START(REALVIEW_PBA8, "ARM-RealView PB-A8")
diff --git a/arch/arm/mach-realview/realview_pbx.c b/arch/arm/mach-realview/realview_pbx.c
index 3f2f605..4f486f0 100644
--- a/arch/arm/mach-realview/realview_pbx.c
+++ b/arch/arm/mach-realview/realview_pbx.c
@@ -26,11 +26,10 @@
 #include <linux/amba/mmci.h>
 #include <linux/amba/pl022.h>
 #include <linux/io.h>
+#include <linux/platform_data/clk-realview.h>
 
 #include <asm/irq.h>
-#include <asm/leds.h>
 #include <asm/mach-types.h>
-#include <asm/pmu.h>
 #include <asm/smp_twd.h>
 #include <asm/pgtable.h>
 #include <asm/hardware/gic.h>
@@ -280,7 +279,7 @@ static struct resource pmu_resources[] = {
 
 static struct platform_device pmu_device = {
 	.name			= "arm-pmu",
-	.id			= ARM_PMU_DEVICE_CPU,
+	.id			= -1,
 	.num_resources		= ARRAY_SIZE(pmu_resources),
 	.resource		= pmu_resources,
 };
@@ -320,6 +319,7 @@ static void __init realview_pbx_timer_init(void)
 	timer2_va_base = __io_address(REALVIEW_PBX_TIMER2_3_BASE);
 	timer3_va_base = __io_address(REALVIEW_PBX_TIMER2_3_BASE) + 0x20;
 
+	realview_clk_init(__io_address(REALVIEW_SYS_BASE), false);
 	realview_timer_init(IRQ_PBX_TIMER0_1);
 	realview_pbx_twd_init();
 }
@@ -394,15 +394,12 @@ static void __init realview_pbx_init(void)
 		struct amba_device *d = amba_devs[i];
 		amba_device_register(d, &iomem_resource);
 	}
-
-#ifdef CONFIG_LEDS
-	leds_event = realview_leds_event;
-#endif
 }
 
 MACHINE_START(REALVIEW_PBX, "ARM-RealView PBX")
 	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
 	.atag_offset	= 0x100,
+	.smp		= smp_ops(realview_smp_ops),
 	.fixup		= realview_pbx_fixup,
 	.map_io		= realview_pbx_map_io,
 	.init_early	= realview_init_early,
diff --git a/arch/arm/mach-s3c24xx/clock-s3c2440.c b/arch/arm/mach-s3c24xx/clock-s3c2440.c
index cb2883d..749220f 100644
--- a/arch/arm/mach-s3c24xx/clock-s3c2440.c
+++ b/arch/arm/mach-s3c24xx/clock-s3c2440.c
@@ -87,6 +87,19 @@ static int s3c2440_camif_upll_setrate(struct clk *clk, unsigned long rate)
 	return 0;
 }
 
+static unsigned long s3c2440_camif_upll_getrate(struct clk *clk)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	unsigned long camdivn =  __raw_readl(S3C2440_CAMDIVN);
+
+	if (!(camdivn & S3C2440_CAMDIVN_CAMCLK_SEL))
+		return parent_rate;
+
+	camdivn &= S3C2440_CAMDIVN_CAMCLK_MASK;
+
+	return parent_rate / (camdivn + 1) / 2;
+}
+
 /* Extra S3C2440 clocks */
 
 static struct clk s3c2440_clk_cam = {
@@ -99,6 +112,7 @@ static struct clk s3c2440_clk_cam_upll = {
 	.name		= "camif-upll",
 	.ops		= &(struct clk_ops) {
 		.set_rate	= s3c2440_camif_upll_setrate,
+		.get_rate	= s3c2440_camif_upll_getrate,
 		.round_rate	= s3c2440_camif_upll_round,
 	},
 };
diff --git a/arch/arm/mach-s3c24xx/common-smdk.c b/arch/arm/mach-s3c24xx/common-smdk.c
index 87e75a2..3b2cf6d 100644
--- a/arch/arm/mach-s3c24xx/common-smdk.c
+++ b/arch/arm/mach-s3c24xx/common-smdk.c
@@ -37,9 +37,9 @@
 #include <asm/irq.h>
 
 #include <mach/regs-gpio.h>
-#include <mach/leds-gpio.h>
+#include <linux/platform_data/leds-s3c24xx.h>
 
-#include <plat/nand.h>
+#include <linux/platform_data/mtd-nand-s3c2410.h>
 
 #include <plat/common-smdk.h>
 #include <plat/gpio-cfg.h>
diff --git a/arch/arm/mach-s3c24xx/h1940-bluetooth.c b/arch/arm/mach-s3c24xx/h1940-bluetooth.c
index a5eeb62..57aee91 100644
--- a/arch/arm/mach-s3c24xx/h1940-bluetooth.c
+++ b/arch/arm/mach-s3c24xx/h1940-bluetooth.c
@@ -138,19 +138,7 @@ static struct platform_driver h1940bt_driver = {
 	.remove		= h1940bt_remove,
 };
 
-
-static int __init h1940bt_init(void)
-{
-	return platform_driver_register(&h1940bt_driver);
-}
-
-static void __exit h1940bt_exit(void)
-{
-	platform_driver_unregister(&h1940bt_driver);
-}
-
-module_init(h1940bt_init);
-module_exit(h1940bt_exit);
+module_platform_driver(h1940bt_driver);
 
 MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");
 MODULE_DESCRIPTION("Driver for the iPAQ H1940 bluetooth chip");
diff --git a/arch/arm/mach-s3c24xx/include/mach/leds-gpio.h b/arch/arm/mach-s3c24xx/include/mach/leds-gpio.h
deleted file mode 100644
index d8a7672..0000000
--- a/arch/arm/mach-s3c24xx/include/mach/leds-gpio.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/* arch/arm/mach-s3c2410/include/mach/leds-gpio.h
- *
- * Copyright (c) 2006 Simtec Electronics
- *	http://armlinux.simtec.co.uk/
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C24XX - LEDs GPIO connector
- *
- * This program is free software; you can 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_LEDSGPIO_H
-#define __ASM_ARCH_LEDSGPIO_H "leds-gpio.h"
-
-#define S3C24XX_LEDF_ACTLOW	(1<<0)		/* LED is on when GPIO low */
-#define S3C24XX_LEDF_TRISTATE	(1<<1)		/* tristate to turn off */
-
-struct s3c24xx_led_platdata {
-	unsigned int		 gpio;
-	unsigned int		 flags;
-
-	char			*name;
-	char			*def_trigger;
-};
-
-#endif /* __ASM_ARCH_LEDSGPIO_H */
diff --git a/arch/arm/mach-s3c24xx/mach-amlm5900.c b/arch/arm/mach-s3c24xx/mach-amlm5900.c
index ea2c4b0..f4ad99c 100644
--- a/arch/arm/mach-s3c24xx/mach-amlm5900.c
+++ b/arch/arm/mach-s3c24xx/mach-amlm5900.c
@@ -53,7 +53,7 @@
 #include <mach/regs-lcd.h>
 #include <mach/regs-gpio.h>
 
-#include <plat/iic.h>
+#include <linux/platform_data/i2c-s3c2410.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
 #include <plat/gpio-cfg.h>
diff --git a/arch/arm/mach-s3c24xx/mach-anubis.c b/arch/arm/mach-s3c24xx/mach-anubis.c
index 5a7d0c0..1ee8c46 100644
--- a/arch/arm/mach-s3c24xx/mach-anubis.c
+++ b/arch/arm/mach-s3c24xx/mach-anubis.c
@@ -40,8 +40,8 @@
 #include <mach/regs-gpio.h>
 #include <mach/regs-mem.h>
 #include <mach/regs-lcd.h>
-#include <plat/nand.h>
-#include <plat/iic.h>
+#include <linux/platform_data/mtd-nand-s3c2410.h>
+#include <linux/platform_data/i2c-s3c2410.h>
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
@@ -53,7 +53,7 @@
 #include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
-#include <plat/audio-simtec.h>
+#include <linux/platform_data/asoc-s3c24xx_simtec.h>
 
 #include "simtec.h"
 #include "common.h"
@@ -424,7 +424,8 @@ static void __init anubis_map_io(void)
 		anubis_nand_sets[0].nr_partitions = ARRAY_SIZE(anubis_default_nand_part_large);
 	} else {
 		/* ensure that the GPIO is setup */
-		s3c2410_gpio_setpin(S3C2410_GPA(0), 1);
+		gpio_request_one(S3C2410_GPA(0), GPIOF_OUT_INIT_HIGH, NULL);
+		gpio_free(S3C2410_GPA(0));
 	}
 }
 
diff --git a/arch/arm/mach-s3c24xx/mach-at2440evb.c b/arch/arm/mach-s3c24xx/mach-at2440evb.c
index 7a05abf..00381fe 100644
--- a/arch/arm/mach-s3c24xx/mach-at2440evb.c
+++ b/arch/arm/mach-s3c24xx/mach-at2440evb.c
@@ -36,8 +36,8 @@
 #include <mach/regs-gpio.h>
 #include <mach/regs-mem.h>
 #include <mach/regs-lcd.h>
-#include <plat/nand.h>
-#include <plat/iic.h>
+#include <linux/platform_data/mtd-nand-s3c2410.h>
+#include <linux/platform_data/i2c-s3c2410.h>
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
@@ -47,7 +47,7 @@
 #include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
-#include <plat/mci.h>
+#include <linux/platform_data/mmc-s3cmci.h>
 
 #include "common.h"
 
diff --git a/arch/arm/mach-s3c24xx/mach-bast.c b/arch/arm/mach-s3c24xx/mach-bast.c
index 1cf1720..6a30ce7 100644
--- a/arch/arm/mach-s3c24xx/mach-bast.c
+++ b/arch/arm/mach-s3c24xx/mach-bast.c
@@ -45,9 +45,9 @@
 #include <mach/regs-mem.h>
 #include <mach/regs-lcd.h>
 
-#include <plat/hwmon.h>
-#include <plat/nand.h>
-#include <plat/iic.h>
+#include <linux/platform_data/hwmon-s3c.h>
+#include <linux/platform_data/mtd-nand-s3c2410.h>
+#include <linux/platform_data/i2c-s3c2410.h>
 #include <mach/fb.h>
 
 #include <linux/mtd/mtd.h>
@@ -62,7 +62,7 @@
 #include <plat/cpu.h>
 #include <plat/cpu-freq.h>
 #include <plat/gpio-cfg.h>
-#include <plat/audio-simtec.h>
+#include <linux/platform_data/asoc-s3c24xx_simtec.h>
 
 #include "simtec.h"
 #include "common.h"
diff --git a/arch/arm/mach-s3c24xx/mach-gta02.c b/arch/arm/mach-s3c24xx/mach-gta02.c
index 92e1f93..4a96346 100644
--- a/arch/arm/mach-s3c24xx/mach-gta02.c
+++ b/arch/arm/mach-s3c24xx/mach-gta02.c
@@ -73,21 +73,21 @@
 #include <mach/regs-gpio.h>
 #include <mach/fb.h>
 
-#include <plat/usb-control.h>
+#include <linux/platform_data/usb-ohci-s3c2410.h>
 #include <mach/regs-mem.h>
 #include <mach/hardware.h>
 
 #include <mach/gta02.h>
 
 #include <plat/regs-serial.h>
-#include <plat/nand.h>
+#include <linux/platform_data/mtd-nand-s3c2410.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
 #include <plat/pm.h>
-#include <plat/udc.h>
+#include <linux/platform_data/usb-s3c2410_udc.h>
 #include <plat/gpio-cfg.h>
-#include <plat/iic.h>
-#include <plat/ts.h>
+#include <linux/platform_data/i2c-s3c2410.h>
+#include <linux/platform_data/touchscreen-s3c2410.h>
 
 #include "common.h"
 
diff --git a/arch/arm/mach-s3c24xx/mach-h1940.c b/arch/arm/mach-s3c24xx/mach-h1940.c
index bb8d008..63aaf07 100644
--- a/arch/arm/mach-s3c24xx/mach-h1940.c
+++ b/arch/arm/mach-s3c24xx/mach-h1940.c
@@ -56,8 +56,8 @@
 #include <mach/h1940.h>
 #include <mach/h1940-latch.h>
 #include <mach/fb.h>
-#include <plat/udc.h>
-#include <plat/iic.h>
+#include <linux/platform_data/usb-s3c2410_udc.h>
+#include <linux/platform_data/i2c-s3c2410.h>
 
 #include <plat/gpio-cfg.h>
 #include <plat/clock.h>
@@ -65,8 +65,8 @@
 #include <plat/cpu.h>
 #include <plat/pll.h>
 #include <plat/pm.h>
-#include <plat/mci.h>
-#include <plat/ts.h>
+#include <linux/platform_data/mmc-s3cmci.h>
+#include <linux/platform_data/touchscreen-s3c2410.h>
 
 #include <sound/uda1380.h>
 
@@ -380,7 +380,7 @@ int h1940_led_blink_set(unsigned gpio, int state,
 	default:
 		blink_gpio = S3C2410_GPA(3);
 		check_gpio1 = S3C2410_GPA(1);
-		check_gpio1 = S3C2410_GPA(7);
+		check_gpio2 = S3C2410_GPA(7);
 		break;
 	}
 
@@ -460,7 +460,7 @@ static void h1940_set_mmc_power(unsigned char power_mode, unsigned short vdd)
 		break;
 	default:
 		break;
-	};
+	}
 }
 
 static struct s3c24xx_mci_pdata h1940_mmc_cfg __initdata = {
diff --git a/arch/arm/mach-s3c24xx/mach-jive.c b/arch/arm/mach-s3c24xx/mach-jive.c
index ae73ba3..c9954e2 100644
--- a/arch/arm/mach-s3c24xx/mach-jive.c
+++ b/arch/arm/mach-s3c24xx/mach-jive.c
@@ -32,8 +32,8 @@
 #include <asm/mach/irq.h>
 
 #include <plat/regs-serial.h>
-#include <plat/nand.h>
-#include <plat/iic.h>
+#include <linux/platform_data/mtd-nand-s3c2410.h>
+#include <linux/platform_data/i2c-s3c2410.h>
 
 #include <mach/regs-power.h>
 #include <mach/regs-gpio.h>
@@ -54,7 +54,7 @@
 #include <plat/devs.h>
 #include <plat/cpu.h>
 #include <plat/pm.h>
-#include <plat/udc.h>
+#include <linux/platform_data/usb-s3c2410_udc.h>
 
 static struct map_desc jive_iodesc[] __initdata = {
 };
@@ -512,8 +512,8 @@ static void jive_power_off(void)
 {
 	printk(KERN_INFO "powering system down...\n");
 
-	s3c2410_gpio_setpin(S3C2410_GPC(5), 1);
-	s3c_gpio_cfgpin(S3C2410_GPC(5), S3C2410_GPIO_OUTPUT);
+	gpio_request_one(S3C2410_GPC(5), GPIOF_OUT_INIT_HIGH, NULL);
+	gpio_free(S3C2410_GPC(5));
 }
 
 static void __init jive_machine_init(void)
@@ -623,11 +623,11 @@ static void __init jive_machine_init(void)
 	gpio_request(S3C2410_GPB(7), "jive spi");
 	gpio_direction_output(S3C2410_GPB(7), 1);
 
-	s3c2410_gpio_setpin(S3C2410_GPB(6), 0);
-	s3c_gpio_cfgpin(S3C2410_GPB(6), S3C2410_GPIO_OUTPUT);
+	gpio_request_one(S3C2410_GPB(6), GPIOF_OUT_INIT_LOW, NULL);
+	gpio_free(S3C2410_GPB(6));
 
-	s3c2410_gpio_setpin(S3C2410_GPG(8), 1);
-	s3c_gpio_cfgpin(S3C2410_GPG(8), S3C2410_GPIO_OUTPUT);
+	gpio_request_one(S3C2410_GPG(8), GPIOF_OUT_INIT_HIGH, NULL);
+	gpio_free(S3C2410_GPG(8));
 
 	/* initialise the WM8750 spi */
 
diff --git a/arch/arm/mach-s3c24xx/mach-mini2440.c b/arch/arm/mach-s3c24xx/mach-mini2440.c
index bd6d252..393c0f1 100644
--- a/arch/arm/mach-s3c24xx/mach-mini2440.c
+++ b/arch/arm/mach-s3c24xx/mach-mini2440.c
@@ -39,14 +39,14 @@
 
 #include <plat/regs-serial.h>
 #include <mach/regs-gpio.h>
-#include <mach/leds-gpio.h>
+#include <linux/platform_data/leds-s3c24xx.h>
 #include <mach/regs-mem.h>
 #include <mach/regs-lcd.h>
 #include <mach/irqs.h>
-#include <plat/nand.h>
-#include <plat/iic.h>
-#include <plat/mci.h>
-#include <plat/udc.h>
+#include <linux/platform_data/mtd-nand-s3c2410.h>
+#include <linux/platform_data/i2c-s3c2410.h>
+#include <linux/platform_data/mmc-s3cmci.h>
+#include <linux/platform_data/usb-s3c2410_udc.h>
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
@@ -638,9 +638,9 @@ static void __init mini2440_init(void)
 	gpio_free(S3C2410_GPG(4));
 
 	/* remove pullup on optional PWM backlight -- unused on 3.5 and 7"s */
+	gpio_request_one(S3C2410_GPB(1), GPIOF_IN, NULL);
 	s3c_gpio_setpull(S3C2410_GPB(1), S3C_GPIO_PULL_UP);
-	s3c2410_gpio_setpin(S3C2410_GPB(1), 0);
-	s3c_gpio_cfgpin(S3C2410_GPB(1), S3C2410_GPIO_INPUT);
+	gpio_free(S3C2410_GPB(1));
 
 	/* mark the key as input, without pullups (there is one on the board) */
 	for (i = 0; i < ARRAY_SIZE(mini2440_buttons); i++) {
diff --git a/arch/arm/mach-s3c24xx/mach-n30.c b/arch/arm/mach-s3c24xx/mach-n30.c
index 383d00c..c53a9bf 100644
--- a/arch/arm/mach-s3c24xx/mach-n30.c
+++ b/arch/arm/mach-s3c24xx/mach-n30.c
@@ -33,7 +33,7 @@
 #include <asm/mach-types.h>
 
 #include <mach/fb.h>
-#include <mach/leds-gpio.h>
+#include <linux/platform_data/leds-s3c24xx.h>
 #include <mach/regs-gpio.h>
 #include <mach/regs-lcd.h>
 
@@ -41,15 +41,15 @@
 #include <asm/mach/irq.h>
 #include <asm/mach/map.h>
 
-#include <plat/iic.h>
+#include <linux/platform_data/i2c-s3c2410.h>
 #include <plat/regs-serial.h>
 
 #include <plat/clock.h>
 #include <plat/cpu.h>
 #include <plat/devs.h>
-#include <plat/mci.h>
+#include <linux/platform_data/mmc-s3cmci.h>
 #include <plat/s3c2410.h>
-#include <plat/udc.h>
+#include <linux/platform_data/usb-s3c2410_udc.h>
 
 #include "common.h"
 
diff --git a/arch/arm/mach-s3c24xx/mach-nexcoder.c b/arch/arm/mach-s3c24xx/mach-nexcoder.c
index 5c05ba1..a2b92b0 100644
--- a/arch/arm/mach-s3c24xx/mach-nexcoder.c
+++ b/arch/arm/mach-s3c24xx/mach-nexcoder.c
@@ -38,7 +38,7 @@
 //#include <asm/debug-ll.h>
 #include <mach/regs-gpio.h>
 #include <plat/regs-serial.h>
-#include <plat/iic.h>
+#include <linux/platform_data/i2c-s3c2410.h>
 
 #include <plat/gpio-cfg.h>
 #include <plat/s3c2410.h>
@@ -119,17 +119,17 @@ static struct platform_device *nexcoder_devices[] __initdata = {
 
 static void __init nexcoder_sensorboard_init(void)
 {
-	// Initialize SCCB bus
-	s3c2410_gpio_setpin(S3C2410_GPE(14), 1); // IICSCL
-	s3c_gpio_cfgpin(S3C2410_GPE(14), S3C2410_GPIO_OUTPUT);
-	s3c2410_gpio_setpin(S3C2410_GPE(15), 1); // IICSDA
-	s3c_gpio_cfgpin(S3C2410_GPE(15), S3C2410_GPIO_OUTPUT);
-
-	// Power up the sensor board
-	s3c2410_gpio_setpin(S3C2410_GPF(1), 1);
-	s3c_gpio_cfgpin(S3C2410_GPF(1), S3C2410_GPIO_OUTPUT); // CAM_GPIO7 => nLDO_PWRDN
-	s3c2410_gpio_setpin(S3C2410_GPF(2), 0);
-	s3c_gpio_cfgpin(S3C2410_GPF(2), S3C2410_GPIO_OUTPUT); // CAM_GPIO6 => CAM_PWRDN
+	/* Initialize SCCB bus */
+	gpio_request_one(S3C2410_GPE(14), GPIOF_OUT_INIT_HIGH, NULL);
+	gpio_free(S3C2410_GPE(14)); /* IICSCL */
+	gpio_request_one(S3C2410_GPE(15), GPIOF_OUT_INIT_HIGH, NULL);
+	gpio_free(S3C2410_GPE(15)); /* IICSDA */
+
+	/* Power up the sensor board */
+	gpio_request_one(S3C2410_GPF(1), GPIOF_OUT_INIT_HIGH, NULL);
+	gpio_free(S3C2410_GPF(1)); /* CAM_GPIO7 => nLDO_PWRDN */
+	gpio_request_one(S3C2410_GPF(2), GPIOF_OUT_INIT_LOW, NULL);
+	gpio_free(S3C2410_GPF(2)); /* CAM_GPIO6 => CAM_PWRDN */
 }
 
 static void __init nexcoder_map_io(void)
diff --git a/arch/arm/mach-s3c24xx/mach-osiris-dvs.c b/arch/arm/mach-s3c24xx/mach-osiris-dvs.c
index ad2792d..5876c6b 100644
--- a/arch/arm/mach-s3c24xx/mach-osiris-dvs.c
+++ b/arch/arm/mach-s3c24xx/mach-osiris-dvs.c
@@ -175,18 +175,7 @@ static struct platform_driver osiris_dvs_driver = {
 	},
 };
 
-static int __init osiris_dvs_init(void)
-{
-	return platform_driver_register(&osiris_dvs_driver);
-}
-
-static void __exit osiris_dvs_exit(void)
-{
-	platform_driver_unregister(&osiris_dvs_driver);
-}
-
-module_init(osiris_dvs_init);
-module_exit(osiris_dvs_exit);
+module_platform_driver(osiris_dvs_driver);
 
 MODULE_DESCRIPTION("Simtec OSIRIS DVS support");
 MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
diff --git a/arch/arm/mach-s3c24xx/mach-osiris.c b/arch/arm/mach-s3c24xx/mach-osiris.c
index 95d0772..bb36d83 100644
--- a/arch/arm/mach-s3c24xx/mach-osiris.c
+++ b/arch/arm/mach-s3c24xx/mach-osiris.c
@@ -41,8 +41,8 @@
 #include <mach/regs-gpio.h>
 #include <mach/regs-mem.h>
 #include <mach/regs-lcd.h>
-#include <plat/nand.h>
-#include <plat/iic.h>
+#include <linux/platform_data/mtd-nand-s3c2410.h>
+#include <linux/platform_data/i2c-s3c2410.h>
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
@@ -274,8 +274,8 @@ static int osiris_pm_suspend(void)
 	__raw_writeb(tmp, OSIRIS_VA_CTRL0);
 
 	/* ensure that an nRESET is not generated on resume. */
-	s3c2410_gpio_setpin(S3C2410_GPA(21), 1);
-	s3c_gpio_cfgpin(S3C2410_GPA(21), S3C2410_GPIO_OUTPUT);
+	gpio_request_one(S3C2410_GPA(21), GPIOF_OUT_INIT_HIGH, NULL);
+	gpio_free(S3C2410_GPA(21));
 
 	return 0;
 }
@@ -396,7 +396,8 @@ static void __init osiris_map_io(void)
 		osiris_nand_sets[0].nr_partitions = ARRAY_SIZE(osiris_default_nand_part_large);
 	} else {
 		/* write-protect line to the NAND */
-		s3c2410_gpio_setpin(S3C2410_GPA(0), 1);
+		gpio_request_one(S3C2410_GPA(0), GPIOF_OUT_INIT_HIGH, NULL);
+		gpio_free(S3C2410_GPA(0));
 	}
 
 	/* fix bus configuration (nBE settings wrong on ABLE pre v2.20) */
diff --git a/arch/arm/mach-s3c24xx/mach-otom.c b/arch/arm/mach-s3c24xx/mach-otom.c
index bc4b6ef..bca39f0 100644
--- a/arch/arm/mach-s3c24xx/mach-otom.c
+++ b/arch/arm/mach-s3c24xx/mach-otom.c
@@ -35,7 +35,7 @@
 #include <plat/s3c2410.h>
 #include <plat/clock.h>
 #include <plat/devs.h>
-#include <plat/iic.h>
+#include <linux/platform_data/i2c-s3c2410.h>
 #include <plat/cpu.h>
 
 #include "common.h"
diff --git a/arch/arm/mach-s3c24xx/mach-qt2410.c b/arch/arm/mach-s3c24xx/mach-qt2410.c
index 678bbca..7b6ba13 100644
--- a/arch/arm/mach-s3c24xx/mach-qt2410.c
+++ b/arch/arm/mach-s3c24xx/mach-qt2410.c
@@ -47,13 +47,13 @@
 #include <asm/irq.h>
 #include <asm/mach-types.h>
 
-#include <mach/leds-gpio.h>
+#include <linux/platform_data/leds-s3c24xx.h>
 #include <mach/regs-lcd.h>
 #include <plat/regs-serial.h>
 #include <mach/fb.h>
-#include <plat/nand.h>
-#include <plat/udc.h>
-#include <plat/iic.h>
+#include <linux/platform_data/mtd-nand-s3c2410.h>
+#include <linux/platform_data/usb-s3c2410_udc.h>
+#include <linux/platform_data/i2c-s3c2410.h>
 
 #include <plat/common-smdk.h>
 #include <plat/gpio-cfg.h>
diff --git a/arch/arm/mach-s3c24xx/mach-rx1950.c b/arch/arm/mach-s3c24xx/mach-rx1950.c
index 7ee73f2..379fde5 100644
--- a/arch/arm/mach-s3c24xx/mach-rx1950.c
+++ b/arch/arm/mach-s3c24xx/mach-rx1950.c
@@ -49,15 +49,15 @@
 #include <plat/clock.h>
 #include <plat/regs-serial.h>
 #include <plat/regs-iic.h>
-#include <plat/mci.h>
-#include <plat/udc.h>
-#include <plat/nand.h>
-#include <plat/iic.h>
+#include <linux/platform_data/mmc-s3cmci.h>
+#include <linux/platform_data/usb-s3c2410_udc.h>
+#include <linux/platform_data/mtd-nand-s3c2410.h>
+#include <linux/platform_data/i2c-s3c2410.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
 #include <plat/pm.h>
 #include <plat/irq.h>
-#include <plat/ts.h>
+#include <linux/platform_data/touchscreen-s3c2410.h>
 
 #include <sound/uda1380.h>
 
diff --git a/arch/arm/mach-s3c24xx/mach-rx3715.c b/arch/arm/mach-s3c24xx/mach-rx3715.c
index 56af354..dacbb9a 100644
--- a/arch/arm/mach-s3c24xx/mach-rx3715.c
+++ b/arch/arm/mach-s3c24xx/mach-rx3715.c
@@ -43,7 +43,7 @@
 #include <mach/regs-lcd.h>
 
 #include <mach/h1940.h>
-#include <plat/nand.h>
+#include <linux/platform_data/mtd-nand-s3c2410.h>
 #include <mach/fb.h>
 
 #include <plat/clock.h>
diff --git a/arch/arm/mach-s3c24xx/mach-smdk2410.c b/arch/arm/mach-s3c24xx/mach-smdk2410.c
index bdc27e7..82796b9 100644
--- a/arch/arm/mach-s3c24xx/mach-smdk2410.c
+++ b/arch/arm/mach-s3c24xx/mach-smdk2410.c
@@ -47,7 +47,7 @@
 #include <asm/mach-types.h>
 
 #include <plat/regs-serial.h>
-#include <plat/iic.h>
+#include <linux/platform_data/i2c-s3c2410.h>
 
 #include <plat/devs.h>
 #include <plat/cpu.h>
diff --git a/arch/arm/mach-s3c24xx/mach-smdk2413.c b/arch/arm/mach-s3c24xx/mach-smdk2413.c
index b11451b..ce99fd8 100644
--- a/arch/arm/mach-s3c24xx/mach-smdk2413.c
+++ b/arch/arm/mach-s3c24xx/mach-smdk2413.c
@@ -38,8 +38,8 @@
 #include <mach/regs-lcd.h>
 
 #include <mach/idle.h>
-#include <plat/udc.h>
-#include <plat/iic.h>
+#include <linux/platform_data/usb-s3c2410_udc.h>
+#include <linux/platform_data/i2c-s3c2410.h>
 #include <mach/fb.h>
 
 #include <plat/s3c2410.h>
diff --git a/arch/arm/mach-s3c24xx/mach-smdk2416.c b/arch/arm/mach-s3c24xx/mach-smdk2416.c
index c3100a0..f30d7fc 100644
--- a/arch/arm/mach-s3c24xx/mach-smdk2416.c
+++ b/arch/arm/mach-s3c24xx/mach-smdk2416.c
@@ -29,6 +29,7 @@
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 
+#include <video/samsung_fimd.h>
 #include <mach/hardware.h>
 #include <asm/irq.h>
 #include <asm/mach-types.h>
@@ -39,20 +40,19 @@
 #include <mach/regs-s3c2443-clock.h>
 
 #include <mach/idle.h>
-#include <mach/leds-gpio.h>
-#include <plat/iic.h>
+#include <linux/platform_data/leds-s3c24xx.h>
+#include <linux/platform_data/i2c-s3c2410.h>
 
 #include <plat/s3c2416.h>
 #include <plat/gpio-cfg.h>
 #include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
-#include <plat/nand.h>
+#include <linux/platform_data/mtd-nand-s3c2410.h>
 #include <plat/sdhci.h>
-#include <plat/udc.h>
+#include <linux/platform_data/usb-s3c2410_udc.h>
 #include <linux/platform_data/s3c-hsudc.h>
 
-#include <plat/regs-fb-v4.h>
 #include <plat/fb.h>
 
 #include <plat/common-smdk.h>
diff --git a/arch/arm/mach-s3c24xx/mach-smdk2440.c b/arch/arm/mach-s3c24xx/mach-smdk2440.c
index 83a1036..b7ff882 100644
--- a/arch/arm/mach-s3c24xx/mach-smdk2440.c
+++ b/arch/arm/mach-s3c24xx/mach-smdk2440.c
@@ -37,7 +37,7 @@
 
 #include <mach/idle.h>
 #include <mach/fb.h>
-#include <plat/iic.h>
+#include <linux/platform_data/i2c-s3c2410.h>
 
 #include <plat/s3c2410.h>
 #include <plat/s3c244x.h>
diff --git a/arch/arm/mach-s3c24xx/mach-smdk2443.c b/arch/arm/mach-s3c24xx/mach-smdk2443.c
index 2092369..2568656 100644
--- a/arch/arm/mach-s3c24xx/mach-smdk2443.c
+++ b/arch/arm/mach-s3c24xx/mach-smdk2443.c
@@ -37,7 +37,7 @@
 
 #include <mach/idle.h>
 #include <mach/fb.h>
-#include <plat/iic.h>
+#include <linux/platform_data/i2c-s3c2410.h>
 
 #include <plat/s3c2410.h>
 #include <plat/s3c2443.h>
diff --git a/arch/arm/mach-s3c24xx/mach-tct_hammer.c b/arch/arm/mach-s3c24xx/mach-tct_hammer.c
index fe99028..495bf5c 100644
--- a/arch/arm/mach-s3c24xx/mach-tct_hammer.c
+++ b/arch/arm/mach-s3c24xx/mach-tct_hammer.c
@@ -45,7 +45,7 @@
 #include <asm/mach-types.h>
 
 #include <plat/regs-serial.h>
-#include <plat/iic.h>
+#include <linux/platform_data/i2c-s3c2410.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
 
diff --git a/arch/arm/mach-s3c24xx/mach-vr1000.c b/arch/arm/mach-s3c24xx/mach-vr1000.c
index bd5f189..14d5b12 100644
--- a/arch/arm/mach-s3c24xx/mach-vr1000.c
+++ b/arch/arm/mach-s3c24xx/mach-vr1000.c
@@ -43,13 +43,13 @@
 
 #include <plat/regs-serial.h>
 #include <mach/regs-gpio.h>
-#include <mach/leds-gpio.h>
+#include <linux/platform_data/leds-s3c24xx.h>
 
 #include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
-#include <plat/iic.h>
-#include <plat/audio-simtec.h>
+#include <linux/platform_data/i2c-s3c2410.h>
+#include <linux/platform_data/asoc-s3c24xx_simtec.h>
 
 #include "simtec.h"
 #include "common.h"
diff --git a/arch/arm/mach-s3c24xx/mach-vstms.c b/arch/arm/mach-s3c24xx/mach-vstms.c
index 94bfaa1..f1d44ae 100644
--- a/arch/arm/mach-s3c24xx/mach-vstms.c
+++ b/arch/arm/mach-s3c24xx/mach-vstms.c
@@ -39,8 +39,8 @@
 #include <mach/idle.h>
 #include <mach/fb.h>
 
-#include <plat/iic.h>
-#include <plat/nand.h>
+#include <linux/platform_data/i2c-s3c2410.h>
+#include <linux/platform_data/mtd-nand-s3c2410.h>
 
 #include <plat/s3c2410.h>
 #include <plat/s3c2412.h>
diff --git a/arch/arm/mach-s3c24xx/setup-i2c.c b/arch/arm/mach-s3c24xx/setup-i2c.c
index 9e90a7c..7b4f333 100644
--- a/arch/arm/mach-s3c24xx/setup-i2c.c
+++ b/arch/arm/mach-s3c24xx/setup-i2c.c
@@ -16,7 +16,7 @@
 struct platform_device;
 
 #include <plat/gpio-cfg.h>
-#include <plat/iic.h>
+#include <linux/platform_data/i2c-s3c2410.h>
 #include <mach/hardware.h>
 #include <mach/regs-gpio.h>
 
diff --git a/arch/arm/mach-s3c24xx/simtec-audio.c b/arch/arm/mach-s3c24xx/simtec-audio.c
index 11881c9..fd0ef05 100644
--- a/arch/arm/mach-s3c24xx/simtec-audio.c
+++ b/arch/arm/mach-s3c24xx/simtec-audio.c
@@ -24,7 +24,7 @@
 #include <mach/hardware.h>
 #include <mach/regs-gpio.h>
 
-#include <plat/audio-simtec.h>
+#include <linux/platform_data/asoc-s3c24xx_simtec.h>
 #include <plat/devs.h>
 
 #include "simtec.h"
diff --git a/arch/arm/mach-s3c24xx/simtec-usb.c b/arch/arm/mach-s3c24xx/simtec-usb.c
index d91c1a7..17f8356 100644
--- a/arch/arm/mach-s3c24xx/simtec-usb.c
+++ b/arch/arm/mach-s3c24xx/simtec-usb.c
@@ -34,7 +34,7 @@
 #include <mach/hardware.h>
 #include <asm/irq.h>
 
-#include <plat/usb-control.h>
+#include <linux/platform_data/usb-ohci-s3c2410.h>
 #include <plat/devs.h>
 
 #include "simtec.h"
diff --git a/arch/arm/mach-s3c64xx/dev-audio.c b/arch/arm/mach-s3c64xx/dev-audio.c
index 124fd5d..35f3e07 100644
--- a/arch/arm/mach-s3c64xx/dev-audio.c
+++ b/arch/arm/mach-s3c64xx/dev-audio.c
@@ -20,7 +20,7 @@
 #include <mach/dma.h>
 
 #include <plat/devs.h>
-#include <plat/audio.h>
+#include <linux/platform_data/asoc-s3c.h>
 #include <plat/gpio-cfg.h>
 
 static const char *rclksrc[] = {
diff --git a/arch/arm/mach-s3c64xx/mach-anw6410.c b/arch/arm/mach-s3c64xx/mach-anw6410.c
index ffa29dd..99e82ac 100644
--- a/arch/arm/mach-s3c64xx/mach-anw6410.c
+++ b/arch/arm/mach-s3c64xx/mach-anw6410.c
@@ -29,6 +29,7 @@
 #include <linux/dm9000.h>
 
 #include <video/platform_lcd.h>
+#include <video/samsung_fimd.h>
 
 #include <asm/hardware/vic.h>
 #include <asm/mach/arch.h>
@@ -42,9 +43,8 @@
 #include <asm/mach-types.h>
 
 #include <plat/regs-serial.h>
-#include <plat/iic.h>
+#include <linux/platform_data/i2c-s3c2410.h>
 #include <plat/fb.h>
-#include <plat/regs-fb-v4.h>
 
 #include <plat/clock.h>
 #include <plat/devs.h>
diff --git a/arch/arm/mach-s3c64xx/mach-crag6410-module.c b/arch/arm/mach-s3c64xx/mach-crag6410-module.c
index 9e382e7..4e3fe57 100644
--- a/arch/arm/mach-s3c64xx/mach-crag6410-module.c
+++ b/arch/arm/mach-s3c64xx/mach-crag6410-module.c
@@ -16,6 +16,7 @@
 #include <linux/mfd/wm831x/irq.h>
 #include <linux/mfd/wm831x/gpio.h>
 #include <linux/mfd/wm8994/pdata.h>
+#include <linux/mfd/arizona/pdata.h>
 
 #include <linux/regulator/machine.h>
 
@@ -24,7 +25,7 @@
 #include <sound/wm8962.h>
 #include <sound/wm9081.h>
 
-#include <plat/s3c64xx-spi.h>
+#include <linux/platform_data/spi-s3c64xx.h>
 
 #include <mach/crag6410.h>
 
@@ -181,9 +182,33 @@ static const struct i2c_board_info wm1277_devs[] = {
 	},
 };
 
-static const struct i2c_board_info wm5102_devs[] = {
-	{ I2C_BOARD_INFO("wm5102", 0x1a),
-	  .irq = GLENFARCLAS_PMIC_IRQ_BASE + WM831X_IRQ_GPIO_2, },
+static struct arizona_pdata wm5102_pdata = {
+	.ldoena = S3C64XX_GPN(7),
+	.gpio_base = CODEC_GPIO_BASE,
+	.irq_active_high = true,
+	.micd_pol_gpio = CODEC_GPIO_BASE + 4,
+	.gpio_defaults = {
+		[2] = 0x10000, /* AIF3TXLRCLK */
+		[3] = 0x4,     /* OPCLK */
+	},
+};
+
+static struct s3c64xx_spi_csinfo wm5102_spi_csinfo = {
+	.line = S3C64XX_GPN(5),
+};
+
+static struct spi_board_info wm5102_spi_devs[] = {
+	[0] = {
+		.modalias	= "wm5102",
+		.max_speed_hz	= 10 * 1000 * 1000,
+		.bus_num	= 0,
+		.chip_select	= 0,
+		.mode		= SPI_MODE_0,
+		.irq		= GLENFARCLAS_PMIC_IRQ_BASE +
+				  WM831X_IRQ_GPIO_2,
+		.controller_data = &wm5102_spi_csinfo,
+		.platform_data = &wm5102_pdata,
+	},
 };
 
 static const struct i2c_board_info wm6230_i2c_devs[] = {
@@ -223,8 +248,9 @@ static __devinitdata const struct {
 	{ .id = 0x3c, .name = "1273-EV1 Longmorn" },
 	{ .id = 0x3d, .name = "1277-EV1 Littlemill",
 	  .i2c_devs = wm1277_devs, .num_i2c_devs = ARRAY_SIZE(wm1277_devs) },
-	{ .id = 0x3e, .name = "WM5102-6271-EV1-CS127",
-	  .i2c_devs = wm5102_devs, .num_i2c_devs = ARRAY_SIZE(wm5102_devs) },
+	{ .id = 0x3e, .name = "WM5102-6271-EV1-CS127 Amrut",
+	  .spi_devs = wm5102_spi_devs,
+	  .num_spi_devs = ARRAY_SIZE(wm5102_spi_devs) },
 };
 
 static __devinit int wlf_gf_module_probe(struct i2c_client *i2c,
diff --git a/arch/arm/mach-s3c64xx/mach-crag6410.c b/arch/arm/mach-s3c64xx/mach-crag6410.c
index 09cd812..13b7eaa 100644
--- a/arch/arm/mach-s3c64xx/mach-crag6410.c
+++ b/arch/arm/mach-s3c64xx/mach-crag6410.c
@@ -46,6 +46,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 
+#include <video/samsung_fimd.h>
 #include <mach/hardware.h>
 #include <mach/map.h>
 
@@ -57,18 +58,17 @@
 #include <mach/regs-gpio-memport.h>
 
 #include <plat/regs-serial.h>
-#include <plat/regs-fb-v4.h>
 #include <plat/fb.h>
 #include <plat/sdhci.h>
 #include <plat/gpio-cfg.h>
-#include <plat/s3c64xx-spi.h>
+#include <linux/platform_data/spi-s3c64xx.h>
 
 #include <plat/keypad.h>
 #include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
 #include <plat/adc.h>
-#include <plat/iic.h>
+#include <linux/platform_data/i2c-s3c2410.h>
 #include <plat/pm.h>
 
 #include "common.h"
@@ -287,6 +287,16 @@ static struct platform_device littlemill_device = {
 	.id		= -1,
 };
 
+static struct platform_device bells_wm5102_device = {
+	.name		= "bells",
+	.id		= 0,
+};
+
+static struct platform_device bells_wm5110_device = {
+	.name		= "bells",
+	.id		= 1,
+};
+
 static struct regulator_consumer_supply wallvdd_consumers[] = {
 	REGULATOR_SUPPLY("SPKVDD", "1-001a"),
 	REGULATOR_SUPPLY("SPKVDD1", "1-001a"),
@@ -359,6 +369,8 @@ static struct platform_device *crag6410_devices[] __initdata = {
 	&tobermory_device,
 	&littlemill_device,
 	&lowland_device,
+	&bells_wm5102_device,
+	&bells_wm5110_device,
 	&wallvdd_device,
 };
 
diff --git a/arch/arm/mach-s3c64xx/mach-hmt.c b/arch/arm/mach-s3c64xx/mach-hmt.c
index 6890881..2b14489 100644
--- a/arch/arm/mach-s3c64xx/mach-hmt.c
+++ b/arch/arm/mach-s3c64xx/mach-hmt.c
@@ -26,6 +26,7 @@
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 
+#include <video/samsung_fimd.h>
 #include <mach/hardware.h>
 #include <mach/map.h>
 
@@ -34,14 +35,13 @@
 #include <asm/mach-types.h>
 
 #include <plat/regs-serial.h>
-#include <plat/iic.h>
+#include <linux/platform_data/i2c-s3c2410.h>
 #include <plat/fb.h>
-#include <plat/nand.h>
+#include <linux/platform_data/mtd-nand-s3c2410.h>
 
 #include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
-#include <plat/regs-fb-v4.h>
 
 #include "common.h"
 
diff --git a/arch/arm/mach-s3c64xx/mach-mini6410.c b/arch/arm/mach-s3c64xx/mach-mini6410.c
index 5539a255..07c349c 100644
--- a/arch/arm/mach-s3c64xx/mach-mini6410.c
+++ b/arch/arm/mach-s3c64xx/mach-mini6410.c
@@ -38,12 +38,12 @@
 #include <plat/cpu.h>
 #include <plat/devs.h>
 #include <plat/fb.h>
-#include <plat/nand.h>
+#include <linux/platform_data/mtd-nand-s3c2410.h>
 #include <plat/regs-serial.h>
-#include <plat/ts.h>
-#include <plat/regs-fb-v4.h>
+#include <linux/platform_data/touchscreen-s3c2410.h>
 
 #include <video/platform_lcd.h>
+#include <video/samsung_fimd.h>
 
 #include "common.h"
 
diff --git a/arch/arm/mach-s3c64xx/mach-ncp.c b/arch/arm/mach-s3c64xx/mach-ncp.c
index cad2e05..e5f9a79 100644
--- a/arch/arm/mach-s3c64xx/mach-ncp.c
+++ b/arch/arm/mach-s3c64xx/mach-ncp.c
@@ -24,6 +24,7 @@
 #include <linux/delay.h>
 
 #include <video/platform_lcd.h>
+#include <video/samsung_fimd.h>
 
 #include <asm/hardware/vic.h>
 #include <asm/mach/arch.h>
@@ -37,13 +38,12 @@
 #include <asm/mach-types.h>
 
 #include <plat/regs-serial.h>
-#include <plat/iic.h>
+#include <linux/platform_data/i2c-s3c2410.h>
 #include <plat/fb.h>
 
 #include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
-#include <plat/regs-fb-v4.h>
 
 #include "common.h"
 
diff --git a/arch/arm/mach-s3c64xx/mach-real6410.c b/arch/arm/mach-s3c64xx/mach-real6410.c
index 326b216..7476f7c 100644
--- a/arch/arm/mach-s3c64xx/mach-real6410.c
+++ b/arch/arm/mach-s3c64xx/mach-real6410.c
@@ -39,12 +39,12 @@
 #include <plat/cpu.h>
 #include <plat/devs.h>
 #include <plat/fb.h>
-#include <plat/nand.h>
+#include <linux/platform_data/mtd-nand-s3c2410.h>
 #include <plat/regs-serial.h>
-#include <plat/ts.h>
-#include <plat/regs-fb-v4.h>
+#include <linux/platform_data/touchscreen-s3c2410.h>
 
 #include <video/platform_lcd.h>
+#include <video/samsung_fimd.h>
 
 #include "common.h"
 
diff --git a/arch/arm/mach-s3c64xx/mach-smartq.c b/arch/arm/mach-s3c64xx/mach-smartq.c
index ceeb1de..c6d7390 100644
--- a/arch/arm/mach-s3c64xx/mach-smartq.c
+++ b/arch/arm/mach-s3c64xx/mach-smartq.c
@@ -30,13 +30,13 @@
 #include <plat/clock.h>
 #include <plat/cpu.h>
 #include <plat/devs.h>
-#include <plat/iic.h>
+#include <linux/platform_data/i2c-s3c2410.h>
 #include <plat/gpio-cfg.h>
-#include <plat/hwmon.h>
+#include <linux/platform_data/hwmon-s3c.h>
 #include <plat/regs-serial.h>
-#include <plat/usb-control.h>
+#include <linux/platform_data/usb-ohci-s3c2410.h>
 #include <plat/sdhci.h>
-#include <plat/ts.h>
+#include <linux/platform_data/touchscreen-s3c2410.h>
 
 #include <video/platform_lcd.h>
 
diff --git a/arch/arm/mach-s3c64xx/mach-smartq5.c b/arch/arm/mach-s3c64xx/mach-smartq5.c
index d6266d8..96d6da2 100644
--- a/arch/arm/mach-s3c64xx/mach-smartq5.c
+++ b/arch/arm/mach-s3c64xx/mach-smartq5.c
@@ -21,6 +21,7 @@
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
+#include <video/samsung_fimd.h>
 #include <mach/map.h>
 #include <mach/regs-gpio.h>
 
@@ -28,7 +29,6 @@
 #include <plat/devs.h>
 #include <plat/fb.h>
 #include <plat/gpio-cfg.h>
-#include <plat/regs-fb-v4.h>
 
 #include "common.h"
 #include "mach-smartq.h"
diff --git a/arch/arm/mach-s3c64xx/mach-smartq7.c b/arch/arm/mach-s3c64xx/mach-smartq7.c
index 0957d2a..7d1167b 100644
--- a/arch/arm/mach-s3c64xx/mach-smartq7.c
+++ b/arch/arm/mach-s3c64xx/mach-smartq7.c
@@ -21,6 +21,7 @@
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
+#include <video/samsung_fimd.h>
 #include <mach/map.h>
 #include <mach/regs-gpio.h>
 
@@ -28,7 +29,6 @@
 #include <plat/devs.h>
 #include <plat/fb.h>
 #include <plat/gpio-cfg.h>
-#include <plat/regs-fb-v4.h>
 
 #include "common.h"
 #include "mach-smartq.h"
diff --git a/arch/arm/mach-s3c64xx/mach-smdk6400.c b/arch/arm/mach-s3c64xx/mach-smdk6400.c
index b0f4525..a928fae 100644
--- a/arch/arm/mach-s3c64xx/mach-smdk6400.c
+++ b/arch/arm/mach-s3c64xx/mach-smdk6400.c
@@ -35,7 +35,7 @@
 #include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
-#include <plat/iic.h>
+#include <linux/platform_data/i2c-s3c2410.h>
 
 #include "common.h"
 
diff --git a/arch/arm/mach-s3c64xx/mach-smdk6410.c b/arch/arm/mach-s3c64xx/mach-smdk6410.c
index 0fe4f15..da1a771 100644
--- a/arch/arm/mach-s3c64xx/mach-smdk6410.c
+++ b/arch/arm/mach-s3c64xx/mach-smdk6410.c
@@ -43,6 +43,7 @@
 #endif
 
 #include <video/platform_lcd.h>
+#include <video/samsung_fimd.h>
 
 #include <asm/hardware/vic.h>
 #include <asm/mach/arch.h>
@@ -60,8 +61,8 @@
 #include <mach/regs-gpio.h>
 #include <mach/regs-sys.h>
 #include <mach/regs-srom.h>
-#include <plat/ata.h>
-#include <plat/iic.h>
+#include <linux/platform_data/ata-samsung_cf.h>
+#include <linux/platform_data/i2c-s3c2410.h>
 #include <plat/fb.h>
 #include <plat/gpio-cfg.h>
 
@@ -69,10 +70,9 @@
 #include <plat/devs.h>
 #include <plat/cpu.h>
 #include <plat/adc.h>
-#include <plat/ts.h>
+#include <linux/platform_data/touchscreen-s3c2410.h>
 #include <plat/keypad.h>
 #include <plat/backlight.h>
-#include <plat/regs-fb-v4.h>
 
 #include "common.h"
 
diff --git a/arch/arm/mach-s3c64xx/setup-i2c0.c b/arch/arm/mach-s3c64xx/setup-i2c0.c
index 241af94..40666ba 100644
--- a/arch/arm/mach-s3c64xx/setup-i2c0.c
+++ b/arch/arm/mach-s3c64xx/setup-i2c0.c
@@ -18,7 +18,7 @@
 
 struct platform_device; /* don't need the contents */
 
-#include <plat/iic.h>
+#include <linux/platform_data/i2c-s3c2410.h>
 #include <plat/gpio-cfg.h>
 
 void s3c_i2c0_cfg_gpio(struct platform_device *dev)
diff --git a/arch/arm/mach-s3c64xx/setup-i2c1.c b/arch/arm/mach-s3c64xx/setup-i2c1.c
index 3d13a96..3fdb24c 100644
--- a/arch/arm/mach-s3c64xx/setup-i2c1.c
+++ b/arch/arm/mach-s3c64xx/setup-i2c1.c
@@ -18,7 +18,7 @@
 
 struct platform_device; /* don't need the contents */
 
-#include <plat/iic.h>
+#include <linux/platform_data/i2c-s3c2410.h>
 #include <plat/gpio-cfg.h>
 
 void s3c_i2c1_cfg_gpio(struct platform_device *dev)
diff --git a/arch/arm/mach-s3c64xx/setup-ide.c b/arch/arm/mach-s3c64xx/setup-ide.c
index 41b4256..648d8b8 100644
--- a/arch/arm/mach-s3c64xx/setup-ide.c
+++ b/arch/arm/mach-s3c64xx/setup-ide.c
@@ -17,7 +17,7 @@
 #include <mach/map.h>
 #include <mach/regs-clock.h>
 #include <plat/gpio-cfg.h>
-#include <plat/ata.h>
+#include <linux/platform_data/ata-samsung_cf.h>
 
 void s3c64xx_ide_setup_gpio(void)
 {
diff --git a/arch/arm/mach-s5p64x0/dev-audio.c b/arch/arm/mach-s5p64x0/dev-audio.c
index 91113dd..a0d6edf 100644
--- a/arch/arm/mach-s5p64x0/dev-audio.c
+++ b/arch/arm/mach-s5p64x0/dev-audio.c
@@ -13,7 +13,7 @@
 #include <linux/gpio.h>
 
 #include <plat/gpio-cfg.h>
-#include <plat/audio.h>
+#include <linux/platform_data/asoc-s3c.h>
 
 #include <mach/map.h>
 #include <mach/dma.h>
diff --git a/arch/arm/mach-s5p64x0/mach-smdk6440.c b/arch/arm/mach-s5p64x0/mach-smdk6440.c
index 92fefad..96ea1fe 100644
--- a/arch/arm/mach-s5p64x0/mach-smdk6440.c
+++ b/arch/arm/mach-s5p64x0/mach-smdk6440.c
@@ -27,6 +27,7 @@
 #include <linux/mmc/host.h>
 
 #include <video/platform_lcd.h>
+#include <video/samsung_fimd.h>
 
 #include <asm/hardware/vic.h>
 #include <asm/mach/arch.h>
@@ -45,14 +46,13 @@
 #include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
-#include <plat/iic.h>
+#include <linux/platform_data/i2c-s3c2410.h>
 #include <plat/pll.h>
 #include <plat/adc.h>
-#include <plat/ts.h>
+#include <linux/platform_data/touchscreen-s3c2410.h>
 #include <plat/s5p-time.h>
 #include <plat/backlight.h>
 #include <plat/fb.h>
-#include <plat/regs-fb.h>
 #include <plat/sdhci.h>
 
 #include "common.h"
diff --git a/arch/arm/mach-s5p64x0/mach-smdk6450.c b/arch/arm/mach-s5p64x0/mach-smdk6450.c
index e2335ec..12748b6 100644
--- a/arch/arm/mach-s5p64x0/mach-smdk6450.c
+++ b/arch/arm/mach-s5p64x0/mach-smdk6450.c
@@ -27,6 +27,7 @@
 #include <linux/mmc/host.h>
 
 #include <video/platform_lcd.h>
+#include <video/samsung_fimd.h>
 
 #include <asm/hardware/vic.h>
 #include <asm/mach/arch.h>
@@ -45,14 +46,13 @@
 #include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
-#include <plat/iic.h>
+#include <linux/platform_data/i2c-s3c2410.h>
 #include <plat/pll.h>
 #include <plat/adc.h>
-#include <plat/ts.h>
+#include <linux/platform_data/touchscreen-s3c2410.h>
 #include <plat/s5p-time.h>
 #include <plat/backlight.h>
 #include <plat/fb.h>
-#include <plat/regs-fb.h>
 #include <plat/sdhci.h>
 
 #include "common.h"
diff --git a/arch/arm/mach-s5p64x0/setup-i2c0.c b/arch/arm/mach-s5p64x0/setup-i2c0.c
index 46b4639..a32edc5 100644
--- a/arch/arm/mach-s5p64x0/setup-i2c0.c
+++ b/arch/arm/mach-s5p64x0/setup-i2c0.c
@@ -19,7 +19,7 @@
 struct platform_device; /* don't need the contents */
 
 #include <plat/gpio-cfg.h>
-#include <plat/iic.h>
+#include <linux/platform_data/i2c-s3c2410.h>
 
 #include <mach/i2c.h>
 
diff --git a/arch/arm/mach-s5p64x0/setup-i2c1.c b/arch/arm/mach-s5p64x0/setup-i2c1.c
index 6ad3b98..ca2c5c7 100644
--- a/arch/arm/mach-s5p64x0/setup-i2c1.c
+++ b/arch/arm/mach-s5p64x0/setup-i2c1.c
@@ -19,7 +19,7 @@
 struct platform_device; /* don't need the contents */
 
 #include <plat/gpio-cfg.h>
-#include <plat/iic.h>
+#include <linux/platform_data/i2c-s3c2410.h>
 
 #include <mach/i2c.h>
 
diff --git a/arch/arm/mach-s5pc100/dev-audio.c b/arch/arm/mach-s5pc100/dev-audio.c
index 9d4bde3..1cc252c 100644
--- a/arch/arm/mach-s5pc100/dev-audio.c
+++ b/arch/arm/mach-s5pc100/dev-audio.c
@@ -13,7 +13,7 @@
 #include <linux/gpio.h>
 
 #include <plat/gpio-cfg.h>
-#include <plat/audio.h>
+#include <linux/platform_data/asoc-s3c.h>
 
 #include <mach/map.h>
 #include <mach/dma.h>
diff --git a/arch/arm/mach-s5pc100/mach-smdkc100.c b/arch/arm/mach-s5pc100/mach-smdkc100.c
index 0c3ae38..dba7384 100644
--- a/arch/arm/mach-s5pc100/mach-smdkc100.c
+++ b/arch/arm/mach-s5pc100/mach-smdkc100.c
@@ -33,6 +33,7 @@
 #include <mach/regs-gpio.h>
 
 #include <video/platform_lcd.h>
+#include <video/samsung_fimd.h>
 
 #include <asm/irq.h>
 #include <asm/mach-types.h>
@@ -44,14 +45,13 @@
 #include <plat/devs.h>
 #include <plat/cpu.h>
 #include <plat/fb.h>
-#include <plat/iic.h>
-#include <plat/ata.h>
+#include <linux/platform_data/i2c-s3c2410.h>
+#include <linux/platform_data/ata-samsung_cf.h>
 #include <plat/adc.h>
 #include <plat/keypad.h>
-#include <plat/ts.h>
-#include <plat/audio.h>
+#include <linux/platform_data/touchscreen-s3c2410.h>
+#include <linux/platform_data/asoc-s3c.h>
 #include <plat/backlight.h>
-#include <plat/regs-fb-v4.h>
 
 #include "common.h"
 
diff --git a/arch/arm/mach-s5pc100/setup-i2c0.c b/arch/arm/mach-s5pc100/setup-i2c0.c
index eaef7a3..89a6a76 100644
--- a/arch/arm/mach-s5pc100/setup-i2c0.c
+++ b/arch/arm/mach-s5pc100/setup-i2c0.c
@@ -18,7 +18,7 @@
 struct platform_device; /* don't need the contents */
 
 #include <linux/gpio.h>
-#include <plat/iic.h>
+#include <linux/platform_data/i2c-s3c2410.h>
 #include <plat/gpio-cfg.h>
 
 void s3c_i2c0_cfg_gpio(struct platform_device *dev)
diff --git a/arch/arm/mach-s5pc100/setup-i2c1.c b/arch/arm/mach-s5pc100/setup-i2c1.c
index aaff74a..faa667e 100644
--- a/arch/arm/mach-s5pc100/setup-i2c1.c
+++ b/arch/arm/mach-s5pc100/setup-i2c1.c
@@ -18,7 +18,7 @@
 struct platform_device; /* don't need the contents */
 
 #include <linux/gpio.h>
-#include <plat/iic.h>
+#include <linux/platform_data/i2c-s3c2410.h>
 #include <plat/gpio-cfg.h>
 
 void s3c_i2c1_cfg_gpio(struct platform_device *dev)
diff --git a/arch/arm/mach-s5pv210/dev-audio.c b/arch/arm/mach-s5pv210/dev-audio.c
index 8367749..0a5480b 100644
--- a/arch/arm/mach-s5pv210/dev-audio.c
+++ b/arch/arm/mach-s5pv210/dev-audio.c
@@ -13,7 +13,7 @@
 #include <linux/gpio.h>
 
 #include <plat/gpio-cfg.h>
-#include <plat/audio.h>
+#include <linux/platform_data/asoc-s3c.h>
 
 #include <mach/map.h>
 #include <mach/dma.h>
diff --git a/arch/arm/mach-s5pv210/mach-aquila.c b/arch/arm/mach-s5pv210/mach-aquila.c
index 78028df..ee9fa5c 100644
--- a/arch/arm/mach-s5pv210/mach-aquila.c
+++ b/arch/arm/mach-s5pv210/mach-aquila.c
@@ -28,6 +28,7 @@
 #include <asm/setup.h>
 #include <asm/mach-types.h>
 
+#include <video/samsung_fimd.h>
 #include <mach/map.h>
 #include <mach/regs-clock.h>
 
@@ -39,7 +40,6 @@
 #include <plat/fimc-core.h>
 #include <plat/sdhci.h>
 #include <plat/s5p-time.h>
-#include <plat/regs-fb-v4.h>
 
 #include "common.h"
 
diff --git a/arch/arm/mach-s5pv210/mach-goni.c b/arch/arm/mach-s5pv210/mach-goni.c
index 822a559..55e1dba 100644
--- a/arch/arm/mach-s5pv210/mach-goni.c
+++ b/arch/arm/mach-s5pv210/mach-goni.c
@@ -35,6 +35,7 @@
 #include <asm/setup.h>
 #include <asm/mach-types.h>
 
+#include <video/samsung_fimd.h>
 #include <mach/map.h>
 #include <mach/regs-clock.h>
 
@@ -43,13 +44,12 @@
 #include <plat/devs.h>
 #include <plat/cpu.h>
 #include <plat/fb.h>
-#include <plat/iic.h>
+#include <linux/platform_data/i2c-s3c2410.h>
 #include <plat/keypad.h>
 #include <plat/sdhci.h>
 #include <plat/clock.h>
 #include <plat/s5p-time.h>
 #include <plat/mfc.h>
-#include <plat/regs-fb-v4.h>
 #include <plat/camport.h>
 
 #include <media/v4l2-mediabus.h>
diff --git a/arch/arm/mach-s5pv210/mach-smdkc110.c b/arch/arm/mach-s5pv210/mach-smdkc110.c
index dfc2923..d9c99fc 100644
--- a/arch/arm/mach-s5pv210/mach-smdkc110.c
+++ b/arch/arm/mach-s5pv210/mach-smdkc110.c
@@ -27,8 +27,8 @@
 #include <plat/regs-serial.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
-#include <plat/ata.h>
-#include <plat/iic.h>
+#include <linux/platform_data/ata-samsung_cf.h>
+#include <linux/platform_data/i2c-s3c2410.h>
 #include <plat/pm.h>
 #include <plat/s5p-time.h>
 #include <plat/mfc.h>
diff --git a/arch/arm/mach-s5pv210/mach-smdkv210.c b/arch/arm/mach-s5pv210/mach-smdkv210.c
index 918b23d..4cdb5bb 100644
--- a/arch/arm/mach-s5pv210/mach-smdkv210.c
+++ b/arch/arm/mach-s5pv210/mach-smdkv210.c
@@ -28,6 +28,7 @@
 #include <asm/mach-types.h>
 
 #include <video/platform_lcd.h>
+#include <video/samsung_fimd.h>
 
 #include <mach/map.h>
 #include <mach/regs-clock.h>
@@ -38,15 +39,14 @@
 #include <plat/devs.h>
 #include <plat/cpu.h>
 #include <plat/adc.h>
-#include <plat/ts.h>
-#include <plat/ata.h>
-#include <plat/iic.h>
+#include <linux/platform_data/touchscreen-s3c2410.h>
+#include <linux/platform_data/ata-samsung_cf.h>
+#include <linux/platform_data/i2c-s3c2410.h>
 #include <plat/keypad.h>
 #include <plat/pm.h>
 #include <plat/fb.h>
 #include <plat/s5p-time.h>
 #include <plat/backlight.h>
-#include <plat/regs-fb-v4.h>
 #include <plat/mfc.h>
 #include <plat/clock.h>
 
diff --git a/arch/arm/mach-s5pv210/mach-torbreck.c b/arch/arm/mach-s5pv210/mach-torbreck.c
index 74e99bc..18785cb 100644
--- a/arch/arm/mach-s5pv210/mach-torbreck.c
+++ b/arch/arm/mach-s5pv210/mach-torbreck.c
@@ -26,7 +26,7 @@
 #include <plat/regs-serial.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
-#include <plat/iic.h>
+#include <linux/platform_data/i2c-s3c2410.h>
 #include <plat/s5p-time.h>
 
 #include "common.h"
diff --git a/arch/arm/mach-s5pv210/setup-i2c0.c b/arch/arm/mach-s5pv210/setup-i2c0.c
index 0f1cc3a..4a15849 100644
--- a/arch/arm/mach-s5pv210/setup-i2c0.c
+++ b/arch/arm/mach-s5pv210/setup-i2c0.c
@@ -18,7 +18,7 @@
 
 struct platform_device; /* don't need the contents */
 
-#include <plat/iic.h>
+#include <linux/platform_data/i2c-s3c2410.h>
 #include <plat/gpio-cfg.h>
 
 void s3c_i2c0_cfg_gpio(struct platform_device *dev)
diff --git a/arch/arm/mach-s5pv210/setup-i2c1.c b/arch/arm/mach-s5pv210/setup-i2c1.c
index f61365a..4777f6b 100644
--- a/arch/arm/mach-s5pv210/setup-i2c1.c
+++ b/arch/arm/mach-s5pv210/setup-i2c1.c
@@ -18,7 +18,7 @@
 
 struct platform_device; /* don't need the contents */
 
-#include <plat/iic.h>
+#include <linux/platform_data/i2c-s3c2410.h>
 #include <plat/gpio-cfg.h>
 
 void s3c_i2c1_cfg_gpio(struct platform_device *dev)
diff --git a/arch/arm/mach-s5pv210/setup-i2c2.c b/arch/arm/mach-s5pv210/setup-i2c2.c
index 2f91b5c..bbce6c7 100644
--- a/arch/arm/mach-s5pv210/setup-i2c2.c
+++ b/arch/arm/mach-s5pv210/setup-i2c2.c
@@ -18,7 +18,7 @@
 
 struct platform_device; /* don't need the contents */
 
-#include <plat/iic.h>
+#include <linux/platform_data/i2c-s3c2410.h>
 #include <plat/gpio-cfg.h>
 
 void s3c_i2c2_cfg_gpio(struct platform_device *dev)
diff --git a/arch/arm/mach-sa1100/Makefile b/arch/arm/mach-sa1100/Makefile
index 60b97ec..1aed9e7 100644
--- a/arch/arm/mach-sa1100/Makefile
+++ b/arch/arm/mach-sa1100/Makefile
@@ -7,21 +7,17 @@ obj-y := clock.o generic.o irq.o time.o #nmi-oopser.o
 obj-m :=
 obj-n :=
 obj-  :=
-led-y := leds.o
 
 obj-$(CONFIG_CPU_FREQ_SA1100)		+= cpu-sa1100.o
 obj-$(CONFIG_CPU_FREQ_SA1110)		+= cpu-sa1110.o
 
 # Specific board support
 obj-$(CONFIG_SA1100_ASSABET)		+= assabet.o
-led-$(CONFIG_SA1100_ASSABET)		+= leds-assabet.o
 obj-$(CONFIG_ASSABET_NEPONSET)		+= neponset.o
 
 obj-$(CONFIG_SA1100_BADGE4)		+= badge4.o
-led-$(CONFIG_SA1100_BADGE4)		+= leds-badge4.o
 
 obj-$(CONFIG_SA1100_CERF)		+= cerf.o
-led-$(CONFIG_SA1100_CERF)		+= leds-cerf.o
 
 obj-$(CONFIG_SA1100_COLLIE)		+= collie.o
 
@@ -29,13 +25,11 @@ obj-$(CONFIG_SA1100_H3100)		+= h3100.o h3xxx.o
 obj-$(CONFIG_SA1100_H3600)		+= h3600.o h3xxx.o
 
 obj-$(CONFIG_SA1100_HACKKIT)		+= hackkit.o
-led-$(CONFIG_SA1100_HACKKIT)		+= leds-hackkit.o
 
 obj-$(CONFIG_SA1100_JORNADA720)		+= jornada720.o
 obj-$(CONFIG_SA1100_JORNADA720_SSP)	+= jornada720_ssp.o
 
 obj-$(CONFIG_SA1100_LART)		+= lart.o
-led-$(CONFIG_SA1100_LART)		+= leds-lart.o
 
 obj-$(CONFIG_SA1100_NANOENGINE)		+= nanoengine.o
 obj-$(CONFIG_PCI_NANOENGINE)		+= pci-nanoengine.o
@@ -46,9 +40,6 @@ obj-$(CONFIG_SA1100_SHANNON)		+= shannon.o
 
 obj-$(CONFIG_SA1100_SIMPAD)		+= simpad.o
 
-# LEDs support
-obj-$(CONFIG_LEDS) += $(led-y)
-
 # Miscellaneous functions
 obj-$(CONFIG_PM)			+= pm.o sleep.o
 obj-$(CONFIG_SA1100_SSP)		+= ssp.o
diff --git a/arch/arm/mach-sa1100/assabet.c b/arch/arm/mach-sa1100/assabet.c
index d673211..e1ccda6 100644
--- a/arch/arm/mach-sa1100/assabet.c
+++ b/arch/arm/mach-sa1100/assabet.c
@@ -20,6 +20,8 @@
 #include <linux/mtd/partitions.h>
 #include <linux/delay.h>
 #include <linux/mm.h>
+#include <linux/leds.h>
+#include <linux/slab.h>
 
 #include <video/sa1100fb.h>
 
@@ -37,7 +39,7 @@
 #include <asm/mach/map.h>
 #include <asm/mach/serial_sa1100.h>
 #include <mach/assabet.h>
-#include <mach/mcp.h>
+#include <linux/platform_data/mfd-mcp-sa11x0.h>
 #include <mach/irqs.h>
 
 #include "generic.h"
@@ -529,6 +531,89 @@ static void __init assabet_map_io(void)
 	sa1100_register_uart(2, 3);
 }
 
+/* LEDs */
+#if defined(CONFIG_NEW_LEDS) && defined(CONFIG_LEDS_CLASS)
+struct assabet_led {
+	struct led_classdev cdev;
+	u32 mask;
+};
+
+/*
+ * The triggers lines up below will only be used if the
+ * LED triggers are compiled in.
+ */
+static const struct {
+	const char *name;
+	const char *trigger;
+} assabet_leds[] = {
+	{ "assabet:red", "cpu0",},
+	{ "assabet:green", "heartbeat", },
+};
+
+/*
+ * The LED control in Assabet is reversed:
+ *  - setting bit means turn off LED
+ *  - clearing bit means turn on LED
+ */
+static void assabet_led_set(struct led_classdev *cdev,
+		enum led_brightness b)
+{
+	struct assabet_led *led = container_of(cdev,
+			struct assabet_led, cdev);
+
+	if (b != LED_OFF)
+		ASSABET_BCR_clear(led->mask);
+	else
+		ASSABET_BCR_set(led->mask);
+}
+
+static enum led_brightness assabet_led_get(struct led_classdev *cdev)
+{
+	struct assabet_led *led = container_of(cdev,
+			struct assabet_led, cdev);
+
+	return (ASSABET_BCR & led->mask) ? LED_OFF : LED_FULL;
+}
+
+static int __init assabet_leds_init(void)
+{
+	int i;
+
+	if (!machine_is_assabet())
+		return -ENODEV;
+
+	for (i = 0; i < ARRAY_SIZE(assabet_leds); i++) {
+		struct assabet_led *led;
+
+		led = kzalloc(sizeof(*led), GFP_KERNEL);
+		if (!led)
+			break;
+
+		led->cdev.name = assabet_leds[i].name;
+		led->cdev.brightness_set = assabet_led_set;
+		led->cdev.brightness_get = assabet_led_get;
+		led->cdev.default_trigger = assabet_leds[i].trigger;
+
+		if (!i)
+			led->mask = ASSABET_BCR_LED_RED;
+		else
+			led->mask = ASSABET_BCR_LED_GREEN;
+
+		if (led_classdev_register(NULL, &led->cdev) < 0) {
+			kfree(led);
+			break;
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * Since we may have triggers on any subsystem, defer registration
+ * until after subsystem_init.
+ */
+fs_initcall(assabet_leds_init);
+#endif
 
 MACHINE_START(ASSABET, "Intel-Assabet")
 	.atag_offset	= 0x100,
diff --git a/arch/arm/mach-sa1100/badge4.c b/arch/arm/mach-sa1100/badge4.c
index b30fb99..038df48 100644
--- a/arch/arm/mach-sa1100/badge4.c
+++ b/arch/arm/mach-sa1100/badge4.c
@@ -22,6 +22,8 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <linux/errno.h>
+#include <linux/gpio.h>
+#include <linux/leds.h>
 
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
@@ -76,8 +78,36 @@ static struct platform_device sa1111_device = {
 	.resource	= sa1111_resources,
 };
 
+/* LEDs */
+struct gpio_led badge4_gpio_leds[] = {
+	{
+		.name			= "badge4:red",
+		.default_trigger	= "heartbeat",
+		.gpio			= 7,
+	},
+	{
+		.name			= "badge4:green",
+		.default_trigger	= "cpu0",
+		.gpio			= 9,
+	},
+};
+
+static struct gpio_led_platform_data badge4_gpio_led_info = {
+	.leds		= badge4_gpio_leds,
+	.num_leds	= ARRAY_SIZE(badge4_gpio_leds),
+};
+
+static struct platform_device badge4_leds = {
+	.name	= "leds-gpio",
+	.id	= -1,
+	.dev	= {
+		.platform_data	= &badge4_gpio_led_info,
+	}
+};
+
 static struct platform_device *devices[] __initdata = {
 	&sa1111_device,
+	&badge4_leds,
 };
 
 static int __init badge4_sa1111_init(void)
diff --git a/arch/arm/mach-sa1100/cerf.c b/arch/arm/mach-sa1100/cerf.c
index 09d7f4b..ad0eb08 100644
--- a/arch/arm/mach-sa1100/cerf.c
+++ b/arch/arm/mach-sa1100/cerf.c
@@ -17,6 +17,8 @@
 #include <linux/irq.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
+#include <linux/gpio.h>
+#include <linux/leds.h>
 
 #include <mach/hardware.h>
 #include <asm/setup.h>
@@ -28,7 +30,7 @@
 #include <asm/mach/serial_sa1100.h>
 
 #include <mach/cerf.h>
-#include <mach/mcp.h>
+#include <linux/platform_data/mfd-mcp-sa11x0.h>
 #include <mach/irqs.h>
 #include "generic.h"
 
@@ -43,8 +45,48 @@ static struct platform_device cerfuart2_device = {
 	.resource	= cerfuart2_resources,
 };
 
+/* LEDs */
+struct gpio_led cerf_gpio_leds[] = {
+	{
+		.name			= "cerf:d0",
+		.default_trigger	= "heartbeat",
+		.gpio			= 0,
+	},
+	{
+		.name			= "cerf:d1",
+		.default_trigger	= "cpu0",
+		.gpio			= 1,
+	},
+	{
+		.name			= "cerf:d2",
+		.default_trigger	= "default-on",
+		.gpio			= 2,
+	},
+	{
+		.name			= "cerf:d3",
+		.default_trigger	= "default-on",
+		.gpio			= 3,
+	},
+
+};
+
+static struct gpio_led_platform_data cerf_gpio_led_info = {
+	.leds		= cerf_gpio_leds,
+	.num_leds	= ARRAY_SIZE(cerf_gpio_leds),
+};
+
+static struct platform_device cerf_leds = {
+	.name	= "leds-gpio",
+	.id	= -1,
+	.dev	= {
+		.platform_data	= &cerf_gpio_led_info,
+	}
+};
+
+
 static struct platform_device *cerf_devices[] __initdata = {
 	&cerfuart2_device,
+	&cerf_leds,
 };
 
 #ifdef CONFIG_SA1100_CERF_FLASH_32MB
diff --git a/arch/arm/mach-sa1100/collie.c b/arch/arm/mach-sa1100/collie.c
index ea5cff3..170cb61 100644
--- a/arch/arm/mach-sa1100/collie.c
+++ b/arch/arm/mach-sa1100/collie.c
@@ -45,7 +45,7 @@
 #include <asm/hardware/scoop.h>
 #include <asm/mach/sharpsl_param.h>
 #include <asm/hardware/locomo.h>
-#include <mach/mcp.h>
+#include <linux/platform_data/mfd-mcp-sa11x0.h>
 #include <mach/irqs.h>
 
 #include "generic.h"
diff --git a/arch/arm/mach-sa1100/hackkit.c b/arch/arm/mach-sa1100/hackkit.c
index 7f86bd9..fc106aa 100644
--- a/arch/arm/mach-sa1100/hackkit.c
+++ b/arch/arm/mach-sa1100/hackkit.c
@@ -21,6 +21,10 @@
 #include <linux/serial_core.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
+#include <linux/tty.h>
+#include <linux/gpio.h>
+#include <linux/leds.h>
+#include <linux/platform_device.h>
 
 #include <asm/mach-types.h>
 #include <asm/setup.h>
@@ -183,9 +187,37 @@ static struct flash_platform_data hackkit_flash_data = {
 static struct resource hackkit_flash_resource =
 	DEFINE_RES_MEM(SA1100_CS0_PHYS, SZ_32M);
 
+/* LEDs */
+struct gpio_led hackkit_gpio_leds[] = {
+	{
+		.name			= "hackkit:red",
+		.default_trigger	= "cpu0",
+		.gpio			= 22,
+	},
+	{
+		.name			= "hackkit:green",
+		.default_trigger	= "heartbeat",
+		.gpio			= 23,
+	},
+};
+
+static struct gpio_led_platform_data hackkit_gpio_led_info = {
+	.leds		= hackkit_gpio_leds,
+	.num_leds	= ARRAY_SIZE(hackkit_gpio_leds),
+};
+
+static struct platform_device hackkit_leds = {
+	.name	= "leds-gpio",
+	.id	= -1,
+	.dev	= {
+		.platform_data	= &hackkit_gpio_led_info,
+	}
+};
+
 static void __init hackkit_init(void)
 {
 	sa11x0_register_mtd(&hackkit_flash_data, &hackkit_flash_resource, 1);
+	platform_device_register(&hackkit_leds);
 }
 
 /**********************************************************************
diff --git a/arch/arm/mach-sa1100/include/mach/SA-1111.h b/arch/arm/mach-sa1100/include/mach/SA-1111.h
deleted file mode 100644
index c38f609..0000000
--- a/arch/arm/mach-sa1100/include/mach/SA-1111.h
+++ /dev/null
@@ -1,5 +0,0 @@
-/*
- * Moved to new location
- */
-#warning using old SA-1111.h - update to <asm/hardware/sa1111.h>
-#include <asm/hardware/sa1111.h>
diff --git a/arch/arm/mach-sa1100/include/mach/lart.h b/arch/arm/mach-sa1100/include/mach/lart.h
deleted file mode 100644
index 8a5482d..0000000
--- a/arch/arm/mach-sa1100/include/mach/lart.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef _INCLUDE_LART_H
-#define _INCLUDE_LART_H
-
-#define LART_GPIO_ETH0			GPIO_GPIO0
-#define LART_IRQ_ETH0			IRQ_GPIO0
-
-#define LART_GPIO_IDE			GPIO_GPIO1
-#define LART_IRQ_IDE			IRQ_GPIO1
-
-#define LART_GPIO_UCB1200		GPIO_GPIO18
-#define LART_IRQ_UCB1200		IRQ_GPIO18
-
-#endif
diff --git a/arch/arm/mach-sa1100/include/mach/mcp.h b/arch/arm/mach-sa1100/include/mach/mcp.h
deleted file mode 100644
index 4b2860ae..0000000
--- a/arch/arm/mach-sa1100/include/mach/mcp.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- *  arch/arm/mach-sa1100/include/mach/mcp.h
- *
- *  Copyright (C) 2005 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.
- */
-#ifndef __ASM_ARM_ARCH_MCP_H
-#define __ASM_ARM_ARCH_MCP_H
-
-#include <linux/types.h>
-
-struct mcp_plat_data {
-	u32 mccr0;
-	u32 mccr1;
-	unsigned int sclk_rate;
-	void *codec_pdata;
-};
-
-#endif
diff --git a/arch/arm/mach-sa1100/include/mach/simpad.h b/arch/arm/mach-sa1100/include/mach/simpad.h
index cdea671..ac2ea76 100644
--- a/arch/arm/mach-sa1100/include/mach/simpad.h
+++ b/arch/arm/mach-sa1100/include/mach/simpad.h
@@ -87,7 +87,7 @@
 #define SIMPAD_CS3_PCMCIA_SHORT		(SIMPAD_CS3_GPIO_BASE + 22)
 #define SIMPAD_CS3_GPIO_23		(SIMPAD_CS3_GPIO_BASE + 23)
 
-#define CS3_BASE        0xf1000000
+#define CS3_BASE        IOMEM(0xf1000000)
 
 long simpad_get_cs3_ro(void);
 long simpad_get_cs3_shadow(void);
diff --git a/arch/arm/mach-sa1100/lart.c b/arch/arm/mach-sa1100/lart.c
index b775a0a..3048b17 100644
--- a/arch/arm/mach-sa1100/lart.c
+++ b/arch/arm/mach-sa1100/lart.c
@@ -5,6 +5,9 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/tty.h>
+#include <linux/gpio.h>
+#include <linux/leds.h>
+#include <linux/platform_device.h>
 
 #include <video/sa1100fb.h>
 
@@ -16,7 +19,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/serial_sa1100.h>
-#include <mach/mcp.h>
+#include <linux/platform_data/mfd-mcp-sa11x0.h>
 #include <mach/irqs.h>
 
 #include "generic.h"
@@ -126,6 +129,27 @@ static struct map_desc lart_io_desc[] __initdata = {
 	}
 };
 
+/* LEDs */
+struct gpio_led lart_gpio_leds[] = {
+	{
+		.name			= "lart:red",
+		.default_trigger	= "cpu0",
+		.gpio			= 23,
+	},
+};
+
+static struct gpio_led_platform_data lart_gpio_led_info = {
+	.leds		= lart_gpio_leds,
+	.num_leds	= ARRAY_SIZE(lart_gpio_leds),
+};
+
+static struct platform_device lart_leds = {
+	.name	= "leds-gpio",
+	.id	= -1,
+	.dev	= {
+		.platform_data	= &lart_gpio_led_info,
+	}
+};
 static void __init lart_map_io(void)
 {
 	sa1100_map_io();
@@ -139,6 +163,8 @@ static void __init lart_map_io(void)
 	GPDR |= GPIO_UART_TXD;
 	GPDR &= ~GPIO_UART_RXD;
 	PPAR |= PPAR_UPR;
+
+	platform_device_register(&lart_leds);
 }
 
 MACHINE_START(LART, "LART")
diff --git a/arch/arm/mach-sa1100/leds-assabet.c b/arch/arm/mach-sa1100/leds-assabet.c
deleted file mode 100644
index 3699176..0000000
--- a/arch/arm/mach-sa1100/leds-assabet.c
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * linux/arch/arm/mach-sa1100/leds-assabet.c
- *
- * Copyright (C) 2000 John Dorsey <john+@cs.cmu.edu>
- *
- * Original (leds-footbridge.c) by Russell King
- *
- * Assabet uses the LEDs as follows:
- *   - Green - toggles state every 50 timer interrupts
- *   - Red   - on if system is not idle
- */
-#include <linux/init.h>
-
-#include <mach/hardware.h>
-#include <asm/leds.h>
-#include <mach/assabet.h>
-
-#include "leds.h"
-
-
-#define LED_STATE_ENABLED	1
-#define LED_STATE_CLAIMED	2
-
-static unsigned int led_state;
-static unsigned int hw_led_state;
-
-#define ASSABET_BCR_LED_MASK	(ASSABET_BCR_LED_GREEN | ASSABET_BCR_LED_RED)
-
-void assabet_leds_event(led_event_t evt)
-{
-	unsigned long flags;
-
-	local_irq_save(flags);
-
-	switch (evt) {
-	case led_start:
-		hw_led_state = ASSABET_BCR_LED_RED | ASSABET_BCR_LED_GREEN;
-		led_state = LED_STATE_ENABLED;
-		break;
-
-	case led_stop:
-		led_state &= ~LED_STATE_ENABLED;
-		hw_led_state = ASSABET_BCR_LED_RED | ASSABET_BCR_LED_GREEN;
-		ASSABET_BCR_frob(ASSABET_BCR_LED_MASK, hw_led_state);
-		break;
-
-	case led_claim:
-		led_state |= LED_STATE_CLAIMED;
-		hw_led_state = ASSABET_BCR_LED_RED | ASSABET_BCR_LED_GREEN;
-		break;
-
-	case led_release:
-		led_state &= ~LED_STATE_CLAIMED;
-		hw_led_state = ASSABET_BCR_LED_RED | ASSABET_BCR_LED_GREEN;
-		break;
-
-#ifdef CONFIG_LEDS_TIMER
-	case led_timer:
-		if (!(led_state & LED_STATE_CLAIMED))
-			hw_led_state ^= ASSABET_BCR_LED_GREEN;
-		break;
-#endif
-
-#ifdef CONFIG_LEDS_CPU
-	case led_idle_start:
-		if (!(led_state & LED_STATE_CLAIMED))
-			hw_led_state |= ASSABET_BCR_LED_RED;
-		break;
-
-	case led_idle_end:
-		if (!(led_state & LED_STATE_CLAIMED))
-			hw_led_state &= ~ASSABET_BCR_LED_RED;
-		break;
-#endif
-
-	case led_halted:
-		break;
-
-	case led_green_on:
-		if (led_state & LED_STATE_CLAIMED)
-			hw_led_state &= ~ASSABET_BCR_LED_GREEN;
-		break;
-
-	case led_green_off:
-		if (led_state & LED_STATE_CLAIMED)
-			hw_led_state |= ASSABET_BCR_LED_GREEN;
-		break;
-
-	case led_amber_on:
-		break;
-
-	case led_amber_off:
-		break;
-
-	case led_red_on:
-		if (led_state & LED_STATE_CLAIMED)
-			hw_led_state &= ~ASSABET_BCR_LED_RED;
-		break;
-
-	case led_red_off:
-		if (led_state & LED_STATE_CLAIMED)
-			hw_led_state |= ASSABET_BCR_LED_RED;
-		break;
-
-	default:
-		break;
-	}
-
-	if  (led_state & LED_STATE_ENABLED)
-		ASSABET_BCR_frob(ASSABET_BCR_LED_MASK, hw_led_state);
-
-	local_irq_restore(flags);
-}
diff --git a/arch/arm/mach-sa1100/leds-badge4.c b/arch/arm/mach-sa1100/leds-badge4.c
deleted file mode 100644
index f99fac3..0000000
--- a/arch/arm/mach-sa1100/leds-badge4.c
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * linux/arch/arm/mach-sa1100/leds-badge4.c
- *
- * Author: Christopher Hoover <ch@hpl.hp.com>
- * Copyright (C) 2002 Hewlett-Packard Company
- *
- * This program is free software; you can 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 <mach/hardware.h>
-#include <asm/leds.h>
-
-#include "leds.h"
-
-#define LED_STATE_ENABLED	1
-#define LED_STATE_CLAIMED	2
-
-static unsigned int led_state;
-static unsigned int hw_led_state;
-
-#define LED_RED		GPIO_GPIO(7)
-#define LED_GREEN       GPIO_GPIO(9)
-#define LED_MASK	(LED_RED|LED_GREEN)
-
-#define LED_IDLE	LED_GREEN
-#define LED_TIMER	LED_RED
-
-void badge4_leds_event(led_event_t evt)
-{
-        unsigned long flags;
-
-	local_irq_save(flags);
-
-        switch (evt) {
-        case led_start:
-		GPDR |= LED_MASK;
-                hw_led_state = LED_MASK;
-                led_state = LED_STATE_ENABLED;
-                break;
-
-        case led_stop:
-                led_state &= ~LED_STATE_ENABLED;
-                break;
-
-        case led_claim:
-                led_state |= LED_STATE_CLAIMED;
-                hw_led_state = LED_MASK;
-                break;
-
-        case led_release:
-                led_state &= ~LED_STATE_CLAIMED;
-                hw_led_state = LED_MASK;
-                break;
-
-#ifdef CONFIG_LEDS_TIMER
-        case led_timer:
-                if (!(led_state & LED_STATE_CLAIMED))
-                        hw_led_state ^= LED_TIMER;
-                break;
-#endif
-
-#ifdef CONFIG_LEDS_CPU
-        case led_idle_start:
-		/* LED off when system is idle */
-                if (!(led_state & LED_STATE_CLAIMED))
-                        hw_led_state &= ~LED_IDLE;
-                break;
-
-        case led_idle_end:
-                if (!(led_state & LED_STATE_CLAIMED))
-                        hw_led_state |= LED_IDLE;
-                break;
-#endif
-
-        case led_red_on:
-                if (!(led_state & LED_STATE_CLAIMED))
-                        hw_led_state &= ~LED_RED;
-                break;
-
-        case led_red_off:
-                if (!(led_state & LED_STATE_CLAIMED))
-                        hw_led_state |= LED_RED;
-                break;
-
-        case led_green_on:
-                if (!(led_state & LED_STATE_CLAIMED))
-                        hw_led_state &= ~LED_GREEN;
-                break;
-
-        case led_green_off:
-                if (!(led_state & LED_STATE_CLAIMED))
-                        hw_led_state |= LED_GREEN;
-                break;
-
-	default:
-		break;
-        }
-
-        if  (led_state & LED_STATE_ENABLED) {
-                GPSR = hw_led_state;
-                GPCR = hw_led_state ^ LED_MASK;
-        }
-
-	local_irq_restore(flags);
-}
diff --git a/arch/arm/mach-sa1100/leds-cerf.c b/arch/arm/mach-sa1100/leds-cerf.c
deleted file mode 100644
index 30fc3b2..0000000
--- a/arch/arm/mach-sa1100/leds-cerf.c
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * linux/arch/arm/mach-sa1100/leds-cerf.c
- *
- * Author: ???
- */
-#include <linux/init.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <asm/leds.h>
-
-#include "leds.h"
-
-
-#define LED_STATE_ENABLED	1
-#define LED_STATE_CLAIMED	2
-
-static unsigned int led_state;
-static unsigned int hw_led_state;
-
-#define LED_D0          GPIO_GPIO(0)
-#define LED_D1          GPIO_GPIO(1)
-#define LED_D2          GPIO_GPIO(2)
-#define LED_D3          GPIO_GPIO(3)
-#define LED_MASK        (LED_D0|LED_D1|LED_D2|LED_D3)
-
-void cerf_leds_event(led_event_t evt)
-{
-        unsigned long flags;
-
-	local_irq_save(flags);
-
-        switch (evt) {
-        case led_start:
-                hw_led_state = LED_MASK;
-                led_state = LED_STATE_ENABLED;
-                break;
-
-        case led_stop:
-                led_state &= ~LED_STATE_ENABLED;
-                break;
-
-        case led_claim:
-                led_state |= LED_STATE_CLAIMED;
-                hw_led_state = LED_MASK;
-                break;
-        case led_release:
-                led_state &= ~LED_STATE_CLAIMED;
-                hw_led_state = LED_MASK;
-                break;
-
-#ifdef CONFIG_LEDS_TIMER
-        case led_timer:
-                if (!(led_state & LED_STATE_CLAIMED))
-                        hw_led_state ^= LED_D0;
-                break;
-#endif
-
-#ifdef CONFIG_LEDS_CPU
-        case led_idle_start:
-                if (!(led_state & LED_STATE_CLAIMED))
-                        hw_led_state &= ~LED_D1;
-                break;
-
-        case led_idle_end:
-                if (!(led_state & LED_STATE_CLAIMED))
-                        hw_led_state |= LED_D1;
-                break;
-#endif
-        case led_green_on:
-                if (!(led_state & LED_STATE_CLAIMED))
-                        hw_led_state &= ~LED_D2;
-                break;
-
-        case led_green_off:
-                if (!(led_state & LED_STATE_CLAIMED))
-                        hw_led_state |= LED_D2;
-                break;
-
-        case led_amber_on:
-                if (!(led_state & LED_STATE_CLAIMED))
-                        hw_led_state &= ~LED_D3;
-                break;
-
-        case led_amber_off:
-                if (!(led_state & LED_STATE_CLAIMED))
-                        hw_led_state |= LED_D3;
-                break;
-
-        case led_red_on:
-                if (!(led_state & LED_STATE_CLAIMED))
-                        hw_led_state &= ~LED_D1;
-                break;
-
-        case led_red_off:
-                if (!(led_state & LED_STATE_CLAIMED))
-                        hw_led_state |= LED_D1;
-                break;
-
-        default:
-                break;
-        }
-
-        if  (led_state & LED_STATE_ENABLED) {
-                GPSR = hw_led_state;
-                GPCR = hw_led_state ^ LED_MASK;
-        }
-
-	local_irq_restore(flags);
-}
diff --git a/arch/arm/mach-sa1100/leds-hackkit.c b/arch/arm/mach-sa1100/leds-hackkit.c
deleted file mode 100644
index f8e4723..0000000
--- a/arch/arm/mach-sa1100/leds-hackkit.c
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * linux/arch/arm/mach-sa1100/leds-hackkit.c
- *
- * based on leds-lart.c
- *
- * (C) Erik Mouw (J.A.K.Mouw@its.tudelft.nl), April 21, 2000
- * (C) Stefan Eletzhofer <stefan.eletzhofer@eletztrick.de>, 2002
- *
- * The HackKit has two leds (GPIO 22/23). The red led (gpio 22) is used
- * as cpu led, the green one is used as timer led.
- */
-#include <linux/init.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <asm/leds.h>
-
-#include "leds.h"
-
-
-#define LED_STATE_ENABLED	1
-#define LED_STATE_CLAIMED	2
-
-static unsigned int led_state;
-static unsigned int hw_led_state;
-
-#define LED_GREEN    GPIO_GPIO23
-#define LED_RED    GPIO_GPIO22
-#define LED_MASK  (LED_RED | LED_GREEN)
-
-void hackkit_leds_event(led_event_t evt)
-{
-	unsigned long flags;
-
-	local_irq_save(flags);
-
-	switch(evt) {
-		case led_start:
-			/* pin 22/23 are outputs */
-			GPDR |= LED_MASK;
-			hw_led_state = LED_MASK;
-			led_state = LED_STATE_ENABLED;
-			break;
-
-		case led_stop:
-			led_state &= ~LED_STATE_ENABLED;
-			break;
-
-		case led_claim:
-			led_state |= LED_STATE_CLAIMED;
-			hw_led_state = LED_MASK;
-			break;
-
-		case led_release:
-			led_state &= ~LED_STATE_CLAIMED;
-			hw_led_state = LED_MASK;
-			break;
-
-#ifdef CONFIG_LEDS_TIMER
-		case led_timer:
-			if (!(led_state & LED_STATE_CLAIMED))
-				hw_led_state ^= LED_GREEN;
-			break;
-#endif
-
-#ifdef CONFIG_LEDS_CPU
-		case led_idle_start:
-			/* The LART people like the LED to be off when the
-			   system is idle... */
-			if (!(led_state & LED_STATE_CLAIMED))
-				hw_led_state &= ~LED_RED;
-			break;
-
-		case led_idle_end:
-			/* ... and on if the system is not idle */
-			if (!(led_state & LED_STATE_CLAIMED))
-				hw_led_state |= LED_RED;
-			break;
-#endif
-
-		case led_red_on:
-			if (led_state & LED_STATE_CLAIMED)
-				hw_led_state &= ~LED_RED;
-			break;
-
-		case led_red_off:
-			if (led_state & LED_STATE_CLAIMED)
-				hw_led_state |= LED_RED;
-			break;
-
-		case led_green_on:
-			if (led_state & LED_STATE_CLAIMED)
-				hw_led_state &= ~LED_GREEN;
-			break;
-
-		case led_green_off:
-			if (led_state & LED_STATE_CLAIMED)
-				hw_led_state |= LED_GREEN;
-			break;
-
-		default:
-			break;
-	}
-
-	/* Now set the GPIO state, or nothing will happen at all */
-	if (led_state & LED_STATE_ENABLED) {
-		GPSR = hw_led_state;
-		GPCR = hw_led_state ^ LED_MASK;
-	}
-
-	local_irq_restore(flags);
-}
diff --git a/arch/arm/mach-sa1100/leds-lart.c b/arch/arm/mach-sa1100/leds-lart.c
deleted file mode 100644
index 50a5b14..0000000
--- a/arch/arm/mach-sa1100/leds-lart.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * linux/arch/arm/mach-sa1100/leds-lart.c
- *
- * (C) Erik Mouw (J.A.K.Mouw@its.tudelft.nl), April 21, 2000
- *
- * LART uses the LED as follows:
- *   - GPIO23 is the LED, on if system is not idle
- *  You can use both CONFIG_LEDS_CPU and CONFIG_LEDS_TIMER at the same
- *  time, but in that case the timer events will still dictate the
- *  pace of the LED.
- */
-#include <linux/init.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <asm/leds.h>
-
-#include "leds.h"
-
-
-#define LED_STATE_ENABLED	1
-#define LED_STATE_CLAIMED	2
-
-static unsigned int led_state;
-static unsigned int hw_led_state;
-
-#define LED_23    GPIO_GPIO23
-#define LED_MASK  (LED_23)
-
-void lart_leds_event(led_event_t evt)
-{
-	unsigned long flags;
-
-	local_irq_save(flags);
-
-	switch(evt) {
-	case led_start:
-		/* pin 23 is output pin */
-		GPDR |= LED_23;
-		hw_led_state = LED_MASK;
-		led_state = LED_STATE_ENABLED;
-		break;
-
-	case led_stop:
-		led_state &= ~LED_STATE_ENABLED;
-		break;
-
-	case led_claim:
-		led_state |= LED_STATE_CLAIMED;
-		hw_led_state = LED_MASK;
-		break;
-
-	case led_release:
-		led_state &= ~LED_STATE_CLAIMED;
-		hw_led_state = LED_MASK;
-		break;
-
-#ifdef CONFIG_LEDS_TIMER
-	case led_timer:
-		if (!(led_state & LED_STATE_CLAIMED))
-			hw_led_state ^= LED_23;
-		break;
-#endif
-
-#ifdef CONFIG_LEDS_CPU
-	case led_idle_start:
-		/* The LART people like the LED to be off when the
-                   system is idle... */
-		if (!(led_state & LED_STATE_CLAIMED))
-			hw_led_state &= ~LED_23;
-		break;
-
-	case led_idle_end:
-		/* ... and on if the system is not idle */
-		if (!(led_state & LED_STATE_CLAIMED))
-			hw_led_state |= LED_23;
-		break;
-#endif
-
-	case led_red_on:
-		if (led_state & LED_STATE_CLAIMED)
-			hw_led_state &= ~LED_23;
-		break;
-
-	case led_red_off:
-		if (led_state & LED_STATE_CLAIMED)
-			hw_led_state |= LED_23;
-		break;
-
-	default:
-		break;
-	}
-
-	/* Now set the GPIO state, or nothing will happen at all */
-	if (led_state & LED_STATE_ENABLED) {
-		GPSR = hw_led_state;
-		GPCR = hw_led_state ^ LED_MASK;
-	}
-
-	local_irq_restore(flags);
-}
diff --git a/arch/arm/mach-sa1100/leds.c b/arch/arm/mach-sa1100/leds.c
deleted file mode 100644
index 5fe71a0..0000000
--- a/arch/arm/mach-sa1100/leds.c
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * linux/arch/arm/mach-sa1100/leds.c
- *
- * SA1100 LEDs dispatcher
- *
- * Copyright (C) 2001 Nicolas Pitre
- */
-#include <linux/compiler.h>
-#include <linux/init.h>
-
-#include <asm/leds.h>
-#include <asm/mach-types.h>
-
-#include "leds.h"
-
-static int __init
-sa1100_leds_init(void)
-{
-	if (machine_is_assabet())
-		leds_event = assabet_leds_event;
-	if (machine_is_consus())
-		leds_event = consus_leds_event;
-	if (machine_is_badge4())
-		leds_event = badge4_leds_event;
-	if (machine_is_brutus())
-		leds_event = brutus_leds_event;
-	if (machine_is_cerf())
-		leds_event = cerf_leds_event;
-	if (machine_is_flexanet())
-		leds_event = flexanet_leds_event;
-	if (machine_is_graphicsclient())
-		leds_event = graphicsclient_leds_event;
-	if (machine_is_hackkit())
-		leds_event = hackkit_leds_event;
-	if (machine_is_lart())
-		leds_event = lart_leds_event;
-	if (machine_is_pfs168())
-		leds_event = pfs168_leds_event;
-	if (machine_is_graphicsmaster())
-		leds_event = graphicsmaster_leds_event;
-	if (machine_is_adsbitsy())
-		leds_event = adsbitsy_leds_event;
-	if (machine_is_pt_system3())
-		leds_event = system3_leds_event;
-
-	leds_event(led_start);
-	return 0;
-}
-
-core_initcall(sa1100_leds_init);
diff --git a/arch/arm/mach-sa1100/leds.h b/arch/arm/mach-sa1100/leds.h
deleted file mode 100644
index 776b602..0000000
--- a/arch/arm/mach-sa1100/leds.h
+++ /dev/null
@@ -1,13 +0,0 @@
-extern void assabet_leds_event(led_event_t evt);
-extern void badge4_leds_event(led_event_t evt);
-extern void consus_leds_event(led_event_t evt);
-extern void brutus_leds_event(led_event_t evt);
-extern void cerf_leds_event(led_event_t evt);
-extern void flexanet_leds_event(led_event_t evt);
-extern void graphicsclient_leds_event(led_event_t evt);
-extern void hackkit_leds_event(led_event_t evt);
-extern void lart_leds_event(led_event_t evt);
-extern void pfs168_leds_event(led_event_t evt);
-extern void graphicsmaster_leds_event(led_event_t evt);
-extern void adsbitsy_leds_event(led_event_t evt);
-extern void system3_leds_event(led_event_t evt);
diff --git a/arch/arm/mach-sa1100/shannon.c b/arch/arm/mach-sa1100/shannon.c
index 5d33fc3..ff6b7b3 100644
--- a/arch/arm/mach-sa1100/shannon.c
+++ b/arch/arm/mach-sa1100/shannon.c
@@ -19,7 +19,7 @@
 #include <asm/mach/flash.h>
 #include <asm/mach/map.h>
 #include <asm/mach/serial_sa1100.h>
-#include <mach/mcp.h>
+#include <linux/platform_data/mfd-mcp-sa11x0.h>
 #include <mach/shannon.h>
 #include <mach/irqs.h>
 
diff --git a/arch/arm/mach-sa1100/simpad.c b/arch/arm/mach-sa1100/simpad.c
index fbd5359..71790e5 100644
--- a/arch/arm/mach-sa1100/simpad.c
+++ b/arch/arm/mach-sa1100/simpad.c
@@ -24,7 +24,7 @@
 #include <asm/mach/flash.h>
 #include <asm/mach/map.h>
 #include <asm/mach/serial_sa1100.h>
-#include <mach/mcp.h>
+#include <linux/platform_data/mfd-mcp-sa11x0.h>
 #include <mach/simpad.h>
 #include <mach/irqs.h>
 
@@ -124,7 +124,7 @@ static struct map_desc simpad_io_desc[] __initdata = {
 		.length		= 0x00800000,
 		.type		= MT_DEVICE
 	}, {	/* Simpad CS3 */
-		.virtual	= CS3_BASE,
+		.virtual	= (unsigned long)CS3_BASE,
 		.pfn		= __phys_to_pfn(SA1100_CS3_PHYS),
 		.length		= 0x00100000,
 		.type		= MT_DEVICE
diff --git a/arch/arm/mach-shark/Makefile b/arch/arm/mach-shark/Makefile
index 45be9b0..2965718 100644
--- a/arch/arm/mach-shark/Makefile
+++ b/arch/arm/mach-shark/Makefile
@@ -4,9 +4,7 @@
 
 # Object file lists.
 
-obj-y			:= core.o dma.o irq.o pci.o
+obj-y			:= core.o dma.o irq.o pci.o leds.o
 obj-m			:=
 obj-n			:=
 obj-			:=
-
-obj-$(CONFIG_LEDS)	+= leds.o
diff --git a/arch/arm/mach-shark/core.c b/arch/arm/mach-shark/core.c
index 2704bcd..9ad2e97 100644
--- a/arch/arm/mach-shark/core.c
+++ b/arch/arm/mach-shark/core.c
@@ -13,7 +13,6 @@
 
 #include <asm/setup.h>
 #include <asm/mach-types.h>
-#include <asm/leds.h>
 #include <asm/param.h>
 #include <asm/system_misc.h>
 
@@ -21,9 +20,6 @@
 #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
 
@@ -104,20 +100,6 @@ arch_initcall(shark_init);
 
 extern void shark_init_irq(void);
 
-static struct map_desc shark_io_desc[] __initdata = {
-	{
-		.virtual	= IO_BASE,
-		.pfn		= __phys_to_pfn(IO_START),
-		.length		= IO_SIZE,
-		.type		= MT_DEVICE
-	}
-};
-
-static void __init shark_map_io(void)
-{
-	iotable_init(shark_io_desc, ARRAY_SIZE(shark_io_desc));
-}
-
 #define IRQ_TIMER 0
 #define HZ_TIME ((1193180 + HZ/2) / HZ)
 
@@ -158,7 +140,6 @@ static void shark_init_early(void)
 MACHINE_START(SHARK, "Shark")
 	/* Maintainer: Alexander Schulz */
 	.atag_offset	= 0x3000,
-	.map_io		= shark_map_io,
 	.init_early	= shark_init_early,
 	.init_irq	= shark_init_irq,
 	.timer		= &shark_timer,
diff --git a/arch/arm/mach-shark/include/mach/debug-macro.S b/arch/arm/mach-shark/include/mach/debug-macro.S
index 20eb2bf..d129119 100644
--- a/arch/arm/mach-shark/include/mach/debug-macro.S
+++ b/arch/arm/mach-shark/include/mach/debug-macro.S
@@ -12,9 +12,10 @@
 */
 
 		.macro	addruart, rp, rv, tmp
-		mov	\rp, #0xe0000000
-		orr	\rp, \rp, #0x000003f8
-		mov	\rv, \rp
+		mov	\rp, #0x3f8
+		orr	\rv, \rp, #0xfe000000
+		orr	\rv, \rv, #0x00e00000
+		orr	\rp, \rp, #0x40000000
 		.endm
 
 		.macro	senduart,rd,rx
diff --git a/arch/arm/mach-shark/include/mach/entry-macro.S b/arch/arm/mach-shark/include/mach/entry-macro.S
index 5901b09..c9e49f0 100644
--- a/arch/arm/mach-shark/include/mach/entry-macro.S
+++ b/arch/arm/mach-shark/include/mach/entry-macro.S
@@ -8,7 +8,8 @@
  * warranty of any kind, whether express or implied.
  */
 		.macro  get_irqnr_preamble, base, tmp
-		mov	\base, #0xe0000000
+		mov	\base, #0xfe000000
+		orr	\base, \base, #0x00e00000
 		.endm
 
 		.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
diff --git a/arch/arm/mach-shark/include/mach/io.h b/arch/arm/mach-shark/include/mach/io.h
deleted file mode 100644
index 1a45fc0..0000000
--- a/arch/arm/mach-shark/include/mach/io.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * arch/arm/mach-shark/include/mach/io.h
- *
- * by Alexander Schulz
- *
- * derived from:
- * arch/arm/mach-ebsa110/include/mach/io.h
- * Copyright (C) 1997,1998 Russell King
- */
-
-#ifndef __ASM_ARM_ARCH_IO_H
-#define __ASM_ARM_ARCH_IO_H
-
-#define IO_SPACE_LIMIT 0xffffffff
-
-#define __io(a)                 ((void __iomem *)(0xe0000000 + (a)))
-
-#endif
diff --git a/arch/arm/mach-shark/leds.c b/arch/arm/mach-shark/leds.c
index 2560907..081c778 100644
--- a/arch/arm/mach-shark/leds.c
+++ b/arch/arm/mach-shark/leds.c
@@ -1,165 +1,117 @@
 /*
- * arch/arm/mach-shark/leds.c
- * by Alexander Schulz
- *
- * derived from:
- * arch/arm/kernel/leds-footbridge.c
- * Copyright (C) 1998-1999 Russell King
- *
  * DIGITAL Shark LED control routines.
  *
- * The leds use is as follows:
- *  - Green front - toggles state every 50 timer interrupts
- *  - Amber front - Unused, this is a dual color led (Amber/Green)
- *  - Amber back  - On if system is not idle
+ * Driver for the 3 user LEDs found on the Shark
+ * Based on Versatile and RealView machine LED code
  *
- * Changelog:
+ * License terms: GNU General Public License (GPL) version 2
+ * Author: Bryan Wu <bryan.wu@canonical.com>
  */
 #include <linux/kernel.h>
-#include <linux/module.h>
 #include <linux/init.h>
-#include <linux/spinlock.h>
-#include <linux/ioport.h>
 #include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/leds.h>
 
-#include <asm/leds.h>
+#include <asm/mach-types.h>
 
-#define LED_STATE_ENABLED	1
-#define LED_STATE_CLAIMED	2
+#if defined(CONFIG_NEW_LEDS) && defined(CONFIG_LEDS_CLASS)
+struct shark_led {
+	struct led_classdev cdev;
+	u8 mask;
+};
 
-#define SEQUOIA_LED_GREEN       (1<<6)
-#define SEQUOIA_LED_AMBER       (1<<5)
-#define SEQUOIA_LED_BACK        (1<<7)
+/*
+ * The triggers lines up below will only be used if the
+ * LED triggers are compiled in.
+ */
+static const struct {
+	const char *name;
+	const char *trigger;
+} shark_leds[] = {
+	{ "shark:amber0", "default-on", },	/* Bit 5 */
+	{ "shark:green", "heartbeat", },	/* Bit 6 */
+	{ "shark:amber1", "cpu0" },		/* Bit 7 */
+};
+
+static u16 led_reg_read(void)
+{
+	outw(0x09, 0x24);
+	return inw(0x26);
+}
 
-static char led_state;
-static short hw_led_state;
-static short saved_state;
+static void led_reg_write(u16 value)
+{
+	outw(0x09, 0x24);
+	outw(value, 0x26);
+}
 
-static DEFINE_RAW_SPINLOCK(leds_lock);
+static void shark_led_set(struct led_classdev *cdev,
+			      enum led_brightness b)
+{
+	struct shark_led *led = container_of(cdev,
+						 struct shark_led, cdev);
+	u16 reg = led_reg_read();
 
-short sequoia_read(int addr) {
-  outw(addr,0x24);
-  return inw(0x26);
-}
+	if (b != LED_OFF)
+		reg |= led->mask;
+	else
+		reg &= ~led->mask;
 
-void sequoia_write(short value,short addr) {
-  outw(addr,0x24);
-  outw(value,0x26);
+	led_reg_write(reg);
 }
 
-static void sequoia_leds_event(led_event_t evt)
+static enum led_brightness shark_led_get(struct led_classdev *cdev)
 {
-	unsigned long flags;
-
-	raw_spin_lock_irqsave(&leds_lock, flags);
+	struct shark_led *led = container_of(cdev,
+						 struct shark_led, cdev);
+	u16 reg = led_reg_read();
 
-	hw_led_state = sequoia_read(0x09);
+	return (reg & led->mask) ? LED_FULL : LED_OFF;
+}
 
-	switch (evt) {
-	case led_start:
-		hw_led_state |= SEQUOIA_LED_GREEN;
-		hw_led_state |= SEQUOIA_LED_AMBER;
-#ifdef CONFIG_LEDS_CPU
-		hw_led_state |= SEQUOIA_LED_BACK;
-#else
-		hw_led_state &= ~SEQUOIA_LED_BACK;
-#endif
-		led_state |= LED_STATE_ENABLED;
-		break;
-
-	case led_stop:
-		hw_led_state &= ~SEQUOIA_LED_BACK;
-		hw_led_state |= SEQUOIA_LED_GREEN;
-		hw_led_state |= SEQUOIA_LED_AMBER;
-		led_state &= ~LED_STATE_ENABLED;
-		break;
-
-	case led_claim:
-		led_state |= LED_STATE_CLAIMED;
-		saved_state = hw_led_state;
-		hw_led_state &= ~SEQUOIA_LED_BACK;
-		hw_led_state |= SEQUOIA_LED_GREEN;
-		hw_led_state |= SEQUOIA_LED_AMBER;
-		break;
-
-	case led_release:
-		led_state &= ~LED_STATE_CLAIMED;
-		hw_led_state = saved_state;
-		break;
-
-#ifdef CONFIG_LEDS_TIMER
-	case led_timer:
-		if (!(led_state & LED_STATE_CLAIMED))
-			hw_led_state ^= SEQUOIA_LED_GREEN;
-		break;
-#endif
+static int __init shark_leds_init(void)
+{
+	int i;
+	u16 reg;
 
-#ifdef CONFIG_LEDS_CPU
-	case led_idle_start:
-		if (!(led_state & LED_STATE_CLAIMED))
-			hw_led_state &= ~SEQUOIA_LED_BACK;
-		break;
+	if (!machine_is_shark())
+		return -ENODEV;
 
-	case led_idle_end:
-		if (!(led_state & LED_STATE_CLAIMED))
-			hw_led_state |= SEQUOIA_LED_BACK;
-		break;
-#endif
+	for (i = 0; i < ARRAY_SIZE(shark_leds); i++) {
+		struct shark_led *led;
 
-	case led_green_on:
-		if (led_state & LED_STATE_CLAIMED)
-			hw_led_state &= ~SEQUOIA_LED_GREEN;
-		break;
-
-	case led_green_off:
-		if (led_state & LED_STATE_CLAIMED)
-			hw_led_state |= SEQUOIA_LED_GREEN;
-		break;
-
-	case led_amber_on:
-		if (led_state & LED_STATE_CLAIMED)
-			hw_led_state &= ~SEQUOIA_LED_AMBER;
-		break;
-
-	case led_amber_off:
-		if (led_state & LED_STATE_CLAIMED)
-			hw_led_state |= SEQUOIA_LED_AMBER;
-		break;
-
-	case led_red_on:
-		if (led_state & LED_STATE_CLAIMED)
-			hw_led_state |= SEQUOIA_LED_BACK;
-		break;
-
-	case led_red_off:
-		if (led_state & LED_STATE_CLAIMED)
-			hw_led_state &= ~SEQUOIA_LED_BACK;
-		break;
-
-	default:
-		break;
-	}
+		led = kzalloc(sizeof(*led), GFP_KERNEL);
+		if (!led)
+			break;
 
-	if  (led_state & LED_STATE_ENABLED)
-		sequoia_write(hw_led_state,0x09);
+		led->cdev.name = shark_leds[i].name;
+		led->cdev.brightness_set = shark_led_set;
+		led->cdev.brightness_get = shark_led_get;
+		led->cdev.default_trigger = shark_leds[i].trigger;
 
-	raw_spin_unlock_irqrestore(&leds_lock, flags);
-}
+		/* Count in 5 bits offset */
+		led->mask = BIT(i + 5);
 
-static int __init leds_init(void)
-{
-	extern void (*leds_event)(led_event_t);
-	short temp;
-	
-	leds_event = sequoia_leds_event;
+		if (led_classdev_register(NULL, &led->cdev) < 0) {
+			kfree(led);
+			break;
+		}
+	}
 
 	/* Make LEDs independent of power-state */
-	request_region(0x24,4,"sequoia");
-	temp = sequoia_read(0x09);
-	temp |= 1<<10;
-	sequoia_write(temp,0x09);
-	leds_event(led_start);
+	request_region(0x24, 4, "led_reg");
+	reg = led_reg_read();
+	reg |= 1 << 10;
+	led_reg_write(reg);
+
 	return 0;
 }
 
-__initcall(leds_init);
+/*
+ * Since we may have triggers on any subsystem, defer registration
+ * until after subsystem_init.
+ */
+fs_initcall(shark_leds_init);
+#endif
diff --git a/arch/arm/mach-shark/pci.c b/arch/arm/mach-shark/pci.c
index 9089407..b8b4ab3 100644
--- a/arch/arm/mach-shark/pci.c
+++ b/arch/arm/mach-shark/pci.c
@@ -8,12 +8,15 @@
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/init.h>
+#include <linux/io.h>
 #include <video/vga.h>
 
 #include <asm/irq.h>
 #include <asm/mach/pci.h>
 #include <asm/mach-types.h>
 
+#define IO_START	0x40000000
+
 static int __init shark_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 	if (dev->bus->number == 0)
@@ -44,6 +47,8 @@ static int __init shark_pci_init(void)
 	pcibios_min_mem = 0x50000000;
 	vga_base = 0xe8000000;
 
+	pci_ioremap_io(0, IO_START);
+
 	pci_common_init(&shark_pci);
 
 	return 0;
diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile
index 0df5ae6..fe2c97c 100644
--- a/arch/arm/mach-shmobile/Makefile
+++ b/arch/arm/mach-shmobile/Makefile
@@ -3,7 +3,7 @@
 #
 
 # Common objects
-obj-y				:= timer.o console.o clock.o common.o
+obj-y				:= timer.o console.o clock.o
 
 # CPU objects
 obj-$(CONFIG_ARCH_SH7367)	+= setup-sh7367.o clock-sh7367.o intc-sh7367.o
diff --git a/arch/arm/mach-shmobile/board-ag5evm.c b/arch/arm/mach-shmobile/board-ag5evm.c
index d82c010..25eb88a 100644
--- a/arch/arm/mach-shmobile/board-ag5evm.c
+++ b/arch/arm/mach-shmobile/board-ag5evm.c
@@ -40,7 +40,6 @@
 #include <linux/mmc/sh_mobile_sdhi.h>
 #include <linux/mfd/tmio.h>
 #include <linux/sh_clk.h>
-#include <linux/videodev2.h>
 #include <video/sh_mobile_lcdc.h>
 #include <video/sh_mipi_dsi.h>
 #include <sound/sh_fsi.h>
@@ -650,6 +649,7 @@ static void __init ag5evm_init(void)
 }
 
 MACHINE_START(AG5EVM, "ag5evm")
+	.smp		= smp_ops(sh73a0_smp_ops),
 	.map_io		= sh73a0_map_io,
 	.init_early	= sh73a0_add_early_devices,
 	.nr_irqs	= NR_IRQS_LEGACY,
diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c
index f172ca8..790dc68 100644
--- a/arch/arm/mach-shmobile/board-ap4evb.c
+++ b/arch/arm/mach-shmobile/board-ap4evb.c
@@ -66,6 +66,8 @@
 #include <asm/mach/arch.h>
 #include <asm/setup.h>
 
+#include "sh-gpio.h"
+
 /*
  * Address	Interface		BusWidth	note
  * ------------------------------------------------------------------
@@ -432,7 +434,7 @@ static void usb1_host_port_power(int port, int power)
 		return;
 
 	/* set VBOUT/PWEN and EXTLP1 in DVSTCTR */
-	__raw_writew(__raw_readw(0xE68B0008) | 0x600, 0xE68B0008);
+	__raw_writew(__raw_readw(IOMEM(0xE68B0008)) | 0x600, IOMEM(0xE68B0008));
 }
 
 static struct r8a66597_platdata usb1_host_data = {
@@ -1224,11 +1226,20 @@ static struct i2c_board_info i2c1_devices[] = {
 };
 
 
-#define GPIO_PORT9CR	0xE6051009
-#define GPIO_PORT10CR	0xE605100A
-#define USCCR1		0xE6058144
+#define GPIO_PORT9CR	IOMEM(0xE6051009)
+#define GPIO_PORT10CR	IOMEM(0xE605100A)
+#define USCCR1		IOMEM(0xE6058144)
 static void __init ap4evb_init(void)
 {
+	struct pm_domain_device domain_devices[] = {
+		{ "A4LC", &lcdc1_device, },
+		{ "A4LC", &lcdc_device, },
+		{ "A4MP", &fsi_device, },
+		{ "A3SP", &sh_mmcif_device, },
+		{ "A3SP", &sdhi0_device, },
+		{ "A3SP", &sdhi1_device, },
+		{ "A4R", &ceu_device, },
+	};
 	u32 srcr4;
 	struct clk *clk;
 
@@ -1304,7 +1315,7 @@ static void __init ap4evb_init(void)
 	gpio_request(GPIO_FN_OVCN2_1,    NULL);
 
 	/* setup USB phy */
-	__raw_writew(0x8a0a, 0xE6058130);	/* USBCR4 */
+	__raw_writew(0x8a0a, IOMEM(0xE6058130));	/* USBCR4 */
 
 	/* enable FSI2 port A (ak4643) */
 	gpio_request(GPIO_FN_FSIAIBT,	NULL);
@@ -1453,7 +1464,7 @@ static void __init ap4evb_init(void)
 	gpio_request(GPIO_FN_HDMI_CEC, NULL);
 
 	/* Reset HDMI, must be held at least one EXTALR (32768Hz) period */
-#define SRCR4 0xe61580bc
+#define SRCR4 IOMEM(0xe61580bc)
 	srcr4 = __raw_readl(SRCR4);
 	__raw_writel(srcr4 | (1 << 13), SRCR4);
 	udelay(50);
@@ -1461,14 +1472,8 @@ static void __init ap4evb_init(void)
 
 	platform_add_devices(ap4evb_devices, ARRAY_SIZE(ap4evb_devices));
 
-	rmobile_add_device_to_domain(&sh7372_pd_a4lc, &lcdc1_device);
-	rmobile_add_device_to_domain(&sh7372_pd_a4lc, &lcdc_device);
-	rmobile_add_device_to_domain(&sh7372_pd_a4mp, &fsi_device);
-
-	rmobile_add_device_to_domain(&sh7372_pd_a3sp, &sh_mmcif_device);
-	rmobile_add_device_to_domain(&sh7372_pd_a3sp, &sdhi0_device);
-	rmobile_add_device_to_domain(&sh7372_pd_a3sp, &sdhi1_device);
-	rmobile_add_device_to_domain(&sh7372_pd_a4r, &ceu_device);
+	rmobile_add_devices_to_domains(domain_devices,
+				       ARRAY_SIZE(domain_devices));
 
 	hdmi_init_pm_clock();
 	fsi_init_pm_clock();
@@ -1483,6 +1488,6 @@ MACHINE_START(AP4EVB, "ap4evb")
 	.init_irq	= sh7372_init_irq,
 	.handle_irq	= shmobile_handle_irq_intc,
 	.init_machine	= ap4evb_init,
-	.init_late	= shmobile_init_late,
+	.init_late	= sh7372_pm_init_late,
 	.timer		= &shmobile_timer,
 MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
index 453a6e5..2912eab 100644
--- a/arch/arm/mach-shmobile/board-armadillo800eva.c
+++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
@@ -37,6 +37,7 @@
 #include <linux/mmc/host.h>
 #include <linux/mmc/sh_mmcif.h>
 #include <linux/mmc/sh_mobile_sdhi.h>
+#include <linux/i2c-gpio.h>
 #include <mach/common.h>
 #include <mach/irqs.h>
 #include <mach/r8a7740.h>
@@ -54,6 +55,8 @@
 #include <sound/sh_fsi.h>
 #include <sound/simple_card.h>
 
+#include "sh-gpio.h"
+
 /*
  * CON1		Camera Module
  * CON2		Extension Bus
@@ -135,7 +138,7 @@
  *	usbhsf_power_ctrl()
  */
 #define IRQ7		evt2irq(0x02e0)
-#define USBCR1		0xe605810a
+#define USBCR1		IOMEM(0xe605810a)
 #define USBH		0xC6700000
 #define USBH_USBCTR	0x10834
 
@@ -877,6 +880,21 @@ static struct platform_device fsi_hdmi_device = {
 	},
 };
 
+/* RTC: RTC connects i2c-gpio. */
+static struct i2c_gpio_platform_data i2c_gpio_data = {
+	.sda_pin	= GPIO_PORT208,
+	.scl_pin	= GPIO_PORT91,
+	.udelay		= 5, /* 100 kHz */
+};
+
+static struct platform_device i2c_gpio_device = {
+	.name = "i2c-gpio",
+	.id = 2,
+	.dev = {
+		.platform_data = &i2c_gpio_data,
+	},
+};
+
 /* I2C */
 static struct i2c_board_info i2c0_devices[] = {
 	{
@@ -888,6 +906,13 @@ static struct i2c_board_info i2c0_devices[] = {
 	},
 };
 
+static struct i2c_board_info i2c2_devices[] = {
+	{
+		I2C_BOARD_INFO("s35390a", 0x30),
+		.type = "s35390a",
+	},
+};
+
 /*
  * board devices
  */
@@ -904,6 +929,7 @@ static struct platform_device *eva_devices[] __initdata = {
 	&fsi_device,
 	&fsi_wm8978_device,
 	&fsi_hdmi_device,
+	&i2c_gpio_device,
 };
 
 static void __init eva_clock_init(void)
@@ -950,8 +976,8 @@ clock_error:
 /*
  * board init
  */
-#define GPIO_PORT7CR	0xe6050007
-#define GPIO_PORT8CR	0xe6050008
+#define GPIO_PORT7CR	IOMEM(0xe6050007)
+#define GPIO_PORT8CR	IOMEM(0xe6050008)
 static void __init eva_init(void)
 {
 	struct platform_device *usb = NULL;
@@ -1174,6 +1200,7 @@ static void __init eva_init(void)
 #endif
 
 	i2c_register_board_info(0, i2c0_devices, ARRAY_SIZE(i2c0_devices));
+	i2c_register_board_info(2, i2c2_devices, ARRAY_SIZE(i2c2_devices));
 
 	r8a7740_add_standard_devices();
 
@@ -1182,10 +1209,10 @@ static void __init eva_init(void)
 
 	eva_clock_init();
 
-	rmobile_add_device_to_domain(&r8a7740_pd_a4lc, &lcdc0_device);
-	rmobile_add_device_to_domain(&r8a7740_pd_a4lc, &hdmi_lcdc_device);
+	rmobile_add_device_to_domain("A4LC", &lcdc0_device);
+	rmobile_add_device_to_domain("A4LC", &hdmi_lcdc_device);
 	if (usb)
-		rmobile_add_device_to_domain(&r8a7740_pd_a3sp, usb);
+		rmobile_add_device_to_domain("A3SP", usb);
 }
 
 static void __init eva_earlytimer_init(void)
diff --git a/arch/arm/mach-shmobile/board-bonito.c b/arch/arm/mach-shmobile/board-bonito.c
index 4129008..cb8c994 100644
--- a/arch/arm/mach-shmobile/board-bonito.c
+++ b/arch/arm/mach-shmobile/board-bonito.c
@@ -108,12 +108,12 @@ static struct regulator_consumer_supply dummy_supplies[] = {
 #define FPGA_ETH_IRQ		(FPGA_IRQ0 + 15)
 static u16 bonito_fpga_read(u32 offset)
 {
-	return __raw_readw(0xf0003000 + offset);
+	return __raw_readw(IOMEM(0xf0003000) + offset);
 }
 
 static void bonito_fpga_write(u32 offset, u16 val)
 {
-	__raw_writew(val, 0xf0003000 + offset);
+	__raw_writew(val, IOMEM(0xf0003000) + offset);
 }
 
 static void bonito_fpga_irq_disable(struct irq_data *data)
@@ -361,8 +361,8 @@ static void __init bonito_map_io(void)
 #define BIT_ON(sw, bit)		(sw & (1 << bit))
 #define BIT_OFF(sw, bit)	(!(sw & (1 << bit)))
 
-#define VCCQ1CR		0xE6058140
-#define VCCQ1LCDCR	0xE6058186
+#define VCCQ1CR		IOMEM(0xE6058140)
+#define VCCQ1LCDCR	IOMEM(0xE6058186)
 
 static void __init bonito_init(void)
 {
diff --git a/arch/arm/mach-shmobile/board-g3evm.c b/arch/arm/mach-shmobile/board-g3evm.c
index 796fa00..b179d4c 100644
--- a/arch/arm/mach-shmobile/board-g3evm.c
+++ b/arch/arm/mach-shmobile/board-g3evm.c
@@ -106,7 +106,7 @@ static void usb_host_port_power(int port, int power)
 		return;
 
 	/* set VBOUT/PWEN and EXTLP0 in DVSTCTR */
-	__raw_writew(__raw_readw(0xe6890008) | 0x600, 0xe6890008);
+	__raw_writew(__raw_readw(IOMEM(0xe6890008)) | 0x600, IOMEM(0xe6890008));
 }
 
 static struct r8a66597_platdata usb_host_data = {
@@ -279,10 +279,10 @@ static void __init g3evm_init(void)
 	gpio_request(GPIO_FN_IDIN, NULL);
 
 	/* setup USB phy */
-	__raw_writew(0x0300, 0xe605810a);	/* USBCR1 */
-	__raw_writew(0x00e0, 0xe60581c0);	/* CPFCH */
-	__raw_writew(0x6010, 0xe60581c6);	/* CGPOSR */
-	__raw_writew(0x8a0a, 0xe605810c);	/* USBCR2 */
+	__raw_writew(0x0300, IOMEM(0xe605810a));	/* USBCR1 */
+	__raw_writew(0x00e0, IOMEM(0xe60581c0));	/* CPFCH */
+	__raw_writew(0x6010, IOMEM(0xe60581c6));	/* CGPOSR */
+	__raw_writew(0x8a0a, IOMEM(0xe605810c));	/* USBCR2 */
 
 	/* KEYSC @ CN7 */
 	gpio_request(GPIO_FN_PORT42_KEYOUT0, NULL);
@@ -320,7 +320,7 @@ static void __init g3evm_init(void)
 	gpio_request(GPIO_FN_WE0_XWR0_FWE, NULL);
 	gpio_request(GPIO_FN_FRB, NULL);
 	/* FOE, FCDE, FSC on dedicated pins */
-	__raw_writel(__raw_readl(0xe6158048) & ~(1 << 15), 0xe6158048);
+	__raw_writel(__raw_readl(IOMEM(0xe6158048)) & ~(1 << 15), IOMEM(0xe6158048));
 
 	/* IrDA */
 	gpio_request(GPIO_FN_IRDA_OUT, NULL);
diff --git a/arch/arm/mach-shmobile/board-g4evm.c b/arch/arm/mach-shmobile/board-g4evm.c
index fa5dfc5..35c126c 100644
--- a/arch/arm/mach-shmobile/board-g4evm.c
+++ b/arch/arm/mach-shmobile/board-g4evm.c
@@ -42,6 +42,8 @@
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
+#include "sh-gpio.h"
+
 /*
  * SDHI
  *
@@ -126,7 +128,7 @@ static void usb_host_port_power(int port, int power)
 		return;
 
 	/* set VBOUT/PWEN and EXTLP0 in DVSTCTR */
-	__raw_writew(__raw_readw(0xe6890008) | 0x600, 0xe6890008);
+	__raw_writew(__raw_readw(IOMEM(0xe6890008)) | 0x600, IOMEM(0xe6890008));
 }
 
 static struct r8a66597_platdata usb_host_data = {
@@ -270,17 +272,17 @@ static struct platform_device *g4evm_devices[] __initdata = {
 	&sdhi1_device,
 };
 
-#define GPIO_SDHID0_D0	0xe60520fc
-#define GPIO_SDHID0_D1	0xe60520fd
-#define GPIO_SDHID0_D2	0xe60520fe
-#define GPIO_SDHID0_D3	0xe60520ff
-#define GPIO_SDHICMD0	0xe6052100
+#define GPIO_SDHID0_D0	IOMEM(0xe60520fc)
+#define GPIO_SDHID0_D1	IOMEM(0xe60520fd)
+#define GPIO_SDHID0_D2	IOMEM(0xe60520fe)
+#define GPIO_SDHID0_D3	IOMEM(0xe60520ff)
+#define GPIO_SDHICMD0	IOMEM(0xe6052100)
 
-#define GPIO_SDHID1_D0	0xe6052103
-#define GPIO_SDHID1_D1	0xe6052104
-#define GPIO_SDHID1_D2	0xe6052105
-#define GPIO_SDHID1_D3	0xe6052106
-#define GPIO_SDHICMD1	0xe6052107
+#define GPIO_SDHID1_D0	IOMEM(0xe6052103)
+#define GPIO_SDHID1_D1	IOMEM(0xe6052104)
+#define GPIO_SDHID1_D2	IOMEM(0xe6052105)
+#define GPIO_SDHID1_D3	IOMEM(0xe6052106)
+#define GPIO_SDHICMD1	IOMEM(0xe6052107)
 
 static void __init g4evm_init(void)
 {
@@ -318,10 +320,10 @@ static void __init g4evm_init(void)
 	gpio_request(GPIO_FN_IDIN, NULL);
 
 	/* setup USB phy */
-	__raw_writew(0x0200, 0xe605810a);       /* USBCR1 */
-	__raw_writew(0x00e0, 0xe60581c0);       /* CPFCH */
-	__raw_writew(0x6010, 0xe60581c6);       /* CGPOSR */
-	__raw_writew(0x8a0a, 0xe605810c);       /* USBCR2 */
+	__raw_writew(0x0200, IOMEM(0xe605810a));       /* USBCR1 */
+	__raw_writew(0x00e0, IOMEM(0xe60581c0));       /* CPFCH */
+	__raw_writew(0x6010, IOMEM(0xe60581c6));       /* CGPOSR */
+	__raw_writew(0x8a0a, IOMEM(0xe605810c));       /* USBCR2 */
 
 	/* KEYSC @ CN31 */
 	gpio_request(GPIO_FN_PORT60_KEYOUT5, NULL);
diff --git a/arch/arm/mach-shmobile/board-kota2.c b/arch/arm/mach-shmobile/board-kota2.c
index 21dbe54..bf88f9a 100644
--- a/arch/arm/mach-shmobile/board-kota2.c
+++ b/arch/arm/mach-shmobile/board-kota2.c
@@ -545,6 +545,7 @@ static void __init kota2_init(void)
 }
 
 MACHINE_START(KOTA2, "kota2")
+	.smp		= smp_ops(sh73a0_smp_ops),
 	.map_io		= sh73a0_map_io,
 	.init_early	= sh73a0_add_early_devices,
 	.nr_irqs	= NR_IRQS_LEGACY,
diff --git a/arch/arm/mach-shmobile/board-kzm9d.c b/arch/arm/mach-shmobile/board-kzm9d.c
index 2c986ea..b52bc0d 100644
--- a/arch/arm/mach-shmobile/board-kzm9d.c
+++ b/arch/arm/mach-shmobile/board-kzm9d.c
@@ -84,6 +84,7 @@ static const char *kzm9d_boards_compat_dt[] __initdata = {
 };
 
 DT_MACHINE_START(KZM9D_DT, "kzm9d")
+	.smp		= smp_ops(emev2_smp_ops),
 	.map_io		= emev2_map_io,
 	.init_early	= emev2_add_early_devices,
 	.nr_irqs	= NR_IRQS_LEGACY,
diff --git a/arch/arm/mach-shmobile/board-kzm9g.c b/arch/arm/mach-shmobile/board-kzm9g.c
index 3b8a017..ab5bbce 100644
--- a/arch/arm/mach-shmobile/board-kzm9g.c
+++ b/arch/arm/mach-shmobile/board-kzm9g.c
@@ -133,8 +133,8 @@ static struct platform_device usb_host_device = {
 
 /* USB Func CN17 */
 struct usbhs_private {
-	unsigned int phy;
-	unsigned int cr2;
+	void __iomem *phy;
+	void __iomem *cr2;
 	struct renesas_usbhs_platform_info info;
 };
 
@@ -232,8 +232,8 @@ static u32 usbhs_pipe_cfg[] = {
 };
 
 static struct usbhs_private usbhs_private = {
-	.phy	= 0xe60781e0,		/* USBPHYINT */
-	.cr2	= 0xe605810c,		/* USBCR2 */
+	.phy	= IOMEM(0xe60781e0),		/* USBPHYINT */
+	.cr2	= IOMEM(0xe605810c),		/* USBCR2 */
 	.info = {
 		.platform_callback = {
 			.hardware_init	= usbhs_hardware_init,
@@ -384,6 +384,8 @@ static struct regulator_consumer_supply fixed2v8_power_consumers[] =
 
 /* SDHI */
 static struct sh_mobile_sdhi_info sdhi0_info = {
+	.dma_slave_tx	= SHDMA_SLAVE_SDHI0_TX,
+	.dma_slave_rx	= SHDMA_SLAVE_SDHI0_RX,
 	.tmio_flags	= TMIO_MMC_HAS_IDLE_WAIT,
 	.tmio_caps	= MMC_CAP_SD_HIGHSPEED,
 	.tmio_ocr_mask	= MMC_VDD_27_28 | MMC_VDD_28_29,
@@ -424,6 +426,8 @@ static struct platform_device sdhi0_device = {
 
 /* Micro SD */
 static struct sh_mobile_sdhi_info sdhi2_info = {
+	.dma_slave_tx	= SHDMA_SLAVE_SDHI2_TX,
+	.dma_slave_rx	= SHDMA_SLAVE_SDHI2_RX,
 	.tmio_flags	= TMIO_MMC_HAS_IDLE_WAIT |
 			  TMIO_MMC_USE_GPIO_CD |
 			  TMIO_MMC_WRPROTECT_DISABLE,
@@ -482,12 +486,10 @@ static struct gpio_keys_button gpio_buttons[] = {
 static struct gpio_keys_platform_data gpio_key_info = {
 	.buttons	= gpio_buttons,
 	.nbuttons	= ARRAY_SIZE(gpio_buttons),
-	.poll_interval	= 250, /* poling at this point */
 };
 
 static struct platform_device gpio_keys_device = {
-	/* gpio-pcf857x.c driver doesn't support gpio_to_irq() */
-	.name	= "gpio-keys-polled",
+	.name	= "gpio-keys",
 	.dev	= {
 		.platform_data  = &gpio_key_info,
 	},
@@ -550,6 +552,7 @@ static struct platform_device fsi_ak4648_device = {
 /* I2C */
 static struct pcf857x_platform_data pcf8575_pdata = {
 	.gpio_base	= GPIO_PCF8575_BASE,
+	.irq		= intcs_evt2irq(0x3260), /* IRQ19 */
 };
 
 static struct i2c_board_info i2c0_devices[] = {
@@ -558,7 +561,15 @@ static struct i2c_board_info i2c0_devices[] = {
 	},
 	{
 		I2C_BOARD_INFO("r2025sd", 0x32),
-	}
+	},
+	{
+		I2C_BOARD_INFO("ak8975", 0x0c),
+		.irq = intcs_evt2irq(0x3380), /* IRQ28 */
+	},
+	{
+		I2C_BOARD_INFO("adxl34x", 0x1d),
+		.irq = intcs_evt2irq(0x3340), /* IRQ26 */
+	},
 };
 
 static struct i2c_board_info i2c1_devices[] = {
@@ -763,12 +774,20 @@ static void __init kzm_init(void)
 	platform_add_devices(kzm_devices, ARRAY_SIZE(kzm_devices));
 }
 
+static void kzm9g_restart(char mode, const char *cmd)
+{
+#define RESCNT2 0xe6188020
+	/* Do soft power on reset */
+	writel((1 << 31), RESCNT2);
+}
+
 static const char *kzm9g_boards_compat_dt[] __initdata = {
 	"renesas,kzm9g",
 	NULL,
 };
 
 DT_MACHINE_START(KZM9G_DT, "kzm9g")
+	.smp		= smp_ops(sh73a0_smp_ops),
 	.map_io		= sh73a0_map_io,
 	.init_early	= sh73a0_add_early_devices,
 	.nr_irqs	= NR_IRQS_LEGACY,
@@ -777,5 +796,6 @@ DT_MACHINE_START(KZM9G_DT, "kzm9g")
 	.init_machine	= kzm_init,
 	.init_late	= shmobile_init_late,
 	.timer		= &shmobile_timer,
+	.restart	= kzm9g_restart,
 	.dt_compat	= kzm9g_boards_compat_dt,
 MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c
index c129542..0c27c81 100644
--- a/arch/arm/mach-shmobile/board-mackerel.c
+++ b/arch/arm/mach-shmobile/board-mackerel.c
@@ -64,6 +64,8 @@
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 
+#include "sh-gpio.h"
+
 /*
  * Address	Interface		BusWidth	note
  * ------------------------------------------------------------------
@@ -583,8 +585,8 @@ out:
 #define USBHS0_POLL_INTERVAL (HZ * 5)
 
 struct usbhs_private {
-	unsigned int usbphyaddr;
-	unsigned int usbcrcaddr;
+	void __iomem *usbphyaddr;
+	void __iomem *usbcrcaddr;
 	struct renesas_usbhs_platform_info info;
 	struct delayed_work work;
 	struct platform_device *pdev;
@@ -642,7 +644,7 @@ static void usbhs0_hardware_exit(struct platform_device *pdev)
 }
 
 static struct usbhs_private usbhs0_private = {
-	.usbcrcaddr	= 0xe605810c,		/* USBCR2 */
+	.usbcrcaddr	= IOMEM(0xe605810c),		/* USBCR2 */
 	.info = {
 		.platform_callback = {
 			.hardware_init	= usbhs0_hardware_init,
@@ -776,8 +778,8 @@ static u32 usbhs1_pipe_cfg[] = {
 };
 
 static struct usbhs_private usbhs1_private = {
-	.usbphyaddr	= 0xe60581e2,		/* USBPHY1INTAP */
-	.usbcrcaddr	= 0xe6058130,		/* USBCR4 */
+	.usbphyaddr	= IOMEM(0xe60581e2),	/* USBPHY1INTAP */
+	.usbcrcaddr	= IOMEM(0xe6058130),	/* USBCR4 */
 	.info = {
 		.platform_callback = {
 			.hardware_init	= usbhs1_hardware_init,
@@ -1402,14 +1404,30 @@ static struct i2c_board_info i2c1_devices[] = {
 	},
 };
 
-#define GPIO_PORT9CR	0xE6051009
-#define GPIO_PORT10CR	0xE605100A
-#define GPIO_PORT167CR	0xE60520A7
-#define GPIO_PORT168CR	0xE60520A8
-#define SRCR4		0xe61580bc
-#define USCCR1		0xE6058144
+#define GPIO_PORT9CR	IOMEM(0xE6051009)
+#define GPIO_PORT10CR	IOMEM(0xE605100A)
+#define GPIO_PORT167CR	IOMEM(0xE60520A7)
+#define GPIO_PORT168CR	IOMEM(0xE60520A8)
+#define SRCR4		IOMEM(0xe61580bc)
+#define USCCR1		IOMEM(0xE6058144)
 static void __init mackerel_init(void)
 {
+	struct pm_domain_device domain_devices[] = {
+		{ "A4LC", &lcdc_device, },
+		{ "A4LC", &hdmi_lcdc_device, },
+		{ "A4LC", &meram_device, },
+		{ "A4MP", &fsi_device, },
+		{ "A3SP", &usbhs0_device, },
+		{ "A3SP", &usbhs1_device, },
+		{ "A3SP", &nand_flash_device, },
+		{ "A3SP", &sh_mmcif_device, },
+		{ "A3SP", &sdhi0_device, },
+#if !defined(CONFIG_MMC_SH_MMCIF) && !defined(CONFIG_MMC_SH_MMCIF_MODULE)
+		{ "A3SP", &sdhi1_device, },
+#endif
+		{ "A3SP", &sdhi2_device, },
+		{ "A4R", &ceu_device, },
+	};
 	u32 srcr4;
 	struct clk *clk;
 
@@ -1624,20 +1642,8 @@ static void __init mackerel_init(void)
 
 	platform_add_devices(mackerel_devices, ARRAY_SIZE(mackerel_devices));
 
-	rmobile_add_device_to_domain(&sh7372_pd_a4lc, &lcdc_device);
-	rmobile_add_device_to_domain(&sh7372_pd_a4lc, &hdmi_lcdc_device);
-	rmobile_add_device_to_domain(&sh7372_pd_a4lc, &meram_device);
-	rmobile_add_device_to_domain(&sh7372_pd_a4mp, &fsi_device);
-	rmobile_add_device_to_domain(&sh7372_pd_a3sp, &usbhs0_device);
-	rmobile_add_device_to_domain(&sh7372_pd_a3sp, &usbhs1_device);
-	rmobile_add_device_to_domain(&sh7372_pd_a3sp, &nand_flash_device);
-	rmobile_add_device_to_domain(&sh7372_pd_a3sp, &sh_mmcif_device);
-	rmobile_add_device_to_domain(&sh7372_pd_a3sp, &sdhi0_device);
-#if !defined(CONFIG_MMC_SH_MMCIF) && !defined(CONFIG_MMC_SH_MMCIF_MODULE)
-	rmobile_add_device_to_domain(&sh7372_pd_a3sp, &sdhi1_device);
-#endif
-	rmobile_add_device_to_domain(&sh7372_pd_a3sp, &sdhi2_device);
-	rmobile_add_device_to_domain(&sh7372_pd_a4r, &ceu_device);
+	rmobile_add_devices_to_domains(domain_devices,
+				       ARRAY_SIZE(domain_devices));
 
 	hdmi_init_pm_clock();
 	sh7372_pm_init();
@@ -1651,6 +1657,6 @@ MACHINE_START(MACKEREL, "mackerel")
 	.init_irq	= sh7372_init_irq,
 	.handle_irq	= shmobile_handle_irq_intc,
 	.init_machine	= mackerel_init,
-	.init_late	= shmobile_init_late,
+	.init_late	= sh7372_pm_init_late,
 	.timer		= &shmobile_timer,
 MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-marzen.c b/arch/arm/mach-shmobile/board-marzen.c
index fcf5a47..b8a7525 100644
--- a/arch/arm/mach-shmobile/board-marzen.c
+++ b/arch/arm/mach-shmobile/board-marzen.c
@@ -30,6 +30,8 @@
 #include <linux/regulator/fixed.h>
 #include <linux/regulator/machine.h>
 #include <linux/smsc911x.h>
+#include <linux/mmc/sh_mobile_sdhi.h>
+#include <linux/mfd/tmio.h>
 #include <mach/hardware.h>
 #include <mach/r8a7779.h>
 #include <mach/common.h>
@@ -39,6 +41,12 @@
 #include <asm/hardware/gic.h>
 #include <asm/traps.h>
 
+/* Fixed 3.3V regulator to be used by SDHI0 */
+static struct regulator_consumer_supply fixed3v3_power_consumers[] = {
+	REGULATOR_SUPPLY("vmmc", "sh_mobile_sdhi.0"),
+	REGULATOR_SUPPLY("vqmmc", "sh_mobile_sdhi.0"),
+};
+
 /* Dummy supplies, where voltage doesn't matter */
 static struct regulator_consumer_supply dummy_supplies[] = {
 	REGULATOR_SUPPLY("vddvario", "smsc911x"),
@@ -75,13 +83,61 @@ static struct platform_device eth_device = {
 	.num_resources	= ARRAY_SIZE(smsc911x_resources),
 };
 
+static struct resource sdhi0_resources[] = {
+	[0] = {
+		.name	= "sdhi0",
+		.start	= 0xffe4c000,
+		.end	= 0xffe4c0ff,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= gic_spi(104),
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct sh_mobile_sdhi_info sdhi0_platform_data = {
+	.tmio_flags = TMIO_MMC_WRPROTECT_DISABLE | TMIO_MMC_HAS_IDLE_WAIT,
+	.tmio_caps = MMC_CAP_SD_HIGHSPEED,
+};
+
+static struct platform_device sdhi0_device = {
+	.name = "sh_mobile_sdhi",
+	.num_resources = ARRAY_SIZE(sdhi0_resources),
+	.resource = sdhi0_resources,
+	.id = 0,
+	.dev = {
+		.platform_data = &sdhi0_platform_data,
+	}
+};
+
+/* Thermal */
+static struct resource thermal_resources[] = {
+	[0] = {
+		.start		= 0xFFC48000,
+		.end		= 0xFFC48038 - 1,
+		.flags		= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device thermal_device = {
+	.name		= "rcar_thermal",
+	.resource	= thermal_resources,
+	.num_resources	= ARRAY_SIZE(thermal_resources),
+};
+
 static struct platform_device *marzen_devices[] __initdata = {
 	&eth_device,
+	&sdhi0_device,
+	&thermal_device,
 };
 
 static void __init marzen_init(void)
 {
-	regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
+	regulator_register_always_on(0, "fixed-3.3V", fixed3v3_power_consumers,
+				ARRAY_SIZE(fixed3v3_power_consumers), 3300000);
+	regulator_register_fixed(1, dummy_supplies,
+				ARRAY_SIZE(dummy_supplies));
 
 	r8a7779_pinmux_init();
 
@@ -97,11 +153,22 @@ static void __init marzen_init(void)
 	gpio_request(GPIO_FN_EX_CS0, NULL); /* nCS */
 	gpio_request(GPIO_FN_IRQ1_B, NULL); /* IRQ + PME */
 
+	/* SD0 (CN20) */
+	gpio_request(GPIO_FN_SD0_CLK, NULL);
+	gpio_request(GPIO_FN_SD0_CMD, NULL);
+	gpio_request(GPIO_FN_SD0_DAT0, NULL);
+	gpio_request(GPIO_FN_SD0_DAT1, NULL);
+	gpio_request(GPIO_FN_SD0_DAT2, NULL);
+	gpio_request(GPIO_FN_SD0_DAT3, NULL);
+	gpio_request(GPIO_FN_SD0_CD, NULL);
+	gpio_request(GPIO_FN_SD0_WP, NULL);
+
 	r8a7779_add_standard_devices();
 	platform_add_devices(marzen_devices, ARRAY_SIZE(marzen_devices));
 }
 
 MACHINE_START(MARZEN, "marzen")
+	.smp		= smp_ops(r8a7779_smp_ops),
 	.map_io		= r8a7779_map_io,
 	.init_early	= r8a7779_add_early_devices,
 	.nr_irqs	= NR_IRQS_LEGACY,
diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c
index ad5fccc..6729e00 100644
--- a/arch/arm/mach-shmobile/clock-r8a7740.c
+++ b/arch/arm/mach-shmobile/clock-r8a7740.c
@@ -41,29 +41,29 @@
  */
 
 /* CPG registers */
-#define FRQCRA		0xe6150000
-#define FRQCRB		0xe6150004
-#define VCLKCR1		0xE6150008
-#define VCLKCR2		0xE615000c
-#define FRQCRC		0xe61500e0
-#define FSIACKCR	0xe6150018
-#define PLLC01CR	0xe6150028
-
-#define SUBCKCR		0xe6150080
-#define USBCKCR		0xe615008c
-
-#define MSTPSR0		0xe6150030
-#define MSTPSR1		0xe6150038
-#define MSTPSR2		0xe6150040
-#define MSTPSR3		0xe6150048
-#define MSTPSR4		0xe615004c
-#define FSIBCKCR	0xe6150090
-#define HDMICKCR	0xe6150094
-#define SMSTPCR0	0xe6150130
-#define SMSTPCR1	0xe6150134
-#define SMSTPCR2	0xe6150138
-#define SMSTPCR3	0xe615013c
-#define SMSTPCR4	0xe6150140
+#define FRQCRA		IOMEM(0xe6150000)
+#define FRQCRB		IOMEM(0xe6150004)
+#define VCLKCR1		IOMEM(0xE6150008)
+#define VCLKCR2		IOMEM(0xE615000c)
+#define FRQCRC		IOMEM(0xe61500e0)
+#define FSIACKCR	IOMEM(0xe6150018)
+#define PLLC01CR	IOMEM(0xe6150028)
+
+#define SUBCKCR		IOMEM(0xe6150080)
+#define USBCKCR		IOMEM(0xe615008c)
+
+#define MSTPSR0		IOMEM(0xe6150030)
+#define MSTPSR1		IOMEM(0xe6150038)
+#define MSTPSR2		IOMEM(0xe6150040)
+#define MSTPSR3		IOMEM(0xe6150048)
+#define MSTPSR4		IOMEM(0xe615004c)
+#define FSIBCKCR	IOMEM(0xe6150090)
+#define HDMICKCR	IOMEM(0xe6150094)
+#define SMSTPCR0	IOMEM(0xe6150130)
+#define SMSTPCR1	IOMEM(0xe6150134)
+#define SMSTPCR2	IOMEM(0xe6150138)
+#define SMSTPCR3	IOMEM(0xe615013c)
+#define SMSTPCR4	IOMEM(0xe6150140)
 
 /* Fixed 32 KHz root clock from EXTALR pin */
 static struct clk extalr_clk = {
diff --git a/arch/arm/mach-shmobile/clock-r8a7779.c b/arch/arm/mach-shmobile/clock-r8a7779.c
index 339c62c..3cafb6a 100644
--- a/arch/arm/mach-shmobile/clock-r8a7779.c
+++ b/arch/arm/mach-shmobile/clock-r8a7779.c
@@ -86,11 +86,16 @@ static struct clk div4_clks[DIV4_NR] = {
 				      0x0300, CLK_ENABLE_ON_INIT),
 };
 
-enum { MSTP026, MSTP025, MSTP024, MSTP023, MSTP022, MSTP021,
+enum { MSTP323, MSTP322, MSTP321, MSTP320,
+	MSTP026, MSTP025, MSTP024, MSTP023, MSTP022, MSTP021,
 	MSTP016, MSTP015, MSTP014,
 	MSTP_NR };
 
 static struct clk mstp_clks[MSTP_NR] = {
+	[MSTP323] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 23, 0), /* SDHI0 */
+	[MSTP322] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 22, 0), /* SDHI1 */
+	[MSTP321] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 21, 0), /* SDHI2 */
+	[MSTP320] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 20, 0), /* SDHI3 */
 	[MSTP026] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 26, 0), /* SCIF0 */
 	[MSTP025] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 25, 0), /* SCIF1 */
 	[MSTP024] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 24, 0), /* SCIF2 */
@@ -149,6 +154,10 @@ static struct clk_lookup lookups[] = {
 	CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP023]), /* SCIF3 */
 	CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP022]), /* SCIF4 */
 	CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP021]), /* SCIF6 */
+	CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP323]), /* SDHI0 */
+	CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP322]), /* SDHI1 */
+	CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP321]), /* SDHI2 */
+	CLKDEV_DEV_ID("sh_mobile_sdhi.3", &mstp_clks[MSTP320]), /* SDHI3 */
 };
 
 void __init r8a7779_clock_init(void)
diff --git a/arch/arm/mach-shmobile/clock-sh7367.c b/arch/arm/mach-shmobile/clock-sh7367.c
index 162b791..ef0a95e 100644
--- a/arch/arm/mach-shmobile/clock-sh7367.c
+++ b/arch/arm/mach-shmobile/clock-sh7367.c
@@ -24,28 +24,28 @@
 #include <mach/common.h>
 
 /* SH7367 registers */
-#define RTFRQCR    0xe6150000
-#define SYFRQCR    0xe6150004
-#define CMFRQCR    0xe61500E0
-#define VCLKCR1    0xe6150008
-#define VCLKCR2    0xe615000C
-#define VCLKCR3    0xe615001C
-#define SCLKACR    0xe6150010
-#define SCLKBCR    0xe6150014
-#define SUBUSBCKCR 0xe6158080
-#define SPUCKCR    0xe6150084
-#define MSUCKCR    0xe6150088
-#define MVI3CKCR   0xe6150090
-#define VOUCKCR    0xe6150094
-#define MFCK1CR    0xe6150098
-#define MFCK2CR    0xe615009C
-#define PLLC1CR    0xe6150028
-#define PLLC2CR    0xe615002C
-#define RTMSTPCR0  0xe6158030
-#define RTMSTPCR2  0xe6158038
-#define SYMSTPCR0  0xe6158040
-#define SYMSTPCR2  0xe6158048
-#define CMMSTPCR0  0xe615804c
+#define RTFRQCR    IOMEM(0xe6150000)
+#define SYFRQCR    IOMEM(0xe6150004)
+#define CMFRQCR    IOMEM(0xe61500E0)
+#define VCLKCR1    IOMEM(0xe6150008)
+#define VCLKCR2    IOMEM(0xe615000C)
+#define VCLKCR3    IOMEM(0xe615001C)
+#define SCLKACR    IOMEM(0xe6150010)
+#define SCLKBCR    IOMEM(0xe6150014)
+#define SUBUSBCKCR IOMEM(0xe6158080)
+#define SPUCKCR    IOMEM(0xe6150084)
+#define MSUCKCR    IOMEM(0xe6150088)
+#define MVI3CKCR   IOMEM(0xe6150090)
+#define VOUCKCR    IOMEM(0xe6150094)
+#define MFCK1CR    IOMEM(0xe6150098)
+#define MFCK2CR    IOMEM(0xe615009C)
+#define PLLC1CR    IOMEM(0xe6150028)
+#define PLLC2CR    IOMEM(0xe615002C)
+#define RTMSTPCR0  IOMEM(0xe6158030)
+#define RTMSTPCR2  IOMEM(0xe6158038)
+#define SYMSTPCR0  IOMEM(0xe6158040)
+#define SYMSTPCR2  IOMEM(0xe6158048)
+#define CMMSTPCR0  IOMEM(0xe615804c)
 
 /* Fixed 32 KHz root clock from EXTALR pin */
 static struct clk r_clk = {
diff --git a/arch/arm/mach-shmobile/clock-sh7372.c b/arch/arm/mach-shmobile/clock-sh7372.c
index 5a2894b..430a90f 100644
--- a/arch/arm/mach-shmobile/clock-sh7372.c
+++ b/arch/arm/mach-shmobile/clock-sh7372.c
@@ -24,36 +24,36 @@
 #include <mach/common.h>
 
 /* SH7372 registers */
-#define FRQCRA		0xe6150000
-#define FRQCRB		0xe6150004
-#define FRQCRC		0xe61500e0
-#define FRQCRD		0xe61500e4
-#define VCLKCR1		0xe6150008
-#define VCLKCR2		0xe615000c
-#define VCLKCR3		0xe615001c
-#define FMSICKCR	0xe6150010
-#define FMSOCKCR	0xe6150014
-#define FSIACKCR	0xe6150018
-#define FSIBCKCR	0xe6150090
-#define SUBCKCR		0xe6150080
-#define SPUCKCR		0xe6150084
-#define VOUCKCR		0xe6150088
-#define HDMICKCR	0xe6150094
-#define DSITCKCR	0xe6150060
-#define DSI0PCKCR	0xe6150064
-#define DSI1PCKCR	0xe6150098
-#define PLLC01CR	0xe6150028
-#define PLLC2CR		0xe615002c
-#define RMSTPCR0	0xe6150110
-#define RMSTPCR1	0xe6150114
-#define RMSTPCR2	0xe6150118
-#define RMSTPCR3	0xe615011c
-#define RMSTPCR4	0xe6150120
-#define SMSTPCR0	0xe6150130
-#define SMSTPCR1	0xe6150134
-#define SMSTPCR2	0xe6150138
-#define SMSTPCR3	0xe615013c
-#define SMSTPCR4	0xe6150140
+#define FRQCRA		IOMEM(0xe6150000)
+#define FRQCRB		IOMEM(0xe6150004)
+#define FRQCRC		IOMEM(0xe61500e0)
+#define FRQCRD		IOMEM(0xe61500e4)
+#define VCLKCR1		IOMEM(0xe6150008)
+#define VCLKCR2		IOMEM(0xe615000c)
+#define VCLKCR3		IOMEM(0xe615001c)
+#define FMSICKCR	IOMEM(0xe6150010)
+#define FMSOCKCR	IOMEM(0xe6150014)
+#define FSIACKCR	IOMEM(0xe6150018)
+#define FSIBCKCR	IOMEM(0xe6150090)
+#define SUBCKCR		IOMEM(0xe6150080)
+#define SPUCKCR		IOMEM(0xe6150084)
+#define VOUCKCR		IOMEM(0xe6150088)
+#define HDMICKCR	IOMEM(0xe6150094)
+#define DSITCKCR	IOMEM(0xe6150060)
+#define DSI0PCKCR	IOMEM(0xe6150064)
+#define DSI1PCKCR	IOMEM(0xe6150098)
+#define PLLC01CR	IOMEM(0xe6150028)
+#define PLLC2CR		IOMEM(0xe615002c)
+#define RMSTPCR0	IOMEM(0xe6150110)
+#define RMSTPCR1	IOMEM(0xe6150114)
+#define RMSTPCR2	IOMEM(0xe6150118)
+#define RMSTPCR3	IOMEM(0xe615011c)
+#define RMSTPCR4	IOMEM(0xe6150120)
+#define SMSTPCR0	IOMEM(0xe6150130)
+#define SMSTPCR1	IOMEM(0xe6150134)
+#define SMSTPCR2	IOMEM(0xe6150138)
+#define SMSTPCR3	IOMEM(0xe615013c)
+#define SMSTPCR4	IOMEM(0xe6150140)
 
 #define FSIDIVA		0xFE1F8000
 #define FSIDIVB		0xFE1F8008
diff --git a/arch/arm/mach-shmobile/clock-sh7377.c b/arch/arm/mach-shmobile/clock-sh7377.c
index 85f2a3e..b8480d1 100644
--- a/arch/arm/mach-shmobile/clock-sh7377.c
+++ b/arch/arm/mach-shmobile/clock-sh7377.c
@@ -24,31 +24,31 @@
 #include <mach/common.h>
 
 /* SH7377 registers */
-#define RTFRQCR    0xe6150000
-#define SYFRQCR    0xe6150004
-#define CMFRQCR    0xe61500E0
-#define VCLKCR1    0xe6150008
-#define VCLKCR2    0xe615000C
-#define VCLKCR3    0xe615001C
-#define FMSICKCR   0xe6150010
-#define FMSOCKCR   0xe6150014
-#define FSICKCR    0xe6150018
-#define PLLC1CR    0xe6150028
-#define PLLC2CR    0xe615002C
-#define SUBUSBCKCR 0xe6150080
-#define SPUCKCR    0xe6150084
-#define MSUCKCR    0xe6150088
-#define MVI3CKCR   0xe6150090
-#define HDMICKCR   0xe6150094
-#define MFCK1CR    0xe6150098
-#define MFCK2CR    0xe615009C
-#define DSITCKCR   0xe6150060
-#define DSIPCKCR   0xe6150064
-#define SMSTPCR0   0xe6150130
-#define SMSTPCR1   0xe6150134
-#define SMSTPCR2   0xe6150138
-#define SMSTPCR3   0xe615013C
-#define SMSTPCR4   0xe6150140
+#define RTFRQCR    IOMEM(0xe6150000)
+#define SYFRQCR    IOMEM(0xe6150004)
+#define CMFRQCR    IOMEM(0xe61500E0)
+#define VCLKCR1    IOMEM(0xe6150008)
+#define VCLKCR2    IOMEM(0xe615000C)
+#define VCLKCR3    IOMEM(0xe615001C)
+#define FMSICKCR   IOMEM(0xe6150010)
+#define FMSOCKCR   IOMEM(0xe6150014)
+#define FSICKCR    IOMEM(0xe6150018)
+#define PLLC1CR    IOMEM(0xe6150028)
+#define PLLC2CR    IOMEM(0xe615002C)
+#define SUBUSBCKCR IOMEM(0xe6150080)
+#define SPUCKCR    IOMEM(0xe6150084)
+#define MSUCKCR    IOMEM(0xe6150088)
+#define MVI3CKCR   IOMEM(0xe6150090)
+#define HDMICKCR   IOMEM(0xe6150094)
+#define MFCK1CR    IOMEM(0xe6150098)
+#define MFCK2CR    IOMEM(0xe615009C)
+#define DSITCKCR   IOMEM(0xe6150060)
+#define DSIPCKCR   IOMEM(0xe6150064)
+#define SMSTPCR0   IOMEM(0xe6150130)
+#define SMSTPCR1   IOMEM(0xe6150134)
+#define SMSTPCR2   IOMEM(0xe6150138)
+#define SMSTPCR3   IOMEM(0xe615013C)
+#define SMSTPCR4   IOMEM(0xe6150140)
 
 /* Fixed 32 KHz root clock from EXTALR pin */
 static struct clk r_clk = {
diff --git a/arch/arm/mach-shmobile/clock-sh73a0.c b/arch/arm/mach-shmobile/clock-sh73a0.c
index 7f8da18..516ff7f 100644
--- a/arch/arm/mach-shmobile/clock-sh73a0.c
+++ b/arch/arm/mach-shmobile/clock-sh73a0.c
@@ -23,43 +23,43 @@
 #include <linux/clkdev.h>
 #include <mach/common.h>
 
-#define FRQCRA		0xe6150000
-#define FRQCRB		0xe6150004
-#define FRQCRD		0xe61500e4
-#define VCLKCR1		0xe6150008
-#define VCLKCR2		0xe615000C
-#define VCLKCR3		0xe615001C
-#define ZBCKCR		0xe6150010
-#define FLCKCR		0xe6150014
-#define SD0CKCR		0xe6150074
-#define SD1CKCR		0xe6150078
-#define SD2CKCR		0xe615007C
-#define FSIACKCR	0xe6150018
-#define FSIBCKCR	0xe6150090
-#define SUBCKCR		0xe6150080
-#define SPUACKCR	0xe6150084
-#define SPUVCKCR	0xe6150094
-#define MSUCKCR		0xe6150088
-#define HSICKCR		0xe615008C
-#define MFCK1CR		0xe6150098
-#define MFCK2CR		0xe615009C
-#define DSITCKCR	0xe6150060
-#define DSI0PCKCR	0xe6150064
-#define DSI1PCKCR	0xe6150068
+#define FRQCRA		IOMEM(0xe6150000)
+#define FRQCRB		IOMEM(0xe6150004)
+#define FRQCRD		IOMEM(0xe61500e4)
+#define VCLKCR1		IOMEM(0xe6150008)
+#define VCLKCR2		IOMEM(0xe615000C)
+#define VCLKCR3		IOMEM(0xe615001C)
+#define ZBCKCR		IOMEM(0xe6150010)
+#define FLCKCR		IOMEM(0xe6150014)
+#define SD0CKCR		IOMEM(0xe6150074)
+#define SD1CKCR		IOMEM(0xe6150078)
+#define SD2CKCR		IOMEM(0xe615007C)
+#define FSIACKCR	IOMEM(0xe6150018)
+#define FSIBCKCR	IOMEM(0xe6150090)
+#define SUBCKCR		IOMEM(0xe6150080)
+#define SPUACKCR	IOMEM(0xe6150084)
+#define SPUVCKCR	IOMEM(0xe6150094)
+#define MSUCKCR		IOMEM(0xe6150088)
+#define HSICKCR		IOMEM(0xe615008C)
+#define MFCK1CR		IOMEM(0xe6150098)
+#define MFCK2CR		IOMEM(0xe615009C)
+#define DSITCKCR	IOMEM(0xe6150060)
+#define DSI0PCKCR	IOMEM(0xe6150064)
+#define DSI1PCKCR	IOMEM(0xe6150068)
 #define DSI0PHYCR	0xe615006C
 #define DSI1PHYCR	0xe6150070
-#define PLLECR		0xe61500d0
-#define PLL0CR		0xe61500d8
-#define PLL1CR		0xe6150028
-#define PLL2CR		0xe615002c
-#define PLL3CR		0xe61500dc
-#define SMSTPCR0	0xe6150130
-#define SMSTPCR1	0xe6150134
-#define SMSTPCR2	0xe6150138
-#define SMSTPCR3	0xe615013c
-#define SMSTPCR4	0xe6150140
-#define SMSTPCR5	0xe6150144
-#define CKSCR		0xe61500c0
+#define PLLECR		IOMEM(0xe61500d0)
+#define PLL0CR		IOMEM(0xe61500d8)
+#define PLL1CR		IOMEM(0xe6150028)
+#define PLL2CR		IOMEM(0xe615002c)
+#define PLL3CR		IOMEM(0xe61500dc)
+#define SMSTPCR0	IOMEM(0xe6150130)
+#define SMSTPCR1	IOMEM(0xe6150134)
+#define SMSTPCR2	IOMEM(0xe6150138)
+#define SMSTPCR3	IOMEM(0xe615013c)
+#define SMSTPCR4	IOMEM(0xe6150140)
+#define SMSTPCR5	IOMEM(0xe6150144)
+#define CKSCR		IOMEM(0xe61500c0)
 
 /* Fixed 32 KHz root clock from EXTALR pin */
 static struct clk r_clk = {
diff --git a/arch/arm/mach-shmobile/common.c b/arch/arm/mach-shmobile/common.c
deleted file mode 100644
index 608aba9..0000000
--- a/arch/arm/mach-shmobile/common.c
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- *
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <mach/common.h>
-
-void __init shmobile_init_late(void)
-{
-	shmobile_suspend_init();
-	shmobile_cpuidle_init();
-}
diff --git a/arch/arm/mach-shmobile/cpuidle.c b/arch/arm/mach-shmobile/cpuidle.c
index 7b541e9..9e05026 100644
--- a/arch/arm/mach-shmobile/cpuidle.c
+++ b/arch/arm/mach-shmobile/cpuidle.c
@@ -16,51 +16,38 @@
 #include <asm/cpuidle.h>
 #include <asm/io.h>
 
-static void shmobile_enter_wfi(void)
+int shmobile_enter_wfi(struct cpuidle_device *dev, struct cpuidle_driver *drv,
+		       int index)
 {
 	cpu_do_idle();
-}
-
-void (*shmobile_cpuidle_modes[CPUIDLE_STATE_MAX])(void) = {
-	shmobile_enter_wfi, /* regular sleep mode */
-};
-
-static int shmobile_cpuidle_enter(struct cpuidle_device *dev,
-				  struct cpuidle_driver *drv,
-				  int index)
-{
-	shmobile_cpuidle_modes[index]();
-
-	return index;
+	return 0;
 }
 
 static struct cpuidle_device shmobile_cpuidle_dev;
-static struct cpuidle_driver shmobile_cpuidle_driver = {
+static struct cpuidle_driver shmobile_cpuidle_default_driver = {
 	.name			= "shmobile_cpuidle",
 	.owner			= THIS_MODULE,
 	.en_core_tk_irqen	= 1,
 	.states[0]		= ARM_CPUIDLE_WFI_STATE,
+	.states[0].enter	= shmobile_enter_wfi,
 	.safe_state_index	= 0, /* C1 */
 	.state_count		= 1,
 };
 
-void (*shmobile_cpuidle_setup)(struct cpuidle_driver *drv);
+static struct cpuidle_driver *cpuidle_drv = &shmobile_cpuidle_default_driver;
+
+void shmobile_cpuidle_set_driver(struct cpuidle_driver *drv)
+{
+	cpuidle_drv = drv;
+}
 
 int shmobile_cpuidle_init(void)
 {
 	struct cpuidle_device *dev = &shmobile_cpuidle_dev;
-	struct cpuidle_driver *drv = &shmobile_cpuidle_driver;
-	int i;
-
-	for (i = 0; i < CPUIDLE_STATE_MAX; i++)
-		drv->states[i].enter = shmobile_cpuidle_enter;
-
-	if (shmobile_cpuidle_setup)
-		shmobile_cpuidle_setup(drv);
 
-	cpuidle_register_driver(drv);
+	cpuidle_register_driver(cpuidle_drv);
 
-	dev->state_count = drv->state_count;
+	dev->state_count = cpuidle_drv->state_count;
 	cpuidle_register_device(dev);
 
 	return 0;
diff --git a/arch/arm/mach-shmobile/hotplug.c b/arch/arm/mach-shmobile/hotplug.c
index 828d22f..b09a0bd 100644
--- a/arch/arm/mach-shmobile/hotplug.c
+++ b/arch/arm/mach-shmobile/hotplug.c
@@ -14,30 +14,16 @@
 #include <linux/smp.h>
 #include <linux/cpumask.h>
 #include <linux/delay.h>
+#include <linux/of.h>
 #include <mach/common.h>
+#include <mach/r8a7779.h>
+#include <mach/emev2.h>
 #include <asm/cacheflush.h>
+#include <asm/mach-types.h>
 
 static cpumask_t dead_cpus;
 
-int platform_cpu_kill(unsigned int cpu)
-{
-	int k;
-
-	/* this function is running on another CPU than the offline target,
-	 * here we need wait for shutdown code in platform_cpu_die() to
-	 * finish before asking SoC-specific code to power off the CPU core.
-	 */
-	for (k = 0; k < 1000; k++) {
-		if (cpumask_test_cpu(cpu, &dead_cpus))
-			return shmobile_platform_cpu_kill(cpu);
-
-		mdelay(1);
-	}
-
-	return 0;
-}
-
-void platform_cpu_die(unsigned int cpu)
+void shmobile_cpu_die(unsigned int cpu)
 {
 	/* hardware shutdown code running on the CPU that is being offlined */
 	flush_cache_all();
@@ -60,7 +46,7 @@ void platform_cpu_die(unsigned int cpu)
 	}
 }
 
-int platform_cpu_disable(unsigned int cpu)
+int shmobile_cpu_disable(unsigned int cpu)
 {
 	cpumask_clear_cpu(cpu, &dead_cpus);
 	/*
@@ -69,3 +55,8 @@ int platform_cpu_disable(unsigned int cpu)
 	 */
 	return cpu == 0 ? -EPERM : 0;
 }
+
+int shmobile_cpu_is_dead(unsigned int cpu)
+{
+	return cpumask_test_cpu(cpu, &dead_cpus);
+}
diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h
index 45e61da..e675ef9 100644
--- a/arch/arm/mach-shmobile/include/mach/common.h
+++ b/arch/arm/mach-shmobile/include/mach/common.h
@@ -4,18 +4,19 @@
 extern void shmobile_earlytimer_init(void);
 extern struct sys_timer shmobile_timer;
 extern void shmobile_setup_delay(unsigned int max_cpu_core_mhz,
-				 unsigned int mult, unsigned int div);
+			 unsigned int mult, unsigned int div);
 struct twd_local_timer;
 extern void shmobile_setup_console(void);
 extern void shmobile_secondary_vector(void);
-extern int shmobile_platform_cpu_kill(unsigned int cpu);
 struct clk;
 extern int shmobile_clk_init(void);
 extern void shmobile_handle_irq_intc(struct pt_regs *);
 extern struct platform_suspend_ops shmobile_suspend_ops;
 struct cpuidle_driver;
-extern void (*shmobile_cpuidle_modes[])(void);
-extern void (*shmobile_cpuidle_setup)(struct cpuidle_driver *drv);
+struct cpuidle_device;
+extern int shmobile_enter_wfi(struct cpuidle_device *dev,
+			      struct cpuidle_driver *drv, int index);
+extern void shmobile_cpuidle_set_driver(struct cpuidle_driver *drv);
 
 extern void sh7367_init_irq(void);
 extern void sh7367_map_io(void);
@@ -58,11 +59,6 @@ extern struct clk sh73a0_extal2_clk;
 extern struct clk sh73a0_extcki_clk;
 extern struct clk sh73a0_extalr_clk;
 
-extern unsigned int sh73a0_get_core_count(void);
-extern void sh73a0_secondary_init(unsigned int cpu);
-extern int sh73a0_boot_secondary(unsigned int cpu);
-extern void sh73a0_smp_prepare_cpus(void);
-
 extern void r8a7740_init_irq(void);
 extern void r8a7740_map_io(void);
 extern void r8a7740_add_early_devices(void);
@@ -79,15 +75,8 @@ extern void r8a7779_pinmux_init(void);
 extern void r8a7779_pm_init(void);
 extern void r8a7740_meram_workaround(void);
 
-extern unsigned int r8a7779_get_core_count(void);
-extern int r8a7779_platform_cpu_kill(unsigned int cpu);
-extern void r8a7779_secondary_init(unsigned int cpu);
-extern int r8a7779_boot_secondary(unsigned int cpu);
-extern void r8a7779_smp_prepare_cpus(void);
 extern void r8a7779_register_twd(void);
 
-extern void shmobile_init_late(void);
-
 #ifdef CONFIG_SUSPEND
 int shmobile_suspend_init(void);
 #else
@@ -100,4 +89,21 @@ int shmobile_cpuidle_init(void);
 static inline int shmobile_cpuidle_init(void) { return 0; }
 #endif
 
+static inline void shmobile_init_late(void)
+{
+	shmobile_suspend_init();
+	shmobile_cpuidle_init();
+}
+
+extern void shmobile_cpu_die(unsigned int cpu);
+extern int shmobile_cpu_disable(unsigned int cpu);
+
+#ifdef CONFIG_HOTPLUG_CPU
+extern int shmobile_cpu_is_dead(unsigned int cpu);
+#else
+static inline int shmobile_cpu_is_dead(unsigned int cpu) { return 1; }
+#endif
+
+extern void shmobile_smp_init_cpus(unsigned int ncores);
+
 #endif /* __ARCH_MACH_COMMON_H */
diff --git a/arch/arm/mach-shmobile/include/mach/emev2.h b/arch/arm/mach-shmobile/include/mach/emev2.h
index e6b0c1b..ac37517 100644
--- a/arch/arm/mach-shmobile/include/mach/emev2.h
+++ b/arch/arm/mach-shmobile/include/mach/emev2.h
@@ -7,13 +7,10 @@ extern void emev2_add_early_devices(void);
 extern void emev2_add_standard_devices(void);
 extern void emev2_clock_init(void);
 extern void emev2_set_boot_vector(unsigned long value);
-extern unsigned int emev2_get_core_count(void);
-extern int emev2_platform_cpu_kill(unsigned int cpu);
-extern void emev2_secondary_init(unsigned int cpu);
-extern int emev2_boot_secondary(unsigned int cpu);
-extern void emev2_smp_prepare_cpus(void);
 
 #define EMEV2_GPIO_BASE 200
 #define EMEV2_GPIO_IRQ(n) (EMEV2_GPIO_BASE + (n))
 
+extern struct smp_operations emev2_smp_ops;
+
 #endif /* __ASM_EMEV2_H__ */
diff --git a/arch/arm/mach-shmobile/include/mach/gpio.h b/arch/arm/mach-shmobile/include/mach/gpio.h
deleted file mode 100644
index 844507d..0000000
--- a/arch/arm/mach-shmobile/include/mach/gpio.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Generic GPIO API and pinmux table support
- *
- * Copyright (c) 2008  Magnus Damm
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-#ifndef __ASM_ARCH_GPIO_H
-#define __ASM_ARCH_GPIO_H
-
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/sh_pfc.h>
-#include <linux/io.h>
-
-#ifdef CONFIG_GPIOLIB
-
-static inline int irq_to_gpio(unsigned int irq)
-{
-	return -ENOSYS;
-}
-
-#else
-
-#define __ARM_GPIOLIB_COMPLEX
-
-#endif /* CONFIG_GPIOLIB */
-
-/*
- * FIXME !!
- *
- * current gpio frame work doesn't have
- * the method to control only pull up/down/free.
- * this function should be replaced by correct gpio function
- */
-static inline void __init gpio_direction_none(u32 addr)
-{
-	__raw_writeb(0x00, addr);
-}
-
-static inline void __init gpio_request_pullup(u32 addr)
-{
-	u8 data = __raw_readb(addr);
-
-	data &= 0x0F;
-	data |= 0xC0;
-	__raw_writeb(data, addr);
-}
-
-static inline void __init gpio_request_pulldown(u32 addr)
-{
-	u8 data = __raw_readb(addr);
-
-	data &= 0x0F;
-	data |= 0xA0;
-
-	__raw_writeb(data, addr);
-}
-
-#endif /* __ASM_ARCH_GPIO_H */
diff --git a/arch/arm/mach-shmobile/include/mach/pm-rmobile.h b/arch/arm/mach-shmobile/include/mach/pm-rmobile.h
index 5a40284..690553a 100644
--- a/arch/arm/mach-shmobile/include/mach/pm-rmobile.h
+++ b/arch/arm/mach-shmobile/include/mach/pm-rmobile.h
@@ -12,6 +12,8 @@
 
 #include <linux/pm_domain.h>
 
+#define DEFAULT_DEV_LATENCY_NS	250000
+
 struct platform_device;
 
 struct rmobile_pm_domain {
@@ -29,16 +31,33 @@ struct rmobile_pm_domain *to_rmobile_pd(struct generic_pm_domain *d)
 	return container_of(d, struct rmobile_pm_domain, genpd);
 }
 
+struct pm_domain_device {
+	const char *domain_name;
+	struct platform_device *pdev;
+};
+
 #ifdef CONFIG_PM
-extern void rmobile_init_pm_domain(struct rmobile_pm_domain *rmobile_pd);
-extern void rmobile_add_device_to_domain(struct rmobile_pm_domain *rmobile_pd,
-					struct platform_device *pdev);
-extern void rmobile_pm_add_subdomain(struct rmobile_pm_domain *rmobile_pd,
-				    struct rmobile_pm_domain *rmobile_sd);
+extern void rmobile_init_domains(struct rmobile_pm_domain domains[], int num);
+extern void rmobile_add_device_to_domain_td(const char *domain_name,
+					    struct platform_device *pdev,
+					    struct gpd_timing_data *td);
+
+static inline void rmobile_add_device_to_domain(const char *domain_name,
+						struct platform_device *pdev)
+{
+	rmobile_add_device_to_domain_td(domain_name, pdev, NULL);
+}
+
+extern void rmobile_add_devices_to_domains(struct pm_domain_device data[],
+					   int size);
 #else
-#define rmobile_init_pm_domain(pd) do { } while (0)
-#define rmobile_add_device_to_domain(pd, pdev) do { } while (0)
-#define rmobile_pm_add_subdomain(pd, sd) do { } while (0)
+
+#define rmobile_init_domains(domains, num) do { } while (0)
+#define rmobile_add_device_to_domain_td(name, pdev, td) do { } while (0)
+#define rmobile_add_device_to_domain(name, pdev) do { } while (0)
+
+static inline void rmobile_add_devices_to_domains(struct pm_domain_device d[],
+						  int size) {}
 #endif /* CONFIG_PM */
 
 #endif /* PM_RMOBILE_H */
diff --git a/arch/arm/mach-shmobile/include/mach/r8a7740.h b/arch/arm/mach-shmobile/include/mach/r8a7740.h
index 7143147..59d252f 100644
--- a/arch/arm/mach-shmobile/include/mach/r8a7740.h
+++ b/arch/arm/mach-shmobile/include/mach/r8a7740.h
@@ -607,9 +607,9 @@ enum {
 };
 
 #ifdef CONFIG_PM
-extern struct rmobile_pm_domain r8a7740_pd_a4s;
-extern struct rmobile_pm_domain r8a7740_pd_a3sp;
-extern struct rmobile_pm_domain r8a7740_pd_a4lc;
+extern void __init r8a7740_init_pm_domains(void);
+#else
+static inline void r8a7740_init_pm_domains(void) {}
 #endif /* CONFIG_PM */
 
 #endif /* __ASM_R8A7740_H__ */
diff --git a/arch/arm/mach-shmobile/include/mach/r8a7779.h b/arch/arm/mach-shmobile/include/mach/r8a7779.h
index b07ad31..499f52d 100644
--- a/arch/arm/mach-shmobile/include/mach/r8a7779.h
+++ b/arch/arm/mach-shmobile/include/mach/r8a7779.h
@@ -347,17 +347,11 @@ extern int r8a7779_sysc_power_down(struct r8a7779_pm_ch *r8a7779_ch);
 extern int r8a7779_sysc_power_up(struct r8a7779_pm_ch *r8a7779_ch);
 
 #ifdef CONFIG_PM
-extern struct r8a7779_pm_domain r8a7779_sh4a;
-extern struct r8a7779_pm_domain r8a7779_sgx;
-extern struct r8a7779_pm_domain r8a7779_vdp1;
-extern struct r8a7779_pm_domain r8a7779_impx3;
-
-extern void r8a7779_init_pm_domain(struct r8a7779_pm_domain *r8a7779_pd);
-extern void r8a7779_add_device_to_domain(struct r8a7779_pm_domain *r8a7779_pd,
-					struct platform_device *pdev);
+extern void __init r8a7779_init_pm_domains(void);
 #else
-#define r8a7779_init_pm_domain(pd) do { } while (0)
-#define r8a7779_add_device_to_domain(pd, pdev) do { } while (0)
+static inline void r8a7779_init_pm_domains(void) {}
 #endif /* CONFIG_PM */
 
+extern struct smp_operations r8a7779_smp_ops;
+
 #endif /* __ASM_R8A7779_H__ */
diff --git a/arch/arm/mach-shmobile/include/mach/sh7372.h b/arch/arm/mach-shmobile/include/mach/sh7372.h
index b59048e..d65fbbe 100644
--- a/arch/arm/mach-shmobile/include/mach/sh7372.h
+++ b/arch/arm/mach-shmobile/include/mach/sh7372.h
@@ -452,6 +452,10 @@ enum {
 	SHDMA_SLAVE_SCIF5_RX,
 	SHDMA_SLAVE_SCIF6_TX,
 	SHDMA_SLAVE_SCIF6_RX,
+	SHDMA_SLAVE_FLCTL0_TX,
+	SHDMA_SLAVE_FLCTL0_RX,
+	SHDMA_SLAVE_FLCTL1_TX,
+	SHDMA_SLAVE_FLCTL1_RX,
 	SHDMA_SLAVE_SDHI0_RX,
 	SHDMA_SLAVE_SDHI0_TX,
 	SHDMA_SLAVE_SDHI1_RX,
@@ -478,21 +482,17 @@ extern struct clk sh7372_fsibck_clk;
 extern struct clk sh7372_fsidiva_clk;
 extern struct clk sh7372_fsidivb_clk;
 
-#ifdef CONFIG_PM
-extern struct rmobile_pm_domain sh7372_pd_a4lc;
-extern struct rmobile_pm_domain sh7372_pd_a4mp;
-extern struct rmobile_pm_domain sh7372_pd_d4;
-extern struct rmobile_pm_domain sh7372_pd_a4r;
-extern struct rmobile_pm_domain sh7372_pd_a3rv;
-extern struct rmobile_pm_domain sh7372_pd_a3ri;
-extern struct rmobile_pm_domain sh7372_pd_a4s;
-extern struct rmobile_pm_domain sh7372_pd_a3sp;
-extern struct rmobile_pm_domain sh7372_pd_a3sg;
-#endif /* CONFIG_PM */
-
 extern void sh7372_intcs_suspend(void);
 extern void sh7372_intcs_resume(void);
 extern void sh7372_intca_suspend(void);
 extern void sh7372_intca_resume(void);
 
+#ifdef CONFIG_PM
+extern void __init sh7372_init_pm_domains(void);
+#else
+static inline void sh7372_init_pm_domains(void) {}
+#endif
+
+extern void __init sh7372_pm_init_late(void);
+
 #endif /* __ASM_SH7372_H__ */
diff --git a/arch/arm/mach-shmobile/include/mach/sh73a0.h b/arch/arm/mach-shmobile/include/mach/sh73a0.h
index fe950f2..606d31d 100644
--- a/arch/arm/mach-shmobile/include/mach/sh73a0.h
+++ b/arch/arm/mach-shmobile/include/mach/sh73a0.h
@@ -557,4 +557,6 @@ enum {
 #define SH73A0_PINT0_IRQ(irq) ((irq) + 700)
 #define SH73A0_PINT1_IRQ(irq) ((irq) + 732)
 
+extern struct smp_operations sh73a0_smp_ops;
+
 #endif /* __ASM_SH73A0_H__ */
diff --git a/arch/arm/mach-shmobile/intc-r8a7779.c b/arch/arm/mach-shmobile/intc-r8a7779.c
index f04fad4..ef66f1a 100644
--- a/arch/arm/mach-shmobile/intc-r8a7779.c
+++ b/arch/arm/mach-shmobile/intc-r8a7779.c
@@ -29,14 +29,14 @@
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
-#define INT2SMSKCR0 0xfe7822a0
-#define INT2SMSKCR1 0xfe7822a4
-#define INT2SMSKCR2 0xfe7822a8
-#define INT2SMSKCR3 0xfe7822ac
-#define INT2SMSKCR4 0xfe7822b0
+#define INT2SMSKCR0 IOMEM(0xfe7822a0)
+#define INT2SMSKCR1 IOMEM(0xfe7822a4)
+#define INT2SMSKCR2 IOMEM(0xfe7822a8)
+#define INT2SMSKCR3 IOMEM(0xfe7822ac)
+#define INT2SMSKCR4 IOMEM(0xfe7822b0)
 
-#define INT2NTSR0 0xfe700060
-#define INT2NTSR1 0xfe700064
+#define INT2NTSR0 IOMEM(0xfe700060)
+#define INT2NTSR1 IOMEM(0xfe700064)
 
 static int r8a7779_set_wake(struct irq_data *data, unsigned int on)
 {
diff --git a/arch/arm/mach-shmobile/intc-sh7372.c b/arch/arm/mach-shmobile/intc-sh7372.c
index 2587a22..a91caad 100644
--- a/arch/arm/mach-shmobile/intc-sh7372.c
+++ b/arch/arm/mach-shmobile/intc-sh7372.c
@@ -624,6 +624,9 @@ void sh7372_intcs_resume(void)
 		__raw_writeb(ffd5[k], intcs_ffd5 + k);
 }
 
+#define E694_BASE IOMEM(0xe6940000)
+#define E695_BASE IOMEM(0xe6950000)
+
 static unsigned short e694[0x200];
 static unsigned short e695[0x200];
 
@@ -632,22 +635,22 @@ void sh7372_intca_suspend(void)
 	int k;
 
 	for (k = 0x00; k <= 0x38; k += 4)
-		e694[k] = __raw_readw(0xe6940000 + k);
+		e694[k] = __raw_readw(E694_BASE + k);
 
 	for (k = 0x80; k <= 0xb4; k += 4)
-		e694[k] = __raw_readb(0xe6940000 + k);
+		e694[k] = __raw_readb(E694_BASE + k);
 
 	for (k = 0x180; k <= 0x1b4; k += 4)
-		e694[k] = __raw_readb(0xe6940000 + k);
+		e694[k] = __raw_readb(E694_BASE + k);
 
 	for (k = 0x00; k <= 0x50; k += 4)
-		e695[k] = __raw_readw(0xe6950000 + k);
+		e695[k] = __raw_readw(E695_BASE + k);
 
 	for (k = 0x80; k <= 0xa8; k += 4)
-		e695[k] = __raw_readb(0xe6950000 + k);
+		e695[k] = __raw_readb(E695_BASE + k);
 
 	for (k = 0x180; k <= 0x1a8; k += 4)
-		e695[k] = __raw_readb(0xe6950000 + k);
+		e695[k] = __raw_readb(E695_BASE + k);
 }
 
 void sh7372_intca_resume(void)
@@ -655,20 +658,20 @@ void sh7372_intca_resume(void)
 	int k;
 
 	for (k = 0x00; k <= 0x38; k += 4)
-		__raw_writew(e694[k], 0xe6940000 + k);
+		__raw_writew(e694[k], E694_BASE + k);
 
 	for (k = 0x80; k <= 0xb4; k += 4)
-		__raw_writeb(e694[k], 0xe6940000 + k);
+		__raw_writeb(e694[k], E694_BASE + k);
 
 	for (k = 0x180; k <= 0x1b4; k += 4)
-		__raw_writeb(e694[k], 0xe6940000 + k);
+		__raw_writeb(e694[k], E694_BASE + k);
 
 	for (k = 0x00; k <= 0x50; k += 4)
-		__raw_writew(e695[k], 0xe6950000 + k);
+		__raw_writew(e695[k], E695_BASE + k);
 
 	for (k = 0x80; k <= 0xa8; k += 4)
-		__raw_writeb(e695[k], 0xe6950000 + k);
+		__raw_writeb(e695[k], E695_BASE + k);
 
 	for (k = 0x180; k <= 0x1a8; k += 4)
-		__raw_writeb(e695[k], 0xe6950000 + k);
+		__raw_writeb(e695[k], E695_BASE + k);
 }
diff --git a/arch/arm/mach-shmobile/intc-sh73a0.c b/arch/arm/mach-shmobile/intc-sh73a0.c
index 588555a..f0c5e51 100644
--- a/arch/arm/mach-shmobile/intc-sh73a0.c
+++ b/arch/arm/mach-shmobile/intc-sh73a0.c
@@ -366,10 +366,12 @@ static irqreturn_t sh73a0_irq_pin_demux(int irq, void *dev_id)
 
 static struct irqaction sh73a0_irq_pin_cascade[32];
 
-#define PINTER0 0xe69000a0
-#define PINTER1 0xe69000a4
-#define PINTRR0 0xe69000d0
-#define PINTRR1 0xe69000d4
+#define PINTER0_PHYS 0xe69000a0
+#define PINTER1_PHYS 0xe69000a4
+#define PINTER0_VIRT IOMEM(0xe69000a0)
+#define PINTER1_VIRT IOMEM(0xe69000a4)
+#define PINTRR0 IOMEM(0xe69000d0)
+#define PINTRR1 IOMEM(0xe69000d4)
 
 #define PINT0A_IRQ(n, irq) INTC_IRQ((n), SH73A0_PINT0_IRQ(irq))
 #define PINT0B_IRQ(n, irq) INTC_IRQ((n), SH73A0_PINT0_IRQ(irq + 8))
@@ -377,14 +379,14 @@ static struct irqaction sh73a0_irq_pin_cascade[32];
 #define PINT0D_IRQ(n, irq) INTC_IRQ((n), SH73A0_PINT0_IRQ(irq + 24))
 #define PINT1E_IRQ(n, irq) INTC_IRQ((n), SH73A0_PINT1_IRQ(irq))
 
-INTC_PINT(intc_pint0, PINTER0, 0xe69000b0, "sh73a0-pint0",		\
+INTC_PINT(intc_pint0, PINTER0_PHYS, 0xe69000b0, "sh73a0-pint0",		\
   INTC_PINT_E(A), INTC_PINT_E(B), INTC_PINT_E(C), INTC_PINT_E(D),	\
   INTC_PINT_V(A, PINT0A_IRQ), INTC_PINT_V(B, PINT0B_IRQ),		\
   INTC_PINT_V(C, PINT0C_IRQ), INTC_PINT_V(D, PINT0D_IRQ),		\
   INTC_PINT_E(A), INTC_PINT_E(B), INTC_PINT_E(C), INTC_PINT_E(D),	\
   INTC_PINT_E(A), INTC_PINT_E(B), INTC_PINT_E(C), INTC_PINT_E(D));
 
-INTC_PINT(intc_pint1, PINTER1, 0xe69000c0, "sh73a0-pint1",		\
+INTC_PINT(intc_pint1, PINTER1_PHYS, 0xe69000c0, "sh73a0-pint1",		\
   INTC_PINT_E(E), INTC_PINT_E_EMPTY, INTC_PINT_E_EMPTY, INTC_PINT_E_EMPTY, \
   INTC_PINT_V(E, PINT1E_IRQ), INTC_PINT_V_NONE,				\
   INTC_PINT_V_NONE, INTC_PINT_V_NONE,					\
@@ -394,7 +396,7 @@ INTC_PINT(intc_pint1, PINTER1, 0xe69000c0, "sh73a0-pint1",		\
 static struct irqaction sh73a0_pint0_cascade;
 static struct irqaction sh73a0_pint1_cascade;
 
-static void pint_demux(unsigned long rr, unsigned long er, int base_irq)
+static void pint_demux(void __iomem *rr, void __iomem *er, int base_irq)
 {
 	unsigned long value =  ioread32(rr) & ioread32(er);
 	int k;
@@ -409,13 +411,13 @@ static void pint_demux(unsigned long rr, unsigned long er, int base_irq)
 
 static irqreturn_t sh73a0_pint0_demux(int irq, void *dev_id)
 {
-	pint_demux(PINTRR0, PINTER0, SH73A0_PINT0_IRQ(0));
+	pint_demux(PINTRR0, PINTER0_VIRT, SH73A0_PINT0_IRQ(0));
 	return IRQ_HANDLED;
 }
 
 static irqreturn_t sh73a0_pint1_demux(int irq, void *dev_id)
 {
-	pint_demux(PINTRR1, PINTER1, SH73A0_PINT1_IRQ(0));
+	pint_demux(PINTRR1, PINTER1_VIRT, SH73A0_PINT1_IRQ(0));
 	return IRQ_HANDLED;
 }
 
diff --git a/arch/arm/mach-shmobile/pfc-r8a7740.c b/arch/arm/mach-shmobile/pfc-r8a7740.c
index ce9e7fa..134d1b9 100644
--- a/arch/arm/mach-shmobile/pfc-r8a7740.c
+++ b/arch/arm/mach-shmobile/pfc-r8a7740.c
@@ -20,7 +20,7 @@
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/gpio.h>
+#include <linux/sh_pfc.h>
 #include <mach/r8a7740.h>
 #include <mach/irqs.h>
 
diff --git a/arch/arm/mach-shmobile/pfc-r8a7779.c b/arch/arm/mach-shmobile/pfc-r8a7779.c
index d14c9b0..cbc26ba 100644
--- a/arch/arm/mach-shmobile/pfc-r8a7779.c
+++ b/arch/arm/mach-shmobile/pfc-r8a7779.c
@@ -19,7 +19,7 @@
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/gpio.h>
+#include <linux/sh_pfc.h>
 #include <linux/ioport.h>
 #include <mach/r8a7779.h>
 
diff --git a/arch/arm/mach-shmobile/pfc-sh7367.c b/arch/arm/mach-shmobile/pfc-sh7367.c
index e6e5246..c0c137f 100644
--- a/arch/arm/mach-shmobile/pfc-sh7367.c
+++ b/arch/arm/mach-shmobile/pfc-sh7367.c
@@ -18,7 +18,7 @@
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/gpio.h>
+#include <linux/sh_pfc.h>
 #include <mach/sh7367.h>
 
 #define CPU_ALL_PORT(fn, pfx, sfx)				\
diff --git a/arch/arm/mach-shmobile/pfc-sh7372.c b/arch/arm/mach-shmobile/pfc-sh7372.c
index 336093f..7a1525f 100644
--- a/arch/arm/mach-shmobile/pfc-sh7372.c
+++ b/arch/arm/mach-shmobile/pfc-sh7372.c
@@ -22,7 +22,7 @@
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/gpio.h>
+#include <linux/sh_pfc.h>
 #include <mach/irqs.h>
 #include <mach/sh7372.h>
 
diff --git a/arch/arm/mach-shmobile/pfc-sh7377.c b/arch/arm/mach-shmobile/pfc-sh7377.c
index 2f10511..f3117f6 100644
--- a/arch/arm/mach-shmobile/pfc-sh7377.c
+++ b/arch/arm/mach-shmobile/pfc-sh7377.c
@@ -19,7 +19,7 @@
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/gpio.h>
+#include <linux/sh_pfc.h>
 #include <mach/sh7377.h>
 
 #define CPU_ALL_PORT(fn, pfx, sfx)				\
diff --git a/arch/arm/mach-shmobile/pfc-sh73a0.c b/arch/arm/mach-shmobile/pfc-sh73a0.c
index 4a547b8..b442f9d 100644
--- a/arch/arm/mach-shmobile/pfc-sh73a0.c
+++ b/arch/arm/mach-shmobile/pfc-sh73a0.c
@@ -20,7 +20,7 @@
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/gpio.h>
+#include <linux/sh_pfc.h>
 #include <mach/sh73a0.h>
 #include <mach/irqs.h>
 
diff --git a/arch/arm/mach-shmobile/platsmp.c b/arch/arm/mach-shmobile/platsmp.c
index fde0d23..ed8d235 100644
--- a/arch/arm/mach-shmobile/platsmp.c
+++ b/arch/arm/mach-shmobile/platsmp.c
@@ -11,100 +11,11 @@
  * published by the Free Software Foundation.
  */
 #include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/delay.h>
-#include <linux/device.h>
 #include <linux/smp.h>
-#include <linux/io.h>
-#include <linux/of.h>
 #include <asm/hardware/gic.h>
-#include <asm/mach-types.h>
-#include <mach/common.h>
-#include <mach/emev2.h>
 
-#ifdef CONFIG_ARCH_SH73A0
-#define is_sh73a0() (machine_is_ag5evm() || machine_is_kota2() || \
-			of_machine_is_compatible("renesas,sh73a0"))
-#else
-#define is_sh73a0() (0)
-#endif
-
-#define is_r8a7779() machine_is_marzen()
-
-#ifdef CONFIG_ARCH_EMEV2
-#define is_emev2() of_machine_is_compatible("renesas,emev2")
-#else
-#define is_emev2() (0)
-#endif
-
-static unsigned int __init shmobile_smp_get_core_count(void)
-{
-	if (is_sh73a0())
-		return sh73a0_get_core_count();
-
-	if (is_r8a7779())
-		return r8a7779_get_core_count();
-
-	if (is_emev2())
-		return emev2_get_core_count();
-
-	return 1;
-}
-
-static void __init shmobile_smp_prepare_cpus(void)
-{
-	if (is_sh73a0())
-		sh73a0_smp_prepare_cpus();
-
-	if (is_r8a7779())
-		r8a7779_smp_prepare_cpus();
-
-	if (is_emev2())
-		emev2_smp_prepare_cpus();
-}
-
-int shmobile_platform_cpu_kill(unsigned int cpu)
-{
-	if (is_r8a7779())
-		return r8a7779_platform_cpu_kill(cpu);
-
-	if (is_emev2())
-		return emev2_platform_cpu_kill(cpu);
-
-	return 1;
-}
-
-void __cpuinit platform_secondary_init(unsigned int cpu)
+void __init shmobile_smp_init_cpus(unsigned int ncores)
 {
-	trace_hardirqs_off();
-
-	if (is_sh73a0())
-		sh73a0_secondary_init(cpu);
-
-	if (is_r8a7779())
-		r8a7779_secondary_init(cpu);
-
-	if (is_emev2())
-		emev2_secondary_init(cpu);
-}
-
-int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
-{
-	if (is_sh73a0())
-		return sh73a0_boot_secondary(cpu);
-
-	if (is_r8a7779())
-		return r8a7779_boot_secondary(cpu);
-
-	if (is_emev2())
-		return emev2_boot_secondary(cpu);
-
-	return -ENOSYS;
-}
-
-void __init smp_init_cpus(void)
-{
-	unsigned int ncores = shmobile_smp_get_core_count();
 	unsigned int i;
 
 	if (ncores > nr_cpu_ids) {
@@ -118,8 +29,3 @@ void __init smp_init_cpus(void)
 
 	set_smp_cross_call(gic_raise_softirq);
 }
-
-void __init platform_smp_prepare_cpus(unsigned int max_cpus)
-{
-	shmobile_smp_prepare_cpus();
-}
diff --git a/arch/arm/mach-shmobile/pm-r8a7740.c b/arch/arm/mach-shmobile/pm-r8a7740.c
index 893504d..21e5316d 100644
--- a/arch/arm/mach-shmobile/pm-r8a7740.c
+++ b/arch/arm/mach-shmobile/pm-r8a7740.c
@@ -21,14 +21,6 @@ static int r8a7740_pd_a4s_suspend(void)
 	return -EBUSY;
 }
 
-struct rmobile_pm_domain r8a7740_pd_a4s = {
-	.genpd.name	= "A4S",
-	.bit_shift	= 10,
-	.gov		= &pm_domain_always_on_gov,
-	.no_debug	= true,
-	.suspend	= r8a7740_pd_a4s_suspend,
-};
-
 static int r8a7740_pd_a3sp_suspend(void)
 {
 	/*
@@ -38,17 +30,31 @@ static int r8a7740_pd_a3sp_suspend(void)
 	return console_suspend_enabled ? 0 : -EBUSY;
 }
 
-struct rmobile_pm_domain r8a7740_pd_a3sp = {
-	.genpd.name	= "A3SP",
-	.bit_shift	= 11,
-	.gov		= &pm_domain_always_on_gov,
-	.no_debug	= true,
-	.suspend	= r8a7740_pd_a3sp_suspend,
+static struct rmobile_pm_domain r8a7740_pm_domains[] = {
+	{
+		.genpd.name	= "A4S",
+		.bit_shift	= 10,
+		.gov		= &pm_domain_always_on_gov,
+		.no_debug	= true,
+		.suspend	= r8a7740_pd_a4s_suspend,
+	},
+	{
+		.genpd.name	= "A3SP",
+		.bit_shift	= 11,
+		.gov		= &pm_domain_always_on_gov,
+		.no_debug	= true,
+		.suspend	= r8a7740_pd_a3sp_suspend,
+	},
+	{
+		.genpd.name	= "A4LC",
+		.bit_shift	= 1,
+	},
 };
 
-struct rmobile_pm_domain r8a7740_pd_a4lc = {
-	.genpd.name	= "A4LC",
-	.bit_shift	= 1,
-};
+void __init r8a7740_init_pm_domains(void)
+{
+	rmobile_init_domains(r8a7740_pm_domains, ARRAY_SIZE(r8a7740_pm_domains));
+	pm_genpd_add_subdomain_names("A4S", "A3SP");
+}
 
 #endif /* CONFIG_PM */
diff --git a/arch/arm/mach-shmobile/pm-r8a7779.c b/arch/arm/mach-shmobile/pm-r8a7779.c
index a18a4ae..d50a8e9 100644
--- a/arch/arm/mach-shmobile/pm-r8a7779.c
+++ b/arch/arm/mach-shmobile/pm-r8a7779.c
@@ -183,7 +183,7 @@ static bool pd_active_wakeup(struct device *dev)
 	return true;
 }
 
-void r8a7779_init_pm_domain(struct r8a7779_pm_domain *r8a7779_pd)
+static void r8a7779_init_pm_domain(struct r8a7779_pm_domain *r8a7779_pd)
 {
 	struct generic_pm_domain *genpd = &r8a7779_pd->genpd;
 
@@ -199,43 +199,44 @@ void r8a7779_init_pm_domain(struct r8a7779_pm_domain *r8a7779_pd)
 		pd_power_up(&r8a7779_pd->genpd);
 }
 
-void r8a7779_add_device_to_domain(struct r8a7779_pm_domain *r8a7779_pd,
-				 struct platform_device *pdev)
-{
-	struct device *dev = &pdev->dev;
-
-	pm_genpd_add_device(&r8a7779_pd->genpd, dev);
-	if (pm_clk_no_clocks(dev))
-		pm_clk_add(dev, NULL);
-}
-
-struct r8a7779_pm_domain r8a7779_sh4a = {
-	.ch = {
-		.chan_offs = 0x80, /* PWRSR1 .. PWRER1 */
-		.isr_bit = 16, /* SH4A */
-	}
-};
-
-struct r8a7779_pm_domain r8a7779_sgx = {
-	.ch = {
-		.chan_offs = 0xc0, /* PWRSR2 .. PWRER2 */
-		.isr_bit = 20, /* SGX */
-	}
+static struct r8a7779_pm_domain r8a7779_pm_domains[] = {
+	{
+		.genpd.name = "SH4A",
+		.ch = {
+			.chan_offs = 0x80, /* PWRSR1 .. PWRER1 */
+			.isr_bit = 16, /* SH4A */
+		},
+	},
+	{
+		.genpd.name = "SGX",
+		.ch = {
+			.chan_offs = 0xc0, /* PWRSR2 .. PWRER2 */
+			.isr_bit = 20, /* SGX */
+		},
+	},
+	{
+		.genpd.name = "VDP1",
+		.ch = {
+			.chan_offs = 0x100, /* PWRSR3 .. PWRER3 */
+			.isr_bit = 21, /* VDP */
+		},
+	},
+	{
+		.genpd.name = "IMPX3",
+		.ch = {
+			.chan_offs = 0x140, /* PWRSR4 .. PWRER4 */
+			.isr_bit = 24, /* IMP */
+		},
+	},
 };
 
-struct r8a7779_pm_domain r8a7779_vdp1 = {
-	.ch = {
-		.chan_offs = 0x100, /* PWRSR3 .. PWRER3 */
-		.isr_bit = 21, /* VDP */
-	}
-};
+void __init r8a7779_init_pm_domains(void)
+{
+	int j;
 
-struct r8a7779_pm_domain r8a7779_impx3 = {
-	.ch = {
-		.chan_offs = 0x140, /* PWRSR4 .. PWRER4 */
-		.isr_bit = 24, /* IMP */
-	}
-};
+	for (j = 0; j < ARRAY_SIZE(r8a7779_pm_domains); j++)
+		r8a7779_init_pm_domain(&r8a7779_pm_domains[j]);
+}
 
 #endif /* CONFIG_PM */
 
diff --git a/arch/arm/mach-shmobile/pm-rmobile.c b/arch/arm/mach-shmobile/pm-rmobile.c
index a856254..1fc05d9 100644
--- a/arch/arm/mach-shmobile/pm-rmobile.c
+++ b/arch/arm/mach-shmobile/pm-rmobile.c
@@ -20,9 +20,9 @@
 #include <mach/pm-rmobile.h>
 
 /* SYSC */
-#define SPDCR		0xe6180008
-#define SWUCR		0xe6180014
-#define PSTR		0xe6180080
+#define SPDCR		IOMEM(0xe6180008)
+#define SWUCR		IOMEM(0xe6180014)
+#define PSTR		IOMEM(0xe6180080)
 
 #define PSTR_RETRIES	100
 #define PSTR_DELAY_US	10
@@ -134,7 +134,7 @@ static int rmobile_pd_start_dev(struct device *dev)
 	return ret;
 }
 
-void rmobile_init_pm_domain(struct rmobile_pm_domain *rmobile_pd)
+static void rmobile_init_pm_domain(struct rmobile_pm_domain *rmobile_pd)
 {
 	struct generic_pm_domain *genpd = &rmobile_pd->genpd;
 	struct dev_power_governor *gov = rmobile_pd->gov;
@@ -149,19 +149,38 @@ void rmobile_init_pm_domain(struct rmobile_pm_domain *rmobile_pd)
 	__rmobile_pd_power_up(rmobile_pd, false);
 }
 
-void rmobile_add_device_to_domain(struct rmobile_pm_domain *rmobile_pd,
-				 struct platform_device *pdev)
+void rmobile_init_domains(struct rmobile_pm_domain domains[], int num)
+{
+	int j;
+
+	for (j = 0; j < num; j++)
+		rmobile_init_pm_domain(&domains[j]);
+}
+
+void rmobile_add_device_to_domain_td(const char *domain_name,
+				     struct platform_device *pdev,
+				     struct gpd_timing_data *td)
 {
 	struct device *dev = &pdev->dev;
 
-	pm_genpd_add_device(&rmobile_pd->genpd, dev);
+	__pm_genpd_name_add_device(domain_name, dev, td);
 	if (pm_clk_no_clocks(dev))
 		pm_clk_add(dev, NULL);
 }
 
-void rmobile_pm_add_subdomain(struct rmobile_pm_domain *rmobile_pd,
-			     struct rmobile_pm_domain *rmobile_sd)
+void rmobile_add_devices_to_domains(struct pm_domain_device data[],
+				    int size)
 {
-	pm_genpd_add_subdomain(&rmobile_pd->genpd, &rmobile_sd->genpd);
+	struct gpd_timing_data latencies = {
+		.stop_latency_ns = DEFAULT_DEV_LATENCY_NS,
+		.start_latency_ns = DEFAULT_DEV_LATENCY_NS,
+		.save_state_latency_ns = DEFAULT_DEV_LATENCY_NS,
+		.restore_state_latency_ns = DEFAULT_DEV_LATENCY_NS,
+	};
+	int j;
+
+	for (j = 0; j < size; j++)
+		rmobile_add_device_to_domain_td(data[j].domain_name,
+						data[j].pdev, &latencies);
 }
 #endif /* CONFIG_PM */
diff --git a/arch/arm/mach-shmobile/pm-sh7372.c b/arch/arm/mach-shmobile/pm-sh7372.c
index 7920370..a0826a4 100644
--- a/arch/arm/mach-shmobile/pm-sh7372.c
+++ b/arch/arm/mach-shmobile/pm-sh7372.c
@@ -21,6 +21,7 @@
 #include <linux/irq.h>
 #include <linux/bitrev.h>
 #include <linux/console.h>
+#include <asm/cpuidle.h>
 #include <asm/io.h>
 #include <asm/tlbflush.h>
 #include <asm/suspend.h>
@@ -29,62 +30,50 @@
 #include <mach/pm-rmobile.h>
 
 /* DBG */
-#define DBGREG1 0xe6100020
-#define DBGREG9 0xe6100040
+#define DBGREG1 IOMEM(0xe6100020)
+#define DBGREG9 IOMEM(0xe6100040)
 
 /* CPGA */
-#define SYSTBCR 0xe6150024
-#define MSTPSR0 0xe6150030
-#define MSTPSR1 0xe6150038
-#define MSTPSR2 0xe6150040
-#define MSTPSR3 0xe6150048
-#define MSTPSR4 0xe615004c
-#define PLLC01STPCR 0xe61500c8
+#define SYSTBCR IOMEM(0xe6150024)
+#define MSTPSR0 IOMEM(0xe6150030)
+#define MSTPSR1 IOMEM(0xe6150038)
+#define MSTPSR2 IOMEM(0xe6150040)
+#define MSTPSR3 IOMEM(0xe6150048)
+#define MSTPSR4 IOMEM(0xe615004c)
+#define PLLC01STPCR IOMEM(0xe61500c8)
 
 /* SYSC */
-#define SBAR 0xe6180020
-#define WUPRMSK 0xe6180028
-#define WUPSMSK 0xe618002c
-#define WUPSMSK2 0xe6180048
-#define WUPSFAC 0xe6180098
-#define IRQCR 0xe618022c
-#define IRQCR2 0xe6180238
-#define IRQCR3 0xe6180244
-#define IRQCR4 0xe6180248
-#define PDNSEL 0xe6180254
+#define SBAR IOMEM(0xe6180020)
+#define WUPRMSK IOMEM(0xe6180028)
+#define WUPSMSK IOMEM(0xe618002c)
+#define WUPSMSK2 IOMEM(0xe6180048)
+#define WUPSFAC IOMEM(0xe6180098)
+#define IRQCR IOMEM(0xe618022c)
+#define IRQCR2 IOMEM(0xe6180238)
+#define IRQCR3 IOMEM(0xe6180244)
+#define IRQCR4 IOMEM(0xe6180248)
+#define PDNSEL IOMEM(0xe6180254)
 
 /* INTC */
-#define ICR1A 0xe6900000
-#define ICR2A 0xe6900004
-#define ICR3A 0xe6900008
-#define ICR4A 0xe690000c
-#define INTMSK00A 0xe6900040
-#define INTMSK10A 0xe6900044
-#define INTMSK20A 0xe6900048
-#define INTMSK30A 0xe690004c
+#define ICR1A IOMEM(0xe6900000)
+#define ICR2A IOMEM(0xe6900004)
+#define ICR3A IOMEM(0xe6900008)
+#define ICR4A IOMEM(0xe690000c)
+#define INTMSK00A IOMEM(0xe6900040)
+#define INTMSK10A IOMEM(0xe6900044)
+#define INTMSK20A IOMEM(0xe6900048)
+#define INTMSK30A IOMEM(0xe690004c)
 
 /* MFIS */
+/* FIXME: pointing where? */
 #define SMFRAM 0xe6a70000
 
 /* AP-System Core */
-#define APARMBAREA 0xe6f10020
+#define APARMBAREA IOMEM(0xe6f10020)
 
 #ifdef CONFIG_PM
 
-struct rmobile_pm_domain sh7372_pd_a4lc = {
-	.genpd.name = "A4LC",
-	.bit_shift = 1,
-};
-
-struct rmobile_pm_domain sh7372_pd_a4mp = {
-	.genpd.name = "A4MP",
-	.bit_shift = 2,
-};
-
-struct rmobile_pm_domain sh7372_pd_d4 = {
-	.genpd.name = "D4",
-	.bit_shift = 3,
-};
+#define PM_DOMAIN_ON_OFF_LATENCY_NS	250000
 
 static int sh7372_a4r_pd_suspend(void)
 {
@@ -93,39 +82,25 @@ static int sh7372_a4r_pd_suspend(void)
 	return 0;
 }
 
-struct rmobile_pm_domain sh7372_pd_a4r = {
-	.genpd.name = "A4R",
-	.bit_shift = 5,
-	.suspend = sh7372_a4r_pd_suspend,
-	.resume = sh7372_intcs_resume,
-};
+static bool a4s_suspend_ready;
 
-struct rmobile_pm_domain sh7372_pd_a3rv = {
-	.genpd.name = "A3RV",
-	.bit_shift = 6,
-};
-
-struct rmobile_pm_domain sh7372_pd_a3ri = {
-	.genpd.name = "A3RI",
-	.bit_shift = 8,
-};
-
-static int sh7372_pd_a4s_suspend(void)
+static int sh7372_a4s_pd_suspend(void)
 {
 	/*
 	 * The A4S domain contains the CPU core and therefore it should
-	 * only be turned off if the CPU is in use.
+	 * only be turned off if the CPU is not in use.  This may happen
+	 * during system suspend, when SYSC is going to be used for generating
+	 * resume signals and a4s_suspend_ready is set to let
+	 * sh7372_enter_suspend() know that it can turn A4S off.
 	 */
+	a4s_suspend_ready = true;
 	return -EBUSY;
 }
 
-struct rmobile_pm_domain sh7372_pd_a4s = {
-	.genpd.name = "A4S",
-	.bit_shift = 10,
-	.gov = &pm_domain_always_on_gov,
-	.no_debug = true,
-	.suspend = sh7372_pd_a4s_suspend,
-};
+static void sh7372_a4s_pd_resume(void)
+{
+	a4s_suspend_ready = false;
+}
 
 static int sh7372_a3sp_pd_suspend(void)
 {
@@ -136,18 +111,80 @@ static int sh7372_a3sp_pd_suspend(void)
 	return console_suspend_enabled ? 0 : -EBUSY;
 }
 
-struct rmobile_pm_domain sh7372_pd_a3sp = {
-	.genpd.name = "A3SP",
-	.bit_shift = 11,
-	.gov = &pm_domain_always_on_gov,
-	.no_debug = true,
-	.suspend = sh7372_a3sp_pd_suspend,
+static struct rmobile_pm_domain sh7372_pm_domains[] = {
+	{
+		.genpd.name = "A4LC",
+		.genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
+		.genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
+		.bit_shift = 1,
+	},
+	{
+		.genpd.name = "A4MP",
+		.genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
+		.genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
+		.bit_shift = 2,
+	},
+	{
+		.genpd.name = "D4",
+		.genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
+		.genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
+		.bit_shift = 3,
+	},
+	{
+		.genpd.name = "A4R",
+		.genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
+		.genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
+		.bit_shift = 5,
+		.suspend = sh7372_a4r_pd_suspend,
+		.resume = sh7372_intcs_resume,
+	},
+	{
+		.genpd.name = "A3RV",
+		.genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
+		.genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
+		.bit_shift = 6,
+	},
+	{
+		.genpd.name = "A3RI",
+		.genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
+		.genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
+		.bit_shift = 8,
+	},
+	{
+		.genpd.name = "A4S",
+		.genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
+		.genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
+		.bit_shift = 10,
+		.gov = &pm_domain_always_on_gov,
+		.no_debug = true,
+		.suspend = sh7372_a4s_pd_suspend,
+		.resume = sh7372_a4s_pd_resume,
+	},
+	{
+		.genpd.name = "A3SP",
+		.genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
+		.genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
+		.bit_shift = 11,
+		.gov = &pm_domain_always_on_gov,
+		.no_debug = true,
+		.suspend = sh7372_a3sp_pd_suspend,
+	},
+	{
+		.genpd.name = "A3SG",
+		.genpd.power_on_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
+		.genpd.power_off_latency_ns = PM_DOMAIN_ON_OFF_LATENCY_NS,
+		.bit_shift = 13,
+	},
 };
 
-struct rmobile_pm_domain sh7372_pd_a3sg = {
-	.genpd.name = "A3SG",
-	.bit_shift = 13,
-};
+void __init sh7372_init_pm_domains(void)
+{
+	rmobile_init_domains(sh7372_pm_domains, ARRAY_SIZE(sh7372_pm_domains));
+	pm_genpd_add_subdomain_names("A4LC", "A3RV");
+	pm_genpd_add_subdomain_names("A4R", "A4LC");
+	pm_genpd_add_subdomain_names("A4S", "A3SG");
+	pm_genpd_add_subdomain_names("A4S", "A3SP");
+}
 
 #endif /* CONFIG_PM */
 
@@ -303,6 +340,21 @@ static void sh7372_enter_a3sm_common(int pllc0_on)
 	sh7372_set_reset_vector(__pa(sh7372_resume_core_standby_sysc));
 	sh7372_enter_sysc(pllc0_on, 1 << 12);
 }
+
+static void sh7372_enter_a4s_common(int pllc0_on)
+{
+	sh7372_intca_suspend();
+	sh7372_set_reset_vector(SMFRAM);
+	sh7372_enter_sysc(pllc0_on, 1 << 10);
+	sh7372_intca_resume();
+}
+
+static void sh7372_pm_setup_smfram(void)
+{
+	memcpy((void *)SMFRAM, sh7372_resume_core_standby_sysc, 0x100);
+}
+#else
+static inline void sh7372_pm_setup_smfram(void) {}
 #endif /* CONFIG_SUSPEND || CONFIG_CPU_IDLE */
 
 #ifdef CONFIG_CPU_IDLE
@@ -312,7 +364,8 @@ static int sh7372_do_idle_core_standby(unsigned long unused)
 	return 0;
 }
 
-static void sh7372_enter_core_standby(void)
+static int sh7372_enter_core_standby(struct cpuidle_device *dev,
+				     struct cpuidle_driver *drv, int index)
 {
 	sh7372_set_reset_vector(__pa(sh7372_resume_core_standby_sysc));
 
@@ -323,83 +376,102 @@ static void sh7372_enter_core_standby(void)
 
 	 /* disable reset vector translation */
 	__raw_writel(0, SBAR);
+
+	return 1;
 }
 
-static void sh7372_enter_a3sm_pll_on(void)
+static int sh7372_enter_a3sm_pll_on(struct cpuidle_device *dev,
+				    struct cpuidle_driver *drv, int index)
 {
 	sh7372_enter_a3sm_common(1);
+	return 2;
 }
 
-static void sh7372_enter_a3sm_pll_off(void)
+static int sh7372_enter_a3sm_pll_off(struct cpuidle_device *dev,
+				     struct cpuidle_driver *drv, int index)
 {
 	sh7372_enter_a3sm_common(0);
+	return 3;
 }
 
-static void sh7372_cpuidle_setup(struct cpuidle_driver *drv)
+static int sh7372_enter_a4s(struct cpuidle_device *dev,
+			    struct cpuidle_driver *drv, int index)
 {
-	struct cpuidle_state *state = &drv->states[drv->state_count];
-
-	snprintf(state->name, CPUIDLE_NAME_LEN, "C2");
-	strncpy(state->desc, "Core Standby Mode", CPUIDLE_DESC_LEN);
-	state->exit_latency = 10;
-	state->target_residency = 20 + 10;
-	state->flags = CPUIDLE_FLAG_TIME_VALID;
-	shmobile_cpuidle_modes[drv->state_count] = sh7372_enter_core_standby;
-	drv->state_count++;
-
-	state = &drv->states[drv->state_count];
-	snprintf(state->name, CPUIDLE_NAME_LEN, "C3");
-	strncpy(state->desc, "A3SM PLL ON", CPUIDLE_DESC_LEN);
-	state->exit_latency = 20;
-	state->target_residency = 30 + 20;
-	state->flags = CPUIDLE_FLAG_TIME_VALID;
-	shmobile_cpuidle_modes[drv->state_count] = sh7372_enter_a3sm_pll_on;
-	drv->state_count++;
-
-	state = &drv->states[drv->state_count];
-	snprintf(state->name, CPUIDLE_NAME_LEN, "C4");
-	strncpy(state->desc, "A3SM PLL OFF", CPUIDLE_DESC_LEN);
-	state->exit_latency = 120;
-	state->target_residency = 30 + 120;
-	state->flags = CPUIDLE_FLAG_TIME_VALID;
-	shmobile_cpuidle_modes[drv->state_count] = sh7372_enter_a3sm_pll_off;
-	drv->state_count++;
+	unsigned long msk, msk2;
+
+	if (!sh7372_sysc_valid(&msk, &msk2))
+		return sh7372_enter_a3sm_pll_off(dev, drv, index);
+
+	sh7372_setup_sysc(msk, msk2);
+	sh7372_enter_a4s_common(0);
+	return 4;
 }
 
+static struct cpuidle_driver sh7372_cpuidle_driver = {
+	.name			= "sh7372_cpuidle",
+	.owner			= THIS_MODULE,
+	.en_core_tk_irqen	= 1,
+	.state_count		= 5,
+	.safe_state_index	= 0, /* C1 */
+	.states[0] = ARM_CPUIDLE_WFI_STATE,
+	.states[0].enter = shmobile_enter_wfi,
+	.states[1] = {
+		.name = "C2",
+		.desc = "Core Standby Mode",
+		.exit_latency = 10,
+		.target_residency = 20 + 10,
+		.flags = CPUIDLE_FLAG_TIME_VALID,
+		.enter = sh7372_enter_core_standby,
+	},
+	.states[2] = {
+		.name = "C3",
+		.desc = "A3SM PLL ON",
+		.exit_latency = 20,
+		.target_residency = 30 + 20,
+		.flags = CPUIDLE_FLAG_TIME_VALID,
+		.enter = sh7372_enter_a3sm_pll_on,
+	},
+	.states[3] = {
+		.name = "C4",
+		.desc = "A3SM PLL OFF",
+		.exit_latency = 120,
+		.target_residency = 30 + 120,
+		.flags = CPUIDLE_FLAG_TIME_VALID,
+		.enter = sh7372_enter_a3sm_pll_off,
+	},
+	.states[4] = {
+		.name = "C5",
+		.desc = "A4S PLL OFF",
+		.exit_latency = 240,
+		.target_residency = 30 + 240,
+		.flags = CPUIDLE_FLAG_TIME_VALID,
+		.enter = sh7372_enter_a4s,
+		.disabled = true,
+	},
+};
+
 static void sh7372_cpuidle_init(void)
 {
-	shmobile_cpuidle_setup = sh7372_cpuidle_setup;
+	shmobile_cpuidle_set_driver(&sh7372_cpuidle_driver);
 }
 #else
 static void sh7372_cpuidle_init(void) {}
 #endif
 
 #ifdef CONFIG_SUSPEND
-static void sh7372_enter_a4s_common(int pllc0_on)
-{
-	sh7372_intca_suspend();
-	memcpy((void *)SMFRAM, sh7372_resume_core_standby_sysc, 0x100);
-	sh7372_set_reset_vector(SMFRAM);
-	sh7372_enter_sysc(pllc0_on, 1 << 10);
-	sh7372_intca_resume();
-}
-
 static int sh7372_enter_suspend(suspend_state_t suspend_state)
 {
 	unsigned long msk, msk2;
 
 	/* check active clocks to determine potential wakeup sources */
-	if (sh7372_sysc_valid(&msk, &msk2)) {
-		if (!console_suspend_enabled &&
-		    sh7372_pd_a4s.genpd.status == GPD_STATE_POWER_OFF) {
-			/* convert INTC mask/sense to SYSC mask/sense */
-			sh7372_setup_sysc(msk, msk2);
-
-			/* enter A4S sleep with PLLC0 off */
-			pr_debug("entering A4S\n");
-			sh7372_enter_a4s_common(0);
-			return 0;
-		}
+	if (sh7372_sysc_valid(&msk, &msk2) && a4s_suspend_ready) {
+		/* convert INTC mask/sense to SYSC mask/sense */
+		sh7372_setup_sysc(msk, msk2);
+
+		/* enter A4S sleep with PLLC0 off */
+		pr_debug("entering A4S\n");
+		sh7372_enter_a4s_common(0);
+		return 0;
 	}
 
 	/* default to enter A3SM sleep with PLLC0 off */
@@ -425,7 +497,7 @@ static int sh7372_pm_notifier_fn(struct notifier_block *notifier,
 		 * executed during system suspend and resume, respectively, so
 		 * that those functions don't crash while accessing the INTCS.
 		 */
-		pm_genpd_poweron(&sh7372_pd_a4r.genpd);
+		pm_genpd_name_poweron("A4R");
 		break;
 	case PM_POST_SUSPEND:
 		pm_genpd_poweroff_unused();
@@ -454,6 +526,14 @@ void __init sh7372_pm_init(void)
 	/* do not convert A3SM, A3SP, A3SG, A4R power down into A4S */
 	__raw_writel(0, PDNSEL);
 
+	sh7372_pm_setup_smfram();
+
 	sh7372_suspend_init();
 	sh7372_cpuidle_init();
 }
+
+void __init sh7372_pm_init_late(void)
+{
+	shmobile_init_late();
+	pm_genpd_name_attach_cpuidle("A4S", 4);
+}
diff --git a/arch/arm/mach-shmobile/setup-emev2.c b/arch/arm/mach-shmobile/setup-emev2.c
index dae9aa6..a47beeb 100644
--- a/arch/arm/mach-shmobile/setup-emev2.c
+++ b/arch/arm/mach-shmobile/setup-emev2.c
@@ -356,6 +356,26 @@ static struct platform_device gio4_device = {
 	},
 };
 
+static struct resource pmu_resources[] = {
+	[0] = {
+		.start	= 152,
+		.end	= 152,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[1] = {
+		.start	= 153,
+		.end	= 153,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device pmu_device = {
+	.name		= "arm-pmu",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(pmu_resources),
+	.resource	= pmu_resources,
+};
+
 static struct platform_device *emev2_early_devices[] __initdata = {
 	&uart0_device,
 	&uart1_device,
@@ -370,6 +390,7 @@ static struct platform_device *emev2_late_devices[] __initdata = {
 	&gio2_device,
 	&gio3_device,
 	&gio4_device,
+	&pmu_device,
 };
 
 void __init emev2_add_standard_devices(void)
@@ -440,6 +461,7 @@ void __init emev2_init_irq_dt(void)
 }
 
 DT_MACHINE_START(EMEV2_DT, "Generic Emma Mobile EV2 (Flattened Device Tree)")
+	.smp		= smp_ops(emev2_smp_ops),
 	.init_early	= emev2_init_delay,
 	.nr_irqs	= NR_IRQS_LEGACY,
 	.init_irq	= emev2_init_irq_dt,
diff --git a/arch/arm/mach-shmobile/setup-r8a7740.c b/arch/arm/mach-shmobile/setup-r8a7740.c
index 78948a9..1e032cb 100644
--- a/arch/arm/mach-shmobile/setup-r8a7740.c
+++ b/arch/arm/mach-shmobile/setup-r8a7740.c
@@ -590,6 +590,21 @@ static struct platform_device i2c1_device = {
 	.num_resources	= ARRAY_SIZE(i2c1_resources),
 };
 
+static struct resource pmu_resources[] = {
+	[0] = {
+		.start	= evt2irq(0x19a0),
+		.end	= evt2irq(0x19a0),
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device pmu_device = {
+	.name	= "arm-pmu",
+	.id		= -1,
+	.num_resources = ARRAY_SIZE(pmu_resources),
+	.resource = pmu_resources,
+};
+
 static struct platform_device *r8a7740_late_devices[] __initdata = {
 	&i2c0_device,
 	&i2c1_device,
@@ -597,6 +612,7 @@ static struct platform_device *r8a7740_late_devices[] __initdata = {
 	&dma1_device,
 	&dma2_device,
 	&usb_dma_device,
+	&pmu_device,
 };
 
 /*
@@ -673,12 +689,7 @@ void __init r8a7740_add_standard_devices(void)
 	r8a7740_i2c_workaround(&i2c0_device);
 	r8a7740_i2c_workaround(&i2c1_device);
 
-	/* PM domain */
-	rmobile_init_pm_domain(&r8a7740_pd_a4s);
-	rmobile_init_pm_domain(&r8a7740_pd_a3sp);
-	rmobile_init_pm_domain(&r8a7740_pd_a4lc);
-
-	rmobile_pm_add_subdomain(&r8a7740_pd_a4s, &r8a7740_pd_a3sp);
+	r8a7740_init_pm_domains();
 
 	/* add devices */
 	platform_add_devices(r8a7740_early_devices,
@@ -688,16 +699,16 @@ void __init r8a7740_add_standard_devices(void)
 
 	/* add devices to PM domain  */
 
-	rmobile_add_device_to_domain(&r8a7740_pd_a3sp,	&scif0_device);
-	rmobile_add_device_to_domain(&r8a7740_pd_a3sp,	&scif1_device);
-	rmobile_add_device_to_domain(&r8a7740_pd_a3sp,	&scif2_device);
-	rmobile_add_device_to_domain(&r8a7740_pd_a3sp,	&scif3_device);
-	rmobile_add_device_to_domain(&r8a7740_pd_a3sp,	&scif4_device);
-	rmobile_add_device_to_domain(&r8a7740_pd_a3sp,	&scif5_device);
-	rmobile_add_device_to_domain(&r8a7740_pd_a3sp,	&scif6_device);
-	rmobile_add_device_to_domain(&r8a7740_pd_a3sp,	&scif7_device);
-	rmobile_add_device_to_domain(&r8a7740_pd_a3sp,	&scifb_device);
-	rmobile_add_device_to_domain(&r8a7740_pd_a3sp,	&i2c1_device);
+	rmobile_add_device_to_domain("A3SP",	&scif0_device);
+	rmobile_add_device_to_domain("A3SP",	&scif1_device);
+	rmobile_add_device_to_domain("A3SP",	&scif2_device);
+	rmobile_add_device_to_domain("A3SP",	&scif3_device);
+	rmobile_add_device_to_domain("A3SP",	&scif4_device);
+	rmobile_add_device_to_domain("A3SP",	&scif5_device);
+	rmobile_add_device_to_domain("A3SP",	&scif6_device);
+	rmobile_add_device_to_domain("A3SP",	&scif7_device);
+	rmobile_add_device_to_domain("A3SP",	&scifb_device);
+	rmobile_add_device_to_domain("A3SP",	&i2c1_device);
 }
 
 static void __init r8a7740_earlytimer_init(void)
diff --git a/arch/arm/mach-shmobile/setup-r8a7779.c b/arch/arm/mach-shmobile/setup-r8a7779.c
index e98e46f..2917668 100644
--- a/arch/arm/mach-shmobile/setup-r8a7779.c
+++ b/arch/arm/mach-shmobile/setup-r8a7779.c
@@ -251,10 +251,7 @@ void __init r8a7779_add_standard_devices(void)
 #endif
 	r8a7779_pm_init();
 
-	r8a7779_init_pm_domain(&r8a7779_sh4a);
-	r8a7779_init_pm_domain(&r8a7779_sgx);
-	r8a7779_init_pm_domain(&r8a7779_vdp1);
-	r8a7779_init_pm_domain(&r8a7779_impx3);
+	r8a7779_init_pm_domains();
 
 	platform_add_devices(r8a7779_early_devices,
 			    ARRAY_SIZE(r8a7779_early_devices));
diff --git a/arch/arm/mach-shmobile/setup-sh7367.c b/arch/arm/mach-shmobile/setup-sh7367.c
index 2e3074a..e647f54 100644
--- a/arch/arm/mach-shmobile/setup-sh7367.c
+++ b/arch/arm/mach-shmobile/setup-sh7367.c
@@ -462,7 +462,7 @@ static void __init sh7367_earlytimer_init(void)
 	shmobile_earlytimer_init();
 }
 
-#define SYMSTPCR2 0xe6158048
+#define SYMSTPCR2 IOMEM(0xe6158048)
 #define SYMSTPCR2_CMT1 (1 << 29)
 
 void __init sh7367_add_early_devices(void)
diff --git a/arch/arm/mach-shmobile/setup-sh7372.c b/arch/arm/mach-shmobile/setup-sh7372.c
index 838a87b..a360111 100644
--- a/arch/arm/mach-shmobile/setup-sh7372.c
+++ b/arch/arm/mach-shmobile/setup-sh7372.c
@@ -408,6 +408,26 @@ static const struct sh_dmae_slave_config sh7372_dmae_slaves[] = {
 		.chcr		= CHCR_RX(XMIT_SZ_8BIT),
 		.mid_rid	= 0x3e,
 	}, {
+		.slave_id	= SHDMA_SLAVE_FLCTL0_TX,
+		.addr		= 0xe6a30050,
+		.chcr		= CHCR_TX(XMIT_SZ_32BIT),
+		.mid_rid	= 0x83,
+	}, {
+		.slave_id	= SHDMA_SLAVE_FLCTL0_RX,
+		.addr		= 0xe6a30050,
+		.chcr		= CHCR_RX(XMIT_SZ_32BIT),
+		.mid_rid	= 0x83,
+	}, {
+		.slave_id	= SHDMA_SLAVE_FLCTL1_TX,
+		.addr		= 0xe6a30060,
+		.chcr		= CHCR_TX(XMIT_SZ_32BIT),
+		.mid_rid	= 0x87,
+	}, {
+		.slave_id	= SHDMA_SLAVE_FLCTL1_RX,
+		.addr		= 0xe6a30060,
+		.chcr		= CHCR_RX(XMIT_SZ_32BIT),
+		.mid_rid	= 0x87,
+	}, {
 		.slave_id	= SHDMA_SLAVE_SDHI0_TX,
 		.addr		= 0xe6850030,
 		.chcr		= CHCR_TX(XMIT_SZ_16BIT),
@@ -1001,21 +1021,34 @@ static struct platform_device *sh7372_late_devices[] __initdata = {
 
 void __init sh7372_add_standard_devices(void)
 {
-	rmobile_init_pm_domain(&sh7372_pd_a4lc);
-	rmobile_init_pm_domain(&sh7372_pd_a4mp);
-	rmobile_init_pm_domain(&sh7372_pd_d4);
-	rmobile_init_pm_domain(&sh7372_pd_a4r);
-	rmobile_init_pm_domain(&sh7372_pd_a3rv);
-	rmobile_init_pm_domain(&sh7372_pd_a3ri);
-	rmobile_init_pm_domain(&sh7372_pd_a4s);
-	rmobile_init_pm_domain(&sh7372_pd_a3sp);
-	rmobile_init_pm_domain(&sh7372_pd_a3sg);
-
-	rmobile_pm_add_subdomain(&sh7372_pd_a4lc, &sh7372_pd_a3rv);
-	rmobile_pm_add_subdomain(&sh7372_pd_a4r, &sh7372_pd_a4lc);
-
-	rmobile_pm_add_subdomain(&sh7372_pd_a4s, &sh7372_pd_a3sg);
-	rmobile_pm_add_subdomain(&sh7372_pd_a4s, &sh7372_pd_a3sp);
+	struct pm_domain_device domain_devices[] = {
+		{ "A3RV", &vpu_device, },
+		{ "A4MP", &spu0_device, },
+		{ "A4MP", &spu1_device, },
+		{ "A3SP", &scif0_device, },
+		{ "A3SP", &scif1_device, },
+		{ "A3SP", &scif2_device, },
+		{ "A3SP", &scif3_device, },
+		{ "A3SP", &scif4_device, },
+		{ "A3SP", &scif5_device, },
+		{ "A3SP", &scif6_device, },
+		{ "A3SP", &iic1_device, },
+		{ "A3SP", &dma0_device, },
+		{ "A3SP", &dma1_device, },
+		{ "A3SP", &dma2_device, },
+		{ "A3SP", &usb_dma0_device, },
+		{ "A3SP", &usb_dma1_device, },
+		{ "A4R", &iic0_device, },
+		{ "A4R", &veu0_device, },
+		{ "A4R", &veu1_device, },
+		{ "A4R", &veu2_device, },
+		{ "A4R", &veu3_device, },
+		{ "A4R", &jpu_device, },
+		{ "A4R", &tmu00_device, },
+		{ "A4R", &tmu01_device, },
+	};
+
+	sh7372_init_pm_domains();
 
 	platform_add_devices(sh7372_early_devices,
 			    ARRAY_SIZE(sh7372_early_devices));
@@ -1023,30 +1056,8 @@ void __init sh7372_add_standard_devices(void)
 	platform_add_devices(sh7372_late_devices,
 			    ARRAY_SIZE(sh7372_late_devices));
 
-	rmobile_add_device_to_domain(&sh7372_pd_a3rv, &vpu_device);
-	rmobile_add_device_to_domain(&sh7372_pd_a4mp, &spu0_device);
-	rmobile_add_device_to_domain(&sh7372_pd_a4mp, &spu1_device);
-	rmobile_add_device_to_domain(&sh7372_pd_a3sp, &scif0_device);
-	rmobile_add_device_to_domain(&sh7372_pd_a3sp, &scif1_device);
-	rmobile_add_device_to_domain(&sh7372_pd_a3sp, &scif2_device);
-	rmobile_add_device_to_domain(&sh7372_pd_a3sp, &scif3_device);
-	rmobile_add_device_to_domain(&sh7372_pd_a3sp, &scif4_device);
-	rmobile_add_device_to_domain(&sh7372_pd_a3sp, &scif5_device);
-	rmobile_add_device_to_domain(&sh7372_pd_a3sp, &scif6_device);
-	rmobile_add_device_to_domain(&sh7372_pd_a3sp, &iic1_device);
-	rmobile_add_device_to_domain(&sh7372_pd_a3sp, &dma0_device);
-	rmobile_add_device_to_domain(&sh7372_pd_a3sp, &dma1_device);
-	rmobile_add_device_to_domain(&sh7372_pd_a3sp, &dma2_device);
-	rmobile_add_device_to_domain(&sh7372_pd_a3sp, &usb_dma0_device);
-	rmobile_add_device_to_domain(&sh7372_pd_a3sp, &usb_dma1_device);
-	rmobile_add_device_to_domain(&sh7372_pd_a4r, &iic0_device);
-	rmobile_add_device_to_domain(&sh7372_pd_a4r, &veu0_device);
-	rmobile_add_device_to_domain(&sh7372_pd_a4r, &veu1_device);
-	rmobile_add_device_to_domain(&sh7372_pd_a4r, &veu2_device);
-	rmobile_add_device_to_domain(&sh7372_pd_a4r, &veu3_device);
-	rmobile_add_device_to_domain(&sh7372_pd_a4r, &jpu_device);
-	rmobile_add_device_to_domain(&sh7372_pd_a4r, &tmu00_device);
-	rmobile_add_device_to_domain(&sh7372_pd_a4r, &tmu01_device);
+	rmobile_add_devices_to_domains(domain_devices,
+				       ARRAY_SIZE(domain_devices));
 }
 
 static void __init sh7372_earlytimer_init(void)
diff --git a/arch/arm/mach-shmobile/setup-sh7377.c b/arch/arm/mach-shmobile/setup-sh7377.c
index 855b150..edcf98b 100644
--- a/arch/arm/mach-shmobile/setup-sh7377.c
+++ b/arch/arm/mach-shmobile/setup-sh7377.c
@@ -484,7 +484,7 @@ static void __init sh7377_earlytimer_init(void)
 	shmobile_earlytimer_init();
 }
 
-#define SMSTPCR3 0xe615013c
+#define SMSTPCR3 IOMEM(0xe615013c)
 #define SMSTPCR3_CMT1 (1 << 29)
 
 void __init sh7377_add_early_devices(void)
diff --git a/arch/arm/mach-shmobile/setup-sh73a0.c b/arch/arm/mach-shmobile/setup-sh73a0.c
index d230af6..db99a4a 100644
--- a/arch/arm/mach-shmobile/setup-sh73a0.c
+++ b/arch/arm/mach-shmobile/setup-sh73a0.c
@@ -734,6 +734,26 @@ static struct platform_device mpdma0_device = {
 	},
 };
 
+static struct resource pmu_resources[] = {
+	[0] = {
+		.start	= gic_spi(55),
+		.end	= gic_spi(55),
+		.flags	= IORESOURCE_IRQ,
+	},
+	[1] = {
+		.start	= gic_spi(56),
+		.end	= gic_spi(56),
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device pmu_device = {
+	.name		= "arm-pmu",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(pmu_resources),
+	.resource	= pmu_resources,
+};
+
 static struct platform_device *sh73a0_early_devices[] __initdata = {
 	&scif0_device,
 	&scif1_device,
@@ -757,9 +777,10 @@ static struct platform_device *sh73a0_late_devices[] __initdata = {
 	&i2c4_device,
 	&dma0_device,
 	&mpdma0_device,
+	&pmu_device,
 };
 
-#define SRCR2          0xe61580b0
+#define SRCR2          IOMEM(0xe61580b0)
 
 void __init sh73a0_add_standard_devices(void)
 {
diff --git a/arch/arm/mach-shmobile/sh-gpio.h b/arch/arm/mach-shmobile/sh-gpio.h
new file mode 100644
index 0000000..e834763
--- /dev/null
+++ b/arch/arm/mach-shmobile/sh-gpio.h
@@ -0,0 +1,48 @@
+/*
+ * Generic GPIO API and pinmux table support
+ *
+ * Copyright (c) 2008  Magnus Damm
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#ifndef __ASM_ARCH_GPIO_H
+#define __ASM_ARCH_GPIO_H
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+
+/*
+ * FIXME !!
+ *
+ * current gpio frame work doesn't have
+ * the method to control only pull up/down/free.
+ * this function should be replaced by correct gpio function
+ */
+static inline void __init gpio_direction_none(void __iomem * addr)
+{
+	__raw_writeb(0x00, addr);
+}
+
+static inline void __init gpio_request_pullup(void __iomem * addr)
+{
+	u8 data = __raw_readb(addr);
+
+	data &= 0x0F;
+	data |= 0xC0;
+	__raw_writeb(data, addr);
+}
+
+static inline void __init gpio_request_pulldown(void __iomem * addr)
+{
+	u8 data = __raw_readb(addr);
+
+	data &= 0x0F;
+	data |= 0xA0;
+
+	__raw_writeb(data, addr);
+}
+
+#endif /* __ASM_ARCH_GPIO_H */
diff --git a/arch/arm/mach-shmobile/smp-emev2.c b/arch/arm/mach-shmobile/smp-emev2.c
index 6a35c4a..f674562 100644
--- a/arch/arm/mach-shmobile/smp-emev2.c
+++ b/arch/arm/mach-shmobile/smp-emev2.c
@@ -50,7 +50,7 @@ static void modify_scu_cpu_psr(unsigned long set, unsigned long clr)
 
 }
 
-unsigned int __init emev2_get_core_count(void)
+static unsigned int __init emev2_get_core_count(void)
 {
 	if (!scu_base) {
 		scu_base = ioremap(EMEV2_SCU_BASE, PAGE_SIZE);
@@ -62,17 +62,35 @@ unsigned int __init emev2_get_core_count(void)
 	return scu_base ? scu_get_core_count(scu_base) : 1;
 }
 
-int emev2_platform_cpu_kill(unsigned int cpu)
+static int emev2_platform_cpu_kill(unsigned int cpu)
 {
 	return 0; /* not supported yet */
 }
 
-void __cpuinit emev2_secondary_init(unsigned int cpu)
+static int __maybe_unused emev2_cpu_kill(unsigned int cpu)
+{
+	int k;
+
+	/* this function is running on another CPU than the offline target,
+	 * here we need wait for shutdown code in platform_cpu_die() to
+	 * finish before asking SoC-specific code to power off the CPU core.
+	 */
+	for (k = 0; k < 1000; k++) {
+		if (shmobile_cpu_is_dead(cpu))
+			return emev2_platform_cpu_kill(cpu);
+		mdelay(1);
+	}
+
+	return 0;
+}
+
+
+static void __cpuinit emev2_secondary_init(unsigned int cpu)
 {
 	gic_secondary_init(0);
 }
 
-int __cpuinit emev2_boot_secondary(unsigned int cpu)
+static int __cpuinit emev2_boot_secondary(unsigned int cpu, struct task_struct *idle)
 {
 	cpu = cpu_logical_map(cpu);
 
@@ -82,11 +100,11 @@ int __cpuinit emev2_boot_secondary(unsigned int cpu)
 	/* Tell ROM loader about our vector (in headsmp.S) */
 	emev2_set_boot_vector(__pa(shmobile_secondary_vector));
 
-	gic_raise_softirq(cpumask_of(cpu), 1);
+	gic_raise_softirq(cpumask_of(cpu), 0);
 	return 0;
 }
 
-void __init emev2_smp_prepare_cpus(void)
+static void __init emev2_smp_prepare_cpus(unsigned int max_cpus)
 {
 	int cpu = cpu_logical_map(0);
 
@@ -95,3 +113,22 @@ void __init emev2_smp_prepare_cpus(void)
 	/* enable cache coherency on CPU0 */
 	modify_scu_cpu_psr(0, 3 << (cpu * 8));
 }
+
+static void __init emev2_smp_init_cpus(void)
+{
+	unsigned int ncores = emev2_get_core_count();
+
+	shmobile_smp_init_cpus(ncores);
+}
+
+struct smp_operations emev2_smp_ops __initdata = {
+	.smp_init_cpus		= emev2_smp_init_cpus,
+	.smp_prepare_cpus	= emev2_smp_prepare_cpus,
+	.smp_secondary_init	= emev2_secondary_init,
+	.smp_boot_secondary	= emev2_boot_secondary,
+#ifdef CONFIG_HOTPLUG_CPU
+	.cpu_kill		= emev2_cpu_kill,
+	.cpu_die		= shmobile_cpu_die,
+	.cpu_disable		= shmobile_cpu_disable,
+#endif
+};
diff --git a/arch/arm/mach-shmobile/smp-r8a7779.c b/arch/arm/mach-shmobile/smp-r8a7779.c
index 6d1d023..2ce6af9 100644
--- a/arch/arm/mach-shmobile/smp-r8a7779.c
+++ b/arch/arm/mach-shmobile/smp-r8a7779.c
@@ -87,14 +87,14 @@ static void modify_scu_cpu_psr(unsigned long set, unsigned long clr)
 	__raw_writel(tmp, scu_base + 8);
 }
 
-unsigned int __init r8a7779_get_core_count(void)
+static unsigned int __init r8a7779_get_core_count(void)
 {
 	void __iomem *scu_base = scu_base_addr();
 
 	return scu_get_core_count(scu_base);
 }
 
-int r8a7779_platform_cpu_kill(unsigned int cpu)
+static int r8a7779_platform_cpu_kill(unsigned int cpu)
 {
 	struct r8a7779_pm_ch *ch = NULL;
 	int ret = -EIO;
@@ -113,12 +113,31 @@ int r8a7779_platform_cpu_kill(unsigned int cpu)
 	return ret ? ret : 1;
 }
 
-void __cpuinit r8a7779_secondary_init(unsigned int cpu)
+static int __maybe_unused r8a7779_cpu_kill(unsigned int cpu)
+{
+	int k;
+
+	/* this function is running on another CPU than the offline target,
+	 * here we need wait for shutdown code in platform_cpu_die() to
+	 * finish before asking SoC-specific code to power off the CPU core.
+	 */
+	for (k = 0; k < 1000; k++) {
+		if (shmobile_cpu_is_dead(cpu))
+			return r8a7779_platform_cpu_kill(cpu);
+
+		mdelay(1);
+	}
+
+	return 0;
+}
+
+
+static void __cpuinit r8a7779_secondary_init(unsigned int cpu)
 {
 	gic_secondary_init(0);
 }
 
-int __cpuinit r8a7779_boot_secondary(unsigned int cpu)
+static int __cpuinit r8a7779_boot_secondary(unsigned int cpu, struct task_struct *idle)
 {
 	struct r8a7779_pm_ch *ch = NULL;
 	int ret = -EIO;
@@ -137,7 +156,7 @@ int __cpuinit r8a7779_boot_secondary(unsigned int cpu)
 	return ret;
 }
 
-void __init r8a7779_smp_prepare_cpus(void)
+static void __init r8a7779_smp_prepare_cpus(unsigned int max_cpus)
 {
 	int cpu = cpu_logical_map(0);
 
@@ -156,3 +175,22 @@ void __init r8a7779_smp_prepare_cpus(void)
 	r8a7779_platform_cpu_kill(2);
 	r8a7779_platform_cpu_kill(3);
 }
+
+static void __init r8a7779_smp_init_cpus(void)
+{
+	unsigned int ncores = r8a7779_get_core_count();
+
+	shmobile_smp_init_cpus(ncores);
+}
+
+struct smp_operations r8a7779_smp_ops  __initdata = {
+	.smp_init_cpus		= r8a7779_smp_init_cpus,
+	.smp_prepare_cpus	= r8a7779_smp_prepare_cpus,
+	.smp_secondary_init	= r8a7779_secondary_init,
+	.smp_boot_secondary	= r8a7779_boot_secondary,
+#ifdef CONFIG_HOTPLUG_CPU
+	.cpu_kill		= r8a7779_cpu_kill,
+	.cpu_die		= shmobile_cpu_die,
+	.cpu_disable		= shmobile_cpu_disable,
+#endif
+};
diff --git a/arch/arm/mach-shmobile/smp-sh73a0.c b/arch/arm/mach-shmobile/smp-sh73a0.c
index e36c41c..624f00f 100644
--- a/arch/arm/mach-shmobile/smp-sh73a0.c
+++ b/arch/arm/mach-shmobile/smp-sh73a0.c
@@ -22,8 +22,10 @@
 #include <linux/smp.h>
 #include <linux/spinlock.h>
 #include <linux/io.h>
+#include <linux/delay.h>
 #include <mach/common.h>
 #include <asm/smp_plat.h>
+#include <mach/sh73a0.h>
 #include <asm/smp_scu.h>
 #include <asm/smp_twd.h>
 #include <asm/hardware/gic.h>
@@ -64,19 +66,19 @@ static void modify_scu_cpu_psr(unsigned long set, unsigned long clr)
 	__raw_writel(tmp, scu_base + 8);
 }
 
-unsigned int __init sh73a0_get_core_count(void)
+static unsigned int __init sh73a0_get_core_count(void)
 {
 	void __iomem *scu_base = scu_base_addr();
 
 	return scu_get_core_count(scu_base);
 }
 
-void __cpuinit sh73a0_secondary_init(unsigned int cpu)
+static void __cpuinit sh73a0_secondary_init(unsigned int cpu)
 {
 	gic_secondary_init(0);
 }
 
-int __cpuinit sh73a0_boot_secondary(unsigned int cpu)
+static int __cpuinit sh73a0_boot_secondary(unsigned int cpu, struct task_struct *idle)
 {
 	cpu = cpu_logical_map(cpu);
 
@@ -91,7 +93,7 @@ int __cpuinit sh73a0_boot_secondary(unsigned int cpu)
 	return 0;
 }
 
-void __init sh73a0_smp_prepare_cpus(void)
+static void __init sh73a0_smp_prepare_cpus(unsigned int max_cpus)
 {
 	int cpu = cpu_logical_map(0);
 
@@ -104,3 +106,41 @@ void __init sh73a0_smp_prepare_cpus(void)
 	/* enable cache coherency on CPU0 */
 	modify_scu_cpu_psr(0, 3 << (cpu * 8));
 }
+
+static void __init sh73a0_smp_init_cpus(void)
+{
+	unsigned int ncores = sh73a0_get_core_count();
+
+	shmobile_smp_init_cpus(ncores);
+}
+
+static int __maybe_unused sh73a0_cpu_kill(unsigned int cpu)
+{
+	int k;
+
+	/* this function is running on another CPU than the offline target,
+	 * here we need wait for shutdown code in platform_cpu_die() to
+	 * finish before asking SoC-specific code to power off the CPU core.
+	 */
+	for (k = 0; k < 1000; k++) {
+		if (shmobile_cpu_is_dead(cpu))
+			return 1;
+
+		mdelay(1);
+	}
+
+	return 0;
+}
+
+
+struct smp_operations sh73a0_smp_ops __initdata = {
+	.smp_init_cpus		= sh73a0_smp_init_cpus,
+	.smp_prepare_cpus	= sh73a0_smp_prepare_cpus,
+	.smp_secondary_init	= sh73a0_secondary_init,
+	.smp_boot_secondary	= sh73a0_boot_secondary,
+#ifdef CONFIG_HOTPLUG_CPU
+	.cpu_kill		= sh73a0_cpu_kill,
+	.cpu_die		= shmobile_cpu_die,
+	.cpu_disable		= shmobile_cpu_disable,
+#endif
+};
diff --git a/arch/arm/mach-socfpga/Kconfig b/arch/arm/mach-socfpga/Kconfig
new file mode 100644
index 0000000..803a328
--- /dev/null
+++ b/arch/arm/mach-socfpga/Kconfig
@@ -0,0 +1,16 @@
+config ARCH_SOCFPGA
+	bool "Altera SOCFPGA family" if ARCH_MULTI_V7
+	select ARCH_WANT_OPTIONAL_GPIOLIB
+	select ARM_AMBA
+	select ARM_GIC
+	select CACHE_L2X0
+	select CLKDEV_LOOKUP
+	select COMMON_CLK
+	select CPU_V7
+	select DW_APB_TIMER
+	select DW_APB_TIMER_OF
+	select GENERIC_CLOCKEVENTS
+	select GPIO_PL061 if GPIOLIB
+	select HAVE_ARM_SCU
+	select SPARSE_IRQ
+	select USE_OF
diff --git a/arch/arm/mach-socfpga/Makefile.boot b/arch/arm/mach-socfpga/Makefile.boot
deleted file mode 100644
index dae9661..0000000
--- a/arch/arm/mach-socfpga/Makefile.boot
+++ /dev/null
@@ -1 +0,0 @@
-zreladdr-y	:= 0x00008000
diff --git a/arch/arm/mach-socfpga/include/mach/debug-macro.S b/arch/arm/mach-socfpga/include/mach/debug-macro.S
deleted file mode 100644
index d6f26d2..0000000
--- a/arch/arm/mach-socfpga/include/mach/debug-macro.S
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- *  Copyright (C) 1994-1999 Russell King
- *  Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-		.macro	addruart, rp, rv, tmp
-		mov	\rp, #DEBUG_LL_UART_OFFSET
-		orr	\rp, \rp, #0x00c00000
-		orr	\rv, \rp, #0xfe000000	@ virtual base
-		orr	\rp, \rp, #0xff000000	@ physical base
-		.endm
-
diff --git a/arch/arm/mach-socfpga/include/mach/timex.h b/arch/arm/mach-socfpga/include/mach/timex.h
deleted file mode 100644
index 43df435..0000000
--- a/arch/arm/mach-socfpga/include/mach/timex.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- *  Copyright (C) 2003 ARM Limited
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#define CLOCK_TICK_RATE		(50000000 / 16)
diff --git a/arch/arm/mach-socfpga/include/mach/uncompress.h b/arch/arm/mach-socfpga/include/mach/uncompress.h
deleted file mode 100644
index bbe20e6..0000000
--- a/arch/arm/mach-socfpga/include/mach/uncompress.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef __MACH_UNCOMPRESS_H
-#define __MACH_UNCOMPRESS_H
-
-#define putc(c)
-#define flush()
-#define arch_decomp_setup()
-#define arch_decomp_wdog()
-
-#endif
diff --git a/arch/arm/mach-spear13xx/Makefile.boot b/arch/arm/mach-spear13xx/Makefile.boot
index 403efd7..4674a4c 100644
--- a/arch/arm/mach-spear13xx/Makefile.boot
+++ b/arch/arm/mach-spear13xx/Makefile.boot
@@ -1,6 +1,3 @@
 zreladdr-y	+= 0x00008000
 params_phys-y	:= 0x00000100
 initrd_phys-y	:= 0x00800000
-
-dtb-$(CONFIG_MACH_SPEAR1310)	+= spear1310-evb.dtb
-dtb-$(CONFIG_MACH_SPEAR1340)	+= spear1340-evb.dtb
diff --git a/arch/arm/mach-spear13xx/hotplug.c b/arch/arm/mach-spear13xx/hotplug.c
index 5c6867b..a7d2dd1 100644
--- a/arch/arm/mach-spear13xx/hotplug.c
+++ b/arch/arm/mach-spear13xx/hotplug.c
@@ -17,8 +17,6 @@
 #include <asm/cp15.h>
 #include <asm/smp_plat.h>
 
-extern volatile int pen_release;
-
 static inline void cpu_enter_lowpower(void)
 {
 	unsigned int v;
@@ -56,7 +54,7 @@ static inline void cpu_leave_lowpower(void)
 	: "cc");
 }
 
-static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
+static inline void spear13xx_do_lowpower(unsigned int cpu, int *spurious)
 {
 	for (;;) {
 		wfi();
@@ -79,17 +77,12 @@ static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
 	}
 }
 
-int platform_cpu_kill(unsigned int cpu)
-{
-	return 1;
-}
-
 /*
  * platform-specific code to shutdown a CPU
  *
  * Called with IRQs disabled
  */
-void __cpuinit platform_cpu_die(unsigned int cpu)
+void __ref spear13xx_cpu_die(unsigned int cpu)
 {
 	int spurious = 0;
 
@@ -97,7 +90,7 @@ void __cpuinit platform_cpu_die(unsigned int cpu)
 	 * we're ready for shutdown now, so do it
 	 */
 	cpu_enter_lowpower();
-	platform_do_lowpower(cpu, &spurious);
+	spear13xx_do_lowpower(cpu, &spurious);
 
 	/*
 	 * bring this CPU back into the world of cache
@@ -108,12 +101,3 @@ void __cpuinit platform_cpu_die(unsigned int cpu)
 	if (spurious)
 		pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
 }
-
-int platform_cpu_disable(unsigned int cpu)
-{
-	/*
-	 * we don't allow CPU 0 to be shutdown (it is still too special
-	 * e.g. clock tick interrupts)
-	 */
-	return cpu == 0 ? -EPERM : 0;
-}
diff --git a/arch/arm/mach-spear13xx/include/mach/generic.h b/arch/arm/mach-spear13xx/include/mach/generic.h
index dac57fd..c33f4d9 100644
--- a/arch/arm/mach-spear13xx/include/mach/generic.h
+++ b/arch/arm/mach-spear13xx/include/mach/generic.h
@@ -33,6 +33,9 @@ void __init spear13xx_l2x0_init(void);
 bool dw_dma_filter(struct dma_chan *chan, void *slave);
 void spear_restart(char, const char *);
 void spear13xx_secondary_startup(void);
+void __cpuinit spear13xx_cpu_die(unsigned int cpu);
+
+extern struct smp_operations spear13xx_smp_ops;
 
 #ifdef CONFIG_MACH_SPEAR1310
 void __init spear1310_clk_init(void);
diff --git a/arch/arm/mach-spear13xx/include/mach/gpio.h b/arch/arm/mach-spear13xx/include/mach/gpio.h
deleted file mode 100644
index 85f1763..0000000
--- a/arch/arm/mach-spear13xx/include/mach/gpio.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * arch/arm/mach-spear13xx/include/mach/gpio.h
- *
- * GPIO macros for SPEAr13xx machine family
- *
- * Copyright (C) 2012 ST Microelectronics
- * Viresh Kumar <viresh.linux@gmail.com>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#ifndef __MACH_GPIO_H
-#define __MACH_GPIO_H
-
-#include <plat/gpio.h>
-
-#endif /* __MACH_GPIO_H */
diff --git a/arch/arm/mach-spear13xx/include/mach/spear.h b/arch/arm/mach-spear13xx/include/mach/spear.h
index 65f27de..07d90ac 100644
--- a/arch/arm/mach-spear13xx/include/mach/spear.h
+++ b/arch/arm/mach-spear13xx/include/mach/spear.h
@@ -17,26 +17,26 @@
 #include <asm/memory.h>
 
 #define PERIP_GRP2_BASE				UL(0xB3000000)
-#define VA_PERIP_GRP2_BASE			UL(0xFE000000)
+#define VA_PERIP_GRP2_BASE			IOMEM(0xFE000000)
 #define MCIF_SDHCI_BASE				UL(0xB3000000)
 #define SYSRAM0_BASE				UL(0xB3800000)
-#define VA_SYSRAM0_BASE				UL(0xFE800000)
+#define VA_SYSRAM0_BASE				IOMEM(0xFE800000)
 #define SYS_LOCATION				(VA_SYSRAM0_BASE + 0x600)
 
 #define PERIP_GRP1_BASE				UL(0xE0000000)
-#define VA_PERIP_GRP1_BASE			UL(0xFD000000)
+#define VA_PERIP_GRP1_BASE			IOMEM(0xFD000000)
 #define UART_BASE				UL(0xE0000000)
-#define VA_UART_BASE				UL(0xFD000000)
+#define VA_UART_BASE				IOMEM(0xFD000000)
 #define SSP_BASE				UL(0xE0100000)
 #define MISC_BASE				UL(0xE0700000)
-#define VA_MISC_BASE				IOMEM(UL(0xFD700000))
+#define VA_MISC_BASE				IOMEM(0xFD700000)
 
 #define A9SM_AND_MPMC_BASE			UL(0xEC000000)
-#define VA_A9SM_AND_MPMC_BASE			UL(0xFC000000)
+#define VA_A9SM_AND_MPMC_BASE			IOMEM(0xFC000000)
 
 /* A9SM peripheral offsets */
 #define A9SM_PERIP_BASE				UL(0xEC800000)
-#define VA_A9SM_PERIP_BASE			UL(0xFC800000)
+#define VA_A9SM_PERIP_BASE			IOMEM(0xFC800000)
 #define VA_SCU_BASE				(VA_A9SM_PERIP_BASE + 0x00)
 
 #define L2CC_BASE				UL(0xED000000)
diff --git a/arch/arm/mach-spear13xx/platsmp.c b/arch/arm/mach-spear13xx/platsmp.c
index f5d07f2..2eaa3fa 100644
--- a/arch/arm/mach-spear13xx/platsmp.c
+++ b/arch/arm/mach-spear13xx/platsmp.c
@@ -19,18 +19,13 @@
 #include <asm/hardware/gic.h>
 #include <asm/smp_scu.h>
 #include <mach/spear.h>
+#include <mach/generic.h>
 
-/*
- * control for which core is the next to come out of the secondary
- * boot "holding pen"
- */
-volatile int __cpuinitdata pen_release = -1;
 static DEFINE_SPINLOCK(boot_lock);
 
 static void __iomem *scu_base = IOMEM(VA_SCU_BASE);
-extern void spear13xx_secondary_startup(void);
 
-void __cpuinit platform_secondary_init(unsigned int cpu)
+static void __cpuinit spear13xx_secondary_init(unsigned int cpu)
 {
 	/*
 	 * if any interrupts are already enabled for the primary
@@ -53,7 +48,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
 	spin_unlock(&boot_lock);
 }
 
-int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
+static int __cpuinit spear13xx_boot_secondary(unsigned int cpu, struct task_struct *idle)
 {
 	unsigned long timeout;
 
@@ -97,7 +92,7 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
  * Initialise the CPU possible map early - this describes the CPUs
  * which may be present or become present in the system.
  */
-void __init smp_init_cpus(void)
+static void __init spear13xx_smp_init_cpus(void)
 {
 	unsigned int i, ncores = scu_get_core_count(scu_base);
 
@@ -113,7 +108,7 @@ void __init smp_init_cpus(void)
 	set_smp_cross_call(gic_raise_softirq);
 }
 
-void __init platform_smp_prepare_cpus(unsigned int max_cpus)
+static void __init spear13xx_smp_prepare_cpus(unsigned int max_cpus)
 {
 
 	scu_enable(scu_base);
@@ -125,3 +120,13 @@ void __init platform_smp_prepare_cpus(unsigned int max_cpus)
 	 */
 	__raw_writel(virt_to_phys(spear13xx_secondary_startup), SYS_LOCATION);
 }
+
+struct smp_operations spear13xx_smp_ops __initdata = {
+       .smp_init_cpus		= spear13xx_smp_init_cpus,
+       .smp_prepare_cpus	= spear13xx_smp_prepare_cpus,
+       .smp_secondary_init	= spear13xx_secondary_init,
+       .smp_boot_secondary	= spear13xx_boot_secondary,
+#ifdef CONFIG_HOTPLUG_CPU
+       .cpu_die			= spear13xx_cpu_die,
+#endif
+};
diff --git a/arch/arm/mach-spear13xx/spear1310.c b/arch/arm/mach-spear13xx/spear1310.c
index 732d29b..9fbbfc5 100644
--- a/arch/arm/mach-spear13xx/spear1310.c
+++ b/arch/arm/mach-spear13xx/spear1310.c
@@ -78,6 +78,7 @@ static void __init spear1310_map_io(void)
 }
 
 DT_MACHINE_START(SPEAR1310_DT, "ST SPEAr1310 SoC with Flattened Device Tree")
+	.smp		=	smp_ops(spear13xx_smp_ops),
 	.map_io		=	spear1310_map_io,
 	.init_irq	=	spear13xx_dt_init_irq,
 	.handle_irq	=	gic_handle_irq,
diff --git a/arch/arm/mach-spear13xx/spear1340.c b/arch/arm/mach-spear13xx/spear1340.c
index 81e4ed7..081014f 100644
--- a/arch/arm/mach-spear13xx/spear1340.c
+++ b/arch/arm/mach-spear13xx/spear1340.c
@@ -182,6 +182,7 @@ static const char * const spear1340_dt_board_compat[] = {
 };
 
 DT_MACHINE_START(SPEAR1340_DT, "ST SPEAr1340 SoC with Flattened Device Tree")
+	.smp		=	smp_ops(spear13xx_smp_ops),
 	.map_io		=	spear13xx_map_io,
 	.init_irq	=	spear13xx_dt_init_irq,
 	.handle_irq	=	gic_handle_irq,
diff --git a/arch/arm/mach-spear13xx/spear13xx.c b/arch/arm/mach-spear13xx/spear13xx.c
index cf936b1..e106488 100644
--- a/arch/arm/mach-spear13xx/spear13xx.c
+++ b/arch/arm/mach-spear13xx/spear13xx.c
@@ -114,17 +114,17 @@ void __init spear13xx_l2x0_init(void)
  */
 struct map_desc spear13xx_io_desc[] __initdata = {
 	{
-		.virtual	= VA_PERIP_GRP2_BASE,
+		.virtual	= (unsigned long)VA_PERIP_GRP2_BASE,
 		.pfn		= __phys_to_pfn(PERIP_GRP2_BASE),
 		.length		= SZ_16M,
 		.type		= MT_DEVICE
 	}, {
-		.virtual	= VA_PERIP_GRP1_BASE,
+		.virtual	= (unsigned long)VA_PERIP_GRP1_BASE,
 		.pfn		= __phys_to_pfn(PERIP_GRP1_BASE),
 		.length		= SZ_16M,
 		.type		= MT_DEVICE
 	}, {
-		.virtual	= VA_A9SM_AND_MPMC_BASE,
+		.virtual	= (unsigned long)VA_A9SM_AND_MPMC_BASE,
 		.pfn		= __phys_to_pfn(A9SM_AND_MPMC_BASE),
 		.length		= SZ_16M,
 		.type		= MT_DEVICE
diff --git a/arch/arm/mach-spear3xx/Makefile.boot b/arch/arm/mach-spear3xx/Makefile.boot
index d93e217..4674a4c 100644
--- a/arch/arm/mach-spear3xx/Makefile.boot
+++ b/arch/arm/mach-spear3xx/Makefile.boot
@@ -1,7 +1,3 @@
 zreladdr-y	+= 0x00008000
 params_phys-y	:= 0x00000100
 initrd_phys-y	:= 0x00800000
-
-dtb-$(CONFIG_MACH_SPEAR300)	+= spear300-evb.dtb
-dtb-$(CONFIG_MACH_SPEAR310)	+= spear310-evb.dtb
-dtb-$(CONFIG_MACH_SPEAR320)	+= spear320-evb.dtb
diff --git a/arch/arm/mach-spear3xx/include/mach/gpio.h b/arch/arm/mach-spear3xx/include/mach/gpio.h
deleted file mode 100644
index 2ac74c6..0000000
--- a/arch/arm/mach-spear3xx/include/mach/gpio.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * arch/arm/mach-spear3xx/include/mach/gpio.h
- *
- * GPIO macros for SPEAr3xx machine family
- *
- * Copyright (C) 2009 ST Microelectronics
- * Viresh Kumar<viresh.linux@gmail.com>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#ifndef __MACH_GPIO_H
-#define __MACH_GPIO_H
-
-#include <plat/gpio.h>
-
-#endif /* __MACH_GPIO_H */
diff --git a/arch/arm/mach-spear6xx/Makefile.boot b/arch/arm/mach-spear6xx/Makefile.boot
index af493da..4674a4c 100644
--- a/arch/arm/mach-spear6xx/Makefile.boot
+++ b/arch/arm/mach-spear6xx/Makefile.boot
@@ -1,5 +1,3 @@
 zreladdr-y	+= 0x00008000
 params_phys-y	:= 0x00000100
 initrd_phys-y	:= 0x00800000
-
-dtb-$(CONFIG_BOARD_SPEAR600_DT)	+= spear600-evb.dtb
diff --git a/arch/arm/mach-spear6xx/include/mach/gpio.h b/arch/arm/mach-spear6xx/include/mach/gpio.h
deleted file mode 100644
index d42cefc..0000000
--- a/arch/arm/mach-spear6xx/include/mach/gpio.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * arch/arm/mach-spear6xx/include/mach/gpio.h
- *
- * GPIO macros for SPEAr6xx machine family
- *
- * Copyright (C) 2009 ST Microelectronics
- * Viresh Kumar <viresh.linux@gmail.com>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#ifndef __MACH_GPIO_H
-#define __MACH_GPIO_H
-
-#include <plat/gpio.h>
-
-#endif /* __MACH_GPIO_H */
diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig
index 9077aaa..5f3c03b 100644
--- a/arch/arm/mach-tegra/Kconfig
+++ b/arch/arm/mach-tegra/Kconfig
@@ -34,7 +34,6 @@ config ARCH_TEGRA_3x_SOC
 	select USB_ARCH_HAS_EHCI if USB_SUPPORT
 	select USB_ULPI if USB
 	select USB_ULPI_VIEWPORT if USB_SUPPORT
-	select USE_OF
 	select ARM_ERRATA_743622
 	select ARM_ERRATA_751472
 	select ARM_ERRATA_754322
@@ -60,25 +59,6 @@ config TEGRA_AHB
 
 comment "Tegra board type"
 
-config MACH_HARMONY
-       bool "Harmony board"
-       depends on ARCH_TEGRA_2x_SOC
-       help
-         Support for nVidia Harmony development platform
-
-config MACH_PAZ00
-       bool "Paz00 board"
-       depends on ARCH_TEGRA_2x_SOC
-       help
-         Support for the Toshiba AC100/Dynabook AZ netbook
-
-config MACH_TRIMSLICE
-       bool "TrimSlice board"
-       depends on ARCH_TEGRA_2x_SOC
-       select TEGRA_PCI
-       help
-         Support for CompuLab TrimSlice platform
-
 choice
         prompt "Default low-level debug console UART"
         default TEGRA_DEBUG_UART_NONE
@@ -130,13 +110,6 @@ config TEGRA_DEBUG_UART_AUTO_SCRATCH
 
 endchoice
 
-config TEGRA_SYSTEM_DMA
-	bool "Enable system DMA driver for NVIDIA Tegra SoCs"
-	default y
-	help
-	  Adds system DMA functionality for NVIDIA Tegra SoCs, used by
-	  several Tegra device drivers
-
 config TEGRA_EMC_SCALING_ENABLE
 	bool "Enable scaling the memory frequency"
 
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
index c3d7303..9aa653b 100644
--- a/arch/arm/mach-tegra/Makefile
+++ b/arch/arm/mach-tegra/Makefile
@@ -1,6 +1,4 @@
-obj-y                                   += board-pinmux.o
 obj-y                                   += common.o
-obj-y                                   += devices.o
 obj-y                                   += io.o
 obj-y                                   += irq.o
 obj-y                                   += clock.o
@@ -12,27 +10,22 @@ obj-y					+= powergate.o
 obj-y					+= apbio.o
 obj-$(CONFIG_CPU_IDLE)			+= cpuidle.o
 obj-$(CONFIG_CPU_IDLE)			+= sleep.o
-obj-$(CONFIG_ARCH_TEGRA_2x_SOC)         += tegra2_clocks.o
+obj-$(CONFIG_ARCH_TEGRA_2x_SOC)         += tegra20_clocks.o
+obj-$(CONFIG_ARCH_TEGRA_2x_SOC)         += tegra20_clocks_data.o
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)		+= tegra2_emc.o
+obj-$(CONFIG_ARCH_TEGRA_2x_SOC)		+= sleep-t20.o
 obj-$(CONFIG_ARCH_TEGRA_3x_SOC)		+= tegra30_clocks.o
+obj-$(CONFIG_ARCH_TEGRA_3x_SOC)		+= tegra30_clocks_data.o
+obj-$(CONFIG_ARCH_TEGRA_3x_SOC)		+= sleep-t30.o
 obj-$(CONFIG_SMP)			+= platsmp.o headsmp.o
 obj-$(CONFIG_SMP)                       += reset.o
 obj-$(CONFIG_HOTPLUG_CPU)               += hotplug.o
-obj-$(CONFIG_TEGRA_SYSTEM_DMA)		+= dma.o
 obj-$(CONFIG_CPU_FREQ)                  += cpu-tegra.o
 obj-$(CONFIG_TEGRA_PCI)			+= pcie.o
-obj-$(CONFIG_USB_SUPPORT)		+= usb_phy.o
 
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)		+= board-dt-tegra20.o
 obj-$(CONFIG_ARCH_TEGRA_3x_SOC)		+= board-dt-tegra30.o
 
-obj-$(CONFIG_MACH_HARMONY)              += board-harmony.o
-obj-$(CONFIG_MACH_HARMONY)              += board-harmony-pinmux.o
-obj-$(CONFIG_MACH_HARMONY)              += board-harmony-pcie.o
-obj-$(CONFIG_MACH_HARMONY)              += board-harmony-power.o
+obj-$(CONFIG_ARCH_TEGRA_2x_SOC)		+= board-harmony-pcie.o
 
-obj-$(CONFIG_MACH_PAZ00)		+= board-paz00.o
-obj-$(CONFIG_MACH_PAZ00)		+= board-paz00-pinmux.o
-
-obj-$(CONFIG_MACH_TRIMSLICE)            += board-trimslice.o
-obj-$(CONFIG_MACH_TRIMSLICE)            += board-trimslice-pinmux.o
+obj-$(CONFIG_ARCH_TEGRA_2x_SOC)		+= board-paz00.o
diff --git a/arch/arm/mach-tegra/Makefile.boot b/arch/arm/mach-tegra/Makefile.boot
index 7a1bb62..2943381 100644
--- a/arch/arm/mach-tegra/Makefile.boot
+++ b/arch/arm/mach-tegra/Makefile.boot
@@ -1,11 +1,3 @@
 zreladdr-$(CONFIG_ARCH_TEGRA_2x_SOC)	+= 0x00008000
 params_phys-$(CONFIG_ARCH_TEGRA_2x_SOC)	:= 0x00000100
 initrd_phys-$(CONFIG_ARCH_TEGRA_2x_SOC)	:= 0x00800000
-
-dtb-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20-harmony.dtb
-dtb-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20-paz00.dtb
-dtb-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20-seaboard.dtb
-dtb-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20-trimslice.dtb
-dtb-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20-ventana.dtb
-dtb-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20-whistler.dtb
-dtb-$(CONFIG_ARCH_TEGRA_3x_SOC) += tegra30-cardhu.dtb
diff --git a/arch/arm/mach-tegra/apbio.c b/arch/arm/mach-tegra/apbio.c
index dc0fe38..b5015d0 100644
--- a/arch/arm/mach-tegra/apbio.c
+++ b/arch/arm/mach-tegra/apbio.c
@@ -28,7 +28,7 @@
 
 #include "apbio.h"
 
-#if defined(CONFIG_TEGRA_SYSTEM_DMA) || defined(CONFIG_TEGRA20_APB_DMA)
+#if defined(CONFIG_TEGRA20_APB_DMA)
 static DEFINE_MUTEX(tegra_apb_dma_lock);
 static u32 *tegra_apb_bb;
 static dma_addr_t tegra_apb_bb_phys;
@@ -37,121 +37,6 @@ static DECLARE_COMPLETION(tegra_apb_wait);
 static u32 tegra_apb_readl_direct(unsigned long offset);
 static void tegra_apb_writel_direct(u32 value, unsigned long offset);
 
-#if defined(CONFIG_TEGRA_SYSTEM_DMA)
-static struct tegra_dma_channel *tegra_apb_dma;
-
-bool tegra_apb_init(void)
-{
-	struct tegra_dma_channel *ch;
-
-	mutex_lock(&tegra_apb_dma_lock);
-
-	/* Check to see if we raced to setup */
-	if (tegra_apb_dma)
-		goto out;
-
-	ch = tegra_dma_allocate_channel(TEGRA_DMA_MODE_ONESHOT |
-		TEGRA_DMA_SHARED);
-
-	if (!ch)
-		goto out_fail;
-
-	tegra_apb_bb = dma_alloc_coherent(NULL, sizeof(u32),
-		&tegra_apb_bb_phys, GFP_KERNEL);
-	if (!tegra_apb_bb) {
-		pr_err("%s: can not allocate bounce buffer\n", __func__);
-		tegra_dma_free_channel(ch);
-		goto out_fail;
-	}
-
-	tegra_apb_dma = ch;
-out:
-	mutex_unlock(&tegra_apb_dma_lock);
-	return true;
-
-out_fail:
-	mutex_unlock(&tegra_apb_dma_lock);
-	return false;
-}
-
-static void apb_dma_complete(struct tegra_dma_req *req)
-{
-	complete(&tegra_apb_wait);
-}
-
-static u32 tegra_apb_readl_using_dma(unsigned long offset)
-{
-	struct tegra_dma_req req;
-	int ret;
-
-	if (!tegra_apb_dma && !tegra_apb_init())
-		return tegra_apb_readl_direct(offset);
-
-	mutex_lock(&tegra_apb_dma_lock);
-	req.complete = apb_dma_complete;
-	req.to_memory = 1;
-	req.dest_addr = tegra_apb_bb_phys;
-	req.dest_bus_width = 32;
-	req.dest_wrap = 1;
-	req.source_addr = offset;
-	req.source_bus_width = 32;
-	req.source_wrap = 4;
-	req.req_sel = TEGRA_DMA_REQ_SEL_CNTR;
-	req.size = 4;
-
-	INIT_COMPLETION(tegra_apb_wait);
-
-	tegra_dma_enqueue_req(tegra_apb_dma, &req);
-
-	ret = wait_for_completion_timeout(&tegra_apb_wait,
-		msecs_to_jiffies(50));
-
-	if (WARN(ret == 0, "apb read dma timed out")) {
-		tegra_dma_dequeue_req(tegra_apb_dma, &req);
-		*(u32 *)tegra_apb_bb = 0;
-	}
-
-	mutex_unlock(&tegra_apb_dma_lock);
-	return *((u32 *)tegra_apb_bb);
-}
-
-static void tegra_apb_writel_using_dma(u32 value, unsigned long offset)
-{
-	struct tegra_dma_req req;
-	int ret;
-
-	if (!tegra_apb_dma && !tegra_apb_init()) {
-		tegra_apb_writel_direct(value, offset);
-		return;
-	}
-
-	mutex_lock(&tegra_apb_dma_lock);
-	*((u32 *)tegra_apb_bb) = value;
-	req.complete = apb_dma_complete;
-	req.to_memory = 0;
-	req.dest_addr = offset;
-	req.dest_wrap = 4;
-	req.dest_bus_width = 32;
-	req.source_addr = tegra_apb_bb_phys;
-	req.source_bus_width = 32;
-	req.source_wrap = 1;
-	req.req_sel = TEGRA_DMA_REQ_SEL_CNTR;
-	req.size = 4;
-
-	INIT_COMPLETION(tegra_apb_wait);
-
-	tegra_dma_enqueue_req(tegra_apb_dma, &req);
-
-	ret = wait_for_completion_timeout(&tegra_apb_wait,
-		msecs_to_jiffies(50));
-
-	if (WARN(ret == 0, "apb write dma timed out"))
-		tegra_dma_dequeue_req(tegra_apb_dma, &req);
-
-	mutex_unlock(&tegra_apb_dma_lock);
-}
-
-#else
 static struct dma_chan *tegra_apb_dma_chan;
 static struct dma_slave_config dma_sconfig;
 
@@ -279,7 +164,6 @@ static void tegra_apb_writel_using_dma(u32 value, unsigned long offset)
 		pr_err("error in writing offset 0x%08lx using dma\n", offset);
 	mutex_unlock(&tegra_apb_dma_lock);
 }
-#endif
 #else
 #define tegra_apb_readl_using_dma tegra_apb_readl_direct
 #define tegra_apb_writel_using_dma tegra_apb_writel_direct
@@ -293,12 +177,12 @@ static apbio_write_fptr apbio_write;
 
 static u32 tegra_apb_readl_direct(unsigned long offset)
 {
-	return readl(IO_TO_VIRT(offset));
+	return readl(IO_ADDRESS(offset));
 }
 
 static void tegra_apb_writel_direct(u32 value, unsigned long offset)
 {
-	writel(value, IO_TO_VIRT(offset));
+	writel(value, IO_ADDRESS(offset));
 }
 
 void tegra_apb_io_init(void)
diff --git a/arch/arm/mach-tegra/board-dt-tegra20.c b/arch/arm/mach-tegra/board-dt-tegra20.c
index c099963..57e235f 100644
--- a/arch/arm/mach-tegra/board-dt-tegra20.c
+++ b/arch/arm/mach-tegra/board-dt-tegra20.c
@@ -28,9 +28,11 @@
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/pda_power.h>
+#include <linux/platform_data/tegra_usb.h>
 #include <linux/io.h>
 #include <linux/i2c.h>
 #include <linux/i2c-tegra.h>
+#include <linux/usb/tegra_usb_phy.h>
 
 #include <asm/hardware/gic.h>
 #include <asm/mach-types.h>
@@ -42,9 +44,32 @@
 #include <mach/irqs.h>
 
 #include "board.h"
-#include "board-harmony.h"
 #include "clock.h"
-#include "devices.h"
+#include "common.h"
+
+struct tegra_ehci_platform_data tegra_ehci1_pdata = {
+	.operating_mode = TEGRA_USB_OTG,
+	.power_down_on_bus_suspend = 1,
+	.vbus_gpio = -1,
+};
+
+struct tegra_ulpi_config tegra_ehci2_ulpi_phy_config = {
+	.reset_gpio = -1,
+	.clk = "cdev2",
+};
+
+struct tegra_ehci_platform_data tegra_ehci2_pdata = {
+	.phy_config = &tegra_ehci2_ulpi_phy_config,
+	.operating_mode = TEGRA_USB_HOST,
+	.power_down_on_bus_suspend = 1,
+	.vbus_gpio = -1,
+};
+
+struct tegra_ehci_platform_data tegra_ehci3_pdata = {
+	.operating_mode = TEGRA_USB_HOST,
+	.power_down_on_bus_suspend = 1,
+	.vbus_gpio = -1,
+};
 
 struct of_dev_auxdata tegra20_auxdata_lookup[] __initdata = {
 	OF_DEV_AUXDATA("nvidia,tegra20-sdhci", TEGRA_SDMMC1_BASE, "sdhci-tegra.0", NULL),
@@ -71,6 +96,7 @@ struct of_dev_auxdata tegra20_auxdata_lookup[] __initdata = {
 
 static __initdata struct tegra_clk_init_table tegra_dt_clk_init_table[] = {
 	/* name		parent		rate		enabled */
+	{ "uarta",	"pll_p",	216000000,	true },
 	{ "uartd",	"pll_p",	216000000,	true },
 	{ "usbd",	"clk_m",	12000000,	false },
 	{ "usb2",	"clk_m",	12000000,	false },
@@ -95,54 +121,40 @@ static void __init tegra_dt_init(void)
 				tegra20_auxdata_lookup, NULL);
 }
 
-#ifdef CONFIG_MACH_TRIMSLICE
 static void __init trimslice_init(void)
 {
+#ifdef CONFIG_TEGRA_PCI
 	int ret;
 
 	ret = tegra_pcie_init(true, true);
 	if (ret)
 		pr_err("tegra_pci_init() failed: %d\n", ret);
-}
 #endif
+}
 
-#ifdef CONFIG_MACH_HARMONY
 static void __init harmony_init(void)
 {
+#ifdef CONFIG_TEGRA_PCI
 	int ret;
 
-	ret = harmony_regulator_init();
-	if (ret) {
-		pr_err("harmony_regulator_init() failed: %d\n", ret);
-		return;
-	}
-
 	ret = harmony_pcie_init();
 	if (ret)
 		pr_err("harmony_pcie_init() failed: %d\n", ret);
-}
 #endif
+}
 
-#ifdef CONFIG_MACH_PAZ00
 static void __init paz00_init(void)
 {
 	tegra_paz00_wifikill_init();
 }
-#endif
 
 static struct {
 	char *machine;
 	void (*init)(void);
 } board_init_funcs[] = {
-#ifdef CONFIG_MACH_TRIMSLICE
 	{ "compulab,trimslice", trimslice_init },
-#endif
-#ifdef CONFIG_MACH_HARMONY
 	{ "nvidia,harmony", harmony_init },
-#endif
-#ifdef CONFIG_MACH_PAZ00
 	{ "compal,paz00", paz00_init },
-#endif
 };
 
 static void __init tegra_dt_init_late(void)
@@ -166,6 +178,7 @@ static const char *tegra20_dt_board_compat[] = {
 
 DT_MACHINE_START(TEGRA_DT, "nVidia Tegra20 (Flattened Device Tree)")
 	.map_io		= tegra_map_common_io,
+	.smp		= smp_ops(tegra_smp_ops),
 	.init_early	= tegra20_init_early,
 	.init_irq	= tegra_dt_init_irq,
 	.handle_irq	= gic_handle_irq,
diff --git a/arch/arm/mach-tegra/board-dt-tegra30.c b/arch/arm/mach-tegra/board-dt-tegra30.c
index 53bf60f..e4a676d 100644
--- a/arch/arm/mach-tegra/board-dt-tegra30.c
+++ b/arch/arm/mach-tegra/board-dt-tegra30.c
@@ -37,6 +37,7 @@
 
 #include "board.h"
 #include "clock.h"
+#include "common.h"
 
 struct of_dev_auxdata tegra30_auxdata_lookup[] __initdata = {
 	OF_DEV_AUXDATA("nvidia,tegra20-sdhci", 0x78000000, "sdhci-tegra.0", NULL),
@@ -83,6 +84,7 @@ static const char *tegra30_dt_board_compat[] = {
 };
 
 DT_MACHINE_START(TEGRA30_DT, "NVIDIA Tegra30 (Flattened Device Tree)")
+	.smp		= smp_ops(tegra_smp_ops),
 	.map_io		= tegra_map_common_io,
 	.init_early	= tegra30_init_early,
 	.init_irq	= tegra_dt_init_irq,
diff --git a/arch/arm/mach-tegra/board-harmony-pcie.c b/arch/arm/mach-tegra/board-harmony-pcie.c
index e8c3fda..3cdc1bb 100644
--- a/arch/arm/mach-tegra/board-harmony-pcie.c
+++ b/arch/arm/mach-tegra/board-harmony-pcie.c
@@ -18,35 +18,57 @@
 #include <linux/kernel.h>
 #include <linux/gpio.h>
 #include <linux/err.h>
+#include <linux/of_gpio.h>
 #include <linux/regulator/consumer.h>
 
 #include <asm/mach-types.h>
 
 #include "board.h"
-#include "board-harmony.h"
 
 #ifdef CONFIG_TEGRA_PCI
 
 int __init harmony_pcie_init(void)
 {
+	struct device_node *np;
+	int en_vdd_1v05;
 	struct regulator *regulator = NULL;
 	int err;
 
-	err = gpio_request(TEGRA_GPIO_EN_VDD_1V05_GPIO, "EN_VDD_1V05");
-	if (err)
+	np = of_find_node_by_path("/regulators/regulator@3");
+	if (!np) {
+		pr_err("%s: of_find_node_by_path failed\n", __func__);
+		return -ENODEV;
+	}
+
+	en_vdd_1v05 = of_get_named_gpio(np, "gpio", 0);
+	if (en_vdd_1v05 < 0) {
+		pr_err("%s: of_get_named_gpio failed: %d\n", __func__,
+		       en_vdd_1v05);
+		return en_vdd_1v05;
+	}
+
+	err = gpio_request(en_vdd_1v05, "EN_VDD_1V05");
+	if (err) {
+		pr_err("%s: gpio_request failed: %d\n", __func__, err);
 		return err;
+	}
 
-	gpio_direction_output(TEGRA_GPIO_EN_VDD_1V05_GPIO, 1);
+	gpio_direction_output(en_vdd_1v05, 1);
 
-	regulator = regulator_get(NULL, "pex_clk");
-	if (IS_ERR_OR_NULL(regulator))
+	regulator = regulator_get(NULL, "vdd_ldo0,vddio_pex_clk");
+	if (IS_ERR_OR_NULL(regulator)) {
+		pr_err("%s: regulator_get failed: %d\n", __func__,
+		       (int)PTR_ERR(regulator));
 		goto err_reg;
+	}
 
 	regulator_enable(regulator);
 
 	err = tegra_pcie_init(true, true);
-	if (err)
+	if (err) {
+		pr_err("%s: tegra_pcie_init failed: %d\n", __func__, err);
 		goto err_pcie;
+	}
 
 	return 0;
 
@@ -54,20 +76,9 @@ err_pcie:
 	regulator_disable(regulator);
 	regulator_put(regulator);
 err_reg:
-	gpio_free(TEGRA_GPIO_EN_VDD_1V05_GPIO);
+	gpio_free(en_vdd_1v05);
 
 	return err;
 }
 
-static int __init harmony_pcie_initcall(void)
-{
-	if (!machine_is_harmony())
-		return 0;
-
-	return harmony_pcie_init();
-}
-
-/* PCI should be initialized after I2C, mfd and regulators */
-subsys_initcall_sync(harmony_pcie_initcall);
-
 #endif
diff --git a/arch/arm/mach-tegra/board-harmony-pinmux.c b/arch/arm/mach-tegra/board-harmony-pinmux.c
deleted file mode 100644
index 83d420f..0000000
--- a/arch/arm/mach-tegra/board-harmony-pinmux.c
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * arch/arm/mach-tegra/board-harmony-pinmux.c
- *
- * Copyright (C) 2010 Google, Inc.
- * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/kernel.h>
-
-#include "board-harmony.h"
-#include "board-pinmux.h"
-
-static struct pinctrl_map harmony_map[] = {
-	TEGRA_MAP_MUXCONF("ata",   "ide",           none, driven),
-	TEGRA_MAP_MUXCONF("atb",   "sdio4",         none, driven),
-	TEGRA_MAP_MUXCONF("atc",   "nand",          none, driven),
-	TEGRA_MAP_MUXCONF("atd",   "gmi",           none, driven),
-	TEGRA_MAP_MUXCONF("ate",   "gmi",           none, driven),
-	TEGRA_MAP_MUXCONF("cdev1", "plla_out",      none, driven),
-	TEGRA_MAP_MUXCONF("cdev2", "pllp_out4",     down, tristate),
-	TEGRA_MAP_MUXCONF("crtp",  "crt",           none, tristate),
-	TEGRA_MAP_MUXCONF("csus",  "vi_sensor_clk", down, tristate),
-	TEGRA_MAP_MUXCONF("dap1",  "dap1",          none, driven),
-	TEGRA_MAP_MUXCONF("dap2",  "dap2",          none, tristate),
-	TEGRA_MAP_MUXCONF("dap3",  "dap3",          none, tristate),
-	TEGRA_MAP_MUXCONF("dap4",  "dap4",          none, tristate),
-	TEGRA_MAP_MUXCONF("ddc",   "i2c2",          up,   driven),
-	TEGRA_MAP_MUXCONF("dta",   "sdio2",         up,   driven),
-	TEGRA_MAP_MUXCONF("dtb",   "rsvd1",         none, driven),
-	TEGRA_MAP_MUXCONF("dtc",   "rsvd1",         none, tristate),
-	TEGRA_MAP_MUXCONF("dtd",   "sdio2",         up,   driven),
-	TEGRA_MAP_MUXCONF("dte",   "rsvd1",         none, tristate),
-	TEGRA_MAP_MUXCONF("dtf",   "i2c3",          none, tristate),
-	TEGRA_MAP_MUXCONF("gma",   "sdio4",         none, driven),
-	TEGRA_MAP_MUXCONF("gmb",   "gmi",           none, driven),
-	TEGRA_MAP_MUXCONF("gmc",   "uartd",         none, driven),
-	TEGRA_MAP_MUXCONF("gmd",   "gmi",           none, driven),
-	TEGRA_MAP_MUXCONF("gme",   "sdio4",         none, driven),
-	TEGRA_MAP_MUXCONF("gpu",   "gmi",           none, tristate),
-	TEGRA_MAP_MUXCONF("gpu7",  "rtck",          none, driven),
-	TEGRA_MAP_MUXCONF("gpv",   "pcie",          none, driven),
-	TEGRA_MAP_MUXCONF("hdint", "hdmi",          na,   tristate),
-	TEGRA_MAP_MUXCONF("i2cp",  "i2cp",          none, driven),
-	TEGRA_MAP_MUXCONF("irrx",  "uarta",         up,   tristate),
-	TEGRA_MAP_MUXCONF("irtx",  "uarta",         up,   tristate),
-	TEGRA_MAP_MUXCONF("kbca",  "kbc",           up,   driven),
-	TEGRA_MAP_MUXCONF("kbcb",  "kbc",           up,   driven),
-	TEGRA_MAP_MUXCONF("kbcc",  "kbc",           up,   driven),
-	TEGRA_MAP_MUXCONF("kbcd",  "kbc",           up,   driven),
-	TEGRA_MAP_MUXCONF("kbce",  "kbc",           up,   driven),
-	TEGRA_MAP_MUXCONF("kbcf",  "kbc",           up,   driven),
-	TEGRA_MAP_MUXCONF("lcsn",  "displaya",      na,   tristate),
-	TEGRA_MAP_MUXCONF("ld0",   "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("ld1",   "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("ld10",  "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("ld11",  "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("ld12",  "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("ld13",  "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("ld14",  "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("ld15",  "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("ld16",  "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("ld17",  "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("ld2",   "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("ld3",   "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("ld4",   "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("ld5",   "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("ld6",   "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("ld7",   "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("ld8",   "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("ld9",   "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("ldc",   "displaya",      na,   tristate),
-	TEGRA_MAP_MUXCONF("ldi",   "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("lhp0",  "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("lhp1",  "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("lhp2",  "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("lhs",   "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("lm0",   "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("lm1",   "displaya",      na,   tristate),
-	TEGRA_MAP_MUXCONF("lpp",   "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("lpw0",  "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("lpw1",  "displaya",      na,   tristate),
-	TEGRA_MAP_MUXCONF("lpw2",  "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("lsc0",  "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("lsc1",  "displaya",      na,   tristate),
-	TEGRA_MAP_MUXCONF("lsck",  "displaya",      na,   tristate),
-	TEGRA_MAP_MUXCONF("lsda",  "displaya",      na,   tristate),
-	TEGRA_MAP_MUXCONF("lsdi",  "displaya",      na,   tristate),
-	TEGRA_MAP_MUXCONF("lspi",  "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("lvp0",  "displaya",      na,   tristate),
-	TEGRA_MAP_MUXCONF("lvp1",  "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("lvs",   "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("owc",   "rsvd2",         na,   tristate),
-	TEGRA_MAP_MUXCONF("pmc",   "pwr_on",        na,   driven),
-	TEGRA_MAP_MUXCONF("pta",   "hdmi",          none, driven),
-	TEGRA_MAP_MUXCONF("rm",    "i2c1",          none, driven),
-	TEGRA_MAP_MUXCONF("sdb",   "pwm",           na,   tristate),
-	TEGRA_MAP_MUXCONF("sdc",   "pwm",           up,   driven),
-	TEGRA_MAP_MUXCONF("sdd",   "pwm",           up,   tristate),
-	TEGRA_MAP_MUXCONF("sdio1", "sdio1",         none, tristate),
-	TEGRA_MAP_MUXCONF("slxa",  "pcie",          none, driven),
-	TEGRA_MAP_MUXCONF("slxc",  "spdif",         none, tristate),
-	TEGRA_MAP_MUXCONF("slxd",  "spdif",         none, tristate),
-	TEGRA_MAP_MUXCONF("slxk",  "pcie",          none, driven),
-	TEGRA_MAP_MUXCONF("spdi",  "rsvd2",         none, tristate),
-	TEGRA_MAP_MUXCONF("spdo",  "rsvd2",         none, tristate),
-	TEGRA_MAP_MUXCONF("spia",  "gmi",           none, driven),
-	TEGRA_MAP_MUXCONF("spib",  "gmi",           none, driven),
-	TEGRA_MAP_MUXCONF("spic",  "gmi",           up,   tristate),
-	TEGRA_MAP_MUXCONF("spid",  "spi1",          down, tristate),
-	TEGRA_MAP_MUXCONF("spie",  "spi1",          up,   tristate),
-	TEGRA_MAP_MUXCONF("spif",  "spi1",          down, tristate),
-	TEGRA_MAP_MUXCONF("spig",  "spi2_alt",      none, tristate),
-	TEGRA_MAP_MUXCONF("spih",  "spi2_alt",      up,   tristate),
-	TEGRA_MAP_MUXCONF("uaa",   "ulpi",          up,   tristate),
-	TEGRA_MAP_MUXCONF("uab",   "ulpi",          up,   tristate),
-	TEGRA_MAP_MUXCONF("uac",   "rsvd2",         none, tristate),
-	TEGRA_MAP_MUXCONF("uad",   "irda",          up,   tristate),
-	TEGRA_MAP_MUXCONF("uca",   "uartc",         up,   tristate),
-	TEGRA_MAP_MUXCONF("ucb",   "uartc",         up,   tristate),
-	TEGRA_MAP_MUXCONF("uda",   "ulpi",          none, tristate),
-	TEGRA_MAP_CONF("ck32",    none, na),
-	TEGRA_MAP_CONF("ddrc",    none, na),
-	TEGRA_MAP_CONF("pmca",    none, na),
-	TEGRA_MAP_CONF("pmcb",    none, na),
-	TEGRA_MAP_CONF("pmcc",    none, na),
-	TEGRA_MAP_CONF("pmcd",    none, na),
-	TEGRA_MAP_CONF("pmce",    none, na),
-	TEGRA_MAP_CONF("xm2c",    none, na),
-	TEGRA_MAP_CONF("xm2d",    none, na),
-	TEGRA_MAP_CONF("ls",      up,   na),
-	TEGRA_MAP_CONF("lc",      up,   na),
-	TEGRA_MAP_CONF("ld17_0",  down, na),
-	TEGRA_MAP_CONF("ld19_18", down, na),
-	TEGRA_MAP_CONF("ld21_20", down, na),
-	TEGRA_MAP_CONF("ld23_22", down, na),
-};
-
-static struct tegra_board_pinmux_conf conf = {
-	.maps = harmony_map,
-	.map_count = ARRAY_SIZE(harmony_map),
-};
-
-void harmony_pinmux_init(void)
-{
-	tegra_board_pinmux_init(&conf, NULL);
-}
diff --git a/arch/arm/mach-tegra/board-harmony-power.c b/arch/arm/mach-tegra/board-harmony-power.c
deleted file mode 100644
index b7344be..0000000
--- a/arch/arm/mach-tegra/board-harmony-power.c
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright (C) 2010 NVIDIA, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- * 02111-1307, USA
- */
-#include <linux/i2c.h>
-#include <linux/platform_device.h>
-#include <linux/gpio.h>
-#include <linux/regulator/machine.h>
-#include <linux/regulator/fixed.h>
-#include <linux/mfd/tps6586x.h>
-#include <linux/of.h>
-#include <linux/of_i2c.h>
-
-#include <asm/mach-types.h>
-
-#include <mach/irqs.h>
-
-#include "board-harmony.h"
-
-static struct regulator_consumer_supply tps658621_ldo0_supply[] = {
-	REGULATOR_SUPPLY("pex_clk", NULL),
-};
-
-static struct regulator_init_data ldo0_data = {
-	.supply_regulator = "vdd_sm2",
-	.constraints = {
-		.name = "vdd_ldo0",
-		.min_uV = 3300 * 1000,
-		.max_uV = 3300 * 1000,
-		.valid_modes_mask = (REGULATOR_MODE_NORMAL |
-				     REGULATOR_MODE_STANDBY),
-		.valid_ops_mask = (REGULATOR_CHANGE_MODE |
-				   REGULATOR_CHANGE_STATUS |
-				   REGULATOR_CHANGE_VOLTAGE),
-		.apply_uV = 1,
-	},
-	.num_consumer_supplies = ARRAY_SIZE(tps658621_ldo0_supply),
-	.consumer_supplies = tps658621_ldo0_supply,
-};
-
-#define HARMONY_REGULATOR_INIT(_id, _name, _supply, _minmv, _maxmv, _on)\
-	static struct regulator_init_data _id##_data = {		\
-		.supply_regulator = _supply,				\
-		.constraints = {					\
-			.name = _name,					\
-			.min_uV = (_minmv)*1000,			\
-			.max_uV = (_maxmv)*1000,			\
-			.valid_modes_mask = (REGULATOR_MODE_NORMAL |	\
-					     REGULATOR_MODE_STANDBY),	\
-			.valid_ops_mask = (REGULATOR_CHANGE_MODE |	\
-					   REGULATOR_CHANGE_STATUS |	\
-					   REGULATOR_CHANGE_VOLTAGE),	\
-			.always_on = _on,				\
-		},							\
-	}
-
-HARMONY_REGULATOR_INIT(sm0,  "vdd_sm0",  "vdd_sys", 725, 1500, 1);
-HARMONY_REGULATOR_INIT(sm1,  "vdd_sm1",  "vdd_sys", 725, 1500, 1);
-HARMONY_REGULATOR_INIT(sm2,  "vdd_sm2",  "vdd_sys", 3000, 4550, 1);
-HARMONY_REGULATOR_INIT(ldo1, "vdd_ldo1", "vdd_sm2", 725, 1500, 1);
-HARMONY_REGULATOR_INIT(ldo2, "vdd_ldo2", "vdd_sm2", 725, 1500, 0);
-HARMONY_REGULATOR_INIT(ldo3, "vdd_ldo3", "vdd_sm2", 1250, 3300, 1);
-HARMONY_REGULATOR_INIT(ldo4, "vdd_ldo4", "vdd_sm2", 1700, 2475, 1);
-HARMONY_REGULATOR_INIT(ldo5, "vdd_ldo5", NULL,	    1250, 3300, 1);
-HARMONY_REGULATOR_INIT(ldo6, "vdd_ldo6", "vdd_sm2", 1250, 3300, 0);
-HARMONY_REGULATOR_INIT(ldo7, "vdd_ldo7", "vdd_sm2", 1250, 3300, 0);
-HARMONY_REGULATOR_INIT(ldo8, "vdd_ldo8", "vdd_sm2", 1250, 3300, 0);
-HARMONY_REGULATOR_INIT(ldo9, "vdd_ldo9", "vdd_sm2", 1250, 3300, 1);
-
-#define TPS_REG(_id, _data)			\
-	{					\
-		.id = TPS6586X_ID_##_id,	\
-		.name = "tps6586x-regulator",	\
-		.platform_data = _data,		\
-	}
-
-static struct tps6586x_subdev_info tps_devs[] = {
-	TPS_REG(SM_0, &sm0_data),
-	TPS_REG(SM_1, &sm1_data),
-	TPS_REG(SM_2, &sm2_data),
-	TPS_REG(LDO_0, &ldo0_data),
-	TPS_REG(LDO_1, &ldo1_data),
-	TPS_REG(LDO_2, &ldo2_data),
-	TPS_REG(LDO_3, &ldo3_data),
-	TPS_REG(LDO_4, &ldo4_data),
-	TPS_REG(LDO_5, &ldo5_data),
-	TPS_REG(LDO_6, &ldo6_data),
-	TPS_REG(LDO_7, &ldo7_data),
-	TPS_REG(LDO_8, &ldo8_data),
-	TPS_REG(LDO_9, &ldo9_data),
-};
-
-static struct tps6586x_platform_data tps_platform = {
-	.irq_base	= TEGRA_NR_IRQS,
-	.num_subdevs	= ARRAY_SIZE(tps_devs),
-	.subdevs	= tps_devs,
-	.gpio_base	= HARMONY_GPIO_TPS6586X(0),
-};
-
-static struct i2c_board_info __initdata harmony_regulators[] = {
-	{
-		I2C_BOARD_INFO("tps6586x", 0x34),
-		.irq		= INT_EXTERNAL_PMU,
-		.platform_data	= &tps_platform,
-	},
-};
-
-int __init harmony_regulator_init(void)
-{
-	regulator_register_always_on(0, "vdd_sys",
-		NULL, 0, 5000000);
-
-	if (machine_is_harmony()) {
-		i2c_register_board_info(3, harmony_regulators, 1);
-	} else { /* Harmony, booted using device tree */
-		struct device_node *np;
-		struct i2c_adapter *adapter;
-
-		np = of_find_node_by_path("/i2c@7000d000");
-		if (np == NULL) {
-			pr_err("Could not find device_node for DVC I2C\n");
-			return -ENODEV;
-		}
-
-		adapter = of_find_i2c_adapter_by_node(np);
-		if (!adapter) {
-			pr_err("Could not find i2c_adapter for DVC I2C\n");
-			return -ENODEV;
-		}
-
-		i2c_new_device(adapter, harmony_regulators);
-	}
-
-	return 0;
-}
diff --git a/arch/arm/mach-tegra/board-harmony.c b/arch/arm/mach-tegra/board-harmony.c
deleted file mode 100644
index e65e837..0000000
--- a/arch/arm/mach-tegra/board-harmony.c
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * arch/arm/mach-tegra/board-harmony.c
- *
- * Copyright (C) 2010 Google, Inc.
- * Copyright (C) 2011 NVIDIA, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/serial_8250.h>
-#include <linux/of_serial.h>
-#include <linux/clk.h>
-#include <linux/dma-mapping.h>
-#include <linux/pda_power.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-#include <linux/i2c.h>
-
-#include <sound/wm8903.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-#include <asm/hardware/gic.h>
-#include <asm/setup.h>
-
-#include <mach/tegra_wm8903_pdata.h>
-#include <mach/iomap.h>
-#include <mach/irqs.h>
-#include <mach/sdhci.h>
-
-#include "board.h"
-#include "board-harmony.h"
-#include "clock.h"
-#include "devices.h"
-#include "gpio-names.h"
-
-static struct plat_serial8250_port debug_uart_platform_data[] = {
-	{
-		.membase	= IO_ADDRESS(TEGRA_UARTD_BASE),
-		.mapbase	= TEGRA_UARTD_BASE,
-		.irq		= INT_UARTD,
-		.flags		= UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE,
-		.type		= PORT_TEGRA,
-		.handle_break	= tegra_serial_handle_break,
-		.iotype		= UPIO_MEM,
-		.regshift	= 2,
-		.uartclk	= 216000000,
-	}, {
-		.flags		= 0
-	}
-};
-
-static struct platform_device debug_uart = {
-	.name = "serial8250",
-	.id = PLAT8250_DEV_PLATFORM,
-	.dev = {
-		.platform_data = debug_uart_platform_data,
-	},
-};
-
-static struct tegra_wm8903_platform_data harmony_audio_pdata = {
-	.gpio_spkr_en		= TEGRA_GPIO_SPKR_EN,
-	.gpio_hp_det		= TEGRA_GPIO_HP_DET,
-	.gpio_hp_mute		= -1,
-	.gpio_int_mic_en	= TEGRA_GPIO_INT_MIC_EN,
-	.gpio_ext_mic_en	= TEGRA_GPIO_EXT_MIC_EN,
-};
-
-static struct platform_device harmony_audio_device = {
-	.name	= "tegra-snd-wm8903",
-	.id	= 0,
-	.dev	= {
-		.platform_data  = &harmony_audio_pdata,
-	},
-};
-
-static struct wm8903_platform_data harmony_wm8903_pdata = {
-	.irq_active_low = 0,
-	.micdet_cfg = 0,
-	.micdet_delay = 100,
-	.gpio_base = HARMONY_GPIO_WM8903(0),
-	.gpio_cfg = {
-		0,
-		0,
-		WM8903_GPIO_CONFIG_ZERO,
-		0,
-		0,
-	},
-};
-
-static struct i2c_board_info __initdata wm8903_board_info = {
-	I2C_BOARD_INFO("wm8903", 0x1a),
-	.platform_data = &harmony_wm8903_pdata,
-};
-
-static void __init harmony_i2c_init(void)
-{
-	platform_device_register(&tegra_i2c_device1);
-	platform_device_register(&tegra_i2c_device2);
-	platform_device_register(&tegra_i2c_device3);
-	platform_device_register(&tegra_i2c_device4);
-
-	wm8903_board_info.irq = gpio_to_irq(TEGRA_GPIO_CDC_IRQ);
-	i2c_register_board_info(0, &wm8903_board_info, 1);
-}
-
-static struct platform_device *harmony_devices[] __initdata = {
-	&debug_uart,
-	&tegra_sdhci_device1,
-	&tegra_sdhci_device2,
-	&tegra_sdhci_device4,
-	&tegra_ehci3_device,
-	&tegra_i2s_device1,
-	&tegra_das_device,
-	&harmony_audio_device,
-};
-
-static void __init tegra_harmony_fixup(struct tag *tags, char **cmdline,
-	struct meminfo *mi)
-{
-	mi->nr_banks = 2;
-	mi->bank[0].start = PHYS_OFFSET;
-	mi->bank[0].size = 448 * SZ_1M;
-	mi->bank[1].start = SZ_512M;
-	mi->bank[1].size = SZ_512M;
-}
-
-static __initdata struct tegra_clk_init_table harmony_clk_init_table[] = {
-	/* name		parent		rate		enabled */
-	{ "uartd",	"pll_p",	216000000,	true },
-	{ "pll_a",	"pll_p_out1",	56448000,	true },
-	{ "pll_a_out0",	"pll_a",	11289600,	true },
-	{ "cdev1",	NULL,		0,		true },
-	{ "i2s1",	"pll_a_out0",	11289600,	false},
-	{ "usb3",	"clk_m",	12000000,	true },
-	{ NULL,		NULL,		0,		0},
-};
-
-
-static struct tegra_sdhci_platform_data sdhci_pdata1 = {
-	.cd_gpio	= -1,
-	.wp_gpio	= -1,
-	.power_gpio	= -1,
-};
-
-static struct tegra_sdhci_platform_data sdhci_pdata2 = {
-	.cd_gpio	= TEGRA_GPIO_SD2_CD,
-	.wp_gpio	= TEGRA_GPIO_SD2_WP,
-	.power_gpio	= TEGRA_GPIO_SD2_POWER,
-};
-
-static struct tegra_sdhci_platform_data sdhci_pdata4 = {
-	.cd_gpio	= TEGRA_GPIO_SD4_CD,
-	.wp_gpio	= TEGRA_GPIO_SD4_WP,
-	.power_gpio	= TEGRA_GPIO_SD4_POWER,
-	.is_8bit	= 1,
-};
-
-static void __init tegra_harmony_init(void)
-{
-	tegra_clk_init_from_table(harmony_clk_init_table);
-
-	harmony_pinmux_init();
-
-	tegra_sdhci_device1.dev.platform_data = &sdhci_pdata1;
-	tegra_sdhci_device2.dev.platform_data = &sdhci_pdata2;
-	tegra_sdhci_device4.dev.platform_data = &sdhci_pdata4;
-
-	platform_add_devices(harmony_devices, ARRAY_SIZE(harmony_devices));
-	harmony_i2c_init();
-	harmony_regulator_init();
-}
-
-MACHINE_START(HARMONY, "harmony")
-	.atag_offset	= 0x100,
-	.fixup		= tegra_harmony_fixup,
-	.map_io         = tegra_map_common_io,
-	.init_early	= tegra20_init_early,
-	.init_irq       = tegra_init_irq,
-	.handle_irq	= gic_handle_irq,
-	.timer          = &tegra_timer,
-	.init_machine   = tegra_harmony_init,
-	.init_late	= tegra_init_late,
-	.restart	= tegra_assert_system_reset,
-MACHINE_END
diff --git a/arch/arm/mach-tegra/board-harmony.h b/arch/arm/mach-tegra/board-harmony.h
deleted file mode 100644
index 139d96c..0000000
--- a/arch/arm/mach-tegra/board-harmony.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * arch/arm/mach-tegra/board-harmony.h
- *
- * Copyright (C) 2010 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef _MACH_TEGRA_BOARD_HARMONY_H
-#define _MACH_TEGRA_BOARD_HARMONY_H
-
-#include <mach/gpio-tegra.h>
-
-#define HARMONY_GPIO_TPS6586X(_x_)	(TEGRA_NR_GPIOS + (_x_))
-#define HARMONY_GPIO_WM8903(_x_)	(HARMONY_GPIO_TPS6586X(4) + (_x_))
-
-#define TEGRA_GPIO_SD2_CD		TEGRA_GPIO_PI5
-#define TEGRA_GPIO_SD2_WP		TEGRA_GPIO_PH1
-#define TEGRA_GPIO_SD2_POWER		TEGRA_GPIO_PT3
-#define TEGRA_GPIO_SD4_CD		TEGRA_GPIO_PH2
-#define TEGRA_GPIO_SD4_WP		TEGRA_GPIO_PH3
-#define TEGRA_GPIO_SD4_POWER		TEGRA_GPIO_PI6
-#define TEGRA_GPIO_CDC_IRQ		TEGRA_GPIO_PX3
-#define TEGRA_GPIO_SPKR_EN		HARMONY_GPIO_WM8903(2)
-#define TEGRA_GPIO_HP_DET		TEGRA_GPIO_PW2
-#define TEGRA_GPIO_INT_MIC_EN		TEGRA_GPIO_PX0
-#define TEGRA_GPIO_EXT_MIC_EN		TEGRA_GPIO_PX1
-#define TEGRA_GPIO_EN_VDD_1V05_GPIO	HARMONY_GPIO_TPS6586X(2)
-
-void harmony_pinmux_init(void);
-int harmony_regulator_init(void);
-
-#endif
diff --git a/arch/arm/mach-tegra/board-paz00-pinmux.c b/arch/arm/mach-tegra/board-paz00-pinmux.c
deleted file mode 100644
index 6f1111b..0000000
--- a/arch/arm/mach-tegra/board-paz00-pinmux.c
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * arch/arm/mach-tegra/board-paz00-pinmux.c
- *
- * Copyright (C) 2010 Marc Dietrich <marvin24@gmx.de>
- * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/kernel.h>
-
-#include "board-paz00.h"
-#include "board-pinmux.h"
-
-static struct pinctrl_map paz00_map[] = {
-	TEGRA_MAP_MUXCONF("ata",   "gmi",           none, driven),
-	TEGRA_MAP_MUXCONF("atb",   "sdio4",         none, driven),
-	TEGRA_MAP_MUXCONF("atc",   "gmi",           none, driven),
-	TEGRA_MAP_MUXCONF("atd",   "gmi",           none, driven),
-	TEGRA_MAP_MUXCONF("ate",   "gmi",           none, driven),
-	TEGRA_MAP_MUXCONF("cdev1", "plla_out",      none, driven),
-	TEGRA_MAP_MUXCONF("cdev2", "pllp_out4",     down, driven),
-	TEGRA_MAP_MUXCONF("crtp",  "crt",           none, tristate),
-	TEGRA_MAP_MUXCONF("csus",  "pllc_out1",     down, tristate),
-	TEGRA_MAP_MUXCONF("dap1",  "dap1",          none, driven),
-	TEGRA_MAP_MUXCONF("dap2",  "gmi",           none, driven),
-	TEGRA_MAP_MUXCONF("dap3",  "dap3",          none, tristate),
-	TEGRA_MAP_MUXCONF("dap4",  "dap4",          none, tristate),
-	TEGRA_MAP_MUXCONF("ddc",   "i2c2",          up,   driven),
-	TEGRA_MAP_MUXCONF("dta",   "rsvd1",         up,   tristate),
-	TEGRA_MAP_MUXCONF("dtb",   "rsvd1",         none, tristate),
-	TEGRA_MAP_MUXCONF("dtc",   "rsvd1",         none, tristate),
-	TEGRA_MAP_MUXCONF("dtd",   "rsvd1",         up,   tristate),
-	TEGRA_MAP_MUXCONF("dte",   "rsvd1",         none, tristate),
-	TEGRA_MAP_MUXCONF("dtf",   "i2c3",          none, driven),
-	TEGRA_MAP_MUXCONF("gma",   "sdio4",         none, driven),
-	TEGRA_MAP_MUXCONF("gmb",   "gmi",           none, driven),
-	TEGRA_MAP_MUXCONF("gmc",   "gmi",           none, driven),
-	TEGRA_MAP_MUXCONF("gmd",   "gmi",           none, driven),
-	TEGRA_MAP_MUXCONF("gme",   "sdio4",         none, driven),
-	TEGRA_MAP_MUXCONF("gpu",   "pwm",           none, driven),
-	TEGRA_MAP_MUXCONF("gpu7",  "rtck",          none, driven),
-	TEGRA_MAP_MUXCONF("gpv",   "pcie",          none, driven),
-	TEGRA_MAP_MUXCONF("hdint", "hdmi",          na,   driven),
-	TEGRA_MAP_MUXCONF("i2cp",  "i2cp",          none, driven),
-	TEGRA_MAP_MUXCONF("irrx",  "uarta",         up,   driven),
-	TEGRA_MAP_MUXCONF("irtx",  "uarta",         up,   driven),
-	TEGRA_MAP_MUXCONF("kbca",  "kbc",           up,   driven),
-	TEGRA_MAP_MUXCONF("kbcb",  "sdio2",         up,   driven),
-	TEGRA_MAP_MUXCONF("kbcc",  "kbc",           up,   driven),
-	TEGRA_MAP_MUXCONF("kbcd",  "sdio2",         up,   driven),
-	TEGRA_MAP_MUXCONF("kbce",  "kbc",           up,   driven),
-	TEGRA_MAP_MUXCONF("kbcf",  "kbc",           up,   driven),
-	TEGRA_MAP_MUXCONF("lcsn",  "displaya",      na,   tristate),
-	TEGRA_MAP_MUXCONF("ld0",   "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("ld1",   "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("ld10",  "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("ld11",  "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("ld12",  "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("ld13",  "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("ld14",  "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("ld15",  "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("ld16",  "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("ld17",  "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("ld2",   "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("ld3",   "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("ld4",   "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("ld5",   "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("ld6",   "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("ld7",   "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("ld8",   "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("ld9",   "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("ldc",   "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("ldi",   "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("lhp0",  "displaya",      na,   tristate),
-	TEGRA_MAP_MUXCONF("lhp1",  "displaya",      na,   tristate),
-	TEGRA_MAP_MUXCONF("lhp2",  "displaya",      na,   tristate),
-	TEGRA_MAP_MUXCONF("lhs",   "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("lm0",   "displaya",      na,   tristate),
-	TEGRA_MAP_MUXCONF("lm1",   "displaya",      na,   tristate),
-	TEGRA_MAP_MUXCONF("lpp",   "displaya",      na,   tristate),
-	TEGRA_MAP_MUXCONF("lpw0",  "displaya",      na,   tristate),
-	TEGRA_MAP_MUXCONF("lpw1",  "displaya",      na,   tristate),
-	TEGRA_MAP_MUXCONF("lpw2",  "displaya",      na,   tristate),
-	TEGRA_MAP_MUXCONF("lsc0",  "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("lsc1",  "displaya",      na,   tristate),
-	TEGRA_MAP_MUXCONF("lsck",  "displaya",      na,   tristate),
-	TEGRA_MAP_MUXCONF("lsda",  "displaya",      na,   tristate),
-	TEGRA_MAP_MUXCONF("lsdi",  "displaya",      na,   tristate),
-	TEGRA_MAP_MUXCONF("lspi",  "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("lvp0",  "displaya",      na,   tristate),
-	TEGRA_MAP_MUXCONF("lvp1",  "displaya",      na,   tristate),
-	TEGRA_MAP_MUXCONF("lvs",   "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("owc",   "owr",           up,   tristate),
-	TEGRA_MAP_MUXCONF("pmc",   "pwr_on",        na,   driven),
-	TEGRA_MAP_MUXCONF("pta",   "hdmi",          none, driven),
-	TEGRA_MAP_MUXCONF("rm",    "i2c1",          none, driven),
-	TEGRA_MAP_MUXCONF("sdb",   "pwm",           na,   tristate),
-	TEGRA_MAP_MUXCONF("sdc",   "twc",           up,   tristate),
-	TEGRA_MAP_MUXCONF("sdd",   "pwm",           up,   tristate),
-	TEGRA_MAP_MUXCONF("sdio1", "sdio1",         none, driven),
-	TEGRA_MAP_MUXCONF("slxa",  "pcie",          none, tristate),
-	TEGRA_MAP_MUXCONF("slxc",  "spi4",          none, tristate),
-	TEGRA_MAP_MUXCONF("slxd",  "spi4",          none, tristate),
-	TEGRA_MAP_MUXCONF("slxk",  "pcie",          none, driven),
-	TEGRA_MAP_MUXCONF("spdi",  "rsvd2",         none, tristate),
-	TEGRA_MAP_MUXCONF("spdo",  "rsvd2",         none, driven),
-	TEGRA_MAP_MUXCONF("spia",  "gmi",           down, tristate),
-	TEGRA_MAP_MUXCONF("spib",  "gmi",           down, tristate),
-	TEGRA_MAP_MUXCONF("spic",  "gmi",           up,   driven),
-	TEGRA_MAP_MUXCONF("spid",  "gmi",           down, tristate),
-	TEGRA_MAP_MUXCONF("spie",  "gmi",           up,   tristate),
-	TEGRA_MAP_MUXCONF("spif",  "rsvd4",         down, tristate),
-	TEGRA_MAP_MUXCONF("spig",  "spi2_alt",      up,   driven),
-	TEGRA_MAP_MUXCONF("spih",  "spi2_alt",      up,   tristate),
-	TEGRA_MAP_MUXCONF("uaa",   "ulpi",          up,   driven),
-	TEGRA_MAP_MUXCONF("uab",   "ulpi",          up,   driven),
-	TEGRA_MAP_MUXCONF("uac",   "rsvd4",         none, driven),
-	TEGRA_MAP_MUXCONF("uad",   "spdif",         up,   tristate),
-	TEGRA_MAP_MUXCONF("uca",   "uartc",         up,   tristate),
-	TEGRA_MAP_MUXCONF("ucb",   "uartc",         up,   tristate),
-	TEGRA_MAP_MUXCONF("uda",   "ulpi",          none, driven),
-	TEGRA_MAP_CONF("ck32",    none, na),
-	TEGRA_MAP_CONF("ddrc",    none, na),
-	TEGRA_MAP_CONF("pmca",    none, na),
-	TEGRA_MAP_CONF("pmcb",    none, na),
-	TEGRA_MAP_CONF("pmcc",    none, na),
-	TEGRA_MAP_CONF("pmcd",    none, na),
-	TEGRA_MAP_CONF("pmce",    none, na),
-	TEGRA_MAP_CONF("xm2c",    none, na),
-	TEGRA_MAP_CONF("xm2d",    none, na),
-	TEGRA_MAP_CONF("ls",      up,   na),
-	TEGRA_MAP_CONF("lc",      up,   na),
-	TEGRA_MAP_CONF("ld17_0",  down, na),
-	TEGRA_MAP_CONF("ld19_18", down, na),
-	TEGRA_MAP_CONF("ld21_20", down, na),
-	TEGRA_MAP_CONF("ld23_22", down, na),
-};
-
-static struct tegra_board_pinmux_conf conf = {
-	.maps = paz00_map,
-	.map_count = ARRAY_SIZE(paz00_map),
-};
-
-void paz00_pinmux_init(void)
-{
-	tegra_board_pinmux_init(&conf, NULL);
-}
diff --git a/arch/arm/mach-tegra/board-paz00.c b/arch/arm/mach-tegra/board-paz00.c
index 4b64af5..740e16f 100644
--- a/arch/arm/mach-tegra/board-paz00.c
+++ b/arch/arm/mach-tegra/board-paz00.c
@@ -17,72 +17,10 @@
  *
  */
 
-#include <linux/kernel.h>
-#include <linux/init.h>
 #include <linux/platform_device.h>
-#include <linux/serial_8250.h>
-#include <linux/of_serial.h>
-#include <linux/clk.h>
-#include <linux/dma-mapping.h>
-#include <linux/gpio_keys.h>
-#include <linux/pda_power.h>
-#include <linux/io.h>
-#include <linux/input.h>
-#include <linux/i2c.h>
-#include <linux/gpio.h>
 #include <linux/rfkill-gpio.h>
-
-#include <asm/hardware/gic.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-#include <asm/setup.h>
-
-#include <mach/iomap.h>
-#include <mach/irqs.h>
-#include <mach/sdhci.h>
-
 #include "board.h"
 #include "board-paz00.h"
-#include "clock.h"
-#include "devices.h"
-#include "gpio-names.h"
-
-static struct plat_serial8250_port debug_uart_platform_data[] = {
-	{
-		/* serial port on JP1 */
-		.membase	= IO_ADDRESS(TEGRA_UARTA_BASE),
-		.mapbase	= TEGRA_UARTA_BASE,
-		.irq		= INT_UARTA,
-		.flags		= UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE,
-		.type		= PORT_TEGRA,
-		.handle_break	= tegra_serial_handle_break,
-		.iotype		= UPIO_MEM,
-		.regshift	= 2,
-		.uartclk	= 216000000,
-	}, {
-		/* serial port on mini-pcie */
-		.membase	= IO_ADDRESS(TEGRA_UARTC_BASE),
-		.mapbase	= TEGRA_UARTC_BASE,
-		.irq		= INT_UARTC,
-		.flags		= UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE,
-		.type		= PORT_TEGRA,
-		.handle_break	= tegra_serial_handle_break,
-		.iotype		= UPIO_MEM,
-		.regshift	= 2,
-		.uartclk	= 216000000,
-	}, {
-		.flags		= 0
-	}
-};
-
-static struct platform_device debug_uart = {
-	.name = "serial8250",
-	.id = PLAT8250_DEV_PLATFORM,
-	.dev = {
-		.platform_data = debug_uart_platform_data,
-	},
-};
 
 static struct rfkill_gpio_platform_data wifi_rfkill_platform_data = {
 	.name		= "wifi_rfkill",
@@ -99,137 +37,7 @@ static struct platform_device wifi_rfkill_device = {
 	},
 };
 
-static struct gpio_led gpio_leds[] = {
-	{
-		.name			= "wifi-led",
-		.default_trigger	= "rfkill0",
-		.gpio			= TEGRA_WIFI_LED,
-	},
-};
-
-static struct gpio_led_platform_data gpio_led_info = {
-	.leds		= gpio_leds,
-	.num_leds	= ARRAY_SIZE(gpio_leds),
-};
-
-static struct platform_device leds_gpio = {
-	.name	= "leds-gpio",
-	.id	= -1,
-	.dev	= {
-		.platform_data = &gpio_led_info,
-        },
-};
-
-static struct gpio_keys_button paz00_gpio_keys_buttons[] = {
-	{
-		.code		= KEY_POWER,
-		.gpio		= TEGRA_GPIO_POWERKEY,
-		.active_low	= 1,
-		.desc		= "Power",
-		.type		= EV_KEY,
-		.wakeup		= 1,
-	},
-};
-
-static struct gpio_keys_platform_data paz00_gpio_keys = {
-	.buttons	= paz00_gpio_keys_buttons,
-	.nbuttons	= ARRAY_SIZE(paz00_gpio_keys_buttons),
-};
-
-static struct platform_device gpio_keys_device = {
-	.name	= "gpio-keys",
-	.id	= -1,
-	.dev	= {
-		.platform_data = &paz00_gpio_keys,
-	},
-};
-
-static struct platform_device *paz00_devices[] __initdata = {
-	&debug_uart,
-	&tegra_sdhci_device4,
-	&tegra_sdhci_device1,
-	&leds_gpio,
-	&gpio_keys_device,
-};
-
-static void paz00_i2c_init(void)
-{
-	platform_device_register(&tegra_i2c_device1);
-	platform_device_register(&tegra_i2c_device2);
-	platform_device_register(&tegra_i2c_device4);
-}
-
-static void paz00_usb_init(void)
-{
-	tegra_ehci2_ulpi_phy_config.reset_gpio = TEGRA_ULPI_RST;
-
-	platform_device_register(&tegra_ehci2_device);
-	platform_device_register(&tegra_ehci3_device);
-}
-
-static void __init tegra_paz00_fixup(struct tag *tags, char **cmdline,
-	struct meminfo *mi)
-{
-	mi->nr_banks = 1;
-	mi->bank[0].start = PHYS_OFFSET;
-	mi->bank[0].size = 448 * SZ_1M;
-}
-
-static __initdata struct tegra_clk_init_table paz00_clk_init_table[] = {
-	/* name		parent		rate		enabled */
-	{ "uarta",	"pll_p",	216000000,	true },
-	{ "uartc",	"pll_p",	216000000,	true },
-
-	{ "usbd",	"clk_m",	12000000,	false },
-	{ "usb2",	"clk_m",	12000000,	false },
-	{ "usb3",	"clk_m",	12000000,	false },
-
-	{ NULL,		NULL,		0,		0},
-};
-
-static struct tegra_sdhci_platform_data sdhci_pdata1 = {
-	.cd_gpio	= TEGRA_GPIO_SD1_CD,
-	.wp_gpio	= TEGRA_GPIO_SD1_WP,
-	.power_gpio	= TEGRA_GPIO_SD1_POWER,
-};
-
-static struct tegra_sdhci_platform_data sdhci_pdata4 = {
-	.cd_gpio	= -1,
-	.wp_gpio	= -1,
-	.power_gpio	= -1,
-	.is_8bit	= 1,
-};
-
 void __init tegra_paz00_wifikill_init(void)
 {
 	platform_device_register(&wifi_rfkill_device);
 }
-
-static void __init tegra_paz00_init(void)
-{
-	tegra_clk_init_from_table(paz00_clk_init_table);
-
-	paz00_pinmux_init();
-
-	tegra_sdhci_device1.dev.platform_data = &sdhci_pdata1;
-	tegra_sdhci_device4.dev.platform_data = &sdhci_pdata4;
-
-	platform_add_devices(paz00_devices, ARRAY_SIZE(paz00_devices));
-	tegra_paz00_wifikill_init();
-
-	paz00_i2c_init();
-	paz00_usb_init();
-}
-
-MACHINE_START(PAZ00, "Toshiba AC100 / Dynabook AZ")
-	.atag_offset	= 0x100,
-	.fixup		= tegra_paz00_fixup,
-	.map_io         = tegra_map_common_io,
-	.init_early	= tegra20_init_early,
-	.init_irq       = tegra_init_irq,
-	.handle_irq	= gic_handle_irq,
-	.timer          = &tegra_timer,
-	.init_machine   = tegra_paz00_init,
-	.init_late	= tegra_init_late,
-	.restart	= tegra_assert_system_reset,
-MACHINE_END
diff --git a/arch/arm/mach-tegra/board-paz00.h b/arch/arm/mach-tegra/board-paz00.h
index 3c9f8da..25c08ec 100644
--- a/arch/arm/mach-tegra/board-paz00.h
+++ b/arch/arm/mach-tegra/board-paz00.h
@@ -17,24 +17,9 @@
 #ifndef _MACH_TEGRA_BOARD_PAZ00_H
 #define _MACH_TEGRA_BOARD_PAZ00_H
 
-#include <mach/gpio-tegra.h>
+#include "gpio-names.h"
 
-/* SDCARD */
-#define TEGRA_GPIO_SD1_CD		TEGRA_GPIO_PV5
-#define TEGRA_GPIO_SD1_WP		TEGRA_GPIO_PH1
-#define TEGRA_GPIO_SD1_POWER		TEGRA_GPIO_PV1
-
-/* ULPI */
-#define TEGRA_ULPI_RST			TEGRA_GPIO_PV0
-
-/* WIFI */
 #define TEGRA_WIFI_PWRN			TEGRA_GPIO_PK5
 #define TEGRA_WIFI_RST			TEGRA_GPIO_PD1
-#define TEGRA_WIFI_LED			TEGRA_GPIO_PD0
-
-/* WakeUp */
-#define TEGRA_GPIO_POWERKEY	TEGRA_GPIO_PJ7
-
-void paz00_pinmux_init(void);
 
 #endif
diff --git a/arch/arm/mach-tegra/board-pinmux.c b/arch/arm/mach-tegra/board-pinmux.c
deleted file mode 100644
index a5574c7..0000000
--- a/arch/arm/mach-tegra/board-pinmux.c
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (c) 2011,2012, NVIDIA CORPORATION.  All rights reserved.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/device.h>
-#include <linux/kernel.h>
-#include <linux/notifier.h>
-#include <linux/string.h>
-
-#include "board-pinmux.h"
-#include "devices.h"
-
-unsigned long tegra_pincfg_pullnone_driven[2] = {
-	TEGRA_PINCONF_PACK(TEGRA_PINCONF_PARAM_PULL, TEGRA_PINCONFIG_PULL_NONE),
-	TEGRA_PINCONF_PACK(TEGRA_PINCONF_PARAM_TRISTATE, TEGRA_PINCONFIG_DRIVEN),
-};
-
-unsigned long tegra_pincfg_pullnone_tristate[2] = {
-	TEGRA_PINCONF_PACK(TEGRA_PINCONF_PARAM_PULL, TEGRA_PINCONFIG_PULL_NONE),
-	TEGRA_PINCONF_PACK(TEGRA_PINCONF_PARAM_TRISTATE, TEGRA_PINCONFIG_TRISTATE),
-};
-
-unsigned long tegra_pincfg_pullnone_na[1] = {
-	TEGRA_PINCONF_PACK(TEGRA_PINCONF_PARAM_PULL, TEGRA_PINCONFIG_PULL_NONE),
-};
-
-unsigned long tegra_pincfg_pullup_driven[2] = {
-	TEGRA_PINCONF_PACK(TEGRA_PINCONF_PARAM_PULL, TEGRA_PINCONFIG_PULL_UP),
-	TEGRA_PINCONF_PACK(TEGRA_PINCONF_PARAM_TRISTATE, TEGRA_PINCONFIG_DRIVEN),
-};
-
-unsigned long tegra_pincfg_pullup_tristate[2] = {
-	TEGRA_PINCONF_PACK(TEGRA_PINCONF_PARAM_PULL, TEGRA_PINCONFIG_PULL_UP),
-	TEGRA_PINCONF_PACK(TEGRA_PINCONF_PARAM_TRISTATE, TEGRA_PINCONFIG_TRISTATE),
-};
-
-unsigned long tegra_pincfg_pullup_na[1] = {
-	TEGRA_PINCONF_PACK(TEGRA_PINCONF_PARAM_PULL, TEGRA_PINCONFIG_PULL_UP),
-};
-
-unsigned long tegra_pincfg_pulldown_driven[2] = {
-	TEGRA_PINCONF_PACK(TEGRA_PINCONF_PARAM_PULL, TEGRA_PINCONFIG_PULL_DOWN),
-	TEGRA_PINCONF_PACK(TEGRA_PINCONF_PARAM_TRISTATE, TEGRA_PINCONFIG_DRIVEN),
-};
-
-unsigned long tegra_pincfg_pulldown_tristate[2] = {
-	TEGRA_PINCONF_PACK(TEGRA_PINCONF_PARAM_PULL, TEGRA_PINCONFIG_PULL_DOWN),
-	TEGRA_PINCONF_PACK(TEGRA_PINCONF_PARAM_TRISTATE, TEGRA_PINCONFIG_TRISTATE),
-};
-
-unsigned long tegra_pincfg_pulldown_na[1] = {
-	TEGRA_PINCONF_PACK(TEGRA_PINCONF_PARAM_PULL, TEGRA_PINCONFIG_PULL_DOWN),
-};
-
-unsigned long tegra_pincfg_pullna_driven[1] = {
-	TEGRA_PINCONF_PACK(TEGRA_PINCONF_PARAM_TRISTATE, TEGRA_PINCONFIG_DRIVEN),
-};
-
-unsigned long tegra_pincfg_pullna_tristate[1] = {
-	TEGRA_PINCONF_PACK(TEGRA_PINCONF_PARAM_TRISTATE, TEGRA_PINCONFIG_TRISTATE),
-};
-
-static struct platform_device *devices[] = {
-	&tegra_gpio_device,
-	&tegra_pinmux_device,
-};
-
-void tegra_board_pinmux_init(struct tegra_board_pinmux_conf *conf_a,
-			     struct tegra_board_pinmux_conf *conf_b)
-{
-	if (conf_a)
-		pinctrl_register_mappings(conf_a->maps, conf_a->map_count);
-	if (conf_b)
-		pinctrl_register_mappings(conf_b->maps, conf_b->map_count);
-
-	platform_add_devices(devices, ARRAY_SIZE(devices));
-}
diff --git a/arch/arm/mach-tegra/board-pinmux.h b/arch/arm/mach-tegra/board-pinmux.h
deleted file mode 100644
index c5f3f33..0000000
--- a/arch/arm/mach-tegra/board-pinmux.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2011,2012, NVIDIA CORPORATION.  All rights reserved.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef __MACH_TEGRA_BOARD_PINMUX_H
-#define __MACH_TEGRA_BOARD_PINMUX_H
-
-#include <linux/pinctrl/machine.h>
-
-#include <mach/pinconf-tegra.h>
-
-#define PINMUX_DEV "tegra20-pinctrl"
-
-#define TEGRA_MAP_MUX(_group_, _function_) \
-	PIN_MAP_MUX_GROUP_HOG_DEFAULT(PINMUX_DEV, _group_, _function_)
-
-#define TEGRA_MAP_CONF(_group_, _pull_, _drive_) \
-	PIN_MAP_CONFIGS_GROUP_HOG_DEFAULT(PINMUX_DEV, _group_, tegra_pincfg_pull##_pull_##_##_drive_)
-
-#define TEGRA_MAP_MUXCONF(_group_, _function_, _pull_, _drive_) \
-	TEGRA_MAP_MUX(_group_, _function_), \
-	TEGRA_MAP_CONF(_group_, _pull_, _drive_)
-
-extern unsigned long tegra_pincfg_pullnone_driven[2];
-extern unsigned long tegra_pincfg_pullnone_tristate[2];
-extern unsigned long tegra_pincfg_pullnone_na[1];
-extern unsigned long tegra_pincfg_pullup_driven[2];
-extern unsigned long tegra_pincfg_pullup_tristate[2];
-extern unsigned long tegra_pincfg_pullup_na[1];
-extern unsigned long tegra_pincfg_pulldown_driven[2];
-extern unsigned long tegra_pincfg_pulldown_tristate[2];
-extern unsigned long tegra_pincfg_pulldown_na[1];
-extern unsigned long tegra_pincfg_pullna_driven[1];
-extern unsigned long tegra_pincfg_pullna_tristate[1];
-
-struct tegra_board_pinmux_conf {
-	struct pinctrl_map *maps;
-	int map_count;
-};
-
-void tegra_board_pinmux_init(struct tegra_board_pinmux_conf *conf_a,
-			     struct tegra_board_pinmux_conf *conf_b);
-
-#endif
diff --git a/arch/arm/mach-tegra/board-trimslice-pinmux.c b/arch/arm/mach-tegra/board-trimslice-pinmux.c
deleted file mode 100644
index 7b39511..0000000
--- a/arch/arm/mach-tegra/board-trimslice-pinmux.c
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * arch/arm/mach-tegra/board-trimslice-pinmux.c
- *
- * Copyright (C) 2011 CompuLab, Ltd.
- * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-#include <linux/kernel.h>
-
-#include "board-trimslice.h"
-#include "board-pinmux.h"
-
-static struct pinctrl_map trimslice_map[] = {
-	TEGRA_MAP_MUXCONF("ata",   "ide",           none, tristate),
-	TEGRA_MAP_MUXCONF("atb",   "sdio4",         none, driven),
-	TEGRA_MAP_MUXCONF("atc",   "nand",          none, tristate),
-	TEGRA_MAP_MUXCONF("atd",   "gmi",           none, tristate),
-	TEGRA_MAP_MUXCONF("ate",   "gmi",           none, tristate),
-	TEGRA_MAP_MUXCONF("cdev1", "plla_out",      none, driven),
-	TEGRA_MAP_MUXCONF("cdev2", "pllp_out4",     down, tristate),
-	TEGRA_MAP_MUXCONF("crtp",  "crt",           none, tristate),
-	TEGRA_MAP_MUXCONF("csus",  "vi_sensor_clk", down, tristate),
-	TEGRA_MAP_MUXCONF("dap1",  "dap1",          none, driven),
-	TEGRA_MAP_MUXCONF("dap2",  "dap2",          none, tristate),
-	TEGRA_MAP_MUXCONF("dap3",  "dap3",          none, tristate),
-	TEGRA_MAP_MUXCONF("dap4",  "dap4",          none, tristate),
-	TEGRA_MAP_MUXCONF("ddc",   "i2c2",          up,   driven),
-	TEGRA_MAP_MUXCONF("dta",   "vi",            none, tristate),
-	TEGRA_MAP_MUXCONF("dtb",   "vi",            none, tristate),
-	TEGRA_MAP_MUXCONF("dtc",   "vi",            none, tristate),
-	TEGRA_MAP_MUXCONF("dtd",   "vi",            none, tristate),
-	TEGRA_MAP_MUXCONF("dte",   "vi",            none, tristate),
-	TEGRA_MAP_MUXCONF("dtf",   "i2c3",          up,   driven),
-	TEGRA_MAP_MUXCONF("gma",   "sdio4",         none, driven),
-	TEGRA_MAP_MUXCONF("gmb",   "nand",          none, tristate),
-	TEGRA_MAP_MUXCONF("gmc",   "sflash",        none, driven),
-	TEGRA_MAP_MUXCONF("gmd",   "sflash",        none, driven),
-	TEGRA_MAP_MUXCONF("gme",   "gmi",           none, tristate),
-	TEGRA_MAP_MUXCONF("gpu",   "uarta",         none, driven),
-	TEGRA_MAP_MUXCONF("gpu7",  "rtck",          none, driven),
-	TEGRA_MAP_MUXCONF("gpv",   "pcie",          none, driven),
-	TEGRA_MAP_MUXCONF("hdint", "hdmi",          na,   tristate),
-	TEGRA_MAP_MUXCONF("i2cp",  "i2cp",          none, tristate),
-	TEGRA_MAP_MUXCONF("irrx",  "uartb",         up,   tristate),
-	TEGRA_MAP_MUXCONF("irtx",  "uartb",         up,   tristate),
-	TEGRA_MAP_MUXCONF("kbca",  "kbc",           up,   tristate),
-	TEGRA_MAP_MUXCONF("kbcb",  "kbc",           up,   tristate),
-	TEGRA_MAP_MUXCONF("kbcc",  "kbc",           up,   tristate),
-	TEGRA_MAP_MUXCONF("kbcd",  "kbc",           up,   tristate),
-	TEGRA_MAP_MUXCONF("kbce",  "kbc",           up,   tristate),
-	TEGRA_MAP_MUXCONF("kbcf",  "kbc",           up,   tristate),
-	TEGRA_MAP_MUXCONF("lcsn",  "displaya",      na,   tristate),
-	TEGRA_MAP_MUXCONF("ld0",   "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("ld1",   "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("ld10",  "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("ld11",  "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("ld12",  "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("ld13",  "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("ld14",  "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("ld15",  "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("ld16",  "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("ld17",  "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("ld2",   "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("ld3",   "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("ld4",   "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("ld5",   "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("ld6",   "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("ld7",   "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("ld8",   "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("ld9",   "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("ldc",   "displaya",      na,   tristate),
-	TEGRA_MAP_MUXCONF("ldi",   "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("lhp0",  "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("lhp1",  "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("lhp2",  "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("lhs",   "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("lm0",   "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("lm1",   "displaya",      na,   tristate),
-	TEGRA_MAP_MUXCONF("lpp",   "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("lpw0",  "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("lpw1",  "displaya",      na,   tristate),
-	TEGRA_MAP_MUXCONF("lpw2",  "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("lsc0",  "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("lsc1",  "displaya",      na,   tristate),
-	TEGRA_MAP_MUXCONF("lsck",  "displaya",      na,   tristate),
-	TEGRA_MAP_MUXCONF("lsda",  "displaya",      na,   tristate),
-	TEGRA_MAP_MUXCONF("lsdi",  "displaya",      na,   tristate),
-	TEGRA_MAP_MUXCONF("lspi",  "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("lvp0",  "displaya",      na,   tristate),
-	TEGRA_MAP_MUXCONF("lvp1",  "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("lvs",   "displaya",      na,   driven),
-	TEGRA_MAP_MUXCONF("owc",   "rsvd2",         up,   tristate),
-	TEGRA_MAP_MUXCONF("pmc",   "pwr_on",        na,   tristate),
-	TEGRA_MAP_MUXCONF("pta",   "gmi",           none, tristate),
-	TEGRA_MAP_MUXCONF("rm",    "i2c1",          up,   driven),
-	TEGRA_MAP_MUXCONF("sdb",   "pwm",           na,   driven),
-	TEGRA_MAP_MUXCONF("sdc",   "pwm",           up,   driven),
-	TEGRA_MAP_MUXCONF("sdd",   "pwm",           up,   driven),
-	TEGRA_MAP_MUXCONF("sdio1", "sdio1",         none, driven),
-	TEGRA_MAP_MUXCONF("slxa",  "pcie",          none, driven),
-	TEGRA_MAP_MUXCONF("slxc",  "sdio3",         none, tristate),
-	TEGRA_MAP_MUXCONF("slxd",  "sdio3",         none, tristate),
-	TEGRA_MAP_MUXCONF("slxk",  "pcie",          none, driven),
-	TEGRA_MAP_MUXCONF("spdi",  "spdif",         none, tristate),
-	TEGRA_MAP_MUXCONF("spdo",  "spdif",         none, tristate),
-	TEGRA_MAP_MUXCONF("spia",  "spi2",          down, tristate),
-	TEGRA_MAP_MUXCONF("spib",  "spi2",          down, tristate),
-	TEGRA_MAP_MUXCONF("spic",  "spi2",          up,   tristate),
-	TEGRA_MAP_MUXCONF("spid",  "spi1",          down, tristate),
-	TEGRA_MAP_MUXCONF("spie",  "spi1",          up,   tristate),
-	TEGRA_MAP_MUXCONF("spif",  "spi1",          down, tristate),
-	TEGRA_MAP_MUXCONF("spig",  "spi2_alt",      up,   tristate),
-	TEGRA_MAP_MUXCONF("spih",  "spi2_alt",      up,   tristate),
-	TEGRA_MAP_MUXCONF("uaa",   "ulpi",          up,   tristate),
-	TEGRA_MAP_MUXCONF("uab",   "ulpi",          up,   tristate),
-	TEGRA_MAP_MUXCONF("uac",   "rsvd2",         none, driven),
-	TEGRA_MAP_MUXCONF("uad",   "irda",          up,   tristate),
-	TEGRA_MAP_MUXCONF("uca",   "uartc",         up,   tristate),
-	TEGRA_MAP_MUXCONF("ucb",   "uartc",         up,   tristate),
-	TEGRA_MAP_MUXCONF("uda",   "ulpi",          none, tristate),
-	TEGRA_MAP_CONF("ck32",    none, na),
-	TEGRA_MAP_CONF("ddrc",    none, na),
-	TEGRA_MAP_CONF("pmca",    none, na),
-	TEGRA_MAP_CONF("pmcb",    none, na),
-	TEGRA_MAP_CONF("pmcc",    none, na),
-	TEGRA_MAP_CONF("pmcd",    none, na),
-	TEGRA_MAP_CONF("pmce",    none, na),
-	TEGRA_MAP_CONF("xm2c",    none, na),
-	TEGRA_MAP_CONF("xm2d",    none, na),
-	TEGRA_MAP_CONF("ls",      up,   na),
-	TEGRA_MAP_CONF("lc",      up,   na),
-	TEGRA_MAP_CONF("ld17_0",  down, na),
-	TEGRA_MAP_CONF("ld19_18", down, na),
-	TEGRA_MAP_CONF("ld21_20", down, na),
-	TEGRA_MAP_CONF("ld23_22", down, na),
-};
-
-static struct tegra_board_pinmux_conf conf = {
-	.maps = trimslice_map,
-	.map_count = ARRAY_SIZE(trimslice_map),
-};
-
-void trimslice_pinmux_init(void)
-{
-	tegra_board_pinmux_init(&conf, NULL);
-}
diff --git a/arch/arm/mach-tegra/board-trimslice.c b/arch/arm/mach-tegra/board-trimslice.c
deleted file mode 100644
index 776aa95..0000000
--- a/arch/arm/mach-tegra/board-trimslice.c
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * arch/arm/mach-tegra/board-trimslice.c
- *
- * Copyright (C) 2011 CompuLab, Ltd.
- * Author: Mike Rapoport <mike@compulab.co.il>
- *
- * Based on board-harmony.c
- * Copyright (C) 2010 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/serial_8250.h>
-#include <linux/of_serial.h>
-#include <linux/io.h>
-#include <linux/i2c.h>
-#include <linux/gpio.h>
-#include <linux/platform_data/tegra_usb.h>
-
-#include <asm/hardware/gic.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/setup.h>
-
-#include <mach/iomap.h>
-#include <mach/sdhci.h>
-
-#include "board.h"
-#include "clock.h"
-#include "devices.h"
-#include "gpio-names.h"
-
-#include "board-trimslice.h"
-
-static struct plat_serial8250_port debug_uart_platform_data[] = {
-	{
-		.membase	= IO_ADDRESS(TEGRA_UARTA_BASE),
-		.mapbase	= TEGRA_UARTA_BASE,
-		.irq		= INT_UARTA,
-		.flags		= UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE,
-		.type		= PORT_TEGRA,
-		.handle_break	= tegra_serial_handle_break,
-		.iotype		= UPIO_MEM,
-		.regshift	= 2,
-		.uartclk	= 216000000,
-	}, {
-		.flags		= 0
-	}
-};
-
-static struct platform_device debug_uart = {
-	.name	= "serial8250",
-	.id	= PLAT8250_DEV_PLATFORM,
-	.dev	= {
-		.platform_data	= debug_uart_platform_data,
-	},
-};
-static struct tegra_sdhci_platform_data sdhci_pdata1 = {
-	.cd_gpio	= -1,
-	.wp_gpio	= -1,
-	.power_gpio	= -1,
-};
-
-static struct tegra_sdhci_platform_data sdhci_pdata4 = {
-	.cd_gpio	= TRIMSLICE_GPIO_SD4_CD,
-	.wp_gpio	= TRIMSLICE_GPIO_SD4_WP,
-	.power_gpio	= -1,
-};
-
-static struct platform_device trimslice_audio_device = {
-	.name	= "tegra-snd-trimslice",
-	.id	= 0,
-};
-
-static struct platform_device *trimslice_devices[] __initdata = {
-	&debug_uart,
-	&tegra_sdhci_device1,
-	&tegra_sdhci_device4,
-	&tegra_i2s_device1,
-	&tegra_das_device,
-	&trimslice_audio_device,
-};
-
-static struct i2c_board_info trimslice_i2c3_board_info[] = {
-	{
-		I2C_BOARD_INFO("tlv320aic23", 0x1a),
-	},
-	{
-		I2C_BOARD_INFO("em3027", 0x56),
-	},
-};
-
-static void trimslice_i2c_init(void)
-{
-	platform_device_register(&tegra_i2c_device1);
-	platform_device_register(&tegra_i2c_device2);
-	platform_device_register(&tegra_i2c_device3);
-
-	i2c_register_board_info(2, trimslice_i2c3_board_info,
-				ARRAY_SIZE(trimslice_i2c3_board_info));
-}
-
-static void trimslice_usb_init(void)
-{
-	struct tegra_ehci_platform_data *pdata;
-
-	pdata = tegra_ehci1_device.dev.platform_data;
-	pdata->vbus_gpio = TRIMSLICE_GPIO_USB1_MODE;
-
-	tegra_ehci2_ulpi_phy_config.reset_gpio = TEGRA_GPIO_PV0;
-
-	platform_device_register(&tegra_ehci3_device);
-	platform_device_register(&tegra_ehci2_device);
-	platform_device_register(&tegra_ehci1_device);
-}
-
-static void __init tegra_trimslice_fixup(struct tag *tags, char **cmdline,
-	struct meminfo *mi)
-{
-	mi->nr_banks = 2;
-	mi->bank[0].start = PHYS_OFFSET;
-	mi->bank[0].size = 448 * SZ_1M;
-	mi->bank[1].start = SZ_512M;
-	mi->bank[1].size = SZ_512M;
-}
-
-static __initdata struct tegra_clk_init_table trimslice_clk_init_table[] = {
-	/* name		parent		rate		enabled */
-	{ "uarta",	"pll_p",	216000000,	true },
-	{ "pll_a",	"pll_p_out1",	56448000,	true },
-	{ "pll_a_out0",	"pll_a",	11289600,	true },
-	{ "cdev1",	NULL,		0,		true },
-	{ "i2s1",	"pll_a_out0",	11289600,	false},
-	{ NULL,		NULL,		0,		0},
-};
-
-static int __init tegra_trimslice_pci_init(void)
-{
-	if (!machine_is_trimslice())
-		return 0;
-
-	return tegra_pcie_init(true, true);
-}
-subsys_initcall(tegra_trimslice_pci_init);
-
-static void __init tegra_trimslice_init(void)
-{
-	tegra_clk_init_from_table(trimslice_clk_init_table);
-
-	trimslice_pinmux_init();
-
-	tegra_sdhci_device1.dev.platform_data = &sdhci_pdata1;
-	tegra_sdhci_device4.dev.platform_data = &sdhci_pdata4;
-
-	platform_add_devices(trimslice_devices, ARRAY_SIZE(trimslice_devices));
-
-	trimslice_i2c_init();
-	trimslice_usb_init();
-}
-
-MACHINE_START(TRIMSLICE, "trimslice")
-	.atag_offset	= 0x100,
-	.fixup		= tegra_trimslice_fixup,
-	.map_io         = tegra_map_common_io,
-	.init_early	= tegra20_init_early,
-	.init_irq       = tegra_init_irq,
-	.handle_irq	= gic_handle_irq,
-	.timer          = &tegra_timer,
-	.init_machine   = tegra_trimslice_init,
-	.init_late	= tegra_init_late,
-	.restart	= tegra_assert_system_reset,
-MACHINE_END
diff --git a/arch/arm/mach-tegra/board-trimslice.h b/arch/arm/mach-tegra/board-trimslice.h
deleted file mode 100644
index 50f128d..0000000
--- a/arch/arm/mach-tegra/board-trimslice.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * arch/arm/mach-tegra/board-trimslice.h
- *
- * Copyright (C) 2011 CompuLab, Ltd.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef _MACH_TEGRA_BOARD_TRIMSLICE_H
-#define _MACH_TEGRA_BOARD_TRIMSLICE_H
-
-#include <mach/gpio-tegra.h>
-
-#define TRIMSLICE_GPIO_SD4_CD	TEGRA_GPIO_PP1	/* mmc4 cd */
-#define TRIMSLICE_GPIO_SD4_WP	TEGRA_GPIO_PP2	/* mmc4 wp */
-
-#define TRIMSLICE_GPIO_USB1_MODE	TEGRA_GPIO_PV2 /* USB1 mode */
-#define TRIMSLICE_GPIO_USB2_RST		TEGRA_GPIO_PV0 /* USB2 PHY reset */
-
-void trimslice_pinmux_init(void);
-
-#endif
diff --git a/arch/arm/mach-tegra/clock.c b/arch/arm/mach-tegra/clock.c
index 58f981c..fd82085 100644
--- a/arch/arm/mach-tegra/clock.c
+++ b/arch/arm/mach-tegra/clock.c
@@ -1,6 +1,7 @@
 /*
  *
  * Copyright (C) 2010 Google, Inc.
+ * Copyright (c) 2012 NVIDIA CORPORATION.  All rights reserved.
  *
  * Author:
  *	Colin Cross <ccross@google.com>
@@ -19,8 +20,6 @@
 #include <linux/kernel.h>
 #include <linux/clk.h>
 #include <linux/clkdev.h>
-#include <linux/debugfs.h>
-#include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/list.h>
 #include <linux/module.h>
@@ -32,325 +31,75 @@
 
 #include "board.h"
 #include "clock.h"
+#include "tegra_cpu_car.h"
+
+/* Global data of Tegra CPU CAR ops */
+struct tegra_cpu_car_ops *tegra_cpu_car_ops;
 
 /*
  * Locking:
  *
- * Each struct clk has a spinlock.
- *
- * To avoid AB-BA locking problems, locks must always be traversed from child
- * clock to parent clock.  For example, when enabling a clock, the clock's lock
- * is taken, and then clk_enable is called on the parent, which take's the
- * parent clock's lock.  There is one exceptions to this ordering: When dumping
- * the clock tree through debugfs.  In this case, clk_lock_all is called,
- * which attemps to iterate through the entire list of clocks and take every
- * clock lock.  If any call to spin_trylock fails, all locked clocks are
- * unlocked, and the process is retried.  When all the locks are held,
- * the only clock operation that can be called is clk_get_rate_all_locked.
- *
- * Within a single clock, no clock operation can call another clock operation
- * on itself, except for clk_get_rate_locked and clk_set_rate_locked.  Any
- * clock operation can call any other clock operation on any of it's possible
- * parents.
- *
  * An additional mutex, clock_list_lock, is used to protect the list of all
  * clocks.
  *
- * The clock operations must lock internally to protect against
- * read-modify-write on registers that are shared by multiple clocks
  */
 static DEFINE_MUTEX(clock_list_lock);
 static LIST_HEAD(clocks);
 
-struct clk *tegra_get_clock_by_name(const char *name)
-{
-	struct clk *c;
-	struct clk *ret = NULL;
-	mutex_lock(&clock_list_lock);
-	list_for_each_entry(c, &clocks, node) {
-		if (strcmp(c->name, name) == 0) {
-			ret = c;
-			break;
-		}
-	}
-	mutex_unlock(&clock_list_lock);
-	return ret;
-}
-
-/* Must be called with c->spinlock held */
-static unsigned long clk_predict_rate_from_parent(struct clk *c, struct clk *p)
-{
-	u64 rate;
-
-	rate = clk_get_rate(p);
-
-	if (c->mul != 0 && c->div != 0) {
-		rate *= c->mul;
-		rate += c->div - 1; /* round up */
-		do_div(rate, c->div);
-	}
-
-	return rate;
-}
-
-/* Must be called with c->spinlock held */
-unsigned long clk_get_rate_locked(struct clk *c)
-{
-	unsigned long rate;
-
-	if (c->parent)
-		rate = clk_predict_rate_from_parent(c, c->parent);
-	else
-		rate = c->rate;
-
-	return rate;
-}
-
-unsigned long clk_get_rate(struct clk *c)
+void tegra_clk_add(struct clk *clk)
 {
-	unsigned long flags;
-	unsigned long rate;
-
-	spin_lock_irqsave(&c->spinlock, flags);
-
-	rate = clk_get_rate_locked(c);
-
-	spin_unlock_irqrestore(&c->spinlock, flags);
-
-	return rate;
-}
-EXPORT_SYMBOL(clk_get_rate);
-
-int clk_reparent(struct clk *c, struct clk *parent)
-{
-	c->parent = parent;
-	return 0;
-}
-
-void clk_init(struct clk *c)
-{
-	spin_lock_init(&c->spinlock);
-
-	if (c->ops && c->ops->init)
-		c->ops->init(c);
-
-	if (!c->ops || !c->ops->enable) {
-		c->refcnt++;
-		c->set = true;
-		if (c->parent)
-			c->state = c->parent->state;
-		else
-			c->state = ON;
-	}
+	struct clk_tegra *c = to_clk_tegra(__clk_get_hw(clk));
 
 	mutex_lock(&clock_list_lock);
 	list_add(&c->node, &clocks);
 	mutex_unlock(&clock_list_lock);
 }
 
-int clk_enable(struct clk *c)
-{
-	int ret = 0;
-	unsigned long flags;
-
-	spin_lock_irqsave(&c->spinlock, flags);
-
-	if (c->refcnt == 0) {
-		if (c->parent) {
-			ret = clk_enable(c->parent);
-			if (ret)
-				goto out;
-		}
-
-		if (c->ops && c->ops->enable) {
-			ret = c->ops->enable(c);
-			if (ret) {
-				if (c->parent)
-					clk_disable(c->parent);
-				goto out;
-			}
-			c->state = ON;
-			c->set = true;
-		}
-	}
-	c->refcnt++;
-out:
-	spin_unlock_irqrestore(&c->spinlock, flags);
-	return ret;
-}
-EXPORT_SYMBOL(clk_enable);
-
-void clk_disable(struct clk *c)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&c->spinlock, flags);
-
-	if (c->refcnt == 0) {
-		WARN(1, "Attempting to disable clock %s with refcnt 0", c->name);
-		spin_unlock_irqrestore(&c->spinlock, flags);
-		return;
-	}
-	if (c->refcnt == 1) {
-		if (c->ops && c->ops->disable)
-			c->ops->disable(c);
-
-		if (c->parent)
-			clk_disable(c->parent);
-
-		c->state = OFF;
-	}
-	c->refcnt--;
-
-	spin_unlock_irqrestore(&c->spinlock, flags);
-}
-EXPORT_SYMBOL(clk_disable);
-
-int clk_set_parent(struct clk *c, struct clk *parent)
-{
-	int ret;
-	unsigned long flags;
-	unsigned long new_rate;
-	unsigned long old_rate;
-
-	spin_lock_irqsave(&c->spinlock, flags);
-
-	if (!c->ops || !c->ops->set_parent) {
-		ret = -ENOSYS;
-		goto out;
-	}
-
-	new_rate = clk_predict_rate_from_parent(c, parent);
-	old_rate = clk_get_rate_locked(c);
-
-	ret = c->ops->set_parent(c, parent);
-	if (ret)
-		goto out;
-
-out:
-	spin_unlock_irqrestore(&c->spinlock, flags);
-	return ret;
-}
-EXPORT_SYMBOL(clk_set_parent);
-
-struct clk *clk_get_parent(struct clk *c)
-{
-	return c->parent;
-}
-EXPORT_SYMBOL(clk_get_parent);
-
-int clk_set_rate_locked(struct clk *c, unsigned long rate)
-{
-	long new_rate;
-
-	if (!c->ops || !c->ops->set_rate)
-		return -ENOSYS;
-
-	if (rate > c->max_rate)
-		rate = c->max_rate;
-
-	if (c->ops && c->ops->round_rate) {
-		new_rate = c->ops->round_rate(c, rate);
-
-		if (new_rate < 0)
-			return new_rate;
-
-		rate = new_rate;
-	}
-
-	return c->ops->set_rate(c, rate);
-}
-
-int clk_set_rate(struct clk *c, unsigned long rate)
-{
-	int ret;
-	unsigned long flags;
-
-	spin_lock_irqsave(&c->spinlock, flags);
-
-	ret = clk_set_rate_locked(c, rate);
-
-	spin_unlock_irqrestore(&c->spinlock, flags);
-
-	return ret;
-}
-EXPORT_SYMBOL(clk_set_rate);
-
-
-/* Must be called with clocks lock and all indvidual clock locks held */
-unsigned long clk_get_rate_all_locked(struct clk *c)
+struct clk *tegra_get_clock_by_name(const char *name)
 {
-	u64 rate;
-	int mul = 1;
-	int div = 1;
-	struct clk *p = c;
-
-	while (p) {
-		c = p;
-		if (c->mul != 0 && c->div != 0) {
-			mul *= c->mul;
-			div *= c->div;
+	struct clk_tegra *c;
+	struct clk *ret = NULL;
+	mutex_lock(&clock_list_lock);
+	list_for_each_entry(c, &clocks, node) {
+		if (strcmp(__clk_get_name(c->hw.clk), name) == 0) {
+			ret = c->hw.clk;
+			break;
 		}
-		p = c->parent;
-	}
-
-	rate = c->rate;
-	rate *= mul;
-	do_div(rate, div);
-
-	return rate;
-}
-
-long clk_round_rate(struct clk *c, unsigned long rate)
-{
-	unsigned long flags;
-	long ret;
-
-	spin_lock_irqsave(&c->spinlock, flags);
-
-	if (!c->ops || !c->ops->round_rate) {
-		ret = -ENOSYS;
-		goto out;
 	}
-
-	if (rate > c->max_rate)
-		rate = c->max_rate;
-
-	ret = c->ops->round_rate(c, rate);
-
-out:
-	spin_unlock_irqrestore(&c->spinlock, flags);
+	mutex_unlock(&clock_list_lock);
 	return ret;
 }
-EXPORT_SYMBOL(clk_round_rate);
 
 static int tegra_clk_init_one_from_table(struct tegra_clk_init_table *table)
 {
 	struct clk *c;
 	struct clk *p;
+	struct clk *parent;
 
 	int ret = 0;
 
 	c = tegra_get_clock_by_name(table->name);
 
 	if (!c) {
-		pr_warning("Unable to initialize clock %s\n",
+		pr_warn("Unable to initialize clock %s\n",
 			table->name);
 		return -ENODEV;
 	}
 
+	parent = clk_get_parent(c);
+
 	if (table->parent) {
 		p = tegra_get_clock_by_name(table->parent);
 		if (!p) {
-			pr_warning("Unable to find parent %s of clock %s\n",
+			pr_warn("Unable to find parent %s of clock %s\n",
 				table->parent, table->name);
 			return -ENODEV;
 		}
 
-		if (c->parent != p) {
+		if (parent != p) {
 			ret = clk_set_parent(c, p);
 			if (ret) {
-				pr_warning("Unable to set parent %s of clock %s: %d\n",
+				pr_warn("Unable to set parent %s of clock %s: %d\n",
 					table->parent, table->name, ret);
 				return -EINVAL;
 			}
@@ -360,16 +109,16 @@ static int tegra_clk_init_one_from_table(struct tegra_clk_init_table *table)
 	if (table->rate && table->rate != clk_get_rate(c)) {
 		ret = clk_set_rate(c, table->rate);
 		if (ret) {
-			pr_warning("Unable to set clock %s to rate %lu: %d\n",
+			pr_warn("Unable to set clock %s to rate %lu: %d\n",
 				table->name, table->rate, ret);
 			return -EINVAL;
 		}
 	}
 
 	if (table->enabled) {
-		ret = clk_enable(c);
+		ret = clk_prepare_enable(c);
 		if (ret) {
-			pr_warning("Unable to enable clock %s: %d\n",
+			pr_warn("Unable to enable clock %s: %d\n",
 				table->name, ret);
 			return -EINVAL;
 		}
@@ -383,19 +132,20 @@ void tegra_clk_init_from_table(struct tegra_clk_init_table *table)
 	for (; table->name; table++)
 		tegra_clk_init_one_from_table(table);
 }
-EXPORT_SYMBOL(tegra_clk_init_from_table);
 
 void tegra_periph_reset_deassert(struct clk *c)
 {
-	BUG_ON(!c->ops->reset);
-	c->ops->reset(c, false);
+	struct clk_tegra *clk = to_clk_tegra(__clk_get_hw(c));
+	BUG_ON(!clk->reset);
+	clk->reset(__clk_get_hw(c), false);
 }
 EXPORT_SYMBOL(tegra_periph_reset_deassert);
 
 void tegra_periph_reset_assert(struct clk *c)
 {
-	BUG_ON(!c->ops->reset);
-	c->ops->reset(c, true);
+	struct clk_tegra *clk = to_clk_tegra(__clk_get_hw(c));
+	BUG_ON(!clk->reset);
+	clk->reset(__clk_get_hw(c), true);
 }
 EXPORT_SYMBOL(tegra_periph_reset_assert);
 
@@ -405,268 +155,14 @@ EXPORT_SYMBOL(tegra_periph_reset_assert);
 int tegra_clk_cfg_ex(struct clk *c, enum tegra_clk_ex_param p, u32 setting)
 {
 	int ret = 0;
-	unsigned long flags;
+	struct clk_tegra *clk = to_clk_tegra(__clk_get_hw(c));
 
-	spin_lock_irqsave(&c->spinlock, flags);
-
-	if (!c->ops || !c->ops->clk_cfg_ex) {
+	if (!clk->clk_cfg_ex) {
 		ret = -ENOSYS;
 		goto out;
 	}
-	ret = c->ops->clk_cfg_ex(c, p, setting);
+	ret = clk->clk_cfg_ex(__clk_get_hw(c), p, setting);
 
 out:
-	spin_unlock_irqrestore(&c->spinlock, flags);
-
 	return ret;
 }
-
-#ifdef CONFIG_DEBUG_FS
-
-static int __clk_lock_all_spinlocks(void)
-{
-	struct clk *c;
-
-	list_for_each_entry(c, &clocks, node)
-		if (!spin_trylock(&c->spinlock))
-			goto unlock_spinlocks;
-
-	return 0;
-
-unlock_spinlocks:
-	list_for_each_entry_continue_reverse(c, &clocks, node)
-		spin_unlock(&c->spinlock);
-
-	return -EAGAIN;
-}
-
-static void __clk_unlock_all_spinlocks(void)
-{
-	struct clk *c;
-
-	list_for_each_entry_reverse(c, &clocks, node)
-		spin_unlock(&c->spinlock);
-}
-
-/*
- * This function retries until it can take all locks, and may take
- * an arbitrarily long time to complete.
- * Must be called with irqs enabled, returns with irqs disabled
- * Must be called with clock_list_lock held
- */
-static void clk_lock_all(void)
-{
-	int ret;
-retry:
-	local_irq_disable();
-
-	ret = __clk_lock_all_spinlocks();
-	if (ret)
-		goto failed_spinlocks;
-
-	/* All locks taken successfully, return */
-	return;
-
-failed_spinlocks:
-	local_irq_enable();
-	yield();
-	goto retry;
-}
-
-/*
- * Unlocks all clocks after a clk_lock_all
- * Must be called with irqs disabled, returns with irqs enabled
- * Must be called with clock_list_lock held
- */
-static void clk_unlock_all(void)
-{
-	__clk_unlock_all_spinlocks();
-
-	local_irq_enable();
-}
-
-static struct dentry *clk_debugfs_root;
-
-
-static void clock_tree_show_one(struct seq_file *s, struct clk *c, int level)
-{
-	struct clk *child;
-	const char *state = "uninit";
-	char div[8] = {0};
-
-	if (c->state == ON)
-		state = "on";
-	else if (c->state == OFF)
-		state = "off";
-
-	if (c->mul != 0 && c->div != 0) {
-		if (c->mul > c->div) {
-			int mul = c->mul / c->div;
-			int mul2 = (c->mul * 10 / c->div) % 10;
-			int mul3 = (c->mul * 10) % c->div;
-			if (mul2 == 0 && mul3 == 0)
-				snprintf(div, sizeof(div), "x%d", mul);
-			else if (mul3 == 0)
-				snprintf(div, sizeof(div), "x%d.%d", mul, mul2);
-			else
-				snprintf(div, sizeof(div), "x%d.%d..", mul, mul2);
-		} else {
-			snprintf(div, sizeof(div), "%d%s", c->div / c->mul,
-				(c->div % c->mul) ? ".5" : "");
-		}
-	}
-
-	seq_printf(s, "%*s%c%c%-*s %-6s %-3d %-8s %-10lu\n",
-		level * 3 + 1, "",
-		c->rate > c->max_rate ? '!' : ' ',
-		!c->set ? '*' : ' ',
-		30 - level * 3, c->name,
-		state, c->refcnt, div, clk_get_rate_all_locked(c));
-
-	list_for_each_entry(child, &clocks, node) {
-		if (child->parent != c)
-			continue;
-
-		clock_tree_show_one(s, child, level + 1);
-	}
-}
-
-static int clock_tree_show(struct seq_file *s, void *data)
-{
-	struct clk *c;
-	seq_printf(s, "   clock                          state  ref div      rate\n");
-	seq_printf(s, "--------------------------------------------------------------\n");
-
-	mutex_lock(&clock_list_lock);
-
-	clk_lock_all();
-
-	list_for_each_entry(c, &clocks, node)
-		if (c->parent == NULL)
-			clock_tree_show_one(s, c, 0);
-
-	clk_unlock_all();
-
-	mutex_unlock(&clock_list_lock);
-	return 0;
-}
-
-static int clock_tree_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, clock_tree_show, inode->i_private);
-}
-
-static const struct file_operations clock_tree_fops = {
-	.open		= clock_tree_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
-static int possible_parents_show(struct seq_file *s, void *data)
-{
-	struct clk *c = s->private;
-	int i;
-
-	for (i = 0; c->inputs[i].input; i++) {
-		char *first = (i == 0) ? "" : " ";
-		seq_printf(s, "%s%s", first, c->inputs[i].input->name);
-	}
-	seq_printf(s, "\n");
-	return 0;
-}
-
-static int possible_parents_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, possible_parents_show, inode->i_private);
-}
-
-static const struct file_operations possible_parents_fops = {
-	.open		= possible_parents_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
-static int clk_debugfs_register_one(struct clk *c)
-{
-	struct dentry *d;
-
-	d = debugfs_create_dir(c->name, clk_debugfs_root);
-	if (!d)
-		return -ENOMEM;
-	c->dent = d;
-
-	d = debugfs_create_u8("refcnt", S_IRUGO, c->dent, (u8 *)&c->refcnt);
-	if (!d)
-		goto err_out;
-
-	d = debugfs_create_u32("rate", S_IRUGO, c->dent, (u32 *)&c->rate);
-	if (!d)
-		goto err_out;
-
-	d = debugfs_create_x32("flags", S_IRUGO, c->dent, (u32 *)&c->flags);
-	if (!d)
-		goto err_out;
-
-	if (c->inputs) {
-		d = debugfs_create_file("possible_parents", S_IRUGO, c->dent,
-			c, &possible_parents_fops);
-		if (!d)
-			goto err_out;
-	}
-
-	return 0;
-
-err_out:
-	debugfs_remove_recursive(c->dent);
-	return -ENOMEM;
-}
-
-static int clk_debugfs_register(struct clk *c)
-{
-	int err;
-	struct clk *pa = c->parent;
-
-	if (pa && !pa->dent) {
-		err = clk_debugfs_register(pa);
-		if (err)
-			return err;
-	}
-
-	if (!c->dent) {
-		err = clk_debugfs_register_one(c);
-		if (err)
-			return err;
-	}
-	return 0;
-}
-
-int __init tegra_clk_debugfs_init(void)
-{
-	struct clk *c;
-	struct dentry *d;
-	int err = -ENOMEM;
-
-	d = debugfs_create_dir("clock", NULL);
-	if (!d)
-		return -ENOMEM;
-	clk_debugfs_root = d;
-
-	d = debugfs_create_file("clock_tree", S_IRUGO, clk_debugfs_root, NULL,
-		&clock_tree_fops);
-	if (!d)
-		goto err_out;
-
-	list_for_each_entry(c, &clocks, node) {
-		err = clk_debugfs_register(c);
-		if (err)
-			goto err_out;
-	}
-	return 0;
-err_out:
-	debugfs_remove_recursive(clk_debugfs_root);
-	return err;
-}
-
-#endif
diff --git a/arch/arm/mach-tegra/clock.h b/arch/arm/mach-tegra/clock.h
index bc30065..2aa37f5 100644
--- a/arch/arm/mach-tegra/clock.h
+++ b/arch/arm/mach-tegra/clock.h
@@ -2,6 +2,7 @@
  * arch/arm/mach-tegra/include/mach/clock.h
  *
  * Copyright (C) 2010 Google, Inc.
+ * Copyright (c) 2012 NVIDIA CORPORATION.  All rights reserved.
  *
  * Author:
  *	Colin Cross <ccross@google.com>
@@ -20,9 +21,9 @@
 #ifndef __MACH_TEGRA_CLOCK_H
 #define __MACH_TEGRA_CLOCK_H
 
+#include <linux/clk-provider.h>
 #include <linux/clkdev.h>
 #include <linux/list.h>
-#include <linux/spinlock.h>
 
 #include <mach/clk.h>
 
@@ -52,7 +53,8 @@
 #define ENABLE_ON_INIT		(1 << 28)
 #define PERIPH_ON_APB           (1 << 29)
 
-struct clk;
+struct clk_tegra;
+#define to_clk_tegra(_hw) container_of(_hw, struct clk_tegra, hw)
 
 struct clk_mux_sel {
 	struct clk	*input;
@@ -68,47 +70,29 @@ struct clk_pll_freq_table {
 	u8		cpcon;
 };
 
-struct clk_ops {
-	void		(*init)(struct clk *);
-	int		(*enable)(struct clk *);
-	void		(*disable)(struct clk *);
-	int		(*set_parent)(struct clk *, struct clk *);
-	int		(*set_rate)(struct clk *, unsigned long);
-	long		(*round_rate)(struct clk *, unsigned long);
-	void		(*reset)(struct clk *, bool);
-	int		(*clk_cfg_ex)(struct clk *,
-				enum tegra_clk_ex_param, u32);
-};
-
 enum clk_state {
 	UNINITIALIZED = 0,
 	ON,
 	OFF,
 };
 
-struct clk {
+struct clk_tegra {
 	/* node for master clocks list */
-	struct list_head	node;		/* node for list of all clocks */
+	struct list_head	node;	/* node for list of all clocks */
 	struct clk_lookup	lookup;
+	struct clk_hw		hw;
 
-#ifdef CONFIG_DEBUG_FS
-	struct dentry		*dent;
-#endif
 	bool			set;
-	struct clk_ops		*ops;
-	unsigned long		rate;
+	unsigned long		fixed_rate;
 	unsigned long		max_rate;
 	unsigned long		min_rate;
 	u32			flags;
 	const char		*name;
 
-	u32			refcnt;
 	enum clk_state		state;
-	struct clk		*parent;
 	u32			div;
 	u32			mul;
 
-	const struct clk_mux_sel	*inputs;
 	u32				reg;
 	u32				reg_shift;
 
@@ -144,7 +128,8 @@ struct clk {
 		} shared_bus_user;
 	} u;
 
-	spinlock_t spinlock;
+	void (*reset)(struct clk_hw *, bool);
+	int (*clk_cfg_ex)(struct clk_hw *, enum tegra_clk_ex_param, u32);
 };
 
 struct clk_duplicate {
@@ -159,13 +144,10 @@ struct tegra_clk_init_table {
 	bool enabled;
 };
 
+void tegra_clk_add(struct clk *c);
 void tegra2_init_clocks(void);
 void tegra30_init_clocks(void);
-void clk_init(struct clk *clk);
 struct clk *tegra_get_clock_by_name(const char *name);
-int clk_reparent(struct clk *c, struct clk *parent);
 void tegra_clk_init_from_table(struct tegra_clk_init_table *table);
-unsigned long clk_get_rate_locked(struct clk *c);
-int clk_set_rate_locked(struct clk *c, unsigned long rate);
 
 #endif
diff --git a/arch/arm/mach-tegra/common.c b/arch/arm/mach-tegra/common.c
index 96fef6b..0b0a5f5 100644
--- a/arch/arm/mach-tegra/common.c
+++ b/arch/arm/mach-tegra/common.c
@@ -31,9 +31,11 @@
 
 #include "board.h"
 #include "clock.h"
+#include "common.h"
 #include "fuse.h"
 #include "pmc.h"
 #include "apbio.h"
+#include "sleep.h"
 
 /*
  * Storage for debug-macro.S's state.
@@ -135,6 +137,7 @@ void __init tegra20_init_early(void)
 	tegra_init_cache(0x331, 0x441);
 	tegra_pmc_init();
 	tegra_powergate_init();
+	tegra20_hotplug_init();
 }
 #endif
 #ifdef CONFIG_ARCH_TEGRA_3x_SOC
@@ -147,11 +150,11 @@ void __init tegra30_init_early(void)
 	tegra_init_cache(0x441, 0x551);
 	tegra_pmc_init();
 	tegra_powergate_init();
+	tegra30_hotplug_init();
 }
 #endif
 
 void __init tegra_init_late(void)
 {
-	tegra_clk_debugfs_init();
 	tegra_powergate_debugfs_init();
 }
diff --git a/arch/arm/mach-tegra/common.h b/arch/arm/mach-tegra/common.h
new file mode 100644
index 0000000..02f71b4
--- /dev/null
+++ b/arch/arm/mach-tegra/common.h
@@ -0,0 +1,4 @@
+extern struct smp_operations tegra_smp_ops;
+
+extern void tegra_cpu_die(unsigned int cpu);
+extern int tegra_cpu_disable(unsigned int cpu);
diff --git a/arch/arm/mach-tegra/cpu-tegra.c b/arch/arm/mach-tegra/cpu-tegra.c
index ceb52db..627bf0f 100644
--- a/arch/arm/mach-tegra/cpu-tegra.c
+++ b/arch/arm/mach-tegra/cpu-tegra.c
@@ -49,6 +49,8 @@ static struct cpufreq_frequency_table freq_table[] = {
 #define NUM_CPUS	2
 
 static struct clk *cpu_clk;
+static struct clk *pll_x_clk;
+static struct clk *pll_p_clk;
 static struct clk *emc_clk;
 
 static unsigned long target_cpu_speed[NUM_CPUS];
@@ -71,6 +73,42 @@ static unsigned int tegra_getspeed(unsigned int cpu)
 	return rate;
 }
 
+static int tegra_cpu_clk_set_rate(unsigned long rate)
+{
+	int ret;
+
+	/*
+	 * Take an extra reference to the main pll so it doesn't turn
+	 * off when we move the cpu off of it
+	 */
+	clk_prepare_enable(pll_x_clk);
+
+	ret = clk_set_parent(cpu_clk, pll_p_clk);
+	if (ret) {
+		pr_err("Failed to switch cpu to clock pll_p\n");
+		goto out;
+	}
+
+	if (rate == clk_get_rate(pll_p_clk))
+		goto out;
+
+	ret = clk_set_rate(pll_x_clk, rate);
+	if (ret) {
+		pr_err("Failed to change pll_x to %lu\n", rate);
+		goto out;
+	}
+
+	ret = clk_set_parent(cpu_clk, pll_x_clk);
+	if (ret) {
+		pr_err("Failed to switch cpu to clock pll_x\n");
+		goto out;
+	}
+
+out:
+	clk_disable_unprepare(pll_x_clk);
+	return ret;
+}
+
 static int tegra_update_cpu_speed(unsigned long rate)
 {
 	int ret = 0;
@@ -101,7 +139,7 @@ static int tegra_update_cpu_speed(unsigned long rate)
 	       freqs.old, freqs.new);
 #endif
 
-	ret = clk_set_rate(cpu_clk, freqs.new * 1000);
+	ret = tegra_cpu_clk_set_rate(freqs.new * 1000);
 	if (ret) {
 		pr_err("cpu-tegra: Failed to set cpu frequency to %d kHz\n",
 			freqs.new);
@@ -183,6 +221,14 @@ static int tegra_cpu_init(struct cpufreq_policy *policy)
 	if (IS_ERR(cpu_clk))
 		return PTR_ERR(cpu_clk);
 
+	pll_x_clk = clk_get_sys(NULL, "pll_x");
+	if (IS_ERR(pll_x_clk))
+		return PTR_ERR(pll_x_clk);
+
+	pll_p_clk = clk_get_sys(NULL, "pll_p");
+	if (IS_ERR(pll_p_clk))
+		return PTR_ERR(pll_p_clk);
+
 	emc_clk = clk_get_sys("cpu", "emc");
 	if (IS_ERR(emc_clk)) {
 		clk_put(cpu_clk);
diff --git a/arch/arm/mach-tegra/devices.c b/arch/arm/mach-tegra/devices.c
deleted file mode 100644
index c70e65f..0000000
--- a/arch/arm/mach-tegra/devices.c
+++ /dev/null
@@ -1,702 +0,0 @@
-/*
- * Copyright (C) 2010,2011 Google, Inc.
- *
- * Author:
- *	Colin Cross <ccross@android.com>
- *	Erik Gilling <ccross@android.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-
-#include <linux/resource.h>
-#include <linux/platform_device.h>
-#include <linux/dma-mapping.h>
-#include <linux/fsl_devices.h>
-#include <linux/serial_8250.h>
-#include <linux/i2c-tegra.h>
-#include <asm/pmu.h>
-#include <mach/irqs.h>
-#include <mach/iomap.h>
-#include <mach/dma.h>
-#include <mach/usb_phy.h>
-
-#include "gpio-names.h"
-#include "devices.h"
-
-static struct resource gpio_resource[] = {
-	[0] = {
-		.start	= TEGRA_GPIO_BASE,
-		.end	= TEGRA_GPIO_BASE + TEGRA_GPIO_SIZE-1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= INT_GPIO1,
-		.end	= INT_GPIO1,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[2] = {
-		.start	= INT_GPIO2,
-		.end	= INT_GPIO2,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[3] = {
-		.start	= INT_GPIO3,
-		.end	= INT_GPIO3,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[4] = {
-		.start	= INT_GPIO4,
-		.end	= INT_GPIO4,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[5] = {
-		.start	= INT_GPIO5,
-		.end	= INT_GPIO5,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[6] = {
-		.start	= INT_GPIO6,
-		.end	= INT_GPIO6,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[7] = {
-		.start	= INT_GPIO7,
-		.end	= INT_GPIO7,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device tegra_gpio_device = {
-	.name		= "tegra-gpio",
-	.id		= -1,
-	.resource	= gpio_resource,
-	.num_resources	= ARRAY_SIZE(gpio_resource),
-};
-
-static struct resource pinmux_resource[] = {
-	[0] = {
-		/* Tri-state registers */
-		.start	= TEGRA_APB_MISC_BASE + 0x14,
-		.end	= TEGRA_APB_MISC_BASE + 0x20 + 3,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		/* Mux registers */
-		.start	= TEGRA_APB_MISC_BASE + 0x80,
-		.end	= TEGRA_APB_MISC_BASE + 0x9c + 3,
-		.flags	= IORESOURCE_MEM,
-	},
-	[2] = {
-		/* Pull-up/down registers */
-		.start	= TEGRA_APB_MISC_BASE + 0xa0,
-		.end	= TEGRA_APB_MISC_BASE + 0xb0 + 3,
-		.flags	= IORESOURCE_MEM,
-	},
-	[3] = {
-		/* Pad control registers */
-		.start	= TEGRA_APB_MISC_BASE + 0x868,
-		.end	= TEGRA_APB_MISC_BASE + 0x90c + 3,
-		.flags	= IORESOURCE_MEM,
-	},
-};
-
-struct platform_device tegra_pinmux_device = {
-	.name		= "tegra20-pinctrl",
-	.id		= -1,
-	.resource	= pinmux_resource,
-	.num_resources	= ARRAY_SIZE(pinmux_resource),
-};
-
-static struct resource i2c_resource1[] = {
-	[0] = {
-		.start	= INT_I2C,
-		.end	= INT_I2C,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[1] = {
-		.start	= TEGRA_I2C_BASE,
-		.end	= TEGRA_I2C_BASE + TEGRA_I2C_SIZE-1,
-		.flags	= IORESOURCE_MEM,
-	},
-};
-
-static struct resource i2c_resource2[] = {
-	[0] = {
-		.start	= INT_I2C2,
-		.end	= INT_I2C2,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[1] = {
-		.start	= TEGRA_I2C2_BASE,
-		.end	= TEGRA_I2C2_BASE + TEGRA_I2C2_SIZE-1,
-		.flags	= IORESOURCE_MEM,
-	},
-};
-
-static struct resource i2c_resource3[] = {
-	[0] = {
-		.start	= INT_I2C3,
-		.end	= INT_I2C3,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[1] = {
-		.start	= TEGRA_I2C3_BASE,
-		.end	= TEGRA_I2C3_BASE + TEGRA_I2C3_SIZE-1,
-		.flags	= IORESOURCE_MEM,
-	},
-};
-
-static struct resource i2c_resource4[] = {
-	[0] = {
-		.start	= INT_DVC,
-		.end	= INT_DVC,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[1] = {
-		.start	= TEGRA_DVC_BASE,
-		.end	= TEGRA_DVC_BASE + TEGRA_DVC_SIZE-1,
-		.flags	= IORESOURCE_MEM,
-	},
-};
-
-static struct tegra_i2c_platform_data tegra_i2c1_platform_data = {
-	.bus_clk_rate   = 400000,
-};
-
-static struct tegra_i2c_platform_data tegra_i2c2_platform_data = {
-	.bus_clk_rate   = 400000,
-};
-
-static struct tegra_i2c_platform_data tegra_i2c3_platform_data = {
-	.bus_clk_rate   = 400000,
-};
-
-static struct tegra_i2c_platform_data tegra_dvc_platform_data = {
-	.bus_clk_rate   = 400000,
-};
-
-struct platform_device tegra_i2c_device1 = {
-	.name		= "tegra-i2c",
-	.id		= 0,
-	.resource	= i2c_resource1,
-	.num_resources	= ARRAY_SIZE(i2c_resource1),
-	.dev = {
-		.platform_data = &tegra_i2c1_platform_data,
-	},
-};
-
-struct platform_device tegra_i2c_device2 = {
-	.name		= "tegra-i2c",
-	.id		= 1,
-	.resource	= i2c_resource2,
-	.num_resources	= ARRAY_SIZE(i2c_resource2),
-	.dev = {
-		.platform_data = &tegra_i2c2_platform_data,
-	},
-};
-
-struct platform_device tegra_i2c_device3 = {
-	.name		= "tegra-i2c",
-	.id		= 2,
-	.resource	= i2c_resource3,
-	.num_resources	= ARRAY_SIZE(i2c_resource3),
-	.dev = {
-		.platform_data = &tegra_i2c3_platform_data,
-	},
-};
-
-struct platform_device tegra_i2c_device4 = {
-	.name		= "tegra-i2c",
-	.id		= 3,
-	.resource	= i2c_resource4,
-	.num_resources	= ARRAY_SIZE(i2c_resource4),
-	.dev = {
-		.platform_data = &tegra_dvc_platform_data,
-	},
-};
-
-static struct resource spi_resource1[] = {
-	[0] = {
-		.start	= INT_S_LINK1,
-		.end	= INT_S_LINK1,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[1] = {
-		.start	= TEGRA_SPI1_BASE,
-		.end	= TEGRA_SPI1_BASE + TEGRA_SPI1_SIZE-1,
-		.flags	= IORESOURCE_MEM,
-	},
-};
-
-static struct resource spi_resource2[] = {
-	[0] = {
-		.start	= INT_SPI_2,
-		.end	= INT_SPI_2,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[1] = {
-		.start	= TEGRA_SPI2_BASE,
-		.end	= TEGRA_SPI2_BASE + TEGRA_SPI2_SIZE-1,
-		.flags	= IORESOURCE_MEM,
-	},
-};
-
-static struct resource spi_resource3[] = {
-	[0] = {
-		.start	= INT_SPI_3,
-		.end	= INT_SPI_3,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[1] = {
-		.start	= TEGRA_SPI3_BASE,
-		.end	= TEGRA_SPI3_BASE + TEGRA_SPI3_SIZE-1,
-		.flags	= IORESOURCE_MEM,
-	},
-};
-
-static struct resource spi_resource4[] = {
-	[0] = {
-		.start	= INT_SPI_4,
-		.end	= INT_SPI_4,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[1] = {
-		.start	= TEGRA_SPI4_BASE,
-		.end	= TEGRA_SPI4_BASE + TEGRA_SPI4_SIZE-1,
-		.flags	= IORESOURCE_MEM,
-	},
-};
-
-struct platform_device tegra_spi_device1 = {
-	.name		= "spi_tegra",
-	.id		= 0,
-	.resource	= spi_resource1,
-	.num_resources	= ARRAY_SIZE(spi_resource1),
-	.dev		= {
-		.coherent_dma_mask	= 0xffffffff,
-	},
-};
-
-struct platform_device tegra_spi_device2 = {
-	.name		= "spi_tegra",
-	.id		= 1,
-	.resource	= spi_resource2,
-	.num_resources	= ARRAY_SIZE(spi_resource2),
-	.dev		= {
-		.coherent_dma_mask	= 0xffffffff,
-	},
-};
-
-struct platform_device tegra_spi_device3 = {
-	.name		= "spi_tegra",
-	.id		= 2,
-	.resource	= spi_resource3,
-	.num_resources	= ARRAY_SIZE(spi_resource3),
-	.dev		= {
-		.coherent_dma_mask	= 0xffffffff,
-	},
-};
-
-struct platform_device tegra_spi_device4 = {
-	.name		= "spi_tegra",
-	.id		= 3,
-	.resource	= spi_resource4,
-	.num_resources	= ARRAY_SIZE(spi_resource4),
-	.dev		= {
-		.coherent_dma_mask	= 0xffffffff,
-	},
-};
-
-
-static struct resource sdhci_resource1[] = {
-	[0] = {
-		.start	= INT_SDMMC1,
-		.end	= INT_SDMMC1,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[1] = {
-		.start	= TEGRA_SDMMC1_BASE,
-		.end	= TEGRA_SDMMC1_BASE + TEGRA_SDMMC1_SIZE-1,
-		.flags	= IORESOURCE_MEM,
-	},
-};
-
-static struct resource sdhci_resource2[] = {
-	[0] = {
-		.start	= INT_SDMMC2,
-		.end	= INT_SDMMC2,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[1] = {
-		.start	= TEGRA_SDMMC2_BASE,
-		.end	= TEGRA_SDMMC2_BASE + TEGRA_SDMMC2_SIZE-1,
-		.flags	= IORESOURCE_MEM,
-	},
-};
-
-static struct resource sdhci_resource3[] = {
-	[0] = {
-		.start	= INT_SDMMC3,
-		.end	= INT_SDMMC3,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[1] = {
-		.start	= TEGRA_SDMMC3_BASE,
-		.end	= TEGRA_SDMMC3_BASE + TEGRA_SDMMC3_SIZE-1,
-		.flags	= IORESOURCE_MEM,
-	},
-};
-
-static struct resource sdhci_resource4[] = {
-	[0] = {
-		.start	= INT_SDMMC4,
-		.end	= INT_SDMMC4,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[1] = {
-		.start	= TEGRA_SDMMC4_BASE,
-		.end	= TEGRA_SDMMC4_BASE + TEGRA_SDMMC4_SIZE-1,
-		.flags	= IORESOURCE_MEM,
-	},
-};
-
-/* board files should fill in platform_data register the devices themselvs.
- * See board-harmony.c for an example
- */
-struct platform_device tegra_sdhci_device1 = {
-	.name		= "sdhci-tegra",
-	.id		= 0,
-	.resource	= sdhci_resource1,
-	.num_resources	= ARRAY_SIZE(sdhci_resource1),
-};
-
-struct platform_device tegra_sdhci_device2 = {
-	.name		= "sdhci-tegra",
-	.id		= 1,
-	.resource	= sdhci_resource2,
-	.num_resources	= ARRAY_SIZE(sdhci_resource2),
-};
-
-struct platform_device tegra_sdhci_device3 = {
-	.name		= "sdhci-tegra",
-	.id		= 2,
-	.resource	= sdhci_resource3,
-	.num_resources	= ARRAY_SIZE(sdhci_resource3),
-};
-
-struct platform_device tegra_sdhci_device4 = {
-	.name		= "sdhci-tegra",
-	.id		= 3,
-	.resource	= sdhci_resource4,
-	.num_resources	= ARRAY_SIZE(sdhci_resource4),
-};
-
-static struct resource tegra_usb1_resources[] = {
-	[0] = {
-		.start	= TEGRA_USB_BASE,
-		.end	= TEGRA_USB_BASE + TEGRA_USB_SIZE - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= INT_USB,
-		.end	= INT_USB,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct resource tegra_usb2_resources[] = {
-	[0] = {
-		.start	= TEGRA_USB2_BASE,
-		.end	= TEGRA_USB2_BASE + TEGRA_USB2_SIZE - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= INT_USB2,
-		.end	= INT_USB2,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct resource tegra_usb3_resources[] = {
-	[0] = {
-		.start	= TEGRA_USB3_BASE,
-		.end	= TEGRA_USB3_BASE + TEGRA_USB3_SIZE - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= INT_USB3,
-		.end	= INT_USB3,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-struct tegra_ulpi_config tegra_ehci2_ulpi_phy_config = {
-	.reset_gpio = -1,
-	.clk = "cdev2",
-};
-
-struct tegra_ehci_platform_data tegra_ehci1_pdata = {
-	.operating_mode = TEGRA_USB_OTG,
-	.power_down_on_bus_suspend = 1,
-	.vbus_gpio = -1,
-};
-
-struct tegra_ehci_platform_data tegra_ehci2_pdata = {
-	.phy_config = &tegra_ehci2_ulpi_phy_config,
-	.operating_mode = TEGRA_USB_HOST,
-	.power_down_on_bus_suspend = 1,
-	.vbus_gpio = -1,
-};
-
-struct tegra_ehci_platform_data tegra_ehci3_pdata = {
-	.operating_mode = TEGRA_USB_HOST,
-	.power_down_on_bus_suspend = 1,
-	.vbus_gpio = -1,
-};
-
-static u64 tegra_ehci_dmamask = DMA_BIT_MASK(32);
-
-struct platform_device tegra_ehci1_device = {
-	.name	= "tegra-ehci",
-	.id	= 0,
-	.dev	= {
-		.dma_mask	= &tegra_ehci_dmamask,
-		.coherent_dma_mask = DMA_BIT_MASK(32),
-		.platform_data = &tegra_ehci1_pdata,
-	},
-	.resource = tegra_usb1_resources,
-	.num_resources = ARRAY_SIZE(tegra_usb1_resources),
-};
-
-struct platform_device tegra_ehci2_device = {
-	.name	= "tegra-ehci",
-	.id	= 1,
-	.dev	= {
-		.dma_mask	= &tegra_ehci_dmamask,
-		.coherent_dma_mask = DMA_BIT_MASK(32),
-		.platform_data = &tegra_ehci2_pdata,
-	},
-	.resource = tegra_usb2_resources,
-	.num_resources = ARRAY_SIZE(tegra_usb2_resources),
-};
-
-struct platform_device tegra_ehci3_device = {
-	.name	= "tegra-ehci",
-	.id	= 2,
-	.dev	= {
-		.dma_mask	= &tegra_ehci_dmamask,
-		.coherent_dma_mask = DMA_BIT_MASK(32),
-		.platform_data = &tegra_ehci3_pdata,
-	},
-	.resource = tegra_usb3_resources,
-	.num_resources = ARRAY_SIZE(tegra_usb3_resources),
-};
-
-static struct resource tegra_pmu_resources[] = {
-	[0] = {
-		.start	= INT_CPU0_PMU_INTR,
-		.end	= INT_CPU0_PMU_INTR,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[1] = {
-		.start	= INT_CPU1_PMU_INTR,
-		.end	= INT_CPU1_PMU_INTR,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device tegra_pmu_device = {
-	.name		= "arm-pmu",
-	.id		= ARM_PMU_DEVICE_CPU,
-	.num_resources	= ARRAY_SIZE(tegra_pmu_resources),
-	.resource	= tegra_pmu_resources,
-};
-
-static struct resource tegra_uarta_resources[] = {
-	[0] = {
-		.start	= TEGRA_UARTA_BASE,
-		.end	= TEGRA_UARTA_BASE + TEGRA_UARTA_SIZE - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= INT_UARTA,
-		.end	= INT_UARTA,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct resource tegra_uartb_resources[] = {
-	[0] = {
-		.start	= TEGRA_UARTB_BASE,
-		.end	= TEGRA_UARTB_BASE + TEGRA_UARTB_SIZE - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= INT_UARTB,
-		.end	= INT_UARTB,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct resource tegra_uartc_resources[] = {
-	[0] = {
-		.start	= TEGRA_UARTC_BASE,
-		.end	= TEGRA_UARTC_BASE + TEGRA_UARTC_SIZE - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= INT_UARTC,
-		.end	= INT_UARTC,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct resource tegra_uartd_resources[] = {
-	[0] = {
-		.start	= TEGRA_UARTD_BASE,
-		.end	= TEGRA_UARTD_BASE + TEGRA_UARTD_SIZE - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= INT_UARTD,
-		.end	= INT_UARTD,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct resource tegra_uarte_resources[] = {
-	[0] = {
-		.start	= TEGRA_UARTE_BASE,
-		.end	= TEGRA_UARTE_BASE + TEGRA_UARTE_SIZE - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= INT_UARTE,
-		.end	= INT_UARTE,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device tegra_uarta_device = {
-	.name	= "tegra_uart",
-	.id	= 0,
-	.num_resources	= ARRAY_SIZE(tegra_uarta_resources),
-	.resource	= tegra_uarta_resources,
-	.dev	= {
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-};
-
-struct platform_device tegra_uartb_device = {
-	.name	= "tegra_uart",
-	.id	= 1,
-	.num_resources	= ARRAY_SIZE(tegra_uartb_resources),
-	.resource	= tegra_uartb_resources,
-	.dev	= {
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-};
-
-struct platform_device tegra_uartc_device = {
-	.name	= "tegra_uart",
-	.id	= 2,
-	.num_resources	= ARRAY_SIZE(tegra_uartc_resources),
-	.resource	= tegra_uartc_resources,
-	.dev	= {
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-};
-
-struct platform_device tegra_uartd_device = {
-	.name	= "tegra_uart",
-	.id	= 3,
-	.num_resources	= ARRAY_SIZE(tegra_uartd_resources),
-	.resource	= tegra_uartd_resources,
-	.dev	= {
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-};
-
-struct platform_device tegra_uarte_device = {
-	.name	= "tegra_uart",
-	.id	= 4,
-	.num_resources	= ARRAY_SIZE(tegra_uarte_resources),
-	.resource	= tegra_uarte_resources,
-	.dev	= {
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-	},
-};
-
-static struct resource i2s_resource1[] = {
-	[0] = {
-		.start	= INT_I2S1,
-		.end	= INT_I2S1,
-		.flags	= IORESOURCE_IRQ
-	},
-	[1] = {
-		.start	= TEGRA_DMA_REQ_SEL_I2S_1,
-		.end	= TEGRA_DMA_REQ_SEL_I2S_1,
-		.flags	= IORESOURCE_DMA
-	},
-	[2] = {
-		.start	= TEGRA_I2S1_BASE,
-		.end	= TEGRA_I2S1_BASE + TEGRA_I2S1_SIZE - 1,
-		.flags	= IORESOURCE_MEM
-	}
-};
-
-static struct resource i2s_resource2[] = {
-	[0] = {
-		.start	= INT_I2S2,
-		.end	= INT_I2S2,
-		.flags	= IORESOURCE_IRQ
-	},
-	[1] = {
-		.start	= TEGRA_DMA_REQ_SEL_I2S2_1,
-		.end	= TEGRA_DMA_REQ_SEL_I2S2_1,
-		.flags	= IORESOURCE_DMA
-	},
-	[2] = {
-		.start	= TEGRA_I2S2_BASE,
-		.end	= TEGRA_I2S2_BASE + TEGRA_I2S2_SIZE - 1,
-		.flags	= IORESOURCE_MEM
-	}
-};
-
-struct platform_device tegra_i2s_device1 = {
-	.name		= "tegra20-i2s",
-	.id		= 0,
-	.resource	= i2s_resource1,
-	.num_resources	= ARRAY_SIZE(i2s_resource1),
-};
-
-struct platform_device tegra_i2s_device2 = {
-	.name		= "tegra20-i2s",
-	.id		= 1,
-	.resource	= i2s_resource2,
-	.num_resources	= ARRAY_SIZE(i2s_resource2),
-};
-
-static struct resource tegra_das_resources[] = {
-	[0] = {
-		.start = TEGRA_APB_MISC_DAS_BASE,
-		.end = TEGRA_APB_MISC_DAS_BASE + TEGRA_APB_MISC_DAS_SIZE - 1,
-		.flags = IORESOURCE_MEM,
-	},
-};
-
-struct platform_device tegra_das_device = {
-	.name		= "tegra20-das",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(tegra_das_resources),
-	.resource	= tegra_das_resources,
-};
diff --git a/arch/arm/mach-tegra/devices.h b/arch/arm/mach-tegra/devices.h
deleted file mode 100644
index 4f50527..0000000
--- a/arch/arm/mach-tegra/devices.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2010,2011 Google, Inc.
- *
- * Author:
- *	Colin Cross <ccross@android.com>
- *	Erik Gilling <ccross@android.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef __MACH_TEGRA_DEVICES_H
-#define __MACH_TEGRA_DEVICES_H
-
-#include <linux/platform_device.h>
-#include <linux/platform_data/tegra_usb.h>
-
-#include <mach/usb_phy.h>
-
-extern struct tegra_ulpi_config tegra_ehci2_ulpi_phy_config;
-
-extern struct tegra_ehci_platform_data tegra_ehci1_pdata;
-extern struct tegra_ehci_platform_data tegra_ehci2_pdata;
-extern struct tegra_ehci_platform_data tegra_ehci3_pdata;
-
-extern struct platform_device tegra_gpio_device;
-extern struct platform_device tegra_pinmux_device;
-extern struct platform_device tegra_sdhci_device1;
-extern struct platform_device tegra_sdhci_device2;
-extern struct platform_device tegra_sdhci_device3;
-extern struct platform_device tegra_sdhci_device4;
-extern struct platform_device tegra_i2c_device1;
-extern struct platform_device tegra_i2c_device2;
-extern struct platform_device tegra_i2c_device3;
-extern struct platform_device tegra_i2c_device4;
-extern struct platform_device tegra_spi_device1;
-extern struct platform_device tegra_spi_device2;
-extern struct platform_device tegra_spi_device3;
-extern struct platform_device tegra_spi_device4;
-extern struct platform_device tegra_ehci1_device;
-extern struct platform_device tegra_ehci2_device;
-extern struct platform_device tegra_ehci3_device;
-extern struct platform_device tegra_uarta_device;
-extern struct platform_device tegra_uartb_device;
-extern struct platform_device tegra_uartc_device;
-extern struct platform_device tegra_uartd_device;
-extern struct platform_device tegra_uarte_device;
-extern struct platform_device tegra_pmu_device;
-extern struct platform_device tegra_i2s_device1;
-extern struct platform_device tegra_i2s_device2;
-extern struct platform_device tegra_das_device;
-
-#endif
diff --git a/arch/arm/mach-tegra/dma.c b/arch/arm/mach-tegra/dma.c
deleted file mode 100644
index 29c5114..0000000
--- a/arch/arm/mach-tegra/dma.c
+++ /dev/null
@@ -1,823 +0,0 @@
-/*
- * arch/arm/mach-tegra/dma.c
- *
- * System DMA driver for NVIDIA Tegra SoCs
- *
- * Copyright (c) 2008-2009, NVIDIA Corporation.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-#include <linux/io.h>
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/spinlock.h>
-#include <linux/err.h>
-#include <linux/irq.h>
-#include <linux/delay.h>
-#include <linux/clk.h>
-#include <mach/dma.h>
-#include <mach/irqs.h>
-#include <mach/iomap.h>
-#include <mach/suspend.h>
-
-#include "apbio.h"
-
-#define APB_DMA_GEN				0x000
-#define GEN_ENABLE				(1<<31)
-
-#define APB_DMA_CNTRL				0x010
-
-#define APB_DMA_IRQ_MASK			0x01c
-
-#define APB_DMA_IRQ_MASK_SET			0x020
-
-#define APB_DMA_CHAN_CSR			0x000
-#define CSR_ENB					(1<<31)
-#define CSR_IE_EOC				(1<<30)
-#define CSR_HOLD				(1<<29)
-#define CSR_DIR					(1<<28)
-#define CSR_ONCE				(1<<27)
-#define CSR_FLOW				(1<<21)
-#define CSR_REQ_SEL_SHIFT			16
-#define CSR_WCOUNT_SHIFT			2
-#define CSR_WCOUNT_MASK				0xFFFC
-
-#define APB_DMA_CHAN_STA				0x004
-#define STA_BUSY				(1<<31)
-#define STA_ISE_EOC				(1<<30)
-#define STA_HALT				(1<<29)
-#define STA_PING_PONG				(1<<28)
-#define STA_COUNT_SHIFT				2
-#define STA_COUNT_MASK				0xFFFC
-
-#define APB_DMA_CHAN_AHB_PTR				0x010
-
-#define APB_DMA_CHAN_AHB_SEQ				0x014
-#define AHB_SEQ_INTR_ENB			(1<<31)
-#define AHB_SEQ_BUS_WIDTH_SHIFT			28
-#define AHB_SEQ_BUS_WIDTH_MASK			(0x7<<AHB_SEQ_BUS_WIDTH_SHIFT)
-#define AHB_SEQ_BUS_WIDTH_8			(0<<AHB_SEQ_BUS_WIDTH_SHIFT)
-#define AHB_SEQ_BUS_WIDTH_16			(1<<AHB_SEQ_BUS_WIDTH_SHIFT)
-#define AHB_SEQ_BUS_WIDTH_32			(2<<AHB_SEQ_BUS_WIDTH_SHIFT)
-#define AHB_SEQ_BUS_WIDTH_64			(3<<AHB_SEQ_BUS_WIDTH_SHIFT)
-#define AHB_SEQ_BUS_WIDTH_128			(4<<AHB_SEQ_BUS_WIDTH_SHIFT)
-#define AHB_SEQ_DATA_SWAP			(1<<27)
-#define AHB_SEQ_BURST_MASK			(0x7<<24)
-#define AHB_SEQ_BURST_1				(4<<24)
-#define AHB_SEQ_BURST_4				(5<<24)
-#define AHB_SEQ_BURST_8				(6<<24)
-#define AHB_SEQ_DBL_BUF				(1<<19)
-#define AHB_SEQ_WRAP_SHIFT			16
-#define AHB_SEQ_WRAP_MASK			(0x7<<AHB_SEQ_WRAP_SHIFT)
-
-#define APB_DMA_CHAN_APB_PTR				0x018
-
-#define APB_DMA_CHAN_APB_SEQ				0x01c
-#define APB_SEQ_BUS_WIDTH_SHIFT			28
-#define APB_SEQ_BUS_WIDTH_MASK			(0x7<<APB_SEQ_BUS_WIDTH_SHIFT)
-#define APB_SEQ_BUS_WIDTH_8			(0<<APB_SEQ_BUS_WIDTH_SHIFT)
-#define APB_SEQ_BUS_WIDTH_16			(1<<APB_SEQ_BUS_WIDTH_SHIFT)
-#define APB_SEQ_BUS_WIDTH_32			(2<<APB_SEQ_BUS_WIDTH_SHIFT)
-#define APB_SEQ_BUS_WIDTH_64			(3<<APB_SEQ_BUS_WIDTH_SHIFT)
-#define APB_SEQ_BUS_WIDTH_128			(4<<APB_SEQ_BUS_WIDTH_SHIFT)
-#define APB_SEQ_DATA_SWAP			(1<<27)
-#define APB_SEQ_WRAP_SHIFT			16
-#define APB_SEQ_WRAP_MASK			(0x7<<APB_SEQ_WRAP_SHIFT)
-
-#define TEGRA_SYSTEM_DMA_CH_NR			16
-#define TEGRA_SYSTEM_DMA_AVP_CH_NUM		4
-#define TEGRA_SYSTEM_DMA_CH_MIN			0
-#define TEGRA_SYSTEM_DMA_CH_MAX	\
-	(TEGRA_SYSTEM_DMA_CH_NR - TEGRA_SYSTEM_DMA_AVP_CH_NUM - 1)
-
-#define NV_DMA_MAX_TRASFER_SIZE 0x10000
-
-static const unsigned int ahb_addr_wrap_table[8] = {
-	0, 32, 64, 128, 256, 512, 1024, 2048
-};
-
-static const unsigned int apb_addr_wrap_table[8] = {
-	0, 1, 2, 4, 8, 16, 32, 64
-};
-
-static const unsigned int bus_width_table[5] = {
-	8, 16, 32, 64, 128
-};
-
-#define TEGRA_DMA_NAME_SIZE 16
-struct tegra_dma_channel {
-	struct list_head	list;
-	int			id;
-	spinlock_t		lock;
-	char			name[TEGRA_DMA_NAME_SIZE];
-	void  __iomem		*addr;
-	int			mode;
-	int			irq;
-	int			req_transfer_count;
-};
-
-#define  NV_DMA_MAX_CHANNELS  32
-
-static bool tegra_dma_initialized;
-static DEFINE_MUTEX(tegra_dma_lock);
-static DEFINE_SPINLOCK(enable_lock);
-
-static DECLARE_BITMAP(channel_usage, NV_DMA_MAX_CHANNELS);
-static struct tegra_dma_channel dma_channels[NV_DMA_MAX_CHANNELS];
-
-static void tegra_dma_update_hw(struct tegra_dma_channel *ch,
-	struct tegra_dma_req *req);
-static void tegra_dma_update_hw_partial(struct tegra_dma_channel *ch,
-	struct tegra_dma_req *req);
-static void tegra_dma_stop(struct tegra_dma_channel *ch);
-
-void tegra_dma_flush(struct tegra_dma_channel *ch)
-{
-}
-EXPORT_SYMBOL(tegra_dma_flush);
-
-void tegra_dma_dequeue(struct tegra_dma_channel *ch)
-{
-	struct tegra_dma_req *req;
-
-	if (tegra_dma_is_empty(ch))
-		return;
-
-	req = list_entry(ch->list.next, typeof(*req), node);
-
-	tegra_dma_dequeue_req(ch, req);
-	return;
-}
-
-static void tegra_dma_stop(struct tegra_dma_channel *ch)
-{
-	u32 csr;
-	u32 status;
-
-	csr = readl(ch->addr + APB_DMA_CHAN_CSR);
-	csr &= ~CSR_IE_EOC;
-	writel(csr, ch->addr + APB_DMA_CHAN_CSR);
-
-	csr &= ~CSR_ENB;
-	writel(csr, ch->addr + APB_DMA_CHAN_CSR);
-
-	status = readl(ch->addr + APB_DMA_CHAN_STA);
-	if (status & STA_ISE_EOC)
-		writel(status, ch->addr + APB_DMA_CHAN_STA);
-}
-
-static int tegra_dma_cancel(struct tegra_dma_channel *ch)
-{
-	unsigned long irq_flags;
-
-	spin_lock_irqsave(&ch->lock, irq_flags);
-	while (!list_empty(&ch->list))
-		list_del(ch->list.next);
-
-	tegra_dma_stop(ch);
-
-	spin_unlock_irqrestore(&ch->lock, irq_flags);
-	return 0;
-}
-
-static unsigned int get_channel_status(struct tegra_dma_channel *ch,
-			struct tegra_dma_req *req, bool is_stop_dma)
-{
-	void __iomem *addr = IO_ADDRESS(TEGRA_APB_DMA_BASE);
-	unsigned int status;
-
-	if (is_stop_dma) {
-		/*
-		 * STOP the DMA and get the transfer count.
-		 * Getting the transfer count is tricky.
-		 *  - Globally disable DMA on all channels
-		 *  - Read the channel's status register to know the number
-		 *    of pending bytes to be transfered.
-		 *  - Stop the dma channel
-		 *  - Globally re-enable DMA to resume other transfers
-		 */
-		spin_lock(&enable_lock);
-		writel(0, addr + APB_DMA_GEN);
-		udelay(20);
-		status = readl(ch->addr + APB_DMA_CHAN_STA);
-		tegra_dma_stop(ch);
-		writel(GEN_ENABLE, addr + APB_DMA_GEN);
-		spin_unlock(&enable_lock);
-		if (status & STA_ISE_EOC) {
-			pr_err("Got Dma Int here clearing");
-			writel(status, ch->addr + APB_DMA_CHAN_STA);
-		}
-		req->status = TEGRA_DMA_REQ_ERROR_ABORTED;
-	} else {
-		status = readl(ch->addr + APB_DMA_CHAN_STA);
-	}
-	return status;
-}
-
-/* should be called with the channel lock held */
-static unsigned int dma_active_count(struct tegra_dma_channel *ch,
-	struct tegra_dma_req *req, unsigned int status)
-{
-	unsigned int to_transfer;
-	unsigned int req_transfer_count;
-	unsigned int bytes_transferred;
-
-	to_transfer = ((status & STA_COUNT_MASK) >> STA_COUNT_SHIFT) + 1;
-	req_transfer_count = ch->req_transfer_count + 1;
-	bytes_transferred = req_transfer_count;
-	if (status & STA_BUSY)
-		bytes_transferred -= to_transfer;
-	/*
-	 * In continuous transfer mode, DMA only tracks the count of the
-	 * half DMA buffer. So, if the DMA already finished half the DMA
-	 * then add the half buffer to the completed count.
-	 */
-	if (ch->mode & TEGRA_DMA_MODE_CONTINOUS) {
-		if (req->buffer_status == TEGRA_DMA_REQ_BUF_STATUS_HALF_FULL)
-			bytes_transferred += req_transfer_count;
-		if (status & STA_ISE_EOC)
-			bytes_transferred += req_transfer_count;
-	}
-	bytes_transferred *= 4;
-	return bytes_transferred;
-}
-
-int tegra_dma_dequeue_req(struct tegra_dma_channel *ch,
-	struct tegra_dma_req *_req)
-{
-	unsigned int status;
-	struct tegra_dma_req *req = NULL;
-	int found = 0;
-	unsigned long irq_flags;
-	int stop = 0;
-
-	spin_lock_irqsave(&ch->lock, irq_flags);
-
-	if (list_entry(ch->list.next, struct tegra_dma_req, node) == _req)
-		stop = 1;
-
-	list_for_each_entry(req, &ch->list, node) {
-		if (req == _req) {
-			list_del(&req->node);
-			found = 1;
-			break;
-		}
-	}
-	if (!found) {
-		spin_unlock_irqrestore(&ch->lock, irq_flags);
-		return 0;
-	}
-
-	if (!stop)
-		goto skip_stop_dma;
-
-	status = get_channel_status(ch, req, true);
-	req->bytes_transferred = dma_active_count(ch, req, status);
-
-	if (!list_empty(&ch->list)) {
-		/* if the list is not empty, queue the next request */
-		struct tegra_dma_req *next_req;
-		next_req = list_entry(ch->list.next,
-			typeof(*next_req), node);
-		tegra_dma_update_hw(ch, next_req);
-	}
-
-skip_stop_dma:
-	req->status = -TEGRA_DMA_REQ_ERROR_ABORTED;
-
-	spin_unlock_irqrestore(&ch->lock, irq_flags);
-
-	/* Callback should be called without any lock */
-	req->complete(req);
-	return 0;
-}
-EXPORT_SYMBOL(tegra_dma_dequeue_req);
-
-bool tegra_dma_is_empty(struct tegra_dma_channel *ch)
-{
-	unsigned long irq_flags;
-	bool is_empty;
-
-	spin_lock_irqsave(&ch->lock, irq_flags);
-	if (list_empty(&ch->list))
-		is_empty = true;
-	else
-		is_empty = false;
-	spin_unlock_irqrestore(&ch->lock, irq_flags);
-	return is_empty;
-}
-EXPORT_SYMBOL(tegra_dma_is_empty);
-
-bool tegra_dma_is_req_inflight(struct tegra_dma_channel *ch,
-	struct tegra_dma_req *_req)
-{
-	unsigned long irq_flags;
-	struct tegra_dma_req *req;
-
-	spin_lock_irqsave(&ch->lock, irq_flags);
-	list_for_each_entry(req, &ch->list, node) {
-		if (req == _req) {
-			spin_unlock_irqrestore(&ch->lock, irq_flags);
-			return true;
-		}
-	}
-	spin_unlock_irqrestore(&ch->lock, irq_flags);
-	return false;
-}
-EXPORT_SYMBOL(tegra_dma_is_req_inflight);
-
-int tegra_dma_enqueue_req(struct tegra_dma_channel *ch,
-	struct tegra_dma_req *req)
-{
-	unsigned long irq_flags;
-	struct tegra_dma_req *_req;
-	int start_dma = 0;
-
-	if (req->size > NV_DMA_MAX_TRASFER_SIZE ||
-		req->source_addr & 0x3 || req->dest_addr & 0x3) {
-		pr_err("Invalid DMA request for channel %d\n", ch->id);
-		return -EINVAL;
-	}
-
-	spin_lock_irqsave(&ch->lock, irq_flags);
-
-	list_for_each_entry(_req, &ch->list, node) {
-		if (req == _req) {
-		    spin_unlock_irqrestore(&ch->lock, irq_flags);
-		    return -EEXIST;
-		}
-	}
-
-	req->bytes_transferred = 0;
-	req->status = 0;
-	req->buffer_status = 0;
-	if (list_empty(&ch->list))
-		start_dma = 1;
-
-	list_add_tail(&req->node, &ch->list);
-
-	if (start_dma)
-		tegra_dma_update_hw(ch, req);
-
-	spin_unlock_irqrestore(&ch->lock, irq_flags);
-
-	return 0;
-}
-EXPORT_SYMBOL(tegra_dma_enqueue_req);
-
-struct tegra_dma_channel *tegra_dma_allocate_channel(int mode)
-{
-	int channel;
-	struct tegra_dma_channel *ch = NULL;
-
-	if (!tegra_dma_initialized)
-		return NULL;
-
-	mutex_lock(&tegra_dma_lock);
-
-	/* first channel is the shared channel */
-	if (mode & TEGRA_DMA_SHARED) {
-		channel = TEGRA_SYSTEM_DMA_CH_MIN;
-	} else {
-		channel = find_first_zero_bit(channel_usage,
-			ARRAY_SIZE(dma_channels));
-		if (channel >= ARRAY_SIZE(dma_channels))
-			goto out;
-	}
-	__set_bit(channel, channel_usage);
-	ch = &dma_channels[channel];
-	ch->mode = mode;
-
-out:
-	mutex_unlock(&tegra_dma_lock);
-	return ch;
-}
-EXPORT_SYMBOL(tegra_dma_allocate_channel);
-
-void tegra_dma_free_channel(struct tegra_dma_channel *ch)
-{
-	if (ch->mode & TEGRA_DMA_SHARED)
-		return;
-	tegra_dma_cancel(ch);
-	mutex_lock(&tegra_dma_lock);
-	__clear_bit(ch->id, channel_usage);
-	mutex_unlock(&tegra_dma_lock);
-}
-EXPORT_SYMBOL(tegra_dma_free_channel);
-
-static void tegra_dma_update_hw_partial(struct tegra_dma_channel *ch,
-	struct tegra_dma_req *req)
-{
-	u32 apb_ptr;
-	u32 ahb_ptr;
-
-	if (req->to_memory) {
-		apb_ptr = req->source_addr;
-		ahb_ptr = req->dest_addr;
-	} else {
-		apb_ptr = req->dest_addr;
-		ahb_ptr = req->source_addr;
-	}
-	writel(apb_ptr, ch->addr + APB_DMA_CHAN_APB_PTR);
-	writel(ahb_ptr, ch->addr + APB_DMA_CHAN_AHB_PTR);
-
-	req->status = TEGRA_DMA_REQ_INFLIGHT;
-	return;
-}
-
-static void tegra_dma_update_hw(struct tegra_dma_channel *ch,
-	struct tegra_dma_req *req)
-{
-	int ahb_addr_wrap;
-	int apb_addr_wrap;
-	int ahb_bus_width;
-	int apb_bus_width;
-	int index;
-
-	u32 ahb_seq;
-	u32 apb_seq;
-	u32 ahb_ptr;
-	u32 apb_ptr;
-	u32 csr;
-
-	csr = CSR_IE_EOC | CSR_FLOW;
-	ahb_seq = AHB_SEQ_INTR_ENB | AHB_SEQ_BURST_1;
-	apb_seq = 0;
-
-	csr |= req->req_sel << CSR_REQ_SEL_SHIFT;
-
-	/* One shot mode is always single buffered,
-	 * continuous mode is always double buffered
-	 * */
-	if (ch->mode & TEGRA_DMA_MODE_ONESHOT) {
-		csr |= CSR_ONCE;
-		ch->req_transfer_count = (req->size >> 2) - 1;
-	} else {
-		ahb_seq |= AHB_SEQ_DBL_BUF;
-
-		/* In double buffered mode, we set the size to half the
-		 * requested size and interrupt when half the buffer
-		 * is full */
-		ch->req_transfer_count = (req->size >> 3) - 1;
-	}
-
-	csr |= ch->req_transfer_count << CSR_WCOUNT_SHIFT;
-
-	if (req->to_memory) {
-		apb_ptr = req->source_addr;
-		ahb_ptr = req->dest_addr;
-
-		apb_addr_wrap = req->source_wrap;
-		ahb_addr_wrap = req->dest_wrap;
-		apb_bus_width = req->source_bus_width;
-		ahb_bus_width = req->dest_bus_width;
-
-	} else {
-		csr |= CSR_DIR;
-		apb_ptr = req->dest_addr;
-		ahb_ptr = req->source_addr;
-
-		apb_addr_wrap = req->dest_wrap;
-		ahb_addr_wrap = req->source_wrap;
-		apb_bus_width = req->dest_bus_width;
-		ahb_bus_width = req->source_bus_width;
-	}
-
-	apb_addr_wrap >>= 2;
-	ahb_addr_wrap >>= 2;
-
-	/* set address wrap for APB size */
-	index = 0;
-	do  {
-		if (apb_addr_wrap_table[index] == apb_addr_wrap)
-			break;
-		index++;
-	} while (index < ARRAY_SIZE(apb_addr_wrap_table));
-	BUG_ON(index == ARRAY_SIZE(apb_addr_wrap_table));
-	apb_seq |= index << APB_SEQ_WRAP_SHIFT;
-
-	/* set address wrap for AHB size */
-	index = 0;
-	do  {
-		if (ahb_addr_wrap_table[index] == ahb_addr_wrap)
-			break;
-		index++;
-	} while (index < ARRAY_SIZE(ahb_addr_wrap_table));
-	BUG_ON(index == ARRAY_SIZE(ahb_addr_wrap_table));
-	ahb_seq |= index << AHB_SEQ_WRAP_SHIFT;
-
-	for (index = 0; index < ARRAY_SIZE(bus_width_table); index++) {
-		if (bus_width_table[index] == ahb_bus_width)
-			break;
-	}
-	BUG_ON(index == ARRAY_SIZE(bus_width_table));
-	ahb_seq |= index << AHB_SEQ_BUS_WIDTH_SHIFT;
-
-	for (index = 0; index < ARRAY_SIZE(bus_width_table); index++) {
-		if (bus_width_table[index] == apb_bus_width)
-			break;
-	}
-	BUG_ON(index == ARRAY_SIZE(bus_width_table));
-	apb_seq |= index << APB_SEQ_BUS_WIDTH_SHIFT;
-
-	writel(csr, ch->addr + APB_DMA_CHAN_CSR);
-	writel(apb_seq, ch->addr + APB_DMA_CHAN_APB_SEQ);
-	writel(apb_ptr, ch->addr + APB_DMA_CHAN_APB_PTR);
-	writel(ahb_seq, ch->addr + APB_DMA_CHAN_AHB_SEQ);
-	writel(ahb_ptr, ch->addr + APB_DMA_CHAN_AHB_PTR);
-
-	csr |= CSR_ENB;
-	writel(csr, ch->addr + APB_DMA_CHAN_CSR);
-
-	req->status = TEGRA_DMA_REQ_INFLIGHT;
-}
-
-static void handle_oneshot_dma(struct tegra_dma_channel *ch)
-{
-	struct tegra_dma_req *req;
-	unsigned long irq_flags;
-
-	spin_lock_irqsave(&ch->lock, irq_flags);
-	if (list_empty(&ch->list)) {
-		spin_unlock_irqrestore(&ch->lock, irq_flags);
-		return;
-	}
-
-	req = list_entry(ch->list.next, typeof(*req), node);
-	if (req) {
-		int bytes_transferred;
-
-		bytes_transferred = ch->req_transfer_count;
-		bytes_transferred += 1;
-		bytes_transferred <<= 2;
-
-		list_del(&req->node);
-		req->bytes_transferred = bytes_transferred;
-		req->status = TEGRA_DMA_REQ_SUCCESS;
-
-		spin_unlock_irqrestore(&ch->lock, irq_flags);
-		/* Callback should be called without any lock */
-		pr_debug("%s: transferred %d bytes\n", __func__,
-			req->bytes_transferred);
-		req->complete(req);
-		spin_lock_irqsave(&ch->lock, irq_flags);
-	}
-
-	if (!list_empty(&ch->list)) {
-		req = list_entry(ch->list.next, typeof(*req), node);
-		/* the complete function we just called may have enqueued
-		   another req, in which case dma has already started */
-		if (req->status != TEGRA_DMA_REQ_INFLIGHT)
-			tegra_dma_update_hw(ch, req);
-	}
-	spin_unlock_irqrestore(&ch->lock, irq_flags);
-}
-
-static void handle_continuous_dma(struct tegra_dma_channel *ch)
-{
-	struct tegra_dma_req *req;
-	unsigned long irq_flags;
-
-	spin_lock_irqsave(&ch->lock, irq_flags);
-	if (list_empty(&ch->list)) {
-		spin_unlock_irqrestore(&ch->lock, irq_flags);
-		return;
-	}
-
-	req = list_entry(ch->list.next, typeof(*req), node);
-	if (req) {
-		if (req->buffer_status == TEGRA_DMA_REQ_BUF_STATUS_EMPTY) {
-			bool is_dma_ping_complete;
-			is_dma_ping_complete = (readl(ch->addr + APB_DMA_CHAN_STA)
-						& STA_PING_PONG) ? true : false;
-			if (req->to_memory)
-				is_dma_ping_complete = !is_dma_ping_complete;
-			/* Out of sync - Release current buffer */
-			if (!is_dma_ping_complete) {
-				int bytes_transferred;
-
-				bytes_transferred = ch->req_transfer_count;
-				bytes_transferred += 1;
-				bytes_transferred <<= 3;
-				req->buffer_status = TEGRA_DMA_REQ_BUF_STATUS_FULL;
-				req->bytes_transferred = bytes_transferred;
-				req->status = TEGRA_DMA_REQ_SUCCESS;
-				tegra_dma_stop(ch);
-
-				if (!list_is_last(&req->node, &ch->list)) {
-					struct tegra_dma_req *next_req;
-
-					next_req = list_entry(req->node.next,
-						typeof(*next_req), node);
-					tegra_dma_update_hw(ch, next_req);
-				}
-
-				list_del(&req->node);
-
-				/* DMA lock is NOT held when callbak is called */
-				spin_unlock_irqrestore(&ch->lock, irq_flags);
-				req->complete(req);
-				return;
-			}
-			/* Load the next request into the hardware, if available
-			 * */
-			if (!list_is_last(&req->node, &ch->list)) {
-				struct tegra_dma_req *next_req;
-
-				next_req = list_entry(req->node.next,
-					typeof(*next_req), node);
-				tegra_dma_update_hw_partial(ch, next_req);
-			}
-			req->buffer_status = TEGRA_DMA_REQ_BUF_STATUS_HALF_FULL;
-			req->status = TEGRA_DMA_REQ_SUCCESS;
-			/* DMA lock is NOT held when callback is called */
-			spin_unlock_irqrestore(&ch->lock, irq_flags);
-			if (likely(req->threshold))
-				req->threshold(req);
-			return;
-
-		} else if (req->buffer_status ==
-			TEGRA_DMA_REQ_BUF_STATUS_HALF_FULL) {
-			/* Callback when the buffer is completely full (i.e on
-			 * the second  interrupt */
-			int bytes_transferred;
-
-			bytes_transferred = ch->req_transfer_count;
-			bytes_transferred += 1;
-			bytes_transferred <<= 3;
-
-			req->buffer_status = TEGRA_DMA_REQ_BUF_STATUS_FULL;
-			req->bytes_transferred = bytes_transferred;
-			req->status = TEGRA_DMA_REQ_SUCCESS;
-			list_del(&req->node);
-
-			/* DMA lock is NOT held when callbak is called */
-			spin_unlock_irqrestore(&ch->lock, irq_flags);
-			req->complete(req);
-			return;
-
-		} else {
-			BUG();
-		}
-	}
-	spin_unlock_irqrestore(&ch->lock, irq_flags);
-}
-
-static irqreturn_t dma_isr(int irq, void *data)
-{
-	struct tegra_dma_channel *ch = data;
-	unsigned long status;
-
-	status = readl(ch->addr + APB_DMA_CHAN_STA);
-	if (status & STA_ISE_EOC)
-		writel(status, ch->addr + APB_DMA_CHAN_STA);
-	else {
-		pr_warning("Got a spurious ISR for DMA channel %d\n", ch->id);
-		return IRQ_HANDLED;
-	}
-	return IRQ_WAKE_THREAD;
-}
-
-static irqreturn_t dma_thread_fn(int irq, void *data)
-{
-	struct tegra_dma_channel *ch = data;
-
-	if (ch->mode & TEGRA_DMA_MODE_ONESHOT)
-		handle_oneshot_dma(ch);
-	else
-		handle_continuous_dma(ch);
-
-
-	return IRQ_HANDLED;
-}
-
-int __init tegra_dma_init(void)
-{
-	int ret = 0;
-	int i;
-	unsigned int irq;
-	void __iomem *addr;
-	struct clk *c;
-
-	bitmap_fill(channel_usage, NV_DMA_MAX_CHANNELS);
-
-	c = clk_get_sys("tegra-apbdma", NULL);
-	if (IS_ERR(c)) {
-		pr_err("Unable to get clock for APB DMA\n");
-		ret = PTR_ERR(c);
-		goto fail;
-	}
-	ret = clk_prepare_enable(c);
-	if (ret != 0) {
-		pr_err("Unable to enable clock for APB DMA\n");
-		goto fail;
-	}
-
-	addr = IO_ADDRESS(TEGRA_APB_DMA_BASE);
-	writel(GEN_ENABLE, addr + APB_DMA_GEN);
-	writel(0, addr + APB_DMA_CNTRL);
-	writel(0xFFFFFFFFul >> (31 - TEGRA_SYSTEM_DMA_CH_MAX),
-	       addr + APB_DMA_IRQ_MASK_SET);
-
-	for (i = TEGRA_SYSTEM_DMA_CH_MIN; i <= TEGRA_SYSTEM_DMA_CH_MAX; i++) {
-		struct tegra_dma_channel *ch = &dma_channels[i];
-
-		ch->id = i;
-		snprintf(ch->name, TEGRA_DMA_NAME_SIZE, "dma_channel_%d", i);
-
-		ch->addr = IO_ADDRESS(TEGRA_APB_DMA_CH0_BASE +
-			TEGRA_APB_DMA_CH0_SIZE * i);
-
-		spin_lock_init(&ch->lock);
-		INIT_LIST_HEAD(&ch->list);
-
-		irq = INT_APB_DMA_CH0 + i;
-		ret = request_threaded_irq(irq, dma_isr, dma_thread_fn, 0,
-			dma_channels[i].name, ch);
-		if (ret) {
-			pr_err("Failed to register IRQ %d for DMA %d\n",
-				irq, i);
-			goto fail;
-		}
-		ch->irq = irq;
-
-		__clear_bit(i, channel_usage);
-	}
-	/* mark the shared channel allocated */
-	__set_bit(TEGRA_SYSTEM_DMA_CH_MIN, channel_usage);
-
-	tegra_dma_initialized = true;
-
-	return 0;
-fail:
-	writel(0, addr + APB_DMA_GEN);
-	for (i = TEGRA_SYSTEM_DMA_CH_MIN; i <= TEGRA_SYSTEM_DMA_CH_MAX; i++) {
-		struct tegra_dma_channel *ch = &dma_channels[i];
-		if (ch->irq)
-			free_irq(ch->irq, ch);
-	}
-	return ret;
-}
-postcore_initcall(tegra_dma_init);
-
-#ifdef CONFIG_PM
-static u32 apb_dma[5*TEGRA_SYSTEM_DMA_CH_NR + 3];
-
-void tegra_dma_suspend(void)
-{
-	void __iomem *addr = IO_ADDRESS(TEGRA_APB_DMA_BASE);
-	u32 *ctx = apb_dma;
-	int i;
-
-	*ctx++ = readl(addr + APB_DMA_GEN);
-	*ctx++ = readl(addr + APB_DMA_CNTRL);
-	*ctx++ = readl(addr + APB_DMA_IRQ_MASK);
-
-	for (i = 0; i < TEGRA_SYSTEM_DMA_CH_NR; i++) {
-		addr = IO_ADDRESS(TEGRA_APB_DMA_CH0_BASE +
-				  TEGRA_APB_DMA_CH0_SIZE * i);
-
-		*ctx++ = readl(addr + APB_DMA_CHAN_CSR);
-		*ctx++ = readl(addr + APB_DMA_CHAN_AHB_PTR);
-		*ctx++ = readl(addr + APB_DMA_CHAN_AHB_SEQ);
-		*ctx++ = readl(addr + APB_DMA_CHAN_APB_PTR);
-		*ctx++ = readl(addr + APB_DMA_CHAN_APB_SEQ);
-	}
-}
-
-void tegra_dma_resume(void)
-{
-	void __iomem *addr = IO_ADDRESS(TEGRA_APB_DMA_BASE);
-	u32 *ctx = apb_dma;
-	int i;
-
-	writel(*ctx++, addr + APB_DMA_GEN);
-	writel(*ctx++, addr + APB_DMA_CNTRL);
-	writel(*ctx++, addr + APB_DMA_IRQ_MASK);
-
-	for (i = 0; i < TEGRA_SYSTEM_DMA_CH_NR; i++) {
-		addr = IO_ADDRESS(TEGRA_APB_DMA_CH0_BASE +
-				  TEGRA_APB_DMA_CH0_SIZE * i);
-
-		writel(*ctx++, addr + APB_DMA_CHAN_CSR);
-		writel(*ctx++, addr + APB_DMA_CHAN_AHB_PTR);
-		writel(*ctx++, addr + APB_DMA_CHAN_AHB_SEQ);
-		writel(*ctx++, addr + APB_DMA_CHAN_APB_PTR);
-		writel(*ctx++, addr + APB_DMA_CHAN_APB_SEQ);
-	}
-}
-
-#endif
diff --git a/arch/arm/mach-tegra/fuse.c b/arch/arm/mach-tegra/fuse.c
index f946d12..0b7db17 100644
--- a/arch/arm/mach-tegra/fuse.c
+++ b/arch/arm/mach-tegra/fuse.c
@@ -93,9 +93,9 @@ void tegra_init_fuse(void)
 {
 	u32 id;
 
-	u32 reg = readl(IO_TO_VIRT(TEGRA_CLK_RESET_BASE + 0x48));
+	u32 reg = readl(IO_ADDRESS(TEGRA_CLK_RESET_BASE + 0x48));
 	reg |= 1 << 28;
-	writel(reg, IO_TO_VIRT(TEGRA_CLK_RESET_BASE + 0x48));
+	writel(reg, IO_ADDRESS(TEGRA_CLK_RESET_BASE + 0x48));
 
 	reg = tegra_fuse_readl(FUSE_SKU_INFO);
 	tegra_sku_id = reg & 0xFF;
diff --git a/arch/arm/mach-tegra/headsmp.S b/arch/arm/mach-tegra/headsmp.S
index fef9c2c..6addc78 100644
--- a/arch/arm/mach-tegra/headsmp.S
+++ b/arch/arm/mach-tegra/headsmp.S
@@ -7,17 +7,13 @@
 
 #include "flowctrl.h"
 #include "reset.h"
+#include "sleep.h"
 
 #define APB_MISC_GP_HIDREV	0x804
 #define PMC_SCRATCH41	0x140
 
 #define RESET_DATA(x)	((TEGRA_RESET_##x)*4)
 
-	.macro mov32, reg, val
-	movw	\reg, #:lower16:\val
-	movt	\reg, #:upper16:\val
-	.endm
-
         .section ".text.head", "ax"
 	__CPUINIT
 
diff --git a/arch/arm/mach-tegra/hotplug.c b/arch/arm/mach-tegra/hotplug.c
index d8dc9dd..dca5141 100644
--- a/arch/arm/mach-tegra/hotplug.c
+++ b/arch/arm/mach-tegra/hotplug.c
@@ -1,123 +1,48 @@
 /*
- *  linux/arch/arm/mach-realview/hotplug.c
  *
  *  Copyright (C) 2002 ARM Ltd.
  *  All Rights Reserved
+ *  Copyright (c) 2010, 2012 NVIDIA Corporation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
 #include <linux/kernel.h>
-#include <linux/errno.h>
 #include <linux/smp.h>
 
 #include <asm/cacheflush.h>
-#include <asm/cp15.h>
+#include <asm/smp_plat.h>
 
-static inline void cpu_enter_lowpower(void)
-{
-	unsigned int v;
-
-	flush_cache_all();
-	asm volatile(
-	"	mcr	p15, 0, %1, c7, c5, 0\n"
-	"	mcr	p15, 0, %1, c7, c10, 4\n"
-	/*
-	 * Turn off coherency
-	 */
-	"	mrc	p15, 0, %0, c1, c0, 1\n"
-	"	bic	%0, %0, #0x20\n"
-	"	mcr	p15, 0, %0, c1, c0, 1\n"
-	"	mrc	p15, 0, %0, c1, c0, 0\n"
-	"	bic	%0, %0, %2\n"
-	"	mcr	p15, 0, %0, c1, c0, 0\n"
-	  : "=&r" (v)
-	  : "r" (0), "Ir" (CR_C)
-	  : "cc");
-}
-
-static inline void cpu_leave_lowpower(void)
-{
-	unsigned int v;
+#include "sleep.h"
+#include "tegra_cpu_car.h"
 
-	asm volatile(
-	"mrc	p15, 0, %0, c1, c0, 0\n"
-	"	orr	%0, %0, %1\n"
-	"	mcr	p15, 0, %0, c1, c0, 0\n"
-	"	mrc	p15, 0, %0, c1, c0, 1\n"
-	"	orr	%0, %0, #0x20\n"
-	"	mcr	p15, 0, %0, c1, c0, 1\n"
-	  : "=&r" (v)
-	  : "Ir" (CR_C)
-	  : "cc");
-}
-
-static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
-{
-	/*
-	 * there is no power-control hardware on this platform, so all
-	 * we can do is put the core into WFI; this is safe as the calling
-	 * code will have already disabled interrupts
-	 */
-	for (;;) {
-		/*
-		 * here's the WFI
-		 */
-		asm(".word	0xe320f003\n"
-		    :
-		    :
-		    : "memory", "cc");
-
-		/*if (pen_release == cpu) {*/
-			/*
-			 * OK, proper wakeup, we're done
-			 */
-			break;
-		/*}*/
-
-		/*
-		 * Getting here, means that we have come out of WFI without
-		 * having been woken up - this shouldn't happen
-		 *
-		 * Just note it happening - when we're woken, we can report
-		 * its occurrence.
-		 */
-		(*spurious)++;
-	}
-}
-
-int platform_cpu_kill(unsigned int cpu)
-{
-	return 1;
-}
+static void (*tegra_hotplug_shutdown)(void);
 
 /*
  * platform-specific code to shutdown a CPU
  *
  * Called with IRQs disabled
  */
-void platform_cpu_die(unsigned int cpu)
+void __ref tegra_cpu_die(unsigned int cpu)
 {
-	int spurious = 0;
+	cpu = cpu_logical_map(cpu);
 
-	/*
-	 * we're ready for shutdown now, so do it
-	 */
-	cpu_enter_lowpower();
-	platform_do_lowpower(cpu, &spurious);
+	/* Flush the L1 data cache. */
+	flush_cache_all();
 
-	/*
-	 * bring this CPU back into the world of cache
-	 * coherency, and then restore interrupts
-	 */
-	cpu_leave_lowpower();
+	/* Shut down the current CPU. */
+	tegra_hotplug_shutdown();
 
-	if (spurious)
-		pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
+	/* Clock gate the CPU */
+	tegra_wait_cpu_in_reset(cpu);
+	tegra_disable_cpu_clock(cpu);
+
+	/* Should never return here. */
+	BUG();
 }
 
-int platform_cpu_disable(unsigned int cpu)
+int tegra_cpu_disable(unsigned int cpu)
 {
 	/*
 	 * we don't allow CPU 0 to be shutdown (it is still too special
@@ -125,3 +50,19 @@ int platform_cpu_disable(unsigned int cpu)
 	 */
 	return cpu == 0 ? -EPERM : 0;
 }
+
+#ifdef CONFIG_ARCH_TEGRA_2x_SOC
+extern void tegra20_hotplug_shutdown(void);
+void __init tegra20_hotplug_init(void)
+{
+	tegra_hotplug_shutdown = tegra20_hotplug_shutdown;
+}
+#endif
+
+#ifdef CONFIG_ARCH_TEGRA_3x_SOC
+extern void tegra30_hotplug_shutdown(void);
+void __init tegra30_hotplug_init(void)
+{
+	tegra_hotplug_shutdown = tegra30_hotplug_shutdown;
+}
+#endif
diff --git a/arch/arm/mach-tegra/include/mach/clk.h b/arch/arm/mach-tegra/include/mach/clk.h
index d97e403..95f3a54 100644
--- a/arch/arm/mach-tegra/include/mach/clk.h
+++ b/arch/arm/mach-tegra/include/mach/clk.h
@@ -34,7 +34,10 @@ enum tegra_clk_ex_param {
 void tegra_periph_reset_deassert(struct clk *c);
 void tegra_periph_reset_assert(struct clk *c);
 
+#ifndef CONFIG_COMMON_CLK
 unsigned long clk_get_rate_all_locked(struct clk *c);
+#endif
+
 void tegra2_sdmmc_tap_delay(struct clk *c, int delay);
 int tegra_clk_cfg_ex(struct clk *c, enum tegra_clk_ex_param p, u32 setting);
 
diff --git a/arch/arm/mach-tegra/include/mach/dma.h b/arch/arm/mach-tegra/include/mach/dma.h
index 9077092..3081cc6 100644
--- a/arch/arm/mach-tegra/include/mach/dma.h
+++ b/arch/arm/mach-tegra/include/mach/dma.h
@@ -51,101 +51,4 @@
 #define TEGRA_DMA_REQ_SEL_OWR			25
 #define TEGRA_DMA_REQ_SEL_INVALID		31
 
-struct tegra_dma_req;
-struct tegra_dma_channel;
-
-enum tegra_dma_mode {
-	TEGRA_DMA_SHARED = 1,
-	TEGRA_DMA_MODE_CONTINOUS = 2,
-	TEGRA_DMA_MODE_ONESHOT = 4,
-};
-
-enum tegra_dma_req_error {
-	TEGRA_DMA_REQ_SUCCESS = 0,
-	TEGRA_DMA_REQ_ERROR_ABORTED,
-	TEGRA_DMA_REQ_INFLIGHT,
-};
-
-enum tegra_dma_req_buff_status {
-	TEGRA_DMA_REQ_BUF_STATUS_EMPTY = 0,
-	TEGRA_DMA_REQ_BUF_STATUS_HALF_FULL,
-	TEGRA_DMA_REQ_BUF_STATUS_FULL,
-};
-
-struct tegra_dma_req {
-	struct list_head node;
-	unsigned int modid;
-	int instance;
-
-	/* Called when the req is complete and from the DMA ISR context.
-	 * When this is called the req structure is no longer queued by
-	 * the DMA channel.
-	 *
-	 * State of the DMA depends on the number of req it has. If there are
-	 * no DMA requests queued up, then it will STOP the DMA. It there are
-	 * more requests in the DMA, then it will queue the next request.
-	 */
-	void (*complete)(struct tegra_dma_req *req);
-
-	/*  This is a called from the DMA ISR context when the DMA is still in
-	 *  progress and is actively filling same buffer.
-	 *
-	 *  In case of continuous mode receive, this threshold is 1/2 the buffer
-	 *  size. In other cases, this will not even be called as there is no
-	 *  hardware support for it.
-	 *
-	 * In the case of continuous mode receive, if there is next req already
-	 * queued, DMA programs the HW to use that req when this req is
-	 * completed. If there is no "next req" queued, then DMA ISR doesn't do
-	 * anything before calling this callback.
-	 *
-	 *	This is mainly used by the cases, where the clients has queued
-	 *	only one req and want to get some sort of DMA threshold
-	 *	callback to program the next buffer.
-	 *
-	 */
-	void (*threshold)(struct tegra_dma_req *req);
-
-	/* 1 to copy to memory.
-	 * 0 to copy from the memory to device FIFO */
-	int to_memory;
-
-	void *virt_addr;
-
-	unsigned long source_addr;
-	unsigned long dest_addr;
-	unsigned long dest_wrap;
-	unsigned long source_wrap;
-	unsigned long source_bus_width;
-	unsigned long dest_bus_width;
-	unsigned long req_sel;
-	unsigned int size;
-
-	/* Updated by the DMA driver on the conpletion of the request. */
-	int bytes_transferred;
-	int status;
-
-	/* DMA completion tracking information */
-	int buffer_status;
-
-	/* Client specific data */
-	void *dev;
-};
-
-int tegra_dma_enqueue_req(struct tegra_dma_channel *ch,
-	struct tegra_dma_req *req);
-int tegra_dma_dequeue_req(struct tegra_dma_channel *ch,
-	struct tegra_dma_req *req);
-void tegra_dma_dequeue(struct tegra_dma_channel *ch);
-void tegra_dma_flush(struct tegra_dma_channel *ch);
-
-bool tegra_dma_is_req_inflight(struct tegra_dma_channel *ch,
-	struct tegra_dma_req *req);
-bool tegra_dma_is_empty(struct tegra_dma_channel *ch);
-
-struct tegra_dma_channel *tegra_dma_allocate_channel(int mode);
-void tegra_dma_free_channel(struct tegra_dma_channel *ch);
-
-int __init tegra_dma_init(void);
-
 #endif
diff --git a/arch/arm/mach-tegra/include/mach/gpio-tegra.h b/arch/arm/mach-tegra/include/mach/gpio-tegra.h
deleted file mode 100644
index a978b3c..0000000
--- a/arch/arm/mach-tegra/include/mach/gpio-tegra.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * arch/arm/mach-tegra/include/mach/gpio.h
- *
- * Copyright (C) 2010 Google, Inc.
- *
- * Author:
- *	Erik Gilling <konkers@google.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef __MACH_TEGRA_GPIO_TEGRA_H
-#define __MACH_TEGRA_GPIO_TEGRA_H
-
-#include <linux/types.h>
-#include <mach/irqs.h>
-
-#define TEGRA_NR_GPIOS		INT_GPIO_NR
-
-#endif
diff --git a/arch/arm/mach-tegra/include/mach/gpio.h b/arch/arm/mach-tegra/include/mach/gpio.h
deleted file mode 100644
index 40a8c17..0000000
--- a/arch/arm/mach-tegra/include/mach/gpio.h
+++ /dev/null
@@ -1 +0,0 @@
-/* empty */
diff --git a/arch/arm/mach-tegra/include/mach/io.h b/arch/arm/mach-tegra/include/mach/io.h
deleted file mode 100644
index fe700f9..0000000
--- a/arch/arm/mach-tegra/include/mach/io.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * arch/arm/mach-tegra/include/mach/io.h
- *
- * Copyright (C) 2010 Google, Inc.
- *
- * Author:
- *	Colin Cross <ccross@google.com>
- *	Erik Gilling <konkers@google.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef __MACH_TEGRA_IO_H
-#define __MACH_TEGRA_IO_H
-
-#define IO_SPACE_LIMIT 0xffff
-
-#ifndef __ASSEMBLER__
-
-#ifdef CONFIG_TEGRA_PCI
-extern void __iomem *tegra_pcie_io_base;
-
-static inline void __iomem *__io(unsigned long addr)
-{
-	return tegra_pcie_io_base + (addr & IO_SPACE_LIMIT);
-}
-#else
-static inline void __iomem *__io(unsigned long addr)
-{
-	return (void __iomem *)addr;
-}
-#endif
-
-#define __io(a)         __io(a)
-
-#endif
-
-#endif
diff --git a/arch/arm/mach-tegra/include/mach/iomap.h b/arch/arm/mach-tegra/include/mach/iomap.h
index 7e76da7..fee3a94 100644
--- a/arch/arm/mach-tegra/include/mach/iomap.h
+++ b/arch/arm/mach-tegra/include/mach/iomap.h
@@ -303,6 +303,9 @@
 #define IO_APB_VIRT	IOMEM(0xFE300000)
 #define IO_APB_SIZE	SZ_1M
 
+#define TEGRA_PCIE_BASE		0x80000000
+#define TEGRA_PCIE_IO_BASE	(TEGRA_PCIE_BASE + SZ_4M)
+
 #define IO_TO_VIRT_BETWEEN(p, st, sz)	((p) >= (st) && (p) < ((st) + (sz)))
 #define IO_TO_VIRT_XLATE(p, pst, vst)	(((p) - (pst) + (vst)))
 
diff --git a/arch/arm/mach-tegra/include/mach/kbc.h b/arch/arm/mach-tegra/include/mach/kbc.h
deleted file mode 100644
index a130256..0000000
--- a/arch/arm/mach-tegra/include/mach/kbc.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Platform definitions for tegra-kbc keyboard input driver
- *
- * Copyright (c) 2010-2011, NVIDIA Corporation.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-
-#ifndef ASMARM_ARCH_TEGRA_KBC_H
-#define ASMARM_ARCH_TEGRA_KBC_H
-
-#include <linux/types.h>
-#include <linux/input/matrix_keypad.h>
-
-#define KBC_MAX_GPIO	24
-#define KBC_MAX_KPENT	8
-
-#define KBC_MAX_ROW	16
-#define KBC_MAX_COL	8
-#define KBC_MAX_KEY	(KBC_MAX_ROW * KBC_MAX_COL)
-
-enum tegra_pin_type {
-	PIN_CFG_IGNORE,
-	PIN_CFG_COL,
-	PIN_CFG_ROW,
-};
-
-struct tegra_kbc_pin_cfg {
-	enum tegra_pin_type type;
-	unsigned char num;
-};
-
-struct tegra_kbc_wake_key {
-	u8 row:4;
-	u8 col:4;
-};
-
-struct tegra_kbc_platform_data {
-	unsigned int debounce_cnt;
-	unsigned int repeat_cnt;
-
-	struct tegra_kbc_pin_cfg pin_cfg[KBC_MAX_GPIO];
-	const struct matrix_keymap_data *keymap_data;
-
-	u32 wakeup_key;
-	bool wakeup;
-	bool use_fn_map;
-	bool use_ghost_filter;
-};
-#endif
diff --git a/arch/arm/mach-tegra/include/mach/pinconf-tegra.h b/arch/arm/mach-tegra/include/mach/pinconf-tegra.h
deleted file mode 100644
index 1f24d30..0000000
--- a/arch/arm/mach-tegra/include/mach/pinconf-tegra.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * pinctrl configuration definitions for the NVIDIA Tegra pinmux
- *
- * Copyright (c) 2011, NVIDIA CORPORATION.  All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- */
-
-#ifndef __PINCONF_TEGRA_H__
-#define __PINCONF_TEGRA_H__
-
-enum tegra_pinconf_param {
-	/* argument: tegra_pinconf_pull */
-	TEGRA_PINCONF_PARAM_PULL,
-	/* argument: tegra_pinconf_tristate */
-	TEGRA_PINCONF_PARAM_TRISTATE,
-	/* argument: Boolean */
-	TEGRA_PINCONF_PARAM_ENABLE_INPUT,
-	/* argument: Boolean */
-	TEGRA_PINCONF_PARAM_OPEN_DRAIN,
-	/* argument: Boolean */
-	TEGRA_PINCONF_PARAM_LOCK,
-	/* argument: Boolean */
-	TEGRA_PINCONF_PARAM_IORESET,
-	/* argument: Boolean */
-	TEGRA_PINCONF_PARAM_HIGH_SPEED_MODE,
-	/* argument: Boolean */
-	TEGRA_PINCONF_PARAM_SCHMITT,
-	/* argument: Boolean */
-	TEGRA_PINCONF_PARAM_LOW_POWER_MODE,
-	/* argument: Integer, range is HW-dependant */
-	TEGRA_PINCONF_PARAM_DRIVE_DOWN_STRENGTH,
-	/* argument: Integer, range is HW-dependant */
-	TEGRA_PINCONF_PARAM_DRIVE_UP_STRENGTH,
-	/* argument: Integer, range is HW-dependant */
-	TEGRA_PINCONF_PARAM_SLEW_RATE_FALLING,
-	/* argument: Integer, range is HW-dependant */
-	TEGRA_PINCONF_PARAM_SLEW_RATE_RISING,
-};
-
-enum tegra_pinconf_pull {
-	TEGRA_PINCONFIG_PULL_NONE,
-	TEGRA_PINCONFIG_PULL_DOWN,
-	TEGRA_PINCONFIG_PULL_UP,
-};
-
-enum tegra_pinconf_tristate {
-	TEGRA_PINCONFIG_DRIVEN,
-	TEGRA_PINCONFIG_TRISTATE,
-};
-
-#define TEGRA_PINCONF_PACK(_param_, _arg_) ((_param_) << 16 | (_arg_))
-#define TEGRA_PINCONF_UNPACK_PARAM(_conf_) ((_conf_) >> 16)
-#define TEGRA_PINCONF_UNPACK_ARG(_conf_) ((_conf_) & 0xffff)
-
-#endif
diff --git a/arch/arm/mach-tegra/include/mach/sdhci.h b/arch/arm/mach-tegra/include/mach/sdhci.h
deleted file mode 100644
index 4231bc7..0000000
--- a/arch/arm/mach-tegra/include/mach/sdhci.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * include/asm-arm/arch-tegra/include/mach/sdhci.h
- *
- * Copyright (C) 2009 Palm, Inc.
- * Author: Yvonne Yip <y@palm.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-#ifndef __ASM_ARM_ARCH_TEGRA_SDHCI_H
-#define __ASM_ARM_ARCH_TEGRA_SDHCI_H
-
-#include <linux/mmc/host.h>
-
-struct tegra_sdhci_platform_data {
-	int cd_gpio;
-	int wp_gpio;
-	int power_gpio;
-	int is_8bit;
-	int pm_flags;
-};
-
-#endif
diff --git a/arch/arm/mach-tegra/include/mach/smmu.h b/arch/arm/mach-tegra/include/mach/smmu.h
deleted file mode 100644
index dad403a..0000000
--- a/arch/arm/mach-tegra/include/mach/smmu.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * IOMMU API for SMMU in Tegra30
- *
- * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef	MACH_SMMU_H
-#define	MACH_SMMU_H
-
-enum smmu_hwgrp {
-	HWGRP_AFI,
-	HWGRP_AVPC,
-	HWGRP_DC,
-	HWGRP_DCB,
-	HWGRP_EPP,
-	HWGRP_G2,
-	HWGRP_HC,
-	HWGRP_HDA,
-	HWGRP_ISP,
-	HWGRP_MPE,
-	HWGRP_NV,
-	HWGRP_NV2,
-	HWGRP_PPCS,
-	HWGRP_SATA,
-	HWGRP_VDE,
-	HWGRP_VI,
-
-	HWGRP_COUNT,
-
-	HWGRP_END = ~0,
-};
-
-#define HWG_AFI		(1 << HWGRP_AFI)
-#define HWG_AVPC	(1 << HWGRP_AVPC)
-#define HWG_DC		(1 << HWGRP_DC)
-#define HWG_DCB		(1 << HWGRP_DCB)
-#define HWG_EPP		(1 << HWGRP_EPP)
-#define HWG_G2		(1 << HWGRP_G2)
-#define HWG_HC		(1 << HWGRP_HC)
-#define HWG_HDA		(1 << HWGRP_HDA)
-#define HWG_ISP		(1 << HWGRP_ISP)
-#define HWG_MPE		(1 << HWGRP_MPE)
-#define HWG_NV		(1 << HWGRP_NV)
-#define HWG_NV2		(1 << HWGRP_NV2)
-#define HWG_PPCS	(1 << HWGRP_PPCS)
-#define HWG_SATA	(1 << HWGRP_SATA)
-#define HWG_VDE		(1 << HWGRP_VDE)
-#define HWG_VI		(1 << HWGRP_VI)
-
-#endif	/* MACH_SMMU_H */
diff --git a/arch/arm/mach-tegra/include/mach/suspend.h b/arch/arm/mach-tegra/include/mach/suspend.h
deleted file mode 100644
index 5af8715..0000000
--- a/arch/arm/mach-tegra/include/mach/suspend.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * arch/arm/mach-tegra/include/mach/suspend.h
- *
- * Copyright (C) 2010 Google, Inc.
- *
- * Author:
- *	Colin Cross <ccross@google.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-
-#ifndef _MACH_TEGRA_SUSPEND_H_
-#define _MACH_TEGRA_SUSPEND_H_
-
-void tegra_pinmux_suspend(void);
-void tegra_irq_suspend(void);
-void tegra_gpio_suspend(void);
-void tegra_clk_suspend(void);
-void tegra_dma_suspend(void);
-void tegra_timer_suspend(void);
-
-void tegra_pinmux_resume(void);
-void tegra_irq_resume(void);
-void tegra_gpio_resume(void);
-void tegra_clk_resume(void);
-void tegra_dma_resume(void);
-void tegra_timer_resume(void);
-
-#endif /* _MACH_TEGRA_SUSPEND_H_ */
diff --git a/arch/arm/mach-tegra/include/mach/tegra_wm8903_pdata.h b/arch/arm/mach-tegra/include/mach/tegra_wm8903_pdata.h
deleted file mode 100644
index 9d29334..0000000
--- a/arch/arm/mach-tegra/include/mach/tegra_wm8903_pdata.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * arch/arm/mach-tegra/include/mach/tegra_wm8903_pdata.h
- *
- * Copyright 2011 NVIDIA, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-struct tegra_wm8903_platform_data {
-	int gpio_spkr_en;
-	int gpio_hp_det;
-	int gpio_hp_mute;
-	int gpio_int_mic_en;
-	int gpio_ext_mic_en;
-};
diff --git a/arch/arm/mach-tegra/include/mach/usb_phy.h b/arch/arm/mach-tegra/include/mach/usb_phy.h
deleted file mode 100644
index 935ce9f..0000000
--- a/arch/arm/mach-tegra/include/mach/usb_phy.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * arch/arm/mach-tegra/include/mach/usb_phy.h
- *
- * Copyright (C) 2010 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef __MACH_USB_PHY_H
-#define __MACH_USB_PHY_H
-
-#include <linux/clk.h>
-#include <linux/usb/otg.h>
-
-struct tegra_utmip_config {
-	u8 hssync_start_delay;
-	u8 elastic_limit;
-	u8 idle_wait_delay;
-	u8 term_range_adj;
-	u8 xcvr_setup;
-	u8 xcvr_lsfslew;
-	u8 xcvr_lsrslew;
-};
-
-struct tegra_ulpi_config {
-	int reset_gpio;
-	const char *clk;
-};
-
-enum tegra_usb_phy_port_speed {
-	TEGRA_USB_PHY_PORT_SPEED_FULL = 0,
-	TEGRA_USB_PHY_PORT_SPEED_LOW,
-	TEGRA_USB_PHY_PORT_SPEED_HIGH,
-};
-
-enum tegra_usb_phy_mode {
-	TEGRA_USB_PHY_MODE_DEVICE,
-	TEGRA_USB_PHY_MODE_HOST,
-};
-
-struct tegra_xtal_freq;
-
-struct tegra_usb_phy {
-	int instance;
-	const struct tegra_xtal_freq *freq;
-	void __iomem *regs;
-	void __iomem *pad_regs;
-	struct clk *clk;
-	struct clk *pll_u;
-	struct clk *pad_clk;
-	enum tegra_usb_phy_mode mode;
-	void *config;
-	struct usb_phy *ulpi;
-};
-
-struct tegra_usb_phy *tegra_usb_phy_open(struct device *dev, int instance,
-	void __iomem *regs, void *config, enum tegra_usb_phy_mode phy_mode);
-
-int tegra_usb_phy_power_on(struct tegra_usb_phy *phy);
-
-void tegra_usb_phy_clk_disable(struct tegra_usb_phy *phy);
-
-void tegra_usb_phy_clk_enable(struct tegra_usb_phy *phy);
-
-void tegra_usb_phy_power_off(struct tegra_usb_phy *phy);
-
-void tegra_usb_phy_preresume(struct tegra_usb_phy *phy);
-
-void tegra_usb_phy_postresume(struct tegra_usb_phy *phy);
-
-void tegra_ehci_phy_restore_start(struct tegra_usb_phy *phy,
-				 enum tegra_usb_phy_port_speed port_speed);
-
-void tegra_ehci_phy_restore_end(struct tegra_usb_phy *phy);
-
-void tegra_usb_phy_close(struct tegra_usb_phy *phy);
-
-#endif /* __MACH_USB_PHY_H */
diff --git a/arch/arm/mach-tegra/pcie.c b/arch/arm/mach-tegra/pcie.c
index d3ad515..a8dba64 100644
--- a/arch/arm/mach-tegra/pcie.c
+++ b/arch/arm/mach-tegra/pcie.c
@@ -171,8 +171,6 @@ static void __iomem *reg_pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
  * 0x90000000 - 0x9fffffff - non-prefetchable memory
  * 0xa0000000 - 0xbfffffff - prefetchable memory
  */
-#define TEGRA_PCIE_BASE		0x80000000
-
 #define PCIE_REGS_SZ		SZ_16K
 #define PCIE_CFG_OFF		PCIE_REGS_SZ
 #define PCIE_CFG_SZ		SZ_1M
@@ -180,8 +178,6 @@ static void __iomem *reg_pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
 #define PCIE_EXT_CFG_SZ		SZ_1M
 #define PCIE_IOMAP_SZ		(PCIE_REGS_SZ + PCIE_CFG_SZ + PCIE_EXT_CFG_SZ)
 
-#define MMIO_BASE		(TEGRA_PCIE_BASE + SZ_4M)
-#define MMIO_SIZE		SZ_64K
 #define MEM_BASE_0		(TEGRA_PCIE_BASE + SZ_256M)
 #define MEM_SIZE_0		SZ_128M
 #define MEM_BASE_1		(MEM_BASE_0 + MEM_SIZE_0)
@@ -204,10 +200,9 @@ struct tegra_pcie_port {
 
 	bool			link_up;
 
-	char			io_space_name[16];
 	char			mem_space_name[16];
 	char			prefetch_space_name[20];
-	struct resource		res[3];
+	struct resource		res[2];
 };
 
 struct tegra_pcie_info {
@@ -223,17 +218,7 @@ struct tegra_pcie_info {
 	struct clk		*pll_e;
 };
 
-static struct tegra_pcie_info tegra_pcie = {
-	.res_mmio = {
-		.name = "PCI IO",
-		.start = MMIO_BASE,
-		.end = MMIO_BASE + MMIO_SIZE - 1,
-		.flags = IORESOURCE_MEM,
-	},
-};
-
-void __iomem *tegra_pcie_io_base;
-EXPORT_SYMBOL(tegra_pcie_io_base);
+static struct tegra_pcie_info tegra_pcie;
 
 static inline void afi_writel(u32 value, unsigned long offset)
 {
@@ -367,17 +352,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NVIDIA, 0x0bf1, tegra_pcie_fixup_class);
 /* Tegra PCIE requires relaxed ordering */
 static void __devinit tegra_pcie_relax_enable(struct pci_dev *dev)
 {
-	u16 val16;
-	int pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
-
-	if (pos <= 0) {
-		dev_err(&dev->dev, "skipping relaxed ordering fixup\n");
-		return;
-	}
-
-	pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &val16);
-	val16 |= PCI_EXP_DEVCTL_RELAX_EN;
-	pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, val16);
+	pcie_capability_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_RELAX_EN);
 }
 DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, tegra_pcie_relax_enable);
 
@@ -391,24 +366,7 @@ static int tegra_pcie_setup(int nr, struct pci_sys_data *sys)
 	pp = tegra_pcie.port + nr;
 	pp->root_bus_nr = sys->busnr;
 
-	/*
-	 * IORESOURCE_IO
-	 */
-	snprintf(pp->io_space_name, sizeof(pp->io_space_name),
-		 "PCIe %d I/O", pp->index);
-	pp->io_space_name[sizeof(pp->io_space_name) - 1] = 0;
-	pp->res[0].name = pp->io_space_name;
-	if (pp->index == 0) {
-		pp->res[0].start = PCIBIOS_MIN_IO;
-		pp->res[0].end = pp->res[0].start + SZ_32K - 1;
-	} else {
-		pp->res[0].start = PCIBIOS_MIN_IO + SZ_32K;
-		pp->res[0].end = IO_SPACE_LIMIT;
-	}
-	pp->res[0].flags = IORESOURCE_IO;
-	if (request_resource(&ioport_resource, &pp->res[0]))
-		panic("Request PCIe IO resource failed\n");
-	pci_add_resource_offset(&sys->resources, &pp->res[0], sys->io_offset);
+	pci_ioremap_io(nr * SZ_64K, TEGRA_PCIE_IO_BASE);
 
 	/*
 	 * IORESOURCE_MEM
@@ -416,18 +374,18 @@ static int tegra_pcie_setup(int nr, struct pci_sys_data *sys)
 	snprintf(pp->mem_space_name, sizeof(pp->mem_space_name),
 		 "PCIe %d MEM", pp->index);
 	pp->mem_space_name[sizeof(pp->mem_space_name) - 1] = 0;
-	pp->res[1].name = pp->mem_space_name;
+	pp->res[0].name = pp->mem_space_name;
 	if (pp->index == 0) {
-		pp->res[1].start = MEM_BASE_0;
-		pp->res[1].end = pp->res[1].start + MEM_SIZE_0 - 1;
+		pp->res[0].start = MEM_BASE_0;
+		pp->res[0].end = pp->res[0].start + MEM_SIZE_0 - 1;
 	} else {
-		pp->res[1].start = MEM_BASE_1;
-		pp->res[1].end = pp->res[1].start + MEM_SIZE_1 - 1;
+		pp->res[0].start = MEM_BASE_1;
+		pp->res[0].end = pp->res[0].start + MEM_SIZE_1 - 1;
 	}
-	pp->res[1].flags = IORESOURCE_MEM;
-	if (request_resource(&iomem_resource, &pp->res[1]))
+	pp->res[0].flags = IORESOURCE_MEM;
+	if (request_resource(&iomem_resource, &pp->res[0]))
 		panic("Request PCIe Memory resource failed\n");
-	pci_add_resource_offset(&sys->resources, &pp->res[1], sys->mem_offset);
+	pci_add_resource_offset(&sys->resources, &pp->res[0], sys->mem_offset);
 
 	/*
 	 * IORESOURCE_MEM | IORESOURCE_PREFETCH
@@ -435,18 +393,18 @@ static int tegra_pcie_setup(int nr, struct pci_sys_data *sys)
 	snprintf(pp->prefetch_space_name, sizeof(pp->prefetch_space_name),
 		 "PCIe %d PREFETCH MEM", pp->index);
 	pp->prefetch_space_name[sizeof(pp->prefetch_space_name) - 1] = 0;
-	pp->res[2].name = pp->prefetch_space_name;
+	pp->res[1].name = pp->prefetch_space_name;
 	if (pp->index == 0) {
-		pp->res[2].start = PREFETCH_MEM_BASE_0;
-		pp->res[2].end = pp->res[2].start + PREFETCH_MEM_SIZE_0 - 1;
+		pp->res[1].start = PREFETCH_MEM_BASE_0;
+		pp->res[1].end = pp->res[1].start + PREFETCH_MEM_SIZE_0 - 1;
 	} else {
-		pp->res[2].start = PREFETCH_MEM_BASE_1;
-		pp->res[2].end = pp->res[2].start + PREFETCH_MEM_SIZE_1 - 1;
+		pp->res[1].start = PREFETCH_MEM_BASE_1;
+		pp->res[1].end = pp->res[1].start + PREFETCH_MEM_SIZE_1 - 1;
 	}
-	pp->res[2].flags = IORESOURCE_MEM | IORESOURCE_PREFETCH;
-	if (request_resource(&iomem_resource, &pp->res[2]))
+	pp->res[1].flags = IORESOURCE_MEM | IORESOURCE_PREFETCH;
+	if (request_resource(&iomem_resource, &pp->res[1]))
 		panic("Request PCIe Prefetch Memory resource failed\n");
-	pci_add_resource_offset(&sys->resources, &pp->res[2], sys->mem_offset);
+	pci_add_resource_offset(&sys->resources, &pp->res[1], sys->mem_offset);
 
 	return 1;
 }
@@ -541,8 +499,8 @@ static void tegra_pcie_setup_translations(void)
 
 	/* Bar 2: downstream IO bar */
 	fpci_bar = ((__u32)0xfdfc << 16);
-	size = MMIO_SIZE;
-	axi_address = MMIO_BASE;
+	size = SZ_128K;
+	axi_address = TEGRA_PCIE_IO_BASE;
 	afi_writel(axi_address, AFI_AXI_BAR2_START);
 	afi_writel(size >> 12, AFI_AXI_BAR2_SZ);
 	afi_writel(fpci_bar, AFI_FPCI_BAR2);
@@ -776,7 +734,6 @@ static void tegra_pcie_clocks_put(void)
 
 static int __init tegra_pcie_get_resources(void)
 {
-	struct resource *res_mmio = &tegra_pcie.res_mmio;
 	int err;
 
 	err = tegra_pcie_clocks_get();
@@ -798,34 +755,16 @@ static int __init tegra_pcie_get_resources(void)
 		goto err_map_reg;
 	}
 
-	err = request_resource(&iomem_resource, res_mmio);
-	if (err) {
-		pr_err("PCIE: Failed to request resources: %d\n", err);
-		goto err_req_io;
-	}
-
-	tegra_pcie_io_base = ioremap_nocache(res_mmio->start,
-					     resource_size(res_mmio));
-	if (tegra_pcie_io_base == NULL) {
-		pr_err("PCIE: Failed to map IO\n");
-		err = -ENOMEM;
-		goto err_map_io;
-	}
-
 	err = request_irq(INT_PCIE_INTR, tegra_pcie_isr,
 			  IRQF_SHARED, "PCIE", &tegra_pcie);
 	if (err) {
 		pr_err("PCIE: Failed to register IRQ: %d\n", err);
-		goto err_irq;
+		goto err_req_io;
 	}
 	set_irq_flags(INT_PCIE_INTR, IRQF_VALID);
 
 	return 0;
 
-err_irq:
-	iounmap(tegra_pcie_io_base);
-err_map_io:
-	release_resource(&tegra_pcie.res_mmio);
 err_req_io:
 	iounmap(tegra_pcie.regs);
 err_map_reg:
diff --git a/arch/arm/mach-tegra/platsmp.c b/arch/arm/mach-tegra/platsmp.c
index 1a208db..81cb265 100644
--- a/arch/arm/mach-tegra/platsmp.c
+++ b/arch/arm/mach-tegra/platsmp.c
@@ -31,6 +31,9 @@
 #include "fuse.h"
 #include "flowctrl.h"
 #include "reset.h"
+#include "tegra_cpu_car.h"
+
+#include "common.h"
 
 extern void tegra_secondary_startup(void);
 
@@ -38,19 +41,8 @@ static void __iomem *scu_base = IO_ADDRESS(TEGRA_ARM_PERIF_BASE);
 
 #define EVP_CPU_RESET_VECTOR \
 	(IO_ADDRESS(TEGRA_EXCEPTION_VECTORS_BASE) + 0x100)
-#define CLK_RST_CONTROLLER_CLK_CPU_CMPLX \
-	(IO_ADDRESS(TEGRA_CLK_RESET_BASE) + 0x4c)
-#define CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET \
-	(IO_ADDRESS(TEGRA_CLK_RESET_BASE) + 0x340)
-#define CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR \
-	(IO_ADDRESS(TEGRA_CLK_RESET_BASE) + 0x344)
-#define CLK_RST_CONTROLLER_CLK_CPU_CMPLX_CLR \
-	(IO_ADDRESS(TEGRA_CLK_RESET_BASE) + 0x34c)
-
-#define CPU_CLOCK(cpu)	(0x1<<(8+cpu))
-#define CPU_RESET(cpu)	(0x1111ul<<(cpu))
-
-void __cpuinit platform_secondary_init(unsigned int cpu)
+
+static void __cpuinit tegra_secondary_init(unsigned int cpu)
 {
 	/*
 	 * if any interrupts are already enabled for the primary
@@ -63,13 +55,8 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
 
 static int tegra20_power_up_cpu(unsigned int cpu)
 {
-	u32 reg;
-
 	/* Enable the CPU clock. */
-	reg = readl(CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
-	writel(reg & ~CPU_CLOCK(cpu), CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
-	barrier();
-	reg = readl(CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
+	tegra_enable_cpu_clock(cpu);
 
 	/* Clear flow controller CSR. */
 	flowctrl_write_cpu_csr(cpu, 0);
@@ -79,7 +66,6 @@ static int tegra20_power_up_cpu(unsigned int cpu)
 
 static int tegra30_power_up_cpu(unsigned int cpu)
 {
-	u32 reg;
 	int ret, pwrgateid;
 	unsigned long timeout;
 
@@ -103,8 +89,7 @@ static int tegra30_power_up_cpu(unsigned int cpu)
 	}
 
 	/* CPU partition is powered. Enable the CPU clock. */
-	writel(CPU_CLOCK(cpu), CLK_RST_CONTROLLER_CLK_CPU_CMPLX_CLR);
-	reg = readl(CLK_RST_CONTROLLER_CLK_CPU_CMPLX_CLR);
+	tegra_enable_cpu_clock(cpu);
 	udelay(10);
 
 	/* Remove I/O clamps. */
@@ -117,7 +102,7 @@ static int tegra30_power_up_cpu(unsigned int cpu)
 	return 0;
 }
 
-int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
+static int __cpuinit tegra_boot_secondary(unsigned int cpu, struct task_struct *idle)
 {
 	int status;
 
@@ -128,8 +113,7 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
 	 * via the flow controller). This will have no effect on first boot
 	 * of the CPU since it should already be in reset.
 	 */
-	writel(CPU_RESET(cpu), CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET);
-	dmb();
+	tegra_put_cpu_in_reset(cpu);
 
 	/*
 	 * Unhalt the CPU. If the flow controller was used to power-gate the
@@ -155,8 +139,7 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
 		goto done;
 
 	/* Take the CPU out of reset. */
-	writel(CPU_RESET(cpu), CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR);
-	wmb();
+	tegra_cpu_out_of_reset(cpu);
 done:
 	return status;
 }
@@ -165,7 +148,7 @@ done:
  * Initialise the CPU possible map early - this describes the CPUs
  * which may be present or become present in the system.
  */
-void __init smp_init_cpus(void)
+static void __init tegra_smp_init_cpus(void)
 {
 	unsigned int i, ncores = scu_get_core_count(scu_base);
 
@@ -181,8 +164,19 @@ void __init smp_init_cpus(void)
 	set_smp_cross_call(gic_raise_softirq);
 }
 
-void __init platform_smp_prepare_cpus(unsigned int max_cpus)
+static void __init tegra_smp_prepare_cpus(unsigned int max_cpus)
 {
 	tegra_cpu_reset_handler_init();
 	scu_enable(scu_base);
 }
+
+struct smp_operations tegra_smp_ops __initdata = {
+	.smp_init_cpus		= tegra_smp_init_cpus,
+	.smp_prepare_cpus	= tegra_smp_prepare_cpus,
+	.smp_secondary_init	= tegra_secondary_init,
+	.smp_boot_secondary	= tegra_boot_secondary,
+#ifdef CONFIG_HOTPLUG_CPU
+	.cpu_die		= tegra_cpu_die,
+	.cpu_disable		= tegra_cpu_disable,
+#endif
+};
diff --git a/arch/arm/mach-tegra/powergate.c b/arch/arm/mach-tegra/powergate.c
index 15d5065..de0662d 100644
--- a/arch/arm/mach-tegra/powergate.c
+++ b/arch/arm/mach-tegra/powergate.c
@@ -199,7 +199,9 @@ int __init tegra_powergate_init(void)
 
 #ifdef CONFIG_DEBUG_FS
 
-static const char * const powergate_name[] = {
+static const char * const *powergate_name;
+
+static const char * const powergate_name_t20[] = {
 	[TEGRA_POWERGATE_CPU]	= "cpu",
 	[TEGRA_POWERGATE_3D]	= "3d",
 	[TEGRA_POWERGATE_VENC]	= "venc",
@@ -209,6 +211,23 @@ static const char * const powergate_name[] = {
 	[TEGRA_POWERGATE_MPE]	= "mpe",
 };
 
+static const char * const powergate_name_t30[] = {
+	[TEGRA_POWERGATE_CPU]	= "cpu0",
+	[TEGRA_POWERGATE_3D]	= "3d0",
+	[TEGRA_POWERGATE_VENC]	= "venc",
+	[TEGRA_POWERGATE_VDEC]	= "vdec",
+	[TEGRA_POWERGATE_PCIE]	= "pcie",
+	[TEGRA_POWERGATE_L2]	= "l2",
+	[TEGRA_POWERGATE_MPE]	= "mpe",
+	[TEGRA_POWERGATE_HEG]	= "heg",
+	[TEGRA_POWERGATE_SATA]	= "sata",
+	[TEGRA_POWERGATE_CPU1]	= "cpu1",
+	[TEGRA_POWERGATE_CPU2]	= "cpu2",
+	[TEGRA_POWERGATE_CPU3]	= "cpu3",
+	[TEGRA_POWERGATE_CELP]	= "celp",
+	[TEGRA_POWERGATE_3D1]	= "3d1",
+};
+
 static int powergate_show(struct seq_file *s, void *data)
 {
 	int i;
@@ -237,14 +256,24 @@ static const struct file_operations powergate_fops = {
 int __init tegra_powergate_debugfs_init(void)
 {
 	struct dentry *d;
-	int err = -ENOMEM;
 
-	d = debugfs_create_file("powergate", S_IRUGO, NULL, NULL,
-		&powergate_fops);
-	if (!d)
-		return -ENOMEM;
+	switch (tegra_chip_id) {
+	case TEGRA20:
+		powergate_name = powergate_name_t20;
+		break;
+	case TEGRA30:
+		powergate_name = powergate_name_t30;
+		break;
+	}
+
+	if (powergate_name) {
+		d = debugfs_create_file("powergate", S_IRUGO, NULL, NULL,
+			&powergate_fops);
+		if (!d)
+			return -ENOMEM;
+	}
 
-	return err;
+	return 0;
 }
 
 #endif
diff --git a/arch/arm/mach-tegra/sleep-t20.S b/arch/arm/mach-tegra/sleep-t20.S
new file mode 100644
index 0000000..a36ae41
--- /dev/null
+++ b/arch/arm/mach-tegra/sleep-t20.S
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2010-2012, NVIDIA Corporation. All rights reserved.
+ * Copyright (c) 2011, Google, Inc.
+ *
+ * Author: Colin Cross <ccross@android.com>
+ *         Gary King <gking@nvidia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/linkage.h>
+
+#include <asm/assembler.h>
+
+#include <mach/iomap.h>
+
+#include "sleep.h"
+#include "flowctrl.h"
+
+#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_PM_SLEEP)
+/*
+ * tegra20_hotplug_shutdown(void)
+ *
+ * puts the current cpu in reset
+ * should never return
+ */
+ENTRY(tegra20_hotplug_shutdown)
+	/* Turn off SMP coherency */
+	exit_smp r4, r5
+
+	/* Put this CPU down */
+	cpu_id	r0
+	bl	tegra20_cpu_shutdown
+	mov	pc, lr			@ should never get here
+ENDPROC(tegra20_hotplug_shutdown)
+
+/*
+ * tegra20_cpu_shutdown(int cpu)
+ *
+ * r0 is cpu to reset
+ *
+ * puts the specified CPU in wait-for-event mode on the flow controller
+ * and puts the CPU in reset
+ * can be called on the current cpu or another cpu
+ * if called on the current cpu, does not return
+ * MUST NOT BE CALLED FOR CPU 0.
+ *
+ * corrupts r0-r3, r12
+ */
+ENTRY(tegra20_cpu_shutdown)
+	cmp	r0, #0
+	moveq	pc, lr			@ must not be called for CPU 0
+
+	cpu_to_halt_reg r1, r0
+	ldr	r3, =TEGRA_FLOW_CTRL_VIRT
+	mov	r2, #FLOW_CTRL_WAITEVENT | FLOW_CTRL_JTAG_RESUME
+	str	r2, [r3, r1]		@ put flow controller in wait event mode
+	ldr	r2, [r3, r1]
+	isb
+	dsb
+	movw	r1, 0x1011
+	mov	r1, r1, lsl r0
+	ldr	r3, =TEGRA_CLK_RESET_VIRT
+	str	r1, [r3, #0x340]	@ put slave CPU in reset
+	isb
+	dsb
+	cpu_id	r3
+	cmp	r3, r0
+	beq	.
+	mov	pc, lr
+ENDPROC(tegra20_cpu_shutdown)
+#endif
diff --git a/arch/arm/mach-tegra/sleep-t30.S b/arch/arm/mach-tegra/sleep-t30.S
new file mode 100644
index 0000000..777d9ce
--- /dev/null
+++ b/arch/arm/mach-tegra/sleep-t30.S
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2012, NVIDIA Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/linkage.h>
+
+#include <asm/assembler.h>
+
+#include <mach/iomap.h>
+
+#include "sleep.h"
+#include "flowctrl.h"
+
+#define TEGRA30_POWER_HOTPLUG_SHUTDOWN	(1 << 27) /* Hotplug shutdown */
+
+#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_PM_SLEEP)
+/*
+ * tegra30_hotplug_shutdown(void)
+ *
+ * Powergates the current CPU.
+ * Should never return.
+ */
+ENTRY(tegra30_hotplug_shutdown)
+	/* Turn off SMP coherency */
+	exit_smp r4, r5
+
+	/* Powergate this CPU */
+	mov	r0, #TEGRA30_POWER_HOTPLUG_SHUTDOWN
+	bl	tegra30_cpu_shutdown
+	mov	pc, lr			@ should never get here
+ENDPROC(tegra30_hotplug_shutdown)
+
+/*
+ * tegra30_cpu_shutdown(unsigned long flags)
+ *
+ * Puts the current CPU in wait-for-event mode on the flow controller
+ * and powergates it -- flags (in R0) indicate the request type.
+ * Must never be called for CPU 0.
+ *
+ * corrupts r0-r4, r12
+ */
+ENTRY(tegra30_cpu_shutdown)
+	cpu_id	r3
+	cmp	r3, #0
+	moveq	pc, lr		@ Must never be called for CPU 0
+
+	ldr	r12, =TEGRA_FLOW_CTRL_VIRT
+	cpu_to_csr_reg r1, r3
+	add	r1, r1, r12	@ virtual CSR address for this CPU
+	cpu_to_halt_reg r2, r3
+	add	r2, r2, r12	@ virtual HALT_EVENTS address for this CPU
+
+	/*
+	 * Clear this CPU's "event" and "interrupt" flags and power gate
+	 * it when halting but not before it is in the "WFE" state.
+	 */
+	movw	r12, \
+		FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG | \
+		FLOW_CTRL_CSR_ENABLE
+	mov	r4, #(1 << 4)
+	orr	r12, r12, r4, lsl r3
+	str	r12, [r1]
+
+	/* Halt this CPU. */
+	mov	r3, #0x400
+delay_1:
+	subs	r3, r3, #1			@ delay as a part of wfe war.
+	bge	delay_1;
+	cpsid	a				@ disable imprecise aborts.
+	ldr	r3, [r1]			@ read CSR
+	str	r3, [r1]			@ clear CSR
+	tst	r0, #TEGRA30_POWER_HOTPLUG_SHUTDOWN
+	movne	r3, #FLOW_CTRL_WAITEVENT		@ For hotplug
+	str	r3, [r2]
+	ldr	r0, [r2]
+	b	wfe_war
+
+__cpu_reset_again:
+	dsb
+	.align 5
+	wfe					@ CPU should be power gated here
+wfe_war:
+	b	__cpu_reset_again
+
+	/*
+	 * 38 nop's, which fills reset of wfe cache line and
+	 * 4 more cachelines with nop
+	 */
+	.rept 38
+	nop
+	.endr
+	b	.				@ should never get here
+
+ENDPROC(tegra30_cpu_shutdown)
+#endif
diff --git a/arch/arm/mach-tegra/sleep.S b/arch/arm/mach-tegra/sleep.S
index d29b156..ea81554 100644
--- a/arch/arm/mach-tegra/sleep.S
+++ b/arch/arm/mach-tegra/sleep.S
@@ -29,36 +29,5 @@
 #include <mach/iomap.h>
 
 #include "flowctrl.h"
+#include "sleep.h"
 
-#define TEGRA_FLOW_CTRL_VIRT (TEGRA_FLOW_CTRL_BASE - IO_PPSB_PHYS \
-					+ IO_PPSB_VIRT)
-
-/* returns the offset of the flow controller halt register for a cpu */
-.macro cpu_to_halt_reg rd, rcpu
-	cmp	\rcpu, #0
-	subne	\rd, \rcpu, #1
-	movne	\rd, \rd, lsl #3
-	addne	\rd, \rd, #0x14
-	moveq	\rd, #0
-.endm
-
-/* returns the offset of the flow controller csr register for a cpu */
-.macro cpu_to_csr_reg rd, rcpu
-	cmp	\rcpu, #0
-	subne	\rd, \rcpu, #1
-	movne	\rd, \rd, lsl #3
-	addne	\rd, \rd, #0x18
-	moveq	\rd, #8
-.endm
-
-/* returns the ID of the current processor */
-.macro cpu_id, rd
-	mrc	p15, 0, \rd, c0, c0, 5
-	and	\rd, \rd, #0xF
-.endm
-
-/* loads a 32-bit value into a register without a data access */
-.macro mov32, reg, val
-	movw	\reg, #:lower16:\val
-	movt	\reg, #:upper16:\val
-.endm
diff --git a/arch/arm/mach-tegra/sleep.h b/arch/arm/mach-tegra/sleep.h
new file mode 100644
index 0000000..e25a7cd
--- /dev/null
+++ b/arch/arm/mach-tegra/sleep.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2010-2012, NVIDIA Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __MACH_TEGRA_SLEEP_H
+#define __MACH_TEGRA_SLEEP_H
+
+#include <mach/iomap.h>
+
+#define TEGRA_ARM_PERIF_VIRT (TEGRA_ARM_PERIF_BASE - IO_CPU_PHYS \
+					+ IO_CPU_VIRT)
+#define TEGRA_FLOW_CTRL_VIRT (TEGRA_FLOW_CTRL_BASE - IO_PPSB_PHYS \
+					+ IO_PPSB_VIRT)
+#define TEGRA_CLK_RESET_VIRT (TEGRA_CLK_RESET_BASE - IO_PPSB_PHYS \
+					+ IO_PPSB_VIRT)
+
+#ifdef __ASSEMBLY__
+/* returns the offset of the flow controller halt register for a cpu */
+.macro cpu_to_halt_reg rd, rcpu
+	cmp	\rcpu, #0
+	subne	\rd, \rcpu, #1
+	movne	\rd, \rd, lsl #3
+	addne	\rd, \rd, #0x14
+	moveq	\rd, #0
+.endm
+
+/* returns the offset of the flow controller csr register for a cpu */
+.macro cpu_to_csr_reg rd, rcpu
+	cmp	\rcpu, #0
+	subne	\rd, \rcpu, #1
+	movne	\rd, \rd, lsl #3
+	addne	\rd, \rd, #0x18
+	moveq	\rd, #8
+.endm
+
+/* returns the ID of the current processor */
+.macro cpu_id, rd
+	mrc	p15, 0, \rd, c0, c0, 5
+	and	\rd, \rd, #0xF
+.endm
+
+/* loads a 32-bit value into a register without a data access */
+.macro mov32, reg, val
+	movw	\reg, #:lower16:\val
+	movt	\reg, #:upper16:\val
+.endm
+
+/* Macro to exit SMP coherency. */
+.macro exit_smp, tmp1, tmp2
+	mrc	p15, 0, \tmp1, c1, c0, 1	@ ACTLR
+	bic	\tmp1, \tmp1, #(1<<6) | (1<<0)	@ clear ACTLR.SMP | ACTLR.FW
+	mcr	p15, 0, \tmp1, c1, c0, 1	@ ACTLR
+	isb
+	cpu_id	\tmp1
+	mov	\tmp1, \tmp1, lsl #2
+	mov	\tmp2, #0xf
+	mov	\tmp2, \tmp2, lsl \tmp1
+	mov32	\tmp1, TEGRA_ARM_PERIF_VIRT + 0xC
+	str	\tmp2, [\tmp1]			@ invalidate SCU tags for CPU
+	dsb
+.endm
+#else
+
+#ifdef CONFIG_HOTPLUG_CPU
+void tegra20_hotplug_init(void);
+void tegra30_hotplug_init(void);
+#else
+static inline void tegra20_hotplug_init(void) {}
+static inline void tegra30_hotplug_init(void) {}
+#endif
+
+#endif
+#endif
diff --git a/arch/arm/mach-tegra/tegra20_clocks.c b/arch/arm/mach-tegra/tegra20_clocks.c
new file mode 100644
index 0000000..deb873f
--- /dev/null
+++ b/arch/arm/mach-tegra/tegra20_clocks.c
@@ -0,0 +1,1624 @@
+/*
+ * arch/arm/mach-tegra/tegra20_clocks.c
+ *
+ * Copyright (C) 2010 Google, Inc.
+ * Copyright (c) 2010-2012 NVIDIA CORPORATION.  All rights reserved.
+ *
+ * Author:
+ *	Colin Cross <ccross@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/clkdev.h>
+#include <linux/clk.h>
+
+#include <mach/iomap.h>
+
+#include "clock.h"
+#include "fuse.h"
+#include "tegra2_emc.h"
+#include "tegra_cpu_car.h"
+
+#define RST_DEVICES			0x004
+#define RST_DEVICES_SET			0x300
+#define RST_DEVICES_CLR			0x304
+#define RST_DEVICES_NUM			3
+
+#define CLK_OUT_ENB			0x010
+#define CLK_OUT_ENB_SET			0x320
+#define CLK_OUT_ENB_CLR			0x324
+#define CLK_OUT_ENB_NUM			3
+
+#define CLK_MASK_ARM			0x44
+#define MISC_CLK_ENB			0x48
+
+#define OSC_CTRL			0x50
+#define OSC_CTRL_OSC_FREQ_MASK		(3<<30)
+#define OSC_CTRL_OSC_FREQ_13MHZ		(0<<30)
+#define OSC_CTRL_OSC_FREQ_19_2MHZ	(1<<30)
+#define OSC_CTRL_OSC_FREQ_12MHZ		(2<<30)
+#define OSC_CTRL_OSC_FREQ_26MHZ		(3<<30)
+#define OSC_CTRL_MASK			(0x3f2 | OSC_CTRL_OSC_FREQ_MASK)
+
+#define OSC_FREQ_DET			0x58
+#define OSC_FREQ_DET_TRIG		(1<<31)
+
+#define OSC_FREQ_DET_STATUS		0x5C
+#define OSC_FREQ_DET_BUSY		(1<<31)
+#define OSC_FREQ_DET_CNT_MASK		0xFFFF
+
+#define PERIPH_CLK_SOURCE_I2S1		0x100
+#define PERIPH_CLK_SOURCE_EMC		0x19c
+#define PERIPH_CLK_SOURCE_OSC		0x1fc
+#define PERIPH_CLK_SOURCE_NUM \
+	((PERIPH_CLK_SOURCE_OSC - PERIPH_CLK_SOURCE_I2S1) / 4)
+
+#define PERIPH_CLK_SOURCE_MASK		(3<<30)
+#define PERIPH_CLK_SOURCE_SHIFT		30
+#define PERIPH_CLK_SOURCE_PWM_MASK	(7<<28)
+#define PERIPH_CLK_SOURCE_PWM_SHIFT	28
+#define PERIPH_CLK_SOURCE_ENABLE	(1<<28)
+#define PERIPH_CLK_SOURCE_DIVU71_MASK	0xFF
+#define PERIPH_CLK_SOURCE_DIVU16_MASK	0xFFFF
+#define PERIPH_CLK_SOURCE_DIV_SHIFT	0
+
+#define SDMMC_CLK_INT_FB_SEL		(1 << 23)
+#define SDMMC_CLK_INT_FB_DLY_SHIFT	16
+#define SDMMC_CLK_INT_FB_DLY_MASK	(0xF << SDMMC_CLK_INT_FB_DLY_SHIFT)
+
+#define PLL_BASE			0x0
+#define PLL_BASE_BYPASS			(1<<31)
+#define PLL_BASE_ENABLE			(1<<30)
+#define PLL_BASE_REF_ENABLE		(1<<29)
+#define PLL_BASE_OVERRIDE		(1<<28)
+#define PLL_BASE_DIVP_MASK		(0x7<<20)
+#define PLL_BASE_DIVP_SHIFT		20
+#define PLL_BASE_DIVN_MASK		(0x3FF<<8)
+#define PLL_BASE_DIVN_SHIFT		8
+#define PLL_BASE_DIVM_MASK		(0x1F)
+#define PLL_BASE_DIVM_SHIFT		0
+
+#define PLL_OUT_RATIO_MASK		(0xFF<<8)
+#define PLL_OUT_RATIO_SHIFT		8
+#define PLL_OUT_OVERRIDE		(1<<2)
+#define PLL_OUT_CLKEN			(1<<1)
+#define PLL_OUT_RESET_DISABLE		(1<<0)
+
+#define PLL_MISC(c) (((c)->flags & PLL_ALT_MISC_REG) ? 0x4 : 0xc)
+
+#define PLL_MISC_DCCON_SHIFT		20
+#define PLL_MISC_CPCON_SHIFT		8
+#define PLL_MISC_CPCON_MASK		(0xF<<PLL_MISC_CPCON_SHIFT)
+#define PLL_MISC_LFCON_SHIFT		4
+#define PLL_MISC_LFCON_MASK		(0xF<<PLL_MISC_LFCON_SHIFT)
+#define PLL_MISC_VCOCON_SHIFT		0
+#define PLL_MISC_VCOCON_MASK		(0xF<<PLL_MISC_VCOCON_SHIFT)
+
+#define PLLU_BASE_POST_DIV		(1<<20)
+
+#define PLLD_MISC_CLKENABLE		(1<<30)
+#define PLLD_MISC_DIV_RST		(1<<23)
+#define PLLD_MISC_DCCON_SHIFT		12
+
+#define PLLE_MISC_READY			(1 << 15)
+
+#define PERIPH_CLK_TO_ENB_REG(c)	((c->u.periph.clk_num / 32) * 4)
+#define PERIPH_CLK_TO_ENB_SET_REG(c)	((c->u.periph.clk_num / 32) * 8)
+#define PERIPH_CLK_TO_ENB_BIT(c)	(1 << (c->u.periph.clk_num % 32))
+
+#define SUPER_CLK_MUX			0x00
+#define SUPER_STATE_SHIFT		28
+#define SUPER_STATE_MASK		(0xF << SUPER_STATE_SHIFT)
+#define SUPER_STATE_STANDBY		(0x0 << SUPER_STATE_SHIFT)
+#define SUPER_STATE_IDLE		(0x1 << SUPER_STATE_SHIFT)
+#define SUPER_STATE_RUN			(0x2 << SUPER_STATE_SHIFT)
+#define SUPER_STATE_IRQ			(0x3 << SUPER_STATE_SHIFT)
+#define SUPER_STATE_FIQ			(0x4 << SUPER_STATE_SHIFT)
+#define SUPER_SOURCE_MASK		0xF
+#define	SUPER_FIQ_SOURCE_SHIFT		12
+#define	SUPER_IRQ_SOURCE_SHIFT		8
+#define	SUPER_RUN_SOURCE_SHIFT		4
+#define	SUPER_IDLE_SOURCE_SHIFT		0
+
+#define SUPER_CLK_DIVIDER		0x04
+
+#define BUS_CLK_DISABLE			(1<<3)
+#define BUS_CLK_DIV_MASK		0x3
+
+#define PMC_CTRL			0x0
+ #define PMC_CTRL_BLINK_ENB		(1 << 7)
+
+#define PMC_DPD_PADS_ORIDE		0x1c
+ #define PMC_DPD_PADS_ORIDE_BLINK_ENB	(1 << 20)
+
+#define PMC_BLINK_TIMER_DATA_ON_SHIFT	0
+#define PMC_BLINK_TIMER_DATA_ON_MASK	0x7fff
+#define PMC_BLINK_TIMER_ENB		(1 << 15)
+#define PMC_BLINK_TIMER_DATA_OFF_SHIFT	16
+#define PMC_BLINK_TIMER_DATA_OFF_MASK	0xffff
+
+/* Tegra CPU clock and reset control regs */
+#define TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX		0x4c
+#define TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET	0x340
+#define TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR	0x344
+
+#define CPU_CLOCK(cpu)	(0x1 << (8 + cpu))
+#define CPU_RESET(cpu)	(0x1111ul << (cpu))
+
+static void __iomem *reg_clk_base = IO_ADDRESS(TEGRA_CLK_RESET_BASE);
+static void __iomem *reg_pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
+
+/*
+ * Some clocks share a register with other clocks.  Any clock op that
+ * non-atomically modifies a register used by another clock must lock
+ * clock_register_lock first.
+ */
+static DEFINE_SPINLOCK(clock_register_lock);
+
+/*
+ * Some peripheral clocks share an enable bit, so refcount the enable bits
+ * in registers CLK_ENABLE_L, CLK_ENABLE_H, and CLK_ENABLE_U
+ */
+static int tegra_periph_clk_enable_refcount[3 * 32];
+
+#define clk_writel(value, reg) \
+	__raw_writel(value, reg_clk_base + (reg))
+#define clk_readl(reg) \
+	__raw_readl(reg_clk_base + (reg))
+#define pmc_writel(value, reg) \
+	__raw_writel(value, reg_pmc_base + (reg))
+#define pmc_readl(reg) \
+	__raw_readl(reg_pmc_base + (reg))
+
+static unsigned long clk_measure_input_freq(void)
+{
+	u32 clock_autodetect;
+	clk_writel(OSC_FREQ_DET_TRIG | 1, OSC_FREQ_DET);
+	do {} while (clk_readl(OSC_FREQ_DET_STATUS) & OSC_FREQ_DET_BUSY);
+	clock_autodetect = clk_readl(OSC_FREQ_DET_STATUS);
+	if (clock_autodetect >= 732 - 3 && clock_autodetect <= 732 + 3) {
+		return 12000000;
+	} else if (clock_autodetect >= 794 - 3 && clock_autodetect <= 794 + 3) {
+		return 13000000;
+	} else if (clock_autodetect >= 1172 - 3 && clock_autodetect <= 1172 + 3) {
+		return 19200000;
+	} else if (clock_autodetect >= 1587 - 3 && clock_autodetect <= 1587 + 3) {
+		return 26000000;
+	} else {
+		pr_err("%s: Unexpected clock autodetect value %d",
+						__func__, clock_autodetect);
+		BUG();
+		return 0;
+	}
+}
+
+static int clk_div71_get_divider(unsigned long parent_rate, unsigned long rate)
+{
+	s64 divider_u71 = parent_rate * 2;
+	divider_u71 += rate - 1;
+	do_div(divider_u71, rate);
+
+	if (divider_u71 - 2 < 0)
+		return 0;
+
+	if (divider_u71 - 2 > 255)
+		return -EINVAL;
+
+	return divider_u71 - 2;
+}
+
+static int clk_div16_get_divider(unsigned long parent_rate, unsigned long rate)
+{
+	s64 divider_u16;
+
+	divider_u16 = parent_rate;
+	divider_u16 += rate - 1;
+	do_div(divider_u16, rate);
+
+	if (divider_u16 - 1 < 0)
+		return 0;
+
+	if (divider_u16 - 1 > 0xFFFF)
+		return -EINVAL;
+
+	return divider_u16 - 1;
+}
+
+static unsigned long tegra_clk_fixed_recalc_rate(struct clk_hw *hw,
+		unsigned long parent_rate)
+{
+	return to_clk_tegra(hw)->fixed_rate;
+}
+
+struct clk_ops tegra_clk_32k_ops = {
+	.recalc_rate = tegra_clk_fixed_recalc_rate,
+};
+
+/* clk_m functions */
+static unsigned long tegra20_clk_m_recalc_rate(struct clk_hw *hw,
+			unsigned long prate)
+{
+	if (!to_clk_tegra(hw)->fixed_rate)
+		to_clk_tegra(hw)->fixed_rate = clk_measure_input_freq();
+	return to_clk_tegra(hw)->fixed_rate;
+}
+
+static void tegra20_clk_m_init(struct clk_hw *hw)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+	u32 osc_ctrl = clk_readl(OSC_CTRL);
+	u32 auto_clock_control = osc_ctrl & ~OSC_CTRL_OSC_FREQ_MASK;
+
+	switch (c->fixed_rate) {
+	case 12000000:
+		auto_clock_control |= OSC_CTRL_OSC_FREQ_12MHZ;
+		break;
+	case 13000000:
+		auto_clock_control |= OSC_CTRL_OSC_FREQ_13MHZ;
+		break;
+	case 19200000:
+		auto_clock_control |= OSC_CTRL_OSC_FREQ_19_2MHZ;
+		break;
+	case 26000000:
+		auto_clock_control |= OSC_CTRL_OSC_FREQ_26MHZ;
+		break;
+	default:
+		BUG();
+	}
+	clk_writel(auto_clock_control, OSC_CTRL);
+}
+
+struct clk_ops tegra_clk_m_ops = {
+	.init = tegra20_clk_m_init,
+	.recalc_rate = tegra20_clk_m_recalc_rate,
+};
+
+/* super clock functions */
+/* "super clocks" on tegra have two-stage muxes and a clock skipping
+ * super divider.  We will ignore the clock skipping divider, since we
+ * can't lower the voltage when using the clock skip, but we can if we
+ * lower the PLL frequency.
+ */
+static int tegra20_super_clk_is_enabled(struct clk_hw *hw)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+	u32 val;
+
+	val = clk_readl(c->reg + SUPER_CLK_MUX);
+	BUG_ON(((val & SUPER_STATE_MASK) != SUPER_STATE_RUN) &&
+		((val & SUPER_STATE_MASK) != SUPER_STATE_IDLE));
+	c->state = ON;
+	return c->state;
+}
+
+static int tegra20_super_clk_enable(struct clk_hw *hw)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+	clk_writel(0, c->reg + SUPER_CLK_DIVIDER);
+	return 0;
+}
+
+static void tegra20_super_clk_disable(struct clk_hw *hw)
+{
+	pr_debug("%s on clock %s\n", __func__, __clk_get_name(hw->clk));
+
+	/* oops - don't disable the CPU clock! */
+	BUG();
+}
+
+static u8 tegra20_super_clk_get_parent(struct clk_hw *hw)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+	int val = clk_readl(c->reg + SUPER_CLK_MUX);
+	int source;
+	int shift;
+
+	BUG_ON(((val & SUPER_STATE_MASK) != SUPER_STATE_RUN) &&
+		((val & SUPER_STATE_MASK) != SUPER_STATE_IDLE));
+	shift = ((val & SUPER_STATE_MASK) == SUPER_STATE_IDLE) ?
+		SUPER_IDLE_SOURCE_SHIFT : SUPER_RUN_SOURCE_SHIFT;
+	source = (val >> shift) & SUPER_SOURCE_MASK;
+	return source;
+}
+
+static int tegra20_super_clk_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+	u32 val = clk_readl(c->reg + SUPER_CLK_MUX);
+	int shift;
+
+	BUG_ON(((val & SUPER_STATE_MASK) != SUPER_STATE_RUN) &&
+		((val & SUPER_STATE_MASK) != SUPER_STATE_IDLE));
+	shift = ((val & SUPER_STATE_MASK) == SUPER_STATE_IDLE) ?
+		SUPER_IDLE_SOURCE_SHIFT : SUPER_RUN_SOURCE_SHIFT;
+	val &= ~(SUPER_SOURCE_MASK << shift);
+	val |= index << shift;
+
+	clk_writel(val, c->reg);
+
+	return 0;
+}
+
+/* FIX ME: Need to switch parents to change the source PLL rate */
+static unsigned long tegra20_super_clk_recalc_rate(struct clk_hw *hw,
+			unsigned long prate)
+{
+	return prate;
+}
+
+static long tegra20_super_clk_round_rate(struct clk_hw *hw, unsigned long rate,
+				unsigned long *prate)
+{
+	return *prate;
+}
+
+static int tegra20_super_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long parent_rate)
+{
+	return 0;
+}
+
+struct clk_ops tegra_super_ops = {
+	.is_enabled = tegra20_super_clk_is_enabled,
+	.enable = tegra20_super_clk_enable,
+	.disable = tegra20_super_clk_disable,
+	.set_parent = tegra20_super_clk_set_parent,
+	.get_parent = tegra20_super_clk_get_parent,
+	.set_rate = tegra20_super_clk_set_rate,
+	.round_rate = tegra20_super_clk_round_rate,
+	.recalc_rate = tegra20_super_clk_recalc_rate,
+};
+
+static unsigned long tegra20_twd_clk_recalc_rate(struct clk_hw *hw,
+		unsigned long parent_rate)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+	u64 rate = parent_rate;
+
+	if (c->mul != 0 && c->div != 0) {
+		rate *= c->mul;
+		rate += c->div - 1; /* round up */
+		do_div(rate, c->div);
+	}
+
+	return rate;
+}
+
+struct clk_ops tegra_twd_ops = {
+	.recalc_rate = tegra20_twd_clk_recalc_rate,
+};
+
+static u8 tegra20_cop_clk_get_parent(struct clk_hw *hw)
+{
+	return 0;
+}
+
+struct clk_ops tegra_cop_ops = {
+	.get_parent = tegra20_cop_clk_get_parent,
+};
+
+/* virtual cop clock functions. Used to acquire the fake 'cop' clock to
+ * reset the COP block (i.e. AVP) */
+void tegra2_cop_clk_reset(struct clk_hw *hw, bool assert)
+{
+	unsigned long reg = assert ? RST_DEVICES_SET : RST_DEVICES_CLR;
+
+	pr_debug("%s %s\n", __func__, assert ? "assert" : "deassert");
+	clk_writel(1 << 1, reg);
+}
+
+/* bus clock functions */
+static int tegra20_bus_clk_is_enabled(struct clk_hw *hw)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+	u32 val = clk_readl(c->reg);
+
+	c->state = ((val >> c->reg_shift) & BUS_CLK_DISABLE) ? OFF : ON;
+	return c->state;
+}
+
+static int tegra20_bus_clk_enable(struct clk_hw *hw)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+	unsigned long flags;
+	u32 val;
+
+	spin_lock_irqsave(&clock_register_lock, flags);
+
+	val = clk_readl(c->reg);
+	val &= ~(BUS_CLK_DISABLE << c->reg_shift);
+	clk_writel(val, c->reg);
+
+	spin_unlock_irqrestore(&clock_register_lock, flags);
+
+	return 0;
+}
+
+static void tegra20_bus_clk_disable(struct clk_hw *hw)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+	unsigned long flags;
+	u32 val;
+
+	spin_lock_irqsave(&clock_register_lock, flags);
+
+	val = clk_readl(c->reg);
+	val |= BUS_CLK_DISABLE << c->reg_shift;
+	clk_writel(val, c->reg);
+
+	spin_unlock_irqrestore(&clock_register_lock, flags);
+}
+
+static unsigned long tegra20_bus_clk_recalc_rate(struct clk_hw *hw,
+			unsigned long prate)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+	u32 val = clk_readl(c->reg);
+	u64 rate = prate;
+
+	c->div = ((val >> c->reg_shift) & BUS_CLK_DIV_MASK) + 1;
+	c->mul = 1;
+
+	if (c->mul != 0 && c->div != 0) {
+		rate *= c->mul;
+		rate += c->div - 1; /* round up */
+		do_div(rate, c->div);
+	}
+	return rate;
+}
+
+static int tegra20_bus_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long parent_rate)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+	int ret = -EINVAL;
+	unsigned long flags;
+	u32 val;
+	int i;
+
+	spin_lock_irqsave(&clock_register_lock, flags);
+
+	val = clk_readl(c->reg);
+	for (i = 1; i <= 4; i++) {
+		if (rate == parent_rate / i) {
+			val &= ~(BUS_CLK_DIV_MASK << c->reg_shift);
+			val |= (i - 1) << c->reg_shift;
+			clk_writel(val, c->reg);
+			c->div = i;
+			c->mul = 1;
+			ret = 0;
+			break;
+		}
+	}
+
+	spin_unlock_irqrestore(&clock_register_lock, flags);
+
+	return ret;
+}
+
+static long tegra20_bus_clk_round_rate(struct clk_hw *hw, unsigned long rate,
+				unsigned long *prate)
+{
+	unsigned long parent_rate = *prate;
+	s64 divider;
+
+	if (rate >= parent_rate)
+		return rate;
+
+	divider = parent_rate;
+	divider += rate - 1;
+	do_div(divider, rate);
+
+	if (divider < 0)
+		return divider;
+
+	if (divider > 4)
+		divider = 4;
+	do_div(parent_rate, divider);
+
+	return parent_rate;
+}
+
+struct clk_ops tegra_bus_ops = {
+	.is_enabled = tegra20_bus_clk_is_enabled,
+	.enable = tegra20_bus_clk_enable,
+	.disable = tegra20_bus_clk_disable,
+	.set_rate = tegra20_bus_clk_set_rate,
+	.round_rate = tegra20_bus_clk_round_rate,
+	.recalc_rate = tegra20_bus_clk_recalc_rate,
+};
+
+/* Blink output functions */
+static int tegra20_blink_clk_is_enabled(struct clk_hw *hw)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+	u32 val;
+
+	val = pmc_readl(PMC_CTRL);
+	c->state = (val & PMC_CTRL_BLINK_ENB) ? ON : OFF;
+	return c->state;
+}
+
+static unsigned long tegra20_blink_clk_recalc_rate(struct clk_hw *hw,
+			unsigned long prate)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+	u64 rate = prate;
+	u32 val;
+
+	c->mul = 1;
+	val = pmc_readl(c->reg);
+
+	if (val & PMC_BLINK_TIMER_ENB) {
+		unsigned int on_off;
+
+		on_off = (val >> PMC_BLINK_TIMER_DATA_ON_SHIFT) &
+			PMC_BLINK_TIMER_DATA_ON_MASK;
+		val >>= PMC_BLINK_TIMER_DATA_OFF_SHIFT;
+		val &= PMC_BLINK_TIMER_DATA_OFF_MASK;
+		on_off += val;
+		/* each tick in the blink timer is 4 32KHz clocks */
+		c->div = on_off * 4;
+	} else {
+		c->div = 1;
+	}
+
+	if (c->mul != 0 && c->div != 0) {
+		rate *= c->mul;
+		rate += c->div - 1; /* round up */
+		do_div(rate, c->div);
+	}
+	return rate;
+}
+
+static int tegra20_blink_clk_enable(struct clk_hw *hw)
+{
+	u32 val;
+
+	val = pmc_readl(PMC_DPD_PADS_ORIDE);
+	pmc_writel(val | PMC_DPD_PADS_ORIDE_BLINK_ENB, PMC_DPD_PADS_ORIDE);
+
+	val = pmc_readl(PMC_CTRL);
+	pmc_writel(val | PMC_CTRL_BLINK_ENB, PMC_CTRL);
+
+	return 0;
+}
+
+static void tegra20_blink_clk_disable(struct clk_hw *hw)
+{
+	u32 val;
+
+	val = pmc_readl(PMC_CTRL);
+	pmc_writel(val & ~PMC_CTRL_BLINK_ENB, PMC_CTRL);
+
+	val = pmc_readl(PMC_DPD_PADS_ORIDE);
+	pmc_writel(val & ~PMC_DPD_PADS_ORIDE_BLINK_ENB, PMC_DPD_PADS_ORIDE);
+}
+
+static int tegra20_blink_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long parent_rate)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+
+	if (rate >= parent_rate) {
+		c->div = 1;
+		pmc_writel(0, c->reg);
+	} else {
+		unsigned int on_off;
+		u32 val;
+
+		on_off = DIV_ROUND_UP(parent_rate / 8, rate);
+		c->div = on_off * 8;
+
+		val = (on_off & PMC_BLINK_TIMER_DATA_ON_MASK) <<
+			PMC_BLINK_TIMER_DATA_ON_SHIFT;
+		on_off &= PMC_BLINK_TIMER_DATA_OFF_MASK;
+		on_off <<= PMC_BLINK_TIMER_DATA_OFF_SHIFT;
+		val |= on_off;
+		val |= PMC_BLINK_TIMER_ENB;
+		pmc_writel(val, c->reg);
+	}
+
+	return 0;
+}
+
+static long tegra20_blink_clk_round_rate(struct clk_hw *hw, unsigned long rate,
+				unsigned long *prate)
+{
+	int div;
+	int mul;
+	long round_rate = *prate;
+
+	mul = 1;
+
+	if (rate >= *prate) {
+		div = 1;
+	} else {
+		div = DIV_ROUND_UP(*prate / 8, rate);
+		div *= 8;
+	}
+
+	round_rate *= mul;
+	round_rate += div - 1;
+	do_div(round_rate, div);
+
+	return round_rate;
+}
+
+struct clk_ops tegra_blink_clk_ops = {
+	.is_enabled = tegra20_blink_clk_is_enabled,
+	.enable = tegra20_blink_clk_enable,
+	.disable = tegra20_blink_clk_disable,
+	.set_rate = tegra20_blink_clk_set_rate,
+	.round_rate = tegra20_blink_clk_round_rate,
+	.recalc_rate = tegra20_blink_clk_recalc_rate,
+};
+
+/* PLL Functions */
+static int tegra20_pll_clk_wait_for_lock(struct clk_tegra *c)
+{
+	udelay(c->u.pll.lock_delay);
+	return 0;
+}
+
+static int tegra20_pll_clk_is_enabled(struct clk_hw *hw)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+	u32 val = clk_readl(c->reg + PLL_BASE);
+
+	c->state = (val & PLL_BASE_ENABLE) ? ON : OFF;
+	return c->state;
+}
+
+static unsigned long tegra20_pll_clk_recalc_rate(struct clk_hw *hw,
+				unsigned long prate)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+	u32 val = clk_readl(c->reg + PLL_BASE);
+	u64 rate = prate;
+
+	if (c->flags & PLL_FIXED && !(val & PLL_BASE_OVERRIDE)) {
+		const struct clk_pll_freq_table *sel;
+		for (sel = c->u.pll.freq_table; sel->input_rate != 0; sel++) {
+			if (sel->input_rate == prate &&
+				sel->output_rate == c->u.pll.fixed_rate) {
+				c->mul = sel->n;
+				c->div = sel->m * sel->p;
+				break;
+			}
+		}
+		pr_err("Clock %s has unknown fixed frequency\n",
+			__clk_get_name(hw->clk));
+		BUG();
+	} else if (val & PLL_BASE_BYPASS) {
+		c->mul = 1;
+		c->div = 1;
+	} else {
+		c->mul = (val & PLL_BASE_DIVN_MASK) >> PLL_BASE_DIVN_SHIFT;
+		c->div = (val & PLL_BASE_DIVM_MASK) >> PLL_BASE_DIVM_SHIFT;
+		if (c->flags & PLLU)
+			c->div *= (val & PLLU_BASE_POST_DIV) ? 1 : 2;
+		else
+			c->div *= (val & PLL_BASE_DIVP_MASK) ? 2 : 1;
+	}
+
+	if (c->mul != 0 && c->div != 0) {
+		rate *= c->mul;
+		rate += c->div - 1; /* round up */
+		do_div(rate, c->div);
+	}
+	return rate;
+}
+
+static int tegra20_pll_clk_enable(struct clk_hw *hw)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+	u32 val;
+	pr_debug("%s on clock %s\n", __func__, __clk_get_name(hw->clk));
+
+	val = clk_readl(c->reg + PLL_BASE);
+	val &= ~PLL_BASE_BYPASS;
+	val |= PLL_BASE_ENABLE;
+	clk_writel(val, c->reg + PLL_BASE);
+
+	tegra20_pll_clk_wait_for_lock(c);
+
+	return 0;
+}
+
+static void tegra20_pll_clk_disable(struct clk_hw *hw)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+	u32 val;
+	pr_debug("%s on clock %s\n", __func__, __clk_get_name(hw->clk));
+
+	val = clk_readl(c->reg);
+	val &= ~(PLL_BASE_BYPASS | PLL_BASE_ENABLE);
+	clk_writel(val, c->reg);
+}
+
+static int tegra20_pll_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long parent_rate)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+	unsigned long input_rate = parent_rate;
+	const struct clk_pll_freq_table *sel;
+	u32 val;
+
+	pr_debug("%s: %s %lu\n", __func__, __clk_get_name(hw->clk), rate);
+
+	if (c->flags & PLL_FIXED) {
+		int ret = 0;
+		if (rate != c->u.pll.fixed_rate) {
+			pr_err("%s: Can not change %s fixed rate %lu to %lu\n",
+				__func__, __clk_get_name(hw->clk),
+				c->u.pll.fixed_rate, rate);
+			ret = -EINVAL;
+		}
+		return ret;
+	}
+
+	for (sel = c->u.pll.freq_table; sel->input_rate != 0; sel++) {
+		if (sel->input_rate == input_rate && sel->output_rate == rate) {
+			c->mul = sel->n;
+			c->div = sel->m * sel->p;
+
+			val = clk_readl(c->reg + PLL_BASE);
+			if (c->flags & PLL_FIXED)
+				val |= PLL_BASE_OVERRIDE;
+			val &= ~(PLL_BASE_DIVP_MASK | PLL_BASE_DIVN_MASK |
+				 PLL_BASE_DIVM_MASK);
+			val |= (sel->m << PLL_BASE_DIVM_SHIFT) |
+				(sel->n << PLL_BASE_DIVN_SHIFT);
+			BUG_ON(sel->p < 1 || sel->p > 2);
+			if (c->flags & PLLU) {
+				if (sel->p == 1)
+					val |= PLLU_BASE_POST_DIV;
+			} else {
+				if (sel->p == 2)
+					val |= 1 << PLL_BASE_DIVP_SHIFT;
+			}
+			clk_writel(val, c->reg + PLL_BASE);
+
+			if (c->flags & PLL_HAS_CPCON) {
+				val = clk_readl(c->reg + PLL_MISC(c));
+				val &= ~PLL_MISC_CPCON_MASK;
+				val |= sel->cpcon << PLL_MISC_CPCON_SHIFT;
+				clk_writel(val, c->reg + PLL_MISC(c));
+			}
+
+			if (c->state == ON)
+				tegra20_pll_clk_enable(hw);
+			return 0;
+		}
+	}
+	return -EINVAL;
+}
+
+static long tegra20_pll_clk_round_rate(struct clk_hw *hw, unsigned long rate,
+				unsigned long *prate)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+	const struct clk_pll_freq_table *sel;
+	unsigned long input_rate = *prate;
+	u64 output_rate = *prate;
+	int mul;
+	int div;
+
+	if (c->flags & PLL_FIXED)
+		return c->u.pll.fixed_rate;
+
+	for (sel = c->u.pll.freq_table; sel->input_rate != 0; sel++)
+		if (sel->input_rate == input_rate && sel->output_rate == rate) {
+			mul = sel->n;
+			div = sel->m * sel->p;
+			break;
+		}
+
+	if (sel->input_rate == 0)
+		return -EINVAL;
+
+	output_rate *= mul;
+	output_rate += div - 1; /* round up */
+	do_div(output_rate, div);
+
+	return output_rate;
+}
+
+struct clk_ops tegra_pll_ops = {
+	.is_enabled = tegra20_pll_clk_is_enabled,
+	.enable = tegra20_pll_clk_enable,
+	.disable = tegra20_pll_clk_disable,
+	.set_rate = tegra20_pll_clk_set_rate,
+	.recalc_rate = tegra20_pll_clk_recalc_rate,
+	.round_rate = tegra20_pll_clk_round_rate,
+};
+
+static void tegra20_pllx_clk_init(struct clk_hw *hw)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+
+	if (tegra_sku_id == 7)
+		c->max_rate = 750000000;
+}
+
+struct clk_ops tegra_pllx_ops = {
+	.init = tegra20_pllx_clk_init,
+	.is_enabled = tegra20_pll_clk_is_enabled,
+	.enable = tegra20_pll_clk_enable,
+	.disable = tegra20_pll_clk_disable,
+	.set_rate = tegra20_pll_clk_set_rate,
+	.recalc_rate = tegra20_pll_clk_recalc_rate,
+	.round_rate = tegra20_pll_clk_round_rate,
+};
+
+static int tegra20_plle_clk_enable(struct clk_hw *hw)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+	u32 val;
+
+	pr_debug("%s on clock %s\n", __func__, __clk_get_name(hw->clk));
+
+	mdelay(1);
+
+	val = clk_readl(c->reg + PLL_BASE);
+	if (!(val & PLLE_MISC_READY))
+		return -EBUSY;
+
+	val = clk_readl(c->reg + PLL_BASE);
+	val |= PLL_BASE_ENABLE | PLL_BASE_BYPASS;
+	clk_writel(val, c->reg + PLL_BASE);
+
+	return 0;
+}
+
+struct clk_ops tegra_plle_ops = {
+	.is_enabled = tegra20_pll_clk_is_enabled,
+	.enable = tegra20_plle_clk_enable,
+	.set_rate = tegra20_pll_clk_set_rate,
+	.recalc_rate = tegra20_pll_clk_recalc_rate,
+	.round_rate = tegra20_pll_clk_round_rate,
+};
+
+/* Clock divider ops */
+static int tegra20_pll_div_clk_is_enabled(struct clk_hw *hw)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+	u32 val = clk_readl(c->reg);
+
+	val >>= c->reg_shift;
+	c->state = (val & PLL_OUT_CLKEN) ? ON : OFF;
+	if (!(val & PLL_OUT_RESET_DISABLE))
+		c->state = OFF;
+	return c->state;
+}
+
+static unsigned long tegra20_pll_div_clk_recalc_rate(struct clk_hw *hw,
+			unsigned long prate)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+	u64 rate = prate;
+	u32 val = clk_readl(c->reg);
+	u32 divu71;
+
+	val >>= c->reg_shift;
+
+	if (c->flags & DIV_U71) {
+		divu71 = (val & PLL_OUT_RATIO_MASK) >> PLL_OUT_RATIO_SHIFT;
+		c->div = (divu71 + 2);
+		c->mul = 2;
+	} else if (c->flags & DIV_2) {
+		c->div = 2;
+		c->mul = 1;
+	} else {
+		c->div = 1;
+		c->mul = 1;
+	}
+
+	rate *= c->mul;
+	rate += c->div - 1; /* round up */
+	do_div(rate, c->div);
+
+	return rate;
+}
+
+static int tegra20_pll_div_clk_enable(struct clk_hw *hw)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+	unsigned long flags;
+	u32 new_val;
+	u32 val;
+
+	pr_debug("%s: %s\n", __func__, __clk_get_name(hw->clk));
+
+	if (c->flags & DIV_U71) {
+		spin_lock_irqsave(&clock_register_lock, flags);
+		val = clk_readl(c->reg);
+		new_val = val >> c->reg_shift;
+		new_val &= 0xFFFF;
+
+		new_val |= PLL_OUT_CLKEN | PLL_OUT_RESET_DISABLE;
+
+		val &= ~(0xFFFF << c->reg_shift);
+		val |= new_val << c->reg_shift;
+		clk_writel(val, c->reg);
+		spin_unlock_irqrestore(&clock_register_lock, flags);
+		return 0;
+	} else if (c->flags & DIV_2) {
+		BUG_ON(!(c->flags & PLLD));
+		spin_lock_irqsave(&clock_register_lock, flags);
+		val = clk_readl(c->reg);
+		val &= ~PLLD_MISC_DIV_RST;
+		clk_writel(val, c->reg);
+		spin_unlock_irqrestore(&clock_register_lock, flags);
+		return 0;
+	}
+	return -EINVAL;
+}
+
+static void tegra20_pll_div_clk_disable(struct clk_hw *hw)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+	unsigned long flags;
+	u32 new_val;
+	u32 val;
+
+	pr_debug("%s: %s\n", __func__, __clk_get_name(hw->clk));
+
+	if (c->flags & DIV_U71) {
+		spin_lock_irqsave(&clock_register_lock, flags);
+		val = clk_readl(c->reg);
+		new_val = val >> c->reg_shift;
+		new_val &= 0xFFFF;
+
+		new_val &= ~(PLL_OUT_CLKEN | PLL_OUT_RESET_DISABLE);
+
+		val &= ~(0xFFFF << c->reg_shift);
+		val |= new_val << c->reg_shift;
+		clk_writel(val, c->reg);
+		spin_unlock_irqrestore(&clock_register_lock, flags);
+	} else if (c->flags & DIV_2) {
+		BUG_ON(!(c->flags & PLLD));
+		spin_lock_irqsave(&clock_register_lock, flags);
+		val = clk_readl(c->reg);
+		val |= PLLD_MISC_DIV_RST;
+		clk_writel(val, c->reg);
+		spin_unlock_irqrestore(&clock_register_lock, flags);
+	}
+}
+
+static int tegra20_pll_div_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long parent_rate)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+	unsigned long flags;
+	int divider_u71;
+	u32 new_val;
+	u32 val;
+
+	pr_debug("%s: %s %lu\n", __func__, __clk_get_name(hw->clk), rate);
+
+	if (c->flags & DIV_U71) {
+		divider_u71 = clk_div71_get_divider(parent_rate, rate);
+		if (divider_u71 >= 0) {
+			spin_lock_irqsave(&clock_register_lock, flags);
+			val = clk_readl(c->reg);
+			new_val = val >> c->reg_shift;
+			new_val &= 0xFFFF;
+			if (c->flags & DIV_U71_FIXED)
+				new_val |= PLL_OUT_OVERRIDE;
+			new_val &= ~PLL_OUT_RATIO_MASK;
+			new_val |= divider_u71 << PLL_OUT_RATIO_SHIFT;
+
+			val &= ~(0xFFFF << c->reg_shift);
+			val |= new_val << c->reg_shift;
+			clk_writel(val, c->reg);
+			c->div = divider_u71 + 2;
+			c->mul = 2;
+			spin_unlock_irqrestore(&clock_register_lock, flags);
+			return 0;
+		}
+	} else if (c->flags & DIV_2) {
+		if (parent_rate == rate * 2)
+			return 0;
+	}
+	return -EINVAL;
+}
+
+static long tegra20_pll_div_clk_round_rate(struct clk_hw *hw, unsigned long rate,
+				unsigned long *prate)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+	unsigned long parent_rate = *prate;
+	int divider;
+
+	pr_debug("%s: %s %lu\n", __func__, __clk_get_name(hw->clk), rate);
+
+	if (c->flags & DIV_U71) {
+		divider = clk_div71_get_divider(parent_rate, rate);
+		if (divider < 0)
+			return divider;
+		return DIV_ROUND_UP(parent_rate * 2, divider + 2);
+	} else if (c->flags & DIV_2) {
+		return DIV_ROUND_UP(parent_rate, 2);
+	}
+	return -EINVAL;
+}
+
+struct clk_ops tegra_pll_div_ops = {
+	.is_enabled = tegra20_pll_div_clk_is_enabled,
+	.enable = tegra20_pll_div_clk_enable,
+	.disable = tegra20_pll_div_clk_disable,
+	.set_rate = tegra20_pll_div_clk_set_rate,
+	.round_rate = tegra20_pll_div_clk_round_rate,
+	.recalc_rate = tegra20_pll_div_clk_recalc_rate,
+};
+
+/* Periph clk ops */
+
+static int tegra20_periph_clk_is_enabled(struct clk_hw *hw)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+
+	c->state = ON;
+
+	if (!c->u.periph.clk_num)
+		goto out;
+
+	if (!(clk_readl(CLK_OUT_ENB + PERIPH_CLK_TO_ENB_REG(c)) &
+			PERIPH_CLK_TO_ENB_BIT(c)))
+		c->state = OFF;
+
+	if (!(c->flags & PERIPH_NO_RESET))
+		if (clk_readl(RST_DEVICES + PERIPH_CLK_TO_ENB_REG(c)) &
+				PERIPH_CLK_TO_ENB_BIT(c))
+			c->state = OFF;
+
+out:
+	return c->state;
+}
+
+static int tegra20_periph_clk_enable(struct clk_hw *hw)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+	unsigned long flags;
+	u32 val;
+
+	pr_debug("%s on clock %s\n", __func__, __clk_get_name(hw->clk));
+
+	if (!c->u.periph.clk_num)
+		return 0;
+
+	tegra_periph_clk_enable_refcount[c->u.periph.clk_num]++;
+	if (tegra_periph_clk_enable_refcount[c->u.periph.clk_num] > 1)
+		return 0;
+
+	spin_lock_irqsave(&clock_register_lock, flags);
+
+	clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
+		CLK_OUT_ENB_SET + PERIPH_CLK_TO_ENB_SET_REG(c));
+	if (!(c->flags & PERIPH_NO_RESET) && !(c->flags & PERIPH_MANUAL_RESET))
+		clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
+			RST_DEVICES_CLR + PERIPH_CLK_TO_ENB_SET_REG(c));
+	if (c->flags & PERIPH_EMC_ENB) {
+		/* The EMC peripheral clock has 2 extra enable bits */
+		/* FIXME: Do they need to be disabled? */
+		val = clk_readl(c->reg);
+		val |= 0x3 << 24;
+		clk_writel(val, c->reg);
+	}
+
+	spin_unlock_irqrestore(&clock_register_lock, flags);
+
+	return 0;
+}
+
+static void tegra20_periph_clk_disable(struct clk_hw *hw)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+	unsigned long flags;
+
+	pr_debug("%s on clock %s\n", __func__, __clk_get_name(hw->clk));
+
+	if (!c->u.periph.clk_num)
+		return;
+
+	tegra_periph_clk_enable_refcount[c->u.periph.clk_num]--;
+
+	if (tegra_periph_clk_enable_refcount[c->u.periph.clk_num] > 0)
+		return;
+
+	spin_lock_irqsave(&clock_register_lock, flags);
+
+	clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
+		CLK_OUT_ENB_CLR + PERIPH_CLK_TO_ENB_SET_REG(c));
+
+	spin_unlock_irqrestore(&clock_register_lock, flags);
+}
+
+void tegra2_periph_clk_reset(struct clk_hw *hw, bool assert)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+	unsigned long base = assert ? RST_DEVICES_SET : RST_DEVICES_CLR;
+
+	pr_debug("%s %s on clock %s\n", __func__,
+		assert ? "assert" : "deassert", __clk_get_name(hw->clk));
+
+	BUG_ON(!c->u.periph.clk_num);
+
+	if (!(c->flags & PERIPH_NO_RESET))
+		clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
+			   base + PERIPH_CLK_TO_ENB_SET_REG(c));
+}
+
+static int tegra20_periph_clk_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+	u32 val;
+	u32 mask;
+	u32 shift;
+
+	pr_debug("%s: %s %d\n", __func__, __clk_get_name(hw->clk), index);
+
+	if (c->flags & MUX_PWM) {
+		shift = PERIPH_CLK_SOURCE_PWM_SHIFT;
+		mask = PERIPH_CLK_SOURCE_PWM_MASK;
+	} else {
+		shift = PERIPH_CLK_SOURCE_SHIFT;
+		mask = PERIPH_CLK_SOURCE_MASK;
+	}
+
+	val = clk_readl(c->reg);
+	val &= ~mask;
+	val |= (index) << shift;
+
+	clk_writel(val, c->reg);
+
+	return 0;
+}
+
+static u8 tegra20_periph_clk_get_parent(struct clk_hw *hw)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+	u32 val = clk_readl(c->reg);
+	u32 mask;
+	u32 shift;
+
+	if (c->flags & MUX_PWM) {
+		shift = PERIPH_CLK_SOURCE_PWM_SHIFT;
+		mask = PERIPH_CLK_SOURCE_PWM_MASK;
+	} else {
+		shift = PERIPH_CLK_SOURCE_SHIFT;
+		mask = PERIPH_CLK_SOURCE_MASK;
+	}
+
+	if (c->flags & MUX)
+		return (val & mask) >> shift;
+	else
+		return 0;
+}
+
+static unsigned long tegra20_periph_clk_recalc_rate(struct clk_hw *hw,
+			unsigned long prate)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+	unsigned long rate = prate;
+	u32 val = clk_readl(c->reg);
+
+	if (c->flags & DIV_U71) {
+		u32 divu71 = val & PERIPH_CLK_SOURCE_DIVU71_MASK;
+		c->div = divu71 + 2;
+		c->mul = 2;
+	} else if (c->flags & DIV_U16) {
+		u32 divu16 = val & PERIPH_CLK_SOURCE_DIVU16_MASK;
+		c->div = divu16 + 1;
+		c->mul = 1;
+	} else {
+		c->div = 1;
+		c->mul = 1;
+		return rate;
+	}
+
+	if (c->mul != 0 && c->div != 0) {
+		rate *= c->mul;
+		rate += c->div - 1; /* round up */
+		do_div(rate, c->div);
+	}
+
+	return rate;
+}
+
+static int tegra20_periph_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long parent_rate)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+	u32 val;
+	int divider;
+
+	val = clk_readl(c->reg);
+
+	if (c->flags & DIV_U71) {
+		divider = clk_div71_get_divider(parent_rate, rate);
+
+		if (divider >= 0) {
+			val = clk_readl(c->reg);
+			val &= ~PERIPH_CLK_SOURCE_DIVU71_MASK;
+			val |= divider;
+			clk_writel(val, c->reg);
+			c->div = divider + 2;
+			c->mul = 2;
+			return 0;
+		}
+	} else if (c->flags & DIV_U16) {
+		divider = clk_div16_get_divider(parent_rate, rate);
+		if (divider >= 0) {
+			val = clk_readl(c->reg);
+			val &= ~PERIPH_CLK_SOURCE_DIVU16_MASK;
+			val |= divider;
+			clk_writel(val, c->reg);
+			c->div = divider + 1;
+			c->mul = 1;
+			return 0;
+		}
+	} else if (parent_rate <= rate) {
+		c->div = 1;
+		c->mul = 1;
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+static long tegra20_periph_clk_round_rate(struct clk_hw *hw,
+	unsigned long rate, unsigned long *prate)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+	unsigned long parent_rate = __clk_get_rate(__clk_get_parent(hw->clk));
+	int divider;
+
+	pr_debug("%s: %s %lu\n", __func__, __clk_get_name(hw->clk), rate);
+
+	if (prate)
+		parent_rate = *prate;
+
+	if (c->flags & DIV_U71) {
+		divider = clk_div71_get_divider(parent_rate, rate);
+		if (divider < 0)
+			return divider;
+
+		return DIV_ROUND_UP(parent_rate * 2, divider + 2);
+	} else if (c->flags & DIV_U16) {
+		divider = clk_div16_get_divider(parent_rate, rate);
+		if (divider < 0)
+			return divider;
+		return DIV_ROUND_UP(parent_rate, divider + 1);
+	}
+	return -EINVAL;
+}
+
+struct clk_ops tegra_periph_clk_ops = {
+	.is_enabled = tegra20_periph_clk_is_enabled,
+	.enable = tegra20_periph_clk_enable,
+	.disable = tegra20_periph_clk_disable,
+	.set_parent = tegra20_periph_clk_set_parent,
+	.get_parent = tegra20_periph_clk_get_parent,
+	.set_rate = tegra20_periph_clk_set_rate,
+	.round_rate = tegra20_periph_clk_round_rate,
+	.recalc_rate = tegra20_periph_clk_recalc_rate,
+};
+
+/* External memory controller clock ops */
+static void tegra20_emc_clk_init(struct clk_hw *hw)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+	c->max_rate = __clk_get_rate(hw->clk);
+}
+
+static long tegra20_emc_clk_round_rate(struct clk_hw *hw, unsigned long rate,
+				unsigned long *prate)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+	long emc_rate;
+	long clk_rate;
+
+	/*
+	 * The slowest entry in the EMC clock table that is at least as
+	 * fast as rate.
+	 */
+	emc_rate = tegra_emc_round_rate(rate);
+	if (emc_rate < 0)
+		return c->max_rate;
+
+	/*
+	 * The fastest rate the PLL will generate that is at most the
+	 * requested rate.
+	 */
+	clk_rate = tegra20_periph_clk_round_rate(hw, emc_rate, NULL);
+
+	/*
+	 * If this fails, and emc_rate > clk_rate, it's because the maximum
+	 * rate in the EMC tables is larger than the maximum rate of the EMC
+	 * clock. The EMC clock's max rate is the rate it was running when the
+	 * kernel booted. Such a mismatch is probably due to using the wrong
+	 * BCT, i.e. using a Tegra20 BCT with an EMC table written for Tegra25.
+	 */
+	WARN_ONCE(emc_rate != clk_rate,
+		"emc_rate %ld != clk_rate %ld",
+		emc_rate, clk_rate);
+
+	return emc_rate;
+}
+
+static int tegra20_emc_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long parent_rate)
+{
+	int ret;
+
+	/*
+	 * The Tegra2 memory controller has an interlock with the clock
+	 * block that allows memory shadowed registers to be updated,
+	 * and then transfer them to the main registers at the same
+	 * time as the clock update without glitches.
+	 */
+	ret = tegra_emc_set_rate(rate);
+	if (ret < 0)
+		return ret;
+
+	ret = tegra20_periph_clk_set_rate(hw, rate, parent_rate);
+	udelay(1);
+
+	return ret;
+}
+
+struct clk_ops tegra_emc_clk_ops = {
+	.init = tegra20_emc_clk_init,
+	.is_enabled = tegra20_periph_clk_is_enabled,
+	.enable = tegra20_periph_clk_enable,
+	.disable = tegra20_periph_clk_disable,
+	.set_parent = tegra20_periph_clk_set_parent,
+	.get_parent = tegra20_periph_clk_get_parent,
+	.set_rate = tegra20_emc_clk_set_rate,
+	.round_rate = tegra20_emc_clk_round_rate,
+	.recalc_rate = tegra20_periph_clk_recalc_rate,
+};
+
+/* Clock doubler ops */
+static int tegra20_clk_double_is_enabled(struct clk_hw *hw)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+
+	c->state = ON;
+
+	if (!c->u.periph.clk_num)
+		goto out;
+
+	if (!(clk_readl(CLK_OUT_ENB + PERIPH_CLK_TO_ENB_REG(c)) &
+			PERIPH_CLK_TO_ENB_BIT(c)))
+		c->state = OFF;
+
+out:
+	return c->state;
+};
+
+static unsigned long tegra20_clk_double_recalc_rate(struct clk_hw *hw,
+			unsigned long prate)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+	u64 rate = prate;
+
+	c->mul = 2;
+	c->div = 1;
+
+	rate *= c->mul;
+	rate += c->div - 1; /* round up */
+	do_div(rate, c->div);
+
+	return rate;
+}
+
+static long tegra20_clk_double_round_rate(struct clk_hw *hw, unsigned long rate,
+				unsigned long *prate)
+{
+	unsigned long output_rate = *prate;
+
+	do_div(output_rate, 2);
+	return output_rate;
+}
+
+static int tegra20_clk_double_set_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long parent_rate)
+{
+	if (rate != 2 * parent_rate)
+		return -EINVAL;
+	return 0;
+}
+
+struct clk_ops tegra_clk_double_ops = {
+	.is_enabled = tegra20_clk_double_is_enabled,
+	.enable = tegra20_periph_clk_enable,
+	.disable = tegra20_periph_clk_disable,
+	.set_rate = tegra20_clk_double_set_rate,
+	.recalc_rate = tegra20_clk_double_recalc_rate,
+	.round_rate = tegra20_clk_double_round_rate,
+};
+
+/* Audio sync clock ops */
+static int tegra20_audio_sync_clk_is_enabled(struct clk_hw *hw)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+	u32 val = clk_readl(c->reg);
+
+	c->state = (val & (1<<4)) ? OFF : ON;
+	return c->state;
+}
+
+static int tegra20_audio_sync_clk_enable(struct clk_hw *hw)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+
+	clk_writel(0, c->reg);
+	return 0;
+}
+
+static void tegra20_audio_sync_clk_disable(struct clk_hw *hw)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+	clk_writel(1, c->reg);
+}
+
+static u8 tegra20_audio_sync_clk_get_parent(struct clk_hw *hw)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+	u32 val = clk_readl(c->reg);
+	int source;
+
+	source = val & 0xf;
+	return source;
+}
+
+static int tegra20_audio_sync_clk_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+	u32 val;
+
+	val = clk_readl(c->reg);
+	val &= ~0xf;
+	val |= index;
+
+	clk_writel(val, c->reg);
+
+	return 0;
+}
+
+struct clk_ops tegra_audio_sync_clk_ops = {
+	.is_enabled = tegra20_audio_sync_clk_is_enabled,
+	.enable = tegra20_audio_sync_clk_enable,
+	.disable = tegra20_audio_sync_clk_disable,
+	.set_parent = tegra20_audio_sync_clk_set_parent,
+	.get_parent = tegra20_audio_sync_clk_get_parent,
+};
+
+/* cdev1 and cdev2 (dap_mclk1 and dap_mclk2) ops */
+
+static int tegra20_cdev_clk_is_enabled(struct clk_hw *hw)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+	/* We could un-tristate the cdev1 or cdev2 pingroup here; this is
+	 * currently done in the pinmux code. */
+	c->state = ON;
+
+	BUG_ON(!c->u.periph.clk_num);
+
+	if (!(clk_readl(CLK_OUT_ENB + PERIPH_CLK_TO_ENB_REG(c)) &
+			PERIPH_CLK_TO_ENB_BIT(c)))
+		c->state = OFF;
+	return c->state;
+}
+
+static int tegra20_cdev_clk_enable(struct clk_hw *hw)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+	BUG_ON(!c->u.periph.clk_num);
+
+	clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
+		CLK_OUT_ENB_SET + PERIPH_CLK_TO_ENB_SET_REG(c));
+	return 0;
+}
+
+static void tegra20_cdev_clk_disable(struct clk_hw *hw)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+	BUG_ON(!c->u.periph.clk_num);
+
+	clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
+		CLK_OUT_ENB_CLR + PERIPH_CLK_TO_ENB_SET_REG(c));
+}
+
+static unsigned long tegra20_cdev_recalc_rate(struct clk_hw *hw,
+			unsigned long prate)
+{
+	return to_clk_tegra(hw)->fixed_rate;
+}
+
+struct clk_ops tegra_cdev_clk_ops = {
+	.is_enabled = tegra20_cdev_clk_is_enabled,
+	.enable = tegra20_cdev_clk_enable,
+	.disable = tegra20_cdev_clk_disable,
+	.recalc_rate = tegra20_cdev_recalc_rate,
+};
+
+/* Tegra20 CPU clock and reset control functions */
+static void tegra20_wait_cpu_in_reset(u32 cpu)
+{
+	unsigned int reg;
+
+	do {
+		reg = readl(reg_clk_base +
+			    TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET);
+		cpu_relax();
+	} while (!(reg & (1 << cpu)));	/* check CPU been reset or not */
+
+	return;
+}
+
+static void tegra20_put_cpu_in_reset(u32 cpu)
+{
+	writel(CPU_RESET(cpu),
+	       reg_clk_base + TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET);
+	dmb();
+}
+
+static void tegra20_cpu_out_of_reset(u32 cpu)
+{
+	writel(CPU_RESET(cpu),
+	       reg_clk_base + TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR);
+	wmb();
+}
+
+static void tegra20_enable_cpu_clock(u32 cpu)
+{
+	unsigned int reg;
+
+	reg = readl(reg_clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
+	writel(reg & ~CPU_CLOCK(cpu),
+	       reg_clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
+	barrier();
+	reg = readl(reg_clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
+}
+
+static void tegra20_disable_cpu_clock(u32 cpu)
+{
+	unsigned int reg;
+
+	reg = readl(reg_clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
+	writel(reg | CPU_CLOCK(cpu),
+	       reg_clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
+}
+
+static struct tegra_cpu_car_ops tegra20_cpu_car_ops = {
+	.wait_for_reset	= tegra20_wait_cpu_in_reset,
+	.put_in_reset	= tegra20_put_cpu_in_reset,
+	.out_of_reset	= tegra20_cpu_out_of_reset,
+	.enable_clock	= tegra20_enable_cpu_clock,
+	.disable_clock	= tegra20_disable_cpu_clock,
+};
+
+void __init tegra20_cpu_car_ops_init(void)
+{
+	tegra_cpu_car_ops = &tegra20_cpu_car_ops;
+}
diff --git a/arch/arm/mach-tegra/tegra20_clocks.h b/arch/arm/mach-tegra/tegra20_clocks.h
new file mode 100644
index 0000000..8bfd31b
--- /dev/null
+++ b/arch/arm/mach-tegra/tegra20_clocks.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __MACH_TEGRA20_CLOCK_H
+#define __MACH_TEGRA20_CLOCK_H
+
+extern struct clk_ops tegra_clk_32k_ops;
+extern struct clk_ops tegra_pll_ops;
+extern struct clk_ops tegra_clk_m_ops;
+extern struct clk_ops tegra_pll_div_ops;
+extern struct clk_ops tegra_pllx_ops;
+extern struct clk_ops tegra_plle_ops;
+extern struct clk_ops tegra_clk_double_ops;
+extern struct clk_ops tegra_cdev_clk_ops;
+extern struct clk_ops tegra_audio_sync_clk_ops;
+extern struct clk_ops tegra_super_ops;
+extern struct clk_ops tegra_cpu_ops;
+extern struct clk_ops tegra_twd_ops;
+extern struct clk_ops tegra_cop_ops;
+extern struct clk_ops tegra_bus_ops;
+extern struct clk_ops tegra_blink_clk_ops;
+extern struct clk_ops tegra_emc_clk_ops;
+extern struct clk_ops tegra_periph_clk_ops;
+extern struct clk_ops tegra_clk_shared_bus_ops;
+
+void tegra2_periph_clk_reset(struct clk_hw *hw, bool assert);
+void tegra2_cop_clk_reset(struct clk_hw *hw, bool assert);
+
+#endif
diff --git a/arch/arm/mach-tegra/tegra20_clocks_data.c b/arch/arm/mach-tegra/tegra20_clocks_data.c
new file mode 100644
index 0000000..cc9b5fd
--- /dev/null
+++ b/arch/arm/mach-tegra/tegra20_clocks_data.c
@@ -0,0 +1,1139 @@
+/*
+ * arch/arm/mach-tegra/tegra2_clocks.c
+ *
+ * Copyright (C) 2010 Google, Inc.
+ * Copyright (c) 2012 NVIDIA CORPORATION.  All rights reserved.
+ *
+ * Author:
+ *	Colin Cross <ccross@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/clk-private.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+
+#include <mach/iomap.h>
+
+#include "clock.h"
+#include "fuse.h"
+#include "tegra2_emc.h"
+#include "tegra20_clocks.h"
+#include "tegra_cpu_car.h"
+
+/* Clock definitions */
+
+#define DEFINE_CLK_TEGRA(_name, _rate, _ops, _flags,		\
+		   _parent_names, _parents, _parent)		\
+	static struct clk tegra_##_name = {			\
+		.hw = &tegra_##_name##_hw.hw,			\
+		.name = #_name,					\
+		.rate = _rate,					\
+		.ops = _ops,					\
+		.flags = _flags,				\
+		.parent_names = _parent_names,			\
+		.parents = _parents,				\
+		.num_parents = ARRAY_SIZE(_parent_names),	\
+		.parent = _parent,				\
+	};
+
+static struct clk tegra_clk_32k;
+static struct clk_tegra tegra_clk_32k_hw = {
+	.hw = {
+		.clk = &tegra_clk_32k,
+	},
+	.fixed_rate = 32768,
+};
+
+static struct clk tegra_clk_32k = {
+	.name = "clk_32k",
+	.rate = 32768,
+	.ops = &tegra_clk_32k_ops,
+	.hw = &tegra_clk_32k_hw.hw,
+	.flags = CLK_IS_ROOT,
+};
+
+static struct clk tegra_clk_m;
+static struct clk_tegra tegra_clk_m_hw = {
+	.hw = {
+		.clk = &tegra_clk_m,
+	},
+	.flags = ENABLE_ON_INIT,
+	.reg = 0x1fc,
+	.reg_shift = 28,
+	.max_rate = 26000000,
+	.fixed_rate = 0,
+};
+
+static struct clk tegra_clk_m = {
+	.name = "clk_m",
+	.ops = &tegra_clk_m_ops,
+	.hw = &tegra_clk_m_hw.hw,
+	.flags = CLK_IS_ROOT,
+};
+
+#define DEFINE_PLL(_name, _flags, _reg, _max_rate, _input_min,	\
+		   _input_max, _cf_min, _cf_max, _vco_min,	\
+		   _vco_max, _freq_table, _lock_delay, _ops,	\
+		   _fixed_rate, _parent)			\
+	static const char *tegra_##_name##_parent_names[] = {	\
+		#_parent,					\
+	};							\
+	static struct clk *tegra_##_name##_parents[] = {	\
+		&tegra_##_parent,				\
+	};							\
+	static struct clk tegra_##_name;			\
+	static struct clk_tegra tegra_##_name##_hw = {		\
+		.hw = {						\
+			.clk = &tegra_##_name,			\
+		},						\
+		.flags = _flags,				\
+		.reg = _reg,					\
+		.max_rate = _max_rate,				\
+		.u.pll = {					\
+			.input_min = _input_min,		\
+			.input_max = _input_max,		\
+			.cf_min = _cf_min,			\
+			.cf_max = _cf_max,			\
+			.vco_min = _vco_min,			\
+			.vco_max = _vco_max,			\
+			.freq_table = _freq_table,		\
+			.lock_delay = _lock_delay,		\
+			.fixed_rate = _fixed_rate,		\
+		},						\
+	};							\
+	static struct clk tegra_##_name = {			\
+		.name = #_name,					\
+		.ops = &_ops,					\
+		.hw = &tegra_##_name##_hw.hw,			\
+		.parent = &tegra_##_parent,			\
+		.parent_names = tegra_##_name##_parent_names,	\
+		.parents = tegra_##_name##_parents,		\
+		.num_parents = 1,				\
+	};
+
+#define DEFINE_PLL_OUT(_name, _flags, _reg, _reg_shift,		\
+		_max_rate, _ops, _parent, _clk_flags)		\
+	static const char *tegra_##_name##_parent_names[] = {	\
+		#_parent,					\
+	};							\
+	static struct clk *tegra_##_name##_parents[] = {	\
+		&tegra_##_parent,				\
+	};							\
+	static struct clk tegra_##_name;			\
+	static struct clk_tegra tegra_##_name##_hw = {		\
+		.hw = {						\
+			.clk = &tegra_##_name,			\
+		},						\
+		.flags = _flags,				\
+		.reg = _reg,					\
+		.max_rate = _max_rate,				\
+		.reg_shift = _reg_shift,			\
+	};							\
+	static struct clk tegra_##_name = {			\
+		.name = #_name,					\
+		.ops = &tegra_pll_div_ops,			\
+		.hw = &tegra_##_name##_hw.hw,			\
+		.parent = &tegra_##_parent,			\
+		.parent_names = tegra_##_name##_parent_names,	\
+		.parents = tegra_##_name##_parents,		\
+		.num_parents = 1,				\
+		.flags = _clk_flags,				\
+	};
+
+
+static struct clk_pll_freq_table tegra_pll_s_freq_table[] = {
+	{32768, 12000000, 366, 1, 1, 0},
+	{32768, 13000000, 397, 1, 1, 0},
+	{32768, 19200000, 586, 1, 1, 0},
+	{32768, 26000000, 793, 1, 1, 0},
+	{0, 0, 0, 0, 0, 0},
+};
+
+DEFINE_PLL(pll_s, PLL_ALT_MISC_REG, 0xf0, 26000000, 32768, 32768, 0,
+		0, 12000000, 26000000, tegra_pll_s_freq_table, 300,
+		tegra_pll_ops, 0, clk_32k);
+
+static struct clk_pll_freq_table tegra_pll_c_freq_table[] = {
+	{ 12000000, 600000000, 600, 12, 1, 8 },
+	{ 13000000, 600000000, 600, 13, 1, 8 },
+	{ 19200000, 600000000, 500, 16, 1, 6 },
+	{ 26000000, 600000000, 600, 26, 1, 8 },
+	{ 0, 0, 0, 0, 0, 0 },
+};
+
+DEFINE_PLL(pll_c, PLL_HAS_CPCON, 0x80, 600000000, 2000000, 31000000, 1000000,
+		6000000, 20000000, 1400000000, tegra_pll_c_freq_table, 300,
+		tegra_pll_ops, 0, clk_m);
+
+DEFINE_PLL_OUT(pll_c_out1, DIV_U71, 0x84, 0, 600000000,
+		tegra_pll_div_ops, pll_c, 0);
+
+static struct clk_pll_freq_table tegra_pll_m_freq_table[] = {
+	{ 12000000, 666000000, 666, 12, 1, 8},
+	{ 13000000, 666000000, 666, 13, 1, 8},
+	{ 19200000, 666000000, 555, 16, 1, 8},
+	{ 26000000, 666000000, 666, 26, 1, 8},
+	{ 12000000, 600000000, 600, 12, 1, 8},
+	{ 13000000, 600000000, 600, 13, 1, 8},
+	{ 19200000, 600000000, 375, 12, 1, 6},
+	{ 26000000, 600000000, 600, 26, 1, 8},
+	{ 0, 0, 0, 0, 0, 0 },
+};
+
+DEFINE_PLL(pll_m, PLL_HAS_CPCON, 0x90, 800000000, 2000000, 31000000, 1000000,
+		6000000, 20000000, 1200000000, tegra_pll_m_freq_table, 300,
+		tegra_pll_ops, 0, clk_m);
+
+DEFINE_PLL_OUT(pll_m_out1, DIV_U71, 0x94, 0, 600000000,
+		tegra_pll_div_ops, pll_m, 0);
+
+static struct clk_pll_freq_table tegra_pll_p_freq_table[] = {
+	{ 12000000, 216000000, 432, 12, 2, 8},
+	{ 13000000, 216000000, 432, 13, 2, 8},
+	{ 19200000, 216000000, 90,   4, 2, 1},
+	{ 26000000, 216000000, 432, 26, 2, 8},
+	{ 12000000, 432000000, 432, 12, 1, 8},
+	{ 13000000, 432000000, 432, 13, 1, 8},
+	{ 19200000, 432000000, 90,   4, 1, 1},
+	{ 26000000, 432000000, 432, 26, 1, 8},
+	{ 0, 0, 0, 0, 0, 0 },
+};
+
+
+DEFINE_PLL(pll_p, ENABLE_ON_INIT | PLL_FIXED | PLL_HAS_CPCON, 0xa0, 432000000,
+		2000000, 31000000, 1000000, 6000000, 20000000, 1400000000,
+		tegra_pll_p_freq_table, 300, tegra_pll_ops, 216000000, clk_m);
+
+DEFINE_PLL_OUT(pll_p_out1, ENABLE_ON_INIT | DIV_U71 | DIV_U71_FIXED, 0xa4, 0,
+		432000000, tegra_pll_div_ops, pll_p, 0);
+DEFINE_PLL_OUT(pll_p_out2, ENABLE_ON_INIT | DIV_U71 | DIV_U71_FIXED, 0xa4, 16,
+		432000000, tegra_pll_div_ops, pll_p, 0);
+DEFINE_PLL_OUT(pll_p_out3, ENABLE_ON_INIT | DIV_U71 | DIV_U71_FIXED, 0xa8, 0,
+		432000000, tegra_pll_div_ops, pll_p, 0);
+DEFINE_PLL_OUT(pll_p_out4, ENABLE_ON_INIT | DIV_U71 | DIV_U71_FIXED, 0xa8, 16,
+		432000000, tegra_pll_div_ops, pll_p, 0);
+
+static struct clk_pll_freq_table tegra_pll_a_freq_table[] = {
+	{ 28800000, 56448000, 49, 25, 1, 1},
+	{ 28800000, 73728000, 64, 25, 1, 1},
+	{ 28800000, 24000000,  5,  6, 1, 1},
+	{ 0, 0, 0, 0, 0, 0 },
+};
+
+DEFINE_PLL(pll_a, PLL_HAS_CPCON, 0xb0, 73728000, 2000000, 31000000, 1000000,
+		6000000, 20000000, 1400000000, tegra_pll_a_freq_table, 300,
+		tegra_pll_ops, 0, pll_p_out1);
+
+DEFINE_PLL_OUT(pll_a_out0, DIV_U71, 0xb4, 0, 73728000,
+		tegra_pll_div_ops, pll_a, 0);
+
+static struct clk_pll_freq_table tegra_pll_d_freq_table[] = {
+	{ 12000000, 216000000, 216, 12, 1, 4},
+	{ 13000000, 216000000, 216, 13, 1, 4},
+	{ 19200000, 216000000, 135, 12, 1, 3},
+	{ 26000000, 216000000, 216, 26, 1, 4},
+
+	{ 12000000, 594000000, 594, 12, 1, 8},
+	{ 13000000, 594000000, 594, 13, 1, 8},
+	{ 19200000, 594000000, 495, 16, 1, 8},
+	{ 26000000, 594000000, 594, 26, 1, 8},
+
+	{ 12000000, 1000000000, 1000, 12, 1, 12},
+	{ 13000000, 1000000000, 1000, 13, 1, 12},
+	{ 19200000, 1000000000, 625,  12, 1, 8},
+	{ 26000000, 1000000000, 1000, 26, 1, 12},
+
+	{ 0, 0, 0, 0, 0, 0 },
+};
+
+DEFINE_PLL(pll_d, PLL_HAS_CPCON | PLLD, 0xd0, 1000000000, 2000000, 40000000,
+		1000000, 6000000, 40000000, 1000000000, tegra_pll_d_freq_table,
+		1000, tegra_pll_ops, 0, clk_m);
+
+DEFINE_PLL_OUT(pll_d_out0, DIV_2 | PLLD, 0, 0, 500000000,
+		tegra_pll_div_ops, pll_d, CLK_SET_RATE_PARENT);
+
+static struct clk_pll_freq_table tegra_pll_u_freq_table[] = {
+	{ 12000000, 480000000, 960, 12, 2, 0},
+	{ 13000000, 480000000, 960, 13, 2, 0},
+	{ 19200000, 480000000, 200, 4,  2, 0},
+	{ 26000000, 480000000, 960, 26, 2, 0},
+	{ 0, 0, 0, 0, 0, 0 },
+};
+
+DEFINE_PLL(pll_u, PLLU, 0xc0, 480000000, 2000000, 40000000, 1000000, 6000000,
+		48000000, 960000000, tegra_pll_u_freq_table, 1000,
+		tegra_pll_ops, 0, clk_m);
+
+static struct clk_pll_freq_table tegra_pll_x_freq_table[] = {
+	/* 1 GHz */
+	{ 12000000, 1000000000, 1000, 12, 1, 12},
+	{ 13000000, 1000000000, 1000, 13, 1, 12},
+	{ 19200000, 1000000000, 625,  12, 1, 8},
+	{ 26000000, 1000000000, 1000, 26, 1, 12},
+
+	/* 912 MHz */
+	{ 12000000, 912000000,  912,  12, 1, 12},
+	{ 13000000, 912000000,  912,  13, 1, 12},
+	{ 19200000, 912000000,  760,  16, 1, 8},
+	{ 26000000, 912000000,  912,  26, 1, 12},
+
+	/* 816 MHz */
+	{ 12000000, 816000000,  816,  12, 1, 12},
+	{ 13000000, 816000000,  816,  13, 1, 12},
+	{ 19200000, 816000000,  680,  16, 1, 8},
+	{ 26000000, 816000000,  816,  26, 1, 12},
+
+	/* 760 MHz */
+	{ 12000000, 760000000,  760,  12, 1, 12},
+	{ 13000000, 760000000,  760,  13, 1, 12},
+	{ 19200000, 760000000,  950,  24, 1, 8},
+	{ 26000000, 760000000,  760,  26, 1, 12},
+
+	/* 750 MHz */
+	{ 12000000, 750000000,  750,  12, 1, 12},
+	{ 13000000, 750000000,  750,  13, 1, 12},
+	{ 19200000, 750000000,  625,  16, 1, 8},
+	{ 26000000, 750000000,  750,  26, 1, 12},
+
+	/* 608 MHz */
+	{ 12000000, 608000000,  608,  12, 1, 12},
+	{ 13000000, 608000000,  608,  13, 1, 12},
+	{ 19200000, 608000000,  380,  12, 1, 8},
+	{ 26000000, 608000000,  608,  26, 1, 12},
+
+	/* 456 MHz */
+	{ 12000000, 456000000,  456,  12, 1, 12},
+	{ 13000000, 456000000,  456,  13, 1, 12},
+	{ 19200000, 456000000,  380,  16, 1, 8},
+	{ 26000000, 456000000,  456,  26, 1, 12},
+
+	/* 312 MHz */
+	{ 12000000, 312000000,  312,  12, 1, 12},
+	{ 13000000, 312000000,  312,  13, 1, 12},
+	{ 19200000, 312000000,  260,  16, 1, 8},
+	{ 26000000, 312000000,  312,  26, 1, 12},
+
+	{ 0, 0, 0, 0, 0, 0 },
+};
+
+DEFINE_PLL(pll_x, PLL_HAS_CPCON | PLL_ALT_MISC_REG, 0xe0, 1000000000, 2000000,
+		31000000, 1000000, 6000000, 20000000, 1200000000,
+		tegra_pll_x_freq_table, 300, tegra_pllx_ops, 0, clk_m);
+
+static struct clk_pll_freq_table tegra_pll_e_freq_table[] = {
+	{ 12000000, 100000000,  200,  24, 1, 0 },
+	{ 0, 0, 0, 0, 0, 0 },
+};
+
+DEFINE_PLL(pll_e, PLL_ALT_MISC_REG, 0xe8, 100000000, 12000000, 12000000, 0, 0,
+		0, 0, tegra_pll_e_freq_table, 0, tegra_plle_ops, 0, clk_m);
+
+static const char *tegra_common_parent_names[] = {
+	"clk_m",
+};
+
+static struct clk *tegra_common_parents[] = {
+	&tegra_clk_m,
+};
+
+static struct clk tegra_clk_d;
+static struct clk_tegra tegra_clk_d_hw = {
+	.hw = {
+		.clk = &tegra_clk_d,
+	},
+	.flags = PERIPH_NO_RESET,
+	.reg = 0x34,
+	.reg_shift = 12,
+	.max_rate = 52000000,
+	.u.periph = {
+		.clk_num = 90,
+	},
+};
+
+static struct clk tegra_clk_d = {
+	.name = "clk_d",
+	.hw = &tegra_clk_d_hw.hw,
+	.ops = &tegra_clk_double_ops,
+	.parent = &tegra_clk_m,
+	.parent_names = tegra_common_parent_names,
+	.parents = tegra_common_parents,
+	.num_parents = ARRAY_SIZE(tegra_common_parent_names),
+};
+
+static struct clk tegra_cdev1;
+static struct clk_tegra tegra_cdev1_hw = {
+	.hw = {
+		.clk = &tegra_cdev1,
+	},
+	.fixed_rate = 26000000,
+	.u.periph = {
+		.clk_num = 94,
+	},
+};
+static struct clk tegra_cdev1 = {
+	.name = "cdev1",
+	.hw = &tegra_cdev1_hw.hw,
+	.ops = &tegra_cdev_clk_ops,
+	.flags = CLK_IS_ROOT,
+};
+
+/* dap_mclk2, belongs to the cdev2 pingroup. */
+static struct clk tegra_cdev2;
+static struct clk_tegra tegra_cdev2_hw = {
+	.hw = {
+		.clk = &tegra_cdev2,
+	},
+	.fixed_rate = 26000000,
+	.u.periph = {
+		.clk_num  = 93,
+	},
+};
+static struct clk tegra_cdev2 = {
+	.name = "cdev2",
+	.hw = &tegra_cdev2_hw.hw,
+	.ops = &tegra_cdev_clk_ops,
+	.flags = CLK_IS_ROOT,
+};
+
+/* initialized before peripheral clocks */
+static struct clk_mux_sel mux_audio_sync_clk[8+1];
+static const struct audio_sources {
+	const char *name;
+	int value;
+} mux_audio_sync_clk_sources[] = {
+	{ .name = "spdif_in", .value = 0 },
+	{ .name = "i2s1", .value = 1 },
+	{ .name = "i2s2", .value = 2 },
+	{ .name = "pll_a_out0", .value = 4 },
+#if 0 /* FIXME: not implemented */
+	{ .name = "ac97", .value = 3 },
+	{ .name = "ext_audio_clk2", .value = 5 },
+	{ .name = "ext_audio_clk1", .value = 6 },
+	{ .name = "ext_vimclk", .value = 7 },
+#endif
+	{ NULL, 0 }
+};
+
+static const char *audio_parent_names[] = {
+	"spdif_in",
+	"i2s1",
+	"i2s2",
+	"dummy",
+	"pll_a_out0",
+	"dummy",
+	"dummy",
+	"dummy",
+};
+
+static struct clk *audio_parents[] = {
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+};
+
+static struct clk tegra_audio;
+static struct clk_tegra tegra_audio_hw = {
+	.hw = {
+		.clk = &tegra_audio,
+	},
+	.reg = 0x38,
+	.max_rate = 73728000,
+};
+DEFINE_CLK_TEGRA(audio, 0, &tegra_audio_sync_clk_ops, 0, audio_parent_names,
+		audio_parents, NULL);
+
+static const char *audio_2x_parent_names[] = {
+	"audio",
+};
+
+static struct clk *audio_2x_parents[] = {
+	&tegra_audio,
+};
+
+static struct clk tegra_audio_2x;
+static struct clk_tegra tegra_audio_2x_hw = {
+	.hw = {
+		.clk = &tegra_audio_2x,
+	},
+	.flags = PERIPH_NO_RESET,
+	.max_rate = 48000000,
+	.reg = 0x34,
+	.reg_shift = 8,
+	.u.periph = {
+		.clk_num = 89,
+	},
+};
+DEFINE_CLK_TEGRA(audio_2x, 0, &tegra_clk_double_ops, 0, audio_2x_parent_names,
+		audio_2x_parents, &tegra_audio);
+
+static struct clk_lookup tegra_audio_clk_lookups[] = {
+	{ .con_id = "audio", .clk = &tegra_audio },
+	{ .con_id = "audio_2x", .clk = &tegra_audio_2x }
+};
+
+/* This is called after peripheral clocks are initialized, as the
+ * audio_sync clock depends on some of the peripheral clocks.
+ */
+
+static void init_audio_sync_clock_mux(void)
+{
+	int i;
+	struct clk_mux_sel *sel = mux_audio_sync_clk;
+	const struct audio_sources *src = mux_audio_sync_clk_sources;
+	struct clk_lookup *lookup;
+
+	for (i = 0; src->name; i++, sel++, src++) {
+		sel->input = tegra_get_clock_by_name(src->name);
+		if (!sel->input)
+			pr_err("%s: could not find clk %s\n", __func__,
+				src->name);
+		audio_parents[src->value] = sel->input;
+		sel->value = src->value;
+	}
+
+	lookup = tegra_audio_clk_lookups;
+	for (i = 0; i < ARRAY_SIZE(tegra_audio_clk_lookups); i++, lookup++) {
+		struct clk *c = lookup->clk;
+		struct clk_tegra *clk = to_clk_tegra(c->hw);
+		__clk_init(NULL, c);
+		INIT_LIST_HEAD(&clk->shared_bus_list);
+		clk->lookup.con_id = lookup->con_id;
+		clk->lookup.clk = c;
+		clkdev_add(&clk->lookup);
+		tegra_clk_add(c);
+	}
+}
+
+static const char *mux_cclk[] = {
+	"clk_m",
+	"pll_c",
+	"clk_32k",
+	"pll_m",
+	"pll_p",
+	"pll_p_out4",
+	"pll_p_out3",
+	"clk_d",
+	"pll_x",
+};
+
+
+static struct clk *mux_cclk_p[] = {
+	&tegra_clk_m,
+	&tegra_pll_c,
+	&tegra_clk_32k,
+	&tegra_pll_m,
+	&tegra_pll_p,
+	&tegra_pll_p_out4,
+	&tegra_pll_p_out3,
+	&tegra_clk_d,
+	&tegra_pll_x,
+};
+
+static const char *mux_sclk[] = {
+	"clk_m",
+	"pll_c_out1",
+	"pll_p_out4",
+	"pllp_p_out3",
+	"pll_p_out2",
+	"clk_d",
+	"clk_32k",
+	"pll_m_out1",
+};
+
+static struct clk *mux_sclk_p[] = {
+	&tegra_clk_m,
+	&tegra_pll_c_out1,
+	&tegra_pll_p_out4,
+	&tegra_pll_p_out3,
+	&tegra_pll_p_out2,
+	&tegra_clk_d,
+	&tegra_clk_32k,
+	&tegra_pll_m_out1,
+};
+
+static struct clk tegra_cclk;
+static struct clk_tegra tegra_cclk_hw = {
+	.hw = {
+		.clk = &tegra_cclk,
+	},
+	.reg = 0x20,
+	.max_rate = 1000000000,
+};
+DEFINE_CLK_TEGRA(cclk, 0, &tegra_super_ops, 0, mux_cclk,
+		mux_cclk_p, NULL);
+
+static const char *mux_twd[] = {
+	"cclk",
+};
+
+static struct clk *mux_twd_p[] = {
+	&tegra_cclk,
+};
+
+static struct clk tegra_clk_twd;
+static struct clk_tegra tegra_clk_twd_hw = {
+	.hw = {
+		.clk = &tegra_clk_twd,
+	},
+	.max_rate = 1000000000,
+	.mul = 1,
+	.div = 4,
+};
+
+static struct clk tegra_clk_twd = {
+	.name = "twd",
+	.ops = &tegra_twd_ops,
+	.hw = &tegra_clk_twd_hw.hw,
+	.parent = &tegra_cclk,
+	.parent_names = mux_twd,
+	.parents = mux_twd_p,
+	.num_parents = ARRAY_SIZE(mux_twd),
+};
+
+static struct clk tegra_sclk;
+static struct clk_tegra tegra_sclk_hw = {
+	.hw = {
+		.clk = &tegra_sclk,
+	},
+	.reg = 0x28,
+	.max_rate = 240000000,
+	.min_rate = 120000000,
+};
+DEFINE_CLK_TEGRA(sclk, 0, &tegra_super_ops, 0, mux_sclk,
+		mux_sclk_p, NULL);
+
+static const char *tegra_cop_parent_names[] = {
+	"tegra_sclk",
+};
+
+static struct clk *tegra_cop_parents[] = {
+	&tegra_sclk,
+};
+
+static struct clk tegra_cop;
+static struct clk_tegra tegra_cop_hw = {
+	.hw = {
+		.clk = &tegra_cop,
+	},
+	.max_rate  = 240000000,
+	.reset = &tegra2_cop_clk_reset,
+};
+DEFINE_CLK_TEGRA(cop, 0, &tegra_cop_ops, CLK_SET_RATE_PARENT,
+		tegra_cop_parent_names, tegra_cop_parents, &tegra_sclk);
+
+static const char *tegra_hclk_parent_names[] = {
+	"tegra_sclk",
+};
+
+static struct clk *tegra_hclk_parents[] = {
+	&tegra_sclk,
+};
+
+static struct clk tegra_hclk;
+static struct clk_tegra tegra_hclk_hw = {
+	.hw = {
+		.clk = &tegra_hclk,
+	},
+	.flags = DIV_BUS,
+	.reg = 0x30,
+	.reg_shift = 4,
+	.max_rate = 240000000,
+};
+DEFINE_CLK_TEGRA(hclk, 0, &tegra_bus_ops, 0, tegra_hclk_parent_names,
+		tegra_hclk_parents, &tegra_sclk);
+
+static const char *tegra_pclk_parent_names[] = {
+	"tegra_hclk",
+};
+
+static struct clk *tegra_pclk_parents[] = {
+	&tegra_hclk,
+};
+
+static struct clk tegra_pclk;
+static struct clk_tegra tegra_pclk_hw = {
+	.hw = {
+		.clk = &tegra_pclk,
+	},
+	.flags = DIV_BUS,
+	.reg = 0x30,
+	.reg_shift = 0,
+	.max_rate = 120000000,
+};
+DEFINE_CLK_TEGRA(pclk, 0, &tegra_bus_ops, 0, tegra_pclk_parent_names,
+		tegra_pclk_parents, &tegra_hclk);
+
+static const char *tegra_blink_parent_names[] = {
+	"clk_32k",
+};
+
+static struct clk *tegra_blink_parents[] = {
+	&tegra_clk_32k,
+};
+
+static struct clk tegra_blink;
+static struct clk_tegra tegra_blink_hw = {
+	.hw = {
+		.clk = &tegra_blink,
+	},
+	.reg = 0x40,
+	.max_rate = 32768,
+};
+DEFINE_CLK_TEGRA(blink, 0, &tegra_blink_clk_ops, 0, tegra_blink_parent_names,
+		tegra_blink_parents, &tegra_clk_32k);
+
+static const char *mux_pllm_pllc_pllp_plla[] = {
+	"pll_m",
+	"pll_c",
+	"pll_p",
+	"pll_a_out0",
+};
+
+static struct clk *mux_pllm_pllc_pllp_plla_p[] = {
+	&tegra_pll_m,
+	&tegra_pll_c,
+	&tegra_pll_p,
+	&tegra_pll_a_out0,
+};
+
+static const char *mux_pllm_pllc_pllp_clkm[] = {
+	"pll_m",
+	"pll_c",
+	"pll_p",
+	"clk_m",
+};
+
+static struct clk *mux_pllm_pllc_pllp_clkm_p[] = {
+	&tegra_pll_m,
+	&tegra_pll_c,
+	&tegra_pll_p,
+	&tegra_clk_m,
+};
+
+static const char *mux_pllp_pllc_pllm_clkm[] = {
+	"pll_p",
+	"pll_c",
+	"pll_m",
+	"clk_m",
+};
+
+static struct clk *mux_pllp_pllc_pllm_clkm_p[] = {
+	&tegra_pll_p,
+	&tegra_pll_c,
+	&tegra_pll_m,
+	&tegra_clk_m,
+};
+
+static const char *mux_pllaout0_audio2x_pllp_clkm[] = {
+	"pll_a_out0",
+	"audio_2x",
+	"pll_p",
+	"clk_m",
+};
+
+static struct clk *mux_pllaout0_audio2x_pllp_clkm_p[] = {
+	&tegra_pll_a_out0,
+	&tegra_audio_2x,
+	&tegra_pll_p,
+	&tegra_clk_m,
+};
+
+static const char *mux_pllp_plld_pllc_clkm[] = {
+	"pllp",
+	"pll_d_out0",
+	"pll_c",
+	"clk_m",
+};
+
+static struct clk *mux_pllp_plld_pllc_clkm_p[] = {
+	&tegra_pll_p,
+	&tegra_pll_d_out0,
+	&tegra_pll_c,
+	&tegra_clk_m,
+};
+
+static const char *mux_pllp_pllc_audio_clkm_clk32[] = {
+	"pll_p",
+	"pll_c",
+	"audio",
+	"clk_m",
+	"clk_32k",
+};
+
+static struct clk *mux_pllp_pllc_audio_clkm_clk32_p[] = {
+	&tegra_pll_p,
+	&tegra_pll_c,
+	&tegra_audio,
+	&tegra_clk_m,
+	&tegra_clk_32k,
+};
+
+static const char *mux_pllp_pllc_pllm[] = {
+	"pll_p",
+	"pll_c",
+	"pll_m"
+};
+
+static struct clk *mux_pllp_pllc_pllm_p[] = {
+	&tegra_pll_p,
+	&tegra_pll_c,
+	&tegra_pll_m,
+};
+
+static const char *mux_clk_m[] = {
+	"clk_m",
+};
+
+static struct clk *mux_clk_m_p[] = {
+	&tegra_clk_m,
+};
+
+static const char *mux_pllp_out3[] = {
+	"pll_p_out3",
+};
+
+static struct clk *mux_pllp_out3_p[] = {
+	&tegra_pll_p_out3,
+};
+
+static const char *mux_plld[] = {
+	"pll_d",
+};
+
+static struct clk *mux_plld_p[] = {
+	&tegra_pll_d,
+};
+
+static const char *mux_clk_32k[] = {
+	"clk_32k",
+};
+
+static struct clk *mux_clk_32k_p[] = {
+	&tegra_clk_32k,
+};
+
+static const char *mux_pclk[] = {
+	"pclk",
+};
+
+static struct clk *mux_pclk_p[] = {
+	&tegra_pclk,
+};
+
+static struct clk tegra_emc;
+static struct clk_tegra tegra_emc_hw = {
+	.hw = {
+		.clk = &tegra_emc,
+	},
+	.reg = 0x19c,
+	.max_rate = 800000000,
+	.flags = MUX | DIV_U71 | PERIPH_EMC_ENB,
+	.reset = &tegra2_periph_clk_reset,
+	.u.periph = {
+		.clk_num = 57,
+	},
+};
+DEFINE_CLK_TEGRA(emc, 0, &tegra_emc_clk_ops, 0, mux_pllm_pllc_pllp_clkm,
+		mux_pllm_pllc_pllp_clkm_p, NULL);
+
+#define PERIPH_CLK(_name, _dev, _con, _clk_num, _reg,	\
+		_max, _inputs, _flags) 			\
+	static struct clk tegra_##_name;		\
+	static struct clk_tegra tegra_##_name##_hw = {	\
+		.hw = {					\
+			.clk = &tegra_##_name,		\
+		},					\
+		.lookup = {				\
+			.dev_id = _dev,			\
+			.con_id = _con,			\
+		},					\
+		.reg = _reg,				\
+		.flags = _flags,			\
+		.max_rate = _max,			\
+		.u.periph = {				\
+			.clk_num = _clk_num,		\
+		},					\
+		.reset = tegra2_periph_clk_reset,	\
+	};						\
+	static struct clk tegra_##_name = {		\
+		.name = #_name,				\
+		.ops = &tegra_periph_clk_ops,		\
+		.hw = &tegra_##_name##_hw.hw,		\
+		.parent_names = _inputs,		\
+		.parents = _inputs##_p,			\
+		.num_parents = ARRAY_SIZE(_inputs),	\
+	};
+
+PERIPH_CLK(apbdma,	"tegra-apbdma",		NULL,	34,	0,	108000000, mux_pclk,			0);
+PERIPH_CLK(rtc,		"rtc-tegra",		NULL,	4,	0,	32768,     mux_clk_32k,			PERIPH_NO_RESET);
+PERIPH_CLK(timer,	"timer",		NULL,	5,	0,	26000000,  mux_clk_m,			0);
+PERIPH_CLK(i2s1,	"tegra20-i2s.0",	NULL,	11,	0x100,	26000000,  mux_pllaout0_audio2x_pllp_clkm,	MUX | DIV_U71);
+PERIPH_CLK(i2s2,	"tegra20-i2s.1",	NULL,	18,	0x104,	26000000,  mux_pllaout0_audio2x_pllp_clkm,	MUX | DIV_U71);
+PERIPH_CLK(spdif_out,	"spdif_out",		NULL,	10,	0x108,	100000000, mux_pllaout0_audio2x_pllp_clkm,	MUX | DIV_U71);
+PERIPH_CLK(spdif_in,	"spdif_in",		NULL,	10,	0x10c,	100000000, mux_pllp_pllc_pllm,		MUX | DIV_U71);
+PERIPH_CLK(pwm,		"tegra-pwm",		NULL,	17,	0x110,	432000000, mux_pllp_pllc_audio_clkm_clk32,	MUX | DIV_U71 | MUX_PWM);
+PERIPH_CLK(spi,		"spi",			NULL,	43,	0x114,	40000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71);
+PERIPH_CLK(xio,		"xio",			NULL,	45,	0x120,	150000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71);
+PERIPH_CLK(twc,		"twc",			NULL,	16,	0x12c,	150000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71);
+PERIPH_CLK(sbc1,	"spi_tegra.0",		NULL,	41,	0x134,	160000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71);
+PERIPH_CLK(sbc2,	"spi_tegra.1",		NULL,	44,	0x118,	160000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71);
+PERIPH_CLK(sbc3,	"spi_tegra.2",		NULL,	46,	0x11c,	160000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71);
+PERIPH_CLK(sbc4,	"spi_tegra.3",		NULL,	68,	0x1b4,	160000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71);
+PERIPH_CLK(ide,		"ide",			NULL,	25,	0x144,	100000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71); /* requires min voltage */
+PERIPH_CLK(ndflash,	"tegra_nand",		NULL,	13,	0x160,	164000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71); /* scales with voltage */
+PERIPH_CLK(vfir,	"vfir",			NULL,	7,	0x168,	72000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71);
+PERIPH_CLK(sdmmc1,	"sdhci-tegra.0",	NULL,	14,	0x150,	52000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71); /* scales with voltage */
+PERIPH_CLK(sdmmc2,	"sdhci-tegra.1",	NULL,	9,	0x154,	52000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71); /* scales with voltage */
+PERIPH_CLK(sdmmc3,	"sdhci-tegra.2",	NULL,	69,	0x1bc,	52000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71); /* scales with voltage */
+PERIPH_CLK(sdmmc4,	"sdhci-tegra.3",	NULL,	15,	0x164,	52000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71); /* scales with voltage */
+PERIPH_CLK(vcp,		"tegra-avp",		"vcp",	29,	0,	250000000, mux_clk_m,			0);
+PERIPH_CLK(bsea,	"tegra-avp",		"bsea",	62,	0,	250000000, mux_clk_m,			0);
+PERIPH_CLK(bsev,	"tegra-aes",		"bsev",	63,	0,	250000000, mux_clk_m,			0);
+PERIPH_CLK(vde,		"tegra-avp",		"vde",	61,	0x1c8,	250000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71); /* scales with voltage and process_id */
+PERIPH_CLK(csite,	"csite",		NULL,	73,	0x1d4,	144000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71); /* max rate ??? */
+/* FIXME: what is la? */
+PERIPH_CLK(la,		"la",			NULL,	76,	0x1f8,	26000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71);
+PERIPH_CLK(owr,		"tegra_w1",		NULL,	71,	0x1cc,	26000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71);
+PERIPH_CLK(nor,		"nor",			NULL,	42,	0x1d0,	92000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71); /* requires min voltage */
+PERIPH_CLK(mipi,	"mipi",			NULL,	50,	0x174,	60000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71); /* scales with voltage */
+PERIPH_CLK(i2c1,	"tegra-i2c.0",		"div-clk", 12,	0x124,	26000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U16);
+PERIPH_CLK(i2c2,	"tegra-i2c.1",		"div-clk", 54,	0x198,	26000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U16);
+PERIPH_CLK(i2c3,	"tegra-i2c.2",		"div-clk", 67,	0x1b8,	26000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U16);
+PERIPH_CLK(dvc,		"tegra-i2c.3",		"div-clk", 47,	0x128,	26000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U16);
+PERIPH_CLK(uarta,	"tegra-uart.0",		NULL,	6,	0x178,	600000000, mux_pllp_pllc_pllm_clkm,	MUX);
+PERIPH_CLK(uartb,	"tegra-uart.1",		NULL,	7,	0x17c,	600000000, mux_pllp_pllc_pllm_clkm,	MUX);
+PERIPH_CLK(uartc,	"tegra-uart.2",		NULL,	55,	0x1a0,	600000000, mux_pllp_pllc_pllm_clkm,	MUX);
+PERIPH_CLK(uartd,	"tegra-uart.3",		NULL,	65,	0x1c0,	600000000, mux_pllp_pllc_pllm_clkm,	MUX);
+PERIPH_CLK(uarte,	"tegra-uart.4",		NULL,	66,	0x1c4,	600000000, mux_pllp_pllc_pllm_clkm,	MUX);
+PERIPH_CLK(3d,		"3d",			NULL,	24,	0x158,	300000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71 | PERIPH_MANUAL_RESET); /* scales with voltage and process_id */
+PERIPH_CLK(2d,		"2d",			NULL,	21,	0x15c,	300000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71); /* scales with voltage and process_id */
+PERIPH_CLK(vi,		"tegra_camera",		"vi",	20,	0x148,	150000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71); /* scales with voltage and process_id */
+PERIPH_CLK(vi_sensor,	"tegra_camera",		"vi_sensor",	20,	0x1a8,	150000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71 | PERIPH_NO_RESET); /* scales with voltage and process_id */
+PERIPH_CLK(epp,		"epp",			NULL,	19,	0x16c,	300000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71); /* scales with voltage and process_id */
+PERIPH_CLK(mpe,		"mpe",			NULL,	60,	0x170,	250000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71); /* scales with voltage and process_id */
+PERIPH_CLK(host1x,	"host1x",		NULL,	28,	0x180,	166000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71); /* scales with voltage and process_id */
+PERIPH_CLK(cve,		"cve",			NULL,	49,	0x140,	250000000, mux_pllp_plld_pllc_clkm,	MUX | DIV_U71); /* requires min voltage */
+PERIPH_CLK(tvo,		"tvo",			NULL,	49,	0x188,	250000000, mux_pllp_plld_pllc_clkm,	MUX | DIV_U71); /* requires min voltage */
+PERIPH_CLK(hdmi,	"hdmi",			NULL,	51,	0x18c,	600000000, mux_pllp_plld_pllc_clkm,	MUX | DIV_U71); /* requires min voltage */
+PERIPH_CLK(tvdac,	"tvdac",		NULL,	53,	0x194,	250000000, mux_pllp_plld_pllc_clkm,	MUX | DIV_U71); /* requires min voltage */
+PERIPH_CLK(disp1,	"tegradc.0",		NULL,	27,	0x138,	600000000, mux_pllp_plld_pllc_clkm,	MUX); /* scales with voltage and process_id */
+PERIPH_CLK(disp2,	"tegradc.1",		NULL,	26,	0x13c,	600000000, mux_pllp_plld_pllc_clkm,	MUX); /* scales with voltage and process_id */
+PERIPH_CLK(usbd,	"fsl-tegra-udc",	NULL,	22,	0,	480000000, mux_clk_m,			0); /* requires min voltage */
+PERIPH_CLK(usb2,	"tegra-ehci.1",		NULL,	58,	0,	480000000, mux_clk_m,			0); /* requires min voltage */
+PERIPH_CLK(usb3,	"tegra-ehci.2",		NULL,	59,	0,	480000000, mux_clk_m,			0); /* requires min voltage */
+PERIPH_CLK(dsi,		"dsi",			NULL,	48,	0,	500000000, mux_plld,			0); /* scales with voltage */
+PERIPH_CLK(csi,		"tegra_camera",		"csi",	52,	0,	72000000,  mux_pllp_out3,		0);
+PERIPH_CLK(isp,		"tegra_camera",		"isp",	23,	0,	150000000, mux_clk_m,			0); /* same frequency as VI */
+PERIPH_CLK(csus,	"tegra_camera",		"csus",	92,	0,	150000000, mux_clk_m,			PERIPH_NO_RESET);
+PERIPH_CLK(pex,		NULL,			"pex",  70,     0,	26000000,  mux_clk_m,			PERIPH_MANUAL_RESET);
+PERIPH_CLK(afi,		NULL,			"afi",  72,     0,	26000000,  mux_clk_m,			PERIPH_MANUAL_RESET);
+PERIPH_CLK(pcie_xclk,	NULL,		  "pcie_xclk",  74,     0,	26000000,  mux_clk_m,			PERIPH_MANUAL_RESET);
+
+static struct clk *tegra_list_clks[] = {
+	&tegra_apbdma,
+	&tegra_rtc,
+	&tegra_i2s1,
+	&tegra_i2s2,
+	&tegra_spdif_out,
+	&tegra_spdif_in,
+	&tegra_pwm,
+	&tegra_spi,
+	&tegra_xio,
+	&tegra_twc,
+	&tegra_sbc1,
+	&tegra_sbc2,
+	&tegra_sbc3,
+	&tegra_sbc4,
+	&tegra_ide,
+	&tegra_ndflash,
+	&tegra_vfir,
+	&tegra_sdmmc1,
+	&tegra_sdmmc2,
+	&tegra_sdmmc3,
+	&tegra_sdmmc4,
+	&tegra_vcp,
+	&tegra_bsea,
+	&tegra_bsev,
+	&tegra_vde,
+	&tegra_csite,
+	&tegra_la,
+	&tegra_owr,
+	&tegra_nor,
+	&tegra_mipi,
+	&tegra_i2c1,
+	&tegra_i2c2,
+	&tegra_i2c3,
+	&tegra_dvc,
+	&tegra_uarta,
+	&tegra_uartb,
+	&tegra_uartc,
+	&tegra_uartd,
+	&tegra_uarte,
+	&tegra_3d,
+	&tegra_2d,
+	&tegra_vi,
+	&tegra_vi_sensor,
+	&tegra_epp,
+	&tegra_mpe,
+	&tegra_host1x,
+	&tegra_cve,
+	&tegra_tvo,
+	&tegra_hdmi,
+	&tegra_tvdac,
+	&tegra_disp1,
+	&tegra_disp2,
+	&tegra_usbd,
+	&tegra_usb2,
+	&tegra_usb3,
+	&tegra_dsi,
+	&tegra_csi,
+	&tegra_isp,
+	&tegra_csus,
+	&tegra_pex,
+	&tegra_afi,
+	&tegra_pcie_xclk,
+};
+
+#define CLK_DUPLICATE(_name, _dev, _con)	\
+	{					\
+		.name	= _name,		\
+		.lookup	= {			\
+			.dev_id	= _dev,		\
+			.con_id	= _con,		\
+		},				\
+	}
+
+/* Some clocks may be used by different drivers depending on the board
+ * configuration.  List those here to register them twice in the clock lookup
+ * table under two names.
+ */
+static struct clk_duplicate tegra_clk_duplicates[] = {
+	CLK_DUPLICATE("uarta",	"serial8250.0",	NULL),
+	CLK_DUPLICATE("uartb",	"serial8250.1",	NULL),
+	CLK_DUPLICATE("uartc",	"serial8250.2",	NULL),
+	CLK_DUPLICATE("uartd",	"serial8250.3",	NULL),
+	CLK_DUPLICATE("uarte",	"serial8250.4",	NULL),
+	CLK_DUPLICATE("usbd",	"utmip-pad",	NULL),
+	CLK_DUPLICATE("usbd",	"tegra-ehci.0",	NULL),
+	CLK_DUPLICATE("usbd",	"tegra-otg",	NULL),
+	CLK_DUPLICATE("hdmi",	"tegradc.0",	"hdmi"),
+	CLK_DUPLICATE("hdmi",	"tegradc.1",	"hdmi"),
+	CLK_DUPLICATE("host1x",	"tegra_grhost",	"host1x"),
+	CLK_DUPLICATE("2d",	"tegra_grhost",	"gr2d"),
+	CLK_DUPLICATE("3d",	"tegra_grhost",	"gr3d"),
+	CLK_DUPLICATE("epp",	"tegra_grhost",	"epp"),
+	CLK_DUPLICATE("mpe",	"tegra_grhost",	"mpe"),
+	CLK_DUPLICATE("cop",	"tegra-avp",	"cop"),
+	CLK_DUPLICATE("vde",	"tegra-aes",	"vde"),
+	CLK_DUPLICATE("cclk",	NULL,		"cpu"),
+	CLK_DUPLICATE("twd",	"smp_twd",	NULL),
+	CLK_DUPLICATE("pll_p_out3", "tegra-i2c.0", "fast-clk"),
+	CLK_DUPLICATE("pll_p_out3", "tegra-i2c.1", "fast-clk"),
+	CLK_DUPLICATE("pll_p_out3", "tegra-i2c.2", "fast-clk"),
+	CLK_DUPLICATE("pll_p_out3", "tegra-i2c.3", "fast-clk"),
+};
+
+#define CLK(dev, con, ck)	\
+	{			\
+		.dev_id	= dev,	\
+		.con_id	= con,	\
+		.clk	= ck,	\
+	}
+
+static struct clk *tegra_ptr_clks[] = {
+	&tegra_clk_32k,
+	&tegra_pll_s,
+	&tegra_clk_m,
+	&tegra_pll_m,
+	&tegra_pll_m_out1,
+	&tegra_pll_c,
+	&tegra_pll_c_out1,
+	&tegra_pll_p,
+	&tegra_pll_p_out1,
+	&tegra_pll_p_out2,
+	&tegra_pll_p_out3,
+	&tegra_pll_p_out4,
+	&tegra_pll_a,
+	&tegra_pll_a_out0,
+	&tegra_pll_d,
+	&tegra_pll_d_out0,
+	&tegra_pll_u,
+	&tegra_pll_x,
+	&tegra_pll_e,
+	&tegra_cclk,
+	&tegra_clk_twd,
+	&tegra_sclk,
+	&tegra_hclk,
+	&tegra_pclk,
+	&tegra_clk_d,
+	&tegra_cdev1,
+	&tegra_cdev2,
+	&tegra_blink,
+	&tegra_cop,
+	&tegra_emc,
+};
+
+static void tegra2_init_one_clock(struct clk *c)
+{
+	struct clk_tegra *clk = to_clk_tegra(c->hw);
+	int ret;
+
+	ret = __clk_init(NULL, c);
+	if (ret)
+		pr_err("clk init failed %s\n", __clk_get_name(c));
+
+	INIT_LIST_HEAD(&clk->shared_bus_list);
+	if (!clk->lookup.dev_id && !clk->lookup.con_id)
+		clk->lookup.con_id = c->name;
+	clk->lookup.clk = c;
+	clkdev_add(&clk->lookup);
+	tegra_clk_add(c);
+}
+
+void __init tegra2_init_clocks(void)
+{
+	int i;
+	struct clk *c;
+
+	for (i = 0; i < ARRAY_SIZE(tegra_ptr_clks); i++)
+		tegra2_init_one_clock(tegra_ptr_clks[i]);
+
+	for (i = 0; i < ARRAY_SIZE(tegra_list_clks); i++)
+		tegra2_init_one_clock(tegra_list_clks[i]);
+
+	for (i = 0; i < ARRAY_SIZE(tegra_clk_duplicates); i++) {
+		c = tegra_get_clock_by_name(tegra_clk_duplicates[i].name);
+		if (!c) {
+			pr_err("%s: Unknown duplicate clock %s\n", __func__,
+				tegra_clk_duplicates[i].name);
+			continue;
+		}
+
+		tegra_clk_duplicates[i].lookup.clk = c;
+		clkdev_add(&tegra_clk_duplicates[i].lookup);
+	}
+
+	init_audio_sync_clock_mux();
+	tegra20_cpu_car_ops_init();
+}
diff --git a/arch/arm/mach-tegra/tegra2_clocks.c b/arch/arm/mach-tegra/tegra2_clocks.c
deleted file mode 100644
index a703844..0000000
--- a/arch/arm/mach-tegra/tegra2_clocks.c
+++ /dev/null
@@ -1,2484 +0,0 @@
-/*
- * arch/arm/mach-tegra/tegra2_clocks.c
- *
- * Copyright (C) 2010 Google, Inc.
- *
- * Author:
- *	Colin Cross <ccross@google.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/list.h>
-#include <linux/spinlock.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/clkdev.h>
-#include <linux/clk.h>
-
-#include <mach/iomap.h>
-#include <mach/suspend.h>
-
-#include "clock.h"
-#include "fuse.h"
-#include "tegra2_emc.h"
-
-#define RST_DEVICES			0x004
-#define RST_DEVICES_SET			0x300
-#define RST_DEVICES_CLR			0x304
-#define RST_DEVICES_NUM			3
-
-#define CLK_OUT_ENB			0x010
-#define CLK_OUT_ENB_SET			0x320
-#define CLK_OUT_ENB_CLR			0x324
-#define CLK_OUT_ENB_NUM			3
-
-#define CLK_MASK_ARM			0x44
-#define MISC_CLK_ENB			0x48
-
-#define OSC_CTRL			0x50
-#define OSC_CTRL_OSC_FREQ_MASK		(3<<30)
-#define OSC_CTRL_OSC_FREQ_13MHZ		(0<<30)
-#define OSC_CTRL_OSC_FREQ_19_2MHZ	(1<<30)
-#define OSC_CTRL_OSC_FREQ_12MHZ		(2<<30)
-#define OSC_CTRL_OSC_FREQ_26MHZ		(3<<30)
-#define OSC_CTRL_MASK			(0x3f2 | OSC_CTRL_OSC_FREQ_MASK)
-
-#define OSC_FREQ_DET			0x58
-#define OSC_FREQ_DET_TRIG		(1<<31)
-
-#define OSC_FREQ_DET_STATUS		0x5C
-#define OSC_FREQ_DET_BUSY		(1<<31)
-#define OSC_FREQ_DET_CNT_MASK		0xFFFF
-
-#define PERIPH_CLK_SOURCE_I2S1		0x100
-#define PERIPH_CLK_SOURCE_EMC		0x19c
-#define PERIPH_CLK_SOURCE_OSC		0x1fc
-#define PERIPH_CLK_SOURCE_NUM \
-	((PERIPH_CLK_SOURCE_OSC - PERIPH_CLK_SOURCE_I2S1) / 4)
-
-#define PERIPH_CLK_SOURCE_MASK		(3<<30)
-#define PERIPH_CLK_SOURCE_SHIFT		30
-#define PERIPH_CLK_SOURCE_PWM_MASK	(7<<28)
-#define PERIPH_CLK_SOURCE_PWM_SHIFT	28
-#define PERIPH_CLK_SOURCE_ENABLE	(1<<28)
-#define PERIPH_CLK_SOURCE_DIVU71_MASK	0xFF
-#define PERIPH_CLK_SOURCE_DIVU16_MASK	0xFFFF
-#define PERIPH_CLK_SOURCE_DIV_SHIFT	0
-
-#define SDMMC_CLK_INT_FB_SEL		(1 << 23)
-#define SDMMC_CLK_INT_FB_DLY_SHIFT	16
-#define SDMMC_CLK_INT_FB_DLY_MASK	(0xF << SDMMC_CLK_INT_FB_DLY_SHIFT)
-
-#define PLL_BASE			0x0
-#define PLL_BASE_BYPASS			(1<<31)
-#define PLL_BASE_ENABLE			(1<<30)
-#define PLL_BASE_REF_ENABLE		(1<<29)
-#define PLL_BASE_OVERRIDE		(1<<28)
-#define PLL_BASE_DIVP_MASK		(0x7<<20)
-#define PLL_BASE_DIVP_SHIFT		20
-#define PLL_BASE_DIVN_MASK		(0x3FF<<8)
-#define PLL_BASE_DIVN_SHIFT		8
-#define PLL_BASE_DIVM_MASK		(0x1F)
-#define PLL_BASE_DIVM_SHIFT		0
-
-#define PLL_OUT_RATIO_MASK		(0xFF<<8)
-#define PLL_OUT_RATIO_SHIFT		8
-#define PLL_OUT_OVERRIDE		(1<<2)
-#define PLL_OUT_CLKEN			(1<<1)
-#define PLL_OUT_RESET_DISABLE		(1<<0)
-
-#define PLL_MISC(c)			(((c)->flags & PLL_ALT_MISC_REG) ? 0x4 : 0xc)
-
-#define PLL_MISC_DCCON_SHIFT		20
-#define PLL_MISC_CPCON_SHIFT		8
-#define PLL_MISC_CPCON_MASK		(0xF<<PLL_MISC_CPCON_SHIFT)
-#define PLL_MISC_LFCON_SHIFT		4
-#define PLL_MISC_LFCON_MASK		(0xF<<PLL_MISC_LFCON_SHIFT)
-#define PLL_MISC_VCOCON_SHIFT		0
-#define PLL_MISC_VCOCON_MASK		(0xF<<PLL_MISC_VCOCON_SHIFT)
-
-#define PLLU_BASE_POST_DIV		(1<<20)
-
-#define PLLD_MISC_CLKENABLE		(1<<30)
-#define PLLD_MISC_DIV_RST		(1<<23)
-#define PLLD_MISC_DCCON_SHIFT		12
-
-#define PLLE_MISC_READY			(1 << 15)
-
-#define PERIPH_CLK_TO_ENB_REG(c)	((c->u.periph.clk_num / 32) * 4)
-#define PERIPH_CLK_TO_ENB_SET_REG(c)	((c->u.periph.clk_num / 32) * 8)
-#define PERIPH_CLK_TO_ENB_BIT(c)	(1 << (c->u.periph.clk_num % 32))
-
-#define SUPER_CLK_MUX			0x00
-#define SUPER_STATE_SHIFT		28
-#define SUPER_STATE_MASK		(0xF << SUPER_STATE_SHIFT)
-#define SUPER_STATE_STANDBY		(0x0 << SUPER_STATE_SHIFT)
-#define SUPER_STATE_IDLE		(0x1 << SUPER_STATE_SHIFT)
-#define SUPER_STATE_RUN			(0x2 << SUPER_STATE_SHIFT)
-#define SUPER_STATE_IRQ			(0x3 << SUPER_STATE_SHIFT)
-#define SUPER_STATE_FIQ			(0x4 << SUPER_STATE_SHIFT)
-#define SUPER_SOURCE_MASK		0xF
-#define	SUPER_FIQ_SOURCE_SHIFT		12
-#define	SUPER_IRQ_SOURCE_SHIFT		8
-#define	SUPER_RUN_SOURCE_SHIFT		4
-#define	SUPER_IDLE_SOURCE_SHIFT		0
-
-#define SUPER_CLK_DIVIDER		0x04
-
-#define BUS_CLK_DISABLE			(1<<3)
-#define BUS_CLK_DIV_MASK		0x3
-
-#define PMC_CTRL			0x0
- #define PMC_CTRL_BLINK_ENB		(1 << 7)
-
-#define PMC_DPD_PADS_ORIDE		0x1c
- #define PMC_DPD_PADS_ORIDE_BLINK_ENB	(1 << 20)
-
-#define PMC_BLINK_TIMER_DATA_ON_SHIFT	0
-#define PMC_BLINK_TIMER_DATA_ON_MASK	0x7fff
-#define PMC_BLINK_TIMER_ENB		(1 << 15)
-#define PMC_BLINK_TIMER_DATA_OFF_SHIFT	16
-#define PMC_BLINK_TIMER_DATA_OFF_MASK	0xffff
-
-static void __iomem *reg_clk_base = IO_ADDRESS(TEGRA_CLK_RESET_BASE);
-static void __iomem *reg_pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
-
-/*
- * Some clocks share a register with other clocks.  Any clock op that
- * non-atomically modifies a register used by another clock must lock
- * clock_register_lock first.
- */
-static DEFINE_SPINLOCK(clock_register_lock);
-
-/*
- * Some peripheral clocks share an enable bit, so refcount the enable bits
- * in registers CLK_ENABLE_L, CLK_ENABLE_H, and CLK_ENABLE_U
- */
-static int tegra_periph_clk_enable_refcount[3 * 32];
-
-#define clk_writel(value, reg) \
-	__raw_writel(value, reg_clk_base + (reg))
-#define clk_readl(reg) \
-	__raw_readl(reg_clk_base + (reg))
-#define pmc_writel(value, reg) \
-	__raw_writel(value, reg_pmc_base + (reg))
-#define pmc_readl(reg) \
-	__raw_readl(reg_pmc_base + (reg))
-
-static unsigned long clk_measure_input_freq(void)
-{
-	u32 clock_autodetect;
-	clk_writel(OSC_FREQ_DET_TRIG | 1, OSC_FREQ_DET);
-	do {} while (clk_readl(OSC_FREQ_DET_STATUS) & OSC_FREQ_DET_BUSY);
-	clock_autodetect = clk_readl(OSC_FREQ_DET_STATUS);
-	if (clock_autodetect >= 732 - 3 && clock_autodetect <= 732 + 3) {
-		return 12000000;
-	} else if (clock_autodetect >= 794 - 3 && clock_autodetect <= 794 + 3) {
-		return 13000000;
-	} else if (clock_autodetect >= 1172 - 3 && clock_autodetect <= 1172 + 3) {
-		return 19200000;
-	} else if (clock_autodetect >= 1587 - 3 && clock_autodetect <= 1587 + 3) {
-		return 26000000;
-	} else {
-		pr_err("%s: Unexpected clock autodetect value %d", __func__, clock_autodetect);
-		BUG();
-		return 0;
-	}
-}
-
-static int clk_div71_get_divider(unsigned long parent_rate, unsigned long rate)
-{
-	s64 divider_u71 = parent_rate * 2;
-	divider_u71 += rate - 1;
-	do_div(divider_u71, rate);
-
-	if (divider_u71 - 2 < 0)
-		return 0;
-
-	if (divider_u71 - 2 > 255)
-		return -EINVAL;
-
-	return divider_u71 - 2;
-}
-
-static int clk_div16_get_divider(unsigned long parent_rate, unsigned long rate)
-{
-	s64 divider_u16;
-
-	divider_u16 = parent_rate;
-	divider_u16 += rate - 1;
-	do_div(divider_u16, rate);
-
-	if (divider_u16 - 1 < 0)
-		return 0;
-
-	if (divider_u16 - 1 > 255)
-		return -EINVAL;
-
-	return divider_u16 - 1;
-}
-
-/* clk_m functions */
-static unsigned long tegra2_clk_m_autodetect_rate(struct clk *c)
-{
-	u32 auto_clock_control = clk_readl(OSC_CTRL) & ~OSC_CTRL_OSC_FREQ_MASK;
-
-	c->rate = clk_measure_input_freq();
-	switch (c->rate) {
-	case 12000000:
-		auto_clock_control |= OSC_CTRL_OSC_FREQ_12MHZ;
-		break;
-	case 13000000:
-		auto_clock_control |= OSC_CTRL_OSC_FREQ_13MHZ;
-		break;
-	case 19200000:
-		auto_clock_control |= OSC_CTRL_OSC_FREQ_19_2MHZ;
-		break;
-	case 26000000:
-		auto_clock_control |= OSC_CTRL_OSC_FREQ_26MHZ;
-		break;
-	default:
-		pr_err("%s: Unexpected clock rate %ld", __func__, c->rate);
-		BUG();
-	}
-	clk_writel(auto_clock_control, OSC_CTRL);
-	return c->rate;
-}
-
-static void tegra2_clk_m_init(struct clk *c)
-{
-	pr_debug("%s on clock %s\n", __func__, c->name);
-	tegra2_clk_m_autodetect_rate(c);
-}
-
-static int tegra2_clk_m_enable(struct clk *c)
-{
-	pr_debug("%s on clock %s\n", __func__, c->name);
-	return 0;
-}
-
-static void tegra2_clk_m_disable(struct clk *c)
-{
-	pr_debug("%s on clock %s\n", __func__, c->name);
-	BUG();
-}
-
-static struct clk_ops tegra_clk_m_ops = {
-	.init		= tegra2_clk_m_init,
-	.enable		= tegra2_clk_m_enable,
-	.disable	= tegra2_clk_m_disable,
-};
-
-/* super clock functions */
-/* "super clocks" on tegra have two-stage muxes and a clock skipping
- * super divider.  We will ignore the clock skipping divider, since we
- * can't lower the voltage when using the clock skip, but we can if we
- * lower the PLL frequency.
- */
-static void tegra2_super_clk_init(struct clk *c)
-{
-	u32 val;
-	int source;
-	int shift;
-	const struct clk_mux_sel *sel;
-	val = clk_readl(c->reg + SUPER_CLK_MUX);
-	c->state = ON;
-	BUG_ON(((val & SUPER_STATE_MASK) != SUPER_STATE_RUN) &&
-		((val & SUPER_STATE_MASK) != SUPER_STATE_IDLE));
-	shift = ((val & SUPER_STATE_MASK) == SUPER_STATE_IDLE) ?
-		SUPER_IDLE_SOURCE_SHIFT : SUPER_RUN_SOURCE_SHIFT;
-	source = (val >> shift) & SUPER_SOURCE_MASK;
-	for (sel = c->inputs; sel->input != NULL; sel++) {
-		if (sel->value == source)
-			break;
-	}
-	BUG_ON(sel->input == NULL);
-	c->parent = sel->input;
-}
-
-static int tegra2_super_clk_enable(struct clk *c)
-{
-	clk_writel(0, c->reg + SUPER_CLK_DIVIDER);
-	return 0;
-}
-
-static void tegra2_super_clk_disable(struct clk *c)
-{
-	pr_debug("%s on clock %s\n", __func__, c->name);
-
-	/* oops - don't disable the CPU clock! */
-	BUG();
-}
-
-static int tegra2_super_clk_set_parent(struct clk *c, struct clk *p)
-{
-	u32 val;
-	const struct clk_mux_sel *sel;
-	int shift;
-
-	val = clk_readl(c->reg + SUPER_CLK_MUX);
-	BUG_ON(((val & SUPER_STATE_MASK) != SUPER_STATE_RUN) &&
-		((val & SUPER_STATE_MASK) != SUPER_STATE_IDLE));
-	shift = ((val & SUPER_STATE_MASK) == SUPER_STATE_IDLE) ?
-		SUPER_IDLE_SOURCE_SHIFT : SUPER_RUN_SOURCE_SHIFT;
-	for (sel = c->inputs; sel->input != NULL; sel++) {
-		if (sel->input == p) {
-			val &= ~(SUPER_SOURCE_MASK << shift);
-			val |= sel->value << shift;
-
-			if (c->refcnt)
-				clk_enable(p);
-
-			clk_writel(val, c->reg);
-
-			if (c->refcnt && c->parent)
-				clk_disable(c->parent);
-
-			clk_reparent(c, p);
-			return 0;
-		}
-	}
-	return -EINVAL;
-}
-
-/*
- * Super clocks have "clock skippers" instead of dividers.  Dividing using
- * a clock skipper does not allow the voltage to be scaled down, so instead
- * adjust the rate of the parent clock.  This requires that the parent of a
- * super clock have no other children, otherwise the rate will change
- * underneath the other children.
- */
-static int tegra2_super_clk_set_rate(struct clk *c, unsigned long rate)
-{
-	return clk_set_rate(c->parent, rate);
-}
-
-static struct clk_ops tegra_super_ops = {
-	.init			= tegra2_super_clk_init,
-	.enable			= tegra2_super_clk_enable,
-	.disable		= tegra2_super_clk_disable,
-	.set_parent		= tegra2_super_clk_set_parent,
-	.set_rate		= tegra2_super_clk_set_rate,
-};
-
-/* virtual cpu clock functions */
-/* some clocks can not be stopped (cpu, memory bus) while the SoC is running.
-   To change the frequency of these clocks, the parent pll may need to be
-   reprogrammed, so the clock must be moved off the pll, the pll reprogrammed,
-   and then the clock moved back to the pll.  To hide this sequence, a virtual
-   clock handles it.
- */
-static void tegra2_cpu_clk_init(struct clk *c)
-{
-}
-
-static int tegra2_cpu_clk_enable(struct clk *c)
-{
-	return 0;
-}
-
-static void tegra2_cpu_clk_disable(struct clk *c)
-{
-	pr_debug("%s on clock %s\n", __func__, c->name);
-
-	/* oops - don't disable the CPU clock! */
-	BUG();
-}
-
-static int tegra2_cpu_clk_set_rate(struct clk *c, unsigned long rate)
-{
-	int ret;
-	/*
-	 * Take an extra reference to the main pll so it doesn't turn
-	 * off when we move the cpu off of it
-	 */
-	clk_enable(c->u.cpu.main);
-
-	ret = clk_set_parent(c->parent, c->u.cpu.backup);
-	if (ret) {
-		pr_err("Failed to switch cpu to clock %s\n", c->u.cpu.backup->name);
-		goto out;
-	}
-
-	if (rate == clk_get_rate(c->u.cpu.backup))
-		goto out;
-
-	ret = clk_set_rate(c->u.cpu.main, rate);
-	if (ret) {
-		pr_err("Failed to change cpu pll to %lu\n", rate);
-		goto out;
-	}
-
-	ret = clk_set_parent(c->parent, c->u.cpu.main);
-	if (ret) {
-		pr_err("Failed to switch cpu to clock %s\n", c->u.cpu.main->name);
-		goto out;
-	}
-
-out:
-	clk_disable(c->u.cpu.main);
-	return ret;
-}
-
-static struct clk_ops tegra_cpu_ops = {
-	.init     = tegra2_cpu_clk_init,
-	.enable   = tegra2_cpu_clk_enable,
-	.disable  = tegra2_cpu_clk_disable,
-	.set_rate = tegra2_cpu_clk_set_rate,
-};
-
-/* virtual cop clock functions. Used to acquire the fake 'cop' clock to
- * reset the COP block (i.e. AVP) */
-static void tegra2_cop_clk_reset(struct clk *c, bool assert)
-{
-	unsigned long reg = assert ? RST_DEVICES_SET : RST_DEVICES_CLR;
-
-	pr_debug("%s %s\n", __func__, assert ? "assert" : "deassert");
-	clk_writel(1 << 1, reg);
-}
-
-static struct clk_ops tegra_cop_ops = {
-	.reset    = tegra2_cop_clk_reset,
-};
-
-/* bus clock functions */
-static void tegra2_bus_clk_init(struct clk *c)
-{
-	u32 val = clk_readl(c->reg);
-	c->state = ((val >> c->reg_shift) & BUS_CLK_DISABLE) ? OFF : ON;
-	c->div = ((val >> c->reg_shift) & BUS_CLK_DIV_MASK) + 1;
-	c->mul = 1;
-}
-
-static int tegra2_bus_clk_enable(struct clk *c)
-{
-	u32 val;
-	unsigned long flags;
-
-	spin_lock_irqsave(&clock_register_lock, flags);
-
-	val = clk_readl(c->reg);
-	val &= ~(BUS_CLK_DISABLE << c->reg_shift);
-	clk_writel(val, c->reg);
-
-	spin_unlock_irqrestore(&clock_register_lock, flags);
-
-	return 0;
-}
-
-static void tegra2_bus_clk_disable(struct clk *c)
-{
-	u32 val;
-	unsigned long flags;
-
-	spin_lock_irqsave(&clock_register_lock, flags);
-
-	val = clk_readl(c->reg);
-	val |= BUS_CLK_DISABLE << c->reg_shift;
-	clk_writel(val, c->reg);
-
-	spin_unlock_irqrestore(&clock_register_lock, flags);
-}
-
-static int tegra2_bus_clk_set_rate(struct clk *c, unsigned long rate)
-{
-	u32 val;
-	unsigned long parent_rate = clk_get_rate(c->parent);
-	unsigned long flags;
-	int ret = -EINVAL;
-	int i;
-
-	spin_lock_irqsave(&clock_register_lock, flags);
-
-	val = clk_readl(c->reg);
-	for (i = 1; i <= 4; i++) {
-		if (rate == parent_rate / i) {
-			val &= ~(BUS_CLK_DIV_MASK << c->reg_shift);
-			val |= (i - 1) << c->reg_shift;
-			clk_writel(val, c->reg);
-			c->div = i;
-			c->mul = 1;
-			ret = 0;
-			break;
-		}
-	}
-
-	spin_unlock_irqrestore(&clock_register_lock, flags);
-
-	return ret;
-}
-
-static struct clk_ops tegra_bus_ops = {
-	.init			= tegra2_bus_clk_init,
-	.enable			= tegra2_bus_clk_enable,
-	.disable		= tegra2_bus_clk_disable,
-	.set_rate		= tegra2_bus_clk_set_rate,
-};
-
-/* Blink output functions */
-
-static void tegra2_blink_clk_init(struct clk *c)
-{
-	u32 val;
-
-	val = pmc_readl(PMC_CTRL);
-	c->state = (val & PMC_CTRL_BLINK_ENB) ? ON : OFF;
-	c->mul = 1;
-	val = pmc_readl(c->reg);
-
-	if (val & PMC_BLINK_TIMER_ENB) {
-		unsigned int on_off;
-
-		on_off = (val >> PMC_BLINK_TIMER_DATA_ON_SHIFT) &
-			PMC_BLINK_TIMER_DATA_ON_MASK;
-		val >>= PMC_BLINK_TIMER_DATA_OFF_SHIFT;
-		val &= PMC_BLINK_TIMER_DATA_OFF_MASK;
-		on_off += val;
-		/* each tick in the blink timer is 4 32KHz clocks */
-		c->div = on_off * 4;
-	} else {
-		c->div = 1;
-	}
-}
-
-static int tegra2_blink_clk_enable(struct clk *c)
-{
-	u32 val;
-
-	val = pmc_readl(PMC_DPD_PADS_ORIDE);
-	pmc_writel(val | PMC_DPD_PADS_ORIDE_BLINK_ENB, PMC_DPD_PADS_ORIDE);
-
-	val = pmc_readl(PMC_CTRL);
-	pmc_writel(val | PMC_CTRL_BLINK_ENB, PMC_CTRL);
-
-	return 0;
-}
-
-static void tegra2_blink_clk_disable(struct clk *c)
-{
-	u32 val;
-
-	val = pmc_readl(PMC_CTRL);
-	pmc_writel(val & ~PMC_CTRL_BLINK_ENB, PMC_CTRL);
-
-	val = pmc_readl(PMC_DPD_PADS_ORIDE);
-	pmc_writel(val & ~PMC_DPD_PADS_ORIDE_BLINK_ENB, PMC_DPD_PADS_ORIDE);
-}
-
-static int tegra2_blink_clk_set_rate(struct clk *c, unsigned long rate)
-{
-	unsigned long parent_rate = clk_get_rate(c->parent);
-	if (rate >= parent_rate) {
-		c->div = 1;
-		pmc_writel(0, c->reg);
-	} else {
-		unsigned int on_off;
-		u32 val;
-
-		on_off = DIV_ROUND_UP(parent_rate / 8, rate);
-		c->div = on_off * 8;
-
-		val = (on_off & PMC_BLINK_TIMER_DATA_ON_MASK) <<
-			PMC_BLINK_TIMER_DATA_ON_SHIFT;
-		on_off &= PMC_BLINK_TIMER_DATA_OFF_MASK;
-		on_off <<= PMC_BLINK_TIMER_DATA_OFF_SHIFT;
-		val |= on_off;
-		val |= PMC_BLINK_TIMER_ENB;
-		pmc_writel(val, c->reg);
-	}
-
-	return 0;
-}
-
-static struct clk_ops tegra_blink_clk_ops = {
-	.init			= &tegra2_blink_clk_init,
-	.enable			= &tegra2_blink_clk_enable,
-	.disable		= &tegra2_blink_clk_disable,
-	.set_rate		= &tegra2_blink_clk_set_rate,
-};
-
-/* PLL Functions */
-static int tegra2_pll_clk_wait_for_lock(struct clk *c)
-{
-	udelay(c->u.pll.lock_delay);
-
-	return 0;
-}
-
-static void tegra2_pll_clk_init(struct clk *c)
-{
-	u32 val = clk_readl(c->reg + PLL_BASE);
-
-	c->state = (val & PLL_BASE_ENABLE) ? ON : OFF;
-
-	if (c->flags & PLL_FIXED && !(val & PLL_BASE_OVERRIDE)) {
-		pr_warning("Clock %s has unknown fixed frequency\n", c->name);
-		c->mul = 1;
-		c->div = 1;
-	} else if (val & PLL_BASE_BYPASS) {
-		c->mul = 1;
-		c->div = 1;
-	} else {
-		c->mul = (val & PLL_BASE_DIVN_MASK) >> PLL_BASE_DIVN_SHIFT;
-		c->div = (val & PLL_BASE_DIVM_MASK) >> PLL_BASE_DIVM_SHIFT;
-		if (c->flags & PLLU)
-			c->div *= (val & PLLU_BASE_POST_DIV) ? 1 : 2;
-		else
-			c->div *= (val & PLL_BASE_DIVP_MASK) ? 2 : 1;
-	}
-}
-
-static int tegra2_pll_clk_enable(struct clk *c)
-{
-	u32 val;
-	pr_debug("%s on clock %s\n", __func__, c->name);
-
-	val = clk_readl(c->reg + PLL_BASE);
-	val &= ~PLL_BASE_BYPASS;
-	val |= PLL_BASE_ENABLE;
-	clk_writel(val, c->reg + PLL_BASE);
-
-	tegra2_pll_clk_wait_for_lock(c);
-
-	return 0;
-}
-
-static void tegra2_pll_clk_disable(struct clk *c)
-{
-	u32 val;
-	pr_debug("%s on clock %s\n", __func__, c->name);
-
-	val = clk_readl(c->reg);
-	val &= ~(PLL_BASE_BYPASS | PLL_BASE_ENABLE);
-	clk_writel(val, c->reg);
-}
-
-static int tegra2_pll_clk_set_rate(struct clk *c, unsigned long rate)
-{
-	u32 val;
-	unsigned long input_rate;
-	const struct clk_pll_freq_table *sel;
-
-	pr_debug("%s: %s %lu\n", __func__, c->name, rate);
-
-	input_rate = clk_get_rate(c->parent);
-	for (sel = c->u.pll.freq_table; sel->input_rate != 0; sel++) {
-		if (sel->input_rate == input_rate && sel->output_rate == rate) {
-			c->mul = sel->n;
-			c->div = sel->m * sel->p;
-
-			val = clk_readl(c->reg + PLL_BASE);
-			if (c->flags & PLL_FIXED)
-				val |= PLL_BASE_OVERRIDE;
-			val &= ~(PLL_BASE_DIVP_MASK | PLL_BASE_DIVN_MASK |
-				 PLL_BASE_DIVM_MASK);
-			val |= (sel->m << PLL_BASE_DIVM_SHIFT) |
-				(sel->n << PLL_BASE_DIVN_SHIFT);
-			BUG_ON(sel->p < 1 || sel->p > 2);
-			if (c->flags & PLLU) {
-				if (sel->p == 1)
-					val |= PLLU_BASE_POST_DIV;
-			} else {
-				if (sel->p == 2)
-					val |= 1 << PLL_BASE_DIVP_SHIFT;
-			}
-			clk_writel(val, c->reg + PLL_BASE);
-
-			if (c->flags & PLL_HAS_CPCON) {
-				val = clk_readl(c->reg + PLL_MISC(c));
-				val &= ~PLL_MISC_CPCON_MASK;
-				val |= sel->cpcon << PLL_MISC_CPCON_SHIFT;
-				clk_writel(val, c->reg + PLL_MISC(c));
-			}
-
-			if (c->state == ON)
-				tegra2_pll_clk_enable(c);
-
-			return 0;
-		}
-	}
-	return -EINVAL;
-}
-
-static struct clk_ops tegra_pll_ops = {
-	.init			= tegra2_pll_clk_init,
-	.enable			= tegra2_pll_clk_enable,
-	.disable		= tegra2_pll_clk_disable,
-	.set_rate		= tegra2_pll_clk_set_rate,
-};
-
-static void tegra2_pllx_clk_init(struct clk *c)
-{
-	tegra2_pll_clk_init(c);
-
-	if (tegra_sku_id == 7)
-		c->max_rate = 750000000;
-}
-
-static struct clk_ops tegra_pllx_ops = {
-	.init     = tegra2_pllx_clk_init,
-	.enable   = tegra2_pll_clk_enable,
-	.disable  = tegra2_pll_clk_disable,
-	.set_rate = tegra2_pll_clk_set_rate,
-};
-
-static int tegra2_plle_clk_enable(struct clk *c)
-{
-	u32 val;
-
-	pr_debug("%s on clock %s\n", __func__, c->name);
-
-	mdelay(1);
-
-	val = clk_readl(c->reg + PLL_BASE);
-	if (!(val & PLLE_MISC_READY))
-		return -EBUSY;
-
-	val = clk_readl(c->reg + PLL_BASE);
-	val |= PLL_BASE_ENABLE | PLL_BASE_BYPASS;
-	clk_writel(val, c->reg + PLL_BASE);
-
-	return 0;
-}
-
-static struct clk_ops tegra_plle_ops = {
-	.init       = tegra2_pll_clk_init,
-	.enable     = tegra2_plle_clk_enable,
-	.set_rate   = tegra2_pll_clk_set_rate,
-};
-
-/* Clock divider ops */
-static void tegra2_pll_div_clk_init(struct clk *c)
-{
-	u32 val = clk_readl(c->reg);
-	u32 divu71;
-	val >>= c->reg_shift;
-	c->state = (val & PLL_OUT_CLKEN) ? ON : OFF;
-	if (!(val & PLL_OUT_RESET_DISABLE))
-		c->state = OFF;
-
-	if (c->flags & DIV_U71) {
-		divu71 = (val & PLL_OUT_RATIO_MASK) >> PLL_OUT_RATIO_SHIFT;
-		c->div = (divu71 + 2);
-		c->mul = 2;
-	} else if (c->flags & DIV_2) {
-		c->div = 2;
-		c->mul = 1;
-	} else {
-		c->div = 1;
-		c->mul = 1;
-	}
-}
-
-static int tegra2_pll_div_clk_enable(struct clk *c)
-{
-	u32 val;
-	u32 new_val;
-	unsigned long flags;
-
-	pr_debug("%s: %s\n", __func__, c->name);
-	if (c->flags & DIV_U71) {
-		spin_lock_irqsave(&clock_register_lock, flags);
-		val = clk_readl(c->reg);
-		new_val = val >> c->reg_shift;
-		new_val &= 0xFFFF;
-
-		new_val |= PLL_OUT_CLKEN | PLL_OUT_RESET_DISABLE;
-
-		val &= ~(0xFFFF << c->reg_shift);
-		val |= new_val << c->reg_shift;
-		clk_writel(val, c->reg);
-		spin_unlock_irqrestore(&clock_register_lock, flags);
-		return 0;
-	} else if (c->flags & DIV_2) {
-		BUG_ON(!(c->flags & PLLD));
-		spin_lock_irqsave(&clock_register_lock, flags);
-		val = clk_readl(c->reg);
-		val &= ~PLLD_MISC_DIV_RST;
-		clk_writel(val, c->reg);
-		spin_unlock_irqrestore(&clock_register_lock, flags);
-		return 0;
-	}
-	return -EINVAL;
-}
-
-static void tegra2_pll_div_clk_disable(struct clk *c)
-{
-	u32 val;
-	u32 new_val;
-	unsigned long flags;
-
-	pr_debug("%s: %s\n", __func__, c->name);
-	if (c->flags & DIV_U71) {
-		spin_lock_irqsave(&clock_register_lock, flags);
-		val = clk_readl(c->reg);
-		new_val = val >> c->reg_shift;
-		new_val &= 0xFFFF;
-
-		new_val &= ~(PLL_OUT_CLKEN | PLL_OUT_RESET_DISABLE);
-
-		val &= ~(0xFFFF << c->reg_shift);
-		val |= new_val << c->reg_shift;
-		clk_writel(val, c->reg);
-		spin_unlock_irqrestore(&clock_register_lock, flags);
-	} else if (c->flags & DIV_2) {
-		BUG_ON(!(c->flags & PLLD));
-		spin_lock_irqsave(&clock_register_lock, flags);
-		val = clk_readl(c->reg);
-		val |= PLLD_MISC_DIV_RST;
-		clk_writel(val, c->reg);
-		spin_unlock_irqrestore(&clock_register_lock, flags);
-	}
-}
-
-static int tegra2_pll_div_clk_set_rate(struct clk *c, unsigned long rate)
-{
-	u32 val;
-	u32 new_val;
-	int divider_u71;
-	unsigned long parent_rate = clk_get_rate(c->parent);
-	unsigned long flags;
-
-	pr_debug("%s: %s %lu\n", __func__, c->name, rate);
-	if (c->flags & DIV_U71) {
-		divider_u71 = clk_div71_get_divider(parent_rate, rate);
-		if (divider_u71 >= 0) {
-			spin_lock_irqsave(&clock_register_lock, flags);
-			val = clk_readl(c->reg);
-			new_val = val >> c->reg_shift;
-			new_val &= 0xFFFF;
-			if (c->flags & DIV_U71_FIXED)
-				new_val |= PLL_OUT_OVERRIDE;
-			new_val &= ~PLL_OUT_RATIO_MASK;
-			new_val |= divider_u71 << PLL_OUT_RATIO_SHIFT;
-
-			val &= ~(0xFFFF << c->reg_shift);
-			val |= new_val << c->reg_shift;
-			clk_writel(val, c->reg);
-			c->div = divider_u71 + 2;
-			c->mul = 2;
-			spin_unlock_irqrestore(&clock_register_lock, flags);
-			return 0;
-		}
-	} else if (c->flags & DIV_2) {
-		if (parent_rate == rate * 2)
-			return 0;
-	}
-	return -EINVAL;
-}
-
-static long tegra2_pll_div_clk_round_rate(struct clk *c, unsigned long rate)
-{
-	int divider;
-	unsigned long parent_rate = clk_get_rate(c->parent);
-	pr_debug("%s: %s %lu\n", __func__, c->name, rate);
-
-	if (c->flags & DIV_U71) {
-		divider = clk_div71_get_divider(parent_rate, rate);
-		if (divider < 0)
-			return divider;
-		return DIV_ROUND_UP(parent_rate * 2, divider + 2);
-	} else if (c->flags & DIV_2) {
-		return DIV_ROUND_UP(parent_rate, 2);
-	}
-	return -EINVAL;
-}
-
-static struct clk_ops tegra_pll_div_ops = {
-	.init			= tegra2_pll_div_clk_init,
-	.enable			= tegra2_pll_div_clk_enable,
-	.disable		= tegra2_pll_div_clk_disable,
-	.set_rate		= tegra2_pll_div_clk_set_rate,
-	.round_rate		= tegra2_pll_div_clk_round_rate,
-};
-
-/* Periph clk ops */
-
-static void tegra2_periph_clk_init(struct clk *c)
-{
-	u32 val = clk_readl(c->reg);
-	const struct clk_mux_sel *mux = NULL;
-	const struct clk_mux_sel *sel;
-	u32 shift;
-	u32 mask;
-
-	if (c->flags & MUX_PWM) {
-		shift = PERIPH_CLK_SOURCE_PWM_SHIFT;
-		mask = PERIPH_CLK_SOURCE_PWM_MASK;
-	} else {
-		shift = PERIPH_CLK_SOURCE_SHIFT;
-		mask = PERIPH_CLK_SOURCE_MASK;
-	}
-
-	if (c->flags & MUX) {
-		for (sel = c->inputs; sel->input != NULL; sel++) {
-			if ((val & mask) >> shift == sel->value)
-				mux = sel;
-		}
-		BUG_ON(!mux);
-
-		c->parent = mux->input;
-	} else {
-		c->parent = c->inputs[0].input;
-	}
-
-	if (c->flags & DIV_U71) {
-		u32 divu71 = val & PERIPH_CLK_SOURCE_DIVU71_MASK;
-		c->div = divu71 + 2;
-		c->mul = 2;
-	} else if (c->flags & DIV_U16) {
-		u32 divu16 = val & PERIPH_CLK_SOURCE_DIVU16_MASK;
-		c->div = divu16 + 1;
-		c->mul = 1;
-	} else {
-		c->div = 1;
-		c->mul = 1;
-	}
-
-	c->state = ON;
-
-	if (!c->u.periph.clk_num)
-		return;
-
-	if (!(clk_readl(CLK_OUT_ENB + PERIPH_CLK_TO_ENB_REG(c)) &
-			PERIPH_CLK_TO_ENB_BIT(c)))
-		c->state = OFF;
-
-	if (!(c->flags & PERIPH_NO_RESET))
-		if (clk_readl(RST_DEVICES + PERIPH_CLK_TO_ENB_REG(c)) &
-				PERIPH_CLK_TO_ENB_BIT(c))
-			c->state = OFF;
-}
-
-static int tegra2_periph_clk_enable(struct clk *c)
-{
-	u32 val;
-	unsigned long flags;
-	int refcount;
-	pr_debug("%s on clock %s\n", __func__, c->name);
-
-	if (!c->u.periph.clk_num)
-		return 0;
-
-	spin_lock_irqsave(&clock_register_lock, flags);
-
-	refcount = tegra_periph_clk_enable_refcount[c->u.periph.clk_num]++;
-
-	if (refcount > 1)
-		goto out;
-
-	clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
-		CLK_OUT_ENB_SET + PERIPH_CLK_TO_ENB_SET_REG(c));
-	if (!(c->flags & PERIPH_NO_RESET) && !(c->flags & PERIPH_MANUAL_RESET))
-		clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
-			RST_DEVICES_CLR + PERIPH_CLK_TO_ENB_SET_REG(c));
-	if (c->flags & PERIPH_EMC_ENB) {
-		/* The EMC peripheral clock has 2 extra enable bits */
-		/* FIXME: Do they need to be disabled? */
-		val = clk_readl(c->reg);
-		val |= 0x3 << 24;
-		clk_writel(val, c->reg);
-	}
-
-out:
-	spin_unlock_irqrestore(&clock_register_lock, flags);
-
-	return 0;
-}
-
-static void tegra2_periph_clk_disable(struct clk *c)
-{
-	unsigned long flags;
-
-	pr_debug("%s on clock %s\n", __func__, c->name);
-
-	if (!c->u.periph.clk_num)
-		return;
-
-	spin_lock_irqsave(&clock_register_lock, flags);
-
-	if (c->refcnt)
-		tegra_periph_clk_enable_refcount[c->u.periph.clk_num]--;
-
-	if (tegra_periph_clk_enable_refcount[c->u.periph.clk_num] == 0)
-		clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
-			CLK_OUT_ENB_CLR + PERIPH_CLK_TO_ENB_SET_REG(c));
-
-	spin_unlock_irqrestore(&clock_register_lock, flags);
-}
-
-static void tegra2_periph_clk_reset(struct clk *c, bool assert)
-{
-	unsigned long base = assert ? RST_DEVICES_SET : RST_DEVICES_CLR;
-
-	pr_debug("%s %s on clock %s\n", __func__,
-		 assert ? "assert" : "deassert", c->name);
-
-	BUG_ON(!c->u.periph.clk_num);
-
-	if (!(c->flags & PERIPH_NO_RESET))
-		clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
-			   base + PERIPH_CLK_TO_ENB_SET_REG(c));
-}
-
-static int tegra2_periph_clk_set_parent(struct clk *c, struct clk *p)
-{
-	u32 val;
-	const struct clk_mux_sel *sel;
-	u32 mask, shift;
-
-	pr_debug("%s: %s %s\n", __func__, c->name, p->name);
-
-	if (c->flags & MUX_PWM) {
-		shift = PERIPH_CLK_SOURCE_PWM_SHIFT;
-		mask = PERIPH_CLK_SOURCE_PWM_MASK;
-	} else {
-		shift = PERIPH_CLK_SOURCE_SHIFT;
-		mask = PERIPH_CLK_SOURCE_MASK;
-	}
-
-	for (sel = c->inputs; sel->input != NULL; sel++) {
-		if (sel->input == p) {
-			val = clk_readl(c->reg);
-			val &= ~mask;
-			val |= (sel->value) << shift;
-
-			if (c->refcnt)
-				clk_enable(p);
-
-			clk_writel(val, c->reg);
-
-			if (c->refcnt && c->parent)
-				clk_disable(c->parent);
-
-			clk_reparent(c, p);
-			return 0;
-		}
-	}
-
-	return -EINVAL;
-}
-
-static int tegra2_periph_clk_set_rate(struct clk *c, unsigned long rate)
-{
-	u32 val;
-	int divider;
-	unsigned long parent_rate = clk_get_rate(c->parent);
-
-	if (c->flags & DIV_U71) {
-		divider = clk_div71_get_divider(parent_rate, rate);
-		if (divider >= 0) {
-			val = clk_readl(c->reg);
-			val &= ~PERIPH_CLK_SOURCE_DIVU71_MASK;
-			val |= divider;
-			clk_writel(val, c->reg);
-			c->div = divider + 2;
-			c->mul = 2;
-			return 0;
-		}
-	} else if (c->flags & DIV_U16) {
-		divider = clk_div16_get_divider(parent_rate, rate);
-		if (divider >= 0) {
-			val = clk_readl(c->reg);
-			val &= ~PERIPH_CLK_SOURCE_DIVU16_MASK;
-			val |= divider;
-			clk_writel(val, c->reg);
-			c->div = divider + 1;
-			c->mul = 1;
-			return 0;
-		}
-	} else if (parent_rate <= rate) {
-		c->div = 1;
-		c->mul = 1;
-		return 0;
-	}
-	return -EINVAL;
-}
-
-static long tegra2_periph_clk_round_rate(struct clk *c,
-	unsigned long rate)
-{
-	int divider;
-	unsigned long parent_rate = clk_get_rate(c->parent);
-	pr_debug("%s: %s %lu\n", __func__, c->name, rate);
-
-	if (c->flags & DIV_U71) {
-		divider = clk_div71_get_divider(parent_rate, rate);
-		if (divider < 0)
-			return divider;
-
-		return DIV_ROUND_UP(parent_rate * 2, divider + 2);
-	} else if (c->flags & DIV_U16) {
-		divider = clk_div16_get_divider(parent_rate, rate);
-		if (divider < 0)
-			return divider;
-		return DIV_ROUND_UP(parent_rate, divider + 1);
-	}
-	return -EINVAL;
-}
-
-static struct clk_ops tegra_periph_clk_ops = {
-	.init			= &tegra2_periph_clk_init,
-	.enable			= &tegra2_periph_clk_enable,
-	.disable		= &tegra2_periph_clk_disable,
-	.set_parent		= &tegra2_periph_clk_set_parent,
-	.set_rate		= &tegra2_periph_clk_set_rate,
-	.round_rate		= &tegra2_periph_clk_round_rate,
-	.reset			= &tegra2_periph_clk_reset,
-};
-
-/* The SDMMC controllers have extra bits in the clock source register that
- * adjust the delay between the clock and data to compenstate for delays
- * on the PCB. */
-void tegra2_sdmmc_tap_delay(struct clk *c, int delay)
-{
-	u32 reg;
-	unsigned long flags;
-
-	spin_lock_irqsave(&c->spinlock, flags);
-
-	delay = clamp(delay, 0, 15);
-	reg = clk_readl(c->reg);
-	reg &= ~SDMMC_CLK_INT_FB_DLY_MASK;
-	reg |= SDMMC_CLK_INT_FB_SEL;
-	reg |= delay << SDMMC_CLK_INT_FB_DLY_SHIFT;
-	clk_writel(reg, c->reg);
-
-	spin_unlock_irqrestore(&c->spinlock, flags);
-}
-
-/* External memory controller clock ops */
-static void tegra2_emc_clk_init(struct clk *c)
-{
-	tegra2_periph_clk_init(c);
-	c->max_rate = clk_get_rate_locked(c);
-}
-
-static long tegra2_emc_clk_round_rate(struct clk *c, unsigned long rate)
-{
-	long emc_rate;
-	long clk_rate;
-
-	/*
-	 * The slowest entry in the EMC clock table that is at least as
-	 * fast as rate.
-	 */
-	emc_rate = tegra_emc_round_rate(rate);
-	if (emc_rate < 0)
-		return c->max_rate;
-
-	/*
-	 * The fastest rate the PLL will generate that is at most the
-	 * requested rate.
-	 */
-	clk_rate = tegra2_periph_clk_round_rate(c, emc_rate);
-
-	/*
-	 * If this fails, and emc_rate > clk_rate, it's because the maximum
-	 * rate in the EMC tables is larger than the maximum rate of the EMC
-	 * clock. The EMC clock's max rate is the rate it was running when the
-	 * kernel booted. Such a mismatch is probably due to using the wrong
-	 * BCT, i.e. using a Tegra20 BCT with an EMC table written for Tegra25.
-	 */
-	WARN_ONCE(emc_rate != clk_rate,
-		"emc_rate %ld != clk_rate %ld",
-		emc_rate, clk_rate);
-
-	return emc_rate;
-}
-
-static int tegra2_emc_clk_set_rate(struct clk *c, unsigned long rate)
-{
-	int ret;
-	/*
-	 * The Tegra2 memory controller has an interlock with the clock
-	 * block that allows memory shadowed registers to be updated,
-	 * and then transfer them to the main registers at the same
-	 * time as the clock update without glitches.
-	 */
-	ret = tegra_emc_set_rate(rate);
-	if (ret < 0)
-		return ret;
-
-	ret = tegra2_periph_clk_set_rate(c, rate);
-	udelay(1);
-
-	return ret;
-}
-
-static struct clk_ops tegra_emc_clk_ops = {
-	.init			= &tegra2_emc_clk_init,
-	.enable			= &tegra2_periph_clk_enable,
-	.disable		= &tegra2_periph_clk_disable,
-	.set_parent		= &tegra2_periph_clk_set_parent,
-	.set_rate		= &tegra2_emc_clk_set_rate,
-	.round_rate		= &tegra2_emc_clk_round_rate,
-	.reset			= &tegra2_periph_clk_reset,
-};
-
-/* Clock doubler ops */
-static void tegra2_clk_double_init(struct clk *c)
-{
-	c->mul = 2;
-	c->div = 1;
-	c->state = ON;
-
-	if (!c->u.periph.clk_num)
-		return;
-
-	if (!(clk_readl(CLK_OUT_ENB + PERIPH_CLK_TO_ENB_REG(c)) &
-			PERIPH_CLK_TO_ENB_BIT(c)))
-		c->state = OFF;
-};
-
-static int tegra2_clk_double_set_rate(struct clk *c, unsigned long rate)
-{
-	if (rate != 2 * clk_get_rate(c->parent))
-		return -EINVAL;
-	c->mul = 2;
-	c->div = 1;
-	return 0;
-}
-
-static struct clk_ops tegra_clk_double_ops = {
-	.init			= &tegra2_clk_double_init,
-	.enable			= &tegra2_periph_clk_enable,
-	.disable		= &tegra2_periph_clk_disable,
-	.set_rate		= &tegra2_clk_double_set_rate,
-};
-
-/* Audio sync clock ops */
-static void tegra2_audio_sync_clk_init(struct clk *c)
-{
-	int source;
-	const struct clk_mux_sel *sel;
-	u32 val = clk_readl(c->reg);
-	c->state = (val & (1<<4)) ? OFF : ON;
-	source = val & 0xf;
-	for (sel = c->inputs; sel->input != NULL; sel++)
-		if (sel->value == source)
-			break;
-	BUG_ON(sel->input == NULL);
-	c->parent = sel->input;
-}
-
-static int tegra2_audio_sync_clk_enable(struct clk *c)
-{
-	clk_writel(0, c->reg);
-	return 0;
-}
-
-static void tegra2_audio_sync_clk_disable(struct clk *c)
-{
-	clk_writel(1, c->reg);
-}
-
-static int tegra2_audio_sync_clk_set_parent(struct clk *c, struct clk *p)
-{
-	u32 val;
-	const struct clk_mux_sel *sel;
-	for (sel = c->inputs; sel->input != NULL; sel++) {
-		if (sel->input == p) {
-			val = clk_readl(c->reg);
-			val &= ~0xf;
-			val |= sel->value;
-
-			if (c->refcnt)
-				clk_enable(p);
-
-			clk_writel(val, c->reg);
-
-			if (c->refcnt && c->parent)
-				clk_disable(c->parent);
-
-			clk_reparent(c, p);
-			return 0;
-		}
-	}
-
-	return -EINVAL;
-}
-
-static struct clk_ops tegra_audio_sync_clk_ops = {
-	.init       = tegra2_audio_sync_clk_init,
-	.enable     = tegra2_audio_sync_clk_enable,
-	.disable    = tegra2_audio_sync_clk_disable,
-	.set_parent = tegra2_audio_sync_clk_set_parent,
-};
-
-/* cdev1 and cdev2 (dap_mclk1 and dap_mclk2) ops */
-
-static void tegra2_cdev_clk_init(struct clk *c)
-{
-	/* We could un-tristate the cdev1 or cdev2 pingroup here; this is
-	 * currently done in the pinmux code. */
-	c->state = ON;
-
-	BUG_ON(!c->u.periph.clk_num);
-
-	if (!(clk_readl(CLK_OUT_ENB + PERIPH_CLK_TO_ENB_REG(c)) &
-			PERIPH_CLK_TO_ENB_BIT(c)))
-		c->state = OFF;
-}
-
-static int tegra2_cdev_clk_enable(struct clk *c)
-{
-	BUG_ON(!c->u.periph.clk_num);
-
-	clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
-		CLK_OUT_ENB_SET + PERIPH_CLK_TO_ENB_SET_REG(c));
-	return 0;
-}
-
-static void tegra2_cdev_clk_disable(struct clk *c)
-{
-	BUG_ON(!c->u.periph.clk_num);
-
-	clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
-		CLK_OUT_ENB_CLR + PERIPH_CLK_TO_ENB_SET_REG(c));
-}
-
-static struct clk_ops tegra_cdev_clk_ops = {
-	.init			= &tegra2_cdev_clk_init,
-	.enable			= &tegra2_cdev_clk_enable,
-	.disable		= &tegra2_cdev_clk_disable,
-};
-
-/* shared bus ops */
-/*
- * Some clocks may have multiple downstream users that need to request a
- * higher clock rate.  Shared bus clocks provide a unique shared_bus_user
- * clock to each user.  The frequency of the bus is set to the highest
- * enabled shared_bus_user clock, with a minimum value set by the
- * shared bus.
- */
-static int tegra_clk_shared_bus_update(struct clk *bus)
-{
-	struct clk *c;
-	unsigned long rate = bus->min_rate;
-
-	list_for_each_entry(c, &bus->shared_bus_list, u.shared_bus_user.node)
-		if (c->u.shared_bus_user.enabled)
-			rate = max(c->u.shared_bus_user.rate, rate);
-
-	if (rate == clk_get_rate_locked(bus))
-		return 0;
-
-	return clk_set_rate_locked(bus, rate);
-};
-
-static void tegra_clk_shared_bus_init(struct clk *c)
-{
-	unsigned long flags;
-
-	c->max_rate = c->parent->max_rate;
-	c->u.shared_bus_user.rate = c->parent->max_rate;
-	c->state = OFF;
-	c->set = true;
-
-	spin_lock_irqsave(&c->parent->spinlock, flags);
-
-	list_add_tail(&c->u.shared_bus_user.node,
-		&c->parent->shared_bus_list);
-
-	spin_unlock_irqrestore(&c->parent->spinlock, flags);
-}
-
-static int tegra_clk_shared_bus_set_rate(struct clk *c, unsigned long rate)
-{
-	unsigned long flags;
-	int ret;
-	long new_rate = rate;
-
-	new_rate = clk_round_rate(c->parent, new_rate);
-	if (new_rate < 0)
-		return new_rate;
-
-	spin_lock_irqsave(&c->parent->spinlock, flags);
-
-	c->u.shared_bus_user.rate = new_rate;
-	ret = tegra_clk_shared_bus_update(c->parent);
-
-	spin_unlock_irqrestore(&c->parent->spinlock, flags);
-
-	return ret;
-}
-
-static long tegra_clk_shared_bus_round_rate(struct clk *c, unsigned long rate)
-{
-	return clk_round_rate(c->parent, rate);
-}
-
-static int tegra_clk_shared_bus_enable(struct clk *c)
-{
-	unsigned long flags;
-	int ret;
-
-	spin_lock_irqsave(&c->parent->spinlock, flags);
-
-	c->u.shared_bus_user.enabled = true;
-	ret = tegra_clk_shared_bus_update(c->parent);
-
-	spin_unlock_irqrestore(&c->parent->spinlock, flags);
-
-	return ret;
-}
-
-static void tegra_clk_shared_bus_disable(struct clk *c)
-{
-	unsigned long flags;
-	int ret;
-
-	spin_lock_irqsave(&c->parent->spinlock, flags);
-
-	c->u.shared_bus_user.enabled = false;
-	ret = tegra_clk_shared_bus_update(c->parent);
-	WARN_ON_ONCE(ret);
-
-	spin_unlock_irqrestore(&c->parent->spinlock, flags);
-}
-
-static struct clk_ops tegra_clk_shared_bus_ops = {
-	.init = tegra_clk_shared_bus_init,
-	.enable = tegra_clk_shared_bus_enable,
-	.disable = tegra_clk_shared_bus_disable,
-	.set_rate = tegra_clk_shared_bus_set_rate,
-	.round_rate = tegra_clk_shared_bus_round_rate,
-};
-
-
-/* Clock definitions */
-static struct clk tegra_clk_32k = {
-	.name = "clk_32k",
-	.rate = 32768,
-	.ops  = NULL,
-	.max_rate = 32768,
-};
-
-static struct clk_pll_freq_table tegra_pll_s_freq_table[] = {
-	{32768, 12000000, 366, 1, 1, 0},
-	{32768, 13000000, 397, 1, 1, 0},
-	{32768, 19200000, 586, 1, 1, 0},
-	{32768, 26000000, 793, 1, 1, 0},
-	{0, 0, 0, 0, 0, 0},
-};
-
-static struct clk tegra_pll_s = {
-	.name      = "pll_s",
-	.flags     = PLL_ALT_MISC_REG,
-	.ops       = &tegra_pll_ops,
-	.parent    = &tegra_clk_32k,
-	.max_rate  = 26000000,
-	.reg       = 0xf0,
-	.u.pll = {
-		.input_min = 32768,
-		.input_max = 32768,
-		.cf_min    = 0, /* FIXME */
-		.cf_max    = 0, /* FIXME */
-		.vco_min   = 12000000,
-		.vco_max   = 26000000,
-		.freq_table = tegra_pll_s_freq_table,
-		.lock_delay = 300,
-	},
-};
-
-static struct clk_mux_sel tegra_clk_m_sel[] = {
-	{ .input = &tegra_clk_32k, .value = 0},
-	{ .input = &tegra_pll_s,  .value = 1},
-	{ NULL , 0},
-};
-
-static struct clk tegra_clk_m = {
-	.name      = "clk_m",
-	.flags     = ENABLE_ON_INIT,
-	.ops       = &tegra_clk_m_ops,
-	.inputs    = tegra_clk_m_sel,
-	.reg       = 0x1fc,
-	.reg_shift = 28,
-	.max_rate  = 26000000,
-};
-
-static struct clk_pll_freq_table tegra_pll_c_freq_table[] = {
-	{ 12000000, 600000000, 600, 12, 1, 8 },
-	{ 13000000, 600000000, 600, 13, 1, 8 },
-	{ 19200000, 600000000, 500, 16, 1, 6 },
-	{ 26000000, 600000000, 600, 26, 1, 8 },
-	{ 0, 0, 0, 0, 0, 0 },
-};
-
-static struct clk tegra_pll_c = {
-	.name      = "pll_c",
-	.flags	   = PLL_HAS_CPCON,
-	.ops       = &tegra_pll_ops,
-	.reg       = 0x80,
-	.parent    = &tegra_clk_m,
-	.max_rate  = 600000000,
-	.u.pll = {
-		.input_min = 2000000,
-		.input_max = 31000000,
-		.cf_min    = 1000000,
-		.cf_max    = 6000000,
-		.vco_min   = 20000000,
-		.vco_max   = 1400000000,
-		.freq_table = tegra_pll_c_freq_table,
-		.lock_delay = 300,
-	},
-};
-
-static struct clk tegra_pll_c_out1 = {
-	.name      = "pll_c_out1",
-	.ops       = &tegra_pll_div_ops,
-	.flags     = DIV_U71,
-	.parent    = &tegra_pll_c,
-	.reg       = 0x84,
-	.reg_shift = 0,
-	.max_rate  = 600000000,
-};
-
-static struct clk_pll_freq_table tegra_pll_m_freq_table[] = {
-	{ 12000000, 666000000, 666, 12, 1, 8},
-	{ 13000000, 666000000, 666, 13, 1, 8},
-	{ 19200000, 666000000, 555, 16, 1, 8},
-	{ 26000000, 666000000, 666, 26, 1, 8},
-	{ 12000000, 600000000, 600, 12, 1, 8},
-	{ 13000000, 600000000, 600, 13, 1, 8},
-	{ 19200000, 600000000, 375, 12, 1, 6},
-	{ 26000000, 600000000, 600, 26, 1, 8},
-	{ 0, 0, 0, 0, 0, 0 },
-};
-
-static struct clk tegra_pll_m = {
-	.name      = "pll_m",
-	.flags     = PLL_HAS_CPCON,
-	.ops       = &tegra_pll_ops,
-	.reg       = 0x90,
-	.parent    = &tegra_clk_m,
-	.max_rate  = 800000000,
-	.u.pll = {
-		.input_min = 2000000,
-		.input_max = 31000000,
-		.cf_min    = 1000000,
-		.cf_max    = 6000000,
-		.vco_min   = 20000000,
-		.vco_max   = 1200000000,
-		.freq_table = tegra_pll_m_freq_table,
-		.lock_delay = 300,
-	},
-};
-
-static struct clk tegra_pll_m_out1 = {
-	.name      = "pll_m_out1",
-	.ops       = &tegra_pll_div_ops,
-	.flags     = DIV_U71,
-	.parent    = &tegra_pll_m,
-	.reg       = 0x94,
-	.reg_shift = 0,
-	.max_rate  = 600000000,
-};
-
-static struct clk_pll_freq_table tegra_pll_p_freq_table[] = {
-	{ 12000000, 216000000, 432, 12, 2, 8},
-	{ 13000000, 216000000, 432, 13, 2, 8},
-	{ 19200000, 216000000, 90,   4, 2, 1},
-	{ 26000000, 216000000, 432, 26, 2, 8},
-	{ 12000000, 432000000, 432, 12, 1, 8},
-	{ 13000000, 432000000, 432, 13, 1, 8},
-	{ 19200000, 432000000, 90,   4, 1, 1},
-	{ 26000000, 432000000, 432, 26, 1, 8},
-	{ 0, 0, 0, 0, 0, 0 },
-};
-
-static struct clk tegra_pll_p = {
-	.name      = "pll_p",
-	.flags     = ENABLE_ON_INIT | PLL_FIXED | PLL_HAS_CPCON,
-	.ops       = &tegra_pll_ops,
-	.reg       = 0xa0,
-	.parent    = &tegra_clk_m,
-	.max_rate  = 432000000,
-	.u.pll = {
-		.input_min = 2000000,
-		.input_max = 31000000,
-		.cf_min    = 1000000,
-		.cf_max    = 6000000,
-		.vco_min   = 20000000,
-		.vco_max   = 1400000000,
-		.freq_table = tegra_pll_p_freq_table,
-		.lock_delay = 300,
-	},
-};
-
-static struct clk tegra_pll_p_out1 = {
-	.name      = "pll_p_out1",
-	.ops       = &tegra_pll_div_ops,
-	.flags     = ENABLE_ON_INIT | DIV_U71 | DIV_U71_FIXED,
-	.parent    = &tegra_pll_p,
-	.reg       = 0xa4,
-	.reg_shift = 0,
-	.max_rate  = 432000000,
-};
-
-static struct clk tegra_pll_p_out2 = {
-	.name      = "pll_p_out2",
-	.ops       = &tegra_pll_div_ops,
-	.flags     = ENABLE_ON_INIT | DIV_U71 | DIV_U71_FIXED,
-	.parent    = &tegra_pll_p,
-	.reg       = 0xa4,
-	.reg_shift = 16,
-	.max_rate  = 432000000,
-};
-
-static struct clk tegra_pll_p_out3 = {
-	.name      = "pll_p_out3",
-	.ops       = &tegra_pll_div_ops,
-	.flags     = ENABLE_ON_INIT | DIV_U71 | DIV_U71_FIXED,
-	.parent    = &tegra_pll_p,
-	.reg       = 0xa8,
-	.reg_shift = 0,
-	.max_rate  = 432000000,
-};
-
-static struct clk tegra_pll_p_out4 = {
-	.name      = "pll_p_out4",
-	.ops       = &tegra_pll_div_ops,
-	.flags     = ENABLE_ON_INIT | DIV_U71 | DIV_U71_FIXED,
-	.parent    = &tegra_pll_p,
-	.reg       = 0xa8,
-	.reg_shift = 16,
-	.max_rate  = 432000000,
-};
-
-static struct clk_pll_freq_table tegra_pll_a_freq_table[] = {
-	{ 28800000, 56448000, 49, 25, 1, 1},
-	{ 28800000, 73728000, 64, 25, 1, 1},
-	{ 28800000, 24000000,  5,  6, 1, 1},
-	{ 0, 0, 0, 0, 0, 0 },
-};
-
-static struct clk tegra_pll_a = {
-	.name      = "pll_a",
-	.flags     = PLL_HAS_CPCON,
-	.ops       = &tegra_pll_ops,
-	.reg       = 0xb0,
-	.parent    = &tegra_pll_p_out1,
-	.max_rate  = 73728000,
-	.u.pll = {
-		.input_min = 2000000,
-		.input_max = 31000000,
-		.cf_min    = 1000000,
-		.cf_max    = 6000000,
-		.vco_min   = 20000000,
-		.vco_max   = 1400000000,
-		.freq_table = tegra_pll_a_freq_table,
-		.lock_delay = 300,
-	},
-};
-
-static struct clk tegra_pll_a_out0 = {
-	.name      = "pll_a_out0",
-	.ops       = &tegra_pll_div_ops,
-	.flags     = DIV_U71,
-	.parent    = &tegra_pll_a,
-	.reg       = 0xb4,
-	.reg_shift = 0,
-	.max_rate  = 73728000,
-};
-
-static struct clk_pll_freq_table tegra_pll_d_freq_table[] = {
-	{ 12000000, 216000000, 216, 12, 1, 4},
-	{ 13000000, 216000000, 216, 13, 1, 4},
-	{ 19200000, 216000000, 135, 12, 1, 3},
-	{ 26000000, 216000000, 216, 26, 1, 4},
-
-	{ 12000000, 594000000, 594, 12, 1, 8},
-	{ 13000000, 594000000, 594, 13, 1, 8},
-	{ 19200000, 594000000, 495, 16, 1, 8},
-	{ 26000000, 594000000, 594, 26, 1, 8},
-
-	{ 12000000, 1000000000, 1000, 12, 1, 12},
-	{ 13000000, 1000000000, 1000, 13, 1, 12},
-	{ 19200000, 1000000000, 625,  12, 1, 8},
-	{ 26000000, 1000000000, 1000, 26, 1, 12},
-
-	{ 0, 0, 0, 0, 0, 0 },
-};
-
-static struct clk tegra_pll_d = {
-	.name      = "pll_d",
-	.flags     = PLL_HAS_CPCON | PLLD,
-	.ops       = &tegra_pll_ops,
-	.reg       = 0xd0,
-	.parent    = &tegra_clk_m,
-	.max_rate  = 1000000000,
-	.u.pll = {
-		.input_min = 2000000,
-		.input_max = 40000000,
-		.cf_min    = 1000000,
-		.cf_max    = 6000000,
-		.vco_min   = 40000000,
-		.vco_max   = 1000000000,
-		.freq_table = tegra_pll_d_freq_table,
-		.lock_delay = 1000,
-	},
-};
-
-static struct clk tegra_pll_d_out0 = {
-	.name      = "pll_d_out0",
-	.ops       = &tegra_pll_div_ops,
-	.flags     = DIV_2 | PLLD,
-	.parent    = &tegra_pll_d,
-	.max_rate  = 500000000,
-};
-
-static struct clk_pll_freq_table tegra_pll_u_freq_table[] = {
-	{ 12000000, 480000000, 960, 12, 2, 0},
-	{ 13000000, 480000000, 960, 13, 2, 0},
-	{ 19200000, 480000000, 200, 4,  2, 0},
-	{ 26000000, 480000000, 960, 26, 2, 0},
-	{ 0, 0, 0, 0, 0, 0 },
-};
-
-static struct clk tegra_pll_u = {
-	.name      = "pll_u",
-	.flags     = PLLU,
-	.ops       = &tegra_pll_ops,
-	.reg       = 0xc0,
-	.parent    = &tegra_clk_m,
-	.max_rate  = 480000000,
-	.u.pll = {
-		.input_min = 2000000,
-		.input_max = 40000000,
-		.cf_min    = 1000000,
-		.cf_max    = 6000000,
-		.vco_min   = 480000000,
-		.vco_max   = 960000000,
-		.freq_table = tegra_pll_u_freq_table,
-		.lock_delay = 1000,
-	},
-};
-
-static struct clk_pll_freq_table tegra_pll_x_freq_table[] = {
-	/* 1 GHz */
-	{ 12000000, 1000000000, 1000, 12, 1, 12},
-	{ 13000000, 1000000000, 1000, 13, 1, 12},
-	{ 19200000, 1000000000, 625,  12, 1, 8},
-	{ 26000000, 1000000000, 1000, 26, 1, 12},
-
-	/* 912 MHz */
-	{ 12000000, 912000000,  912,  12, 1, 12},
-	{ 13000000, 912000000,  912,  13, 1, 12},
-	{ 19200000, 912000000,  760,  16, 1, 8},
-	{ 26000000, 912000000,  912,  26, 1, 12},
-
-	/* 816 MHz */
-	{ 12000000, 816000000,  816,  12, 1, 12},
-	{ 13000000, 816000000,  816,  13, 1, 12},
-	{ 19200000, 816000000,  680,  16, 1, 8},
-	{ 26000000, 816000000,  816,  26, 1, 12},
-
-	/* 760 MHz */
-	{ 12000000, 760000000,  760,  12, 1, 12},
-	{ 13000000, 760000000,  760,  13, 1, 12},
-	{ 19200000, 760000000,  950,  24, 1, 8},
-	{ 26000000, 760000000,  760,  26, 1, 12},
-
-	/* 750 MHz */
-	{ 12000000, 750000000,  750,  12, 1, 12},
-	{ 13000000, 750000000,  750,  13, 1, 12},
-	{ 19200000, 750000000,  625,  16, 1, 8},
-	{ 26000000, 750000000,  750,  26, 1, 12},
-
-	/* 608 MHz */
-	{ 12000000, 608000000,  608,  12, 1, 12},
-	{ 13000000, 608000000,  608,  13, 1, 12},
-	{ 19200000, 608000000,  380,  12, 1, 8},
-	{ 26000000, 608000000,  608,  26, 1, 12},
-
-	/* 456 MHz */
-	{ 12000000, 456000000,  456,  12, 1, 12},
-	{ 13000000, 456000000,  456,  13, 1, 12},
-	{ 19200000, 456000000,  380,  16, 1, 8},
-	{ 26000000, 456000000,  456,  26, 1, 12},
-
-	/* 312 MHz */
-	{ 12000000, 312000000,  312,  12, 1, 12},
-	{ 13000000, 312000000,  312,  13, 1, 12},
-	{ 19200000, 312000000,  260,  16, 1, 8},
-	{ 26000000, 312000000,  312,  26, 1, 12},
-
-	{ 0, 0, 0, 0, 0, 0 },
-};
-
-static struct clk tegra_pll_x = {
-	.name      = "pll_x",
-	.flags     = PLL_HAS_CPCON | PLL_ALT_MISC_REG,
-	.ops       = &tegra_pllx_ops,
-	.reg       = 0xe0,
-	.parent    = &tegra_clk_m,
-	.max_rate  = 1000000000,
-	.u.pll = {
-		.input_min = 2000000,
-		.input_max = 31000000,
-		.cf_min    = 1000000,
-		.cf_max    = 6000000,
-		.vco_min   = 20000000,
-		.vco_max   = 1200000000,
-		.freq_table = tegra_pll_x_freq_table,
-		.lock_delay = 300,
-	},
-};
-
-static struct clk_pll_freq_table tegra_pll_e_freq_table[] = {
-	{ 12000000, 100000000,  200,  24, 1, 0 },
-	{ 0, 0, 0, 0, 0, 0 },
-};
-
-static struct clk tegra_pll_e = {
-	.name      = "pll_e",
-	.flags	   = PLL_ALT_MISC_REG,
-	.ops       = &tegra_plle_ops,
-	.parent    = &tegra_clk_m,
-	.reg       = 0xe8,
-	.max_rate  = 100000000,
-	.u.pll = {
-		.input_min = 12000000,
-		.input_max = 12000000,
-		.freq_table = tegra_pll_e_freq_table,
-	},
-};
-
-static struct clk tegra_clk_d = {
-	.name      = "clk_d",
-	.flags     = PERIPH_NO_RESET,
-	.ops       = &tegra_clk_double_ops,
-	.reg       = 0x34,
-	.reg_shift = 12,
-	.parent    = &tegra_clk_m,
-	.max_rate  = 52000000,
-	.u.periph  = {
-		.clk_num = 90,
-	},
-};
-
-/* dap_mclk1, belongs to the cdev1 pingroup. */
-static struct clk tegra_clk_cdev1 = {
-	.name      = "cdev1",
-	.ops       = &tegra_cdev_clk_ops,
-	.rate      = 26000000,
-	.max_rate  = 26000000,
-	.u.periph  = {
-		.clk_num = 94,
-	},
-};
-
-/* dap_mclk2, belongs to the cdev2 pingroup. */
-static struct clk tegra_clk_cdev2 = {
-	.name      = "cdev2",
-	.ops       = &tegra_cdev_clk_ops,
-	.rate      = 26000000,
-	.max_rate  = 26000000,
-	.u.periph  = {
-		.clk_num   = 93,
-	},
-};
-
-/* initialized before peripheral clocks */
-static struct clk_mux_sel mux_audio_sync_clk[8+1];
-static const struct audio_sources {
-	const char *name;
-	int value;
-} mux_audio_sync_clk_sources[] = {
-	{ .name = "spdif_in", .value = 0 },
-	{ .name = "i2s1", .value = 1 },
-	{ .name = "i2s2", .value = 2 },
-	{ .name = "pll_a_out0", .value = 4 },
-#if 0 /* FIXME: not implemented */
-	{ .name = "ac97", .value = 3 },
-	{ .name = "ext_audio_clk2", .value = 5 },
-	{ .name = "ext_audio_clk1", .value = 6 },
-	{ .name = "ext_vimclk", .value = 7 },
-#endif
-	{ NULL, 0 }
-};
-
-static struct clk tegra_clk_audio = {
-	.name      = "audio",
-	.inputs    = mux_audio_sync_clk,
-	.reg       = 0x38,
-	.max_rate  = 73728000,
-	.ops       = &tegra_audio_sync_clk_ops
-};
-
-static struct clk tegra_clk_audio_2x = {
-	.name      = "audio_2x",
-	.flags     = PERIPH_NO_RESET,
-	.max_rate  = 48000000,
-	.ops       = &tegra_clk_double_ops,
-	.reg       = 0x34,
-	.reg_shift = 8,
-	.parent    = &tegra_clk_audio,
-	.u.periph = {
-		.clk_num = 89,
-	},
-};
-
-static struct clk_lookup tegra_audio_clk_lookups[] = {
-	{ .con_id = "audio", .clk = &tegra_clk_audio },
-	{ .con_id = "audio_2x", .clk = &tegra_clk_audio_2x }
-};
-
-/* This is called after peripheral clocks are initialized, as the
- * audio_sync clock depends on some of the peripheral clocks.
- */
-
-static void init_audio_sync_clock_mux(void)
-{
-	int i;
-	struct clk_mux_sel *sel = mux_audio_sync_clk;
-	const struct audio_sources *src = mux_audio_sync_clk_sources;
-	struct clk_lookup *lookup;
-
-	for (i = 0; src->name; i++, sel++, src++) {
-		sel->input = tegra_get_clock_by_name(src->name);
-		if (!sel->input)
-			pr_err("%s: could not find clk %s\n", __func__,
-				src->name);
-		sel->value = src->value;
-	}
-
-	lookup = tegra_audio_clk_lookups;
-	for (i = 0; i < ARRAY_SIZE(tegra_audio_clk_lookups); i++, lookup++) {
-		clk_init(lookup->clk);
-		clkdev_add(lookup);
-	}
-}
-
-static struct clk_mux_sel mux_cclk[] = {
-	{ .input = &tegra_clk_m,	.value = 0},
-	{ .input = &tegra_pll_c,	.value = 1},
-	{ .input = &tegra_clk_32k,	.value = 2},
-	{ .input = &tegra_pll_m,	.value = 3},
-	{ .input = &tegra_pll_p,	.value = 4},
-	{ .input = &tegra_pll_p_out4,	.value = 5},
-	{ .input = &tegra_pll_p_out3,	.value = 6},
-	{ .input = &tegra_clk_d,	.value = 7},
-	{ .input = &tegra_pll_x,	.value = 8},
-	{ NULL, 0},
-};
-
-static struct clk_mux_sel mux_sclk[] = {
-	{ .input = &tegra_clk_m,	.value = 0},
-	{ .input = &tegra_pll_c_out1,	.value = 1},
-	{ .input = &tegra_pll_p_out4,	.value = 2},
-	{ .input = &tegra_pll_p_out3,	.value = 3},
-	{ .input = &tegra_pll_p_out2,	.value = 4},
-	{ .input = &tegra_clk_d,	.value = 5},
-	{ .input = &tegra_clk_32k,	.value = 6},
-	{ .input = &tegra_pll_m_out1,	.value = 7},
-	{ NULL, 0},
-};
-
-static struct clk tegra_clk_cclk = {
-	.name	= "cclk",
-	.inputs	= mux_cclk,
-	.reg	= 0x20,
-	.ops	= &tegra_super_ops,
-	.max_rate = 1000000000,
-};
-
-static struct clk tegra_clk_sclk = {
-	.name	= "sclk",
-	.inputs	= mux_sclk,
-	.reg	= 0x28,
-	.ops	= &tegra_super_ops,
-	.max_rate = 240000000,
-	.min_rate = 120000000,
-};
-
-static struct clk tegra_clk_virtual_cpu = {
-	.name      = "cpu",
-	.parent    = &tegra_clk_cclk,
-	.ops       = &tegra_cpu_ops,
-	.max_rate  = 1000000000,
-	.u.cpu = {
-		.main      = &tegra_pll_x,
-		.backup    = &tegra_pll_p,
-	},
-};
-
-static struct clk tegra_clk_cop = {
-	.name      = "cop",
-	.parent    = &tegra_clk_sclk,
-	.ops       = &tegra_cop_ops,
-	.max_rate  = 240000000,
-};
-
-static struct clk tegra_clk_hclk = {
-	.name		= "hclk",
-	.flags		= DIV_BUS,
-	.parent		= &tegra_clk_sclk,
-	.reg		= 0x30,
-	.reg_shift	= 4,
-	.ops		= &tegra_bus_ops,
-	.max_rate       = 240000000,
-};
-
-static struct clk tegra_clk_pclk = {
-	.name		= "pclk",
-	.flags		= DIV_BUS,
-	.parent		= &tegra_clk_hclk,
-	.reg		= 0x30,
-	.reg_shift	= 0,
-	.ops		= &tegra_bus_ops,
-	.max_rate       = 120000000,
-};
-
-static struct clk tegra_clk_blink = {
-	.name		= "blink",
-	.parent		= &tegra_clk_32k,
-	.reg		= 0x40,
-	.ops		= &tegra_blink_clk_ops,
-	.max_rate	= 32768,
-};
-
-static struct clk_mux_sel mux_pllm_pllc_pllp_plla[] = {
-	{ .input = &tegra_pll_m, .value = 0},
-	{ .input = &tegra_pll_c, .value = 1},
-	{ .input = &tegra_pll_p, .value = 2},
-	{ .input = &tegra_pll_a_out0, .value = 3},
-	{ NULL, 0},
-};
-
-static struct clk_mux_sel mux_pllm_pllc_pllp_clkm[] = {
-	{ .input = &tegra_pll_m, .value = 0},
-	{ .input = &tegra_pll_c, .value = 1},
-	{ .input = &tegra_pll_p, .value = 2},
-	{ .input = &tegra_clk_m, .value = 3},
-	{ NULL, 0},
-};
-
-static struct clk_mux_sel mux_pllp_pllc_pllm_clkm[] = {
-	{ .input = &tegra_pll_p, .value = 0},
-	{ .input = &tegra_pll_c, .value = 1},
-	{ .input = &tegra_pll_m, .value = 2},
-	{ .input = &tegra_clk_m, .value = 3},
-	{ NULL, 0},
-};
-
-static struct clk_mux_sel mux_pllaout0_audio2x_pllp_clkm[] = {
-	{.input = &tegra_pll_a_out0, .value = 0},
-	{.input = &tegra_clk_audio_2x, .value = 1},
-	{.input = &tegra_pll_p, .value = 2},
-	{.input = &tegra_clk_m, .value = 3},
-	{ NULL, 0},
-};
-
-static struct clk_mux_sel mux_pllp_plld_pllc_clkm[] = {
-	{.input = &tegra_pll_p, .value = 0},
-	{.input = &tegra_pll_d_out0, .value = 1},
-	{.input = &tegra_pll_c, .value = 2},
-	{.input = &tegra_clk_m, .value = 3},
-	{ NULL, 0},
-};
-
-static struct clk_mux_sel mux_pllp_pllc_audio_clkm_clk32[] = {
-	{.input = &tegra_pll_p,     .value = 0},
-	{.input = &tegra_pll_c,     .value = 1},
-	{.input = &tegra_clk_audio,     .value = 2},
-	{.input = &tegra_clk_m,     .value = 3},
-	{.input = &tegra_clk_32k,   .value = 4},
-	{ NULL, 0},
-};
-
-static struct clk_mux_sel mux_pllp_pllc_pllm[] = {
-	{.input = &tegra_pll_p,     .value = 0},
-	{.input = &tegra_pll_c,     .value = 1},
-	{.input = &tegra_pll_m,     .value = 2},
-	{ NULL, 0},
-};
-
-static struct clk_mux_sel mux_clk_m[] = {
-	{ .input = &tegra_clk_m, .value = 0},
-	{ NULL, 0},
-};
-
-static struct clk_mux_sel mux_pllp_out3[] = {
-	{ .input = &tegra_pll_p_out3, .value = 0},
-	{ NULL, 0},
-};
-
-static struct clk_mux_sel mux_plld[] = {
-	{ .input = &tegra_pll_d, .value = 0},
-	{ NULL, 0},
-};
-
-static struct clk_mux_sel mux_clk_32k[] = {
-	{ .input = &tegra_clk_32k, .value = 0},
-	{ NULL, 0},
-};
-
-static struct clk_mux_sel mux_pclk[] = {
-	{ .input = &tegra_clk_pclk, .value = 0},
-	{ NULL, 0},
-};
-
-static struct clk tegra_clk_emc = {
-	.name = "emc",
-	.ops = &tegra_emc_clk_ops,
-	.reg = 0x19c,
-	.max_rate = 800000000,
-	.inputs = mux_pllm_pllc_pllp_clkm,
-	.flags = MUX | DIV_U71 | PERIPH_EMC_ENB,
-	.u.periph = {
-		.clk_num = 57,
-	},
-};
-
-#define PERIPH_CLK(_name, _dev, _con, _clk_num, _reg, _max, _inputs, _flags) \
-	{						\
-		.name      = _name,			\
-		.lookup    = {				\
-			.dev_id    = _dev,		\
-			.con_id	   = _con,		\
-		},					\
-		.ops       = &tegra_periph_clk_ops,	\
-		.reg       = _reg,			\
-		.inputs    = _inputs,			\
-		.flags     = _flags,			\
-		.max_rate  = _max,			\
-		.u.periph = {				\
-			.clk_num   = _clk_num,		\
-		},					\
-	}
-
-#define SHARED_CLK(_name, _dev, _con, _parent)		\
-	{						\
-		.name      = _name,			\
-		.lookup    = {				\
-			.dev_id    = _dev,		\
-			.con_id    = _con,		\
-		},					\
-		.ops       = &tegra_clk_shared_bus_ops,	\
-		.parent = _parent,			\
-	}
-
-static struct clk tegra_list_clks[] = {
-	PERIPH_CLK("apbdma",	"tegra-apbdma",		NULL,	34,	0,	108000000, mux_pclk,			0),
-	PERIPH_CLK("rtc",	"rtc-tegra",		NULL,	4,	0,	32768,     mux_clk_32k,			PERIPH_NO_RESET),
-	PERIPH_CLK("timer",	"timer",		NULL,	5,	0,	26000000,  mux_clk_m,			0),
-	PERIPH_CLK("i2s1",	"tegra20-i2s.0",	NULL,	11,	0x100,	26000000,  mux_pllaout0_audio2x_pllp_clkm,	MUX | DIV_U71),
-	PERIPH_CLK("i2s2",	"tegra20-i2s.1",	NULL,	18,	0x104,	26000000,  mux_pllaout0_audio2x_pllp_clkm,	MUX | DIV_U71),
-	PERIPH_CLK("spdif_out",	"spdif_out",		NULL,	10,	0x108,	100000000, mux_pllaout0_audio2x_pllp_clkm,	MUX | DIV_U71),
-	PERIPH_CLK("spdif_in",	"spdif_in",		NULL,	10,	0x10c,	100000000, mux_pllp_pllc_pllm,		MUX | DIV_U71),
-	PERIPH_CLK("pwm",	"tegra-pwm",		NULL,	17,	0x110,	432000000, mux_pllp_pllc_audio_clkm_clk32,	MUX | DIV_U71 | MUX_PWM),
-	PERIPH_CLK("spi",	"spi",			NULL,	43,	0x114,	40000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
-	PERIPH_CLK("xio",	"xio",			NULL,	45,	0x120,	150000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
-	PERIPH_CLK("twc",	"twc",			NULL,	16,	0x12c,	150000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
-	PERIPH_CLK("sbc1",	"spi_tegra.0",		NULL,	41,	0x134,	160000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
-	PERIPH_CLK("sbc2",	"spi_tegra.1",		NULL,	44,	0x118,	160000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
-	PERIPH_CLK("sbc3",	"spi_tegra.2",		NULL,	46,	0x11c,	160000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
-	PERIPH_CLK("sbc4",	"spi_tegra.3",		NULL,	68,	0x1b4,	160000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
-	PERIPH_CLK("ide",	"ide",			NULL,	25,	0x144,	100000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71), /* requires min voltage */
-	PERIPH_CLK("ndflash",	"tegra_nand",		NULL,	13,	0x160,	164000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71), /* scales with voltage */
-	PERIPH_CLK("vfir",	"vfir",			NULL,	7,	0x168,	72000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
-	PERIPH_CLK("sdmmc1",	"sdhci-tegra.0",	NULL,	14,	0x150,	52000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71), /* scales with voltage */
-	PERIPH_CLK("sdmmc2",	"sdhci-tegra.1",	NULL,	9,	0x154,	52000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71), /* scales with voltage */
-	PERIPH_CLK("sdmmc3",	"sdhci-tegra.2",	NULL,	69,	0x1bc,	52000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71), /* scales with voltage */
-	PERIPH_CLK("sdmmc4",	"sdhci-tegra.3",	NULL,	15,	0x164,	52000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71), /* scales with voltage */
-	PERIPH_CLK("vcp",	"tegra-avp",		"vcp",	29,	0,	250000000, mux_clk_m,			0),
-	PERIPH_CLK("bsea",	"tegra-avp",		"bsea",	62,	0,	250000000, mux_clk_m,			0),
-	PERIPH_CLK("bsev",	"tegra-aes",		"bsev",	63,	0,	250000000, mux_clk_m,			0),
-	PERIPH_CLK("vde",	"tegra-avp",		"vde",	61,	0x1c8,	250000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71), /* scales with voltage and process_id */
-	PERIPH_CLK("csite",	"csite",		NULL,	73,	0x1d4,	144000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71), /* max rate ??? */
-	/* FIXME: what is la? */
-	PERIPH_CLK("la",	"la",			NULL,	76,	0x1f8,	26000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
-	PERIPH_CLK("owr",	"tegra_w1",		NULL,	71,	0x1cc,	26000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
-	PERIPH_CLK("nor",	"nor",			NULL,	42,	0x1d0,	92000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71), /* requires min voltage */
-	PERIPH_CLK("mipi",	"mipi",			NULL,	50,	0x174,	60000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71), /* scales with voltage */
-	PERIPH_CLK("i2c1",	"tegra-i2c.0",		NULL,	12,	0x124,	26000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U16),
-	PERIPH_CLK("i2c2",	"tegra-i2c.1",		NULL,	54,	0x198,	26000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U16),
-	PERIPH_CLK("i2c3",	"tegra-i2c.2",		NULL,	67,	0x1b8,	26000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U16),
-	PERIPH_CLK("dvc",	"tegra-i2c.3",		NULL,	47,	0x128,	26000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U16),
-	PERIPH_CLK("i2c1_i2c",	"tegra-i2c.0",		"i2c",	0,	0,	72000000,  mux_pllp_out3,			0),
-	PERIPH_CLK("i2c2_i2c",	"tegra-i2c.1",		"i2c",	0,	0,	72000000,  mux_pllp_out3,			0),
-	PERIPH_CLK("i2c3_i2c",	"tegra-i2c.2",		"i2c",	0,	0,	72000000,  mux_pllp_out3,			0),
-	PERIPH_CLK("dvc_i2c",	"tegra-i2c.3",		"i2c",	0,	0,	72000000,  mux_pllp_out3,			0),
-	PERIPH_CLK("uarta",	"tegra-uart.0",		NULL,	6,	0x178,	600000000, mux_pllp_pllc_pllm_clkm,	MUX),
-	PERIPH_CLK("uartb",	"tegra-uart.1",		NULL,	7,	0x17c,	600000000, mux_pllp_pllc_pllm_clkm,	MUX),
-	PERIPH_CLK("uartc",	"tegra-uart.2",		NULL,	55,	0x1a0,	600000000, mux_pllp_pllc_pllm_clkm,	MUX),
-	PERIPH_CLK("uartd",	"tegra-uart.3",		NULL,	65,	0x1c0,	600000000, mux_pllp_pllc_pllm_clkm,	MUX),
-	PERIPH_CLK("uarte",	"tegra-uart.4",		NULL,	66,	0x1c4,	600000000, mux_pllp_pllc_pllm_clkm,	MUX),
-	PERIPH_CLK("3d",	"3d",			NULL,	24,	0x158,	300000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71 | PERIPH_MANUAL_RESET), /* scales with voltage and process_id */
-	PERIPH_CLK("2d",	"2d",			NULL,	21,	0x15c,	300000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71), /* scales with voltage and process_id */
-	PERIPH_CLK("vi",	"tegra_camera",		"vi",	20,	0x148,	150000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71), /* scales with voltage and process_id */
-	PERIPH_CLK("vi_sensor",	"tegra_camera",		"vi_sensor",	20,	0x1a8,	150000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71 | PERIPH_NO_RESET), /* scales with voltage and process_id */
-	PERIPH_CLK("epp",	"epp",			NULL,	19,	0x16c,	300000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71), /* scales with voltage and process_id */
-	PERIPH_CLK("mpe",	"mpe",			NULL,	60,	0x170,	250000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71), /* scales with voltage and process_id */
-	PERIPH_CLK("host1x",	"host1x",		NULL,	28,	0x180,	166000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71), /* scales with voltage and process_id */
-	PERIPH_CLK("cve",	"cve",			NULL,	49,	0x140,	250000000, mux_pllp_plld_pllc_clkm,	MUX | DIV_U71), /* requires min voltage */
-	PERIPH_CLK("tvo",	"tvo",			NULL,	49,	0x188,	250000000, mux_pllp_plld_pllc_clkm,	MUX | DIV_U71), /* requires min voltage */
-	PERIPH_CLK("hdmi",	"hdmi",			NULL,	51,	0x18c,	600000000, mux_pllp_plld_pllc_clkm,	MUX | DIV_U71), /* requires min voltage */
-	PERIPH_CLK("tvdac",	"tvdac",		NULL,	53,	0x194,	250000000, mux_pllp_plld_pllc_clkm,	MUX | DIV_U71), /* requires min voltage */
-	PERIPH_CLK("disp1",	"tegradc.0",		NULL,	27,	0x138,	600000000, mux_pllp_plld_pllc_clkm,	MUX), /* scales with voltage and process_id */
-	PERIPH_CLK("disp2",	"tegradc.1",		NULL,	26,	0x13c,	600000000, mux_pllp_plld_pllc_clkm,	MUX), /* scales with voltage and process_id */
-	PERIPH_CLK("usbd",	"fsl-tegra-udc",	NULL,	22,	0,	480000000, mux_clk_m,			0), /* requires min voltage */
-	PERIPH_CLK("usb2",	"tegra-ehci.1",		NULL,	58,	0,	480000000, mux_clk_m,			0), /* requires min voltage */
-	PERIPH_CLK("usb3",	"tegra-ehci.2",		NULL,	59,	0,	480000000, mux_clk_m,			0), /* requires min voltage */
-	PERIPH_CLK("dsi",	"dsi",			NULL,	48,	0,	500000000, mux_plld,			0), /* scales with voltage */
-	PERIPH_CLK("csi",	"tegra_camera",		"csi",	52,	0,	72000000,  mux_pllp_out3,		0),
-	PERIPH_CLK("isp",	"tegra_camera",		"isp",	23,	0,	150000000, mux_clk_m,			0), /* same frequency as VI */
-	PERIPH_CLK("csus",	"tegra_camera",		"csus",	92,	0,	150000000, mux_clk_m,			PERIPH_NO_RESET),
-	PERIPH_CLK("pex",       NULL,			"pex",  70,     0,	26000000,  mux_clk_m,			PERIPH_MANUAL_RESET),
-	PERIPH_CLK("afi",       NULL,			"afi",  72,     0,	26000000,  mux_clk_m,			PERIPH_MANUAL_RESET),
-	PERIPH_CLK("pcie_xclk", NULL,		  "pcie_xclk",  74,     0,	26000000,  mux_clk_m,			PERIPH_MANUAL_RESET),
-
-	SHARED_CLK("avp.sclk",	"tegra-avp",		"sclk",	&tegra_clk_sclk),
-	SHARED_CLK("avp.emc",	"tegra-avp",		"emc",	&tegra_clk_emc),
-	SHARED_CLK("cpu.emc",	"cpu",			"emc",	&tegra_clk_emc),
-	SHARED_CLK("disp1.emc",	"tegradc.0",		"emc",	&tegra_clk_emc),
-	SHARED_CLK("disp2.emc",	"tegradc.1",		"emc",	&tegra_clk_emc),
-	SHARED_CLK("hdmi.emc",	"hdmi",			"emc",	&tegra_clk_emc),
-	SHARED_CLK("host.emc",	"tegra_grhost",		"emc",	&tegra_clk_emc),
-	SHARED_CLK("usbd.emc",	"fsl-tegra-udc",	"emc",	&tegra_clk_emc),
-	SHARED_CLK("usb1.emc",	"tegra-ehci.0",		"emc",	&tegra_clk_emc),
-	SHARED_CLK("usb2.emc",	"tegra-ehci.1",		"emc",	&tegra_clk_emc),
-	SHARED_CLK("usb3.emc",	"tegra-ehci.2",		"emc",	&tegra_clk_emc),
-};
-
-#define CLK_DUPLICATE(_name, _dev, _con)		\
-	{						\
-		.name	= _name,			\
-		.lookup	= {				\
-			.dev_id	= _dev,			\
-			.con_id		= _con,		\
-		},					\
-	}
-
-/* Some clocks may be used by different drivers depending on the board
- * configuration.  List those here to register them twice in the clock lookup
- * table under two names.
- */
-static struct clk_duplicate tegra_clk_duplicates[] = {
-	CLK_DUPLICATE("uarta",  "serial8250.0", NULL),
-	CLK_DUPLICATE("uartb",  "serial8250.1", NULL),
-	CLK_DUPLICATE("uartc",  "serial8250.2", NULL),
-	CLK_DUPLICATE("uartd",  "serial8250.3", NULL),
-	CLK_DUPLICATE("uarte",  "serial8250.4", NULL),
-	CLK_DUPLICATE("usbd", "utmip-pad", NULL),
-	CLK_DUPLICATE("usbd", "tegra-ehci.0", NULL),
-	CLK_DUPLICATE("usbd", "tegra-otg", NULL),
-	CLK_DUPLICATE("hdmi", "tegradc.0", "hdmi"),
-	CLK_DUPLICATE("hdmi", "tegradc.1", "hdmi"),
-	CLK_DUPLICATE("host1x", "tegra_grhost", "host1x"),
-	CLK_DUPLICATE("2d", "tegra_grhost", "gr2d"),
-	CLK_DUPLICATE("3d", "tegra_grhost", "gr3d"),
-	CLK_DUPLICATE("epp", "tegra_grhost", "epp"),
-	CLK_DUPLICATE("mpe", "tegra_grhost", "mpe"),
-	CLK_DUPLICATE("cop", "tegra-avp", "cop"),
-	CLK_DUPLICATE("vde", "tegra-aes", "vde"),
-};
-
-#define CLK(dev, con, ck)	\
-	{			\
-		.dev_id = dev,	\
-		.con_id = con,	\
-		.clk = ck,	\
-	}
-
-static struct clk *tegra_ptr_clks[] = {
-	&tegra_clk_32k,
-	&tegra_pll_s,
-	&tegra_clk_m,
-	&tegra_pll_m,
-	&tegra_pll_m_out1,
-	&tegra_pll_c,
-	&tegra_pll_c_out1,
-	&tegra_pll_p,
-	&tegra_pll_p_out1,
-	&tegra_pll_p_out2,
-	&tegra_pll_p_out3,
-	&tegra_pll_p_out4,
-	&tegra_pll_a,
-	&tegra_pll_a_out0,
-	&tegra_pll_d,
-	&tegra_pll_d_out0,
-	&tegra_pll_u,
-	&tegra_pll_x,
-	&tegra_pll_e,
-	&tegra_clk_cclk,
-	&tegra_clk_sclk,
-	&tegra_clk_hclk,
-	&tegra_clk_pclk,
-	&tegra_clk_d,
-	&tegra_clk_cdev1,
-	&tegra_clk_cdev2,
-	&tegra_clk_virtual_cpu,
-	&tegra_clk_blink,
-	&tegra_clk_cop,
-	&tegra_clk_emc,
-};
-
-static void tegra2_init_one_clock(struct clk *c)
-{
-	clk_init(c);
-	INIT_LIST_HEAD(&c->shared_bus_list);
-	if (!c->lookup.dev_id && !c->lookup.con_id)
-		c->lookup.con_id = c->name;
-	c->lookup.clk = c;
-	clkdev_add(&c->lookup);
-}
-
-void __init tegra2_init_clocks(void)
-{
-	int i;
-	struct clk *c;
-
-	for (i = 0; i < ARRAY_SIZE(tegra_ptr_clks); i++)
-		tegra2_init_one_clock(tegra_ptr_clks[i]);
-
-	for (i = 0; i < ARRAY_SIZE(tegra_list_clks); i++)
-		tegra2_init_one_clock(&tegra_list_clks[i]);
-
-	for (i = 0; i < ARRAY_SIZE(tegra_clk_duplicates); i++) {
-		c = tegra_get_clock_by_name(tegra_clk_duplicates[i].name);
-		if (!c) {
-			pr_err("%s: Unknown duplicate clock %s\n", __func__,
-				tegra_clk_duplicates[i].name);
-			continue;
-		}
-
-		tegra_clk_duplicates[i].lookup.clk = c;
-		clkdev_add(&tegra_clk_duplicates[i].lookup);
-	}
-
-	init_audio_sync_clock_mux();
-}
-
-#ifdef CONFIG_PM
-static u32 clk_rst_suspend[RST_DEVICES_NUM + CLK_OUT_ENB_NUM +
-			   PERIPH_CLK_SOURCE_NUM + 22];
-
-void tegra_clk_suspend(void)
-{
-	unsigned long off, i;
-	u32 *ctx = clk_rst_suspend;
-
-	*ctx++ = clk_readl(OSC_CTRL) & OSC_CTRL_MASK;
-	*ctx++ = clk_readl(tegra_pll_c.reg + PLL_BASE);
-	*ctx++ = clk_readl(tegra_pll_c.reg + PLL_MISC(&tegra_pll_c));
-	*ctx++ = clk_readl(tegra_pll_a.reg + PLL_BASE);
-	*ctx++ = clk_readl(tegra_pll_a.reg + PLL_MISC(&tegra_pll_a));
-	*ctx++ = clk_readl(tegra_pll_s.reg + PLL_BASE);
-	*ctx++ = clk_readl(tegra_pll_s.reg + PLL_MISC(&tegra_pll_s));
-	*ctx++ = clk_readl(tegra_pll_d.reg + PLL_BASE);
-	*ctx++ = clk_readl(tegra_pll_d.reg + PLL_MISC(&tegra_pll_d));
-	*ctx++ = clk_readl(tegra_pll_u.reg + PLL_BASE);
-	*ctx++ = clk_readl(tegra_pll_u.reg + PLL_MISC(&tegra_pll_u));
-
-	*ctx++ = clk_readl(tegra_pll_m_out1.reg);
-	*ctx++ = clk_readl(tegra_pll_a_out0.reg);
-	*ctx++ = clk_readl(tegra_pll_c_out1.reg);
-
-	*ctx++ = clk_readl(tegra_clk_cclk.reg);
-	*ctx++ = clk_readl(tegra_clk_cclk.reg + SUPER_CLK_DIVIDER);
-
-	*ctx++ = clk_readl(tegra_clk_sclk.reg);
-	*ctx++ = clk_readl(tegra_clk_sclk.reg + SUPER_CLK_DIVIDER);
-	*ctx++ = clk_readl(tegra_clk_pclk.reg);
-
-	*ctx++ = clk_readl(tegra_clk_audio.reg);
-
-	for (off = PERIPH_CLK_SOURCE_I2S1; off <= PERIPH_CLK_SOURCE_OSC;
-			off += 4) {
-		if (off == PERIPH_CLK_SOURCE_EMC)
-			continue;
-		*ctx++ = clk_readl(off);
-	}
-
-	off = RST_DEVICES;
-	for (i = 0; i < RST_DEVICES_NUM; i++, off += 4)
-		*ctx++ = clk_readl(off);
-
-	off = CLK_OUT_ENB;
-	for (i = 0; i < CLK_OUT_ENB_NUM; i++, off += 4)
-		*ctx++ = clk_readl(off);
-
-	*ctx++ = clk_readl(MISC_CLK_ENB);
-	*ctx++ = clk_readl(CLK_MASK_ARM);
-
-	BUG_ON(ctx - clk_rst_suspend != ARRAY_SIZE(clk_rst_suspend));
-}
-
-void tegra_clk_resume(void)
-{
-	unsigned long off, i;
-	const u32 *ctx = clk_rst_suspend;
-	u32 val;
-
-	val = clk_readl(OSC_CTRL) & ~OSC_CTRL_MASK;
-	val |= *ctx++;
-	clk_writel(val, OSC_CTRL);
-
-	clk_writel(*ctx++, tegra_pll_c.reg + PLL_BASE);
-	clk_writel(*ctx++, tegra_pll_c.reg + PLL_MISC(&tegra_pll_c));
-	clk_writel(*ctx++, tegra_pll_a.reg + PLL_BASE);
-	clk_writel(*ctx++, tegra_pll_a.reg + PLL_MISC(&tegra_pll_a));
-	clk_writel(*ctx++, tegra_pll_s.reg + PLL_BASE);
-	clk_writel(*ctx++, tegra_pll_s.reg + PLL_MISC(&tegra_pll_s));
-	clk_writel(*ctx++, tegra_pll_d.reg + PLL_BASE);
-	clk_writel(*ctx++, tegra_pll_d.reg + PLL_MISC(&tegra_pll_d));
-	clk_writel(*ctx++, tegra_pll_u.reg + PLL_BASE);
-	clk_writel(*ctx++, tegra_pll_u.reg + PLL_MISC(&tegra_pll_u));
-	udelay(1000);
-
-	clk_writel(*ctx++, tegra_pll_m_out1.reg);
-	clk_writel(*ctx++, tegra_pll_a_out0.reg);
-	clk_writel(*ctx++, tegra_pll_c_out1.reg);
-
-	clk_writel(*ctx++, tegra_clk_cclk.reg);
-	clk_writel(*ctx++, tegra_clk_cclk.reg + SUPER_CLK_DIVIDER);
-
-	clk_writel(*ctx++, tegra_clk_sclk.reg);
-	clk_writel(*ctx++, tegra_clk_sclk.reg + SUPER_CLK_DIVIDER);
-	clk_writel(*ctx++, tegra_clk_pclk.reg);
-
-	clk_writel(*ctx++, tegra_clk_audio.reg);
-
-	/* enable all clocks before configuring clock sources */
-	clk_writel(0xbffffff9ul, CLK_OUT_ENB);
-	clk_writel(0xfefffff7ul, CLK_OUT_ENB + 4);
-	clk_writel(0x77f01bfful, CLK_OUT_ENB + 8);
-	wmb();
-
-	for (off = PERIPH_CLK_SOURCE_I2S1; off <= PERIPH_CLK_SOURCE_OSC;
-			off += 4) {
-		if (off == PERIPH_CLK_SOURCE_EMC)
-			continue;
-		clk_writel(*ctx++, off);
-	}
-	wmb();
-
-	off = RST_DEVICES;
-	for (i = 0; i < RST_DEVICES_NUM; i++, off += 4)
-		clk_writel(*ctx++, off);
-	wmb();
-
-	off = CLK_OUT_ENB;
-	for (i = 0; i < CLK_OUT_ENB_NUM; i++, off += 4)
-		clk_writel(*ctx++, off);
-	wmb();
-
-	clk_writel(*ctx++, MISC_CLK_ENB);
-	clk_writel(*ctx++, CLK_MASK_ARM);
-}
-#endif
diff --git a/arch/arm/mach-tegra/tegra30_clocks.c b/arch/arm/mach-tegra/tegra30_clocks.c
index 6674f10..5cd502c 100644
--- a/arch/arm/mach-tegra/tegra30_clocks.c
+++ b/arch/arm/mach-tegra/tegra30_clocks.c
@@ -1,7 +1,7 @@
 /*
  * arch/arm/mach-tegra/tegra30_clocks.c
  *
- * Copyright (c) 2010-2011 NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2010-2012 NVIDIA CORPORATION.  All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -35,6 +35,7 @@
 
 #include "clock.h"
 #include "fuse.h"
+#include "tegra_cpu_car.h"
 
 #define USE_PLL_LOCK_BITS 0
 
@@ -299,6 +300,16 @@
 /* FIXME: recommended safety delay after lock is detected */
 #define PLL_POST_LOCK_DELAY		100
 
+/* Tegra CPU clock and reset control regs */
+#define TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX		0x4c
+#define TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET	0x340
+#define TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR	0x344
+#define TEGRA30_CLK_RST_CONTROLLER_CLK_CPU_CMPLX_CLR	0x34c
+#define TEGRA30_CLK_RST_CONTROLLER_CPU_CMPLX_STATUS	0x470
+
+#define CPU_CLOCK(cpu)	(0x1 << (8 + cpu))
+#define CPU_RESET(cpu)	(0x1111ul << (cpu))
+
 /**
 * Structure defining the fields for USB UTMI clocks Parameters.
 */
@@ -365,30 +376,32 @@ static void __iomem *misc_gp_hidrev_base = IO_ADDRESS(TEGRA_APB_MISC_BASE);
 static int tegra_periph_clk_enable_refcount[CLK_OUT_ENB_NUM * 32];
 
 #define clk_writel(value, reg) \
-	__raw_writel(value, (u32)reg_clk_base + (reg))
+	__raw_writel(value, reg_clk_base + (reg))
 #define clk_readl(reg) \
-	__raw_readl((u32)reg_clk_base + (reg))
+	__raw_readl(reg_clk_base + (reg))
 #define pmc_writel(value, reg) \
-	__raw_writel(value, (u32)reg_pmc_base + (reg))
+	__raw_writel(value, reg_pmc_base + (reg))
 #define pmc_readl(reg) \
-	__raw_readl((u32)reg_pmc_base + (reg))
+	__raw_readl(reg_pmc_base + (reg))
 #define chipid_readl() \
-	__raw_readl((u32)misc_gp_hidrev_base + MISC_GP_HIDREV)
+	__raw_readl(misc_gp_hidrev_base + MISC_GP_HIDREV)
 
 #define clk_writel_delay(value, reg)					\
 	do {								\
-		__raw_writel((value), (u32)reg_clk_base + (reg));	\
+		__raw_writel((value), reg_clk_base + (reg));	\
 		udelay(2);						\
 	} while (0)
 
-
-static inline int clk_set_div(struct clk *c, u32 n)
+static inline int clk_set_div(struct clk_tegra *c, u32 n)
 {
-	return clk_set_rate(c, (clk_get_rate(c->parent) + n-1) / n);
+	struct clk *clk = c->hw.clk;
+
+	return clk_set_rate(clk,
+			(__clk_get_rate(__clk_get_parent(clk)) + n - 1) / n);
 }
 
 static inline u32 periph_clk_to_reg(
-	struct clk *c, u32 reg_L, u32 reg_V, int offs)
+	struct clk_tegra *c, u32 reg_L, u32 reg_V, int offs)
 {
 	u32 reg = c->u.periph.clk_num / 32;
 	BUG_ON(reg >= RST_DEVICES_NUM);
@@ -470,15 +483,32 @@ static int clk_div16_get_divider(unsigned long parent_rate, unsigned long rate)
 	return divider_u16 - 1;
 }
 
+static unsigned long tegra30_clk_fixed_recalc_rate(struct clk_hw *hw,
+		unsigned long parent_rate)
+{
+	return to_clk_tegra(hw)->fixed_rate;
+}
+
+struct clk_ops tegra30_clk_32k_ops = {
+	.recalc_rate = tegra30_clk_fixed_recalc_rate,
+};
+
 /* clk_m functions */
-static unsigned long tegra30_clk_m_autodetect_rate(struct clk *c)
+static unsigned long tegra30_clk_m_recalc_rate(struct clk_hw *hw,
+		unsigned long parent_rate)
+{
+	if (!to_clk_tegra(hw)->fixed_rate)
+		to_clk_tegra(hw)->fixed_rate = clk_measure_input_freq();
+	return to_clk_tegra(hw)->fixed_rate;
+}
+
+static void tegra30_clk_m_init(struct clk_hw *hw)
 {
 	u32 osc_ctrl = clk_readl(OSC_CTRL);
 	u32 auto_clock_control = osc_ctrl & ~OSC_CTRL_OSC_FREQ_MASK;
 	u32 pll_ref_div = osc_ctrl & OSC_CTRL_PLL_REF_DIV_MASK;
 
-	c->rate = clk_measure_input_freq();
-	switch (c->rate) {
+	switch (to_clk_tegra(hw)->fixed_rate) {
 	case 12000000:
 		auto_clock_control |= OSC_CTRL_OSC_FREQ_12MHZ;
 		BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_1);
@@ -508,46 +538,44 @@ static unsigned long tegra30_clk_m_autodetect_rate(struct clk *c)
 		BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_4);
 		break;
 	default:
-		pr_err("%s: Unexpected clock rate %ld", __func__, c->rate);
+		pr_err("%s: Unexpected clock rate %ld", __func__,
+				to_clk_tegra(hw)->fixed_rate);
 		BUG();
 	}
 	clk_writel(auto_clock_control, OSC_CTRL);
-	return c->rate;
 }
 
-static void tegra30_clk_m_init(struct clk *c)
-{
-	pr_debug("%s on clock %s\n", __func__, c->name);
-	tegra30_clk_m_autodetect_rate(c);
-}
+struct clk_ops tegra30_clk_m_ops = {
+	.init = tegra30_clk_m_init,
+	.recalc_rate = tegra30_clk_m_recalc_rate,
+};
 
-static int tegra30_clk_m_enable(struct clk *c)
+static unsigned long tegra30_clk_m_div_recalc_rate(struct clk_hw *hw,
+		unsigned long parent_rate)
 {
-	pr_debug("%s on clock %s\n", __func__, c->name);
-	return 0;
-}
+	struct clk_tegra *c = to_clk_tegra(hw);
+	u64 rate = parent_rate;
 
-static void tegra30_clk_m_disable(struct clk *c)
-{
-	pr_debug("%s on clock %s\n", __func__, c->name);
-	WARN(1, "Attempting to disable main SoC clock\n");
-}
+	if (c->mul != 0 && c->div != 0) {
+		rate *= c->mul;
+		rate += c->div - 1; /* round up */
+		do_div(rate, c->div);
+	}
 
-static struct clk_ops tegra_clk_m_ops = {
-	.init		= tegra30_clk_m_init,
-	.enable		= tegra30_clk_m_enable,
-	.disable	= tegra30_clk_m_disable,
-};
+	return rate;
+}
 
-static struct clk_ops tegra_clk_m_div_ops = {
-	.enable		= tegra30_clk_m_enable,
+struct clk_ops tegra_clk_m_div_ops = {
+	.recalc_rate = tegra30_clk_m_div_recalc_rate,
 };
 
 /* PLL reference divider functions */
-static void tegra30_pll_ref_init(struct clk *c)
+static unsigned long tegra30_pll_ref_recalc_rate(struct clk_hw *hw,
+			unsigned long parent_rate)
 {
+	struct clk_tegra *c = to_clk_tegra(hw);
+	unsigned long rate = parent_rate;
 	u32 pll_ref_div = clk_readl(OSC_CTRL) & OSC_CTRL_PLL_REF_DIV_MASK;
-	pr_debug("%s on clock %s\n", __func__, c->name);
 
 	switch (pll_ref_div) {
 	case OSC_CTRL_PLL_REF_DIV_1:
@@ -564,13 +592,18 @@ static void tegra30_pll_ref_init(struct clk *c)
 		BUG();
 	}
 	c->mul = 1;
-	c->state = ON;
+
+	if (c->mul != 0 && c->div != 0) {
+		rate *= c->mul;
+		rate += c->div - 1; /* round up */
+		do_div(rate, c->div);
+	}
+
+	return rate;
 }
 
-static struct clk_ops tegra_pll_ref_ops = {
-	.init		= tegra30_pll_ref_init,
-	.enable		= tegra30_clk_m_enable,
-	.disable	= tegra30_clk_m_disable,
+struct clk_ops tegra_pll_ref_ops = {
+	.recalc_rate = tegra30_pll_ref_recalc_rate,
 };
 
 /* super clock functions */
@@ -581,56 +614,50 @@ static struct clk_ops tegra_pll_ref_ops = {
  * only when its parent is a fixed rate PLL, since we can't change PLL rate
  * in this case.
  */
-static void tegra30_super_clk_init(struct clk *c)
+static void tegra30_super_clk_init(struct clk_hw *hw)
 {
-	u32 val;
-	int source;
-	int shift;
-	const struct clk_mux_sel *sel;
-	val = clk_readl(c->reg + SUPER_CLK_MUX);
-	c->state = ON;
-	BUG_ON(((val & SUPER_STATE_MASK) != SUPER_STATE_RUN) &&
-		((val & SUPER_STATE_MASK) != SUPER_STATE_IDLE));
-	shift = ((val & SUPER_STATE_MASK) == SUPER_STATE_IDLE) ?
-		SUPER_IDLE_SOURCE_SHIFT : SUPER_RUN_SOURCE_SHIFT;
-	source = (val >> shift) & SUPER_SOURCE_MASK;
-	if (c->flags & DIV_2)
-		source |= val & SUPER_LP_DIV2_BYPASS;
-	for (sel = c->inputs; sel->input != NULL; sel++) {
-		if (sel->value == source)
-			break;
-	}
-	BUG_ON(sel->input == NULL);
-	c->parent = sel->input;
+	struct clk_tegra *c = to_clk_tegra(hw);
+	struct clk_tegra *p =
+			to_clk_tegra(__clk_get_hw(__clk_get_parent(hw->clk)));
 
+	c->state = ON;
 	if (c->flags & DIV_U71) {
 		/* Init safe 7.1 divider value (does not affect PLLX path) */
 		clk_writel(SUPER_CLOCK_DIV_U71_MIN << SUPER_CLOCK_DIV_U71_SHIFT,
 			   c->reg + SUPER_CLK_DIVIDER);
 		c->mul = 2;
 		c->div = 2;
-		if (!(c->parent->flags & PLLX))
+		if (!(p->flags & PLLX))
 			c->div += SUPER_CLOCK_DIV_U71_MIN;
 	} else
 		clk_writel(0, c->reg + SUPER_CLK_DIVIDER);
 }
 
-static int tegra30_super_clk_enable(struct clk *c)
+static u8 tegra30_super_clk_get_parent(struct clk_hw *hw)
 {
-	return 0;
-}
+	struct clk_tegra *c = to_clk_tegra(hw);
+	u32 val;
+	int source;
+	int shift;
 
-static void tegra30_super_clk_disable(struct clk *c)
-{
-	/* since tegra 3 has 2 CPU super clocks - low power lp-mode clock and
-	   geared up g-mode super clock - mode switch may request to disable
-	   either of them; accept request with no affect on h/w */
+	val = clk_readl(c->reg + SUPER_CLK_MUX);
+	BUG_ON(((val & SUPER_STATE_MASK) != SUPER_STATE_RUN) &&
+		((val & SUPER_STATE_MASK) != SUPER_STATE_IDLE));
+	shift = ((val & SUPER_STATE_MASK) == SUPER_STATE_IDLE) ?
+		SUPER_IDLE_SOURCE_SHIFT : SUPER_RUN_SOURCE_SHIFT;
+	source = (val >> shift) & SUPER_SOURCE_MASK;
+	if (c->flags & DIV_2)
+		source |= val & SUPER_LP_DIV2_BYPASS;
+
+	return source;
 }
 
-static int tegra30_super_clk_set_parent(struct clk *c, struct clk *p)
+static int tegra30_super_clk_set_parent(struct clk_hw *hw, u8 index)
 {
+	struct clk_tegra *c = to_clk_tegra(hw);
+	struct clk_tegra *p =
+			to_clk_tegra(__clk_get_hw(clk_get_parent(hw->clk)));
 	u32 val;
-	const struct clk_mux_sel *sel;
 	int shift;
 
 	val = clk_readl(c->reg + SUPER_CLK_MUX);
@@ -638,48 +665,36 @@ static int tegra30_super_clk_set_parent(struct clk *c, struct clk *p)
 		((val & SUPER_STATE_MASK) != SUPER_STATE_IDLE));
 	shift = ((val & SUPER_STATE_MASK) == SUPER_STATE_IDLE) ?
 		SUPER_IDLE_SOURCE_SHIFT : SUPER_RUN_SOURCE_SHIFT;
-	for (sel = c->inputs; sel->input != NULL; sel++) {
-		if (sel->input == p) {
-			/* For LP mode super-clock switch between PLLX direct
-			   and divided-by-2 outputs is allowed only when other
-			   than PLLX clock source is current parent */
-			if ((c->flags & DIV_2) && (p->flags & PLLX) &&
-			    ((sel->value ^ val) & SUPER_LP_DIV2_BYPASS)) {
-				if (c->parent->flags & PLLX)
-					return -EINVAL;
-				val ^= SUPER_LP_DIV2_BYPASS;
-				clk_writel_delay(val, c->reg);
-			}
-			val &= ~(SUPER_SOURCE_MASK << shift);
-			val |= (sel->value & SUPER_SOURCE_MASK) << shift;
-
-			/* 7.1 divider for CPU super-clock does not affect
-			   PLLX path */
-			if (c->flags & DIV_U71) {
-				u32 div = 0;
-				if (!(p->flags & PLLX)) {
-					div = clk_readl(c->reg +
-							SUPER_CLK_DIVIDER);
-					div &= SUPER_CLOCK_DIV_U71_MASK;
-					div >>= SUPER_CLOCK_DIV_U71_SHIFT;
-				}
-				c->div = div + 2;
-				c->mul = 2;
-			}
-
-			if (c->refcnt)
-				clk_enable(p);
-
-			clk_writel_delay(val, c->reg);
 
-			if (c->refcnt && c->parent)
-				clk_disable(c->parent);
+	/* For LP mode super-clock switch between PLLX direct
+	   and divided-by-2 outputs is allowed only when other
+	   than PLLX clock source is current parent */
+	if ((c->flags & DIV_2) && (p->flags & PLLX) &&
+	    ((index ^ val) & SUPER_LP_DIV2_BYPASS)) {
+		if (p->flags & PLLX)
+			return -EINVAL;
+		val ^= SUPER_LP_DIV2_BYPASS;
+		clk_writel_delay(val, c->reg);
+	}
+	val &= ~(SUPER_SOURCE_MASK << shift);
+	val |= (index & SUPER_SOURCE_MASK) << shift;
 
-			clk_reparent(c, p);
-			return 0;
+	/* 7.1 divider for CPU super-clock does not affect
+	   PLLX path */
+	if (c->flags & DIV_U71) {
+		u32 div = 0;
+		if (!(p->flags & PLLX)) {
+			div = clk_readl(c->reg +
+					SUPER_CLK_DIVIDER);
+			div &= SUPER_CLOCK_DIV_U71_MASK;
+			div >>= SUPER_CLOCK_DIV_U71_SHIFT;
 		}
+		c->div = div + 2;
+		c->mul = 2;
 	}
-	return -EINVAL;
+	clk_writel_delay(val, c->reg);
+
+	return 0;
 }
 
 /*
@@ -691,10 +706,15 @@ static int tegra30_super_clk_set_parent(struct clk *c, struct clk *p)
  * rate of this PLL can't be changed, and it has many other children. In
  * this case use 7.1 fractional divider to adjust the super clock rate.
  */
-static int tegra30_super_clk_set_rate(struct clk *c, unsigned long rate)
+static int tegra30_super_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long parent_rate)
 {
-	if ((c->flags & DIV_U71) && (c->parent->flags & PLL_FIXED)) {
-		int div = clk_div71_get_divider(c->parent->u.pll.fixed_rate,
+	struct clk_tegra *c = to_clk_tegra(hw);
+	struct clk *parent = __clk_get_parent(hw->clk);
+	struct clk_tegra *cparent = to_clk_tegra(__clk_get_hw(parent));
+
+	if ((c->flags & DIV_U71) && (cparent->flags & PLL_FIXED)) {
+		int div = clk_div71_get_divider(parent_rate,
 					rate, c->flags, ROUND_DIVIDER_DOWN);
 		div = max(div, SUPER_CLOCK_DIV_U71_MIN);
 
@@ -704,55 +724,86 @@ static int tegra30_super_clk_set_rate(struct clk *c, unsigned long rate)
 		c->mul = 2;
 		return 0;
 	}
-	return clk_set_rate(c->parent, rate);
+	return 0;
+}
+
+static unsigned long tegra30_super_clk_recalc_rate(struct clk_hw *hw,
+		unsigned long parent_rate)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+	u64 rate = parent_rate;
+
+	if (c->mul != 0 && c->div != 0) {
+		rate *= c->mul;
+		rate += c->div - 1; /* round up */
+		do_div(rate, c->div);
+	}
+
+	return rate;
+}
+
+static long tegra30_super_clk_round_rate(struct clk_hw *hw, unsigned long rate,
+				unsigned long *prate)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+	struct clk *parent = __clk_get_parent(hw->clk);
+	struct clk_tegra *cparent = to_clk_tegra(__clk_get_hw(parent));
+	int mul = 2;
+	int div;
+
+	if ((c->flags & DIV_U71) && (cparent->flags & PLL_FIXED)) {
+		div = clk_div71_get_divider(*prate,
+				rate, c->flags, ROUND_DIVIDER_DOWN);
+		div = max(div, SUPER_CLOCK_DIV_U71_MIN) + 2;
+		rate = *prate * mul;
+		rate += div - 1; /* round up */
+		do_div(rate, c->div);
+
+		return rate;
+	}
+	return *prate;
 }
 
-static struct clk_ops tegra_super_ops = {
-	.init			= tegra30_super_clk_init,
-	.enable			= tegra30_super_clk_enable,
-	.disable		= tegra30_super_clk_disable,
-	.set_parent		= tegra30_super_clk_set_parent,
-	.set_rate		= tegra30_super_clk_set_rate,
+struct clk_ops tegra30_super_ops = {
+	.init = tegra30_super_clk_init,
+	.set_parent = tegra30_super_clk_set_parent,
+	.get_parent = tegra30_super_clk_get_parent,
+	.recalc_rate = tegra30_super_clk_recalc_rate,
+	.round_rate = tegra30_super_clk_round_rate,
+	.set_rate = tegra30_super_clk_set_rate,
 };
 
-static int tegra30_twd_clk_set_rate(struct clk *c, unsigned long rate)
+static unsigned long tegra30_twd_clk_recalc_rate(struct clk_hw *hw,
+		unsigned long parent_rate)
 {
-	/* The input value 'rate' is the clock rate of the CPU complex. */
-	c->rate = (rate * c->mul) / c->div;
-	return 0;
+	struct clk_tegra *c = to_clk_tegra(hw);
+	u64 rate = parent_rate;
+
+	if (c->mul != 0 && c->div != 0) {
+		rate *= c->mul;
+		rate += c->div - 1; /* round up */
+		do_div(rate, c->div);
+	}
+
+	return rate;
 }
 
-static struct clk_ops tegra30_twd_ops = {
-	.set_rate	= tegra30_twd_clk_set_rate,
+struct clk_ops tegra30_twd_ops = {
+	.recalc_rate = tegra30_twd_clk_recalc_rate,
 };
 
 /* Blink output functions */
-
-static void tegra30_blink_clk_init(struct clk *c)
+static int tegra30_blink_clk_is_enabled(struct clk_hw *hw)
 {
+	struct clk_tegra *c = to_clk_tegra(hw);
 	u32 val;
 
 	val = pmc_readl(PMC_CTRL);
 	c->state = (val & PMC_CTRL_BLINK_ENB) ? ON : OFF;
-	c->mul = 1;
-	val = pmc_readl(c->reg);
-
-	if (val & PMC_BLINK_TIMER_ENB) {
-		unsigned int on_off;
-
-		on_off = (val >> PMC_BLINK_TIMER_DATA_ON_SHIFT) &
-			PMC_BLINK_TIMER_DATA_ON_MASK;
-		val >>= PMC_BLINK_TIMER_DATA_OFF_SHIFT;
-		val &= PMC_BLINK_TIMER_DATA_OFF_MASK;
-		on_off += val;
-		/* each tick in the blink timer is 4 32KHz clocks */
-		c->div = on_off * 4;
-	} else {
-		c->div = 1;
-	}
+	return c->state;
 }
 
-static int tegra30_blink_clk_enable(struct clk *c)
+static int tegra30_blink_clk_enable(struct clk_hw *hw)
 {
 	u32 val;
 
@@ -765,7 +816,7 @@ static int tegra30_blink_clk_enable(struct clk *c)
 	return 0;
 }
 
-static void tegra30_blink_clk_disable(struct clk *c)
+static void tegra30_blink_clk_disable(struct clk_hw *hw)
 {
 	u32 val;
 
@@ -776,9 +827,11 @@ static void tegra30_blink_clk_disable(struct clk *c)
 	pmc_writel(val & ~PMC_DPD_PADS_ORIDE_BLINK_ENB, PMC_DPD_PADS_ORIDE);
 }
 
-static int tegra30_blink_clk_set_rate(struct clk *c, unsigned long rate)
+static int tegra30_blink_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long parent_rate)
 {
-	unsigned long parent_rate = clk_get_rate(c->parent);
+	struct clk_tegra *c = to_clk_tegra(hw);
+
 	if (rate >= parent_rate) {
 		c->div = 1;
 		pmc_writel(0, c->reg);
@@ -801,41 +854,77 @@ static int tegra30_blink_clk_set_rate(struct clk *c, unsigned long rate)
 	return 0;
 }
 
-static struct clk_ops tegra_blink_clk_ops = {
-	.init			= &tegra30_blink_clk_init,
-	.enable			= &tegra30_blink_clk_enable,
-	.disable		= &tegra30_blink_clk_disable,
-	.set_rate		= &tegra30_blink_clk_set_rate,
-};
+static unsigned long tegra30_blink_clk_recalc_rate(struct clk_hw *hw,
+		unsigned long parent_rate)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+	u64 rate = parent_rate;
+	u32 val;
+	u32 mul;
+	u32 div;
+	u32 on_off;
 
-/* PLL Functions */
-static int tegra30_pll_clk_wait_for_lock(struct clk *c, u32 lock_reg,
-					 u32 lock_bit)
+	mul = 1;
+	val = pmc_readl(c->reg);
+
+	if (val & PMC_BLINK_TIMER_ENB) {
+		on_off = (val >> PMC_BLINK_TIMER_DATA_ON_SHIFT) &
+			PMC_BLINK_TIMER_DATA_ON_MASK;
+		val >>= PMC_BLINK_TIMER_DATA_OFF_SHIFT;
+		val &= PMC_BLINK_TIMER_DATA_OFF_MASK;
+		on_off += val;
+		/* each tick in the blink timer is 4 32KHz clocks */
+		div = on_off * 4;
+	} else {
+		div = 1;
+	}
+
+	if (mul != 0 && div != 0) {
+		rate *= mul;
+		rate += div - 1; /* round up */
+		do_div(rate, div);
+	}
+	return rate;
+}
+
+static long tegra30_blink_clk_round_rate(struct clk_hw *hw, unsigned long rate,
+				unsigned long *prate)
 {
-#if USE_PLL_LOCK_BITS
-	int i;
-	for (i = 0; i < c->u.pll.lock_delay; i++) {
-		if (clk_readl(lock_reg) & lock_bit) {
-			udelay(PLL_POST_LOCK_DELAY);
-			return 0;
-		}
-		udelay(2);		/* timeout = 2 * lock time */
+	int div;
+	int mul;
+	long round_rate = *prate;
+
+	mul = 1;
+
+	if (rate >= *prate) {
+		div = 1;
+	} else {
+		div = DIV_ROUND_UP(*prate / 8, rate);
+		div *= 8;
 	}
-	pr_err("Timed out waiting for lock bit on pll %s", c->name);
-	return -1;
-#endif
-	udelay(c->u.pll.lock_delay);
 
-	return 0;
+	round_rate *= mul;
+	round_rate += div - 1;
+	do_div(round_rate, div);
+
+	return round_rate;
 }
 
+struct clk_ops tegra30_blink_clk_ops = {
+	.is_enabled = tegra30_blink_clk_is_enabled,
+	.enable = tegra30_blink_clk_enable,
+	.disable = tegra30_blink_clk_disable,
+	.recalc_rate = tegra30_blink_clk_recalc_rate,
+	.round_rate = tegra30_blink_clk_round_rate,
+	.set_rate = tegra30_blink_clk_set_rate,
+};
 
-static void tegra30_utmi_param_configure(struct clk *c)
+static void tegra30_utmi_param_configure(struct clk_hw *hw)
 {
+	unsigned long main_rate =
+		__clk_get_rate(__clk_get_parent(__clk_get_parent(hw->clk)));
 	u32 reg;
 	int i;
-	unsigned long main_rate =
-		clk_get_rate(c->parent->parent);
 
 	for (i = 0; i < ARRAY_SIZE(utmi_parameters); i++) {
 		if (main_rate == utmi_parameters[i].osc_frequency)
@@ -886,50 +975,52 @@ static void tegra30_utmi_param_configure(struct clk *c)
 	clk_writel(reg, UTMIP_PLL_CFG1);
 }
 
-static void tegra30_pll_clk_init(struct clk *c)
+/* PLL Functions */
+static int tegra30_pll_clk_wait_for_lock(struct clk_tegra *c, u32 lock_reg,
+					 u32 lock_bit)
+{
+	int ret = 0;
+
+#if USE_PLL_LOCK_BITS
+	int i;
+	for (i = 0; i < c->u.pll.lock_delay; i++) {
+		if (clk_readl(lock_reg) & lock_bit) {
+			udelay(PLL_POST_LOCK_DELAY);
+			return 0;
+		}
+		udelay(2);	/* timeout = 2 * lock time */
+	}
+	pr_err("Timed out waiting for lock bit on pll %s",
+					__clk_get_name(hw->clk));
+	ret = -1;
+#else
+	udelay(c->u.pll.lock_delay);
+#endif
+	return ret;
+}
+
+static int tegra30_pll_clk_is_enabled(struct clk_hw *hw)
 {
+	struct clk_tegra *c = to_clk_tegra(hw);
 	u32 val = clk_readl(c->reg + PLL_BASE);
 
 	c->state = (val & PLL_BASE_ENABLE) ? ON : OFF;
+	return c->state;
+}
 
-	if (c->flags & PLL_FIXED && !(val & PLL_BASE_OVERRIDE)) {
-		const struct clk_pll_freq_table *sel;
-		unsigned long input_rate = clk_get_rate(c->parent);
-		for (sel = c->u.pll.freq_table; sel->input_rate != 0; sel++) {
-			if (sel->input_rate == input_rate &&
-				sel->output_rate == c->u.pll.fixed_rate) {
-				c->mul = sel->n;
-				c->div = sel->m * sel->p;
-				return;
-			}
-		}
-		pr_err("Clock %s has unknown fixed frequency\n", c->name);
-		BUG();
-	} else if (val & PLL_BASE_BYPASS) {
-		c->mul = 1;
-		c->div = 1;
-	} else {
-		c->mul = (val & PLL_BASE_DIVN_MASK) >> PLL_BASE_DIVN_SHIFT;
-		c->div = (val & PLL_BASE_DIVM_MASK) >> PLL_BASE_DIVM_SHIFT;
-		if (c->flags & PLLU)
-			c->div *= (val & PLLU_BASE_POST_DIV) ? 1 : 2;
-		else
-			c->div *= (0x1 << ((val & PLL_BASE_DIVP_MASK) >>
-					PLL_BASE_DIVP_SHIFT));
-		if (c->flags & PLL_FIXED) {
-			unsigned long rate = clk_get_rate_locked(c);
-			BUG_ON(rate != c->u.pll.fixed_rate);
-		}
-	}
+static void tegra30_pll_clk_init(struct clk_hw *hw)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
 
 	if (c->flags & PLLU)
-		tegra30_utmi_param_configure(c);
+		tegra30_utmi_param_configure(hw);
 }
 
-static int tegra30_pll_clk_enable(struct clk *c)
+static int tegra30_pll_clk_enable(struct clk_hw *hw)
 {
+	struct clk_tegra *c = to_clk_tegra(hw);
 	u32 val;
-	pr_debug("%s on clock %s\n", __func__, c->name);
+	pr_debug("%s on clock %s\n", __func__, __clk_get_name(hw->clk));
 
 #if USE_PLL_LOCK_BITS
 	val = clk_readl(c->reg + PLL_MISC(c));
@@ -952,10 +1043,11 @@ static int tegra30_pll_clk_enable(struct clk *c)
 	return 0;
 }
 
-static void tegra30_pll_clk_disable(struct clk *c)
+static void tegra30_pll_clk_disable(struct clk_hw *hw)
 {
+	struct clk_tegra *c = to_clk_tegra(hw);
 	u32 val;
-	pr_debug("%s on clock %s\n", __func__, c->name);
+	pr_debug("%s on clock %s\n", __func__, __clk_get_name(hw->clk));
 
 	val = clk_readl(c->reg);
 	val &= ~(PLL_BASE_BYPASS | PLL_BASE_ENABLE);
@@ -968,36 +1060,36 @@ static void tegra30_pll_clk_disable(struct clk *c)
 	}
 }
 
-static int tegra30_pll_clk_set_rate(struct clk *c, unsigned long rate)
+static int tegra30_pll_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long parent_rate)
 {
+	struct clk_tegra *c = to_clk_tegra(hw);
 	u32 val, p_div, old_base;
 	unsigned long input_rate;
 	const struct clk_pll_freq_table *sel;
 	struct clk_pll_freq_table cfg;
 
-	pr_debug("%s: %s %lu\n", __func__, c->name, rate);
-
 	if (c->flags & PLL_FIXED) {
 		int ret = 0;
 		if (rate != c->u.pll.fixed_rate) {
 			pr_err("%s: Can not change %s fixed rate %lu to %lu\n",
-			       __func__, c->name, c->u.pll.fixed_rate, rate);
+			       __func__, __clk_get_name(hw->clk),
+				c->u.pll.fixed_rate, rate);
 			ret = -EINVAL;
 		}
 		return ret;
 	}
 
 	if (c->flags & PLLM) {
-		if (rate != clk_get_rate_locked(c)) {
+		if (rate != __clk_get_rate(hw->clk)) {
 			pr_err("%s: Can not change memory %s rate in flight\n",
-			       __func__, c->name);
+				__func__, __clk_get_name(hw->clk));
 			return -EINVAL;
 		}
-		return 0;
 	}
 
 	p_div = 0;
-	input_rate = clk_get_rate(c->parent);
+	input_rate = parent_rate;
 
 	/* Check if the target rate is tabulated */
 	for (sel = c->u.pll.freq_table; sel->input_rate != 0; sel++) {
@@ -1055,7 +1147,7 @@ static int tegra30_pll_clk_set_rate(struct clk *c, unsigned long rate)
 		    (p_div > (PLL_BASE_DIVP_MASK >> PLL_BASE_DIVP_SHIFT)) ||
 		    (cfg.output_rate > c->u.pll.vco_max)) {
 			pr_err("%s: Failed to set %s out-of-table rate %lu\n",
-			       __func__, c->name, rate);
+			       __func__, __clk_get_name(hw->clk), rate);
 			return -EINVAL;
 		}
 		p_div <<= PLL_BASE_DIVP_SHIFT;
@@ -1073,7 +1165,7 @@ static int tegra30_pll_clk_set_rate(struct clk *c, unsigned long rate)
 		return 0;
 
 	if (c->state == ON) {
-		tegra30_pll_clk_disable(c);
+		tegra30_pll_clk_disable(hw);
 		val &= ~(PLL_BASE_BYPASS | PLL_BASE_ENABLE);
 	}
 	clk_writel(val, c->reg + PLL_BASE);
@@ -1095,87 +1187,201 @@ static int tegra30_pll_clk_set_rate(struct clk *c, unsigned long rate)
 	}
 
 	if (c->state == ON)
-		tegra30_pll_clk_enable(c);
-
-	return 0;
-}
-
-static struct clk_ops tegra_pll_ops = {
-	.init			= tegra30_pll_clk_init,
-	.enable			= tegra30_pll_clk_enable,
-	.disable		= tegra30_pll_clk_disable,
-	.set_rate		= tegra30_pll_clk_set_rate,
-};
-
-static int
-tegra30_plld_clk_cfg_ex(struct clk *c, enum tegra_clk_ex_param p, u32 setting)
-{
-	u32 val, mask, reg;
+		tegra30_pll_clk_enable(hw);
 
-	switch (p) {
-	case TEGRA_CLK_PLLD_CSI_OUT_ENB:
-		mask = PLLD_BASE_CSI_CLKENABLE;
-		reg = c->reg + PLL_BASE;
-		break;
-	case TEGRA_CLK_PLLD_DSI_OUT_ENB:
-		mask = PLLD_MISC_DSI_CLKENABLE;
-		reg = c->reg + PLL_MISC(c);
-		break;
-	case TEGRA_CLK_PLLD_MIPI_MUX_SEL:
-		if (!(c->flags & PLL_ALT_MISC_REG)) {
-			mask = PLLD_BASE_DSIB_MUX_MASK;
-			reg = c->reg + PLL_BASE;
-			break;
-		}
-	/* fall through - error since PLLD2 does not have MUX_SEL control */
-	default:
-		return -EINVAL;
-	}
+	c->u.pll.fixed_rate = rate;
 
-	val = clk_readl(reg);
-	if (setting)
-		val |= mask;
-	else
-		val &= ~mask;
-	clk_writel(val, reg);
 	return 0;
 }
 
-static struct clk_ops tegra_plld_ops = {
-	.init			= tegra30_pll_clk_init,
-	.enable			= tegra30_pll_clk_enable,
-	.disable		= tegra30_pll_clk_disable,
-	.set_rate		= tegra30_pll_clk_set_rate,
-	.clk_cfg_ex		= tegra30_plld_clk_cfg_ex,
-};
-
-static void tegra30_plle_clk_init(struct clk *c)
+static long tegra30_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+				unsigned long *prate)
 {
+	struct clk_tegra *c = to_clk_tegra(hw);
+	unsigned long input_rate = *prate;
+	unsigned long output_rate = *prate;
+	const struct clk_pll_freq_table *sel;
+	struct clk_pll_freq_table cfg;
+	int mul;
+	int div;
+	u32 p_div;
 	u32 val;
 
-	val = clk_readl(PLLE_AUX);
-	c->parent = (val & PLLE_AUX_PLLP_SEL) ?
-		tegra_get_clock_by_name("pll_p") :
-		tegra_get_clock_by_name("pll_ref");
+	if (c->flags & PLL_FIXED)
+		return c->u.pll.fixed_rate;
 
-	val = clk_readl(c->reg + PLL_BASE);
-	c->state = (val & PLLE_BASE_ENABLE) ? ON : OFF;
-	c->mul = (val & PLLE_BASE_DIVN_MASK) >> PLLE_BASE_DIVN_SHIFT;
-	c->div = (val & PLLE_BASE_DIVM_MASK) >> PLLE_BASE_DIVM_SHIFT;
-	c->div *= (val & PLLE_BASE_DIVP_MASK) >> PLLE_BASE_DIVP_SHIFT;
-}
+	if (c->flags & PLLM)
+		return __clk_get_rate(hw->clk);
 
-static void tegra30_plle_clk_disable(struct clk *c)
-{
-	u32 val;
-	pr_debug("%s on clock %s\n", __func__, c->name);
+	p_div = 0;
+	/* Check if the target rate is tabulated */
+	for (sel = c->u.pll.freq_table; sel->input_rate != 0; sel++) {
+		if (sel->input_rate == input_rate && sel->output_rate == rate) {
+			if (c->flags & PLLU) {
+				BUG_ON(sel->p < 1 || sel->p > 2);
+				if (sel->p == 1)
+					p_div = PLLU_BASE_POST_DIV;
+			} else {
+				BUG_ON(sel->p < 1);
+				for (val = sel->p; val > 1; val >>= 1)
+					p_div++;
+				p_div <<= PLL_BASE_DIVP_SHIFT;
+			}
+			break;
+		}
+	}
 
-	val = clk_readl(c->reg + PLL_BASE);
-	val &= ~(PLLE_BASE_CML_ENABLE | PLLE_BASE_ENABLE);
-	clk_writel(val, c->reg + PLL_BASE);
-}
+	if (sel->input_rate == 0) {
+		unsigned long cfreq;
+		BUG_ON(c->flags & PLLU);
+		sel = &cfg;
 
-static void tegra30_plle_training(struct clk *c)
+		switch (input_rate) {
+		case 12000000:
+		case 26000000:
+			cfreq = (rate <= 1000000 * 1000) ? 1000000 : 2000000;
+			break;
+		case 13000000:
+			cfreq = (rate <= 1000000 * 1000) ? 1000000 : 2600000;
+			break;
+		case 16800000:
+		case 19200000:
+			cfreq = (rate <= 1200000 * 1000) ? 1200000 : 2400000;
+			break;
+		default:
+			pr_err("%s: Unexpected reference rate %lu\n",
+			       __func__, input_rate);
+			BUG();
+		}
+
+		/* Raise VCO to guarantee 0.5% accuracy */
+		for (cfg.output_rate = rate; cfg.output_rate < 200 * cfreq;
+		      cfg.output_rate <<= 1)
+			p_div++;
+
+		cfg.p = 0x1 << p_div;
+		cfg.m = input_rate / cfreq;
+		cfg.n = cfg.output_rate / cfreq;
+	}
+
+	mul = sel->n;
+	div = sel->m * sel->p;
+
+	output_rate *= mul;
+	output_rate += div - 1; /* round up */
+	do_div(output_rate, div);
+
+	return output_rate;
+}
+
+static unsigned long tegra30_pll_recalc_rate(struct clk_hw *hw,
+		unsigned long parent_rate)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+	u64 rate = parent_rate;
+	u32 val = clk_readl(c->reg + PLL_BASE);
+
+	if (c->flags & PLL_FIXED && !(val & PLL_BASE_OVERRIDE)) {
+		const struct clk_pll_freq_table *sel;
+		for (sel = c->u.pll.freq_table; sel->input_rate != 0; sel++) {
+			if (sel->input_rate == parent_rate &&
+				sel->output_rate == c->u.pll.fixed_rate) {
+				c->mul = sel->n;
+				c->div = sel->m * sel->p;
+				break;
+			}
+		}
+		pr_err("Clock %s has unknown fixed frequency\n",
+						__clk_get_name(hw->clk));
+		BUG();
+	} else if (val & PLL_BASE_BYPASS) {
+		c->mul = 1;
+		c->div = 1;
+	} else {
+		c->mul = (val & PLL_BASE_DIVN_MASK) >> PLL_BASE_DIVN_SHIFT;
+		c->div = (val & PLL_BASE_DIVM_MASK) >> PLL_BASE_DIVM_SHIFT;
+		if (c->flags & PLLU)
+			c->div *= (val & PLLU_BASE_POST_DIV) ? 1 : 2;
+		else
+			c->div *= (0x1 << ((val & PLL_BASE_DIVP_MASK) >>
+					PLL_BASE_DIVP_SHIFT));
+	}
+
+	if (c->mul != 0 && c->div != 0) {
+		rate *= c->mul;
+		rate += c->div - 1; /* round up */
+		do_div(rate, c->div);
+	}
+
+	return rate;
+}
+
+struct clk_ops tegra30_pll_ops = {
+	.is_enabled = tegra30_pll_clk_is_enabled,
+	.init = tegra30_pll_clk_init,
+	.enable = tegra30_pll_clk_enable,
+	.disable = tegra30_pll_clk_disable,
+	.recalc_rate = tegra30_pll_recalc_rate,
+	.round_rate = tegra30_pll_round_rate,
+	.set_rate = tegra30_pll_clk_set_rate,
+};
+
+int tegra30_plld_clk_cfg_ex(struct clk_hw *hw,
+				enum tegra_clk_ex_param p, u32 setting)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+	u32 val, mask, reg;
+
+	switch (p) {
+	case TEGRA_CLK_PLLD_CSI_OUT_ENB:
+		mask = PLLD_BASE_CSI_CLKENABLE;
+		reg = c->reg + PLL_BASE;
+		break;
+	case TEGRA_CLK_PLLD_DSI_OUT_ENB:
+		mask = PLLD_MISC_DSI_CLKENABLE;
+		reg = c->reg + PLL_MISC(c);
+		break;
+	case TEGRA_CLK_PLLD_MIPI_MUX_SEL:
+		if (!(c->flags & PLL_ALT_MISC_REG)) {
+			mask = PLLD_BASE_DSIB_MUX_MASK;
+			reg = c->reg + PLL_BASE;
+			break;
+		}
+	/* fall through - error since PLLD2 does not have MUX_SEL control */
+	default:
+		return -EINVAL;
+	}
+
+	val = clk_readl(reg);
+	if (setting)
+		val |= mask;
+	else
+		val &= ~mask;
+	clk_writel(val, reg);
+	return 0;
+}
+
+static int tegra30_plle_clk_is_enabled(struct clk_hw *hw)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+	u32 val;
+
+	val = clk_readl(c->reg + PLL_BASE);
+	c->state = (val & PLLE_BASE_ENABLE) ? ON : OFF;
+	return c->state;
+}
+
+static void tegra30_plle_clk_disable(struct clk_hw *hw)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+	u32 val;
+
+	val = clk_readl(c->reg + PLL_BASE);
+	val &= ~(PLLE_BASE_CML_ENABLE | PLLE_BASE_ENABLE);
+	clk_writel(val, c->reg + PLL_BASE);
+}
+
+static void tegra30_plle_training(struct clk_tegra *c)
 {
 	u32 val;
 
@@ -1198,12 +1404,15 @@ static void tegra30_plle_training(struct clk *c)
 	} while (!(val & PLLE_MISC_READY));
 }
 
-static int tegra30_plle_configure(struct clk *c, bool force_training)
+static int tegra30_plle_configure(struct clk_hw *hw, bool force_training)
 {
-	u32 val;
+	struct clk_tegra *c = to_clk_tegra(hw);
+	struct clk *parent = __clk_get_parent(hw->clk);
 	const struct clk_pll_freq_table *sel;
+	u32 val;
+
 	unsigned long rate = c->u.pll.fixed_rate;
-	unsigned long input_rate = clk_get_rate(c->parent);
+	unsigned long input_rate = __clk_get_rate(parent);
 
 	for (sel = c->u.pll.freq_table; sel->input_rate != 0; sel++) {
 		if (sel->input_rate == input_rate && sel->output_rate == rate)
@@ -1214,7 +1423,7 @@ static int tegra30_plle_configure(struct clk *c, bool force_training)
 		return -ENOSYS;
 
 	/* disable PLLE, clear setup fiels */
-	tegra30_plle_clk_disable(c);
+	tegra30_plle_clk_disable(hw);
 
 	val = clk_readl(c->reg + PLL_MISC(c));
 	val &= ~(PLLE_MISC_LOCK_ENABLE | PLLE_MISC_SETUP_MASK);
@@ -1252,52 +1461,64 @@ static int tegra30_plle_configure(struct clk *c, bool force_training)
 	return 0;
 }
 
-static int tegra30_plle_clk_enable(struct clk *c)
+static int tegra30_plle_clk_enable(struct clk_hw *hw)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+
+	return tegra30_plle_configure(hw, !c->set);
+}
+
+static unsigned long tegra30_plle_clk_recalc_rate(struct clk_hw *hw,
+			unsigned long parent_rate)
 {
-	pr_debug("%s on clock %s\n", __func__, c->name);
-	return tegra30_plle_configure(c, !c->set);
+	struct clk_tegra *c = to_clk_tegra(hw);
+	unsigned long rate = parent_rate;
+	u32 val;
+
+	val = clk_readl(c->reg + PLL_BASE);
+	c->mul = (val & PLLE_BASE_DIVN_MASK) >> PLLE_BASE_DIVN_SHIFT;
+	c->div = (val & PLLE_BASE_DIVM_MASK) >> PLLE_BASE_DIVM_SHIFT;
+	c->div *= (val & PLLE_BASE_DIVP_MASK) >> PLLE_BASE_DIVP_SHIFT;
+
+	if (c->mul != 0 && c->div != 0) {
+		rate *= c->mul;
+		rate += c->div - 1; /* round up */
+		do_div(rate, c->div);
+	}
+	return rate;
 }
 
-static struct clk_ops tegra_plle_ops = {
-	.init			= tegra30_plle_clk_init,
-	.enable			= tegra30_plle_clk_enable,
-	.disable		= tegra30_plle_clk_disable,
+struct clk_ops tegra30_plle_ops = {
+	.is_enabled = tegra30_plle_clk_is_enabled,
+	.enable = tegra30_plle_clk_enable,
+	.disable = tegra30_plle_clk_disable,
+	.recalc_rate = tegra30_plle_clk_recalc_rate,
 };
 
 /* Clock divider ops */
-static void tegra30_pll_div_clk_init(struct clk *c)
+static int tegra30_pll_div_clk_is_enabled(struct clk_hw *hw)
 {
+	struct clk_tegra *c = to_clk_tegra(hw);
+
 	if (c->flags & DIV_U71) {
-		u32 divu71;
 		u32 val = clk_readl(c->reg);
 		val >>= c->reg_shift;
 		c->state = (val & PLL_OUT_CLKEN) ? ON : OFF;
 		if (!(val & PLL_OUT_RESET_DISABLE))
 			c->state = OFF;
-
-		divu71 = (val & PLL_OUT_RATIO_MASK) >> PLL_OUT_RATIO_SHIFT;
-		c->div = (divu71 + 2);
-		c->mul = 2;
-	} else if (c->flags & DIV_2) {
-		c->state = ON;
-		if (c->flags & (PLLD | PLLX)) {
-			c->div = 2;
-			c->mul = 1;
-		} else
-			BUG();
 	} else {
 		c->state = ON;
-		c->div = 1;
-		c->mul = 1;
 	}
+	return c->state;
 }
 
-static int tegra30_pll_div_clk_enable(struct clk *c)
+static int tegra30_pll_div_clk_enable(struct clk_hw *hw)
 {
+	struct clk_tegra *c = to_clk_tegra(hw);
 	u32 val;
 	u32 new_val;
 
-	pr_debug("%s: %s\n", __func__, c->name);
+	pr_debug("%s: %s\n", __func__, __clk_get_name(hw->clk));
 	if (c->flags & DIV_U71) {
 		val = clk_readl(c->reg);
 		new_val = val >> c->reg_shift;
@@ -1315,12 +1536,13 @@ static int tegra30_pll_div_clk_enable(struct clk *c)
 	return -EINVAL;
 }
 
-static void tegra30_pll_div_clk_disable(struct clk *c)
+static void tegra30_pll_div_clk_disable(struct clk_hw *hw)
 {
+	struct clk_tegra *c = to_clk_tegra(hw);
 	u32 val;
 	u32 new_val;
 
-	pr_debug("%s: %s\n", __func__, c->name);
+	pr_debug("%s: %s\n", __func__, __clk_get_name(hw->clk));
 	if (c->flags & DIV_U71) {
 		val = clk_readl(c->reg);
 		new_val = val >> c->reg_shift;
@@ -1334,14 +1556,14 @@ static void tegra30_pll_div_clk_disable(struct clk *c)
 	}
 }
 
-static int tegra30_pll_div_clk_set_rate(struct clk *c, unsigned long rate)
+static int tegra30_pll_div_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long parent_rate)
 {
+	struct clk_tegra *c = to_clk_tegra(hw);
 	u32 val;
 	u32 new_val;
 	int divider_u71;
-	unsigned long parent_rate = clk_get_rate(c->parent);
 
-	pr_debug("%s: %s %lu\n", __func__, c->name, rate);
 	if (c->flags & DIV_U71) {
 		divider_u71 = clk_div71_get_divider(
 			parent_rate, rate, c->flags, ROUND_DIVIDER_UP);
@@ -1359,19 +1581,59 @@ static int tegra30_pll_div_clk_set_rate(struct clk *c, unsigned long rate)
 			clk_writel_delay(val, c->reg);
 			c->div = divider_u71 + 2;
 			c->mul = 2;
+			c->fixed_rate = rate;
 			return 0;
 		}
-	} else if (c->flags & DIV_2)
-		return clk_set_rate(c->parent, rate * 2);
+	} else if (c->flags & DIV_2) {
+		c->fixed_rate = rate;
+		return 0;
+	}
 
 	return -EINVAL;
 }
 
-static long tegra30_pll_div_clk_round_rate(struct clk *c, unsigned long rate)
+static unsigned long tegra30_pll_div_clk_recalc_rate(struct clk_hw *hw,
+		unsigned long parent_rate)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+	u64 rate = parent_rate;
+
+	if (c->flags & DIV_U71) {
+		u32 divu71;
+		u32 val = clk_readl(c->reg);
+		val >>= c->reg_shift;
+
+		divu71 = (val & PLL_OUT_RATIO_MASK) >> PLL_OUT_RATIO_SHIFT;
+		c->div = (divu71 + 2);
+		c->mul = 2;
+	} else if (c->flags & DIV_2) {
+		if (c->flags & (PLLD | PLLX)) {
+			c->div = 2;
+			c->mul = 1;
+		} else
+			BUG();
+	} else {
+		c->div = 1;
+		c->mul = 1;
+	}
+	if (c->mul != 0 && c->div != 0) {
+		rate *= c->mul;
+		rate += c->div - 1; /* round up */
+		do_div(rate, c->div);
+	}
+
+	return rate;
+}
+
+static long tegra30_pll_div_clk_round_rate(struct clk_hw *hw,
+				unsigned long rate, unsigned long *prate)
 {
+	struct clk_tegra *c = to_clk_tegra(hw);
+	unsigned long parent_rate = __clk_get_rate(__clk_get_parent(hw->clk));
 	int divider;
-	unsigned long parent_rate = clk_get_rate(c->parent);
-	pr_debug("%s: %s %lu\n", __func__, c->name, rate);
+
+	if (prate)
+		parent_rate = *prate;
 
 	if (c->flags & DIV_U71) {
 		divider = clk_div71_get_divider(
@@ -1379,23 +1641,25 @@ static long tegra30_pll_div_clk_round_rate(struct clk *c, unsigned long rate)
 		if (divider < 0)
 			return divider;
 		return DIV_ROUND_UP(parent_rate * 2, divider + 2);
-	} else if (c->flags & DIV_2)
-		/* no rounding - fixed DIV_2 dividers pass rate to parent PLL */
+	} else if (c->flags & DIV_2) {
+		*prate = rate * 2;
 		return rate;
+	}
 
 	return -EINVAL;
 }
 
-static struct clk_ops tegra_pll_div_ops = {
-	.init			= tegra30_pll_div_clk_init,
-	.enable			= tegra30_pll_div_clk_enable,
-	.disable		= tegra30_pll_div_clk_disable,
-	.set_rate		= tegra30_pll_div_clk_set_rate,
-	.round_rate		= tegra30_pll_div_clk_round_rate,
+struct clk_ops tegra30_pll_div_ops = {
+	.is_enabled = tegra30_pll_div_clk_is_enabled,
+	.enable = tegra30_pll_div_clk_enable,
+	.disable = tegra30_pll_div_clk_disable,
+	.set_rate = tegra30_pll_div_clk_set_rate,
+	.recalc_rate = tegra30_pll_div_clk_recalc_rate,
+	.round_rate = tegra30_pll_div_clk_round_rate,
 };
 
 /* Periph clk ops */
-static inline u32 periph_clk_source_mask(struct clk *c)
+static inline u32 periph_clk_source_mask(struct clk_tegra *c)
 {
 	if (c->flags & MUX8)
 		return 7 << 29;
@@ -1409,7 +1673,7 @@ static inline u32 periph_clk_source_mask(struct clk *c)
 		return 3 << 30;
 }
 
-static inline u32 periph_clk_source_shift(struct clk *c)
+static inline u32 periph_clk_source_shift(struct clk_tegra *c)
 {
 	if (c->flags & MUX8)
 		return 29;
@@ -1423,47 +1687,9 @@ static inline u32 periph_clk_source_shift(struct clk *c)
 		return 30;
 }
 
-static void tegra30_periph_clk_init(struct clk *c)
+static int tegra30_periph_clk_is_enabled(struct clk_hw *hw)
 {
-	u32 val = clk_readl(c->reg);
-	const struct clk_mux_sel *mux = 0;
-	const struct clk_mux_sel *sel;
-	if (c->flags & MUX) {
-		for (sel = c->inputs; sel->input != NULL; sel++) {
-			if (((val & periph_clk_source_mask(c)) >>
-			    periph_clk_source_shift(c)) == sel->value)
-				mux = sel;
-		}
-		BUG_ON(!mux);
-
-		c->parent = mux->input;
-	} else {
-		c->parent = c->inputs[0].input;
-	}
-
-	if (c->flags & DIV_U71) {
-		u32 divu71 = val & PERIPH_CLK_SOURCE_DIVU71_MASK;
-		if ((c->flags & DIV_U71_UART) &&
-		    (!(val & PERIPH_CLK_UART_DIV_ENB))) {
-			divu71 = 0;
-		}
-		if (c->flags & DIV_U71_IDLE) {
-			val &= ~(PERIPH_CLK_SOURCE_DIVU71_MASK <<
-				PERIPH_CLK_SOURCE_DIVIDLE_SHIFT);
-			val |= (PERIPH_CLK_SOURCE_DIVIDLE_VAL <<
-				PERIPH_CLK_SOURCE_DIVIDLE_SHIFT);
-			clk_writel(val, c->reg);
-		}
-		c->div = divu71 + 2;
-		c->mul = 2;
-	} else if (c->flags & DIV_U16) {
-		u32 divu16 = val & PERIPH_CLK_SOURCE_DIVU16_MASK;
-		c->div = divu16 + 1;
-		c->mul = 1;
-	} else {
-		c->div = 1;
-		c->mul = 1;
-	}
+	struct clk_tegra *c = to_clk_tegra(hw);
 
 	c->state = ON;
 	if (!(clk_readl(PERIPH_CLK_TO_ENB_REG(c)) & PERIPH_CLK_TO_BIT(c)))
@@ -1471,11 +1697,12 @@ static void tegra30_periph_clk_init(struct clk *c)
 	if (!(c->flags & PERIPH_NO_RESET))
 		if (clk_readl(PERIPH_CLK_TO_RST_REG(c)) & PERIPH_CLK_TO_BIT(c))
 			c->state = OFF;
+	return c->state;
 }
 
-static int tegra30_periph_clk_enable(struct clk *c)
+static int tegra30_periph_clk_enable(struct clk_hw *hw)
 {
-	pr_debug("%s on clock %s\n", __func__, c->name);
+	struct clk_tegra *c = to_clk_tegra(hw);
 
 	tegra_periph_clk_enable_refcount[c->u.periph.clk_num]++;
 	if (tegra_periph_clk_enable_refcount[c->u.periph.clk_num] > 1)
@@ -1494,31 +1721,29 @@ static int tegra30_periph_clk_enable(struct clk *c)
 	return 0;
 }
 
-static void tegra30_periph_clk_disable(struct clk *c)
+static void tegra30_periph_clk_disable(struct clk_hw *hw)
 {
+	struct clk_tegra *c = to_clk_tegra(hw);
 	unsigned long val;
-	pr_debug("%s on clock %s\n", __func__, c->name);
 
-	if (c->refcnt)
-		tegra_periph_clk_enable_refcount[c->u.periph.clk_num]--;
+	tegra_periph_clk_enable_refcount[c->u.periph.clk_num]--;
+
+	if (tegra_periph_clk_enable_refcount[c->u.periph.clk_num] > 0)
+		return;
 
-	if (tegra_periph_clk_enable_refcount[c->u.periph.clk_num] == 0) {
-		/* If peripheral is in the APB bus then read the APB bus to
-		 * flush the write operation in apb bus. This will avoid the
-		 * peripheral access after disabling clock*/
-		if (c->flags & PERIPH_ON_APB)
-			val = chipid_readl();
+	/* If peripheral is in the APB bus then read the APB bus to
+	 * flush the write operation in apb bus. This will avoid the
+	 * peripheral access after disabling clock*/
+	if (c->flags & PERIPH_ON_APB)
+		val = chipid_readl();
 
-		clk_writel_delay(
-			PERIPH_CLK_TO_BIT(c), PERIPH_CLK_TO_ENB_CLR_REG(c));
-	}
+	clk_writel_delay(PERIPH_CLK_TO_BIT(c), PERIPH_CLK_TO_ENB_CLR_REG(c));
 }
 
-static void tegra30_periph_clk_reset(struct clk *c, bool assert)
+void tegra30_periph_clk_reset(struct clk_hw *hw, bool assert)
 {
+	struct clk_tegra *c = to_clk_tegra(hw);
 	unsigned long val;
-	pr_debug("%s %s on clock %s\n", __func__,
-		 assert ? "assert" : "deassert", c->name);
 
 	if (!(c->flags & PERIPH_NO_RESET)) {
 		if (assert) {
@@ -1537,42 +1762,40 @@ static void tegra30_periph_clk_reset(struct clk *c, bool assert)
 	}
 }
 
-static int tegra30_periph_clk_set_parent(struct clk *c, struct clk *p)
+static int tegra30_periph_clk_set_parent(struct clk_hw *hw, u8 index)
 {
+	struct clk_tegra *c = to_clk_tegra(hw);
 	u32 val;
-	const struct clk_mux_sel *sel;
-	pr_debug("%s: %s %s\n", __func__, c->name, p->name);
 
 	if (!(c->flags & MUX))
-		return (p == c->parent) ? 0 : (-EINVAL);
-
-	for (sel = c->inputs; sel->input != NULL; sel++) {
-		if (sel->input == p) {
-			val = clk_readl(c->reg);
-			val &= ~periph_clk_source_mask(c);
-			val |= (sel->value << periph_clk_source_shift(c));
+		return (index == 0) ? 0 : (-EINVAL);
 
-			if (c->refcnt)
-				clk_enable(p);
-
-			clk_writel_delay(val, c->reg);
+	val = clk_readl(c->reg);
+	val &= ~periph_clk_source_mask(c);
+	val |= (index << periph_clk_source_shift(c));
+	clk_writel_delay(val, c->reg);
+	return 0;
+}
 
-			if (c->refcnt && c->parent)
-				clk_disable(c->parent);
+static u8 tegra30_periph_clk_get_parent(struct clk_hw *hw)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+	u32 val = clk_readl(c->reg);
+	int source  = (val & periph_clk_source_mask(c)) >>
+					periph_clk_source_shift(c);
 
-			clk_reparent(c, p);
-			return 0;
-		}
-	}
+	if (!(c->flags & MUX))
+		return 0;
 
-	return -EINVAL;
+	return source;
 }
 
-static int tegra30_periph_clk_set_rate(struct clk *c, unsigned long rate)
+static int tegra30_periph_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long parent_rate)
 {
+	struct clk_tegra *c = to_clk_tegra(hw);
 	u32 val;
 	int divider;
-	unsigned long parent_rate = clk_get_rate(c->parent);
 
 	if (c->flags & DIV_U71) {
 		divider = clk_div71_get_divider(
@@ -1611,12 +1834,15 @@ static int tegra30_periph_clk_set_rate(struct clk *c, unsigned long rate)
 	return -EINVAL;
 }
 
-static long tegra30_periph_clk_round_rate(struct clk *c,
-	unsigned long rate)
+static long tegra30_periph_clk_round_rate(struct clk_hw *hw, unsigned long rate,
+				unsigned long *prate)
 {
+	struct clk_tegra *c = to_clk_tegra(hw);
+	unsigned long parent_rate = __clk_get_rate(__clk_get_parent(hw->clk));
 	int divider;
-	unsigned long parent_rate = clk_get_rate(c->parent);
-	pr_debug("%s: %s %lu\n", __func__, c->name, rate);
+
+	if (prate)
+		parent_rate = *prate;
 
 	if (c->flags & DIV_U71) {
 		divider = clk_div71_get_divider(
@@ -1634,21 +1860,85 @@ static long tegra30_periph_clk_round_rate(struct clk *c,
 	return -EINVAL;
 }
 
-static struct clk_ops tegra_periph_clk_ops = {
-	.init			= &tegra30_periph_clk_init,
+static unsigned long tegra30_periph_clk_recalc_rate(struct clk_hw *hw,
+		unsigned long parent_rate)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+	u64 rate = parent_rate;
+	u32 val = clk_readl(c->reg);
+
+	if (c->flags & DIV_U71) {
+		u32 divu71 = val & PERIPH_CLK_SOURCE_DIVU71_MASK;
+		if ((c->flags & DIV_U71_UART) &&
+		    (!(val & PERIPH_CLK_UART_DIV_ENB))) {
+			divu71 = 0;
+		}
+		if (c->flags & DIV_U71_IDLE) {
+			val &= ~(PERIPH_CLK_SOURCE_DIVU71_MASK <<
+				PERIPH_CLK_SOURCE_DIVIDLE_SHIFT);
+			val |= (PERIPH_CLK_SOURCE_DIVIDLE_VAL <<
+				PERIPH_CLK_SOURCE_DIVIDLE_SHIFT);
+			clk_writel(val, c->reg);
+		}
+		c->div = divu71 + 2;
+		c->mul = 2;
+	} else if (c->flags & DIV_U16) {
+		u32 divu16 = val & PERIPH_CLK_SOURCE_DIVU16_MASK;
+		c->div = divu16 + 1;
+		c->mul = 1;
+	} else {
+		c->div = 1;
+		c->mul = 1;
+	}
+
+	if (c->mul != 0 && c->div != 0) {
+		rate *= c->mul;
+		rate += c->div - 1; /* round up */
+		do_div(rate, c->div);
+	}
+	return rate;
+}
+
+struct clk_ops tegra30_periph_clk_ops = {
+	.is_enabled = tegra30_periph_clk_is_enabled,
+	.enable = tegra30_periph_clk_enable,
+	.disable = tegra30_periph_clk_disable,
+	.set_parent = tegra30_periph_clk_set_parent,
+	.get_parent = tegra30_periph_clk_get_parent,
+	.set_rate = tegra30_periph_clk_set_rate,
+	.round_rate = tegra30_periph_clk_round_rate,
+	.recalc_rate = tegra30_periph_clk_recalc_rate,
+};
+
+static int tegra30_dsib_clk_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct clk *d = clk_get_sys(NULL, "pll_d");
+	/* The DSIB parent selection bit is in PLLD base
+	   register - can not do direct r-m-w, must be
+	   protected by PLLD lock */
+	tegra_clk_cfg_ex(
+		d, TEGRA_CLK_PLLD_MIPI_MUX_SEL, index);
+
+	return 0;
+}
+
+struct clk_ops tegra30_dsib_clk_ops = {
+	.is_enabled = tegra30_periph_clk_is_enabled,
 	.enable			= &tegra30_periph_clk_enable,
 	.disable		= &tegra30_periph_clk_disable,
-	.set_parent		= &tegra30_periph_clk_set_parent,
+	.set_parent		= &tegra30_dsib_clk_set_parent,
+	.get_parent		= &tegra30_periph_clk_get_parent,
 	.set_rate		= &tegra30_periph_clk_set_rate,
 	.round_rate		= &tegra30_periph_clk_round_rate,
-	.reset			= &tegra30_periph_clk_reset,
+	.recalc_rate		= &tegra30_periph_clk_recalc_rate,
 };
 
-
 /* Periph extended clock configuration ops */
-static int
-tegra30_vi_clk_cfg_ex(struct clk *c, enum tegra_clk_ex_param p, u32 setting)
+int tegra30_vi_clk_cfg_ex(struct clk_hw *hw,
+				enum tegra_clk_ex_param p, u32 setting)
 {
+	struct clk_tegra *c = to_clk_tegra(hw);
+
 	if (p == TEGRA_CLK_VI_INP_SEL) {
 		u32 val = clk_readl(c->reg);
 		val &= ~PERIPH_CLK_VI_SEL_EX_MASK;
@@ -1660,20 +1950,11 @@ tegra30_vi_clk_cfg_ex(struct clk *c, enum tegra_clk_ex_param p, u32 setting)
 	return -EINVAL;
 }
 
-static struct clk_ops tegra_vi_clk_ops = {
-	.init			= &tegra30_periph_clk_init,
-	.enable			= &tegra30_periph_clk_enable,
-	.disable		= &tegra30_periph_clk_disable,
-	.set_parent		= &tegra30_periph_clk_set_parent,
-	.set_rate		= &tegra30_periph_clk_set_rate,
-	.round_rate		= &tegra30_periph_clk_round_rate,
-	.clk_cfg_ex		= &tegra30_vi_clk_cfg_ex,
-	.reset			= &tegra30_periph_clk_reset,
-};
-
-static int
-tegra30_nand_clk_cfg_ex(struct clk *c, enum tegra_clk_ex_param p, u32 setting)
+int tegra30_nand_clk_cfg_ex(struct clk_hw *hw,
+				enum tegra_clk_ex_param p, u32 setting)
 {
+	struct clk_tegra *c = to_clk_tegra(hw);
+
 	if (p == TEGRA_CLK_NAND_PAD_DIV2_ENB) {
 		u32 val = clk_readl(c->reg);
 		if (setting)
@@ -1686,21 +1967,11 @@ tegra30_nand_clk_cfg_ex(struct clk *c, enum tegra_clk_ex_param p, u32 setting)
 	return -EINVAL;
 }
 
-static struct clk_ops tegra_nand_clk_ops = {
-	.init			= &tegra30_periph_clk_init,
-	.enable			= &tegra30_periph_clk_enable,
-	.disable		= &tegra30_periph_clk_disable,
-	.set_parent		= &tegra30_periph_clk_set_parent,
-	.set_rate		= &tegra30_periph_clk_set_rate,
-	.round_rate		= &tegra30_periph_clk_round_rate,
-	.clk_cfg_ex		= &tegra30_nand_clk_cfg_ex,
-	.reset			= &tegra30_periph_clk_reset,
-};
-
-
-static int
-tegra30_dtv_clk_cfg_ex(struct clk *c, enum tegra_clk_ex_param p, u32 setting)
+int tegra30_dtv_clk_cfg_ex(struct clk_hw *hw,
+				enum tegra_clk_ex_param p, u32 setting)
 {
+	struct clk_tegra *c = to_clk_tegra(hw);
+
 	if (p == TEGRA_CLK_DTV_INVERT) {
 		u32 val = clk_readl(c->reg);
 		if (setting)
@@ -1713,91 +1984,27 @@ tegra30_dtv_clk_cfg_ex(struct clk *c, enum tegra_clk_ex_param p, u32 setting)
 	return -EINVAL;
 }
 
-static struct clk_ops tegra_dtv_clk_ops = {
-	.init			= &tegra30_periph_clk_init,
-	.enable			= &tegra30_periph_clk_enable,
-	.disable		= &tegra30_periph_clk_disable,
-	.set_parent		= &tegra30_periph_clk_set_parent,
-	.set_rate		= &tegra30_periph_clk_set_rate,
-	.round_rate		= &tegra30_periph_clk_round_rate,
-	.clk_cfg_ex		= &tegra30_dtv_clk_cfg_ex,
-	.reset			= &tegra30_periph_clk_reset,
-};
-
-static int tegra30_dsib_clk_set_parent(struct clk *c, struct clk *p)
-{
-	const struct clk_mux_sel *sel;
-	struct clk *d = tegra_get_clock_by_name("pll_d");
-
-	pr_debug("%s: %s %s\n", __func__, c->name, p->name);
-
-	for (sel = c->inputs; sel->input != NULL; sel++) {
-		if (sel->input == p) {
-			if (c->refcnt)
-				clk_enable(p);
-
-			/* The DSIB parent selection bit is in PLLD base
-			   register - can not do direct r-m-w, must be
-			   protected by PLLD lock */
-			tegra_clk_cfg_ex(
-				d, TEGRA_CLK_PLLD_MIPI_MUX_SEL, sel->value);
-
-			if (c->refcnt && c->parent)
-				clk_disable(c->parent);
-
-			clk_reparent(c, p);
-			return 0;
-		}
-	}
-
-	return -EINVAL;
-}
-
-static struct clk_ops tegra_dsib_clk_ops = {
-	.init			= &tegra30_periph_clk_init,
-	.enable			= &tegra30_periph_clk_enable,
-	.disable		= &tegra30_periph_clk_disable,
-	.set_parent		= &tegra30_dsib_clk_set_parent,
-	.set_rate		= &tegra30_periph_clk_set_rate,
-	.round_rate		= &tegra30_periph_clk_round_rate,
-	.reset			= &tegra30_periph_clk_reset,
-};
-
-/* pciex clock support only reset function */
-static struct clk_ops tegra_pciex_clk_ops = {
-	.reset    = tegra30_periph_clk_reset,
-};
-
 /* Output clock ops */
 
 static DEFINE_SPINLOCK(clk_out_lock);
 
-static void tegra30_clk_out_init(struct clk *c)
+static int tegra30_clk_out_is_enabled(struct clk_hw *hw)
 {
-	const struct clk_mux_sel *mux = 0;
-	const struct clk_mux_sel *sel;
+	struct clk_tegra *c = to_clk_tegra(hw);
 	u32 val = pmc_readl(c->reg);
 
 	c->state = (val & (0x1 << c->u.periph.clk_num)) ? ON : OFF;
 	c->mul = 1;
 	c->div = 1;
-
-	for (sel = c->inputs; sel->input != NULL; sel++) {
-		if (((val & periph_clk_source_mask(c)) >>
-		     periph_clk_source_shift(c)) == sel->value)
-			mux = sel;
-	}
-	BUG_ON(!mux);
-	c->parent = mux->input;
+	return c->state;
 }
 
-static int tegra30_clk_out_enable(struct clk *c)
+static int tegra30_clk_out_enable(struct clk_hw *hw)
 {
+	struct clk_tegra *c = to_clk_tegra(hw);
 	u32 val;
 	unsigned long flags;
 
-	pr_debug("%s on clock %s\n", __func__, c->name);
-
 	spin_lock_irqsave(&clk_out_lock, flags);
 	val = pmc_readl(c->reg);
 	val |= (0x1 << c->u.periph.clk_num);
@@ -1807,13 +2014,12 @@ static int tegra30_clk_out_enable(struct clk *c)
 	return 0;
 }
 
-static void tegra30_clk_out_disable(struct clk *c)
+static void tegra30_clk_out_disable(struct clk_hw *hw)
 {
+	struct clk_tegra *c = to_clk_tegra(hw);
 	u32 val;
 	unsigned long flags;
 
-	pr_debug("%s on clock %s\n", __func__, c->name);
-
 	spin_lock_irqsave(&clk_out_lock, flags);
 	val = pmc_readl(c->reg);
 	val &= ~(0x1 << c->u.periph.clk_num);
@@ -1821,59 +2027,59 @@ static void tegra30_clk_out_disable(struct clk *c)
 	spin_unlock_irqrestore(&clk_out_lock, flags);
 }
 
-static int tegra30_clk_out_set_parent(struct clk *c, struct clk *p)
+static int tegra30_clk_out_set_parent(struct clk_hw *hw, u8 index)
 {
+	struct clk_tegra *c = to_clk_tegra(hw);
 	u32 val;
 	unsigned long flags;
-	const struct clk_mux_sel *sel;
-
-	pr_debug("%s: %s %s\n", __func__, c->name, p->name);
 
-	for (sel = c->inputs; sel->input != NULL; sel++) {
-		if (sel->input == p) {
-			if (c->refcnt)
-				clk_enable(p);
+	spin_lock_irqsave(&clk_out_lock, flags);
+	val = pmc_readl(c->reg);
+	val &= ~periph_clk_source_mask(c);
+	val |= (index << periph_clk_source_shift(c));
+	pmc_writel(val, c->reg);
+	spin_unlock_irqrestore(&clk_out_lock, flags);
 
-			spin_lock_irqsave(&clk_out_lock, flags);
-			val = pmc_readl(c->reg);
-			val &= ~periph_clk_source_mask(c);
-			val |= (sel->value << periph_clk_source_shift(c));
-			pmc_writel(val, c->reg);
-			spin_unlock_irqrestore(&clk_out_lock, flags);
+	return 0;
+}
 
-			if (c->refcnt && c->parent)
-				clk_disable(c->parent);
+static u8 tegra30_clk_out_get_parent(struct clk_hw *hw)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+	u32 val = pmc_readl(c->reg);
+	int source;
 
-			clk_reparent(c, p);
-			return 0;
-		}
-	}
-	return -EINVAL;
+	source = (val & periph_clk_source_mask(c)) >>
+				periph_clk_source_shift(c);
+	return source;
 }
 
-static struct clk_ops tegra_clk_out_ops = {
-	.init			= &tegra30_clk_out_init,
-	.enable			= &tegra30_clk_out_enable,
-	.disable		= &tegra30_clk_out_disable,
-	.set_parent		= &tegra30_clk_out_set_parent,
+struct clk_ops tegra_clk_out_ops = {
+	.is_enabled = tegra30_clk_out_is_enabled,
+	.enable = tegra30_clk_out_enable,
+	.disable = tegra30_clk_out_disable,
+	.set_parent = tegra30_clk_out_set_parent,
+	.get_parent = tegra30_clk_out_get_parent,
+	.recalc_rate = tegra30_clk_fixed_recalc_rate,
 };
 
-
 /* Clock doubler ops */
-static void tegra30_clk_double_init(struct clk *c)
+static int tegra30_clk_double_is_enabled(struct clk_hw *hw)
 {
-	u32 val = clk_readl(c->reg);
-	c->mul = val & (0x1 << c->reg_shift) ? 1 : 2;
-	c->div = 1;
+	struct clk_tegra *c = to_clk_tegra(hw);
+
 	c->state = ON;
 	if (!(clk_readl(PERIPH_CLK_TO_ENB_REG(c)) & PERIPH_CLK_TO_BIT(c)))
 		c->state = OFF;
+	return c->state;
 };
 
-static int tegra30_clk_double_set_rate(struct clk *c, unsigned long rate)
+static int tegra30_clk_double_set_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long parent_rate)
 {
+	struct clk_tegra *c = to_clk_tegra(hw);
 	u32 val;
-	unsigned long parent_rate = clk_get_rate(c->parent);
+
 	if (rate == parent_rate) {
 		val = clk_readl(c->reg) | (0x1 << c->reg_shift);
 		clk_writel(val, c->reg);
@@ -1890,1215 +2096,200 @@ static int tegra30_clk_double_set_rate(struct clk *c, unsigned long rate)
 	return -EINVAL;
 }
 
-static struct clk_ops tegra_clk_double_ops = {
-	.init			= &tegra30_clk_double_init,
-	.enable			= &tegra30_periph_clk_enable,
-	.disable		= &tegra30_periph_clk_disable,
-	.set_rate		= &tegra30_clk_double_set_rate,
-};
+static unsigned long tegra30_clk_double_recalc_rate(struct clk_hw *hw,
+		unsigned long parent_rate)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+	u64 rate = parent_rate;
 
-/* Audio sync clock ops */
-static int tegra30_sync_source_set_rate(struct clk *c, unsigned long rate)
+	u32 val = clk_readl(c->reg);
+	c->mul = val & (0x1 << c->reg_shift) ? 1 : 2;
+	c->div = 1;
+
+	if (c->mul != 0 && c->div != 0) {
+		rate *= c->mul;
+		rate += c->div - 1; /* round up */
+		do_div(rate, c->div);
+	}
+
+	return rate;
+}
+
+static long tegra30_clk_double_round_rate(struct clk_hw *hw, unsigned long rate,
+				unsigned long *prate)
 {
-	c->rate = rate;
-	return 0;
+	unsigned long output_rate = *prate;
+
+	do_div(output_rate, 2);
+	return output_rate;
 }
 
-static struct clk_ops tegra_sync_source_ops = {
-	.set_rate		= &tegra30_sync_source_set_rate,
+struct clk_ops tegra30_clk_double_ops = {
+	.is_enabled = tegra30_clk_double_is_enabled,
+	.enable = tegra30_periph_clk_enable,
+	.disable = tegra30_periph_clk_disable,
+	.recalc_rate = tegra30_clk_double_recalc_rate,
+	.round_rate = tegra30_clk_double_round_rate,
+	.set_rate = tegra30_clk_double_set_rate,
+};
+
+/* Audio sync clock ops */
+struct clk_ops tegra_sync_source_ops = {
+	.recalc_rate = tegra30_clk_fixed_recalc_rate,
 };
 
-static void tegra30_audio_sync_clk_init(struct clk *c)
+static int tegra30_audio_sync_clk_is_enabled(struct clk_hw *hw)
 {
-	int source;
-	const struct clk_mux_sel *sel;
+	struct clk_tegra *c = to_clk_tegra(hw);
 	u32 val = clk_readl(c->reg);
 	c->state = (val & AUDIO_SYNC_DISABLE_BIT) ? OFF : ON;
-	source = val & AUDIO_SYNC_SOURCE_MASK;
-	for (sel = c->inputs; sel->input != NULL; sel++)
-		if (sel->value == source)
-			break;
-	BUG_ON(sel->input == NULL);
-	c->parent = sel->input;
+	return c->state;
 }
 
-static int tegra30_audio_sync_clk_enable(struct clk *c)
+static int tegra30_audio_sync_clk_enable(struct clk_hw *hw)
 {
+	struct clk_tegra *c = to_clk_tegra(hw);
 	u32 val = clk_readl(c->reg);
 	clk_writel((val & (~AUDIO_SYNC_DISABLE_BIT)), c->reg);
 	return 0;
 }
 
-static void tegra30_audio_sync_clk_disable(struct clk *c)
+static void tegra30_audio_sync_clk_disable(struct clk_hw *hw)
 {
+	struct clk_tegra *c = to_clk_tegra(hw);
 	u32 val = clk_readl(c->reg);
 	clk_writel((val | AUDIO_SYNC_DISABLE_BIT), c->reg);
 }
 
-static int tegra30_audio_sync_clk_set_parent(struct clk *c, struct clk *p)
+static int tegra30_audio_sync_clk_set_parent(struct clk_hw *hw, u8 index)
 {
+	struct clk_tegra *c = to_clk_tegra(hw);
 	u32 val;
-	const struct clk_mux_sel *sel;
-	for (sel = c->inputs; sel->input != NULL; sel++) {
-		if (sel->input == p) {
-			val = clk_readl(c->reg);
-			val &= ~AUDIO_SYNC_SOURCE_MASK;
-			val |= sel->value;
 
-			if (c->refcnt)
-				clk_enable(p);
-
-			clk_writel(val, c->reg);
+	val = clk_readl(c->reg);
+	val &= ~AUDIO_SYNC_SOURCE_MASK;
+	val |= index;
 
-			if (c->refcnt && c->parent)
-				clk_disable(c->parent);
+	clk_writel(val, c->reg);
+	return 0;
+}
 
-			clk_reparent(c, p);
-			return 0;
-		}
-	}
+static u8 tegra30_audio_sync_clk_get_parent(struct clk_hw *hw)
+{
+	struct clk_tegra *c = to_clk_tegra(hw);
+	u32 val = clk_readl(c->reg);
+	int source;
 
-	return -EINVAL;
+	source = val & AUDIO_SYNC_SOURCE_MASK;
+	return source;
 }
 
-static struct clk_ops tegra_audio_sync_clk_ops = {
-	.init       = tegra30_audio_sync_clk_init,
-	.enable     = tegra30_audio_sync_clk_enable,
-	.disable    = tegra30_audio_sync_clk_disable,
+struct clk_ops tegra30_audio_sync_clk_ops = {
+	.is_enabled = tegra30_audio_sync_clk_is_enabled,
+	.enable = tegra30_audio_sync_clk_enable,
+	.disable = tegra30_audio_sync_clk_disable,
 	.set_parent = tegra30_audio_sync_clk_set_parent,
+	.get_parent = tegra30_audio_sync_clk_get_parent,
+	.recalc_rate = tegra30_clk_fixed_recalc_rate,
 };
 
 /* cml0 (pcie), and cml1 (sata) clock ops */
-static void tegra30_cml_clk_init(struct clk *c)
+static int tegra30_cml_clk_is_enabled(struct clk_hw *hw)
 {
+	struct clk_tegra *c = to_clk_tegra(hw);
 	u32 val = clk_readl(c->reg);
 	c->state = val & (0x1 << c->u.periph.clk_num) ? ON : OFF;
+	return c->state;
 }
 
-static int tegra30_cml_clk_enable(struct clk *c)
+static int tegra30_cml_clk_enable(struct clk_hw *hw)
 {
+	struct clk_tegra *c = to_clk_tegra(hw);
+
 	u32 val = clk_readl(c->reg);
 	val |= (0x1 << c->u.periph.clk_num);
 	clk_writel(val, c->reg);
+
 	return 0;
 }
 
-static void tegra30_cml_clk_disable(struct clk *c)
+static void tegra30_cml_clk_disable(struct clk_hw *hw)
 {
+	struct clk_tegra *c = to_clk_tegra(hw);
+
 	u32 val = clk_readl(c->reg);
 	val &= ~(0x1 << c->u.periph.clk_num);
 	clk_writel(val, c->reg);
 }
 
-static struct clk_ops tegra_cml_clk_ops = {
-	.init			= &tegra30_cml_clk_init,
-	.enable			= &tegra30_cml_clk_enable,
-	.disable		= &tegra30_cml_clk_disable,
-};
-
-/* Clock definitions */
-static struct clk tegra_clk_32k = {
-	.name = "clk_32k",
-	.rate = 32768,
-	.ops  = NULL,
-	.max_rate = 32768,
-};
-
-static struct clk tegra_clk_m = {
-	.name      = "clk_m",
-	.flags     = ENABLE_ON_INIT,
-	.ops       = &tegra_clk_m_ops,
-	.reg       = 0x1fc,
-	.reg_shift = 28,
-	.max_rate  = 48000000,
-};
-
-static struct clk tegra_clk_m_div2 = {
-	.name      = "clk_m_div2",
-	.ops       = &tegra_clk_m_div_ops,
-	.parent    = &tegra_clk_m,
-	.mul       = 1,
-	.div       = 2,
-	.state     = ON,
-	.max_rate  = 24000000,
-};
-
-static struct clk tegra_clk_m_div4 = {
-	.name      = "clk_m_div4",
-	.ops       = &tegra_clk_m_div_ops,
-	.parent    = &tegra_clk_m,
-	.mul       = 1,
-	.div       = 4,
-	.state     = ON,
-	.max_rate  = 12000000,
-};
-
-static struct clk tegra_pll_ref = {
-	.name      = "pll_ref",
-	.flags     = ENABLE_ON_INIT,
-	.ops       = &tegra_pll_ref_ops,
-	.parent    = &tegra_clk_m,
-	.max_rate  = 26000000,
-};
-
-static struct clk_pll_freq_table tegra_pll_c_freq_table[] = {
-	{ 12000000, 1040000000, 520,  6, 1, 8},
-	{ 13000000, 1040000000, 480,  6, 1, 8},
-	{ 16800000, 1040000000, 495,  8, 1, 8},		/* actual: 1039.5 MHz */
-	{ 19200000, 1040000000, 325,  6, 1, 6},
-	{ 26000000, 1040000000, 520, 13, 1, 8},
-
-	{ 12000000, 832000000, 416,  6, 1, 8},
-	{ 13000000, 832000000, 832, 13, 1, 8},
-	{ 16800000, 832000000, 396,  8, 1, 8},		/* actual: 831.6 MHz */
-	{ 19200000, 832000000, 260,  6, 1, 8},
-	{ 26000000, 832000000, 416, 13, 1, 8},
-
-	{ 12000000, 624000000, 624, 12, 1, 8},
-	{ 13000000, 624000000, 624, 13, 1, 8},
-	{ 16800000, 600000000, 520, 14, 1, 8},
-	{ 19200000, 624000000, 520, 16, 1, 8},
-	{ 26000000, 624000000, 624, 26, 1, 8},
-
-	{ 12000000, 600000000, 600, 12, 1, 8},
-	{ 13000000, 600000000, 600, 13, 1, 8},
-	{ 16800000, 600000000, 500, 14, 1, 8},
-	{ 19200000, 600000000, 375, 12, 1, 6},
-	{ 26000000, 600000000, 600, 26, 1, 8},
-
-	{ 12000000, 520000000, 520, 12, 1, 8},
-	{ 13000000, 520000000, 520, 13, 1, 8},
-	{ 16800000, 520000000, 495, 16, 1, 8},		/* actual: 519.75 MHz */
-	{ 19200000, 520000000, 325, 12, 1, 6},
-	{ 26000000, 520000000, 520, 26, 1, 8},
-
-	{ 12000000, 416000000, 416, 12, 1, 8},
-	{ 13000000, 416000000, 416, 13, 1, 8},
-	{ 16800000, 416000000, 396, 16, 1, 8},		/* actual: 415.8 MHz */
-	{ 19200000, 416000000, 260, 12, 1, 6},
-	{ 26000000, 416000000, 416, 26, 1, 8},
-	{ 0, 0, 0, 0, 0, 0 },
-};
-
-static struct clk tegra_pll_c = {
-	.name      = "pll_c",
-	.flags	   = PLL_HAS_CPCON,
-	.ops       = &tegra_pll_ops,
-	.reg       = 0x80,
-	.parent    = &tegra_pll_ref,
-	.max_rate  = 1400000000,
-	.u.pll = {
-		.input_min = 2000000,
-		.input_max = 31000000,
-		.cf_min    = 1000000,
-		.cf_max    = 6000000,
-		.vco_min   = 20000000,
-		.vco_max   = 1400000000,
-		.freq_table = tegra_pll_c_freq_table,
-		.lock_delay = 300,
-	},
-};
-
-static struct clk tegra_pll_c_out1 = {
-	.name      = "pll_c_out1",
-	.ops       = &tegra_pll_div_ops,
-	.flags     = DIV_U71,
-	.parent    = &tegra_pll_c,
-	.reg       = 0x84,
-	.reg_shift = 0,
-	.max_rate  = 700000000,
-};
-
-static struct clk_pll_freq_table tegra_pll_m_freq_table[] = {
-	{ 12000000, 666000000, 666, 12, 1, 8},
-	{ 13000000, 666000000, 666, 13, 1, 8},
-	{ 16800000, 666000000, 555, 14, 1, 8},
-	{ 19200000, 666000000, 555, 16, 1, 8},
-	{ 26000000, 666000000, 666, 26, 1, 8},
-	{ 12000000, 600000000, 600, 12, 1, 8},
-	{ 13000000, 600000000, 600, 13, 1, 8},
-	{ 16800000, 600000000, 500, 14, 1, 8},
-	{ 19200000, 600000000, 375, 12, 1, 6},
-	{ 26000000, 600000000, 600, 26, 1, 8},
-	{ 0, 0, 0, 0, 0, 0 },
-};
-
-static struct clk tegra_pll_m = {
-	.name      = "pll_m",
-	.flags     = PLL_HAS_CPCON | PLLM,
-	.ops       = &tegra_pll_ops,
-	.reg       = 0x90,
-	.parent    = &tegra_pll_ref,
-	.max_rate  = 800000000,
-	.u.pll = {
-		.input_min = 2000000,
-		.input_max = 31000000,
-		.cf_min    = 1000000,
-		.cf_max    = 6000000,
-		.vco_min   = 20000000,
-		.vco_max   = 1200000000,
-		.freq_table = tegra_pll_m_freq_table,
-		.lock_delay = 300,
-	},
-};
-
-static struct clk tegra_pll_m_out1 = {
-	.name      = "pll_m_out1",
-	.ops       = &tegra_pll_div_ops,
-	.flags     = DIV_U71,
-	.parent    = &tegra_pll_m,
-	.reg       = 0x94,
-	.reg_shift = 0,
-	.max_rate  = 600000000,
-};
-
-static struct clk_pll_freq_table tegra_pll_p_freq_table[] = {
-	{ 12000000, 216000000, 432, 12, 2, 8},
-	{ 13000000, 216000000, 432, 13, 2, 8},
-	{ 16800000, 216000000, 360, 14, 2, 8},
-	{ 19200000, 216000000, 360, 16, 2, 8},
-	{ 26000000, 216000000, 432, 26, 2, 8},
-	{ 0, 0, 0, 0, 0, 0 },
-};
-
-static struct clk tegra_pll_p = {
-	.name      = "pll_p",
-	.flags     = ENABLE_ON_INIT | PLL_FIXED | PLL_HAS_CPCON,
-	.ops       = &tegra_pll_ops,
-	.reg       = 0xa0,
-	.parent    = &tegra_pll_ref,
-	.max_rate  = 432000000,
-	.u.pll = {
-		.input_min = 2000000,
-		.input_max = 31000000,
-		.cf_min    = 1000000,
-		.cf_max    = 6000000,
-		.vco_min   = 20000000,
-		.vco_max   = 1400000000,
-		.freq_table = tegra_pll_p_freq_table,
-		.lock_delay = 300,
-		.fixed_rate = 408000000,
-	},
-};
-
-static struct clk tegra_pll_p_out1 = {
-	.name      = "pll_p_out1",
-	.ops       = &tegra_pll_div_ops,
-	.flags     = ENABLE_ON_INIT | DIV_U71 | DIV_U71_FIXED,
-	.parent    = &tegra_pll_p,
-	.reg       = 0xa4,
-	.reg_shift = 0,
-	.max_rate  = 432000000,
-};
-
-static struct clk tegra_pll_p_out2 = {
-	.name      = "pll_p_out2",
-	.ops       = &tegra_pll_div_ops,
-	.flags     = ENABLE_ON_INIT | DIV_U71 | DIV_U71_FIXED,
-	.parent    = &tegra_pll_p,
-	.reg       = 0xa4,
-	.reg_shift = 16,
-	.max_rate  = 432000000,
-};
-
-static struct clk tegra_pll_p_out3 = {
-	.name      = "pll_p_out3",
-	.ops       = &tegra_pll_div_ops,
-	.flags     = ENABLE_ON_INIT | DIV_U71 | DIV_U71_FIXED,
-	.parent    = &tegra_pll_p,
-	.reg       = 0xa8,
-	.reg_shift = 0,
-	.max_rate  = 432000000,
-};
-
-static struct clk tegra_pll_p_out4 = {
-	.name      = "pll_p_out4",
-	.ops       = &tegra_pll_div_ops,
-	.flags     = ENABLE_ON_INIT | DIV_U71 | DIV_U71_FIXED,
-	.parent    = &tegra_pll_p,
-	.reg       = 0xa8,
-	.reg_shift = 16,
-	.max_rate  = 432000000,
-};
-
-static struct clk_pll_freq_table tegra_pll_a_freq_table[] = {
-	{ 9600000, 564480000, 294, 5, 1, 4},
-	{ 9600000, 552960000, 288, 5, 1, 4},
-	{ 9600000, 24000000,  5,   2, 1, 1},
-
-	{ 28800000, 56448000, 49, 25, 1, 1},
-	{ 28800000, 73728000, 64, 25, 1, 1},
-	{ 28800000, 24000000,  5,  6, 1, 1},
-	{ 0, 0, 0, 0, 0, 0 },
-};
-
-static struct clk tegra_pll_a = {
-	.name      = "pll_a",
-	.flags     = PLL_HAS_CPCON,
-	.ops       = &tegra_pll_ops,
-	.reg       = 0xb0,
-	.parent    = &tegra_pll_p_out1,
-	.max_rate  = 700000000,
-	.u.pll = {
-		.input_min = 2000000,
-		.input_max = 31000000,
-		.cf_min    = 1000000,
-		.cf_max    = 6000000,
-		.vco_min   = 20000000,
-		.vco_max   = 1400000000,
-		.freq_table = tegra_pll_a_freq_table,
-		.lock_delay = 300,
-	},
+struct clk_ops tegra_cml_clk_ops = {
+	.is_enabled = tegra30_cml_clk_is_enabled,
+	.enable = tegra30_cml_clk_enable,
+	.disable = tegra30_cml_clk_disable,
+	.recalc_rate = tegra30_clk_fixed_recalc_rate,
 };
 
-static struct clk tegra_pll_a_out0 = {
-	.name      = "pll_a_out0",
-	.ops       = &tegra_pll_div_ops,
-	.flags     = DIV_U71,
-	.parent    = &tegra_pll_a,
-	.reg       = 0xb4,
-	.reg_shift = 0,
-	.max_rate  = 100000000,
+struct clk_ops tegra_pciex_clk_ops = {
+	.recalc_rate = tegra30_clk_fixed_recalc_rate,
 };
 
-static struct clk_pll_freq_table tegra_pll_d_freq_table[] = {
-	{ 12000000, 216000000, 216, 12, 1, 4},
-	{ 13000000, 216000000, 216, 13, 1, 4},
-	{ 16800000, 216000000, 180, 14, 1, 4},
-	{ 19200000, 216000000, 180, 16, 1, 4},
-	{ 26000000, 216000000, 216, 26, 1, 4},
-
-	{ 12000000, 594000000, 594, 12, 1, 8},
-	{ 13000000, 594000000, 594, 13, 1, 8},
-	{ 16800000, 594000000, 495, 14, 1, 8},
-	{ 19200000, 594000000, 495, 16, 1, 8},
-	{ 26000000, 594000000, 594, 26, 1, 8},
-
-	{ 12000000, 1000000000, 1000, 12, 1, 12},
-	{ 13000000, 1000000000, 1000, 13, 1, 12},
-	{ 19200000, 1000000000, 625,  12, 1, 8},
-	{ 26000000, 1000000000, 1000, 26, 1, 12},
-
-	{ 0, 0, 0, 0, 0, 0 },
-};
-
-static struct clk tegra_pll_d = {
-	.name      = "pll_d",
-	.flags     = PLL_HAS_CPCON | PLLD,
-	.ops       = &tegra_plld_ops,
-	.reg       = 0xd0,
-	.parent    = &tegra_pll_ref,
-	.max_rate  = 1000000000,
-	.u.pll = {
-		.input_min = 2000000,
-		.input_max = 40000000,
-		.cf_min    = 1000000,
-		.cf_max    = 6000000,
-		.vco_min   = 40000000,
-		.vco_max   = 1000000000,
-		.freq_table = tegra_pll_d_freq_table,
-		.lock_delay = 1000,
-	},
-};
-
-static struct clk tegra_pll_d_out0 = {
-	.name      = "pll_d_out0",
-	.ops       = &tegra_pll_div_ops,
-	.flags     = DIV_2 | PLLD,
-	.parent    = &tegra_pll_d,
-	.max_rate  = 500000000,
-};
-
-static struct clk tegra_pll_d2 = {
-	.name      = "pll_d2",
-	.flags     = PLL_HAS_CPCON | PLL_ALT_MISC_REG | PLLD,
-	.ops       = &tegra_plld_ops,
-	.reg       = 0x4b8,
-	.parent    = &tegra_pll_ref,
-	.max_rate  = 1000000000,
-	.u.pll = {
-		.input_min = 2000000,
-		.input_max = 40000000,
-		.cf_min    = 1000000,
-		.cf_max    = 6000000,
-		.vco_min   = 40000000,
-		.vco_max   = 1000000000,
-		.freq_table = tegra_pll_d_freq_table,
-		.lock_delay = 1000,
-	},
-};
-
-static struct clk tegra_pll_d2_out0 = {
-	.name      = "pll_d2_out0",
-	.ops       = &tegra_pll_div_ops,
-	.flags     = DIV_2 | PLLD,
-	.parent    = &tegra_pll_d2,
-	.max_rate  = 500000000,
-};
-
-static struct clk_pll_freq_table tegra_pll_u_freq_table[] = {
-	{ 12000000, 480000000, 960, 12, 2, 12},
-	{ 13000000, 480000000, 960, 13, 2, 12},
-	{ 16800000, 480000000, 400, 7,  2, 5},
-	{ 19200000, 480000000, 200, 4,  2, 3},
-	{ 26000000, 480000000, 960, 26, 2, 12},
-	{ 0, 0, 0, 0, 0, 0 },
-};
-
-static struct clk tegra_pll_u = {
-	.name      = "pll_u",
-	.flags     = PLL_HAS_CPCON | PLLU,
-	.ops       = &tegra_pll_ops,
-	.reg       = 0xc0,
-	.parent    = &tegra_pll_ref,
-	.max_rate  = 480000000,
-	.u.pll = {
-		.input_min = 2000000,
-		.input_max = 40000000,
-		.cf_min    = 1000000,
-		.cf_max    = 6000000,
-		.vco_min   = 480000000,
-		.vco_max   = 960000000,
-		.freq_table = tegra_pll_u_freq_table,
-		.lock_delay = 1000,
-	},
-};
-
-static struct clk_pll_freq_table tegra_pll_x_freq_table[] = {
-	/* 1.7 GHz */
-	{ 12000000, 1700000000, 850,  6,  1, 8},
-	{ 13000000, 1700000000, 915,  7,  1, 8},	/* actual: 1699.2 MHz */
-	{ 16800000, 1700000000, 708,  7,  1, 8},	/* actual: 1699.2 MHz */
-	{ 19200000, 1700000000, 885,  10, 1, 8},	/* actual: 1699.2 MHz */
-	{ 26000000, 1700000000, 850,  13, 1, 8},
-
-	/* 1.6 GHz */
-	{ 12000000, 1600000000, 800,  6,  1, 8},
-	{ 13000000, 1600000000, 738,  6,  1, 8},	/* actual: 1599.0 MHz */
-	{ 16800000, 1600000000, 857,  9,  1, 8},	/* actual: 1599.7 MHz */
-	{ 19200000, 1600000000, 500,  6,  1, 8},
-	{ 26000000, 1600000000, 800,  13, 1, 8},
-
-	/* 1.5 GHz */
-	{ 12000000, 1500000000, 750,  6,  1, 8},
-	{ 13000000, 1500000000, 923,  8,  1, 8},	/* actual: 1499.8 MHz */
-	{ 16800000, 1500000000, 625,  7,  1, 8},
-	{ 19200000, 1500000000, 625,  8,  1, 8},
-	{ 26000000, 1500000000, 750,  13, 1, 8},
-
-	/* 1.4 GHz */
-	{ 12000000, 1400000000, 700,  6,  1, 8},
-	{ 13000000, 1400000000, 969,  9,  1, 8},	/* actual: 1399.7 MHz */
-	{ 16800000, 1400000000, 1000, 12, 1, 8},
-	{ 19200000, 1400000000, 875,  12, 1, 8},
-	{ 26000000, 1400000000, 700,  13, 1, 8},
-
-	/* 1.3 GHz */
-	{ 12000000, 1300000000, 975,  9,  1, 8},
-	{ 13000000, 1300000000, 1000, 10, 1, 8},
-	{ 16800000, 1300000000, 928,  12, 1, 8},	/* actual: 1299.2 MHz */
-	{ 19200000, 1300000000, 812,  12, 1, 8},	/* actual: 1299.2 MHz */
-	{ 26000000, 1300000000, 650,  13, 1, 8},
-
-	/* 1.2 GHz */
-	{ 12000000, 1200000000, 1000, 10, 1, 8},
-	{ 13000000, 1200000000, 923,  10, 1, 8},	/* actual: 1199.9 MHz */
-	{ 16800000, 1200000000, 1000, 14, 1, 8},
-	{ 19200000, 1200000000, 1000, 16, 1, 8},
-	{ 26000000, 1200000000, 600,  13, 1, 8},
-
-	/* 1.1 GHz */
-	{ 12000000, 1100000000, 825,  9,  1, 8},
-	{ 13000000, 1100000000, 846,  10, 1, 8},	/* actual: 1099.8 MHz */
-	{ 16800000, 1100000000, 982,  15, 1, 8},	/* actual: 1099.8 MHz */
-	{ 19200000, 1100000000, 859,  15, 1, 8},	/* actual: 1099.5 MHz */
-	{ 26000000, 1100000000, 550,  13, 1, 8},
-
-	/* 1 GHz */
-	{ 12000000, 1000000000, 1000, 12, 1, 8},
-	{ 13000000, 1000000000, 1000, 13, 1, 8},
-	{ 16800000, 1000000000, 833,  14, 1, 8},	/* actual: 999.6 MHz */
-	{ 19200000, 1000000000, 625,  12, 1, 8},
-	{ 26000000, 1000000000, 1000, 26, 1, 8},
-
-	{ 0, 0, 0, 0, 0, 0 },
-};
-
-static struct clk tegra_pll_x = {
-	.name      = "pll_x",
-	.flags     = PLL_HAS_CPCON | PLL_ALT_MISC_REG | PLLX,
-	.ops       = &tegra_pll_ops,
-	.reg       = 0xe0,
-	.parent    = &tegra_pll_ref,
-	.max_rate  = 1700000000,
-	.u.pll = {
-		.input_min = 2000000,
-		.input_max = 31000000,
-		.cf_min    = 1000000,
-		.cf_max    = 6000000,
-		.vco_min   = 20000000,
-		.vco_max   = 1700000000,
-		.freq_table = tegra_pll_x_freq_table,
-		.lock_delay = 300,
-	},
-};
-
-static struct clk tegra_pll_x_out0 = {
-	.name      = "pll_x_out0",
-	.ops       = &tegra_pll_div_ops,
-	.flags     = DIV_2 | PLLX,
-	.parent    = &tegra_pll_x,
-	.max_rate  = 850000000,
-};
-
-
-static struct clk_pll_freq_table tegra_pll_e_freq_table[] = {
-	/* PLLE special case: use cpcon field to store cml divider value */
-	{ 12000000,  100000000, 150, 1,  18, 11},
-	{ 216000000, 100000000, 200, 18, 24, 13},
-	{ 0, 0, 0, 0, 0, 0 },
-};
-
-static struct clk tegra_pll_e = {
-	.name      = "pll_e",
-	.flags     = PLL_ALT_MISC_REG,
-	.ops       = &tegra_plle_ops,
-	.reg       = 0xe8,
-	.max_rate  = 100000000,
-	.u.pll = {
-		.input_min = 12000000,
-		.input_max = 216000000,
-		.cf_min    = 12000000,
-		.cf_max    = 12000000,
-		.vco_min   = 1200000000,
-		.vco_max   = 2400000000U,
-		.freq_table = tegra_pll_e_freq_table,
-		.lock_delay = 300,
-		.fixed_rate = 100000000,
-	},
-};
-
-static struct clk tegra_cml0_clk = {
-	.name      = "cml0",
-	.parent    = &tegra_pll_e,
-	.ops       = &tegra_cml_clk_ops,
-	.reg       = PLLE_AUX,
-	.max_rate  = 100000000,
-	.u.periph  = {
-		.clk_num = 0,
-	},
-};
-
-static struct clk tegra_cml1_clk = {
-	.name      = "cml1",
-	.parent    = &tegra_pll_e,
-	.ops       = &tegra_cml_clk_ops,
-	.reg       = PLLE_AUX,
-	.max_rate  = 100000000,
-	.u.periph  = {
-		.clk_num   = 1,
-	},
-};
-
-static struct clk tegra_pciex_clk = {
-	.name      = "pciex",
-	.parent    = &tegra_pll_e,
-	.ops       = &tegra_pciex_clk_ops,
-	.max_rate  = 100000000,
-	.u.periph  = {
-		.clk_num   = 74,
-	},
-};
-
-/* Audio sync clocks */
-#define SYNC_SOURCE(_id)				\
-	{						\
-		.name      = #_id "_sync",		\
-		.rate      = 24000000,			\
-		.max_rate  = 24000000,			\
-		.ops       = &tegra_sync_source_ops	\
-	}
-static struct clk tegra_sync_source_list[] = {
-	SYNC_SOURCE(spdif_in),
-	SYNC_SOURCE(i2s0),
-	SYNC_SOURCE(i2s1),
-	SYNC_SOURCE(i2s2),
-	SYNC_SOURCE(i2s3),
-	SYNC_SOURCE(i2s4),
-	SYNC_SOURCE(vimclk),
-};
-
-static struct clk_mux_sel mux_audio_sync_clk[] = {
-	{ .input = &tegra_sync_source_list[0],	.value = 0},
-	{ .input = &tegra_sync_source_list[1],	.value = 1},
-	{ .input = &tegra_sync_source_list[2],	.value = 2},
-	{ .input = &tegra_sync_source_list[3],	.value = 3},
-	{ .input = &tegra_sync_source_list[4],	.value = 4},
-	{ .input = &tegra_sync_source_list[5],	.value = 5},
-	{ .input = &tegra_pll_a_out0,		.value = 6},
-	{ .input = &tegra_sync_source_list[6],	.value = 7},
-	{ 0, 0 }
-};
-
-#define AUDIO_SYNC_CLK(_id, _index)			\
-	{						\
-		.name      = #_id,			\
-		.inputs    = mux_audio_sync_clk,	\
-		.reg       = 0x4A0 + (_index) * 4,	\
-		.max_rate  = 24000000,			\
-		.ops       = &tegra_audio_sync_clk_ops	\
-	}
-static struct clk tegra_clk_audio_list[] = {
-	AUDIO_SYNC_CLK(audio0, 0),
-	AUDIO_SYNC_CLK(audio1, 1),
-	AUDIO_SYNC_CLK(audio2, 2),
-	AUDIO_SYNC_CLK(audio3, 3),
-	AUDIO_SYNC_CLK(audio4, 4),
-	AUDIO_SYNC_CLK(audio, 5),	/* SPDIF */
-};
-
-#define AUDIO_SYNC_2X_CLK(_id, _index)				\
-	{							\
-		.name      = #_id "_2x",			\
-		.flags     = PERIPH_NO_RESET,			\
-		.max_rate  = 48000000,				\
-		.ops       = &tegra_clk_double_ops,		\
-		.reg       = 0x49C,				\
-		.reg_shift = 24 + (_index),			\
-		.parent    = &tegra_clk_audio_list[(_index)],	\
-		.u.periph = {					\
-			.clk_num = 113 + (_index),		\
-		},						\
-	}
-static struct clk tegra_clk_audio_2x_list[] = {
-	AUDIO_SYNC_2X_CLK(audio0, 0),
-	AUDIO_SYNC_2X_CLK(audio1, 1),
-	AUDIO_SYNC_2X_CLK(audio2, 2),
-	AUDIO_SYNC_2X_CLK(audio3, 3),
-	AUDIO_SYNC_2X_CLK(audio4, 4),
-	AUDIO_SYNC_2X_CLK(audio, 5),	/* SPDIF */
-};
+/* Tegra30 CPU clock and reset control functions */
+static void tegra30_wait_cpu_in_reset(u32 cpu)
+{
+	unsigned int reg;
 
-#define MUX_I2S_SPDIF(_id, _index)					\
-static struct clk_mux_sel mux_pllaout0_##_id##_2x_pllp_clkm[] = {	\
-	{.input = &tegra_pll_a_out0, .value = 0},			\
-	{.input = &tegra_clk_audio_2x_list[(_index)], .value = 1},	\
-	{.input = &tegra_pll_p, .value = 2},				\
-	{.input = &tegra_clk_m, .value = 3},				\
-	{ 0, 0},							\
-}
-MUX_I2S_SPDIF(audio0, 0);
-MUX_I2S_SPDIF(audio1, 1);
-MUX_I2S_SPDIF(audio2, 2);
-MUX_I2S_SPDIF(audio3, 3);
-MUX_I2S_SPDIF(audio4, 4);
-MUX_I2S_SPDIF(audio, 5);		/* SPDIF */
-
-/* External clock outputs (through PMC) */
-#define MUX_EXTERN_OUT(_id)						\
-static struct clk_mux_sel mux_clkm_clkm2_clkm4_extern##_id[] = {	\
-	{.input = &tegra_clk_m,		.value = 0},			\
-	{.input = &tegra_clk_m_div2,	.value = 1},			\
-	{.input = &tegra_clk_m_div4,	.value = 2},			\
-	{.input = NULL,			.value = 3}, /* placeholder */	\
-	{ 0, 0},							\
-}
-MUX_EXTERN_OUT(1);
-MUX_EXTERN_OUT(2);
-MUX_EXTERN_OUT(3);
-
-static struct clk_mux_sel *mux_extern_out_list[] = {
-	mux_clkm_clkm2_clkm4_extern1,
-	mux_clkm_clkm2_clkm4_extern2,
-	mux_clkm_clkm2_clkm4_extern3,
-};
+	do {
+		reg = readl(reg_clk_base +
+			    TEGRA30_CLK_RST_CONTROLLER_CPU_CMPLX_STATUS);
+		cpu_relax();
+	} while (!(reg & (1 << cpu)));	/* check CPU been reset or not */
 
-#define CLK_OUT_CLK(_id)					\
-	{							\
-		.name      = "clk_out_" #_id,			\
-		.lookup    = {					\
-			.dev_id    = "clk_out_" #_id,		\
-			.con_id	   = "extern" #_id,		\
-		},						\
-		.ops       = &tegra_clk_out_ops,		\
-		.reg       = 0x1a8,				\
-		.inputs    = mux_clkm_clkm2_clkm4_extern##_id,	\
-		.flags     = MUX_CLK_OUT,			\
-		.max_rate  = 216000000,				\
-		.u.periph = {					\
-			.clk_num   = (_id - 1) * 8 + 2,		\
-		},						\
-	}
-static struct clk tegra_clk_out_list[] = {
-	CLK_OUT_CLK(1),
-	CLK_OUT_CLK(2),
-	CLK_OUT_CLK(3),
-};
+	return;
+}
 
-/* called after peripheral external clocks are initialized */
-static void init_clk_out_mux(void)
+static void tegra30_put_cpu_in_reset(u32 cpu)
 {
-	int i;
-	struct clk *c;
-
-	/* output clock con_id is the name of peripheral
-	   external clock connected to input 3 of the output mux */
-	for (i = 0; i < ARRAY_SIZE(tegra_clk_out_list); i++) {
-		c = tegra_get_clock_by_name(
-			tegra_clk_out_list[i].lookup.con_id);
-		if (!c)
-			pr_err("%s: could not find clk %s\n", __func__,
-			       tegra_clk_out_list[i].lookup.con_id);
-		mux_extern_out_list[i][3].input = c;
-	}
+	writel(CPU_RESET(cpu),
+	       reg_clk_base + TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET);
+	dmb();
 }
 
-/* Peripheral muxes */
-static struct clk_mux_sel mux_sclk[] = {
-	{ .input = &tegra_clk_m,	.value = 0},
-	{ .input = &tegra_pll_c_out1,	.value = 1},
-	{ .input = &tegra_pll_p_out4,	.value = 2},
-	{ .input = &tegra_pll_p_out3,	.value = 3},
-	{ .input = &tegra_pll_p_out2,	.value = 4},
-	/* { .input = &tegra_clk_d,	.value = 5}, - no use on tegra30 */
-	{ .input = &tegra_clk_32k,	.value = 6},
-	{ .input = &tegra_pll_m_out1,	.value = 7},
-	{ 0, 0},
-};
-
-static struct clk tegra_clk_sclk = {
-	.name	= "sclk",
-	.inputs	= mux_sclk,
-	.reg	= 0x28,
-	.ops	= &tegra_super_ops,
-	.max_rate = 334000000,
-	.min_rate = 40000000,
-};
-
-static struct clk tegra_clk_blink = {
-	.name		= "blink",
-	.parent		= &tegra_clk_32k,
-	.reg		= 0x40,
-	.ops		= &tegra_blink_clk_ops,
-	.max_rate	= 32768,
-};
-
-static struct clk_mux_sel mux_pllm_pllc_pllp_plla[] = {
-	{ .input = &tegra_pll_m, .value = 0},
-	{ .input = &tegra_pll_c, .value = 1},
-	{ .input = &tegra_pll_p, .value = 2},
-	{ .input = &tegra_pll_a_out0, .value = 3},
-	{ 0, 0},
-};
-
-static struct clk_mux_sel mux_pllp_pllc_pllm_clkm[] = {
-	{ .input = &tegra_pll_p, .value = 0},
-	{ .input = &tegra_pll_c, .value = 1},
-	{ .input = &tegra_pll_m, .value = 2},
-	{ .input = &tegra_clk_m, .value = 3},
-	{ 0, 0},
-};
-
-static struct clk_mux_sel mux_pllp_clkm[] = {
-	{ .input = &tegra_pll_p, .value = 0},
-	{ .input = &tegra_clk_m, .value = 3},
-	{ 0, 0},
-};
-
-static struct clk_mux_sel mux_pllp_plld_pllc_clkm[] = {
-	{.input = &tegra_pll_p, .value = 0},
-	{.input = &tegra_pll_d_out0, .value = 1},
-	{.input = &tegra_pll_c, .value = 2},
-	{.input = &tegra_clk_m, .value = 3},
-	{ 0, 0},
-};
-
-static struct clk_mux_sel mux_pllp_pllm_plld_plla_pllc_plld2_clkm[] = {
-	{.input = &tegra_pll_p, .value = 0},
-	{.input = &tegra_pll_m, .value = 1},
-	{.input = &tegra_pll_d_out0, .value = 2},
-	{.input = &tegra_pll_a_out0, .value = 3},
-	{.input = &tegra_pll_c, .value = 4},
-	{.input = &tegra_pll_d2_out0, .value = 5},
-	{.input = &tegra_clk_m, .value = 6},
-	{ 0, 0},
-};
-
-static struct clk_mux_sel mux_plla_pllc_pllp_clkm[] = {
-	{ .input = &tegra_pll_a_out0, .value = 0},
-	/* { .input = &tegra_pll_c, .value = 1}, no use on tegra30 */
-	{ .input = &tegra_pll_p, .value = 2},
-	{ .input = &tegra_clk_m, .value = 3},
-	{ 0, 0},
-};
-
-static struct clk_mux_sel mux_pllp_pllc_clk32_clkm[] = {
-	{.input = &tegra_pll_p,     .value = 0},
-	{.input = &tegra_pll_c,     .value = 1},
-	{.input = &tegra_clk_32k,   .value = 2},
-	{.input = &tegra_clk_m,     .value = 3},
-	{ 0, 0},
-};
-
-static struct clk_mux_sel mux_pllp_pllc_clkm_clk32[] = {
-	{.input = &tegra_pll_p,     .value = 0},
-	{.input = &tegra_pll_c,     .value = 1},
-	{.input = &tegra_clk_m,     .value = 2},
-	{.input = &tegra_clk_32k,   .value = 3},
-	{ 0, 0},
-};
-
-static struct clk_mux_sel mux_pllp_pllc_pllm[] = {
-	{.input = &tegra_pll_p,     .value = 0},
-	{.input = &tegra_pll_c,     .value = 1},
-	{.input = &tegra_pll_m,     .value = 2},
-	{ 0, 0},
-};
-
-static struct clk_mux_sel mux_clk_m[] = {
-	{ .input = &tegra_clk_m, .value = 0},
-	{ 0, 0},
-};
-
-static struct clk_mux_sel mux_pllp_out3[] = {
-	{ .input = &tegra_pll_p_out3, .value = 0},
-	{ 0, 0},
-};
-
-static struct clk_mux_sel mux_plld_out0[] = {
-	{ .input = &tegra_pll_d_out0, .value = 0},
-	{ 0, 0},
-};
-
-static struct clk_mux_sel mux_plld_out0_plld2_out0[] = {
-	{ .input = &tegra_pll_d_out0,  .value = 0},
-	{ .input = &tegra_pll_d2_out0, .value = 1},
-	{ 0, 0},
-};
-
-static struct clk_mux_sel mux_clk_32k[] = {
-	{ .input = &tegra_clk_32k, .value = 0},
-	{ 0, 0},
-};
-
-static struct clk_mux_sel mux_plla_clk32_pllp_clkm_plle[] = {
-	{ .input = &tegra_pll_a_out0, .value = 0},
-	{ .input = &tegra_clk_32k,    .value = 1},
-	{ .input = &tegra_pll_p,      .value = 2},
-	{ .input = &tegra_clk_m,      .value = 3},
-	{ .input = &tegra_pll_e,      .value = 4},
-	{ 0, 0},
-};
-
-static struct clk_mux_sel mux_cclk_g[] = {
-	{ .input = &tegra_clk_m,        .value = 0},
-	{ .input = &tegra_pll_c,        .value = 1},
-	{ .input = &tegra_clk_32k,      .value = 2},
-	{ .input = &tegra_pll_m,        .value = 3},
-	{ .input = &tegra_pll_p,        .value = 4},
-	{ .input = &tegra_pll_p_out4,   .value = 5},
-	{ .input = &tegra_pll_p_out3,   .value = 6},
-	{ .input = &tegra_pll_x,        .value = 8},
-	{ 0, 0},
-};
-
-static struct clk tegra_clk_cclk_g = {
-	.name	= "cclk_g",
-	.flags	= DIV_U71 | DIV_U71_INT,
-	.inputs = mux_cclk_g,
-	.reg	= 0x368,
-	.ops	= &tegra_super_ops,
-	.max_rate = 1700000000,
-};
-
-static struct clk tegra30_clk_twd = {
-	.parent	  = &tegra_clk_cclk_g,
-	.name     = "twd",
-	.ops      = &tegra30_twd_ops,
-	.max_rate = 1400000000,	/* Same as tegra_clk_cpu_cmplx.max_rate */
-	.mul      = 1,
-	.div      = 2,
-};
-
-#define PERIPH_CLK(_name, _dev, _con, _clk_num, _reg, _max, _inputs, _flags) \
-	{						\
-		.name      = _name,			\
-		.lookup    = {				\
-			.dev_id    = _dev,		\
-			.con_id	   = _con,		\
-		},					\
-		.ops       = &tegra_periph_clk_ops,	\
-		.reg       = _reg,			\
-		.inputs    = _inputs,			\
-		.flags     = _flags,			\
-		.max_rate  = _max,			\
-		.u.periph = {				\
-			.clk_num   = _clk_num,		\
-		},					\
-	}
-
-#define PERIPH_CLK_EX(_name, _dev, _con, _clk_num, _reg, _max, _inputs,	\
-			_flags, _ops)					\
-	{						\
-		.name      = _name,			\
-		.lookup    = {				\
-			.dev_id    = _dev,		\
-			.con_id	   = _con,		\
-		},					\
-		.ops       = _ops,			\
-		.reg       = _reg,			\
-		.inputs    = _inputs,			\
-		.flags     = _flags,			\
-		.max_rate  = _max,			\
-		.u.periph = {				\
-			.clk_num   = _clk_num,		\
-		},					\
-	}
-
-#define SHARED_CLK(_name, _dev, _con, _parent, _id, _div, _mode)\
-	{						\
-		.name      = _name,			\
-		.lookup    = {				\
-			.dev_id    = _dev,		\
-			.con_id    = _con,		\
-		},					\
-		.ops       = &tegra_clk_shared_bus_ops,	\
-		.parent = _parent,			\
-		.u.shared_bus_user = {			\
-			.client_id = _id,		\
-			.client_div = _div,		\
-			.mode = _mode,			\
-		},					\
-	}
-struct clk tegra_list_clks[] = {
-	PERIPH_CLK("apbdma",	"tegra-apbdma",		NULL,	34,	0,	26000000,  mux_clk_m,			0),
-	PERIPH_CLK("rtc",	"rtc-tegra",		NULL,	4,	0,	32768,     mux_clk_32k,			PERIPH_NO_RESET | PERIPH_ON_APB),
-	PERIPH_CLK("kbc",	"tegra-kbc",		NULL,	36,	0,	32768,     mux_clk_32k,			PERIPH_NO_RESET | PERIPH_ON_APB),
-	PERIPH_CLK("timer",	"timer",		NULL,	5,	0,	26000000,  mux_clk_m,			0),
-	PERIPH_CLK("kfuse",	"kfuse-tegra",		NULL,	40,	0,	26000000,  mux_clk_m,			0),
-	PERIPH_CLK("fuse",	"fuse-tegra",		"fuse",	39,	0,	26000000,  mux_clk_m,			PERIPH_ON_APB),
-	PERIPH_CLK("fuse_burn",	"fuse-tegra",		"fuse_burn",	39,	0,	26000000,  mux_clk_m,		PERIPH_ON_APB),
-	PERIPH_CLK("apbif",	"tegra30-ahub",		"apbif", 107,	0,	26000000,  mux_clk_m,			0),
-	PERIPH_CLK("i2s0",	"tegra30-i2s.0",	NULL,	30,	0x1d8,	26000000,  mux_pllaout0_audio0_2x_pllp_clkm,	MUX | DIV_U71 | PERIPH_ON_APB),
-	PERIPH_CLK("i2s1",	"tegra30-i2s.1",	NULL,	11,	0x100,	26000000,  mux_pllaout0_audio1_2x_pllp_clkm,	MUX | DIV_U71 | PERIPH_ON_APB),
-	PERIPH_CLK("i2s2",	"tegra30-i2s.2",	NULL,	18,	0x104,	26000000,  mux_pllaout0_audio2_2x_pllp_clkm,	MUX | DIV_U71 | PERIPH_ON_APB),
-	PERIPH_CLK("i2s3",	"tegra30-i2s.3",	NULL,	101,	0x3bc,	26000000,  mux_pllaout0_audio3_2x_pllp_clkm,	MUX | DIV_U71 | PERIPH_ON_APB),
-	PERIPH_CLK("i2s4",	"tegra30-i2s.4",	NULL,	102,	0x3c0,	26000000,  mux_pllaout0_audio4_2x_pllp_clkm,	MUX | DIV_U71 | PERIPH_ON_APB),
-	PERIPH_CLK("spdif_out",	"tegra30-spdif",	"spdif_out",	10,	0x108,	100000000, mux_pllaout0_audio_2x_pllp_clkm,	MUX | DIV_U71 | PERIPH_ON_APB),
-	PERIPH_CLK("spdif_in",	"tegra30-spdif",	"spdif_in",	10,	0x10c,	100000000, mux_pllp_pllc_pllm,		MUX | DIV_U71 | PERIPH_ON_APB),
-	PERIPH_CLK("pwm",	"tegra-pwm",		NULL,	17,	0x110,	432000000, mux_pllp_pllc_clk32_clkm,	MUX | MUX_PWM | DIV_U71 | PERIPH_ON_APB),
-	PERIPH_CLK("d_audio",	"tegra30-ahub",		"d_audio", 106,	0x3d0,	48000000,  mux_plla_pllc_pllp_clkm,	MUX | DIV_U71),
-	PERIPH_CLK("dam0",	"tegra30-dam.0",	NULL,   108,	0x3d8,	48000000,  mux_plla_pllc_pllp_clkm,	MUX | DIV_U71),
-	PERIPH_CLK("dam1",	"tegra30-dam.1",	NULL,   109,	0x3dc,	48000000,  mux_plla_pllc_pllp_clkm,	MUX | DIV_U71),
-	PERIPH_CLK("dam2",	"tegra30-dam.2",	NULL,   110,	0x3e0,	48000000,  mux_plla_pllc_pllp_clkm,	MUX | DIV_U71),
-	PERIPH_CLK("hda",	"tegra30-hda",		"hda",   125,	0x428,	108000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
-	PERIPH_CLK("hda2codec_2x",	"tegra30-hda",	"hda2codec",   111,	0x3e4,	48000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
-	PERIPH_CLK("hda2hdmi",	"tegra30-hda",		"hda2hdmi",	128,	0,	48000000,  mux_clk_m,			0),
-	PERIPH_CLK("sbc1",	"spi_tegra.0",		NULL,	41,	0x134,	160000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71 | PERIPH_ON_APB),
-	PERIPH_CLK("sbc2",	"spi_tegra.1",		NULL,	44,	0x118,	160000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71 | PERIPH_ON_APB),
-	PERIPH_CLK("sbc3",	"spi_tegra.2",		NULL,	46,	0x11c,	160000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71 | PERIPH_ON_APB),
-	PERIPH_CLK("sbc4",	"spi_tegra.3",		NULL,	68,	0x1b4,	160000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71 | PERIPH_ON_APB),
-	PERIPH_CLK("sbc5",	"spi_tegra.4",		NULL,	104,	0x3c8,	160000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71 | PERIPH_ON_APB),
-	PERIPH_CLK("sbc6",	"spi_tegra.5",		NULL,	105,	0x3cc,	160000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71 | PERIPH_ON_APB),
-	PERIPH_CLK("sata_oob",	"tegra_sata_oob",	NULL,	123,	0x420,	216000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
-	PERIPH_CLK("sata",	"tegra_sata",		NULL,	124,	0x424,	216000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
-	PERIPH_CLK("sata_cold",	"tegra_sata_cold",	NULL,	129,	0,	48000000,  mux_clk_m,			0),
-	PERIPH_CLK_EX("ndflash", "tegra_nand",		NULL,	13,	0x160,	240000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71,	&tegra_nand_clk_ops),
-	PERIPH_CLK("ndspeed",	"tegra_nand_speed",	NULL,	80,	0x3f8,	240000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
-	PERIPH_CLK("vfir",	"vfir",			NULL,	7,	0x168,	72000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71 | PERIPH_ON_APB),
-	PERIPH_CLK("sdmmc1",	"sdhci-tegra.0",	NULL,	14,	0x150,	208000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71), /* scales with voltage */
-	PERIPH_CLK("sdmmc2",	"sdhci-tegra.1",	NULL,	9,	0x154,	104000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71), /* scales with voltage */
-	PERIPH_CLK("sdmmc3",	"sdhci-tegra.2",	NULL,	69,	0x1bc,	208000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71), /* scales with voltage */
-	PERIPH_CLK("sdmmc4",	"sdhci-tegra.3",	NULL,	15,	0x164,	104000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71), /* scales with voltage */
-	PERIPH_CLK("vcp",	"tegra-avp",		"vcp",	29,	0,	250000000, mux_clk_m,			0),
-	PERIPH_CLK("bsea",	"tegra-avp",		"bsea",	62,	0,	250000000, mux_clk_m,			0),
-	PERIPH_CLK("bsev",	"tegra-aes",		"bsev",	63,	0,	250000000, mux_clk_m,			0),
-	PERIPH_CLK("vde",	"vde",			NULL,	61,	0x1c8,	520000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71 | DIV_U71_INT),
-	PERIPH_CLK("csite",	"csite",		NULL,	73,	0x1d4,	144000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71), /* max rate ??? */
-	PERIPH_CLK("la",	"la",			NULL,	76,	0x1f8,	26000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
-	PERIPH_CLK("owr",	"tegra_w1",		NULL,	71,	0x1cc,	26000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71 | PERIPH_ON_APB),
-	PERIPH_CLK("nor",	"nor",			NULL,	42,	0x1d0,	127000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71), /* requires min voltage */
-	PERIPH_CLK("mipi",	"mipi",			NULL,	50,	0x174,	60000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71 | PERIPH_ON_APB), /* scales with voltage */
-	PERIPH_CLK("i2c1",	"tegra-i2c.0",		NULL,	12,	0x124,	26000000,  mux_pllp_clkm,		MUX | DIV_U16 | PERIPH_ON_APB),
-	PERIPH_CLK("i2c2",	"tegra-i2c.1",		NULL,	54,	0x198,	26000000,  mux_pllp_clkm,		MUX | DIV_U16 | PERIPH_ON_APB),
-	PERIPH_CLK("i2c3",	"tegra-i2c.2",		NULL,	67,	0x1b8,	26000000,  mux_pllp_clkm,		MUX | DIV_U16 | PERIPH_ON_APB),
-	PERIPH_CLK("i2c4",	"tegra-i2c.3",		NULL,	103,	0x3c4,	26000000,  mux_pllp_clkm,		MUX | DIV_U16 | PERIPH_ON_APB),
-	PERIPH_CLK("i2c5",	"tegra-i2c.4",		NULL,	47,	0x128,	26000000,  mux_pllp_clkm,		MUX | DIV_U16 | PERIPH_ON_APB),
-	PERIPH_CLK("uarta",	"tegra-uart.0",		NULL,	6,	0x178,	800000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB),
-	PERIPH_CLK("uartb",	"tegra-uart.1",		NULL,	7,	0x17c,	800000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB),
-	PERIPH_CLK("uartc",	"tegra-uart.2",		NULL,	55,	0x1a0,	800000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB),
-	PERIPH_CLK("uartd",	"tegra-uart.3",		NULL,	65,	0x1c0,	800000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB),
-	PERIPH_CLK("uarte",	"tegra-uart.4",		NULL,	66,	0x1c4,	800000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB),
-	PERIPH_CLK_EX("vi",	"tegra_camera",		"vi",	20,	0x148,	425000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71 | DIV_U71_INT,	&tegra_vi_clk_ops),
-	PERIPH_CLK("3d",	"3d",			NULL,	24,	0x158,	520000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71 | DIV_U71_INT | DIV_U71_IDLE | PERIPH_MANUAL_RESET),
-	PERIPH_CLK("3d2",       "3d2",			NULL,	98,	0x3b0,	520000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71 | DIV_U71_INT | DIV_U71_IDLE | PERIPH_MANUAL_RESET),
-	PERIPH_CLK("2d",	"2d",			NULL,	21,	0x15c,	520000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71 | DIV_U71_INT | DIV_U71_IDLE),
-	PERIPH_CLK("vi_sensor",	"tegra_camera",		"vi_sensor",	20,	0x1a8,	150000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71 | PERIPH_NO_RESET),
-	PERIPH_CLK("epp",	"epp",			NULL,	19,	0x16c,	520000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71 | DIV_U71_INT),
-	PERIPH_CLK("mpe",	"mpe",			NULL,	60,	0x170,	520000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71 | DIV_U71_INT),
-	PERIPH_CLK("host1x",	"host1x",		NULL,	28,	0x180,	260000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71 | DIV_U71_INT),
-	PERIPH_CLK("cve",	"cve",			NULL,	49,	0x140,	250000000, mux_pllp_plld_pllc_clkm,	MUX | DIV_U71), /* requires min voltage */
-	PERIPH_CLK("tvo",	"tvo",			NULL,	49,	0x188,	250000000, mux_pllp_plld_pllc_clkm,	MUX | DIV_U71), /* requires min voltage */
-	PERIPH_CLK_EX("dtv",	"dtv",			NULL,	79,	0x1dc,	250000000, mux_clk_m,			0,		&tegra_dtv_clk_ops),
-	PERIPH_CLK("hdmi",	"hdmi",			NULL,	51,	0x18c,	148500000, mux_pllp_pllm_plld_plla_pllc_plld2_clkm,	MUX | MUX8 | DIV_U71),
-	PERIPH_CLK("tvdac",	"tvdac",		NULL,	53,	0x194,	220000000, mux_pllp_plld_pllc_clkm,	MUX | DIV_U71), /* requires min voltage */
-	PERIPH_CLK("disp1",	"tegradc.0",		NULL,	27,	0x138,	600000000, mux_pllp_pllm_plld_plla_pllc_plld2_clkm,	MUX | MUX8),
-	PERIPH_CLK("disp2",	"tegradc.1",		NULL,	26,	0x13c,	600000000, mux_pllp_pllm_plld_plla_pllc_plld2_clkm,	MUX | MUX8),
-	PERIPH_CLK("usbd",	"fsl-tegra-udc",	NULL,	22,	0,	480000000, mux_clk_m,			0), /* requires min voltage */
-	PERIPH_CLK("usb2",	"tegra-ehci.1",		NULL,	58,	0,	480000000, mux_clk_m,			0), /* requires min voltage */
-	PERIPH_CLK("usb3",	"tegra-ehci.2",		NULL,	59,	0,	480000000, mux_clk_m,			0), /* requires min voltage */
-	PERIPH_CLK("dsia",	"tegradc.0",		"dsia",	48,	0,	500000000, mux_plld_out0,		0),
-	PERIPH_CLK_EX("dsib",	"tegradc.1",		"dsib",	82,	0xd0,	500000000, mux_plld_out0_plld2_out0,	MUX | PLLD,	&tegra_dsib_clk_ops),
-	PERIPH_CLK("csi",	"tegra_camera",		"csi",	52,	0,	102000000, mux_pllp_out3,		0),
-	PERIPH_CLK("isp",	"tegra_camera",		"isp",	23,	0,	150000000, mux_clk_m,			0), /* same frequency as VI */
-	PERIPH_CLK("csus",	"tegra_camera",		"csus",	92,	0,	150000000, mux_clk_m,			PERIPH_NO_RESET),
-
-	PERIPH_CLK("tsensor",	"tegra-tsensor",	NULL,	100,	0x3b8,	216000000, mux_pllp_pllc_clkm_clk32,	MUX | DIV_U71),
-	PERIPH_CLK("actmon",	"actmon",		NULL,	119,	0x3e8,	216000000, mux_pllp_pllc_clk32_clkm,	MUX | DIV_U71),
-	PERIPH_CLK("extern1",	"extern1",		NULL,	120,	0x3ec,	216000000, mux_plla_clk32_pllp_clkm_plle,	MUX | MUX8 | DIV_U71),
-	PERIPH_CLK("extern2",	"extern2",		NULL,	121,	0x3f0,	216000000, mux_plla_clk32_pllp_clkm_plle,	MUX | MUX8 | DIV_U71),
-	PERIPH_CLK("extern3",	"extern3",		NULL,	122,	0x3f4,	216000000, mux_plla_clk32_pllp_clkm_plle,	MUX | MUX8 | DIV_U71),
-	PERIPH_CLK("i2cslow",	"i2cslow",		NULL,	81,	0x3fc,	26000000,  mux_pllp_pllc_clk32_clkm,	MUX | DIV_U71 | PERIPH_ON_APB),
-	PERIPH_CLK("pcie",	"tegra-pcie",		"pcie",	70,	0,	250000000, mux_clk_m,			0),
-	PERIPH_CLK("afi",	"tegra-pcie",		"afi",	72,	0,	250000000, mux_clk_m,			0),
-	PERIPH_CLK("se",	"se",			NULL,	127,	0x42c,	520000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71 | DIV_U71_INT),
-};
-
-#define CLK_DUPLICATE(_name, _dev, _con)		\
-	{						\
-		.name	= _name,			\
-		.lookup	= {				\
-			.dev_id	= _dev,			\
-			.con_id		= _con,		\
-		},					\
-	}
-
-/* Some clocks may be used by different drivers depending on the board
- * configuration.  List those here to register them twice in the clock lookup
- * table under two names.
- */
-struct clk_duplicate tegra_clk_duplicates[] = {
-	CLK_DUPLICATE("uarta",  "serial8250.0", NULL),
-	CLK_DUPLICATE("uartb",  "serial8250.1", NULL),
-	CLK_DUPLICATE("uartc",  "serial8250.2", NULL),
-	CLK_DUPLICATE("uartd",  "serial8250.3", NULL),
-	CLK_DUPLICATE("uarte",  "serial8250.4", NULL),
-	CLK_DUPLICATE("usbd", "utmip-pad", NULL),
-	CLK_DUPLICATE("usbd", "tegra-ehci.0", NULL),
-	CLK_DUPLICATE("usbd", "tegra-otg", NULL),
-	CLK_DUPLICATE("hdmi", "tegradc.0", "hdmi"),
-	CLK_DUPLICATE("hdmi", "tegradc.1", "hdmi"),
-	CLK_DUPLICATE("dsib", "tegradc.0", "dsib"),
-	CLK_DUPLICATE("dsia", "tegradc.1", "dsia"),
-	CLK_DUPLICATE("bsev", "tegra-avp", "bsev"),
-	CLK_DUPLICATE("bsev", "nvavp", "bsev"),
-	CLK_DUPLICATE("vde", "tegra-aes", "vde"),
-	CLK_DUPLICATE("bsea", "tegra-aes", "bsea"),
-	CLK_DUPLICATE("bsea", "nvavp", "bsea"),
-	CLK_DUPLICATE("cml1", "tegra_sata_cml", NULL),
-	CLK_DUPLICATE("cml0", "tegra_pcie", "cml"),
-	CLK_DUPLICATE("pciex", "tegra_pcie", "pciex"),
-	CLK_DUPLICATE("i2c1", "tegra-i2c-slave.0", NULL),
-	CLK_DUPLICATE("i2c2", "tegra-i2c-slave.1", NULL),
-	CLK_DUPLICATE("i2c3", "tegra-i2c-slave.2", NULL),
-	CLK_DUPLICATE("i2c4", "tegra-i2c-slave.3", NULL),
-	CLK_DUPLICATE("i2c5", "tegra-i2c-slave.4", NULL),
-	CLK_DUPLICATE("sbc1", "spi_slave_tegra.0", NULL),
-	CLK_DUPLICATE("sbc2", "spi_slave_tegra.1", NULL),
-	CLK_DUPLICATE("sbc3", "spi_slave_tegra.2", NULL),
-	CLK_DUPLICATE("sbc4", "spi_slave_tegra.3", NULL),
-	CLK_DUPLICATE("sbc5", "spi_slave_tegra.4", NULL),
-	CLK_DUPLICATE("sbc6", "spi_slave_tegra.5", NULL),
-	CLK_DUPLICATE("twd", "smp_twd", NULL),
-	CLK_DUPLICATE("vcp", "nvavp", "vcp"),
-	CLK_DUPLICATE("i2s0", NULL, "i2s0"),
-	CLK_DUPLICATE("i2s1", NULL, "i2s1"),
-	CLK_DUPLICATE("i2s2", NULL, "i2s2"),
-	CLK_DUPLICATE("i2s3", NULL, "i2s3"),
-	CLK_DUPLICATE("i2s4", NULL, "i2s4"),
-	CLK_DUPLICATE("dam0", NULL, "dam0"),
-	CLK_DUPLICATE("dam1", NULL, "dam1"),
-	CLK_DUPLICATE("dam2", NULL, "dam2"),
-	CLK_DUPLICATE("spdif_in", NULL, "spdif_in"),
-};
-
-struct clk *tegra_ptr_clks[] = {
-	&tegra_clk_32k,
-	&tegra_clk_m,
-	&tegra_clk_m_div2,
-	&tegra_clk_m_div4,
-	&tegra_pll_ref,
-	&tegra_pll_m,
-	&tegra_pll_m_out1,
-	&tegra_pll_c,
-	&tegra_pll_c_out1,
-	&tegra_pll_p,
-	&tegra_pll_p_out1,
-	&tegra_pll_p_out2,
-	&tegra_pll_p_out3,
-	&tegra_pll_p_out4,
-	&tegra_pll_a,
-	&tegra_pll_a_out0,
-	&tegra_pll_d,
-	&tegra_pll_d_out0,
-	&tegra_pll_d2,
-	&tegra_pll_d2_out0,
-	&tegra_pll_u,
-	&tegra_pll_x,
-	&tegra_pll_x_out0,
-	&tegra_pll_e,
-	&tegra_clk_cclk_g,
-	&tegra_cml0_clk,
-	&tegra_cml1_clk,
-	&tegra_pciex_clk,
-	&tegra_clk_sclk,
-	&tegra_clk_blink,
-	&tegra30_clk_twd,
-};
-
-
-static void tegra30_init_one_clock(struct clk *c)
+static void tegra30_cpu_out_of_reset(u32 cpu)
 {
-	clk_init(c);
-	INIT_LIST_HEAD(&c->shared_bus_list);
-	if (!c->lookup.dev_id && !c->lookup.con_id)
-		c->lookup.con_id = c->name;
-	c->lookup.clk = c;
-	clkdev_add(&c->lookup);
+	writel(CPU_RESET(cpu),
+	       reg_clk_base + TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR);
+	wmb();
 }
 
-void __init tegra30_init_clocks(void)
+static void tegra30_enable_cpu_clock(u32 cpu)
 {
-	int i;
-	struct clk *c;
+	unsigned int reg;
 
-	for (i = 0; i < ARRAY_SIZE(tegra_ptr_clks); i++)
-		tegra30_init_one_clock(tegra_ptr_clks[i]);
-
-	for (i = 0; i < ARRAY_SIZE(tegra_list_clks); i++)
-		tegra30_init_one_clock(&tegra_list_clks[i]);
+	writel(CPU_CLOCK(cpu),
+	       reg_clk_base + TEGRA30_CLK_RST_CONTROLLER_CLK_CPU_CMPLX_CLR);
+	reg = readl(reg_clk_base +
+		    TEGRA30_CLK_RST_CONTROLLER_CLK_CPU_CMPLX_CLR);
+}
 
-	for (i = 0; i < ARRAY_SIZE(tegra_clk_duplicates); i++) {
-		c = tegra_get_clock_by_name(tegra_clk_duplicates[i].name);
-		if (!c) {
-			pr_err("%s: Unknown duplicate clock %s\n", __func__,
-				tegra_clk_duplicates[i].name);
-			continue;
-		}
+static void tegra30_disable_cpu_clock(u32 cpu)
+{
 
-		tegra_clk_duplicates[i].lookup.clk = c;
-		clkdev_add(&tegra_clk_duplicates[i].lookup);
-	}
+	unsigned int reg;
 
-	for (i = 0; i < ARRAY_SIZE(tegra_sync_source_list); i++)
-		tegra30_init_one_clock(&tegra_sync_source_list[i]);
-	for (i = 0; i < ARRAY_SIZE(tegra_clk_audio_list); i++)
-		tegra30_init_one_clock(&tegra_clk_audio_list[i]);
-	for (i = 0; i < ARRAY_SIZE(tegra_clk_audio_2x_list); i++)
-		tegra30_init_one_clock(&tegra_clk_audio_2x_list[i]);
+	reg = readl(reg_clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
+	writel(reg | CPU_CLOCK(cpu),
+	       reg_clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
+}
 
-	init_clk_out_mux();
-	for (i = 0; i < ARRAY_SIZE(tegra_clk_out_list); i++)
-		tegra30_init_one_clock(&tegra_clk_out_list[i]);
+static struct tegra_cpu_car_ops tegra30_cpu_car_ops = {
+	.wait_for_reset	= tegra30_wait_cpu_in_reset,
+	.put_in_reset	= tegra30_put_cpu_in_reset,
+	.out_of_reset	= tegra30_cpu_out_of_reset,
+	.enable_clock	= tegra30_enable_cpu_clock,
+	.disable_clock	= tegra30_disable_cpu_clock,
+};
 
+void __init tegra30_cpu_car_ops_init(void)
+{
+	tegra_cpu_car_ops = &tegra30_cpu_car_ops;
 }
diff --git a/arch/arm/mach-tegra/tegra30_clocks.h b/arch/arm/mach-tegra/tegra30_clocks.h
new file mode 100644
index 0000000..f2f88fe
--- /dev/null
+++ b/arch/arm/mach-tegra/tegra30_clocks.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __MACH_TEGRA30_CLOCK_H
+#define __MACH_TEGRA30_CLOCK_H
+
+extern struct clk_ops tegra30_clk_32k_ops;
+extern struct clk_ops tegra30_clk_m_ops;
+extern struct clk_ops tegra_clk_m_div_ops;
+extern struct clk_ops tegra_pll_ref_ops;
+extern struct clk_ops tegra30_pll_ops;
+extern struct clk_ops tegra30_pll_div_ops;
+extern struct clk_ops tegra_plld_ops;
+extern struct clk_ops tegra30_plle_ops;
+extern struct clk_ops tegra_cml_clk_ops;
+extern struct clk_ops tegra_pciex_clk_ops;
+extern struct clk_ops tegra_sync_source_ops;
+extern struct clk_ops tegra30_audio_sync_clk_ops;
+extern struct clk_ops tegra30_clk_double_ops;
+extern struct clk_ops tegra_clk_out_ops;
+extern struct clk_ops tegra30_super_ops;
+extern struct clk_ops tegra30_blink_clk_ops;
+extern struct clk_ops tegra30_twd_ops;
+extern struct clk_ops tegra30_periph_clk_ops;
+extern struct clk_ops tegra30_dsib_clk_ops;
+extern struct clk_ops tegra_nand_clk_ops;
+extern struct clk_ops tegra_vi_clk_ops;
+extern struct clk_ops tegra_dtv_clk_ops;
+extern struct clk_ops tegra_clk_shared_bus_ops;
+
+int tegra30_plld_clk_cfg_ex(struct clk_hw *hw,
+				enum tegra_clk_ex_param p, u32 setting);
+void tegra30_periph_clk_reset(struct clk_hw *hw, bool assert);
+int tegra30_vi_clk_cfg_ex(struct clk_hw *hw,
+				enum tegra_clk_ex_param p, u32 setting);
+int tegra30_nand_clk_cfg_ex(struct clk_hw *hw,
+				enum tegra_clk_ex_param p, u32 setting);
+int tegra30_dtv_clk_cfg_ex(struct clk_hw *hw,
+				enum tegra_clk_ex_param p, u32 setting);
+#endif
diff --git a/arch/arm/mach-tegra/tegra30_clocks_data.c b/arch/arm/mach-tegra/tegra30_clocks_data.c
new file mode 100644
index 0000000..d92cb55
--- /dev/null
+++ b/arch/arm/mach-tegra/tegra30_clocks_data.c
@@ -0,0 +1,1377 @@
+/*
+ * arch/arm/mach-tegra/tegra30_clocks.c
+ *
+ * Copyright (c) 2010-2012 NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ */
+
+#include <linux/clk-private.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/cpufreq.h>
+
+#include "clock.h"
+#include "fuse.h"
+#include "tegra30_clocks.h"
+#include "tegra_cpu_car.h"
+
+#define DEFINE_CLK_TEGRA(_name, _rate, _ops, _flags,		\
+		   _parent_names, _parents, _parent)		\
+	static struct clk tegra_##_name = {			\
+		.hw = &tegra_##_name##_hw.hw,			\
+		.name = #_name,					\
+		.rate = _rate,					\
+		.ops = _ops,					\
+		.flags = _flags,				\
+		.parent_names = _parent_names,			\
+		.parents = _parents,				\
+		.num_parents = ARRAY_SIZE(_parent_names),	\
+		.parent	= _parent,				\
+	};
+
+static struct clk tegra_clk_32k;
+static struct clk_tegra tegra_clk_32k_hw = {
+	.hw = {
+		.clk = &tegra_clk_32k,
+	},
+	.fixed_rate = 32768,
+};
+static struct clk tegra_clk_32k = {
+	.name = "clk_32k",
+	.hw = &tegra_clk_32k_hw.hw,
+	.ops = &tegra30_clk_32k_ops,
+	.flags = CLK_IS_ROOT,
+};
+
+static struct clk tegra_clk_m;
+static struct clk_tegra tegra_clk_m_hw = {
+	.hw = {
+		.clk = &tegra_clk_m,
+	},
+	.flags = ENABLE_ON_INIT,
+	.reg = 0x1fc,
+	.reg_shift = 28,
+	.max_rate = 48000000,
+};
+static struct clk tegra_clk_m = {
+	.name = "clk_m",
+	.hw = &tegra_clk_m_hw.hw,
+	.ops = &tegra30_clk_m_ops,
+	.flags = CLK_IS_ROOT | CLK_IGNORE_UNUSED,
+};
+
+static const char *clk_m_div_parent_names[] = {
+	"clk_m",
+};
+
+static struct clk *clk_m_div_parents[] = {
+	&tegra_clk_m,
+};
+
+static struct clk tegra_clk_m_div2;
+static struct clk_tegra tegra_clk_m_div2_hw = {
+	.hw = {
+		.clk = &tegra_clk_m_div2,
+	},
+	.mul = 1,
+	.div = 2,
+	.max_rate = 24000000,
+};
+DEFINE_CLK_TEGRA(clk_m_div2, 0, &tegra_clk_m_div_ops, 0,
+		clk_m_div_parent_names, clk_m_div_parents, &tegra_clk_m);
+
+static struct clk tegra_clk_m_div4;
+static struct clk_tegra tegra_clk_m_div4_hw = {
+	.hw = {
+		.clk = &tegra_clk_m_div4,
+	},
+	.mul = 1,
+	.div = 4,
+	.max_rate = 12000000,
+};
+DEFINE_CLK_TEGRA(clk_m_div4, 0, &tegra_clk_m_div_ops, 0,
+		clk_m_div_parent_names, clk_m_div_parents, &tegra_clk_m);
+
+static struct clk tegra_pll_ref;
+static struct clk_tegra tegra_pll_ref_hw = {
+	.hw = {
+		.clk = &tegra_pll_ref,
+	},
+	.flags = ENABLE_ON_INIT,
+	.max_rate = 26000000,
+};
+DEFINE_CLK_TEGRA(pll_ref, 0, &tegra_pll_ref_ops, 0, clk_m_div_parent_names,
+		clk_m_div_parents, &tegra_clk_m);
+
+#define DEFINE_PLL(_name, _flags, _reg, _max_rate, _input_min,	\
+		   _input_max, _cf_min, _cf_max, _vco_min,	\
+		   _vco_max, _freq_table, _lock_delay, _ops,	\
+		   _fixed_rate, _clk_cfg_ex, _parent)		\
+	static struct clk tegra_##_name;			\
+	static const char *_name##_parent_names[] = {		\
+		#_parent,					\
+	};							\
+	static struct clk *_name##_parents[] = {		\
+		&tegra_##_parent,				\
+	};							\
+	static struct clk_tegra tegra_##_name##_hw = {		\
+		.hw = {						\
+			.clk = &tegra_##_name,			\
+		},						\
+		.flags = _flags,				\
+		.reg = _reg,					\
+		.max_rate = _max_rate,				\
+		.u.pll = {					\
+			.input_min = _input_min,		\
+			.input_max = _input_max,		\
+			.cf_min = _cf_min,			\
+			.cf_max = _cf_max,			\
+			.vco_min = _vco_min,			\
+			.vco_max = _vco_max,			\
+			.freq_table = _freq_table,		\
+			.lock_delay = _lock_delay,		\
+			.fixed_rate = _fixed_rate,		\
+		},						\
+		.clk_cfg_ex = _clk_cfg_ex,			\
+	};							\
+	DEFINE_CLK_TEGRA(_name, 0, &_ops, CLK_IGNORE_UNUSED,	\
+			 _name##_parent_names, _name##_parents,	\
+			&tegra_##_parent);
+
+#define DEFINE_PLL_OUT(_name, _flags, _reg, _reg_shift,		\
+		_max_rate, _ops, _parent, _clk_flags)		\
+	static const char *_name##_parent_names[] = {		\
+		#_parent,					\
+	};							\
+	static struct clk *_name##_parents[] = {		\
+		&tegra_##_parent,				\
+	};							\
+	static struct clk tegra_##_name;			\
+	static struct clk_tegra tegra_##_name##_hw = {		\
+		.hw = {						\
+			.clk = &tegra_##_name,			\
+		},						\
+		.flags = _flags,				\
+		.reg = _reg,					\
+		.max_rate = _max_rate,				\
+		.reg_shift = _reg_shift,			\
+	};							\
+	DEFINE_CLK_TEGRA(_name, 0, &tegra30_pll_div_ops,	\
+		_clk_flags,  _name##_parent_names,		\
+		_name##_parents, &tegra_##_parent);
+
+static struct clk_pll_freq_table tegra_pll_c_freq_table[] = {
+	{ 12000000, 1040000000, 520,  6, 1, 8},
+	{ 13000000, 1040000000, 480,  6, 1, 8},
+	{ 16800000, 1040000000, 495,  8, 1, 8},	/* actual: 1039.5 MHz */
+	{ 19200000, 1040000000, 325,  6, 1, 6},
+	{ 26000000, 1040000000, 520, 13, 1, 8},
+
+	{ 12000000, 832000000, 416,  6, 1, 8},
+	{ 13000000, 832000000, 832, 13, 1, 8},
+	{ 16800000, 832000000, 396,  8, 1, 8},	/* actual: 831.6 MHz */
+	{ 19200000, 832000000, 260,  6, 1, 8},
+	{ 26000000, 832000000, 416, 13, 1, 8},
+
+	{ 12000000, 624000000, 624, 12, 1, 8},
+	{ 13000000, 624000000, 624, 13, 1, 8},
+	{ 16800000, 600000000, 520, 14, 1, 8},
+	{ 19200000, 624000000, 520, 16, 1, 8},
+	{ 26000000, 624000000, 624, 26, 1, 8},
+
+	{ 12000000, 600000000, 600, 12, 1, 8},
+	{ 13000000, 600000000, 600, 13, 1, 8},
+	{ 16800000, 600000000, 500, 14, 1, 8},
+	{ 19200000, 600000000, 375, 12, 1, 6},
+	{ 26000000, 600000000, 600, 26, 1, 8},
+
+	{ 12000000, 520000000, 520, 12, 1, 8},
+	{ 13000000, 520000000, 520, 13, 1, 8},
+	{ 16800000, 520000000, 495, 16, 1, 8},	/* actual: 519.75 MHz */
+	{ 19200000, 520000000, 325, 12, 1, 6},
+	{ 26000000, 520000000, 520, 26, 1, 8},
+
+	{ 12000000, 416000000, 416, 12, 1, 8},
+	{ 13000000, 416000000, 416, 13, 1, 8},
+	{ 16800000, 416000000, 396, 16, 1, 8},	/* actual: 415.8 MHz */
+	{ 19200000, 416000000, 260, 12, 1, 6},
+	{ 26000000, 416000000, 416, 26, 1, 8},
+	{ 0, 0, 0, 0, 0, 0 },
+};
+
+DEFINE_PLL(pll_c, PLL_HAS_CPCON, 0x80, 1400000000, 2000000, 31000000, 1000000,
+		6000000, 20000000, 1400000000, tegra_pll_c_freq_table, 300,
+		tegra30_pll_ops, 0, NULL, pll_ref);
+
+DEFINE_PLL_OUT(pll_c_out1, DIV_U71, 0x84, 0, 700000000,
+		tegra30_pll_div_ops, pll_c, CLK_IGNORE_UNUSED);
+
+static struct clk_pll_freq_table tegra_pll_m_freq_table[] = {
+	{ 12000000, 666000000, 666, 12, 1, 8},
+	{ 13000000, 666000000, 666, 13, 1, 8},
+	{ 16800000, 666000000, 555, 14, 1, 8},
+	{ 19200000, 666000000, 555, 16, 1, 8},
+	{ 26000000, 666000000, 666, 26, 1, 8},
+	{ 12000000, 600000000, 600, 12, 1, 8},
+	{ 13000000, 600000000, 600, 13, 1, 8},
+	{ 16800000, 600000000, 500, 14, 1, 8},
+	{ 19200000, 600000000, 375, 12, 1, 6},
+	{ 26000000, 600000000, 600, 26, 1, 8},
+	{ 0, 0, 0, 0, 0, 0 },
+};
+
+DEFINE_PLL(pll_m, PLL_HAS_CPCON | PLLM, 0x90, 800000000, 2000000, 31000000,
+		1000000, 6000000, 20000000, 1200000000, tegra_pll_m_freq_table,
+		300, tegra30_pll_ops, 0, NULL, pll_ref);
+
+DEFINE_PLL_OUT(pll_m_out1, DIV_U71, 0x94, 0, 600000000,
+		tegra30_pll_div_ops, pll_m, CLK_IGNORE_UNUSED);
+
+static struct clk_pll_freq_table tegra_pll_p_freq_table[] = {
+	{ 12000000, 216000000, 432, 12, 2, 8},
+	{ 13000000, 216000000, 432, 13, 2, 8},
+	{ 16800000, 216000000, 360, 14, 2, 8},
+	{ 19200000, 216000000, 360, 16, 2, 8},
+	{ 26000000, 216000000, 432, 26, 2, 8},
+	{ 0, 0, 0, 0, 0, 0 },
+};
+
+DEFINE_PLL(pll_p, ENABLE_ON_INIT | PLL_FIXED | PLL_HAS_CPCON, 0xa0, 432000000,
+		2000000, 31000000, 1000000, 6000000, 20000000, 1400000000,
+		tegra_pll_p_freq_table, 300, tegra30_pll_ops, 408000000, NULL,
+		pll_ref);
+
+DEFINE_PLL_OUT(pll_p_out1, ENABLE_ON_INIT | DIV_U71 | DIV_U71_FIXED, 0xa4,
+		0, 432000000, tegra30_pll_div_ops, pll_p, CLK_IGNORE_UNUSED);
+DEFINE_PLL_OUT(pll_p_out2, ENABLE_ON_INIT | DIV_U71 | DIV_U71_FIXED, 0xa4,
+		16, 432000000, tegra30_pll_div_ops, pll_p, CLK_IGNORE_UNUSED);
+DEFINE_PLL_OUT(pll_p_out3, ENABLE_ON_INIT | DIV_U71 | DIV_U71_FIXED, 0xa8,
+		0, 432000000, tegra30_pll_div_ops, pll_p, CLK_IGNORE_UNUSED);
+DEFINE_PLL_OUT(pll_p_out4, ENABLE_ON_INIT | DIV_U71 | DIV_U71_FIXED, 0xa8,
+		16, 432000000, tegra30_pll_div_ops, pll_p, CLK_IGNORE_UNUSED);
+
+static struct clk_pll_freq_table tegra_pll_a_freq_table[] = {
+	{ 9600000, 564480000, 294, 5, 1, 4},
+	{ 9600000, 552960000, 288, 5, 1, 4},
+	{ 9600000, 24000000,  5,   2, 1, 1},
+
+	{ 28800000, 56448000, 49, 25, 1, 1},
+	{ 28800000, 73728000, 64, 25, 1, 1},
+	{ 28800000, 24000000,  5,  6, 1, 1},
+	{ 0, 0, 0, 0, 0, 0 },
+};
+
+DEFINE_PLL(pll_a, PLL_HAS_CPCON, 0xb0, 700000000, 2000000, 31000000, 1000000,
+		6000000, 20000000, 1400000000, tegra_pll_a_freq_table,
+		300, tegra30_pll_ops, 0, NULL, pll_p_out1);
+
+DEFINE_PLL_OUT(pll_a_out0, DIV_U71, 0xb4, 0, 100000000, tegra30_pll_div_ops,
+		pll_a, CLK_IGNORE_UNUSED);
+
+static struct clk_pll_freq_table tegra_pll_d_freq_table[] = {
+	{ 12000000, 216000000, 216, 12, 1, 4},
+	{ 13000000, 216000000, 216, 13, 1, 4},
+	{ 16800000, 216000000, 180, 14, 1, 4},
+	{ 19200000, 216000000, 180, 16, 1, 4},
+	{ 26000000, 216000000, 216, 26, 1, 4},
+
+	{ 12000000, 594000000, 594, 12, 1, 8},
+	{ 13000000, 594000000, 594, 13, 1, 8},
+	{ 16800000, 594000000, 495, 14, 1, 8},
+	{ 19200000, 594000000, 495, 16, 1, 8},
+	{ 26000000, 594000000, 594, 26, 1, 8},
+
+	{ 12000000, 1000000000, 1000, 12, 1, 12},
+	{ 13000000, 1000000000, 1000, 13, 1, 12},
+	{ 19200000, 1000000000, 625,  12, 1, 8},
+	{ 26000000, 1000000000, 1000, 26, 1, 12},
+
+	{ 0, 0, 0, 0, 0, 0 },
+};
+
+DEFINE_PLL(pll_d, PLL_HAS_CPCON | PLLD, 0xd0, 1000000000, 2000000, 40000000,
+		1000000, 6000000, 40000000, 1000000000, tegra_pll_d_freq_table,
+		1000, tegra30_pll_ops, 0, tegra30_plld_clk_cfg_ex, pll_ref);
+
+DEFINE_PLL_OUT(pll_d_out0, DIV_2 | PLLD, 0, 0, 500000000, tegra30_pll_div_ops,
+		pll_d, CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED);
+
+DEFINE_PLL(pll_d2, PLL_HAS_CPCON | PLL_ALT_MISC_REG | PLLD, 0x4b8, 1000000000,
+		2000000, 40000000, 1000000, 6000000, 40000000, 1000000000,
+		tegra_pll_d_freq_table, 1000, tegra30_pll_ops, 0, NULL,
+		pll_ref);
+
+DEFINE_PLL_OUT(pll_d2_out0, DIV_2 | PLLD, 0, 0, 500000000, tegra30_pll_div_ops,
+		pll_d2, CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED);
+
+static struct clk_pll_freq_table tegra_pll_u_freq_table[] = {
+	{ 12000000, 480000000, 960, 12, 2, 12},
+	{ 13000000, 480000000, 960, 13, 2, 12},
+	{ 16800000, 480000000, 400, 7,  2, 5},
+	{ 19200000, 480000000, 200, 4,  2, 3},
+	{ 26000000, 480000000, 960, 26, 2, 12},
+	{ 0, 0, 0, 0, 0, 0 },
+};
+
+DEFINE_PLL(pll_u, PLL_HAS_CPCON | PLLU, 0xc0, 480000000, 2000000, 40000000,
+		1000000, 6000000, 48000000, 960000000, tegra_pll_u_freq_table,
+		1000, tegra30_pll_ops, 0, NULL, pll_ref);
+
+static struct clk_pll_freq_table tegra_pll_x_freq_table[] = {
+	/* 1.7 GHz */
+	{ 12000000, 1700000000, 850,  6,  1, 8},
+	{ 13000000, 1700000000, 915,  7,  1, 8},	/* actual: 1699.2 MHz */
+	{ 16800000, 1700000000, 708,  7,  1, 8},	/* actual: 1699.2 MHz */
+	{ 19200000, 1700000000, 885,  10, 1, 8},	/* actual: 1699.2 MHz */
+	{ 26000000, 1700000000, 850,  13, 1, 8},
+
+	/* 1.6 GHz */
+	{ 12000000, 1600000000, 800,  6,  1, 8},
+	{ 13000000, 1600000000, 738,  6,  1, 8},	/* actual: 1599.0 MHz */
+	{ 16800000, 1600000000, 857,  9,  1, 8},	/* actual: 1599.7 MHz */
+	{ 19200000, 1600000000, 500,  6,  1, 8},
+	{ 26000000, 1600000000, 800,  13, 1, 8},
+
+	/* 1.5 GHz */
+	{ 12000000, 1500000000, 750,  6,  1, 8},
+	{ 13000000, 1500000000, 923,  8,  1, 8},	/* actual: 1499.8 MHz */
+	{ 16800000, 1500000000, 625,  7,  1, 8},
+	{ 19200000, 1500000000, 625,  8,  1, 8},
+	{ 26000000, 1500000000, 750,  13, 1, 8},
+
+	/* 1.4 GHz */
+	{ 12000000, 1400000000, 700,  6,  1, 8},
+	{ 13000000, 1400000000, 969,  9,  1, 8},	/* actual: 1399.7 MHz */
+	{ 16800000, 1400000000, 1000, 12, 1, 8},
+	{ 19200000, 1400000000, 875,  12, 1, 8},
+	{ 26000000, 1400000000, 700,  13, 1, 8},
+
+	/* 1.3 GHz */
+	{ 12000000, 1300000000, 975,  9,  1, 8},
+	{ 13000000, 1300000000, 1000, 10, 1, 8},
+	{ 16800000, 1300000000, 928,  12, 1, 8},	/* actual: 1299.2 MHz */
+	{ 19200000, 1300000000, 812,  12, 1, 8},	/* actual: 1299.2 MHz */
+	{ 26000000, 1300000000, 650,  13, 1, 8},
+
+	/* 1.2 GHz */
+	{ 12000000, 1200000000, 1000, 10, 1, 8},
+	{ 13000000, 1200000000, 923,  10, 1, 8},	/* actual: 1199.9 MHz */
+	{ 16800000, 1200000000, 1000, 14, 1, 8},
+	{ 19200000, 1200000000, 1000, 16, 1, 8},
+	{ 26000000, 1200000000, 600,  13, 1, 8},
+
+	/* 1.1 GHz */
+	{ 12000000, 1100000000, 825,  9,  1, 8},
+	{ 13000000, 1100000000, 846,  10, 1, 8},	/* actual: 1099.8 MHz */
+	{ 16800000, 1100000000, 982,  15, 1, 8},	/* actual: 1099.8 MHz */
+	{ 19200000, 1100000000, 859,  15, 1, 8},	/* actual: 1099.5 MHz */
+	{ 26000000, 1100000000, 550,  13, 1, 8},
+
+	/* 1 GHz */
+	{ 12000000, 1000000000, 1000, 12, 1, 8},
+	{ 13000000, 1000000000, 1000, 13, 1, 8},
+	{ 16800000, 1000000000, 833,  14, 1, 8},	/* actual: 999.6 MHz */
+	{ 19200000, 1000000000, 625,  12, 1, 8},
+	{ 26000000, 1000000000, 1000, 26, 1, 8},
+
+	{ 0, 0, 0, 0, 0, 0 },
+};
+
+DEFINE_PLL(pll_x, PLL_HAS_CPCON | PLL_ALT_MISC_REG | PLLX, 0xe0, 1700000000,
+		2000000, 31000000, 1000000, 6000000, 20000000, 1700000000,
+		tegra_pll_x_freq_table, 300, tegra30_pll_ops, 0, NULL, pll_ref);
+
+DEFINE_PLL_OUT(pll_x_out0, DIV_2 | PLLX, 0, 0, 850000000, tegra30_pll_div_ops,
+		pll_x, CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED);
+
+static struct clk_pll_freq_table tegra_pll_e_freq_table[] = {
+	/* PLLE special case: use cpcon field to store cml divider value */
+	{ 12000000,  100000000, 150, 1,  18, 11},
+	{ 216000000, 100000000, 200, 18, 24, 13},
+	{ 0, 0, 0, 0, 0, 0 },
+};
+
+DEFINE_PLL(pll_e, PLL_ALT_MISC_REG, 0xe8, 100000000, 2000000, 216000000,
+		12000000, 12000000, 1200000000, 2400000000U,
+		tegra_pll_e_freq_table, 300, tegra30_plle_ops, 100000000, NULL,
+		pll_ref);
+
+static const char *mux_plle[] = {
+	"pll_e",
+};
+
+static struct clk *mux_plle_p[] = {
+	&tegra_pll_e,
+};
+
+static struct clk tegra_cml0;
+static struct clk_tegra tegra_cml0_hw = {
+	.hw = {
+		.clk = &tegra_cml0,
+	},
+	.reg = 0x48c,
+	.fixed_rate = 100000000,
+	.u.periph = {
+		.clk_num = 0,
+	},
+};
+DEFINE_CLK_TEGRA(cml0, 0, &tegra_cml_clk_ops, 0, mux_plle,
+		mux_plle_p, &tegra_pll_e);
+
+static struct clk tegra_cml1;
+static struct clk_tegra tegra_cml1_hw = {
+	.hw = {
+		.clk = &tegra_cml1,
+	},
+	.reg = 0x48c,
+	.fixed_rate = 100000000,
+	.u.periph = {
+		.clk_num = 1,
+	},
+};
+DEFINE_CLK_TEGRA(cml1, 0, &tegra_cml_clk_ops, 0, mux_plle,
+		mux_plle_p, &tegra_pll_e);
+
+static struct clk tegra_pciex;
+static struct clk_tegra tegra_pciex_hw = {
+	.hw = {
+		.clk = &tegra_pciex,
+	},
+	.reg = 0x48c,
+	.fixed_rate = 100000000,
+	.reset = tegra30_periph_clk_reset,
+	.u.periph = {
+		.clk_num = 74,
+	},
+};
+DEFINE_CLK_TEGRA(pciex, 0, &tegra_pciex_clk_ops, 0, mux_plle,
+		mux_plle_p, &tegra_pll_e);
+
+#define SYNC_SOURCE(_name)					\
+	static struct clk tegra_##_name##_sync;			\
+	static struct clk_tegra tegra_##_name##_sync_hw = {	\
+		.hw = {						\
+			.clk = &tegra_##_name##_sync,		\
+		},						\
+		.max_rate = 24000000,				\
+		.fixed_rate = 24000000,				\
+	};							\
+	static struct clk tegra_##_name##_sync = {		\
+		.name = #_name "_sync",				\
+		.hw = &tegra_##_name##_sync_hw.hw,		\
+		.ops = &tegra_sync_source_ops,			\
+		.flags = CLK_IS_ROOT,				\
+	};
+
+SYNC_SOURCE(spdif_in);
+SYNC_SOURCE(i2s0);
+SYNC_SOURCE(i2s1);
+SYNC_SOURCE(i2s2);
+SYNC_SOURCE(i2s3);
+SYNC_SOURCE(i2s4);
+SYNC_SOURCE(vimclk);
+
+static struct clk *tegra_sync_source_list[] = {
+	&tegra_spdif_in_sync,
+	&tegra_i2s0_sync,
+	&tegra_i2s1_sync,
+	&tegra_i2s2_sync,
+	&tegra_i2s3_sync,
+	&tegra_i2s4_sync,
+	&tegra_vimclk_sync,
+};
+
+static const char *mux_audio_sync_clk[] = {
+	"spdif_in_sync",
+	"i2s0_sync",
+	"i2s1_sync",
+	"i2s2_sync",
+	"i2s3_sync",
+	"i2s4_sync",
+	"vimclk_sync",
+};
+
+#define AUDIO_SYNC_CLK(_name, _index)				\
+	static struct clk tegra_##_name;			\
+	static struct clk_tegra tegra_##_name##_hw = {		\
+		.hw = {						\
+			.clk = &tegra_##_name,			\
+		},						\
+		.max_rate = 24000000,				\
+		.reg = 0x4A0 + (_index) * 4,			\
+	};							\
+	static struct clk tegra_##_name = {			\
+		.name = #_name,					\
+		.ops = &tegra30_audio_sync_clk_ops,		\
+		.hw = &tegra_##_name##_hw.hw,			\
+		.parent_names = mux_audio_sync_clk,		\
+		.parents = tegra_sync_source_list,		\
+		.num_parents = ARRAY_SIZE(mux_audio_sync_clk),	\
+	};
+
+AUDIO_SYNC_CLK(audio0, 0);
+AUDIO_SYNC_CLK(audio1, 1);
+AUDIO_SYNC_CLK(audio2, 2);
+AUDIO_SYNC_CLK(audio3, 3);
+AUDIO_SYNC_CLK(audio4, 4);
+AUDIO_SYNC_CLK(audio5, 5);
+
+static struct clk *tegra_clk_audio_list[] = {
+	&tegra_audio0,
+	&tegra_audio1,
+	&tegra_audio2,
+	&tegra_audio3,
+	&tegra_audio4,
+	&tegra_audio5,	/* SPDIF */
+};
+
+#define AUDIO_SYNC_2X_CLK(_name, _index)			\
+	static const char *_name##_parent_names[] = {		\
+		"tegra_" #_name,				\
+	};							\
+	static struct clk *_name##_parents[] = {		\
+		&tegra_##_name,					\
+	};							\
+	static struct clk tegra_##_name##_2x;			\
+	static struct clk_tegra tegra_##_name##_2x_hw = {	\
+		.hw = {						\
+			.clk = &tegra_##_name##_2x,		\
+		},						\
+		.flags = PERIPH_NO_RESET,			\
+		.max_rate = 48000000,				\
+		.reg = 0x49C,					\
+		.reg_shift = 24 + (_index),			\
+		.u.periph = {					\
+			.clk_num = 113 + (_index),		\
+		},						\
+	};							\
+	static struct clk tegra_##_name##_2x = {		\
+		.name = #_name "_2x",				\
+		.ops = &tegra30_clk_double_ops,			\
+		.hw = &tegra_##_name##_2x_hw.hw,		\
+		.parent_names = _name##_parent_names,		\
+		.parents = _name##_parents,			\
+		.parent = &tegra_##_name,			\
+		.num_parents = 1,				\
+	};
+
+AUDIO_SYNC_2X_CLK(audio0, 0);
+AUDIO_SYNC_2X_CLK(audio1, 1);
+AUDIO_SYNC_2X_CLK(audio2, 2);
+AUDIO_SYNC_2X_CLK(audio3, 3);
+AUDIO_SYNC_2X_CLK(audio4, 4);
+AUDIO_SYNC_2X_CLK(audio5, 5);	/* SPDIF */
+
+static struct clk *tegra_clk_audio_2x_list[] = {
+	&tegra_audio0_2x,
+	&tegra_audio1_2x,
+	&tegra_audio2_2x,
+	&tegra_audio3_2x,
+	&tegra_audio4_2x,
+	&tegra_audio5_2x,	/* SPDIF */
+};
+
+#define MUX_I2S_SPDIF(_id)					\
+static const char *mux_pllaout0_##_id##_2x_pllp_clkm[] = {	\
+	"pll_a_out0",						\
+	#_id "_2x",						\
+	"pll_p",						\
+	"clk_m",						\
+};								\
+static struct clk *mux_pllaout0_##_id##_2x_pllp_clkm_p[] = {	\
+	&tegra_pll_a_out0,					\
+	&tegra_##_id##_2x,					\
+	&tegra_pll_p,						\
+	&tegra_clk_m,						\
+};
+
+MUX_I2S_SPDIF(audio0);
+MUX_I2S_SPDIF(audio1);
+MUX_I2S_SPDIF(audio2);
+MUX_I2S_SPDIF(audio3);
+MUX_I2S_SPDIF(audio4);
+MUX_I2S_SPDIF(audio5);		/* SPDIF */
+
+static struct clk tegra_extern1;
+static struct clk tegra_extern2;
+static struct clk tegra_extern3;
+
+/* External clock outputs (through PMC) */
+#define MUX_EXTERN_OUT(_id)					\
+static const char *mux_clkm_clkm2_clkm4_extern##_id[] = {	\
+	"clk_m",						\
+	"clk_m_div2",						\
+	"clk_m_div4",						\
+	"extern" #_id,						\
+};								\
+static struct clk *mux_clkm_clkm2_clkm4_extern##_id##_p[] = {	\
+	&tegra_clk_m,						\
+	&tegra_clk_m_div2,					\
+	&tegra_clk_m_div4,					\
+	&tegra_extern##_id,					\
+};
+
+MUX_EXTERN_OUT(1);
+MUX_EXTERN_OUT(2);
+MUX_EXTERN_OUT(3);
+
+#define CLK_OUT_CLK(_name, _index)					\
+	static struct clk tegra_##_name;				\
+	static struct clk_tegra tegra_##_name##_hw = {			\
+		.hw = {							\
+			.clk = &tegra_##_name,				\
+		},							\
+		.lookup = {						\
+			.dev_id	= #_name,				\
+			.con_id	= "extern" #_index,			\
+		},							\
+		.flags = MUX_CLK_OUT,					\
+		.fixed_rate = 216000000,					\
+		.reg = 0x1a8,						\
+		.u.periph = {						\
+			.clk_num = (_index - 1) * 8 + 2,		\
+		},							\
+	};								\
+	static struct clk tegra_##_name = {				\
+		.name = #_name,						\
+		.ops = &tegra_clk_out_ops,				\
+		.hw = &tegra_##_name##_hw.hw,				\
+		.parent_names = mux_clkm_clkm2_clkm4_extern##_index,	\
+		.parents = mux_clkm_clkm2_clkm4_extern##_index##_p,	\
+		.num_parents = ARRAY_SIZE(mux_clkm_clkm2_clkm4_extern##_index),\
+	};
+
+CLK_OUT_CLK(clk_out_1, 1);
+CLK_OUT_CLK(clk_out_2, 2);
+CLK_OUT_CLK(clk_out_3, 3);
+
+static struct clk *tegra_clk_out_list[] = {
+	&tegra_clk_out_1,
+	&tegra_clk_out_2,
+	&tegra_clk_out_3,
+};
+
+static const char *mux_sclk[] = {
+	"clk_m",
+	"pll_c_out1",
+	"pll_p_out4",
+	"pll_p_out3",
+	"pll_p_out2",
+	"dummy",
+	"clk_32k",
+	"pll_m_out1",
+};
+
+static struct clk *mux_sclk_p[] = {
+	&tegra_clk_m,
+	&tegra_pll_c_out1,
+	&tegra_pll_p_out4,
+	&tegra_pll_p_out3,
+	&tegra_pll_p_out2,
+	NULL,
+	&tegra_clk_32k,
+	&tegra_pll_m_out1,
+};
+
+static struct clk tegra_clk_sclk;
+static struct clk_tegra tegra_clk_sclk_hw = {
+	.hw = {
+		.clk = &tegra_clk_sclk,
+	},
+	.reg = 0x28,
+	.max_rate = 334000000,
+	.min_rate = 40000000,
+};
+
+static struct clk tegra_clk_sclk = {
+	.name = "sclk",
+	.ops = &tegra30_super_ops,
+	.hw = &tegra_clk_sclk_hw.hw,
+	.parent_names = mux_sclk,
+	.parents = mux_sclk_p,
+	.num_parents = ARRAY_SIZE(mux_sclk),
+};
+
+static const char *mux_blink[] = {
+	"clk_32k",
+};
+
+static struct clk *mux_blink_p[] = {
+	&tegra_clk_32k,
+};
+
+static struct clk tegra_clk_blink;
+static struct clk_tegra tegra_clk_blink_hw = {
+	.hw = {
+		.clk = &tegra_clk_blink,
+	},
+	.reg = 0x40,
+	.max_rate = 32768,
+};
+static struct clk tegra_clk_blink = {
+	.name = "blink",
+	.ops = &tegra30_blink_clk_ops,
+	.hw = &tegra_clk_blink_hw.hw,
+	.parent = &tegra_clk_32k,
+	.parent_names = mux_blink,
+	.parents = mux_blink_p,
+	.num_parents = ARRAY_SIZE(mux_blink),
+};
+
+static const char *mux_pllm_pllc_pllp_plla[] = {
+	"pll_m",
+	"pll_c",
+	"pll_p",
+	"pll_a_out0",
+};
+
+static const char *mux_pllp_pllc_pllm_clkm[] = {
+	"pll_p",
+	"pll_c",
+	"pll_m",
+	"clk_m",
+};
+
+static const char *mux_pllp_clkm[] = {
+	"pll_p",
+	"dummy",
+	"dummy",
+	"clk_m",
+};
+
+static const char *mux_pllp_plld_pllc_clkm[] = {
+	"pll_p",
+	"pll_d_out0",
+	"pll_c",
+	"clk_m",
+};
+
+static const char *mux_pllp_pllm_plld_plla_pllc_plld2_clkm[] = {
+	"pll_p",
+	"pll_m",
+	"pll_d_out0",
+	"pll_a_out0",
+	"pll_c",
+	"pll_d2_out0",
+	"clk_m",
+};
+
+static const char *mux_plla_pllc_pllp_clkm[] = {
+	"pll_a_out0",
+	"dummy",
+	"pll_p",
+	"clk_m"
+};
+
+static const char *mux_pllp_pllc_clk32_clkm[] = {
+	"pll_p",
+	"pll_c",
+	"clk_32k",
+	"clk_m",
+};
+
+static const char *mux_pllp_pllc_clkm_clk32[] = {
+	"pll_p",
+	"pll_c",
+	"clk_m",
+	"clk_32k",
+};
+
+static const char *mux_pllp_pllc_pllm[] = {
+	"pll_p",
+	"pll_c",
+	"pll_m",
+};
+
+static const char *mux_clk_m[] = {
+	"clk_m",
+};
+
+static const char *mux_pllp_out3[] = {
+	"pll_p_out3",
+};
+
+static const char *mux_plld_out0[] = {
+	"pll_d_out0",
+};
+
+static const char *mux_plld_out0_plld2_out0[] = {
+	"pll_d_out0",
+	"pll_d2_out0",
+};
+
+static const char *mux_clk_32k[] = {
+	"clk_32k",
+};
+
+static const char *mux_plla_clk32_pllp_clkm_plle[] = {
+	"pll_a_out0",
+	"clk_32k",
+	"pll_p",
+	"clk_m",
+	"pll_e",
+};
+
+static const char *mux_cclk_g[] = {
+	"clk_m",
+	"pll_c",
+	"clk_32k",
+	"pll_m",
+	"pll_p",
+	"pll_p_out4",
+	"pll_p_out3",
+	"dummy",
+	"pll_x",
+};
+
+static struct clk *mux_pllm_pllc_pllp_plla_p[] = {
+	&tegra_pll_m,
+	&tegra_pll_c,
+	&tegra_pll_p,
+	&tegra_pll_a_out0,
+};
+
+static struct clk *mux_pllp_pllc_pllm_clkm_p[] = {
+	&tegra_pll_p,
+	&tegra_pll_c,
+	&tegra_pll_m,
+	&tegra_clk_m,
+};
+
+static struct clk *mux_pllp_clkm_p[] = {
+	&tegra_pll_p,
+	NULL,
+	NULL,
+	&tegra_clk_m,
+};
+
+static struct clk *mux_pllp_plld_pllc_clkm_p[] = {
+	&tegra_pll_p,
+	&tegra_pll_d_out0,
+	&tegra_pll_c,
+	&tegra_clk_m,
+};
+
+static struct clk *mux_pllp_pllm_plld_plla_pllc_plld2_clkm_p[] = {
+	&tegra_pll_p,
+	&tegra_pll_m,
+	&tegra_pll_d_out0,
+	&tegra_pll_a_out0,
+	&tegra_pll_c,
+	&tegra_pll_d2_out0,
+	&tegra_clk_m,
+};
+
+static struct clk *mux_plla_pllc_pllp_clkm_p[] = {
+	&tegra_pll_a_out0,
+	NULL,
+	&tegra_pll_p,
+	&tegra_clk_m,
+};
+
+static struct clk *mux_pllp_pllc_clk32_clkm_p[] = {
+	&tegra_pll_p,
+	&tegra_pll_c,
+	&tegra_clk_32k,
+	&tegra_clk_m,
+};
+
+static struct clk *mux_pllp_pllc_clkm_clk32_p[] = {
+	&tegra_pll_p,
+	&tegra_pll_c,
+	&tegra_clk_m,
+	&tegra_clk_32k,
+};
+
+static struct clk *mux_pllp_pllc_pllm_p[] = {
+	&tegra_pll_p,
+	&tegra_pll_c,
+	&tegra_pll_m,
+};
+
+static struct clk *mux_clk_m_p[] = {
+	&tegra_clk_m,
+};
+
+static struct clk *mux_pllp_out3_p[] = {
+	&tegra_pll_p_out3,
+};
+
+static struct clk *mux_plld_out0_p[] = {
+	&tegra_pll_d_out0,
+};
+
+static struct clk *mux_plld_out0_plld2_out0_p[] = {
+	&tegra_pll_d_out0,
+	&tegra_pll_d2_out0,
+};
+
+static struct clk *mux_clk_32k_p[] = {
+	&tegra_clk_32k,
+};
+
+static struct clk *mux_plla_clk32_pllp_clkm_plle_p[] = {
+	&tegra_pll_a_out0,
+	&tegra_clk_32k,
+	&tegra_pll_p,
+	&tegra_clk_m,
+	&tegra_pll_e,
+};
+
+static struct clk *mux_cclk_g_p[] = {
+	&tegra_clk_m,
+	&tegra_pll_c,
+	&tegra_clk_32k,
+	&tegra_pll_m,
+	&tegra_pll_p,
+	&tegra_pll_p_out4,
+	&tegra_pll_p_out3,
+	NULL,
+	&tegra_pll_x,
+};
+
+static struct clk tegra_clk_cclk_g;
+static struct clk_tegra tegra_clk_cclk_g_hw = {
+	.hw = {
+		.clk = &tegra_clk_cclk_g,
+	},
+	.flags = DIV_U71 | DIV_U71_INT,
+	.reg = 0x368,
+	.max_rate = 1700000000,
+};
+static struct clk tegra_clk_cclk_g = {
+	.name = "cclk_g",
+	.ops = &tegra30_super_ops,
+	.hw = &tegra_clk_cclk_g_hw.hw,
+	.parent_names = mux_cclk_g,
+	.parents = mux_cclk_g_p,
+	.num_parents = ARRAY_SIZE(mux_cclk_g),
+};
+
+static const char *mux_twd[] = {
+	"cclk_g",
+};
+
+static struct clk *mux_twd_p[] = {
+	&tegra_clk_cclk_g,
+};
+
+static struct clk tegra30_clk_twd;
+static struct clk_tegra tegra30_clk_twd_hw = {
+	.hw = {
+		.clk = &tegra30_clk_twd,
+	},
+	.max_rate = 1400000000,
+	.mul = 1,
+	.div = 2,
+};
+
+static struct clk tegra30_clk_twd = {
+	.name = "twd",
+	.ops = &tegra30_twd_ops,
+	.hw = &tegra30_clk_twd_hw.hw,
+	.parent = &tegra_clk_cclk_g,
+	.parent_names = mux_twd,
+	.parents = mux_twd_p,
+	.num_parents = ARRAY_SIZE(mux_twd),
+};
+
+#define PERIPH_CLK(_name, _dev, _con, _clk_num, _reg,	\
+		_max, _inputs, _flags)	 		\
+	static struct clk tegra_##_name;		\
+	static struct clk_tegra tegra_##_name##_hw = {	\
+		.hw = {					\
+			.clk = &tegra_##_name,		\
+		},					\
+		.lookup = {				\
+			.dev_id	= _dev,			\
+			.con_id	= _con,			\
+		},					\
+		.reg = _reg,				\
+		.flags = _flags,			\
+		.max_rate = _max,			\
+		.u.periph = {				\
+			.clk_num = _clk_num,		\
+		},					\
+		.reset = &tegra30_periph_clk_reset,	\
+	};						\
+	static struct clk tegra_##_name = {		\
+		.name = #_name,				\
+		.ops = &tegra30_periph_clk_ops,		\
+		.hw = &tegra_##_name##_hw.hw,		\
+		.parent_names = _inputs,		\
+		.parents = _inputs##_p,			\
+		.num_parents = ARRAY_SIZE(_inputs),	\
+	};
+
+PERIPH_CLK(apbdma,	"tegra-apbdma",		NULL,	34,	0,	26000000,  mux_clk_m,			0);
+PERIPH_CLK(rtc,		"rtc-tegra",		NULL,	4,	0,	32768,     mux_clk_32k,			PERIPH_NO_RESET | PERIPH_ON_APB);
+PERIPH_CLK(kbc,		"tegra-kbc",		NULL,	36,	0,	32768,     mux_clk_32k,			PERIPH_NO_RESET | PERIPH_ON_APB);
+PERIPH_CLK(timer,	"timer",		NULL,	5,	0,	26000000,  mux_clk_m,			0);
+PERIPH_CLK(kfuse,	"kfuse-tegra",		NULL,	40,	0,	26000000,  mux_clk_m,			0);
+PERIPH_CLK(fuse,	"fuse-tegra",		"fuse",	39,	0,	26000000,  mux_clk_m,			PERIPH_ON_APB);
+PERIPH_CLK(fuse_burn,	"fuse-tegra",		"fuse_burn",	39,	0,	26000000,  mux_clk_m,		PERIPH_ON_APB);
+PERIPH_CLK(apbif,	"tegra30-ahub",		"apbif", 107,	0,	26000000,  mux_clk_m,			0);
+PERIPH_CLK(i2s0,	"tegra30-i2s.0",	NULL,	30,	0x1d8,	26000000,  mux_pllaout0_audio0_2x_pllp_clkm,	MUX | DIV_U71 | PERIPH_ON_APB);
+PERIPH_CLK(i2s1,	"tegra30-i2s.1",	NULL,	11,	0x100,	26000000,  mux_pllaout0_audio1_2x_pllp_clkm,	MUX | DIV_U71 | PERIPH_ON_APB);
+PERIPH_CLK(i2s2,	"tegra30-i2s.2",	NULL,	18,	0x104,	26000000,  mux_pllaout0_audio2_2x_pllp_clkm,	MUX | DIV_U71 | PERIPH_ON_APB);
+PERIPH_CLK(i2s3,	"tegra30-i2s.3",	NULL,	101,	0x3bc,	26000000,  mux_pllaout0_audio3_2x_pllp_clkm,	MUX | DIV_U71 | PERIPH_ON_APB);
+PERIPH_CLK(i2s4,	"tegra30-i2s.4",	NULL,	102,	0x3c0,	26000000,  mux_pllaout0_audio4_2x_pllp_clkm,	MUX | DIV_U71 | PERIPH_ON_APB);
+PERIPH_CLK(spdif_out,	"tegra30-spdif",	"spdif_out",	10,	0x108,	100000000, mux_pllaout0_audio5_2x_pllp_clkm,	MUX | DIV_U71 | PERIPH_ON_APB);
+PERIPH_CLK(spdif_in,	"tegra30-spdif",	"spdif_in",	10,	0x10c,	100000000, mux_pllp_pllc_pllm,		MUX | DIV_U71 | PERIPH_ON_APB);
+PERIPH_CLK(pwm,		"tegra-pwm",		NULL,	17,	0x110,	432000000, mux_pllp_pllc_clk32_clkm,	MUX | MUX_PWM | DIV_U71 | PERIPH_ON_APB);
+PERIPH_CLK(d_audio,	"tegra30-ahub",		"d_audio", 106,	0x3d0,	48000000,  mux_plla_pllc_pllp_clkm,	MUX | DIV_U71);
+PERIPH_CLK(dam0,	"tegra30-dam.0",	NULL,	108,	0x3d8,	48000000,  mux_plla_pllc_pllp_clkm,	MUX | DIV_U71);
+PERIPH_CLK(dam1,	"tegra30-dam.1",	NULL,	109,	0x3dc,	48000000,  mux_plla_pllc_pllp_clkm,	MUX | DIV_U71);
+PERIPH_CLK(dam2,	"tegra30-dam.2",	NULL,	110,	0x3e0,	48000000,  mux_plla_pllc_pllp_clkm,	MUX | DIV_U71);
+PERIPH_CLK(hda,		"tegra30-hda",		"hda",	125,	0x428,	108000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71);
+PERIPH_CLK(hda2codec_2x,	"tegra30-hda",	"hda2codec",	111,	0x3e4,	48000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71);
+PERIPH_CLK(hda2hdmi,	"tegra30-hda",		"hda2hdmi",	128,	0,	48000000,  mux_clk_m,			0);
+PERIPH_CLK(sbc1,	"spi_tegra.0",		NULL,	41,	0x134,	160000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71 | PERIPH_ON_APB);
+PERIPH_CLK(sbc2,	"spi_tegra.1",		NULL,	44,	0x118,	160000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71 | PERIPH_ON_APB);
+PERIPH_CLK(sbc3,	"spi_tegra.2",		NULL,	46,	0x11c,	160000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71 | PERIPH_ON_APB);
+PERIPH_CLK(sbc4,	"spi_tegra.3",		NULL,	68,	0x1b4,	160000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71 | PERIPH_ON_APB);
+PERIPH_CLK(sbc5,	"spi_tegra.4",		NULL,	104,	0x3c8,	160000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71 | PERIPH_ON_APB);
+PERIPH_CLK(sbc6,	"spi_tegra.5",		NULL,	105,	0x3cc,	160000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71 | PERIPH_ON_APB);
+PERIPH_CLK(sata_oob,	"tegra_sata_oob",	NULL,	123,	0x420,	216000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71);
+PERIPH_CLK(sata,	"tegra_sata",		NULL,	124,	0x424,	216000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71);
+PERIPH_CLK(sata_cold,	"tegra_sata_cold",	NULL,	129,	0,	48000000,  mux_clk_m,			0);
+PERIPH_CLK(ndflash,	"tegra_nand",		NULL,	13,	0x160,	240000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71);
+PERIPH_CLK(ndspeed,	"tegra_nand_speed",	NULL,	80,	0x3f8,	240000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71);
+PERIPH_CLK(vfir,	"vfir",			NULL,	7,	0x168,	72000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71 | PERIPH_ON_APB);
+PERIPH_CLK(sdmmc1,	"sdhci-tegra.0",	NULL,	14,	0x150,	208000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71); /* scales with voltage */
+PERIPH_CLK(sdmmc2,	"sdhci-tegra.1",	NULL,	9,	0x154,	104000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71); /* scales with voltage */
+PERIPH_CLK(sdmmc3,	"sdhci-tegra.2",	NULL,	69,	0x1bc,	208000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71); /* scales with voltage */
+PERIPH_CLK(sdmmc4,	"sdhci-tegra.3",	NULL,	15,	0x164,	104000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71); /* scales with voltage */
+PERIPH_CLK(vcp,		"tegra-avp",		"vcp",	29,	0,	250000000, mux_clk_m,			0);
+PERIPH_CLK(bsea,	"tegra-avp",		"bsea",	62,	0,	250000000, mux_clk_m,			0);
+PERIPH_CLK(bsev,	"tegra-aes",		"bsev",	63,	0,	250000000, mux_clk_m,			0);
+PERIPH_CLK(vde,		"vde",			NULL,	61,	0x1c8,	520000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71 | DIV_U71_INT);
+PERIPH_CLK(csite,	"csite",		NULL,	73,	0x1d4,	144000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71); /* max rate ??? */
+PERIPH_CLK(la,		"la",			NULL,	76,	0x1f8,	26000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71);
+PERIPH_CLK(owr,		"tegra_w1",		NULL,	71,	0x1cc,	26000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71 | PERIPH_ON_APB);
+PERIPH_CLK(nor,		"nor",			NULL,	42,	0x1d0,	127000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71); /* requires min voltage */
+PERIPH_CLK(mipi,	"mipi",			NULL,	50,	0x174,	60000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71 | PERIPH_ON_APB); /* scales with voltage */
+PERIPH_CLK(i2c1,	"tegra-i2c.0",		"div-clk", 12,	0x124,	26000000,  mux_pllp_clkm,		MUX | DIV_U16 | PERIPH_ON_APB);
+PERIPH_CLK(i2c2,	"tegra-i2c.1",		"div-clk", 54,	0x198,	26000000,  mux_pllp_clkm,		MUX | DIV_U16 | PERIPH_ON_APB);
+PERIPH_CLK(i2c3,	"tegra-i2c.2",		"div-clk", 67,	0x1b8,	26000000,  mux_pllp_clkm,		MUX | DIV_U16 | PERIPH_ON_APB);
+PERIPH_CLK(i2c4,	"tegra-i2c.3",		"div-clk", 103,	0x3c4,	26000000,  mux_pllp_clkm,		MUX | DIV_U16 | PERIPH_ON_APB);
+PERIPH_CLK(i2c5,	"tegra-i2c.4",		"div-clk", 47,	0x128,	26000000,  mux_pllp_clkm,		MUX | DIV_U16 | PERIPH_ON_APB);
+PERIPH_CLK(uarta,	"tegra-uart.0",		NULL,	6,	0x178,	800000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB);
+PERIPH_CLK(uartb,	"tegra-uart.1",		NULL,	7,	0x17c,	800000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB);
+PERIPH_CLK(uartc,	"tegra-uart.2",		NULL,	55,	0x1a0,	800000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB);
+PERIPH_CLK(uartd,	"tegra-uart.3",		NULL,	65,	0x1c0,	800000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB);
+PERIPH_CLK(uarte,	"tegra-uart.4",		NULL,	66,	0x1c4,	800000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB);
+PERIPH_CLK(vi,		"tegra_camera",		"vi",	20,	0x148,	425000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71 | DIV_U71_INT);
+PERIPH_CLK(3d,		"3d",			NULL,	24,	0x158,	520000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71 | DIV_U71_INT | DIV_U71_IDLE | PERIPH_MANUAL_RESET);
+PERIPH_CLK(3d2,		"3d2",			NULL,	98,	0x3b0,	520000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71 | DIV_U71_INT | DIV_U71_IDLE | PERIPH_MANUAL_RESET);
+PERIPH_CLK(2d,		"2d",			NULL,	21,	0x15c,	520000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71 | DIV_U71_INT | DIV_U71_IDLE);
+PERIPH_CLK(vi_sensor,	"tegra_camera",		"vi_sensor",	20,	0x1a8,	150000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71 | PERIPH_NO_RESET);
+PERIPH_CLK(epp,		"epp",			NULL,	19,	0x16c,	520000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71 | DIV_U71_INT);
+PERIPH_CLK(mpe,		"mpe",			NULL,	60,	0x170,	520000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71 | DIV_U71_INT);
+PERIPH_CLK(host1x,	"host1x",		NULL,	28,	0x180,	260000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71 | DIV_U71_INT);
+PERIPH_CLK(cve,		"cve",			NULL,	49,	0x140,	250000000, mux_pllp_plld_pllc_clkm,	MUX | DIV_U71); /* requires min voltage */
+PERIPH_CLK(tvo,		"tvo",			NULL,	49,	0x188,	250000000, mux_pllp_plld_pllc_clkm,	MUX | DIV_U71); /* requires min voltage */
+PERIPH_CLK(dtv,		"dtv",			NULL,	79,	0x1dc,	250000000, mux_clk_m,			0);
+PERIPH_CLK(hdmi,	"hdmi",			NULL,	51,	0x18c,	148500000, mux_pllp_pllm_plld_plla_pllc_plld2_clkm,	MUX | MUX8 | DIV_U71);
+PERIPH_CLK(tvdac,	"tvdac",		NULL,	53,	0x194,	220000000, mux_pllp_plld_pllc_clkm,	MUX | DIV_U71); /* requires min voltage */
+PERIPH_CLK(disp1,	"tegradc.0",		NULL,	27,	0x138,	600000000, mux_pllp_pllm_plld_plla_pllc_plld2_clkm,	MUX | MUX8);
+PERIPH_CLK(disp2,	"tegradc.1",		NULL,	26,	0x13c,	600000000, mux_pllp_pllm_plld_plla_pllc_plld2_clkm,	MUX | MUX8);
+PERIPH_CLK(usbd,	"fsl-tegra-udc",	NULL,	22,	0,	480000000, mux_clk_m,			0); /* requires min voltage */
+PERIPH_CLK(usb2,	"tegra-ehci.1",		NULL,	58,	0,	480000000, mux_clk_m,			0); /* requires min voltage */
+PERIPH_CLK(usb3,	"tegra-ehci.2",		NULL,	59,	0,	480000000, mux_clk_m,			0); /* requires min voltage */
+PERIPH_CLK(dsia,	"tegradc.0",		"dsia",	48,	0,	500000000, mux_plld_out0,		0);
+PERIPH_CLK(csi,		"tegra_camera",		"csi",	52,	0,	102000000, mux_pllp_out3,		0);
+PERIPH_CLK(isp,		"tegra_camera",		"isp",	23,	0,	150000000, mux_clk_m,			0); /* same frequency as VI */
+PERIPH_CLK(csus,	"tegra_camera",		"csus",	92,	0,	150000000, mux_clk_m,			PERIPH_NO_RESET);
+PERIPH_CLK(tsensor,	"tegra-tsensor",	NULL,	100,	0x3b8,	216000000, mux_pllp_pllc_clkm_clk32,	MUX | DIV_U71);
+PERIPH_CLK(actmon,	"actmon",		NULL,	119,	0x3e8,	216000000, mux_pllp_pllc_clk32_clkm,	MUX | DIV_U71);
+PERIPH_CLK(extern1,	"extern1",		NULL,	120,	0x3ec,	216000000, mux_plla_clk32_pllp_clkm_plle,	MUX | MUX8 | DIV_U71);
+PERIPH_CLK(extern2,	"extern2",		NULL,	121,	0x3f0,	216000000, mux_plla_clk32_pllp_clkm_plle,	MUX | MUX8 | DIV_U71);
+PERIPH_CLK(extern3,	"extern3",		NULL,	122,	0x3f4,	216000000, mux_plla_clk32_pllp_clkm_plle,	MUX | MUX8 | DIV_U71);
+PERIPH_CLK(i2cslow,	"i2cslow",		NULL,	81,	0x3fc,	26000000,  mux_pllp_pllc_clk32_clkm,	MUX | DIV_U71 | PERIPH_ON_APB);
+PERIPH_CLK(pcie,	"tegra-pcie",		"pcie",	70,	0,	250000000, mux_clk_m,			0);
+PERIPH_CLK(afi,		"tegra-pcie",		"afi",	72,	0,	250000000, mux_clk_m,			0);
+PERIPH_CLK(se,		"se",			NULL,	127,	0x42c,	520000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71 | DIV_U71_INT);
+
+static struct clk tegra_dsib;
+static struct clk_tegra tegra_dsib_hw = {
+	.hw = {
+		.clk = &tegra_dsib,
+	},
+	.lookup = {
+		.dev_id	= "tegradc.1",
+		.con_id	= "dsib",
+	},
+	.reg = 0xd0,
+	.flags = MUX | PLLD,
+	.max_rate = 500000000,
+	.u.periph = {
+		.clk_num = 82,
+	},
+	.reset = &tegra30_periph_clk_reset,
+};
+static struct clk tegra_dsib = {
+	.name = "dsib",
+	.ops = &tegra30_dsib_clk_ops,
+	.hw = &tegra_dsib_hw.hw,
+	.parent_names = mux_plld_out0_plld2_out0,
+	.parents = mux_plld_out0_plld2_out0_p,
+	.num_parents = ARRAY_SIZE(mux_plld_out0_plld2_out0),
+};
+
+struct clk *tegra_list_clks[] = {
+	&tegra_apbdma,
+	&tegra_rtc,
+	&tegra_kbc,
+	&tegra_kfuse,
+	&tegra_fuse,
+	&tegra_fuse_burn,
+	&tegra_apbif,
+	&tegra_i2s0,
+	&tegra_i2s1,
+	&tegra_i2s2,
+	&tegra_i2s3,
+	&tegra_i2s4,
+	&tegra_spdif_out,
+	&tegra_spdif_in,
+	&tegra_pwm,
+	&tegra_d_audio,
+	&tegra_dam0,
+	&tegra_dam1,
+	&tegra_dam2,
+	&tegra_hda,
+	&tegra_hda2codec_2x,
+	&tegra_hda2hdmi,
+	&tegra_sbc1,
+	&tegra_sbc2,
+	&tegra_sbc3,
+	&tegra_sbc4,
+	&tegra_sbc5,
+	&tegra_sbc6,
+	&tegra_sata_oob,
+	&tegra_sata,
+	&tegra_sata_cold,
+	&tegra_ndflash,
+	&tegra_ndspeed,
+	&tegra_vfir,
+	&tegra_sdmmc1,
+	&tegra_sdmmc2,
+	&tegra_sdmmc3,
+	&tegra_sdmmc4,
+	&tegra_vcp,
+	&tegra_bsea,
+	&tegra_bsev,
+	&tegra_vde,
+	&tegra_csite,
+	&tegra_la,
+	&tegra_owr,
+	&tegra_nor,
+	&tegra_mipi,
+	&tegra_i2c1,
+	&tegra_i2c2,
+	&tegra_i2c3,
+	&tegra_i2c4,
+	&tegra_i2c5,
+	&tegra_uarta,
+	&tegra_uartb,
+	&tegra_uartc,
+	&tegra_uartd,
+	&tegra_uarte,
+	&tegra_vi,
+	&tegra_3d,
+	&tegra_3d2,
+	&tegra_2d,
+	&tegra_vi_sensor,
+	&tegra_epp,
+	&tegra_mpe,
+	&tegra_host1x,
+	&tegra_cve,
+	&tegra_tvo,
+	&tegra_dtv,
+	&tegra_hdmi,
+	&tegra_tvdac,
+	&tegra_disp1,
+	&tegra_disp2,
+	&tegra_usbd,
+	&tegra_usb2,
+	&tegra_usb3,
+	&tegra_dsia,
+	&tegra_dsib,
+	&tegra_csi,
+	&tegra_isp,
+	&tegra_csus,
+	&tegra_tsensor,
+	&tegra_actmon,
+	&tegra_extern1,
+	&tegra_extern2,
+	&tegra_extern3,
+	&tegra_i2cslow,
+	&tegra_pcie,
+	&tegra_afi,
+	&tegra_se,
+};
+
+#define CLK_DUPLICATE(_name, _dev, _con)	\
+	{					\
+		.name	= _name,		\
+		.lookup	= {			\
+			.dev_id	= _dev,		\
+			.con_id	= _con,		\
+		},				\
+	}
+
+/* Some clocks may be used by different drivers depending on the board
+ * configuration.  List those here to register them twice in the clock lookup
+ * table under two names.
+ */
+struct clk_duplicate tegra_clk_duplicates[] = {
+	CLK_DUPLICATE("uarta",  "serial8250.0", NULL),
+	CLK_DUPLICATE("uartb",  "serial8250.1", NULL),
+	CLK_DUPLICATE("uartc",  "serial8250.2", NULL),
+	CLK_DUPLICATE("uartd",  "serial8250.3", NULL),
+	CLK_DUPLICATE("uarte",  "serial8250.4", NULL),
+	CLK_DUPLICATE("usbd", "utmip-pad", NULL),
+	CLK_DUPLICATE("usbd", "tegra-ehci.0", NULL),
+	CLK_DUPLICATE("usbd", "tegra-otg", NULL),
+	CLK_DUPLICATE("hdmi", "tegradc.0", "hdmi"),
+	CLK_DUPLICATE("hdmi", "tegradc.1", "hdmi"),
+	CLK_DUPLICATE("dsib", "tegradc.0", "dsib"),
+	CLK_DUPLICATE("dsia", "tegradc.1", "dsia"),
+	CLK_DUPLICATE("bsev", "tegra-avp", "bsev"),
+	CLK_DUPLICATE("bsev", "nvavp", "bsev"),
+	CLK_DUPLICATE("vde", "tegra-aes", "vde"),
+	CLK_DUPLICATE("bsea", "tegra-aes", "bsea"),
+	CLK_DUPLICATE("bsea", "nvavp", "bsea"),
+	CLK_DUPLICATE("cml1", "tegra_sata_cml", NULL),
+	CLK_DUPLICATE("cml0", "tegra_pcie", "cml"),
+	CLK_DUPLICATE("pciex", "tegra_pcie", "pciex"),
+	CLK_DUPLICATE("i2c1", "tegra-i2c-slave.0", NULL),
+	CLK_DUPLICATE("i2c2", "tegra-i2c-slave.1", NULL),
+	CLK_DUPLICATE("i2c3", "tegra-i2c-slave.2", NULL),
+	CLK_DUPLICATE("i2c4", "tegra-i2c-slave.3", NULL),
+	CLK_DUPLICATE("i2c5", "tegra-i2c-slave.4", NULL),
+	CLK_DUPLICATE("sbc1", "spi_slave_tegra.0", NULL),
+	CLK_DUPLICATE("sbc2", "spi_slave_tegra.1", NULL),
+	CLK_DUPLICATE("sbc3", "spi_slave_tegra.2", NULL),
+	CLK_DUPLICATE("sbc4", "spi_slave_tegra.3", NULL),
+	CLK_DUPLICATE("sbc5", "spi_slave_tegra.4", NULL),
+	CLK_DUPLICATE("sbc6", "spi_slave_tegra.5", NULL),
+	CLK_DUPLICATE("twd", "smp_twd", NULL),
+	CLK_DUPLICATE("vcp", "nvavp", "vcp"),
+	CLK_DUPLICATE("i2s0", NULL, "i2s0"),
+	CLK_DUPLICATE("i2s1", NULL, "i2s1"),
+	CLK_DUPLICATE("i2s2", NULL, "i2s2"),
+	CLK_DUPLICATE("i2s3", NULL, "i2s3"),
+	CLK_DUPLICATE("i2s4", NULL, "i2s4"),
+	CLK_DUPLICATE("dam0", NULL, "dam0"),
+	CLK_DUPLICATE("dam1", NULL, "dam1"),
+	CLK_DUPLICATE("dam2", NULL, "dam2"),
+	CLK_DUPLICATE("spdif_in", NULL, "spdif_in"),
+	CLK_DUPLICATE("pll_p_out3", "tegra-i2c.0", "fast-clk"),
+	CLK_DUPLICATE("pll_p_out3", "tegra-i2c.1", "fast-clk"),
+	CLK_DUPLICATE("pll_p_out3", "tegra-i2c.2", "fast-clk"),
+	CLK_DUPLICATE("pll_p_out3", "tegra-i2c.3", "fast-clk"),
+	CLK_DUPLICATE("pll_p_out3", "tegra-i2c.4", "fast-clk"),
+};
+
+struct clk *tegra_ptr_clks[] = {
+	&tegra_clk_32k,
+	&tegra_clk_m,
+	&tegra_clk_m_div2,
+	&tegra_clk_m_div4,
+	&tegra_pll_ref,
+	&tegra_pll_m,
+	&tegra_pll_m_out1,
+	&tegra_pll_c,
+	&tegra_pll_c_out1,
+	&tegra_pll_p,
+	&tegra_pll_p_out1,
+	&tegra_pll_p_out2,
+	&tegra_pll_p_out3,
+	&tegra_pll_p_out4,
+	&tegra_pll_a,
+	&tegra_pll_a_out0,
+	&tegra_pll_d,
+	&tegra_pll_d_out0,
+	&tegra_pll_d2,
+	&tegra_pll_d2_out0,
+	&tegra_pll_u,
+	&tegra_pll_x,
+	&tegra_pll_x_out0,
+	&tegra_pll_e,
+	&tegra_clk_cclk_g,
+	&tegra_cml0,
+	&tegra_cml1,
+	&tegra_pciex,
+	&tegra_clk_sclk,
+	&tegra_clk_blink,
+	&tegra30_clk_twd,
+};
+
+static void tegra30_init_one_clock(struct clk *c)
+{
+	struct clk_tegra *clk = to_clk_tegra(c->hw);
+	__clk_init(NULL, c);
+	INIT_LIST_HEAD(&clk->shared_bus_list);
+	if (!clk->lookup.dev_id && !clk->lookup.con_id)
+		clk->lookup.con_id = c->name;
+	clk->lookup.clk = c;
+	clkdev_add(&clk->lookup);
+	tegra_clk_add(c);
+}
+
+void __init tegra30_init_clocks(void)
+{
+	int i;
+	struct clk *c;
+
+	for (i = 0; i < ARRAY_SIZE(tegra_ptr_clks); i++)
+		tegra30_init_one_clock(tegra_ptr_clks[i]);
+
+	for (i = 0; i < ARRAY_SIZE(tegra_list_clks); i++)
+		tegra30_init_one_clock(tegra_list_clks[i]);
+
+	for (i = 0; i < ARRAY_SIZE(tegra_clk_duplicates); i++) {
+		c = tegra_get_clock_by_name(tegra_clk_duplicates[i].name);
+		if (!c) {
+			pr_err("%s: Unknown duplicate clock %s\n", __func__,
+				tegra_clk_duplicates[i].name);
+			continue;
+		}
+
+		tegra_clk_duplicates[i].lookup.clk = c;
+		clkdev_add(&tegra_clk_duplicates[i].lookup);
+	}
+
+	for (i = 0; i < ARRAY_SIZE(tegra_sync_source_list); i++)
+		tegra30_init_one_clock(tegra_sync_source_list[i]);
+	for (i = 0; i < ARRAY_SIZE(tegra_clk_audio_list); i++)
+		tegra30_init_one_clock(tegra_clk_audio_list[i]);
+	for (i = 0; i < ARRAY_SIZE(tegra_clk_audio_2x_list); i++)
+		tegra30_init_one_clock(tegra_clk_audio_2x_list[i]);
+
+	for (i = 0; i < ARRAY_SIZE(tegra_clk_out_list); i++)
+		tegra30_init_one_clock(tegra_clk_out_list[i]);
+
+	tegra30_cpu_car_ops_init();
+}
diff --git a/arch/arm/mach-tegra/tegra_cpu_car.h b/arch/arm/mach-tegra/tegra_cpu_car.h
new file mode 100644
index 0000000..30d063a
--- /dev/null
+++ b/arch/arm/mach-tegra/tegra_cpu_car.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __MACH_TEGRA_CPU_CAR_H
+#define __MACH_TEGRA_CPU_CAR_H
+
+/*
+ * Tegra CPU clock and reset control ops
+ *
+ * wait_for_reset:
+ *	keep waiting until the CPU in reset state
+ * put_in_reset:
+ *	put the CPU in reset state
+ * out_of_reset:
+ *	release the CPU from reset state
+ * enable_clock:
+ *	CPU clock un-gate
+ * disable_clock:
+ *	CPU clock gate
+ */
+struct tegra_cpu_car_ops {
+	void (*wait_for_reset)(u32 cpu);
+	void (*put_in_reset)(u32 cpu);
+	void (*out_of_reset)(u32 cpu);
+	void (*enable_clock)(u32 cpu);
+	void (*disable_clock)(u32 cpu);
+};
+
+extern struct tegra_cpu_car_ops *tegra_cpu_car_ops;
+
+static inline void tegra_wait_cpu_in_reset(u32 cpu)
+{
+	if (WARN_ON(!tegra_cpu_car_ops->wait_for_reset))
+		return;
+
+	tegra_cpu_car_ops->wait_for_reset(cpu);
+}
+
+static inline void tegra_put_cpu_in_reset(u32 cpu)
+{
+	if (WARN_ON(!tegra_cpu_car_ops->put_in_reset))
+		return;
+
+	tegra_cpu_car_ops->put_in_reset(cpu);
+}
+
+static inline void tegra_cpu_out_of_reset(u32 cpu)
+{
+	if (WARN_ON(!tegra_cpu_car_ops->out_of_reset))
+		return;
+
+	tegra_cpu_car_ops->out_of_reset(cpu);
+}
+
+static inline void tegra_enable_cpu_clock(u32 cpu)
+{
+	if (WARN_ON(!tegra_cpu_car_ops->enable_clock))
+		return;
+
+	tegra_cpu_car_ops->enable_clock(cpu);
+}
+
+static inline void tegra_disable_cpu_clock(u32 cpu)
+{
+	if (WARN_ON(!tegra_cpu_car_ops->disable_clock))
+		return;
+
+	tegra_cpu_car_ops->disable_clock(cpu);
+}
+
+void tegra20_cpu_car_ops_init(void);
+void tegra30_cpu_car_ops_init(void);
+
+#endif /* __MACH_TEGRA_CPU_CAR_H */
diff --git a/arch/arm/mach-tegra/timer.c b/arch/arm/mach-tegra/timer.c
index 57b5bdc..eccdce9 100644
--- a/arch/arm/mach-tegra/timer.c
+++ b/arch/arm/mach-tegra/timer.c
@@ -33,7 +33,6 @@
 
 #include <mach/iomap.h>
 #include <mach/irqs.h>
-#include <mach/suspend.h>
 
 #include "board.h"
 #include "clock.h"
diff --git a/arch/arm/mach-tegra/usb_phy.c b/arch/arm/mach-tegra/usb_phy.c
deleted file mode 100644
index 022b33a..0000000
--- a/arch/arm/mach-tegra/usb_phy.c
+++ /dev/null
@@ -1,817 +0,0 @@
-/*
- * arch/arm/mach-tegra/usb_phy.c
- *
- * Copyright (C) 2010 Google, Inc.
- *
- * Author:
- *	Erik Gilling <konkers@google.com>
- *	Benoit Goby <benoit@android.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/resource.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/err.h>
-#include <linux/export.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-#include <linux/of_gpio.h>
-#include <linux/usb/otg.h>
-#include <linux/usb/ulpi.h>
-#include <asm/mach-types.h>
-#include <mach/gpio-tegra.h>
-#include <mach/usb_phy.h>
-#include <mach/iomap.h>
-
-#define ULPI_VIEWPORT		0x170
-
-#define USB_PORTSC1		0x184
-#define   USB_PORTSC1_PTS(x)	(((x) & 0x3) << 30)
-#define   USB_PORTSC1_PSPD(x)	(((x) & 0x3) << 26)
-#define   USB_PORTSC1_PHCD	(1 << 23)
-#define   USB_PORTSC1_WKOC	(1 << 22)
-#define   USB_PORTSC1_WKDS	(1 << 21)
-#define   USB_PORTSC1_WKCN	(1 << 20)
-#define   USB_PORTSC1_PTC(x)	(((x) & 0xf) << 16)
-#define   USB_PORTSC1_PP	(1 << 12)
-#define   USB_PORTSC1_SUSP	(1 << 7)
-#define   USB_PORTSC1_PE	(1 << 2)
-#define   USB_PORTSC1_CCS	(1 << 0)
-
-#define USB_SUSP_CTRL		0x400
-#define   USB_WAKE_ON_CNNT_EN_DEV	(1 << 3)
-#define   USB_WAKE_ON_DISCON_EN_DEV	(1 << 4)
-#define   USB_SUSP_CLR		(1 << 5)
-#define   USB_PHY_CLK_VALID	(1 << 7)
-#define   UTMIP_RESET			(1 << 11)
-#define   UHSIC_RESET			(1 << 11)
-#define   UTMIP_PHY_ENABLE		(1 << 12)
-#define   ULPI_PHY_ENABLE	(1 << 13)
-#define   USB_SUSP_SET		(1 << 14)
-#define   USB_WAKEUP_DEBOUNCE_COUNT(x)	(((x) & 0x7) << 16)
-
-#define USB1_LEGACY_CTRL	0x410
-#define   USB1_NO_LEGACY_MODE			(1 << 0)
-#define   USB1_VBUS_SENSE_CTL_MASK		(3 << 1)
-#define   USB1_VBUS_SENSE_CTL_VBUS_WAKEUP	(0 << 1)
-#define   USB1_VBUS_SENSE_CTL_AB_SESS_VLD_OR_VBUS_WAKEUP \
-						(1 << 1)
-#define   USB1_VBUS_SENSE_CTL_AB_SESS_VLD	(2 << 1)
-#define   USB1_VBUS_SENSE_CTL_A_SESS_VLD	(3 << 1)
-
-#define ULPI_TIMING_CTRL_0	0x424
-#define   ULPI_OUTPUT_PINMUX_BYP	(1 << 10)
-#define   ULPI_CLKOUT_PINMUX_BYP	(1 << 11)
-
-#define ULPI_TIMING_CTRL_1	0x428
-#define   ULPI_DATA_TRIMMER_LOAD	(1 << 0)
-#define   ULPI_DATA_TRIMMER_SEL(x)	(((x) & 0x7) << 1)
-#define   ULPI_STPDIRNXT_TRIMMER_LOAD	(1 << 16)
-#define   ULPI_STPDIRNXT_TRIMMER_SEL(x)	(((x) & 0x7) << 17)
-#define   ULPI_DIR_TRIMMER_LOAD		(1 << 24)
-#define   ULPI_DIR_TRIMMER_SEL(x)	(((x) & 0x7) << 25)
-
-#define UTMIP_PLL_CFG1		0x804
-#define   UTMIP_XTAL_FREQ_COUNT(x)		(((x) & 0xfff) << 0)
-#define   UTMIP_PLLU_ENABLE_DLY_COUNT(x)	(((x) & 0x1f) << 27)
-
-#define UTMIP_XCVR_CFG0		0x808
-#define   UTMIP_XCVR_SETUP(x)			(((x) & 0xf) << 0)
-#define   UTMIP_XCVR_LSRSLEW(x)			(((x) & 0x3) << 8)
-#define   UTMIP_XCVR_LSFSLEW(x)			(((x) & 0x3) << 10)
-#define   UTMIP_FORCE_PD_POWERDOWN		(1 << 14)
-#define   UTMIP_FORCE_PD2_POWERDOWN		(1 << 16)
-#define   UTMIP_FORCE_PDZI_POWERDOWN		(1 << 18)
-#define   UTMIP_XCVR_HSSLEW_MSB(x)		(((x) & 0x7f) << 25)
-
-#define UTMIP_BIAS_CFG0		0x80c
-#define   UTMIP_OTGPD			(1 << 11)
-#define   UTMIP_BIASPD			(1 << 10)
-
-#define UTMIP_HSRX_CFG0		0x810
-#define   UTMIP_ELASTIC_LIMIT(x)	(((x) & 0x1f) << 10)
-#define   UTMIP_IDLE_WAIT(x)		(((x) & 0x1f) << 15)
-
-#define UTMIP_HSRX_CFG1		0x814
-#define   UTMIP_HS_SYNC_START_DLY(x)	(((x) & 0x1f) << 1)
-
-#define UTMIP_TX_CFG0		0x820
-#define   UTMIP_FS_PREABMLE_J		(1 << 19)
-#define   UTMIP_HS_DISCON_DISABLE	(1 << 8)
-
-#define UTMIP_MISC_CFG0		0x824
-#define   UTMIP_DPDM_OBSERVE		(1 << 26)
-#define   UTMIP_DPDM_OBSERVE_SEL(x)	(((x) & 0xf) << 27)
-#define   UTMIP_DPDM_OBSERVE_SEL_FS_J	UTMIP_DPDM_OBSERVE_SEL(0xf)
-#define   UTMIP_DPDM_OBSERVE_SEL_FS_K	UTMIP_DPDM_OBSERVE_SEL(0xe)
-#define   UTMIP_DPDM_OBSERVE_SEL_FS_SE1 UTMIP_DPDM_OBSERVE_SEL(0xd)
-#define   UTMIP_DPDM_OBSERVE_SEL_FS_SE0 UTMIP_DPDM_OBSERVE_SEL(0xc)
-#define   UTMIP_SUSPEND_EXIT_ON_EDGE	(1 << 22)
-
-#define UTMIP_MISC_CFG1		0x828
-#define   UTMIP_PLL_ACTIVE_DLY_COUNT(x)	(((x) & 0x1f) << 18)
-#define   UTMIP_PLLU_STABLE_COUNT(x)	(((x) & 0xfff) << 6)
-
-#define UTMIP_DEBOUNCE_CFG0	0x82c
-#define   UTMIP_BIAS_DEBOUNCE_A(x)	(((x) & 0xffff) << 0)
-
-#define UTMIP_BAT_CHRG_CFG0	0x830
-#define   UTMIP_PD_CHRG			(1 << 0)
-
-#define UTMIP_SPARE_CFG0	0x834
-#define   FUSE_SETUP_SEL		(1 << 3)
-
-#define UTMIP_XCVR_CFG1		0x838
-#define   UTMIP_FORCE_PDDISC_POWERDOWN	(1 << 0)
-#define   UTMIP_FORCE_PDCHRP_POWERDOWN	(1 << 2)
-#define   UTMIP_FORCE_PDDR_POWERDOWN	(1 << 4)
-#define   UTMIP_XCVR_TERM_RANGE_ADJ(x)	(((x) & 0xf) << 18)
-
-#define UTMIP_BIAS_CFG1		0x83c
-#define   UTMIP_BIAS_PDTRK_COUNT(x)	(((x) & 0x1f) << 3)
-
-static DEFINE_SPINLOCK(utmip_pad_lock);
-static int utmip_pad_count;
-
-struct tegra_xtal_freq {
-	int freq;
-	u8 enable_delay;
-	u8 stable_count;
-	u8 active_delay;
-	u8 xtal_freq_count;
-	u16 debounce;
-};
-
-static const struct tegra_xtal_freq tegra_freq_table[] = {
-	{
-		.freq = 12000000,
-		.enable_delay = 0x02,
-		.stable_count = 0x2F,
-		.active_delay = 0x04,
-		.xtal_freq_count = 0x76,
-		.debounce = 0x7530,
-	},
-	{
-		.freq = 13000000,
-		.enable_delay = 0x02,
-		.stable_count = 0x33,
-		.active_delay = 0x05,
-		.xtal_freq_count = 0x7F,
-		.debounce = 0x7EF4,
-	},
-	{
-		.freq = 19200000,
-		.enable_delay = 0x03,
-		.stable_count = 0x4B,
-		.active_delay = 0x06,
-		.xtal_freq_count = 0xBB,
-		.debounce = 0xBB80,
-	},
-	{
-		.freq = 26000000,
-		.enable_delay = 0x04,
-		.stable_count = 0x66,
-		.active_delay = 0x09,
-		.xtal_freq_count = 0xFE,
-		.debounce = 0xFDE8,
-	},
-};
-
-static struct tegra_utmip_config utmip_default[] = {
-	[0] = {
-		.hssync_start_delay = 9,
-		.idle_wait_delay = 17,
-		.elastic_limit = 16,
-		.term_range_adj = 6,
-		.xcvr_setup = 9,
-		.xcvr_lsfslew = 1,
-		.xcvr_lsrslew = 1,
-	},
-	[2] = {
-		.hssync_start_delay = 9,
-		.idle_wait_delay = 17,
-		.elastic_limit = 16,
-		.term_range_adj = 6,
-		.xcvr_setup = 9,
-		.xcvr_lsfslew = 2,
-		.xcvr_lsrslew = 2,
-	},
-};
-
-static inline bool phy_is_ulpi(struct tegra_usb_phy *phy)
-{
-	return (phy->instance == 1);
-}
-
-static int utmip_pad_open(struct tegra_usb_phy *phy)
-{
-	phy->pad_clk = clk_get_sys("utmip-pad", NULL);
-	if (IS_ERR(phy->pad_clk)) {
-		pr_err("%s: can't get utmip pad clock\n", __func__);
-		return PTR_ERR(phy->pad_clk);
-	}
-
-	if (phy->instance == 0) {
-		phy->pad_regs = phy->regs;
-	} else {
-		phy->pad_regs = ioremap(TEGRA_USB_BASE, TEGRA_USB_SIZE);
-		if (!phy->pad_regs) {
-			pr_err("%s: can't remap usb registers\n", __func__);
-			clk_put(phy->pad_clk);
-			return -ENOMEM;
-		}
-	}
-	return 0;
-}
-
-static void utmip_pad_close(struct tegra_usb_phy *phy)
-{
-	if (phy->instance != 0)
-		iounmap(phy->pad_regs);
-	clk_put(phy->pad_clk);
-}
-
-static void utmip_pad_power_on(struct tegra_usb_phy *phy)
-{
-	unsigned long val, flags;
-	void __iomem *base = phy->pad_regs;
-
-	clk_prepare_enable(phy->pad_clk);
-
-	spin_lock_irqsave(&utmip_pad_lock, flags);
-
-	if (utmip_pad_count++ == 0) {
-		val = readl(base + UTMIP_BIAS_CFG0);
-		val &= ~(UTMIP_OTGPD | UTMIP_BIASPD);
-		writel(val, base + UTMIP_BIAS_CFG0);
-	}
-
-	spin_unlock_irqrestore(&utmip_pad_lock, flags);
-
-	clk_disable_unprepare(phy->pad_clk);
-}
-
-static int utmip_pad_power_off(struct tegra_usb_phy *phy)
-{
-	unsigned long val, flags;
-	void __iomem *base = phy->pad_regs;
-
-	if (!utmip_pad_count) {
-		pr_err("%s: utmip pad already powered off\n", __func__);
-		return -EINVAL;
-	}
-
-	clk_prepare_enable(phy->pad_clk);
-
-	spin_lock_irqsave(&utmip_pad_lock, flags);
-
-	if (--utmip_pad_count == 0) {
-		val = readl(base + UTMIP_BIAS_CFG0);
-		val |= UTMIP_OTGPD | UTMIP_BIASPD;
-		writel(val, base + UTMIP_BIAS_CFG0);
-	}
-
-	spin_unlock_irqrestore(&utmip_pad_lock, flags);
-
-	clk_disable_unprepare(phy->pad_clk);
-
-	return 0;
-}
-
-static int utmi_wait_register(void __iomem *reg, u32 mask, u32 result)
-{
-	unsigned long timeout = 2000;
-	do {
-		if ((readl(reg) & mask) == result)
-			return 0;
-		udelay(1);
-		timeout--;
-	} while (timeout);
-	return -1;
-}
-
-static void utmi_phy_clk_disable(struct tegra_usb_phy *phy)
-{
-	unsigned long val;
-	void __iomem *base = phy->regs;
-
-	if (phy->instance == 0) {
-		val = readl(base + USB_SUSP_CTRL);
-		val |= USB_SUSP_SET;
-		writel(val, base + USB_SUSP_CTRL);
-
-		udelay(10);
-
-		val = readl(base + USB_SUSP_CTRL);
-		val &= ~USB_SUSP_SET;
-		writel(val, base + USB_SUSP_CTRL);
-	}
-
-	if (phy->instance == 2) {
-		val = readl(base + USB_PORTSC1);
-		val |= USB_PORTSC1_PHCD;
-		writel(val, base + USB_PORTSC1);
-	}
-
-	if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID, 0) < 0)
-		pr_err("%s: timeout waiting for phy to stabilize\n", __func__);
-}
-
-static void utmi_phy_clk_enable(struct tegra_usb_phy *phy)
-{
-	unsigned long val;
-	void __iomem *base = phy->regs;
-
-	if (phy->instance == 0) {
-		val = readl(base + USB_SUSP_CTRL);
-		val |= USB_SUSP_CLR;
-		writel(val, base + USB_SUSP_CTRL);
-
-		udelay(10);
-
-		val = readl(base + USB_SUSP_CTRL);
-		val &= ~USB_SUSP_CLR;
-		writel(val, base + USB_SUSP_CTRL);
-	}
-
-	if (phy->instance == 2) {
-		val = readl(base + USB_PORTSC1);
-		val &= ~USB_PORTSC1_PHCD;
-		writel(val, base + USB_PORTSC1);
-	}
-
-	if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID,
-						     USB_PHY_CLK_VALID))
-		pr_err("%s: timeout waiting for phy to stabilize\n", __func__);
-}
-
-static int utmi_phy_power_on(struct tegra_usb_phy *phy)
-{
-	unsigned long val;
-	void __iomem *base = phy->regs;
-	struct tegra_utmip_config *config = phy->config;
-
-	val = readl(base + USB_SUSP_CTRL);
-	val |= UTMIP_RESET;
-	writel(val, base + USB_SUSP_CTRL);
-
-	if (phy->instance == 0) {
-		val = readl(base + USB1_LEGACY_CTRL);
-		val |= USB1_NO_LEGACY_MODE;
-		writel(val, base + USB1_LEGACY_CTRL);
-	}
-
-	val = readl(base + UTMIP_TX_CFG0);
-	val &= ~UTMIP_FS_PREABMLE_J;
-	writel(val, base + UTMIP_TX_CFG0);
-
-	val = readl(base + UTMIP_HSRX_CFG0);
-	val &= ~(UTMIP_IDLE_WAIT(~0) | UTMIP_ELASTIC_LIMIT(~0));
-	val |= UTMIP_IDLE_WAIT(config->idle_wait_delay);
-	val |= UTMIP_ELASTIC_LIMIT(config->elastic_limit);
-	writel(val, base + UTMIP_HSRX_CFG0);
-
-	val = readl(base + UTMIP_HSRX_CFG1);
-	val &= ~UTMIP_HS_SYNC_START_DLY(~0);
-	val |= UTMIP_HS_SYNC_START_DLY(config->hssync_start_delay);
-	writel(val, base + UTMIP_HSRX_CFG1);
-
-	val = readl(base + UTMIP_DEBOUNCE_CFG0);
-	val &= ~UTMIP_BIAS_DEBOUNCE_A(~0);
-	val |= UTMIP_BIAS_DEBOUNCE_A(phy->freq->debounce);
-	writel(val, base + UTMIP_DEBOUNCE_CFG0);
-
-	val = readl(base + UTMIP_MISC_CFG0);
-	val &= ~UTMIP_SUSPEND_EXIT_ON_EDGE;
-	writel(val, base + UTMIP_MISC_CFG0);
-
-	val = readl(base + UTMIP_MISC_CFG1);
-	val &= ~(UTMIP_PLL_ACTIVE_DLY_COUNT(~0) | UTMIP_PLLU_STABLE_COUNT(~0));
-	val |= UTMIP_PLL_ACTIVE_DLY_COUNT(phy->freq->active_delay) |
-		UTMIP_PLLU_STABLE_COUNT(phy->freq->stable_count);
-	writel(val, base + UTMIP_MISC_CFG1);
-
-	val = readl(base + UTMIP_PLL_CFG1);
-	val &= ~(UTMIP_XTAL_FREQ_COUNT(~0) | UTMIP_PLLU_ENABLE_DLY_COUNT(~0));
-	val |= UTMIP_XTAL_FREQ_COUNT(phy->freq->xtal_freq_count) |
-		UTMIP_PLLU_ENABLE_DLY_COUNT(phy->freq->enable_delay);
-	writel(val, base + UTMIP_PLL_CFG1);
-
-	if (phy->mode == TEGRA_USB_PHY_MODE_DEVICE) {
-		val = readl(base + USB_SUSP_CTRL);
-		val &= ~(USB_WAKE_ON_CNNT_EN_DEV | USB_WAKE_ON_DISCON_EN_DEV);
-		writel(val, base + USB_SUSP_CTRL);
-	}
-
-	utmip_pad_power_on(phy);
-
-	val = readl(base + UTMIP_XCVR_CFG0);
-	val &= ~(UTMIP_FORCE_PD_POWERDOWN | UTMIP_FORCE_PD2_POWERDOWN |
-		 UTMIP_FORCE_PDZI_POWERDOWN | UTMIP_XCVR_SETUP(~0) |
-		 UTMIP_XCVR_LSFSLEW(~0) | UTMIP_XCVR_LSRSLEW(~0) |
-		 UTMIP_XCVR_HSSLEW_MSB(~0));
-	val |= UTMIP_XCVR_SETUP(config->xcvr_setup);
-	val |= UTMIP_XCVR_LSFSLEW(config->xcvr_lsfslew);
-	val |= UTMIP_XCVR_LSRSLEW(config->xcvr_lsrslew);
-	writel(val, base + UTMIP_XCVR_CFG0);
-
-	val = readl(base + UTMIP_XCVR_CFG1);
-	val &= ~(UTMIP_FORCE_PDDISC_POWERDOWN | UTMIP_FORCE_PDCHRP_POWERDOWN |
-		 UTMIP_FORCE_PDDR_POWERDOWN | UTMIP_XCVR_TERM_RANGE_ADJ(~0));
-	val |= UTMIP_XCVR_TERM_RANGE_ADJ(config->term_range_adj);
-	writel(val, base + UTMIP_XCVR_CFG1);
-
-	val = readl(base + UTMIP_BAT_CHRG_CFG0);
-	val &= ~UTMIP_PD_CHRG;
-	writel(val, base + UTMIP_BAT_CHRG_CFG0);
-
-	val = readl(base + UTMIP_BIAS_CFG1);
-	val &= ~UTMIP_BIAS_PDTRK_COUNT(~0);
-	val |= UTMIP_BIAS_PDTRK_COUNT(0x5);
-	writel(val, base + UTMIP_BIAS_CFG1);
-
-	if (phy->instance == 0) {
-		val = readl(base + UTMIP_SPARE_CFG0);
-		if (phy->mode == TEGRA_USB_PHY_MODE_DEVICE)
-			val &= ~FUSE_SETUP_SEL;
-		else
-			val |= FUSE_SETUP_SEL;
-		writel(val, base + UTMIP_SPARE_CFG0);
-	}
-
-	if (phy->instance == 2) {
-		val = readl(base + USB_SUSP_CTRL);
-		val |= UTMIP_PHY_ENABLE;
-		writel(val, base + USB_SUSP_CTRL);
-	}
-
-	val = readl(base + USB_SUSP_CTRL);
-	val &= ~UTMIP_RESET;
-	writel(val, base + USB_SUSP_CTRL);
-
-	if (phy->instance == 0) {
-		val = readl(base + USB1_LEGACY_CTRL);
-		val &= ~USB1_VBUS_SENSE_CTL_MASK;
-		val |= USB1_VBUS_SENSE_CTL_A_SESS_VLD;
-		writel(val, base + USB1_LEGACY_CTRL);
-
-		val = readl(base + USB_SUSP_CTRL);
-		val &= ~USB_SUSP_SET;
-		writel(val, base + USB_SUSP_CTRL);
-	}
-
-	utmi_phy_clk_enable(phy);
-
-	if (phy->instance == 2) {
-		val = readl(base + USB_PORTSC1);
-		val &= ~USB_PORTSC1_PTS(~0);
-		writel(val, base + USB_PORTSC1);
-	}
-
-	return 0;
-}
-
-static void utmi_phy_power_off(struct tegra_usb_phy *phy)
-{
-	unsigned long val;
-	void __iomem *base = phy->regs;
-
-	utmi_phy_clk_disable(phy);
-
-	if (phy->mode == TEGRA_USB_PHY_MODE_DEVICE) {
-		val = readl(base + USB_SUSP_CTRL);
-		val &= ~USB_WAKEUP_DEBOUNCE_COUNT(~0);
-		val |= USB_WAKE_ON_CNNT_EN_DEV | USB_WAKEUP_DEBOUNCE_COUNT(5);
-		writel(val, base + USB_SUSP_CTRL);
-	}
-
-	val = readl(base + USB_SUSP_CTRL);
-	val |= UTMIP_RESET;
-	writel(val, base + USB_SUSP_CTRL);
-
-	val = readl(base + UTMIP_BAT_CHRG_CFG0);
-	val |= UTMIP_PD_CHRG;
-	writel(val, base + UTMIP_BAT_CHRG_CFG0);
-
-	val = readl(base + UTMIP_XCVR_CFG0);
-	val |= UTMIP_FORCE_PD_POWERDOWN | UTMIP_FORCE_PD2_POWERDOWN |
-	       UTMIP_FORCE_PDZI_POWERDOWN;
-	writel(val, base + UTMIP_XCVR_CFG0);
-
-	val = readl(base + UTMIP_XCVR_CFG1);
-	val |= UTMIP_FORCE_PDDISC_POWERDOWN | UTMIP_FORCE_PDCHRP_POWERDOWN |
-	       UTMIP_FORCE_PDDR_POWERDOWN;
-	writel(val, base + UTMIP_XCVR_CFG1);
-
-	utmip_pad_power_off(phy);
-}
-
-static void utmi_phy_preresume(struct tegra_usb_phy *phy)
-{
-	unsigned long val;
-	void __iomem *base = phy->regs;
-
-	val = readl(base + UTMIP_TX_CFG0);
-	val |= UTMIP_HS_DISCON_DISABLE;
-	writel(val, base + UTMIP_TX_CFG0);
-}
-
-static void utmi_phy_postresume(struct tegra_usb_phy *phy)
-{
-	unsigned long val;
-	void __iomem *base = phy->regs;
-
-	val = readl(base + UTMIP_TX_CFG0);
-	val &= ~UTMIP_HS_DISCON_DISABLE;
-	writel(val, base + UTMIP_TX_CFG0);
-}
-
-static void utmi_phy_restore_start(struct tegra_usb_phy *phy,
-				   enum tegra_usb_phy_port_speed port_speed)
-{
-	unsigned long val;
-	void __iomem *base = phy->regs;
-
-	val = readl(base + UTMIP_MISC_CFG0);
-	val &= ~UTMIP_DPDM_OBSERVE_SEL(~0);
-	if (port_speed == TEGRA_USB_PHY_PORT_SPEED_LOW)
-		val |= UTMIP_DPDM_OBSERVE_SEL_FS_K;
-	else
-		val |= UTMIP_DPDM_OBSERVE_SEL_FS_J;
-	writel(val, base + UTMIP_MISC_CFG0);
-	udelay(1);
-
-	val = readl(base + UTMIP_MISC_CFG0);
-	val |= UTMIP_DPDM_OBSERVE;
-	writel(val, base + UTMIP_MISC_CFG0);
-	udelay(10);
-}
-
-static void utmi_phy_restore_end(struct tegra_usb_phy *phy)
-{
-	unsigned long val;
-	void __iomem *base = phy->regs;
-
-	val = readl(base + UTMIP_MISC_CFG0);
-	val &= ~UTMIP_DPDM_OBSERVE;
-	writel(val, base + UTMIP_MISC_CFG0);
-	udelay(10);
-}
-
-static int ulpi_phy_power_on(struct tegra_usb_phy *phy)
-{
-	int ret;
-	unsigned long val;
-	void __iomem *base = phy->regs;
-	struct tegra_ulpi_config *config = phy->config;
-
-	gpio_direction_output(config->reset_gpio, 0);
-	msleep(5);
-	gpio_direction_output(config->reset_gpio, 1);
-
-	clk_prepare_enable(phy->clk);
-	msleep(1);
-
-	val = readl(base + USB_SUSP_CTRL);
-	val |= UHSIC_RESET;
-	writel(val, base + USB_SUSP_CTRL);
-
-	val = readl(base + ULPI_TIMING_CTRL_0);
-	val |= ULPI_OUTPUT_PINMUX_BYP | ULPI_CLKOUT_PINMUX_BYP;
-	writel(val, base + ULPI_TIMING_CTRL_0);
-
-	val = readl(base + USB_SUSP_CTRL);
-	val |= ULPI_PHY_ENABLE;
-	writel(val, base + USB_SUSP_CTRL);
-
-	val = 0;
-	writel(val, base + ULPI_TIMING_CTRL_1);
-
-	val |= ULPI_DATA_TRIMMER_SEL(4);
-	val |= ULPI_STPDIRNXT_TRIMMER_SEL(4);
-	val |= ULPI_DIR_TRIMMER_SEL(4);
-	writel(val, base + ULPI_TIMING_CTRL_1);
-	udelay(10);
-
-	val |= ULPI_DATA_TRIMMER_LOAD;
-	val |= ULPI_STPDIRNXT_TRIMMER_LOAD;
-	val |= ULPI_DIR_TRIMMER_LOAD;
-	writel(val, base + ULPI_TIMING_CTRL_1);
-
-	/* Fix VbusInvalid due to floating VBUS */
-	ret = usb_phy_io_write(phy->ulpi, 0x40, 0x08);
-	if (ret) {
-		pr_err("%s: ulpi write failed\n", __func__);
-		return ret;
-	}
-
-	ret = usb_phy_io_write(phy->ulpi, 0x80, 0x0B);
-	if (ret) {
-		pr_err("%s: ulpi write failed\n", __func__);
-		return ret;
-	}
-
-	val = readl(base + USB_PORTSC1);
-	val |= USB_PORTSC1_WKOC | USB_PORTSC1_WKDS | USB_PORTSC1_WKCN;
-	writel(val, base + USB_PORTSC1);
-
-	val = readl(base + USB_SUSP_CTRL);
-	val |= USB_SUSP_CLR;
-	writel(val, base + USB_SUSP_CTRL);
-	udelay(100);
-
-	val = readl(base + USB_SUSP_CTRL);
-	val &= ~USB_SUSP_CLR;
-	writel(val, base + USB_SUSP_CTRL);
-
-	return 0;
-}
-
-static void ulpi_phy_power_off(struct tegra_usb_phy *phy)
-{
-	unsigned long val;
-	void __iomem *base = phy->regs;
-	struct tegra_ulpi_config *config = phy->config;
-
-	/* Clear WKCN/WKDS/WKOC wake-on events that can cause the USB
-	 * Controller to immediately bring the ULPI PHY out of low power
-	 */
-	val = readl(base + USB_PORTSC1);
-	val &= ~(USB_PORTSC1_WKOC | USB_PORTSC1_WKDS | USB_PORTSC1_WKCN);
-	writel(val, base + USB_PORTSC1);
-
-	gpio_direction_output(config->reset_gpio, 0);
-	clk_disable(phy->clk);
-}
-
-struct tegra_usb_phy *tegra_usb_phy_open(struct device *dev, int instance,
-	void __iomem *regs, void *config, enum tegra_usb_phy_mode phy_mode)
-{
-	struct tegra_usb_phy *phy;
-	struct tegra_ulpi_config *ulpi_config;
-	unsigned long parent_rate;
-	int i;
-	int err;
-
-	phy = kmalloc(sizeof(struct tegra_usb_phy), GFP_KERNEL);
-	if (!phy)
-		return ERR_PTR(-ENOMEM);
-
-	phy->instance = instance;
-	phy->regs = regs;
-	phy->config = config;
-	phy->mode = phy_mode;
-
-	if (!phy->config) {
-		if (phy_is_ulpi(phy)) {
-			pr_err("%s: ulpi phy configuration missing", __func__);
-			err = -EINVAL;
-			goto err0;
-		} else {
-			phy->config = &utmip_default[instance];
-		}
-	}
-
-	phy->pll_u = clk_get_sys(NULL, "pll_u");
-	if (IS_ERR(phy->pll_u)) {
-		pr_err("Can't get pll_u clock\n");
-		err = PTR_ERR(phy->pll_u);
-		goto err0;
-	}
-	clk_prepare_enable(phy->pll_u);
-
-	parent_rate = clk_get_rate(clk_get_parent(phy->pll_u));
-	for (i = 0; i < ARRAY_SIZE(tegra_freq_table); i++) {
-		if (tegra_freq_table[i].freq == parent_rate) {
-			phy->freq = &tegra_freq_table[i];
-			break;
-		}
-	}
-	if (!phy->freq) {
-		pr_err("invalid pll_u parent rate %ld\n", parent_rate);
-		err = -EINVAL;
-		goto err1;
-	}
-
-	if (phy_is_ulpi(phy)) {
-		ulpi_config = config;
-		phy->clk = clk_get_sys(NULL, ulpi_config->clk);
-		if (IS_ERR(phy->clk)) {
-			pr_err("%s: can't get ulpi clock\n", __func__);
-			err = -ENXIO;
-			goto err1;
-		}
-		if (!gpio_is_valid(ulpi_config->reset_gpio))
-			ulpi_config->reset_gpio =
-				of_get_named_gpio(dev->of_node,
-						  "nvidia,phy-reset-gpio", 0);
-		if (!gpio_is_valid(ulpi_config->reset_gpio)) {
-			pr_err("%s: invalid reset gpio: %d\n", __func__,
-			       ulpi_config->reset_gpio);
-			err = -EINVAL;
-			goto err1;
-		}
-		gpio_request(ulpi_config->reset_gpio, "ulpi_phy_reset_b");
-		gpio_direction_output(ulpi_config->reset_gpio, 0);
-		phy->ulpi = otg_ulpi_create(&ulpi_viewport_access_ops, 0);
-		phy->ulpi->io_priv = regs + ULPI_VIEWPORT;
-	} else {
-		err = utmip_pad_open(phy);
-		if (err < 0)
-			goto err1;
-	}
-
-	return phy;
-
-err1:
-	clk_disable_unprepare(phy->pll_u);
-	clk_put(phy->pll_u);
-err0:
-	kfree(phy);
-	return ERR_PTR(err);
-}
-EXPORT_SYMBOL_GPL(tegra_usb_phy_open);
-
-int tegra_usb_phy_power_on(struct tegra_usb_phy *phy)
-{
-	if (phy_is_ulpi(phy))
-		return ulpi_phy_power_on(phy);
-	else
-		return utmi_phy_power_on(phy);
-}
-EXPORT_SYMBOL_GPL(tegra_usb_phy_power_on);
-
-void tegra_usb_phy_power_off(struct tegra_usb_phy *phy)
-{
-	if (phy_is_ulpi(phy))
-		ulpi_phy_power_off(phy);
-	else
-		utmi_phy_power_off(phy);
-}
-EXPORT_SYMBOL_GPL(tegra_usb_phy_power_off);
-
-void tegra_usb_phy_preresume(struct tegra_usb_phy *phy)
-{
-	if (!phy_is_ulpi(phy))
-		utmi_phy_preresume(phy);
-}
-EXPORT_SYMBOL_GPL(tegra_usb_phy_preresume);
-
-void tegra_usb_phy_postresume(struct tegra_usb_phy *phy)
-{
-	if (!phy_is_ulpi(phy))
-		utmi_phy_postresume(phy);
-}
-EXPORT_SYMBOL_GPL(tegra_usb_phy_postresume);
-
-void tegra_ehci_phy_restore_start(struct tegra_usb_phy *phy,
-				 enum tegra_usb_phy_port_speed port_speed)
-{
-	if (!phy_is_ulpi(phy))
-		utmi_phy_restore_start(phy, port_speed);
-}
-EXPORT_SYMBOL_GPL(tegra_ehci_phy_restore_start);
-
-void tegra_ehci_phy_restore_end(struct tegra_usb_phy *phy)
-{
-	if (!phy_is_ulpi(phy))
-		utmi_phy_restore_end(phy);
-}
-EXPORT_SYMBOL_GPL(tegra_ehci_phy_restore_end);
-
-void tegra_usb_phy_clk_disable(struct tegra_usb_phy *phy)
-{
-	if (!phy_is_ulpi(phy))
-		utmi_phy_clk_disable(phy);
-}
-EXPORT_SYMBOL_GPL(tegra_usb_phy_clk_disable);
-
-void tegra_usb_phy_clk_enable(struct tegra_usb_phy *phy)
-{
-	if (!phy_is_ulpi(phy))
-		utmi_phy_clk_enable(phy);
-}
-EXPORT_SYMBOL_GPL(tegra_usb_phy_clk_enable);
-
-void tegra_usb_phy_close(struct tegra_usb_phy *phy)
-{
-	if (phy_is_ulpi(phy))
-		clk_put(phy->clk);
-	else
-		utmip_pad_close(phy);
-	clk_disable_unprepare(phy->pll_u);
-	clk_put(phy->pll_u);
-	kfree(phy);
-}
-EXPORT_SYMBOL_GPL(tegra_usb_phy_close);
diff --git a/arch/arm/mach-u300/Kconfig b/arch/arm/mach-u300/Kconfig
index 54d8f34..f7e12ed 100644
--- a/arch/arm/mach-u300/Kconfig
+++ b/arch/arm/mach-u300/Kconfig
@@ -1,6 +1,6 @@
 if ARCH_U300
 
-menu "ST-Ericsson AB U300/U330/U335/U365 Platform"
+menu "ST-Ericsson AB U300/U335 Platform"
 
 comment "ST-Ericsson Mobile Platform Products"
 
@@ -10,46 +10,7 @@ config MACH_U300
 	select PINCTRL_U300
 	select PINCTRL_COH901
 
-comment "ST-Ericsson U300/U330/U335/U365 Feature Selections"
-
-choice
-	prompt "U300/U330/U335/U365 system type"
-	default MACH_U300_BS2X
-	---help---
-	You need to select the target system, i.e. the
-	U300/U330/U335/U365 board that you want to compile your kernel
-	for.
-
-config MACH_U300_BS2X
-	bool "S26/S26/B25/B26 Test Products"
-	depends on MACH_U300
-	help
-		Select this if you're developing on the
-		S26/S25 test products. (Also works on
-		B26/B25 big boards.)
-
-config MACH_U300_BS330
-	bool "S330/B330 Test Products"
-	depends on MACH_U300
-	help
-		Select this if you're developing on the
-		S330/B330 test products.
-
-config MACH_U300_BS335
-	bool "S335/B335 Test Products"
-	depends on MACH_U300
-	help
-		Select this if you're developing on the
-		S335/B335 test products.
-
-config MACH_U300_BS365
-	bool "S365/B365 Test Products"
-	depends on MACH_U300
-	help
-		Select this if you're developing on the
-		S365/B365 test products.
-
-endchoice
+comment "ST-Ericsson U300/U335 Feature Selections"
 
 config U300_DEBUG
 	bool "Debug support for U300"
diff --git a/arch/arm/mach-u300/Makefile b/arch/arm/mach-u300/Makefile
index 7e47d37..5a86c58 100644
--- a/arch/arm/mach-u300/Makefile
+++ b/arch/arm/mach-u300/Makefile
@@ -7,7 +7,6 @@ obj-m		:=
 obj-n		:=
 obj-		:=
 
-obj-$(CONFIG_ARCH_U300)	          += u300.o
 obj-$(CONFIG_SPI_PL022)           += spi.o
 obj-$(CONFIG_MACH_U300_SPIDUMMY)  += dummyspichip.o
 obj-$(CONFIG_I2C_STU300)          += i2c.o
diff --git a/arch/arm/mach-u300/core.c b/arch/arm/mach-u300/core.c
index 03acf18..b8efac4 100644
--- a/arch/arm/mach-u300/core.c
+++ b/arch/arm/mach-u300/core.c
@@ -3,7 +3,7 @@
  * arch/arm/mach-u300/core.c
  *
  *
- * Copyright (C) 2007-2010 ST-Ericsson SA
+ * Copyright (C) 2007-2012 ST-Ericsson SA
  * License terms: GNU General Public License (GPL) version 2
  * Core platform support, IRQ handling and device definitions.
  * Author: Linus Walleij <linus.walleij@stericsson.com>
@@ -31,23 +31,26 @@
 #include <linux/pinctrl/pinconf-generic.h>
 #include <linux/dma-mapping.h>
 #include <linux/platform_data/clk-u300.h>
+#include <linux/platform_data/pinctrl-coh901.h>
 
 #include <asm/types.h>
 #include <asm/setup.h>
 #include <asm/memory.h>
 #include <asm/hardware/vic.h>
 #include <asm/mach/map.h>
-#include <asm/mach/irq.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
 
 #include <mach/coh901318.h>
 #include <mach/hardware.h>
 #include <mach/syscon.h>
-#include <mach/dma_channels.h>
-#include <mach/gpio-u300.h>
+#include <mach/irqs.h>
 
+#include "timer.h"
 #include "spi.h"
 #include "i2c.h"
 #include "u300-gpio.h"
+#include "dma_channels.h"
 
 /*
  * Static I/O mappings that are needed for booting the U300 platforms. The
@@ -76,7 +79,7 @@ static struct map_desc u300_io_desc[] __initdata = {
 	},
 };
 
-void __init u300_map_io(void)
+static void __init u300_map_io(void)
 {
 	iotable_init(u300_io_desc, ARRAY_SIZE(u300_io_desc));
 	/* We enable a real big DMA buffer if need be. */
@@ -101,7 +104,6 @@ static AMBA_APB_DEVICE(uart0, "uart0", 0, U300_UART0_BASE,
 	{ IRQ_U300_UART0 }, &uart0_plat_data);
 
 /* The U335 have an additional UART1 on the APP CPU */
-#ifdef CONFIG_MACH_U300_BS335
 static struct amba_pl011_data uart1_plat_data = {
 #ifdef CONFIG_COH901318
 	.dma_filter = coh901318_filter_id,
@@ -113,7 +115,6 @@ static struct amba_pl011_data uart1_plat_data = {
 /* Fast device at 0x7000 offset */
 static AMBA_APB_DEVICE(uart1, "uart1", 0, U300_UART1_BASE,
 	{ IRQ_U300_UART1 }, &uart1_plat_data);
-#endif
 
 /* AHB device at 0x4000 offset */
 static AMBA_APB_DEVICE(pl172, "pl172", 0, U300_EMIF_CFG_BASE, { }, NULL);
@@ -152,9 +153,7 @@ static AMBA_APB_DEVICE(mmcsd, "mmci", 0, U300_MMCSD_BASE,
  */
 static struct amba_device *amba_devs[] __initdata = {
 	&uart0_device,
-#ifdef CONFIG_MACH_U300_BS335
 	&uart1_device,
-#endif
 	&pl022_device,
 	&pl172_device,
 	&mmcsd_device,
@@ -188,7 +187,6 @@ static struct resource gpio_resources[] = {
 		.end   = IRQ_U300_GPIO_PORT2,
 		.flags = IORESOURCE_IRQ,
 	},
-#if defined(CONFIG_MACH_U300_BS365) || defined(CONFIG_MACH_U300_BS335)
 	{
 		.name  = "gpio3",
 		.start = IRQ_U300_GPIO_PORT3,
@@ -201,8 +199,6 @@ static struct resource gpio_resources[] = {
 		.end   = IRQ_U300_GPIO_PORT4,
 		.flags = IORESOURCE_IRQ,
 	},
-#endif
-#ifdef CONFIG_MACH_U300_BS335
 	{
 		.name  = "gpio5",
 		.start = IRQ_U300_GPIO_PORT5,
@@ -215,7 +211,6 @@ static struct resource gpio_resources[] = {
 		.end   = IRQ_U300_GPIO_PORT6,
 		.flags = IORESOURCE_IRQ,
 	},
-#endif /* CONFIG_MACH_U300_BS335 */
 };
 
 static struct resource keypad_resources[] = {
@@ -323,7 +318,6 @@ static struct resource dma_resource[] = {
 	}
 };
 
-#ifdef CONFIG_MACH_U300_BS335
 /* points out all dma slave channels.
  * Syntax is [A1, B1, A2, B2, .... ,-1,-1]
  * Select all channels from A to B, end of list is marked with -1,-1
@@ -336,14 +330,6 @@ static int dma_slave_channels[] = {
 static int dma_memcpy_channels[] = {
 	U300_DMA_GENERAL_PURPOSE_0, U300_DMA_GENERAL_PURPOSE_8, -1, -1};
 
-#else /* CONFIG_MACH_U300_BS335 */
-
-static int dma_slave_channels[] = {U300_DMA_MSL_TX_0, U300_DMA_SPI_RX, -1, -1};
-static int dma_memcpy_channels[] = {
-	U300_DMA_GENERAL_PURPOSE_0, U300_DMA_GENERAL_PURPOSE_10, -1, -1};
-
-#endif
-
 /** register dma for memory access
  *
  * active  1 means dma intends to access memory
@@ -1395,7 +1381,6 @@ const struct coh_dma_channel chan_config[U300_DMA_CHANNELS] = {
 		.param.ctrl_lli = flags_memcpy_lli,
 		.param.ctrl_lli_last = flags_memcpy_lli_last,
 	},
-#ifdef CONFIG_MACH_U300_BS335
 	{
 		.number = U300_DMA_UART1_TX,
 		.name = "UART1 TX",
@@ -1406,28 +1391,6 @@ const struct coh_dma_channel chan_config[U300_DMA_CHANNELS] = {
 		.name = "UART1 RX",
 		.priority_high = 0,
 	}
-#else
-	{
-		.number = U300_DMA_GENERAL_PURPOSE_9,
-		.name = "GENERAL 09",
-		.priority_high = 0,
-
-		.param.config = flags_memcpy_config,
-		.param.ctrl_lli_chained = flags_memcpy_lli_chained,
-		.param.ctrl_lli = flags_memcpy_lli,
-		.param.ctrl_lli_last = flags_memcpy_lli_last,
-	},
-	{
-		.number = U300_DMA_GENERAL_PURPOSE_10,
-		.name = "GENERAL 10",
-		.priority_high = 0,
-
-		.param.config = flags_memcpy_config,
-		.param.ctrl_lli_chained = flags_memcpy_lli_chained,
-		.param.ctrl_lli = flags_memcpy_lli,
-		.param.ctrl_lli_last = flags_memcpy_lli_last,
-	}
-#endif
 };
 
 
@@ -1480,18 +1443,7 @@ static struct platform_device pinctrl_device = {
  * GPIO block, with different number of ports.
  */
 static struct u300_gpio_platform u300_gpio_plat = {
-#if defined(CONFIG_MACH_U300_BS2X) || defined(CONFIG_MACH_U300_BS330)
-	.variant = U300_GPIO_COH901335,
-	.ports = 3,
-#endif
-#ifdef CONFIG_MACH_U300_BS335
-	.variant = U300_GPIO_COH901571_3_BS335,
 	.ports = 7,
-#endif
-#ifdef CONFIG_MACH_U300_BS365
-	.variant = U300_GPIO_COH901571_3_BS365,
-	.ports = 5,
-#endif
 	.gpio_base = 0,
 	.gpio_irq_base = IRQ_U300_GPIO_BASE,
 	.pinctrl_device = &pinctrl_device,
@@ -1605,9 +1557,6 @@ static struct u300_mux_hog u300_mux_hogs[] = {
 		.dev = &uart0_device.dev,
 	},
 	{
-		.dev = &pl022_device.dev,
-	},
-	{
 		.dev = &mmcsd_device.dev,
 	},
 };
@@ -1651,7 +1600,7 @@ static struct platform_device *platform_devs[] __initdata = {
  * together so some interrupts are connected to the first one and some
  * to the second one.
  */
-void __init u300_init_irq(void)
+static void __init u300_init_irq(void)
 {
 	u32 mask[2] = {0, 0};
 	struct clk *clk;
@@ -1756,29 +1705,11 @@ static void __init u300_init_check_chip(void)
 	printk(KERN_INFO "Initializing U300 system on %s baseband chip " \
 	       "(chip ID 0x%04x)\n", chipname, val);
 
-#ifdef CONFIG_MACH_U300_BS330
-	if ((val & 0xFF00U) != 0xd800) {
-		printk(KERN_ERR "Platform configured for BS330 " \
-		       "with DB3200 but %s detected, expect problems!",
-		       chipname);
-	}
-#endif
-#ifdef CONFIG_MACH_U300_BS335
 	if ((val & 0xFF00U) != 0xf000 && (val & 0xFF00U) != 0xf100) {
 		printk(KERN_ERR "Platform configured for BS335 " \
 		       " with DB3350 but %s detected, expect problems!",
 		       chipname);
 	}
-#endif
-#ifdef CONFIG_MACH_U300_BS365
-	if ((val & 0xFF00U) != 0xe800) {
-		printk(KERN_ERR "Platform configured for BS365 " \
-		       "with DB3210 but %s detected, expect problems!",
-		       chipname);
-	}
-#endif
-
-
 }
 
 /*
@@ -1811,7 +1742,7 @@ static void __init u300_assign_physmem(void)
 	}
 }
 
-void __init u300_init_devices(void)
+static void __init u300_init_machine(void)
 {
 	int i;
 	u16 val;
@@ -1852,7 +1783,7 @@ void __init u300_init_devices(void)
 /* Forward declare this function from the watchdog */
 void coh901327_watchdog_reset(void);
 
-void u300_restart(char mode, const char *cmd)
+static void u300_restart(char mode, const char *cmd)
 {
 	switch (mode) {
 	case 's':
@@ -1868,3 +1799,15 @@ void u300_restart(char mode, const char *cmd)
 	/* Wait for system do die/reset. */
 	while (1);
 }
+
+MACHINE_START(U300, "Ericsson AB U335 S335/B335 Prototype Board")
+	/* Maintainer: Linus Walleij <linus.walleij@stericsson.com> */
+	.atag_offset	= 0x100,
+	.map_io		= u300_map_io,
+	.nr_irqs	= NR_IRQS_U300,
+	.init_irq	= u300_init_irq,
+	.handle_irq	= vic_handle_irq,
+	.timer		= &u300_timer,
+	.init_machine	= u300_init_machine,
+	.restart	= u300_restart,
+MACHINE_END
diff --git a/arch/arm/mach-u300/dma_channels.h b/arch/arm/mach-u300/dma_channels.h
new file mode 100644
index 0000000..4e8a88f
--- /dev/null
+++ b/arch/arm/mach-u300/dma_channels.h
@@ -0,0 +1,60 @@
+/*
+ *
+ * arch/arm/mach-u300/include/mach/dma_channels.h
+ *
+ *
+ * Copyright (C) 2007-2012 ST-Ericsson
+ * License terms: GNU General Public License (GPL) version 2
+ * Map file for the U300 dma driver.
+ * Author: Per Friden <per.friden@stericsson.com>
+ */
+
+#ifndef DMA_CHANNELS_H
+#define DMA_CHANNELS_H
+
+#define U300_DMA_MSL_TX_0             0
+#define U300_DMA_MSL_TX_1             1
+#define U300_DMA_MSL_TX_2             2
+#define U300_DMA_MSL_TX_3             3
+#define U300_DMA_MSL_TX_4             4
+#define U300_DMA_MSL_TX_5             5
+#define U300_DMA_MSL_TX_6             6
+#define U300_DMA_MSL_RX_0             7
+#define U300_DMA_MSL_RX_1             8
+#define U300_DMA_MSL_RX_2             9
+#define U300_DMA_MSL_RX_3             10
+#define U300_DMA_MSL_RX_4             11
+#define U300_DMA_MSL_RX_5             12
+#define U300_DMA_MSL_RX_6             13
+#define U300_DMA_MMCSD_RX_TX          14
+#define U300_DMA_MSPRO_TX             15
+#define U300_DMA_MSPRO_RX             16
+#define U300_DMA_UART0_TX             17
+#define U300_DMA_UART0_RX             18
+#define U300_DMA_APEX_TX              19
+#define U300_DMA_APEX_RX              20
+#define U300_DMA_PCM_I2S0_TX          21
+#define U300_DMA_PCM_I2S0_RX          22
+#define U300_DMA_PCM_I2S1_TX          23
+#define U300_DMA_PCM_I2S1_RX          24
+#define U300_DMA_XGAM_CDI             25
+#define U300_DMA_XGAM_PDI             26
+#define U300_DMA_SPI_TX               27
+#define U300_DMA_SPI_RX               28
+#define U300_DMA_GENERAL_PURPOSE_0    29
+#define U300_DMA_GENERAL_PURPOSE_1    30
+#define U300_DMA_GENERAL_PURPOSE_2    31
+#define U300_DMA_GENERAL_PURPOSE_3    32
+#define U300_DMA_GENERAL_PURPOSE_4    33
+#define U300_DMA_GENERAL_PURPOSE_5    34
+#define U300_DMA_GENERAL_PURPOSE_6    35
+#define U300_DMA_GENERAL_PURPOSE_7    36
+#define U300_DMA_GENERAL_PURPOSE_8    37
+#define U300_DMA_UART1_TX             38
+#define U300_DMA_UART1_RX             39
+
+#define U300_DMA_DEVICE_CHANNELS      32
+#define U300_DMA_CHANNELS             40
+
+
+#endif /* DMA_CHANNELS_H */
diff --git a/arch/arm/mach-u300/i2c.c b/arch/arm/mach-u300/i2c.c
index cb04bd6..96800aa 100644
--- a/arch/arm/mach-u300/i2c.c
+++ b/arch/arm/mach-u300/i2c.c
@@ -1,7 +1,7 @@
 /*
  * arch/arm/mach-u300/i2c.c
  *
- * Copyright (C) 2009 ST-Ericsson AB
+ * Copyright (C) 2009-2012 ST-Ericsson AB
  * License terms: GNU General Public License (GPL) version 2
  *
  * Register board i2c devices
@@ -9,7 +9,7 @@
  */
 #include <linux/kernel.h>
 #include <linux/i2c.h>
-#include <linux/mfd/abx500.h>
+#include <linux/mfd/ab3100.h>
 #include <linux/regulator/machine.h>
 #include <linux/amba/bus.h>
 #include <mach/irqs.h>
@@ -261,7 +261,6 @@ static struct i2c_board_info __initdata bus0_i2c_board_info[] = {
 };
 
 static struct i2c_board_info __initdata bus1_i2c_board_info[] = {
-#ifdef CONFIG_MACH_U300_BS335
 	{
 		.type = "fwcam",
 		.addr = 0x10,
@@ -270,9 +269,6 @@ static struct i2c_board_info __initdata bus1_i2c_board_info[] = {
 		.type = "fwcam",
 		.addr = 0x5d,
 	},
-#else
-	{ },
-#endif
 };
 
 void __init u300_i2c_register_board_devices(void)
diff --git a/arch/arm/mach-u300/include/mach/clkdev.h b/arch/arm/mach-u300/include/mach/clkdev.h
deleted file mode 100644
index 92e3cc8..0000000
--- a/arch/arm/mach-u300/include/mach/clkdev.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __MACH_CLKDEV_H
-#define __MACH_CLKDEV_H
-
-int __clk_get(struct clk *clk);
-void __clk_put(struct clk *clk);
-
-#endif
diff --git a/arch/arm/mach-u300/include/mach/dma_channels.h b/arch/arm/mach-u300/include/mach/dma_channels.h
deleted file mode 100644
index b239149..0000000
--- a/arch/arm/mach-u300/include/mach/dma_channels.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- *
- * arch/arm/mach-u300/include/mach/dma_channels.h
- *
- *
- * Copyright (C) 2007-2009 ST-Ericsson
- * License terms: GNU General Public License (GPL) version 2
- * Map file for the U300 dma driver.
- * Author: Per Friden <per.friden@stericsson.com>
- */
-
-#ifndef DMA_CHANNELS_H
-#define DMA_CHANNELS_H
-
-#define U300_DMA_MSL_TX_0             0
-#define U300_DMA_MSL_TX_1             1
-#define U300_DMA_MSL_TX_2             2
-#define U300_DMA_MSL_TX_3             3
-#define U300_DMA_MSL_TX_4             4
-#define U300_DMA_MSL_TX_5             5
-#define U300_DMA_MSL_TX_6             6
-#define U300_DMA_MSL_RX_0             7
-#define U300_DMA_MSL_RX_1             8
-#define U300_DMA_MSL_RX_2             9
-#define U300_DMA_MSL_RX_3             10
-#define U300_DMA_MSL_RX_4             11
-#define U300_DMA_MSL_RX_5             12
-#define U300_DMA_MSL_RX_6             13
-#define U300_DMA_MMCSD_RX_TX          14
-#define U300_DMA_MSPRO_TX             15
-#define U300_DMA_MSPRO_RX             16
-#define U300_DMA_UART0_TX             17
-#define U300_DMA_UART0_RX             18
-#define U300_DMA_APEX_TX              19
-#define U300_DMA_APEX_RX              20
-#define U300_DMA_PCM_I2S0_TX          21
-#define U300_DMA_PCM_I2S0_RX          22
-#define U300_DMA_PCM_I2S1_TX          23
-#define U300_DMA_PCM_I2S1_RX          24
-#define U300_DMA_XGAM_CDI             25
-#define U300_DMA_XGAM_PDI             26
-#define U300_DMA_SPI_TX               27
-#define U300_DMA_SPI_RX               28
-#define U300_DMA_GENERAL_PURPOSE_0    29
-#define U300_DMA_GENERAL_PURPOSE_1    30
-#define U300_DMA_GENERAL_PURPOSE_2    31
-#define U300_DMA_GENERAL_PURPOSE_3    32
-#define U300_DMA_GENERAL_PURPOSE_4    33
-#define U300_DMA_GENERAL_PURPOSE_5    34
-#define U300_DMA_GENERAL_PURPOSE_6    35
-#define U300_DMA_GENERAL_PURPOSE_7    36
-#define U300_DMA_GENERAL_PURPOSE_8    37
-#ifdef CONFIG_MACH_U300_BS335
-#define U300_DMA_UART1_TX             38
-#define U300_DMA_UART1_RX             39
-#else
-#define U300_DMA_GENERAL_PURPOSE_9    38
-#define U300_DMA_GENERAL_PURPOSE_10   39
-#endif
-
-#ifdef CONFIG_MACH_U300_BS335
-#define U300_DMA_DEVICE_CHANNELS      32
-#else
-#define U300_DMA_DEVICE_CHANNELS      30
-#endif
-#define U300_DMA_CHANNELS             40
-
-
-#endif /* DMA_CHANNELS_H */
diff --git a/arch/arm/mach-u300/include/mach/gpio-u300.h b/arch/arm/mach-u300/include/mach/gpio-u300.h
deleted file mode 100644
index e81400c..0000000
--- a/arch/arm/mach-u300/include/mach/gpio-u300.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2007-2011 ST-Ericsson AB
- * License terms: GNU General Public License (GPL) version 2
- * GPIO block resgister definitions and inline macros for
- * U300 GPIO COH 901 335 or COH 901 571/3
- * Author: Linus Walleij <linus.walleij@stericsson.com>
- */
-
-#ifndef __MACH_U300_GPIO_U300_H
-#define __MACH_U300_GPIO_U300_H
-
-/**
- * enum u300_gpio_variant - the type of U300 GPIO employed
- */
-enum u300_gpio_variant {
-	U300_GPIO_COH901335,
-	U300_GPIO_COH901571_3_BS335,
-	U300_GPIO_COH901571_3_BS365,
-};
-
-/**
- * struct u300_gpio_platform - U300 GPIO platform data
- * @variant: IP block variant
- * @ports: number of GPIO block ports
- * @gpio_base: first GPIO number for this block (use a free range)
- * @gpio_irq_base: first GPIO IRQ number for this block (use a free range)
- * @pinctrl_device: pin control device to spawn as child
- */
-struct u300_gpio_platform {
-	enum u300_gpio_variant variant;
-	u8 ports;
-	int gpio_base;
-	int gpio_irq_base;
-	struct platform_device *pinctrl_device;
-};
-
-#endif /* __MACH_U300_GPIO_U300_H */
diff --git a/arch/arm/mach-u300/include/mach/gpio.h b/arch/arm/mach-u300/include/mach/gpio.h
deleted file mode 100644
index 40a8c17..0000000
--- a/arch/arm/mach-u300/include/mach/gpio.h
+++ /dev/null
@@ -1 +0,0 @@
-/* empty */
diff --git a/arch/arm/mach-u300/include/mach/irqs.h b/arch/arm/mach-u300/include/mach/irqs.h
index ec09c1e..e27425a 100644
--- a/arch/arm/mach-u300/include/mach/irqs.h
+++ b/arch/arm/mach-u300/include/mach/irqs.h
@@ -3,7 +3,7 @@
  * arch/arm/mach-u300/include/mach/irqs.h
  *
  *
- * Copyright (C) 2006-2009 ST-Ericsson AB
+ * Copyright (C) 2006-2012 ST-Ericsson AB
  * License terms: GNU General Public License (GPL) version 2
  * IRQ channel definitions for the U300 platforms.
  * Author: Linus Walleij <linus.walleij@stericsson.com>
@@ -31,10 +31,6 @@
 #define IRQ_U300_XGAM_GAMCON		14
 #define IRQ_U300_XGAM_CDI		15
 #define IRQ_U300_XGAM_CDICON		16
-#if defined(CONFIG_MACH_U300_BS2X) || defined(CONFIG_MACH_U300_BS330)
-/* MMIACC not used on the DB3210 or DB3350 chips */
-#define IRQ_U300_XGAM_MMIACC		17
-#endif
 #define IRQ_U300_XGAM_PDI		18
 #define IRQ_U300_XGAM_PDICON		19
 #define IRQ_U300_XGAM_GAMEACC		20
@@ -55,8 +51,6 @@
 #define IRQ_U300_GPIO_PORT1		34
 #define IRQ_U300_GPIO_PORT2		35
 
-#if defined(CONFIG_MACH_U300_BS2X) || defined(CONFIG_MACH_U300_BS330) || \
-    defined(CONFIG_MACH_U300_BS335)
 /* These are for DB3150, DB3200 and DB3350 */
 #define IRQ_U300_WDOG			36
 #define IRQ_U300_EVHIST			37
@@ -68,15 +62,8 @@
 #define IRQ_U300_RTC			43
 #define IRQ_U300_NFIF			44
 #define IRQ_U300_NFIF2			45
-#endif
-
-/* DB3150 and DB3200 have only 45 IRQs */
-#if defined(CONFIG_MACH_U300_BS2X) || defined(CONFIG_MACH_U300_BS330)
-#define U300_VIC_IRQS_END		46
-#endif
 
 /* The DB3350-specific interrupt lines */
-#ifdef CONFIG_MACH_U300_BS335
 #define IRQ_U300_ISP_F0			46
 #define IRQ_U300_ISP_F1			47
 #define IRQ_U300_ISP_F2			48
@@ -89,25 +76,6 @@
 #define IRQ_U300_GPIO_PORT5		55
 #define IRQ_U300_GPIO_PORT6		56
 #define U300_VIC_IRQS_END		57
-#endif
-
-/* The DB3210-specific interrupt lines */
-#ifdef CONFIG_MACH_U300_BS365
-#define IRQ_U300_GPIO_PORT3		36
-#define IRQ_U300_GPIO_PORT4		37
-#define IRQ_U300_WDOG			38
-#define IRQ_U300_EVHIST			39
-#define IRQ_U300_MSPRO			40
-#define IRQ_U300_MMCSD_MCIINTR0		41
-#define IRQ_U300_MMCSD_MCIINTR1		42
-#define IRQ_U300_I2C0			43
-#define IRQ_U300_I2C1			44
-#define IRQ_U300_RTC			45
-#define IRQ_U300_NFIF			46
-#define IRQ_U300_NFIF2			47
-#define IRQ_U300_SYSCON_PLL_LOCK	48
-#define U300_VIC_IRQS_END		49
-#endif
 
 /* Maximum 8*7 GPIO lines */
 #ifdef CONFIG_PINCTRL_COH901
@@ -117,6 +85,6 @@
 #define IRQ_U300_GPIO_END		(U300_VIC_IRQS_END)
 #endif
 
-#define NR_IRQS				(IRQ_U300_GPIO_END - IRQ_U300_INTCON0_START)
+#define NR_IRQS_U300			(IRQ_U300_GPIO_END - IRQ_U300_INTCON0_START)
 
 #endif
diff --git a/arch/arm/mach-u300/include/mach/platform.h b/arch/arm/mach-u300/include/mach/platform.h
deleted file mode 100644
index 096333f..0000000
--- a/arch/arm/mach-u300/include/mach/platform.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- *
- * arch/arm/mach-u300/include/mach/platform.h
- *
- *
- * Copyright (C) 2006-2009 ST-Ericsson AB
- * License terms: GNU General Public License (GPL) version 2
- * Basic platform init and mapping functions.
- * Author: Linus Walleij <linus.walleij@stericsson.com>
- */
-
-#ifndef __ASSEMBLY__
-
-void u300_map_io(void);
-void u300_init_irq(void);
-void u300_init_devices(void);
-void u300_restart(char, const char *);
-extern struct sys_timer u300_timer;
-
-#endif
diff --git a/arch/arm/mach-u300/include/mach/syscon.h b/arch/arm/mach-u300/include/mach/syscon.h
index 6e84f07..10bdd0b 100644
--- a/arch/arm/mach-u300/include/mach/syscon.h
+++ b/arch/arm/mach-u300/include/mach/syscon.h
@@ -3,7 +3,7 @@
  * arch/arm/mach-u300/include/mach/syscon.h
  *
  *
- * Copyright (C) 2008 ST-Ericsson AB
+ * Copyright (C) 2008-2012 ST-Ericsson AB
  *
  * Author: Rickard Andersson <rickard.andersson@stericsson.com>
  */
@@ -36,9 +36,7 @@
 #define U300_SYSCON_CSR_PLL13_LOCK_IND				(0x0001)
 /* Reset lines for SLOW devices 16bit (R/W) */
 #define U300_SYSCON_RSR						(0x0014)
-#ifdef CONFIG_MACH_U300_BS335
 #define U300_SYSCON_RSR_PPM_RESET_EN				(0x0200)
-#endif
 #define U300_SYSCON_RSR_ACC_TMR_RESET_EN			(0x0100)
 #define U300_SYSCON_RSR_APP_TMR_RESET_EN			(0x0080)
 #define U300_SYSCON_RSR_RTC_RESET_EN				(0x0040)
@@ -50,9 +48,7 @@
 #define U300_SYSCON_RSR_SLOW_BRIDGE_RESET_EN			(0x0001)
 /* Reset lines for FAST devices 16bit (R/W) */
 #define U300_SYSCON_RFR						(0x0018)
-#ifdef CONFIG_MACH_U300_BS335
 #define U300_SYSCON_RFR_UART1_RESET_ENABLE			(0x0080)
-#endif
 #define U300_SYSCON_RFR_SPI_RESET_ENABLE			(0x0040)
 #define U300_SYSCON_RFR_MMC_RESET_ENABLE			(0x0020)
 #define U300_SYSCON_RFR_PCM_I2S1_RESET_ENABLE			(0x0010)
@@ -62,10 +58,8 @@
 #define U300_SYSCON_RFR_FAST_BRIDGE_RESET_ENABLE		(0x0001)
 /* Reset lines for the rest of the peripherals 16bit (R/W) */
 #define U300_SYSCON_RRR						(0x001c)
-#ifdef CONFIG_MACH_U300_BS335
 #define U300_SYSCON_RRR_CDS_RESET_EN				(0x4000)
 #define U300_SYSCON_RRR_ISP_RESET_EN				(0x2000)
-#endif
 #define U300_SYSCON_RRR_INTCON_RESET_EN				(0x1000)
 #define U300_SYSCON_RRR_MSPRO_RESET_EN				(0x0800)
 #define U300_SYSCON_RRR_XGAM_RESET_EN				(0x0100)
@@ -79,9 +73,7 @@
 #define U300_SYSCON_RRR_AAIF_RESET_EN				(0x0001)
 /* Clock enable for SLOW peripherals 16bit (R/W) */
 #define U300_SYSCON_CESR					(0x0020)
-#ifdef CONFIG_MACH_U300_BS335
 #define U300_SYSCON_CESR_PPM_CLK_EN				(0x0200)
-#endif
 #define U300_SYSCON_CESR_ACC_TMR_CLK_EN				(0x0100)
 #define U300_SYSCON_CESR_APP_TMR_CLK_EN				(0x0080)
 #define U300_SYSCON_CESR_KEYPAD_CLK_EN				(0x0040)
@@ -92,24 +84,20 @@
 #define U300_SYSCON_CESR_SLOW_BRIDGE_CLK_EN			(0x0001)
 /* Clock enable for FAST peripherals 16bit (R/W) */
 #define U300_SYSCON_CEFR					(0x0024)
-#ifdef CONFIG_MACH_U300_BS335
 #define U300_SYSCON_CEFR_UART1_CLK_EN				(0x0200)
-#endif
 #define U300_SYSCON_CEFR_I2S1_CORE_CLK_EN			(0x0100)
 #define U300_SYSCON_CEFR_I2S0_CORE_CLK_EN			(0x0080)
 #define U300_SYSCON_CEFR_SPI_CLK_EN				(0x0040)
 #define U300_SYSCON_CEFR_MMC_CLK_EN				(0x0020)
-#define U300_SYSCON_CEFR_I2S1_CLK_EN    			(0x0010)
-#define U300_SYSCON_CEFR_I2S0_CLK_EN     			(0x0008)
-#define U300_SYSCON_CEFR_I2C1_CLK_EN     			(0x0004)
-#define U300_SYSCON_CEFR_I2C0_CLK_EN     			(0x0002)
+#define U300_SYSCON_CEFR_I2S1_CLK_EN				(0x0010)
+#define U300_SYSCON_CEFR_I2S0_CLK_EN				(0x0008)
+#define U300_SYSCON_CEFR_I2C1_CLK_EN				(0x0004)
+#define U300_SYSCON_CEFR_I2C0_CLK_EN				(0x0002)
 #define U300_SYSCON_CEFR_FAST_BRIDGE_CLK_EN			(0x0001)
 /* Clock enable for the rest of the peripherals 16bit (R/W) */
 #define U300_SYSCON_CERR					(0x0028)
-#ifdef CONFIG_MACH_U300_BS335
 #define U300_SYSCON_CERR_CDS_CLK_EN				(0x2000)
 #define U300_SYSCON_CERR_ISP_CLK_EN				(0x1000)
-#endif
 #define U300_SYSCON_CERR_MSPRO_CLK_EN				(0x0800)
 #define U300_SYSCON_CERR_AHB_SUBSYS_BRIDGE_CLK_EN		(0x0400)
 #define U300_SYSCON_CERR_SEMI_CLK_EN				(0x0200)
@@ -124,9 +112,7 @@
 #define U300_SYSCON_CERR_AAIF_CLK_EN				(0x0001)
 /* Single block clock enable 16bit (-/W) */
 #define U300_SYSCON_SBCER					(0x002c)
-#ifdef CONFIG_MACH_U300_BS335
 #define U300_SYSCON_SBCER_PPM_CLK_EN				(0x0009)
-#endif
 #define U300_SYSCON_SBCER_ACC_TMR_CLK_EN			(0x0008)
 #define U300_SYSCON_SBCER_APP_TMR_CLK_EN			(0x0007)
 #define U300_SYSCON_SBCER_KEYPAD_CLK_EN				(0x0006)
@@ -135,9 +121,7 @@
 #define U300_SYSCON_SBCER_BTR_CLK_EN				(0x0002)
 #define U300_SYSCON_SBCER_UART_CLK_EN				(0x0001)
 #define U300_SYSCON_SBCER_SLOW_BRIDGE_CLK_EN			(0x0000)
-#ifdef CONFIG_MACH_U300_BS335
 #define U300_SYSCON_SBCER_UART1_CLK_EN				(0x0019)
-#endif
 #define U300_SYSCON_SBCER_I2S1_CORE_CLK_EN			(0x0018)
 #define U300_SYSCON_SBCER_I2S0_CORE_CLK_EN			(0x0017)
 #define U300_SYSCON_SBCER_SPI_CLK_EN				(0x0016)
@@ -147,10 +131,8 @@
 #define U300_SYSCON_SBCER_I2C1_CLK_EN				(0x0012)
 #define U300_SYSCON_SBCER_I2C0_CLK_EN				(0x0011)
 #define U300_SYSCON_SBCER_FAST_BRIDGE_CLK_EN			(0x0010)
-#ifdef CONFIG_MACH_U300_BS335
 #define U300_SYSCON_SBCER_CDS_CLK_EN				(0x002D)
 #define U300_SYSCON_SBCER_ISP_CLK_EN				(0x002C)
-#endif
 #define U300_SYSCON_SBCER_MSPRO_CLK_EN				(0x002B)
 #define U300_SYSCON_SBCER_AHB_SUBSYS_BRIDGE_CLK_EN		(0x002A)
 #define U300_SYSCON_SBCER_SEMI_CLK_EN				(0x0029)
@@ -168,9 +150,7 @@
 /* Same values as above for SBCER */
 /* Clock force SLOW peripherals 16bit (R/W) */
 #define U300_SYSCON_CFSR					(0x003c)
-#ifdef CONFIG_MACH_U300_BS335
 #define U300_SYSCON_CFSR_PPM_CLK_FORCE_EN			(0x0200)
-#endif
 #define U300_SYSCON_CFSR_ACC_TMR_CLK_FORCE_EN			(0x0100)
 #define U300_SYSCON_CFSR_APP_TMR_CLK_FORCE_EN			(0x0080)
 #define U300_SYSCON_CFSR_KEYPAD_CLK_FORCE_EN			(0x0020)
@@ -184,10 +164,8 @@
 /* Values not defined. Define if you want to use them. */
 /* Clock force the rest of the peripherals 16bit (R/W) */
 #define U300_SYSCON_CFRR					(0x44)
-#ifdef CONFIG_MACH_U300_BS335
 #define U300_SYSCON_CFRR_CDS_CLK_FORCE_EN			(0x2000)
 #define U300_SYSCON_CFRR_ISP_CLK_FORCE_EN			(0x1000)
-#endif
 #define U300_SYSCON_CFRR_MSPRO_CLK_FORCE_EN			(0x0800)
 #define U300_SYSCON_CFRR_AHB_SUBSYS_BRIDGE_CLK_FORCE_EN		(0x0400)
 #define U300_SYSCON_CFRR_SEMI_CLK_FORCE_EN			(0x0200)
diff --git a/arch/arm/mach-u300/include/mach/u300-regs.h b/arch/arm/mach-u300/include/mach/u300-regs.h
index 65f87c5..1e49d90 100644
--- a/arch/arm/mach-u300/include/mach/u300-regs.h
+++ b/arch/arm/mach-u300/include/mach/u300-regs.h
@@ -28,7 +28,6 @@
 #define PLAT_NAND_CLE			(1 << 16)
 #define PLAT_NAND_ALE			(1 << 17)
 
-
 /* AHB Peripherals */
 #define U300_AHB_PER_PHYS_BASE		0xa0000000
 #define U300_AHB_PER_VIRT_BASE		0xff010000
@@ -46,11 +45,7 @@
 #define U300_BOOTROM_VIRT_BASE		0xffff0000
 
 /* SEMI config base */
-#ifdef CONFIG_MACH_U300_BS335
 #define U300_SEMI_CONFIG_BASE		0x2FFE0000
-#else
-#define U300_SEMI_CONFIG_BASE		0x30000000
-#endif
 
 /*
  * AHB peripherals
@@ -99,10 +94,8 @@
 /* SPI controller */
 #define U300_SPI_BASE			(U300_FAST_PER_PHYS_BASE+0x6000)
 
-#ifdef CONFIG_MACH_U300_BS335
 /* Fast UART1 on U335 only */
 #define U300_UART1_BASE			(U300_SLOW_PER_PHYS_BASE+0x7000)
-#endif
 
 /*
  * SLOW peripherals
@@ -151,10 +144,8 @@
  * REST peripherals
  */
 
-/* ISP (image signal processor) is only available in U335 */
-#ifdef CONFIG_MACH_U300_BS335
+/* ISP (image signal processor) */
 #define U300_ISP_BASE			(0xA0008000)
-#endif
 
 /* DMA Controller base */
 #define U300_DMAC_BASE			(0xC0020000)
@@ -166,17 +157,9 @@
 #define U300_APEX_BASE			(0xc0030000)
 
 /* Video Encoder Base */
-#ifdef CONFIG_MACH_U300_BS335
 #define U300_VIDEOENC_BASE		(0xc0080000)
-#else
-#define U300_VIDEOENC_BASE		(0xc0040000)
-#endif
 
 /* XGAM Base */
 #define U300_XGAM_BASE			(0xd0000000)
 
-/*
- * Virtual accessor macros for static devices
- */
-
 #endif
diff --git a/arch/arm/mach-u300/spi.c b/arch/arm/mach-u300/spi.c
index a1affac..02e6659 100644
--- a/arch/arm/mach-u300/spi.c
+++ b/arch/arm/mach-u300/spi.c
@@ -12,7 +12,7 @@
 #include <linux/amba/pl022.h>
 #include <linux/err.h>
 #include <mach/coh901318.h>
-#include <mach/dma_channels.h>
+#include "dma_channels.h"
 
 /*
  * The following is for the actual devices on the SSP/SPI bus
diff --git a/arch/arm/mach-u300/timer.c b/arch/arm/mach-u300/timer.c
index 56ac06d..1da10e2 100644
--- a/arch/arm/mach-u300/timer.c
+++ b/arch/arm/mach-u300/timer.c
@@ -17,14 +17,17 @@
 #include <linux/io.h>
 #include <linux/clk.h>
 #include <linux/err.h>
+#include <linux/irq.h>
 
 #include <mach/hardware.h>
+#include <mach/irqs.h>
 
 /* Generic stuff */
 #include <asm/sched_clock.h>
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
-#include <asm/mach/irq.h>
+
+#include "timer.h"
 
 /*
  * APP side special timer registers
diff --git a/arch/arm/mach-u300/timer.h b/arch/arm/mach-u300/timer.h
new file mode 100644
index 0000000..b5e9791
--- /dev/null
+++ b/arch/arm/mach-u300/timer.h
@@ -0,0 +1 @@
+extern struct sys_timer u300_timer;
diff --git a/arch/arm/mach-u300/u300-gpio.h b/arch/arm/mach-u300/u300-gpio.h
index 847dc25..83f5077 100644
--- a/arch/arm/mach-u300/u300-gpio.h
+++ b/arch/arm/mach-u300/u300-gpio.h
@@ -1,50 +1,11 @@
 /*
- * Individual pin assignments for the B26/S26. Notice that the
- * actual usage of these pins depends on the PAD MUX settings, that
- * is why the same number can potentially appear several times.
- * In the reference design each pin is only used for one purpose.
- * These were determined by inspecting the B26/S26 schematic:
- * 2/1911-ROA 128 1603
- */
-#ifdef CONFIG_MACH_U300_BS2X
-#define U300_GPIO_PIN_UART_RX		0
-#define U300_GPIO_PIN_UART_TX		1
-#define U300_GPIO_PIN_GPIO02		2  /* Unrouted */
-#define U300_GPIO_PIN_GPIO03		3  /* Unrouted */
-#define U300_GPIO_PIN_CAM_SLEEP		4
-#define U300_GPIO_PIN_CAM_REG_EN	5
-#define U300_GPIO_PIN_GPIO06		6  /* Unrouted */
-#define U300_GPIO_PIN_GPIO07		7  /* Unrouted */
-
-#define U300_GPIO_PIN_GPIO08		8  /* Service point SP2321 */
-#define U300_GPIO_PIN_GPIO09		9  /* Service point SP2322 */
-#define U300_GPIO_PIN_PHFSENSE		10 /* Headphone jack sensing */
-#define U300_GPIO_PIN_MMC_CLKRET	11 /* Clock return from MMC/SD card */
-#define U300_GPIO_PIN_MMC_CD		12 /* MMC Card insertion detection */
-#define U300_GPIO_PIN_FLIPSENSE		13 /* Mechanical flip sensing */
-#define U300_GPIO_PIN_GPIO14		14 /* DSP JTAG Port RTCK */
-#define U300_GPIO_PIN_GPIO15		15 /* Unrouted */
-
-#define U300_GPIO_PIN_GPIO16		16 /* Unrouted */
-#define U300_GPIO_PIN_GPIO17		17 /* Unrouted */
-#define U300_GPIO_PIN_GPIO18		18 /* Unrouted */
-#define U300_GPIO_PIN_GPIO19		19 /* Unrouted */
-#define U300_GPIO_PIN_GPIO20		20 /* Unrouted */
-#define U300_GPIO_PIN_GPIO21		21 /* Unrouted */
-#define U300_GPIO_PIN_GPIO22		22 /* Unrouted */
-#define U300_GPIO_PIN_GPIO23		23 /* Unrouted */
-#endif
-
-/*
- * Individual pin assignments for the B330/S330 and B365/S365.
+ * Individual pin assignments for the B335/S335.
  * Notice that the actual usage of these pins depends on the
  * PAD MUX settings, that is why the same number can potentially
  * appear several times. In the reference design each pin is only
  * used for one purpose. These were determined by inspecting the
  * S365 schematic.
  */
-#if defined(CONFIG_MACH_U300_BS330) || defined(CONFIG_MACH_U300_BS365) || \
-    defined(CONFIG_MACH_U300_BS335)
 #define U300_GPIO_PIN_UART_RX		0
 #define U300_GPIO_PIN_UART_TX		1
 #define U300_GPIO_PIN_UART_CTS		2
@@ -90,8 +51,6 @@
 #define U300_GPIO_PIN_GPIO38		38 /* Unrouted */
 #define U300_GPIO_PIN_GPIO39		39 /* Unrouted */
 
-#ifdef CONFIG_MACH_U300_BS335
-
 #define U300_GPIO_PIN_GPIO40		40 /* Unrouted */
 #define U300_GPIO_PIN_GPIO41		41 /* Unrouted */
 #define U300_GPIO_PIN_GPIO42		42 /* Unrouted */
@@ -109,6 +68,3 @@
 #define U300_GPIO_PIN_GPIO53		53 /* Unrouted */
 #define U300_GPIO_PIN_GPIO54		54 /* Unrouted */
 #define U300_GPIO_PIN_GPIO55		55 /* Unrouted */
-#endif
-
-#endif
diff --git a/arch/arm/mach-u300/u300.c b/arch/arm/mach-u300/u300.c
deleted file mode 100644
index f30c69d..0000000
--- a/arch/arm/mach-u300/u300.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- *
- * arch/arm/mach-u300/u300.c
- *
- *
- * Copyright (C) 2006-2009 ST-Ericsson AB
- * License terms: GNU General Public License (GPL) version 2
- * Platform machine definition.
- * Author: Linus Walleij <linus.walleij@stericsson.com>
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/memblock.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <mach/hardware.h>
-#include <mach/platform.h>
-#include <asm/hardware/vic.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/memory.h>
-
-static void __init u300_init_machine(void)
-{
-	u300_init_devices();
-}
-
-#ifdef CONFIG_MACH_U300_BS2X
-#define MACH_U300_STRING "Ericsson AB U300 S25/S26/B25/B26 Prototype Board"
-#endif
-
-#ifdef CONFIG_MACH_U300_BS330
-#define MACH_U300_STRING "Ericsson AB U330 S330/B330 Prototype Board"
-#endif
-
-#ifdef CONFIG_MACH_U300_BS335
-#define MACH_U300_STRING "Ericsson AB U335 S335/B335 Prototype Board"
-#endif
-
-#ifdef CONFIG_MACH_U300_BS365
-#define MACH_U300_STRING "Ericsson AB U365 S365/B365 Prototype Board"
-#endif
-
-MACHINE_START(U300, MACH_U300_STRING)
-	/* Maintainer: Linus Walleij <linus.walleij@stericsson.com> */
-	.atag_offset	= 0x100,
-	.map_io		= u300_map_io,
-	.init_irq	= u300_init_irq,
-	.handle_irq	= vic_handle_irq,
-	.timer		= &u300_timer,
-	.init_machine	= u300_init_machine,
-	.restart	= u300_restart,
-MACHINE_END
diff --git a/arch/arm/mach-ux500/Kconfig b/arch/arm/mach-ux500/Kconfig
index 53d3d46..c77c86c4 100644
--- a/arch/arm/mach-ux500/Kconfig
+++ b/arch/arm/mach-ux500/Kconfig
@@ -11,6 +11,7 @@ config UX500_SOC_COMMON
 	select CACHE_L2X0
 	select PINCTRL
 	select PINCTRL_NOMADIK
+	select COMMON_CLK
 
 config UX500_SOC_DB8500
 	bool
@@ -28,6 +29,7 @@ config MACH_MOP500
 	select I2C
 	select I2C_NOMADIK
 	select SOC_BUS
+	select REGULATOR_FIXED_VOLTAGE
 	help
 	  Include support for the MOP500 development platform.
 
diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile
index 026086f..f24710d 100644
--- a/arch/arm/mach-ux500/Makefile
+++ b/arch/arm/mach-ux500/Makefile
@@ -2,7 +2,7 @@
 # Makefile for the linux kernel, U8500 machine.
 #
 
-obj-y				:= clock.o cpu.o devices.o devices-common.o \
+obj-y				:= cpu.o devices.o devices-common.o \
 				   id.o usb.o timer.o
 obj-$(CONFIG_CPU_IDLE)          += cpuidle.o
 obj-$(CONFIG_CACHE_L2X0)	+= cache-l2x0.o
@@ -12,6 +12,6 @@ obj-$(CONFIG_MACH_MOP500)	+= board-mop500.o board-mop500-sdi.o \
 				board-mop500-uib.o board-mop500-stuib.o \
 				board-mop500-u8500uib.o \
 				board-mop500-pins.o \
-				board-mop500-msp.o
+				board-mop500-audio.o
 obj-$(CONFIG_SMP)		+= platsmp.o headsmp.o
 obj-$(CONFIG_HOTPLUG_CPU)	+= hotplug.o
diff --git a/arch/arm/mach-ux500/Makefile.boot b/arch/arm/mach-ux500/Makefile.boot
index dd5cd00..760a0ef 100644
--- a/arch/arm/mach-ux500/Makefile.boot
+++ b/arch/arm/mach-ux500/Makefile.boot
@@ -1,5 +1,3 @@
    zreladdr-y	+= 0x00008000
 params_phys-y	:= 0x00000100
 initrd_phys-y	:= 0x00800000
-
-dtb-$(CONFIG_MACH_SNOWBALL) += snowball.dtb
diff --git a/arch/arm/mach-ux500/board-mop500-audio.c b/arch/arm/mach-ux500/board-mop500-audio.c
new file mode 100644
index 0000000..070629a
--- /dev/null
+++ b/arch/arm/mach-ux500/board-mop500-audio.c
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/gpio.h>
+
+#include <plat/gpio-nomadik.h>
+#include <plat/pincfg.h>
+#include <plat/ste_dma40.h>
+
+#include <mach/devices.h>
+#include <mach/hardware.h>
+#include <mach/irqs.h>
+#include <mach/msp.h>
+
+#include "ste-dma40-db8500.h"
+#include "board-mop500.h"
+#include "devices-db8500.h"
+#include "pins-db8500.h"
+
+static struct stedma40_chan_cfg msp0_dma_rx = {
+	.high_priority = true,
+	.dir = STEDMA40_PERIPH_TO_MEM,
+
+	.src_dev_type = DB8500_DMA_DEV31_MSP0_RX_SLIM0_CH0_RX,
+	.dst_dev_type = STEDMA40_DEV_DST_MEMORY,
+
+	.src_info.psize = STEDMA40_PSIZE_LOG_4,
+	.dst_info.psize = STEDMA40_PSIZE_LOG_4,
+
+	/* data_width is set during configuration */
+};
+
+static struct stedma40_chan_cfg msp0_dma_tx = {
+	.high_priority = true,
+	.dir = STEDMA40_MEM_TO_PERIPH,
+
+	.src_dev_type = STEDMA40_DEV_DST_MEMORY,
+	.dst_dev_type = DB8500_DMA_DEV31_MSP0_TX_SLIM0_CH0_TX,
+
+	.src_info.psize = STEDMA40_PSIZE_LOG_4,
+	.dst_info.psize = STEDMA40_PSIZE_LOG_4,
+
+	/* data_width is set during configuration */
+};
+
+struct msp_i2s_platform_data msp0_platform_data = {
+	.id = MSP_I2S_0,
+	.msp_i2s_dma_rx = &msp0_dma_rx,
+	.msp_i2s_dma_tx = &msp0_dma_tx,
+};
+
+static struct stedma40_chan_cfg msp1_dma_rx = {
+	.high_priority = true,
+	.dir = STEDMA40_PERIPH_TO_MEM,
+
+	.src_dev_type = DB8500_DMA_DEV30_MSP3_RX,
+	.dst_dev_type = STEDMA40_DEV_DST_MEMORY,
+
+	.src_info.psize = STEDMA40_PSIZE_LOG_4,
+	.dst_info.psize = STEDMA40_PSIZE_LOG_4,
+
+	/* data_width is set during configuration */
+};
+
+static struct stedma40_chan_cfg msp1_dma_tx = {
+	.high_priority = true,
+	.dir = STEDMA40_MEM_TO_PERIPH,
+
+	.src_dev_type = STEDMA40_DEV_DST_MEMORY,
+	.dst_dev_type = DB8500_DMA_DEV30_MSP1_TX,
+
+	.src_info.psize = STEDMA40_PSIZE_LOG_4,
+	.dst_info.psize = STEDMA40_PSIZE_LOG_4,
+
+	/* data_width is set during configuration */
+};
+
+struct msp_i2s_platform_data msp1_platform_data = {
+	.id = MSP_I2S_1,
+	.msp_i2s_dma_rx = NULL,
+	.msp_i2s_dma_tx = &msp1_dma_tx,
+};
+
+static struct stedma40_chan_cfg msp2_dma_rx = {
+	.high_priority = true,
+	.dir = STEDMA40_PERIPH_TO_MEM,
+
+	.src_dev_type = DB8500_DMA_DEV14_MSP2_RX,
+	.dst_dev_type = STEDMA40_DEV_DST_MEMORY,
+
+	/* MSP2 DMA doesn't work with PSIZE == 4 on DB8500v2 */
+	.src_info.psize = STEDMA40_PSIZE_LOG_1,
+	.dst_info.psize = STEDMA40_PSIZE_LOG_1,
+
+	/* data_width is set during configuration */
+};
+
+static struct stedma40_chan_cfg msp2_dma_tx = {
+	.high_priority = true,
+	.dir = STEDMA40_MEM_TO_PERIPH,
+
+	.src_dev_type = STEDMA40_DEV_DST_MEMORY,
+	.dst_dev_type = DB8500_DMA_DEV14_MSP2_TX,
+
+	.src_info.psize = STEDMA40_PSIZE_LOG_4,
+	.dst_info.psize = STEDMA40_PSIZE_LOG_4,
+
+	.use_fixed_channel = true,
+	.phy_channel = 1,
+
+	/* data_width is set during configuration */
+};
+
+static struct platform_device *db8500_add_msp_i2s(struct device *parent,
+			int id,
+			resource_size_t base, int irq,
+			struct msp_i2s_platform_data *pdata)
+{
+	struct platform_device *pdev;
+	struct resource res[] = {
+		DEFINE_RES_MEM(base, SZ_4K),
+		DEFINE_RES_IRQ(irq),
+	};
+
+	pr_info("Register platform-device 'ux500-msp-i2s', id %d, irq %d\n",
+		id, irq);
+	pdev = platform_device_register_resndata(parent, "ux500-msp-i2s", id,
+						res, ARRAY_SIZE(res),
+						pdata, sizeof(*pdata));
+	if (!pdev) {
+		pr_err("Failed to register platform-device 'ux500-msp-i2s.%d'!\n",
+			id);
+		return NULL;
+	}
+
+	return pdev;
+}
+
+/* Platform device for ASoC MOP500 machine */
+static struct platform_device snd_soc_mop500 = {
+	.name = "snd-soc-mop500",
+	.id = 0,
+	.dev = {
+		.platform_data = NULL,
+	},
+};
+
+/* Platform device for Ux500-PCM */
+static struct platform_device ux500_pcm = {
+		.name = "ux500-pcm",
+		.id = 0,
+		.dev = {
+			.platform_data = NULL,
+		},
+};
+
+struct msp_i2s_platform_data msp2_platform_data = {
+	.id = MSP_I2S_2,
+	.msp_i2s_dma_rx = &msp2_dma_rx,
+	.msp_i2s_dma_tx = &msp2_dma_tx,
+};
+
+struct msp_i2s_platform_data msp3_platform_data = {
+	.id		= MSP_I2S_3,
+	.msp_i2s_dma_rx	= &msp1_dma_rx,
+	.msp_i2s_dma_tx	= NULL,
+};
+
+void mop500_audio_init(struct device *parent)
+{
+	pr_info("%s: Register platform-device 'snd-soc-mop500'.\n", __func__);
+	platform_device_register(&snd_soc_mop500);
+
+	pr_info("Initialize MSP I2S-devices.\n");
+	db8500_add_msp_i2s(parent, 0, U8500_MSP0_BASE, IRQ_DB8500_MSP0,
+			   &msp0_platform_data);
+	db8500_add_msp_i2s(parent, 1, U8500_MSP1_BASE, IRQ_DB8500_MSP1,
+			   &msp1_platform_data);
+	db8500_add_msp_i2s(parent, 2, U8500_MSP2_BASE, IRQ_DB8500_MSP2,
+			   &msp2_platform_data);
+	db8500_add_msp_i2s(parent, 3, U8500_MSP3_BASE, IRQ_DB8500_MSP1,
+			   &msp3_platform_data);
+}
+
+/* Due for removal once the MSP driver has been fully DT:ed. */
+void mop500_of_audio_init(struct device *parent)
+{
+	pr_info("%s: Register platform-device 'ux500-pcm'\n", __func__);
+	platform_device_register(&ux500_pcm);
+}
diff --git a/arch/arm/mach-ux500/board-mop500-msp.c b/arch/arm/mach-ux500/board-mop500-msp.c
deleted file mode 100644
index df15646..0000000
--- a/arch/arm/mach-ux500/board-mop500-msp.c
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson SA 2010
- *
- * License terms: GNU General Public License (GPL), version 2
- */
-
-#include <linux/platform_device.h>
-#include <linux/init.h>
-#include <linux/gpio.h>
-#include <linux/pinctrl/consumer.h>
-
-#include <plat/gpio-nomadik.h>
-#include <plat/pincfg.h>
-#include <plat/ste_dma40.h>
-
-#include <mach/devices.h>
-#include <mach/hardware.h>
-#include <mach/irqs.h>
-#include <mach/msp.h>
-
-#include "ste-dma40-db8500.h"
-#include "board-mop500.h"
-#include "devices-db8500.h"
-#include "pins-db8500.h"
-
-/* MSP1/3 Tx/Rx usage protection */
-static DEFINE_SPINLOCK(msp_rxtx_lock);
-
-/* Reference Count */
-static int msp_rxtx_ref;
-
-/* Pin modes */
-struct pinctrl *msp1_p;
-struct pinctrl_state *msp1_def;
-struct pinctrl_state *msp1_sleep;
-
-int msp13_i2s_init(void)
-{
-	int retval = 0;
-	unsigned long flags;
-
-	spin_lock_irqsave(&msp_rxtx_lock, flags);
-	if (msp_rxtx_ref == 0 && !(IS_ERR(msp1_p) || IS_ERR(msp1_def))) {
-		retval = pinctrl_select_state(msp1_p, msp1_def);
-		if (retval)
-			pr_err("could not set MSP1 defstate\n");
-	}
-	if (!retval)
-		msp_rxtx_ref++;
-	spin_unlock_irqrestore(&msp_rxtx_lock, flags);
-
-	return retval;
-}
-
-int msp13_i2s_exit(void)
-{
-	int retval = 0;
-	unsigned long flags;
-
-	spin_lock_irqsave(&msp_rxtx_lock, flags);
-	WARN_ON(!msp_rxtx_ref);
-	msp_rxtx_ref--;
-	if (msp_rxtx_ref == 0 && !(IS_ERR(msp1_p) || IS_ERR(msp1_sleep))) {
-		retval = pinctrl_select_state(msp1_p, msp1_sleep);
-		if (retval)
-			pr_err("could not set MSP1 sleepstate\n");
-	}
-	spin_unlock_irqrestore(&msp_rxtx_lock, flags);
-
-	return retval;
-}
-
-static struct stedma40_chan_cfg msp0_dma_rx = {
-	.high_priority = true,
-	.dir = STEDMA40_PERIPH_TO_MEM,
-
-	.src_dev_type = DB8500_DMA_DEV31_MSP0_RX_SLIM0_CH0_RX,
-	.dst_dev_type = STEDMA40_DEV_DST_MEMORY,
-
-	.src_info.psize = STEDMA40_PSIZE_LOG_4,
-	.dst_info.psize = STEDMA40_PSIZE_LOG_4,
-
-	/* data_width is set during configuration */
-};
-
-static struct stedma40_chan_cfg msp0_dma_tx = {
-	.high_priority = true,
-	.dir = STEDMA40_MEM_TO_PERIPH,
-
-	.src_dev_type = STEDMA40_DEV_DST_MEMORY,
-	.dst_dev_type = DB8500_DMA_DEV31_MSP0_TX_SLIM0_CH0_TX,
-
-	.src_info.psize = STEDMA40_PSIZE_LOG_4,
-	.dst_info.psize = STEDMA40_PSIZE_LOG_4,
-
-	/* data_width is set during configuration */
-};
-
-static struct msp_i2s_platform_data msp0_platform_data = {
-	.id = MSP_I2S_0,
-	.msp_i2s_dma_rx = &msp0_dma_rx,
-	.msp_i2s_dma_tx = &msp0_dma_tx,
-};
-
-static struct stedma40_chan_cfg msp1_dma_rx = {
-	.high_priority = true,
-	.dir = STEDMA40_PERIPH_TO_MEM,
-
-	.src_dev_type = DB8500_DMA_DEV30_MSP3_RX,
-	.dst_dev_type = STEDMA40_DEV_DST_MEMORY,
-
-	.src_info.psize = STEDMA40_PSIZE_LOG_4,
-	.dst_info.psize = STEDMA40_PSIZE_LOG_4,
-
-	/* data_width is set during configuration */
-};
-
-static struct stedma40_chan_cfg msp1_dma_tx = {
-	.high_priority = true,
-	.dir = STEDMA40_MEM_TO_PERIPH,
-
-	.src_dev_type = STEDMA40_DEV_DST_MEMORY,
-	.dst_dev_type = DB8500_DMA_DEV30_MSP1_TX,
-
-	.src_info.psize = STEDMA40_PSIZE_LOG_4,
-	.dst_info.psize = STEDMA40_PSIZE_LOG_4,
-
-	/* data_width is set during configuration */
-};
-
-static struct msp_i2s_platform_data msp1_platform_data = {
-	.id = MSP_I2S_1,
-	.msp_i2s_dma_rx = NULL,
-	.msp_i2s_dma_tx = &msp1_dma_tx,
-	.msp_i2s_init = msp13_i2s_init,
-	.msp_i2s_exit = msp13_i2s_exit,
-};
-
-static struct stedma40_chan_cfg msp2_dma_rx = {
-	.high_priority = true,
-	.dir = STEDMA40_PERIPH_TO_MEM,
-
-	.src_dev_type = DB8500_DMA_DEV14_MSP2_RX,
-	.dst_dev_type = STEDMA40_DEV_DST_MEMORY,
-
-	/* MSP2 DMA doesn't work with PSIZE == 4 on DB8500v2 */
-	.src_info.psize = STEDMA40_PSIZE_LOG_1,
-	.dst_info.psize = STEDMA40_PSIZE_LOG_1,
-
-	/* data_width is set during configuration */
-};
-
-static struct stedma40_chan_cfg msp2_dma_tx = {
-	.high_priority = true,
-	.dir = STEDMA40_MEM_TO_PERIPH,
-
-	.src_dev_type = STEDMA40_DEV_DST_MEMORY,
-	.dst_dev_type = DB8500_DMA_DEV14_MSP2_TX,
-
-	.src_info.psize = STEDMA40_PSIZE_LOG_4,
-	.dst_info.psize = STEDMA40_PSIZE_LOG_4,
-
-	.use_fixed_channel = true,
-	.phy_channel = 1,
-
-	/* data_width is set during configuration */
-};
-
-static struct platform_device *db8500_add_msp_i2s(struct device *parent,
-			int id,
-			resource_size_t base, int irq,
-			struct msp_i2s_platform_data *pdata)
-{
-	struct platform_device *pdev;
-	struct resource res[] = {
-		DEFINE_RES_MEM(base, SZ_4K),
-		DEFINE_RES_IRQ(irq),
-	};
-
-	pr_info("Register platform-device 'ux500-msp-i2s', id %d, irq %d\n",
-		id, irq);
-	pdev = platform_device_register_resndata(parent, "ux500-msp-i2s", id,
-						res, ARRAY_SIZE(res),
-						pdata, sizeof(*pdata));
-	if (!pdev) {
-		pr_err("Failed to register platform-device 'ux500-msp-i2s.%d'!\n",
-			id);
-		return NULL;
-	}
-
-	return pdev;
-}
-
-/* Platform device for ASoC MOP500 machine */
-static struct platform_device snd_soc_mop500 = {
-		.name = "snd-soc-mop500",
-		.id = 0,
-		.dev = {
-			.platform_data = NULL,
-		},
-};
-
-/* Platform device for Ux500-PCM */
-static struct platform_device ux500_pcm = {
-		.name = "ux500-pcm",
-		.id = 0,
-		.dev = {
-			.platform_data = NULL,
-		},
-};
-
-static struct msp_i2s_platform_data msp2_platform_data = {
-	.id = MSP_I2S_2,
-	.msp_i2s_dma_rx = &msp2_dma_rx,
-	.msp_i2s_dma_tx = &msp2_dma_tx,
-};
-
-static struct msp_i2s_platform_data msp3_platform_data = {
-	.id		= MSP_I2S_3,
-	.msp_i2s_dma_rx	= &msp1_dma_rx,
-	.msp_i2s_dma_tx	= NULL,
-	.msp_i2s_init = msp13_i2s_init,
-	.msp_i2s_exit = msp13_i2s_exit,
-};
-
-int mop500_msp_init(struct device *parent)
-{
-	struct platform_device *msp1;
-
-	pr_info("%s: Register platform-device 'snd-soc-mop500'.\n", __func__);
-	platform_device_register(&snd_soc_mop500);
-
-	pr_info("Initialize MSP I2S-devices.\n");
-	db8500_add_msp_i2s(parent, 0, U8500_MSP0_BASE, IRQ_DB8500_MSP0,
-			   &msp0_platform_data);
-	msp1 = db8500_add_msp_i2s(parent, 1, U8500_MSP1_BASE, IRQ_DB8500_MSP1,
-			   &msp1_platform_data);
-	db8500_add_msp_i2s(parent, 2, U8500_MSP2_BASE, IRQ_DB8500_MSP2,
-			   &msp2_platform_data);
-	db8500_add_msp_i2s(parent, 3, U8500_MSP3_BASE, IRQ_DB8500_MSP1,
-			   &msp3_platform_data);
-
-	/* Get the pinctrl handle for MSP1 */
-	if (msp1) {
-		msp1_p = pinctrl_get(&msp1->dev);
-		if (IS_ERR(msp1_p))
-			dev_err(&msp1->dev, "could not get MSP1 pinctrl\n");
-		else {
-			msp1_def = pinctrl_lookup_state(msp1_p,
-							PINCTRL_STATE_DEFAULT);
-			if (IS_ERR(msp1_def)) {
-				dev_err(&msp1->dev,
-					"could not get MSP1 defstate\n");
-			}
-			msp1_sleep = pinctrl_lookup_state(msp1_p,
-							  PINCTRL_STATE_SLEEP);
-			if (IS_ERR(msp1_sleep))
-				dev_err(&msp1->dev,
-					"could not get MSP1 idlestate\n");
-		}
-	}
-
-	pr_info("%s: Register platform-device 'ux500-pcm'\n", __func__);
-	platform_device_register(&ux500_pcm);
-
-	return 0;
-}
diff --git a/arch/arm/mach-ux500/board-mop500-msp.h b/arch/arm/mach-ux500/board-mop500-msp.h
deleted file mode 100644
index 6fcfb5e..0000000
--- a/arch/arm/mach-ux500/board-mop500-msp.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson SA 2012
- *
- * Author: Ola Lilja <ola.o.lilja@stericsson.com>,
- *         for ST-Ericsson.
- *
- * License terms:
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation.
- */
-
-void mop500_msp_init(struct device *parent);
diff --git a/arch/arm/mach-ux500/board-mop500-pins.c b/arch/arm/mach-ux500/board-mop500-pins.c
index 32fd992..722523c 100644
--- a/arch/arm/mach-ux500/board-mop500-pins.c
+++ b/arch/arm/mach-ux500/board-mop500-pins.c
@@ -32,14 +32,14 @@ static enum custom_pin_cfg_t pinsfor;
 BIAS(pd, PIN_PULL_DOWN);
 BIAS(slpm_gpio_nopull, PIN_SLPM_GPIO|PIN_SLPM_INPUT_NOPULL);
 BIAS(in_nopull, PIN_INPUT_NOPULL);
-BIAS(in_nopull_sleep_nowkup, PIN_INPUT_NOPULL|PIN_SLPM_WAKEUP_DISABLE);
+BIAS(in_nopull_slpm_nowkup, PIN_INPUT_NOPULL|PIN_SLPM_WAKEUP_DISABLE);
 BIAS(in_pu, PIN_INPUT_PULLUP);
 BIAS(in_pd, PIN_INPUT_PULLDOWN);
 BIAS(in_pd_slpm_in_pu, PIN_INPUT_PULLDOWN|PIN_SLPM_INPUT_PULLUP);
 BIAS(in_pu_slpm_out_lo, PIN_INPUT_PULLUP|PIN_SLPM_OUTPUT_LOW);
 BIAS(out_hi, PIN_OUTPUT_HIGH);
 BIAS(out_lo, PIN_OUTPUT_LOW);
-BIAS(out_lo_sleep_nowkup, PIN_OUTPUT_LOW|PIN_SLPM_WAKEUP_DISABLE);
+BIAS(out_lo_slpm_nowkup, PIN_OUTPUT_LOW|PIN_SLPM_WAKEUP_DISABLE);
 /* These also force them into GPIO mode */
 BIAS(gpio_in_pu, PIN_INPUT_PULLUP|PIN_GPIOMODE_ENABLED);
 BIAS(gpio_in_pd, PIN_INPUT_PULLDOWN|PIN_GPIOMODE_ENABLED);
@@ -48,11 +48,13 @@ BIAS(gpio_in_pd_slpm_gpio_nopull, PIN_INPUT_PULLDOWN|PIN_GPIOMODE_ENABLED|PIN_SL
 BIAS(gpio_out_hi, PIN_OUTPUT_HIGH|PIN_GPIOMODE_ENABLED);
 BIAS(gpio_out_lo, PIN_OUTPUT_LOW|PIN_GPIOMODE_ENABLED);
 /* Sleep modes */
-BIAS(sleep_in_wkup_pdis, PIN_SLPM_DIR_INPUT|PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_DISABLED);
-BIAS(sleep_in_nopull_wkup, PIN_INPUT_NOPULL|PIN_SLPM_WAKEUP_ENABLE);
-BIAS(sleep_out_hi_wkup_pdis, PIN_SLPM_OUTPUT_HIGH|PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_DISABLED);
-BIAS(sleep_out_lo_wkup, PIN_OUTPUT_LOW|PIN_SLPM_WAKEUP_ENABLE);
-BIAS(sleep_out_wkup_pdis, PIN_SLPM_DIR_OUTPUT|PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_DISABLED);
+BIAS(slpm_in_wkup_pdis, PIN_SLEEPMODE_ENABLED|PIN_SLPM_DIR_INPUT|PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_DISABLED);
+BIAS(slpm_in_nopull_wkup, PIN_SLEEPMODE_ENABLED|PIN_SLPM_DIR_INPUT|PIN_SLPM_PULL_NONE|PIN_SLPM_WAKEUP_ENABLE);
+BIAS(slpm_wkup_pdis, PIN_SLEEPMODE_ENABLED|PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_DISABLED);
+BIAS(slpm_out_hi_wkup_pdis, PIN_SLEEPMODE_ENABLED|PIN_SLPM_OUTPUT_HIGH|PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_DISABLED);
+BIAS(slpm_out_wkup_pdis, PIN_SLEEPMODE_ENABLED|PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_DISABLED);
+BIAS(slpm_out_lo_wkup, PIN_SLEEPMODE_ENABLED|PIN_SLPM_OUTPUT_LOW|PIN_SLPM_WAKEUP_ENABLE);
+BIAS(slpm_out_lo_wkup_pdis, PIN_SLEEPMODE_ENABLED|PIN_SLPM_OUTPUT_LOW|PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_DISABLED);
 
 /* We use these to define hog settings that are always done on boot */
 #define DB8500_MUX_HOG(group,func) \
@@ -65,6 +67,9 @@ BIAS(sleep_out_wkup_pdis, PIN_SLPM_DIR_OUTPUT|PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PD
 	PIN_MAP_MUX_GROUP_DEFAULT(dev, "pinctrl-db8500", group, func)
 #define DB8500_PIN(pin,conf,dev) \
 	PIN_MAP_CONFIGS_PIN_DEFAULT(dev, "pinctrl-db8500", pin, conf)
+#define DB8500_PIN_SLEEP(pin, conf, dev) \
+	PIN_MAP_CONFIGS_PIN(dev, PINCTRL_STATE_SLEEP, "pinctrl-db8500",	\
+			    pin, conf)
 
 #define DB8500_PIN_SLEEP(pin,conf,dev) \
 	PIN_MAP_CONFIGS_PIN(dev, PINCTRL_STATE_SLEEP, "pinctrl-db8500",	\
@@ -134,22 +139,22 @@ static struct pinctrl_map __initdata mop500_family_pinmap[] = {
 	DB8500_PIN("GPIO2_AH4", in_pu, "uart0"), /* RXD */
 	DB8500_PIN("GPIO3_AH3", out_hi, "uart0"), /* TXD */
 	/* UART0 sleep state */
-	DB8500_PIN_SLEEP("GPIO0_AJ5", sleep_in_wkup_pdis, "uart0"),
-	DB8500_PIN_SLEEP("GPIO1_AJ3", sleep_out_hi_wkup_pdis, "uart0"),
-	DB8500_PIN_SLEEP("GPIO2_AH4", sleep_in_wkup_pdis, "uart0"),
-	DB8500_PIN_SLEEP("GPIO3_AH3", sleep_out_wkup_pdis, "uart0"),
+	DB8500_PIN_SLEEP("GPIO0_AJ5", slpm_in_wkup_pdis, "uart0"),
+	DB8500_PIN_SLEEP("GPIO1_AJ3", slpm_out_hi_wkup_pdis, "uart0"),
+	DB8500_PIN_SLEEP("GPIO2_AH4", slpm_in_wkup_pdis, "uart0"),
+	DB8500_PIN_SLEEP("GPIO3_AH3", slpm_out_wkup_pdis, "uart0"),
 	/* MSP1 for ALSA codec */
 	DB8500_MUX("msp1txrx_a_1", "msp1", "ux500-msp-i2s.1"),
 	DB8500_MUX("msp1_a_1", "msp1", "ux500-msp-i2s.1"),
-	DB8500_PIN("GPIO33_AF2", out_lo_sleep_nowkup, "ux500-msp-i2s.1"),
-	DB8500_PIN("GPIO34_AE1", in_nopull_sleep_nowkup, "ux500-msp-i2s.1"),
-	DB8500_PIN("GPIO35_AE2", in_nopull_sleep_nowkup, "ux500-msp-i2s.1"),
-	DB8500_PIN("GPIO36_AG2", in_nopull_sleep_nowkup, "ux500-msp-i2s.1"),
+	DB8500_PIN("GPIO33_AF2", out_lo_slpm_nowkup, "ux500-msp-i2s.1"),
+	DB8500_PIN("GPIO34_AE1", in_nopull_slpm_nowkup, "ux500-msp-i2s.1"),
+	DB8500_PIN("GPIO35_AE2", in_nopull_slpm_nowkup, "ux500-msp-i2s.1"),
+	DB8500_PIN("GPIO36_AG2", in_nopull_slpm_nowkup, "ux500-msp-i2s.1"),
 	/* MSP1 sleep state */
-	DB8500_PIN_SLEEP("GPIO33_AF2", sleep_out_lo_wkup, "ux500-msp-i2s.1"),
-	DB8500_PIN_SLEEP("GPIO34_AE1", sleep_in_nopull_wkup, "ux500-msp-i2s.1"),
-	DB8500_PIN_SLEEP("GPIO35_AE2", sleep_in_nopull_wkup, "ux500-msp-i2s.1"),
-	DB8500_PIN_SLEEP("GPIO36_AG2", sleep_in_nopull_wkup, "ux500-msp-i2s.1"),
+	DB8500_PIN_SLEEP("GPIO33_AF2", slpm_out_lo_wkup, "ux500-msp-i2s.1"),
+	DB8500_PIN_SLEEP("GPIO34_AE1", slpm_in_nopull_wkup, "ux500-msp-i2s.1"),
+	DB8500_PIN_SLEEP("GPIO35_AE2", slpm_in_nopull_wkup, "ux500-msp-i2s.1"),
+	DB8500_PIN_SLEEP("GPIO36_AG2", slpm_in_nopull_wkup, "ux500-msp-i2s.1"),
 	/* Mux in LCD data lines 8 thru 11 and LCDA CLK for MCDE TVOUT */
 	DB8500_MUX("lcd_d8_d11_a_1", "lcd", "mcde-tvout"),
 	DB8500_MUX("lcdaclk_b_1", "lcda", "mcde-tvout"),
@@ -219,11 +224,16 @@ static struct pinctrl_map __initdata mop500_family_pinmap[] = {
 	DB8500_MUX("usb_a_1", "usb", "musb-ux500.0"),
 	DB8500_PIN("GPIO257_AE29", out_hi, "musb-ux500.0"), /* STP */
 	/* Mux in SPI2 pins on the "other C1" altfunction */
-	DB8500_MUX("spi2_oc1_1", "spi2", "spi2"),
+	DB8500_MUX("spi2_oc1_2", "spi2", "spi2"),
 	DB8500_PIN("GPIO216_AG12", gpio_out_hi, "spi2"), /* FRM */
 	DB8500_PIN("GPIO218_AH11", in_pd, "spi2"), /* RXD */
 	DB8500_PIN("GPIO215_AH13", out_lo, "spi2"), /* TXD */
 	DB8500_PIN("GPIO217_AH12", out_lo, "spi2"), /* CLK */
+	/* SPI2 sleep state */
+	DB8500_PIN_SLEEP("GPIO216_AG12", slpm_in_wkup_pdis, "spi2"), /* FRM */
+	DB8500_PIN_SLEEP("GPIO218_AH11", slpm_in_wkup_pdis, "spi2"), /* RXD */
+	DB8500_PIN_SLEEP("GPIO215_AH13", slpm_out_lo_wkup_pdis, "spi2"), /* TXD */
+	DB8500_PIN_SLEEP("GPIO217_AH12", slpm_wkup_pdis, "spi2"), /* CLK */
 };
 
 /*
@@ -410,7 +420,7 @@ static struct pinctrl_map __initdata u9500_pinmap[] = {
 	DB8500_PIN_HOG("GPIO144_B13", gpio_in_pu),
 	/* HSI */
 	DB8500_MUX_HOG("hsir_a_1", "hsi"),
-	DB8500_MUX_HOG("hsit_a_1", "hsi"),
+	DB8500_MUX_HOG("hsit_a_2", "hsi"),
 	DB8500_PIN_HOG("GPIO219_AG10", in_pd), /* RX FLA0 */
 	DB8500_PIN_HOG("GPIO220_AH10", in_pd), /* RX DAT0 */
 	DB8500_PIN_HOG("GPIO221_AJ11", out_lo), /* RX RDY0 */
@@ -418,7 +428,7 @@ static struct pinctrl_map __initdata u9500_pinmap[] = {
 	DB8500_PIN_HOG("GPIO223_AH9", out_lo), /* TX DAT0 */
 	DB8500_PIN_HOG("GPIO224_AG9", in_pd), /* TX RDY0 */
 	DB8500_PIN_HOG("GPIO225_AG8", in_pd), /* CAWAKE0 */
-	DB8500_PIN_HOG("GPIO226_AF8", out_hi), /* ACWAKE0 */
+	DB8500_PIN_HOG("GPIO226_AF8", gpio_out_hi), /* ACWAKE0 */
 };
 
 static struct pinctrl_map __initdata u8500_pinmap[] = {
diff --git a/arch/arm/mach-ux500/board-mop500-regulators.c b/arch/arm/mach-ux500/board-mop500-regulators.c
index 52426a4..2a17bc5 100644
--- a/arch/arm/mach-ux500/board-mop500-regulators.c
+++ b/arch/arm/mach-ux500/board-mop500-regulators.c
@@ -13,6 +13,21 @@
 #include <linux/regulator/ab8500.h>
 #include "board-mop500-regulators.h"
 
+static struct regulator_consumer_supply gpio_en_3v3_consumers[] = {
+       REGULATOR_SUPPLY("vdd33a", "smsc911x.0"),
+};
+
+struct regulator_init_data gpio_en_3v3_regulator = {
+       .constraints = {
+               .name = "EN-3V3",
+               .min_uV = 3300000,
+               .max_uV = 3300000,
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+       },
+       .num_consumer_supplies = ARRAY_SIZE(gpio_en_3v3_consumers),
+       .consumer_supplies = gpio_en_3v3_consumers,
+};
+
 /*
  * TPS61052 regulator
  */
diff --git a/arch/arm/mach-ux500/board-mop500-regulators.h b/arch/arm/mach-ux500/board-mop500-regulators.h
index 9499215..78a0642 100644
--- a/arch/arm/mach-ux500/board-mop500-regulators.h
+++ b/arch/arm/mach-ux500/board-mop500-regulators.h
@@ -18,5 +18,6 @@ extern struct ab8500_regulator_reg_init
 ab8500_regulator_reg_init[AB8500_NUM_REGULATOR_REGISTERS];
 extern struct regulator_init_data ab8500_regulators[AB8500_NUM_REGULATORS];
 extern struct regulator_init_data tps61052_regulator;
+extern struct regulator_init_data gpio_en_3v3_regulator;
 
 #endif
diff --git a/arch/arm/mach-ux500/board-mop500-sdi.c b/arch/arm/mach-ux500/board-mop500-sdi.c
index 18ff781..9c8e4a9 100644
--- a/arch/arm/mach-ux500/board-mop500-sdi.c
+++ b/arch/arm/mach-ux500/board-mop500-sdi.c
@@ -152,7 +152,7 @@ static struct stedma40_chan_cfg sdi1_dma_cfg_tx = {
 };
 #endif
 
-static struct mmci_platform_data mop500_sdi1_data = {
+struct mmci_platform_data mop500_sdi1_data = {
 	.ocr_mask	= MMC_VDD_29_30,
 	.f_max		= 50000000,
 	.capabilities	= MMC_CAP_4_BIT_DATA,
@@ -189,7 +189,7 @@ static struct stedma40_chan_cfg mop500_sdi2_dma_cfg_tx = {
 };
 #endif
 
-static struct mmci_platform_data mop500_sdi2_data = {
+struct mmci_platform_data mop500_sdi2_data = {
 	.ocr_mask	= MMC_VDD_165_195,
 	.f_max		= 50000000,
 	.capabilities	= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA |
diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c
index a534d88..416d436 100644
--- a/arch/arm/mach-ux500/board-mop500.c
+++ b/arch/arm/mach-ux500/board-mop500.c
@@ -23,6 +23,7 @@
 #include <linux/spi/spi.h>
 #include <linux/mfd/abx500/ab8500.h>
 #include <linux/regulator/ab8500.h>
+#include <linux/regulator/fixed.h>
 #include <linux/mfd/tc3589x.h>
 #include <linux/mfd/tps6105x.h>
 #include <linux/mfd/abx500/ab8500-gpio.h>
@@ -48,13 +49,12 @@
 #include <mach/setup.h>
 #include <mach/devices.h>
 #include <mach/irqs.h>
-#include <mach/crypto-ux500.h>
+#include <linux/platform_data/crypto-ux500.h>
 
 #include "ste-dma40-db8500.h"
 #include "devices-db8500.h"
 #include "board-mop500.h"
 #include "board-mop500-regulators.h"
-#include "board-mop500-msp.h"
 
 static struct gpio_led snowball_led_array[] = {
 	{
@@ -76,6 +76,23 @@ static struct platform_device snowball_led_dev = {
 	},
 };
 
+static struct fixed_voltage_config snowball_gpio_en_3v3_data = {
+       .supply_name            = "EN-3V3",
+       .gpio                   = SNOWBALL_EN_3V3_ETH_GPIO,
+       .microvolts             = 3300000,
+       .enable_high            = 1,
+       .init_data              = &gpio_en_3v3_regulator,
+       .startup_delay          = 5000, /* 1200us */
+};
+
+static struct platform_device snowball_gpio_en_3v3_regulator_dev = {
+       .name   = "reg-fixed-voltage",
+       .id     = 1,
+       .dev    = {
+               .platform_data  = &snowball_gpio_en_3v3_data,
+       },
+};
+
 static struct ab8500_gpio_platform_data ab8500_gpio_pdata = {
 	.gpio_base		= MOP500_AB8500_PIN_GPIO(1),
 	.irq_base		= MOP500_AB8500_VIR_GPIO_IRQ_BASE,
@@ -524,33 +541,12 @@ static struct stedma40_chan_cfg uart2_dma_cfg_tx = {
 };
 #endif
 
-#define PRCC_K_SOFTRST_SET      0x18
-#define PRCC_K_SOFTRST_CLEAR    0x1C
-static void ux500_uart0_reset(void)
-{
-	void __iomem *prcc_rst_set, *prcc_rst_clr;
-
-	prcc_rst_set = (void __iomem *)IO_ADDRESS(U8500_CLKRST1_BASE +
-			PRCC_K_SOFTRST_SET);
-	prcc_rst_clr = (void __iomem *)IO_ADDRESS(U8500_CLKRST1_BASE +
-			PRCC_K_SOFTRST_CLEAR);
-
-	/* Activate soft reset PRCC_K_SOFTRST_CLEAR */
-	writel((readl(prcc_rst_clr) | 0x1), prcc_rst_clr);
-	udelay(1);
-
-	/* Release soft reset PRCC_K_SOFTRST_SET */
-	writel((readl(prcc_rst_set) | 0x1), prcc_rst_set);
-	udelay(1);
-}
-
 static struct amba_pl011_data uart0_plat = {
 #ifdef CONFIG_STE_DMA40
 	.dma_filter = stedma40_filter,
 	.dma_rx_param = &uart0_dma_cfg_rx,
 	.dma_tx_param = &uart0_dma_cfg_tx,
 #endif
-	.reset = ux500_uart0_reset,
 };
 
 static struct amba_pl011_data uart1_plat = {
@@ -586,6 +582,7 @@ static struct platform_device *snowball_platform_devs[] __initdata = {
 	&snowball_led_dev,
 	&snowball_key_dev,
 	&snowball_sbnet_dev,
+	&snowball_gpio_en_3v3_regulator_dev,
 };
 
 static void __init mop500_init_machine(void)
@@ -608,7 +605,7 @@ static void __init mop500_init_machine(void)
 	mop500_i2c_init(parent);
 	mop500_sdi_init(parent);
 	mop500_spi_init(parent);
-	mop500_msp_init(parent);
+	mop500_audio_init(parent);
 	mop500_uart_init(parent);
 
 	u8500_cryp1_hash1_init(parent);
@@ -642,7 +639,7 @@ static void __init snowball_init_machine(void)
 	mop500_i2c_init(parent);
 	snowball_sdi_init(parent);
 	mop500_spi_init(parent);
-	mop500_msp_init(parent);
+	mop500_audio_init(parent);
 	mop500_uart_init(parent);
 
 	/* This board has full regulator constraints */
@@ -674,7 +671,7 @@ static void __init hrefv60_init_machine(void)
 	mop500_i2c_init(parent);
 	hrefv60_sdi_init(parent);
 	mop500_spi_init(parent);
-	mop500_msp_init(parent);
+	mop500_audio_init(parent);
 	mop500_uart_init(parent);
 
 	i2c0_devs = ARRAY_SIZE(mop500_i2c0_devices);
@@ -694,6 +691,7 @@ static void __init hrefv60_init_machine(void)
 MACHINE_START(U8500, "ST-Ericsson MOP500 platform")
 	/* Maintainer: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com> */
 	.atag_offset	= 0x100,
+	.smp		= smp_ops(ux500_smp_ops),
 	.map_io		= u8500_map_io,
 	.init_irq	= ux500_init_irq,
 	/* we re-use nomadik timer here */
@@ -705,6 +703,7 @@ MACHINE_END
 
 MACHINE_START(HREFV60, "ST-Ericsson U8500 Platform HREFv60+")
 	.atag_offset	= 0x100,
+	.smp		= smp_ops(ux500_smp_ops),
 	.map_io		= u8500_map_io,
 	.init_irq	= ux500_init_irq,
 	.timer		= &ux500_timer,
@@ -715,6 +714,7 @@ MACHINE_END
 
 MACHINE_START(SNOWBALL, "Calao Systems Snowball platform")
 	.atag_offset	= 0x100,
+	.smp		= smp_ops(ux500_smp_ops),
 	.map_io		= u8500_map_io,
 	.init_irq	= ux500_init_irq,
 	/* we re-use nomadik timer here */
@@ -726,12 +726,9 @@ MACHINE_END
 
 #ifdef CONFIG_MACH_UX500_DT
 
-static struct platform_device *snowball_of_platform_devs[] __initdata = {
-	&snowball_led_dev,
-	&snowball_key_dev,
-};
-
 struct of_dev_auxdata u8500_auxdata_lookup[] __initdata = {
+	/* Requires call-back bindings. */
+	OF_DEV_AUXDATA("arm,cortex-a9-pmu", 0, "arm-pmu", &db8500_pmu_platdata),
 	/* Requires DMA and call-back bindings. */
 	OF_DEV_AUXDATA("arm,pl011", 0x80120000, "uart0", &uart0_plat),
 	OF_DEV_AUXDATA("arm,pl011", 0x80121000, "uart1", &uart1_plat),
@@ -739,6 +736,8 @@ struct of_dev_auxdata u8500_auxdata_lookup[] __initdata = {
 	/* Requires DMA bindings. */
 	OF_DEV_AUXDATA("arm,pl022", 0x80002000, "ssp0",  &ssp0_plat),
 	OF_DEV_AUXDATA("arm,pl18x", 0x80126000, "sdi0",  &mop500_sdi0_data),
+	OF_DEV_AUXDATA("arm,pl18x", 0x80118000, "sdi1",  &mop500_sdi1_data),
+	OF_DEV_AUXDATA("arm,pl18x", 0x80005000, "sdi2",  &mop500_sdi2_data),
 	OF_DEV_AUXDATA("arm,pl18x", 0x80114000, "sdi4",  &mop500_sdi4_data),
 	/* Requires clock name bindings. */
 	OF_DEV_AUXDATA("st,nomadik-gpio", 0x8012e000, "gpio.0", NULL),
@@ -757,6 +756,15 @@ struct of_dev_auxdata u8500_auxdata_lookup[] __initdata = {
 	OF_DEV_AUXDATA("st,nomadik-i2c", 0x8012a000, "nmk-i2c.4", NULL),
 	/* Requires device name bindings. */
 	OF_DEV_AUXDATA("stericsson,nmk_pinctrl", 0, "pinctrl-db8500", NULL),
+	/* Requires clock name and DMA bindings. */
+	OF_DEV_AUXDATA("stericsson,ux500-msp-i2s", 0x80123000,
+		"ux500-msp-i2s.0", &msp0_platform_data),
+	OF_DEV_AUXDATA("stericsson,ux500-msp-i2s", 0x80124000,
+		"ux500-msp-i2s.1", &msp1_platform_data),
+	OF_DEV_AUXDATA("stericsson,ux500-msp-i2s", 0x80117000,
+		"ux500-msp-i2s.2", &msp2_platform_data),
+	OF_DEV_AUXDATA("stericsson,ux500-msp-i2s", 0x80125000,
+		"ux500-msp-i2s.3", &msp3_platform_data),
 	{},
 };
 
@@ -797,7 +805,7 @@ static void __init u8500_init_machine(void)
 				ARRAY_SIZE(mop500_platform_devs));
 
 		mop500_sdi_init(parent);
-		mop500_msp_init(parent);
+		mop500_audio_init(parent);
 		i2c0_devs = ARRAY_SIZE(mop500_i2c0_devices);
 		i2c_register_board_info(0, mop500_i2c0_devices, i2c0_devs);
 		i2c_register_board_info(2, mop500_i2c2_devices,
@@ -806,7 +814,7 @@ static void __init u8500_init_machine(void)
 		mop500_uib_init();
 
 	} else if (of_machine_is_compatible("calaosystems,snowball-a9500")) {
-		mop500_msp_init(parent);
+		mop500_of_audio_init(parent);
 	} else if (of_machine_is_compatible("st-ericsson,hrefv60+")) {
 		/*
 		 * The HREFv60 board removed a GPIO expander and routed
@@ -817,16 +825,6 @@ static void __init u8500_init_machine(void)
 		platform_add_devices(mop500_platform_devs,
 				ARRAY_SIZE(mop500_platform_devs));
 
-		hrefv60_sdi_init(parent);
-		mop500_msp_init(parent);
-
-		i2c0_devs = ARRAY_SIZE(mop500_i2c0_devices);
-		i2c0_devs -= NUM_PRE_V60_I2C0_DEVICES;
-
-		i2c_register_board_info(0, mop500_i2c0_devices, i2c0_devs);
-		i2c_register_board_info(2, mop500_i2c2_devices,
-					ARRAY_SIZE(mop500_i2c2_devices));
-
 		mop500_uib_init();
 	}
 
@@ -844,6 +842,7 @@ static const char * u8500_dt_board_compat[] = {
 
 
 DT_MACHINE_START(U8500_DT, "ST-Ericsson U8500 platform (Device Tree Support)")
+	.smp		= smp_ops(ux500_smp_ops),
 	.map_io		= u8500_map_io,
 	.init_irq	= ux500_init_irq,
 	/* we re-use nomadik timer here */
diff --git a/arch/arm/mach-ux500/board-mop500.h b/arch/arm/mach-ux500/board-mop500.h
index b5bfc1a..aca39a6 100644
--- a/arch/arm/mach-ux500/board-mop500.h
+++ b/arch/arm/mach-ux500/board-mop500.h
@@ -9,6 +9,7 @@
 
 /* For NOMADIK_NR_GPIO */
 #include <mach/irqs.h>
+#include <mach/msp.h>
 #include <linux/amba/mmci.h>
 
 /* Snowball specific GPIO assignments, this board has no GPIO expander */
@@ -80,7 +81,14 @@
 struct device;
 struct i2c_board_info;
 extern struct mmci_platform_data mop500_sdi0_data;
+extern struct mmci_platform_data mop500_sdi1_data;
+extern struct mmci_platform_data mop500_sdi2_data;
 extern struct mmci_platform_data mop500_sdi4_data;
+extern struct msp_i2s_platform_data msp0_platform_data;
+extern struct msp_i2s_platform_data msp1_platform_data;
+extern struct msp_i2s_platform_data msp2_platform_data;
+extern struct msp_i2s_platform_data msp3_platform_data;
+extern struct arm_pmu_platdata db8500_pmu_platdata;
 
 extern void mop500_sdi_init(struct device *parent);
 extern void snowball_sdi_init(struct device *parent);
@@ -91,6 +99,9 @@ void __init mop500_stuib_init(void);
 void __init mop500_pinmaps_init(void);
 void __init snowball_pinmaps_init(void);
 void __init hrefv60_pinmaps_init(void);
+void mop500_audio_init(struct device *parent);
+/* Due for removal once the MSP driver has been fully DT:ed. */
+void mop500_of_audio_init(struct device *parent);
 
 int __init mop500_uib_init(void);
 void mop500_uib_i2c_add(int busnum, struct i2c_board_info *info,
diff --git a/arch/arm/mach-ux500/cache-l2x0.c b/arch/arm/mach-ux500/cache-l2x0.c
index dc12394..75d5b51 100644
--- a/arch/arm/mach-ux500/cache-l2x0.c
+++ b/arch/arm/mach-ux500/cache-l2x0.c
@@ -38,7 +38,7 @@ static int __init ux500_l2x0_init(void)
 {
 	u32 aux_val = 0x3e000000;
 
-	if (cpu_is_u8500_family())
+	if (cpu_is_u8500_family() || cpu_is_ux540_family())
 		l2x0_base = __io_address(U8500_L2CC_BASE);
 	else
 		ux500_unknown_soc();
diff --git a/arch/arm/mach-ux500/clock.c b/arch/arm/mach-ux500/clock.c
deleted file mode 100644
index 8d73b06..0000000
--- a/arch/arm/mach-ux500/clock.c
+++ /dev/null
@@ -1,715 +0,0 @@
-/*
- *  Copyright (C) 2009 ST-Ericsson
- *  Copyright (C) 2009 STMicroelectronics
- *
- * This program is free software; you can 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/errno.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/clkdev.h>
-#include <linux/cpufreq.h>
-
-#include <plat/mtu.h>
-#include <mach/hardware.h>
-#include "clock.h"
-
-#ifdef CONFIG_DEBUG_FS
-#include <linux/debugfs.h>
-#include <linux/uaccess.h>	/* for copy_from_user */
-static LIST_HEAD(clk_list);
-#endif
-
-#define PRCC_PCKEN		0x00
-#define PRCC_PCKDIS		0x04
-#define PRCC_KCKEN		0x08
-#define PRCC_KCKDIS		0x0C
-
-#define PRCM_YYCLKEN0_MGT_SET	0x510
-#define PRCM_YYCLKEN1_MGT_SET	0x514
-#define PRCM_YYCLKEN0_MGT_CLR	0x518
-#define PRCM_YYCLKEN1_MGT_CLR	0x51C
-#define PRCM_YYCLKEN0_MGT_VAL	0x520
-#define PRCM_YYCLKEN1_MGT_VAL	0x524
-
-#define PRCM_SVAMMDSPCLK_MGT	0x008
-#define PRCM_SIAMMDSPCLK_MGT	0x00C
-#define PRCM_SGACLK_MGT		0x014
-#define PRCM_UARTCLK_MGT	0x018
-#define PRCM_MSP02CLK_MGT	0x01C
-#define PRCM_MSP1CLK_MGT	0x288
-#define PRCM_I2CCLK_MGT		0x020
-#define PRCM_SDMMCCLK_MGT	0x024
-#define PRCM_SLIMCLK_MGT	0x028
-#define PRCM_PER1CLK_MGT	0x02C
-#define PRCM_PER2CLK_MGT	0x030
-#define PRCM_PER3CLK_MGT	0x034
-#define PRCM_PER5CLK_MGT	0x038
-#define PRCM_PER6CLK_MGT	0x03C
-#define PRCM_PER7CLK_MGT	0x040
-#define PRCM_LCDCLK_MGT		0x044
-#define PRCM_BMLCLK_MGT		0x04C
-#define PRCM_HSITXCLK_MGT	0x050
-#define PRCM_HSIRXCLK_MGT	0x054
-#define PRCM_HDMICLK_MGT	0x058
-#define PRCM_APEATCLK_MGT	0x05C
-#define PRCM_APETRACECLK_MGT	0x060
-#define PRCM_MCDECLK_MGT	0x064
-#define PRCM_IPI2CCLK_MGT	0x068
-#define PRCM_DSIALTCLK_MGT	0x06C
-#define PRCM_DMACLK_MGT		0x074
-#define PRCM_B2R2CLK_MGT	0x078
-#define PRCM_TVCLK_MGT		0x07C
-#define PRCM_TCR		0x1C8
-#define PRCM_TCR_STOPPED	(1 << 16)
-#define PRCM_TCR_DOZE_MODE	(1 << 17)
-#define PRCM_UNIPROCLK_MGT	0x278
-#define PRCM_SSPCLK_MGT		0x280
-#define PRCM_RNGCLK_MGT		0x284
-#define PRCM_UICCCLK_MGT	0x27C
-
-#define PRCM_MGT_ENABLE		(1 << 8)
-
-static DEFINE_SPINLOCK(clocks_lock);
-
-static void __clk_enable(struct clk *clk)
-{
-	if (clk->enabled++ == 0) {
-		if (clk->parent_cluster)
-			__clk_enable(clk->parent_cluster);
-
-		if (clk->parent_periph)
-			__clk_enable(clk->parent_periph);
-
-		if (clk->ops && clk->ops->enable)
-			clk->ops->enable(clk);
-	}
-}
-
-int clk_enable(struct clk *clk)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&clocks_lock, flags);
-	__clk_enable(clk);
-	spin_unlock_irqrestore(&clocks_lock, flags);
-
-	return 0;
-}
-EXPORT_SYMBOL(clk_enable);
-
-static void __clk_disable(struct clk *clk)
-{
-	if (--clk->enabled == 0) {
-		if (clk->ops && clk->ops->disable)
-			clk->ops->disable(clk);
-
-		if (clk->parent_periph)
-			__clk_disable(clk->parent_periph);
-
-		if (clk->parent_cluster)
-			__clk_disable(clk->parent_cluster);
-	}
-}
-
-void clk_disable(struct clk *clk)
-{
-	unsigned long flags;
-
-	WARN_ON(!clk->enabled);
-
-	spin_lock_irqsave(&clocks_lock, flags);
-	__clk_disable(clk);
-	spin_unlock_irqrestore(&clocks_lock, flags);
-}
-EXPORT_SYMBOL(clk_disable);
-
-/*
- * The MTU has a separate, rather complex muxing setup
- * with alternative parents (peripheral cluster or
- * ULP or fixed 32768 Hz) depending on settings
- */
-static unsigned long clk_mtu_get_rate(struct clk *clk)
-{
-	void __iomem *addr;
-	u32 tcr;
-	int mtu = (int) clk->data;
-	/*
-	 * One of these is selected eventually
-	 * TODO: Replace the constant with a reference
-	 * to the ULP source once this is modeled.
-	 */
-	unsigned long clk32k = 32768;
-	unsigned long mturate;
-	unsigned long retclk;
-
-	if (cpu_is_u8500_family())
-		addr = __io_address(U8500_PRCMU_BASE);
-	else
-		ux500_unknown_soc();
-
-	/*
-	 * On a startup, always conifgure the TCR to the doze mode;
-	 * bootloaders do it for us. Do this in the kernel too.
-	 */
-	writel(PRCM_TCR_DOZE_MODE, addr + PRCM_TCR);
-
-	tcr = readl(addr + PRCM_TCR);
-
-	/* Get the rate from the parent as a default */
-	if (clk->parent_periph)
-		mturate = clk_get_rate(clk->parent_periph);
-	else if (clk->parent_cluster)
-		mturate = clk_get_rate(clk->parent_cluster);
-	else
-		/* We need to be connected SOMEWHERE */
-		BUG();
-
-	/* Return the clock selected for this MTU */
-	if (tcr & (1 << mtu))
-		retclk = clk32k;
-	else
-		retclk = mturate;
-
-	pr_info("MTU%d clock rate: %lu Hz\n", mtu, retclk);
-	return retclk;
-}
-
-unsigned long clk_get_rate(struct clk *clk)
-{
-	unsigned long rate;
-
-	/*
-	 * If there is a custom getrate callback for this clock,
-	 * it will take precedence.
-	 */
-	if (clk->get_rate)
-		return clk->get_rate(clk);
-
-	if (clk->ops && clk->ops->get_rate)
-		return clk->ops->get_rate(clk);
-
-	rate = clk->rate;
-	if (!rate) {
-		if (clk->parent_periph)
-			rate = clk_get_rate(clk->parent_periph);
-		else if (clk->parent_cluster)
-			rate = clk_get_rate(clk->parent_cluster);
-	}
-
-	return rate;
-}
-EXPORT_SYMBOL(clk_get_rate);
-
-long clk_round_rate(struct clk *clk, unsigned long rate)
-{
-	/*TODO*/
-	return rate;
-}
-EXPORT_SYMBOL(clk_round_rate);
-
-int clk_set_rate(struct clk *clk, unsigned long rate)
-{
-	clk->rate = rate;
-	return 0;
-}
-EXPORT_SYMBOL(clk_set_rate);
-
-int clk_set_parent(struct clk *clk, struct clk *parent)
-{
-	/*TODO*/
-	return -ENOSYS;
-}
-EXPORT_SYMBOL(clk_set_parent);
-
-static void clk_prcmu_enable(struct clk *clk)
-{
-	void __iomem *cg_set_reg = __io_address(U8500_PRCMU_BASE)
-				   + PRCM_YYCLKEN0_MGT_SET + clk->prcmu_cg_off;
-
-	writel(1 << clk->prcmu_cg_bit, cg_set_reg);
-}
-
-static void clk_prcmu_disable(struct clk *clk)
-{
-	void __iomem *cg_clr_reg = __io_address(U8500_PRCMU_BASE)
-				   + PRCM_YYCLKEN0_MGT_CLR + clk->prcmu_cg_off;
-
-	writel(1 << clk->prcmu_cg_bit, cg_clr_reg);
-}
-
-static struct clkops clk_prcmu_ops = {
-	.enable = clk_prcmu_enable,
-	.disable = clk_prcmu_disable,
-};
-
-static unsigned int clkrst_base[] = {
-	[1] = U8500_CLKRST1_BASE,
-	[2] = U8500_CLKRST2_BASE,
-	[3] = U8500_CLKRST3_BASE,
-	[5] = U8500_CLKRST5_BASE,
-	[6] = U8500_CLKRST6_BASE,
-};
-
-static void clk_prcc_enable(struct clk *clk)
-{
-	void __iomem *addr = __io_address(clkrst_base[clk->cluster]);
-
-	if (clk->prcc_kernel != -1)
-		writel(1 << clk->prcc_kernel, addr + PRCC_KCKEN);
-
-	if (clk->prcc_bus != -1)
-		writel(1 << clk->prcc_bus, addr + PRCC_PCKEN);
-}
-
-static void clk_prcc_disable(struct clk *clk)
-{
-	void __iomem *addr = __io_address(clkrst_base[clk->cluster]);
-
-	if (clk->prcc_bus != -1)
-		writel(1 << clk->prcc_bus, addr + PRCC_PCKDIS);
-
-	if (clk->prcc_kernel != -1)
-		writel(1 << clk->prcc_kernel, addr + PRCC_KCKDIS);
-}
-
-static struct clkops clk_prcc_ops = {
-	.enable = clk_prcc_enable,
-	.disable = clk_prcc_disable,
-};
-
-static struct clk clk_32khz = {
-	.name =  "clk_32khz",
-	.rate = 32000,
-};
-
-/*
- * PRCMU level clock gating
- */
-
-/* Bank 0 */
-static DEFINE_PRCMU_CLK(svaclk,		0x0, 2, SVAMMDSPCLK);
-static DEFINE_PRCMU_CLK(siaclk,		0x0, 3, SIAMMDSPCLK);
-static DEFINE_PRCMU_CLK(sgaclk,		0x0, 4, SGACLK);
-static DEFINE_PRCMU_CLK_RATE(uartclk,	0x0, 5, UARTCLK, 38400000);
-static DEFINE_PRCMU_CLK(msp02clk,	0x0, 6, MSP02CLK);
-static DEFINE_PRCMU_CLK(msp1clk,	0x0, 7, MSP1CLK); /* v1 */
-static DEFINE_PRCMU_CLK_RATE(i2cclk,	0x0, 8, I2CCLK, 48000000);
-static DEFINE_PRCMU_CLK_RATE(sdmmcclk,	0x0, 9, SDMMCCLK, 100000000);
-static DEFINE_PRCMU_CLK(slimclk,	0x0, 10, SLIMCLK);
-static DEFINE_PRCMU_CLK(per1clk,	0x0, 11, PER1CLK);
-static DEFINE_PRCMU_CLK(per2clk,	0x0, 12, PER2CLK);
-static DEFINE_PRCMU_CLK(per3clk,	0x0, 13, PER3CLK);
-static DEFINE_PRCMU_CLK(per5clk,	0x0, 14, PER5CLK);
-static DEFINE_PRCMU_CLK_RATE(per6clk,	0x0, 15, PER6CLK, 133330000);
-static DEFINE_PRCMU_CLK(lcdclk,		0x0, 17, LCDCLK);
-static DEFINE_PRCMU_CLK(bmlclk,		0x0, 18, BMLCLK);
-static DEFINE_PRCMU_CLK(hsitxclk,	0x0, 19, HSITXCLK);
-static DEFINE_PRCMU_CLK(hsirxclk,	0x0, 20, HSIRXCLK);
-static DEFINE_PRCMU_CLK(hdmiclk,	0x0, 21, HDMICLK);
-static DEFINE_PRCMU_CLK(apeatclk,	0x0, 22, APEATCLK);
-static DEFINE_PRCMU_CLK(apetraceclk,	0x0, 23, APETRACECLK);
-static DEFINE_PRCMU_CLK(mcdeclk,	0x0, 24, MCDECLK);
-static DEFINE_PRCMU_CLK(ipi2clk,	0x0, 25, IPI2CCLK);
-static DEFINE_PRCMU_CLK(dsialtclk,	0x0, 26, DSIALTCLK); /* v1 */
-static DEFINE_PRCMU_CLK(dmaclk,		0x0, 27, DMACLK);
-static DEFINE_PRCMU_CLK(b2r2clk,	0x0, 28, B2R2CLK);
-static DEFINE_PRCMU_CLK(tvclk,		0x0, 29, TVCLK);
-static DEFINE_PRCMU_CLK(uniproclk,	0x0, 30, UNIPROCLK); /* v1 */
-static DEFINE_PRCMU_CLK_RATE(sspclk,	0x0, 31, SSPCLK, 48000000); /* v1 */
-
-/* Bank 1 */
-static DEFINE_PRCMU_CLK(rngclk,		0x4, 0, RNGCLK); /* v1 */
-static DEFINE_PRCMU_CLK(uiccclk,	0x4, 1, UICCCLK); /* v1 */
-
-/*
- * PRCC level clock gating
- * Format: per#, clk, PCKEN bit, KCKEN bit, parent
- */
-
-/* Peripheral Cluster #1 */
-static DEFINE_PRCC_CLK(1, msp3,		11, 10, &clk_msp1clk);
-static DEFINE_PRCC_CLK(1, i2c4,		10, 9, &clk_i2cclk);
-static DEFINE_PRCC_CLK(1, gpio0,	9, -1, NULL);
-static DEFINE_PRCC_CLK(1, slimbus0,	8,  8, &clk_slimclk);
-static DEFINE_PRCC_CLK(1, spi3,		7, -1, NULL);
-static DEFINE_PRCC_CLK(1, i2c2,		6,  6, &clk_i2cclk);
-static DEFINE_PRCC_CLK(1, sdi0,		5,  5, &clk_sdmmcclk);
-static DEFINE_PRCC_CLK(1, msp1,		4,  4, &clk_msp1clk);
-static DEFINE_PRCC_CLK(1, msp0,		3,  3, &clk_msp02clk);
-static DEFINE_PRCC_CLK(1, i2c1,		2,  2, &clk_i2cclk);
-static DEFINE_PRCC_CLK(1, uart1,	1,  1, &clk_uartclk);
-static DEFINE_PRCC_CLK(1, uart0,	0,  0, &clk_uartclk);
-
-/* Peripheral Cluster #2 */
-static DEFINE_PRCC_CLK(2, gpio1,	11, -1, NULL);
-static DEFINE_PRCC_CLK(2, ssitx,	10,  7, NULL);
-static DEFINE_PRCC_CLK(2, ssirx,	 9,  6, NULL);
-static DEFINE_PRCC_CLK(2, spi0,		8, -1, NULL);
-static DEFINE_PRCC_CLK(2, sdi3,		7,  5, &clk_sdmmcclk);
-static DEFINE_PRCC_CLK(2, sdi1,		6,  4, &clk_sdmmcclk);
-static DEFINE_PRCC_CLK(2, msp2,		5,  3, &clk_msp02clk);
-static DEFINE_PRCC_CLK(2, sdi4,		4,  2, &clk_sdmmcclk);
-static DEFINE_PRCC_CLK(2, pwl,		3,  1, NULL);
-static DEFINE_PRCC_CLK(2, spi1,		2, -1, NULL);
-static DEFINE_PRCC_CLK(2, spi2,		1, -1, NULL);
-static DEFINE_PRCC_CLK(2, i2c3,		0,  0, &clk_i2cclk);
-
-/* Peripheral Cluster #3 */
-static DEFINE_PRCC_CLK(3, gpio2,	8, -1, NULL);
-static DEFINE_PRCC_CLK(3, sdi5,		7,  7, &clk_sdmmcclk);
-static DEFINE_PRCC_CLK(3, uart2,	6,  6, &clk_uartclk);
-static DEFINE_PRCC_CLK(3, ske,		5,  5, &clk_32khz);
-static DEFINE_PRCC_CLK(3, sdi2,		4,  4, &clk_sdmmcclk);
-static DEFINE_PRCC_CLK(3, i2c0,		3,  3, &clk_i2cclk);
-static DEFINE_PRCC_CLK(3, ssp1,		2,  2, &clk_sspclk);
-static DEFINE_PRCC_CLK(3, ssp0,		1,  1, &clk_sspclk);
-static DEFINE_PRCC_CLK(3, fsmc,		0, -1, NULL);
-
-/* Peripheral Cluster #4 is in the always on domain */
-
-/* Peripheral Cluster #5 */
-static DEFINE_PRCC_CLK(5, gpio3,	1, -1, NULL);
-static DEFINE_PRCC_CLK(5, usb,		0,  0, NULL);
-
-/* Peripheral Cluster #6 */
-
-/* MTU ID in data */
-static DEFINE_PRCC_CLK_CUSTOM(6, mtu1, 9, -1, NULL, clk_mtu_get_rate, 1);
-static DEFINE_PRCC_CLK_CUSTOM(6, mtu0, 8, -1, NULL, clk_mtu_get_rate, 0);
-static DEFINE_PRCC_CLK(6, cfgreg,	7,  7, NULL);
-static DEFINE_PRCC_CLK(6, hash1,	6, -1, NULL);
-static DEFINE_PRCC_CLK(6, unipro,	5,  1, &clk_uniproclk);
-static DEFINE_PRCC_CLK(6, pka,		4, -1, NULL);
-static DEFINE_PRCC_CLK(6, hash0,	3, -1, NULL);
-static DEFINE_PRCC_CLK(6, cryp0,	2, -1, NULL);
-static DEFINE_PRCC_CLK(6, cryp1,    1, -1, NULL);
-static DEFINE_PRCC_CLK(6, rng,	0,  0, &clk_rngclk);
-
-static struct clk clk_dummy_apb_pclk = {
-	.name = "apb_pclk",
-};
-
-static struct clk_lookup u8500_clks[] = {
-	CLK(dummy_apb_pclk, NULL,	"apb_pclk"),
-
-	/* Peripheral Cluster #1 */
-	CLK(gpio0,	"gpio.0",	NULL),
-	CLK(gpio0,	"gpio.1",	NULL),
-	CLK(slimbus0,	"slimbus0",	NULL),
-	CLK(i2c2,	"nmk-i2c.2",	NULL),
-	CLK(sdi0,	"sdi0",		NULL),
-	CLK(msp0,	"ux500-msp-i2s.0",	NULL),
-	CLK(i2c1,	"nmk-i2c.1",	NULL),
-	CLK(uart1,	"uart1",	NULL),
-	CLK(uart0,	"uart0",	NULL),
-
-	/* Peripheral Cluster #3 */
-	CLK(gpio2,	"gpio.2",	NULL),
-	CLK(gpio2,	"gpio.3",	NULL),
-	CLK(gpio2,	"gpio.4",	NULL),
-	CLK(gpio2,	"gpio.5",	NULL),
-	CLK(sdi5,	"sdi5",		NULL),
-	CLK(uart2,	"uart2",	NULL),
-	CLK(ske,	"ske",		NULL),
-	CLK(ske,	"nmk-ske-keypad",	NULL),
-	CLK(sdi2,	"sdi2",		NULL),
-	CLK(i2c0,	"nmk-i2c.0",	NULL),
-	CLK(fsmc,	"fsmc",		NULL),
-
-	/* Peripheral Cluster #5 */
-	CLK(gpio3,	"gpio.8",	NULL),
-
-	/* Peripheral Cluster #6 */
-	CLK(hash1,	"hash1",	NULL),
-	CLK(pka,	"pka",		NULL),
-	CLK(hash0,	"hash0",	NULL),
-	CLK(cryp0,	"cryp0",	NULL),
-	CLK(cryp1,  "cryp1",    NULL),
-
-	/* PRCMU level clock gating */
-
-	/* Bank 0 */
-	CLK(svaclk,	"sva",		NULL),
-	CLK(siaclk,	"sia",		NULL),
-	CLK(sgaclk,	"sga",		NULL),
-	CLK(slimclk,	"slim",		NULL),
-	CLK(lcdclk,	"lcd",		NULL),
-	CLK(bmlclk,	"bml",		NULL),
-	CLK(hsitxclk,	"stm-hsi.0",	NULL),
-	CLK(hsirxclk,	"stm-hsi.1",	NULL),
-	CLK(hdmiclk,	"hdmi",		NULL),
-	CLK(apeatclk,	"apeat",	NULL),
-	CLK(apetraceclk,	"apetrace",	NULL),
-	CLK(mcdeclk,	"mcde",		NULL),
-	CLK(ipi2clk,	"ipi2",		NULL),
-	CLK(dmaclk,	"dma40.0",	NULL),
-	CLK(b2r2clk,	"b2r2",		NULL),
-	CLK(tvclk,	"tv",		NULL),
-
-	/* Peripheral Cluster #1 */
-	CLK(i2c4,	"nmk-i2c.4",	NULL),
-	CLK(spi3,	"spi3",		NULL),
-	CLK(msp1,	"ux500-msp-i2s.1",	NULL),
-	CLK(msp3,	"ux500-msp-i2s.3",	NULL),
-
-	/* Peripheral Cluster #2 */
-	CLK(gpio1,	"gpio.6",	NULL),
-	CLK(gpio1,	"gpio.7",	NULL),
-	CLK(ssitx,	"ssitx",	NULL),
-	CLK(ssirx,	"ssirx",	NULL),
-	CLK(spi0,	"spi0",		NULL),
-	CLK(sdi3,	"sdi3",		NULL),
-	CLK(sdi1,	"sdi1",		NULL),
-	CLK(msp2,	"ux500-msp-i2s.2",	NULL),
-	CLK(sdi4,	"sdi4",		NULL),
-	CLK(pwl,	"pwl",		NULL),
-	CLK(spi1,	"spi1",		NULL),
-	CLK(spi2,	"spi2",		NULL),
-	CLK(i2c3,	"nmk-i2c.3",	NULL),
-
-	/* Peripheral Cluster #3 */
-	CLK(ssp1,	"ssp1",		NULL),
-	CLK(ssp0,	"ssp0",		NULL),
-
-	/* Peripheral Cluster #5 */
-	CLK(usb,	"musb-ux500.0",	"usb"),
-
-	/* Peripheral Cluster #6 */
-	CLK(mtu1,	"mtu1",		NULL),
-	CLK(mtu0,	"mtu0",		NULL),
-	CLK(cfgreg,	"cfgreg",	NULL),
-	CLK(hash1,	"hash1",	NULL),
-	CLK(unipro,	"unipro",	NULL),
-	CLK(rng,	"rng",		NULL),
-
-	/* PRCMU level clock gating */
-
-	/* Bank 0 */
-	CLK(uniproclk,	"uniproclk",	NULL),
-	CLK(dsialtclk,	"dsialt",	NULL),
-
-	/* Bank 1 */
-	CLK(rngclk,	"rng",		NULL),
-	CLK(uiccclk,	"uicc",		NULL),
-};
-
-#ifdef CONFIG_DEBUG_FS
-/*
- *	debugfs support to trace clock tree hierarchy and attributes with
- *	powerdebug
- */
-static struct dentry *clk_debugfs_root;
-
-void __init clk_debugfs_add_table(struct clk_lookup *cl, size_t num)
-{
-	while (num--) {
-		/* Check that the clock has not been already registered */
-		if (!(cl->clk->list.prev != cl->clk->list.next))
-			list_add_tail(&cl->clk->list, &clk_list);
-
-		cl++;
-	}
-}
-
-static ssize_t usecount_dbg_read(struct file *file, char __user *buf,
-						  size_t size, loff_t *off)
-{
-	struct clk *clk = file->f_dentry->d_inode->i_private;
-	char cusecount[128];
-	unsigned int len;
-
-	len = sprintf(cusecount, "%u\n", clk->enabled);
-	return simple_read_from_buffer(buf, size, off, cusecount, len);
-}
-
-static ssize_t rate_dbg_read(struct file *file, char __user *buf,
-					  size_t size, loff_t *off)
-{
-	struct clk *clk = file->f_dentry->d_inode->i_private;
-	char crate[128];
-	unsigned int rate;
-	unsigned int len;
-
-	rate = clk_get_rate(clk);
-	len = sprintf(crate, "%u\n", rate);
-	return simple_read_from_buffer(buf, size, off, crate, len);
-}
-
-static const struct file_operations usecount_fops = {
-	.read = usecount_dbg_read,
-};
-
-static const struct file_operations set_rate_fops = {
-	.read = rate_dbg_read,
-};
-
-static struct dentry *clk_debugfs_register_dir(struct clk *c,
-						struct dentry *p_dentry)
-{
-	struct dentry *d, *clk_d;
-	const char *p = c->name;
-
-	if (!p)
-		p = "BUG";
-
-	clk_d = debugfs_create_dir(p, p_dentry);
-	if (!clk_d)
-		return NULL;
-
-	d = debugfs_create_file("usecount", S_IRUGO,
-				clk_d, c, &usecount_fops);
-	if (!d)
-		goto err_out;
-	d = debugfs_create_file("rate", S_IRUGO,
-				clk_d, c, &set_rate_fops);
-	if (!d)
-		goto err_out;
-	/*
-	 * TODO : not currently available in ux500
-	 * d = debugfs_create_x32("flags", S_IRUGO, clk_d, (u32 *)&c->flags);
-	 * if (!d)
-	 *	goto err_out;
-	 */
-
-	return clk_d;
-
-err_out:
-	debugfs_remove_recursive(clk_d);
-	return NULL;
-}
-
-static int clk_debugfs_register_one(struct clk *c)
-{
-	struct clk *pa = c->parent_periph;
-	struct clk *bpa = c->parent_cluster;
-
-	if (!(bpa && !pa)) {
-		c->dent = clk_debugfs_register_dir(c,
-				pa ? pa->dent : clk_debugfs_root);
-		if (!c->dent)
-			return -ENOMEM;
-	}
-
-	if (bpa) {
-		c->dent_bus = clk_debugfs_register_dir(c,
-				bpa->dent_bus ? bpa->dent_bus : bpa->dent);
-		if ((!c->dent_bus) &&  (c->dent)) {
-			debugfs_remove_recursive(c->dent);
-			c->dent = NULL;
-			return -ENOMEM;
-		}
-	}
-	return 0;
-}
-
-static int clk_debugfs_register(struct clk *c)
-{
-	int err;
-	struct clk *pa = c->parent_periph;
-	struct clk *bpa = c->parent_cluster;
-
-	if (pa && (!pa->dent && !pa->dent_bus)) {
-		err = clk_debugfs_register(pa);
-		if (err)
-			return err;
-	}
-
-	if (bpa && (!bpa->dent && !bpa->dent_bus)) {
-		err = clk_debugfs_register(bpa);
-		if (err)
-			return err;
-	}
-
-	if ((!c->dent) && (!c->dent_bus)) {
-		err = clk_debugfs_register_one(c);
-		if (err)
-			return err;
-	}
-	return 0;
-}
-
-int __init clk_debugfs_init(void)
-{
-	struct clk *c;
-	struct dentry *d;
-	int err;
-
-	d = debugfs_create_dir("clock", NULL);
-	if (!d)
-		return -ENOMEM;
-	clk_debugfs_root = d;
-
-	list_for_each_entry(c, &clk_list, list) {
-		err = clk_debugfs_register(c);
-		if (err)
-			goto err_out;
-	}
-	return 0;
-err_out:
-	debugfs_remove_recursive(clk_debugfs_root);
-	return err;
-}
-
-#endif /* defined(CONFIG_DEBUG_FS) */
-
-unsigned long clk_smp_twd_rate = 500000000;
-
-unsigned long clk_smp_twd_get_rate(struct clk *clk)
-{
-	return clk_smp_twd_rate;
-}
-
-static struct clk clk_smp_twd = {
-	.get_rate = clk_smp_twd_get_rate,
-	.name =  "smp_twd",
-};
-
-static struct clk_lookup clk_smp_twd_lookup = {
-	.dev_id = "smp_twd",
-	.clk = &clk_smp_twd,
-};
-
-#ifdef CONFIG_CPU_FREQ
-
-static int clk_twd_cpufreq_transition(struct notifier_block *nb,
-				      unsigned long state, void *data)
-{
-	struct cpufreq_freqs *f = data;
-
-	if (state == CPUFREQ_PRECHANGE) {
-		/* Save frequency in simple Hz */
-		clk_smp_twd_rate = (f->new * 1000) / 2;
-	}
-
-	return NOTIFY_OK;
-}
-
-static struct notifier_block clk_twd_cpufreq_nb = {
-	.notifier_call = clk_twd_cpufreq_transition,
-};
-
-int clk_init_smp_twd_cpufreq(void)
-{
-	return cpufreq_register_notifier(&clk_twd_cpufreq_nb,
-				  CPUFREQ_TRANSITION_NOTIFIER);
-}
-
-#endif
-
-int __init clk_init(void)
-{
-	clkdev_add_table(u8500_clks, ARRAY_SIZE(u8500_clks));
-	clkdev_add(&clk_smp_twd_lookup);
-
-#ifdef CONFIG_DEBUG_FS
-	clk_debugfs_add_table(u8500_clks, ARRAY_SIZE(u8500_clks));
-#endif
-	return 0;
-}
diff --git a/arch/arm/mach-ux500/clock.h b/arch/arm/mach-ux500/clock.h
deleted file mode 100644
index 65d27a1..0000000
--- a/arch/arm/mach-ux500/clock.h
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- *  Copyright (C) 2010 ST-Ericsson
- *  Copyright (C) 2009 STMicroelectronics
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-/**
- * struct clkops - ux500 clock operations
- * @enable:	function to enable the clock
- * @disable:	function to disable the clock
- * @get_rate:	function to get the current clock rate
- *
- * This structure contains function pointers to functions that will be used to
- * control the clock.  All of these functions are optional.  If get_rate is
- * NULL, the rate in the struct clk will be used.
- */
-struct clkops {
-	void (*enable) (struct clk *);
-	void (*disable) (struct clk *);
-	unsigned long (*get_rate) (struct clk *);
-	int (*set_parent)(struct clk *, struct clk *);
-};
-
-/**
- * struct clk - ux500 clock structure
- * @ops:		pointer to clkops struct used to control this clock
- * @name:		name, for debugging
- * @enabled:		refcount. positive if enabled, zero if disabled
- * @get_rate:		custom callback for getting the clock rate
- * @data:		custom per-clock data for example for the get_rate
- *			callback
- * @rate:		fixed rate for clocks which don't implement
- * 			ops->getrate
- * @prcmu_cg_off:	address offset of the combined enable/disable register
- * 			(used on u8500v1)
- * @prcmu_cg_bit:	bit in the combined enable/disable register (used on
- * 			u8500v1)
- * @prcmu_cg_mgt:	address of the enable/disable register (used on
- * 			u8500ed)
- * @cluster:		peripheral cluster number
- * @prcc_bus:		bit for the bus clock in the peripheral's CLKRST
- * @prcc_kernel:	bit for the kernel clock in the peripheral's CLKRST.
- * 			-1 if no kernel clock exists.
- * @parent_cluster:	pointer to parent's cluster clk struct
- * @parent_periph:	pointer to parent's peripheral clk struct
- *
- * Peripherals are organised into clusters, and each cluster has an associated
- * bus clock.  Some peripherals also have a parent peripheral clock.
- *
- * In order to enable a clock for a peripheral, we need to enable:
- * 	(1) the parent cluster (bus) clock at the PRCMU level
- * 	(2) the parent peripheral clock (if any) at the PRCMU level
- * 	(3) the peripheral's bus & kernel clock at the PRCC level
- *
- * (1) and (2) are handled by defining clk structs (DEFINE_PRCMU_CLK) for each
- * of the cluster and peripheral clocks, and hooking these as the parents of
- * the individual peripheral clocks.
- *
- * (3) is handled by specifying the bits in the PRCC control registers required
- * to enable these clocks and modifying them in the ->enable and
- * ->disable callbacks of the peripheral clocks (DEFINE_PRCC_CLK).
- *
- * This structure describes both the PRCMU-level clocks and PRCC-level clocks.
- * The prcmu_* fields are only used for the PRCMU clocks, and the cluster,
- * prcc, and parent pointers are only used for the PRCC-level clocks.
- */
-struct clk {
-	const struct clkops	*ops;
-	const char 		*name;
-	unsigned int		enabled;
-	unsigned long		(*get_rate)(struct clk *);
-	void			*data;
-
-	unsigned long		rate;
-	struct list_head	list;
-
-	/* These three are only for PRCMU clks */
-
-	unsigned int		prcmu_cg_off;
-	unsigned int		prcmu_cg_bit;
-	unsigned int		prcmu_cg_mgt;
-
-	/* The rest are only for PRCC clks */
-
-	int			cluster;
-	unsigned int		prcc_bus;
-	unsigned int		prcc_kernel;
-
-	struct clk		*parent_cluster;
-	struct clk		*parent_periph;
-#if defined(CONFIG_DEBUG_FS)
-	struct dentry		*dent;		/* For visible tree hierarchy */
-	struct dentry		*dent_bus;	/* For visible tree hierarchy */
-#endif
-};
-
-#define DEFINE_PRCMU_CLK(_name, _cg_off, _cg_bit, _reg)		\
-struct clk clk_##_name = {					\
-		.name		= #_name,			\
-		.ops    	= &clk_prcmu_ops, 		\
-		.prcmu_cg_off	= _cg_off, 			\
-		.prcmu_cg_bit	= _cg_bit,			\
-		.prcmu_cg_mgt	= PRCM_##_reg##_MGT		\
-	}
-
-#define DEFINE_PRCMU_CLK_RATE(_name, _cg_off, _cg_bit, _reg, _rate)	\
-struct clk clk_##_name = {						\
-		.name		= #_name,				\
-		.ops    	= &clk_prcmu_ops, 			\
-		.prcmu_cg_off	= _cg_off, 				\
-		.prcmu_cg_bit	= _cg_bit,				\
-		.rate		= _rate,				\
-		.prcmu_cg_mgt	= PRCM_##_reg##_MGT			\
-	}
-
-#define DEFINE_PRCC_CLK(_pclust, _name, _bus_en, _kernel_en, _kernclk)	\
-struct clk clk_##_name = {						\
-		.name		= #_name,				\
-		.ops    	= &clk_prcc_ops, 			\
-		.cluster 	= _pclust,				\
-		.prcc_bus 	= _bus_en, 				\
-		.prcc_kernel 	= _kernel_en, 				\
-		.parent_cluster = &clk_per##_pclust##clk,		\
-		.parent_periph 	= _kernclk				\
-	}
-
-#define DEFINE_PRCC_CLK_CUSTOM(_pclust, _name, _bus_en, _kernel_en, _kernclk, _callback, _data) \
-struct clk clk_##_name = {						\
-		.name		= #_name,				\
-		.ops		= &clk_prcc_ops,			\
-		.cluster	= _pclust,				\
-		.prcc_bus	= _bus_en,				\
-		.prcc_kernel	= _kernel_en,				\
-		.parent_cluster = &clk_per##_pclust##clk,		\
-		.parent_periph	= _kernclk,				\
-		.get_rate	= _callback,				\
-		.data		= (void *) _data			\
-	}
-
-
-#define CLK(_clk, _devname, _conname)			\
-	{						\
-		.clk	= &clk_##_clk,			\
-		.dev_id	= _devname,			\
-		.con_id = _conname,			\
-	}
-
-int __init clk_db8500_ed_fixup(void);
-int __init clk_init(void);
-
-#ifdef CONFIG_DEBUG_FS
-int clk_debugfs_init(void);
-#else
-static inline int clk_debugfs_init(void) { return 0; }
-#endif
-
-#ifdef CONFIG_CPU_FREQ
-int clk_init_smp_twd_cpufreq(void);
-#else
-static inline int clk_init_smp_twd_cpufreq(void) { return 0; }
-#endif
diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c
index db3c52d..bcdfe6b 100644
--- a/arch/arm/mach-ux500/cpu-db8500.c
+++ b/arch/arm/mach-ux500/cpu-db8500.c
@@ -18,13 +18,13 @@
 #include <linux/io.h>
 #include <linux/mfd/abx500/ab8500.h>
 
-#include <asm/mach/map.h>
 #include <asm/pmu.h>
+#include <asm/mach/map.h>
 #include <plat/gpio-nomadik.h>
 #include <mach/hardware.h>
 #include <mach/setup.h>
 #include <mach/devices.h>
-#include <mach/usb.h>
+#include <linux/platform_data/usb-musb-ux500.h>
 #include <mach/db8500-regs.h>
 
 #include "devices-db8500.h"
@@ -80,7 +80,7 @@ void __init u8500_map_io(void)
 
 	iotable_init(u8500_common_io_desc, ARRAY_SIZE(u8500_common_io_desc));
 
-	if (cpu_is_u9540())
+	if (cpu_is_ux540_family())
 		iotable_init(u9540_io_desc, ARRAY_SIZE(u9540_io_desc));
 	else
 		iotable_init(u8500_io_desc, ARRAY_SIZE(u8500_io_desc));
@@ -122,7 +122,7 @@ struct arm_pmu_platdata db8500_pmu_platdata = {
 
 static struct platform_device db8500_pmu_device = {
 	.name			= "arm-pmu",
-	.id			= ARM_PMU_DEVICE_CPU,
+	.id			= -1,
 	.num_resources		= ARRAY_SIZE(db8500_pmu_resources),
 	.resource		= db8500_pmu_resources,
 	.dev.platform_data	= &db8500_pmu_platdata,
@@ -138,10 +138,6 @@ static struct platform_device *platform_devs[] __initdata = {
 	&db8500_prcmu_device,
 };
 
-static struct platform_device *of_platform_devs[] __initdata = {
-	&u8500_dma40_device,
-};
-
 static resource_size_t __initdata db8500_gpio_base[] = {
 	U8500_GPIOBANK0_BASE,
 	U8500_GPIOBANK1_BASE,
@@ -235,7 +231,6 @@ struct device * __init u8500_init_devices(struct ab8500_platform_data *ab8500)
 struct device * __init u8500_of_init_devices(void)
 {
 	struct device *parent;
-	int i;
 
 	parent = db8500_soc_device_init();
 
@@ -244,8 +239,7 @@ struct device * __init u8500_of_init_devices(void)
 	platform_device_register_data(parent,
 		"cpufreq-u8500", -1, NULL, 0);
 
-	for (i = 0; i < ARRAY_SIZE(of_platform_devs); i++)
-		of_platform_devs[i]->dev.parent = parent;
+	u8500_dma40_device.dev.parent = parent;
 
 	/*
 	 * Devices to be DT:ed:
@@ -253,7 +247,7 @@ struct device * __init u8500_of_init_devices(void)
 	 *   db8500_pmu_device   = done
 	 *   db8500_prcmu_device = done
 	 */
-	platform_add_devices(of_platform_devs, ARRAY_SIZE(of_platform_devs));
+	platform_device_register(&u8500_dma40_device);
 
 	return parent;
 }
diff --git a/arch/arm/mach-ux500/cpu.c b/arch/arm/mach-ux500/cpu.c
index e2360e7..2236cbd 100644
--- a/arch/arm/mach-ux500/cpu.c
+++ b/arch/arm/mach-ux500/cpu.c
@@ -8,7 +8,6 @@
 
 #include <linux/platform_device.h>
 #include <linux/io.h>
-#include <linux/clk.h>
 #include <linux/mfd/db8500-prcmu.h>
 #include <linux/clksrc-dbx500-prcmu.h>
 #include <linux/sys_soc.h>
@@ -17,6 +16,7 @@
 #include <linux/stat.h>
 #include <linux/of.h>
 #include <linux/of_irq.h>
+#include <linux/platform_data/clk-ux500.h>
 
 #include <asm/hardware/gic.h>
 #include <asm/mach/map.h>
@@ -25,8 +25,6 @@
 #include <mach/setup.h>
 #include <mach/devices.h>
 
-#include "clock.h"
-
 void __iomem *_PRCMU_BASE;
 
 /*
@@ -51,7 +49,9 @@ void __init ux500_init_irq(void)
 	void __iomem *dist_base;
 	void __iomem *cpu_base;
 
-	if (cpu_is_u8500_family()) {
+	gic_arch_extn.flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND;
+
+	if (cpu_is_u8500_family() || cpu_is_ux540_family()) {
 		dist_base = __io_address(U8500_GIC_DIST_BASE);
 		cpu_base = __io_address(U8500_GIC_CPU_BASE);
 	} else
@@ -70,13 +70,17 @@ void __init ux500_init_irq(void)
 	 */
 	if (cpu_is_u8500_family())
 		db8500_prcmu_early_init();
-	clk_init();
+
+	if (cpu_is_u8500_family())
+		u8500_clk_init();
+	else if (cpu_is_u9540())
+		u9540_clk_init();
+	else if (cpu_is_u8540())
+		u8540_clk_init();
 }
 
 void __init ux500_init_late(void)
 {
-	clk_debugfs_init();
-	clk_init_smp_twd_cpufreq();
 }
 
 static const char * __init ux500_get_machine(void)
diff --git a/arch/arm/mach-ux500/devices-common.h b/arch/arm/mach-ux500/devices-common.h
index ecdd838..7fbf0ba 100644
--- a/arch/arm/mach-ux500/devices-common.h
+++ b/arch/arm/mach-ux500/devices-common.h
@@ -13,7 +13,7 @@
 #include <linux/sys_soc.h>
 #include <linux/amba/bus.h>
 #include <linux/platform_data/i2c-nomadik.h>
-#include <mach/crypto-ux500.h>
+#include <linux/platform_data/crypto-ux500.h>
 
 struct spi_master_cntlr;
 
diff --git a/arch/arm/mach-ux500/hotplug.c b/arch/arm/mach-ux500/hotplug.c
index c76f0f4..2f6af25 100644
--- a/arch/arm/mach-ux500/hotplug.c
+++ b/arch/arm/mach-ux500/hotplug.c
@@ -15,13 +15,18 @@
 #include <asm/cacheflush.h>
 #include <asm/smp_plat.h>
 
-extern volatile int pen_release;
+#include <mach/setup.h>
 
-static inline void platform_do_lowpower(unsigned int cpu)
+/*
+ * platform-specific code to shutdown a CPU
+ *
+ * Called with IRQs disabled
+ */
+void __ref ux500_cpu_die(unsigned int cpu)
 {
 	flush_cache_all();
 
-	/* we put the platform to just WFI */
+	/* directly enter low power state, skipping secure registers */
 	for (;;) {
 		__asm__ __volatile__("dsb\n\t" "wfi\n\t"
 				: : : "memory");
@@ -33,28 +38,3 @@ static inline void platform_do_lowpower(unsigned int cpu)
 		}
 	}
 }
-
-int platform_cpu_kill(unsigned int cpu)
-{
-	return 1;
-}
-
-/*
- * platform-specific code to shutdown a CPU
- *
- * Called with IRQs disabled
- */
-void platform_cpu_die(unsigned int cpu)
-{
-	/* directly enter low power state, skipping secure registers */
-	platform_do_lowpower(cpu);
-}
-
-int platform_cpu_disable(unsigned int cpu)
-{
-	/*
-	 * we don't allow CPU 0 to be shutdown (it is still too special
-	 * e.g. clock tick interrupts)
-	 */
-	return cpu == 0 ? -EPERM : 0;
-}
diff --git a/arch/arm/mach-ux500/include/mach/crypto-ux500.h b/arch/arm/mach-ux500/include/mach/crypto-ux500.h
deleted file mode 100644
index 5b2d081..0000000
--- a/arch/arm/mach-ux500/include/mach/crypto-ux500.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson SA 2011
- *
- * Author: Joakim Bech <joakim.xx.bech@stericsson.com> for ST-Ericsson
- * License terms: GNU General Public License (GPL) version 2
- */
-#ifndef _CRYPTO_UX500_H
-#define _CRYPTO_UX500_H
-#include <linux/dmaengine.h>
-#include <plat/ste_dma40.h>
-
-struct hash_platform_data {
-	void *mem_to_engine;
-	bool (*dma_filter)(struct dma_chan *chan, void *filter_param);
-};
-
-struct cryp_platform_data {
-	struct stedma40_chan_cfg mem_to_engine;
-	struct stedma40_chan_cfg engine_to_mem;
-};
-
-#endif
diff --git a/arch/arm/mach-ux500/include/mach/gpio.h b/arch/arm/mach-ux500/include/mach/gpio.h
deleted file mode 100644
index c01ef66..0000000
--- a/arch/arm/mach-ux500/include/mach/gpio.h
+++ /dev/null
@@ -1,5 +0,0 @@
-#ifndef __ASM_ARCH_GPIO_H
-#define __ASM_ARCH_GPIO_H
-
-
-#endif /* __ASM_ARCH_GPIO_H */
diff --git a/arch/arm/mach-ux500/include/mach/id.h b/arch/arm/mach-ux500/include/mach/id.h
index c6e2db9..9c42642 100644
--- a/arch/arm/mach-ux500/include/mach/id.h
+++ b/arch/arm/mach-ux500/include/mach/id.h
@@ -41,43 +41,29 @@ static inline bool __attribute_const__ cpu_is_u8500(void)
 	return dbx500_partnumber() == 0x8500;
 }
 
-static inline bool __attribute_const__ cpu_is_u9540(void)
+static inline bool __attribute_const__ cpu_is_u8520(void)
 {
-	return dbx500_partnumber() == 0x9540;
+	return dbx500_partnumber() == 0x8520;
 }
 
 static inline bool cpu_is_u8500_family(void)
 {
-	return cpu_is_u8500() || cpu_is_u9540();
-}
-
-static inline bool __attribute_const__ cpu_is_u5500(void)
-{
-	return dbx500_partnumber() == 0x5500;
-}
-
-/*
- * 5500 revisions
- */
-
-static inline bool __attribute_const__ cpu_is_u5500v1(void)
-{
-	return cpu_is_u5500() && (dbx500_revision() & 0xf0) == 0xA0;
+	return cpu_is_u8500() || cpu_is_u8520();
 }
 
-static inline bool __attribute_const__ cpu_is_u5500v2(void)
+static inline bool __attribute_const__ cpu_is_u9540(void)
 {
-	return (dbx500_id.revision & 0xf0) == 0xB0;
+	return dbx500_partnumber() == 0x9540;
 }
 
-static inline bool __attribute_const__ cpu_is_u5500v20(void)
+static inline bool __attribute_const__ cpu_is_u8540(void)
 {
-	return cpu_is_u5500() && ((dbx500_revision() & 0xf0) == 0xB0);
+	return dbx500_partnumber() == 0x8540;
 }
 
-static inline bool __attribute_const__ cpu_is_u5500v21(void)
+static inline bool cpu_is_ux540_family(void)
 {
-	return cpu_is_u5500() && (dbx500_revision() == 0xB1);
+	return cpu_is_u9540() || cpu_is_u8540();
 }
 
 /*
@@ -119,14 +105,14 @@ static inline bool cpu_is_u8500v21(void)
 	return cpu_is_u8500() && (dbx500_revision() == 0xB1);
 }
 
+static inline bool cpu_is_u8500v22(void)
+{
+	return cpu_is_u8500() && (dbx500_revision() == 0xB2);
+}
+
 static inline bool cpu_is_u8500v20_or_later(void)
 {
-	/*
-	 * U9540 has so much in common with U8500 that is is considered a
-	 * U8500 variant.
-	 */
-	return cpu_is_u9540() ||
-		(cpu_is_u8500() && !cpu_is_u8500v10() && !cpu_is_u8500v11());
+	return (cpu_is_u8500() && !cpu_is_u8500v10() && !cpu_is_u8500v11());
 }
 
 static inline bool ux500_is_svp(void)
diff --git a/arch/arm/mach-ux500/include/mach/msp.h b/arch/arm/mach-ux500/include/mach/msp.h
index 798be19..3cc7142 100644
--- a/arch/arm/mach-ux500/include/mach/msp.h
+++ b/arch/arm/mach-ux500/include/mach/msp.h
@@ -22,8 +22,6 @@ struct msp_i2s_platform_data {
 	enum msp_i2s_id id;
 	struct stedma40_chan_cfg *msp_i2s_dma_rx;
 	struct stedma40_chan_cfg *msp_i2s_dma_tx;
-	int (*msp_i2s_init) (void);
-	int (*msp_i2s_exit) (void);
 };
 
 #endif
diff --git a/arch/arm/mach-ux500/include/mach/setup.h b/arch/arm/mach-ux500/include/mach/setup.h
index 7914e5e..6be4c4d 100644
--- a/arch/arm/mach-ux500/include/mach/setup.h
+++ b/arch/arm/mach-ux500/include/mach/setup.h
@@ -45,4 +45,7 @@ extern struct sys_timer ux500_timer;
 	.type		= MT_MEMORY,		\
 }
 
+extern struct smp_operations ux500_smp_ops;
+extern void ux500_cpu_die(unsigned int cpu);
+
 #endif /*  __ASM_ARCH_SETUP_H */
diff --git a/arch/arm/mach-ux500/include/mach/usb.h b/arch/arm/mach-ux500/include/mach/usb.h
deleted file mode 100644
index 4c1cc50..0000000
--- a/arch/arm/mach-ux500/include/mach/usb.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson SA 2011
- *
- * Author: Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com>
- * License terms: GNU General Public License (GPL) version 2
- */
-#ifndef __ASM_ARCH_USB_H
-#define __ASM_ARCH_USB_H
-
-#include <linux/dmaengine.h>
-
-#define UX500_MUSB_DMA_NUM_RX_CHANNELS 8
-#define UX500_MUSB_DMA_NUM_TX_CHANNELS 8
-
-struct ux500_musb_board_data {
-	void	**dma_rx_param_array;
-	void	**dma_tx_param_array;
-	u32	num_rx_channels;
-	u32	num_tx_channels;
-	bool (*dma_filter)(struct dma_chan *chan, void *filter_param);
-};
-
-void ux500_add_usb(struct device *parent, resource_size_t base,
-		   int irq, int *dma_rx_cfg, int *dma_tx_cfg);
-#endif
diff --git a/arch/arm/mach-ux500/platsmp.c b/arch/arm/mach-ux500/platsmp.c
index da1d5ad..3db7782 100644
--- a/arch/arm/mach-ux500/platsmp.c
+++ b/arch/arm/mach-ux500/platsmp.c
@@ -28,12 +28,6 @@
 extern void u8500_secondary_startup(void);
 
 /*
- * control for which core is the next to come out of the secondary
- * boot "holding pen"
- */
-volatile int pen_release = -1;
-
-/*
  * Write pen_release in a way that is guaranteed to be visible to all
  * observers, irrespective of whether they're taking part in coherency
  * or not.  This is necessary for the hotplug code to work reliably.
@@ -48,7 +42,7 @@ static void write_pen_release(int val)
 
 static void __iomem *scu_base_addr(void)
 {
-	if (cpu_is_u8500_family())
+	if (cpu_is_u8500_family() || cpu_is_ux540_family())
 		return __io_address(U8500_SCU_BASE);
 	else
 		ux500_unknown_soc();
@@ -58,7 +52,7 @@ static void __iomem *scu_base_addr(void)
 
 static DEFINE_SPINLOCK(boot_lock);
 
-void __cpuinit platform_secondary_init(unsigned int cpu)
+static void __cpuinit ux500_secondary_init(unsigned int cpu)
 {
 	/*
 	 * if any interrupts are already enabled for the primary
@@ -80,7 +74,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
 	spin_unlock(&boot_lock);
 }
 
-int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
+static int __cpuinit ux500_boot_secondary(unsigned int cpu, struct task_struct *idle)
 {
 	unsigned long timeout;
 
@@ -118,7 +112,7 @@ static void __init wakeup_secondary(void)
 {
 	void __iomem *backupram;
 
-	if (cpu_is_u8500_family())
+	if (cpu_is_u8500_family() || cpu_is_ux540_family())
 		backupram = __io_address(U8500_BACKUPRAM0_BASE);
 	else
 		ux500_unknown_soc();
@@ -145,7 +139,7 @@ static void __init wakeup_secondary(void)
  * Initialise the CPU possible map early - this describes the CPUs
  * which may be present or become present in the system.
  */
-void __init smp_init_cpus(void)
+static void __init ux500_smp_init_cpus(void)
 {
 	void __iomem *scu_base = scu_base_addr();
 	unsigned int i, ncores;
@@ -165,9 +159,19 @@ void __init smp_init_cpus(void)
 	set_smp_cross_call(gic_raise_softirq);
 }
 
-void __init platform_smp_prepare_cpus(unsigned int max_cpus)
+static void __init ux500_smp_prepare_cpus(unsigned int max_cpus)
 {
 
 	scu_enable(scu_base_addr());
 	wakeup_secondary();
 }
+
+struct smp_operations ux500_smp_ops __initdata = {
+	.smp_init_cpus		= ux500_smp_init_cpus,
+	.smp_prepare_cpus	= ux500_smp_prepare_cpus,
+	.smp_secondary_init	= ux500_secondary_init,
+	.smp_boot_secondary	= ux500_boot_secondary,
+#ifdef CONFIG_HOTPLUG_CPU
+	.cpu_die		= ux500_cpu_die,
+#endif
+};
diff --git a/arch/arm/mach-ux500/timer.c b/arch/arm/mach-ux500/timer.c
index 66e7f00..6f39731 100644
--- a/arch/arm/mach-ux500/timer.c
+++ b/arch/arm/mach-ux500/timer.c
@@ -54,7 +54,7 @@ static void __init ux500_timer_init(void)
 	void __iomem *tmp_base;
 	struct device_node *np;
 
-	if (cpu_is_u8500_family()) {
+	if (cpu_is_u8500_family() || cpu_is_ux540_family()) {
 		mtu_timer_base = __io_address(U8500_MTU0_BASE);
 		prcmu_timer_base = __io_address(U8500_PRCMU_TIMER_4_BASE);
 	} else {
diff --git a/arch/arm/mach-ux500/usb.c b/arch/arm/mach-ux500/usb.c
index a74af38..145482e 100644
--- a/arch/arm/mach-ux500/usb.c
+++ b/arch/arm/mach-ux500/usb.c
@@ -10,7 +10,7 @@
 
 #include <plat/ste_dma40.h>
 #include <mach/hardware.h>
-#include <mach/usb.h>
+#include <linux/platform_data/usb-musb-ux500.h>
 
 #define MUSB_DMA40_RX_CH { \
 		.mode = STEDMA40_MODE_LOGICAL, \
diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c
index cd8ea35..5b5c1ee 100644
--- a/arch/arm/mach-versatile/core.c
+++ b/arch/arm/mach-versatile/core.c
@@ -37,7 +37,6 @@
 #include <linux/mtd/physmap.h>
 
 #include <asm/irq.h>
-#include <asm/leds.h>
 #include <asm/hardware/arm_timer.h>
 #include <asm/hardware/icst.h>
 #include <asm/hardware/vic.h>
@@ -169,11 +168,6 @@ static struct map_desc versatile_io_desc[] __initdata = {
 		.pfn		= __phys_to_pfn(VERSATILE_PCI_CFG_BASE),
 		.length		= VERSATILE_PCI_CFG_BASE_SIZE,
 		.type		= MT_DEVICE
-	}, {
-		.virtual	=  (unsigned long)VERSATILE_PCI_VIRT_MEM_BASE0,
-		.pfn		= __phys_to_pfn(VERSATILE_PCI_MEM_BASE0),
-		.length		= IO_SPACE_LIMIT,
-		.type		= MT_DEVICE
 	},
 #endif
 };
@@ -763,10 +757,6 @@ void __init versatile_init(void)
 		struct amba_device *d = amba_devs[i];
 		amba_device_register(d, &iomem_resource);
 	}
-
-#ifdef CONFIG_LEDS
-	leds_event = versatile_leds_event;
-#endif
 }
 
 /*
diff --git a/arch/arm/mach-versatile/include/mach/gpio.h b/arch/arm/mach-versatile/include/mach/gpio.h
deleted file mode 100644
index 40a8c17..0000000
--- a/arch/arm/mach-versatile/include/mach/gpio.h
+++ /dev/null
@@ -1 +0,0 @@
-/* empty */
diff --git a/arch/arm/mach-versatile/include/mach/hardware.h b/arch/arm/mach-versatile/include/mach/hardware.h
index 408e58d..3e5d425 100644
--- a/arch/arm/mach-versatile/include/mach/hardware.h
+++ b/arch/arm/mach-versatile/include/mach/hardware.h
@@ -29,7 +29,6 @@
  */
 #define VERSATILE_PCI_VIRT_BASE		(void __iomem *)0xe8000000ul
 #define VERSATILE_PCI_CFG_VIRT_BASE	(void __iomem *)0xe9000000ul
-#define VERSATILE_PCI_VIRT_MEM_BASE0	(void __iomem *)PCIO_BASE
 
 /* macro to get at MMIO space when running virtually */
 #define IO_ADDRESS(x)		(((x) & 0x0fffffff) + (((x) >> 4) & 0x0f000000) + 0xf0000000)
diff --git a/arch/arm/mach-versatile/include/mach/io.h b/arch/arm/mach-versatile/include/mach/io.h
deleted file mode 100644
index 0406513..0000000
--- a/arch/arm/mach-versatile/include/mach/io.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- *  arch/arm/mach-versatile/include/mach/io.h
- *
- *  Copyright (C) 2003 ARM Limited
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#ifndef __ASM_ARM_ARCH_IO_H
-#define __ASM_ARM_ARCH_IO_H
-
-#define PCIO_BASE	0xeb000000ul
-
-#define __io(a)		((a) + PCIO_BASE)
-
-#endif
diff --git a/arch/arm/mach-versatile/pci.c b/arch/arm/mach-versatile/pci.c
index e95bf84..2f84f40 100644
--- a/arch/arm/mach-versatile/pci.c
+++ b/arch/arm/mach-versatile/pci.c
@@ -169,13 +169,6 @@ static struct pci_ops pci_versatile_ops = {
 	.write	= versatile_write_config,
 };
 
-static struct resource io_port = {
-	.name	= "PCI",
-	.start	= 0,
-	.end	= IO_SPACE_LIMIT,
-	.flags	= IORESOURCE_IO,
-};
-
 static struct resource io_mem = {
 	.name	= "PCI I/O space",
 	.start	= VERSATILE_PCI_MEM_BASE0,
@@ -207,12 +200,6 @@ static int __init pci_versatile_setup_resources(struct pci_sys_data *sys)
 		       "memory region (%d)\n", ret);
 		goto out;
 	}
-	ret = request_resource(&ioport_resource, &io_port);
-	if (ret) {
-		printk(KERN_ERR "PCI: unable to allocate I/O "
-		       "port region (%d)\n", ret);
-		goto out;
-	}
 	ret = request_resource(&iomem_resource, &non_mem);
 	if (ret) {
 		printk(KERN_ERR "PCI: unable to allocate non-prefetchable "
@@ -227,11 +214,9 @@ static int __init pci_versatile_setup_resources(struct pci_sys_data *sys)
 	}
 
 	/*
-	 * the IO resource for this bus
 	 * the mem resource for this bus
 	 * the prefetch mem resource for this bus
 	 */
-	pci_add_resource_offset(&sys->resources, &io_port, sys->io_offset);
 	pci_add_resource_offset(&sys->resources, &non_mem, sys->mem_offset);
 	pci_add_resource_offset(&sys->resources, &pre_mem, sys->mem_offset);
 
@@ -260,9 +245,11 @@ int __init pci_versatile_setup(int nr, struct pci_sys_data *sys)
 		goto out;
 	}
 
+	ret = pci_ioremap_io(0, VERSATILE_PCI_MEM_BASE0);
+	if (ret)
+		goto out;
+
 	if (nr == 0) {
-		sys->mem_offset = 0;
-		sys->io_offset = 0;
 		ret = pci_versatile_setup_resources(sys);
 		if (ret < 0) {
 			printk("pci_versatile_setup: resources... oops?\n");
@@ -319,7 +306,6 @@ int __init pci_versatile_setup(int nr, struct pci_sys_data *sys)
 
 void __init pci_versatile_preinit(void)
 {
-	pcibios_min_io = 0x44000000;
 	pcibios_min_mem = 0x50000000;
 
 	__raw_writel(VERSATILE_PCI_MEM_BASE0 >> 28, PCI_IMAP0);
diff --git a/arch/arm/mach-vexpress/Kconfig b/arch/arm/mach-vexpress/Kconfig
index fc3730f..c952960 100644
--- a/arch/arm/mach-vexpress/Kconfig
+++ b/arch/arm/mach-vexpress/Kconfig
@@ -1,38 +1,23 @@
-menu "Versatile Express platform type"
-	depends on ARCH_VEXPRESS
-
-config ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA
-	bool "Enable A5 and A9 only errata work-arounds"
-	default y
-	select ARM_ERRATA_720789
-	select ARM_ERRATA_751472
-	select PL310_ERRATA_753970 if CACHE_PL310
-	help
-	  Provides common dependencies for Versatile Express platforms
-	  based on Cortex-A5 and Cortex-A9 processors. In order to
-	  build a working kernel, you must also enable relevant core
-	  tile support or Flattened Device Tree based support options.
-
-config ARCH_VEXPRESS_CA9X4
-	bool "Versatile Express Cortex-A9x4 tile"
-	select ARM_GIC
-	select CPU_V7
-	select HAVE_SMP
-	select MIGHT_HAVE_CACHE_L2X0
-
-config ARCH_VEXPRESS_DT
-	bool "Device Tree support for Versatile Express platforms"
+config ARCH_VEXPRESS
+	bool "ARM Ltd. Versatile Express family" if ARCH_MULTI_V7
+	select ARCH_WANT_OPTIONAL_GPIOLIB
+	select ARM_AMBA
 	select ARM_GIC
-	select ARM_PATCH_PHYS_VIRT
-	select AUTO_ZRELADDR
+	select ARM_TIMER_SP804
+	select CLKDEV_LOOKUP
+	select COMMON_CLK
 	select CPU_V7
+	select GENERIC_CLOCKEVENTS
+	select HAVE_CLK
+	select HAVE_PATA_PLATFORM
 	select HAVE_SMP
+	select ICST
 	select MIGHT_HAVE_CACHE_L2X0
-	select USE_OF
+	select NO_IOPORT
+	select PLAT_VERSATILE
+	select PLAT_VERSATILE_CLCD
+	select REGULATOR_FIXED_VOLTAGE if REGULATOR
 	help
-	  New Versatile Express platforms require Flattened Device Tree to
-	  be passed to the kernel.
-
 	  This option enables support for systems using Cortex processor based
 	  ARM core and logic (FPGA) tiles on the Versatile Express motherboard,
 	  for example:
@@ -48,7 +33,22 @@ config ARCH_VEXPRESS_DT
 	  platforms. The traditional (ATAGs) boot method is not usable on
 	  these boards with this option.
 
-	  If your bootloader supports Flattened Device Tree based booting,
-	  say Y here.
+menu "Versatile Express platform type"
+	depends on ARCH_VEXPRESS
+
+config ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA
+	bool "Enable A5 and A9 only errata work-arounds"
+	default y
+	select ARM_ERRATA_720789
+	select ARM_ERRATA_751472
+	select PL310_ERRATA_753970 if CACHE_PL310
+	help
+	  Provides common dependencies for Versatile Express platforms
+	  based on Cortex-A5 and Cortex-A9 processors. In order to
+	  build a working kernel, you must also enable relevant core
+	  tile support or Flattened Device Tree based support options.
+
+config ARCH_VEXPRESS_CA9X4
+	bool "Versatile Express Cortex-A9x4 tile"
 
 endmenu
diff --git a/arch/arm/mach-vexpress/Makefile b/arch/arm/mach-vexpress/Makefile
index 90551b9..42703e8 100644
--- a/arch/arm/mach-vexpress/Makefile
+++ b/arch/arm/mach-vexpress/Makefile
@@ -1,6 +1,8 @@
 #
 # Makefile for the linux kernel.
 #
+ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include \
+	-I$(srctree)/arch/arm/plat-versatile/include
 
 obj-y					:= v2m.o
 obj-$(CONFIG_ARCH_VEXPRESS_CA9X4)	+= ct-ca9x4.o
diff --git a/arch/arm/mach-vexpress/Makefile.boot b/arch/arm/mach-vexpress/Makefile.boot
deleted file mode 100644
index 318d308..0000000
--- a/arch/arm/mach-vexpress/Makefile.boot
+++ /dev/null
@@ -1,10 +0,0 @@
-# Those numbers are used only by the non-DT V2P-CA9 platform
-# The DT-enabled ones require CONFIG_AUTO_ZRELADDR=y
-   zreladdr-y	+= 0x60008000
-params_phys-y	:= 0x60000100
-initrd_phys-y	:= 0x60800000
-
-dtb-$(CONFIG_ARCH_VEXPRESS_DT)	+= vexpress-v2p-ca5s.dtb \
-				   vexpress-v2p-ca9.dtb \
-				   vexpress-v2p-ca15-tc1.dtb \
-				   vexpress-v2p-ca15_a7.dtb
diff --git a/arch/arm/mach-vexpress/core.h b/arch/arm/mach-vexpress/core.h
index a3a4980..f134cd4 100644
--- a/arch/arm/mach-vexpress/core.h
+++ b/arch/arm/mach-vexpress/core.h
@@ -5,3 +5,7 @@
 #define V2T_PERIPH 0xf8200000
 
 void vexpress_dt_smp_map_io(void);
+
+extern struct smp_operations	vexpress_smp_ops;
+
+extern void vexpress_cpu_die(unsigned int cpu);
diff --git a/arch/arm/mach-vexpress/ct-ca9x4.c b/arch/arm/mach-vexpress/ct-ca9x4.c
index 61c4924..4f471fa 100644
--- a/arch/arm/mach-vexpress/ct-ca9x4.c
+++ b/arch/arm/mach-vexpress/ct-ca9x4.c
@@ -13,7 +13,6 @@
 #include <asm/hardware/arm_timer.h>
 #include <asm/hardware/cache-l2x0.h>
 #include <asm/hardware/gic.h>
-#include <asm/pmu.h>
 #include <asm/smp_scu.h>
 #include <asm/smp_twd.h>
 
@@ -27,6 +26,7 @@
 #include "core.h"
 
 #include <mach/motherboard.h>
+#include <mach/irqs.h>
 
 #include <plat/clcd.h>
 
@@ -144,7 +144,7 @@ static struct resource pmu_resources[] = {
 
 static struct platform_device pmu_device = {
 	.name		= "arm-pmu",
-	.id		= ARM_PMU_DEVICE_CPU,
+	.id		= -1,
 	.num_resources	= ARRAY_SIZE(pmu_resources),
 	.resource	= pmu_resources,
 };
diff --git a/arch/arm/mach-vexpress/hotplug.c b/arch/arm/mach-vexpress/hotplug.c
index c504a72..a141b98 100644
--- a/arch/arm/mach-vexpress/hotplug.c
+++ b/arch/arm/mach-vexpress/hotplug.c
@@ -16,8 +16,6 @@
 #include <asm/smp_plat.h>
 #include <asm/cp15.h>
 
-extern volatile int pen_release;
-
 static inline void cpu_enter_lowpower(void)
 {
 	unsigned int v;
@@ -84,17 +82,12 @@ static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
 	}
 }
 
-int platform_cpu_kill(unsigned int cpu)
-{
-	return 1;
-}
-
 /*
  * platform-specific code to shutdown a CPU
  *
  * Called with IRQs disabled
  */
-void platform_cpu_die(unsigned int cpu)
+void __ref vexpress_cpu_die(unsigned int cpu)
 {
 	int spurious = 0;
 
@@ -113,12 +106,3 @@ void platform_cpu_die(unsigned int cpu)
 	if (spurious)
 		pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
 }
-
-int platform_cpu_disable(unsigned int cpu)
-{
-	/*
-	 * we don't allow CPU 0 to be shutdown (it is still too special
-	 * e.g. clock tick interrupts)
-	 */
-	return cpu == 0 ? -EPERM : 0;
-}
diff --git a/arch/arm/mach-vexpress/include/mach/debug-macro.S b/arch/arm/mach-vexpress/include/mach/debug-macro.S
deleted file mode 100644
index 9f509f5..0000000
--- a/arch/arm/mach-vexpress/include/mach/debug-macro.S
+++ /dev/null
@@ -1,84 +0,0 @@
-/* arch/arm/mach-realview/include/mach/debug-macro.S
- *
- * Debugging macro include header
- *
- *  Copyright (C) 1994-1999 Russell King
- *  Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#define DEBUG_LL_PHYS_BASE		0x10000000
-#define DEBUG_LL_UART_OFFSET		0x00009000
-
-#define DEBUG_LL_PHYS_BASE_RS1		0x1c000000
-#define DEBUG_LL_UART_OFFSET_RS1	0x00090000
-
-#define DEBUG_LL_VIRT_BASE		0xf8000000
-
-#if defined(CONFIG_DEBUG_VEXPRESS_UART0_DETECT)
-
-		.macro	addruart,rp,rv,tmp
-
-		@ Make an educated guess regarding the memory map:
-		@ - the original A9 core tile, which has MPCore peripherals
-		@   located at 0x1e000000, should use UART at 0x10009000
-		@ - all other (RS1 complaint) tiles use UART mapped
-		@   at 0x1c090000
-		mrc	p15, 4, \tmp, c15, c0, 0
-		cmp	\tmp, #0x1e000000
-
-		@ Original memory map
-		moveq	\rp, #DEBUG_LL_UART_OFFSET
-		orreq	\rv, \rp, #DEBUG_LL_VIRT_BASE
-		orreq	\rp, \rp, #DEBUG_LL_PHYS_BASE
-
-		@ RS1 memory map
-		movne	\rp, #DEBUG_LL_UART_OFFSET_RS1
-		orrne	\rv, \rp, #DEBUG_LL_VIRT_BASE
-		orrne	\rp, \rp, #DEBUG_LL_PHYS_BASE_RS1
-
-		.endm
-
-#include <asm/hardware/debug-pl01x.S>
-
-#elif defined(CONFIG_DEBUG_VEXPRESS_UART0_CA9)
-
-		.macro	addruart,rp,rv,tmp
-		mov	\rp, #DEBUG_LL_UART_OFFSET
-		orr	\rv, \rp, #DEBUG_LL_VIRT_BASE
-		orr	\rp, \rp, #DEBUG_LL_PHYS_BASE
-		.endm
-
-#include <asm/hardware/debug-pl01x.S>
-
-#elif defined(CONFIG_DEBUG_VEXPRESS_UART0_RS1)
-
-		.macro	addruart,rp,rv,tmp
-		mov	\rp, #DEBUG_LL_UART_OFFSET_RS1
-		orr	\rv, \rp, #DEBUG_LL_VIRT_BASE
-		orr	\rp, \rp, #DEBUG_LL_PHYS_BASE_RS1
-		.endm
-
-#include <asm/hardware/debug-pl01x.S>
-
-#else /* CONFIG_DEBUG_LL_UART_NONE */
-
-		.macro	addruart, rp, rv, tmp
-		/* Safe dummy values */
-		mov	\rp, #0
-		mov	\rv, #DEBUG_LL_VIRT_BASE
-		.endm
-
-		.macro	senduart,rd,rx
-		.endm
-
-		.macro	waituart,rd,rx
-		.endm
-
-		.macro	busyuart,rd,rx
-		.endm
-
-#endif
diff --git a/arch/arm/mach-vexpress/include/mach/gpio.h b/arch/arm/mach-vexpress/include/mach/gpio.h
deleted file mode 100644
index 40a8c17..0000000
--- a/arch/arm/mach-vexpress/include/mach/gpio.h
+++ /dev/null
@@ -1 +0,0 @@
-/* empty */
diff --git a/arch/arm/mach-vexpress/include/mach/irqs.h b/arch/arm/mach-vexpress/include/mach/irqs.h
index 4b10ee7..f8f7f78 100644
--- a/arch/arm/mach-vexpress/include/mach/irqs.h
+++ b/arch/arm/mach-vexpress/include/mach/irqs.h
@@ -1,4 +1,6 @@
 #define IRQ_LOCALTIMER		29
 #define IRQ_LOCALWDOG		30
 
+#ifndef CONFIG_SPARSE_IRQ
 #define NR_IRQS	256
+#endif
diff --git a/arch/arm/mach-vexpress/include/mach/timex.h b/arch/arm/mach-vexpress/include/mach/timex.h
deleted file mode 100644
index 00029ba..0000000
--- a/arch/arm/mach-vexpress/include/mach/timex.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- *  arch/arm/mach-vexpress/include/mach/timex.h
- *
- *  RealView architecture timex specifications
- *
- *  Copyright (C) 2003 ARM Limited
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#define CLOCK_TICK_RATE		(50000000 / 16)
diff --git a/arch/arm/mach-vexpress/include/mach/uncompress.h b/arch/arm/mach-vexpress/include/mach/uncompress.h
deleted file mode 100644
index 1e472eb..0000000
--- a/arch/arm/mach-vexpress/include/mach/uncompress.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- *  arch/arm/mach-vexpress/include/mach/uncompress.h
- *
- *  Copyright (C) 2003 ARM Limited
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#define AMBA_UART_DR(base)	(*(volatile unsigned char *)((base) + 0x00))
-#define AMBA_UART_LCRH(base)	(*(volatile unsigned char *)((base) + 0x2c))
-#define AMBA_UART_CR(base)	(*(volatile unsigned char *)((base) + 0x30))
-#define AMBA_UART_FR(base)	(*(volatile unsigned char *)((base) + 0x18))
-
-#define UART_BASE	0x10009000
-#define UART_BASE_RS1	0x1c090000
-
-static unsigned long get_uart_base(void)
-{
-#if defined(CONFIG_DEBUG_VEXPRESS_UART0_DETECT)
-	unsigned long mpcore_periph;
-
-	/*
-	 * Make an educated guess regarding the memory map:
-	 * - the original A9 core tile, which has MPCore peripherals
-	 *   located at 0x1e000000, should use UART at 0x10009000
-	 * - all other (RS1 complaint) tiles use UART mapped
-	 *   at 0x1c090000
-	 */
-	asm("mrc p15, 4, %0, c15, c0, 0" : "=r" (mpcore_periph));
-
-	if (mpcore_periph == 0x1e000000)
-		return UART_BASE;
-	else
-		return UART_BASE_RS1;
-#elif defined(CONFIG_DEBUG_VEXPRESS_UART0_CA9)
-	return UART_BASE;
-#elif defined(CONFIG_DEBUG_VEXPRESS_UART0_RS1)
-	return UART_BASE_RS1;
-#else
-	return 0;
-#endif
-}
-
-/*
- * This does not append a newline
- */
-static inline void putc(int c)
-{
-	unsigned long base = get_uart_base();
-
-	if (!base)
-		return;
-
-	while (AMBA_UART_FR(base) & (1 << 5))
-		barrier();
-
-	AMBA_UART_DR(base) = c;
-}
-
-static inline void flush(void)
-{
-	unsigned long base = get_uart_base();
-
-	if (!base)
-		return;
-
-	while (AMBA_UART_FR(base) & (1 << 3))
-		barrier();
-}
-
-/*
- * nothing to do
- */
-#define arch_decomp_setup()
-#define arch_decomp_wdog()
diff --git a/arch/arm/mach-vexpress/platsmp.c b/arch/arm/mach-vexpress/platsmp.c
index 14ba112..7db27c8 100644
--- a/arch/arm/mach-vexpress/platsmp.c
+++ b/arch/arm/mach-vexpress/platsmp.c
@@ -20,9 +20,9 @@
 
 #include <mach/motherboard.h>
 
-#include "core.h"
+#include <plat/platsmp.h>
 
-extern void versatile_secondary_startup(void);
+#include "core.h"
 
 #if defined(CONFIG_OF)
 
@@ -167,7 +167,7 @@ void __init vexpress_dt_smp_prepare_cpus(unsigned int max_cpus)
  * Initialise the CPU possible map early - this describes the CPUs
  * which may be present or become present in the system.
  */
-void __init smp_init_cpus(void)
+static void __init vexpress_smp_init_cpus(void)
 {
 	if (ct_desc)
 		ct_desc->init_cpu_map();
@@ -176,7 +176,7 @@ void __init smp_init_cpus(void)
 
 }
 
-void __init platform_smp_prepare_cpus(unsigned int max_cpus)
+static void __init vexpress_smp_prepare_cpus(unsigned int max_cpus)
 {
 	/*
 	 * Initialise the present map, which describes the set of CPUs
@@ -195,3 +195,13 @@ void __init platform_smp_prepare_cpus(unsigned int max_cpus)
 	 */
 	v2m_flags_set(virt_to_phys(versatile_secondary_startup));
 }
+
+struct smp_operations __initdata vexpress_smp_ops = {
+	.smp_init_cpus		= vexpress_smp_init_cpus,
+	.smp_prepare_cpus	= vexpress_smp_prepare_cpus,
+	.smp_secondary_init	= versatile_secondary_init,
+	.smp_boot_secondary	= versatile_boot_secondary,
+#ifdef CONFIG_HOTPLUG_CPU
+	.cpu_die		= vexpress_cpu_die,
+#endif
+};
diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c
index 37608f2..5f6b7d5 100644
--- a/arch/arm/mach-vexpress/v2m.c
+++ b/arch/arm/mach-vexpress/v2m.c
@@ -5,6 +5,7 @@
 #include <linux/amba/bus.h>
 #include <linux/amba/mmci.h>
 #include <linux/io.h>
+#include <linux/smp.h>
 #include <linux/init.h>
 #include <linux/of_address.h>
 #include <linux/of_fdt.h>
@@ -38,6 +39,7 @@
 #include <mach/motherboard.h>
 
 #include <plat/sched_clock.h>
+#include <plat/platsmp.h>
 
 #include "core.h"
 
@@ -530,6 +532,7 @@ static void __init v2m_init(void)
 
 MACHINE_START(VEXPRESS, "ARM-Versatile Express")
 	.atag_offset	= 0x100,
+	.smp		= smp_ops(vexpress_smp_ops),
 	.map_io		= v2m_map_io,
 	.init_early	= v2m_init_early,
 	.init_irq	= v2m_init_irq,
@@ -539,8 +542,6 @@ MACHINE_START(VEXPRESS, "ARM-Versatile Express")
 	.restart	= v2m_restart,
 MACHINE_END
 
-#if defined(CONFIG_ARCH_VEXPRESS_DT)
-
 static struct map_desc v2m_rs1_io_desc __initdata = {
 	.virtual	= V2M_PERIPH,
 	.pfn		= __phys_to_pfn(0x1c000000),
@@ -663,6 +664,7 @@ const static char *v2m_dt_match[] __initconst = {
 
 DT_MACHINE_START(VEXPRESS_DT, "ARM-Versatile Express")
 	.dt_compat	= v2m_dt_match,
+	.smp		= smp_ops(vexpress_smp_ops),
 	.map_io		= v2m_dt_map_io,
 	.init_early	= v2m_dt_init_early,
 	.init_irq	= v2m_dt_init_irq,
@@ -671,5 +673,3 @@ DT_MACHINE_START(VEXPRESS_DT, "ARM-Versatile Express")
 	.handle_irq	= gic_handle_irq,
 	.restart	= v2m_restart,
 MACHINE_END
-
-#endif
diff --git a/arch/arm/mach-vt8500/Kconfig b/arch/arm/mach-vt8500/Kconfig
deleted file mode 100644
index 2c20a34..0000000
--- a/arch/arm/mach-vt8500/Kconfig
+++ /dev/null
@@ -1,73 +0,0 @@
-if ARCH_VT8500
-
-config VTWM_VERSION_VT8500
-	bool
-
-config VTWM_VERSION_WM8505
-	bool
-
-config MACH_BV07
-	bool "Benign BV07-8500 Mini Netbook"
-	depends on ARCH_VT8500
-	select VTWM_VERSION_VT8500
-	help
-	  Add support for the inexpensive 7-inch netbooks sold by many
-	  Chinese distributors under various names. Note that there are
-	  many hardware implementations in identical exterior, make sure
-	  that yours is indeed based on a VIA VT8500 chip.
-
-config MACH_WM8505_7IN_NETBOOK
-	bool "WM8505 7-inch generic netbook"
-	depends on ARCH_VT8500
-	select VTWM_VERSION_WM8505
-	help
-	  Add support for the inexpensive 7-inch netbooks sold by many
-	  Chinese distributors under various names. Note that there are
-	  many hardware implementations in identical exterior, make sure
-	  that yours is indeed based on a WonderMedia WM8505 chip.
-
-comment "LCD panel size"
-
-config WMT_PANEL_800X480
-	bool "7-inch with 800x480 resolution"
-	depends on (FB_VT8500 || FB_WM8505)
-	default y
-	help
-	  These are found in most of the netbooks in generic cases, as
-	  well as in Eken M001 tablets and possibly elsewhere.
-
-	  To select this panel at runtime, say y here and append
-	  'panel=800x480' to your kernel command line. Otherwise, the
-	  largest one available will be used.
-
-config WMT_PANEL_800X600
-	bool "8-inch with 800x600 resolution"
-	depends on (FB_VT8500 || FB_WM8505)
-	help
-	  These are found in Eken M003 tablets and possibly elsewhere.
-
-	  To select this panel at runtime, say y here and append
-	  'panel=800x600' to your kernel command line. Otherwise, the
-	  largest one available will be used.
-
-config WMT_PANEL_1024X576
-	bool "10-inch with 1024x576 resolution"
-	depends on (FB_VT8500 || FB_WM8505)
-	help
-	  These are found in CherryPal netbooks and possibly elsewhere.
-
-	  To select this panel at runtime, say y here and append
-	  'panel=1024x576' to your kernel command line. Otherwise, the
-	  largest one available will be used.
-
-config WMT_PANEL_1024X600
-	bool "10-inch with 1024x600 resolution"
-	depends on (FB_VT8500 || FB_WM8505)
-	help
-	  These are found in Eken M006 tablets and possibly elsewhere.
-
-	  To select this panel at runtime, say y here and append
-	  'panel=1024x600' to your kernel command line. Otherwise, the
-	  largest one available will be used.
-
-endif
diff --git a/arch/arm/mach-vt8500/Makefile b/arch/arm/mach-vt8500/Makefile
index 7ce5176..e035251 100644
--- a/arch/arm/mach-vt8500/Makefile
+++ b/arch/arm/mach-vt8500/Makefile
@@ -1,7 +1 @@
-obj-y += devices.o gpio.o irq.o timer.o restart.o
-
-obj-$(CONFIG_VTWM_VERSION_VT8500) += devices-vt8500.o
-obj-$(CONFIG_VTWM_VERSION_WM8505) += devices-wm8505.o
-
-obj-$(CONFIG_MACH_BV07) += bv07.o
-obj-$(CONFIG_MACH_WM8505_7IN_NETBOOK) += wm8505_7in.o
+obj-$(CONFIG_ARCH_VT8500) += irq.o timer.o vt8500.o
diff --git a/arch/arm/mach-vt8500/bv07.c b/arch/arm/mach-vt8500/bv07.c
deleted file mode 100644
index f9fbeb2..0000000
--- a/arch/arm/mach-vt8500/bv07.c
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- *  arch/arm/mach-vt8500/bv07.c
- *
- *  Copyright (C) 2010 Alexey Charkov <alchark@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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <linux/io.h>
-#include <linux/pm.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <mach/restart.h>
-
-#include "devices.h"
-
-static void __iomem *pmc_hiber;
-
-static struct platform_device *devices[] __initdata = {
-	&vt8500_device_uart0,
-	&vt8500_device_lcdc,
-	&vt8500_device_ehci,
-	&vt8500_device_ge_rops,
-	&vt8500_device_pwm,
-	&vt8500_device_pwmbl,
-	&vt8500_device_rtc,
-};
-
-static void vt8500_power_off(void)
-{
-	local_irq_disable();
-	writew(5, pmc_hiber);
-	asm("mcr%? p15, 0, %0, c7, c0, 4" : : "r" (0));
-}
-
-void __init bv07_init(void)
-{
-#ifdef CONFIG_FB_VT8500
-	void __iomem *gpio_mux_reg = ioremap(wmt_gpio_base + 0x200, 4);
-	if (gpio_mux_reg) {
-		writel(readl(gpio_mux_reg) | 1, gpio_mux_reg);
-		iounmap(gpio_mux_reg);
-	} else {
-		printk(KERN_ERR "Could not remap the GPIO mux register, display may not work properly!\n");
-	}
-#endif
-	pmc_hiber = ioremap(wmt_pmc_base + 0x12, 2);
-	if (pmc_hiber)
-		pm_power_off = &vt8500_power_off;
-	else
-		printk(KERN_ERR "PMC Hibernation register could not be remapped, not enabling power off!\n");
-
-	wmt_setup_restart();
-	vt8500_set_resources();
-	platform_add_devices(devices, ARRAY_SIZE(devices));
-	vt8500_gpio_init();
-}
-
-MACHINE_START(BV07, "Benign BV07 Mini Netbook")
-	.atag_offset	= 0x100,
-	.restart	= wmt_restart,
-	.reserve	= vt8500_reserve_mem,
-	.map_io		= vt8500_map_io,
-	.init_irq	= vt8500_init_irq,
-	.timer		= &vt8500_timer,
-	.init_machine	= bv07_init,
-MACHINE_END
diff --git a/arch/arm/mach-vt8500/common.h b/arch/arm/mach-vt8500/common.h
new file mode 100644
index 0000000..2b24196
--- /dev/null
+++ b/arch/arm/mach-vt8500/common.h
@@ -0,0 +1,28 @@
+/* linux/arch/arm/mach-vt8500/dt_common.h
+ *
+ * Copyright (C) 2012 Tony Prisk <linux@prisktech.co.nz>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __ARCH_ARM_MACH_VT8500_DT_COMMON_H
+#define __ARCH_ARM_MACH_VT8500_DT_COMMON_H
+
+#include <linux/of.h>
+
+void __init vt8500_timer_init(void);
+int __init vt8500_irq_init(struct device_node *node,
+				struct device_node *parent);
+
+/* defined in drivers/clk/clk-vt8500.c */
+void __init vtwm_clk_init(void __iomem *pmc_base);
+
+#endif
diff --git a/arch/arm/mach-vt8500/devices-vt8500.c b/arch/arm/mach-vt8500/devices-vt8500.c
deleted file mode 100644
index 19519ae..0000000
--- a/arch/arm/mach-vt8500/devices-vt8500.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/* linux/arch/arm/mach-vt8500/devices-vt8500.c
- *
- * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/platform_device.h>
-
-#include <mach/vt8500_regs.h>
-#include <mach/vt8500_irqs.h>
-#include <mach/i8042.h>
-#include "devices.h"
-
-void __init vt8500_set_resources(void)
-{
-	struct resource tmp[3];
-
-	tmp[0] = wmt_mmio_res(VT8500_LCDC_BASE, SZ_1K);
-	tmp[1] = wmt_irq_res(IRQ_LCDC);
-	wmt_res_add(&vt8500_device_lcdc, tmp, 2);
-
-	tmp[0] = wmt_mmio_res(VT8500_UART0_BASE, 0x1040);
-	tmp[1] = wmt_irq_res(IRQ_UART0);
-	wmt_res_add(&vt8500_device_uart0, tmp, 2);
-
-	tmp[0] = wmt_mmio_res(VT8500_UART1_BASE, 0x1040);
-	tmp[1] = wmt_irq_res(IRQ_UART1);
-	wmt_res_add(&vt8500_device_uart1, tmp, 2);
-
-	tmp[0] = wmt_mmio_res(VT8500_UART2_BASE, 0x1040);
-	tmp[1] = wmt_irq_res(IRQ_UART2);
-	wmt_res_add(&vt8500_device_uart2, tmp, 2);
-
-	tmp[0] = wmt_mmio_res(VT8500_UART3_BASE, 0x1040);
-	tmp[1] = wmt_irq_res(IRQ_UART3);
-	wmt_res_add(&vt8500_device_uart3, tmp, 2);
-
-	tmp[0] = wmt_mmio_res(VT8500_EHCI_BASE, SZ_512);
-	tmp[1] = wmt_irq_res(IRQ_EHCI);
-	wmt_res_add(&vt8500_device_ehci, tmp, 2);
-
-	tmp[0] = wmt_mmio_res(VT8500_GEGEA_BASE, SZ_256);
-	wmt_res_add(&vt8500_device_ge_rops, tmp, 1);
-
-	tmp[0] = wmt_mmio_res(VT8500_PWM_BASE, 0x44);
-	wmt_res_add(&vt8500_device_pwm, tmp, 1);
-
-	tmp[0] = wmt_mmio_res(VT8500_RTC_BASE, 0x2c);
-	tmp[1] = wmt_irq_res(IRQ_RTC);
-	tmp[2] = wmt_irq_res(IRQ_RTCSM);
-	wmt_res_add(&vt8500_device_rtc, tmp, 3);
-}
-
-static void __init vt8500_set_externs(void)
-{
-	/* Non-resource-aware stuff */
-	wmt_ic_base = VT8500_IC_BASE;
-	wmt_gpio_base = VT8500_GPIO_BASE;
-	wmt_pmc_base = VT8500_PMC_BASE;
-	wmt_i8042_base = VT8500_PS2_BASE;
-
-	wmt_nr_irqs = VT8500_NR_IRQS;
-	wmt_timer_irq = IRQ_PMCOS0;
-	wmt_gpio_ext_irq[0] = IRQ_EXT0;
-	wmt_gpio_ext_irq[1] = IRQ_EXT1;
-	wmt_gpio_ext_irq[2] = IRQ_EXT2;
-	wmt_gpio_ext_irq[3] = IRQ_EXT3;
-	wmt_gpio_ext_irq[4] = IRQ_EXT4;
-	wmt_gpio_ext_irq[5] = IRQ_EXT5;
-	wmt_gpio_ext_irq[6] = IRQ_EXT6;
-	wmt_gpio_ext_irq[7] = IRQ_EXT7;
-	wmt_i8042_kbd_irq = IRQ_PS2KBD;
-	wmt_i8042_aux_irq = IRQ_PS2MOUSE;
-}
-
-void __init vt8500_map_io(void)
-{
-	iotable_init(wmt_io_desc, ARRAY_SIZE(wmt_io_desc));
-
-	/* Should be done before interrupts and timers are initialized */
-	vt8500_set_externs();
-}
diff --git a/arch/arm/mach-vt8500/devices-wm8505.c b/arch/arm/mach-vt8500/devices-wm8505.c
deleted file mode 100644
index db4594e..0000000
--- a/arch/arm/mach-vt8500/devices-wm8505.c
+++ /dev/null
@@ -1,99 +0,0 @@
-/* linux/arch/arm/mach-vt8500/devices-wm8505.c
- *
- * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/platform_device.h>
-
-#include <mach/wm8505_regs.h>
-#include <mach/wm8505_irqs.h>
-#include <mach/i8042.h>
-#include "devices.h"
-
-void __init wm8505_set_resources(void)
-{
-	struct resource tmp[3];
-
-	tmp[0] = wmt_mmio_res(WM8505_GOVR_BASE, SZ_512);
-	wmt_res_add(&vt8500_device_wm8505_fb, tmp, 1);
-
-	tmp[0] = wmt_mmio_res(WM8505_UART0_BASE, 0x1040);
-	tmp[1] = wmt_irq_res(IRQ_UART0);
-	wmt_res_add(&vt8500_device_uart0, tmp, 2);
-
-	tmp[0] = wmt_mmio_res(WM8505_UART1_BASE, 0x1040);
-	tmp[1] = wmt_irq_res(IRQ_UART1);
-	wmt_res_add(&vt8500_device_uart1, tmp, 2);
-
-	tmp[0] = wmt_mmio_res(WM8505_UART2_BASE, 0x1040);
-	tmp[1] = wmt_irq_res(IRQ_UART2);
-	wmt_res_add(&vt8500_device_uart2, tmp, 2);
-
-	tmp[0] = wmt_mmio_res(WM8505_UART3_BASE, 0x1040);
-	tmp[1] = wmt_irq_res(IRQ_UART3);
-	wmt_res_add(&vt8500_device_uart3, tmp, 2);
-
-	tmp[0] = wmt_mmio_res(WM8505_UART4_BASE, 0x1040);
-	tmp[1] = wmt_irq_res(IRQ_UART4);
-	wmt_res_add(&vt8500_device_uart4, tmp, 2);
-
-	tmp[0] = wmt_mmio_res(WM8505_UART5_BASE, 0x1040);
-	tmp[1] = wmt_irq_res(IRQ_UART5);
-	wmt_res_add(&vt8500_device_uart5, tmp, 2);
-
-	tmp[0] = wmt_mmio_res(WM8505_EHCI_BASE, SZ_512);
-	tmp[1] = wmt_irq_res(IRQ_EHCI);
-	wmt_res_add(&vt8500_device_ehci, tmp, 2);
-
-	tmp[0] = wmt_mmio_res(WM8505_GEGEA_BASE, SZ_256);
-	wmt_res_add(&vt8500_device_ge_rops, tmp, 1);
-
-	tmp[0] = wmt_mmio_res(WM8505_PWM_BASE, 0x44);
-	wmt_res_add(&vt8500_device_pwm, tmp, 1);
-
-	tmp[0] = wmt_mmio_res(WM8505_RTC_BASE, 0x2c);
-	tmp[1] = wmt_irq_res(IRQ_RTC);
-	tmp[2] = wmt_irq_res(IRQ_RTCSM);
-	wmt_res_add(&vt8500_device_rtc, tmp, 3);
-}
-
-static void __init wm8505_set_externs(void)
-{
-	/* Non-resource-aware stuff */
-	wmt_ic_base = WM8505_IC_BASE;
-	wmt_sic_base = WM8505_SIC_BASE;
-	wmt_gpio_base = WM8505_GPIO_BASE;
-	wmt_pmc_base = WM8505_PMC_BASE;
-	wmt_i8042_base = WM8505_PS2_BASE;
-
-	wmt_nr_irqs = WM8505_NR_IRQS;
-	wmt_timer_irq = IRQ_PMCOS0;
-	wmt_gpio_ext_irq[0] = IRQ_EXT0;
-	wmt_gpio_ext_irq[1] = IRQ_EXT1;
-	wmt_gpio_ext_irq[2] = IRQ_EXT2;
-	wmt_gpio_ext_irq[3] = IRQ_EXT3;
-	wmt_gpio_ext_irq[4] = IRQ_EXT4;
-	wmt_gpio_ext_irq[5] = IRQ_EXT5;
-	wmt_gpio_ext_irq[6] = IRQ_EXT6;
-	wmt_gpio_ext_irq[7] = IRQ_EXT7;
-	wmt_i8042_kbd_irq = IRQ_PS2KBD;
-	wmt_i8042_aux_irq = IRQ_PS2MOUSE;
-}
-
-void __init wm8505_map_io(void)
-{
-	iotable_init(wmt_io_desc, ARRAY_SIZE(wmt_io_desc));
-
-	/* Should be done before interrupts and timers are initialized */
-	wm8505_set_externs();
-}
diff --git a/arch/arm/mach-vt8500/devices.c b/arch/arm/mach-vt8500/devices.c
deleted file mode 100644
index 1fcdc36..0000000
--- a/arch/arm/mach-vt8500/devices.c
+++ /dev/null
@@ -1,270 +0,0 @@
-/* linux/arch/arm/mach-vt8500/devices.c
- *
- * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/io.h>
-#include <linux/device.h>
-#include <linux/dma-mapping.h>
-#include <linux/platform_device.h>
-#include <linux/pwm_backlight.h>
-#include <linux/memblock.h>
-
-#include <asm/mach/arch.h>
-
-#include <mach/vt8500fb.h>
-#include <mach/i8042.h>
-#include "devices.h"
-
-/* These can't use resources currently */
-unsigned long wmt_ic_base __initdata;
-unsigned long wmt_sic_base __initdata;
-unsigned long wmt_gpio_base __initdata;
-unsigned long wmt_pmc_base __initdata;
-unsigned long wmt_i8042_base __initdata;
-
-int wmt_nr_irqs __initdata;
-int wmt_timer_irq __initdata;
-int wmt_gpio_ext_irq[8] __initdata;
-
-/* Should remain accessible after init.
- * i8042 driver desperately calls for attention...
- */
-int wmt_i8042_kbd_irq;
-int wmt_i8042_aux_irq;
-
-static u64 fb_dma_mask = DMA_BIT_MASK(32);
-
-struct platform_device vt8500_device_lcdc = {
-	.name           = "vt8500-lcd",
-	.id             = 0,
-	.dev		= {
-		.dma_mask	= &fb_dma_mask,
-		.coherent_dma_mask = DMA_BIT_MASK(32),
-	},
-};
-
-struct platform_device vt8500_device_wm8505_fb = {
-	.name           = "wm8505-fb",
-	.id             = 0,
-};
-
-/* Smallest to largest */
-static struct vt8500fb_platform_data panels[] = {
-#ifdef CONFIG_WMT_PANEL_800X480
-{
-	.xres_virtual	= 800,
-	.yres_virtual	= 480 * 2,
-	.mode		= {
-		.name		= "800x480",
-		.xres		= 800,
-		.yres		= 480,
-		.left_margin	= 88,
-		.right_margin	= 40,
-		.upper_margin	= 32,
-		.lower_margin	= 11,
-		.hsync_len	= 0,
-		.vsync_len	= 1,
-		.vmode		= FB_VMODE_NONINTERLACED,
-	},
-},
-#endif
-#ifdef CONFIG_WMT_PANEL_800X600
-{
-	.xres_virtual	= 800,
-	.yres_virtual	= 600 * 2,
-	.mode		= {
-		.name		= "800x600",
-		.xres		= 800,
-		.yres		= 600,
-		.left_margin	= 88,
-		.right_margin	= 40,
-		.upper_margin	= 32,
-		.lower_margin	= 11,
-		.hsync_len	= 0,
-		.vsync_len	= 1,
-		.vmode		= FB_VMODE_NONINTERLACED,
-	},
-},
-#endif
-#ifdef CONFIG_WMT_PANEL_1024X576
-{
-	.xres_virtual	= 1024,
-	.yres_virtual	= 576 * 2,
-	.mode		= {
-		.name		= "1024x576",
-		.xres		= 1024,
-		.yres		= 576,
-		.left_margin	= 40,
-		.right_margin	= 24,
-		.upper_margin	= 32,
-		.lower_margin	= 11,
-		.hsync_len	= 96,
-		.vsync_len	= 2,
-		.vmode		= FB_VMODE_NONINTERLACED,
-	},
-},
-#endif
-#ifdef CONFIG_WMT_PANEL_1024X600
-{
-	.xres_virtual	= 1024,
-	.yres_virtual	= 600 * 2,
-	.mode		= {
-		.name		= "1024x600",
-		.xres		= 1024,
-		.yres		= 600,
-		.left_margin	= 66,
-		.right_margin	= 2,
-		.upper_margin	= 19,
-		.lower_margin	= 1,
-		.hsync_len	= 23,
-		.vsync_len	= 8,
-		.vmode		= FB_VMODE_NONINTERLACED,
-	},
-},
-#endif
-};
-
-static int current_panel_idx __initdata = ARRAY_SIZE(panels) - 1;
-
-static int __init panel_setup(char *str)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(panels); i++) {
-		if (strcmp(panels[i].mode.name, str) == 0) {
-			current_panel_idx = i;
-			break;
-		}
-	}
-	return 0;
-}
-
-early_param("panel", panel_setup);
-
-static inline void preallocate_fb(struct vt8500fb_platform_data *p,
-				  unsigned long align) {
-	p->video_mem_len = (p->xres_virtual * p->yres_virtual * 4) >>
-			(p->bpp > 16 ? 0 : (p->bpp > 8 ? 1 :
-					(8 / p->bpp) + 1));
-	p->video_mem_phys = (unsigned long)memblock_alloc(p->video_mem_len,
-							  align);
-	p->video_mem_virt = phys_to_virt(p->video_mem_phys);
-}
-
-struct platform_device vt8500_device_uart0 = {
-	.name		= "vt8500_serial",
-	.id		= 0,
-};
-
-struct platform_device vt8500_device_uart1 = {
-	.name		= "vt8500_serial",
-	.id		= 1,
-};
-
-struct platform_device vt8500_device_uart2 = {
-	.name		= "vt8500_serial",
-	.id		= 2,
-};
-
-struct platform_device vt8500_device_uart3 = {
-	.name		= "vt8500_serial",
-	.id		= 3,
-};
-
-struct platform_device vt8500_device_uart4 = {
-	.name		= "vt8500_serial",
-	.id		= 4,
-};
-
-struct platform_device vt8500_device_uart5 = {
-	.name		= "vt8500_serial",
-	.id		= 5,
-};
-
-static u64 ehci_dma_mask = DMA_BIT_MASK(32);
-
-struct platform_device vt8500_device_ehci = {
-	.name		= "vt8500-ehci",
-	.id		= 0,
-	.dev		= {
-		.dma_mask	= &ehci_dma_mask,
-		.coherent_dma_mask = DMA_BIT_MASK(32),
-	},
-};
-
-struct platform_device vt8500_device_ge_rops = {
-	.name		= "wmt_ge_rops",
-	.id		= -1,
-};
-
-struct platform_device vt8500_device_pwm = {
-	.name		= "vt8500-pwm",
-	.id		= 0,
-};
-
-static struct platform_pwm_backlight_data vt8500_pwmbl_data = {
-	.pwm_id		= 0,
-	.max_brightness	= 128,
-	.dft_brightness = 70,
-	.pwm_period_ns	= 250000, /* revisit when clocks are implemented */
-};
-
-struct platform_device vt8500_device_pwmbl = {
-	.name		= "pwm-backlight",
-	.id		= 0,
-	.dev		= {
-		.platform_data = &vt8500_pwmbl_data,
-	},
-};
-
-struct platform_device vt8500_device_rtc = {
-	.name		= "vt8500-rtc",
-	.id		= 0,
-};
-
-struct map_desc wmt_io_desc[] __initdata = {
-	/* SoC MMIO registers */
-	[0] = {
-		.virtual	= 0xf8000000,
-		.pfn		= __phys_to_pfn(0xd8000000),
-		.length		= 0x00390000, /* max of all chip variants */
-		.type		= MT_DEVICE
-	},
-	/* PCI I/O space, numbers tied to those in <mach/io.h> */
-	[1] = {
-		.virtual	= 0xf0000000,
-		.pfn		= __phys_to_pfn(0xc0000000),
-		.length		= SZ_64K,
-		.type		= MT_DEVICE
-	},
-};
-
-void __init vt8500_reserve_mem(void)
-{
-#ifdef CONFIG_FB_VT8500
-	panels[current_panel_idx].bpp = 16; /* Always use RGB565 */
-	preallocate_fb(&panels[current_panel_idx], SZ_4M);
-	vt8500_device_lcdc.dev.platform_data = &panels[current_panel_idx];
-#endif
-}
-
-void __init wm8505_reserve_mem(void)
-{
-#if defined CONFIG_FB_WM8505
-	panels[current_panel_idx].bpp = 32; /* Always use RGB888 */
-	preallocate_fb(&panels[current_panel_idx], 32);
-	vt8500_device_wm8505_fb.dev.platform_data = &panels[current_panel_idx];
-#endif
-}
diff --git a/arch/arm/mach-vt8500/devices.h b/arch/arm/mach-vt8500/devices.h
deleted file mode 100644
index 188d4e1..0000000
--- a/arch/arm/mach-vt8500/devices.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/* linux/arch/arm/mach-vt8500/devices.h
- *
- * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef __ARCH_ARM_MACH_VT8500_DEVICES_H
-#define __ARCH_ARM_MACH_VT8500_DEVICES_H
-
-#include <linux/platform_device.h>
-#include <asm/mach/map.h>
-
-void __init vt8500_init_irq(void);
-void __init wm8505_init_irq(void);
-void __init vt8500_map_io(void);
-void __init wm8505_map_io(void);
-void __init vt8500_reserve_mem(void);
-void __init wm8505_reserve_mem(void);
-void __init vt8500_gpio_init(void);
-void __init vt8500_set_resources(void);
-void __init wm8505_set_resources(void);
-
-extern unsigned long wmt_ic_base __initdata;
-extern unsigned long wmt_sic_base __initdata;
-extern unsigned long wmt_gpio_base __initdata;
-extern unsigned long wmt_pmc_base __initdata;
-
-extern int wmt_nr_irqs __initdata;
-extern int wmt_timer_irq __initdata;
-extern int wmt_gpio_ext_irq[8] __initdata;
-
-extern struct map_desc wmt_io_desc[2] __initdata;
-
-static inline struct resource wmt_mmio_res(u32 start, u32 size)
-{
-	struct resource tmp = {
-		.flags = IORESOURCE_MEM,
-		.start = start,
-		.end = start + size - 1,
-	};
-
-	return tmp;
-}
-
-static inline struct resource wmt_irq_res(int irq)
-{
-	struct resource tmp = {
-		.flags = IORESOURCE_IRQ,
-		.start = irq,
-		.end = irq,
-	};
-
-	return tmp;
-}
-
-static inline void wmt_res_add(struct platform_device *pdev,
-			       const struct resource *res, unsigned int num)
-{
-	if (unlikely(platform_device_add_resources(pdev, res, num)))
-		pr_err("Failed to assign resources\n");
-}
-
-extern struct sys_timer vt8500_timer;
-
-extern struct platform_device vt8500_device_uart0;
-extern struct platform_device vt8500_device_uart1;
-extern struct platform_device vt8500_device_uart2;
-extern struct platform_device vt8500_device_uart3;
-extern struct platform_device vt8500_device_uart4;
-extern struct platform_device vt8500_device_uart5;
-
-extern struct platform_device vt8500_device_lcdc;
-extern struct platform_device vt8500_device_wm8505_fb;
-extern struct platform_device vt8500_device_ehci;
-extern struct platform_device vt8500_device_ge_rops;
-extern struct platform_device vt8500_device_pwm;
-extern struct platform_device vt8500_device_pwmbl;
-extern struct platform_device vt8500_device_rtc;
-#endif
diff --git a/arch/arm/mach-vt8500/gpio.c b/arch/arm/mach-vt8500/gpio.c
deleted file mode 100644
index 2bcc0ec..0000000
--- a/arch/arm/mach-vt8500/gpio.c
+++ /dev/null
@@ -1,240 +0,0 @@
-/* linux/arch/arm/mach-vt8500/gpio.c
- *
- * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/gpio.h>
-#include <linux/init.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-
-#include "devices.h"
-
-#define to_vt8500(__chip) container_of(__chip, struct vt8500_gpio_chip, chip)
-
-#define ENABLE_REGS	0x0
-#define DIRECTION_REGS	0x20
-#define OUTVALUE_REGS	0x40
-#define INVALUE_REGS	0x60
-
-#define EXT_REGOFF	0x1c
-
-static void __iomem *regbase;
-
-struct vt8500_gpio_chip {
-	struct gpio_chip	chip;
-	unsigned int		shift;
-	unsigned int		regoff;
-};
-
-static int gpio_to_irq_map[8];
-
-static int vt8500_muxed_gpio_request(struct gpio_chip *chip,
-				     unsigned offset)
-{
-	struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
-	unsigned val = readl(regbase + ENABLE_REGS + vt8500_chip->regoff);
-
-	val |= (1 << vt8500_chip->shift << offset);
-	writel(val, regbase + ENABLE_REGS + vt8500_chip->regoff);
-
-	return 0;
-}
-
-static void vt8500_muxed_gpio_free(struct gpio_chip *chip,
-				   unsigned offset)
-{
-	struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
-	unsigned val = readl(regbase + ENABLE_REGS + vt8500_chip->regoff);
-
-	val &= ~(1 << vt8500_chip->shift << offset);
-	writel(val, regbase + ENABLE_REGS + vt8500_chip->regoff);
-}
-
-static int vt8500_muxed_gpio_direction_input(struct gpio_chip *chip,
-				       unsigned offset)
-{
-	struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
-	unsigned val = readl(regbase + DIRECTION_REGS + vt8500_chip->regoff);
-
-	val &= ~(1 << vt8500_chip->shift << offset);
-	writel(val, regbase + DIRECTION_REGS + vt8500_chip->regoff);
-
-	return 0;
-}
-
-static int vt8500_muxed_gpio_direction_output(struct gpio_chip *chip,
-					unsigned offset, int value)
-{
-	struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
-	unsigned val = readl(regbase + DIRECTION_REGS + vt8500_chip->regoff);
-
-	val |= (1 << vt8500_chip->shift << offset);
-	writel(val, regbase + DIRECTION_REGS + vt8500_chip->regoff);
-
-	if (value) {
-		val = readl(regbase + OUTVALUE_REGS + vt8500_chip->regoff);
-		val |= (1 << vt8500_chip->shift << offset);
-		writel(val, regbase + OUTVALUE_REGS + vt8500_chip->regoff);
-	}
-	return 0;
-}
-
-static int vt8500_muxed_gpio_get_value(struct gpio_chip *chip,
-				       unsigned offset)
-{
-	struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
-
-	return (readl(regbase + INVALUE_REGS + vt8500_chip->regoff)
-		>> vt8500_chip->shift >> offset) & 1;
-}
-
-static void vt8500_muxed_gpio_set_value(struct gpio_chip *chip,
-					unsigned offset, int value)
-{
-	struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
-	unsigned val = readl(regbase + INVALUE_REGS + vt8500_chip->regoff);
-
-	if (value)
-		val |= (1 << vt8500_chip->shift << offset);
-	else
-		val &= ~(1 << vt8500_chip->shift << offset);
-
-	writel(val, regbase + INVALUE_REGS + vt8500_chip->regoff);
-}
-
-#define VT8500_GPIO_BANK(__name, __shift, __off, __base, __num)		\
-{									\
-	.chip = {							\
-		.label			= __name,			\
-		.request		= vt8500_muxed_gpio_request,	\
-		.free			= vt8500_muxed_gpio_free,	\
-		.direction_input  = vt8500_muxed_gpio_direction_input,	\
-		.direction_output = vt8500_muxed_gpio_direction_output,	\
-		.get			= vt8500_muxed_gpio_get_value,	\
-		.set			= vt8500_muxed_gpio_set_value,	\
-		.can_sleep		= 0,				\
-		.base			= __base,			\
-		.ngpio			= __num,			\
-	},								\
-	.shift		= __shift,					\
-	.regoff		= __off,					\
-}
-
-static struct vt8500_gpio_chip vt8500_muxed_gpios[] = {
-	VT8500_GPIO_BANK("uart0",	0,	0x0,	8,	4),
-	VT8500_GPIO_BANK("uart1",	4,	0x0,	12,	4),
-	VT8500_GPIO_BANK("spi0",	8,	0x0,	16,	4),
-	VT8500_GPIO_BANK("spi1",	12,	0x0,	20,	4),
-	VT8500_GPIO_BANK("spi2",	16,	0x0,	24,	4),
-	VT8500_GPIO_BANK("pwmout",	24,	0x0,	28,	2),
-
-	VT8500_GPIO_BANK("sdmmc",	0,	0x4,	30,	11),
-	VT8500_GPIO_BANK("ms",		16,	0x4,	41,	7),
-	VT8500_GPIO_BANK("i2c0",	24,	0x4,	48,	2),
-	VT8500_GPIO_BANK("i2c1",	26,	0x4,	50,	2),
-
-	VT8500_GPIO_BANK("mii",		0,	0x8,	52,	20),
-	VT8500_GPIO_BANK("see",		20,	0x8,	72,	4),
-	VT8500_GPIO_BANK("ide",		24,	0x8,	76,	7),
-
-	VT8500_GPIO_BANK("ccir",	0,	0xc,	83,	19),
-
-	VT8500_GPIO_BANK("ts",		8,	0x10,	102,	11),
-
-	VT8500_GPIO_BANK("lcd",		0,	0x14,	113,	23),
-};
-
-static int vt8500_gpio_direction_input(struct gpio_chip *chip,
-				       unsigned offset)
-{
-	unsigned val = readl(regbase + DIRECTION_REGS + EXT_REGOFF);
-
-	val &= ~(1 << offset);
-	writel(val, regbase + DIRECTION_REGS + EXT_REGOFF);
-	return 0;
-}
-
-static int vt8500_gpio_direction_output(struct gpio_chip *chip,
-					unsigned offset, int value)
-{
-	unsigned val = readl(regbase + DIRECTION_REGS + EXT_REGOFF);
-
-	val |= (1 << offset);
-	writel(val, regbase + DIRECTION_REGS + EXT_REGOFF);
-
-	if (value) {
-		val = readl(regbase + OUTVALUE_REGS + EXT_REGOFF);
-		val |= (1 << offset);
-		writel(val, regbase + OUTVALUE_REGS + EXT_REGOFF);
-	}
-	return 0;
-}
-
-static int vt8500_gpio_get_value(struct gpio_chip *chip,
-				       unsigned offset)
-{
-	return (readl(regbase + INVALUE_REGS + EXT_REGOFF) >> offset) & 1;
-}
-
-static void vt8500_gpio_set_value(struct gpio_chip *chip,
-					unsigned offset, int value)
-{
-	unsigned val = readl(regbase + OUTVALUE_REGS + EXT_REGOFF);
-
-	if (value)
-		val |= (1 << offset);
-	else
-		val &= ~(1 << offset);
-
-	writel(val, regbase + OUTVALUE_REGS + EXT_REGOFF);
-}
-
-static int vt8500_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
-{
-	if (offset > 7)
-		return -EINVAL;
-
-	return gpio_to_irq_map[offset];
-}
-
-static struct gpio_chip vt8500_external_gpios = {
-	.label			= "extgpio",
-	.direction_input	= vt8500_gpio_direction_input,
-	.direction_output	= vt8500_gpio_direction_output,
-	.get			= vt8500_gpio_get_value,
-	.set			= vt8500_gpio_set_value,
-	.to_irq			= vt8500_gpio_to_irq,
-	.can_sleep		= 0,
-	.base			= 0,
-	.ngpio			= 8,
-};
-
-void __init vt8500_gpio_init(void)
-{
-	int i;
-
-	for (i = 0; i < 8; i++)
-		gpio_to_irq_map[i] = wmt_gpio_ext_irq[i];
-
-	regbase = ioremap(wmt_gpio_base, SZ_64K);
-	if (!regbase) {
-		printk(KERN_ERR "Failed to map MMIO registers for GPIO\n");
-		return;
-	}
-
-	gpiochip_add(&vt8500_external_gpios);
-
-	for (i = 0; i < ARRAY_SIZE(vt8500_muxed_gpios); i++)
-		gpiochip_add(&vt8500_muxed_gpios[i].chip);
-}
diff --git a/arch/arm/mach-vt8500/include/mach/gpio.h b/arch/arm/mach-vt8500/include/mach/gpio.h
deleted file mode 100644
index 40a8c17..0000000
--- a/arch/arm/mach-vt8500/include/mach/gpio.h
+++ /dev/null
@@ -1 +0,0 @@
-/* empty */
diff --git a/arch/arm/mach-vt8500/include/mach/restart.h b/arch/arm/mach-vt8500/include/mach/restart.h
index 89f9b78..7389795 100644
--- a/arch/arm/mach-vt8500/include/mach/restart.h
+++ b/arch/arm/mach-vt8500/include/mach/restart.h
@@ -13,5 +13,5 @@
  *
  */
 
-void wmt_setup_restart(void);
-void wmt_restart(char mode, const char *cmd);
+void vt8500_setup_restart(void);
+void vt8500_restart(char mode, const char *cmd);
diff --git a/arch/arm/mach-vt8500/include/mach/vt8500_irqs.h b/arch/arm/mach-vt8500/include/mach/vt8500_irqs.h
deleted file mode 100644
index ecfee91..0000000
--- a/arch/arm/mach-vt8500/include/mach/vt8500_irqs.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- *  arch/arm/mach-vt8500/include/mach/vt8500_irqs.h
- *
- *  Copyright (C) 2010 Alexey Charkov <alchark@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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/* VT8500 Interrupt Sources */
-
-#define IRQ_JPEGENC	0	/* JPEG Encoder */
-#define IRQ_JPEGDEC	1	/* JPEG Decoder */
-				/* Reserved */
-#define IRQ_PATA	3	/* PATA Controller */
-				/* Reserved */
-#define IRQ_DMA		5	/* DMA Controller */
-#define IRQ_EXT0	6	/* External Interrupt 0 */
-#define IRQ_EXT1	7	/* External Interrupt 1 */
-#define IRQ_GE		8	/* Graphic Engine */
-#define IRQ_GOV		9	/* Graphic Overlay Engine */
-#define IRQ_ETHER	10	/* Ethernet MAC */
-#define IRQ_MPEGTS	11	/* Transport Stream Interface */
-#define IRQ_LCDC	12	/* LCD Controller */
-#define IRQ_EXT2	13	/* External Interrupt 2 */
-#define IRQ_EXT3	14	/* External Interrupt 3 */
-#define IRQ_EXT4	15	/* External Interrupt 4 */
-#define IRQ_CIPHER	16	/* Cipher */
-#define IRQ_VPP		17	/* Video Post-Processor */
-#define IRQ_I2C1	18	/* I2C 1 */
-#define IRQ_I2C0	19	/* I2C 0 */
-#define IRQ_SDMMC	20	/* SD/MMC Controller */
-#define IRQ_SDMMC_DMA	21	/* SD/MMC Controller DMA */
-#define IRQ_PMC_WU	22	/* Power Management Controller Wakeup */
-				/* Reserved */
-#define IRQ_SPI0	24	/* SPI 0 */
-#define IRQ_SPI1	25	/* SPI 1 */
-#define IRQ_SPI2	26	/* SPI 2 */
-#define IRQ_LCDDF	27	/* LCD Data Formatter */
-#define IRQ_NAND	28	/* NAND Flash Controller */
-#define IRQ_NAND_DMA	29	/* NAND Flash Controller DMA */
-#define IRQ_MS		30	/* MemoryStick Controller */
-#define IRQ_MS_DMA	31	/* MemoryStick Controller DMA */
-#define IRQ_UART0	32	/* UART 0 */
-#define IRQ_UART1	33	/* UART 1 */
-#define IRQ_I2S		34	/* I2S */
-#define IRQ_PCM		35	/* PCM */
-#define IRQ_PMCOS0	36	/* PMC OS Timer 0 */
-#define IRQ_PMCOS1	37	/* PMC OS Timer 1 */
-#define IRQ_PMCOS2	38	/* PMC OS Timer 2 */
-#define IRQ_PMCOS3	39	/* PMC OS Timer 3 */
-#define IRQ_VPU		40	/* Video Processing Unit */
-#define IRQ_VID		41	/* Video Digital Input Interface */
-#define IRQ_AC97	42	/* AC97 Interface */
-#define IRQ_EHCI	43	/* USB */
-#define IRQ_NOR		44	/* NOR Flash Controller */
-#define IRQ_PS2MOUSE	45	/* PS/2 Mouse */
-#define IRQ_PS2KBD	46	/* PS/2 Keyboard */
-#define IRQ_UART2	47	/* UART 2 */
-#define IRQ_RTC		48	/* RTC Interrupt */
-#define IRQ_RTCSM	49	/* RTC Second/Minute Update Interrupt */
-#define IRQ_UART3	50	/* UART 3 */
-#define IRQ_ADC		51	/* ADC */
-#define IRQ_EXT5	52	/* External Interrupt 5 */
-#define IRQ_EXT6	53	/* External Interrupt 6 */
-#define IRQ_EXT7	54	/* External Interrupt 7 */
-#define IRQ_CIR		55	/* CIR */
-#define IRQ_DMA0	56	/* DMA Channel 0 */
-#define IRQ_DMA1	57	/* DMA Channel 1 */
-#define IRQ_DMA2	58	/* DMA Channel 2 */
-#define IRQ_DMA3	59	/* DMA Channel 3 */
-#define IRQ_DMA4	60	/* DMA Channel 4 */
-#define IRQ_DMA5	61	/* DMA Channel 5 */
-#define IRQ_DMA6	62	/* DMA Channel 6 */
-#define IRQ_DMA7	63	/* DMA Channel 7 */
-
-#define VT8500_NR_IRQS		64
diff --git a/arch/arm/mach-vt8500/include/mach/vt8500_regs.h b/arch/arm/mach-vt8500/include/mach/vt8500_regs.h
deleted file mode 100644
index 29c63ec..0000000
--- a/arch/arm/mach-vt8500/include/mach/vt8500_regs.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- *  arch/arm/mach-vt8500/include/mach/vt8500_regs.h
- *
- *  Copyright (C) 2010 Alexey Charkov <alchark@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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#ifndef __ASM_ARM_ARCH_VT8500_REGS_H
-#define __ASM_ARM_ARCH_VT8500_REGS_H
-
-/* VT8500 Registers Map */
-
-#define VT8500_REGS_START_PHYS	0xd8000000	/* Start of MMIO registers */
-#define VT8500_REGS_START_VIRT	0xf8000000	/* Virtual mapping start */
-
-#define VT8500_DDR_BASE		0xd8000000	/* 1k	DDR/DDR2 Memory
-							Controller */
-#define VT8500_DMA_BASE		0xd8001000	/* 1k	DMA Controller */
-#define VT8500_SFLASH_BASE	0xd8002000	/* 1k	Serial Flash Memory
-							Controller */
-#define VT8500_ETHER_BASE	0xd8004000	/* 1k	Ethernet MAC 0 */
-#define VT8500_CIPHER_BASE	0xd8006000	/* 4k	Cipher */
-#define VT8500_USB_BASE		0xd8007800	/* 2k	USB OTG */
-# define VT8500_EHCI_BASE	0xd8007900	/*	EHCI */
-# define VT8500_UHCI_BASE	0xd8007b01	/*	UHCI */
-#define VT8500_PATA_BASE	0xd8008000	/* 512	PATA */
-#define VT8500_PS2_BASE		0xd8008800	/* 1k	PS/2 */
-#define VT8500_NAND_BASE	0xd8009000	/* 1k	NAND Controller */
-#define VT8500_NOR_BASE		0xd8009400	/* 1k	NOR Controller */
-#define VT8500_SDMMC_BASE	0xd800a000	/* 1k	SD/MMC Controller */
-#define VT8500_MS_BASE		0xd800b000	/* 1k	MS/MSPRO Controller */
-#define VT8500_LCDC_BASE	0xd800e400	/* 1k	LCD Controller */
-#define VT8500_VPU_BASE		0xd8050000	/* 256	VPU */
-#define VT8500_GOV_BASE		0xd8050300	/* 256	GOV */
-#define VT8500_GEGEA_BASE	0xd8050400	/* 768	GE/GE Alpha Mixing */
-#define VT8500_LCDF_BASE	0xd8050900	/* 256	LCD Formatter */
-#define VT8500_VID_BASE		0xd8050a00	/* 256	VID */
-#define VT8500_VPP_BASE		0xd8050b00	/* 256	VPP */
-#define VT8500_TSBK_BASE	0xd80f4000	/* 4k	TSBK */
-#define VT8500_JPEGDEC_BASE	0xd80fe000	/* 4k	JPEG Decoder */
-#define VT8500_JPEGENC_BASE	0xd80ff000	/* 4k	JPEG Encoder */
-#define VT8500_RTC_BASE		0xd8100000	/* 64k	RTC */
-#define VT8500_GPIO_BASE	0xd8110000	/* 64k	GPIO Configuration */
-#define VT8500_SCC_BASE		0xd8120000	/* 64k	System Configuration*/
-#define VT8500_PMC_BASE		0xd8130000	/* 64k	PMC Configuration */
-#define VT8500_IC_BASE		0xd8140000	/* 64k	Interrupt Controller*/
-#define VT8500_UART0_BASE	0xd8200000	/* 64k	UART 0 */
-#define VT8500_UART2_BASE	0xd8210000	/* 64k	UART 2 */
-#define VT8500_PWM_BASE		0xd8220000	/* 64k	PWM Configuration */
-#define VT8500_SPI0_BASE	0xd8240000	/* 64k	SPI 0 */
-#define VT8500_SPI1_BASE	0xd8250000	/* 64k	SPI 1 */
-#define VT8500_CIR_BASE		0xd8270000	/* 64k	CIR */
-#define VT8500_I2C0_BASE	0xd8280000	/* 64k	I2C 0 */
-#define VT8500_AC97_BASE	0xd8290000	/* 64k	AC97 */
-#define VT8500_SPI2_BASE	0xd82a0000	/* 64k	SPI 2 */
-#define VT8500_UART1_BASE	0xd82b0000	/* 64k	UART 1 */
-#define VT8500_UART3_BASE	0xd82c0000	/* 64k	UART 3 */
-#define VT8500_PCM_BASE		0xd82d0000	/* 64k	PCM */
-#define VT8500_I2C1_BASE	0xd8320000	/* 64k	I2C 1 */
-#define VT8500_I2S_BASE		0xd8330000	/* 64k	I2S */
-#define VT8500_ADC_BASE		0xd8340000	/* 64k	ADC */
-
-#define VT8500_REGS_END_PHYS	0xd834ffff	/* End of MMIO registers */
-#define VT8500_REGS_LENGTH	(VT8500_REGS_END_PHYS \
-				- VT8500_REGS_START_PHYS + 1)
-
-#endif
diff --git a/arch/arm/mach-vt8500/include/mach/vt8500fb.h b/arch/arm/mach-vt8500/include/mach/vt8500fb.h
deleted file mode 100644
index 7f399c3..0000000
--- a/arch/arm/mach-vt8500/include/mach/vt8500fb.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- *  VT8500/WM8505 Frame Buffer platform data definitions
- *
- *  Copyright (C) 2010 Ed Spiridonov <edo.rus@gmail.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#ifndef _VT8500FB_H
-#define _VT8500FB_H
-
-#include <linux/fb.h>
-
-struct vt8500fb_platform_data {
-	struct fb_videomode	mode;
-	u32			xres_virtual;
-	u32			yres_virtual;
-	u32			bpp;
-	unsigned long		video_mem_phys;
-	void			*video_mem_virt;
-	unsigned long		video_mem_len;
-};
-
-#endif /* _VT8500FB_H */
diff --git a/arch/arm/mach-vt8500/include/mach/wm8505_irqs.h b/arch/arm/mach-vt8500/include/mach/wm8505_irqs.h
deleted file mode 100644
index 6128627..0000000
--- a/arch/arm/mach-vt8500/include/mach/wm8505_irqs.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- *  arch/arm/mach-vt8500/include/mach/wm8505_irqs.h
- *
- *  Copyright (C) 2010 Alexey Charkov <alchark@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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/* WM8505 Interrupt Sources */
-
-#define IRQ_UHCI	0	/* UHC FS (UHCI?) */
-#define IRQ_EHCI	1	/* UHC HS */
-#define IRQ_UDCDMA	2	/* UDC DMA */
-				/* Reserved */
-#define IRQ_PS2MOUSE	4	/* PS/2 Mouse */
-#define IRQ_UDC		5	/* UDC */
-#define IRQ_EXT0	6	/* External Interrupt 0 */
-#define IRQ_EXT1	7	/* External Interrupt 1 */
-#define IRQ_KEYPAD	8	/* Keypad */
-#define IRQ_DMA		9	/* DMA Controller */
-#define IRQ_ETHER	10	/* Ethernet MAC */
-				/* Reserved */
-				/* Reserved */
-#define IRQ_EXT2	13	/* External Interrupt 2 */
-#define IRQ_EXT3	14	/* External Interrupt 3 */
-#define IRQ_EXT4	15	/* External Interrupt 4 */
-#define IRQ_APB		16	/* APB Bridge */
-#define IRQ_DMA0	17	/* DMA Channel 0 */
-#define IRQ_I2C1	18	/* I2C 1 */
-#define IRQ_I2C0	19	/* I2C 0 */
-#define IRQ_SDMMC	20	/* SD/MMC Controller */
-#define IRQ_SDMMC_DMA	21	/* SD/MMC Controller DMA */
-#define IRQ_PMC_WU	22	/* Power Management Controller Wakeup */
-#define IRQ_PS2KBD	23	/* PS/2 Keyboard */
-#define IRQ_SPI0	24	/* SPI 0 */
-#define IRQ_SPI1	25	/* SPI 1 */
-#define IRQ_SPI2	26	/* SPI 2 */
-#define IRQ_DMA1	27	/* DMA Channel 1 */
-#define IRQ_NAND	28	/* NAND Flash Controller */
-#define IRQ_NAND_DMA	29	/* NAND Flash Controller DMA */
-#define IRQ_UART5	30	/* UART 5 */
-#define IRQ_UART4	31	/* UART 4 */
-#define IRQ_UART0	32	/* UART 0 */
-#define IRQ_UART1	33	/* UART 1 */
-#define IRQ_DMA2	34	/* DMA Channel 2 */
-#define IRQ_I2S		35	/* I2S */
-#define IRQ_PMCOS0	36	/* PMC OS Timer 0 */
-#define IRQ_PMCOS1	37	/* PMC OS Timer 1 */
-#define IRQ_PMCOS2	38	/* PMC OS Timer 2 */
-#define IRQ_PMCOS3	39	/* PMC OS Timer 3 */
-#define IRQ_DMA3	40	/* DMA Channel 3 */
-#define IRQ_DMA4	41	/* DMA Channel 4 */
-#define IRQ_AC97	42	/* AC97 Interface */
-				/* Reserved */
-#define IRQ_NOR		44	/* NOR Flash Controller */
-#define IRQ_DMA5	45	/* DMA Channel 5 */
-#define IRQ_DMA6	46	/* DMA Channel 6 */
-#define IRQ_UART2	47	/* UART 2 */
-#define IRQ_RTC		48	/* RTC Interrupt */
-#define IRQ_RTCSM	49	/* RTC Second/Minute Update Interrupt */
-#define IRQ_UART3	50	/* UART 3 */
-#define IRQ_DMA7	51	/* DMA Channel 7 */
-#define IRQ_EXT5	52	/* External Interrupt 5 */
-#define IRQ_EXT6	53	/* External Interrupt 6 */
-#define IRQ_EXT7	54	/* External Interrupt 7 */
-#define IRQ_CIR		55	/* CIR */
-#define IRQ_SIC0	56	/* SIC IRQ0 */
-#define IRQ_SIC1	57	/* SIC IRQ1 */
-#define IRQ_SIC2	58	/* SIC IRQ2 */
-#define IRQ_SIC3	59	/* SIC IRQ3 */
-#define IRQ_SIC4	60	/* SIC IRQ4 */
-#define IRQ_SIC5	61	/* SIC IRQ5 */
-#define IRQ_SIC6	62	/* SIC IRQ6 */
-#define IRQ_SIC7	63	/* SIC IRQ7 */
-				/* Reserved */
-#define IRQ_JPEGDEC	65	/* JPEG Decoder */
-#define IRQ_SAE		66	/* SAE (?) */
-				/* Reserved */
-#define IRQ_VPU		79	/* Video Processing Unit */
-#define IRQ_VPP		80	/* Video Post-Processor */
-#define IRQ_VID		81	/* Video Digital Input Interface */
-#define IRQ_SPU		82	/* SPU (?) */
-#define IRQ_PIP		83	/* PIP Error */
-#define IRQ_GE		84	/* Graphic Engine */
-#define IRQ_GOV		85	/* Graphic Overlay Engine */
-#define IRQ_DVO		86	/* Digital Video Output */
-				/* Reserved */
-#define IRQ_DMA8	92	/* DMA Channel 8 */
-#define IRQ_DMA9	93	/* DMA Channel 9 */
-#define IRQ_DMA10	94	/* DMA Channel 10 */
-#define IRQ_DMA11	95	/* DMA Channel 11 */
-#define IRQ_DMA12	96	/* DMA Channel 12 */
-#define IRQ_DMA13	97	/* DMA Channel 13 */
-#define IRQ_DMA14	98	/* DMA Channel 14 */
-#define IRQ_DMA15	99	/* DMA Channel 15 */
-				/* Reserved */
-#define IRQ_GOVW	111	/* GOVW (?) */
-#define IRQ_GOVRSDSCD	112	/* GOVR SDSCD (?) */
-#define IRQ_GOVRSDMIF	113	/* GOVR SDMIF (?) */
-#define IRQ_GOVRHDSCD	114	/* GOVR HDSCD (?) */
-#define IRQ_GOVRHDMIF	115	/* GOVR HDMIF (?) */
-
-#define WM8505_NR_IRQS		116
diff --git a/arch/arm/mach-vt8500/include/mach/wm8505_regs.h b/arch/arm/mach-vt8500/include/mach/wm8505_regs.h
deleted file mode 100644
index df15509..0000000
--- a/arch/arm/mach-vt8500/include/mach/wm8505_regs.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- *  arch/arm/mach-vt8500/include/mach/wm8505_regs.h
- *
- *  Copyright (C) 2010 Alexey Charkov <alchark@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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#ifndef __ASM_ARM_ARCH_WM8505_REGS_H
-#define __ASM_ARM_ARCH_WM8505_REGS_H
-
-/* WM8505 Registers Map */
-
-#define WM8505_REGS_START_PHYS	0xd8000000	/* Start of MMIO registers */
-#define WM8505_REGS_START_VIRT	0xf8000000	/* Virtual mapping start */
-
-#define WM8505_DDR_BASE		0xd8000400	/* 1k	DDR/DDR2 Memory
-							Controller */
-#define WM8505_DMA_BASE		0xd8001800	/* 1k	DMA Controller */
-#define WM8505_VDMA_BASE	0xd8001c00	/* 1k	VDMA */
-#define WM8505_SFLASH_BASE	0xd8002000	/* 1k	Serial Flash Memory
-							Controller */
-#define WM8505_ETHER_BASE	0xd8004000	/* 1k	Ethernet MAC 0 */
-#define WM8505_CIPHER_BASE	0xd8006000	/* 4k	Cipher */
-#define WM8505_USB_BASE		0xd8007000	/* 2k	USB 2.0 Host */
-# define WM8505_EHCI_BASE	0xd8007100	/*	EHCI */
-# define WM8505_UHCI_BASE	0xd8007301	/*	UHCI */
-#define WM8505_PS2_BASE		0xd8008800	/* 1k	PS/2 */
-#define WM8505_NAND_BASE	0xd8009000	/* 1k	NAND Controller */
-#define WM8505_NOR_BASE		0xd8009400	/* 1k	NOR Controller */
-#define WM8505_SDMMC_BASE	0xd800a000	/* 1k	SD/MMC Controller */
-#define WM8505_VPU_BASE		0xd8050000	/* 256	VPU */
-#define WM8505_GOV_BASE		0xd8050300	/* 256	GOV */
-#define WM8505_GEGEA_BASE	0xd8050400	/* 768	GE/GE Alpha Mixing */
-#define WM8505_GOVR_BASE	0xd8050800	/* 512	GOVR (frambuffer) */
-#define WM8505_VID_BASE		0xd8050a00	/* 256	VID */
-#define WM8505_SCL_BASE		0xd8050d00	/* 256	SCL */
-#define WM8505_VPP_BASE		0xd8050f00	/* 256	VPP */
-#define WM8505_JPEGDEC_BASE	0xd80fe000	/* 4k	JPEG Decoder */
-#define WM8505_RTC_BASE		0xd8100000	/* 64k	RTC */
-#define WM8505_GPIO_BASE	0xd8110000	/* 64k	GPIO Configuration */
-#define WM8505_SCC_BASE		0xd8120000	/* 64k	System Configuration*/
-#define WM8505_PMC_BASE		0xd8130000	/* 64k	PMC Configuration */
-#define WM8505_IC_BASE		0xd8140000	/* 64k	Interrupt Controller*/
-#define WM8505_SIC_BASE		0xd8150000	/* 64k	Secondary IC */
-#define WM8505_UART0_BASE	0xd8200000	/* 64k	UART 0 */
-#define WM8505_UART2_BASE	0xd8210000	/* 64k	UART 2 */
-#define WM8505_PWM_BASE		0xd8220000	/* 64k	PWM Configuration */
-#define WM8505_SPI0_BASE	0xd8240000	/* 64k	SPI 0 */
-#define WM8505_SPI1_BASE	0xd8250000	/* 64k	SPI 1 */
-#define WM8505_KEYPAD_BASE	0xd8260000	/* 64k	Keypad control */
-#define WM8505_CIR_BASE		0xd8270000	/* 64k	CIR */
-#define WM8505_I2C0_BASE	0xd8280000	/* 64k	I2C 0 */
-#define WM8505_AC97_BASE	0xd8290000	/* 64k	AC97 */
-#define WM8505_SPI2_BASE	0xd82a0000	/* 64k	SPI 2 */
-#define WM8505_UART1_BASE	0xd82b0000	/* 64k	UART 1 */
-#define WM8505_UART3_BASE	0xd82c0000	/* 64k	UART 3 */
-#define WM8505_I2C1_BASE	0xd8320000	/* 64k	I2C 1 */
-#define WM8505_I2S_BASE		0xd8330000	/* 64k	I2S */
-#define WM8505_UART4_BASE	0xd8370000	/* 64k	UART 4 */
-#define WM8505_UART5_BASE	0xd8380000	/* 64k	UART 5 */
-
-#define WM8505_REGS_END_PHYS	0xd838ffff	/* End of MMIO registers */
-#define WM8505_REGS_LENGTH	(WM8505_REGS_END_PHYS \
-				- WM8505_REGS_START_PHYS + 1)
-
-#endif
diff --git a/arch/arm/mach-vt8500/irq.c b/arch/arm/mach-vt8500/irq.c
index 642de04..f8f9ab9 100644
--- a/arch/arm/mach-vt8500/irq.c
+++ b/arch/arm/mach-vt8500/irq.c
@@ -1,6 +1,7 @@
 /*
  *  arch/arm/mach-vt8500/irq.c
  *
+ *  Copyright (C) 2012 Tony Prisk <linux@prisktech.co.nz>
  *  Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -18,81 +19,102 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
+/*
+ * This file is copied and modified from the original irq.c provided by
+ * Alexey Charkov. Minor changes have been made for Device Tree Support.
+ */
+
+#include <linux/slab.h>
 #include <linux/io.h>
 #include <linux/irq.h>
+#include <linux/irqdomain.h>
 #include <linux/interrupt.h>
+#include <linux/bitops.h>
+
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
 
 #include <asm/irq.h>
 
-#include "devices.h"
 
-#define VT8500_IC_DCTR		0x40		/* Destination control
-						register, 64*u8 */
-#define VT8500_INT_ENABLE	(1 << 3)
-#define VT8500_TRIGGER_HIGH	(0 << 4)
-#define VT8500_TRIGGER_RISING	(1 << 4)
-#define VT8500_TRIGGER_FALLING	(2 << 4)
+#define VT8500_ICPC_IRQ		0x20
+#define VT8500_ICPC_FIQ		0x24
+#define VT8500_ICDC		0x40		/* Destination Control 64*u32 */
+#define VT8500_ICIS		0x80		/* Interrupt status, 16*u32 */
+
+/* ICPC */
+#define ICPC_MASK		0x3F
+#define ICPC_ROTATE		BIT(6)
+
+/* IC_DCTR */
+#define ICDC_IRQ		0x00
+#define ICDC_FIQ		0x01
+#define ICDC_DSS0		0x02
+#define ICDC_DSS1		0x03
+#define ICDC_DSS2		0x04
+#define ICDC_DSS3		0x05
+#define ICDC_DSS4		0x06
+#define ICDC_DSS5		0x07
+
+#define VT8500_INT_DISABLE	0
+#define VT8500_INT_ENABLE	BIT(3)
+
+#define VT8500_TRIGGER_HIGH	0
+#define VT8500_TRIGGER_RISING	BIT(5)
+#define VT8500_TRIGGER_FALLING	BIT(6)
 #define VT8500_EDGE		( VT8500_TRIGGER_RISING \
 				| VT8500_TRIGGER_FALLING)
-#define VT8500_IC_STATUS	0x80		/* Interrupt status, 2*u32 */
 
-static void __iomem *ic_regbase;
-static void __iomem *sic_regbase;
+static int irq_cnt;
+
+struct vt8500_irq_priv {
+	void __iomem *base;
+};
 
 static void vt8500_irq_mask(struct irq_data *d)
 {
-	void __iomem *base = ic_regbase;
-	unsigned irq = d->irq;
+	struct vt8500_irq_priv *priv =
+			(struct vt8500_irq_priv *)(d->domain->host_data);
+	void __iomem *base = priv->base;
 	u8 edge;
 
-	if (irq >= 64) {
-		base = sic_regbase;
-		irq -= 64;
-	}
-	edge = readb(base + VT8500_IC_DCTR + irq) & VT8500_EDGE;
+	edge = readb(base + VT8500_ICDC + d->hwirq) & VT8500_EDGE;
 	if (edge) {
-		void __iomem *stat_reg = base + VT8500_IC_STATUS
-						+ (irq < 32 ? 0 : 4);
+		void __iomem *stat_reg = base + VT8500_ICIS
+						+ (d->hwirq < 32 ? 0 : 4);
 		unsigned status = readl(stat_reg);
 
-		status |= (1 << (irq & 0x1f));
+		status |= (1 << (d->hwirq & 0x1f));
 		writel(status, stat_reg);
 	} else {
-		u8 dctr = readb(base + VT8500_IC_DCTR + irq);
+		u8 dctr = readb(base + VT8500_ICDC + d->hwirq);
 
 		dctr &= ~VT8500_INT_ENABLE;
-		writeb(dctr, base + VT8500_IC_DCTR + irq);
+		writeb(dctr, base + VT8500_ICDC + d->hwirq);
 	}
 }
 
 static void vt8500_irq_unmask(struct irq_data *d)
 {
-	void __iomem *base = ic_regbase;
-	unsigned irq = d->irq;
+	struct vt8500_irq_priv *priv =
+			(struct vt8500_irq_priv *)(d->domain->host_data);
+	void __iomem *base = priv->base;
 	u8 dctr;
 
-	if (irq >= 64) {
-		base = sic_regbase;
-		irq -= 64;
-	}
-	dctr = readb(base + VT8500_IC_DCTR + irq);
+	dctr = readb(base + VT8500_ICDC + d->hwirq);
 	dctr |= VT8500_INT_ENABLE;
-	writeb(dctr, base + VT8500_IC_DCTR + irq);
+	writeb(dctr, base + VT8500_ICDC + d->hwirq);
 }
 
 static int vt8500_irq_set_type(struct irq_data *d, unsigned int flow_type)
 {
-	void __iomem *base = ic_regbase;
-	unsigned irq = d->irq;
-	unsigned orig_irq = irq;
+	struct vt8500_irq_priv *priv =
+			(struct vt8500_irq_priv *)(d->domain->host_data);
+	void __iomem *base = priv->base;
 	u8 dctr;
 
-	if (irq >= 64) {
-		base = sic_regbase;
-		irq -= 64;
-	}
-
-	dctr = readb(base + VT8500_IC_DCTR + irq);
+	dctr = readb(base + VT8500_ICDC + d->hwirq);
 	dctr &= ~VT8500_EDGE;
 
 	switch (flow_type) {
@@ -100,18 +122,18 @@ static int vt8500_irq_set_type(struct irq_data *d, unsigned int flow_type)
 		return -EINVAL;
 	case IRQF_TRIGGER_HIGH:
 		dctr |= VT8500_TRIGGER_HIGH;
-		__irq_set_handler_locked(orig_irq, handle_level_irq);
+		__irq_set_handler_locked(d->irq, handle_level_irq);
 		break;
 	case IRQF_TRIGGER_FALLING:
 		dctr |= VT8500_TRIGGER_FALLING;
-		__irq_set_handler_locked(orig_irq, handle_edge_irq);
+		__irq_set_handler_locked(d->irq, handle_edge_irq);
 		break;
 	case IRQF_TRIGGER_RISING:
 		dctr |= VT8500_TRIGGER_RISING;
-		__irq_set_handler_locked(orig_irq, handle_edge_irq);
+		__irq_set_handler_locked(d->irq, handle_edge_irq);
 		break;
 	}
-	writeb(dctr, base + VT8500_IC_DCTR + irq);
+	writeb(dctr, base + VT8500_ICDC + d->hwirq);
 
 	return 0;
 }
@@ -124,57 +146,76 @@ static struct irq_chip vt8500_irq_chip = {
 	.irq_set_type = vt8500_irq_set_type,
 };
 
-void __init vt8500_init_irq(void)
+static void __init vt8500_init_irq_hw(void __iomem *base)
 {
 	unsigned int i;
 
-	ic_regbase = ioremap(wmt_ic_base, SZ_64K);
+	/* Enable rotating priority for IRQ */
+	writel(ICPC_ROTATE, base + VT8500_ICPC_IRQ);
+	writel(0x00, base + VT8500_ICPC_FIQ);
 
-	if (ic_regbase) {
-		/* Enable rotating priority for IRQ */
-		writel((1 << 6), ic_regbase + 0x20);
-		writel(0, ic_regbase + 0x24);
+	for (i = 0; i < 64; i++) {
+		/* Disable all interrupts and route them to IRQ */
+		writeb(VT8500_INT_DISABLE | ICDC_IRQ,
+						base + VT8500_ICDC + i);
+	}
+}
 
-		for (i = 0; i < wmt_nr_irqs; i++) {
-			/* Disable all interrupts and route them to IRQ */
-			writeb(0x00, ic_regbase + VT8500_IC_DCTR + i);
+static int vt8500_irq_map(struct irq_domain *h, unsigned int virq,
+							irq_hw_number_t hw)
+{
+	irq_set_chip_and_handler(virq, &vt8500_irq_chip, handle_level_irq);
+	set_irq_flags(virq, IRQF_VALID);
 
-			irq_set_chip_and_handler(i, &vt8500_irq_chip,
-						 handle_level_irq);
-			set_irq_flags(i, IRQF_VALID);
-		}
-	} else {
-		printk(KERN_ERR "Unable to remap the Interrupt Controller registers, not enabling IRQs!\n");
-	}
+	return 0;
 }
 
-void __init wm8505_init_irq(void)
+static struct irq_domain_ops vt8500_irq_domain_ops = {
+	.map = vt8500_irq_map,
+	.xlate = irq_domain_xlate_onecell,
+};
+
+int __init vt8500_irq_init(struct device_node *node, struct device_node *parent)
 {
-	unsigned int i;
+	struct irq_domain *vt8500_irq_domain;
+	struct vt8500_irq_priv *priv;
+	int irq, i;
+	struct device_node *np = node;
+
+	priv = kzalloc(sizeof(struct vt8500_irq_priv), GFP_KERNEL);
+	priv->base = of_iomap(np, 0);
+
+	vt8500_irq_domain = irq_domain_add_legacy(node, 64, irq_cnt, 0,
+				&vt8500_irq_domain_ops, priv);
+	if (!vt8500_irq_domain)
+		pr_err("%s: Unable to add wmt irq domain!\n", __func__);
+
+	irq_set_default_host(vt8500_irq_domain);
+
+	vt8500_init_irq_hw(priv->base);
 
-	ic_regbase = ioremap(wmt_ic_base, SZ_64K);
-	sic_regbase = ioremap(wmt_sic_base, SZ_64K);
-
-	if (ic_regbase && sic_regbase) {
-		/* Enable rotating priority for IRQ */
-		writel((1 << 6), ic_regbase + 0x20);
-		writel(0, ic_regbase + 0x24);
-		writel((1 << 6), sic_regbase + 0x20);
-		writel(0, sic_regbase + 0x24);
-
-		for (i = 0; i < wmt_nr_irqs; i++) {
-			/* Disable all interrupts and route them to IRQ */
-			if (i < 64)
-				writeb(0x00, ic_regbase + VT8500_IC_DCTR + i);
-			else
-				writeb(0x00, sic_regbase + VT8500_IC_DCTR
-								+ i - 64);
-
-			irq_set_chip_and_handler(i, &vt8500_irq_chip,
-						 handle_level_irq);
-			set_irq_flags(i, IRQF_VALID);
+	pr_info("Added IRQ Controller @ %x [virq_base = %d]\n",
+						(u32)(priv->base), irq_cnt);
+
+	/* check if this is a slaved controller */
+	if (of_irq_count(np) != 0) {
+		/* check that we have the correct number of interrupts */
+		if (of_irq_count(np) != 8) {
+			pr_err("%s: Incorrect IRQ map for slave controller\n",
+					__func__);
+			return -EINVAL;
 		}
-	} else {
-		printk(KERN_ERR "Unable to remap the Interrupt Controller registers, not enabling IRQs!\n");
+
+		for (i = 0; i < 8; i++) {
+			irq = irq_of_parse_and_map(np, i);
+			enable_irq(irq);
+		}
+
+		pr_info("vt8500-irq: Enabled slave->parent interrupts\n");
 	}
+
+	irq_cnt += 64;
+
+	return 0;
 }
+
diff --git a/arch/arm/mach-vt8500/restart.c b/arch/arm/mach-vt8500/restart.c
deleted file mode 100644
index 497e89a..0000000
--- a/arch/arm/mach-vt8500/restart.c
+++ /dev/null
@@ -1,54 +0,0 @@
-/* linux/arch/arm/mach-vt8500/restart.c
- *
- * Copyright (C) 2012 Tony Prisk <linux@prisktech.co.nz>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-#include <asm/io.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-
-#define LEGACY_PMC_BASE		0xD8130000
-#define WMT_PRIZM_PMSR_REG	0x60
-
-static void __iomem *pmc_base;
-
-void wmt_setup_restart(void)
-{
-	struct device_node *np;
-
-	/*
-	 * Check if Power Mgmt Controller node is present in device tree. If no
-	 * device tree node, use the legacy PMSR value (valid for all current
-	 * SoCs).
-	 */
-	np = of_find_compatible_node(NULL, NULL, "wmt,prizm-pmc");
-	if (np) {
-		pmc_base = of_iomap(np, 0);
-
-		if (!pmc_base)
-			pr_err("%s:of_iomap(pmc) failed\n", __func__);
-
-		of_node_put(np);
-	} else {
-		pmc_base = ioremap(LEGACY_PMC_BASE, 0x1000);
-		if (!pmc_base) {
-			pr_err("%s:ioremap(rstc) failed\n", __func__);
-			return;
-		}
-	}
-}
-
-void wmt_restart(char mode, const char *cmd)
-{
-	if (pmc_base)
-		writel(1, pmc_base + WMT_PRIZM_PMSR_REG);
-}
diff --git a/arch/arm/mach-vt8500/timer.c b/arch/arm/mach-vt8500/timer.c
index d5376c5..050e183 100644
--- a/arch/arm/mach-vt8500/timer.c
+++ b/arch/arm/mach-vt8500/timer.c
@@ -1,6 +1,7 @@
 /*
- *  arch/arm/mach-vt8500/timer.c
+ *  arch/arm/mach-vt8500/timer_dt.c
  *
+ *  Copyright (C) 2012 Tony Prisk <linux@prisktech.co.nz>
  *  Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -18,18 +19,25 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
+/*
+ * This file is copied and modified from the original timer.c provided by
+ * Alexey Charkov. Minor changes have been made for Device Tree Support.
+ */
+
 #include <linux/io.h>
 #include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/clocksource.h>
 #include <linux/clockchips.h>
 #include <linux/delay.h>
-
 #include <asm/mach/time.h>
 
-#include "devices.h"
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 
 #define VT8500_TIMER_OFFSET	0x0100
+#define VT8500_TIMER_HZ		3000000
 #define TIMER_MATCH_VAL		0x0000
 #define TIMER_COUNT_VAL		0x0010
 #define TIMER_STATUS_VAL	0x0014
@@ -39,7 +47,6 @@
 #define TIMER_COUNT_R_ACTIVE	(1 << 5)	/* not ready for read */
 #define TIMER_COUNT_W_ACTIVE	(1 << 4)	/* not ready for write */
 #define TIMER_MATCH_W_ACTIVE	(1 << 0)	/* not ready for write */
-#define VT8500_TIMER_HZ		3000000
 
 #define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t)
 
@@ -55,7 +62,7 @@ static cycle_t vt8500_timer_read(struct clocksource *cs)
 	return readl(regbase + TIMER_COUNT_VAL);
 }
 
-struct clocksource clocksource = {
+static struct clocksource clocksource = {
 	.name           = "vt8500_timer",
 	.rating         = 200,
 	.read           = vt8500_timer_read,
@@ -98,7 +105,7 @@ static void vt8500_timer_set_mode(enum clock_event_mode mode,
 	}
 }
 
-struct clock_event_device clockevent = {
+static struct clock_event_device clockevent = {
 	.name           = "vt8500_timer",
 	.features       = CLOCK_EVT_FEAT_ONESHOT,
 	.rating         = 200,
@@ -115,26 +122,51 @@ static irqreturn_t vt8500_timer_interrupt(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
-struct irqaction irq = {
+static struct irqaction irq = {
 	.name    = "vt8500_timer",
 	.flags   = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
 	.handler = vt8500_timer_interrupt,
 	.dev_id  = &clockevent,
 };
 
-static void __init vt8500_timer_init(void)
+static struct of_device_id vt8500_timer_ids[] = {
+	{ .compatible = "via,vt8500-timer" },
+	{ }
+};
+
+void __init vt8500_timer_init(void)
 {
-	regbase = ioremap(wmt_pmc_base + VT8500_TIMER_OFFSET, 0x28);
-	if (!regbase)
-		printk(KERN_ERR "vt8500_timer_init: failed to map MMIO registers\n");
+	struct device_node *np;
+	int timer_irq;
+
+	np = of_find_matching_node(NULL, vt8500_timer_ids);
+	if (!np) {
+		pr_err("%s: Timer description missing from Device Tree\n",
+								__func__);
+		return;
+	}
+	regbase = of_iomap(np, 0);
+	if (!regbase) {
+		pr_err("%s: Missing iobase description in Device Tree\n",
+								__func__);
+		of_node_put(np);
+		return;
+	}
+	timer_irq = irq_of_parse_and_map(np, 0);
+	if (!timer_irq) {
+		pr_err("%s: Missing irq description in Device Tree\n",
+								__func__);
+		of_node_put(np);
+		return;
+	}
 
 	writel(1, regbase + TIMER_CTRL_VAL);
 	writel(0xf, regbase + TIMER_STATUS_VAL);
 	writel(~0, regbase + TIMER_MATCH_VAL);
 
 	if (clocksource_register_hz(&clocksource, VT8500_TIMER_HZ))
-		printk(KERN_ERR "vt8500_timer_init: clocksource_register failed for %s\n",
-					clocksource.name);
+		pr_err("%s: vt8500_timer_init: clocksource_register failed for %s\n",
+					__func__, clocksource.name);
 
 	clockevents_calc_mult_shift(&clockevent, VT8500_TIMER_HZ, 4);
 
@@ -144,12 +176,9 @@ static void __init vt8500_timer_init(void)
 	clockevent.min_delta_ns = clockevent_delta2ns(4, &clockevent);
 	clockevent.cpumask = cpumask_of(0);
 
-	if (setup_irq(wmt_timer_irq, &irq))
-		printk(KERN_ERR "vt8500_timer_init: setup_irq failed for %s\n",
-					clockevent.name);
+	if (setup_irq(timer_irq, &irq))
+		pr_err("%s: setup_irq failed for %s\n", __func__,
+							clockevent.name);
 	clockevents_register_device(&clockevent);
 }
 
-struct sys_timer vt8500_timer = {
-	.init = vt8500_timer_init
-};
diff --git a/arch/arm/mach-vt8500/vt8500.c b/arch/arm/mach-vt8500/vt8500.c
new file mode 100644
index 0000000..4494993
--- /dev/null
+++ b/arch/arm/mach-vt8500/vt8500.c
@@ -0,0 +1,196 @@
+/*
+ *  arch/arm/mach-vt8500/vt8500.c
+ *
+ *  Copyright (C) 2012 Tony Prisk <linux@prisktech.co.nz>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/io.h>
+#include <linux/pm.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <asm/mach/map.h>
+
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+
+#include <mach/restart.h>
+#include <mach/gpio.h>
+
+#include "common.h"
+
+#define LEGACY_GPIO_BASE	0xD8110000
+#define LEGACY_PMC_BASE		0xD8130000
+
+/* Registers in GPIO Controller */
+#define VT8500_GPIO_MUX_REG	0x200
+
+/* Registers in Power Management Controller */
+#define VT8500_HCR_REG		0x12
+#define VT8500_PMSR_REG		0x60
+
+static void __iomem *pmc_base;
+
+void vt8500_restart(char mode, const char *cmd)
+{
+	if (pmc_base)
+		writel(1, pmc_base + VT8500_PMSR_REG);
+}
+
+static struct map_desc vt8500_io_desc[] __initdata = {
+	/* SoC MMIO registers */
+	[0] = {
+		.virtual	= 0xf8000000,
+		.pfn		= __phys_to_pfn(0xd8000000),
+		.length		= 0x00390000, /* max of all chip variants */
+		.type		= MT_DEVICE
+	},
+};
+
+void __init vt8500_map_io(void)
+{
+	iotable_init(vt8500_io_desc, ARRAY_SIZE(vt8500_io_desc));
+}
+
+static void vt8500_power_off(void)
+{
+	local_irq_disable();
+	writew(5, pmc_base + VT8500_HCR_REG);
+	asm("mcr%? p15, 0, %0, c7, c0, 4" : : "r" (0));
+}
+
+void __init vt8500_init(void)
+{
+	struct device_node *np, *fb;
+	void __iomem *gpio_base;
+
+#ifdef CONFIG_FB_VT8500
+	fb = of_find_compatible_node(NULL, NULL, "via,vt8500-fb");
+	if (fb) {
+		np = of_find_compatible_node(NULL, NULL, "via,vt8500-gpio");
+		if (np) {
+			gpio_base = of_iomap(np, 0);
+
+			if (!gpio_base)
+				pr_err("%s: of_iomap(gpio_mux) failed\n",
+								__func__);
+
+			of_node_put(np);
+		} else {
+			gpio_base = ioremap(LEGACY_GPIO_BASE, 0x1000);
+			if (!gpio_base)
+				pr_err("%s: ioremap(legacy_gpio_mux) failed\n",
+								__func__);
+		}
+		if (gpio_base) {
+			writel(readl(gpio_base + VT8500_GPIO_MUX_REG) | 1,
+				gpio_base + VT8500_GPIO_MUX_REG);
+			iounmap(gpio_base);
+		} else
+			pr_err("%s: Could not remap GPIO mux\n", __func__);
+
+		of_node_put(fb);
+	}
+#endif
+
+#ifdef CONFIG_FB_WM8505
+	fb = of_find_compatible_node(NULL, NULL, "wm,wm8505-fb");
+	if (fb) {
+		np = of_find_compatible_node(NULL, NULL, "wm,wm8505-gpio");
+		if (!np)
+			np = of_find_compatible_node(NULL, NULL,
+							"wm,wm8650-gpio");
+		if (np) {
+			gpio_base = of_iomap(np, 0);
+
+			if (!gpio_base)
+				pr_err("%s: of_iomap(gpio_mux) failed\n",
+								__func__);
+
+			of_node_put(np);
+		} else {
+			gpio_base = ioremap(LEGACY_GPIO_BASE, 0x1000);
+			if (!gpio_base)
+				pr_err("%s: ioremap(legacy_gpio_mux) failed\n",
+								__func__);
+		}
+		if (gpio_base) {
+			writel(readl(gpio_base + VT8500_GPIO_MUX_REG) |
+				0x80000000, gpio_base + VT8500_GPIO_MUX_REG);
+			iounmap(gpio_base);
+		} else
+			pr_err("%s: Could not remap GPIO mux\n", __func__);
+
+		of_node_put(fb);
+	}
+#endif
+
+	np = of_find_compatible_node(NULL, NULL, "via,vt8500-pmc");
+	if (np) {
+		pmc_base = of_iomap(np, 0);
+
+		if (!pmc_base)
+			pr_err("%s:of_iomap(pmc) failed\n", __func__);
+
+		of_node_put(np);
+	} else {
+		pmc_base = ioremap(LEGACY_PMC_BASE, 0x1000);
+		if (!pmc_base)
+			pr_err("%s:ioremap(power_off) failed\n", __func__);
+	}
+	if (pmc_base)
+		pm_power_off = &vt8500_power_off;
+	else
+		pr_err("%s: PMC Hibernation register could not be remapped, not enabling power off!\n", __func__);
+
+	vtwm_clk_init(pmc_base);
+
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+}
+
+static const struct of_device_id vt8500_irq_match[] __initconst = {
+	{ .compatible = "via,vt8500-intc", .data = vt8500_irq_init, },
+	{ /* sentinel */ },
+};
+
+static void __init vt8500_init_irq(void)
+{
+	of_irq_init(vt8500_irq_match);
+};
+
+static struct sys_timer vt8500_timer = {
+	.init = vt8500_timer_init,
+};
+
+static const char * const vt8500_dt_compat[] = {
+	"via,vt8500",
+	"wm,wm8650",
+	"wm,wm8505",
+};
+
+DT_MACHINE_START(WMT_DT, "VIA/Wondermedia SoC (Device Tree Support)")
+	.dt_compat	= vt8500_dt_compat,
+	.map_io		= vt8500_map_io,
+	.init_irq	= vt8500_init_irq,
+	.timer		= &vt8500_timer,
+	.init_machine	= vt8500_init,
+	.restart	= vt8500_restart,
+MACHINE_END
+
diff --git a/arch/arm/mach-vt8500/wm8505_7in.c b/arch/arm/mach-vt8500/wm8505_7in.c
deleted file mode 100644
index db19886..0000000
--- a/arch/arm/mach-vt8500/wm8505_7in.c
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- *  arch/arm/mach-vt8500/wm8505_7in.c
- *
- *  Copyright (C) 2010 Alexey Charkov <alchark@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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <linux/io.h>
-#include <linux/pm.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <mach/restart.h>
-
-#include "devices.h"
-
-static void __iomem *pmc_hiber;
-
-static struct platform_device *devices[] __initdata = {
-	&vt8500_device_uart0,
-	&vt8500_device_ehci,
-	&vt8500_device_wm8505_fb,
-	&vt8500_device_ge_rops,
-	&vt8500_device_pwm,
-	&vt8500_device_pwmbl,
-	&vt8500_device_rtc,
-};
-
-static void vt8500_power_off(void)
-{
-	local_irq_disable();
-	writew(5, pmc_hiber);
-	asm("mcr%? p15, 0, %0, c7, c0, 4" : : "r" (0));
-}
-
-void __init wm8505_7in_init(void)
-{
-#ifdef CONFIG_FB_WM8505
-	void __iomem *gpio_mux_reg = ioremap(wmt_gpio_base + 0x200, 4);
-	if (gpio_mux_reg) {
-		writel(readl(gpio_mux_reg) | 0x80000000, gpio_mux_reg);
-		iounmap(gpio_mux_reg);
-	} else {
-		printk(KERN_ERR "Could not remap the GPIO mux register, display may not work properly!\n");
-	}
-#endif
-	pmc_hiber = ioremap(wmt_pmc_base + 0x12, 2);
-	if (pmc_hiber)
-		pm_power_off = &vt8500_power_off;
-	else
-		printk(KERN_ERR "PMC Hibernation register could not be remapped, not enabling power off!\n");
-	wmt_setup_restart();
-	wm8505_set_resources();
-	platform_add_devices(devices, ARRAY_SIZE(devices));
-	vt8500_gpio_init();
-}
-
-MACHINE_START(WM8505_7IN_NETBOOK, "WM8505 7-inch generic netbook")
-	.atag_offset	= 0x100,
-	.restart	= wmt_restart,
-	.reserve	= wm8505_reserve_mem,
-	.map_io		= wm8505_map_io,
-	.init_irq	= wm8505_init_irq,
-	.timer		= &vt8500_timer,
-	.init_machine	= wm8505_7in_init,
-MACHINE_END
diff --git a/arch/arm/mach-w90x900/dev.c b/arch/arm/mach-w90x900/dev.c
index 48f5b9f..7abdb96 100644
--- a/arch/arm/mach-w90x900/dev.c
+++ b/arch/arm/mach-w90x900/dev.c
@@ -34,11 +34,11 @@
 #include <asm/mach-types.h>
 
 #include <mach/regs-serial.h>
-#include <mach/nuc900_spi.h>
+#include <linux/platform_data/spi-nuc900.h>
 #include <mach/map.h>
-#include <mach/fb.h>
+#include <linux/platform_data/video-nuc900fb.h>
 #include <mach/regs-ldm.h>
-#include <mach/w90p910_keypad.h>
+#include <linux/platform_data/keypad-w90p910.h>
 
 #include "cpu.h"
 
diff --git a/arch/arm/mach-w90x900/include/mach/fb.h b/arch/arm/mach-w90x900/include/mach/fb.h
deleted file mode 100644
index cec5ece..0000000
--- a/arch/arm/mach-w90x900/include/mach/fb.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/* linux/include/asm/arch-nuc900/fb.h
- *
- * Copyright (c) 2008 Nuvoton technology corporation
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * Changelog:
- *
- *   2008/08/26     vincen.zswan modify this file for LCD.
- */
-
-#ifndef __ASM_ARM_FB_H
-#define __ASM_ARM_FB_H
-
-
-
-/* LCD Controller Hardware Desc */
-struct nuc900fb_hw {
-	unsigned int lcd_dccs;
-	unsigned int lcd_device_ctrl;
-	unsigned int lcd_mpulcd_cmd;
-	unsigned int lcd_int_cs;
-	unsigned int lcd_crtc_size;
-	unsigned int lcd_crtc_dend;
-	unsigned int lcd_crtc_hr;
-	unsigned int lcd_crtc_hsync;
-	unsigned int lcd_crtc_vr;
-	unsigned int lcd_va_baddr0;
-	unsigned int lcd_va_baddr1;
-	unsigned int lcd_va_fbctrl;
-	unsigned int lcd_va_scale;
-	unsigned int lcd_va_test;
-	unsigned int lcd_va_win;
-	unsigned int lcd_va_stuff;
-};
-
-/* LCD Display Description */
-struct nuc900fb_display {
-	/* LCD Image type */
-	unsigned type;
-
-	/* LCD Screen Size */
-	unsigned short width;
-	unsigned short height;
-
-	/* LCD Screen Info */
-	unsigned short xres;
-	unsigned short yres;
-	unsigned short bpp;
-
-	unsigned long pixclock;
-	unsigned short left_margin;
-	unsigned short right_margin;
-	unsigned short hsync_len;
-	unsigned short upper_margin;
-	unsigned short lower_margin;
-	unsigned short vsync_len;
-
-	/* hardware special register value */
-	unsigned int dccs;
-	unsigned int devctl;
-	unsigned int fbctrl;
-	unsigned int scale;
-};
-
-struct nuc900fb_mach_info {
-	struct nuc900fb_display *displays;
-	unsigned num_displays;
-	unsigned default_display;
-	/* GPIO Setting  Info */
-	unsigned gpio_dir;
-	unsigned gpio_dir_mask;
-	unsigned gpio_data;
-	unsigned gpio_data_mask;
-};
-
-extern void __init nuc900_fb_set_platdata(struct nuc900fb_mach_info *);
-
-#endif /* __ASM_ARM_FB_H */
diff --git a/arch/arm/mach-w90x900/include/mach/i2c.h b/arch/arm/mach-w90x900/include/mach/i2c.h
deleted file mode 100644
index 9ffb12d..0000000
--- a/arch/arm/mach-w90x900/include/mach/i2c.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef __ASM_ARCH_NUC900_I2C_H
-#define __ASM_ARCH_NUC900_I2C_H
-
-struct nuc900_platform_i2c {
-	int		bus_num;
-	unsigned long   bus_freq;
-};
-
-#endif /* __ASM_ARCH_NUC900_I2C_H */
diff --git a/arch/arm/mach-w90x900/include/mach/nuc900_spi.h b/arch/arm/mach-w90x900/include/mach/nuc900_spi.h
deleted file mode 100644
index 2c4e0c1..0000000
--- a/arch/arm/mach-w90x900/include/mach/nuc900_spi.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * arch/arm/mach-w90x900/include/mach/nuc900_spi.h
- *
- * Copyright (c) 2009 Nuvoton technology corporation.
- *
- * Wan ZongShun <mcuos.com@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;version 2 of the License.
- *
- */
-
-#ifndef __ASM_ARCH_SPI_H
-#define __ASM_ARCH_SPI_H
-
-extern void mfp_set_groupg(struct device *dev, const char *subname);
-
-struct nuc900_spi_info {
-	unsigned int num_cs;
-	unsigned int lsb;
-	unsigned int txneg;
-	unsigned int rxneg;
-	unsigned int divider;
-	unsigned int sleep;
-	unsigned int txnum;
-	unsigned int txbitlen;
-	int bus_num;
-};
-
-struct nuc900_spi_chip {
-	unsigned char bits_per_word;
-};
-
-#endif /* __ASM_ARCH_SPI_H */
diff --git a/arch/arm/mach-w90x900/include/mach/w90p910_keypad.h b/arch/arm/mach-w90x900/include/mach/w90p910_keypad.h
deleted file mode 100644
index 556778e..0000000
--- a/arch/arm/mach-w90x900/include/mach/w90p910_keypad.h
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifndef __ASM_ARCH_W90P910_KEYPAD_H
-#define __ASM_ARCH_W90P910_KEYPAD_H
-
-#include <linux/input/matrix_keypad.h>
-
-extern void mfp_set_groupi(struct device *dev);
-
-struct w90p910_keypad_platform_data {
-	const struct matrix_keymap_data *keymap_data;
-
-	unsigned int	prescale;
-	unsigned int	debounce;
-};
-
-#endif /* __ASM_ARCH_W90P910_KEYPAD_H */
diff --git a/arch/arm/mach-w90x900/mach-nuc950evb.c b/arch/arm/mach-w90x900/mach-nuc950evb.c
index 067d8f9..500fe59 100644
--- a/arch/arm/mach-w90x900/mach-nuc950evb.c
+++ b/arch/arm/mach-w90x900/mach-nuc950evb.c
@@ -20,7 +20,7 @@
 #include <asm/mach/map.h>
 #include <asm/mach-types.h>
 #include <mach/map.h>
-#include <mach/fb.h>
+#include <linux/platform_data/video-nuc900fb.h>
 
 #include "nuc950.h"
 
diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c
index 9107231..b9f60eb 100644
--- a/arch/arm/mm/alignment.c
+++ b/arch/arm/mm/alignment.c
@@ -699,7 +699,6 @@ do_alignment_t32_to_handler(unsigned long *pinstr, struct pt_regs *regs,
 	unsigned long instr = *pinstr;
 	u16 tinst1 = (instr >> 16) & 0xffff;
 	u16 tinst2 = instr & 0xffff;
-	poffset->un = 0;
 
 	switch (tinst1 & 0xffe0) {
 	/* A6.3.5 Load/Store multiple */
@@ -854,9 +853,10 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
 		break;
 
 	case 0x08000000:	/* ldm or stm, or thumb-2 32bit instruction */
-		if (thumb2_32b)
+		if (thumb2_32b) {
+			offset.un = 0;
 			handler = do_alignment_t32_to_handler(&instr, regs, &offset);
-		else
+		} else
 			handler = do_alignment_ldmstm;
 		break;
 
diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c
index 2a8e380..8a97e64 100644
--- a/arch/arm/mm/cache-l2x0.c
+++ b/arch/arm/mm/cache-l2x0.c
@@ -368,14 +368,18 @@ void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask)
 		/* l2x0 controller is disabled */
 		writel_relaxed(aux, l2x0_base + L2X0_AUX_CTRL);
 
-		l2x0_saved_regs.aux_ctrl = aux;
-
 		l2x0_inv_all();
 
 		/* enable L2X0 */
 		writel_relaxed(1, l2x0_base + L2X0_CTRL);
 	}
 
+	/* Re-read it in case some bits are reserved. */
+	aux = readl_relaxed(l2x0_base + L2X0_AUX_CTRL);
+
+	/* Save the value for resuming. */
+	l2x0_saved_regs.aux_ctrl = aux;
+
 	outer_cache.inv_range = l2x0_inv_range;
 	outer_cache.clean_range = l2x0_clean_range;
 	outer_cache.flush_range = l2x0_flush_range;
@@ -554,7 +558,7 @@ static const struct of_device_id l2x0_ids[] __initconst = {
 int __init l2x0_of_init(u32 aux_val, u32 aux_mask)
 {
 	struct device_node *np;
-	struct l2x0_of_data *data;
+	const struct l2x0_of_data *data;
 	struct resource res;
 
 	np = of_find_matching_node(NULL, l2x0_ids);
diff --git a/arch/arm/mm/cache-tauros2.c b/arch/arm/mm/cache-tauros2.c
index 23a7643..1be0f4e 100644
--- a/arch/arm/mm/cache-tauros2.c
+++ b/arch/arm/mm/cache-tauros2.c
@@ -15,8 +15,11 @@
  */
 
 #include <linux/init.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
 #include <asm/cacheflush.h>
 #include <asm/cp15.h>
+#include <asm/cputype.h>
 #include <asm/hardware/cache-tauros2.h>
 
 
@@ -144,25 +147,8 @@ static inline void __init write_extra_features(u32 u)
 	__asm__("mcr p15, 1, %0, c15, c1, 0" : : "r" (u));
 }
 
-static void __init disable_l2_prefetch(void)
-{
-	u32 u;
-
-	/*
-	 * Read the CPU Extra Features register and verify that the
-	 * Disable L2 Prefetch bit is set.
-	 */
-	u = read_extra_features();
-	if (!(u & 0x01000000)) {
-		printk(KERN_INFO "Tauros2: Disabling L2 prefetch.\n");
-		write_extra_features(u | 0x01000000);
-	}
-}
-
 static inline int __init cpuid_scheme(void)
 {
-	extern int processor_id;
-
 	return !!((processor_id & 0x000f0000) == 0x000f0000);
 }
 
@@ -189,12 +175,36 @@ static inline void __init write_actlr(u32 actlr)
 	__asm__("mcr p15, 0, %0, c1, c0, 1\n" : : "r" (actlr));
 }
 
-void __init tauros2_init(void)
+static void enable_extra_feature(unsigned int features)
+{
+	u32 u;
+
+	u = read_extra_features();
+
+	if (features & CACHE_TAUROS2_PREFETCH_ON)
+		u &= ~0x01000000;
+	else
+		u |= 0x01000000;
+	printk(KERN_INFO "Tauros2: %s L2 prefetch.\n",
+			(features & CACHE_TAUROS2_PREFETCH_ON)
+			? "Enabling" : "Disabling");
+
+	if (features & CACHE_TAUROS2_LINEFILL_BURST8)
+		u |= 0x00100000;
+	else
+		u &= ~0x00100000;
+	printk(KERN_INFO "Tauros2: %s line fill burt8.\n",
+			(features & CACHE_TAUROS2_LINEFILL_BURST8)
+			? "Enabling" : "Disabling");
+
+	write_extra_features(u);
+}
+
+static void __init tauros2_internal_init(unsigned int features)
 {
-	extern int processor_id;
-	char *mode;
+	char *mode = NULL;
 
-	disable_l2_prefetch();
+	enable_extra_feature(features);
 
 #ifdef CONFIG_CPU_32v5
 	if ((processor_id & 0xff0f0000) == 0x56050000) {
@@ -286,3 +296,34 @@ void __init tauros2_init(void)
 	printk(KERN_INFO "Tauros2: L2 cache support initialised "
 			 "in %s mode.\n", mode);
 }
+
+#ifdef CONFIG_OF
+static const struct of_device_id tauros2_ids[] __initconst = {
+	{ .compatible = "marvell,tauros2-cache"},
+	{}
+};
+#endif
+
+void __init tauros2_init(unsigned int features)
+{
+#ifdef CONFIG_OF
+	struct device_node *node;
+	int ret;
+	unsigned int f;
+
+	node = of_find_matching_node(NULL, tauros2_ids);
+	if (!node) {
+		pr_info("Not found marvell,tauros2-cache, disable it\n");
+		return;
+	}
+
+	ret = of_property_read_u32(node, "marvell,tauros2-cache-features", &f);
+	if (ret) {
+		pr_info("Not found marvell,tauros-cache-features property, "
+			"disable extra features\n");
+		features = 0;
+	} else
+		features = f;
+#endif
+	tauros2_internal_init(features);
+}
diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S
index 39e3fb3..3b17227 100644
--- a/arch/arm/mm/cache-v7.S
+++ b/arch/arm/mm/cache-v7.S
@@ -211,6 +211,9 @@ ENTRY(v7_coherent_user_range)
  * isn't mapped, fail with -EFAULT.
  */
 9001:
+#ifdef CONFIG_ARM_ERRATA_775420
+	dsb
+#endif
 	mov	r0, #-EFAULT
 	mov	pc, lr
  UNWIND(.fnend		)
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index e59c4ab..477a2d2 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -73,11 +73,18 @@ static dma_addr_t arm_dma_map_page(struct device *dev, struct page *page,
 	     unsigned long offset, size_t size, enum dma_data_direction dir,
 	     struct dma_attrs *attrs)
 {
-	if (!arch_is_coherent() && !dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs))
+	if (!dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs))
 		__dma_page_cpu_to_dev(page, offset, size, dir);
 	return pfn_to_dma(dev, page_to_pfn(page)) + offset;
 }
 
+static dma_addr_t arm_coherent_dma_map_page(struct device *dev, struct page *page,
+	     unsigned long offset, size_t size, enum dma_data_direction dir,
+	     struct dma_attrs *attrs)
+{
+	return pfn_to_dma(dev, page_to_pfn(page)) + offset;
+}
+
 /**
  * arm_dma_unmap_page - unmap a buffer previously mapped through dma_map_page()
  * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
@@ -96,7 +103,7 @@ static void arm_dma_unmap_page(struct device *dev, dma_addr_t handle,
 		size_t size, enum dma_data_direction dir,
 		struct dma_attrs *attrs)
 {
-	if (!arch_is_coherent() && !dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs))
+	if (!dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs))
 		__dma_page_dev_to_cpu(pfn_to_page(dma_to_pfn(dev, handle)),
 				      handle & ~PAGE_MASK, size, dir);
 }
@@ -106,8 +113,7 @@ static void arm_dma_sync_single_for_cpu(struct device *dev,
 {
 	unsigned int offset = handle & (PAGE_SIZE - 1);
 	struct page *page = pfn_to_page(dma_to_pfn(dev, handle-offset));
-	if (!arch_is_coherent())
-		__dma_page_dev_to_cpu(page, offset, size, dir);
+	__dma_page_dev_to_cpu(page, offset, size, dir);
 }
 
 static void arm_dma_sync_single_for_device(struct device *dev,
@@ -115,8 +121,7 @@ static void arm_dma_sync_single_for_device(struct device *dev,
 {
 	unsigned int offset = handle & (PAGE_SIZE - 1);
 	struct page *page = pfn_to_page(dma_to_pfn(dev, handle-offset));
-	if (!arch_is_coherent())
-		__dma_page_cpu_to_dev(page, offset, size, dir);
+	__dma_page_cpu_to_dev(page, offset, size, dir);
 }
 
 static int arm_dma_set_mask(struct device *dev, u64 dma_mask);
@@ -138,6 +143,22 @@ struct dma_map_ops arm_dma_ops = {
 };
 EXPORT_SYMBOL(arm_dma_ops);
 
+static void *arm_coherent_dma_alloc(struct device *dev, size_t size,
+	dma_addr_t *handle, gfp_t gfp, struct dma_attrs *attrs);
+static void arm_coherent_dma_free(struct device *dev, size_t size, void *cpu_addr,
+				  dma_addr_t handle, struct dma_attrs *attrs);
+
+struct dma_map_ops arm_coherent_dma_ops = {
+	.alloc			= arm_coherent_dma_alloc,
+	.free			= arm_coherent_dma_free,
+	.mmap			= arm_dma_mmap,
+	.get_sgtable		= arm_dma_get_sgtable,
+	.map_page		= arm_coherent_dma_map_page,
+	.map_sg			= arm_dma_map_sg,
+	.set_dma_mask		= arm_dma_set_mask,
+};
+EXPORT_SYMBOL(arm_coherent_dma_ops);
+
 static u64 get_coherent_dma_mask(struct device *dev)
 {
 	u64 mask = (u64)arm_dma_limit;
@@ -346,6 +367,8 @@ static int __init atomic_pool_init(void)
 		       (unsigned)pool->size / 1024);
 		return 0;
 	}
+
+	kfree(pages);
 no_pages:
 	kfree(bitmap);
 no_bitmap:
@@ -584,7 +607,7 @@ static void *__alloc_simple_buffer(struct device *dev, size_t size, gfp_t gfp,
 
 
 static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
-			 gfp_t gfp, pgprot_t prot, const void *caller)
+			 gfp_t gfp, pgprot_t prot, bool is_coherent, const void *caller)
 {
 	u64 mask = get_coherent_dma_mask(dev);
 	struct page *page;
@@ -617,7 +640,7 @@ static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
 	*handle = DMA_ERROR_CODE;
 	size = PAGE_ALIGN(size);
 
-	if (arch_is_coherent() || nommu())
+	if (is_coherent || nommu())
 		addr = __alloc_simple_buffer(dev, size, gfp, &page);
 	else if (gfp & GFP_ATOMIC)
 		addr = __alloc_from_pool(size, &page);
@@ -645,7 +668,20 @@ void *arm_dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
 	if (dma_alloc_from_coherent(dev, size, handle, &memory))
 		return memory;
 
-	return __dma_alloc(dev, size, handle, gfp, prot,
+	return __dma_alloc(dev, size, handle, gfp, prot, false,
+			   __builtin_return_address(0));
+}
+
+static void *arm_coherent_dma_alloc(struct device *dev, size_t size,
+	dma_addr_t *handle, gfp_t gfp, struct dma_attrs *attrs)
+{
+	pgprot_t prot = __get_dma_pgprot(attrs, pgprot_kernel);
+	void *memory;
+
+	if (dma_alloc_from_coherent(dev, size, handle, &memory))
+		return memory;
+
+	return __dma_alloc(dev, size, handle, gfp, prot, true,
 			   __builtin_return_address(0));
 }
 
@@ -682,8 +718,9 @@ int arm_dma_mmap(struct device *dev, struct vm_area_struct *vma,
 /*
  * Free a buffer as defined by the above mapping.
  */
-void arm_dma_free(struct device *dev, size_t size, void *cpu_addr,
-		  dma_addr_t handle, struct dma_attrs *attrs)
+static void __arm_dma_free(struct device *dev, size_t size, void *cpu_addr,
+			   dma_addr_t handle, struct dma_attrs *attrs,
+			   bool is_coherent)
 {
 	struct page *page = pfn_to_page(dma_to_pfn(dev, handle));
 
@@ -692,7 +729,7 @@ void arm_dma_free(struct device *dev, size_t size, void *cpu_addr,
 
 	size = PAGE_ALIGN(size);
 
-	if (arch_is_coherent() || nommu()) {
+	if (is_coherent || nommu()) {
 		__dma_free_buffer(page, size);
 	} else if (__free_from_pool(cpu_addr, size)) {
 		return;
@@ -708,6 +745,18 @@ void arm_dma_free(struct device *dev, size_t size, void *cpu_addr,
 	}
 }
 
+void arm_dma_free(struct device *dev, size_t size, void *cpu_addr,
+		  dma_addr_t handle, struct dma_attrs *attrs)
+{
+	__arm_dma_free(dev, size, cpu_addr, handle, attrs, false);
+}
+
+static void arm_coherent_dma_free(struct device *dev, size_t size, void *cpu_addr,
+				  dma_addr_t handle, struct dma_attrs *attrs)
+{
+	__arm_dma_free(dev, size, cpu_addr, handle, attrs, true);
+}
+
 int arm_dma_get_sgtable(struct device *dev, struct sg_table *sgt,
 		 void *cpu_addr, dma_addr_t handle, size_t size,
 		 struct dma_attrs *attrs)
@@ -1010,11 +1059,12 @@ static struct page **__iommu_alloc_buffer(struct device *dev, size_t size, gfp_t
 		if (!pages[i])
 			goto error;
 
-		if (order)
+		if (order) {
 			split_page(pages[i], order);
-		j = 1 << order;
-		while (--j)
-			pages[i + j] = pages[i] + j;
+			j = 1 << order;
+			while (--j)
+				pages[i + j] = pages[i] + j;
+		}
 
 		__dma_clear_buffer(pages[i], PAGE_SIZE << order);
 		i += 1 << order;
@@ -1301,7 +1351,8 @@ static int arm_iommu_get_sgtable(struct device *dev, struct sg_table *sgt,
  */
 static int __map_sg_chunk(struct device *dev, struct scatterlist *sg,
 			  size_t size, dma_addr_t *handle,
-			  enum dma_data_direction dir, struct dma_attrs *attrs)
+			  enum dma_data_direction dir, struct dma_attrs *attrs,
+			  bool is_coherent)
 {
 	struct dma_iommu_mapping *mapping = dev->archdata.mapping;
 	dma_addr_t iova, iova_base;
@@ -1320,8 +1371,8 @@ static int __map_sg_chunk(struct device *dev, struct scatterlist *sg,
 		phys_addr_t phys = page_to_phys(sg_page(s));
 		unsigned int len = PAGE_ALIGN(s->offset + s->length);
 
-		if (!arch_is_coherent() &&
-		    !dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs))
+		if (!is_coherent &&
+			!dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs))
 			__dma_page_cpu_to_dev(sg_page(s), s->offset, s->length, dir);
 
 		ret = iommu_map(mapping->domain, iova, phys, len, 0);
@@ -1339,20 +1390,9 @@ fail:
 	return ret;
 }
 
-/**
- * arm_iommu_map_sg - map a set of SG buffers for streaming mode DMA
- * @dev: valid struct device pointer
- * @sg: list of buffers
- * @nents: number of buffers to map
- * @dir: DMA transfer direction
- *
- * Map a set of buffers described by scatterlist in streaming mode for DMA.
- * The scatter gather list elements are merged together (if possible) and
- * tagged with the appropriate dma address and length. They are obtained via
- * sg_dma_{address,length}.
- */
-int arm_iommu_map_sg(struct device *dev, struct scatterlist *sg, int nents,
-		     enum dma_data_direction dir, struct dma_attrs *attrs)
+static int __iommu_map_sg(struct device *dev, struct scatterlist *sg, int nents,
+		     enum dma_data_direction dir, struct dma_attrs *attrs,
+		     bool is_coherent)
 {
 	struct scatterlist *s = sg, *dma = sg, *start = sg;
 	int i, count = 0;
@@ -1368,7 +1408,7 @@ int arm_iommu_map_sg(struct device *dev, struct scatterlist *sg, int nents,
 
 		if (s->offset || (size & ~PAGE_MASK) || size + s->length > max) {
 			if (__map_sg_chunk(dev, start, size, &dma->dma_address,
-			    dir, attrs) < 0)
+			    dir, attrs, is_coherent) < 0)
 				goto bad_mapping;
 
 			dma->dma_address += offset;
@@ -1381,7 +1421,8 @@ int arm_iommu_map_sg(struct device *dev, struct scatterlist *sg, int nents,
 		}
 		size += s->length;
 	}
-	if (__map_sg_chunk(dev, start, size, &dma->dma_address, dir, attrs) < 0)
+	if (__map_sg_chunk(dev, start, size, &dma->dma_address, dir, attrs,
+		is_coherent) < 0)
 		goto bad_mapping;
 
 	dma->dma_address += offset;
@@ -1396,17 +1437,44 @@ bad_mapping:
 }
 
 /**
- * arm_iommu_unmap_sg - unmap a set of SG buffers mapped by dma_map_sg
+ * arm_coherent_iommu_map_sg - map a set of SG buffers for streaming mode DMA
  * @dev: valid struct device pointer
  * @sg: list of buffers
- * @nents: number of buffers to unmap (same as was passed to dma_map_sg)
- * @dir: DMA transfer direction (same as was passed to dma_map_sg)
+ * @nents: number of buffers to map
+ * @dir: DMA transfer direction
  *
- * Unmap a set of streaming mode DMA translations.  Again, CPU access
- * rules concerning calls here are the same as for dma_unmap_single().
+ * Map a set of i/o coherent buffers described by scatterlist in streaming
+ * mode for DMA. The scatter gather list elements are merged together (if
+ * possible) and tagged with the appropriate dma address and length. They are
+ * obtained via sg_dma_{address,length}.
  */
-void arm_iommu_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
-			enum dma_data_direction dir, struct dma_attrs *attrs)
+int arm_coherent_iommu_map_sg(struct device *dev, struct scatterlist *sg,
+		int nents, enum dma_data_direction dir, struct dma_attrs *attrs)
+{
+	return __iommu_map_sg(dev, sg, nents, dir, attrs, true);
+}
+
+/**
+ * arm_iommu_map_sg - map a set of SG buffers for streaming mode DMA
+ * @dev: valid struct device pointer
+ * @sg: list of buffers
+ * @nents: number of buffers to map
+ * @dir: DMA transfer direction
+ *
+ * Map a set of buffers described by scatterlist in streaming mode for DMA.
+ * The scatter gather list elements are merged together (if possible) and
+ * tagged with the appropriate dma address and length. They are obtained via
+ * sg_dma_{address,length}.
+ */
+int arm_iommu_map_sg(struct device *dev, struct scatterlist *sg,
+		int nents, enum dma_data_direction dir, struct dma_attrs *attrs)
+{
+	return __iommu_map_sg(dev, sg, nents, dir, attrs, false);
+}
+
+static void __iommu_unmap_sg(struct device *dev, struct scatterlist *sg,
+		int nents, enum dma_data_direction dir, struct dma_attrs *attrs,
+		bool is_coherent)
 {
 	struct scatterlist *s;
 	int i;
@@ -1415,7 +1483,7 @@ void arm_iommu_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
 		if (sg_dma_len(s))
 			__iommu_remove_mapping(dev, sg_dma_address(s),
 					       sg_dma_len(s));
-		if (!arch_is_coherent() &&
+		if (!is_coherent &&
 		    !dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs))
 			__dma_page_dev_to_cpu(sg_page(s), s->offset,
 					      s->length, dir);
@@ -1423,6 +1491,38 @@ void arm_iommu_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
 }
 
 /**
+ * arm_coherent_iommu_unmap_sg - unmap a set of SG buffers mapped by dma_map_sg
+ * @dev: valid struct device pointer
+ * @sg: list of buffers
+ * @nents: number of buffers to unmap (same as was passed to dma_map_sg)
+ * @dir: DMA transfer direction (same as was passed to dma_map_sg)
+ *
+ * Unmap a set of streaming mode DMA translations.  Again, CPU access
+ * rules concerning calls here are the same as for dma_unmap_single().
+ */
+void arm_coherent_iommu_unmap_sg(struct device *dev, struct scatterlist *sg,
+		int nents, enum dma_data_direction dir, struct dma_attrs *attrs)
+{
+	__iommu_unmap_sg(dev, sg, nents, dir, attrs, true);
+}
+
+/**
+ * arm_iommu_unmap_sg - unmap a set of SG buffers mapped by dma_map_sg
+ * @dev: valid struct device pointer
+ * @sg: list of buffers
+ * @nents: number of buffers to unmap (same as was passed to dma_map_sg)
+ * @dir: DMA transfer direction (same as was passed to dma_map_sg)
+ *
+ * Unmap a set of streaming mode DMA translations.  Again, CPU access
+ * rules concerning calls here are the same as for dma_unmap_single().
+ */
+void arm_iommu_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
+			enum dma_data_direction dir, struct dma_attrs *attrs)
+{
+	__iommu_unmap_sg(dev, sg, nents, dir, attrs, false);
+}
+
+/**
  * arm_iommu_sync_sg_for_cpu
  * @dev: valid struct device pointer
  * @sg: list of buffers
@@ -1436,8 +1536,7 @@ void arm_iommu_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg,
 	int i;
 
 	for_each_sg(sg, s, nents, i)
-		if (!arch_is_coherent())
-			__dma_page_dev_to_cpu(sg_page(s), s->offset, s->length, dir);
+		__dma_page_dev_to_cpu(sg_page(s), s->offset, s->length, dir);
 
 }
 
@@ -1455,22 +1554,21 @@ void arm_iommu_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
 	int i;
 
 	for_each_sg(sg, s, nents, i)
-		if (!arch_is_coherent())
-			__dma_page_cpu_to_dev(sg_page(s), s->offset, s->length, dir);
+		__dma_page_cpu_to_dev(sg_page(s), s->offset, s->length, dir);
 }
 
 
 /**
- * arm_iommu_map_page
+ * arm_coherent_iommu_map_page
  * @dev: valid struct device pointer
  * @page: page that buffer resides in
  * @offset: offset into page for start of buffer
  * @size: size of buffer to map
  * @dir: DMA transfer direction
  *
- * IOMMU aware version of arm_dma_map_page()
+ * Coherent IOMMU aware version of arm_dma_map_page()
  */
-static dma_addr_t arm_iommu_map_page(struct device *dev, struct page *page,
+static dma_addr_t arm_coherent_iommu_map_page(struct device *dev, struct page *page,
 	     unsigned long offset, size_t size, enum dma_data_direction dir,
 	     struct dma_attrs *attrs)
 {
@@ -1478,9 +1576,6 @@ static dma_addr_t arm_iommu_map_page(struct device *dev, struct page *page,
 	dma_addr_t dma_addr;
 	int ret, len = PAGE_ALIGN(size + offset);
 
-	if (!arch_is_coherent() && !dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs))
-		__dma_page_cpu_to_dev(page, offset, size, dir);
-
 	dma_addr = __alloc_iova(mapping, len);
 	if (dma_addr == DMA_ERROR_CODE)
 		return dma_addr;
@@ -1496,6 +1591,51 @@ fail:
 }
 
 /**
+ * arm_iommu_map_page
+ * @dev: valid struct device pointer
+ * @page: page that buffer resides in
+ * @offset: offset into page for start of buffer
+ * @size: size of buffer to map
+ * @dir: DMA transfer direction
+ *
+ * IOMMU aware version of arm_dma_map_page()
+ */
+static dma_addr_t arm_iommu_map_page(struct device *dev, struct page *page,
+	     unsigned long offset, size_t size, enum dma_data_direction dir,
+	     struct dma_attrs *attrs)
+{
+	if (!dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs))
+		__dma_page_cpu_to_dev(page, offset, size, dir);
+
+	return arm_coherent_iommu_map_page(dev, page, offset, size, dir, attrs);
+}
+
+/**
+ * arm_coherent_iommu_unmap_page
+ * @dev: valid struct device pointer
+ * @handle: DMA address of buffer
+ * @size: size of buffer (same as passed to dma_map_page)
+ * @dir: DMA transfer direction (same as passed to dma_map_page)
+ *
+ * Coherent IOMMU aware version of arm_dma_unmap_page()
+ */
+static void arm_coherent_iommu_unmap_page(struct device *dev, dma_addr_t handle,
+		size_t size, enum dma_data_direction dir,
+		struct dma_attrs *attrs)
+{
+	struct dma_iommu_mapping *mapping = dev->archdata.mapping;
+	dma_addr_t iova = handle & PAGE_MASK;
+	int offset = handle & ~PAGE_MASK;
+	int len = PAGE_ALIGN(size + offset);
+
+	if (!iova)
+		return;
+
+	iommu_unmap(mapping->domain, iova, len);
+	__free_iova(mapping, iova, len);
+}
+
+/**
  * arm_iommu_unmap_page
  * @dev: valid struct device pointer
  * @handle: DMA address of buffer
@@ -1517,7 +1657,7 @@ static void arm_iommu_unmap_page(struct device *dev, dma_addr_t handle,
 	if (!iova)
 		return;
 
-	if (!arch_is_coherent() && !dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs))
+	if (!dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs))
 		__dma_page_dev_to_cpu(page, offset, size, dir);
 
 	iommu_unmap(mapping->domain, iova, len);
@@ -1535,8 +1675,7 @@ static void arm_iommu_sync_single_for_cpu(struct device *dev,
 	if (!iova)
 		return;
 
-	if (!arch_is_coherent())
-		__dma_page_dev_to_cpu(page, offset, size, dir);
+	__dma_page_dev_to_cpu(page, offset, size, dir);
 }
 
 static void arm_iommu_sync_single_for_device(struct device *dev,
@@ -1570,6 +1709,19 @@ struct dma_map_ops iommu_ops = {
 	.sync_sg_for_device	= arm_iommu_sync_sg_for_device,
 };
 
+struct dma_map_ops iommu_coherent_ops = {
+	.alloc		= arm_iommu_alloc_attrs,
+	.free		= arm_iommu_free_attrs,
+	.mmap		= arm_iommu_mmap_attrs,
+	.get_sgtable	= arm_iommu_get_sgtable,
+
+	.map_page	= arm_coherent_iommu_map_page,
+	.unmap_page	= arm_coherent_iommu_unmap_page,
+
+	.map_sg		= arm_coherent_iommu_map_sg,
+	.unmap_sg	= arm_coherent_iommu_unmap_sg,
+};
+
 /**
  * arm_iommu_create_mapping
  * @bus: pointer to the bus holding the client device (for IOMMU calls)
@@ -1663,7 +1815,7 @@ int arm_iommu_attach_device(struct device *dev,
 	dev->archdata.mapping = mapping;
 	set_dma_ops(dev, &iommu_ops);
 
-	pr_info("Attached IOMMU controller to %s device.\n", dev_name(dev));
+	pr_debug("Attached IOMMU controller to %s device.\n", dev_name(dev));
 	return 0;
 }
 
diff --git a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c
index 7599e26..2a5907b 100644
--- a/arch/arm/mm/fault-armv.c
+++ b/arch/arm/mm/fault-armv.c
@@ -134,7 +134,6 @@ make_coherent(struct address_space *mapping, struct vm_area_struct *vma,
 {
 	struct mm_struct *mm = vma->vm_mm;
 	struct vm_area_struct *mpnt;
-	struct prio_tree_iter iter;
 	unsigned long offset;
 	pgoff_t pgoff;
 	int aliases = 0;
@@ -147,7 +146,7 @@ make_coherent(struct address_space *mapping, struct vm_area_struct *vma,
 	 * cache coherency.
 	 */
 	flush_dcache_mmap_lock(mapping);
-	vma_prio_tree_foreach(mpnt, &iter, &mapping->i_mmap, pgoff, pgoff) {
+	vma_interval_tree_foreach(mpnt, &mapping->i_mmap, pgoff, pgoff) {
 		/*
 		 * If this VMA is not in our MM, we can ignore it.
 		 * Note that we intentionally mask out the VMA
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c
index c3bd834..5dbf13f 100644
--- a/arch/arm/mm/fault.c
+++ b/arch/arm/mm/fault.c
@@ -336,6 +336,7 @@ retry:
 			/* Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk
 			* of starvation. */
 			flags &= ~FAULT_FLAG_ALLOW_RETRY;
+			flags |= FAULT_FLAG_TRIED;
 			goto retry;
 		}
 	}
diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c
index 40ca11e..1c8f7f5 100644
--- a/arch/arm/mm/flush.c
+++ b/arch/arm/mm/flush.c
@@ -196,7 +196,6 @@ static void __flush_dcache_aliases(struct address_space *mapping, struct page *p
 {
 	struct mm_struct *mm = current->active_mm;
 	struct vm_area_struct *mpnt;
-	struct prio_tree_iter iter;
 	pgoff_t pgoff;
 
 	/*
@@ -208,7 +207,7 @@ static void __flush_dcache_aliases(struct address_space *mapping, struct page *p
 	pgoff = page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT);
 
 	flush_dcache_mmap_lock(mapping);
-	vma_prio_tree_foreach(mpnt, &iter, &mapping->i_mmap, pgoff, pgoff) {
+	vma_interval_tree_foreach(mpnt, &mapping->i_mmap, pgoff, pgoff) {
 		unsigned long offset;
 
 		/*
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index 9aec41f..ad722f1 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -324,7 +324,7 @@ phys_addr_t __init arm_memblock_steal(phys_addr_t size, phys_addr_t align)
 
 	BUG_ON(!arm_memblock_steal_permitted);
 
-	phys = memblock_alloc(size, align);
+	phys = memblock_alloc_base(size, align, MEMBLOCK_ALLOC_ANYWHERE);
 	memblock_free(phys, size);
 	memblock_remove(phys, size);
 
diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c
index 566750f..9d869f9 100644
--- a/arch/arm/mm/ioremap.c
+++ b/arch/arm/mm/ioremap.c
@@ -36,6 +36,7 @@
 #include <asm/system_info.h>
 
 #include <asm/mach/map.h>
+#include <asm/mach/pci.h>
 #include "mm.h"
 
 int ioremap_page(unsigned long virt, unsigned long phys,
@@ -383,3 +384,16 @@ void __arm_iounmap(volatile void __iomem *io_addr)
 	arch_iounmap(io_addr);
 }
 EXPORT_SYMBOL(__arm_iounmap);
+
+#ifdef CONFIG_PCI
+int pci_ioremap_io(unsigned int offset, phys_addr_t phys_addr)
+{
+	BUG_ON(offset + SZ_64K > IO_SPACE_LIMIT);
+
+	return ioremap_page_range(PCI_IO_VIRT_BASE + offset,
+				  PCI_IO_VIRT_BASE + offset + SZ_64K,
+				  phys_addr,
+				  __pgprot(get_mem_type(MT_DEVICE)->prot_pte));
+}
+EXPORT_SYMBOL_GPL(pci_ioremap_io);
+#endif
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index c2fa21d..941dfb9 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -31,6 +31,7 @@
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
+#include <asm/mach/pci.h>
 
 #include "mm.h"
 
@@ -216,7 +217,7 @@ static struct mem_type mem_types[] = {
 		.prot_l1	= PMD_TYPE_TABLE,
 		.prot_sect	= PROT_SECT_DEVICE | PMD_SECT_WB,
 		.domain		= DOMAIN_IO,
-	},	
+	},
 	[MT_DEVICE_WC] = {	/* ioremap_wc */
 		.prot_pte	= PROT_PTE_DEVICE | L_PTE_MT_DEV_WC,
 		.prot_l1	= PMD_TYPE_TABLE,
@@ -422,17 +423,6 @@ static void __init build_mem_type_table(void)
 	vecs_pgprot = kern_pgprot = user_pgprot = cp->pte;
 
 	/*
-	 * Enable CPU-specific coherency if supported.
-	 * (Only available on XSC3 at the moment.)
-	 */
-	if (arch_is_coherent() && cpu_is_xsc3()) {
-		mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S;
-		mem_types[MT_MEMORY].prot_pte |= L_PTE_SHARED;
-		mem_types[MT_MEMORY_DMA_READY].prot_pte |= L_PTE_SHARED;
-		mem_types[MT_MEMORY_NONCACHED].prot_sect |= PMD_SECT_S;
-		mem_types[MT_MEMORY_NONCACHED].prot_pte |= L_PTE_SHARED;
-	}
-	/*
 	 * ARMv6 and above have extended page tables.
 	 */
 	if (cpu_arch >= CPU_ARCH_ARMv6 && (cr & CR_XP)) {
@@ -777,14 +767,27 @@ void __init iotable_init(struct map_desc *io_desc, int nr)
 		create_mapping(md);
 		vm->addr = (void *)(md->virtual & PAGE_MASK);
 		vm->size = PAGE_ALIGN(md->length + (md->virtual & ~PAGE_MASK));
-		vm->phys_addr = __pfn_to_phys(md->pfn); 
-		vm->flags = VM_IOREMAP | VM_ARM_STATIC_MAPPING; 
+		vm->phys_addr = __pfn_to_phys(md->pfn);
+		vm->flags = VM_IOREMAP | VM_ARM_STATIC_MAPPING;
 		vm->flags |= VM_ARM_MTYPE(md->type);
 		vm->caller = iotable_init;
 		vm_area_add_early(vm++);
 	}
 }
 
+void __init vm_reserve_area_early(unsigned long addr, unsigned long size,
+				  void *caller)
+{
+	struct vm_struct *vm;
+
+	vm = early_alloc_aligned(sizeof(*vm), __alignof__(*vm));
+	vm->addr = (void *)addr;
+	vm->size = size;
+	vm->flags = VM_IOREMAP | VM_ARM_EMPTY_MAPPING;
+	vm->caller = caller;
+	vm_area_add_early(vm);
+}
+
 #ifndef CONFIG_ARM_LPAE
 
 /*
@@ -802,14 +805,7 @@ void __init iotable_init(struct map_desc *io_desc, int nr)
 
 static void __init pmd_empty_section_gap(unsigned long addr)
 {
-	struct vm_struct *vm;
-
-	vm = early_alloc_aligned(sizeof(*vm), __alignof__(*vm));
-	vm->addr = (void *)addr;
-	vm->size = SECTION_SIZE;
-	vm->flags = VM_IOREMAP | VM_ARM_EMPTY_MAPPING;
-	vm->caller = pmd_empty_section_gap;
-	vm_area_add_early(vm);
+	vm_reserve_area_early(addr, SECTION_SIZE, pmd_empty_section_gap);
 }
 
 static void __init fill_pmd_gaps(void)
@@ -858,6 +854,28 @@ static void __init fill_pmd_gaps(void)
 #define fill_pmd_gaps() do { } while (0)
 #endif
 
+#if defined(CONFIG_PCI) && !defined(CONFIG_NEED_MACH_IO_H)
+static void __init pci_reserve_io(void)
+{
+	struct vm_struct *vm;
+	unsigned long addr;
+
+	/* we're still single threaded hence no lock needed here */
+	for (vm = vmlist; vm; vm = vm->next) {
+		if (!(vm->flags & VM_ARM_STATIC_MAPPING))
+			continue;
+		addr = (unsigned long)vm->addr;
+		addr &= ~(SZ_2M - 1);
+		if (addr == PCI_IO_VIRT_BASE)
+			return;
+
+	}
+	vm_reserve_area_early(PCI_IO_VIRT_BASE, SZ_2M, pci_reserve_io);
+}
+#else
+#define pci_reserve_io() do { } while (0)
+#endif
+
 static void * __initdata vmalloc_min =
 	(void *)(VMALLOC_END - (240 << 20) - VMALLOC_OFFSET);
 
@@ -1141,6 +1159,9 @@ static void __init devicemaps_init(struct machine_desc *mdesc)
 		mdesc->map_io();
 	fill_pmd_gaps();
 
+	/* Reserve fixed i/o space in VMALLOC region */
+	pci_reserve_io();
+
 	/*
 	 * Finally flush the caches and tlb to ensure that we're in a
 	 * consistent state wrt the writebuffer.  This also ensures that
diff --git a/arch/arm/mm/proc-v7-2level.S b/arch/arm/mm/proc-v7-2level.S
index fd045e7..9207b9f 100644
--- a/arch/arm/mm/proc-v7-2level.S
+++ b/arch/arm/mm/proc-v7-2level.S
@@ -103,9 +103,17 @@ ENTRY(cpu_v7_set_pte_ext)
 	tstne	r1, #L_PTE_PRESENT
 	moveq	r3, #0
 
+#ifdef CONFIG_ARM_ERRATA_782773
+	mrs	r2, cpsr			@ save cpsr
+	cpsid	if				@ disable interrupts
+	mcr	p15, 0, r0, c7, c14, 1		@ clean & invalidate D line
+#endif
  ARM(	str	r3, [r0, #2048]! )
  THUMB(	add	r0, r0, #2048 )
  THUMB(	str	r3, [r0] )
+#ifdef CONFIG_ARM_ERRATA_782773
+	msr	cpsr_c, r2			@ load cpsr
+#endif
 	mcr	p15, 0, r0, c7, c10, 1		@ flush_pte
 #endif
 	mov	pc, lr
diff --git a/arch/arm/plat-iop/pci.c b/arch/arm/plat-iop/pci.c
index 8daae9b..362474b 100644
--- a/arch/arm/plat-iop/pci.c
+++ b/arch/arm/plat-iop/pci.c
@@ -192,30 +192,24 @@ int iop3xx_pci_setup(int nr, struct pci_sys_data *sys)
 	if (nr != 0)
 		return 0;
 
-	res = kzalloc(2 * sizeof(struct resource), GFP_KERNEL);
+	res = kzalloc(sizeof(struct resource), GFP_KERNEL);
 	if (!res)
 		panic("PCI: unable to alloc resources");
 
-	res[0].start = IOP3XX_PCI_LOWER_IO_PA;
-	res[0].end   = IOP3XX_PCI_LOWER_IO_PA + IOP3XX_PCI_IO_WINDOW_SIZE - 1;
-	res[0].name  = "IOP3XX PCI I/O Space";
-	res[0].flags = IORESOURCE_IO;
-	request_resource(&ioport_resource, &res[0]);
-
-	res[1].start = IOP3XX_PCI_LOWER_MEM_PA;
-	res[1].end   = IOP3XX_PCI_LOWER_MEM_PA + IOP3XX_PCI_MEM_WINDOW_SIZE - 1;
-	res[1].name  = "IOP3XX PCI Memory Space";
-	res[1].flags = IORESOURCE_MEM;
-	request_resource(&iomem_resource, &res[1]);
+	res->start = IOP3XX_PCI_LOWER_MEM_PA;
+	res->end   = IOP3XX_PCI_LOWER_MEM_PA + IOP3XX_PCI_MEM_WINDOW_SIZE - 1;
+	res->name  = "IOP3XX PCI Memory Space";
+	res->flags = IORESOURCE_MEM;
+	request_resource(&iomem_resource, res);
 
 	/*
 	 * Use whatever translation is already setup.
 	 */
 	sys->mem_offset = IOP3XX_PCI_LOWER_MEM_PA - *IOP3XX_OMWTVR0;
-	sys->io_offset  = IOP3XX_PCI_LOWER_IO_PA - *IOP3XX_OIOWTVR;
 
-	pci_add_resource_offset(&sys->resources, &res[0], sys->io_offset);
-	pci_add_resource_offset(&sys->resources, &res[1], sys->mem_offset);
+	pci_add_resource_offset(&sys->resources, res, sys->mem_offset);
+
+	pci_ioremap_io(0, IOP3XX_PCI_LOWER_IO_PA);
 
 	return 1;
 }
@@ -367,7 +361,6 @@ void __init iop3xx_pci_preinit_cond(void)
 
 void __init iop3xx_pci_preinit(void)
 {
-	pcibios_min_io = 0;
 	pcibios_min_mem = 0;
 
 	iop3xx_atu_disable();
diff --git a/arch/arm/plat-iop/pmu.c b/arch/arm/plat-iop/pmu.c
index a2024b8..ad9f974 100644
--- a/arch/arm/plat-iop/pmu.c
+++ b/arch/arm/plat-iop/pmu.c
@@ -9,7 +9,6 @@
  */
 
 #include <linux/platform_device.h>
-#include <asm/pmu.h>
 #include <mach/irqs.h>
 
 static struct resource pmu_resource = {
@@ -26,7 +25,7 @@ static struct resource pmu_resource = {
 
 static struct platform_device pmu_device = {
 	.name		= "arm-pmu",
-	.id		= ARM_PMU_DEVICE_CPU,
+	.id		= -1,
 	.resource	= &pmu_resource,
 	.num_resources	= 1,
 };
diff --git a/arch/arm/plat-iop/setup.c b/arch/arm/plat-iop/setup.c
index bade586..5b217f4 100644
--- a/arch/arm/plat-iop/setup.c
+++ b/arch/arm/plat-iop/setup.c
@@ -25,11 +25,6 @@ static struct map_desc iop3xx_std_desc[] __initdata = {
 		.pfn		= __phys_to_pfn(IOP3XX_PERIPHERAL_PHYS_BASE),
 		.length		= IOP3XX_PERIPHERAL_SIZE,
 		.type		= MT_UNCACHED,
-	 }, {	/* PCI IO space */
-		.virtual	= IOP3XX_PCI_LOWER_IO_VA,
-		.pfn		= __phys_to_pfn(IOP3XX_PCI_LOWER_IO_PA),
-		.length		= IOP3XX_PCI_IO_WINDOW_SIZE,
-		.type		= MT_DEVICE,
 	 },
 };
 
diff --git a/arch/arm/plat-mxc/Makefile b/arch/arm/plat-mxc/Makefile
index 6ac7200..149237e 100644
--- a/arch/arm/plat-mxc/Makefile
+++ b/arch/arm/plat-mxc/Makefile
@@ -3,7 +3,7 @@
 #
 
 # Common support
-obj-y := clock.o time.o devices.o cpu.o system.o irq-common.o
+obj-y := time.o devices.o cpu.o system.o irq-common.o
 
 obj-$(CONFIG_MXC_TZIC) += tzic.o
 obj-$(CONFIG_MXC_AVIC) += avic.o
diff --git a/arch/arm/plat-mxc/clock.c b/arch/arm/plat-mxc/clock.c
deleted file mode 100644
index 5079787..0000000
--- a/arch/arm/plat-mxc/clock.c
+++ /dev/null
@@ -1,257 +0,0 @@
-/*
- * Based on arch/arm/plat-omap/clock.c
- *
- * Copyright (C) 2004 - 2005 Nokia corporation
- * Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
- * Modified for omap shared clock framework by Tony Lindgren <tony@atomide.com>
- * Copyright 2007 Freescale Semiconductor, Inc. All Rights Reserved.
- * 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.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA  02110-1301, USA.
- */
-
-/* #define DEBUG */
-
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/platform_device.h>
-#include <linux/proc_fs.h>
-#include <linux/semaphore.h>
-#include <linux/string.h>
-
-#include <mach/clock.h>
-#include <mach/hardware.h>
-
-#ifndef CONFIG_COMMON_CLK
-static LIST_HEAD(clocks);
-static DEFINE_MUTEX(clocks_mutex);
-
-/*-------------------------------------------------------------------------
- * Standard clock functions defined in include/linux/clk.h
- *-------------------------------------------------------------------------*/
-
-static void __clk_disable(struct clk *clk)
-{
-	if (clk == NULL || IS_ERR(clk))
-		return;
-	WARN_ON(!clk->usecount);
-
-	if (!(--clk->usecount)) {
-		if (clk->disable)
-			clk->disable(clk);
-		__clk_disable(clk->parent);
-		__clk_disable(clk->secondary);
-	}
-}
-
-static int __clk_enable(struct clk *clk)
-{
-	if (clk == NULL || IS_ERR(clk))
-		return -EINVAL;
-
-	if (clk->usecount++ == 0) {
-		__clk_enable(clk->parent);
-		__clk_enable(clk->secondary);
-
-		if (clk->enable)
-			clk->enable(clk);
-	}
-	return 0;
-}
-
-/* This function increments the reference count on the clock and enables the
- * clock if not already enabled. The parent clock tree is recursively enabled
- */
-int clk_enable(struct clk *clk)
-{
-	int ret = 0;
-
-	if (clk == NULL || IS_ERR(clk))
-		return -EINVAL;
-
-	mutex_lock(&clocks_mutex);
-	ret = __clk_enable(clk);
-	mutex_unlock(&clocks_mutex);
-
-	return ret;
-}
-EXPORT_SYMBOL(clk_enable);
-
-/* This function decrements the reference count on the clock and disables
- * the clock when reference count is 0. The parent clock tree is
- * recursively disabled
- */
-void clk_disable(struct clk *clk)
-{
-	if (clk == NULL || IS_ERR(clk))
-		return;
-
-	mutex_lock(&clocks_mutex);
-	__clk_disable(clk);
-	mutex_unlock(&clocks_mutex);
-}
-EXPORT_SYMBOL(clk_disable);
-
-/* Retrieve the *current* clock rate. If the clock itself
- * does not provide a special calculation routine, ask
- * its parent and so on, until one is able to return
- * a valid clock rate
- */
-unsigned long clk_get_rate(struct clk *clk)
-{
-	if (clk == NULL || IS_ERR(clk))
-		return 0UL;
-
-	if (clk->get_rate)
-		return clk->get_rate(clk);
-
-	return clk_get_rate(clk->parent);
-}
-EXPORT_SYMBOL(clk_get_rate);
-
-/* Round the requested clock rate to the nearest supported
- * rate that is less than or equal to the requested rate.
- * This is dependent on the clock's current parent.
- */
-long clk_round_rate(struct clk *clk, unsigned long rate)
-{
-	if (clk == NULL || IS_ERR(clk) || !clk->round_rate)
-		return 0;
-
-	return clk->round_rate(clk, rate);
-}
-EXPORT_SYMBOL(clk_round_rate);
-
-/* Set the clock to the requested clock rate. The rate must
- * match a supported rate exactly based on what clk_round_rate returns
- */
-int clk_set_rate(struct clk *clk, unsigned long rate)
-{
-	int ret = -EINVAL;
-
-	if (clk == NULL || IS_ERR(clk) || clk->set_rate == NULL || rate == 0)
-		return ret;
-
-	mutex_lock(&clocks_mutex);
-	ret = clk->set_rate(clk, rate);
-	mutex_unlock(&clocks_mutex);
-
-	return ret;
-}
-EXPORT_SYMBOL(clk_set_rate);
-
-/* Set the clock's parent to another clock source */
-int clk_set_parent(struct clk *clk, struct clk *parent)
-{
-	int ret = -EINVAL;
-	struct clk *old;
-
-	if (clk == NULL || IS_ERR(clk) || parent == NULL ||
-	    IS_ERR(parent) || clk->set_parent == NULL)
-		return ret;
-
-	if (clk->usecount)
-		clk_enable(parent);
-
-	mutex_lock(&clocks_mutex);
-	ret = clk->set_parent(clk, parent);
-	if (ret == 0) {
-		old = clk->parent;
-		clk->parent = parent;
-	} else {
-		old = parent;
-	}
-	mutex_unlock(&clocks_mutex);
-
-	if (clk->usecount)
-		clk_disable(old);
-
-	return ret;
-}
-EXPORT_SYMBOL(clk_set_parent);
-
-/* Retrieve the clock's parent clock source */
-struct clk *clk_get_parent(struct clk *clk)
-{
-	struct clk *ret = NULL;
-
-	if (clk == NULL || IS_ERR(clk))
-		return ret;
-
-	return clk->parent;
-}
-EXPORT_SYMBOL(clk_get_parent);
-
-#else
-
-/*
- * Lock to protect the clock module (ccm) registers. Used
- * on all i.MXs
- */
-DEFINE_SPINLOCK(imx_ccm_lock);
-
-#endif /* CONFIG_COMMON_CLK */
-
-/*
- * 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;
-
-	/* On all i.MXs except i.MX1 and i.MX21 mfn is a 10bit
-	 * 2's complements number
-	 */
-	if (!cpu_is_mx1() && !cpu_is_mx21() && mfn >= 0x200)
-		mfn_abs = 0x400 - mfn;
-
-	freq *= 2;
-	freq /= pd + 1;
-
-	ll = (unsigned long long)freq * mfn_abs;
-
-	do_div(ll, mfd + 1);
-
-	if (!cpu_is_mx1() && !cpu_is_mx21() && mfn >= 0x200)
-		ll = -ll;
-
-	ll = (freq * mfi) + ll;
-
-	return ll;
-}
diff --git a/arch/arm/plat-mxc/cpufreq.c b/arch/arm/plat-mxc/cpufreq.c
index 73db34b..b5b6f80 100644
--- a/arch/arm/plat-mxc/cpufreq.c
+++ b/arch/arm/plat-mxc/cpufreq.c
@@ -23,7 +23,6 @@
 #include <linux/err.h>
 #include <linux/slab.h>
 #include <mach/hardware.h>
-#include <mach/clock.h>
 
 #define CLK32_FREQ	32768
 #define NANOSECOND	(1000 * 1000 * 1000)
diff --git a/arch/arm/plat-mxc/devices/Kconfig b/arch/arm/plat-mxc/devices/Kconfig
index cb3e3ee..6b46cee 100644
--- a/arch/arm/plat-mxc/devices/Kconfig
+++ b/arch/arm/plat-mxc/devices/Kconfig
@@ -15,7 +15,11 @@ config IMX_HAVE_PLATFORM_GPIO_KEYS
 
 config IMX_HAVE_PLATFORM_IMX21_HCD
 	bool
-	
+
+config IMX_HAVE_PLATFORM_IMX27_CODA
+	bool
+	default y if SOC_IMX27
+
 config IMX_HAVE_PLATFORM_IMX2_WDT
 	bool
 
diff --git a/arch/arm/plat-mxc/devices/Makefile b/arch/arm/plat-mxc/devices/Makefile
index c11ac84..76f3195 100644
--- a/arch/arm/plat-mxc/devices/Makefile
+++ b/arch/arm/plat-mxc/devices/Makefile
@@ -4,6 +4,7 @@ obj-$(CONFIG_IMX_HAVE_PLATFORM_FSL_USB2_UDC) += platform-fsl-usb2-udc.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_GPIO_KEYS) += platform-gpio_keys.o
 obj-y += platform-gpio-mxc.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX21_HCD) += platform-imx21-hcd.o
+obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX27_CODA) += platform-imx27-coda.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX2_WDT) += platform-imx2-wdt.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_IMXDI_RTC) += platform-imxdi_rtc.o
 obj-y += platform-imx-dma.o
diff --git a/arch/arm/plat-mxc/devices/platform-imx-uart.c b/arch/arm/plat-mxc/devices/platform-imx-uart.c
index 2020d84..d390f00 100644
--- a/arch/arm/plat-mxc/devices/platform-imx-uart.c
+++ b/arch/arm/plat-mxc/devices/platform-imx-uart.c
@@ -87,7 +87,7 @@ const struct imx_imx_uart_1irq_data imx31_imx_uart_data[] __initconst = {
 #ifdef CONFIG_SOC_IMX35
 const struct imx_imx_uart_1irq_data imx35_imx_uart_data[] __initconst = {
 #define imx35_imx_uart_data_entry(_id, _hwid)				\
-	imx_imx_uart_1irq_data_entry(MX31, _id, _hwid, SZ_16K)
+	imx_imx_uart_1irq_data_entry(MX35, _id, _hwid, SZ_16K)
 	imx35_imx_uart_data_entry(0, 1),
 	imx35_imx_uart_data_entry(1, 2),
 	imx35_imx_uart_data_entry(2, 3),
diff --git a/arch/arm/plat-mxc/devices/platform-imx27-coda.c b/arch/arm/plat-mxc/devices/platform-imx27-coda.c
new file mode 100644
index 0000000..8b12aac
--- /dev/null
+++ b/arch/arm/plat-mxc/devices/platform-imx27-coda.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2012 Vista Silicon
+ * Javier Martin <javier.martin@vista-silicon.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 <mach/hardware.h>
+#include <mach/devices-common.h>
+
+#ifdef CONFIG_SOC_IMX27
+const struct imx_imx27_coda_data imx27_coda_data __initconst = {
+	.iobase = MX27_VPU_BASE_ADDR,
+	.iosize = SZ_512,
+	.irq = MX27_INT_VPU,
+};
+#endif
+
+struct platform_device *__init imx_add_imx27_coda(
+		const struct imx_imx27_coda_data *data)
+{
+	struct resource res[] = {
+		{
+			.start = data->iobase,
+			.end = data->iobase + data->iosize - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = data->irq,
+			.end = data->irq,
+			.flags = IORESOURCE_IRQ,
+		},
+	};
+	return imx_add_platform_device_dmamask("coda-imx27", 0, res, 2, NULL,
+					0, DMA_BIT_MASK(32));
+}
diff --git a/arch/arm/plat-mxc/devices/platform-mxc_nand.c b/arch/arm/plat-mxc/devices/platform-mxc_nand.c
index 1568f39..95b75cc 100644
--- a/arch/arm/plat-mxc/devices/platform-mxc_nand.c
+++ b/arch/arm/plat-mxc/devices/platform-mxc_nand.c
@@ -63,10 +63,6 @@ struct platform_device *__init imx_add_mxc_nand(
 	/* AXI has to come first, that's how the mxc_nand driver expect it */
 	struct resource res[] = {
 		{
-			.start = data->axibase,
-			.end = data->axibase + SZ_16K - 1,
-			.flags = IORESOURCE_MEM,
-		}, {
 			.start = data->iobase,
 			.end = data->iobase + data->iosize - 1,
 			.flags = IORESOURCE_MEM,
@@ -74,10 +70,13 @@ struct platform_device *__init imx_add_mxc_nand(
 			.start = data->irq,
 			.end = data->irq,
 			.flags = IORESOURCE_IRQ,
+		}, {
+			.start = data->axibase,
+			.end = data->axibase + SZ_16K - 1,
+			.flags = IORESOURCE_MEM,
 		},
 	};
 	return imx_add_platform_device("mxc_nand", data->id,
-			res + !data->axibase,
-			ARRAY_SIZE(res) - !data->axibase,
+			res, ARRAY_SIZE(res) - !data->axibase,
 			pdata, sizeof(*pdata));
 }
diff --git a/arch/arm/plat-mxc/devices/platform-sdhci-esdhc-imx.c b/arch/arm/plat-mxc/devices/platform-sdhci-esdhc-imx.c
index 5955f5d..3793e47 100644
--- a/arch/arm/plat-mxc/devices/platform-sdhci-esdhc-imx.c
+++ b/arch/arm/plat-mxc/devices/platform-sdhci-esdhc-imx.c
@@ -8,7 +8,7 @@
 
 #include <mach/hardware.h>
 #include <mach/devices-common.h>
-#include <mach/esdhc.h>
+#include <linux/platform_data/mmc-esdhc-imx.h>
 
 #define imx_sdhci_esdhc_imx_data_entry_single(soc, _devid, _id, hwid) \
 	{								\
diff --git a/arch/arm/plat-mxc/include/mach/clock.h b/arch/arm/plat-mxc/include/mach/clock.h
deleted file mode 100644
index bd940c7..0000000
--- a/arch/arm/plat-mxc/include/mach/clock.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright 2005-2007 Freescale Semiconductor, Inc. All Rights Reserved.
- * 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.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You 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_CLOCK_H__
-#define __ASM_ARCH_MXC_CLOCK_H__
-
-#ifndef __ASSEMBLY__
-#include <linux/list.h>
-
-#ifndef CONFIG_COMMON_CLK
-struct module;
-
-struct clk {
-	int id;
-	/* Source clock this clk depends on */
-	struct clk *parent;
-	/* Secondary clock to enable/disable with this clock */
-	struct clk *secondary;
-	/* Reference count of clock enable/disable */
-	__s8 usecount;
-	/* Register bit position for clock's enable/disable control. */
-	u8 enable_shift;
-	/* Register address for clock's enable/disable control. */
-	void __iomem *enable_reg;
-	u32 flags;
-	/* get the current clock rate (always a fresh value) */
-	unsigned long (*get_rate) (struct clk *);
-	/* Function ptr to set the clock to a new rate. The rate must match a
-	   supported rate returned from round_rate. Leave blank if clock is not
-	   programmable */
-	int (*set_rate) (struct clk *, unsigned long);
-	/* Function ptr to round the requested clock rate to the nearest
-	   supported rate that is less than or equal to the requested rate. */
-	unsigned long (*round_rate) (struct clk *, unsigned long);
-	/* Function ptr to enable the clock. Leave blank if clock can not
-	   be gated. */
-	int (*enable) (struct clk *);
-	/* Function ptr to disable the clock. Leave blank if clock can not
-	   be gated. */
-	void (*disable) (struct clk *);
-	/* Function ptr to set the parent clock of the clock. */
-	int (*set_parent) (struct clk *, struct clk *);
-};
-
-int clk_register(struct clk *clk);
-void clk_unregister(struct clk *clk);
-#endif /* CONFIG_COMMON_CLK */
-
-extern spinlock_t imx_ccm_lock;
-
-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 7128e97..ead9018 100644
--- a/arch/arm/plat-mxc/include/mach/common.h
+++ b/arch/arm/plat-mxc/include/mach/common.h
@@ -52,7 +52,6 @@ extern void imx31_soc_init(void);
 extern void imx35_soc_init(void);
 extern void imx50_soc_init(void);
 extern void imx51_soc_init(void);
-extern void imx53_soc_init(void);
 extern void imx51_init_late(void);
 extern void imx53_init_late(void);
 extern void epit_timer_init(void __iomem *base, int irq);
@@ -137,14 +136,11 @@ extern void imx_src_prepare_restart(void);
 extern void imx_gpc_init(void);
 extern void imx_gpc_pre_suspend(void);
 extern void imx_gpc_post_resume(void);
-extern void imx51_babbage_common_init(void);
-extern void imx53_ard_common_init(void);
-extern void imx53_evk_common_init(void);
-extern void imx53_qsb_common_init(void);
-extern void imx53_smd_common_init(void);
 extern int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode);
 extern void imx6q_clock_map_io(void);
 
+extern void imx_cpu_die(unsigned int cpu);
+
 #ifdef CONFIG_PM
 extern void imx6q_pm_init(void);
 extern void imx51_pm_init(void);
@@ -161,4 +157,6 @@ extern int mx51_neon_fixup(void);
 static inline int mx51_neon_fixup(void) { return 0; }
 #endif
 
+extern struct smp_operations imx_smp_ops;
+
 #endif
diff --git a/arch/arm/plat-mxc/include/mach/devices-common.h b/arch/arm/plat-mxc/include/mach/devices-common.h
index a7f5bb1..eaf79d2 100644
--- a/arch/arm/plat-mxc/include/mach/devices-common.h
+++ b/arch/arm/plat-mxc/include/mach/devices-common.h
@@ -9,7 +9,7 @@
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/init.h>
-#include <mach/sdma.h>
+#include <linux/platform_data/dma-imx-sdma.h>
 
 extern struct device mxc_aips_bus;
 extern struct device mxc_ahb_bus;
@@ -74,7 +74,7 @@ struct platform_device *__init imx_add_fsl_usb2_udc(
 struct platform_device *__init imx_add_gpio_keys(
 		const struct gpio_keys_platform_data *pdata);
 
-#include <mach/mx21-usbhost.h>
+#include <linux/platform_data/usb-mx2.h>
 struct imx_imx21_hcd_data {
 	resource_size_t iobase;
 	resource_size_t irq;
@@ -83,6 +83,14 @@ struct platform_device *__init imx_add_imx21_hcd(
 		const struct imx_imx21_hcd_data *data,
 		const struct mx21_usbh_platform_data *pdata);
 
+struct imx_imx27_coda_data {
+	resource_size_t iobase;
+	resource_size_t iosize;
+	resource_size_t irq;
+};
+struct platform_device *__init imx_add_imx27_coda(
+		const struct imx_imx27_coda_data *data);
+
 struct imx_imx2_wdt_data {
 	int id;
 	resource_size_t iobase;
@@ -98,7 +106,7 @@ struct imx_imxdi_rtc_data {
 struct platform_device *__init imx_add_imxdi_rtc(
 		const struct imx_imxdi_rtc_data *data);
 
-#include <mach/imxfb.h>
+#include <linux/platform_data/video-imxfb.h>
 struct imx_imx_fb_data {
 	resource_size_t iobase;
 	resource_size_t iosize;
@@ -108,7 +116,7 @@ struct platform_device *__init imx_add_imx_fb(
 		const struct imx_imx_fb_data *data,
 		const struct imx_fb_platform_data *pdata);
 
-#include <mach/i2c.h>
+#include <linux/platform_data/i2c-imx.h>
 struct imx_imx_i2c_data {
 	int id;
 	resource_size_t iobase;
@@ -129,7 +137,7 @@ struct platform_device *__init imx_add_imx_keypad(
 		const struct imx_imx_keypad_data *data,
 		const struct matrix_keymap_data *pdata);
 
-#include <mach/ssi.h>
+#include <linux/platform_data/asoc-imx-ssi.h>
 struct imx_imx_ssi_data {
 	int id;
 	resource_size_t iobase;
@@ -144,7 +152,7 @@ struct platform_device *__init imx_add_imx_ssi(
 		const struct imx_imx_ssi_data *data,
 		const struct imx_ssi_platform_data *pdata);
 
-#include <mach/imx-uart.h>
+#include <linux/platform_data/serial-imx.h>
 struct imx_imx_uart_3irq_data {
 	int id;
 	resource_size_t iobase;
@@ -167,7 +175,7 @@ struct platform_device *__init imx_add_imx_uart_1irq(
 		const struct imx_imx_uart_1irq_data *data,
 		const struct imxuart_platform_data *pdata);
 
-#include <mach/usb.h>
+#include <linux/platform_data/usb-imx_udc.h>
 struct imx_imx_udc_data {
 	resource_size_t iobase;
 	resource_size_t iosize;
@@ -183,8 +191,8 @@ struct platform_device *__init imx_add_imx_udc(
 		const struct imx_imx_udc_data *data,
 		const struct imxusb_platform_data *pdata);
 
-#include <mach/mx3fb.h>
-#include <mach/mx3_camera.h>
+#include <linux/platform_data/video-mx3fb.h>
+#include <linux/platform_data/camera-mx3.h>
 struct imx_ipu_core_data {
 	resource_size_t iobase;
 	resource_size_t synirq;
@@ -199,7 +207,7 @@ struct platform_device *__init imx_add_mx3_sdc_fb(
 		const struct imx_ipu_core_data *data,
 		struct mx3fb_platform_data *pdata);
 
-#include <mach/mx1_camera.h>
+#include <linux/platform_data/camera-mx1.h>
 struct imx_mx1_camera_data {
 	resource_size_t iobase;
 	resource_size_t iosize;
@@ -209,7 +217,7 @@ struct platform_device *__init imx_add_mx1_camera(
 		const struct imx_mx1_camera_data *data,
 		const struct mx1_camera_pdata *pdata);
 
-#include <mach/mx2_cam.h>
+#include <linux/platform_data/camera-mx2.h>
 struct imx_mx2_camera_data {
 	resource_size_t iobasecsi;
 	resource_size_t iosizecsi;
@@ -224,7 +232,7 @@ struct platform_device *__init imx_add_mx2_camera(
 struct platform_device *__init imx_add_mx2_emmaprp(
 		const struct imx_mx2_camera_data *data);
 
-#include <mach/mxc_ehci.h>
+#include <linux/platform_data/usb-ehci-mxc.h>
 struct imx_mxc_ehci_data {
 	int id;
 	resource_size_t iobase;
@@ -234,7 +242,7 @@ struct platform_device *__init imx_add_mxc_ehci(
 		const struct imx_mxc_ehci_data *data,
 		const struct mxc_usbh_platform_data *pdata);
 
-#include <mach/mmc.h>
+#include <linux/platform_data/mmc-mxcmmc.h>
 struct imx_mxc_mmc_data {
 	int id;
 	resource_size_t iobase;
@@ -246,7 +254,7 @@ struct platform_device *__init imx_add_mxc_mmc(
 		const struct imx_mxc_mmc_data *data,
 		const struct imxmmc_platform_data *pdata);
 
-#include <mach/mxc_nand.h>
+#include <linux/platform_data/mtd-mxc_nand.h>
 struct imx_mxc_nand_data {
 	/*
 	 * id is traditionally 0, but -1 is more appropriate.  We use -1 for new
@@ -295,7 +303,7 @@ struct imx_mxc_w1_data {
 struct platform_device *__init imx_add_mxc_w1(
 		const struct imx_mxc_w1_data *data);
 
-#include <mach/esdhc.h>
+#include <linux/platform_data/mmc-esdhc-imx.h>
 struct imx_sdhci_esdhc_imx_data {
 	const char *devid;
 	int id;
@@ -306,7 +314,7 @@ struct platform_device *__init imx_add_sdhci_esdhc_imx(
 		const struct imx_sdhci_esdhc_imx_data *data,
 		const struct esdhc_platform_data *pdata);
 
-#include <mach/spi.h>
+#include <linux/platform_data/spi-imx.h>
 struct imx_spi_imx_data {
 	const char *devid;
 	int id;
diff --git a/arch/arm/plat-mxc/include/mach/dma.h b/arch/arm/plat-mxc/include/mach/dma.h
deleted file mode 100644
index 1b90803..0000000
--- a/arch/arm/plat-mxc/include/mach/dma.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright 2004-2009 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_DMA_H__
-#define __ASM_ARCH_MXC_DMA_H__
-
-#include <linux/scatterlist.h>
-#include <linux/device.h>
-#include <linux/dmaengine.h>
-
-/*
- * This enumerates peripheral types. Used for SDMA.
- */
-enum sdma_peripheral_type {
-	IMX_DMATYPE_SSI,	/* MCU domain SSI */
-	IMX_DMATYPE_SSI_SP,	/* Shared SSI */
-	IMX_DMATYPE_MMC,	/* MMC */
-	IMX_DMATYPE_SDHC,	/* SDHC */
-	IMX_DMATYPE_UART,	/* MCU domain UART */
-	IMX_DMATYPE_UART_SP,	/* Shared UART */
-	IMX_DMATYPE_FIRI,	/* FIRI */
-	IMX_DMATYPE_CSPI,	/* MCU domain CSPI */
-	IMX_DMATYPE_CSPI_SP,	/* Shared CSPI */
-	IMX_DMATYPE_SIM,	/* SIM */
-	IMX_DMATYPE_ATA,	/* ATA */
-	IMX_DMATYPE_CCM,	/* CCM */
-	IMX_DMATYPE_EXT,	/* External peripheral */
-	IMX_DMATYPE_MSHC,	/* Memory Stick Host Controller */
-	IMX_DMATYPE_MSHC_SP,	/* Shared Memory Stick Host Controller */
-	IMX_DMATYPE_DSP,	/* DSP */
-	IMX_DMATYPE_MEMORY,	/* Memory */
-	IMX_DMATYPE_FIFO_MEMORY,/* FIFO type Memory */
-	IMX_DMATYPE_SPDIF,	/* SPDIF */
-	IMX_DMATYPE_IPU_MEMORY,	/* IPU Memory */
-	IMX_DMATYPE_ASRC,	/* ASRC */
-	IMX_DMATYPE_ESAI,	/* ESAI */
-};
-
-enum imx_dma_prio {
-	DMA_PRIO_HIGH = 0,
-	DMA_PRIO_MEDIUM = 1,
-	DMA_PRIO_LOW = 2
-};
-
-struct imx_dma_data {
-	int dma_request; /* DMA request line */
-	enum sdma_peripheral_type peripheral_type;
-	int priority;
-};
-
-static inline int imx_dma_is_ipu(struct dma_chan *chan)
-{
-	return !strcmp(dev_name(chan->device->dev), "ipu-core");
-}
-
-static inline int imx_dma_is_general_purpose(struct dma_chan *chan)
-{
-	return strstr(dev_name(chan->device->dev), "sdma") ||
-		!strcmp(dev_name(chan->device->dev), "imx-dma");
-}
-
-#endif
diff --git a/arch/arm/plat-mxc/include/mach/esdhc.h b/arch/arm/plat-mxc/include/mach/esdhc.h
deleted file mode 100644
index aaf9748..0000000
--- a/arch/arm/plat-mxc/include/mach/esdhc.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright 2010 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; version 2
- * of the License.
- */
-
-#ifndef __ASM_ARCH_IMX_ESDHC_H
-#define __ASM_ARCH_IMX_ESDHC_H
-
-enum wp_types {
-	ESDHC_WP_NONE,		/* no WP, neither controller nor gpio */
-	ESDHC_WP_CONTROLLER,	/* mmc controller internal WP */
-	ESDHC_WP_GPIO,		/* external gpio pin for WP */
-};
-
-enum cd_types {
-	ESDHC_CD_NONE,		/* no CD, neither controller nor gpio */
-	ESDHC_CD_CONTROLLER,	/* mmc controller internal CD */
-	ESDHC_CD_GPIO,		/* external gpio pin for CD */
-	ESDHC_CD_PERMANENT,	/* no CD, card permanently wired to host */
-};
-
-/**
- * struct esdhc_platform_data - platform data for esdhc on i.MX
- *
- * ESDHC_WP(CD)_CONTROLLER type is not available on i.MX25/35.
- *
- * @wp_gpio:	gpio for write_protect
- * @cd_gpio:	gpio for card_detect interrupt
- * @wp_type:	type of write_protect method (see wp_types enum above)
- * @cd_type:	type of card_detect method (see cd_types enum above)
- */
-
-struct esdhc_platform_data {
-	unsigned int wp_gpio;
-	unsigned int cd_gpio;
-	enum wp_types wp_type;
-	enum cd_types cd_type;
-};
-#endif /* __ASM_ARCH_IMX_ESDHC_H */
diff --git a/arch/arm/plat-mxc/include/mach/gpio.h b/arch/arm/plat-mxc/include/mach/gpio.h
deleted file mode 100644
index 40a8c17..0000000
--- a/arch/arm/plat-mxc/include/mach/gpio.h
+++ /dev/null
@@ -1 +0,0 @@
-/* empty */
diff --git a/arch/arm/plat-mxc/include/mach/i2c.h b/arch/arm/plat-mxc/include/mach/i2c.h
deleted file mode 100644
index 8289d91..0000000
--- a/arch/arm/plat-mxc/include/mach/i2c.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * i2c.h - i.MX I2C driver header file
- *
- * Copyright (c) 2008, Darius Augulis <augulis.darius@gmail.com>
- *
- * This file is released under the GPLv2
- */
-
-#ifndef __ASM_ARCH_I2C_H_
-#define __ASM_ARCH_I2C_H_
-
-/**
- * struct imxi2c_platform_data - structure of platform data for MXC I2C driver
- * @bitrate:	Bus speed measured in Hz
- *
- **/
-struct imxi2c_platform_data {
-	u32 bitrate;
-};
-
-#endif /* __ASM_ARCH_I2C_H_ */
diff --git a/arch/arm/plat-mxc/include/mach/imx-uart.h b/arch/arm/plat-mxc/include/mach/imx-uart.h
deleted file mode 100644
index 4adec9b..0000000
--- a/arch/arm/plat-mxc/include/mach/imx-uart.h
+++ /dev/null
@@ -1,35 +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 ASMARM_ARCH_UART_H
-#define ASMARM_ARCH_UART_H
-
-#define IMXUART_HAVE_RTSCTS (1<<0)
-#define IMXUART_IRDA        (1<<1)
-
-struct imxuart_platform_data {
-	int (*init)(struct platform_device *pdev);
-	void (*exit)(struct platform_device *pdev);
-	unsigned int flags;
-	void (*irda_enable)(int enable);
-	unsigned int irda_inv_rx:1;
-	unsigned int irda_inv_tx:1;
-	unsigned short transceiver_delay;
-};
-
-#endif
diff --git a/arch/arm/plat-mxc/include/mach/imxfb.h b/arch/arm/plat-mxc/include/mach/imxfb.h
deleted file mode 100644
index 9de8f06..0000000
--- a/arch/arm/plat-mxc/include/mach/imxfb.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * This structure describes the machine which we are running on.
- */
-#ifndef __MACH_IMXFB_H__
-#define __MACH_IMXFB_H__
-
-#include <linux/fb.h>
-
-#define PCR_TFT		(1 << 31)
-#define PCR_COLOR	(1 << 30)
-#define PCR_PBSIZ_1	(0 << 28)
-#define PCR_PBSIZ_2	(1 << 28)
-#define PCR_PBSIZ_4	(2 << 28)
-#define PCR_PBSIZ_8	(3 << 28)
-#define PCR_BPIX_1	(0 << 25)
-#define PCR_BPIX_2	(1 << 25)
-#define PCR_BPIX_4	(2 << 25)
-#define PCR_BPIX_8	(3 << 25)
-#define PCR_BPIX_12	(4 << 25)
-#define PCR_BPIX_16	(5 << 25)
-#define PCR_BPIX_18	(6 << 25)
-#define PCR_PIXPOL	(1 << 24)
-#define PCR_FLMPOL	(1 << 23)
-#define PCR_LPPOL	(1 << 22)
-#define PCR_CLKPOL	(1 << 21)
-#define PCR_OEPOL	(1 << 20)
-#define PCR_SCLKIDLE	(1 << 19)
-#define PCR_END_SEL	(1 << 18)
-#define PCR_END_BYTE_SWAP (1 << 17)
-#define PCR_REV_VS	(1 << 16)
-#define PCR_ACD_SEL	(1 << 15)
-#define PCR_ACD(x)	(((x) & 0x7f) << 8)
-#define PCR_SCLK_SEL	(1 << 7)
-#define PCR_SHARP	(1 << 6)
-#define PCR_PCD(x)	((x) & 0x3f)
-
-#define PWMR_CLS(x)	(((x) & 0x1ff) << 16)
-#define PWMR_LDMSK	(1 << 15)
-#define PWMR_SCR1	(1 << 10)
-#define PWMR_SCR0	(1 << 9)
-#define PWMR_CC_EN	(1 << 8)
-#define PWMR_PW(x)	((x) & 0xff)
-
-#define LSCR1_PS_RISE_DELAY(x)    (((x) & 0x7f) << 26)
-#define LSCR1_CLS_RISE_DELAY(x)   (((x) & 0x3f) << 16)
-#define LSCR1_REV_TOGGLE_DELAY(x) (((x) & 0xf) << 8)
-#define LSCR1_GRAY2(x)            (((x) & 0xf) << 4)
-#define LSCR1_GRAY1(x)            (((x) & 0xf))
-
-#define DMACR_BURST	(1 << 31)
-#define DMACR_HM(x)	(((x) & 0xf) << 16)
-#define DMACR_TM(x)	((x) & 0xf)
-
-struct imx_fb_videomode {
-	struct fb_videomode mode;
-	u32 pcr;
-	unsigned char	bpp;
-};
-
-struct imx_fb_platform_data {
-	struct imx_fb_videomode *mode;
-	int		num_modes;
-
-	u_int		cmap_greyscale:1,
-			cmap_inverse:1,
-			cmap_static:1,
-			unused:29;
-
-	u_int		pwmr;
-	u_int		lscr1;
-	u_int		dmacr;
-
-	u_char * fixed_screen_cpu;
-	dma_addr_t fixed_screen_dma;
-
-	int (*init)(struct platform_device *);
-	void (*exit)(struct platform_device *);
-
-	void (*lcd_power)(int);
-	void (*backlight_power)(int);
-};
-
-void set_imx_fb_info(struct imx_fb_platform_data *);
-#endif /* ifndef __MACH_IMXFB_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx3.h b/arch/arm/plat-mxc/include/mach/iomux-mx3.h
index d8b65b5..f79f78a 100644
--- a/arch/arm/plat-mxc/include/mach/iomux-mx3.h
+++ b/arch/arm/plat-mxc/include/mach/iomux-mx3.h
@@ -512,12 +512,16 @@ enum iomux_pins {
 #define MX31_PIN_CSPI3_SPI_RDY__CTS3	IOMUX_MODE(MX31_PIN_CSPI3_SPI_RDY, IOMUX_CONFIG_ALT1)
 #define MX31_PIN_CTS1__CTS1		IOMUX_MODE(MX31_PIN_CTS1, IOMUX_CONFIG_FUNC)
 #define MX31_PIN_RTS1__RTS1		IOMUX_MODE(MX31_PIN_RTS1, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_RTS1__SFS		IOMUX_MODE(MX31_PIN_RTS1, IOMUX_CONFIG_ALT2)
 #define MX31_PIN_TXD1__TXD1		IOMUX_MODE(MX31_PIN_TXD1, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_TXD1__SCK		IOMUX_MODE(MX31_PIN_TXD1, IOMUX_CONFIG_ALT2)
 #define MX31_PIN_RXD1__RXD1		IOMUX_MODE(MX31_PIN_RXD1, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_RXD1__STXDA		IOMUX_MODE(MX31_PIN_RXD1, IOMUX_CONFIG_ALT2)
 #define MX31_PIN_DCD_DCE1__DCD_DCE1	IOMUX_MODE(MX31_PIN_DCD_DCE1, IOMUX_CONFIG_FUNC)
 #define MX31_PIN_RI_DCE1__RI_DCE1	IOMUX_MODE(MX31_PIN_RI_DCE1, IOMUX_CONFIG_FUNC)
 #define MX31_PIN_DSR_DCE1__DSR_DCE1	IOMUX_MODE(MX31_PIN_DSR_DCE1, IOMUX_CONFIG_FUNC)
 #define MX31_PIN_DTR_DCE1__DTR_DCE1	IOMUX_MODE(MX31_PIN_DTR_DCE1, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_DTR_DCE1__SRXDA	IOMUX_MODE(MX31_PIN_DTR_DCE1, IOMUX_CONFIG_ALT2)
 #define MX31_PIN_CTS2__CTS2		IOMUX_MODE(MX31_PIN_CTS2, IOMUX_CONFIG_FUNC)
 #define MX31_PIN_RTS2__RTS2		IOMUX_MODE(MX31_PIN_RTS2, IOMUX_CONFIG_FUNC)
 #define MX31_PIN_TXD2__TXD2		IOMUX_MODE(MX31_PIN_TXD2, IOMUX_CONFIG_FUNC)
@@ -721,6 +725,7 @@ enum iomux_pins {
 #define MX31_PIN_KEY_ROW2_KEY_ROW2	IOMUX_MODE(MX31_PIN_KEY_ROW2, IOMUX_CONFIG_FUNC)
 #define MX31_PIN_KEY_ROW3_KEY_ROW3	IOMUX_MODE(MX31_PIN_KEY_ROW3, IOMUX_CONFIG_FUNC)
 #define MX31_PIN_KEY_ROW4_KEY_ROW4	IOMUX_MODE(MX31_PIN_KEY_ROW4, IOMUX_CONFIG_FUNC)
+#define MX31_PIN_KEY_ROW4_GPIO		IOMUX_MODE(MX31_PIN_KEY_ROW4, IOMUX_CONFIG_GPIO)
 #define MX31_PIN_KEY_ROW5_KEY_ROW5	IOMUX_MODE(MX31_PIN_KEY_ROW5, IOMUX_CONFIG_FUNC)
 #define MX31_PIN_KEY_ROW6_KEY_ROW6	IOMUX_MODE(MX31_PIN_KEY_ROW6, IOMUX_CONFIG_FUNC)
 #define MX31_PIN_KEY_ROW7_KEY_ROW7	IOMUX_MODE(MX31_PIN_KEY_ROW7, IOMUX_CONFIG_FUNC)
diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx53.h b/arch/arm/plat-mxc/include/mach/iomux-mx53.h
deleted file mode 100644
index 9761e00..0000000
--- a/arch/arm/plat-mxc/include/mach/iomux-mx53.h
+++ /dev/null
@@ -1,1219 +0,0 @@
-/*
- * Copyright (C) 2010-2011 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 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 __MACH_IOMUX_MX53_H__
-#define __MACH_IOMUX_MX53_H__
-
-#include <mach/iomux-v3.h>
-
-/* These 2 defines are for pins that may not have a mux register, but could
- * have a pad setting register, and vice-versa. */
-#define __NA_	0x00
-
-#define MX53_UART_PAD_CTRL		(PAD_CTL_PKE | PAD_CTL_PUE |	\
-		PAD_CTL_DSE_HIGH | PAD_CTL_SRE_FAST | PAD_CTL_HYS)
-#define MX53_SDHC_PAD_CTRL 	(PAD_CTL_HYS | PAD_CTL_PKE | PAD_CTL_PUE | \
-				PAD_CTL_PUS_47K_UP | PAD_CTL_DSE_HIGH | \
-				PAD_CTL_SRE_FAST)
-
-
-#define MX53_PAD_GPIO_19__KPP_COL_5			IOMUX_PAD(0x348, 0x020, 0, 0x840, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_19__GPIO4_5			IOMUX_PAD(0x348, 0x020, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_19__CCM_CLKO			IOMUX_PAD(0x348, 0x020, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_19__SPDIF_OUT1			IOMUX_PAD(0x348, 0x020, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_19__RTC_CE_RTC_EXT_TRIG2		IOMUX_PAD(0x348, 0x020, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_19__ECSPI1_RDY			IOMUX_PAD(0x348, 0x020, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_19__FEC_TDATA_3			IOMUX_PAD(0x348, 0x020, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_19__SRC_INT_BOOT			IOMUX_PAD(0x348, 0x020, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_COL0__KPP_COL_0			IOMUX_PAD(0x34C, 0x024, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_COL0__GPIO4_6			IOMUX_PAD(0x34C, 0x024, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_COL0__AUDMUX_AUD5_TXC		IOMUX_PAD(0x34C, 0x024, 2, 0x758, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_COL0__UART4_TXD_MUX		IOMUX_PAD(0x34C, 0x024, 4, __NA_, 0, MX53_UART_PAD_CTRL)
-#define MX53_PAD_KEY_COL0__ECSPI1_SCLK			IOMUX_PAD(0x34C, 0x024, 5, 0x79C, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_COL0__FEC_RDATA_3			IOMUX_PAD(0x34C, 0x024, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_COL0__SRC_ANY_PU_RST		IOMUX_PAD(0x34C, 0x024, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_ROW0__KPP_ROW_0			IOMUX_PAD(0x350, 0x028, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_ROW0__GPIO4_7			IOMUX_PAD(0x350, 0x028, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_ROW0__AUDMUX_AUD5_TXD		IOMUX_PAD(0x350, 0x028, 2, 0x74C, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_ROW0__UART4_RXD_MUX		IOMUX_PAD(0x350, 0x028, 4, 0x890, 1, MX53_UART_PAD_CTRL)
-#define MX53_PAD_KEY_ROW0__ECSPI1_MOSI			IOMUX_PAD(0x350, 0x028, 5, 0x7A4, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_ROW0__FEC_TX_ER			IOMUX_PAD(0x350, 0x028, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_COL1__KPP_COL_1			IOMUX_PAD(0x354, 0x02C, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_COL1__GPIO4_8			IOMUX_PAD(0x354, 0x02C, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_COL1__AUDMUX_AUD5_TXFS		IOMUX_PAD(0x354, 0x02C, 2, 0x75C, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_COL1__UART5_TXD_MUX		IOMUX_PAD(0x354, 0x02C, 4, __NA_, 0, MX53_UART_PAD_CTRL)
-#define MX53_PAD_KEY_COL1__ECSPI1_MISO			IOMUX_PAD(0x354, 0x02C, 5, 0x7A0, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_COL1__FEC_RX_CLK			IOMUX_PAD(0x354, 0x02C, 6, 0x808, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_COL1__USBPHY1_TXREADY		IOMUX_PAD(0x354, 0x02C, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_ROW1__KPP_ROW_1			IOMUX_PAD(0x358, 0x030, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_ROW1__GPIO4_9			IOMUX_PAD(0x358, 0x030, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_ROW1__AUDMUX_AUD5_RXD		IOMUX_PAD(0x358, 0x030, 2, 0x748, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_ROW1__UART5_RXD_MUX		IOMUX_PAD(0x358, 0x030, 4, 0x898, 1, MX53_UART_PAD_CTRL)
-#define MX53_PAD_KEY_ROW1__ECSPI1_SS0			IOMUX_PAD(0x358, 0x030, 5, 0x7A8, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_ROW1__FEC_COL			IOMUX_PAD(0x358, 0x030, 6, 0x800, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_ROW1__USBPHY1_RXVALID		IOMUX_PAD(0x358, 0x030, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_COL2__KPP_COL_2			IOMUX_PAD(0x35C, 0x034, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_COL2__GPIO4_10			IOMUX_PAD(0x35C, 0x034, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_COL2__CAN1_TXCAN			IOMUX_PAD(0x35C, 0x034, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_COL2__FEC_MDIO			IOMUX_PAD(0x35C, 0x034, 4, 0x804, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_COL2__ECSPI1_SS1			IOMUX_PAD(0x35C, 0x034, 5, 0x7AC, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_COL2__FEC_RDATA_2			IOMUX_PAD(0x35C, 0x034, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_COL2__USBPHY1_RXACTIVE		IOMUX_PAD(0x35C, 0x034, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_ROW2__KPP_ROW_2			IOMUX_PAD(0x360, 0x038, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_ROW2__GPIO4_11			IOMUX_PAD(0x360, 0x038, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_ROW2__CAN1_RXCAN			IOMUX_PAD(0x360, 0x038, 2, 0x760, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_ROW2__FEC_MDC			IOMUX_PAD(0x360, 0x038, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_ROW2__ECSPI1_SS2			IOMUX_PAD(0x360, 0x038, 5, 0x7B0, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_ROW2__FEC_TDATA_2			IOMUX_PAD(0x360, 0x038, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_ROW2__USBPHY1_RXERROR		IOMUX_PAD(0x360, 0x038, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_COL3__KPP_COL_3			IOMUX_PAD(0x364, 0x03C, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_COL3__GPIO4_12			IOMUX_PAD(0x364, 0x03C, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_COL3__USBOH3_H2_DP			IOMUX_PAD(0x364, 0x03C, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_COL3__SPDIF_IN1			IOMUX_PAD(0x364, 0x03C, 3, 0x870, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_COL3__I2C2_SCL			IOMUX_PAD(0x364, 0x03C, 4 | IOMUX_CONFIG_SION, 0x81C, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_COL3__ECSPI1_SS3			IOMUX_PAD(0x364, 0x03C, 5, 0x7B4, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_COL3__FEC_CRS			IOMUX_PAD(0x364, 0x03C, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_COL3__USBPHY1_SIECLOCK		IOMUX_PAD(0x364, 0x03C, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_ROW3__KPP_ROW_3			IOMUX_PAD(0x368, 0x040, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_ROW3__GPIO4_13			IOMUX_PAD(0x368, 0x040, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_ROW3__USBOH3_H2_DM			IOMUX_PAD(0x368, 0x040, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_ROW3__CCM_ASRC_EXT_CLK		IOMUX_PAD(0x368, 0x040, 3, 0x768, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_ROW3__I2C2_SDA			IOMUX_PAD(0x368, 0x040, 4 | IOMUX_CONFIG_SION, 0x820, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_ROW3__OSC32K_32K_OUT		IOMUX_PAD(0x368, 0x040, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_ROW3__CCM_PLL4_BYP			IOMUX_PAD(0x368, 0x040, 6, 0x77C, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_ROW3__USBPHY1_LINESTATE_0		IOMUX_PAD(0x368, 0x040, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_COL4__KPP_COL_4			IOMUX_PAD(0x36C, 0x044, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_COL4__GPIO4_14			IOMUX_PAD(0x36C, 0x044, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_COL4__CAN2_TXCAN			IOMUX_PAD(0x36C, 0x044, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_COL4__IPU_SISG_4			IOMUX_PAD(0x36C, 0x044, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_COL4__UART5_RTS			IOMUX_PAD(0x36C, 0x044, 4, 0x894, 0, MX53_UART_PAD_CTRL)
-#define MX53_PAD_KEY_COL4__USBOH3_USBOTG_OC		IOMUX_PAD(0x36C, 0x044, 5, 0x89C, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_COL4__USBPHY1_LINESTATE_1		IOMUX_PAD(0x36C, 0x044, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_ROW4__KPP_ROW_4			IOMUX_PAD(0x370, 0x048, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_ROW4__GPIO4_15			IOMUX_PAD(0x370, 0x048, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_ROW4__CAN2_RXCAN			IOMUX_PAD(0x370, 0x048, 2, 0x764, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_ROW4__IPU_SISG_5			IOMUX_PAD(0x370, 0x048, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_ROW4__UART5_CTS			IOMUX_PAD(0x370, 0x048, 4, __NA_, 0, MX53_UART_PAD_CTRL)
-#define MX53_PAD_KEY_ROW4__USBOH3_USBOTG_PWR		IOMUX_PAD(0x370, 0x048, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_ROW4__USBPHY1_VBUSVALID		IOMUX_PAD(0x370, 0x048, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DI0_DISP_CLK__IPU_DI0_DISP_CLK		IOMUX_PAD(0x378, 0x04C, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DI0_DISP_CLK__GPIO4_16			IOMUX_PAD(0x378, 0x04C, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DI0_DISP_CLK__USBOH3_USBH2_DIR		IOMUX_PAD(0x378, 0x04C, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DI0_DISP_CLK__SDMA_DEBUG_CORE_STATE_0	IOMUX_PAD(0x378, 0x04C, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DI0_DISP_CLK__EMI_EMI_DEBUG_0		IOMUX_PAD(0x378, 0x04C, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DI0_DISP_CLK__USBPHY1_AVALID		IOMUX_PAD(0x378, 0x04C, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DI0_PIN15__IPU_DI0_PIN15		IOMUX_PAD(0x37C, 0x050, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DI0_PIN15__GPIO4_17			IOMUX_PAD(0x37C, 0x050, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DI0_PIN15__AUDMUX_AUD6_TXC		IOMUX_PAD(0x37C, 0x050, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DI0_PIN15__SDMA_DEBUG_CORE_STATE_1	IOMUX_PAD(0x37C, 0x050, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DI0_PIN15__EMI_EMI_DEBUG_1		IOMUX_PAD(0x37C, 0x050, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DI0_PIN15__USBPHY1_BVALID		IOMUX_PAD(0x37C, 0x050, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DI0_PIN2__IPU_DI0_PIN2			IOMUX_PAD(0x380, 0x054, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DI0_PIN2__GPIO4_18			IOMUX_PAD(0x380, 0x054, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DI0_PIN2__AUDMUX_AUD6_TXD		IOMUX_PAD(0x380, 0x054, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DI0_PIN2__SDMA_DEBUG_CORE_STATE_2	IOMUX_PAD(0x380, 0x054, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DI0_PIN2__EMI_EMI_DEBUG_2		IOMUX_PAD(0x380, 0x054, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DI0_PIN2__USBPHY1_ENDSESSION		IOMUX_PAD(0x380, 0x054, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DI0_PIN3__IPU_DI0_PIN3			IOMUX_PAD(0x384, 0x058, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DI0_PIN3__GPIO4_19			IOMUX_PAD(0x384, 0x058, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DI0_PIN3__AUDMUX_AUD6_TXFS		IOMUX_PAD(0x384, 0x058, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DI0_PIN3__SDMA_DEBUG_CORE_STATE_3	IOMUX_PAD(0x384, 0x058, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DI0_PIN3__EMI_EMI_DEBUG_3		IOMUX_PAD(0x384, 0x058, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DI0_PIN3__USBPHY1_IDDIG		IOMUX_PAD(0x384, 0x058, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DI0_PIN4__IPU_DI0_PIN4			IOMUX_PAD(0x388, 0x05C, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DI0_PIN4__GPIO4_20			IOMUX_PAD(0x388, 0x05C, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DI0_PIN4__AUDMUX_AUD6_RXD		IOMUX_PAD(0x388, 0x05C, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DI0_PIN4__ESDHC1_WP			IOMUX_PAD(0x388, 0x05C, 3, 0x7FC, 0, NO_PAD_CTRL)
-#define MX53_PAD_DI0_PIN4__SDMA_DEBUG_YIELD		IOMUX_PAD(0x388, 0x05C, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DI0_PIN4__EMI_EMI_DEBUG_4		IOMUX_PAD(0x388, 0x05C, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DI0_PIN4__USBPHY1_HOSTDISCONNECT	IOMUX_PAD(0x388, 0x05C, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT0__IPU_DISP0_DAT_0		IOMUX_PAD(0x38C, 0x060, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT0__GPIO4_21			IOMUX_PAD(0x38C, 0x060, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT0__CSPI_SCLK			IOMUX_PAD(0x38C, 0x060, 2, 0x780, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT0__USBOH3_USBH2_DATA_0	IOMUX_PAD(0x38C, 0x060, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT0__SDMA_DEBUG_CORE_RUN	IOMUX_PAD(0x38C, 0x060, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT0__EMI_EMI_DEBUG_5		IOMUX_PAD(0x38C, 0x060, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT0__USBPHY2_TXREADY		IOMUX_PAD(0x38C, 0x060, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT1__IPU_DISP0_DAT_1		IOMUX_PAD(0x390, 0x064, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT1__GPIO4_22			IOMUX_PAD(0x390, 0x064, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT1__CSPI_MOSI			IOMUX_PAD(0x390, 0x064, 2, 0x788, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT1__USBOH3_USBH2_DATA_1	IOMUX_PAD(0x390, 0x064, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT1__SDMA_DEBUG_EVENT_CHANNEL_SEL	\
-							IOMUX_PAD(0x390, 0x064, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT1__EMI_EMI_DEBUG_6		IOMUX_PAD(0x390, 0x064, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT1__USBPHY2_RXVALID		IOMUX_PAD(0x390, 0x064, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT2__IPU_DISP0_DAT_2		IOMUX_PAD(0x394, 0x068, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT2__GPIO4_23			IOMUX_PAD(0x394, 0x068, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT2__CSPI_MISO			IOMUX_PAD(0x394, 0x068, 2, 0x784, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT2__USBOH3_USBH2_DATA_2	IOMUX_PAD(0x394, 0x068, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT2__SDMA_DEBUG_MODE		IOMUX_PAD(0x394, 0x068, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT2__EMI_EMI_DEBUG_7		IOMUX_PAD(0x394, 0x068, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT2__USBPHY2_RXACTIVE		IOMUX_PAD(0x394, 0x068, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT3__IPU_DISP0_DAT_3		IOMUX_PAD(0x398, 0x06C, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT3__GPIO4_24			IOMUX_PAD(0x398, 0x06C, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT3__CSPI_SS0			IOMUX_PAD(0x398, 0x06C, 2, 0x78C, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT3__USBOH3_USBH2_DATA_3	IOMUX_PAD(0x398, 0x06C, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT3__SDMA_DEBUG_BUS_ERROR	IOMUX_PAD(0x398, 0x06C, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT3__EMI_EMI_DEBUG_8		IOMUX_PAD(0x398, 0x06C, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT3__USBPHY2_RXERROR		IOMUX_PAD(0x398, 0x06C, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT4__IPU_DISP0_DAT_4		IOMUX_PAD(0x39C, 0x070, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT4__GPIO4_25			IOMUX_PAD(0x39C, 0x070, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT4__CSPI_SS1			IOMUX_PAD(0x39C, 0x070, 2, 0x790, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT4__USBOH3_USBH2_DATA_4	IOMUX_PAD(0x39C, 0x070, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT4__SDMA_DEBUG_BUS_RWB		IOMUX_PAD(0x39C, 0x070, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT4__EMI_EMI_DEBUG_9		IOMUX_PAD(0x39C, 0x070, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT4__USBPHY2_SIECLOCK		IOMUX_PAD(0x39C, 0x070, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT5__IPU_DISP0_DAT_5		IOMUX_PAD(0x3A0, 0x074, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT5__GPIO4_26			IOMUX_PAD(0x3A0, 0x074, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT5__CSPI_SS2			IOMUX_PAD(0x3A0, 0x074, 2, 0x794, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT5__USBOH3_USBH2_DATA_5	IOMUX_PAD(0x3A0, 0x074, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT5__SDMA_DEBUG_MATCHED_DMBUS	IOMUX_PAD(0x3A0, 0x074, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT5__EMI_EMI_DEBUG_10		IOMUX_PAD(0x3A0, 0x074, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT5__USBPHY2_LINESTATE_0	IOMUX_PAD(0x3A0, 0x074, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT6__IPU_DISP0_DAT_6		IOMUX_PAD(0x3A4, 0x078, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT6__GPIO4_27			IOMUX_PAD(0x3A4, 0x078, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT6__CSPI_SS3			IOMUX_PAD(0x3A4, 0x078, 2, 0x798, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT6__USBOH3_USBH2_DATA_6	IOMUX_PAD(0x3A4, 0x078, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT6__SDMA_DEBUG_RTBUFFER_WRITE	IOMUX_PAD(0x3A4, 0x078, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT6__EMI_EMI_DEBUG_11		IOMUX_PAD(0x3A4, 0x078, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT6__USBPHY2_LINESTATE_1	IOMUX_PAD(0x3A4, 0x078, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT7__IPU_DISP0_DAT_7		IOMUX_PAD(0x3A8, 0x07C, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT7__GPIO4_28			IOMUX_PAD(0x3A8, 0x07C, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT7__CSPI_RDY			IOMUX_PAD(0x3A8, 0x07C, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT7__USBOH3_USBH2_DATA_7	IOMUX_PAD(0x3A8, 0x07C, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT7__SDMA_DEBUG_EVENT_CHANNEL_0	IOMUX_PAD(0x3A8, 0x07C, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT7__EMI_EMI_DEBUG_12		IOMUX_PAD(0x3A8, 0x07C, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT7__USBPHY2_VBUSVALID		IOMUX_PAD(0x3A8, 0x07C, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT8__IPU_DISP0_DAT_8		IOMUX_PAD(0x3AC, 0x080, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT8__GPIO4_29			IOMUX_PAD(0x3AC, 0x080, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT8__PWM1_PWMO			IOMUX_PAD(0x3AC, 0x080, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT8__WDOG1_WDOG_B		IOMUX_PAD(0x3AC, 0x080, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT8__SDMA_DEBUG_EVENT_CHANNEL_1	IOMUX_PAD(0x3AC, 0x080, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT8__EMI_EMI_DEBUG_13		IOMUX_PAD(0x3AC, 0x080, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT8__USBPHY2_AVALID		IOMUX_PAD(0x3AC, 0x080, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT9__IPU_DISP0_DAT_9		IOMUX_PAD(0x3B0, 0x084, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT9__GPIO4_30			IOMUX_PAD(0x3B0, 0x084, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT9__PWM2_PWMO			IOMUX_PAD(0x3B0, 0x084, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT9__WDOG2_WDOG_B		IOMUX_PAD(0x3B0, 0x084, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT9__SDMA_DEBUG_EVENT_CHANNEL_2	IOMUX_PAD(0x3B0, 0x084, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT9__EMI_EMI_DEBUG_14		IOMUX_PAD(0x3B0, 0x084, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT9__USBPHY2_VSTATUS_0		IOMUX_PAD(0x3B0, 0x084, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT10__IPU_DISP0_DAT_10		IOMUX_PAD(0x3B4, 0x088, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT10__GPIO4_31			IOMUX_PAD(0x3B4, 0x088, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT10__USBOH3_USBH2_STP		IOMUX_PAD(0x3B4, 0x088, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT10__SDMA_DEBUG_EVENT_CHANNEL_3	\
-							IOMUX_PAD(0x3B4, 0x088, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT10__EMI_EMI_DEBUG_15		IOMUX_PAD(0x3B4, 0x088, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT10__USBPHY2_VSTATUS_1		IOMUX_PAD(0x3B4, 0x088, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT11__IPU_DISP0_DAT_11		IOMUX_PAD(0x3B8, 0x08C, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT11__GPIO5_5			IOMUX_PAD(0x3B8, 0x08C, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT11__USBOH3_USBH2_NXT		IOMUX_PAD(0x3B8, 0x08C, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT11__SDMA_DEBUG_EVENT_CHANNEL_4	\
-							IOMUX_PAD(0x3B8, 0x08C, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT11__EMI_EMI_DEBUG_16		IOMUX_PAD(0x3B8, 0x08C, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT11__USBPHY2_VSTATUS_2		IOMUX_PAD(0x3B8, 0x08C, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT12__IPU_DISP0_DAT_12		IOMUX_PAD(0x3BC, 0x090, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT12__GPIO5_6			IOMUX_PAD(0x3BC, 0x090, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT12__USBOH3_USBH2_CLK		IOMUX_PAD(0x3BC, 0x090, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT12__SDMA_DEBUG_EVENT_CHANNEL_5	\
-							IOMUX_PAD(0x3BC, 0x090, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT12__EMI_EMI_DEBUG_17		IOMUX_PAD(0x3BC, 0x090, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT12__USBPHY2_VSTATUS_3		IOMUX_PAD(0x3BC, 0x090, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT13__IPU_DISP0_DAT_13		IOMUX_PAD(0x3C0, 0x094, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT13__GPIO5_7			IOMUX_PAD(0x3C0, 0x094, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT13__AUDMUX_AUD5_RXFS		IOMUX_PAD(0x3C0, 0x094, 3, 0x754, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT13__SDMA_DEBUG_EVT_CHN_LINES_0	\
-							IOMUX_PAD(0x3C0, 0x094, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT13__EMI_EMI_DEBUG_18		IOMUX_PAD(0x3C0, 0x094, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT13__USBPHY2_VSTATUS_4		IOMUX_PAD(0x3C0, 0x094, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT14__IPU_DISP0_DAT_14		IOMUX_PAD(0x3C4, 0x098, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT14__GPIO5_8			IOMUX_PAD(0x3C4, 0x098, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT14__AUDMUX_AUD5_RXC		IOMUX_PAD(0x3C4, 0x098, 3, 0x750, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT14__SDMA_DEBUG_EVT_CHN_LINES_1	\
-							IOMUX_PAD(0x3C4, 0x098, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT14__EMI_EMI_DEBUG_19		IOMUX_PAD(0x3C4, 0x098, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT14__USBPHY2_VSTATUS_5		IOMUX_PAD(0x3C4, 0x098, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT15__IPU_DISP0_DAT_15		IOMUX_PAD(0x3C8, 0x09C, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT15__GPIO5_9			IOMUX_PAD(0x3C8, 0x09C, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT15__ECSPI1_SS1		IOMUX_PAD(0x3C8, 0x09C, 2, 0x7AC, 1, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT15__ECSPI2_SS1		IOMUX_PAD(0x3C8, 0x09C, 3, 0x7C8, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT15__SDMA_DEBUG_EVT_CHN_LINES_2	\
-							IOMUX_PAD(0x3C8, 0x09C, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT15__EMI_EMI_DEBUG_20		IOMUX_PAD(0x3C8, 0x09C, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT15__USBPHY2_VSTATUS_6		IOMUX_PAD(0x3C8, 0x09C, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT16__IPU_DISP0_DAT_16		IOMUX_PAD(0x3CC, 0x0A0, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT16__GPIO5_10			IOMUX_PAD(0x3CC, 0x0A0, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT16__ECSPI2_MOSI		IOMUX_PAD(0x3CC, 0x0A0, 2, 0x7C0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT16__AUDMUX_AUD5_TXC		IOMUX_PAD(0x3CC, 0x0A0, 3, 0x758, 1, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT16__SDMA_EXT_EVENT_0		IOMUX_PAD(0x3CC, 0x0A0, 4, 0x868, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT16__SDMA_DEBUG_EVT_CHN_LINES_3	\
-							IOMUX_PAD(0x3CC, 0x0A0, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT16__EMI_EMI_DEBUG_21		IOMUX_PAD(0x3CC, 0x0A0, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT16__USBPHY2_VSTATUS_7		IOMUX_PAD(0x3CC, 0x0A0, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT17__IPU_DISP0_DAT_17		IOMUX_PAD(0x3D0, 0x0A4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT17__GPIO5_11			IOMUX_PAD(0x3D0, 0x0A4, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT17__ECSPI2_MISO		IOMUX_PAD(0x3D0, 0x0A4, 2, 0x7BC, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT17__AUDMUX_AUD5_TXD		IOMUX_PAD(0x3D0, 0x0A4, 3, 0x74C, 1, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT17__SDMA_EXT_EVENT_1		IOMUX_PAD(0x3D0, 0x0A4, 4, 0x86C, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT17__SDMA_DEBUG_EVT_CHN_LINES_4	\
-							IOMUX_PAD(0x3D0, 0x0A4, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT17__EMI_EMI_DEBUG_22		IOMUX_PAD(0x3D0, 0x0A4, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT18__IPU_DISP0_DAT_18		IOMUX_PAD(0x3D4, 0x0A8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT18__GPIO5_12			IOMUX_PAD(0x3D4, 0x0A8, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT18__ECSPI2_SS0		IOMUX_PAD(0x3D4, 0x0A8, 2, 0x7C4, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT18__AUDMUX_AUD5_TXFS		IOMUX_PAD(0x3D4, 0x0A8, 3, 0x75C, 1, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT18__AUDMUX_AUD4_RXFS		IOMUX_PAD(0x3D4, 0x0A8, 4, 0x73C, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT18__SDMA_DEBUG_EVT_CHN_LINES_5	\
-							IOMUX_PAD(0x3D4, 0x0A8, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT18__EMI_EMI_DEBUG_23		IOMUX_PAD(0x3D4, 0x0A8, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT18__EMI_WEIM_CS_2		IOMUX_PAD(0x3D4, 0x0A8, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT19__IPU_DISP0_DAT_19		IOMUX_PAD(0x3D8, 0x0AC, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT19__GPIO5_13			IOMUX_PAD(0x3D8, 0x0AC, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT19__ECSPI2_SCLK		IOMUX_PAD(0x3D8, 0x0AC, 2, 0x7B8, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT19__AUDMUX_AUD5_RXD		IOMUX_PAD(0x3D8, 0x0AC, 3, 0x748, 1, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT19__AUDMUX_AUD4_RXC		IOMUX_PAD(0x3D8, 0x0AC, 4, 0x738, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT19__SDMA_DEBUG_EVT_CHN_LINES_6	\
-							IOMUX_PAD(0x3D8, 0x0AC, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT19__EMI_EMI_DEBUG_24		IOMUX_PAD(0x3D8, 0x0AC, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT19__EMI_WEIM_CS_3		IOMUX_PAD(0x3D8, 0x0AC, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT20__IPU_DISP0_DAT_20		IOMUX_PAD(0x3DC, 0x0B0, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT20__GPIO5_14			IOMUX_PAD(0x3DC, 0x0B0, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT20__ECSPI1_SCLK		IOMUX_PAD(0x3DC, 0x0B0, 2, 0x79C, 1, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT20__AUDMUX_AUD4_TXC		IOMUX_PAD(0x3DC, 0x0B0, 3, 0x740, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT20__SDMA_DEBUG_EVT_CHN_LINES_7	\
-							IOMUX_PAD(0x3DC, 0x0B0, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT20__EMI_EMI_DEBUG_25		IOMUX_PAD(0x3DC, 0x0B0, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT20__SATA_PHY_TDI		IOMUX_PAD(0x3DC, 0x0B0, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT21__IPU_DISP0_DAT_21		IOMUX_PAD(0x3E0, 0x0B4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT21__GPIO5_15			IOMUX_PAD(0x3E0, 0x0B4, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT21__ECSPI1_MOSI		IOMUX_PAD(0x3E0, 0x0B4, 2, 0x7A4, 1, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT21__AUDMUX_AUD4_TXD		IOMUX_PAD(0x3E0, 0x0B4, 3, 0x734, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT21__SDMA_DEBUG_BUS_DEVICE_0	IOMUX_PAD(0x3E0, 0x0B4, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT21__EMI_EMI_DEBUG_26		IOMUX_PAD(0x3E0, 0x0B4, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT21__SATA_PHY_TDO		IOMUX_PAD(0x3E0, 0x0B4, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT22__IPU_DISP0_DAT_22		IOMUX_PAD(0x3E4, 0x0B8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT22__GPIO5_16			IOMUX_PAD(0x3E4, 0x0B8, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT22__ECSPI1_MISO		IOMUX_PAD(0x3E4, 0x0B8, 2, 0x7A0, 1, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT22__AUDMUX_AUD4_TXFS		IOMUX_PAD(0x3E4, 0x0B8, 3, 0x744, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT22__SDMA_DEBUG_BUS_DEVICE_1	IOMUX_PAD(0x3E4, 0x0B8, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT22__EMI_EMI_DEBUG_27		IOMUX_PAD(0x3E4, 0x0B8, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT22__SATA_PHY_TCK		IOMUX_PAD(0x3E4, 0x0B8, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT23__IPU_DISP0_DAT_23		IOMUX_PAD(0x3E8, 0x0BC, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT23__GPIO5_17			IOMUX_PAD(0x3E8, 0x0BC, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT23__ECSPI1_SS0		IOMUX_PAD(0x3E8, 0x0BC, 2, 0x7A8, 1, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT23__AUDMUX_AUD4_RXD		IOMUX_PAD(0x3E8, 0x0BC, 3, 0x730, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT23__SDMA_DEBUG_BUS_DEVICE_2	IOMUX_PAD(0x3E8, 0x0BC, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT23__EMI_EMI_DEBUG_28		IOMUX_PAD(0x3E8, 0x0BC, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT23__SATA_PHY_TMS		IOMUX_PAD(0x3E8, 0x0BC, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_PIXCLK__IPU_CSI0_PIXCLK		IOMUX_PAD(0x3EC, 0x0C0, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_PIXCLK__GPIO5_18			IOMUX_PAD(0x3EC, 0x0C0, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_PIXCLK__SDMA_DEBUG_PC_0		IOMUX_PAD(0x3EC, 0x0C0, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_PIXCLK__EMI_EMI_DEBUG_29		IOMUX_PAD(0x3EC, 0x0C0, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_MCLK__IPU_CSI0_HSYNC		IOMUX_PAD(0x3F0, 0x0C4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_MCLK__GPIO5_19			IOMUX_PAD(0x3F0, 0x0C4, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_MCLK__CCM_CSI0_MCLK		IOMUX_PAD(0x3F0, 0x0C4, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_MCLK__SDMA_DEBUG_PC_1		IOMUX_PAD(0x3F0, 0x0C4, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_MCLK__EMI_EMI_DEBUG_30		IOMUX_PAD(0x3F0, 0x0C4, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_MCLK__TPIU_TRCTL			IOMUX_PAD(0x3F0, 0x0C4, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DATA_EN__IPU_CSI0_DATA_EN		IOMUX_PAD(0x3F4, 0x0C8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DATA_EN__GPIO5_20			IOMUX_PAD(0x3F4, 0x0C8, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DATA_EN__SDMA_DEBUG_PC_2		IOMUX_PAD(0x3F4, 0x0C8, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DATA_EN__EMI_EMI_DEBUG_31		IOMUX_PAD(0x3F4, 0x0C8, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DATA_EN__TPIU_TRCLK		IOMUX_PAD(0x3F4, 0x0C8, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_VSYNC__IPU_CSI0_VSYNC		IOMUX_PAD(0x3F8, 0x0CC, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_VSYNC__GPIO5_21			IOMUX_PAD(0x3F8, 0x0CC, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_VSYNC__SDMA_DEBUG_PC_3		IOMUX_PAD(0x3F8, 0x0CC, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_VSYNC__EMI_EMI_DEBUG_32		IOMUX_PAD(0x3F8, 0x0CC, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_VSYNC__TPIU_TRACE_0		IOMUX_PAD(0x3F8, 0x0CC, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT4__IPU_CSI0_D_4		IOMUX_PAD(0x3FC, 0x0D0, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT4__GPIO5_22			IOMUX_PAD(0x3FC, 0x0D0, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT4__KPP_COL_5			IOMUX_PAD(0x3FC, 0x0D0, 2, 0x840, 1, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT4__ECSPI1_SCLK			IOMUX_PAD(0x3FC, 0x0D0, 3, 0x79C, 2, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT4__USBOH3_USBH3_STP		IOMUX_PAD(0x3FC, 0x0D0, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT4__AUDMUX_AUD3_TXC		IOMUX_PAD(0x3FC, 0x0D0, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT4__EMI_EMI_DEBUG_33		IOMUX_PAD(0x3FC, 0x0D0, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT4__TPIU_TRACE_1		IOMUX_PAD(0x3FC, 0x0D0, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT5__IPU_CSI0_D_5		IOMUX_PAD(0x400, 0x0D4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT5__GPIO5_23			IOMUX_PAD(0x400, 0x0D4, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT5__KPP_ROW_5			IOMUX_PAD(0x400, 0x0D4, 2, 0x84C, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT5__ECSPI1_MOSI			IOMUX_PAD(0x400, 0x0D4, 3, 0x7A4, 2, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT5__USBOH3_USBH3_NXT		IOMUX_PAD(0x400, 0x0D4, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT5__AUDMUX_AUD3_TXD		IOMUX_PAD(0x400, 0x0D4, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT5__EMI_EMI_DEBUG_34		IOMUX_PAD(0x400, 0x0D4, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT5__TPIU_TRACE_2		IOMUX_PAD(0x400, 0x0D4, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT6__IPU_CSI0_D_6		IOMUX_PAD(0x404, 0x0D8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT6__GPIO5_24			IOMUX_PAD(0x404, 0x0D8, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT6__KPP_COL_6			IOMUX_PAD(0x404, 0x0D8, 2, 0x844, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT6__ECSPI1_MISO			IOMUX_PAD(0x404, 0x0D8, 3, 0x7A0, 2, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT6__USBOH3_USBH3_CLK		IOMUX_PAD(0x404, 0x0D8, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT6__AUDMUX_AUD3_TXFS		IOMUX_PAD(0x404, 0x0D8, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT6__EMI_EMI_DEBUG_35		IOMUX_PAD(0x404, 0x0D8, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT6__TPIU_TRACE_3		IOMUX_PAD(0x404, 0x0D8, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT7__IPU_CSI0_D_7		IOMUX_PAD(0x408, 0x0DC, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT7__GPIO5_25			IOMUX_PAD(0x408, 0x0DC, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT7__KPP_ROW_6			IOMUX_PAD(0x408, 0x0DC, 2, 0x850, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT7__ECSPI1_SS0			IOMUX_PAD(0x408, 0x0DC, 3, 0x7A8, 2, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT7__USBOH3_USBH3_DIR		IOMUX_PAD(0x408, 0x0DC, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT7__AUDMUX_AUD3_RXD		IOMUX_PAD(0x408, 0x0DC, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT7__EMI_EMI_DEBUG_36		IOMUX_PAD(0x408, 0x0DC, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT7__TPIU_TRACE_4		IOMUX_PAD(0x408, 0x0DC, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT8__IPU_CSI0_D_8		IOMUX_PAD(0x40C, 0x0E0, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT8__GPIO5_26			IOMUX_PAD(0x40C, 0x0E0, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT8__KPP_COL_7			IOMUX_PAD(0x40C, 0x0E0, 2, 0x848, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT8__ECSPI2_SCLK			IOMUX_PAD(0x40C, 0x0E0, 3, 0x7B8, 1, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT8__USBOH3_USBH3_OC		IOMUX_PAD(0x40C, 0x0E0, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT8__I2C1_SDA			IOMUX_PAD(0x40C, 0x0E0, 5 | IOMUX_CONFIG_SION, 0x818, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT8__EMI_EMI_DEBUG_37		IOMUX_PAD(0x40C, 0x0E0, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT8__TPIU_TRACE_5		IOMUX_PAD(0x40C, 0x0E0, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT9__IPU_CSI0_D_9		IOMUX_PAD(0x410, 0x0E4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT9__GPIO5_27			IOMUX_PAD(0x410, 0x0E4, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT9__KPP_ROW_7			IOMUX_PAD(0x410, 0x0E4, 2, 0x854, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT9__ECSPI2_MOSI			IOMUX_PAD(0x410, 0x0E4, 3, 0x7C0, 1, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT9__USBOH3_USBH3_PWR		IOMUX_PAD(0x410, 0x0E4, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT9__I2C1_SCL			IOMUX_PAD(0x410, 0x0E4, 5 | IOMUX_CONFIG_SION, 0x814, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT9__EMI_EMI_DEBUG_38		IOMUX_PAD(0x410, 0x0E4, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT9__TPIU_TRACE_6		IOMUX_PAD(0x410, 0x0E4, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT10__IPU_CSI0_D_10		IOMUX_PAD(0x414, 0x0E8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT10__GPIO5_28			IOMUX_PAD(0x414, 0x0E8, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT10__UART1_TXD_MUX		IOMUX_PAD(0x414, 0x0E8, 2, __NA_, 0, MX53_UART_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT10__ECSPI2_MISO		IOMUX_PAD(0x414, 0x0E8, 3, 0x7BC, 1, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT10__AUDMUX_AUD3_RXC		IOMUX_PAD(0x414, 0x0E8, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT10__SDMA_DEBUG_PC_4		IOMUX_PAD(0x414, 0x0E8, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT10__EMI_EMI_DEBUG_39		IOMUX_PAD(0x414, 0x0E8, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT10__TPIU_TRACE_7		IOMUX_PAD(0x414, 0x0E8, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT11__IPU_CSI0_D_11		IOMUX_PAD(0x418, 0x0EC, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT11__GPIO5_29			IOMUX_PAD(0x418, 0x0EC, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT11__UART1_RXD_MUX		IOMUX_PAD(0x418, 0x0EC, 2, 0x878, 1, MX53_UART_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT11__ECSPI2_SS0			IOMUX_PAD(0x418, 0x0EC, 3, 0x7C4, 1, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT11__AUDMUX_AUD3_RXFS		IOMUX_PAD(0x418, 0x0EC, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT11__SDMA_DEBUG_PC_5		IOMUX_PAD(0x418, 0x0EC, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT11__EMI_EMI_DEBUG_40		IOMUX_PAD(0x418, 0x0EC, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT11__TPIU_TRACE_8		IOMUX_PAD(0x418, 0x0EC, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT12__IPU_CSI0_D_12		IOMUX_PAD(0x41C, 0x0F0, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT12__GPIO5_30			IOMUX_PAD(0x41C, 0x0F0, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT12__UART4_TXD_MUX		IOMUX_PAD(0x41C, 0x0F0, 2, __NA_, 0, MX53_UART_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT12__USBOH3_USBH3_DATA_0	IOMUX_PAD(0x41C, 0x0F0, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT12__SDMA_DEBUG_PC_6		IOMUX_PAD(0x41C, 0x0F0, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT12__EMI_EMI_DEBUG_41		IOMUX_PAD(0x41C, 0x0F0, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT12__TPIU_TRACE_9		IOMUX_PAD(0x41C, 0x0F0, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT13__IPU_CSI0_D_13		IOMUX_PAD(0x420, 0x0F4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT13__GPIO5_31			IOMUX_PAD(0x420, 0x0F4, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT13__UART4_RXD_MUX		IOMUX_PAD(0x420, 0x0F4, 2, 0x890, 3, MX53_UART_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT13__USBOH3_USBH3_DATA_1	IOMUX_PAD(0x420, 0x0F4, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT13__SDMA_DEBUG_PC_7		IOMUX_PAD(0x420, 0x0F4, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT13__EMI_EMI_DEBUG_42		IOMUX_PAD(0x420, 0x0F4, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT13__TPIU_TRACE_10		IOMUX_PAD(0x420, 0x0F4, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT14__IPU_CSI0_D_14		IOMUX_PAD(0x424, 0x0F8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT14__GPIO6_0			IOMUX_PAD(0x424, 0x0F8, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT14__UART5_TXD_MUX		IOMUX_PAD(0x424, 0x0F8, 2, __NA_, 0, MX53_UART_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT14__USBOH3_USBH3_DATA_2	IOMUX_PAD(0x424, 0x0F8, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT14__SDMA_DEBUG_PC_8		IOMUX_PAD(0x424, 0x0F8, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT14__EMI_EMI_DEBUG_43		IOMUX_PAD(0x424, 0x0F8, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT14__TPIU_TRACE_11		IOMUX_PAD(0x424, 0x0F8, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT15__IPU_CSI0_D_15		IOMUX_PAD(0x428, 0x0FC, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT15__GPIO6_1			IOMUX_PAD(0x428, 0x0FC, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT15__UART5_RXD_MUX		IOMUX_PAD(0x428, 0x0FC, 2, 0x898, 3, MX53_UART_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT15__USBOH3_USBH3_DATA_3	IOMUX_PAD(0x428, 0x0FC, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT15__SDMA_DEBUG_PC_9		IOMUX_PAD(0x428, 0x0FC, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT15__EMI_EMI_DEBUG_44		IOMUX_PAD(0x428, 0x0FC, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT15__TPIU_TRACE_12		IOMUX_PAD(0x428, 0x0FC, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT16__IPU_CSI0_D_16		IOMUX_PAD(0x42C, 0x100, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT16__GPIO6_2			IOMUX_PAD(0x42C, 0x100, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT16__UART4_RTS			IOMUX_PAD(0x42C, 0x100, 2, 0x88C, 0, MX53_UART_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT16__USBOH3_USBH3_DATA_4	IOMUX_PAD(0x42C, 0x100, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT16__SDMA_DEBUG_PC_10		IOMUX_PAD(0x42C, 0x100, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT16__EMI_EMI_DEBUG_45		IOMUX_PAD(0x42C, 0x100, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT16__TPIU_TRACE_13		IOMUX_PAD(0x42C, 0x100, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT17__IPU_CSI0_D_17		IOMUX_PAD(0x430, 0x104, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT17__GPIO6_3			IOMUX_PAD(0x430, 0x104, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT17__UART4_CTS			IOMUX_PAD(0x430, 0x104, 2, __NA_, 0, MX53_UART_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT17__USBOH3_USBH3_DATA_5	IOMUX_PAD(0x430, 0x104, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT17__SDMA_DEBUG_PC_11		IOMUX_PAD(0x430, 0x104, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT17__EMI_EMI_DEBUG_46		IOMUX_PAD(0x430, 0x104, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT17__TPIU_TRACE_14		IOMUX_PAD(0x430, 0x104, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT18__IPU_CSI0_D_18		IOMUX_PAD(0x434, 0x108, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT18__GPIO6_4			IOMUX_PAD(0x434, 0x108, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT18__UART5_RTS			IOMUX_PAD(0x434, 0x108, 2, 0x894, 2, MX53_UART_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT18__USBOH3_USBH3_DATA_6	IOMUX_PAD(0x434, 0x108, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT18__SDMA_DEBUG_PC_12		IOMUX_PAD(0x434, 0x108, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT18__EMI_EMI_DEBUG_47		IOMUX_PAD(0x434, 0x108, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT18__TPIU_TRACE_15		IOMUX_PAD(0x434, 0x108, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT19__IPU_CSI0_D_19		IOMUX_PAD(0x438, 0x10C, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT19__GPIO6_5			IOMUX_PAD(0x438, 0x10C, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT19__UART5_CTS			IOMUX_PAD(0x438, 0x10C, 2, __NA_, 0, MX53_UART_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT19__USBOH3_USBH3_DATA_7	IOMUX_PAD(0x438, 0x10C, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT19__SDMA_DEBUG_PC_13		IOMUX_PAD(0x438, 0x10C, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT19__EMI_EMI_DEBUG_48		IOMUX_PAD(0x438, 0x10C, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DAT19__USBPHY2_BISTOK		IOMUX_PAD(0x438, 0x10C, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A25__EMI_WEIM_A_25			IOMUX_PAD(0x458, 0x110, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A25__GPIO5_2			IOMUX_PAD(0x458, 0x110, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A25__ECSPI2_RDY			IOMUX_PAD(0x458, 0x110, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A25__IPU_DI1_PIN12			IOMUX_PAD(0x458, 0x110, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A25__CSPI_SS1			IOMUX_PAD(0x458, 0x110, 4, 0x790, 1, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A25__IPU_DI0_D1_CS			IOMUX_PAD(0x458, 0x110, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A25__USBPHY1_BISTOK		IOMUX_PAD(0x458, 0x110, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_EB2__EMI_WEIM_EB_2			IOMUX_PAD(0x45C, 0x114, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_EB2__GPIO2_30			IOMUX_PAD(0x45C, 0x114, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_EB2__CCM_DI1_EXT_CLK		IOMUX_PAD(0x45C, 0x114, 2, 0x76C, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_EB2__IPU_SER_DISP1_CS		IOMUX_PAD(0x45C, 0x114, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_EB2__ECSPI1_SS0			IOMUX_PAD(0x45C, 0x114, 4, 0x7A8, 3, NO_PAD_CTRL)
-#define MX53_PAD_EIM_EB2__I2C2_SCL			IOMUX_PAD(0x45C, 0x114, 5 | IOMUX_CONFIG_SION, 0x81C, 1, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D16__EMI_WEIM_D_16			IOMUX_PAD(0x460, 0x118, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D16__GPIO3_16			IOMUX_PAD(0x460, 0x118, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D16__IPU_DI0_PIN5			IOMUX_PAD(0x460, 0x118, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D16__IPU_DISPB1_SER_CLK		IOMUX_PAD(0x460, 0x118, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D16__ECSPI1_SCLK			IOMUX_PAD(0x460, 0x118, 4, 0x79C, 3, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D16__I2C2_SDA			IOMUX_PAD(0x460, 0x118, 5 | IOMUX_CONFIG_SION, 0x820, 1, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D17__EMI_WEIM_D_17			IOMUX_PAD(0x464, 0x11C, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D17__GPIO3_17			IOMUX_PAD(0x464, 0x11C, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D17__IPU_DI0_PIN6			IOMUX_PAD(0x464, 0x11C, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D17__IPU_DISPB1_SER_DIN		IOMUX_PAD(0x464, 0x11C, 3, 0x830, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D17__ECSPI1_MISO			IOMUX_PAD(0x464, 0x11C, 4, 0x7A0, 3, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D17__I2C3_SCL			IOMUX_PAD(0x464, 0x11C, 5 | IOMUX_CONFIG_SION, 0x824, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D18__EMI_WEIM_D_18			IOMUX_PAD(0x468, 0x120, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D18__GPIO3_18			IOMUX_PAD(0x468, 0x120, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D18__IPU_DI0_PIN7			IOMUX_PAD(0x468, 0x120, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D18__IPU_DISPB1_SER_DIO		IOMUX_PAD(0x468, 0x120, 3, 0x830, 1, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D18__ECSPI1_MOSI			IOMUX_PAD(0x468, 0x120, 4, 0x7A4, 3, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D18__I2C3_SDA			IOMUX_PAD(0x468, 0x120, 5 | IOMUX_CONFIG_SION, 0x828, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D18__IPU_DI1_D0_CS			IOMUX_PAD(0x468, 0x120, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D19__EMI_WEIM_D_19			IOMUX_PAD(0x46C, 0x124, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D19__GPIO3_19			IOMUX_PAD(0x46C, 0x124, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D19__IPU_DI0_PIN8			IOMUX_PAD(0x46C, 0x124, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D19__IPU_DISPB1_SER_RS		IOMUX_PAD(0x46C, 0x124, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D19__ECSPI1_SS1			IOMUX_PAD(0x46C, 0x124, 4, 0x7AC, 2, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D19__EPIT1_EPITO			IOMUX_PAD(0x46C, 0x124, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D19__UART1_CTS			IOMUX_PAD(0x46C, 0x124, 6, __NA_, 0, MX53_UART_PAD_CTRL)
-#define MX53_PAD_EIM_D19__USBOH3_USBH2_OC		IOMUX_PAD(0x46C, 0x124, 7, 0x8A4, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D20__EMI_WEIM_D_20			IOMUX_PAD(0x470, 0x128, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D20__GPIO3_20			IOMUX_PAD(0x470, 0x128, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D20__IPU_DI0_PIN16			IOMUX_PAD(0x470, 0x128, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D20__IPU_SER_DISP0_CS		IOMUX_PAD(0x470, 0x128, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D20__CSPI_SS0			IOMUX_PAD(0x470, 0x128, 4, 0x78C, 1, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D20__EPIT2_EPITO			IOMUX_PAD(0x470, 0x128, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D20__UART1_RTS			IOMUX_PAD(0x470, 0x128, 6, 0x874, 1, MX53_UART_PAD_CTRL)
-#define MX53_PAD_EIM_D20__USBOH3_USBH2_PWR		IOMUX_PAD(0x470, 0x128, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D21__EMI_WEIM_D_21			IOMUX_PAD(0x474, 0x12C, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D21__GPIO3_21			IOMUX_PAD(0x474, 0x12C, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D21__IPU_DI0_PIN17			IOMUX_PAD(0x474, 0x12C, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D21__IPU_DISPB0_SER_CLK		IOMUX_PAD(0x474, 0x12C, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D21__CSPI_SCLK			IOMUX_PAD(0x474, 0x12C, 4, 0x780, 1, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D21__I2C1_SCL			IOMUX_PAD(0x474, 0x12C, 5 | IOMUX_CONFIG_SION, 0x814, 1, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D21__USBOH3_USBOTG_OC		IOMUX_PAD(0x474, 0x12C, 6, 0x89C, 1, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D22__EMI_WEIM_D_22			IOMUX_PAD(0x478, 0x130, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D22__GPIO3_22			IOMUX_PAD(0x478, 0x130, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D22__IPU_DI0_PIN1			IOMUX_PAD(0x478, 0x130, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D22__IPU_DISPB0_SER_DIN		IOMUX_PAD(0x478, 0x130, 3, 0x82C, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D22__CSPI_MISO			IOMUX_PAD(0x478, 0x130, 4, 0x784, 1, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D22__USBOH3_USBOTG_PWR		IOMUX_PAD(0x478, 0x130, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D23__EMI_WEIM_D_23			IOMUX_PAD(0x47C, 0x134, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D23__GPIO3_23			IOMUX_PAD(0x47C, 0x134, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D23__UART3_CTS			IOMUX_PAD(0x47C, 0x134, 2, __NA_, 0, MX53_UART_PAD_CTRL)
-#define MX53_PAD_EIM_D23__UART1_DCD			IOMUX_PAD(0x47C, 0x134, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D23__IPU_DI0_D0_CS			IOMUX_PAD(0x47C, 0x134, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D23__IPU_DI1_PIN2			IOMUX_PAD(0x47C, 0x134, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D23__IPU_CSI1_DATA_EN		IOMUX_PAD(0x47C, 0x134, 6, 0x834, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D23__IPU_DI1_PIN14			IOMUX_PAD(0x47C, 0x134, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_EB3__EMI_WEIM_EB_3			IOMUX_PAD(0x480, 0x138, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_EB3__GPIO2_31			IOMUX_PAD(0x480, 0x138, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_EB3__UART3_RTS			IOMUX_PAD(0x480, 0x138, 2, 0x884, 1, MX53_UART_PAD_CTRL)
-#define MX53_PAD_EIM_EB3__UART1_RI			IOMUX_PAD(0x480, 0x138, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_EB3__IPU_DI1_PIN3			IOMUX_PAD(0x480, 0x138, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_EB3__IPU_CSI1_HSYNC		IOMUX_PAD(0x480, 0x138, 6, 0x838, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_EB3__IPU_DI1_PIN16			IOMUX_PAD(0x480, 0x138, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D24__EMI_WEIM_D_24			IOMUX_PAD(0x484, 0x13C, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D24__GPIO3_24			IOMUX_PAD(0x484, 0x13C, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D24__UART3_TXD_MUX			IOMUX_PAD(0x484, 0x13C, 2, __NA_, 0, MX53_UART_PAD_CTRL)
-#define MX53_PAD_EIM_D24__ECSPI1_SS2			IOMUX_PAD(0x484, 0x13C, 3, 0x7B0, 1, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D24__CSPI_SS2			IOMUX_PAD(0x484, 0x13C, 4, 0x794, 1, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D24__AUDMUX_AUD5_RXFS		IOMUX_PAD(0x484, 0x13C, 5, 0x754, 1, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D24__ECSPI2_SS2			IOMUX_PAD(0x484, 0x13C, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D24__UART1_DTR			IOMUX_PAD(0x484, 0x13C, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D25__EMI_WEIM_D_25			IOMUX_PAD(0x488, 0x140, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D25__GPIO3_25			IOMUX_PAD(0x488, 0x140, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D25__UART3_RXD_MUX			IOMUX_PAD(0x488, 0x140, 2, 0x888, 1, MX53_UART_PAD_CTRL)
-#define MX53_PAD_EIM_D25__ECSPI1_SS3			IOMUX_PAD(0x488, 0x140, 3, 0x7B4, 1, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D25__CSPI_SS3			IOMUX_PAD(0x488, 0x140, 4, 0x798, 1, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D25__AUDMUX_AUD5_RXC		IOMUX_PAD(0x488, 0x140, 5, 0x750, 1, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D25__ECSPI2_SS3			IOMUX_PAD(0x488, 0x140, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D25__UART1_DSR			IOMUX_PAD(0x488, 0x140, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D26__EMI_WEIM_D_26			IOMUX_PAD(0x48C, 0x144, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D26__GPIO3_26			IOMUX_PAD(0x48C, 0x144, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D26__UART2_TXD_MUX			IOMUX_PAD(0x48C, 0x144, 2, __NA_, 0, MX53_UART_PAD_CTRL)
-#define MX53_PAD_EIM_D26__FIRI_RXD			IOMUX_PAD(0x48C, 0x144, 3, 0x80C, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D26__IPU_CSI0_D_1			IOMUX_PAD(0x48C, 0x144, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D26__IPU_DI1_PIN11			IOMUX_PAD(0x48C, 0x144, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D26__IPU_SISG_2			IOMUX_PAD(0x48C, 0x144, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D26__IPU_DISP1_DAT_22		IOMUX_PAD(0x48C, 0x144, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D27__EMI_WEIM_D_27			IOMUX_PAD(0x490, 0x148, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D27__GPIO3_27			IOMUX_PAD(0x490, 0x148, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D27__UART2_RXD_MUX			IOMUX_PAD(0x490, 0x148, 2, 0x880, 1, MX53_UART_PAD_CTRL)
-#define MX53_PAD_EIM_D27__FIRI_TXD			IOMUX_PAD(0x490, 0x148, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D27__IPU_CSI0_D_0			IOMUX_PAD(0x490, 0x148, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D27__IPU_DI1_PIN13			IOMUX_PAD(0x490, 0x148, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D27__IPU_SISG_3			IOMUX_PAD(0x490, 0x148, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D27__IPU_DISP1_DAT_23		IOMUX_PAD(0x490, 0x148, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D28__EMI_WEIM_D_28			IOMUX_PAD(0x494, 0x14C, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D28__GPIO3_28			IOMUX_PAD(0x494, 0x14C, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D28__UART2_CTS			IOMUX_PAD(0x494, 0x14C, 2, __NA_, 0, MX53_UART_PAD_CTRL)
-#define MX53_PAD_EIM_D28__IPU_DISPB0_SER_DIO		IOMUX_PAD(0x494, 0x14C, 3, 0x82C, 1, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D28__CSPI_MOSI			IOMUX_PAD(0x494, 0x14C, 4, 0x788, 1, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D28__I2C1_SDA			IOMUX_PAD(0x494, 0x14C, 5 | IOMUX_CONFIG_SION, 0x818, 1, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D28__IPU_EXT_TRIG			IOMUX_PAD(0x494, 0x14C, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D28__IPU_DI0_PIN13			IOMUX_PAD(0x494, 0x14C, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D29__EMI_WEIM_D_29			IOMUX_PAD(0x498, 0x150, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D29__GPIO3_29			IOMUX_PAD(0x498, 0x150, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D29__UART2_RTS			IOMUX_PAD(0x498, 0x150, 2, 0x87C, 1, MX53_UART_PAD_CTRL)
-#define MX53_PAD_EIM_D29__IPU_DISPB0_SER_RS		IOMUX_PAD(0x498, 0x150, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D29__CSPI_SS0			IOMUX_PAD(0x498, 0x150, 4, 0x78C, 2, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D29__IPU_DI1_PIN15			IOMUX_PAD(0x498, 0x150, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D29__IPU_CSI1_VSYNC		IOMUX_PAD(0x498, 0x150, 6, 0x83C, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D29__IPU_DI0_PIN14			IOMUX_PAD(0x498, 0x150, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D30__EMI_WEIM_D_30			IOMUX_PAD(0x49C, 0x154, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D30__GPIO3_30			IOMUX_PAD(0x49C, 0x154, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D30__UART3_CTS			IOMUX_PAD(0x49C, 0x154, 2, __NA_, 0, MX53_UART_PAD_CTRL)
-#define MX53_PAD_EIM_D30__IPU_CSI0_D_3			IOMUX_PAD(0x49C, 0x154, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D30__IPU_DI0_PIN11			IOMUX_PAD(0x49C, 0x154, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D30__IPU_DISP1_DAT_21		IOMUX_PAD(0x49C, 0x154, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D30__USBOH3_USBH1_OC		IOMUX_PAD(0x49C, 0x154, 6, 0x8A0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D30__USBOH3_USBH2_OC		IOMUX_PAD(0x49C, 0x154, 7, 0x8A4, 1, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D31__EMI_WEIM_D_31			IOMUX_PAD(0x4A0, 0x158, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D31__GPIO3_31			IOMUX_PAD(0x4A0, 0x158, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D31__UART3_RTS			IOMUX_PAD(0x4A0, 0x158, 2, 0x884, 3, MX53_UART_PAD_CTRL)
-#define MX53_PAD_EIM_D31__IPU_CSI0_D_2			IOMUX_PAD(0x4A0, 0x158, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D31__IPU_DI0_PIN12			IOMUX_PAD(0x4A0, 0x158, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D31__IPU_DISP1_DAT_20		IOMUX_PAD(0x4A0, 0x158, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D31__USBOH3_USBH1_PWR		IOMUX_PAD(0x4A0, 0x158, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D31__USBOH3_USBH2_PWR		IOMUX_PAD(0x4A0, 0x158, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A24__EMI_WEIM_A_24			IOMUX_PAD(0x4A8, 0x15C, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A24__GPIO5_4			IOMUX_PAD(0x4A8, 0x15C, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A24__IPU_DISP1_DAT_19		IOMUX_PAD(0x4A8, 0x15C, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A24__IPU_CSI1_D_19			IOMUX_PAD(0x4A8, 0x15C, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A24__IPU_SISG_2			IOMUX_PAD(0x4A8, 0x15C, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A24__USBPHY2_BVALID		IOMUX_PAD(0x4A8, 0x15C, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A23__EMI_WEIM_A_23			IOMUX_PAD(0x4AC, 0x160, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A23__GPIO6_6			IOMUX_PAD(0x4AC, 0x160, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A23__IPU_DISP1_DAT_18		IOMUX_PAD(0x4AC, 0x160, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A23__IPU_CSI1_D_18			IOMUX_PAD(0x4AC, 0x160, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A23__IPU_SISG_3			IOMUX_PAD(0x4AC, 0x160, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A23__USBPHY2_ENDSESSION		IOMUX_PAD(0x4AC, 0x160, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A22__EMI_WEIM_A_22			IOMUX_PAD(0x4B0, 0x164, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A22__GPIO2_16			IOMUX_PAD(0x4B0, 0x164, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A22__IPU_DISP1_DAT_17		IOMUX_PAD(0x4B0, 0x164, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A22__IPU_CSI1_D_17			IOMUX_PAD(0x4B0, 0x164, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A22__SRC_BT_CFG1_7			IOMUX_PAD(0x4B0, 0x164, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A21__EMI_WEIM_A_21			IOMUX_PAD(0x4B4, 0x168, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A21__GPIO2_17			IOMUX_PAD(0x4B4, 0x168, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A21__IPU_DISP1_DAT_16		IOMUX_PAD(0x4B4, 0x168, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A21__IPU_CSI1_D_16			IOMUX_PAD(0x4B4, 0x168, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A21__SRC_BT_CFG1_6			IOMUX_PAD(0x4B4, 0x168, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A20__EMI_WEIM_A_20			IOMUX_PAD(0x4B8, 0x16C, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A20__GPIO2_18			IOMUX_PAD(0x4B8, 0x16C, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A20__IPU_DISP1_DAT_15		IOMUX_PAD(0x4B8, 0x16C, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A20__IPU_CSI1_D_15			IOMUX_PAD(0x4B8, 0x16C, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A20__SRC_BT_CFG1_5			IOMUX_PAD(0x4B8, 0x16C, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A19__EMI_WEIM_A_19			IOMUX_PAD(0x4BC, 0x170, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A19__GPIO2_19			IOMUX_PAD(0x4BC, 0x170, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A19__IPU_DISP1_DAT_14		IOMUX_PAD(0x4BC, 0x170, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A19__IPU_CSI1_D_14			IOMUX_PAD(0x4BC, 0x170, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A19__SRC_BT_CFG1_4			IOMUX_PAD(0x4BC, 0x170, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A18__EMI_WEIM_A_18			IOMUX_PAD(0x4C0, 0x174, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A18__GPIO2_20			IOMUX_PAD(0x4C0, 0x174, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A18__IPU_DISP1_DAT_13		IOMUX_PAD(0x4C0, 0x174, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A18__IPU_CSI1_D_13			IOMUX_PAD(0x4C0, 0x174, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A18__SRC_BT_CFG1_3			IOMUX_PAD(0x4C0, 0x174, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A17__EMI_WEIM_A_17			IOMUX_PAD(0x4C4, 0x178, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A17__GPIO2_21			IOMUX_PAD(0x4C4, 0x178, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A17__IPU_DISP1_DAT_12		IOMUX_PAD(0x4C4, 0x178, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A17__IPU_CSI1_D_12			IOMUX_PAD(0x4C4, 0x178, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A17__SRC_BT_CFG1_2			IOMUX_PAD(0x4C4, 0x178, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A16__EMI_WEIM_A_16			IOMUX_PAD(0x4C8, 0x17C, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A16__GPIO2_22			IOMUX_PAD(0x4C8, 0x17C, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A16__IPU_DI1_DISP_CLK		IOMUX_PAD(0x4C8, 0x17C, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A16__IPU_CSI1_PIXCLK		IOMUX_PAD(0x4C8, 0x17C, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A16__SRC_BT_CFG1_1			IOMUX_PAD(0x4C8, 0x17C, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_CS0__EMI_WEIM_CS_0			IOMUX_PAD(0x4CC, 0x180, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_CS0__GPIO2_23			IOMUX_PAD(0x4CC, 0x180, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_CS0__ECSPI2_SCLK			IOMUX_PAD(0x4CC, 0x180, 2, 0x7B8, 2, NO_PAD_CTRL)
-#define MX53_PAD_EIM_CS0__IPU_DI1_PIN5			IOMUX_PAD(0x4CC, 0x180, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_CS1__EMI_WEIM_CS_1			IOMUX_PAD(0x4D0, 0x184, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_CS1__GPIO2_24			IOMUX_PAD(0x4D0, 0x184, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_CS1__ECSPI2_MOSI			IOMUX_PAD(0x4D0, 0x184, 2, 0x7C0, 2, NO_PAD_CTRL)
-#define MX53_PAD_EIM_CS1__IPU_DI1_PIN6			IOMUX_PAD(0x4D0, 0x184, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_OE__EMI_WEIM_OE			IOMUX_PAD(0x4D4, 0x188, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_OE__GPIO2_25			IOMUX_PAD(0x4D4, 0x188, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_OE__ECSPI2_MISO			IOMUX_PAD(0x4D4, 0x188, 2, 0x7BC, 2, NO_PAD_CTRL)
-#define MX53_PAD_EIM_OE__IPU_DI1_PIN7			IOMUX_PAD(0x4D4, 0x188, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_OE__USBPHY2_IDDIG			IOMUX_PAD(0x4D4, 0x188, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_RW__EMI_WEIM_RW			IOMUX_PAD(0x4D8, 0x18C, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_RW__GPIO2_26			IOMUX_PAD(0x4D8, 0x18C, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_RW__ECSPI2_SS0			IOMUX_PAD(0x4D8, 0x18C, 2, 0x7C4, 2, NO_PAD_CTRL)
-#define MX53_PAD_EIM_RW__IPU_DI1_PIN8			IOMUX_PAD(0x4D8, 0x18C, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_RW__USBPHY2_HOSTDISCONNECT		IOMUX_PAD(0x4D8, 0x18C, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_LBA__EMI_WEIM_LBA			IOMUX_PAD(0x4DC, 0x190, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_LBA__GPIO2_27			IOMUX_PAD(0x4DC, 0x190, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_LBA__ECSPI2_SS1			IOMUX_PAD(0x4DC, 0x190, 2, 0x7C8, 1, NO_PAD_CTRL)
-#define MX53_PAD_EIM_LBA__IPU_DI1_PIN17			IOMUX_PAD(0x4DC, 0x190, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_LBA__SRC_BT_CFG1_0			IOMUX_PAD(0x4DC, 0x190, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_EB0__EMI_WEIM_EB_0			IOMUX_PAD(0x4E4, 0x194, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_EB0__GPIO2_28			IOMUX_PAD(0x4E4, 0x194, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_EB0__IPU_DISP1_DAT_11		IOMUX_PAD(0x4E4, 0x194, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_EB0__IPU_CSI1_D_11			IOMUX_PAD(0x4E4, 0x194, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_EB0__GPC_PMIC_RDY			IOMUX_PAD(0x4E4, 0x194, 5, 0x810, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_EB0__SRC_BT_CFG2_7			IOMUX_PAD(0x4E4, 0x194, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_EB1__EMI_WEIM_EB_1			IOMUX_PAD(0x4E8, 0x198, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_EB1__GPIO2_29			IOMUX_PAD(0x4E8, 0x198, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_EB1__IPU_DISP1_DAT_10		IOMUX_PAD(0x4E8, 0x198, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_EB1__IPU_CSI1_D_10			IOMUX_PAD(0x4E8, 0x198, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_EB1__SRC_BT_CFG2_6			IOMUX_PAD(0x4E8, 0x198, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA0__EMI_NAND_WEIM_DA_0		IOMUX_PAD(0x4EC, 0x19C, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA0__GPIO3_0			IOMUX_PAD(0x4EC, 0x19C, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA0__IPU_DISP1_DAT_9		IOMUX_PAD(0x4EC, 0x19C, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA0__IPU_CSI1_D_9			IOMUX_PAD(0x4EC, 0x19C, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA0__SRC_BT_CFG2_5			IOMUX_PAD(0x4EC, 0x19C, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA1__EMI_NAND_WEIM_DA_1		IOMUX_PAD(0x4F0, 0x1A0, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA1__GPIO3_1			IOMUX_PAD(0x4F0, 0x1A0, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA1__IPU_DISP1_DAT_8		IOMUX_PAD(0x4F0, 0x1A0, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA1__IPU_CSI1_D_8			IOMUX_PAD(0x4F0, 0x1A0, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA1__SRC_BT_CFG2_4			IOMUX_PAD(0x4F0, 0x1A0, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA2__EMI_NAND_WEIM_DA_2		IOMUX_PAD(0x4F4, 0x1A4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA2__GPIO3_2			IOMUX_PAD(0x4F4, 0x1A4, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA2__IPU_DISP1_DAT_7		IOMUX_PAD(0x4F4, 0x1A4, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA2__IPU_CSI1_D_7			IOMUX_PAD(0x4F4, 0x1A4, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA2__SRC_BT_CFG2_3			IOMUX_PAD(0x4F4, 0x1A4, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA3__EMI_NAND_WEIM_DA_3		IOMUX_PAD(0x4F8, 0x1A8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA3__GPIO3_3			IOMUX_PAD(0x4F8, 0x1A8, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA3__IPU_DISP1_DAT_6		IOMUX_PAD(0x4F8, 0x1A8, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA3__IPU_CSI1_D_6			IOMUX_PAD(0x4F8, 0x1A8, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA3__SRC_BT_CFG2_2			IOMUX_PAD(0x4F8, 0x1A8, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA4__EMI_NAND_WEIM_DA_4		IOMUX_PAD(0x4FC, 0x1AC, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA4__GPIO3_4			IOMUX_PAD(0x4FC, 0x1AC, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA4__IPU_DISP1_DAT_5		IOMUX_PAD(0x4FC, 0x1AC, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA4__IPU_CSI1_D_5			IOMUX_PAD(0x4FC, 0x1AC, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA4__SRC_BT_CFG3_7			IOMUX_PAD(0x4FC, 0x1AC, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA5__EMI_NAND_WEIM_DA_5		IOMUX_PAD(0x500, 0x1B0, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA5__GPIO3_5			IOMUX_PAD(0x500, 0x1B0, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA5__IPU_DISP1_DAT_4		IOMUX_PAD(0x500, 0x1B0, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA5__IPU_CSI1_D_4			IOMUX_PAD(0x500, 0x1B0, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA5__SRC_BT_CFG3_6			IOMUX_PAD(0x500, 0x1B0, 7 | IOMUX_CONFIG_SION, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA6__EMI_NAND_WEIM_DA_6		IOMUX_PAD(0x504, 0x1B4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA6__GPIO3_6			IOMUX_PAD(0x504, 0x1B4, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA6__IPU_DISP1_DAT_3		IOMUX_PAD(0x504, 0x1B4, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA6__IPU_CSI1_D_3			IOMUX_PAD(0x504, 0x1B4, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA6__SRC_BT_CFG3_5			IOMUX_PAD(0x504, 0x1B4, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA7__EMI_NAND_WEIM_DA_7		IOMUX_PAD(0x508, 0x1B8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA7__GPIO3_7			IOMUX_PAD(0x508, 0x1B8, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA7__IPU_DISP1_DAT_2		IOMUX_PAD(0x508, 0x1B8, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA7__IPU_CSI1_D_2			IOMUX_PAD(0x508, 0x1B8, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA7__SRC_BT_CFG3_4			IOMUX_PAD(0x508, 0x1B8, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA8__EMI_NAND_WEIM_DA_8		IOMUX_PAD(0x50C, 0x1BC, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA8__GPIO3_8			IOMUX_PAD(0x50C, 0x1BC, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA8__IPU_DISP1_DAT_1		IOMUX_PAD(0x50C, 0x1BC, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA8__IPU_CSI1_D_1			IOMUX_PAD(0x50C, 0x1BC, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA8__SRC_BT_CFG3_3			IOMUX_PAD(0x50C, 0x1BC, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA9__EMI_NAND_WEIM_DA_9		IOMUX_PAD(0x510, 0x1C0, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA9__GPIO3_9			IOMUX_PAD(0x510, 0x1C0, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA9__IPU_DISP1_DAT_0		IOMUX_PAD(0x510, 0x1C0, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA9__IPU_CSI1_D_0			IOMUX_PAD(0x510, 0x1C0, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA9__SRC_BT_CFG3_2			IOMUX_PAD(0x510, 0x1C0, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA10__EMI_NAND_WEIM_DA_10		IOMUX_PAD(0x514, 0x1C4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA10__GPIO3_10			IOMUX_PAD(0x514, 0x1C4, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA10__IPU_DI1_PIN15		IOMUX_PAD(0x514, 0x1C4, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA10__IPU_CSI1_DATA_EN		IOMUX_PAD(0x514, 0x1C4, 4, 0x834, 1, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA10__SRC_BT_CFG3_1		IOMUX_PAD(0x514, 0x1C4, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA11__EMI_NAND_WEIM_DA_11		IOMUX_PAD(0x518, 0x1C8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA11__GPIO3_11			IOMUX_PAD(0x518, 0x1C8, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA11__IPU_DI1_PIN2			IOMUX_PAD(0x518, 0x1C8, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA11__IPU_CSI1_HSYNC		IOMUX_PAD(0x518, 0x1C8, 4, 0x838, 1, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA12__EMI_NAND_WEIM_DA_12		IOMUX_PAD(0x51C, 0x1CC, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA12__GPIO3_12			IOMUX_PAD(0x51C, 0x1CC, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA12__IPU_DI1_PIN3			IOMUX_PAD(0x51C, 0x1CC, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA12__IPU_CSI1_VSYNC		IOMUX_PAD(0x51C, 0x1CC, 4, 0x83C, 1, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA13__EMI_NAND_WEIM_DA_13		IOMUX_PAD(0x520, 0x1D0, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA13__GPIO3_13			IOMUX_PAD(0x520, 0x1D0, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA13__IPU_DI1_D0_CS		IOMUX_PAD(0x520, 0x1D0, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA13__CCM_DI1_EXT_CLK		IOMUX_PAD(0x520, 0x1D0, 4, 0x76C, 1, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA14__EMI_NAND_WEIM_DA_14		IOMUX_PAD(0x524, 0x1D4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA14__GPIO3_14			IOMUX_PAD(0x524, 0x1D4, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA14__IPU_DI1_D1_CS		IOMUX_PAD(0x524, 0x1D4, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA14__CCM_DI0_EXT_CLK		IOMUX_PAD(0x524, 0x1D4, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA15__EMI_NAND_WEIM_DA_15		IOMUX_PAD(0x528, 0x1D8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA15__GPIO3_15			IOMUX_PAD(0x528, 0x1D8, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA15__IPU_DI1_PIN1			IOMUX_PAD(0x528, 0x1D8, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA15__IPU_DI1_PIN4			IOMUX_PAD(0x528, 0x1D8, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_NANDF_WE_B__EMI_NANDF_WE_B		IOMUX_PAD(0x52C, 0x1DC, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_NANDF_WE_B__GPIO6_12			IOMUX_PAD(0x52C, 0x1DC, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_NANDF_RE_B__EMI_NANDF_RE_B		IOMUX_PAD(0x530, 0x1E0, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_NANDF_RE_B__GPIO6_13			IOMUX_PAD(0x530, 0x1E0, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_WAIT__EMI_WEIM_WAIT		IOMUX_PAD(0x534, 0x1E4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_WAIT__GPIO5_0			IOMUX_PAD(0x534, 0x1E4, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_WAIT__EMI_WEIM_DTACK_B		IOMUX_PAD(0x534, 0x1E4, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_LVDS1_TX3_P__GPIO6_22			IOMUX_PAD(__NA_, 0x1EC, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_LVDS1_TX3_P__LDB_LVDS1_TX3		IOMUX_PAD(__NA_, 0x1EC, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_LVDS1_TX2_P__GPIO6_24			IOMUX_PAD(__NA_, 0x1F0, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_LVDS1_TX2_P__LDB_LVDS1_TX2		IOMUX_PAD(__NA_, 0x1F0, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_LVDS1_CLK_P__GPIO6_26			IOMUX_PAD(__NA_, 0x1F4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_LVDS1_CLK_P__LDB_LVDS1_CLK		IOMUX_PAD(__NA_, 0x1F4, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_LVDS1_TX1_P__GPIO6_28			IOMUX_PAD(__NA_, 0x1F8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_LVDS1_TX1_P__LDB_LVDS1_TX1		IOMUX_PAD(__NA_, 0x1F8, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_LVDS1_TX0_P__GPIO6_30			IOMUX_PAD(__NA_, 0x1FC, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_LVDS1_TX0_P__LDB_LVDS1_TX0		IOMUX_PAD(__NA_, 0x1FC, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_LVDS0_TX3_P__GPIO7_22			IOMUX_PAD(__NA_, 0x200, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_LVDS0_TX3_P__LDB_LVDS0_TX3		IOMUX_PAD(__NA_, 0x200, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_LVDS0_CLK_P__GPIO7_24			IOMUX_PAD(__NA_, 0x204, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_LVDS0_CLK_P__LDB_LVDS0_CLK		IOMUX_PAD(__NA_, 0x204, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_LVDS0_TX2_P__GPIO7_26			IOMUX_PAD(__NA_, 0x208, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_LVDS0_TX2_P__LDB_LVDS0_TX2		IOMUX_PAD(__NA_, 0x208, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_LVDS0_TX1_P__GPIO7_28			IOMUX_PAD(__NA_, 0x20C, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_LVDS0_TX1_P__LDB_LVDS0_TX1		IOMUX_PAD(__NA_, 0x20C, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_LVDS0_TX0_P__GPIO7_30			IOMUX_PAD(__NA_, 0x210, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_LVDS0_TX0_P__LDB_LVDS0_TX0		IOMUX_PAD(__NA_, 0x210, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_10__GPIO4_0			IOMUX_PAD(0x540, 0x214, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_10__OSC32k_32K_OUT		IOMUX_PAD(0x540, 0x214, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_11__GPIO4_1			IOMUX_PAD(0x544, 0x218, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_12__GPIO4_2			IOMUX_PAD(0x548, 0x21C, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_13__GPIO4_3			IOMUX_PAD(0x54C, 0x220, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_14__GPIO4_4			IOMUX_PAD(0x550, 0x224, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_NANDF_CLE__EMI_NANDF_CLE		IOMUX_PAD(0x5A0, 0x228, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_NANDF_CLE__GPIO6_7			IOMUX_PAD(0x5A0, 0x228, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_NANDF_CLE__USBPHY1_VSTATUS_0		IOMUX_PAD(0x5A0, 0x228, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_NANDF_ALE__EMI_NANDF_ALE		IOMUX_PAD(0x5A4, 0x22C, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_NANDF_ALE__GPIO6_8			IOMUX_PAD(0x5A4, 0x22C, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_NANDF_ALE__USBPHY1_VSTATUS_1		IOMUX_PAD(0x5A4, 0x22C, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_NANDF_WP_B__EMI_NANDF_WP_B		IOMUX_PAD(0x5A8, 0x230, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_NANDF_WP_B__GPIO6_9			IOMUX_PAD(0x5A8, 0x230, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_NANDF_WP_B__USBPHY1_VSTATUS_2		IOMUX_PAD(0x5A8, 0x230, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_NANDF_RB0__EMI_NANDF_RB_0		IOMUX_PAD(0x5AC, 0x234, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_NANDF_RB0__GPIO6_10			IOMUX_PAD(0x5AC, 0x234, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_NANDF_RB0__USBPHY1_VSTATUS_3		IOMUX_PAD(0x5AC, 0x234, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_NANDF_CS0__EMI_NANDF_CS_0		IOMUX_PAD(0x5B0, 0x238, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_NANDF_CS0__GPIO6_11			IOMUX_PAD(0x5B0, 0x238, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_NANDF_CS0__USBPHY1_VSTATUS_4		IOMUX_PAD(0x5B0, 0x238, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_NANDF_CS1__EMI_NANDF_CS_1		IOMUX_PAD(0x5B4, 0x23C, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_NANDF_CS1__GPIO6_14			IOMUX_PAD(0x5B4, 0x23C, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_NANDF_CS1__MLB_MLBCLK			IOMUX_PAD(0x5B4, 0x23C, 6, 0x858, 0, NO_PAD_CTRL)
-#define MX53_PAD_NANDF_CS1__USBPHY1_VSTATUS_5		IOMUX_PAD(0x5B4, 0x23C, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_NANDF_CS2__EMI_NANDF_CS_2		IOMUX_PAD(0x5B8, 0x240, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_NANDF_CS2__GPIO6_15			IOMUX_PAD(0x5B8, 0x240, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_NANDF_CS2__IPU_SISG_0			IOMUX_PAD(0x5B8, 0x240, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_NANDF_CS2__ESAI1_TX0			IOMUX_PAD(0x5B8, 0x240, 3, 0x7E4, 0, NO_PAD_CTRL)
-#define MX53_PAD_NANDF_CS2__EMI_WEIM_CRE		IOMUX_PAD(0x5B8, 0x240, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_NANDF_CS2__CCM_CSI0_MCLK		IOMUX_PAD(0x5B8, 0x240, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_NANDF_CS2__MLB_MLBSIG			IOMUX_PAD(0x5B8, 0x240, 6, 0x860, 0, NO_PAD_CTRL)
-#define MX53_PAD_NANDF_CS2__USBPHY1_VSTATUS_6		IOMUX_PAD(0x5B8, 0x240, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_NANDF_CS3__EMI_NANDF_CS_3		IOMUX_PAD(0x5BC, 0x244, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_NANDF_CS3__GPIO6_16			IOMUX_PAD(0x5BC, 0x244, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_NANDF_CS3__IPU_SISG_1			IOMUX_PAD(0x5BC, 0x244, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_NANDF_CS3__ESAI1_TX1			IOMUX_PAD(0x5BC, 0x244, 3, 0x7E8, 0, NO_PAD_CTRL)
-#define MX53_PAD_NANDF_CS3__EMI_WEIM_A_26		IOMUX_PAD(0x5BC, 0x244, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_NANDF_CS3__MLB_MLBDAT			IOMUX_PAD(0x5BC, 0x244, 6, 0x85C, 0, NO_PAD_CTRL)
-#define MX53_PAD_NANDF_CS3__USBPHY1_VSTATUS_7		IOMUX_PAD(0x5BC, 0x244, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_FEC_MDIO__FEC_MDIO			IOMUX_PAD(0x5C4, 0x248, 0, 0x804, 1, NO_PAD_CTRL)
-#define MX53_PAD_FEC_MDIO__GPIO1_22			IOMUX_PAD(0x5C4, 0x248, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_FEC_MDIO__ESAI1_SCKR			IOMUX_PAD(0x5C4, 0x248, 2, 0x7DC, 0, NO_PAD_CTRL)
-#define MX53_PAD_FEC_MDIO__FEC_COL			IOMUX_PAD(0x5C4, 0x248, 3, 0x800, 1, NO_PAD_CTRL)
-#define MX53_PAD_FEC_MDIO__RTC_CE_RTC_PS2		IOMUX_PAD(0x5C4, 0x248, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_FEC_MDIO__SDMA_DEBUG_BUS_DEVICE_3	IOMUX_PAD(0x5C4, 0x248, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_FEC_MDIO__EMI_EMI_DEBUG_49		IOMUX_PAD(0x5C4, 0x248, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_FEC_REF_CLK__FEC_TX_CLK		IOMUX_PAD(0x5C8, 0x24C, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_FEC_REF_CLK__GPIO1_23			IOMUX_PAD(0x5C8, 0x24C, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_FEC_REF_CLK__ESAI1_FSR			IOMUX_PAD(0x5C8, 0x24C, 2, 0x7CC, 0, NO_PAD_CTRL)
-#define MX53_PAD_FEC_REF_CLK__SDMA_DEBUG_BUS_DEVICE_4	IOMUX_PAD(0x5C8, 0x24C, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_FEC_REF_CLK__EMI_EMI_DEBUG_50		IOMUX_PAD(0x5C8, 0x24C, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_FEC_RX_ER__FEC_RX_ER			IOMUX_PAD(0x5CC, 0x250, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_FEC_RX_ER__GPIO1_24			IOMUX_PAD(0x5CC, 0x250, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_FEC_RX_ER__ESAI1_HCKR			IOMUX_PAD(0x5CC, 0x250, 2, 0x7D4, 0, NO_PAD_CTRL)
-#define MX53_PAD_FEC_RX_ER__FEC_RX_CLK			IOMUX_PAD(0x5CC, 0x250, 3, 0x808, 1, NO_PAD_CTRL)
-#define MX53_PAD_FEC_RX_ER__RTC_CE_RTC_PS3		IOMUX_PAD(0x5CC, 0x250, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_FEC_CRS_DV__FEC_RX_DV			IOMUX_PAD(0x5D0, 0x254, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_FEC_CRS_DV__GPIO1_25			IOMUX_PAD(0x5D0, 0x254, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_FEC_CRS_DV__ESAI1_SCKT			IOMUX_PAD(0x5D0, 0x254, 2, 0x7E0, 0, NO_PAD_CTRL)
-#define MX53_PAD_FEC_RXD1__FEC_RDATA_1			IOMUX_PAD(0x5D4, 0x258, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_FEC_RXD1__GPIO1_26			IOMUX_PAD(0x5D4, 0x258, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_FEC_RXD1__ESAI1_FST			IOMUX_PAD(0x5D4, 0x258, 2, 0x7D0, 0, NO_PAD_CTRL)
-#define MX53_PAD_FEC_RXD1__MLB_MLBSIG			IOMUX_PAD(0x5D4, 0x258, 3, 0x860, 1, NO_PAD_CTRL)
-#define MX53_PAD_FEC_RXD1__RTC_CE_RTC_PS1		IOMUX_PAD(0x5D4, 0x258, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_FEC_RXD0__FEC_RDATA_0			IOMUX_PAD(0x5D8, 0x25C, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_FEC_RXD0__GPIO1_27			IOMUX_PAD(0x5D8, 0x25C, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_FEC_RXD0__ESAI1_HCKT			IOMUX_PAD(0x5D8, 0x25C, 2, 0x7D8, 0, NO_PAD_CTRL)
-#define MX53_PAD_FEC_RXD0__OSC32k_32K_OUT		IOMUX_PAD(0x5D8, 0x25C, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_FEC_TX_EN__FEC_TX_EN			IOMUX_PAD(0x5DC, 0x260, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_FEC_TX_EN__GPIO1_28			IOMUX_PAD(0x5DC, 0x260, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_FEC_TX_EN__ESAI1_TX3_RX2		IOMUX_PAD(0x5DC, 0x260, 2, 0x7F0, 0, NO_PAD_CTRL)
-#define MX53_PAD_FEC_TXD1__FEC_TDATA_1			IOMUX_PAD(0x5E0, 0x264, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_FEC_TXD1__GPIO1_29			IOMUX_PAD(0x5E0, 0x264, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_FEC_TXD1__ESAI1_TX2_RX3		IOMUX_PAD(0x5E0, 0x264, 2, 0x7EC, 0, NO_PAD_CTRL)
-#define MX53_PAD_FEC_TXD1__MLB_MLBCLK			IOMUX_PAD(0x5E0, 0x264, 3, 0x858, 1, NO_PAD_CTRL)
-#define MX53_PAD_FEC_TXD1__RTC_CE_RTC_PRSC_CLK		IOMUX_PAD(0x5E0, 0x264, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_FEC_TXD0__FEC_TDATA_0			IOMUX_PAD(0x5E4, 0x268, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_FEC_TXD0__GPIO1_30			IOMUX_PAD(0x5E4, 0x268, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_FEC_TXD0__ESAI1_TX4_RX1		IOMUX_PAD(0x5E4, 0x268, 2, 0x7F4, 0, NO_PAD_CTRL)
-#define MX53_PAD_FEC_TXD0__USBPHY2_DATAOUT_0		IOMUX_PAD(0x5E4, 0x268, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_FEC_MDC__FEC_MDC			IOMUX_PAD(0x5E8, 0x26C, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_FEC_MDC__GPIO1_31			IOMUX_PAD(0x5E8, 0x26C, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_FEC_MDC__ESAI1_TX5_RX0			IOMUX_PAD(0x5E8, 0x26C, 2, 0x7F8, 0, NO_PAD_CTRL)
-#define MX53_PAD_FEC_MDC__MLB_MLBDAT			IOMUX_PAD(0x5E8, 0x26C, 3, 0x85C, 1, NO_PAD_CTRL)
-#define MX53_PAD_FEC_MDC__RTC_CE_RTC_ALARM1_TRIG	IOMUX_PAD(0x5E8, 0x26C, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_FEC_MDC__USBPHY2_DATAOUT_1		IOMUX_PAD(0x5E8, 0x26C, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DIOW__PATA_DIOW			IOMUX_PAD(0x5F0, 0x270, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DIOW__GPIO6_17			IOMUX_PAD(0x5F0, 0x270, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DIOW__UART1_TXD_MUX		IOMUX_PAD(0x5F0, 0x270, 3, __NA_, 0, MX53_UART_PAD_CTRL)
-#define MX53_PAD_PATA_DIOW__USBPHY2_DATAOUT_2		IOMUX_PAD(0x5F0, 0x270, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DMACK__PATA_DMACK			IOMUX_PAD(0x5F4, 0x274, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DMACK__GPIO6_18			IOMUX_PAD(0x5F4, 0x274, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DMACK__UART1_RXD_MUX		IOMUX_PAD(0x5F4, 0x274, 3, 0x878, 3, MX53_UART_PAD_CTRL)
-#define MX53_PAD_PATA_DMACK__USBPHY2_DATAOUT_3		IOMUX_PAD(0x5F4, 0x274, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DMARQ__PATA_DMARQ			IOMUX_PAD(0x5F8, 0x278, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DMARQ__GPIO7_0			IOMUX_PAD(0x5F8, 0x278, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DMARQ__UART2_TXD_MUX		IOMUX_PAD(0x5F8, 0x278, 3, __NA_, 0, MX53_UART_PAD_CTRL)
-#define MX53_PAD_PATA_DMARQ__CCM_CCM_OUT_0		IOMUX_PAD(0x5F8, 0x278, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DMARQ__USBPHY2_DATAOUT_4		IOMUX_PAD(0x5F8, 0x278, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_BUFFER_EN__PATA_BUFFER_EN		IOMUX_PAD(0x5FC, 0x27C, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_BUFFER_EN__GPIO7_1		IOMUX_PAD(0x5FC, 0x27C, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX		IOMUX_PAD(0x5FC, 0x27C, 3, 0x880, 3, MX53_UART_PAD_CTRL)
-#define MX53_PAD_PATA_BUFFER_EN__CCM_CCM_OUT_1		IOMUX_PAD(0x5FC, 0x27C, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_BUFFER_EN__USBPHY2_DATAOUT_5	IOMUX_PAD(0x5FC, 0x27C, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_INTRQ__PATA_INTRQ			IOMUX_PAD(0x600, 0x280, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_INTRQ__GPIO7_2			IOMUX_PAD(0x600, 0x280, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_INTRQ__UART2_CTS			IOMUX_PAD(0x600, 0x280, 3, __NA_, 0, MX53_UART_PAD_CTRL)
-#define MX53_PAD_PATA_INTRQ__CAN1_TXCAN			IOMUX_PAD(0x600, 0x280, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_INTRQ__CCM_CCM_OUT_2		IOMUX_PAD(0x600, 0x280, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_INTRQ__USBPHY2_DATAOUT_6		IOMUX_PAD(0x600, 0x280, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DIOR__PATA_DIOR			IOMUX_PAD(0x604, 0x284, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DIOR__GPIO7_3			IOMUX_PAD(0x604, 0x284, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DIOR__UART2_RTS			IOMUX_PAD(0x604, 0x284, 3, 0x87C, 3, MX53_UART_PAD_CTRL)
-#define MX53_PAD_PATA_DIOR__CAN1_RXCAN			IOMUX_PAD(0x604, 0x284, 4, 0x760, 1, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DIOR__USBPHY2_DATAOUT_7		IOMUX_PAD(0x604, 0x284, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_RESET_B__PATA_PATA_RESET_B	IOMUX_PAD(0x608, 0x288, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_RESET_B__GPIO7_4			IOMUX_PAD(0x608, 0x288, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_RESET_B__ESDHC3_CMD		IOMUX_PAD(0x608, 0x288, 2, __NA_, 0, MX53_SDHC_PAD_CTRL)
-#define MX53_PAD_PATA_RESET_B__UART1_CTS		IOMUX_PAD(0x608, 0x288, 3, __NA_, 0, MX53_UART_PAD_CTRL)
-#define MX53_PAD_PATA_RESET_B__CAN2_TXCAN		IOMUX_PAD(0x608, 0x288, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_RESET_B__USBPHY1_DATAOUT_0	IOMUX_PAD(0x608, 0x288, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_IORDY__PATA_IORDY			IOMUX_PAD(0x60C, 0x28C, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_IORDY__GPIO7_5			IOMUX_PAD(0x60C, 0x28C, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_IORDY__ESDHC3_CLK			IOMUX_PAD(0x60C, 0x28C, 2, __NA_, 0, MX53_SDHC_PAD_CTRL)
-#define MX53_PAD_PATA_IORDY__UART1_RTS			IOMUX_PAD(0x60C, 0x28C, 3, 0x874, 3, MX53_UART_PAD_CTRL)
-#define MX53_PAD_PATA_IORDY__CAN2_RXCAN			IOMUX_PAD(0x60C, 0x28C, 4, 0x764, 1, NO_PAD_CTRL)
-#define MX53_PAD_PATA_IORDY__USBPHY1_DATAOUT_1		IOMUX_PAD(0x60C, 0x28C, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DA_0__PATA_DA_0			IOMUX_PAD(0x610, 0x290, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DA_0__GPIO7_6			IOMUX_PAD(0x610, 0x290, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DA_0__ESDHC3_RST			IOMUX_PAD(0x610, 0x290, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DA_0__OWIRE_LINE			IOMUX_PAD(0x610, 0x290, 4, 0x864, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DA_0__USBPHY1_DATAOUT_2		IOMUX_PAD(0x610, 0x290, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DA_1__PATA_DA_1			IOMUX_PAD(0x614, 0x294, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DA_1__GPIO7_7			IOMUX_PAD(0x614, 0x294, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DA_1__ESDHC4_CMD			IOMUX_PAD(0x614, 0x294, 2, __NA_, 0, MX53_SDHC_PAD_CTRL)
-#define MX53_PAD_PATA_DA_1__UART3_CTS			IOMUX_PAD(0x614, 0x294, 4, __NA_, 0, MX53_UART_PAD_CTRL)
-#define MX53_PAD_PATA_DA_1__USBPHY1_DATAOUT_3		IOMUX_PAD(0x614, 0x294, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DA_2__PATA_DA_2			IOMUX_PAD(0x618, 0x298, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DA_2__GPIO7_8			IOMUX_PAD(0x618, 0x298, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DA_2__ESDHC4_CLK			IOMUX_PAD(0x618, 0x298, 2, __NA_, 0, MX53_SDHC_PAD_CTRL)
-#define MX53_PAD_PATA_DA_2__UART3_RTS			IOMUX_PAD(0x618, 0x298, 4, 0x884, 5, MX53_UART_PAD_CTRL)
-#define MX53_PAD_PATA_DA_2__USBPHY1_DATAOUT_4		IOMUX_PAD(0x618, 0x298, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_CS_0__PATA_CS_0			IOMUX_PAD(0x61C, 0x29C, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_CS_0__GPIO7_9			IOMUX_PAD(0x61C, 0x29C, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_CS_0__UART3_TXD_MUX		IOMUX_PAD(0x61C, 0x29C, 4, __NA_, 0, MX53_UART_PAD_CTRL)
-#define MX53_PAD_PATA_CS_0__USBPHY1_DATAOUT_5		IOMUX_PAD(0x61C, 0x29C, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_CS_1__PATA_CS_1			IOMUX_PAD(0x620, 0x2A0, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_CS_1__GPIO7_10			IOMUX_PAD(0x620, 0x2A0, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_CS_1__UART3_RXD_MUX		IOMUX_PAD(0x620, 0x2A0, 4, 0x888, 3, MX53_UART_PAD_CTRL)
-#define MX53_PAD_PATA_CS_1__USBPHY1_DATAOUT_6		IOMUX_PAD(0x620, 0x2A0, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA0__PATA_DATA_0		IOMUX_PAD(0x628, 0x2A4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA0__GPIO2_0			IOMUX_PAD(0x628, 0x2A4, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA0__EMI_NANDF_D_0		IOMUX_PAD(0x628, 0x2A4, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA0__ESDHC3_DAT4		IOMUX_PAD(0x628, 0x2A4, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
-#define MX53_PAD_PATA_DATA0__GPU3d_GPU_DEBUG_OUT_0	IOMUX_PAD(0x628, 0x2A4, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA0__IPU_DIAG_BUS_0		IOMUX_PAD(0x628, 0x2A4, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA0__USBPHY1_DATAOUT_7		IOMUX_PAD(0x628, 0x2A4, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA1__PATA_DATA_1		IOMUX_PAD(0x62C, 0x2A8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA1__GPIO2_1			IOMUX_PAD(0x62C, 0x2A8, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA1__EMI_NANDF_D_1		IOMUX_PAD(0x62C, 0x2A8, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA1__ESDHC3_DAT5		IOMUX_PAD(0x62C, 0x2A8, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
-#define MX53_PAD_PATA_DATA1__GPU3d_GPU_DEBUG_OUT_1	IOMUX_PAD(0x62C, 0x2A8, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA1__IPU_DIAG_BUS_1		IOMUX_PAD(0x62C, 0x2A8, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA2__PATA_DATA_2		IOMUX_PAD(0x630, 0x2AC, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA2__GPIO2_2			IOMUX_PAD(0x630, 0x2AC, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA2__EMI_NANDF_D_2		IOMUX_PAD(0x630, 0x2AC, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA2__ESDHC3_DAT6		IOMUX_PAD(0x630, 0x2AC, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
-#define MX53_PAD_PATA_DATA2__GPU3d_GPU_DEBUG_OUT_2	IOMUX_PAD(0x630, 0x2AC, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA2__IPU_DIAG_BUS_2		IOMUX_PAD(0x630, 0x2AC, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA3__PATA_DATA_3		IOMUX_PAD(0x634, 0x2B0, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA3__GPIO2_3			IOMUX_PAD(0x634, 0x2B0, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA3__EMI_NANDF_D_3		IOMUX_PAD(0x634, 0x2B0, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA3__ESDHC3_DAT7		IOMUX_PAD(0x634, 0x2B0, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
-#define MX53_PAD_PATA_DATA3__GPU3d_GPU_DEBUG_OUT_3	IOMUX_PAD(0x634, 0x2B0, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA3__IPU_DIAG_BUS_3		IOMUX_PAD(0x634, 0x2B0, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA4__PATA_DATA_4		IOMUX_PAD(0x638, 0x2B4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA4__GPIO2_4			IOMUX_PAD(0x638, 0x2B4, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA4__EMI_NANDF_D_4		IOMUX_PAD(0x638, 0x2B4, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA4__ESDHC4_DAT4		IOMUX_PAD(0x638, 0x2B4, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
-#define MX53_PAD_PATA_DATA4__GPU3d_GPU_DEBUG_OUT_4	IOMUX_PAD(0x638, 0x2B4, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA4__IPU_DIAG_BUS_4		IOMUX_PAD(0x638, 0x2B4, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA5__PATA_DATA_5		IOMUX_PAD(0x63C, 0x2B8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA5__GPIO2_5			IOMUX_PAD(0x63C, 0x2B8, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA5__EMI_NANDF_D_5		IOMUX_PAD(0x63C, 0x2B8, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA5__ESDHC4_DAT5		IOMUX_PAD(0x63C, 0x2B8, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
-#define MX53_PAD_PATA_DATA5__GPU3d_GPU_DEBUG_OUT_5	IOMUX_PAD(0x63C, 0x2B8, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA5__IPU_DIAG_BUS_5		IOMUX_PAD(0x63C, 0x2B8, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA6__PATA_DATA_6		IOMUX_PAD(0x640, 0x2BC, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA6__GPIO2_6			IOMUX_PAD(0x640, 0x2BC, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA6__EMI_NANDF_D_6		IOMUX_PAD(0x640, 0x2BC, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA6__ESDHC4_DAT6		IOMUX_PAD(0x640, 0x2BC, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
-#define MX53_PAD_PATA_DATA6__GPU3d_GPU_DEBUG_OUT_6	IOMUX_PAD(0x640, 0x2BC, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA6__IPU_DIAG_BUS_6		IOMUX_PAD(0x640, 0x2BC, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA7__PATA_DATA_7		IOMUX_PAD(0x644, 0x2C0, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA7__GPIO2_7			IOMUX_PAD(0x644, 0x2C0, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA7__EMI_NANDF_D_7		IOMUX_PAD(0x644, 0x2C0, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA7__ESDHC4_DAT7		IOMUX_PAD(0x644, 0x2C0, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
-#define MX53_PAD_PATA_DATA7__GPU3d_GPU_DEBUG_OUT_7	IOMUX_PAD(0x644, 0x2C0, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA7__IPU_DIAG_BUS_7		IOMUX_PAD(0x644, 0x2C0, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA8__PATA_DATA_8		IOMUX_PAD(0x648, 0x2C4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA8__GPIO2_8			IOMUX_PAD(0x648, 0x2C4, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA8__ESDHC1_DAT4		IOMUX_PAD(0x648, 0x2C4, 2, __NA_, 0, MX53_SDHC_PAD_CTRL)
-#define MX53_PAD_PATA_DATA8__EMI_NANDF_D_8		IOMUX_PAD(0x648, 0x2C4, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA8__ESDHC3_DAT0		IOMUX_PAD(0x648, 0x2C4, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
-#define MX53_PAD_PATA_DATA8__GPU3d_GPU_DEBUG_OUT_8	IOMUX_PAD(0x648, 0x2C4, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA8__IPU_DIAG_BUS_8		IOMUX_PAD(0x648, 0x2C4, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA9__PATA_DATA_9		IOMUX_PAD(0x64C, 0x2C8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA9__GPIO2_9			IOMUX_PAD(0x64C, 0x2C8, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA9__ESDHC1_DAT5		IOMUX_PAD(0x64C, 0x2C8, 2, __NA_, 0, MX53_SDHC_PAD_CTRL)
-#define MX53_PAD_PATA_DATA9__EMI_NANDF_D_9		IOMUX_PAD(0x64C, 0x2C8, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA9__ESDHC3_DAT1		IOMUX_PAD(0x64C, 0x2C8, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
-#define MX53_PAD_PATA_DATA9__GPU3d_GPU_DEBUG_OUT_9	IOMUX_PAD(0x64C, 0x2C8, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA9__IPU_DIAG_BUS_9		IOMUX_PAD(0x64C, 0x2C8, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA10__PATA_DATA_10		IOMUX_PAD(0x650, 0x2CC, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA10__GPIO2_10			IOMUX_PAD(0x650, 0x2CC, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA10__ESDHC1_DAT6		IOMUX_PAD(0x650, 0x2CC, 2, __NA_, 0, MX53_SDHC_PAD_CTRL)
-#define MX53_PAD_PATA_DATA10__EMI_NANDF_D_10		IOMUX_PAD(0x650, 0x2CC, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA10__ESDHC3_DAT2		IOMUX_PAD(0x650, 0x2CC, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
-#define MX53_PAD_PATA_DATA10__GPU3d_GPU_DEBUG_OUT_10	IOMUX_PAD(0x650, 0x2CC, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA10__IPU_DIAG_BUS_10		IOMUX_PAD(0x650, 0x2CC, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA11__PATA_DATA_11		IOMUX_PAD(0x654, 0x2D0, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA11__GPIO2_11			IOMUX_PAD(0x654, 0x2D0, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA11__ESDHC1_DAT7		IOMUX_PAD(0x654, 0x2D0, 2, __NA_, 0, MX53_SDHC_PAD_CTRL)
-#define MX53_PAD_PATA_DATA11__EMI_NANDF_D_11		IOMUX_PAD(0x654, 0x2D0, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA11__ESDHC3_DAT3		IOMUX_PAD(0x654, 0x2D0, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
-#define MX53_PAD_PATA_DATA11__GPU3d_GPU_DEBUG_OUT_11	IOMUX_PAD(0x654, 0x2D0, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA11__IPU_DIAG_BUS_11		IOMUX_PAD(0x654, 0x2D0, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA12__PATA_DATA_12		IOMUX_PAD(0x658, 0x2D4, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA12__GPIO2_12			IOMUX_PAD(0x658, 0x2D4, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA12__ESDHC2_DAT4		IOMUX_PAD(0x658, 0x2D4, 2, __NA_, 0, MX53_SDHC_PAD_CTRL)
-#define MX53_PAD_PATA_DATA12__EMI_NANDF_D_12		IOMUX_PAD(0x658, 0x2D4, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA12__ESDHC4_DAT0		IOMUX_PAD(0x658, 0x2D4, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
-#define MX53_PAD_PATA_DATA12__GPU3d_GPU_DEBUG_OUT_12	IOMUX_PAD(0x658, 0x2D4, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA12__IPU_DIAG_BUS_12		IOMUX_PAD(0x658, 0x2D4, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA13__PATA_DATA_13		IOMUX_PAD(0x65C, 0x2D8, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA13__GPIO2_13			IOMUX_PAD(0x65C, 0x2D8, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA13__ESDHC2_DAT5		IOMUX_PAD(0x65C, 0x2D8, 2, __NA_, 0, MX53_SDHC_PAD_CTRL)
-#define MX53_PAD_PATA_DATA13__EMI_NANDF_D_13		IOMUX_PAD(0x65C, 0x2D8, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA13__ESDHC4_DAT1		IOMUX_PAD(0x65C, 0x2D8, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
-#define MX53_PAD_PATA_DATA13__GPU3d_GPU_DEBUG_OUT_13	IOMUX_PAD(0x65C, 0x2D8, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA13__IPU_DIAG_BUS_13		IOMUX_PAD(0x65C, 0x2D8, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA14__PATA_DATA_14		IOMUX_PAD(0x660, 0x2DC, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA14__GPIO2_14			IOMUX_PAD(0x660, 0x2DC, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA14__ESDHC2_DAT6		IOMUX_PAD(0x660, 0x2DC, 2, __NA_, 0, MX53_SDHC_PAD_CTRL)
-#define MX53_PAD_PATA_DATA14__EMI_NANDF_D_14		IOMUX_PAD(0x660, 0x2DC, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA14__ESDHC4_DAT2		IOMUX_PAD(0x660, 0x2DC, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
-#define MX53_PAD_PATA_DATA14__GPU3d_GPU_DEBUG_OUT_14	IOMUX_PAD(0x660, 0x2DC, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA14__IPU_DIAG_BUS_14		IOMUX_PAD(0x660, 0x2DC, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA15__PATA_DATA_15		IOMUX_PAD(0x664, 0x2E0, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA15__GPIO2_15			IOMUX_PAD(0x664, 0x2E0, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA15__ESDHC2_DAT7		IOMUX_PAD(0x664, 0x2E0, 2, __NA_, 0, MX53_SDHC_PAD_CTRL)
-#define MX53_PAD_PATA_DATA15__EMI_NANDF_D_15		IOMUX_PAD(0x664, 0x2E0, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA15__ESDHC4_DAT3		IOMUX_PAD(0x664, 0x2E0, 4, __NA_, 0, MX53_SDHC_PAD_CTRL)
-#define MX53_PAD_PATA_DATA15__GPU3d_GPU_DEBUG_OUT_15	IOMUX_PAD(0x664, 0x2E0, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_PATA_DATA15__IPU_DIAG_BUS_15		IOMUX_PAD(0x664, 0x2E0, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_SD1_DATA0__ESDHC1_DAT0			IOMUX_PAD(0x66C, 0x2E4, 0, __NA_, 0, MX53_SDHC_PAD_CTRL)
-#define MX53_PAD_SD1_DATA0__GPIO1_16			IOMUX_PAD(0x66C, 0x2E4, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_SD1_DATA0__GPT_CAPIN1			IOMUX_PAD(0x66C, 0x2E4, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_SD1_DATA0__CSPI_MISO			IOMUX_PAD(0x66C, 0x2E4, 5, 0x784, 2, NO_PAD_CTRL)
-#define MX53_PAD_SD1_DATA0__CCM_PLL3_BYP		IOMUX_PAD(0x66C, 0x2E4, 7, 0x778, 0, NO_PAD_CTRL)
-#define MX53_PAD_SD1_DATA1__ESDHC1_DAT1			IOMUX_PAD(0x670, 0x2E8, 0, __NA_, 0, MX53_SDHC_PAD_CTRL)
-#define MX53_PAD_SD1_DATA1__GPIO1_17			IOMUX_PAD(0x670, 0x2E8, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_SD1_DATA1__GPT_CAPIN2			IOMUX_PAD(0x670, 0x2E8, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_SD1_DATA1__CSPI_SS0			IOMUX_PAD(0x670, 0x2E8, 5, 0x78C, 3, NO_PAD_CTRL)
-#define MX53_PAD_SD1_DATA1__CCM_PLL4_BYP		IOMUX_PAD(0x670, 0x2E8, 7, 0x77C, 1, NO_PAD_CTRL)
-#define MX53_PAD_SD1_CMD__ESDHC1_CMD			IOMUX_PAD(0x674, 0x2EC, 0 | IOMUX_CONFIG_SION, __NA_, 0, MX53_SDHC_PAD_CTRL)
-#define MX53_PAD_SD1_CMD__GPIO1_18			IOMUX_PAD(0x674, 0x2EC, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_SD1_CMD__GPT_CMPOUT1			IOMUX_PAD(0x674, 0x2EC, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_SD1_CMD__CSPI_MOSI			IOMUX_PAD(0x674, 0x2EC, 5, 0x788, 2, NO_PAD_CTRL)
-#define MX53_PAD_SD1_CMD__CCM_PLL1_BYP			IOMUX_PAD(0x674, 0x2EC, 7, 0x770, 0, NO_PAD_CTRL)
-#define MX53_PAD_SD1_DATA2__ESDHC1_DAT2			IOMUX_PAD(0x678, 0x2F0, 0, __NA_, 0, MX53_SDHC_PAD_CTRL)
-#define MX53_PAD_SD1_DATA2__GPIO1_19			IOMUX_PAD(0x678, 0x2F0, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_SD1_DATA2__GPT_CMPOUT2			IOMUX_PAD(0x678, 0x2F0, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_SD1_DATA2__PWM2_PWMO			IOMUX_PAD(0x678, 0x2F0, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_SD1_DATA2__WDOG1_WDOG_B		IOMUX_PAD(0x678, 0x2F0, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_SD1_DATA2__CSPI_SS1			IOMUX_PAD(0x678, 0x2F0, 5, 0x790, 2, NO_PAD_CTRL)
-#define MX53_PAD_SD1_DATA2__WDOG1_WDOG_RST_B_DEB	IOMUX_PAD(0x678, 0x2F0, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_SD1_DATA2__CCM_PLL2_BYP		IOMUX_PAD(0x678, 0x2F0, 7, 0x774, 0, NO_PAD_CTRL)
-#define MX53_PAD_SD1_CLK__ESDHC1_CLK			IOMUX_PAD(0x67C, 0x2F4, 0, __NA_, 0, MX53_SDHC_PAD_CTRL)
-#define MX53_PAD_SD1_CLK__GPIO1_20			IOMUX_PAD(0x67C, 0x2F4, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_SD1_CLK__OSC32k_32K_OUT		IOMUX_PAD(0x67C, 0x2F4, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_SD1_CLK__GPT_CLKIN			IOMUX_PAD(0x67C, 0x2F4, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_SD1_CLK__CSPI_SCLK			IOMUX_PAD(0x67C, 0x2F4, 5, 0x780, 2, NO_PAD_CTRL)
-#define MX53_PAD_SD1_CLK__SATA_PHY_DTB_0		IOMUX_PAD(0x67C, 0x2F4, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_SD1_DATA3__ESDHC1_DAT3			IOMUX_PAD(0x680, 0x2F8, 0, __NA_, 0, MX53_SDHC_PAD_CTRL)
-#define MX53_PAD_SD1_DATA3__GPIO1_21			IOMUX_PAD(0x680, 0x2F8, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_SD1_DATA3__GPT_CMPOUT3			IOMUX_PAD(0x680, 0x2F8, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_SD1_DATA3__PWM1_PWMO			IOMUX_PAD(0x680, 0x2F8, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_SD1_DATA3__WDOG2_WDOG_B		IOMUX_PAD(0x680, 0x2F8, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_SD1_DATA3__CSPI_SS2			IOMUX_PAD(0x680, 0x2F8, 5, 0x794, 2, NO_PAD_CTRL)
-#define MX53_PAD_SD1_DATA3__WDOG2_WDOG_RST_B_DEB	IOMUX_PAD(0x680, 0x2F8, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_SD1_DATA3__SATA_PHY_DTB_1		IOMUX_PAD(0x680, 0x2F8, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_SD2_CLK__ESDHC2_CLK			IOMUX_PAD(0x688, 0x2FC, 0, __NA_, 0, MX53_SDHC_PAD_CTRL)
-#define MX53_PAD_SD2_CLK__GPIO1_10			IOMUX_PAD(0x688, 0x2FC, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_SD2_CLK__KPP_COL_5			IOMUX_PAD(0x688, 0x2FC, 2, 0x840, 2, NO_PAD_CTRL)
-#define MX53_PAD_SD2_CLK__AUDMUX_AUD4_RXFS		IOMUX_PAD(0x688, 0x2FC, 3, 0x73C, 1, NO_PAD_CTRL)
-#define MX53_PAD_SD2_CLK__CSPI_SCLK			IOMUX_PAD(0x688, 0x2FC, 5, 0x780, 3, NO_PAD_CTRL)
-#define MX53_PAD_SD2_CLK__SCC_RANDOM_V			IOMUX_PAD(0x688, 0x2FC, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_SD2_CMD__ESDHC2_CMD			IOMUX_PAD(0x68C, 0x300, 0, __NA_, 0, MX53_SDHC_PAD_CTRL)
-#define MX53_PAD_SD2_CMD__GPIO1_11			IOMUX_PAD(0x68C, 0x300, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_SD2_CMD__KPP_ROW_5			IOMUX_PAD(0x68C, 0x300, 2, 0x84C, 1, NO_PAD_CTRL)
-#define MX53_PAD_SD2_CMD__AUDMUX_AUD4_RXC		IOMUX_PAD(0x68C, 0x300, 3, 0x738, 1, NO_PAD_CTRL)
-#define MX53_PAD_SD2_CMD__CSPI_MOSI			IOMUX_PAD(0x68C, 0x300, 5, 0x788, 3, NO_PAD_CTRL)
-#define MX53_PAD_SD2_CMD__SCC_RANDOM			IOMUX_PAD(0x68C, 0x300, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_SD2_DATA3__ESDHC2_DAT3			IOMUX_PAD(0x690, 0x304, 0, __NA_, 0, MX53_SDHC_PAD_CTRL)
-#define MX53_PAD_SD2_DATA3__GPIO1_12			IOMUX_PAD(0x690, 0x304, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_SD2_DATA3__KPP_COL_6			IOMUX_PAD(0x690, 0x304, 2, 0x844, 1, NO_PAD_CTRL)
-#define MX53_PAD_SD2_DATA3__AUDMUX_AUD4_TXC		IOMUX_PAD(0x690, 0x304, 3, 0x740, 1, NO_PAD_CTRL)
-#define MX53_PAD_SD2_DATA3__CSPI_SS2			IOMUX_PAD(0x690, 0x304, 5, 0x794, 3, NO_PAD_CTRL)
-#define MX53_PAD_SD2_DATA3__SJC_DONE			IOMUX_PAD(0x690, 0x304, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_SD2_DATA2__ESDHC2_DAT2			IOMUX_PAD(0x694, 0x308, 0, __NA_, 0, MX53_SDHC_PAD_CTRL)
-#define MX53_PAD_SD2_DATA2__GPIO1_13			IOMUX_PAD(0x694, 0x308, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_SD2_DATA2__KPP_ROW_6			IOMUX_PAD(0x694, 0x308, 2, 0x850, 1, NO_PAD_CTRL)
-#define MX53_PAD_SD2_DATA2__AUDMUX_AUD4_TXD		IOMUX_PAD(0x694, 0x308, 3, 0x734, 1, NO_PAD_CTRL)
-#define MX53_PAD_SD2_DATA2__CSPI_SS1			IOMUX_PAD(0x694, 0x308, 5, 0x790, 3, NO_PAD_CTRL)
-#define MX53_PAD_SD2_DATA2__SJC_FAIL			IOMUX_PAD(0x694, 0x308, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_SD2_DATA1__ESDHC2_DAT1			IOMUX_PAD(0x698, 0x30C, 0, __NA_, 0, MX53_SDHC_PAD_CTRL)
-#define MX53_PAD_SD2_DATA1__GPIO1_14			IOMUX_PAD(0x698, 0x30C, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_SD2_DATA1__KPP_COL_7			IOMUX_PAD(0x698, 0x30C, 2, 0x848, 1, NO_PAD_CTRL)
-#define MX53_PAD_SD2_DATA1__AUDMUX_AUD4_TXFS		IOMUX_PAD(0x698, 0x30C, 3, 0x744, 0, NO_PAD_CTRL)
-#define MX53_PAD_SD2_DATA1__CSPI_SS0			IOMUX_PAD(0x698, 0x30C, 5, 0x78C, 4, NO_PAD_CTRL)
-#define MX53_PAD_SD2_DATA1__RTIC_SEC_VIO		IOMUX_PAD(0x698, 0x30C, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_SD2_DATA0__ESDHC2_DAT0			IOMUX_PAD(0x69C, 0x310, 0, __NA_, 0, MX53_SDHC_PAD_CTRL)
-#define MX53_PAD_SD2_DATA0__GPIO1_15			IOMUX_PAD(0x69C, 0x310, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_SD2_DATA0__KPP_ROW_7			IOMUX_PAD(0x69C, 0x310, 2, 0x854, 1, NO_PAD_CTRL)
-#define MX53_PAD_SD2_DATA0__AUDMUX_AUD4_RXD		IOMUX_PAD(0x69C, 0x310, 3, 0x730, 1, NO_PAD_CTRL)
-#define MX53_PAD_SD2_DATA0__CSPI_MISO			IOMUX_PAD(0x69C, 0x310, 5, 0x784, 3, NO_PAD_CTRL)
-#define MX53_PAD_SD2_DATA0__RTIC_DONE_INT		IOMUX_PAD(0x69C, 0x310, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_0__CCM_CLKO			IOMUX_PAD(0x6A4, 0x314, 0, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_0__GPIO1_0			IOMUX_PAD(0x6A4, 0x314, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_0__KPP_COL_5			IOMUX_PAD(0x6A4, 0x314, 2, 0x840, 3, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_0__CCM_SSI_EXT1_CLK		IOMUX_PAD(0x6A4, 0x314, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_0__EPIT1_EPITO			IOMUX_PAD(0x6A4, 0x314, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_0__SRTC_ALARM_DEB			IOMUX_PAD(0x6A4, 0x314, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_0__USBOH3_USBH1_PWR		IOMUX_PAD(0x6A4, 0x314, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_0__CSU_TD				IOMUX_PAD(0x6A4, 0x314, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_1__ESAI1_SCKR			IOMUX_PAD(0x6A8, 0x318, 0, 0x7DC, 1, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_1__GPIO1_1			IOMUX_PAD(0x6A8, 0x318, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_1__KPP_ROW_5			IOMUX_PAD(0x6A8, 0x318, 2, 0x84C, 2, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_1__CCM_SSI_EXT2_CLK		IOMUX_PAD(0x6A8, 0x318, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_1__PWM2_PWMO			IOMUX_PAD(0x6A8, 0x318, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_1__WDOG2_WDOG_B			IOMUX_PAD(0x6A8, 0x318, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_1__ESDHC1_CD			IOMUX_PAD(0x6A8, 0x318, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_1__SRC_TESTER_ACK			IOMUX_PAD(0x6A8, 0x318, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_9__ESAI1_FSR			IOMUX_PAD(0x6AC, 0x31C, 0, 0x7CC, 1, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_9__GPIO1_9			IOMUX_PAD(0x6AC, 0x31C, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_9__KPP_COL_6			IOMUX_PAD(0x6AC, 0x31C, 2, 0x844, 2, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_9__CCM_REF_EN_B			IOMUX_PAD(0x6AC, 0x31C, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_9__PWM1_PWMO			IOMUX_PAD(0x6AC, 0x31C, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_9__WDOG1_WDOG_B			IOMUX_PAD(0x6AC, 0x31C, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_9__ESDHC1_WP			IOMUX_PAD(0x6AC, 0x31C, 6, 0x7FC, 1, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_9__SCC_FAIL_STATE			IOMUX_PAD(0x6AC, 0x31C, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_3__ESAI1_HCKR			IOMUX_PAD(0x6B0, 0x320, 0, 0x7D4, 1, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_3__GPIO1_3			IOMUX_PAD(0x6B0, 0x320, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_3__I2C3_SCL			IOMUX_PAD(0x6B0, 0x320, 2 | IOMUX_CONFIG_SION, 0x824, 1, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_3__DPLLIP1_TOG_EN			IOMUX_PAD(0x6B0, 0x320, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_3__CCM_CLKO2			IOMUX_PAD(0x6B0, 0x320, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_3__OBSERVE_MUX_OBSRV_INT_OUT0	IOMUX_PAD(0x6B0, 0x320, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_3__USBOH3_USBH1_OC		IOMUX_PAD(0x6B0, 0x320, 6, 0x8A0, 1, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_3__MLB_MLBCLK			IOMUX_PAD(0x6B0, 0x320, 7, 0x858, 2, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_6__ESAI1_SCKT			IOMUX_PAD(0x6B4, 0x324, 0, 0x7E0, 1, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_6__GPIO1_6			IOMUX_PAD(0x6B4, 0x324, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_6__I2C3_SDA			IOMUX_PAD(0x6B4, 0x324, 2 | IOMUX_CONFIG_SION, 0x828, 1, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_6__CCM_CCM_OUT_0			IOMUX_PAD(0x6B4, 0x324, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_6__CSU_CSU_INT_DEB		IOMUX_PAD(0x6B4, 0x324, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_6__OBSERVE_MUX_OBSRV_INT_OUT1	IOMUX_PAD(0x6B4, 0x324, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_6__ESDHC2_LCTL			IOMUX_PAD(0x6B4, 0x324, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_6__MLB_MLBSIG			IOMUX_PAD(0x6B4, 0x324, 7, 0x860, 2, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_2__ESAI1_FST			IOMUX_PAD(0x6B8, 0x328, 0, 0x7D0, 1, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_2__GPIO1_2			IOMUX_PAD(0x6B8, 0x328, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_2__KPP_ROW_6			IOMUX_PAD(0x6B8, 0x328, 2, 0x850, 2, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_2__CCM_CCM_OUT_1			IOMUX_PAD(0x6B8, 0x328, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_2__CSU_CSU_ALARM_AUT_0		IOMUX_PAD(0x6B8, 0x328, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_2__OBSERVE_MUX_OBSRV_INT_OUT2	IOMUX_PAD(0x6B8, 0x328, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_2__ESDHC2_WP			IOMUX_PAD(0x6B8, 0x328, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_2__MLB_MLBDAT			IOMUX_PAD(0x6B8, 0x328, 7, 0x85C, 2, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_4__ESAI1_HCKT			IOMUX_PAD(0x6BC, 0x32C, 0, 0x7D8, 1, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_4__GPIO1_4			IOMUX_PAD(0x6BC, 0x32C, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_4__KPP_COL_7			IOMUX_PAD(0x6BC, 0x32C, 2, 0x848, 2, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_4__CCM_CCM_OUT_2			IOMUX_PAD(0x6BC, 0x32C, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_4__CSU_CSU_ALARM_AUT_1		IOMUX_PAD(0x6BC, 0x32C, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_4__OBSERVE_MUX_OBSRV_INT_OUT3	IOMUX_PAD(0x6BC, 0x32C, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_4__ESDHC2_CD			IOMUX_PAD(0x6BC, 0x32C, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_4__SCC_SEC_STATE			IOMUX_PAD(0x6BC, 0x32C, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_5__ESAI1_TX2_RX3			IOMUX_PAD(0x6C0, 0x330, 0, 0x7EC, 1, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_5__GPIO1_5			IOMUX_PAD(0x6C0, 0x330, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_5__KPP_ROW_7			IOMUX_PAD(0x6C0, 0x330, 2, 0x854, 2, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_5__CCM_CLKO			IOMUX_PAD(0x6C0, 0x330, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_5__CSU_CSU_ALARM_AUT_2		IOMUX_PAD(0x6C0, 0x330, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_5__OBSERVE_MUX_OBSRV_INT_OUT4	IOMUX_PAD(0x6C0, 0x330, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_5__I2C3_SCL			IOMUX_PAD(0x6C0, 0x330, 6 | IOMUX_CONFIG_SION, 0x824, 2, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_5__CCM_PLL1_BYP			IOMUX_PAD(0x6C0, 0x330, 7, 0x770, 1, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_7__ESAI1_TX4_RX1			IOMUX_PAD(0x6C4, 0x334, 0, 0x7F4, 1, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_7__GPIO1_7			IOMUX_PAD(0x6C4, 0x334, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_7__EPIT1_EPITO			IOMUX_PAD(0x6C4, 0x334, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_7__CAN1_TXCAN			IOMUX_PAD(0x6C4, 0x334, 3, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_7__UART2_TXD_MUX			IOMUX_PAD(0x6C4, 0x334, 4, __NA_, 0, MX53_UART_PAD_CTRL)
-#define MX53_PAD_GPIO_7__FIRI_RXD			IOMUX_PAD(0x6C4, 0x334, 5, 0x80C, 1, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_7__SPDIF_PLOCK			IOMUX_PAD(0x6C4, 0x334, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_7__CCM_PLL2_BYP			IOMUX_PAD(0x6C4, 0x334, 7, 0x774, 1, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_8__ESAI1_TX5_RX0			IOMUX_PAD(0x6C8, 0x338, 0, 0x7F8, 1, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_8__GPIO1_8			IOMUX_PAD(0x6C8, 0x338, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_8__EPIT2_EPITO			IOMUX_PAD(0x6C8, 0x338, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_8__CAN1_RXCAN			IOMUX_PAD(0x6C8, 0x338, 3, 0x760, 2, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_8__UART2_RXD_MUX			IOMUX_PAD(0x6C8, 0x338, 4, 0x880, 5, MX53_UART_PAD_CTRL)
-#define MX53_PAD_GPIO_8__FIRI_TXD			IOMUX_PAD(0x6C8, 0x338, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_8__SPDIF_SRCLK			IOMUX_PAD(0x6C8, 0x338, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_8__CCM_PLL3_BYP			IOMUX_PAD(0x6C8, 0x338, 7, 0x778, 1, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_16__ESAI1_TX3_RX2			IOMUX_PAD(0x6CC, 0x33C, 0, 0x7F0, 1, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_16__GPIO7_11			IOMUX_PAD(0x6CC, 0x33C, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_16__TZIC_PWRFAIL_INT		IOMUX_PAD(0x6CC, 0x33C, 2, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_16__RTC_CE_RTC_EXT_TRIG1		IOMUX_PAD(0x6CC, 0x33C, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_16__SPDIF_IN1			IOMUX_PAD(0x6CC, 0x33C, 5, 0x870, 1, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_16__I2C3_SDA			IOMUX_PAD(0x6CC, 0x33C, 6 | IOMUX_CONFIG_SION, 0x828, 2, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_16__SJC_DE_B			IOMUX_PAD(0x6CC, 0x33C, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_17__ESAI1_TX0			IOMUX_PAD(0x6D0, 0x340, 0, 0x7E4, 1, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_17__GPIO7_12			IOMUX_PAD(0x6D0, 0x340, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_17__SDMA_EXT_EVENT_0		IOMUX_PAD(0x6D0, 0x340, 2, 0x868, 1, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_17__GPC_PMIC_RDY			IOMUX_PAD(0x6D0, 0x340, 3, 0x810, 1, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_17__RTC_CE_RTC_FSV_TRIG		IOMUX_PAD(0x6D0, 0x340, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_17__SPDIF_OUT1			IOMUX_PAD(0x6D0, 0x340, 5, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_17__IPU_SNOOP2			IOMUX_PAD(0x6D0, 0x340, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_17__SJC_JTAG_ACT			IOMUX_PAD(0x6D0, 0x340, 7, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_18__ESAI1_TX1			IOMUX_PAD(0x6D4, 0x344, 0, 0x7E8, 1, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_18__GPIO7_13			IOMUX_PAD(0x6D4, 0x344, 1, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_18__SDMA_EXT_EVENT_1		IOMUX_PAD(0x6D4, 0x344, 2, 0x86C, 1, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_18__OWIRE_LINE			IOMUX_PAD(0x6D4, 0x344, 3, 0x864, 1, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_18__RTC_CE_RTC_ALARM2_TRIG	IOMUX_PAD(0x6D4, 0x344, 4, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_18__CCM_ASRC_EXT_CLK		IOMUX_PAD(0x6D4, 0x344, 5, 0x768, 1, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_18__ESDHC1_LCTL			IOMUX_PAD(0x6D4, 0x344, 6, __NA_, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_18__SRC_SYSTEM_RST		IOMUX_PAD(0x6D4, 0x344, 7, __NA_, 0, NO_PAD_CTRL)
-
-#endif	/* __MACH_IOMUX_MX53_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/mmc.h b/arch/arm/plat-mxc/include/mach/mmc.h
deleted file mode 100644
index 29115f4..0000000
--- a/arch/arm/plat-mxc/include/mach/mmc.h
+++ /dev/null
@@ -1,39 +0,0 @@
-#ifndef ASMARM_ARCH_MMC_H
-#define ASMARM_ARCH_MMC_H
-
-#include <linux/mmc/host.h>
-
-struct device;
-
-/* board specific SDHC data, optional.
- * If not present, a writable card with 3,3V is assumed.
- */
-struct imxmmc_platform_data {
-	/* Return values for the get_ro callback should be:
-	 *   0 for a read/write card
-	 *   1 for a read-only card
-	 *   -ENOSYS when not supported (equal to NULL callback)
-	 *   or a negative errno value when something bad happened
-	 */
-	int (*get_ro)(struct device *);
-
-	/* board specific hook to (de)initialize the SD slot.
-	 * The board code can call 'handler' on a card detection
-	 * change giving data as argument.
-	 */
-	int (*init)(struct device *dev, irq_handler_t handler, void *data);
-	void (*exit)(struct device *dev, void *data);
-
-	/* available voltages. If not given, assume
-	 * MMC_VDD_32_33 | MMC_VDD_33_34
-	 */
-	unsigned int ocr_avail;
-
-	/* adjust slot voltage */
-	void (*setpower)(struct device *, unsigned int vdd);
-
-	/* enable card detect using DAT3 */
-	int dat3_card_detect;
-};
-
-#endif
diff --git a/arch/arm/plat-mxc/include/mach/mx1_camera.h b/arch/arm/plat-mxc/include/mach/mx1_camera.h
deleted file mode 100644
index 4fd6c70..0000000
--- a/arch/arm/plat-mxc/include/mach/mx1_camera.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * mx1_camera.h - i.MX1/i.MXL camera driver header file
- *
- * Copyright (c) 2008, Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
- * Copyright (C) 2009, Darius Augulis <augulis.darius@gmail.com>
- *
- * Based on PXA camera.h file:
- * Copyright (C) 2003, Intel Corporation
- * Copyright (C) 2008, Guennadi Liakhovetski <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 version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __ASM_ARCH_CAMERA_H_
-#define __ASM_ARCH_CAMERA_H_
-
-#define MX1_CAMERA_DATA_HIGH	1
-#define MX1_CAMERA_PCLK_RISING	2
-#define MX1_CAMERA_VSYNC_HIGH	4
-
-extern unsigned char mx1_camera_sof_fiq_start, mx1_camera_sof_fiq_end;
-
-/**
- * struct mx1_camera_pdata - i.MX1/i.MXL camera platform data
- * @mclk_10khz:	master clock frequency in 10kHz units
- * @flags:	MX1 camera platform flags
- */
-struct mx1_camera_pdata {
-	unsigned long mclk_10khz;
-	unsigned long flags;
-};
-
-#endif /* __ASM_ARCH_CAMERA_H_ */
diff --git a/arch/arm/plat-mxc/include/mach/mx21-usbhost.h b/arch/arm/plat-mxc/include/mach/mx21-usbhost.h
deleted file mode 100644
index 22d0b59..0000000
--- a/arch/arm/plat-mxc/include/mach/mx21-usbhost.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- *	Copyright (C) 2009 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.
- */
-
-#ifndef __ASM_ARCH_MX21_USBH
-#define __ASM_ARCH_MX21_USBH
-
-enum mx21_usbh_xcvr {
-	/* Values below as used by hardware (HWMODE register) */
-	MX21_USBXCVR_TXDIF_RXDIF = 0,
-	MX21_USBXCVR_TXDIF_RXSE = 1,
-	MX21_USBXCVR_TXSE_RXDIF = 2,
-	MX21_USBXCVR_TXSE_RXSE = 3,
-};
-
-struct mx21_usbh_platform_data {
-	enum mx21_usbh_xcvr host_xcvr; /* tranceiver mode host 1,2 ports */
-	enum mx21_usbh_xcvr otg_xcvr; /* tranceiver mode otg (as host) port */
-	u16 	enable_host1:1,
-		enable_host2:1,
-		enable_otg_host:1, /* enable "OTG" port (as host) */
-		host1_xcverless:1, /* traceiverless host1 port */
-		host1_txenoe:1, /* output enable host1 transmit enable */
-		otg_ext_xcvr:1, /* external tranceiver for OTG port */
-		unused:10;
-};
-
-#endif /* __ASM_ARCH_MX21_USBH */
diff --git a/arch/arm/plat-mxc/include/mach/mx2_cam.h b/arch/arm/plat-mxc/include/mach/mx2_cam.h
deleted file mode 100644
index 3c080a3..0000000
--- a/arch/arm/plat-mxc/include/mach/mx2_cam.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * mx2-cam.h - i.MX27/i.MX25 camera driver header file
- *
- * Copyright (C) 2003, Intel Corporation
- * Copyright (C) 2008, Sascha Hauer <s.hauer@pengutronix.de>
- * Copyright (C) 2010, Baruch Siach <baruch@tkos.co.il>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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 St - Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef __MACH_MX2_CAM_H_
-#define __MACH_MX2_CAM_H_
-
-#define MX2_CAMERA_SWAP16		(1 << 0)
-#define MX2_CAMERA_EXT_VSYNC		(1 << 1)
-#define MX2_CAMERA_CCIR			(1 << 2)
-#define MX2_CAMERA_CCIR_INTERLACE	(1 << 3)
-#define MX2_CAMERA_HSYNC_HIGH		(1 << 4)
-#define MX2_CAMERA_GATED_CLOCK		(1 << 5)
-#define MX2_CAMERA_INV_DATA		(1 << 6)
-#define MX2_CAMERA_PCLK_SAMPLE_RISING	(1 << 7)
-#define MX2_CAMERA_PACK_DIR_MSB		(1 << 8)
-
-/**
- * struct mx2_camera_platform_data - optional platform data for mx2_camera
- * @flags: any combination of MX2_CAMERA_*
- * @clk: clock rate of the csi block / 2
- */
-struct mx2_camera_platform_data {
-	unsigned long flags;
-	unsigned long clk;
-};
-
-#endif /* __MACH_MX2_CAM_H_ */
diff --git a/arch/arm/plat-mxc/include/mach/mx31.h b/arch/arm/plat-mxc/include/mach/mx31.h
index dbced61..ee9b1f9 100644
--- a/arch/arm/plat-mxc/include/mach/mx31.h
+++ b/arch/arm/plat-mxc/include/mach/mx31.h
@@ -76,7 +76,7 @@
 #define MX31_RTIC_BASE_ADDR			(MX31_AIPS2_BASE_ADDR + 0xec000)
 
 #define MX31_ROMP_BASE_ADDR		0x60000000
-#define MX31_ROMP_BASE_ADDR_VIRT	0xfc500000
+#define MX31_ROMP_BASE_ADDR_VIRT	IOMEM(0xfc500000)
 #define MX31_ROMP_SIZE			SZ_1M
 
 #define MX31_AVIC_BASE_ADDR		0x68000000
@@ -92,11 +92,11 @@
 #define MX31_CS3_BASE_ADDR		0xb2000000
 
 #define MX31_CS4_BASE_ADDR		0xb4000000
-#define MX31_CS4_BASE_ADDR_VIRT		0xf6000000
+#define MX31_CS4_BASE_ADDR_VIRT		IOMEM(0xf6000000)
 #define MX31_CS4_SIZE			SZ_32M
 
 #define MX31_CS5_BASE_ADDR		0xb6000000
-#define MX31_CS5_BASE_ADDR_VIRT		0xf8000000
+#define MX31_CS5_BASE_ADDR_VIRT		IOMEM(0xf8000000)
 #define MX31_CS5_SIZE			SZ_32M
 
 #define MX31_X_MEMC_BASE_ADDR		0xb8000000
diff --git a/arch/arm/plat-mxc/include/mach/mx3_camera.h b/arch/arm/plat-mxc/include/mach/mx3_camera.h
deleted file mode 100644
index f226ee3..0000000
--- a/arch/arm/plat-mxc/include/mach/mx3_camera.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * 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.
- */
-
-#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
deleted file mode 100644
index fdbe600..0000000
--- a/arch/arm/plat-mxc/include/mach/mx3fb.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef __ASM_ARCH_MX3FB_H__
-#define __ASM_ARCH_MX3FB_H__
-
-#include <linux/device.h>
-#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
-
-/*
- * Specify the way your display is connected. The IPU can arbitrarily
- * map the internal colors to the external data lines. We only support
- * the following mappings at the moment.
- */
-enum disp_data_mapping {
-	/* blue -> d[0..5], green -> d[6..11], red -> d[12..17] */
-	IPU_DISP_DATA_MAPPING_RGB666,
-	/* blue -> d[0..4], green -> d[5..10], red -> d[11..15] */
-	IPU_DISP_DATA_MAPPING_RGB565,
-	/* blue -> d[0..7], green -> d[8..15], red -> d[16..23] */
-	IPU_DISP_DATA_MAPPING_RGB888,
-};
-
-/**
- * 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
- */
-struct mx3fb_platform_data {
-	struct device			*dma_dev;
-	const char			*name;
-	const struct fb_videomode	*mode;
-	int				num_modes;
-	enum disp_data_mapping		disp_data_fmt;
-};
-
-#endif
diff --git a/arch/arm/plat-mxc/include/mach/mxc_ehci.h b/arch/arm/plat-mxc/include/mach/mxc_ehci.h
deleted file mode 100644
index 7eb9d13..0000000
--- a/arch/arm/plat-mxc/include/mach/mxc_ehci.h
+++ /dev/null
@@ -1,59 +0,0 @@
-#ifndef __INCLUDE_ASM_ARCH_MXC_EHCI_H
-#define __INCLUDE_ASM_ARCH_MXC_EHCI_H
-
-/* values for portsc field */
-#define MXC_EHCI_PHY_LOW_POWER_SUSPEND	(1 << 23)
-#define MXC_EHCI_FORCE_FS		(1 << 24)
-#define MXC_EHCI_UTMI_8BIT		(0 << 28)
-#define MXC_EHCI_UTMI_16BIT		(1 << 28)
-#define MXC_EHCI_SERIAL			(1 << 29)
-#define MXC_EHCI_MODE_UTMI		(0 << 30)
-#define MXC_EHCI_MODE_PHILIPS		(1 << 30)
-#define MXC_EHCI_MODE_ULPI		(2 << 30)
-#define MXC_EHCI_MODE_SERIAL		(3 << 30)
-
-/* values for flags field */
-#define MXC_EHCI_INTERFACE_DIFF_UNI	(0 << 0)
-#define MXC_EHCI_INTERFACE_DIFF_BI	(1 << 0)
-#define MXC_EHCI_INTERFACE_SINGLE_UNI	(2 << 0)
-#define MXC_EHCI_INTERFACE_SINGLE_BI	(3 << 0)
-#define MXC_EHCI_INTERFACE_MASK		(0xf)
-
-#define MXC_EHCI_POWER_PINS_ENABLED	(1 << 5)
-#define MXC_EHCI_PWR_PIN_ACTIVE_HIGH	(1 << 6)
-#define MXC_EHCI_OC_PIN_ACTIVE_LOW	(1 << 7)
-#define MXC_EHCI_TTL_ENABLED		(1 << 8)
-
-#define MXC_EHCI_INTERNAL_PHY		(1 << 9)
-#define MXC_EHCI_IPPUE_DOWN		(1 << 10)
-#define MXC_EHCI_IPPUE_UP		(1 << 11)
-#define MXC_EHCI_WAKEUP_ENABLED		(1 << 12)
-#define MXC_EHCI_ITC_NO_THRESHOLD	(1 << 13)
-
-#define MXC_USBCTRL_OFFSET		0
-#define MXC_USB_PHY_CTR_FUNC_OFFSET	0x8
-#define MXC_USB_PHY_CTR_FUNC2_OFFSET	0xc
-#define MXC_USBH2CTRL_OFFSET		0x14
-
-#define MX5_USBOTHER_REGS_OFFSET	0x800
-
-/* USB_PHY_CTRL_FUNC2*/
-#define MX5_USB_UTMI_PHYCTRL1_PLLDIV_MASK		0x3
-#define MX5_USB_UTMI_PHYCTRL1_PLLDIV_SHIFT		0
-
-struct mxc_usbh_platform_data {
-	int (*init)(struct platform_device *pdev);
-	int (*exit)(struct platform_device *pdev);
-
-	unsigned int		 portsc;
-	struct usb_phy		*otg;
-};
-
-int mx51_initialize_usb_hw(int port, unsigned int flags);
-int mx25_initialize_usb_hw(int port, unsigned int flags);
-int mx31_initialize_usb_hw(int port, unsigned int flags);
-int mx35_initialize_usb_hw(int port, unsigned int flags);
-int mx27_initialize_usb_hw(int port, unsigned int flags);
-
-#endif /* __INCLUDE_ASM_ARCH_MXC_EHCI_H */
-
diff --git a/arch/arm/plat-mxc/include/mach/mxc_nand.h b/arch/arm/plat-mxc/include/mach/mxc_nand.h
deleted file mode 100644
index 6bb96ef..0000000
--- a/arch/arm/plat-mxc/include/mach/mxc_nand.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright 2008 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 __ASM_ARCH_NAND_H
-#define __ASM_ARCH_NAND_H
-
-#include <linux/mtd/partitions.h>
-
-struct mxc_nand_platform_data {
-	unsigned int width;	/* data bus width in bytes */
-	unsigned int hw_ecc:1;	/* 0 if suppress hardware ECC */
-	unsigned int flash_bbt:1; /* set to 1 to use a flash based bbt */
-	struct mtd_partition *parts;	/* partition table */
-	int nr_parts;			/* size of parts */
-};
-#endif /* __ASM_ARCH_NAND_H */
diff --git a/arch/arm/plat-mxc/include/mach/sdma.h b/arch/arm/plat-mxc/include/mach/sdma.h
deleted file mode 100644
index 3a39428..0000000
--- a/arch/arm/plat-mxc/include/mach/sdma.h
+++ /dev/null
@@ -1,59 +0,0 @@
-#ifndef __MACH_MXC_SDMA_H__
-#define __MACH_MXC_SDMA_H__
-
-/**
- * struct sdma_script_start_addrs - SDMA script start pointers
- *
- * start addresses of the different functions in the physical
- * address space of the SDMA engine.
- */
-struct sdma_script_start_addrs {
-	s32 ap_2_ap_addr;
-	s32 ap_2_bp_addr;
-	s32 ap_2_ap_fixed_addr;
-	s32 bp_2_ap_addr;
-	s32 loopback_on_dsp_side_addr;
-	s32 mcu_interrupt_only_addr;
-	s32 firi_2_per_addr;
-	s32 firi_2_mcu_addr;
-	s32 per_2_firi_addr;
-	s32 mcu_2_firi_addr;
-	s32 uart_2_per_addr;
-	s32 uart_2_mcu_addr;
-	s32 per_2_app_addr;
-	s32 mcu_2_app_addr;
-	s32 per_2_per_addr;
-	s32 uartsh_2_per_addr;
-	s32 uartsh_2_mcu_addr;
-	s32 per_2_shp_addr;
-	s32 mcu_2_shp_addr;
-	s32 ata_2_mcu_addr;
-	s32 mcu_2_ata_addr;
-	s32 app_2_per_addr;
-	s32 app_2_mcu_addr;
-	s32 shp_2_per_addr;
-	s32 shp_2_mcu_addr;
-	s32 mshc_2_mcu_addr;
-	s32 mcu_2_mshc_addr;
-	s32 spdif_2_mcu_addr;
-	s32 mcu_2_spdif_addr;
-	s32 asrc_2_mcu_addr;
-	s32 ext_mem_2_ipu_addr;
-	s32 descrambler_addr;
-	s32 dptc_dvfs_addr;
-	s32 utra_addr;
-	s32 ram_code_start_addr;
-};
-
-/**
- * struct sdma_platform_data - platform specific data for SDMA engine
- *
- * @fw_name		The firmware name
- * @script_addrs	SDMA scripts addresses in SDMA ROM
- */
-struct sdma_platform_data {
-	char *fw_name;
-	struct sdma_script_start_addrs *script_addrs;
-};
-
-#endif /* __MACH_MXC_SDMA_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/spi.h b/arch/arm/plat-mxc/include/mach/spi.h
deleted file mode 100644
index 08be445..0000000
--- a/arch/arm/plat-mxc/include/mach/spi.h
+++ /dev/null
@@ -1,27 +0,0 @@
-
-#ifndef __MACH_SPI_H_
-#define __MACH_SPI_H_
-
-/*
- * struct spi_imx_master - device.platform_data for SPI controller devices.
- * @chipselect: Array of chipselects for this master. Numbers >= 0 mean gpio
- *              pins, numbers < 0 mean internal CSPI chipselects according
- *              to MXC_SPI_CS(). Normally you want to use gpio based chip
- *              selects as the CSPI module tries to be intelligent about
- *              when to assert the chipselect: The CSPI module deasserts the
- *              chipselect once it runs out of input data. The other problem
- *              is that it is not possible to mix between high active and low
- *              active chipselects on one single bus using the internal
- *              chipselects. Unfortunately Freescale decided to put some
- *              chipselects on dedicated pins which are not usable as gpios,
- *              so we have to support the internal chipselects.
- * @num_chipselect: ARRAY_SIZE(chipselect)
- */
-struct spi_imx_master {
-	int	*chipselect;
-	int	num_chipselect;
-};
-
-#define MXC_SPI_CS(no)	((no) - 32)
-
-#endif /* __MACH_SPI_H_*/
diff --git a/arch/arm/plat-mxc/include/mach/ssi.h b/arch/arm/plat-mxc/include/mach/ssi.h
deleted file mode 100644
index 63f3c28..0000000
--- a/arch/arm/plat-mxc/include/mach/ssi.h
+++ /dev/null
@@ -1,21 +0,0 @@
-#ifndef __MACH_SSI_H
-#define __MACH_SSI_H
-
-struct snd_ac97;
-
-extern unsigned char imx_ssi_fiq_start, imx_ssi_fiq_end;
-extern unsigned long imx_ssi_fiq_base, imx_ssi_fiq_tx_buffer, imx_ssi_fiq_rx_buffer;
-
-struct imx_ssi_platform_data {
-	unsigned int flags;
-#define IMX_SSI_DMA            (1 << 0)
-#define IMX_SSI_USE_AC97       (1 << 1)
-#define IMX_SSI_NET            (1 << 2)
-#define IMX_SSI_SYN            (1 << 3)
-#define IMX_SSI_USE_I2S_SLAVE  (1 << 4)
-	void (*ac97_reset) (struct snd_ac97 *ac97);
-	void (*ac97_warm_reset)(struct snd_ac97 *ac97);
-};
-
-#endif /* __MACH_SSI_H */
-
diff --git a/arch/arm/plat-mxc/include/mach/usb.h b/arch/arm/plat-mxc/include/mach/usb.h
deleted file mode 100644
index be27337..0000000
--- a/arch/arm/plat-mxc/include/mach/usb.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- *	Copyright (C) 2008 Darius Augulis <augulis.darius@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.
- */
-
-#ifndef __ASM_ARCH_MXC_USB
-#define __ASM_ARCH_MXC_USB
-
-struct imxusb_platform_data {
-	int (*init)(struct device *);
-	void (*exit)(struct device *);
-};
-
-#endif /* __ASM_ARCH_MXC_USB */
diff --git a/arch/arm/plat-mxc/ssi-fiq-ksym.c b/arch/arm/plat-mxc/ssi-fiq-ksym.c
index b5fad45..792090f 100644
--- a/arch/arm/plat-mxc/ssi-fiq-ksym.c
+++ b/arch/arm/plat-mxc/ssi-fiq-ksym.c
@@ -10,7 +10,7 @@
 
 #include <linux/module.h>
 
-#include <mach/ssi.h>
+#include <linux/platform_data/asoc-imx-ssi.h>
 
 EXPORT_SYMBOL(imx_ssi_fiq_tx_buffer);
 EXPORT_SYMBOL(imx_ssi_fiq_rx_buffer);
diff --git a/arch/arm/plat-mxc/ssi-fiq.S b/arch/arm/plat-mxc/ssi-fiq.S
index 8397a2d..a8b93c5 100644
--- a/arch/arm/plat-mxc/ssi-fiq.S
+++ b/arch/arm/plat-mxc/ssi-fiq.S
@@ -34,91 +34,98 @@
 		.global imx_ssi_fiq_rx_buffer
 		.global imx_ssi_fiq_tx_buffer
 
+/*
+ * imx_ssi_fiq_start is _intentionally_ not marked as a function symbol
+ * using ENDPROC().  imx_ssi_fiq_start and imx_ssi_fiq_end are used to
+ * mark the function body so that it can be copied to the FIQ vector in
+ * the vectors page.  imx_ssi_fiq_start should only be called as the result
+ * of an FIQ: calling it directly will not work.
+ */
 imx_ssi_fiq_start:
-		ldr r12, imx_ssi_fiq_base
+		ldr r12, .L_imx_ssi_fiq_base
 
 		/* TX */
-		ldr r11, imx_ssi_fiq_tx_buffer
+		ldr r13, .L_imx_ssi_fiq_tx_buffer
 
 		/* shall we send? */
-		ldr r13, [r12, #SSI_SIER]
-		tst r13, #SSI_SIER_TFE0_EN
+		ldr r11, [r12, #SSI_SIER]
+		tst r11, #SSI_SIER_TFE0_EN
 		beq 1f
 
 		/* TX FIFO empty? */
-		ldr r13, [r12, #SSI_SISR]
-		tst r13, #SSI_SISR_TFE0
+		ldr r11, [r12, #SSI_SISR]
+		tst r11, #SSI_SISR_TFE0
 		beq 1f
 
 		mov r10, #0x10000
 		sub r10, #1
 		and r10, r10, r8	/* r10: current buffer offset */
 
-		add r11, r11, r10
+		add r13, r13, r10
 
-		ldrh r13, [r11]
-		strh r13, [r12, #SSI_STX0]
+		ldrh r11, [r13]
+		strh r11, [r12, #SSI_STX0]
 
-		ldrh r13, [r11, #2]
-		strh r13, [r12, #SSI_STX0]
+		ldrh r11, [r13, #2]
+		strh r11, [r12, #SSI_STX0]
 
-		ldrh r13, [r11, #4]
-		strh r13, [r12, #SSI_STX0]
+		ldrh r11, [r13, #4]
+		strh r11, [r12, #SSI_STX0]
 
-		ldrh r13, [r11, #6]
-		strh r13, [r12, #SSI_STX0]
+		ldrh r11, [r13, #6]
+		strh r11, [r12, #SSI_STX0]
 
 		add r10, #8
-		lsr r13, r8, #16	/* r13: buffer size */
-		cmp r10, r13
-		lslgt r8, r13, #16
+		lsr r11, r8, #16	/* r11: buffer size */
+		cmp r10, r11
+		lslgt r8, r11, #16
 		addle r8, #8
 1:
 		/* RX */
 
 		/* shall we receive? */
-		ldr r13, [r12, #SSI_SIER]
-		tst r13, #SSI_SIER_RFF0_EN
+		ldr r11, [r12, #SSI_SIER]
+		tst r11, #SSI_SIER_RFF0_EN
 		beq 1f
 
 		/* RX FIFO full? */
-		ldr r13, [r12, #SSI_SISR]
-		tst r13, #SSI_SISR_RFF0
+		ldr r11, [r12, #SSI_SISR]
+		tst r11, #SSI_SISR_RFF0
 		beq 1f
 
-		ldr r11, imx_ssi_fiq_rx_buffer
+		ldr r13, .L_imx_ssi_fiq_rx_buffer
 
 		mov r10, #0x10000
 		sub r10, #1
 		and r10, r10, r9	/* r10: current buffer offset */
 
-		add r11, r11, r10
+		add r13, r13, r10
 
-		ldr r13, [r12, #SSI_SACNT]
-		tst r13, #SSI_SACNT_AC97EN
+		ldr r11, [r12, #SSI_SACNT]
+		tst r11, #SSI_SACNT_AC97EN
 
-		ldr r13, [r12, #SSI_SRX0]
-		strh r13, [r11]
+		ldr r11, [r12, #SSI_SRX0]
+		strh r11, [r13]
 
-		ldr r13, [r12, #SSI_SRX0]
-		strh r13, [r11, #2]
+		ldr r11, [r12, #SSI_SRX0]
+		strh r11, [r13, #2]
 
 		/* dummy read to skip slot 12 */
-		ldrne r13, [r12, #SSI_SRX0]
+		ldrne r11, [r12, #SSI_SRX0]
 
-		ldr r13, [r12, #SSI_SRX0]
-		strh r13, [r11, #4]
+		ldr r11, [r12, #SSI_SRX0]
+		strh r11, [r13, #4]
 
-		ldr r13, [r12, #SSI_SRX0]
-		strh r13, [r11, #6]
+		ldr r11, [r12, #SSI_SRX0]
+		strh r11, [r13, #6]
 
 		/* dummy read to skip slot 12 */
-		ldrne r13, [r12, #SSI_SRX0]
+		ldrne r11, [r12, #SSI_SRX0]
 
 		add r10, #8
-		lsr r13, r9, #16	/* r13: buffer size */
-		cmp r10, r13
-		lslgt r9, r13, #16
+		lsr r11, r9, #16	/* r11: buffer size */
+		cmp r10, r11
+		lslgt r9, r11, #16
 		addle r9, #8
 
 1:
@@ -126,11 +133,15 @@ imx_ssi_fiq_start:
 		subs	pc, lr, #4
 
 		.align
+.L_imx_ssi_fiq_base:
 imx_ssi_fiq_base:
 		.word 0x0
+.L_imx_ssi_fiq_rx_buffer:
 imx_ssi_fiq_rx_buffer:
 		.word 0x0
+.L_imx_ssi_fiq_tx_buffer:
 imx_ssi_fiq_tx_buffer:
 		.word 0x0
+.L_imx_ssi_fiq_end:
 imx_ssi_fiq_end:
 
diff --git a/arch/arm/plat-mxc/system.c b/arch/arm/plat-mxc/system.c
index 1996c3e..3da78cf 100644
--- a/arch/arm/plat-mxc/system.c
+++ b/arch/arm/plat-mxc/system.c
@@ -21,7 +21,6 @@
 #include <linux/io.h>
 #include <linux/err.h>
 #include <linux/delay.h>
-#include <linux/module.h>
 
 #include <mach/hardware.h>
 #include <mach/common.h>
@@ -29,9 +28,6 @@
 #include <asm/proc-fns.h>
 #include <asm/mach-types.h>
 
-void __iomem *(*imx_ioremap)(unsigned long, size_t, unsigned int) = NULL;
-EXPORT_SYMBOL_GPL(imx_ioremap);
-
 static void __iomem *wdog_base;
 
 /*
diff --git a/arch/arm/plat-nomadik/include/plat/ske.h b/arch/arm/plat-nomadik/include/plat/ske.h
deleted file mode 100644
index 31382fb..0000000
--- a/arch/arm/plat-nomadik/include/plat/ske.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson SA 2010
- *
- * License Terms: GNU General Public License v2
- * Author: Naveen Kumar Gaddipati <naveen.gaddipati@stericsson.com>
- *
- * ux500 Scroll key and Keypad Encoder (SKE) header
- */
-
-#ifndef __SKE_H
-#define __SKE_H
-
-#include <linux/input/matrix_keypad.h>
-
-/* register definitions for SKE peripheral */
-#define SKE_CR		0x00
-#define SKE_VAL0	0x04
-#define SKE_VAL1	0x08
-#define SKE_DBCR	0x0C
-#define SKE_IMSC	0x10
-#define SKE_RIS		0x14
-#define SKE_MIS		0x18
-#define SKE_ICR		0x1C
-
-/*
- * Keypad module
- */
-
-/**
- * struct keypad_platform_data - structure for platform specific data
- * @init:	pointer to keypad init function
- * @exit:	pointer to keypad deinitialisation function
- * @keymap_data: matrix scan code table for keycodes
- * @krow:	maximum number of rows
- * @kcol:	maximum number of columns
- * @debounce_ms: platform specific debounce time
- * @no_autorepeat: flag for auto repetition
- * @wakeup_enable: allow waking up the system
- */
-struct ske_keypad_platform_data {
-	int (*init)(void);
-	int (*exit)(void);
-	const struct matrix_keymap_data *keymap_data;
-	u8 krow;
-	u8 kcol;
-	u8 debounce_ms;
-	bool no_autorepeat;
-	bool wakeup_enable;
-};
-#endif	/*__SKE_KPD_H*/
diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
index dd36eba..ca83a76 100644
--- a/arch/arm/plat-omap/Kconfig
+++ b/arch/arm/plat-omap/Kconfig
@@ -25,6 +25,7 @@ config ARCH_OMAP2PLUS
 	bool "TI OMAP2/3/4"
 	select CLKDEV_LOOKUP
 	select GENERIC_IRQ_CHIP
+	select SPARSE_IRQ
 	select OMAP_DM_TIMER
 	select USE_OF
 	select PROC_DEVICETREE if PROC_FS
@@ -41,9 +42,8 @@ config OMAP_DEBUG_DEVICES
 	  For debug cards on TI reference boards.
 
 config OMAP_DEBUG_LEDS
-	bool
+	def_bool y if NEW_LEDS
 	depends on OMAP_DEBUG_DEVICES
-	default y if LEDS_CLASS
 
 config POWER_AVS_OMAP
 	bool "AVS(Adaptive Voltage Scaling) support for OMAP IP versions 1&2"
diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile
index 961bf85..dacaee0 100644
--- a/arch/arm/plat-omap/Makefile
+++ b/arch/arm/plat-omap/Makefile
@@ -3,8 +3,7 @@
 #
 
 # Common support
-obj-y := common.o sram.o clock.o devices.o dma.o mux.o \
-	 fb.o counter_32k.o
+obj-y := common.o sram.o clock.o dma.o fb.o counter_32k.o
 obj-m :=
 obj-n :=
 obj-  :=
diff --git a/arch/arm/plat-omap/common.c b/arch/arm/plat-omap/common.c
index 89a3723..111315a 100644
--- a/arch/arm/plat-omap/common.c
+++ b/arch/arm/plat-omap/common.c
@@ -17,52 +17,12 @@
 #include <linux/dma-mapping.h>
 
 #include <plat/common.h>
-#include <plat/board.h>
 #include <plat/vram.h>
-#include <plat/dsp.h>
+#include <linux/platform_data/dsp-omap.h>
 #include <plat/dma.h>
 
 #include <plat/omap-secure.h>
 
-
-#define NO_LENGTH_CHECK 0xffffffff
-
-struct omap_board_config_kernel *omap_board_config __initdata;
-int omap_board_config_size;
-
-static const void *__init get_config(u16 tag, size_t len,
-		int skip, size_t *len_out)
-{
-	struct omap_board_config_kernel *kinfo = NULL;
-	int i;
-
-	/* Try to find the config from the board-specific structures
-	 * in the kernel. */
-	for (i = 0; i < omap_board_config_size; i++) {
-		if (omap_board_config[i].tag == tag) {
-			if (skip == 0) {
-				kinfo = &omap_board_config[i];
-				break;
-			} else {
-				skip--;
-			}
-		}
-	}
-	if (kinfo == NULL)
-		return NULL;
-	return kinfo->data;
-}
-
-const void *__init __omap_get_config(u16 tag, size_t len, int nr)
-{
-        return get_config(tag, len, nr, NULL);
-}
-
-const void *__init omap_get_var_config(u16 tag, size_t *len)
-{
-        return get_config(tag, NO_LENGTH_CHECK, 0, len);
-}
-
 void __init omap_reserve(void)
 {
 	omap_vram_reserve_sdram_memblock();
diff --git a/arch/arm/plat-omap/counter_32k.c b/arch/arm/plat-omap/counter_32k.c
index dbf1e03..2e826f1 100644
--- a/arch/arm/plat-omap/counter_32k.c
+++ b/arch/arm/plat-omap/counter_32k.c
@@ -22,10 +22,7 @@
 #include <asm/mach/time.h>
 #include <asm/sched_clock.h>
 
-#include <plat/hardware.h>
 #include <plat/common.h>
-#include <plat/board.h>
-
 #include <plat/clock.h>
 
 /* OMAP2_32KSYNCNT_CR_OFF: offset of 32ksync counter register */
diff --git a/arch/arm/plat-omap/debug-devices.c b/arch/arm/plat-omap/debug-devices.c
index caa1f7b..c7a4c09 100644
--- a/arch/arm/plat-omap/debug-devices.c
+++ b/arch/arm/plat-omap/debug-devices.c
@@ -17,9 +17,6 @@
 
 #include <mach/hardware.h>
 
-#include <plat/board.h>
-
-
 /* Many OMAP development platforms reuse the same "debug board"; these
  * platforms include H2, H3, H4, and Perseus2.
  */
diff --git a/arch/arm/plat-omap/debug-leds.c b/arch/arm/plat-omap/debug-leds.c
index 39407cb..0fc8175 100644
--- a/arch/arm/plat-omap/debug-leds.c
+++ b/arch/arm/plat-omap/debug-leds.c
@@ -1,279 +1,119 @@
 /*
  * linux/arch/arm/plat-omap/debug-leds.c
  *
+ * Copyright 2011 by Bryan Wu <bryan.wu@canonical.com>
  * Copyright 2003 by Texas Instruments Incorporated
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-#include <linux/gpio.h>
+
+#include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/leds.h>
 #include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/platform_data/gpio-omap.h>
 
 #include <mach/hardware.h>
-#include <asm/leds.h>
 #include <asm/mach-types.h>
 
 #include <plat/fpga.h>
 
-
 /* Many OMAP development platforms reuse the same "debug board"; these
  * platforms include H2, H3, H4, and Perseus2.  There are 16 LEDs on the
  * debug board (all green), accessed through FPGA registers.
- *
- * The "surfer" expansion board and H2 sample board also have two-color
- * green+red LEDs (in parallel), used here for timer and idle indicators
- * in preference to the ones on the debug board, for a "Disco LED" effect.
- *
- * This driver exports either the original ARM LED API, the new generic
- * one, or both.
- */
-
-static spinlock_t			lock;
-static struct h2p2_dbg_fpga __iomem	*fpga;
-static u16				led_state, hw_led_state;
-
-
-#ifdef	CONFIG_OMAP_DEBUG_LEDS
-#define new_led_api()	1
-#else
-#define new_led_api()	0
-#endif
-
-
-/*-------------------------------------------------------------------------*/
-
-/* original ARM debug LED API:
- *  - timer and idle leds (some boards use non-FPGA leds here);
- *  - up to 4 generic leds, easily accessed in-kernel (any context)
  */
 
-#define GPIO_LED_RED		3
-#define GPIO_LED_GREEN		OMAP_MPUIO(4)
-
-#define LED_STATE_ENABLED	0x01
-#define LED_STATE_CLAIMED	0x02
-#define LED_TIMER_ON		0x04
-
-#define GPIO_IDLE		GPIO_LED_GREEN
-#define GPIO_TIMER		GPIO_LED_RED
-
-static void h2p2_dbg_leds_event(led_event_t evt)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&lock, flags);
-
-	if (!(led_state & LED_STATE_ENABLED) && evt != led_start)
-		goto done;
-
-	switch (evt) {
-	case led_start:
-		if (fpga)
-			led_state |= LED_STATE_ENABLED;
-		break;
-
-	case led_stop:
-	case led_halted:
-		/* all leds off during suspend or shutdown */
-
-		if (!(machine_is_omap_perseus2() || machine_is_omap_h4())) {
-			gpio_set_value(GPIO_TIMER, 0);
-			gpio_set_value(GPIO_IDLE, 0);
-		}
-
-		__raw_writew(~0, &fpga->leds);
-		led_state &= ~LED_STATE_ENABLED;
-		goto done;
-
-	case led_claim:
-		led_state |= LED_STATE_CLAIMED;
-		hw_led_state = 0;
-		break;
-
-	case led_release:
-		led_state &= ~LED_STATE_CLAIMED;
-		break;
-
-#ifdef CONFIG_LEDS_TIMER
-	case led_timer:
-		led_state ^= LED_TIMER_ON;
-
-		if (machine_is_omap_perseus2() || machine_is_omap_h4())
-			hw_led_state ^= H2P2_DBG_FPGA_P2_LED_TIMER;
-		else {
-			gpio_set_value(GPIO_TIMER,
-					led_state & LED_TIMER_ON);
-			goto done;
-		}
-
-		break;
-#endif
-
-#ifdef CONFIG_LEDS_CPU
-	/* LED lit iff busy */
-	case led_idle_start:
-		if (machine_is_omap_perseus2() || machine_is_omap_h4())
-			hw_led_state &= ~H2P2_DBG_FPGA_P2_LED_IDLE;
-		else {
-			gpio_set_value(GPIO_IDLE, 1);
-			goto done;
-		}
-
-		break;
+static struct h2p2_dbg_fpga __iomem *fpga;
 
-	case led_idle_end:
-		if (machine_is_omap_perseus2() || machine_is_omap_h4())
-			hw_led_state |= H2P2_DBG_FPGA_P2_LED_IDLE;
-		else {
-			gpio_set_value(GPIO_IDLE, 0);
-			goto done;
-		}
-
-		break;
-#endif
-
-	case led_green_on:
-		hw_led_state |= H2P2_DBG_FPGA_LED_GREEN;
-		break;
-	case led_green_off:
-		hw_led_state &= ~H2P2_DBG_FPGA_LED_GREEN;
-		break;
-
-	case led_amber_on:
-		hw_led_state |= H2P2_DBG_FPGA_LED_AMBER;
-		break;
-	case led_amber_off:
-		hw_led_state &= ~H2P2_DBG_FPGA_LED_AMBER;
-		break;
-
-	case led_red_on:
-		hw_led_state |= H2P2_DBG_FPGA_LED_RED;
-		break;
-	case led_red_off:
-		hw_led_state &= ~H2P2_DBG_FPGA_LED_RED;
-		break;
-
-	case led_blue_on:
-		hw_led_state |= H2P2_DBG_FPGA_LED_BLUE;
-		break;
-	case led_blue_off:
-		hw_led_state &= ~H2P2_DBG_FPGA_LED_BLUE;
-		break;
-
-	default:
-		break;
-	}
-
-
-	/*
-	 *  Actually burn the LEDs
-	 */
-	if (led_state & LED_STATE_ENABLED)
-		__raw_writew(~hw_led_state, &fpga->leds);
-
-done:
-	spin_unlock_irqrestore(&lock, flags);
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* "new" LED API
- *  - with syfs access and generic triggering
- *  - not readily accessible to in-kernel drivers
- */
+static u16 fpga_led_state;
 
 struct dbg_led {
 	struct led_classdev	cdev;
 	u16			mask;
 };
 
-static struct dbg_led dbg_leds[] = {
-	/* REVISIT at least H2 uses different timer & cpu leds... */
-#ifndef CONFIG_LEDS_TIMER
-	{ .mask = 1 << 0,  .cdev.name =  "d4:green",
-		.cdev.default_trigger = "heartbeat", },
-#endif
-#ifndef CONFIG_LEDS_CPU
-	{ .mask = 1 << 1,  .cdev.name =  "d5:green", },		/* !idle */
-#endif
-	{ .mask = 1 << 2,  .cdev.name =  "d6:green", },
-	{ .mask = 1 << 3,  .cdev.name =  "d7:green", },
-
-	{ .mask = 1 << 4,  .cdev.name =  "d8:green", },
-	{ .mask = 1 << 5,  .cdev.name =  "d9:green", },
-	{ .mask = 1 << 6,  .cdev.name = "d10:green", },
-	{ .mask = 1 << 7,  .cdev.name = "d11:green", },
-
-	{ .mask = 1 << 8,  .cdev.name = "d12:green", },
-	{ .mask = 1 << 9,  .cdev.name = "d13:green", },
-	{ .mask = 1 << 10, .cdev.name = "d14:green", },
-	{ .mask = 1 << 11, .cdev.name = "d15:green", },
-
-#ifndef	CONFIG_LEDS
-	{ .mask = 1 << 12, .cdev.name = "d16:green", },
-	{ .mask = 1 << 13, .cdev.name = "d17:green", },
-	{ .mask = 1 << 14, .cdev.name = "d18:green", },
-	{ .mask = 1 << 15, .cdev.name = "d19:green", },
-#endif
+static const struct {
+	const char *name;
+	const char *trigger;
+} dbg_leds[] = {
+	{ "dbg:d4", "heartbeat", },
+	{ "dbg:d5", "cpu0", },
+	{ "dbg:d6", "default-on", },
+	{ "dbg:d7", },
+	{ "dbg:d8", },
+	{ "dbg:d9", },
+	{ "dbg:d10", },
+	{ "dbg:d11", },
+	{ "dbg:d12", },
+	{ "dbg:d13", },
+	{ "dbg:d14", },
+	{ "dbg:d15", },
+	{ "dbg:d16", },
+	{ "dbg:d17", },
+	{ "dbg:d18", },
+	{ "dbg:d19", },
 };
 
-static void
-fpga_led_set(struct led_classdev *cdev, enum led_brightness value)
+/*
+ * The triggers lines up below will only be used if the
+ * LED triggers are compiled in.
+ */
+static void dbg_led_set(struct led_classdev *cdev,
+			      enum led_brightness b)
 {
-	struct dbg_led	*led = container_of(cdev, struct dbg_led, cdev);
-	unsigned long	flags;
+	struct dbg_led *led = container_of(cdev, struct dbg_led, cdev);
+	u16 reg;
 
-	spin_lock_irqsave(&lock, flags);
-	if (value == LED_OFF)
-		hw_led_state &= ~led->mask;
+	reg = __raw_readw(&fpga->leds);
+	if (b != LED_OFF)
+		reg |= led->mask;
 	else
-		hw_led_state |= led->mask;
-	__raw_writew(~hw_led_state, &fpga->leds);
-	spin_unlock_irqrestore(&lock, flags);
+		reg &= ~led->mask;
+	__raw_writew(reg, &fpga->leds);
 }
 
-static void __init newled_init(struct device *dev)
+static enum led_brightness dbg_led_get(struct led_classdev *cdev)
 {
-	unsigned	i;
-	struct dbg_led	*led;
-	int		status;
+	struct dbg_led *led = container_of(cdev, struct dbg_led, cdev);
+	u16 reg;
 
-	for (i = 0, led = dbg_leds; i < ARRAY_SIZE(dbg_leds); i++, led++) {
-		led->cdev.brightness_set = fpga_led_set;
-		status = led_classdev_register(dev, &led->cdev);
-		if (status < 0)
-			break;
-	}
-	return;
+	reg = __raw_readw(&fpga->leds);
+	return (reg & led->mask) ? LED_FULL : LED_OFF;
 }
 
-
-/*-------------------------------------------------------------------------*/
-
-static int /* __init */ fpga_probe(struct platform_device *pdev)
+static int fpga_probe(struct platform_device *pdev)
 {
 	struct resource	*iomem;
-
-	spin_lock_init(&lock);
+	int i;
 
 	iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!iomem)
 		return -ENODEV;
 
 	fpga = ioremap(iomem->start, H2P2_DBG_FPGA_SIZE);
-	__raw_writew(~0, &fpga->leds);
+	__raw_writew(0xff, &fpga->leds);
+
+	for (i = 0; i < ARRAY_SIZE(dbg_leds); i++) {
+		struct dbg_led *led;
+
+		led = kzalloc(sizeof(*led), GFP_KERNEL);
+		if (!led)
+			break;
 
-#ifdef	CONFIG_LEDS
-	leds_event = h2p2_dbg_leds_event;
-	leds_event(led_start);
-#endif
+		led->cdev.name = dbg_leds[i].name;
+		led->cdev.brightness_set = dbg_led_set;
+		led->cdev.brightness_get = dbg_led_get;
+		led->cdev.default_trigger = dbg_leds[i].trigger;
+		led->mask = BIT(i);
 
-	if (new_led_api()) {
-		newled_init(&pdev->dev);
+		if (led_classdev_register(NULL, &led->cdev) < 0) {
+			kfree(led);
+			break;
+		}
 	}
 
 	return 0;
@@ -281,13 +121,15 @@ static int /* __init */ fpga_probe(struct platform_device *pdev)
 
 static int fpga_suspend_noirq(struct device *dev)
 {
-	__raw_writew(~0, &fpga->leds);
+	fpga_led_state = __raw_readw(&fpga->leds);
+	__raw_writew(0xff, &fpga->leds);
+
 	return 0;
 }
 
 static int fpga_resume_noirq(struct device *dev)
 {
-	__raw_writew(~hw_led_state, &fpga->leds);
+	__raw_writew(~fpga_led_state, &fpga->leds);
 	return 0;
 }
 
diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c
deleted file mode 100644
index 1cba927..0000000
--- a/arch/arm/plat-omap/devices.c
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * linux/arch/arm/plat-omap/devices.c
- *
- * Common platform device setup/initialization for OMAP1 and OMAP2
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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/gpio.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-#include <linux/memblock.h>
-
-#include <mach/hardware.h>
-#include <asm/mach-types.h>
-#include <asm/mach/map.h>
-#include <asm/memblock.h>
-
-#include <plat/tc.h>
-#include <plat/board.h>
-#include <plat/mmc.h>
-#include <plat/menelaus.h>
-#include <plat/omap44xx.h>
-
-/*-------------------------------------------------------------------------*/
-
-#if defined(CONFIG_HW_RANDOM_OMAP) || defined(CONFIG_HW_RANDOM_OMAP_MODULE)
-
-#ifdef CONFIG_ARCH_OMAP2
-#define	OMAP_RNG_BASE		0x480A0000
-#else
-#define	OMAP_RNG_BASE		0xfffe5000
-#endif
-
-static struct resource rng_resources[] = {
-	{
-		.start		= OMAP_RNG_BASE,
-		.end		= OMAP_RNG_BASE + 0x4f,
-		.flags		= IORESOURCE_MEM,
-	},
-};
-
-static struct platform_device omap_rng_device = {
-	.name		= "omap_rng",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(rng_resources),
-	.resource	= rng_resources,
-};
-
-static void omap_init_rng(void)
-{
-	(void) platform_device_register(&omap_rng_device);
-}
-#else
-static inline void omap_init_rng(void) {}
-#endif
-
-/*
- * This gets called after board-specific INIT_MACHINE, and initializes most
- * on-chip peripherals accessible on this board (except for few like USB):
- *
- *  (a) Does any "standard config" pin muxing needed.  Board-specific
- *	code will have muxed GPIO pins and done "nonstandard" setup;
- *	that code could live in the boot loader.
- *  (b) Populating board-specific platform_data with the data drivers
- *	rely on to handle wiring variations.
- *  (c) Creating platform devices as meaningful on this board and
- *	with this kernel configuration.
- *
- * Claiming GPIOs, and setting their direction and initial values, is the
- * responsibility of the device drivers.  So is responding to probe().
- *
- * Board-specific knowledge like creating devices or pin setup is to be
- * kept out of drivers as much as possible.  In particular, pin setup
- * may be handled by the boot loader, and drivers should expect it will
- * normally have been done by the time they're probed.
- */
-static int __init omap_init_devices(void)
-{
-	/* please keep these calls, and their implementations above,
-	 * in alphabetical order so they're easier to sort through.
-	 */
-	omap_init_rng();
-	return 0;
-}
-arch_initcall(omap_init_devices);
diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c
index 7fe6267..c76ed8b 100644
--- a/arch/arm/plat-omap/dma.c
+++ b/arch/arm/plat-omap/dma.c
@@ -36,9 +36,8 @@
 #include <linux/slab.h>
 #include <linux/delay.h>
 
-#include <mach/hardware.h>
+#include <plat/cpu.h>
 #include <plat/dma.h>
-
 #include <plat/tc.h>
 
 /*
@@ -969,8 +968,7 @@ void omap_stop_dma(int lch)
 			l = p->dma_read(CCR, lch);
 		}
 		if (i >= 100)
-			printk(KERN_ERR "DMA drain did not complete on "
-					"lch %d\n", lch);
+			pr_err("DMA drain did not complete on lch %d\n", lch);
 		/* Restore OCP_SYSCONFIG */
 		p->dma_write(sys_cf, OCP_SYSCONFIG, lch);
 	} else {
@@ -1154,8 +1152,7 @@ void omap_dma_link_lch(int lch_head, int lch_queue)
 
 	if ((dma_chan[lch_head].dev_id == -1) ||
 	    (dma_chan[lch_queue].dev_id == -1)) {
-		printk(KERN_ERR "omap_dma: trying to link "
-		       "non requested channels\n");
+		pr_err("omap_dma: trying to link non requested channels\n");
 		dump_stack();
 	}
 
@@ -1181,15 +1178,13 @@ void omap_dma_unlink_lch(int lch_head, int lch_queue)
 
 	if (dma_chan[lch_head].next_lch != lch_queue ||
 	    dma_chan[lch_head].next_lch == -1) {
-		printk(KERN_ERR "omap_dma: trying to unlink "
-		       "non linked channels\n");
+		pr_err("omap_dma: trying to unlink non linked channels\n");
 		dump_stack();
 	}
 
 	if ((dma_chan[lch_head].flags & OMAP_DMA_ACTIVE) ||
 	    (dma_chan[lch_queue].flags & OMAP_DMA_ACTIVE)) {
-		printk(KERN_ERR "omap_dma: You need to stop the DMA channels "
-		       "before unlinking\n");
+		pr_err("omap_dma: You need to stop the DMA channels before unlinking\n");
 		dump_stack();
 	}
 
@@ -1831,16 +1826,15 @@ static int omap1_dma_handle_ch(int ch)
 	if ((csr & 0x3f) == 0)
 		return 0;
 	if (unlikely(dma_chan[ch].dev_id == -1)) {
-		printk(KERN_WARNING "Spurious interrupt from DMA channel "
-		       "%d (CSR %04x)\n", ch, csr);
+		pr_warn("Spurious interrupt from DMA channel %d (CSR %04x)\n",
+			ch, csr);
 		return 0;
 	}
 	if (unlikely(csr & OMAP1_DMA_TOUT_IRQ))
-		printk(KERN_WARNING "DMA timeout with device %d\n",
-		       dma_chan[ch].dev_id);
+		pr_warn("DMA timeout with device %d\n", dma_chan[ch].dev_id);
 	if (unlikely(csr & OMAP_DMA_DROP_IRQ))
-		printk(KERN_WARNING "DMA synchronization event drop occurred "
-		       "with device %d\n", dma_chan[ch].dev_id);
+		pr_warn("DMA synchronization event drop occurred with device %d\n",
+			dma_chan[ch].dev_id);
 	if (likely(csr & OMAP_DMA_BLOCK_IRQ))
 		dma_chan[ch].flags &= ~OMAP_DMA_ACTIVE;
 	if (likely(dma_chan[ch].callback != NULL))
@@ -1880,21 +1874,19 @@ static int omap2_dma_handle_ch(int ch)
 
 	if (!status) {
 		if (printk_ratelimit())
-			printk(KERN_WARNING "Spurious DMA IRQ for lch %d\n",
-				ch);
+			pr_warn("Spurious DMA IRQ for lch %d\n", ch);
 		p->dma_write(1 << ch, IRQSTATUS_L0, ch);
 		return 0;
 	}
 	if (unlikely(dma_chan[ch].dev_id == -1)) {
 		if (printk_ratelimit())
-			printk(KERN_WARNING "IRQ %04x for non-allocated DMA"
-					"channel %d\n", status, ch);
+			pr_warn("IRQ %04x for non-allocated DMA channel %d\n",
+				status, ch);
 		return 0;
 	}
 	if (unlikely(status & OMAP_DMA_DROP_IRQ))
-		printk(KERN_INFO
-		       "DMA synchronization event drop occurred with device "
-		       "%d\n", dma_chan[ch].dev_id);
+		pr_info("DMA synchronization event drop occurred with device %d\n",
+			dma_chan[ch].dev_id);
 	if (unlikely(status & OMAP2_DMA_TRANS_ERR_IRQ)) {
 		printk(KERN_INFO "DMA transaction error with device %d\n",
 		       dma_chan[ch].dev_id);
@@ -2014,8 +2006,9 @@ static int __devinit omap_system_dma_probe(struct platform_device *pdev)
 
 	p = pdev->dev.platform_data;
 	if (!p) {
-		dev_err(&pdev->dev, "%s: System DMA initialized without"
-			"platform data\n", __func__);
+		dev_err(&pdev->dev,
+			"%s: System DMA initialized without platform data\n",
+			__func__);
 		return -EINVAL;
 	}
 
@@ -2090,8 +2083,8 @@ static int __devinit omap_system_dma_probe(struct platform_device *pdev)
 		}
 		ret = setup_irq(dma_irq, &omap24xx_dma_irq);
 		if (ret) {
-			dev_err(&pdev->dev, "set_up failed for IRQ %d"
-				"for DMA (error %d)\n", dma_irq, ret);
+			dev_err(&pdev->dev, "set_up failed for IRQ %d for DMA (error %d)\n",
+				dma_irq, ret);
 			goto exit_dma_lch_fail;
 		}
 	}
@@ -2099,8 +2092,7 @@ static int __devinit omap_system_dma_probe(struct platform_device *pdev)
 	/* reserve dma channels 0 and 1 in high security devices */
 	if (cpu_is_omap34xx() &&
 		(omap_type() != OMAP2_DEVICE_TYPE_GP)) {
-		printk(KERN_INFO "Reserving DMA channels 0 and 1 for "
-				"HS ROM code\n");
+		pr_info("Reserving DMA channels 0 and 1 for HS ROM code\n");
 		dma_chan[0].dev_id = 0;
 		dma_chan[1].dev_id = 1;
 	}
@@ -2108,8 +2100,8 @@ static int __devinit omap_system_dma_probe(struct platform_device *pdev)
 	return 0;
 
 exit_dma_irq_fail:
-	dev_err(&pdev->dev, "unable to request IRQ %d"
-			"for DMA (error %d)\n", dma_irq, ret);
+	dev_err(&pdev->dev, "unable to request IRQ %d for DMA (error %d)\n",
+		dma_irq, ret);
 	for (irq_rel = 0; irq_rel < ch;	irq_rel++) {
 		dma_irq = platform_get_irq(pdev, irq_rel);
 		free_irq(dma_irq, (void *)(irq_rel + 1));
diff --git a/arch/arm/plat-omap/fb.c b/arch/arm/plat-omap/fb.c
index dd6f92c..bcbb9d5 100644
--- a/arch/arm/plat-omap/fb.c
+++ b/arch/arm/plat-omap/fb.c
@@ -33,8 +33,6 @@
 #include <mach/hardware.h>
 #include <asm/mach/map.h>
 
-#include <plat/board.h>
-
 #if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE)
 
 static bool omapfb_lcd_configured;
diff --git a/arch/arm/plat-omap/i2c.c b/arch/arm/plat-omap/i2c.c
index db071bc..6013831 100644
--- a/arch/arm/plat-omap/i2c.c
+++ b/arch/arm/plat-omap/i2c.c
@@ -32,13 +32,13 @@
 #include <linux/clk.h>
 
 #include <mach/irqs.h>
-#include <plat/mux.h>
 #include <plat/i2c.h>
 #include <plat/omap-pm.h>
 #include <plat/omap_device.h>
 
 #define OMAP_I2C_SIZE		0x3f
 #define OMAP1_I2C_BASE		0xfffb3800
+#define OMAP1_INT_I2C		(32 + 4)
 
 static const char name[] = "omap_i2c";
 
@@ -105,7 +105,7 @@ static inline int omap1_i2c_add_bus(int bus_id)
 	res = pdev->resource;
 	res[0].start = OMAP1_I2C_BASE;
 	res[0].end = res[0].start + OMAP_I2C_SIZE;
-	res[1].start = INT_I2C;
+	res[1].start = OMAP1_INT_I2C;
 	pdata = &i2c_pdata[bus_id - 1];
 
 	/* all OMAP1 have IP version 1 register set */
diff --git a/arch/arm/plat-omap/include/plat/am33xx.h b/arch/arm/plat-omap/include/plat/am33xx.h
deleted file mode 100644
index 06c19bb..0000000
--- a/arch/arm/plat-omap/include/plat/am33xx.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * This file contains the address info for various AM33XX modules.
- *
- * Copyright (C) 2011 Texas Instruments, Inc. - http://www.ti.com/
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation version 2.
- *
- * This program is distributed "as is" WITHOUT ANY WARRANTY of any
- * kind, whether express or implied; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#ifndef __ASM_ARCH_AM33XX_H
-#define __ASM_ARCH_AM33XX_H
-
-#define L4_SLOW_AM33XX_BASE	0x48000000
-
-#define AM33XX_SCM_BASE		0x44E10000
-#define AM33XX_CTRL_BASE	AM33XX_SCM_BASE
-#define AM33XX_PRCM_BASE	0x44E00000
-
-#endif /* __ASM_ARCH_AM33XX_H */
diff --git a/arch/arm/plat-omap/include/plat/board-ams-delta.h b/arch/arm/plat-omap/include/plat/board-ams-delta.h
deleted file mode 100644
index ad6f865..0000000
--- a/arch/arm/plat-omap/include/plat/board-ams-delta.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * arch/arm/plat-omap/include/mach/board-ams-delta.h
- *
- * Copyright (C) 2006 Jonathan McDowell <noodles@earth.li>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * THIS 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_AMS_DELTA_H
-#define __ASM_ARCH_OMAP_AMS_DELTA_H
-
-#if defined (CONFIG_MACH_AMS_DELTA)
-
-#define AMD_DELTA_LATCH2_SCARD_RSTIN	0x0400
-#define AMD_DELTA_LATCH2_SCARD_CMDVCC	0x0800
-#define AMS_DELTA_LATCH2_MODEM_CODEC	0x2000
-
-#define AMS_DELTA_GPIO_PIN_KEYBRD_DATA	0
-#define AMS_DELTA_GPIO_PIN_KEYBRD_CLK	1
-#define AMS_DELTA_GPIO_PIN_MODEM_IRQ	2
-#define AMS_DELTA_GPIO_PIN_HOOK_SWITCH	4
-#define AMS_DELTA_GPIO_PIN_SCARD_NOFF	6
-#define AMS_DELTA_GPIO_PIN_SCARD_IO	7
-#define AMS_DELTA_GPIO_PIN_CONFIG	11
-#define AMS_DELTA_GPIO_PIN_NAND_RB	12
-
-#define AMS_DELTA_GPIO_PIN_LCD_VBLEN		240
-#define AMS_DELTA_GPIO_PIN_LCD_NDISP		241
-#define AMS_DELTA_GPIO_PIN_NAND_NCE		242
-#define AMS_DELTA_GPIO_PIN_NAND_NRE		243
-#define AMS_DELTA_GPIO_PIN_NAND_NWP		244
-#define AMS_DELTA_GPIO_PIN_NAND_NWE		245
-#define AMS_DELTA_GPIO_PIN_NAND_ALE		246
-#define AMS_DELTA_GPIO_PIN_NAND_CLE		247
-#define AMS_DELTA_GPIO_PIN_KEYBRD_PWR		248
-#define AMS_DELTA_GPIO_PIN_KEYBRD_DATAOUT	249
-#define AMS_DELTA_GPIO_PIN_SCARD_RSTIN		250
-#define AMS_DELTA_GPIO_PIN_SCARD_CMDVCC		251
-#define AMS_DELTA_GPIO_PIN_MODEM_NRESET		252
-#define AMS_DELTA_GPIO_PIN_MODEM_CODEC		253
-
-#define AMS_DELTA_LATCH2_GPIO_BASE	AMS_DELTA_GPIO_PIN_LCD_VBLEN
-#define AMS_DELTA_LATCH2_NGPIO		16
-
-#ifndef __ASSEMBLY__
-void ams_delta_latch_write(int base, int ngpio, u16 mask, u16 value);
-#define ams_delta_latch2_write(mask, value) \
-	ams_delta_latch_write(AMS_DELTA_LATCH2_GPIO_BASE, \
-			AMS_DELTA_LATCH2_NGPIO, (mask), (value))
-#endif
-
-#endif /* CONFIG_MACH_AMS_DELTA */
-
-#endif /* __ASM_ARCH_OMAP_AMS_DELTA_H */
diff --git a/arch/arm/plat-omap/include/plat/board-sx1.h b/arch/arm/plat-omap/include/plat/board-sx1.h
deleted file mode 100644
index 355adbd..0000000
--- a/arch/arm/plat-omap/include/plat/board-sx1.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Siemens SX1 board definitions
- *
- * Copyright: Vovan888 at gmail com
- *
- * This package is free software; you can 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 PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
-#ifndef __ASM_ARCH_SX1_I2C_CHIPS_H
-#define __ASM_ARCH_SX1_I2C_CHIPS_H
-
-#define SOFIA_MAX_LIGHT_VAL	0x2B
-
-#define SOFIA_I2C_ADDR		0x32
-/* Sofia reg 3 bits masks */
-#define SOFIA_POWER1_REG	0x03
-
-#define	SOFIA_USB_POWER		0x01
-#define	SOFIA_MMC_POWER		0x04
-#define	SOFIA_BLUETOOTH_POWER	0x08
-#define	SOFIA_MMILIGHT_POWER	0x20
-
-#define SOFIA_POWER2_REG	0x04
-#define SOFIA_BACKLIGHT_REG	0x06
-#define SOFIA_KEYLIGHT_REG	0x07
-#define SOFIA_DIMMING_REG	0x09
-
-
-/* Function Prototypes for SX1 devices control on I2C bus */
-
-int sx1_setbacklight(u8 backlight);
-int sx1_getbacklight(u8 *backlight);
-int sx1_setkeylight(u8 keylight);
-int sx1_getkeylight(u8 *keylight);
-
-int sx1_setmmipower(u8 onoff);
-int sx1_setusbpower(u8 onoff);
-int sx1_i2c_read_byte(u8 devaddr, u8 regoffset, u8 *value);
-int sx1_i2c_write_byte(u8 devaddr, u8 regoffset, u8 value);
-
-/* MMC prototypes */
-
-extern void sx1_mmc_init(void);
-extern void sx1_mmc_slot_cover_handler(void *arg, int state);
-
-#endif /* __ASM_ARCH_SX1_I2C_CHIPS_H */
diff --git a/arch/arm/plat-omap/include/plat/board-voiceblue.h b/arch/arm/plat-omap/include/plat/board-voiceblue.h
deleted file mode 100644
index 27916b2..0000000
--- a/arch/arm/plat-omap/include/plat/board-voiceblue.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2004 2N Telekomunikace, Ladislav Michl <michl@2n.cz>
- *
- * Hardware definitions for OMAP5910 based VoiceBlue board.
- *
- * This program is free software; you can 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_VOICEBLUE_H
-#define __ASM_ARCH_VOICEBLUE_H
-
-extern void voiceblue_wdt_enable(void);
-extern void voiceblue_wdt_disable(void);
-extern void voiceblue_wdt_ping(void);
-
-#endif /*  __ASM_ARCH_VOICEBLUE_H */
-
diff --git a/arch/arm/plat-omap/include/plat/board.h b/arch/arm/plat-omap/include/plat/board.h
deleted file mode 100644
index e62f20a..0000000
--- a/arch/arm/plat-omap/include/plat/board.h
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- *  arch/arm/plat-omap/include/mach/board.h
- *
- *  Information structures for board-specific data
- *
- *  Copyright (C) 2004	Nokia Corporation
- *  Written by Juha Yrjölä <juha.yrjola@nokia.com>
- */
-
-#ifndef _OMAP_BOARD_H
-#define _OMAP_BOARD_H
-
-#include <linux/types.h>
-
-#include <plat/gpio-switch.h>
-
-/*
- * OMAP35x EVM revision
- * Run time detection of EVM revision is done by reading Ethernet
- * PHY ID -
- *	GEN_1	= 0x01150000
- *	GEN_2	= 0x92200000
- */
-enum {
-	OMAP3EVM_BOARD_GEN_1 = 0,	/* EVM Rev between  A - D */
-	OMAP3EVM_BOARD_GEN_2,		/* EVM Rev >= Rev E */
-};
-
-/* Different peripheral ids */
-#define OMAP_TAG_CLOCK		0x4f01
-#define OMAP_TAG_GPIO_SWITCH	0x4f06
-#define OMAP_TAG_STI_CONSOLE	0x4f09
-#define OMAP_TAG_CAMERA_SENSOR	0x4f0a
-
-#define OMAP_TAG_BOOT_REASON    0x4f80
-#define OMAP_TAG_FLASH_PART	0x4f81
-#define OMAP_TAG_VERSION_STR	0x4f82
-
-struct omap_clock_config {
-	/* 0 for 12 MHz, 1 for 13 MHz and 2 for 19.2 MHz */
-	u8 system_clock_type;
-};
-
-struct omap_serial_console_config {
-	u8 console_uart;
-	u32 console_speed;
-};
-
-struct omap_sti_console_config {
-	unsigned enable:1;
-	u8 channel;
-};
-
-struct omap_camera_sensor_config {
-	u16 reset_gpio;
-	int (*power_on)(void * data);
-	int (*power_off)(void * data);
-};
-
-struct omap_lcd_config {
-	char panel_name[16];
-	char ctrl_name[16];
-	s16  nreset_gpio;
-	u8   data_lines;
-};
-
-struct device;
-struct fb_info;
-struct omap_backlight_config {
-	int default_intensity;
-	int (*set_power)(struct device *dev, int state);
-};
-
-struct omap_fbmem_config {
-	u32 start;
-	u32 size;
-};
-
-struct omap_pwm_led_platform_data {
-	const char *name;
-	int intensity_timer;
-	int blink_timer;
-	void (*set_power)(struct omap_pwm_led_platform_data *self, int on_off);
-};
-
-struct omap_uart_config {
-	/* Bit field of UARTs present; bit 0 --> UART1 */
-	unsigned int enabled_uarts;
-};
-
-
-struct omap_flash_part_config {
-	char part_table[0];
-};
-
-struct omap_boot_reason_config {
-	char reason_str[12];
-};
-
-struct omap_version_config {
-	char component[12];
-	char version[12];
-};
-
-struct omap_board_config_entry {
-	u16 tag;
-	u16 len;
-	u8  data[0];
-};
-
-struct omap_board_config_kernel {
-	u16 tag;
-	const void *data;
-};
-
-extern const void *__init __omap_get_config(u16 tag, size_t len, int nr);
-
-#define omap_get_config(tag, type) \
-	((const type *) __omap_get_config((tag), sizeof(type), 0))
-#define omap_get_nr_config(tag, type, nr) \
-	((const type *) __omap_get_config((tag), sizeof(type), (nr)))
-
-extern const void *__init omap_get_var_config(u16 tag, size_t *len);
-
-extern struct omap_board_config_kernel *omap_board_config;
-extern int omap_board_config_size;
-
-
-/* for TI reference platforms sharing the same debug card */
-extern int debug_card_init(u32 addr, unsigned gpio);
-
-/* OMAP3EVM revision */
-#if defined(CONFIG_MACH_OMAP3EVM)
-u8 get_omap3_evm_rev(void);
-#else
-#define get_omap3_evm_rev() (-EINVAL)
-#endif
-#endif
diff --git a/arch/arm/plat-omap/include/plat/cpu.h b/arch/arm/plat-omap/include/plat/cpu.h
index bb5d08a..67da857 100644
--- a/arch/arm/plat-omap/include/plat/cpu.h
+++ b/arch/arm/plat-omap/include/plat/cpu.h
@@ -30,6 +30,8 @@
 #ifndef __ASM_ARCH_OMAP_CPU_H
 #define __ASM_ARCH_OMAP_CPU_H
 
+#ifndef __ASSEMBLY__
+
 #include <linux/bitops.h>
 #include <plat/multi.h>
 
@@ -493,4 +495,5 @@ OMAP4_HAS_FEATURE(mpu_1ghz, MPU_1GHZ)
 OMAP4_HAS_FEATURE(mpu_1_2ghz, MPU_1_2GHZ)
 OMAP4_HAS_FEATURE(mpu_1_5ghz, MPU_1_5GHZ)
 
+#endif	/* __ASSEMBLY__ */
 #endif
diff --git a/arch/arm/plat-omap/include/plat/dma.h b/arch/arm/plat-omap/include/plat/dma.h
index c5811d4..0a87b05 100644
--- a/arch/arm/plat-omap/include/plat/dma.h
+++ b/arch/arm/plat-omap/include/plat/dma.h
@@ -31,6 +31,8 @@
 /* Move omap4 specific defines to dma-44xx.h */
 #include "dma-44xx.h"
 
+#define INT_DMA_LCD			25
+
 /* DMA channels for omap1 */
 #define OMAP_DMA_NO_DEVICE		0
 #define OMAP_DMA_MCSI1_TX		1
diff --git a/arch/arm/plat-omap/include/plat/dsp.h b/arch/arm/plat-omap/include/plat/dsp.h
deleted file mode 100644
index 5927709..0000000
--- a/arch/arm/plat-omap/include/plat/dsp.h
+++ /dev/null
@@ -1,34 +0,0 @@
-#ifndef __OMAP_DSP_H__
-#define __OMAP_DSP_H__
-
-#include <linux/types.h>
-
-struct omap_dsp_platform_data {
-	void (*dsp_set_min_opp) (u8 opp_id);
-	u8 (*dsp_get_opp) (void);
-	void (*cpu_set_freq) (unsigned long f);
-	unsigned long (*cpu_get_freq) (void);
-	unsigned long mpu_speed[6];
-
-	/* functions to write and read PRCM registers */
-	void (*dsp_prm_write)(u32, s16 , u16);
-	u32 (*dsp_prm_read)(s16 , u16);
-	u32 (*dsp_prm_rmw_bits)(u32, u32, s16, s16);
-	void (*dsp_cm_write)(u32, s16 , u16);
-	u32 (*dsp_cm_read)(s16 , u16);
-	u32 (*dsp_cm_rmw_bits)(u32, u32, s16, s16);
-
-	void (*set_bootaddr)(u32);
-	void (*set_bootmode)(u8);
-
-	phys_addr_t phys_mempool_base;
-	phys_addr_t phys_mempool_size;
-};
-
-#if defined(CONFIG_TIDSPBRIDGE) || defined(CONFIG_TIDSPBRIDGE_MODULE)
-extern void omap_dsp_reserve_sdram_memblock(void);
-#else
-static inline void omap_dsp_reserve_sdram_memblock(void) { }
-#endif
-
-#endif
diff --git a/arch/arm/plat-omap/include/plat/flash.h b/arch/arm/plat-omap/include/plat/flash.h
deleted file mode 100644
index 0d88499..0000000
--- a/arch/arm/plat-omap/include/plat/flash.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Flash support for OMAP1
- *
- * This program is free software; you can 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_FLASH_H
-#define __OMAP_FLASH_H
-
-#include <linux/mtd/map.h>
-
-struct platform_device;
-extern void omap1_set_vpp(struct platform_device *pdev, int enable);
-
-#endif
diff --git a/arch/arm/plat-omap/include/plat/gpio-switch.h b/arch/arm/plat-omap/include/plat/gpio-switch.h
deleted file mode 100644
index 10da0e0..0000000
--- a/arch/arm/plat-omap/include/plat/gpio-switch.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * GPIO switch definitions
- *
- * Copyright (C) 2006 Nokia Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __ASM_ARCH_OMAP_GPIO_SWITCH_H
-#define __ASM_ARCH_OMAP_GPIO_SWITCH_H
-
-#include <linux/types.h>
-
-/* Cover:
- *	high -> closed
- *	low  -> open
- * Connection:
- *	high -> connected
- *	low  -> disconnected
- * Activity:
- *	high -> active
- *	low  -> inactive
- *
- */
-#define OMAP_GPIO_SWITCH_TYPE_COVER		0x0000
-#define OMAP_GPIO_SWITCH_TYPE_CONNECTION	0x0001
-#define OMAP_GPIO_SWITCH_TYPE_ACTIVITY		0x0002
-#define OMAP_GPIO_SWITCH_FLAG_INVERTED		0x0001
-#define OMAP_GPIO_SWITCH_FLAG_OUTPUT		0x0002
-
-struct omap_gpio_switch {
-	const char *name;
-	s16 gpio;
-	unsigned flags:4;
-	unsigned type:4;
-
-	/* Time in ms to debounce when transitioning from
-	 * inactive state to active state. */
-	u16 debounce_rising;
-	/* Same for transition from active to inactive state. */
-	u16 debounce_falling;
-
-	/* notify board-specific code about state changes */
-	void (* notify)(void *data, int state);
-	void *notify_data;
-};
-
-/* Call at init time only */
-extern void omap_register_gpio_switches(const struct omap_gpio_switch *tbl,
-					int count);
-
-#endif
diff --git a/arch/arm/plat-omap/include/plat/gpio.h b/arch/arm/plat-omap/include/plat/gpio.h
deleted file mode 100644
index 50fb7cc..0000000
--- a/arch/arm/plat-omap/include/plat/gpio.h
+++ /dev/null
@@ -1,228 +0,0 @@
-/*
- * arch/arm/plat-omap/include/mach/gpio.h
- *
- * OMAP GPIO handling defines and functions
- *
- * Copyright (C) 2003-2005 Nokia Corporation
- *
- * Written by Juha Yrjölä <juha.yrjola@nokia.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#ifndef __ASM_ARCH_OMAP_GPIO_H
-#define __ASM_ARCH_OMAP_GPIO_H
-
-#include <linux/io.h>
-#include <linux/platform_device.h>
-#include <mach/irqs.h>
-
-#define OMAP1_MPUIO_BASE			0xfffb5000
-
-/*
- * These are the omap15xx/16xx offsets. The omap7xx offset are
- * OMAP_MPUIO_ / 2 offsets below.
- */
-#define OMAP_MPUIO_INPUT_LATCH		0x00
-#define OMAP_MPUIO_OUTPUT		0x04
-#define OMAP_MPUIO_IO_CNTL		0x08
-#define OMAP_MPUIO_KBR_LATCH		0x10
-#define OMAP_MPUIO_KBC			0x14
-#define OMAP_MPUIO_GPIO_EVENT_MODE	0x18
-#define OMAP_MPUIO_GPIO_INT_EDGE	0x1c
-#define OMAP_MPUIO_KBD_INT		0x20
-#define OMAP_MPUIO_GPIO_INT		0x24
-#define OMAP_MPUIO_KBD_MASKIT		0x28
-#define OMAP_MPUIO_GPIO_MASKIT		0x2c
-#define OMAP_MPUIO_GPIO_DEBOUNCING	0x30
-#define OMAP_MPUIO_LATCH		0x34
-
-#define OMAP34XX_NR_GPIOS		6
-
-/*
- * OMAP1510 GPIO registers
- */
-#define OMAP1510_GPIO_DATA_INPUT	0x00
-#define OMAP1510_GPIO_DATA_OUTPUT	0x04
-#define OMAP1510_GPIO_DIR_CONTROL	0x08
-#define OMAP1510_GPIO_INT_CONTROL	0x0c
-#define OMAP1510_GPIO_INT_MASK		0x10
-#define OMAP1510_GPIO_INT_STATUS	0x14
-#define OMAP1510_GPIO_PIN_CONTROL	0x18
-
-#define OMAP1510_IH_GPIO_BASE		64
-
-/*
- * OMAP1610 specific GPIO registers
- */
-#define OMAP1610_GPIO_REVISION		0x0000
-#define OMAP1610_GPIO_SYSCONFIG		0x0010
-#define OMAP1610_GPIO_SYSSTATUS		0x0014
-#define OMAP1610_GPIO_IRQSTATUS1	0x0018
-#define OMAP1610_GPIO_IRQENABLE1	0x001c
-#define OMAP1610_GPIO_WAKEUPENABLE	0x0028
-#define OMAP1610_GPIO_DATAIN		0x002c
-#define OMAP1610_GPIO_DATAOUT		0x0030
-#define OMAP1610_GPIO_DIRECTION		0x0034
-#define OMAP1610_GPIO_EDGE_CTRL1	0x0038
-#define OMAP1610_GPIO_EDGE_CTRL2	0x003c
-#define OMAP1610_GPIO_CLEAR_IRQENABLE1	0x009c
-#define OMAP1610_GPIO_CLEAR_WAKEUPENA	0x00a8
-#define OMAP1610_GPIO_CLEAR_DATAOUT	0x00b0
-#define OMAP1610_GPIO_SET_IRQENABLE1	0x00dc
-#define OMAP1610_GPIO_SET_WAKEUPENA	0x00e8
-#define OMAP1610_GPIO_SET_DATAOUT	0x00f0
-
-/*
- * OMAP7XX specific GPIO registers
- */
-#define OMAP7XX_GPIO_DATA_INPUT		0x00
-#define OMAP7XX_GPIO_DATA_OUTPUT	0x04
-#define OMAP7XX_GPIO_DIR_CONTROL	0x08
-#define OMAP7XX_GPIO_INT_CONTROL	0x0c
-#define OMAP7XX_GPIO_INT_MASK		0x10
-#define OMAP7XX_GPIO_INT_STATUS		0x14
-
-/*
- * omap2+ specific GPIO registers
- */
-#define OMAP24XX_GPIO_REVISION		0x0000
-#define OMAP24XX_GPIO_IRQSTATUS1	0x0018
-#define OMAP24XX_GPIO_IRQSTATUS2	0x0028
-#define OMAP24XX_GPIO_IRQENABLE2	0x002c
-#define OMAP24XX_GPIO_IRQENABLE1	0x001c
-#define OMAP24XX_GPIO_WAKE_EN		0x0020
-#define OMAP24XX_GPIO_CTRL		0x0030
-#define OMAP24XX_GPIO_OE		0x0034
-#define OMAP24XX_GPIO_DATAIN		0x0038
-#define OMAP24XX_GPIO_DATAOUT		0x003c
-#define OMAP24XX_GPIO_LEVELDETECT0	0x0040
-#define OMAP24XX_GPIO_LEVELDETECT1	0x0044
-#define OMAP24XX_GPIO_RISINGDETECT	0x0048
-#define OMAP24XX_GPIO_FALLINGDETECT	0x004c
-#define OMAP24XX_GPIO_DEBOUNCE_EN	0x0050
-#define OMAP24XX_GPIO_DEBOUNCE_VAL	0x0054
-#define OMAP24XX_GPIO_CLEARIRQENABLE1	0x0060
-#define OMAP24XX_GPIO_SETIRQENABLE1	0x0064
-#define OMAP24XX_GPIO_CLEARWKUENA	0x0080
-#define OMAP24XX_GPIO_SETWKUENA		0x0084
-#define OMAP24XX_GPIO_CLEARDATAOUT	0x0090
-#define OMAP24XX_GPIO_SETDATAOUT	0x0094
-
-#define OMAP4_GPIO_REVISION		0x0000
-#define OMAP4_GPIO_EOI			0x0020
-#define OMAP4_GPIO_IRQSTATUSRAW0	0x0024
-#define OMAP4_GPIO_IRQSTATUSRAW1	0x0028
-#define OMAP4_GPIO_IRQSTATUS0		0x002c
-#define OMAP4_GPIO_IRQSTATUS1		0x0030
-#define OMAP4_GPIO_IRQSTATUSSET0	0x0034
-#define OMAP4_GPIO_IRQSTATUSSET1	0x0038
-#define OMAP4_GPIO_IRQSTATUSCLR0	0x003c
-#define OMAP4_GPIO_IRQSTATUSCLR1	0x0040
-#define OMAP4_GPIO_IRQWAKEN0		0x0044
-#define OMAP4_GPIO_IRQWAKEN1		0x0048
-#define OMAP4_GPIO_IRQENABLE1		0x011c
-#define OMAP4_GPIO_WAKE_EN		0x0120
-#define OMAP4_GPIO_IRQSTATUS2		0x0128
-#define OMAP4_GPIO_IRQENABLE2		0x012c
-#define OMAP4_GPIO_CTRL			0x0130
-#define OMAP4_GPIO_OE			0x0134
-#define OMAP4_GPIO_DATAIN		0x0138
-#define OMAP4_GPIO_DATAOUT		0x013c
-#define OMAP4_GPIO_LEVELDETECT0		0x0140
-#define OMAP4_GPIO_LEVELDETECT1		0x0144
-#define OMAP4_GPIO_RISINGDETECT		0x0148
-#define OMAP4_GPIO_FALLINGDETECT	0x014c
-#define OMAP4_GPIO_DEBOUNCENABLE	0x0150
-#define OMAP4_GPIO_DEBOUNCINGTIME	0x0154
-#define OMAP4_GPIO_CLEARIRQENABLE1	0x0160
-#define OMAP4_GPIO_SETIRQENABLE1	0x0164
-#define OMAP4_GPIO_CLEARWKUENA		0x0180
-#define OMAP4_GPIO_SETWKUENA		0x0184
-#define OMAP4_GPIO_CLEARDATAOUT		0x0190
-#define OMAP4_GPIO_SETDATAOUT		0x0194
-
-#define OMAP_MPUIO(nr)		(OMAP_MAX_GPIO_LINES + (nr))
-#define OMAP_GPIO_IS_MPUIO(nr)	((nr) >= OMAP_MAX_GPIO_LINES)
-
-struct omap_gpio_dev_attr {
-	int bank_width;		/* GPIO bank width */
-	bool dbck_flag;		/* dbck required or not - True for OMAP3&4 */
-};
-
-struct omap_gpio_reg_offs {
-	u16 revision;
-	u16 direction;
-	u16 datain;
-	u16 dataout;
-	u16 set_dataout;
-	u16 clr_dataout;
-	u16 irqstatus;
-	u16 irqstatus2;
-	u16 irqstatus_raw0;
-	u16 irqstatus_raw1;
-	u16 irqenable;
-	u16 irqenable2;
-	u16 set_irqenable;
-	u16 clr_irqenable;
-	u16 debounce;
-	u16 debounce_en;
-	u16 ctrl;
-	u16 wkup_en;
-	u16 leveldetect0;
-	u16 leveldetect1;
-	u16 risingdetect;
-	u16 fallingdetect;
-	u16 irqctrl;
-	u16 edgectrl1;
-	u16 edgectrl2;
-	u16 pinctrl;
-
-	bool irqenable_inv;
-};
-
-struct omap_gpio_platform_data {
-	int bank_type;
-	int bank_width;		/* GPIO bank width */
-	int bank_stride;	/* Only needed for omap1 MPUIO */
-	bool dbck_flag;		/* dbck required or not - True for OMAP3&4 */
-	bool loses_context;	/* whether the bank would ever lose context */
-	bool is_mpuio;		/* whether the bank is of type MPUIO */
-	u32 non_wakeup_gpios;
-
-	struct omap_gpio_reg_offs *regs;
-
-	/* Return context loss count due to PM states changing */
-	int (*get_context_loss_count)(struct device *dev);
-};
-
-extern void omap2_gpio_prepare_for_idle(int off_mode);
-extern void omap2_gpio_resume_after_idle(void);
-extern void omap_set_gpio_debounce(int gpio, int enable);
-extern void omap_set_gpio_debounce_time(int gpio, int enable);
-/*-------------------------------------------------------------------------*/
-
-/*
- * Wrappers for "new style" GPIO calls, using the new infrastructure
- * which lets us plug in FPGA, I2C, and other implementations.
- *
- * The original OMAP-specific calls should eventually be removed.
- */
-
-#include <linux/errno.h>
-#include <asm-generic/gpio.h>
-
-#endif
diff --git a/arch/arm/plat-omap/include/plat/gpmc-smc91x.h b/arch/arm/plat-omap/include/plat/gpmc-smc91x.h
deleted file mode 100644
index b64fbee..0000000
--- a/arch/arm/plat-omap/include/plat/gpmc-smc91x.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * arch/arm/plat-omap/include/mach/gpmc-smc91x.h
- *
- * Copyright (C) 2009 Nokia Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __ASM_ARCH_OMAP_GPMC_SMC91X_H__
-
-#define GPMC_TIMINGS_SMC91C96	(1 << 4)
-#define GPMC_MUX_ADD_DATA	(1 << 5) /* GPMC_CONFIG1_MUXADDDATA */
-#define GPMC_READ_MON		(1 << 6) /* GPMC_CONFIG1_WAIT_READ_MON */
-#define GPMC_WRITE_MON		(1 << 7) /* GPMC_CONFIG1_WAIT_WRITE_MON */
-
-struct omap_smc91x_platform_data {
-	int	cs;
-	int	gpio_irq;
-	int	gpio_pwrdwn;
-	int	gpio_reset;
-	int	wait_pin;	/* Optional GPMC_CONFIG1_WAITPINSELECT */
-	u32	flags;
-	int	(*retime)(void);
-};
-
-#if defined(CONFIG_SMC91X) || \
-	defined(CONFIG_SMC91X_MODULE)
-
-extern void gpmc_smc91x_init(struct omap_smc91x_platform_data *d);
-
-#else
-
-#define board_smc91x_data	NULL
-
-static inline void gpmc_smc91x_init(struct omap_smc91x_platform_data *d)
-{
-}
-
-#endif
-#endif
diff --git a/arch/arm/plat-omap/include/plat/gpmc-smsc911x.h b/arch/arm/plat-omap/include/plat/gpmc-smsc911x.h
deleted file mode 100644
index ea6c9c8..0000000
--- a/arch/arm/plat-omap/include/plat/gpmc-smsc911x.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * arch/arm/plat-omap/include/plat/gpmc-smsc911x.h
- *
- * Copyright (C) 2009 Li-Pro.Net
- * Stephan Linz <linz@li-pro.net>
- *
- * Modified from arch/arm/plat-omap/include/plat/gpmc-smc91x.h
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __ASM_ARCH_OMAP_GPMC_SMSC911X_H__
-
-struct omap_smsc911x_platform_data {
-	int	id;
-	int	cs;
-	int	gpio_irq;
-	int	gpio_reset;
-	u32	flags;
-};
-
-#if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)
-
-extern void gpmc_smsc911x_init(struct omap_smsc911x_platform_data *d);
-
-#else
-
-static inline void gpmc_smsc911x_init(struct omap_smsc911x_platform_data *d)
-{
-}
-
-#endif
-#endif
diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h
index f37764a..2e6e259 100644
--- a/arch/arm/plat-omap/include/plat/gpmc.h
+++ b/arch/arm/plat-omap/include/plat/gpmc.h
@@ -133,6 +133,25 @@ struct gpmc_timings {
 	u16 wr_data_mux_bus;	/* WRDATAONADMUXBUS */
 };
 
+struct gpmc_nand_regs {
+	void __iomem	*gpmc_status;
+	void __iomem	*gpmc_nand_command;
+	void __iomem	*gpmc_nand_address;
+	void __iomem	*gpmc_nand_data;
+	void __iomem	*gpmc_prefetch_config1;
+	void __iomem	*gpmc_prefetch_config2;
+	void __iomem	*gpmc_prefetch_control;
+	void __iomem	*gpmc_prefetch_status;
+	void __iomem	*gpmc_ecc_config;
+	void __iomem	*gpmc_ecc_control;
+	void __iomem	*gpmc_ecc_size_config;
+	void __iomem	*gpmc_ecc1_result;
+	void __iomem	*gpmc_bch_result0;
+};
+
+extern void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs);
+extern int gpmc_get_client_irq(unsigned irq_config);
+
 extern unsigned int gpmc_ns_to_ticks(unsigned int time_ns);
 extern unsigned int gpmc_ps_to_ticks(unsigned int time_ps);
 extern unsigned int gpmc_ticks_to_ns(unsigned int ticks);
diff --git a/arch/arm/plat-omap/include/plat/hardware.h b/arch/arm/plat-omap/include/plat/hardware.h
deleted file mode 100644
index ddbde38..0000000
--- a/arch/arm/plat-omap/include/plat/hardware.h
+++ /dev/null
@@ -1,293 +0,0 @@
-/*
- * arch/arm/plat-omap/include/mach/hardware.h
- *
- * Hardware definitions for TI OMAP processors and boards
- *
- * NOTE: Please put device driver specific defines into a separate header
- *	 file for each driver.
- *
- * Copyright (C) 2001 RidgeRun, Inc.
- * Author: RidgeRun, Inc. Greg Lonnon <glonnon@ridgerun.com>
- *
- * Reorganized for Linux-2.6 by Tony Lindgren <tony@atomide.com>
- *                          and 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_HARDWARE_H
-#define __ASM_ARCH_OMAP_HARDWARE_H
-
-#include <asm/sizes.h>
-#ifndef __ASSEMBLER__
-#include <asm/types.h>
-#include <plat/cpu.h>
-#endif
-#include <plat/serial.h>
-
-/*
- * ---------------------------------------------------------------------------
- * Common definitions for all OMAP processors
- * NOTE: Put all processor or board specific parts to the special header
- *	 files.
- * ---------------------------------------------------------------------------
- */
-
-/*
- * ----------------------------------------------------------------------------
- * Timers
- * ----------------------------------------------------------------------------
- */
-#define OMAP_MPU_TIMER1_BASE	(0xfffec500)
-#define OMAP_MPU_TIMER2_BASE	(0xfffec600)
-#define OMAP_MPU_TIMER3_BASE	(0xfffec700)
-#define MPU_TIMER_FREE		(1 << 6)
-#define MPU_TIMER_CLOCK_ENABLE	(1 << 5)
-#define MPU_TIMER_AR		(1 << 1)
-#define MPU_TIMER_ST		(1 << 0)
-
-/*
- * ----------------------------------------------------------------------------
- * Clocks
- * ----------------------------------------------------------------------------
- */
-#define CLKGEN_REG_BASE		(0xfffece00)
-#define ARM_CKCTL		(CLKGEN_REG_BASE + 0x0)
-#define ARM_IDLECT1		(CLKGEN_REG_BASE + 0x4)
-#define ARM_IDLECT2		(CLKGEN_REG_BASE + 0x8)
-#define ARM_EWUPCT		(CLKGEN_REG_BASE + 0xC)
-#define ARM_RSTCT1		(CLKGEN_REG_BASE + 0x10)
-#define ARM_RSTCT2		(CLKGEN_REG_BASE + 0x14)
-#define ARM_SYSST		(CLKGEN_REG_BASE + 0x18)
-#define ARM_IDLECT3		(CLKGEN_REG_BASE + 0x24)
-
-#define CK_RATEF		1
-#define CK_IDLEF		2
-#define CK_ENABLEF		4
-#define CK_SELECTF		8
-#define SETARM_IDLE_SHIFT
-
-/* DPLL control registers */
-#define DPLL_CTL		(0xfffecf00)
-
-/* DSP clock control. Must use __raw_readw() and __raw_writew() with these */
-#define DSP_CONFIG_REG_BASE     IOMEM(0xe1008000)
-#define DSP_CKCTL		(DSP_CONFIG_REG_BASE + 0x0)
-#define DSP_IDLECT1		(DSP_CONFIG_REG_BASE + 0x4)
-#define DSP_IDLECT2		(DSP_CONFIG_REG_BASE + 0x8)
-#define DSP_RSTCT2		(DSP_CONFIG_REG_BASE + 0x14)
-
-/*
- * ---------------------------------------------------------------------------
- * UPLD
- * ---------------------------------------------------------------------------
- */
-#define ULPD_REG_BASE		(0xfffe0800)
-#define ULPD_IT_STATUS		(ULPD_REG_BASE + 0x14)
-#define ULPD_SETUP_ANALOG_CELL_3	(ULPD_REG_BASE + 0x24)
-#define ULPD_CLOCK_CTRL		(ULPD_REG_BASE + 0x30)
-#	define DIS_USB_PVCI_CLK		(1 << 5)	/* no USB/FAC synch */
-#	define USB_MCLK_EN		(1 << 4)	/* enable W4_USB_CLKO */
-#define ULPD_SOFT_REQ		(ULPD_REG_BASE + 0x34)
-#	define SOFT_UDC_REQ		(1 << 4)
-#	define SOFT_USB_CLK_REQ		(1 << 3)
-#	define SOFT_DPLL_REQ		(1 << 0)
-#define ULPD_DPLL_CTRL		(ULPD_REG_BASE + 0x3c)
-#define ULPD_STATUS_REQ		(ULPD_REG_BASE + 0x40)
-#define ULPD_APLL_CTRL		(ULPD_REG_BASE + 0x4c)
-#define ULPD_POWER_CTRL		(ULPD_REG_BASE + 0x50)
-#define ULPD_SOFT_DISABLE_REQ_REG	(ULPD_REG_BASE + 0x68)
-#	define DIS_MMC2_DPLL_REQ	(1 << 11)
-#	define DIS_MMC1_DPLL_REQ	(1 << 10)
-#	define DIS_UART3_DPLL_REQ	(1 << 9)
-#	define DIS_UART2_DPLL_REQ	(1 << 8)
-#	define DIS_UART1_DPLL_REQ	(1 << 7)
-#	define DIS_USB_HOST_DPLL_REQ	(1 << 6)
-#define ULPD_SDW_CLK_DIV_CTRL_SEL	(ULPD_REG_BASE + 0x74)
-#define ULPD_CAM_CLK_CTRL	(ULPD_REG_BASE + 0x7c)
-
-/*
- * ---------------------------------------------------------------------------
- * Watchdog timer
- * ---------------------------------------------------------------------------
- */
-
-/* Watchdog timer within the OMAP3.2 gigacell */
-#define OMAP_MPU_WATCHDOG_BASE	(0xfffec800)
-#define OMAP_WDT_TIMER		(OMAP_MPU_WATCHDOG_BASE + 0x0)
-#define OMAP_WDT_LOAD_TIM	(OMAP_MPU_WATCHDOG_BASE + 0x4)
-#define OMAP_WDT_READ_TIM	(OMAP_MPU_WATCHDOG_BASE + 0x4)
-#define OMAP_WDT_TIMER_MODE	(OMAP_MPU_WATCHDOG_BASE + 0x8)
-
-/*
- * ---------------------------------------------------------------------------
- * Interrupts
- * ---------------------------------------------------------------------------
- */
-#ifdef CONFIG_ARCH_OMAP1
-
-/*
- * XXX: These probably want to be moved to arch/arm/mach-omap/omap1/irq.c
- * or something similar.. -- PFM.
- */
-
-#define OMAP_IH1_BASE		0xfffecb00
-#define OMAP_IH2_BASE		0xfffe0000
-
-#define OMAP_IH1_ITR		(OMAP_IH1_BASE + 0x00)
-#define OMAP_IH1_MIR		(OMAP_IH1_BASE + 0x04)
-#define OMAP_IH1_SIR_IRQ	(OMAP_IH1_BASE + 0x10)
-#define OMAP_IH1_SIR_FIQ	(OMAP_IH1_BASE + 0x14)
-#define OMAP_IH1_CONTROL	(OMAP_IH1_BASE + 0x18)
-#define OMAP_IH1_ILR0		(OMAP_IH1_BASE + 0x1c)
-#define OMAP_IH1_ISR		(OMAP_IH1_BASE + 0x9c)
-
-#define OMAP_IH2_ITR		(OMAP_IH2_BASE + 0x00)
-#define OMAP_IH2_MIR		(OMAP_IH2_BASE + 0x04)
-#define OMAP_IH2_SIR_IRQ	(OMAP_IH2_BASE + 0x10)
-#define OMAP_IH2_SIR_FIQ	(OMAP_IH2_BASE + 0x14)
-#define OMAP_IH2_CONTROL	(OMAP_IH2_BASE + 0x18)
-#define OMAP_IH2_ILR0		(OMAP_IH2_BASE + 0x1c)
-#define OMAP_IH2_ISR		(OMAP_IH2_BASE + 0x9c)
-
-#define IRQ_ITR_REG_OFFSET	0x00
-#define IRQ_MIR_REG_OFFSET	0x04
-#define IRQ_SIR_IRQ_REG_OFFSET	0x10
-#define IRQ_SIR_FIQ_REG_OFFSET	0x14
-#define IRQ_CONTROL_REG_OFFSET	0x18
-#define IRQ_ISR_REG_OFFSET	0x9c
-#define IRQ_ILR0_REG_OFFSET	0x1c
-#define IRQ_GMR_REG_OFFSET	0xa0
-
-#endif
-
-/*
- * ----------------------------------------------------------------------------
- * System control registers
- * ----------------------------------------------------------------------------
- */
-#define MOD_CONF_CTRL_0		0xfffe1080
-#define MOD_CONF_CTRL_1		0xfffe1110
-
-/*
- * ----------------------------------------------------------------------------
- * Pin multiplexing registers
- * ----------------------------------------------------------------------------
- */
-#define FUNC_MUX_CTRL_0		0xfffe1000
-#define FUNC_MUX_CTRL_1		0xfffe1004
-#define FUNC_MUX_CTRL_2		0xfffe1008
-#define COMP_MODE_CTRL_0	0xfffe100c
-#define FUNC_MUX_CTRL_3		0xfffe1010
-#define FUNC_MUX_CTRL_4		0xfffe1014
-#define FUNC_MUX_CTRL_5		0xfffe1018
-#define FUNC_MUX_CTRL_6		0xfffe101C
-#define FUNC_MUX_CTRL_7		0xfffe1020
-#define FUNC_MUX_CTRL_8		0xfffe1024
-#define FUNC_MUX_CTRL_9		0xfffe1028
-#define FUNC_MUX_CTRL_A		0xfffe102C
-#define FUNC_MUX_CTRL_B		0xfffe1030
-#define FUNC_MUX_CTRL_C		0xfffe1034
-#define FUNC_MUX_CTRL_D		0xfffe1038
-#define PULL_DWN_CTRL_0		0xfffe1040
-#define PULL_DWN_CTRL_1		0xfffe1044
-#define PULL_DWN_CTRL_2		0xfffe1048
-#define PULL_DWN_CTRL_3		0xfffe104c
-#define PULL_DWN_CTRL_4		0xfffe10ac
-
-/* OMAP-1610 specific multiplexing registers */
-#define FUNC_MUX_CTRL_E		0xfffe1090
-#define FUNC_MUX_CTRL_F		0xfffe1094
-#define FUNC_MUX_CTRL_10	0xfffe1098
-#define FUNC_MUX_CTRL_11	0xfffe109c
-#define FUNC_MUX_CTRL_12	0xfffe10a0
-#define PU_PD_SEL_0		0xfffe10b4
-#define PU_PD_SEL_1		0xfffe10b8
-#define PU_PD_SEL_2		0xfffe10bc
-#define PU_PD_SEL_3		0xfffe10c0
-#define PU_PD_SEL_4		0xfffe10c4
-
-/* Timer32K for 1610 and 1710*/
-#define OMAP_TIMER32K_BASE	0xFFFBC400
-
-/*
- * ---------------------------------------------------------------------------
- * TIPB bus interface
- * ---------------------------------------------------------------------------
- */
-#define TIPB_PUBLIC_CNTL_BASE		0xfffed300
-#define MPU_PUBLIC_TIPB_CNTL		(TIPB_PUBLIC_CNTL_BASE + 0x8)
-#define TIPB_PRIVATE_CNTL_BASE		0xfffeca00
-#define MPU_PRIVATE_TIPB_CNTL		(TIPB_PRIVATE_CNTL_BASE + 0x8)
-
-/*
- * ----------------------------------------------------------------------------
- * MPUI interface
- * ----------------------------------------------------------------------------
- */
-#define MPUI_BASE			(0xfffec900)
-#define MPUI_CTRL			(MPUI_BASE + 0x0)
-#define MPUI_DEBUG_ADDR			(MPUI_BASE + 0x4)
-#define MPUI_DEBUG_DATA			(MPUI_BASE + 0x8)
-#define MPUI_DEBUG_FLAG			(MPUI_BASE + 0xc)
-#define MPUI_STATUS_REG			(MPUI_BASE + 0x10)
-#define MPUI_DSP_STATUS			(MPUI_BASE + 0x14)
-#define MPUI_DSP_BOOT_CONFIG		(MPUI_BASE + 0x18)
-#define MPUI_DSP_API_CONFIG		(MPUI_BASE + 0x1c)
-
-/*
- * ----------------------------------------------------------------------------
- * LED Pulse Generator
- * ----------------------------------------------------------------------------
- */
-#define OMAP_LPG1_BASE			0xfffbd000
-#define OMAP_LPG2_BASE			0xfffbd800
-#define OMAP_LPG1_LCR			(OMAP_LPG1_BASE + 0x00)
-#define OMAP_LPG1_PMR			(OMAP_LPG1_BASE + 0x04)
-#define OMAP_LPG2_LCR			(OMAP_LPG2_BASE + 0x00)
-#define OMAP_LPG2_PMR			(OMAP_LPG2_BASE + 0x04)
-
-/*
- * ----------------------------------------------------------------------------
- * Pulse-Width Light
- * ----------------------------------------------------------------------------
- */
-#define OMAP_PWL_BASE			0xfffb5800
-#define OMAP_PWL_ENABLE			(OMAP_PWL_BASE + 0x00)
-#define OMAP_PWL_CLK_ENABLE		(OMAP_PWL_BASE + 0x04)
-
-/*
- * ---------------------------------------------------------------------------
- * Processor specific defines
- * ---------------------------------------------------------------------------
- */
-
-#include <plat/omap7xx.h>
-#include <plat/omap1510.h>
-#include <plat/omap16xx.h>
-#include <plat/omap24xx.h>
-#include <plat/omap34xx.h>
-#include <plat/omap44xx.h>
-#include <plat/ti81xx.h>
-#include <plat/am33xx.h>
-#include <plat/omap54xx.h>
-
-#endif	/* __ASM_ARCH_OMAP_HARDWARE_H */
diff --git a/arch/arm/plat-omap/include/plat/hdq1w.h b/arch/arm/plat-omap/include/plat/hdq1w.h
deleted file mode 100644
index 0c1efc8..0000000
--- a/arch/arm/plat-omap/include/plat/hdq1w.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Shared macros and function prototypes for the HDQ1W/1-wire IP block
- *
- * Copyright (C) 2012 Texas Instruments, Inc.
- * Paul Walmsley
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- */
-#ifndef ARCH_ARM_MACH_OMAP2_HDQ1W_H
-#define ARCH_ARM_MACH_OMAP2_HDQ1W_H
-
-#include <plat/omap_hwmod.h>
-
-/*
- * XXX A future cleanup patch should modify
- * drivers/w1/masters/omap_hdq.c to use these macros
- */
-#define HDQ_CTRL_STATUS_OFFSET			0x0c
-#define HDQ_CTRL_STATUS_CLOCKENABLE_SHIFT	5
-
-
-extern int omap_hdq1w_reset(struct omap_hwmod *oh);
-
-#endif
diff --git a/arch/arm/plat-omap/include/plat/irda.h b/arch/arm/plat-omap/include/plat/irda.h
deleted file mode 100644
index 40f6033..0000000
--- a/arch/arm/plat-omap/include/plat/irda.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- *  arch/arm/plat-omap/include/mach/irda.h
- *
- *  Copyright (C) 2005-2006 Komal Shah <komal_shah802003@yahoo.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 ASMARM_ARCH_IRDA_H
-#define ASMARM_ARCH_IRDA_H
-
-/* board specific transceiver capabilities */
-
-#define IR_SEL		1	/* Selects IrDA */
-#define IR_SIRMODE	2
-#define IR_FIRMODE	4
-#define IR_MIRMODE	8
-
-struct omap_irda_config {
-	int transceiver_cap;
-	int (*transceiver_mode)(struct device *dev, int mode);
-	int (*select_irda)(struct device *dev, int state);
-	int rx_channel;
-	int tx_channel;
-	unsigned long dest_start;
-	unsigned long src_start;
-	int tx_trigger;
-	int rx_trigger;
-	int mode;
-};
-
-#endif
diff --git a/arch/arm/plat-omap/include/plat/irqs-44xx.h b/arch/arm/plat-omap/include/plat/irqs-44xx.h
deleted file mode 100644
index 518322c..0000000
--- a/arch/arm/plat-omap/include/plat/irqs-44xx.h
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * OMAP4 Interrupt lines definitions
- *
- * Copyright (C) 2009-2010 Texas Instruments, Inc.
- *
- * Santosh Shilimkar (santosh.shilimkar@ti.com)
- * Benoit Cousson (b-cousson@ti.com)
- *
- * This file is automatically generated from the OMAP hardware databases.
- * We respectfully ask that any modifications to this file be coordinated
- * with the public linux-omap@vger.kernel.org mailing list and the
- * authors above to ensure that the autogeneration scripts are kept
- * up-to-date with the file contents.
- *
- * This program is free software; you can 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_OMAP44XX_IRQS_H
-#define __ARCH_ARM_MACH_OMAP2_OMAP44XX_IRQS_H
-
-/* OMAP44XX IRQs numbers definitions */
-#define OMAP44XX_IRQ_LOCALTIMER			29
-#define OMAP44XX_IRQ_LOCALWDT			30
-
-#define OMAP44XX_IRQ_GIC_START			32
-
-#define OMAP44XX_IRQ_PL310			(0 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_CTI0			(1 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_CTI1			(2 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_ELM			(4 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_SYS_1N			(7 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_SECURITY_EVENTS		(8 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_L3_DBG			(9 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_L3_APP			(10 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_PRCM			(11 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_SDMA_0			(12 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_SDMA_1			(13 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_SDMA_2			(14 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_SDMA_3			(15 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_MCBSP4			(16 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_MCBSP1			(17 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_SR_MCU			(18 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_SR_CORE			(19 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_GPMC			(20 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_GFX			(21 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_MCBSP2			(22 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_MCBSP3			(23 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_ISS_5			(24 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_DSS_DISPC			(25 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_MAIL_U0			(26 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_C2C_SSCM_0			(27 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_TESLA_MMU			(28 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_GPIO1			(29 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_GPIO2			(30 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_GPIO3			(31 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_GPIO4			(32 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_GPIO5			(33 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_GPIO6			(34 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_USIM			(35 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_WDT3			(36 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_GPT1			(37 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_GPT2			(38 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_GPT3			(39 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_GPT4			(40 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_GPT5			(41 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_GPT6			(42 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_GPT7			(43 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_GPT8			(44 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_GPT9			(45 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_GPT10			(46 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_GPT11			(47 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_SPI4			(48 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_SHA1_S			(49 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_FPKA_SINTREQUEST_S		(50 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_SHA1_P			(51 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_RNG			(52 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_DSS_DSI1			(53 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_I2C1			(56 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_I2C2			(57 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_HDQ			(58 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_MMC5			(59 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_I2C3			(61 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_I2C4			(62 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_AES2_S			(63 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_AES2_P			(64 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_SPI1			(65 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_SPI2			(66 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_HSI_P1			(67 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_HSI_P2			(68 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_FDIF_3			(69 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_UART4			(70 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_HSI_DMA			(71 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_UART1			(72 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_UART2			(73 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_UART3			(74 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_PBIAS			(75 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_OHCI			(76 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_EHCI			(77 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_TLL			(78 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_AES1_S			(79 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_WDT2			(80 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_DES_S			(81 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_DES_P			(82 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_MMC1			(83 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_DSS_DSI2			(84 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_AES1_P			(85 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_MMC2			(86 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_MPU_ICR			(87 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_C2C_SSCM_1			(88 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_FSUSB			(89 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_FSUSB_SMI			(90 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_SPI3			(91 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_HS_USB_MC_N		(92 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_HS_USB_DMA_N		(93 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_MMC3			(94 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_GPT12			(95 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_MMC4			(96 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_SLIMBUS1			(97 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_SLIMBUS2			(98 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_ABE			(99 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_DUCATI_MMU			(100 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_DSS_HDMI			(101 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_SR_IVA			(102 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_IVA_HD_POSYNCITRPEND_1	(103 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_IVA_HD_POSYNCITRPEND_0	(104 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_IVA_HD_POMBINTRPEND_0	(107 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_MCASP1_AR			(108 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_MCASP1_AX			(109 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_EMIF4_1			(110 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_EMIF4_2			(111 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_MCPDM			(112 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_DMM			(113 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_DMIC			(114 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_CDMA_0			(115 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_CDMA_1			(116 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_CDMA_2			(117 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_CDMA_3			(118 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_SYS_2N			(119 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_KBD_CTL			(120 + OMAP44XX_IRQ_GIC_START)
-#define OMAP44XX_IRQ_UNIPRO1			(124 + OMAP44XX_IRQ_GIC_START)
-
-#endif
diff --git a/arch/arm/plat-omap/include/plat/irqs.h b/arch/arm/plat-omap/include/plat/irqs.h
deleted file mode 100644
index 37bbbbb..0000000
--- a/arch/arm/plat-omap/include/plat/irqs.h
+++ /dev/null
@@ -1,453 +0,0 @@
-/*
- *  arch/arm/plat-omap/include/mach/irqs.h
- *
- *  Copyright (C) Greg Lonnon 2001
- *  Updated for OMAP-1610 by Tony Lindgren <tony@atomide.com>
- *
- * Copyright (C) 2009 Texas Instruments
- * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@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 program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * NOTE: The interrupt vectors for the OMAP-1509, OMAP-1510, and OMAP-1610
- *	 are different.
- */
-
-#ifndef __ASM_ARCH_OMAP15XX_IRQS_H
-#define __ASM_ARCH_OMAP15XX_IRQS_H
-
-/* All OMAP4 specific defines are moved to irqs-44xx.h */
-#include "irqs-44xx.h"
-
-/*
- * IRQ numbers for interrupt handler 1
- *
- * NOTE: See also the OMAP-1510 and 1610 specific IRQ numbers below
- *
- */
-#define INT_CAMERA		1
-#define INT_FIQ			3
-#define INT_RTDX		6
-#define INT_DSP_MMU_ABORT	7
-#define INT_HOST		8
-#define INT_ABORT		9
-#define INT_BRIDGE_PRIV		13
-#define INT_GPIO_BANK1		14
-#define INT_UART3		15
-#define INT_TIMER3		16
-#define INT_DMA_CH0_6		19
-#define INT_DMA_CH1_7		20
-#define INT_DMA_CH2_8		21
-#define INT_DMA_CH3		22
-#define INT_DMA_CH4		23
-#define INT_DMA_CH5		24
-#define INT_DMA_LCD		25
-#define INT_TIMER1		26
-#define INT_WD_TIMER		27
-#define INT_BRIDGE_PUB		28
-#define INT_TIMER2		30
-#define INT_LCD_CTRL		31
-
-/*
- * OMAP-1510 specific IRQ numbers for interrupt handler 1
- */
-#define INT_1510_IH2_IRQ	0
-#define INT_1510_RES2		2
-#define INT_1510_SPI_TX		4
-#define INT_1510_SPI_RX		5
-#define INT_1510_DSP_MAILBOX1	10
-#define INT_1510_DSP_MAILBOX2	11
-#define INT_1510_RES12		12
-#define INT_1510_LB_MMU		17
-#define INT_1510_RES18		18
-#define INT_1510_LOCAL_BUS	29
-
-/*
- * OMAP-1610 specific IRQ numbers for interrupt handler 1
- */
-#define INT_1610_IH2_IRQ	INT_1510_IH2_IRQ
-#define INT_1610_IH2_FIQ	2
-#define INT_1610_McBSP2_TX	4
-#define INT_1610_McBSP2_RX	5
-#define INT_1610_DSP_MAILBOX1	10
-#define INT_1610_DSP_MAILBOX2	11
-#define INT_1610_LCD_LINE	12
-#define INT_1610_GPTIMER1	17
-#define INT_1610_GPTIMER2	18
-#define INT_1610_SSR_FIFO_0	29
-
-/*
- * OMAP-7xx specific IRQ numbers for interrupt handler 1
- */
-#define INT_7XX_IH2_FIQ		0
-#define INT_7XX_IH2_IRQ		1
-#define INT_7XX_USB_NON_ISO	2
-#define INT_7XX_USB_ISO		3
-#define INT_7XX_ICR		4
-#define INT_7XX_EAC		5
-#define INT_7XX_GPIO_BANK1	6
-#define INT_7XX_GPIO_BANK2	7
-#define INT_7XX_GPIO_BANK3	8
-#define INT_7XX_McBSP2TX	10
-#define INT_7XX_McBSP2RX	11
-#define INT_7XX_McBSP2RX_OVF	12
-#define INT_7XX_LCD_LINE	14
-#define INT_7XX_GSM_PROTECT	15
-#define INT_7XX_TIMER3		16
-#define INT_7XX_GPIO_BANK5	17
-#define INT_7XX_GPIO_BANK6	18
-#define INT_7XX_SPGIO_WR	29
-
-/*
- * IRQ numbers for interrupt handler 2
- *
- * NOTE: See also the OMAP-1510 and 1610 specific IRQ numbers below
- */
-#define IH2_BASE		32
-
-#define INT_KEYBOARD		(1 + IH2_BASE)
-#define INT_uWireTX		(2 + IH2_BASE)
-#define INT_uWireRX		(3 + IH2_BASE)
-#define INT_I2C			(4 + IH2_BASE)
-#define INT_MPUIO		(5 + IH2_BASE)
-#define INT_USB_HHC_1		(6 + IH2_BASE)
-#define INT_McBSP3TX		(10 + IH2_BASE)
-#define INT_McBSP3RX		(11 + IH2_BASE)
-#define INT_McBSP1TX		(12 + IH2_BASE)
-#define INT_McBSP1RX		(13 + IH2_BASE)
-#define INT_UART1		(14 + IH2_BASE)
-#define INT_UART2		(15 + IH2_BASE)
-#define INT_BT_MCSI1TX		(16 + IH2_BASE)
-#define INT_BT_MCSI1RX		(17 + IH2_BASE)
-#define INT_SOSSI_MATCH		(19 + IH2_BASE)
-#define INT_USB_W2FC		(20 + IH2_BASE)
-#define INT_1WIRE		(21 + IH2_BASE)
-#define INT_OS_TIMER		(22 + IH2_BASE)
-#define INT_MMC			(23 + IH2_BASE)
-#define INT_GAUGE_32K		(24 + IH2_BASE)
-#define INT_RTC_TIMER		(25 + IH2_BASE)
-#define INT_RTC_ALARM		(26 + IH2_BASE)
-#define INT_MEM_STICK		(27 + IH2_BASE)
-
-/*
- * OMAP-1510 specific IRQ numbers for interrupt handler 2
- */
-#define INT_1510_DSP_MMU	(28 + IH2_BASE)
-#define INT_1510_COM_SPI_RO	(31 + IH2_BASE)
-
-/*
- * OMAP-1610 specific IRQ numbers for interrupt handler 2
- */
-#define INT_1610_FAC		(0 + IH2_BASE)
-#define INT_1610_USB_HHC_2	(7 + IH2_BASE)
-#define INT_1610_USB_OTG	(8 + IH2_BASE)
-#define INT_1610_SoSSI		(9 + IH2_BASE)
-#define INT_1610_SoSSI_MATCH	(19 + IH2_BASE)
-#define INT_1610_DSP_MMU	(28 + IH2_BASE)
-#define INT_1610_McBSP2RX_OF	(31 + IH2_BASE)
-#define INT_1610_STI		(32 + IH2_BASE)
-#define INT_1610_STI_WAKEUP	(33 + IH2_BASE)
-#define INT_1610_GPTIMER3	(34 + IH2_BASE)
-#define INT_1610_GPTIMER4	(35 + IH2_BASE)
-#define INT_1610_GPTIMER5	(36 + IH2_BASE)
-#define INT_1610_GPTIMER6	(37 + IH2_BASE)
-#define INT_1610_GPTIMER7	(38 + IH2_BASE)
-#define INT_1610_GPTIMER8	(39 + IH2_BASE)
-#define INT_1610_GPIO_BANK2	(40 + IH2_BASE)
-#define INT_1610_GPIO_BANK3	(41 + IH2_BASE)
-#define INT_1610_MMC2		(42 + IH2_BASE)
-#define INT_1610_CF		(43 + IH2_BASE)
-#define INT_1610_WAKE_UP_REQ	(46 + IH2_BASE)
-#define INT_1610_GPIO_BANK4	(48 + IH2_BASE)
-#define INT_1610_SPI		(49 + IH2_BASE)
-#define INT_1610_DMA_CH6	(53 + IH2_BASE)
-#define INT_1610_DMA_CH7	(54 + IH2_BASE)
-#define INT_1610_DMA_CH8	(55 + IH2_BASE)
-#define INT_1610_DMA_CH9	(56 + IH2_BASE)
-#define INT_1610_DMA_CH10	(57 + IH2_BASE)
-#define INT_1610_DMA_CH11	(58 + IH2_BASE)
-#define INT_1610_DMA_CH12	(59 + IH2_BASE)
-#define INT_1610_DMA_CH13	(60 + IH2_BASE)
-#define INT_1610_DMA_CH14	(61 + IH2_BASE)
-#define INT_1610_DMA_CH15	(62 + IH2_BASE)
-#define INT_1610_NAND		(63 + IH2_BASE)
-#define INT_1610_SHA1MD5	(91 + IH2_BASE)
-
-/*
- * OMAP-7xx specific IRQ numbers for interrupt handler 2
- */
-#define INT_7XX_HW_ERRORS	(0 + IH2_BASE)
-#define INT_7XX_NFIQ_PWR_FAIL	(1 + IH2_BASE)
-#define INT_7XX_CFCD		(2 + IH2_BASE)
-#define INT_7XX_CFIREQ		(3 + IH2_BASE)
-#define INT_7XX_I2C		(4 + IH2_BASE)
-#define INT_7XX_PCC		(5 + IH2_BASE)
-#define INT_7XX_MPU_EXT_NIRQ	(6 + IH2_BASE)
-#define INT_7XX_SPI_100K_1	(7 + IH2_BASE)
-#define INT_7XX_SYREN_SPI	(8 + IH2_BASE)
-#define INT_7XX_VLYNQ		(9 + IH2_BASE)
-#define INT_7XX_GPIO_BANK4	(10 + IH2_BASE)
-#define INT_7XX_McBSP1TX	(11 + IH2_BASE)
-#define INT_7XX_McBSP1RX	(12 + IH2_BASE)
-#define INT_7XX_McBSP1RX_OF	(13 + IH2_BASE)
-#define INT_7XX_UART_MODEM_IRDA_2 (14 + IH2_BASE)
-#define INT_7XX_UART_MODEM_1	(15 + IH2_BASE)
-#define INT_7XX_MCSI		(16 + IH2_BASE)
-#define INT_7XX_uWireTX		(17 + IH2_BASE)
-#define INT_7XX_uWireRX		(18 + IH2_BASE)
-#define INT_7XX_SMC_CD		(19 + IH2_BASE)
-#define INT_7XX_SMC_IREQ	(20 + IH2_BASE)
-#define INT_7XX_HDQ_1WIRE	(21 + IH2_BASE)
-#define INT_7XX_TIMER32K	(22 + IH2_BASE)
-#define INT_7XX_MMC_SDIO	(23 + IH2_BASE)
-#define INT_7XX_UPLD		(24 + IH2_BASE)
-#define INT_7XX_USB_HHC_1	(27 + IH2_BASE)
-#define INT_7XX_USB_HHC_2	(28 + IH2_BASE)
-#define INT_7XX_USB_GENI	(29 + IH2_BASE)
-#define INT_7XX_USB_OTG		(30 + IH2_BASE)
-#define INT_7XX_CAMERA_IF	(31 + IH2_BASE)
-#define INT_7XX_RNG		(32 + IH2_BASE)
-#define INT_7XX_DUAL_MODE_TIMER (33 + IH2_BASE)
-#define INT_7XX_DBB_RF_EN	(34 + IH2_BASE)
-#define INT_7XX_MPUIO_KEYPAD	(35 + IH2_BASE)
-#define INT_7XX_SHA1_MD5	(36 + IH2_BASE)
-#define INT_7XX_SPI_100K_2	(37 + IH2_BASE)
-#define INT_7XX_RNG_IDLE	(38 + IH2_BASE)
-#define INT_7XX_MPUIO		(39 + IH2_BASE)
-#define INT_7XX_LLPC_LCD_CTRL_CAN_BE_OFF	(40 + IH2_BASE)
-#define INT_7XX_LLPC_OE_FALLING (41 + IH2_BASE)
-#define INT_7XX_LLPC_OE_RISING	(42 + IH2_BASE)
-#define INT_7XX_LLPC_VSYNC	(43 + IH2_BASE)
-#define INT_7XX_WAKE_UP_REQ	(46 + IH2_BASE)
-#define INT_7XX_DMA_CH6		(53 + IH2_BASE)
-#define INT_7XX_DMA_CH7		(54 + IH2_BASE)
-#define INT_7XX_DMA_CH8		(55 + IH2_BASE)
-#define INT_7XX_DMA_CH9		(56 + IH2_BASE)
-#define INT_7XX_DMA_CH10	(57 + IH2_BASE)
-#define INT_7XX_DMA_CH11	(58 + IH2_BASE)
-#define INT_7XX_DMA_CH12	(59 + IH2_BASE)
-#define INT_7XX_DMA_CH13	(60 + IH2_BASE)
-#define INT_7XX_DMA_CH14	(61 + IH2_BASE)
-#define INT_7XX_DMA_CH15	(62 + IH2_BASE)
-#define INT_7XX_NAND		(63 + IH2_BASE)
-
-#define INT_24XX_SYS_NIRQ	7
-#define INT_24XX_SDMA_IRQ0	12
-#define INT_24XX_SDMA_IRQ1	13
-#define INT_24XX_SDMA_IRQ2	14
-#define INT_24XX_SDMA_IRQ3	15
-#define INT_24XX_CAM_IRQ	24
-#define INT_24XX_DSS_IRQ	25
-#define INT_24XX_MAIL_U0_MPU	26
-#define INT_24XX_DSP_UMA	27
-#define INT_24XX_DSP_MMU	28
-#define INT_24XX_GPIO_BANK1	29
-#define INT_24XX_GPIO_BANK2	30
-#define INT_24XX_GPIO_BANK3	31
-#define INT_24XX_GPIO_BANK4	32
-#define INT_24XX_GPIO_BANK5	33
-#define INT_24XX_MAIL_U3_MPU	34
-#define INT_24XX_GPTIMER1	37
-#define INT_24XX_GPTIMER2	38
-#define INT_24XX_GPTIMER3	39
-#define INT_24XX_GPTIMER4	40
-#define INT_24XX_GPTIMER5	41
-#define INT_24XX_GPTIMER6	42
-#define INT_24XX_GPTIMER7	43
-#define INT_24XX_GPTIMER8	44
-#define INT_24XX_GPTIMER9	45
-#define INT_24XX_GPTIMER10	46
-#define INT_24XX_GPTIMER11	47
-#define INT_24XX_GPTIMER12	48
-#define INT_24XX_SHA1MD5	51
-#define INT_24XX_MCBSP4_IRQ_TX	54
-#define INT_24XX_MCBSP4_IRQ_RX	55
-#define INT_24XX_I2C1_IRQ	56
-#define INT_24XX_I2C2_IRQ	57
-#define INT_24XX_HDQ_IRQ	58
-#define INT_24XX_MCBSP1_IRQ_TX	59
-#define INT_24XX_MCBSP1_IRQ_RX	60
-#define INT_24XX_MCBSP2_IRQ_TX	62
-#define INT_24XX_MCBSP2_IRQ_RX	63
-#define INT_24XX_SPI1_IRQ	65
-#define INT_24XX_SPI2_IRQ	66
-#define INT_24XX_UART1_IRQ	72
-#define INT_24XX_UART2_IRQ	73
-#define INT_24XX_UART3_IRQ	74
-#define INT_24XX_USB_IRQ_GEN	75
-#define INT_24XX_USB_IRQ_NISO	76
-#define INT_24XX_USB_IRQ_ISO	77
-#define INT_24XX_USB_IRQ_HGEN	78
-#define INT_24XX_USB_IRQ_HSOF	79
-#define INT_24XX_USB_IRQ_OTG	80
-#define INT_24XX_MCBSP5_IRQ_TX	81
-#define INT_24XX_MCBSP5_IRQ_RX	82
-#define INT_24XX_MMC_IRQ	83
-#define INT_24XX_MMC2_IRQ	86
-#define INT_24XX_MCBSP3_IRQ_TX	89
-#define INT_24XX_MCBSP3_IRQ_RX	90
-#define INT_24XX_SPI3_IRQ	91
-
-#define INT_243X_MCBSP2_IRQ	16
-#define INT_243X_MCBSP3_IRQ	17
-#define INT_243X_MCBSP4_IRQ	18
-#define INT_243X_MCBSP5_IRQ	19
-#define INT_243X_MCBSP1_IRQ	64
-#define INT_243X_HS_USB_MC	92
-#define INT_243X_HS_USB_DMA	93
-#define INT_243X_CARKIT_IRQ	94
-
-#define INT_34XX_BENCH_MPU_EMUL	3
-#define INT_34XX_ST_MCBSP2_IRQ	4
-#define INT_34XX_ST_MCBSP3_IRQ	5
-#define INT_34XX_SSM_ABORT_IRQ	6
-#define INT_34XX_SYS_NIRQ	7
-#define INT_34XX_D2D_FW_IRQ	8
-#define INT_34XX_L3_DBG_IRQ     9
-#define INT_34XX_L3_APP_IRQ     10
-#define INT_34XX_PRCM_MPU_IRQ	11
-#define INT_34XX_MCBSP1_IRQ	16
-#define INT_34XX_MCBSP2_IRQ	17
-#define INT_34XX_GPMC_IRQ	20
-#define INT_34XX_MCBSP3_IRQ	22
-#define INT_34XX_MCBSP4_IRQ	23
-#define INT_34XX_CAM_IRQ	24
-#define INT_34XX_MCBSP5_IRQ	27
-#define INT_34XX_GPIO_BANK1	29
-#define INT_34XX_GPIO_BANK2	30
-#define INT_34XX_GPIO_BANK3	31
-#define INT_34XX_GPIO_BANK4	32
-#define INT_34XX_GPIO_BANK5	33
-#define INT_34XX_GPIO_BANK6	34
-#define INT_34XX_USIM_IRQ	35
-#define INT_34XX_WDT3_IRQ	36
-#define INT_34XX_SPI4_IRQ	48
-#define INT_34XX_SHA1MD52_IRQ	49
-#define INT_34XX_FPKA_READY_IRQ	50
-#define INT_34XX_SHA1MD51_IRQ	51
-#define INT_34XX_RNG_IRQ	52
-#define INT_34XX_I2C3_IRQ	61
-#define INT_34XX_FPKA_ERROR_IRQ	64
-#define INT_34XX_PBIAS_IRQ	75
-#define INT_34XX_OHCI_IRQ	76
-#define INT_34XX_EHCI_IRQ	77
-#define INT_34XX_TLL_IRQ	78
-#define INT_34XX_PARTHASH_IRQ	79
-#define INT_34XX_MMC3_IRQ	94
-#define INT_34XX_GPT12_IRQ	95
-
-#define INT_36XX_UART4_IRQ	80
-
-#define INT_35XX_HECC0_IRQ		24
-#define INT_35XX_HECC1_IRQ		28
-#define INT_35XX_EMAC_C0_RXTHRESH_IRQ	67
-#define INT_35XX_EMAC_C0_RX_PULSE_IRQ	68
-#define INT_35XX_EMAC_C0_TX_PULSE_IRQ	69
-#define INT_35XX_EMAC_C0_MISC_PULSE_IRQ	70
-#define INT_35XX_USBOTG_IRQ		71
-#define INT_35XX_UART4_IRQ		84
-#define INT_35XX_CCDC_VD0_IRQ		88
-#define INT_35XX_CCDC_VD1_IRQ		92
-#define INT_35XX_CCDC_VD2_IRQ		93
-
-/* 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)
-#define IH_MPUIO_BASE		(OMAP_MAX_GPIO_LINES + IH_GPIO_BASE)
-#define OMAP_IRQ_END		(IH_MPUIO_BASE + 16)
-
-/* External FPGA handles interrupts on Innovator boards */
-#define	OMAP_FPGA_IRQ_BASE	(OMAP_IRQ_END)
-#ifdef	CONFIG_MACH_OMAP_INNOVATOR
-#define OMAP_FPGA_NR_IRQS	24
-#else
-#define OMAP_FPGA_NR_IRQS	0
-#endif
-#define OMAP_FPGA_IRQ_END	(OMAP_FPGA_IRQ_BASE + OMAP_FPGA_NR_IRQS)
-
-/* External TWL4030 can handle interrupts on 2430 and 34xx boards */
-#define	TWL4030_IRQ_BASE	(OMAP_FPGA_IRQ_END)
-#ifdef	CONFIG_TWL4030_CORE
-#define	TWL4030_BASE_NR_IRQS	8
-#define	TWL4030_PWR_NR_IRQS	8
-#else
-#define	TWL4030_BASE_NR_IRQS	0
-#define	TWL4030_PWR_NR_IRQS	0
-#endif
-#define TWL4030_IRQ_END		(TWL4030_IRQ_BASE + TWL4030_BASE_NR_IRQS)
-#define TWL4030_PWR_IRQ_BASE	TWL4030_IRQ_END
-#define	TWL4030_PWR_IRQ_END	(TWL4030_PWR_IRQ_BASE + TWL4030_PWR_NR_IRQS)
-
-/* External TWL4030 gpio interrupts are optional */
-#define TWL4030_GPIO_IRQ_BASE	TWL4030_PWR_IRQ_END
-#ifdef	CONFIG_GPIO_TWL4030
-#define TWL4030_GPIO_NR_IRQS	18
-#else
-#define	TWL4030_GPIO_NR_IRQS	0
-#endif
-#define TWL4030_GPIO_IRQ_END	(TWL4030_GPIO_IRQ_BASE + TWL4030_GPIO_NR_IRQS)
-
-#define	TWL6030_IRQ_BASE	(OMAP_FPGA_IRQ_END)
-#ifdef CONFIG_TWL4030_CORE
-#define	TWL6030_BASE_NR_IRQS	20
-#else
-#define	TWL6030_BASE_NR_IRQS	0
-#endif
-#define TWL6030_IRQ_END		(TWL6030_IRQ_BASE + TWL6030_BASE_NR_IRQS)
-
-#define TWL6040_CODEC_IRQ_BASE	TWL6030_IRQ_END
-#ifdef CONFIG_TWL6040_CODEC
-#define TWL6040_CODEC_NR_IRQS	6
-#else
-#define TWL6040_CODEC_NR_IRQS	0
-#endif
-#define TWL6040_CODEC_IRQ_END	(TWL6040_CODEC_IRQ_BASE + TWL6040_CODEC_NR_IRQS)
-
-/* Total number of interrupts depends on the enabled blocks above */
-#if (TWL4030_GPIO_IRQ_END > TWL6040_CODEC_IRQ_END)
-#define TWL_IRQ_END 		TWL4030_GPIO_IRQ_END
-#else
-#define TWL_IRQ_END		TWL6040_CODEC_IRQ_END
-#endif
-
-/* GPMC related */
-#define OMAP_GPMC_IRQ_BASE	(TWL_IRQ_END)
-#define OMAP_GPMC_NR_IRQS	8
-#define OMAP_GPMC_IRQ_END	(OMAP_GPMC_IRQ_BASE + OMAP_GPMC_NR_IRQS)
-
-/* PRCM IRQ handler */
-#ifdef CONFIG_ARCH_OMAP2PLUS
-#define OMAP_PRCM_IRQ_BASE	(OMAP_GPMC_IRQ_END)
-#define OMAP_PRCM_NR_IRQS	64
-#define OMAP_PRCM_IRQ_END	(OMAP_PRCM_IRQ_BASE + OMAP_PRCM_NR_IRQS)
-#else
-#define OMAP_PRCM_IRQ_END	OMAP_GPMC_IRQ_END
-#endif
-
-#define NR_IRQS			OMAP_PRCM_IRQ_END
-
-#define OMAP_IRQ_BIT(irq)	(1 << ((irq) % 32))
-
-#define INTCPS_NR_MIR_REGS	3
-#define INTCPS_NR_IRQS		96
-
-#include <mach/hardware.h>
-
-#ifdef CONFIG_FIQ
-#define FIQ_START		1024
-#endif
-
-#endif
diff --git a/arch/arm/plat-omap/include/plat/keypad.h b/arch/arm/plat-omap/include/plat/keypad.h
deleted file mode 100644
index a6b21ed..0000000
--- a/arch/arm/plat-omap/include/plat/keypad.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- *  arch/arm/plat-omap/include/mach/keypad.h
- *
- *  Copyright (C) 2006 Komal Shah <komal_shah802003@yahoo.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 ASMARM_ARCH_KEYPAD_H
-#define ASMARM_ARCH_KEYPAD_H
-
-#ifndef CONFIG_ARCH_OMAP1
-#warning Please update the board to use matrix-keypad driver
-#define omap_readw(reg)		0
-#define omap_writew(val, reg)	do {} while (0)
-#endif
-#include <linux/input/matrix_keypad.h>
-
-struct omap_kp_platform_data {
-	int rows;
-	int cols;
-	const struct matrix_keymap_data *keymap_data;
-	bool rep;
-	unsigned long delay;
-	bool dbounce;
-	/* specific to OMAP242x*/
-	unsigned int *row_gpios;
-	unsigned int *col_gpios;
-};
-
-/* Group (0..3) -- when multiple keys are pressed, only the
- * keys pressed in the same group are considered as pressed. This is
- * in order to workaround certain crappy HW designs that produce ghost
- * keypresses. Two free bits, not used by neither row/col nor keynum,
- * must be available for use as group bits. The below GROUP_SHIFT
- * macro definition is based on some prior knowledge of the
- * matrix_keypad defined KEY() macro internals.
- */
-#define GROUP_SHIFT	14
-#define GROUP_0		(0 << GROUP_SHIFT)
-#define GROUP_1		(1 << GROUP_SHIFT)
-#define GROUP_2		(2 << GROUP_SHIFT)
-#define GROUP_3		(3 << GROUP_SHIFT)
-#define GROUP_MASK	GROUP_3
-#if KEY_MAX & GROUP_MASK
-#error Group bits in conflict with keynum bits
-#endif
-
-
-#endif
-
diff --git a/arch/arm/plat-omap/include/plat/l3_2xxx.h b/arch/arm/plat-omap/include/plat/l3_2xxx.h
deleted file mode 100644
index b8b5641..0000000
--- a/arch/arm/plat-omap/include/plat/l3_2xxx.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * arch/arm/plat-omap/include/plat/l3_2xxx.h - L3 firewall definitions
- *
- * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
- *	Sumit Semwal
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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 __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_L3_2XXX_H
-#define __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_L3_2XXX_H
-
-/* L3 CONNIDs */
-/* Display Sub system (DSS) */
-#define OMAP2_L3_CORE_FW_CONNID_DSS			8
-
-#endif
diff --git a/arch/arm/plat-omap/include/plat/l3_3xxx.h b/arch/arm/plat-omap/include/plat/l3_3xxx.h
deleted file mode 100644
index cde1938..0000000
--- a/arch/arm/plat-omap/include/plat/l3_3xxx.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * arch/arm/plat-omap/include/plat/l3_3xxx.h - L3 firewall definitions
- *
- * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
- *	Sumit Semwal
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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 __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_L3_3XXX_H
-#define __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_L3_3XXX_H
-
-/* L3 Initiator IDs */
-/* Display Sub system (DSS) */
-#define OMAP3_L3_CORE_FW_INIT_ID_DSS			29
-
-#endif
diff --git a/arch/arm/plat-omap/include/plat/l4_2xxx.h b/arch/arm/plat-omap/include/plat/l4_2xxx.h
deleted file mode 100644
index 3f39cf8..0000000
--- a/arch/arm/plat-omap/include/plat/l4_2xxx.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * arch/arm/plat-omap/include/plat/l4_2xxx.h - L4 firewall definitions
- *
- * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
- *	Sumit Semwal
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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 __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_L4_2XXX_H
-#define __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_L4_2XXX_H
-
-/* L4 CORE */
-/* Display Sub system (DSS) */
-#define OMAP2420_L4_CORE_FW_DSS_CORE_REGION			28
-#define OMAP2420_L4_CORE_FW_DSS_DISPC_REGION			29
-#define OMAP2420_L4_CORE_FW_DSS_RFBI_REGION			30
-#define OMAP2420_L4_CORE_FW_DSS_VENC_REGION			31
-#define OMAP2420_L4_CORE_FW_DSS_TA_REGION			32
-
-#endif
diff --git a/arch/arm/plat-omap/include/plat/l4_3xxx.h b/arch/arm/plat-omap/include/plat/l4_3xxx.h
deleted file mode 100644
index 881a858..0000000
--- a/arch/arm/plat-omap/include/plat/l4_3xxx.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * arch/arm/plat-omap/include/mach/l4_3xxx.h - L4 firewall definitions
- *
- * Copyright (C) 2009 Nokia Corporation
- * Paul Walmsley
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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 __ARCH_ARM_PLAT_OMAP_INCLUDE_MACH_L4_3XXX_H
-#define __ARCH_ARM_PLAT_OMAP_INCLUDE_MACH_L4_3XXX_H
-
-/* L4 CORE */
-#define OMAP3_L4_CORE_FW_I2C1_REGION				21
-#define OMAP3_L4_CORE_FW_I2C1_TA_REGION				22
-#define OMAP3_L4_CORE_FW_I2C2_REGION				23
-#define OMAP3_L4_CORE_FW_I2C2_TA_REGION				24
-#define OMAP3_L4_CORE_FW_I2C3_REGION				73
-#define OMAP3_L4_CORE_FW_I2C3_TA_REGION				74
-
-/* Display Sub system (DSS) */
-#define OMAP3_L4_CORE_FW_DSS_PROT_GROUP				2
-
-#define OMAP3_L4_CORE_FW_DSS_DSI_REGION				104
-#define OMAP3ES1_L4_CORE_FW_DSS_CORE_REGION			3
-#define OMAP3_L4_CORE_FW_DSS_CORE_REGION			4
-#define OMAP3_L4_CORE_FW_DSS_DISPC_REGION			4
-#define OMAP3_L4_CORE_FW_DSS_RFBI_REGION			5
-#define OMAP3_L4_CORE_FW_DSS_VENC_REGION			6
-#define OMAP3_L4_CORE_FW_DSS_TA_REGION				7
-#endif
diff --git a/arch/arm/plat-omap/include/plat/lcd_mipid.h b/arch/arm/plat-omap/include/plat/lcd_mipid.h
deleted file mode 100644
index 8e52c65..0000000
--- a/arch/arm/plat-omap/include/plat/lcd_mipid.h
+++ /dev/null
@@ -1,29 +0,0 @@
-#ifndef __LCD_MIPID_H
-#define __LCD_MIPID_H
-
-enum mipid_test_num {
-	MIPID_TEST_RGB_LINES,
-};
-
-enum mipid_test_result {
-	MIPID_TEST_SUCCESS,
-	MIPID_TEST_INVALID,
-	MIPID_TEST_FAILED,
-};
-
-#ifdef __KERNEL__
-
-struct mipid_platform_data {
-	int	nreset_gpio;
-	int	data_lines;
-
-	void	(*shutdown)(struct mipid_platform_data *pdata);
-	void	(*set_bklight_level)(struct mipid_platform_data *pdata,
-				     int level);
-	int	(*get_bklight_level)(struct mipid_platform_data *pdata);
-	int	(*get_bklight_max)(struct mipid_platform_data *pdata);
-};
-
-#endif
-
-#endif
diff --git a/arch/arm/plat-omap/include/plat/mcbsp.h b/arch/arm/plat-omap/include/plat/mcbsp.h
deleted file mode 100644
index 1881412..0000000
--- a/arch/arm/plat-omap/include/plat/mcbsp.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * arch/arm/plat-omap/include/mach/mcbsp.h
- *
- * Defines for Multi-Channel Buffered Serial Port
- *
- * Copyright (C) 2002 RidgeRun, Inc.
- * Author: Steve Johnson
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-#ifndef __ASM_ARCH_OMAP_MCBSP_H
-#define __ASM_ARCH_OMAP_MCBSP_H
-
-#include <linux/spinlock.h>
-#include <linux/clk.h>
-
-#define MCBSP_CONFIG_TYPE2	0x2
-#define MCBSP_CONFIG_TYPE3	0x3
-#define MCBSP_CONFIG_TYPE4	0x4
-
-/* Platform specific configuration */
-struct omap_mcbsp_ops {
-	void (*request)(unsigned int);
-	void (*free)(unsigned int);
-};
-
-struct omap_mcbsp_platform_data {
-	struct omap_mcbsp_ops *ops;
-	u16 buffer_size;
-	u8 reg_size;
-	u8 reg_step;
-
-	/* McBSP platform and instance specific features */
-	bool has_wakeup; /* Wakeup capability */
-	bool has_ccr; /* Transceiver has configuration control registers */
-	int (*enable_st_clock)(unsigned int, bool);
-	int (*set_clk_src)(struct device *dev, struct clk *clk, const char *src);
-	int (*mux_signal)(struct device *dev, const char *signal, const char *src);
-};
-
-/**
- * omap_mcbsp_dev_attr - OMAP McBSP device attributes for omap_hwmod
- * @sidetone: name of the sidetone device
- */
-struct omap_mcbsp_dev_attr {
-	const char *sidetone;
-};
-
-#endif
diff --git a/arch/arm/plat-omap/include/plat/mcspi.h b/arch/arm/plat-omap/include/plat/mcspi.h
deleted file mode 100644
index a357eb2..0000000
--- a/arch/arm/plat-omap/include/plat/mcspi.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef _OMAP2_MCSPI_H
-#define _OMAP2_MCSPI_H
-
-#define OMAP2_MCSPI_REV 0
-#define OMAP3_MCSPI_REV 1
-#define OMAP4_MCSPI_REV 2
-
-#define OMAP4_MCSPI_REG_OFFSET 0x100
-
-struct omap2_mcspi_platform_config {
-	unsigned short	num_cs;
-	unsigned int regs_offset;
-};
-
-struct omap2_mcspi_dev_attr {
-	unsigned short num_chipselect;
-};
-
-struct omap2_mcspi_device_config {
-	unsigned turbo_mode:1;
-};
-
-#endif
diff --git a/arch/arm/plat-omap/include/plat/mmc.h b/arch/arm/plat-omap/include/plat/mmc.h
index eb3e4d5..8b4e4f2 100644
--- a/arch/arm/plat-omap/include/plat/mmc.h
+++ b/arch/arm/plat-omap/include/plat/mmc.h
@@ -15,7 +15,6 @@
 #include <linux/device.h>
 #include <linux/mmc/host.h>
 
-#include <plat/board.h>
 #include <plat/omap_hwmod.h>
 
 #define OMAP15XX_NR_MMC		1
diff --git a/arch/arm/plat-omap/include/plat/mux.h b/arch/arm/plat-omap/include/plat/mux.h
deleted file mode 100644
index 3239489..0000000
--- a/arch/arm/plat-omap/include/plat/mux.h
+++ /dev/null
@@ -1,454 +0,0 @@
-/*
- * arch/arm/plat-omap/include/mach/mux.h
- *
- * Table of the Omap register configurations for the FUNC_MUX and
- * PULL_DWN combinations.
- *
- * Copyright (C) 2004 - 2008 Texas Instruments Inc.
- * Copyright (C) 2003 - 2008 Nokia Corporation
- *
- * Written by Tony Lindgren
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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
- *
- * NOTE: Please use the following naming style for new pin entries.
- *	 For example, W8_1610_MMC2_DAT0, where:
- *	 - W8	     = ball
- *	 - 1610	     = 1510 or 1610, none if common for both 1510 and 1610
- *	 - MMC2_DAT0 = function
- */
-
-#ifndef __ASM_ARCH_MUX_H
-#define __ASM_ARCH_MUX_H
-
-#define PU_PD_SEL_NA		0	/* No pu_pd reg available */
-#define PULL_DWN_CTRL_NA	0	/* No pull-down control needed */
-
-#ifdef	CONFIG_OMAP_MUX_DEBUG
-#define MUX_REG(reg, mode_offset, mode) .mux_reg_name = "FUNC_MUX_CTRL_"#reg, \
-					.mux_reg = FUNC_MUX_CTRL_##reg, \
-					.mask_offset = mode_offset, \
-					.mask = mode,
-
-#define PULL_REG(reg, bit, status)	.pull_name = "PULL_DWN_CTRL_"#reg, \
-					.pull_reg = PULL_DWN_CTRL_##reg, \
-					.pull_bit = bit, \
-					.pull_val = status,
-
-#define PU_PD_REG(reg, status)		.pu_pd_name = "PU_PD_SEL_"#reg, \
-					.pu_pd_reg = PU_PD_SEL_##reg, \
-					.pu_pd_val = status,
-
-#define MUX_REG_7XX(reg, mode_offset, mode) .mux_reg_name = "OMAP7XX_IO_CONF_"#reg, \
-					.mux_reg = OMAP7XX_IO_CONF_##reg, \
-					.mask_offset = mode_offset, \
-					.mask = mode,
-
-#define PULL_REG_7XX(reg, bit, status)	.pull_name = "OMAP7XX_IO_CONF_"#reg, \
-					.pull_reg = OMAP7XX_IO_CONF_##reg, \
-					.pull_bit = bit, \
-					.pull_val = status,
-
-#else
-
-#define MUX_REG(reg, mode_offset, mode) .mux_reg = FUNC_MUX_CTRL_##reg, \
-					.mask_offset = mode_offset, \
-					.mask = mode,
-
-#define PULL_REG(reg, bit, status)	.pull_reg = PULL_DWN_CTRL_##reg, \
-					.pull_bit = bit, \
-					.pull_val = status,
-
-#define PU_PD_REG(reg, status)		.pu_pd_reg = PU_PD_SEL_##reg, \
-					.pu_pd_val = status,
-
-#define MUX_REG_7XX(reg, mode_offset, mode) \
-					.mux_reg = OMAP7XX_IO_CONF_##reg, \
-					.mask_offset = mode_offset, \
-					.mask = mode,
-
-#define PULL_REG_7XX(reg, bit, status)	.pull_reg = OMAP7XX_IO_CONF_##reg, \
-					.pull_bit = bit, \
-					.pull_val = status,
-
-#endif /* CONFIG_OMAP_MUX_DEBUG */
-
-#define MUX_CFG(desc, mux_reg, mode_offset, mode,	\
-		pull_reg, pull_bit, pull_status,	\
-		pu_pd_reg, pu_pd_status, debug_status)	\
-{							\
-	.name =	 desc,					\
-	.debug = debug_status,				\
-	MUX_REG(mux_reg, mode_offset, mode)		\
-	PULL_REG(pull_reg, pull_bit, pull_status)	\
-	PU_PD_REG(pu_pd_reg, pu_pd_status)		\
-},
-
-
-/*
- * OMAP730/850 has a slightly different config for the pin mux.
- * - config regs are the OMAP7XX_IO_CONF_x regs (see omap7xx.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
- *   as mux config
- */
-#define MUX_CFG_7XX(desc, mux_reg, mode_offset, mode,	\
-		   pull_bit, pull_status, debug_status)\
-{							\
-	.name =	 desc,					\
-	.debug = debug_status,				\
-	MUX_REG_7XX(mux_reg, mode_offset, mode)		\
-	PULL_REG_7XX(mux_reg, pull_bit, pull_status)	\
-	PU_PD_REG(NA, 0)		\
-},
-
-struct pin_config {
-	char 			*name;
-	const unsigned int 	mux_reg;
-	unsigned char		debug;
-
-	const unsigned char mask_offset;
-	const unsigned char mask;
-
-	const char *pull_name;
-	const unsigned int pull_reg;
-	const unsigned char pull_val;
-	const unsigned char pull_bit;
-
-	const char *pu_pd_name;
-	const unsigned int pu_pd_reg;
-	const unsigned char pu_pd_val;
-
-#if	defined(CONFIG_OMAP_MUX_DEBUG) || defined(CONFIG_OMAP_MUX_WARNINGS)
-	const char *mux_reg_name;
-#endif
-
-};
-
-enum omap7xx_index {
-	/* OMAP 730 keyboard */
-	E2_7XX_KBR0,
-	J7_7XX_KBR1,
-	E1_7XX_KBR2,
-	F3_7XX_KBR3,
-	D2_7XX_KBR4,
-	C2_7XX_KBC0,
-	D3_7XX_KBC1,
-	E4_7XX_KBC2,
-	F4_7XX_KBC3,
-	E3_7XX_KBC4,
-
-	/* USB */
-	AA17_7XX_USB_DM,
-	W16_7XX_USB_PU_EN,
-	W17_7XX_USB_VBUSI,
-	W18_7XX_USB_DMCK_OUT,
-	W19_7XX_USB_DCRST,
-
-	/* MMC */
-	MMC_7XX_CMD,
-	MMC_7XX_CLK,
-	MMC_7XX_DAT0,
-
-	/* I2C */
-	I2C_7XX_SCL,
-	I2C_7XX_SDA,
-
-	/* SPI */
-	SPI_7XX_1,
-	SPI_7XX_2,
-	SPI_7XX_3,
-	SPI_7XX_4,
-	SPI_7XX_5,
-	SPI_7XX_6,
-
-	/* UART */
-	UART_7XX_1,
-	UART_7XX_2,
-};
-
-enum omap1xxx_index {
-	/* UART1 (BT_UART_GATING)*/
-	UART1_TX = 0,
-	UART1_RTS,
-
-	/* UART2 (COM_UART_GATING)*/
-	UART2_TX,
-	UART2_RX,
-	UART2_CTS,
-	UART2_RTS,
-
-	/* UART3 (GIGA_UART_GATING) */
-	UART3_TX,
-	UART3_RX,
-	UART3_CTS,
-	UART3_RTS,
-	UART3_CLKREQ,
-	UART3_BCLK,	/* 12MHz clock out */
-	Y15_1610_UART3_RTS,
-
-	/* PWT & PWL */
-	PWT,
-	PWL,
-
-	/* USB master generic */
-	R18_USB_VBUS,
-	R18_1510_USB_GPIO0,
-	W4_USB_PUEN,
-	W4_USB_CLKO,
-	W4_USB_HIGHZ,
-	W4_GPIO58,
-
-	/* USB1 master */
-	USB1_SUSP,
-	USB1_SEO,
-	W13_1610_USB1_SE0,
-	USB1_TXEN,
-	USB1_TXD,
-	USB1_VP,
-	USB1_VM,
-	USB1_RCV,
-	USB1_SPEED,
-	R13_1610_USB1_SPEED,
-	R13_1710_USB1_SE0,
-
-	/* USB2 master */
-	USB2_SUSP,
-	USB2_VP,
-	USB2_TXEN,
-	USB2_VM,
-	USB2_RCV,
-	USB2_SEO,
-	USB2_TXD,
-
-	/* OMAP-1510 GPIO */
-	R18_1510_GPIO0,
-	R19_1510_GPIO1,
-	M14_1510_GPIO2,
-
-	/* OMAP1610 GPIO */
-	P18_1610_GPIO3,
-	Y15_1610_GPIO17,
-
-	/* OMAP-1710 GPIO */
-	R18_1710_GPIO0,
-	V2_1710_GPIO10,
-	N21_1710_GPIO14,
-	W15_1710_GPIO40,
-
-	/* MPUIO */
-	MPUIO2,
-	N15_1610_MPUIO2,
-	MPUIO4,
-	MPUIO5,
-	T20_1610_MPUIO5,
-	W11_1610_MPUIO6,
-	V10_1610_MPUIO7,
-	W11_1610_MPUIO9,
-	V10_1610_MPUIO10,
-	W10_1610_MPUIO11,
-	E20_1610_MPUIO13,
-	U20_1610_MPUIO14,
-	E19_1610_MPUIO15,
-
-	/* MCBSP2 */
-	MCBSP2_CLKR,
-	MCBSP2_CLKX,
-	MCBSP2_DR,
-	MCBSP2_DX,
-	MCBSP2_FSR,
-	MCBSP2_FSX,
-
-	/* MCBSP3 */
-	MCBSP3_CLKX,
-
-	/* Misc ballouts */
-	BALLOUT_V8_ARMIO3,
-	N20_HDQ,
-
-	/* OMAP-1610 MMC2 */
-	W8_1610_MMC2_DAT0,
-	V8_1610_MMC2_DAT1,
-	W15_1610_MMC2_DAT2,
-	R10_1610_MMC2_DAT3,
-	Y10_1610_MMC2_CLK,
-	Y8_1610_MMC2_CMD,
-	V9_1610_MMC2_CMDDIR,
-	V5_1610_MMC2_DATDIR0,
-	W19_1610_MMC2_DATDIR1,
-	R18_1610_MMC2_CLKIN,
-
-	/* OMAP-1610 External Trace Interface */
-	M19_1610_ETM_PSTAT0,
-	L15_1610_ETM_PSTAT1,
-	L18_1610_ETM_PSTAT2,
-	L19_1610_ETM_D0,
-	J19_1610_ETM_D6,
-	J18_1610_ETM_D7,
-
-	/* OMAP16XX GPIO */
-	P20_1610_GPIO4,
-	V9_1610_GPIO7,
-	W8_1610_GPIO9,
-	N20_1610_GPIO11,
-	N19_1610_GPIO13,
-	P10_1610_GPIO22,
-	V5_1610_GPIO24,
-	AA20_1610_GPIO_41,
-	W19_1610_GPIO48,
-	M7_1610_GPIO62,
-	V14_16XX_GPIO37,
-	R9_16XX_GPIO18,
-	L14_16XX_GPIO49,
-
-	/* OMAP-1610 uWire */
-	V19_1610_UWIRE_SCLK,
-	U18_1610_UWIRE_SDI,
-	W21_1610_UWIRE_SDO,
-	N14_1610_UWIRE_CS0,
-	P15_1610_UWIRE_CS3,
-	N15_1610_UWIRE_CS1,
-
-	/* OMAP-1610 SPI */
-	U19_1610_SPIF_SCK,
-	U18_1610_SPIF_DIN,
-	P20_1610_SPIF_DIN,
-	W21_1610_SPIF_DOUT,
-	R18_1610_SPIF_DOUT,
-	N14_1610_SPIF_CS0,
-	N15_1610_SPIF_CS1,
-	T19_1610_SPIF_CS2,
-	P15_1610_SPIF_CS3,
-
-	/* OMAP-1610 Flash */
-	L3_1610_FLASH_CS2B_OE,
-	M8_1610_FLASH_CS2B_WE,
-
-	/* First MMC */
-	MMC_CMD,
-	MMC_DAT1,
-	MMC_DAT2,
-	MMC_DAT0,
-	MMC_CLK,
-	MMC_DAT3,
-
-	/* OMAP-1710 MMC CMDDIR and DATDIR0 */
-	M15_1710_MMC_CLKI,
-	P19_1710_MMC_CMDDIR,
-	P20_1710_MMC_DATDIR0,
-
-	/* OMAP-1610 USB0 alternate pin configuration */
-	W9_USB0_TXEN,
-	AA9_USB0_VP,
-	Y5_USB0_RCV,
-	R9_USB0_VM,
-	V6_USB0_TXD,
-	W5_USB0_SE0,
-	V9_USB0_SPEED,
-	V9_USB0_SUSP,
-
-	/* USB2 */
-	W9_USB2_TXEN,
-	AA9_USB2_VP,
-	Y5_USB2_RCV,
-	R9_USB2_VM,
-	V6_USB2_TXD,
-	W5_USB2_SE0,
-
-	/* 16XX UART */
-	R13_1610_UART1_TX,
-	V14_16XX_UART1_RX,
-	R14_1610_UART1_CTS,
-	AA15_1610_UART1_RTS,
-	R9_16XX_UART2_RX,
-	L14_16XX_UART3_RX,
-
-	/* I2C OMAP-1610 */
-	I2C_SCL,
-	I2C_SDA,
-
-	/* Keypad */
-	F18_1610_KBC0,
-	D20_1610_KBC1,
-	D19_1610_KBC2,
-	E18_1610_KBC3,
-	C21_1610_KBC4,
-	G18_1610_KBR0,
-	F19_1610_KBR1,
-	H14_1610_KBR2,
-	E20_1610_KBR3,
-	E19_1610_KBR4,
-	N19_1610_KBR5,
-
-	/* Power management */
-	T20_1610_LOW_PWR,
-
-	/* MCLK Settings */
-	V5_1710_MCLK_ON,
-	V5_1710_MCLK_OFF,
-	R10_1610_MCLK_ON,
-	R10_1610_MCLK_OFF,
-
-	/* CompactFlash controller */
-	P11_1610_CF_CD2,
-	R11_1610_CF_IOIS16,
-	V10_1610_CF_IREQ,
-	W10_1610_CF_RESET,
-	W11_1610_CF_CD1,
-
-	/* parallel camera */
-	J15_1610_CAM_LCLK,
-	J18_1610_CAM_D7,
-	J19_1610_CAM_D6,
-	J14_1610_CAM_D5,
-	K18_1610_CAM_D4,
-	K19_1610_CAM_D3,
-	K15_1610_CAM_D2,
-	K14_1610_CAM_D1,
-	L19_1610_CAM_D0,
-	L18_1610_CAM_VS,
-	L15_1610_CAM_HS,
-	M19_1610_CAM_RSTZ,
-	Y15_1610_CAM_OUTCLK,
-
-	/* serial camera */
-	H19_1610_CAM_EXCLK,
-	Y12_1610_CCP_CLKP,
-	W13_1610_CCP_CLKM,
-	W14_1610_CCP_DATAP,
-	Y14_1610_CCP_DATAM,
-
-};
-
-struct omap_mux_cfg {
-	struct pin_config	*pins;
-	unsigned long		size;
-	int			(*cfg_reg)(const struct pin_config *cfg);
-};
-
-#ifdef	CONFIG_OMAP_MUX
-/* setup pin muxing in Linux */
-extern int omap1_mux_init(void);
-extern int omap_mux_register(struct omap_mux_cfg *);
-extern int omap_cfg_reg(unsigned long reg_cfg);
-#else
-/* boot loader does it all (no warnings from CONFIG_OMAP_MUX_WARNINGS) */
-static inline int omap1_mux_init(void) { return 0; }
-static inline int omap_cfg_reg(unsigned long reg_cfg) { return 0; }
-#endif
-
-extern int omap2_mux_init(void);
-
-#endif
diff --git a/arch/arm/plat-omap/include/plat/nand.h b/arch/arm/plat-omap/include/plat/nand.h
deleted file mode 100644
index 67fc506..0000000
--- a/arch/arm/plat-omap/include/plat/nand.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * arch/arm/plat-omap/include/mach/nand.h
- *
- * Copyright (C) 2006 Micron Technology 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 <plat/gpmc.h>
-#include <linux/mtd/partitions.h>
-
-enum nand_io {
-	NAND_OMAP_PREFETCH_POLLED = 0,	/* prefetch polled mode, default */
-	NAND_OMAP_POLLED,		/* polled mode, without prefetch */
-	NAND_OMAP_PREFETCH_DMA,		/* prefetch enabled sDMA mode */
-	NAND_OMAP_PREFETCH_IRQ		/* prefetch enabled irq mode */
-};
-
-struct omap_nand_platform_data {
-	int			cs;
-	struct mtd_partition	*parts;
-	struct gpmc_timings	*gpmc_t;
-	int			nr_parts;
-	bool			dev_ready;
-	int			gpmc_irq;
-	enum nand_io		xfer_type;
-	unsigned long		phys_base;
-	int			devsize;
-	enum omap_ecc           ecc_opt;
-};
-
-/* minimum size for IO mapping */
-#define	NAND_IO_SIZE	4
-
-#if defined(CONFIG_MTD_NAND_OMAP2) || defined(CONFIG_MTD_NAND_OMAP2_MODULE)
-extern int gpmc_nand_init(struct omap_nand_platform_data *d);
-#else
-static inline int gpmc_nand_init(struct omap_nand_platform_data *d)
-{
-	return 0;
-}
-#endif
diff --git a/arch/arm/plat-omap/include/plat/omap-serial.h b/arch/arm/plat-omap/include/plat/omap-serial.h
index 1a52725..b2eac60 100644
--- a/arch/arm/plat-omap/include/plat/omap-serial.h
+++ b/arch/arm/plat-omap/include/plat/omap-serial.h
@@ -18,11 +18,9 @@
 #define __OMAP_SERIAL_H__
 
 #include <linux/serial_core.h>
-#include <linux/platform_device.h>
+#include <linux/device.h>
 #include <linux/pm_qos.h>
 
-#include <plat/mux.h>
-
 #define DRIVER_NAME	"omap_uart"
 
 /*
@@ -42,10 +40,10 @@
 #define OMAP_UART_WER_MOD_WKUP	0X7F
 
 /* Enable XON/XOFF flow control on output */
-#define OMAP_UART_SW_TX		0x04
+#define OMAP_UART_SW_TX		0x8
 
 /* Enable XON/XOFF flow control on input */
-#define OMAP_UART_SW_RX		0x04
+#define OMAP_UART_SW_RX		0x2
 
 #define OMAP_UART_SYSC_RESET	0X07
 #define OMAP_UART_TCR_TRIG	0X0F
@@ -69,11 +67,14 @@ struct omap_uart_port_info {
 	unsigned int		dma_rx_timeout;
 	unsigned int		autosuspend_timeout;
 	unsigned int		dma_rx_poll_rate;
+	int			DTR_gpio;
+	int			DTR_inverted;
+	int			DTR_present;
 
 	int (*get_context_loss_count)(struct device *);
-	void (*set_forceidle)(struct platform_device *);
-	void (*set_noidle)(struct platform_device *);
-	void (*enable_wakeup)(struct platform_device *, bool);
+	void (*set_forceidle)(struct device *);
+	void (*set_noidle)(struct device *);
+	void (*enable_wakeup)(struct device *, bool);
 };
 
 struct uart_omap_dma {
@@ -102,39 +103,4 @@ struct uart_omap_dma {
 	unsigned int		rx_timeout;
 };
 
-struct uart_omap_port {
-	struct uart_port	port;
-	struct uart_omap_dma	uart_dma;
-	struct platform_device	*pdev;
-
-	unsigned char		ier;
-	unsigned char		lcr;
-	unsigned char		mcr;
-	unsigned char		fcr;
-	unsigned char		efr;
-	unsigned char		dll;
-	unsigned char		dlh;
-	unsigned char		mdr1;
-	unsigned char		scr;
-
-	int			use_dma;
-	/*
-	 * Some bits in registers are cleared on a read, so they must
-	 * be saved whenever the register is read but the bits will not
-	 * be immediately processed.
-	 */
-	unsigned int		lsr_break_flag;
-	unsigned char		msr_saved_flags;
-	char			name[20];
-	unsigned long		port_activity;
-	u32			context_loss_cnt;
-	u32			errata;
-	u8			wakeups_enabled;
-
-	struct pm_qos_request	pm_qos_request;
-	u32			latency;
-	u32			calc_latency;
-	struct work_struct	qos_work;
-};
-
 #endif /* __OMAP_SERIAL_H__ */
diff --git a/arch/arm/plat-omap/include/plat/omap1510.h b/arch/arm/plat-omap/include/plat/omap1510.h
deleted file mode 100644
index d240046..0000000
--- a/arch/arm/plat-omap/include/plat/omap1510.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/* arch/arm/plat-omap/include/mach/omap1510.h
- *
- * Hardware definitions for TI OMAP1510 processor.
- *
- * Cleanup for Linux-2.6 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_OMAP15XX_H
-#define __ASM_ARCH_OMAP15XX_H
-
-/*
- * ----------------------------------------------------------------------------
- * Base addresses
- * ----------------------------------------------------------------------------
- */
-
-/* Syntax: XX_BASE = Virtual base address, XX_START = Physical base address */
-
-#define OMAP1510_DSP_BASE	0xE0000000
-#define OMAP1510_DSP_SIZE	0x28000
-#define OMAP1510_DSP_START	0xE0000000
-
-#define OMAP1510_DSPREG_BASE	0xE1000000
-#define OMAP1510_DSPREG_SIZE	SZ_128K
-#define OMAP1510_DSPREG_START	0xE1000000
-
-#define OMAP1510_DSP_MMU_BASE	(0xfffed200)
-
-#endif /*  __ASM_ARCH_OMAP15XX_H */
-
diff --git a/arch/arm/plat-omap/include/plat/omap16xx.h b/arch/arm/plat-omap/include/plat/omap16xx.h
deleted file mode 100644
index e69e1d8..0000000
--- a/arch/arm/plat-omap/include/plat/omap16xx.h
+++ /dev/null
@@ -1,202 +0,0 @@
-/* arch/arm/plat-omap/include/mach/omap16xx.h
- *
- * Hardware definitions for TI OMAP1610/5912/1710 processors.
- *
- * Cleanup for Linux-2.6 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_OMAP16XX_H
-#define __ASM_ARCH_OMAP16XX_H
-
-/*
- * ----------------------------------------------------------------------------
- * Base addresses
- * ----------------------------------------------------------------------------
- */
-
-/* Syntax: XX_BASE = Virtual base address, XX_START = Physical base address */
-
-#define OMAP16XX_DSP_BASE	0xE0000000
-#define OMAP16XX_DSP_SIZE	0x28000
-#define OMAP16XX_DSP_START	0xE0000000
-
-#define OMAP16XX_DSPREG_BASE	0xE1000000
-#define OMAP16XX_DSPREG_SIZE	SZ_128K
-#define OMAP16XX_DSPREG_START	0xE1000000
-
-#define OMAP16XX_SEC_BASE	0xFFFE4000
-#define OMAP16XX_SEC_DES	(OMAP16XX_SEC_BASE + 0x0000)
-#define OMAP16XX_SEC_SHA1MD5	(OMAP16XX_SEC_BASE + 0x0800)
-#define OMAP16XX_SEC_RNG	(OMAP16XX_SEC_BASE + 0x1000)
-
-/*
- * ---------------------------------------------------------------------------
- * Interrupts
- * ---------------------------------------------------------------------------
- */
-#define OMAP_IH2_0_BASE		(0xfffe0000)
-#define OMAP_IH2_1_BASE		(0xfffe0100)
-#define OMAP_IH2_2_BASE		(0xfffe0200)
-#define OMAP_IH2_3_BASE		(0xfffe0300)
-
-#define OMAP_IH2_0_ITR		(OMAP_IH2_0_BASE + 0x00)
-#define OMAP_IH2_0_MIR		(OMAP_IH2_0_BASE + 0x04)
-#define OMAP_IH2_0_SIR_IRQ	(OMAP_IH2_0_BASE + 0x10)
-#define OMAP_IH2_0_SIR_FIQ	(OMAP_IH2_0_BASE + 0x14)
-#define OMAP_IH2_0_CONTROL	(OMAP_IH2_0_BASE + 0x18)
-#define OMAP_IH2_0_ILR0		(OMAP_IH2_0_BASE + 0x1c)
-#define OMAP_IH2_0_ISR		(OMAP_IH2_0_BASE + 0x9c)
-
-#define OMAP_IH2_1_ITR		(OMAP_IH2_1_BASE + 0x00)
-#define OMAP_IH2_1_MIR		(OMAP_IH2_1_BASE + 0x04)
-#define OMAP_IH2_1_SIR_IRQ	(OMAP_IH2_1_BASE + 0x10)
-#define OMAP_IH2_1_SIR_FIQ	(OMAP_IH2_1_BASE + 0x14)
-#define OMAP_IH2_1_CONTROL	(OMAP_IH2_1_BASE + 0x18)
-#define OMAP_IH2_1_ILR1		(OMAP_IH2_1_BASE + 0x1c)
-#define OMAP_IH2_1_ISR		(OMAP_IH2_1_BASE + 0x9c)
-
-#define OMAP_IH2_2_ITR		(OMAP_IH2_2_BASE + 0x00)
-#define OMAP_IH2_2_MIR		(OMAP_IH2_2_BASE + 0x04)
-#define OMAP_IH2_2_SIR_IRQ	(OMAP_IH2_2_BASE + 0x10)
-#define OMAP_IH2_2_SIR_FIQ	(OMAP_IH2_2_BASE + 0x14)
-#define OMAP_IH2_2_CONTROL	(OMAP_IH2_2_BASE + 0x18)
-#define OMAP_IH2_2_ILR2		(OMAP_IH2_2_BASE + 0x1c)
-#define OMAP_IH2_2_ISR		(OMAP_IH2_2_BASE + 0x9c)
-
-#define OMAP_IH2_3_ITR		(OMAP_IH2_3_BASE + 0x00)
-#define OMAP_IH2_3_MIR		(OMAP_IH2_3_BASE + 0x04)
-#define OMAP_IH2_3_SIR_IRQ	(OMAP_IH2_3_BASE + 0x10)
-#define OMAP_IH2_3_SIR_FIQ	(OMAP_IH2_3_BASE + 0x14)
-#define OMAP_IH2_3_CONTROL	(OMAP_IH2_3_BASE + 0x18)
-#define OMAP_IH2_3_ILR3		(OMAP_IH2_3_BASE + 0x1c)
-#define OMAP_IH2_3_ISR		(OMAP_IH2_3_BASE + 0x9c)
-
-/*
- * ----------------------------------------------------------------------------
- * Clocks
- * ----------------------------------------------------------------------------
- */
-#define OMAP16XX_ARM_IDLECT3	(CLKGEN_REG_BASE + 0x24)
-
-/*
- * ----------------------------------------------------------------------------
- * Pin configuration registers
- * ----------------------------------------------------------------------------
- */
-#define OMAP16XX_CONF_VOLTAGE_VDDSHV6	(1 << 8)
-#define OMAP16XX_CONF_VOLTAGE_VDDSHV7	(1 << 9)
-#define OMAP16XX_CONF_VOLTAGE_VDDSHV8	(1 << 10)
-#define OMAP16XX_CONF_VOLTAGE_VDDSHV9	(1 << 11)
-#define OMAP16XX_SUBLVDS_CONF_VALID	(1 << 13)
-
-/*
- * ----------------------------------------------------------------------------
- * System control registers
- * ----------------------------------------------------------------------------
- */
-#define OMAP1610_RESET_CONTROL  0xfffe1140
-
-/*
- * ---------------------------------------------------------------------------
- * TIPB bus interface
- * ---------------------------------------------------------------------------
- */
-#define TIPB_SWITCH_BASE		 (0xfffbc800)
-#define OMAP16XX_MMCSD2_SSW_MPU_CONF	(TIPB_SWITCH_BASE + 0x160)
-
-/* UART3 Registers Mapping through MPU bus */
-#define UART3_RHR               (OMAP1_UART3_BASE + 0)
-#define UART3_THR               (OMAP1_UART3_BASE + 0)
-#define UART3_DLL               (OMAP1_UART3_BASE + 0)
-#define UART3_IER               (OMAP1_UART3_BASE + 4)
-#define UART3_DLH               (OMAP1_UART3_BASE + 4)
-#define UART3_IIR               (OMAP1_UART3_BASE + 8)
-#define UART3_FCR               (OMAP1_UART3_BASE + 8)
-#define UART3_EFR               (OMAP1_UART3_BASE + 8)
-#define UART3_LCR               (OMAP1_UART3_BASE + 0x0C)
-#define UART3_MCR               (OMAP1_UART3_BASE + 0x10)
-#define UART3_XON1_ADDR1        (OMAP1_UART3_BASE + 0x10)
-#define UART3_XON2_ADDR2        (OMAP1_UART3_BASE + 0x14)
-#define UART3_LSR               (OMAP1_UART3_BASE + 0x14)
-#define UART3_TCR               (OMAP1_UART3_BASE + 0x18)
-#define UART3_MSR               (OMAP1_UART3_BASE + 0x18)
-#define UART3_XOFF1             (OMAP1_UART3_BASE + 0x18)
-#define UART3_XOFF2             (OMAP1_UART3_BASE + 0x1C)
-#define UART3_SPR               (OMAP1_UART3_BASE + 0x1C)
-#define UART3_TLR               (OMAP1_UART3_BASE + 0x1C)
-#define UART3_MDR1              (OMAP1_UART3_BASE + 0x20)
-#define UART3_MDR2              (OMAP1_UART3_BASE + 0x24)
-#define UART3_SFLSR             (OMAP1_UART3_BASE + 0x28)
-#define UART3_TXFLL             (OMAP1_UART3_BASE + 0x28)
-#define UART3_RESUME            (OMAP1_UART3_BASE + 0x2C)
-#define UART3_TXFLH             (OMAP1_UART3_BASE + 0x2C)
-#define UART3_SFREGL            (OMAP1_UART3_BASE + 0x30)
-#define UART3_RXFLL             (OMAP1_UART3_BASE + 0x30)
-#define UART3_SFREGH            (OMAP1_UART3_BASE + 0x34)
-#define UART3_RXFLH             (OMAP1_UART3_BASE + 0x34)
-#define UART3_BLR               (OMAP1_UART3_BASE + 0x38)
-#define UART3_ACREG             (OMAP1_UART3_BASE + 0x3C)
-#define UART3_DIV16             (OMAP1_UART3_BASE + 0x3C)
-#define UART3_SCR               (OMAP1_UART3_BASE + 0x40)
-#define UART3_SSR               (OMAP1_UART3_BASE + 0x44)
-#define UART3_EBLR              (OMAP1_UART3_BASE + 0x48)
-#define UART3_OSC_12M_SEL       (OMAP1_UART3_BASE + 0x4C)
-#define UART3_MVR               (OMAP1_UART3_BASE + 0x50)
-
-/*
- * ---------------------------------------------------------------------------
- * Watchdog timer
- * ---------------------------------------------------------------------------
- */
-
-/* 32-bit Watchdog timer in OMAP 16XX */
-#define OMAP_16XX_WATCHDOG_BASE        (0xfffeb000)
-#define OMAP_16XX_WIDR         (OMAP_16XX_WATCHDOG_BASE + 0x00)
-#define OMAP_16XX_WD_SYSCONFIG (OMAP_16XX_WATCHDOG_BASE + 0x10)
-#define OMAP_16XX_WD_SYSSTATUS (OMAP_16XX_WATCHDOG_BASE + 0x14)
-#define OMAP_16XX_WCLR         (OMAP_16XX_WATCHDOG_BASE + 0x24)
-#define OMAP_16XX_WCRR         (OMAP_16XX_WATCHDOG_BASE + 0x28)
-#define OMAP_16XX_WLDR         (OMAP_16XX_WATCHDOG_BASE + 0x2c)
-#define OMAP_16XX_WTGR         (OMAP_16XX_WATCHDOG_BASE + 0x30)
-#define OMAP_16XX_WWPS         (OMAP_16XX_WATCHDOG_BASE + 0x34)
-#define OMAP_16XX_WSPR         (OMAP_16XX_WATCHDOG_BASE + 0x48)
-
-#define WCLR_PRE_SHIFT         5
-#define WCLR_PTV_SHIFT         2
-
-#define WWPS_W_PEND_WSPR       (1 << 4)
-#define WWPS_W_PEND_WTGR       (1 << 3)
-#define WWPS_W_PEND_WLDR       (1 << 2)
-#define WWPS_W_PEND_WCRR       (1 << 1)
-#define WWPS_W_PEND_WCLR       (1 << 0)
-
-#define WSPR_ENABLE_0          (0x0000bbbb)
-#define WSPR_ENABLE_1          (0x00004444)
-#define WSPR_DISABLE_0         (0x0000aaaa)
-#define WSPR_DISABLE_1         (0x00005555)
-
-#define OMAP16XX_DSP_MMU_BASE	(0xfffed200)
-#define OMAP16XX_MAILBOX_BASE	(0xfffcf000)
-
-#endif /*  __ASM_ARCH_OMAP16XX_H */
-
diff --git a/arch/arm/plat-omap/include/plat/omap24xx.h b/arch/arm/plat-omap/include/plat/omap24xx.h
deleted file mode 100644
index 92df9e2..0000000
--- a/arch/arm/plat-omap/include/plat/omap24xx.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * arch/arm/plat-omap/include/mach/omap24xx.h
- *
- * This file contains the processor specific definitions
- * of the TI OMAP24XX.
- *
- * Copyright (C) 2007 Texas Instruments.
- * Copyright (C) 2007 Nokia Corporation.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-#ifndef __ASM_ARCH_OMAP2_H
-#define __ASM_ARCH_OMAP2_H
-
-/*
- * Please place only base defines here and put the rest in device
- * specific headers. Note also that some of these defines are needed
- * for omap1 to compile without adding ifdefs.
- */
-
-#define L4_24XX_BASE		0x48000000
-#define L4_WK_243X_BASE		0x49000000
-#define L3_24XX_BASE		0x68000000
-
-/* interrupt controller */
-#define OMAP24XX_IC_BASE	(L4_24XX_BASE + 0xfe000)
-#define OMAP24XX_IVA_INTC_BASE	0x40000000
-
-#define OMAP242X_CTRL_BASE	L4_24XX_BASE
-#define OMAP2420_32KSYNCT_BASE	(L4_24XX_BASE + 0x4000)
-#define OMAP2420_PRCM_BASE	(L4_24XX_BASE + 0x8000)
-#define OMAP2420_CM_BASE	(L4_24XX_BASE + 0x8000)
-#define OMAP2420_PRM_BASE	OMAP2420_CM_BASE
-#define OMAP2420_SDRC_BASE	(L3_24XX_BASE + 0x9000)
-#define OMAP2420_SMS_BASE	0x68008000
-#define OMAP2420_GPMC_BASE	0x6800a000
-
-#define OMAP2430_32KSYNCT_BASE	(L4_WK_243X_BASE + 0x20000)
-#define OMAP2430_PRCM_BASE	(L4_WK_243X_BASE + 0x6000)
-#define OMAP2430_CM_BASE	(L4_WK_243X_BASE + 0x6000)
-#define OMAP2430_PRM_BASE	OMAP2430_CM_BASE
-
-#define OMAP243X_SMS_BASE	0x6C000000
-#define OMAP243X_SDRC_BASE	0x6D000000
-#define OMAP243X_GPMC_BASE	0x6E000000
-#define OMAP243X_SCM_BASE	(L4_WK_243X_BASE + 0x2000)
-#define OMAP243X_CTRL_BASE	OMAP243X_SCM_BASE
-#define OMAP243X_HS_BASE	(L4_24XX_BASE + 0x000ac000)
-
-/* DSP SS */
-#define OMAP2420_DSP_BASE	0x58000000
-#define OMAP2420_DSP_MEM_BASE	(OMAP2420_DSP_BASE + 0x0)
-#define OMAP2420_DSP_IPI_BASE	(OMAP2420_DSP_BASE + 0x1000000)
-#define OMAP2420_DSP_MMU_BASE	(OMAP2420_DSP_BASE + 0x2000000)
-
-#define OMAP243X_DSP_BASE	0x5C000000
-#define OMAP243X_DSP_MEM_BASE	(OMAP243X_DSP_BASE + 0x0)
-#define OMAP243X_DSP_MMU_BASE	(OMAP243X_DSP_BASE + 0x1000000)
-
-/* Mailbox */
-#define OMAP24XX_MAILBOX_BASE	(L4_24XX_BASE + 0x94000)
-
-/* Camera */
-#define OMAP24XX_CAMERA_BASE	(L4_24XX_BASE + 0x52000)
-
-/* Security */
-#define OMAP24XX_SEC_BASE	(L4_24XX_BASE + 0xA0000)
-#define OMAP24XX_SEC_RNG_BASE	(OMAP24XX_SEC_BASE + 0x0000)
-#define OMAP24XX_SEC_DES_BASE	(OMAP24XX_SEC_BASE + 0x2000)
-#define OMAP24XX_SEC_SHA1MD5_BASE (OMAP24XX_SEC_BASE + 0x4000)
-#define OMAP24XX_SEC_AES_BASE	(OMAP24XX_SEC_BASE + 0x6000)
-#define OMAP24XX_SEC_PKA_BASE	(OMAP24XX_SEC_BASE + 0x8000)
-
-#endif /* __ASM_ARCH_OMAP2_H */
-
diff --git a/arch/arm/plat-omap/include/plat/omap34xx.h b/arch/arm/plat-omap/include/plat/omap34xx.h
deleted file mode 100644
index 0d818ac..0000000
--- a/arch/arm/plat-omap/include/plat/omap34xx.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * arch/arm/plat-omap/include/mach/omap34xx.h
- *
- * This file contains the processor specific definitions of the TI OMAP34XX.
- *
- * Copyright (C) 2007 Texas Instruments.
- * Copyright (C) 2007 Nokia Corporation.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#ifndef __ASM_ARCH_OMAP3_H
-#define __ASM_ARCH_OMAP3_H
-
-/*
- * Please place only base defines here and put the rest in device
- * specific headers.
- */
-
-#define L4_34XX_BASE		0x48000000
-#define L4_WK_34XX_BASE		0x48300000
-#define L4_PER_34XX_BASE	0x49000000
-#define L4_EMU_34XX_BASE	0x54000000
-#define L3_34XX_BASE		0x68000000
-
-#define L4_WK_AM33XX_BASE	0x44C00000
-
-#define OMAP3430_32KSYNCT_BASE	0x48320000
-#define OMAP3430_CM_BASE	0x48004800
-#define OMAP3430_PRM_BASE	0x48306800
-#define OMAP343X_SMS_BASE	0x6C000000
-#define OMAP343X_SDRC_BASE	0x6D000000
-#define OMAP34XX_GPMC_BASE	0x6E000000
-#define OMAP343X_SCM_BASE	0x48002000
-#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_REGS1_BASE	(OMAP3430_ISP_BASE + 0x1800)
-#define OMAP3430_ISP_CSIPHY2_BASE	(OMAP3430_ISP_BASE + 0x1970)
-#define OMAP3630_ISP_CSI2A_REGS2_BASE	(OMAP3430_ISP_BASE + 0x19C0)
-#define OMAP3630_ISP_CSI2C_REGS1_BASE	(OMAP3430_ISP_BASE + 0x1C00)
-#define OMAP3630_ISP_CSIPHY1_BASE	(OMAP3430_ISP_BASE + 0x1D70)
-#define OMAP3630_ISP_CSI2C_REGS2_BASE	(OMAP3430_ISP_BASE + 0x1DC0)
-
-#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_REGS1_END	(OMAP3430_ISP_CSI2A_REGS1_BASE + 0x16F)
-#define OMAP3430_ISP_CSIPHY2_END	(OMAP3430_ISP_CSIPHY2_BASE + 0x00B)
-#define OMAP3630_ISP_CSI2A_REGS2_END	(OMAP3630_ISP_CSI2A_REGS2_BASE + 0x3F)
-#define OMAP3630_ISP_CSI2C_REGS1_END	(OMAP3630_ISP_CSI2C_REGS1_BASE + 0x16F)
-#define OMAP3630_ISP_CSIPHY1_END	(OMAP3630_ISP_CSIPHY1_BASE + 0x00B)
-#define OMAP3630_ISP_CSI2C_REGS2_END	(OMAP3630_ISP_CSI2C_REGS2_BASE + 0x3F)
-
-#define OMAP34XX_HSUSB_OTG_BASE	(L4_34XX_BASE + 0xAB000)
-#define OMAP34XX_USBTLL_BASE	(L4_34XX_BASE + 0x62000)
-#define OMAP34XX_UHH_CONFIG_BASE	(L4_34XX_BASE + 0x64000)
-#define OMAP34XX_OHCI_BASE	(L4_34XX_BASE + 0x64400)
-#define OMAP34XX_EHCI_BASE	(L4_34XX_BASE + 0x64800)
-#define OMAP34XX_SR1_BASE	0x480C9000
-#define OMAP34XX_SR2_BASE	0x480CB000
-
-#define OMAP34XX_MAILBOX_BASE		(L4_34XX_BASE + 0x94000)
-
-/* Security */
-#define OMAP34XX_SEC_BASE	(L4_34XX_BASE + 0xA0000)
-#define OMAP34XX_SEC_SHA1MD5_BASE	(OMAP34XX_SEC_BASE + 0x23000)
-#define OMAP34XX_SEC_AES_BASE	(OMAP34XX_SEC_BASE + 0x25000)
-
-#endif /* __ASM_ARCH_OMAP3_H */
-
diff --git a/arch/arm/plat-omap/include/plat/omap4-keypad.h b/arch/arm/plat-omap/include/plat/omap4-keypad.h
deleted file mode 100644
index 8ad0a37..0000000
--- a/arch/arm/plat-omap/include/plat/omap4-keypad.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef ARCH_ARM_PLAT_OMAP4_KEYPAD_H
-#define ARCH_ARM_PLAT_OMAP4_KEYPAD_H
-
-extern int omap4_keyboard_init(struct omap4_keypad_platform_data *,
-				struct omap_board_data *);
-#endif
diff --git a/arch/arm/plat-omap/include/plat/omap44xx.h b/arch/arm/plat-omap/include/plat/omap44xx.h
deleted file mode 100644
index c0d478e..0000000
--- a/arch/arm/plat-omap/include/plat/omap44xx.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*:
- * Address mappings and base address for OMAP4 interconnects
- * and peripherals.
- *
- * Copyright (C) 2009 Texas Instruments
- *
- * Author: Santosh Shilimkar <santosh.shilimkar@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.
- */
-#ifndef __ASM_ARCH_OMAP44XX_H
-#define __ASM_ARCH_OMAP44XX_H
-
-/*
- * Please place only base defines here and put the rest in device
- * specific headers.
- */
-#define L4_44XX_BASE			0x4a000000
-#define L4_WK_44XX_BASE			0x4a300000
-#define L4_PER_44XX_BASE		0x48000000
-#define L4_EMU_44XX_BASE		0x54000000
-#define L3_44XX_BASE			0x44000000
-#define OMAP44XX_EMIF1_BASE		0x4c000000
-#define OMAP44XX_EMIF2_BASE		0x4d000000
-#define OMAP44XX_DMM_BASE		0x4e000000
-#define OMAP4430_32KSYNCT_BASE		0x4a304000
-#define OMAP4430_CM1_BASE		0x4a004000
-#define OMAP4430_CM_BASE		OMAP4430_CM1_BASE
-#define OMAP4430_CM2_BASE		0x4a008000
-#define OMAP4430_PRM_BASE		0x4a306000
-#define OMAP4430_PRCM_MPU_BASE		0x48243000
-#define OMAP44XX_GPMC_BASE		0x50000000
-#define OMAP443X_SCM_BASE		0x4a002000
-#define OMAP443X_CTRL_BASE		0x4a100000
-#define OMAP44XX_IC_BASE		0x48200000
-#define OMAP44XX_IVA_INTC_BASE		0x40000000
-#define IRQ_SIR_IRQ			0x0040
-#define OMAP44XX_GIC_DIST_BASE		0x48241000
-#define OMAP44XX_GIC_CPU_BASE		0x48240100
-#define OMAP44XX_SCU_BASE		0x48240000
-#define OMAP44XX_LOCAL_TWD_BASE		0x48240600
-#define OMAP44XX_L2CACHE_BASE		0x48242000
-#define OMAP44XX_WKUPGEN_BASE		0x48281000
-#define OMAP44XX_MCPDM_BASE		0x40132000
-#define OMAP44XX_MCPDM_L3_BASE		0x49032000
-#define OMAP44XX_SAR_RAM_BASE		0x4a326000
-
-#define OMAP44XX_MAILBOX_BASE		(L4_44XX_BASE + 0xF4000)
-#define OMAP44XX_HSUSB_OTG_BASE		(L4_44XX_BASE + 0xAB000)
-
-#define OMAP4_MMU1_BASE			0x55082000
-#define OMAP4_MMU2_BASE			0x4A066000
-
-#define OMAP44XX_USBTLL_BASE		(L4_44XX_BASE + 0x62000)
-#define OMAP44XX_UHH_CONFIG_BASE	(L4_44XX_BASE + 0x64000)
-#define OMAP44XX_HSUSB_OHCI_BASE	(L4_44XX_BASE + 0x64800)
-#define OMAP44XX_HSUSB_EHCI_BASE	(L4_44XX_BASE + 0x64C00)
-
-#endif /* __ASM_ARCH_OMAP44XX_H */
-
diff --git a/arch/arm/plat-omap/include/plat/omap54xx.h b/arch/arm/plat-omap/include/plat/omap54xx.h
deleted file mode 100644
index a2582bb..0000000
--- a/arch/arm/plat-omap/include/plat/omap54xx.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*:
- * Address mappings and base address for OMAP5 interconnects
- * and peripherals.
- *
- * Copyright (C) 2012 Texas Instruments
- *	Santosh Shilimkar <santosh.shilimkar@ti.com>
- *	Sricharan <r.sricharan@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.
- */
-#ifndef __ASM_SOC_OMAP54XX_H
-#define __ASM_SOC_OMAP54XX_H
-
-/*
- * Please place only base defines here and put the rest in device
- * specific headers.
- */
-#define L4_54XX_BASE			0x4a000000
-#define L4_WK_54XX_BASE			0x4ae00000
-#define L4_PER_54XX_BASE		0x48000000
-#define L3_54XX_BASE			0x44000000
-#define OMAP54XX_32KSYNCT_BASE		0x4ae04000
-#define OMAP54XX_CM_CORE_AON_BASE	0x4a004000
-#define OMAP54XX_CM_CORE_BASE		0x4a008000
-#define OMAP54XX_PRM_BASE		0x4ae06000
-#define OMAP54XX_PRCM_MPU_BASE		0x48243000
-#define OMAP54XX_SCM_BASE		0x4a002000
-#define OMAP54XX_CTRL_BASE		0x4a002800
-
-#endif /* __ASM_SOC_OMAP555554XX_H */
diff --git a/arch/arm/plat-omap/include/plat/omap7xx.h b/arch/arm/plat-omap/include/plat/omap7xx.h
deleted file mode 100644
index 48e4757..0000000
--- a/arch/arm/plat-omap/include/plat/omap7xx.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/* arch/arm/plat-omap/include/mach/omap7xx.h
- *
- * Hardware definitions for TI OMAP7XX processor.
- *
- * Cleanup for Linux-2.6 by Dirk Behme <dirk.behme@de.bosch.com>
- * Adapted for omap850 by Zebediah C. McClure <zmc@lurian.net>
- * Adapted for omap7xx by Alistair Buxton <a.j.buxton@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 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_OMAP7XX_H
-#define __ASM_ARCH_OMAP7XX_H
-
-/*
- * ----------------------------------------------------------------------------
- * Base addresses
- * ----------------------------------------------------------------------------
- */
-
-/* Syntax: XX_BASE = Virtual base address, XX_START = Physical base address */
-
-#define OMAP7XX_DSP_BASE	0xE0000000
-#define OMAP7XX_DSP_SIZE	0x50000
-#define OMAP7XX_DSP_START	0xE0000000
-
-#define OMAP7XX_DSPREG_BASE	0xE1000000
-#define OMAP7XX_DSPREG_SIZE	SZ_128K
-#define OMAP7XX_DSPREG_START	0xE1000000
-
-#define OMAP7XX_SPI1_BASE	0xfffc0800
-#define OMAP7XX_SPI2_BASE	0xfffc1000
-
-/*
- * ----------------------------------------------------------------------------
- * OMAP7XX specific configuration registers
- * ----------------------------------------------------------------------------
- */
-#define OMAP7XX_CONFIG_BASE	0xfffe1000
-#define OMAP7XX_IO_CONF_0	0xfffe1070
-#define OMAP7XX_IO_CONF_1	0xfffe1074
-#define OMAP7XX_IO_CONF_2	0xfffe1078
-#define OMAP7XX_IO_CONF_3	0xfffe107c
-#define OMAP7XX_IO_CONF_4	0xfffe1080
-#define OMAP7XX_IO_CONF_5	0xfffe1084
-#define OMAP7XX_IO_CONF_6	0xfffe1088
-#define OMAP7XX_IO_CONF_7	0xfffe108c
-#define OMAP7XX_IO_CONF_8	0xfffe1090
-#define OMAP7XX_IO_CONF_9	0xfffe1094
-#define OMAP7XX_IO_CONF_10	0xfffe1098
-#define OMAP7XX_IO_CONF_11	0xfffe109c
-#define OMAP7XX_IO_CONF_12	0xfffe10a0
-#define OMAP7XX_IO_CONF_13	0xfffe10a4
-
-#define OMAP7XX_MODE_1		0xfffe1010
-#define OMAP7XX_MODE_2		0xfffe1014
-
-/* CSMI specials: in terms of base + offset */
-#define OMAP7XX_MODE2_OFFSET	0x14
-
-/*
- * ----------------------------------------------------------------------------
- * OMAP7XX traffic controller configuration registers
- * ----------------------------------------------------------------------------
- */
-#define OMAP7XX_FLASH_CFG_0	0xfffecc10
-#define OMAP7XX_FLASH_ACFG_0	0xfffecc50
-#define OMAP7XX_FLASH_CFG_1	0xfffecc14
-#define OMAP7XX_FLASH_ACFG_1	0xfffecc54
-
-/*
- * ----------------------------------------------------------------------------
- * OMAP7XX DSP control registers
- * ----------------------------------------------------------------------------
- */
-#define OMAP7XX_ICR_BASE	0xfffbb800
-#define OMAP7XX_DSP_M_CTL	0xfffbb804
-#define OMAP7XX_DSP_MMU_BASE	0xfffed200
-
-/*
- * ----------------------------------------------------------------------------
- * OMAP7XX PCC_UPLD configuration registers
- * ----------------------------------------------------------------------------
- */
-#define OMAP7XX_PCC_UPLD_CTRL_BASE	(0xfffe0900)
-#define OMAP7XX_PCC_UPLD_CTRL		(OMAP7XX_PCC_UPLD_CTRL_BASE + 0x00)
-
-#endif /*  __ASM_ARCH_OMAP7XX_H */
-
diff --git a/arch/arm/plat-omap/include/plat/omap_device.h b/arch/arm/plat-omap/include/plat/omap_device.h
index 4327b2c..e7259c0 100644
--- a/arch/arm/plat-omap/include/plat/omap_device.h
+++ b/arch/arm/plat-omap/include/plat/omap_device.h
@@ -60,6 +60,7 @@ extern struct dev_pm_domain omap_device_pm_domain;
  * @_dev_wakeup_lat_limit: dev wakeup latency limit in nsec - set by OMAP PM
  * @_state: one of OMAP_DEVICE_STATE_* (see above)
  * @flags: device flags
+ * @_driver_status: one of BUS_NOTIFY_*_DRIVER from <linux/device.h>
  *
  * Integrates omap_hwmod data into Linux platform_device.
  *
@@ -73,6 +74,7 @@ struct omap_device {
 	struct omap_device_pm_latency	*pm_lats;
 	u32				dev_wakeup_lat;
 	u32				_dev_wakeup_lat_limit;
+	unsigned long			_driver_status;
 	u8				pm_lats_cnt;
 	s8				pm_lat_level;
 	u8				hwmods_cnt;
diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h
index 6132972..0533073 100644
--- a/arch/arm/plat-omap/include/plat/omap_hwmod.h
+++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h
@@ -615,6 +615,7 @@ int omap_hwmod_softreset(struct omap_hwmod *oh);
 
 int omap_hwmod_count_resources(struct omap_hwmod *oh);
 int omap_hwmod_fill_resources(struct omap_hwmod *oh, struct resource *res);
+int omap_hwmod_fill_dma_resources(struct omap_hwmod *oh, struct resource *res);
 int omap_hwmod_get_resource_byname(struct omap_hwmod *oh, unsigned int type,
 				   const char *name, struct resource *res);
 
@@ -658,6 +659,7 @@ extern int omap2420_hwmod_init(void);
 extern int omap2430_hwmod_init(void);
 extern int omap3xxx_hwmod_init(void);
 extern int omap44xx_hwmod_init(void);
+extern int am33xx_hwmod_init(void);
 
 extern int __init omap_hwmod_register_links(struct omap_hwmod_ocp_if **ois);
 
diff --git a/arch/arm/plat-omap/include/plat/onenand.h b/arch/arm/plat-omap/include/plat/onenand.h
deleted file mode 100644
index 2858667..0000000
--- a/arch/arm/plat-omap/include/plat/onenand.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * arch/arm/plat-omap/include/mach/onenand.h
- *
- * Copyright (C) 2006 Nokia Corporation
- * Author: Juha Yrjola
- *
- * This program is free software; you can 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/mtd/mtd.h>
-#include <linux/mtd/partitions.h>
-
-#define ONENAND_SYNC_READ	(1 << 0)
-#define ONENAND_SYNC_READWRITE	(1 << 1)
-
-struct onenand_freq_info {
-	u16			maf_id;
-	u16			dev_id;
-	u16			ver_id;
-};
-
-struct omap_onenand_platform_data {
-	int			cs;
-	int			gpio_irq;
-	struct mtd_partition	*parts;
-	int			nr_parts;
-	int			(*onenand_setup)(void __iomem *, int *freq_ptr);
-	int		(*get_freq)(const struct onenand_freq_info *freq_info,
-				    bool *clk_dep);
-	int			dma_channel;
-	u8			flags;
-	u8			regulator_can_sleep;
-	u8			skip_initial_unlocking;
-};
-
-#define ONENAND_MAX_PARTITIONS 8
-
-#if defined(CONFIG_MTD_ONENAND_OMAP2) || \
-	defined(CONFIG_MTD_ONENAND_OMAP2_MODULE)
-
-extern void gpmc_onenand_init(struct omap_onenand_platform_data *d);
-
-#else
-
-#define board_onenand_data	NULL
-
-static inline void gpmc_onenand_init(struct omap_onenand_platform_data *d)
-{
-}
-
-#endif
diff --git a/arch/arm/plat-omap/include/plat/param.h b/arch/arm/plat-omap/include/plat/param.h
deleted file mode 100644
index 1eb4dc3..0000000
--- a/arch/arm/plat-omap/include/plat/param.h
+++ /dev/null
@@ -1,8 +0,0 @@
-/*
- *  arch/arm/plat-omap/include/mach/param.h
- *
- */
-
-#ifdef CONFIG_OMAP_32K_TIMER_HZ
-#define HZ	CONFIG_OMAP_32K_TIMER_HZ
-#endif
diff --git a/arch/arm/plat-omap/include/plat/remoteproc.h b/arch/arm/plat-omap/include/plat/remoteproc.h
deleted file mode 100644
index b10eac8..0000000
--- a/arch/arm/plat-omap/include/plat/remoteproc.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Remote Processor - omap-specific bits
- *
- * Copyright (C) 2011 Texas Instruments, Inc.
- * Copyright (C) 2011 Google, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#ifndef _PLAT_REMOTEPROC_H
-#define _PLAT_REMOTEPROC_H
-
-struct rproc_ops;
-struct platform_device;
-
-/*
- * struct omap_rproc_pdata - omap remoteproc's platform data
- * @name: the remoteproc's name
- * @oh_name: omap hwmod device
- * @oh_name_opt: optional, secondary omap hwmod device
- * @firmware: name of firmware file to load
- * @mbox_name: name of omap mailbox device to use with this rproc
- * @ops: start/stop rproc handlers
- * @device_enable: omap-specific handler for enabling a device
- * @device_shutdown: omap-specific handler for shutting down a device
- */
-struct omap_rproc_pdata {
-	const char *name;
-	const char *oh_name;
-	const char *oh_name_opt;
-	const char *firmware;
-	const char *mbox_name;
-	const struct rproc_ops *ops;
-	int (*device_enable) (struct platform_device *pdev);
-	int (*device_shutdown) (struct platform_device *pdev);
-};
-
-#if defined(CONFIG_OMAP_REMOTEPROC) || defined(CONFIG_OMAP_REMOTEPROC_MODULE)
-
-void __init omap_rproc_reserve_cma(void);
-
-#else
-
-void __init omap_rproc_reserve_cma(void)
-{
-}
-
-#endif
-
-#endif /* _PLAT_REMOTEPROC_H */
diff --git a/arch/arm/plat-omap/include/plat/ti81xx.h b/arch/arm/plat-omap/include/plat/ti81xx.h
deleted file mode 100644
index 8f9843f..0000000
--- a/arch/arm/plat-omap/include/plat/ti81xx.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * This file contains the address data for various TI81XX modules.
- *
- * Copyright (C) 2010 Texas Instruments, Inc. - http://www.ti.com/
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation version 2.
- *
- * This program is distributed "as is" WITHOUT ANY WARRANTY of any
- * kind, whether express or implied; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#ifndef __ASM_ARCH_TI81XX_H
-#define __ASM_ARCH_TI81XX_H
-
-#define L4_SLOW_TI81XX_BASE	0x48000000
-
-#define TI81XX_SCM_BASE		0x48140000
-#define TI81XX_CTRL_BASE	TI81XX_SCM_BASE
-#define TI81XX_PRCM_BASE	0x48180000
-
-#define TI81XX_ARM_INTC_BASE	0x48200000
-
-#endif /* __ASM_ARCH_TI81XX_H */
diff --git a/arch/arm/plat-omap/include/plat/usb.h b/arch/arm/plat-omap/include/plat/usb.h
index 548a4c8..87ee140 100644
--- a/arch/arm/plat-omap/include/plat/usb.h
+++ b/arch/arm/plat-omap/include/plat/usb.h
@@ -4,8 +4,8 @@
 #define	__ASM_ARCH_OMAP_USB_H
 
 #include <linux/io.h>
+#include <linux/platform_device.h>
 #include <linux/usb/musb.h>
-#include <plat/board.h>
 
 #define OMAP3_HS_USB_PORTS	3
 
@@ -64,6 +64,10 @@ struct usbhs_omap_platform_data {
 	struct ehci_hcd_omap_platform_data	*ehci_data;
 	struct ohci_hcd_omap_platform_data	*ohci_data;
 };
+
+struct usbtll_omap_platform_data {
+	enum usbhs_omap_port_mode		port_mode[OMAP3_HS_USB_PORTS];
+};
 /*-------------------------------------------------------------------------*/
 
 struct omap_musb_board_data {
@@ -82,6 +86,8 @@ enum musb_interface    {MUSB_INTERFACE_ULPI, MUSB_INTERFACE_UTMI};
 extern void usb_musb_init(struct omap_musb_board_data *board_data);
 
 extern void usbhs_init(const struct usbhs_omap_board_data *pdata);
+extern int omap_tll_enable(void);
+extern int omap_tll_disable(void);
 
 extern int omap4430_phy_power(struct device *dev, int ID, int on);
 extern int omap4430_phy_set_clk(struct device *dev, int on);
diff --git a/arch/arm/plat-omap/include/plat/voltage.h b/arch/arm/plat-omap/include/plat/voltage.h
deleted file mode 100644
index 5be4d5d..0000000
--- a/arch/arm/plat-omap/include/plat/voltage.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * OMAP Voltage Management Routines
- *
- * Copyright (C) 2011, 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 version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __ARCH_ARM_OMAP_VOLTAGE_H
-#define __ARCH_ARM_OMAP_VOLTAGE_H
-
-/**
- * struct omap_volt_data - Omap voltage specific data.
- * @voltage_nominal:	The possible voltage value in uV
- * @sr_efuse_offs:	The offset of the efuse register(from system
- *			control module base address) from where to read
- *			the n-target value for the smartreflex module.
- * @sr_errminlimit:	Error min limit value for smartreflex. This value
- *			differs at differnet opp and thus is linked
- *			with voltage.
- * @vp_errorgain:	Error gain value for the voltage processor. This
- *			field also differs according to the voltage/opp.
- */
-struct omap_volt_data {
-	u32	volt_nominal;
-	u32	sr_efuse_offs;
-	u8	sr_errminlimit;
-	u8	vp_errgain;
-};
-struct voltagedomain;
-
-struct voltagedomain *voltdm_lookup(const char *name);
-int voltdm_scale(struct voltagedomain *voltdm, unsigned long target_volt);
-unsigned long voltdm_get_voltage(struct voltagedomain *voltdm);
-struct omap_volt_data *omap_voltage_get_voltdata(struct voltagedomain *voltdm,
-		unsigned long volt);
-#endif
diff --git a/arch/arm/plat-omap/mailbox.c b/arch/arm/plat-omap/mailbox.c
index 5e13c38..42377ef 100644
--- a/arch/arm/plat-omap/mailbox.c
+++ b/arch/arm/plat-omap/mailbox.c
@@ -310,7 +310,7 @@ static void omap_mbox_fini(struct omap_mbox *mbox)
 		omap_mbox_disable_irq(mbox, IRQ_RX);
 		free_irq(mbox->irq, mbox);
 		tasklet_kill(&mbox->txq->tasklet);
-		flush_work_sync(&mbox->rxq->work);
+		flush_work(&mbox->rxq->work);
 		mbox_queue_free(mbox->txq);
 		mbox_queue_free(mbox->rxq);
 	}
diff --git a/arch/arm/plat-omap/mux.c b/arch/arm/plat-omap/mux.c
deleted file mode 100644
index cff8712..0000000
--- a/arch/arm/plat-omap/mux.c
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * linux/arch/arm/plat-omap/mux.c
- *
- * Utility to set the Omap MUX and PULL_DWN registers from a table in mux.h
- *
- * Copyright (C) 2003 - 2008 Nokia Corporation
- *
- * Written by Tony Lindgren
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/io.h>
-#include <linux/spinlock.h>
-
-#include <asm/system.h>
-
-#include <plat/cpu.h>
-#include <plat/mux.h>
-
-#ifdef CONFIG_OMAP_MUX
-
-static struct omap_mux_cfg *mux_cfg;
-
-int __init omap_mux_register(struct omap_mux_cfg *arch_mux_cfg)
-{
-	if (!arch_mux_cfg || !arch_mux_cfg->pins || arch_mux_cfg->size == 0
-			|| !arch_mux_cfg->cfg_reg) {
-		printk(KERN_ERR "Invalid pin table\n");
-		return -EINVAL;
-	}
-
-	mux_cfg = arch_mux_cfg;
-
-	return 0;
-}
-
-/*
- * Sets the Omap MUX and PULL_DWN registers based on the table
- */
-int __init_or_module omap_cfg_reg(const unsigned long index)
-{
-	struct pin_config *reg;
-
-	if (!cpu_class_is_omap1()) {
-		printk(KERN_ERR "mux: Broken omap_cfg_reg(%lu) entry\n",
-				index);
-		WARN_ON(1);
-		return -EINVAL;
-	}
-
-	if (mux_cfg == NULL) {
-		printk(KERN_ERR "Pin mux table not initialized\n");
-		return -ENODEV;
-	}
-
-	if (index >= mux_cfg->size) {
-		printk(KERN_ERR "Invalid pin mux index: %lu (%lu)\n",
-		       index, mux_cfg->size);
-		dump_stack();
-		return -ENODEV;
-	}
-
-	reg = (struct pin_config *)&mux_cfg->pins[index];
-
-	if (!mux_cfg->cfg_reg)
-		return -ENODEV;
-
-	return mux_cfg->cfg_reg(reg);
-}
-EXPORT_SYMBOL(omap_cfg_reg);
-#else
-#define omap_mux_init() do {} while(0)
-#define omap_cfg_reg(x)	do {} while(0)
-#endif	/* CONFIG_OMAP_MUX */
diff --git a/arch/arm/plat-omap/omap-pm-noop.c b/arch/arm/plat-omap/omap-pm-noop.c
index 5a97b4d..9f64133 100644
--- a/arch/arm/plat-omap/omap-pm-noop.c
+++ b/arch/arm/plat-omap/omap-pm-noop.c
@@ -41,11 +41,11 @@ int omap_pm_set_max_mpu_wakeup_lat(struct device *dev, long t)
 	};
 
 	if (t == -1)
-		pr_debug("OMAP PM: remove max MPU wakeup latency constraint: "
-			 "dev %s\n", dev_name(dev));
+		pr_debug("OMAP PM: remove max MPU wakeup latency constraint: dev %s\n",
+			 dev_name(dev));
 	else
-		pr_debug("OMAP PM: add max MPU wakeup latency constraint: "
-			 "dev %s, t = %ld usec\n", dev_name(dev), t);
+		pr_debug("OMAP PM: add max MPU wakeup latency constraint: dev %s, t = %ld usec\n",
+			 dev_name(dev), t);
 
 	/*
 	 * For current Linux, this needs to map the MPU to a
@@ -70,11 +70,10 @@ int omap_pm_set_min_bus_tput(struct device *dev, u8 agent_id, unsigned long r)
 	};
 
 	if (r == 0)
-		pr_debug("OMAP PM: remove min bus tput constraint: "
-			 "dev %s for agent_id %d\n", dev_name(dev), agent_id);
+		pr_debug("OMAP PM: remove min bus tput constraint: dev %s for agent_id %d\n",
+			 dev_name(dev), agent_id);
 	else
-		pr_debug("OMAP PM: add min bus tput constraint: "
-			 "dev %s for agent_id %d: rate %ld KiB\n",
+		pr_debug("OMAP PM: add min bus tput constraint: dev %s for agent_id %d: rate %ld KiB\n",
 			 dev_name(dev), agent_id, r);
 
 	/*
@@ -97,11 +96,11 @@ int omap_pm_set_max_dev_wakeup_lat(struct device *req_dev, struct device *dev,
 	};
 
 	if (t == -1)
-		pr_debug("OMAP PM: remove max device latency constraint: "
-			 "dev %s\n", dev_name(dev));
+		pr_debug("OMAP PM: remove max device latency constraint: dev %s\n",
+			 dev_name(dev));
 	else
-		pr_debug("OMAP PM: add max device latency constraint: "
-			 "dev %s, t = %ld usec\n", dev_name(dev), t);
+		pr_debug("OMAP PM: add max device latency constraint: dev %s, t = %ld usec\n",
+			 dev_name(dev), t);
 
 	/*
 	 * For current Linux, this needs to map the device to a
@@ -127,11 +126,11 @@ int omap_pm_set_max_sdma_lat(struct device *dev, long t)
 	};
 
 	if (t == -1)
-		pr_debug("OMAP PM: remove max DMA latency constraint: "
-			 "dev %s\n", dev_name(dev));
+		pr_debug("OMAP PM: remove max DMA latency constraint: dev %s\n",
+			 dev_name(dev));
 	else
-		pr_debug("OMAP PM: add max DMA latency constraint: "
-			 "dev %s, t = %ld usec\n", dev_name(dev), t);
+		pr_debug("OMAP PM: add max DMA latency constraint: dev %s, t = %ld usec\n",
+			 dev_name(dev), t);
 
 	/*
 	 * For current Linux PM QOS params, this code should scan the
@@ -156,11 +155,11 @@ int omap_pm_set_min_clk_rate(struct device *dev, struct clk *c, long r)
 	}
 
 	if (r == 0)
-		pr_debug("OMAP PM: remove min clk rate constraint: "
-			 "dev %s\n", dev_name(dev));
+		pr_debug("OMAP PM: remove min clk rate constraint: dev %s\n",
+			 dev_name(dev));
 	else
-		pr_debug("OMAP PM: add min clk rate constraint: "
-			 "dev %s, rate = %ld Hz\n", dev_name(dev), r);
+		pr_debug("OMAP PM: add min clk rate constraint: dev %s, rate = %ld Hz\n",
+			 dev_name(dev), r);
 
 	/*
 	 * Code in a real implementation should keep track of these
diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c
index c490240..d5f617c 100644
--- a/arch/arm/plat-omap/omap_device.c
+++ b/arch/arm/plat-omap/omap_device.c
@@ -1,4 +1,3 @@
-
 /*
  * omap_device implementation
  *
@@ -153,21 +152,19 @@ static int _omap_device_activate(struct omap_device *od, u8 ignore_lat)
 		act_lat = timespec_to_ns(&c);
 
 		dev_dbg(&od->pdev->dev,
-			"omap_device: pm_lat %d: activate: elapsed time "
-			"%llu nsec\n", od->pm_lat_level, act_lat);
+			"omap_device: pm_lat %d: activate: elapsed time %llu nsec\n",
+			od->pm_lat_level, act_lat);
 
 		if (act_lat > odpl->activate_lat) {
 			odpl->activate_lat_worst = act_lat;
 			if (odpl->flags & OMAP_DEVICE_LATENCY_AUTO_ADJUST) {
 				odpl->activate_lat = act_lat;
 				dev_dbg(&od->pdev->dev,
-					"new worst case activate latency "
-					"%d: %llu\n",
+					"new worst case activate latency %d: %llu\n",
 					od->pm_lat_level, act_lat);
 			} else
 				dev_warn(&od->pdev->dev,
-					 "activate latency %d "
-					 "higher than exptected. (%llu > %d)\n",
+					 "activate latency %d higher than expected. (%llu > %d)\n",
 					 od->pm_lat_level, act_lat,
 					 odpl->activate_lat);
 		}
@@ -220,21 +217,19 @@ static int _omap_device_deactivate(struct omap_device *od, u8 ignore_lat)
 		deact_lat = timespec_to_ns(&c);
 
 		dev_dbg(&od->pdev->dev,
-			"omap_device: pm_lat %d: deactivate: elapsed time "
-			"%llu nsec\n", od->pm_lat_level, deact_lat);
+			"omap_device: pm_lat %d: deactivate: elapsed time %llu nsec\n",
+			od->pm_lat_level, deact_lat);
 
 		if (deact_lat > odpl->deactivate_lat) {
 			odpl->deactivate_lat_worst = deact_lat;
 			if (odpl->flags & OMAP_DEVICE_LATENCY_AUTO_ADJUST) {
 				odpl->deactivate_lat = deact_lat;
 				dev_dbg(&od->pdev->dev,
-					"new worst case deactivate latency "
-					"%d: %llu\n",
+					"new worst case deactivate latency %d: %llu\n",
 					od->pm_lat_level, deact_lat);
 			} else
 				dev_warn(&od->pdev->dev,
-					 "deactivate latency %d "
-					 "higher than exptected. (%llu > %d)\n",
+					 "deactivate latency %d higher than expected. (%llu > %d)\n",
 					 od->pm_lat_level, deact_lat,
 					 odpl->deactivate_lat);
 		}
@@ -370,6 +365,14 @@ static int omap_device_build_from_dt(struct platform_device *pdev)
 		goto odbfd_exit1;
 	}
 
+	/* Fix up missing resource names */
+	for (i = 0; i < pdev->num_resources; i++) {
+		struct resource *r = &pdev->resource[i];
+
+		if (r->name == NULL)
+			r->name = dev_name(&pdev->dev);
+	}
+
 	if (of_get_property(node, "ti,no_idle_on_suspend", NULL))
 		omap_device_disable_idle_on_suspend(pdev);
 
@@ -385,17 +388,21 @@ static int _omap_device_notifier_call(struct notifier_block *nb,
 				      unsigned long event, void *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
+	struct omap_device *od;
 
 	switch (event) {
-	case BUS_NOTIFY_ADD_DEVICE:
-		if (pdev->dev.of_node)
-			omap_device_build_from_dt(pdev);
-		break;
-
 	case BUS_NOTIFY_DEL_DEVICE:
 		if (pdev->archdata.od)
 			omap_device_delete(pdev->archdata.od);
 		break;
+	case BUS_NOTIFY_ADD_DEVICE:
+		if (pdev->dev.of_node)
+			omap_device_build_from_dt(pdev);
+		/* fall through */
+	default:
+		od = to_omap_device(pdev);
+		if (od)
+			od->_driver_status = event;
 	}
 
 	return NOTIFY_DONE;
@@ -449,8 +456,8 @@ static int omap_device_count_resources(struct omap_device *od)
 	for (i = 0; i < od->hwmods_cnt; i++)
 		c += omap_hwmod_count_resources(od->hwmods[i]);
 
-	pr_debug("omap_device: %s: counted %d total resources across %d "
-		 "hwmods\n", od->pdev->name, c, od->hwmods_cnt);
+	pr_debug("omap_device: %s: counted %d total resources across %d hwmods\n",
+		 od->pdev->name, c, od->hwmods_cnt);
 
 	return c;
 }
@@ -486,6 +493,33 @@ static int omap_device_fill_resources(struct omap_device *od,
 }
 
 /**
+ * _od_fill_dma_resources - fill in array of struct resource with dma resources
+ * @od: struct omap_device *
+ * @res: pointer to an array of struct resource to be filled in
+ *
+ * Populate one or more empty struct resource pointed to by @res with
+ * the dma resource data for this omap_device @od.  Used by
+ * omap_device_alloc() after calling omap_device_count_resources().
+ *
+ * Ideally this function would not be needed at all.  If we have
+ * mechanism to get dma resources from DT.
+ *
+ * Returns 0.
+ */
+static int _od_fill_dma_resources(struct omap_device *od,
+				      struct resource *res)
+{
+	int i, r;
+
+	for (i = 0; i < od->hwmods_cnt; i++) {
+		r = omap_hwmod_fill_dma_resources(od->hwmods[i], res);
+		res += r;
+	}
+
+	return 0;
+}
+
+/**
  * omap_device_alloc - allocate an omap_device
  * @pdev: platform_device that will be included in this omap_device
  * @oh: ptr to the single omap_hwmod that backs this omap_device
@@ -524,24 +558,44 @@ struct omap_device *omap_device_alloc(struct platform_device *pdev,
 	od->hwmods = hwmods;
 	od->pdev = pdev;
 
+	res_count = omap_device_count_resources(od);
 	/*
-	 * HACK: Ideally the resources from DT should match, and hwmod
-	 * should just add the missing ones. Since the name is not
-	 * properly populated by DT, stick to hwmod resources only.
+	 * DT Boot:
+	 *   OF framework will construct the resource structure (currently
+	 *   does for MEM & IRQ resource) and we should respect/use these
+	 *   resources, killing hwmod dependency.
+	 *   If pdev->num_resources > 0, we assume that MEM & IRQ resources
+	 *   have been allocated by OF layer already (through DTB).
+	 *
+	 * Non-DT Boot:
+	 *   Here, pdev->num_resources = 0, and we should get all the
+	 *   resources from hwmod.
+	 *
+	 * TODO: Once DMA resource is available from OF layer, we should
+	 *   kill filling any resources from hwmod.
 	 */
-	if (pdev->num_resources && pdev->resource)
-		dev_warn(&pdev->dev, "%s(): resources already allocated %d\n",
-			__func__, pdev->num_resources);
-
-	res_count = omap_device_count_resources(od);
-	if (res_count > 0) {
-		dev_dbg(&pdev->dev, "%s(): resources allocated from hwmod %d\n",
-			__func__, res_count);
+	if (res_count > pdev->num_resources) {
+		/* Allocate resources memory to account for new resources */
 		res = kzalloc(sizeof(struct resource) * res_count, GFP_KERNEL);
 		if (!res)
 			goto oda_exit3;
 
-		omap_device_fill_resources(od, res);
+		/*
+		 * If pdev->num_resources > 0, then assume that,
+		 * MEM and IRQ resources will only come from DT and only
+		 * fill DMA resource from hwmod layer.
+		 */
+		if (pdev->num_resources && pdev->resource) {
+			dev_dbg(&pdev->dev, "%s(): resources already allocated %d\n",
+				__func__, res_count);
+			memcpy(res, pdev->resource,
+			       sizeof(struct resource) * pdev->num_resources);
+			_od_fill_dma_resources(od, &res[pdev->num_resources]);
+		} else {
+			dev_dbg(&pdev->dev, "%s(): using resources from hwmod %d\n",
+				__func__, res_count);
+			omap_device_fill_resources(od, res);
+		}
 
 		ret = platform_device_add_resources(pdev, res, res_count);
 		kfree(res);
@@ -752,6 +806,10 @@ static int _od_suspend_noirq(struct device *dev)
 	struct omap_device *od = to_omap_device(pdev);
 	int ret;
 
+	/* Don't attempt late suspend on a driver that is not bound */
+	if (od->_driver_status != BUS_NOTIFY_BOUND_DRIVER)
+		return 0;
+
 	ret = pm_generic_suspend_noirq(dev);
 
 	if (!ret && !pm_runtime_status_suspended(dev)) {
@@ -1125,3 +1183,41 @@ static int __init omap_device_init(void)
 	return 0;
 }
 core_initcall(omap_device_init);
+
+/**
+ * omap_device_late_idle - idle devices without drivers
+ * @dev: struct device * associated with omap_device
+ * @data: unused
+ *
+ * Check the driver bound status of this device, and idle it
+ * if there is no driver attached.
+ */
+static int __init omap_device_late_idle(struct device *dev, void *data)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct omap_device *od = to_omap_device(pdev);
+
+	if (!od)
+		return 0;
+
+	/*
+	 * If omap_device state is enabled, but has no driver bound,
+	 * idle it.
+	 */
+	if (od->_driver_status != BUS_NOTIFY_BOUND_DRIVER) {
+		if (od->_state == OMAP_DEVICE_STATE_ENABLED) {
+			dev_warn(dev, "%s: enabled but no driver.  Idling\n",
+				 __func__);
+			omap_device_idle(pdev);
+		}
+	}
+
+	return 0;
+}
+
+static int __init omap_device_late_init(void)
+{
+	bus_for_each_dev(&platform_bus_type, NULL, NULL, omap_device_late_idle);
+	return 0;
+}
+late_initcall(omap_device_late_init);
diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c
index 024f3b0..28acb38 100644
--- a/arch/arm/plat-omap/sram.c
+++ b/arch/arm/plat-omap/sram.c
@@ -26,7 +26,6 @@
 #include <asm/mach/map.h>
 
 #include <plat/sram.h>
-#include <plat/board.h>
 #include <plat/cpu.h>
 
 #include "sram.h"
diff --git a/arch/arm/plat-orion/Makefile b/arch/arm/plat-orion/Makefile
index c20ce0f..1251e5b 100644
--- a/arch/arm/plat-orion/Makefile
+++ b/arch/arm/plat-orion/Makefile
@@ -2,9 +2,8 @@
 # Makefile for the linux kernel.
 #
 
-obj-y	:= irq.o pcie.o time.o common.o mpp.o addr-map.o
-obj-m	:=
-obj-n	:=
-obj-	:=
+obj-y                             += addr-map.o
 
-obj-$(CONFIG_GENERIC_GPIO) += gpio.o
+orion-gpio-$(CONFIG_GENERIC_GPIO) += gpio.o
+obj-$(CONFIG_PLAT_ORION_LEGACY)   += irq.o pcie.o time.o common.o mpp.o
+obj-$(CONFIG_PLAT_ORION_LEGACY)   += $(orion-gpio-y)
diff --git a/arch/arm/plat-orion/addr-map.c b/arch/arm/plat-orion/addr-map.c
index 367ca89..a7b8060 100644
--- a/arch/arm/plat-orion/addr-map.c
+++ b/arch/arm/plat-orion/addr-map.c
@@ -48,7 +48,7 @@ EXPORT_SYMBOL_GPL(mv_mbus_dram_info);
 static void __init __iomem *
 orion_win_cfg_base(const struct orion_addr_map_cfg *cfg, int win)
 {
-	return (void __iomem *)(cfg->bridge_virt_base + (win << 4));
+	return cfg->bridge_virt_base + (win << 4);
 }
 
 /*
@@ -143,19 +143,16 @@ void __init orion_config_wins(struct orion_addr_map_cfg * cfg,
  * Setup MBUS dram target info.
  */
 void __init orion_setup_cpu_mbus_target(const struct orion_addr_map_cfg *cfg,
-					const u32 ddr_window_cpu_base)
+					const void __iomem *ddr_window_cpu_base)
 {
-	void __iomem *addr;
 	int i;
 	int cs;
 
 	orion_mbus_dram_info.mbus_dram_target_id = TARGET_DDR;
 
-	addr = (void __iomem *)ddr_window_cpu_base;
-
 	for (i = 0, cs = 0; i < 4; i++) {
-		u32 base = readl(addr + DDR_BASE_CS_OFF(i));
-		u32 size = readl(addr + DDR_SIZE_CS_OFF(i));
+		u32 base = readl(ddr_window_cpu_base + DDR_BASE_CS_OFF(i));
+		u32 size = readl(ddr_window_cpu_base + DDR_SIZE_CS_OFF(i));
 
 		/*
 		 * Chip select enabled?
diff --git a/arch/arm/plat-orion/common.c b/arch/arm/plat-orion/common.c
index b8b747a..b8a688c 100644
--- a/arch/arm/plat-orion/common.c
+++ b/arch/arm/plat-orion/common.c
@@ -19,8 +19,8 @@
 #include <linux/mv643xx_eth.h>
 #include <linux/mv643xx_i2c.h>
 #include <net/dsa.h>
-#include <plat/mv_xor.h>
-#include <plat/ehci-orion.h>
+#include <linux/platform_data/dma-mv_xor.h>
+#include <linux/platform_data/usb-ehci-orion.h>
 #include <mach/bridge-regs.h>
 
 /* Create a clkdev entry for a given device/clk */
@@ -86,13 +86,13 @@ static void __init uart_complete(
 	struct platform_device *orion_uart,
 	struct plat_serial8250_port *data,
 	struct resource *resources,
-	unsigned int membase,
+	void __iomem *membase,
 	resource_size_t mapbase,
 	unsigned int irq,
 	struct clk *clk)
 {
 	data->mapbase = mapbase;
-	data->membase = (void __iomem *)membase;
+	data->membase = membase;
 	data->irq = irq;
 	data->uartclk = uart_get_clk_rate(clk);
 	orion_uart->dev.platform_data = data;
@@ -120,7 +120,7 @@ static struct platform_device orion_uart0 = {
 	.id			= PLAT8250_DEV_PLATFORM,
 };
 
-void __init orion_uart0_init(unsigned int membase,
+void __init orion_uart0_init(void __iomem *membase,
 			     resource_size_t mapbase,
 			     unsigned int irq,
 			     struct clk *clk)
@@ -148,7 +148,7 @@ static struct platform_device orion_uart1 = {
 	.id			= PLAT8250_DEV_PLATFORM1,
 };
 
-void __init orion_uart1_init(unsigned int membase,
+void __init orion_uart1_init(void __iomem *membase,
 			     resource_size_t mapbase,
 			     unsigned int irq,
 			     struct clk *clk)
@@ -176,7 +176,7 @@ static struct platform_device orion_uart2 = {
 	.id			= PLAT8250_DEV_PLATFORM2,
 };
 
-void __init orion_uart2_init(unsigned int membase,
+void __init orion_uart2_init(void __iomem *membase,
 			     resource_size_t mapbase,
 			     unsigned int irq,
 			     struct clk *clk)
@@ -204,7 +204,7 @@ static struct platform_device orion_uart3 = {
 	.id			= 3,
 };
 
-void __init orion_uart3_init(unsigned int membase,
+void __init orion_uart3_init(void __iomem *membase,
 			     resource_size_t mapbase,
 			     unsigned int irq,
 			     struct clk *clk)
diff --git a/arch/arm/plat-orion/gpio.c b/arch/arm/plat-orion/gpio.c
index dfda74f..c29ee7e 100644
--- a/arch/arm/plat-orion/gpio.c
+++ b/arch/arm/plat-orion/gpio.c
@@ -23,7 +23,7 @@
 #include <linux/of.h>
 #include <linux/of_irq.h>
 #include <linux/of_address.h>
-#include <plat/gpio.h>
+#include <plat/orion-gpio.h>
 
 /*
  * GPIO unit register offsets.
diff --git a/arch/arm/plat-orion/include/plat/addr-map.h b/arch/arm/plat-orion/include/plat/addr-map.h
index fd556f7..ec63e4a 100644
--- a/arch/arm/plat-orion/include/plat/addr-map.h
+++ b/arch/arm/plat-orion/include/plat/addr-map.h
@@ -16,7 +16,7 @@ extern struct mbus_dram_target_info orion_mbus_dram_info;
 struct orion_addr_map_cfg {
 	const int num_wins;	/* Total number of windows */
 	const int remappable_wins;
-	const u32 bridge_virt_base;
+	void __iomem *bridge_virt_base;
 
 	/* If NULL, the default cpu_win_can_remap will be used, using
 	   the value in remappable_wins */
@@ -49,5 +49,5 @@ void __init orion_setup_cpu_win(const struct orion_addr_map_cfg *cfg,
 				const u8 attr, const int remap);
 
 void __init orion_setup_cpu_mbus_target(const struct orion_addr_map_cfg *cfg,
-					const u32 ddr_window_cpu_base);
+					const void __iomem *ddr_window_cpu_base);
 #endif
diff --git a/arch/arm/plat-orion/include/plat/audio.h b/arch/arm/plat-orion/include/plat/audio.h
deleted file mode 100644
index d6a55bd..0000000
--- a/arch/arm/plat-orion/include/plat/audio.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __PLAT_AUDIO_H
-#define __PLAT_AUDIO_H
-
-struct kirkwood_asoc_platform_data {
-	int burst;
-};
-#endif
diff --git a/arch/arm/plat-orion/include/plat/common.h b/arch/arm/plat-orion/include/plat/common.h
index ae2377e..6bbc3fe 100644
--- a/arch/arm/plat-orion/include/plat/common.h
+++ b/arch/arm/plat-orion/include/plat/common.h
@@ -13,22 +13,22 @@
 
 struct dsa_platform_data;
 
-void __init orion_uart0_init(unsigned int membase,
+void __init orion_uart0_init(void __iomem *membase,
 			     resource_size_t mapbase,
 			     unsigned int irq,
 			     struct clk *clk);
 
-void __init orion_uart1_init(unsigned int membase,
+void __init orion_uart1_init(void __iomem *membase,
 			     resource_size_t mapbase,
 			     unsigned int irq,
 			     struct clk *clk);
 
-void __init orion_uart2_init(unsigned int membase,
+void __init orion_uart2_init(void __iomem *membase,
 			     resource_size_t mapbase,
 			     unsigned int irq,
 			     struct clk *clk);
 
-void __init orion_uart3_init(unsigned int membase,
+void __init orion_uart3_init(void __iomem *membase,
 			     resource_size_t mapbase,
 			     unsigned int irq,
 			     struct clk *clk);
diff --git a/arch/arm/plat-orion/include/plat/ehci-orion.h b/arch/arm/plat-orion/include/plat/ehci-orion.h
deleted file mode 100644
index 6fc78e4..0000000
--- a/arch/arm/plat-orion/include/plat/ehci-orion.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * arch/arm/plat-orion/include/plat/ehci-orion.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 __PLAT_EHCI_ORION_H
-#define __PLAT_EHCI_ORION_H
-
-#include <linux/mbus.h>
-
-enum orion_ehci_phy_ver {
-	EHCI_PHY_ORION,
-	EHCI_PHY_DD,
-	EHCI_PHY_KW,
-	EHCI_PHY_NA,
-};
-
-struct orion_ehci_data {
-	enum orion_ehci_phy_ver phy_version;
-};
-
-
-#endif
diff --git a/arch/arm/plat-orion/include/plat/gpio.h b/arch/arm/plat-orion/include/plat/gpio.h
deleted file mode 100644
index 81c6fc8..0000000
--- a/arch/arm/plat-orion/include/plat/gpio.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * arch/arm/plat-orion/include/plat/gpio.h
- *
- * Marvell Orion SoC GPIO handling.
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2.  This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#ifndef __PLAT_GPIO_H
-#define __PLAT_GPIO_H
-
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/irqdomain.h>
-/*
- * Orion-specific GPIO API extensions.
- */
-void orion_gpio_set_unused(unsigned pin);
-void orion_gpio_set_blink(unsigned pin, int blink);
-int orion_gpio_led_blink_set(unsigned gpio, int state,
-	unsigned long *delay_on, unsigned long *delay_off);
-
-#define GPIO_INPUT_OK		(1 << 0)
-#define GPIO_OUTPUT_OK		(1 << 1)
-void orion_gpio_set_valid(unsigned pin, int mode);
-
-/* Initialize gpiolib. */
-void __init orion_gpio_init(struct device_node *np,
-			    int gpio_base, int ngpio,
-			    void __iomem *base, int mask_offset,
-			    int secondary_irq_base,
-			    int irq[4]);
-
-void __init orion_gpio_of_init(int irq_gpio_base);
-#endif
diff --git a/arch/arm/plat-orion/include/plat/mpp.h b/arch/arm/plat-orion/include/plat/mpp.h
index 723adce..254552f 100644
--- a/arch/arm/plat-orion/include/plat/mpp.h
+++ b/arch/arm/plat-orion/include/plat/mpp.h
@@ -29,6 +29,6 @@
 #define MPP_OUTPUT_MASK		GENERIC_MPP(0, 0x0, 0, 1)
 
 void __init orion_mpp_conf(unsigned int *mpp_list, unsigned int variant_mask,
-			   unsigned int mpp_max, unsigned int dev_bus);
+			   unsigned int mpp_max, void __iomem *dev_bus);
 
 #endif
diff --git a/arch/arm/plat-orion/include/plat/mv_xor.h b/arch/arm/plat-orion/include/plat/mv_xor.h
deleted file mode 100644
index 2ba1f7d..0000000
--- a/arch/arm/plat-orion/include/plat/mv_xor.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * arch/arm/plat-orion/include/plat/mv_xor.h
- *
- * Marvell XOR platform device data definition file.
- */
-
-#ifndef __PLAT_MV_XOR_H
-#define __PLAT_MV_XOR_H
-
-#include <linux/dmaengine.h>
-#include <linux/mbus.h>
-
-#define MV_XOR_SHARED_NAME	"mv_xor_shared"
-#define MV_XOR_NAME		"mv_xor"
-
-struct mv_xor_platform_data {
-	struct platform_device		*shared;
-	int				hw_id;
-	dma_cap_mask_t			cap_mask;
-	size_t				pool_size;
-};
-
-
-#endif
diff --git a/arch/arm/plat-orion/include/plat/mvsdio.h b/arch/arm/plat-orion/include/plat/mvsdio.h
deleted file mode 100644
index 1190efe..0000000
--- a/arch/arm/plat-orion/include/plat/mvsdio.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * 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 {
-	unsigned int clock;
-	int gpio_card_detect;
-	int gpio_write_protect;
-};
-
-#endif
diff --git a/arch/arm/plat-orion/include/plat/orion-gpio.h b/arch/arm/plat-orion/include/plat/orion-gpio.h
new file mode 100644
index 0000000..614dcac
--- /dev/null
+++ b/arch/arm/plat-orion/include/plat/orion-gpio.h
@@ -0,0 +1,37 @@
+/*
+ * arch/arm/plat-orion/include/plat/orion-gpio.h
+ *
+ * Marvell Orion SoC GPIO handling.
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef __PLAT_GPIO_H
+#define __PLAT_GPIO_H
+
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/irqdomain.h>
+/*
+ * Orion-specific GPIO API extensions.
+ */
+void orion_gpio_set_unused(unsigned pin);
+void orion_gpio_set_blink(unsigned pin, int blink);
+int orion_gpio_led_blink_set(unsigned gpio, int state,
+	unsigned long *delay_on, unsigned long *delay_off);
+
+#define GPIO_INPUT_OK		(1 << 0)
+#define GPIO_OUTPUT_OK		(1 << 1)
+void orion_gpio_set_valid(unsigned pin, int mode);
+
+/* Initialize gpiolib. */
+void __init orion_gpio_init(struct device_node *np,
+			    int gpio_base, int ngpio,
+			    void __iomem *base, int mask_offset,
+			    int secondary_irq_base,
+			    int irq[4]);
+
+void __init orion_gpio_of_init(int irq_gpio_base);
+#endif
diff --git a/arch/arm/plat-orion/include/plat/orion_nand.h b/arch/arm/plat-orion/include/plat/orion_nand.h
deleted file mode 100644
index 9f3c180..0000000
--- a/arch/arm/plat-orion/include/plat/orion_nand.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * arch/arm/plat-orion/include/plat/orion_nand.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 __PLAT_ORION_NAND_H
-#define __PLAT_ORION_NAND_H
-
-/*
- * Device bus NAND private data
- */
-struct orion_nand_data {
-	struct mtd_partition *parts;
-	int (*dev_ready)(struct mtd_info *mtd);
-	u32 nr_parts;
-	u8 ale;		/* address line number connected to ALE */
-	u8 cle;		/* address line number connected to CLE */
-	u8 width;	/* buswidth */
-	u8 chip_delay;
-};
-
-
-#endif
diff --git a/arch/arm/plat-orion/include/plat/time.h b/arch/arm/plat-orion/include/plat/time.h
index 4d5f1f6..07527e4 100644
--- a/arch/arm/plat-orion/include/plat/time.h
+++ b/arch/arm/plat-orion/include/plat/time.h
@@ -11,9 +11,9 @@
 #ifndef __PLAT_TIME_H
 #define __PLAT_TIME_H
 
-void orion_time_set_base(u32 timer_base);
+void orion_time_set_base(void __iomem *timer_base);
 
-void orion_time_init(u32 bridge_base, u32 bridge_timer1_clr_mask,
+void orion_time_init(void __iomem *bridge_base, u32 bridge_timer1_clr_mask,
 		     unsigned int irq, unsigned int tclk);
 
 
diff --git a/arch/arm/plat-orion/irq.c b/arch/arm/plat-orion/irq.c
index d751964..1867944 100644
--- a/arch/arm/plat-orion/irq.c
+++ b/arch/arm/plat-orion/irq.c
@@ -16,7 +16,7 @@
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 #include <plat/irq.h>
-#include <plat/gpio.h>
+#include <plat/orion-gpio.h>
 
 void __init orion_irq_init(unsigned int irq_start, void __iomem *maskaddr)
 {
diff --git a/arch/arm/plat-orion/mpp.c b/arch/arm/plat-orion/mpp.c
index 3b1e17b..e686fe7 100644
--- a/arch/arm/plat-orion/mpp.c
+++ b/arch/arm/plat-orion/mpp.c
@@ -14,18 +14,19 @@
 #include <linux/io.h>
 #include <linux/gpio.h>
 #include <mach/hardware.h>
+#include <plat/orion-gpio.h>
 #include <plat/mpp.h>
 
 /* Address of the ith MPP control register */
-static __init unsigned long mpp_ctrl_addr(unsigned int i,
-					  unsigned long dev_bus)
+static __init void __iomem *mpp_ctrl_addr(unsigned int i,
+					  void __iomem *dev_bus)
 {
 	return dev_bus + (i) * 4;
 }
 
 
 void __init orion_mpp_conf(unsigned int *mpp_list, unsigned int variant_mask,
-			   unsigned int mpp_max, unsigned int dev_bus)
+			   unsigned int mpp_max, void __iomem *dev_bus)
 {
 	unsigned int mpp_nr_regs = (1 + mpp_max/8);
 	u32 mpp_ctrl[mpp_nr_regs];
diff --git a/arch/arm/plat-orion/time.c b/arch/arm/plat-orion/time.c
index 1ed8d13..0f4fa86 100644
--- a/arch/arm/plat-orion/time.c
+++ b/arch/arm/plat-orion/time.c
@@ -180,13 +180,13 @@ static struct irqaction orion_timer_irq = {
 };
 
 void __init
-orion_time_set_base(u32 _timer_base)
+orion_time_set_base(void __iomem *_timer_base)
 {
-	timer_base = (void __iomem *)_timer_base;
+	timer_base = _timer_base;
 }
 
 void __init
-orion_time_init(u32 _bridge_base, u32 _bridge_timer1_clr_mask,
+orion_time_init(void __iomem *_bridge_base, u32 _bridge_timer1_clr_mask,
 		unsigned int irq, unsigned int tclk)
 {
 	u32 u;
@@ -194,7 +194,7 @@ orion_time_init(u32 _bridge_base, u32 _bridge_timer1_clr_mask,
 	/*
 	 * Set SoC-specific data.
 	 */
-	bridge_base = (void __iomem *)_bridge_base;
+	bridge_base = _bridge_base;
 	bridge_timer1_clr_mask = _bridge_timer1_clr_mask;
 
 	ticks_per_jiffy = (tclk + HZ/2) / HZ;
diff --git a/arch/arm/plat-pxa/include/plat/pxa27x_keypad.h b/arch/arm/plat-pxa/include/plat/pxa27x_keypad.h
deleted file mode 100644
index 5ce8d5e..0000000
--- a/arch/arm/plat-pxa/include/plat/pxa27x_keypad.h
+++ /dev/null
@@ -1,73 +0,0 @@
-#ifndef __ASM_ARCH_PXA27x_KEYPAD_H
-#define __ASM_ARCH_PXA27x_KEYPAD_H
-
-#include <linux/input.h>
-#include <linux/input/matrix_keypad.h>
-
-#define MAX_MATRIX_KEY_ROWS	(8)
-#define MAX_MATRIX_KEY_COLS	(8)
-#define MATRIX_ROW_SHIFT	(3)
-#define MAX_DIRECT_KEY_NUM	(8)
-
-/* pxa3xx keypad platform specific parameters
- *
- * NOTE:
- * 1. direct_key_num indicates the number of keys in the direct keypad
- *    _plus_ the number of rotary-encoder sensor inputs,  this can be
- *    left as 0 if only rotary encoders are enabled,  the driver will
- *    automatically calculate this
- *
- * 2. direct_key_map is the key code map for the direct keys, if rotary
- *    encoder(s) are enabled, direct key 0/1(2/3) will be ignored
- *
- * 3. rotary can be either interpreted as a relative input event (e.g.
- *    REL_WHEEL/REL_HWHEEL) or specific keys (e.g. UP/DOWN/LEFT/RIGHT)
- *
- * 4. matrix key and direct key will use the same debounce_interval by
- *    default, which should be sufficient in most cases
- *
- * pxa168 keypad platform specific parameter
- *
- * NOTE:
- * clear_wakeup_event callback is a workaround required to clear the
- * keypad interrupt. The keypad wake must be cleared in addition to
- * reading the MI/DI bits in the KPC register.
- */
-struct pxa27x_keypad_platform_data {
-
-	/* code map for the matrix keys */
-	unsigned int	matrix_key_rows;
-	unsigned int	matrix_key_cols;
-	unsigned int	*matrix_key_map;
-	int		matrix_key_map_size;
-
-	/* direct keys */
-	int		direct_key_num;
-	unsigned int	direct_key_map[MAX_DIRECT_KEY_NUM];
-	/* the key output may be low active */
-	int		direct_key_low_active;
-	/* give board a chance to choose the start direct key */
-	unsigned int	direct_key_mask;
-
-	/* rotary encoders 0 */
-	int		enable_rotary0;
-	int		rotary0_rel_code;
-	int		rotary0_up_key;
-	int		rotary0_down_key;
-
-	/* rotary encoders 1 */
-	int		enable_rotary1;
-	int		rotary1_rel_code;
-	int		rotary1_up_key;
-	int		rotary1_down_key;
-
-	/* key debounce interval */
-	unsigned int	debounce_interval;
-
-	/* clear wakeup event requirement for pxa168 */
-	void		(*clear_wakeup_event)(void);
-};
-
-extern void pxa_set_keypad_info(struct pxa27x_keypad_platform_data *info);
-
-#endif /* __ASM_ARCH_PXA27x_KEYPAD_H */
diff --git a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
deleted file mode 100644
index c42f39f..0000000
--- a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
+++ /dev/null
@@ -1,79 +0,0 @@
-#ifndef __ASM_ARCH_PXA3XX_NAND_H
-#define __ASM_ARCH_PXA3XX_NAND_H
-
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/partitions.h>
-
-struct pxa3xx_nand_timing {
-	unsigned int	tCH;  /* Enable signal hold time */
-	unsigned int	tCS;  /* Enable signal setup time */
-	unsigned int	tWH;  /* ND_nWE high duration */
-	unsigned int	tWP;  /* ND_nWE pulse time */
-	unsigned int	tRH;  /* ND_nRE high duration */
-	unsigned int	tRP;  /* ND_nRE pulse width */
-	unsigned int	tR;   /* ND_nWE high to ND_nRE low for read */
-	unsigned int	tWHR; /* ND_nWE high to ND_nRE low for status read */
-	unsigned int	tAR;  /* ND_ALE low to ND_nRE low delay */
-};
-
-struct pxa3xx_nand_cmdset {
-	uint16_t	read1;
-	uint16_t	read2;
-	uint16_t	program;
-	uint16_t	read_status;
-	uint16_t	read_id;
-	uint16_t	erase;
-	uint16_t	reset;
-	uint16_t	lock;
-	uint16_t	unlock;
-	uint16_t	lock_status;
-};
-
-struct pxa3xx_nand_flash {
-	char		*name;
-	uint32_t	chip_id;
-	unsigned int	page_per_block; /* Pages per block (PG_PER_BLK) */
-	unsigned int	page_size;	/* Page size in bytes (PAGE_SZ) */
-	unsigned int	flash_width;	/* Width of Flash memory (DWIDTH_M) */
-	unsigned int	dfc_width;	/* Width of flash controller(DWIDTH_C) */
-	unsigned int	num_blocks;	/* Number of physical blocks in Flash */
-
-	struct pxa3xx_nand_timing *timing;	/* NAND Flash timing */
-};
-
-/*
- * Current pxa3xx_nand controller has two chip select which
- * both be workable.
- *
- * Notice should be taken that:
- * When you want to use this feature, you should not enable the
- * keep configuration feature, for two chip select could be
- * attached with different nand chip. The different page size
- * and timing requirement make the keep configuration impossible.
- */
-
-/* The max num of chip select current support */
-#define NUM_CHIP_SELECT		(2)
-struct pxa3xx_nand_platform_data {
-
-	/* the data flash bus is shared between the Static Memory
-	 * Controller and the Data Flash Controller,  the arbiter
-	 * controls the ownership of the bus
-	 */
-	int	enable_arbiter;
-
-	/* allow platform code to keep OBM/bootloader defined NFC config */
-	int	keep_config;
-
-	/* indicate how many chip selects will be used */
-	int	num_cs;
-
-	const struct mtd_partition		*parts[NUM_CHIP_SELECT];
-	unsigned int				nr_parts[NUM_CHIP_SELECT];
-
-	const struct pxa3xx_nand_flash * 	flash;
-	size_t					num_flash;
-};
-
-extern void pxa3xx_set_nand_info(struct pxa3xx_nand_platform_data *info);
-#endif /* __ASM_ARCH_PXA3XX_NAND_H */
diff --git a/arch/arm/plat-samsung/clock.c b/arch/arm/plat-samsung/clock.c
index d1116e2..012bbd0 100644
--- a/arch/arm/plat-samsung/clock.c
+++ b/arch/arm/plat-samsung/clock.c
@@ -119,7 +119,7 @@ void clk_disable(struct clk *clk)
 
 unsigned long clk_get_rate(struct clk *clk)
 {
-	if (IS_ERR(clk))
+	if (IS_ERR_OR_NULL(clk))
 		return 0;
 
 	if (clk->rate != 0)
@@ -136,7 +136,7 @@ unsigned long clk_get_rate(struct clk *clk)
 
 long clk_round_rate(struct clk *clk, unsigned long rate)
 {
-	if (!IS_ERR(clk) && clk->ops && clk->ops->round_rate)
+	if (!IS_ERR_OR_NULL(clk) && clk->ops && clk->ops->round_rate)
 		return (clk->ops->round_rate)(clk, rate);
 
 	return rate;
@@ -147,7 +147,7 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
 	unsigned long flags;
 	int ret;
 
-	if (IS_ERR(clk))
+	if (IS_ERR_OR_NULL(clk))
 		return -EINVAL;
 
 	/* We do not default just do a clk->rate = rate as
@@ -177,7 +177,7 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
 	unsigned long flags;
 	int ret = 0;
 
-	if (IS_ERR(clk))
+	if (IS_ERR_OR_NULL(clk) || IS_ERR_OR_NULL(parent))
 		return -EINVAL;
 
 	spin_lock_irqsave(&clocks_lock, flags);
diff --git a/arch/arm/plat-samsung/devs.c b/arch/arm/plat-samsung/devs.c
index fc49f3d..03f654d 100644
--- a/arch/arm/plat-samsung/devs.c
+++ b/arch/arm/plat-samsung/devs.c
@@ -35,7 +35,6 @@
 #include <media/s5p_hdmi.h>
 
 #include <asm/irq.h>
-#include <asm/pmu.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
@@ -48,24 +47,25 @@
 #include <plat/cpu.h>
 #include <plat/devs.h>
 #include <plat/adc.h>
-#include <plat/ata.h>
-#include <plat/ehci.h>
+#include <linux/platform_data/ata-samsung_cf.h>
+#include <linux/platform_data/usb-ehci-s5p.h>
 #include <plat/fb.h>
 #include <plat/fb-s3c2410.h>
-#include <plat/hwmon.h>
-#include <plat/iic.h>
+#include <plat/hdmi.h>
+#include <linux/platform_data/hwmon-s3c.h>
+#include <linux/platform_data/i2c-s3c2410.h>
 #include <plat/keypad.h>
-#include <plat/mci.h>
-#include <plat/nand.h>
+#include <linux/platform_data/mmc-s3cmci.h>
+#include <linux/platform_data/mtd-nand-s3c2410.h>
 #include <plat/sdhci.h>
-#include <plat/ts.h>
-#include <plat/udc.h>
-#include <plat/usb-control.h>
+#include <linux/platform_data/touchscreen-s3c2410.h>
+#include <linux/platform_data/usb-s3c2410_udc.h>
+#include <linux/platform_data/usb-ohci-s3c2410.h>
 #include <plat/usb-phy.h>
 #include <plat/regs-iic.h>
 #include <plat/regs-serial.h>
 #include <plat/regs-spi.h>
-#include <plat/s3c64xx-spi.h>
+#include <linux/platform_data/spi-s3c64xx.h>
 
 static u64 samsung_device_dma_mask = DMA_BIT_MASK(32);
 
@@ -763,7 +763,7 @@ void __init s5p_i2c_hdmiphy_set_platdata(struct s3c2410_platform_i2c *pd)
 			       &s5p_device_i2c_hdmiphy);
 }
 
-struct s5p_hdmi_platform_data s5p_hdmi_def_platdata;
+static struct s5p_hdmi_platform_data s5p_hdmi_def_platdata;
 
 void __init s5p_hdmi_set_platdata(struct i2c_board_info *hdmiphy_info,
 				  struct i2c_board_info *mhl_info, int mhl_bus)
@@ -1132,7 +1132,7 @@ static struct resource s5p_pmu_resource[] = {
 
 static struct platform_device s5p_device_pmu = {
 	.name		= "arm-pmu",
-	.id		= ARM_PMU_DEVICE_CPU,
+	.id		= -1,
 	.num_resources	= ARRAY_SIZE(s5p_pmu_resource),
 	.resource	= s5p_pmu_resource,
 };
@@ -1591,6 +1591,8 @@ struct platform_device s3c64xx_device_spi1 = {
 void __init s3c64xx_spi1_set_platdata(int (*cfg_gpio)(void), int src_clk_nr,
 						int num_cs)
 {
+	struct s3c64xx_spi_info pd;
+
 	/* Reject invalid configuration */
 	if (!num_cs || src_clk_nr < 0) {
 		pr_err("%s: Invalid SPI configuration\n", __func__);
diff --git a/arch/arm/plat-samsung/dma-ops.c b/arch/arm/plat-samsung/dma-ops.c
index c38d754..d088afa 100644
--- a/arch/arm/plat-samsung/dma-ops.c
+++ b/arch/arm/plat-samsung/dma-ops.c
@@ -91,7 +91,8 @@ static int samsung_dmadev_prepare(unsigned ch,
 		break;
 	case DMA_CYCLIC:
 		desc = dmaengine_prep_dma_cyclic(chan, param->buf,
-			param->len, param->period, param->direction);
+			param->len, param->period, param->direction,
+			DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
 		break;
 	default:
 		dev_err(&chan->dev->device, "unsupported format\n");
diff --git a/arch/arm/plat-samsung/include/plat/ata.h b/arch/arm/plat-samsung/include/plat/ata.h
deleted file mode 100644
index 2a3855a..0000000
--- a/arch/arm/plat-samsung/include/plat/ata.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/* linux/arch/arm/plat-samsung/include/plat/ata.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * Samsung CF-ATA platform_device info
- *
- * This program is free software; you can 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_ATA_H
-#define __ASM_PLAT_ATA_H __FILE__
-
-/**
- * struct s3c_ide_platdata - S3C IDE driver platform data.
- * @setup_gpio: Setup the external GPIO pins to the right state for data
- * transfer in true-ide mode.
- */
-struct s3c_ide_platdata {
-	void (*setup_gpio)(void);
-};
-
-/*
- * s3c_ide_set_platdata() - Setup the platform specifc data for IDE driver.
- * @pdata: Platform data for IDE driver.
- */
-extern void s3c_ide_set_platdata(struct s3c_ide_platdata *pdata);
-
-/* architecture-specific IDE configuration */
-extern void s3c64xx_ide_setup_gpio(void);
-extern void s5pc100_ide_setup_gpio(void);
-extern void s5pv210_ide_setup_gpio(void);
-
-#endif /*__ASM_PLAT_ATA_H */
diff --git a/arch/arm/plat-samsung/include/plat/audio-simtec.h b/arch/arm/plat-samsung/include/plat/audio-simtec.h
deleted file mode 100644
index 376af52..0000000
--- a/arch/arm/plat-samsung/include/plat/audio-simtec.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/* arch/arm/plat-samsung/include/plat/audio-simtec.h
- *
- * Copyright 2008 Simtec Electronics
- *	http://armlinux.simtec.co.uk/
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Simtec Audio support.
-*/
-
-/**
- * struct s3c24xx_audio_simtec_pdata - platform data for simtec audio
- * @use_mpllin: Select codec clock from MPLLin
- * @output_cdclk: Need to output CDCLK to the codec
- * @have_mic: Set if we have a MIC socket
- * @have_lout: Set if we have a LineOut socket
- * @amp_gpio: GPIO pin to enable the AMP
- * @amp_gain: Option GPIO to control AMP gain
- */
-struct s3c24xx_audio_simtec_pdata {
-	unsigned int	use_mpllin:1;
-	unsigned int	output_cdclk:1;
-
-	unsigned int	have_mic:1;
-	unsigned int	have_lout:1;
-
-	int		amp_gpio;
-	int		amp_gain[2];
-
-	void	(*startup)(void);
-};
diff --git a/arch/arm/plat-samsung/include/plat/audio.h b/arch/arm/plat-samsung/include/plat/audio.h
deleted file mode 100644
index aa9875f..0000000
--- a/arch/arm/plat-samsung/include/plat/audio.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/* arch/arm/plat-samsung/include/plat/audio.h
- *
- * Copyright (c) 2009 Samsung Electronics Co. Ltd
- * Author: Jaswinder Singh <jassi.brar@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-/* The machine init code calls s3c*_ac97_setup_gpio with
- * one of these defines in order to select appropriate bank
- * of GPIO for AC97 pins
- */
-#define S3C64XX_AC97_GPD  0
-#define S3C64XX_AC97_GPE  1
-extern void s3c64xx_ac97_setup_gpio(int);
-
-/*
- * The machine init code calls s5p*_spdif_setup_gpio with
- * one of these defines in order to select appropriate bank
- * of GPIO for S/PDIF pins
- */
-#define S5PC100_SPDIF_GPD  0
-#define S5PC100_SPDIF_GPG3 1
-extern void s5pc100_spdif_setup_gpio(int);
-
-struct samsung_i2s {
-/* If the Primary DAI has 5.1 Channels */
-#define QUIRK_PRI_6CHAN		(1 << 0)
-/* If the I2S block has a Stereo Overlay Channel */
-#define QUIRK_SEC_DAI		(1 << 1)
-/*
- * If the I2S block has no internal prescalar or MUX (I2SMOD[10] bit)
- * The Machine driver must provide suitably set clock to the I2S block.
- */
-#define QUIRK_NO_MUXPSR		(1 << 2)
-#define QUIRK_NEED_RSTCLR	(1 << 3)
-	/* Quirks of the I2S controller */
-	u32 quirks;
-
-	/*
-	 * Array of clock names that can be used to generate I2S signals.
-	 * Also corresponds to clocks of I2SMOD[10]
-	 */
-	const char **src_clk;
-	dma_addr_t idma_addr;
-};
-
-/**
- * struct s3c_audio_pdata - common platform data for audio device drivers
- * @cfg_gpio: Callback function to setup mux'ed pins in I2S/PCM/AC97 mode
- */
-struct s3c_audio_pdata {
-	int (*cfg_gpio)(struct platform_device *);
-	union {
-		struct samsung_i2s i2s;
-	} type;
-};
diff --git a/arch/arm/plat-samsung/include/plat/ehci.h b/arch/arm/plat-samsung/include/plat/ehci.h
deleted file mode 100644
index 5f28cae..0000000
--- a/arch/arm/plat-samsung/include/plat/ehci.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 2011 Samsung Electronics Co.Ltd
- * Author: Joonyoung Shim <jy0922.shim@samsung.com>
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-
-#ifndef __PLAT_SAMSUNG_EHCI_H
-#define __PLAT_SAMSUNG_EHCI_H __FILE__
-
-struct s5p_ehci_platdata {
-	int (*phy_init)(struct platform_device *pdev, int type);
-	int (*phy_exit)(struct platform_device *pdev, int type);
-};
-
-extern void s5p_ehci_set_platdata(struct s5p_ehci_platdata *pd);
-
-#endif /* __PLAT_SAMSUNG_EHCI_H */
diff --git a/arch/arm/plat-samsung/include/plat/gpio-fns.h b/arch/arm/plat-samsung/include/plat/gpio-fns.h
index bab1392..d1ecef0 100644
--- a/arch/arm/plat-samsung/include/plat/gpio-fns.h
+++ b/arch/arm/plat-samsung/include/plat/gpio-fns.h
@@ -1,98 +1 @@
-/* arch/arm/mach-s3c2410/include/mach/gpio-fns.h
- *
- * Copyright (c) 2003-2009 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C2410 - hardware
- *
- * This program is free software; you can 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 __MACH_GPIO_FNS_H
-#define __MACH_GPIO_FNS_H __FILE__
-
-/* These functions are in the to-be-removed category and it is strongly
- * encouraged not to use these in new code. They will be marked deprecated
- * very soon.
- *
- * Most of the functionality can be either replaced by the gpiocfg calls
- * for the s3c platform or by the generic GPIOlib API.
- *
- * As of 2.6.35-rc, these will be removed, with the few drivers using them
- * either replaced or given a wrapper until the calls can be removed.
-*/
-
 #include <plat/gpio-cfg.h>
-
-static inline void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int cfg)
-{
-	/* 1:1 mapping between cfgpin and setcfg calls at the moment */
-	s3c_gpio_cfgpin(pin, cfg);
-}
-
-/* external functions for GPIO support
- *
- * These allow various different clients to access the same GPIO
- * registers without conflicting. If your driver only owns the entire
- * GPIO register, then it is safe to ioremap/__raw_{read|write} to it.
-*/
-
-extern unsigned int s3c2410_gpio_getcfg(unsigned int pin);
-
-/* s3c2410_gpio_getirq
- *
- * turn the given pin number into the corresponding IRQ number
- *
- * returns:
- *	< 0 = no interrupt for this pin
- *	>=0 = interrupt number for the pin
-*/
-
-extern int s3c2410_gpio_getirq(unsigned int pin);
-
-/* s3c2410_gpio_irqfilter
- *
- * set the irq filtering on the given pin
- *
- * on = 0 => disable filtering
- *      1 => enable filtering
- *
- * config = S3C2410_EINTFLT_PCLK or S3C2410_EINTFLT_EXTCLK orred with
- *          width of filter (0 through 63)
- *
- *
-*/
-
-extern int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on,
-				  unsigned int config);
-
-/* s3c2410_gpio_pullup
- *
- * This call should be replaced with s3c_gpio_setpull().
- *
- * As a note, there is currently no distinction between pull-up and pull-down
- * in the s3c24xx series devices with only an on/off configuration.
- */
-
-/* s3c2410_gpio_pullup
- *
- * configure the pull-up control on the given pin
- *
- * to = 1 => disable the pull-up
- *      0 => enable the pull-up
- *
- * eg;
- *
- *   s3c2410_gpio_pullup(S3C2410_GPB(0), 0);
- *   s3c2410_gpio_pullup(S3C2410_GPE(8), 0);
-*/
-
-extern void s3c2410_gpio_pullup(unsigned int pin, unsigned int to);
-
-extern void s3c2410_gpio_setpin(unsigned int pin, unsigned int to);
-
-extern unsigned int s3c2410_gpio_getpin(unsigned int pin);
-
-#endif /* __MACH_GPIO_FNS_H */
diff --git a/arch/arm/plat-samsung/include/plat/hwmon.h b/arch/arm/plat-samsung/include/plat/hwmon.h
deleted file mode 100644
index c167e44..0000000
--- a/arch/arm/plat-samsung/include/plat/hwmon.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/* linux/arch/arm/plat-s3c/include/plat/hwmon.h
- *
- * Copyright 2005 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *	http://armlinux.simtec.co.uk/
- *
- * S3C - HWMon interface for ADC
- *
- * This program is free software; you can 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_ADC_HWMON_H
-#define __ASM_ARCH_ADC_HWMON_H __FILE__
-
-/**
- * s3c_hwmon_chcfg - channel configuration
- * @name: The name to give this channel.
- * @mult: Multiply the ADC value read by this.
- * @div: Divide the value from the ADC by this.
- *
- * The value read from the ADC is converted to a value that
- * hwmon expects (mV) by result = (value_read * @mult) / @div.
- */
-struct s3c_hwmon_chcfg {
-	const char	*name;
-	unsigned int	mult;
-	unsigned int	div;
-};
-
-/**
- * s3c_hwmon_pdata - HWMON platform data
- * @in: One configuration for each possible channel used.
- */
-struct s3c_hwmon_pdata {
-	struct s3c_hwmon_chcfg	*in[8];
-};
-
-/**
- * s3c_hwmon_set_platdata - Set platform data for S3C HWMON device
- * @pd: Platform data to register to device.
- *
- * Register the given platform data for use with the S3C HWMON device.
- * The call will copy the platform data, so the board definitions can
- * make the structure itself __initdata.
- */
-extern void __init s3c_hwmon_set_platdata(struct s3c_hwmon_pdata *pd);
-
-#endif /* __ASM_ARCH_ADC_HWMON_H */
-
diff --git a/arch/arm/plat-samsung/include/plat/iic.h b/arch/arm/plat-samsung/include/plat/iic.h
deleted file mode 100644
index 51d52e7..0000000
--- a/arch/arm/plat-samsung/include/plat/iic.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/* arch/arm/plat-s3c/include/plat/iic.h
- *
- * Copyright 2004-2009 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C - I2C Controller platform_device info
- *
- * This program is free software; you can 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_IIC_H
-#define __ASM_ARCH_IIC_H __FILE__
-
-#define S3C_IICFLG_FILTER	(1<<0)	/* enable s3c2440 filter */
-
-/**
- *	struct s3c2410_platform_i2c - Platform data for s3c I2C.
- *	@bus_num: The bus number to use (if possible).
- *	@flags: Any flags for the I2C bus (E.g. S3C_IICFLK_FILTER).
- *	@slave_addr: The I2C address for the slave device (if enabled).
- *	@frequency: The desired frequency in Hz of the bus.  This is
- *                  guaranteed to not be exceeded.  If the caller does
- *                  not care, use zero and the driver will select a
- *                  useful default.
- *	@sda_delay: The delay (in ns) applied to SDA edges.
- *	@cfg_gpio: A callback to configure the pins for I2C operation.
- */
-struct s3c2410_platform_i2c {
-	int		bus_num;
-	unsigned int	flags;
-	unsigned int	slave_addr;
-	unsigned long	frequency;
-	unsigned int	sda_delay;
-
-	void	(*cfg_gpio)(struct platform_device *dev);
-};
-
-/**
- * s3c_i2c0_set_platdata - set platform data for i2c0 device
- * @i2c: The platform data to set, or NULL for default data.
- *
- * Register the given platform data for use with the i2c0 device. This
- * call copies the platform data, so the caller can use __initdata for
- * their copy.
- *
- * This call will set cfg_gpio if is null to the default platform
- * implementation.
- *
- * Any user of s3c_device_i2c0 should call this, even if it is with
- * NULL to ensure that the device is given the default platform data
- * as the driver will no longer carry defaults.
- */
-extern void s3c_i2c0_set_platdata(struct s3c2410_platform_i2c *i2c);
-extern void s3c_i2c1_set_platdata(struct s3c2410_platform_i2c *i2c);
-extern void s3c_i2c2_set_platdata(struct s3c2410_platform_i2c *i2c);
-extern void s3c_i2c3_set_platdata(struct s3c2410_platform_i2c *i2c);
-extern void s3c_i2c4_set_platdata(struct s3c2410_platform_i2c *i2c);
-extern void s3c_i2c5_set_platdata(struct s3c2410_platform_i2c *i2c);
-extern void s3c_i2c6_set_platdata(struct s3c2410_platform_i2c *i2c);
-extern void s3c_i2c7_set_platdata(struct s3c2410_platform_i2c *i2c);
-extern void s5p_i2c_hdmiphy_set_platdata(struct s3c2410_platform_i2c *i2c);
-
-/* defined by architecture to configure gpio */
-extern void s3c_i2c0_cfg_gpio(struct platform_device *dev);
-extern void s3c_i2c1_cfg_gpio(struct platform_device *dev);
-extern void s3c_i2c2_cfg_gpio(struct platform_device *dev);
-extern void s3c_i2c3_cfg_gpio(struct platform_device *dev);
-extern void s3c_i2c4_cfg_gpio(struct platform_device *dev);
-extern void s3c_i2c5_cfg_gpio(struct platform_device *dev);
-extern void s3c_i2c6_cfg_gpio(struct platform_device *dev);
-extern void s3c_i2c7_cfg_gpio(struct platform_device *dev);
-
-extern struct s3c2410_platform_i2c default_i2c_data;
-
-#endif /* __ASM_ARCH_IIC_H */
diff --git a/arch/arm/plat-samsung/include/plat/mci.h b/arch/arm/plat-samsung/include/plat/mci.h
deleted file mode 100644
index c42d317..0000000
--- a/arch/arm/plat-samsung/include/plat/mci.h
+++ /dev/null
@@ -1,52 +0,0 @@
-#ifndef _ARCH_MCI_H
-#define _ARCH_MCI_H
-
-/**
- * struct s3c24xx_mci_pdata - sd/mmc controller platform data
- * @no_wprotect: Set this to indicate there is no write-protect switch.
- * @no_detect: Set this if there is no detect switch.
- * @wprotect_invert: Invert the default sense of the write protect switch.
- * @detect_invert: Invert the default sense of the write protect switch.
- * @use_dma: Set to allow the use of DMA.
- * @gpio_detect: GPIO number for the card detect line.
- * @gpio_wprotect: GPIO number for the write protect line.
- * @ocr_avail: The mask of the available power states, non-zero to use.
- * @set_power: Callback to control the power mode.
- *
- * The @gpio_detect is used for card detection when @no_wprotect is unset,
- * and the default sense is that 0 returned from gpio_get_value() means
- * that a card is inserted. If @detect_invert is set, then the value from
- * gpio_get_value() is inverted, which makes 1 mean card inserted.
- *
- * The driver will use @gpio_wprotect to signal whether the card is write
- * protected if @no_wprotect is not set. A 0 returned from gpio_get_value()
- * means the card is read/write, and 1 means read-only. The @wprotect_invert
- * will invert the value returned from gpio_get_value().
- *
- * Card power is set by @ocr_availa, using MCC_VDD_ constants if it is set
- * to a non-zero value, otherwise the default of 3.2-3.4V is used.
- */
-struct s3c24xx_mci_pdata {
-	unsigned int	no_wprotect:1;
-	unsigned int	no_detect:1;
-	unsigned int	wprotect_invert:1;
-	unsigned int	detect_invert:1;	/* set => detect active high */
-	unsigned int	use_dma:1;
-
-	unsigned int	gpio_detect;
-	unsigned int	gpio_wprotect;
-	unsigned long	ocr_avail;
-	void		(*set_power)(unsigned char power_mode,
-				     unsigned short vdd);
-};
-
-/**
- * s3c24xx_mci_set_platdata - set platform data for mmc/sdi device
- * @pdata: The platform data
- *
- * Copy the platform data supplied by @pdata so that this can be marked
- * __initdata.
- */
-extern void s3c24xx_mci_set_platdata(struct s3c24xx_mci_pdata *pdata);
-
-#endif /* _ARCH_NCI_H */
diff --git a/arch/arm/plat-samsung/include/plat/mipi_csis.h b/arch/arm/plat-samsung/include/plat/mipi_csis.h
deleted file mode 100644
index c45b1e8..0000000
--- a/arch/arm/plat-samsung/include/plat/mipi_csis.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2010-2011 Samsung Electronics Co., Ltd.
- *
- * S5P series MIPI CSI slave device 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.
- */
-
-#ifndef __PLAT_SAMSUNG_MIPI_CSIS_H_
-#define __PLAT_SAMSUNG_MIPI_CSIS_H_ __FILE__
-
-struct platform_device;
-
-/**
- * struct s5p_platform_mipi_csis - platform data for S5P MIPI-CSIS driver
- * @clk_rate: bus clock frequency
- * @lanes: number of data lanes used
- * @alignment: data alignment in bits
- * @hs_settle: HS-RX settle time
- * @fixed_phy_vdd: false to enable external D-PHY regulator management in the
- *		   driver or true in case this regulator has no enable function
- * @phy_enable: pointer to a callback controlling D-PHY enable/reset
- */
-struct s5p_platform_mipi_csis {
-	unsigned long clk_rate;
-	u8 lanes;
-	u8 alignment;
-	u8 hs_settle;
-	bool fixed_phy_vdd;
-	int (*phy_enable)(struct platform_device *pdev, bool on);
-};
-
-/**
- * s5p_csis_phy_enable - global MIPI-CSI receiver D-PHY control
- * @pdev: MIPI-CSIS platform device
- * @on: true to enable D-PHY and deassert its reset
- *	false to disable D-PHY
- */
-int s5p_csis_phy_enable(struct platform_device *pdev, bool on);
-
-#endif /* __PLAT_SAMSUNG_MIPI_CSIS_H_ */
diff --git a/arch/arm/plat-samsung/include/plat/nand.h b/arch/arm/plat-samsung/include/plat/nand.h
deleted file mode 100644
index b64115f..0000000
--- a/arch/arm/plat-samsung/include/plat/nand.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/* arch/arm/mach-s3c2410/include/mach/nand.h
- *
- * Copyright (c) 2004 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C2410 - NAND device controller platform_device info
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-/**
- * struct s3c2410_nand_set - define a set of one or more nand chips
- * @disable_ecc:	Entirely disable ECC - Dangerous
- * @flash_bbt: 		Openmoko u-boot can create a Bad Block Table
- *			Setting this flag will allow the kernel to
- *			look for it at boot time and also skip the NAND
- *			scan.
- * @options:		Default value to set into 'struct nand_chip' options.
- * @nr_chips:		Number of chips in this set
- * @nr_partitions:	Number of partitions pointed to by @partitions
- * @name:		Name of set (optional)
- * @nr_map:		Map for low-layer logical to physical chip numbers (option)
- * @partitions:		The mtd partition list
- *
- * define a set of one or more nand chips registered with an unique mtd. Also
- * allows to pass flag to the underlying NAND layer. 'disable_ecc' will trigger
- * a warning at boot time.
- */
-struct s3c2410_nand_set {
-	unsigned int		disable_ecc:1;
-	unsigned int		flash_bbt:1;
-
-	unsigned int		options;
-	int			nr_chips;
-	int			nr_partitions;
-	char			*name;
-	int			*nr_map;
-	struct mtd_partition	*partitions;
-	struct nand_ecclayout	*ecc_layout;
-};
-
-struct s3c2410_platform_nand {
-	/* timing information for controller, all times in nanoseconds */
-
-	int	tacls;	/* time for active CLE/ALE to nWE/nOE */
-	int	twrph0;	/* active time for nWE/nOE */
-	int	twrph1;	/* time for release CLE/ALE from nWE/nOE inactive */
-
-	unsigned int	ignore_unset_ecc:1;
-
-	int			nr_sets;
-	struct s3c2410_nand_set *sets;
-
-	void			(*select_chip)(struct s3c2410_nand_set *,
-					       int chip);
-};
-
-/**
- * s3c_nand_set_platdata() - register NAND platform data.
- * @nand: The NAND platform data to register with s3c_device_nand.
- *
- * This function copies the given NAND platform data, @nand and registers
- * it with the s3c_device_nand. This allows @nand to be __initdata.
-*/
-extern void s3c_nand_set_platdata(struct s3c2410_platform_nand *nand);
diff --git a/arch/arm/plat-samsung/include/plat/regs-fb-v4.h b/arch/arm/plat-samsung/include/plat/regs-fb-v4.h
deleted file mode 100644
index 4c3647f..0000000
--- a/arch/arm/plat-samsung/include/plat/regs-fb-v4.h
+++ /dev/null
@@ -1,159 +0,0 @@
-/* arch/arm/plat-samsung/include/plat/regs-fb-v4.h
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *      http://armlinux.simtec.co.uk/
- *      Ben Dooks <ben@simtec.co.uk>
- *
- * S3C64XX - new-style framebuffer register definitions
- *
- * This is the register set for the new style framebuffer interface
- * found from the S3C2443 onwards and specifically the S3C64XX series
- * S3C6400 and S3C6410.
- *
- * The file contains the cpu specific items which change between whichever
- * architecture is selected. See <plat/regs-fb.h> for the core definitions
- * that are the same.
- *
- * This program is free software; you can 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 the core definitions here, in case we really do need to
- * override them at a later date.
-*/
-
-#include <plat/regs-fb.h>
-
-#define S3C_FB_MAX_WIN (5)  /* number of hardware windows available. */
-#define VIDCON1_FSTATUS_EVEN	(1 << 15)
-
-/* Video timing controls */
-#define VIDTCON0				(0x10)
-#define VIDTCON1				(0x14)
-#define VIDTCON2				(0x18)
-
-/* Window position controls */
-
-#define WINCON(_win)				(0x20 + ((_win) * 4))
-
-/* OSD1 and OSD4 do not have register D */
-
-#define VIDOSD_BASE				(0x40)
-
-#define VIDINTCON0				(0x130)
-
-/* WINCONx */
-
-#define WINCONx_CSCWIDTH_MASK			(0x3 << 26)
-#define WINCONx_CSCWIDTH_SHIFT			(26)
-#define WINCONx_CSCWIDTH_WIDE			(0x0 << 26)
-#define WINCONx_CSCWIDTH_NARROW			(0x3 << 26)
-
-#define WINCONx_ENLOCAL				(1 << 22)
-#define WINCONx_BUFSTATUS			(1 << 21)
-#define WINCONx_BUFSEL				(1 << 20)
-#define WINCONx_BUFAUTOEN			(1 << 19)
-#define WINCONx_YCbCr				(1 << 13)
-
-#define WINCON1_LOCALSEL_CAMIF			(1 << 23)
-
-#define WINCON2_LOCALSEL_CAMIF			(1 << 23)
-#define WINCON2_BLD_PIX				(1 << 6)
-
-#define WINCON2_ALPHA_SEL			(1 << 1)
-#define WINCON2_BPPMODE_MASK			(0xf << 2)
-#define WINCON2_BPPMODE_SHIFT			(2)
-#define WINCON2_BPPMODE_1BPP			(0x0 << 2)
-#define WINCON2_BPPMODE_2BPP			(0x1 << 2)
-#define WINCON2_BPPMODE_4BPP			(0x2 << 2)
-#define WINCON2_BPPMODE_8BPP_1232		(0x4 << 2)
-#define WINCON2_BPPMODE_16BPP_565		(0x5 << 2)
-#define WINCON2_BPPMODE_16BPP_A1555		(0x6 << 2)
-#define WINCON2_BPPMODE_16BPP_I1555		(0x7 << 2)
-#define WINCON2_BPPMODE_18BPP_666		(0x8 << 2)
-#define WINCON2_BPPMODE_18BPP_A1665		(0x9 << 2)
-#define WINCON2_BPPMODE_19BPP_A1666		(0xa << 2)
-#define WINCON2_BPPMODE_24BPP_888		(0xb << 2)
-#define WINCON2_BPPMODE_24BPP_A1887		(0xc << 2)
-#define WINCON2_BPPMODE_25BPP_A1888		(0xd << 2)
-#define WINCON2_BPPMODE_28BPP_A4888		(0xd << 2)
-
-#define WINCON3_BLD_PIX				(1 << 6)
-
-#define WINCON3_ALPHA_SEL			(1 << 1)
-#define WINCON3_BPPMODE_MASK			(0xf << 2)
-#define WINCON3_BPPMODE_SHIFT			(2)
-#define WINCON3_BPPMODE_1BPP			(0x0 << 2)
-#define WINCON3_BPPMODE_2BPP			(0x1 << 2)
-#define WINCON3_BPPMODE_4BPP			(0x2 << 2)
-#define WINCON3_BPPMODE_16BPP_565		(0x5 << 2)
-#define WINCON3_BPPMODE_16BPP_A1555		(0x6 << 2)
-#define WINCON3_BPPMODE_16BPP_I1555		(0x7 << 2)
-#define WINCON3_BPPMODE_18BPP_666		(0x8 << 2)
-#define WINCON3_BPPMODE_18BPP_A1665		(0x9 << 2)
-#define WINCON3_BPPMODE_19BPP_A1666		(0xa << 2)
-#define WINCON3_BPPMODE_24BPP_888		(0xb << 2)
-#define WINCON3_BPPMODE_24BPP_A1887		(0xc << 2)
-#define WINCON3_BPPMODE_25BPP_A1888		(0xd << 2)
-#define WINCON3_BPPMODE_28BPP_A4888		(0xd << 2)
-
-#define VIDINTCON0_FIFIOSEL_WINDOW2		(0x10 << 5)
-#define VIDINTCON0_FIFIOSEL_WINDOW3		(0x20 << 5)
-#define VIDINTCON0_FIFIOSEL_WINDOW4		(0x40 << 5)
-
-#define DITHMODE				(0x170)
-#define WINxMAP(_win)				(0x180 + ((_win) * 4))
-
-
-#define DITHMODE_R_POS_MASK			(0x3 << 5)
-#define DITHMODE_R_POS_SHIFT			(5)
-#define DITHMODE_R_POS_8BIT			(0x0 << 5)
-#define DITHMODE_R_POS_6BIT			(0x1 << 5)
-#define DITHMODE_R_POS_5BIT			(0x2 << 5)
-
-#define DITHMODE_G_POS_MASK			(0x3 << 3)
-#define DITHMODE_G_POS_SHIFT			(3)
-#define DITHMODE_G_POS_8BIT			(0x0 << 3)
-#define DITHMODE_G_POS_6BIT			(0x1 << 3)
-#define DITHMODE_G_POS_5BIT			(0x2 << 3)
-
-#define DITHMODE_B_POS_MASK			(0x3 << 1)
-#define DITHMODE_B_POS_SHIFT			(1)
-#define DITHMODE_B_POS_8BIT			(0x0 << 1)
-#define DITHMODE_B_POS_6BIT			(0x1 << 1)
-#define DITHMODE_B_POS_5BIT			(0x2 << 1)
-
-#define DITHMODE_DITH_EN			(1 << 0)
-
-#define WPALCON					(0x1A0)
-
-/* Palette control */
-/* Note for S5PC100: you can still use those macros on WPALCON (aka WPALCON_L),
- * but make sure that WPALCON_H W2PAL-W4PAL entries are zeroed out */
-#define WPALCON_W4PAL_16BPP_A555		(1 << 8)
-#define WPALCON_W3PAL_16BPP_A555		(1 << 7)
-#define WPALCON_W2PAL_16BPP_A555		(1 << 6)
-
-
-/* Notes on per-window bpp settings
- *
- * Value	Win0	 Win1	  Win2	   Win3	    Win 4
- * 0000		1(P)	 1(P)	  1(P)	   1(P)	    1(P)
- * 0001		2(P)	 2(P)     2(P)	   2(P)	    2(P)
- * 0010		4(P)	 4(P)     4(P)	   4(P)     -none-
- * 0011		8(P)	 8(P)     -none-   -none-   -none-
- * 0100		-none-	 8(A232)  8(A232)  -none-   -none-
- * 0101		16(565)	 16(565)  16(565)  16(565)   16(565)
- * 0110		-none-	 16(A555) 16(A555) 16(A555)  16(A555)
- * 0111		16(I555) 16(I565) 16(I555) 16(I555)  16(I555)
- * 1000		18(666)	 18(666)  18(666)  18(666)   18(666)
- * 1001		-none-	 18(A665) 18(A665) 18(A665)  16(A665)
- * 1010		-none-	 19(A666) 19(A666) 19(A666)  19(A666)
- * 1011		24(888)	 24(888)  24(888)  24(888)   24(888)
- * 1100		-none-	 24(A887) 24(A887) 24(A887)  24(A887)
- * 1101		-none-	 25(A888) 25(A888) 25(A888)  25(A888)
- * 1110		-none-	 -none-	  -none-   -none-    -none-
- * 1111		-none-	 -none-   -none-   -none-    -none-
-*/
diff --git a/arch/arm/plat-samsung/include/plat/regs-fb.h b/arch/arm/plat-samsung/include/plat/regs-fb.h
deleted file mode 100644
index 9a78012..0000000
--- a/arch/arm/plat-samsung/include/plat/regs-fb.h
+++ /dev/null
@@ -1,403 +0,0 @@
-/* arch/arm/plat-samsung/include/plat/regs-fb.h
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *      http://armlinux.simtec.co.uk/
- *      Ben Dooks <ben@simtec.co.uk>
- *
- * S3C Platform - new-style framebuffer register definitions
- *
- * This is the register set for the new style framebuffer interface
- * found from the S3C2443 onwards into the S3C2416, S3C2450 and the
- * S3C64XX series such as the S3C6400 and S3C6410.
- *
- * The file does not contain the cpu specific items which are based on
- * whichever architecture is selected, it only contains the core of the
- * register set. See <mach/regs-fb.h> to get the specifics.
- *
- * Note, we changed to using regs-fb.h as it avoids any clashes with
- * the original regs-lcd.h so out of the way of regs-lcd.h as well as
- * indicating the newer block is much more than just an LCD interface.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-/* Please do not include this file directly, use <mach/regs-fb.h> to
- * ensure all the localised SoC support is included as necessary.
-*/
-
-/* VIDCON0 */
-
-#define VIDCON0					(0x00)
-#define VIDCON0_INTERLACE			(1 << 29)
-#define VIDCON0_VIDOUT_MASK			(0x3 << 26)
-#define VIDCON0_VIDOUT_SHIFT			(26)
-#define VIDCON0_VIDOUT_RGB			(0x0 << 26)
-#define VIDCON0_VIDOUT_TV			(0x1 << 26)
-#define VIDCON0_VIDOUT_I80_LDI0			(0x2 << 26)
-#define VIDCON0_VIDOUT_I80_LDI1			(0x3 << 26)
-
-#define VIDCON0_L1_DATA_MASK			(0x7 << 23)
-#define VIDCON0_L1_DATA_SHIFT			(23)
-#define VIDCON0_L1_DATA_16BPP			(0x0 << 23)
-#define VIDCON0_L1_DATA_18BPP16			(0x1 << 23)
-#define VIDCON0_L1_DATA_18BPP9			(0x2 << 23)
-#define VIDCON0_L1_DATA_24BPP			(0x3 << 23)
-#define VIDCON0_L1_DATA_18BPP			(0x4 << 23)
-#define VIDCON0_L1_DATA_16BPP8			(0x5 << 23)
-
-#define VIDCON0_L0_DATA_MASK			(0x7 << 20)
-#define VIDCON0_L0_DATA_SHIFT			(20)
-#define VIDCON0_L0_DATA_16BPP			(0x0 << 20)
-#define VIDCON0_L0_DATA_18BPP16			(0x1 << 20)
-#define VIDCON0_L0_DATA_18BPP9			(0x2 << 20)
-#define VIDCON0_L0_DATA_24BPP			(0x3 << 20)
-#define VIDCON0_L0_DATA_18BPP			(0x4 << 20)
-#define VIDCON0_L0_DATA_16BPP8			(0x5 << 20)
-
-#define VIDCON0_PNRMODE_MASK			(0x3 << 17)
-#define VIDCON0_PNRMODE_SHIFT			(17)
-#define VIDCON0_PNRMODE_RGB			(0x0 << 17)
-#define VIDCON0_PNRMODE_BGR			(0x1 << 17)
-#define VIDCON0_PNRMODE_SERIAL_RGB		(0x2 << 17)
-#define VIDCON0_PNRMODE_SERIAL_BGR		(0x3 << 17)
-
-#define VIDCON0_CLKVALUP			(1 << 16)
-#define VIDCON0_CLKVAL_F_MASK			(0xff << 6)
-#define VIDCON0_CLKVAL_F_SHIFT			(6)
-#define VIDCON0_CLKVAL_F_LIMIT			(0xff)
-#define VIDCON0_CLKVAL_F(_x)			((_x) << 6)
-#define VIDCON0_VLCKFREE			(1 << 5)
-#define VIDCON0_CLKDIR				(1 << 4)
-
-#define VIDCON0_CLKSEL_MASK			(0x3 << 2)
-#define VIDCON0_CLKSEL_SHIFT			(2)
-#define VIDCON0_CLKSEL_HCLK			(0x0 << 2)
-#define VIDCON0_CLKSEL_LCD			(0x1 << 2)
-#define VIDCON0_CLKSEL_27M			(0x3 << 2)
-
-#define VIDCON0_ENVID				(1 << 1)
-#define VIDCON0_ENVID_F				(1 << 0)
-
-#define VIDCON1					(0x04)
-#define VIDCON1_LINECNT_MASK			(0x7ff << 16)
-#define VIDCON1_LINECNT_SHIFT			(16)
-#define VIDCON1_LINECNT_GET(_v)			(((_v) >> 16) & 0x7ff)
-#define VIDCON1_VSTATUS_MASK			(0x3 << 13)
-#define VIDCON1_VSTATUS_SHIFT			(13)
-#define VIDCON1_VSTATUS_VSYNC			(0x0 << 13)
-#define VIDCON1_VSTATUS_BACKPORCH		(0x1 << 13)
-#define VIDCON1_VSTATUS_ACTIVE			(0x2 << 13)
-#define VIDCON1_VSTATUS_FRONTPORCH		(0x0 << 13)
-#define VIDCON1_VCLK_MASK			(0x3 << 9)
-#define VIDCON1_VCLK_HOLD			(0x0 << 9)
-#define VIDCON1_VCLK_RUN			(0x1 << 9)
-
-#define VIDCON1_INV_VCLK			(1 << 7)
-#define VIDCON1_INV_HSYNC			(1 << 6)
-#define VIDCON1_INV_VSYNC			(1 << 5)
-#define VIDCON1_INV_VDEN			(1 << 4)
-
-/* VIDCON2 */
-
-#define VIDCON2					(0x08)
-#define VIDCON2_EN601				(1 << 23)
-#define VIDCON2_TVFMTSEL_SW			(1 << 14)
-
-#define VIDCON2_TVFMTSEL1_MASK			(0x3 << 12)
-#define VIDCON2_TVFMTSEL1_SHIFT			(12)
-#define VIDCON2_TVFMTSEL1_RGB			(0x0 << 12)
-#define VIDCON2_TVFMTSEL1_YUV422		(0x1 << 12)
-#define VIDCON2_TVFMTSEL1_YUV444		(0x2 << 12)
-
-#define VIDCON2_ORGYCbCr			(1 << 8)
-#define VIDCON2_YUVORDCrCb			(1 << 7)
-
-/* PRTCON (S3C6410, S5PC100)
- * Might not be present in the S3C6410 documentation,
- * but tests prove it's there almost for sure; shouldn't hurt in any case.
- */
-#define PRTCON					(0x0c)
-#define PRTCON_PROTECT				(1 << 11)
-
-/* VIDTCON0 */
-
-#define VIDTCON0_VBPDE_MASK			(0xff << 24)
-#define VIDTCON0_VBPDE_SHIFT			(24)
-#define VIDTCON0_VBPDE_LIMIT			(0xff)
-#define VIDTCON0_VBPDE(_x)			((_x) << 24)
-
-#define VIDTCON0_VBPD_MASK			(0xff << 16)
-#define VIDTCON0_VBPD_SHIFT			(16)
-#define VIDTCON0_VBPD_LIMIT			(0xff)
-#define VIDTCON0_VBPD(_x)			((_x) << 16)
-
-#define VIDTCON0_VFPD_MASK			(0xff << 8)
-#define VIDTCON0_VFPD_SHIFT			(8)
-#define VIDTCON0_VFPD_LIMIT			(0xff)
-#define VIDTCON0_VFPD(_x)			((_x) << 8)
-
-#define VIDTCON0_VSPW_MASK			(0xff << 0)
-#define VIDTCON0_VSPW_SHIFT			(0)
-#define VIDTCON0_VSPW_LIMIT			(0xff)
-#define VIDTCON0_VSPW(_x)			((_x) << 0)
-
-/* VIDTCON1 */
-
-#define VIDTCON1_VFPDE_MASK			(0xff << 24)
-#define VIDTCON1_VFPDE_SHIFT			(24)
-#define VIDTCON1_VFPDE_LIMIT			(0xff)
-#define VIDTCON1_VFPDE(_x)			((_x) << 24)
-
-#define VIDTCON1_HBPD_MASK			(0xff << 16)
-#define VIDTCON1_HBPD_SHIFT			(16)
-#define VIDTCON1_HBPD_LIMIT			(0xff)
-#define VIDTCON1_HBPD(_x)			((_x) << 16)
-
-#define VIDTCON1_HFPD_MASK			(0xff << 8)
-#define VIDTCON1_HFPD_SHIFT			(8)
-#define VIDTCON1_HFPD_LIMIT			(0xff)
-#define VIDTCON1_HFPD(_x)			((_x) << 8)
-
-#define VIDTCON1_HSPW_MASK			(0xff << 0)
-#define VIDTCON1_HSPW_SHIFT			(0)
-#define VIDTCON1_HSPW_LIMIT			(0xff)
-#define VIDTCON1_HSPW(_x)			((_x) << 0)
-
-#define VIDTCON2				(0x18)
-#define VIDTCON2_LINEVAL_E(_x)			((((_x) & 0x800) >> 11) << 23)
-#define VIDTCON2_LINEVAL_MASK			(0x7ff << 11)
-#define VIDTCON2_LINEVAL_SHIFT			(11)
-#define VIDTCON2_LINEVAL_LIMIT			(0x7ff)
-#define VIDTCON2_LINEVAL(_x)			(((_x) & 0x7ff) << 11)
-
-#define VIDTCON2_HOZVAL_E(_x)			((((_x) & 0x800) >> 11) << 22)
-#define VIDTCON2_HOZVAL_MASK			(0x7ff << 0)
-#define VIDTCON2_HOZVAL_SHIFT			(0)
-#define VIDTCON2_HOZVAL_LIMIT			(0x7ff)
-#define VIDTCON2_HOZVAL(_x)			(((_x) & 0x7ff) << 0)
-
-/* WINCONx */
-
-
-#define WINCONx_BITSWP				(1 << 18)
-#define WINCONx_BYTSWP				(1 << 17)
-#define WINCONx_HAWSWP				(1 << 16)
-#define WINCONx_WSWP				(1 << 15)
-#define WINCONx_BURSTLEN_MASK			(0x3 << 9)
-#define WINCONx_BURSTLEN_SHIFT			(9)
-#define WINCONx_BURSTLEN_16WORD			(0x0 << 9)
-#define WINCONx_BURSTLEN_8WORD			(0x1 << 9)
-#define WINCONx_BURSTLEN_4WORD			(0x2 << 9)
-
-#define WINCONx_ENWIN				(1 << 0)
-#define WINCON0_BPPMODE_MASK			(0xf << 2)
-#define WINCON0_BPPMODE_SHIFT			(2)
-#define WINCON0_BPPMODE_1BPP			(0x0 << 2)
-#define WINCON0_BPPMODE_2BPP			(0x1 << 2)
-#define WINCON0_BPPMODE_4BPP			(0x2 << 2)
-#define WINCON0_BPPMODE_8BPP_PALETTE		(0x3 << 2)
-#define WINCON0_BPPMODE_16BPP_565		(0x5 << 2)
-#define WINCON0_BPPMODE_16BPP_1555		(0x7 << 2)
-#define WINCON0_BPPMODE_18BPP_666		(0x8 << 2)
-#define WINCON0_BPPMODE_24BPP_888		(0xb << 2)
-
-#define WINCON1_BLD_PIX				(1 << 6)
-
-#define WINCON1_ALPHA_SEL			(1 << 1)
-#define WINCON1_BPPMODE_MASK			(0xf << 2)
-#define WINCON1_BPPMODE_SHIFT			(2)
-#define WINCON1_BPPMODE_1BPP			(0x0 << 2)
-#define WINCON1_BPPMODE_2BPP			(0x1 << 2)
-#define WINCON1_BPPMODE_4BPP			(0x2 << 2)
-#define WINCON1_BPPMODE_8BPP_PALETTE		(0x3 << 2)
-#define WINCON1_BPPMODE_8BPP_1232		(0x4 << 2)
-#define WINCON1_BPPMODE_16BPP_565		(0x5 << 2)
-#define WINCON1_BPPMODE_16BPP_A1555		(0x6 << 2)
-#define WINCON1_BPPMODE_16BPP_I1555		(0x7 << 2)
-#define WINCON1_BPPMODE_18BPP_666		(0x8 << 2)
-#define WINCON1_BPPMODE_18BPP_A1665		(0x9 << 2)
-#define WINCON1_BPPMODE_19BPP_A1666		(0xa << 2)
-#define WINCON1_BPPMODE_24BPP_888		(0xb << 2)
-#define WINCON1_BPPMODE_24BPP_A1887		(0xc << 2)
-#define WINCON1_BPPMODE_25BPP_A1888		(0xd << 2)
-#define WINCON1_BPPMODE_28BPP_A4888		(0xd << 2)
-
-/* S5PV210 */
-#define SHADOWCON				(0x34)
-#define SHADOWCON_WINx_PROTECT(_win)		(1 << (10 + (_win)))
-/* DMA channels (all windows) */
-#define SHADOWCON_CHx_ENABLE(_win)		(1 << (_win))
-/* Local input channels (windows 0-2) */
-#define SHADOWCON_CHx_LOCAL_ENABLE(_win)	(1 << (5 + (_win)))
-
-#define VIDOSDxA_TOPLEFT_X_E(_x)		((((_x) & 0x800) >> 11) << 23)
-#define VIDOSDxA_TOPLEFT_X_MASK			(0x7ff << 11)
-#define VIDOSDxA_TOPLEFT_X_SHIFT		(11)
-#define VIDOSDxA_TOPLEFT_X_LIMIT		(0x7ff)
-#define VIDOSDxA_TOPLEFT_X(_x)			(((_x) & 0x7ff) << 11)
-
-#define VIDOSDxA_TOPLEFT_Y_E(_x)		((((_x) & 0x800) >> 11) << 22)
-#define VIDOSDxA_TOPLEFT_Y_MASK			(0x7ff << 0)
-#define VIDOSDxA_TOPLEFT_Y_SHIFT		(0)
-#define VIDOSDxA_TOPLEFT_Y_LIMIT		(0x7ff)
-#define VIDOSDxA_TOPLEFT_Y(_x)			(((_x) & 0x7ff) << 0)
-
-#define VIDOSDxB_BOTRIGHT_X_E(_x)		((((_x) & 0x800) >> 11) << 23)
-#define VIDOSDxB_BOTRIGHT_X_MASK		(0x7ff << 11)
-#define VIDOSDxB_BOTRIGHT_X_SHIFT		(11)
-#define VIDOSDxB_BOTRIGHT_X_LIMIT		(0x7ff)
-#define VIDOSDxB_BOTRIGHT_X(_x)			(((_x) & 0x7ff) << 11)
-
-#define VIDOSDxB_BOTRIGHT_Y_E(_x)		((((_x) & 0x800) >> 11) << 22)
-#define VIDOSDxB_BOTRIGHT_Y_MASK		(0x7ff << 0)
-#define VIDOSDxB_BOTRIGHT_Y_SHIFT		(0)
-#define VIDOSDxB_BOTRIGHT_Y_LIMIT		(0x7ff)
-#define VIDOSDxB_BOTRIGHT_Y(_x)			(((_x) & 0x7ff) << 0)
-
-/* For VIDOSD[1..4]C */
-#define VIDISD14C_ALPHA0_R(_x)			((_x) << 20)
-#define VIDISD14C_ALPHA0_G_MASK			(0xf << 16)
-#define VIDISD14C_ALPHA0_G_SHIFT		(16)
-#define VIDISD14C_ALPHA0_G_LIMIT		(0xf)
-#define VIDISD14C_ALPHA0_G(_x)			((_x) << 16)
-#define VIDISD14C_ALPHA0_B_MASK			(0xf << 12)
-#define VIDISD14C_ALPHA0_B_SHIFT		(12)
-#define VIDISD14C_ALPHA0_B_LIMIT		(0xf)
-#define VIDISD14C_ALPHA0_B(_x)			((_x) << 12)
-#define VIDISD14C_ALPHA1_R_MASK			(0xf << 8)
-#define VIDISD14C_ALPHA1_R_SHIFT		(8)
-#define VIDISD14C_ALPHA1_R_LIMIT		(0xf)
-#define VIDISD14C_ALPHA1_R(_x)			((_x) << 8)
-#define VIDISD14C_ALPHA1_G_MASK			(0xf << 4)
-#define VIDISD14C_ALPHA1_G_SHIFT		(4)
-#define VIDISD14C_ALPHA1_G_LIMIT		(0xf)
-#define VIDISD14C_ALPHA1_G(_x)			((_x) << 4)
-#define VIDISD14C_ALPHA1_B_MASK			(0xf << 0)
-#define VIDISD14C_ALPHA1_B_SHIFT		(0)
-#define VIDISD14C_ALPHA1_B_LIMIT		(0xf)
-#define VIDISD14C_ALPHA1_B(_x)			((_x) << 0)
-
-/* Video buffer addresses */
-#define VIDW_BUF_START(_buff)			(0xA0 + ((_buff) * 8))
-#define VIDW_BUF_START1(_buff)			(0xA4 + ((_buff) * 8))
-#define VIDW_BUF_END(_buff)			(0xD0 + ((_buff) * 8))
-#define VIDW_BUF_END1(_buff)			(0xD4 + ((_buff) * 8))
-#define VIDW_BUF_SIZE(_buff)			(0x100 + ((_buff) * 4))
-
-#define VIDW_BUF_SIZE_OFFSET_E(_x)		((((_x) & 0x2000) >> 13) << 27)
-#define VIDW_BUF_SIZE_OFFSET_MASK		(0x1fff << 13)
-#define VIDW_BUF_SIZE_OFFSET_SHIFT		(13)
-#define VIDW_BUF_SIZE_OFFSET_LIMIT		(0x1fff)
-#define VIDW_BUF_SIZE_OFFSET(_x)		(((_x) & 0x1fff) << 13)
-
-#define VIDW_BUF_SIZE_PAGEWIDTH_E(_x)		((((_x) & 0x2000) >> 13) << 26)
-#define VIDW_BUF_SIZE_PAGEWIDTH_MASK		(0x1fff << 0)
-#define VIDW_BUF_SIZE_PAGEWIDTH_SHIFT		(0)
-#define VIDW_BUF_SIZE_PAGEWIDTH_LIMIT		(0x1fff)
-#define VIDW_BUF_SIZE_PAGEWIDTH(_x)		(((_x) & 0x1fff) << 0)
-
-/* Interrupt controls and status */
-
-#define VIDINTCON0_FIFOINTERVAL_MASK		(0x3f << 20)
-#define VIDINTCON0_FIFOINTERVAL_SHIFT		(20)
-#define VIDINTCON0_FIFOINTERVAL_LIMIT		(0x3f)
-#define VIDINTCON0_FIFOINTERVAL(_x)		((_x) << 20)
-
-#define VIDINTCON0_INT_SYSMAINCON		(1 << 19)
-#define VIDINTCON0_INT_SYSSUBCON		(1 << 18)
-#define VIDINTCON0_INT_I80IFDONE		(1 << 17)
-
-#define VIDINTCON0_FRAMESEL0_MASK		(0x3 << 15)
-#define VIDINTCON0_FRAMESEL0_SHIFT		(15)
-#define VIDINTCON0_FRAMESEL0_BACKPORCH		(0x0 << 15)
-#define VIDINTCON0_FRAMESEL0_VSYNC		(0x1 << 15)
-#define VIDINTCON0_FRAMESEL0_ACTIVE		(0x2 << 15)
-#define VIDINTCON0_FRAMESEL0_FRONTPORCH		(0x3 << 15)
-
-#define VIDINTCON0_FRAMESEL1			(1 << 13)
-#define VIDINTCON0_FRAMESEL1_MASK		(0x3 << 13)
-#define VIDINTCON0_FRAMESEL1_NONE		(0x0 << 13)
-#define VIDINTCON0_FRAMESEL1_BACKPORCH		(0x1 << 13)
-#define VIDINTCON0_FRAMESEL1_VSYNC		(0x2 << 13)
-#define VIDINTCON0_FRAMESEL1_FRONTPORCH		(0x3 << 13)
-
-#define VIDINTCON0_INT_FRAME			(1 << 12)
-#define VIDINTCON0_FIFIOSEL_MASK		(0x7f << 5)
-#define VIDINTCON0_FIFIOSEL_SHIFT		(5)
-#define VIDINTCON0_FIFIOSEL_WINDOW0		(0x1 << 5)
-#define VIDINTCON0_FIFIOSEL_WINDOW1		(0x2 << 5)
-
-#define VIDINTCON0_FIFOLEVEL_MASK		(0x7 << 2)
-#define VIDINTCON0_FIFOLEVEL_SHIFT		(2)
-#define VIDINTCON0_FIFOLEVEL_TO25PC		(0x0 << 2)
-#define VIDINTCON0_FIFOLEVEL_TO50PC		(0x1 << 2)
-#define VIDINTCON0_FIFOLEVEL_TO75PC		(0x2 << 2)
-#define VIDINTCON0_FIFOLEVEL_EMPTY		(0x3 << 2)
-#define VIDINTCON0_FIFOLEVEL_FULL		(0x4 << 2)
-
-#define VIDINTCON0_INT_FIFO_MASK		(0x3 << 0)
-#define VIDINTCON0_INT_FIFO_SHIFT		(0)
-#define VIDINTCON0_INT_ENABLE			(1 << 0)
-
-#define VIDINTCON1				(0x134)
-#define VIDINTCON1_INT_I180			(1 << 2)
-#define VIDINTCON1_INT_FRAME			(1 << 1)
-#define VIDINTCON1_INT_FIFO			(1 << 0)
-
-/* Window colour-key control registers */
-#define WKEYCON					(0x140)	/* 6410,V210 */
-
-#define WKEYCON0				(0x00)
-#define WKEYCON1				(0x04)
-
-#define WxKEYCON0_KEYBL_EN			(1 << 26)
-#define WxKEYCON0_KEYEN_F			(1 << 25)
-#define WxKEYCON0_DIRCON			(1 << 24)
-#define WxKEYCON0_COMPKEY_MASK			(0xffffff << 0)
-#define WxKEYCON0_COMPKEY_SHIFT			(0)
-#define WxKEYCON0_COMPKEY_LIMIT			(0xffffff)
-#define WxKEYCON0_COMPKEY(_x)			((_x) << 0)
-#define WxKEYCON1_COLVAL_MASK			(0xffffff << 0)
-#define WxKEYCON1_COLVAL_SHIFT			(0)
-#define WxKEYCON1_COLVAL_LIMIT			(0xffffff)
-#define WxKEYCON1_COLVAL(_x)			((_x) << 0)
-
-
-/* Window blanking (MAP) */
-
-#define WINxMAP_MAP				(1 << 24)
-#define WINxMAP_MAP_COLOUR_MASK			(0xffffff << 0)
-#define WINxMAP_MAP_COLOUR_SHIFT		(0)
-#define WINxMAP_MAP_COLOUR_LIMIT		(0xffffff)
-#define WINxMAP_MAP_COLOUR(_x)			((_x) << 0)
-
-#define WPALCON_PAL_UPDATE			(1 << 9)
-#define WPALCON_W1PAL_MASK			(0x7 << 3)
-#define WPALCON_W1PAL_SHIFT			(3)
-#define WPALCON_W1PAL_25BPP_A888		(0x0 << 3)
-#define WPALCON_W1PAL_24BPP			(0x1 << 3)
-#define WPALCON_W1PAL_19BPP_A666		(0x2 << 3)
-#define WPALCON_W1PAL_18BPP_A665		(0x3 << 3)
-#define WPALCON_W1PAL_18BPP			(0x4 << 3)
-#define WPALCON_W1PAL_16BPP_A555		(0x5 << 3)
-#define WPALCON_W1PAL_16BPP_565			(0x6 << 3)
-
-#define WPALCON_W0PAL_MASK			(0x7 << 0)
-#define WPALCON_W0PAL_SHIFT			(0)
-#define WPALCON_W0PAL_25BPP_A888		(0x0 << 0)
-#define WPALCON_W0PAL_24BPP			(0x1 << 0)
-#define WPALCON_W0PAL_19BPP_A666		(0x2 << 0)
-#define WPALCON_W0PAL_18BPP_A665		(0x3 << 0)
-#define WPALCON_W0PAL_18BPP			(0x4 << 0)
-#define WPALCON_W0PAL_16BPP_A555		(0x5 << 0)
-#define WPALCON_W0PAL_16BPP_565			(0x6 << 0)
-
-/* Blending equation control */
-#define BLENDCON				(0x260)
-#define BLENDCON_NEW_MASK			(1 << 0)
-#define BLENDCON_NEW_8BIT_ALPHA_VALUE		(1 << 0)
-#define BLENDCON_NEW_4BIT_ALPHA_VALUE		(0 << 0)
-
diff --git a/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h b/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h
deleted file mode 100644
index ceba18d..0000000
--- a/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/* linux/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h
- *
- * Copyright (C) 2009 Samsung Electronics Ltd.
- *	Jaswinder Singh <jassi.brar@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __S3C64XX_PLAT_SPI_H
-#define __S3C64XX_PLAT_SPI_H
-
-struct platform_device;
-
-/**
- * struct s3c64xx_spi_csinfo - ChipSelect description
- * @fb_delay: Slave specific feedback delay.
- *            Refer to FB_CLK_SEL register definition in SPI chapter.
- * @line: Custom 'identity' of the CS line.
- *
- * This is per SPI-Slave Chipselect information.
- * Allocate and initialize one in machine init code and make the
- * spi_board_info.controller_data point to it.
- */
-struct s3c64xx_spi_csinfo {
-	u8 fb_delay;
-	unsigned line;
-};
-
-/**
- * struct s3c64xx_spi_info - SPI Controller defining structure
- * @src_clk_nr: Clock source index for the CLK_CFG[SPI_CLKSEL] field.
- * @num_cs: Number of CS this controller emulates.
- * @cfg_gpio: Configure pins for this SPI controller.
- */
-struct s3c64xx_spi_info {
-	int src_clk_nr;
-	int num_cs;
-	int (*cfg_gpio)(void);
-};
-
-/**
- * s3c64xx_spi_set_platdata - SPI Controller configure callback by the board
- *				initialization code.
- * @cfg_gpio: Pointer to gpio setup function.
- * @src_clk_nr: Clock the SPI controller is to use to generate SPI clocks.
- * @num_cs: Number of elements in the 'cs' array.
- *
- * Call this from machine init code for each SPI Controller that
- * has some chips attached to it.
- */
-extern void s3c64xx_spi0_set_platdata(int (*cfg_gpio)(void), int src_clk_nr,
-						int num_cs);
-extern void s3c64xx_spi1_set_platdata(int (*cfg_gpio)(void), int src_clk_nr,
-						int num_cs);
-extern void s3c64xx_spi2_set_platdata(int (*cfg_gpio)(void), int src_clk_nr,
-						int num_cs);
-
-/* defined by architecture to configure gpio */
-extern int s3c64xx_spi0_cfg_gpio(void);
-extern int s3c64xx_spi1_cfg_gpio(void);
-extern int s3c64xx_spi2_cfg_gpio(void);
-
-extern struct s3c64xx_spi_info s3c64xx_spi0_pdata;
-extern struct s3c64xx_spi_info s3c64xx_spi1_pdata;
-extern struct s3c64xx_spi_info s3c64xx_spi2_pdata;
-#endif /* __S3C64XX_PLAT_SPI_H */
diff --git a/arch/arm/plat-samsung/include/plat/ts.h b/arch/arm/plat-samsung/include/plat/ts.h
deleted file mode 100644
index 26fdb22..0000000
--- a/arch/arm/plat-samsung/include/plat/ts.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/* arch/arm/plat-samsung/include/plat/ts.h
- *
- * Copyright (c) 2005 Arnaud Patard <arnaud.patard@rtp-net.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARM_TS_H
-#define __ASM_ARM_TS_H
-
-struct s3c2410_ts_mach_info {
-       int             delay;
-       int             presc;
-       int             oversampling_shift;
-	void    (*cfg_gpio)(struct platform_device *dev);
-};
-
-extern void s3c24xx_ts_set_platdata(struct s3c2410_ts_mach_info *);
-
-/* defined by architecture to configure gpio */
-extern void s3c24xx_ts_cfg_gpio(struct platform_device *dev);
-
-#endif /* __ASM_ARM_TS_H */
diff --git a/arch/arm/plat-samsung/include/plat/udc.h b/arch/arm/plat-samsung/include/plat/udc.h
deleted file mode 100644
index de8e228..0000000
--- a/arch/arm/plat-samsung/include/plat/udc.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/* arch/arm/plat-samsung/include/plat/udc.h
- *
- * Copyright (c) 2005 Arnaud Patard <arnaud.patard@rtp-net.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.
- *
- *
- *  Changelog:
- *	14-Mar-2005	RTP	Created file
- *	02-Aug-2005	RTP	File rename
- *	07-Sep-2005	BJD	Minor cleanups, changed cmd to enum
- *	18-Jan-2007	HMW	Add per-platform vbus_draw function
-*/
-
-#ifndef __ASM_ARM_ARCH_UDC_H
-#define __ASM_ARM_ARCH_UDC_H
-
-enum s3c2410_udc_cmd_e {
-	S3C2410_UDC_P_ENABLE	= 1,	/* Pull-up enable        */
-	S3C2410_UDC_P_DISABLE	= 2,	/* Pull-up disable       */
-	S3C2410_UDC_P_RESET	= 3,	/* UDC reset, in case of */
-};
-
-struct s3c2410_udc_mach_info {
-	void	(*udc_command)(enum s3c2410_udc_cmd_e);
-	void	(*vbus_draw)(unsigned int ma);
-
-	unsigned int pullup_pin;
-	unsigned int pullup_pin_inverted;
-
-	unsigned int vbus_pin;
-	unsigned char vbus_pin_inverted;
-};
-
-extern void __init s3c24xx_udc_set_platdata(struct s3c2410_udc_mach_info *);
-
-struct s3c24xx_hsudc_platdata;
-
-extern void __init s3c24xx_hsudc_set_platdata(struct s3c24xx_hsudc_platdata *pd);
-
-#endif /* __ASM_ARM_ARCH_UDC_H */
diff --git a/arch/arm/plat-samsung/include/plat/usb-control.h b/arch/arm/plat-samsung/include/plat/usb-control.h
deleted file mode 100644
index 7fa1fbe..0000000
--- a/arch/arm/plat-samsung/include/plat/usb-control.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/* arch/arm/plat-samsung/include/plat/usb-control.h
- *
- * Copyright (c) 2004 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S3C - USB host port information
- *
- * This program is free software; you can 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_USBCONTROL_H
-#define __ASM_ARCH_USBCONTROL_H
-
-#define S3C_HCDFLG_USED	(1)
-
-struct s3c2410_hcd_port {
-	unsigned char	flags;
-	unsigned char	power;
-	unsigned char	oc_status;
-	unsigned char	oc_changed;
-};
-
-struct s3c2410_hcd_info {
-	struct usb_hcd		*hcd;
-	struct s3c2410_hcd_port	port[2];
-
-	void		(*power_control)(int port, int to);
-	void		(*enable_oc)(struct s3c2410_hcd_info *, int on);
-	void		(*report_oc)(struct s3c2410_hcd_info *, int ports);
-};
-
-static void inline s3c2410_usb_report_oc(struct s3c2410_hcd_info *info, int ports)
-{
-	if (info->report_oc != NULL) {
-		(info->report_oc)(info, ports);
-	}
-}
-
-extern void s3c_ohci_set_platdata(struct s3c2410_hcd_info *info);
-
-#endif /*__ASM_ARCH_USBCONTROL_H */
diff --git a/arch/arm/plat-samsung/s5p-irq-gpioint.c b/arch/arm/plat-samsung/s5p-irq-gpioint.c
index f9431fe..23557d3 100644
--- a/arch/arm/plat-samsung/s5p-irq-gpioint.c
+++ b/arch/arm/plat-samsung/s5p-irq-gpioint.c
@@ -24,7 +24,7 @@
 
 #include <asm/mach/irq.h>
 
-#define GPIO_BASE(chip)		(((unsigned long)(chip)->base) & 0xFFFFF000u)
+#define GPIO_BASE(chip)		((void __iomem *)((unsigned long)((chip)->base) & 0xFFFFF000u))
 
 #define CON_OFFSET		0x700
 #define MASK_OFFSET		0x900
@@ -153,7 +153,7 @@ static __init int s5p_gpioint_add(struct samsung_gpio_chip *chip)
 	bank->chips[group - bank->start] = chip;
 
 	gc = irq_alloc_generic_chip("s5p_gpioint", 1, chip->irq_base,
-				    (void __iomem *)GPIO_BASE(chip),
+				    GPIO_BASE(chip),
 				    handle_level_irq);
 	if (!gc)
 		return -ENOMEM;
diff --git a/arch/arm/plat-samsung/time.c b/arch/arm/plat-samsung/time.c
index 4dcb11c..60552e2 100644
--- a/arch/arm/plat-samsung/time.c
+++ b/arch/arm/plat-samsung/time.c
@@ -28,7 +28,6 @@
 #include <linux/io.h>
 #include <linux/platform_device.h>
 
-#include <asm/leds.h>
 #include <asm/mach-types.h>
 
 #include <asm/irq.h>
diff --git a/arch/arm/plat-spear/include/plat/gpio.h b/arch/arm/plat-spear/include/plat/gpio.h
deleted file mode 100644
index 40a8c17..0000000
--- a/arch/arm/plat-spear/include/plat/gpio.h
+++ /dev/null
@@ -1 +0,0 @@
-/* empty */
diff --git a/arch/arm/plat-spear/include/plat/keyboard.h b/arch/arm/plat-spear/include/plat/keyboard.h
deleted file mode 100644
index 9248e3a..0000000
--- a/arch/arm/plat-spear/include/plat/keyboard.h
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright (C) 2010 ST Microelectronics
- * Rajeev Kumar<rajeev-dlh.kumar@st.com>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#ifndef __PLAT_KEYBOARD_H
-#define __PLAT_KEYBOARD_H
-
-#include <linux/bitops.h>
-#include <linux/input.h>
-#include <linux/input/matrix_keypad.h>
-#include <linux/types.h>
-
-#define DECLARE_9x9_KEYMAP(_name) \
-int _name[] = { \
-	KEY(0, 0, KEY_ESC), \
-	KEY(0, 1, KEY_1), \
-	KEY(0, 2, KEY_2), \
-	KEY(0, 3, KEY_3), \
-	KEY(0, 4, KEY_4), \
-	KEY(0, 5, KEY_5), \
-	KEY(0, 6, KEY_6), \
-	KEY(0, 7, KEY_7), \
-	KEY(0, 8, KEY_8), \
-	KEY(1, 0, KEY_9), \
-	KEY(1, 1, KEY_MINUS), \
-	KEY(1, 2, KEY_EQUAL), \
-	KEY(1, 3, KEY_BACKSPACE), \
-	KEY(1, 4, KEY_TAB), \
-	KEY(1, 5, KEY_Q), \
-	KEY(1, 6, KEY_W), \
-	KEY(1, 7, KEY_E), \
-	KEY(1, 8, KEY_R), \
-	KEY(2, 0, KEY_T), \
-	KEY(2, 1, KEY_Y), \
-	KEY(2, 2, KEY_U), \
-	KEY(2, 3, KEY_I), \
-	KEY(2, 4, KEY_O), \
-	KEY(2, 5, KEY_P), \
-	KEY(2, 6, KEY_LEFTBRACE), \
-	KEY(2, 7, KEY_RIGHTBRACE), \
-	KEY(2, 8, KEY_ENTER), \
-	KEY(3, 0, KEY_LEFTCTRL), \
-	KEY(3, 1, KEY_A), \
-	KEY(3, 2, KEY_S), \
-	KEY(3, 3, KEY_D), \
-	KEY(3, 4, KEY_F), \
-	KEY(3, 5, KEY_G), \
-	KEY(3, 6, KEY_H), \
-	KEY(3, 7, KEY_J), \
-	KEY(3, 8, KEY_K), \
-	KEY(4, 0, KEY_L), \
-	KEY(4, 1, KEY_SEMICOLON), \
-	KEY(4, 2, KEY_APOSTROPHE), \
-	KEY(4, 3, KEY_GRAVE), \
-	KEY(4, 4, KEY_LEFTSHIFT), \
-	KEY(4, 5, KEY_BACKSLASH), \
-	KEY(4, 6, KEY_Z), \
-	KEY(4, 7, KEY_X), \
-	KEY(4, 8, KEY_C), \
-	KEY(5, 0, KEY_V), \
-	KEY(5, 1, KEY_B), \
-	KEY(5, 2, KEY_N), \
-	KEY(5, 3, KEY_M), \
-	KEY(5, 4, KEY_COMMA), \
-	KEY(5, 5, KEY_DOT), \
-	KEY(5, 6, KEY_SLASH), \
-	KEY(5, 7, KEY_RIGHTSHIFT), \
-	KEY(5, 8, KEY_KPASTERISK), \
-	KEY(6, 0, KEY_LEFTALT), \
-	KEY(6, 1, KEY_SPACE), \
-	KEY(6, 2, KEY_CAPSLOCK), \
-	KEY(6, 3, KEY_F1), \
-	KEY(6, 4, KEY_F2), \
-	KEY(6, 5, KEY_F3), \
-	KEY(6, 6, KEY_F4), \
-	KEY(6, 7, KEY_F5), \
-	KEY(6, 8, KEY_F6), \
-	KEY(7, 0, KEY_F7), \
-	KEY(7, 1, KEY_F8), \
-	KEY(7, 2, KEY_F9), \
-	KEY(7, 3, KEY_F10), \
-	KEY(7, 4, KEY_NUMLOCK), \
-	KEY(7, 5, KEY_SCROLLLOCK), \
-	KEY(7, 6, KEY_KP7), \
-	KEY(7, 7, KEY_KP8), \
-	KEY(7, 8, KEY_KP9), \
-	KEY(8, 0, KEY_KPMINUS), \
-	KEY(8, 1, KEY_KP4), \
-	KEY(8, 2, KEY_KP5), \
-	KEY(8, 3, KEY_KP6), \
-	KEY(8, 4, KEY_KPPLUS), \
-	KEY(8, 5, KEY_KP1), \
-	KEY(8, 6, KEY_KP2), \
-	KEY(8, 7, KEY_KP3), \
-	KEY(8, 8, KEY_KP0), \
-}
-
-#define DECLARE_6x6_KEYMAP(_name) \
-int _name[] = { \
-	KEY(0, 0, KEY_RESERVED), \
-	KEY(0, 1, KEY_1), \
-	KEY(0, 2, KEY_2), \
-	KEY(0, 3, KEY_3), \
-	KEY(0, 4, KEY_4), \
-	KEY(0, 5, KEY_5), \
-	KEY(1, 0, KEY_Q), \
-	KEY(1, 1, KEY_W), \
-	KEY(1, 2, KEY_E), \
-	KEY(1, 3, KEY_R), \
-	KEY(1, 4, KEY_T), \
-	KEY(1, 5, KEY_Y), \
-	KEY(2, 0, KEY_D), \
-	KEY(2, 1, KEY_F), \
-	KEY(2, 2, KEY_G), \
-	KEY(2, 3, KEY_H), \
-	KEY(2, 4, KEY_J), \
-	KEY(2, 5, KEY_K), \
-	KEY(3, 0, KEY_B), \
-	KEY(3, 1, KEY_N), \
-	KEY(3, 2, KEY_M), \
-	KEY(3, 3, KEY_COMMA), \
-	KEY(3, 4, KEY_DOT), \
-	KEY(3, 5, KEY_SLASH), \
-	KEY(4, 0, KEY_F6), \
-	KEY(4, 1, KEY_F7), \
-	KEY(4, 2, KEY_F8), \
-	KEY(4, 3, KEY_F9), \
-	KEY(4, 4, KEY_F10), \
-	KEY(4, 5, KEY_NUMLOCK), \
-	KEY(5, 0, KEY_KP2), \
-	KEY(5, 1, KEY_KP3), \
-	KEY(5, 2, KEY_KP0), \
-	KEY(5, 3, KEY_KPDOT), \
-	KEY(5, 4, KEY_RO), \
-	KEY(5, 5, KEY_ZENKAKUHANKAKU), \
-}
-
-#define KEYPAD_9x9     0
-#define KEYPAD_6x6     1
-#define KEYPAD_2x2     2
-
-/**
- * struct kbd_platform_data - spear keyboard platform data
- * keymap: pointer to keymap data (table and size)
- * rep: enables key autorepeat
- * mode: choose keyboard support(9x9, 6x6, 2x2)
- * suspended_rate: rate at which keyboard would operate in suspended mode
- *
- * This structure is supposed to be used by platform code to supply
- * keymaps to drivers that implement keyboards.
- */
-struct kbd_platform_data {
-	const struct matrix_keymap_data *keymap;
-	bool rep;
-	unsigned int mode;
-	unsigned int suspended_rate;
-};
-
-#endif /* __PLAT_KEYBOARD_H */
diff --git a/arch/arm/plat-versatile/Kconfig b/arch/arm/plat-versatile/Kconfig
index 8d5c10a..2a4ae8a 100644
--- a/arch/arm/plat-versatile/Kconfig
+++ b/arch/arm/plat-versatile/Kconfig
@@ -16,8 +16,10 @@ config PLAT_VERSATILE_FPGA_IRQ_NR
        depends on PLAT_VERSATILE_FPGA_IRQ
 
 config PLAT_VERSATILE_LEDS
-	def_bool y if LEDS_CLASS
+	def_bool y if NEW_LEDS
 	depends on ARCH_REALVIEW || ARCH_VERSATILE
+	select LEDS_CLASS
+	select LEDS_TRIGGER
 
 config PLAT_VERSATILE_SCHED_CLOCK
 	def_bool y
diff --git a/arch/arm/plat-versatile/Makefile b/arch/arm/plat-versatile/Makefile
index 272769a8..74cfd94 100644
--- a/arch/arm/plat-versatile/Makefile
+++ b/arch/arm/plat-versatile/Makefile
@@ -1,3 +1,5 @@
+ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include
+
 obj-$(CONFIG_PLAT_VERSATILE_CLOCK) += clock.o
 obj-$(CONFIG_PLAT_VERSATILE_CLCD) += clcd.o
 obj-$(CONFIG_PLAT_VERSATILE_FPGA_IRQ) += fpga-irq.o
diff --git a/arch/arm/plat-versatile/fpga-irq.c b/arch/arm/plat-versatile/fpga-irq.c
index 6e70d03..091ae10 100644
--- a/arch/arm/plat-versatile/fpga-irq.c
+++ b/arch/arm/plat-versatile/fpga-irq.c
@@ -5,6 +5,8 @@
 #include <linux/io.h>
 #include <linux/irqdomain.h>
 #include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
 
 #include <asm/exception.h>
 #include <asm/mach/irq.h>
@@ -14,11 +16,17 @@
 #define IRQ_RAW_STATUS		0x04
 #define IRQ_ENABLE_SET		0x08
 #define IRQ_ENABLE_CLEAR	0x0c
+#define INT_SOFT_SET		0x10
+#define INT_SOFT_CLEAR		0x14
+#define FIQ_STATUS		0x20
+#define FIQ_RAW_STATUS		0x24
+#define FIQ_ENABLE		0x28
+#define FIQ_ENABLE_SET		0x28
+#define FIQ_ENABLE_CLEAR	0x2C
 
 /**
  * struct fpga_irq_data - irq data container for the FPGA IRQ controller
  * @base: memory offset in virtual memory
- * @irq_start: first IRQ number handled by this instance
  * @chip: chip container for this instance
  * @domain: IRQ domain for this instance
  * @valid: mask for valid IRQs on this controller
@@ -26,7 +34,6 @@
  */
 struct fpga_irq_data {
 	void __iomem *base;
-	unsigned int irq_start;
 	struct irq_chip chip;
 	u32 valid;
 	struct irq_domain *domain;
@@ -125,34 +132,79 @@ static struct irq_domain_ops fpga_irqdomain_ops = {
 	.xlate = irq_domain_xlate_onetwocell,
 };
 
-void __init fpga_irq_init(void __iomem *base, const char *name, int irq_start,
-			  int parent_irq, u32 valid, struct device_node *node)
-{
+static __init struct fpga_irq_data *
+fpga_irq_prep_struct(void __iomem *base, const char *name, u32 valid) {
 	struct fpga_irq_data *f;
 
 	if (fpga_irq_id >= ARRAY_SIZE(fpga_irq_devices)) {
 		printk(KERN_ERR "%s: too few FPGA IRQ controllers, increase CONFIG_PLAT_VERSATILE_FPGA_IRQ_NR\n", __func__);
-		return;
+		return NULL;
 	}
-
 	f = &fpga_irq_devices[fpga_irq_id];
 	f->base = base;
-	f->irq_start = irq_start;
 	f->chip.name = name;
 	f->chip.irq_ack = fpga_irq_mask;
 	f->chip.irq_mask = fpga_irq_mask;
 	f->chip.irq_unmask = fpga_irq_unmask;
 	f->valid = valid;
+	fpga_irq_id++;
+
+	return f;
+}
+
+void __init fpga_irq_init(void __iomem *base, const char *name, int irq_start,
+			  int parent_irq, u32 valid, struct device_node *node)
+{
+	struct fpga_irq_data *f;
+
+	f = fpga_irq_prep_struct(base, name, valid);
+	if (!f)
+		return;
 
 	if (parent_irq != -1) {
 		irq_set_handler_data(parent_irq, f);
 		irq_set_chained_handler(parent_irq, fpga_irq_handle);
 	}
 
-	f->domain = irq_domain_add_legacy(node, fls(valid), f->irq_start, 0,
+	f->domain = irq_domain_add_legacy(node, fls(valid), irq_start, 0,
 					  &fpga_irqdomain_ops, f);
 	pr_info("FPGA IRQ chip %d \"%s\" @ %p, %u irqs\n",
 		fpga_irq_id, name, base, f->used_irqs);
+}
 
-	fpga_irq_id++;
+#ifdef CONFIG_OF
+int __init fpga_irq_of_init(struct device_node *node,
+			    struct device_node *parent)
+{
+	struct fpga_irq_data *f;
+	void __iomem *base;
+	u32 clear_mask;
+	u32 valid_mask;
+
+	if (WARN_ON(!node))
+		return -ENODEV;
+
+	base = of_iomap(node, 0);
+	WARN(!base, "unable to map fpga irq registers\n");
+
+	if (of_property_read_u32(node, "clear-mask", &clear_mask))
+		clear_mask = 0;
+
+	if (of_property_read_u32(node, "valid-mask", &valid_mask))
+		valid_mask = 0;
+
+	f = fpga_irq_prep_struct(base, node->name, valid_mask);
+	if (!f)
+		return -ENOMEM;
+
+	writel(clear_mask, base + IRQ_ENABLE_CLEAR);
+	writel(clear_mask, base + FIQ_ENABLE_CLEAR);
+
+	f->domain = irq_domain_add_linear(node, fls(valid_mask), &fpga_irqdomain_ops, f);
+	f->used_irqs = hweight32(valid_mask);
+
+	pr_info("FPGA IRQ chip %d \"%s\" @ %p, %u irqs\n",
+		fpga_irq_id, node->name, base, f->used_irqs);
+	return 0;
 }
+#endif
diff --git a/arch/arm/plat-versatile/include/plat/fpga-irq.h b/arch/arm/plat-versatile/include/plat/fpga-irq.h
index 91bcfb6..1fac965 100644
--- a/arch/arm/plat-versatile/include/plat/fpga-irq.h
+++ b/arch/arm/plat-versatile/include/plat/fpga-irq.h
@@ -7,5 +7,7 @@ struct pt_regs;
 void fpga_handle_irq(struct pt_regs *regs);
 void fpga_irq_init(void __iomem *, const char *, int, int, u32,
 		struct device_node *node);
+int fpga_irq_of_init(struct device_node *node,
+		     struct device_node *parent);
 
 #endif
diff --git a/arch/arm/plat-versatile/include/plat/platsmp.h b/arch/arm/plat-versatile/include/plat/platsmp.h
new file mode 100644
index 0000000..50fb830
--- /dev/null
+++ b/arch/arm/plat-versatile/include/plat/platsmp.h
@@ -0,0 +1,14 @@
+/*
+ *  linux/arch/arm/plat-versatile/include/plat/platsmp.h
+ *
+ *  Copyright (C) 2011 ARM Ltd.
+ *  All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+extern void versatile_secondary_startup(void);
+extern void versatile_secondary_init(unsigned int cpu);
+extern int  versatile_boot_secondary(unsigned int cpu, struct task_struct *idle);
diff --git a/arch/arm/plat-versatile/leds.c b/arch/arm/plat-versatile/leds.c
index 3169fa5..d2490d0 100644
--- a/arch/arm/plat-versatile/leds.c
+++ b/arch/arm/plat-versatile/leds.c
@@ -37,10 +37,10 @@ static const struct {
 } versatile_leds[] = {
 	{ "versatile:0", "heartbeat", },
 	{ "versatile:1", "mmc0", },
-	{ "versatile:2", },
-	{ "versatile:3", },
-	{ "versatile:4", },
-	{ "versatile:5", },
+	{ "versatile:2", "cpu0" },
+	{ "versatile:3", "cpu1" },
+	{ "versatile:4", "cpu2" },
+	{ "versatile:5", "cpu3" },
 	{ "versatile:6", },
 	{ "versatile:7", },
 };
diff --git a/arch/arm/plat-versatile/platsmp.c b/arch/arm/plat-versatile/platsmp.c
index d7c5c17..04ca493 100644
--- a/arch/arm/plat-versatile/platsmp.c
+++ b/arch/arm/plat-versatile/platsmp.c
@@ -20,12 +20,6 @@
 #include <asm/hardware/gic.h>
 
 /*
- * control for which core is the next to come out of the secondary
- * boot "holding pen"
- */
-volatile int __cpuinitdata pen_release = -1;
-
-/*
  * Write pen_release in a way that is guaranteed to be visible to all
  * observers, irrespective of whether they're taking part in coherency
  * or not.  This is necessary for the hotplug code to work reliably.
@@ -40,7 +34,7 @@ static void __cpuinit write_pen_release(int val)
 
 static DEFINE_SPINLOCK(boot_lock);
 
-void __cpuinit platform_secondary_init(unsigned int cpu)
+void __cpuinit versatile_secondary_init(unsigned int cpu)
 {
 	/*
 	 * if any interrupts are already enabled for the primary
@@ -62,7 +56,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
 	spin_unlock(&boot_lock);
 }
 
-int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
+int __cpuinit versatile_boot_secondary(unsigned int cpu, struct task_struct *idle)
 {
 	unsigned long timeout;
 
diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types
index 2997e56..7bc7948 100644
--- a/arch/arm/tools/mach-types
+++ b/arch/arm/tools/mach-types
@@ -158,7 +158,6 @@ edb9315a		MACH_EDB9315A		EDB9315A		772
 stargate2		MACH_STARGATE2		STARGATE2		774
 intelmote2		MACH_INTELMOTE2		INTELMOTE2		775
 trizeps4		MACH_TRIZEPS4		TRIZEPS4		776
-pnx4008			MACH_PNX4008		PNX4008			782
 cpuat91			MACH_CPUAT91		CPUAT91			787
 iq81340sc		MACH_IQ81340SC		IQ81340SC		799
 iq81340mc		MACH_IQ81340MC		IQ81340MC		801
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
new file mode 100644
index 0000000..767ba56
--- /dev/null
+++ b/arch/arm64/Kconfig
@@ -0,0 +1,222 @@
+config ARM64
+	def_bool y
+	select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
+	select GENERIC_CLOCKEVENTS
+	select GENERIC_HARDIRQS_NO_DEPRECATED
+	select GENERIC_IOMAP
+	select GENERIC_IRQ_PROBE
+	select GENERIC_IRQ_SHOW
+	select GENERIC_SMP_IDLE_THREAD
+	select GENERIC_TIME_VSYSCALL
+	select HARDIRQS_SW_RESEND
+	select HAVE_ARCH_TRACEHOOK
+	select HAVE_DMA_API_DEBUG
+	select HAVE_DMA_ATTRS
+	select HAVE_GENERIC_DMA_COHERENT
+	select HAVE_GENERIC_HARDIRQS
+	select HAVE_HW_BREAKPOINT if PERF_EVENTS
+	select HAVE_IRQ_WORK
+	select HAVE_MEMBLOCK
+	select HAVE_PERF_EVENTS
+	select HAVE_SPARSE_IRQ
+	select IRQ_DOMAIN
+	select NO_BOOTMEM
+	select OF
+	select OF_EARLY_FLATTREE
+	select PERF_USE_VMALLOC
+	select RTC_LIB
+	select SPARSE_IRQ
+	help
+	  ARM 64-bit (AArch64) Linux support.
+
+config 64BIT
+	def_bool y
+
+config ARCH_PHYS_ADDR_T_64BIT
+	def_bool y
+
+config MMU
+	def_bool y
+
+config NO_IOPORT
+	def_bool y
+
+config STACKTRACE_SUPPORT
+	def_bool y
+
+config LOCKDEP_SUPPORT
+	def_bool y
+
+config TRACE_IRQFLAGS_SUPPORT
+	def_bool y
+
+config GENERIC_LOCKBREAK
+	def_bool y
+	depends on SMP && PREEMPT
+
+config RWSEM_GENERIC_SPINLOCK
+	def_bool y
+
+config GENERIC_HWEIGHT
+	def_bool y
+
+config GENERIC_CSUM
+        def_bool y
+
+config GENERIC_CALIBRATE_DELAY
+	def_bool y
+
+config ZONE_DMA32
+	def_bool y
+
+config ARCH_DMA_ADDR_T_64BIT
+	def_bool y
+
+config NEED_DMA_MAP_STATE
+	def_bool y
+
+config NEED_SG_DMA_LENGTH
+	def_bool y
+
+config SWIOTLB
+	def_bool y
+
+config IOMMU_HELPER
+	def_bool SWIOTLB
+
+source "init/Kconfig"
+
+source "kernel/Kconfig.freezer"
+
+menu "System Type"
+
+endmenu
+
+menu "Bus support"
+
+config ARM_AMBA
+	bool
+
+endmenu
+
+menu "Kernel Features"
+
+source "kernel/time/Kconfig"
+
+config ARM64_64K_PAGES
+	bool "Enable 64KB pages support"
+	help
+	  This feature enables 64KB pages support (4KB by default)
+	  allowing only two levels of page tables and faster TLB
+	  look-up. AArch32 emulation is not available when this feature
+	  is enabled.
+
+config SMP
+	bool "Symmetric Multi-Processing"
+	select USE_GENERIC_SMP_HELPERS
+	help
+	  This enables support for systems with more than one CPU.  If
+	  you say N here, the kernel will run on single and
+	  multiprocessor machines, but will use only one CPU of a
+	  multiprocessor machine. If you say Y here, the kernel will run
+	  on many, but not all, single processor machines. On a single
+	  processor machine, the kernel will run faster if you say N
+	  here.
+
+	  If you don't know what to do here, say N.
+
+config NR_CPUS
+	int "Maximum number of CPUs (2-32)"
+	range 2 32
+	depends on SMP
+	default "4"
+
+source kernel/Kconfig.preempt
+
+config HZ
+	int
+	default 100
+
+config ARCH_HAS_HOLES_MEMORYMODEL
+	def_bool y if SPARSEMEM
+
+config ARCH_SPARSEMEM_ENABLE
+	def_bool y
+	select SPARSEMEM_VMEMMAP_ENABLE
+
+config ARCH_SPARSEMEM_DEFAULT
+	def_bool ARCH_SPARSEMEM_ENABLE
+
+config ARCH_SELECT_MEMORY_MODEL
+	def_bool ARCH_SPARSEMEM_ENABLE
+
+config HAVE_ARCH_PFN_VALID
+	def_bool ARCH_HAS_HOLES_MEMORYMODEL || !SPARSEMEM
+
+config HW_PERF_EVENTS
+	bool "Enable hardware performance counter support for perf events"
+	depends on PERF_EVENTS
+	default y
+	help
+	  Enable hardware performance counter support for perf events. If
+	  disabled, perf events will use software events only.
+
+source "mm/Kconfig"
+
+endmenu
+
+menu "Boot options"
+
+config CMDLINE
+	string "Default kernel command string"
+	default ""
+	help
+	  Provide a set of default command-line options at build time by
+	  entering them here. As a minimum, you should specify the the
+	  root device (e.g. root=/dev/nfs).
+
+config CMDLINE_FORCE
+	bool "Always use the default kernel command string"
+	help
+	  Always use the default kernel command string, even if the boot
+	  loader passes other arguments to the kernel.
+	  This is useful if you cannot or don't want to change the
+	  command-line options your boot loader passes to the kernel.
+
+endmenu
+
+menu "Userspace binary formats"
+
+source "fs/Kconfig.binfmt"
+
+config COMPAT
+	bool "Kernel support for 32-bit EL0"
+	depends on !ARM64_64K_PAGES
+	select COMPAT_BINFMT_ELF
+	help
+	  This option enables support for a 32-bit EL0 running under a 64-bit
+	  kernel at EL1. AArch32-specific components such as system calls,
+	  the user helper functions, VFP support and the ptrace interface are
+	  handled appropriately by the kernel.
+
+	  If you want to execute 32-bit userspace applications, say Y.
+
+config SYSVIPC_COMPAT
+	def_bool y
+	depends on COMPAT && SYSVIPC
+
+endmenu
+
+source "net/Kconfig"
+
+source "drivers/Kconfig"
+
+source "fs/Kconfig"
+
+source "arch/arm64/Kconfig.debug"
+
+source "security/Kconfig"
+
+source "crypto/Kconfig"
+
+source "lib/Kconfig"
diff --git a/arch/arm64/Kconfig.debug b/arch/arm64/Kconfig.debug
new file mode 100644
index 0000000..d7553f2
--- /dev/null
+++ b/arch/arm64/Kconfig.debug
@@ -0,0 +1,27 @@
+menu "Kernel hacking"
+
+source "lib/Kconfig.debug"
+
+config FRAME_POINTER
+	bool
+	default y
+
+config DEBUG_ERRORS
+	bool "Verbose kernel error messages"
+	depends on DEBUG_KERNEL
+	help
+	  This option controls verbose debugging information which can be
+	  printed when the kernel detects an internal error. This debugging
+	  information is useful to kernel hackers when tracking down problems,
+	  but mostly meaningless to other people. It's safe to say Y unless
+	  you are concerned with the code size or don't want to see these
+	  messages.
+
+config DEBUG_STACK_USAGE
+	bool "Enable stack utilization instrumentation"
+	depends on DEBUG_KERNEL
+	help
+	  Enables the display of the minimum amount of free stack which each
+	  task has ever had available in the sysrq-T output.
+
+endmenu
diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
new file mode 100644
index 0000000..364191f
--- /dev/null
+++ b/arch/arm64/Makefile
@@ -0,0 +1,71 @@
+#
+# arch/arm64/Makefile
+#
+# This file is included by the global makefile so that you can add your own
+# architecture-specific flags and dependencies.
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License.  See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+# Copyright (C) 1995-2001 by Russell King
+
+LDFLAGS_vmlinux	:=-p --no-undefined -X
+CPPFLAGS_vmlinux.lds = -DTEXT_OFFSET=$(TEXT_OFFSET)
+OBJCOPYFLAGS	:=-O binary -R .note -R .note.gnu.build-id -R .comment -S
+GZFLAGS		:=-9
+
+LIBGCC 		:= $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name)
+
+KBUILD_DEFCONFIG := defconfig
+
+KBUILD_CFLAGS	+= -mgeneral-regs-only
+KBUILD_CPPFLAGS	+= -mlittle-endian
+AS		+= -EL
+LD		+= -EL
+
+comma = ,
+
+CHECKFLAGS	+= -D__aarch64__
+
+# Default value
+head-y		:= arch/arm64/kernel/head.o
+
+# The byte offset of the kernel image in RAM from the start of RAM.
+TEXT_OFFSET := 0x00080000
+
+export	TEXT_OFFSET GZFLAGS
+
+core-y		+= arch/arm64/kernel/ arch/arm64/mm/
+libs-y		:= arch/arm64/lib/ $(libs-y)
+libs-y		+= $(LIBGCC)
+
+# Default target when executing plain make
+KBUILD_IMAGE := Image.gz
+
+all:	$(KBUILD_IMAGE)
+
+boot := arch/arm64/boot
+
+Image Image.gz: vmlinux
+	$(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@
+
+zinstall install: vmlinux
+	$(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $@
+
+%.dtb:
+	$(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@
+
+# We use MRPROPER_FILES and CLEAN_FILES now
+archclean:
+	$(Q)$(MAKE) $(clean)=$(boot)
+
+define archhelp
+  echo  '* Image.gz      - Compressed kernel image (arch/$(ARCH)/boot/Image.gz)'
+  echo  '  Image         - Uncompressed kernel image (arch/$(ARCH)/boot/Image)'
+  echo  '  install       - Install uncompressed kernel'
+  echo  '  zinstall      - Install compressed kernel'
+  echo  '                  Install using (your) ~/bin/installkernel or'
+  echo  '                  (distribution) /sbin/installkernel or'
+  echo  '                  install to $$(INSTALL_PATH) and run lilo'
+endef
diff --git a/arch/arm64/boot/.gitignore b/arch/arm64/boot/.gitignore
new file mode 100644
index 0000000..8dab0bb
--- /dev/null
+++ b/arch/arm64/boot/.gitignore
@@ -0,0 +1,2 @@
+Image
+Image.gz
diff --git a/arch/arm64/boot/Makefile b/arch/arm64/boot/Makefile
new file mode 100644
index 0000000..eca209b
--- /dev/null
+++ b/arch/arm64/boot/Makefile
@@ -0,0 +1,36 @@
+#
+# arch/arm64/boot/Makefile
+#
+# This file is included by the global makefile so that you can add your own
+# architecture-specific flags and dependencies.
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License.  See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+# Copyright (C) 2012, ARM Ltd.
+# Author: Will Deacon <will.deacon@arm.com>
+#
+# Based on the ia64 boot/Makefile.
+#
+
+targets := Image Image.gz
+
+$(obj)/Image: vmlinux FORCE
+	$(call if_changed,objcopy)
+
+$(obj)/Image.gz: $(obj)/Image FORCE
+	$(call if_changed,gzip)
+
+$(obj)/%.dtb: $(src)/dts/%.dts
+	$(call cmd,dtc)
+
+install: $(obj)/Image
+	$(CONFIG_SHELL) $(srctree)/$(src)/install.sh $(KERNELRELEASE) \
+	$(obj)/Image System.map "$(INSTALL_PATH)"
+
+zinstall: $(obj)/Image.gz
+	$(CONFIG_SHELL) $(srctree)/$(src)/install.sh $(KERNELRELEASE) \
+	$(obj)/Image.gz System.map "$(INSTALL_PATH)"
+
+clean-files += *.dtb
diff --git a/arch/arm64/boot/install.sh b/arch/arm64/boot/install.sh
new file mode 100644
index 0000000..12ed78a
--- /dev/null
+++ b/arch/arm64/boot/install.sh
@@ -0,0 +1,46 @@
+#!/bin/sh
+#
+# arch/arm64/boot/install.sh
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License.  See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+# Copyright (C) 1995 by Linus Torvalds
+#
+# Adapted from code in arch/i386/boot/Makefile by H. Peter Anvin
+# Adapted from code in arch/i386/boot/install.sh by Russell King
+#
+# "make install" script for the AArch64 Linux port
+#
+# Arguments:
+#   $1 - kernel version
+#   $2 - kernel image file
+#   $3 - kernel map file
+#   $4 - default install path (blank if root directory)
+#
+
+# User may have a custom install script
+if [ -x ~/bin/${INSTALLKERNEL} ]; then exec ~/bin/${INSTALLKERNEL} "$@"; fi
+if [ -x /sbin/${INSTALLKERNEL} ]; then exec /sbin/${INSTALLKERNEL} "$@"; fi
+
+if [ "$(basename $2)" = "Image.gz" ]; then
+# Compressed install
+  echo "Installing compressed kernel"
+  base=vmlinuz
+else
+# Normal install
+  echo "Installing normal kernel"
+  base=vmlinux
+fi
+
+if [ -f $4/$base-$1 ]; then
+  mv $4/$base-$1 $4/$base-$1.old
+fi
+cat $2 > $4/$base-$1
+
+# Install system map file
+if [ -f $4/System.map-$1 ]; then
+  mv $4/System.map-$1 $4/System.map-$1.old
+fi
+cp $3 $4/System.map-$1
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
new file mode 100644
index 0000000..9212c78
--- /dev/null
+++ b/arch/arm64/configs/defconfig
@@ -0,0 +1,85 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
+CONFIG_SCHED_AUTOGROUP=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_KALLSYMS_ALL=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_PROFILING=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_SMP=y
+CONFIG_PREEMPT_VOLUNTARY=y
+CONFIG_CMDLINE="console=ttyAMA0"
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_COMPAT=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_INET_LRO is not set
+# CONFIG_IPV6 is not set
+# CONFIG_WIRELESS is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+# CONFIG_BLK_DEV is not set
+CONFIG_SCSI=y
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_NETDEVICES=y
+CONFIG_MII=y
+# CONFIG_WLAN is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_SERIO_I8042 is not set
+# CONFIG_SERIO_SERPORT is not set
+CONFIG_LEGACY_PTY_COUNT=16
+# CONFIG_HW_RANDOM is not set
+# CONFIG_HWMON is not set
+CONFIG_FB=y
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_EXT2_FS=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+# CONFIG_EXT3_FS_XATTR is not set
+CONFIG_FUSE_FS=y
+CONFIG_CUSE=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+# CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_NFS_FS=y
+CONFIG_ROOT_NFS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_FS=y
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_SCHED_DEBUG is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_FTRACE is not set
+CONFIG_ATOMIC64_SELFTEST=y
+CONFIG_DEBUG_ERRORS=y
diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild
new file mode 100644
index 0000000..35924a5
--- /dev/null
+++ b/arch/arm64/include/asm/Kbuild
@@ -0,0 +1,51 @@
+include include/asm-generic/Kbuild.asm
+
+header-y += hwcap.h
+
+generic-y += bug.h
+generic-y += bugs.h
+generic-y += checksum.h
+generic-y += cputime.h
+generic-y += current.h
+generic-y += delay.h
+generic-y += div64.h
+generic-y += dma.h
+generic-y += emergency-restart.h
+generic-y += errno.h
+generic-y += ftrace.h
+generic-y += hw_irq.h
+generic-y += ioctl.h
+generic-y += ioctls.h
+generic-y += ipcbuf.h
+generic-y += irq_regs.h
+generic-y += kdebug.h
+generic-y += kmap_types.h
+generic-y += linkage.h
+generic-y += local.h
+generic-y += local64.h
+generic-y += mman.h
+generic-y += msgbuf.h
+generic-y += mutex.h
+generic-y += pci.h
+generic-y += percpu.h
+generic-y += poll.h
+generic-y += posix_types.h
+generic-y += resource.h
+generic-y += scatterlist.h
+generic-y += sections.h
+generic-y += segment.h
+generic-y += sembuf.h
+generic-y += serial.h
+generic-y += shmbuf.h
+generic-y += sizes.h
+generic-y += socket.h
+generic-y += sockios.h
+generic-y += string.h
+generic-y += switch_to.h
+generic-y += swab.h
+generic-y += termbits.h
+generic-y += termios.h
+generic-y += topology.h
+generic-y += types.h
+generic-y += unaligned.h
+generic-y += user.h
diff --git a/arch/arm64/include/asm/arm_generic.h b/arch/arm64/include/asm/arm_generic.h
new file mode 100644
index 0000000..e4cec9d
--- /dev/null
+++ b/arch/arm64/include/asm/arm_generic.h
@@ -0,0 +1,100 @@
+/*
+ * arch/arm64/include/asm/arm_generic.h
+ *
+ * Copyright (C) 2012 ARM Ltd.
+ * Author: Marc Zyngier <marc.zyngier@arm.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_ARM_GENERIC_H
+#define __ASM_ARM_GENERIC_H
+
+#include <linux/clocksource.h>
+
+#define ARCH_TIMER_CTRL_ENABLE		(1 << 0)
+#define ARCH_TIMER_CTRL_IMASK		(1 << 1)
+#define ARCH_TIMER_CTRL_ISTATUS		(1 << 2)
+
+#define ARCH_TIMER_REG_CTRL		0
+#define ARCH_TIMER_REG_FREQ		1
+#define ARCH_TIMER_REG_TVAL		2
+
+static inline void arch_timer_reg_write(int reg, u32 val)
+{
+	switch (reg) {
+	case ARCH_TIMER_REG_CTRL:
+		asm volatile("msr cntp_ctl_el0,  %0" : : "r" (val));
+		break;
+	case ARCH_TIMER_REG_TVAL:
+		asm volatile("msr cntp_tval_el0, %0" : : "r" (val));
+		break;
+	default:
+		BUILD_BUG();
+	}
+
+	isb();
+}
+
+static inline u32 arch_timer_reg_read(int reg)
+{
+	u32 val;
+
+	switch (reg) {
+	case ARCH_TIMER_REG_CTRL:
+		asm volatile("mrs %0,  cntp_ctl_el0" : "=r" (val));
+		break;
+	case ARCH_TIMER_REG_FREQ:
+		asm volatile("mrs %0,   cntfrq_el0" : "=r" (val));
+		break;
+	case ARCH_TIMER_REG_TVAL:
+		asm volatile("mrs %0, cntp_tval_el0" : "=r" (val));
+		break;
+	default:
+		BUILD_BUG();
+	}
+
+	return val;
+}
+
+static inline void __cpuinit arch_counter_enable_user_access(void)
+{
+	u32 cntkctl;
+
+	/* Disable user access to the timers and the virtual counter. */
+	asm volatile("mrs	%0, cntkctl_el1" : "=r" (cntkctl));
+	cntkctl &= ~((3 << 8) | (1 << 1));
+
+	/* Enable user access to the physical counter and frequency. */
+	cntkctl |= 1;
+	asm volatile("msr	cntkctl_el1, %0" : : "r" (cntkctl));
+}
+
+static inline cycle_t arch_counter_get_cntpct(void)
+{
+	cycle_t cval;
+
+	asm volatile("mrs %0, cntpct_el0" : "=r" (cval));
+
+	return cval;
+}
+
+static inline cycle_t arch_counter_get_cntvct(void)
+{
+	cycle_t cval;
+
+	asm volatile("mrs %0, cntvct_el0" : "=r" (cval));
+
+	return cval;
+}
+
+#endif
diff --git a/arch/arm64/include/asm/asm-offsets.h b/arch/arm64/include/asm/asm-offsets.h
new file mode 100644
index 0000000..d370ee3
--- /dev/null
+++ b/arch/arm64/include/asm/asm-offsets.h
@@ -0,0 +1 @@
+#include <generated/asm-offsets.h>
diff --git a/arch/arm64/include/asm/assembler.h b/arch/arm64/include/asm/assembler.h
new file mode 100644
index 0000000..da2a13e
--- /dev/null
+++ b/arch/arm64/include/asm/assembler.h
@@ -0,0 +1,109 @@
+/*
+ * Based on arch/arm/include/asm/assembler.h
+ *
+ * Copyright (C) 1996-2000 Russell King
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASSEMBLY__
+#error "Only include this from assembly code"
+#endif
+
+#include <asm/ptrace.h>
+
+/*
+ * Stack pushing/popping (register pairs only). Equivalent to store decrement
+ * before, load increment after.
+ */
+	.macro	push, xreg1, xreg2
+	stp	\xreg1, \xreg2, [sp, #-16]!
+	.endm
+
+	.macro	pop, xreg1, xreg2
+	ldp	\xreg1, \xreg2, [sp], #16
+	.endm
+
+/*
+ * Enable and disable interrupts.
+ */
+	.macro	disable_irq
+	msr	daifset, #2
+	.endm
+
+	.macro	enable_irq
+	msr	daifclr, #2
+	.endm
+
+/*
+ * Save/disable and restore interrupts.
+ */
+	.macro	save_and_disable_irqs, olddaif
+	mrs	\olddaif, daif
+	disable_irq
+	.endm
+
+	.macro	restore_irqs, olddaif
+	msr	daif, \olddaif
+	.endm
+
+/*
+ * Enable and disable debug exceptions.
+ */
+	.macro	disable_dbg
+	msr	daifset, #8
+	.endm
+
+	.macro	enable_dbg
+	msr	daifclr, #8
+	.endm
+
+	.macro	disable_step, tmp
+	mrs	\tmp, mdscr_el1
+	bic	\tmp, \tmp, #1
+	msr	mdscr_el1, \tmp
+	.endm
+
+	.macro	enable_step, tmp
+	mrs	\tmp, mdscr_el1
+	orr	\tmp, \tmp, #1
+	msr	mdscr_el1, \tmp
+	.endm
+
+	.macro	enable_dbg_if_not_stepping, tmp
+	mrs	\tmp, mdscr_el1
+	tbnz	\tmp, #1, 9990f
+	enable_dbg
+9990:
+	.endm
+
+/*
+ * SMP data memory barrier
+ */
+	.macro	smp_dmb, opt
+#ifdef CONFIG_SMP
+	dmb	\opt
+#endif
+	.endm
+
+#define USER(l, x...)				\
+9999:	x;					\
+	.section __ex_table,"a";		\
+	.align	3;				\
+	.quad	9999b,l;			\
+	.previous
+
+/*
+ * Register aliases.
+ */
+lr	.req	x30		// link register
diff --git a/arch/arm64/include/asm/atomic.h b/arch/arm64/include/asm/atomic.h
new file mode 100644
index 0000000..407717b
--- /dev/null
+++ b/arch/arm64/include/asm/atomic.h
@@ -0,0 +1,305 @@
+/*
+ * Based on arch/arm/include/asm/atomic.h
+ *
+ * Copyright (C) 1996 Russell King.
+ * Copyright (C) 2002 Deep Blue Solutions Ltd.
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_ATOMIC_H
+#define __ASM_ATOMIC_H
+
+#include <linux/compiler.h>
+#include <linux/types.h>
+
+#include <asm/barrier.h>
+#include <asm/cmpxchg.h>
+
+#define ATOMIC_INIT(i)	{ (i) }
+
+#ifdef __KERNEL__
+
+/*
+ * On ARM, ordinary assignment (str instruction) doesn't clear the local
+ * strex/ldrex monitor on some implementations. The reason we can use it for
+ * atomic_set() is the clrex or dummy strex done on every exception return.
+ */
+#define atomic_read(v)	(*(volatile int *)&(v)->counter)
+#define atomic_set(v,i)	(((v)->counter) = (i))
+
+/*
+ * AArch64 UP and SMP safe atomic ops.  We use load exclusive and
+ * store exclusive to ensure that these are atomic.  We may loop
+ * to ensure that the update happens.
+ */
+static inline void atomic_add(int i, atomic_t *v)
+{
+	unsigned long tmp;
+	int result;
+
+	asm volatile("// atomic_add\n"
+"1:	ldxr	%w0, [%3]\n"
+"	add	%w0, %w0, %w4\n"
+"	stxr	%w1, %w0, [%3]\n"
+"	cbnz	%w1, 1b"
+	: "=&r" (result), "=&r" (tmp), "+o" (v->counter)
+	: "r" (&v->counter), "Ir" (i)
+	: "cc");
+}
+
+static inline int atomic_add_return(int i, atomic_t *v)
+{
+	unsigned long tmp;
+	int result;
+
+	asm volatile("// atomic_add_return\n"
+"1:	ldaxr	%w0, [%3]\n"
+"	add	%w0, %w0, %w4\n"
+"	stlxr	%w1, %w0, [%3]\n"
+"	cbnz	%w1, 1b"
+	: "=&r" (result), "=&r" (tmp), "+o" (v->counter)
+	: "r" (&v->counter), "Ir" (i)
+	: "cc");
+
+	return result;
+}
+
+static inline void atomic_sub(int i, atomic_t *v)
+{
+	unsigned long tmp;
+	int result;
+
+	asm volatile("// atomic_sub\n"
+"1:	ldxr	%w0, [%3]\n"
+"	sub	%w0, %w0, %w4\n"
+"	stxr	%w1, %w0, [%3]\n"
+"	cbnz	%w1, 1b"
+	: "=&r" (result), "=&r" (tmp), "+o" (v->counter)
+	: "r" (&v->counter), "Ir" (i)
+	: "cc");
+}
+
+static inline int atomic_sub_return(int i, atomic_t *v)
+{
+	unsigned long tmp;
+	int result;
+
+	asm volatile("// atomic_sub_return\n"
+"1:	ldaxr	%w0, [%3]\n"
+"	sub	%w0, %w0, %w4\n"
+"	stlxr	%w1, %w0, [%3]\n"
+"	cbnz	%w1, 1b"
+	: "=&r" (result), "=&r" (tmp), "+o" (v->counter)
+	: "r" (&v->counter), "Ir" (i)
+	: "cc");
+
+	return result;
+}
+
+static inline int atomic_cmpxchg(atomic_t *ptr, int old, int new)
+{
+	unsigned long tmp;
+	int oldval;
+
+	asm volatile("// atomic_cmpxchg\n"
+"1:	ldaxr	%w1, [%3]\n"
+"	cmp	%w1, %w4\n"
+"	b.ne	2f\n"
+"	stlxr	%w0, %w5, [%3]\n"
+"	cbnz	%w0, 1b\n"
+"2:"
+	: "=&r" (tmp), "=&r" (oldval), "+o" (ptr->counter)
+	: "r" (&ptr->counter), "Ir" (old), "r" (new)
+	: "cc");
+
+	return oldval;
+}
+
+static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr)
+{
+	unsigned long tmp, tmp2;
+
+	asm volatile("// atomic_clear_mask\n"
+"1:	ldxr	%0, [%3]\n"
+"	bic	%0, %0, %4\n"
+"	stxr	%w1, %0, [%3]\n"
+"	cbnz	%w1, 1b"
+	: "=&r" (tmp), "=&r" (tmp2), "+o" (*addr)
+	: "r" (addr), "Ir" (mask)
+	: "cc");
+}
+
+#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
+
+static inline int __atomic_add_unless(atomic_t *v, int a, int u)
+{
+	int c, old;
+
+	c = atomic_read(v);
+	while (c != u && (old = atomic_cmpxchg((v), c, c + a)) != c)
+		c = old;
+	return c;
+}
+
+#define atomic_inc(v)		atomic_add(1, v)
+#define atomic_dec(v)		atomic_sub(1, v)
+
+#define atomic_inc_and_test(v)	(atomic_add_return(1, v) == 0)
+#define atomic_dec_and_test(v)	(atomic_sub_return(1, v) == 0)
+#define atomic_inc_return(v)    (atomic_add_return(1, v))
+#define atomic_dec_return(v)    (atomic_sub_return(1, v))
+#define atomic_sub_and_test(i, v) (atomic_sub_return(i, v) == 0)
+
+#define atomic_add_negative(i,v) (atomic_add_return(i, v) < 0)
+
+#define smp_mb__before_atomic_dec()	smp_mb()
+#define smp_mb__after_atomic_dec()	smp_mb()
+#define smp_mb__before_atomic_inc()	smp_mb()
+#define smp_mb__after_atomic_inc()	smp_mb()
+
+/*
+ * 64-bit atomic operations.
+ */
+#define ATOMIC64_INIT(i) { (i) }
+
+#define atomic64_read(v)	(*(volatile long long *)&(v)->counter)
+#define atomic64_set(v,i)	(((v)->counter) = (i))
+
+static inline void atomic64_add(u64 i, atomic64_t *v)
+{
+	long result;
+	unsigned long tmp;
+
+	asm volatile("// atomic64_add\n"
+"1:	ldxr	%0, [%3]\n"
+"	add	%0, %0, %4\n"
+"	stxr	%w1, %0, [%3]\n"
+"	cbnz	%w1, 1b"
+	: "=&r" (result), "=&r" (tmp), "+o" (v->counter)
+	: "r" (&v->counter), "Ir" (i)
+	: "cc");
+}
+
+static inline long atomic64_add_return(long i, atomic64_t *v)
+{
+	long result;
+	unsigned long tmp;
+
+	asm volatile("// atomic64_add_return\n"
+"1:	ldaxr	%0, [%3]\n"
+"	add	%0, %0, %4\n"
+"	stlxr	%w1, %0, [%3]\n"
+"	cbnz	%w1, 1b"
+	: "=&r" (result), "=&r" (tmp), "+o" (v->counter)
+	: "r" (&v->counter), "Ir" (i)
+	: "cc");
+
+	return result;
+}
+
+static inline void atomic64_sub(u64 i, atomic64_t *v)
+{
+	long result;
+	unsigned long tmp;
+
+	asm volatile("// atomic64_sub\n"
+"1:	ldxr	%0, [%3]\n"
+"	sub	%0, %0, %4\n"
+"	stxr	%w1, %0, [%3]\n"
+"	cbnz	%w1, 1b"
+	: "=&r" (result), "=&r" (tmp), "+o" (v->counter)
+	: "r" (&v->counter), "Ir" (i)
+	: "cc");
+}
+
+static inline long atomic64_sub_return(long i, atomic64_t *v)
+{
+	long result;
+	unsigned long tmp;
+
+	asm volatile("// atomic64_sub_return\n"
+"1:	ldaxr	%0, [%3]\n"
+"	sub	%0, %0, %4\n"
+"	stlxr	%w1, %0, [%3]\n"
+"	cbnz	%w1, 1b"
+	: "=&r" (result), "=&r" (tmp), "+o" (v->counter)
+	: "r" (&v->counter), "Ir" (i)
+	: "cc");
+
+	return result;
+}
+
+static inline long atomic64_cmpxchg(atomic64_t *ptr, long old, long new)
+{
+	long oldval;
+	unsigned long res;
+
+	asm volatile("// atomic64_cmpxchg\n"
+"1:	ldaxr	%1, [%3]\n"
+"	cmp	%1, %4\n"
+"	b.ne	2f\n"
+"	stlxr	%w0, %5, [%3]\n"
+"	cbnz	%w0, 1b\n"
+"2:"
+	: "=&r" (res), "=&r" (oldval), "+o" (ptr->counter)
+	: "r" (&ptr->counter), "Ir" (old), "r" (new)
+	: "cc");
+
+	return oldval;
+}
+
+#define atomic64_xchg(v, new) (xchg(&((v)->counter), new))
+
+static inline long atomic64_dec_if_positive(atomic64_t *v)
+{
+	long result;
+	unsigned long tmp;
+
+	asm volatile("// atomic64_dec_if_positive\n"
+"1:	ldaxr	%0, [%3]\n"
+"	subs	%0, %0, #1\n"
+"	b.mi	2f\n"
+"	stlxr	%w1, %0, [%3]\n"
+"	cbnz	%w1, 1b\n"
+"2:"
+	: "=&r" (result), "=&r" (tmp), "+o" (v->counter)
+	: "r" (&v->counter)
+	: "cc");
+
+	return result;
+}
+
+static inline int atomic64_add_unless(atomic64_t *v, long a, long u)
+{
+	long c, old;
+
+	c = atomic64_read(v);
+	while (c != u && (old = atomic64_cmpxchg((v), c, c + a)) != c)
+		c = old;
+
+	return c != u;
+}
+
+#define atomic64_add_negative(a, v)	(atomic64_add_return((a), (v)) < 0)
+#define atomic64_inc(v)			atomic64_add(1LL, (v))
+#define atomic64_inc_return(v)		atomic64_add_return(1LL, (v))
+#define atomic64_inc_and_test(v)	(atomic64_inc_return(v) == 0)
+#define atomic64_sub_and_test(a, v)	(atomic64_sub_return((a), (v)) == 0)
+#define atomic64_dec(v)			atomic64_sub(1LL, (v))
+#define atomic64_dec_return(v)		atomic64_sub_return(1LL, (v))
+#define atomic64_dec_and_test(v)	(atomic64_dec_return((v)) == 0)
+#define atomic64_inc_not_zero(v)	atomic64_add_unless((v), 1LL, 0LL)
+
+#endif
+#endif
diff --git a/arch/arm64/include/asm/auxvec.h b/arch/arm64/include/asm/auxvec.h
new file mode 100644
index 0000000..22d6d88
--- /dev/null
+++ b/arch/arm64/include/asm/auxvec.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_AUXVEC_H
+#define __ASM_AUXVEC_H
+
+/* vDSO location */
+#define AT_SYSINFO_EHDR	33
+
+#endif
diff --git a/arch/arm64/include/asm/barrier.h b/arch/arm64/include/asm/barrier.h
new file mode 100644
index 0000000..d4a6333
--- /dev/null
+++ b/arch/arm64/include/asm/barrier.h
@@ -0,0 +1,52 @@
+/*
+ * Based on arch/arm/include/asm/barrier.h
+ *
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_BARRIER_H
+#define __ASM_BARRIER_H
+
+#ifndef __ASSEMBLY__
+
+#define sev()		asm volatile("sev" : : : "memory")
+#define wfe()		asm volatile("wfe" : : : "memory")
+#define wfi()		asm volatile("wfi" : : : "memory")
+
+#define isb()		asm volatile("isb" : : : "memory")
+#define dsb()		asm volatile("dsb sy" : : : "memory")
+
+#define mb()		dsb()
+#define rmb()		asm volatile("dsb ld" : : : "memory")
+#define wmb()		asm volatile("dsb st" : : : "memory")
+
+#ifndef CONFIG_SMP
+#define smp_mb()	barrier()
+#define smp_rmb()	barrier()
+#define smp_wmb()	barrier()
+#else
+#define smp_mb()	asm volatile("dmb ish" : : : "memory")
+#define smp_rmb()	asm volatile("dmb ishld" : : : "memory")
+#define smp_wmb()	asm volatile("dmb ishst" : : : "memory")
+#endif
+
+#define read_barrier_depends()		do { } while(0)
+#define smp_read_barrier_depends()	do { } while(0)
+
+#define set_mb(var, value)	do { var = value; smp_mb(); } while (0)
+#define nop()		asm volatile("nop");
+
+#endif	/* __ASSEMBLY__ */
+
+#endif	/* __ASM_BARRIER_H */
diff --git a/arch/arm64/include/asm/bitops.h b/arch/arm64/include/asm/bitops.h
new file mode 100644
index 0000000..5e69307
--- /dev/null
+++ b/arch/arm64/include/asm/bitops.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_BITOPS_H
+#define __ASM_BITOPS_H
+
+#include <linux/compiler.h>
+
+#include <asm/barrier.h>
+
+/*
+ * clear_bit may not imply a memory barrier
+ */
+#ifndef smp_mb__before_clear_bit
+#define smp_mb__before_clear_bit()	smp_mb()
+#define smp_mb__after_clear_bit()	smp_mb()
+#endif
+
+#ifndef _LINUX_BITOPS_H
+#error only <linux/bitops.h> can be included directly
+#endif
+
+#include <asm-generic/bitops/builtin-__ffs.h>
+#include <asm-generic/bitops/builtin-ffs.h>
+#include <asm-generic/bitops/builtin-__fls.h>
+#include <asm-generic/bitops/builtin-fls.h>
+
+#include <asm-generic/bitops/ffz.h>
+#include <asm-generic/bitops/fls64.h>
+#include <asm-generic/bitops/find.h>
+
+#include <asm-generic/bitops/sched.h>
+#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/lock.h>
+
+#include <asm-generic/bitops/atomic.h>
+#include <asm-generic/bitops/non-atomic.h>
+#include <asm-generic/bitops/le.h>
+#include <asm-generic/bitops/ext2-atomic.h>
+
+#endif /* __ASM_BITOPS_H */
diff --git a/arch/arm64/include/asm/bitsperlong.h b/arch/arm64/include/asm/bitsperlong.h
new file mode 100644
index 0000000..fce9c29
--- /dev/null
+++ b/arch/arm64/include/asm/bitsperlong.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_BITSPERLONG_H
+#define __ASM_BITSPERLONG_H
+
+#define __BITS_PER_LONG 64
+
+#include <asm-generic/bitsperlong.h>
+
+#endif	/* __ASM_BITSPERLONG_H */
diff --git a/arch/arm64/include/asm/byteorder.h b/arch/arm64/include/asm/byteorder.h
new file mode 100644
index 0000000..2b92046
--- /dev/null
+++ b/arch/arm64/include/asm/byteorder.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_BYTEORDER_H
+#define __ASM_BYTEORDER_H
+
+#include <linux/byteorder/little_endian.h>
+
+#endif	/* __ASM_BYTEORDER_H */
diff --git a/arch/arm64/include/asm/cache.h b/arch/arm64/include/asm/cache.h
new file mode 100644
index 0000000..390308a
--- /dev/null
+++ b/arch/arm64/include/asm/cache.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_CACHE_H
+#define __ASM_CACHE_H
+
+#define L1_CACHE_SHIFT		6
+#define L1_CACHE_BYTES		(1 << L1_CACHE_SHIFT)
+
+/*
+ * Memory returned by kmalloc() may be used for DMA, so we must make
+ * sure that all such allocations are cache aligned. Otherwise,
+ * unrelated code may cause parts of the buffer to be read into the
+ * cache before the transfer is done, causing old data to be seen by
+ * the CPU.
+ */
+#define ARCH_DMA_MINALIGN	L1_CACHE_BYTES
+#define ARCH_SLAB_MINALIGN	8
+
+#endif
diff --git a/arch/arm64/include/asm/cacheflush.h b/arch/arm64/include/asm/cacheflush.h
new file mode 100644
index 0000000..aa3132a
--- /dev/null
+++ b/arch/arm64/include/asm/cacheflush.h
@@ -0,0 +1,148 @@
+/*
+ * Based on arch/arm/include/asm/cacheflush.h
+ *
+ * Copyright (C) 1999-2002 Russell King.
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_CACHEFLUSH_H
+#define __ASM_CACHEFLUSH_H
+
+#include <linux/mm.h>
+
+/*
+ * This flag is used to indicate that the page pointed to by a pte is clean
+ * and does not require cleaning before returning it to the user.
+ */
+#define PG_dcache_clean PG_arch_1
+
+/*
+ *	MM Cache Management
+ *	===================
+ *
+ *	The arch/arm64/mm/cache.S implements these methods.
+ *
+ *	Start addresses are inclusive and end addresses are exclusive; start
+ *	addresses should be rounded down, end addresses up.
+ *
+ *	See Documentation/cachetlb.txt for more information. Please note that
+ *	the implementation assumes non-aliasing VIPT D-cache and (aliasing)
+ *	VIPT or ASID-tagged VIVT I-cache.
+ *
+ *	flush_cache_all()
+ *
+ *		Unconditionally clean and invalidate the entire cache.
+ *
+ *	flush_cache_mm(mm)
+ *
+ *		Clean and invalidate all user space cache entries
+ *		before a change of page tables.
+ *
+ *	flush_icache_range(start, end)
+ *
+ *		Ensure coherency between the I-cache and the D-cache in the
+ *		region described by start, end.
+ *		- start  - virtual start address
+ *		- end    - virtual end address
+ *
+ *	__flush_cache_user_range(start, end)
+ *
+ *		Ensure coherency between the I-cache and the D-cache in the
+ *		region described by start, end.
+ *		- start  - virtual start address
+ *		- end    - virtual end address
+ *
+ *	__flush_dcache_area(kaddr, size)
+ *
+ *		Ensure that the data held in page is written back.
+ *		- kaddr  - page address
+ *		- size   - region size
+ */
+extern void flush_cache_all(void);
+extern void flush_cache_mm(struct mm_struct *mm);
+extern void flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end);
+extern void flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr, unsigned long pfn);
+extern void flush_icache_range(unsigned long start, unsigned long end);
+extern void __flush_dcache_area(void *addr, size_t len);
+extern void __flush_cache_user_range(unsigned long start, unsigned long end);
+
+/*
+ * Copy user data from/to a page which is mapped into a different
+ * processes address space.  Really, we want to allow our "user
+ * space" model to handle this.
+ */
+extern void copy_to_user_page(struct vm_area_struct *, struct page *,
+	unsigned long, void *, const void *, unsigned long);
+#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
+	do {							\
+		memcpy(dst, src, len);				\
+	} while (0)
+
+#define flush_cache_dup_mm(mm) flush_cache_mm(mm)
+
+/*
+ * flush_dcache_page is used when the kernel has written to the page
+ * cache page at virtual address page->virtual.
+ *
+ * If this page isn't mapped (ie, page_mapping == NULL), or it might
+ * have userspace mappings, then we _must_ always clean + invalidate
+ * the dcache entries associated with the kernel mapping.
+ *
+ * Otherwise we can defer the operation, and clean the cache when we are
+ * about to change to user space.  This is the same method as used on SPARC64.
+ * See update_mmu_cache for the user space part.
+ */
+#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
+extern void flush_dcache_page(struct page *);
+
+static inline void __flush_icache_all(void)
+{
+	asm("ic	ialluis");
+}
+
+#define flush_dcache_mmap_lock(mapping) \
+	spin_lock_irq(&(mapping)->tree_lock)
+#define flush_dcache_mmap_unlock(mapping) \
+	spin_unlock_irq(&(mapping)->tree_lock)
+
+#define flush_icache_user_range(vma,page,addr,len) \
+	flush_dcache_page(page)
+
+/*
+ * We don't appear to need to do anything here.  In fact, if we did, we'd
+ * duplicate cache flushing elsewhere performed by flush_dcache_page().
+ */
+#define flush_icache_page(vma,page)	do { } while (0)
+
+/*
+ * flush_cache_vmap() is used when creating mappings (eg, via vmap,
+ * vmalloc, ioremap etc) in kernel space for pages.  On non-VIPT
+ * caches, since the direct-mappings of these pages may contain cached
+ * data, we need to do a full cache flush to ensure that writebacks
+ * don't corrupt data placed into these pages via the new mappings.
+ */
+static inline void flush_cache_vmap(unsigned long start, unsigned long end)
+{
+	/*
+	 * set_pte_at() called from vmap_pte_range() does not
+	 * have a DSB after cleaning the cache line.
+	 */
+	dsb();
+}
+
+static inline void flush_cache_vunmap(unsigned long start, unsigned long end)
+{
+}
+
+#endif
diff --git a/arch/arm64/include/asm/cachetype.h b/arch/arm64/include/asm/cachetype.h
new file mode 100644
index 0000000..85f5f51
--- /dev/null
+++ b/arch/arm64/include/asm/cachetype.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_CACHETYPE_H
+#define __ASM_CACHETYPE_H
+
+#include <asm/cputype.h>
+
+#define CTR_L1IP_SHIFT		14
+#define CTR_L1IP_MASK		3
+
+#define ICACHE_POLICY_RESERVED	0
+#define ICACHE_POLICY_AIVIVT	1
+#define ICACHE_POLICY_VIPT	2
+#define ICACHE_POLICY_PIPT	3
+
+static inline u32 icache_policy(void)
+{
+	return (read_cpuid_cachetype() >> CTR_L1IP_SHIFT) & CTR_L1IP_MASK;
+}
+
+/*
+ * Whilst the D-side always behaves as PIPT on AArch64, aliasing is
+ * permitted in the I-cache.
+ */
+static inline int icache_is_aliasing(void)
+{
+	return icache_policy() != ICACHE_POLICY_PIPT;
+}
+
+static inline int icache_is_aivivt(void)
+{
+	return icache_policy() == ICACHE_POLICY_AIVIVT;
+}
+
+#endif	/* __ASM_CACHETYPE_H */
diff --git a/arch/arm64/include/asm/cmpxchg.h b/arch/arm64/include/asm/cmpxchg.h
new file mode 100644
index 0000000..e0e65b0
--- /dev/null
+++ b/arch/arm64/include/asm/cmpxchg.h
@@ -0,0 +1,173 @@
+/*
+ * Based on arch/arm/include/asm/cmpxchg.h
+ *
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_CMPXCHG_H
+#define __ASM_CMPXCHG_H
+
+#include <linux/bug.h>
+
+#include <asm/barrier.h>
+
+static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size)
+{
+	unsigned long ret, tmp;
+
+	switch (size) {
+	case 1:
+		asm volatile("//	__xchg1\n"
+		"1:	ldaxrb	%w0, [%3]\n"
+		"	stlxrb	%w1, %w2, [%3]\n"
+		"	cbnz	%w1, 1b\n"
+			: "=&r" (ret), "=&r" (tmp)
+			: "r" (x), "r" (ptr)
+			: "memory", "cc");
+		break;
+	case 2:
+		asm volatile("//	__xchg2\n"
+		"1:	ldaxrh	%w0, [%3]\n"
+		"	stlxrh	%w1, %w2, [%3]\n"
+		"	cbnz	%w1, 1b\n"
+			: "=&r" (ret), "=&r" (tmp)
+			: "r" (x), "r" (ptr)
+			: "memory", "cc");
+		break;
+	case 4:
+		asm volatile("//	__xchg4\n"
+		"1:	ldaxr	%w0, [%3]\n"
+		"	stlxr	%w1, %w2, [%3]\n"
+		"	cbnz	%w1, 1b\n"
+			: "=&r" (ret), "=&r" (tmp)
+			: "r" (x), "r" (ptr)
+			: "memory", "cc");
+		break;
+	case 8:
+		asm volatile("//	__xchg8\n"
+		"1:	ldaxr	%0, [%3]\n"
+		"	stlxr	%w1, %2, [%3]\n"
+		"	cbnz	%w1, 1b\n"
+			: "=&r" (ret), "=&r" (tmp)
+			: "r" (x), "r" (ptr)
+			: "memory", "cc");
+		break;
+	default:
+		BUILD_BUG();
+	}
+
+	return ret;
+}
+
+#define xchg(ptr,x) \
+	((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
+
+static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
+				      unsigned long new, int size)
+{
+	unsigned long oldval = 0, res;
+
+	switch (size) {
+	case 1:
+		do {
+			asm volatile("// __cmpxchg1\n"
+			"	ldxrb	%w1, [%2]\n"
+			"	mov	%w0, #0\n"
+			"	cmp	%w1, %w3\n"
+			"	b.ne	1f\n"
+			"	stxrb	%w0, %w4, [%2]\n"
+			"1:\n"
+				: "=&r" (res), "=&r" (oldval)
+				: "r" (ptr), "Ir" (old), "r" (new)
+				: "cc");
+		} while (res);
+		break;
+
+	case 2:
+		do {
+			asm volatile("// __cmpxchg2\n"
+			"	ldxrh	%w1, [%2]\n"
+			"	mov	%w0, #0\n"
+			"	cmp	%w1, %w3\n"
+			"	b.ne	1f\n"
+			"	stxrh	%w0, %w4, [%2]\n"
+			"1:\n"
+				: "=&r" (res), "=&r" (oldval)
+				: "r" (ptr), "Ir" (old), "r" (new)
+				: "memory", "cc");
+		} while (res);
+		break;
+
+	case 4:
+		do {
+			asm volatile("// __cmpxchg4\n"
+			"	ldxr	%w1, [%2]\n"
+			"	mov	%w0, #0\n"
+			"	cmp	%w1, %w3\n"
+			"	b.ne	1f\n"
+			"	stxr	%w0, %w4, [%2]\n"
+			"1:\n"
+				: "=&r" (res), "=&r" (oldval)
+				: "r" (ptr), "Ir" (old), "r" (new)
+				: "cc");
+		} while (res);
+		break;
+
+	case 8:
+		do {
+			asm volatile("// __cmpxchg8\n"
+			"	ldxr	%1, [%2]\n"
+			"	mov	%w0, #0\n"
+			"	cmp	%1, %3\n"
+			"	b.ne	1f\n"
+			"	stxr	%w0, %4, [%2]\n"
+			"1:\n"
+				: "=&r" (res), "=&r" (oldval)
+				: "r" (ptr), "Ir" (old), "r" (new)
+				: "cc");
+		} while (res);
+		break;
+
+	default:
+		BUILD_BUG();
+	}
+
+	return oldval;
+}
+
+static inline unsigned long __cmpxchg_mb(volatile void *ptr, unsigned long old,
+					 unsigned long new, int size)
+{
+	unsigned long ret;
+
+	smp_mb();
+	ret = __cmpxchg(ptr, old, new, size);
+	smp_mb();
+
+	return ret;
+}
+
+#define cmpxchg(ptr,o,n)						\
+	((__typeof__(*(ptr)))__cmpxchg_mb((ptr),			\
+					  (unsigned long)(o),		\
+					  (unsigned long)(n),		\
+					  sizeof(*(ptr))))
+
+#define cmpxchg_local(ptr,o,n)						\
+	((__typeof__(*(ptr)))__cmpxchg((ptr),				\
+				       (unsigned long)(o),		\
+				       (unsigned long)(n),		\
+				       sizeof(*(ptr))))
+
+#endif	/* __ASM_CMPXCHG_H */
diff --git a/arch/arm64/include/asm/compat.h b/arch/arm64/include/asm/compat.h
new file mode 100644
index 0000000..37e610d
--- /dev/null
+++ b/arch/arm64/include/asm/compat.h
@@ -0,0 +1,300 @@
+/*
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_COMPAT_H
+#define __ASM_COMPAT_H
+#ifdef __KERNEL__
+#ifdef CONFIG_COMPAT
+
+/*
+ * Architecture specific compatibility types
+ */
+#include <linux/types.h>
+#include <linux/sched.h>
+
+#define COMPAT_USER_HZ		100
+#define COMPAT_UTS_MACHINE	"armv8l\0\0"
+
+typedef u32		compat_size_t;
+typedef s32		compat_ssize_t;
+typedef s32		compat_time_t;
+typedef s32		compat_clock_t;
+typedef s32		compat_pid_t;
+typedef u32		__compat_uid_t;
+typedef u32		__compat_gid_t;
+typedef u32		__compat_uid32_t;
+typedef u32		__compat_gid32_t;
+typedef u32		compat_mode_t;
+typedef u32		compat_ino_t;
+typedef u32		compat_dev_t;
+typedef s32		compat_off_t;
+typedef s64		compat_loff_t;
+typedef s16		compat_nlink_t;
+typedef u16		compat_ipc_pid_t;
+typedef s32		compat_daddr_t;
+typedef u32		compat_caddr_t;
+typedef __kernel_fsid_t	compat_fsid_t;
+typedef s32		compat_key_t;
+typedef s32		compat_timer_t;
+
+typedef s32		compat_int_t;
+typedef s32		compat_long_t;
+typedef s64		compat_s64;
+typedef u32		compat_uint_t;
+typedef u32		compat_ulong_t;
+typedef u64		compat_u64;
+typedef u32		compat_uptr_t;
+
+struct compat_timespec {
+	compat_time_t	tv_sec;
+	s32		tv_nsec;
+};
+
+struct compat_timeval {
+	compat_time_t	tv_sec;
+	s32		tv_usec;
+};
+
+struct compat_stat {
+	compat_dev_t	st_dev;
+	compat_ino_t	st_ino;
+	compat_mode_t	st_mode;
+	compat_nlink_t	st_nlink;
+	__compat_uid32_t	st_uid;
+	__compat_gid32_t	st_gid;
+	compat_dev_t	st_rdev;
+	compat_off_t	st_size;
+	compat_off_t	st_blksize;
+	compat_off_t	st_blocks;
+	compat_time_t	st_atime;
+	u32		st_atime_nsec;
+	compat_time_t	st_mtime;
+	u32		st_mtime_nsec;
+	compat_time_t	st_ctime;
+	u32		st_ctime_nsec;
+	u32		__unused4[2];
+};
+
+struct compat_flock {
+	short		l_type;
+	short		l_whence;
+	compat_off_t	l_start;
+	compat_off_t	l_len;
+	compat_pid_t	l_pid;
+};
+
+#define F_GETLK64	12	/*  using 'struct flock64' */
+#define F_SETLK64	13
+#define F_SETLKW64	14
+
+struct compat_flock64 {
+	short		l_type;
+	short		l_whence;
+	compat_loff_t	l_start;
+	compat_loff_t	l_len;
+	compat_pid_t	l_pid;
+};
+
+struct compat_statfs {
+	int		f_type;
+	int		f_bsize;
+	int		f_blocks;
+	int		f_bfree;
+	int		f_bavail;
+	int		f_files;
+	int		f_ffree;
+	compat_fsid_t	f_fsid;
+	int		f_namelen;	/* SunOS ignores this field. */
+	int		f_frsize;
+	int		f_flags;
+	int		f_spare[4];
+};
+
+#define COMPAT_RLIM_INFINITY		0xffffffff
+
+typedef u32		compat_old_sigset_t;
+
+#define _COMPAT_NSIG		64
+#define _COMPAT_NSIG_BPW	32
+
+typedef u32		compat_sigset_word;
+
+typedef union compat_sigval {
+	compat_int_t	sival_int;
+	compat_uptr_t	sival_ptr;
+} compat_sigval_t;
+
+typedef struct compat_siginfo {
+	int si_signo;
+	int si_errno;
+	int si_code;
+
+	union {
+		/* The padding is the same size as AArch64. */
+		int _pad[128/sizeof(int) - 3];
+
+		/* kill() */
+		struct {
+			compat_pid_t _pid;	/* sender's pid */
+			__compat_uid32_t _uid;	/* sender's uid */
+		} _kill;
+
+		/* POSIX.1b timers */
+		struct {
+			compat_timer_t _tid;	/* timer id */
+			int _overrun;		/* overrun count */
+			compat_sigval_t _sigval;	/* same as below */
+			int _sys_private;       /* not to be passed to user */
+		} _timer;
+
+		/* POSIX.1b signals */
+		struct {
+			compat_pid_t _pid;	/* sender's pid */
+			__compat_uid32_t _uid;	/* sender's uid */
+			compat_sigval_t _sigval;
+		} _rt;
+
+		/* SIGCHLD */
+		struct {
+			compat_pid_t _pid;	/* which child */
+			__compat_uid32_t _uid;	/* sender's uid */
+			int _status;		/* exit code */
+			compat_clock_t _utime;
+			compat_clock_t _stime;
+		} _sigchld;
+
+		/* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
+		struct {
+			compat_uptr_t _addr; /* faulting insn/memory ref. */
+			short _addr_lsb; /* LSB of the reported address */
+		} _sigfault;
+
+		/* SIGPOLL */
+		struct {
+			compat_long_t _band;	/* POLL_IN, POLL_OUT, POLL_MSG */
+			int _fd;
+		} _sigpoll;
+	} _sifields;
+} compat_siginfo_t;
+
+#define COMPAT_OFF_T_MAX	0x7fffffff
+#define COMPAT_LOFF_T_MAX	0x7fffffffffffffffL
+
+/*
+ * A pointer passed in from user mode. This should not
+ * be used for syscall parameters, just declare them
+ * as pointers because the syscall entry code will have
+ * appropriately converted them already.
+ */
+
+static inline void __user *compat_ptr(compat_uptr_t uptr)
+{
+	return (void __user *)(unsigned long)uptr;
+}
+
+static inline compat_uptr_t ptr_to_compat(void __user *uptr)
+{
+	return (u32)(unsigned long)uptr;
+}
+
+static inline void __user *arch_compat_alloc_user_space(long len)
+{
+	struct pt_regs *regs = task_pt_regs(current);
+	return (void __user *)regs->compat_sp - len;
+}
+
+struct compat_ipc64_perm {
+	compat_key_t key;
+	__compat_uid32_t uid;
+	__compat_gid32_t gid;
+	__compat_uid32_t cuid;
+	__compat_gid32_t cgid;
+	unsigned short mode;
+	unsigned short __pad1;
+	unsigned short seq;
+	unsigned short __pad2;
+	compat_ulong_t unused1;
+	compat_ulong_t unused2;
+};
+
+struct compat_semid64_ds {
+	struct compat_ipc64_perm sem_perm;
+	compat_time_t  sem_otime;
+	compat_ulong_t __unused1;
+	compat_time_t  sem_ctime;
+	compat_ulong_t __unused2;
+	compat_ulong_t sem_nsems;
+	compat_ulong_t __unused3;
+	compat_ulong_t __unused4;
+};
+
+struct compat_msqid64_ds {
+	struct compat_ipc64_perm msg_perm;
+	compat_time_t  msg_stime;
+	compat_ulong_t __unused1;
+	compat_time_t  msg_rtime;
+	compat_ulong_t __unused2;
+	compat_time_t  msg_ctime;
+	compat_ulong_t __unused3;
+	compat_ulong_t msg_cbytes;
+	compat_ulong_t msg_qnum;
+	compat_ulong_t msg_qbytes;
+	compat_pid_t   msg_lspid;
+	compat_pid_t   msg_lrpid;
+	compat_ulong_t __unused4;
+	compat_ulong_t __unused5;
+};
+
+struct compat_shmid64_ds {
+	struct compat_ipc64_perm shm_perm;
+	compat_size_t  shm_segsz;
+	compat_time_t  shm_atime;
+	compat_ulong_t __unused1;
+	compat_time_t  shm_dtime;
+	compat_ulong_t __unused2;
+	compat_time_t  shm_ctime;
+	compat_ulong_t __unused3;
+	compat_pid_t   shm_cpid;
+	compat_pid_t   shm_lpid;
+	compat_ulong_t shm_nattch;
+	compat_ulong_t __unused4;
+	compat_ulong_t __unused5;
+};
+
+static inline int is_compat_task(void)
+{
+	return test_thread_flag(TIF_32BIT);
+}
+
+static inline int is_compat_thread(struct thread_info *thread)
+{
+	return test_ti_thread_flag(thread, TIF_32BIT);
+}
+
+#else /* !CONFIG_COMPAT */
+
+static inline int is_compat_task(void)
+{
+	return 0;
+}
+
+static inline int is_compat_thread(struct thread_info *thread)
+{
+	return 0;
+}
+
+#endif /* CONFIG_COMPAT */
+#endif /* __KERNEL__ */
+#endif /* __ASM_COMPAT_H */
diff --git a/arch/arm64/include/asm/compiler.h b/arch/arm64/include/asm/compiler.h
new file mode 100644
index 0000000..ee35fd0
--- /dev/null
+++ b/arch/arm64/include/asm/compiler.h
@@ -0,0 +1,30 @@
+/*
+ * Based on arch/arm/include/asm/compiler.h
+ *
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_COMPILER_H
+#define __ASM_COMPILER_H
+
+/*
+ * This is used to ensure the compiler did actually allocate the register we
+ * asked it for some inline assembly sequences.  Apparently we can't trust the
+ * compiler from one version to another so a bit of paranoia won't hurt.  This
+ * string is meant to be concatenated with the inline asm string and will
+ * cause compilation to stop on mismatch.  (for details, see gcc PR 15089)
+ */
+#define __asmeq(x, y)  ".ifnc " x "," y " ; .err ; .endif\n\t"
+
+#endif	/* __ASM_COMPILER_H */
diff --git a/arch/arm64/include/asm/cputable.h b/arch/arm64/include/asm/cputable.h
new file mode 100644
index 0000000..e3bd983
--- /dev/null
+++ b/arch/arm64/include/asm/cputable.h
@@ -0,0 +1,30 @@
+/*
+ * arch/arm64/include/asm/cputable.h
+ *
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_CPUTABLE_H
+#define __ASM_CPUTABLE_H
+
+struct cpu_info {
+	unsigned int	cpu_id_val;
+	unsigned int	cpu_id_mask;
+	const char	*cpu_name;
+	unsigned long	(*cpu_setup)(void);
+};
+
+extern struct cpu_info *lookup_processor_type(unsigned int);
+
+#endif
diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h
new file mode 100644
index 0000000..ef54125
--- /dev/null
+++ b/arch/arm64/include/asm/cputype.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_CPUTYPE_H
+#define __ASM_CPUTYPE_H
+
+#define ID_MIDR_EL1		"midr_el1"
+#define ID_CTR_EL0		"ctr_el0"
+
+#define ID_AA64PFR0_EL1		"id_aa64pfr0_el1"
+#define ID_AA64DFR0_EL1		"id_aa64dfr0_el1"
+#define ID_AA64AFR0_EL1		"id_aa64afr0_el1"
+#define ID_AA64ISAR0_EL1	"id_aa64isar0_el1"
+#define ID_AA64MMFR0_EL1	"id_aa64mmfr0_el1"
+
+#define read_cpuid(reg) ({						\
+	u64 __val;							\
+	asm("mrs	%0, " reg : "=r" (__val));			\
+	__val;								\
+})
+
+/*
+ * The CPU ID never changes at run time, so we might as well tell the
+ * compiler that it's constant.  Use this function to read the CPU ID
+ * rather than directly reading processor_id or read_cpuid() directly.
+ */
+static inline u32 __attribute_const__ read_cpuid_id(void)
+{
+	return read_cpuid(ID_MIDR_EL1);
+}
+
+static inline u32 __attribute_const__ read_cpuid_cachetype(void)
+{
+	return read_cpuid(ID_CTR_EL0);
+}
+
+#endif
diff --git a/arch/arm64/include/asm/debug-monitors.h b/arch/arm64/include/asm/debug-monitors.h
new file mode 100644
index 0000000..7eaa0b3
--- /dev/null
+++ b/arch/arm64/include/asm/debug-monitors.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_DEBUG_MONITORS_H
+#define __ASM_DEBUG_MONITORS_H
+
+#ifdef __KERNEL__
+
+#define	DBG_ESR_EVT(x)		(((x) >> 27) & 0x7)
+
+/* AArch64 */
+#define DBG_ESR_EVT_HWBP	0x0
+#define DBG_ESR_EVT_HWSS	0x1
+#define DBG_ESR_EVT_HWWP	0x2
+#define DBG_ESR_EVT_BRK		0x6
+
+enum debug_el {
+	DBG_ACTIVE_EL0 = 0,
+	DBG_ACTIVE_EL1,
+};
+
+/* AArch32 */
+#define DBG_ESR_EVT_BKPT	0x4
+#define DBG_ESR_EVT_VECC	0x5
+
+#define AARCH32_BREAK_ARM	0x07f001f0
+#define AARCH32_BREAK_THUMB	0xde01
+#define AARCH32_BREAK_THUMB2_LO	0xf7f0
+#define AARCH32_BREAK_THUMB2_HI	0xa000
+
+#ifndef __ASSEMBLY__
+struct task_struct;
+
+#define local_dbg_save(flags)							\
+	do {									\
+		typecheck(unsigned long, flags);				\
+		asm volatile(							\
+		"mrs	%0, daif			// local_dbg_save\n"	\
+		"msr	daifset, #8"						\
+		: "=r" (flags) : : "memory");					\
+	} while (0)
+
+#define local_dbg_restore(flags)						\
+	do {									\
+		typecheck(unsigned long, flags);				\
+		asm volatile(							\
+		"msr	daif, %0			// local_dbg_restore\n"	\
+		: : "r" (flags) : "memory");					\
+	} while (0)
+
+#define DBG_ARCH_ID_RESERVED	0	/* In case of ptrace ABI updates. */
+
+u8 debug_monitors_arch(void);
+
+void enable_debug_monitors(enum debug_el el);
+void disable_debug_monitors(enum debug_el el);
+
+void user_rewind_single_step(struct task_struct *task);
+void user_fastforward_single_step(struct task_struct *task);
+
+void kernel_enable_single_step(struct pt_regs *regs);
+void kernel_disable_single_step(void);
+int kernel_active_single_step(void);
+
+#ifdef CONFIG_HAVE_HW_BREAKPOINT
+int reinstall_suspended_bps(struct pt_regs *regs);
+#else
+static inline int reinstall_suspended_bps(struct pt_regs *regs)
+{
+	return -ENODEV;
+}
+#endif
+
+#endif	/* __ASSEMBLY */
+#endif	/* __KERNEL__ */
+#endif	/* __ASM_DEBUG_MONITORS_H */
diff --git a/arch/arm64/include/asm/device.h b/arch/arm64/include/asm/device.h
new file mode 100644
index 0000000..0d8453c
--- /dev/null
+++ b/arch/arm64/include/asm/device.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_DEVICE_H
+#define __ASM_DEVICE_H
+
+struct dev_archdata {
+	struct dma_map_ops *dma_ops;
+};
+
+struct pdev_archdata {
+};
+
+#endif
diff --git a/arch/arm64/include/asm/dma-mapping.h b/arch/arm64/include/asm/dma-mapping.h
new file mode 100644
index 0000000..538f4b4
--- /dev/null
+++ b/arch/arm64/include/asm/dma-mapping.h
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_DMA_MAPPING_H
+#define __ASM_DMA_MAPPING_H
+
+#ifdef __KERNEL__
+
+#include <linux/types.h>
+#include <linux/vmalloc.h>
+
+#include <asm-generic/dma-coherent.h>
+
+#define ARCH_HAS_DMA_GET_REQUIRED_MASK
+
+extern struct dma_map_ops *dma_ops;
+
+static inline struct dma_map_ops *get_dma_ops(struct device *dev)
+{
+	if (unlikely(!dev) || !dev->archdata.dma_ops)
+		return dma_ops;
+	else
+		return dev->archdata.dma_ops;
+}
+
+#include <asm-generic/dma-mapping-common.h>
+
+static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
+{
+	return (dma_addr_t)paddr;
+}
+
+static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t dev_addr)
+{
+	return (phys_addr_t)dev_addr;
+}
+
+static inline int dma_mapping_error(struct device *dev, dma_addr_t dev_addr)
+{
+	struct dma_map_ops *ops = get_dma_ops(dev);
+	return ops->mapping_error(dev, dev_addr);
+}
+
+static inline int dma_supported(struct device *dev, u64 mask)
+{
+	struct dma_map_ops *ops = get_dma_ops(dev);
+	return ops->dma_supported(dev, mask);
+}
+
+static inline int dma_set_mask(struct device *dev, u64 mask)
+{
+	if (!dev->dma_mask || !dma_supported(dev, mask))
+		return -EIO;
+	*dev->dma_mask = mask;
+
+	return 0;
+}
+
+static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
+{
+	if (!dev->dma_mask)
+		return 0;
+
+	return addr + size - 1 <= *dev->dma_mask;
+}
+
+static inline void dma_mark_clean(void *addr, size_t size)
+{
+}
+
+static inline void *dma_alloc_coherent(struct device *dev, size_t size,
+				       dma_addr_t *dma_handle, gfp_t flags)
+{
+	struct dma_map_ops *ops = get_dma_ops(dev);
+	void *vaddr;
+
+	if (dma_alloc_from_coherent(dev, size, dma_handle, &vaddr))
+		return vaddr;
+
+	vaddr = ops->alloc(dev, size, dma_handle, flags, NULL);
+	debug_dma_alloc_coherent(dev, size, *dma_handle, vaddr);
+	return vaddr;
+}
+
+static inline void dma_free_coherent(struct device *dev, size_t size,
+				     void *vaddr, dma_addr_t dev_addr)
+{
+	struct dma_map_ops *ops = get_dma_ops(dev);
+
+	if (dma_release_from_coherent(dev, get_order(size), vaddr))
+		return;
+
+	debug_dma_free_coherent(dev, size, vaddr, dev_addr);
+	ops->free(dev, size, vaddr, dev_addr, NULL);
+}
+
+/*
+ * There is no dma_cache_sync() implementation, so just return NULL here.
+ */
+static inline void *dma_alloc_noncoherent(struct device *dev, size_t size,
+					  dma_addr_t *handle, gfp_t flags)
+{
+	return NULL;
+}
+
+static inline void dma_free_noncoherent(struct device *dev, size_t size,
+					void *cpu_addr, dma_addr_t handle)
+{
+}
+
+#endif	/* __KERNEL__ */
+#endif	/* __ASM_DMA_MAPPING_H */
diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h
new file mode 100644
index 0000000..cf28464
--- /dev/null
+++ b/arch/arm64/include/asm/elf.h
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_ELF_H
+#define __ASM_ELF_H
+
+#include <asm/hwcap.h>
+
+/*
+ * ELF register definitions..
+ */
+#include <asm/ptrace.h>
+#include <asm/user.h>
+
+typedef unsigned long elf_greg_t;
+typedef unsigned long elf_freg_t[3];
+
+#define ELF_NGREG (sizeof (struct pt_regs) / sizeof(elf_greg_t))
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+
+typedef struct user_fp elf_fpregset_t;
+
+#define EM_AARCH64		183
+
+/*
+ * AArch64 static relocation types.
+ */
+
+/* Miscellaneous. */
+#define R_ARM_NONE			0
+#define R_AARCH64_NONE			256
+
+/* Data. */
+#define R_AARCH64_ABS64			257
+#define R_AARCH64_ABS32			258
+#define R_AARCH64_ABS16			259
+#define R_AARCH64_PREL64		260
+#define R_AARCH64_PREL32		261
+#define R_AARCH64_PREL16		262
+
+/* Instructions. */
+#define R_AARCH64_MOVW_UABS_G0		263
+#define R_AARCH64_MOVW_UABS_G0_NC	264
+#define R_AARCH64_MOVW_UABS_G1		265
+#define R_AARCH64_MOVW_UABS_G1_NC	266
+#define R_AARCH64_MOVW_UABS_G2		267
+#define R_AARCH64_MOVW_UABS_G2_NC	268
+#define R_AARCH64_MOVW_UABS_G3		269
+
+#define R_AARCH64_MOVW_SABS_G0		270
+#define R_AARCH64_MOVW_SABS_G1		271
+#define R_AARCH64_MOVW_SABS_G2		272
+
+#define R_AARCH64_LD_PREL_LO19		273
+#define R_AARCH64_ADR_PREL_LO21		274
+#define R_AARCH64_ADR_PREL_PG_HI21	275
+#define R_AARCH64_ADR_PREL_PG_HI21_NC	276
+#define R_AARCH64_ADD_ABS_LO12_NC	277
+#define R_AARCH64_LDST8_ABS_LO12_NC	278
+
+#define R_AARCH64_TSTBR14		279
+#define R_AARCH64_CONDBR19		280
+#define R_AARCH64_JUMP26		282
+#define R_AARCH64_CALL26		283
+#define R_AARCH64_LDST16_ABS_LO12_NC	284
+#define R_AARCH64_LDST32_ABS_LO12_NC	285
+#define R_AARCH64_LDST64_ABS_LO12_NC	286
+#define R_AARCH64_LDST128_ABS_LO12_NC	299
+
+#define R_AARCH64_MOVW_PREL_G0		287
+#define R_AARCH64_MOVW_PREL_G0_NC	288
+#define R_AARCH64_MOVW_PREL_G1		289
+#define R_AARCH64_MOVW_PREL_G1_NC	290
+#define R_AARCH64_MOVW_PREL_G2		291
+#define R_AARCH64_MOVW_PREL_G2_NC	292
+#define R_AARCH64_MOVW_PREL_G3		293
+
+
+/*
+ * These are used to set parameters in the core dumps.
+ */
+#define ELF_CLASS	ELFCLASS64
+#define ELF_DATA	ELFDATA2LSB
+#define ELF_ARCH	EM_AARCH64
+
+#define ELF_PLATFORM_SIZE	16
+#define ELF_PLATFORM		("aarch64")
+
+/*
+ * This is used to ensure we don't load something for the wrong architecture.
+ */
+#define elf_check_arch(x)		((x)->e_machine == EM_AARCH64)
+
+#define elf_read_implies_exec(ex,stk)	(stk != EXSTACK_DISABLE_X)
+
+#define CORE_DUMP_USE_REGSET
+#define ELF_EXEC_PAGESIZE	PAGE_SIZE
+
+/*
+ * This is the location that an ET_DYN program is loaded if exec'ed.  Typical
+ * use of this is to invoke "./ld.so someprog" to test out a new version of
+ * 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.
+ */
+extern unsigned long randomize_et_dyn(unsigned long base);
+#define ELF_ET_DYN_BASE	(randomize_et_dyn(2 * TASK_SIZE_64 / 3))
+
+/*
+ * When the program starts, a1 contains a pointer to a function to be
+ * registered with atexit, as per the SVR4 ABI.  A value of 0 means we have no
+ * such handler.
+ */
+#define ELF_PLAT_INIT(_r, load_addr)	(_r)->regs[0] = 0
+
+#define SET_PERSONALITY(ex)		clear_thread_flag(TIF_32BIT);
+
+#define ARCH_DLINFO							\
+do {									\
+	NEW_AUX_ENT(AT_SYSINFO_EHDR,					\
+		    (elf_addr_t)current->mm->context.vdso);		\
+} while (0)
+
+#define ARCH_HAS_SETUP_ADDITIONAL_PAGES
+struct linux_binprm;
+extern int arch_setup_additional_pages(struct linux_binprm *bprm,
+				       int uses_interp);
+
+/* 1GB of VA */
+#ifdef CONFIG_COMPAT
+#define STACK_RND_MASK			(test_thread_flag(TIF_32BIT) ? \
+						0x7ff >> (PAGE_SHIFT - 12) : \
+						0x3ffff >> (PAGE_SHIFT - 12))
+#else
+#define STACK_RND_MASK			(0x3ffff >> (PAGE_SHIFT - 12))
+#endif
+
+struct mm_struct;
+extern unsigned long arch_randomize_brk(struct mm_struct *mm);
+#define arch_randomize_brk arch_randomize_brk
+
+#ifdef CONFIG_COMPAT
+#define EM_ARM				40
+#define COMPAT_ELF_PLATFORM		("v8l")
+
+#define COMPAT_ELF_ET_DYN_BASE		(randomize_et_dyn(2 * TASK_SIZE_32 / 3))
+
+/* AArch32 registers. */
+#define COMPAT_ELF_NGREG		18
+typedef unsigned int			compat_elf_greg_t;
+typedef compat_elf_greg_t		compat_elf_gregset_t[COMPAT_ELF_NGREG];
+
+/* AArch32 EABI. */
+#define EF_ARM_EABI_MASK		0xff000000
+#define compat_elf_check_arch(x)	(((x)->e_machine == EM_ARM) && \
+					 ((x)->e_flags & EF_ARM_EABI_MASK))
+
+#define compat_start_thread		compat_start_thread
+#define COMPAT_SET_PERSONALITY(ex)	set_thread_flag(TIF_32BIT);
+#define COMPAT_ARCH_DLINFO
+extern int aarch32_setup_vectors_page(struct linux_binprm *bprm,
+				      int uses_interp);
+#define compat_arch_setup_additional_pages \
+					aarch32_setup_vectors_page
+
+#endif /* CONFIG_COMPAT */
+
+#endif
diff --git a/arch/arm64/include/asm/exception.h b/arch/arm64/include/asm/exception.h
new file mode 100644
index 0000000..ac63519
--- /dev/null
+++ b/arch/arm64/include/asm/exception.h
@@ -0,0 +1,23 @@
+/*
+ * Based on arch/arm/include/asm/exception.h
+ *
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_EXCEPTION_H
+#define __ASM_EXCEPTION_H
+
+#define __exception	__attribute__((section(".exception.text")))
+
+#endif	/* __ASM_EXCEPTION_H */
diff --git a/arch/arm64/include/asm/exec.h b/arch/arm64/include/asm/exec.h
new file mode 100644
index 0000000..db0563c
--- /dev/null
+++ b/arch/arm64/include/asm/exec.h
@@ -0,0 +1,23 @@
+/*
+ * Based on arch/arm/include/asm/exec.h
+ *
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_EXEC_H
+#define __ASM_EXEC_H
+
+extern unsigned long arch_align_stack(unsigned long sp);
+
+#endif	/* __ASM_EXEC_H */
diff --git a/arch/arm64/include/asm/fb.h b/arch/arm64/include/asm/fb.h
new file mode 100644
index 0000000..adb88a6
--- /dev/null
+++ b/arch/arm64/include/asm/fb.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_FB_H_
+#define __ASM_FB_H_
+
+#include <linux/fb.h>
+#include <linux/fs.h>
+#include <asm/page.h>
+
+static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
+				unsigned long off)
+{
+	vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+}
+
+static inline int fb_is_primary_device(struct fb_info *info)
+{
+	return 0;
+}
+
+#endif /* __ASM_FB_H_ */
diff --git a/arch/arm64/include/asm/fcntl.h b/arch/arm64/include/asm/fcntl.h
new file mode 100644
index 0000000..cd2e630
--- /dev/null
+++ b/arch/arm64/include/asm/fcntl.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_FCNTL_H
+#define __ASM_FCNTL_H
+
+/*
+ * Using our own definitions for AArch32 (compat) support.
+ */
+#define O_DIRECTORY	 040000	/* must be a directory */
+#define O_NOFOLLOW	0100000	/* don't follow links */
+#define O_DIRECT	0200000	/* direct disk access hint - currently ignored */
+#define O_LARGEFILE	0400000
+
+#include <asm-generic/fcntl.h>
+
+#endif
diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsimd.h
new file mode 100644
index 0000000..b42fab9
--- /dev/null
+++ b/arch/arm64/include/asm/fpsimd.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_FP_H
+#define __ASM_FP_H
+
+#include <asm/ptrace.h>
+
+#ifndef __ASSEMBLY__
+
+/*
+ * FP/SIMD storage area has:
+ *  - FPSR and FPCR
+ *  - 32 128-bit data registers
+ *
+ * Note that user_fp forms a prefix of this structure, which is relied
+ * upon in the ptrace FP/SIMD accessors. struct user_fpsimd_state must
+ * form a prefix of struct fpsimd_state.
+ */
+struct fpsimd_state {
+	union {
+		struct user_fpsimd_state user_fpsimd;
+		struct {
+			__uint128_t vregs[32];
+			u32 fpsr;
+			u32 fpcr;
+		};
+	};
+};
+
+#if defined(__KERNEL__) && defined(CONFIG_COMPAT)
+/* Masks for extracting the FPSR and FPCR from the FPSCR */
+#define VFP_FPSCR_STAT_MASK	0xf800009f
+#define VFP_FPSCR_CTRL_MASK	0x07f79f00
+/*
+ * The VFP state has 32x64-bit registers and a single 32-bit
+ * control/status register.
+ */
+#define VFP_STATE_SIZE		((32 * 8) + 4)
+#endif
+
+struct task_struct;
+
+extern void fpsimd_save_state(struct fpsimd_state *state);
+extern void fpsimd_load_state(struct fpsimd_state *state);
+
+extern void fpsimd_thread_switch(struct task_struct *next);
+extern void fpsimd_flush_thread(void);
+
+#endif
+
+#endif
diff --git a/arch/arm64/include/asm/futex.h b/arch/arm64/include/asm/futex.h
new file mode 100644
index 0000000..3468ae8
--- /dev/null
+++ b/arch/arm64/include/asm/futex.h
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_FUTEX_H
+#define __ASM_FUTEX_H
+
+#ifdef __KERNEL__
+
+#include <linux/futex.h>
+#include <linux/uaccess.h>
+#include <asm/errno.h>
+
+#define __futex_atomic_op(insn, ret, oldval, uaddr, tmp, oparg)		\
+	asm volatile(							\
+"1:	ldaxr	%w1, %2\n"						\
+	insn "\n"							\
+"2:	stlxr	%w3, %w0, %2\n"						\
+"	cbnz	%w3, 1b\n"						\
+"3:\n"									\
+"	.pushsection .fixup,\"ax\"\n"					\
+"4:	mov	%w0, %w5\n"						\
+"	b	3b\n"							\
+"	.popsection\n"							\
+"	.pushsection __ex_table,\"a\"\n"				\
+"	.align	3\n"							\
+"	.quad	1b, 4b, 2b, 4b\n"					\
+"	.popsection\n"							\
+	: "=&r" (ret), "=&r" (oldval), "+Q" (*uaddr), "=&r" (tmp)	\
+	: "r" (oparg), "Ir" (-EFAULT)					\
+	: "cc")
+
+static inline int
+futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
+{
+	int op = (encoded_op >> 28) & 7;
+	int cmp = (encoded_op >> 24) & 15;
+	int oparg = (encoded_op << 8) >> 20;
+	int cmparg = (encoded_op << 20) >> 20;
+	int oldval = 0, ret, tmp;
+
+	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+		oparg = 1 << oparg;
+
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
+		return -EFAULT;
+
+	pagefault_disable();	/* implies preempt_disable() */
+
+	switch (op) {
+	case FUTEX_OP_SET:
+		__futex_atomic_op("mov	%w0, %w4",
+				  ret, oldval, uaddr, tmp, oparg);
+		break;
+	case FUTEX_OP_ADD:
+		__futex_atomic_op("add	%w0, %w1, %w4",
+				  ret, oldval, uaddr, tmp, oparg);
+		break;
+	case FUTEX_OP_OR:
+		__futex_atomic_op("orr	%w0, %w1, %w4",
+				  ret, oldval, uaddr, tmp, oparg);
+		break;
+	case FUTEX_OP_ANDN:
+		__futex_atomic_op("and	%w0, %w1, %w4",
+				  ret, oldval, uaddr, tmp, ~oparg);
+		break;
+	case FUTEX_OP_XOR:
+		__futex_atomic_op("eor	%w0, %w1, %w4",
+				  ret, oldval, uaddr, tmp, oparg);
+		break;
+	default:
+		ret = -ENOSYS;
+	}
+
+	pagefault_enable();	/* subsumes preempt_enable() */
+
+	if (!ret) {
+		switch (cmp) {
+		case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
+		case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
+		case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
+		case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
+		case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
+		case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
+		default: ret = -ENOSYS;
+		}
+	}
+	return ret;
+}
+
+static inline int
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+			      u32 oldval, u32 newval)
+{
+	int ret = 0;
+	u32 val, tmp;
+
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
+		return -EFAULT;
+
+	asm volatile("// futex_atomic_cmpxchg_inatomic\n"
+"1:	ldaxr	%w1, %2\n"
+"	sub	%w3, %w1, %w4\n"
+"	cbnz	%w3, 3f\n"
+"2:	stlxr	%w3, %w5, %2\n"
+"	cbnz	%w3, 1b\n"
+"3:\n"
+"	.pushsection .fixup,\"ax\"\n"
+"4:	mov	%w0, %w6\n"
+"	b	3b\n"
+"	.popsection\n"
+"	.pushsection __ex_table,\"a\"\n"
+"	.align	3\n"
+"	.quad	1b, 4b, 2b, 4b\n"
+"	.popsection\n"
+	: "+r" (ret), "=&r" (val), "+Q" (*uaddr), "=&r" (tmp)
+	: "r" (oldval), "r" (newval), "Ir" (-EFAULT)
+	: "cc", "memory");
+
+	*uval = val;
+	return ret;
+}
+
+#endif /* __KERNEL__ */
+#endif /* __ASM_FUTEX_H */
diff --git a/arch/arm64/include/asm/hardirq.h b/arch/arm64/include/asm/hardirq.h
new file mode 100644
index 0000000..5075463
--- /dev/null
+++ b/arch/arm64/include/asm/hardirq.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_HARDIRQ_H
+#define __ASM_HARDIRQ_H
+
+#include <linux/cache.h>
+#include <linux/threads.h>
+#include <asm/irq.h>
+
+#define NR_IPI	4
+
+typedef struct {
+	unsigned int __softirq_pending;
+#ifdef CONFIG_SMP
+	unsigned int ipi_irqs[NR_IPI];
+#endif
+} ____cacheline_aligned irq_cpustat_t;
+
+#include <linux/irq_cpustat.h>	/* Standard mappings for irq_cpustat_t above */
+
+#define __inc_irq_stat(cpu, member)	__IRQ_STAT(cpu, member)++
+#define __get_irq_stat(cpu, member)	__IRQ_STAT(cpu, member)
+
+#ifdef CONFIG_SMP
+u64 smp_irq_stat_cpu(unsigned int cpu);
+#define arch_irq_stat_cpu	smp_irq_stat_cpu
+#endif
+
+#define __ARCH_IRQ_EXIT_IRQS_DISABLED	1
+
+static inline void ack_bad_irq(unsigned int irq)
+{
+	extern unsigned long irq_err_count;
+	irq_err_count++;
+}
+
+extern void handle_IRQ(unsigned int, struct pt_regs *);
+
+#endif /* __ASM_HARDIRQ_H */
diff --git a/arch/arm64/include/asm/hw_breakpoint.h b/arch/arm64/include/asm/hw_breakpoint.h
new file mode 100644
index 0000000..d064047
--- /dev/null
+++ b/arch/arm64/include/asm/hw_breakpoint.h
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_HW_BREAKPOINT_H
+#define __ASM_HW_BREAKPOINT_H
+
+#ifdef __KERNEL__
+
+struct arch_hw_breakpoint_ctrl {
+	u32 __reserved	: 19,
+	len		: 8,
+	type		: 2,
+	privilege	: 2,
+	enabled		: 1;
+};
+
+struct arch_hw_breakpoint {
+	u64 address;
+	u64 trigger;
+	struct arch_hw_breakpoint_ctrl ctrl;
+};
+
+static inline u32 encode_ctrl_reg(struct arch_hw_breakpoint_ctrl ctrl)
+{
+	return (ctrl.len << 5) | (ctrl.type << 3) | (ctrl.privilege << 1) |
+		ctrl.enabled;
+}
+
+static inline void decode_ctrl_reg(u32 reg,
+				   struct arch_hw_breakpoint_ctrl *ctrl)
+{
+	ctrl->enabled	= reg & 0x1;
+	reg >>= 1;
+	ctrl->privilege	= reg & 0x3;
+	reg >>= 2;
+	ctrl->type	= reg & 0x3;
+	reg >>= 2;
+	ctrl->len	= reg & 0xff;
+}
+
+/* Breakpoint */
+#define ARM_BREAKPOINT_EXECUTE	0
+
+/* Watchpoints */
+#define ARM_BREAKPOINT_LOAD	1
+#define ARM_BREAKPOINT_STORE	2
+#define AARCH64_ESR_ACCESS_MASK	(1 << 6)
+
+/* Privilege Levels */
+#define AARCH64_BREAKPOINT_EL1	1
+#define AARCH64_BREAKPOINT_EL0	2
+
+/* Lengths */
+#define ARM_BREAKPOINT_LEN_1	0x1
+#define ARM_BREAKPOINT_LEN_2	0x3
+#define ARM_BREAKPOINT_LEN_4	0xf
+#define ARM_BREAKPOINT_LEN_8	0xff
+
+/* Kernel stepping */
+#define ARM_KERNEL_STEP_NONE	0
+#define ARM_KERNEL_STEP_ACTIVE	1
+#define ARM_KERNEL_STEP_SUSPEND	2
+
+/*
+ * Limits.
+ * Changing these will require modifications to the register accessors.
+ */
+#define ARM_MAX_BRP		16
+#define ARM_MAX_WRP		16
+#define ARM_MAX_HBP_SLOTS	(ARM_MAX_BRP + ARM_MAX_WRP)
+
+/* Virtual debug register bases. */
+#define AARCH64_DBG_REG_BVR	0
+#define AARCH64_DBG_REG_BCR	(AARCH64_DBG_REG_BVR + ARM_MAX_BRP)
+#define AARCH64_DBG_REG_WVR	(AARCH64_DBG_REG_BCR + ARM_MAX_BRP)
+#define AARCH64_DBG_REG_WCR	(AARCH64_DBG_REG_WVR + ARM_MAX_WRP)
+
+/* Debug register names. */
+#define AARCH64_DBG_REG_NAME_BVR	"bvr"
+#define AARCH64_DBG_REG_NAME_BCR	"bcr"
+#define AARCH64_DBG_REG_NAME_WVR	"wvr"
+#define AARCH64_DBG_REG_NAME_WCR	"wcr"
+
+/* Accessor macros for the debug registers. */
+#define AARCH64_DBG_READ(N, REG, VAL) do {\
+	asm volatile("mrs %0, dbg" REG #N "_el1" : "=r" (VAL));\
+} while (0)
+
+#define AARCH64_DBG_WRITE(N, REG, VAL) do {\
+	asm volatile("msr dbg" REG #N "_el1, %0" :: "r" (VAL));\
+} while (0)
+
+struct task_struct;
+struct notifier_block;
+struct perf_event;
+struct pmu;
+
+extern int arch_bp_generic_fields(struct arch_hw_breakpoint_ctrl ctrl,
+				  int *gen_len, int *gen_type);
+extern int arch_check_bp_in_kernelspace(struct perf_event *bp);
+extern int arch_validate_hwbkpt_settings(struct perf_event *bp);
+extern int hw_breakpoint_exceptions_notify(struct notifier_block *unused,
+					   unsigned long val, void *data);
+
+extern int arch_install_hw_breakpoint(struct perf_event *bp);
+extern void arch_uninstall_hw_breakpoint(struct perf_event *bp);
+extern void hw_breakpoint_pmu_read(struct perf_event *bp);
+extern int hw_breakpoint_slots(int type);
+
+#ifdef CONFIG_HAVE_HW_BREAKPOINT
+extern void hw_breakpoint_thread_switch(struct task_struct *next);
+extern void ptrace_hw_copy_thread(struct task_struct *task);
+#else
+static inline void hw_breakpoint_thread_switch(struct task_struct *next)
+{
+}
+static inline void ptrace_hw_copy_thread(struct task_struct *task)
+{
+}
+#endif
+
+extern struct pmu perf_ops_bp;
+
+#endif	/* __KERNEL__ */
+#endif	/* __ASM_BREAKPOINT_H */
diff --git a/arch/arm64/include/asm/hwcap.h b/arch/arm64/include/asm/hwcap.h
new file mode 100644
index 0000000..f8190ba
--- /dev/null
+++ b/arch/arm64/include/asm/hwcap.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_HWCAP_H
+#define __ASM_HWCAP_H
+
+/*
+ * HWCAP flags - for elf_hwcap (in kernel) and AT_HWCAP
+ */
+#define HWCAP_FP		(1 << 0)
+#define HWCAP_ASIMD		(1 << 1)
+
+#define COMPAT_HWCAP_HALF	(1 << 1)
+#define COMPAT_HWCAP_THUMB	(1 << 2)
+#define COMPAT_HWCAP_FAST_MULT	(1 << 4)
+#define COMPAT_HWCAP_VFP	(1 << 6)
+#define COMPAT_HWCAP_EDSP	(1 << 7)
+#define COMPAT_HWCAP_NEON	(1 << 12)
+#define COMPAT_HWCAP_VFPv3	(1 << 13)
+#define COMPAT_HWCAP_TLS	(1 << 15)
+#define COMPAT_HWCAP_VFPv4	(1 << 16)
+#define COMPAT_HWCAP_IDIVA	(1 << 17)
+#define COMPAT_HWCAP_IDIVT	(1 << 18)
+#define COMPAT_HWCAP_IDIV	(COMPAT_HWCAP_IDIVA|COMPAT_HWCAP_IDIVT)
+
+#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
+/*
+ * This yields a mask that user programs can use to figure out what
+ * instruction set this cpu supports.
+ */
+#define ELF_HWCAP		(elf_hwcap)
+#define COMPAT_ELF_HWCAP	(COMPAT_HWCAP_HALF|COMPAT_HWCAP_THUMB|\
+				 COMPAT_HWCAP_FAST_MULT|COMPAT_HWCAP_EDSP|\
+				 COMPAT_HWCAP_TLS|COMPAT_HWCAP_VFP|\
+				 COMPAT_HWCAP_VFPv3|COMPAT_HWCAP_VFPv4|\
+				 COMPAT_HWCAP_NEON|COMPAT_HWCAP_IDIV)
+
+extern unsigned int elf_hwcap;
+#endif
+
+#endif
diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
new file mode 100644
index 0000000..74a2a7d
--- /dev/null
+++ b/arch/arm64/include/asm/io.h
@@ -0,0 +1,258 @@
+/*
+ * Based on arch/arm/include/asm/io.h
+ *
+ * Copyright (C) 1996-2000 Russell King
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_IO_H
+#define __ASM_IO_H
+
+#ifdef __KERNEL__
+
+#include <linux/types.h>
+
+#include <asm/byteorder.h>
+#include <asm/barrier.h>
+#include <asm/pgtable.h>
+
+/*
+ * Generic IO read/write.  These perform native-endian accesses.
+ */
+static inline void __raw_writeb(u8 val, volatile void __iomem *addr)
+{
+	asm volatile("strb %w0, [%1]" : : "r" (val), "r" (addr));
+}
+
+static inline void __raw_writew(u16 val, volatile void __iomem *addr)
+{
+	asm volatile("strh %w0, [%1]" : : "r" (val), "r" (addr));
+}
+
+static inline void __raw_writel(u32 val, volatile void __iomem *addr)
+{
+	asm volatile("str %w0, [%1]" : : "r" (val), "r" (addr));
+}
+
+static inline void __raw_writeq(u64 val, volatile void __iomem *addr)
+{
+	asm volatile("str %0, [%1]" : : "r" (val), "r" (addr));
+}
+
+static inline u8 __raw_readb(const volatile void __iomem *addr)
+{
+	u8 val;
+	asm volatile("ldrb %w0, [%1]" : "=r" (val) : "r" (addr));
+	return val;
+}
+
+static inline u16 __raw_readw(const volatile void __iomem *addr)
+{
+	u16 val;
+	asm volatile("ldrh %w0, [%1]" : "=r" (val) : "r" (addr));
+	return val;
+}
+
+static inline u32 __raw_readl(const volatile void __iomem *addr)
+{
+	u32 val;
+	asm volatile("ldr %w0, [%1]" : "=r" (val) : "r" (addr));
+	return val;
+}
+
+static inline u64 __raw_readq(const volatile void __iomem *addr)
+{
+	u64 val;
+	asm volatile("ldr %0, [%1]" : "=r" (val) : "r" (addr));
+	return val;
+}
+
+/* IO barriers */
+#define __iormb()		rmb()
+#define __iowmb()		wmb()
+
+#define mmiowb()		do { } while (0)
+
+/*
+ * Relaxed I/O memory access primitives. These follow the Device memory
+ * ordering rules but do not guarantee any ordering relative to Normal memory
+ * accesses.
+ */
+#define readb_relaxed(c)	({ u8  __v = __raw_readb(c); __v; })
+#define readw_relaxed(c)	({ u16 __v = le16_to_cpu((__force __le16)__raw_readw(c)); __v; })
+#define readl_relaxed(c)	({ u32 __v = le32_to_cpu((__force __le32)__raw_readl(c)); __v; })
+
+#define writeb_relaxed(v,c)	((void)__raw_writeb((v),(c)))
+#define writew_relaxed(v,c)	((void)__raw_writew((__force u16)cpu_to_le16(v),(c)))
+#define writel_relaxed(v,c)	((void)__raw_writel((__force u32)cpu_to_le32(v),(c)))
+
+/*
+ * I/O memory access primitives. Reads are ordered relative to any
+ * following Normal memory access. Writes are ordered relative to any prior
+ * Normal memory access.
+ */
+#define readb(c)		({ u8  __v = readb_relaxed(c); __iormb(); __v; })
+#define readw(c)		({ u16 __v = readw_relaxed(c); __iormb(); __v; })
+#define readl(c)		({ u32 __v = readl_relaxed(c); __iormb(); __v; })
+
+#define writeb(v,c)		({ __iowmb(); writeb_relaxed((v),(c)); })
+#define writew(v,c)		({ __iowmb(); writew_relaxed((v),(c)); })
+#define writel(v,c)		({ __iowmb(); writel_relaxed((v),(c)); })
+
+/*
+ *  I/O port access primitives.
+ */
+#define IO_SPACE_LIMIT		0xffff
+#define PCI_IOBASE		((void __iomem *)0xffffffbbfffe0000UL)
+
+static inline u8 inb(unsigned long addr)
+{
+	return readb(addr + PCI_IOBASE);
+}
+
+static inline u16 inw(unsigned long addr)
+{
+	return readw(addr + PCI_IOBASE);
+}
+
+static inline u32 inl(unsigned long addr)
+{
+	return readl(addr + PCI_IOBASE);
+}
+
+static inline void outb(u8 b, unsigned long addr)
+{
+	writeb(b, addr + PCI_IOBASE);
+}
+
+static inline void outw(u16 b, unsigned long addr)
+{
+	writew(b, addr + PCI_IOBASE);
+}
+
+static inline void outl(u32 b, unsigned long addr)
+{
+	writel(b, addr + PCI_IOBASE);
+}
+
+#define inb_p(addr)	inb(addr)
+#define inw_p(addr)	inw(addr)
+#define inl_p(addr)	inl(addr)
+
+#define outb_p(x, addr)	outb((x), (addr))
+#define outw_p(x, addr)	outw((x), (addr))
+#define outl_p(x, addr)	outl((x), (addr))
+
+static inline void insb(unsigned long addr, void *buffer, int count)
+{
+	u8 *buf = buffer;
+	while (count--)
+		*buf++ = __raw_readb(addr + PCI_IOBASE);
+}
+
+static inline void insw(unsigned long addr, void *buffer, int count)
+{
+	u16 *buf = buffer;
+	while (count--)
+		*buf++ = __raw_readw(addr + PCI_IOBASE);
+}
+
+static inline void insl(unsigned long addr, void *buffer, int count)
+{
+	u32 *buf = buffer;
+	while (count--)
+		*buf++ = __raw_readl(addr + PCI_IOBASE);
+}
+
+static inline void outsb(unsigned long addr, const void *buffer, int count)
+{
+	const u8 *buf = buffer;
+	while (count--)
+		__raw_writeb(*buf++, addr + PCI_IOBASE);
+}
+
+static inline void outsw(unsigned long addr, const void *buffer, int count)
+{
+	const u16 *buf = buffer;
+	while (count--)
+		__raw_writew(*buf++, addr + PCI_IOBASE);
+}
+
+static inline void outsl(unsigned long addr, const void *buffer, int count)
+{
+	const u32 *buf = buffer;
+	while (count--)
+		__raw_writel(*buf++, addr + PCI_IOBASE);
+}
+
+#define insb_p(port,to,len)	insb(port,to,len)
+#define insw_p(port,to,len)	insw(port,to,len)
+#define insl_p(port,to,len)	insl(port,to,len)
+
+#define outsb_p(port,from,len)	outsb(port,from,len)
+#define outsw_p(port,from,len)	outsw(port,from,len)
+#define outsl_p(port,from,len)	outsl(port,from,len)
+
+/*
+ * String version of I/O memory access operations.
+ */
+extern void __memcpy_fromio(void *, const volatile void __iomem *, size_t);
+extern void __memcpy_toio(volatile void __iomem *, const void *, size_t);
+extern void __memset_io(volatile void __iomem *, int, size_t);
+
+#define memset_io(c,v,l)	__memset_io((c),(v),(l))
+#define memcpy_fromio(a,c,l)	__memcpy_fromio((a),(c),(l))
+#define memcpy_toio(c,a,l)	__memcpy_toio((c),(a),(l))
+
+/*
+ * I/O memory mapping functions.
+ */
+extern void __iomem *__ioremap(phys_addr_t phys_addr, size_t size, pgprot_t prot);
+extern void __iounmap(volatile void __iomem *addr);
+
+#define PROT_DEFAULT		(PTE_TYPE_PAGE | PTE_AF | PTE_DIRTY)
+#define PROT_DEVICE_nGnRE	(PROT_DEFAULT | PTE_XN | PTE_ATTRINDX(MT_DEVICE_nGnRE))
+#define PROT_NORMAL_NC		(PROT_DEFAULT | PTE_ATTRINDX(MT_NORMAL_NC))
+
+#define ioremap(addr, size)		__ioremap((addr), (size), PROT_DEVICE_nGnRE)
+#define ioremap_nocache(addr, size)	__ioremap((addr), (size), PROT_DEVICE_nGnRE)
+#define ioremap_wc(addr, size)		__ioremap((addr), (size), PROT_NORMAL_NC)
+#define iounmap				__iounmap
+
+#define ARCH_HAS_IOREMAP_WC
+#include <asm-generic/iomap.h>
+
+/*
+ * More restrictive address range checking than the default implementation
+ * (PHYS_OFFSET and PHYS_MASK taken into account).
+ */
+#define ARCH_HAS_VALID_PHYS_ADDR_RANGE
+extern int valid_phys_addr_range(unsigned long addr, size_t size);
+extern int valid_mmap_phys_addr_range(unsigned long pfn, size_t size);
+
+extern int devmem_is_allowed(unsigned long pfn);
+
+/*
+ * Convert a physical pointer to a virtual kernel pointer for /dev/mem
+ * access
+ */
+#define xlate_dev_mem_ptr(p)	__va(p)
+
+/*
+ * Convert a virtual cached pointer to an uncached pointer
+ */
+#define xlate_dev_kmem_ptr(p)	p
+
+#endif	/* __KERNEL__ */
+#endif	/* __ASM_IO_H */
diff --git a/arch/arm64/include/asm/irq.h b/arch/arm64/include/asm/irq.h
new file mode 100644
index 0000000..a4e1cad
--- /dev/null
+++ b/arch/arm64/include/asm/irq.h
@@ -0,0 +1,8 @@
+#ifndef __ASM_IRQ_H
+#define __ASM_IRQ_H
+
+#include <asm-generic/irq.h>
+
+extern void (*handle_arch_irq)(struct pt_regs *);
+
+#endif
diff --git a/arch/arm64/include/asm/irqflags.h b/arch/arm64/include/asm/irqflags.h
new file mode 100644
index 0000000..aa11943
--- /dev/null
+++ b/arch/arm64/include/asm/irqflags.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_IRQFLAGS_H
+#define __ASM_IRQFLAGS_H
+
+#ifdef __KERNEL__
+
+#include <asm/ptrace.h>
+
+/*
+ * CPU interrupt mask handling.
+ */
+static inline unsigned long arch_local_irq_save(void)
+{
+	unsigned long flags;
+	asm volatile(
+		"mrs	%0, daif		// arch_local_irq_save\n"
+		"msr	daifset, #2"
+		: "=r" (flags)
+		:
+		: "memory");
+	return flags;
+}
+
+static inline void arch_local_irq_enable(void)
+{
+	asm volatile(
+		"msr	daifclr, #2		// arch_local_irq_enable"
+		:
+		:
+		: "memory");
+}
+
+static inline void arch_local_irq_disable(void)
+{
+	asm volatile(
+		"msr	daifset, #2		// arch_local_irq_disable"
+		:
+		:
+		: "memory");
+}
+
+#define local_fiq_enable()	asm("msr	daifclr, #1" : : : "memory")
+#define local_fiq_disable()	asm("msr	daifset, #1" : : : "memory")
+
+/*
+ * Save the current interrupt enable state.
+ */
+static inline unsigned long arch_local_save_flags(void)
+{
+	unsigned long flags;
+	asm volatile(
+		"mrs	%0, daif		// arch_local_save_flags"
+		: "=r" (flags)
+		:
+		: "memory");
+	return flags;
+}
+
+/*
+ * restore saved IRQ state
+ */
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+	asm volatile(
+		"msr	daif, %0		// arch_local_irq_restore"
+	:
+	: "r" (flags)
+	: "memory");
+}
+
+static inline int arch_irqs_disabled_flags(unsigned long flags)
+{
+	return flags & PSR_I_BIT;
+}
+
+#endif
+#endif
diff --git a/arch/arm64/include/asm/memblock.h b/arch/arm64/include/asm/memblock.h
new file mode 100644
index 0000000..6afeed2
--- /dev/null
+++ b/arch/arm64/include/asm/memblock.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_MEMBLOCK_H
+#define __ASM_MEMBLOCK_H
+
+extern void arm64_memblock_init(void);
+
+#endif
diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h
new file mode 100644
index 0000000..1cac16a
--- /dev/null
+++ b/arch/arm64/include/asm/memory.h
@@ -0,0 +1,144 @@
+/*
+ * Based on arch/arm/include/asm/memory.h
+ *
+ * Copyright (C) 2000-2002 Russell King
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Note: this file should not be included by non-asm/.h files
+ */
+#ifndef __ASM_MEMORY_H
+#define __ASM_MEMORY_H
+
+#include <linux/compiler.h>
+#include <linux/const.h>
+#include <linux/types.h>
+#include <asm/sizes.h>
+
+/*
+ * Allow for constants defined here to be used from assembly code
+ * by prepending the UL suffix only with actual C code compilation.
+ */
+#define UL(x) _AC(x, UL)
+
+/*
+ * PAGE_OFFSET - the virtual address of the start of the kernel image.
+ * VA_BITS - the maximum number of bits for virtual addresses.
+ * TASK_SIZE - the maximum size of a user space task.
+ * TASK_UNMAPPED_BASE - the lower boundary of the mmap VM area.
+ * The module space lives between the addresses given by TASK_SIZE
+ * and PAGE_OFFSET - it must be within 128MB of the kernel text.
+ */
+#define PAGE_OFFSET		UL(0xffffffc000000000)
+#define MODULES_END		(PAGE_OFFSET)
+#define MODULES_VADDR		(MODULES_END - SZ_64M)
+#define VA_BITS			(39)
+#define TASK_SIZE_64		(UL(1) << VA_BITS)
+
+#ifdef CONFIG_COMPAT
+#define TASK_SIZE_32		UL(0x100000000)
+#define TASK_SIZE		(test_thread_flag(TIF_32BIT) ? \
+				TASK_SIZE_32 : TASK_SIZE_64)
+#else
+#define TASK_SIZE		TASK_SIZE_64
+#endif /* CONFIG_COMPAT */
+
+#define TASK_UNMAPPED_BASE	(PAGE_ALIGN(TASK_SIZE / 4))
+
+#if TASK_SIZE_64 > MODULES_VADDR
+#error Top of 64-bit user space clashes with start of module space
+#endif
+
+/*
+ * Physical vs virtual RAM address space conversion.  These are
+ * private definitions which should NOT be used outside memory.h
+ * files.  Use virt_to_phys/phys_to_virt/__pa/__va instead.
+ */
+#define __virt_to_phys(x)	(((phys_addr_t)(x) - PAGE_OFFSET + PHYS_OFFSET))
+#define __phys_to_virt(x)	((unsigned long)((x) - PHYS_OFFSET + PAGE_OFFSET))
+
+/*
+ * Convert a physical address to a Page Frame Number and back
+ */
+#define	__phys_to_pfn(paddr)	((unsigned long)((paddr) >> PAGE_SHIFT))
+#define	__pfn_to_phys(pfn)	((phys_addr_t)(pfn) << PAGE_SHIFT)
+
+/*
+ * Convert a page to/from a physical address
+ */
+#define page_to_phys(page)	(__pfn_to_phys(page_to_pfn(page)))
+#define phys_to_page(phys)	(pfn_to_page(__phys_to_pfn(phys)))
+
+/*
+ * Memory types available.
+ */
+#define MT_DEVICE_nGnRnE	0
+#define MT_DEVICE_nGnRE		1
+#define MT_DEVICE_GRE		2
+#define MT_NORMAL_NC		3
+#define MT_NORMAL		4
+
+#ifndef __ASSEMBLY__
+
+extern phys_addr_t		memstart_addr;
+/* PHYS_OFFSET - the physical address of the start of memory. */
+#define PHYS_OFFSET		({ memstart_addr; })
+
+/*
+ * PFNs are used to describe any physical page; this means
+ * PFN 0 == physical address 0.
+ *
+ * This is the PFN of the first RAM page in the kernel
+ * direct-mapped view.  We assume this is the first page
+ * of RAM in the mem_map as well.
+ */
+#define PHYS_PFN_OFFSET	(PHYS_OFFSET >> PAGE_SHIFT)
+
+/*
+ * Note: Drivers should NOT use these.  They are the wrong
+ * translation for translating DMA addresses.  Use the driver
+ * DMA support - see dma-mapping.h.
+ */
+static inline phys_addr_t virt_to_phys(const volatile void *x)
+{
+	return __virt_to_phys((unsigned long)(x));
+}
+
+static inline void *phys_to_virt(phys_addr_t x)
+{
+	return (void *)(__phys_to_virt(x));
+}
+
+/*
+ * Drivers should NOT use these either.
+ */
+#define __pa(x)			__virt_to_phys((unsigned long)(x))
+#define __va(x)			((void *)__phys_to_virt((phys_addr_t)(x)))
+#define pfn_to_kaddr(pfn)	__va((pfn) << PAGE_SHIFT)
+
+/*
+ *  virt_to_page(k)	convert a _valid_ virtual address to struct page *
+ *  virt_addr_valid(k)	indicates whether a virtual address is valid
+ */
+#define ARCH_PFN_OFFSET		PHYS_PFN_OFFSET
+
+#define virt_to_page(kaddr)	pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
+#define	virt_addr_valid(kaddr)	(((void *)(kaddr) >= (void *)PAGE_OFFSET) && \
+				 ((void *)(kaddr) < (void *)high_memory))
+
+#endif
+
+#include <asm-generic/memory_model.h>
+
+#endif
diff --git a/arch/arm64/include/asm/mmu.h b/arch/arm64/include/asm/mmu.h
new file mode 100644
index 0000000..d4f7fd5
--- /dev/null
+++ b/arch/arm64/include/asm/mmu.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_MMU_H
+#define __ASM_MMU_H
+
+typedef struct {
+	unsigned int id;
+	raw_spinlock_t id_lock;
+	void *vdso;
+} mm_context_t;
+
+#define ASID(mm)	((mm)->context.id & 0xffff)
+
+extern void paging_init(void);
+extern void setup_mm_for_reboot(void);
+
+#endif
diff --git a/arch/arm64/include/asm/mmu_context.h b/arch/arm64/include/asm/mmu_context.h
new file mode 100644
index 0000000..f68465d
--- /dev/null
+++ b/arch/arm64/include/asm/mmu_context.h
@@ -0,0 +1,152 @@
+/*
+ * Based on arch/arm/include/asm/mmu_context.h
+ *
+ * Copyright (C) 1996 Russell King.
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_MMU_CONTEXT_H
+#define __ASM_MMU_CONTEXT_H
+
+#include <linux/compiler.h>
+#include <linux/sched.h>
+
+#include <asm/cacheflush.h>
+#include <asm/proc-fns.h>
+#include <asm-generic/mm_hooks.h>
+#include <asm/cputype.h>
+#include <asm/pgtable.h>
+
+#define MAX_ASID_BITS	16
+
+extern unsigned int cpu_last_asid;
+
+void __init_new_context(struct task_struct *tsk, struct mm_struct *mm);
+void __new_context(struct mm_struct *mm);
+
+/*
+ * Set TTBR0 to empty_zero_page. No translations will be possible via TTBR0.
+ */
+static inline void cpu_set_reserved_ttbr0(void)
+{
+	unsigned long ttbr = page_to_phys(empty_zero_page);
+
+	asm(
+	"	msr	ttbr0_el1, %0			// set TTBR0\n"
+	"	isb"
+	:
+	: "r" (ttbr));
+}
+
+static inline void switch_new_context(struct mm_struct *mm)
+{
+	unsigned long flags;
+
+	__new_context(mm);
+
+	local_irq_save(flags);
+	cpu_switch_mm(mm->pgd, mm);
+	local_irq_restore(flags);
+}
+
+static inline void check_and_switch_context(struct mm_struct *mm,
+					    struct task_struct *tsk)
+{
+	/*
+	 * Required during context switch to avoid speculative page table
+	 * walking with the wrong TTBR.
+	 */
+	cpu_set_reserved_ttbr0();
+
+	if (!((mm->context.id ^ cpu_last_asid) >> MAX_ASID_BITS))
+		/*
+		 * The ASID is from the current generation, just switch to the
+		 * new pgd. This condition is only true for calls from
+		 * context_switch() and interrupts are already disabled.
+		 */
+		cpu_switch_mm(mm->pgd, mm);
+	else if (irqs_disabled())
+		/*
+		 * Defer the new ASID allocation until after the context
+		 * switch critical region since __new_context() cannot be
+		 * called with interrupts disabled.
+		 */
+		set_ti_thread_flag(task_thread_info(tsk), TIF_SWITCH_MM);
+	else
+		/*
+		 * That is a direct call to switch_mm() or activate_mm() with
+		 * interrupts enabled and a new context.
+		 */
+		switch_new_context(mm);
+}
+
+#define init_new_context(tsk,mm)	(__init_new_context(tsk,mm),0)
+#define destroy_context(mm)		do { } while(0)
+
+#define finish_arch_post_lock_switch \
+	finish_arch_post_lock_switch
+static inline void finish_arch_post_lock_switch(void)
+{
+	if (test_and_clear_thread_flag(TIF_SWITCH_MM)) {
+		struct mm_struct *mm = current->mm;
+		unsigned long flags;
+
+		__new_context(mm);
+
+		local_irq_save(flags);
+		cpu_switch_mm(mm->pgd, mm);
+		local_irq_restore(flags);
+	}
+}
+
+/*
+ * This is called when "tsk" is about to enter lazy TLB mode.
+ *
+ * mm:  describes the currently active mm context
+ * tsk: task which is entering lazy tlb
+ * cpu: cpu number which is entering lazy tlb
+ *
+ * tsk->mm will be NULL
+ */
+static inline void
+enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
+{
+}
+
+/*
+ * This is the actual mm switch as far as the scheduler
+ * is concerned.  No registers are touched.  We avoid
+ * calling the CPU specific function when the mm hasn't
+ * actually changed.
+ */
+static inline void
+switch_mm(struct mm_struct *prev, struct mm_struct *next,
+	  struct task_struct *tsk)
+{
+	unsigned int cpu = smp_processor_id();
+
+#ifdef CONFIG_SMP
+	/* check for possible thread migration */
+	if (!cpumask_empty(mm_cpumask(next)) &&
+	    !cpumask_test_cpu(cpu, mm_cpumask(next)))
+		__flush_icache_all();
+#endif
+	if (!cpumask_test_and_set_cpu(cpu, mm_cpumask(next)) || prev != next)
+		check_and_switch_context(next, tsk);
+}
+
+#define deactivate_mm(tsk,mm)	do { } while (0)
+#define activate_mm(prev,next)	switch_mm(prev, next, NULL)
+
+#endif
diff --git a/arch/arm64/include/asm/module.h b/arch/arm64/include/asm/module.h
new file mode 100644
index 0000000..e80e232
--- /dev/null
+++ b/arch/arm64/include/asm/module.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_MODULE_H
+#define __ASM_MODULE_H
+
+#include <asm-generic/module.h>
+
+#define MODULE_ARCH_VERMAGIC	"aarch64"
+
+#endif /* __ASM_MODULE_H */
diff --git a/arch/arm64/include/asm/page.h b/arch/arm64/include/asm/page.h
new file mode 100644
index 0000000..46bf666
--- /dev/null
+++ b/arch/arm64/include/asm/page.h
@@ -0,0 +1,67 @@
+/*
+ * Based on arch/arm/include/asm/page.h
+ *
+ * Copyright (C) 1995-2003 Russell King
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_PAGE_H
+#define __ASM_PAGE_H
+
+/* PAGE_SHIFT determines the page size */
+#ifdef CONFIG_ARM64_64K_PAGES
+#define PAGE_SHIFT		16
+#else
+#define PAGE_SHIFT		12
+#endif
+#define PAGE_SIZE		(_AC(1,UL) << PAGE_SHIFT)
+#define PAGE_MASK		(~(PAGE_SIZE-1))
+
+/* We do define AT_SYSINFO_EHDR but don't use the gate mechanism */
+#define __HAVE_ARCH_GATE_AREA		1
+
+#ifndef __ASSEMBLY__
+
+#ifdef CONFIG_ARM64_64K_PAGES
+#include <asm/pgtable-2level-types.h>
+#else
+#include <asm/pgtable-3level-types.h>
+#endif
+
+extern void __cpu_clear_user_page(void *p, unsigned long user);
+extern void __cpu_copy_user_page(void *to, const void *from,
+				 unsigned long user);
+extern void copy_page(void *to, const void *from);
+extern void clear_page(void *to);
+
+#define clear_user_page(addr,vaddr,pg)  __cpu_clear_user_page(addr, vaddr)
+#define copy_user_page(to,from,vaddr,pg) __cpu_copy_user_page(to, from, vaddr)
+
+typedef struct page *pgtable_t;
+
+#ifdef CONFIG_HAVE_ARCH_PFN_VALID
+extern int pfn_valid(unsigned long);
+#endif
+
+#include <asm/memory.h>
+
+#endif /* !__ASSEMBLY__ */
+
+#define VM_DATA_DEFAULT_FLAGS \
+	(((current->personality & READ_IMPLIES_EXEC) ? VM_EXEC : 0) | \
+	 VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
+
+#include <asm-generic/getorder.h>
+
+#endif
diff --git a/arch/arm64/include/asm/param.h b/arch/arm64/include/asm/param.h
new file mode 100644
index 0000000..8e3a281
--- /dev/null
+++ b/arch/arm64/include/asm/param.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_PARAM_H
+#define __ASM_PARAM_H
+
+#define EXEC_PAGESIZE	65536
+
+#include <asm-generic/param.h>
+
+#endif
diff --git a/arch/arm64/include/asm/perf_event.h b/arch/arm64/include/asm/perf_event.h
new file mode 100644
index 0000000..a6fffd5
--- /dev/null
+++ b/arch/arm64/include/asm/perf_event.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ASM_PERF_EVENT_H
+#define __ASM_PERF_EVENT_H
+
+/* It's quiet around here... */
+
+#endif
diff --git a/arch/arm64/include/asm/pgalloc.h b/arch/arm64/include/asm/pgalloc.h
new file mode 100644
index 0000000..f214069
--- /dev/null
+++ b/arch/arm64/include/asm/pgalloc.h
@@ -0,0 +1,113 @@
+/*
+ * Based on arch/arm/include/asm/pgalloc.h
+ *
+ * Copyright (C) 2000-2001 Russell King
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_PGALLOC_H
+#define __ASM_PGALLOC_H
+
+#include <asm/pgtable-hwdef.h>
+#include <asm/processor.h>
+#include <asm/cacheflush.h>
+#include <asm/tlbflush.h>
+
+#define check_pgt_cache()		do { } while (0)
+
+#ifndef CONFIG_ARM64_64K_PAGES
+
+static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
+{
+	return (pmd_t *)get_zeroed_page(GFP_KERNEL | __GFP_REPEAT);
+}
+
+static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
+{
+	BUG_ON((unsigned long)pmd & (PAGE_SIZE-1));
+	free_page((unsigned long)pmd);
+}
+
+static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)
+{
+	set_pud(pud, __pud(__pa(pmd) | PMD_TYPE_TABLE));
+}
+
+#endif	/* CONFIG_ARM64_64K_PAGES */
+
+extern pgd_t *pgd_alloc(struct mm_struct *mm);
+extern void pgd_free(struct mm_struct *mm, pgd_t *pgd);
+
+#define PGALLOC_GFP	(GFP_KERNEL | __GFP_NOTRACK | __GFP_REPEAT | __GFP_ZERO)
+
+static inline pte_t *
+pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr)
+{
+	return (pte_t *)__get_free_page(PGALLOC_GFP);
+}
+
+static inline pgtable_t
+pte_alloc_one(struct mm_struct *mm, unsigned long addr)
+{
+	struct page *pte;
+
+	pte = alloc_pages(PGALLOC_GFP, 0);
+	if (pte)
+		pgtable_page_ctor(pte);
+
+	return pte;
+}
+
+/*
+ * Free a PTE table.
+ */
+static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
+{
+	if (pte)
+		free_page((unsigned long)pte);
+}
+
+static inline void pte_free(struct mm_struct *mm, pgtable_t pte)
+{
+	pgtable_page_dtor(pte);
+	__free_page(pte);
+}
+
+static inline void __pmd_populate(pmd_t *pmdp, phys_addr_t pte,
+				  pmdval_t prot)
+{
+	set_pmd(pmdp, __pmd(pte | prot));
+}
+
+/*
+ * Populate the pmdp entry with a pointer to the pte.  This pmd is part
+ * of the mm address space.
+ */
+static inline void
+pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmdp, pte_t *ptep)
+{
+	/*
+	 * The pmd must be loaded with the physical address of the PTE table
+	 */
+	__pmd_populate(pmdp, __pa(ptep), PMD_TYPE_TABLE);
+}
+
+static inline void
+pmd_populate(struct mm_struct *mm, pmd_t *pmdp, pgtable_t ptep)
+{
+	__pmd_populate(pmdp, page_to_phys(ptep), PMD_TYPE_TABLE);
+}
+#define pmd_pgtable(pmd) pmd_page(pmd)
+
+#endif
diff --git a/arch/arm64/include/asm/pgtable-2level-hwdef.h b/arch/arm64/include/asm/pgtable-2level-hwdef.h
new file mode 100644
index 0000000..0a8ed3f
--- /dev/null
+++ b/arch/arm64/include/asm/pgtable-2level-hwdef.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_PGTABLE_2LEVEL_HWDEF_H
+#define __ASM_PGTABLE_2LEVEL_HWDEF_H
+
+/*
+ * With LPAE and 64KB pages, there are 2 levels of page tables. Each level has
+ * 8192 entries of 8 bytes each, occupying a 64KB page. Levels 0 and 1 are not
+ * used. The 2nd level table (PGD for Linux) can cover a range of 4TB, each
+ * entry representing 512MB. The user and kernel address spaces are limited to
+ * 512GB and therefore we only use 1024 entries in the PGD.
+ */
+#define PTRS_PER_PTE		8192
+#define PTRS_PER_PGD		1024
+
+/*
+ * PGDIR_SHIFT determines the size a top-level page table entry can map.
+ */
+#define PGDIR_SHIFT		29
+#define PGDIR_SIZE		(_AC(1, UL) << PGDIR_SHIFT)
+#define PGDIR_MASK		(~(PGDIR_SIZE-1))
+
+/*
+ * section address mask and size definitions.
+ */
+#define SECTION_SHIFT		29
+#define SECTION_SIZE		(_AC(1, UL) << SECTION_SHIFT)
+#define SECTION_MASK		(~(SECTION_SIZE-1))
+
+#endif
diff --git a/arch/arm64/include/asm/pgtable-2level-types.h b/arch/arm64/include/asm/pgtable-2level-types.h
new file mode 100644
index 0000000..3c3ca7d
--- /dev/null
+++ b/arch/arm64/include/asm/pgtable-2level-types.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_PGTABLE_2LEVEL_TYPES_H
+#define __ASM_PGTABLE_2LEVEL_TYPES_H
+
+typedef u64 pteval_t;
+typedef u64 pgdval_t;
+typedef pgdval_t pmdval_t;
+
+#undef STRICT_MM_TYPECHECKS
+
+#ifdef STRICT_MM_TYPECHECKS
+
+/*
+ * These are used to make use of C type-checking..
+ */
+typedef struct { pteval_t pte; } pte_t;
+typedef struct { pgdval_t pgd; } pgd_t;
+typedef struct { pteval_t pgprot; } pgprot_t;
+
+#define pte_val(x)      ((x).pte)
+#define pgd_val(x)	((x).pgd)
+#define pgprot_val(x)   ((x).pgprot)
+
+#define __pte(x)        ((pte_t) { (x) } )
+#define __pgd(x)	((pgd_t) { (x) } )
+#define __pgprot(x)     ((pgprot_t) { (x) } )
+
+#else	/* !STRICT_MM_TYPECHECKS */
+
+typedef pteval_t pte_t;
+typedef pgdval_t pgd_t;
+typedef pteval_t pgprot_t;
+
+#define pte_val(x)	(x)
+#define pgd_val(x)	(x)
+#define pgprot_val(x)	(x)
+
+#define __pte(x)	(x)
+#define __pgd(x)	(x)
+#define __pgprot(x)	(x)
+
+#endif	/* STRICT_MM_TYPECHECKS */
+
+#include <asm-generic/pgtable-nopmd.h>
+
+#endif	/* __ASM_PGTABLE_2LEVEL_TYPES_H */
diff --git a/arch/arm64/include/asm/pgtable-3level-hwdef.h b/arch/arm64/include/asm/pgtable-3level-hwdef.h
new file mode 100644
index 0000000..3dbf941
--- /dev/null
+++ b/arch/arm64/include/asm/pgtable-3level-hwdef.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_PGTABLE_3LEVEL_HWDEF_H
+#define __ASM_PGTABLE_3LEVEL_HWDEF_H
+
+/*
+ * With LPAE and 4KB pages, there are 3 levels of page tables. Each level has
+ * 512 entries of 8 bytes each, occupying a 4K page. The first level table
+ * covers a range of 512GB, each entry representing 1GB. The user and kernel
+ * address spaces are limited to 512GB each.
+ */
+#define PTRS_PER_PTE		512
+#define PTRS_PER_PMD		512
+#define PTRS_PER_PGD		512
+
+/*
+ * PGDIR_SHIFT determines the size a top-level page table entry can map.
+ */
+#define PGDIR_SHIFT		30
+#define PGDIR_SIZE		(_AC(1, UL) << PGDIR_SHIFT)
+#define PGDIR_MASK		(~(PGDIR_SIZE-1))
+
+/*
+ * PMD_SHIFT determines the size a middle-level page table entry can map.
+ */
+#define PMD_SHIFT		21
+#define PMD_SIZE		(_AC(1, UL) << PMD_SHIFT)
+#define PMD_MASK		(~(PMD_SIZE-1))
+
+/*
+ * section address mask and size definitions.
+ */
+#define SECTION_SHIFT		21
+#define SECTION_SIZE		(_AC(1, UL) << SECTION_SHIFT)
+#define SECTION_MASK		(~(SECTION_SIZE-1))
+
+#endif
diff --git a/arch/arm64/include/asm/pgtable-3level-types.h b/arch/arm64/include/asm/pgtable-3level-types.h
new file mode 100644
index 0000000..4489615
--- /dev/null
+++ b/arch/arm64/include/asm/pgtable-3level-types.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_PGTABLE_3LEVEL_TYPES_H
+#define __ASM_PGTABLE_3LEVEL_TYPES_H
+
+typedef u64 pteval_t;
+typedef u64 pmdval_t;
+typedef u64 pgdval_t;
+
+#undef STRICT_MM_TYPECHECKS
+
+#ifdef STRICT_MM_TYPECHECKS
+
+/*
+ * These are used to make use of C type-checking..
+ */
+typedef struct { pteval_t pte; } pte_t;
+typedef struct { pmdval_t pmd; } pmd_t;
+typedef struct { pgdval_t pgd; } pgd_t;
+typedef struct { pteval_t pgprot; } pgprot_t;
+
+#define pte_val(x)      ((x).pte)
+#define pmd_val(x)      ((x).pmd)
+#define pgd_val(x)	((x).pgd)
+#define pgprot_val(x)   ((x).pgprot)
+
+#define __pte(x)        ((pte_t) { (x) } )
+#define __pmd(x)        ((pmd_t) { (x) } )
+#define __pgd(x)	((pgd_t) { (x) } )
+#define __pgprot(x)     ((pgprot_t) { (x) } )
+
+#else	/* !STRICT_MM_TYPECHECKS */
+
+typedef pteval_t pte_t;
+typedef pmdval_t pmd_t;
+typedef pgdval_t pgd_t;
+typedef pteval_t pgprot_t;
+
+#define pte_val(x)	(x)
+#define pmd_val(x)	(x)
+#define pgd_val(x)	(x)
+#define pgprot_val(x)	(x)
+
+#define __pte(x)	(x)
+#define __pmd(x)	(x)
+#define __pgd(x)	(x)
+#define __pgprot(x)	(x)
+
+#endif	/* STRICT_MM_TYPECHECKS */
+
+#include <asm-generic/pgtable-nopud.h>
+
+#endif	/* __ASM_PGTABLE_3LEVEL_TYPES_H */
diff --git a/arch/arm64/include/asm/pgtable-hwdef.h b/arch/arm64/include/asm/pgtable-hwdef.h
new file mode 100644
index 0000000..0f3b458
--- /dev/null
+++ b/arch/arm64/include/asm/pgtable-hwdef.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_PGTABLE_HWDEF_H
+#define __ASM_PGTABLE_HWDEF_H
+
+#ifdef CONFIG_ARM64_64K_PAGES
+#include <asm/pgtable-2level-hwdef.h>
+#else
+#include <asm/pgtable-3level-hwdef.h>
+#endif
+
+/*
+ * Hardware page table definitions.
+ *
+ * Level 2 descriptor (PMD).
+ */
+#define PMD_TYPE_MASK		(_AT(pmdval_t, 3) << 0)
+#define PMD_TYPE_FAULT		(_AT(pmdval_t, 0) << 0)
+#define PMD_TYPE_TABLE		(_AT(pmdval_t, 3) << 0)
+#define PMD_TYPE_SECT		(_AT(pmdval_t, 1) << 0)
+
+/*
+ * Section
+ */
+#define PMD_SECT_S		(_AT(pmdval_t, 3) << 8)
+#define PMD_SECT_AF		(_AT(pmdval_t, 1) << 10)
+#define PMD_SECT_NG		(_AT(pmdval_t, 1) << 11)
+#define PMD_SECT_XN		(_AT(pmdval_t, 1) << 54)
+
+/*
+ * AttrIndx[2:0] encoding (mapping attributes defined in the MAIR* registers).
+ */
+#define PMD_ATTRINDX(t)		(_AT(pmdval_t, (t)) << 2)
+#define PMD_ATTRINDX_MASK	(_AT(pmdval_t, 7) << 2)
+
+/*
+ * Level 3 descriptor (PTE).
+ */
+#define PTE_TYPE_MASK		(_AT(pteval_t, 3) << 0)
+#define PTE_TYPE_FAULT		(_AT(pteval_t, 0) << 0)
+#define PTE_TYPE_PAGE		(_AT(pteval_t, 3) << 0)
+#define PTE_USER		(_AT(pteval_t, 1) << 6)		/* AP[1] */
+#define PTE_RDONLY		(_AT(pteval_t, 1) << 7)		/* AP[2] */
+#define PTE_SHARED		(_AT(pteval_t, 3) << 8)		/* SH[1:0], inner shareable */
+#define PTE_AF			(_AT(pteval_t, 1) << 10)	/* Access Flag */
+#define PTE_NG			(_AT(pteval_t, 1) << 11)	/* nG */
+#define PTE_XN			(_AT(pteval_t, 1) << 54)	/* XN */
+
+/*
+ * AttrIndx[2:0] encoding (mapping attributes defined in the MAIR* registers).
+ */
+#define PTE_ATTRINDX(t)		(_AT(pteval_t, (t)) << 2)
+#define PTE_ATTRINDX_MASK	(_AT(pteval_t, 7) << 2)
+
+/*
+ * 40-bit physical address supported.
+ */
+#define PHYS_MASK_SHIFT		(40)
+#define PHYS_MASK		((UL(1) << PHYS_MASK_SHIFT) - 1)
+
+/*
+ * TCR flags.
+ */
+#define TCR_TxSZ(x)		(((UL(64) - (x)) << 16) | ((UL(64) - (x)) << 0))
+#define TCR_IRGN_NC		((UL(0) << 8) | (UL(0) << 24))
+#define TCR_IRGN_WBWA		((UL(1) << 8) | (UL(1) << 24))
+#define TCR_IRGN_WT		((UL(2) << 8) | (UL(2) << 24))
+#define TCR_IRGN_WBnWA		((UL(3) << 8) | (UL(3) << 24))
+#define TCR_IRGN_MASK		((UL(3) << 8) | (UL(3) << 24))
+#define TCR_ORGN_NC		((UL(0) << 10) | (UL(0) << 26))
+#define TCR_ORGN_WBWA		((UL(1) << 10) | (UL(1) << 26))
+#define TCR_ORGN_WT		((UL(2) << 10) | (UL(2) << 26))
+#define TCR_ORGN_WBnWA		((UL(3) << 10) | (UL(3) << 26))
+#define TCR_ORGN_MASK		((UL(3) << 10) | (UL(3) << 26))
+#define TCR_SHARED		((UL(3) << 12) | (UL(3) << 28))
+#define TCR_TG0_64K		(UL(1) << 14)
+#define TCR_TG1_64K		(UL(1) << 30)
+#define TCR_IPS_40BIT		(UL(2) << 32)
+#define TCR_ASID16		(UL(1) << 36)
+
+#endif
diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
new file mode 100644
index 0000000..8960239
--- /dev/null
+++ b/arch/arm64/include/asm/pgtable.h
@@ -0,0 +1,328 @@
+/*
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_PGTABLE_H
+#define __ASM_PGTABLE_H
+
+#include <asm/proc-fns.h>
+
+#include <asm/memory.h>
+#include <asm/pgtable-hwdef.h>
+
+/*
+ * Software defined PTE bits definition.
+ */
+#define PTE_VALID		(_AT(pteval_t, 1) << 0)	/* pte_present() check */
+#define PTE_FILE		(_AT(pteval_t, 1) << 2)	/* only when !pte_present() */
+#define PTE_DIRTY		(_AT(pteval_t, 1) << 55)
+#define PTE_SPECIAL		(_AT(pteval_t, 1) << 56)
+
+/*
+ * VMALLOC and SPARSEMEM_VMEMMAP ranges.
+ */
+#define VMALLOC_START		UL(0xffffff8000000000)
+#define VMALLOC_END		(PAGE_OFFSET - UL(0x400000000) - SZ_64K)
+
+#define vmemmap			((struct page *)(VMALLOC_END + SZ_64K))
+
+#define FIRST_USER_ADDRESS	0
+
+#ifndef __ASSEMBLY__
+extern void __pte_error(const char *file, int line, unsigned long val);
+extern void __pmd_error(const char *file, int line, unsigned long val);
+extern void __pgd_error(const char *file, int line, unsigned long val);
+
+#define pte_ERROR(pte)		__pte_error(__FILE__, __LINE__, pte_val(pte))
+#ifndef CONFIG_ARM64_64K_PAGES
+#define pmd_ERROR(pmd)		__pmd_error(__FILE__, __LINE__, pmd_val(pmd))
+#endif
+#define pgd_ERROR(pgd)		__pgd_error(__FILE__, __LINE__, pgd_val(pgd))
+
+/*
+ * The pgprot_* and protection_map entries will be fixed up at runtime to
+ * include the cachable and bufferable bits based on memory policy, as well as
+ * any architecture dependent bits like global/ASID and SMP shared mapping
+ * bits.
+ */
+#define _PAGE_DEFAULT		PTE_TYPE_PAGE | PTE_AF
+
+extern pgprot_t pgprot_default;
+
+#define _MOD_PROT(p, b)	__pgprot(pgprot_val(p) | (b))
+
+#define PAGE_NONE		_MOD_PROT(pgprot_default, PTE_NG | PTE_XN | PTE_RDONLY)
+#define PAGE_SHARED		_MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_XN)
+#define PAGE_SHARED_EXEC	_MOD_PROT(pgprot_default, PTE_USER | PTE_NG)
+#define PAGE_COPY		_MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_XN | PTE_RDONLY)
+#define PAGE_COPY_EXEC		_MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_RDONLY)
+#define PAGE_READONLY		_MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_XN | PTE_RDONLY)
+#define PAGE_READONLY_EXEC	_MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_RDONLY)
+#define PAGE_KERNEL		_MOD_PROT(pgprot_default, PTE_XN | PTE_DIRTY)
+#define PAGE_KERNEL_EXEC	_MOD_PROT(pgprot_default, PTE_DIRTY)
+
+#define __PAGE_NONE		__pgprot(_PAGE_DEFAULT | PTE_NG | PTE_XN | PTE_RDONLY)
+#define __PAGE_SHARED		__pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_XN)
+#define __PAGE_SHARED_EXEC	__pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG)
+#define __PAGE_COPY		__pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_XN | PTE_RDONLY)
+#define __PAGE_COPY_EXEC	__pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_RDONLY)
+#define __PAGE_READONLY		__pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_XN | PTE_RDONLY)
+#define __PAGE_READONLY_EXEC	__pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_RDONLY)
+
+#endif /* __ASSEMBLY__ */
+
+#define __P000  __PAGE_NONE
+#define __P001  __PAGE_READONLY
+#define __P010  __PAGE_COPY
+#define __P011  __PAGE_COPY
+#define __P100  __PAGE_READONLY_EXEC
+#define __P101  __PAGE_READONLY_EXEC
+#define __P110  __PAGE_COPY_EXEC
+#define __P111  __PAGE_COPY_EXEC
+
+#define __S000  __PAGE_NONE
+#define __S001  __PAGE_READONLY
+#define __S010  __PAGE_SHARED
+#define __S011  __PAGE_SHARED
+#define __S100  __PAGE_READONLY_EXEC
+#define __S101  __PAGE_READONLY_EXEC
+#define __S110  __PAGE_SHARED_EXEC
+#define __S111  __PAGE_SHARED_EXEC
+
+#ifndef __ASSEMBLY__
+/*
+ * ZERO_PAGE is a global shared page that is always zero: used
+ * for zero-mapped memory areas etc..
+ */
+extern struct page *empty_zero_page;
+#define ZERO_PAGE(vaddr)	(empty_zero_page)
+
+#define pte_pfn(pte)		((pte_val(pte) & PHYS_MASK) >> PAGE_SHIFT)
+
+#define pfn_pte(pfn,prot)	(__pte(((phys_addr_t)(pfn) << PAGE_SHIFT) | pgprot_val(prot)))
+
+#define pte_none(pte)		(!pte_val(pte))
+#define pte_clear(mm,addr,ptep)	set_pte(ptep, __pte(0))
+#define pte_page(pte)		(pfn_to_page(pte_pfn(pte)))
+#define pte_offset_kernel(dir,addr)	(pmd_page_vaddr(*(dir)) + __pte_index(addr))
+
+#define pte_offset_map(dir,addr)	pte_offset_kernel((dir), (addr))
+#define pte_offset_map_nested(dir,addr)	pte_offset_kernel((dir), (addr))
+#define pte_unmap(pte)			do { } while (0)
+#define pte_unmap_nested(pte)		do { } while (0)
+
+/*
+ * The following only work if pte_present(). Undefined behaviour otherwise.
+ */
+#define pte_present(pte)	(pte_val(pte) & PTE_VALID)
+#define pte_dirty(pte)		(pte_val(pte) & PTE_DIRTY)
+#define pte_young(pte)		(pte_val(pte) & PTE_AF)
+#define pte_special(pte)	(pte_val(pte) & PTE_SPECIAL)
+#define pte_write(pte)		(!(pte_val(pte) & PTE_RDONLY))
+#define pte_exec(pte)		(!(pte_val(pte) & PTE_XN))
+
+#define pte_present_exec_user(pte) \
+	((pte_val(pte) & (PTE_VALID | PTE_USER | PTE_XN)) == \
+	 (PTE_VALID | PTE_USER))
+
+#define PTE_BIT_FUNC(fn,op) \
+static inline pte_t pte_##fn(pte_t pte) { pte_val(pte) op; return pte; }
+
+PTE_BIT_FUNC(wrprotect, |= PTE_RDONLY);
+PTE_BIT_FUNC(mkwrite,   &= ~PTE_RDONLY);
+PTE_BIT_FUNC(mkclean,   &= ~PTE_DIRTY);
+PTE_BIT_FUNC(mkdirty,   |= PTE_DIRTY);
+PTE_BIT_FUNC(mkold,     &= ~PTE_AF);
+PTE_BIT_FUNC(mkyoung,   |= PTE_AF);
+PTE_BIT_FUNC(mkspecial, |= PTE_SPECIAL);
+
+static inline void set_pte(pte_t *ptep, pte_t pte)
+{
+	*ptep = pte;
+}
+
+extern void __sync_icache_dcache(pte_t pteval, unsigned long addr);
+
+static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
+			      pte_t *ptep, pte_t pte)
+{
+	if (pte_present_exec_user(pte))
+		__sync_icache_dcache(pte, addr);
+	set_pte(ptep, pte);
+}
+
+/*
+ * Huge pte definitions.
+ */
+#define pte_huge(pte)		((pte_val(pte) & PTE_TYPE_MASK) == PTE_TYPE_HUGEPAGE)
+#define pte_mkhuge(pte)		(__pte((pte_val(pte) & ~PTE_TYPE_MASK) | PTE_TYPE_HUGEPAGE))
+
+#define __pgprot_modify(prot,mask,bits)		\
+	__pgprot((pgprot_val(prot) & ~(mask)) | (bits))
+
+#define __HAVE_ARCH_PTE_SPECIAL
+
+/*
+ * Mark the prot value as uncacheable and unbufferable.
+ */
+#define pgprot_noncached(prot) \
+	__pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_DEVICE_nGnRnE))
+#define pgprot_writecombine(prot) \
+	__pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_DEVICE_GRE))
+#define pgprot_dmacoherent(prot) \
+	__pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_NORMAL_NC))
+#define __HAVE_PHYS_MEM_ACCESS_PROT
+struct file;
+extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
+				     unsigned long size, pgprot_t vma_prot);
+
+#define pmd_none(pmd)		(!pmd_val(pmd))
+#define pmd_present(pmd)	(pmd_val(pmd))
+
+#define pmd_bad(pmd)		(!(pmd_val(pmd) & 2))
+
+static inline void set_pmd(pmd_t *pmdp, pmd_t pmd)
+{
+	*pmdp = pmd;
+	dsb();
+}
+
+static inline void pmd_clear(pmd_t *pmdp)
+{
+	set_pmd(pmdp, __pmd(0));
+}
+
+static inline pte_t *pmd_page_vaddr(pmd_t pmd)
+{
+	return __va(pmd_val(pmd) & PHYS_MASK & (s32)PAGE_MASK);
+}
+
+#define pmd_page(pmd)		pfn_to_page(__phys_to_pfn(pmd_val(pmd) & PHYS_MASK))
+
+/*
+ * Conversion functions: convert a page and protection to a page entry,
+ * and a page entry and page directory to the page they refer to.
+ */
+#define mk_pte(page,prot)	pfn_pte(page_to_pfn(page),prot)
+
+#ifndef CONFIG_ARM64_64K_PAGES
+
+#define pud_none(pud)		(!pud_val(pud))
+#define pud_bad(pud)		(!(pud_val(pud) & 2))
+#define pud_present(pud)	(pud_val(pud))
+
+static inline void set_pud(pud_t *pudp, pud_t pud)
+{
+	*pudp = pud;
+	dsb();
+}
+
+static inline void pud_clear(pud_t *pudp)
+{
+	set_pud(pudp, __pud(0));
+}
+
+static inline pmd_t *pud_page_vaddr(pud_t pud)
+{
+	return __va(pud_val(pud) & PHYS_MASK & (s32)PAGE_MASK);
+}
+
+#endif	/* CONFIG_ARM64_64K_PAGES */
+
+/* to find an entry in a page-table-directory */
+#define pgd_index(addr)		(((addr) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1))
+
+#define pgd_offset(mm, addr)	((mm)->pgd+pgd_index(addr))
+
+/* to find an entry in a kernel page-table-directory */
+#define pgd_offset_k(addr)	pgd_offset(&init_mm, addr)
+
+/* Find an entry in the second-level page table.. */
+#ifndef CONFIG_ARM64_64K_PAGES
+#define pmd_index(addr)		(((addr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1))
+static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr)
+{
+	return (pmd_t *)pud_page_vaddr(*pud) + pmd_index(addr);
+}
+#endif
+
+/* Find an entry in the third-level page table.. */
+#define __pte_index(addr)	(((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
+
+static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+{
+	const pteval_t mask = PTE_USER | PTE_XN | PTE_RDONLY;
+	pte_val(pte) = (pte_val(pte) & ~mask) | (pgprot_val(newprot) & mask);
+	return pte;
+}
+
+extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
+extern pgd_t idmap_pg_dir[PTRS_PER_PGD];
+
+#define SWAPPER_DIR_SIZE	(3 * PAGE_SIZE)
+#define IDMAP_DIR_SIZE		(2 * PAGE_SIZE)
+
+/*
+ * Encode and decode a swap entry:
+ *	bits 0-1:	present (must be zero)
+ *	bit  2:		PTE_FILE
+ *	bits 3-8:	swap type
+ *	bits 9-63:	swap offset
+ */
+#define __SWP_TYPE_SHIFT	3
+#define __SWP_TYPE_BITS		6
+#define __SWP_TYPE_MASK		((1 << __SWP_TYPE_BITS) - 1)
+#define __SWP_OFFSET_SHIFT	(__SWP_TYPE_BITS + __SWP_TYPE_SHIFT)
+
+#define __swp_type(x)		(((x).val >> __SWP_TYPE_SHIFT) & __SWP_TYPE_MASK)
+#define __swp_offset(x)		((x).val >> __SWP_OFFSET_SHIFT)
+#define __swp_entry(type,offset) ((swp_entry_t) { ((type) << __SWP_TYPE_SHIFT) | ((offset) << __SWP_OFFSET_SHIFT) })
+
+#define __pte_to_swp_entry(pte)	((swp_entry_t) { pte_val(pte) })
+#define __swp_entry_to_pte(swp)	((pte_t) { (swp).val })
+
+/*
+ * Ensure that there are not more swap files than can be encoded in the kernel
+ * the PTEs.
+ */
+#define MAX_SWAPFILES_CHECK() BUILD_BUG_ON(MAX_SWAPFILES_SHIFT > __SWP_TYPE_BITS)
+
+/*
+ * Encode and decode a file entry:
+ *	bits 0-1:	present (must be zero)
+ *	bit  2:		PTE_FILE
+ *	bits 3-63:	file offset / PAGE_SIZE
+ */
+#define pte_file(pte)		(pte_val(pte) & PTE_FILE)
+#define pte_to_pgoff(x)		(pte_val(x) >> 3)
+#define pgoff_to_pte(x)		__pte(((x) << 3) | PTE_FILE)
+
+#define PTE_FILE_MAX_BITS	61
+
+extern int kern_addr_valid(unsigned long addr);
+
+#include <asm-generic/pgtable.h>
+
+/*
+ * remap a physical page `pfn' of size `size' with page protection `prot'
+ * into virtual address `from'
+ */
+#define io_remap_pfn_range(vma,from,pfn,size,prot) \
+		remap_pfn_range(vma, from, pfn, size, prot)
+
+#define pgtable_cache_init() do { } while (0)
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* __ASM_PGTABLE_H */
diff --git a/arch/arm64/include/asm/pmu.h b/arch/arm64/include/asm/pmu.h
new file mode 100644
index 0000000..e6f0878
--- /dev/null
+++ b/arch/arm64/include/asm/pmu.h
@@ -0,0 +1,82 @@
+/*
+ * Based on arch/arm/include/asm/pmu.h
+ *
+ * Copyright (C) 2009 picoChip Designs Ltd, Jamie Iles
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_PMU_H
+#define __ASM_PMU_H
+
+#ifdef CONFIG_HW_PERF_EVENTS
+
+/* The events for a given PMU register set. */
+struct pmu_hw_events {
+	/*
+	 * The events that are active on the PMU for the given index.
+	 */
+	struct perf_event	**events;
+
+	/*
+	 * A 1 bit for an index indicates that the counter is being used for
+	 * an event. A 0 means that the counter can be used.
+	 */
+	unsigned long           *used_mask;
+
+	/*
+	 * Hardware lock to serialize accesses to PMU registers. Needed for the
+	 * read/modify/write sequences.
+	 */
+	raw_spinlock_t		pmu_lock;
+};
+
+struct arm_pmu {
+	struct pmu		pmu;
+	cpumask_t		active_irqs;
+	const char		*name;
+	irqreturn_t		(*handle_irq)(int irq_num, void *dev);
+	void			(*enable)(struct hw_perf_event *evt, int idx);
+	void			(*disable)(struct hw_perf_event *evt, int idx);
+	int			(*get_event_idx)(struct pmu_hw_events *hw_events,
+						 struct hw_perf_event *hwc);
+	int			(*set_event_filter)(struct hw_perf_event *evt,
+						    struct perf_event_attr *attr);
+	u32			(*read_counter)(int idx);
+	void			(*write_counter)(int idx, u32 val);
+	void			(*start)(void);
+	void			(*stop)(void);
+	void			(*reset)(void *);
+	int			(*map_event)(struct perf_event *event);
+	int			num_events;
+	atomic_t		active_events;
+	struct mutex		reserve_mutex;
+	u64			max_period;
+	struct platform_device	*plat_device;
+	struct pmu_hw_events	*(*get_hw_events)(void);
+};
+
+#define to_arm_pmu(p) (container_of(p, struct arm_pmu, pmu))
+
+int __init armpmu_register(struct arm_pmu *armpmu, char *name, int type);
+
+u64 armpmu_event_update(struct perf_event *event,
+			struct hw_perf_event *hwc,
+			int idx);
+
+int armpmu_event_set_period(struct perf_event *event,
+			    struct hw_perf_event *hwc,
+			    int idx);
+
+#endif /* CONFIG_HW_PERF_EVENTS */
+#endif /* __ASM_PMU_H */
diff --git a/arch/arm64/include/asm/proc-fns.h b/arch/arm64/include/asm/proc-fns.h
new file mode 100644
index 0000000..7cdf466
--- /dev/null
+++ b/arch/arm64/include/asm/proc-fns.h
@@ -0,0 +1,50 @@
+/*
+ * Based on arch/arm/include/asm/proc-fns.h
+ *
+ * Copyright (C) 1997-1999 Russell King
+ * Copyright (C) 2000 Deep Blue Solutions Ltd
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_PROCFNS_H
+#define __ASM_PROCFNS_H
+
+#ifdef __KERNEL__
+#ifndef __ASSEMBLY__
+
+#include <asm/page.h>
+
+struct mm_struct;
+
+extern void cpu_cache_off(void);
+extern void cpu_do_idle(void);
+extern void cpu_do_switch_mm(unsigned long pgd_phys, struct mm_struct *mm);
+extern void cpu_reset(unsigned long addr) __attribute__((noreturn));
+
+#include <asm/memory.h>
+
+#define cpu_switch_mm(pgd,mm) cpu_do_switch_mm(virt_to_phys(pgd),mm)
+
+#define cpu_get_pgd()					\
+({							\
+	unsigned long pg;				\
+	asm("mrs	%0, ttbr0_el1\n"		\
+	    : "=r" (pg));				\
+	pg &= ~0xffff000000003ffful;			\
+	(pgd_t *)phys_to_virt(pg);			\
+})
+
+#endif /* __ASSEMBLY__ */
+#endif /* __KERNEL__ */
+#endif /* __ASM_PROCFNS_H */
diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h
new file mode 100644
index 0000000..39a208a
--- /dev/null
+++ b/arch/arm64/include/asm/processor.h
@@ -0,0 +1,175 @@
+/*
+ * Based on arch/arm/include/asm/processor.h
+ *
+ * Copyright (C) 1995-1999 Russell King
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_PROCESSOR_H
+#define __ASM_PROCESSOR_H
+
+/*
+ * Default implementation of macro that returns current
+ * instruction pointer ("program counter").
+ */
+#define current_text_addr() ({ __label__ _l; _l: &&_l;})
+
+#ifdef __KERNEL__
+
+#include <linux/string.h>
+
+#include <asm/fpsimd.h>
+#include <asm/hw_breakpoint.h>
+#include <asm/ptrace.h>
+#include <asm/types.h>
+
+#ifdef __KERNEL__
+#define STACK_TOP_MAX		TASK_SIZE_64
+#ifdef CONFIG_COMPAT
+#define AARCH32_VECTORS_BASE	0xffff0000
+#define STACK_TOP		(test_thread_flag(TIF_32BIT) ? \
+				AARCH32_VECTORS_BASE : STACK_TOP_MAX)
+#else
+#define STACK_TOP		STACK_TOP_MAX
+#endif /* CONFIG_COMPAT */
+#endif /* __KERNEL__ */
+
+struct debug_info {
+	/* Have we suspended stepping by a debugger? */
+	int			suspended_step;
+	/* Allow breakpoints and watchpoints to be disabled for this thread. */
+	int			bps_disabled;
+	int			wps_disabled;
+	/* Hardware breakpoints pinned to this task. */
+	struct perf_event	*hbp_break[ARM_MAX_BRP];
+	struct perf_event	*hbp_watch[ARM_MAX_WRP];
+};
+
+struct cpu_context {
+	unsigned long x19;
+	unsigned long x20;
+	unsigned long x21;
+	unsigned long x22;
+	unsigned long x23;
+	unsigned long x24;
+	unsigned long x25;
+	unsigned long x26;
+	unsigned long x27;
+	unsigned long x28;
+	unsigned long fp;
+	unsigned long sp;
+	unsigned long pc;
+};
+
+struct thread_struct {
+	struct cpu_context	cpu_context;	/* cpu context */
+	unsigned long		tp_value;
+	struct fpsimd_state	fpsimd_state;
+	unsigned long		fault_address;	/* fault info */
+	struct debug_info	debug;		/* debugging */
+};
+
+#define INIT_THREAD  {	}
+
+static inline void start_thread_common(struct pt_regs *regs, unsigned long pc)
+{
+	memset(regs, 0, sizeof(*regs));
+	regs->syscallno = ~0UL;
+	regs->pc = pc;
+}
+
+static inline void start_thread(struct pt_regs *regs, unsigned long pc,
+				unsigned long sp)
+{
+	unsigned long *stack = (unsigned long *)sp;
+
+	start_thread_common(regs, pc);
+	regs->pstate = PSR_MODE_EL0t;
+	regs->sp = sp;
+	regs->regs[2] = stack[2];	/* x2 (envp) */
+	regs->regs[1] = stack[1];	/* x1 (argv) */
+	regs->regs[0] = stack[0];	/* x0 (argc) */
+}
+
+#ifdef CONFIG_COMPAT
+static inline void compat_start_thread(struct pt_regs *regs, unsigned long pc,
+				       unsigned long sp)
+{
+	unsigned int *stack = (unsigned int *)sp;
+
+	start_thread_common(regs, pc);
+	regs->pstate = COMPAT_PSR_MODE_USR;
+	if (pc & 1)
+		regs->pstate |= COMPAT_PSR_T_BIT;
+	regs->compat_sp = sp;
+	regs->regs[2] = stack[2];	/* x2 (envp) */
+	regs->regs[1] = stack[1];	/* x1 (argv) */
+	regs->regs[0] = stack[0];	/* x0 (argc) */
+}
+#endif
+
+/* Forward declaration, a strange C thing */
+struct task_struct;
+
+/* Free all resources held by a thread. */
+extern void release_thread(struct task_struct *);
+
+/* Prepare to copy thread state - unlazy all lazy status */
+#define prepare_to_copy(tsk)	do { } while (0)
+
+unsigned long get_wchan(struct task_struct *p);
+
+#define cpu_relax()			barrier()
+
+/* Thread switching */
+extern struct task_struct *cpu_switch_to(struct task_struct *prev,
+					 struct task_struct *next);
+
+/*
+ * Create a new kernel thread
+ */
+extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
+
+#define task_pt_regs(p) \
+	((struct pt_regs *)(THREAD_START_SP + task_stack_page(p)) - 1)
+
+#define KSTK_EIP(tsk)	task_pt_regs(tsk)->pc
+#define KSTK_ESP(tsk)	task_pt_regs(tsk)->sp
+
+/*
+ * Prefetching support
+ */
+#define ARCH_HAS_PREFETCH
+static inline void prefetch(const void *ptr)
+{
+	asm volatile("prfm pldl1keep, %a0\n" : : "p" (ptr));
+}
+
+#define ARCH_HAS_PREFETCHW
+static inline void prefetchw(const void *ptr)
+{
+	asm volatile("prfm pstl1keep, %a0\n" : : "p" (ptr));
+}
+
+#define ARCH_HAS_SPINLOCK_PREFETCH
+static inline void spin_lock_prefetch(const void *x)
+{
+	prefetchw(x);
+}
+
+#define HAVE_ARCH_PICK_MMAP_LAYOUT
+
+#endif
+
+#endif /* __ASM_PROCESSOR_H */
diff --git a/arch/arm64/include/asm/prom.h b/arch/arm64/include/asm/prom.h
new file mode 100644
index 0000000..68b90e6
--- /dev/null
+++ b/arch/arm64/include/asm/prom.h
@@ -0,0 +1 @@
+/* Empty for now */
diff --git a/arch/arm64/include/asm/ptrace.h b/arch/arm64/include/asm/ptrace.h
new file mode 100644
index 0000000..b0a2e1f
--- /dev/null
+++ b/arch/arm64/include/asm/ptrace.h
@@ -0,0 +1,212 @@
+/*
+ * Based on arch/arm/include/asm/ptrace.h
+ *
+ * Copyright (C) 1996-2003 Russell King
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_PTRACE_H
+#define __ASM_PTRACE_H
+
+#include <linux/types.h>
+
+#include <asm/hwcap.h>
+
+#define PTRACE_GETREGS		12
+#define PTRACE_SETREGS		13
+#define PTRACE_GETFPSIMDREGS	14
+#define PTRACE_SETFPSIMDREGS	15
+/* PTRACE_ATTACH is 16 */
+/* PTRACE_DETACH is 17 */
+#define PTRACE_GET_THREAD_AREA	22
+#define PTRACE_SET_SYSCALL	23
+#define PTRACE_GETHBPREGS	29
+#define PTRACE_SETHBPREGS	30
+
+/* AArch32-specific ptrace requests */
+#define COMPAT_PTRACE_GETVFPREGS	27
+#define COMPAT_PTRACE_SETVFPREGS	28
+
+/*
+ * PSR bits
+ */
+#define PSR_MODE_EL0t	0x00000000
+#define PSR_MODE_EL1t	0x00000004
+#define PSR_MODE_EL1h	0x00000005
+#define PSR_MODE_EL2t	0x00000008
+#define PSR_MODE_EL2h	0x00000009
+#define PSR_MODE_EL3t	0x0000000c
+#define PSR_MODE_EL3h	0x0000000d
+#define PSR_MODE_MASK	0x0000000f
+
+/* AArch32 CPSR bits */
+#define PSR_MODE32_BIT		0x00000010
+#define COMPAT_PSR_MODE_USR	0x00000010
+#define COMPAT_PSR_T_BIT	0x00000020
+#define COMPAT_PSR_IT_MASK	0x0600fc00	/* If-Then execution state mask */
+
+/* AArch64 SPSR bits */
+#define PSR_F_BIT	0x00000040
+#define PSR_I_BIT	0x00000080
+#define PSR_A_BIT	0x00000100
+#define PSR_D_BIT	0x00000200
+#define PSR_Q_BIT	0x08000000
+#define PSR_V_BIT	0x10000000
+#define PSR_C_BIT	0x20000000
+#define PSR_Z_BIT	0x40000000
+#define PSR_N_BIT	0x80000000
+
+/*
+ * Groups of PSR bits
+ */
+#define PSR_f		0xff000000	/* Flags		*/
+#define PSR_s		0x00ff0000	/* Status		*/
+#define PSR_x		0x0000ff00	/* Extension		*/
+#define PSR_c		0x000000ff	/* Control		*/
+
+/*
+ * These are 'magic' values for PTRACE_PEEKUSR that return info about where a
+ * process is located in memory.
+ */
+#define PT_TEXT_ADDR		0x10000
+#define PT_DATA_ADDR		0x10004
+#define PT_TEXT_END_ADDR	0x10008
+
+#ifndef __ASSEMBLY__
+
+/*
+ * User structures for general purpose, floating point and debug registers.
+ */
+struct user_pt_regs {
+	__u64		regs[31];
+	__u64		sp;
+	__u64		pc;
+	__u64		pstate;
+};
+
+struct user_fpsimd_state {
+	__uint128_t	vregs[32];
+	__u32		fpsr;
+	__u32		fpcr;
+};
+
+struct user_hwdebug_state {
+	__u32		dbg_info;
+	struct {
+		__u64	addr;
+		__u32	ctrl;
+	}		dbg_regs[16];
+};
+
+#ifdef __KERNEL__
+
+/* sizeof(struct user) for AArch32 */
+#define COMPAT_USER_SZ	296
+/* AArch32 uses x13 as the stack pointer... */
+#define compat_sp	regs[13]
+/* ... and x14 as the link register. */
+#define compat_lr	regs[14]
+
+/*
+ * This struct defines the way the registers are stored on the stack during an
+ * exception. Note that sizeof(struct pt_regs) has to be a multiple of 16 (for
+ * stack alignment). struct user_pt_regs must form a prefix of struct pt_regs.
+ */
+struct pt_regs {
+	union {
+		struct user_pt_regs user_regs;
+		struct {
+			u64 regs[31];
+			u64 sp;
+			u64 pc;
+			u64 pstate;
+		};
+	};
+	u64 orig_x0;
+	u64 syscallno;
+};
+
+#define arch_has_single_step()	(1)
+
+#ifdef CONFIG_COMPAT
+#define compat_thumb_mode(regs) \
+	(((regs)->pstate & COMPAT_PSR_T_BIT))
+#else
+#define compat_thumb_mode(regs) (0)
+#endif
+
+#define user_mode(regs)	\
+	(((regs)->pstate & PSR_MODE_MASK) == PSR_MODE_EL0t)
+
+#define compat_user_mode(regs)	\
+	(((regs)->pstate & (PSR_MODE32_BIT | PSR_MODE_MASK)) == \
+	 (PSR_MODE32_BIT | PSR_MODE_EL0t))
+
+#define processor_mode(regs) \
+	((regs)->pstate & PSR_MODE_MASK)
+
+#define interrupts_enabled(regs) \
+	(!((regs)->pstate & PSR_I_BIT))
+
+#define fast_interrupts_enabled(regs) \
+	(!((regs)->pstate & PSR_F_BIT))
+
+#define user_stack_pointer(regs) \
+	((regs)->sp)
+
+/*
+ * Are the current registers suitable for user mode? (used to maintain
+ * security in signal handlers)
+ */
+static inline int valid_user_regs(struct user_pt_regs *regs)
+{
+	if (user_mode(regs) && (regs->pstate & PSR_I_BIT) == 0) {
+		regs->pstate &= ~(PSR_F_BIT | PSR_A_BIT);
+
+		/* The T bit is reserved for AArch64 */
+		if (!(regs->pstate & PSR_MODE32_BIT))
+			regs->pstate &= ~COMPAT_PSR_T_BIT;
+
+		return 1;
+	}
+
+	/*
+	 * Force PSR to something logical...
+	 */
+	regs->pstate &= PSR_f | PSR_s | (PSR_x & ~PSR_A_BIT) | \
+			COMPAT_PSR_T_BIT | PSR_MODE32_BIT;
+
+	if (!(regs->pstate & PSR_MODE32_BIT)) {
+		regs->pstate &= ~COMPAT_PSR_T_BIT;
+		regs->pstate |= PSR_MODE_EL0t;
+	}
+
+	return 0;
+}
+
+#define instruction_pointer(regs)	(regs)->pc
+
+#ifdef CONFIG_SMP
+extern unsigned long profile_pc(struct pt_regs *regs);
+#else
+#define profile_pc(regs) instruction_pointer(regs)
+#endif
+
+extern int aarch32_break_trap(struct pt_regs *regs);
+
+#endif /* __KERNEL__ */
+
+#endif /* __ASSEMBLY__ */
+
+#endif
diff --git a/arch/arm64/include/asm/setup.h b/arch/arm64/include/asm/setup.h
new file mode 100644
index 0000000..9cf2e46
--- /dev/null
+++ b/arch/arm64/include/asm/setup.h
@@ -0,0 +1,26 @@
+/*
+ * Based on arch/arm/include/asm/setup.h
+ *
+ * Copyright (C) 1997-1999 Russell King
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_SETUP_H
+#define __ASM_SETUP_H
+
+#include <linux/types.h>
+
+#define COMMAND_LINE_SIZE	2048
+
+#endif
diff --git a/arch/arm64/include/asm/shmparam.h b/arch/arm64/include/asm/shmparam.h
new file mode 100644
index 0000000..4df608a
--- /dev/null
+++ b/arch/arm64/include/asm/shmparam.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_SHMPARAM_H
+#define __ASM_SHMPARAM_H
+
+/*
+ * For IPC syscalls from compat tasks, we need to use the legacy 16k
+ * alignment value. Since we don't have aliasing D-caches, the rest of
+ * the time we can safely use PAGE_SIZE.
+ */
+#define COMPAT_SHMLBA	0x4000
+
+#include <asm-generic/shmparam.h>
+
+#endif /* __ASM_SHMPARAM_H */
diff --git a/arch/arm64/include/asm/sigcontext.h b/arch/arm64/include/asm/sigcontext.h
new file mode 100644
index 0000000..573cec7
--- /dev/null
+++ b/arch/arm64/include/asm/sigcontext.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_SIGCONTEXT_H
+#define __ASM_SIGCONTEXT_H
+
+#include <linux/types.h>
+
+/*
+ * Signal context structure - contains all info to do with the state
+ * before the signal handler was invoked.
+ */
+struct sigcontext {
+	__u64 fault_address;
+	/* AArch64 registers */
+	__u64 regs[31];
+	__u64 sp;
+	__u64 pc;
+	__u64 pstate;
+	/* 4K reserved for FP/SIMD state and future expansion */
+	__u8 __reserved[4096] __attribute__((__aligned__(16)));
+};
+
+/*
+ * Header to be used at the beginning of structures extending the user
+ * context. Such structures must be placed after the rt_sigframe on the stack
+ * and be 16-byte aligned. The last structure must be a dummy one with the
+ * magic and size set to 0.
+ */
+struct _aarch64_ctx {
+	__u32 magic;
+	__u32 size;
+};
+
+#define FPSIMD_MAGIC	0x46508001
+
+struct fpsimd_context {
+	struct _aarch64_ctx head;
+	__u32 fpsr;
+	__u32 fpcr;
+	__uint128_t vregs[32];
+};
+
+#ifdef __KERNEL__
+/*
+ * Auxiliary context saved in the sigcontext.__reserved array. Not exported to
+ * user space as it will change with the addition of new context. User space
+ * should check the magic/size information.
+ */
+struct aux_context {
+	struct fpsimd_context fpsimd;
+	/* additional context to be added before "end" */
+	struct _aarch64_ctx end;
+};
+#endif
+
+#endif
diff --git a/arch/arm64/include/asm/siginfo.h b/arch/arm64/include/asm/siginfo.h
new file mode 100644
index 0000000..5a74a08
--- /dev/null
+++ b/arch/arm64/include/asm/siginfo.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_SIGINFO_H
+#define __ASM_SIGINFO_H
+
+#define __ARCH_SI_PREAMBLE_SIZE	(4 * sizeof(int))
+
+#include <asm-generic/siginfo.h>
+
+#endif
diff --git a/arch/arm64/include/asm/signal.h b/arch/arm64/include/asm/signal.h
new file mode 100644
index 0000000..8d1e723
--- /dev/null
+++ b/arch/arm64/include/asm/signal.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_SIGNAL_H
+#define __ASM_SIGNAL_H
+
+/* Required for AArch32 compatibility. */
+#define SA_RESTORER	0x04000000
+
+#include <asm-generic/signal.h>
+
+#endif
diff --git a/arch/arm64/include/asm/signal32.h b/arch/arm64/include/asm/signal32.h
new file mode 100644
index 0000000..7c275e3
--- /dev/null
+++ b/arch/arm64/include/asm/signal32.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_SIGNAL32_H
+#define __ASM_SIGNAL32_H
+
+#ifdef __KERNEL__
+#ifdef CONFIG_COMPAT
+#include <linux/compat.h>
+
+#define AARCH32_KERN_SIGRET_CODE_OFFSET	0x500
+
+extern const compat_ulong_t aarch32_sigret_code[6];
+
+int compat_setup_frame(int usig, struct k_sigaction *ka, sigset_t *set,
+		       struct pt_regs *regs);
+int compat_setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
+			  sigset_t *set, struct pt_regs *regs);
+
+void compat_setup_restart_syscall(struct pt_regs *regs);
+#else
+
+static inline int compat_setup_frame(int usid, struct k_sigaction *ka,
+				     sigset_t *set, struct pt_regs *regs)
+{
+	return -ENOSYS;
+}
+
+static inline int compat_setup_rt_frame(int usig, struct k_sigaction *ka,
+					siginfo_t *info, sigset_t *set,
+					struct pt_regs *regs)
+{
+	return -ENOSYS;
+}
+
+static inline void compat_setup_restart_syscall(struct pt_regs *regs)
+{
+}
+#endif /* CONFIG_COMPAT */
+#endif /* __KERNEL__ */
+#endif /* __ASM_SIGNAL32_H */
diff --git a/arch/arm64/include/asm/smp.h b/arch/arm64/include/asm/smp.h
new file mode 100644
index 0000000..7e34295
--- /dev/null
+++ b/arch/arm64/include/asm/smp.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_SMP_H
+#define __ASM_SMP_H
+
+#include <linux/threads.h>
+#include <linux/cpumask.h>
+#include <linux/thread_info.h>
+
+#ifndef CONFIG_SMP
+# error "<asm/smp.h> included in non-SMP build"
+#endif
+
+#define raw_smp_processor_id() (current_thread_info()->cpu)
+
+struct seq_file;
+
+/*
+ * generate IPI list text
+ */
+extern void show_ipi_list(struct seq_file *p, int prec);
+
+/*
+ * Called from C code, this handles an IPI.
+ */
+extern void handle_IPI(int ipinr, struct pt_regs *regs);
+
+/*
+ * Setup the set of possible CPUs (via set_cpu_possible)
+ */
+extern void smp_init_cpus(void);
+
+/*
+ * Provide a function to raise an IPI cross call on CPUs in callmap.
+ */
+extern void set_smp_cross_call(void (*)(const struct cpumask *, unsigned int));
+
+/*
+ * Called from the secondary holding pen, this is the secondary CPU entry point.
+ */
+asmlinkage void secondary_start_kernel(void);
+
+/*
+ * Initial data for bringing up a secondary CPU.
+ */
+struct secondary_data {
+	void *stack;
+};
+extern struct secondary_data secondary_data;
+extern void secondary_holding_pen(void);
+extern volatile unsigned long secondary_holding_pen_release;
+
+extern void arch_send_call_function_single_ipi(int cpu);
+extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
+
+#endif /* ifndef __ASM_SMP_H */
diff --git a/arch/arm64/include/asm/sparsemem.h b/arch/arm64/include/asm/sparsemem.h
new file mode 100644
index 0000000..1be62bc
--- /dev/null
+++ b/arch/arm64/include/asm/sparsemem.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_SPARSEMEM_H
+#define __ASM_SPARSEMEM_H
+
+#ifdef CONFIG_SPARSEMEM
+#define MAX_PHYSMEM_BITS	40
+#define SECTION_SIZE_BITS	30
+#endif
+
+#endif
diff --git a/arch/arm64/include/asm/spinlock.h b/arch/arm64/include/asm/spinlock.h
new file mode 100644
index 0000000..41112fe
--- /dev/null
+++ b/arch/arm64/include/asm/spinlock.h
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_SPINLOCK_H
+#define __ASM_SPINLOCK_H
+
+#include <asm/spinlock_types.h>
+#include <asm/processor.h>
+
+/*
+ * Spinlock implementation.
+ *
+ * The old value is read exclusively and the new one, if unlocked, is written
+ * exclusively. In case of failure, the loop is restarted.
+ *
+ * The memory barriers are implicit with the load-acquire and store-release
+ * instructions.
+ *
+ * Unlocked value: 0
+ * Locked value: 1
+ */
+
+#define arch_spin_is_locked(x)		((x)->lock != 0)
+#define arch_spin_unlock_wait(lock) \
+	do { while (arch_spin_is_locked(lock)) cpu_relax(); } while (0)
+
+#define arch_spin_lock_flags(lock, flags) arch_spin_lock(lock)
+
+static inline void arch_spin_lock(arch_spinlock_t *lock)
+{
+	unsigned int tmp;
+
+	asm volatile(
+	"	sevl\n"
+	"1:	wfe\n"
+	"2:	ldaxr	%w0, [%1]\n"
+	"	cbnz	%w0, 1b\n"
+	"	stxr	%w0, %w2, [%1]\n"
+	"	cbnz	%w0, 2b\n"
+	: "=&r" (tmp)
+	: "r" (&lock->lock), "r" (1)
+	: "memory");
+}
+
+static inline int arch_spin_trylock(arch_spinlock_t *lock)
+{
+	unsigned int tmp;
+
+	asm volatile(
+	"	ldaxr	%w0, [%1]\n"
+	"	cbnz	%w0, 1f\n"
+	"	stxr	%w0, %w2, [%1]\n"
+	"1:\n"
+	: "=&r" (tmp)
+	: "r" (&lock->lock), "r" (1)
+	: "memory");
+
+	return !tmp;
+}
+
+static inline void arch_spin_unlock(arch_spinlock_t *lock)
+{
+	asm volatile(
+	"	stlr	%w1, [%0]\n"
+	: : "r" (&lock->lock), "r" (0) : "memory");
+}
+
+/*
+ * Write lock implementation.
+ *
+ * Write locks set bit 31. Unlocking, is done by writing 0 since the lock is
+ * exclusively held.
+ *
+ * The memory barriers are implicit with the load-acquire and store-release
+ * instructions.
+ */
+
+static inline void arch_write_lock(arch_rwlock_t *rw)
+{
+	unsigned int tmp;
+
+	asm volatile(
+	"	sevl\n"
+	"1:	wfe\n"
+	"2:	ldaxr	%w0, [%1]\n"
+	"	cbnz	%w0, 1b\n"
+	"	stxr	%w0, %w2, [%1]\n"
+	"	cbnz	%w0, 2b\n"
+	: "=&r" (tmp)
+	: "r" (&rw->lock), "r" (0x80000000)
+	: "memory");
+}
+
+static inline int arch_write_trylock(arch_rwlock_t *rw)
+{
+	unsigned int tmp;
+
+	asm volatile(
+	"	ldaxr	%w0, [%1]\n"
+	"	cbnz	%w0, 1f\n"
+	"	stxr	%w0, %w2, [%1]\n"
+	"1:\n"
+	: "=&r" (tmp)
+	: "r" (&rw->lock), "r" (0x80000000)
+	: "memory");
+
+	return !tmp;
+}
+
+static inline void arch_write_unlock(arch_rwlock_t *rw)
+{
+	asm volatile(
+	"	stlr	%w1, [%0]\n"
+	: : "r" (&rw->lock), "r" (0) : "memory");
+}
+
+/* write_can_lock - would write_trylock() succeed? */
+#define arch_write_can_lock(x)		((x)->lock == 0)
+
+/*
+ * Read lock implementation.
+ *
+ * It exclusively loads the lock value, increments it and stores the new value
+ * back if positive and the CPU still exclusively owns the location. If the
+ * value is negative, the lock is already held.
+ *
+ * During unlocking there may be multiple active read locks but no write lock.
+ *
+ * The memory barriers are implicit with the load-acquire and store-release
+ * instructions.
+ */
+static inline void arch_read_lock(arch_rwlock_t *rw)
+{
+	unsigned int tmp, tmp2;
+
+	asm volatile(
+	"	sevl\n"
+	"1:	wfe\n"
+	"2:	ldaxr	%w0, [%2]\n"
+	"	add	%w0, %w0, #1\n"
+	"	tbnz	%w0, #31, 1b\n"
+	"	stxr	%w1, %w0, [%2]\n"
+	"	cbnz	%w1, 2b\n"
+	: "=&r" (tmp), "=&r" (tmp2)
+	: "r" (&rw->lock)
+	: "memory");
+}
+
+static inline void arch_read_unlock(arch_rwlock_t *rw)
+{
+	unsigned int tmp, tmp2;
+
+	asm volatile(
+	"1:	ldxr	%w0, [%2]\n"
+	"	sub	%w0, %w0, #1\n"
+	"	stlxr	%w1, %w0, [%2]\n"
+	"	cbnz	%w1, 1b\n"
+	: "=&r" (tmp), "=&r" (tmp2)
+	: "r" (&rw->lock)
+	: "memory");
+}
+
+static inline int arch_read_trylock(arch_rwlock_t *rw)
+{
+	unsigned int tmp, tmp2 = 1;
+
+	asm volatile(
+	"	ldaxr	%w0, [%2]\n"
+	"	add	%w0, %w0, #1\n"
+	"	tbnz	%w0, #31, 1f\n"
+	"	stxr	%w1, %w0, [%2]\n"
+	"1:\n"
+	: "=&r" (tmp), "+r" (tmp2)
+	: "r" (&rw->lock)
+	: "memory");
+
+	return !tmp2;
+}
+
+/* read_can_lock - would read_trylock() succeed? */
+#define arch_read_can_lock(x)		((x)->lock < 0x80000000)
+
+#define arch_read_lock_flags(lock, flags) arch_read_lock(lock)
+#define arch_write_lock_flags(lock, flags) arch_write_lock(lock)
+
+#define arch_spin_relax(lock)	cpu_relax()
+#define arch_read_relax(lock)	cpu_relax()
+#define arch_write_relax(lock)	cpu_relax()
+
+#endif /* __ASM_SPINLOCK_H */
diff --git a/arch/arm64/include/asm/spinlock_types.h b/arch/arm64/include/asm/spinlock_types.h
new file mode 100644
index 0000000..9a49434
--- /dev/null
+++ b/arch/arm64/include/asm/spinlock_types.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_SPINLOCK_TYPES_H
+#define __ASM_SPINLOCK_TYPES_H
+
+#if !defined(__LINUX_SPINLOCK_TYPES_H) && !defined(__ASM_SPINLOCK_H)
+# error "please don't include this file directly"
+#endif
+
+/* We only require natural alignment for exclusive accesses. */
+#define __lock_aligned
+
+typedef struct {
+	volatile unsigned int lock;
+} arch_spinlock_t;
+
+#define __ARCH_SPIN_LOCK_UNLOCKED	{ 0 }
+
+typedef struct {
+	volatile unsigned int lock;
+} arch_rwlock_t;
+
+#define __ARCH_RW_LOCK_UNLOCKED		{ 0 }
+
+#endif
diff --git a/arch/arm64/include/asm/stacktrace.h b/arch/arm64/include/asm/stacktrace.h
new file mode 100644
index 0000000..7318f6d
--- /dev/null
+++ b/arch/arm64/include/asm/stacktrace.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_STACKTRACE_H
+#define __ASM_STACKTRACE_H
+
+struct stackframe {
+	unsigned long fp;
+	unsigned long sp;
+	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/arm64/include/asm/stat.h b/arch/arm64/include/asm/stat.h
new file mode 100644
index 0000000..d87225c
--- /dev/null
+++ b/arch/arm64/include/asm/stat.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_STAT_H
+#define __ASM_STAT_H
+
+#include <asm-generic/stat.h>
+
+#if defined(__KERNEL__) && defined(CONFIG_COMPAT)
+
+#include <asm/compat.h>
+
+/*
+ * struct stat64 is needed for compat tasks only. Its definition is different
+ * from the generic struct stat64.
+ */
+struct stat64 {
+	compat_u64	st_dev;
+	unsigned char   __pad0[4];
+
+#define STAT64_HAS_BROKEN_ST_INO	1
+	compat_ulong_t	__st_ino;
+	compat_uint_t	st_mode;
+	compat_uint_t	st_nlink;
+
+	compat_ulong_t	st_uid;
+	compat_ulong_t	st_gid;
+
+	compat_u64	st_rdev;
+	unsigned char   __pad3[4];
+
+	compat_s64	st_size;
+	compat_ulong_t	st_blksize;
+	compat_u64	st_blocks;	/* Number of 512-byte blocks allocated. */
+
+	compat_ulong_t	st_atime;
+	compat_ulong_t	st_atime_nsec;
+
+	compat_ulong_t	st_mtime;
+	compat_ulong_t	st_mtime_nsec;
+
+	compat_ulong_t	st_ctime;
+	compat_ulong_t	st_ctime_nsec;
+
+	compat_u64	st_ino;
+};
+
+#endif
+
+#endif
diff --git a/arch/arm64/include/asm/statfs.h b/arch/arm64/include/asm/statfs.h
new file mode 100644
index 0000000..6f62190
--- /dev/null
+++ b/arch/arm64/include/asm/statfs.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_STATFS_H
+#define __ASM_STATFS_H
+
+#define ARCH_PACK_COMPAT_STATFS64 __attribute__((packed,aligned(4)))
+
+#include <asm-generic/statfs.h>
+
+#endif
diff --git a/arch/arm64/include/asm/syscall.h b/arch/arm64/include/asm/syscall.h
new file mode 100644
index 0000000..89c047f
--- /dev/null
+++ b/arch/arm64/include/asm/syscall.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_SYSCALL_H
+#define __ASM_SYSCALL_H
+
+#include <linux/err.h>
+
+
+static inline int syscall_get_nr(struct task_struct *task,
+				 struct pt_regs *regs)
+{
+	return regs->syscallno;
+}
+
+static inline void syscall_rollback(struct task_struct *task,
+				    struct pt_regs *regs)
+{
+	regs->regs[0] = regs->orig_x0;
+}
+
+
+static inline long syscall_get_error(struct task_struct *task,
+				     struct pt_regs *regs)
+{
+	unsigned long error = regs->regs[0];
+	return IS_ERR_VALUE(error) ? error : 0;
+}
+
+static inline long syscall_get_return_value(struct task_struct *task,
+					    struct pt_regs *regs)
+{
+	return regs->regs[0];
+}
+
+static inline void syscall_set_return_value(struct task_struct *task,
+					    struct pt_regs *regs,
+					    int error, long val)
+{
+	regs->regs[0] = (long) error ? error : val;
+}
+
+#define SYSCALL_MAX_ARGS 6
+
+static inline void syscall_get_arguments(struct task_struct *task,
+					 struct pt_regs *regs,
+					 unsigned int i, unsigned int n,
+					 unsigned long *args)
+{
+	if (i + n > SYSCALL_MAX_ARGS) {
+		unsigned long *args_bad = args + SYSCALL_MAX_ARGS - i;
+		unsigned int n_bad = n + i - SYSCALL_MAX_ARGS;
+		pr_warning("%s called with max args %d, handling only %d\n",
+			   __func__, i + n, SYSCALL_MAX_ARGS);
+		memset(args_bad, 0, n_bad * sizeof(args[0]));
+	}
+
+	if (i == 0) {
+		args[0] = regs->orig_x0;
+		args++;
+		i++;
+		n--;
+	}
+
+	memcpy(args, &regs->regs[i], n * sizeof(args[0]));
+}
+
+static inline void syscall_set_arguments(struct task_struct *task,
+					 struct pt_regs *regs,
+					 unsigned int i, unsigned int n,
+					 const unsigned long *args)
+{
+	if (i + n > SYSCALL_MAX_ARGS) {
+		pr_warning("%s called with max args %d, handling only %d\n",
+			   __func__, i + n, SYSCALL_MAX_ARGS);
+		n = SYSCALL_MAX_ARGS - i;
+	}
+
+	if (i == 0) {
+		regs->orig_x0 = args[0];
+		args++;
+		i++;
+		n--;
+	}
+
+	memcpy(&regs->regs[i], args, n * sizeof(args[0]));
+}
+
+#endif	/* __ASM_SYSCALL_H */
diff --git a/arch/arm64/include/asm/syscalls.h b/arch/arm64/include/asm/syscalls.h
new file mode 100644
index 0000000..09ff335
--- /dev/null
+++ b/arch/arm64/include/asm/syscalls.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_SYSCALLS_H
+#define __ASM_SYSCALLS_H
+
+#include <linux/linkage.h>
+#include <linux/compiler.h>
+#include <linux/signal.h>
+
+/*
+ * System call wrappers implemented in kernel/entry.S.
+ */
+asmlinkage long sys_execve_wrapper(const char __user *filename,
+				   const char __user *const __user *argv,
+				   const char __user *const __user *envp);
+asmlinkage long sys_clone_wrapper(unsigned long clone_flags,
+				  unsigned long newsp,
+				  void __user *parent_tid,
+				  unsigned long tls_val,
+				  void __user *child_tid);
+asmlinkage long sys_rt_sigreturn_wrapper(void);
+asmlinkage long sys_sigaltstack_wrapper(const stack_t __user *uss,
+					stack_t __user *uoss);
+
+#include <asm-generic/syscalls.h>
+
+#endif	/* __ASM_SYSCALLS_H */
diff --git a/arch/arm64/include/asm/system_misc.h b/arch/arm64/include/asm/system_misc.h
new file mode 100644
index 0000000..95e4072
--- /dev/null
+++ b/arch/arm64/include/asm/system_misc.h
@@ -0,0 +1,54 @@
+/*
+ * Based on arch/arm/include/asm/system_misc.h
+ *
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_SYSTEM_MISC_H
+#define __ASM_SYSTEM_MISC_H
+
+#ifndef __ASSEMBLY__
+
+#include <linux/compiler.h>
+#include <linux/linkage.h>
+#include <linux/irqflags.h>
+
+struct pt_regs;
+
+void die(const char *msg, struct pt_regs *regs, int err);
+
+struct siginfo;
+void arm64_notify_die(const char *str, struct pt_regs *regs,
+		      struct siginfo *info, int err);
+
+void hook_debug_fault_code(int nr, int (*fn)(unsigned long, unsigned int,
+					     struct pt_regs *),
+			   int sig, int code, const char *name);
+
+struct mm_struct;
+extern void show_pte(struct mm_struct *mm, unsigned long addr);
+extern void __show_regs(struct pt_regs *);
+
+void soft_restart(unsigned long);
+extern void (*pm_restart)(const char *cmd);
+
+#define UDBG_UNDEFINED	(1 << 0)
+#define UDBG_SYSCALL	(1 << 1)
+#define UDBG_BADABORT	(1 << 2)
+#define UDBG_SEGV	(1 << 3)
+#define UDBG_BUS	(1 << 4)
+
+#endif	/* __ASSEMBLY__ */
+
+#endif	/* __ASM_SYSTEM_MISC_H */
diff --git a/arch/arm64/include/asm/thread_info.h b/arch/arm64/include/asm/thread_info.h
new file mode 100644
index 0000000..3659e46
--- /dev/null
+++ b/arch/arm64/include/asm/thread_info.h
@@ -0,0 +1,127 @@
+/*
+ * Based on arch/arm/include/asm/thread_info.h
+ *
+ * Copyright (C) 2002 Russell King.
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_THREAD_INFO_H
+#define __ASM_THREAD_INFO_H
+
+#ifdef __KERNEL__
+
+#include <linux/compiler.h>
+
+#ifndef CONFIG_ARM64_64K_PAGES
+#define THREAD_SIZE_ORDER	1
+#endif
+
+#define THREAD_SIZE		8192
+#define THREAD_START_SP		(THREAD_SIZE - 16)
+
+#ifndef __ASSEMBLY__
+
+struct task_struct;
+struct exec_domain;
+
+#include <asm/types.h>
+
+typedef unsigned long mm_segment_t;
+
+/*
+ * low level task data that entry.S needs immediate access to.
+ * __switch_to() assumes cpu_context follows immediately after cpu_domain.
+ */
+struct thread_info {
+	unsigned long		flags;		/* low level flags */
+	mm_segment_t		addr_limit;	/* address limit */
+	struct task_struct	*task;		/* main task structure */
+	struct exec_domain	*exec_domain;	/* execution domain */
+	struct restart_block	restart_block;
+	int			preempt_count;	/* 0 => preemptable, <0 => bug */
+	int			cpu;		/* cpu */
+};
+
+#define INIT_THREAD_INFO(tsk)						\
+{									\
+	.task		= &tsk,						\
+	.exec_domain	= &default_exec_domain,				\
+	.flags		= 0,						\
+	.preempt_count	= INIT_PREEMPT_COUNT,				\
+	.addr_limit	= KERNEL_DS,					\
+	.restart_block	= {						\
+		.fn	= do_no_restart_syscall,			\
+	},								\
+}
+
+#define init_thread_info	(init_thread_union.thread_info)
+#define init_stack		(init_thread_union.stack)
+
+/*
+ * how to get the thread information struct from C
+ */
+static inline struct thread_info *current_thread_info(void) __attribute_const__;
+
+static inline struct thread_info *current_thread_info(void)
+{
+	register unsigned long sp asm ("sp");
+	return (struct thread_info *)(sp & ~(THREAD_SIZE - 1));
+}
+
+#define thread_saved_pc(tsk)	\
+	((unsigned long)(tsk->thread.cpu_context.pc))
+#define thread_saved_sp(tsk)	\
+	((unsigned long)(tsk->thread.cpu_context.sp))
+#define thread_saved_fp(tsk)	\
+	((unsigned long)(tsk->thread.cpu_context.fp))
+
+#endif
+
+/*
+ * We use bit 30 of the preempt_count to indicate that kernel
+ * preemption is occurring.  See <asm/hardirq.h>.
+ */
+#define PREEMPT_ACTIVE	0x40000000
+
+/*
+ * thread information flags:
+ *  TIF_SYSCALL_TRACE	- syscall trace active
+ *  TIF_SIGPENDING	- signal pending
+ *  TIF_NEED_RESCHED	- rescheduling necessary
+ *  TIF_NOTIFY_RESUME	- callback before returning to user
+ *  TIF_USEDFPU		- FPU was used by this task this quantum (SMP)
+ *  TIF_POLLING_NRFLAG	- true if poll_idle() is polling TIF_NEED_RESCHED
+ */
+#define TIF_SIGPENDING		0
+#define TIF_NEED_RESCHED	1
+#define TIF_NOTIFY_RESUME	2	/* callback before returning to user */
+#define TIF_SYSCALL_TRACE	8
+#define TIF_POLLING_NRFLAG	16
+#define TIF_MEMDIE		18	/* is terminating due to OOM killer */
+#define TIF_FREEZE		19
+#define TIF_RESTORE_SIGMASK	20
+#define TIF_SINGLESTEP		21
+#define TIF_32BIT		22	/* 32bit process */
+#define TIF_SWITCH_MM		23	/* deferred switch_mm */
+
+#define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
+#define _TIF_NEED_RESCHED	(1 << TIF_NEED_RESCHED)
+#define _TIF_NOTIFY_RESUME	(1 << TIF_NOTIFY_RESUME)
+#define _TIF_32BIT		(1 << TIF_32BIT)
+
+#define _TIF_WORK_MASK		(_TIF_NEED_RESCHED | _TIF_SIGPENDING | \
+				 _TIF_NOTIFY_RESUME)
+
+#endif /* __KERNEL__ */
+#endif /* __ASM_THREAD_INFO_H */
diff --git a/arch/arm64/include/asm/timex.h b/arch/arm64/include/asm/timex.h
new file mode 100644
index 0000000..b24a31a
--- /dev/null
+++ b/arch/arm64/include/asm/timex.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_TIMEX_H
+#define __ASM_TIMEX_H
+
+/*
+ * Use the current timer as a cycle counter since this is what we use for
+ * the delay loop.
+ */
+#define get_cycles()	({ cycles_t c; read_current_timer(&c); c; })
+
+#include <asm-generic/timex.h>
+
+#define ARCH_HAS_READ_CURRENT_TIMER
+
+#endif
diff --git a/arch/arm64/include/asm/tlb.h b/arch/arm64/include/asm/tlb.h
new file mode 100644
index 0000000..654f096
--- /dev/null
+++ b/arch/arm64/include/asm/tlb.h
@@ -0,0 +1,190 @@
+/*
+ * Based on arch/arm/include/asm/tlb.h
+ *
+ * Copyright (C) 2002 Russell King
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_TLB_H
+#define __ASM_TLB_H
+
+#include <linux/pagemap.h>
+#include <linux/swap.h>
+
+#include <asm/pgalloc.h>
+#include <asm/tlbflush.h>
+
+#define MMU_GATHER_BUNDLE	8
+
+/*
+ * TLB handling.  This allows us to remove pages from the page
+ * tables, and efficiently handle the TLB issues.
+ */
+struct mmu_gather {
+	struct mm_struct	*mm;
+	unsigned int		fullmm;
+	struct vm_area_struct	*vma;
+	unsigned long		range_start;
+	unsigned long		range_end;
+	unsigned int		nr;
+	unsigned int		max;
+	struct page		**pages;
+	struct page		*local[MMU_GATHER_BUNDLE];
+};
+
+/*
+ * This is unnecessarily complex.  There's three ways the TLB shootdown
+ * code is used:
+ *  1. Unmapping a range of vmas.  See zap_page_range(), unmap_region().
+ *     tlb->fullmm = 0, and tlb_start_vma/tlb_end_vma will be called.
+ *     tlb->vma will be non-NULL.
+ *  2. Unmapping all vmas.  See exit_mmap().
+ *     tlb->fullmm = 1, and tlb_start_vma/tlb_end_vma will be called.
+ *     tlb->vma will be non-NULL.  Additionally, page tables will be freed.
+ *  3. Unmapping argument pages.  See shift_arg_pages().
+ *     tlb->fullmm = 0, but tlb_start_vma/tlb_end_vma will not be called.
+ *     tlb->vma will be NULL.
+ */
+static inline void tlb_flush(struct mmu_gather *tlb)
+{
+	if (tlb->fullmm || !tlb->vma)
+		flush_tlb_mm(tlb->mm);
+	else if (tlb->range_end > 0) {
+		flush_tlb_range(tlb->vma, tlb->range_start, tlb->range_end);
+		tlb->range_start = TASK_SIZE;
+		tlb->range_end = 0;
+	}
+}
+
+static inline void tlb_add_flush(struct mmu_gather *tlb, unsigned long addr)
+{
+	if (!tlb->fullmm) {
+		if (addr < tlb->range_start)
+			tlb->range_start = addr;
+		if (addr + PAGE_SIZE > tlb->range_end)
+			tlb->range_end = addr + PAGE_SIZE;
+	}
+}
+
+static inline void __tlb_alloc_page(struct mmu_gather *tlb)
+{
+	unsigned long addr = __get_free_pages(GFP_NOWAIT | __GFP_NOWARN, 0);
+
+	if (addr) {
+		tlb->pages = (void *)addr;
+		tlb->max = PAGE_SIZE / sizeof(struct page *);
+	}
+}
+
+static inline void tlb_flush_mmu(struct mmu_gather *tlb)
+{
+	tlb_flush(tlb);
+	free_pages_and_swap_cache(tlb->pages, tlb->nr);
+	tlb->nr = 0;
+	if (tlb->pages == tlb->local)
+		__tlb_alloc_page(tlb);
+}
+
+static inline void
+tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned int fullmm)
+{
+	tlb->mm = mm;
+	tlb->fullmm = fullmm;
+	tlb->vma = NULL;
+	tlb->max = ARRAY_SIZE(tlb->local);
+	tlb->pages = tlb->local;
+	tlb->nr = 0;
+	__tlb_alloc_page(tlb);
+}
+
+static inline void
+tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end)
+{
+	tlb_flush_mmu(tlb);
+
+	/* keep the page table cache within bounds */
+	check_pgt_cache();
+
+	if (tlb->pages != tlb->local)
+		free_pages((unsigned long)tlb->pages, 0);
+}
+
+/*
+ * Memorize the range for the TLB flush.
+ */
+static inline void
+tlb_remove_tlb_entry(struct mmu_gather *tlb, pte_t *ptep, unsigned long addr)
+{
+	tlb_add_flush(tlb, addr);
+}
+
+/*
+ * In the case of tlb vma handling, we can optimise these away in the
+ * case where we're doing a full MM flush.  When we're doing a munmap,
+ * the vmas are adjusted to only cover the region to be torn down.
+ */
+static inline void
+tlb_start_vma(struct mmu_gather *tlb, struct vm_area_struct *vma)
+{
+	if (!tlb->fullmm) {
+		tlb->vma = vma;
+		tlb->range_start = TASK_SIZE;
+		tlb->range_end = 0;
+	}
+}
+
+static inline void
+tlb_end_vma(struct mmu_gather *tlb, struct vm_area_struct *vma)
+{
+	if (!tlb->fullmm)
+		tlb_flush(tlb);
+}
+
+static inline int __tlb_remove_page(struct mmu_gather *tlb, struct page *page)
+{
+	tlb->pages[tlb->nr++] = page;
+	VM_BUG_ON(tlb->nr > tlb->max);
+	return tlb->max - tlb->nr;
+}
+
+static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page)
+{
+	if (!__tlb_remove_page(tlb, page))
+		tlb_flush_mmu(tlb);
+}
+
+static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte,
+	unsigned long addr)
+{
+	pgtable_page_dtor(pte);
+	tlb_add_flush(tlb, addr);
+	tlb_remove_page(tlb, pte);
+}
+
+#ifndef CONFIG_ARM64_64K_PAGES
+static inline void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmdp,
+				  unsigned long addr)
+{
+	tlb_add_flush(tlb, addr);
+	tlb_remove_page(tlb, virt_to_page(pmdp));
+}
+#endif
+
+#define pte_free_tlb(tlb, ptep, addr)	__pte_free_tlb(tlb, ptep, addr)
+#define pmd_free_tlb(tlb, pmdp, addr)	__pmd_free_tlb(tlb, pmdp, addr)
+#define pud_free_tlb(tlb, pudp, addr)	pud_free((tlb)->mm, pudp)
+
+#define tlb_migrate_finish(mm)		do { } while (0)
+
+#endif
diff --git a/arch/arm64/include/asm/tlbflush.h b/arch/arm64/include/asm/tlbflush.h
new file mode 100644
index 0000000..122d632
--- /dev/null
+++ b/arch/arm64/include/asm/tlbflush.h
@@ -0,0 +1,122 @@
+/*
+ * Based on arch/arm/include/asm/tlbflush.h
+ *
+ * Copyright (C) 1999-2003 Russell King
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_TLBFLUSH_H
+#define __ASM_TLBFLUSH_H
+
+#ifndef __ASSEMBLY__
+
+#include <linux/sched.h>
+#include <asm/cputype.h>
+
+extern void __cpu_flush_user_tlb_range(unsigned long, unsigned long, struct vm_area_struct *);
+extern void __cpu_flush_kern_tlb_range(unsigned long, unsigned long);
+
+extern struct cpu_tlb_fns cpu_tlb;
+
+/*
+ *	TLB Management
+ *	==============
+ *
+ *	The arch/arm64/mm/tlb.S files implement these methods.
+ *
+ *	The TLB specific code is expected to perform whatever tests it needs
+ *	to determine if it should invalidate the TLB for each call.  Start
+ *	addresses are inclusive and end addresses are exclusive; it is safe to
+ *	round these addresses down.
+ *
+ *	flush_tlb_all()
+ *
+ *		Invalidate the entire TLB.
+ *
+ *	flush_tlb_mm(mm)
+ *
+ *		Invalidate all TLB entries in a particular address space.
+ *		- mm	- mm_struct describing address space
+ *
+ *	flush_tlb_range(mm,start,end)
+ *
+ *		Invalidate a range of TLB entries in the specified address
+ *		space.
+ *		- mm	- mm_struct describing address space
+ *		- start - start address (may not be aligned)
+ *		- end	- end address (exclusive, may not be aligned)
+ *
+ *	flush_tlb_page(vaddr,vma)
+ *
+ *		Invalidate the specified page in the specified address range.
+ *		- vaddr - virtual address (may not be aligned)
+ *		- vma	- vma_struct describing address range
+ *
+ *	flush_kern_tlb_page(kaddr)
+ *
+ *		Invalidate the TLB entry for the specified page.  The address
+ *		will be in the kernels virtual memory space.  Current uses
+ *		only require the D-TLB to be invalidated.
+ *		- kaddr - Kernel virtual memory address
+ */
+static inline void flush_tlb_all(void)
+{
+	dsb();
+	asm("tlbi	vmalle1is");
+	dsb();
+	isb();
+}
+
+static inline void flush_tlb_mm(struct mm_struct *mm)
+{
+	unsigned long asid = (unsigned long)ASID(mm) << 48;
+
+	dsb();
+	asm("tlbi	aside1is, %0" : : "r" (asid));
+	dsb();
+}
+
+static inline void flush_tlb_page(struct vm_area_struct *vma,
+				  unsigned long uaddr)
+{
+	unsigned long addr = uaddr >> 12 |
+		((unsigned long)ASID(vma->vm_mm) << 48);
+
+	dsb();
+	asm("tlbi	vae1is, %0" : : "r" (addr));
+	dsb();
+}
+
+/*
+ * Convert calls to our calling convention.
+ */
+#define flush_tlb_range(vma,start,end)	__cpu_flush_user_tlb_range(start,end,vma)
+#define flush_tlb_kernel_range(s,e)	__cpu_flush_kern_tlb_range(s,e)
+
+/*
+ * On AArch64, the cache coherency is handled via the set_pte_at() function.
+ */
+static inline void update_mmu_cache(struct vm_area_struct *vma,
+				    unsigned long addr, pte_t *ptep)
+{
+	/*
+	 * set_pte() does not have a DSB, so make sure that the page table
+	 * write is visible.
+	 */
+	dsb();
+}
+
+#endif
+
+#endif
diff --git a/arch/arm64/include/asm/traps.h b/arch/arm64/include/asm/traps.h
new file mode 100644
index 0000000..10ca8ff
--- /dev/null
+++ b/arch/arm64/include/asm/traps.h
@@ -0,0 +1,30 @@
+/*
+ * Based on arch/arm/include/asm/traps.h
+ *
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_TRAP_H
+#define __ASM_TRAP_H
+
+static inline int in_exception_text(unsigned long ptr)
+{
+	extern char __exception_text_start[];
+	extern char __exception_text_end[];
+
+	return ptr >= (unsigned long)&__exception_text_start &&
+	       ptr < (unsigned long)&__exception_text_end;
+}
+
+#endif
diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h
new file mode 100644
index 0000000..008f848
--- /dev/null
+++ b/arch/arm64/include/asm/uaccess.h
@@ -0,0 +1,297 @@
+/*
+ * Based on arch/arm/include/asm/uaccess.h
+ *
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_UACCESS_H
+#define __ASM_UACCESS_H
+
+/*
+ * User space memory access functions
+ */
+#include <linux/string.h>
+#include <linux/thread_info.h>
+
+#include <asm/ptrace.h>
+#include <asm/errno.h>
+#include <asm/memory.h>
+#include <asm/compiler.h>
+
+#define VERIFY_READ 0
+#define VERIFY_WRITE 1
+
+/*
+ * The exception table consists of pairs of addresses: the first is the
+ * address of an instruction that is allowed to fault, and the second is
+ * the address at which the program should continue.  No registers are
+ * modified, so it is entirely up to the continuation code to figure out
+ * what to do.
+ *
+ * All the routines below use bits of fixup code that are out of line
+ * with the main instruction path.  This means when everything is well,
+ * we don't even have to jump over them.  Further, they do not intrude
+ * on our cache or tlb entries.
+ */
+
+struct exception_table_entry
+{
+	unsigned long insn, fixup;
+};
+
+extern int fixup_exception(struct pt_regs *regs);
+
+#define KERNEL_DS	(-1UL)
+#define get_ds()	(KERNEL_DS)
+
+#define USER_DS		TASK_SIZE_64
+#define get_fs()	(current_thread_info()->addr_limit)
+
+static inline void set_fs(mm_segment_t fs)
+{
+	current_thread_info()->addr_limit = fs;
+}
+
+#define segment_eq(a,b)	((a) == (b))
+
+/*
+ * Return 1 if addr < current->addr_limit, 0 otherwise.
+ */
+#define __addr_ok(addr)							\
+({									\
+	unsigned long flag;						\
+	asm("cmp %1, %0; cset %0, lo"					\
+		: "=&r" (flag)						\
+		: "r" (addr), "0" (current_thread_info()->addr_limit)	\
+		: "cc");						\
+	flag;								\
+})
+
+/*
+ * Test whether a block of memory is a valid user space address.
+ * Returns 1 if the range is valid, 0 otherwise.
+ *
+ * This is equivalent to the following test:
+ * (u65)addr + (u65)size < (u65)current->addr_limit
+ *
+ * This needs 65-bit arithmetic.
+ */
+#define __range_ok(addr, size)						\
+({									\
+	unsigned long flag, roksum;					\
+	__chk_user_ptr(addr);						\
+	asm("adds %1, %1, %3; ccmp %1, %4, #2, cc; cset %0, cc"		\
+		: "=&r" (flag), "=&r" (roksum)				\
+		: "1" (addr), "Ir" (size),				\
+		  "r" (current_thread_info()->addr_limit)		\
+		: "cc");						\
+	flag;								\
+})
+
+#define access_ok(type, addr, size)	__range_ok(addr, size)
+
+/*
+ * The "__xxx" versions of the user access functions do not verify the address
+ * space - it must have been done previously with a separate "access_ok()"
+ * call.
+ *
+ * The "__xxx_error" versions set the third argument to -EFAULT if an error
+ * occurs, and leave it unchanged on success.
+ */
+#define __get_user_asm(instr, reg, x, addr, err)			\
+	asm volatile(							\
+	"1:	" instr "	" reg "1, [%2]\n"			\
+	"2:\n"								\
+	"	.section .fixup, \"ax\"\n"				\
+	"	.align	2\n"						\
+	"3:	mov	%w0, %3\n"					\
+	"	mov	%1, #0\n"					\
+	"	b	2b\n"						\
+	"	.previous\n"						\
+	"	.section __ex_table,\"a\"\n"				\
+	"	.align	3\n"						\
+	"	.quad	1b, 3b\n"					\
+	"	.previous"						\
+	: "+r" (err), "=&r" (x)						\
+	: "r" (addr), "i" (-EFAULT))
+
+#define __get_user_err(x, ptr, err)					\
+do {									\
+	unsigned long __gu_val;						\
+	__chk_user_ptr(ptr);						\
+	switch (sizeof(*(ptr))) {					\
+	case 1:								\
+		__get_user_asm("ldrb", "%w", __gu_val, (ptr), (err));	\
+		break;							\
+	case 2:								\
+		__get_user_asm("ldrh", "%w", __gu_val, (ptr), (err));	\
+		break;							\
+	case 4:								\
+		__get_user_asm("ldr", "%w", __gu_val, (ptr), (err));	\
+		break;							\
+	case 8:								\
+		__get_user_asm("ldr", "%",  __gu_val, (ptr), (err));	\
+		break;							\
+	default:							\
+		BUILD_BUG();						\
+	}								\
+	(x) = (__typeof__(*(ptr)))__gu_val;				\
+} while (0)
+
+#define __get_user(x, ptr)						\
+({									\
+	int __gu_err = 0;						\
+	__get_user_err((x), (ptr), __gu_err);				\
+	__gu_err;							\
+})
+
+#define __get_user_error(x, ptr, err)					\
+({									\
+	__get_user_err((x), (ptr), (err));				\
+	(void)0;							\
+})
+
+#define __get_user_unaligned __get_user
+
+#define get_user(x, ptr)						\
+({									\
+	might_sleep();							\
+	access_ok(VERIFY_READ, (ptr), sizeof(*(ptr))) ?			\
+		__get_user((x), (ptr)) :				\
+		((x) = 0, -EFAULT);					\
+})
+
+#define __put_user_asm(instr, reg, x, addr, err)			\
+	asm volatile(							\
+	"1:	" instr "	" reg "1, [%2]\n"			\
+	"2:\n"								\
+	"	.section .fixup,\"ax\"\n"				\
+	"	.align	2\n"						\
+	"3:	mov	%w0, %3\n"					\
+	"	b	2b\n"						\
+	"	.previous\n"						\
+	"	.section __ex_table,\"a\"\n"				\
+	"	.align	3\n"						\
+	"	.quad	1b, 3b\n"					\
+	"	.previous"						\
+	: "+r" (err)							\
+	: "r" (x), "r" (addr), "i" (-EFAULT))
+
+#define __put_user_err(x, ptr, err)					\
+do {									\
+	__typeof__(*(ptr)) __pu_val = (x);				\
+	__chk_user_ptr(ptr);						\
+	switch (sizeof(*(ptr))) {					\
+	case 1:								\
+		__put_user_asm("strb", "%w", __pu_val, (ptr), (err));	\
+		break;							\
+	case 2:								\
+		__put_user_asm("strh", "%w", __pu_val, (ptr), (err));	\
+		break;							\
+	case 4:								\
+		__put_user_asm("str",  "%w", __pu_val, (ptr), (err));	\
+		break;							\
+	case 8:								\
+		__put_user_asm("str",  "%", __pu_val, (ptr), (err));	\
+		break;							\
+	default:							\
+		BUILD_BUG();						\
+	}								\
+} while (0)
+
+#define __put_user(x, ptr)						\
+({									\
+	int __pu_err = 0;						\
+	__put_user_err((x), (ptr), __pu_err);				\
+	__pu_err;							\
+})
+
+#define __put_user_error(x, ptr, err)					\
+({									\
+	__put_user_err((x), (ptr), (err));				\
+	(void)0;							\
+})
+
+#define __put_user_unaligned __put_user
+
+#define put_user(x, ptr)						\
+({									\
+	might_sleep();							\
+	access_ok(VERIFY_WRITE, (ptr), sizeof(*(ptr))) ?		\
+		__put_user((x), (ptr)) :				\
+		-EFAULT;						\
+})
+
+extern unsigned long __must_check __copy_from_user(void *to, const void __user *from, unsigned long n);
+extern unsigned long __must_check __copy_to_user(void __user *to, const void *from, unsigned long n);
+extern unsigned long __must_check __copy_in_user(void __user *to, const void __user *from, unsigned long n);
+extern unsigned long __must_check __clear_user(void __user *addr, unsigned long n);
+
+extern unsigned long __must_check __strncpy_from_user(char *to, const char __user *from, unsigned long count);
+extern unsigned long __must_check __strnlen_user(const char __user *s, long n);
+
+static inline unsigned long __must_check copy_from_user(void *to, const void __user *from, unsigned long n)
+{
+	if (access_ok(VERIFY_READ, from, n))
+		n = __copy_from_user(to, from, n);
+	else /* security hole - plug it */
+		memset(to, 0, n);
+	return n;
+}
+
+static inline unsigned long __must_check copy_to_user(void __user *to, const void *from, unsigned long n)
+{
+	if (access_ok(VERIFY_WRITE, to, n))
+		n = __copy_to_user(to, from, n);
+	return n;
+}
+
+static inline unsigned long __must_check copy_in_user(void __user *to, const void __user *from, unsigned long n)
+{
+	if (access_ok(VERIFY_READ, from, n) && access_ok(VERIFY_WRITE, to, n))
+		n = __copy_in_user(to, from, n);
+	return n;
+}
+
+#define __copy_to_user_inatomic __copy_to_user
+#define __copy_from_user_inatomic __copy_from_user
+
+static inline unsigned long __must_check clear_user(void __user *to, unsigned long n)
+{
+	if (access_ok(VERIFY_WRITE, to, n))
+		n = __clear_user(to, n);
+	return n;
+}
+
+static inline long __must_check strncpy_from_user(char *dst, const char __user *src, long count)
+{
+	long res = -EFAULT;
+	if (access_ok(VERIFY_READ, src, 1))
+		res = __strncpy_from_user(dst, src, count);
+	return res;
+}
+
+#define strlen_user(s)	strnlen_user(s, ~0UL >> 1)
+
+static inline long __must_check strnlen_user(const char __user *s, long n)
+{
+	unsigned long res = 0;
+
+	if (__addr_ok(s))
+		res = __strnlen_user(s, n);
+
+	return res;
+}
+
+#endif /* __ASM_UACCESS_H */
diff --git a/arch/arm64/include/asm/ucontext.h b/arch/arm64/include/asm/ucontext.h
new file mode 100644
index 0000000..bde9607
--- /dev/null
+++ b/arch/arm64/include/asm/ucontext.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_UCONTEXT_H
+#define __ASM_UCONTEXT_H
+
+struct ucontext {
+	unsigned long	  uc_flags;
+	struct ucontext	 *uc_link;
+	stack_t		  uc_stack;
+	sigset_t	  uc_sigmask;
+	/* glibc uses a 1024-bit sigset_t */
+	__u8		  __unused[(1024 - sizeof(sigset_t)) / 8];
+	/* last for future expansion */
+	struct sigcontext uc_mcontext;
+};
+
+#endif /* __ASM_UCONTEXT_H */
diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h
new file mode 100644
index 0000000..fe18a68
--- /dev/null
+++ b/arch/arm64/include/asm/unistd.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#if !defined(__ASM_UNISTD_H) || defined(__SYSCALL)
+#define __ASM_UNISTD_H
+
+#ifndef __SYSCALL_COMPAT
+#include <asm-generic/unistd.h>
+#endif
+
+#if defined(__KERNEL__) && defined(CONFIG_COMPAT)
+#include <asm/unistd32.h>
+#endif
+
+#endif /* __ASM_UNISTD_H */
diff --git a/arch/arm64/include/asm/unistd32.h b/arch/arm64/include/asm/unistd32.h
new file mode 100644
index 0000000..a50405f
--- /dev/null
+++ b/arch/arm64/include/asm/unistd32.h
@@ -0,0 +1,758 @@
+/*
+ * Based on arch/arm/include/asm/unistd.h
+ *
+ * Copyright (C) 2001-2005 Russell King
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#if !defined(__ASM_UNISTD32_H) || defined(__SYSCALL)
+#define __ASM_UNISTD32_H
+
+#ifndef __SYSCALL
+#define __SYSCALL(x, y)
+#endif
+
+/*
+ * This file contains the system call numbers.
+ */
+
+#ifdef __SYSCALL_COMPAT
+
+#define __NR_restart_syscall		0
+__SYSCALL(__NR_restart_syscall, sys_restart_syscall)
+#define __NR_exit			1
+__SYSCALL(__NR_exit, sys_exit)
+#define __NR_fork			2
+__SYSCALL(__NR_fork, sys_fork)
+#define __NR_read			3
+__SYSCALL(__NR_read, sys_read)
+#define __NR_write			4
+__SYSCALL(__NR_write, sys_write)
+#define __NR_open			5
+__SYSCALL(__NR_open, sys_open)
+#define __NR_close			6
+__SYSCALL(__NR_close, sys_close)
+__SYSCALL(7, sys_ni_syscall)		/* 7 was sys_waitpid */
+#define __NR_creat			8
+__SYSCALL(__NR_creat, sys_creat)
+#define __NR_link			9
+__SYSCALL(__NR_link, sys_link)
+#define __NR_unlink			10
+__SYSCALL(__NR_unlink, sys_unlink)
+#define __NR_execve			11
+__SYSCALL(__NR_execve, sys_execve)
+#define __NR_chdir			12
+__SYSCALL(__NR_chdir, sys_chdir)
+__SYSCALL(13, sys_ni_syscall)		/* 13 was sys_time */
+#define __NR_mknod			14
+__SYSCALL(__NR_mknod, sys_mknod)
+#define __NR_chmod			15
+__SYSCALL(__NR_chmod, sys_chmod)
+#define __NR_lchown			16
+__SYSCALL(__NR_lchown, sys_lchown16)
+__SYSCALL(17, sys_ni_syscall)		/* 17 was sys_break */
+__SYSCALL(18, sys_ni_syscall)		/* 18 was sys_stat */
+#define __NR_lseek			19
+__SYSCALL(__NR_lseek, sys_lseek)
+#define __NR_getpid			20
+__SYSCALL(__NR_getpid, sys_getpid)
+#define __NR_mount			21
+__SYSCALL(__NR_mount, sys_mount)
+__SYSCALL(22, sys_ni_syscall)		/* 22 was sys_umount */
+#define __NR_setuid			23
+__SYSCALL(__NR_setuid, sys_setuid16)
+#define __NR_getuid			24
+__SYSCALL(__NR_getuid, sys_getuid16)
+__SYSCALL(25, sys_ni_syscall)		/* 25 was sys_stime */
+#define __NR_ptrace			26
+__SYSCALL(__NR_ptrace, sys_ptrace)
+__SYSCALL(27, sys_ni_syscall)		/* 27 was sys_alarm */
+__SYSCALL(28, sys_ni_syscall)		/* 28 was sys_fstat */
+#define __NR_pause			29
+__SYSCALL(__NR_pause, sys_pause)
+__SYSCALL(30, sys_ni_syscall)		/* 30 was sys_utime */
+__SYSCALL(31, sys_ni_syscall)		/* 31 was sys_stty */
+__SYSCALL(32, sys_ni_syscall)		/* 32 was sys_gtty */
+#define __NR_access			33
+__SYSCALL(__NR_access, sys_access)
+#define __NR_nice			34
+__SYSCALL(__NR_nice, sys_nice)
+__SYSCALL(35, sys_ni_syscall)		/* 35 was sys_ftime */
+#define __NR_sync			36
+__SYSCALL(__NR_sync, sys_sync)
+#define __NR_kill			37
+__SYSCALL(__NR_kill, sys_kill)
+#define __NR_rename			38
+__SYSCALL(__NR_rename, sys_rename)
+#define __NR_mkdir			39
+__SYSCALL(__NR_mkdir, sys_mkdir)
+#define __NR_rmdir			40
+__SYSCALL(__NR_rmdir, sys_rmdir)
+#define __NR_dup			41
+__SYSCALL(__NR_dup, sys_dup)
+#define __NR_pipe			42
+__SYSCALL(__NR_pipe, sys_pipe)
+#define __NR_times			43
+__SYSCALL(__NR_times, sys_times)
+__SYSCALL(44, sys_ni_syscall)		/* 44 was sys_prof */
+#define __NR_brk			45
+__SYSCALL(__NR_brk, sys_brk)
+#define __NR_setgid			46
+__SYSCALL(__NR_setgid, sys_setgid16)
+#define __NR_getgid			47
+__SYSCALL(__NR_getgid, sys_getgid16)
+__SYSCALL(48, sys_ni_syscall)		/* 48 was sys_signal */
+#define __NR_geteuid			49
+__SYSCALL(__NR_geteuid, sys_geteuid16)
+#define __NR_getegid			50
+__SYSCALL(__NR_getegid, sys_getegid16)
+#define __NR_acct			51
+__SYSCALL(__NR_acct, sys_acct)
+#define __NR_umount2			52
+__SYSCALL(__NR_umount2, sys_umount)
+__SYSCALL(53, sys_ni_syscall)		/* 53 was sys_lock */
+#define __NR_ioctl			54
+__SYSCALL(__NR_ioctl, sys_ioctl)
+#define __NR_fcntl			55
+__SYSCALL(__NR_fcntl, sys_fcntl)
+__SYSCALL(56, sys_ni_syscall)		/* 56 was sys_mpx */
+#define __NR_setpgid			57
+__SYSCALL(__NR_setpgid, sys_setpgid)
+__SYSCALL(58, sys_ni_syscall)		/* 58 was sys_ulimit */
+__SYSCALL(59, sys_ni_syscall)		/* 59 was sys_olduname */
+#define __NR_umask			60
+__SYSCALL(__NR_umask, sys_umask)
+#define __NR_chroot			61
+__SYSCALL(__NR_chroot, sys_chroot)
+#define __NR_ustat			62
+__SYSCALL(__NR_ustat, sys_ustat)
+#define __NR_dup2			63
+__SYSCALL(__NR_dup2, sys_dup2)
+#define __NR_getppid			64
+__SYSCALL(__NR_getppid, sys_getppid)
+#define __NR_getpgrp			65
+__SYSCALL(__NR_getpgrp, sys_getpgrp)
+#define __NR_setsid			66
+__SYSCALL(__NR_setsid, sys_setsid)
+#define __NR_sigaction			67
+__SYSCALL(__NR_sigaction, sys_sigaction)
+__SYSCALL(68, sys_ni_syscall)		/* 68 was sys_sgetmask */
+__SYSCALL(69, sys_ni_syscall)		/* 69 was sys_ssetmask */
+#define __NR_setreuid			70
+__SYSCALL(__NR_setreuid, sys_setreuid16)
+#define __NR_setregid			71
+__SYSCALL(__NR_setregid, sys_setregid16)
+#define __NR_sigsuspend			72
+__SYSCALL(__NR_sigsuspend, sys_sigsuspend)
+#define __NR_sigpending			73
+__SYSCALL(__NR_sigpending, sys_sigpending)
+#define __NR_sethostname		74
+__SYSCALL(__NR_sethostname, sys_sethostname)
+#define __NR_setrlimit			75
+__SYSCALL(__NR_setrlimit, sys_setrlimit)
+__SYSCALL(76, sys_ni_syscall)		/* 76 was sys_getrlimit */
+#define __NR_getrusage			77
+__SYSCALL(__NR_getrusage, sys_getrusage)
+#define __NR_gettimeofday		78
+__SYSCALL(__NR_gettimeofday, sys_gettimeofday)
+#define __NR_settimeofday		79
+__SYSCALL(__NR_settimeofday, sys_settimeofday)
+#define __NR_getgroups			80
+__SYSCALL(__NR_getgroups, sys_getgroups16)
+#define __NR_setgroups			81
+__SYSCALL(__NR_setgroups, sys_setgroups16)
+__SYSCALL(82, sys_ni_syscall)		/* 82 was sys_select */
+#define __NR_symlink			83
+__SYSCALL(__NR_symlink, sys_symlink)
+__SYSCALL(84, sys_ni_syscall)		/* 84 was sys_lstat */
+#define __NR_readlink			85
+__SYSCALL(__NR_readlink, sys_readlink)
+#define __NR_uselib			86
+__SYSCALL(__NR_uselib, sys_uselib)
+#define __NR_swapon			87
+__SYSCALL(__NR_swapon, sys_swapon)
+#define __NR_reboot			88
+__SYSCALL(__NR_reboot, sys_reboot)
+__SYSCALL(89, sys_ni_syscall)		/* 89 was sys_readdir */
+__SYSCALL(90, sys_ni_syscall)		/* 90 was sys_mmap */
+#define __NR_munmap			91
+__SYSCALL(__NR_munmap, sys_munmap)
+#define __NR_truncate			92
+__SYSCALL(__NR_truncate, sys_truncate)
+#define __NR_ftruncate			93
+__SYSCALL(__NR_ftruncate, sys_ftruncate)
+#define __NR_fchmod			94
+__SYSCALL(__NR_fchmod, sys_fchmod)
+#define __NR_fchown			95
+__SYSCALL(__NR_fchown, sys_fchown16)
+#define __NR_getpriority		96
+__SYSCALL(__NR_getpriority, sys_getpriority)
+#define __NR_setpriority		97
+__SYSCALL(__NR_setpriority, sys_setpriority)
+__SYSCALL(98, sys_ni_syscall)		/* 98 was sys_profil */
+#define __NR_statfs			99
+__SYSCALL(__NR_statfs, sys_statfs)
+#define __NR_fstatfs			100
+__SYSCALL(__NR_fstatfs, sys_fstatfs)
+__SYSCALL(101, sys_ni_syscall)		/* 101 was sys_ioperm */
+__SYSCALL(102, sys_ni_syscall)		/* 102 was sys_socketcall */
+#define __NR_syslog			103
+__SYSCALL(__NR_syslog, sys_syslog)
+#define __NR_setitimer			104
+__SYSCALL(__NR_setitimer, sys_setitimer)
+#define __NR_getitimer			105
+__SYSCALL(__NR_getitimer, sys_getitimer)
+#define __NR_stat			106
+__SYSCALL(__NR_stat, sys_newstat)
+#define __NR_lstat			107
+__SYSCALL(__NR_lstat, sys_newlstat)
+#define __NR_fstat			108
+__SYSCALL(__NR_fstat, sys_newfstat)
+__SYSCALL(109, sys_ni_syscall)		/* 109 was sys_uname */
+__SYSCALL(110, sys_ni_syscall)		/* 110 was sys_iopl */
+#define __NR_vhangup			111
+__SYSCALL(__NR_vhangup, sys_vhangup)
+__SYSCALL(112, sys_ni_syscall)		/* 112 was sys_idle */
+__SYSCALL(113, sys_ni_syscall)		/* 113 was sys_syscall */
+#define __NR_wait4			114
+__SYSCALL(__NR_wait4, sys_wait4)
+#define __NR_swapoff			115
+__SYSCALL(__NR_swapoff, sys_swapoff)
+#define __NR_sysinfo			116
+__SYSCALL(__NR_sysinfo, sys_sysinfo)
+__SYSCALL(117, sys_ni_syscall)		/* 117 was sys_ipc */
+#define __NR_fsync			118
+__SYSCALL(__NR_fsync, sys_fsync)
+#define __NR_sigreturn			119
+__SYSCALL(__NR_sigreturn, sys_sigreturn)
+#define __NR_clone			120
+__SYSCALL(__NR_clone, sys_clone)
+#define __NR_setdomainname		121
+__SYSCALL(__NR_setdomainname, sys_setdomainname)
+#define __NR_uname			122
+__SYSCALL(__NR_uname, sys_newuname)
+__SYSCALL(123, sys_ni_syscall)		/* 123 was sys_modify_ldt */
+#define __NR_adjtimex			124
+__SYSCALL(__NR_adjtimex, sys_adjtimex)
+#define __NR_mprotect			125
+__SYSCALL(__NR_mprotect, sys_mprotect)
+#define __NR_sigprocmask		126
+__SYSCALL(__NR_sigprocmask, sys_sigprocmask)
+__SYSCALL(127, sys_ni_syscall)		/* 127 was sys_create_module */
+#define __NR_init_module		128
+__SYSCALL(__NR_init_module, sys_init_module)
+#define __NR_delete_module		129
+__SYSCALL(__NR_delete_module, sys_delete_module)
+__SYSCALL(130, sys_ni_syscall)		/* 130 was sys_get_kernel_syms */
+#define __NR_quotactl			131
+__SYSCALL(__NR_quotactl, sys_quotactl)
+#define __NR_getpgid			132
+__SYSCALL(__NR_getpgid, sys_getpgid)
+#define __NR_fchdir			133
+__SYSCALL(__NR_fchdir, sys_fchdir)
+#define __NR_bdflush			134
+__SYSCALL(__NR_bdflush, sys_bdflush)
+#define __NR_sysfs			135
+__SYSCALL(__NR_sysfs, sys_sysfs)
+#define __NR_personality		136
+__SYSCALL(__NR_personality, sys_personality)
+__SYSCALL(137, sys_ni_syscall)		/* 137 was sys_afs_syscall */
+#define __NR_setfsuid			138
+__SYSCALL(__NR_setfsuid, sys_setfsuid16)
+#define __NR_setfsgid			139
+__SYSCALL(__NR_setfsgid, sys_setfsgid16)
+#define __NR__llseek			140
+__SYSCALL(__NR__llseek, sys_llseek)
+#define __NR_getdents			141
+__SYSCALL(__NR_getdents, sys_getdents)
+#define __NR__newselect			142
+__SYSCALL(__NR__newselect, sys_select)
+#define __NR_flock			143
+__SYSCALL(__NR_flock, sys_flock)
+#define __NR_msync			144
+__SYSCALL(__NR_msync, sys_msync)
+#define __NR_readv			145
+__SYSCALL(__NR_readv, sys_readv)
+#define __NR_writev			146
+__SYSCALL(__NR_writev, sys_writev)
+#define __NR_getsid			147
+__SYSCALL(__NR_getsid, sys_getsid)
+#define __NR_fdatasync			148
+__SYSCALL(__NR_fdatasync, sys_fdatasync)
+#define __NR__sysctl			149
+__SYSCALL(__NR__sysctl, sys_sysctl)
+#define __NR_mlock			150
+__SYSCALL(__NR_mlock, sys_mlock)
+#define __NR_munlock			151
+__SYSCALL(__NR_munlock, sys_munlock)
+#define __NR_mlockall			152
+__SYSCALL(__NR_mlockall, sys_mlockall)
+#define __NR_munlockall			153
+__SYSCALL(__NR_munlockall, sys_munlockall)
+#define __NR_sched_setparam		154
+__SYSCALL(__NR_sched_setparam, sys_sched_setparam)
+#define __NR_sched_getparam		155
+__SYSCALL(__NR_sched_getparam, sys_sched_getparam)
+#define __NR_sched_setscheduler		156
+__SYSCALL(__NR_sched_setscheduler, sys_sched_setscheduler)
+#define __NR_sched_getscheduler		157
+__SYSCALL(__NR_sched_getscheduler, sys_sched_getscheduler)
+#define __NR_sched_yield		158
+__SYSCALL(__NR_sched_yield, sys_sched_yield)
+#define __NR_sched_get_priority_max	159
+__SYSCALL(__NR_sched_get_priority_max, sys_sched_get_priority_max)
+#define __NR_sched_get_priority_min	160
+__SYSCALL(__NR_sched_get_priority_min, sys_sched_get_priority_min)
+#define __NR_sched_rr_get_interval	161
+__SYSCALL(__NR_sched_rr_get_interval, sys_sched_rr_get_interval)
+#define __NR_nanosleep			162
+__SYSCALL(__NR_nanosleep, sys_nanosleep)
+#define __NR_mremap			163
+__SYSCALL(__NR_mremap, sys_mremap)
+#define __NR_setresuid			164
+__SYSCALL(__NR_setresuid, sys_setresuid16)
+#define __NR_getresuid			165
+__SYSCALL(__NR_getresuid, sys_getresuid16)
+__SYSCALL(166, sys_ni_syscall)		/* 166 was sys_vm86 */
+__SYSCALL(167, sys_ni_syscall)		/* 167 was sys_query_module */
+#define __NR_poll			168
+__SYSCALL(__NR_poll, sys_poll)
+#define __NR_nfsservctl			169
+__SYSCALL(__NR_nfsservctl, sys_ni_syscall)
+#define __NR_setresgid			170
+__SYSCALL(__NR_setresgid, sys_setresgid16)
+#define __NR_getresgid			171
+__SYSCALL(__NR_getresgid, sys_getresgid16)
+#define __NR_prctl			172
+__SYSCALL(__NR_prctl, sys_prctl)
+#define __NR_rt_sigreturn		173
+__SYSCALL(__NR_rt_sigreturn, sys_rt_sigreturn)
+#define __NR_rt_sigaction		174
+__SYSCALL(__NR_rt_sigaction, sys_rt_sigaction)
+#define __NR_rt_sigprocmask		175
+__SYSCALL(__NR_rt_sigprocmask, sys_rt_sigprocmask)
+#define __NR_rt_sigpending		176
+__SYSCALL(__NR_rt_sigpending, sys_rt_sigpending)
+#define __NR_rt_sigtimedwait		177
+__SYSCALL(__NR_rt_sigtimedwait, sys_rt_sigtimedwait)
+#define __NR_rt_sigqueueinfo		178
+__SYSCALL(__NR_rt_sigqueueinfo, sys_rt_sigqueueinfo)
+#define __NR_rt_sigsuspend		179
+__SYSCALL(__NR_rt_sigsuspend, sys_rt_sigsuspend)
+#define __NR_pread64			180
+__SYSCALL(__NR_pread64, sys_pread64)
+#define __NR_pwrite64			181
+__SYSCALL(__NR_pwrite64, sys_pwrite64)
+#define __NR_chown			182
+__SYSCALL(__NR_chown, sys_chown16)
+#define __NR_getcwd			183
+__SYSCALL(__NR_getcwd, sys_getcwd)
+#define __NR_capget			184
+__SYSCALL(__NR_capget, sys_capget)
+#define __NR_capset			185
+__SYSCALL(__NR_capset, sys_capset)
+#define __NR_sigaltstack		186
+__SYSCALL(__NR_sigaltstack, sys_sigaltstack)
+#define __NR_sendfile			187
+__SYSCALL(__NR_sendfile, sys_sendfile)
+__SYSCALL(188, sys_ni_syscall)		/* 188 reserved */
+__SYSCALL(189, sys_ni_syscall)		/* 189 reserved */
+#define __NR_vfork			190
+__SYSCALL(__NR_vfork, sys_vfork)
+#define __NR_ugetrlimit			191	/* SuS compliant getrlimit */
+__SYSCALL(__NR_ugetrlimit, sys_getrlimit)
+#define __NR_mmap2			192
+__SYSCALL(__NR_mmap2, sys_mmap2)
+#define __NR_truncate64			193
+__SYSCALL(__NR_truncate64, sys_truncate64)
+#define __NR_ftruncate64		194
+__SYSCALL(__NR_ftruncate64, sys_ftruncate64)
+#define __NR_stat64			195
+__SYSCALL(__NR_stat64, sys_stat64)
+#define __NR_lstat64			196
+__SYSCALL(__NR_lstat64, sys_lstat64)
+#define __NR_fstat64			197
+__SYSCALL(__NR_fstat64, sys_fstat64)
+#define __NR_lchown32			198
+__SYSCALL(__NR_lchown32, sys_lchown)
+#define __NR_getuid32			199
+__SYSCALL(__NR_getuid32, sys_getuid)
+#define __NR_getgid32			200
+__SYSCALL(__NR_getgid32, sys_getgid)
+#define __NR_geteuid32			201
+__SYSCALL(__NR_geteuid32, sys_geteuid)
+#define __NR_getegid32			202
+__SYSCALL(__NR_getegid32, sys_getegid)
+#define __NR_setreuid32			203
+__SYSCALL(__NR_setreuid32, sys_setreuid)
+#define __NR_setregid32			204
+__SYSCALL(__NR_setregid32, sys_setregid)
+#define __NR_getgroups32		205
+__SYSCALL(__NR_getgroups32, sys_getgroups)
+#define __NR_setgroups32		206
+__SYSCALL(__NR_setgroups32, sys_setgroups)
+#define __NR_fchown32			207
+__SYSCALL(__NR_fchown32, sys_fchown)
+#define __NR_setresuid32		208
+__SYSCALL(__NR_setresuid32, sys_setresuid)
+#define __NR_getresuid32		209
+__SYSCALL(__NR_getresuid32, sys_getresuid)
+#define __NR_setresgid32		210
+__SYSCALL(__NR_setresgid32, sys_setresgid)
+#define __NR_getresgid32		211
+__SYSCALL(__NR_getresgid32, sys_getresgid)
+#define __NR_chown32			212
+__SYSCALL(__NR_chown32, sys_chown)
+#define __NR_setuid32			213
+__SYSCALL(__NR_setuid32, sys_setuid)
+#define __NR_setgid32			214
+__SYSCALL(__NR_setgid32, sys_setgid)
+#define __NR_setfsuid32			215
+__SYSCALL(__NR_setfsuid32, sys_setfsuid)
+#define __NR_setfsgid32			216
+__SYSCALL(__NR_setfsgid32, sys_setfsgid)
+#define __NR_getdents64			217
+__SYSCALL(__NR_getdents64, sys_getdents64)
+#define __NR_pivot_root			218
+__SYSCALL(__NR_pivot_root, sys_pivot_root)
+#define __NR_mincore			219
+__SYSCALL(__NR_mincore, sys_mincore)
+#define __NR_madvise			220
+__SYSCALL(__NR_madvise, sys_madvise)
+#define __NR_fcntl64			221
+__SYSCALL(__NR_fcntl64, sys_fcntl64)
+__SYSCALL(222, sys_ni_syscall)		/* 222 for tux */
+__SYSCALL(223, sys_ni_syscall)		/* 223 is unused */
+#define __NR_gettid			224
+__SYSCALL(__NR_gettid, sys_gettid)
+#define __NR_readahead			225
+__SYSCALL(__NR_readahead, sys_readahead)
+#define __NR_setxattr			226
+__SYSCALL(__NR_setxattr, sys_setxattr)
+#define __NR_lsetxattr			227
+__SYSCALL(__NR_lsetxattr, sys_lsetxattr)
+#define __NR_fsetxattr			228
+__SYSCALL(__NR_fsetxattr, sys_fsetxattr)
+#define __NR_getxattr			229
+__SYSCALL(__NR_getxattr, sys_getxattr)
+#define __NR_lgetxattr			230
+__SYSCALL(__NR_lgetxattr, sys_lgetxattr)
+#define __NR_fgetxattr			231
+__SYSCALL(__NR_fgetxattr, sys_fgetxattr)
+#define __NR_listxattr			232
+__SYSCALL(__NR_listxattr, sys_listxattr)
+#define __NR_llistxattr			233
+__SYSCALL(__NR_llistxattr, sys_llistxattr)
+#define __NR_flistxattr			234
+__SYSCALL(__NR_flistxattr, sys_flistxattr)
+#define __NR_removexattr		235
+__SYSCALL(__NR_removexattr, sys_removexattr)
+#define __NR_lremovexattr		236
+__SYSCALL(__NR_lremovexattr, sys_lremovexattr)
+#define __NR_fremovexattr		237
+__SYSCALL(__NR_fremovexattr, sys_fremovexattr)
+#define __NR_tkill			238
+__SYSCALL(__NR_tkill, sys_tkill)
+#define __NR_sendfile64			239
+__SYSCALL(__NR_sendfile64, sys_sendfile64)
+#define __NR_futex			240
+__SYSCALL(__NR_futex, sys_futex)
+#define __NR_sched_setaffinity		241
+__SYSCALL(__NR_sched_setaffinity, sys_sched_setaffinity)
+#define __NR_sched_getaffinity		242
+__SYSCALL(__NR_sched_getaffinity, sys_sched_getaffinity)
+#define __NR_io_setup			243
+__SYSCALL(__NR_io_setup, sys_io_setup)
+#define __NR_io_destroy			244
+__SYSCALL(__NR_io_destroy, sys_io_destroy)
+#define __NR_io_getevents		245
+__SYSCALL(__NR_io_getevents, sys_io_getevents)
+#define __NR_io_submit			246
+__SYSCALL(__NR_io_submit, sys_io_submit)
+#define __NR_io_cancel			247
+__SYSCALL(__NR_io_cancel, sys_io_cancel)
+#define __NR_exit_group			248
+__SYSCALL(__NR_exit_group, sys_exit_group)
+#define __NR_lookup_dcookie		249
+__SYSCALL(__NR_lookup_dcookie, sys_lookup_dcookie)
+#define __NR_epoll_create		250
+__SYSCALL(__NR_epoll_create, sys_epoll_create)
+#define __NR_epoll_ctl			251
+__SYSCALL(__NR_epoll_ctl, sys_epoll_ctl)
+#define __NR_epoll_wait			252
+__SYSCALL(__NR_epoll_wait, sys_epoll_wait)
+#define __NR_remap_file_pages		253
+__SYSCALL(__NR_remap_file_pages, sys_remap_file_pages)
+__SYSCALL(254, sys_ni_syscall)		/* 254 for set_thread_area */
+__SYSCALL(255, sys_ni_syscall)		/* 255 for get_thread_area */
+#define __NR_set_tid_address		256
+__SYSCALL(__NR_set_tid_address, sys_set_tid_address)
+#define __NR_timer_create		257
+__SYSCALL(__NR_timer_create, sys_timer_create)
+#define __NR_timer_settime		258
+__SYSCALL(__NR_timer_settime, sys_timer_settime)
+#define __NR_timer_gettime		259
+__SYSCALL(__NR_timer_gettime, sys_timer_gettime)
+#define __NR_timer_getoverrun		260
+__SYSCALL(__NR_timer_getoverrun, sys_timer_getoverrun)
+#define __NR_timer_delete		261
+__SYSCALL(__NR_timer_delete, sys_timer_delete)
+#define __NR_clock_settime		262
+__SYSCALL(__NR_clock_settime, sys_clock_settime)
+#define __NR_clock_gettime		263
+__SYSCALL(__NR_clock_gettime, sys_clock_gettime)
+#define __NR_clock_getres		264
+__SYSCALL(__NR_clock_getres, sys_clock_getres)
+#define __NR_clock_nanosleep		265
+__SYSCALL(__NR_clock_nanosleep, sys_clock_nanosleep)
+#define __NR_statfs64			266
+__SYSCALL(__NR_statfs64, sys_statfs64)
+#define __NR_fstatfs64			267
+__SYSCALL(__NR_fstatfs64, sys_fstatfs64)
+#define __NR_tgkill			268
+__SYSCALL(__NR_tgkill, sys_tgkill)
+#define __NR_utimes			269
+__SYSCALL(__NR_utimes, sys_utimes)
+#define __NR_fadvise64			270
+__SYSCALL(__NR_fadvise64, sys_fadvise64_64)
+#define __NR_pciconfig_iobase		271
+__SYSCALL(__NR_pciconfig_iobase, sys_pciconfig_iobase)
+#define __NR_pciconfig_read		272
+__SYSCALL(__NR_pciconfig_read, sys_pciconfig_read)
+#define __NR_pciconfig_write		273
+__SYSCALL(__NR_pciconfig_write, sys_pciconfig_write)
+#define __NR_mq_open			274
+__SYSCALL(__NR_mq_open, sys_mq_open)
+#define __NR_mq_unlink			275
+__SYSCALL(__NR_mq_unlink, sys_mq_unlink)
+#define __NR_mq_timedsend		276
+__SYSCALL(__NR_mq_timedsend, sys_mq_timedsend)
+#define __NR_mq_timedreceive		277
+__SYSCALL(__NR_mq_timedreceive, sys_mq_timedreceive)
+#define __NR_mq_notify			278
+__SYSCALL(__NR_mq_notify, sys_mq_notify)
+#define __NR_mq_getsetattr		279
+__SYSCALL(__NR_mq_getsetattr, sys_mq_getsetattr)
+#define __NR_waitid			280
+__SYSCALL(__NR_waitid, sys_waitid)
+#define __NR_socket			281
+__SYSCALL(__NR_socket, sys_socket)
+#define __NR_bind			282
+__SYSCALL(__NR_bind, sys_bind)
+#define __NR_connect			283
+__SYSCALL(__NR_connect, sys_connect)
+#define __NR_listen			284
+__SYSCALL(__NR_listen, sys_listen)
+#define __NR_accept			285
+__SYSCALL(__NR_accept, sys_accept)
+#define __NR_getsockname		286
+__SYSCALL(__NR_getsockname, sys_getsockname)
+#define __NR_getpeername		287
+__SYSCALL(__NR_getpeername, sys_getpeername)
+#define __NR_socketpair			288
+__SYSCALL(__NR_socketpair, sys_socketpair)
+#define __NR_send			289
+__SYSCALL(__NR_send, sys_send)
+#define __NR_sendto			290
+__SYSCALL(__NR_sendto, sys_sendto)
+#define __NR_recv			291
+__SYSCALL(__NR_recv, sys_recv)
+#define __NR_recvfrom			292
+__SYSCALL(__NR_recvfrom, sys_recvfrom)
+#define __NR_shutdown			293
+__SYSCALL(__NR_shutdown, sys_shutdown)
+#define __NR_setsockopt			294
+__SYSCALL(__NR_setsockopt, sys_setsockopt)
+#define __NR_getsockopt			295
+__SYSCALL(__NR_getsockopt, sys_getsockopt)
+#define __NR_sendmsg			296
+__SYSCALL(__NR_sendmsg, sys_sendmsg)
+#define __NR_recvmsg			297
+__SYSCALL(__NR_recvmsg, sys_recvmsg)
+#define __NR_semop			298
+__SYSCALL(__NR_semop, sys_semop)
+#define __NR_semget			299
+__SYSCALL(__NR_semget, sys_semget)
+#define __NR_semctl			300
+__SYSCALL(__NR_semctl, sys_semctl)
+#define __NR_msgsnd			301
+__SYSCALL(__NR_msgsnd, sys_msgsnd)
+#define __NR_msgrcv			302
+__SYSCALL(__NR_msgrcv, sys_msgrcv)
+#define __NR_msgget			303
+__SYSCALL(__NR_msgget, sys_msgget)
+#define __NR_msgctl			304
+__SYSCALL(__NR_msgctl, sys_msgctl)
+#define __NR_shmat			305
+__SYSCALL(__NR_shmat, sys_shmat)
+#define __NR_shmdt			306
+__SYSCALL(__NR_shmdt, sys_shmdt)
+#define __NR_shmget			307
+__SYSCALL(__NR_shmget, sys_shmget)
+#define __NR_shmctl			308
+__SYSCALL(__NR_shmctl, sys_shmctl)
+#define __NR_add_key			309
+__SYSCALL(__NR_add_key, sys_add_key)
+#define __NR_request_key		310
+__SYSCALL(__NR_request_key, sys_request_key)
+#define __NR_keyctl			311
+__SYSCALL(__NR_keyctl, sys_keyctl)
+#define __NR_semtimedop			312
+__SYSCALL(__NR_semtimedop, sys_semtimedop)
+#define __NR_vserver			313
+__SYSCALL(__NR_vserver, sys_ni_syscall)
+#define __NR_ioprio_set			314
+__SYSCALL(__NR_ioprio_set, sys_ioprio_set)
+#define __NR_ioprio_get			315
+__SYSCALL(__NR_ioprio_get, sys_ioprio_get)
+#define __NR_inotify_init		316
+__SYSCALL(__NR_inotify_init, sys_inotify_init)
+#define __NR_inotify_add_watch		317
+__SYSCALL(__NR_inotify_add_watch, sys_inotify_add_watch)
+#define __NR_inotify_rm_watch		318
+__SYSCALL(__NR_inotify_rm_watch, sys_inotify_rm_watch)
+#define __NR_mbind			319
+__SYSCALL(__NR_mbind, sys_mbind)
+#define __NR_get_mempolicy		320
+__SYSCALL(__NR_get_mempolicy, sys_get_mempolicy)
+#define __NR_set_mempolicy		321
+__SYSCALL(__NR_set_mempolicy, sys_set_mempolicy)
+#define __NR_openat			322
+__SYSCALL(__NR_openat, sys_openat)
+#define __NR_mkdirat			323
+__SYSCALL(__NR_mkdirat, sys_mkdirat)
+#define __NR_mknodat			324
+__SYSCALL(__NR_mknodat, sys_mknodat)
+#define __NR_fchownat			325
+__SYSCALL(__NR_fchownat, sys_fchownat)
+#define __NR_futimesat			326
+__SYSCALL(__NR_futimesat, sys_futimesat)
+#define __NR_fstatat64			327
+__SYSCALL(__NR_fstatat64, sys_fstatat64)
+#define __NR_unlinkat			328
+__SYSCALL(__NR_unlinkat, sys_unlinkat)
+#define __NR_renameat			329
+__SYSCALL(__NR_renameat, sys_renameat)
+#define __NR_linkat			330
+__SYSCALL(__NR_linkat, sys_linkat)
+#define __NR_symlinkat			331
+__SYSCALL(__NR_symlinkat, sys_symlinkat)
+#define __NR_readlinkat			332
+__SYSCALL(__NR_readlinkat, sys_readlinkat)
+#define __NR_fchmodat			333
+__SYSCALL(__NR_fchmodat, sys_fchmodat)
+#define __NR_faccessat			334
+__SYSCALL(__NR_faccessat, sys_faccessat)
+#define __NR_pselect6			335
+__SYSCALL(__NR_pselect6, sys_pselect6)
+#define __NR_ppoll			336
+__SYSCALL(__NR_ppoll, sys_ppoll)
+#define __NR_unshare			337
+__SYSCALL(__NR_unshare, sys_unshare)
+#define __NR_set_robust_list		338
+__SYSCALL(__NR_set_robust_list, sys_set_robust_list)
+#define __NR_get_robust_list		339
+__SYSCALL(__NR_get_robust_list, sys_get_robust_list)
+#define __NR_splice			340
+__SYSCALL(__NR_splice, sys_splice)
+#define __NR_sync_file_range2		341
+__SYSCALL(__NR_sync_file_range2, sys_sync_file_range2)
+#define __NR_tee			342
+__SYSCALL(__NR_tee, sys_tee)
+#define __NR_vmsplice			343
+__SYSCALL(__NR_vmsplice, sys_vmsplice)
+#define __NR_move_pages			344
+__SYSCALL(__NR_move_pages, sys_move_pages)
+#define __NR_getcpu			345
+__SYSCALL(__NR_getcpu, sys_getcpu)
+#define __NR_epoll_pwait		346
+__SYSCALL(__NR_epoll_pwait, sys_epoll_pwait)
+#define __NR_kexec_load			347
+__SYSCALL(__NR_kexec_load, sys_kexec_load)
+#define __NR_utimensat			348
+__SYSCALL(__NR_utimensat, sys_utimensat)
+#define __NR_signalfd			349
+__SYSCALL(__NR_signalfd, sys_signalfd)
+#define __NR_timerfd_create		350
+__SYSCALL(__NR_timerfd_create, sys_timerfd_create)
+#define __NR_eventfd			351
+__SYSCALL(__NR_eventfd, sys_eventfd)
+#define __NR_fallocate			352
+__SYSCALL(__NR_fallocate, sys_fallocate)
+#define __NR_timerfd_settime		353
+__SYSCALL(__NR_timerfd_settime, sys_timerfd_settime)
+#define __NR_timerfd_gettime		354
+__SYSCALL(__NR_timerfd_gettime, sys_timerfd_gettime)
+#define __NR_signalfd4			355
+__SYSCALL(__NR_signalfd4, sys_signalfd4)
+#define __NR_eventfd2			356
+__SYSCALL(__NR_eventfd2, sys_eventfd2)
+#define __NR_epoll_create1		357
+__SYSCALL(__NR_epoll_create1, sys_epoll_create1)
+#define __NR_dup3			358
+__SYSCALL(__NR_dup3, sys_dup3)
+#define __NR_pipe2			359
+__SYSCALL(__NR_pipe2, sys_pipe2)
+#define __NR_inotify_init1		360
+__SYSCALL(__NR_inotify_init1, sys_inotify_init1)
+#define __NR_preadv			361
+__SYSCALL(__NR_preadv, sys_preadv)
+#define __NR_pwritev			362
+__SYSCALL(__NR_pwritev, sys_pwritev)
+#define __NR_rt_tgsigqueueinfo		363
+__SYSCALL(__NR_rt_tgsigqueueinfo, sys_rt_tgsigqueueinfo)
+#define __NR_perf_event_open		364
+__SYSCALL(__NR_perf_event_open, sys_perf_event_open)
+#define __NR_recvmmsg			365
+__SYSCALL(__NR_recvmmsg, sys_recvmmsg)
+#define __NR_accept4			366
+__SYSCALL(__NR_accept4, sys_accept4)
+#define __NR_fanotify_init		367
+__SYSCALL(__NR_fanotify_init, sys_fanotify_init)
+#define __NR_fanotify_mark		368
+__SYSCALL(__NR_fanotify_mark, sys_fanotify_mark)
+#define __NR_prlimit64			369
+__SYSCALL(__NR_prlimit64, sys_prlimit64)
+#define __NR_name_to_handle_at		370
+__SYSCALL(__NR_name_to_handle_at, sys_name_to_handle_at)
+#define __NR_open_by_handle_at		371
+__SYSCALL(__NR_open_by_handle_at, sys_open_by_handle_at)
+#define __NR_clock_adjtime		372
+__SYSCALL(__NR_clock_adjtime, sys_clock_adjtime)
+#define __NR_syncfs			373
+__SYSCALL(__NR_syncfs, sys_syncfs)
+
+/*
+ * The following SVCs are ARM private.
+ */
+#define __ARM_NR_COMPAT_BASE		0x0f0000
+#define __ARM_NR_compat_cacheflush	(__ARM_NR_COMPAT_BASE+2)
+#define __ARM_NR_compat_set_tls		(__ARM_NR_COMPAT_BASE+5)
+
+#endif	/* __SYSCALL_COMPAT */
+
+#define __NR_compat_syscalls		374
+
+#define __ARCH_WANT_COMPAT_IPC_PARSE_VERSION
+#define __ARCH_WANT_COMPAT_STAT64
+#define __ARCH_WANT_SYS_GETHOSTNAME
+#define __ARCH_WANT_SYS_PAUSE
+#define __ARCH_WANT_SYS_GETPGRP
+#define __ARCH_WANT_SYS_LLSEEK
+#define __ARCH_WANT_SYS_NICE
+#define __ARCH_WANT_SYS_SIGPENDING
+#define __ARCH_WANT_SYS_SIGPROCMASK
+#define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
+
+#endif /* __ASM_UNISTD32_H */
diff --git a/arch/arm64/include/asm/vdso.h b/arch/arm64/include/asm/vdso.h
new file mode 100644
index 0000000..839ce00
--- /dev/null
+++ b/arch/arm64/include/asm/vdso.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2012 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, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_VDSO_H
+#define __ASM_VDSO_H
+
+#ifdef __KERNEL__
+
+/*
+ * Default link address for the vDSO.
+ * Since we randomise the VDSO mapping, there's little point in trying
+ * to prelink this.
+ */
+#define VDSO_LBASE	0x0
+
+#ifndef __ASSEMBLY__
+
+#include <generated/vdso-offsets.h>
+
+#define VDSO_SYMBOL(base, name)						   \
+({									   \
+	(void *)(vdso_offset_##name - VDSO_LBASE + (unsigned long)(base)); \
+})
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* __KERNEL__ */
+
+#endif /* __ASM_VDSO_H */
diff --git a/arch/arm64/include/asm/vdso_datapage.h b/arch/arm64/include/asm/vdso_datapage.h
new file mode 100644
index 0000000..de66199
--- /dev/null
+++ b/arch/arm64/include/asm/vdso_datapage.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2012 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, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_VDSO_DATAPAGE_H
+#define __ASM_VDSO_DATAPAGE_H
+
+#ifdef __KERNEL__
+
+#ifndef __ASSEMBLY__
+
+struct vdso_data {
+	__u64 cs_cycle_last;	/* Timebase at clocksource init */
+	__u64 xtime_clock_sec;	/* Kernel time */
+	__u64 xtime_clock_nsec;
+	__u64 xtime_coarse_sec;	/* Coarse time */
+	__u64 xtime_coarse_nsec;
+	__u64 wtm_clock_sec;	/* Wall to monotonic time */
+	__u64 wtm_clock_nsec;
+	__u32 tb_seq_count;	/* Timebase sequence counter */
+	__u32 cs_mult;		/* Clocksource multiplier */
+	__u32 cs_shift;		/* Clocksource shift */
+	__u32 tz_minuteswest;	/* Whacky timezone stuff */
+	__u32 tz_dsttime;
+	__u32 use_syscall;
+};
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* __KERNEL__ */
+
+#endif /* __ASM_VDSO_DATAPAGE_H */
diff --git a/arch/arm64/kernel/.gitignore b/arch/arm64/kernel/.gitignore
new file mode 100644
index 0000000..c5f676c
--- /dev/null
+++ b/arch/arm64/kernel/.gitignore
@@ -0,0 +1 @@
+vmlinux.lds
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
new file mode 100644
index 0000000..e2caff1
--- /dev/null
+++ b/arch/arm64/kernel/Makefile
@@ -0,0 +1,27 @@
+#
+# Makefile for the linux kernel.
+#
+
+CPPFLAGS_vmlinux.lds	:= -DTEXT_OFFSET=$(TEXT_OFFSET)
+AFLAGS_head.o		:= -DTEXT_OFFSET=$(TEXT_OFFSET)
+
+# Object file lists.
+arm64-obj-y		:= cputable.o debug-monitors.o entry.o irq.o fpsimd.o	\
+			   entry-fpsimd.o process.o ptrace.o setup.o signal.o	\
+			   sys.o stacktrace.o time.o traps.o io.o vdso.o
+
+arm64-obj-$(CONFIG_COMPAT)		+= sys32.o kuser32.o signal32.o 	\
+					   sys_compat.o
+arm64-obj-$(CONFIG_MODULES)		+= arm64ksyms.o module.o
+arm64-obj-$(CONFIG_SMP)			+= smp.o
+arm64-obj-$(CONFIG_HW_PERF_EVENTS)	+= perf_event.o
+arm64-obj-$(CONFIG_HAVE_HW_BREAKPOINT)+= hw_breakpoint.o
+
+obj-y					+= $(arm64-obj-y) vdso/
+obj-m					+= $(arm64-obj-m)
+head-y					:= head.o
+extra-y					:= $(head-y) vmlinux.lds
+
+# vDSO - this must be built first to generate the symbol offsets
+$(call objectify,$(arm64-obj-y)): $(obj)/vdso/vdso-offsets.h
+$(obj)/vdso/vdso-offsets.h: $(obj)/vdso
diff --git a/arch/arm64/kernel/arm64ksyms.c b/arch/arm64/kernel/arm64ksyms.c
new file mode 100644
index 0000000..cef3925
--- /dev/null
+++ b/arch/arm64/kernel/arm64ksyms.c
@@ -0,0 +1,46 @@
+/*
+ * Based on arch/arm/kernel/armksyms.c
+ *
+ * Copyright (C) 2000 Russell King
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/export.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/cryptohash.h>
+#include <linux/delay.h>
+#include <linux/in6.h>
+#include <linux/syscalls.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+
+#include <asm/checksum.h>
+
+	/* user mem (segment) */
+EXPORT_SYMBOL(__strnlen_user);
+EXPORT_SYMBOL(__strncpy_from_user);
+
+EXPORT_SYMBOL(copy_page);
+
+EXPORT_SYMBOL(__copy_from_user);
+EXPORT_SYMBOL(__copy_to_user);
+EXPORT_SYMBOL(__clear_user);
+
+	/* bitops */
+EXPORT_SYMBOL(__atomic_hash);
+
+	/* physical memory */
+EXPORT_SYMBOL(memstart_addr);
diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c
new file mode 100644
index 0000000..a2a4d81
--- /dev/null
+++ b/arch/arm64/kernel/asm-offsets.c
@@ -0,0 +1,108 @@
+/*
+ * Based on arch/arm/kernel/asm-offsets.c
+ *
+ * Copyright (C) 1995-2003 Russell King
+ *               2001-2002 Keith Owens
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/dma-mapping.h>
+#include <asm/thread_info.h>
+#include <asm/memory.h>
+#include <asm/cputable.h>
+#include <asm/vdso_datapage.h>
+#include <linux/kbuild.h>
+
+int main(void)
+{
+  DEFINE(TSK_ACTIVE_MM,		offsetof(struct task_struct, active_mm));
+  BLANK();
+  DEFINE(TI_FLAGS,		offsetof(struct thread_info, flags));
+  DEFINE(TI_PREEMPT,		offsetof(struct thread_info, preempt_count));
+  DEFINE(TI_ADDR_LIMIT,		offsetof(struct thread_info, addr_limit));
+  DEFINE(TI_TASK,		offsetof(struct thread_info, task));
+  DEFINE(TI_EXEC_DOMAIN,	offsetof(struct thread_info, exec_domain));
+  DEFINE(TI_CPU,		offsetof(struct thread_info, cpu));
+  BLANK();
+  DEFINE(THREAD_CPU_CONTEXT,	offsetof(struct task_struct, thread.cpu_context));
+  BLANK();
+  DEFINE(S_X0,			offsetof(struct pt_regs, regs[0]));
+  DEFINE(S_X1,			offsetof(struct pt_regs, regs[1]));
+  DEFINE(S_X2,			offsetof(struct pt_regs, regs[2]));
+  DEFINE(S_X3,			offsetof(struct pt_regs, regs[3]));
+  DEFINE(S_X4,			offsetof(struct pt_regs, regs[4]));
+  DEFINE(S_X5,			offsetof(struct pt_regs, regs[5]));
+  DEFINE(S_X6,			offsetof(struct pt_regs, regs[6]));
+  DEFINE(S_X7,			offsetof(struct pt_regs, regs[7]));
+  DEFINE(S_LR,			offsetof(struct pt_regs, regs[30]));
+  DEFINE(S_SP,			offsetof(struct pt_regs, sp));
+#ifdef CONFIG_COMPAT
+  DEFINE(S_COMPAT_SP,		offsetof(struct pt_regs, compat_sp));
+#endif
+  DEFINE(S_PSTATE,		offsetof(struct pt_regs, pstate));
+  DEFINE(S_PC,			offsetof(struct pt_regs, pc));
+  DEFINE(S_ORIG_X0,		offsetof(struct pt_regs, orig_x0));
+  DEFINE(S_SYSCALLNO,		offsetof(struct pt_regs, syscallno));
+  DEFINE(S_FRAME_SIZE,		sizeof(struct pt_regs));
+  BLANK();
+  DEFINE(MM_CONTEXT_ID,		offsetof(struct mm_struct, context.id));
+  BLANK();
+  DEFINE(VMA_VM_MM,		offsetof(struct vm_area_struct, vm_mm));
+  DEFINE(VMA_VM_FLAGS,		offsetof(struct vm_area_struct, vm_flags));
+  BLANK();
+  DEFINE(VM_EXEC,	       	VM_EXEC);
+  BLANK();
+  DEFINE(PAGE_SZ,	       	PAGE_SIZE);
+  BLANK();
+  DEFINE(CPU_INFO_SZ,		sizeof(struct cpu_info));
+  DEFINE(CPU_INFO_SETUP,	offsetof(struct cpu_info, cpu_setup));
+  BLANK();
+  DEFINE(DMA_BIDIRECTIONAL,	DMA_BIDIRECTIONAL);
+  DEFINE(DMA_TO_DEVICE,		DMA_TO_DEVICE);
+  DEFINE(DMA_FROM_DEVICE,	DMA_FROM_DEVICE);
+  BLANK();
+  DEFINE(CLOCK_REALTIME,	CLOCK_REALTIME);
+  DEFINE(CLOCK_MONOTONIC,	CLOCK_MONOTONIC);
+  DEFINE(CLOCK_REALTIME_RES,	MONOTONIC_RES_NSEC);
+  DEFINE(CLOCK_REALTIME_COARSE,	CLOCK_REALTIME_COARSE);
+  DEFINE(CLOCK_MONOTONIC_COARSE,CLOCK_MONOTONIC_COARSE);
+  DEFINE(CLOCK_COARSE_RES,	LOW_RES_NSEC);
+  DEFINE(NSEC_PER_SEC,		NSEC_PER_SEC);
+  BLANK();
+  DEFINE(VDSO_CS_CYCLE_LAST,	offsetof(struct vdso_data, cs_cycle_last));
+  DEFINE(VDSO_XTIME_CLK_SEC,	offsetof(struct vdso_data, xtime_clock_sec));
+  DEFINE(VDSO_XTIME_CLK_NSEC,	offsetof(struct vdso_data, xtime_clock_nsec));
+  DEFINE(VDSO_XTIME_CRS_SEC,	offsetof(struct vdso_data, xtime_coarse_sec));
+  DEFINE(VDSO_XTIME_CRS_NSEC,	offsetof(struct vdso_data, xtime_coarse_nsec));
+  DEFINE(VDSO_WTM_CLK_SEC,	offsetof(struct vdso_data, wtm_clock_sec));
+  DEFINE(VDSO_WTM_CLK_NSEC,	offsetof(struct vdso_data, wtm_clock_nsec));
+  DEFINE(VDSO_TB_SEQ_COUNT,	offsetof(struct vdso_data, tb_seq_count));
+  DEFINE(VDSO_CS_MULT,		offsetof(struct vdso_data, cs_mult));
+  DEFINE(VDSO_CS_SHIFT,		offsetof(struct vdso_data, cs_shift));
+  DEFINE(VDSO_TZ_MINWEST,	offsetof(struct vdso_data, tz_minuteswest));
+  DEFINE(VDSO_TZ_DSTTIME,	offsetof(struct vdso_data, tz_dsttime));
+  DEFINE(VDSO_USE_SYSCALL,	offsetof(struct vdso_data, use_syscall));
+  BLANK();
+  DEFINE(TVAL_TV_SEC,		offsetof(struct timeval, tv_sec));
+  DEFINE(TVAL_TV_USEC,		offsetof(struct timeval, tv_usec));
+  DEFINE(TSPEC_TV_SEC,		offsetof(struct timespec, tv_sec));
+  DEFINE(TSPEC_TV_NSEC,		offsetof(struct timespec, tv_nsec));
+  BLANK();
+  DEFINE(TZ_MINWEST,		offsetof(struct timezone, tz_minuteswest));
+  DEFINE(TZ_DSTTIME,		offsetof(struct timezone, tz_dsttime));
+  return 0;
+}
diff --git a/arch/arm64/kernel/cputable.c b/arch/arm64/kernel/cputable.c
new file mode 100644
index 0000000..63cfc4a
--- /dev/null
+++ b/arch/arm64/kernel/cputable.c
@@ -0,0 +1,33 @@
+/*
+ * arch/arm64/kernel/cputable.c
+ *
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/init.h>
+
+#include <asm/cputable.h>
+
+extern unsigned long __cpu_setup(void);
+
+struct cpu_info __initdata cpu_table[] = {
+	{
+		.cpu_id_val	= 0x000f0000,
+		.cpu_id_mask	= 0x000f0000,
+		.cpu_name	= "AArch64 Processor",
+		.cpu_setup	= __cpu_setup,
+	},
+	{ /* Empty */ },
+};
diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c
new file mode 100644
index 0000000..0c3ba9f
--- /dev/null
+++ b/arch/arm64/kernel/debug-monitors.c
@@ -0,0 +1,288 @@
+/*
+ * ARMv8 single-step debug support and mdscr context switching.
+ *
+ * Copyright (C) 2012 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Will Deacon <will.deacon@arm.com>
+ */
+
+#include <linux/cpu.h>
+#include <linux/debugfs.h>
+#include <linux/hardirq.h>
+#include <linux/init.h>
+#include <linux/ptrace.h>
+#include <linux/stat.h>
+
+#include <asm/debug-monitors.h>
+#include <asm/local.h>
+#include <asm/cputype.h>
+#include <asm/system_misc.h>
+
+/* Low-level stepping controls. */
+#define DBG_MDSCR_SS		(1 << 0)
+#define DBG_SPSR_SS		(1 << 21)
+
+/* MDSCR_EL1 enabling bits */
+#define DBG_MDSCR_KDE		(1 << 13)
+#define DBG_MDSCR_MDE		(1 << 15)
+#define DBG_MDSCR_MASK		~(DBG_MDSCR_KDE | DBG_MDSCR_MDE)
+
+/* Determine debug architecture. */
+u8 debug_monitors_arch(void)
+{
+	return read_cpuid(ID_AA64DFR0_EL1) & 0xf;
+}
+
+/*
+ * MDSCR access routines.
+ */
+static void mdscr_write(u32 mdscr)
+{
+	unsigned long flags;
+	local_dbg_save(flags);
+	asm volatile("msr mdscr_el1, %0" :: "r" (mdscr));
+	local_dbg_restore(flags);
+}
+
+static u32 mdscr_read(void)
+{
+	u32 mdscr;
+	asm volatile("mrs %0, mdscr_el1" : "=r" (mdscr));
+	return mdscr;
+}
+
+/*
+ * Allow root to disable self-hosted debug from userspace.
+ * This is useful if you want to connect an external JTAG debugger.
+ */
+static u32 debug_enabled = 1;
+
+static int create_debug_debugfs_entry(void)
+{
+	debugfs_create_bool("debug_enabled", 0644, NULL, &debug_enabled);
+	return 0;
+}
+fs_initcall(create_debug_debugfs_entry);
+
+static int __init early_debug_disable(char *buf)
+{
+	debug_enabled = 0;
+	return 0;
+}
+
+early_param("nodebugmon", early_debug_disable);
+
+/*
+ * Keep track of debug users on each core.
+ * The ref counts are per-cpu so we use a local_t type.
+ */
+static DEFINE_PER_CPU(local_t, mde_ref_count);
+static DEFINE_PER_CPU(local_t, kde_ref_count);
+
+void enable_debug_monitors(enum debug_el el)
+{
+	u32 mdscr, enable = 0;
+
+	WARN_ON(preemptible());
+
+	if (local_inc_return(&__get_cpu_var(mde_ref_count)) == 1)
+		enable = DBG_MDSCR_MDE;
+
+	if (el == DBG_ACTIVE_EL1 &&
+	    local_inc_return(&__get_cpu_var(kde_ref_count)) == 1)
+		enable |= DBG_MDSCR_KDE;
+
+	if (enable && debug_enabled) {
+		mdscr = mdscr_read();
+		mdscr |= enable;
+		mdscr_write(mdscr);
+	}
+}
+
+void disable_debug_monitors(enum debug_el el)
+{
+	u32 mdscr, disable = 0;
+
+	WARN_ON(preemptible());
+
+	if (local_dec_and_test(&__get_cpu_var(mde_ref_count)))
+		disable = ~DBG_MDSCR_MDE;
+
+	if (el == DBG_ACTIVE_EL1 &&
+	    local_dec_and_test(&__get_cpu_var(kde_ref_count)))
+		disable &= ~DBG_MDSCR_KDE;
+
+	if (disable) {
+		mdscr = mdscr_read();
+		mdscr &= disable;
+		mdscr_write(mdscr);
+	}
+}
+
+/*
+ * OS lock clearing.
+ */
+static void clear_os_lock(void *unused)
+{
+	asm volatile("msr mdscr_el1, %0" : : "r" (0));
+	isb();
+	asm volatile("msr oslar_el1, %0" : : "r" (0));
+	isb();
+}
+
+static int __cpuinit os_lock_notify(struct notifier_block *self,
+				    unsigned long action, void *data)
+{
+	int cpu = (unsigned long)data;
+	if (action == CPU_ONLINE)
+		smp_call_function_single(cpu, clear_os_lock, NULL, 1);
+	return NOTIFY_OK;
+}
+
+static struct notifier_block __cpuinitdata os_lock_nb = {
+	.notifier_call = os_lock_notify,
+};
+
+static int __cpuinit debug_monitors_init(void)
+{
+	/* Clear the OS lock. */
+	smp_call_function(clear_os_lock, NULL, 1);
+	clear_os_lock(NULL);
+
+	/* Register hotplug handler. */
+	register_cpu_notifier(&os_lock_nb);
+	return 0;
+}
+postcore_initcall(debug_monitors_init);
+
+/*
+ * Single step API and exception handling.
+ */
+static void set_regs_spsr_ss(struct pt_regs *regs)
+{
+	unsigned long spsr;
+
+	spsr = regs->pstate;
+	spsr &= ~DBG_SPSR_SS;
+	spsr |= DBG_SPSR_SS;
+	regs->pstate = spsr;
+}
+
+static void clear_regs_spsr_ss(struct pt_regs *regs)
+{
+	unsigned long spsr;
+
+	spsr = regs->pstate;
+	spsr &= ~DBG_SPSR_SS;
+	regs->pstate = spsr;
+}
+
+static int single_step_handler(unsigned long addr, unsigned int esr,
+			       struct pt_regs *regs)
+{
+	siginfo_t info;
+
+	/*
+	 * If we are stepping a pending breakpoint, call the hw_breakpoint
+	 * handler first.
+	 */
+	if (!reinstall_suspended_bps(regs))
+		return 0;
+
+	if (user_mode(regs)) {
+		info.si_signo = SIGTRAP;
+		info.si_errno = 0;
+		info.si_code  = TRAP_HWBKPT;
+		info.si_addr  = (void __user *)instruction_pointer(regs);
+		force_sig_info(SIGTRAP, &info, current);
+
+		/*
+		 * ptrace will disable single step unless explicitly
+		 * asked to re-enable it. For other clients, it makes
+		 * sense to leave it enabled (i.e. rewind the controls
+		 * to the active-not-pending state).
+		 */
+		user_rewind_single_step(current);
+	} else {
+		/* TODO: route to KGDB */
+		pr_warning("Unexpected kernel single-step exception at EL1\n");
+		/*
+		 * Re-enable stepping since we know that we will be
+		 * returning to regs.
+		 */
+		set_regs_spsr_ss(regs);
+	}
+
+	return 0;
+}
+
+static int __init single_step_init(void)
+{
+	hook_debug_fault_code(DBG_ESR_EVT_HWSS, single_step_handler, SIGTRAP,
+			      TRAP_HWBKPT, "single-step handler");
+	return 0;
+}
+arch_initcall(single_step_init);
+
+/* Re-enable single step for syscall restarting. */
+void user_rewind_single_step(struct task_struct *task)
+{
+	/*
+	 * If single step is active for this thread, then set SPSR.SS
+	 * to 1 to avoid returning to the active-pending state.
+	 */
+	if (test_ti_thread_flag(task_thread_info(task), TIF_SINGLESTEP))
+		set_regs_spsr_ss(task_pt_regs(task));
+}
+
+void user_fastforward_single_step(struct task_struct *task)
+{
+	if (test_ti_thread_flag(task_thread_info(task), TIF_SINGLESTEP))
+		clear_regs_spsr_ss(task_pt_regs(task));
+}
+
+/* Kernel API */
+void kernel_enable_single_step(struct pt_regs *regs)
+{
+	WARN_ON(!irqs_disabled());
+	set_regs_spsr_ss(regs);
+	mdscr_write(mdscr_read() | DBG_MDSCR_SS);
+	enable_debug_monitors(DBG_ACTIVE_EL1);
+}
+
+void kernel_disable_single_step(void)
+{
+	WARN_ON(!irqs_disabled());
+	mdscr_write(mdscr_read() & ~DBG_MDSCR_SS);
+	disable_debug_monitors(DBG_ACTIVE_EL1);
+}
+
+int kernel_active_single_step(void)
+{
+	WARN_ON(!irqs_disabled());
+	return mdscr_read() & DBG_MDSCR_SS;
+}
+
+/* ptrace API */
+void user_enable_single_step(struct task_struct *task)
+{
+	set_ti_thread_flag(task_thread_info(task), TIF_SINGLESTEP);
+	set_regs_spsr_ss(task_pt_regs(task));
+}
+
+void user_disable_single_step(struct task_struct *task)
+{
+	clear_ti_thread_flag(task_thread_info(task), TIF_SINGLESTEP);
+}
diff --git a/arch/arm64/kernel/entry-fpsimd.S b/arch/arm64/kernel/entry-fpsimd.S
new file mode 100644
index 0000000..17988a6
--- /dev/null
+++ b/arch/arm64/kernel/entry-fpsimd.S
@@ -0,0 +1,80 @@
+/*
+ * FP/SIMD state saving and restoring
+ *
+ * Copyright (C) 2012 ARM Ltd.
+ * Author: Catalin Marinas <catalin.marinas@arm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/linkage.h>
+
+#include <asm/assembler.h>
+
+/*
+ * Save the FP registers.
+ *
+ * x0 - pointer to struct fpsimd_state
+ */
+ENTRY(fpsimd_save_state)
+	stp	q0, q1, [x0, #16 * 0]
+	stp	q2, q3, [x0, #16 * 2]
+	stp	q4, q5, [x0, #16 * 4]
+	stp	q6, q7, [x0, #16 * 6]
+	stp	q8, q9, [x0, #16 * 8]
+	stp	q10, q11, [x0, #16 * 10]
+	stp	q12, q13, [x0, #16 * 12]
+	stp	q14, q15, [x0, #16 * 14]
+	stp	q16, q17, [x0, #16 * 16]
+	stp	q18, q19, [x0, #16 * 18]
+	stp	q20, q21, [x0, #16 * 20]
+	stp	q22, q23, [x0, #16 * 22]
+	stp	q24, q25, [x0, #16 * 24]
+	stp	q26, q27, [x0, #16 * 26]
+	stp	q28, q29, [x0, #16 * 28]
+	stp	q30, q31, [x0, #16 * 30]!
+	mrs	x8, fpsr
+	str	w8, [x0, #16 * 2]
+	mrs	x8, fpcr
+	str	w8, [x0, #16 * 2 + 4]
+	ret
+ENDPROC(fpsimd_save_state)
+
+/*
+ * Load the FP registers.
+ *
+ * x0 - pointer to struct fpsimd_state
+ */
+ENTRY(fpsimd_load_state)
+	ldp	q0, q1, [x0, #16 * 0]
+	ldp	q2, q3, [x0, #16 * 2]
+	ldp	q4, q5, [x0, #16 * 4]
+	ldp	q6, q7, [x0, #16 * 6]
+	ldp	q8, q9, [x0, #16 * 8]
+	ldp	q10, q11, [x0, #16 * 10]
+	ldp	q12, q13, [x0, #16 * 12]
+	ldp	q14, q15, [x0, #16 * 14]
+	ldp	q16, q17, [x0, #16 * 16]
+	ldp	q18, q19, [x0, #16 * 18]
+	ldp	q20, q21, [x0, #16 * 20]
+	ldp	q22, q23, [x0, #16 * 22]
+	ldp	q24, q25, [x0, #16 * 24]
+	ldp	q26, q27, [x0, #16 * 26]
+	ldp	q28, q29, [x0, #16 * 28]
+	ldp	q30, q31, [x0, #16 * 30]!
+	ldr	w8, [x0, #16 * 2]
+	ldr	w9, [x0, #16 * 2 + 4]
+	msr	fpsr, x8
+	msr	fpcr, x9
+	ret
+ENDPROC(fpsimd_load_state)
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
new file mode 100644
index 0000000..38cf853
--- /dev/null
+++ b/arch/arm64/kernel/entry.S
@@ -0,0 +1,695 @@
+/*
+ * Low-level exception handling code
+ *
+ * Copyright (C) 2012 ARM Ltd.
+ * Authors:	Catalin Marinas <catalin.marinas@arm.com>
+ *		Will Deacon <will.deacon@arm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/init.h>
+#include <linux/linkage.h>
+
+#include <asm/assembler.h>
+#include <asm/asm-offsets.h>
+#include <asm/errno.h>
+#include <asm/thread_info.h>
+#include <asm/unistd.h>
+
+/*
+ * Bad Abort numbers
+ *-----------------
+ */
+#define BAD_SYNC	0
+#define BAD_IRQ		1
+#define BAD_FIQ		2
+#define BAD_ERROR	3
+
+	.macro	kernel_entry, el, regsize = 64
+	sub	sp, sp, #S_FRAME_SIZE - S_LR	// room for LR, SP, SPSR, ELR
+	.if	\regsize == 32
+	mov	w0, w0				// zero upper 32 bits of x0
+	.endif
+	push	x28, x29
+	push	x26, x27
+	push	x24, x25
+	push	x22, x23
+	push	x20, x21
+	push	x18, x19
+	push	x16, x17
+	push	x14, x15
+	push	x12, x13
+	push	x10, x11
+	push	x8, x9
+	push	x6, x7
+	push	x4, x5
+	push	x2, x3
+	push	x0, x1
+	.if	\el == 0
+	mrs	x21, sp_el0
+	.else
+	add	x21, sp, #S_FRAME_SIZE
+	.endif
+	mrs	x22, elr_el1
+	mrs	x23, spsr_el1
+	stp	lr, x21, [sp, #S_LR]
+	stp	x22, x23, [sp, #S_PC]
+
+	/*
+	 * Set syscallno to -1 by default (overridden later if real syscall).
+	 */
+	.if	\el == 0
+	mvn	x21, xzr
+	str	x21, [sp, #S_SYSCALLNO]
+	.endif
+
+	/*
+	 * Registers that may be useful after this macro is invoked:
+	 *
+	 * x21 - aborted SP
+	 * x22 - aborted PC
+	 * x23 - aborted PSTATE
+	*/
+	.endm
+
+	.macro	kernel_exit, el, ret = 0
+	ldp	x21, x22, [sp, #S_PC]		// load ELR, SPSR
+	.if	\el == 0
+	ldr	x23, [sp, #S_SP]		// load return stack pointer
+	.endif
+	.if	\ret
+	ldr	x1, [sp, #S_X1]			// preserve x0 (syscall return)
+	add	sp, sp, S_X2
+	.else
+	pop	x0, x1
+	.endif
+	pop	x2, x3				// load the rest of the registers
+	pop	x4, x5
+	pop	x6, x7
+	pop	x8, x9
+	msr	elr_el1, x21			// set up the return data
+	msr	spsr_el1, x22
+	.if	\el == 0
+	msr	sp_el0, x23
+	.endif
+	pop	x10, x11
+	pop	x12, x13
+	pop	x14, x15
+	pop	x16, x17
+	pop	x18, x19
+	pop	x20, x21
+	pop	x22, x23
+	pop	x24, x25
+	pop	x26, x27
+	pop	x28, x29
+	ldr	lr, [sp], #S_FRAME_SIZE - S_LR	// load LR and restore SP
+	eret					// return to kernel
+	.endm
+
+	.macro	get_thread_info, rd
+	mov	\rd, sp
+	and	\rd, \rd, #~((1 << 13) - 1)	// top of 8K stack
+	.endm
+
+/*
+ * These are the registers used in the syscall handler, and allow us to
+ * have in theory up to 7 arguments to a function - x0 to x6.
+ *
+ * x7 is reserved for the system call number in 32-bit mode.
+ */
+sc_nr	.req	x25		// number of system calls
+scno	.req	x26		// syscall number
+stbl	.req	x27		// syscall table pointer
+tsk	.req	x28		// current thread_info
+
+/*
+ * Interrupt handling.
+ */
+	.macro	irq_handler
+	ldr	x1, handle_arch_irq
+	mov	x0, sp
+	blr	x1
+	.endm
+
+	.text
+
+/*
+ * Exception vectors.
+ */
+	.macro	ventry	label
+	.align	7
+	b	\label
+	.endm
+
+	.align	11
+ENTRY(vectors)
+	ventry	el1_sync_invalid		// Synchronous EL1t
+	ventry	el1_irq_invalid			// IRQ EL1t
+	ventry	el1_fiq_invalid			// FIQ EL1t
+	ventry	el1_error_invalid		// Error EL1t
+
+	ventry	el1_sync			// Synchronous EL1h
+	ventry	el1_irq				// IRQ EL1h
+	ventry	el1_fiq_invalid			// FIQ EL1h
+	ventry	el1_error_invalid		// Error EL1h
+
+	ventry	el0_sync			// Synchronous 64-bit EL0
+	ventry	el0_irq				// IRQ 64-bit EL0
+	ventry	el0_fiq_invalid			// FIQ 64-bit EL0
+	ventry	el0_error_invalid		// Error 64-bit EL0
+
+#ifdef CONFIG_COMPAT
+	ventry	el0_sync_compat			// Synchronous 32-bit EL0
+	ventry	el0_irq_compat			// IRQ 32-bit EL0
+	ventry	el0_fiq_invalid_compat		// FIQ 32-bit EL0
+	ventry	el0_error_invalid_compat	// Error 32-bit EL0
+#else
+	ventry	el0_sync_invalid		// Synchronous 32-bit EL0
+	ventry	el0_irq_invalid			// IRQ 32-bit EL0
+	ventry	el0_fiq_invalid			// FIQ 32-bit EL0
+	ventry	el0_error_invalid		// Error 32-bit EL0
+#endif
+END(vectors)
+
+/*
+ * Invalid mode handlers
+ */
+	.macro	inv_entry, el, reason, regsize = 64
+	kernel_entry el, \regsize
+	mov	x0, sp
+	mov	x1, #\reason
+	mrs	x2, esr_el1
+	b	bad_mode
+	.endm
+
+el0_sync_invalid:
+	inv_entry 0, BAD_SYNC
+ENDPROC(el0_sync_invalid)
+
+el0_irq_invalid:
+	inv_entry 0, BAD_IRQ
+ENDPROC(el0_irq_invalid)
+
+el0_fiq_invalid:
+	inv_entry 0, BAD_FIQ
+ENDPROC(el0_fiq_invalid)
+
+el0_error_invalid:
+	inv_entry 0, BAD_ERROR
+ENDPROC(el0_error_invalid)
+
+#ifdef CONFIG_COMPAT
+el0_fiq_invalid_compat:
+	inv_entry 0, BAD_FIQ, 32
+ENDPROC(el0_fiq_invalid_compat)
+
+el0_error_invalid_compat:
+	inv_entry 0, BAD_ERROR, 32
+ENDPROC(el0_error_invalid_compat)
+#endif
+
+el1_sync_invalid:
+	inv_entry 1, BAD_SYNC
+ENDPROC(el1_sync_invalid)
+
+el1_irq_invalid:
+	inv_entry 1, BAD_IRQ
+ENDPROC(el1_irq_invalid)
+
+el1_fiq_invalid:
+	inv_entry 1, BAD_FIQ
+ENDPROC(el1_fiq_invalid)
+
+el1_error_invalid:
+	inv_entry 1, BAD_ERROR
+ENDPROC(el1_error_invalid)
+
+/*
+ * EL1 mode handlers.
+ */
+	.align	6
+el1_sync:
+	kernel_entry 1
+	mrs	x1, esr_el1			// read the syndrome register
+	lsr	x24, x1, #26			// exception class
+	cmp	x24, #0x25			// data abort in EL1
+	b.eq	el1_da
+	cmp	x24, #0x18			// configurable trap
+	b.eq	el1_undef
+	cmp	x24, #0x26			// stack alignment exception
+	b.eq	el1_sp_pc
+	cmp	x24, #0x22			// pc alignment exception
+	b.eq	el1_sp_pc
+	cmp	x24, #0x00			// unknown exception in EL1
+	b.eq	el1_undef
+	cmp	x24, #0x30			// debug exception in EL1
+	b.ge	el1_dbg
+	b	el1_inv
+el1_da:
+	/*
+	 * Data abort handling
+	 */
+	mrs	x0, far_el1
+	enable_dbg_if_not_stepping x2
+	// re-enable interrupts if they were enabled in the aborted context
+	tbnz	x23, #7, 1f			// PSR_I_BIT
+	enable_irq
+1:
+	mov	x2, sp				// struct pt_regs
+	bl	do_mem_abort
+
+	// disable interrupts before pulling preserved data off the stack
+	disable_irq
+	kernel_exit 1
+el1_sp_pc:
+	/*
+	 * Stack or PC alignment exception handling
+	 */
+	mrs	x0, far_el1
+	mov	x1, x25
+	mov	x2, sp
+	b	do_sp_pc_abort
+el1_undef:
+	/*
+	 * Undefined instruction
+	 */
+	mov	x0, sp
+	b	do_undefinstr
+el1_dbg:
+	/*
+	 * Debug exception handling
+	 */
+	tbz	x24, #0, el1_inv		// EL1 only
+	mrs	x0, far_el1
+	mov	x2, sp				// struct pt_regs
+	bl	do_debug_exception
+
+	kernel_exit 1
+el1_inv:
+	// TODO: add support for undefined instructions in kernel mode
+	mov	x0, sp
+	mov	x1, #BAD_SYNC
+	mrs	x2, esr_el1
+	b	bad_mode
+ENDPROC(el1_sync)
+
+	.align	6
+el1_irq:
+	kernel_entry 1
+	enable_dbg_if_not_stepping x0
+#ifdef CONFIG_TRACE_IRQFLAGS
+	bl	trace_hardirqs_off
+#endif
+#ifdef CONFIG_PREEMPT
+	get_thread_info tsk
+	ldr	x24, [tsk, #TI_PREEMPT]		// get preempt count
+	add	x0, x24, #1			// increment it
+	str	x0, [tsk, #TI_PREEMPT]
+#endif
+	irq_handler
+#ifdef CONFIG_PREEMPT
+	str	x24, [tsk, #TI_PREEMPT]		// restore preempt count
+	cbnz	x24, 1f				// preempt count != 0
+	ldr	x0, [tsk, #TI_FLAGS]		// get flags
+	tbz	x0, #TIF_NEED_RESCHED, 1f	// needs rescheduling?
+	bl	el1_preempt
+1:
+#endif
+#ifdef CONFIG_TRACE_IRQFLAGS
+	bl	trace_hardirqs_on
+#endif
+	kernel_exit 1
+ENDPROC(el1_irq)
+
+#ifdef CONFIG_PREEMPT
+el1_preempt:
+	mov	x24, lr
+1:	enable_dbg
+	bl	preempt_schedule_irq		// irq en/disable is done inside
+	ldr	x0, [tsk, #TI_FLAGS]		// get new tasks TI_FLAGS
+	tbnz	x0, #TIF_NEED_RESCHED, 1b	// needs rescheduling?
+	ret	x24
+#endif
+
+/*
+ * EL0 mode handlers.
+ */
+	.align	6
+el0_sync:
+	kernel_entry 0
+	mrs	x25, esr_el1			// read the syndrome register
+	lsr	x24, x25, #26			// exception class
+	cmp	x24, #0x15			// SVC in 64-bit state
+	b.eq	el0_svc
+	adr	lr, ret_from_exception
+	cmp	x24, #0x24			// data abort in EL0
+	b.eq	el0_da
+	cmp	x24, #0x20			// instruction abort in EL0
+	b.eq	el0_ia
+	cmp	x24, #0x07			// FP/ASIMD access
+	b.eq	el0_fpsimd_acc
+	cmp	x24, #0x2c			// FP/ASIMD exception
+	b.eq	el0_fpsimd_exc
+	cmp	x24, #0x18			// configurable trap
+	b.eq	el0_undef
+	cmp	x24, #0x26			// stack alignment exception
+	b.eq	el0_sp_pc
+	cmp	x24, #0x22			// pc alignment exception
+	b.eq	el0_sp_pc
+	cmp	x24, #0x00			// unknown exception in EL0
+	b.eq	el0_undef
+	cmp	x24, #0x30			// debug exception in EL0
+	b.ge	el0_dbg
+	b	el0_inv
+
+#ifdef CONFIG_COMPAT
+	.align	6
+el0_sync_compat:
+	kernel_entry 0, 32
+	mrs	x25, esr_el1			// read the syndrome register
+	lsr	x24, x25, #26			// exception class
+	cmp	x24, #0x11			// SVC in 32-bit state
+	b.eq	el0_svc_compat
+	adr	lr, ret_from_exception
+	cmp	x24, #0x24			// data abort in EL0
+	b.eq	el0_da
+	cmp	x24, #0x20			// instruction abort in EL0
+	b.eq	el0_ia
+	cmp	x24, #0x07			// FP/ASIMD access
+	b.eq	el0_fpsimd_acc
+	cmp	x24, #0x28			// FP/ASIMD exception
+	b.eq	el0_fpsimd_exc
+	cmp	x24, #0x00			// unknown exception in EL0
+	b.eq	el0_undef
+	cmp	x24, #0x30			// debug exception in EL0
+	b.ge	el0_dbg
+	b	el0_inv
+el0_svc_compat:
+	/*
+	 * AArch32 syscall handling
+	 */
+	adr	stbl, compat_sys_call_table	// load compat syscall table pointer
+	uxtw	scno, w7			// syscall number in w7 (r7)
+	mov     sc_nr, #__NR_compat_syscalls
+	b	el0_svc_naked
+
+	.align	6
+el0_irq_compat:
+	kernel_entry 0, 32
+	b	el0_irq_naked
+#endif
+
+el0_da:
+	/*
+	 * Data abort handling
+	 */
+	mrs	x0, far_el1
+	disable_step x1
+	isb
+	enable_dbg
+	// enable interrupts before calling the main handler
+	enable_irq
+	mov	x1, x25
+	mov	x2, sp
+	b	do_mem_abort
+el0_ia:
+	/*
+	 * Instruction abort handling
+	 */
+	mrs	x0, far_el1
+	disable_step x1
+	isb
+	enable_dbg
+	// enable interrupts before calling the main handler
+	enable_irq
+	orr	x1, x25, #1 << 24		// use reserved ISS bit for instruction aborts
+	mov	x2, sp
+	b	do_mem_abort
+el0_fpsimd_acc:
+	/*
+	 * Floating Point or Advanced SIMD access
+	 */
+	mov	x0, x25
+	mov	x1, sp
+	b	do_fpsimd_acc
+el0_fpsimd_exc:
+	/*
+	 * Floating Point or Advanced SIMD exception
+	 */
+	mov	x0, x25
+	mov	x1, sp
+	b	do_fpsimd_exc
+el0_sp_pc:
+	/*
+	 * Stack or PC alignment exception handling
+	 */
+	mrs	x0, far_el1
+	disable_step x1
+	isb
+	enable_dbg
+	// enable interrupts before calling the main handler
+	enable_irq
+	mov	x1, x25
+	mov	x2, sp
+	b	do_sp_pc_abort
+el0_undef:
+	/*
+	 * Undefined instruction
+	 */
+	mov	x0, sp
+	b	do_undefinstr
+el0_dbg:
+	/*
+	 * Debug exception handling
+	 */
+	tbnz	x24, #0, el0_inv		// EL0 only
+	mrs	x0, far_el1
+	disable_step x1
+	mov	x1, x25
+	mov	x2, sp
+	b	do_debug_exception
+el0_inv:
+	mov	x0, sp
+	mov	x1, #BAD_SYNC
+	mrs	x2, esr_el1
+	b	bad_mode
+ENDPROC(el0_sync)
+
+	.align	6
+el0_irq:
+	kernel_entry 0
+el0_irq_naked:
+	disable_step x1
+	isb
+	enable_dbg
+#ifdef CONFIG_TRACE_IRQFLAGS
+	bl	trace_hardirqs_off
+#endif
+	get_thread_info tsk
+#ifdef CONFIG_PREEMPT
+	ldr	x24, [tsk, #TI_PREEMPT]		// get preempt count
+	add	x23, x24, #1			// increment it
+	str	x23, [tsk, #TI_PREEMPT]
+#endif
+	irq_handler
+#ifdef CONFIG_PREEMPT
+	ldr	x0, [tsk, #TI_PREEMPT]
+	str	x24, [tsk, #TI_PREEMPT]
+	cmp	x0, x23
+	b.eq	1f
+	mov	x1, #0
+	str	x1, [x1]			// BUG
+1:
+#endif
+#ifdef CONFIG_TRACE_IRQFLAGS
+	bl	trace_hardirqs_on
+#endif
+	b	ret_to_user
+ENDPROC(el0_irq)
+
+/*
+ * This is the return code to user mode for abort handlers
+ */
+ret_from_exception:
+	get_thread_info tsk
+	b	ret_to_user
+ENDPROC(ret_from_exception)
+
+/*
+ * Register switch for AArch64. The callee-saved registers need to be saved
+ * and restored. On entry:
+ *   x0 = previous task_struct (must be preserved across the switch)
+ *   x1 = next task_struct
+ * Previous and next are guaranteed not to be the same.
+ *
+ */
+ENTRY(cpu_switch_to)
+	add	x8, x0, #THREAD_CPU_CONTEXT
+	mov	x9, sp
+	stp	x19, x20, [x8], #16		// store callee-saved registers
+	stp	x21, x22, [x8], #16
+	stp	x23, x24, [x8], #16
+	stp	x25, x26, [x8], #16
+	stp	x27, x28, [x8], #16
+	stp	x29, x9, [x8], #16
+	str	lr, [x8]
+	add	x8, x1, #THREAD_CPU_CONTEXT
+	ldp	x19, x20, [x8], #16		// restore callee-saved registers
+	ldp	x21, x22, [x8], #16
+	ldp	x23, x24, [x8], #16
+	ldp	x25, x26, [x8], #16
+	ldp	x27, x28, [x8], #16
+	ldp	x29, x9, [x8], #16
+	ldr	lr, [x8]
+	mov	sp, x9
+	ret
+ENDPROC(cpu_switch_to)
+
+/*
+ * This is the fast syscall return path.  We do as little as possible here,
+ * and this includes saving x0 back into the kernel stack.
+ */
+ret_fast_syscall:
+	disable_irq				// disable interrupts
+	ldr	x1, [tsk, #TI_FLAGS]
+	and	x2, x1, #_TIF_WORK_MASK
+	cbnz	x2, fast_work_pending
+	tbz	x1, #TIF_SINGLESTEP, fast_exit
+	disable_dbg
+	enable_step x2
+fast_exit:
+	kernel_exit 0, ret = 1
+
+/*
+ * Ok, we need to do extra processing, enter the slow path.
+ */
+fast_work_pending:
+	str	x0, [sp, #S_X0]			// returned x0
+work_pending:
+	tbnz	x1, #TIF_NEED_RESCHED, work_resched
+	/* TIF_SIGPENDING or TIF_NOTIFY_RESUME case */
+	ldr	x2, [sp, #S_PSTATE]
+	mov	x0, sp				// 'regs'
+	tst	x2, #PSR_MODE_MASK		// user mode regs?
+	b.ne	no_work_pending			// returning to kernel
+	bl	do_notify_resume
+	b	ret_to_user
+work_resched:
+	enable_dbg
+	bl	schedule
+
+/*
+ * "slow" syscall return path.
+ */
+ENTRY(ret_to_user)
+	disable_irq				// disable interrupts
+	ldr	x1, [tsk, #TI_FLAGS]
+	and	x2, x1, #_TIF_WORK_MASK
+	cbnz	x2, work_pending
+	tbz	x1, #TIF_SINGLESTEP, no_work_pending
+	disable_dbg
+	enable_step x2
+no_work_pending:
+	kernel_exit 0, ret = 0
+ENDPROC(ret_to_user)
+
+/*
+ * This is how we return from a fork.
+ */
+ENTRY(ret_from_fork)
+	bl	schedule_tail
+	get_thread_info tsk
+	b	ret_to_user
+ENDPROC(ret_from_fork)
+
+/*
+ * SVC handler.
+ */
+	.align	6
+el0_svc:
+	adrp	stbl, sys_call_table		// load syscall table pointer
+	uxtw	scno, w8			// syscall number in w8
+	mov	sc_nr, #__NR_syscalls
+el0_svc_naked:					// compat entry point
+	stp	x0, scno, [sp, #S_ORIG_X0]	// save the original x0 and syscall number
+	disable_step x16
+	isb
+	enable_dbg
+	enable_irq
+
+	get_thread_info tsk
+	ldr	x16, [tsk, #TI_FLAGS]		// check for syscall tracing
+	tbnz	x16, #TIF_SYSCALL_TRACE, __sys_trace // are we tracing syscalls?
+	adr	lr, ret_fast_syscall		// return address
+	cmp     scno, sc_nr                     // check upper syscall limit
+	b.hs	ni_sys
+	ldr	x16, [stbl, scno, lsl #3]	// address in the syscall table
+	br	x16				// call sys_* routine
+ni_sys:
+	mov	x0, sp
+	b	do_ni_syscall
+ENDPROC(el0_svc)
+
+	/*
+	 * This is the really slow path.  We're going to be doing context
+	 * switches, and waiting for our parent to respond.
+	 */
+__sys_trace:
+	mov	x1, sp
+	mov	w0, #0				// trace entry
+	bl	syscall_trace
+	adr	lr, __sys_trace_return		// return address
+	uxtw	scno, w0			// syscall number (possibly new)
+	mov	x1, sp				// pointer to regs
+	cmp	scno, sc_nr			// check upper syscall limit
+	b.hs	ni_sys
+	ldp	x0, x1, [sp]			// restore the syscall args
+	ldp	x2, x3, [sp, #S_X2]
+	ldp	x4, x5, [sp, #S_X4]
+	ldp	x6, x7, [sp, #S_X6]
+	ldr	x16, [stbl, scno, lsl #3]	// address in the syscall table
+	br	x16				// call sys_* routine
+
+__sys_trace_return:
+	str	x0, [sp]			// save returned x0
+	mov	x1, sp
+	mov	w0, #1				// trace exit
+	bl	syscall_trace
+	b	ret_to_user
+
+/*
+ * Special system call wrappers.
+ */
+ENTRY(sys_execve_wrapper)
+	mov	x3, sp
+	b	sys_execve
+ENDPROC(sys_execve_wrapper)
+
+ENTRY(sys_clone_wrapper)
+	mov	x5, sp
+	b	sys_clone
+ENDPROC(sys_clone_wrapper)
+
+ENTRY(sys_rt_sigreturn_wrapper)
+	mov	x0, sp
+	b	sys_rt_sigreturn
+ENDPROC(sys_rt_sigreturn_wrapper)
+
+ENTRY(sys_sigaltstack_wrapper)
+	ldr	x2, [sp, #S_SP]
+	b	sys_sigaltstack
+ENDPROC(sys_sigaltstack_wrapper)
+
+ENTRY(handle_arch_irq)
+	.quad	0
diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
new file mode 100644
index 0000000..e8b8357
--- /dev/null
+++ b/arch/arm64/kernel/fpsimd.c
@@ -0,0 +1,106 @@
+/*
+ * FP/SIMD context switching and fault handling
+ *
+ * Copyright (C) 2012 ARM Ltd.
+ * Author: Catalin Marinas <catalin.marinas@arm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+
+#include <asm/fpsimd.h>
+#include <asm/cputype.h>
+
+#define FPEXC_IOF	(1 << 0)
+#define FPEXC_DZF	(1 << 1)
+#define FPEXC_OFF	(1 << 2)
+#define FPEXC_UFF	(1 << 3)
+#define FPEXC_IXF	(1 << 4)
+#define FPEXC_IDF	(1 << 7)
+
+/*
+ * Trapped FP/ASIMD access.
+ */
+void do_fpsimd_acc(unsigned int esr, struct pt_regs *regs)
+{
+	/* TODO: implement lazy context saving/restoring */
+	WARN_ON(1);
+}
+
+/*
+ * Raise a SIGFPE for the current process.
+ */
+void do_fpsimd_exc(unsigned int esr, struct pt_regs *regs)
+{
+	siginfo_t info;
+	unsigned int si_code = 0;
+
+	if (esr & FPEXC_IOF)
+		si_code = FPE_FLTINV;
+	else if (esr & FPEXC_DZF)
+		si_code = FPE_FLTDIV;
+	else if (esr & FPEXC_OFF)
+		si_code = FPE_FLTOVF;
+	else if (esr & FPEXC_UFF)
+		si_code = FPE_FLTUND;
+	else if (esr & FPEXC_IXF)
+		si_code = FPE_FLTRES;
+
+	memset(&info, 0, sizeof(info));
+	info.si_signo = SIGFPE;
+	info.si_code = si_code;
+	info.si_addr = (void __user *)instruction_pointer(regs);
+
+	send_sig_info(SIGFPE, &info, current);
+}
+
+void fpsimd_thread_switch(struct task_struct *next)
+{
+	/* check if not kernel threads */
+	if (current->mm)
+		fpsimd_save_state(&current->thread.fpsimd_state);
+	if (next->mm)
+		fpsimd_load_state(&next->thread.fpsimd_state);
+}
+
+void fpsimd_flush_thread(void)
+{
+	memset(&current->thread.fpsimd_state, 0, sizeof(struct fpsimd_state));
+	fpsimd_load_state(&current->thread.fpsimd_state);
+}
+
+/*
+ * FP/SIMD support code initialisation.
+ */
+static int __init fpsimd_init(void)
+{
+	u64 pfr = read_cpuid(ID_AA64PFR0_EL1);
+
+	if (pfr & (0xf << 16)) {
+		pr_notice("Floating-point is not implemented\n");
+		return 0;
+	}
+	elf_hwcap |= HWCAP_FP;
+
+	if (pfr & (0xf << 20))
+		pr_notice("Advanced SIMD is not implemented\n");
+	else
+		elf_hwcap |= HWCAP_ASIMD;
+
+	return 0;
+}
+late_initcall(fpsimd_init);
diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
new file mode 100644
index 0000000..a2f02b6
--- /dev/null
+++ b/arch/arm64/kernel/head.S
@@ -0,0 +1,510 @@
+/*
+ * Low-level CPU initialisation
+ * Based on arch/arm/kernel/head.S
+ *
+ * Copyright (C) 1994-2002 Russell King
+ * Copyright (C) 2003-2012 ARM Ltd.
+ * Authors:	Catalin Marinas <catalin.marinas@arm.com>
+ *		Will Deacon <will.deacon@arm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/linkage.h>
+#include <linux/init.h>
+
+#include <asm/assembler.h>
+#include <asm/ptrace.h>
+#include <asm/asm-offsets.h>
+#include <asm/memory.h>
+#include <asm/thread_info.h>
+#include <asm/pgtable-hwdef.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+
+/*
+ * swapper_pg_dir is the virtual address of the initial page table. We place
+ * the page tables 3 * PAGE_SIZE below KERNEL_RAM_VADDR. The idmap_pg_dir has
+ * 2 pages and is placed below swapper_pg_dir.
+ */
+#define KERNEL_RAM_VADDR	(PAGE_OFFSET + TEXT_OFFSET)
+
+#if (KERNEL_RAM_VADDR & 0xfffff) != 0x80000
+#error KERNEL_RAM_VADDR must start at 0xXXX80000
+#endif
+
+#define SWAPPER_DIR_SIZE	(3 * PAGE_SIZE)
+#define IDMAP_DIR_SIZE		(2 * PAGE_SIZE)
+
+	.globl	swapper_pg_dir
+	.equ	swapper_pg_dir, KERNEL_RAM_VADDR - SWAPPER_DIR_SIZE
+
+	.globl	idmap_pg_dir
+	.equ	idmap_pg_dir, swapper_pg_dir - IDMAP_DIR_SIZE
+
+	.macro	pgtbl, ttb0, ttb1, phys
+	add	\ttb1, \phys, #TEXT_OFFSET - SWAPPER_DIR_SIZE
+	sub	\ttb0, \ttb1, #IDMAP_DIR_SIZE
+	.endm
+
+#ifdef CONFIG_ARM64_64K_PAGES
+#define BLOCK_SHIFT	PAGE_SHIFT
+#define BLOCK_SIZE	PAGE_SIZE
+#else
+#define BLOCK_SHIFT	SECTION_SHIFT
+#define BLOCK_SIZE	SECTION_SIZE
+#endif
+
+#define KERNEL_START	KERNEL_RAM_VADDR
+#define KERNEL_END	_end
+
+/*
+ * Initial memory map attributes.
+ */
+#ifndef CONFIG_SMP
+#define PTE_FLAGS	PTE_TYPE_PAGE | PTE_AF
+#define PMD_FLAGS	PMD_TYPE_SECT | PMD_SECT_AF
+#else
+#define PTE_FLAGS	PTE_TYPE_PAGE | PTE_AF | PTE_SHARED
+#define PMD_FLAGS	PMD_TYPE_SECT | PMD_SECT_AF | PMD_SECT_S
+#endif
+
+#ifdef CONFIG_ARM64_64K_PAGES
+#define MM_MMUFLAGS	PTE_ATTRINDX(MT_NORMAL) | PTE_FLAGS
+#define IO_MMUFLAGS	PTE_ATTRINDX(MT_DEVICE_nGnRE) | PTE_XN | PTE_FLAGS
+#else
+#define MM_MMUFLAGS	PMD_ATTRINDX(MT_NORMAL) | PMD_FLAGS
+#define IO_MMUFLAGS	PMD_ATTRINDX(MT_DEVICE_nGnRE) | PMD_SECT_XN | PMD_FLAGS
+#endif
+
+/*
+ * Kernel startup entry point.
+ * ---------------------------
+ *
+ * The requirements are:
+ *   MMU = off, D-cache = off, I-cache = on or off,
+ *   x0 = physical address to the FDT blob.
+ *
+ * This code is mostly position independent so you call this at
+ * __pa(PAGE_OFFSET + TEXT_OFFSET).
+ *
+ * Note that the callee-saved registers are used for storing variables
+ * that are useful before the MMU is enabled. The allocations are described
+ * in the entry routines.
+ */
+	__HEAD
+
+	/*
+	 * DO NOT MODIFY. Image header expected by Linux boot-loaders.
+	 */
+	b	stext				// branch to kernel start, magic
+	.long	0				// reserved
+	.quad	TEXT_OFFSET			// Image load offset from start of RAM
+	.quad	0				// reserved
+	.quad	0				// reserved
+
+ENTRY(stext)
+	mov	x21, x0				// x21=FDT
+	bl	el2_setup			// Drop to EL1
+	mrs	x22, midr_el1			// x22=cpuid
+	mov	x0, x22
+	bl	lookup_processor_type
+	mov	x23, x0				// x23=current cpu_table
+	cbz	x23, __error_p			// invalid processor (x23=0)?
+	bl	__calc_phys_offset		// x24=PHYS_OFFSET, x28=PHYS_OFFSET-PAGE_OFFSET
+	bl	__vet_fdt
+	bl	__create_page_tables		// x25=TTBR0, x26=TTBR1
+	/*
+	 * The following calls CPU specific code in a position independent
+	 * manner. See arch/arm64/mm/proc.S for details. x23 = base of
+	 * cpu_info structure selected by lookup_processor_type above.
+	 * On return, the CPU will be ready for the MMU to be turned on and
+	 * the TCR will have been set.
+	 */
+	ldr	x27, __switch_data		// address to jump to after
+						// MMU has been enabled
+	adr	lr, __enable_mmu		// return (PIC) address
+	ldr	x12, [x23, #CPU_INFO_SETUP]
+	add	x12, x12, x28			// __virt_to_phys
+	br	x12				// initialise processor
+ENDPROC(stext)
+
+/*
+ * If we're fortunate enough to boot at EL2, ensure that the world is
+ * sane before dropping to EL1.
+ */
+ENTRY(el2_setup)
+	mrs	x0, CurrentEL
+	cmp	x0, #PSR_MODE_EL2t
+	ccmp	x0, #PSR_MODE_EL2h, #0x4, ne
+	b.eq	1f
+	ret
+
+	/* Hyp configuration. */
+1:	mov	x0, #(1 << 31)			// 64-bit EL1
+	msr	hcr_el2, x0
+
+	/* Generic timers. */
+	mrs	x0, cnthctl_el2
+	orr	x0, x0, #3			// Enable EL1 physical timers
+	msr	cnthctl_el2, x0
+
+	/* Populate ID registers. */
+	mrs	x0, midr_el1
+	mrs	x1, mpidr_el1
+	msr	vpidr_el2, x0
+	msr	vmpidr_el2, x1
+
+	/* sctlr_el1 */
+	mov	x0, #0x0800			// Set/clear RES{1,0} bits
+	movk	x0, #0x30d0, lsl #16
+	msr	sctlr_el1, x0
+
+	/* Coprocessor traps. */
+	mov	x0, #0x33ff
+	msr	cptr_el2, x0			// Disable copro. traps to EL2
+
+#ifdef CONFIG_COMPAT
+	msr	hstr_el2, xzr			// Disable CP15 traps to EL2
+#endif
+
+	/* spsr */
+	mov	x0, #(PSR_F_BIT | PSR_I_BIT | PSR_A_BIT | PSR_D_BIT |\
+		      PSR_MODE_EL1h)
+	msr	spsr_el2, x0
+	msr	elr_el2, lr
+	eret
+ENDPROC(el2_setup)
+
+	.align	3
+2:	.quad	.
+	.quad	PAGE_OFFSET
+
+#ifdef CONFIG_SMP
+	.pushsection    .smp.pen.text, "ax"
+	.align	3
+1:	.quad	.
+	.quad	secondary_holding_pen_release
+
+	/*
+	 * This provides a "holding pen" for platforms to hold all secondary
+	 * cores are held until we're ready for them to initialise.
+	 */
+ENTRY(secondary_holding_pen)
+	bl	el2_setup			// Drop to EL1
+	mrs	x0, mpidr_el1
+	and	x0, x0, #15			// CPU number
+	adr	x1, 1b
+	ldp	x2, x3, [x1]
+	sub	x1, x1, x2
+	add	x3, x3, x1
+pen:	ldr	x4, [x3]
+	cmp	x4, x0
+	b.eq	secondary_startup
+	wfe
+	b	pen
+ENDPROC(secondary_holding_pen)
+	.popsection
+
+ENTRY(secondary_startup)
+	/*
+	 * Common entry point for secondary CPUs.
+	 */
+	mrs	x22, midr_el1			// x22=cpuid
+	mov	x0, x22
+	bl	lookup_processor_type
+	mov	x23, x0				// x23=current cpu_table
+	cbz	x23, __error_p			// invalid processor (x23=0)?
+
+	bl	__calc_phys_offset		// x24=phys offset
+	pgtbl	x25, x26, x24			// x25=TTBR0, x26=TTBR1
+	ldr	x12, [x23, #CPU_INFO_SETUP]
+	add	x12, x12, x28			// __virt_to_phys
+	blr	x12				// initialise processor
+
+	ldr	x21, =secondary_data
+	ldr	x27, =__secondary_switched	// address to jump to after enabling the MMU
+	b	__enable_mmu
+ENDPROC(secondary_startup)
+
+ENTRY(__secondary_switched)
+	ldr	x0, [x21]			// get secondary_data.stack
+	mov	sp, x0
+	mov	x29, #0
+	b	secondary_start_kernel
+ENDPROC(__secondary_switched)
+#endif	/* CONFIG_SMP */
+
+/*
+ * Setup common bits before finally enabling the MMU. Essentially this is just
+ * loading the page table pointer and vector base registers.
+ *
+ * On entry to this code, x0 must contain the SCTLR_EL1 value for turning on
+ * the MMU.
+ */
+__enable_mmu:
+	ldr	x5, =vectors
+	msr	vbar_el1, x5
+	msr	ttbr0_el1, x25			// load TTBR0
+	msr	ttbr1_el1, x26			// load TTBR1
+	isb
+	b	__turn_mmu_on
+ENDPROC(__enable_mmu)
+
+/*
+ * Enable the MMU. This completely changes the structure of the visible memory
+ * space. You will not be able to trace execution through this.
+ *
+ *  x0  = system control register
+ *  x27 = *virtual* address to jump to upon completion
+ *
+ * other registers depend on the function called upon completion
+ */
+	.align	6
+__turn_mmu_on:
+	msr	sctlr_el1, x0
+	isb
+	br	x27
+ENDPROC(__turn_mmu_on)
+
+/*
+ * Calculate the start of physical memory.
+ */
+__calc_phys_offset:
+	adr	x0, 1f
+	ldp	x1, x2, [x0]
+	sub	x28, x0, x1			// x28 = PHYS_OFFSET - PAGE_OFFSET
+	add	x24, x2, x28			// x24 = PHYS_OFFSET
+	ret
+ENDPROC(__calc_phys_offset)
+
+	.align 3
+1:	.quad	.
+	.quad	PAGE_OFFSET
+
+/*
+ * Macro to populate the PGD for the corresponding block entry in the next
+ * level (tbl) for the given virtual address.
+ *
+ * Preserves:	pgd, tbl, virt
+ * Corrupts:	tmp1, tmp2
+ */
+	.macro	create_pgd_entry, pgd, tbl, virt, tmp1, tmp2
+	lsr	\tmp1, \virt, #PGDIR_SHIFT
+	and	\tmp1, \tmp1, #PTRS_PER_PGD - 1	// PGD index
+	orr	\tmp2, \tbl, #3			// PGD entry table type
+	str	\tmp2, [\pgd, \tmp1, lsl #3]
+	.endm
+
+/*
+ * Macro to populate block entries in the page table for the start..end
+ * virtual range (inclusive).
+ *
+ * Preserves:	tbl, flags
+ * Corrupts:	phys, start, end, pstate
+ */
+	.macro	create_block_map, tbl, flags, phys, start, end, idmap=0
+	lsr	\phys, \phys, #BLOCK_SHIFT
+	.if	\idmap
+	and	\start, \phys, #PTRS_PER_PTE - 1	// table index
+	.else
+	lsr	\start, \start, #BLOCK_SHIFT
+	and	\start, \start, #PTRS_PER_PTE - 1	// table index
+	.endif
+	orr	\phys, \flags, \phys, lsl #BLOCK_SHIFT	// table entry
+	.ifnc	\start,\end
+	lsr	\end, \end, #BLOCK_SHIFT
+	and	\end, \end, #PTRS_PER_PTE - 1		// table end index
+	.endif
+9999:	str	\phys, [\tbl, \start, lsl #3]		// store the entry
+	.ifnc	\start,\end
+	add	\start, \start, #1			// next entry
+	add	\phys, \phys, #BLOCK_SIZE		// next block
+	cmp	\start, \end
+	b.ls	9999b
+	.endif
+	.endm
+
+/*
+ * Setup the initial page tables. We only setup the barest amount which is
+ * required to get the kernel running. The following sections are required:
+ *   - identity mapping to enable the MMU (low address, TTBR0)
+ *   - first few MB of the kernel linear mapping to jump to once the MMU has
+ *     been enabled, including the FDT blob (TTBR1)
+ */
+__create_page_tables:
+	pgtbl	x25, x26, x24			// idmap_pg_dir and swapper_pg_dir addresses
+
+	/*
+	 * Clear the idmap and swapper page tables.
+	 */
+	mov	x0, x25
+	add	x6, x26, #SWAPPER_DIR_SIZE
+1:	stp	xzr, xzr, [x0], #16
+	stp	xzr, xzr, [x0], #16
+	stp	xzr, xzr, [x0], #16
+	stp	xzr, xzr, [x0], #16
+	cmp	x0, x6
+	b.lo	1b
+
+	ldr	x7, =MM_MMUFLAGS
+
+	/*
+	 * Create the identity mapping.
+	 */
+	add	x0, x25, #PAGE_SIZE		// section table address
+	adr	x3, __turn_mmu_on		// virtual/physical address
+	create_pgd_entry x25, x0, x3, x5, x6
+	create_block_map x0, x7, x3, x5, x5, idmap=1
+
+	/*
+	 * Map the kernel image (starting with PHYS_OFFSET).
+	 */
+	add	x0, x26, #PAGE_SIZE		// section table address
+	mov	x5, #PAGE_OFFSET
+	create_pgd_entry x26, x0, x5, x3, x6
+	ldr	x6, =KERNEL_END - 1
+	mov	x3, x24				// phys offset
+	create_block_map x0, x7, x3, x5, x6
+
+	/*
+	 * Map the FDT blob (maximum 2MB; must be within 512MB of
+	 * PHYS_OFFSET).
+	 */
+	mov	x3, x21				// FDT phys address
+	and	x3, x3, #~((1 << 21) - 1)	// 2MB aligned
+	mov	x6, #PAGE_OFFSET
+	sub	x5, x3, x24			// subtract PHYS_OFFSET
+	tst	x5, #~((1 << 29) - 1)		// within 512MB?
+	csel	x21, xzr, x21, ne		// zero the FDT pointer
+	b.ne	1f
+	add	x5, x5, x6			// __va(FDT blob)
+	add	x6, x5, #1 << 21		// 2MB for the FDT blob
+	sub	x6, x6, #1			// inclusive range
+	create_block_map x0, x7, x3, x5, x6
+1:
+	ret
+ENDPROC(__create_page_tables)
+	.ltorg
+
+	.align	3
+	.type	__switch_data, %object
+__switch_data:
+	.quad	__mmap_switched
+	.quad	__data_loc			// x4
+	.quad	_data				// x5
+	.quad	__bss_start			// x6
+	.quad	_end				// x7
+	.quad	processor_id			// x4
+	.quad	__fdt_pointer			// x5
+	.quad	memstart_addr			// x6
+	.quad	init_thread_union + THREAD_START_SP // sp
+
+/*
+ * The following fragment of code is executed with the MMU on in MMU mode, and
+ * uses absolute addresses; this is not position independent.
+ */
+__mmap_switched:
+	adr	x3, __switch_data + 8
+
+	ldp	x4, x5, [x3], #16
+	ldp	x6, x7, [x3], #16
+	cmp	x4, x5				// Copy data segment if needed
+1:	ccmp	x5, x6, #4, ne
+	b.eq	2f
+	ldr	x16, [x4], #8
+	str	x16, [x5], #8
+	b	1b
+2:
+1:	cmp	x6, x7
+	b.hs	2f
+	str	xzr, [x6], #8			// Clear BSS
+	b	1b
+2:
+	ldp	x4, x5, [x3], #16
+	ldr	x6, [x3], #8
+	ldr	x16, [x3]
+	mov	sp, x16
+	str	x22, [x4]			// Save processor ID
+	str	x21, [x5]			// Save FDT pointer
+	str	x24, [x6]			// Save PHYS_OFFSET
+	mov	x29, #0
+	b	start_kernel
+ENDPROC(__mmap_switched)
+
+/*
+ * Exception handling. Something went wrong and we can't proceed. We ought to
+ * tell the user, but since we don't have any guarantee that we're even
+ * running on the right architecture, we do virtually nothing.
+ */
+__error_p:
+ENDPROC(__error_p)
+
+__error:
+1:	nop
+	b	1b
+ENDPROC(__error)
+
+/*
+ * This function gets the processor ID in w0 and searches the cpu_table[] for
+ * a match. It returns a pointer to the struct cpu_info it found. The
+ * cpu_table[] must end with an empty (all zeros) structure.
+ *
+ * This routine can be called via C code and it needs to work with the MMU
+ * both disabled and enabled (the offset is calculated automatically).
+ */
+ENTRY(lookup_processor_type)
+	adr	x1, __lookup_processor_type_data
+	ldp	x2, x3, [x1]
+	sub	x1, x1, x2			// get offset between VA and PA
+	add	x3, x3, x1			// convert VA to PA
+1:
+	ldp	w5, w6, [x3]			// load cpu_id_val and cpu_id_mask
+	cbz	w5, 2f				// end of list?
+	and	w6, w6, w0
+	cmp	w5, w6
+	b.eq	3f
+	add	x3, x3, #CPU_INFO_SZ
+	b	1b
+2:
+	mov	x3, #0				// unknown processor
+3:
+	mov	x0, x3
+	ret
+ENDPROC(lookup_processor_type)
+
+	.align	3
+	.type	__lookup_processor_type_data, %object
+__lookup_processor_type_data:
+	.quad	.
+	.quad	cpu_table
+	.size	__lookup_processor_type_data, . - __lookup_processor_type_data
+
+/*
+ * Determine validity of the x21 FDT pointer.
+ * The dtb must be 8-byte aligned and live in the first 512M of memory.
+ */
+__vet_fdt:
+	tst	x21, #0x7
+	b.ne	1f
+	cmp	x21, x24
+	b.lt	1f
+	mov	x0, #(1 << 29)
+	add	x0, x0, x24
+	cmp	x21, x0
+	b.ge	1f
+	ret
+1:
+	mov	x21, #0
+	ret
+ENDPROC(__vet_fdt)
diff --git a/arch/arm64/kernel/hw_breakpoint.c b/arch/arm64/kernel/hw_breakpoint.c
new file mode 100644
index 0000000..5ab825c
--- /dev/null
+++ b/arch/arm64/kernel/hw_breakpoint.c
@@ -0,0 +1,880 @@
+/*
+ * HW_breakpoint: a unified kernel/user-space hardware breakpoint facility,
+ * using the CPU's debug registers.
+ *
+ * Copyright (C) 2012 ARM Limited
+ * Author: Will Deacon <will.deacon@arm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define pr_fmt(fmt) "hw-breakpoint: " fmt
+
+#include <linux/errno.h>
+#include <linux/hw_breakpoint.h>
+#include <linux/perf_event.h>
+#include <linux/ptrace.h>
+#include <linux/smp.h>
+
+#include <asm/compat.h>
+#include <asm/current.h>
+#include <asm/debug-monitors.h>
+#include <asm/hw_breakpoint.h>
+#include <asm/kdebug.h>
+#include <asm/traps.h>
+#include <asm/cputype.h>
+#include <asm/system_misc.h>
+
+/* Breakpoint currently in use for each BRP. */
+static DEFINE_PER_CPU(struct perf_event *, bp_on_reg[ARM_MAX_BRP]);
+
+/* Watchpoint currently in use for each WRP. */
+static DEFINE_PER_CPU(struct perf_event *, wp_on_reg[ARM_MAX_WRP]);
+
+/* Currently stepping a per-CPU kernel breakpoint. */
+static DEFINE_PER_CPU(int, stepping_kernel_bp);
+
+/* Number of BRP/WRP registers on this CPU. */
+static int core_num_brps;
+static int core_num_wrps;
+
+/* Determine number of BRP registers available. */
+static int get_num_brps(void)
+{
+	return ((read_cpuid(ID_AA64DFR0_EL1) >> 12) & 0xf) + 1;
+}
+
+/* Determine number of WRP registers available. */
+static int get_num_wrps(void)
+{
+	return ((read_cpuid(ID_AA64DFR0_EL1) >> 20) & 0xf) + 1;
+}
+
+int hw_breakpoint_slots(int type)
+{
+	/*
+	 * We can be called early, so don't rely on
+	 * our static variables being initialised.
+	 */
+	switch (type) {
+	case TYPE_INST:
+		return get_num_brps();
+	case TYPE_DATA:
+		return get_num_wrps();
+	default:
+		pr_warning("unknown slot type: %d\n", type);
+		return 0;
+	}
+}
+
+#define READ_WB_REG_CASE(OFF, N, REG, VAL)	\
+	case (OFF + N):				\
+		AARCH64_DBG_READ(N, REG, VAL);	\
+		break
+
+#define WRITE_WB_REG_CASE(OFF, N, REG, VAL)	\
+	case (OFF + N):				\
+		AARCH64_DBG_WRITE(N, REG, VAL);	\
+		break
+
+#define GEN_READ_WB_REG_CASES(OFF, REG, VAL)	\
+	READ_WB_REG_CASE(OFF,  0, REG, VAL);	\
+	READ_WB_REG_CASE(OFF,  1, REG, VAL);	\
+	READ_WB_REG_CASE(OFF,  2, REG, VAL);	\
+	READ_WB_REG_CASE(OFF,  3, REG, VAL);	\
+	READ_WB_REG_CASE(OFF,  4, REG, VAL);	\
+	READ_WB_REG_CASE(OFF,  5, REG, VAL);	\
+	READ_WB_REG_CASE(OFF,  6, REG, VAL);	\
+	READ_WB_REG_CASE(OFF,  7, REG, VAL);	\
+	READ_WB_REG_CASE(OFF,  8, REG, VAL);	\
+	READ_WB_REG_CASE(OFF,  9, REG, VAL);	\
+	READ_WB_REG_CASE(OFF, 10, REG, VAL);	\
+	READ_WB_REG_CASE(OFF, 11, REG, VAL);	\
+	READ_WB_REG_CASE(OFF, 12, REG, VAL);	\
+	READ_WB_REG_CASE(OFF, 13, REG, VAL);	\
+	READ_WB_REG_CASE(OFF, 14, REG, VAL);	\
+	READ_WB_REG_CASE(OFF, 15, REG, VAL)
+
+#define GEN_WRITE_WB_REG_CASES(OFF, REG, VAL)	\
+	WRITE_WB_REG_CASE(OFF,  0, REG, VAL);	\
+	WRITE_WB_REG_CASE(OFF,  1, REG, VAL);	\
+	WRITE_WB_REG_CASE(OFF,  2, REG, VAL);	\
+	WRITE_WB_REG_CASE(OFF,  3, REG, VAL);	\
+	WRITE_WB_REG_CASE(OFF,  4, REG, VAL);	\
+	WRITE_WB_REG_CASE(OFF,  5, REG, VAL);	\
+	WRITE_WB_REG_CASE(OFF,  6, REG, VAL);	\
+	WRITE_WB_REG_CASE(OFF,  7, REG, VAL);	\
+	WRITE_WB_REG_CASE(OFF,  8, REG, VAL);	\
+	WRITE_WB_REG_CASE(OFF,  9, REG, VAL);	\
+	WRITE_WB_REG_CASE(OFF, 10, REG, VAL);	\
+	WRITE_WB_REG_CASE(OFF, 11, REG, VAL);	\
+	WRITE_WB_REG_CASE(OFF, 12, REG, VAL);	\
+	WRITE_WB_REG_CASE(OFF, 13, REG, VAL);	\
+	WRITE_WB_REG_CASE(OFF, 14, REG, VAL);	\
+	WRITE_WB_REG_CASE(OFF, 15, REG, VAL)
+
+static u64 read_wb_reg(int reg, int n)
+{
+	u64 val = 0;
+
+	switch (reg + n) {
+	GEN_READ_WB_REG_CASES(AARCH64_DBG_REG_BVR, AARCH64_DBG_REG_NAME_BVR, val);
+	GEN_READ_WB_REG_CASES(AARCH64_DBG_REG_BCR, AARCH64_DBG_REG_NAME_BCR, val);
+	GEN_READ_WB_REG_CASES(AARCH64_DBG_REG_WVR, AARCH64_DBG_REG_NAME_WVR, val);
+	GEN_READ_WB_REG_CASES(AARCH64_DBG_REG_WCR, AARCH64_DBG_REG_NAME_WCR, val);
+	default:
+		pr_warning("attempt to read from unknown breakpoint register %d\n", n);
+	}
+
+	return val;
+}
+
+static void write_wb_reg(int reg, int n, u64 val)
+{
+	switch (reg + n) {
+	GEN_WRITE_WB_REG_CASES(AARCH64_DBG_REG_BVR, AARCH64_DBG_REG_NAME_BVR, val);
+	GEN_WRITE_WB_REG_CASES(AARCH64_DBG_REG_BCR, AARCH64_DBG_REG_NAME_BCR, val);
+	GEN_WRITE_WB_REG_CASES(AARCH64_DBG_REG_WVR, AARCH64_DBG_REG_NAME_WVR, val);
+	GEN_WRITE_WB_REG_CASES(AARCH64_DBG_REG_WCR, AARCH64_DBG_REG_NAME_WCR, val);
+	default:
+		pr_warning("attempt to write to unknown breakpoint register %d\n", n);
+	}
+	isb();
+}
+
+/*
+ * Convert a breakpoint privilege level to the corresponding exception
+ * level.
+ */
+static enum debug_el debug_exception_level(int privilege)
+{
+	switch (privilege) {
+	case AARCH64_BREAKPOINT_EL0:
+		return DBG_ACTIVE_EL0;
+	case AARCH64_BREAKPOINT_EL1:
+		return DBG_ACTIVE_EL1;
+	default:
+		pr_warning("invalid breakpoint privilege level %d\n", privilege);
+		return -EINVAL;
+	}
+}
+
+/*
+ * Install a perf counter breakpoint.
+ */
+int arch_install_hw_breakpoint(struct perf_event *bp)
+{
+	struct arch_hw_breakpoint *info = counter_arch_bp(bp);
+	struct perf_event **slot, **slots;
+	struct debug_info *debug_info = &current->thread.debug;
+	int i, max_slots, ctrl_reg, val_reg, reg_enable;
+	u32 ctrl;
+
+	if (info->ctrl.type == ARM_BREAKPOINT_EXECUTE) {
+		/* Breakpoint */
+		ctrl_reg = AARCH64_DBG_REG_BCR;
+		val_reg = AARCH64_DBG_REG_BVR;
+		slots = __get_cpu_var(bp_on_reg);
+		max_slots = core_num_brps;
+		reg_enable = !debug_info->bps_disabled;
+	} else {
+		/* Watchpoint */
+		ctrl_reg = AARCH64_DBG_REG_WCR;
+		val_reg = AARCH64_DBG_REG_WVR;
+		slots = __get_cpu_var(wp_on_reg);
+		max_slots = core_num_wrps;
+		reg_enable = !debug_info->wps_disabled;
+	}
+
+	for (i = 0; i < max_slots; ++i) {
+		slot = &slots[i];
+
+		if (!*slot) {
+			*slot = bp;
+			break;
+		}
+	}
+
+	if (WARN_ONCE(i == max_slots, "Can't find any breakpoint slot"))
+		return -ENOSPC;
+
+	/* Ensure debug monitors are enabled at the correct exception level.  */
+	enable_debug_monitors(debug_exception_level(info->ctrl.privilege));
+
+	/* Setup the address register. */
+	write_wb_reg(val_reg, i, info->address);
+
+	/* Setup the control register. */
+	ctrl = encode_ctrl_reg(info->ctrl);
+	write_wb_reg(ctrl_reg, i, reg_enable ? ctrl | 0x1 : ctrl & ~0x1);
+
+	return 0;
+}
+
+void arch_uninstall_hw_breakpoint(struct perf_event *bp)
+{
+	struct arch_hw_breakpoint *info = counter_arch_bp(bp);
+	struct perf_event **slot, **slots;
+	int i, max_slots, base;
+
+	if (info->ctrl.type == ARM_BREAKPOINT_EXECUTE) {
+		/* Breakpoint */
+		base = AARCH64_DBG_REG_BCR;
+		slots = __get_cpu_var(bp_on_reg);
+		max_slots = core_num_brps;
+	} else {
+		/* Watchpoint */
+		base = AARCH64_DBG_REG_WCR;
+		slots = __get_cpu_var(wp_on_reg);
+		max_slots = core_num_wrps;
+	}
+
+	/* Remove the breakpoint. */
+	for (i = 0; i < max_slots; ++i) {
+		slot = &slots[i];
+
+		if (*slot == bp) {
+			*slot = NULL;
+			break;
+		}
+	}
+
+	if (WARN_ONCE(i == max_slots, "Can't find any breakpoint slot"))
+		return;
+
+	/* Reset the control register. */
+	write_wb_reg(base, i, 0);
+
+	/* Release the debug monitors for the correct exception level.  */
+	disable_debug_monitors(debug_exception_level(info->ctrl.privilege));
+}
+
+static int get_hbp_len(u8 hbp_len)
+{
+	unsigned int len_in_bytes = 0;
+
+	switch (hbp_len) {
+	case ARM_BREAKPOINT_LEN_1:
+		len_in_bytes = 1;
+		break;
+	case ARM_BREAKPOINT_LEN_2:
+		len_in_bytes = 2;
+		break;
+	case ARM_BREAKPOINT_LEN_4:
+		len_in_bytes = 4;
+		break;
+	case ARM_BREAKPOINT_LEN_8:
+		len_in_bytes = 8;
+		break;
+	}
+
+	return len_in_bytes;
+}
+
+/*
+ * Check whether bp virtual address is in kernel space.
+ */
+int arch_check_bp_in_kernelspace(struct perf_event *bp)
+{
+	unsigned int len;
+	unsigned long va;
+	struct arch_hw_breakpoint *info = counter_arch_bp(bp);
+
+	va = info->address;
+	len = get_hbp_len(info->ctrl.len);
+
+	return (va >= TASK_SIZE) && ((va + len - 1) >= TASK_SIZE);
+}
+
+/*
+ * Extract generic type and length encodings from an arch_hw_breakpoint_ctrl.
+ * Hopefully this will disappear when ptrace can bypass the conversion
+ * to generic breakpoint descriptions.
+ */
+int arch_bp_generic_fields(struct arch_hw_breakpoint_ctrl ctrl,
+			   int *gen_len, int *gen_type)
+{
+	/* Type */
+	switch (ctrl.type) {
+	case ARM_BREAKPOINT_EXECUTE:
+		*gen_type = HW_BREAKPOINT_X;
+		break;
+	case ARM_BREAKPOINT_LOAD:
+		*gen_type = HW_BREAKPOINT_R;
+		break;
+	case ARM_BREAKPOINT_STORE:
+		*gen_type = HW_BREAKPOINT_W;
+		break;
+	case ARM_BREAKPOINT_LOAD | ARM_BREAKPOINT_STORE:
+		*gen_type = HW_BREAKPOINT_RW;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* Len */
+	switch (ctrl.len) {
+	case ARM_BREAKPOINT_LEN_1:
+		*gen_len = HW_BREAKPOINT_LEN_1;
+		break;
+	case ARM_BREAKPOINT_LEN_2:
+		*gen_len = HW_BREAKPOINT_LEN_2;
+		break;
+	case ARM_BREAKPOINT_LEN_4:
+		*gen_len = HW_BREAKPOINT_LEN_4;
+		break;
+	case ARM_BREAKPOINT_LEN_8:
+		*gen_len = HW_BREAKPOINT_LEN_8;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/*
+ * Construct an arch_hw_breakpoint from a perf_event.
+ */
+static int arch_build_bp_info(struct perf_event *bp)
+{
+	struct arch_hw_breakpoint *info = counter_arch_bp(bp);
+
+	/* Type */
+	switch (bp->attr.bp_type) {
+	case HW_BREAKPOINT_X:
+		info->ctrl.type = ARM_BREAKPOINT_EXECUTE;
+		break;
+	case HW_BREAKPOINT_R:
+		info->ctrl.type = ARM_BREAKPOINT_LOAD;
+		break;
+	case HW_BREAKPOINT_W:
+		info->ctrl.type = ARM_BREAKPOINT_STORE;
+		break;
+	case HW_BREAKPOINT_RW:
+		info->ctrl.type = ARM_BREAKPOINT_LOAD | ARM_BREAKPOINT_STORE;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* Len */
+	switch (bp->attr.bp_len) {
+	case HW_BREAKPOINT_LEN_1:
+		info->ctrl.len = ARM_BREAKPOINT_LEN_1;
+		break;
+	case HW_BREAKPOINT_LEN_2:
+		info->ctrl.len = ARM_BREAKPOINT_LEN_2;
+		break;
+	case HW_BREAKPOINT_LEN_4:
+		info->ctrl.len = ARM_BREAKPOINT_LEN_4;
+		break;
+	case HW_BREAKPOINT_LEN_8:
+		info->ctrl.len = ARM_BREAKPOINT_LEN_8;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/*
+	 * On AArch64, we only permit breakpoints of length 4, whereas
+	 * AArch32 also requires breakpoints of length 2 for Thumb.
+	 * Watchpoints can be of length 1, 2, 4 or 8 bytes.
+	 */
+	if (info->ctrl.type == ARM_BREAKPOINT_EXECUTE) {
+		if (is_compat_task()) {
+			if (info->ctrl.len != ARM_BREAKPOINT_LEN_2 &&
+			    info->ctrl.len != ARM_BREAKPOINT_LEN_4)
+				return -EINVAL;
+		} else if (info->ctrl.len != ARM_BREAKPOINT_LEN_4) {
+			/*
+			 * FIXME: Some tools (I'm looking at you perf) assume
+			 *	  that breakpoints should be sizeof(long). This
+			 *	  is nonsense. For now, we fix up the parameter
+			 *	  but we should probably return -EINVAL instead.
+			 */
+			info->ctrl.len = ARM_BREAKPOINT_LEN_4;
+		}
+	}
+
+	/* Address */
+	info->address = bp->attr.bp_addr;
+
+	/*
+	 * Privilege
+	 * Note that we disallow combined EL0/EL1 breakpoints because
+	 * that would complicate the stepping code.
+	 */
+	if (arch_check_bp_in_kernelspace(bp))
+		info->ctrl.privilege = AARCH64_BREAKPOINT_EL1;
+	else
+		info->ctrl.privilege = AARCH64_BREAKPOINT_EL0;
+
+	/* Enabled? */
+	info->ctrl.enabled = !bp->attr.disabled;
+
+	return 0;
+}
+
+/*
+ * Validate the arch-specific HW Breakpoint register settings.
+ */
+int arch_validate_hwbkpt_settings(struct perf_event *bp)
+{
+	struct arch_hw_breakpoint *info = counter_arch_bp(bp);
+	int ret;
+	u64 alignment_mask, offset;
+
+	/* Build the arch_hw_breakpoint. */
+	ret = arch_build_bp_info(bp);
+	if (ret)
+		return ret;
+
+	/*
+	 * Check address alignment.
+	 * We don't do any clever alignment correction for watchpoints
+	 * because using 64-bit unaligned addresses is deprecated for
+	 * AArch64.
+	 *
+	 * AArch32 tasks expect some simple alignment fixups, so emulate
+	 * that here.
+	 */
+	if (is_compat_task()) {
+		if (info->ctrl.len == ARM_BREAKPOINT_LEN_8)
+			alignment_mask = 0x7;
+		else
+			alignment_mask = 0x3;
+		offset = info->address & alignment_mask;
+		switch (offset) {
+		case 0:
+			/* Aligned */
+			break;
+		case 1:
+			/* Allow single byte watchpoint. */
+			if (info->ctrl.len == ARM_BREAKPOINT_LEN_1)
+				break;
+		case 2:
+			/* Allow halfword watchpoints and breakpoints. */
+			if (info->ctrl.len == ARM_BREAKPOINT_LEN_2)
+				break;
+		default:
+			return -EINVAL;
+		}
+
+		info->address &= ~alignment_mask;
+		info->ctrl.len <<= offset;
+	} else {
+		if (info->ctrl.type == ARM_BREAKPOINT_EXECUTE)
+			alignment_mask = 0x3;
+		else
+			alignment_mask = 0x7;
+		if (info->address & alignment_mask)
+			return -EINVAL;
+	}
+
+	/*
+	 * Disallow per-task kernel breakpoints since these would
+	 * complicate the stepping code.
+	 */
+	if (info->ctrl.privilege == AARCH64_BREAKPOINT_EL1 && bp->hw.bp_target)
+		return -EINVAL;
+
+	return 0;
+}
+
+/*
+ * Enable/disable all of the breakpoints active at the specified
+ * exception level at the register level.
+ * This is used when single-stepping after a breakpoint exception.
+ */
+static void toggle_bp_registers(int reg, enum debug_el el, int enable)
+{
+	int i, max_slots, privilege;
+	u32 ctrl;
+	struct perf_event **slots;
+
+	switch (reg) {
+	case AARCH64_DBG_REG_BCR:
+		slots = __get_cpu_var(bp_on_reg);
+		max_slots = core_num_brps;
+		break;
+	case AARCH64_DBG_REG_WCR:
+		slots = __get_cpu_var(wp_on_reg);
+		max_slots = core_num_wrps;
+		break;
+	default:
+		return;
+	}
+
+	for (i = 0; i < max_slots; ++i) {
+		if (!slots[i])
+			continue;
+
+		privilege = counter_arch_bp(slots[i])->ctrl.privilege;
+		if (debug_exception_level(privilege) != el)
+			continue;
+
+		ctrl = read_wb_reg(reg, i);
+		if (enable)
+			ctrl |= 0x1;
+		else
+			ctrl &= ~0x1;
+		write_wb_reg(reg, i, ctrl);
+	}
+}
+
+/*
+ * Debug exception handlers.
+ */
+static int breakpoint_handler(unsigned long unused, unsigned int esr,
+			      struct pt_regs *regs)
+{
+	int i, step = 0, *kernel_step;
+	u32 ctrl_reg;
+	u64 addr, val;
+	struct perf_event *bp, **slots;
+	struct debug_info *debug_info;
+	struct arch_hw_breakpoint_ctrl ctrl;
+
+	slots = (struct perf_event **)__get_cpu_var(bp_on_reg);
+	addr = instruction_pointer(regs);
+	debug_info = &current->thread.debug;
+
+	for (i = 0; i < core_num_brps; ++i) {
+		rcu_read_lock();
+
+		bp = slots[i];
+
+		if (bp == NULL)
+			goto unlock;
+
+		/* Check if the breakpoint value matches. */
+		val = read_wb_reg(AARCH64_DBG_REG_BVR, i);
+		if (val != (addr & ~0x3))
+			goto unlock;
+
+		/* Possible match, check the byte address select to confirm. */
+		ctrl_reg = read_wb_reg(AARCH64_DBG_REG_BCR, i);
+		decode_ctrl_reg(ctrl_reg, &ctrl);
+		if (!((1 << (addr & 0x3)) & ctrl.len))
+			goto unlock;
+
+		counter_arch_bp(bp)->trigger = addr;
+		perf_bp_event(bp, regs);
+
+		/* Do we need to handle the stepping? */
+		if (!bp->overflow_handler)
+			step = 1;
+unlock:
+		rcu_read_unlock();
+	}
+
+	if (!step)
+		return 0;
+
+	if (user_mode(regs)) {
+		debug_info->bps_disabled = 1;
+		toggle_bp_registers(AARCH64_DBG_REG_BCR, DBG_ACTIVE_EL0, 0);
+
+		/* If we're already stepping a watchpoint, just return. */
+		if (debug_info->wps_disabled)
+			return 0;
+
+		if (test_thread_flag(TIF_SINGLESTEP))
+			debug_info->suspended_step = 1;
+		else
+			user_enable_single_step(current);
+	} else {
+		toggle_bp_registers(AARCH64_DBG_REG_BCR, DBG_ACTIVE_EL1, 0);
+		kernel_step = &__get_cpu_var(stepping_kernel_bp);
+
+		if (*kernel_step != ARM_KERNEL_STEP_NONE)
+			return 0;
+
+		if (kernel_active_single_step()) {
+			*kernel_step = ARM_KERNEL_STEP_SUSPEND;
+		} else {
+			*kernel_step = ARM_KERNEL_STEP_ACTIVE;
+			kernel_enable_single_step(regs);
+		}
+	}
+
+	return 0;
+}
+
+static int watchpoint_handler(unsigned long addr, unsigned int esr,
+			      struct pt_regs *regs)
+{
+	int i, step = 0, *kernel_step, access;
+	u32 ctrl_reg;
+	u64 val, alignment_mask;
+	struct perf_event *wp, **slots;
+	struct debug_info *debug_info;
+	struct arch_hw_breakpoint *info;
+	struct arch_hw_breakpoint_ctrl ctrl;
+
+	slots = (struct perf_event **)__get_cpu_var(wp_on_reg);
+	debug_info = &current->thread.debug;
+
+	for (i = 0; i < core_num_wrps; ++i) {
+		rcu_read_lock();
+
+		wp = slots[i];
+
+		if (wp == NULL)
+			goto unlock;
+
+		info = counter_arch_bp(wp);
+		/* AArch32 watchpoints are either 4 or 8 bytes aligned. */
+		if (is_compat_task()) {
+			if (info->ctrl.len == ARM_BREAKPOINT_LEN_8)
+				alignment_mask = 0x7;
+			else
+				alignment_mask = 0x3;
+		} else {
+			alignment_mask = 0x7;
+		}
+
+		/* Check if the watchpoint value matches. */
+		val = read_wb_reg(AARCH64_DBG_REG_WVR, i);
+		if (val != (addr & ~alignment_mask))
+			goto unlock;
+
+		/* Possible match, check the byte address select to confirm. */
+		ctrl_reg = read_wb_reg(AARCH64_DBG_REG_WCR, i);
+		decode_ctrl_reg(ctrl_reg, &ctrl);
+		if (!((1 << (addr & alignment_mask)) & ctrl.len))
+			goto unlock;
+
+		/*
+		 * Check that the access type matches.
+		 * 0 => load, otherwise => store
+		 */
+		access = (esr & AARCH64_ESR_ACCESS_MASK) ? HW_BREAKPOINT_W :
+			 HW_BREAKPOINT_R;
+		if (!(access & hw_breakpoint_type(wp)))
+			goto unlock;
+
+		info->trigger = addr;
+		perf_bp_event(wp, regs);
+
+		/* Do we need to handle the stepping? */
+		if (!wp->overflow_handler)
+			step = 1;
+
+unlock:
+		rcu_read_unlock();
+	}
+
+	if (!step)
+		return 0;
+
+	/*
+	 * We always disable EL0 watchpoints because the kernel can
+	 * cause these to fire via an unprivileged access.
+	 */
+	toggle_bp_registers(AARCH64_DBG_REG_WCR, DBG_ACTIVE_EL0, 0);
+
+	if (user_mode(regs)) {
+		debug_info->wps_disabled = 1;
+
+		/* If we're already stepping a breakpoint, just return. */
+		if (debug_info->bps_disabled)
+			return 0;
+
+		if (test_thread_flag(TIF_SINGLESTEP))
+			debug_info->suspended_step = 1;
+		else
+			user_enable_single_step(current);
+	} else {
+		toggle_bp_registers(AARCH64_DBG_REG_WCR, DBG_ACTIVE_EL1, 0);
+		kernel_step = &__get_cpu_var(stepping_kernel_bp);
+
+		if (*kernel_step != ARM_KERNEL_STEP_NONE)
+			return 0;
+
+		if (kernel_active_single_step()) {
+			*kernel_step = ARM_KERNEL_STEP_SUSPEND;
+		} else {
+			*kernel_step = ARM_KERNEL_STEP_ACTIVE;
+			kernel_enable_single_step(regs);
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * Handle single-step exception.
+ */
+int reinstall_suspended_bps(struct pt_regs *regs)
+{
+	struct debug_info *debug_info = &current->thread.debug;
+	int handled_exception = 0, *kernel_step;
+
+	kernel_step = &__get_cpu_var(stepping_kernel_bp);
+
+	/*
+	 * Called from single-step exception handler.
+	 * Return 0 if execution can resume, 1 if a SIGTRAP should be
+	 * reported.
+	 */
+	if (user_mode(regs)) {
+		if (debug_info->bps_disabled) {
+			debug_info->bps_disabled = 0;
+			toggle_bp_registers(AARCH64_DBG_REG_BCR, DBG_ACTIVE_EL0, 1);
+			handled_exception = 1;
+		}
+
+		if (debug_info->wps_disabled) {
+			debug_info->wps_disabled = 0;
+			toggle_bp_registers(AARCH64_DBG_REG_WCR, DBG_ACTIVE_EL0, 1);
+			handled_exception = 1;
+		}
+
+		if (handled_exception) {
+			if (debug_info->suspended_step) {
+				debug_info->suspended_step = 0;
+				/* Allow exception handling to fall-through. */
+				handled_exception = 0;
+			} else {
+				user_disable_single_step(current);
+			}
+		}
+	} else if (*kernel_step != ARM_KERNEL_STEP_NONE) {
+		toggle_bp_registers(AARCH64_DBG_REG_BCR, DBG_ACTIVE_EL1, 1);
+		toggle_bp_registers(AARCH64_DBG_REG_WCR, DBG_ACTIVE_EL1, 1);
+
+		if (!debug_info->wps_disabled)
+			toggle_bp_registers(AARCH64_DBG_REG_WCR, DBG_ACTIVE_EL0, 1);
+
+		if (*kernel_step != ARM_KERNEL_STEP_SUSPEND) {
+			kernel_disable_single_step();
+			handled_exception = 1;
+		} else {
+			handled_exception = 0;
+		}
+
+		*kernel_step = ARM_KERNEL_STEP_NONE;
+	}
+
+	return !handled_exception;
+}
+
+/*
+ * Context-switcher for restoring suspended breakpoints.
+ */
+void hw_breakpoint_thread_switch(struct task_struct *next)
+{
+	/*
+	 *           current        next
+	 * disabled: 0              0     => The usual case, NOTIFY_DONE
+	 *           0              1     => Disable the registers
+	 *           1              0     => Enable the registers
+	 *           1              1     => NOTIFY_DONE. per-task bps will
+	 *                                   get taken care of by perf.
+	 */
+
+	struct debug_info *current_debug_info, *next_debug_info;
+
+	current_debug_info = &current->thread.debug;
+	next_debug_info = &next->thread.debug;
+
+	/* Update breakpoints. */
+	if (current_debug_info->bps_disabled != next_debug_info->bps_disabled)
+		toggle_bp_registers(AARCH64_DBG_REG_BCR,
+				    DBG_ACTIVE_EL0,
+				    !next_debug_info->bps_disabled);
+
+	/* Update watchpoints. */
+	if (current_debug_info->wps_disabled != next_debug_info->wps_disabled)
+		toggle_bp_registers(AARCH64_DBG_REG_WCR,
+				    DBG_ACTIVE_EL0,
+				    !next_debug_info->wps_disabled);
+}
+
+/*
+ * CPU initialisation.
+ */
+static void reset_ctrl_regs(void *unused)
+{
+	int i;
+
+	for (i = 0; i < core_num_brps; ++i) {
+		write_wb_reg(AARCH64_DBG_REG_BCR, i, 0UL);
+		write_wb_reg(AARCH64_DBG_REG_BVR, i, 0UL);
+	}
+
+	for (i = 0; i < core_num_wrps; ++i) {
+		write_wb_reg(AARCH64_DBG_REG_WCR, i, 0UL);
+		write_wb_reg(AARCH64_DBG_REG_WVR, i, 0UL);
+	}
+}
+
+static int __cpuinit hw_breakpoint_reset_notify(struct notifier_block *self,
+						unsigned long action,
+						void *hcpu)
+{
+	int cpu = (long)hcpu;
+	if (action == CPU_ONLINE)
+		smp_call_function_single(cpu, reset_ctrl_regs, NULL, 1);
+	return NOTIFY_OK;
+}
+
+static struct notifier_block __cpuinitdata hw_breakpoint_reset_nb = {
+	.notifier_call = hw_breakpoint_reset_notify,
+};
+
+/*
+ * One-time initialisation.
+ */
+static int __init arch_hw_breakpoint_init(void)
+{
+	core_num_brps = get_num_brps();
+	core_num_wrps = get_num_wrps();
+
+	pr_info("found %d breakpoint and %d watchpoint registers.\n",
+		core_num_brps, core_num_wrps);
+
+	/*
+	 * Reset the breakpoint resources. We assume that a halting
+	 * debugger will leave the world in a nice state for us.
+	 */
+	smp_call_function(reset_ctrl_regs, NULL, 1);
+	reset_ctrl_regs(NULL);
+
+	/* Register debug fault handlers. */
+	hook_debug_fault_code(DBG_ESR_EVT_HWBP, breakpoint_handler, SIGTRAP,
+			      TRAP_HWBKPT, "hw-breakpoint handler");
+	hook_debug_fault_code(DBG_ESR_EVT_HWWP, watchpoint_handler, SIGTRAP,
+			      TRAP_HWBKPT, "hw-watchpoint handler");
+
+	/* Register hotplug notifier. */
+	register_cpu_notifier(&hw_breakpoint_reset_nb);
+
+	return 0;
+}
+arch_initcall(arch_hw_breakpoint_init);
+
+void hw_breakpoint_pmu_read(struct perf_event *bp)
+{
+}
+
+/*
+ * Dummy function to register with die_notifier.
+ */
+int hw_breakpoint_exceptions_notify(struct notifier_block *unused,
+				    unsigned long val, void *data)
+{
+	return NOTIFY_DONE;
+}
diff --git a/arch/arm64/kernel/io.c b/arch/arm64/kernel/io.c
new file mode 100644
index 0000000..7d37ead
--- /dev/null
+++ b/arch/arm64/kernel/io.c
@@ -0,0 +1,64 @@
+/*
+ * Based on arch/arm/kernel/io.c
+ *
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/export.h>
+#include <linux/types.h>
+#include <linux/io.h>
+
+/*
+ * Copy data from IO memory space to "real" memory space.
+ */
+void __memcpy_fromio(void *to, const volatile void __iomem *from, size_t count)
+{
+	unsigned char *t = to;
+	while (count) {
+		count--;
+		*t = readb(from);
+		t++;
+		from++;
+	}
+}
+EXPORT_SYMBOL(__memcpy_fromio);
+
+/*
+ * Copy data from "real" memory space to IO memory space.
+ */
+void __memcpy_toio(volatile void __iomem *to, const void *from, size_t count)
+{
+	const unsigned char *f = from;
+	while (count) {
+		count--;
+		writeb(*f, to);
+		f++;
+		to++;
+	}
+}
+EXPORT_SYMBOL(__memcpy_toio);
+
+/*
+ * "memset" on IO memory space.
+ */
+void __memset_io(volatile void __iomem *dst, int c, size_t count)
+{
+	while (count) {
+		count--;
+		writeb(c, dst);
+		dst++;
+	}
+}
+EXPORT_SYMBOL(__memset_io);
diff --git a/arch/arm64/kernel/irq.c b/arch/arm64/kernel/irq.c
new file mode 100644
index 0000000..0373c66
--- /dev/null
+++ b/arch/arm64/kernel/irq.c
@@ -0,0 +1,84 @@
+/*
+ * Based on arch/arm/kernel/irq.c
+ *
+ * Copyright (C) 1992 Linus Torvalds
+ * Modifications for ARM processor Copyright (C) 1995-2000 Russell King.
+ * Support for Dynamic Tick Timer Copyright (C) 2004-2005 Nokia Corporation.
+ * Dynamic Tick Timer written by Tony Lindgren <tony@atomide.com> and
+ * Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>.
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel_stat.h>
+#include <linux/irq.h>
+#include <linux/smp.h>
+#include <linux/init.h>
+#include <linux/of_irq.h>
+#include <linux/seq_file.h>
+#include <linux/ratelimit.h>
+
+unsigned long irq_err_count;
+
+int arch_show_interrupts(struct seq_file *p, int prec)
+{
+#ifdef CONFIG_SMP
+	show_ipi_list(p, prec);
+#endif
+	seq_printf(p, "%*s: %10lu\n", prec, "Err", irq_err_count);
+	return 0;
+}
+
+/*
+ * handle_IRQ handles all hardware IRQ's.  Decoded IRQs should
+ * not come via this function.  Instead, they should provide their
+ * own 'handler'.  Used by platform code implementing C-based 1st
+ * level decoding.
+ */
+void handle_IRQ(unsigned int irq, struct pt_regs *regs)
+{
+	struct pt_regs *old_regs = set_irq_regs(regs);
+
+	irq_enter();
+
+	/*
+	 * Some hardware gives randomly wrong interrupts.  Rather
+	 * than crashing, do something sensible.
+	 */
+	if (unlikely(irq >= nr_irqs)) {
+		pr_warn_ratelimited("Bad IRQ%u\n", irq);
+		ack_bad_irq(irq);
+	} else {
+		generic_handle_irq(irq);
+	}
+
+	irq_exit();
+	set_irq_regs(old_regs);
+}
+
+/*
+ * Interrupt controllers supported by the kernel.
+ */
+static const struct of_device_id intctrl_of_match[] __initconst = {
+	/* IRQ controllers { .compatible, .data } info to go here */
+	{}
+};
+
+void __init init_IRQ(void)
+{
+	of_irq_init(intctrl_of_match);
+
+	if (!handle_arch_irq)
+		panic("No interrupt controller found.");
+}
diff --git a/arch/arm64/kernel/kuser32.S b/arch/arm64/kernel/kuser32.S
new file mode 100644
index 0000000..8b69ecb
--- /dev/null
+++ b/arch/arm64/kernel/kuser32.S
@@ -0,0 +1,77 @@
+/*
+ * Low-level user helpers placed in the vectors page for AArch32.
+ * Based on the kuser helpers in arch/arm/kernel/entry-armv.S.
+ *
+ * Copyright (C) 2005-2011 Nicolas Pitre <nico@fluxnic.net>
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *
+ * AArch32 user helpers.
+ *
+ * Each segment is 32-byte aligned and will be moved to the top of the high
+ * vector page.  New segments (if ever needed) must be added in front of
+ * existing ones.  This mechanism should be used only for things that are
+ * really small and justified, and not be abused freely.
+ *
+ * See Documentation/arm/kernel_user_helpers.txt for formal definitions.
+ */
+	.align	5
+	.globl	__kuser_helper_start
+__kuser_helper_start:
+
+__kuser_cmpxchg64:			// 0xffff0f60
+	.inst	0xe92d00f0		//	push		{r4, r5, r6, r7}
+	.inst	0xe1c040d0		//	ldrd		r4, r5, [r0]
+	.inst	0xe1c160d0		//	ldrd		r6, r7, [r1]
+	.inst	0xf57ff05f		//	dmb		sy
+	.inst	0xe1b20f9f		// 1:	ldrexd		r0, r1, [r2]
+	.inst	0xe0303004		//	eors		r3, r0, r4
+	.inst	0x00313005		//	eoreqs		r3, r1, r5
+	.inst	0x01a23f96		//	strexdeq	r3, r6, [r2]
+	.inst	0x03330001		//	teqeq		r3, #1
+	.inst	0x0afffff9		//	beq		1b
+	.inst	0xf57ff05f		//	dmb		sy
+	.inst	0xe2730000		//	rsbs		r0, r3, #0
+	.inst	0xe8bd00f0		//	pop		{r4, r5, r6, r7}
+	.inst	0xe12fff1e		//	bx		lr
+
+	.align	5
+__kuser_memory_barrier:			// 0xffff0fa0
+	.inst	0xf57ff05f		//	dmb		sy
+	.inst	0xe12fff1e		//	bx		lr
+
+	.align	5
+__kuser_cmpxchg:			// 0xffff0fc0
+	.inst	0xf57ff05f		//	dmb		sy
+	.inst	0xe1923f9f		// 1:	ldrex		r3, [r2]
+	.inst	0xe0533000		//	subs		r3, r3, r0
+	.inst	0x01823f91		//	strexeq	r3, r1, [r2]
+	.inst	0x03330001		//	teqeq		r3, #1
+	.inst	0x0afffffa		//	beq		1b
+	.inst	0xe2730000		//	rsbs		r0, r3, #0
+	.inst	0xeaffffef		//	b		<__kuser_memory_barrier>
+
+	.align	5
+__kuser_get_tls:			// 0xffff0fe0
+	.inst	0xee1d0f70		//	mrc		p15, 0, r0, c13, c0, 3
+	.inst	0xe12fff1e		//	bx		lr
+	.rep	5
+	.word	0
+	.endr
+
+__kuser_helper_version:			// 0xffff0ffc
+	.word	((__kuser_helper_end - __kuser_helper_start) >> 5)
+	.globl	__kuser_helper_end
+__kuser_helper_end:
diff --git a/arch/arm64/kernel/module.c b/arch/arm64/kernel/module.c
new file mode 100644
index 0000000..ca0e3d5
--- /dev/null
+++ b/arch/arm64/kernel/module.c
@@ -0,0 +1,456 @@
+/*
+ * AArch64 loadable module support.
+ *
+ * Copyright (C) 2012 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Will Deacon <will.deacon@arm.com>
+ */
+
+#include <linux/bitops.h>
+#include <linux/elf.h>
+#include <linux/gfp.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/moduleloader.h>
+#include <linux/vmalloc.h>
+
+void *module_alloc(unsigned long size)
+{
+	return __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END,
+				    GFP_KERNEL, PAGE_KERNEL_EXEC, -1,
+				    __builtin_return_address(0));
+}
+
+enum aarch64_reloc_op {
+	RELOC_OP_NONE,
+	RELOC_OP_ABS,
+	RELOC_OP_PREL,
+	RELOC_OP_PAGE,
+};
+
+static u64 do_reloc(enum aarch64_reloc_op reloc_op, void *place, u64 val)
+{
+	switch (reloc_op) {
+	case RELOC_OP_ABS:
+		return val;
+	case RELOC_OP_PREL:
+		return val - (u64)place;
+	case RELOC_OP_PAGE:
+		return (val & ~0xfff) - ((u64)place & ~0xfff);
+	case RELOC_OP_NONE:
+		return 0;
+	}
+
+	pr_err("do_reloc: unknown relocation operation %d\n", reloc_op);
+	return 0;
+}
+
+static int reloc_data(enum aarch64_reloc_op op, void *place, u64 val, int len)
+{
+	u64 imm_mask = (1 << len) - 1;
+	s64 sval = do_reloc(op, place, val);
+
+	switch (len) {
+	case 16:
+		*(s16 *)place = sval;
+		break;
+	case 32:
+		*(s32 *)place = sval;
+		break;
+	case 64:
+		*(s64 *)place = sval;
+		break;
+	default:
+		pr_err("Invalid length (%d) for data relocation\n", len);
+		return 0;
+	}
+
+	/*
+	 * Extract the upper value bits (including the sign bit) and
+	 * shift them to bit 0.
+	 */
+	sval = (s64)(sval & ~(imm_mask >> 1)) >> (len - 1);
+
+	/*
+	 * Overflow has occurred if the value is not representable in
+	 * len bits (i.e the bottom len bits are not sign-extended and
+	 * the top bits are not all zero).
+	 */
+	if ((u64)(sval + 1) > 2)
+		return -ERANGE;
+
+	return 0;
+}
+
+enum aarch64_imm_type {
+	INSN_IMM_MOVNZ,
+	INSN_IMM_MOVK,
+	INSN_IMM_ADR,
+	INSN_IMM_26,
+	INSN_IMM_19,
+	INSN_IMM_16,
+	INSN_IMM_14,
+	INSN_IMM_12,
+	INSN_IMM_9,
+};
+
+static u32 encode_insn_immediate(enum aarch64_imm_type type, u32 insn, u64 imm)
+{
+	u32 immlo, immhi, lomask, himask, mask;
+	int shift;
+
+	switch (type) {
+	case INSN_IMM_MOVNZ:
+		/*
+		 * For signed MOVW relocations, we have to manipulate the
+		 * instruction encoding depending on whether or not the
+		 * immediate is less than zero.
+		 */
+		insn &= ~(3 << 29);
+		if ((s64)imm >= 0) {
+			/* >=0: Set the instruction to MOVZ (opcode 10b). */
+			insn |= 2 << 29;
+		} else {
+			/*
+			 * <0: Set the instruction to MOVN (opcode 00b).
+			 *     Since we've masked the opcode already, we
+			 *     don't need to do anything other than
+			 *     inverting the new immediate field.
+			 */
+			imm = ~imm;
+		}
+	case INSN_IMM_MOVK:
+		mask = BIT(16) - 1;
+		shift = 5;
+		break;
+	case INSN_IMM_ADR:
+		lomask = 0x3;
+		himask = 0x7ffff;
+		immlo = imm & lomask;
+		imm >>= 2;
+		immhi = imm & himask;
+		imm = (immlo << 24) | (immhi);
+		mask = (lomask << 24) | (himask);
+		shift = 5;
+		break;
+	case INSN_IMM_26:
+		mask = BIT(26) - 1;
+		shift = 0;
+		break;
+	case INSN_IMM_19:
+		mask = BIT(19) - 1;
+		shift = 5;
+		break;
+	case INSN_IMM_16:
+		mask = BIT(16) - 1;
+		shift = 5;
+		break;
+	case INSN_IMM_14:
+		mask = BIT(14) - 1;
+		shift = 5;
+		break;
+	case INSN_IMM_12:
+		mask = BIT(12) - 1;
+		shift = 10;
+		break;
+	case INSN_IMM_9:
+		mask = BIT(9) - 1;
+		shift = 12;
+		break;
+	default:
+		pr_err("encode_insn_immediate: unknown immediate encoding %d\n",
+			type);
+		return 0;
+	}
+
+	/* Update the immediate field. */
+	insn &= ~(mask << shift);
+	insn |= (imm & mask) << shift;
+
+	return insn;
+}
+
+static int reloc_insn_movw(enum aarch64_reloc_op op, void *place, u64 val,
+			   int lsb, enum aarch64_imm_type imm_type)
+{
+	u64 imm, limit = 0;
+	s64 sval;
+	u32 insn = *(u32 *)place;
+
+	sval = do_reloc(op, place, val);
+	sval >>= lsb;
+	imm = sval & 0xffff;
+
+	/* Update the instruction with the new encoding. */
+	*(u32 *)place = encode_insn_immediate(imm_type, insn, imm);
+
+	/* Shift out the immediate field. */
+	sval >>= 16;
+
+	/*
+	 * For unsigned immediates, the overflow check is straightforward.
+	 * For signed immediates, the sign bit is actually the bit past the
+	 * most significant bit of the field.
+	 * The INSN_IMM_16 immediate type is unsigned.
+	 */
+	if (imm_type != INSN_IMM_16) {
+		sval++;
+		limit++;
+	}
+
+	/* Check the upper bits depending on the sign of the immediate. */
+	if ((u64)sval > limit)
+		return -ERANGE;
+
+	return 0;
+}
+
+static int reloc_insn_imm(enum aarch64_reloc_op op, void *place, u64 val,
+			  int lsb, int len, enum aarch64_imm_type imm_type)
+{
+	u64 imm, imm_mask;
+	s64 sval;
+	u32 insn = *(u32 *)place;
+
+	/* Calculate the relocation value. */
+	sval = do_reloc(op, place, val);
+	sval >>= lsb;
+
+	/* Extract the value bits and shift them to bit 0. */
+	imm_mask = (BIT(lsb + len) - 1) >> lsb;
+	imm = sval & imm_mask;
+
+	/* Update the instruction's immediate field. */
+	*(u32 *)place = encode_insn_immediate(imm_type, insn, imm);
+
+	/*
+	 * Extract the upper value bits (including the sign bit) and
+	 * shift them to bit 0.
+	 */
+	sval = (s64)(sval & ~(imm_mask >> 1)) >> (len - 1);
+
+	/*
+	 * Overflow has occurred if the upper bits are not all equal to
+	 * the sign bit of the value.
+	 */
+	if ((u64)(sval + 1) >= 2)
+		return -ERANGE;
+
+	return 0;
+}
+
+int apply_relocate_add(Elf64_Shdr *sechdrs,
+		       const char *strtab,
+		       unsigned int symindex,
+		       unsigned int relsec,
+		       struct module *me)
+{
+	unsigned int i;
+	int ovf;
+	bool overflow_check;
+	Elf64_Sym *sym;
+	void *loc;
+	u64 val;
+	Elf64_Rela *rel = (void *)sechdrs[relsec].sh_addr;
+
+	for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
+		/* loc corresponds to P in the AArch64 ELF document. */
+		loc = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
+			+ rel[i].r_offset;
+
+		/* sym is the ELF symbol we're referring to. */
+		sym = (Elf64_Sym *)sechdrs[symindex].sh_addr
+			+ ELF64_R_SYM(rel[i].r_info);
+
+		/* val corresponds to (S + A) in the AArch64 ELF document. */
+		val = sym->st_value + rel[i].r_addend;
+
+		/* Check for overflow by default. */
+		overflow_check = true;
+
+		/* Perform the static relocation. */
+		switch (ELF64_R_TYPE(rel[i].r_info)) {
+		/* Null relocations. */
+		case R_ARM_NONE:
+		case R_AARCH64_NONE:
+			ovf = 0;
+			break;
+
+		/* Data relocations. */
+		case R_AARCH64_ABS64:
+			overflow_check = false;
+			ovf = reloc_data(RELOC_OP_ABS, loc, val, 64);
+			break;
+		case R_AARCH64_ABS32:
+			ovf = reloc_data(RELOC_OP_ABS, loc, val, 32);
+			break;
+		case R_AARCH64_ABS16:
+			ovf = reloc_data(RELOC_OP_ABS, loc, val, 16);
+			break;
+		case R_AARCH64_PREL64:
+			overflow_check = false;
+			ovf = reloc_data(RELOC_OP_PREL, loc, val, 64);
+			break;
+		case R_AARCH64_PREL32:
+			ovf = reloc_data(RELOC_OP_PREL, loc, val, 32);
+			break;
+		case R_AARCH64_PREL16:
+			ovf = reloc_data(RELOC_OP_PREL, loc, val, 16);
+			break;
+
+		/* MOVW instruction relocations. */
+		case R_AARCH64_MOVW_UABS_G0_NC:
+			overflow_check = false;
+		case R_AARCH64_MOVW_UABS_G0:
+			ovf = reloc_insn_movw(RELOC_OP_ABS, loc, val, 0,
+					      INSN_IMM_16);
+			break;
+		case R_AARCH64_MOVW_UABS_G1_NC:
+			overflow_check = false;
+		case R_AARCH64_MOVW_UABS_G1:
+			ovf = reloc_insn_movw(RELOC_OP_ABS, loc, val, 16,
+					      INSN_IMM_16);
+			break;
+		case R_AARCH64_MOVW_UABS_G2_NC:
+			overflow_check = false;
+		case R_AARCH64_MOVW_UABS_G2:
+			ovf = reloc_insn_movw(RELOC_OP_ABS, loc, val, 32,
+					      INSN_IMM_16);
+			break;
+		case R_AARCH64_MOVW_UABS_G3:
+			/* We're using the top bits so we can't overflow. */
+			overflow_check = false;
+			ovf = reloc_insn_movw(RELOC_OP_ABS, loc, val, 48,
+					      INSN_IMM_16);
+			break;
+		case R_AARCH64_MOVW_SABS_G0:
+			ovf = reloc_insn_movw(RELOC_OP_ABS, loc, val, 0,
+					      INSN_IMM_MOVNZ);
+			break;
+		case R_AARCH64_MOVW_SABS_G1:
+			ovf = reloc_insn_movw(RELOC_OP_ABS, loc, val, 16,
+					      INSN_IMM_MOVNZ);
+			break;
+		case R_AARCH64_MOVW_SABS_G2:
+			ovf = reloc_insn_movw(RELOC_OP_ABS, loc, val, 32,
+					      INSN_IMM_MOVNZ);
+			break;
+		case R_AARCH64_MOVW_PREL_G0_NC:
+			overflow_check = false;
+			ovf = reloc_insn_movw(RELOC_OP_PREL, loc, val, 0,
+					      INSN_IMM_MOVK);
+			break;
+		case R_AARCH64_MOVW_PREL_G0:
+			ovf = reloc_insn_movw(RELOC_OP_PREL, loc, val, 0,
+					      INSN_IMM_MOVNZ);
+			break;
+		case R_AARCH64_MOVW_PREL_G1_NC:
+			overflow_check = false;
+			ovf = reloc_insn_movw(RELOC_OP_PREL, loc, val, 16,
+					      INSN_IMM_MOVK);
+			break;
+		case R_AARCH64_MOVW_PREL_G1:
+			ovf = reloc_insn_movw(RELOC_OP_PREL, loc, val, 16,
+					      INSN_IMM_MOVNZ);
+			break;
+		case R_AARCH64_MOVW_PREL_G2_NC:
+			overflow_check = false;
+			ovf = reloc_insn_movw(RELOC_OP_PREL, loc, val, 32,
+					      INSN_IMM_MOVK);
+			break;
+		case R_AARCH64_MOVW_PREL_G2:
+			ovf = reloc_insn_movw(RELOC_OP_PREL, loc, val, 32,
+					      INSN_IMM_MOVNZ);
+			break;
+		case R_AARCH64_MOVW_PREL_G3:
+			/* We're using the top bits so we can't overflow. */
+			overflow_check = false;
+			ovf = reloc_insn_movw(RELOC_OP_PREL, loc, val, 48,
+					      INSN_IMM_MOVNZ);
+			break;
+
+		/* Immediate instruction relocations. */
+		case R_AARCH64_LD_PREL_LO19:
+			ovf = reloc_insn_imm(RELOC_OP_PREL, loc, val, 2, 19,
+					     INSN_IMM_19);
+			break;
+		case R_AARCH64_ADR_PREL_LO21:
+			ovf = reloc_insn_imm(RELOC_OP_PREL, loc, val, 0, 21,
+					     INSN_IMM_ADR);
+			break;
+		case R_AARCH64_ADR_PREL_PG_HI21_NC:
+			overflow_check = false;
+		case R_AARCH64_ADR_PREL_PG_HI21:
+			ovf = reloc_insn_imm(RELOC_OP_PAGE, loc, val, 12, 21,
+					     INSN_IMM_ADR);
+			break;
+		case R_AARCH64_ADD_ABS_LO12_NC:
+		case R_AARCH64_LDST8_ABS_LO12_NC:
+			overflow_check = false;
+			ovf = reloc_insn_imm(RELOC_OP_ABS, loc, val, 0, 12,
+					     INSN_IMM_12);
+			break;
+		case R_AARCH64_LDST16_ABS_LO12_NC:
+			overflow_check = false;
+			ovf = reloc_insn_imm(RELOC_OP_ABS, loc, val, 1, 11,
+					     INSN_IMM_12);
+			break;
+		case R_AARCH64_LDST32_ABS_LO12_NC:
+			overflow_check = false;
+			ovf = reloc_insn_imm(RELOC_OP_ABS, loc, val, 2, 10,
+					     INSN_IMM_12);
+			break;
+		case R_AARCH64_LDST64_ABS_LO12_NC:
+			overflow_check = false;
+			ovf = reloc_insn_imm(RELOC_OP_ABS, loc, val, 3, 9,
+					     INSN_IMM_12);
+			break;
+		case R_AARCH64_LDST128_ABS_LO12_NC:
+			overflow_check = false;
+			ovf = reloc_insn_imm(RELOC_OP_ABS, loc, val, 4, 8,
+					     INSN_IMM_12);
+			break;
+		case R_AARCH64_TSTBR14:
+			ovf = reloc_insn_imm(RELOC_OP_PREL, loc, val, 2, 14,
+					     INSN_IMM_14);
+			break;
+		case R_AARCH64_CONDBR19:
+			ovf = reloc_insn_imm(RELOC_OP_PREL, loc, val, 2, 19,
+					     INSN_IMM_19);
+			break;
+		case R_AARCH64_JUMP26:
+		case R_AARCH64_CALL26:
+			ovf = reloc_insn_imm(RELOC_OP_PREL, loc, val, 2, 26,
+					     INSN_IMM_26);
+			break;
+
+		default:
+			pr_err("module %s: unsupported RELA relocation: %llu\n",
+			       me->name, ELF64_R_TYPE(rel[i].r_info));
+			return -ENOEXEC;
+		}
+
+		if (overflow_check && ovf == -ERANGE)
+			goto overflow;
+
+	}
+
+	return 0;
+
+overflow:
+	pr_err("module %s: overflow in relocation type %d val %Lx\n",
+	       me->name, (int)ELF64_R_TYPE(rel[i].r_info), val);
+	return -ENOEXEC;
+}
diff --git a/arch/arm64/kernel/perf_event.c b/arch/arm64/kernel/perf_event.c
new file mode 100644
index 0000000..ecbf2d8
--- /dev/null
+++ b/arch/arm64/kernel/perf_event.c
@@ -0,0 +1,1368 @@
+/*
+ * PMU support
+ *
+ * Copyright (C) 2012 ARM Limited
+ * Author: Will Deacon <will.deacon@arm.com>
+ *
+ * This code is based heavily on the ARMv7 perf event 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#define pr_fmt(fmt) "hw perfevents: " fmt
+
+#include <linux/bitmap.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/export.h>
+#include <linux/perf_event.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/uaccess.h>
+
+#include <asm/cputype.h>
+#include <asm/irq.h>
+#include <asm/irq_regs.h>
+#include <asm/pmu.h>
+#include <asm/stacktrace.h>
+
+/*
+ * ARMv8 supports a maximum of 32 events.
+ * The cycle counter is included in this total.
+ */
+#define ARMPMU_MAX_HWEVENTS		32
+
+static DEFINE_PER_CPU(struct perf_event * [ARMPMU_MAX_HWEVENTS], hw_events);
+static DEFINE_PER_CPU(unsigned long [BITS_TO_LONGS(ARMPMU_MAX_HWEVENTS)], used_mask);
+static DEFINE_PER_CPU(struct pmu_hw_events, cpu_hw_events);
+
+#define to_arm_pmu(p) (container_of(p, struct arm_pmu, pmu))
+
+/* Set at runtime when we know what CPU type we are. */
+static struct arm_pmu *cpu_pmu;
+
+int
+armpmu_get_max_events(void)
+{
+	int max_events = 0;
+
+	if (cpu_pmu != NULL)
+		max_events = cpu_pmu->num_events;
+
+	return max_events;
+}
+EXPORT_SYMBOL_GPL(armpmu_get_max_events);
+
+int perf_num_counters(void)
+{
+	return armpmu_get_max_events();
+}
+EXPORT_SYMBOL_GPL(perf_num_counters);
+
+#define HW_OP_UNSUPPORTED		0xFFFF
+
+#define C(_x) \
+	PERF_COUNT_HW_CACHE_##_x
+
+#define CACHE_OP_UNSUPPORTED		0xFFFF
+
+static int
+armpmu_map_cache_event(const unsigned (*cache_map)
+				      [PERF_COUNT_HW_CACHE_MAX]
+				      [PERF_COUNT_HW_CACHE_OP_MAX]
+				      [PERF_COUNT_HW_CACHE_RESULT_MAX],
+		       u64 config)
+{
+	unsigned int cache_type, cache_op, cache_result, ret;
+
+	cache_type = (config >>  0) & 0xff;
+	if (cache_type >= PERF_COUNT_HW_CACHE_MAX)
+		return -EINVAL;
+
+	cache_op = (config >>  8) & 0xff;
+	if (cache_op >= PERF_COUNT_HW_CACHE_OP_MAX)
+		return -EINVAL;
+
+	cache_result = (config >> 16) & 0xff;
+	if (cache_result >= PERF_COUNT_HW_CACHE_RESULT_MAX)
+		return -EINVAL;
+
+	ret = (int)(*cache_map)[cache_type][cache_op][cache_result];
+
+	if (ret == CACHE_OP_UNSUPPORTED)
+		return -ENOENT;
+
+	return ret;
+}
+
+static int
+armpmu_map_event(const unsigned (*event_map)[PERF_COUNT_HW_MAX], u64 config)
+{
+	int mapping = (*event_map)[config];
+	return mapping == HW_OP_UNSUPPORTED ? -ENOENT : mapping;
+}
+
+static int
+armpmu_map_raw_event(u32 raw_event_mask, u64 config)
+{
+	return (int)(config & raw_event_mask);
+}
+
+static int map_cpu_event(struct perf_event *event,
+			 const unsigned (*event_map)[PERF_COUNT_HW_MAX],
+			 const unsigned (*cache_map)
+					[PERF_COUNT_HW_CACHE_MAX]
+					[PERF_COUNT_HW_CACHE_OP_MAX]
+					[PERF_COUNT_HW_CACHE_RESULT_MAX],
+			 u32 raw_event_mask)
+{
+	u64 config = event->attr.config;
+
+	switch (event->attr.type) {
+	case PERF_TYPE_HARDWARE:
+		return armpmu_map_event(event_map, config);
+	case PERF_TYPE_HW_CACHE:
+		return armpmu_map_cache_event(cache_map, config);
+	case PERF_TYPE_RAW:
+		return armpmu_map_raw_event(raw_event_mask, config);
+	}
+
+	return -ENOENT;
+}
+
+int
+armpmu_event_set_period(struct perf_event *event,
+			struct hw_perf_event *hwc,
+			int idx)
+{
+	struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
+	s64 left = local64_read(&hwc->period_left);
+	s64 period = hwc->sample_period;
+	int ret = 0;
+
+	if (unlikely(left <= -period)) {
+		left = period;
+		local64_set(&hwc->period_left, left);
+		hwc->last_period = period;
+		ret = 1;
+	}
+
+	if (unlikely(left <= 0)) {
+		left += period;
+		local64_set(&hwc->period_left, left);
+		hwc->last_period = period;
+		ret = 1;
+	}
+
+	if (left > (s64)armpmu->max_period)
+		left = armpmu->max_period;
+
+	local64_set(&hwc->prev_count, (u64)-left);
+
+	armpmu->write_counter(idx, (u64)(-left) & 0xffffffff);
+
+	perf_event_update_userpage(event);
+
+	return ret;
+}
+
+u64
+armpmu_event_update(struct perf_event *event,
+		    struct hw_perf_event *hwc,
+		    int idx)
+{
+	struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
+	u64 delta, prev_raw_count, new_raw_count;
+
+again:
+	prev_raw_count = local64_read(&hwc->prev_count);
+	new_raw_count = armpmu->read_counter(idx);
+
+	if (local64_cmpxchg(&hwc->prev_count, prev_raw_count,
+			     new_raw_count) != prev_raw_count)
+		goto again;
+
+	delta = (new_raw_count - prev_raw_count) & armpmu->max_period;
+
+	local64_add(delta, &event->count);
+	local64_sub(delta, &hwc->period_left);
+
+	return new_raw_count;
+}
+
+static void
+armpmu_read(struct perf_event *event)
+{
+	struct hw_perf_event *hwc = &event->hw;
+
+	/* Don't read disabled counters! */
+	if (hwc->idx < 0)
+		return;
+
+	armpmu_event_update(event, hwc, hwc->idx);
+}
+
+static void
+armpmu_stop(struct perf_event *event, int flags)
+{
+	struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
+	struct hw_perf_event *hwc = &event->hw;
+
+	/*
+	 * ARM pmu always has to update the counter, so ignore
+	 * PERF_EF_UPDATE, see comments in armpmu_start().
+	 */
+	if (!(hwc->state & PERF_HES_STOPPED)) {
+		armpmu->disable(hwc, hwc->idx);
+		barrier(); /* why? */
+		armpmu_event_update(event, hwc, hwc->idx);
+		hwc->state |= PERF_HES_STOPPED | PERF_HES_UPTODATE;
+	}
+}
+
+static void
+armpmu_start(struct perf_event *event, int flags)
+{
+	struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
+	struct hw_perf_event *hwc = &event->hw;
+
+	/*
+	 * ARM pmu always has to reprogram the period, so ignore
+	 * PERF_EF_RELOAD, see the comment below.
+	 */
+	if (flags & PERF_EF_RELOAD)
+		WARN_ON_ONCE(!(hwc->state & PERF_HES_UPTODATE));
+
+	hwc->state = 0;
+	/*
+	 * Set the period again. Some counters can't be stopped, so when we
+	 * were stopped we simply disabled the IRQ source and the counter
+	 * may have been left counting. If we don't do this step then we may
+	 * get an interrupt too soon or *way* too late if the overflow has
+	 * happened since disabling.
+	 */
+	armpmu_event_set_period(event, hwc, hwc->idx);
+	armpmu->enable(hwc, hwc->idx);
+}
+
+static void
+armpmu_del(struct perf_event *event, int flags)
+{
+	struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
+	struct pmu_hw_events *hw_events = armpmu->get_hw_events();
+	struct hw_perf_event *hwc = &event->hw;
+	int idx = hwc->idx;
+
+	WARN_ON(idx < 0);
+
+	armpmu_stop(event, PERF_EF_UPDATE);
+	hw_events->events[idx] = NULL;
+	clear_bit(idx, hw_events->used_mask);
+
+	perf_event_update_userpage(event);
+}
+
+static int
+armpmu_add(struct perf_event *event, int flags)
+{
+	struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
+	struct pmu_hw_events *hw_events = armpmu->get_hw_events();
+	struct hw_perf_event *hwc = &event->hw;
+	int idx;
+	int err = 0;
+
+	perf_pmu_disable(event->pmu);
+
+	/* If we don't have a space for the counter then finish early. */
+	idx = armpmu->get_event_idx(hw_events, hwc);
+	if (idx < 0) {
+		err = idx;
+		goto out;
+	}
+
+	/*
+	 * If there is an event in the counter we are going to use then make
+	 * sure it is disabled.
+	 */
+	event->hw.idx = idx;
+	armpmu->disable(hwc, idx);
+	hw_events->events[idx] = event;
+
+	hwc->state = PERF_HES_STOPPED | PERF_HES_UPTODATE;
+	if (flags & PERF_EF_START)
+		armpmu_start(event, PERF_EF_RELOAD);
+
+	/* Propagate our changes to the userspace mapping. */
+	perf_event_update_userpage(event);
+
+out:
+	perf_pmu_enable(event->pmu);
+	return err;
+}
+
+static int
+validate_event(struct pmu_hw_events *hw_events,
+	       struct perf_event *event)
+{
+	struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
+	struct hw_perf_event fake_event = event->hw;
+	struct pmu *leader_pmu = event->group_leader->pmu;
+
+	if (event->pmu != leader_pmu || event->state <= PERF_EVENT_STATE_OFF)
+		return 1;
+
+	return armpmu->get_event_idx(hw_events, &fake_event) >= 0;
+}
+
+static int
+validate_group(struct perf_event *event)
+{
+	struct perf_event *sibling, *leader = event->group_leader;
+	struct pmu_hw_events fake_pmu;
+	DECLARE_BITMAP(fake_used_mask, ARMPMU_MAX_HWEVENTS);
+
+	/*
+	 * Initialise the fake PMU. We only need to populate the
+	 * used_mask for the purposes of validation.
+	 */
+	memset(fake_used_mask, 0, sizeof(fake_used_mask));
+	fake_pmu.used_mask = fake_used_mask;
+
+	if (!validate_event(&fake_pmu, leader))
+		return -EINVAL;
+
+	list_for_each_entry(sibling, &leader->sibling_list, group_entry) {
+		if (!validate_event(&fake_pmu, sibling))
+			return -EINVAL;
+	}
+
+	if (!validate_event(&fake_pmu, event))
+		return -EINVAL;
+
+	return 0;
+}
+
+static void
+armpmu_release_hardware(struct arm_pmu *armpmu)
+{
+	int i, irq, irqs;
+	struct platform_device *pmu_device = armpmu->plat_device;
+
+	irqs = min(pmu_device->num_resources, num_possible_cpus());
+
+	for (i = 0; i < irqs; ++i) {
+		if (!cpumask_test_and_clear_cpu(i, &armpmu->active_irqs))
+			continue;
+		irq = platform_get_irq(pmu_device, i);
+		if (irq >= 0)
+			free_irq(irq, armpmu);
+	}
+}
+
+static int
+armpmu_reserve_hardware(struct arm_pmu *armpmu)
+{
+	int i, err, irq, irqs;
+	struct platform_device *pmu_device = armpmu->plat_device;
+
+	if (!pmu_device) {
+		pr_err("no PMU device registered\n");
+		return -ENODEV;
+	}
+
+	irqs = min(pmu_device->num_resources, num_possible_cpus());
+	if (irqs < 1) {
+		pr_err("no irqs for PMUs defined\n");
+		return -ENODEV;
+	}
+
+	for (i = 0; i < irqs; ++i) {
+		err = 0;
+		irq = platform_get_irq(pmu_device, i);
+		if (irq < 0)
+			continue;
+
+		/*
+		 * If we have a single PMU interrupt that we can't shift,
+		 * assume that we're running on a uniprocessor machine and
+		 * continue. Otherwise, continue without this interrupt.
+		 */
+		if (irq_set_affinity(irq, cpumask_of(i)) && irqs > 1) {
+			pr_warning("unable to set irq affinity (irq=%d, cpu=%u)\n",
+				    irq, i);
+			continue;
+		}
+
+		err = request_irq(irq, armpmu->handle_irq,
+				  IRQF_NOBALANCING,
+				  "arm-pmu", armpmu);
+		if (err) {
+			pr_err("unable to request IRQ%d for ARM PMU counters\n",
+				irq);
+			armpmu_release_hardware(armpmu);
+			return err;
+		}
+
+		cpumask_set_cpu(i, &armpmu->active_irqs);
+	}
+
+	return 0;
+}
+
+static void
+hw_perf_event_destroy(struct perf_event *event)
+{
+	struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
+	atomic_t *active_events	 = &armpmu->active_events;
+	struct mutex *pmu_reserve_mutex = &armpmu->reserve_mutex;
+
+	if (atomic_dec_and_mutex_lock(active_events, pmu_reserve_mutex)) {
+		armpmu_release_hardware(armpmu);
+		mutex_unlock(pmu_reserve_mutex);
+	}
+}
+
+static int
+event_requires_mode_exclusion(struct perf_event_attr *attr)
+{
+	return attr->exclude_idle || attr->exclude_user ||
+	       attr->exclude_kernel || attr->exclude_hv;
+}
+
+static int
+__hw_perf_event_init(struct perf_event *event)
+{
+	struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
+	struct hw_perf_event *hwc = &event->hw;
+	int mapping, err;
+
+	mapping = armpmu->map_event(event);
+
+	if (mapping < 0) {
+		pr_debug("event %x:%llx not supported\n", event->attr.type,
+			 event->attr.config);
+		return mapping;
+	}
+
+	/*
+	 * We don't assign an index until we actually place the event onto
+	 * hardware. Use -1 to signify that we haven't decided where to put it
+	 * yet. For SMP systems, each core has it's own PMU so we can't do any
+	 * clever allocation or constraints checking at this point.
+	 */
+	hwc->idx		= -1;
+	hwc->config_base	= 0;
+	hwc->config		= 0;
+	hwc->event_base		= 0;
+
+	/*
+	 * Check whether we need to exclude the counter from certain modes.
+	 */
+	if ((!armpmu->set_event_filter ||
+	     armpmu->set_event_filter(hwc, &event->attr)) &&
+	     event_requires_mode_exclusion(&event->attr)) {
+		pr_debug("ARM performance counters do not support mode exclusion\n");
+		return -EPERM;
+	}
+
+	/*
+	 * Store the event encoding into the config_base field.
+	 */
+	hwc->config_base	    |= (unsigned long)mapping;
+
+	if (!hwc->sample_period) {
+		/*
+		 * For non-sampling runs, limit the sample_period to half
+		 * of the counter width. That way, the new counter value
+		 * is far less likely to overtake the previous one unless
+		 * you have some serious IRQ latency issues.
+		 */
+		hwc->sample_period  = armpmu->max_period >> 1;
+		hwc->last_period    = hwc->sample_period;
+		local64_set(&hwc->period_left, hwc->sample_period);
+	}
+
+	err = 0;
+	if (event->group_leader != event) {
+		err = validate_group(event);
+		if (err)
+			return -EINVAL;
+	}
+
+	return err;
+}
+
+static int armpmu_event_init(struct perf_event *event)
+{
+	struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
+	int err = 0;
+	atomic_t *active_events = &armpmu->active_events;
+
+	if (armpmu->map_event(event) == -ENOENT)
+		return -ENOENT;
+
+	event->destroy = hw_perf_event_destroy;
+
+	if (!atomic_inc_not_zero(active_events)) {
+		mutex_lock(&armpmu->reserve_mutex);
+		if (atomic_read(active_events) == 0)
+			err = armpmu_reserve_hardware(armpmu);
+
+		if (!err)
+			atomic_inc(active_events);
+		mutex_unlock(&armpmu->reserve_mutex);
+	}
+
+	if (err)
+		return err;
+
+	err = __hw_perf_event_init(event);
+	if (err)
+		hw_perf_event_destroy(event);
+
+	return err;
+}
+
+static void armpmu_enable(struct pmu *pmu)
+{
+	struct arm_pmu *armpmu = to_arm_pmu(pmu);
+	struct pmu_hw_events *hw_events = armpmu->get_hw_events();
+	int enabled = bitmap_weight(hw_events->used_mask, armpmu->num_events);
+
+	if (enabled)
+		armpmu->start();
+}
+
+static void armpmu_disable(struct pmu *pmu)
+{
+	struct arm_pmu *armpmu = to_arm_pmu(pmu);
+	armpmu->stop();
+}
+
+static void __init armpmu_init(struct arm_pmu *armpmu)
+{
+	atomic_set(&armpmu->active_events, 0);
+	mutex_init(&armpmu->reserve_mutex);
+
+	armpmu->pmu = (struct pmu) {
+		.pmu_enable	= armpmu_enable,
+		.pmu_disable	= armpmu_disable,
+		.event_init	= armpmu_event_init,
+		.add		= armpmu_add,
+		.del		= armpmu_del,
+		.start		= armpmu_start,
+		.stop		= armpmu_stop,
+		.read		= armpmu_read,
+	};
+}
+
+int __init armpmu_register(struct arm_pmu *armpmu, char *name, int type)
+{
+	armpmu_init(armpmu);
+	return perf_pmu_register(&armpmu->pmu, name, type);
+}
+
+/*
+ * ARMv8 PMUv3 Performance Events handling code.
+ * Common event types.
+ */
+enum armv8_pmuv3_perf_types {
+	/* Required events. */
+	ARMV8_PMUV3_PERFCTR_PMNC_SW_INCR			= 0x00,
+	ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL			= 0x03,
+	ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS			= 0x04,
+	ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED			= 0x10,
+	ARMV8_PMUV3_PERFCTR_CLOCK_CYCLES			= 0x11,
+	ARMV8_PMUV3_PERFCTR_PC_BRANCH_PRED			= 0x12,
+
+	/* At least one of the following is required. */
+	ARMV8_PMUV3_PERFCTR_INSTR_EXECUTED			= 0x08,
+	ARMV8_PMUV3_PERFCTR_OP_SPEC				= 0x1B,
+
+	/* Common architectural events. */
+	ARMV8_PMUV3_PERFCTR_MEM_READ				= 0x06,
+	ARMV8_PMUV3_PERFCTR_MEM_WRITE				= 0x07,
+	ARMV8_PMUV3_PERFCTR_EXC_TAKEN				= 0x09,
+	ARMV8_PMUV3_PERFCTR_EXC_EXECUTED			= 0x0A,
+	ARMV8_PMUV3_PERFCTR_CID_WRITE				= 0x0B,
+	ARMV8_PMUV3_PERFCTR_PC_WRITE				= 0x0C,
+	ARMV8_PMUV3_PERFCTR_PC_IMM_BRANCH			= 0x0D,
+	ARMV8_PMUV3_PERFCTR_PC_PROC_RETURN			= 0x0E,
+	ARMV8_PMUV3_PERFCTR_MEM_UNALIGNED_ACCESS		= 0x0F,
+	ARMV8_PMUV3_PERFCTR_TTBR_WRITE				= 0x1C,
+
+	/* Common microarchitectural events. */
+	ARMV8_PMUV3_PERFCTR_L1_ICACHE_REFILL			= 0x01,
+	ARMV8_PMUV3_PERFCTR_ITLB_REFILL				= 0x02,
+	ARMV8_PMUV3_PERFCTR_DTLB_REFILL				= 0x05,
+	ARMV8_PMUV3_PERFCTR_MEM_ACCESS				= 0x13,
+	ARMV8_PMUV3_PERFCTR_L1_ICACHE_ACCESS			= 0x14,
+	ARMV8_PMUV3_PERFCTR_L1_DCACHE_WB			= 0x15,
+	ARMV8_PMUV3_PERFCTR_L2_CACHE_ACCESS			= 0x16,
+	ARMV8_PMUV3_PERFCTR_L2_CACHE_REFILL			= 0x17,
+	ARMV8_PMUV3_PERFCTR_L2_CACHE_WB				= 0x18,
+	ARMV8_PMUV3_PERFCTR_BUS_ACCESS				= 0x19,
+	ARMV8_PMUV3_PERFCTR_MEM_ERROR				= 0x1A,
+	ARMV8_PMUV3_PERFCTR_BUS_CYCLES				= 0x1D,
+
+	/*
+	 * This isn't an architected event.
+	 * We detect this event number and use the cycle counter instead.
+	 */
+	ARMV8_PMUV3_PERFCTR_CPU_CYCLES				= 0xFF,
+};
+
+/* PMUv3 HW events mapping. */
+static const unsigned armv8_pmuv3_perf_map[PERF_COUNT_HW_MAX] = {
+	[PERF_COUNT_HW_CPU_CYCLES]		= ARMV8_PMUV3_PERFCTR_CPU_CYCLES,
+	[PERF_COUNT_HW_INSTRUCTIONS]		= ARMV8_PMUV3_PERFCTR_INSTR_EXECUTED,
+	[PERF_COUNT_HW_CACHE_REFERENCES]	= ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS,
+	[PERF_COUNT_HW_CACHE_MISSES]		= ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL,
+	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS]	= HW_OP_UNSUPPORTED,
+	[PERF_COUNT_HW_BRANCH_MISSES]		= ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED,
+	[PERF_COUNT_HW_BUS_CYCLES]		= HW_OP_UNSUPPORTED,
+	[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND]	= HW_OP_UNSUPPORTED,
+	[PERF_COUNT_HW_STALLED_CYCLES_BACKEND]	= HW_OP_UNSUPPORTED,
+};
+
+static const unsigned armv8_pmuv3_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
+						[PERF_COUNT_HW_CACHE_OP_MAX]
+						[PERF_COUNT_HW_CACHE_RESULT_MAX] = {
+	[C(L1D)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS,
+			[C(RESULT_MISS)]	= ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS,
+			[C(RESULT_MISS)]	= ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
+	[C(L1I)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
+	[C(LL)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
+	[C(DTLB)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
+	[C(ITLB)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
+	[C(BPU)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= ARMV8_PMUV3_PERFCTR_PC_BRANCH_PRED,
+			[C(RESULT_MISS)]	= ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= ARMV8_PMUV3_PERFCTR_PC_BRANCH_PRED,
+			[C(RESULT_MISS)]	= ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
+	[C(NODE)] = {
+		[C(OP_READ)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+		[C(OP_WRITE)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+		[C(OP_PREFETCH)] = {
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
+		},
+	},
+};
+
+/*
+ * Perf Events' indices
+ */
+#define	ARMV8_IDX_CYCLE_COUNTER	0
+#define	ARMV8_IDX_COUNTER0	1
+#define	ARMV8_IDX_COUNTER_LAST	(ARMV8_IDX_CYCLE_COUNTER + cpu_pmu->num_events - 1)
+
+#define	ARMV8_MAX_COUNTERS	32
+#define	ARMV8_COUNTER_MASK	(ARMV8_MAX_COUNTERS - 1)
+
+/*
+ * ARMv8 low level PMU access
+ */
+
+/*
+ * Perf Event to low level counters mapping
+ */
+#define	ARMV8_IDX_TO_COUNTER(x)	\
+	(((x) - ARMV8_IDX_COUNTER0) & ARMV8_COUNTER_MASK)
+
+/*
+ * Per-CPU PMCR: config reg
+ */
+#define ARMV8_PMCR_E		(1 << 0) /* Enable all counters */
+#define ARMV8_PMCR_P		(1 << 1) /* Reset all counters */
+#define ARMV8_PMCR_C		(1 << 2) /* Cycle counter reset */
+#define ARMV8_PMCR_D		(1 << 3) /* CCNT counts every 64th cpu cycle */
+#define ARMV8_PMCR_X		(1 << 4) /* Export to ETM */
+#define ARMV8_PMCR_DP		(1 << 5) /* Disable CCNT if non-invasive debug*/
+#define	ARMV8_PMCR_N_SHIFT	11	 /* Number of counters supported */
+#define	ARMV8_PMCR_N_MASK	0x1f
+#define	ARMV8_PMCR_MASK		0x3f	 /* Mask for writable bits */
+
+/*
+ * PMOVSR: counters overflow flag status reg
+ */
+#define	ARMV8_OVSR_MASK		0xffffffff	/* Mask for writable bits */
+#define	ARMV8_OVERFLOWED_MASK	ARMV8_OVSR_MASK
+
+/*
+ * PMXEVTYPER: Event selection reg
+ */
+#define	ARMV8_EVTYPE_MASK	0xc00000ff	/* Mask for writable bits */
+#define	ARMV8_EVTYPE_EVENT	0xff		/* Mask for EVENT bits */
+
+/*
+ * Event filters for PMUv3
+ */
+#define	ARMV8_EXCLUDE_EL1	(1 << 31)
+#define	ARMV8_EXCLUDE_EL0	(1 << 30)
+#define	ARMV8_INCLUDE_EL2	(1 << 27)
+
+static inline u32 armv8pmu_pmcr_read(void)
+{
+	u32 val;
+	asm volatile("mrs %0, pmcr_el0" : "=r" (val));
+	return val;
+}
+
+static inline void armv8pmu_pmcr_write(u32 val)
+{
+	val &= ARMV8_PMCR_MASK;
+	isb();
+	asm volatile("msr pmcr_el0, %0" :: "r" (val));
+}
+
+static inline int armv8pmu_has_overflowed(u32 pmovsr)
+{
+	return pmovsr & ARMV8_OVERFLOWED_MASK;
+}
+
+static inline int armv8pmu_counter_valid(int idx)
+{
+	return idx >= ARMV8_IDX_CYCLE_COUNTER && idx <= ARMV8_IDX_COUNTER_LAST;
+}
+
+static inline int armv8pmu_counter_has_overflowed(u32 pmnc, int idx)
+{
+	int ret = 0;
+	u32 counter;
+
+	if (!armv8pmu_counter_valid(idx)) {
+		pr_err("CPU%u checking wrong counter %d overflow status\n",
+			smp_processor_id(), idx);
+	} else {
+		counter = ARMV8_IDX_TO_COUNTER(idx);
+		ret = pmnc & BIT(counter);
+	}
+
+	return ret;
+}
+
+static inline int armv8pmu_select_counter(int idx)
+{
+	u32 counter;
+
+	if (!armv8pmu_counter_valid(idx)) {
+		pr_err("CPU%u selecting wrong PMNC counter %d\n",
+			smp_processor_id(), idx);
+		return -EINVAL;
+	}
+
+	counter = ARMV8_IDX_TO_COUNTER(idx);
+	asm volatile("msr pmselr_el0, %0" :: "r" (counter));
+	isb();
+
+	return idx;
+}
+
+static inline u32 armv8pmu_read_counter(int idx)
+{
+	u32 value = 0;
+
+	if (!armv8pmu_counter_valid(idx))
+		pr_err("CPU%u reading wrong counter %d\n",
+			smp_processor_id(), idx);
+	else if (idx == ARMV8_IDX_CYCLE_COUNTER)
+		asm volatile("mrs %0, pmccntr_el0" : "=r" (value));
+	else if (armv8pmu_select_counter(idx) == idx)
+		asm volatile("mrs %0, pmxevcntr_el0" : "=r" (value));
+
+	return value;
+}
+
+static inline void armv8pmu_write_counter(int idx, u32 value)
+{
+	if (!armv8pmu_counter_valid(idx))
+		pr_err("CPU%u writing wrong counter %d\n",
+			smp_processor_id(), idx);
+	else if (idx == ARMV8_IDX_CYCLE_COUNTER)
+		asm volatile("msr pmccntr_el0, %0" :: "r" (value));
+	else if (armv8pmu_select_counter(idx) == idx)
+		asm volatile("msr pmxevcntr_el0, %0" :: "r" (value));
+}
+
+static inline void armv8pmu_write_evtype(int idx, u32 val)
+{
+	if (armv8pmu_select_counter(idx) == idx) {
+		val &= ARMV8_EVTYPE_MASK;
+		asm volatile("msr pmxevtyper_el0, %0" :: "r" (val));
+	}
+}
+
+static inline int armv8pmu_enable_counter(int idx)
+{
+	u32 counter;
+
+	if (!armv8pmu_counter_valid(idx)) {
+		pr_err("CPU%u enabling wrong PMNC counter %d\n",
+			smp_processor_id(), idx);
+		return -EINVAL;
+	}
+
+	counter = ARMV8_IDX_TO_COUNTER(idx);
+	asm volatile("msr pmcntenset_el0, %0" :: "r" (BIT(counter)));
+	return idx;
+}
+
+static inline int armv8pmu_disable_counter(int idx)
+{
+	u32 counter;
+
+	if (!armv8pmu_counter_valid(idx)) {
+		pr_err("CPU%u disabling wrong PMNC counter %d\n",
+			smp_processor_id(), idx);
+		return -EINVAL;
+	}
+
+	counter = ARMV8_IDX_TO_COUNTER(idx);
+	asm volatile("msr pmcntenclr_el0, %0" :: "r" (BIT(counter)));
+	return idx;
+}
+
+static inline int armv8pmu_enable_intens(int idx)
+{
+	u32 counter;
+
+	if (!armv8pmu_counter_valid(idx)) {
+		pr_err("CPU%u enabling wrong PMNC counter IRQ enable %d\n",
+			smp_processor_id(), idx);
+		return -EINVAL;
+	}
+
+	counter = ARMV8_IDX_TO_COUNTER(idx);
+	asm volatile("msr pmintenset_el1, %0" :: "r" (BIT(counter)));
+	return idx;
+}
+
+static inline int armv8pmu_disable_intens(int idx)
+{
+	u32 counter;
+
+	if (!armv8pmu_counter_valid(idx)) {
+		pr_err("CPU%u disabling wrong PMNC counter IRQ enable %d\n",
+			smp_processor_id(), idx);
+		return -EINVAL;
+	}
+
+	counter = ARMV8_IDX_TO_COUNTER(idx);
+	asm volatile("msr pmintenclr_el1, %0" :: "r" (BIT(counter)));
+	isb();
+	/* Clear the overflow flag in case an interrupt is pending. */
+	asm volatile("msr pmovsclr_el0, %0" :: "r" (BIT(counter)));
+	isb();
+	return idx;
+}
+
+static inline u32 armv8pmu_getreset_flags(void)
+{
+	u32 value;
+
+	/* Read */
+	asm volatile("mrs %0, pmovsclr_el0" : "=r" (value));
+
+	/* Write to clear flags */
+	value &= ARMV8_OVSR_MASK;
+	asm volatile("msr pmovsclr_el0, %0" :: "r" (value));
+
+	return value;
+}
+
+static void armv8pmu_enable_event(struct hw_perf_event *hwc, int idx)
+{
+	unsigned long flags;
+	struct pmu_hw_events *events = cpu_pmu->get_hw_events();
+
+	/*
+	 * Enable counter and interrupt, and set the counter to count
+	 * the event that we're interested in.
+	 */
+	raw_spin_lock_irqsave(&events->pmu_lock, flags);
+
+	/*
+	 * Disable counter
+	 */
+	armv8pmu_disable_counter(idx);
+
+	/*
+	 * Set event (if destined for PMNx counters).
+	 */
+	armv8pmu_write_evtype(idx, hwc->config_base);
+
+	/*
+	 * Enable interrupt for this counter
+	 */
+	armv8pmu_enable_intens(idx);
+
+	/*
+	 * Enable counter
+	 */
+	armv8pmu_enable_counter(idx);
+
+	raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
+}
+
+static void armv8pmu_disable_event(struct hw_perf_event *hwc, int idx)
+{
+	unsigned long flags;
+	struct pmu_hw_events *events = cpu_pmu->get_hw_events();
+
+	/*
+	 * Disable counter and interrupt
+	 */
+	raw_spin_lock_irqsave(&events->pmu_lock, flags);
+
+	/*
+	 * Disable counter
+	 */
+	armv8pmu_disable_counter(idx);
+
+	/*
+	 * Disable interrupt for this counter
+	 */
+	armv8pmu_disable_intens(idx);
+
+	raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
+}
+
+static irqreturn_t armv8pmu_handle_irq(int irq_num, void *dev)
+{
+	u32 pmovsr;
+	struct perf_sample_data data;
+	struct pmu_hw_events *cpuc;
+	struct pt_regs *regs;
+	int idx;
+
+	/*
+	 * Get and reset the IRQ flags
+	 */
+	pmovsr = armv8pmu_getreset_flags();
+
+	/*
+	 * Did an overflow occur?
+	 */
+	if (!armv8pmu_has_overflowed(pmovsr))
+		return IRQ_NONE;
+
+	/*
+	 * Handle the counter(s) overflow(s)
+	 */
+	regs = get_irq_regs();
+
+	cpuc = &__get_cpu_var(cpu_hw_events);
+	for (idx = 0; idx < cpu_pmu->num_events; ++idx) {
+		struct perf_event *event = cpuc->events[idx];
+		struct hw_perf_event *hwc;
+
+		/* Ignore if we don't have an event. */
+		if (!event)
+			continue;
+
+		/*
+		 * We have a single interrupt for all counters. Check that
+		 * each counter has overflowed before we process it.
+		 */
+		if (!armv8pmu_counter_has_overflowed(pmovsr, idx))
+			continue;
+
+		hwc = &event->hw;
+		armpmu_event_update(event, hwc, idx);
+		perf_sample_data_init(&data, 0, hwc->last_period);
+		if (!armpmu_event_set_period(event, hwc, idx))
+			continue;
+
+		if (perf_event_overflow(event, &data, regs))
+			cpu_pmu->disable(hwc, idx);
+	}
+
+	/*
+	 * Handle the pending perf events.
+	 *
+	 * Note: this call *must* be run with interrupts disabled. For
+	 * platforms that can have the PMU interrupts raised as an NMI, this
+	 * will not work.
+	 */
+	irq_work_run();
+
+	return IRQ_HANDLED;
+}
+
+static void armv8pmu_start(void)
+{
+	unsigned long flags;
+	struct pmu_hw_events *events = cpu_pmu->get_hw_events();
+
+	raw_spin_lock_irqsave(&events->pmu_lock, flags);
+	/* Enable all counters */
+	armv8pmu_pmcr_write(armv8pmu_pmcr_read() | ARMV8_PMCR_E);
+	raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
+}
+
+static void armv8pmu_stop(void)
+{
+	unsigned long flags;
+	struct pmu_hw_events *events = cpu_pmu->get_hw_events();
+
+	raw_spin_lock_irqsave(&events->pmu_lock, flags);
+	/* Disable all counters */
+	armv8pmu_pmcr_write(armv8pmu_pmcr_read() & ~ARMV8_PMCR_E);
+	raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
+}
+
+static int armv8pmu_get_event_idx(struct pmu_hw_events *cpuc,
+				  struct hw_perf_event *event)
+{
+	int idx;
+	unsigned long evtype = event->config_base & ARMV8_EVTYPE_EVENT;
+
+	/* Always place a cycle counter into the cycle counter. */
+	if (evtype == ARMV8_PMUV3_PERFCTR_CPU_CYCLES) {
+		if (test_and_set_bit(ARMV8_IDX_CYCLE_COUNTER, cpuc->used_mask))
+			return -EAGAIN;
+
+		return ARMV8_IDX_CYCLE_COUNTER;
+	}
+
+	/*
+	 * For anything other than a cycle counter, try and use
+	 * the events counters
+	 */
+	for (idx = ARMV8_IDX_COUNTER0; idx < cpu_pmu->num_events; ++idx) {
+		if (!test_and_set_bit(idx, cpuc->used_mask))
+			return idx;
+	}
+
+	/* The counters are all in use. */
+	return -EAGAIN;
+}
+
+/*
+ * Add an event filter to a given event. This will only work for PMUv2 PMUs.
+ */
+static int armv8pmu_set_event_filter(struct hw_perf_event *event,
+				     struct perf_event_attr *attr)
+{
+	unsigned long config_base = 0;
+
+	if (attr->exclude_idle)
+		return -EPERM;
+	if (attr->exclude_user)
+		config_base |= ARMV8_EXCLUDE_EL0;
+	if (attr->exclude_kernel)
+		config_base |= ARMV8_EXCLUDE_EL1;
+	if (!attr->exclude_hv)
+		config_base |= ARMV8_INCLUDE_EL2;
+
+	/*
+	 * Install the filter into config_base as this is used to
+	 * construct the event type.
+	 */
+	event->config_base = config_base;
+
+	return 0;
+}
+
+static void armv8pmu_reset(void *info)
+{
+	u32 idx, nb_cnt = cpu_pmu->num_events;
+
+	/* The counter and interrupt enable registers are unknown at reset. */
+	for (idx = ARMV8_IDX_CYCLE_COUNTER; idx < nb_cnt; ++idx)
+		armv8pmu_disable_event(NULL, idx);
+
+	/* Initialize & Reset PMNC: C and P bits. */
+	armv8pmu_pmcr_write(ARMV8_PMCR_P | ARMV8_PMCR_C);
+
+	/* Disable access from userspace. */
+	asm volatile("msr pmuserenr_el0, %0" :: "r" (0));
+}
+
+static int armv8_pmuv3_map_event(struct perf_event *event)
+{
+	return map_cpu_event(event, &armv8_pmuv3_perf_map,
+				&armv8_pmuv3_perf_cache_map, 0xFF);
+}
+
+static struct arm_pmu armv8pmu = {
+	.handle_irq		= armv8pmu_handle_irq,
+	.enable			= armv8pmu_enable_event,
+	.disable		= armv8pmu_disable_event,
+	.read_counter		= armv8pmu_read_counter,
+	.write_counter		= armv8pmu_write_counter,
+	.get_event_idx		= armv8pmu_get_event_idx,
+	.start			= armv8pmu_start,
+	.stop			= armv8pmu_stop,
+	.reset			= armv8pmu_reset,
+	.max_period		= (1LLU << 32) - 1,
+};
+
+static u32 __init armv8pmu_read_num_pmnc_events(void)
+{
+	u32 nb_cnt;
+
+	/* Read the nb of CNTx counters supported from PMNC */
+	nb_cnt = (armv8pmu_pmcr_read() >> ARMV8_PMCR_N_SHIFT) & ARMV8_PMCR_N_MASK;
+
+	/* Add the CPU cycles counter and return */
+	return nb_cnt + 1;
+}
+
+static struct arm_pmu *__init armv8_pmuv3_pmu_init(void)
+{
+	armv8pmu.name			= "arm/armv8-pmuv3";
+	armv8pmu.map_event		= armv8_pmuv3_map_event;
+	armv8pmu.num_events		= armv8pmu_read_num_pmnc_events();
+	armv8pmu.set_event_filter	= armv8pmu_set_event_filter;
+	return &armv8pmu;
+}
+
+/*
+ * Ensure the PMU has sane values out of reset.
+ * This requires SMP to be available, so exists as a separate initcall.
+ */
+static int __init
+cpu_pmu_reset(void)
+{
+	if (cpu_pmu && cpu_pmu->reset)
+		return on_each_cpu(cpu_pmu->reset, NULL, 1);
+	return 0;
+}
+arch_initcall(cpu_pmu_reset);
+
+/*
+ * PMU platform driver and devicetree bindings.
+ */
+static struct of_device_id armpmu_of_device_ids[] = {
+	{.compatible = "arm,armv8-pmuv3"},
+	{},
+};
+
+static int __devinit armpmu_device_probe(struct platform_device *pdev)
+{
+	if (!cpu_pmu)
+		return -ENODEV;
+
+	cpu_pmu->plat_device = pdev;
+	return 0;
+}
+
+static struct platform_driver armpmu_driver = {
+	.driver		= {
+		.name	= "arm-pmu",
+		.of_match_table = armpmu_of_device_ids,
+	},
+	.probe		= armpmu_device_probe,
+};
+
+static int __init register_pmu_driver(void)
+{
+	return platform_driver_register(&armpmu_driver);
+}
+device_initcall(register_pmu_driver);
+
+static struct pmu_hw_events *armpmu_get_cpu_events(void)
+{
+	return &__get_cpu_var(cpu_hw_events);
+}
+
+static void __init cpu_pmu_init(struct arm_pmu *armpmu)
+{
+	int cpu;
+	for_each_possible_cpu(cpu) {
+		struct pmu_hw_events *events = &per_cpu(cpu_hw_events, cpu);
+		events->events = per_cpu(hw_events, cpu);
+		events->used_mask = per_cpu(used_mask, cpu);
+		raw_spin_lock_init(&events->pmu_lock);
+	}
+	armpmu->get_hw_events = armpmu_get_cpu_events;
+}
+
+static int __init init_hw_perf_events(void)
+{
+	u64 dfr = read_cpuid(ID_AA64DFR0_EL1);
+
+	switch ((dfr >> 8) & 0xf) {
+	case 0x1:	/* PMUv3 */
+		cpu_pmu = armv8_pmuv3_pmu_init();
+		break;
+	}
+
+	if (cpu_pmu) {
+		pr_info("enabled with %s PMU driver, %d counters available\n",
+			cpu_pmu->name, cpu_pmu->num_events);
+		cpu_pmu_init(cpu_pmu);
+		armpmu_register(cpu_pmu, "cpu", PERF_TYPE_RAW);
+	} else {
+		pr_info("no hardware support available\n");
+	}
+
+	return 0;
+}
+early_initcall(init_hw_perf_events);
+
+/*
+ * Callchain handling code.
+ */
+struct frame_tail {
+	struct frame_tail   __user *fp;
+	unsigned long	    lr;
+} __attribute__((packed));
+
+/*
+ * Get the return address for a single stackframe and return a pointer to the
+ * next frame tail.
+ */
+static struct frame_tail __user *
+user_backtrace(struct frame_tail __user *tail,
+	       struct perf_callchain_entry *entry)
+{
+	struct frame_tail buftail;
+	unsigned long err;
+
+	/* Also check accessibility of one struct frame_tail beyond */
+	if (!access_ok(VERIFY_READ, tail, sizeof(buftail)))
+		return NULL;
+
+	pagefault_disable();
+	err = __copy_from_user_inatomic(&buftail, tail, sizeof(buftail));
+	pagefault_enable();
+
+	if (err)
+		return NULL;
+
+	perf_callchain_store(entry, buftail.lr);
+
+	/*
+	 * Frame pointers should strictly progress back up the stack
+	 * (towards higher addresses).
+	 */
+	if (tail >= buftail.fp)
+		return NULL;
+
+	return buftail.fp;
+}
+
+void perf_callchain_user(struct perf_callchain_entry *entry,
+			 struct pt_regs *regs)
+{
+	struct frame_tail __user *tail;
+
+	tail = (struct frame_tail __user *)regs->regs[29];
+
+	while (entry->nr < PERF_MAX_STACK_DEPTH &&
+	       tail && !((unsigned long)tail & 0xf))
+		tail = user_backtrace(tail, entry);
+}
+
+/*
+ * Gets called by walk_stackframe() for every stackframe. This will be called
+ * whist unwinding the stackframe and is like a subroutine return so we use
+ * the PC.
+ */
+static int callchain_trace(struct stackframe *frame, void *data)
+{
+	struct perf_callchain_entry *entry = data;
+	perf_callchain_store(entry, frame->pc);
+	return 0;
+}
+
+void perf_callchain_kernel(struct perf_callchain_entry *entry,
+			   struct pt_regs *regs)
+{
+	struct stackframe frame;
+
+	frame.fp = regs->regs[29];
+	frame.sp = regs->sp;
+	frame.pc = regs->pc;
+	walk_stackframe(&frame, callchain_trace, entry);
+}
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
new file mode 100644
index 0000000..f22965e
--- /dev/null
+++ b/arch/arm64/kernel/process.c
@@ -0,0 +1,408 @@
+/*
+ * Based on arch/arm/kernel/process.c
+ *
+ * Original Copyright (C) 1995  Linus Torvalds
+ * Copyright (C) 1996-2000 Russell King - Converted to ARM.
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdarg.h>
+
+#include <linux/export.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/user.h>
+#include <linux/delay.h>
+#include <linux/reboot.h>
+#include <linux/interrupt.h>
+#include <linux/kallsyms.h>
+#include <linux/init.h>
+#include <linux/cpu.h>
+#include <linux/elfcore.h>
+#include <linux/pm.h>
+#include <linux/tick.h>
+#include <linux/utsname.h>
+#include <linux/uaccess.h>
+#include <linux/random.h>
+#include <linux/hw_breakpoint.h>
+#include <linux/personality.h>
+#include <linux/notifier.h>
+
+#include <asm/compat.h>
+#include <asm/cacheflush.h>
+#include <asm/processor.h>
+#include <asm/stacktrace.h>
+#include <asm/fpsimd.h>
+
+static void setup_restart(void)
+{
+	/*
+	 * Tell the mm system that we are going to reboot -
+	 * we may need it to insert some 1:1 mappings so that
+	 * soft boot works.
+	 */
+	setup_mm_for_reboot();
+
+	/* Clean and invalidate caches */
+	flush_cache_all();
+
+	/* Turn D-cache off */
+	cpu_cache_off();
+
+	/* Push out any further dirty data, and ensure cache is empty */
+	flush_cache_all();
+}
+
+void soft_restart(unsigned long addr)
+{
+	setup_restart();
+	cpu_reset(addr);
+}
+
+/*
+ * Function pointers to optional machine specific functions
+ */
+void (*pm_power_off)(void);
+EXPORT_SYMBOL_GPL(pm_power_off);
+
+void (*pm_restart)(const char *cmd);
+EXPORT_SYMBOL_GPL(pm_restart);
+
+
+/*
+ * This is our default idle handler.
+ */
+static void default_idle(void)
+{
+	/*
+	 * This should do all the clock switching and wait for interrupt
+	 * tricks
+	 */
+	cpu_do_idle();
+	local_irq_enable();
+}
+
+void (*pm_idle)(void) = default_idle;
+EXPORT_SYMBOL_GPL(pm_idle);
+
+/*
+ * The idle thread, has rather strange semantics for calling pm_idle,
+ * but this is what x86 does and we need to do the same, so that
+ * things like cpuidle get called in the same way.  The only difference
+ * is that we always respect 'hlt_counter' to prevent low power idle.
+ */
+void cpu_idle(void)
+{
+	local_fiq_enable();
+
+	/* endless idle loop with no priority at all */
+	while (1) {
+		tick_nohz_idle_enter();
+		rcu_idle_enter();
+		while (!need_resched()) {
+			/*
+			 * We need to disable interrupts here to ensure
+			 * we don't miss a wakeup call.
+			 */
+			local_irq_disable();
+			if (!need_resched()) {
+				stop_critical_timings();
+				pm_idle();
+				start_critical_timings();
+				/*
+				 * pm_idle functions should always return
+				 * with IRQs enabled.
+				 */
+				WARN_ON(irqs_disabled());
+			} else {
+				local_irq_enable();
+			}
+		}
+		rcu_idle_exit();
+		tick_nohz_idle_exit();
+		schedule_preempt_disabled();
+	}
+}
+
+void machine_shutdown(void)
+{
+#ifdef CONFIG_SMP
+	smp_send_stop();
+#endif
+}
+
+void machine_halt(void)
+{
+	machine_shutdown();
+	while (1);
+}
+
+void machine_power_off(void)
+{
+	machine_shutdown();
+	if (pm_power_off)
+		pm_power_off();
+}
+
+void machine_restart(char *cmd)
+{
+	machine_shutdown();
+
+	/* Disable interrupts first */
+	local_irq_disable();
+	local_fiq_disable();
+
+	/* Now call the architecture specific reboot code. */
+	if (pm_restart)
+		pm_restart(cmd);
+
+	/*
+	 * Whoops - the architecture was unable to reboot.
+	 */
+	printk("Reboot failed -- System halted\n");
+	while (1);
+}
+
+void __show_regs(struct pt_regs *regs)
+{
+	int i;
+
+	printk("CPU: %d    %s  (%s %.*s)\n",
+		raw_smp_processor_id(), print_tainted(),
+		init_utsname()->release,
+		(int)strcspn(init_utsname()->version, " "),
+		init_utsname()->version);
+	print_symbol("PC is at %s\n", instruction_pointer(regs));
+	print_symbol("LR is at %s\n", regs->regs[30]);
+	printk("pc : [<%016llx>] lr : [<%016llx>] pstate: %08llx\n",
+	       regs->pc, regs->regs[30], regs->pstate);
+	printk("sp : %016llx\n", regs->sp);
+	for (i = 29; i >= 0; i--) {
+		printk("x%-2d: %016llx ", i, regs->regs[i]);
+		if (i % 2 == 0)
+			printk("\n");
+	}
+	printk("\n");
+}
+
+void show_regs(struct pt_regs * regs)
+{
+	printk("\n");
+	printk("Pid: %d, comm: %20s\n", task_pid_nr(current), current->comm);
+	__show_regs(regs);
+}
+
+/*
+ * Free current thread data structures etc..
+ */
+void exit_thread(void)
+{
+}
+
+void flush_thread(void)
+{
+	fpsimd_flush_thread();
+	flush_ptrace_hw_breakpoint(current);
+}
+
+void release_thread(struct task_struct *dead_task)
+{
+}
+
+int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
+{
+	fpsimd_save_state(&current->thread.fpsimd_state);
+	*dst = *src;
+	return 0;
+}
+
+asmlinkage void ret_from_fork(void) asm("ret_from_fork");
+
+int copy_thread(unsigned long clone_flags, unsigned long stack_start,
+		unsigned long stk_sz, struct task_struct *p,
+		struct pt_regs *regs)
+{
+	struct pt_regs *childregs = task_pt_regs(p);
+	unsigned long tls = p->thread.tp_value;
+
+	*childregs = *regs;
+	childregs->regs[0] = 0;
+
+	if (is_compat_thread(task_thread_info(p)))
+		childregs->compat_sp = stack_start;
+	else {
+		/*
+		 * Read the current TLS pointer from tpidr_el0 as it may be
+		 * out-of-sync with the saved value.
+		 */
+		asm("mrs %0, tpidr_el0" : "=r" (tls));
+		childregs->sp = stack_start;
+	}
+
+	memset(&p->thread.cpu_context, 0, sizeof(struct cpu_context));
+	p->thread.cpu_context.sp = (unsigned long)childregs;
+	p->thread.cpu_context.pc = (unsigned long)ret_from_fork;
+
+	/* If a TLS pointer was passed to clone, use that for the new thread. */
+	if (clone_flags & CLONE_SETTLS)
+		tls = regs->regs[3];
+	p->thread.tp_value = tls;
+
+	ptrace_hw_copy_thread(p);
+
+	return 0;
+}
+
+static void tls_thread_switch(struct task_struct *next)
+{
+	unsigned long tpidr, tpidrro;
+
+	if (!is_compat_task()) {
+		asm("mrs %0, tpidr_el0" : "=r" (tpidr));
+		current->thread.tp_value = tpidr;
+	}
+
+	if (is_compat_thread(task_thread_info(next))) {
+		tpidr = 0;
+		tpidrro = next->thread.tp_value;
+	} else {
+		tpidr = next->thread.tp_value;
+		tpidrro = 0;
+	}
+
+	asm(
+	"	msr	tpidr_el0, %0\n"
+	"	msr	tpidrro_el0, %1"
+	: : "r" (tpidr), "r" (tpidrro));
+}
+
+/*
+ * Thread switching.
+ */
+struct task_struct *__switch_to(struct task_struct *prev,
+				struct task_struct *next)
+{
+	struct task_struct *last;
+
+	fpsimd_thread_switch(next);
+	tls_thread_switch(next);
+	hw_breakpoint_thread_switch(next);
+
+	/* the actual thread switch */
+	last = cpu_switch_to(prev, next);
+
+	return last;
+}
+
+/*
+ * Fill in the task's elfregs structure for a core dump.
+ */
+int dump_task_regs(struct task_struct *t, elf_gregset_t *elfregs)
+{
+	elf_core_copy_regs(elfregs, task_pt_regs(t));
+	return 1;
+}
+
+/*
+ * fill in the fpe structure for a core dump...
+ */
+int dump_fpu (struct pt_regs *regs, struct user_fp *fp)
+{
+	return 0;
+}
+EXPORT_SYMBOL(dump_fpu);
+
+/*
+ * Shuffle the argument into the correct register before calling the
+ * thread function.  x1 is the thread argument, x2 is the pointer to
+ * the thread function, and x3 points to the exit function.
+ */
+extern void kernel_thread_helper(void);
+asm(	".section .text\n"
+"	.align\n"
+"	.type	kernel_thread_helper, #function\n"
+"kernel_thread_helper:\n"
+"	mov	x0, x1\n"
+"	mov	x30, x3\n"
+"	br	x2\n"
+"	.size	kernel_thread_helper, . - kernel_thread_helper\n"
+"	.previous");
+
+#define kernel_thread_exit	do_exit
+
+/*
+ * Create a kernel thread.
+ */
+pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
+{
+	struct pt_regs regs;
+
+	memset(&regs, 0, sizeof(regs));
+
+	regs.regs[1] = (unsigned long)arg;
+	regs.regs[2] = (unsigned long)fn;
+	regs.regs[3] = (unsigned long)kernel_thread_exit;
+	regs.pc = (unsigned long)kernel_thread_helper;
+	regs.pstate = PSR_MODE_EL1h;
+
+	return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
+}
+EXPORT_SYMBOL(kernel_thread);
+
+unsigned long get_wchan(struct task_struct *p)
+{
+	struct stackframe frame;
+	int count = 0;
+	if (!p || p == current || p->state == TASK_RUNNING)
+		return 0;
+
+	frame.fp = thread_saved_fp(p);
+	frame.sp = thread_saved_sp(p);
+	frame.pc = thread_saved_pc(p);
+	do {
+		int ret = unwind_frame(&frame);
+		if (ret < 0)
+			return 0;
+		if (!in_sched_functions(frame.pc))
+			return frame.pc;
+	} while (count ++ < 16);
+	return 0;
+}
+
+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 unsigned long randomize_base(unsigned long base)
+{
+	unsigned long range_end = base + (STACK_RND_MASK << PAGE_SHIFT) + 1;
+	return randomize_range(base, range_end, 0) ? : base;
+}
+
+unsigned long arch_randomize_brk(struct mm_struct *mm)
+{
+	return randomize_base(mm->brk);
+}
+
+unsigned long randomize_et_dyn(unsigned long base)
+{
+	return randomize_base(base);
+}
diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
new file mode 100644
index 0000000..490f753
--- /dev/null
+++ b/arch/arm64/kernel/ptrace.c
@@ -0,0 +1,1126 @@
+/*
+ * Based on arch/arm/kernel/ptrace.c
+ *
+ * By Ross Biro 1/23/92
+ * edited by Linus Torvalds
+ * ARM modifications Copyright (C) 2000 Russell King
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/ptrace.h>
+#include <linux/user.h>
+#include <linux/security.h>
+#include <linux/init.h>
+#include <linux/signal.h>
+#include <linux/uaccess.h>
+#include <linux/perf_event.h>
+#include <linux/hw_breakpoint.h>
+#include <linux/regset.h>
+#include <linux/tracehook.h>
+#include <linux/elf.h>
+
+#include <asm/compat.h>
+#include <asm/debug-monitors.h>
+#include <asm/pgtable.h>
+#include <asm/traps.h>
+#include <asm/system_misc.h>
+
+/*
+ * TODO: does not yet catch signals sent when the child dies.
+ * in exit.c or in signal.c.
+ */
+
+/*
+ * Called by kernel/ptrace.c when detaching..
+ */
+void ptrace_disable(struct task_struct *child)
+{
+}
+
+/*
+ * Handle hitting a breakpoint.
+ */
+static int ptrace_break(struct pt_regs *regs)
+{
+	siginfo_t info = {
+		.si_signo = SIGTRAP,
+		.si_errno = 0,
+		.si_code  = TRAP_BRKPT,
+		.si_addr  = (void __user *)instruction_pointer(regs),
+	};
+
+	force_sig_info(SIGTRAP, &info, current);
+	return 0;
+}
+
+static int arm64_break_trap(unsigned long addr, unsigned int esr,
+			    struct pt_regs *regs)
+{
+	return ptrace_break(regs);
+}
+
+#ifdef CONFIG_HAVE_HW_BREAKPOINT
+/*
+ * Handle hitting a HW-breakpoint.
+ */
+static void ptrace_hbptriggered(struct perf_event *bp,
+				struct perf_sample_data *data,
+				struct pt_regs *regs)
+{
+	struct arch_hw_breakpoint *bkpt = counter_arch_bp(bp);
+	siginfo_t info = {
+		.si_signo	= SIGTRAP,
+		.si_errno	= 0,
+		.si_code	= TRAP_HWBKPT,
+		.si_addr	= (void __user *)(bkpt->trigger),
+	};
+
+#ifdef CONFIG_COMPAT
+	int i;
+
+	if (!is_compat_task())
+		goto send_sig;
+
+	for (i = 0; i < ARM_MAX_BRP; ++i) {
+		if (current->thread.debug.hbp_break[i] == bp) {
+			info.si_errno = (i << 1) + 1;
+			break;
+		}
+	}
+	for (i = ARM_MAX_BRP; i < ARM_MAX_HBP_SLOTS && !bp; ++i) {
+		if (current->thread.debug.hbp_watch[i] == bp) {
+			info.si_errno = -((i << 1) + 1);
+			break;
+		}
+	}
+
+send_sig:
+#endif
+	force_sig_info(SIGTRAP, &info, current);
+}
+
+/*
+ * Unregister breakpoints from this task and reset the pointers in
+ * the thread_struct.
+ */
+void flush_ptrace_hw_breakpoint(struct task_struct *tsk)
+{
+	int i;
+	struct thread_struct *t = &tsk->thread;
+
+	for (i = 0; i < ARM_MAX_BRP; i++) {
+		if (t->debug.hbp_break[i]) {
+			unregister_hw_breakpoint(t->debug.hbp_break[i]);
+			t->debug.hbp_break[i] = NULL;
+		}
+	}
+
+	for (i = 0; i < ARM_MAX_WRP; i++) {
+		if (t->debug.hbp_watch[i]) {
+			unregister_hw_breakpoint(t->debug.hbp_watch[i]);
+			t->debug.hbp_watch[i] = NULL;
+		}
+	}
+}
+
+void ptrace_hw_copy_thread(struct task_struct *tsk)
+{
+	memset(&tsk->thread.debug, 0, sizeof(struct debug_info));
+}
+
+static struct perf_event *ptrace_hbp_get_event(unsigned int note_type,
+					       struct task_struct *tsk,
+					       unsigned long idx)
+{
+	struct perf_event *bp = ERR_PTR(-EINVAL);
+
+	switch (note_type) {
+	case NT_ARM_HW_BREAK:
+		if (idx < ARM_MAX_BRP)
+			bp = tsk->thread.debug.hbp_break[idx];
+		break;
+	case NT_ARM_HW_WATCH:
+		if (idx < ARM_MAX_WRP)
+			bp = tsk->thread.debug.hbp_watch[idx];
+		break;
+	}
+
+	return bp;
+}
+
+static int ptrace_hbp_set_event(unsigned int note_type,
+				struct task_struct *tsk,
+				unsigned long idx,
+				struct perf_event *bp)
+{
+	int err = -EINVAL;
+
+	switch (note_type) {
+	case NT_ARM_HW_BREAK:
+		if (idx < ARM_MAX_BRP) {
+			tsk->thread.debug.hbp_break[idx] = bp;
+			err = 0;
+		}
+		break;
+	case NT_ARM_HW_WATCH:
+		if (idx < ARM_MAX_WRP) {
+			tsk->thread.debug.hbp_watch[idx] = bp;
+			err = 0;
+		}
+		break;
+	}
+
+	return err;
+}
+
+static struct perf_event *ptrace_hbp_create(unsigned int note_type,
+					    struct task_struct *tsk,
+					    unsigned long idx)
+{
+	struct perf_event *bp;
+	struct perf_event_attr attr;
+	int err, type;
+
+	switch (note_type) {
+	case NT_ARM_HW_BREAK:
+		type = HW_BREAKPOINT_X;
+		break;
+	case NT_ARM_HW_WATCH:
+		type = HW_BREAKPOINT_RW;
+		break;
+	default:
+		return ERR_PTR(-EINVAL);
+	}
+
+	ptrace_breakpoint_init(&attr);
+
+	/*
+	 * Initialise fields to sane defaults
+	 * (i.e. values that will pass validation).
+	 */
+	attr.bp_addr	= 0;
+	attr.bp_len	= HW_BREAKPOINT_LEN_4;
+	attr.bp_type	= type;
+	attr.disabled	= 1;
+
+	bp = register_user_hw_breakpoint(&attr, ptrace_hbptriggered, NULL, tsk);
+	if (IS_ERR(bp))
+		return bp;
+
+	err = ptrace_hbp_set_event(note_type, tsk, idx, bp);
+	if (err)
+		return ERR_PTR(err);
+
+	return bp;
+}
+
+static int ptrace_hbp_fill_attr_ctrl(unsigned int note_type,
+				     struct arch_hw_breakpoint_ctrl ctrl,
+				     struct perf_event_attr *attr)
+{
+	int err, len, type;
+
+	err = arch_bp_generic_fields(ctrl, &len, &type);
+	if (err)
+		return err;
+
+	switch (note_type) {
+	case NT_ARM_HW_BREAK:
+		if ((type & HW_BREAKPOINT_X) != type)
+			return -EINVAL;
+		break;
+	case NT_ARM_HW_WATCH:
+		if ((type & HW_BREAKPOINT_RW) != type)
+			return -EINVAL;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	attr->bp_len	= len;
+	attr->bp_type	= type;
+	attr->disabled	= !ctrl.enabled;
+
+	return 0;
+}
+
+static int ptrace_hbp_get_resource_info(unsigned int note_type, u32 *info)
+{
+	u8 num;
+	u32 reg = 0;
+
+	switch (note_type) {
+	case NT_ARM_HW_BREAK:
+		num = hw_breakpoint_slots(TYPE_INST);
+		break;
+	case NT_ARM_HW_WATCH:
+		num = hw_breakpoint_slots(TYPE_DATA);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	reg |= debug_monitors_arch();
+	reg <<= 8;
+	reg |= num;
+
+	*info = reg;
+	return 0;
+}
+
+static int ptrace_hbp_get_ctrl(unsigned int note_type,
+			       struct task_struct *tsk,
+			       unsigned long idx,
+			       u32 *ctrl)
+{
+	struct perf_event *bp = ptrace_hbp_get_event(note_type, tsk, idx);
+
+	if (IS_ERR(bp))
+		return PTR_ERR(bp);
+
+	*ctrl = bp ? encode_ctrl_reg(counter_arch_bp(bp)->ctrl) : 0;
+	return 0;
+}
+
+static int ptrace_hbp_get_addr(unsigned int note_type,
+			       struct task_struct *tsk,
+			       unsigned long idx,
+			       u64 *addr)
+{
+	struct perf_event *bp = ptrace_hbp_get_event(note_type, tsk, idx);
+
+	if (IS_ERR(bp))
+		return PTR_ERR(bp);
+
+	*addr = bp ? bp->attr.bp_addr : 0;
+	return 0;
+}
+
+static struct perf_event *ptrace_hbp_get_initialised_bp(unsigned int note_type,
+							struct task_struct *tsk,
+							unsigned long idx)
+{
+	struct perf_event *bp = ptrace_hbp_get_event(note_type, tsk, idx);
+
+	if (!bp)
+		bp = ptrace_hbp_create(note_type, tsk, idx);
+
+	return bp;
+}
+
+static int ptrace_hbp_set_ctrl(unsigned int note_type,
+			       struct task_struct *tsk,
+			       unsigned long idx,
+			       u32 uctrl)
+{
+	int err;
+	struct perf_event *bp;
+	struct perf_event_attr attr;
+	struct arch_hw_breakpoint_ctrl ctrl;
+
+	bp = ptrace_hbp_get_initialised_bp(note_type, tsk, idx);
+	if (IS_ERR(bp)) {
+		err = PTR_ERR(bp);
+		return err;
+	}
+
+	attr = bp->attr;
+	decode_ctrl_reg(uctrl, &ctrl);
+	err = ptrace_hbp_fill_attr_ctrl(note_type, ctrl, &attr);
+	if (err)
+		return err;
+
+	return modify_user_hw_breakpoint(bp, &attr);
+}
+
+static int ptrace_hbp_set_addr(unsigned int note_type,
+			       struct task_struct *tsk,
+			       unsigned long idx,
+			       u64 addr)
+{
+	int err;
+	struct perf_event *bp;
+	struct perf_event_attr attr;
+
+	bp = ptrace_hbp_get_initialised_bp(note_type, tsk, idx);
+	if (IS_ERR(bp)) {
+		err = PTR_ERR(bp);
+		return err;
+	}
+
+	attr = bp->attr;
+	attr.bp_addr = addr;
+	err = modify_user_hw_breakpoint(bp, &attr);
+	return err;
+}
+
+#define PTRACE_HBP_ADDR_SZ	sizeof(u64)
+#define PTRACE_HBP_CTRL_SZ	sizeof(u32)
+#define PTRACE_HBP_REG_OFF	sizeof(u32)
+
+static int hw_break_get(struct task_struct *target,
+			const struct user_regset *regset,
+			unsigned int pos, unsigned int count,
+			void *kbuf, void __user *ubuf)
+{
+	unsigned int note_type = regset->core_note_type;
+	int ret, idx = 0, offset = PTRACE_HBP_REG_OFF, limit;
+	u32 info, ctrl;
+	u64 addr;
+
+	/* Resource info */
+	ret = ptrace_hbp_get_resource_info(note_type, &info);
+	if (ret)
+		return ret;
+
+	ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &info, 0, 4);
+	if (ret)
+		return ret;
+
+	/* (address, ctrl) registers */
+	limit = regset->n * regset->size;
+	while (count && offset < limit) {
+		ret = ptrace_hbp_get_addr(note_type, target, idx, &addr);
+		if (ret)
+			return ret;
+		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &addr,
+					  offset, offset + PTRACE_HBP_ADDR_SZ);
+		if (ret)
+			return ret;
+		offset += PTRACE_HBP_ADDR_SZ;
+
+		ret = ptrace_hbp_get_ctrl(note_type, target, idx, &ctrl);
+		if (ret)
+			return ret;
+		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &ctrl,
+					  offset, offset + PTRACE_HBP_CTRL_SZ);
+		if (ret)
+			return ret;
+		offset += PTRACE_HBP_CTRL_SZ;
+		idx++;
+	}
+
+	return 0;
+}
+
+static int hw_break_set(struct task_struct *target,
+			const struct user_regset *regset,
+			unsigned int pos, unsigned int count,
+			const void *kbuf, const void __user *ubuf)
+{
+	unsigned int note_type = regset->core_note_type;
+	int ret, idx = 0, offset = PTRACE_HBP_REG_OFF, limit;
+	u32 ctrl;
+	u64 addr;
+
+	/* Resource info */
+	ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 0, 4);
+	if (ret)
+		return ret;
+
+	/* (address, ctrl) registers */
+	limit = regset->n * regset->size;
+	while (count && offset < limit) {
+		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &addr,
+					 offset, offset + PTRACE_HBP_ADDR_SZ);
+		if (ret)
+			return ret;
+		ret = ptrace_hbp_set_addr(note_type, target, idx, addr);
+		if (ret)
+			return ret;
+		offset += PTRACE_HBP_ADDR_SZ;
+
+		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &ctrl,
+					 offset, offset + PTRACE_HBP_CTRL_SZ);
+		if (ret)
+			return ret;
+		ret = ptrace_hbp_set_ctrl(note_type, target, idx, ctrl);
+		if (ret)
+			return ret;
+		offset += PTRACE_HBP_CTRL_SZ;
+		idx++;
+	}
+
+	return 0;
+}
+#endif	/* CONFIG_HAVE_HW_BREAKPOINT */
+
+static int gpr_get(struct task_struct *target,
+		   const struct user_regset *regset,
+		   unsigned int pos, unsigned int count,
+		   void *kbuf, void __user *ubuf)
+{
+	struct user_pt_regs *uregs = &task_pt_regs(target)->user_regs;
+	return user_regset_copyout(&pos, &count, &kbuf, &ubuf, uregs, 0, -1);
+}
+
+static int gpr_set(struct task_struct *target, const struct user_regset *regset,
+		   unsigned int pos, unsigned int count,
+		   const void *kbuf, const void __user *ubuf)
+{
+	int ret;
+	struct user_pt_regs newregs;
+
+	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &newregs, 0, -1);
+	if (ret)
+		return ret;
+
+	if (!valid_user_regs(&newregs))
+		return -EINVAL;
+
+	task_pt_regs(target)->user_regs = newregs;
+	return 0;
+}
+
+/*
+ * TODO: update fp accessors for lazy context switching (sync/flush hwstate)
+ */
+static int fpr_get(struct task_struct *target, const struct user_regset *regset,
+		   unsigned int pos, unsigned int count,
+		   void *kbuf, void __user *ubuf)
+{
+	struct user_fpsimd_state *uregs;
+	uregs = &target->thread.fpsimd_state.user_fpsimd;
+	return user_regset_copyout(&pos, &count, &kbuf, &ubuf, uregs, 0, -1);
+}
+
+static int fpr_set(struct task_struct *target, const struct user_regset *regset,
+		   unsigned int pos, unsigned int count,
+		   const void *kbuf, const void __user *ubuf)
+{
+	int ret;
+	struct user_fpsimd_state newstate;
+
+	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &newstate, 0, -1);
+	if (ret)
+		return ret;
+
+	target->thread.fpsimd_state.user_fpsimd = newstate;
+	return ret;
+}
+
+static int tls_get(struct task_struct *target, const struct user_regset *regset,
+		   unsigned int pos, unsigned int count,
+		   void *kbuf, void __user *ubuf)
+{
+	unsigned long *tls = &target->thread.tp_value;
+	return user_regset_copyout(&pos, &count, &kbuf, &ubuf, tls, 0, -1);
+}
+
+static int tls_set(struct task_struct *target, const struct user_regset *regset,
+		   unsigned int pos, unsigned int count,
+		   const void *kbuf, const void __user *ubuf)
+{
+	int ret;
+	unsigned long tls;
+
+	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &tls, 0, -1);
+	if (ret)
+		return ret;
+
+	target->thread.tp_value = tls;
+	return ret;
+}
+
+enum aarch64_regset {
+	REGSET_GPR,
+	REGSET_FPR,
+	REGSET_TLS,
+#ifdef CONFIG_HAVE_HW_BREAKPOINT
+	REGSET_HW_BREAK,
+	REGSET_HW_WATCH,
+#endif
+};
+
+static const struct user_regset aarch64_regsets[] = {
+	[REGSET_GPR] = {
+		.core_note_type = NT_PRSTATUS,
+		.n = sizeof(struct user_pt_regs) / sizeof(u64),
+		.size = sizeof(u64),
+		.align = sizeof(u64),
+		.get = gpr_get,
+		.set = gpr_set
+	},
+	[REGSET_FPR] = {
+		.core_note_type = NT_PRFPREG,
+		.n = sizeof(struct user_fpsimd_state) / sizeof(u32),
+		/*
+		 * We pretend we have 32-bit registers because the fpsr and
+		 * fpcr are 32-bits wide.
+		 */
+		.size = sizeof(u32),
+		.align = sizeof(u32),
+		.get = fpr_get,
+		.set = fpr_set
+	},
+	[REGSET_TLS] = {
+		.core_note_type = NT_ARM_TLS,
+		.n = 1,
+		.size = sizeof(void *),
+		.align = sizeof(void *),
+		.get = tls_get,
+		.set = tls_set,
+	},
+#ifdef CONFIG_HAVE_HW_BREAKPOINT
+	[REGSET_HW_BREAK] = {
+		.core_note_type = NT_ARM_HW_BREAK,
+		.n = sizeof(struct user_hwdebug_state) / sizeof(u32),
+		.size = sizeof(u32),
+		.align = sizeof(u32),
+		.get = hw_break_get,
+		.set = hw_break_set,
+	},
+	[REGSET_HW_WATCH] = {
+		.core_note_type = NT_ARM_HW_WATCH,
+		.n = sizeof(struct user_hwdebug_state) / sizeof(u32),
+		.size = sizeof(u32),
+		.align = sizeof(u32),
+		.get = hw_break_get,
+		.set = hw_break_set,
+	},
+#endif
+};
+
+static const struct user_regset_view user_aarch64_view = {
+	.name = "aarch64", .e_machine = EM_AARCH64,
+	.regsets = aarch64_regsets, .n = ARRAY_SIZE(aarch64_regsets)
+};
+
+#ifdef CONFIG_COMPAT
+#include <linux/compat.h>
+
+enum compat_regset {
+	REGSET_COMPAT_GPR,
+	REGSET_COMPAT_VFP,
+};
+
+static int compat_gpr_get(struct task_struct *target,
+			  const struct user_regset *regset,
+			  unsigned int pos, unsigned int count,
+			  void *kbuf, void __user *ubuf)
+{
+	int ret = 0;
+	unsigned int i, start, num_regs;
+
+	/* Calculate the number of AArch32 registers contained in count */
+	num_regs = count / regset->size;
+
+	/* Convert pos into an register number */
+	start = pos / regset->size;
+
+	if (start + num_regs > regset->n)
+		return -EIO;
+
+	for (i = 0; i < num_regs; ++i) {
+		unsigned int idx = start + i;
+		void *reg;
+
+		switch (idx) {
+		case 15:
+			reg = (void *)&task_pt_regs(target)->pc;
+			break;
+		case 16:
+			reg = (void *)&task_pt_regs(target)->pstate;
+			break;
+		case 17:
+			reg = (void *)&task_pt_regs(target)->orig_x0;
+			break;
+		default:
+			reg = (void *)&task_pt_regs(target)->regs[idx];
+		}
+
+		ret = copy_to_user(ubuf, reg, sizeof(compat_ulong_t));
+
+		if (ret)
+			break;
+		else
+			ubuf += sizeof(compat_ulong_t);
+	}
+
+	return ret;
+}
+
+static int compat_gpr_set(struct task_struct *target,
+			  const struct user_regset *regset,
+			  unsigned int pos, unsigned int count,
+			  const void *kbuf, const void __user *ubuf)
+{
+	struct pt_regs newregs;
+	int ret = 0;
+	unsigned int i, start, num_regs;
+
+	/* Calculate the number of AArch32 registers contained in count */
+	num_regs = count / regset->size;
+
+	/* Convert pos into an register number */
+	start = pos / regset->size;
+
+	if (start + num_regs > regset->n)
+		return -EIO;
+
+	newregs = *task_pt_regs(target);
+
+	for (i = 0; i < num_regs; ++i) {
+		unsigned int idx = start + i;
+		void *reg;
+
+		switch (idx) {
+		case 15:
+			reg = (void *)&newregs.pc;
+			break;
+		case 16:
+			reg = (void *)&newregs.pstate;
+			break;
+		case 17:
+			reg = (void *)&newregs.orig_x0;
+			break;
+		default:
+			reg = (void *)&newregs.regs[idx];
+		}
+
+		ret = copy_from_user(reg, ubuf, sizeof(compat_ulong_t));
+
+		if (ret)
+			goto out;
+		else
+			ubuf += sizeof(compat_ulong_t);
+	}
+
+	if (valid_user_regs(&newregs.user_regs))
+		*task_pt_regs(target) = newregs;
+	else
+		ret = -EINVAL;
+
+out:
+	return ret;
+}
+
+static int compat_vfp_get(struct task_struct *target,
+			  const struct user_regset *regset,
+			  unsigned int pos, unsigned int count,
+			  void *kbuf, void __user *ubuf)
+{
+	struct user_fpsimd_state *uregs;
+	compat_ulong_t fpscr;
+	int ret;
+
+	uregs = &target->thread.fpsimd_state.user_fpsimd;
+
+	/*
+	 * The VFP registers are packed into the fpsimd_state, so they all sit
+	 * nicely together for us. We just need to create the fpscr separately.
+	 */
+	ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, uregs, 0,
+				  VFP_STATE_SIZE - sizeof(compat_ulong_t));
+
+	if (count && !ret) {
+		fpscr = (uregs->fpsr & VFP_FPSCR_STAT_MASK) |
+			(uregs->fpcr & VFP_FPSCR_CTRL_MASK);
+		ret = put_user(fpscr, (compat_ulong_t *)ubuf);
+	}
+
+	return ret;
+}
+
+static int compat_vfp_set(struct task_struct *target,
+			  const struct user_regset *regset,
+			  unsigned int pos, unsigned int count,
+			  const void *kbuf, const void __user *ubuf)
+{
+	struct user_fpsimd_state *uregs;
+	compat_ulong_t fpscr;
+	int ret;
+
+	if (pos + count > VFP_STATE_SIZE)
+		return -EIO;
+
+	uregs = &target->thread.fpsimd_state.user_fpsimd;
+
+	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, uregs, 0,
+				 VFP_STATE_SIZE - sizeof(compat_ulong_t));
+
+	if (count && !ret) {
+		ret = get_user(fpscr, (compat_ulong_t *)ubuf);
+		uregs->fpsr = fpscr & VFP_FPSCR_STAT_MASK;
+		uregs->fpcr = fpscr & VFP_FPSCR_CTRL_MASK;
+	}
+
+	return ret;
+}
+
+static const struct user_regset aarch32_regsets[] = {
+	[REGSET_COMPAT_GPR] = {
+		.core_note_type = NT_PRSTATUS,
+		.n = COMPAT_ELF_NGREG,
+		.size = sizeof(compat_elf_greg_t),
+		.align = sizeof(compat_elf_greg_t),
+		.get = compat_gpr_get,
+		.set = compat_gpr_set
+	},
+	[REGSET_COMPAT_VFP] = {
+		.core_note_type = NT_ARM_VFP,
+		.n = VFP_STATE_SIZE / sizeof(compat_ulong_t),
+		.size = sizeof(compat_ulong_t),
+		.align = sizeof(compat_ulong_t),
+		.get = compat_vfp_get,
+		.set = compat_vfp_set
+	},
+};
+
+static const struct user_regset_view user_aarch32_view = {
+	.name = "aarch32", .e_machine = EM_ARM,
+	.regsets = aarch32_regsets, .n = ARRAY_SIZE(aarch32_regsets)
+};
+
+int aarch32_break_trap(struct pt_regs *regs)
+{
+	unsigned int instr;
+	bool bp = false;
+	void __user *pc = (void __user *)instruction_pointer(regs);
+
+	if (compat_thumb_mode(regs)) {
+		/* get 16-bit Thumb instruction */
+		get_user(instr, (u16 __user *)pc);
+		if (instr == AARCH32_BREAK_THUMB2_LO) {
+			/* get second half of 32-bit Thumb-2 instruction */
+			get_user(instr, (u16 __user *)(pc + 2));
+			bp = instr == AARCH32_BREAK_THUMB2_HI;
+		} else {
+			bp = instr == AARCH32_BREAK_THUMB;
+		}
+	} else {
+		/* 32-bit ARM instruction */
+		get_user(instr, (u32 __user *)pc);
+		bp = (instr & ~0xf0000000) == AARCH32_BREAK_ARM;
+	}
+
+	if (bp)
+		return ptrace_break(regs);
+	return 1;
+}
+
+static int compat_ptrace_read_user(struct task_struct *tsk, compat_ulong_t off,
+				   compat_ulong_t __user *ret)
+{
+	compat_ulong_t tmp;
+
+	if (off & 3)
+		return -EIO;
+
+	if (off == PT_TEXT_ADDR)
+		tmp = tsk->mm->start_code;
+	else if (off == PT_DATA_ADDR)
+		tmp = tsk->mm->start_data;
+	else if (off == PT_TEXT_END_ADDR)
+		tmp = tsk->mm->end_code;
+	else if (off < sizeof(compat_elf_gregset_t))
+		return copy_regset_to_user(tsk, &user_aarch32_view,
+					   REGSET_COMPAT_GPR, off,
+					   sizeof(compat_ulong_t), ret);
+	else if (off >= COMPAT_USER_SZ)
+		return -EIO;
+	else
+		tmp = 0;
+
+	return put_user(tmp, ret);
+}
+
+static int compat_ptrace_write_user(struct task_struct *tsk, compat_ulong_t off,
+				    compat_ulong_t val)
+{
+	int ret;
+
+	if (off & 3 || off >= COMPAT_USER_SZ)
+		return -EIO;
+
+	if (off >= sizeof(compat_elf_gregset_t))
+		return 0;
+
+	ret = copy_regset_from_user(tsk, &user_aarch32_view,
+				    REGSET_COMPAT_GPR, off,
+				    sizeof(compat_ulong_t),
+				    &val);
+	return ret;
+}
+
+#ifdef CONFIG_HAVE_HW_BREAKPOINT
+
+/*
+ * Convert a virtual register number into an index for a thread_info
+ * breakpoint array. Breakpoints are identified using positive numbers
+ * whilst watchpoints are negative. The registers are laid out as pairs
+ * of (address, control), each pair mapping to a unique hw_breakpoint struct.
+ * Register 0 is reserved for describing resource information.
+ */
+static int compat_ptrace_hbp_num_to_idx(compat_long_t num)
+{
+	return (abs(num) - 1) >> 1;
+}
+
+static int compat_ptrace_hbp_get_resource_info(u32 *kdata)
+{
+	u8 num_brps, num_wrps, debug_arch, wp_len;
+	u32 reg = 0;
+
+	num_brps	= hw_breakpoint_slots(TYPE_INST);
+	num_wrps	= hw_breakpoint_slots(TYPE_DATA);
+
+	debug_arch	= debug_monitors_arch();
+	wp_len		= 8;
+	reg		|= debug_arch;
+	reg		<<= 8;
+	reg		|= wp_len;
+	reg		<<= 8;
+	reg		|= num_wrps;
+	reg		<<= 8;
+	reg		|= num_brps;
+
+	*kdata = reg;
+	return 0;
+}
+
+static int compat_ptrace_hbp_get(unsigned int note_type,
+				 struct task_struct *tsk,
+				 compat_long_t num,
+				 u32 *kdata)
+{
+	u64 addr = 0;
+	u32 ctrl = 0;
+
+	int err, idx = compat_ptrace_hbp_num_to_idx(num);;
+
+	if (num & 1) {
+		err = ptrace_hbp_get_addr(note_type, tsk, idx, &addr);
+		*kdata = (u32)addr;
+	} else {
+		err = ptrace_hbp_get_ctrl(note_type, tsk, idx, &ctrl);
+		*kdata = ctrl;
+	}
+
+	return err;
+}
+
+static int compat_ptrace_hbp_set(unsigned int note_type,
+				 struct task_struct *tsk,
+				 compat_long_t num,
+				 u32 *kdata)
+{
+	u64 addr;
+	u32 ctrl;
+
+	int err, idx = compat_ptrace_hbp_num_to_idx(num);
+
+	if (num & 1) {
+		addr = *kdata;
+		err = ptrace_hbp_set_addr(note_type, tsk, idx, addr);
+	} else {
+		ctrl = *kdata;
+		err = ptrace_hbp_set_ctrl(note_type, tsk, idx, ctrl);
+	}
+
+	return err;
+}
+
+static int compat_ptrace_gethbpregs(struct task_struct *tsk, compat_long_t num,
+				    compat_ulong_t __user *data)
+{
+	int ret;
+	u32 kdata;
+	mm_segment_t old_fs = get_fs();
+
+	set_fs(KERNEL_DS);
+	/* Watchpoint */
+	if (num < 0) {
+		ret = compat_ptrace_hbp_get(NT_ARM_HW_WATCH, tsk, num, &kdata);
+	/* Resource info */
+	} else if (num == 0) {
+		ret = compat_ptrace_hbp_get_resource_info(&kdata);
+	/* Breakpoint */
+	} else {
+		ret = compat_ptrace_hbp_get(NT_ARM_HW_BREAK, tsk, num, &kdata);
+	}
+	set_fs(old_fs);
+
+	if (!ret)
+		ret = put_user(kdata, data);
+
+	return ret;
+}
+
+static int compat_ptrace_sethbpregs(struct task_struct *tsk, compat_long_t num,
+				    compat_ulong_t __user *data)
+{
+	int ret;
+	u32 kdata = 0;
+	mm_segment_t old_fs = get_fs();
+
+	if (num == 0)
+		return 0;
+
+	ret = get_user(kdata, data);
+	if (ret)
+		return ret;
+
+	set_fs(KERNEL_DS);
+	if (num < 0)
+		ret = compat_ptrace_hbp_set(NT_ARM_HW_WATCH, tsk, num, &kdata);
+	else
+		ret = compat_ptrace_hbp_set(NT_ARM_HW_BREAK, tsk, num, &kdata);
+	set_fs(old_fs);
+
+	return ret;
+}
+#endif	/* CONFIG_HAVE_HW_BREAKPOINT */
+
+long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
+			compat_ulong_t caddr, compat_ulong_t cdata)
+{
+	unsigned long addr = caddr;
+	unsigned long data = cdata;
+	void __user *datap = compat_ptr(data);
+	int ret;
+
+	switch (request) {
+		case PTRACE_PEEKUSR:
+			ret = compat_ptrace_read_user(child, addr, datap);
+			break;
+
+		case PTRACE_POKEUSR:
+			ret = compat_ptrace_write_user(child, addr, data);
+			break;
+
+		case PTRACE_GETREGS:
+			ret = copy_regset_to_user(child,
+						  &user_aarch32_view,
+						  REGSET_COMPAT_GPR,
+						  0, sizeof(compat_elf_gregset_t),
+						  datap);
+			break;
+
+		case PTRACE_SETREGS:
+			ret = copy_regset_from_user(child,
+						    &user_aarch32_view,
+						    REGSET_COMPAT_GPR,
+						    0, sizeof(compat_elf_gregset_t),
+						    datap);
+			break;
+
+		case PTRACE_GET_THREAD_AREA:
+			ret = put_user((compat_ulong_t)child->thread.tp_value,
+				       (compat_ulong_t __user *)datap);
+			break;
+
+		case PTRACE_SET_SYSCALL:
+			task_pt_regs(child)->syscallno = data;
+			ret = 0;
+			break;
+
+		case COMPAT_PTRACE_GETVFPREGS:
+			ret = copy_regset_to_user(child,
+						  &user_aarch32_view,
+						  REGSET_COMPAT_VFP,
+						  0, VFP_STATE_SIZE,
+						  datap);
+			break;
+
+		case COMPAT_PTRACE_SETVFPREGS:
+			ret = copy_regset_from_user(child,
+						    &user_aarch32_view,
+						    REGSET_COMPAT_VFP,
+						    0, VFP_STATE_SIZE,
+						    datap);
+			break;
+
+#ifdef CONFIG_HAVE_HW_BREAKPOINT
+		case PTRACE_GETHBPREGS:
+			ret = compat_ptrace_gethbpregs(child, addr, datap);
+			break;
+
+		case PTRACE_SETHBPREGS:
+			ret = compat_ptrace_sethbpregs(child, addr, datap);
+			break;
+#endif
+
+		default:
+			ret = compat_ptrace_request(child, request, addr,
+						    data);
+			break;
+	}
+
+	return ret;
+}
+#endif /* CONFIG_COMPAT */
+
+const struct user_regset_view *task_user_regset_view(struct task_struct *task)
+{
+#ifdef CONFIG_COMPAT
+	if (is_compat_thread(task_thread_info(task)))
+		return &user_aarch32_view;
+#endif
+	return &user_aarch64_view;
+}
+
+long arch_ptrace(struct task_struct *child, long request,
+		 unsigned long addr, unsigned long data)
+{
+	return ptrace_request(child, request, addr, data);
+}
+
+
+static int __init ptrace_break_init(void)
+{
+	hook_debug_fault_code(DBG_ESR_EVT_BRK, arm64_break_trap, SIGTRAP,
+			      TRAP_BRKPT, "ptrace BRK handler");
+	return 0;
+}
+core_initcall(ptrace_break_init);
+
+
+asmlinkage int syscall_trace(int dir, struct pt_regs *regs)
+{
+	unsigned long saved_reg;
+
+	if (!test_thread_flag(TIF_SYSCALL_TRACE))
+		return regs->syscallno;
+
+	if (is_compat_task()) {
+		/* AArch32 uses ip (r12) for scratch */
+		saved_reg = regs->regs[12];
+		regs->regs[12] = dir;
+	} else {
+		/*
+		 * Save X7. X7 is used to denote syscall entry/exit:
+		 *   X7 = 0 -> entry, = 1 -> exit
+		 */
+		saved_reg = regs->regs[7];
+		regs->regs[7] = dir;
+	}
+
+	if (dir)
+		tracehook_report_syscall_exit(regs, 0);
+	else if (tracehook_report_syscall_entry(regs))
+		regs->syscallno = ~0UL;
+
+	if (is_compat_task())
+		regs->regs[12] = saved_reg;
+	else
+		regs->regs[7] = saved_reg;
+
+	return regs->syscallno;
+}
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
new file mode 100644
index 0000000..48ffb9f
--- /dev/null
+++ b/arch/arm64/kernel/setup.c
@@ -0,0 +1,347 @@
+/*
+ * Based on arch/arm/kernel/setup.c
+ *
+ * Copyright (C) 1995-2001 Russell King
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/export.h>
+#include <linux/kernel.h>
+#include <linux/stddef.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/utsname.h>
+#include <linux/initrd.h>
+#include <linux/console.h>
+#include <linux/bootmem.h>
+#include <linux/seq_file.h>
+#include <linux/screen_info.h>
+#include <linux/init.h>
+#include <linux/kexec.h>
+#include <linux/crash_dump.h>
+#include <linux/root_dev.h>
+#include <linux/cpu.h>
+#include <linux/interrupt.h>
+#include <linux/smp.h>
+#include <linux/fs.h>
+#include <linux/proc_fs.h>
+#include <linux/memblock.h>
+#include <linux/of_fdt.h>
+
+#include <asm/cputype.h>
+#include <asm/elf.h>
+#include <asm/cputable.h>
+#include <asm/sections.h>
+#include <asm/setup.h>
+#include <asm/cacheflush.h>
+#include <asm/tlbflush.h>
+#include <asm/traps.h>
+#include <asm/memblock.h>
+
+unsigned int processor_id;
+EXPORT_SYMBOL(processor_id);
+
+unsigned int elf_hwcap __read_mostly;
+EXPORT_SYMBOL_GPL(elf_hwcap);
+
+static const char *cpu_name;
+static const char *machine_name;
+phys_addr_t __fdt_pointer __initdata;
+
+/*
+ * Standard memory resources
+ */
+static struct resource mem_res[] = {
+	{
+		.name = "Kernel code",
+		.start = 0,
+		.end = 0,
+		.flags = IORESOURCE_MEM
+	},
+	{
+		.name = "Kernel data",
+		.start = 0,
+		.end = 0,
+		.flags = IORESOURCE_MEM
+	}
+};
+
+#define kernel_code mem_res[0]
+#define kernel_data mem_res[1]
+
+void __init early_print(const char *str, ...)
+{
+	char buf[256];
+	va_list ap;
+
+	va_start(ap, str);
+	vsnprintf(buf, sizeof(buf), str, ap);
+	va_end(ap);
+
+	printk("%s", buf);
+}
+
+static void __init setup_processor(void)
+{
+	struct cpu_info *cpu_info;
+
+	/*
+	 * locate processor in the list of supported processor
+	 * types.  The linker builds this table for us from the
+	 * entries in arch/arm/mm/proc.S
+	 */
+	cpu_info = lookup_processor_type(read_cpuid_id());
+	if (!cpu_info) {
+		printk("CPU configuration botched (ID %08x), unable to continue.\n",
+		       read_cpuid_id());
+		while (1);
+	}
+
+	cpu_name = cpu_info->cpu_name;
+
+	printk("CPU: %s [%08x] revision %d\n",
+	       cpu_name, read_cpuid_id(), read_cpuid_id() & 15);
+
+	sprintf(init_utsname()->machine, "aarch64");
+	elf_hwcap = 0;
+}
+
+static void __init setup_machine_fdt(phys_addr_t dt_phys)
+{
+	struct boot_param_header *devtree;
+	unsigned long dt_root;
+
+	/* Check we have a non-NULL DT pointer */
+	if (!dt_phys) {
+		early_print("\n"
+			"Error: NULL or invalid device tree blob\n"
+			"The dtb must be 8-byte aligned and passed in the first 512MB of memory\n"
+			"\nPlease check your bootloader.\n");
+
+		while (true)
+			cpu_relax();
+
+	}
+
+	devtree = phys_to_virt(dt_phys);
+
+	/* Check device tree validity */
+	if (be32_to_cpu(devtree->magic) != OF_DT_HEADER) {
+		early_print("\n"
+			"Error: invalid device tree blob at physical address 0x%p (virtual address 0x%p)\n"
+			"Expected 0x%x, found 0x%x\n"
+			"\nPlease check your bootloader.\n",
+			dt_phys, devtree, OF_DT_HEADER,
+			be32_to_cpu(devtree->magic));
+
+		while (true)
+			cpu_relax();
+	}
+
+	initial_boot_params = devtree;
+	dt_root = of_get_flat_dt_root();
+
+	machine_name = of_get_flat_dt_prop(dt_root, "model", NULL);
+	if (!machine_name)
+		machine_name = of_get_flat_dt_prop(dt_root, "compatible", NULL);
+	if (!machine_name)
+		machine_name = "<unknown>";
+	pr_info("Machine: %s\n", machine_name);
+
+	/* Retrieve various information from the /chosen node */
+	of_scan_flat_dt(early_init_dt_scan_chosen, boot_command_line);
+	/* Initialize {size,address}-cells info */
+	of_scan_flat_dt(early_init_dt_scan_root, NULL);
+	/* Setup memory, calling early_init_dt_add_memory_arch */
+	of_scan_flat_dt(early_init_dt_scan_memory, NULL);
+}
+
+void __init early_init_dt_add_memory_arch(u64 base, u64 size)
+{
+	size &= PAGE_MASK;
+	memblock_add(base, size);
+}
+
+void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
+{
+	return __va(memblock_alloc(size, align));
+}
+
+/*
+ * Limit the memory size that was specified via FDT.
+ */
+static int __init early_mem(char *p)
+{
+	phys_addr_t limit;
+
+	if (!p)
+		return 1;
+
+	limit = memparse(p, &p) & PAGE_MASK;
+	pr_notice("Memory limited to %lldMB\n", limit >> 20);
+
+	memblock_enforce_memory_limit(limit);
+
+	return 0;
+}
+early_param("mem", early_mem);
+
+static void __init request_standard_resources(void)
+{
+	struct memblock_region *region;
+	struct resource *res;
+
+	kernel_code.start   = virt_to_phys(_text);
+	kernel_code.end     = virt_to_phys(_etext - 1);
+	kernel_data.start   = virt_to_phys(_sdata);
+	kernel_data.end     = virt_to_phys(_end - 1);
+
+	for_each_memblock(memory, region) {
+		res = alloc_bootmem_low(sizeof(*res));
+		res->name  = "System RAM";
+		res->start = __pfn_to_phys(memblock_region_memory_base_pfn(region));
+		res->end = __pfn_to_phys(memblock_region_memory_end_pfn(region)) - 1;
+		res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+
+		request_resource(&iomem_resource, res);
+
+		if (kernel_code.start >= res->start &&
+		    kernel_code.end <= res->end)
+			request_resource(res, &kernel_code);
+		if (kernel_data.start >= res->start &&
+		    kernel_data.end <= res->end)
+			request_resource(res, &kernel_data);
+	}
+}
+
+void __init setup_arch(char **cmdline_p)
+{
+	setup_processor();
+
+	setup_machine_fdt(__fdt_pointer);
+
+	init_mm.start_code = (unsigned long) _text;
+	init_mm.end_code   = (unsigned long) _etext;
+	init_mm.end_data   = (unsigned long) _edata;
+	init_mm.brk	   = (unsigned long) _end;
+
+	*cmdline_p = boot_command_line;
+
+	parse_early_param();
+
+	arm64_memblock_init();
+
+	paging_init();
+	request_standard_resources();
+
+	unflatten_device_tree();
+
+#ifdef CONFIG_SMP
+	smp_init_cpus();
+#endif
+
+#ifdef CONFIG_VT
+#if defined(CONFIG_VGA_CONSOLE)
+	conswitchp = &vga_con;
+#elif defined(CONFIG_DUMMY_CONSOLE)
+	conswitchp = &dummy_con;
+#endif
+#endif
+}
+
+static DEFINE_PER_CPU(struct cpu, cpu_data);
+
+static int __init topology_init(void)
+{
+	int i;
+
+	for_each_possible_cpu(i) {
+		struct cpu *cpu = &per_cpu(cpu_data, i);
+		cpu->hotpluggable = 1;
+		register_cpu(cpu, i);
+	}
+
+	return 0;
+}
+subsys_initcall(topology_init);
+
+static const char *hwcap_str[] = {
+	"fp",
+	"asimd",
+	NULL
+};
+
+static int c_show(struct seq_file *m, void *v)
+{
+	int i;
+
+	seq_printf(m, "Processor\t: %s rev %d (%s)\n",
+		   cpu_name, read_cpuid_id() & 15, ELF_PLATFORM);
+
+	for_each_online_cpu(i) {
+		/*
+		 * glibc reads /proc/cpuinfo to determine the number of
+		 * online processors, looking for lines beginning with
+		 * "processor".  Give glibc what it expects.
+		 */
+#ifdef CONFIG_SMP
+		seq_printf(m, "processor\t: %d\n", i);
+#endif
+		seq_printf(m, "BogoMIPS\t: %lu.%02lu\n\n",
+			   loops_per_jiffy / (500000UL/HZ),
+			   loops_per_jiffy / (5000UL/HZ) % 100);
+	}
+
+	/* dump out the processor features */
+	seq_puts(m, "Features\t: ");
+
+	for (i = 0; hwcap_str[i]; i++)
+		if (elf_hwcap & (1 << i))
+			seq_printf(m, "%s ", hwcap_str[i]);
+
+	seq_printf(m, "\nCPU implementer\t: 0x%02x\n", read_cpuid_id() >> 24);
+	seq_printf(m, "CPU architecture: AArch64\n");
+	seq_printf(m, "CPU variant\t: 0x%x\n", (read_cpuid_id() >> 20) & 15);
+	seq_printf(m, "CPU part\t: 0x%03x\n", (read_cpuid_id() >> 4) & 0xfff);
+	seq_printf(m, "CPU revision\t: %d\n", read_cpuid_id() & 15);
+
+	seq_puts(m, "\n");
+
+	seq_printf(m, "Hardware\t: %s\n", machine_name);
+
+	return 0;
+}
+
+static void *c_start(struct seq_file *m, loff_t *pos)
+{
+	return *pos < 1 ? (void *)1 : NULL;
+}
+
+static void *c_next(struct seq_file *m, void *v, loff_t *pos)
+{
+	++*pos;
+	return NULL;
+}
+
+static void c_stop(struct seq_file *m, void *v)
+{
+}
+
+const struct seq_operations cpuinfo_op = {
+	.start	= c_start,
+	.next	= c_next,
+	.stop	= c_stop,
+	.show	= c_show
+};
diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
new file mode 100644
index 0000000..8807ba2
--- /dev/null
+++ b/arch/arm64/kernel/signal.c
@@ -0,0 +1,437 @@
+/*
+ * Based on arch/arm/kernel/signal.c
+ *
+ * Copyright (C) 1995-2009 Russell King
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/personality.h>
+#include <linux/freezer.h>
+#include <linux/uaccess.h>
+#include <linux/tracehook.h>
+#include <linux/ratelimit.h>
+
+#include <asm/compat.h>
+#include <asm/debug-monitors.h>
+#include <asm/elf.h>
+#include <asm/cacheflush.h>
+#include <asm/ucontext.h>
+#include <asm/unistd.h>
+#include <asm/fpsimd.h>
+#include <asm/signal32.h>
+#include <asm/vdso.h>
+
+/*
+ * Do a signal return; undo the signal stack. These are aligned to 128-bit.
+ */
+struct rt_sigframe {
+	struct siginfo info;
+	struct ucontext uc;
+};
+
+static int preserve_fpsimd_context(struct fpsimd_context __user *ctx)
+{
+	struct fpsimd_state *fpsimd = &current->thread.fpsimd_state;
+	int err;
+
+	/* dump the hardware registers to the fpsimd_state structure */
+	fpsimd_save_state(fpsimd);
+
+	/* copy the FP and status/control registers */
+	err = __copy_to_user(ctx->vregs, fpsimd->vregs, sizeof(fpsimd->vregs));
+	__put_user_error(fpsimd->fpsr, &ctx->fpsr, err);
+	__put_user_error(fpsimd->fpcr, &ctx->fpcr, err);
+
+	/* copy the magic/size information */
+	__put_user_error(FPSIMD_MAGIC, &ctx->head.magic, err);
+	__put_user_error(sizeof(struct fpsimd_context), &ctx->head.size, err);
+
+	return err ? -EFAULT : 0;
+}
+
+static int restore_fpsimd_context(struct fpsimd_context __user *ctx)
+{
+	struct fpsimd_state fpsimd;
+	__u32 magic, size;
+	int err = 0;
+
+	/* check the magic/size information */
+	__get_user_error(magic, &ctx->head.magic, err);
+	__get_user_error(size, &ctx->head.size, err);
+	if (err)
+		return -EFAULT;
+	if (magic != FPSIMD_MAGIC || size != sizeof(struct fpsimd_context))
+		return -EINVAL;
+
+	/* copy the FP and status/control registers */
+	err = __copy_from_user(fpsimd.vregs, ctx->vregs,
+			       sizeof(fpsimd.vregs));
+	__get_user_error(fpsimd.fpsr, &ctx->fpsr, err);
+	__get_user_error(fpsimd.fpcr, &ctx->fpcr, err);
+
+	/* load the hardware registers from the fpsimd_state structure */
+	if (!err) {
+		preempt_disable();
+		fpsimd_load_state(&fpsimd);
+		preempt_enable();
+	}
+
+	return err ? -EFAULT : 0;
+}
+
+static int restore_sigframe(struct pt_regs *regs,
+			    struct rt_sigframe __user *sf)
+{
+	sigset_t set;
+	int i, err;
+	struct aux_context __user *aux =
+		(struct aux_context __user *)sf->uc.uc_mcontext.__reserved;
+
+	err = __copy_from_user(&set, &sf->uc.uc_sigmask, sizeof(set));
+	if (err == 0)
+		set_current_blocked(&set);
+
+	for (i = 0; i < 31; i++)
+		__get_user_error(regs->regs[i], &sf->uc.uc_mcontext.regs[i],
+				 err);
+	__get_user_error(regs->sp, &sf->uc.uc_mcontext.sp, err);
+	__get_user_error(regs->pc, &sf->uc.uc_mcontext.pc, err);
+	__get_user_error(regs->pstate, &sf->uc.uc_mcontext.pstate, err);
+
+	/*
+	 * Avoid sys_rt_sigreturn() restarting.
+	 */
+	regs->syscallno = ~0UL;
+
+	err |= !valid_user_regs(&regs->user_regs);
+
+	if (err == 0)
+		err |= restore_fpsimd_context(&aux->fpsimd);
+
+	return err;
+}
+
+asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
+{
+	struct rt_sigframe __user *frame;
+
+	/* Always make any pending restarted system calls return -EINTR */
+	current_thread_info()->restart_block.fn = do_no_restart_syscall;
+
+	/*
+	 * Since we stacked the signal on a 128-bit boundary, then 'sp' should
+	 * be word aligned here.
+	 */
+	if (regs->sp & 15)
+		goto badframe;
+
+	frame = (struct rt_sigframe __user *)regs->sp;
+
+	if (!access_ok(VERIFY_READ, frame, sizeof (*frame)))
+		goto badframe;
+
+	if (restore_sigframe(regs, frame))
+		goto badframe;
+
+	if (do_sigaltstack(&frame->uc.uc_stack,
+			   NULL, regs->sp) == -EFAULT)
+		goto badframe;
+
+	return regs->regs[0];
+
+badframe:
+	if (show_unhandled_signals)
+		pr_info_ratelimited("%s[%d]: bad frame in %s: pc=%08llx sp=%08llx\n",
+				    current->comm, task_pid_nr(current), __func__,
+				    regs->pc, regs->sp);
+	force_sig(SIGSEGV, current);
+	return 0;
+}
+
+asmlinkage long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
+				unsigned long sp)
+{
+	return do_sigaltstack(uss, uoss, sp);
+}
+
+static int setup_sigframe(struct rt_sigframe __user *sf,
+			  struct pt_regs *regs, sigset_t *set)
+{
+	int i, err = 0;
+	struct aux_context __user *aux =
+		(struct aux_context __user *)sf->uc.uc_mcontext.__reserved;
+
+	for (i = 0; i < 31; i++)
+		__put_user_error(regs->regs[i], &sf->uc.uc_mcontext.regs[i],
+				 err);
+	__put_user_error(regs->sp, &sf->uc.uc_mcontext.sp, err);
+	__put_user_error(regs->pc, &sf->uc.uc_mcontext.pc, err);
+	__put_user_error(regs->pstate, &sf->uc.uc_mcontext.pstate, err);
+
+	__put_user_error(current->thread.fault_address, &sf->uc.uc_mcontext.fault_address, err);
+
+	err |= __copy_to_user(&sf->uc.uc_sigmask, set, sizeof(*set));
+
+	if (err == 0)
+		err |= preserve_fpsimd_context(&aux->fpsimd);
+
+	/* set the "end" magic */
+	__put_user_error(0, &aux->end.magic, err);
+	__put_user_error(0, &aux->end.size, err);
+
+	return err;
+}
+
+static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
+				 int framesize)
+{
+	unsigned long sp, sp_top;
+	void __user *frame;
+
+	sp = sp_top = regs->sp;
+
+	/*
+	 * This is the X/Open sanctioned signal stack switching.
+	 */
+	if ((ka->sa.sa_flags & SA_ONSTACK) && !sas_ss_flags(sp))
+		sp = sp_top = current->sas_ss_sp + current->sas_ss_size;
+
+	/* room for stack frame (FP, LR) */
+	sp -= 16;
+
+	sp = (sp - framesize) & ~15;
+	frame = (void __user *)sp;
+
+	/*
+	 * Check that we can actually write to the signal frame.
+	 */
+	if (!access_ok(VERIFY_WRITE, frame, sp_top - sp))
+		frame = NULL;
+
+	return frame;
+}
+
+static int setup_return(struct pt_regs *regs, struct k_sigaction *ka,
+			void __user *frame, int usig)
+{
+	int err = 0;
+	__sigrestore_t sigtramp;
+	unsigned long __user *sp = (unsigned long __user *)regs->sp;
+
+	/* set up the stack frame */
+	__put_user_error(regs->regs[29], sp - 2, err);
+	__put_user_error(regs->regs[30], sp - 1, err);
+
+	regs->regs[0] = usig;
+	regs->regs[29] = regs->sp - 16;
+	regs->sp = (unsigned long)frame;
+	regs->pc = (unsigned long)ka->sa.sa_handler;
+
+	if (ka->sa.sa_flags & SA_RESTORER)
+		sigtramp = ka->sa.sa_restorer;
+	else
+		sigtramp = VDSO_SYMBOL(current->mm->context.vdso, sigtramp);
+
+	regs->regs[30] = (unsigned long)sigtramp;
+
+	return err;
+}
+
+static int setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
+			  sigset_t *set, struct pt_regs *regs)
+{
+	struct rt_sigframe __user *frame;
+	stack_t stack;
+	int err = 0;
+
+	frame = get_sigframe(ka, regs, sizeof(*frame));
+	if (!frame)
+		return 1;
+
+	__put_user_error(0, &frame->uc.uc_flags, err);
+	__put_user_error(NULL, &frame->uc.uc_link, err);
+
+	memset(&stack, 0, sizeof(stack));
+	stack.ss_sp = (void __user *)current->sas_ss_sp;
+	stack.ss_flags = sas_ss_flags(regs->sp);
+	stack.ss_size = current->sas_ss_size;
+	err |= __copy_to_user(&frame->uc.uc_stack, &stack, sizeof(stack));
+
+	err |= setup_sigframe(frame, regs, set);
+	if (err == 0)
+		err = setup_return(regs, ka, frame, usig);
+
+	if (err == 0 && ka->sa.sa_flags & SA_SIGINFO) {
+		err |= copy_siginfo_to_user(&frame->info, info);
+		regs->regs[1] = (unsigned long)&frame->info;
+		regs->regs[2] = (unsigned long)&frame->uc;
+	}
+
+	return err;
+}
+
+static void setup_restart_syscall(struct pt_regs *regs)
+{
+	if (is_compat_task())
+		compat_setup_restart_syscall(regs);
+	else
+		regs->regs[8] = __NR_restart_syscall;
+}
+
+/*
+ * OK, we're invoking a handler
+ */
+static void handle_signal(unsigned long sig, struct k_sigaction *ka,
+			  siginfo_t *info, struct pt_regs *regs)
+{
+	struct thread_info *thread = current_thread_info();
+	struct task_struct *tsk = current;
+	sigset_t *oldset = sigmask_to_save();
+	int usig = sig;
+	int ret;
+
+	/*
+	 * translate the signal
+	 */
+	if (usig < 32 && thread->exec_domain && thread->exec_domain->signal_invmap)
+		usig = thread->exec_domain->signal_invmap[usig];
+
+	/*
+	 * Set up the stack frame
+	 */
+	if (is_compat_task()) {
+		if (ka->sa.sa_flags & SA_SIGINFO)
+			ret = compat_setup_rt_frame(usig, ka, info, oldset,
+						    regs);
+		else
+			ret = compat_setup_frame(usig, ka, oldset, regs);
+	} else {
+		ret = setup_rt_frame(usig, ka, info, oldset, regs);
+	}
+
+	/*
+	 * Check that the resulting registers are actually sane.
+	 */
+	ret |= !valid_user_regs(&regs->user_regs);
+
+	if (ret != 0) {
+		force_sigsegv(sig, tsk);
+		return;
+	}
+
+	/*
+	 * Fast forward the stepping logic so we step into the signal
+	 * handler.
+	 */
+	user_fastforward_single_step(tsk);
+
+	signal_delivered(sig, info, ka, regs, 0);
+}
+
+/*
+ * Note that 'init' is a special process: it doesn't get signals it doesn't
+ * want to handle. Thus you cannot kill init even with a SIGKILL even by
+ * mistake.
+ *
+ * Note that we go through the signals twice: once to check the signals that
+ * the kernel can handle, and then we build all the user-level signal handling
+ * stack-frames in one go after that.
+ */
+static void do_signal(struct pt_regs *regs)
+{
+	unsigned long continue_addr = 0, restart_addr = 0;
+	struct k_sigaction ka;
+	siginfo_t info;
+	int signr, retval = 0;
+	int syscall = (int)regs->syscallno;
+
+	/*
+	 * If we were from a system call, check for system call restarting...
+	 */
+	if (syscall >= 0) {
+		continue_addr = regs->pc;
+		restart_addr = continue_addr - (compat_thumb_mode(regs) ? 2 : 4);
+		retval = regs->regs[0];
+
+		/*
+		 * Avoid additional syscall restarting via ret_to_user.
+		 */
+		regs->syscallno = ~0UL;
+
+		/*
+		 * Prepare for system call restart. We do this here so that a
+		 * debugger will see the already changed PC.
+		 */
+		switch (retval) {
+		case -ERESTARTNOHAND:
+		case -ERESTARTSYS:
+		case -ERESTARTNOINTR:
+		case -ERESTART_RESTARTBLOCK:
+			regs->regs[0] = regs->orig_x0;
+			regs->pc = restart_addr;
+			break;
+		}
+	}
+
+	/*
+	 * Get the signal to deliver. When running under ptrace, at this point
+	 * the debugger may change all of our registers.
+	 */
+	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
+	if (signr > 0) {
+		/*
+		 * Depending on the signal settings, we may need to revert the
+		 * decision to restart the system call, but skip this if a
+		 * debugger has chosen to restart at a different PC.
+		 */
+		if (regs->pc == restart_addr &&
+		    (retval == -ERESTARTNOHAND ||
+		     retval == -ERESTART_RESTARTBLOCK ||
+		     (retval == -ERESTARTSYS &&
+		      !(ka.sa.sa_flags & SA_RESTART)))) {
+			regs->regs[0] = -EINTR;
+			regs->pc = continue_addr;
+		}
+
+		handle_signal(signr, &ka, &info, regs);
+		return;
+	}
+
+	/*
+	 * Handle restarting a different system call. As above, if a debugger
+	 * has chosen to restart at a different PC, ignore the restart.
+	 */
+	if (syscall >= 0 && regs->pc == restart_addr) {
+		if (retval == -ERESTART_RESTARTBLOCK)
+			setup_restart_syscall(regs);
+		user_rewind_single_step(current);
+	}
+
+	restore_saved_sigmask();
+}
+
+asmlinkage void do_notify_resume(struct pt_regs *regs,
+				 unsigned int thread_flags)
+{
+	if (thread_flags & _TIF_SIGPENDING)
+		do_signal(regs);
+
+	if (thread_flags & _TIF_NOTIFY_RESUME) {
+		clear_thread_flag(TIF_NOTIFY_RESUME);
+		tracehook_notify_resume(regs);
+	}
+}
diff --git a/arch/arm64/kernel/signal32.c b/arch/arm64/kernel/signal32.c
new file mode 100644
index 0000000..0790a87
--- /dev/null
+++ b/arch/arm64/kernel/signal32.c
@@ -0,0 +1,823 @@
+/*
+ * Based on arch/arm/kernel/signal.c
+ *
+ * Copyright (C) 1995-2009 Russell King
+ * Copyright (C) 2012 ARM Ltd.
+ * Modified by Will Deacon <will.deacon@arm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define __SYSCALL_COMPAT
+
+#include <linux/compat.h>
+#include <linux/signal.h>
+#include <linux/syscalls.h>
+#include <linux/ratelimit.h>
+
+#include <asm/fpsimd.h>
+#include <asm/signal32.h>
+#include <asm/uaccess.h>
+#include <asm/unistd.h>
+
+struct compat_sigaction {
+	compat_uptr_t			sa_handler;
+	compat_ulong_t			sa_flags;
+	compat_uptr_t			sa_restorer;
+	compat_sigset_t			sa_mask;
+};
+
+struct compat_old_sigaction {
+	compat_uptr_t			sa_handler;
+	compat_old_sigset_t		sa_mask;
+	compat_ulong_t			sa_flags;
+	compat_uptr_t			sa_restorer;
+};
+
+typedef struct compat_sigaltstack {
+	compat_uptr_t			ss_sp;
+	int				ss_flags;
+	compat_size_t			ss_size;
+} compat_stack_t;
+
+struct compat_sigcontext {
+	/* We always set these two fields to 0 */
+	compat_ulong_t			trap_no;
+	compat_ulong_t			error_code;
+
+	compat_ulong_t			oldmask;
+	compat_ulong_t			arm_r0;
+	compat_ulong_t			arm_r1;
+	compat_ulong_t			arm_r2;
+	compat_ulong_t			arm_r3;
+	compat_ulong_t			arm_r4;
+	compat_ulong_t			arm_r5;
+	compat_ulong_t			arm_r6;
+	compat_ulong_t			arm_r7;
+	compat_ulong_t			arm_r8;
+	compat_ulong_t			arm_r9;
+	compat_ulong_t			arm_r10;
+	compat_ulong_t			arm_fp;
+	compat_ulong_t			arm_ip;
+	compat_ulong_t			arm_sp;
+	compat_ulong_t			arm_lr;
+	compat_ulong_t			arm_pc;
+	compat_ulong_t			arm_cpsr;
+	compat_ulong_t			fault_address;
+};
+
+struct compat_ucontext {
+	compat_ulong_t			uc_flags;
+	struct compat_ucontext		*uc_link;
+	compat_stack_t			uc_stack;
+	struct compat_sigcontext	uc_mcontext;
+	compat_sigset_t			uc_sigmask;
+	int		__unused[32 - (sizeof (compat_sigset_t) / sizeof (int))];
+	compat_ulong_t	uc_regspace[128] __attribute__((__aligned__(8)));
+};
+
+struct compat_vfp_sigframe {
+	compat_ulong_t	magic;
+	compat_ulong_t	size;
+	struct compat_user_vfp {
+		compat_u64	fpregs[32];
+		compat_ulong_t	fpscr;
+	} ufp;
+	struct compat_user_vfp_exc {
+		compat_ulong_t	fpexc;
+		compat_ulong_t	fpinst;
+		compat_ulong_t	fpinst2;
+	} ufp_exc;
+} __attribute__((__aligned__(8)));
+
+#define VFP_MAGIC		0x56465001
+#define VFP_STORAGE_SIZE	sizeof(struct compat_vfp_sigframe)
+
+struct compat_aux_sigframe {
+	struct compat_vfp_sigframe	vfp;
+
+	/* Something that isn't a valid magic number for any coprocessor.  */
+	unsigned long			end_magic;
+} __attribute__((__aligned__(8)));
+
+struct compat_sigframe {
+	struct compat_ucontext	uc;
+	compat_ulong_t		retcode[2];
+};
+
+struct compat_rt_sigframe {
+	struct compat_siginfo info;
+	struct compat_sigframe sig;
+};
+
+#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+
+/*
+ * For ARM syscalls, the syscall number has to be loaded into r7.
+ * We do not support an OABI userspace.
+ */
+#define MOV_R7_NR_SIGRETURN	(0xe3a07000 | __NR_sigreturn)
+#define SVC_SYS_SIGRETURN	(0xef000000 | __NR_sigreturn)
+#define MOV_R7_NR_RT_SIGRETURN	(0xe3a07000 | __NR_rt_sigreturn)
+#define SVC_SYS_RT_SIGRETURN	(0xef000000 | __NR_rt_sigreturn)
+
+/*
+ * For Thumb syscalls, we also pass the syscall number via r7. We therefore
+ * need two 16-bit instructions.
+ */
+#define SVC_THUMB_SIGRETURN	(((0xdf00 | __NR_sigreturn) << 16) | \
+				   0x2700 | __NR_sigreturn)
+#define SVC_THUMB_RT_SIGRETURN	(((0xdf00 | __NR_rt_sigreturn) << 16) | \
+				   0x2700 | __NR_rt_sigreturn)
+
+const compat_ulong_t aarch32_sigret_code[6] = {
+	/*
+	 * AArch32 sigreturn code.
+	 * We don't construct an OABI SWI - instead we just set the imm24 field
+	 * to the EABI syscall number so that we create a sane disassembly.
+	 */
+	MOV_R7_NR_SIGRETURN,    SVC_SYS_SIGRETURN,    SVC_THUMB_SIGRETURN,
+	MOV_R7_NR_RT_SIGRETURN, SVC_SYS_RT_SIGRETURN, SVC_THUMB_RT_SIGRETURN,
+};
+
+static inline int put_sigset_t(compat_sigset_t __user *uset, sigset_t *set)
+{
+	compat_sigset_t	cset;
+
+	cset.sig[0] = set->sig[0] & 0xffffffffull;
+	cset.sig[1] = set->sig[0] >> 32;
+
+	return copy_to_user(uset, &cset, sizeof(*uset));
+}
+
+static inline int get_sigset_t(sigset_t *set,
+			       const compat_sigset_t __user *uset)
+{
+	compat_sigset_t s32;
+
+	if (copy_from_user(&s32, uset, sizeof(*uset)))
+		return -EFAULT;
+
+	set->sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32);
+	return 0;
+}
+
+int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
+{
+	int err;
+
+	if (!access_ok(VERIFY_WRITE, to, sizeof(*to)))
+		return -EFAULT;
+
+	/* If you change siginfo_t structure, please be sure
+	 * this code is fixed accordingly.
+	 * It should never copy any pad contained in the structure
+	 * to avoid security leaks, but must copy the generic
+	 * 3 ints plus the relevant union member.
+	 * This routine must convert siginfo from 64bit to 32bit as well
+	 * at the same time.
+	 */
+	err = __put_user(from->si_signo, &to->si_signo);
+	err |= __put_user(from->si_errno, &to->si_errno);
+	err |= __put_user((short)from->si_code, &to->si_code);
+	if (from->si_code < 0)
+		err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad,
+				      SI_PAD_SIZE);
+	else switch (from->si_code & __SI_MASK) {
+	case __SI_KILL:
+		err |= __put_user(from->si_pid, &to->si_pid);
+		err |= __put_user(from->si_uid, &to->si_uid);
+		break;
+	case __SI_TIMER:
+		 err |= __put_user(from->si_tid, &to->si_tid);
+		 err |= __put_user(from->si_overrun, &to->si_overrun);
+		 err |= __put_user((compat_uptr_t)(unsigned long)from->si_ptr,
+				   &to->si_ptr);
+		break;
+	case __SI_POLL:
+		err |= __put_user(from->si_band, &to->si_band);
+		err |= __put_user(from->si_fd, &to->si_fd);
+		break;
+	case __SI_FAULT:
+		err |= __put_user((compat_uptr_t)(unsigned long)from->si_addr,
+				  &to->si_addr);
+#ifdef BUS_MCEERR_AO
+		/*
+		 * Other callers might not initialize the si_lsb field,
+		 * so check explicitely for the right codes here.
+		 */
+		if (from->si_code == BUS_MCEERR_AR || from->si_code == BUS_MCEERR_AO)
+			err |= __put_user(from->si_addr_lsb, &to->si_addr_lsb);
+#endif
+		break;
+	case __SI_CHLD:
+		err |= __put_user(from->si_pid, &to->si_pid);
+		err |= __put_user(from->si_uid, &to->si_uid);
+		err |= __put_user(from->si_status, &to->si_status);
+		err |= __put_user(from->si_utime, &to->si_utime);
+		err |= __put_user(from->si_stime, &to->si_stime);
+		break;
+	case __SI_RT: /* This is not generated by the kernel as of now. */
+	case __SI_MESGQ: /* But this is */
+		err |= __put_user(from->si_pid, &to->si_pid);
+		err |= __put_user(from->si_uid, &to->si_uid);
+		err |= __put_user((compat_uptr_t)(unsigned long)from->si_ptr, &to->si_ptr);
+		break;
+	default: /* this is just in case for now ... */
+		err |= __put_user(from->si_pid, &to->si_pid);
+		err |= __put_user(from->si_uid, &to->si_uid);
+		break;
+	}
+	return err;
+}
+
+int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
+{
+	memset(to, 0, sizeof *to);
+
+	if (copy_from_user(to, from, __ARCH_SI_PREAMBLE_SIZE) ||
+	    copy_from_user(to->_sifields._pad,
+			   from->_sifields._pad, SI_PAD_SIZE))
+		return -EFAULT;
+
+	return 0;
+}
+
+/*
+ * VFP save/restore code.
+ */
+static int compat_preserve_vfp_context(struct compat_vfp_sigframe __user *frame)
+{
+	struct fpsimd_state *fpsimd = &current->thread.fpsimd_state;
+	compat_ulong_t magic = VFP_MAGIC;
+	compat_ulong_t size = VFP_STORAGE_SIZE;
+	compat_ulong_t fpscr, fpexc;
+	int err = 0;
+
+	/*
+	 * Save the hardware registers to the fpsimd_state structure.
+	 * Note that this also saves V16-31, which aren't visible
+	 * in AArch32.
+	 */
+	fpsimd_save_state(fpsimd);
+
+	/* Place structure header on the stack */
+	__put_user_error(magic, &frame->magic, err);
+	__put_user_error(size, &frame->size, err);
+
+	/*
+	 * Now copy the FP registers. Since the registers are packed,
+	 * we can copy the prefix we want (V0-V15) as it is.
+	 * FIXME: Won't work if big endian.
+	 */
+	err |= __copy_to_user(&frame->ufp.fpregs, fpsimd->vregs,
+			      sizeof(frame->ufp.fpregs));
+
+	/* Create an AArch32 fpscr from the fpsr and the fpcr. */
+	fpscr = (fpsimd->fpsr & VFP_FPSCR_STAT_MASK) |
+		(fpsimd->fpcr & VFP_FPSCR_CTRL_MASK);
+	__put_user_error(fpscr, &frame->ufp.fpscr, err);
+
+	/*
+	 * The exception register aren't available so we fake up a
+	 * basic FPEXC and zero everything else.
+	 */
+	fpexc = (1 << 30);
+	__put_user_error(fpexc, &frame->ufp_exc.fpexc, err);
+	__put_user_error(0, &frame->ufp_exc.fpinst, err);
+	__put_user_error(0, &frame->ufp_exc.fpinst2, err);
+
+	return err ? -EFAULT : 0;
+}
+
+static int compat_restore_vfp_context(struct compat_vfp_sigframe __user *frame)
+{
+	struct fpsimd_state fpsimd;
+	compat_ulong_t magic = VFP_MAGIC;
+	compat_ulong_t size = VFP_STORAGE_SIZE;
+	compat_ulong_t fpscr;
+	int err = 0;
+
+	__get_user_error(magic, &frame->magic, err);
+	__get_user_error(size, &frame->size, err);
+
+	if (err)
+		return -EFAULT;
+	if (magic != VFP_MAGIC || size != VFP_STORAGE_SIZE)
+		return -EINVAL;
+
+	/*
+	 * Copy the FP registers into the start of the fpsimd_state.
+	 * FIXME: Won't work if big endian.
+	 */
+	err |= __copy_from_user(fpsimd.vregs, frame->ufp.fpregs,
+				sizeof(frame->ufp.fpregs));
+
+	/* Extract the fpsr and the fpcr from the fpscr */
+	__get_user_error(fpscr, &frame->ufp.fpscr, err);
+	fpsimd.fpsr = fpscr & VFP_FPSCR_STAT_MASK;
+	fpsimd.fpcr = fpscr & VFP_FPSCR_CTRL_MASK;
+
+	/*
+	 * We don't need to touch the exception register, so
+	 * reload the hardware state.
+	 */
+	if (!err) {
+		preempt_disable();
+		fpsimd_load_state(&fpsimd);
+		preempt_enable();
+	}
+
+	return err ? -EFAULT : 0;
+}
+
+/*
+ * atomically swap in the new signal mask, and wait for a signal.
+ */
+asmlinkage int compat_sys_sigsuspend(int restart, compat_ulong_t oldmask,
+				     compat_old_sigset_t mask)
+{
+	sigset_t blocked;
+
+	siginitset(&current->blocked, mask);
+	return sigsuspend(&blocked);
+}
+
+asmlinkage int compat_sys_sigaction(int sig,
+				    const struct compat_old_sigaction __user *act,
+				    struct compat_old_sigaction __user *oact)
+{
+	struct k_sigaction new_ka, old_ka;
+	int ret;
+	compat_old_sigset_t mask;
+	compat_uptr_t handler, restorer;
+
+	if (act) {
+		if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
+		    __get_user(handler, &act->sa_handler) ||
+		    __get_user(restorer, &act->sa_restorer) ||
+		    __get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
+		    __get_user(mask, &act->sa_mask))
+			return -EFAULT;
+
+		new_ka.sa.sa_handler = compat_ptr(handler);
+		new_ka.sa.sa_restorer = compat_ptr(restorer);
+		siginitset(&new_ka.sa.sa_mask, mask);
+	}
+
+	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
+
+	if (!ret && oact) {
+		if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
+		    __put_user(ptr_to_compat(old_ka.sa.sa_handler),
+			       &oact->sa_handler) ||
+		    __put_user(ptr_to_compat(old_ka.sa.sa_restorer),
+			       &oact->sa_restorer) ||
+		    __put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
+		    __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask))
+			return -EFAULT;
+	}
+
+	return ret;
+}
+
+asmlinkage int compat_sys_rt_sigaction(int sig,
+				       const struct compat_sigaction __user *act,
+				       struct compat_sigaction __user *oact,
+				       compat_size_t sigsetsize)
+{
+	struct k_sigaction new_ka, old_ka;
+	int ret;
+
+	/* XXX: Don't preclude handling different sized sigset_t's.  */
+	if (sigsetsize != sizeof(compat_sigset_t))
+		return -EINVAL;
+
+	if (act) {
+		compat_uptr_t handler, restorer;
+
+		ret = get_user(handler, &act->sa_handler);
+		new_ka.sa.sa_handler = compat_ptr(handler);
+		ret |= get_user(restorer, &act->sa_restorer);
+		new_ka.sa.sa_restorer = compat_ptr(restorer);
+		ret |= get_sigset_t(&new_ka.sa.sa_mask, &act->sa_mask);
+		ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
+		if (ret)
+			return -EFAULT;
+	}
+
+	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
+	if (!ret && oact) {
+		ret = put_user(ptr_to_compat(old_ka.sa.sa_handler), &oact->sa_handler);
+		ret |= put_sigset_t(&oact->sa_mask, &old_ka.sa.sa_mask);
+		ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
+	}
+	return ret;
+}
+
+int compat_do_sigaltstack(compat_uptr_t compat_uss, compat_uptr_t compat_uoss,
+			  compat_ulong_t sp)
+{
+	compat_stack_t __user *newstack = compat_ptr(compat_uss);
+	compat_stack_t __user *oldstack = compat_ptr(compat_uoss);
+	compat_uptr_t ss_sp;
+	int ret;
+	mm_segment_t old_fs;
+	stack_t uss, uoss;
+
+	/* Marshall the compat new stack into a stack_t */
+	if (newstack) {
+		if (get_user(ss_sp, &newstack->ss_sp) ||
+		    __get_user(uss.ss_flags, &newstack->ss_flags) ||
+		    __get_user(uss.ss_size, &newstack->ss_size))
+			return -EFAULT;
+		uss.ss_sp = compat_ptr(ss_sp);
+	}
+
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+	/* The __user pointer casts are valid because of the set_fs() */
+	ret = do_sigaltstack(
+		newstack ? (stack_t __user *) &uss : NULL,
+		oldstack ? (stack_t __user *) &uoss : NULL,
+		(unsigned long)sp);
+	set_fs(old_fs);
+
+	/* Convert the old stack_t into a compat stack. */
+	if (!ret && oldstack &&
+		(put_user(ptr_to_compat(uoss.ss_sp), &oldstack->ss_sp) ||
+		 __put_user(uoss.ss_flags, &oldstack->ss_flags) ||
+		 __put_user(uoss.ss_size, &oldstack->ss_size)))
+		return -EFAULT;
+	return ret;
+}
+
+static int compat_restore_sigframe(struct pt_regs *regs,
+				   struct compat_sigframe __user *sf)
+{
+	int err;
+	sigset_t set;
+	struct compat_aux_sigframe __user *aux;
+
+	err = get_sigset_t(&set, &sf->uc.uc_sigmask);
+	if (err == 0) {
+		sigdelsetmask(&set, ~_BLOCKABLE);
+		set_current_blocked(&set);
+	}
+
+	__get_user_error(regs->regs[0], &sf->uc.uc_mcontext.arm_r0, err);
+	__get_user_error(regs->regs[1], &sf->uc.uc_mcontext.arm_r1, err);
+	__get_user_error(regs->regs[2], &sf->uc.uc_mcontext.arm_r2, err);
+	__get_user_error(regs->regs[3], &sf->uc.uc_mcontext.arm_r3, err);
+	__get_user_error(regs->regs[4], &sf->uc.uc_mcontext.arm_r4, err);
+	__get_user_error(regs->regs[5], &sf->uc.uc_mcontext.arm_r5, err);
+	__get_user_error(regs->regs[6], &sf->uc.uc_mcontext.arm_r6, err);
+	__get_user_error(regs->regs[7], &sf->uc.uc_mcontext.arm_r7, err);
+	__get_user_error(regs->regs[8], &sf->uc.uc_mcontext.arm_r8, err);
+	__get_user_error(regs->regs[9], &sf->uc.uc_mcontext.arm_r9, err);
+	__get_user_error(regs->regs[10], &sf->uc.uc_mcontext.arm_r10, err);
+	__get_user_error(regs->regs[11], &sf->uc.uc_mcontext.arm_fp, err);
+	__get_user_error(regs->regs[12], &sf->uc.uc_mcontext.arm_ip, err);
+	__get_user_error(regs->compat_sp, &sf->uc.uc_mcontext.arm_sp, err);
+	__get_user_error(regs->compat_lr, &sf->uc.uc_mcontext.arm_lr, err);
+	__get_user_error(regs->pc, &sf->uc.uc_mcontext.arm_pc, err);
+	__get_user_error(regs->pstate, &sf->uc.uc_mcontext.arm_cpsr, err);
+
+	/*
+	 * Avoid compat_sys_sigreturn() restarting.
+	 */
+	regs->syscallno = ~0UL;
+
+	err |= !valid_user_regs(&regs->user_regs);
+
+	aux = (struct compat_aux_sigframe __user *) sf->uc.uc_regspace;
+	if (err == 0)
+		err |= compat_restore_vfp_context(&aux->vfp);
+
+	return err;
+}
+
+asmlinkage int compat_sys_sigreturn(struct pt_regs *regs)
+{
+	struct compat_sigframe __user *frame;
+
+	/* Always make any pending restarted system calls return -EINTR */
+	current_thread_info()->restart_block.fn = do_no_restart_syscall;
+
+	/*
+	 * Since we stacked the signal on a 64-bit boundary,
+	 * then 'sp' should be word aligned here.  If it's
+	 * not, then the user is trying to mess with us.
+	 */
+	if (regs->compat_sp & 7)
+		goto badframe;
+
+	frame = (struct compat_sigframe __user *)regs->compat_sp;
+
+	if (!access_ok(VERIFY_READ, frame, sizeof (*frame)))
+		goto badframe;
+
+	if (compat_restore_sigframe(regs, frame))
+		goto badframe;
+
+	return regs->regs[0];
+
+badframe:
+	if (show_unhandled_signals)
+		pr_info_ratelimited("%s[%d]: bad frame in %s: pc=%08llx sp=%08llx\n",
+				    current->comm, task_pid_nr(current), __func__,
+				    regs->pc, regs->sp);
+	force_sig(SIGSEGV, current);
+	return 0;
+}
+
+asmlinkage int compat_sys_rt_sigreturn(struct pt_regs *regs)
+{
+	struct compat_rt_sigframe __user *frame;
+
+	/* Always make any pending restarted system calls return -EINTR */
+	current_thread_info()->restart_block.fn = do_no_restart_syscall;
+
+	/*
+	 * Since we stacked the signal on a 64-bit boundary,
+	 * then 'sp' should be word aligned here.  If it's
+	 * not, then the user is trying to mess with us.
+	 */
+	if (regs->compat_sp & 7)
+		goto badframe;
+
+	frame = (struct compat_rt_sigframe __user *)regs->compat_sp;
+
+	if (!access_ok(VERIFY_READ, frame, sizeof (*frame)))
+		goto badframe;
+
+	if (compat_restore_sigframe(regs, &frame->sig))
+		goto badframe;
+
+	if (compat_do_sigaltstack(ptr_to_compat(&frame->sig.uc.uc_stack),
+				 ptr_to_compat((void __user *)NULL),
+				 regs->compat_sp) == -EFAULT)
+		goto badframe;
+
+	return regs->regs[0];
+
+badframe:
+	if (show_unhandled_signals)
+		pr_info_ratelimited("%s[%d]: bad frame in %s: pc=%08llx sp=%08llx\n",
+				    current->comm, task_pid_nr(current), __func__,
+				    regs->pc, regs->sp);
+	force_sig(SIGSEGV, current);
+	return 0;
+}
+
+static inline void __user *compat_get_sigframe(struct k_sigaction *ka,
+					       struct pt_regs *regs,
+					       int framesize)
+{
+	compat_ulong_t sp = regs->compat_sp;
+	void __user *frame;
+
+	/*
+	 * This is the X/Open sanctioned signal stack switching.
+	 */
+	if ((ka->sa.sa_flags & SA_ONSTACK) && !sas_ss_flags(sp))
+		sp = current->sas_ss_sp + current->sas_ss_size;
+
+	/*
+	 * ATPCS B01 mandates 8-byte alignment
+	 */
+	frame = compat_ptr((compat_uptr_t)((sp - framesize) & ~7));
+
+	/*
+	 * Check that we can actually write to the signal frame.
+	 */
+	if (!access_ok(VERIFY_WRITE, frame, framesize))
+		frame = NULL;
+
+	return frame;
+}
+
+static int compat_setup_return(struct pt_regs *regs, struct k_sigaction *ka,
+			       compat_ulong_t __user *rc, void __user *frame,
+			       int usig)
+{
+	compat_ulong_t handler = ptr_to_compat(ka->sa.sa_handler);
+	compat_ulong_t retcode;
+	compat_ulong_t spsr = regs->pstate & ~PSR_f;
+	int thumb;
+
+	/* Check if the handler is written for ARM or Thumb */
+	thumb = handler & 1;
+
+	if (thumb) {
+		spsr |= COMPAT_PSR_T_BIT;
+		spsr &= ~COMPAT_PSR_IT_MASK;
+	} else {
+		spsr &= ~COMPAT_PSR_T_BIT;
+	}
+
+	if (ka->sa.sa_flags & SA_RESTORER) {
+		retcode = ptr_to_compat(ka->sa.sa_restorer);
+	} else {
+		/* Set up sigreturn pointer */
+		unsigned int idx = thumb << 1;
+
+		if (ka->sa.sa_flags & SA_SIGINFO)
+			idx += 3;
+
+		retcode = AARCH32_VECTORS_BASE +
+			  AARCH32_KERN_SIGRET_CODE_OFFSET +
+			  (idx << 2) + thumb;
+	}
+
+	regs->regs[0]	= usig;
+	regs->compat_sp	= ptr_to_compat(frame);
+	regs->compat_lr	= retcode;
+	regs->pc	= handler;
+	regs->pstate	= spsr;
+
+	return 0;
+}
+
+static int compat_setup_sigframe(struct compat_sigframe __user *sf,
+				 struct pt_regs *regs, sigset_t *set)
+{
+	struct compat_aux_sigframe __user *aux;
+	int err = 0;
+
+	__put_user_error(regs->regs[0], &sf->uc.uc_mcontext.arm_r0, err);
+	__put_user_error(regs->regs[1], &sf->uc.uc_mcontext.arm_r1, err);
+	__put_user_error(regs->regs[2], &sf->uc.uc_mcontext.arm_r2, err);
+	__put_user_error(regs->regs[3], &sf->uc.uc_mcontext.arm_r3, err);
+	__put_user_error(regs->regs[4], &sf->uc.uc_mcontext.arm_r4, err);
+	__put_user_error(regs->regs[5], &sf->uc.uc_mcontext.arm_r5, err);
+	__put_user_error(regs->regs[6], &sf->uc.uc_mcontext.arm_r6, err);
+	__put_user_error(regs->regs[7], &sf->uc.uc_mcontext.arm_r7, err);
+	__put_user_error(regs->regs[8], &sf->uc.uc_mcontext.arm_r8, err);
+	__put_user_error(regs->regs[9], &sf->uc.uc_mcontext.arm_r9, err);
+	__put_user_error(regs->regs[10], &sf->uc.uc_mcontext.arm_r10, err);
+	__put_user_error(regs->regs[11], &sf->uc.uc_mcontext.arm_fp, err);
+	__put_user_error(regs->regs[12], &sf->uc.uc_mcontext.arm_ip, err);
+	__put_user_error(regs->compat_sp, &sf->uc.uc_mcontext.arm_sp, err);
+	__put_user_error(regs->compat_lr, &sf->uc.uc_mcontext.arm_lr, err);
+	__put_user_error(regs->pc, &sf->uc.uc_mcontext.arm_pc, err);
+	__put_user_error(regs->pstate, &sf->uc.uc_mcontext.arm_cpsr, err);
+
+	__put_user_error((compat_ulong_t)0, &sf->uc.uc_mcontext.trap_no, err);
+	__put_user_error((compat_ulong_t)0, &sf->uc.uc_mcontext.error_code, err);
+	__put_user_error(current->thread.fault_address, &sf->uc.uc_mcontext.fault_address, err);
+	__put_user_error(set->sig[0], &sf->uc.uc_mcontext.oldmask, err);
+
+	err |= put_sigset_t(&sf->uc.uc_sigmask, set);
+
+	aux = (struct compat_aux_sigframe __user *) sf->uc.uc_regspace;
+
+	if (err == 0)
+		err |= compat_preserve_vfp_context(&aux->vfp);
+	__put_user_error(0, &aux->end_magic, err);
+
+	return err;
+}
+
+/*
+ * 32-bit signal handling routines called from signal.c
+ */
+int compat_setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
+			  sigset_t *set, struct pt_regs *regs)
+{
+	struct compat_rt_sigframe __user *frame;
+	compat_stack_t stack;
+	int err = 0;
+
+	frame = compat_get_sigframe(ka, regs, sizeof(*frame));
+
+	if (!frame)
+		return 1;
+
+	err |= copy_siginfo_to_user32(&frame->info, info);
+
+	__put_user_error(0, &frame->sig.uc.uc_flags, err);
+	__put_user_error(NULL, &frame->sig.uc.uc_link, err);
+
+	memset(&stack, 0, sizeof(stack));
+	stack.ss_sp = (compat_uptr_t)current->sas_ss_sp;
+	stack.ss_flags = sas_ss_flags(regs->compat_sp);
+	stack.ss_size = current->sas_ss_size;
+	err |= __copy_to_user(&frame->sig.uc.uc_stack, &stack, sizeof(stack));
+
+	err |= compat_setup_sigframe(&frame->sig, regs, set);
+	if (err == 0)
+		err = compat_setup_return(regs, ka, frame->sig.retcode, frame,
+					  usig);
+
+	if (err == 0) {
+		regs->regs[1] = (compat_ulong_t)(unsigned long)&frame->info;
+		regs->regs[2] = (compat_ulong_t)(unsigned long)&frame->sig.uc;
+	}
+
+	return err;
+}
+
+int compat_setup_frame(int usig, struct k_sigaction *ka, sigset_t *set,
+		       struct pt_regs *regs)
+{
+	struct compat_sigframe __user *frame;
+	int err = 0;
+
+	frame = compat_get_sigframe(ka, regs, sizeof(*frame));
+
+	if (!frame)
+		return 1;
+
+	__put_user_error(0x5ac3c35a, &frame->uc.uc_flags, err);
+
+	err |= compat_setup_sigframe(frame, regs, set);
+	if (err == 0)
+		err = compat_setup_return(regs, ka, frame->retcode, frame, usig);
+
+	return err;
+}
+
+/*
+ * RT signals don't have generic compat wrappers.
+ * See arch/powerpc/kernel/signal_32.c
+ */
+asmlinkage int compat_sys_rt_sigprocmask(int how, compat_sigset_t __user *set,
+					 compat_sigset_t __user *oset,
+					 compat_size_t sigsetsize)
+{
+	sigset_t s;
+	sigset_t __user *up;
+	int ret;
+	mm_segment_t old_fs = get_fs();
+
+	if (set) {
+		if (get_sigset_t(&s, set))
+			return -EFAULT;
+	}
+
+	set_fs(KERNEL_DS);
+	/* This is valid because of the set_fs() */
+	up = (sigset_t __user *) &s;
+	ret = sys_rt_sigprocmask(how, set ? up : NULL, oset ? up : NULL,
+				 sigsetsize);
+	set_fs(old_fs);
+	if (ret)
+		return ret;
+	if (oset) {
+		if (put_sigset_t(oset, &s))
+			return -EFAULT;
+	}
+	return 0;
+}
+
+asmlinkage int compat_sys_rt_sigpending(compat_sigset_t __user *set,
+					compat_size_t sigsetsize)
+{
+	sigset_t s;
+	int ret;
+	mm_segment_t old_fs = get_fs();
+
+	set_fs(KERNEL_DS);
+	/* The __user pointer cast is valid because of the set_fs() */
+	ret = sys_rt_sigpending((sigset_t __user *) &s, sigsetsize);
+	set_fs(old_fs);
+	if (!ret) {
+		if (put_sigset_t(set, &s))
+			return -EFAULT;
+	}
+	return ret;
+}
+
+asmlinkage int compat_sys_rt_sigqueueinfo(int pid, int sig,
+					  compat_siginfo_t __user *uinfo)
+{
+	siginfo_t info;
+	int ret;
+	mm_segment_t old_fs = get_fs();
+
+	ret = copy_siginfo_from_user32(&info, uinfo);
+	if (unlikely(ret))
+		return ret;
+
+	set_fs (KERNEL_DS);
+	/* The __user pointer cast is valid because of the set_fs() */
+	ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __user *) &info);
+	set_fs (old_fs);
+	return ret;
+}
+
+void compat_setup_restart_syscall(struct pt_regs *regs)
+{
+       regs->regs[7] = __NR_restart_syscall;
+}
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
new file mode 100644
index 0000000..b711525
--- /dev/null
+++ b/arch/arm64/kernel/smp.c
@@ -0,0 +1,469 @@
+/*
+ * SMP initialisation and IPI support
+ * Based on arch/arm/kernel/smp.c
+ *
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/cache.h>
+#include <linux/profile.h>
+#include <linux/errno.h>
+#include <linux/mm.h>
+#include <linux/err.h>
+#include <linux/cpu.h>
+#include <linux/smp.h>
+#include <linux/seq_file.h>
+#include <linux/irq.h>
+#include <linux/percpu.h>
+#include <linux/clockchips.h>
+#include <linux/completion.h>
+#include <linux/of.h>
+
+#include <asm/atomic.h>
+#include <asm/cacheflush.h>
+#include <asm/cputype.h>
+#include <asm/mmu_context.h>
+#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
+#include <asm/processor.h>
+#include <asm/sections.h>
+#include <asm/tlbflush.h>
+#include <asm/ptrace.h>
+#include <asm/mmu_context.h>
+
+/*
+ * as from 2.5, kernels no longer have an init_tasks structure
+ * so we need some other way of telling a new secondary core
+ * where to place its SVC stack
+ */
+struct secondary_data secondary_data;
+volatile unsigned long secondary_holding_pen_release = -1;
+
+enum ipi_msg_type {
+	IPI_RESCHEDULE,
+	IPI_CALL_FUNC,
+	IPI_CALL_FUNC_SINGLE,
+	IPI_CPU_STOP,
+};
+
+static DEFINE_RAW_SPINLOCK(boot_lock);
+
+/*
+ * Write secondary_holding_pen_release in a way that is guaranteed to be
+ * visible to all observers, irrespective of whether they're taking part
+ * in coherency or not.  This is necessary for the hotplug code to work
+ * reliably.
+ */
+static void __cpuinit write_pen_release(int val)
+{
+	void *start = (void *)&secondary_holding_pen_release;
+	unsigned long size = sizeof(secondary_holding_pen_release);
+
+	secondary_holding_pen_release = val;
+	__flush_dcache_area(start, size);
+}
+
+/*
+ * Boot a secondary CPU, and assign it the specified idle task.
+ * This also gives us the initial stack to use for this CPU.
+ */
+static int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+	unsigned long timeout;
+
+	/*
+	 * Set synchronisation state between this boot processor
+	 * and the secondary one
+	 */
+	raw_spin_lock(&boot_lock);
+
+	/*
+	 * Update the pen release flag.
+	 */
+	write_pen_release(cpu);
+
+	/*
+	 * Send an event, causing the secondaries to read pen_release.
+	 */
+	sev();
+
+	timeout = jiffies + (1 * HZ);
+	while (time_before(jiffies, timeout)) {
+		if (secondary_holding_pen_release == -1UL)
+			break;
+		udelay(10);
+	}
+
+	/*
+	 * Now the secondary core is starting up let it run its
+	 * calibrations, then wait for it to finish
+	 */
+	raw_spin_unlock(&boot_lock);
+
+	return secondary_holding_pen_release != -1 ? -ENOSYS : 0;
+}
+
+static DECLARE_COMPLETION(cpu_running);
+
+int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *idle)
+{
+	int ret;
+
+	/*
+	 * We need to tell the secondary core where to find its stack and the
+	 * page tables.
+	 */
+	secondary_data.stack = task_stack_page(idle) + THREAD_START_SP;
+	__flush_dcache_area(&secondary_data, sizeof(secondary_data));
+
+	/*
+	 * Now bring the CPU into our world.
+	 */
+	ret = boot_secondary(cpu, idle);
+	if (ret == 0) {
+		/*
+		 * CPU was successfully started, wait for it to come online or
+		 * time out.
+		 */
+		wait_for_completion_timeout(&cpu_running,
+					    msecs_to_jiffies(1000));
+
+		if (!cpu_online(cpu)) {
+			pr_crit("CPU%u: failed to come online\n", cpu);
+			ret = -EIO;
+		}
+	} else {
+		pr_err("CPU%u: failed to boot: %d\n", cpu, ret);
+	}
+
+	secondary_data.stack = NULL;
+
+	return ret;
+}
+
+/*
+ * This is the secondary CPU boot entry.  We're using this CPUs
+ * idle thread stack, but a set of temporary page tables.
+ */
+asmlinkage void __cpuinit secondary_start_kernel(void)
+{
+	struct mm_struct *mm = &init_mm;
+	unsigned int cpu = smp_processor_id();
+
+	printk("CPU%u: Booted secondary processor\n", cpu);
+
+	/*
+	 * All kernel threads share the same mm context; grab a
+	 * reference and switch to it.
+	 */
+	atomic_inc(&mm->mm_count);
+	current->active_mm = mm;
+	cpumask_set_cpu(cpu, mm_cpumask(mm));
+
+	/*
+	 * TTBR0 is only used for the identity mapping at this stage. Make it
+	 * point to zero page to avoid speculatively fetching new entries.
+	 */
+	cpu_set_reserved_ttbr0();
+	flush_tlb_all();
+
+	preempt_disable();
+	trace_hardirqs_off();
+
+	/*
+	 * Let the primary processor know we're out of the
+	 * pen, then head off into the C entry point
+	 */
+	write_pen_release(-1);
+
+	/*
+	 * Synchronise with the boot thread.
+	 */
+	raw_spin_lock(&boot_lock);
+	raw_spin_unlock(&boot_lock);
+
+	/*
+	 * Enable local interrupts.
+	 */
+	notify_cpu_starting(cpu);
+	local_irq_enable();
+	local_fiq_enable();
+
+	/*
+	 * OK, now it's safe to let the boot CPU continue.  Wait for
+	 * the CPU migration code to notice that the CPU is online
+	 * before we continue.
+	 */
+	set_cpu_online(cpu, true);
+	while (!cpu_active(cpu))
+		cpu_relax();
+
+	/*
+	 * OK, it's off to the idle thread for us
+	 */
+	cpu_idle();
+}
+
+void __init smp_cpus_done(unsigned int max_cpus)
+{
+	unsigned long bogosum = loops_per_jiffy * num_online_cpus();
+
+	pr_info("SMP: Total of %d processors activated (%lu.%02lu BogoMIPS).\n",
+		num_online_cpus(), bogosum / (500000/HZ),
+		(bogosum / (5000/HZ)) % 100);
+}
+
+void __init smp_prepare_boot_cpu(void)
+{
+}
+
+static void (*smp_cross_call)(const struct cpumask *, unsigned int);
+static phys_addr_t cpu_release_addr[NR_CPUS];
+
+/*
+ * Enumerate the possible CPU set from the device tree.
+ */
+void __init smp_init_cpus(void)
+{
+	const char *enable_method;
+	struct device_node *dn = NULL;
+	int cpu = 0;
+
+	while ((dn = of_find_node_by_type(dn, "cpu"))) {
+		if (cpu >= NR_CPUS)
+			goto next;
+
+		/*
+		 * We currently support only the "spin-table" enable-method.
+		 */
+		enable_method = of_get_property(dn, "enable-method", NULL);
+		if (!enable_method || strcmp(enable_method, "spin-table")) {
+			pr_err("CPU %d: missing or invalid enable-method property: %s\n",
+			       cpu, enable_method);
+			goto next;
+		}
+
+		/*
+		 * Determine the address from which the CPU is polling.
+		 */
+		if (of_property_read_u64(dn, "cpu-release-addr",
+					 &cpu_release_addr[cpu])) {
+			pr_err("CPU %d: missing or invalid cpu-release-addr property\n",
+			       cpu);
+			goto next;
+		}
+
+		set_cpu_possible(cpu, true);
+next:
+		cpu++;
+	}
+
+	/* sanity check */
+	if (cpu > NR_CPUS)
+		pr_warning("no. of cores (%d) greater than configured maximum of %d - clipping\n",
+			   cpu, NR_CPUS);
+}
+
+void __init smp_prepare_cpus(unsigned int max_cpus)
+{
+	int cpu;
+	void **release_addr;
+	unsigned int ncores = num_possible_cpus();
+
+	/*
+	 * are we trying to boot more cores than exist?
+	 */
+	if (max_cpus > ncores)
+		max_cpus = ncores;
+
+	/*
+	 * Initialise the present map (which describes the set of CPUs
+	 * actually populated at the present time) and release the
+	 * secondaries from the bootloader.
+	 */
+	for_each_possible_cpu(cpu) {
+		if (max_cpus == 0)
+			break;
+
+		if (!cpu_release_addr[cpu])
+			continue;
+
+		release_addr = __va(cpu_release_addr[cpu]);
+		release_addr[0] = (void *)__pa(secondary_holding_pen);
+		__flush_dcache_area(release_addr, sizeof(release_addr[0]));
+
+		set_cpu_present(cpu, true);
+		max_cpus--;
+	}
+
+	/*
+	 * Send an event to wake up the secondaries.
+	 */
+	sev();
+}
+
+
+void __init set_smp_cross_call(void (*fn)(const struct cpumask *, unsigned int))
+{
+	smp_cross_call = fn;
+}
+
+void arch_send_call_function_ipi_mask(const struct cpumask *mask)
+{
+	smp_cross_call(mask, IPI_CALL_FUNC);
+}
+
+void arch_send_call_function_single_ipi(int cpu)
+{
+	smp_cross_call(cpumask_of(cpu), IPI_CALL_FUNC_SINGLE);
+}
+
+static const char *ipi_types[NR_IPI] = {
+#define S(x,s)	[x - IPI_RESCHEDULE] = s
+	S(IPI_RESCHEDULE, "Rescheduling interrupts"),
+	S(IPI_CALL_FUNC, "Function call interrupts"),
+	S(IPI_CALL_FUNC_SINGLE, "Single function call interrupts"),
+	S(IPI_CPU_STOP, "CPU stop interrupts"),
+};
+
+void show_ipi_list(struct seq_file *p, int prec)
+{
+	unsigned int cpu, i;
+
+	for (i = 0; i < NR_IPI; i++) {
+		seq_printf(p, "%*s%u:%s", prec - 1, "IPI", i + IPI_RESCHEDULE,
+			   prec >= 4 ? " " : "");
+		for_each_present_cpu(cpu)
+			seq_printf(p, "%10u ",
+				   __get_irq_stat(cpu, ipi_irqs[i]));
+		seq_printf(p, "      %s\n", ipi_types[i]);
+	}
+}
+
+u64 smp_irq_stat_cpu(unsigned int cpu)
+{
+	u64 sum = 0;
+	int i;
+
+	for (i = 0; i < NR_IPI; i++)
+		sum += __get_irq_stat(cpu, ipi_irqs[i]);
+
+	return sum;
+}
+
+static DEFINE_RAW_SPINLOCK(stop_lock);
+
+/*
+ * ipi_cpu_stop - handle IPI from smp_send_stop()
+ */
+static void ipi_cpu_stop(unsigned int cpu)
+{
+	if (system_state == SYSTEM_BOOTING ||
+	    system_state == SYSTEM_RUNNING) {
+		raw_spin_lock(&stop_lock);
+		pr_crit("CPU%u: stopping\n", cpu);
+		dump_stack();
+		raw_spin_unlock(&stop_lock);
+	}
+
+	set_cpu_online(cpu, false);
+
+	local_fiq_disable();
+	local_irq_disable();
+
+	while (1)
+		cpu_relax();
+}
+
+/*
+ * Main handler for inter-processor interrupts
+ */
+void handle_IPI(int ipinr, struct pt_regs *regs)
+{
+	unsigned int cpu = smp_processor_id();
+	struct pt_regs *old_regs = set_irq_regs(regs);
+
+	if (ipinr >= IPI_RESCHEDULE && ipinr < IPI_RESCHEDULE + NR_IPI)
+		__inc_irq_stat(cpu, ipi_irqs[ipinr - IPI_RESCHEDULE]);
+
+	switch (ipinr) {
+	case IPI_RESCHEDULE:
+		scheduler_ipi();
+		break;
+
+	case IPI_CALL_FUNC:
+		irq_enter();
+		generic_smp_call_function_interrupt();
+		irq_exit();
+		break;
+
+	case IPI_CALL_FUNC_SINGLE:
+		irq_enter();
+		generic_smp_call_function_single_interrupt();
+		irq_exit();
+		break;
+
+	case IPI_CPU_STOP:
+		irq_enter();
+		ipi_cpu_stop(cpu);
+		irq_exit();
+		break;
+
+	default:
+		pr_crit("CPU%u: Unknown IPI message 0x%x\n", cpu, ipinr);
+		break;
+	}
+	set_irq_regs(old_regs);
+}
+
+void smp_send_reschedule(int cpu)
+{
+	smp_cross_call(cpumask_of(cpu), IPI_RESCHEDULE);
+}
+
+void smp_send_stop(void)
+{
+	unsigned long timeout;
+
+	if (num_online_cpus() > 1) {
+		cpumask_t mask;
+
+		cpumask_copy(&mask, cpu_online_mask);
+		cpu_clear(smp_processor_id(), mask);
+
+		smp_cross_call(&mask, IPI_CPU_STOP);
+	}
+
+	/* Wait up to one second for other CPUs to stop */
+	timeout = USEC_PER_SEC;
+	while (num_online_cpus() > 1 && timeout--)
+		udelay(1);
+
+	if (num_online_cpus() > 1)
+		pr_warning("SMP: failed to stop secondary CPUs\n");
+}
+
+/*
+ * not supported here
+ */
+int setup_profiling_timer(unsigned int multiplier)
+{
+	return -EINVAL;
+}
diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
new file mode 100644
index 0000000..d25459f
--- /dev/null
+++ b/arch/arm64/kernel/stacktrace.c
@@ -0,0 +1,127 @@
+/*
+ * Stack tracing support
+ *
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/kernel.h>
+#include <linux/export.h>
+#include <linux/sched.h>
+#include <linux/stacktrace.h>
+
+#include <asm/stacktrace.h>
+
+/*
+ * AArch64 PCS assigns the frame pointer to x29.
+ *
+ * A simple function prologue looks like this:
+ * 	sub	sp, sp, #0x10
+ *   	stp	x29, x30, [sp]
+ *	mov	x29, sp
+ *
+ * A simple function epilogue looks like this:
+ *	mov	sp, x29
+ *	ldp	x29, x30, [sp]
+ *	add	sp, sp, #0x10
+ */
+int unwind_frame(struct stackframe *frame)
+{
+	unsigned long high, low;
+	unsigned long fp = frame->fp;
+
+	low  = frame->sp;
+	high = ALIGN(low, THREAD_SIZE);
+
+	if (fp < low || fp > high || fp & 0xf)
+		return -EINVAL;
+
+	frame->sp = fp + 0x10;
+	frame->fp = *(unsigned long *)(fp);
+	frame->pc = *(unsigned long *)(fp + 8);
+
+	return 0;
+}
+
+void notrace walk_stackframe(struct stackframe *frame,
+		     int (*fn)(struct stackframe *, void *), void *data)
+{
+	while (1) {
+		int ret;
+
+		if (fn(frame, data))
+			break;
+		ret = unwind_frame(frame);
+		if (ret < 0)
+			break;
+	}
+}
+EXPORT_SYMBOL(walk_stackframe);
+
+#ifdef CONFIG_STACKTRACE
+struct stack_trace_data {
+	struct stack_trace *trace;
+	unsigned int no_sched_functions;
+	unsigned int skip;
+};
+
+static int save_trace(struct stackframe *frame, void *d)
+{
+	struct stack_trace_data *data = d;
+	struct stack_trace *trace = data->trace;
+	unsigned long addr = frame->pc;
+
+	if (data->no_sched_functions && in_sched_functions(addr))
+		return 0;
+	if (data->skip) {
+		data->skip--;
+		return 0;
+	}
+
+	trace->entries[trace->nr_entries++] = addr;
+
+	return trace->nr_entries >= trace->max_entries;
+}
+
+void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
+{
+	struct stack_trace_data data;
+	struct stackframe frame;
+
+	data.trace = trace;
+	data.skip = trace->skip;
+
+	if (tsk != current) {
+		data.no_sched_functions = 1;
+		frame.fp = thread_saved_fp(tsk);
+		frame.sp = thread_saved_sp(tsk);
+		frame.pc = thread_saved_pc(tsk);
+	} else {
+		register unsigned long current_sp asm("sp");
+		data.no_sched_functions = 0;
+		frame.fp = (unsigned long)__builtin_frame_address(0);
+		frame.sp = current_sp;
+		frame.pc = (unsigned long)save_stack_trace_tsk;
+	}
+
+	walk_stackframe(&frame, save_trace, &data);
+	if (trace->nr_entries < trace->max_entries)
+		trace->entries[trace->nr_entries++] = ULONG_MAX;
+}
+
+void save_stack_trace(struct stack_trace *trace)
+{
+	save_stack_trace_tsk(current, trace);
+}
+EXPORT_SYMBOL_GPL(save_stack_trace);
+#endif
diff --git a/arch/arm64/kernel/sys.c b/arch/arm64/kernel/sys.c
new file mode 100644
index 0000000..905fcfb
--- /dev/null
+++ b/arch/arm64/kernel/sys.c
@@ -0,0 +1,138 @@
+/*
+ * AArch64-specific system calls implementation
+ *
+ * Copyright (C) 2012 ARM Ltd.
+ * Author: Catalin Marinas <catalin.marinas@arm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/compiler.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/export.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/syscalls.h>
+
+/*
+ * Clone a task - this clones the calling program thread.
+ */
+asmlinkage long sys_clone(unsigned long clone_flags, unsigned long newsp,
+			  int __user *parent_tidptr, unsigned long tls_val,
+			  int __user *child_tidptr, struct pt_regs *regs)
+{
+	if (!newsp)
+		newsp = regs->sp;
+	/* 16-byte aligned stack mandatory on AArch64 */
+	if (newsp & 15)
+		return -EINVAL;
+	return do_fork(clone_flags, newsp, regs, 0, parent_tidptr, child_tidptr);
+}
+
+/*
+ * sys_execve() executes a new program.
+ */
+asmlinkage long sys_execve(const char __user *filenamei,
+			   const char __user *const __user *argv,
+			   const char __user *const __user *envp,
+			   struct pt_regs *regs)
+{
+	long error;
+	char * filename;
+
+	filename = getname(filenamei);
+	error = PTR_ERR(filename);
+	if (IS_ERR(filename))
+		goto out;
+	error = do_execve(filename, argv, envp, regs);
+	putname(filename);
+out:
+	return error;
+}
+
+int kernel_execve(const char *filename,
+		  const char *const argv[],
+		  const char *const envp[])
+{
+	struct pt_regs regs;
+	int ret;
+
+	memset(&regs, 0, sizeof(struct pt_regs));
+	ret = do_execve(filename,
+			(const char __user *const __user *)argv,
+			(const char __user *const __user *)envp, &regs);
+	if (ret < 0)
+		goto out;
+
+	/*
+	 * Save argc to the register structure for userspace.
+	 */
+	regs.regs[0] = ret;
+
+	/*
+	 * We were successful.  We won't be returning to our caller, but
+	 * instead to user space by manipulating the kernel stack.
+	 */
+	asm(	"add	x0, %0, %1\n\t"
+		"mov	x1, %2\n\t"
+		"mov	x2, %3\n\t"
+		"bl	memmove\n\t"	/* copy regs to top of stack */
+		"mov	x27, #0\n\t"	/* not a syscall */
+		"mov	x28, %0\n\t"	/* thread structure */
+		"mov	sp, x0\n\t"	/* reposition stack pointer */
+		"b	ret_to_user"
+		:
+		: "r" (current_thread_info()),
+		  "Ir" (THREAD_START_SP - sizeof(regs)),
+		  "r" (&regs),
+		  "Ir" (sizeof(regs))
+		: "x0", "x1", "x2", "x27", "x28", "x30", "memory");
+
+ out:
+	return ret;
+}
+EXPORT_SYMBOL(kernel_execve);
+
+asmlinkage long sys_mmap(unsigned long addr, unsigned long len,
+			 unsigned long prot, unsigned long flags,
+			 unsigned long fd, off_t off)
+{
+	if (offset_in_page(off) != 0)
+		return -EINVAL;
+
+	return sys_mmap_pgoff(addr, len, prot, flags, fd, off >> PAGE_SHIFT);
+}
+
+/*
+ * Wrappers to pass the pt_regs argument.
+ */
+#define sys_execve		sys_execve_wrapper
+#define sys_clone		sys_clone_wrapper
+#define sys_rt_sigreturn	sys_rt_sigreturn_wrapper
+#define sys_sigaltstack		sys_sigaltstack_wrapper
+
+#include <asm/syscalls.h>
+
+#undef __SYSCALL
+#define __SYSCALL(nr, sym)	[nr] = sym,
+
+/*
+ * The sys_call_table array must be 4K aligned to be accessible from
+ * kernel/entry.S.
+ */
+void *sys_call_table[__NR_syscalls] __aligned(4096) = {
+	[0 ... __NR_syscalls - 1] = sys_ni_syscall,
+#include <asm/unistd.h>
+};
diff --git a/arch/arm64/kernel/sys32.S b/arch/arm64/kernel/sys32.S
new file mode 100644
index 0000000..5e4dc93
--- /dev/null
+++ b/arch/arm64/kernel/sys32.S
@@ -0,0 +1,282 @@
+/*
+ * Compat system call wrappers
+ *
+ * Copyright (C) 2012 ARM Ltd.
+ * Authors: Will Deacon <will.deacon@arm.com>
+ *	    Catalin Marinas <catalin.marinas@arm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/linkage.h>
+
+#include <asm/assembler.h>
+#include <asm/asm-offsets.h>
+
+/*
+ * System call wrappers for the AArch32 compatibility layer.
+ */
+compat_sys_fork_wrapper:
+	mov	x0, sp
+	b	compat_sys_fork
+ENDPROC(compat_sys_fork_wrapper)
+
+compat_sys_vfork_wrapper:
+	mov	x0, sp
+	b	compat_sys_vfork
+ENDPROC(compat_sys_vfork_wrapper)
+
+compat_sys_execve_wrapper:
+	mov	x3, sp
+	b	compat_sys_execve
+ENDPROC(compat_sys_execve_wrapper)
+
+compat_sys_clone_wrapper:
+	mov	x5, sp
+	b	compat_sys_clone
+ENDPROC(compat_sys_clone_wrapper)
+
+compat_sys_sigreturn_wrapper:
+	mov	x0, sp
+	mov	x27, #0		// prevent syscall restart handling (why)
+	b	compat_sys_sigreturn
+ENDPROC(compat_sys_sigreturn_wrapper)
+
+compat_sys_rt_sigreturn_wrapper:
+	mov	x0, sp
+	mov	x27, #0		// prevent syscall restart handling (why)
+	b	compat_sys_rt_sigreturn
+ENDPROC(compat_sys_rt_sigreturn_wrapper)
+
+compat_sys_sigaltstack_wrapper:
+	ldr	x2, [sp, #S_COMPAT_SP]
+	b	compat_do_sigaltstack
+ENDPROC(compat_sys_sigaltstack_wrapper)
+
+compat_sys_statfs64_wrapper:
+	mov	w3, #84
+	cmp	w1, #88
+	csel	w1, w3, w1, eq
+	b	compat_sys_statfs64
+ENDPROC(compat_sys_statfs64_wrapper)
+
+compat_sys_fstatfs64_wrapper:
+	mov	w3, #84
+	cmp	w1, #88
+	csel	w1, w3, w1, eq
+	b	compat_sys_fstatfs64
+ENDPROC(compat_sys_fstatfs64_wrapper)
+
+/*
+ * Wrappers for AArch32 syscalls that either take 64-bit parameters
+ * in registers or that take 32-bit parameters which require sign
+ * extension.
+ */
+compat_sys_lseek_wrapper:
+	sxtw	x1, w1
+	b	sys_lseek
+ENDPROC(compat_sys_lseek_wrapper)
+
+compat_sys_pread64_wrapper:
+	orr	x3, x4, x5, lsl #32
+	b	sys_pread64
+ENDPROC(compat_sys_pread64_wrapper)
+
+compat_sys_pwrite64_wrapper:
+	orr	x3, x4, x5, lsl #32
+	b	sys_pwrite64
+ENDPROC(compat_sys_pwrite64_wrapper)
+
+compat_sys_truncate64_wrapper:
+	orr	x1, x2, x3, lsl #32
+	b	sys_truncate
+ENDPROC(compat_sys_truncate64_wrapper)
+
+compat_sys_ftruncate64_wrapper:
+	orr	x1, x2, x3, lsl #32
+	b	sys_ftruncate
+ENDPROC(compat_sys_ftruncate64_wrapper)
+
+compat_sys_readahead_wrapper:
+	orr	x1, x2, x3, lsl #32
+	mov	w2, w4
+	b	sys_readahead
+ENDPROC(compat_sys_readahead_wrapper)
+
+compat_sys_lookup_dcookie:
+	orr	x0, x0, x1, lsl #32
+	mov	w1, w2
+	mov	w2, w3
+	b	sys_lookup_dcookie
+ENDPROC(compat_sys_lookup_dcookie)
+
+compat_sys_fadvise64_64_wrapper:
+	mov	w6, w1
+	orr	x1, x2, x3, lsl #32
+	orr	x2, x4, x5, lsl #32
+	mov	w3, w6
+	b	sys_fadvise64_64
+ENDPROC(compat_sys_fadvise64_64_wrapper)
+
+compat_sys_sync_file_range2_wrapper:
+	orr	x2, x2, x3, lsl #32
+	orr	x3, x4, x5, lsl #32
+	b	sys_sync_file_range2
+ENDPROC(compat_sys_sync_file_range2_wrapper)
+
+compat_sys_fallocate_wrapper:
+	orr	x2, x2, x3, lsl #32
+	orr	x3, x4, x5, lsl #32
+	b	sys_fallocate
+ENDPROC(compat_sys_fallocate_wrapper)
+
+compat_sys_fanotify_mark_wrapper:
+	orr	x2, x2, x3, lsl #32
+	mov	w3, w4
+	mov	w4, w5
+	b	sys_fanotify_mark
+ENDPROC(compat_sys_fanotify_mark_wrapper)
+
+/*
+ * Use the compat system call wrappers.
+ */
+#define sys_fork		compat_sys_fork_wrapper
+#define sys_open		compat_sys_open
+#define sys_execve		compat_sys_execve_wrapper
+#define sys_lseek		compat_sys_lseek_wrapper
+#define sys_mount		compat_sys_mount
+#define sys_ptrace		compat_sys_ptrace
+#define sys_times		compat_sys_times
+#define sys_ioctl		compat_sys_ioctl
+#define sys_fcntl		compat_sys_fcntl
+#define sys_ustat		compat_sys_ustat
+#define sys_sigaction		compat_sys_sigaction
+#define sys_sigsuspend		compat_sys_sigsuspend
+#define sys_sigpending		compat_sys_sigpending
+#define sys_setrlimit		compat_sys_setrlimit
+#define sys_getrusage		compat_sys_getrusage
+#define sys_gettimeofday	compat_sys_gettimeofday
+#define sys_settimeofday	compat_sys_settimeofday
+#define sys_statfs		compat_sys_statfs
+#define sys_fstatfs		compat_sys_fstatfs
+#define sys_setitimer		compat_sys_setitimer
+#define sys_getitimer		compat_sys_getitimer
+#define sys_newstat		compat_sys_newstat
+#define sys_newlstat		compat_sys_newlstat
+#define sys_newfstat		compat_sys_newfstat
+#define sys_wait4		compat_sys_wait4
+#define sys_sysinfo		compat_sys_sysinfo
+#define sys_sigreturn		compat_sys_sigreturn_wrapper
+#define sys_clone		compat_sys_clone_wrapper
+#define sys_adjtimex		compat_sys_adjtimex
+#define sys_sigprocmask		compat_sys_sigprocmask
+#define sys_getdents		compat_sys_getdents
+#define sys_select		compat_sys_select
+#define sys_readv		compat_sys_readv
+#define sys_writev		compat_sys_writev
+#define sys_sysctl		compat_sys_sysctl
+#define sys_sched_rr_get_interval compat_sys_sched_rr_get_interval
+#define sys_nanosleep		compat_sys_nanosleep
+#define sys_rt_sigreturn	compat_sys_rt_sigreturn_wrapper
+#define sys_rt_sigaction	compat_sys_rt_sigaction
+#define sys_rt_sigprocmask	compat_sys_rt_sigprocmask
+#define sys_rt_sigpending	compat_sys_rt_sigpending
+#define sys_rt_sigtimedwait	compat_sys_rt_sigtimedwait
+#define sys_rt_sigqueueinfo	compat_sys_rt_sigqueueinfo
+#define sys_rt_sigsuspend	compat_sys_rt_sigsuspend
+#define sys_pread64		compat_sys_pread64_wrapper
+#define sys_pwrite64		compat_sys_pwrite64_wrapper
+#define sys_sigaltstack		compat_sys_sigaltstack_wrapper
+#define sys_sendfile		compat_sys_sendfile
+#define sys_vfork		compat_sys_vfork_wrapper
+#define sys_getrlimit		compat_sys_getrlimit
+#define sys_mmap2		sys_mmap_pgoff
+#define sys_truncate64		compat_sys_truncate64_wrapper
+#define sys_ftruncate64		compat_sys_ftruncate64_wrapper
+#define sys_getdents64		compat_sys_getdents64
+#define sys_fcntl64		compat_sys_fcntl64
+#define sys_readahead		compat_sys_readahead_wrapper
+#define sys_futex		compat_sys_futex
+#define sys_sched_setaffinity	compat_sys_sched_setaffinity
+#define sys_sched_getaffinity	compat_sys_sched_getaffinity
+#define sys_io_setup		compat_sys_io_setup
+#define sys_io_getevents	compat_sys_io_getevents
+#define sys_io_submit		compat_sys_io_submit
+#define sys_lookup_dcookie	compat_sys_lookup_dcookie
+#define sys_timer_create	compat_sys_timer_create
+#define sys_timer_settime	compat_sys_timer_settime
+#define sys_timer_gettime	compat_sys_timer_gettime
+#define sys_clock_settime	compat_sys_clock_settime
+#define sys_clock_gettime	compat_sys_clock_gettime
+#define sys_clock_getres	compat_sys_clock_getres
+#define sys_clock_nanosleep	compat_sys_clock_nanosleep
+#define sys_statfs64		compat_sys_statfs64_wrapper
+#define sys_fstatfs64		compat_sys_fstatfs64_wrapper
+#define sys_utimes		compat_sys_utimes
+#define sys_fadvise64_64	compat_sys_fadvise64_64_wrapper
+#define sys_mq_open		compat_sys_mq_open
+#define sys_mq_timedsend	compat_sys_mq_timedsend
+#define sys_mq_timedreceive	compat_sys_mq_timedreceive
+#define sys_mq_notify		compat_sys_mq_notify
+#define sys_mq_getsetattr	compat_sys_mq_getsetattr
+#define sys_waitid		compat_sys_waitid
+#define sys_recv		compat_sys_recv
+#define sys_recvfrom		compat_sys_recvfrom
+#define sys_setsockopt		compat_sys_setsockopt
+#define sys_getsockopt		compat_sys_getsockopt
+#define sys_sendmsg		compat_sys_sendmsg
+#define sys_recvmsg		compat_sys_recvmsg
+#define sys_semctl		compat_sys_semctl
+#define sys_msgsnd		compat_sys_msgsnd
+#define sys_msgrcv		compat_sys_msgrcv
+#define sys_msgctl		compat_sys_msgctl
+#define sys_shmat		compat_sys_shmat
+#define sys_shmctl		compat_sys_shmctl
+#define sys_keyctl		compat_sys_keyctl
+#define sys_semtimedop		compat_sys_semtimedop
+#define sys_mbind		compat_sys_mbind
+#define sys_get_mempolicy	compat_sys_get_mempolicy
+#define sys_set_mempolicy	compat_sys_set_mempolicy
+#define sys_openat		compat_sys_openat
+#define sys_futimesat		compat_sys_futimesat
+#define sys_pselect6		compat_sys_pselect6
+#define sys_ppoll		compat_sys_ppoll
+#define sys_set_robust_list	compat_sys_set_robust_list
+#define sys_get_robust_list	compat_sys_get_robust_list
+#define sys_sync_file_range2	compat_sys_sync_file_range2_wrapper
+#define sys_vmsplice		compat_sys_vmsplice
+#define sys_move_pages		compat_sys_move_pages
+#define sys_epoll_pwait		compat_sys_epoll_pwait
+#define sys_kexec_load		compat_sys_kexec_load
+#define sys_utimensat		compat_sys_utimensat
+#define sys_signalfd		compat_sys_signalfd
+#define sys_fallocate		compat_sys_fallocate_wrapper
+#define sys_timerfd_settime	compat_sys_timerfd_settime
+#define sys_timerfd_gettime	compat_sys_timerfd_gettime
+#define sys_signalfd4		compat_sys_signalfd4
+#define sys_preadv		compat_sys_preadv
+#define sys_pwritev		compat_sys_pwritev
+#define sys_rt_tgsigqueueinfo	compat_sys_rt_tgsigqueueinfo
+#define sys_recvmmsg		compat_sys_recvmmsg
+#define sys_fanotify_mark	compat_sys_fanotify_mark_wrapper
+
+#undef __SYSCALL
+#define __SYSCALL(x, y)		.quad	y	// x
+#define __SYSCALL_COMPAT
+
+/*
+ * The system calls table must be 4KB aligned.
+ */
+	.align	12
+ENTRY(compat_sys_call_table)
+#include <asm/unistd.h>
diff --git a/arch/arm64/kernel/sys_compat.c b/arch/arm64/kernel/sys_compat.c
new file mode 100644
index 0000000..967e92f
--- /dev/null
+++ b/arch/arm64/kernel/sys_compat.c
@@ -0,0 +1,164 @@
+/*
+ * Based on arch/arm/kernel/sys_arm.c
+ *
+ * Copyright (C) People who wrote linux/arch/i386/kernel/sys_i386.c
+ * Copyright (C) 1995, 1996 Russell King.
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define __SYSCALL_COMPAT
+
+#include <linux/compat.h>
+#include <linux/personality.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/syscalls.h>
+#include <linux/uaccess.h>
+
+#include <asm/cacheflush.h>
+#include <asm/unistd.h>
+
+asmlinkage int compat_sys_fork(struct pt_regs *regs)
+{
+	return do_fork(SIGCHLD, regs->compat_sp, regs, 0, NULL, NULL);
+}
+
+asmlinkage int compat_sys_clone(unsigned long clone_flags, unsigned long newsp,
+			  int __user *parent_tidptr, int tls_val,
+			  int __user *child_tidptr, struct pt_regs *regs)
+{
+	if (!newsp)
+		newsp = regs->compat_sp;
+
+	return do_fork(clone_flags, newsp, regs, 0, parent_tidptr, child_tidptr);
+}
+
+asmlinkage int compat_sys_vfork(struct pt_regs *regs)
+{
+	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->compat_sp,
+		       regs, 0, NULL, NULL);
+}
+
+asmlinkage int compat_sys_execve(const char __user *filenamei,
+				 compat_uptr_t argv, compat_uptr_t envp,
+				 struct pt_regs *regs)
+{
+	int error;
+	char * filename;
+
+	filename = getname(filenamei);
+	error = PTR_ERR(filename);
+	if (IS_ERR(filename))
+		goto out;
+	error = compat_do_execve(filename, compat_ptr(argv), compat_ptr(envp),
+				 regs);
+	putname(filename);
+out:
+	return error;
+}
+
+asmlinkage int compat_sys_sched_rr_get_interval(compat_pid_t pid,
+						struct compat_timespec __user *interval)
+{
+	struct timespec t;
+	int ret;
+	mm_segment_t old_fs = get_fs();
+
+	set_fs(KERNEL_DS);
+	ret = sys_sched_rr_get_interval(pid, (struct timespec __user *)&t);
+	set_fs(old_fs);
+	if (put_compat_timespec(&t, interval))
+		return -EFAULT;
+	return ret;
+}
+
+asmlinkage int compat_sys_sendfile(int out_fd, int in_fd,
+				   compat_off_t __user *offset, s32 count)
+{
+	mm_segment_t old_fs = get_fs();
+	int ret;
+	off_t of;
+
+	if (offset && get_user(of, offset))
+		return -EFAULT;
+
+	set_fs(KERNEL_DS);
+	ret = sys_sendfile(out_fd, in_fd, offset ? (off_t __user *)&of : NULL,
+			   count);
+	set_fs(old_fs);
+
+	if (offset && put_user(of, offset))
+		return -EFAULT;
+	return ret;
+}
+
+static inline void
+do_compat_cache_op(unsigned long start, unsigned long end, int flags)
+{
+	struct mm_struct *mm = current->active_mm;
+	struct vm_area_struct *vma;
+
+	if (end < start || flags)
+		return;
+
+	down_read(&mm->mmap_sem);
+	vma = find_vma(mm, start);
+	if (vma && vma->vm_start < end) {
+		if (start < vma->vm_start)
+			start = vma->vm_start;
+		if (end > vma->vm_end)
+			end = vma->vm_end;
+		up_read(&mm->mmap_sem);
+		__flush_cache_user_range(start & PAGE_MASK, PAGE_ALIGN(end));
+		return;
+	}
+	up_read(&mm->mmap_sem);
+}
+
+/*
+ * Handle all unrecognised system calls.
+ */
+long compat_arm_syscall(struct pt_regs *regs)
+{
+	unsigned int no = regs->regs[7];
+
+	switch (no) {
+	/*
+	 * Flush a region from virtual address 'r0' to virtual address 'r1'
+	 * _exclusive_.  There is no alignment requirement on either address;
+	 * user space does not need to know the hardware cache layout.
+	 *
+	 * r2 contains flags.  It should ALWAYS be passed as ZERO until it
+	 * is defined to be something else.  For now we ignore it, but may
+	 * the fires of hell burn in your belly if you break this rule. ;)
+	 *
+	 * (at a later date, we may want to allow this call to not flush
+	 * various aspects of the cache.  Passing '0' will guarantee that
+	 * everything necessary gets flushed to maintain consistency in
+	 * the specified region).
+	 */
+	case __ARM_NR_compat_cacheflush:
+		do_compat_cache_op(regs->regs[0], regs->regs[1], regs->regs[2]);
+		return 0;
+
+	case __ARM_NR_compat_set_tls:
+		current->thread.tp_value = regs->regs[0];
+		asm ("msr tpidrro_el0, %0" : : "r" (regs->regs[0]));
+		return 0;
+
+	default:
+		return -ENOSYS;
+	}
+}
diff --git a/arch/arm64/kernel/time.c b/arch/arm64/kernel/time.c
new file mode 100644
index 0000000..3b4b725
--- /dev/null
+++ b/arch/arm64/kernel/time.c
@@ -0,0 +1,65 @@
+/*
+ * Based on arch/arm/kernel/time.c
+ *
+ * Copyright (C) 1991, 1992, 1995  Linus Torvalds
+ * Modifications for ARM (C) 1994-2001 Russell King
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/export.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/timex.h>
+#include <linux/errno.h>
+#include <linux/profile.h>
+#include <linux/syscore_ops.h>
+#include <linux/timer.h>
+#include <linux/irq.h>
+
+#include <clocksource/arm_generic.h>
+
+#include <asm/thread_info.h>
+#include <asm/stacktrace.h>
+
+#ifdef CONFIG_SMP
+unsigned long profile_pc(struct pt_regs *regs)
+{
+	struct stackframe frame;
+
+	if (!in_lock_functions(regs->pc))
+		return regs->pc;
+
+	frame.fp = regs->regs[29];
+	frame.sp = regs->sp;
+	frame.pc = regs->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
+
+void __init time_init(void)
+{
+	arm_generic_timer_init();
+}
diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
new file mode 100644
index 0000000..3883f84
--- /dev/null
+++ b/arch/arm64/kernel/traps.c
@@ -0,0 +1,348 @@
+/*
+ * Based on arch/arm/kernel/traps.c
+ *
+ * Copyright (C) 1995-2009 Russell King
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/signal.h>
+#include <linux/personality.h>
+#include <linux/kallsyms.h>
+#include <linux/spinlock.h>
+#include <linux/uaccess.h>
+#include <linux/hardirq.h>
+#include <linux/kdebug.h>
+#include <linux/module.h>
+#include <linux/kexec.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/syscalls.h>
+
+#include <asm/atomic.h>
+#include <asm/traps.h>
+#include <asm/stacktrace.h>
+#include <asm/exception.h>
+#include <asm/system_misc.h>
+
+static const char *handler[]= {
+	"Synchronous Abort",
+	"IRQ",
+	"FIQ",
+	"Error"
+};
+
+int show_unhandled_signals = 1;
+
+/*
+ * Dump out the contents of some memory nicely...
+ */
+static void dump_mem(const char *lvl, const char *str, unsigned long bottom,
+		     unsigned long top)
+{
+	unsigned long first;
+	mm_segment_t fs;
+	int i;
+
+	/*
+	 * We need to switch to kernel mode so that we can use __get_user
+	 * to safely read from kernel space.  Note that we now dump the
+	 * code first, just in case the backtrace kills us.
+	 */
+	fs = get_fs();
+	set_fs(KERNEL_DS);
+
+	printk("%s%s(0x%016lx to 0x%016lx)\n", lvl, str, bottom, top);
+
+	for (first = bottom & ~31; first < top; first += 32) {
+		unsigned long p;
+		char str[sizeof(" 12345678") * 8 + 1];
+
+		memset(str, ' ', sizeof(str));
+		str[sizeof(str) - 1] = '\0';
+
+		for (p = first, i = 0; i < 8 && p < top; i++, p += 4) {
+			if (p >= bottom && p < top) {
+				unsigned int val;
+				if (__get_user(val, (unsigned int *)p) == 0)
+					sprintf(str + i * 9, " %08x", val);
+				else
+					sprintf(str + i * 9, " ????????");
+			}
+		}
+		printk("%s%04lx:%s\n", lvl, first & 0xffff, str);
+	}
+
+	set_fs(fs);
+}
+
+static void dump_backtrace_entry(unsigned long where, unsigned long stack)
+{
+	print_ip_sym(where);
+	if (in_exception_text(where))
+		dump_mem("", "Exception stack", stack,
+			 stack + sizeof(struct pt_regs));
+}
+
+static void dump_instr(const char *lvl, struct pt_regs *regs)
+{
+	unsigned long addr = instruction_pointer(regs);
+	mm_segment_t fs;
+	char str[sizeof("00000000 ") * 5 + 2 + 1], *p = str;
+	int i;
+
+	/*
+	 * We need to switch to kernel mode so that we can use __get_user
+	 * to safely read from kernel space.  Note that we now dump the
+	 * code first, just in case the backtrace kills us.
+	 */
+	fs = get_fs();
+	set_fs(KERNEL_DS);
+
+	for (i = -4; i < 1; i++) {
+		unsigned int val, bad;
+
+		bad = __get_user(val, &((u32 *)addr)[i]);
+
+		if (!bad)
+			p += sprintf(p, i == 0 ? "(%08x) " : "%08x ", val);
+		else {
+			p += sprintf(p, "bad PC value");
+			break;
+		}
+	}
+	printk("%sCode: %s\n", lvl, str);
+
+	set_fs(fs);
+}
+
+static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk)
+{
+	struct stackframe frame;
+	const 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->regs[29];
+		frame.sp = regs->sp;
+		frame.pc = regs->pc;
+	} else if (tsk == current) {
+		frame.fp = (unsigned long)__builtin_frame_address(0);
+		frame.sp = current_sp;
+		frame.pc = (unsigned long)dump_backtrace;
+	} else {
+		/*
+		 * task blocked in __switch_to
+		 */
+		frame.fp = thread_saved_fp(tsk);
+		frame.sp = thread_saved_sp(tsk);
+		frame.pc = thread_saved_pc(tsk);
+	}
+
+	printk("Call trace:\n");
+	while (1) {
+		unsigned long where = frame.pc;
+		int ret;
+
+		ret = unwind_frame(&frame);
+		if (ret < 0)
+			break;
+		dump_backtrace_entry(where, frame.sp);
+	}
+}
+
+void dump_stack(void)
+{
+	dump_backtrace(NULL, NULL);
+}
+
+EXPORT_SYMBOL(dump_stack);
+
+void show_stack(struct task_struct *tsk, unsigned long *sp)
+{
+	dump_backtrace(NULL, tsk);
+	barrier();
+}
+
+#ifdef CONFIG_PREEMPT
+#define S_PREEMPT " PREEMPT"
+#else
+#define S_PREEMPT ""
+#endif
+#ifdef CONFIG_SMP
+#define S_SMP " SMP"
+#else
+#define S_SMP ""
+#endif
+
+static int __die(const char *str, int err, struct thread_info *thread,
+		 struct pt_regs *regs)
+{
+	struct task_struct *tsk = thread->task;
+	static int die_counter;
+	int ret;
+
+	pr_emerg("Internal error: %s: %x [#%d]" S_PREEMPT S_SMP "\n",
+		 str, err, ++die_counter);
+
+	/* trap and error numbers are mostly meaningless on ARM */
+	ret = notify_die(DIE_OOPS, str, regs, err, 0, SIGSEGV);
+	if (ret == NOTIFY_STOP)
+		return ret;
+
+	print_modules();
+	__show_regs(regs);
+	pr_emerg("Process %.*s (pid: %d, stack limit = 0x%p)\n",
+		 TASK_COMM_LEN, tsk->comm, task_pid_nr(tsk), thread + 1);
+
+	if (!user_mode(regs) || in_interrupt()) {
+		dump_mem(KERN_EMERG, "Stack: ", regs->sp,
+			 THREAD_SIZE + (unsigned long)task_stack_page(tsk));
+		dump_backtrace(regs, tsk);
+		dump_instr(KERN_EMERG, regs);
+	}
+
+	return ret;
+}
+
+static DEFINE_RAW_SPINLOCK(die_lock);
+
+/*
+ * This function is protected against re-entrancy.
+ */
+void die(const char *str, struct pt_regs *regs, int err)
+{
+	struct thread_info *thread = current_thread_info();
+	int ret;
+
+	oops_enter();
+
+	raw_spin_lock_irq(&die_lock);
+	console_verbose();
+	bust_spinlocks(1);
+	ret = __die(str, err, thread, regs);
+
+	if (regs && kexec_should_crash(thread->task))
+		crash_kexec(regs);
+
+	bust_spinlocks(0);
+	add_taint(TAINT_DIE);
+	raw_spin_unlock_irq(&die_lock);
+	oops_exit();
+
+	if (in_interrupt())
+		panic("Fatal exception in interrupt");
+	if (panic_on_oops)
+		panic("Fatal exception");
+	if (ret != NOTIFY_STOP)
+		do_exit(SIGSEGV);
+}
+
+void arm64_notify_die(const char *str, struct pt_regs *regs,
+		      struct siginfo *info, int err)
+{
+	if (user_mode(regs))
+		force_sig_info(info->si_signo, info, current);
+	else
+		die(str, regs, err);
+}
+
+asmlinkage void __exception do_undefinstr(struct pt_regs *regs)
+{
+	siginfo_t info;
+	void __user *pc = (void __user *)instruction_pointer(regs);
+
+#ifdef CONFIG_COMPAT
+	/* check for AArch32 breakpoint instructions */
+	if (compat_user_mode(regs) && aarch32_break_trap(regs) == 0)
+		return;
+#endif
+
+	if (show_unhandled_signals) {
+		pr_info("%s[%d]: undefined instruction: pc=%p\n",
+			current->comm, task_pid_nr(current), pc);
+		dump_instr(KERN_INFO, regs);
+	}
+
+	info.si_signo = SIGILL;
+	info.si_errno = 0;
+	info.si_code  = ILL_ILLOPC;
+	info.si_addr  = pc;
+
+	arm64_notify_die("Oops - undefined instruction", regs, &info, 0);
+}
+
+long compat_arm_syscall(struct pt_regs *regs);
+
+asmlinkage long do_ni_syscall(struct pt_regs *regs)
+{
+#ifdef CONFIG_COMPAT
+	long ret;
+	if (is_compat_task()) {
+		ret = compat_arm_syscall(regs);
+		if (ret != -ENOSYS)
+			return ret;
+	}
+#endif
+
+	if (show_unhandled_signals) {
+		pr_info("%s[%d]: syscall %d\n", current->comm,
+			task_pid_nr(current), (int)regs->syscallno);
+		dump_instr("", regs);
+		if (user_mode(regs))
+			__show_regs(regs);
+	}
+
+	return sys_ni_syscall();
+}
+
+/*
+ * bad_mode handles the impossible case in the exception vector.
+ */
+asmlinkage void bad_mode(struct pt_regs *regs, int reason, unsigned int esr)
+{
+	console_verbose();
+
+	pr_crit("Bad mode in %s handler detected, code 0x%08x\n",
+		handler[reason], esr);
+
+	die("Oops - bad mode", regs, 0);
+	local_irq_disable();
+	panic("bad mode");
+}
+
+void __pte_error(const char *file, int line, unsigned long val)
+{
+	printk("%s:%d: bad pte %016lx.\n", file, line, val);
+}
+
+void __pmd_error(const char *file, int line, unsigned long val)
+{
+	printk("%s:%d: bad pmd %016lx.\n", file, line, val);
+}
+
+void __pgd_error(const char *file, int line, unsigned long val)
+{
+	printk("%s:%d: bad pgd %016lx.\n", file, line, val);
+}
+
+void __init trap_init(void)
+{
+	return;
+}
diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c
new file mode 100644
index 0000000..17948fc
--- /dev/null
+++ b/arch/arm64/kernel/vdso.c
@@ -0,0 +1,261 @@
+/*
+ * VDSO implementation for AArch64 and vector page setup for AArch32.
+ *
+ * Copyright (C) 2012 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Will Deacon <will.deacon@arm.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/clocksource.h>
+#include <linux/elf.h>
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/gfp.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+
+#include <asm/cacheflush.h>
+#include <asm/signal32.h>
+#include <asm/vdso.h>
+#include <asm/vdso_datapage.h>
+
+extern char vdso_start, vdso_end;
+static unsigned long vdso_pages;
+static struct page **vdso_pagelist;
+
+/*
+ * The vDSO data page.
+ */
+static union {
+	struct vdso_data	data;
+	u8			page[PAGE_SIZE];
+} vdso_data_store __page_aligned_data;
+struct vdso_data *vdso_data = &vdso_data_store.data;
+
+#ifdef CONFIG_COMPAT
+/*
+ * Create and map the vectors page for AArch32 tasks.
+ */
+static struct page *vectors_page[1];
+
+static int alloc_vectors_page(void)
+{
+	extern char __kuser_helper_start[], __kuser_helper_end[];
+	int kuser_sz = __kuser_helper_end - __kuser_helper_start;
+	unsigned long vpage;
+
+	vpage = get_zeroed_page(GFP_ATOMIC);
+
+	if (!vpage)
+		return -ENOMEM;
+
+	/* kuser helpers */
+	memcpy((void *)vpage + 0x1000 - kuser_sz, __kuser_helper_start,
+		kuser_sz);
+
+	/* sigreturn code */
+	memcpy((void *)vpage + AARCH32_KERN_SIGRET_CODE_OFFSET,
+		aarch32_sigret_code, sizeof(aarch32_sigret_code));
+
+	flush_icache_range(vpage, vpage + PAGE_SIZE);
+	vectors_page[0] = virt_to_page(vpage);
+
+	return 0;
+}
+arch_initcall(alloc_vectors_page);
+
+int aarch32_setup_vectors_page(struct linux_binprm *bprm, int uses_interp)
+{
+	struct mm_struct *mm = current->mm;
+	unsigned long addr = AARCH32_VECTORS_BASE;
+	int ret;
+
+	down_write(&mm->mmap_sem);
+	current->mm->context.vdso = (void *)addr;
+
+	/* Map vectors page at the high address. */
+	ret = install_special_mapping(mm, addr, PAGE_SIZE,
+				      VM_READ|VM_EXEC|VM_MAYREAD|VM_MAYEXEC,
+				      vectors_page);
+
+	up_write(&mm->mmap_sem);
+
+	return ret;
+}
+#endif /* CONFIG_COMPAT */
+
+static int __init vdso_init(void)
+{
+	struct page *pg;
+	char *vbase;
+	int i, ret = 0;
+
+	vdso_pages = (&vdso_end - &vdso_start) >> PAGE_SHIFT;
+	pr_info("vdso: %ld pages (%ld code, %ld data) at base %p\n",
+		vdso_pages + 1, vdso_pages, 1L, &vdso_start);
+
+	/* Allocate the vDSO pagelist, plus a page for the data. */
+	vdso_pagelist = kzalloc(sizeof(struct page *) * (vdso_pages + 1),
+				GFP_KERNEL);
+	if (vdso_pagelist == NULL) {
+		pr_err("Failed to allocate vDSO pagelist!\n");
+		return -ENOMEM;
+	}
+
+	/* Grab the vDSO code pages. */
+	for (i = 0; i < vdso_pages; i++) {
+		pg = virt_to_page(&vdso_start + i*PAGE_SIZE);
+		ClearPageReserved(pg);
+		get_page(pg);
+		vdso_pagelist[i] = pg;
+	}
+
+	/* Sanity check the shared object header. */
+	vbase = vmap(vdso_pagelist, 1, 0, PAGE_KERNEL);
+	if (vbase == NULL) {
+		pr_err("Failed to map vDSO pagelist!\n");
+		return -ENOMEM;
+	} else if (memcmp(vbase, "\177ELF", 4)) {
+		pr_err("vDSO is not a valid ELF object!\n");
+		ret = -EINVAL;
+		goto unmap;
+	}
+
+	/* Grab the vDSO data page. */
+	pg = virt_to_page(vdso_data);
+	get_page(pg);
+	vdso_pagelist[i] = pg;
+
+unmap:
+	vunmap(vbase);
+	return ret;
+}
+arch_initcall(vdso_init);
+
+int arch_setup_additional_pages(struct linux_binprm *bprm,
+				int uses_interp)
+{
+	struct mm_struct *mm = current->mm;
+	unsigned long vdso_base, vdso_mapping_len;
+	int ret;
+
+	/* Be sure to map the data page */
+	vdso_mapping_len = (vdso_pages + 1) << PAGE_SHIFT;
+
+	down_write(&mm->mmap_sem);
+	vdso_base = get_unmapped_area(NULL, 0, vdso_mapping_len, 0, 0);
+	if (IS_ERR_VALUE(vdso_base)) {
+		ret = vdso_base;
+		goto up_fail;
+	}
+	mm->context.vdso = (void *)vdso_base;
+
+	ret = install_special_mapping(mm, vdso_base, vdso_mapping_len,
+				      VM_READ|VM_EXEC|
+				      VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC,
+				      vdso_pagelist);
+	if (ret) {
+		mm->context.vdso = NULL;
+		goto up_fail;
+	}
+
+up_fail:
+	up_write(&mm->mmap_sem);
+
+	return ret;
+}
+
+const char *arch_vma_name(struct vm_area_struct *vma)
+{
+	/*
+	 * We can re-use the vdso pointer in mm_context_t for identifying
+	 * the vectors page for compat applications. The vDSO will always
+	 * sit above TASK_UNMAPPED_BASE and so we don't need to worry about
+	 * it conflicting with the vectors base.
+	 */
+	if (vma->vm_mm && vma->vm_start == (long)vma->vm_mm->context.vdso) {
+#ifdef CONFIG_COMPAT
+		if (vma->vm_start == AARCH32_VECTORS_BASE)
+			return "[vectors]";
+#endif
+		return "[vdso]";
+	}
+
+	return NULL;
+}
+
+/*
+ * We define AT_SYSINFO_EHDR, so we need these function stubs to keep
+ * Linux happy.
+ */
+int in_gate_area_no_mm(unsigned long addr)
+{
+	return 0;
+}
+
+int in_gate_area(struct mm_struct *mm, unsigned long addr)
+{
+	return 0;
+}
+
+struct vm_area_struct *get_gate_vma(struct mm_struct *mm)
+{
+	return NULL;
+}
+
+/*
+ * Update the vDSO data page to keep in sync with kernel timekeeping.
+ */
+void update_vsyscall(struct timespec *ts, struct timespec *wtm,
+		     struct clocksource *clock, u32 mult)
+{
+	struct timespec xtime_coarse;
+	u32 use_syscall = strcmp(clock->name, "arch_sys_counter");
+
+	++vdso_data->tb_seq_count;
+	smp_wmb();
+
+	xtime_coarse = __current_kernel_time();
+	vdso_data->use_syscall			= use_syscall;
+	vdso_data->xtime_coarse_sec		= xtime_coarse.tv_sec;
+	vdso_data->xtime_coarse_nsec		= xtime_coarse.tv_nsec;
+
+	if (!use_syscall) {
+		vdso_data->cs_cycle_last	= clock->cycle_last;
+		vdso_data->xtime_clock_sec	= ts->tv_sec;
+		vdso_data->xtime_clock_nsec	= ts->tv_nsec;
+		vdso_data->cs_mult		= mult;
+		vdso_data->cs_shift		= clock->shift;
+		vdso_data->wtm_clock_sec	= wtm->tv_sec;
+		vdso_data->wtm_clock_nsec	= wtm->tv_nsec;
+	}
+
+	smp_wmb();
+	++vdso_data->tb_seq_count;
+}
+
+void update_vsyscall_tz(void)
+{
+	++vdso_data->tb_seq_count;
+	smp_wmb();
+	vdso_data->tz_minuteswest	= sys_tz.tz_minuteswest;
+	vdso_data->tz_dsttime		= sys_tz.tz_dsttime;
+	smp_wmb();
+	++vdso_data->tb_seq_count;
+}
diff --git a/arch/arm64/kernel/vdso/.gitignore b/arch/arm64/kernel/vdso/.gitignore
new file mode 100644
index 0000000..b8cc94e
--- /dev/null
+++ b/arch/arm64/kernel/vdso/.gitignore
@@ -0,0 +1,2 @@
+vdso.lds
+vdso-offsets.h
diff --git a/arch/arm64/kernel/vdso/Makefile b/arch/arm64/kernel/vdso/Makefile
new file mode 100644
index 0000000..d8064af
--- /dev/null
+++ b/arch/arm64/kernel/vdso/Makefile
@@ -0,0 +1,63 @@
+#
+# Building a vDSO image for AArch64.
+#
+# Author: Will Deacon <will.deacon@arm.com>
+# Heavily based on the vDSO Makefiles for other archs.
+#
+
+obj-vdso := gettimeofday.o note.o sigreturn.o
+
+# Build rules
+targets := $(obj-vdso) vdso.so vdso.so.dbg
+obj-vdso := $(addprefix $(obj)/, $(obj-vdso))
+
+ccflags-y := -shared -fno-common -fno-builtin
+ccflags-y += -nostdlib -Wl,-soname=linux-vdso.so.1 \
+		$(call cc-ldoption, -Wl$(comma)--hash-style=sysv)
+
+obj-y += vdso.o
+extra-y += vdso.lds vdso-offsets.h
+CPPFLAGS_vdso.lds += -P -C -U$(ARCH)
+
+# Force dependency (incbin is bad)
+$(obj)/vdso.o : $(obj)/vdso.so
+
+# Link rule for the .so file, .lds has to be first
+$(obj)/vdso.so.dbg: $(src)/vdso.lds $(obj-vdso)
+	$(call if_changed,vdsold)
+
+# Strip rule for the .so file
+$(obj)/%.so: OBJCOPYFLAGS := -S
+$(obj)/%.so: $(obj)/%.so.dbg FORCE
+	$(call if_changed,objcopy)
+
+# Generate VDSO offsets using helper script
+gen-vdsosym := $(srctree)/$(src)/gen_vdso_offsets.sh
+quiet_cmd_vdsosym = VDSOSYM $@
+define cmd_vdsosym
+	$(NM) $< | $(gen-vdsosym) | LC_ALL=C sort > $@ && \
+	cp $@ include/generated/
+endef
+
+$(obj)/vdso-offsets.h: $(obj)/vdso.so.dbg FORCE
+	$(call if_changed,vdsosym)
+
+# Assembly rules for the .S files
+$(obj-vdso): %.o: %.S
+	$(call if_changed_dep,vdsoas)
+
+# Actual build commands
+quiet_cmd_vdsold = VDSOL $@
+      cmd_vdsold = $(CC) $(c_flags) -Wl,-T $^ -o $@
+quiet_cmd_vdsoas = VDSOA $@
+      cmd_vdsoas = $(CC) $(a_flags) -c -o $@ $<
+
+# Install commands for the unstripped file
+quiet_cmd_vdso_install = INSTALL $@
+      cmd_vdso_install = cp $(obj)/$@.dbg $(MODLIB)/vdso/$@
+
+vdso.so: $(obj)/vdso.so.dbg
+	@mkdir -p $(MODLIB)/vdso
+	$(call cmd,vdso_install)
+
+vdso_install: vdso.so
diff --git a/arch/arm64/kernel/vdso/gen_vdso_offsets.sh b/arch/arm64/kernel/vdso/gen_vdso_offsets.sh
new file mode 100755
index 0000000..01924ff
--- /dev/null
+++ b/arch/arm64/kernel/vdso/gen_vdso_offsets.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+#
+# Match symbols in the DSO that look like VDSO_*; produce a header file
+# of constant offsets into the shared object.
+#
+# Doing this inside the Makefile will break the $(filter-out) function,
+# causing Kbuild to rebuild the vdso-offsets header file every time.
+#
+# Author: Will Deacon <will.deacon@arm.com
+#
+
+LC_ALL=C
+sed -n -e 's/^00*/0/' -e \
+'s/^\([0-9a-fA-F]*\) . VDSO_\([a-zA-Z0-9_]*\)$/\#define vdso_offset_\2\t0x\1/p'
diff --git a/arch/arm64/kernel/vdso/gettimeofday.S b/arch/arm64/kernel/vdso/gettimeofday.S
new file mode 100644
index 0000000..dcb8c20
--- /dev/null
+++ b/arch/arm64/kernel/vdso/gettimeofday.S
@@ -0,0 +1,242 @@
+/*
+ * Userspace implementations of gettimeofday() and friends.
+ *
+ * Copyright (C) 2012 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Will Deacon <will.deacon@arm.com>
+ */
+
+#include <linux/linkage.h>
+#include <asm/asm-offsets.h>
+#include <asm/unistd.h>
+
+#define NSEC_PER_SEC_LO16	0xca00
+#define NSEC_PER_SEC_HI16	0x3b9a
+
+vdso_data	.req	x6
+use_syscall	.req	w7
+seqcnt		.req	w8
+
+	.macro	seqcnt_acquire
+9999:	ldr	seqcnt, [vdso_data, #VDSO_TB_SEQ_COUNT]
+	tbnz	seqcnt, #0, 9999b
+	dmb	ishld
+	ldr	use_syscall, [vdso_data, #VDSO_USE_SYSCALL]
+	.endm
+
+	.macro	seqcnt_read, cnt
+	dmb	ishld
+	ldr	\cnt, [vdso_data, #VDSO_TB_SEQ_COUNT]
+	.endm
+
+	.macro	seqcnt_check, cnt, fail
+	cmp	\cnt, seqcnt
+	b.ne	\fail
+	.endm
+
+	.text
+
+/* int __kernel_gettimeofday(struct timeval *tv, struct timezone *tz); */
+ENTRY(__kernel_gettimeofday)
+	.cfi_startproc
+	mov	x2, x30
+	.cfi_register x30, x2
+
+	/* Acquire the sequence counter and get the timespec. */
+	adr	vdso_data, _vdso_data
+1:	seqcnt_acquire
+	cbnz	use_syscall, 4f
+
+	/* If tv is NULL, skip to the timezone code. */
+	cbz	x0, 2f
+	bl	__do_get_tspec
+	seqcnt_check w13, 1b
+
+	/* Convert ns to us. */
+	mov	x11, #1000
+	udiv	x10, x10, x11
+	stp	x9, x10, [x0, #TVAL_TV_SEC]
+2:
+	/* If tz is NULL, return 0. */
+	cbz	x1, 3f
+	ldp	w4, w5, [vdso_data, #VDSO_TZ_MINWEST]
+	seqcnt_read w13
+	seqcnt_check w13, 1b
+	stp	w4, w5, [x1, #TZ_MINWEST]
+3:
+	mov	x0, xzr
+	ret	x2
+4:
+	/* Syscall fallback. */
+	mov	x8, #__NR_gettimeofday
+	svc	#0
+	ret	x2
+	.cfi_endproc
+ENDPROC(__kernel_gettimeofday)
+
+/* int __kernel_clock_gettime(clockid_t clock_id, struct timespec *tp); */
+ENTRY(__kernel_clock_gettime)
+	.cfi_startproc
+	cmp	w0, #CLOCK_REALTIME
+	ccmp	w0, #CLOCK_MONOTONIC, #0x4, ne
+	b.ne	2f
+
+	mov	x2, x30
+	.cfi_register x30, x2
+
+	/* Get kernel timespec. */
+	adr	vdso_data, _vdso_data
+1:	seqcnt_acquire
+	cbnz	use_syscall, 7f
+
+	bl	__do_get_tspec
+	seqcnt_check w13, 1b
+
+	cmp	w0, #CLOCK_MONOTONIC
+	b.ne	6f
+
+	/* Get wtm timespec. */
+	ldp	x14, x15, [vdso_data, #VDSO_WTM_CLK_SEC]
+
+	/* Check the sequence counter. */
+	seqcnt_read w13
+	seqcnt_check w13, 1b
+	b	4f
+2:
+	cmp	w0, #CLOCK_REALTIME_COARSE
+	ccmp	w0, #CLOCK_MONOTONIC_COARSE, #0x4, ne
+	b.ne	8f
+
+	/* Get coarse timespec. */
+	adr	vdso_data, _vdso_data
+3:	seqcnt_acquire
+	ldp	x9, x10, [vdso_data, #VDSO_XTIME_CRS_SEC]
+
+	cmp	w0, #CLOCK_MONOTONIC_COARSE
+	b.ne	6f
+
+	/* Get wtm timespec. */
+	ldp	x14, x15, [vdso_data, #VDSO_WTM_CLK_SEC]
+
+	/* Check the sequence counter. */
+	seqcnt_read w13
+	seqcnt_check w13, 3b
+4:
+	/* Add on wtm timespec. */
+	add	x9, x9, x14
+	add	x10, x10, x15
+
+	/* Normalise the new timespec. */
+	mov	x14, #NSEC_PER_SEC_LO16
+	movk	x14, #NSEC_PER_SEC_HI16, lsl #16
+	cmp	x10, x14
+	b.lt	5f
+	sub	x10, x10, x14
+	add	x9, x9, #1
+5:
+	cmp	x10, #0
+	b.ge	6f
+	add	x10, x10, x14
+	sub	x9, x9, #1
+
+6:	/* Store to the user timespec. */
+	stp	x9, x10, [x1, #TSPEC_TV_SEC]
+	mov	x0, xzr
+	ret	x2
+7:
+	mov	x30, x2
+8:	/* Syscall fallback. */
+	mov	x8, #__NR_clock_gettime
+	svc	#0
+	ret
+	.cfi_endproc
+ENDPROC(__kernel_clock_gettime)
+
+/* int __kernel_clock_getres(clockid_t clock_id, struct timespec *res); */
+ENTRY(__kernel_clock_getres)
+	.cfi_startproc
+	cbz	w1, 3f
+
+	cmp	w0, #CLOCK_REALTIME
+	ccmp	w0, #CLOCK_MONOTONIC, #0x4, ne
+	b.ne	1f
+
+	ldr	x2, 5f
+	b	2f
+1:
+	cmp	w0, #CLOCK_REALTIME_COARSE
+	ccmp	w0, #CLOCK_MONOTONIC_COARSE, #0x4, ne
+	b.ne	4f
+	ldr	x2, 6f
+2:
+	stp	xzr, x2, [x1]
+
+3:	/* res == NULL. */
+	mov	w0, wzr
+	ret
+
+4:	/* Syscall fallback. */
+	mov	x8, #__NR_clock_getres
+	svc	#0
+	ret
+5:
+	.quad	CLOCK_REALTIME_RES
+6:
+	.quad	CLOCK_COARSE_RES
+	.cfi_endproc
+ENDPROC(__kernel_clock_getres)
+
+/*
+ * Read the current time from the architected counter.
+ * Expects vdso_data to be initialised.
+ * Clobbers the temporary registers (x9 - x15).
+ * Returns:
+ *  - (x9, x10) = (ts->tv_sec, ts->tv_nsec)
+ *  - (x11, x12) = (xtime->tv_sec, xtime->tv_nsec)
+ *  - w13 = vDSO sequence counter
+ */
+ENTRY(__do_get_tspec)
+	.cfi_startproc
+
+	/* Read from the vDSO data page. */
+	ldr	x10, [vdso_data, #VDSO_CS_CYCLE_LAST]
+	ldp	x11, x12, [vdso_data, #VDSO_XTIME_CLK_SEC]
+	ldp	w14, w15, [vdso_data, #VDSO_CS_MULT]
+	seqcnt_read w13
+
+	/* Read the physical counter. */
+	isb
+	mrs	x9, cntpct_el0
+
+	/* Calculate cycle delta and convert to ns. */
+	sub	x10, x9, x10
+	/* We can only guarantee 56 bits of precision. */
+	movn	x9, #0xff0, lsl #48
+	and	x10, x9, x10
+	mul	x10, x10, x14
+	lsr	x10, x10, x15
+
+	/* Use the kernel time to calculate the new timespec. */
+	add	x10, x12, x10
+	mov	x14, #NSEC_PER_SEC_LO16
+	movk	x14, #NSEC_PER_SEC_HI16, lsl #16
+	udiv	x15, x10, x14
+	add	x9, x15, x11
+	mul	x14, x14, x15
+	sub	x10, x10, x14
+
+	ret
+	.cfi_endproc
+ENDPROC(__do_get_tspec)
diff --git a/arch/arm64/kernel/vdso/note.S b/arch/arm64/kernel/vdso/note.S
new file mode 100644
index 0000000..b82c85e
--- /dev/null
+++ b/arch/arm64/kernel/vdso/note.S
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2012 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Will Deacon <will.deacon@arm.com>
+ *
+ * This supplies .note.* sections to go into the PT_NOTE inside the vDSO text.
+ * Here we can supply some information useful to userland.
+ */
+
+#include <linux/uts.h>
+#include <linux/version.h>
+#include <linux/elfnote.h>
+
+ELFNOTE_START(Linux, 0, "a")
+	.long LINUX_VERSION_CODE
+ELFNOTE_END
diff --git a/arch/arm64/kernel/vdso/sigreturn.S b/arch/arm64/kernel/vdso/sigreturn.S
new file mode 100644
index 0000000..20d98ef
--- /dev/null
+++ b/arch/arm64/kernel/vdso/sigreturn.S
@@ -0,0 +1,37 @@
+/*
+ * Sigreturn trampoline for returning from a signal when the SA_RESTORER
+ * flag is not set.
+ *
+ * Copyright (C) 2012 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Will Deacon <will.deacon@arm.com>
+ */
+
+#include <linux/linkage.h>
+#include <asm/unistd.h>
+
+	.text
+
+	nop
+ENTRY(__kernel_rt_sigreturn)
+	.cfi_startproc
+	.cfi_signal_frame
+	.cfi_def_cfa	x29, 0
+	.cfi_offset	x29, 0 * 8
+	.cfi_offset	x30, 1 * 8
+	mov	x8, #__NR_rt_sigreturn
+	svc	#0
+	.cfi_endproc
+ENDPROC(__kernel_rt_sigreturn)
diff --git a/arch/arm64/kernel/vdso/vdso.S b/arch/arm64/kernel/vdso/vdso.S
new file mode 100644
index 0000000..60c1db5
--- /dev/null
+++ b/arch/arm64/kernel/vdso/vdso.S
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2012 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Will Deacon <will.deacon@arm.com>
+ */
+
+#include <linux/init.h>
+#include <linux/linkage.h>
+#include <linux/const.h>
+#include <asm/page.h>
+
+	__PAGE_ALIGNED_DATA
+
+	.globl vdso_start, vdso_end
+	.balign PAGE_SIZE
+vdso_start:
+	.incbin "arch/arm64/kernel/vdso/vdso.so"
+	.balign PAGE_SIZE
+vdso_end:
+
+	.previous
diff --git a/arch/arm64/kernel/vdso/vdso.lds.S b/arch/arm64/kernel/vdso/vdso.lds.S
new file mode 100644
index 0000000..8154b8d
--- /dev/null
+++ b/arch/arm64/kernel/vdso/vdso.lds.S
@@ -0,0 +1,100 @@
+/*
+ * GNU linker script for the VDSO library.
+*
+ * Copyright (C) 2012 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Will Deacon <will.deacon@arm.com>
+ * Heavily based on the vDSO linker scripts for other archs.
+ */
+
+#include <linux/const.h>
+#include <asm/page.h>
+#include <asm/vdso.h>
+
+OUTPUT_FORMAT("elf64-littleaarch64", "elf64-bigaarch64", "elf64-littleaarch64")
+OUTPUT_ARCH(aarch64)
+
+SECTIONS
+{
+	. = VDSO_LBASE + SIZEOF_HEADERS;
+
+	.hash		: { *(.hash) }			:text
+	.gnu.hash	: { *(.gnu.hash) }
+	.dynsym		: { *(.dynsym) }
+	.dynstr		: { *(.dynstr) }
+	.gnu.version	: { *(.gnu.version) }
+	.gnu.version_d	: { *(.gnu.version_d) }
+	.gnu.version_r	: { *(.gnu.version_r) }
+
+	.note		: { *(.note.*) }		:text	:note
+
+	. = ALIGN(16);
+
+	.text		: { *(.text*) }			:text	=0xd503201f
+	PROVIDE (__etext = .);
+	PROVIDE (_etext = .);
+	PROVIDE (etext = .);
+
+	.eh_frame_hdr	: { *(.eh_frame_hdr) }		:text	:eh_frame_hdr
+	.eh_frame	: { KEEP (*(.eh_frame)) }	:text
+
+	.dynamic	: { *(.dynamic) }		:text	:dynamic
+
+	.rodata		: { *(.rodata*) }		:text
+
+	_end = .;
+	PROVIDE(end = .);
+
+	. = ALIGN(PAGE_SIZE);
+	PROVIDE(_vdso_data = .);
+
+	/DISCARD/	: {
+		*(.note.GNU-stack)
+		*(.data .data.* .gnu.linkonce.d.* .sdata*)
+		*(.bss .sbss .dynbss .dynsbss)
+	}
+}
+
+/*
+ * We must supply the ELF program headers explicitly to get just one
+ * PT_LOAD segment, and set the flags explicitly to make segments read-only.
+ */
+PHDRS
+{
+	text		PT_LOAD		FLAGS(5) FILEHDR PHDRS; /* PF_R|PF_X */
+	dynamic		PT_DYNAMIC	FLAGS(4);		/* PF_R */
+	note		PT_NOTE		FLAGS(4);		/* PF_R */
+	eh_frame_hdr	PT_GNU_EH_FRAME;
+}
+
+/*
+ * This controls what symbols we export from the DSO.
+ */
+VERSION
+{
+	LINUX_2.6.39 {
+	global:
+		__kernel_rt_sigreturn;
+		__kernel_gettimeofday;
+		__kernel_clock_gettime;
+		__kernel_clock_getres;
+	local: *;
+	};
+}
+
+/*
+ * Make the sigreturn code visible to the kernel.
+ */
+VDSO_sigtramp		= __kernel_rt_sigreturn;
diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
new file mode 100644
index 0000000..3fae2be
--- /dev/null
+++ b/arch/arm64/kernel/vmlinux.lds.S
@@ -0,0 +1,126 @@
+/*
+ * ld script to make ARM Linux kernel
+ * taken from the i386 version by Russell King
+ * Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+ */
+
+#include <asm-generic/vmlinux.lds.h>
+#include <asm/thread_info.h>
+#include <asm/memory.h>
+#include <asm/page.h>
+
+#define ARM_EXIT_KEEP(x)
+#define ARM_EXIT_DISCARD(x)	x
+
+OUTPUT_ARCH(aarch64)
+ENTRY(stext)
+
+jiffies = jiffies_64;
+
+SECTIONS
+{
+	/*
+	 * XXX: The linker does not define how output sections are
+	 * assigned to input sections when there are multiple statements
+	 * matching the same input section name.  There is no documented
+	 * order of matching.
+	 */
+	/DISCARD/ : {
+		ARM_EXIT_DISCARD(EXIT_TEXT)
+		ARM_EXIT_DISCARD(EXIT_DATA)
+		EXIT_CALL
+		*(.discard)
+		*(.discard.*)
+	}
+
+	. = PAGE_OFFSET + TEXT_OFFSET;
+
+	.head.text : {
+		_text = .;
+		HEAD_TEXT
+	}
+	.text : {			/* Real text segment		*/
+		_stext = .;		/* Text and read-only data	*/
+			*(.smp.pen.text)
+			__exception_text_start = .;
+			*(.exception.text)
+			__exception_text_end = .;
+			IRQENTRY_TEXT
+			TEXT_TEXT
+			SCHED_TEXT
+			LOCK_TEXT
+			*(.fixup)
+			*(.gnu.warning)
+		. = ALIGN(16);
+		*(.got)			/* Global offset table		*/
+	}
+
+	RO_DATA(PAGE_SIZE)
+
+	_etext = .;			/* End of text and rodata section */
+
+	. = ALIGN(PAGE_SIZE);
+	__init_begin = .;
+
+	INIT_TEXT_SECTION(8)
+	.exit.text : {
+		ARM_EXIT_KEEP(EXIT_TEXT)
+	}
+	. = ALIGN(16);
+	.init.data : {
+		INIT_DATA
+		INIT_SETUP(16)
+		INIT_CALLS
+		CON_INITCALL
+		SECURITY_INITCALL
+		INIT_RAM_FS
+	}
+	.exit.data : {
+		ARM_EXIT_KEEP(EXIT_DATA)
+	}
+
+	PERCPU_SECTION(64)
+
+	__init_end = .;
+	. = ALIGN(THREAD_SIZE);
+	__data_loc = .;
+
+	.data : AT(__data_loc) {
+		_data = .;		/* address in memory */
+		_sdata = .;
+
+		/*
+		 * first, the init task union, aligned
+		 * to an 8192 byte boundary.
+		 */
+		INIT_TASK_DATA(THREAD_SIZE)
+		NOSAVE_DATA
+		CACHELINE_ALIGNED_DATA(64)
+		READ_MOSTLY_DATA(64)
+
+		/*
+		 * The exception fixup table (might need resorting at runtime)
+		 */
+		. = ALIGN(32);
+		__start___ex_table = .;
+		*(__ex_table)
+		__stop___ex_table = .;
+
+		/*
+		 * and the usual data section
+		 */
+		DATA_DATA
+		CONSTRUCTORS
+
+		_edata = .;
+	}
+	_edata_loc = __data_loc + SIZEOF(.data);
+
+	NOTES
+
+	BSS_SECTION(0, 0, 0)
+	_end = .;
+
+	STABS_DEBUG
+	.comment 0 : { *(.comment) }
+}
diff --git a/arch/arm64/lib/Makefile b/arch/arm64/lib/Makefile
new file mode 100644
index 0000000..2fb7f60
--- /dev/null
+++ b/arch/arm64/lib/Makefile
@@ -0,0 +1,4 @@
+lib-y		:= bitops.o delay.o					\
+		   strncpy_from_user.o strnlen_user.o clear_user.o	\
+		   copy_from_user.o copy_to_user.o copy_in_user.o	\
+		   copy_page.o clear_page.o
diff --git a/arch/arm64/lib/bitops.c b/arch/arm64/lib/bitops.c
new file mode 100644
index 0000000..aa4965e
--- /dev/null
+++ b/arch/arm64/lib/bitops.c
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2012 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/atomic.h>
+
+#ifdef CONFIG_SMP
+arch_spinlock_t __atomic_hash[ATOMIC_HASH_SIZE] __lock_aligned = {
+       [0 ... (ATOMIC_HASH_SIZE-1)]  = __ARCH_SPIN_LOCK_UNLOCKED
+};
+#endif
diff --git a/arch/arm64/lib/clear_page.S b/arch/arm64/lib/clear_page.S
new file mode 100644
index 0000000..ef08e90
--- /dev/null
+++ b/arch/arm64/lib/clear_page.S
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/linkage.h>
+#include <linux/const.h>
+#include <asm/assembler.h>
+#include <asm/page.h>
+
+/*
+ * Clear page @dest
+ *
+ * Parameters:
+ *	x0 - dest
+ */
+ENTRY(clear_page)
+	mrs	x1, dczid_el0
+	and	w1, w1, #0xf
+	mov	x2, #4
+	lsl	x1, x2, x1
+
+1:	dc	zva, x0
+	add	x0, x0, x1
+	tst	x0, #(PAGE_SIZE - 1)
+	b.ne	1b
+	ret
+ENDPROC(clear_page)
diff --git a/arch/arm64/lib/clear_user.S b/arch/arm64/lib/clear_user.S
new file mode 100644
index 0000000..6e0ed93
--- /dev/null
+++ b/arch/arm64/lib/clear_user.S
@@ -0,0 +1,58 @@
+/*
+ * Based on arch/arm/lib/clear_user.S
+ *
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+
+	.text
+
+/* Prototype: int __clear_user(void *addr, size_t sz)
+ * Purpose  : clear some user memory
+ * Params   : addr - user memory address to clear
+ *          : sz   - number of bytes to clear
+ * Returns  : number of bytes NOT cleared
+ *
+ * Alignment fixed up by hardware.
+ */
+ENTRY(__clear_user)
+	mov	x2, x1			// save the size for fixup return
+	subs	x1, x1, #8
+	b.mi	2f
+1:
+USER(9f, str	xzr, [x0], #8	)
+	subs	x1, x1, #8
+	b.pl	1b
+2:	adds	x1, x1, #4
+	b.mi	3f
+USER(9f, str	wzr, [x0], #4	)
+	sub	x1, x1, #4
+3:	adds	x1, x1, #2
+	b.mi	4f
+USER(9f, strh	wzr, [x0], #2	)
+	sub	x1, x1, #2
+4:	adds	x1, x1, #1
+	b.mi	5f
+	strb	wzr, [x0]
+5:	mov	x0, #0
+	ret
+ENDPROC(__clear_user)
+
+	.section .fixup,"ax"
+	.align	2
+9:	mov	x0, x2			// return the original size
+	ret
+	.previous
diff --git a/arch/arm64/lib/copy_from_user.S b/arch/arm64/lib/copy_from_user.S
new file mode 100644
index 0000000..5e27add
--- /dev/null
+++ b/arch/arm64/lib/copy_from_user.S
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+
+/*
+ * Copy from user space to a kernel buffer (alignment handled by the hardware)
+ *
+ * Parameters:
+ *	x0 - to
+ *	x1 - from
+ *	x2 - n
+ * Returns:
+ *	x0 - bytes not copied
+ */
+ENTRY(__copy_from_user)
+	add	x4, x1, x2			// upper user buffer boundary
+	subs	x2, x2, #8
+	b.mi	2f
+1:
+USER(9f, ldr	x3, [x1], #8	)
+	subs	x2, x2, #8
+	str	x3, [x0], #8
+	b.pl	1b
+2:	adds	x2, x2, #4
+	b.mi	3f
+USER(9f, ldr	w3, [x1], #4	)
+	sub	x2, x2, #4
+	str	w3, [x0], #4
+3:	adds	x2, x2, #2
+	b.mi	4f
+USER(9f, ldrh	w3, [x1], #2	)
+	sub	x2, x2, #2
+	strh	w3, [x0], #2
+4:	adds	x2, x2, #1
+	b.mi	5f
+USER(9f, ldrb	w3, [x1]	)
+	strb	w3, [x0]
+5:	mov	x0, #0
+	ret
+ENDPROC(__copy_from_user)
+
+	.section .fixup,"ax"
+	.align	2
+9:	sub	x2, x4, x1
+	mov	x3, x2
+10:	strb	wzr, [x0], #1			// zero remaining buffer space
+	subs	x3, x3, #1
+	b.ne	10b
+	mov	x0, x2				// bytes not copied
+	ret
+	.previous
diff --git a/arch/arm64/lib/copy_in_user.S b/arch/arm64/lib/copy_in_user.S
new file mode 100644
index 0000000..84b6c9b
--- /dev/null
+++ b/arch/arm64/lib/copy_in_user.S
@@ -0,0 +1,63 @@
+/*
+ * Copy from user space to user space
+ *
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+
+/*
+ * Copy from user space to user space (alignment handled by the hardware)
+ *
+ * Parameters:
+ *	x0 - to
+ *	x1 - from
+ *	x2 - n
+ * Returns:
+ *	x0 - bytes not copied
+ */
+ENTRY(__copy_in_user)
+	add	x4, x0, x2			// upper user buffer boundary
+	subs	x2, x2, #8
+	b.mi	2f
+1:
+USER(9f, ldr	x3, [x1], #8	)
+	subs	x2, x2, #8
+USER(9f, str	x3, [x0], #8	)
+	b.pl	1b
+2:	adds	x2, x2, #4
+	b.mi	3f
+USER(9f, ldr	w3, [x1], #4	)
+	sub	x2, x2, #4
+USER(9f, str	w3, [x0], #4	)
+3:	adds	x2, x2, #2
+	b.mi	4f
+USER(9f, ldrh	w3, [x1], #2	)
+	sub	x2, x2, #2
+USER(9f, strh	w3, [x0], #2	)
+4:	adds	x2, x2, #1
+	b.mi	5f
+USER(9f, ldrb	w3, [x1]	)
+USER(9f, strb	w3, [x0]	)
+5:	mov	x0, #0
+	ret
+ENDPROC(__copy_in_user)
+
+	.section .fixup,"ax"
+	.align	2
+9:	sub	x0, x4, x0			// bytes not copied
+	ret
+	.previous
diff --git a/arch/arm64/lib/copy_page.S b/arch/arm64/lib/copy_page.S
new file mode 100644
index 0000000..512b9a7
--- /dev/null
+++ b/arch/arm64/lib/copy_page.S
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/linkage.h>
+#include <linux/const.h>
+#include <asm/assembler.h>
+#include <asm/page.h>
+
+/*
+ * Copy a page from src to dest (both are page aligned)
+ *
+ * Parameters:
+ *	x0 - dest
+ *	x1 - src
+ */
+ENTRY(copy_page)
+	/* Assume cache line size is 64 bytes. */
+	prfm	pldl1strm, [x1, #64]
+1:	ldp	x2, x3, [x1]
+	ldp	x4, x5, [x1, #16]
+	ldp	x6, x7, [x1, #32]
+	ldp	x8, x9, [x1, #48]
+	add	x1, x1, #64
+	prfm	pldl1strm, [x1, #64]
+	stnp	x2, x3, [x0]
+	stnp	x4, x5, [x0, #16]
+	stnp	x6, x7, [x0, #32]
+	stnp	x8, x9, [x0, #48]
+	add	x0, x0, #64
+	tst	x1, #(PAGE_SIZE - 1)
+	b.ne	1b
+	ret
+ENDPROC(copy_page)
diff --git a/arch/arm64/lib/copy_to_user.S b/arch/arm64/lib/copy_to_user.S
new file mode 100644
index 0000000..a0aeeb9
--- /dev/null
+++ b/arch/arm64/lib/copy_to_user.S
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+
+/*
+ * Copy to user space from a kernel buffer (alignment handled by the hardware)
+ *
+ * Parameters:
+ *	x0 - to
+ *	x1 - from
+ *	x2 - n
+ * Returns:
+ *	x0 - bytes not copied
+ */
+ENTRY(__copy_to_user)
+	add	x4, x0, x2			// upper user buffer boundary
+	subs	x2, x2, #8
+	b.mi	2f
+1:
+	ldr	x3, [x1], #8
+	subs	x2, x2, #8
+USER(9f, str	x3, [x0], #8	)
+	b.pl	1b
+2:	adds	x2, x2, #4
+	b.mi	3f
+	ldr	w3, [x1], #4
+	sub	x2, x2, #4
+USER(9f, str	w3, [x0], #4	)
+3:	adds	x2, x2, #2
+	b.mi	4f
+	ldrh	w3, [x1], #2
+	sub	x2, x2, #2
+USER(9f, strh	w3, [x0], #2	)
+4:	adds	x2, x2, #1
+	b.mi	5f
+	ldrb	w3, [x1]
+USER(9f, strb	w3, [x0]	)
+5:	mov	x0, #0
+	ret
+ENDPROC(__copy_to_user)
+
+	.section .fixup,"ax"
+	.align	2
+9:	sub	x0, x4, x0			// bytes not copied
+	ret
+	.previous
diff --git a/arch/arm64/lib/delay.c b/arch/arm64/lib/delay.c
new file mode 100644
index 0000000..dad4ec9
--- /dev/null
+++ b/arch/arm64/lib/delay.c
@@ -0,0 +1,55 @@
+/*
+ * Delay loops based on the OpenRISC implementation.
+ *
+ * Copyright (C) 2012 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Will Deacon <will.deacon@arm.com>
+ */
+
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/timex.h>
+
+void __delay(unsigned long cycles)
+{
+	cycles_t start = get_cycles();
+
+	while ((get_cycles() - start) < cycles)
+		cpu_relax();
+}
+EXPORT_SYMBOL(__delay);
+
+inline void __const_udelay(unsigned long xloops)
+{
+	unsigned long loops;
+
+	loops = xloops * loops_per_jiffy * HZ;
+	__delay(loops >> 32);
+}
+EXPORT_SYMBOL(__const_udelay);
+
+void __udelay(unsigned long usecs)
+{
+	__const_udelay(usecs * 0x10C7UL); /* 2**32 / 1000000 (rounded up) */
+}
+EXPORT_SYMBOL(__udelay);
+
+void __ndelay(unsigned long nsecs)
+{
+	__const_udelay(nsecs * 0x5UL); /* 2**32 / 1000000000 (rounded up) */
+}
+EXPORT_SYMBOL(__ndelay);
diff --git a/arch/arm64/lib/strncpy_from_user.S b/arch/arm64/lib/strncpy_from_user.S
new file mode 100644
index 0000000..56e448a
--- /dev/null
+++ b/arch/arm64/lib/strncpy_from_user.S
@@ -0,0 +1,50 @@
+/*
+ * Based on arch/arm/lib/strncpy_from_user.S
+ *
+ * Copyright (C) 1995-2000 Russell King
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/errno.h>
+
+	.text
+	.align	5
+
+/*
+ * Copy a string from user space to kernel space.
+ *  x0 = dst, x1 = src, x2 = byte length
+ * returns the number of characters copied (strlen of copied string),
+ *  -EFAULT on exception, or "len" if we fill the whole buffer
+ */
+ENTRY(__strncpy_from_user)
+	mov	x4, x1
+1:	subs	x2, x2, #1
+	bmi	2f
+USER(9f, ldrb	w3, [x1], #1	)
+	strb	w3, [x0], #1
+	cbnz	w3, 1b
+	sub	x1, x1, #1	// take NUL character out of count
+2:	sub	x0, x1, x4
+	ret
+ENDPROC(__strncpy_from_user)
+
+	.section .fixup,"ax"
+	.align	0
+9:	strb	wzr, [x0]	// null terminate
+	mov	x0, #-EFAULT
+	ret
+	.previous
diff --git a/arch/arm64/lib/strnlen_user.S b/arch/arm64/lib/strnlen_user.S
new file mode 100644
index 0000000..7f7b176
--- /dev/null
+++ b/arch/arm64/lib/strnlen_user.S
@@ -0,0 +1,47 @@
+/*
+ * Based on arch/arm/lib/strnlen_user.S
+ *
+ * Copyright (C) 1995-2000 Russell King
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/errno.h>
+
+	.text
+	.align	5
+
+/* Prototype: unsigned long __strnlen_user(const char *str, long n)
+ * Purpose  : get length of a string in user memory
+ * Params   : str - address of string in user memory
+ * Returns  : length of string *including terminator*
+ *	      or zero on exception, or n if too long
+ */
+ENTRY(__strnlen_user)
+	mov	x2, x0
+1:	subs	x1, x1, #1
+	b.mi	2f
+USER(9f, ldrb	w3, [x0], #1	)
+	cbnz	w3, 1b
+2:	sub	x0, x0, x2
+	ret
+ENDPROC(__strnlen_user)
+
+	.section .fixup,"ax"
+	.align	0
+9:	mov	x0, #0
+	ret
+	.previous
diff --git a/arch/arm64/mm/Makefile b/arch/arm64/mm/Makefile
new file mode 100644
index 0000000..3140a2a
--- /dev/null
+++ b/arch/arm64/mm/Makefile
@@ -0,0 +1,4 @@
+obj-y				:= dma-mapping.o extable.o fault.o init.o \
+				   cache.o copypage.o flush.o \
+				   ioremap.o mmap.o pgd.o mmu.o \
+				   context.o tlb.o proc.o
diff --git a/arch/arm64/mm/cache.S b/arch/arm64/mm/cache.S
new file mode 100644
index 0000000..abe69b8
--- /dev/null
+++ b/arch/arm64/mm/cache.S
@@ -0,0 +1,168 @@
+/*
+ * Cache maintenance
+ *
+ * Copyright (C) 2001 Deep Blue Solutions Ltd.
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <asm/assembler.h>
+
+#include "proc-macros.S"
+
+/*
+ *	__flush_dcache_all()
+ *
+ *	Flush the whole D-cache.
+ *
+ *	Corrupted registers: x0-x7, x9-x11
+ */
+ENTRY(__flush_dcache_all)
+	dsb	sy				// ensure ordering with previous memory accesses
+	mrs	x0, clidr_el1			// read clidr
+	and	x3, x0, #0x7000000		// extract loc from clidr
+	lsr	x3, x3, #23			// left align loc bit field
+	cbz	x3, finished			// if loc is 0, then no need to clean
+	mov	x10, #0				// start clean at cache level 0
+loop1:
+	add	x2, x10, x10, lsr #1		// work out 3x current cache level
+	lsr	x1, x0, x2			// extract cache type bits from clidr
+	and	x1, x1, #7			// mask of the bits for current cache only
+	cmp	x1, #2				// see what cache we have at this level
+	b.lt	skip				// skip if no cache, or just i-cache
+	save_and_disable_irqs x9		// make CSSELR and CCSIDR access atomic
+	msr	csselr_el1, x10			// select current cache level in csselr
+	isb					// isb to sych the new cssr&csidr
+	mrs	x1, ccsidr_el1			// read the new ccsidr
+	restore_irqs x9
+	and	x2, x1, #7			// extract the length of the cache lines
+	add	x2, x2, #4			// add 4 (line length offset)
+	mov	x4, #0x3ff
+	and	x4, x4, x1, lsr #3		// find maximum number on the way size
+	clz	x5, x4				// find bit position of way size increment
+	mov	x7, #0x7fff
+	and	x7, x7, x1, lsr #13		// extract max number of the index size
+loop2:
+	mov	x9, x4				// create working copy of max way size
+loop3:
+	lsl	x6, x9, x5
+	orr	x11, x10, x6			// factor way and cache number into x11
+	lsl	x6, x7, x2
+	orr	x11, x11, x6			// factor index number into x11
+	dc	cisw, x11			// clean & invalidate by set/way
+	subs	x9, x9, #1			// decrement the way
+	b.ge	loop3
+	subs	x7, x7, #1			// decrement the index
+	b.ge	loop2
+skip:
+	add	x10, x10, #2			// increment cache number
+	cmp	x3, x10
+	b.gt	loop1
+finished:
+	mov	x10, #0				// swith back to cache level 0
+	msr	csselr_el1, x10			// select current cache level in csselr
+	dsb	sy
+	isb
+	ret
+ENDPROC(__flush_dcache_all)
+
+/*
+ *	flush_cache_all()
+ *
+ *	Flush the entire cache system.  The data cache flush is now achieved
+ *	using atomic clean / invalidates working outwards from L1 cache. This
+ *	is done using Set/Way based cache maintainance instructions.  The
+ *	instruction cache can still be invalidated back to the point of
+ *	unification in a single instruction.
+ */
+ENTRY(flush_cache_all)
+	mov	x12, lr
+	bl	__flush_dcache_all
+	mov	x0, #0
+	ic	ialluis				// I+BTB cache invalidate
+	ret	x12
+ENDPROC(flush_cache_all)
+
+/*
+ *	flush_icache_range(start,end)
+ *
+ *	Ensure that the I and D caches are coherent within specified region.
+ *	This is typically used when code has been written to a memory region,
+ *	and will be executed.
+ *
+ *	- start   - virtual start address of region
+ *	- end     - virtual end address of region
+ */
+ENTRY(flush_icache_range)
+	/* FALLTHROUGH */
+
+/*
+ *	__flush_cache_user_range(start,end)
+ *
+ *	Ensure that the I and D caches are coherent within specified region.
+ *	This is typically used when code has been written to a memory region,
+ *	and will be executed.
+ *
+ *	- start   - virtual start address of region
+ *	- end     - virtual end address of region
+ */
+ENTRY(__flush_cache_user_range)
+	dcache_line_size x2, x3
+	sub	x3, x2, #1
+	bic	x4, x0, x3
+1:
+USER(9f, dc	cvau, x4	)		// clean D line to PoU
+	add	x4, x4, x2
+	cmp	x4, x1
+	b.lo	1b
+	dsb	sy
+
+	icache_line_size x2, x3
+	sub	x3, x2, #1
+	bic	x4, x0, x3
+1:
+USER(9f, ic	ivau, x4	)		// invalidate I line PoU
+	add	x4, x4, x2
+	cmp	x4, x1
+	b.lo	1b
+9:						// ignore any faulting cache operation
+	dsb	sy
+	isb
+	ret
+ENDPROC(flush_icache_range)
+ENDPROC(__flush_cache_user_range)
+
+/*
+ *	__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
+ *	- size    - size in question
+ */
+ENTRY(__flush_dcache_area)
+	dcache_line_size x2, x3
+	add	x1, x0, x1
+	sub	x3, x2, #1
+	bic	x0, x0, x3
+1:	dc	civac, x0			// clean & invalidate D line / unified line
+	add	x0, x0, x2
+	cmp	x0, x1
+	b.lo	1b
+	dsb	sy
+	ret
+ENDPROC(__flush_dcache_area)
diff --git a/arch/arm64/mm/context.c b/arch/arm64/mm/context.c
new file mode 100644
index 0000000..baa758d
--- /dev/null
+++ b/arch/arm64/mm/context.c
@@ -0,0 +1,159 @@
+/*
+ * Based on arch/arm/mm/context.c
+ *
+ * Copyright (C) 2002-2003 Deep Blue Solutions Ltd, all rights reserved.
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/percpu.h>
+
+#include <asm/mmu_context.h>
+#include <asm/tlbflush.h>
+#include <asm/cachetype.h>
+
+#define asid_bits(reg) \
+	(((read_cpuid(ID_AA64MMFR0_EL1) & 0xf0) >> 2) + 8)
+
+#define ASID_FIRST_VERSION	(1 << MAX_ASID_BITS)
+
+static DEFINE_RAW_SPINLOCK(cpu_asid_lock);
+unsigned int cpu_last_asid = ASID_FIRST_VERSION;
+
+/*
+ * We fork()ed a process, and we need a new context for the child to run in.
+ */
+void __init_new_context(struct task_struct *tsk, struct mm_struct *mm)
+{
+	mm->context.id = 0;
+	raw_spin_lock_init(&mm->context.id_lock);
+}
+
+static void flush_context(void)
+{
+	/* set the reserved TTBR0 before flushing the TLB */
+	cpu_set_reserved_ttbr0();
+	flush_tlb_all();
+	if (icache_is_aivivt())
+		__flush_icache_all();
+}
+
+#ifdef CONFIG_SMP
+
+static void set_mm_context(struct mm_struct *mm, unsigned int asid)
+{
+	unsigned long flags;
+
+	/*
+	 * Locking needed for multi-threaded applications where the same
+	 * mm->context.id could be set from different CPUs during the
+	 * broadcast. This function is also called via IPI so the
+	 * mm->context.id_lock has to be IRQ-safe.
+	 */
+	raw_spin_lock_irqsave(&mm->context.id_lock, flags);
+	if (likely((mm->context.id ^ cpu_last_asid) >> MAX_ASID_BITS)) {
+		/*
+		 * Old version of ASID found. Set the new one and reset
+		 * mm_cpumask(mm).
+		 */
+		mm->context.id = asid;
+		cpumask_clear(mm_cpumask(mm));
+	}
+	raw_spin_unlock_irqrestore(&mm->context.id_lock, flags);
+
+	/*
+	 * Set the mm_cpumask(mm) bit for the current CPU.
+	 */
+	cpumask_set_cpu(smp_processor_id(), mm_cpumask(mm));
+}
+
+/*
+ * Reset the ASID on the current CPU. This function call is broadcast from the
+ * CPU handling the ASID rollover and holding cpu_asid_lock.
+ */
+static void reset_context(void *info)
+{
+	unsigned int asid;
+	unsigned int cpu = smp_processor_id();
+	struct mm_struct *mm = current->active_mm;
+
+	smp_rmb();
+	asid = cpu_last_asid + cpu;
+
+	flush_context();
+	set_mm_context(mm, asid);
+
+	/* set the new ASID */
+	cpu_switch_mm(mm->pgd, mm);
+}
+
+#else
+
+static inline void set_mm_context(struct mm_struct *mm, unsigned int asid)
+{
+	mm->context.id = asid;
+	cpumask_copy(mm_cpumask(mm), cpumask_of(smp_processor_id()));
+}
+
+#endif
+
+void __new_context(struct mm_struct *mm)
+{
+	unsigned int asid;
+	unsigned int bits = asid_bits();
+
+	raw_spin_lock(&cpu_asid_lock);
+#ifdef CONFIG_SMP
+	/*
+	 * Check the ASID again, in case the change was broadcast from another
+	 * CPU before we acquired the lock.
+	 */
+	if (!unlikely((mm->context.id ^ cpu_last_asid) >> MAX_ASID_BITS)) {
+		cpumask_set_cpu(smp_processor_id(), mm_cpumask(mm));
+		raw_spin_unlock(&cpu_asid_lock);
+		return;
+	}
+#endif
+	/*
+	 * At this point, it is guaranteed that the current mm (with an old
+	 * ASID) isn't active on any other CPU since the ASIDs are changed
+	 * simultaneously via IPI.
+	 */
+	asid = ++cpu_last_asid;
+
+	/*
+	 * If we've used up all our ASIDs, we need to start a new version and
+	 * flush the TLB.
+	 */
+	if (unlikely((asid & ((1 << bits) - 1)) == 0)) {
+		/* increment the ASID version */
+		cpu_last_asid += (1 << MAX_ASID_BITS) - (1 << bits);
+		if (cpu_last_asid == 0)
+			cpu_last_asid = ASID_FIRST_VERSION;
+		asid = cpu_last_asid + smp_processor_id();
+		flush_context();
+#ifdef CONFIG_SMP
+		smp_wmb();
+		smp_call_function(reset_context, NULL, 1);
+#endif
+		cpu_last_asid += NR_CPUS - 1;
+	}
+
+	set_mm_context(mm, asid);
+	raw_spin_unlock(&cpu_asid_lock);
+}
diff --git a/arch/arm64/mm/copypage.c b/arch/arm64/mm/copypage.c
new file mode 100644
index 0000000..9aecbac
--- /dev/null
+++ b/arch/arm64/mm/copypage.c
@@ -0,0 +1,34 @@
+/*
+ * Based on arch/arm/mm/copypage.c
+ *
+ * Copyright (C) 2002 Deep Blue Solutions Ltd, All Rights Reserved.
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/mm.h>
+
+#include <asm/page.h>
+#include <asm/cacheflush.h>
+
+void __cpu_copy_user_page(void *kto, const void *kfrom, unsigned long vaddr)
+{
+	copy_page(kto, kfrom);
+	__flush_dcache_area(kto, PAGE_SIZE);
+}
+
+void __cpu_clear_user_page(void *kaddr, unsigned long vaddr)
+{
+	clear_page(kaddr);
+}
diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
new file mode 100644
index 0000000..5eb2444
--- /dev/null
+++ b/arch/arm64/mm/dma-mapping.c
@@ -0,0 +1,79 @@
+/*
+ * SWIOTLB-based DMA API implementation
+ *
+ * Copyright (C) 2012 ARM Ltd.
+ * Author: Catalin Marinas <catalin.marinas@arm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/gfp.h>
+#include <linux/export.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <linux/vmalloc.h>
+#include <linux/swiotlb.h>
+
+#include <asm/cacheflush.h>
+
+struct dma_map_ops *dma_ops;
+EXPORT_SYMBOL(dma_ops);
+
+static void *arm64_swiotlb_alloc_coherent(struct device *dev, size_t size,
+					  dma_addr_t *dma_handle, gfp_t flags,
+					  struct dma_attrs *attrs)
+{
+	if (IS_ENABLED(CONFIG_ZONE_DMA32) &&
+	    dev->coherent_dma_mask <= DMA_BIT_MASK(32))
+		flags |= GFP_DMA32;
+	return swiotlb_alloc_coherent(dev, size, dma_handle, flags);
+}
+
+static void arm64_swiotlb_free_coherent(struct device *dev, size_t size,
+					void *vaddr, dma_addr_t dma_handle,
+					struct dma_attrs *attrs)
+{
+	swiotlb_free_coherent(dev, size, vaddr, dma_handle);
+}
+
+static struct dma_map_ops arm64_swiotlb_dma_ops = {
+	.alloc = arm64_swiotlb_alloc_coherent,
+	.free = arm64_swiotlb_free_coherent,
+	.map_page = swiotlb_map_page,
+	.unmap_page = swiotlb_unmap_page,
+	.map_sg = swiotlb_map_sg_attrs,
+	.unmap_sg = swiotlb_unmap_sg_attrs,
+	.sync_single_for_cpu = swiotlb_sync_single_for_cpu,
+	.sync_single_for_device = swiotlb_sync_single_for_device,
+	.sync_sg_for_cpu = swiotlb_sync_sg_for_cpu,
+	.sync_sg_for_device = swiotlb_sync_sg_for_device,
+	.dma_supported = swiotlb_dma_supported,
+	.mapping_error = swiotlb_dma_mapping_error,
+};
+
+void __init swiotlb_init_with_default_size(size_t default_size, int verbose);
+
+void __init arm64_swiotlb_init(size_t max_size)
+{
+	dma_ops = &arm64_swiotlb_dma_ops;
+	swiotlb_init_with_default_size(min((size_t)SZ_64M, max_size), 1);
+}
+
+#define PREALLOC_DMA_DEBUG_ENTRIES	4096
+
+static int __init dma_debug_do_init(void)
+{
+	dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES);
+	return 0;
+}
+fs_initcall(dma_debug_do_init);
diff --git a/arch/arm64/mm/extable.c b/arch/arm64/mm/extable.c
new file mode 100644
index 0000000..7944427
--- /dev/null
+++ b/arch/arm64/mm/extable.c
@@ -0,0 +1,17 @@
+/*
+ * Based on arch/arm/mm/extable.c
+ */
+
+#include <linux/module.h>
+#include <linux/uaccess.h>
+
+int fixup_exception(struct pt_regs *regs)
+{
+	const struct exception_table_entry *fixup;
+
+	fixup = search_exception_tables(instruction_pointer(regs));
+	if (fixup)
+		regs->pc = fixup->fixup;
+
+	return fixup != NULL;
+}
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
new file mode 100644
index 0000000..1909a69
--- /dev/null
+++ b/arch/arm64/mm/fault.c
@@ -0,0 +1,534 @@
+/*
+ * Based on arch/arm/mm/fault.c
+ *
+ * Copyright (C) 1995  Linus Torvalds
+ * Copyright (C) 1995-2004 Russell King
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/mm.h>
+#include <linux/hardirq.h>
+#include <linux/init.h>
+#include <linux/kprobes.h>
+#include <linux/uaccess.h>
+#include <linux/page-flags.h>
+#include <linux/sched.h>
+#include <linux/highmem.h>
+#include <linux/perf_event.h>
+
+#include <asm/exception.h>
+#include <asm/debug-monitors.h>
+#include <asm/system_misc.h>
+#include <asm/pgtable.h>
+#include <asm/tlbflush.h>
+
+/*
+ * Dump out the page tables associated with 'addr' in mm 'mm'.
+ */
+void show_pte(struct mm_struct *mm, unsigned long addr)
+{
+	pgd_t *pgd;
+
+	if (!mm)
+		mm = &init_mm;
+
+	pr_alert("pgd = %p\n", mm->pgd);
+	pgd = pgd_offset(mm, addr);
+	pr_alert("[%08lx] *pgd=%016llx", addr, pgd_val(*pgd));
+
+	do {
+		pud_t *pud;
+		pmd_t *pmd;
+		pte_t *pte;
+
+		if (pgd_none_or_clear_bad(pgd))
+			break;
+
+		pud = pud_offset(pgd, addr);
+		if (pud_none_or_clear_bad(pud))
+			break;
+
+		pmd = pmd_offset(pud, addr);
+		printk(", *pmd=%016llx", pmd_val(*pmd));
+		if (pmd_none_or_clear_bad(pmd))
+			break;
+
+		pte = pte_offset_map(pmd, addr);
+		printk(", *pte=%016llx", pte_val(*pte));
+		pte_unmap(pte);
+	} while(0);
+
+	printk("\n");
+}
+
+/*
+ * The kernel tried to access some page that wasn't present.
+ */
+static void __do_kernel_fault(struct mm_struct *mm, unsigned long addr,
+			      unsigned int esr, struct pt_regs *regs)
+{
+	/*
+	 * Are we prepared to handle this kernel fault?
+	 */
+	if (fixup_exception(regs))
+		return;
+
+	/*
+	 * No handler, we'll have to terminate things with extreme prejudice.
+	 */
+	bust_spinlocks(1);
+	pr_alert("Unable to handle kernel %s at virtual address %08lx\n",
+		 (addr < PAGE_SIZE) ? "NULL pointer dereference" :
+		 "paging request", addr);
+
+	show_pte(mm, addr);
+	die("Oops", regs, esr);
+	bust_spinlocks(0);
+	do_exit(SIGKILL);
+}
+
+/*
+ * Something tried to access memory that isn't in our memory map. User mode
+ * accesses just cause a SIGSEGV
+ */
+static void __do_user_fault(struct task_struct *tsk, unsigned long addr,
+			    unsigned int esr, unsigned int sig, int code,
+			    struct pt_regs *regs)
+{
+	struct siginfo si;
+
+	if (show_unhandled_signals) {
+		pr_info("%s[%d]: unhandled page fault (%d) at 0x%08lx, code 0x%03x\n",
+			tsk->comm, task_pid_nr(tsk), sig, addr, esr);
+		show_pte(tsk->mm, addr);
+		show_regs(regs);
+	}
+
+	tsk->thread.fault_address = addr;
+	si.si_signo = sig;
+	si.si_errno = 0;
+	si.si_code = code;
+	si.si_addr = (void __user *)addr;
+	force_sig_info(sig, &si, tsk);
+}
+
+void do_bad_area(unsigned long addr, unsigned int esr, struct pt_regs *regs)
+{
+	struct task_struct *tsk = current;
+	struct mm_struct *mm = tsk->active_mm;
+
+	/*
+	 * If we are in kernel mode at this point, we have no context to
+	 * handle this fault with.
+	 */
+	if (user_mode(regs))
+		__do_user_fault(tsk, addr, esr, SIGSEGV, SEGV_MAPERR, regs);
+	else
+		__do_kernel_fault(mm, addr, esr, regs);
+}
+
+#define VM_FAULT_BADMAP		0x010000
+#define VM_FAULT_BADACCESS	0x020000
+
+#define ESR_WRITE		(1 << 6)
+#define ESR_LNX_EXEC		(1 << 24)
+
+/*
+ * Check that the permissions on the VMA allow for the fault which occurred.
+ * If we encountered a write fault, we must have write permission, otherwise
+ * we allow any permission.
+ */
+static inline bool access_error(unsigned int esr, struct vm_area_struct *vma)
+{
+	unsigned int mask = VM_READ | VM_WRITE | VM_EXEC;
+
+	if (esr & ESR_WRITE)
+		mask = VM_WRITE;
+	if (esr & ESR_LNX_EXEC)
+		mask = VM_EXEC;
+
+	return vma->vm_flags & mask ? false : true;
+}
+
+static int __do_page_fault(struct mm_struct *mm, unsigned long addr,
+			   unsigned int esr, unsigned int flags,
+			   struct task_struct *tsk)
+{
+	struct vm_area_struct *vma;
+	int fault;
+
+	vma = find_vma(mm, addr);
+	fault = VM_FAULT_BADMAP;
+	if (unlikely(!vma))
+		goto out;
+	if (unlikely(vma->vm_start > addr))
+		goto check_stack;
+
+	/*
+	 * Ok, we have a good vm_area for this memory access, so we can handle
+	 * it.
+	 */
+good_area:
+	if (access_error(esr, vma)) {
+		fault = VM_FAULT_BADACCESS;
+		goto out;
+	}
+
+	return handle_mm_fault(mm, vma, addr & PAGE_MASK, flags);
+
+check_stack:
+	if (vma->vm_flags & VM_GROWSDOWN && !expand_stack(vma, addr))
+		goto good_area;
+out:
+	return fault;
+}
+
+static int __kprobes do_page_fault(unsigned long addr, unsigned int esr,
+				   struct pt_regs *regs)
+{
+	struct task_struct *tsk;
+	struct mm_struct *mm;
+	int fault, sig, code;
+	int write = esr & ESR_WRITE;
+	unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE |
+		(write ? FAULT_FLAG_WRITE : 0);
+
+	tsk = current;
+	mm  = tsk->mm;
+
+	/* Enable interrupts if they were enabled in the parent context. */
+	if (interrupts_enabled(regs))
+		local_irq_enable();
+
+	/*
+	 * If we're in an interrupt or have no user context, we must not take
+	 * the fault.
+	 */
+	if (in_atomic() || !mm)
+		goto no_context;
+
+	/*
+	 * As per x86, we may deadlock here. However, since the kernel only
+	 * validly references user space from well defined areas of the code,
+	 * we can bug out early if this is from code which shouldn't.
+	 */
+	if (!down_read_trylock(&mm->mmap_sem)) {
+		if (!user_mode(regs) && !search_exception_tables(regs->pc))
+			goto no_context;
+retry:
+		down_read(&mm->mmap_sem);
+	} else {
+		/*
+		 * The above down_read_trylock() might have succeeded in which
+		 * case, we'll have missed the might_sleep() from down_read().
+		 */
+		might_sleep();
+#ifdef CONFIG_DEBUG_VM
+		if (!user_mode(regs) && !search_exception_tables(regs->pc))
+			goto no_context;
+#endif
+	}
+
+	fault = __do_page_fault(mm, addr, esr, flags, tsk);
+
+	/*
+	 * If we need to retry but a fatal signal is pending, handle the
+	 * signal first. We do not need to release the mmap_sem because it
+	 * would already be released in __lock_page_or_retry in mm/filemap.c.
+	 */
+	if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current))
+		return 0;
+
+	/*
+	 * Major/minor page fault accounting is only done on the initial
+	 * attempt. If we go through a retry, it is extremely likely that the
+	 * page will be found in page cache at that point.
+	 */
+
+	perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, addr);
+	if (flags & FAULT_FLAG_ALLOW_RETRY) {
+		if (fault & VM_FAULT_MAJOR) {
+			tsk->maj_flt++;
+			perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, regs,
+				      addr);
+		} else {
+			tsk->min_flt++;
+			perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, regs,
+				      addr);
+		}
+		if (fault & VM_FAULT_RETRY) {
+			/*
+			 * Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk of
+			 * starvation.
+			 */
+			flags &= ~FAULT_FLAG_ALLOW_RETRY;
+			goto retry;
+		}
+	}
+
+	up_read(&mm->mmap_sem);
+
+	/*
+	 * Handle the "normal" case first - VM_FAULT_MAJOR / VM_FAULT_MINOR
+	 */
+	if (likely(!(fault & (VM_FAULT_ERROR | VM_FAULT_BADMAP |
+			      VM_FAULT_BADACCESS))))
+		return 0;
+
+	if (fault & VM_FAULT_OOM) {
+		/*
+		 * We ran out of memory, call the OOM killer, and return to
+		 * userspace (which will retry the fault, or kill us if we got
+		 * oom-killed).
+		 */
+		pagefault_out_of_memory();
+		return 0;
+	}
+
+	/*
+	 * If we are in kernel mode at this point, we have no context to
+	 * handle this fault with.
+	 */
+	if (!user_mode(regs))
+		goto no_context;
+
+	if (fault & VM_FAULT_SIGBUS) {
+		/*
+		 * We had some memory, but were unable to successfully fix up
+		 * this page fault.
+		 */
+		sig = SIGBUS;
+		code = BUS_ADRERR;
+	} else {
+		/*
+		 * Something tried to access memory that isn't in our memory
+		 * map.
+		 */
+		sig = SIGSEGV;
+		code = fault == VM_FAULT_BADACCESS ?
+			SEGV_ACCERR : SEGV_MAPERR;
+	}
+
+	__do_user_fault(tsk, addr, esr, sig, code, regs);
+	return 0;
+
+no_context:
+	__do_kernel_fault(mm, addr, esr, regs);
+	return 0;
+}
+
+/*
+ * First Level Translation Fault Handler
+ *
+ * We enter here because the first level page table doesn't contain a valid
+ * entry for the address.
+ *
+ * If the address is in kernel space (>= TASK_SIZE), then we are probably
+ * faulting in the vmalloc() area.
+ *
+ * If the init_task's first level page tables contains the relevant entry, we
+ * copy the it to this task.  If not, we send the process a signal, fixup the
+ * exception, or oops the kernel.
+ *
+ * NOTE! We MUST NOT take any locks for this case. We may be in an interrupt
+ * or a critical region, and should only copy the information from the master
+ * page table, nothing more.
+ */
+static int __kprobes do_translation_fault(unsigned long addr,
+					  unsigned int esr,
+					  struct pt_regs *regs)
+{
+	if (addr < TASK_SIZE)
+		return do_page_fault(addr, esr, regs);
+
+	do_bad_area(addr, esr, regs);
+	return 0;
+}
+
+/*
+ * Some section permission faults need to be handled gracefully.  They can
+ * happen due to a __{get,put}_user during an oops.
+ */
+static int do_sect_fault(unsigned long addr, unsigned int esr,
+			 struct pt_regs *regs)
+{
+	do_bad_area(addr, esr, regs);
+	return 0;
+}
+
+/*
+ * This abort handler always returns "fault".
+ */
+static int do_bad(unsigned long addr, unsigned int esr, struct pt_regs *regs)
+{
+	return 1;
+}
+
+static struct fault_info {
+	int	(*fn)(unsigned long addr, unsigned int esr, struct pt_regs *regs);
+	int	sig;
+	int	code;
+	const char *name;
+} fault_info[] = {
+	{ do_bad,		SIGBUS,  0,		"ttbr address size fault"	},
+	{ do_bad,		SIGBUS,  0,		"level 1 address size fault"	},
+	{ do_bad,		SIGBUS,  0,		"level 2 address size fault"	},
+	{ do_bad,		SIGBUS,  0,		"level 3 address size fault"	},
+	{ do_translation_fault,	SIGSEGV, SEGV_MAPERR,	"input address range fault"	},
+	{ do_translation_fault,	SIGSEGV, SEGV_MAPERR,	"level 1 translation fault"	},
+	{ do_translation_fault,	SIGSEGV, SEGV_MAPERR,	"level 2 translation fault"	},
+	{ do_page_fault,	SIGSEGV, SEGV_MAPERR,	"level 3 translation fault"	},
+	{ do_bad,		SIGBUS,  0,		"reserved access flag fault"	},
+	{ do_bad,		SIGSEGV, SEGV_ACCERR,	"level 1 access flag fault"	},
+	{ do_bad,		SIGSEGV, SEGV_ACCERR,	"level 2 access flag fault"	},
+	{ do_page_fault,	SIGSEGV, SEGV_ACCERR,	"level 3 access flag fault"	},
+	{ do_bad,		SIGBUS,  0,		"reserved permission fault"	},
+	{ do_bad,		SIGSEGV, SEGV_ACCERR,	"level 1 permission fault"	},
+	{ do_sect_fault,	SIGSEGV, SEGV_ACCERR,	"level 2 permission fault"	},
+	{ do_page_fault,	SIGSEGV, SEGV_ACCERR,	"level 3 permission fault"	},
+	{ do_bad,		SIGBUS,  0,		"synchronous external abort"	},
+	{ do_bad,		SIGBUS,  0,		"asynchronous external abort"	},
+	{ do_bad,		SIGBUS,  0,		"unknown 18"			},
+	{ do_bad,		SIGBUS,  0,		"unknown 19"			},
+	{ do_bad,		SIGBUS,  0,		"synchronous abort (translation table walk)" },
+	{ do_bad,		SIGBUS,  0,		"synchronous abort (translation table walk)" },
+	{ do_bad,		SIGBUS,  0,		"synchronous abort (translation table walk)" },
+	{ do_bad,		SIGBUS,  0,		"synchronous abort (translation table walk)" },
+	{ do_bad,		SIGBUS,  0,		"synchronous parity error"	},
+	{ do_bad,		SIGBUS,  0,		"asynchronous parity error"	},
+	{ do_bad,		SIGBUS,  0,		"unknown 26"			},
+	{ do_bad,		SIGBUS,  0,		"unknown 27"			},
+	{ do_bad,		SIGBUS,  0,		"synchronous parity error (translation table walk" },
+	{ do_bad,		SIGBUS,  0,		"synchronous parity error (translation table walk" },
+	{ do_bad,		SIGBUS,  0,		"synchronous parity error (translation table walk" },
+	{ do_bad,		SIGBUS,  0,		"synchronous parity error (translation table walk" },
+	{ do_bad,		SIGBUS,  0,		"unknown 32"			},
+	{ do_bad,		SIGBUS,  BUS_ADRALN,	"alignment fault"		},
+	{ do_bad,		SIGBUS,  0,		"debug event"			},
+	{ do_bad,		SIGBUS,  0,		"unknown 35"			},
+	{ do_bad,		SIGBUS,  0,		"unknown 36"			},
+	{ do_bad,		SIGBUS,  0,		"unknown 37"			},
+	{ do_bad,		SIGBUS,  0,		"unknown 38"			},
+	{ do_bad,		SIGBUS,  0,		"unknown 39"			},
+	{ do_bad,		SIGBUS,  0,		"unknown 40"			},
+	{ do_bad,		SIGBUS,  0,		"unknown 41"			},
+	{ do_bad,		SIGBUS,  0,		"unknown 42"			},
+	{ do_bad,		SIGBUS,  0,		"unknown 43"			},
+	{ do_bad,		SIGBUS,  0,		"unknown 44"			},
+	{ do_bad,		SIGBUS,  0,		"unknown 45"			},
+	{ do_bad,		SIGBUS,  0,		"unknown 46"			},
+	{ do_bad,		SIGBUS,  0,		"unknown 47"			},
+	{ do_bad,		SIGBUS,  0,		"unknown 48"			},
+	{ do_bad,		SIGBUS,  0,		"unknown 49"			},
+	{ do_bad,		SIGBUS,  0,		"unknown 50"			},
+	{ do_bad,		SIGBUS,  0,		"unknown 51"			},
+	{ do_bad,		SIGBUS,  0,		"implementation fault (lockdown abort)" },
+	{ do_bad,		SIGBUS,  0,		"unknown 53"			},
+	{ do_bad,		SIGBUS,  0,		"unknown 54"			},
+	{ do_bad,		SIGBUS,  0,		"unknown 55"			},
+	{ do_bad,		SIGBUS,  0,		"unknown 56"			},
+	{ do_bad,		SIGBUS,  0,		"unknown 57"			},
+	{ do_bad,		SIGBUS,  0,		"implementation fault (coprocessor abort)" },
+	{ do_bad,		SIGBUS,  0,		"unknown 59"			},
+	{ do_bad,		SIGBUS,  0,		"unknown 60"			},
+	{ do_bad,		SIGBUS,  0,		"unknown 61"			},
+	{ do_bad,		SIGBUS,  0,		"unknown 62"			},
+	{ do_bad,		SIGBUS,  0,		"unknown 63"			},
+};
+
+/*
+ * Dispatch a data abort to the relevant handler.
+ */
+asmlinkage void __exception do_mem_abort(unsigned long addr, unsigned int esr,
+					 struct pt_regs *regs)
+{
+	const struct fault_info *inf = fault_info + (esr & 63);
+	struct siginfo info;
+
+	if (!inf->fn(addr, esr, regs))
+		return;
+
+	pr_alert("Unhandled fault: %s (0x%08x) at 0x%016lx\n",
+		 inf->name, esr, addr);
+
+	info.si_signo = inf->sig;
+	info.si_errno = 0;
+	info.si_code  = inf->code;
+	info.si_addr  = (void __user *)addr;
+	arm64_notify_die("", regs, &info, esr);
+}
+
+/*
+ * Handle stack alignment exceptions.
+ */
+asmlinkage void __exception do_sp_pc_abort(unsigned long addr,
+					   unsigned int esr,
+					   struct pt_regs *regs)
+{
+	struct siginfo info;
+
+	info.si_signo = SIGBUS;
+	info.si_errno = 0;
+	info.si_code  = BUS_ADRALN;
+	info.si_addr  = (void __user *)addr;
+	arm64_notify_die("", regs, &info, esr);
+}
+
+static struct fault_info debug_fault_info[] = {
+	{ do_bad,	SIGTRAP,	TRAP_HWBKPT,	"hardware breakpoint"	},
+	{ do_bad,	SIGTRAP,	TRAP_HWBKPT,	"hardware single-step"	},
+	{ do_bad,	SIGTRAP,	TRAP_HWBKPT,	"hardware watchpoint"	},
+	{ do_bad,	SIGBUS,		0,		"unknown 3"		},
+	{ do_bad,	SIGTRAP,	TRAP_BRKPT,	"aarch32 BKPT"		},
+	{ do_bad,	SIGTRAP,	0,		"aarch32 vector catch"	},
+	{ do_bad,	SIGTRAP,	TRAP_BRKPT,	"aarch64 BRK"		},
+	{ do_bad,	SIGBUS,		0,		"unknown 7"		},
+};
+
+void __init hook_debug_fault_code(int nr,
+				  int (*fn)(unsigned long, unsigned int, struct pt_regs *),
+				  int sig, int code, const char *name)
+{
+	BUG_ON(nr < 0 || nr >= ARRAY_SIZE(debug_fault_info));
+
+	debug_fault_info[nr].fn		= fn;
+	debug_fault_info[nr].sig	= sig;
+	debug_fault_info[nr].code	= code;
+	debug_fault_info[nr].name	= name;
+}
+
+asmlinkage int __exception do_debug_exception(unsigned long addr,
+					      unsigned int esr,
+					      struct pt_regs *regs)
+{
+	const struct fault_info *inf = debug_fault_info + DBG_ESR_EVT(esr);
+	struct siginfo info;
+
+	if (!inf->fn(addr, esr, regs))
+		return 1;
+
+	pr_alert("Unhandled debug exception: %s (0x%08x) at 0x%016lx\n",
+		 inf->name, esr, addr);
+
+	info.si_signo = inf->sig;
+	info.si_errno = 0;
+	info.si_code  = inf->code;
+	info.si_addr  = (void __user *)addr;
+	arm64_notify_die("", regs, &info, esr);
+
+	return 0;
+}
diff --git a/arch/arm64/mm/flush.c b/arch/arm64/mm/flush.c
new file mode 100644
index 0000000..c144adb
--- /dev/null
+++ b/arch/arm64/mm/flush.c
@@ -0,0 +1,135 @@
+/*
+ * Based on arch/arm/mm/flush.c
+ *
+ * Copyright (C) 1995-2002 Russell King
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/export.h>
+#include <linux/mm.h>
+#include <linux/pagemap.h>
+
+#include <asm/cacheflush.h>
+#include <asm/cachetype.h>
+#include <asm/tlbflush.h>
+
+#include "mm.h"
+
+void flush_cache_mm(struct mm_struct *mm)
+{
+}
+
+void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
+		       unsigned long end)
+{
+	if (vma->vm_flags & VM_EXEC)
+		__flush_icache_all();
+}
+
+void flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr,
+		      unsigned long pfn)
+{
+}
+
+static void flush_ptrace_access(struct vm_area_struct *vma, struct page *page,
+				unsigned long uaddr, void *kaddr,
+				unsigned long len)
+{
+	if (vma->vm_flags & VM_EXEC) {
+		unsigned long addr = (unsigned long)kaddr;
+		if (icache_is_aliasing()) {
+			__flush_dcache_area(kaddr, len);
+			__flush_icache_all();
+		} else {
+			flush_icache_range(addr, addr + len);
+		}
+	}
+}
+
+/*
+ * Copy user data from/to a page which is mapped into a different processes
+ * address space.  Really, we want to allow our "user space" model to handle
+ * this.
+ *
+ * Note that this code needs to run on the current CPU.
+ */
+void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
+		       unsigned long uaddr, void *dst, const void *src,
+		       unsigned long len)
+{
+#ifdef CONFIG_SMP
+	preempt_disable();
+#endif
+	memcpy(dst, src, len);
+	flush_ptrace_access(vma, page, uaddr, dst, len);
+#ifdef CONFIG_SMP
+	preempt_enable();
+#endif
+}
+
+void __flush_dcache_page(struct page *page)
+{
+	__flush_dcache_area(page_address(page), PAGE_SIZE);
+}
+
+void __sync_icache_dcache(pte_t pte, unsigned long addr)
+{
+	unsigned long pfn;
+	struct page *page;
+
+	pfn = pte_pfn(pte);
+	if (!pfn_valid(pfn))
+		return;
+
+	page = pfn_to_page(pfn);
+	if (!test_and_set_bit(PG_dcache_clean, &page->flags)) {
+		__flush_dcache_page(page);
+		__flush_icache_all();
+	} else if (icache_is_aivivt()) {
+		__flush_icache_all();
+	}
+}
+
+/*
+ * Ensure cache coherency between kernel mapping and userspace mapping of this
+ * page.
+ */
+void flush_dcache_page(struct page *page)
+{
+	struct address_space *mapping;
+
+	/*
+	 * The zero page is never written to, so never has any dirty cache
+	 * lines, and therefore never needs to be flushed.
+	 */
+	if (page == ZERO_PAGE(0))
+		return;
+
+	mapping = page_mapping(page);
+	if (mapping && mapping_mapped(mapping)) {
+		__flush_dcache_page(page);
+		__flush_icache_all();
+		set_bit(PG_dcache_clean, &page->flags);
+	} else {
+		clear_bit(PG_dcache_clean, &page->flags);
+	}
+}
+EXPORT_SYMBOL(flush_dcache_page);
+
+/*
+ * Additional functions defined in assembly.
+ */
+EXPORT_SYMBOL(flush_cache_all);
+EXPORT_SYMBOL(flush_icache_range);
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
new file mode 100644
index 0000000..5f719ba
--- /dev/null
+++ b/arch/arm64/mm/init.c
@@ -0,0 +1,437 @@
+/*
+ * Based on arch/arm/mm/init.c
+ *
+ * Copyright (C) 1995-2005 Russell King
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/export.h>
+#include <linux/errno.h>
+#include <linux/swap.h>
+#include <linux/init.h>
+#include <linux/bootmem.h>
+#include <linux/mman.h>
+#include <linux/nodemask.h>
+#include <linux/initrd.h>
+#include <linux/gfp.h>
+#include <linux/memblock.h>
+#include <linux/sort.h>
+#include <linux/of_fdt.h>
+
+#include <asm/prom.h>
+#include <asm/sections.h>
+#include <asm/setup.h>
+#include <asm/sizes.h>
+#include <asm/tlb.h>
+
+#include "mm.h"
+
+static unsigned long phys_initrd_start __initdata = 0;
+static unsigned long phys_initrd_size __initdata = 0;
+
+phys_addr_t memstart_addr __read_mostly = 0;
+
+void __init early_init_dt_setup_initrd_arch(unsigned long start,
+					    unsigned long end)
+{
+	phys_initrd_start = start;
+	phys_initrd_size = end - start;
+}
+
+static int __init early_initrd(char *p)
+{
+	unsigned long start, size;
+	char *endp;
+
+	start = memparse(p, &endp);
+	if (*endp == ',') {
+		size = memparse(endp + 1, NULL);
+
+		phys_initrd_start = start;
+		phys_initrd_size = size;
+	}
+	return 0;
+}
+early_param("initrd", early_initrd);
+
+#define MAX_DMA32_PFN ((4UL * 1024 * 1024 * 1024) >> PAGE_SHIFT)
+
+static void __init zone_sizes_init(unsigned long min, unsigned long max)
+{
+	struct memblock_region *reg;
+	unsigned long zone_size[MAX_NR_ZONES], zhole_size[MAX_NR_ZONES];
+	unsigned long max_dma32 = min;
+
+	memset(zone_size, 0, sizeof(zone_size));
+
+#ifdef CONFIG_ZONE_DMA32
+	/* 4GB maximum for 32-bit only capable devices */
+	max_dma32 = min(max, MAX_DMA32_PFN);
+	zone_size[ZONE_DMA32] = max_dma32 - min;
+#endif
+	zone_size[ZONE_NORMAL] = max - max_dma32;
+
+	memcpy(zhole_size, zone_size, sizeof(zhole_size));
+
+	for_each_memblock(memory, reg) {
+		unsigned long start = memblock_region_memory_base_pfn(reg);
+		unsigned long end = memblock_region_memory_end_pfn(reg);
+
+		if (start >= max)
+			continue;
+#ifdef CONFIG_ZONE_DMA32
+		if (start < max_dma32) {
+			unsigned long dma_end = min(end, max_dma32);
+			zhole_size[ZONE_DMA32] -= dma_end - start;
+		}
+#endif
+		if (end > max_dma32) {
+			unsigned long normal_end = min(end, max);
+			unsigned long normal_start = max(start, max_dma32);
+			zhole_size[ZONE_NORMAL] -= normal_end - normal_start;
+		}
+	}
+
+	free_area_init_node(0, zone_size, min, zhole_size);
+}
+
+#ifdef CONFIG_HAVE_ARCH_PFN_VALID
+int pfn_valid(unsigned long pfn)
+{
+	return memblock_is_memory(pfn << PAGE_SHIFT);
+}
+EXPORT_SYMBOL(pfn_valid);
+#endif
+
+#ifndef CONFIG_SPARSEMEM
+static void arm64_memory_present(void)
+{
+}
+#else
+static void arm64_memory_present(void)
+{
+	struct memblock_region *reg;
+
+	for_each_memblock(memory, reg)
+		memory_present(0, memblock_region_memory_base_pfn(reg),
+			       memblock_region_memory_end_pfn(reg));
+}
+#endif
+
+void __init arm64_memblock_init(void)
+{
+	u64 *reserve_map, base, size;
+
+	/* Register the kernel text, kernel data and initrd with memblock */
+	memblock_reserve(__pa(_text), _end - _text);
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (phys_initrd_size) {
+		memblock_reserve(phys_initrd_start, phys_initrd_size);
+
+		/* Now convert initrd to virtual addresses */
+		initrd_start = __phys_to_virt(phys_initrd_start);
+		initrd_end = initrd_start + phys_initrd_size;
+	}
+#endif
+
+	/*
+	 * Reserve the page tables.  These are already in use,
+	 * and can only be in node 0.
+	 */
+	memblock_reserve(__pa(swapper_pg_dir), SWAPPER_DIR_SIZE);
+	memblock_reserve(__pa(idmap_pg_dir), IDMAP_DIR_SIZE);
+
+	/* Reserve the dtb region */
+	memblock_reserve(virt_to_phys(initial_boot_params),
+			 be32_to_cpu(initial_boot_params->totalsize));
+
+	/*
+	 * Process the reserve map.  This will probably overlap the initrd
+	 * and dtb locations which are already reserved, but overlapping
+	 * doesn't hurt anything
+	 */
+	reserve_map = ((void*)initial_boot_params) +
+			be32_to_cpu(initial_boot_params->off_mem_rsvmap);
+	while (1) {
+		base = be64_to_cpup(reserve_map++);
+		size = be64_to_cpup(reserve_map++);
+		if (!size)
+			break;
+		memblock_reserve(base, size);
+	}
+
+	memblock_allow_resize();
+	memblock_dump_all();
+}
+
+void __init bootmem_init(void)
+{
+	unsigned long min, max;
+
+	min = PFN_UP(memblock_start_of_DRAM());
+	max = PFN_DOWN(memblock_end_of_DRAM());
+
+	/*
+	 * Sparsemem tries to allocate bootmem in memory_present(), so must be
+	 * done after the fixed reservations.
+	 */
+	arm64_memory_present();
+
+	sparse_init();
+	zone_sizes_init(min, max);
+
+	high_memory = __va((max << PAGE_SHIFT) - 1) + 1;
+	max_pfn = max_low_pfn = max;
+}
+
+static inline int free_area(unsigned long pfn, unsigned long end, char *s)
+{
+	unsigned int pages = 0, size = (end - pfn) << (PAGE_SHIFT - 10);
+
+	for (; pfn < end; pfn++) {
+		struct page *page = pfn_to_page(pfn);
+		ClearPageReserved(page);
+		init_page_count(page);
+		__free_page(page);
+		pages++;
+	}
+
+	if (size && s)
+		pr_info("Freeing %s memory: %dK\n", s, size);
+
+	return pages;
+}
+
+/*
+ * Poison init memory with an undefined instruction (0x0).
+ */
+static inline void poison_init_mem(void *s, size_t count)
+{
+	memset(s, 0, count);
+}
+
+#ifndef CONFIG_SPARSEMEM_VMEMMAP
+static inline void free_memmap(unsigned long start_pfn, unsigned long end_pfn)
+{
+	struct page *start_pg, *end_pg;
+	unsigned long pg, pgend;
+
+	/*
+	 * Convert start_pfn/end_pfn to a struct page pointer.
+	 */
+	start_pg = pfn_to_page(start_pfn - 1) + 1;
+	end_pg = pfn_to_page(end_pfn - 1) + 1;
+
+	/*
+	 * Convert to physical addresses, and round start upwards and end
+	 * downwards.
+	 */
+	pg = (unsigned long)PAGE_ALIGN(__pa(start_pg));
+	pgend = (unsigned long)__pa(end_pg) & PAGE_MASK;
+
+	/*
+	 * If there are free pages between these, free the section of the
+	 * memmap array.
+	 */
+	if (pg < pgend)
+		free_bootmem(pg, pgend - pg);
+}
+
+/*
+ * The mem_map array can get very big. Free the unused area of the memory map.
+ */
+static void __init free_unused_memmap(void)
+{
+	unsigned long start, prev_end = 0;
+	struct memblock_region *reg;
+
+	for_each_memblock(memory, reg) {
+		start = __phys_to_pfn(reg->base);
+
+#ifdef CONFIG_SPARSEMEM
+		/*
+		 * Take care not to free memmap entries that don't exist due
+		 * to SPARSEMEM sections which aren't present.
+		 */
+		start = min(start, ALIGN(prev_end, PAGES_PER_SECTION));
+#endif
+		/*
+		 * If we had a previous bank, and there is a space between the
+		 * current bank and the previous, free it.
+		 */
+		if (prev_end && prev_end < start)
+			free_memmap(prev_end, start);
+
+		/*
+		 * Align up here since the VM subsystem insists that the
+		 * memmap entries are valid from the bank end aligned to
+		 * MAX_ORDER_NR_PAGES.
+		 */
+		prev_end = ALIGN(start + __phys_to_pfn(reg->size),
+				 MAX_ORDER_NR_PAGES);
+	}
+
+#ifdef CONFIG_SPARSEMEM
+	if (!IS_ALIGNED(prev_end, PAGES_PER_SECTION))
+		free_memmap(prev_end, ALIGN(prev_end, PAGES_PER_SECTION));
+#endif
+}
+#endif	/* !CONFIG_SPARSEMEM_VMEMMAP */
+
+/*
+ * mem_init() marks the free areas in the mem_map and tells us how much memory
+ * is free.  This is done after various parts of the system have claimed their
+ * memory after the kernel image.
+ */
+void __init mem_init(void)
+{
+	unsigned long reserved_pages, free_pages;
+	struct memblock_region *reg;
+
+#if CONFIG_SWIOTLB
+	extern void __init arm64_swiotlb_init(size_t max_size);
+	arm64_swiotlb_init(max_pfn << (PAGE_SHIFT - 1));
+#endif
+
+	max_mapnr   = pfn_to_page(max_pfn + PHYS_PFN_OFFSET) - mem_map;
+
+#ifndef CONFIG_SPARSEMEM_VMEMMAP
+	/* this will put all unused low memory onto the freelists */
+	free_unused_memmap();
+#endif
+
+	totalram_pages += free_all_bootmem();
+
+	reserved_pages = free_pages = 0;
+
+	for_each_memblock(memory, reg) {
+		unsigned int pfn1, pfn2;
+		struct page *page, *end;
+
+		pfn1 = __phys_to_pfn(reg->base);
+		pfn2 = pfn1 + __phys_to_pfn(reg->size);
+
+		page = pfn_to_page(pfn1);
+		end  = pfn_to_page(pfn2 - 1) + 1;
+
+		do {
+			if (PageReserved(page))
+				reserved_pages++;
+			else if (!page_count(page))
+				free_pages++;
+			page++;
+		} while (page < end);
+	}
+
+	/*
+	 * Since our memory may not be contiguous, calculate the real number
+	 * of pages we have in this system.
+	 */
+	pr_info("Memory:");
+	num_physpages = 0;
+	for_each_memblock(memory, reg) {
+		unsigned long pages = memblock_region_memory_end_pfn(reg) -
+			memblock_region_memory_base_pfn(reg);
+		num_physpages += pages;
+		printk(" %ldMB", pages >> (20 - PAGE_SHIFT));
+	}
+	printk(" = %luMB total\n", num_physpages >> (20 - PAGE_SHIFT));
+
+	pr_notice("Memory: %luk/%luk available, %luk reserved\n",
+		  nr_free_pages() << (PAGE_SHIFT-10),
+		  free_pages << (PAGE_SHIFT-10),
+		  reserved_pages << (PAGE_SHIFT-10));
+
+#define MLK(b, t) b, t, ((t) - (b)) >> 10
+#define MLM(b, t) b, t, ((t) - (b)) >> 20
+#define MLK_ROUNDUP(b, t) b, t, DIV_ROUND_UP(((t) - (b)), SZ_1K)
+
+	pr_notice("Virtual kernel memory layout:\n"
+		  "    vmalloc : 0x%16lx - 0x%16lx   (%6ld MB)\n"
+#ifdef CONFIG_SPARSEMEM_VMEMMAP
+		  "    vmemmap : 0x%16lx - 0x%16lx   (%6ld MB)\n"
+#endif
+		  "    modules : 0x%16lx - 0x%16lx   (%6ld MB)\n"
+		  "    memory  : 0x%16lx - 0x%16lx   (%6ld MB)\n"
+		  "      .init : 0x%p" " - 0x%p" "   (%6ld kB)\n"
+		  "      .text : 0x%p" " - 0x%p" "   (%6ld kB)\n"
+		  "      .data : 0x%p" " - 0x%p" "   (%6ld kB)\n",
+		  MLM(VMALLOC_START, VMALLOC_END),
+#ifdef CONFIG_SPARSEMEM_VMEMMAP
+		  MLM((unsigned long)virt_to_page(PAGE_OFFSET),
+		      (unsigned long)virt_to_page(high_memory)),
+#endif
+		  MLM(MODULES_VADDR, MODULES_END),
+		  MLM(PAGE_OFFSET, (unsigned long)high_memory),
+
+		  MLK_ROUNDUP(__init_begin, __init_end),
+		  MLK_ROUNDUP(_text, _etext),
+		  MLK_ROUNDUP(_sdata, _edata));
+
+#undef MLK
+#undef MLM
+#undef MLK_ROUNDUP
+
+	/*
+	 * Check boundaries twice: Some fundamental inconsistencies can be
+	 * detected at build time already.
+	 */
+#ifdef CONFIG_COMPAT
+	BUILD_BUG_ON(TASK_SIZE_32			> TASK_SIZE_64);
+#endif
+	BUILD_BUG_ON(TASK_SIZE_64			> MODULES_VADDR);
+	BUG_ON(TASK_SIZE_64				> MODULES_VADDR);
+
+	if (PAGE_SIZE >= 16384 && num_physpages <= 128) {
+		extern int sysctl_overcommit_memory;
+		/*
+		 * On a machine this small we won't get anywhere without
+		 * overcommit, so turn it on by default.
+		 */
+		sysctl_overcommit_memory = OVERCOMMIT_ALWAYS;
+	}
+}
+
+void free_initmem(void)
+{
+	poison_init_mem(__init_begin, __init_end - __init_begin);
+	totalram_pages += free_area(__phys_to_pfn(__pa(__init_begin)),
+				    __phys_to_pfn(__pa(__init_end)),
+				    "init");
+}
+
+#ifdef CONFIG_BLK_DEV_INITRD
+
+static int keep_initrd;
+
+void free_initrd_mem(unsigned long start, unsigned long end)
+{
+	if (!keep_initrd) {
+		poison_init_mem((void *)start, PAGE_ALIGN(end) - start);
+		totalram_pages += free_area(__phys_to_pfn(__pa(start)),
+					    __phys_to_pfn(__pa(end)),
+					    "initrd");
+	}
+}
+
+static int __init keepinitrd_setup(char *__unused)
+{
+	keep_initrd = 1;
+	return 1;
+}
+
+__setup("keepinitrd", keepinitrd_setup);
+#endif
diff --git a/arch/arm64/mm/ioremap.c b/arch/arm64/mm/ioremap.c
new file mode 100644
index 0000000..1725cd6
--- /dev/null
+++ b/arch/arm64/mm/ioremap.c
@@ -0,0 +1,84 @@
+/*
+ * Based on arch/arm/mm/ioremap.c
+ *
+ * (C) Copyright 1995 1996 Linus Torvalds
+ * Hacked for ARM by Phil Blundell <philb@gnu.org>
+ * Hacked to allow all architectures to build, and various cleanups
+ * by Russell King
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/export.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <linux/io.h>
+
+static void __iomem *__ioremap_caller(phys_addr_t phys_addr, size_t size,
+				      pgprot_t prot, void *caller)
+{
+	unsigned long last_addr;
+	unsigned long offset = phys_addr & ~PAGE_MASK;
+	int err;
+	unsigned long addr;
+	struct vm_struct *area;
+
+	/*
+	 * Page align the mapping address and size, taking account of any
+	 * offset.
+	 */
+	phys_addr &= PAGE_MASK;
+	size = PAGE_ALIGN(size + offset);
+
+	/*
+	 * Don't allow wraparound, zero size or outside PHYS_MASK.
+	 */
+	last_addr = phys_addr + size - 1;
+	if (!size || last_addr < phys_addr || (last_addr & ~PHYS_MASK))
+		return NULL;
+
+	/*
+	 * Don't allow RAM to be mapped.
+	 */
+	if (WARN_ON(pfn_valid(__phys_to_pfn(phys_addr))))
+		return NULL;
+
+	area = get_vm_area_caller(size, VM_IOREMAP, caller);
+	if (!area)
+		return NULL;
+	addr = (unsigned long)area->addr;
+
+	err = ioremap_page_range(addr, addr + size, phys_addr, prot);
+	if (err) {
+		vunmap((void *)addr);
+		return NULL;
+	}
+
+	return (void __iomem *)(offset + addr);
+}
+
+void __iomem *__ioremap(phys_addr_t phys_addr, size_t size, pgprot_t prot)
+{
+	return __ioremap_caller(phys_addr, size, prot,
+				__builtin_return_address(0));
+}
+EXPORT_SYMBOL(__ioremap);
+
+void __iounmap(volatile void __iomem *io_addr)
+{
+	void *addr = (void *)(PAGE_MASK & (unsigned long)io_addr);
+
+	vunmap(addr);
+}
+EXPORT_SYMBOL(__iounmap);
diff --git a/arch/arm64/mm/mm.h b/arch/arm64/mm/mm.h
new file mode 100644
index 0000000..d8d6e78
--- /dev/null
+++ b/arch/arm64/mm/mm.h
@@ -0,0 +1,2 @@
+extern void __flush_dcache_page(struct page *page);
+extern void __init bootmem_init(void);
diff --git a/arch/arm64/mm/mmap.c b/arch/arm64/mm/mmap.c
new file mode 100644
index 0000000..7c7be78
--- /dev/null
+++ b/arch/arm64/mm/mmap.c
@@ -0,0 +1,144 @@
+/*
+ * Based on arch/arm/mm/mmap.c
+ *
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/elf.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/export.h>
+#include <linux/shm.h>
+#include <linux/sched.h>
+#include <linux/io.h>
+#include <linux/personality.h>
+#include <linux/random.h>
+
+#include <asm/cputype.h>
+
+/*
+ * Leave enough space between the mmap area and the stack to honour ulimit in
+ * the face of randomisation.
+ */
+#define MIN_GAP (SZ_128M + ((STACK_RND_MASK << PAGE_SHIFT) + 1))
+#define MAX_GAP	(STACK_TOP/6*5)
+
+static int mmap_is_legacy(void)
+{
+	if (current->personality & ADDR_COMPAT_LAYOUT)
+		return 1;
+
+	if (rlimit(RLIMIT_STACK) == 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)
+		rnd = (long)get_random_int() & (STACK_RND_MASK >> 1);
+
+	return rnd << (PAGE_SHIFT + 1);
+}
+
+static unsigned long mmap_base(void)
+{
+	unsigned long gap = rlimit(RLIMIT_STACK);
+
+	if (gap < MIN_GAP)
+		gap = MIN_GAP;
+	else if (gap > MAX_GAP)
+		gap = MAX_GAP;
+
+	return PAGE_ALIGN(STACK_TOP - gap - mmap_rnd());
+}
+
+/*
+ * This function, called very early during the creation of a new process VM
+ * image, sets up which VM layout function to use:
+ */
+void arch_pick_mmap_layout(struct mm_struct *mm)
+{
+	/*
+	 * Fall back to the standard layout if the personality bit is set, or
+	 * if the expected stack growth is unlimited:
+	 */
+	if (mmap_is_legacy()) {
+		mm->mmap_base = TASK_UNMAPPED_BASE;
+		mm->get_unmapped_area = arch_get_unmapped_area;
+		mm->unmap_area = arch_unmap_area;
+	} else {
+		mm->mmap_base = mmap_base();
+		mm->get_unmapped_area = arch_get_unmapped_area_topdown;
+		mm->unmap_area = arch_unmap_area_topdown;
+	}
+}
+EXPORT_SYMBOL_GPL(arch_pick_mmap_layout);
+
+
+/*
+ * You really shouldn't be using read() or write() on /dev/mem.  This might go
+ * away in the future.
+ */
+int valid_phys_addr_range(unsigned long addr, size_t size)
+{
+	if (addr < PHYS_OFFSET)
+		return 0;
+	if (addr + size > __pa(high_memory - 1) + 1)
+		return 0;
+
+	return 1;
+}
+
+/*
+ * Do not allow /dev/mem mappings beyond the supported physical range.
+ */
+int valid_mmap_phys_addr_range(unsigned long pfn, size_t size)
+{
+	return !(((pfn << PAGE_SHIFT) + size) & ~PHYS_MASK);
+}
+
+#ifdef CONFIG_STRICT_DEVMEM
+
+#include <linux/ioport.h>
+
+/*
+ * devmem_is_allowed() checks to see if /dev/mem access to a certain address
+ * is valid. The argument is a physical page number.  We mimic x86 here by
+ * disallowing access to system RAM as well as device-exclusive MMIO regions.
+ * This effectively disable read()/write() on /dev/mem.
+ */
+int devmem_is_allowed(unsigned long pfn)
+{
+	if (iomem_is_exclusive(pfn << PAGE_SHIFT))
+		return 0;
+	if (!page_is_ram(pfn))
+		return 1;
+	return 0;
+}
+
+#endif
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
new file mode 100644
index 0000000..a6885d8
--- /dev/null
+++ b/arch/arm64/mm/mmu.c
@@ -0,0 +1,395 @@
+/*
+ * Based on arch/arm/mm/mmu.c
+ *
+ * Copyright (C) 1995-2005 Russell King
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/export.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/mman.h>
+#include <linux/nodemask.h>
+#include <linux/memblock.h>
+#include <linux/fs.h>
+
+#include <asm/cputype.h>
+#include <asm/sections.h>
+#include <asm/setup.h>
+#include <asm/sizes.h>
+#include <asm/tlb.h>
+#include <asm/mmu_context.h>
+
+#include "mm.h"
+
+/*
+ * Empty_zero_page is a special page that is used for zero-initialized data
+ * and COW.
+ */
+struct page *empty_zero_page;
+EXPORT_SYMBOL(empty_zero_page);
+
+pgprot_t pgprot_default;
+EXPORT_SYMBOL(pgprot_default);
+
+static pmdval_t prot_sect_kernel;
+
+struct cachepolicy {
+	const char	policy[16];
+	u64		mair;
+	u64		tcr;
+};
+
+static struct cachepolicy cache_policies[] __initdata = {
+	{
+		.policy		= "uncached",
+		.mair		= 0x44,			/* inner, outer non-cacheable */
+		.tcr		= TCR_IRGN_NC | TCR_ORGN_NC,
+	}, {
+		.policy		= "writethrough",
+		.mair		= 0xaa,			/* inner, outer write-through, read-allocate */
+		.tcr		= TCR_IRGN_WT | TCR_ORGN_WT,
+	}, {
+		.policy		= "writeback",
+		.mair		= 0xee,			/* inner, outer write-back, read-allocate */
+		.tcr		= TCR_IRGN_WBnWA | TCR_ORGN_WBnWA,
+	}
+};
+
+/*
+ * These are useful for identifying cache coherency problems by allowing the
+ * cache or the cache and writebuffer to be turned off. It changes the Normal
+ * memory caching attributes in the MAIR_EL1 register.
+ */
+static int __init early_cachepolicy(char *p)
+{
+	int i;
+	u64 tmp;
+
+	for (i = 0; i < ARRAY_SIZE(cache_policies); i++) {
+		int len = strlen(cache_policies[i].policy);
+
+		if (memcmp(p, cache_policies[i].policy, len) == 0)
+			break;
+	}
+	if (i == ARRAY_SIZE(cache_policies)) {
+		pr_err("ERROR: unknown or unsupported cache policy: %s\n", p);
+		return 0;
+	}
+
+	flush_cache_all();
+
+	/*
+	 * Modify MT_NORMAL attributes in MAIR_EL1.
+	 */
+	asm volatile(
+	"	mrs	%0, mair_el1\n"
+	"	bfi	%0, %1, #%2, #8\n"
+	"	msr	mair_el1, %0\n"
+	"	isb\n"
+	: "=&r" (tmp)
+	: "r" (cache_policies[i].mair), "i" (MT_NORMAL * 8));
+
+	/*
+	 * Modify TCR PTW cacheability attributes.
+	 */
+	asm volatile(
+	"	mrs	%0, tcr_el1\n"
+	"	bic	%0, %0, %2\n"
+	"	orr	%0, %0, %1\n"
+	"	msr	tcr_el1, %0\n"
+	"	isb\n"
+	: "=&r" (tmp)
+	: "r" (cache_policies[i].tcr), "r" (TCR_IRGN_MASK | TCR_ORGN_MASK));
+
+	flush_cache_all();
+
+	return 0;
+}
+early_param("cachepolicy", early_cachepolicy);
+
+/*
+ * Adjust the PMD section entries according to the CPU in use.
+ */
+static void __init init_mem_pgprot(void)
+{
+	pteval_t default_pgprot;
+	int i;
+
+	default_pgprot = PTE_ATTRINDX(MT_NORMAL);
+	prot_sect_kernel = PMD_TYPE_SECT | PMD_SECT_AF | PMD_ATTRINDX(MT_NORMAL);
+
+#ifdef CONFIG_SMP
+	/*
+	 * Mark memory with the "shared" attribute for SMP systems
+	 */
+	default_pgprot |= PTE_SHARED;
+	prot_sect_kernel |= PMD_SECT_S;
+#endif
+
+	for (i = 0; i < 16; i++) {
+		unsigned long v = pgprot_val(protection_map[i]);
+		protection_map[i] = __pgprot(v | default_pgprot);
+	}
+
+	pgprot_default = __pgprot(PTE_TYPE_PAGE | PTE_AF | default_pgprot);
+}
+
+pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
+			      unsigned long size, pgprot_t vma_prot)
+{
+	if (!pfn_valid(pfn))
+		return pgprot_noncached(vma_prot);
+	else if (file->f_flags & O_SYNC)
+		return pgprot_writecombine(vma_prot);
+	return vma_prot;
+}
+EXPORT_SYMBOL(phys_mem_access_prot);
+
+static void __init *early_alloc(unsigned long sz)
+{
+	void *ptr = __va(memblock_alloc(sz, sz));
+	memset(ptr, 0, sz);
+	return ptr;
+}
+
+static void __init alloc_init_pte(pmd_t *pmd, unsigned long addr,
+				  unsigned long end, unsigned long pfn)
+{
+	pte_t *pte;
+
+	if (pmd_none(*pmd)) {
+		pte = early_alloc(PTRS_PER_PTE * sizeof(pte_t));
+		__pmd_populate(pmd, __pa(pte), PMD_TYPE_TABLE);
+	}
+	BUG_ON(pmd_bad(*pmd));
+
+	pte = pte_offset_kernel(pmd, addr);
+	do {
+		set_pte(pte, pfn_pte(pfn, PAGE_KERNEL_EXEC));
+		pfn++;
+	} while (pte++, addr += PAGE_SIZE, addr != end);
+}
+
+static void __init alloc_init_pmd(pud_t *pud, unsigned long addr,
+				  unsigned long end, phys_addr_t phys)
+{
+	pmd_t *pmd;
+	unsigned long next;
+
+	/*
+	 * Check for initial section mappings in the pgd/pud and remove them.
+	 */
+	if (pud_none(*pud) || pud_bad(*pud)) {
+		pmd = early_alloc(PTRS_PER_PMD * sizeof(pmd_t));
+		pud_populate(&init_mm, pud, pmd);
+	}
+
+	pmd = pmd_offset(pud, addr);
+	do {
+		next = pmd_addr_end(addr, end);
+		/* try section mapping first */
+		if (((addr | next | phys) & ~SECTION_MASK) == 0)
+			set_pmd(pmd, __pmd(phys | prot_sect_kernel));
+		else
+			alloc_init_pte(pmd, addr, next, __phys_to_pfn(phys));
+		phys += next - addr;
+	} while (pmd++, addr = next, addr != end);
+}
+
+static void __init alloc_init_pud(pgd_t *pgd, unsigned long addr,
+				  unsigned long end, unsigned long phys)
+{
+	pud_t *pud = pud_offset(pgd, addr);
+	unsigned long next;
+
+	do {
+		next = pud_addr_end(addr, end);
+		alloc_init_pmd(pud, addr, next, phys);
+		phys += next - addr;
+	} while (pud++, addr = next, addr != end);
+}
+
+/*
+ * Create the page directory entries and any necessary page tables for the
+ * mapping specified by 'md'.
+ */
+static void __init create_mapping(phys_addr_t phys, unsigned long virt,
+				  phys_addr_t size)
+{
+	unsigned long addr, length, end, next;
+	pgd_t *pgd;
+
+	if (virt < VMALLOC_START) {
+		pr_warning("BUG: not creating mapping for 0x%016llx at 0x%016lx - outside kernel range\n",
+			   phys, virt);
+		return;
+	}
+
+	addr = virt & PAGE_MASK;
+	length = PAGE_ALIGN(size + (virt & ~PAGE_MASK));
+
+	pgd = pgd_offset_k(addr);
+	end = addr + length;
+	do {
+		next = pgd_addr_end(addr, end);
+		alloc_init_pud(pgd, addr, next, phys);
+		phys += next - addr;
+	} while (pgd++, addr = next, addr != end);
+}
+
+static void __init map_mem(void)
+{
+	struct memblock_region *reg;
+
+	/* map all the memory banks */
+	for_each_memblock(memory, reg) {
+		phys_addr_t start = reg->base;
+		phys_addr_t end = start + reg->size;
+
+		if (start >= end)
+			break;
+
+		create_mapping(start, __phys_to_virt(start), end - start);
+	}
+}
+
+/*
+ * paging_init() sets up the page tables, initialises the zone memory
+ * maps and sets up the zero page.
+ */
+void __init paging_init(void)
+{
+	void *zero_page;
+
+	/*
+	 * Maximum PGDIR_SIZE addressable via the initial direct kernel
+	 * mapping in swapper_pg_dir.
+	 */
+	memblock_set_current_limit((PHYS_OFFSET & PGDIR_MASK) + PGDIR_SIZE);
+
+	init_mem_pgprot();
+	map_mem();
+
+	/*
+	 * Finally flush the caches and tlb to ensure that we're in a
+	 * consistent state.
+	 */
+	flush_cache_all();
+	flush_tlb_all();
+
+	/* allocate the zero page. */
+	zero_page = early_alloc(PAGE_SIZE);
+
+	bootmem_init();
+
+	empty_zero_page = virt_to_page(zero_page);
+	__flush_dcache_page(empty_zero_page);
+
+	/*
+	 * TTBR0 is only used for the identity mapping at this stage. Make it
+	 * point to zero page to avoid speculatively fetching new entries.
+	 */
+	cpu_set_reserved_ttbr0();
+	flush_tlb_all();
+}
+
+/*
+ * Enable the identity mapping to allow the MMU disabling.
+ */
+void setup_mm_for_reboot(void)
+{
+	cpu_switch_mm(idmap_pg_dir, &init_mm);
+	flush_tlb_all();
+}
+
+/*
+ * Check whether a kernel address is valid (derived from arch/x86/).
+ */
+int kern_addr_valid(unsigned long addr)
+{
+	pgd_t *pgd;
+	pud_t *pud;
+	pmd_t *pmd;
+	pte_t *pte;
+
+	if ((((long)addr) >> VA_BITS) != -1UL)
+		return 0;
+
+	pgd = pgd_offset_k(addr);
+	if (pgd_none(*pgd))
+		return 0;
+
+	pud = pud_offset(pgd, addr);
+	if (pud_none(*pud))
+		return 0;
+
+	pmd = pmd_offset(pud, addr);
+	if (pmd_none(*pmd))
+		return 0;
+
+	pte = pte_offset_kernel(pmd, addr);
+	if (pte_none(*pte))
+		return 0;
+
+	return pfn_valid(pte_pfn(*pte));
+}
+#ifdef CONFIG_SPARSEMEM_VMEMMAP
+#ifdef CONFIG_ARM64_64K_PAGES
+int __meminit vmemmap_populate(struct page *start_page,
+			       unsigned long size, int node)
+{
+	return vmemmap_populate_basepages(start_page, size, node);
+}
+#else	/* !CONFIG_ARM64_64K_PAGES */
+int __meminit vmemmap_populate(struct page *start_page,
+			       unsigned long size, int node)
+{
+	unsigned long addr = (unsigned long)start_page;
+	unsigned long end = (unsigned long)(start_page + size);
+	unsigned long next;
+	pgd_t *pgd;
+	pud_t *pud;
+	pmd_t *pmd;
+
+	do {
+		next = pmd_addr_end(addr, end);
+
+		pgd = vmemmap_pgd_populate(addr, node);
+		if (!pgd)
+			return -ENOMEM;
+
+		pud = vmemmap_pud_populate(pgd, addr, node);
+		if (!pud)
+			return -ENOMEM;
+
+		pmd = pmd_offset(pud, addr);
+		if (pmd_none(*pmd)) {
+			void *p = NULL;
+
+			p = vmemmap_alloc_block_buf(PMD_SIZE, node);
+			if (!p)
+				return -ENOMEM;
+
+			set_pmd(pmd, __pmd(__pa(p) | prot_sect_kernel));
+		} else
+			vmemmap_verify((pte_t *)pmd, node, addr, next);
+	} while (addr = next, addr != end);
+
+	return 0;
+}
+#endif	/* CONFIG_ARM64_64K_PAGES */
+#endif	/* CONFIG_SPARSEMEM_VMEMMAP */
diff --git a/arch/arm64/mm/pgd.c b/arch/arm64/mm/pgd.c
new file mode 100644
index 0000000..7083cda
--- /dev/null
+++ b/arch/arm64/mm/pgd.c
@@ -0,0 +1,54 @@
+/*
+ * PGD allocation/freeing
+ *
+ * Copyright (C) 2012 ARM Ltd.
+ * Author: Catalin Marinas <catalin.marinas@arm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/mm.h>
+#include <linux/gfp.h>
+#include <linux/highmem.h>
+#include <linux/slab.h>
+
+#include <asm/pgalloc.h>
+#include <asm/page.h>
+#include <asm/tlbflush.h>
+
+#include "mm.h"
+
+#define PGD_SIZE	(PTRS_PER_PGD * sizeof(pgd_t))
+
+pgd_t *pgd_alloc(struct mm_struct *mm)
+{
+	pgd_t *new_pgd;
+
+	if (PGD_SIZE == PAGE_SIZE)
+		new_pgd = (pgd_t *)get_zeroed_page(GFP_KERNEL);
+	else
+		new_pgd = kzalloc(PGD_SIZE, GFP_KERNEL);
+
+	if (!new_pgd)
+		return NULL;
+
+	return new_pgd;
+}
+
+void pgd_free(struct mm_struct *mm, pgd_t *pgd)
+{
+	if (PGD_SIZE == PAGE_SIZE)
+		free_page((unsigned long)pgd);
+	else
+		kfree(pgd);
+}
diff --git a/arch/arm64/mm/proc-macros.S b/arch/arm64/mm/proc-macros.S
new file mode 100644
index 0000000..8957b82
--- /dev/null
+++ b/arch/arm64/mm/proc-macros.S
@@ -0,0 +1,55 @@
+/*
+ * Based on arch/arm/mm/proc-macros.S
+ *
+ * Copyright (C) 2012 ARM 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <asm/asm-offsets.h>
+#include <asm/thread_info.h>
+
+/*
+ * vma_vm_mm - get mm pointer from vma pointer (vma->vm_mm)
+ */
+	.macro	vma_vm_mm, rd, rn
+	ldr	\rd, [\rn, #VMA_VM_MM]
+	.endm
+
+/*
+ * mmid - get context id from mm pointer (mm->context.id)
+ */
+	.macro	mmid, rd, rn
+	ldr	\rd, [\rn, #MM_CONTEXT_ID]
+	.endm
+
+/*
+ * dcache_line_size - get the minimum D-cache line size from the CTR register.
+ */
+	.macro	dcache_line_size, reg, tmp
+	mrs	\tmp, ctr_el0			// read CTR
+	lsr	\tmp, \tmp, #16
+	and	\tmp, \tmp, #0xf		// cache line size encoding
+	mov	\reg, #4			// bytes per word
+	lsl	\reg, \reg, \tmp		// actual cache line size
+	.endm
+
+/*
+ * icache_line_size - get the minimum I-cache line size from the CTR register.
+ */
+	.macro	icache_line_size, reg, tmp
+	mrs	\tmp, ctr_el0			// read CTR
+	and	\tmp, \tmp, #0xf		// cache line size encoding
+	mov	\reg, #4			// bytes per word
+	lsl	\reg, \reg, \tmp		// actual cache line size
+	.endm
diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S
new file mode 100644
index 0000000..f1d8b9b
--- /dev/null
+++ b/arch/arm64/mm/proc.S
@@ -0,0 +1,175 @@
+/*
+ * Based on arch/arm/mm/proc.S
+ *
+ * Copyright (C) 2001 Deep Blue Solutions Ltd.
+ * Copyright (C) 2012 ARM Ltd.
+ * Author: Catalin Marinas <catalin.marinas@arm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/init.h>
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/asm-offsets.h>
+#include <asm/hwcap.h>
+#include <asm/pgtable-hwdef.h>
+#include <asm/pgtable.h>
+
+#include "proc-macros.S"
+
+#ifndef CONFIG_SMP
+/* PTWs cacheable, inner/outer WBWA not shareable */
+#define TCR_FLAGS	TCR_IRGN_WBWA | TCR_ORGN_WBWA
+#else
+/* PTWs cacheable, inner/outer WBWA shareable */
+#define TCR_FLAGS	TCR_IRGN_WBWA | TCR_ORGN_WBWA | TCR_SHARED
+#endif
+
+#define MAIR(attr, mt)	((attr) << ((mt) * 8))
+
+/*
+ *	cpu_cache_off()
+ *
+ *	Turn the CPU D-cache off.
+ */
+ENTRY(cpu_cache_off)
+	mrs	x0, sctlr_el1
+	bic	x0, x0, #1 << 2			// clear SCTLR.C
+	msr	sctlr_el1, x0
+	isb
+	ret
+ENDPROC(cpu_cache_off)
+
+/*
+ *	cpu_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. It must be executed with the flat identity mapping.
+ *
+ *	- loc   - location to jump to for soft reset
+ */
+	.align	5
+ENTRY(cpu_reset)
+	mrs	x1, sctlr_el1
+	bic	x1, x1, #1
+	msr	sctlr_el1, x1			// disable the MMU
+	isb
+	ret	x0
+ENDPROC(cpu_reset)
+
+/*
+ *	cpu_do_idle()
+ *
+ *	Idle the processor (wait for interrupt).
+ */
+ENTRY(cpu_do_idle)
+	dsb	sy				// WFI may enter a low-power mode
+	wfi
+	ret
+ENDPROC(cpu_do_idle)
+
+/*
+ *	cpu_switch_mm(pgd_phys, tsk)
+ *
+ *	Set the translation table base pointer to be pgd_phys.
+ *
+ *	- pgd_phys - physical address of new TTB
+ */
+ENTRY(cpu_do_switch_mm)
+	mmid	w1, x1				// get mm->context.id
+	bfi	x0, x1, #48, #16		// set the ASID
+	msr	ttbr0_el1, x0			// set TTBR0
+	isb
+	ret
+ENDPROC(cpu_do_switch_mm)
+
+cpu_name:
+	.ascii	"AArch64 Processor"
+	.align
+
+	.section ".text.init", #alloc, #execinstr
+
+/*
+ *	__cpu_setup
+ *
+ *	Initialise the processor for turning the MMU on.  Return in x0 the
+ *	value of the SCTLR_EL1 register.
+ */
+ENTRY(__cpu_setup)
+	/*
+	 * Preserve the link register across the function call.
+	 */
+	mov	x28, lr
+	bl	__flush_dcache_all
+	mov	lr, x28
+	ic	iallu				// I+BTB cache invalidate
+	dsb	sy
+
+	mov	x0, #3 << 20
+	msr	cpacr_el1, x0			// Enable FP/ASIMD
+	mov	x0, #1
+	msr	oslar_el1, x0			// Set the debug OS lock
+	tlbi	vmalle1is			// invalidate I + D TLBs
+	/*
+	 * Memory region attributes for LPAE:
+	 *
+	 *   n = AttrIndx[2:0]
+	 *			n	MAIR
+	 *   DEVICE_nGnRnE	000	00000000
+	 *   DEVICE_nGnRE	001	00000100
+	 *   DEVICE_GRE		010	00001100
+	 *   NORMAL_NC		011	01000100
+	 *   NORMAL		100	11111111
+	 */
+	ldr	x5, =MAIR(0x00, MT_DEVICE_nGnRnE) | \
+		     MAIR(0x04, MT_DEVICE_nGnRE) | \
+		     MAIR(0x0c, MT_DEVICE_GRE) | \
+		     MAIR(0x44, MT_NORMAL_NC) | \
+		     MAIR(0xff, MT_NORMAL)
+	msr	mair_el1, x5
+	/*
+	 * Prepare SCTLR
+	 */
+	adr	x5, crval
+	ldp	w5, w6, [x5]
+	mrs	x0, sctlr_el1
+	bic	x0, x0, x5			// clear bits
+	orr	x0, x0, x6			// set bits
+	/*
+	 * Set/prepare TCR and TTBR. We use 512GB (39-bit) address range for
+	 * both user and kernel.
+	 */
+	ldr	x10, =TCR_TxSZ(VA_BITS) | TCR_FLAGS | TCR_IPS_40BIT | \
+		      TCR_ASID16 | (1 << 31)
+#ifdef CONFIG_ARM64_64K_PAGES
+	orr	x10, x10, TCR_TG0_64K
+	orr	x10, x10, TCR_TG1_64K
+#endif
+	msr	tcr_el1, x10
+	ret					// return to head.S
+ENDPROC(__cpu_setup)
+
+	/*
+	 *                 n n            T
+	 *       U E      WT T UD     US IHBS
+	 *       CE0      XWHW CZ     ME TEEA S
+	 * .... .IEE .... NEAI TE.I ..AD DEN0 ACAM
+	 * 0011 0... 1101 ..0. ..0. 10.. .... .... < hardware reserved
+	 * .... .100 .... 01.1 11.1 ..01 0001 1101 < software settings
+	 */
+	.type	crval, #object
+crval:
+	.word	0x030802e2			// clear
+	.word	0x0405d11d			// set
diff --git a/arch/arm64/mm/tlb.S b/arch/arm64/mm/tlb.S
new file mode 100644
index 0000000..8ae80a1
--- /dev/null
+++ b/arch/arm64/mm/tlb.S
@@ -0,0 +1,71 @@
+/*
+ * Based on arch/arm/mm/tlb.S
+ *
+ * Copyright (C) 1997-2002 Russell King
+ * Copyright (C) 2012 ARM Ltd.
+ * Written by Catalin Marinas <catalin.marinas@arm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/asm-offsets.h>
+#include <asm/page.h>
+#include <asm/tlbflush.h>
+#include "proc-macros.S"
+
+/*
+ *	__cpu_flush_user_tlb_range(start, end, vma)
+ *
+ *	Invalidate a range of TLB entries in the specified address space.
+ *
+ *	- start - start address (may not be aligned)
+ *	- end   - end address (exclusive, may not be aligned)
+ *	- vma   - vma_struct describing address range
+ */
+ENTRY(__cpu_flush_user_tlb_range)
+	vma_vm_mm x3, x2			// get vma->vm_mm
+	mmid	x3, x3				// get vm_mm->context.id
+	dsb	sy
+	lsr	x0, x0, #12			// align address
+	lsr	x1, x1, #12
+	bfi	x0, x3, #48, #16		// start VA and ASID
+	bfi	x1, x3, #48, #16		// end VA and ASID
+1:	tlbi	vae1is, x0			// TLB invalidate by address and ASID
+	add	x0, x0, #1
+	cmp	x0, x1
+	b.lo	1b
+	dsb	sy
+	ret
+ENDPROC(__cpu_flush_user_tlb_range)
+
+/*
+ *	__cpu_flush_kern_tlb_range(start,end)
+ *
+ *	Invalidate a range of kernel TLB entries.
+ *
+ *	- start - start address (may not be aligned)
+ *	- end   - end address (exclusive, may not be aligned)
+ */
+ENTRY(__cpu_flush_kern_tlb_range)
+	dsb	sy
+	lsr	x0, x0, #12			// align address
+	lsr	x1, x1, #12
+1:	tlbi	vaae1is, x0			// TLB invalidate by address
+	add	x0, x0, #1
+	cmp	x0, x1
+	b.lo	1b
+	dsb	sy
+	isb
+	ret
+ENDPROC(__cpu_flush_kern_tlb_range)
diff --git a/arch/avr32/Kconfig b/arch/avr32/Kconfig
index 5ade51c..06e73bf 100644
--- a/arch/avr32/Kconfig
+++ b/arch/avr32/Kconfig
@@ -15,6 +15,8 @@ config AVR32
 	select ARCH_WANT_IPC_PARSE_VERSION
 	select ARCH_HAVE_NMI_SAFE_CMPXCHG
 	select GENERIC_CLOCKEVENTS
+	select HAVE_MOD_ARCH_SPECIFIC
+	select MODULES_USE_ELF_RELA
 	help
 	  AVR32 is a high-performance 32-bit RISC microprocessor core,
 	  designed for cost-sensitive embedded applications, with particular
diff --git a/arch/avr32/include/asm/Kbuild b/arch/avr32/include/asm/Kbuild
index 3136628..aa47fff 100644
--- a/arch/avr32/include/asm/Kbuild
+++ b/arch/avr32/include/asm/Kbuild
@@ -1,3 +1,4 @@
 include include/asm-generic/Kbuild.asm
 
+generic-y	+= exec.h
 header-y	+= cachectl.h
diff --git a/arch/avr32/include/asm/elf.h b/arch/avr32/include/asm/elf.h
index 3b3159b..e2c3287 100644
--- a/arch/avr32/include/asm/elf.h
+++ b/arch/avr32/include/asm/elf.h
@@ -102,6 +102,7 @@ typedef struct user_fpu_struct elf_fpregset_t;
 
 #define ELF_PLATFORM  (NULL)
 
-#define SET_PERSONALITY(ex) set_personality(PER_LINUX_32BIT)
+#define SET_PERSONALITY(ex) \
+	set_personality(PER_LINUX_32BIT | (current->personality & (~PER_MASK)))
 
 #endif /* __ASM_AVR32_ELF_H */
diff --git a/arch/avr32/include/asm/exec.h b/arch/avr32/include/asm/exec.h
deleted file mode 100644
index f467be8..0000000
--- a/arch/avr32/include/asm/exec.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * Copyright (C) 2004-2006 Atmel Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#ifndef __ASM_AVR32_EXEC_H
-#define __ASM_AVR32_EXEC_H
-
-#define arch_align_stack(x)	(x)
-
-#endif /* __ASM_AVR32_EXEC_H */
diff --git a/arch/avr32/include/asm/module.h b/arch/avr32/include/asm/module.h
index 4514445..3f083d3 100644
--- a/arch/avr32/include/asm/module.h
+++ b/arch/avr32/include/asm/module.h
@@ -1,6 +1,8 @@
 #ifndef __ASM_AVR32_MODULE_H
 #define __ASM_AVR32_MODULE_H
 
+#include <asm-generic/module.h>
+
 struct mod_arch_syminfo {
 	unsigned long got_offset;
 	int got_initialized;
@@ -17,10 +19,6 @@ struct mod_arch_specific {
 	struct mod_arch_syminfo *syminfo;
 };
 
-#define Elf_Shdr		Elf32_Shdr
-#define Elf_Sym			Elf32_Sym
-#define Elf_Ehdr		Elf32_Ehdr
-
 #define MODULE_PROC_FAMILY "AVR32v1"
 
 #define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY
diff --git a/arch/avr32/include/asm/thread_info.h b/arch/avr32/include/asm/thread_info.h
index e5deda4..6dc62e1 100644
--- a/arch/avr32/include/asm/thread_info.h
+++ b/arch/avr32/include/asm/thread_info.h
@@ -77,8 +77,6 @@ static inline struct thread_info *current_thread_info(void)
 #define TIF_SYSCALL_TRACE       0       /* syscall trace active */
 #define TIF_SIGPENDING          1       /* signal pending */
 #define TIF_NEED_RESCHED        2       /* rescheduling necessary */
-#define TIF_POLLING_NRFLAG      3       /* true if poll_idle() is polling
-					   TIF_NEED_RESCHED */
 #define TIF_BREAKPOINT		4	/* enter monitor mode on return */
 #define TIF_SINGLE_STEP		5	/* single step in progress */
 #define TIF_MEMDIE		6	/* is terminating due to OOM killer */
@@ -91,10 +89,9 @@ static inline struct thread_info *current_thread_info(void)
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1 << TIF_NEED_RESCHED)
-#define _TIF_POLLING_NRFLAG	(1 << TIF_POLLING_NRFLAG)
+#define _TIF_BREAKPOINT		(1 << TIF_BREAKPOINT)
 #define _TIF_SINGLE_STEP	(1 << TIF_SINGLE_STEP)
 #define _TIF_MEMDIE		(1 << TIF_MEMDIE)
-#define _TIF_RESTORE_SIGMASK	(1 << TIF_RESTORE_SIGMASK)
 #define _TIF_CPU_GOING_TO_SLEEP (1 << TIF_CPU_GOING_TO_SLEEP)
 #define _TIF_NOTIFY_RESUME	(1 << TIF_NOTIFY_RESUME)
 
@@ -102,17 +99,14 @@ static inline struct thread_info *current_thread_info(void)
 
 /* work to do on interrupt/exception return */
 #define _TIF_WORK_MASK				\
-	((1 << TIF_SIGPENDING)			\
+	(_TIF_SIGPENDING			\
 	 | _TIF_NOTIFY_RESUME			\
-	 | (1 << TIF_NEED_RESCHED)		\
-	 | (1 << TIF_POLLING_NRFLAG)		\
-	 | (1 << TIF_BREAKPOINT)		\
-	 | (1 << TIF_RESTORE_SIGMASK))
+	 | _TIF_NEED_RESCHED			\
+	 | _TIF_BREAKPOINT)
 
 /* work to do on any return to userspace */
-#define _TIF_ALLWORK_MASK	(_TIF_WORK_MASK | (1 << TIF_SYSCALL_TRACE) | \
-				 _TIF_NOTIFY_RESUME)
+#define _TIF_ALLWORK_MASK	(_TIF_WORK_MASK | _TIF_SYSCALL_TRACE)
 /* work to do on return from debug mode */
-#define _TIF_DBGWORK_MASK	(_TIF_WORK_MASK & ~(1 << TIF_BREAKPOINT))
+#define _TIF_DBGWORK_MASK	(_TIF_WORK_MASK & ~_TIF_BREAKPOINT)
 
 #endif /* __ASM_AVR32_THREAD_INFO_H */
diff --git a/arch/avr32/kernel/signal.c b/arch/avr32/kernel/signal.c
index d552a85..5e01c3a 100644
--- a/arch/avr32/kernel/signal.c
+++ b/arch/avr32/kernel/signal.c
@@ -15,7 +15,6 @@
 #include <linux/errno.h>
 #include <linux/ptrace.h>
 #include <linux/unistd.h>
-#include <linux/freezer.h>
 #include <linux/tracehook.h>
 
 #include <asm/uaccess.h>
diff --git a/arch/avr32/mm/fault.c b/arch/avr32/mm/fault.c
index b92e609..b2f2d2d 100644
--- a/arch/avr32/mm/fault.c
+++ b/arch/avr32/mm/fault.c
@@ -152,6 +152,7 @@ good_area:
 			tsk->min_flt++;
 		if (fault & VM_FAULT_RETRY) {
 			flags &= ~FAULT_FLAG_ALLOW_RETRY;
+			flags |= FAULT_FLAG_TRIED;
 
 			/*
 			 * No need to up_read(&mm->mmap_sem) as we would have
diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig
index c7092e6..8e82e26 100644
--- a/arch/blackfin/Kconfig
+++ b/arch/blackfin/Kconfig
@@ -42,6 +42,8 @@ config BLACKFIN
 	select HAVE_NMI_WATCHDOG if NMI_WATCHDOG
 	select GENERIC_SMP_IDLE_THREAD
 	select ARCH_USES_GETTIMEOFFSET if !GENERIC_CLOCKEVENTS
+	select HAVE_MOD_ARCH_SPECIFIC
+	select MODULES_USE_ELF_RELA
 
 config GENERIC_CSUM
 	def_bool y
diff --git a/arch/blackfin/configs/BF561-ACVILON_defconfig b/arch/blackfin/configs/BF561-ACVILON_defconfig
index 0fdc4ec..9198837 100644
--- a/arch/blackfin/configs/BF561-ACVILON_defconfig
+++ b/arch/blackfin/configs/BF561-ACVILON_defconfig
@@ -57,7 +57,6 @@ CONFIG_MTD_PLATRAM=y
 CONFIG_MTD_PHRAM=y
 CONFIG_MTD_BLOCK2MTD=y
 CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_VERIFY_WRITE=y
 CONFIG_MTD_NAND_PLATFORM=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
diff --git a/arch/blackfin/include/asm/elf.h b/arch/blackfin/include/asm/elf.h
index e6c6812..14bc98f 100644
--- a/arch/blackfin/include/asm/elf.h
+++ b/arch/blackfin/include/asm/elf.h
@@ -132,6 +132,7 @@ do {											\
 
 #define ELF_PLATFORM  (NULL)
 
-#define SET_PERSONALITY(ex) set_personality(PER_LINUX)
+#define SET_PERSONALITY(ex) \
+	set_personality(PER_LINUX | (current->personality & (~PER_MASK)))
 
 #endif
diff --git a/arch/blackfin/include/asm/module.h b/arch/blackfin/include/asm/module.h
index ed5689b..231a149 100644
--- a/arch/blackfin/include/asm/module.h
+++ b/arch/blackfin/include/asm/module.h
@@ -7,9 +7,7 @@
 #ifndef _ASM_BFIN_MODULE_H
 #define _ASM_BFIN_MODULE_H
 
-#define Elf_Shdr        Elf32_Shdr
-#define Elf_Sym         Elf32_Sym
-#define Elf_Ehdr        Elf32_Ehdr
+#include <asm-generic/module.h>
 
 struct mod_arch_specific {
 	Elf_Shdr	*text_l1;
diff --git a/arch/blackfin/include/asm/thread_info.h b/arch/blackfin/include/asm/thread_info.h
index 53ad100..3894005 100644
--- a/arch/blackfin/include/asm/thread_info.h
+++ b/arch/blackfin/include/asm/thread_info.h
@@ -96,8 +96,6 @@ static inline struct thread_info *current_thread_info(void)
 #define TIF_SYSCALL_TRACE	0	/* syscall trace active */
 #define TIF_SIGPENDING		1	/* signal pending */
 #define TIF_NEED_RESCHED	2	/* rescheduling necessary */
-#define TIF_POLLING_NRFLAG	3	/* true if poll_idle() is polling
-					   TIF_NEED_RESCHED */
 #define TIF_MEMDIE		4	/* is terminating due to OOM killer */
 #define TIF_RESTORE_SIGMASK	5	/* restore signal mask in do_signal() */
 #define TIF_IRQ_SYNC		7	/* sync pipeline stage */
@@ -108,8 +106,6 @@ static inline struct thread_info *current_thread_info(void)
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
-#define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
-#define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
 #define _TIF_IRQ_SYNC		(1<<TIF_IRQ_SYNC)
 #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
 #define _TIF_SINGLESTEP		(1<<TIF_SINGLESTEP)
diff --git a/arch/blackfin/kernel/signal.c b/arch/blackfin/kernel/signal.c
index 6682b73..6ed20a1 100644
--- a/arch/blackfin/kernel/signal.c
+++ b/arch/blackfin/kernel/signal.c
@@ -10,7 +10,6 @@
 #include <linux/tty.h>
 #include <linux/personality.h>
 #include <linux/binfmts.h>
-#include <linux/freezer.h>
 #include <linux/uaccess.h>
 #include <linux/tracehook.h>
 
diff --git a/arch/blackfin/mach-bf527/boards/ezkit.c b/arch/blackfin/mach-bf527/boards/ezkit.c
index fc179ca..29f16e5 100644
--- a/arch/blackfin/mach-bf527/boards/ezkit.c
+++ b/arch/blackfin/mach-bf527/boards/ezkit.c
@@ -587,6 +587,21 @@ static struct platform_device bfin_tdm = {
 };
 #endif
 
+#if defined(CONFIG_SND_BF5XX_SOC_AD1836) \
+	        || defined(CONFIG_SND_BF5XX_SOC_AD1836_MODULE)
+static const char * const ad1836_link[] = {
+	"bfin-tdm.0",
+	"spi0.4",
+};
+static struct platform_device bfin_ad1836_machine = {
+	.name = "bfin-snd-ad1836",
+	.id = -1,
+	.dev = {
+		.platform_data = (void *)ad1836_link,
+	},
+};
+#endif
+
 static struct spi_board_info bfin_spi_board_info[] __initdata = {
 #if defined(CONFIG_MTD_M25P80) \
 	|| defined(CONFIG_MTD_M25P80_MODULE)
@@ -1269,6 +1284,11 @@ static struct platform_device *stamp_devices[] __initdata = {
 #if defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE)
 	&bfin_tdm,
 #endif
+
+#if defined(CONFIG_SND_BF5XX_SOC_AD1836) || \
+	defined(CONFIG_SND_BF5XX_SOC_AD1836_MODULE)
+	&bfin_ad1836_machine,
+#endif
 };
 
 static int __init ezkit_init(void)
diff --git a/arch/blackfin/mach-bf533/boards/stamp.c b/arch/blackfin/mach-bf533/boards/stamp.c
index ce88a71..6fca869 100644
--- a/arch/blackfin/mach-bf533/boards/stamp.c
+++ b/arch/blackfin/mach-bf533/boards/stamp.c
@@ -617,6 +617,21 @@ static struct platform_device bfin_ac97_pcm = {
 };
 #endif
 
+#if defined(CONFIG_SND_BF5XX_SOC_AD1836) \
+	        || defined(CONFIG_SND_BF5XX_SOC_AD1836_MODULE)
+static const char * const ad1836_link[] = {
+	"bfin-tdm.0",
+	"spi0.4",
+};
+static struct platform_device bfin_ad1836_machine = {
+	.name = "bfin-snd-ad1836",
+	.id = -1,
+	.dev = {
+		.platform_data = (void *)ad1836_link,
+	},
+};
+#endif
+
 #if defined(CONFIG_SND_BF5XX_SOC_AD73311) || \
 	defined(CONFIG_SND_BF5XX_SOC_AD73311_MODULE)
 static const unsigned ad73311_gpio[] = {
@@ -754,6 +769,11 @@ static struct platform_device *stamp_devices[] __initdata = {
 	&bfin_ac97_pcm,
 #endif
 
+#if defined(CONFIG_SND_BF5XX_SOC_AD1836) || \
+	defined(CONFIG_SND_BF5XX_SOC_AD1836_MODULE)
+	&bfin_ad1836_machine,
+#endif
+
 #if defined(CONFIG_SND_BF5XX_SOC_AD73311) || \
 	defined(CONFIG_SND_BF5XX_SOC_AD73311_MODULE)
 	&bfin_ad73311_machine,
diff --git a/arch/blackfin/mach-bf537/boards/stamp.c b/arch/blackfin/mach-bf537/boards/stamp.c
index 5ed654a..307bd7e 100644
--- a/arch/blackfin/mach-bf537/boards/stamp.c
+++ b/arch/blackfin/mach-bf537/boards/stamp.c
@@ -2641,6 +2641,21 @@ static struct platform_device bfin_ac97_pcm = {
 };
 #endif
 
+#if defined(CONFIG_SND_BF5XX_SOC_AD1836) \
+	        || defined(CONFIG_SND_BF5XX_SOC_AD1836_MODULE)
+static const char * const ad1836_link[] = {
+	"bfin-tdm.0",
+	"spi0.4",
+};
+static struct platform_device bfin_ad1836_machine = {
+	.name = "bfin-snd-ad1836",
+	.id = -1,
+	.dev = {
+		.platform_data = (void *)ad1836_link,
+	},
+};
+#endif
+
 #if defined(CONFIG_SND_BF5XX_SOC_AD73311) || \
 				defined(CONFIG_SND_BF5XX_SOC_AD73311_MODULE)
 static const unsigned ad73311_gpio[] = {
@@ -2927,6 +2942,11 @@ static struct platform_device *stamp_devices[] __initdata = {
 	&bfin_ac97_pcm,
 #endif
 
+#if defined(CONFIG_SND_BF5XX_SOC_AD1836) || \
+	defined(CONFIG_SND_BF5XX_SOC_AD1836_MODULE)
+	&bfin_ad1836_machine,
+#endif
+
 #if defined(CONFIG_SND_BF5XX_SOC_AD73311) || \
 		defined(CONFIG_SND_BF5XX_SOC_AD73311_MODULE)
 	&bfin_ad73311_machine,
diff --git a/arch/blackfin/mach-bf561/boards/ezkit.c b/arch/blackfin/mach-bf561/boards/ezkit.c
index 7c36777..551f866 100644
--- a/arch/blackfin/mach-bf561/boards/ezkit.c
+++ b/arch/blackfin/mach-bf561/boards/ezkit.c
@@ -539,6 +539,21 @@ static struct platform_device bfin_ac97 = {
 };
 #endif
 
+#if defined(CONFIG_SND_BF5XX_SOC_AD1836) \
+	        || defined(CONFIG_SND_BF5XX_SOC_AD1836_MODULE)
+static const char * const ad1836_link[] = {
+	"bfin-tdm.0",
+	"spi0.4",
+};
+static struct platform_device bfin_ad1836_machine = {
+	.name = "bfin-snd-ad1836",
+	.id = -1,
+	.dev = {
+		.platform_data = (void *)ad1836_link,
+	},
+};
+#endif
+
 static struct platform_device *ezkit_devices[] __initdata = {
 
 	&bfin_dpmc,
@@ -603,6 +618,11 @@ static struct platform_device *ezkit_devices[] __initdata = {
 #if defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE)
 	&bfin_ac97,
 #endif
+
+#if defined(CONFIG_SND_BF5XX_SOC_AD1836) || \
+	defined(CONFIG_SND_BF5XX_SOC_AD1836_MODULE)
+	&bfin_ad1836_machine,
+#endif
 };
 
 static int __init net2272_init(void)
diff --git a/arch/blackfin/mach-bf609/boards/ezkit.c b/arch/blackfin/mach-bf609/boards/ezkit.c
index c2cf1ae..61c1f47 100644
--- a/arch/blackfin/mach-bf609/boards/ezkit.c
+++ b/arch/blackfin/mach-bf609/boards/ezkit.c
@@ -818,6 +818,21 @@ static struct platform_device bfin_i2s = {
 };
 #endif
 
+#if defined(CONFIG_SND_BF5XX_SOC_AD1836) \
+	        || defined(CONFIG_SND_BF5XX_SOC_AD1836_MODULE)
+static const char * const ad1836_link[] = {
+	"bfin-tdm.0",
+	"spi0.76",
+};
+static struct platform_device bfin_ad1836_machine = {
+	.name = "bfin-snd-ad1836",
+	.id = -1,
+	.dev = {
+		.platform_data = (void *)ad1836_link,
+	},
+};
+#endif
+
 #if defined(CONFIG_SND_SOC_BFIN_EVAL_ADAU1X61) || \
 	defined(CONFIG_SND_SOC_BFIN_EVAL_ADAU1X61_MODULE)
 static struct platform_device adau1761_device = {
@@ -1557,6 +1572,10 @@ static struct platform_device *ezkit_devices[] __initdata = {
 	defined(CONFIG_SND_BF6XX_SOC_I2S_MODULE)
 	&bfin_i2s,
 #endif
+#if defined(CONFIG_SND_BF5XX_SOC_AD1836) || \
+	defined(CONFIG_SND_BF5XX_SOC_AD1836_MODULE)
+	&bfin_ad1836_machine,
+#endif
 #if defined(CONFIG_SND_SOC_BFIN_EVAL_ADAU1X61) || \
 	defined(CONFIG_SND_SOC_BFIN_EVAL_ADAU1X61_MODULE)
 	&adau1761_device,
diff --git a/arch/c6x/Kconfig b/arch/c6x/Kconfig
index 983c859..20ef56e 100644
--- a/arch/c6x/Kconfig
+++ b/arch/c6x/Kconfig
@@ -17,6 +17,8 @@ config C6X
 	select OF
 	select OF_EARLY_FLATTREE
 	select GENERIC_CLOCKEVENTS
+	select MODULES_USE_ELF_RELA
+	select GENERIC_KERNEL_THREAD
 
 config MMU
 	def_bool n
diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild
index 3af601e..91d6f87 100644
--- a/arch/c6x/include/asm/Kbuild
+++ b/arch/c6x/include/asm/Kbuild
@@ -2,6 +2,7 @@ include include/asm-generic/Kbuild.asm
 
 generic-y += atomic.h
 generic-y += auxvec.h
+generic-y += barrier.h
 generic-y += bitsperlong.h
 generic-y += bugs.h
 generic-y += cputime.h
@@ -11,6 +12,7 @@ generic-y += div64.h
 generic-y += dma.h
 generic-y += emergency-restart.h
 generic-y += errno.h
+generic-y += exec.h
 generic-y += fb.h
 generic-y += fcntl.h
 generic-y += futex.h
diff --git a/arch/c6x/include/asm/barrier.h b/arch/c6x/include/asm/barrier.h
deleted file mode 100644
index 538240e..0000000
--- a/arch/c6x/include/asm/barrier.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- *  Port on Texas Instruments TMS320C6x architecture
- *
- *  Copyright (C) 2004, 2009, 2010, 2011 Texas Instruments Incorporated
- *  Author: Aurelien Jacquiot (aurelien.jacquiot@jaluna.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_C6X_BARRIER_H
-#define _ASM_C6X_BARRIER_H
-
-#define nop()                    asm("NOP\n");
-
-#define mb()                     barrier()
-#define rmb()                    barrier()
-#define wmb()                    barrier()
-#define set_mb(var, value)       do { var = value;  mb(); } while (0)
-#define set_wmb(var, value)      do { var = value; wmb(); } while (0)
-
-#define smp_mb()	         barrier()
-#define smp_rmb()	         barrier()
-#define smp_wmb()	         barrier()
-#define smp_read_barrier_depends()	do { } while (0)
-
-#endif /* _ASM_C6X_BARRIER_H */
diff --git a/arch/c6x/include/asm/elf.h b/arch/c6x/include/asm/elf.h
index f4552db..32b9971 100644
--- a/arch/c6x/include/asm/elf.h
+++ b/arch/c6x/include/asm/elf.h
@@ -77,7 +77,8 @@ do {								\
 
 #define ELF_PLATFORM  (NULL)
 
-#define SET_PERSONALITY(ex) set_personality(PER_LINUX)
+#define SET_PERSONALITY(ex) \
+	set_personality(PER_LINUX | (current->personality & (~PER_MASK)))
 
 /* C6X specific section types */
 #define SHT_C6000_UNWIND	0x70000001
diff --git a/arch/c6x/include/asm/exec.h b/arch/c6x/include/asm/exec.h
deleted file mode 100644
index 0fea482..0000000
--- a/arch/c6x/include/asm/exec.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ASM_C6X_EXEC_H
-#define _ASM_C6X_EXEC_H
-
-#define arch_align_stack(x) (x)
-
-#endif /* _ASM_C6X_EXEC_H */
diff --git a/arch/c6x/include/asm/module.h b/arch/c6x/include/asm/module.h
index a453f97..5c7269c 100644
--- a/arch/c6x/include/asm/module.h
+++ b/arch/c6x/include/asm/module.h
@@ -13,17 +13,7 @@
 #ifndef _ASM_C6X_MODULE_H
 #define _ASM_C6X_MODULE_H
 
-#define Elf_Shdr	Elf32_Shdr
-#define Elf_Sym		Elf32_Sym
-#define Elf_Ehdr	Elf32_Ehdr
-#define Elf_Addr	Elf32_Addr
-#define Elf_Word	Elf32_Word
-
-/*
- * This file contains the C6x architecture specific module code.
- */
-struct mod_arch_specific {
-};
+#include <asm-generic/module.h>
 
 struct loaded_sections {
 	unsigned int new_vaddr;
diff --git a/arch/c6x/include/asm/processor.h b/arch/c6x/include/asm/processor.h
index c50af7e..b9eb3da 100644
--- a/arch/c6x/include/asm/processor.h
+++ b/arch/c6x/include/asm/processor.h
@@ -92,8 +92,6 @@ static inline void release_thread(struct task_struct *dead_task)
 {
 }
 
-extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
-
 #define copy_segments(tsk, mm)		do { } while (0)
 #define release_segments(mm)		do { } while (0)
 
diff --git a/arch/c6x/include/asm/syscalls.h b/arch/c6x/include/asm/syscalls.h
index aed53da..e7b8991 100644
--- a/arch/c6x/include/asm/syscalls.h
+++ b/arch/c6x/include/asm/syscalls.h
@@ -44,11 +44,6 @@ extern int sys_cache_sync(unsigned long s, unsigned long e);
 struct pt_regs;
 
 extern asmlinkage long sys_c6x_clone(struct pt_regs *regs);
-extern asmlinkage long sys_c6x_execve(const char __user *name,
-				      const char __user *const __user *argv,
-				      const char __user *const __user *envp,
-				      struct pt_regs *regs);
-
 
 #include <asm-generic/syscalls.h>
 
diff --git a/arch/c6x/include/asm/thread_info.h b/arch/c6x/include/asm/thread_info.h
index 1710bcb..4c8dc56 100644
--- a/arch/c6x/include/asm/thread_info.h
+++ b/arch/c6x/include/asm/thread_info.h
@@ -97,7 +97,6 @@ struct thread_info *current_thread_info(void)
 #define TIF_NEED_RESCHED	3	/* rescheduling necessary */
 #define TIF_RESTORE_SIGMASK	4	/* restore signal mask in do_signal() */
 
-#define TIF_POLLING_NRFLAG	16	/* true if polling TIF_NEED_RESCHED */
 #define TIF_MEMDIE		17	/* OOM killer killed process */
 
 #define TIF_WORK_MASK		0x00007FFE /* work on irq/exception return */
diff --git a/arch/c6x/include/asm/unistd.h b/arch/c6x/include/asm/unistd.h
index 6d54ea4..3c131d5 100644
--- a/arch/c6x/include/asm/unistd.h
+++ b/arch/c6x/include/asm/unistd.h
@@ -16,6 +16,9 @@
 #if !defined(_ASM_C6X_UNISTD_H) || defined(__SYSCALL)
 #define _ASM_C6X_UNISTD_H
 
+#define __ARCH_WANT_KERNEL_EXECVE
+#define __ARCH_WANT_SYS_EXECVE
+
 /* Use the standard ABI for syscalls. */
 #include <asm-generic/unistd.h>
 
diff --git a/arch/c6x/kernel/asm-offsets.c b/arch/c6x/kernel/asm-offsets.c
index 759ad6d..60f1e43 100644
--- a/arch/c6x/kernel/asm-offsets.c
+++ b/arch/c6x/kernel/asm-offsets.c
@@ -116,7 +116,6 @@ void foo(void)
 	DEFINE(_TIF_NOTIFY_RESUME, (1<<TIF_NOTIFY_RESUME));
 	DEFINE(_TIF_SIGPENDING, (1<<TIF_SIGPENDING));
 	DEFINE(_TIF_NEED_RESCHED, (1<<TIF_NEED_RESCHED));
-	DEFINE(_TIF_POLLING_NRFLAG, (1<<TIF_POLLING_NRFLAG));
 
 	DEFINE(_TIF_ALLWORK_MASK, TIF_ALLWORK_MASK);
 	DEFINE(_TIF_WORK_MASK, TIF_WORK_MASK);
diff --git a/arch/c6x/kernel/entry.S b/arch/c6x/kernel/entry.S
index 30b37e5..5449c36 100644
--- a/arch/c6x/kernel/entry.S
+++ b/arch/c6x/kernel/entry.S
@@ -400,6 +400,32 @@ ret_from_fork_2:
 	STW	.D2T2	B0,*+SP(REGS_A4+8)
 ENDPROC(ret_from_fork)
 
+ENTRY(ret_from_kernel_thread)
+#ifdef CONFIG_C6X_BIG_KERNEL
+	MVKL	.S1	schedule_tail,A0
+	MVKH	.S1	schedule_tail,A0
+	B	.S2X	A0
+#else
+	B	.S2	schedule_tail
+#endif
+	LDW	.D2T2	*+SP(REGS_A0+8),B10 /* get fn  */
+	ADDKPC	.S2	0f,B3,3
+0:
+	B	.S2	B10		   /* call fn */
+	LDW	.D2T1	*+SP(REGS_A1+8),A4 /* get arg */
+	MVKL	.S2	sys_exit,B11
+	MVKH	.S2	sys_exit,B11
+	ADDKPC	.S2	0f,B3,1
+0:
+	BNOP	.S2	B11,5	/* jump to sys_exit */
+ENDPROC(ret_from_kernel_thread)
+
+ENTRY(ret_from_kernel_execve)
+	GET_THREAD_INFO A12
+	BNOP	.S2	syscall_exit,4
+	ADD	.D2X	A4,-8,SP
+ENDPROC(ret_from_kernel_execve)
+
 	;;
 	;; These are the interrupt handlers, responsible for calling __do_IRQ()
 	;; int6 is used for syscalls (see _system_call entry)
@@ -593,13 +619,6 @@ ENTRY(sys_sigaltstack)
 	NOP	4
 ENDPROC(sys_sigaltstack)
 
-	;; kernel_execve
-ENTRY(kernel_execve)
-	MVK	.S2	__NR_execve,B0
-	SWE
-	BNOP	.S2	B3,5
-ENDPROC(kernel_execve)
-
 	;;
 	;; Special system calls
 	;; return address is in B3
@@ -628,29 +647,6 @@ ENTRY(sys_rt_sigreturn)
 #endif
 ENDPROC(sys_rt_sigreturn)
 
-ENTRY(sys_execve)
-	ADDAW	.D2	SP,2,B6		; put regs addr in 4th parameter
-					; & adjust regs stack addr
-	LDW	.D2T2	*+SP(REGS_B4+8),B4
-
-	;; c6x_execve(char *name, char **argv,
-	;;            char **envp, struct pt_regs *regs)
-#ifdef CONFIG_C6X_BIG_KERNEL
- ||	MVKL	.S1	sys_c6x_execve,A0
-	MVKH	.S1	sys_c6x_execve,A0
-	B	.S2X	A0
-#else
- ||	B	.S2	sys_c6x_execve
-#endif
-	STW	.D2T2	B3,*SP--[2]
-	ADDKPC	.S2	ret_from_c6x_execve,B3,3
-
-ret_from_c6x_execve:
-	LDW	.D2T2	*++SP[2],B3
-	NOP	4
-	BNOP	.S2	B3,5
-ENDPROC(sys_execve)
-
 ENTRY(sys_pread_c6x)
 	MV	.D2X	A8,B7
 #ifdef CONFIG_C6X_BIG_KERNEL
diff --git a/arch/c6x/kernel/process.c b/arch/c6x/kernel/process.c
index 45e924a..2770d9a 100644
--- a/arch/c6x/kernel/process.c
+++ b/arch/c6x/kernel/process.c
@@ -25,6 +25,7 @@ void	(*c6x_restart)(void);
 void	(*c6x_halt)(void);
 
 extern asmlinkage void ret_from_fork(void);
+extern asmlinkage void ret_from_kernel_thread(void);
 
 /*
  * power off function, if any
@@ -103,37 +104,6 @@ void machine_power_off(void)
 	halt_loop();
 }
 
-static void kernel_thread_helper(int dummy, void *arg, int (*fn)(void *))
-{
-	do_exit(fn(arg));
-}
-
-/*
- * Create a kernel thread
- */
-int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
-{
-	struct pt_regs regs;
-
-	/*
-	 * copy_thread sets a4 to zero (child return from fork)
-	 * so we can't just set things up to directly return to
-	 * fn.
-	 */
-	memset(&regs, 0, sizeof(regs));
-	regs.b4 = (unsigned long) arg;
-	regs.a6 = (unsigned long) fn;
-	regs.pc = (unsigned long) kernel_thread_helper;
-	local_save_flags(regs.csr);
-	regs.csr |= 1;
-	regs.tsr = 5; /* Set GEE and GIE in TSR */
-
-	/* Ok, create the new process.. */
-	return do_fork(flags | CLONE_VM | CLONE_UNTRACED, -1, &regs,
-		       0, NULL, NULL);
-}
-EXPORT_SYMBOL(kernel_thread);
-
 void flush_thread(void)
 {
 }
@@ -191,22 +161,24 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
 
 	childregs = task_pt_regs(p);
 
-	*childregs = *regs;
-	childregs->a4 = 0;
-
-	if (usp == -1)
+	if (!regs) {
 		/* case of  __kernel_thread: we return to supervisor space */
+		memset(childregs, 0, sizeof(struct pt_regs));
 		childregs->sp = (unsigned long)(childregs + 1);
-	else
+		p->thread.pc = (unsigned long) ret_from_kernel_thread;
+		childregs->a0 = usp;		/* function */
+		childregs->a1 = ustk_size;	/* argument */
+	} else {
 		/* Otherwise use the given stack */
+		*childregs = *regs;
 		childregs->sp = usp;
+		p->thread.pc = (unsigned long) ret_from_fork;
+	}
 
 	/* Set usp/ksp */
 	p->thread.usp = childregs->sp;
-	/* switch_to uses stack to save/restore 14 callee-saved regs */
 	thread_saved_ksp(p) = (unsigned long)childregs - 8;
-	p->thread.pc = (unsigned int) ret_from_fork;
-	p->thread.wchan	= (unsigned long) ret_from_fork;
+	p->thread.wchan	= p->thread.pc;
 #ifdef __DSBT__
 	{
 		unsigned long dp;
@@ -221,28 +193,6 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
 	return 0;
 }
 
-/*
- * c6x_execve() executes a new program.
- */
-SYSCALL_DEFINE4(c6x_execve, const char __user *, name,
-		const char __user *const __user *, argv,
-		const char __user *const __user *, envp,
-		struct pt_regs *, regs)
-{
-	int error;
-	char *filename;
-
-	filename = getname(name);
-	error = PTR_ERR(filename);
-	if (IS_ERR(filename))
-		goto out;
-
-	error = do_execve(filename, argv, envp, regs);
-	putname(filename);
-out:
-	return error;
-}
-
 unsigned long get_wchan(struct task_struct *p)
 {
 	return p->thread.wchan;
diff --git a/arch/cris/Kconfig b/arch/cris/Kconfig
index e922154..26160e2 100644
--- a/arch/cris/Kconfig
+++ b/arch/cris/Kconfig
@@ -47,6 +47,7 @@ config CRIS
 	select GENERIC_IOMAP
 	select GENERIC_SMP_IDLE_THREAD if ETRAX_ARCH_V32
 	select GENERIC_CMOS_UPDATE
+	select MODULES_USE_ELF_RELA
 
 config HZ
 	int
@@ -138,11 +139,6 @@ config CRIS_MACH_ARTPEC3
 
 endchoice
 
-config ETRAX_VCS_SIM
-	bool "VCS Simulator"
-	help
-	  Setup hardware to be run in the VCS simulator.
-
 config ETRAX_ARCH_V10
        bool
        default y if ETRAX100LX || ETRAX100LX_V2
diff --git a/arch/cris/arch-v32/drivers/axisflashmap.c b/arch/cris/arch-v32/drivers/axisflashmap.c
index b34438e..1b6ad62 100644
--- a/arch/cris/arch-v32/drivers/axisflashmap.c
+++ b/arch/cris/arch-v32/drivers/axisflashmap.c
@@ -329,7 +329,6 @@ static int __init init_axis_flash(void)
 	}
 #endif
 
-#ifndef CONFIG_ETRAX_VCS_SIM
 	main_mtd = flash_probe();
 	if (main_mtd)
 		printk(KERN_INFO "%s: 0x%08x bytes of NOR flash memory.\n",
@@ -603,34 +602,7 @@ static int __init init_axis_flash(void)
 					"partition %d\n", part);
 		}
 	}
-#endif /* CONFIG_EXTRAX_VCS_SIM */
 
-#ifdef CONFIG_ETRAX_VCS_SIM
-	/* For simulator, always use a RAM partition.
-	 * The rootfs will be found after the kernel in RAM,
-	 * with romfs_start and romfs_end indicating location and size.
-	 */
-	struct mtd_info *mtd_ram;
-
-	mtd_ram = kmalloc(sizeof(struct mtd_info), GFP_KERNEL);
-	if (!mtd_ram) {
-		panic("axisflashmap: Couldn't allocate memory for "
-		      "mtd_info!\n");
-	}
-
-	printk(KERN_INFO "axisflashmap: Adding RAM partition for romfs, "
-	       "at %u, size %u\n",
-	       (unsigned) romfs_start, (unsigned) romfs_length);
-
-	err = mtdram_init_device(mtd_ram, (void *)romfs_start,
-				 romfs_length, "romfs");
-	if (err) {
-		panic("axisflashmap: Could not initialize MTD RAM "
-		      "device!\n");
-	}
-#endif /* CONFIG_EXTRAX_VCS_SIM */
-
-#ifndef CONFIG_ETRAX_VCS_SIM
 	if (aux_mtd) {
 		aux_partition.size = aux_mtd->size;
 		err = mtd_device_register(aux_mtd, &aux_partition, 1);
@@ -639,7 +611,6 @@ static int __init init_axis_flash(void)
 			      "aux mtd device!\n");
 
 	}
-#endif /* CONFIG_EXTRAX_VCS_SIM */
 
 	return err;
 }
diff --git a/arch/cris/arch-v32/drivers/pci/bios.c b/arch/cris/arch-v32/drivers/pci/bios.c
index 5b1ee82..e3dfc72 100644
--- a/arch/cris/arch-v32/drivers/pci/bios.c
+++ b/arch/cris/arch-v32/drivers/pci/bios.c
@@ -97,28 +97,3 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
 		pcibios_enable_irq(dev);
 	return 0;
 }
-
-int pcibios_assign_resources(void)
-{
-	struct pci_dev *dev = NULL;
-	int idx;
-	struct resource *r;
-
-	while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
-		int class = dev->class >> 8;
-
-		/* Don't touch classless devices and host bridges */
-		if (!class || class == PCI_CLASS_BRIDGE_HOST)
-			continue;
-
-		for(idx=0; idx<6; idx++) {
-			r = &dev->resource[idx];
-
-			if (!r->start && r->end)
-				pci_assign_resource(dev, idx);
-		}
-	}
-	return 0;
-}
-
-EXPORT_SYMBOL(pcibios_assign_resources);
diff --git a/arch/cris/arch-v32/kernel/head.S b/arch/cris/arch-v32/kernel/head.S
index 5d502b9..51e3416 100644
--- a/arch/cris/arch-v32/kernel/head.S
+++ b/arch/cris/arch-v32/kernel/head.S
@@ -36,13 +36,6 @@
 	.global nand_boot
 	.global swapper_pg_dir
 
-	;; Dummy section to make it bootable with current VCS simulator
-#ifdef CONFIG_ETRAX_VCS_SIM
-	.section ".boot", "ax"
-	ba tstart
-	nop
-#endif
-
 	.text
 tstart:
 	;; This is the entry point of the kernel. The CPU is currently in
@@ -75,17 +68,10 @@ secondary_cpu_entry: /* Entry point for secondary CPUs */
 		| REG_FIELD(mmu, rw_mm_kbase_hi, base_c, 4)	\
 		| REG_FIELD(mmu, rw_mm_kbase_hi, base_d, 5)     \
 		| REG_FIELD(mmu, rw_mm_kbase_hi, base_b, 0xb), $r0
-#elif !defined(CONFIG_ETRAX_VCS_SIM)
-	move.d	REG_FIELD(mmu, rw_mm_kbase_hi, base_e, 8)	\
-		| REG_FIELD(mmu, rw_mm_kbase_hi, base_c, 4)	\
-		| REG_FIELD(mmu, rw_mm_kbase_hi, base_b, 0xb), $r0
 #else
-	;; Map the virtual DRAM to the RW eprom area at address 0.
-	;; Also map 0xa for the hook calls,
 	move.d	REG_FIELD(mmu, rw_mm_kbase_hi, base_e, 8)	\
 		| REG_FIELD(mmu, rw_mm_kbase_hi, base_c, 4)	\
-		| REG_FIELD(mmu, rw_mm_kbase_hi, base_b, 0xb)   \
-		| REG_FIELD(mmu, rw_mm_kbase_hi, base_a, 0xa), $r0
+		| REG_FIELD(mmu, rw_mm_kbase_hi, base_b, 0xb), $r0
 #endif
 
 	;; Temporary map of 0x40 -> 0x40 and 0x00 -> 0x00.
@@ -126,27 +112,6 @@ secondary_cpu_entry: /* Entry point for secondary CPUs */
 		| REG_STATE(mmu, rw_mm_cfg, seg_2, page)	\
 		| REG_STATE(mmu, rw_mm_cfg, seg_1, page)	\
 		| REG_STATE(mmu, rw_mm_cfg, seg_0, linear), $r2
-#elif !defined(CONFIG_ETRAX_VCS_SIM)
-	move.d	REG_STATE(mmu, rw_mm_cfg, we, on)		\
-		| REG_STATE(mmu, rw_mm_cfg, acc, on)		\
-		| REG_STATE(mmu, rw_mm_cfg, ex, on)		\
-		| REG_STATE(mmu, rw_mm_cfg, inv, on)		\
-		| REG_STATE(mmu, rw_mm_cfg, seg_f, linear)	\
-		| REG_STATE(mmu, rw_mm_cfg, seg_e, linear)	\
-		| REG_STATE(mmu, rw_mm_cfg, seg_d, page)	\
-		| REG_STATE(mmu, rw_mm_cfg, seg_c, linear)	\
-		| REG_STATE(mmu, rw_mm_cfg, seg_b, linear)	\
-		| REG_STATE(mmu, rw_mm_cfg, seg_a, page)	\
-		| REG_STATE(mmu, rw_mm_cfg, seg_9, page)	\
-		| REG_STATE(mmu, rw_mm_cfg, seg_8, page)	\
-		| REG_STATE(mmu, rw_mm_cfg, seg_7, page)	\
-		| REG_STATE(mmu, rw_mm_cfg, seg_6, page)	\
-		| REG_STATE(mmu, rw_mm_cfg, seg_5, page)	\
-		| REG_STATE(mmu, rw_mm_cfg, seg_4, linear)	\
-		| REG_STATE(mmu, rw_mm_cfg, seg_3, page)	\
-		| REG_STATE(mmu, rw_mm_cfg, seg_2, page)	\
-		| REG_STATE(mmu, rw_mm_cfg, seg_1, page)	\
-		| REG_STATE(mmu, rw_mm_cfg, seg_0, linear), $r2
 #else
 	move.d	REG_STATE(mmu, rw_mm_cfg, we, on)		\
 		| REG_STATE(mmu, rw_mm_cfg, acc, on)		\
@@ -157,7 +122,7 @@ secondary_cpu_entry: /* Entry point for secondary CPUs */
 		| REG_STATE(mmu, rw_mm_cfg, seg_d, page)	\
 		| REG_STATE(mmu, rw_mm_cfg, seg_c, linear)	\
 		| REG_STATE(mmu, rw_mm_cfg, seg_b, linear)	\
-		| REG_STATE(mmu, rw_mm_cfg, seg_a, linear)	\
+		| REG_STATE(mmu, rw_mm_cfg, seg_a, page)	\
 		| REG_STATE(mmu, rw_mm_cfg, seg_9, page)	\
 		| REG_STATE(mmu, rw_mm_cfg, seg_8, page)	\
 		| REG_STATE(mmu, rw_mm_cfg, seg_7, page)	\
@@ -226,7 +191,6 @@ master_cpu:
 	move.d secondary_cpu_entry, $r1
 	move.d $r1, [$r0]
 #endif
-#ifndef CONFIG_ETRAX_VCS_SIM
 	; Check if starting from DRAM (network->RAM boot or unpacked
 	; compressed kernel), or directly from flash.
 	lapcq	., $r0
@@ -234,7 +198,6 @@ master_cpu:
 	cmp.d	0x10000, $r0	; Arbitrary, something above this code.
 	blo	_inflash0
 	nop
-#endif
 
 	jump	_inram		; Jump to cached RAM.
 	nop
@@ -326,7 +289,6 @@ move_cramfs:
 	move.d	romfs_length, $r1
 	move.d	$r0, [$r1]
 
-#ifndef CONFIG_ETRAX_VCS_SIM
 	;; The kernel could have been unpacked to DRAM by the loader, but
 	;; the cramfs image could still be in the flash immediately
 	;; following the compressed kernel image. The loader passes the address
@@ -335,10 +297,6 @@ move_cramfs:
 	cmp.d	0x0ffffff8, $r9
 	bhs	_no_romfs_in_flash ; R9 points outside the flash area.
 	nop
-#else
-	ba _no_romfs_in_flash
-	nop
-#endif
 	;; cramfs rootfs might to be in flash. Check for it.
 	move.d	[$r9], $r0	; cramfs_super.magic
 	cmp.d	CRAMFS_MAGIC, $r0
@@ -396,7 +354,6 @@ _no_romfs_in_flash:
 	move.d	romfs_length, $r3
 	move.d	$r2, [$r3]	; store size at romfs_length
 
-#ifndef CONFIG_ETRAX_VCS_SIM
 	add.d	$r2, $r0	; copy from end and downwards
 	add.d	$r2, $r1
 
@@ -410,7 +367,6 @@ _no_romfs_in_flash:
 	subq	1, $r2
 	bne	1b
 	nop
-#endif
 
 4:
 	;; BSS move done.
@@ -455,7 +411,6 @@ no_command_line:
 	move.d	etrax_irv, $r1	; Set the exception base register and pointer.
 	move.d	$r0, [$r1]
 
-#ifndef CONFIG_ETRAX_VCS_SIM
 	;; Clear the BSS region from _bss_start to _end.
 	move.d	__bss_start, $r0
 	move.d	_end, $r1
@@ -463,15 +418,6 @@ no_command_line:
 	cmp.d	$r1, $r0
 	blo 1b
 	nop
-#endif
-
-#ifdef CONFIG_ETRAX_VCS_SIM
-	/* Set the watchdog timeout to something big. Will be removed when */
-	/* watchdog can be disabled with command line option */
-	move.d  0x7fffffff, $r10
-	jsr     CPU_WATCHDOG_TIMEOUT
-	nop
-#endif
 
 	; Initialize registers to increase determinism
 	move.d __bss_start, $r0
diff --git a/arch/cris/arch-v32/kernel/kgdb.c b/arch/cris/arch-v32/kernel/kgdb.c
index 8c1d35c..b06813a 100644
--- a/arch/cris/arch-v32/kernel/kgdb.c
+++ b/arch/cris/arch-v32/kernel/kgdb.c
@@ -381,23 +381,9 @@ static int read_register(char regno, unsigned int *valptr);
 /* Serial port, reads one character. ETRAX 100 specific. from debugport.c */
 int getDebugChar(void);
 
-#ifdef CONFIG_ETRAX_VCS_SIM
-int getDebugChar(void)
-{
-  return socketread();
-}
-#endif
-
 /* Serial port, writes one character. ETRAX 100 specific. from debugport.c */
 void putDebugChar(int val);
 
-#ifdef CONFIG_ETRAX_VCS_SIM
-void putDebugChar(int val)
-{
-  socketwrite((char *)&val, 1);
-}
-#endif
-
 /* Returns the integer equivalent of a hexadecimal character. */
 static int hex(char ch);
 
diff --git a/arch/cris/arch-v32/mach-a3/Makefile b/arch/cris/arch-v32/mach-a3/Makefile
index 41fa6a6..d366e08 100644
--- a/arch/cris/arch-v32/mach-a3/Makefile
+++ b/arch/cris/arch-v32/mach-a3/Makefile
@@ -1,10 +1,8 @@
-# $Id: Makefile,v 1.3 2007/03/13 11:57:46 starvik Exp $
 #
 # Makefile for the linux kernel.
 #
 
 obj-y   := dma.o pinmux.o io.o arbiter.o
-obj-$(CONFIG_ETRAX_VCS_SIM) += vcs_hook.o
 obj-$(CONFIG_CPU_FREQ)   += cpufreq.o
 
 clean:
diff --git a/arch/cris/arch-v32/mach-a3/vcs_hook.c b/arch/cris/arch-v32/mach-a3/vcs_hook.c
deleted file mode 100644
index 58b1a54..0000000
--- a/arch/cris/arch-v32/mach-a3/vcs_hook.c
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Simulator hook mechanism
- */
-
-#include "vcs_hook.h"
-#include <asm/io.h>
-#include <stdarg.h>
-
-#define HOOK_TRIG_ADDR      0xb7000000
-#define HOOK_MEM_BASE_ADDR  0xce000000
-
-static volatile unsigned *hook_base;
-
-#define HOOK_DATA(offset) hook_base[offset]
-#define VHOOK_DATA(offset) hook_base[offset]
-#define HOOK_TRIG(funcid) \
-	do { \
-		*((unsigned *) HOOK_TRIG_ADDR) = funcid; \
-	} while (0)
-#define HOOK_DATA_BYTE(offset) ((unsigned char *)hook_base)[offset]
-
-static void hook_init(void)
-{
-	static int first = 1;
-	if (first) {
-		first = 0;
-		hook_base = ioremap(HOOK_MEM_BASE_ADDR, 8192);
-	}
-}
-
-static unsigned hook_trig(unsigned id)
-{
-	unsigned ret;
-
-	/* preempt_disable(); */
-
-	/* Dummy read from mem to make sure data has propagated to memory
-	 * before trigging */
-	ret = *hook_base;
-
-	/* trigger hook */
-	HOOK_TRIG(id);
-
-	/* wait for call to finish */
-	while (VHOOK_DATA(0) > 0) ;
-
-	/* extract return value */
-
-	ret = VHOOK_DATA(1);
-
-	return ret;
-}
-
-int hook_call(unsigned id, unsigned pcnt, ...)
-{
-	va_list ap;
-	int i;
-	unsigned ret;
-
-	hook_init();
-
-	HOOK_DATA(0) = id;
-
-	va_start(ap, pcnt);
-	for (i = 1; i <= pcnt; i++)
-		HOOK_DATA(i) = va_arg(ap, unsigned);
-	va_end(ap);
-
-	ret = hook_trig(id);
-
-	return ret;
-}
-
-int hook_call_str(unsigned id, unsigned size, const char *str)
-{
-	int i;
-	unsigned ret;
-
-	hook_init();
-
-	HOOK_DATA(0) = id;
-	HOOK_DATA(1) = size;
-
-	for (i = 0; i < size; i++)
-		HOOK_DATA_BYTE(8 + i) = str[i];
-	HOOK_DATA_BYTE(8 + i) = 0;
-
-	ret = hook_trig(id);
-
-	return ret;
-}
-
-void print_str(const char *str)
-{
-	int i;
-	/* find null at end of string */
-	for (i = 1; str[i]; i++) ;
-	hook_call(hook_print_str, i, str);
-}
-
-void CPU_WATCHDOG_TIMEOUT(unsigned t)
-{
-}
diff --git a/arch/cris/arch-v32/mach-a3/vcs_hook.h b/arch/cris/arch-v32/mach-a3/vcs_hook.h
deleted file mode 100644
index 8b73d0e..0000000
--- a/arch/cris/arch-v32/mach-a3/vcs_hook.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Simulator hook call mechanism
- */
-
-#ifndef __hook_h__
-#define __hook_h__
-
-int hook_call(unsigned id, unsigned pcnt, ...);
-int hook_call_str(unsigned id, unsigned size, const char *str);
-
-enum hook_ids {
-  hook_debug_on = 1,
-  hook_debug_off,
-  hook_stop_sim_ok,
-  hook_stop_sim_fail,
-  hook_alloc_shared,
-  hook_ptr_shared,
-  hook_free_shared,
-  hook_file2shared,
-  hook_cmp_shared,
-  hook_print_params,
-  hook_sim_time,
-  hook_stop_sim,
-  hook_kick_dog,
-  hook_dog_timeout,
-  hook_rand,
-  hook_srand,
-  hook_rand_range,
-  hook_print_str,
-  hook_print_hex,
-  hook_cmp_offset_shared,
-  hook_fill_random_shared,
-  hook_alloc_random_data,
-  hook_calloc_random_data,
-  hook_print_int,
-  hook_print_uint,
-  hook_fputc,
-  hook_init_fd,
-  hook_sbrk,
-  hook_print_context_descr,
-  hook_print_data_descr,
-  hook_print_group_descr,
-  hook_fill_shared,
-  hook_sl_srand,
-  hook_sl_rand_irange,
-  hook_sl_rand_urange,
-  hook_sl_sh_malloc_aligned,
-  hook_sl_sh_calloc_aligned,
-  hook_sl_sh_alloc_random_data,
-  hook_sl_sh_file2mem,
-  hook_sl_vera_mbox_handle,
-  hook_sl_vera_mbox_put,
-  hook_sl_vera_mbox_get,
-  hook_sl_system,
-  hook_sl_sh_hexdump
-};
-
-#endif
diff --git a/arch/cris/arch-v32/mach-fs/Makefile b/arch/cris/arch-v32/mach-fs/Makefile
index 41fa6a6..d366e08 100644
--- a/arch/cris/arch-v32/mach-fs/Makefile
+++ b/arch/cris/arch-v32/mach-fs/Makefile
@@ -1,10 +1,8 @@
-# $Id: Makefile,v 1.3 2007/03/13 11:57:46 starvik Exp $
 #
 # Makefile for the linux kernel.
 #
 
 obj-y   := dma.o pinmux.o io.o arbiter.o
-obj-$(CONFIG_ETRAX_VCS_SIM) += vcs_hook.o
 obj-$(CONFIG_CPU_FREQ)   += cpufreq.o
 
 clean:
diff --git a/arch/cris/arch-v32/mach-fs/vcs_hook.c b/arch/cris/arch-v32/mach-fs/vcs_hook.c
deleted file mode 100644
index b11594a..0000000
--- a/arch/cris/arch-v32/mach-fs/vcs_hook.c
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Call simulator hook. This is the part running in the
- * simulated program.
- */
-
-#include "vcs_hook.h"
-#include <stdarg.h>
-#include <arch-v32/hwregs/reg_map.h>
-#include <arch-v32/hwregs/intr_vect_defs.h>
-
-#define HOOK_TRIG_ADDR     0xb7000000	/* hook cvlog model reg address */
-#define HOOK_MEM_BASE_ADDR 0xa0000000	/* csp4 (shared mem) base addr */
-
-#define HOOK_DATA(offset) ((unsigned *)HOOK_MEM_BASE_ADDR)[offset]
-#define VHOOK_DATA(offset) ((volatile unsigned *)HOOK_MEM_BASE_ADDR)[offset]
-#define HOOK_TRIG(funcid) \
-	do { \
-		*((unsigned *) HOOK_TRIG_ADDR) = funcid; \
-	} while (0)
-#define HOOK_DATA_BYTE(offset) ((unsigned char *)HOOK_MEM_BASE_ADDR)[offset]
-
-int hook_call(unsigned id, unsigned pcnt, ...)
-{
-	va_list ap;
-	unsigned i;
-	unsigned ret;
-#ifdef USING_SOS
-	PREEMPT_OFF_SAVE();
-#endif
-
-	/* pass parameters */
-	HOOK_DATA(0) = id;
-
-	/* Have to make hook_print_str a special case since we call with a
-	 * parameter of byte type. Should perhaps be a separate
-	 * hook_call. */
-
-	if (id == hook_print_str) {
-		int i;
-		char *str;
-
-		HOOK_DATA(1) = pcnt;
-
-		va_start(ap, pcnt);
-		str = (char *)va_arg(ap, unsigned);
-
-		for (i = 0; i != pcnt; i++)
-			HOOK_DATA_BYTE(8 + i) = str[i];
-
-		HOOK_DATA_BYTE(8 + i) = 0;	/* null byte */
-	} else {
-		va_start(ap, pcnt);
-		for (i = 1; i <= pcnt; i++)
-			HOOK_DATA(i) = va_arg(ap, unsigned);
-		va_end(ap);
-	}
-
-	/* read from mem to make sure data has propagated to memory before
-	 * trigging */
-	ret = *((volatile unsigned *)HOOK_MEM_BASE_ADDR);
-
-	/* trigger hook */
-	HOOK_TRIG(id);
-
-	/* wait for call to finish */
-	while (VHOOK_DATA(0) > 0) ;
-
-	/* extract return value */
-
-	ret = VHOOK_DATA(1);
-
-#ifdef USING_SOS
-	PREEMPT_RESTORE();
-#endif
-	return ret;
-}
-
-unsigned hook_buf(unsigned i)
-{
-	return (HOOK_DATA(i));
-}
-
-void print_str(const char *str)
-{
-	int i;
-	/* find null at end of string */
-	for (i = 1; str[i]; i++) ;
-	hook_call(hook_print_str, i, str);
-}
-
-void CPU_KICK_DOG(void)
-{
-	(void)hook_call(hook_kick_dog, 0);
-}
-
-void CPU_WATCHDOG_TIMEOUT(unsigned t)
-{
-	(void)hook_call(hook_dog_timeout, 1, t);
-}
-
diff --git a/arch/cris/arch-v32/mach-fs/vcs_hook.h b/arch/cris/arch-v32/mach-fs/vcs_hook.h
deleted file mode 100644
index c000b9f..0000000
--- a/arch/cris/arch-v32/mach-fs/vcs_hook.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Call simulator hook functions
- */
-
-#ifndef HOOK_H
-#define HOOK_H
-
-int hook_call(unsigned id, unsigned pcnt, ...);
-
-enum hook_ids {
-  hook_debug_on = 1,
-  hook_debug_off,
-  hook_stop_sim_ok,
-  hook_stop_sim_fail,
-  hook_alloc_shared,
-  hook_ptr_shared,
-  hook_free_shared,
-  hook_file2shared,
-  hook_cmp_shared,
-  hook_print_params,
-  hook_sim_time,
-  hook_stop_sim,
-  hook_kick_dog,
-  hook_dog_timeout,
-  hook_rand,
-  hook_srand,
-  hook_rand_range,
-  hook_print_str,
-  hook_print_hex,
-  hook_cmp_offset_shared,
-  hook_fill_random_shared,
-  hook_alloc_random_data,
-  hook_calloc_random_data,
-  hook_print_int,
-  hook_print_uint,
-  hook_fputc,
-  hook_init_fd,
-  hook_sbrk
-
-};
-
-#endif
diff --git a/arch/cris/arch-v32/mm/init.c b/arch/cris/arch-v32/mm/init.c
index 0768bc4..3deca52 100644
--- a/arch/cris/arch-v32/mm/init.c
+++ b/arch/cris/arch-v32/mm/init.c
@@ -73,11 +73,7 @@ void __init cris_mmu_init(void)
 #endif
 		       REG_STATE(mmu, rw_mm_cfg, seg_c, linear) |
 		       REG_STATE(mmu, rw_mm_cfg, seg_b, linear) |
-#ifndef CONFIG_ETRAX_VCS_SIM
                        REG_STATE(mmu, rw_mm_cfg, seg_a, page)   |
-#else
-		       REG_STATE(mmu, rw_mm_cfg, seg_a, linear) |
-#endif
 		       REG_STATE(mmu, rw_mm_cfg, seg_9, page)   |
 		       REG_STATE(mmu, rw_mm_cfg, seg_8, page)   |
 		       REG_STATE(mmu, rw_mm_cfg, seg_7, page)   |
@@ -100,11 +96,7 @@ void __init cris_mmu_init(void)
 #endif
                          REG_FIELD(mmu, rw_mm_kbase_hi, base_c, 0x4) |
 			 REG_FIELD(mmu, rw_mm_kbase_hi, base_b, 0xb) |
-#ifndef CONFIG_ETRAX_VCS_SIM
 			 REG_FIELD(mmu, rw_mm_kbase_hi, base_a, 0x0) |
-#else
-                         REG_FIELD(mmu, rw_mm_kbase_hi, base_a, 0xa) |
-#endif
 			 REG_FIELD(mmu, rw_mm_kbase_hi, base_9, 0x0) |
 			 REG_FIELD(mmu, rw_mm_kbase_hi, base_8, 0x0));
 
diff --git a/arch/cris/include/arch-v32/arch/page.h b/arch/cris/include/arch-v32/arch/page.h
index 20f1b48..e5b5aab 100644
--- a/arch/cris/include/arch-v32/arch/page.h
+++ b/arch/cris/include/arch-v32/arch/page.h
@@ -11,13 +11,8 @@
  * selected bit it's possible to convert between KSEG_x and 0x40000000 where the
  * DRAM really resides. DRAM is virtually at 0xc.
  */
-#ifndef CONFIG_ETRAX_VCS_SIM
 #define __pa(x) ((unsigned long)(x) & 0x7fffffff)
 #define __va(x) ((void *)((unsigned long)(x) | 0x80000000))
-#else
-#define __pa(x) ((unsigned long)(x) & 0x3fffffff)
-#define __va(x) ((void *)((unsigned long)(x) | 0xc0000000))
-#endif
 
 #define VM_STACK_DEFAULT_FLAGS	(VM_READ | VM_WRITE | \
 				 VM_MAYREAD | VM_MAYWRITE)
diff --git a/arch/cris/include/arch-v32/arch/processor.h b/arch/cris/include/arch-v32/arch/processor.h
index 9603c90..a024b7d 100644
--- a/arch/cris/include/arch-v32/arch/processor.h
+++ b/arch/cris/include/arch-v32/arch/processor.h
@@ -21,13 +21,9 @@ struct thread_struct {
 
 /*
  * User-space process size. This is hardcoded into a few places, so don't
- * changed it unless everything's clear!
+ * change it unless everything's clear!
  */
-#ifndef CONFIG_ETRAX_VCS_SIM
 #define TASK_SIZE	(0xB0000000UL)
-#else
-#define TASK_SIZE	(0xA0000000UL)
-#endif
 
 /* CCS I=1, enable interrupts. */
 #define INIT_THREAD { 0, 0, (1 << I_CCS_BITNR) }
diff --git a/arch/cris/include/arch-v32/mach-fs/mach/startup.inc b/arch/cris/include/arch-v32/mach-fs/mach/startup.inc
index dd1abbd..96c3b0f 100644
--- a/arch/cris/include/arch-v32/mach-fs/mach/startup.inc
+++ b/arch/cris/include/arch-v32/mach-fs/mach/startup.inc
@@ -71,12 +71,6 @@
 	move.d   REG_ADDR(bif_core, regi_bif_core, rw_grp4_cfg), $r0
 	move.d   CONFIG_ETRAX_MEM_GRP4_CONFIG, $r1
 	move.d   $r1, [$r0]
-#ifdef CONFIG_ETRAX_VCS_SIM
-	;; Set up minimal flash waitstates
-	move.d 0, $r10
-	move.d REG_ADDR(bif_core, regi_bif_core, rw_grp1_cfg), $r11
-	move.d $r10, [$r11]
-#endif
 	.endm
 
 #endif
diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild
index 04d02a5..f5ae9de 100644
--- a/arch/cris/include/asm/Kbuild
+++ b/arch/cris/include/asm/Kbuild
@@ -7,3 +7,6 @@ header-y += ethernet.h
 header-y += etraxgpio.h
 header-y += rs485.h
 header-y += sync_serial.h
+
+generic-y += module.h
+generic-y += exec.h
diff --git a/arch/cris/include/asm/elf.h b/arch/cris/include/asm/elf.h
index 8a3d8e2..8182f2d 100644
--- a/arch/cris/include/asm/elf.h
+++ b/arch/cris/include/asm/elf.h
@@ -86,6 +86,7 @@ typedef unsigned long elf_fpregset_t;
 
 #define ELF_PLATFORM  (NULL)
 
-#define SET_PERSONALITY(ex) set_personality(PER_LINUX)
+#define SET_PERSONALITY(ex) \
+	set_personality(PER_LINUX | (current->personality & (~PER_MASK)))
 
 #endif
diff --git a/arch/cris/include/asm/exec.h b/arch/cris/include/asm/exec.h
deleted file mode 100644
index 9665dab..0000000
--- a/arch/cris/include/asm/exec.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __ASM_CRIS_EXEC_H
-#define __ASM_CRIS_EXEC_H
-
-#define arch_align_stack(x) (x)
-
-#endif /* __ASM_CRIS_EXEC_H */
diff --git a/arch/cris/include/asm/io.h b/arch/cris/include/asm/io.h
index 32567bc..ac12ae2 100644
--- a/arch/cris/include/asm/io.h
+++ b/arch/cris/include/asm/io.h
@@ -133,12 +133,39 @@ static inline void writel(unsigned int b, volatile void __iomem *addr)
 #define insb(port,addr,count) (cris_iops ? cris_iops->read_io(port,addr,1,count) : 0)
 #define insw(port,addr,count) (cris_iops ? cris_iops->read_io(port,addr,2,count) : 0)
 #define insl(port,addr,count) (cris_iops ? cris_iops->read_io(port,addr,4,count) : 0)
-#define outb(data,port) if (cris_iops) cris_iops->write_io(port,(void*)(unsigned)data,1,1)
-#define outw(data,port) if (cris_iops) cris_iops->write_io(port,(void*)(unsigned)data,2,1)
-#define outl(data,port) if (cris_iops) cris_iops->write_io(port,(void*)(unsigned)data,4,1)
-#define outsb(port,addr,count) if(cris_iops) cris_iops->write_io(port,(void*)addr,1,count)
-#define outsw(port,addr,count) if(cris_iops) cris_iops->write_io(port,(void*)addr,2,count)
-#define outsl(port,addr,count) if(cris_iops) cris_iops->write_io(port,(void*)addr,3,count)
+static inline void outb(unsigned char data, unsigned int port)
+{
+	if (cris_iops)
+		cris_iops->write_io(port, (void *) &data, 1, 1);
+}
+static inline void outw(unsigned short data, unsigned int port)
+{
+	if (cris_iops)
+		cris_iops->write_io(port, (void *) &data, 2, 1);
+}
+static inline void outl(unsigned int data, unsigned int port)
+{
+	if (cris_iops)
+		cris_iops->write_io(port, (void *) &data, 4, 1);
+}
+static inline void outsb(unsigned int port, const void *addr,
+			 unsigned long count)
+{
+	if (cris_iops)
+		cris_iops->write_io(port, (void *)addr, 1, count);
+}
+static inline void outsw(unsigned int port, const void *addr,
+			 unsigned long count)
+{
+	if (cris_iops)
+		cris_iops->write_io(port, (void *)addr, 2, count);
+}
+static inline void outsl(unsigned int port, const void *addr,
+			 unsigned long count)
+{
+	if (cris_iops)
+		cris_iops->write_io(port, (void *)addr, 4, count);
+}
 
 /*
  * Convert a physical pointer to a virtual kernel pointer for /dev/mem
diff --git a/arch/cris/include/asm/module.h b/arch/cris/include/asm/module.h
deleted file mode 100644
index 7ee7231..0000000
--- a/arch/cris/include/asm/module.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef _ASM_CRIS_MODULE_H
-#define _ASM_CRIS_MODULE_H
-/* cris is simple */
-struct mod_arch_specific { };
-
-#define Elf_Shdr Elf32_Shdr
-#define Elf_Sym Elf32_Sym
-#define Elf_Ehdr Elf32_Ehdr
-#endif /* _ASM_CRIS_MODULE_H */
diff --git a/arch/cris/include/asm/pci.h b/arch/cris/include/asm/pci.h
index 9f1cd56..146da90 100644
--- a/arch/cris/include/asm/pci.h
+++ b/arch/cris/include/asm/pci.h
@@ -19,7 +19,6 @@ extern unsigned long pci_mem_start;
 
 void pcibios_config_init(void);
 struct pci_bus * pcibios_scan_root(int bus);
-int pcibios_assign_resources(void);
 
 void pcibios_set_master(struct pci_dev *dev);
 void pcibios_penalize_isa_irq(int irq);
diff --git a/arch/cris/include/asm/thread_info.h b/arch/cris/include/asm/thread_info.h
index 5b1c448..07c8c40 100644
--- a/arch/cris/include/asm/thread_info.h
+++ b/arch/cris/include/asm/thread_info.h
@@ -78,15 +78,12 @@ struct thread_info {
 #define TIF_SIGPENDING		2	/* signal pending */
 #define TIF_NEED_RESCHED	3	/* rescheduling necessary */
 #define TIF_RESTORE_SIGMASK	9	/* restore signal mask in do_signal() */
-#define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_MEMDIE		17	/* is terminating due to OOM killer */
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
 #define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
-#define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
-#define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
 
 #define _TIF_WORK_MASK		0x0000FFFE	/* work to do on interrupt/exception return */
 #define _TIF_ALLWORK_MASK	0x0000FFFF	/* work to do on any return to u-space */
diff --git a/arch/cris/kernel/process.c b/arch/cris/kernel/process.c
index 66fd017..7f65be6 100644
--- a/arch/cris/kernel/process.c
+++ b/arch/cris/kernel/process.c
@@ -25,6 +25,7 @@
 #include <linux/elfcore.h>
 #include <linux/mqueue.h>
 #include <linux/reboot.h>
+#include <linux/rcupdate.h>
 
 //#define DEBUG
 
@@ -74,6 +75,7 @@ void cpu_idle (void)
 {
 	/* endless idle loop with no priority at all */
 	while (1) {
+		rcu_idle_enter();
 		while (!need_resched()) {
 			void (*idle)(void);
 			/*
@@ -86,6 +88,7 @@ void cpu_idle (void)
 				idle = default_idle;
 			idle();
 		}
+		rcu_idle_exit();
 		schedule_preempt_disabled();
 	}
 }
diff --git a/arch/cris/mm/fault.c b/arch/cris/mm/fault.c
index 45fd542..73312ab 100644
--- a/arch/cris/mm/fault.c
+++ b/arch/cris/mm/fault.c
@@ -186,6 +186,7 @@ retry:
 			tsk->min_flt++;
 		if (fault & VM_FAULT_RETRY) {
 			flags &= ~FAULT_FLAG_ALLOW_RETRY;
+			flags |= FAULT_FLAG_TRIED;
 
 			/*
 			 * No need to up_read(&mm->mmap_sem) as we would
diff --git a/arch/frv/Kconfig b/arch/frv/Kconfig
index 971c0a1..a27a1c6 100644
--- a/arch/frv/Kconfig
+++ b/arch/frv/Kconfig
@@ -10,6 +10,7 @@ config FRV
 	select ARCH_HAVE_NMI_SAFE_CMPXCHG
 	select GENERIC_CPU_DEVICES
 	select ARCH_WANT_IPC_PARSE_VERSION
+	select GENERIC_KERNEL_THREAD
 
 config ZONE_DMA
 	bool
diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild
index 5be6663..32c1646 100644
--- a/arch/frv/include/asm/Kbuild
+++ b/arch/frv/include/asm/Kbuild
@@ -2,3 +2,4 @@ include include/asm-generic/Kbuild.asm
 
 header-y += registers.h
 header-y += termios.h
+generic-y += exec.h
diff --git a/arch/frv/include/asm/elf.h b/arch/frv/include/asm/elf.h
index c381980..9ccbc80 100644
--- a/arch/frv/include/asm/elf.h
+++ b/arch/frv/include/asm/elf.h
@@ -137,6 +137,7 @@ do {											\
 
 #define ELF_PLATFORM  (NULL)
 
-#define SET_PERSONALITY(ex) set_personality(PER_LINUX)
+#define SET_PERSONALITY(ex) \
+	set_personality(PER_LINUX | (current->personality & (~PER_MASK)))
 
 #endif
diff --git a/arch/frv/include/asm/exec.h b/arch/frv/include/asm/exec.h
deleted file mode 100644
index 65c9130..0000000
--- a/arch/frv/include/asm/exec.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/* FR-V CPU executable handling
- *
- * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@redhat.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#ifndef _ASM_EXEC_H
-#define _ASM_EXEC_H
-
-#define arch_align_stack(x) (x)
-
-#endif /* _ASM_EXEC_H */
diff --git a/arch/frv/include/asm/module.h b/arch/frv/include/asm/module.h
index 3d5c636..a8848f0 100644
--- a/arch/frv/include/asm/module.h
+++ b/arch/frv/include/asm/module.h
@@ -11,13 +11,7 @@
 #ifndef _ASM_MODULE_H
 #define _ASM_MODULE_H
 
-struct mod_arch_specific
-{
-};
-
-#define Elf_Shdr	Elf32_Shdr
-#define Elf_Sym		Elf32_Sym
-#define Elf_Ehdr	Elf32_Ehdr
+#include <asm-generic/module.h>
 
 /*
  * Include the architecture version.
diff --git a/arch/frv/include/asm/processor.h b/arch/frv/include/asm/processor.h
index dccb9d1..a34f309 100644
--- a/arch/frv/include/asm/processor.h
+++ b/arch/frv/include/asm/processor.h
@@ -92,14 +92,12 @@ extern struct task_struct *__kernel_current_task;
 
 /*
  * do necessary setup to start up a newly executed thread.
- * - need to discard the frame stacked by init() invoking the execve syscall
  */
 #define start_thread(_regs, _pc, _usp)			\
 do {							\
-	__frame = __kernel_frame0_ptr;			\
-	__frame->pc	= (_pc);			\
-	__frame->psr	&= ~PSR_S;			\
-	__frame->sp	= (_usp);			\
+	_regs->pc	= (_pc);			\
+	_regs->psr	&= ~PSR_S;			\
+	_regs->sp	= (_usp);			\
 } while(0)
 
 /* Free all resources held by a thread. */
@@ -107,7 +105,6 @@ static inline void release_thread(struct task_struct *dead_task)
 {
 }
 
-extern asmlinkage int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
 extern asmlinkage void save_user_regs(struct user_context *target);
 extern asmlinkage void *restore_user_regs(const struct user_context *target, ...);
 
diff --git a/arch/frv/include/asm/ptrace.h b/arch/frv/include/asm/ptrace.h
index ef6635c..bd534b2 100644
--- a/arch/frv/include/asm/ptrace.h
+++ b/arch/frv/include/asm/ptrace.h
@@ -76,6 +76,7 @@ register struct pt_regs *__frame asm("gr28");
 #define user_mode(regs)			(!((regs)->psr & PSR_S))
 #define instruction_pointer(regs)	((regs)->pc)
 #define user_stack_pointer(regs)	((regs)->sp)
+#define current_pt_regs()		(__frame)
 
 extern unsigned long user_stack(const struct pt_regs *);
 #define profile_pc(regs) ((regs)->pc)
diff --git a/arch/frv/include/asm/thread_info.h b/arch/frv/include/asm/thread_info.h
index 0ff03a3..bebd7ea 100644
--- a/arch/frv/include/asm/thread_info.h
+++ b/arch/frv/include/asm/thread_info.h
@@ -94,7 +94,6 @@ register struct thread_info *__current_thread_info asm("gr15");
 #define TIF_NEED_RESCHED	3	/* rescheduling necessary */
 #define TIF_SINGLESTEP		4	/* restore singlestep on return to user mode */
 #define TIF_RESTORE_SIGMASK	5	/* restore signal mask in do_signal() */
-#define TIF_POLLING_NRFLAG	6	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_MEMDIE		7	/* is terminating due to OOM killer */
 
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
@@ -102,8 +101,6 @@ register struct thread_info *__current_thread_info asm("gr15");
 #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1 << TIF_NEED_RESCHED)
 #define _TIF_SINGLESTEP		(1 << TIF_SINGLESTEP)
-#define _TIF_RESTORE_SIGMASK	(1 << TIF_RESTORE_SIGMASK)
-#define _TIF_POLLING_NRFLAG	(1 << TIF_POLLING_NRFLAG)
 
 /* work to do on interrupt/exception return */
 #define _TIF_WORK_MASK		\
diff --git a/arch/frv/include/asm/unistd.h b/arch/frv/include/asm/unistd.h
index 67f23a3..b6b07e5 100644
--- a/arch/frv/include/asm/unistd.h
+++ b/arch/frv/include/asm/unistd.h
@@ -372,6 +372,8 @@
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_RT_SIGACTION
 #define __ARCH_WANT_SYS_RT_SIGSUSPEND
+#define __ARCH_WANT_SYS_EXECVE
+#define __ARCH_WANT_KERNEL_EXECVE
 
 /*
  * "Conditional" syscalls
diff --git a/arch/frv/kernel/Makefile b/arch/frv/kernel/Makefile
index ad4087b..3cbb329 100644
--- a/arch/frv/kernel/Makefile
+++ b/arch/frv/kernel/Makefile
@@ -7,8 +7,8 @@ heads-$(CONFIG_MMU)		:= head-mmu-fr451.o
 
 extra-y:= head.o vmlinux.lds
 
-obj-y := $(heads-y) entry.o entry-table.o break.o switch_to.o kernel_thread.o \
-	 kernel_execve.o process.o traps.o ptrace.o signal.o dma.o \
+obj-y := $(heads-y) entry.o entry-table.o break.o switch_to.o \
+	 process.o traps.o ptrace.o signal.o dma.o \
 	 sys_frv.o time.o setup.o frv_ksyms.o \
 	 debug-stub.o irq.o sleep.o uaccess.o
 
diff --git a/arch/frv/kernel/entry.S b/arch/frv/kernel/entry.S
index 7d5e000..0027329 100644
--- a/arch/frv/kernel/entry.S
+++ b/arch/frv/kernel/entry.S
@@ -863,6 +863,19 @@ ret_from_fork:
 	setlos.p	#0,gr8
 	bra		__syscall_exit
 
+	.globl		ret_from_kernel_thread
+ret_from_kernel_thread:
+	lddi.p		@(gr28,#REG_GR(8)),gr20
+	call		schedule_tail
+	or.p		gr20,gr20,gr8
+	calll		@(gr21,gr0)
+	bra		sys_exit
+
+	.globl		ret_from_kernel_execve
+ret_from_kernel_execve:
+	ori		gr28,0,sp
+	bra		__syscall_exit
+
 ###################################################################################################
 #
 # Return to user mode is not as complex as all this looks,
diff --git a/arch/frv/kernel/frv_ksyms.c b/arch/frv/kernel/frv_ksyms.c
index a89803b..86c516d 100644
--- a/arch/frv/kernel/frv_ksyms.c
+++ b/arch/frv/kernel/frv_ksyms.c
@@ -30,7 +30,6 @@ EXPORT_SYMBOL(ip_fast_csum);
 EXPORT_SYMBOL(local_irq_count);
 EXPORT_SYMBOL(local_bh_count);
 #endif
-EXPORT_SYMBOL(kernel_thread);
 
 EXPORT_SYMBOL(__res_bus_clock_speed_HZ);
 EXPORT_SYMBOL(__page_offset);
diff --git a/arch/frv/kernel/kernel_execve.S b/arch/frv/kernel/kernel_execve.S
deleted file mode 100644
index 9b074a1..0000000
--- a/arch/frv/kernel/kernel_execve.S
+++ /dev/null
@@ -1,33 +0,0 @@
-/* in-kernel program execution
- *
- * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@redhat.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/linkage.h>
-#include <asm/unistd.h>
-
-###############################################################################
-#
-# Do a system call from kernel instead of calling sys_execve so we end up with
-# proper pt_regs.
-#
-# int kernel_execve(const char *filename, char *const argv[], char *const envp[])
-#
-# On entry: GR8/GR9/GR10: arguments to function
-# On return: GR8: syscall return.
-#
-###############################################################################
-	.globl		kernel_execve
-	.type		kernel_execve,@function
-kernel_execve:
-	setlos		__NR_execve,gr7
-	tira		gr0,#0
-	bralr
-
-	.size		kernel_execve,.-kernel_execve
diff --git a/arch/frv/kernel/kernel_thread.S b/arch/frv/kernel/kernel_thread.S
deleted file mode 100644
index f0e5294..0000000
--- a/arch/frv/kernel/kernel_thread.S
+++ /dev/null
@@ -1,77 +0,0 @@
-/* kernel_thread.S: kernel thread creation
- *
- * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@redhat.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/linkage.h>
-#include <linux/kern_levels.h>
-#include <asm/unistd.h>
-
-#define CLONE_VM	0x00000100	/* set if VM shared between processes */
-
-	.section .rodata
-kernel_thread_emsg:
-	.asciz	KERN_ERR "failed to create kernel thread: error=%d\n"
-
-	.text
-	.balign		4
-
-###############################################################################
-#
-# Create a kernel thread
-#
-# int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
-#
-###############################################################################
-	.globl		kernel_thread
-	.type		kernel_thread,@function
-kernel_thread:
-	or.p		gr8,gr0,gr4
-	or		gr9,gr0,gr5
-
-	# start by forking the current process, but with shared VM
-	setlos.p	#__NR_clone,gr7		; syscall number
-	ori		gr10,#CLONE_VM,gr8	; first syscall arg	[clone_flags]
-	sethi.p		#0xe4e4,gr9		; second syscall arg	[newsp]
-	setlo		#0xe4e4,gr9
-	setlos.p	#0,gr10			; third syscall arg	[parent_tidptr]
-	setlos		#0,gr11			; fourth syscall arg	[child_tidptr]
-	tira		gr0,#0
-	setlos.p	#4095,gr7
-	andcc		gr8,gr8,gr0,icc0
-	addcc.p		gr8,gr7,gr0,icc1
-	bnelr		icc0,#2
-	bc		icc1,#0,kernel_thread_error
-
-	# now invoke the work function
-	or		gr5,gr0,gr8
-	calll		@(gr4,gr0)
-
-	# and finally exit the thread
-	setlos		#__NR_exit,gr7		; syscall number
-	tira		gr0,#0
-
-kernel_thread_error:
-	subi		sp,#8,sp
-	movsg		lr,gr4
-	sti		gr8,@(sp,#0)
-	sti.p		gr4,@(sp,#4)
-
-	or		gr8,gr0,gr9
-	sethi.p		%hi(kernel_thread_emsg),gr8
-	setlo		%lo(kernel_thread_emsg),gr8
-
-	call		printk
-
-	ldi		@(sp,#4),gr4
-	ldi		@(sp,#0),gr8
-	subi		sp,#8,sp
-	jmpl		@(gr4,gr0)
-
-	.size		kernel_thread,.-kernel_thread
diff --git a/arch/frv/kernel/pm.c b/arch/frv/kernel/pm.c
index 5fa3889..0b57992 100644
--- a/arch/frv/kernel/pm.c
+++ b/arch/frv/kernel/pm.c
@@ -153,23 +153,22 @@ static int user_atoi(char __user *ubuf, size_t len)
 static int sysctl_pm_do_suspend(ctl_table *ctl, int write,
 				void __user *buffer, size_t *lenp, loff_t *fpos)
 {
-	int retval, mode;
+	int mode;
 
 	if (*lenp <= 0)
 		return -EIO;
 
 	mode = user_atoi(buffer, *lenp);
-	if ((mode != 1) && (mode != 5))
-		return -EINVAL;
+	switch (mode) {
+	case 1:
+	    return pm_do_suspend();
 
-	if (retval == 0) {
-		if (mode == 5)
-		    retval = pm_do_bus_sleep();
-		else
-		    retval = pm_do_suspend();
-	}
+	case 5:
+	    return pm_do_bus_sleep();
 
-	return retval;
+	default:
+	    return -EINVAL;
+	}
 }
 
 static int try_set_cmode(int new_cmode)
diff --git a/arch/frv/kernel/process.c b/arch/frv/kernel/process.c
index ff95f50..655d90d 100644
--- a/arch/frv/kernel/process.c
+++ b/arch/frv/kernel/process.c
@@ -25,6 +25,7 @@
 #include <linux/reboot.h>
 #include <linux/interrupt.h>
 #include <linux/pagemap.h>
+#include <linux/rcupdate.h>
 
 #include <asm/asm-offsets.h>
 #include <asm/uaccess.h>
@@ -37,6 +38,7 @@
 #include "local.h"
 
 asmlinkage void ret_from_fork(void);
+asmlinkage void ret_from_kernel_thread(void);
 
 #include <asm/pgalloc.h>
 
@@ -69,12 +71,14 @@ void cpu_idle(void)
 {
 	/* endless idle loop with no priority at all */
 	while (1) {
+		rcu_idle_enter();
 		while (!need_resched()) {
 			check_pgt_cache();
 
 			if (!frv_dma_inprogress && idle)
 				idle();
 		}
+		rcu_idle_exit();
 
 		schedule_preempt_disabled();
 	}
@@ -169,32 +173,13 @@ asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
  * set up the kernel stack and exception frames for a new process
  */
 int copy_thread(unsigned long clone_flags,
-		unsigned long usp, unsigned long topstk,
+		unsigned long usp, unsigned long arg,
 		struct task_struct *p, struct pt_regs *regs)
 {
-	struct pt_regs *childregs0, *childregs, *regs0;
+	struct pt_regs *childregs;
 
-	regs0 = __kernel_frame0_ptr;
-	childregs0 = (struct pt_regs *)
+	childregs = (struct pt_regs *)
 		(task_stack_page(p) + THREAD_SIZE - FRV_FRAME0_SIZE);
-	childregs = childregs0;
-
-	/* set up the userspace frame (the only place that the USP is stored) */
-	*childregs0 = *regs0;
-
-	childregs0->gr8		= 0;
-	childregs0->sp		= usp;
-	childregs0->next_frame	= NULL;
-
-	/* set up the return kernel frame if called from kernel_thread() */
-	if (regs != regs0) {
-		childregs--;
-		*childregs = *regs;
-		childregs->sp = (unsigned long) childregs0;
-		childregs->next_frame = childregs0;
-		childregs->gr15 = (unsigned long) task_thread_info(p);
-		childregs->gr29 = (unsigned long) p;
-	}
 
 	p->set_child_tid = p->clear_child_tid = NULL;
 
@@ -203,8 +188,25 @@ int copy_thread(unsigned long clone_flags,
 	p->thread.sp	 = (unsigned long) childregs;
 	p->thread.fp	 = 0;
 	p->thread.lr	 = 0;
-	p->thread.pc	 = (unsigned long) ret_from_fork;
-	p->thread.frame0 = childregs0;
+	p->thread.frame0 = childregs;
+
+	if (unlikely(!regs)) {
+		memset(childregs, 0, sizeof(struct pt_regs));
+		childregs->gr9 = usp; /* function */
+		childregs->gr8 = arg;
+		chilregs->psr = PSR_S;
+		p->thread.pc = (unsigned long) ret_from_kernel_thread;
+		save_user_regs(p->thread.user);
+		return 0;
+	}
+
+	/* set up the userspace frame (the only place that the USP is stored) */
+	*childregs = *regs;
+
+	childregs->sp		= usp;
+	childregs->next_frame	= NULL;
+
+	p->thread.pc = (unsigned long) ret_from_fork;
 
 	/* the new TLS pointer is passed in as arg #5 to sys_clone() */
 	if (clone_flags & CLONE_SETTLS)
@@ -215,25 +217,6 @@ int copy_thread(unsigned long clone_flags,
 	return 0;
 } /* end copy_thread() */
 
-/*
- * sys_execve() executes a new program.
- */
-asmlinkage int sys_execve(const char __user *name,
-			  const char __user *const __user *argv,
-			  const char __user *const __user *envp)
-{
-	int error;
-	char * filename;
-
-	filename = getname(name);
-	error = PTR_ERR(filename);
-	if (IS_ERR(filename))
-		return error;
-	error = do_execve(filename, argv, envp, __frame);
-	putname(filename);
-	return error;
-}
-
 unsigned long get_wchan(struct task_struct *p)
 {
 	struct pt_regs *regs0;
diff --git a/arch/frv/kernel/setup.c b/arch/frv/kernel/setup.c
index 75cf7f4..1f1e5ef 100644
--- a/arch/frv/kernel/setup.c
+++ b/arch/frv/kernel/setup.c
@@ -184,7 +184,7 @@ static struct clock_cmode __pminitdata clock_cmodes_fr555[16] = {
 	[6]	= {	_x1,	_x1_5,	_x1_5,	_x4_5,	_x0_375	},
 };
 
-static const struct clock_cmode __pminitdata *clock_cmodes;
+static const struct clock_cmode __pminitconst *clock_cmodes;
 static int __pminitdata clock_doubled;
 
 static struct uart_port __pminitdata __frv_uart0 = {
diff --git a/arch/frv/kernel/signal.c b/arch/frv/kernel/signal.c
index 864c2f0..535810a 100644
--- a/arch/frv/kernel/signal.c
+++ b/arch/frv/kernel/signal.c
@@ -20,7 +20,6 @@
 #include <linux/ptrace.h>
 #include <linux/unistd.h>
 #include <linux/personality.h>
-#include <linux/freezer.h>
 #include <linux/tracehook.h>
 #include <asm/ucontext.h>
 #include <asm/uaccess.h>
@@ -298,10 +297,6 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set)
 	__frame->lr   = (unsigned long) &frame->retcode;
 	__frame->gr8  = sig;
 
-	/* the tracer may want to single-step inside the handler */
-	if (test_thread_flag(TIF_SINGLESTEP))
-		ptrace_notify(SIGTRAP);
-
 #if DEBUG_SIG
 	printk("SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n",
 	       sig, current->comm, current->pid, frame, __frame->pc,
@@ -400,10 +395,6 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 	__frame->gr8 = sig;
 	__frame->gr9 = (unsigned long) &frame->info;
 
-	/* the tracer may want to single-step inside the handler */
-	if (test_thread_flag(TIF_SINGLESTEP))
-		ptrace_notify(SIGTRAP);
-
 #if DEBUG_SIG
 	printk("SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n",
 	       sig, current->comm, current->pid, frame, __frame->pc,
diff --git a/arch/frv/mb93090-mb00/pci-irq.c b/arch/frv/mb93090-mb00/pci-irq.c
index 20f6497..c677b9d 100644
--- a/arch/frv/mb93090-mb00/pci-irq.c
+++ b/arch/frv/mb93090-mb00/pci-irq.c
@@ -28,7 +28,7 @@
  *
  */
 
-static const uint8_t __initdata pci_bus0_irq_routing[32][4] = {
+static const uint8_t __initconst pci_bus0_irq_routing[32][4] = {
 	[0 ] = { IRQ_FPGA_MB86943_PCI_INTA },
 	[16] = { IRQ_FPGA_RTL8029_INTA },
 	[17] = { IRQ_FPGA_PCI_INTC, IRQ_FPGA_PCI_INTD, IRQ_FPGA_PCI_INTA, IRQ_FPGA_PCI_INTB },
diff --git a/arch/frv/mb93090-mb00/pci-vdk.c b/arch/frv/mb93090-mb00/pci-vdk.c
index d04ed14..71e9bcf 100644
--- a/arch/frv/mb93090-mb00/pci-vdk.c
+++ b/arch/frv/mb93090-mb00/pci-vdk.c
@@ -330,10 +330,8 @@ void __init pcibios_fixup_bus(struct pci_bus *bus)
 	pci_read_bridge_bases(bus);
 
 	if (bus->number == 0) {
-		struct list_head *ln;
 		struct pci_dev *dev;
-		for (ln=bus->devices.next; ln != &bus->devices; ln=ln->next) {
-			dev = pci_dev_b(ln);
+		list_for_each_entry(dev, &bus->devices, bus_list) {
 			if (dev->devfn == 0) {
 				dev->resource[0].start = 0;
 				dev->resource[0].end = 0;
diff --git a/arch/h8300/Kconfig b/arch/h8300/Kconfig
index 5e8a0d9..23fff56 100644
--- a/arch/h8300/Kconfig
+++ b/arch/h8300/Kconfig
@@ -3,9 +3,11 @@ config H8300
 	default y
 	select HAVE_IDE
 	select HAVE_GENERIC_HARDIRQS
+	select GENERIC_ATOMIC64
 	select ARCH_WANT_IPC_PARSE_VERSION
 	select GENERIC_IRQ_SHOW
 	select GENERIC_CPU_DEVICES
+	select MODULES_USE_ELF_RELA
 
 config SYMBOL_PREFIX
 	string
diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild
index c68e168..883a0be 100644
--- a/arch/h8300/include/asm/Kbuild
+++ b/arch/h8300/include/asm/Kbuild
@@ -1 +1,4 @@
 include include/asm-generic/Kbuild.asm
+
+generic-y	+= module.h
+generic-y += exec.h
diff --git a/arch/h8300/include/asm/elf.h b/arch/h8300/include/asm/elf.h
index c24fa25..41193c3 100644
--- a/arch/h8300/include/asm/elf.h
+++ b/arch/h8300/include/asm/elf.h
@@ -54,7 +54,8 @@ typedef unsigned long elf_fpregset_t;
 
 #define ELF_PLATFORM  (NULL)
 
-#define SET_PERSONALITY(ex) set_personality(PER_LINUX)
+#define SET_PERSONALITY(ex) \
+	set_personality(PER_LINUX | (current->personality & (~PER_MASK)))
 
 #define R_H8_NONE       0
 #define R_H8_DIR32      1
diff --git a/arch/h8300/include/asm/exec.h b/arch/h8300/include/asm/exec.h
deleted file mode 100644
index c01c45c..0000000
--- a/arch/h8300/include/asm/exec.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _H8300_EXEC_H
-#define _H8300_EXEC_H
-
-#define arch_align_stack(x) (x)
-
-#endif /* _H8300_EXEC_H */
diff --git a/arch/h8300/include/asm/module.h b/arch/h8300/include/asm/module.h
deleted file mode 100644
index 8e46724..0000000
--- a/arch/h8300/include/asm/module.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef _ASM_H8300_MODULE_H
-#define _ASM_H8300_MODULE_H
-/*
- * This file contains the H8/300 architecture specific module code.
- */
-struct mod_arch_specific { };
-#define Elf_Shdr Elf32_Shdr
-#define Elf_Sym Elf32_Sym
-#define Elf_Ehdr Elf32_Ehdr
-
-#endif /* _ASM_H8/300_MODULE_H */
diff --git a/arch/h8300/include/asm/thread_info.h b/arch/h8300/include/asm/thread_info.h
index 9c126e0..ec2f777 100644
--- a/arch/h8300/include/asm/thread_info.h
+++ b/arch/h8300/include/asm/thread_info.h
@@ -85,8 +85,6 @@ static inline struct thread_info *current_thread_info(void)
 #define TIF_SYSCALL_TRACE	0	/* syscall trace active */
 #define TIF_SIGPENDING		1	/* signal pending */
 #define TIF_NEED_RESCHED	2	/* rescheduling necessary */
-#define TIF_POLLING_NRFLAG	3	/* true if poll_idle() is polling
-					   TIF_NEED_RESCHED */
 #define TIF_MEMDIE		4	/* is terminating due to OOM killer */
 #define TIF_RESTORE_SIGMASK	5	/* restore signal mask in do_signal() */
 #define TIF_NOTIFY_RESUME	6	/* callback before returning to user */
@@ -95,11 +93,10 @@ static inline struct thread_info *current_thread_info(void)
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
-#define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
-#define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
 #define _TIF_NOTIFY_RESUME	(1 << TIF_NOTIFY_RESUME)
 
-#define _TIF_WORK_MASK		0x0000FFFE	/* work to do on interrupt/exception return */
+#define _TIF_WORK_MASK		(_TIF_SIGPENDING | _TIF_NEED_RESCHED | \
+				 _TIF_NOTIFY_RESUME)
 
 #endif /* __KERNEL__ */
 
diff --git a/arch/h8300/kernel/process.c b/arch/h8300/kernel/process.c
index 0e9c315..f153ed1 100644
--- a/arch/h8300/kernel/process.c
+++ b/arch/h8300/kernel/process.c
@@ -36,6 +36,7 @@
 #include <linux/reboot.h>
 #include <linux/fs.h>
 #include <linux/slab.h>
+#include <linux/rcupdate.h>
 
 #include <asm/uaccess.h>
 #include <asm/traps.h>
@@ -78,8 +79,10 @@ void (*idle)(void) = default_idle;
 void cpu_idle(void)
 {
 	while (1) {
+		rcu_idle_enter();
 		while (!need_resched())
 			idle();
+		rcu_idle_exit();
 		schedule_preempt_disabled();
 	}
 }
diff --git a/arch/h8300/kernel/signal.c b/arch/h8300/kernel/signal.c
index 5adaada..0e81b96 100644
--- a/arch/h8300/kernel/signal.c
+++ b/arch/h8300/kernel/signal.c
@@ -38,7 +38,6 @@
 #include <linux/personality.h>
 #include <linux/tty.h>
 #include <linux/binfmts.h>
-#include <linux/freezer.h>
 #include <linux/tracehook.h>
 
 #include <asm/setup.h>
diff --git a/arch/h8300/kernel/sys_h8300.c b/arch/h8300/kernel/sys_h8300.c
index aaf5e5a..4bdc731 100644
--- a/arch/h8300/kernel/sys_h8300.c
+++ b/arch/h8300/kernel/sys_h8300.c
@@ -51,6 +51,7 @@ asmlinkage void syscall_print(void *dummy,...)
  * Do a system call from kernel instead of calling sys_execve so we
  * end up with proper pt_regs.
  */
+asmlinkage
 int kernel_execve(const char *filename,
 		  const char *const argv[],
 		  const char *const envp[])
diff --git a/arch/h8300/kernel/timer/itu.c b/arch/h8300/kernel/timer/itu.c
index a2ae5e9..0a8b5cd 100644
--- a/arch/h8300/kernel/timer/itu.c
+++ b/arch/h8300/kernel/timer/itu.c
@@ -62,7 +62,7 @@ static struct irqaction itu_irq = {
 	.flags		= IRQF_DISABLED | IRQF_TIMER,
 };
 
-static const int __initdata divide_rate[] = {1, 2, 4, 8};
+static const int __initconst divide_rate[] = {1, 2, 4, 8};
 
 void __init h8300_timer_setup(void)
 {
diff --git a/arch/h8300/kernel/timer/timer16.c b/arch/h8300/kernel/timer/timer16.c
index ae0d381..462d9f58 100644
--- a/arch/h8300/kernel/timer/timer16.c
+++ b/arch/h8300/kernel/timer/timer16.c
@@ -57,7 +57,7 @@ static struct irqaction timer16_irq = {
 	.flags		= IRQF_DISABLED | IRQF_TIMER,
 };
 
-static const int __initdata divide_rate[] = {1, 2, 4, 8};
+static const int __initconst divide_rate[] = {1, 2, 4, 8};
 
 void __init h8300_timer_setup(void)
 {
diff --git a/arch/h8300/kernel/timer/timer8.c b/arch/h8300/kernel/timer/timer8.c
index 7a1533f..505f341 100644
--- a/arch/h8300/kernel/timer/timer8.c
+++ b/arch/h8300/kernel/timer/timer8.c
@@ -77,7 +77,7 @@ static struct irqaction timer8_irq = {
 	.flags		= IRQF_DISABLED | IRQF_TIMER,
 };
 
-static const int __initdata divide_rate[] = {8, 64, 8192};
+static const int __initconst divide_rate[] = {8, 64, 8192};
 
 void __init h8300_timer_setup(void)
 {
diff --git a/arch/h8300/kernel/timer/tpu.c b/arch/h8300/kernel/timer/tpu.c
index 2193a2e..0350f62 100644
--- a/arch/h8300/kernel/timer/tpu.c
+++ b/arch/h8300/kernel/timer/tpu.c
@@ -66,7 +66,7 @@ static struct irqaction tpu_irq = {
 	.flags		= IRQF_DISABLED | IRQF_TIMER,
 };
 
-static const int __initdata divide_rate[] = {
+static const int __initconst divide_rate[] = {
 #if CONFIG_H8300_TPU_CH == 0
 	1,4,16,64,0,0,0,0,
 #elif (CONFIG_H8300_TPU_CH == 1) || (CONFIG_H8300_TPU_CH == 5)
diff --git a/arch/h8300/platform/h8300h/irq.c b/arch/h8300/platform/h8300h/irq.c
index bc4f51b..0a50353 100644
--- a/arch/h8300/platform/h8300h/irq.c
+++ b/arch/h8300/platform/h8300h/irq.c
@@ -14,14 +14,14 @@
 #include <asm/gpio-internal.h>
 #include <asm/regs306x.h>
 
-const int __initdata h8300_saved_vectors[] = {
+const int __initconst h8300_saved_vectors[] = {
 #if defined(CONFIG_GDB_DEBUG)
 	TRAP3_VEC,	/* TRAPA #3 is GDB breakpoint */
 #endif
 	-1,
 };
 
-const h8300_vector __initdata h8300_trap_table[] = {
+const h8300_vector __initconst h8300_trap_table[] = {
 	0, 0, 0, 0, 0, 0, 0, 0,
 	system_call,
 	0,
diff --git a/arch/h8300/platform/h8s/irq.c b/arch/h8300/platform/h8s/irq.c
index 7b5f29f..f3a5511 100644
--- a/arch/h8300/platform/h8s/irq.c
+++ b/arch/h8300/platform/h8s/irq.c
@@ -18,7 +18,7 @@
 #include <asm/regs267x.h>
 
 /* saved vector list */
-const int __initdata h8300_saved_vectors[]={
+const int __initconst h8300_saved_vectors[] = {
 #if defined(CONFIG_GDB_DEBUG)
 	TRACE_VEC,
 	TRAP3_VEC,
@@ -27,7 +27,7 @@ const int __initdata h8300_saved_vectors[]={
 };
 
 /* trap entry table */
-const H8300_VECTOR __initdata h8300_trap_table[] = {
+const H8300_VECTOR __initconst h8300_trap_table[] = {
 	0,0,0,0,0,
 	trace_break,  /* TRACE */
 	0,0,
diff --git a/arch/hexagon/Kconfig b/arch/hexagon/Kconfig
index b2fdfb7..0744f7d 100644
--- a/arch/hexagon/Kconfig
+++ b/arch/hexagon/Kconfig
@@ -30,6 +30,7 @@ config HEXAGON
 	select KTIME_SCALAR
 	select GENERIC_CLOCKEVENTS
 	select GENERIC_CLOCKEVENTS_BROADCAST
+	select MODULES_USE_ELF_RELA
 	---help---
 	  Qualcomm Hexagon is a processor architecture designed for high
 	  performance and low power across a wide variety of applications.
diff --git a/arch/hexagon/include/asm/elf.h b/arch/hexagon/include/asm/elf.h
index 37976a0..82b4996 100644
--- a/arch/hexagon/include/asm/elf.h
+++ b/arch/hexagon/include/asm/elf.h
@@ -217,7 +217,8 @@ do {					\
 #define ELF_PLATFORM  (NULL)
 
 #ifdef __KERNEL__
-#define SET_PERSONALITY(ex) set_personality(PER_LINUX)
+#define SET_PERSONALITY(ex) \
+	set_personality(PER_LINUX | (current->personality & (~PER_MASK)))
 #endif
 
 #define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1
diff --git a/arch/hexagon/include/asm/thread_info.h b/arch/hexagon/include/asm/thread_info.h
index 4f936a7..e4a0aad 100644
--- a/arch/hexagon/include/asm/thread_info.h
+++ b/arch/hexagon/include/asm/thread_info.h
@@ -120,10 +120,8 @@ register struct thread_info *__current_thread_info asm(QUOTED_THREADINFO_REG);
 #define TIF_SIGPENDING          2       /* signal pending */
 #define TIF_NEED_RESCHED        3       /* rescheduling necessary */
 #define TIF_SINGLESTEP          4       /* restore ss @ return to usr mode */
-#define TIF_IRET                5       /* return with iret */
 #define TIF_RESTORE_SIGMASK     6       /* restore sig mask in do_signal() */
 /* true if poll_idle() is polling TIF_NEED_RESCHED */
-#define TIF_POLLING_NRFLAG      16
 #define TIF_MEMDIE              17      /* OOM killer killed process */
 
 #define _TIF_SYSCALL_TRACE      (1 << TIF_SYSCALL_TRACE)
@@ -131,9 +129,6 @@ register struct thread_info *__current_thread_info asm(QUOTED_THREADINFO_REG);
 #define _TIF_SIGPENDING         (1 << TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED       (1 << TIF_NEED_RESCHED)
 #define _TIF_SINGLESTEP         (1 << TIF_SINGLESTEP)
-#define _TIF_IRET               (1 << TIF_IRET)
-#define _TIF_RESTORE_SIGMASK    (1 << TIF_RESTORE_SIGMASK)
-#define _TIF_POLLING_NRFLAG     (1 << TIF_POLLING_NRFLAG)
 
 /* work to do on interrupt/exception return - All but TIF_SYSCALL_TRACE */
 #define _TIF_WORK_MASK          (0x0000FFFF & ~_TIF_SYSCALL_TRACE)
diff --git a/arch/hexagon/kernel/signal.c b/arch/hexagon/kernel/signal.c
index 304b0808..1ea16be 100644
--- a/arch/hexagon/kernel/signal.c
+++ b/arch/hexagon/kernel/signal.c
@@ -20,7 +20,6 @@
 
 #include <linux/linkage.h>
 #include <linux/syscalls.h>
-#include <linux/freezer.h>
 #include <linux/tracehook.h>
 #include <asm/registers.h>
 #include <asm/thread_info.h>
diff --git a/arch/hexagon/kernel/syscall.c b/arch/hexagon/kernel/syscall.c
index 620dd18..553cd60 100644
--- a/arch/hexagon/kernel/syscall.c
+++ b/arch/hexagon/kernel/syscall.c
@@ -87,4 +87,3 @@ int kernel_execve(const char *filename,
 
 	return retval;
 }
-EXPORT_SYMBOL(kernel_execve);
diff --git a/arch/hexagon/mm/vm_fault.c b/arch/hexagon/mm/vm_fault.c
index 06695cc..513b74c 100644
--- a/arch/hexagon/mm/vm_fault.c
+++ b/arch/hexagon/mm/vm_fault.c
@@ -113,6 +113,7 @@ good_area:
 				current->min_flt++;
 			if (fault & VM_FAULT_RETRY) {
 				flags &= ~FAULT_FLAG_ALLOW_RETRY;
+				flags |= FAULT_FLAG_TRIED;
 				goto retry;
 			}
 		}
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index 310cf57..ac5964c 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -25,6 +25,7 @@ config IA64
 	select HAVE_GENERIC_HARDIRQS
 	select HAVE_MEMBLOCK
 	select HAVE_MEMBLOCK_NODE_MAP
+	select HAVE_VIRT_CPU_ACCOUNTING
 	select ARCH_DISCARD_MEMBLOCK
 	select GENERIC_IRQ_PROBE
 	select GENERIC_PENDING_IRQ if SMP
@@ -39,6 +40,8 @@ config IA64
 	select ARCH_THREAD_INFO_ALLOCATOR
 	select ARCH_CLOCKSOURCE_DATA
 	select GENERIC_TIME_VSYSCALL
+	select HAVE_MOD_ARCH_SPECIFIC
+	select MODULES_USE_ELF_RELA
 	default y
 	help
 	  The Itanium Processor Family is Intel's 64-bit successor to
@@ -340,17 +343,6 @@ config FORCE_MAX_ZONEORDER
 	default "17" if HUGETLB_PAGE
 	default "11"
 
-config VIRT_CPU_ACCOUNTING
-	bool "Deterministic task and CPU time accounting"
-	default n
-	help
-	  Select this option to enable more accurate task and CPU time
-	  accounting.  This is done by reading a CPU counter on each
-	  kernel entry and exit and on transitions within the kernel
-	  between system, softirq and hardirq state, so there is a
-	  small performance impact.
-	  If in doubt, say N here.
-
 config SMP
 	bool "Symmetric multi-processing support"
 	select USE_GENERIC_SMP_HELPERS
diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c
index c34785d..ec536e4 100644
--- a/arch/ia64/hp/sim/simserial.c
+++ b/arch/ia64/hp/sim/simserial.c
@@ -338,7 +338,7 @@ static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
 {
 	/* Handle turning off CRTSCTS */
 	if ((old_termios->c_cflag & CRTSCTS) &&
-	    !(tty->termios->c_cflag & CRTSCTS)) {
+	    !(tty->termios.c_cflag & CRTSCTS)) {
 		tty->hw_stopped = 0;
 	}
 }
@@ -545,6 +545,7 @@ static int __init simrs_init(void)
 	/* the port is imaginary */
 	printk(KERN_INFO "ttyS0 at 0x03f8 (irq = %d) is a 16550\n", state->irq);
 
+	tty_port_link_device(&state->port, hp_simserial_driver, 0);
 	retval = tty_register_driver(hp_simserial_driver);
 	if (retval) {
 		printk(KERN_ERR "Couldn't register simserial driver\n");
diff --git a/arch/ia64/include/asm/Kbuild b/arch/ia64/include/asm/Kbuild
index d4eb938..98efd48 100644
--- a/arch/ia64/include/asm/Kbuild
+++ b/arch/ia64/include/asm/Kbuild
@@ -13,3 +13,4 @@ header-y += ptrace_offsets.h
 header-y += rse.h
 header-y += ucontext.h
 header-y += ustack.h
+generic-y += exec.h
diff --git a/arch/ia64/include/asm/exec.h b/arch/ia64/include/asm/exec.h
deleted file mode 100644
index b262424..0000000
--- a/arch/ia64/include/asm/exec.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Process execution defines.
- *
- * Copyright (C) 1998-2003 Hewlett-Packard Co
- *	David Mosberger-Tang <davidm@hpl.hp.com>
- * Copyright (C) 1999 Asit Mallick <asit.k.mallick@intel.com>
- * Copyright (C) 1999 Don Dugger <don.dugger@intel.com>
- */
-#ifndef _ASM_IA64_EXEC_H
-#define _ASM_IA64_EXEC_H
-
-#define arch_align_stack(x) (x)
-
-#endif /* _ASM_IA64_EXEC_H */
diff --git a/arch/ia64/include/asm/hugetlb.h b/arch/ia64/include/asm/hugetlb.h
index da55c63..94eaa5b 100644
--- a/arch/ia64/include/asm/hugetlb.h
+++ b/arch/ia64/include/asm/hugetlb.h
@@ -77,4 +77,8 @@ static inline void arch_release_hugepage(struct page *page)
 {
 }
 
+static inline void arch_clear_hugepage_flags(struct page *page)
+{
+}
+
 #endif /* _ASM_IA64_HUGETLB_H */
diff --git a/arch/ia64/include/asm/module.h b/arch/ia64/include/asm/module.h
index 908eaef..dfba22a 100644
--- a/arch/ia64/include/asm/module.h
+++ b/arch/ia64/include/asm/module.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_IA64_MODULE_H
 #define _ASM_IA64_MODULE_H
 
+#include <asm-generic/module.h>
+
 /*
  * IA-64-specific support for kernel module loader.
  *
@@ -29,10 +31,6 @@ struct mod_arch_specific {
 	unsigned int next_got_entry;	/* index of next available got entry */
 };
 
-#define Elf_Shdr	Elf64_Shdr
-#define Elf_Sym		Elf64_Sym
-#define Elf_Ehdr	Elf64_Ehdr
-
 #define MODULE_PROC_FAMILY	"ia64"
 #define MODULE_ARCH_VERMAGIC	MODULE_PROC_FAMILY \
 	"gcc-" __stringify(__GNUC__) "." __stringify(__GNUC_MINOR__)
diff --git a/arch/ia64/include/asm/numa.h b/arch/ia64/include/asm/numa.h
index 6a8a27c..2e27ef1 100644
--- a/arch/ia64/include/asm/numa.h
+++ b/arch/ia64/include/asm/numa.h
@@ -59,7 +59,7 @@ extern struct node_cpuid_s node_cpuid[NR_CPUS];
  */
 
 extern u8 numa_slit[MAX_NUMNODES * MAX_NUMNODES];
-#define node_distance(from,to) (numa_slit[(from) * num_online_nodes() + (to)])
+#define node_distance(from,to) (numa_slit[(from) * MAX_NUMNODES + (to)])
 
 extern int paddr_to_nid(unsigned long paddr);
 
diff --git a/arch/ia64/include/asm/switch_to.h b/arch/ia64/include/asm/switch_to.h
index cb2412f..d38c7ea 100644
--- a/arch/ia64/include/asm/switch_to.h
+++ b/arch/ia64/include/asm/switch_to.h
@@ -30,13 +30,6 @@ extern struct task_struct *ia64_switch_to (void *next_task);
 extern void ia64_save_extra (struct task_struct *task);
 extern void ia64_load_extra (struct task_struct *task);
 
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING
-extern void ia64_account_on_switch (struct task_struct *prev, struct task_struct *next);
-# define IA64_ACCOUNT_ON_SWITCH(p,n) ia64_account_on_switch(p,n)
-#else
-# define IA64_ACCOUNT_ON_SWITCH(p,n)
-#endif
-
 #ifdef CONFIG_PERFMON
   DECLARE_PER_CPU(unsigned long, pfm_syst_info);
 # define PERFMON_IS_SYSWIDE() (__get_cpu_var(pfm_syst_info) & 0x1)
@@ -49,7 +42,6 @@ extern void ia64_account_on_switch (struct task_struct *prev, struct task_struct
 	 || PERFMON_IS_SYSWIDE())
 
 #define __switch_to(prev,next,last) do {							 \
-	IA64_ACCOUNT_ON_SWITCH(prev, next);							 \
 	if (IA64_HAS_EXTRA_STATE(prev))								 \
 		ia64_save_extra(prev);								 \
 	if (IA64_HAS_EXTRA_STATE(next))								 \
diff --git a/arch/ia64/include/asm/thread_info.h b/arch/ia64/include/asm/thread_info.h
index f7ee853..ff2ae41 100644
--- a/arch/ia64/include/asm/thread_info.h
+++ b/arch/ia64/include/asm/thread_info.h
@@ -106,7 +106,6 @@ struct thread_info {
 #define TIF_SYSCALL_AUDIT	3	/* syscall auditing active */
 #define TIF_SINGLESTEP		4	/* restore singlestep on return to user mode */
 #define TIF_NOTIFY_RESUME	6	/* resumption notification requested */
-#define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_MEMDIE		17	/* is terminating due to OOM killer */
 #define TIF_MCA_INIT		18	/* this task is processing MCA or INIT */
 #define TIF_DB_DISABLED		19	/* debug trap disabled for fsyscall */
@@ -119,7 +118,6 @@ struct thread_info {
 #define _TIF_NOTIFY_RESUME	(1 << TIF_NOTIFY_RESUME)
 #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1 << TIF_NEED_RESCHED)
-#define _TIF_POLLING_NRFLAG	(1 << TIF_POLLING_NRFLAG)
 #define _TIF_MCA_INIT		(1 << TIF_MCA_INIT)
 #define _TIF_DB_DISABLED	(1 << TIF_DB_DISABLED)
 #define _TIF_RESTORE_RSE	(1 << TIF_RESTORE_RSE)
diff --git a/arch/ia64/include/asm/xen/interface.h b/arch/ia64/include/asm/xen/interface.h
index 09d5f7f..3d52a5b 100644
--- a/arch/ia64/include/asm/xen/interface.h
+++ b/arch/ia64/include/asm/xen/interface.h
@@ -67,6 +67,10 @@
 #define set_xen_guest_handle(hnd, val)	do { (hnd).p = val; } while (0)
 
 #ifndef __ASSEMBLY__
+/* Explicitly size integers that represent pfns in the public interface
+ * with Xen so that we could have one ABI that works for 32 and 64 bit
+ * guests. */
+typedef unsigned long xen_pfn_t;
 /* Guest handles for primitive C types. */
 __DEFINE_GUEST_HANDLE(uchar, unsigned char);
 __DEFINE_GUEST_HANDLE(uint, unsigned int);
@@ -79,7 +83,6 @@ DEFINE_GUEST_HANDLE(void);
 DEFINE_GUEST_HANDLE(uint64_t);
 DEFINE_GUEST_HANDLE(uint32_t);
 
-typedef unsigned long xen_pfn_t;
 DEFINE_GUEST_HANDLE(xen_pfn_t);
 #define PRI_xen_pfn	"lx"
 #endif
@@ -265,6 +268,8 @@ typedef struct xen_callback xen_callback_t;
 
 #endif /* !__ASSEMBLY__ */
 
+#include <asm/pvclock-abi.h>
+
 /* Size of the shared_info area (this is not related to page size).  */
 #define XSI_SHIFT			14
 #define XSI_SIZE			(1 << XSI_SHIFT)
diff --git a/arch/ia64/kernel/machine_kexec.c b/arch/ia64/kernel/machine_kexec.c
index 070e8ef..5151a64 100644
--- a/arch/ia64/kernel/machine_kexec.c
+++ b/arch/ia64/kernel/machine_kexec.c
@@ -85,12 +85,13 @@ static void ia64_machine_kexec(struct unw_frame_info *info, void *arg)
 	struct kimage *image = arg;
 	relocate_new_kernel_t rnk;
 	void *pal_addr = efi_get_pal_addr();
-	unsigned long code_addr = (unsigned long)page_address(image->control_code_page);
+	unsigned long code_addr;
 	int ii;
 	u64 fp, gp;
 	ia64_fptr_t *init_handler = (ia64_fptr_t *)ia64_os_init_on_kdump;
 
 	BUG_ON(!image);
+	code_addr = (unsigned long)page_address(image->control_code_page);
 	if (image->type == KEXEC_TYPE_CRASH) {
 		crash_save_this_cpu();
 		current->thread.ksp = (__u64)info->sw - 16;
diff --git a/arch/ia64/kernel/mca_drv.c b/arch/ia64/kernel/mca_drv.c
index 1c2e894..9392e02 100644
--- a/arch/ia64/kernel/mca_drv.c
+++ b/arch/ia64/kernel/mca_drv.c
@@ -158,7 +158,8 @@ mca_handler_bh(unsigned long paddr, void *iip, unsigned long ipsr)
 	ia64_mlogbuf_dump();
 	printk(KERN_ERR "OS_MCA: process [cpu %d, pid: %d, uid: %d, "
 		"iip: %p, psr: 0x%lx,paddr: 0x%lx](%s) encounters MCA.\n",
-	       raw_smp_processor_id(), current->pid, current_uid(),
+	       raw_smp_processor_id(), current->pid,
+		from_kuid(&init_user_ns, current_uid()),
 		iip, ipsr, paddr, current->comm);
 
 	spin_lock(&mca_bh_lock);
diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
index 3fa4bc5..ea39eba 100644
--- a/arch/ia64/kernel/perfmon.c
+++ b/arch/ia64/kernel/perfmon.c
@@ -2306,8 +2306,8 @@ pfm_smpl_buffer_alloc(struct task_struct *task, struct file *filp, pfm_context_t
 	 * partially initialize the vma for the sampling buffer
 	 */
 	vma->vm_mm	     = mm;
-	vma->vm_file	     = filp;
-	vma->vm_flags	     = VM_READ| VM_MAYREAD |VM_RESERVED;
+	vma->vm_file	     = get_file(filp);
+	vma->vm_flags	     = VM_READ|VM_MAYREAD|VM_DONTEXPAND|VM_DONTDUMP;
 	vma->vm_page_prot    = PAGE_READONLY; /* XXX may need to change */
 
 	/*
@@ -2345,8 +2345,6 @@ pfm_smpl_buffer_alloc(struct task_struct *task, struct file *filp, pfm_context_t
 		goto error;
 	}
 
-	get_file(filp);
-
 	/*
 	 * now insert the vma in the vm list for the process, must be
 	 * done with mmap lock held
@@ -2380,8 +2378,8 @@ static int
 pfm_bad_permissions(struct task_struct *task)
 {
 	const struct cred *tcred;
-	uid_t uid = current_uid();
-	gid_t gid = current_gid();
+	kuid_t uid = current_uid();
+	kgid_t gid = current_gid();
 	int ret;
 
 	rcu_read_lock();
@@ -2389,20 +2387,20 @@ pfm_bad_permissions(struct task_struct *task)
 
 	/* inspired by ptrace_attach() */
 	DPRINT(("cur: uid=%d gid=%d task: euid=%d suid=%d uid=%d egid=%d sgid=%d\n",
-		uid,
-		gid,
-		tcred->euid,
-		tcred->suid,
-		tcred->uid,
-		tcred->egid,
-		tcred->sgid));
-
-	ret = ((uid != tcred->euid)
-	       || (uid != tcred->suid)
-	       || (uid != tcred->uid)
-	       || (gid != tcred->egid)
-	       || (gid != tcred->sgid)
-	       || (gid != tcred->gid)) && !capable(CAP_SYS_PTRACE);
+		from_kuid(&init_user_ns, uid),
+		from_kgid(&init_user_ns, gid),
+		from_kuid(&init_user_ns, tcred->euid),
+		from_kuid(&init_user_ns, tcred->suid),
+		from_kuid(&init_user_ns, tcred->uid),
+		from_kgid(&init_user_ns, tcred->egid),
+		from_kgid(&init_user_ns, tcred->sgid)));
+
+	ret = ((!uid_eq(uid, tcred->euid))
+	       || (!uid_eq(uid, tcred->suid))
+	       || (!uid_eq(uid, tcred->uid))
+	       || (!gid_eq(gid, tcred->egid))
+	       || (!gid_eq(gid, tcred->sgid))
+	       || (!gid_eq(gid, tcred->gid))) && !capable(CAP_SYS_PTRACE);
 
 	rcu_read_unlock();
 	return ret;
@@ -4782,7 +4780,7 @@ recheck:
 asmlinkage long
 sys_perfmonctl (int fd, int cmd, void __user *arg, int count)
 {
-	struct file *file = NULL;
+	struct fd f = {NULL, 0};
 	pfm_context_t *ctx = NULL;
 	unsigned long flags = 0UL;
 	void *args_k = NULL;
@@ -4879,17 +4877,17 @@ restart_args:
 
 	ret = -EBADF;
 
-	file = fget(fd);
-	if (unlikely(file == NULL)) {
+	f = fdget(fd);
+	if (unlikely(f.file == NULL)) {
 		DPRINT(("invalid fd %d\n", fd));
 		goto error_args;
 	}
-	if (unlikely(PFM_IS_FILE(file) == 0)) {
+	if (unlikely(PFM_IS_FILE(f.file) == 0)) {
 		DPRINT(("fd %d not related to perfmon\n", fd));
 		goto error_args;
 	}
 
-	ctx = file->private_data;
+	ctx = f.file->private_data;
 	if (unlikely(ctx == NULL)) {
 		DPRINT(("no context for fd %d\n", fd));
 		goto error_args;
@@ -4919,8 +4917,8 @@ abort_locked:
 	if (call_made && PFM_CMD_RW_ARG(cmd) && copy_to_user(arg, args_k, base_sz*count)) ret = -EFAULT;
 
 error_args:
-	if (file)
-		fput(file);
+	if (f.file)
+		fdput(f);
 
 	kfree(args_k);
 
diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c
index dd6fc14..ee31fe9 100644
--- a/arch/ia64/kernel/process.c
+++ b/arch/ia64/kernel/process.c
@@ -29,6 +29,7 @@
 #include <linux/kdebug.h>
 #include <linux/utsname.h>
 #include <linux/tracehook.h>
+#include <linux/rcupdate.h>
 
 #include <asm/cpu.h>
 #include <asm/delay.h>
@@ -196,8 +197,8 @@ do_notify_resume_user(sigset_t *unused, struct sigscratch *scr, long in_syscall)
 		ia64_do_signal(scr, in_syscall);
 	}
 
-	if (test_thread_flag(TIF_NOTIFY_RESUME)) {
-		clear_thread_flag(TIF_NOTIFY_RESUME);
+	if (test_and_clear_thread_flag(TIF_NOTIFY_RESUME)) {
+		local_irq_enable();	/* force interrupt enable */
 		tracehook_notify_resume(&scr->pt);
 	}
 
@@ -279,6 +280,7 @@ cpu_idle (void)
 
 	/* endless idle loop with no priority at all */
 	while (1) {
+		rcu_idle_enter();
 		if (can_do_pal_halt) {
 			current_thread_info()->status &= ~TS_POLLING;
 			/*
@@ -309,6 +311,7 @@ cpu_idle (void)
 			normal_xtp();
 #endif
 		}
+		rcu_idle_exit();
 		schedule_preempt_disabled();
 		check_pgt_cache();
 		if (cpu_is_offline(cpu))
diff --git a/arch/ia64/kernel/signal.c b/arch/ia64/kernel/signal.c
index a199be1..680b737 100644
--- a/arch/ia64/kernel/signal.c
+++ b/arch/ia64/kernel/signal.c
@@ -220,7 +220,7 @@ ia64_rt_sigreturn (struct sigscratch *scr)
 	si.si_errno = 0;
 	si.si_code = SI_KERNEL;
 	si.si_pid = task_pid_vnr(current);
-	si.si_uid = current_uid();
+	si.si_uid = from_kuid_munged(current_user_ns(), current_uid());
 	si.si_addr = sc;
 	force_sig_info(SIGSEGV, &si, current);
 	return retval;
@@ -317,7 +317,7 @@ force_sigsegv_info (int sig, void __user *addr)
 	si.si_errno = 0;
 	si.si_code = SI_KERNEL;
 	si.si_pid = task_pid_vnr(current);
-	si.si_uid = current_uid();
+	si.si_uid = from_kuid_munged(current_user_ns(), current_uid());
 	si.si_addr = addr;
 	force_sig_info(SIGSEGV, &si, current);
 	return 0;
@@ -438,14 +438,6 @@ ia64_do_signal (struct sigscratch *scr, long in_syscall)
 	long errno = scr->pt.r8;
 
 	/*
-	 * In the ia64_leave_kernel code path, we want the common case to go fast, which
-	 * is why we may in certain cases get here from kernel mode. Just return without
-	 * doing anything if so.
-	 */
-	if (!user_mode(&scr->pt))
-		return;
-
-	/*
 	 * This only loops in the rare cases of handle_signal() failing, in which case we
 	 * need to push through a forced SIGSEGV.
 	 */
diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c
index ecc904b..6247197 100644
--- a/arch/ia64/kernel/time.c
+++ b/arch/ia64/kernel/time.c
@@ -88,10 +88,10 @@ extern cputime_t cycle_to_cputime(u64 cyc);
  * accumulated times to the current process, and to prepare accounting on
  * the next process.
  */
-void ia64_account_on_switch(struct task_struct *prev, struct task_struct *next)
+void account_switch_vtime(struct task_struct *prev)
 {
 	struct thread_info *pi = task_thread_info(prev);
-	struct thread_info *ni = task_thread_info(next);
+	struct thread_info *ni = task_thread_info(current);
 	cputime_t delta_stime, delta_utime;
 	__u64 now;
 
diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c
index bd77cb5..8b3a9c0 100644
--- a/arch/ia64/kvm/kvm-ia64.c
+++ b/arch/ia64/kvm/kvm-ia64.c
@@ -924,6 +924,16 @@ int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
 	return 0;
 }
 
+int kvm_vm_ioctl_irq_line(struct kvm *kvm, struct kvm_irq_level *irq_event)
+{
+	if (!irqchip_in_kernel(kvm))
+		return -ENXIO;
+
+	irq_event->status = kvm_set_irq(kvm, KVM_USERSPACE_IRQ_SOURCE_ID,
+					irq_event->irq, irq_event->level);
+	return 0;
+}
+
 long kvm_arch_vm_ioctl(struct file *filp,
 		unsigned int ioctl, unsigned long arg)
 {
@@ -963,29 +973,6 @@ long kvm_arch_vm_ioctl(struct file *filp,
 			goto out;
 		}
 		break;
-	case KVM_IRQ_LINE_STATUS:
-	case KVM_IRQ_LINE: {
-		struct kvm_irq_level irq_event;
-
-		r = -EFAULT;
-		if (copy_from_user(&irq_event, argp, sizeof irq_event))
-			goto out;
-		r = -ENXIO;
-		if (irqchip_in_kernel(kvm)) {
-			__s32 status;
-			status = kvm_set_irq(kvm, KVM_USERSPACE_IRQ_SOURCE_ID,
-				    irq_event.irq, irq_event.level);
-			if (ioctl == KVM_IRQ_LINE_STATUS) {
-				r = -EFAULT;
-				irq_event.status = status;
-				if (copy_to_user(argp, &irq_event,
-							sizeof irq_event))
-					goto out;
-			}
-			r = 0;
-		}
-		break;
-		}
 	case KVM_GET_IRQCHIP: {
 		/* 0: PIC master, 1: PIC slave, 2: IOAPIC */
 		struct kvm_irqchip chip;
@@ -1626,11 +1613,17 @@ void kvm_arch_commit_memory_region(struct kvm *kvm,
 	return;
 }
 
-void kvm_arch_flush_shadow(struct kvm *kvm)
+void kvm_arch_flush_shadow_all(struct kvm *kvm)
 {
 	kvm_flush_remote_tlbs(kvm);
 }
 
+void kvm_arch_flush_shadow_memslot(struct kvm *kvm,
+				   struct kvm_memory_slot *slot)
+{
+	kvm_arch_flush_shadow_all();
+}
+
 long kvm_arch_dev_ioctl(struct file *filp,
 			unsigned int ioctl, unsigned long arg)
 {
diff --git a/arch/ia64/mm/fault.c b/arch/ia64/mm/fault.c
index 8443daf..6cf0341 100644
--- a/arch/ia64/mm/fault.c
+++ b/arch/ia64/mm/fault.c
@@ -184,6 +184,7 @@ retry:
 			current->min_flt++;
 		if (fault & VM_FAULT_RETRY) {
 			flags &= ~FAULT_FLAG_ALLOW_RETRY;
+			flags |= FAULT_FLAG_TRIED;
 
 			 /* No need to up_read(&mm->mmap_sem) as we would
 			 * have already released it in __lock_page_or_retry
diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c
index 0eab454..acd5b68 100644
--- a/arch/ia64/mm/init.c
+++ b/arch/ia64/mm/init.c
@@ -138,7 +138,8 @@ ia64_init_addr_space (void)
 			vma->vm_mm = current->mm;
 			vma->vm_end = PAGE_SIZE;
 			vma->vm_page_prot = __pgprot(pgprot_val(PAGE_READONLY) | _PAGE_MA_NAT);
-			vma->vm_flags = VM_READ | VM_MAYREAD | VM_IO | VM_RESERVED;
+			vma->vm_flags = VM_READ | VM_MAYREAD | VM_IO |
+					VM_DONTEXPAND | VM_DONTDUMP;
 			down_write(&current->mm->mmap_sem);
 			if (insert_vm_struct(current->mm, vma)) {
 				up_write(&current->mm->mmap_sem);
@@ -636,6 +637,7 @@ mem_init (void)
 
 	high_memory = __va(max_low_pfn * PAGE_SIZE);
 
+	reset_zone_present_pages();
 	for_each_online_pgdat(pgdat)
 		if (pgdat->bdata->node_bootmem_map)
 			totalram_pages += free_all_bootmem_node(pgdat);
diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
index 81acc7a..5faa66c 100644
--- a/arch/ia64/pci/pci.c
+++ b/arch/ia64/pci/pci.c
@@ -295,7 +295,6 @@ static __devinit acpi_status add_window(struct acpi_resource *res, void *data)
 	window->resource.flags = flags;
 	window->resource.start = addr.minimum + offset;
 	window->resource.end = window->resource.start + addr.address_length - 1;
-	window->resource.child = NULL;
 	window->offset = offset;
 
 	if (insert_resource(root, &window->resource)) {
@@ -357,7 +356,7 @@ pci_acpi_scan_root(struct acpi_pci_root *root)
 			&windows);
 	if (windows) {
 		controller->window =
-			kmalloc_node(sizeof(*controller->window) * windows,
+			kzalloc_node(sizeof(*controller->window) * windows,
 				     GFP_KERNEL, controller->node);
 		if (!controller->window)
 			goto out2;
@@ -461,14 +460,6 @@ void pcibios_set_master (struct pci_dev *dev)
 	/* No special bus mastering setup handling */
 }
 
-void __devinit
-pcibios_update_irq (struct pci_dev *dev, int irq)
-{
-	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
-
-	/* ??? FIXME -- record old value for shutdown.  */
-}
-
 int
 pcibios_enable_device (struct pci_dev *dev, int mask)
 {
diff --git a/arch/ia64/sn/kernel/io_common.c b/arch/ia64/sn/kernel/io_common.c
index fbb5f2f..8630875 100644
--- a/arch/ia64/sn/kernel/io_common.c
+++ b/arch/ia64/sn/kernel/io_common.c
@@ -229,7 +229,6 @@ void sn_pci_fixup_slot(struct pci_dev *dev, struct pcidev_info *pcidev_info,
 {
 	int segment = pci_domain_nr(dev->bus);
 	struct pcibus_bussoft *bs;
-	struct pci_bus *host_pci_bus;
 	struct pci_dev *host_pci_dev;
 	unsigned int bus_no, devfn;
 
@@ -245,8 +244,7 @@ void sn_pci_fixup_slot(struct pci_dev *dev, struct pcidev_info *pcidev_info,
 
 	bus_no = (pcidev_info->pdi_slot_host_handle >> 32) & 0xff;
 	devfn = pcidev_info->pdi_slot_host_handle & 0xffffffff;
- 	host_pci_bus = pci_find_bus(segment, bus_no);
- 	host_pci_dev = pci_get_slot(host_pci_bus, devfn);
+	host_pci_dev = pci_get_domain_bus_and_slot(segment, bus_no, devfn);
 
 	pcidev_info->host_pci_dev = host_pci_dev;
 	pcidev_info->pdi_linux_pcidev = dev;
diff --git a/arch/ia64/xen/irq_xen.c b/arch/ia64/xen/irq_xen.c
index 3bb1223..01f479e 100644
--- a/arch/ia64/xen/irq_xen.c
+++ b/arch/ia64/xen/irq_xen.c
@@ -433,7 +433,7 @@ xen_resend_irq(unsigned int vector)
 	(void)resend_irq_on_evtchn(vector);
 }
 
-const struct pv_irq_ops xen_irq_ops __initdata = {
+const struct pv_irq_ops xen_irq_ops __initconst = {
 	.register_ipi = xen_register_ipi,
 
 	.assign_irq_vector = xen_assign_irq_vector,
diff --git a/arch/ia64/xen/irq_xen.h b/arch/ia64/xen/irq_xen.h
index 26110f3..1778517 100644
--- a/arch/ia64/xen/irq_xen.h
+++ b/arch/ia64/xen/irq_xen.h
@@ -27,7 +27,7 @@ extern void (*late_time_init)(void);
 extern char xen_event_callback;
 void __init xen_init_IRQ(void);
 
-extern const struct pv_irq_ops xen_irq_ops __initdata;
+extern const struct pv_irq_ops xen_irq_ops __initconst;
 extern void xen_smp_intr_init(void);
 extern void xen_send_ipi(int cpu, int vec);
 
diff --git a/arch/m32r/Kconfig b/arch/m32r/Kconfig
index 49498bb..fc61533 100644
--- a/arch/m32r/Kconfig
+++ b/arch/m32r/Kconfig
@@ -13,6 +13,7 @@ config M32R
 	select GENERIC_IRQ_SHOW
 	select GENERIC_ATOMIC64
 	select ARCH_USES_GETTIMEOFFSET
+	select MODULES_USE_ELF_RELA
 
 config SBUS
 	bool
diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild
index c68e168..883a0be 100644
--- a/arch/m32r/include/asm/Kbuild
+++ b/arch/m32r/include/asm/Kbuild
@@ -1 +1,4 @@
 include include/asm-generic/Kbuild.asm
+
+generic-y	+= module.h
+generic-y += exec.h
diff --git a/arch/m32r/include/asm/elf.h b/arch/m32r/include/asm/elf.h
index b8da7d0..7089616 100644
--- a/arch/m32r/include/asm/elf.h
+++ b/arch/m32r/include/asm/elf.h
@@ -128,6 +128,7 @@ typedef elf_fpreg_t elf_fpregset_t;
    intent than poking at uname or /proc/cpuinfo.  */
 #define ELF_PLATFORM	(NULL)
 
-#define SET_PERSONALITY(ex) set_personality(PER_LINUX)
+#define SET_PERSONALITY(ex) \
+	set_personality(PER_LINUX | (current->personality & (~PER_MASK)))
 
 #endif  /* _ASM_M32R__ELF_H */
diff --git a/arch/m32r/include/asm/exec.h b/arch/m32r/include/asm/exec.h
deleted file mode 100644
index c805dbd..0000000
--- a/arch/m32r/include/asm/exec.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2001  Hiroyuki Kondo, Hirokazu Takata, and Hitoshi Yamamoto
- * Copyright (C) 2004, 2006  Hirokazu Takata <takata at linux-m32r.org>
- */
-#ifndef _ASM_M32R_EXEC_H
-#define _ASM_M32R_EXEC_H
-
-#define arch_align_stack(x) (x)
-
-#endif /* _ASM_M32R_EXEC_H */
diff --git a/arch/m32r/include/asm/module.h b/arch/m32r/include/asm/module.h
deleted file mode 100644
index eb73ee0..0000000
--- a/arch/m32r/include/asm/module.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef _ASM_M32R_MODULE_H
-#define _ASM_M32R_MODULE_H
-
-struct mod_arch_specific { };
-
-#define Elf_Shdr	Elf32_Shdr
-#define Elf_Sym		Elf32_Sym
-#define Elf_Ehdr	Elf32_Ehdr
-
-#endif /* _ASM_M32R_MODULE_H */
diff --git a/arch/m32r/include/asm/thread_info.h b/arch/m32r/include/asm/thread_info.h
index c083f60..c074f4c 100644
--- a/arch/m32r/include/asm/thread_info.h
+++ b/arch/m32r/include/asm/thread_info.h
@@ -119,25 +119,20 @@ static inline unsigned int get_thread_fault_code(void)
 #define TIF_SIGPENDING		1	/* signal pending */
 #define TIF_NEED_RESCHED	2	/* rescheduling necessary */
 #define TIF_SINGLESTEP		3	/* restore singlestep on return to user mode */
-#define TIF_IRET		4	/* return with iret */
 #define TIF_NOTIFY_RESUME	5	/* callback before returning to user */
 #define TIF_RESTORE_SIGMASK	8	/* restore signal mask in do_signal() */
 #define TIF_USEDFPU		16	/* FPU was used by this task this quantum (SMP) */
-#define TIF_POLLING_NRFLAG	17	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_MEMDIE		18	/* is terminating due to OOM killer */
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
 #define _TIF_SINGLESTEP		(1<<TIF_SINGLESTEP)
-#define _TIF_IRET		(1<<TIF_IRET)
 #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
-#define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
 #define _TIF_USEDFPU		(1<<TIF_USEDFPU)
-#define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
 
-#define _TIF_WORK_MASK		0x0000FFFE	/* work to do on interrupt/exception return */
-#define _TIF_ALLWORK_MASK	0x0000FFFF	/* work to do on any return to u-space */
+#define _TIF_WORK_MASK		(_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_NOTIFY_RESUME)
+#define _TIF_ALLWORK_MASK	(_TIF_WORK_MASK | _TIF_SYSCALL_TRACE)
 
 /*
  * Thread-synchronous status.
diff --git a/arch/m32r/kernel/module.c b/arch/m32r/kernel/module.c
index 3071fe8..38233b6 100644
--- a/arch/m32r/kernel/module.c
+++ b/arch/m32r/kernel/module.c
@@ -201,18 +201,3 @@ int apply_relocate_add(Elf32_Shdr *sechdrs,
 	}
 	return 0;
 }
-
-int apply_relocate(Elf32_Shdr *sechdrs,
-		       const char *strtab,
-		       unsigned int symindex,
-		       unsigned int relsec,
-		       struct module *me)
-{
-#if 0
-	printk(KERN_ERR "module %s: REL RELOCATION unsupported\n",
-	       me->name);
-	return -ENOEXEC;
-#endif
-	return 0;
-
-}
diff --git a/arch/m32r/kernel/process.c b/arch/m32r/kernel/process.c
index 3a4a32b..384e63f 100644
--- a/arch/m32r/kernel/process.c
+++ b/arch/m32r/kernel/process.c
@@ -26,6 +26,7 @@
 #include <linux/ptrace.h>
 #include <linux/unistd.h>
 #include <linux/hardirq.h>
+#include <linux/rcupdate.h>
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
@@ -82,6 +83,7 @@ void cpu_idle (void)
 {
 	/* endless idle loop with no priority at all */
 	while (1) {
+		rcu_idle_enter();
 		while (!need_resched()) {
 			void (*idle)(void) = pm_idle;
 
@@ -90,6 +92,7 @@ void cpu_idle (void)
 
 			idle();
 		}
+		rcu_idle_exit();
 		schedule_preempt_disabled();
 	}
 }
diff --git a/arch/m32r/kernel/signal.c b/arch/m32r/kernel/signal.c
index d0f60b9..6e3c26a 100644
--- a/arch/m32r/kernel/signal.c
+++ b/arch/m32r/kernel/signal.c
@@ -20,7 +20,6 @@
 #include <linux/unistd.h>
 #include <linux/stddef.h>
 #include <linux/personality.h>
-#include <linux/freezer.h>
 #include <linux/tracehook.h>
 #include <asm/cacheflush.h>
 #include <asm/ucontext.h>
@@ -366,6 +365,4 @@ void do_notify_resume(struct pt_regs *regs, __u32 thread_info_flags)
 		clear_thread_flag(TIF_NOTIFY_RESUME);
 		tracehook_notify_resume(regs);
 	}
-
-	clear_thread_flag(TIF_IRET);
 }
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
index b22df94..b4126a7 100644
--- a/arch/m68k/Kconfig
+++ b/arch/m68k/Kconfig
@@ -13,6 +13,10 @@ config M68K
 	select FPU if MMU
 	select ARCH_WANT_IPC_PARSE_VERSION
 	select ARCH_USES_GETTIMEOFFSET if MMU && !COLDFIRE
+	select HAVE_MOD_ARCH_SPECIFIC
+	select MODULES_USE_ELF_REL
+	select MODULES_USE_ELF_RELA
+	select GENERIC_KERNEL_THREAD
 
 config RWSEM_GENERIC_SPINLOCK
 	bool
diff --git a/arch/m68k/amiga/platform.c b/arch/m68k/amiga/platform.c
index 80076d3..6083088 100644
--- a/arch/m68k/amiga/platform.c
+++ b/arch/m68k/amiga/platform.c
@@ -56,10 +56,7 @@ static int __init amiga_init_bus(void)
 	n = AMIGAHW_PRESENT(ZORRO3) ? 4 : 2;
 	pdev = platform_device_register_simple("amiga-zorro", -1,
 					       zorro_resources, n);
-	if (IS_ERR(pdev))
-		return PTR_ERR(pdev);
-
-	return 0;
+	return PTR_RET(pdev);
 }
 
 subsys_initcall(amiga_init_bus);
diff --git a/arch/m68k/configs/amiga_defconfig b/arch/m68k/configs/amiga_defconfig
index e93fdae..90d3109 100644
--- a/arch/m68k/configs/amiga_defconfig
+++ b/arch/m68k/configs/amiga_defconfig
@@ -67,7 +67,6 @@ CONFIG_NETFILTER_XT_TARGET_DSCP=m
 CONFIG_NETFILTER_XT_TARGET_MARK=m
 CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
-CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
 CONFIG_NETFILTER_XT_TARGET_TRACE=m
 CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
 CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
diff --git a/arch/m68k/configs/apollo_defconfig b/arch/m68k/configs/apollo_defconfig
index 66b26c1..8f4f657 100644
--- a/arch/m68k/configs/apollo_defconfig
+++ b/arch/m68k/configs/apollo_defconfig
@@ -67,7 +67,6 @@ CONFIG_NETFILTER_XT_TARGET_DSCP=m
 CONFIG_NETFILTER_XT_TARGET_MARK=m
 CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
-CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
 CONFIG_NETFILTER_XT_TARGET_TRACE=m
 CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
 CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
diff --git a/arch/m68k/configs/atari_defconfig b/arch/m68k/configs/atari_defconfig
index 1513325..4571d33 100644
--- a/arch/m68k/configs/atari_defconfig
+++ b/arch/m68k/configs/atari_defconfig
@@ -65,7 +65,6 @@ CONFIG_NETFILTER_XT_TARGET_DSCP=m
 CONFIG_NETFILTER_XT_TARGET_MARK=m
 CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
-CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
 CONFIG_NETFILTER_XT_TARGET_TRACE=m
 CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
 CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
diff --git a/arch/m68k/configs/bvme6000_defconfig b/arch/m68k/configs/bvme6000_defconfig
index 67bb6fc..12f2117 100644
--- a/arch/m68k/configs/bvme6000_defconfig
+++ b/arch/m68k/configs/bvme6000_defconfig
@@ -65,7 +65,6 @@ CONFIG_NETFILTER_XT_TARGET_DSCP=m
 CONFIG_NETFILTER_XT_TARGET_MARK=m
 CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
-CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
 CONFIG_NETFILTER_XT_TARGET_TRACE=m
 CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
 CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
diff --git a/arch/m68k/configs/hp300_defconfig b/arch/m68k/configs/hp300_defconfig
index 3e35ce5..215389a 100644
--- a/arch/m68k/configs/hp300_defconfig
+++ b/arch/m68k/configs/hp300_defconfig
@@ -66,7 +66,6 @@ CONFIG_NETFILTER_XT_TARGET_DSCP=m
 CONFIG_NETFILTER_XT_TARGET_MARK=m
 CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
-CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
 CONFIG_NETFILTER_XT_TARGET_TRACE=m
 CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
 CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
diff --git a/arch/m68k/configs/mac_defconfig b/arch/m68k/configs/mac_defconfig
index ae81e2d..cb9dfb3 100644
--- a/arch/m68k/configs/mac_defconfig
+++ b/arch/m68k/configs/mac_defconfig
@@ -61,7 +61,6 @@ CONFIG_NETFILTER_XT_TARGET_DSCP=m
 CONFIG_NETFILTER_XT_TARGET_MARK=m
 CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
-CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
 CONFIG_NETFILTER_XT_TARGET_TRACE=m
 CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
 CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
diff --git a/arch/m68k/configs/multi_defconfig b/arch/m68k/configs/multi_defconfig
index 55d394e..8d5def4 100644
--- a/arch/m68k/configs/multi_defconfig
+++ b/arch/m68k/configs/multi_defconfig
@@ -80,7 +80,6 @@ CONFIG_NETFILTER_XT_TARGET_DSCP=m
 CONFIG_NETFILTER_XT_TARGET_MARK=m
 CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
-CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
 CONFIG_NETFILTER_XT_TARGET_TRACE=m
 CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
 CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
diff --git a/arch/m68k/configs/mvme147_defconfig b/arch/m68k/configs/mvme147_defconfig
index af77374..e2af46f 100644
--- a/arch/m68k/configs/mvme147_defconfig
+++ b/arch/m68k/configs/mvme147_defconfig
@@ -64,7 +64,6 @@ CONFIG_NETFILTER_XT_TARGET_DSCP=m
 CONFIG_NETFILTER_XT_TARGET_MARK=m
 CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
-CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
 CONFIG_NETFILTER_XT_TARGET_TRACE=m
 CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
 CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
diff --git a/arch/m68k/configs/mvme16x_defconfig b/arch/m68k/configs/mvme16x_defconfig
index cdb70d6..7c9402b 100644
--- a/arch/m68k/configs/mvme16x_defconfig
+++ b/arch/m68k/configs/mvme16x_defconfig
@@ -65,7 +65,6 @@ CONFIG_NETFILTER_XT_TARGET_DSCP=m
 CONFIG_NETFILTER_XT_TARGET_MARK=m
 CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
-CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
 CONFIG_NETFILTER_XT_TARGET_TRACE=m
 CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
 CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
diff --git a/arch/m68k/configs/q40_defconfig b/arch/m68k/configs/q40_defconfig
index 46bed78..19d23db 100644
--- a/arch/m68k/configs/q40_defconfig
+++ b/arch/m68k/configs/q40_defconfig
@@ -61,7 +61,6 @@ CONFIG_NETFILTER_XT_TARGET_DSCP=m
 CONFIG_NETFILTER_XT_TARGET_MARK=m
 CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
-CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
 CONFIG_NETFILTER_XT_TARGET_TRACE=m
 CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
 CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
diff --git a/arch/m68k/configs/sun3_defconfig b/arch/m68k/configs/sun3_defconfig
index 86f7772..ca6c0b4 100644
--- a/arch/m68k/configs/sun3_defconfig
+++ b/arch/m68k/configs/sun3_defconfig
@@ -62,7 +62,6 @@ CONFIG_NETFILTER_XT_TARGET_DSCP=m
 CONFIG_NETFILTER_XT_TARGET_MARK=m
 CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
-CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
 CONFIG_NETFILTER_XT_TARGET_TRACE=m
 CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
 CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
diff --git a/arch/m68k/configs/sun3x_defconfig b/arch/m68k/configs/sun3x_defconfig
index 2882614..c80941c 100644
--- a/arch/m68k/configs/sun3x_defconfig
+++ b/arch/m68k/configs/sun3x_defconfig
@@ -62,7 +62,6 @@ CONFIG_NETFILTER_XT_TARGET_DSCP=m
 CONFIG_NETFILTER_XT_TARGET_MARK=m
 CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
-CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
 CONFIG_NETFILTER_XT_TARGET_TRACE=m
 CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
 CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
diff --git a/arch/m68k/emu/nfcon.c b/arch/m68k/emu/nfcon.c
index 8db25e8..16d170f 100644
--- a/arch/m68k/emu/nfcon.c
+++ b/arch/m68k/emu/nfcon.c
@@ -19,6 +19,7 @@
 #include <asm/natfeat.h>
 
 static int stderr_id;
+static struct tty_port nfcon_tty_port;
 static struct tty_driver *nfcon_tty_driver;
 
 static void nfputs(const char *str, unsigned int count)
@@ -119,6 +120,8 @@ static int __init nfcon_init(void)
 {
 	int res;
 
+	tty_port_init(&nfcon_tty_port);
+
 	stderr_id = nf_get_id("NF_STDERR");
 	if (!stderr_id)
 		return -ENODEV;
@@ -135,6 +138,7 @@ static int __init nfcon_init(void)
 	nfcon_tty_driver->flags = TTY_DRIVER_REAL_RAW;
 
 	tty_set_operations(nfcon_tty_driver, &nfcon_tty_ops);
+	tty_port_link_device(&nfcon_tty_port, nfcon_tty_driver, 0);
 	res = tty_register_driver(nfcon_tty_driver);
 	if (res) {
 		pr_err("failed to register nfcon tty driver\n");
diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild
index a74e5d9..a9d1bf1 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -6,6 +6,7 @@ generic-y += cputime.h
 generic-y += device.h
 generic-y += emergency-restart.h
 generic-y += errno.h
+generic-y += exec.h
 generic-y += futex.h
 generic-y += ioctl.h
 generic-y += ipcbuf.h
diff --git a/arch/m68k/include/asm/apollohw.h b/arch/m68k/include/asm/apollohw.h
index 635ef4f..6c19e0c 100644
--- a/arch/m68k/include/asm/apollohw.h
+++ b/arch/m68k/include/asm/apollohw.h
@@ -46,18 +46,6 @@ struct SCN2681 {
 
 };
 
-#if 0
-struct mc146818 {
-
-	unsigned int second1:4, second2:4, alarm_second1:4, alarm_second2:4,
-		     minute1:4, minute2:4, alarm_minute1:4, alarm_minute2:4;
-	unsigned int hours1:4, hours2:4, alarm_hours1:4, alarm_hours2:4,
-		     day_of_week1:4, day_of_week2:4, day_of_month1:4, day_of_month2:4;
-	unsigned int month1:4, month2:4, year1:4, year2:4, :16;
-
-};
-#endif
-
 struct mc146818 {
         unsigned char second, alarm_second;
         unsigned char minute, alarm_minute;
diff --git a/arch/m68k/include/asm/cacheflush_no.h b/arch/m68k/include/asm/cacheflush_no.h
index 7cafb53..d2b3935 100644
--- a/arch/m68k/include/asm/cacheflush_no.h
+++ b/arch/m68k/include/asm/cacheflush_no.h
@@ -34,10 +34,9 @@ static inline void __clear_cache_all(void)
 {
 #ifdef CACHE_INVALIDATE
 	__asm__ __volatile__ (
-		"movel	%0, %%d0\n\t"
-		"movec	%%d0, %%CACR\n\t"
+		"movec	%0, %%CACR\n\t"
 		"nop\n\t"
-		: : "i" (CACHE_INVALIDATE) : "d0" );
+		: : "r" (CACHE_INVALIDATE) );
 #endif
 }
 
@@ -58,10 +57,9 @@ static inline void __flush_icache_all(void)
 {
 #ifdef CACHE_INVALIDATEI
 	__asm__ __volatile__ (
-		"movel	%0, %%d0\n\t"
-		"movec	%%d0, %%CACR\n\t"
+		"movec	%0, %%CACR\n\t"
 		"nop\n\t"
-		: : "i" (CACHE_INVALIDATEI) : "d0" );
+		: : "r" (CACHE_INVALIDATEI) );
 #endif
 }
 
@@ -72,19 +70,18 @@ static inline void __flush_dcache_all(void)
 #endif
 #ifdef CACHE_INVALIDATED
 	__asm__ __volatile__ (
-		"movel	%0, %%d0\n\t"
-		"movec	%%d0, %%CACR\n\t"
+		"movec	%0, %%CACR\n\t"
 		"nop\n\t"
-		: : "i" (CACHE_INVALIDATED) : "d0" );
+		: : "r" (CACHE_INVALIDATED) );
 #else
-	/* Flush the wrtite buffer */
+	/* Flush the write buffer */
 	__asm__ __volatile__ ( "nop" );
 #endif
 }
 
 /*
  * Push cache entries at supplied address. We want to write back any dirty
- * data and the invalidate the cache lines associated with this address.
+ * data and then invalidate the cache lines associated with this address.
  */
 static inline void cache_push(unsigned long paddr, int len)
 {
diff --git a/arch/m68k/include/asm/elf.h b/arch/m68k/include/asm/elf.h
index e9b7cda..f83c1d0 100644
--- a/arch/m68k/include/asm/elf.h
+++ b/arch/m68k/include/asm/elf.h
@@ -113,6 +113,7 @@ typedef struct user_m68kfp_struct elf_fpregset_t;
 
 #define ELF_PLATFORM  (NULL)
 
-#define SET_PERSONALITY(ex) set_personality(PER_LINUX)
+#define SET_PERSONALITY(ex) \
+	set_personality(PER_LINUX | (current->personality & (~PER_MASK)))
 
 #endif
diff --git a/arch/m68k/include/asm/exec.h b/arch/m68k/include/asm/exec.h
deleted file mode 100644
index 0499adf..0000000
--- a/arch/m68k/include/asm/exec.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _M68K_EXEC_H
-#define _M68K_EXEC_H
-
-#define arch_align_stack(x) (x)
-
-#endif /* _M68K_EXEC_H */
diff --git a/arch/m68k/include/asm/module.h b/arch/m68k/include/asm/module.h
index edffe66..8b58fce 100644
--- a/arch/m68k/include/asm/module.h
+++ b/arch/m68k/include/asm/module.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_M68K_MODULE_H
 #define _ASM_M68K_MODULE_H
 
+#include <asm-generic/module.h>
+
 enum m68k_fixup_type {
 	m68k_fixup_memoffset,
 	m68k_fixup_vnode_shift,
@@ -36,8 +38,4 @@ struct module;
 extern void module_fixup(struct module *mod, struct m68k_fixup_info *start,
 			 struct m68k_fixup_info *end);
 
-#define Elf_Shdr Elf32_Shdr
-#define Elf_Sym Elf32_Sym
-#define Elf_Ehdr Elf32_Ehdr
-
 #endif /* _ASM_M68K_MODULE_H */
diff --git a/arch/m68k/include/asm/processor.h b/arch/m68k/include/asm/processor.h
index f17c42a..ae700f4 100644
--- a/arch/m68k/include/asm/processor.h
+++ b/arch/m68k/include/asm/processor.h
@@ -100,6 +100,16 @@ struct thread_struct {
 	.fs	= __KERNEL_DS,						\
 }
 
+/*
+ * ColdFire stack format sbould be 0x4 for an aligned usp (will always be
+ * true on thread creation). We need to set this explicitly.
+ */
+#ifdef CONFIG_COLDFIRE
+#define setframeformat(_regs)	do { (_regs)->format = 0x4; } while(0)
+#else
+#define setframeformat(_regs)	do { } while (0)
+#endif
+
 #ifdef CONFIG_MMU
 /*
  * Do necessary setup to start up a newly executed thread.
@@ -109,6 +119,7 @@ static inline void start_thread(struct pt_regs * regs, unsigned long pc,
 {
 	regs->pc = pc;
 	regs->sr &= ~0x2000;
+	setframeformat(regs);
 	wrusp(usp);
 }
 
@@ -116,21 +127,11 @@ extern int handle_kernel_fault(struct pt_regs *regs);
 
 #else
 
-/*
- * Coldfire stacks need to be re-aligned on trap exit, conventional
- * 68k can handle this case cleanly.
- */
-#ifdef CONFIG_COLDFIRE
-#define reformat(_regs)		do { (_regs)->format = 0x4; } while(0)
-#else
-#define reformat(_regs)		do { } while (0)
-#endif
-
 #define start_thread(_regs, _pc, _usp)                  \
 do {                                                    \
 	(_regs)->pc = (_pc);                            \
 	((struct switch_stack *)(_regs))[-1].a6 = 0;    \
-	reformat(_regs);                                \
+	setframeformat(_regs);                          \
 	if (current->mm)                                \
 		(_regs)->d5 = current->mm->start_data;  \
 	(_regs)->sr &= ~0x2000;                         \
@@ -153,8 +154,6 @@ static inline void release_thread(struct task_struct *dead_task)
 {
 }
 
-extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
-
 /*
  * Free current thread data structures etc..
  */
diff --git a/arch/m68k/include/asm/ptrace.h b/arch/m68k/include/asm/ptrace.h
index 65322b1..5e08b59 100644
--- a/arch/m68k/include/asm/ptrace.h
+++ b/arch/m68k/include/asm/ptrace.h
@@ -85,6 +85,8 @@ struct switch_stack {
 #define user_mode(regs) (!((regs)->sr & PS_S))
 #define instruction_pointer(regs) ((regs)->pc)
 #define profile_pc(regs) instruction_pointer(regs)
+#define current_pt_regs() \
+	(struct pt_regs *)((char *)current_thread_info() + THREAD_SIZE) - 1
 
 #define arch_has_single_step()	(1)
 
diff --git a/arch/m68k/include/asm/unistd.h b/arch/m68k/include/asm/unistd.h
index 045cfd6..c702ad7 100644
--- a/arch/m68k/include/asm/unistd.h
+++ b/arch/m68k/include/asm/unistd.h
@@ -382,6 +382,8 @@
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_RT_SIGACTION
 #define __ARCH_WANT_SYS_RT_SIGSUSPEND
+#define __ARCH_WANT_SYS_EXECVE
+#define __ARCH_WANT_KERNEL_EXECVE
 
 /*
  * "Conditional" syscalls
diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S
index 165ee9f..946cb01 100644
--- a/arch/m68k/kernel/entry.S
+++ b/arch/m68k/kernel/entry.S
@@ -111,6 +111,22 @@ ENTRY(ret_from_fork)
 	addql	#4,%sp
 	jra	ret_from_exception
 
+ENTRY(ret_from_kernel_thread)
+	| a3 contains the kernel thread payload, d7 - its argument
+	movel	%d1,%sp@-
+	jsr	schedule_tail
+	GET_CURRENT(%d0)
+	movel	%d7,(%sp)
+	jsr	%a3@
+	addql	#4,%sp
+	movel	%d0,(%sp)
+	jra	sys_exit
+
+ENTRY(ret_from_kernel_execve)
+	movel	4(%sp), %sp
+	GET_CURRENT(%d0)
+	jra	ret_from_exception
+
 #if defined(CONFIG_COLDFIRE) || !defined(CONFIG_MMU)
 
 #ifdef TRAP_DBG_INTERRUPT
diff --git a/arch/m68k/kernel/pcibios.c b/arch/m68k/kernel/pcibios.c
index b2988aa..73fa0b5 100644
--- a/arch/m68k/kernel/pcibios.c
+++ b/arch/m68k/kernel/pcibios.c
@@ -87,11 +87,6 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
 	return 0;
 }
 
-void pcibios_update_irq(struct pci_dev *dev, int irq)
-{
-	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
-}
-
 void __devinit pcibios_fixup_bus(struct pci_bus *bus)
 {
 	struct pci_dev *dev;
diff --git a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c
index c488e3c..c51bb17 100644
--- a/arch/m68k/kernel/process.c
+++ b/arch/m68k/kernel/process.c
@@ -25,6 +25,7 @@
 #include <linux/reboot.h>
 #include <linux/init_task.h>
 #include <linux/mqueue.h>
+#include <linux/rcupdate.h>
 
 #include <asm/uaccess.h>
 #include <asm/traps.h>
@@ -34,6 +35,7 @@
 
 
 asmlinkage void ret_from_fork(void);
+asmlinkage void ret_from_kernel_thread(void);
 
 
 /*
@@ -75,8 +77,10 @@ void cpu_idle(void)
 {
 	/* endless idle loop with no priority at all */
 	while (1) {
+		rcu_idle_enter();
 		while (!need_resched())
 			idle();
+		rcu_idle_exit();
 		schedule_preempt_disabled();
 	}
 }
@@ -120,51 +124,6 @@ void show_regs(struct pt_regs * regs)
 		printk("USP: %08lx\n", rdusp());
 }
 
-/*
- * Create a kernel thread
- */
-int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
-{
-	int pid;
-	mm_segment_t fs;
-
-	fs = get_fs();
-	set_fs (KERNEL_DS);
-
-	{
-	register long retval __asm__ ("d0");
-	register long clone_arg __asm__ ("d1") = flags | CLONE_VM | CLONE_UNTRACED;
-
-	retval = __NR_clone;
-	__asm__ __volatile__
-	  ("clrl %%d2\n\t"
-	   "trap #0\n\t"		/* Linux/m68k system call */
-	   "tstl %0\n\t"		/* child or parent */
-	   "jne 1f\n\t"			/* parent - jump */
-#ifdef CONFIG_MMU
-	   "lea %%sp@(%c7),%6\n\t"	/* reload current */
-	   "movel %6@,%6\n\t"
-#endif
-	   "movel %3,%%sp@-\n\t"	/* push argument */
-	   "jsr %4@\n\t"		/* call fn */
-	   "movel %0,%%d1\n\t"		/* pass exit value */
-	   "movel %2,%%d0\n\t"		/* exit */
-	   "trap #0\n"
-	   "1:"
-	   : "+d" (retval)
-	   : "i" (__NR_clone), "i" (__NR_exit),
-	     "r" (arg), "a" (fn), "d" (clone_arg), "r" (current),
-	     "i" (-THREAD_SIZE)
-	   : "d2");
-
-	pid = retval;
-	}
-
-	set_fs (fs);
-	return pid;
-}
-EXPORT_SYMBOL(kernel_thread);
-
 void flush_thread(void)
 {
 	current->thread.fs = __USER_DS;
@@ -216,30 +175,18 @@ asmlinkage int m68k_clone(struct pt_regs *regs)
 }
 
 int copy_thread(unsigned long clone_flags, unsigned long usp,
-		 unsigned long unused,
+		 unsigned long arg,
 		 struct task_struct * p, struct pt_regs * regs)
 {
 	struct pt_regs * childregs;
-	struct switch_stack * childstack, *stack;
-	unsigned long *retp;
+	struct switch_stack *childstack;
 
 	childregs = (struct pt_regs *) (task_stack_page(p) + THREAD_SIZE) - 1;
-
-	*childregs = *regs;
-	childregs->d0 = 0;
-
-	retp = ((unsigned long *) regs);
-	stack = ((struct switch_stack *) retp) - 1;
-
 	childstack = ((struct switch_stack *) childregs) - 1;
-	*childstack = *stack;
-	childstack->retpc = (unsigned long)ret_from_fork;
 
 	p->thread.usp = usp;
 	p->thread.ksp = (unsigned long)childstack;
-
-	if (clone_flags & CLONE_SETTLS)
-		task_thread_info(p)->tp_value = regs->d5;
+	p->thread.esp0 = (unsigned long)childregs;
 
 	/*
 	 * Must save the current SFC/DFC value, NOT the value when
@@ -247,6 +194,26 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
 	 */
 	p->thread.fs = get_fs().seg;
 
+	if (unlikely(!regs)) {
+		/* kernel thread */
+		memset(childstack, 0,
+			sizeof(struct switch_stack) + sizeof(struct pt_regs));
+		childregs->sr = PS_S;
+		childstack->a3 = usp; /* function */
+		childstack->d7 = arg;
+		childstack->retpc = (unsigned long)ret_from_kernel_thread;
+		p->thread.usp = 0;
+		return 0;
+	}
+	*childregs = *regs;
+	childregs->d0 = 0;
+
+	*childstack = ((struct switch_stack *) regs)[-1];
+	childstack->retpc = (unsigned long)ret_from_fork;
+
+	if (clone_flags & CLONE_SETTLS)
+		task_thread_info(p)->tp_value = regs->d5;
+
 #ifdef CONFIG_FPU
 	if (!FPU_IS_EMU) {
 		/* Copy the current fpu state */
@@ -334,26 +301,6 @@ int dump_fpu (struct pt_regs *regs, struct user_m68kfp_struct *fpu)
 EXPORT_SYMBOL(dump_fpu);
 #endif /* CONFIG_FPU */
 
-/*
- * sys_execve() executes a new program.
- */
-asmlinkage int sys_execve(const char __user *name,
-			  const char __user *const __user *argv,
-			  const char __user *const __user *envp)
-{
-	int error;
-	char * filename;
-	struct pt_regs *regs = (struct pt_regs *) &name;
-
-	filename = getname(name);
-	error = PTR_ERR(filename);
-	if (IS_ERR(filename))
-		return error;
-	error = do_execve(filename, argv, envp, regs);
-	putname(filename);
-	return error;
-}
-
 unsigned long get_wchan(struct task_struct *p)
 {
 	unsigned long fp, pc;
diff --git a/arch/m68k/kernel/sys_m68k.c b/arch/m68k/kernel/sys_m68k.c
index 9a5932e..3a480b3 100644
--- a/arch/m68k/kernel/sys_m68k.c
+++ b/arch/m68k/kernel/sys_m68k.c
@@ -549,23 +549,6 @@ asmlinkage int sys_getpagesize(void)
 	return PAGE_SIZE;
 }
 
-/*
- * Do a system call from kernel instead of calling sys_execve so we
- * end up with proper pt_regs.
- */
-int kernel_execve(const char *filename,
-		  const char *const argv[],
-		  const char *const envp[])
-{
-	register long __res asm ("%d0") = __NR_execve;
-	register long __a asm ("%d1") = (long)(filename);
-	register long __b asm ("%d2") = (long)(argv);
-	register long __c asm ("%d3") = (long)(envp);
-	asm volatile ("trap  #0" : "+d" (__res)
-			: "d" (__a), "d" (__b), "d" (__c));
-	return __res;
-}
-
 asmlinkage unsigned long sys_get_thread_area(void)
 {
 	return current_thread_info()->tp_value;
diff --git a/arch/m68k/kernel/time.c b/arch/m68k/kernel/time.c
index 707f057..5d0bcaa 100644
--- a/arch/m68k/kernel/time.c
+++ b/arch/m68k/kernel/time.c
@@ -100,10 +100,7 @@ static int __init rtc_init(void)
 		return -ENODEV;
 
 	pdev = platform_device_register_simple("rtc-generic", -1, NULL, 0);
-	if (IS_ERR(pdev))
-		return PTR_ERR(pdev);
-
-	return 0;
+	return PTR_RET(pdev);
 }
 
 module_init(rtc_init);
diff --git a/arch/m68k/mm/fault.c b/arch/m68k/mm/fault.c
index aeebbb7..a563727 100644
--- a/arch/m68k/mm/fault.c
+++ b/arch/m68k/mm/fault.c
@@ -170,6 +170,7 @@ good_area:
 			/* Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk
 			 * of starvation. */
 			flags &= ~FAULT_FLAG_ALLOW_RETRY;
+			flags |= FAULT_FLAG_TRIED;
 
 			/*
 			 * No need to up_read(&mm->mmap_sem) as we would
diff --git a/arch/m68k/platform/68VZ328/Makefile b/arch/m68k/platform/68VZ328/Makefile
index a49d75e..8166741 100644
--- a/arch/m68k/platform/68VZ328/Makefile
+++ b/arch/m68k/platform/68VZ328/Makefile
@@ -1,11 +1,5 @@
 #
-# Makefile for arch/m68knommu/platform/68VZ328.
+# Makefile for arch/m68k/platform/68VZ328.
 #
 
 obj-y		:= config.o
-extra-$(DRAGEN2):= screen.h
-
-$(obj)/screen.h: $(src)/screen.xbm $(src)/xbm2lcd.pl
-	perl $(src)/xbm2lcd.pl < $(src)/screen.xbm > $(obj)/screen.h
-
-clean-files := $(obj)/screen.h
diff --git a/arch/m68k/q40/config.c b/arch/m68k/q40/config.c
index 8a1ce32..1adb5b7 100644
--- a/arch/m68k/q40/config.c
+++ b/arch/m68k/q40/config.c
@@ -338,9 +338,6 @@ static __init int q40_add_kbd_device(void)
 		return -ENODEV;
 
 	pdev = platform_device_register_simple("q40kbd", -1, NULL, 0);
-	if (IS_ERR(pdev))
-		return PTR_ERR(pdev);
-
-	return 0;
+	return PTR_RET(pdev);
 }
 arch_initcall(q40_add_kbd_device);
diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig
index ab9afca..b4f409f 100644
--- a/arch/microblaze/Kconfig
+++ b/arch/microblaze/Kconfig
@@ -24,6 +24,7 @@ config MICROBLAZE
 	select GENERIC_CPU_DEVICES
 	select GENERIC_ATOMIC64
 	select GENERIC_CLOCKEVENTS
+	select MODULES_USE_ELF_RELA
 
 config SWAP
 	def_bool n
diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild
index db5294c..5a0e72b 100644
--- a/arch/microblaze/include/asm/Kbuild
+++ b/arch/microblaze/include/asm/Kbuild
@@ -1,3 +1,4 @@
 include include/asm-generic/Kbuild.asm
 
 header-y  += elf.h
+generic-y += exec.h
diff --git a/arch/microblaze/include/asm/atomic.h b/arch/microblaze/include/asm/atomic.h
index 472d8bf..42ac382 100644
--- a/arch/microblaze/include/asm/atomic.h
+++ b/arch/microblaze/include/asm/atomic.h
@@ -22,5 +22,6 @@ static inline int atomic_dec_if_positive(atomic_t *v)
 
 	return res;
 }
+#define atomic_dec_if_positive atomic_dec_if_positive
 
 #endif /* _ASM_MICROBLAZE_ATOMIC_H */
diff --git a/arch/microblaze/include/asm/elf.h b/arch/microblaze/include/asm/elf.h
index 834849f..640ddd4 100644
--- a/arch/microblaze/include/asm/elf.h
+++ b/arch/microblaze/include/asm/elf.h
@@ -116,7 +116,8 @@ do {							\
 } while (0)
 
 #ifdef __KERNEL__
-#define SET_PERSONALITY(ex) set_personality(PER_LINUX_32BIT)
+#define SET_PERSONALITY(ex) \
+	set_personality(PER_LINUX_32BIT | (current->personality & (~PER_MASK)))
 #endif
 
 #endif /* __uClinux__ */
diff --git a/arch/microblaze/include/asm/exec.h b/arch/microblaze/include/asm/exec.h
deleted file mode 100644
index e750de1..0000000
--- a/arch/microblaze/include/asm/exec.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * This file is subject to 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_MICROBLAZE_EXEC_H
-#define _ASM_MICROBLAZE_EXEC_H
-
-#define arch_align_stack(x) (x)
-
-#endif /* _ASM_MICROBLAZE_EXEC_H */
diff --git a/arch/microblaze/include/asm/thread_info.h b/arch/microblaze/include/asm/thread_info.h
index 6c610234..008f304 100644
--- a/arch/microblaze/include/asm/thread_info.h
+++ b/arch/microblaze/include/asm/thread_info.h
@@ -121,7 +121,6 @@ static inline struct thread_info *current_thread_info(void)
 #define TIF_NEED_RESCHED	3 /* rescheduling necessary */
 /* restore singlestep on return to user mode */
 #define TIF_SINGLESTEP		4
-#define TIF_IRET		5 /* return with iret */
 #define TIF_MEMDIE		6	/* is terminating due to OOM killer */
 #define TIF_SYSCALL_AUDIT	9       /* syscall auditing active */
 #define TIF_SECCOMP		10      /* secure computing */
@@ -134,7 +133,6 @@ static inline struct thread_info *current_thread_info(void)
 #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1 << TIF_NEED_RESCHED)
 #define _TIF_SINGLESTEP		(1 << TIF_SINGLESTEP)
-#define _TIF_IRET		(1 << TIF_IRET)
 #define _TIF_POLLING_NRFLAG	(1 << TIF_POLLING_NRFLAG)
 #define _TIF_SYSCALL_AUDIT	(1 << TIF_SYSCALL_AUDIT)
 #define _TIF_SECCOMP		(1 << TIF_SECCOMP)
@@ -184,6 +182,7 @@ static inline bool test_and_clear_restore_sigmask(void)
 	ti->status &= ~TS_RESTORE_SIGMASK;
 	return true;
 }
+#define tsk_is_polling(t) test_tsk_thread_flag(t, TIF_POLLING_NRFLAG)
 #endif
 
 #endif /* __KERNEL__ */
diff --git a/arch/microblaze/kernel/signal.c b/arch/microblaze/kernel/signal.c
index 76b9722..0d27fdb 100644
--- a/arch/microblaze/kernel/signal.c
+++ b/arch/microblaze/kernel/signal.c
@@ -254,10 +254,6 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 
 	set_fs(USER_DS);
 
-	/* the tracer may want to single-step inside the handler */
-	if (test_thread_flag(TIF_SINGLESTEP))
-		ptrace_notify(SIGTRAP);
-
 #ifdef DEBUG_SIG
 	printk(KERN_INFO "SIG deliver (%s:%d): sp=%p pc=%08lx\n",
 		current->comm, current->pid, frame, regs->pc);
@@ -323,7 +319,8 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
 	if (ret)
 		return;
 
-	signal_delivered(sig, info, ka, regs, 0);
+	signal_delivered(sig, info, ka, regs,
+			test_thread_flag(TIF_SINGLESTEP));
 }
 
 /*
diff --git a/arch/microblaze/mm/fault.c b/arch/microblaze/mm/fault.c
index eb365d6..714b35a 100644
--- a/arch/microblaze/mm/fault.c
+++ b/arch/microblaze/mm/fault.c
@@ -233,6 +233,7 @@ good_area:
 			current->min_flt++;
 		if (fault & VM_FAULT_RETRY) {
 			flags &= ~FAULT_FLAG_ALLOW_RETRY;
+			flags |= FAULT_FLAG_TRIED;
 
 			/*
 			 * No need to up_read(&mm->mmap_sem) as we would
diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms
index d64786d..0759dd2 100644
--- a/arch/mips/Kbuild.platforms
+++ b/arch/mips/Kbuild.platforms
@@ -15,7 +15,6 @@ platforms += lantiq
 platforms += lasat
 platforms += loongson
 platforms += loongson1
-platforms += mipssim
 platforms += mti-malta
 platforms += netlogic
 platforms += pmc-sierra
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index faf6528..ccfdd7e 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -8,6 +8,7 @@ config MIPS
 	select HAVE_PERF_EVENTS
 	select PERF_USE_VMALLOC
 	select HAVE_ARCH_KGDB
+	select HAVE_ARCH_TRACEHOOK
 	select ARCH_HAVE_CUSTOM_GPIO_H
 	select HAVE_FUNCTION_TRACER
 	select HAVE_FUNCTION_TRACE_MCOUNT_TEST
@@ -36,6 +37,9 @@ config MIPS
 	select BUILDTIME_EXTABLE_SORT
 	select GENERIC_CLOCKEVENTS
 	select GENERIC_CMOS_UPDATE
+	select HAVE_MOD_ARCH_SPECIFIC
+	select MODULES_USE_ELF_REL
+	select MODULES_USE_ELF_RELA if 64BIT
 
 menu "Machine selection"
 
@@ -320,25 +324,6 @@ config MIPS_MALTA
 	  This enables support for the MIPS Technologies Malta evaluation
 	  board.
 
-config MIPS_SIM
-	bool 'MIPS simulator (MIPSsim)'
-	select CEVT_R4K
-	select CSRC_R4K
-	select DMA_NONCOHERENT
-	select SYS_HAS_EARLY_PRINTK
-	select IRQ_CPU
-	select BOOT_RAW
-	select SYS_HAS_CPU_MIPS32_R1
-	select SYS_HAS_CPU_MIPS32_R2
-	select SYS_HAS_EARLY_PRINTK
-	select SYS_SUPPORTS_32BIT_KERNEL
-	select SYS_SUPPORTS_BIG_ENDIAN
-	select SYS_SUPPORTS_MULTITHREADING
-	select SYS_SUPPORTS_LITTLE_ENDIAN
-	help
-	  This option enables support for MIPS Technologies MIPSsim software
-	  emulator.
-
 config NEC_MARKEINS
 	bool "NEC EMMA2RH Mark-eins board"
 	select SOC_EMMA2RH
@@ -2360,12 +2345,10 @@ config SECCOMP
 	  If unsure, say Y. Only embedded should say N here.
 
 config USE_OF
-	bool "Flattened Device Tree support"
+	bool
 	select OF
 	select OF_EARLY_FLATTREE
 	select IRQ_DOMAIN
-	help
-	  Include support for flattened device tree machine descriptions.
 
 endmenu
 
diff --git a/arch/mips/ath79/clock.c b/arch/mips/ath79/clock.c
index b91ad3e..579f452 100644
--- a/arch/mips/ath79/clock.c
+++ b/arch/mips/ath79/clock.c
@@ -17,6 +17,8 @@
 #include <linux/err.h>
 #include <linux/clk.h>
 
+#include <asm/div64.h>
+
 #include <asm/mach-ath79/ath79.h>
 #include <asm/mach-ath79/ar71xx_regs.h>
 #include "common.h"
@@ -166,11 +168,34 @@ static void __init ar933x_clocks_init(void)
 	ath79_uart_clk.rate = ath79_ref_clk.rate;
 }
 
+static u32 __init ar934x_get_pll_freq(u32 ref, u32 ref_div, u32 nint, u32 nfrac,
+				      u32 frac, u32 out_div)
+{
+	u64 t;
+	u32 ret;
+
+	t = ath79_ref_clk.rate;
+	t *= nint;
+	do_div(t, ref_div);
+	ret = t;
+
+	t = ath79_ref_clk.rate;
+	t *= nfrac;
+	do_div(t, ref_div * frac);
+	ret += t;
+
+	ret /= (1 << out_div);
+	return ret;
+}
+
 static void __init ar934x_clocks_init(void)
 {
-	u32 pll, out_div, ref_div, nint, frac, clk_ctrl, postdiv;
+	u32 pll, out_div, ref_div, nint, nfrac, frac, clk_ctrl, postdiv;
 	u32 cpu_pll, ddr_pll;
 	u32 bootstrap;
+	void __iomem *dpll_base;
+
+	dpll_base = ioremap(AR934X_SRIF_BASE, AR934X_SRIF_SIZE);
 
 	bootstrap = ath79_reset_rr(AR934X_RESET_REG_BOOTSTRAP);
 	if (bootstrap &	AR934X_BOOTSTRAP_REF_CLK_40)
@@ -178,33 +203,59 @@ static void __init ar934x_clocks_init(void)
 	else
 		ath79_ref_clk.rate = 25 * 1000 * 1000;
 
-	pll = ath79_pll_rr(AR934X_PLL_CPU_CONFIG_REG);
-	out_div = (pll >> AR934X_PLL_CPU_CONFIG_OUTDIV_SHIFT) &
-		  AR934X_PLL_CPU_CONFIG_OUTDIV_MASK;
-	ref_div = (pll >> AR934X_PLL_CPU_CONFIG_REFDIV_SHIFT) &
-		  AR934X_PLL_CPU_CONFIG_REFDIV_MASK;
-	nint = (pll >> AR934X_PLL_CPU_CONFIG_NINT_SHIFT) &
-	       AR934X_PLL_CPU_CONFIG_NINT_MASK;
-	frac = (pll >> AR934X_PLL_CPU_CONFIG_NFRAC_SHIFT) &
-	       AR934X_PLL_CPU_CONFIG_NFRAC_MASK;
-
-	cpu_pll = nint * ath79_ref_clk.rate / ref_div;
-	cpu_pll += frac * ath79_ref_clk.rate / (ref_div * (2 << 6));
-	cpu_pll /= (1 << out_div);
-
-	pll = ath79_pll_rr(AR934X_PLL_DDR_CONFIG_REG);
-	out_div = (pll >> AR934X_PLL_DDR_CONFIG_OUTDIV_SHIFT) &
-		  AR934X_PLL_DDR_CONFIG_OUTDIV_MASK;
-	ref_div = (pll >> AR934X_PLL_DDR_CONFIG_REFDIV_SHIFT) &
-		  AR934X_PLL_DDR_CONFIG_REFDIV_MASK;
-	nint = (pll >> AR934X_PLL_DDR_CONFIG_NINT_SHIFT) &
-	       AR934X_PLL_DDR_CONFIG_NINT_MASK;
-	frac = (pll >> AR934X_PLL_DDR_CONFIG_NFRAC_SHIFT) &
-	       AR934X_PLL_DDR_CONFIG_NFRAC_MASK;
-
-	ddr_pll = nint * ath79_ref_clk.rate / ref_div;
-	ddr_pll += frac * ath79_ref_clk.rate / (ref_div * (2 << 10));
-	ddr_pll /= (1 << out_div);
+	pll = __raw_readl(dpll_base + AR934X_SRIF_CPU_DPLL2_REG);
+	if (pll & AR934X_SRIF_DPLL2_LOCAL_PLL) {
+		out_div = (pll >> AR934X_SRIF_DPLL2_OUTDIV_SHIFT) &
+			  AR934X_SRIF_DPLL2_OUTDIV_MASK;
+		pll = __raw_readl(dpll_base + AR934X_SRIF_CPU_DPLL1_REG);
+		nint = (pll >> AR934X_SRIF_DPLL1_NINT_SHIFT) &
+		       AR934X_SRIF_DPLL1_NINT_MASK;
+		nfrac = pll & AR934X_SRIF_DPLL1_NFRAC_MASK;
+		ref_div = (pll >> AR934X_SRIF_DPLL1_REFDIV_SHIFT) &
+			  AR934X_SRIF_DPLL1_REFDIV_MASK;
+		frac = 1 << 18;
+	} else {
+		pll = ath79_pll_rr(AR934X_PLL_CPU_CONFIG_REG);
+		out_div = (pll >> AR934X_PLL_CPU_CONFIG_OUTDIV_SHIFT) &
+			AR934X_PLL_CPU_CONFIG_OUTDIV_MASK;
+		ref_div = (pll >> AR934X_PLL_CPU_CONFIG_REFDIV_SHIFT) &
+			  AR934X_PLL_CPU_CONFIG_REFDIV_MASK;
+		nint = (pll >> AR934X_PLL_CPU_CONFIG_NINT_SHIFT) &
+		       AR934X_PLL_CPU_CONFIG_NINT_MASK;
+		nfrac = (pll >> AR934X_PLL_CPU_CONFIG_NFRAC_SHIFT) &
+			AR934X_PLL_CPU_CONFIG_NFRAC_MASK;
+		frac = 1 << 6;
+	}
+
+	cpu_pll = ar934x_get_pll_freq(ath79_ref_clk.rate, ref_div, nint,
+				      nfrac, frac, out_div);
+
+	pll = __raw_readl(dpll_base + AR934X_SRIF_DDR_DPLL2_REG);
+	if (pll & AR934X_SRIF_DPLL2_LOCAL_PLL) {
+		out_div = (pll >> AR934X_SRIF_DPLL2_OUTDIV_SHIFT) &
+			  AR934X_SRIF_DPLL2_OUTDIV_MASK;
+		pll = __raw_readl(dpll_base + AR934X_SRIF_DDR_DPLL1_REG);
+		nint = (pll >> AR934X_SRIF_DPLL1_NINT_SHIFT) &
+		       AR934X_SRIF_DPLL1_NINT_MASK;
+		nfrac = pll & AR934X_SRIF_DPLL1_NFRAC_MASK;
+		ref_div = (pll >> AR934X_SRIF_DPLL1_REFDIV_SHIFT) &
+			  AR934X_SRIF_DPLL1_REFDIV_MASK;
+		frac = 1 << 18;
+	} else {
+		pll = ath79_pll_rr(AR934X_PLL_DDR_CONFIG_REG);
+		out_div = (pll >> AR934X_PLL_DDR_CONFIG_OUTDIV_SHIFT) &
+			  AR934X_PLL_DDR_CONFIG_OUTDIV_MASK;
+		ref_div = (pll >> AR934X_PLL_DDR_CONFIG_REFDIV_SHIFT) &
+			   AR934X_PLL_DDR_CONFIG_REFDIV_MASK;
+		nint = (pll >> AR934X_PLL_DDR_CONFIG_NINT_SHIFT) &
+		       AR934X_PLL_DDR_CONFIG_NINT_MASK;
+		nfrac = (pll >> AR934X_PLL_DDR_CONFIG_NFRAC_SHIFT) &
+			AR934X_PLL_DDR_CONFIG_NFRAC_MASK;
+		frac = 1 << 10;
+	}
+
+	ddr_pll = ar934x_get_pll_freq(ath79_ref_clk.rate, ref_div, nint,
+				      nfrac, frac, out_div);
 
 	clk_ctrl = ath79_pll_rr(AR934X_PLL_CPU_DDR_CLK_CTRL_REG);
 
@@ -240,6 +291,8 @@ static void __init ar934x_clocks_init(void)
 
 	ath79_wdt_clk.rate = ath79_ref_clk.rate;
 	ath79_uart_clk.rate = ath79_ref_clk.rate;
+
+	iounmap(dpll_base);
 }
 
 void __init ath79_clocks_init(void)
diff --git a/arch/mips/bcm63xx/boards/board_bcm963xx.c b/arch/mips/bcm63xx/boards/board_bcm963xx.c
index feb0525..91c13d9 100644
--- a/arch/mips/bcm63xx/boards/board_bcm963xx.c
+++ b/arch/mips/bcm63xx/boards/board_bcm963xx.c
@@ -632,7 +632,7 @@ static struct board_info __initdata board_DWVS0 = {
 /*
  * all boards
  */
-static const struct board_info __initdata *bcm963xx_boards[] = {
+static const struct board_info __initconst *bcm963xx_boards[] = {
 #ifdef CONFIG_BCM63XX_CPU_6328
 	&board_96328avng,
 #endif
@@ -713,7 +713,7 @@ const char *board_get_name(void)
  */
 static int board_get_mac_address(u8 *mac)
 {
-	u8 *p;
+	u8 *oui;
 	int count;
 
 	if (mac_addr_used >= nvram.mac_addr_count) {
@@ -722,21 +722,23 @@ static int board_get_mac_address(u8 *mac)
 	}
 
 	memcpy(mac, nvram.mac_addr_base, ETH_ALEN);
-	p = mac + ETH_ALEN - 1;
+	oui = mac + ETH_ALEN/2 - 1;
 	count = mac_addr_used;
 
 	while (count--) {
+		u8 *p = mac + ETH_ALEN - 1;
+
 		do {
 			(*p)++;
 			if (*p != 0)
 				break;
 			p--;
-		} while (p != mac);
-	}
+		} while (p != oui);
 
-	if (p == mac) {
-		printk(KERN_ERR PFX "unable to fetch mac address\n");
-		return -ENODEV;
+		if (p == oui) {
+			printk(KERN_ERR PFX "unable to fetch mac address\n");
+			return -ENODEV;
+		}
 	}
 
 	mac_addr_used++;
diff --git a/arch/mips/cavium-octeon/serial.c b/arch/mips/cavium-octeon/serial.c
index 138b221..569f41b 100644
--- a/arch/mips/cavium-octeon/serial.c
+++ b/arch/mips/cavium-octeon/serial.c
@@ -47,40 +47,40 @@ static int __devinit octeon_serial_probe(struct platform_device *pdev)
 {
 	int irq, res;
 	struct resource *res_mem;
-	struct uart_port port;
+	struct uart_8250_port up;
 
 	/* All adaptors have an irq.  */
 	irq = platform_get_irq(pdev, 0);
 	if (irq < 0)
 		return irq;
 
-	memset(&port, 0, sizeof(port));
+	memset(&up, 0, sizeof(up));
 
-	port.flags = ASYNC_SKIP_TEST | UPF_SHARE_IRQ | UPF_FIXED_TYPE;
-	port.type = PORT_OCTEON;
-	port.iotype = UPIO_MEM;
-	port.regshift = 3;
-	port.dev = &pdev->dev;
+	up.port.flags = ASYNC_SKIP_TEST | UPF_SHARE_IRQ | UPF_FIXED_TYPE;
+	up.port.type = PORT_OCTEON;
+	up.port.iotype = UPIO_MEM;
+	up.port.regshift = 3;
+	up.port.dev = &pdev->dev;
 
 	if (octeon_is_simulation())
 		/* Make simulator output fast*/
-		port.uartclk = 115200 * 16;
+		up.port.uartclk = 115200 * 16;
 	else
-		port.uartclk = octeon_get_io_clock_rate();
+		up.port.uartclk = octeon_get_io_clock_rate();
 
-	port.serial_in = octeon_serial_in;
-	port.serial_out = octeon_serial_out;
-	port.irq = irq;
+	up.port.serial_in = octeon_serial_in;
+	up.port.serial_out = octeon_serial_out;
+	up.port.irq = irq;
 
 	res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (res_mem == NULL) {
 		dev_err(&pdev->dev, "found no memory resource\n");
 		return -ENXIO;
 	}
-	port.mapbase = res_mem->start;
-	port.membase = ioremap(res_mem->start, resource_size(res_mem));
+	up.port.mapbase = res_mem->start;
+	up.port.membase = ioremap(res_mem->start, resource_size(res_mem));
 
-	res = serial8250_register_port(&port);
+	res = serial8250_register_8250_port(&up);
 
 	return res >= 0 ? 0 : res;
 }
diff --git a/arch/mips/configs/ar7_defconfig b/arch/mips/configs/ar7_defconfig
index 6cd5a51..80e012fa 100644
--- a/arch/mips/configs/ar7_defconfig
+++ b/arch/mips/configs/ar7_defconfig
@@ -56,7 +56,6 @@ CONFIG_NF_CONNTRACK_MARK=y
 CONFIG_NF_CONNTRACK_FTP=m
 CONFIG_NF_CONNTRACK_IRC=m
 CONFIG_NF_CONNTRACK_TFTP=m
-CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
 CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
 CONFIG_NETFILTER_XT_MATCH_LIMIT=m
 CONFIG_NETFILTER_XT_MATCH_MAC=m
diff --git a/arch/mips/configs/bcm47xx_defconfig b/arch/mips/configs/bcm47xx_defconfig
index ad15fb1..b6fde2b 100644
--- a/arch/mips/configs/bcm47xx_defconfig
+++ b/arch/mips/configs/bcm47xx_defconfig
@@ -96,7 +96,6 @@ CONFIG_NETFILTER_XT_TARGET_DSCP=m
 CONFIG_NETFILTER_XT_TARGET_MARK=m
 CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
-CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
 CONFIG_NETFILTER_XT_TARGET_TRACE=m
 CONFIG_NETFILTER_XT_TARGET_SECMARK=m
 CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
diff --git a/arch/mips/configs/ip22_defconfig b/arch/mips/configs/ip22_defconfig
index d160656..936ec5a 100644
--- a/arch/mips/configs/ip22_defconfig
+++ b/arch/mips/configs/ip22_defconfig
@@ -87,7 +87,6 @@ CONFIG_NETFILTER_XT_TARGET_DSCP=m
 CONFIG_NETFILTER_XT_TARGET_MARK=m
 CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
-CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
 CONFIG_NETFILTER_XT_TARGET_TPROXY=m
 CONFIG_NETFILTER_XT_TARGET_TRACE=m
 CONFIG_NETFILTER_XT_TARGET_SECMARK=m
diff --git a/arch/mips/configs/jazz_defconfig b/arch/mips/configs/jazz_defconfig
index 92a60ae..0315ee3 100644
--- a/arch/mips/configs/jazz_defconfig
+++ b/arch/mips/configs/jazz_defconfig
@@ -60,7 +60,6 @@ CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
 CONFIG_NETFILTER_XT_TARGET_MARK=m
 CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
-CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
 CONFIG_NETFILTER_XT_TARGET_SECMARK=m
 CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
 CONFIG_NETFILTER_XT_MATCH_COMMENT=m
diff --git a/arch/mips/configs/malta_defconfig b/arch/mips/configs/malta_defconfig
index 5527abb..cd732e5 100644
--- a/arch/mips/configs/malta_defconfig
+++ b/arch/mips/configs/malta_defconfig
@@ -86,7 +86,6 @@ CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
 CONFIG_NETFILTER_XT_TARGET_MARK=m
 CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
-CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
 CONFIG_NETFILTER_XT_TARGET_TPROXY=m
 CONFIG_NETFILTER_XT_TARGET_TRACE=m
 CONFIG_NETFILTER_XT_TARGET_SECMARK=m
diff --git a/arch/mips/configs/markeins_defconfig b/arch/mips/configs/markeins_defconfig
index 9c9a123..636f82b 100644
--- a/arch/mips/configs/markeins_defconfig
+++ b/arch/mips/configs/markeins_defconfig
@@ -59,7 +59,6 @@ CONFIG_NETFILTER_XT_TARGET_DSCP=m
 CONFIG_NETFILTER_XT_TARGET_MARK=m
 CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
-CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
 CONFIG_NETFILTER_XT_TARGET_SECMARK=m
 CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
 CONFIG_NETFILTER_XT_MATCH_COMMENT=m
diff --git a/arch/mips/configs/mipssim_defconfig b/arch/mips/configs/mipssim_defconfig
deleted file mode 100644
index b5ad738..0000000
--- a/arch/mips/configs/mipssim_defconfig
+++ /dev/null
@@ -1,64 +0,0 @@
-CONFIG_MIPS_SIM=y
-CONFIG_CPU_LITTLE_ENDIAN=y
-CONFIG_HZ_100=y
-# CONFIG_SECCOMP is not set
-CONFIG_EXPERIMENTAL=y
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EXPERT=y
-CONFIG_SLAB=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODVERSIONS=y
-CONFIG_MODULE_SRCVERSION_ALL=y
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-CONFIG_IP_ADVANCED_ROUTER=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_INET_LRO is not set
-# CONFIG_IPV6 is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-# CONFIG_STANDALONE is not set
-# CONFIG_PREVENT_FIRMWARE_BUILD is not set
-# CONFIG_FW_LOADER is not set
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_NBD=y
-# CONFIG_MISC_DEVICES is not set
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_MIPS_SIM_NET=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
-# CONFIG_INPUT is not set
-# CONFIG_SERIO is not set
-# CONFIG_VT is not set
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_NR_UARTS=1
-CONFIG_SERIAL_8250_RUNTIME_UARTS=1
-# CONFIG_HW_RANDOM is not set
-# CONFIG_HWMON is not set
-# CONFIG_USB_SUPPORT is not set
-# CONFIG_DNOTIFY is not set
-CONFIG_TMPFS=y
-CONFIG_ROMFS_FS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_ROOT_NFS=y
-CONFIG_DEBUG_KERNEL=y
-# CONFIG_SCHED_DEBUG is not set
-CONFIG_DEBUG_INFO=y
-CONFIG_CMDLINE_BOOL=y
-CONFIG_CMDLINE="nfsroot=192.168.192.169:/u1/mipsel,timeo=20 ip=dhcp"
-# CONFIG_CRC32 is not set
diff --git a/arch/mips/configs/nlm_xlp_defconfig b/arch/mips/configs/nlm_xlp_defconfig
index 28c6b27..84624b1 100644
--- a/arch/mips/configs/nlm_xlp_defconfig
+++ b/arch/mips/configs/nlm_xlp_defconfig
@@ -108,7 +108,6 @@ CONFIG_NETFILTER_XT_TARGET_DSCP=m
 CONFIG_NETFILTER_XT_TARGET_MARK=m
 CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
-CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
 CONFIG_NETFILTER_XT_TARGET_TPROXY=m
 CONFIG_NETFILTER_XT_TARGET_TRACE=m
 CONFIG_NETFILTER_XT_TARGET_SECMARK=m
diff --git a/arch/mips/configs/nlm_xlr_defconfig b/arch/mips/configs/nlm_xlr_defconfig
index 138f698..44b4734 100644
--- a/arch/mips/configs/nlm_xlr_defconfig
+++ b/arch/mips/configs/nlm_xlr_defconfig
@@ -109,7 +109,6 @@ CONFIG_NETFILTER_XT_TARGET_DSCP=m
 CONFIG_NETFILTER_XT_TARGET_MARK=m
 CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
-CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
 CONFIG_NETFILTER_XT_TARGET_TPROXY=m
 CONFIG_NETFILTER_XT_TARGET_TRACE=m
 CONFIG_NETFILTER_XT_TARGET_SECMARK=m
diff --git a/arch/mips/configs/rb532_defconfig b/arch/mips/configs/rb532_defconfig
index 55902d9..b85b121 100644
--- a/arch/mips/configs/rb532_defconfig
+++ b/arch/mips/configs/rb532_defconfig
@@ -119,7 +119,6 @@ CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_BLOCK2MTD=y
 CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_VERIFY_WRITE=y
 CONFIG_MTD_NAND_PLATFORM=y
 CONFIG_ATA=y
 # CONFIG_ATA_VERBOSE_ERROR is not set
diff --git a/arch/mips/configs/rm200_defconfig b/arch/mips/configs/rm200_defconfig
index 2c0230e..59d9d2f 100644
--- a/arch/mips/configs/rm200_defconfig
+++ b/arch/mips/configs/rm200_defconfig
@@ -68,7 +68,6 @@ CONFIG_NETFILTER_XT_TARGET_DSCP=m
 CONFIG_NETFILTER_XT_TARGET_MARK=m
 CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
-CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
 CONFIG_NETFILTER_XT_TARGET_SECMARK=m
 CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
 CONFIG_NETFILTER_XT_MATCH_COMMENT=m
diff --git a/arch/mips/include/asm/compat-signal.h b/arch/mips/include/asm/compat-signal.h
index 368a99e..6599a90 100644
--- a/arch/mips/include/asm/compat-signal.h
+++ b/arch/mips/include/asm/compat-signal.h
@@ -10,68 +10,6 @@
 
 #include <asm/uaccess.h>
 
-#define SI_PAD_SIZE32   ((SI_MAX_SIZE/sizeof(int)) - 3)
-
-typedef struct compat_siginfo {
-	int si_signo;
-	int si_code;
-	int si_errno;
-
-	union {
-		int _pad[SI_PAD_SIZE32];
-
-		/* kill() */
-		struct {
-			compat_pid_t _pid;	/* sender's pid */
-			compat_uid_t _uid;	/* sender's uid */
-		} _kill;
-
-		/* SIGCHLD */
-		struct {
-			compat_pid_t _pid;	/* which child */
-			compat_uid_t _uid;	/* sender's uid */
-			int _status;		/* exit code */
-			compat_clock_t _utime;
-			compat_clock_t _stime;
-		} _sigchld;
-
-		/* IRIX SIGCHLD */
-		struct {
-			compat_pid_t _pid;	/* which child */
-			compat_clock_t _utime;
-			int _status;		/* exit code */
-			compat_clock_t _stime;
-		} _irix_sigchld;
-
-		/* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
-		struct {
-			s32 _addr; /* faulting insn/memory ref. */
-		} _sigfault;
-
-		/* SIGPOLL, SIGXFSZ (To do ...)  */
-		struct {
-			int _band;	/* POLL_IN, POLL_OUT, POLL_MSG */
-			int _fd;
-		} _sigpoll;
-
-		/* POSIX.1b timers */
-		struct {
-			timer_t _tid;		/* timer id */
-			int _overrun;		/* overrun count */
-			compat_sigval_t _sigval;/* same as below */
-			int _sys_private;       /* not to be passed to user */
-		} _timer;
-
-		/* POSIX.1b signals */
-		struct {
-			compat_pid_t _pid;	/* sender's pid */
-			compat_uid_t _uid;	/* sender's uid */
-			compat_sigval_t _sigval;
-		} _rt;
-
-	} _sifields;
-} compat_siginfo_t;
-
 static inline int __copy_conv_sigset_to_user(compat_sigset_t __user *d,
 	const sigset_t *s)
 {
diff --git a/arch/mips/include/asm/compat.h b/arch/mips/include/asm/compat.h
index b77df03..58277e0 100644
--- a/arch/mips/include/asm/compat.h
+++ b/arch/mips/include/asm/compat.h
@@ -43,6 +43,7 @@ typedef s64		compat_s64;
 typedef u32		compat_uint_t;
 typedef u32		compat_ulong_t;
 typedef u64		compat_u64;
+typedef u32		compat_uptr_t;
 
 struct compat_timespec {
 	compat_time_t	tv_sec;
@@ -124,6 +125,73 @@ typedef u32		compat_old_sigset_t;	/* at least 32 bits */
 
 typedef u32		compat_sigset_word;
 
+typedef union compat_sigval {
+	compat_int_t	sival_int;
+	compat_uptr_t	sival_ptr;
+} compat_sigval_t;
+
+#define SI_PAD_SIZE32	(128/sizeof(int) - 3)
+
+typedef struct compat_siginfo {
+	int si_signo;
+	int si_code;
+	int si_errno;
+
+	union {
+		int _pad[SI_PAD_SIZE32];
+
+		/* kill() */
+		struct {
+			compat_pid_t _pid;	/* sender's pid */
+			__compat_uid_t _uid;	/* sender's uid */
+		} _kill;
+
+		/* SIGCHLD */
+		struct {
+			compat_pid_t _pid;	/* which child */
+			__compat_uid_t _uid;	/* sender's uid */
+			int _status;		/* exit code */
+			compat_clock_t _utime;
+			compat_clock_t _stime;
+		} _sigchld;
+
+		/* IRIX SIGCHLD */
+		struct {
+			compat_pid_t _pid;	/* which child */
+			compat_clock_t _utime;
+			int _status;		/* exit code */
+			compat_clock_t _stime;
+		} _irix_sigchld;
+
+		/* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
+		struct {
+			s32 _addr; /* faulting insn/memory ref. */
+		} _sigfault;
+
+		/* SIGPOLL, SIGXFSZ (To do ...)  */
+		struct {
+			int _band;	/* POLL_IN, POLL_OUT, POLL_MSG */
+			int _fd;
+		} _sigpoll;
+
+		/* POSIX.1b timers */
+		struct {
+			timer_t _tid;		/* timer id */
+			int _overrun;		/* overrun count */
+			compat_sigval_t _sigval;/* same as below */
+			int _sys_private;       /* not to be passed to user */
+		} _timer;
+
+		/* POSIX.1b signals */
+		struct {
+			compat_pid_t _pid;	/* sender's pid */
+			__compat_uid_t _uid;	/* sender's uid */
+			compat_sigval_t _sigval;
+		} _rt;
+
+	} _sifields;
+} compat_siginfo_t;
+
 #define COMPAT_OFF_T_MAX	0x7fffffff
 #define COMPAT_LOFF_T_MAX	0x7fffffffffffffffL
 
@@ -133,7 +201,6 @@ typedef u32		compat_sigset_word;
  * as pointers because the syscall entry code will have
  * appropriately converted them already.
  */
-typedef u32		compat_uptr_t;
 
 static inline void __user *compat_ptr(compat_uptr_t uptr)
 {
diff --git a/arch/mips/include/asm/elf.h b/arch/mips/include/asm/elf.h
index 455c0ac..aec5163 100644
--- a/arch/mips/include/asm/elf.h
+++ b/arch/mips/include/asm/elf.h
@@ -331,6 +331,7 @@ extern int dump_task_fpu(struct task_struct *, elf_fpregset_t *);
 #define ELF_CORE_COPY_FPREGS(tsk, elf_fpregs)			\
 	dump_task_fpu(tsk, elf_fpregs)
 
+#define CORE_DUMP_USE_REGSET
 #define ELF_EXEC_PAGESIZE	PAGE_SIZE
 
 /* This yields a mask that user programs can use to figure out what
diff --git a/arch/mips/include/asm/hugetlb.h b/arch/mips/include/asm/hugetlb.h
index 58d3688..bd94946 100644
--- a/arch/mips/include/asm/hugetlb.h
+++ b/arch/mips/include/asm/hugetlb.h
@@ -112,4 +112,8 @@ static inline void arch_release_hugepage(struct page *page)
 {
 }
 
+static inline void arch_clear_hugepage_flags(struct page *page)
+{
+}
+
 #endif /* __ASM_HUGETLB_H */
diff --git a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
index dde5044..31a9a7c 100644
--- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
+++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
@@ -63,6 +63,8 @@
 
 #define AR934X_WMAC_BASE	(AR71XX_APB_BASE + 0x00100000)
 #define AR934X_WMAC_SIZE	0x20000
+#define AR934X_SRIF_BASE	(AR71XX_APB_BASE + 0x00116000)
+#define AR934X_SRIF_SIZE	0x1000
 
 /*
  * DDR_CTRL block
@@ -399,4 +401,25 @@
 #define AR933X_GPIO_COUNT		30
 #define AR934X_GPIO_COUNT		23
 
+/*
+ * SRIF block
+ */
+#define AR934X_SRIF_CPU_DPLL1_REG	0x1c0
+#define AR934X_SRIF_CPU_DPLL2_REG	0x1c4
+#define AR934X_SRIF_CPU_DPLL3_REG	0x1c8
+
+#define AR934X_SRIF_DDR_DPLL1_REG	0x240
+#define AR934X_SRIF_DDR_DPLL2_REG	0x244
+#define AR934X_SRIF_DDR_DPLL3_REG	0x248
+
+#define AR934X_SRIF_DPLL1_REFDIV_SHIFT	27
+#define AR934X_SRIF_DPLL1_REFDIV_MASK	0x1f
+#define AR934X_SRIF_DPLL1_NINT_SHIFT	18
+#define AR934X_SRIF_DPLL1_NINT_MASK	0x1ff
+#define AR934X_SRIF_DPLL1_NFRAC_MASK	0x0003ffff
+
+#define AR934X_SRIF_DPLL2_LOCAL_PLL	BIT(30)
+#define AR934X_SRIF_DPLL2_OUTDIV_SHIFT	13
+#define AR934X_SRIF_DPLL2_OUTDIV_MASK	0x7
+
 #endif /* __ASM_MACH_AR71XX_REGS_H */
diff --git a/arch/mips/include/asm/mach-mipssim/cpu-feature-overrides.h b/arch/mips/include/asm/mach-mipssim/cpu-feature-overrides.h
deleted file mode 100644
index 27aaaa5..0000000
--- a/arch/mips/include/asm/mach-mipssim/cpu-feature-overrides.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2003, 2004 Chris Dearman
- */
-#ifndef __ASM_MACH_SIM_CPU_FEATURE_OVERRIDES_H
-#define __ASM_MACH_SIM_CPU_FEATURE_OVERRIDES_H
-
-
-/*
- * CPU feature overrides for MIPS boards
- */
-#ifdef CONFIG_CPU_MIPS32
-#define cpu_has_tlb		1
-#define cpu_has_4kex		1
-#define cpu_has_4k_cache	1
-#define cpu_has_fpu		0
-/* #define cpu_has_32fpr	? */
-#define cpu_has_counter		1
-/* #define cpu_has_watch	? */
-#define cpu_has_divec		1
-#define cpu_has_vce		0
-/* #define cpu_has_cache_cdex_p	? */
-/* #define cpu_has_cache_cdex_s	? */
-/* #define cpu_has_prefetch	? */
-#define cpu_has_mcheck		1
-/* #define cpu_has_ejtag	? */
-#define cpu_has_llsc		1
-/* #define cpu_has_vtag_icache	? */
-/* #define cpu_has_dc_aliases	? */
-/* #define cpu_has_ic_fills_f_dc ? */
-#define cpu_has_clo_clz		1
-#define cpu_has_nofpuex		0
-/* #define cpu_has_64bits	? */
-/* #define cpu_has_64bit_zero_reg ? */
-/* #define cpu_has_inclusive_pcaches ? */
-#endif
-
-#ifdef CONFIG_CPU_MIPS64
-#define cpu_has_tlb		1
-#define cpu_has_4kex		1
-#define cpu_has_4k_cache	1
-/* #define cpu_has_fpu		? */
-/* #define cpu_has_32fpr	? */
-#define cpu_has_counter		1
-/* #define cpu_has_watch	? */
-#define cpu_has_divec		1
-#define cpu_has_vce		0
-/* #define cpu_has_cache_cdex_p	? */
-/* #define cpu_has_cache_cdex_s	? */
-/* #define cpu_has_prefetch	? */
-#define cpu_has_mcheck		1
-/* #define cpu_has_ejtag	? */
-#define cpu_has_llsc		1
-/* #define cpu_has_vtag_icache	? */
-/* #define cpu_has_dc_aliases	? */
-/* #define cpu_has_ic_fills_f_dc ? */
-#define cpu_has_clo_clz		1
-#define cpu_has_nofpuex		0
-/* #define cpu_has_64bits	? */
-/* #define cpu_has_64bit_zero_reg ? */
-/* #define cpu_has_inclusive_pcaches ? */
-#endif
-
-#endif /* __ASM_MACH_MIPS_CPU_FEATURE_OVERRIDES_H */
diff --git a/arch/mips/include/asm/mach-mipssim/war.h b/arch/mips/include/asm/mach-mipssim/war.h
deleted file mode 100644
index c8a74a3..0000000
--- a/arch/mips/include/asm/mach-mipssim/war.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org>
- */
-#ifndef __ASM_MIPS_MACH_MIPSSIM_WAR_H
-#define __ASM_MIPS_MACH_MIPSSIM_WAR_H
-
-#define R4600_V1_INDEX_ICACHEOP_WAR	0
-#define R4600_V1_HIT_CACHEOP_WAR	0
-#define R4600_V2_HIT_CACHEOP_WAR	0
-#define R5432_CP0_INTERRUPT_WAR		0
-#define BCM1250_M3_WAR			0
-#define SIBYTE_1956_WAR			0
-#define MIPS4K_ICACHE_REFILL_WAR	0
-#define MIPS_CACHE_SYNC_WAR		0
-#define TX49XX_ICACHE_INDEX_INV_WAR	0
-#define RM9000_CDEX_SMP_WAR		0
-#define ICACHE_REFILLS_WORKAROUND_WAR	0
-#define R10000_LLSC_WAR			0
-#define MIPS34K_MISSED_ITLB_WAR		0
-
-#endif /* __ASM_MIPS_MACH_MIPSSIM_WAR_H */
diff --git a/arch/mips/include/asm/mips-boards/simint.h b/arch/mips/include/asm/mips-boards/simint.h
deleted file mode 100644
index 8ef6db7..0000000
--- a/arch/mips/include/asm/mips-boards/simint.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2005 MIPS Technologies, Inc.  All rights reserved.
- *
- *  This program is free software; you can distribute 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 it will be useful, but WITHOUT
- *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- *  for more details.
- *
- *  You should have received a copy of the GNU General Public 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 _MIPS_SIMINT_H
-#define _MIPS_SIMINT_H
-
-#include <irq.h>
-
-#define SIM_INT_BASE		0
-#define MIPSCPU_INT_MB0		2
-#define MIPS_CPU_TIMER_IRQ	7
-
-
-#define MSC01E_INT_BASE		64
-
-#define MSC01E_INT_CPUCTR	11
-
-#endif
diff --git a/arch/mips/include/asm/module.h b/arch/mips/include/asm/module.h
index dca8bce..26137da 100644
--- a/arch/mips/include/asm/module.h
+++ b/arch/mips/include/asm/module.h
@@ -35,11 +35,14 @@ typedef struct {
 } Elf64_Mips_Rela;
 
 #ifdef CONFIG_32BIT
-
 #define Elf_Shdr	Elf32_Shdr
 #define Elf_Sym		Elf32_Sym
 #define Elf_Ehdr	Elf32_Ehdr
 #define Elf_Addr	Elf32_Addr
+#define Elf_Rel		Elf32_Rel
+#define Elf_Rela	Elf32_Rela
+#define ELF_R_TYPE(X)	ELF32_R_TYPE(X)
+#define ELF_R_SYM(X)	ELF32_R_SYM(X)
 
 #define Elf_Mips_Rel	Elf32_Rel
 #define Elf_Mips_Rela	Elf32_Rela
@@ -50,11 +53,14 @@ typedef struct {
 #endif
 
 #ifdef CONFIG_64BIT
-
 #define Elf_Shdr	Elf64_Shdr
 #define Elf_Sym		Elf64_Sym
 #define Elf_Ehdr	Elf64_Ehdr
 #define Elf_Addr	Elf64_Addr
+#define Elf_Rel		Elf64_Rel
+#define Elf_Rela	Elf64_Rela
+#define ELF_R_TYPE(X)	ELF64_R_TYPE(X)
+#define ELF_R_SYM(X)	ELF64_R_SYM(X)
 
 #define Elf_Mips_Rel	Elf64_Mips_Rel
 #define Elf_Mips_Rela	Elf64_Mips_Rela
diff --git a/arch/mips/include/asm/ptrace.h b/arch/mips/include/asm/ptrace.h
index 4b7f525..f07a4e6 100644
--- a/arch/mips/include/asm/ptrace.h
+++ b/arch/mips/include/asm/ptrace.h
@@ -164,6 +164,19 @@ static inline void die_if_kernel(const char *str, struct pt_regs *regs)
 		die(str, regs);
 }
 
-#endif
+/* Helpers for working with the user stack pointer */
+
+static inline unsigned long user_stack_pointer(struct pt_regs *regs)
+{
+	return regs->regs[29];
+}
+
+static inline void user_stack_pointer_set(struct pt_regs *regs,
+	unsigned long val)
+{
+	regs->regs[29] = val;
+}
+
+#endif /* __KERNEL__ */
 
 #endif /* _ASM_PTRACE_H */
diff --git a/arch/mips/include/asm/siginfo.h b/arch/mips/include/asm/siginfo.h
index 20ebeb8..5fad4f6 100644
--- a/arch/mips/include/asm/siginfo.h
+++ b/arch/mips/include/asm/siginfo.h
@@ -32,6 +32,8 @@ struct siginfo;
 #define __ARCH_SI_PREAMBLE_SIZE (4 * sizeof(int))
 #endif
 
+#define __ARCH_SIGSYS
+
 #include <asm-generic/siginfo.h>
 
 typedef struct siginfo {
@@ -96,6 +98,13 @@ typedef struct siginfo {
 			__ARCH_SI_BAND_T _band;	/* POLL_IN, POLL_OUT, POLL_MSG */
 			int _fd;
 		} _sigpoll;
+
+		/* SIGSYS */
+		struct {
+			void __user *_call_addr; /* calling user insn */
+			int _syscall;   /* triggering system call number */
+			unsigned int _arch;     /* AUDIT_ARCH_* of syscall */
+		} _sigsys;
 	} _sifields;
 } siginfo_t;
 
diff --git a/arch/mips/include/asm/syscall.h b/arch/mips/include/asm/syscall.h
new file mode 100644
index 0000000..087df5f
--- /dev/null
+++ b/arch/mips/include/asm/syscall.h
@@ -0,0 +1,97 @@
+/*
+ * Access to user system call parameters and results
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * See asm-generic/syscall.h for descriptions of what we must do here.
+ *
+ * Copyright (C) 2012 Ralf Baechle <ralf@linux-mips.org>
+ */
+
+#ifndef __ASM_MIPS_SYSCALL_H
+#define __ASM_MIPS_SYSCALL_H
+
+#include <linux/audit.h>
+#include <linux/elf-em.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/uaccess.h>
+#include <asm/ptrace.h>
+
+static inline long syscall_get_nr(struct task_struct *task,
+				  struct pt_regs *regs)
+{
+	return regs->regs[2];
+}
+
+static inline unsigned long mips_get_syscall_arg(unsigned long *arg,
+	struct task_struct *task, struct pt_regs *regs, unsigned int n)
+{
+	unsigned long usp = regs->regs[29];
+
+	switch (n) {
+	case 0: case 1: case 2: case 3:
+		*arg = regs->regs[4 + n];
+
+		return 0;
+
+#ifdef CONFIG_32BIT
+	case 4: case 5: case 6: case 7:
+		return get_user(*arg, (int *)usp + 4 * n);
+#endif
+
+#ifdef CONFIG_64BIT
+	case 4: case 5: case 6: case 7:
+#ifdef CONFIG_MIPS32_O32
+		if (test_thread_flag(TIF_32BIT_REGS))
+			return get_user(*arg, (int *)usp + 4 * n);
+		else
+#endif
+			*arg = regs->regs[4 + n];
+
+		return 0;
+#endif
+
+	default:
+		BUG();
+	}
+}
+
+static inline void syscall_get_arguments(struct task_struct *task,
+					 struct pt_regs *regs,
+					 unsigned int i, unsigned int n,
+					 unsigned long *args)
+{
+	unsigned long arg;
+	int ret;
+
+	while (n--)
+		ret |= mips_get_syscall_arg(&arg, task, regs, i++);
+
+	/*
+	 * No way to communicate an error because this is a void function.
+	 */
+#if 0
+	return ret;
+#endif
+}
+
+extern const unsigned long sys_call_table[];
+extern const unsigned long sys32_call_table[];
+extern const unsigned long sysn32_call_table[];
+
+static inline int __syscall_get_arch(void)
+{
+	int arch = EM_MIPS;
+#ifdef CONFIG_64BIT
+	arch |=  __AUDIT_ARCH_64BIT;
+#endif
+#if defined(__LITTLE_ENDIAN)
+	arch |=  __AUDIT_ARCH_LE;
+#endif
+	return arch;
+}
+
+#endif	/* __ASM_MIPS_SYSCALL_H */
diff --git a/arch/mips/include/asm/thread_info.h b/arch/mips/include/asm/thread_info.h
index ca97e0e..8debe9e 100644
--- a/arch/mips/include/asm/thread_info.h
+++ b/arch/mips/include/asm/thread_info.h
@@ -103,7 +103,6 @@ register struct thread_info *__current_thread_info __asm__("$28");
 #define TIF_NOTIFY_RESUME	5	/* callback before returning to user */
 #define TIF_RESTORE_SIGMASK	9	/* restore signal mask in do_signal() */
 #define TIF_USEDFPU		16	/* FPU was used by this task this quantum (SMP) */
-#define TIF_POLLING_NRFLAG	17	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_MEMDIE		18	/* is terminating due to OOM killer */
 #define TIF_FIXADE		20	/* Fix address errors in software */
 #define TIF_LOGADE		21	/* Log address errors to syslog */
@@ -125,9 +124,7 @@ register struct thread_info *__current_thread_info __asm__("$28");
 #define _TIF_SYSCALL_AUDIT	(1<<TIF_SYSCALL_AUDIT)
 #define _TIF_SECCOMP		(1<<TIF_SECCOMP)
 #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
-#define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
 #define _TIF_USEDFPU		(1<<TIF_USEDFPU)
-#define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
 #define _TIF_FIXADE		(1<<TIF_FIXADE)
 #define _TIF_LOGADE		(1<<TIF_LOGADE)
 #define _TIF_32BIT_REGS		(1<<TIF_32BIT_REGS)
@@ -139,10 +136,10 @@ register struct thread_info *__current_thread_info __asm__("$28");
 #define _TIF_WORK_SYSCALL_EXIT	(_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT)
 
 /* work to do on interrupt/exception return */
-#define _TIF_WORK_MASK		(0x0000ffef &				\
-					~(_TIF_SECCOMP | _TIF_SYSCALL_AUDIT))
+#define _TIF_WORK_MASK		\
+	(_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_NOTIFY_RESUME)
 /* work to do on any return to u-space */
-#define _TIF_ALLWORK_MASK	(0x8000ffff & ~_TIF_SECCOMP)
+#define _TIF_ALLWORK_MASK	(_TIF_WORK_MASK | _TIF_WORK_SYSCALL_EXIT)
 
 #endif /* __KERNEL__ */
 
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index fdaf65e..a69edf0 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -31,7 +31,9 @@ obj-$(CONFIG_SYNC_R4K)		+= sync-r4k.o
 
 obj-$(CONFIG_STACKTRACE)	+= stacktrace.o
 obj-$(CONFIG_MODULES)		+= mips_ksyms.o module.o
+obj-$(CONFIG_MODULES_USE_ELF_RELA) += module-rela.o
 
+obj-$(CONFIG_FTRACE_SYSCALLS)	+= ftrace.o
 obj-$(CONFIG_FUNCTION_TRACER)	+= mcount.o ftrace.o
 
 obj-$(CONFIG_CPU_LOONGSON2)	+= r4k_fpu.o r4k_switch.o
diff --git a/arch/mips/kernel/entry.S b/arch/mips/kernel/entry.S
index 37acfa0..a6c1332 100644
--- a/arch/mips/kernel/entry.S
+++ b/arch/mips/kernel/entry.S
@@ -77,7 +77,7 @@ FEXPORT(syscall_exit)
 	and	t0, a2, t0
 	bnez	t0, syscall_exit_work
 
-FEXPORT(restore_all)			# restore full frame
+restore_all:				# restore full frame
 #ifdef CONFIG_MIPS_MT_SMTC
 #ifdef CONFIG_MIPS_MT_SMTC_IM_BACKSTOP
 /* Re-arm any temporarily masked interrupts not explicitly "acked" */
@@ -117,7 +117,7 @@ FEXPORT(restore_all)			# restore full frame
 	RESTORE_TEMP
 	RESTORE_AT
 	RESTORE_STATIC
-FEXPORT(restore_partial)		# restore partial frame
+restore_partial:		# restore partial frame
 #ifdef CONFIG_TRACE_IRQFLAGS
 	SAVE_STATIC
 	SAVE_AT
@@ -164,9 +164,18 @@ work_notifysig:				# deal with pending signals and
 	jal	do_notify_resume	# a2 already loaded
 	j	resume_userspace
 
-FEXPORT(syscall_exit_work_partial)
+FEXPORT(syscall_exit_partial)
+	local_irq_disable		# make sure need_resched doesn't
+					# change between and return
+	LONG_L	a2, TI_FLAGS($28)	# current->work
+	li	t0, _TIF_ALLWORK_MASK
+	and	t0, a2
+	beqz	t0, restore_partial
 	SAVE_STATIC
 syscall_exit_work:
+	LONG_L	t0, PT_STATUS(sp)		# returning to kernel mode?
+	andi	t0, t0, KU_USER
+	beqz	t0, resume_kernel
 	li	t0, _TIF_WORK_SYSCALL_EXIT
 	and	t0, a2			# a2 is preloaded with TI_FLAGS
 	beqz	t0, work_pending	# trace bit set?
diff --git a/arch/mips/kernel/ftrace.c b/arch/mips/kernel/ftrace.c
index 6a2d758..dfc7441 100644
--- a/arch/mips/kernel/ftrace.c
+++ b/arch/mips/kernel/ftrace.c
@@ -11,11 +11,14 @@
 #include <linux/uaccess.h>
 #include <linux/init.h>
 #include <linux/ftrace.h>
+#include <linux/syscalls.h>
 
 #include <asm/asm.h>
 #include <asm/asm-offsets.h>
 #include <asm/cacheflush.h>
+#include <asm/syscall.h>
 #include <asm/uasm.h>
+#include <asm/unistd.h>
 
 #include <asm-generic/sections.h>
 
@@ -326,3 +329,33 @@ out:
 	WARN_ON(1);
 }
 #endif	/* CONFIG_FUNCTION_GRAPH_TRACER */
+
+#ifdef CONFIG_FTRACE_SYSCALLS
+
+#ifdef CONFIG_32BIT
+unsigned long __init arch_syscall_addr(int nr)
+{
+	return (unsigned long)sys_call_table[nr - __NR_O32_Linux];
+}
+#endif
+
+#ifdef CONFIG_64BIT
+
+unsigned long __init arch_syscall_addr(int nr)
+{
+#ifdef CONFIG_MIPS32_N32
+	if (nr >= __NR_N32_Linux && nr <= __NR_N32_Linux + __NR_N32_Linux_syscalls)
+		return (unsigned long)sysn32_call_table[nr - __NR_N32_Linux];
+#endif
+	if (nr >= __NR_64_Linux  && nr <= __NR_64_Linux + __NR_64_Linux_syscalls)
+		return (unsigned long)sys_call_table[nr - __NR_64_Linux];
+#ifdef CONFIG_MIPS32_O32
+	if (nr >= __NR_O32_Linux && nr <= __NR_O32_Linux + __NR_O32_Linux_syscalls)
+		return (unsigned long)sys32_call_table[nr - __NR_O32_Linux];
+#endif
+
+	return (unsigned long) &sys_ni_syscall;
+}
+#endif
+
+#endif /* CONFIG_FTRACE_SYSCALLS */
diff --git a/arch/mips/kernel/kgdb.c b/arch/mips/kernel/kgdb.c
index f4546e9..23817a6 100644
--- a/arch/mips/kernel/kgdb.c
+++ b/arch/mips/kernel/kgdb.c
@@ -283,6 +283,15 @@ static int kgdb_mips_notify(struct notifier_block *self, unsigned long cmd,
 	struct pt_regs *regs = args->regs;
 	int trap = (regs->cp0_cause & 0x7c) >> 2;
 
+#ifdef CONFIG_KPROBES
+	/*
+	 * Return immediately if the kprobes fault notifier has set
+	 * DIE_PAGE_FAULT.
+	 */
+	if (cmd == DIE_PAGE_FAULT)
+		return NOTIFY_DONE;
+#endif /* CONFIG_KPROBES */
+
 	/* Userspace events, ignore. */
 	if (user_mode(regs))
 		return NOTIFY_DONE;
diff --git a/arch/mips/kernel/module-rela.c b/arch/mips/kernel/module-rela.c
new file mode 100644
index 0000000..61d6002
--- /dev/null
+++ b/arch/mips/kernel/module-rela.c
@@ -0,0 +1,145 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the 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) 2001 Rusty Russell.
+ *  Copyright (C) 2003, 2004 Ralf Baechle (ralf@linux-mips.org)
+ *  Copyright (C) 2005 Thiemo Seufer
+ */
+
+#include <linux/elf.h>
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/moduleloader.h>
+
+extern int apply_r_mips_none(struct module *me, u32 *location, Elf_Addr v);
+
+static int apply_r_mips_32_rela(struct module *me, u32 *location, Elf_Addr v)
+{
+	*location = v;
+
+	return 0;
+}
+
+static int apply_r_mips_26_rela(struct module *me, u32 *location, Elf_Addr v)
+{
+	if (v % 4) {
+		pr_err("module %s: dangerous R_MIPS_26 RELArelocation\n",
+		       me->name);
+		return -ENOEXEC;
+	}
+
+	if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) {
+		printk(KERN_ERR
+		       "module %s: relocation overflow\n",
+		       me->name);
+		return -ENOEXEC;
+	}
+
+	*location = (*location & ~0x03ffffff) | ((v >> 2) & 0x03ffffff);
+
+	return 0;
+}
+
+static int apply_r_mips_hi16_rela(struct module *me, u32 *location, Elf_Addr v)
+{
+	*location = (*location & 0xffff0000) |
+	            ((((long long) v + 0x8000LL) >> 16) & 0xffff);
+
+	return 0;
+}
+
+static int apply_r_mips_lo16_rela(struct module *me, u32 *location, Elf_Addr v)
+{
+	*location = (*location & 0xffff0000) | (v & 0xffff);
+
+	return 0;
+}
+
+static int apply_r_mips_64_rela(struct module *me, u32 *location, Elf_Addr v)
+{
+	*(Elf_Addr *)location = v;
+
+	return 0;
+}
+
+static int apply_r_mips_higher_rela(struct module *me, u32 *location,
+				    Elf_Addr v)
+{
+	*location = (*location & 0xffff0000) |
+	            ((((long long) v + 0x80008000LL) >> 32) & 0xffff);
+
+	return 0;
+}
+
+static int apply_r_mips_highest_rela(struct module *me, u32 *location,
+				     Elf_Addr v)
+{
+	*location = (*location & 0xffff0000) |
+	            ((((long long) v + 0x800080008000LL) >> 48) & 0xffff);
+
+	return 0;
+}
+
+static int (*reloc_handlers_rela[]) (struct module *me, u32 *location,
+				Elf_Addr v) = {
+	[R_MIPS_NONE]		= apply_r_mips_none,
+	[R_MIPS_32]		= apply_r_mips_32_rela,
+	[R_MIPS_26]		= apply_r_mips_26_rela,
+	[R_MIPS_HI16]		= apply_r_mips_hi16_rela,
+	[R_MIPS_LO16]		= apply_r_mips_lo16_rela,
+	[R_MIPS_64]		= apply_r_mips_64_rela,
+	[R_MIPS_HIGHER]		= apply_r_mips_higher_rela,
+	[R_MIPS_HIGHEST]	= apply_r_mips_highest_rela
+};
+
+int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
+		       unsigned int symindex, unsigned int relsec,
+		       struct module *me)
+{
+	Elf_Mips_Rela *rel = (void *) sechdrs[relsec].sh_addr;
+	Elf_Sym *sym;
+	u32 *location;
+	unsigned int i;
+	Elf_Addr v;
+	int res;
+
+	pr_debug("Applying relocate section %u to %u\n", relsec,
+	       sechdrs[relsec].sh_info);
+
+	for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
+		/* This is where to make the change */
+		location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
+			+ rel[i].r_offset;
+		/* This is the symbol it is referring to */
+		sym = (Elf_Sym *)sechdrs[symindex].sh_addr
+			+ ELF_MIPS_R_SYM(rel[i]);
+		if (IS_ERR_VALUE(sym->st_value)) {
+			/* Ignore unresolved weak symbol */
+			if (ELF_ST_BIND(sym->st_info) == STB_WEAK)
+				continue;
+			printk(KERN_WARNING "%s: Unknown symbol %s\n",
+			       me->name, strtab + sym->st_name);
+			return -ENOENT;
+		}
+
+		v = sym->st_value + rel[i].r_addend;
+
+		res = reloc_handlers_rela[ELF_MIPS_R_TYPE(rel[i])](me, location, v);
+		if (res)
+			return res;
+	}
+
+	return 0;
+}
diff --git a/arch/mips/kernel/module.c b/arch/mips/kernel/module.c
index 4f8c3cb..07ff581 100644
--- a/arch/mips/kernel/module.c
+++ b/arch/mips/kernel/module.c
@@ -51,7 +51,7 @@ void *module_alloc(unsigned long size)
 }
 #endif
 
-static int apply_r_mips_none(struct module *me, u32 *location, Elf_Addr v)
+int apply_r_mips_none(struct module *me, u32 *location, Elf_Addr v)
 {
 	return 0;
 }
@@ -63,13 +63,6 @@ static int apply_r_mips_32_rel(struct module *me, u32 *location, Elf_Addr v)
 	return 0;
 }
 
-static int apply_r_mips_32_rela(struct module *me, u32 *location, Elf_Addr v)
-{
-	*location = v;
-
-	return 0;
-}
-
 static int apply_r_mips_26_rel(struct module *me, u32 *location, Elf_Addr v)
 {
 	if (v % 4) {
@@ -91,26 +84,6 @@ static int apply_r_mips_26_rel(struct module *me, u32 *location, Elf_Addr v)
 	return 0;
 }
 
-static int apply_r_mips_26_rela(struct module *me, u32 *location, Elf_Addr v)
-{
-	if (v % 4) {
-		pr_err("module %s: dangerous R_MIPS_26 RELArelocation\n",
-		       me->name);
-		return -ENOEXEC;
-	}
-
-	if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) {
-		printk(KERN_ERR
-		       "module %s: relocation overflow\n",
-		       me->name);
-		return -ENOEXEC;
-	}
-
-	*location = (*location & ~0x03ffffff) | ((v >> 2) & 0x03ffffff);
-
-	return 0;
-}
-
 static int apply_r_mips_hi16_rel(struct module *me, u32 *location, Elf_Addr v)
 {
 	struct mips_hi16 *n;
@@ -132,14 +105,6 @@ static int apply_r_mips_hi16_rel(struct module *me, u32 *location, Elf_Addr v)
 	return 0;
 }
 
-static int apply_r_mips_hi16_rela(struct module *me, u32 *location, Elf_Addr v)
-{
-	*location = (*location & 0xffff0000) |
-	            ((((long long) v + 0x8000LL) >> 16) & 0xffff);
-
-	return 0;
-}
-
 static void free_relocation_chain(struct mips_hi16 *l)
 {
 	struct mips_hi16 *next;
@@ -217,38 +182,6 @@ out_danger:
 	return -ENOEXEC;
 }
 
-static int apply_r_mips_lo16_rela(struct module *me, u32 *location, Elf_Addr v)
-{
-	*location = (*location & 0xffff0000) | (v & 0xffff);
-
-	return 0;
-}
-
-static int apply_r_mips_64_rela(struct module *me, u32 *location, Elf_Addr v)
-{
-	*(Elf_Addr *)location = v;
-
-	return 0;
-}
-
-static int apply_r_mips_higher_rela(struct module *me, u32 *location,
-				    Elf_Addr v)
-{
-	*location = (*location & 0xffff0000) |
-	            ((((long long) v + 0x80008000LL) >> 32) & 0xffff);
-
-	return 0;
-}
-
-static int apply_r_mips_highest_rela(struct module *me, u32 *location,
-				     Elf_Addr v)
-{
-	*location = (*location & 0xffff0000) |
-	            ((((long long) v + 0x800080008000LL) >> 48) & 0xffff);
-
-	return 0;
-}
-
 static int (*reloc_handlers_rel[]) (struct module *me, u32 *location,
 				Elf_Addr v) = {
 	[R_MIPS_NONE]		= apply_r_mips_none,
@@ -258,18 +191,6 @@ static int (*reloc_handlers_rel[]) (struct module *me, u32 *location,
 	[R_MIPS_LO16]		= apply_r_mips_lo16_rel
 };
 
-static int (*reloc_handlers_rela[]) (struct module *me, u32 *location,
-				Elf_Addr v) = {
-	[R_MIPS_NONE]		= apply_r_mips_none,
-	[R_MIPS_32]		= apply_r_mips_32_rela,
-	[R_MIPS_26]		= apply_r_mips_26_rela,
-	[R_MIPS_HI16]		= apply_r_mips_hi16_rela,
-	[R_MIPS_LO16]		= apply_r_mips_lo16_rela,
-	[R_MIPS_64]		= apply_r_mips_64_rela,
-	[R_MIPS_HIGHER]		= apply_r_mips_higher_rela,
-	[R_MIPS_HIGHEST]	= apply_r_mips_highest_rela
-};
-
 int apply_relocate(Elf_Shdr *sechdrs, const char *strtab,
 		   unsigned int symindex, unsigned int relsec,
 		   struct module *me)
@@ -324,46 +245,6 @@ int apply_relocate(Elf_Shdr *sechdrs, const char *strtab,
 	return 0;
 }
 
-int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
-		       unsigned int symindex, unsigned int relsec,
-		       struct module *me)
-{
-	Elf_Mips_Rela *rel = (void *) sechdrs[relsec].sh_addr;
-	Elf_Sym *sym;
-	u32 *location;
-	unsigned int i;
-	Elf_Addr v;
-	int res;
-
-	pr_debug("Applying relocate section %u to %u\n", relsec,
-	       sechdrs[relsec].sh_info);
-
-	for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
-		/* This is where to make the change */
-		location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
-			+ rel[i].r_offset;
-		/* This is the symbol it is referring to */
-		sym = (Elf_Sym *)sechdrs[symindex].sh_addr
-			+ ELF_MIPS_R_SYM(rel[i]);
-		if (IS_ERR_VALUE(sym->st_value)) {
-			/* Ignore unresolved weak symbol */
-			if (ELF_ST_BIND(sym->st_info) == STB_WEAK)
-				continue;
-			printk(KERN_WARNING "%s: Unknown symbol %s\n",
-			       me->name, strtab + sym->st_name);
-			return -ENOENT;
-		}
-
-		v = sym->st_value + rel[i].r_addend;
-
-		res = reloc_handlers_rela[ELF_MIPS_R_TYPE(rel[i])](me, location, v);
-		if (res)
-			return res;
-	}
-
-	return 0;
-}
-
 /* Given an address, look for it in the module exception tables. */
 const struct exception_table_entry *search_module_dbetables(unsigned long addr)
 {
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index 4812c6d..94fd0f4 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -15,14 +15,17 @@
  * binaries.
  */
 #include <linux/compiler.h>
+#include <linux/elf.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/errno.h>
 #include <linux/ptrace.h>
+#include <linux/regset.h>
 #include <linux/smp.h>
 #include <linux/user.h>
 #include <linux/security.h>
+#include <linux/tracehook.h>
 #include <linux/audit.h>
 #include <linux/seccomp.h>
 
@@ -254,6 +257,133 @@ int ptrace_set_watch_regs(struct task_struct *child,
 	return 0;
 }
 
+/* regset get/set implementations */
+
+static int gpr_get(struct task_struct *target,
+		   const struct user_regset *regset,
+		   unsigned int pos, unsigned int count,
+		   void *kbuf, void __user *ubuf)
+{
+	struct pt_regs *regs = task_pt_regs(target);
+
+	return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+				   regs, 0, sizeof(*regs));
+}
+
+static int gpr_set(struct task_struct *target,
+		   const struct user_regset *regset,
+		   unsigned int pos, unsigned int count,
+		   const void *kbuf, const void __user *ubuf)
+{
+	struct pt_regs newregs;
+	int ret;
+
+	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+				 &newregs,
+				 0, sizeof(newregs));
+	if (ret)
+		return ret;
+
+	*task_pt_regs(target) = newregs;
+
+	return 0;
+}
+
+static int fpr_get(struct task_struct *target,
+		   const struct user_regset *regset,
+		   unsigned int pos, unsigned int count,
+		   void *kbuf, void __user *ubuf)
+{
+	return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+				   &target->thread.fpu,
+				   0, sizeof(elf_fpregset_t));
+	/* XXX fcr31  */
+}
+
+static int fpr_set(struct task_struct *target,
+		   const struct user_regset *regset,
+		   unsigned int pos, unsigned int count,
+		   const void *kbuf, const void __user *ubuf)
+{
+	return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+				  &target->thread.fpu,
+				  0, sizeof(elf_fpregset_t));
+	/* XXX fcr31  */
+}
+
+enum mips_regset {
+	REGSET_GPR,
+	REGSET_FPR,
+};
+
+static const struct user_regset mips_regsets[] = {
+	[REGSET_GPR] = {
+		.core_note_type	= NT_PRSTATUS,
+		.n		= ELF_NGREG,
+		.size		= sizeof(unsigned int),
+		.align		= sizeof(unsigned int),
+		.get		= gpr_get,
+		.set		= gpr_set,
+	},
+	[REGSET_FPR] = {
+		.core_note_type	= NT_PRFPREG,
+		.n		= ELF_NFPREG,
+		.size		= sizeof(elf_fpreg_t),
+		.align		= sizeof(elf_fpreg_t),
+		.get		= fpr_get,
+		.set		= fpr_set,
+	},
+};
+
+static const struct user_regset_view user_mips_view = {
+	.name		= "mips",
+	.e_machine	= ELF_ARCH,
+	.ei_osabi	= ELF_OSABI,
+	.regsets	= mips_regsets,
+	.n		= ARRAY_SIZE(mips_regsets),
+};
+
+static const struct user_regset mips64_regsets[] = {
+	[REGSET_GPR] = {
+		.core_note_type	= NT_PRSTATUS,
+		.n		= ELF_NGREG,
+		.size		= sizeof(unsigned long),
+		.align		= sizeof(unsigned long),
+		.get		= gpr_get,
+		.set		= gpr_set,
+	},
+	[REGSET_FPR] = {
+		.core_note_type	= NT_PRFPREG,
+		.n		= ELF_NFPREG,
+		.size		= sizeof(elf_fpreg_t),
+		.align		= sizeof(elf_fpreg_t),
+		.get		= fpr_get,
+		.set		= fpr_set,
+	},
+};
+
+static const struct user_regset_view user_mips64_view = {
+	.name		= "mips",
+	.e_machine	= ELF_ARCH,
+	.ei_osabi	= ELF_OSABI,
+	.regsets	= mips64_regsets,
+	.n		= ARRAY_SIZE(mips_regsets),
+};
+
+const struct user_regset_view *task_user_regset_view(struct task_struct *task)
+{
+#ifdef CONFIG_32BIT
+	return &user_mips_view;
+#endif
+
+#ifdef CONFIG_MIPS32_O32
+		if (test_thread_flag(TIF_32BIT_REGS))
+			return &user_mips_view;
+#endif
+
+	return &user_mips64_view;
+}
+
 long arch_ptrace(struct task_struct *child, long request,
 		 unsigned long addr, unsigned long data)
 {
@@ -516,50 +646,23 @@ long arch_ptrace(struct task_struct *child, long request,
 	return ret;
 }
 
-static inline int audit_arch(void)
-{
-	int arch = EM_MIPS;
-#ifdef CONFIG_64BIT
-	arch |=  __AUDIT_ARCH_64BIT;
-#endif
-#if defined(__LITTLE_ENDIAN)
-	arch |=  __AUDIT_ARCH_LE;
-#endif
-	return arch;
-}
-
 /*
  * Notification of system call entry/exit
  * - triggered by current->work.syscall_trace
  */
 asmlinkage void syscall_trace_enter(struct pt_regs *regs)
 {
+	long ret = 0;
+
 	/* do the secure computing check first */
 	secure_computing_strict(regs->regs[2]);
 
-	if (!(current->ptrace & PT_PTRACED))
-		goto out;
-
-	if (!test_thread_flag(TIF_SYSCALL_TRACE))
-		goto out;
-
-	/* The 0x80 provides a way for the tracing parent to distinguish
-	   between a syscall stop and SIGTRAP delivery */
-	ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) ?
-	                         0x80 : 0));
-
-	/*
-	 * this isn't the same as continuing with a signal, but it will do
-	 * for normal use.  strace only continues with a signal if the
-	 * stopping signal is not SIGTRAP.  -brl
-	 */
-	if (current->exit_code) {
-		send_sig(current->exit_code, current, 1);
-		current->exit_code = 0;
-	}
+	if (test_thread_flag(TIF_SYSCALL_TRACE) &&
+	    tracehook_report_syscall_entry(regs))
+		ret = -1;
 
-out:
-	audit_syscall_entry(audit_arch(), regs->regs[2],
+	audit_syscall_entry(__syscall_get_arch(),
+			    regs->regs[2],
 			    regs->regs[4], regs->regs[5],
 			    regs->regs[6], regs->regs[7]);
 }
@@ -572,24 +675,6 @@ asmlinkage void syscall_trace_leave(struct pt_regs *regs)
 {
 	audit_syscall_exit(regs);
 
-	if (!(current->ptrace & PT_PTRACED))
-		return;
-
-	if (!test_thread_flag(TIF_SYSCALL_TRACE))
-		return;
-
-	/* The 0x80 provides a way for the tracing parent to distinguish
-	   between a syscall stop and SIGTRAP delivery */
-	ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) ?
-	                         0x80 : 0));
-
-	/*
-	 * this isn't the same as continuing with a signal, but it will do
-	 * for normal use.  strace only continues with a signal if the
-	 * stopping signal is not SIGTRAP.  -brl
-	 */
-	if (current->exit_code) {
-		send_sig(current->exit_code, current, 1);
-		current->exit_code = 0;
-	}
+	if (test_thread_flag(TIF_SYSCALL_TRACE))
+		tracehook_report_syscall_exit(regs, 0);
 }
diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S
index a632bc1..88af1bb 100644
--- a/arch/mips/kernel/scall32-o32.S
+++ b/arch/mips/kernel/scall32-o32.S
@@ -40,17 +40,58 @@ NESTED(handle_sys, PT_SIZE, sp)
 	sw	t1, PT_EPC(sp)
 	beqz	t0, illegal_syscall
 
-	sll	t0, v0, 3
+	sll	t0, v0, 2
 	la	t1, sys_call_table
 	addu	t1, t0
 	lw	t2, (t1)		# syscall routine
-	lw	t3, 4(t1)		# >= 0 if we need stack arguments
 	beqz	t2, illegal_syscall
 
 	sw	a3, PT_R26(sp)		# save a3 for syscall restarting
-	bgez	t3, stackargs
 
-stack_done:
+	/*
+	 * More than four arguments.  Try to deal with it by copying the
+	 * stack arguments from the user stack to the kernel stack.
+	 * This Sucks (TM).
+	 */
+	lw	t0, PT_R29(sp)		# get old user stack pointer
+
+	/*
+	 * We intentionally keep the kernel stack a little below the top of
+	 * userspace so we don't have to do a slower byte accurate check here.
+	 */
+	lw	t5, TI_ADDR_LIMIT($28)
+	addu	t4, t0, 32
+	and	t5, t4
+	bltz	t5, bad_stack		# -> sp is bad
+
+	/*
+	 * Ok, copy the args from the luser stack to the kernel stack.
+	 * t3 is the precomputed number of instruction bytes needed to
+	 * load or store arguments 6-8.
+	 */
+
+	.set    push
+	.set    noreorder
+	.set	nomacro
+
+1:	lw	t5, 16(t0)		# argument #5 from usp
+4:	lw	t6, 20(t0)		# argument #6 from usp
+3:	lw	t7, 24(t0)		# argument #7 from usp
+2:	lw	t8, 28(t0)		# argument #8 from usp
+
+	sw	t5, 16(sp)		# argument #5 to ksp
+	sw	t6, 20(sp)		# argument #6 to ksp
+	sw	t7, 24(sp)		# argument #7 to ksp
+	sw	t8, 28(sp)		# argument #8 to ksp
+	.set	pop
+
+	.section __ex_table,"a"
+	PTR	1b,bad_stack
+	PTR	2b,bad_stack
+	PTR	3b,bad_stack
+	PTR	4b,bad_stack
+	.previous
+
 	lw	t0, TI_FLAGS($28)	# syscall tracing enabled?
 	li	t1, _TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT
 	and	t0, t1
@@ -69,18 +110,7 @@ stack_done:
 1:	sw	v0, PT_R2(sp)		# result
 
 o32_syscall_exit:
-	local_irq_disable		# make sure need_resched and
-					# signals dont change between
-					# sampling and return
-	lw	a2, TI_FLAGS($28)	# current->work
-	li	t0, _TIF_ALLWORK_MASK
-	and	t0, a2
-	bnez	t0, o32_syscall_exit_work
-
-	j	restore_partial
-
-o32_syscall_exit_work:
-	j	syscall_exit_work_partial
+	j	syscall_exit_partial
 
 /* ------------------------------------------------------------------------ */
 
@@ -113,57 +143,6 @@ syscall_trace_entry:
 /* ------------------------------------------------------------------------ */
 
 	/*
-	 * More than four arguments.  Try to deal with it by copying the
-	 * stack arguments from the user stack to the kernel stack.
-	 * This Sucks (TM).
-	 */
-stackargs:
-	lw	t0, PT_R29(sp)		# get old user stack pointer
-
-	/*
-	 * We intentionally keep the kernel stack a little below the top of
-	 * userspace so we don't have to do a slower byte accurate check here.
-	 */
-	lw	t5, TI_ADDR_LIMIT($28)
-	addu	t4, t0, 32
-	and	t5, t4
-	bltz	t5, bad_stack		# -> sp is bad
-
-	/* Ok, copy the args from the luser stack to the kernel stack.
-	 * t3 is the precomputed number of instruction bytes needed to
-	 * load or store arguments 6-8.
-	 */
-
-	la	t1, 5f			# load up to 3 arguments
-	subu	t1, t3
-1:	lw	t5, 16(t0)		# argument #5 from usp
-	.set    push
-	.set    noreorder
-	.set	nomacro
-	jr	t1
-	 addiu	t1, 6f - 5f
-
-2:	lw	t8, 28(t0)		# argument #8 from usp
-3:	lw	t7, 24(t0)		# argument #7 from usp
-4:	lw	t6, 20(t0)		# argument #6 from usp
-5:	jr	t1
-	 sw	t5, 16(sp)		# argument #5 to ksp
-
-	sw	t8, 28(sp)		# argument #8 to ksp
-	sw	t7, 24(sp)		# argument #7 to ksp
-	sw	t6, 20(sp)		# argument #6 to ksp
-6:	j	stack_done		# go back
-	 nop
-	.set	pop
-
-	.section __ex_table,"a"
-	PTR	1b,bad_stack
-	PTR	2b,bad_stack
-	PTR	3b,bad_stack
-	PTR	4b,bad_stack
-	.previous
-
-	/*
 	 * The stackpointer for a call with more than 4 arguments is bad.
 	 * We probably should handle this case a bit more drastic.
 	 */
@@ -189,7 +168,7 @@ illegal_syscall:
 	subu	t0, a0, __NR_O32_Linux	# check syscall number
 	sltiu	v0, t0, __NR_O32_Linux_syscalls + 1
 	beqz	t0, einval		# do not recurse
-	sll	t1, t0, 3
+	sll	t1, t0, 2
 	beqz	v0, einval
 	lw	t2, sys_call_table(t1)		# syscall routine
 
@@ -220,260 +199,248 @@ einval:	li	v0, -ENOSYS
 	jr	ra
 	END(sys_syscall)
 
-	.macro	fifty ptr, nargs, from=1, to=50
-	sys	\ptr		\nargs
-	.if	\to-\from
-	fifty	\ptr,\nargs,"(\from+1)",\to
-	.endif
-	.endm
-
-	.macro	mille ptr, nargs, from=1, to=20
-	fifty	\ptr,\nargs
-	.if	\to-\from
-	mille	\ptr,\nargs,"(\from+1)",\to
-	.endif
-	.endm
-
-	.macro	syscalltable
-	sys	sys_syscall		8	/* 4000 */
-	sys	sys_exit		1
-	sys	sys_fork		0
-	sys	sys_read		3
-	sys	sys_write		3
-	sys	sys_open		3	/* 4005 */
-	sys	sys_close		1
-	sys	sys_waitpid		3
-	sys	sys_creat		2
-	sys	sys_link		2
-	sys	sys_unlink		1	/* 4010 */
-	sys	sys_execve		0
-	sys	sys_chdir		1
-	sys	sys_time		1
-	sys	sys_mknod		3
-	sys	sys_chmod		2	/* 4015 */
-	sys	sys_lchown		3
-	sys	sys_ni_syscall		0
-	sys	sys_ni_syscall		0	/* was sys_stat */
-	sys	sys_lseek		3
-	sys	sys_getpid		0	/* 4020 */
-	sys	sys_mount		5
-	sys	sys_oldumount		1
-	sys	sys_setuid		1
-	sys	sys_getuid		0
-	sys	sys_stime		1	/* 4025 */
-	sys	sys_ptrace		4
-	sys	sys_alarm		1
-	sys	sys_ni_syscall		0	/* was sys_fstat */
-	sys	sys_pause		0
-	sys	sys_utime		2	/* 4030 */
-	sys	sys_ni_syscall		0
-	sys	sys_ni_syscall		0
-	sys	sys_access		2
-	sys	sys_nice		1
-	sys	sys_ni_syscall		0	/* 4035 */
-	sys	sys_sync		0
-	sys	sys_kill		2
-	sys	sys_rename		2
-	sys	sys_mkdir		2
-	sys	sys_rmdir		1	/* 4040 */
-	sys	sys_dup			1
-	sys	sysm_pipe		0
-	sys	sys_times		1
-	sys	sys_ni_syscall		0
-	sys	sys_brk			1	/* 4045 */
-	sys	sys_setgid		1
-	sys	sys_getgid		0
-	sys	sys_ni_syscall		0	/* was signal(2) */
-	sys	sys_geteuid		0
-	sys	sys_getegid		0	/* 4050 */
-	sys	sys_acct		1
-	sys	sys_umount		2
-	sys	sys_ni_syscall		0
-	sys	sys_ioctl		3
-	sys	sys_fcntl		3	/* 4055 */
-	sys	sys_ni_syscall		2
-	sys	sys_setpgid		2
-	sys	sys_ni_syscall		0
-	sys	sys_olduname		1
-	sys	sys_umask		1	/* 4060 */
-	sys	sys_chroot		1
-	sys	sys_ustat		2
-	sys	sys_dup2		2
-	sys	sys_getppid		0
-	sys	sys_getpgrp		0	/* 4065 */
-	sys	sys_setsid		0
-	sys	sys_sigaction		3
-	sys	sys_sgetmask		0
-	sys	sys_ssetmask		1
-	sys	sys_setreuid		2	/* 4070 */
-	sys	sys_setregid		2
-	sys	sys_sigsuspend		0
-	sys	sys_sigpending		1
-	sys	sys_sethostname		2
-	sys	sys_setrlimit		2	/* 4075 */
-	sys	sys_getrlimit		2
-	sys	sys_getrusage		2
-	sys	sys_gettimeofday	2
-	sys	sys_settimeofday	2
-	sys	sys_getgroups		2	/* 4080 */
-	sys	sys_setgroups		2
-	sys	sys_ni_syscall		0	/* old_select */
-	sys	sys_symlink		2
-	sys	sys_ni_syscall		0	/* was sys_lstat */
-	sys	sys_readlink		3	/* 4085 */
-	sys	sys_uselib		1
-	sys	sys_swapon		2
-	sys	sys_reboot		3
-	sys	sys_old_readdir		3
-	sys	sys_mips_mmap		6	/* 4090 */
-	sys	sys_munmap		2
-	sys	sys_truncate		2
-	sys	sys_ftruncate		2
-	sys	sys_fchmod		2
-	sys	sys_fchown		3	/* 4095 */
-	sys	sys_getpriority		2
-	sys	sys_setpriority		3
-	sys	sys_ni_syscall		0
-	sys	sys_statfs		2
-	sys	sys_fstatfs		2	/* 4100 */
-	sys	sys_ni_syscall		0	/* was ioperm(2) */
-	sys	sys_socketcall		2
-	sys	sys_syslog		3
-	sys	sys_setitimer		3
-	sys	sys_getitimer		2	/* 4105 */
-	sys	sys_newstat		2
-	sys	sys_newlstat		2
-	sys	sys_newfstat		2
-	sys	sys_uname		1
-	sys	sys_ni_syscall		0	/* 4110 was iopl(2) */
-	sys	sys_vhangup		0
-	sys	sys_ni_syscall		0	/* was sys_idle() */
-	sys	sys_ni_syscall		0	/* was sys_vm86 */
-	sys	sys_wait4		4
-	sys	sys_swapoff		1	/* 4115 */
-	sys	sys_sysinfo		1
-	sys	sys_ipc			6
-	sys	sys_fsync		1
-	sys	sys_sigreturn		0
-	sys	sys_clone		0	/* 4120 */
-	sys	sys_setdomainname	2
-	sys	sys_newuname		1
-	sys	sys_ni_syscall		0	/* sys_modify_ldt */
-	sys	sys_adjtimex		1
-	sys	sys_mprotect		3	/* 4125 */
-	sys	sys_sigprocmask		3
-	sys	sys_ni_syscall		0	/* was create_module */
-	sys	sys_init_module		5
-	sys	sys_delete_module	1
-	sys	sys_ni_syscall		0	/* 4130	was get_kernel_syms */
-	sys	sys_quotactl		4
-	sys	sys_getpgid		1
-	sys	sys_fchdir		1
-	sys	sys_bdflush		2
-	sys	sys_sysfs		3	/* 4135 */
-	sys	sys_personality		1
-	sys	sys_ni_syscall		0	/* for afs_syscall */
-	sys	sys_setfsuid		1
-	sys	sys_setfsgid		1
-	sys	sys_llseek		5	/* 4140 */
-	sys	sys_getdents		3
-	sys	sys_select		5
-	sys	sys_flock		2
-	sys	sys_msync		3
-	sys	sys_readv		3	/* 4145 */
-	sys	sys_writev		3
-	sys	sys_cacheflush		3
-	sys	sys_cachectl		3
-	sys	sys_sysmips		4
-	sys	sys_ni_syscall		0	/* 4150 */
-	sys	sys_getsid		1
-	sys	sys_fdatasync		1
-	sys	sys_sysctl		1
-	sys	sys_mlock		2
-	sys	sys_munlock		2	/* 4155 */
-	sys	sys_mlockall		1
-	sys	sys_munlockall		0
-	sys	sys_sched_setparam	2
-	sys	sys_sched_getparam	2
-	sys	sys_sched_setscheduler	3	/* 4160 */
-	sys	sys_sched_getscheduler	1
-	sys	sys_sched_yield		0
-	sys	sys_sched_get_priority_max 1
-	sys	sys_sched_get_priority_min 1
-	sys	sys_sched_rr_get_interval 2	/* 4165 */
-	sys	sys_nanosleep,		2
-	sys	sys_mremap,		5
-	sys	sys_accept		3
-	sys	sys_bind		3
-	sys	sys_connect		3	/* 4170 */
-	sys	sys_getpeername		3
-	sys	sys_getsockname		3
-	sys	sys_getsockopt		5
-	sys	sys_listen		2
-	sys	sys_recv		4	/* 4175 */
-	sys	sys_recvfrom		6
-	sys	sys_recvmsg		3
-	sys	sys_send		4
-	sys	sys_sendmsg		3
-	sys	sys_sendto		6	/* 4180 */
-	sys	sys_setsockopt		5
-	sys	sys_shutdown		2
-	sys	sys_socket		3
-	sys	sys_socketpair		4
-	sys	sys_setresuid		3	/* 4185 */
-	sys	sys_getresuid		3
-	sys	sys_ni_syscall		0	/* was sys_query_module */
-	sys	sys_poll		3
-	sys	sys_ni_syscall		0	/* was nfsservctl */
-	sys	sys_setresgid		3	/* 4190 */
-	sys	sys_getresgid		3
-	sys	sys_prctl		5
-	sys	sys_rt_sigreturn	0
-	sys	sys_rt_sigaction	4
-	sys	sys_rt_sigprocmask	4	/* 4195 */
-	sys	sys_rt_sigpending	2
-	sys	sys_rt_sigtimedwait	4
-	sys	sys_rt_sigqueueinfo	3
-	sys	sys_rt_sigsuspend	0
-	sys	sys_pread64		6	/* 4200 */
-	sys	sys_pwrite64		6
-	sys	sys_chown		3
-	sys	sys_getcwd		2
-	sys	sys_capget		2
-	sys	sys_capset		2	/* 4205 */
-	sys	sys_sigaltstack		0
-	sys	sys_sendfile		4
-	sys	sys_ni_syscall		0
-	sys	sys_ni_syscall		0
-	sys	sys_mips_mmap2		6	/* 4210 */
-	sys	sys_truncate64		4
-	sys	sys_ftruncate64		4
-	sys	sys_stat64		2
-	sys	sys_lstat64		2
-	sys	sys_fstat64		2	/* 4215 */
-	sys	sys_pivot_root		2
-	sys	sys_mincore		3
-	sys	sys_madvise		3
-	sys	sys_getdents64		3
-	sys	sys_fcntl64		3	/* 4220 */
-	sys	sys_ni_syscall		0
-	sys	sys_gettid		0
-	sys	sys_readahead		5
-	sys	sys_setxattr		5
-	sys	sys_lsetxattr		5	/* 4225 */
-	sys	sys_fsetxattr		5
-	sys	sys_getxattr		4
-	sys	sys_lgetxattr		4
-	sys	sys_fgetxattr		4
-	sys	sys_listxattr		3	/* 4230 */
-	sys	sys_llistxattr		3
-	sys	sys_flistxattr		3
-	sys	sys_removexattr		2
-	sys	sys_lremovexattr	2
-	sys	sys_fremovexattr	2	/* 4235 */
-	sys	sys_tkill		2
-	sys	sys_sendfile64		5
-	sys	sys_futex		6
+	.align	2
+	.type	sys_call_table, @object
+EXPORT(sys_call_table)
+	PTR	sys_syscall			/* 4000 */
+	PTR	sys_exit
+	PTR	sys_fork
+	PTR	sys_read
+	PTR	sys_write
+	PTR	sys_open			/* 4005 */
+	PTR	sys_close
+	PTR	sys_waitpid
+	PTR	sys_creat
+	PTR	sys_link
+	PTR	sys_unlink			/* 4010 */
+	PTR	sys_execve
+	PTR	sys_chdir
+	PTR	sys_time
+	PTR	sys_mknod
+	PTR	sys_chmod			/* 4015 */
+	PTR	sys_lchown
+	PTR	sys_ni_syscall
+	PTR	sys_ni_syscall			/* was sys_stat */
+	PTR	sys_lseek
+	PTR	sys_getpid			/* 4020 */
+	PTR	sys_mount
+	PTR	sys_oldumount
+	PTR	sys_setuid
+	PTR	sys_getuid
+	PTR	sys_stime			/* 4025 */
+	PTR	sys_ptrace
+	PTR	sys_alarm
+	PTR	sys_ni_syscall			/* was sys_fstat */
+	PTR	sys_pause
+	PTR	sys_utime			/* 4030 */
+	PTR	sys_ni_syscall
+	PTR	sys_ni_syscall
+	PTR	sys_access
+	PTR	sys_nice
+	PTR	sys_ni_syscall			/* 4035 */
+	PTR	sys_sync
+	PTR	sys_kill
+	PTR	sys_rename
+	PTR	sys_mkdir
+	PTR	sys_rmdir			/* 4040 */
+	PTR	sys_dup
+	PTR	sysm_pipe
+	PTR	sys_times
+	PTR	sys_ni_syscall
+	PTR	sys_brk				/* 4045 */
+	PTR	sys_setgid
+	PTR	sys_getgid
+	PTR	sys_ni_syscall			/* was signal(2) */
+	PTR	sys_geteuid
+	PTR	sys_getegid			/* 4050 */
+	PTR	sys_acct
+	PTR	sys_umount
+	PTR	sys_ni_syscall
+	PTR	sys_ioctl
+	PTR	sys_fcntl			/* 4055 */
+	PTR	sys_ni_syscall
+	PTR	sys_setpgid
+	PTR	sys_ni_syscall
+	PTR	sys_olduname
+	PTR	sys_umask			/* 4060 */
+	PTR	sys_chroot
+	PTR	sys_ustat
+	PTR	sys_dup2
+	PTR	sys_getppid
+	PTR	sys_getpgrp			/* 4065 */
+	PTR	sys_setsid
+	PTR	sys_sigaction
+	PTR	sys_sgetmask
+	PTR	sys_ssetmask
+	PTR	sys_setreuid			/* 4070 */
+	PTR	sys_setregid
+	PTR	sys_sigsuspend
+	PTR	sys_sigpending
+	PTR	sys_sethostname
+	PTR	sys_setrlimit			/* 4075 */
+	PTR	sys_getrlimit
+	PTR	sys_getrusage
+	PTR	sys_gettimeofday
+	PTR	sys_settimeofday
+	PTR	sys_getgroups			/* 4080 */
+	PTR	sys_setgroups
+	PTR	sys_ni_syscall			/* old_select */
+	PTR	sys_symlink
+	PTR	sys_ni_syscall			/* was sys_lstat */
+	PTR	sys_readlink			/* 4085 */
+	PTR	sys_uselib
+	PTR	sys_swapon
+	PTR	sys_reboot
+	PTR	sys_old_readdir
+	PTR	sys_mips_mmap			/* 4090 */
+	PTR	sys_munmap
+	PTR	sys_truncate
+	PTR	sys_ftruncate
+	PTR	sys_fchmod
+	PTR	sys_fchown			/* 4095 */
+	PTR	sys_getpriority
+	PTR	sys_setpriority
+	PTR	sys_ni_syscall
+	PTR	sys_statfs
+	PTR	sys_fstatfs			/* 4100 */
+	PTR	sys_ni_syscall			/* was ioperm(2) */
+	PTR	sys_socketcall
+	PTR	sys_syslog
+	PTR	sys_setitimer
+	PTR	sys_getitimer			/* 4105 */
+	PTR	sys_newstat
+	PTR	sys_newlstat
+	PTR	sys_newfstat
+	PTR	sys_uname
+	PTR	sys_ni_syscall			/* 4110 was iopl(2) */
+	PTR	sys_vhangup
+	PTR	sys_ni_syscall			/* was sys_idle() */
+	PTR	sys_ni_syscall			/* was sys_vm86 */
+	PTR	sys_wait4
+	PTR	sys_swapoff			/* 4115 */
+	PTR	sys_sysinfo
+	PTR	sys_ipc
+	PTR	sys_fsync
+	PTR	sys_sigreturn
+	PTR	sys_clone			/* 4120 */
+	PTR	sys_setdomainname
+	PTR	sys_newuname
+	PTR	sys_ni_syscall			/* sys_modify_ldt */
+	PTR	sys_adjtimex
+	PTR	sys_mprotect			/* 4125 */
+	PTR	sys_sigprocmask
+	PTR	sys_ni_syscall			/* was create_module */
+	PTR	sys_init_module
+	PTR	sys_delete_module
+	PTR	sys_ni_syscall			/* 4130	was get_kernel_syms */
+	PTR	sys_quotactl
+	PTR	sys_getpgid
+	PTR	sys_fchdir
+	PTR	sys_bdflush
+	PTR	sys_sysfs			/* 4135 */
+	PTR	sys_personality
+	PTR	sys_ni_syscall			/* for afs_syscall */
+	PTR	sys_setfsuid
+	PTR	sys_setfsgid
+	PTR	sys_llseek			/* 4140 */
+	PTR	sys_getdents
+	PTR	sys_select
+	PTR	sys_flock
+	PTR	sys_msync
+	PTR	sys_readv			/* 4145 */
+	PTR	sys_writev
+	PTR	sys_cacheflush
+	PTR	sys_cachectl
+	PTR	sys_sysmips
+	PTR	sys_ni_syscall			/* 4150 */
+	PTR	sys_getsid
+	PTR	sys_fdatasync
+	PTR	sys_sysctl
+	PTR	sys_mlock
+	PTR	sys_munlock			/* 4155 */
+	PTR	sys_mlockall
+	PTR	sys_munlockall
+	PTR	sys_sched_setparam
+	PTR	sys_sched_getparam
+	PTR	sys_sched_setscheduler		/* 4160 */
+	PTR	sys_sched_getscheduler
+	PTR	sys_sched_yield
+	PTR	sys_sched_get_priority_max
+	PTR	sys_sched_get_priority_min
+	PTR	sys_sched_rr_get_interval	/* 4165 */
+	PTR	sys_nanosleep
+	PTR	sys_mremap
+	PTR	sys_accept
+	PTR	sys_bind
+	PTR	sys_connect			/* 4170 */
+	PTR	sys_getpeername
+	PTR	sys_getsockname
+	PTR	sys_getsockopt
+	PTR	sys_listen
+	PTR	sys_recv			/* 4175 */
+	PTR	sys_recvfrom
+	PTR	sys_recvmsg
+	PTR	sys_send
+	PTR	sys_sendmsg
+	PTR	sys_sendto			/* 4180 */
+	PTR	sys_setsockopt
+	PTR	sys_shutdown
+	PTR	sys_socket
+	PTR	sys_socketpair
+	PTR	sys_setresuid			/* 4185 */
+	PTR	sys_getresuid
+	PTR	sys_ni_syscall			/* was sys_query_module */
+	PTR	sys_poll
+	PTR	sys_ni_syscall			/* was nfsservctl */
+	PTR	sys_setresgid			/* 4190 */
+	PTR	sys_getresgid
+	PTR	sys_prctl
+	PTR	sys_rt_sigreturn
+	PTR	sys_rt_sigaction
+	PTR	sys_rt_sigprocmask		/* 4195 */
+	PTR	sys_rt_sigpending
+	PTR	sys_rt_sigtimedwait
+	PTR	sys_rt_sigqueueinfo
+	PTR	sys_rt_sigsuspend
+	PTR	sys_pread64			/* 4200 */
+	PTR	sys_pwrite64
+	PTR	sys_chown
+	PTR	sys_getcwd
+	PTR	sys_capget
+	PTR	sys_capset			/* 4205 */
+	PTR	sys_sigaltstack
+	PTR	sys_sendfile
+	PTR	sys_ni_syscall
+	PTR	sys_ni_syscall
+	PTR	sys_mips_mmap2			/* 4210 */
+	PTR	sys_truncate64
+	PTR	sys_ftruncate64
+	PTR	sys_stat64
+	PTR	sys_lstat64
+	PTR	sys_fstat64			/* 4215 */
+	PTR	sys_pivot_root
+	PTR	sys_mincore
+	PTR	sys_madvise
+	PTR	sys_getdents64
+	PTR	sys_fcntl64			/* 4220 */
+	PTR	sys_ni_syscall
+	PTR	sys_gettid
+	PTR	sys_readahead
+	PTR	sys_setxattr
+	PTR	sys_lsetxattr			/* 4225 */
+	PTR	sys_fsetxattr
+	PTR	sys_getxattr
+	PTR	sys_lgetxattr
+	PTR	sys_fgetxattr
+	PTR	sys_listxattr			/* 4230 */
+	PTR	sys_llistxattr
+	PTR	sys_flistxattr
+	PTR	sys_removexattr
+	PTR	sys_lremovexattr
+	PTR	sys_fremovexattr		/* 4235 */
+	PTR	sys_tkill
+	PTR	sys_sendfile64
+	PTR	sys_futex
 #ifdef CONFIG_MIPS_MT_FPAFF
 	/*
 	 * For FPU affinity scheduling on MIPS MT processors, we need to
@@ -481,130 +448,116 @@ einval:	li	v0, -ENOSYS
 	 * in kernel/sched.c.  Considered only temporary we only support these
 	 * hooks for the 32-bit kernel - there is no MIPS64 MT processor atm.
 	 */
-	sys	mipsmt_sys_sched_setaffinity	3
-	sys	mipsmt_sys_sched_getaffinity	3
+	PTR	mipsmt_sys_sched_setaffinity
+	PTR	mipsmt_sys_sched_getaffinity
 #else
-	sys	sys_sched_setaffinity	3
-	sys	sys_sched_getaffinity	3	/* 4240 */
+	PTR	sys_sched_setaffinity
+	PTR	sys_sched_getaffinity		/* 4240 */
 #endif /* CONFIG_MIPS_MT_FPAFF */
-	sys	sys_io_setup		2
-	sys	sys_io_destroy		1
-	sys	sys_io_getevents	5
-	sys	sys_io_submit		3
-	sys	sys_io_cancel		3	/* 4245 */
-	sys	sys_exit_group		1
-	sys	sys_lookup_dcookie	4
-	sys	sys_epoll_create	1
-	sys	sys_epoll_ctl		4
-	sys	sys_epoll_wait		4	/* 4250 */
-	sys	sys_remap_file_pages	5
-	sys	sys_set_tid_address	1
-	sys	sys_restart_syscall	0
-	sys	sys_fadvise64_64	7
-	sys	sys_statfs64		3	/* 4255 */
-	sys	sys_fstatfs64		2
-	sys	sys_timer_create	3
-	sys	sys_timer_settime	4
-	sys	sys_timer_gettime	2
-	sys	sys_timer_getoverrun	1	/* 4260 */
-	sys	sys_timer_delete	1
-	sys	sys_clock_settime	2
-	sys	sys_clock_gettime	2
-	sys	sys_clock_getres	2
-	sys	sys_clock_nanosleep	4	/* 4265 */
-	sys	sys_tgkill		3
-	sys	sys_utimes		2
-	sys	sys_mbind		4
-	sys	sys_ni_syscall		0	/* sys_get_mempolicy */
-	sys	sys_ni_syscall		0	/* 4270 sys_set_mempolicy */
-	sys	sys_mq_open		4
-	sys	sys_mq_unlink		1
-	sys	sys_mq_timedsend	5
-	sys	sys_mq_timedreceive	5
-	sys	sys_mq_notify		2	/* 4275 */
-	sys	sys_mq_getsetattr	3
-	sys	sys_ni_syscall		0	/* sys_vserver */
-	sys	sys_waitid		5
-	sys	sys_ni_syscall		0	/* available, was setaltroot */
-	sys	sys_add_key		5	/* 4280 */
-	sys	sys_request_key		4
-	sys	sys_keyctl		5
-	sys	sys_set_thread_area	1
-	sys	sys_inotify_init	0
-	sys	sys_inotify_add_watch	3	/* 4285 */
-	sys	sys_inotify_rm_watch	2
-	sys	sys_migrate_pages	4
-	sys	sys_openat		4
-	sys	sys_mkdirat		3
-	sys	sys_mknodat		4	/* 4290 */
-	sys	sys_fchownat		5
-	sys	sys_futimesat		3
-	sys	sys_fstatat64		4
-	sys	sys_unlinkat		3
-	sys	sys_renameat		4	/* 4295 */
-	sys	sys_linkat		5
-	sys	sys_symlinkat		3
-	sys	sys_readlinkat		4
-	sys	sys_fchmodat		3
-	sys	sys_faccessat		3	/* 4300 */
-	sys	sys_pselect6		6
-	sys	sys_ppoll		5
-	sys	sys_unshare		1
-	sys	sys_splice		6
-	sys	sys_sync_file_range	7	/* 4305 */
-	sys	sys_tee			4
-	sys	sys_vmsplice		4
-	sys	sys_move_pages		6
-	sys	sys_set_robust_list	2
-	sys	sys_get_robust_list	3	/* 4310 */
-	sys	sys_kexec_load		4
-	sys	sys_getcpu		3
-	sys	sys_epoll_pwait		6
-	sys	sys_ioprio_set		3
-	sys	sys_ioprio_get		2	/* 4315 */
-	sys	sys_utimensat		4
-	sys	sys_signalfd		3
-	sys	sys_ni_syscall		0	/* was timerfd */
-	sys	sys_eventfd		1
-	sys	sys_fallocate		6	/* 4320 */
-	sys	sys_timerfd_create	2
-	sys	sys_timerfd_gettime	2
-	sys	sys_timerfd_settime	4
-	sys	sys_signalfd4		4
-	sys	sys_eventfd2		2	/* 4325 */
-	sys	sys_epoll_create1	1
-	sys	sys_dup3		3
-	sys	sys_pipe2		2
-	sys	sys_inotify_init1	1
-	sys	sys_preadv		6	/* 4330 */
-	sys	sys_pwritev		6
-	sys	sys_rt_tgsigqueueinfo	4
-	sys	sys_perf_event_open	5
-	sys	sys_accept4		4
-	sys	sys_recvmmsg		5	/* 4335 */
-	sys	sys_fanotify_init	2
-	sys	sys_fanotify_mark	6
-	sys	sys_prlimit64		4
-	sys	sys_name_to_handle_at	5
-	sys	sys_open_by_handle_at	3	/* 4340 */
-	sys	sys_clock_adjtime	2
-	sys	sys_syncfs		1
-	sys	sys_sendmmsg		4
-	sys	sys_setns		2
-	sys	sys_process_vm_readv	6	/* 4345 */
-	sys	sys_process_vm_writev	6
-	.endm
-
-	/* We pre-compute the number of _instruction_ bytes needed to
-	   load or store the arguments 6-8. Negative values are ignored. */
-
-	.macro  sys function, nargs
-	PTR	\function
-	LONG	(\nargs << 2) - (5 << 2)
-	.endm
-
-	.align	3
-	.type	sys_call_table,@object
-EXPORT(sys_call_table)
-	syscalltable
+	PTR	sys_io_setup
+	PTR	sys_io_destroy
+	PTR	sys_io_getevents
+	PTR	sys_io_submit
+	PTR	sys_io_cancel			/* 4245 */
+	PTR	sys_exit_group
+	PTR	sys_lookup_dcookie
+	PTR	sys_epoll_create
+	PTR	sys_epoll_ctl
+	PTR	sys_epoll_wait			/* 4250 */
+	PTR	sys_remap_file_pages
+	PTR	sys_set_tid_address
+	PTR	sys_restart_syscall
+	PTR	sys_fadvise64_64
+	PTR	sys_statfs64			/* 4255 */
+	PTR	sys_fstatfs64
+	PTR	sys_timer_create
+	PTR	sys_timer_settime
+	PTR	sys_timer_gettime
+	PTR	sys_timer_getoverrun		/* 4260 */
+	PTR	sys_timer_delete
+	PTR	sys_clock_settime
+	PTR	sys_clock_gettime
+	PTR	sys_clock_getres
+	PTR	sys_clock_nanosleep		/* 4265 */
+	PTR	sys_tgkill
+	PTR	sys_utimes
+	PTR	sys_mbind
+	PTR	sys_ni_syscall			/* sys_get_mempolicy */
+	PTR	sys_ni_syscall			/* 4270 sys_set_mempolicy */
+	PTR	sys_mq_open
+	PTR	sys_mq_unlink
+	PTR	sys_mq_timedsend
+	PTR	sys_mq_timedreceive
+	PTR	sys_mq_notify			/* 4275 */
+	PTR	sys_mq_getsetattr
+	PTR	sys_ni_syscall			/* sys_vserver */
+	PTR	sys_waitid
+	PTR	sys_ni_syscall			/* available, was setaltroot */
+	PTR	sys_add_key			/* 4280 */
+	PTR	sys_request_key
+	PTR	sys_keyctl
+	PTR	sys_set_thread_area
+	PTR	sys_inotify_init
+	PTR	sys_inotify_add_watch		/* 4285 */
+	PTR	sys_inotify_rm_watch
+	PTR	sys_migrate_pages
+	PTR	sys_openat
+	PTR	sys_mkdirat
+	PTR	sys_mknodat			/* 4290 */
+	PTR	sys_fchownat
+	PTR	sys_futimesat
+	PTR	sys_fstatat64
+	PTR	sys_unlinkat
+	PTR	sys_renameat			/* 4295 */
+	PTR	sys_linkat
+	PTR	sys_symlinkat
+	PTR	sys_readlinkat
+	PTR	sys_fchmodat
+	PTR	sys_faccessat			/* 4300 */
+	PTR	sys_pselect6
+	PTR	sys_ppoll
+	PTR	sys_unshare
+	PTR	sys_splice
+	PTR	sys_sync_file_range		/* 4305 */
+	PTR	sys_tee
+	PTR	sys_vmsplice
+	PTR	sys_move_pages
+	PTR	sys_set_robust_list
+	PTR	sys_get_robust_list		/* 4310 */
+	PTR	sys_kexec_load
+	PTR	sys_getcpu
+	PTR	sys_epoll_pwait
+	PTR	sys_ioprio_set
+	PTR	sys_ioprio_get			/* 4315 */
+	PTR	sys_utimensat
+	PTR	sys_signalfd
+	PTR	sys_ni_syscall			/* was timerfd */
+	PTR	sys_eventfd
+	PTR	sys_fallocate			/* 4320 */
+	PTR	sys_timerfd_create
+	PTR	sys_timerfd_gettime
+	PTR	sys_timerfd_settime
+	PTR	sys_signalfd4
+	PTR	sys_eventfd2			/* 4325 */
+	PTR	sys_epoll_create1
+	PTR	sys_dup3
+	PTR	sys_pipe2
+	PTR	sys_inotify_init1
+	PTR	sys_preadv			/* 4330 */
+	PTR	sys_pwritev
+	PTR	sys_rt_tgsigqueueinfo
+	PTR	sys_perf_event_open
+	PTR	sys_accept4
+	PTR	sys_recvmmsg			/* 4335 */
+	PTR	sys_fanotify_init
+	PTR	sys_fanotify_mark
+	PTR	sys_prlimit64
+	PTR	sys_name_to_handle_at
+	PTR	sys_open_by_handle_at		/* 4340 */
+	PTR	sys_clock_adjtime
+	PTR	sys_syncfs
+	PTR	sys_sendmmsg
+	PTR	sys_setns
+	PTR	sys_process_vm_readv		/* 4345 */
+	PTR	sys_process_vm_writev
 	.size	sys_call_table, . - sys_call_table
diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S
index 3b5a5e9..6dddf3c 100644
--- a/arch/mips/kernel/scall64-64.S
+++ b/arch/mips/kernel/scall64-64.S
@@ -72,18 +72,7 @@ NESTED(handle_sys64, PT_SIZE, sp)
 1:	sd	v0, PT_R2(sp)		# result
 
 n64_syscall_exit:
-	local_irq_disable		# make sure need_resched and
-					# signals dont change between
-					# sampling and return
-	LONG_L	a2, TI_FLAGS($28)	# current->work
-	li	t0, _TIF_ALLWORK_MASK
-	and	t0, a2, t0
-	bnez	t0, n64_syscall_exit_work
-
-	j	restore_partial
-
-n64_syscall_exit_work:
-	j	syscall_exit_work_partial
+	j	syscall_exit_partial
 
 /* ------------------------------------------------------------------------ */
 
@@ -125,7 +114,8 @@ illegal_syscall:
 	END(handle_sys64)
 
 	.align	3
-sys_call_table:
+	.type	sys_call_table, @object
+EXPORT(sys_call_table)
 	PTR	sys_read			/* 5000 */
 	PTR	sys_write
 	PTR	sys_open
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
index 6be6f70..85ad2a6 100644
--- a/arch/mips/kernel/scall64-n32.S
+++ b/arch/mips/kernel/scall64-n32.S
@@ -17,12 +17,6 @@
 #include <asm/thread_info.h>
 #include <asm/unistd.h>
 
-/* This duplicates the definition from <linux/sched.h> */
-#define PT_TRACESYS	0x00000002	/* tracing system calls */
-
-/* This duplicates the definition from <asm/signal.h> */
-#define SIGILL		4		/* Illegal instruction (ANSI).  */
-
 #ifndef CONFIG_MIPS32_O32
 /* No O32, so define handle_sys here */
 #define handle_sysn32 handle_sys
@@ -70,18 +64,7 @@ NESTED(handle_sysn32, PT_SIZE, sp)
 	sd	t1, PT_R0(sp)		# save it for syscall restarting
 1:	sd	v0, PT_R2(sp)		# result
 
-	local_irq_disable		# make sure need_resched and
-					# signals dont change between
-					# sampling and return
-	LONG_L  a2, TI_FLAGS($28)	# current->work
-	li	t0, _TIF_ALLWORK_MASK
-	and	t0, a2, t0
-	bnez	t0, n32_syscall_exit_work
-
-	j	restore_partial
-
-n32_syscall_exit_work:
-	j	syscall_exit_work_partial
+	j	syscall_exit_partial
 
 /* ------------------------------------------------------------------------ */
 
@@ -120,6 +103,7 @@ not_n32_scall:
 
 	END(handle_sysn32)
 
+	.type	sysn32_call_table, @object
 EXPORT(sysn32_call_table)
 	PTR	sys_read			/* 6000 */
 	PTR	sys_write
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
index 5422855..c2d350c 100644
--- a/arch/mips/kernel/scall64-o32.S
+++ b/arch/mips/kernel/scall64-o32.S
@@ -53,7 +53,7 @@ NESTED(handle_sys, PT_SIZE, sp)
 	sll	a3, a3, 0
 
 	dsll	t0, v0, 3		# offset into table
-	ld	t2, (sys_call_table - (__NR_O32_Linux * 8))(t0)
+	ld	t2, (sys32_call_table - (__NR_O32_Linux * 8))(t0)
 
 	sd	a3, PT_R26(sp)		# save a3 for syscall restarting
 
@@ -99,18 +99,7 @@ NESTED(handle_sys, PT_SIZE, sp)
 1:	sd	v0, PT_R2(sp)		# result
 
 o32_syscall_exit:
-	local_irq_disable		# make need_resched and
-					# signals dont change between
-					# sampling and return
-	LONG_L	a2, TI_FLAGS($28)
-	li	t0, _TIF_ALLWORK_MASK
-	and	t0, a2, t0
-	bnez	t0, o32_syscall_exit_work
-
-	j	restore_partial
-
-o32_syscall_exit_work:
-	j	syscall_exit_work_partial
+	j	syscall_exit_partial
 
 /* ------------------------------------------------------------------------ */
 
@@ -179,7 +168,7 @@ LEAF(sys32_syscall)
 	beqz	t0, einval		# do not recurse
 	dsll	t1, t0, 3
 	beqz	v0, einval
-	ld	t2, sys_call_table(t1)		# syscall routine
+	ld	t2, sys32_call_table(t1)		# syscall routine
 
 	move	a0, a1			# shift argument registers
 	move	a1, a2
@@ -201,8 +190,8 @@ einval:	li	v0, -ENOSYS
 	END(sys32_syscall)
 
 	.align	3
-	.type	sys_call_table,@object
-sys_call_table:
+	.type	sys32_call_table,@object
+EXPORT(sys32_call_table)
 	PTR	sys32_syscall			/* 4000 */
 	PTR	sys_exit
 	PTR	sys_fork
@@ -550,4 +539,4 @@ sys_call_table:
 	PTR	sys_setns
 	PTR	compat_sys_process_vm_readv	/* 4345 */
 	PTR	compat_sys_process_vm_writev
-	.size	sys_call_table,.-sys_call_table
+	.size	sys32_call_table,.-sys32_call_table
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c
index f2c09cf..0e1a5b8 100644
--- a/arch/mips/kernel/signal.c
+++ b/arch/mips/kernel/signal.c
@@ -560,14 +560,6 @@ static void do_signal(struct pt_regs *regs)
 	siginfo_t info;
 	int signr;
 
-	/*
-	 * We want the common case to go fast, which is why we may in certain
-	 * cases get here from kernel mode. Just return without doing anything
-	 * if so.
-	 */
-	if (!user_mode(regs))
-		return;
-
 	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
 	if (signr > 0) {
 		/* Whee!  Actually deliver the signal.  */
diff --git a/arch/mips/mipssim/Makefile b/arch/mips/mipssim/Makefile
deleted file mode 100644
index 01410a3..0000000
--- a/arch/mips/mipssim/Makefile
+++ /dev/null
@@ -1,23 +0,0 @@
-#
-# Copyright (C) 2005 MIPS Technologies, Inc.  All rights reserved.
-# Copyright (C) 2007 MIPS Technologies, Inc.
-#   written by Ralf Baechle (ralf@linux-mips.org)
-#
-# This program is free software; you can distribute 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 it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-# for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
-#
-
-obj-y := sim_platform.o sim_setup.o sim_mem.o sim_time.o sim_int.o
-
-obj-$(CONFIG_EARLY_PRINTK) += sim_console.o
-obj-$(CONFIG_MIPS_MT_SMTC) += sim_smtc.o
diff --git a/arch/mips/mipssim/Platform b/arch/mips/mipssim/Platform
deleted file mode 100644
index 3df60b8..0000000
--- a/arch/mips/mipssim/Platform
+++ /dev/null
@@ -1,6 +0,0 @@
-#
-# MIPS SIM
-#
-platform-$(CONFIG_MIPS_SIM)	+= mipssim/
-cflags-$(CONFIG_MIPS_SIM)	+= -I$(srctree)/arch/mips/include/asm/mach-mipssim
-load-$(CONFIG_MIPS_SIM)		+= 0x80100000
diff --git a/arch/mips/mipssim/sim_console.c b/arch/mips/mipssim/sim_console.c
deleted file mode 100644
index a2f4167..0000000
--- a/arch/mips/mipssim/sim_console.c
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- *  This program is free software; you can distribute 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 it will be useful, but WITHOUT
- *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- *  for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
- * Copyright (C) 2007 MIPS Technologies, Inc.
- *   written by Ralf Baechle
- */
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/serial_reg.h>
-
-static inline unsigned int serial_in(int offset)
-{
-	return inb(0x3f8 + offset);
-}
-
-static inline void serial_out(int offset, int value)
-{
-	outb(value, 0x3f8 + offset);
-}
-
-void __init prom_putchar(char c)
-{
-	while ((serial_in(UART_LSR) & UART_LSR_THRE) == 0)
-		;
-
-	serial_out(UART_TX, c);
-}
diff --git a/arch/mips/mipssim/sim_int.c b/arch/mips/mipssim/sim_int.c
deleted file mode 100644
index 5c779be..0000000
--- a/arch/mips/mipssim/sim_int.c
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 1999, 2005 MIPS Technologies, Inc.  All rights reserved.
- *
- *  This program is free software; you can distribute 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 it will be useful, but WITHOUT
- *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- *  for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- */
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/kernel_stat.h>
-#include <asm/mips-boards/simint.h>
-#include <asm/irq_cpu.h>
-
-static inline int clz(unsigned long x)
-{
-	__asm__(
-	"	.set	push					\n"
-	"	.set	mips32					\n"
-	"	clz	%0, %1					\n"
-	"	.set	pop					\n"
-	: "=r" (x)
-	: "r" (x));
-
-	return x;
-}
-
-/*
- * Version of ffs that only looks at bits 12..15.
- */
-static inline unsigned int irq_ffs(unsigned int pending)
-{
-#if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64)
-	return -clz(pending) + 31 - CAUSEB_IP;
-#else
-	unsigned int a0 = 7;
-	unsigned int t0;
-
-	t0 = s0 & 0xf000;
-	t0 = t0 < 1;
-	t0 = t0 << 2;
-	a0 = a0 - t0;
-	s0 = s0 << t0;
-
-	t0 = s0 & 0xc000;
-	t0 = t0 < 1;
-	t0 = t0 << 1;
-	a0 = a0 - t0;
-	s0 = s0 << t0;
-
-	t0 = s0 & 0x8000;
-	t0 = t0 < 1;
-	/* t0 = t0 << 2; */
-	a0 = a0 - t0;
-	/* s0 = s0 << t0; */
-
-	return a0;
-#endif
-}
-
-asmlinkage void plat_irq_dispatch(void)
-{
-	unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
-	int irq;
-
-	irq = irq_ffs(pending);
-
-	if (irq > 0)
-		do_IRQ(MIPS_CPU_IRQ_BASE + irq);
-	else
-		spurious_interrupt();
-}
-
-void __init arch_init_irq(void)
-{
-	mips_cpu_irq_init();
-}
diff --git a/arch/mips/mipssim/sim_mem.c b/arch/mips/mipssim/sim_mem.c
deleted file mode 100644
index 953d836..0000000
--- a/arch/mips/mipssim/sim_mem.c
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (C) 2005 MIPS Technologies, Inc.  All rights reserved.
- *
- *  This program is free software; you can distribute 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 it will be useful, but WITHOUT
- *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- *  for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- */
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/bootmem.h>
-#include <linux/pfn.h>
-
-#include <asm/bootinfo.h>
-#include <asm/page.h>
-#include <asm/sections.h>
-
-#include <asm/mips-boards/prom.h>
-
-/*#define DEBUG*/
-
-enum simmem_memtypes {
-	simmem_reserved = 0,
-	simmem_free,
-};
-struct prom_pmemblock mdesc[PROM_MAX_PMEMBLOCKS];
-
-#ifdef DEBUG
-static char *mtypes[3] = {
-	"SIM reserved memory",
-	"SIM free memory",
-};
-#endif
-
-struct prom_pmemblock * __init prom_getmdesc(void)
-{
-	unsigned int memsize;
-
-	memsize = 0x02000000;
-	pr_info("Setting default memory size 0x%08x\n", memsize);
-
-	memset(mdesc, 0, sizeof(mdesc));
-
-	mdesc[0].type = simmem_reserved;
-	mdesc[0].base = 0x00000000;
-	mdesc[0].size = 0x00001000;
-
-	mdesc[1].type = simmem_free;
-	mdesc[1].base = 0x00001000;
-	mdesc[1].size = 0x000ff000;
-
-	mdesc[2].type = simmem_reserved;
-	mdesc[2].base = 0x00100000;
-	mdesc[2].size = CPHYSADDR(PFN_ALIGN(&_end)) - mdesc[2].base;
-
-	mdesc[3].type = simmem_free;
-	mdesc[3].base = CPHYSADDR(PFN_ALIGN(&_end));
-	mdesc[3].size = memsize - mdesc[3].base;
-
-	return &mdesc[0];
-}
-
-static int __init prom_memtype_classify(unsigned int type)
-{
-	switch (type) {
-	case simmem_free:
-		return BOOT_MEM_RAM;
-	case simmem_reserved:
-	default:
-		return BOOT_MEM_RESERVED;
-	}
-}
-
-void __init prom_meminit(void)
-{
-	struct prom_pmemblock *p;
-
-	p = prom_getmdesc();
-
-	while (p->size) {
-		long type;
-		unsigned long base, size;
-
-		type = prom_memtype_classify(p->type);
-		base = p->base;
-		size = p->size;
-
-		add_memory_region(base, size, type);
-		p++;
-	}
-}
-
-void __init prom_free_prom_memory(void)
-{
-	int i;
-	unsigned long addr;
-
-	for (i = 0; i < boot_mem_map.nr_map; i++) {
-		if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA)
-			continue;
-
-		addr = boot_mem_map.map[i].addr;
-		free_init_pages("prom memory",
-				addr, addr + boot_mem_map.map[i].size);
-	}
-}
diff --git a/arch/mips/mipssim/sim_platform.c b/arch/mips/mipssim/sim_platform.c
deleted file mode 100644
index 53210a8..0000000
--- a/arch/mips/mipssim/sim_platform.c
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2007 by Ralf Baechle (ralf@linux-mips.org)
- */
-#include <linux/init.h>
-#include <linux/if_ether.h>
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-
-static char mipsnet_string[] = "mipsnet";
-
-static struct platform_device eth1_device = {
-	.name		= mipsnet_string,
-	.id		= 0,
-};
-
-/*
- * Create a platform device for the GPI port that receives the
- * image data from the embedded camera.
- */
-static int __init mipsnet_devinit(void)
-{
-	int err;
-
-	err = platform_device_register(&eth1_device);
-	if (err)
-		printk(KERN_ERR "%s: registration failed\n", mipsnet_string);
-
-	return err;
-}
-
-device_initcall(mipsnet_devinit);
diff --git a/arch/mips/mipssim/sim_setup.c b/arch/mips/mipssim/sim_setup.c
deleted file mode 100644
index 256e0cd..0000000
--- a/arch/mips/mipssim/sim_setup.c
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (C) 2005 MIPS Technologies, Inc.  All rights reserved.
- *
- *  This program is free software; you can distribute 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 it will be useful, but WITHOUT
- *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- *  for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- */
-
-#include <linux/init.h>
-#include <linux/string.h>
-#include <linux/kernel.h>
-#include <linux/io.h>
-#include <linux/irq.h>
-#include <linux/ioport.h>
-#include <linux/tty.h>
-#include <linux/serial.h>
-#include <linux/serial_core.h>
-#include <linux/serial_8250.h>
-
-#include <asm/cpu.h>
-#include <asm/bootinfo.h>
-#include <asm/mips-boards/generic.h>
-#include <asm/mips-boards/prom.h>
-#include <asm/time.h>
-#include <asm/mips-boards/sim.h>
-#include <asm/mips-boards/simint.h>
-#include <asm/smp-ops.h>
-
-
-static void __init serial_init(void);
-unsigned int _isbonito;
-
-const char *get_system_type(void)
-{
-	return "MIPSsim";
-}
-
-void __init plat_mem_setup(void)
-{
-	set_io_port_base(0xbfd00000);
-
-	serial_init();
-}
-
-extern struct plat_smp_ops ssmtc_smp_ops;
-
-void __init prom_init(void)
-{
-	set_io_port_base(0xbfd00000);
-
-	prom_meminit();
-
-	if (cpu_has_mipsmt) {
-		if (!register_vsmp_smp_ops())
-			return;
-
-#ifdef CONFIG_MIPS_MT_SMTC
-		register_smp_ops(&ssmtc_smp_ops);
-			return;
-#endif
-	}
-
-	register_up_smp_ops();
-}
-
-static void __init serial_init(void)
-{
-#ifdef CONFIG_SERIAL_8250
-	struct uart_port s;
-
-	memset(&s, 0, sizeof(s));
-
-	s.iobase = 0x3f8;
-
-	/* hardware int 4 - the serial int, is CPU int 6
-	 but poll for now */
-	s.irq =  0;
-	s.uartclk = 1843200;
-	s.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
-	s.iotype = UPIO_PORT;
-	s.regshift = 0;
-	s.timeout = 4;
-
-	if (early_serial_setup(&s) != 0) {
-		printk(KERN_ERR "Serial setup failed!\n");
-	}
-
-#endif
-}
diff --git a/arch/mips/mipssim/sim_smtc.c b/arch/mips/mipssim/sim_smtc.c
deleted file mode 100644
index 3c104ab..0000000
--- a/arch/mips/mipssim/sim_smtc.c
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (C) 2005 MIPS Technologies, Inc.  All rights reserved.
- *
- *  This program is free software; you can distribute 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 it will be useful, but WITHOUT
- *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- *  for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- */
-/*
- * Simulator Platform-specific hooks for SMTC operation
- */
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/cpumask.h>
-#include <linux/interrupt.h>
-#include <linux/smp.h>
-
-#include <linux/atomic.h>
-#include <asm/cpu.h>
-#include <asm/processor.h>
-#include <asm/smtc.h>
-#include <asm/mmu_context.h>
-#include <asm/smtc_ipi.h>
-
-/* VPE/SMP Prototype implements platform interfaces directly */
-
-/*
- * Cause the specified action to be performed on a targeted "CPU"
- */
-
-static void ssmtc_send_ipi_single(int cpu, unsigned int action)
-{
-	smtc_send_ipi(cpu, LINUX_SMP_IPI, action);
-	/* "CPU" may be TC of same VPE, VPE of same CPU, or different CPU */
-}
-
-static inline void ssmtc_send_ipi_mask(const struct cpumask *mask,
-				       unsigned int action)
-{
-	unsigned int i;
-
-	for_each_cpu(i, mask)
-		ssmtc_send_ipi_single(i, action);
-}
-
-/*
- * Post-config but pre-boot cleanup entry point
- */
-static void __cpuinit ssmtc_init_secondary(void)
-{
-	smtc_init_secondary();
-}
-
-/*
- * SMP initialization finalization entry point
- */
-static void __cpuinit ssmtc_smp_finish(void)
-{
-	smtc_smp_finish();
-}
-
-/*
- * Hook for after all CPUs are online
- */
-static void ssmtc_cpus_done(void)
-{
-}
-
-/*
- * Platform "CPU" startup hook
- */
-static void __cpuinit ssmtc_boot_secondary(int cpu, struct task_struct *idle)
-{
-	smtc_boot_secondary(cpu, idle);
-}
-
-static void __init ssmtc_smp_setup(void)
-{
-	if (read_c0_config3() & (1 << 2))
-		mipsmt_build_cpu_map(0);
-}
-
-/*
- * Platform SMP pre-initialization
- */
-static void ssmtc_prepare_cpus(unsigned int max_cpus)
-{
-	/*
-	 * As noted above, we can assume a single CPU for now
-	 * but it may be multithreaded.
-	 */
-
-	if (read_c0_config3() & (1 << 2)) {
-		mipsmt_prepare_cpus();
-	}
-}
-
-struct plat_smp_ops ssmtc_smp_ops = {
-	.send_ipi_single	= ssmtc_send_ipi_single,
-	.send_ipi_mask		= ssmtc_send_ipi_mask,
-	.init_secondary		= ssmtc_init_secondary,
-	.smp_finish		= ssmtc_smp_finish,
-	.cpus_done		= ssmtc_cpus_done,
-	.boot_secondary		= ssmtc_boot_secondary,
-	.smp_setup		= ssmtc_smp_setup,
-	.prepare_cpus		= ssmtc_prepare_cpus,
-};
diff --git a/arch/mips/mipssim/sim_time.c b/arch/mips/mipssim/sim_time.c
deleted file mode 100644
index 77bad3c..0000000
--- a/arch/mips/mipssim/sim_time.c
+++ /dev/null
@@ -1,117 +0,0 @@
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/kernel_stat.h>
-#include <linux/sched.h>
-#include <linux/spinlock.h>
-#include <linux/interrupt.h>
-#include <linux/mc146818rtc.h>
-#include <linux/smp.h>
-#include <linux/timex.h>
-
-#include <asm/hardirq.h>
-#include <asm/div64.h>
-#include <asm/cpu.h>
-#include <asm/setup.h>
-#include <asm/time.h>
-#include <asm/irq.h>
-#include <asm/mc146818-time.h>
-#include <asm/msc01_ic.h>
-
-#include <asm/mips-boards/generic.h>
-#include <asm/mips-boards/prom.h>
-#include <asm/mips-boards/simint.h>
-
-
-unsigned long cpu_khz;
-
-/*
- * Estimate CPU frequency.  Sets mips_hpt_frequency as a side-effect
- */
-static unsigned int __init estimate_cpu_frequency(void)
-{
-	unsigned int prid = read_c0_prid() & 0xffff00;
-	unsigned int count;
-
-#if 1
-	/*
-	 * hardwire the board frequency to 12MHz.
-	 */
-
-	if ((prid == (PRID_COMP_MIPS | PRID_IMP_20KC)) ||
-	    (prid == (PRID_COMP_MIPS | PRID_IMP_25KF)))
-		count = 12000000;
-	else
-		count =  6000000;
-#else
-	unsigned int flags;
-
-	local_irq_save(flags);
-
-	/* Start counter exactly on falling edge of update flag */
-	while (CMOS_READ(RTC_REG_A) & RTC_UIP);
-	while (!(CMOS_READ(RTC_REG_A) & RTC_UIP));
-
-	/* Start r4k counter. */
-	write_c0_count(0);
-
-	/* Read counter exactly on falling edge of update flag */
-	while (CMOS_READ(RTC_REG_A) & RTC_UIP);
-	while (!(CMOS_READ(RTC_REG_A) & RTC_UIP));
-
-	count = read_c0_count();
-
-	/* restore interrupts */
-	local_irq_restore(flags);
-#endif
-
-	mips_hpt_frequency = count;
-
-	if ((prid != (PRID_COMP_MIPS | PRID_IMP_20KC)) &&
-	    (prid != (PRID_COMP_MIPS | PRID_IMP_25KF)))
-		count *= 2;
-
-	count += 5000;    /* round */
-	count -= count%10000;
-
-	return count;
-}
-
-static int mips_cpu_timer_irq;
-
-static void mips_timer_dispatch(void)
-{
-	do_IRQ(mips_cpu_timer_irq);
-}
-
-
-unsigned __cpuinit get_c0_compare_int(void)
-{
-#ifdef MSC01E_INT_BASE
-	if (cpu_has_veic) {
-		set_vi_handler(MSC01E_INT_CPUCTR, mips_timer_dispatch);
-		mips_cpu_timer_irq = MSC01E_INT_BASE + MSC01E_INT_CPUCTR;
-
-		return mips_cpu_timer_irq;
-	}
-#endif
-	if (cpu_has_vint)
-		set_vi_handler(cp0_compare_irq, mips_timer_dispatch);
-	mips_cpu_timer_irq = MIPS_CPU_IRQ_BASE + cp0_compare_irq;
-
-	return mips_cpu_timer_irq;
-}
-
-void __init plat_time_init(void)
-{
-	unsigned int est_freq;
-
-	/* Set Data mode - binary. */
-	CMOS_WRITE(CMOS_READ(RTC_CONTROL) | RTC_DM_BINARY, RTC_CONTROL);
-
-	est_freq = estimate_cpu_frequency();
-
-	printk(KERN_INFO "CPU frequency %d.%02d MHz\n", est_freq / 1000000,
-	       (est_freq % 1000000) * 100 / 1000000);
-
-	cpu_khz = est_freq / 1000;
-}
diff --git a/arch/mips/mm/fault.c b/arch/mips/mm/fault.c
index c14f6df..9f51348 100644
--- a/arch/mips/mm/fault.c
+++ b/arch/mips/mm/fault.c
@@ -171,6 +171,7 @@ good_area:
 		}
 		if (fault & VM_FAULT_RETRY) {
 			flags &= ~FAULT_FLAG_ALLOW_RETRY;
+			flags |= FAULT_FLAG_TRIED;
 
 			/*
 			 * No need to up_read(&mm->mmap_sem) as we would
diff --git a/arch/mips/pci/pci-octeon.c b/arch/mips/pci/pci-octeon.c
index 52a1ba7..4b0c347 100644
--- a/arch/mips/pci/pci-octeon.c
+++ b/arch/mips/pci/pci-octeon.c
@@ -58,7 +58,7 @@ union octeon_pci_address {
 	} s;
 };
 
-int __initdata (*octeon_pcibios_map_irq)(const struct pci_dev *dev,
+int __initconst (*octeon_pcibios_map_irq)(const struct pci_dev *dev,
 					 u8 slot, u8 pin);
 enum octeon_dma_bar_type octeon_dma_bar_type = OCTEON_DMA_BAR_TYPE_INVALID;
 
@@ -117,16 +117,11 @@ int pcibios_plat_dev_init(struct pci_dev *dev)
 	}
 
 	/* Enable the PCIe normal error reporting */
-	pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
-	if (pos) {
-		/* Update Device Control */
-		pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &config);
-		config |= PCI_EXP_DEVCTL_CERE; /* Correctable Error Reporting */
-		config |= PCI_EXP_DEVCTL_NFERE; /* Non-Fatal Error Reporting */
-		config |= PCI_EXP_DEVCTL_FERE;  /* Fatal Error Reporting */
-		config |= PCI_EXP_DEVCTL_URRE;  /* Unsupported Request */
-		pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, config);
-	}
+	config = PCI_EXP_DEVCTL_CERE; /* Correctable Error Reporting */
+	config |= PCI_EXP_DEVCTL_NFERE; /* Non-Fatal Error Reporting */
+	config |= PCI_EXP_DEVCTL_FERE;  /* Fatal Error Reporting */
+	config |= PCI_EXP_DEVCTL_URRE;  /* Unsupported Request */
+	pcie_capability_set_word(dev, PCI_EXP_DEVCTL, config);
 
 	/* Find the Advanced Error Reporting capability */
 	pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
diff --git a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c
index 6903568..04e35bc 100644
--- a/arch/mips/pci/pci.c
+++ b/arch/mips/pci/pci.c
@@ -313,12 +313,6 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus)
 	}
 }
 
-void __init
-pcibios_update_irq(struct pci_dev *dev, int irq)
-{
-	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
-}
-
 #ifdef CONFIG_HOTPLUG
 EXPORT_SYMBOL(PCIBIOS_MIN_IO);
 EXPORT_SYMBOL(PCIBIOS_MIN_MEM);
diff --git a/arch/mips/sni/a20r.c b/arch/mips/sni/a20r.c
index c48194c..b2d4f49 100644
--- a/arch/mips/sni/a20r.c
+++ b/arch/mips/sni/a20r.c
@@ -133,6 +133,38 @@ static struct platform_device sc26xx_pdev = {
 	}
 };
 
+#warning "Please try migrate to use new driver SCCNXP and report the status" \
+	 "in the linux-serial mailing list."
+
+/* The code bellow is a replacement of SC26XX to SCCNXP */
+#if 0
+#include <linux/platform_data/sccnxp.h>
+
+static struct sccnxp_pdata sccnxp_data = {
+	.reg_shift	= 2,
+	.frequency	= 3686400,
+	.mctrl_cfg[0]	= MCTRL_SIG(DTR_OP, LINE_OP7) |
+			  MCTRL_SIG(RTS_OP, LINE_OP3) |
+			  MCTRL_SIG(DSR_IP, LINE_IP5) |
+			  MCTRL_SIG(DCD_IP, LINE_IP6),
+	.mctrl_cfg[1]	= MCTRL_SIG(DTR_OP, LINE_OP2) |
+			  MCTRL_SIG(RTS_OP, LINE_OP1) |
+			  MCTRL_SIG(DSR_IP, LINE_IP0) |
+			  MCTRL_SIG(CTS_IP, LINE_IP1) |
+			  MCTRL_SIG(DCD_IP, LINE_IP2) |
+			  MCTRL_SIG(RNG_IP, LINE_IP3),
+};
+
+static struct platform_device sc2681_pdev = {
+	.name		= "sc2681",
+	.resource	= sc2xxx_rsrc,
+	.num_resources	= ARRAY_SIZE(sc2xxx_rsrc),
+	.dev	= {
+		.platform_data	= &sccnxp_data,
+	},
+};
+#endif
+
 static u32 a20r_ack_hwint(void)
 {
 	u32 status = read_c0_status();
diff --git a/arch/mn10300/Kconfig b/arch/mn10300/Kconfig
index 5cfb086..549b9e50 100644
--- a/arch/mn10300/Kconfig
+++ b/arch/mn10300/Kconfig
@@ -8,6 +8,8 @@ config MN10300
 	select HAVE_ARCH_KGDB
 	select HAVE_NMI_WATCHDOG if MN10300_WD_TIMER
 	select GENERIC_CLOCKEVENTS
+	select MODULES_USE_ELF_RELA
+	select GENERIC_KERNEL_THREAD
 
 config AM33_2
 	def_bool n
diff --git a/arch/mn10300/Makefile b/arch/mn10300/Makefile
index 33188b6..a3d0fef 100644
--- a/arch/mn10300/Makefile
+++ b/arch/mn10300/Makefile
@@ -26,7 +26,7 @@ CHECKFLAGS	+=
 PROCESSOR	:= unset
 UNIT		:= unset
 
-KBUILD_CFLAGS	+= -mam33 -mmem-funcs -DCPU=AM33
+KBUILD_CFLAGS	+= -mam33 -DCPU=AM33 $(call cc-option,-mmem-funcs,)
 KBUILD_AFLAGS	+= -mam33 -DCPU=AM33
 
 ifeq ($(CONFIG_MN10300_CURRENT_IN_E2),y)
diff --git a/arch/mn10300/include/asm/Kbuild b/arch/mn10300/include/asm/Kbuild
index c68e168..7083403 100644
--- a/arch/mn10300/include/asm/Kbuild
+++ b/arch/mn10300/include/asm/Kbuild
@@ -1 +1,3 @@
 include include/asm-generic/Kbuild.asm
+
+generic-y += exec.h
diff --git a/arch/mn10300/include/asm/elf.h b/arch/mn10300/include/asm/elf.h
index 8157c92..4ebd6b3 100644
--- a/arch/mn10300/include/asm/elf.h
+++ b/arch/mn10300/include/asm/elf.h
@@ -151,7 +151,8 @@ do {						\
 #define ELF_PLATFORM  (NULL)
 
 #ifdef __KERNEL__
-#define SET_PERSONALITY(ex) set_personality(PER_LINUX)
+#define SET_PERSONALITY(ex) \
+	set_personality(PER_LINUX | (current->personality & (~PER_MASK)))
 #endif
 
 #endif /* _ASM_ELF_H */
diff --git a/arch/mn10300/include/asm/exec.h b/arch/mn10300/include/asm/exec.h
deleted file mode 100644
index c74e367..0000000
--- a/arch/mn10300/include/asm/exec.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/* MN10300 process execution definitions
- *
- * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@redhat.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public Licence
- * as published by the Free Software Foundation; either version
- * 2 of the Licence, or (at your option) any later version.
- */
-#ifndef _ASM_EXEC_H
-#define _ASM_EXEC_H
-
-#define arch_align_stack(x) (x)
-
-#endif /* _ASM_EXEC_H */
diff --git a/arch/mn10300/include/asm/frame.inc b/arch/mn10300/include/asm/frame.inc
index 2ee58e3..1c3eb4f 100644
--- a/arch/mn10300/include/asm/frame.inc
+++ b/arch/mn10300/include/asm/frame.inc
@@ -61,7 +61,7 @@
 ###############################################################################
 .macro RESTORE_ALL
 	# peel back the stack to the calling frame
-	# - this permits execve() to discard extra frames due to kernel syscalls
+	# - we need that when returning from interrupts to kernel mode
 	GET_THREAD_INFO a0
 	mov	(TI_frame,a0),fp
 	mov	fp,sp
diff --git a/arch/mn10300/include/asm/module.h b/arch/mn10300/include/asm/module.h
index 5d7057d..6571103 100644
--- a/arch/mn10300/include/asm/module.h
+++ b/arch/mn10300/include/asm/module.h
@@ -12,12 +12,7 @@
 #ifndef _ASM_MODULE_H
 #define _ASM_MODULE_H
 
-struct mod_arch_specific {
-};
-
-#define Elf_Shdr	Elf32_Shdr
-#define Elf_Sym		Elf32_Sym
-#define Elf_Ehdr	Elf32_Ehdr
+#include <asm-generic/module.h>
 
 /*
  * Include the MN10300 architecture version.
diff --git a/arch/mn10300/include/asm/processor.h b/arch/mn10300/include/asm/processor.h
index 247928c..8b80b19 100644
--- a/arch/mn10300/include/asm/processor.h
+++ b/arch/mn10300/include/asm/processor.h
@@ -119,20 +119,13 @@ struct thread_struct {
 
 /*
  * do necessary setup to start up a newly executed thread
- * - need to discard the frame stacked by the kernel thread invoking the execve
- *   syscall (see RESTORE_ALL macro)
  */
 static inline void start_thread(struct pt_regs *regs,
 				unsigned long new_pc, unsigned long new_sp)
 {
-	struct thread_info *ti = current_thread_info();
-	struct pt_regs *frame0;
-
-	frame0 = thread_info_to_uregs(ti);
-	frame0->epsw = EPSW_nSL | EPSW_IE | EPSW_IM;
-	frame0->pc = new_pc;
-	frame0->sp = new_sp;
-	ti->frame = frame0;
+	regs->epsw = EPSW_nSL | EPSW_IE | EPSW_IM;
+	regs->pc = new_pc;
+	regs->sp = new_sp;
 }
 
 
@@ -140,11 +133,6 @@ static inline void start_thread(struct pt_regs *regs,
 extern void release_thread(struct task_struct *);
 
 /*
- * create a kernel thread without removing it from tasklists
- */
-extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
-
-/*
  * Return saved PC of a blocked thread.
  */
 extern unsigned long thread_saved_pc(struct task_struct *tsk);
diff --git a/arch/mn10300/include/asm/ptrace.h b/arch/mn10300/include/asm/ptrace.h
index 44251b9..08ac856 100644
--- a/arch/mn10300/include/asm/ptrace.h
+++ b/arch/mn10300/include/asm/ptrace.h
@@ -86,6 +86,7 @@ struct pt_regs {
 #define user_mode(regs)			(((regs)->epsw & EPSW_nSL) == EPSW_nSL)
 #define instruction_pointer(regs)	((regs)->pc)
 #define user_stack_pointer(regs)	((regs)->sp)
+#define current_pt_regs()		current_frame()
 
 #define arch_has_single_step()	(1)
 
diff --git a/arch/mn10300/include/asm/thread_info.h b/arch/mn10300/include/asm/thread_info.h
index ac519bb..f90062b 100644
--- a/arch/mn10300/include/asm/thread_info.h
+++ b/arch/mn10300/include/asm/thread_info.h
@@ -160,12 +160,13 @@ void arch_release_thread_info(struct thread_info *ti);
 #define _TIF_SIGPENDING		+(1 << TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	+(1 << TIF_NEED_RESCHED)
 #define _TIF_SINGLESTEP		+(1 << TIF_SINGLESTEP)
-#define _TIF_RESTORE_SIGMASK	+(1 << TIF_RESTORE_SIGMASK)
 #define _TIF_POLLING_NRFLAG	+(1 << TIF_POLLING_NRFLAG)
 
 #define _TIF_WORK_MASK		0x0000FFFE	/* work to do on interrupt/exception return */
 #define _TIF_ALLWORK_MASK	0x0000FFFF	/* work to do on any return to u-space */
 
+#define tsk_is_polling(t) test_tsk_thread_flag(t, TIF_POLLING_NRFLAG)
+
 #endif /* __KERNEL__ */
 
 #endif /* _ASM_THREAD_INFO_H */
diff --git a/arch/mn10300/include/asm/unistd.h b/arch/mn10300/include/asm/unistd.h
index 866eb14..044c770 100644
--- a/arch/mn10300/include/asm/unistd.h
+++ b/arch/mn10300/include/asm/unistd.h
@@ -382,6 +382,8 @@
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_RT_SIGACTION
 #define __ARCH_WANT_SYS_RT_SIGSUSPEND
+#define __ARCH_WANT_SYS_EXECVE
+#define __ARCH_WANT_KERNEL_EXECVE
 
 /*
  * "Conditional" syscalls
diff --git a/arch/mn10300/kernel/Makefile b/arch/mn10300/kernel/Makefile
index d067491..561029f 100644
--- a/arch/mn10300/kernel/Makefile
+++ b/arch/mn10300/kernel/Makefile
@@ -7,8 +7,8 @@ fpu-obj-y := fpu-nofpu.o fpu-nofpu-low.o
 fpu-obj-$(CONFIG_FPU) := fpu.o fpu-low.o
 
 obj-y   := process.o signal.o entry.o traps.o irq.o \
-	   ptrace.o setup.o time.o sys_mn10300.o io.o kthread.o \
-	   switch_to.o mn10300_ksyms.o kernel_execve.o $(fpu-obj-y) \
+	   ptrace.o setup.o time.o sys_mn10300.o io.o \
+	   switch_to.o mn10300_ksyms.o $(fpu-obj-y) \
 	   csrc-mn10300.o cevt-mn10300.o
 
 obj-$(CONFIG_SMP) += smp.o smp-low.o
diff --git a/arch/mn10300/kernel/entry.S b/arch/mn10300/kernel/entry.S
index 8e11f9f..0c631d3 100644
--- a/arch/mn10300/kernel/entry.S
+++ b/arch/mn10300/kernel/entry.S
@@ -55,6 +55,20 @@ ENTRY(ret_from_fork)
 	mov	d0,(REG_D0,fp)
 	jmp	syscall_exit
 
+ENTRY(ret_from_kernel_thread)
+	call	schedule_tail[],0
+	mov	(REG_D0,fp),d0
+	mov	(REG_A0,fp),a0
+	calls	(a0)
+	jmp	sys_exit
+
+ENTRY(ret_from_kernel_execve)
+	add	-12,d0	/* pt_regs -> frame */
+	mov	d0,sp
+	GET_THREAD_INFO a2
+	clr	d0
+	jmp	syscall_exit
+
 ###############################################################################
 #
 # system call handler
@@ -94,6 +108,10 @@ restore_all:
 ###############################################################################
 	ALIGN
 syscall_exit_work:
+	mov	(REG_EPSW,fp),d0
+	and	EPSW_nSL,d0
+	beq	resume_kernel		# returning to supervisor mode
+
 	btst	_TIF_SYSCALL_TRACE,d2
 	beq	work_pending
 	LOCAL_IRQ_ENABLE		# could let syscall_trace_exit() call
diff --git a/arch/mn10300/kernel/internal.h b/arch/mn10300/kernel/internal.h
index 2df4401..5617855 100644
--- a/arch/mn10300/kernel/internal.h
+++ b/arch/mn10300/kernel/internal.h
@@ -15,14 +15,10 @@ struct clocksource;
 struct clock_event_device;
 
 /*
- * kthread.S
- */
-extern int kernel_thread_helper(int);
-
-/*
  * entry.S
  */
 extern void ret_from_fork(struct task_struct *) __attribute__((noreturn));
+extern void ret_from_kernel_thread(struct task_struct *) __attribute__((noreturn));
 
 /*
  * smp-low.S
diff --git a/arch/mn10300/kernel/kernel_execve.S b/arch/mn10300/kernel/kernel_execve.S
deleted file mode 100644
index 86039f1..0000000
--- a/arch/mn10300/kernel/kernel_execve.S
+++ /dev/null
@@ -1,37 +0,0 @@
-/* MN10300 In-kernel program execution
- *
- * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@redhat.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public Licence
- * as published by the Free Software Foundation; either version
- * 2 of the Licence, or (at your option) any later version.
- */
-#include <linux/linkage.h>
-#include <asm/unistd.h>
-
-###############################################################################
-#
-# Do a system call from kernel instead of calling sys_execve so we end up with
-# proper pt_regs.
-#
-# int kernel_execve(const char *filename, char *const argv[],
-#		    char *const envp[])
-#
-# On entry: D0/D1/8(SP): arguments to function
-# On return: D0: syscall return.
-#
-###############################################################################
-	.globl		kernel_execve
-	.type		kernel_execve,@function
-kernel_execve:
-	mov		a3,a1
-	mov		d0,a0
-	mov		(12,sp),a3
-	mov		+__NR_execve,d0
-	syscall		0
-	mov		a1,a3
-	rets
-
-	.size		kernel_execve,.-kernel_execve
diff --git a/arch/mn10300/kernel/kthread.S b/arch/mn10300/kernel/kthread.S
deleted file mode 100644
index b5ae467..0000000
--- a/arch/mn10300/kernel/kthread.S
+++ /dev/null
@@ -1,31 +0,0 @@
-/* MN10300 Kernel thread trampoline function
- *
- * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
- * Written by Mark Salter (msalter@redhat.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public Licence
- * as published by the Free Software Foundation; either version
- * 2 of the Licence, or (at your option) any later version.
- */
-	.text
-
-###############################################################################
-#
-# kernel_thread_helper - trampoline for kernel_thread()
-#
-# On entry:
-#   A2 = address of function to call
-#   D2 = function argument
-#
-###############################################################################
-	.globl	kernel_thread_helper
-	.type	kernel_thread_helper,@function
-kernel_thread_helper:
-	mov	do_exit,d1
-	mov	d1,(sp)
-	mov	d1,mdr
-	mov	d2,d0
-	jmp	(a2)
-
-	.size	kernel_thread_helper,.-kernel_thread_helper
diff --git a/arch/mn10300/kernel/process.c b/arch/mn10300/kernel/process.c
index 7dab0cd..f8f19e4 100644
--- a/arch/mn10300/kernel/process.c
+++ b/arch/mn10300/kernel/process.c
@@ -25,6 +25,7 @@
 #include <linux/err.h>
 #include <linux/fs.h>
 #include <linux/slab.h>
+#include <linux/rcupdate.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/io.h>
@@ -107,6 +108,7 @@ void cpu_idle(void)
 {
 	/* endless idle loop with no priority at all */
 	for (;;) {
+		rcu_idle_enter();
 		while (!need_resched()) {
 			void (*idle)(void);
 
@@ -121,6 +123,7 @@ void cpu_idle(void)
 			}
 			idle();
 		}
+		rcu_idle_exit();
 
 		schedule_preempt_disabled();
 	}
@@ -162,27 +165,6 @@ void show_regs(struct pt_regs *regs)
 }
 
 /*
- * create a kernel thread
- */
-int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
-{
-	struct pt_regs regs;
-
-	memset(&regs, 0, sizeof(regs));
-
-	regs.a2 = (unsigned long) fn;
-	regs.d2 = (unsigned long) arg;
-	regs.pc = (unsigned long) kernel_thread_helper;
-	local_save_flags(regs.epsw);
-	regs.epsw |= EPSW_IE | EPSW_IM_7;
-
-	/* Ok, create the new process.. */
-	return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0,
-		       NULL, NULL);
-}
-EXPORT_SYMBOL(kernel_thread);
-
-/*
  * free current thread data structures etc..
  */
 void exit_thread(void)
@@ -227,50 +209,42 @@ int copy_thread(unsigned long clone_flags,
 		struct task_struct *p, struct pt_regs *kregs)
 {
 	struct thread_info *ti = task_thread_info(p);
-	struct pt_regs *c_uregs, *c_kregs, *uregs;
+	struct pt_regs *c_regs;
 	unsigned long c_ksp;
 
-	uregs = current->thread.uregs;
-
 	c_ksp = (unsigned long) task_stack_page(p) + THREAD_SIZE;
 
 	/* allocate the userspace exception frame and set it up */
 	c_ksp -= sizeof(struct pt_regs);
-	c_uregs = (struct pt_regs *) c_ksp;
+	c_regs = (struct pt_regs *) c_ksp;
+	c_ksp -= 12; /* allocate function call ABI slack */
 
-	p->thread.uregs = c_uregs;
-	*c_uregs = *uregs;
-	c_uregs->sp = c_usp;
-	c_uregs->epsw &= ~EPSW_FE; /* my FPU */
+	/* set up things up so the scheduler can start the new task */
+	p->thread.uregs = c_regs;
+	ti->frame	= c_regs;
+	p->thread.a3	= (unsigned long) c_regs;
+	p->thread.sp	= c_ksp;
+	p->thread.wchan	= p->thread.pc;
+	p->thread.usp	= c_usp;
 
-	c_ksp -= 12; /* allocate function call ABI slack */
+	if (unlikely(!kregs)) {
+		memset(c_regs, 0, sizeof(struct pt_regs);
+		c_regs->a0 = c_usp; /* function */
+		c_regs->d0 = ustk_size; /* argument */
+		local_save_flags(c_regs->epsw);
+		c_regs->epsw |= EPSW_IE | EPSW_IM_7;
+		p->thread.pc	= (unsigned long) ret_from_kernel_thread;
+		return 0;
+	}
+	*c_regs = *kregs;
+	c_regs->sp = c_usp;
+	c_regs->epsw &= ~EPSW_FE; /* my FPU */
 
 	/* the new TLS pointer is passed in as arg #5 to sys_clone() */
 	if (clone_flags & CLONE_SETTLS)
-		c_uregs->e2 = current_frame()->d3;
-
-	/* set up the return kernel frame if called from kernel_thread() */
-	c_kregs = c_uregs;
-	if (kregs != uregs) {
-		c_ksp -= sizeof(struct pt_regs);
-		c_kregs = (struct pt_regs *) c_ksp;
-		*c_kregs = *kregs;
-		c_kregs->sp = c_usp;
-		c_kregs->next = c_uregs;
-#ifdef CONFIG_MN10300_CURRENT_IN_E2
-		c_kregs->e2 = (unsigned long) p; /* current */
-#endif
-
-		c_ksp -= 12; /* allocate function call ABI slack */
-	}
+		c_regs->e2 = current_frame()->d3;
 
-	/* set up things up so the scheduler can start the new task */
-	ti->frame	= c_kregs;
-	p->thread.a3	= (unsigned long) c_kregs;
-	p->thread.sp	= c_ksp;
 	p->thread.pc	= (unsigned long) ret_from_fork;
-	p->thread.wchan	= (unsigned long) ret_from_fork;
-	p->thread.usp	= c_usp;
 
 	return 0;
 }
@@ -299,22 +273,6 @@ asmlinkage long sys_vfork(void)
 		       current_frame(), 0, NULL, NULL);
 }
 
-asmlinkage long sys_execve(const char __user *name,
-			   const char __user *const __user *argv,
-			   const char __user *const __user *envp)
-{
-	char *filename;
-	int error;
-
-	filename = getname(name);
-	error = PTR_ERR(filename);
-	if (IS_ERR(filename))
-		return error;
-	error = do_execve(filename, argv, envp, current_frame());
-	putname(filename);
-	return error;
-}
-
 unsigned long get_wchan(struct task_struct *p)
 {
 	return p->thread.wchan;
diff --git a/arch/mn10300/kernel/signal.c b/arch/mn10300/kernel/signal.c
index 4d584ae..f570b30 100644
--- a/arch/mn10300/kernel/signal.c
+++ b/arch/mn10300/kernel/signal.c
@@ -317,10 +317,6 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
 	regs->d0 = sig;
 	regs->d1 = (unsigned long) &frame->sc;
 
-	/* the tracer may want to single-step inside the handler */
-	if (test_thread_flag(TIF_SINGLESTEP))
-		ptrace_notify(SIGTRAP);
-
 #if DEBUG_SIG
 	printk(KERN_DEBUG "SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n",
 	       sig, current->comm, current->pid, frame, regs->pc,
@@ -398,10 +394,6 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 	regs->d0 = sig;
 	regs->d1 = (long) &frame->info;
 
-	/* the tracer may want to single-step inside the handler */
-	if (test_thread_flag(TIF_SINGLESTEP))
-		ptrace_notify(SIGTRAP);
-
 #if DEBUG_SIG
 	printk(KERN_DEBUG "SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n",
 	       sig, current->comm, current->pid, frame, regs->pc,
@@ -475,11 +467,6 @@ static void do_signal(struct pt_regs *regs)
 	siginfo_t info;
 	int signr;
 
-	/* we want the common case to go fast, which is why we may in certain
-	 * cases get here from kernel mode */
-	if (!user_mode(regs))
-		return;
-
 	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
 	if (signr > 0) {
 		if (handle_signal(signr, &info, &ka, regs) == 0) {
diff --git a/arch/openrisc/Kconfig b/arch/openrisc/Kconfig
index 49765b5..05f2ba4 100644
--- a/arch/openrisc/Kconfig
+++ b/arch/openrisc/Kconfig
@@ -21,6 +21,7 @@ config OPENRISC
 	select GENERIC_CLOCKEVENTS
 	select GENERIC_STRNCPY_FROM_USER
 	select GENERIC_STRNLEN_USER
+	select MODULES_USE_ELF_RELA
 
 config MMU
 	def_bool y
diff --git a/arch/openrisc/include/asm/elf.h b/arch/openrisc/include/asm/elf.h
index a8fe2c5..225a7ff 100644
--- a/arch/openrisc/include/asm/elf.h
+++ b/arch/openrisc/include/asm/elf.h
@@ -110,7 +110,8 @@ extern void dump_elf_thread(elf_greg_t *dest, struct pt_regs *pt);
 
 #define ELF_PLATFORM	(NULL)
 
-#define SET_PERSONALITY(ex) set_personality(PER_LINUX)
+#define SET_PERSONALITY(ex) \
+	set_personality(PER_LINUX | (current->personality & (~PER_MASK)))
 
 #endif /* __KERNEL__ */
 #endif
diff --git a/arch/openrisc/include/asm/processor.h b/arch/openrisc/include/asm/processor.h
index 30462f1..43decdb 100644
--- a/arch/openrisc/include/asm/processor.h
+++ b/arch/openrisc/include/asm/processor.h
@@ -103,7 +103,7 @@ extern unsigned long thread_saved_pc(struct task_struct *t);
 
 #define init_stack      (init_thread_union.stack)
 
-#define cpu_relax()     do { } while (0)
+#define cpu_relax()     barrier()
 
 #endif /* __ASSEMBLY__ */
 #endif /* __ASM_OPENRISC_PROCESSOR_H */
diff --git a/arch/openrisc/include/asm/thread_info.h b/arch/openrisc/include/asm/thread_info.h
index 07a8bc0..07f3212 100644
--- a/arch/openrisc/include/asm/thread_info.h
+++ b/arch/openrisc/include/asm/thread_info.h
@@ -121,7 +121,6 @@ register struct thread_info *current_thread_info_reg asm("r10");
 #define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
 #define _TIF_SINGLESTEP		(1<<TIF_SINGLESTEP)
-#define _TIF_RESTORE_SIGMASK     (1<<TIF_RESTORE_SIGMASK)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
 
 
@@ -129,6 +128,8 @@ register struct thread_info *current_thread_info_reg asm("r10");
 /* For OpenRISC, this is anything in the LSW other than syscall trace */
 #define _TIF_WORK_MASK (0xff & ~(_TIF_SYSCALL_TRACE|_TIF_SINGLESTEP))
 
+#define tsk_is_polling(t) test_tsk_thread_flag(t, TIF_POLLING_NRFLAG)
+
 #endif /* __KERNEL__ */
 
 #endif /* _ASM_THREAD_INFO_H */
diff --git a/arch/openrisc/kernel/irq.c b/arch/openrisc/kernel/irq.c
index e935b9d..8ec77bc 100644
--- a/arch/openrisc/kernel/irq.c
+++ b/arch/openrisc/kernel/irq.c
@@ -46,19 +46,19 @@ EXPORT_SYMBOL(arch_local_irq_restore);
 
 static void or1k_pic_mask(struct irq_data *data)
 {
-	mtspr(SPR_PICMR, mfspr(SPR_PICMR) & ~(1UL << data->irq));
+	mtspr(SPR_PICMR, mfspr(SPR_PICMR) & ~(1UL << data->hwirq));
 }
 
 static void or1k_pic_unmask(struct irq_data *data)
 {
-	mtspr(SPR_PICMR, mfspr(SPR_PICMR) | (1UL << data->irq));
+	mtspr(SPR_PICMR, mfspr(SPR_PICMR) | (1UL << data->hwirq));
 }
 
 static void or1k_pic_ack(struct irq_data *data)
 {
 	/* EDGE-triggered interrupts need to be ack'ed in order to clear
 	 * the latch.
-	 * LEVER-triggered interrupts do not need to be ack'ed; however,
+	 * LEVEL-triggered interrupts do not need to be ack'ed; however,
 	 * ack'ing the interrupt has no ill-effect and is quicker than
 	 * trying to figure out what type it is...
 	 */
@@ -75,10 +75,10 @@ static void or1k_pic_ack(struct irq_data *data)
 	 *     as opposed to a 1 as mandated by the spec
 	 */
 
-	mtspr(SPR_PICSR, mfspr(SPR_PICSR) & ~(1UL << data->irq));
+	mtspr(SPR_PICSR, mfspr(SPR_PICSR) & ~(1UL << data->hwirq));
 #else
-	WARN(1, "Interrupt handling possibily broken\n");
-	mtspr(SPR_PICSR, (1UL << irq));
+	WARN(1, "Interrupt handling possibly broken\n");
+	mtspr(SPR_PICSR, (1UL << data->hwirq));
 #endif
 }
 
@@ -87,10 +87,12 @@ static void or1k_pic_mask_ack(struct irq_data *data)
 	/* Comments for pic_ack apply here, too */
 
 #ifdef CONFIG_OR1K_1200
-	mtspr(SPR_PICSR, mfspr(SPR_PICSR) & ~(1UL << data->irq));
+	mtspr(SPR_PICMR, mfspr(SPR_PICMR) & ~(1UL << data->hwirq));
+	mtspr(SPR_PICSR, mfspr(SPR_PICSR) & ~(1UL << data->hwirq));
 #else
-	WARN(1, "Interrupt handling possibily broken\n");
-	mtspr(SPR_PICSR, (1UL << irq));
+	WARN(1, "Interrupt handling possibly broken\n");
+	mtspr(SPR_PICMR, (1UL << data->hwirq));
+	mtspr(SPR_PICSR, (1UL << data->hwirq));
 #endif
 }
 
diff --git a/arch/openrisc/kernel/ptrace.c b/arch/openrisc/kernel/ptrace.c
index e71781d..71a2a0c 100644
--- a/arch/openrisc/kernel/ptrace.c
+++ b/arch/openrisc/kernel/ptrace.c
@@ -187,7 +187,7 @@ asmlinkage long do_syscall_trace_enter(struct pt_regs *regs)
 		 */
 		ret = -1L;
 
-	audit_syscall_entry(audit_arch(), regs->gpr[11],
+	audit_syscall_entry(AUDIT_ARCH_OPENRISC, regs->gpr[11],
 			    regs->gpr[3], regs->gpr[4],
 			    regs->gpr[5], regs->gpr[6]);
 
diff --git a/arch/openrisc/lib/delay.c b/arch/openrisc/lib/delay.c
index 01d9740..c330767 100644
--- a/arch/openrisc/lib/delay.c
+++ b/arch/openrisc/lib/delay.c
@@ -30,9 +30,9 @@ int __devinit read_current_timer(unsigned long *timer_value)
 
 void __delay(unsigned long cycles)
 {
-	cycles_t target = get_cycles() + cycles;
+	cycles_t start = get_cycles();
 
-	while (get_cycles() < target)
+	while ((get_cycles() - start) < cycles)
 		cpu_relax();
 }
 EXPORT_SYMBOL(__delay);
@@ -41,7 +41,7 @@ inline void __const_udelay(unsigned long xloops)
 {
 	unsigned long long loops;
 
-	loops = xloops * loops_per_jiffy * HZ;
+	loops = (unsigned long long)xloops * loops_per_jiffy * HZ;
 
 	__delay(loops >> 32);
 }
diff --git a/arch/openrisc/mm/fault.c b/arch/openrisc/mm/fault.c
index 40f850e..e2bfafc 100644
--- a/arch/openrisc/mm/fault.c
+++ b/arch/openrisc/mm/fault.c
@@ -183,6 +183,7 @@ good_area:
 			tsk->min_flt++;
 		if (fault & VM_FAULT_RETRY) {
 			flags &= ~FAULT_FLAG_ALLOW_RETRY;
+			flags |= FAULT_FLAG_TRIED;
 
 			 /* No need to up_read(&mm->mmap_sem) as we would
 			 * have already released it in __lock_page_or_retry
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
index 3ff21b5..11def45 100644
--- a/arch/parisc/Kconfig
+++ b/arch/parisc/Kconfig
@@ -13,12 +13,15 @@ config PARISC
 	select HAVE_PERF_EVENTS
 	select GENERIC_ATOMIC64 if !64BIT
 	select HAVE_GENERIC_HARDIRQS
+	select BROKEN_RODATA
 	select GENERIC_IRQ_PROBE
 	select GENERIC_PCI_IOMAP
 	select IRQ_PER_CPU
 	select ARCH_HAVE_NMI_SAFE_CMPXCHG
 	select GENERIC_SMP_IDLE_THREAD
 	select GENERIC_STRNCPY_FROM_USER
+	select HAVE_MOD_ARCH_SPECIFIC
+	select MODULES_USE_ELF_RELA
 
 	help
 	  The PA-RISC microprocessor is designed by Hewlett-Packard and used
diff --git a/arch/parisc/hpux/fs.c b/arch/parisc/hpux/fs.c
index c71eb6c..6785de7 100644
--- a/arch/parisc/hpux/fs.c
+++ b/arch/parisc/hpux/fs.c
@@ -109,33 +109,32 @@ Efault:
 
 int hpux_getdents(unsigned int fd, struct hpux_dirent __user *dirent, unsigned int count)
 {
-	struct file * file;
+	struct fd arg;
 	struct hpux_dirent __user * lastdirent;
 	struct getdents_callback buf;
-	int error = -EBADF;
+	int error;
 
-	file = fget(fd);
-	if (!file)
-		goto out;
+	arg = fdget(fd);
+	if (!arg.file)
+		return -EBADF;
 
 	buf.current_dir = dirent;
 	buf.previous = NULL;
 	buf.count = count;
 	buf.error = 0;
 
-	error = vfs_readdir(file, filldir, &buf);
+	error = vfs_readdir(arg.file, filldir, &buf);
 	if (error >= 0)
 		error = buf.error;
 	lastdirent = buf.previous;
 	if (lastdirent) {
-		if (put_user(file->f_pos, &lastdirent->d_off))
+		if (put_user(arg.file->f_pos, &lastdirent->d_off))
 			error = -EFAULT;
 		else
 			error = count - buf.count;
 	}
 
-	fput(file);
-out:
+	fdput(arg);
 	return error;
 }
 
diff --git a/arch/parisc/hpux/gate.S b/arch/parisc/hpux/gate.S
index 38a1c1b..0114688 100644
--- a/arch/parisc/hpux/gate.S
+++ b/arch/parisc/hpux/gate.S
@@ -71,7 +71,7 @@ ENTRY(hpux_gateway_page)
 	STREG	%r26, TASK_PT_GR26(%r1)	 	/* 1st argument */
 	STREG	%r27, TASK_PT_GR27(%r1)		/* user dp */
 	STREG   %r28, TASK_PT_GR28(%r1)         /* return value 0 */
-	STREG   %r28, TASK_PT_ORIG_R28(%r1)     /* return value 0 (saved for signals) */
+	STREG   %r0, TASK_PT_ORIG_R28(%r1)     /* don't prohibit restarts */
 	STREG   %r29, TASK_PT_GR29(%r1)         /* 8th argument */
 	STREG	%r31, TASK_PT_GR31(%r1)		/* preserve syscall return ptr */
 	
diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild
index 4383707..818d651 100644
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -2,3 +2,4 @@ include include/asm-generic/Kbuild.asm
 
 header-y += pdc.h
 generic-y += word-at-a-time.h
+generic-y += exec.h
diff --git a/arch/parisc/include/asm/compat.h b/arch/parisc/include/asm/compat.h
index 760f331..db7a662 100644
--- a/arch/parisc/include/asm/compat.h
+++ b/arch/parisc/include/asm/compat.h
@@ -36,6 +36,7 @@ typedef s64	compat_s64;
 typedef u32	compat_uint_t;
 typedef u32	compat_ulong_t;
 typedef u64	compat_u64;
+typedef u32	compat_uptr_t;
 
 struct compat_timespec {
 	compat_time_t		tv_sec;
@@ -127,6 +128,63 @@ typedef u32		compat_old_sigset_t;	/* at least 32 bits */
 
 typedef u32		compat_sigset_word;
 
+typedef union compat_sigval {
+	compat_int_t	sival_int;
+	compat_uptr_t	sival_ptr;
+} compat_sigval_t;
+
+typedef struct compat_siginfo {
+	int si_signo;
+	int si_errno;
+	int si_code;
+
+	union {
+		int _pad[128/sizeof(int) - 3];
+
+		/* kill() */
+		struct {
+			unsigned int _pid;      /* sender's pid */
+			unsigned int _uid;      /* sender's uid */
+		} _kill;
+
+		/* POSIX.1b timers */
+		struct {
+			compat_timer_t _tid;            /* timer id */
+			int _overrun;           /* overrun count */
+			char _pad[sizeof(unsigned int) - sizeof(int)];
+			compat_sigval_t _sigval;        /* same as below */
+			int _sys_private;       /* not to be passed to user */
+		} _timer;
+
+		/* POSIX.1b signals */
+		struct {
+			unsigned int _pid;      /* sender's pid */
+			unsigned int _uid;      /* sender's uid */
+			compat_sigval_t _sigval;
+		} _rt;
+
+		/* SIGCHLD */
+		struct {
+			unsigned int _pid;      /* which child */
+			unsigned int _uid;      /* sender's uid */
+			int _status;            /* exit code */
+			compat_clock_t _utime;
+			compat_clock_t _stime;
+		} _sigchld;
+
+		/* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
+		struct {
+			unsigned int _addr;     /* faulting insn/memory ref. */
+		} _sigfault;
+
+		/* SIGPOLL */
+		struct {
+			int _band;      /* POLL_IN, POLL_OUT, POLL_MSG */
+			int _fd;
+		} _sigpoll;
+	} _sifields;
+} compat_siginfo_t;
+
 #define COMPAT_OFF_T_MAX	0x7fffffff
 #define COMPAT_LOFF_T_MAX	0x7fffffffffffffffL
 
@@ -136,7 +194,6 @@ typedef u32		compat_sigset_word;
  * as pointers because the syscall entry code will have
  * appropriately converted them already.
  */
-typedef	u32		compat_uptr_t;
 
 static inline void __user *compat_ptr(compat_uptr_t uptr)
 {
diff --git a/arch/parisc/include/asm/exec.h b/arch/parisc/include/asm/exec.h
deleted file mode 100644
index 6bb5af7..0000000
--- a/arch/parisc/include/asm/exec.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __PARISC_EXEC_H
-#define __PARISC_EXEC_H
-
-#define arch_align_stack(x) (x)
-
-#endif /* __PARISC_EXEC_H */
diff --git a/arch/parisc/include/asm/module.h b/arch/parisc/include/asm/module.h
index 1f41234..bab37e9 100644
--- a/arch/parisc/include/asm/module.h
+++ b/arch/parisc/include/asm/module.h
@@ -1,21 +1,11 @@
 #ifndef _ASM_PARISC_MODULE_H
 #define _ASM_PARISC_MODULE_H
+
+#include <asm-generic/module.h>
+
 /*
  * This file contains the parisc architecture specific module code.
  */
-#ifdef CONFIG_64BIT
-#define Elf_Shdr Elf64_Shdr
-#define Elf_Sym Elf64_Sym
-#define Elf_Ehdr Elf64_Ehdr
-#define Elf_Addr Elf64_Addr
-#define Elf_Rela Elf64_Rela
-#else
-#define Elf_Shdr Elf32_Shdr
-#define Elf_Sym Elf32_Sym
-#define Elf_Ehdr Elf32_Ehdr
-#define Elf_Addr Elf32_Addr
-#define Elf_Rela Elf32_Rela
-#endif
 
 struct unwind_table;
 
diff --git a/arch/parisc/include/asm/thread_info.h b/arch/parisc/include/asm/thread_info.h
index 22b4726..d1fb79a 100644
--- a/arch/parisc/include/asm/thread_info.h
+++ b/arch/parisc/include/asm/thread_info.h
@@ -68,13 +68,16 @@ struct thread_info {
 #define _TIF_NEED_RESCHED	(1 << TIF_NEED_RESCHED)
 #define _TIF_POLLING_NRFLAG	(1 << TIF_POLLING_NRFLAG)
 #define _TIF_32BIT		(1 << TIF_32BIT)
-#define _TIF_RESTORE_SIGMASK	(1 << TIF_RESTORE_SIGMASK)
 #define _TIF_NOTIFY_RESUME	(1 << TIF_NOTIFY_RESUME)
 #define _TIF_SINGLESTEP		(1 << TIF_SINGLESTEP)
 #define _TIF_BLOCKSTEP		(1 << TIF_BLOCKSTEP)
 
 #define _TIF_USER_WORK_MASK     (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | \
                                  _TIF_NEED_RESCHED)
+#define _TIF_SYSCALL_TRACE_MASK (_TIF_SYSCALL_TRACE | _TIF_SINGLESTEP |	\
+				 _TIF_BLOCKSTEP)
+
+#define tsk_is_polling(t) test_tsk_thread_flag(t, TIF_POLLING_NRFLAG)
 
 #endif /* __KERNEL__ */
 
diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c
index 9d18189..48e16dc 100644
--- a/arch/parisc/kernel/cache.c
+++ b/arch/parisc/kernel/cache.c
@@ -276,7 +276,6 @@ void flush_dcache_page(struct page *page)
 {
 	struct address_space *mapping = page_mapping(page);
 	struct vm_area_struct *mpnt;
-	struct prio_tree_iter iter;
 	unsigned long offset;
 	unsigned long addr, old_addr = 0;
 	pgoff_t pgoff;
@@ -299,7 +298,7 @@ void flush_dcache_page(struct page *page)
 	 * to flush one address here for them all to become coherent */
 
 	flush_dcache_mmap_lock(mapping);
-	vma_prio_tree_foreach(mpnt, &iter, &mapping->i_mmap, pgoff, pgoff) {
+	vma_interval_tree_foreach(mpnt, &mapping->i_mmap, pgoff, pgoff) {
 		offset = (pgoff - mpnt->vm_pgoff) << PAGE_SHIFT;
 		addr = mpnt->vm_start + offset;
 
diff --git a/arch/parisc/kernel/pdc_cons.c b/arch/parisc/kernel/pdc_cons.c
index 47341aa..8823863 100644
--- a/arch/parisc/kernel/pdc_cons.c
+++ b/arch/parisc/kernel/pdc_cons.c
@@ -202,6 +202,7 @@ static int __init pdc_console_tty_driver_init(void)
 	pdc_console_tty_driver->flags = TTY_DRIVER_REAL_RAW |
 		TTY_DRIVER_RESET_TERMIOS;
 	tty_set_operations(pdc_console_tty_driver, &pdc_console_tty_ops);
+	tty_port_link_device(&tty_port, pdc_console_tty_driver, 0);
 
 	err = tty_register_driver(pdc_console_tty_driver);
 	if (err) {
diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c
index 2c05a92..8c6b6b6 100644
--- a/arch/parisc/kernel/process.c
+++ b/arch/parisc/kernel/process.c
@@ -48,6 +48,7 @@
 #include <linux/unistd.h>
 #include <linux/kallsyms.h>
 #include <linux/uaccess.h>
+#include <linux/rcupdate.h>
 
 #include <asm/io.h>
 #include <asm/asm-offsets.h>
@@ -69,8 +70,10 @@ void cpu_idle(void)
 
 	/* endless idle loop with no priority at all */
 	while (1) {
+		rcu_idle_enter();
 		while (!need_resched())
 			barrier();
+		rcu_idle_exit();
 		schedule_preempt_disabled();
 		check_pgt_cache();
 	}
diff --git a/arch/parisc/kernel/signal.c b/arch/parisc/kernel/signal.c
index 594459b..5379969 100644
--- a/arch/parisc/kernel/signal.c
+++ b/arch/parisc/kernel/signal.c
@@ -113,6 +113,8 @@ sys_rt_sigreturn(struct pt_regs *regs, int in_syscall)
 		(usp - sigframe_size);
 	DBG(2,"sys_rt_sigreturn: frame is %p\n", frame);
 
+	regs->orig_r28 = 1; /* no restarts for sigreturn */
+
 #ifdef CONFIG_64BIT
 	compat_frame = (struct compat_rt_sigframe __user *)frame;
 	
@@ -437,7 +439,7 @@ give_sigsegv:
  * OK, we're invoking a handler.
  */	
 
-static long
+static void
 handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
 		struct pt_regs *regs, int in_syscall)
 {
@@ -447,7 +449,7 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
 	
 	/* Set up the stack frame */
 	if (!setup_rt_frame(sig, ka, info, oldset, regs, in_syscall))
-		return 0;
+		return;
 
 	signal_delivered(sig, info, ka, regs, 
 		test_thread_flag(TIF_SINGLESTEP) ||
@@ -455,13 +457,14 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
 
 	DBG(1,KERN_DEBUG "do_signal: Exit (success), regs->gr[28] = %ld\n",
 		regs->gr[28]);
-
-	return 1;
 }
 
 static inline void
 syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
 {
+	if (regs->orig_r28)
+		return;
+	regs->orig_r28 = 1; /* no more restarts */
 	/* Check the return code */
 	switch (regs->gr[28]) {
 	case -ERESTART_RESTARTBLOCK:
@@ -482,8 +485,6 @@ syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
 		 * we have to do is fiddle the return pointer.
 		 */
 		regs->gr[31] -= 8; /* delayed branching */
-		/* Preserve original r28. */
-		regs->gr[28] = regs->orig_r28;
 		break;
 	}
 }
@@ -491,6 +492,9 @@ syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
 static inline void
 insert_restart_trampoline(struct pt_regs *regs)
 {
+	if (regs->orig_r28)
+		return;
+	regs->orig_r28 = 1; /* no more restarts */
 	switch(regs->gr[28]) {
 	case -ERESTART_RESTARTBLOCK: {
 		/* Restart the system call - no handlers present */
@@ -525,9 +529,6 @@ insert_restart_trampoline(struct pt_regs *regs)
 		flush_user_icache_range(regs->gr[30], regs->gr[30] + 4);
 
 		regs->gr[31] = regs->gr[30] + 8;
-		/* Preserve original r28. */
-		regs->gr[28] = regs->orig_r28;
-
 		return;
 	}
 	case -ERESTARTNOHAND:
@@ -539,9 +540,6 @@ insert_restart_trampoline(struct pt_regs *regs)
 		 * slot of the branch external instruction.
 		 */
 		regs->gr[31] -= 8;
-		/* Preserve original r28. */
-		regs->gr[28] = regs->orig_r28;
-
 		return;
 	}
 	default:
@@ -570,30 +568,17 @@ do_signal(struct pt_regs *regs, long in_syscall)
 	DBG(1,"\ndo_signal: regs=0x%p, sr7 %#lx, in_syscall=%d\n",
 	       regs, regs->sr[7], in_syscall);
 
-	/* Everyone else checks to see if they are in kernel mode at
-	   this point and exits if that's the case.  I'm not sure why
-	   we would be called in that case, but for some reason we
-	   are. */
-
-	/* May need to force signal if handle_signal failed to deliver */
-	while (1) {
-		signr = get_signal_to_deliver(&info, &ka, regs, NULL);
-		DBG(3,"do_signal: signr = %d, regs->gr[28] = %ld\n", signr, regs->gr[28]); 
+	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
+	DBG(3,"do_signal: signr = %d, regs->gr[28] = %ld\n", signr, regs->gr[28]); 
 	
-		if (signr <= 0)
-		  break;
-		
+	if (signr > 0) {
 		/* Restart a system call if necessary. */
 		if (in_syscall)
 			syscall_restart(regs, &ka);
 
-		/* Whee!  Actually deliver the signal.  If the
-		   delivery failed, we need to continue to iterate in
-		   this loop so we can deliver the SIGSEGV... */
-		if (handle_signal(signr, &info, &ka, regs, in_syscall))
-			return;
+		handle_signal(signr, &info, &ka, regs, in_syscall);
+		return;
 	}
-	/* end of while(1) looping forever if we can't force a signal */
 
 	/* Did we come from a system call? */
 	if (in_syscall)
diff --git a/arch/parisc/kernel/signal32.h b/arch/parisc/kernel/signal32.h
index c780084..08a88b5 100644
--- a/arch/parisc/kernel/signal32.h
+++ b/arch/parisc/kernel/signal32.h
@@ -55,58 +55,6 @@ struct k_sigaction32 {
 	struct compat_sigaction sa;
 };
 
-typedef struct compat_siginfo {
-        int si_signo;
-        int si_errno;
-        int si_code;
-
-        union {
-                int _pad[((128/sizeof(int)) - 3)];
-
-                /* kill() */
-                struct {
-                        unsigned int _pid;      /* sender's pid */
-                        unsigned int _uid;      /* sender's uid */
-                } _kill;
-
-                /* POSIX.1b timers */
-                struct {
-                        compat_timer_t _tid;            /* timer id */
-                        int _overrun;           /* overrun count */
-                        char _pad[sizeof(unsigned int) - sizeof(int)];
-                        compat_sigval_t _sigval;        /* same as below */
-                        int _sys_private;       /* not to be passed to user */
-                } _timer;
-
-                /* POSIX.1b signals */
-                struct {
-                        unsigned int _pid;      /* sender's pid */
-                        unsigned int _uid;      /* sender's uid */
-                        compat_sigval_t _sigval;
-                } _rt;
-
-                /* SIGCHLD */
-                struct {
-                        unsigned int _pid;      /* which child */
-                        unsigned int _uid;      /* sender's uid */
-                        int _status;            /* exit code */
-                        compat_clock_t _utime;
-                        compat_clock_t _stime;
-                } _sigchld;
-
-                /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
-                struct {
-                        unsigned int _addr;     /* faulting insn/memory ref. */
-                } _sigfault;
-
-                /* SIGPOLL */
-                struct {
-                        int _band;      /* POLL_IN, POLL_OUT, POLL_MSG */
-                        int _fd;
-                } _sigpoll;
-        } _sifields;
-} compat_siginfo_t;
-
 int copy_siginfo_to_user32 (compat_siginfo_t __user *to, siginfo_t *from);
 int copy_siginfo_from_user32 (siginfo_t *to, compat_siginfo_t __user *from);
 
diff --git a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S
index 82a52b2..86742df 100644
--- a/arch/parisc/kernel/syscall.S
+++ b/arch/parisc/kernel/syscall.S
@@ -156,7 +156,7 @@ linux_gateway_entry:
 	STREG	%r26, TASK_PT_GR26(%r1)	 	/* 1st argument */
 	STREG	%r27, TASK_PT_GR27(%r1)		/* user dp */
 	STREG   %r28, TASK_PT_GR28(%r1)         /* return value 0 */
-	STREG   %r28, TASK_PT_ORIG_R28(%r1)     /* return value 0 (saved for signals) */
+	STREG   %r0, TASK_PT_ORIG_R28(%r1)      /* don't prohibit restarts */
 	STREG	%r29, TASK_PT_GR29(%r1)		/* return value 1 */
 	STREG	%r31, TASK_PT_GR31(%r1)		/* preserve syscall return ptr */
 	
@@ -180,9 +180,10 @@ linux_gateway_entry:
 
 	/* Are we being ptraced? */
 	mfctl	%cr30, %r1
-	LDREG	TI_TASK(%r1),%r1
-	ldw	TASK_PTRACE(%r1), %r1
-	bb,<,n	%r1,31,.Ltracesys
+	LDREG	TI_FLAGS(%r1),%r1
+	ldi	_TIF_SYSCALL_TRACE_MASK, %r19
+	and,COND(=) %r1, %r19, %r0
+	b,n	.Ltracesys
 	
 	/* Note!  We cannot use the syscall table that is mapped
 	nearby since the gateway page is mapped execute-only. */
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 352f416..088fc76 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -139,6 +139,9 @@ config PPC
 	select GENERIC_CLOCKEVENTS
 	select GENERIC_STRNCPY_FROM_USER
 	select GENERIC_STRNLEN_USER
+	select HAVE_MOD_ARCH_SPECIFIC
+	select MODULES_USE_ELF_RELA
+	select GENERIC_KERNEL_THREAD
 
 config EARLY_PRINTK
 	bool
@@ -215,7 +218,8 @@ config ARCH_HIBERNATION_POSSIBLE
 config ARCH_SUSPEND_POSSIBLE
 	def_bool y
 	depends on ADB_PMU || PPC_EFIKA || PPC_LITE5200 || PPC_83xx || \
-		   (PPC_85xx && !SMP) || PPC_86xx || PPC_PSERIES || 44x || 40x
+		   (PPC_85xx && !PPC_E500MC) || PPC_86xx || PPC_PSERIES \
+		   || 44x || 40x
 
 config PPC_DCR_NATIVE
 	bool
@@ -239,6 +243,9 @@ config PPC_OF_PLATFORM_PCI
 config ARCH_SUPPORTS_DEBUG_PAGEALLOC
 	def_bool y
 
+config ARCH_SUPPORTS_UPROBES
+	def_bool y
+
 config PPC_ADV_DEBUG_REGS
 	bool
 	depends on 40x || BOOKE
@@ -325,7 +332,8 @@ config SWIOTLB
 
 config HOTPLUG_CPU
 	bool "Support for enabling/disabling CPUs"
-	depends on SMP && HOTPLUG && EXPERIMENTAL && (PPC_PSERIES || PPC_PMAC || PPC_POWERNV)
+	depends on SMP && HOTPLUG && EXPERIMENTAL && (PPC_PSERIES || \
+	PPC_PMAC || PPC_POWERNV || (PPC_85xx && !PPC_E500MC))
 	---help---
 	  Say Y here to be able to disable and re-enable individual
 	  CPUs at runtime on SMP machines.
@@ -557,6 +565,14 @@ config SCHED_SMT
 	  when dealing with POWER5 cpus at a cost of slightly increased
 	  overhead in some places. If unsure say N here.
 
+config PPC_DENORMALISATION
+	bool "PowerPC denormalisation exception handling"
+	depends on PPC_BOOK3S_64
+	default "n"
+	---help---
+	  Add support for handling denormalisation of single precision
+	  values.  Useful for bare metal only.  If unsure say Y here.
+
 config CMDLINE_BOOL
 	bool "Default bootloader kernel arguments"
 
diff --git a/arch/powerpc/boot/.gitignore b/arch/powerpc/boot/.gitignore
index 1c1aadc..c32ae5c 100644
--- a/arch/powerpc/boot/.gitignore
+++ b/arch/powerpc/boot/.gitignore
@@ -1,10 +1,6 @@
 addnote
 empty.c
 hack-coff
-infblock.c
-infblock.h
-infcodes.c
-infcodes.h
 inffast.c
 inffast.h
 inffixed.h
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index b7d8333..6a15c96 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -107,6 +107,7 @@ src-boot := $(addprefix $(obj)/, $(src-boot))
 obj-boot := $(addsuffix .o, $(basename $(src-boot)))
 obj-wlib := $(addsuffix .o, $(basename $(addprefix $(obj)/, $(src-wlib))))
 obj-plat := $(addsuffix .o, $(basename $(addprefix $(obj)/, $(src-plat))))
+obj-plat: $(libfdt)
 
 quiet_cmd_copy_zlib = COPY    $@
       cmd_copy_zlib = sed "s@__used@@;s@<linux/\([^>]*\).*@\"\1\"@" $< > $@
diff --git a/arch/powerpc/boot/dts/fsl/e500mc_power_isa.dtsi b/arch/powerpc/boot/dts/fsl/e500mc_power_isa.dtsi
new file mode 100644
index 0000000..870c653
--- /dev/null
+++ b/arch/powerpc/boot/dts/fsl/e500mc_power_isa.dtsi
@@ -0,0 +1,58 @@
+/*
+ * e500mc Power ISA Device Tree Source (include)
+ *
+ * Copyright 2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/ {
+	cpus {
+		power-isa-version = "2.06";
+		power-isa-b;		// Base
+		power-isa-e;		// Embedded
+		power-isa-atb;		// Alternate Time Base
+		power-isa-cs;		// Cache Specification
+		power-isa-ds;		// Decorated Storage
+		power-isa-e.ed;		// Embedded.Enhanced Debug
+		power-isa-e.pd;		// Embedded.External PID
+		power-isa-e.hv;		// Embedded.Hypervisor
+		power-isa-e.le;		// Embedded.Little-Endian
+		power-isa-e.pm;		// Embedded.Performance Monitor
+		power-isa-e.pc;		// Embedded.Processor Control
+		power-isa-ecl;		// Embedded Cache Locking
+		power-isa-exp;		// External Proxy
+		power-isa-fp;		// Floating Point
+		power-isa-fp.r;		// Floating Point.Record
+		power-isa-mmc;		// Memory Coherence
+		power-isa-scpm;		// Store Conditional Page Mobility
+		power-isa-wt;		// Wait
+		mmu-type = "power-embedded";
+	};
+};
diff --git a/arch/powerpc/boot/dts/fsl/e500v2_power_isa.dtsi b/arch/powerpc/boot/dts/fsl/e500v2_power_isa.dtsi
new file mode 100644
index 0000000..f492814
--- /dev/null
+++ b/arch/powerpc/boot/dts/fsl/e500v2_power_isa.dtsi
@@ -0,0 +1,52 @@
+/*
+ * e500v2 Power ISA Device Tree Source (include)
+ *
+ * Copyright 2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/ {
+	cpus {
+		power-isa-version = "2.03";
+		power-isa-b;		// Base
+		power-isa-e;		// Embedded
+		power-isa-atb;		// Alternate Time Base
+		power-isa-cs;		// Cache Specification
+		power-isa-e.le;		// Embedded.Little-Endian
+		power-isa-e.pm;		// Embedded.Performance Monitor
+		power-isa-ecl;		// Embedded Cache Locking
+		power-isa-mmc;		// Memory Coherence
+		power-isa-sp;		// Signal Processing Engine
+		power-isa-sp.fd;	// SPE.Embedded Float Scalar Double
+		power-isa-sp.fs;	// SPE.Embedded Float Scalar Single
+		power-isa-sp.fv;	// SPE.Embedded Float Vector
+		mmu-type = "power-embedded";
+	};
+};
diff --git a/arch/powerpc/boot/dts/fsl/e5500_power_isa.dtsi b/arch/powerpc/boot/dts/fsl/e5500_power_isa.dtsi
new file mode 100644
index 0000000..3230212
--- /dev/null
+++ b/arch/powerpc/boot/dts/fsl/e5500_power_isa.dtsi
@@ -0,0 +1,59 @@
+/*
+ * e5500 Power ISA Device Tree Source (include)
+ *
+ * Copyright 2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/ {
+	cpus {
+		power-isa-version = "2.06";
+		power-isa-b;		// Base
+		power-isa-e;		// Embedded
+		power-isa-atb;		// Alternate Time Base
+		power-isa-cs;		// Cache Specification
+		power-isa-ds;		// Decorated Storage
+		power-isa-e.ed;		// Embedded.Enhanced Debug
+		power-isa-e.pd;		// Embedded.External PID
+		power-isa-e.hv;		// Embedded.Hypervisor
+		power-isa-e.le;		// Embedded.Little-Endian
+		power-isa-e.pm;		// Embedded.Performance Monitor
+		power-isa-e.pc;		// Embedded.Processor Control
+		power-isa-ecl;		// Embedded Cache Locking
+		power-isa-exp;		// External Proxy
+		power-isa-fp;		// Floating Point
+		power-isa-fp.r;		// Floating Point.Record
+		power-isa-mmc;		// Memory Coherence
+		power-isa-scpm;		// Store Conditional Page Mobility
+		power-isa-wt;		// Wait
+		power-isa-64;		// 64-bit
+		mmu-type = "power-embedded";
+	};
+};
diff --git a/arch/powerpc/boot/dts/fsl/mpc8536si-pre.dtsi b/arch/powerpc/boot/dts/fsl/mpc8536si-pre.dtsi
index 7de45a7..152906f 100644
--- a/arch/powerpc/boot/dts/fsl/mpc8536si-pre.dtsi
+++ b/arch/powerpc/boot/dts/fsl/mpc8536si-pre.dtsi
@@ -33,6 +33,9 @@
  */
 
 /dts-v1/;
+
+/include/ "e500v2_power_isa.dtsi"
+
 / {
 	compatible = "fsl,MPC8536";
 	#address-cells = <2>;
diff --git a/arch/powerpc/boot/dts/fsl/mpc8544si-pre.dtsi b/arch/powerpc/boot/dts/fsl/mpc8544si-pre.dtsi
index 8777f92..5a69baf 100644
--- a/arch/powerpc/boot/dts/fsl/mpc8544si-pre.dtsi
+++ b/arch/powerpc/boot/dts/fsl/mpc8544si-pre.dtsi
@@ -33,6 +33,9 @@
  */
 
 /dts-v1/;
+
+/include/ "e500v2_power_isa.dtsi"
+
 / {
 	compatible = "fsl,MPC8544";
 	#address-cells = <2>;
diff --git a/arch/powerpc/boot/dts/fsl/mpc8548si-pre.dtsi b/arch/powerpc/boot/dts/fsl/mpc8548si-pre.dtsi
index 720422d..fc1ce97 100644
--- a/arch/powerpc/boot/dts/fsl/mpc8548si-pre.dtsi
+++ b/arch/powerpc/boot/dts/fsl/mpc8548si-pre.dtsi
@@ -33,6 +33,9 @@
  */
 
 /dts-v1/;
+
+/include/ "e500v2_power_isa.dtsi"
+
 / {
 	compatible = "fsl,MPC8548";
 	#address-cells = <2>;
diff --git a/arch/powerpc/boot/dts/fsl/mpc8568si-pre.dtsi b/arch/powerpc/boot/dts/fsl/mpc8568si-pre.dtsi
index eacd62c..122ca3b 100644
--- a/arch/powerpc/boot/dts/fsl/mpc8568si-pre.dtsi
+++ b/arch/powerpc/boot/dts/fsl/mpc8568si-pre.dtsi
@@ -33,6 +33,9 @@
  */
 
 /dts-v1/;
+
+/include/ "e500v2_power_isa.dtsi"
+
 / {
 	compatible = "fsl,MPC8568";
 	#address-cells = <2>;
diff --git a/arch/powerpc/boot/dts/fsl/mpc8569si-pre.dtsi b/arch/powerpc/boot/dts/fsl/mpc8569si-pre.dtsi
index b07064d..2cd15a2 100644
--- a/arch/powerpc/boot/dts/fsl/mpc8569si-pre.dtsi
+++ b/arch/powerpc/boot/dts/fsl/mpc8569si-pre.dtsi
@@ -33,6 +33,9 @@
  */
 
 /dts-v1/;
+
+/include/ "e500v2_power_isa.dtsi"
+
 / {
 	compatible = "fsl,MPC8569";
 	#address-cells = <2>;
diff --git a/arch/powerpc/boot/dts/fsl/mpc8572si-pre.dtsi b/arch/powerpc/boot/dts/fsl/mpc8572si-pre.dtsi
index ca18832..28c2a86 100644
--- a/arch/powerpc/boot/dts/fsl/mpc8572si-pre.dtsi
+++ b/arch/powerpc/boot/dts/fsl/mpc8572si-pre.dtsi
@@ -33,6 +33,9 @@
  */
 
 /dts-v1/;
+
+/include/ "e500v2_power_isa.dtsi"
+
 / {
 	compatible = "fsl,MPC8572";
 	#address-cells = <2>;
diff --git a/arch/powerpc/boot/dts/fsl/p1010si-pre.dtsi b/arch/powerpc/boot/dts/fsl/p1010si-pre.dtsi
index 7354a8f..6e76f9b 100644
--- a/arch/powerpc/boot/dts/fsl/p1010si-pre.dtsi
+++ b/arch/powerpc/boot/dts/fsl/p1010si-pre.dtsi
@@ -33,6 +33,9 @@
  */
 
 /dts-v1/;
+
+/include/ "e500v2_power_isa.dtsi"
+
 / {
 	compatible = "fsl,P1010";
 	#address-cells = <2>;
diff --git a/arch/powerpc/boot/dts/fsl/p1020si-pre.dtsi b/arch/powerpc/boot/dts/fsl/p1020si-pre.dtsi
index 6f0376e..fed9c4c 100644
--- a/arch/powerpc/boot/dts/fsl/p1020si-pre.dtsi
+++ b/arch/powerpc/boot/dts/fsl/p1020si-pre.dtsi
@@ -33,6 +33,9 @@
  */
 
 /dts-v1/;
+
+/include/ "e500v2_power_isa.dtsi"
+
 / {
 	compatible = "fsl,P1020";
 	#address-cells = <2>;
diff --git a/arch/powerpc/boot/dts/fsl/p1021si-pre.dtsi b/arch/powerpc/boot/dts/fsl/p1021si-pre.dtsi
index 4abd54b..36161b5 100644
--- a/arch/powerpc/boot/dts/fsl/p1021si-pre.dtsi
+++ b/arch/powerpc/boot/dts/fsl/p1021si-pre.dtsi
@@ -33,6 +33,9 @@
  */
 
 /dts-v1/;
+
+/include/ "e500v2_power_isa.dtsi"
+
 / {
 	compatible = "fsl,P1021";
 	#address-cells = <2>;
diff --git a/arch/powerpc/boot/dts/fsl/p1022si-pre.dtsi b/arch/powerpc/boot/dts/fsl/p1022si-pre.dtsi
index e930f4f..1956dea 100644
--- a/arch/powerpc/boot/dts/fsl/p1022si-pre.dtsi
+++ b/arch/powerpc/boot/dts/fsl/p1022si-pre.dtsi
@@ -33,6 +33,9 @@
  */
 
 /dts-v1/;
+
+/include/ "e500v2_power_isa.dtsi"
+
 / {
 	compatible = "fsl,P1022";
 	#address-cells = <2>;
diff --git a/arch/powerpc/boot/dts/fsl/p1023si-pre.dtsi b/arch/powerpc/boot/dts/fsl/p1023si-pre.dtsi
index ac45f6d..132a152 100644
--- a/arch/powerpc/boot/dts/fsl/p1023si-pre.dtsi
+++ b/arch/powerpc/boot/dts/fsl/p1023si-pre.dtsi
@@ -33,6 +33,9 @@
  */
 
 /dts-v1/;
+
+/include/ "e500v2_power_isa.dtsi"
+
 / {
 	compatible = "fsl,P1023";
 	#address-cells = <2>;
diff --git a/arch/powerpc/boot/dts/fsl/p2020si-pre.dtsi b/arch/powerpc/boot/dts/fsl/p2020si-pre.dtsi
index 3213288..42bf3c6 100644
--- a/arch/powerpc/boot/dts/fsl/p2020si-pre.dtsi
+++ b/arch/powerpc/boot/dts/fsl/p2020si-pre.dtsi
@@ -33,6 +33,9 @@
  */
 
 /dts-v1/;
+
+/include/ "e500v2_power_isa.dtsi"
+
 / {
 	compatible = "fsl,P2020";
 	#address-cells = <2>;
diff --git a/arch/powerpc/boot/dts/fsl/p2041si-pre.dtsi b/arch/powerpc/boot/dts/fsl/p2041si-pre.dtsi
index 2d0a40d..7a2697d 100644
--- a/arch/powerpc/boot/dts/fsl/p2041si-pre.dtsi
+++ b/arch/powerpc/boot/dts/fsl/p2041si-pre.dtsi
@@ -33,6 +33,9 @@
  */
 
 /dts-v1/;
+
+/include/ "e500mc_power_isa.dtsi"
+
 / {
 	compatible = "fsl,P2041";
 	#address-cells = <2>;
diff --git a/arch/powerpc/boot/dts/fsl/p3041si-pre.dtsi b/arch/powerpc/boot/dts/fsl/p3041si-pre.dtsi
index 136def3..c9ca2c3 100644
--- a/arch/powerpc/boot/dts/fsl/p3041si-pre.dtsi
+++ b/arch/powerpc/boot/dts/fsl/p3041si-pre.dtsi
@@ -33,6 +33,9 @@
  */
 
 /dts-v1/;
+
+/include/ "e500mc_power_isa.dtsi"
+
 / {
 	compatible = "fsl,P3041";
 	#address-cells = <2>;
diff --git a/arch/powerpc/boot/dts/fsl/p4080si-pre.dtsi b/arch/powerpc/boot/dts/fsl/p4080si-pre.dtsi
index b9556ee..493d9a0 100644
--- a/arch/powerpc/boot/dts/fsl/p4080si-pre.dtsi
+++ b/arch/powerpc/boot/dts/fsl/p4080si-pre.dtsi
@@ -33,6 +33,9 @@
  */
 
 /dts-v1/;
+
+/include/ "e500mc_power_isa.dtsi"
+
 / {
 	compatible = "fsl,P4080";
 	#address-cells = <2>;
diff --git a/arch/powerpc/boot/dts/fsl/p5020si-pre.dtsi b/arch/powerpc/boot/dts/fsl/p5020si-pre.dtsi
index ae823a4..0a198b0 100644
--- a/arch/powerpc/boot/dts/fsl/p5020si-pre.dtsi
+++ b/arch/powerpc/boot/dts/fsl/p5020si-pre.dtsi
@@ -33,6 +33,9 @@
  */
 
 /dts-v1/;
+
+/include/ "e5500_power_isa.dtsi"
+
 / {
 	compatible = "fsl,P5020";
 	#address-cells = <2>;
diff --git a/arch/powerpc/boot/dts/fsl/p5040si-post.dtsi b/arch/powerpc/boot/dts/fsl/p5040si-post.dtsi
new file mode 100644
index 0000000..db2c9a7
--- /dev/null
+++ b/arch/powerpc/boot/dts/fsl/p5040si-post.dtsi
@@ -0,0 +1,320 @@
+/*
+ * P5040 Silicon/SoC Device Tree Source (post include)
+ *
+ * Copyright 2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * This software is provided by Freescale Semiconductor "as is" and any
+ * express or implied warranties, including, but not limited to, the implied
+ * warranties of merchantability and fitness for a particular purpose are
+ * disclaimed. In no event shall Freescale Semiconductor be liable for any
+ * direct, indirect, incidental, special, exemplary, or consequential damages
+ * (including, but not limited to, procurement of substitute goods or services;
+ * loss of use, data, or profits; or business interruption) however caused and
+ * on any theory of liability, whether in contract, strict liability, or tort
+ * (including negligence or otherwise) arising in any way out of the use of this
+ * software, even if advised of the possibility of such damage.
+ */
+
+&lbc {
+	compatible = "fsl,p5040-elbc", "fsl,elbc", "simple-bus";
+	interrupts = <25 2 0 0>;
+	#address-cells = <2>;
+	#size-cells = <1>;
+};
+
+/* controller at 0x200000 */
+&pci0 {
+	compatible = "fsl,p5040-pcie", "fsl,qoriq-pcie-v2.4";
+	device_type = "pci";
+	#size-cells = <2>;
+	#address-cells = <3>;
+	bus-range = <0x0 0xff>;
+	clock-frequency = <33333333>;
+	interrupts = <16 2 1 15>;
+	pcie@0 {
+		reg = <0 0 0 0 0>;
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		device_type = "pci";
+		interrupts = <16 2 1 15>;
+		interrupt-map-mask = <0xf800 0 0 7>;
+		interrupt-map = <
+			/* IDSEL 0x0 */
+			0000 0 0 1 &mpic 40 1 0 0
+			0000 0 0 2 &mpic 1 1 0 0
+			0000 0 0 3 &mpic 2 1 0 0
+			0000 0 0 4 &mpic 3 1 0 0
+			>;
+	};
+};
+
+/* controller at 0x201000 */
+&pci1 {
+	compatible = "fsl,p5040-pcie", "fsl,qoriq-pcie-v2.4";
+	device_type = "pci";
+	#size-cells = <2>;
+	#address-cells = <3>;
+	bus-range = <0 0xff>;
+	clock-frequency = <33333333>;
+	interrupts = <16 2 1 14>;
+	pcie@0 {
+		reg = <0 0 0 0 0>;
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		device_type = "pci";
+		interrupts = <16 2 1 14>;
+		interrupt-map-mask = <0xf800 0 0 7>;
+		interrupt-map = <
+			/* IDSEL 0x0 */
+			0000 0 0 1 &mpic 41 1 0 0
+			0000 0 0 2 &mpic 5 1 0 0
+			0000 0 0 3 &mpic 6 1 0 0
+			0000 0 0 4 &mpic 7 1 0 0
+			>;
+	};
+};
+
+/* controller at 0x202000 */
+&pci2 {
+	compatible = "fsl,p5040-pcie", "fsl,qoriq-pcie-v2.4";
+	device_type = "pci";
+	#size-cells = <2>;
+	#address-cells = <3>;
+	bus-range = <0x0 0xff>;
+	clock-frequency = <33333333>;
+	interrupts = <16 2 1 13>;
+	pcie@0 {
+		reg = <0 0 0 0 0>;
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		device_type = "pci";
+		interrupts = <16 2 1 13>;
+		interrupt-map-mask = <0xf800 0 0 7>;
+		interrupt-map = <
+			/* IDSEL 0x0 */
+			0000 0 0 1 &mpic 42 1 0 0
+			0000 0 0 2 &mpic 9 1 0 0
+			0000 0 0 3 &mpic 10 1 0 0
+			0000 0 0 4 &mpic 11 1 0 0
+			>;
+	};
+};
+
+&dcsr {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	compatible = "fsl,dcsr", "simple-bus";
+
+	dcsr-epu@0 {
+		compatible = "fsl,dcsr-epu";
+		interrupts = <52 2 0 0
+			      84 2 0 0
+			      85 2 0 0>;
+		reg = <0x0 0x1000>;
+	};
+	dcsr-npc {
+		compatible = "fsl,dcsr-npc";
+		reg = <0x1000 0x1000 0x1000000 0x8000>;
+	};
+	dcsr-nxc@2000 {
+		compatible = "fsl,dcsr-nxc";
+		reg = <0x2000 0x1000>;
+	};
+	dcsr-corenet {
+		compatible = "fsl,dcsr-corenet";
+		reg = <0x8000 0x1000 0xB0000 0x1000>;
+	};
+	dcsr-dpaa@9000 {
+		compatible = "fsl,p5040-dcsr-dpaa", "fsl,dcsr-dpaa";
+		reg = <0x9000 0x1000>;
+	};
+	dcsr-ocn@11000 {
+		compatible = "fsl,p5040-dcsr-ocn", "fsl,dcsr-ocn";
+		reg = <0x11000 0x1000>;
+	};
+	dcsr-ddr@12000 {
+		compatible = "fsl,dcsr-ddr";
+		dev-handle = <&ddr1>;
+		reg = <0x12000 0x1000>;
+	};
+	dcsr-ddr@13000 {
+		compatible = "fsl,dcsr-ddr";
+		dev-handle = <&ddr2>;
+		reg = <0x13000 0x1000>;
+	};
+	dcsr-nal@18000 {
+		compatible = "fsl,p5040-dcsr-nal", "fsl,dcsr-nal";
+		reg = <0x18000 0x1000>;
+	};
+	dcsr-rcpm@22000 {
+		compatible = "fsl,p5040-dcsr-rcpm", "fsl,dcsr-rcpm";
+		reg = <0x22000 0x1000>;
+	};
+	dcsr-cpu-sb-proxy@40000 {
+		compatible = "fsl,dcsr-e5500-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+		cpu-handle = <&cpu0>;
+		reg = <0x40000 0x1000>;
+	};
+	dcsr-cpu-sb-proxy@41000 {
+		compatible = "fsl,dcsr-e5500-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+		cpu-handle = <&cpu1>;
+		reg = <0x41000 0x1000>;
+	};
+	dcsr-cpu-sb-proxy@42000 {
+		compatible = "fsl,dcsr-e5500-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+		cpu-handle = <&cpu2>;
+		reg = <0x42000 0x1000>;
+	};
+	dcsr-cpu-sb-proxy@43000 {
+		compatible = "fsl,dcsr-e5500-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+		cpu-handle = <&cpu3>;
+		reg = <0x43000 0x1000>;
+	};
+};
+
+&soc {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	device_type = "soc";
+	compatible = "simple-bus";
+
+	soc-sram-error {
+		compatible = "fsl,soc-sram-error";
+		interrupts = <16 2 1 29>;
+	};
+
+	corenet-law@0 {
+		compatible = "fsl,corenet-law";
+		reg = <0x0 0x1000>;
+		fsl,num-laws = <32>;
+	};
+
+	ddr1: memory-controller@8000 {
+		compatible = "fsl,qoriq-memory-controller-v4.5", "fsl,qoriq-memory-controller";
+		reg = <0x8000 0x1000>;
+		interrupts = <16 2 1 23>;
+	};
+
+	ddr2: memory-controller@9000 {
+		compatible = "fsl,qoriq-memory-controller-v4.5","fsl,qoriq-memory-controller";
+		reg = <0x9000 0x1000>;
+		interrupts = <16 2 1 22>;
+	};
+
+	cpc: l3-cache-controller@10000 {
+		compatible = "fsl,p5040-l3-cache-controller", "fsl,p4080-l3-cache-controller", "cache";
+		reg = <0x10000 0x1000
+		       0x11000 0x1000>;
+		interrupts = <16 2 1 27
+			      16 2 1 26>;
+	};
+
+	corenet-cf@18000 {
+		compatible = "fsl,corenet-cf";
+		reg = <0x18000 0x1000>;
+		interrupts = <16 2 1 31>;
+		fsl,ccf-num-csdids = <32>;
+		fsl,ccf-num-snoopids = <32>;
+	};
+
+	iommu@20000 {
+		compatible = "fsl,pamu-v1.0", "fsl,pamu";
+		reg = <0x20000 0x5000>;
+		interrupts = <
+			24 2 0 0
+			16 2 1 30>;
+	};
+
+/include/ "qoriq-mpic.dtsi"
+
+	guts: global-utilities@e0000 {
+		compatible = "fsl,p5040-device-config", "fsl,qoriq-device-config-1.0";
+		reg = <0xe0000 0xe00>;
+		fsl,has-rstcr;
+		#sleep-cells = <1>;
+		fsl,liodn-bits = <12>;
+	};
+
+	pins: global-utilities@e0e00 {
+		compatible = "fsl,p5040-pin-control", "fsl,qoriq-pin-control-1.0";
+		reg = <0xe0e00 0x200>;
+		#sleep-cells = <2>;
+	};
+
+	clockgen: global-utilities@e1000 {
+		compatible = "fsl,p5040-clockgen", "fsl,qoriq-clockgen-1.0";
+		reg = <0xe1000 0x1000>;
+		clock-frequency = <0>;
+	};
+
+	rcpm: global-utilities@e2000 {
+		compatible = "fsl,p5040-rcpm", "fsl,qoriq-rcpm-1.0";
+		reg = <0xe2000 0x1000>;
+		#sleep-cells = <1>;
+	};
+
+	sfp: sfp@e8000 {
+		compatible = "fsl,p5040-sfp", "fsl,qoriq-sfp-1.0";
+		reg	   = <0xe8000 0x1000>;
+	};
+
+	serdes: serdes@ea000 {
+		compatible = "fsl,p5040-serdes";
+		reg	   = <0xea000 0x1000>;
+	};
+
+/include/ "qoriq-dma-0.dtsi"
+/include/ "qoriq-dma-1.dtsi"
+/include/ "qoriq-espi-0.dtsi"
+	spi@110000 {
+		fsl,espi-num-chipselects = <4>;
+	};
+
+/include/ "qoriq-esdhc-0.dtsi"
+	sdhc@114000 {
+		sdhci,auto-cmd12;
+	};
+
+/include/ "qoriq-i2c-0.dtsi"
+/include/ "qoriq-i2c-1.dtsi"
+/include/ "qoriq-duart-0.dtsi"
+/include/ "qoriq-duart-1.dtsi"
+/include/ "qoriq-gpio-0.dtsi"
+/include/ "qoriq-usb2-mph-0.dtsi"
+		usb0: usb@210000 {
+			compatible = "fsl-usb2-mph-v1.6", "fsl,mpc85xx-usb2-mph", "fsl-usb2-mph";
+			phy_type = "utmi";
+			port0;
+		};
+
+/include/ "qoriq-usb2-dr-0.dtsi"
+		usb1: usb@211000 {
+			compatible = "fsl-usb2-dr-v1.6", "fsl,mpc85xx-usb2-dr", "fsl-usb2-dr";
+			dr_mode = "host";
+			phy_type = "utmi";
+		};
+
+/include/ "qoriq-sata2-0.dtsi"
+/include/ "qoriq-sata2-1.dtsi"
+/include/ "qoriq-sec5.2-0.dtsi"
+};
diff --git a/arch/powerpc/boot/dts/fsl/p5040si-pre.dtsi b/arch/powerpc/boot/dts/fsl/p5040si-pre.dtsi
new file mode 100644
index 0000000..40ca943
--- /dev/null
+++ b/arch/powerpc/boot/dts/fsl/p5040si-pre.dtsi
@@ -0,0 +1,114 @@
+/*
+ * P5040 Silicon/SoC Device Tree Source (pre include)
+ *
+ * Copyright 2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * This software is provided by Freescale Semiconductor "as is" and any
+ * express or implied warranties, including, but not limited to, the implied
+ * warranties of merchantability and fitness for a particular purpose are
+ * disclaimed. In no event shall Freescale Semiconductor be liable for any
+ * direct, indirect, incidental, special, exemplary, or consequential damages
+ * (including, but not limited to, procurement of substitute goods or services;
+ * loss of use, data, or profits; or business interruption) however caused and
+ * on any theory of liability, whether in contract, strict liability, or tort
+ * (including negligence or otherwise) arising in any way out of the use of this
+ * software, even if advised of the possibility of such damage.
+ */
+
+/dts-v1/;
+
+/include/ "e5500_power_isa.dtsi"
+
+/ {
+	compatible = "fsl,P5040";
+	#address-cells = <2>;
+	#size-cells = <2>;
+	interrupt-parent = <&mpic>;
+
+	aliases {
+		ccsr = &soc;
+		dcsr = &dcsr;
+
+		serial0 = &serial0;
+		serial1 = &serial1;
+		serial2 = &serial2;
+		serial3 = &serial3;
+		pci0 = &pci0;
+		pci1 = &pci1;
+		pci2 = &pci2;
+		usb0 = &usb0;
+		usb1 = &usb1;
+		dma0 = &dma0;
+		dma1 = &dma1;
+		sdhc = &sdhc;
+		msi0 = &msi0;
+		msi1 = &msi1;
+		msi2 = &msi2;
+
+		crypto = &crypto;
+		sec_jr0 = &sec_jr0;
+		sec_jr1 = &sec_jr1;
+		sec_jr2 = &sec_jr2;
+		sec_jr3 = &sec_jr3;
+		rtic_a = &rtic_a;
+		rtic_b = &rtic_b;
+		rtic_c = &rtic_c;
+		rtic_d = &rtic_d;
+		sec_mon = &sec_mon;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu0: PowerPC,e5500@0 {
+			device_type = "cpu";
+			reg = <0>;
+			next-level-cache = <&L2_0>;
+			L2_0: l2-cache {
+				next-level-cache = <&cpc>;
+			};
+		};
+		cpu1: PowerPC,e5500@1 {
+			device_type = "cpu";
+			reg = <1>;
+			next-level-cache = <&L2_1>;
+			L2_1: l2-cache {
+				next-level-cache = <&cpc>;
+			};
+		};
+		cpu2: PowerPC,e5500@2 {
+			device_type = "cpu";
+			reg = <2>;
+			next-level-cache = <&L2_2>;
+			L2_2: l2-cache {
+				next-level-cache = <&cpc>;
+			};
+		};
+		cpu3: PowerPC,e5500@3 {
+			device_type = "cpu";
+			reg = <3>;
+			next-level-cache = <&L2_3>;
+			L2_3: l2-cache {
+				next-level-cache = <&cpc>;
+			};
+		};
+	};
+};
diff --git a/arch/powerpc/boot/dts/fsl/qoriq-sec5.2-0.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-sec5.2-0.dtsi
new file mode 100644
index 0000000..7b2ab8a
--- /dev/null
+++ b/arch/powerpc/boot/dts/fsl/qoriq-sec5.2-0.dtsi
@@ -0,0 +1,118 @@
+/*
+ * QorIQ Sec/Crypto 5.2 device tree stub [ controller @ offset 0x300000 ]
+ *
+ * Copyright 2011-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+crypto: crypto@300000 {
+	compatible = "fsl,sec-v5.2", "fsl,sec-v5.0", "fsl,sec-v4.0";
+	#address-cells = <1>;
+	#size-cells = <1>;
+	reg		 = <0x300000 0x10000>;
+	ranges		 = <0 0x300000 0x10000>;
+	interrupts	 = <92 2 0 0>;
+
+	sec_jr0: jr@1000 {
+		compatible = "fsl,sec-v5.2-job-ring",
+			     "fsl,sec-v5.0-job-ring",
+			     "fsl,sec-v4.0-job-ring";
+		reg = <0x1000 0x1000>;
+		interrupts = <88 2 0 0>;
+	};
+
+	sec_jr1: jr@2000 {
+		compatible = "fsl,sec-v5.2-job-ring",
+			     "fsl,sec-v5.0-job-ring",
+			     "fsl,sec-v4.0-job-ring";
+		reg = <0x2000 0x1000>;
+		interrupts = <89 2 0 0>;
+	};
+
+	sec_jr2: jr@3000 {
+		compatible = "fsl,sec-v5.2-job-ring",
+			     "fsl,sec-v5.0-job-ring",
+			     "fsl,sec-v4.0-job-ring";
+		reg = <0x3000 0x1000>;
+		interrupts = <90 2 0 0>;
+	};
+
+	sec_jr3: jr@4000 {
+		compatible = "fsl,sec-v5.2-job-ring",
+			     "fsl,sec-v5.0-job-ring",
+			     "fsl,sec-v4.0-job-ring";
+		reg = <0x4000 0x1000>;
+		interrupts = <91 2 0 0>;
+	};
+
+	rtic@6000 {
+		compatible = "fsl,sec-v5.2-rtic",
+			     "fsl,sec-v5.0-rtic",
+			     "fsl,sec-v4.0-rtic";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0x6000 0x100>;
+		ranges = <0x0 0x6100 0xe00>;
+
+		rtic_a: rtic-a@0 {
+			compatible = "fsl,sec-v5.2-rtic-memory",
+				     "fsl,sec-v5.0-rtic-memory",
+				     "fsl,sec-v4.0-rtic-memory";
+			reg = <0x00 0x20 0x100 0x80>;
+		};
+
+		rtic_b: rtic-b@20 {
+			compatible = "fsl,sec-v5.2-rtic-memory",
+				     "fsl,sec-v5.0-rtic-memory",
+				     "fsl,sec-v4.0-rtic-memory";
+			reg = <0x20 0x20 0x200 0x80>;
+		};
+
+		rtic_c: rtic-c@40 {
+			compatible = "fsl,sec-v5.2-rtic-memory",
+				     "fsl,sec-v5.0-rtic-memory",
+				     "fsl,sec-v4.0-rtic-memory";
+			reg = <0x40 0x20 0x300 0x80>;
+		};
+
+		rtic_d: rtic-d@60 {
+			compatible = "fsl,sec-v5.2-rtic-memory",
+				     "fsl,sec-v5.0-rtic-memory",
+				     "fsl,sec-v4.0-rtic-memory";
+			reg = <0x60 0x20 0x500 0x80>;
+		};
+	};
+};
+
+sec_mon: sec_mon@314000 {
+	compatible = "fsl,sec-v5.2-mon", "fsl,sec-v5.0-mon", "fsl,sec-v4.0-mon";
+	reg = <0x314000 0x1000>;
+	interrupts = <93 2 0 0>;
+};
diff --git a/arch/powerpc/boot/dts/mpc8536ds.dtsi b/arch/powerpc/boot/dts/mpc8536ds.dtsi
index d304a2d..7c3dde8 100644
--- a/arch/powerpc/boot/dts/mpc8536ds.dtsi
+++ b/arch/powerpc/boot/dts/mpc8536ds.dtsi
@@ -132,6 +132,10 @@
 			reg = <0x68>;
 			interrupts = <0 0x1 0 0>;
 		};
+		adt7461@4c {
+			compatible = "adi,adt7461";
+			reg = <0x4c>;
+		};
 	};
 
 	spi@7000 {
diff --git a/arch/powerpc/boot/dts/mpc8540ads.dts b/arch/powerpc/boot/dts/mpc8540ads.dts
index f99fb11..2d31863 100644
--- a/arch/powerpc/boot/dts/mpc8540ads.dts
+++ b/arch/powerpc/boot/dts/mpc8540ads.dts
@@ -11,6 +11,8 @@
 
 /dts-v1/;
 
+/include/ "fsl/e500v2_power_isa.dtsi"
+
 / {
 	model = "MPC8540ADS";
 	compatible = "MPC8540ADS", "MPC85xxADS";
diff --git a/arch/powerpc/boot/dts/mpc8541cds.dts b/arch/powerpc/boot/dts/mpc8541cds.dts
index 0f5e939..1c03c26 100644
--- a/arch/powerpc/boot/dts/mpc8541cds.dts
+++ b/arch/powerpc/boot/dts/mpc8541cds.dts
@@ -11,6 +11,8 @@
 
 /dts-v1/;
 
+/include/ "fsl/e500v2_power_isa.dtsi"
+
 / {
 	model = "MPC8541CDS";
 	compatible = "MPC8541CDS", "MPC85xxCDS";
diff --git a/arch/powerpc/boot/dts/mpc8544ds.dts b/arch/powerpc/boot/dts/mpc8544ds.dts
index e934987..ed38874c 100644
--- a/arch/powerpc/boot/dts/mpc8544ds.dts
+++ b/arch/powerpc/boot/dts/mpc8544ds.dts
@@ -20,8 +20,10 @@
 		reg = <0 0 0 0>;	// Filled by U-Boot
 	};
 
-	lbc: localbus@e0005000 {
+	board_lbc: lbc: localbus@e0005000 {
 		reg = <0 0xe0005000 0 0x1000>;
+
+		ranges = <0x0 0x0 0x0 0xff800000 0x800000>;
 	};
 
 	board_soc: soc: soc8544@e0000000 {
diff --git a/arch/powerpc/boot/dts/mpc8544ds.dtsi b/arch/powerpc/boot/dts/mpc8544ds.dtsi
index 77ebc9f..b219d03 100644
--- a/arch/powerpc/boot/dts/mpc8544ds.dtsi
+++ b/arch/powerpc/boot/dts/mpc8544ds.dtsi
@@ -32,6 +32,45 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+&board_lbc {
+	nor@0,0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "cfi-flash";
+		reg = <0x0 0x0 0x800000>;
+		bank-width = <2>;
+		device-width = <1>;
+
+		partition@0 {
+			reg = <0x0 0x10000>;
+			label = "dtb-nor";
+		};
+
+		partition@20000 {
+			reg = <0x20000 0x30000>;
+			label = "diagnostic-nor";
+			read-only;
+		};
+
+		partition@200000 {
+			reg = <0x200000 0x200000>;
+			label = "dink-nor";
+			read-only;
+		};
+
+		partition@400000 {
+			reg = <0x400000 0x380000>;
+			label = "kernel-nor";
+		};
+
+		partition@780000 {
+			reg = <0x780000 0x80000>;
+			label = "u-boot-nor";
+			read-only;
+		};
+	};
+};
+
 &board_soc {
 	enet0: ethernet@24000 {
 		phy-handle = <&phy0>;
diff --git a/arch/powerpc/boot/dts/mpc8555cds.dts b/arch/powerpc/boot/dts/mpc8555cds.dts
index fe10438..36a7ea1 100644
--- a/arch/powerpc/boot/dts/mpc8555cds.dts
+++ b/arch/powerpc/boot/dts/mpc8555cds.dts
@@ -11,6 +11,8 @@
 
 /dts-v1/;
 
+/include/ "fsl/e500v2_power_isa.dtsi"
+
 / {
 	model = "MPC8555CDS";
 	compatible = "MPC8555CDS", "MPC85xxCDS";
diff --git a/arch/powerpc/boot/dts/mpc8560ads.dts b/arch/powerpc/boot/dts/mpc8560ads.dts
index 6e85e1b..1a43f5a 100644
--- a/arch/powerpc/boot/dts/mpc8560ads.dts
+++ b/arch/powerpc/boot/dts/mpc8560ads.dts
@@ -11,6 +11,8 @@
 
 /dts-v1/;
 
+/include/ "fsl/e500v2_power_isa.dtsi"
+
 / {
 	model = "MPC8560ADS";
 	compatible = "MPC8560ADS", "MPC85xxADS";
diff --git a/arch/powerpc/boot/dts/o2d.dts b/arch/powerpc/boot/dts/o2d.dts
new file mode 100644
index 0000000..9f6dd4d
--- /dev/null
+++ b/arch/powerpc/boot/dts/o2d.dts
@@ -0,0 +1,47 @@
+/*
+ * O2D Device Tree Source
+ *
+ * Copyright (C) 2012 DENX Software Engineering
+ * Anatolij Gustschin <agust@denx.de>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+/include/ "o2d.dtsi"
+
+/ {
+	model = "ifm,o2d";
+	compatible = "ifm,o2d";
+
+	memory {
+		reg = <0x00000000 0x08000000>;  // 128MB
+	};
+
+	localbus {
+		ranges = <0 0 0xfc000000 0x02000000
+			  3 0 0xe3000000 0x00100000>;
+
+		flash@0,0 {
+			compatible = "cfi-flash";
+			reg = <0 0 0x02000000>;
+			bank-width = <2>;
+			device-width = <2>;
+			#size-cells = <1>;
+			#address-cells = <1>;
+
+			partition@60000 {
+				label = "kernel";
+				reg = <0x00060000 0x00260000>;
+				read-only;
+			};
+			/* o2d specific partitions */
+			partition@2c0000 {
+				label = "o2d user defined";
+				reg = <0x002c0000 0x01d40000>;
+			};
+		};
+	};
+};
diff --git a/arch/powerpc/boot/dts/o2d.dtsi b/arch/powerpc/boot/dts/o2d.dtsi
new file mode 100644
index 0000000..3444eb8
--- /dev/null
+++ b/arch/powerpc/boot/dts/o2d.dtsi
@@ -0,0 +1,139 @@
+/*
+ * O2D base Device Tree Source
+ *
+ * Copyright (C) 2012 DENX Software Engineering
+ * Anatolij Gustschin <agust@denx.de>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+/include/ "mpc5200b.dtsi"
+
+/ {
+	model = "ifm,o2d";
+	compatible = "ifm,o2d";
+
+	memory {
+		reg = <0x00000000 0x04000000>;	// 64MB
+	};
+
+	soc5200@f0000000 {
+
+		gpio_simple: gpio@b00 {
+		};
+
+		timer@600 {	// General Purpose Timer
+			#gpio-cells = <2>;
+			gpio-controller;
+			fsl,has-wdt;
+			fsl,wdt-on-boot = <0>;
+		};
+
+		timer@610 {
+			#gpio-cells = <2>;
+			gpio-controller;
+		};
+
+		timer7: timer@670 {
+		};
+
+		rtc@800 {
+			status = "disabled";
+		};
+
+		psc@2000 {		// PSC1
+			compatible = "fsl,mpc5200b-psc-spi","fsl,mpc5200-psc-spi";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cell-index = <0>;
+
+			spidev@0 {
+				compatible = "spidev";
+				spi-max-frequency = <250000>;
+				reg = <0>;
+			};
+		};
+
+		psc@2200 {		// PSC2
+			status = "disabled";
+		};
+
+		psc@2400 {		// PSC3
+			status = "disabled";
+		};
+
+		psc@2600 {		// PSC4
+			compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
+		};
+
+		psc@2800 {		// PSC5
+			compatible = "fsl,mpc5200b-psc-uart","fsl,mpc5200-psc-uart";
+		};
+
+		psc@2c00 {		// PSC6
+			status = "disabled";
+		};
+
+		ethernet@3000 {
+			phy-handle = <&phy0>;
+		};
+
+		mdio@3000 {
+			phy0: ethernet-phy@0 {
+				reg = <0>;
+			};
+		};
+
+		sclpc@3c00 {
+			compatible = "fsl,mpc5200-lpbfifo";
+			reg = <0x3c00 0x60>;
+			interrupts = <3 23 0>;
+		};
+	};
+
+	localbus {
+		ranges = <0 0 0xff000000 0x01000000
+			  3 0 0xe3000000 0x00100000>;
+
+		// flash device at LocalPlus Bus CS0
+		flash@0,0 {
+			compatible = "cfi-flash";
+			reg = <0 0 0x01000000>;
+			bank-width = <1>;
+			device-width = <2>;
+			#size-cells = <1>;
+			#address-cells = <1>;
+			no-unaligned-direct-access;
+
+			/* common layout for all machines */
+			partition@0 {
+				label = "u-boot";
+				reg = <0x00000000 0x00040000>;
+				read-only;
+			};
+			partition@40000 {
+				label = "env";
+				reg = <0x00040000 0x00020000>;
+				read-only;
+			};
+		};
+
+		csi@3,0 {
+			compatible = "ifm,o2d-csi";
+			reg = <3 0 0x00100000>;
+			ifm,csi-clk-handle = <&timer7>;
+			gpios = <&gpio_simple 23 0	/* imag_capture */
+				 &gpio_simple 26 0	/* imag_reset */
+				 &gpio_simple 29 0>;	/* imag_master_en */
+
+			interrupts = <1 1 2>;		/* IRQ1, edge falling */
+
+			ifm,csi-addr-bus-width = <24>;
+			ifm,csi-data-bus-width = <8>;
+			ifm,csi-wait-cycles = <0>;
+		};
+	};
+};
diff --git a/arch/powerpc/boot/dts/o2d300.dts b/arch/powerpc/boot/dts/o2d300.dts
new file mode 100644
index 0000000..29affe0
--- /dev/null
+++ b/arch/powerpc/boot/dts/o2d300.dts
@@ -0,0 +1,52 @@
+/*
+ * O2D300 Device Tree Source
+ *
+ * Copyright (C) 2012 DENX Software Engineering
+ * Anatolij Gustschin <agust@denx.de>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+/include/ "o2d.dtsi"
+
+/ {
+	model = "ifm,o2d300";
+	compatible = "ifm,o2d";
+
+	localbus {
+		ranges = <0 0 0xfc000000 0x02000000
+			  3 0 0xe3000000 0x00100000>;
+		flash@0,0 {
+			compatible = "cfi-flash";
+			reg = <0 0 0x02000000>;
+			bank-width = <2>;
+			device-width = <2>;
+			#size-cells = <1>;
+			#address-cells = <1>;
+
+			partition@40000 {
+				label = "env_1";
+				reg = <0x00040000 0x00020000>;
+				read-only;
+			};
+			partition@60000 {
+				label = "env_2";
+				reg = <0x00060000 0x00020000>;
+				read-only;
+			};
+			partition@80000 {
+				label = "kernel";
+				reg = <0x00080000 0x00260000>;
+				read-only;
+			};
+			/* o2d300 specific partitions */
+			partition@2e0000 {
+				label = "o2d300 user defined";
+				reg = <0x002e0000 0x01d20000>;
+			};
+		};
+	};
+};
diff --git a/arch/powerpc/boot/dts/o2dnt2.dts b/arch/powerpc/boot/dts/o2dnt2.dts
new file mode 100644
index 0000000..a0f5b97
--- /dev/null
+++ b/arch/powerpc/boot/dts/o2dnt2.dts
@@ -0,0 +1,48 @@
+/*
+ * O2DNT2 Device Tree Source
+ *
+ * Copyright (C) 2012 DENX Software Engineering
+ * Anatolij Gustschin <agust@denx.de>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+/include/ "o2d.dtsi"
+
+/ {
+	model = "ifm,o2dnt2";
+	compatible = "ifm,o2d";
+
+	memory {
+		reg = <0x00000000 0x08000000>;  // 128MB
+	};
+
+	localbus {
+		ranges = <0 0 0xfc000000 0x02000000
+			  3 0 0xe3000000 0x00100000>;
+
+		flash@0,0 {
+			compatible = "cfi-flash";
+			reg = <0 0 0x02000000>;
+			bank-width = <2>;
+			device-width = <2>;
+			#size-cells = <1>;
+			#address-cells = <1>;
+
+			partition@60000 {
+				label = "kernel";
+				reg = <0x00060000 0x00260000>;
+				read-only;
+			};
+
+			/* o2dnt2 specific partitions */
+			partition@2c0000 {
+				label = "o2dnt2 user defined";
+				reg = <0x002c0000 0x01d40000>;
+			};
+		};
+	};
+};
diff --git a/arch/powerpc/boot/dts/o2i.dts b/arch/powerpc/boot/dts/o2i.dts
new file mode 100644
index 0000000..e3cc99d
--- /dev/null
+++ b/arch/powerpc/boot/dts/o2i.dts
@@ -0,0 +1,33 @@
+/*
+ * O2I Device Tree Source
+ *
+ * Copyright (C) 2012 DENX Software Engineering
+ * Anatolij Gustschin <agust@denx.de>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+/include/ "o2d.dtsi"
+
+/ {
+	model = "ifm,o2i";
+	compatible = "ifm,o2d";
+
+	localbus {
+		flash@0,0 {
+			partition@60000 {
+				label = "kernel";
+				reg = <0x00060000 0x00260000>;
+				read-only;
+			};
+			/* o2i specific partitions */
+			partition@2c0000 {
+				label = "o2i user defined";
+				reg = <0x002c0000 0x00d40000>;
+			};
+		};
+	};
+};
diff --git a/arch/powerpc/boot/dts/o2mnt.dts b/arch/powerpc/boot/dts/o2mnt.dts
new file mode 100644
index 0000000..d91859a
--- /dev/null
+++ b/arch/powerpc/boot/dts/o2mnt.dts
@@ -0,0 +1,33 @@
+/*
+ * O2MNT Device Tree Source
+ *
+ * Copyright (C) 2012 DENX Software Engineering
+ * Anatolij Gustschin <agust@denx.de>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+/include/ "o2d.dtsi"
+
+/ {
+	model = "ifm,o2mnt";
+	compatible = "ifm,o2d";
+
+	localbus {
+		flash@0,0 {
+			partition@60000 {
+				label = "kernel";
+				reg = <0x00060000 0x00260000>;
+				read-only;
+			};
+			/* add o2mnt specific partitions */
+			partition@2c0000 {
+				label = "o2mnt user defined";
+				reg = <0x002c0000 0x00d40000>;
+			};
+		};
+	};
+};
diff --git a/arch/powerpc/boot/dts/o3dnt.dts b/arch/powerpc/boot/dts/o3dnt.dts
new file mode 100644
index 0000000..acce493
--- /dev/null
+++ b/arch/powerpc/boot/dts/o3dnt.dts
@@ -0,0 +1,48 @@
+/*
+ * O3DNT Device Tree Source
+ *
+ * Copyright (C) 2012 DENX Software Engineering
+ * Anatolij Gustschin <agust@denx.de>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+/include/ "o2d.dtsi"
+
+/ {
+	model = "ifm,o3dnt";
+	compatible = "ifm,o2d";
+
+	memory {
+		reg = <0x00000000 0x04000000>;  // 64MB
+	};
+
+	localbus {
+		ranges = <0 0 0xfc000000 0x01000000
+			  3 0 0xe3000000 0x00100000>;
+
+		flash@0,0 {
+			compatible = "cfi-flash";
+			reg = <0 0 0x01000000>;
+			bank-width = <2>;
+			device-width = <2>;
+			#size-cells = <1>;
+			#address-cells = <1>;
+
+			partition@60000 {
+				label = "kernel";
+				reg = <0x00060000 0x00260000>;
+				read-only;
+			};
+
+			/* o3dnt specific partitions */
+			partition@2c0000 {
+				label = "o3dnt user defined";
+				reg = <0x002c0000 0x00d40000>;
+			};
+		};
+	};
+};
diff --git a/arch/powerpc/boot/dts/p1020rdb_camp_core0.dts b/arch/powerpc/boot/dts/p1020rdb_camp_core0.dts
deleted file mode 100644
index 41b4585..0000000
--- a/arch/powerpc/boot/dts/p1020rdb_camp_core0.dts
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * P1020 RDB  Core0 Device Tree Source in CAMP mode.
- *
- * In CAMP mode, each core needs to have its own dts. Only mpic and L2 cache
- * can be shared, all the other devices must be assigned to one core only.
- * This dts file allows core0 to have memory, l2, i2c, spi, gpio, tdm, dma, usb,
- * eth1, eth2, sdhc, crypto, global-util, message, pci0, pci1, msi.
- *
- * Please note to add "-b 0" for core0's dts compiling.
- *
- * Copyright 2011 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/ "p1020rdb.dts"
-
-/ {
-	model = "fsl,P1020RDB";
-	compatible = "fsl,P1020RDB", "fsl,MPC85XXRDB-CAMP";
-
-	aliases {
-		ethernet1 = &enet1;
-		ethernet2 = &enet2;
-		serial0 = &serial0;
-		pci0 = &pci0;
-		pci1 = &pci1;
-	};
-
-	cpus {
-		PowerPC,P1020@1 {
-			status = "disabled";
-		};
-	};
-
-	memory {
-		device_type = "memory";
-	};
-
-	localbus@ffe05000 {
-		status = "disabled";
-	};
-
-	soc@ffe00000 {
-		serial1: serial@4600 {
-			status = "disabled";
-		};
-
-		enet0: ethernet@b0000 {
-			status = "disabled";
-		};
-
-		mpic: pic@40000 {
-			protected-sources = <
-			42 29 30 34	/* serial1, enet0-queue-group0 */
-			17 18 24 45	/* enet0-queue-group1, crypto */
-			>;
-		};
-	};
-};
diff --git a/arch/powerpc/boot/dts/p1020rdb_camp_core1.dts b/arch/powerpc/boot/dts/p1020rdb_camp_core1.dts
deleted file mode 100644
index 5174538..0000000
--- a/arch/powerpc/boot/dts/p1020rdb_camp_core1.dts
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * P1020 RDB Core1 Device Tree Source in CAMP mode.
- *
- * In CAMP mode, each core needs to have its own dts. Only mpic and L2 cache
- * can be shared, all the other devices must be assigned to one core only.
- * This dts allows core1 to have l2, eth0, crypto.
- *
- * Please note to add "-b 1" for core1's dts compiling.
- *
- * Copyright 2011 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/ "p1020rdb.dts"
-
-/ {
-	model = "fsl,P1020RDB";
-	compatible = "fsl,P1020RDB", "fsl,MPC85XXRDB-CAMP";
-
-	aliases {
-		ethernet0 = &enet0;
-		serial0 = &serial1;
-		};
-
-	cpus {
-		PowerPC,P1020@0 {
-			status = "disabled";
-		};
-	};
-
-	memory {
-		device_type = "memory";
-	};
-
-	localbus@ffe05000 {
-		status = "disabled";
-	};
-
-	soc@ffe00000 {
-		ecm-law@0 {
-			status = "disabled";
-		};
-
-		ecm@1000 {
-			status = "disabled";
-		};
-
-		memory-controller@2000 {
-			status = "disabled";
-		};
-
-		i2c@3000 {
-			status = "disabled";
-		};
-
-		i2c@3100 {
-			status = "disabled";
-		};
-
-		serial0: serial@4500 {
-			status = "disabled";
-		};
-
-		spi@7000 {
-			status = "disabled";
-		};
-
-		gpio: gpio-controller@f000 {
-			status = "disabled";
-		};
-
-		dma@21300 {
-			status = "disabled";
-		};
-
-		mdio@24000 {
-			status = "disabled";
-		};
-
-		mdio@25000 {
-			status = "disabled";
-		};
-
-		enet1: ethernet@b1000 {
-			status = "disabled";
-		};
-
-		enet2: ethernet@b2000 {
-			status = "disabled";
-		};
-
-		usb@22000 {
-			status = "disabled";
-		};
-
-		sdhci@2e000 {
-			status = "disabled";
-		};
-
-		mpic: pic@40000 {
-			protected-sources = <
-			16 		/* ecm, mem, L2, pci0, pci1 */
-			43 42 59	/* i2c, serial0, spi */
-			47 63 62 	/* gpio, tdm */
-			20 21 22 23	/* dma */
-			03 02 		/* mdio */
-			35 36 40	/* enet1-queue-group0 */
-			51 52 67	/* enet1-queue-group1 */
-			31 32 33	/* enet2-queue-group0 */
-			25 26 27	/* enet2-queue-group1 */
-			28 72 58 	/* usb, sdhci, crypto */
-			0xb0 0xb1 0xb2	/* message */
-			0xb3 0xb4 0xb5
-			0xb6 0xb7
-			0xe0 0xe1 0xe2	/* msi */
-			0xe3 0xe4 0xe5
-			0xe6 0xe7		/* sdhci, crypto , pci */
-			>;
-		};
-
-		msi@41600 {
-			status = "disabled";
-		};
-
-		global-utilities@e0000 {	//global utilities block
-			status = "disabled";
-		};
-	};
-
-	pci0: pcie@ffe09000 {
-		status = "disabled";
-	};
-
-	pci1: pcie@ffe0a000 {
-		status = "disabled";
-	};
-};
diff --git a/arch/powerpc/boot/dts/p1022ds.dtsi b/arch/powerpc/boot/dts/p1022ds.dtsi
index c3344b0..873da35 100644
--- a/arch/powerpc/boot/dts/p1022ds.dtsi
+++ b/arch/powerpc/boot/dts/p1022ds.dtsi
@@ -149,6 +149,10 @@
 			compatible = "dallas,ds1339";
 			reg = <0x68>;
 		};
+		adt7461@4c {
+			compatible = "adi,adt7461";
+			reg = <0x4c>;
+		};
 	};
 
 	spi@7000 {
diff --git a/arch/powerpc/boot/dts/p1022rdk.dts b/arch/powerpc/boot/dts/p1022rdk.dts
new file mode 100644
index 0000000..51d82de
--- /dev/null
+++ b/arch/powerpc/boot/dts/p1022rdk.dts
@@ -0,0 +1,188 @@
+/*
+ * P1022 RDK 32-bit Physical Address Map Device Tree Source
+ *
+ * Copyright 2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/include/ "fsl/p1022si-pre.dtsi"
+/ {
+	model = "fsl,P1022RDK";
+	compatible = "fsl,P1022RDK";
+
+	memory {
+		device_type = "memory";
+	};
+
+	board_lbc: lbc: localbus@ffe05000 {
+		/* The P1022 RDK does not have any localbus devices */
+		status = "disabled";
+	};
+
+	board_soc: soc: soc@ffe00000 {
+		ranges = <0x0 0x0 0xffe00000 0x100000>;
+
+		i2c@3100 {
+			wm8960:codec@1a {
+				compatible = "wlf,wm8960";
+				reg = <0x1a>;
+				/* MCLK source is a stand-alone oscillator */
+				clock-frequency = <12288000>;
+			};
+			rtc@68 {
+				compatible = "stm,m41t62";
+				reg = <0x68>;
+			};
+			adt7461@4c{
+				compatible = "adi,adt7461";
+				reg = <0x4c>;
+			};
+			zl6100@21{
+				compatible = "isil,zl6100";
+				reg = <0x21>;
+			};
+			zl6100@24{
+				compatible = "isil,zl6100";
+				reg = <0x24>;
+			};
+			zl6100@26{
+				compatible = "isil,zl6100";
+				reg = <0x26>;
+			};
+			zl6100@29{
+				compatible = "isil,zl6100";
+				reg = <0x29>;
+			};
+		};
+
+		spi@7000 {
+			flash@0 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				compatible = "spansion,m25p80";
+				reg = <0>;
+				spi-max-frequency = <1000000>;
+				partition@0 {
+					label = "full-spi-flash";
+					reg = <0x00000000 0x00100000>;
+				};
+			};
+		};
+
+		ssi@15000 {
+			fsl,mode = "i2s-slave";
+			codec-handle = <&wm8960>;
+		};
+
+		usb@22000 {
+			phy_type = "ulpi";
+		};
+
+		usb@23000 {
+			phy_type = "ulpi";
+		};
+
+		mdio@24000 {
+			phy0: ethernet-phy@0 {
+				interrupts = <3 1 0 0>;
+				reg = <0x1>;
+			};
+			phy1: ethernet-phy@1 {
+				interrupts = <9 1 0 0>;
+				reg = <0x2>;
+			};
+		};
+
+		mdio@25000 {
+			tbi0: tbi-phy@11 {
+				reg = <0x11>;
+				device_type = "tbi-phy";
+			};
+		};
+
+		ethernet@b0000 {
+			phy-handle = <&phy0>;
+			phy-connection-type = "rgmii-id";
+		};
+
+		ethernet@b1000 {
+			phy-handle = <&phy1>;
+			tbi-handle = <&tbi0>;
+			phy-connection-type = "sgmii";
+		};
+	};
+
+	pci0: pcie@ffe09000 {
+		ranges = <0x2000000 0x0 0xe0000000 0 0xa0000000 0x0 0x20000000
+			  0x1000000 0x0 0x00000000 0 0xffc10000 0x0 0x10000>;
+		reg = <0x0 0xffe09000 0 0x1000>;
+		pcie@0 {
+			ranges = <0x2000000 0x0 0xe0000000
+				  0x2000000 0x0 0xe0000000
+				  0x0 0x20000000
+
+				  0x1000000 0x0 0x0
+				  0x1000000 0x0 0x0
+				  0x0 0x100000>;
+		};
+	};
+
+	pci1: pcie@ffe0a000 {
+		ranges = <0x2000000 0x0 0xe0000000 0 0xc0000000 0x0 0x20000000
+			  0x1000000 0x0 0x00000000 0 0xffc20000 0x0 0x10000>;
+		reg = <0 0xffe0a000 0 0x1000>;
+		pcie@0 {
+			ranges = <0x2000000 0x0 0xe0000000
+				  0x2000000 0x0 0xe0000000
+				  0x0 0x20000000
+
+				  0x1000000 0x0 0x0
+				  0x1000000 0x0 0x0
+				  0x0 0x100000>;
+		};
+	};
+
+	pci2: pcie@ffe0b000 {
+		ranges = <0x2000000 0x0 0xe0000000 0 0x80000000 0x0 0x20000000
+			  0x1000000 0x0 0x00000000 0 0xffc00000 0x0 0x10000>;
+		reg = <0 0xffe0b000 0 0x1000>;
+		pcie@0 {
+			ranges = <0x2000000 0x0 0xe0000000
+				  0x2000000 0x0 0xe0000000
+				  0x0 0x20000000
+
+				  0x1000000 0x0 0x0
+				  0x1000000 0x0 0x0
+				  0x0 0x100000>;
+		};
+	};
+};
+
+/include/ "fsl/p1022si-post.dtsi"
diff --git a/arch/powerpc/boot/dts/p2020rdb_camp_core0.dts b/arch/powerpc/boot/dts/p2020rdb_camp_core0.dts
deleted file mode 100644
index 66aac86..0000000
--- a/arch/powerpc/boot/dts/p2020rdb_camp_core0.dts
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * P2020 RDB  Core0 Device Tree Source in CAMP mode.
- *
- * In CAMP mode, each core needs to have its own dts. Only mpic and L2 cache
- * can be shared, all the other devices must be assigned to one core only.
- * This dts file allows core0 to have memory, l2, i2c, spi, gpio, dma1, usb,
- * eth1, eth2, sdhc, crypto, global-util, pci0.
- *
- * Copyright 2009-2011 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/ "p2020rdb.dts"
-
-/ {
-	model = "fsl,P2020RDB";
-	compatible = "fsl,P2020RDB", "fsl,MPC85XXRDB-CAMP";
-
-	cpus {
-		PowerPC,P2020@1 {
-			status = "disabled";
-		};
-	};
-
-	localbus@ffe05000 {
-		status = "disabled";
-	};
-
-	soc@ffe00000 {
-		serial1: serial@4600 {
-			status = "disabled";
-		};
-
-		dma@c300 {
-			status = "disabled";
-		};
-
-		enet0: ethernet@24000 {
-			status = "disabled";
-		};
-
-		mpic: pic@40000 {
-			protected-sources = <
-			42 76 77 78 79 /* serial1 , dma2 */
-			29 30 34 26 /* enet0, pci1 */
-			0xe0 0xe1 0xe2 0xe3 /* msi */
-			0xe4 0xe5 0xe6 0xe7
-			>;
-		};
-
-		msi@41600 {
-			status = "disabled";
-		};
-	};
-
-	pci0: pcie@ffe08000 {
-		status = "disabled";
-	};
-
-	pci2: pcie@ffe0a000 {
-		status = "disabled";
-	};
-};
diff --git a/arch/powerpc/boot/dts/p2020rdb_camp_core1.dts b/arch/powerpc/boot/dts/p2020rdb_camp_core1.dts
deleted file mode 100644
index 9bd8ef4..0000000
--- a/arch/powerpc/boot/dts/p2020rdb_camp_core1.dts
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * P2020 RDB Core1 Device Tree Source in CAMP mode.
- *
- * In CAMP mode, each core needs to have its own dts. Only mpic and L2 cache
- * can be shared, all the other devices must be assigned to one core only.
- * This dts allows core1 to have l2, dma2, eth0, pci1, msi.
- *
- * Please note to add "-b 1" for core1's dts compiling.
- *
- * Copyright 2009-2011 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/ "p2020rdb.dts"
-
-/ {
-	model = "fsl,P2020RDB";
-	compatible = "fsl,P2020RDB", "fsl,MPC85XXRDB-CAMP";
-
-	cpus {
-		PowerPC,P2020@0 {
-			status = "disabled";
-		};
-	};
-
-	localbus@ffe05000 {
-		status = "disabled";
-	};
-
-	soc@ffe00000 {
-		ecm-law@0 {
-			status = "disabled";
-		};
-
-		ecm@1000 {
-			status = "disabled";
-		};
-
-		memory-controller@2000 {
-			status = "disabled";
-		};
-
-		i2c@3000 {
-			status = "disabled";
-		};
-
-		i2c@3100 {
-			status = "disabled";
-		};
-
-		serial0: serial@4500 {
-			status = "disabled";
-		};
-
-		spi@7000 {
-			status = "disabled";
-		};
-
-		gpio: gpio-controller@f000 {
-			status = "disabled";
-		};
-
-		dma@21300 {
-			status = "disabled";
-		};
-
-		usb@22000 {
-			status = "disabled";
-		};
-
-		mdio@24520 {
-			status = "disabled";
-		};
-
-		mdio@25520 {
-			status = "disabled";
-		};
-
-		mdio@26520 {
-			status = "disabled";
-		};
-
-		enet1: ethernet@25000 {
-			status = "disabled";
-		};
-
-		enet2: ethernet@26000 {
-			status = "disabled";
-		};
-
-		sdhci@2e000 {
-			status = "disabled";
-		};
-
-		crypto@30000 {
-			status = "disabled";
-		};
-
-		mpic: pic@40000 {
-			protected-sources = <
-			17 18 43 42 59 47 /*ecm, mem, i2c, serial0, spi,gpio */
-			16 20 21 22 23 28 	/* L2, dma1, USB */
-			03 35 36 40 31 32 33 	/* mdio, enet1, enet2 */
-			72 45 58 25 		/* sdhci, crypto , pci */
-			>;
-		};
-
-		global-utilities@e0000 {	//global utilities block
-			status = "disabled";
-		};
-
-	};
-
-	pci0: pcie@ffe08000 {
-		status = "disabled";
-	};
-
-	pci1: pcie@ffe09000 {
-		status = "disabled";
-	};
-};
diff --git a/arch/powerpc/boot/dts/p2041rdb.dts b/arch/powerpc/boot/dts/p2041rdb.dts
index baab034..d97ad74 100644
--- a/arch/powerpc/boot/dts/p2041rdb.dts
+++ b/arch/powerpc/boot/dts/p2041rdb.dts
@@ -94,6 +94,10 @@
 				compatible = "pericom,pt7c4338";
 				reg = <0x68>;
 			};
+			adt7461@4c {
+				compatible = "adi,adt7461";
+				reg = <0x4c>;
+			};
 		};
 
 		i2c@118100 {
diff --git a/arch/powerpc/boot/dts/p3041ds.dts b/arch/powerpc/boot/dts/p3041ds.dts
index 6cdcadc..2fed3bc 100644
--- a/arch/powerpc/boot/dts/p3041ds.dts
+++ b/arch/powerpc/boot/dts/p3041ds.dts
@@ -98,6 +98,10 @@
 				reg = <0x68>;
 				interrupts = <0x1 0x1 0 0>;
 			};
+			adt7461@4c {
+				compatible = "adi,adt7461";
+				reg = <0x4c>;
+			};
 		};
 	};
 
diff --git a/arch/powerpc/boot/dts/p4080ds.dts b/arch/powerpc/boot/dts/p4080ds.dts
index 3e20460..1cf6148 100644
--- a/arch/powerpc/boot/dts/p4080ds.dts
+++ b/arch/powerpc/boot/dts/p4080ds.dts
@@ -96,6 +96,10 @@
 				reg = <0x68>;
 				interrupts = <0x1 0x1 0 0>;
 			};
+			adt7461@4c {
+				compatible = "adi,adt7461";
+				reg = <0x4c>;
+			};
 		};
 
 		usb0: usb@210000 {
diff --git a/arch/powerpc/boot/dts/p5020ds.dts b/arch/powerpc/boot/dts/p5020ds.dts
index 27c07ed..2869fea 100644
--- a/arch/powerpc/boot/dts/p5020ds.dts
+++ b/arch/powerpc/boot/dts/p5020ds.dts
@@ -98,6 +98,10 @@
 				reg = <0x68>;
 				interrupts = <0x1 0x1 0 0>;
 			};
+			adt7461@4c {
+				compatible = "adi,adt7461";
+				reg = <0x4c>;
+			};
 		};
 	};
 
diff --git a/arch/powerpc/boot/dts/p5040ds.dts b/arch/powerpc/boot/dts/p5040ds.dts
new file mode 100644
index 0000000..860b5cc
--- /dev/null
+++ b/arch/powerpc/boot/dts/p5040ds.dts
@@ -0,0 +1,207 @@
+/*
+ * P5040DS Device Tree Source
+ *
+ * Copyright 2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * This software is provided by Freescale Semiconductor "as is" and any
+ * express or implied warranties, including, but not limited to, the implied
+ * warranties of merchantability and fitness for a particular purpose are
+ * disclaimed. In no event shall Freescale Semiconductor be liable for any
+ * direct, indirect, incidental, special, exemplary, or consequential damages
+ * (including, but not limited to, procurement of substitute goods or services;
+ * loss of use, data, or profits; or business interruption) however caused and
+ * on any theory of liability, whether in contract, strict liability, or tort
+ * (including negligence or otherwise) arising in any way out of the use of this
+ * software, even if advised of the possibility of such damage.
+ */
+
+/include/ "fsl/p5040si-pre.dtsi"
+
+/ {
+	model = "fsl,P5040DS";
+	compatible = "fsl,P5040DS";
+	#address-cells = <2>;
+	#size-cells = <2>;
+	interrupt-parent = <&mpic>;
+
+	memory {
+		device_type = "memory";
+	};
+
+	dcsr: dcsr@f00000000 {
+		ranges = <0x00000000 0xf 0x00000000 0x01008000>;
+	};
+
+	soc: soc@ffe000000 {
+		ranges = <0x00000000 0xf 0xfe000000 0x1000000>;
+		reg = <0xf 0xfe000000 0 0x00001000>;
+		spi@110000 {
+			flash@0 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				compatible = "spansion,s25sl12801";
+				reg = <0>;
+				spi-max-frequency = <40000000>; /* input clock */
+				partition@u-boot {
+					label = "u-boot";
+					reg = <0x00000000 0x00100000>;
+				};
+				partition@kernel {
+					label = "kernel";
+					reg = <0x00100000 0x00500000>;
+				};
+				partition@dtb {
+					label = "dtb";
+					reg = <0x00600000 0x00100000>;
+				};
+				partition@fs {
+					label = "file system";
+					reg = <0x00700000 0x00900000>;
+				};
+			};
+		};
+
+		i2c@118100 {
+			eeprom@51 {
+				compatible = "at24,24c256";
+				reg = <0x51>;
+			};
+			eeprom@52 {
+				compatible = "at24,24c256";
+				reg = <0x52>;
+			};
+		};
+
+		i2c@119100 {
+			rtc@68 {
+				compatible = "dallas,ds3232";
+				reg = <0x68>;
+				interrupts = <0x1 0x1 0 0>;
+			};
+			adt7461@4c {
+				compatible = "adi,adt7461";
+				reg = <0x4c>;
+			};
+		};
+	};
+
+	lbc: localbus@ffe124000 {
+		reg = <0xf 0xfe124000 0 0x1000>;
+		ranges = <0 0 0xf 0xe8000000 0x08000000
+			  2 0 0xf 0xffa00000 0x00040000
+			  3 0 0xf 0xffdf0000 0x00008000>;
+
+		flash@0,0 {
+			compatible = "cfi-flash";
+			reg = <0 0 0x08000000>;
+			bank-width = <2>;
+			device-width = <2>;
+		};
+
+		nand@2,0 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "fsl,elbc-fcm-nand";
+			reg = <0x2 0x0 0x40000>;
+
+			partition@0 {
+				label = "NAND U-Boot Image";
+				reg = <0x0 0x02000000>;
+			};
+
+			partition@2000000 {
+				label = "NAND Root File System";
+				reg = <0x02000000 0x10000000>;
+			};
+
+			partition@12000000 {
+				label = "NAND Compressed RFS Image";
+				reg = <0x12000000 0x08000000>;
+			};
+
+			partition@1a000000 {
+				label = "NAND Linux Kernel Image";
+				reg = <0x1a000000 0x04000000>;
+			};
+
+			partition@1e000000 {
+				label = "NAND DTB Image";
+				reg = <0x1e000000 0x01000000>;
+			};
+
+			partition@1f000000 {
+				label = "NAND Writable User area";
+				reg = <0x1f000000 0x01000000>;
+			};
+		};
+
+		board-control@3,0 {
+			compatible = "fsl,p5040ds-fpga", "fsl,fpga-ngpixis";
+			reg = <3 0 0x40>;
+		};
+	};
+
+	pci0: pcie@ffe200000 {
+		reg = <0xf 0xfe200000 0 0x1000>;
+		ranges = <0x02000000 0 0xe0000000 0xc 0x00000000 0x0 0x20000000
+			  0x01000000 0 0x00000000 0xf 0xf8000000 0x0 0x00010000>;
+		pcie@0 {
+			ranges = <0x02000000 0 0xe0000000
+				  0x02000000 0 0xe0000000
+				  0 0x20000000
+
+				  0x01000000 0 0x00000000
+				  0x01000000 0 0x00000000
+				  0 0x00010000>;
+		};
+	};
+
+	pci1: pcie@ffe201000 {
+		reg = <0xf 0xfe201000 0 0x1000>;
+		ranges = <0x02000000 0x0 0xe0000000 0xc 0x20000000 0x0 0x20000000
+			  0x01000000 0x0 0x00000000 0xf 0xf8010000 0x0 0x00010000>;
+		pcie@0 {
+			ranges = <0x02000000 0 0xe0000000
+				  0x02000000 0 0xe0000000
+				  0 0x20000000
+
+				  0x01000000 0 0x00000000
+				  0x01000000 0 0x00000000
+				  0 0x00010000>;
+		};
+	};
+
+	pci2: pcie@ffe202000 {
+		reg = <0xf 0xfe202000 0 0x1000>;
+		ranges = <0x02000000 0 0xe0000000 0xc 0x40000000 0 0x20000000
+			  0x01000000 0 0x00000000 0xf 0xf8020000 0 0x00010000>;
+		pcie@0 {
+			ranges = <0x02000000 0 0xe0000000
+				  0x02000000 0 0xe0000000
+				  0 0x20000000
+
+				  0x01000000 0 0x00000000
+				  0x01000000 0 0x00000000
+				  0 0x00010000>;
+		};
+	};
+};
+
+/include/ "fsl/p5040si-post.dtsi"
diff --git a/arch/powerpc/configs/83xx/mpc8313_rdb_defconfig b/arch/powerpc/configs/83xx/mpc8313_rdb_defconfig
index 126ef1b..e4ad2e2 100644
--- a/arch/powerpc/configs/83xx/mpc8313_rdb_defconfig
+++ b/arch/powerpc/configs/83xx/mpc8313_rdb_defconfig
@@ -38,7 +38,6 @@ CONFIG_MTD_CFI=y
 CONFIG_MTD_CFI_AMDSTD=y
 CONFIG_MTD_PHYSMAP_OF=y
 CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_VERIFY_WRITE=y
 CONFIG_MTD_NAND_FSL_ELBC=y
 CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
diff --git a/arch/powerpc/configs/83xx/mpc8315_rdb_defconfig b/arch/powerpc/configs/83xx/mpc8315_rdb_defconfig
index abcf00a..34ff568 100644
--- a/arch/powerpc/configs/83xx/mpc8315_rdb_defconfig
+++ b/arch/powerpc/configs/83xx/mpc8315_rdb_defconfig
@@ -37,7 +37,6 @@ CONFIG_MTD_CFI=y
 CONFIG_MTD_CFI_AMDSTD=y
 CONFIG_MTD_PHYSMAP_OF=y
 CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_VERIFY_WRITE=y
 CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
diff --git a/arch/powerpc/configs/85xx/p1023rds_defconfig b/arch/powerpc/configs/85xx/p1023rds_defconfig
index 26e541c..b80bcc6 100644
--- a/arch/powerpc/configs/85xx/p1023rds_defconfig
+++ b/arch/powerpc/configs/85xx/p1023rds_defconfig
@@ -112,6 +112,12 @@ CONFIG_SND=y
 CONFIG_SND_MIXER_OSS=y
 CONFIG_SND_PCM_OSS=y
 # CONFIG_SND_SUPPORT_OLD_API is not set
+CONFIG_USB=y
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_MON=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_FSL=y
+CONFIG_USB_STORAGE=y
 CONFIG_EDAC=y
 CONFIG_EDAC_MM_EDAC=y
 CONFIG_RTC_CLASS=y
diff --git a/arch/powerpc/configs/corenet32_smp_defconfig b/arch/powerpc/configs/corenet32_smp_defconfig
index 8b3d57c..1c0f243 100644
--- a/arch/powerpc/configs/corenet32_smp_defconfig
+++ b/arch/powerpc/configs/corenet32_smp_defconfig
@@ -27,6 +27,7 @@ CONFIG_P2041_RDB=y
 CONFIG_P3041_DS=y
 CONFIG_P4080_DS=y
 CONFIG_P5020_DS=y
+CONFIG_P5040_DS=y
 CONFIG_HIGHMEM=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 CONFIG_BINFMT_MISC=m
diff --git a/arch/powerpc/configs/corenet64_smp_defconfig b/arch/powerpc/configs/corenet64_smp_defconfig
index 0516e22..88fa5c4 100644
--- a/arch/powerpc/configs/corenet64_smp_defconfig
+++ b/arch/powerpc/configs/corenet64_smp_defconfig
@@ -23,6 +23,7 @@ CONFIG_MODVERSIONS=y
 CONFIG_PARTITION_ADVANCED=y
 CONFIG_MAC_PARTITION=y
 CONFIG_P5020_DS=y
+CONFIG_P5040_DS=y
 # CONFIG_PPC_OF_BOOT_TRAMPOLINE is not set
 CONFIG_BINFMT_MISC=m
 CONFIG_IRQ_ALL_CPUS=y
diff --git a/arch/powerpc/configs/mpc83xx_defconfig b/arch/powerpc/configs/mpc83xx_defconfig
index 9352e44..09116c6 100644
--- a/arch/powerpc/configs/mpc83xx_defconfig
+++ b/arch/powerpc/configs/mpc83xx_defconfig
@@ -50,7 +50,6 @@ CONFIG_MTD_CFI=y
 CONFIG_MTD_CFI_AMDSTD=y
 CONFIG_MTD_PHYSMAP_OF=y
 CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_VERIFY_WRITE=y
 CONFIG_MTD_NAND_FSL_ELBC=y
 CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
diff --git a/arch/powerpc/configs/mpc85xx_defconfig b/arch/powerpc/configs/mpc85xx_defconfig
index 8b5bda2..cf815e8 100644
--- a/arch/powerpc/configs/mpc85xx_defconfig
+++ b/arch/powerpc/configs/mpc85xx_defconfig
@@ -30,6 +30,7 @@ CONFIG_MPC85xx_DS=y
 CONFIG_MPC85xx_RDB=y
 CONFIG_P1010_RDB=y
 CONFIG_P1022_DS=y
+CONFIG_P1022_RDK=y
 CONFIG_P1023_RDS=y
 CONFIG_SOCRATES=y
 CONFIG_KSI8560=y
diff --git a/arch/powerpc/configs/mpc85xx_smp_defconfig b/arch/powerpc/configs/mpc85xx_smp_defconfig
index b0974e7..502cd9e 100644
--- a/arch/powerpc/configs/mpc85xx_smp_defconfig
+++ b/arch/powerpc/configs/mpc85xx_smp_defconfig
@@ -32,6 +32,7 @@ CONFIG_MPC85xx_DS=y
 CONFIG_MPC85xx_RDB=y
 CONFIG_P1010_RDB=y
 CONFIG_P1022_DS=y
+CONFIG_P1022_RDK=y
 CONFIG_P1023_RDS=y
 CONFIG_SOCRATES=y
 CONFIG_KSI8560=y
diff --git a/arch/powerpc/configs/pmac32_defconfig b/arch/powerpc/configs/pmac32_defconfig
index f8b394a..29767a8 100644
--- a/arch/powerpc/configs/pmac32_defconfig
+++ b/arch/powerpc/configs/pmac32_defconfig
@@ -55,7 +55,6 @@ CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
 CONFIG_NETFILTER_XT_TARGET_MARK=m
 CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
-CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
 CONFIG_NETFILTER_XT_TARGET_TRACE=m
 CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
 CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
diff --git a/arch/powerpc/configs/ppc64_defconfig b/arch/powerpc/configs/ppc64_defconfig
index db27c82..6d03530 100644
--- a/arch/powerpc/configs/ppc64_defconfig
+++ b/arch/powerpc/configs/ppc64_defconfig
@@ -51,6 +51,7 @@ CONFIG_KEXEC=y
 CONFIG_IRQ_ALL_CPUS=y
 CONFIG_MEMORY_HOTREMOVE=y
 CONFIG_SCHED_SMT=y
+CONFIG_PPC_DENORMALISATION=y
 CONFIG_PCCARD=y
 CONFIG_ELECTRA_CF=y
 CONFIG_HOTPLUG_PCI=m
@@ -92,7 +93,6 @@ CONFIG_NETFILTER_XT_TARGET_DSCP=m
 CONFIG_NETFILTER_XT_TARGET_MARK=m
 CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
-CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
 CONFIG_NETFILTER_XT_TARGET_TPROXY=m
 CONFIG_NETFILTER_XT_TARGET_TRACE=m
 CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
@@ -487,7 +487,8 @@ CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_LZO=m
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRYPTO_HW=y
-CONFIG_CRYPTO_DEV_NX=m
+CONFIG_CRYPTO_DEV_NX=y
+CONFIG_CRYPTO_DEV_NX_ENCRYPT=m
 CONFIG_VIRTUALIZATION=y
 CONFIG_KVM_BOOK3S_64=m
 CONFIG_KVM_BOOK3S_64_HV=y
diff --git a/arch/powerpc/configs/ppc64e_defconfig b/arch/powerpc/configs/ppc64e_defconfig
index 7bd1763..f55c276 100644
--- a/arch/powerpc/configs/ppc64e_defconfig
+++ b/arch/powerpc/configs/ppc64e_defconfig
@@ -66,7 +66,6 @@ CONFIG_NETFILTER_XT_TARGET_DSCP=m
 CONFIG_NETFILTER_XT_TARGET_MARK=m
 CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
-CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
 CONFIG_NETFILTER_XT_TARGET_TPROXY=m
 CONFIG_NETFILTER_XT_TARGET_TRACE=m
 CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
diff --git a/arch/powerpc/configs/ppc6xx_defconfig b/arch/powerpc/configs/ppc6xx_defconfig
index c47f2be..be1cb6e 100644
--- a/arch/powerpc/configs/ppc6xx_defconfig
+++ b/arch/powerpc/configs/ppc6xx_defconfig
@@ -167,7 +167,6 @@ CONFIG_NETFILTER_XT_TARGET_DSCP=m
 CONFIG_NETFILTER_XT_TARGET_MARK=m
 CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
-CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
 CONFIG_NETFILTER_XT_TARGET_TPROXY=m
 CONFIG_NETFILTER_XT_TARGET_TRACE=m
 CONFIG_NETFILTER_XT_TARGET_SECMARK=m
diff --git a/arch/powerpc/configs/pseries_defconfig b/arch/powerpc/configs/pseries_defconfig
index 1f65b3c..1f710a3 100644
--- a/arch/powerpc/configs/pseries_defconfig
+++ b/arch/powerpc/configs/pseries_defconfig
@@ -48,6 +48,7 @@ CONFIG_MEMORY_HOTREMOVE=y
 CONFIG_PPC_64K_PAGES=y
 CONFIG_PPC_SUBPAGE_PROT=y
 CONFIG_SCHED_SMT=y
+CONFIG_PPC_DENORMALISATION=y
 CONFIG_HOTPLUG_PCI=m
 CONFIG_HOTPLUG_PCI_RPA=m
 CONFIG_HOTPLUG_PCI_RPA_DLPAR=m
@@ -369,7 +370,8 @@ CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_LZO=m
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRYPTO_HW=y
-CONFIG_CRYPTO_DEV_NX=m
+CONFIG_CRYPTO_DEV_NX=y
+CONFIG_CRYPTO_DEV_NX_ENCRYPT=m
 CONFIG_VIRTUALIZATION=y
 CONFIG_KVM_BOOK3S_64=m
 CONFIG_KVM_BOOK3S_64_HV=y
diff --git a/arch/powerpc/include/asm/Kbuild b/arch/powerpc/include/asm/Kbuild
index 7e313f1..13d6b7bf 100644
--- a/arch/powerpc/include/asm/Kbuild
+++ b/arch/powerpc/include/asm/Kbuild
@@ -34,5 +34,6 @@ header-y += termios.h
 header-y += types.h
 header-y += ucontext.h
 header-y += unistd.h
+header-y += epapr_hcalls.h
 
 generic-y += rwsem.h
diff --git a/arch/powerpc/include/asm/abs_addr.h b/arch/powerpc/include/asm/abs_addr.h
deleted file mode 100644
index 9d92ba0..0000000
--- a/arch/powerpc/include/asm/abs_addr.h
+++ /dev/null
@@ -1,56 +0,0 @@
-#ifndef _ASM_POWERPC_ABS_ADDR_H
-#define _ASM_POWERPC_ABS_ADDR_H
-#ifdef __KERNEL__
-
-
-/*
- * c 2001 PPC 64 Team, IBM Corp
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#include <linux/memblock.h>
-
-#include <asm/types.h>
-#include <asm/page.h>
-#include <asm/prom.h>
-
-struct mschunks_map {
-        unsigned long num_chunks;
-        unsigned long chunk_size;
-        unsigned long chunk_shift;
-        unsigned long chunk_mask;
-        u32 *mapping;
-};
-
-extern struct mschunks_map mschunks_map;
-
-/* Chunks are 256 KB */
-#define MSCHUNKS_CHUNK_SHIFT	(18)
-#define MSCHUNKS_CHUNK_SIZE	(1UL << MSCHUNKS_CHUNK_SHIFT)
-#define MSCHUNKS_OFFSET_MASK	(MSCHUNKS_CHUNK_SIZE - 1)
-
-static inline unsigned long chunk_to_addr(unsigned long chunk)
-{
-	return chunk << MSCHUNKS_CHUNK_SHIFT;
-}
-
-static inline unsigned long addr_to_chunk(unsigned long addr)
-{
-	return addr >> MSCHUNKS_CHUNK_SHIFT;
-}
-
-static inline unsigned long phys_to_abs(unsigned long pa)
-{
-	return pa;
-}
-
-/* Convenience macros */
-#define virt_to_abs(va) phys_to_abs(__pa(va))
-#define abs_to_virt(aa) __va(aa)
-
-#endif /* __KERNEL__ */
-#endif /* _ASM_POWERPC_ABS_ADDR_H */
diff --git a/arch/powerpc/include/asm/atomic.h b/arch/powerpc/include/asm/atomic.h
index da29032..e3b1d41 100644
--- a/arch/powerpc/include/asm/atomic.h
+++ b/arch/powerpc/include/asm/atomic.h
@@ -268,6 +268,7 @@ static __inline__ int atomic_dec_if_positive(atomic_t *v)
 
 	return t;
 }
+#define atomic_dec_if_positive atomic_dec_if_positive
 
 #define smp_mb__before_atomic_dec()     smp_mb()
 #define smp_mb__after_atomic_dec()      smp_mb()
diff --git a/arch/powerpc/include/asm/bitops.h b/arch/powerpc/include/asm/bitops.h
index efdc926..dc2cf9c 100644
--- a/arch/powerpc/include/asm/bitops.h
+++ b/arch/powerpc/include/asm/bitops.h
@@ -288,6 +288,16 @@ static __inline__ int test_bit_le(unsigned long nr,
 	return (tmp[nr >> 3] >> (nr & 7)) & 1;
 }
 
+static inline void set_bit_le(int nr, void *addr)
+{
+	set_bit(nr ^ BITOP_LE_SWIZZLE, addr);
+}
+
+static inline void clear_bit_le(int nr, void *addr)
+{
+	clear_bit(nr ^ BITOP_LE_SWIZZLE, addr);
+}
+
 static inline void __set_bit_le(int nr, void *addr)
 {
 	__set_bit(nr ^ BITOP_LE_SWIZZLE, addr);
diff --git a/arch/powerpc/include/asm/cacheflush.h b/arch/powerpc/include/asm/cacheflush.h
index ab9e402..b843e35 100644
--- a/arch/powerpc/include/asm/cacheflush.h
+++ b/arch/powerpc/include/asm/cacheflush.h
@@ -30,6 +30,8 @@ extern void flush_dcache_page(struct page *page);
 #define flush_dcache_mmap_lock(mapping)		do { } while (0)
 #define flush_dcache_mmap_unlock(mapping)	do { } while (0)
 
+extern void __flush_disable_L1(void);
+
 extern void __flush_icache_range(unsigned long, unsigned long);
 static inline void flush_icache_range(unsigned long start, unsigned long stop)
 {
diff --git a/arch/powerpc/include/asm/compat.h b/arch/powerpc/include/asm/compat.h
index 88e602f..84fdf68 100644
--- a/arch/powerpc/include/asm/compat.h
+++ b/arch/powerpc/include/asm/compat.h
@@ -38,6 +38,7 @@ typedef s64		compat_s64;
 typedef u32		compat_uint_t;
 typedef u32		compat_ulong_t;
 typedef u64		compat_u64;
+typedef u32		compat_uptr_t;
 
 struct compat_timespec {
 	compat_time_t	tv_sec;
@@ -114,6 +115,64 @@ typedef u32		compat_old_sigset_t;
 
 typedef u32		compat_sigset_word;
 
+typedef union compat_sigval {
+	compat_int_t	sival_int;
+	compat_uptr_t	sival_ptr;
+} compat_sigval_t;
+
+#define SI_PAD_SIZE32	(128/sizeof(int) - 3)
+
+typedef struct compat_siginfo {
+	int si_signo;
+	int si_errno;
+	int si_code;
+
+	union {
+		int _pad[SI_PAD_SIZE32];
+
+		/* kill() */
+		struct {
+			compat_pid_t _pid;		/* sender's pid */
+			__compat_uid_t _uid;		/* sender's uid */
+		} _kill;
+
+		/* POSIX.1b timers */
+		struct {
+			compat_timer_t _tid;		/* timer id */
+			int _overrun;			/* overrun count */
+			compat_sigval_t _sigval;	/* same as below */
+			int _sys_private;	/* not to be passed to user */
+		} _timer;
+
+		/* POSIX.1b signals */
+		struct {
+			compat_pid_t _pid;		/* sender's pid */
+			__compat_uid_t _uid;		/* sender's uid */
+			compat_sigval_t _sigval;
+		} _rt;
+
+		/* SIGCHLD */
+		struct {
+			compat_pid_t _pid;		/* which child */
+			__compat_uid_t _uid;		/* sender's uid */
+			int _status;			/* exit code */
+			compat_clock_t _utime;
+			compat_clock_t _stime;
+		} _sigchld;
+
+		/* SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGEMT */
+		struct {
+			unsigned int _addr; /* faulting insn/memory ref. */
+		} _sigfault;
+
+		/* SIGPOLL */
+		struct {
+			int _band;	/* POLL_IN, POLL_OUT, POLL_MSG */
+			int _fd;
+		} _sigpoll;
+	} _sifields;
+} compat_siginfo_t;
+
 #define COMPAT_OFF_T_MAX	0x7fffffff
 #define COMPAT_LOFF_T_MAX	0x7fffffffffffffffL
 
@@ -123,7 +182,6 @@ typedef u32		compat_sigset_word;
  * as pointers because the syscall entry code will have
  * appropriately converted them already.
  */
-typedef	u32		compat_uptr_t;
 
 static inline void __user *compat_ptr(compat_uptr_t uptr)
 {
diff --git a/arch/powerpc/include/asm/debug.h b/arch/powerpc/include/asm/debug.h
index 716d2f0..32de257 100644
--- a/arch/powerpc/include/asm/debug.h
+++ b/arch/powerpc/include/asm/debug.h
@@ -44,7 +44,7 @@ static inline int debugger_dabr_match(struct pt_regs *regs) { return 0; }
 static inline int debugger_fault_handler(struct pt_regs *regs) { return 0; }
 #endif
 
-extern int set_dabr(unsigned long dabr);
+extern int set_dabr(unsigned long dabr, unsigned long dabrx);
 #ifdef CONFIG_PPC_ADV_DEBUG_REGS
 extern void do_send_trap(struct pt_regs *regs, unsigned long address,
 			 unsigned long error_code, int signal_code, int brkpt);
diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h
index d60f998..b0ef738 100644
--- a/arch/powerpc/include/asm/eeh.h
+++ b/arch/powerpc/include/asm/eeh.h
@@ -32,27 +32,62 @@ struct device_node;
 #ifdef CONFIG_EEH
 
 /*
+ * The struct is used to trace PE related EEH functionality.
+ * In theory, there will have one instance of the struct to
+ * be created against particular PE. In nature, PEs corelate
+ * to each other. the struct has to reflect that hierarchy in
+ * order to easily pick up those affected PEs when one particular
+ * PE has EEH errors.
+ *
+ * Also, one particular PE might be composed of PCI device, PCI
+ * bus and its subordinate components. The struct also need ship
+ * the information. Further more, one particular PE is only meaingful
+ * in the corresponding PHB. Therefore, the root PEs should be created
+ * against existing PHBs in on-to-one fashion.
+ */
+#define EEH_PE_INVALID	(1 << 0)	/* Invalid   */
+#define EEH_PE_PHB	(1 << 1)	/* PHB PE    */
+#define EEH_PE_DEVICE 	(1 << 2)	/* Device PE */
+#define EEH_PE_BUS	(1 << 3)	/* Bus PE    */
+
+#define EEH_PE_ISOLATED		(1 << 0)	/* Isolated PE		*/
+#define EEH_PE_RECOVERING	(1 << 1)	/* Recovering PE	*/
+
+struct eeh_pe {
+	int type;			/* PE type: PHB/Bus/Device	*/
+	int state;			/* PE EEH dependent mode	*/
+	int config_addr;		/* Traditional PCI address	*/
+	int addr;			/* PE configuration address	*/
+	struct pci_controller *phb;	/* Associated PHB		*/
+	int check_count;		/* Times of ignored error	*/
+	int freeze_count;		/* Times of froze up		*/
+	int false_positives;		/* Times of reported #ff's	*/
+	struct eeh_pe *parent;		/* Parent PE			*/
+	struct list_head child_list;	/* Link PE to the child list	*/
+	struct list_head edevs;		/* Link list of EEH devices	*/
+	struct list_head child;		/* Child PEs			*/
+};
+
+#define eeh_pe_for_each_dev(pe, edev) \
+		list_for_each_entry(edev, &pe->edevs, list)
+
+/*
  * The struct is used to trace EEH state for the associated
  * PCI device node or PCI device. In future, it might
  * represent PE as well so that the EEH device to form
  * another tree except the currently existing tree of PCI
  * buses and PCI devices
  */
-#define EEH_MODE_SUPPORTED	(1<<0)	/* EEH supported on the device	*/
-#define EEH_MODE_NOCHECK	(1<<1)	/* EEH check should be skipped	*/
-#define EEH_MODE_ISOLATED	(1<<2)	/* The device has been isolated	*/
-#define EEH_MODE_RECOVERING	(1<<3)	/* Recovering the device	*/
-#define EEH_MODE_IRQ_DISABLED	(1<<4)	/* Interrupt disabled		*/
+#define EEH_DEV_IRQ_DISABLED	(1<<0)	/* Interrupt disabled		*/
 
 struct eeh_dev {
 	int mode;			/* EEH mode			*/
 	int class_code;			/* Class code of the device	*/
 	int config_addr;		/* Config address		*/
 	int pe_config_addr;		/* PE config address		*/
-	int check_count;		/* Times of ignored error	*/
-	int freeze_count;		/* Times of froze up		*/
-	int false_positives;		/* Times of reported #ff's	*/
 	u32 config_space[16];		/* Saved PCI config space	*/
+	struct eeh_pe *pe;		/* Associated PE		*/
+	struct list_head list;		/* Form link list in the PE	*/
 	struct pci_controller *phb;	/* Associated PHB		*/
 	struct device_node *dn;		/* Associated device node	*/
 	struct pci_dev *pdev;		/* Associated PCI device	*/
@@ -95,19 +130,51 @@ static inline struct pci_dev *eeh_dev_to_pci_dev(struct eeh_dev *edev)
 struct eeh_ops {
 	char *name;
 	int (*init)(void);
-	int (*set_option)(struct device_node *dn, int option);
-	int (*get_pe_addr)(struct device_node *dn);
-	int (*get_state)(struct device_node *dn, int *state);
-	int (*reset)(struct device_node *dn, int option);
-	int (*wait_state)(struct device_node *dn, int max_wait);
-	int (*get_log)(struct device_node *dn, int severity, char *drv_log, unsigned long len);
-	int (*configure_bridge)(struct device_node *dn);
+	void* (*of_probe)(struct device_node *dn, void *flag);
+	void* (*dev_probe)(struct pci_dev *dev, void *flag);
+	int (*set_option)(struct eeh_pe *pe, int option);
+	int (*get_pe_addr)(struct eeh_pe *pe);
+	int (*get_state)(struct eeh_pe *pe, int *state);
+	int (*reset)(struct eeh_pe *pe, int option);
+	int (*wait_state)(struct eeh_pe *pe, int max_wait);
+	int (*get_log)(struct eeh_pe *pe, int severity, char *drv_log, unsigned long len);
+	int (*configure_bridge)(struct eeh_pe *pe);
 	int (*read_config)(struct device_node *dn, int where, int size, u32 *val);
 	int (*write_config)(struct device_node *dn, int where, int size, u32 val);
 };
 
 extern struct eeh_ops *eeh_ops;
 extern int eeh_subsystem_enabled;
+extern struct mutex eeh_mutex;
+extern int eeh_probe_mode;
+
+#define EEH_PROBE_MODE_DEV	(1<<0)	/* From PCI device	*/
+#define EEH_PROBE_MODE_DEVTREE	(1<<1)	/* From device tree	*/
+
+static inline void eeh_probe_mode_set(int flag)
+{
+	eeh_probe_mode = flag;
+}
+
+static inline int eeh_probe_mode_devtree(void)
+{
+	return (eeh_probe_mode == EEH_PROBE_MODE_DEVTREE);
+}
+
+static inline int eeh_probe_mode_dev(void)
+{
+	return (eeh_probe_mode == EEH_PROBE_MODE_DEV);
+}
+
+static inline void eeh_lock(void)
+{
+	mutex_lock(&eeh_mutex);
+}
+
+static inline void eeh_unlock(void)
+{
+	mutex_unlock(&eeh_mutex);
+}
 
 /*
  * Max number of EEH freezes allowed before we consider the device
@@ -115,22 +182,26 @@ extern int eeh_subsystem_enabled;
  */
 #define EEH_MAX_ALLOWED_FREEZES 5
 
+typedef void *(*eeh_traverse_func)(void *data, void *flag);
+int __devinit eeh_phb_pe_create(struct pci_controller *phb);
+int eeh_add_to_parent_pe(struct eeh_dev *edev);
+int eeh_rmv_from_parent_pe(struct eeh_dev *edev, int purge_pe);
+void *eeh_pe_dev_traverse(struct eeh_pe *root,
+		eeh_traverse_func fn, void *flag);
+void eeh_pe_restore_bars(struct eeh_pe *pe);
+struct pci_bus *eeh_pe_bus_get(struct eeh_pe *pe);
+
 void * __devinit eeh_dev_init(struct device_node *dn, void *data);
 void __devinit eeh_dev_phb_init_dynamic(struct pci_controller *phb);
-void __init eeh_dev_phb_init(void);
-void __init eeh_init(void);
-#ifdef CONFIG_PPC_PSERIES
-int __init eeh_pseries_init(void);
-#endif
 int __init eeh_ops_register(struct eeh_ops *ops);
 int __exit eeh_ops_unregister(const char *name);
 unsigned long eeh_check_failure(const volatile void __iomem *token,
 				unsigned long val);
-int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev);
-void __init pci_addr_cache_build(void);
+int eeh_dev_check_failure(struct eeh_dev *edev);
+void __init eeh_addr_cache_build(void);
 void eeh_add_device_tree_early(struct device_node *);
 void eeh_add_device_tree_late(struct pci_bus *);
-void eeh_remove_bus_device(struct pci_dev *);
+void eeh_remove_bus_device(struct pci_dev *, int);
 
 /**
  * EEH_POSSIBLE_ERROR() -- test for possible MMIO failure.
@@ -156,34 +227,24 @@ static inline void *eeh_dev_init(struct device_node *dn, void *data)
 
 static inline void eeh_dev_phb_init_dynamic(struct pci_controller *phb) { }
 
-static inline void eeh_dev_phb_init(void) { }
-
-static inline void eeh_init(void) { }
-
-#ifdef CONFIG_PPC_PSERIES
-static inline int eeh_pseries_init(void)
-{
-	return 0;
-}
-#endif /* CONFIG_PPC_PSERIES */
-
 static inline unsigned long eeh_check_failure(const volatile void __iomem *token, unsigned long val)
 {
 	return val;
 }
 
-static inline int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
-{
-	return 0;
-}
+#define eeh_dev_check_failure(x) (0)
 
-static inline void pci_addr_cache_build(void) { }
+static inline void eeh_addr_cache_build(void) { }
 
 static inline void eeh_add_device_tree_early(struct device_node *dn) { }
 
 static inline void eeh_add_device_tree_late(struct pci_bus *bus) { }
 
-static inline void eeh_remove_bus_device(struct pci_dev *dev) { }
+static inline void eeh_remove_bus_device(struct pci_dev *dev, int purge_pe) { }
+
+static inline void eeh_lock(void) { }
+static inline void eeh_unlock(void) { }
+
 #define EEH_POSSIBLE_ERROR(val, type) (0)
 #define EEH_IO_ERROR_VALUE(size) (-1UL)
 #endif /* CONFIG_EEH */
diff --git a/arch/powerpc/include/asm/eeh_event.h b/arch/powerpc/include/asm/eeh_event.h
index c68b012..de67d83 100644
--- a/arch/powerpc/include/asm/eeh_event.h
+++ b/arch/powerpc/include/asm/eeh_event.h
@@ -28,11 +28,11 @@
  */
 struct eeh_event {
 	struct list_head	list;	/* to form event queue	*/
-	struct eeh_dev		*edev;	/* EEH device		*/
+	struct eeh_pe		*pe;	/* EEH PE		*/
 };
 
-int eeh_send_failure_event(struct eeh_dev *edev);
-struct eeh_dev *handle_eeh_events(struct eeh_event *);
+int eeh_send_failure_event(struct eeh_pe *pe);
+void eeh_handle_event(struct eeh_pe *pe);
 
 #endif /* __KERNEL__ */
 #endif /* ASM_POWERPC_EEH_EVENT_H */
diff --git a/arch/powerpc/include/asm/epapr_hcalls.h b/arch/powerpc/include/asm/epapr_hcalls.h
index bf2c06c..b8d9445 100644
--- a/arch/powerpc/include/asm/epapr_hcalls.h
+++ b/arch/powerpc/include/asm/epapr_hcalls.h
@@ -50,10 +50,6 @@
 #ifndef _EPAPR_HCALLS_H
 #define _EPAPR_HCALLS_H
 
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <asm/byteorder.h>
-
 #define EV_BYTE_CHANNEL_SEND		1
 #define EV_BYTE_CHANNEL_RECEIVE		2
 #define EV_BYTE_CHANNEL_POLL		3
@@ -88,7 +84,8 @@
 #define _EV_HCALL_TOKEN(id, num) (((id) << 16) | (num))
 #define EV_HCALL_TOKEN(hcall_num) _EV_HCALL_TOKEN(EV_EPAPR_VENDOR_ID, hcall_num)
 
-/* epapr error codes */
+/* epapr return codes */
+#define EV_SUCCESS		0
 #define EV_EPERM		1	/* Operation not permitted */
 #define EV_ENOENT		2	/*  Entry Not Found */
 #define EV_EIO			3	/* I/O error occured */
@@ -108,6 +105,11 @@
 #define EV_UNIMPLEMENTED	12	/* Unimplemented hypercall */
 #define EV_BUFFER_OVERFLOW	13	/* Caller-supplied buffer too small */
 
+#ifndef __ASSEMBLY__
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <asm/byteorder.h>
+
 /*
  * Hypercall register clobber list
  *
@@ -193,7 +195,7 @@ static inline unsigned int ev_int_set_config(unsigned int interrupt,
 	r5  = priority;
 	r6  = destination;
 
-	__asm__ __volatile__ ("sc 1"
+	asm volatile("bl	epapr_hypercall_start"
 		: "+r" (r11), "+r" (r3), "+r" (r4), "+r" (r5), "+r" (r6)
 		: : EV_HCALL_CLOBBERS4
 	);
@@ -222,7 +224,7 @@ static inline unsigned int ev_int_get_config(unsigned int interrupt,
 	r11 = EV_HCALL_TOKEN(EV_INT_GET_CONFIG);
 	r3 = interrupt;
 
-	__asm__ __volatile__ ("sc 1"
+	asm volatile("bl	epapr_hypercall_start"
 		: "+r" (r11), "+r" (r3), "=r" (r4), "=r" (r5), "=r" (r6)
 		: : EV_HCALL_CLOBBERS4
 	);
@@ -252,7 +254,7 @@ static inline unsigned int ev_int_set_mask(unsigned int interrupt,
 	r3 = interrupt;
 	r4 = mask;
 
-	__asm__ __volatile__ ("sc 1"
+	asm volatile("bl	epapr_hypercall_start"
 		: "+r" (r11), "+r" (r3), "+r" (r4)
 		: : EV_HCALL_CLOBBERS2
 	);
@@ -277,7 +279,7 @@ static inline unsigned int ev_int_get_mask(unsigned int interrupt,
 	r11 = EV_HCALL_TOKEN(EV_INT_GET_MASK);
 	r3 = interrupt;
 
-	__asm__ __volatile__ ("sc 1"
+	asm volatile("bl	epapr_hypercall_start"
 		: "+r" (r11), "+r" (r3), "=r" (r4)
 		: : EV_HCALL_CLOBBERS2
 	);
@@ -305,7 +307,7 @@ static inline unsigned int ev_int_eoi(unsigned int interrupt)
 	r11 = EV_HCALL_TOKEN(EV_INT_EOI);
 	r3 = interrupt;
 
-	__asm__ __volatile__ ("sc 1"
+	asm volatile("bl	epapr_hypercall_start"
 		: "+r" (r11), "+r" (r3)
 		: : EV_HCALL_CLOBBERS1
 	);
@@ -344,7 +346,7 @@ static inline unsigned int ev_byte_channel_send(unsigned int handle,
 	r7 = be32_to_cpu(p[2]);
 	r8 = be32_to_cpu(p[3]);
 
-	__asm__ __volatile__ ("sc 1"
+	asm volatile("bl	epapr_hypercall_start"
 		: "+r" (r11), "+r" (r3),
 		  "+r" (r4), "+r" (r5), "+r" (r6), "+r" (r7), "+r" (r8)
 		: : EV_HCALL_CLOBBERS6
@@ -383,7 +385,7 @@ static inline unsigned int ev_byte_channel_receive(unsigned int handle,
 	r3 = handle;
 	r4 = *count;
 
-	__asm__ __volatile__ ("sc 1"
+	asm volatile("bl	epapr_hypercall_start"
 		: "+r" (r11), "+r" (r3), "+r" (r4),
 		  "=r" (r5), "=r" (r6), "=r" (r7), "=r" (r8)
 		: : EV_HCALL_CLOBBERS6
@@ -421,7 +423,7 @@ static inline unsigned int ev_byte_channel_poll(unsigned int handle,
 	r11 = EV_HCALL_TOKEN(EV_BYTE_CHANNEL_POLL);
 	r3 = handle;
 
-	__asm__ __volatile__ ("sc 1"
+	asm volatile("bl	epapr_hypercall_start"
 		: "+r" (r11), "+r" (r3), "=r" (r4), "=r" (r5)
 		: : EV_HCALL_CLOBBERS3
 	);
@@ -454,7 +456,7 @@ static inline unsigned int ev_int_iack(unsigned int handle,
 	r11 = EV_HCALL_TOKEN(EV_INT_IACK);
 	r3 = handle;
 
-	__asm__ __volatile__ ("sc 1"
+	asm volatile("bl	epapr_hypercall_start"
 		: "+r" (r11), "+r" (r3), "=r" (r4)
 		: : EV_HCALL_CLOBBERS2
 	);
@@ -478,7 +480,7 @@ static inline unsigned int ev_doorbell_send(unsigned int handle)
 	r11 = EV_HCALL_TOKEN(EV_DOORBELL_SEND);
 	r3 = handle;
 
-	__asm__ __volatile__ ("sc 1"
+	asm volatile("bl	epapr_hypercall_start"
 		: "+r" (r11), "+r" (r3)
 		: : EV_HCALL_CLOBBERS1
 	);
@@ -498,12 +500,12 @@ static inline unsigned int ev_idle(void)
 
 	r11 = EV_HCALL_TOKEN(EV_IDLE);
 
-	__asm__ __volatile__ ("sc 1"
+	asm volatile("bl	epapr_hypercall_start"
 		: "+r" (r11), "=r" (r3)
 		: : EV_HCALL_CLOBBERS1
 	);
 
 	return r3;
 }
-
+#endif /* !__ASSEMBLY__ */
 #endif
diff --git a/arch/powerpc/include/asm/exception-64e.h b/arch/powerpc/include/asm/exception-64e.h
index ac13add..51fa43e 100644
--- a/arch/powerpc/include/asm/exception-64e.h
+++ b/arch/powerpc/include/asm/exception-64e.h
@@ -37,6 +37,7 @@
  * critical data
  */
 
+#define PACA_EXGDBELL PACA_EXGEN
 
 /* We are out of SPRGs so we save some things in the PACA. The normal
  * exception frame is smaller than the CRIT or MC one though
@@ -45,8 +46,9 @@
 #define EX_CR		(1 * 8)
 #define EX_R10		(2 * 8)
 #define EX_R11		(3 * 8)
-#define EX_R14		(4 * 8)
-#define EX_R15		(5 * 8)
+#define EX_R13		(4 * 8)
+#define EX_R14		(5 * 8)
+#define EX_R15		(6 * 8)
 
 /*
  * The TLB miss exception uses different slots.
diff --git a/arch/powerpc/include/asm/fsl_guts.h b/arch/powerpc/include/asm/fsl_guts.h
index aa4c488..dd5ba2c 100644
--- a/arch/powerpc/include/asm/fsl_guts.h
+++ b/arch/powerpc/include/asm/fsl_guts.h
@@ -48,6 +48,8 @@ struct ccsr_guts {
         __be32  dmuxcr;		/* 0x.0068 - DMA Mux Control Register */
         u8	res06c[0x70 - 0x6c];
 	__be32	devdisr;	/* 0x.0070 - Device Disable Control */
+#define CCSR_GUTS_DEVDISR_TB1	0x00001000
+#define CCSR_GUTS_DEVDISR_TB0	0x00004000
 	__be32	devdisr2;	/* 0x.0074 - Device Disable Control 2 */
 	u8	res078[0x7c - 0x78];
 	__be32  pmjcr;		/* 0x.007c - 4 Power Management Jog Control Register */
diff --git a/arch/powerpc/include/asm/fsl_hcalls.h b/arch/powerpc/include/asm/fsl_hcalls.h
index 922d9b5..3abb583 100644
--- a/arch/powerpc/include/asm/fsl_hcalls.h
+++ b/arch/powerpc/include/asm/fsl_hcalls.h
@@ -96,7 +96,7 @@ static inline unsigned int fh_send_nmi(unsigned int vcpu_mask)
 	r11 = FH_HCALL_TOKEN(FH_SEND_NMI);
 	r3 = vcpu_mask;
 
-	__asm__ __volatile__ ("sc 1"
+	asm volatile("bl	epapr_hypercall_start"
 		: "+r" (r11), "+r" (r3)
 		: : EV_HCALL_CLOBBERS1
 	);
@@ -151,7 +151,7 @@ static inline unsigned int fh_partition_get_dtprop(int handle,
 	r9 = (uint32_t)propvalue_addr;
 	r10 = *propvalue_len;
 
-	__asm__ __volatile__ ("sc 1"
+	asm volatile("bl	epapr_hypercall_start"
 		: "+r" (r11),
 		  "+r" (r3), "+r" (r4), "+r" (r5), "+r" (r6), "+r" (r7),
 		  "+r" (r8), "+r" (r9), "+r" (r10)
@@ -205,7 +205,7 @@ static inline unsigned int fh_partition_set_dtprop(int handle,
 	r9 = (uint32_t)propvalue_addr;
 	r10 = propvalue_len;
 
-	__asm__ __volatile__ ("sc 1"
+	asm volatile("bl	epapr_hypercall_start"
 		: "+r" (r11),
 		  "+r" (r3), "+r" (r4), "+r" (r5), "+r" (r6), "+r" (r7),
 		  "+r" (r8), "+r" (r9), "+r" (r10)
@@ -229,7 +229,7 @@ static inline unsigned int fh_partition_restart(unsigned int partition)
 	r11 = FH_HCALL_TOKEN(FH_PARTITION_RESTART);
 	r3 = partition;
 
-	__asm__ __volatile__ ("sc 1"
+	asm volatile("bl	epapr_hypercall_start"
 		: "+r" (r11), "+r" (r3)
 		: : EV_HCALL_CLOBBERS1
 	);
@@ -262,7 +262,7 @@ static inline unsigned int fh_partition_get_status(unsigned int partition,
 	r11 = FH_HCALL_TOKEN(FH_PARTITION_GET_STATUS);
 	r3 = partition;
 
-	__asm__ __volatile__ ("sc 1"
+	asm volatile("bl	epapr_hypercall_start"
 		: "+r" (r11), "+r" (r3), "=r" (r4)
 		: : EV_HCALL_CLOBBERS2
 	);
@@ -295,7 +295,7 @@ static inline unsigned int fh_partition_start(unsigned int partition,
 	r4 = entry_point;
 	r5 = load;
 
-	__asm__ __volatile__ ("sc 1"
+	asm volatile("bl	epapr_hypercall_start"
 		: "+r" (r11), "+r" (r3), "+r" (r4), "+r" (r5)
 		: : EV_HCALL_CLOBBERS3
 	);
@@ -317,7 +317,7 @@ static inline unsigned int fh_partition_stop(unsigned int partition)
 	r11 = FH_HCALL_TOKEN(FH_PARTITION_STOP);
 	r3 = partition;
 
-	__asm__ __volatile__ ("sc 1"
+	asm volatile("bl	epapr_hypercall_start"
 		: "+r" (r11), "+r" (r3)
 		: : EV_HCALL_CLOBBERS1
 	);
@@ -376,7 +376,7 @@ static inline unsigned int fh_partition_memcpy(unsigned int source,
 #endif
 	r7 = count;
 
-	__asm__ __volatile__ ("sc 1"
+	asm volatile("bl	epapr_hypercall_start"
 		: "+r" (r11),
 		  "+r" (r3), "+r" (r4), "+r" (r5), "+r" (r6), "+r" (r7)
 		: : EV_HCALL_CLOBBERS5
@@ -399,7 +399,7 @@ static inline unsigned int fh_dma_enable(unsigned int liodn)
 	r11 = FH_HCALL_TOKEN(FH_DMA_ENABLE);
 	r3 = liodn;
 
-	__asm__ __volatile__ ("sc 1"
+	asm volatile("bl	epapr_hypercall_start"
 		: "+r" (r11), "+r" (r3)
 		: : EV_HCALL_CLOBBERS1
 	);
@@ -421,7 +421,7 @@ static inline unsigned int fh_dma_disable(unsigned int liodn)
 	r11 = FH_HCALL_TOKEN(FH_DMA_DISABLE);
 	r3 = liodn;
 
-	__asm__ __volatile__ ("sc 1"
+	asm volatile("bl	epapr_hypercall_start"
 		: "+r" (r11), "+r" (r3)
 		: : EV_HCALL_CLOBBERS1
 	);
@@ -447,7 +447,7 @@ static inline unsigned int fh_vmpic_get_msir(unsigned int interrupt,
 	r11 = FH_HCALL_TOKEN(FH_VMPIC_GET_MSIR);
 	r3 = interrupt;
 
-	__asm__ __volatile__ ("sc 1"
+	asm volatile("bl	epapr_hypercall_start"
 		: "+r" (r11), "+r" (r3), "=r" (r4)
 		: : EV_HCALL_CLOBBERS2
 	);
@@ -469,7 +469,7 @@ static inline unsigned int fh_system_reset(void)
 
 	r11 = FH_HCALL_TOKEN(FH_SYSTEM_RESET);
 
-	__asm__ __volatile__ ("sc 1"
+	asm volatile("bl	epapr_hypercall_start"
 		: "+r" (r11), "=r" (r3)
 		: : EV_HCALL_CLOBBERS1
 	);
@@ -506,7 +506,7 @@ static inline unsigned int fh_err_get_info(int queue, uint32_t *bufsize,
 	r6 = addr_lo;
 	r7 = peek;
 
-	__asm__ __volatile__ ("sc 1"
+	asm volatile("bl	epapr_hypercall_start"
 		: "+r" (r11), "+r" (r3), "+r" (r4), "+r" (r5), "+r" (r6),
 		  "+r" (r7)
 		: : EV_HCALL_CLOBBERS5
@@ -542,7 +542,7 @@ static inline unsigned int fh_get_core_state(unsigned int handle,
 	r3 = handle;
 	r4 = vcpu;
 
-	__asm__ __volatile__ ("sc 1"
+	asm volatile("bl	epapr_hypercall_start"
 		: "+r" (r11), "+r" (r3), "+r" (r4)
 		: : EV_HCALL_CLOBBERS2
 	);
@@ -572,7 +572,7 @@ static inline unsigned int fh_enter_nap(unsigned int handle, unsigned int vcpu)
 	r3 = handle;
 	r4 = vcpu;
 
-	__asm__ __volatile__ ("sc 1"
+	asm volatile("bl	epapr_hypercall_start"
 		: "+r" (r11), "+r" (r3), "+r" (r4)
 		: : EV_HCALL_CLOBBERS2
 	);
@@ -597,7 +597,7 @@ static inline unsigned int fh_exit_nap(unsigned int handle, unsigned int vcpu)
 	r3 = handle;
 	r4 = vcpu;
 
-	__asm__ __volatile__ ("sc 1"
+	asm volatile("bl	epapr_hypercall_start"
 		: "+r" (r11), "+r" (r3), "+r" (r4)
 		: : EV_HCALL_CLOBBERS2
 	);
@@ -618,7 +618,7 @@ static inline unsigned int fh_claim_device(unsigned int handle)
 	r11 = FH_HCALL_TOKEN(FH_CLAIM_DEVICE);
 	r3 = handle;
 
-	__asm__ __volatile__ ("sc 1"
+	asm volatile("bl	epapr_hypercall_start"
 		: "+r" (r11), "+r" (r3)
 		: : EV_HCALL_CLOBBERS1
 	);
@@ -645,7 +645,7 @@ static inline unsigned int fh_partition_stop_dma(unsigned int handle)
 	r11 = FH_HCALL_TOKEN(FH_PARTITION_STOP_DMA);
 	r3 = handle;
 
-	__asm__ __volatile__ ("sc 1"
+	asm volatile("bl	epapr_hypercall_start"
 		: "+r" (r11), "+r" (r3)
 		: : EV_HCALL_CLOBBERS1
 	);
diff --git a/arch/powerpc/include/asm/fsl_ifc.h b/arch/powerpc/include/asm/fsl_ifc.h
index b955012..b8a4b9b 100644
--- a/arch/powerpc/include/asm/fsl_ifc.h
+++ b/arch/powerpc/include/asm/fsl_ifc.h
@@ -768,22 +768,24 @@ struct fsl_ifc_gpcm {
  */
 struct fsl_ifc_regs {
 	__be32 ifc_rev;
-	u32 res1[0x3];
+	u32 res1[0x2];
 	struct {
+		__be32 cspr_ext;
 		__be32 cspr;
-		u32 res2[0x2];
+		u32 res2;
 	} cspr_cs[FSL_IFC_BANK_COUNT];
-	u32 res3[0x18];
+	u32 res3[0x19];
 	struct {
 		__be32 amask;
 		u32 res4[0x2];
 	} amask_cs[FSL_IFC_BANK_COUNT];
-	u32 res5[0x18];
+	u32 res5[0x17];
 	struct {
+		__be32 csor_ext;
 		__be32 csor;
-		u32 res6[0x2];
+		u32 res6;
 	} csor_cs[FSL_IFC_BANK_COUNT];
-	u32 res7[0x18];
+	u32 res7[0x19];
 	struct {
 		__be32 ftim[4];
 		u32 res8[0x8];
diff --git a/arch/powerpc/include/asm/hugetlb.h b/arch/powerpc/include/asm/hugetlb.h
index dfdb95b..62e11a3 100644
--- a/arch/powerpc/include/asm/hugetlb.h
+++ b/arch/powerpc/include/asm/hugetlb.h
@@ -151,6 +151,10 @@ static inline void arch_release_hugepage(struct page *page)
 {
 }
 
+static inline void arch_clear_hugepage_flags(struct page *page)
+{
+}
+
 #else /* ! CONFIG_HUGETLB_PAGE */
 static inline void flush_hugetlb_page(struct vm_area_struct *vma,
 				      unsigned long vmaddr)
diff --git a/arch/powerpc/include/asm/hvcall.h b/arch/powerpc/include/asm/hvcall.h
index 423cf9e..7a86706 100644
--- a/arch/powerpc/include/asm/hvcall.h
+++ b/arch/powerpc/include/asm/hvcall.h
@@ -152,11 +152,6 @@
 #define H_VASI_RESUMED          5
 #define H_VASI_COMPLETED        6
 
-/* DABRX flags */
-#define H_DABRX_HYPERVISOR	(1UL<<(63-61))
-#define H_DABRX_KERNEL		(1UL<<(63-62))
-#define H_DABRX_USER		(1UL<<(63-63))
-
 /* Each control block has to be on a 4K boundary */
 #define H_CB_ALIGNMENT          4096
 
diff --git a/arch/powerpc/include/asm/hw_breakpoint.h b/arch/powerpc/include/asm/hw_breakpoint.h
index be04330..4234245 100644
--- a/arch/powerpc/include/asm/hw_breakpoint.h
+++ b/arch/powerpc/include/asm/hw_breakpoint.h
@@ -27,10 +27,11 @@
 #ifdef CONFIG_HAVE_HW_BREAKPOINT
 
 struct arch_hw_breakpoint {
-	bool		extraneous_interrupt;
-	u8		len; /* length of the target data symbol */
-	int		type;
 	unsigned long	address;
+	unsigned long	dabrx;
+	int		type;
+	u8		len; /* length of the target data symbol */
+	bool		extraneous_interrupt;
 };
 
 #include <linux/kdebug.h>
@@ -61,7 +62,7 @@ extern void ptrace_triggered(struct perf_event *bp,
 			struct perf_sample_data *data, struct pt_regs *regs);
 static inline void hw_breakpoint_disable(void)
 {
-	set_dabr(0);
+	set_dabr(0, 0);
 }
 extern void thread_change_pc(struct task_struct *tsk, struct pt_regs *regs);
 
diff --git a/arch/powerpc/include/asm/kprobes.h b/arch/powerpc/include/asm/kprobes.h
index be0171a..7b6feab 100644
--- a/arch/powerpc/include/asm/kprobes.h
+++ b/arch/powerpc/include/asm/kprobes.h
@@ -29,21 +29,16 @@
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
+#include <asm/probes.h>
 
 #define  __ARCH_WANT_KPROBES_INSN_SLOT
 
 struct pt_regs;
 struct kprobe;
 
-typedef unsigned int kprobe_opcode_t;
-#define BREAKPOINT_INSTRUCTION	0x7fe00008	/* trap */
+typedef ppc_opcode_t kprobe_opcode_t;
 #define MAX_INSN_SIZE 1
 
-#define IS_TW(instr)		(((instr) & 0xfc0007fe) == 0x7c000008)
-#define IS_TD(instr)		(((instr) & 0xfc0007fe) == 0x7c000088)
-#define IS_TDI(instr)		(((instr) & 0xfc000000) == 0x08000000)
-#define IS_TWI(instr)		(((instr) & 0xfc000000) == 0x0c000000)
-
 #ifdef CONFIG_PPC64
 /*
  * 64bit powerpc uses function descriptors.
@@ -72,12 +67,6 @@ typedef unsigned int kprobe_opcode_t;
 		addr = (kprobe_opcode_t *)kallsyms_lookup_name(dot_name); \
 	}								\
 }
-
-#define is_trap(instr)	(IS_TW(instr) || IS_TD(instr) || \
-			IS_TWI(instr) || IS_TDI(instr))
-#else
-/* Use stock kprobe_lookup_name since ppc32 doesn't use function descriptors */
-#define is_trap(instr)	(IS_TW(instr) || IS_TWI(instr))
 #endif
 
 #define flush_insn_slot(p)	do { } while (0)
diff --git a/arch/powerpc/include/asm/kvm.h b/arch/powerpc/include/asm/kvm.h
index 1bea4d8..3c14202 100644
--- a/arch/powerpc/include/asm/kvm.h
+++ b/arch/powerpc/include/asm/kvm.h
@@ -221,6 +221,12 @@ struct kvm_sregs {
 
 			__u32 dbsr;	/* KVM_SREGS_E_UPDATE_DBSR */
 			__u32 dbcr[3];
+			/*
+			 * iac/dac registers are 64bit wide, while this API
+			 * interface provides only lower 32 bits on 64 bit
+			 * processors. ONE_REG interface is added for 64bit
+			 * iac/dac registers.
+			 */
 			__u32 iac[4];
 			__u32 dac[2];
 			__u32 dvc[2];
@@ -326,5 +332,11 @@ struct kvm_book3e_206_tlb_params {
 };
 
 #define KVM_REG_PPC_HIOR	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x1)
+#define KVM_REG_PPC_IAC1	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x2)
+#define KVM_REG_PPC_IAC2	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x3)
+#define KVM_REG_PPC_IAC3	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x4)
+#define KVM_REG_PPC_IAC4	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x5)
+#define KVM_REG_PPC_DAC1	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x6)
+#define KVM_REG_PPC_DAC2	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x7)
 
 #endif /* __LINUX_KVM_POWERPC_H */
diff --git a/arch/powerpc/include/asm/kvm_book3s.h b/arch/powerpc/include/asm/kvm_book3s.h
index f0e0c6a..36fcf41 100644
--- a/arch/powerpc/include/asm/kvm_book3s.h
+++ b/arch/powerpc/include/asm/kvm_book3s.h
@@ -59,7 +59,7 @@ struct hpte_cache {
 	struct hlist_node list_vpte;
 	struct hlist_node list_vpte_long;
 	struct rcu_head rcu_head;
-	u64 host_va;
+	u64 host_vpn;
 	u64 pfn;
 	ulong slot;
 	struct kvmppc_pte pte;
@@ -160,7 +160,7 @@ extern long kvmppc_virtmode_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
 extern long kvmppc_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
 			long pte_index, unsigned long pteh, unsigned long ptel);
 extern long kvmppc_hv_get_dirty_log(struct kvm *kvm,
-			struct kvm_memory_slot *memslot);
+			struct kvm_memory_slot *memslot, unsigned long *map);
 
 extern void kvmppc_entry_trampoline(void);
 extern void kvmppc_hv_entry_trampoline(void);
diff --git a/arch/powerpc/include/asm/kvm_book3s_asm.h b/arch/powerpc/include/asm/kvm_book3s_asm.h
index bfcd00c..88609b2 100644
--- a/arch/powerpc/include/asm/kvm_book3s_asm.h
+++ b/arch/powerpc/include/asm/kvm_book3s_asm.h
@@ -74,7 +74,6 @@ struct kvmppc_host_state {
 	ulong vmhandler;
 	ulong scratch0;
 	ulong scratch1;
-	ulong sprg3;
 	u8 in_guest;
 	u8 restore_hid5;
 	u8 napping;
diff --git a/arch/powerpc/include/asm/kvm_booke_hv_asm.h b/arch/powerpc/include/asm/kvm_booke_hv_asm.h
index 30a600f..a37a12a 100644
--- a/arch/powerpc/include/asm/kvm_booke_hv_asm.h
+++ b/arch/powerpc/include/asm/kvm_booke_hv_asm.h
@@ -38,9 +38,9 @@
 #ifdef CONFIG_KVM_BOOKE_HV
 BEGIN_FTR_SECTION
 	mtocrf	0x80, r11	/* check MSR[GS] without clobbering reg */
-	bf	3, kvmppc_resume_\intno\()_\srr1
+	bf	3, 1975f
 	b	kvmppc_handler_\intno\()_\srr1
-kvmppc_resume_\intno\()_\srr1:
+1975:
 END_FTR_SECTION_IFSET(CPU_FTR_EMB_HV)
 #endif
 .endm
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index a8bf5c6..68f5a30 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -46,13 +46,15 @@
 #define KVM_COALESCED_MMIO_PAGE_OFFSET 1
 #endif
 
-#ifdef CONFIG_KVM_BOOK3S_64_HV
+#if !defined(CONFIG_KVM_440)
 #include <linux/mmu_notifier.h>
 
 #define KVM_ARCH_WANT_MMU_NOTIFIER
 
 struct kvm;
 extern int kvm_unmap_hva(struct kvm *kvm, unsigned long hva);
+extern int kvm_unmap_hva_range(struct kvm *kvm,
+			       unsigned long start, unsigned long end);
 extern int kvm_age_hva(struct kvm *kvm, unsigned long hva);
 extern int kvm_test_age_hva(struct kvm *kvm, unsigned long hva);
 extern void kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte);
@@ -202,7 +204,7 @@ struct revmap_entry {
 };
 
 /*
- * We use the top bit of each memslot->rmap entry as a lock bit,
+ * We use the top bit of each memslot->arch.rmap entry as a lock bit,
  * and bit 32 as a present flag.  The bottom 32 bits are the
  * index in the guest HPT of a HPTE that points to the page.
  */
@@ -213,13 +215,17 @@ struct revmap_entry {
 #define KVMPPC_RMAP_PRESENT	0x100000000ul
 #define KVMPPC_RMAP_INDEX	0xfffffffful
 
-/* Low-order bits in kvm->arch.slot_phys[][] */
+/* Low-order bits in memslot->arch.slot_phys[] */
 #define KVMPPC_PAGE_ORDER_MASK	0x1f
 #define KVMPPC_PAGE_NO_CACHE	HPTE_R_I	/* 0x20 */
 #define KVMPPC_PAGE_WRITETHRU	HPTE_R_W	/* 0x40 */
 #define KVMPPC_GOT_PAGE		0x80
 
 struct kvm_arch_memory_slot {
+#ifdef CONFIG_KVM_BOOK3S_64_HV
+	unsigned long *rmap;
+	unsigned long *slot_phys;
+#endif /* CONFIG_KVM_BOOK3S_64_HV */
 };
 
 struct kvm_arch {
@@ -243,8 +249,6 @@ struct kvm_arch {
 	unsigned long hpt_npte;
 	unsigned long hpt_mask;
 	spinlock_t slot_phys_lock;
-	unsigned long *slot_phys[KVM_MEM_SLOTS_NUM];
-	int slot_npages[KVM_MEM_SLOTS_NUM];
 	unsigned short last_vcpu[NR_CPUS];
 	struct kvmppc_vcore *vcores[KVM_MAX_VCORES];
 	struct kvmppc_linear_info *hpt_li;
@@ -343,6 +347,27 @@ struct kvmppc_slb {
 	bool class	: 1;
 };
 
+# ifdef CONFIG_PPC_FSL_BOOK3E
+#define KVMPPC_BOOKE_IAC_NUM	2
+#define KVMPPC_BOOKE_DAC_NUM	2
+# else
+#define KVMPPC_BOOKE_IAC_NUM	4
+#define KVMPPC_BOOKE_DAC_NUM	2
+# endif
+#define KVMPPC_BOOKE_MAX_IAC	4
+#define KVMPPC_BOOKE_MAX_DAC	2
+
+struct kvmppc_booke_debug_reg {
+	u32 dbcr0;
+	u32 dbcr1;
+	u32 dbcr2;
+#ifdef CONFIG_KVM_E500MC
+	u32 dbcr4;
+#endif
+	u64 iac[KVMPPC_BOOKE_MAX_IAC];
+	u64 dac[KVMPPC_BOOKE_MAX_DAC];
+};
+
 struct kvm_vcpu_arch {
 	ulong host_stack;
 	u32 host_pid;
@@ -437,8 +462,6 @@ struct kvm_vcpu_arch {
 
 	u32 ccr0;
 	u32 ccr1;
-	u32 dbcr0;
-	u32 dbcr1;
 	u32 dbsr;
 
 	u64 mmcr[3];
@@ -468,9 +491,12 @@ struct kvm_vcpu_arch {
 	ulong fault_esr;
 	ulong queued_dear;
 	ulong queued_esr;
+	spinlock_t wdt_lock;
+	struct timer_list wdt_timer;
 	u32 tlbcfg[4];
 	u32 mmucfg;
 	u32 epr;
+	struct kvmppc_booke_debug_reg dbg_reg;
 #endif
 	gpa_t paddr_accessed;
 	gva_t vaddr_accessed;
@@ -483,6 +509,7 @@ struct kvm_vcpu_arch {
 	u8 osi_needed;
 	u8 osi_enabled;
 	u8 papr_enabled;
+	u8 watchdog_enabled;
 	u8 sane;
 	u8 cpu_type;
 	u8 hcall_needed;
diff --git a/arch/powerpc/include/asm/kvm_para.h b/arch/powerpc/include/asm/kvm_para.h
index c18916b..a168ce3 100644
--- a/arch/powerpc/include/asm/kvm_para.h
+++ b/arch/powerpc/include/asm/kvm_para.h
@@ -75,9 +75,10 @@ struct kvm_vcpu_arch_shared {
 };
 
 #define KVM_SC_MAGIC_R0		0x4b564d21 /* "KVM!" */
-#define HC_VENDOR_KVM		(42 << 16)
-#define HC_EV_SUCCESS		0
-#define HC_EV_UNIMPLEMENTED	12
+
+#define KVM_HCALL_TOKEN(num)     _EV_HCALL_TOKEN(EV_KVM_VENDOR_ID, num)
+
+#include <asm/epapr_hcalls.h>
 
 #define KVM_FEATURE_MAGIC_PAGE	1
 
@@ -121,7 +122,7 @@ static unsigned long kvm_hypercall(unsigned long *in,
 				   unsigned long *out,
 				   unsigned long nr)
 {
-	return HC_EV_UNIMPLEMENTED;
+	return EV_UNIMPLEMENTED;
 }
 
 #endif
@@ -132,7 +133,7 @@ static inline long kvm_hypercall0_1(unsigned int nr, unsigned long *r2)
 	unsigned long out[8];
 	unsigned long r;
 
-	r = kvm_hypercall(in, out, nr | HC_VENDOR_KVM);
+	r = kvm_hypercall(in, out, KVM_HCALL_TOKEN(nr));
 	*r2 = out[0];
 
 	return r;
@@ -143,7 +144,7 @@ static inline long kvm_hypercall0(unsigned int nr)
 	unsigned long in[8];
 	unsigned long out[8];
 
-	return kvm_hypercall(in, out, nr | HC_VENDOR_KVM);
+	return kvm_hypercall(in, out, KVM_HCALL_TOKEN(nr));
 }
 
 static inline long kvm_hypercall1(unsigned int nr, unsigned long p1)
@@ -152,7 +153,7 @@ static inline long kvm_hypercall1(unsigned int nr, unsigned long p1)
 	unsigned long out[8];
 
 	in[0] = p1;
-	return kvm_hypercall(in, out, nr | HC_VENDOR_KVM);
+	return kvm_hypercall(in, out, KVM_HCALL_TOKEN(nr));
 }
 
 static inline long kvm_hypercall2(unsigned int nr, unsigned long p1,
@@ -163,7 +164,7 @@ static inline long kvm_hypercall2(unsigned int nr, unsigned long p1,
 
 	in[0] = p1;
 	in[1] = p2;
-	return kvm_hypercall(in, out, nr | HC_VENDOR_KVM);
+	return kvm_hypercall(in, out, KVM_HCALL_TOKEN(nr));
 }
 
 static inline long kvm_hypercall3(unsigned int nr, unsigned long p1,
@@ -175,7 +176,7 @@ static inline long kvm_hypercall3(unsigned int nr, unsigned long p1,
 	in[0] = p1;
 	in[1] = p2;
 	in[2] = p3;
-	return kvm_hypercall(in, out, nr | HC_VENDOR_KVM);
+	return kvm_hypercall(in, out, KVM_HCALL_TOKEN(nr));
 }
 
 static inline long kvm_hypercall4(unsigned int nr, unsigned long p1,
@@ -189,7 +190,7 @@ static inline long kvm_hypercall4(unsigned int nr, unsigned long p1,
 	in[1] = p2;
 	in[2] = p3;
 	in[3] = p4;
-	return kvm_hypercall(in, out, nr | HC_VENDOR_KVM);
+	return kvm_hypercall(in, out, KVM_HCALL_TOKEN(nr));
 }
 
 
diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h
index e006f0b..3fb980d 100644
--- a/arch/powerpc/include/asm/kvm_ppc.h
+++ b/arch/powerpc/include/asm/kvm_ppc.h
@@ -68,6 +68,8 @@ extern void kvmppc_emulate_dec(struct kvm_vcpu *vcpu);
 extern u32 kvmppc_get_dec(struct kvm_vcpu *vcpu, u64 tb);
 extern void kvmppc_decrementer_func(unsigned long data);
 extern int kvmppc_sanity_check(struct kvm_vcpu *vcpu);
+extern int kvmppc_subarch_vcpu_init(struct kvm_vcpu *vcpu);
+extern void kvmppc_subarch_vcpu_uninit(struct kvm_vcpu *vcpu);
 
 /* Core-specific hooks */
 
@@ -104,6 +106,7 @@ extern void kvmppc_core_queue_external(struct kvm_vcpu *vcpu,
                                        struct kvm_interrupt *irq);
 extern void kvmppc_core_dequeue_external(struct kvm_vcpu *vcpu,
                                          struct kvm_interrupt *irq);
+extern void kvmppc_core_flush_tlb(struct kvm_vcpu *vcpu);
 
 extern int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
                                   unsigned int op, int *advance);
@@ -111,6 +114,7 @@ extern int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn,
 				     ulong val);
 extern int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn,
 				     ulong *val);
+extern int kvmppc_core_check_requests(struct kvm_vcpu *vcpu);
 
 extern int kvmppc_booke_init(void);
 extern void kvmppc_booke_exit(void);
@@ -139,16 +143,26 @@ extern struct kvmppc_linear_info *kvm_alloc_hpt(void);
 extern void kvm_release_hpt(struct kvmppc_linear_info *li);
 extern int kvmppc_core_init_vm(struct kvm *kvm);
 extern void kvmppc_core_destroy_vm(struct kvm *kvm);
+extern void kvmppc_core_free_memslot(struct kvm_memory_slot *free,
+				     struct kvm_memory_slot *dont);
+extern int kvmppc_core_create_memslot(struct kvm_memory_slot *slot,
+				      unsigned long npages);
 extern int kvmppc_core_prepare_memory_region(struct kvm *kvm,
+				struct kvm_memory_slot *memslot,
 				struct kvm_userspace_memory_region *mem);
 extern void kvmppc_core_commit_memory_region(struct kvm *kvm,
-				struct kvm_userspace_memory_region *mem);
+				struct kvm_userspace_memory_region *mem,
+				struct kvm_memory_slot old);
 extern int kvm_vm_ioctl_get_smmu_info(struct kvm *kvm,
 				      struct kvm_ppc_smmu_info *info);
+extern void kvmppc_core_flush_memslot(struct kvm *kvm,
+				      struct kvm_memory_slot *memslot);
 
 extern int kvmppc_bookehv_init(void);
 extern void kvmppc_bookehv_exit(void);
 
+extern int kvmppc_prepare_to_enter(struct kvm_vcpu *vcpu);
+
 /*
  * Cuts out inst bits with ordering according to spec.
  * That means the leftmost bit is zero. All given bits are included.
@@ -230,5 +244,15 @@ static inline void kvmppc_mmu_flush_icache(pfn_t pfn)
 	}
 }
 
+/* Please call after prepare_to_enter. This function puts the lazy ee state
+   back to normal mode, without actually enabling interrupts. */
+static inline void kvmppc_lazy_ee_enable(void)
+{
+#ifdef CONFIG_PPC64
+	/* Only need to enable IRQs by hard enabling them after this */
+	local_paca->irq_happened = 0;
+	local_paca->soft_enabled = 1;
+#endif
+}
 
 #endif /* __POWERPC_KVM_PPC_H__ */
diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h
index 42ce570..c423197 100644
--- a/arch/powerpc/include/asm/machdep.h
+++ b/arch/powerpc/include/asm/machdep.h
@@ -34,19 +34,19 @@ struct machdep_calls {
 	char		*name;
 #ifdef CONFIG_PPC64
 	void            (*hpte_invalidate)(unsigned long slot,
-					   unsigned long va,
+					   unsigned long vpn,
 					   int psize, int ssize,
 					   int local);
 	long		(*hpte_updatepp)(unsigned long slot, 
 					 unsigned long newpp, 
-					 unsigned long va,
+					 unsigned long vpn,
 					 int psize, int ssize,
 					 int local);
 	void            (*hpte_updateboltedpp)(unsigned long newpp, 
 					       unsigned long ea,
 					       int psize, int ssize);
 	long		(*hpte_insert)(unsigned long hpte_group,
-				       unsigned long va,
+				       unsigned long vpn,
 				       unsigned long prpn,
 				       unsigned long rflags,
 				       unsigned long vflags,
@@ -180,7 +180,8 @@ struct machdep_calls {
 	void		(*enable_pmcs)(void);
 
 	/* Set DABR for this platform, leave empty for default implemenation */
-	int		(*set_dabr)(unsigned long dabr);
+	int		(*set_dabr)(unsigned long dabr,
+				    unsigned long dabrx);
 
 #ifdef CONFIG_PPC32	/* XXX for now */
 	/* A general init function, called by ppc_init in init/main.c.
@@ -214,6 +215,9 @@ struct machdep_calls {
 	/* Called after scan and before resource survey */
 	void (*pcibios_fixup_phb)(struct pci_controller *hose);
 
+	/* Called during PCI resource reassignment */
+	resource_size_t (*pcibios_window_alignment)(struct pci_bus *, unsigned long type);
+
 	/* Called to shutdown machine specific hardware not already controlled
 	 * by other drivers.
 	 */
diff --git a/arch/powerpc/include/asm/mmu-hash64.h b/arch/powerpc/include/asm/mmu-hash64.h
index 1c65a59..9673f73 100644
--- a/arch/powerpc/include/asm/mmu-hash64.h
+++ b/arch/powerpc/include/asm/mmu-hash64.h
@@ -16,6 +16,13 @@
 #include <asm/page.h>
 
 /*
+ * This is necessary to get the definition of PGTABLE_RANGE which we
+ * need for various slices related matters. Note that this isn't the
+ * complete pgtable.h but only a portion of it.
+ */
+#include <asm/pgtable-ppc64.h>
+
+/*
  * Segment table
  */
 
@@ -154,9 +161,25 @@ struct mmu_psize_def
 #define MMU_SEGSIZE_256M	0
 #define MMU_SEGSIZE_1T		1
 
+/*
+ * encode page number shift.
+ * in order to fit the 78 bit va in a 64 bit variable we shift the va by
+ * 12 bits. This enable us to address upto 76 bit va.
+ * For hpt hash from a va we can ignore the page size bits of va and for
+ * hpte encoding we ignore up to 23 bits of va. So ignoring lower 12 bits ensure
+ * we work in all cases including 4k page size.
+ */
+#define VPN_SHIFT	12
 
 #ifndef __ASSEMBLY__
 
+static inline int segment_shift(int ssize)
+{
+	if (ssize == MMU_SEGSIZE_256M)
+		return SID_SHIFT;
+	return SID_SHIFT_1T;
+}
+
 /*
  * The current system page and segment sizes
  */
@@ -180,18 +203,39 @@ extern unsigned long tce_alloc_start, tce_alloc_end;
 extern int mmu_ci_restrictions;
 
 /*
+ * This computes the AVPN and B fields of the first dword of a HPTE,
+ * for use when we want to match an existing PTE.  The bottom 7 bits
+ * of the returned value are zero.
+ */
+static inline unsigned long hpte_encode_avpn(unsigned long vpn, int psize,
+					     int ssize)
+{
+	unsigned long v;
+	/*
+	 * The AVA field omits the low-order 23 bits of the 78 bits VA.
+	 * These bits are not needed in the PTE, because the
+	 * low-order b of these bits are part of the byte offset
+	 * into the virtual page and, if b < 23, the high-order
+	 * 23-b of these bits are always used in selecting the
+	 * PTEGs to be searched
+	 */
+	v = (vpn >> (23 - VPN_SHIFT)) & ~(mmu_psize_defs[psize].avpnm);
+	v <<= HPTE_V_AVPN_SHIFT;
+	v |= ((unsigned long) ssize) << HPTE_V_SSIZE_SHIFT;
+	return v;
+}
+
+/*
  * This function sets the AVPN and L fields of the HPTE  appropriately
  * for the page size
  */
-static inline unsigned long hpte_encode_v(unsigned long va, int psize,
-					  int ssize)
+static inline unsigned long hpte_encode_v(unsigned long vpn,
+					  int psize, int ssize)
 {
 	unsigned long v;
-	v = (va >> 23) & ~(mmu_psize_defs[psize].avpnm);
-	v <<= HPTE_V_AVPN_SHIFT;
+	v = hpte_encode_avpn(vpn, psize, ssize);
 	if (psize != MMU_PAGE_4K)
 		v |= HPTE_V_LARGE;
-	v |= ((unsigned long) ssize) << HPTE_V_SSIZE_SHIFT;
 	return v;
 }
 
@@ -216,30 +260,37 @@ static inline unsigned long hpte_encode_r(unsigned long pa, int psize)
 }
 
 /*
- * Build a VA given VSID, EA and segment size
+ * Build a VPN_SHIFT bit shifted va given VSID, EA and segment size.
  */
-static inline unsigned long hpt_va(unsigned long ea, unsigned long vsid,
-				   int ssize)
+static inline unsigned long hpt_vpn(unsigned long ea,
+				    unsigned long vsid, int ssize)
 {
-	if (ssize == MMU_SEGSIZE_256M)
-		return (vsid << 28) | (ea & 0xfffffffUL);
-	return (vsid << 40) | (ea & 0xffffffffffUL);
+	unsigned long mask;
+	int s_shift = segment_shift(ssize);
+
+	mask = (1ul << (s_shift - VPN_SHIFT)) - 1;
+	return (vsid << (s_shift - VPN_SHIFT)) | ((ea >> VPN_SHIFT) & mask);
 }
 
 /*
  * This hashes a virtual address
  */
-
-static inline unsigned long hpt_hash(unsigned long va, unsigned int shift,
-				     int ssize)
+static inline unsigned long hpt_hash(unsigned long vpn,
+				     unsigned int shift, int ssize)
 {
+	int mask;
 	unsigned long hash, vsid;
 
+	/* VPN_SHIFT can be atmost 12 */
 	if (ssize == MMU_SEGSIZE_256M) {
-		hash = (va >> 28) ^ ((va & 0x0fffffffUL) >> shift);
+		mask = (1ul << (SID_SHIFT - VPN_SHIFT)) - 1;
+		hash = (vpn >> (SID_SHIFT - VPN_SHIFT)) ^
+			((vpn & mask) >> (shift - VPN_SHIFT));
 	} else {
-		vsid = va >> 40;
-		hash = vsid ^ (vsid << 25) ^ ((va & 0xffffffffffUL) >> shift);
+		mask = (1ul << (SID_SHIFT_1T - VPN_SHIFT)) - 1;
+		vsid = vpn >> (SID_SHIFT_1T - VPN_SHIFT);
+		hash = vsid ^ (vsid << 25) ^
+			((vpn & mask) >> (shift - VPN_SHIFT)) ;
 	}
 	return hash & 0x7fffffffffUL;
 }
@@ -280,63 +331,61 @@ extern void slb_set_size(u16 size);
 #endif /* __ASSEMBLY__ */
 
 /*
- * VSID allocation
+ * VSID allocation (256MB segment)
+ *
+ * We first generate a 38-bit "proto-VSID".  For kernel addresses this
+ * is equal to the ESID | 1 << 37, for user addresses it is:
+ *	(context << USER_ESID_BITS) | (esid & ((1U << USER_ESID_BITS) - 1)
  *
- * We first generate a 36-bit "proto-VSID".  For kernel addresses this
- * is equal to the ESID, for user addresses it is:
- *	(context << 15) | (esid & 0x7fff)
+ * This splits the proto-VSID into the below range
+ *  0 - (2^(CONTEXT_BITS + USER_ESID_BITS) - 1) : User proto-VSID range
+ *  2^(CONTEXT_BITS + USER_ESID_BITS) - 2^(VSID_BITS) : Kernel proto-VSID range
  *
- * The two forms are distinguishable because the top bit is 0 for user
- * addresses, whereas the top two bits are 1 for kernel addresses.
- * Proto-VSIDs with the top two bits equal to 0b10 are reserved for
- * now.
+ * We also have CONTEXT_BITS + USER_ESID_BITS = VSID_BITS - 1
+ * That is, we assign half of the space to user processes and half
+ * to the kernel.
  *
  * The proto-VSIDs are then scrambled into real VSIDs with the
  * multiplicative hash:
  *
  *	VSID = (proto-VSID * VSID_MULTIPLIER) % VSID_MODULUS
- *	where	VSID_MULTIPLIER = 268435399 = 0xFFFFFC7
- *		VSID_MODULUS = 2^36-1 = 0xFFFFFFFFF
  *
- * This scramble is only well defined for proto-VSIDs below
- * 0xFFFFFFFFF, so both proto-VSID and actual VSID 0xFFFFFFFFF are
- * reserved.  VSID_MULTIPLIER is prime, so in particular it is
+ * VSID_MULTIPLIER is prime, so in particular it is
  * co-prime to VSID_MODULUS, making this a 1:1 scrambling function.
  * Because the modulus is 2^n-1 we can compute it efficiently without
  * a divide or extra multiply (see below).
  *
  * This scheme has several advantages over older methods:
  *
- * 	- We have VSIDs allocated for every kernel address
+ *	- We have VSIDs allocated for every kernel address
  * (i.e. everything above 0xC000000000000000), except the very top
  * segment, which simplifies several things.
  *
- *	- We allow for 16 significant bits of ESID and 19 bits of
- * context for user addresses.  i.e. 16T (44 bits) of address space for
- * up to half a million contexts.
+ *	- We allow for USER_ESID_BITS significant bits of ESID and
+ * CONTEXT_BITS  bits of context for user addresses.
+ *  i.e. 64T (46 bits) of address space for up to half a million contexts.
  *
- * 	- The scramble function gives robust scattering in the hash
+ *	- The scramble function gives robust scattering in the hash
  * table (at least based on some initial results).  The previous
  * method was more susceptible to pathological cases giving excessive
  * hash collisions.
  */
+
 /*
- * WARNING - If you change these you must make sure the asm
- * implementations in slb_allocate (slb_low.S), do_stab_bolted
- * (head.S) and ASM_VSID_SCRAMBLE (below) are changed accordingly.
+ * This should be computed such that protovosid * vsid_mulitplier
+ * doesn't overflow 64 bits. It should also be co-prime to vsid_modulus
  */
-
-#define VSID_MULTIPLIER_256M	ASM_CONST(200730139)	/* 28-bit prime */
-#define VSID_BITS_256M		36
+#define VSID_MULTIPLIER_256M	ASM_CONST(12538073)	/* 24-bit prime */
+#define VSID_BITS_256M		38
 #define VSID_MODULUS_256M	((1UL<<VSID_BITS_256M)-1)
 
 #define VSID_MULTIPLIER_1T	ASM_CONST(12538073)	/* 24-bit prime */
-#define VSID_BITS_1T		24
+#define VSID_BITS_1T		26
 #define VSID_MODULUS_1T		((1UL<<VSID_BITS_1T)-1)
 
 #define CONTEXT_BITS		19
-#define USER_ESID_BITS		16
-#define USER_ESID_BITS_1T	4
+#define USER_ESID_BITS		18
+#define USER_ESID_BITS_1T	6
 
 #define USER_VSID_RANGE	(1UL << (USER_ESID_BITS + SID_SHIFT))
 
@@ -372,6 +421,8 @@ extern void slb_set_size(u16 size);
 	srdi	rx,rx,VSID_BITS_##size;	/* extract 2^VSID_BITS bit */	\
 	add	rt,rt,rx
 
+/* 4 bits per slice and we have one slice per 1TB */
+#define SLICE_ARRAY_SIZE  (PGTABLE_RANGE >> 41)
 
 #ifndef __ASSEMBLY__
 
@@ -416,7 +467,7 @@ typedef struct {
 
 #ifdef CONFIG_PPC_MM_SLICES
 	u64 low_slices_psize;	/* SLB page size encodings */
-	u64 high_slices_psize;  /* 4 bits per slice for now */
+	unsigned char high_slices_psize[SLICE_ARRAY_SIZE];
 #else
 	u16 sllp;		/* SLB page size encoding */
 #endif
@@ -452,12 +503,32 @@ typedef struct {
 	})
 #endif /* 1 */
 
-/* This is only valid for addresses >= PAGE_OFFSET */
+/*
+ * This is only valid for addresses >= PAGE_OFFSET
+ * The proto-VSID space is divided into two class
+ * User:   0 to 2^(CONTEXT_BITS + USER_ESID_BITS) -1
+ * kernel: 2^(CONTEXT_BITS + USER_ESID_BITS) to 2^(VSID_BITS) - 1
+ *
+ * With KERNEL_START at 0xc000000000000000, the proto vsid for
+ * the kernel ends up with 0xc00000000 (36 bits). With 64TB
+ * support we need to have kernel proto-VSID in the
+ * [2^37 to 2^38 - 1] range due to the increased USER_ESID_BITS.
+ */
 static inline unsigned long get_kernel_vsid(unsigned long ea, int ssize)
 {
-	if (ssize == MMU_SEGSIZE_256M)
-		return vsid_scramble(ea >> SID_SHIFT, 256M);
-	return vsid_scramble(ea >> SID_SHIFT_1T, 1T);
+	unsigned long proto_vsid;
+	/*
+	 * We need to make sure proto_vsid for the kernel is
+	 * >= 2^(CONTEXT_BITS + USER_ESID_BITS[_1T])
+	 */
+	if (ssize == MMU_SEGSIZE_256M) {
+		proto_vsid = ea >> SID_SHIFT;
+		proto_vsid |= (1UL << (CONTEXT_BITS + USER_ESID_BITS));
+		return vsid_scramble(proto_vsid, 256M);
+	}
+	proto_vsid = ea >> SID_SHIFT_1T;
+	proto_vsid |= (1UL << (CONTEXT_BITS + USER_ESID_BITS_1T));
+	return vsid_scramble(proto_vsid, 1T);
 }
 
 /* Returns the segment size indicator for a user address */
diff --git a/arch/powerpc/include/asm/mmu.h b/arch/powerpc/include/asm/mmu.h
index e8a26db..5e38eed 100644
--- a/arch/powerpc/include/asm/mmu.h
+++ b/arch/powerpc/include/asm/mmu.h
@@ -146,6 +146,15 @@ extern void setup_initial_memory_limit(phys_addr_t first_memblock_base,
 extern u64 ppc64_rma_size;
 #endif /* CONFIG_PPC64 */
 
+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__ */
 
 /* The kernel use the constants below to index in the page sizes array.
diff --git a/arch/powerpc/include/asm/module.h b/arch/powerpc/include/asm/module.h
index 0192a4e..c1df590 100644
--- a/arch/powerpc/include/asm/module.h
+++ b/arch/powerpc/include/asm/module.h
@@ -11,6 +11,7 @@
 
 #include <linux/list.h>
 #include <asm/bug.h>
+#include <asm-generic/module.h>
 
 
 #ifndef __powerpc64__
@@ -60,16 +61,10 @@ struct mod_arch_specific {
  */
 
 #ifdef __powerpc64__
-#    define Elf_Shdr	Elf64_Shdr
-#    define Elf_Sym	Elf64_Sym
-#    define Elf_Ehdr	Elf64_Ehdr
 #    ifdef MODULE
 	asm(".section .stubs,\"ax\",@nobits; .align 3; .previous");
 #    endif
 #else
-#    define Elf_Shdr	Elf32_Shdr
-#    define Elf_Sym	Elf32_Sym
-#    define Elf_Ehdr	Elf32_Ehdr
 #    ifdef MODULE
 	asm(".section .plt,\"ax\",@nobits; .align 3; .previous");
 	asm(".section .init.plt,\"ax\",@nobits; .align 3; .previous");
diff --git a/arch/powerpc/include/asm/mpc52xx.h b/arch/powerpc/include/asm/mpc52xx.h
index 1f41382..0acc7c7 100644
--- a/arch/powerpc/include/asm/mpc52xx.h
+++ b/arch/powerpc/include/asm/mpc52xx.h
@@ -307,6 +307,7 @@ struct mpc52xx_lpbfifo_request {
 	size_t size;
 	size_t pos;	/* current position of transfer */
 	int flags;
+	int defer_xfer_start;
 
 	/* What to do when finished */
 	void (*callback)(struct mpc52xx_lpbfifo_request *);
@@ -323,6 +324,7 @@ struct mpc52xx_lpbfifo_request {
 extern int mpc52xx_lpbfifo_submit(struct mpc52xx_lpbfifo_request *req);
 extern void mpc52xx_lpbfifo_abort(struct mpc52xx_lpbfifo_request *req);
 extern void mpc52xx_lpbfifo_poll(void);
+extern int mpc52xx_lpbfifo_start_xfer(struct mpc52xx_lpbfifo_request *req);
 
 /* mpc52xx_pic.c */
 extern void mpc52xx_init_irq(void);
diff --git a/arch/powerpc/include/asm/mpic.h b/arch/powerpc/include/asm/mpic.h
index c9f698a..c0f9ef9 100644
--- a/arch/powerpc/include/asm/mpic.h
+++ b/arch/powerpc/include/asm/mpic.h
@@ -63,6 +63,7 @@
  */
 #define MPIC_TIMER_BASE			0x01100
 #define MPIC_TIMER_STRIDE		0x40
+#define MPIC_TIMER_GROUP_STRIDE		0x1000
 
 #define MPIC_TIMER_CURRENT_CNT		0x00000
 #define MPIC_TIMER_BASE_CNT		0x00010
@@ -110,10 +111,16 @@
 #define 	MPIC_VECPRI_SENSE_MASK			0x00400000
 #define MPIC_IRQ_DESTINATION		0x00010
 
+#define MPIC_FSL_BRR1			0x00000
+#define 	MPIC_FSL_BRR1_VER			0x0000ffff
+
 #define MPIC_MAX_IRQ_SOURCES	2048
 #define MPIC_MAX_CPUS		32
 #define MPIC_MAX_ISU		32
 
+#define MPIC_MAX_ERR      32
+#define MPIC_FSL_ERR_INT  16
+
 /*
  * Tsi108 implementation of MPIC has many differences from the original one
  */
@@ -266,6 +273,7 @@ struct mpic
 	struct irq_chip		hc_ipi;
 #endif
 	struct irq_chip		hc_tm;
+	struct irq_chip		hc_err;
 	const char		*name;
 	/* Flags */
 	unsigned int		flags;
@@ -279,6 +287,8 @@ struct mpic
 	/* vector numbers used for internal sources (ipi/timers) */
 	unsigned int		ipi_vecs[4];
 	unsigned int		timer_vecs[8];
+	/* vector numbers used for FSL MPIC error interrupts */
+	unsigned int		err_int_vecs[MPIC_MAX_ERR];
 
 	/* Spurious vector to program into unused sources */
 	unsigned int		spurious_vec;
@@ -296,11 +306,15 @@ struct mpic
 	phys_addr_t paddr;
 
 	/* The various ioremap'ed bases */
+	struct mpic_reg_bank	thiscpuregs;
 	struct mpic_reg_bank	gregs;
 	struct mpic_reg_bank	tmregs;
 	struct mpic_reg_bank	cpuregs[MPIC_MAX_CPUS];
 	struct mpic_reg_bank	isus[MPIC_MAX_ISU];
 
+	/* ioremap'ed base for error interrupt registers */
+	u32 __iomem	*err_regs;
+
 	/* Protected sources */
 	unsigned long		*protected;
 
@@ -365,6 +379,11 @@ struct mpic
 #define MPIC_NO_RESET			0x00004000
 /* Freescale MPIC (compatible includes "fsl,mpic") */
 #define MPIC_FSL			0x00008000
+/* Freescale MPIC supports EIMR (error interrupt mask register).
+ * This flag is set for MPIC version >= 4.1 (version determined
+ * from the BRR1 register).
+*/
+#define MPIC_FSL_HAS_EIMR		0x00010000
 
 /* MPIC HW modification ID */
 #define MPIC_REGSET_MASK		0xf0000000
diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/paca.h
index daf813f..e9e7a69 100644
--- a/arch/powerpc/include/asm/paca.h
+++ b/arch/powerpc/include/asm/paca.h
@@ -100,7 +100,7 @@ struct paca_struct {
 	/* SLB related definitions */
 	u16 vmalloc_sllp;
 	u16 slb_cache_ptr;
-	u16 slb_cache[SLB_CACHE_ENTRIES];
+	u32 slb_cache[SLB_CACHE_ENTRIES];
 #endif /* CONFIG_PPC_STD_MMU_64 */
 
 #ifdef CONFIG_PPC_BOOK3E
@@ -136,6 +136,7 @@ struct paca_struct {
 	u8 io_sync;			/* writel() needs spin_unlock sync */
 	u8 irq_work_pending;		/* IRQ_WORK interrupt while soft-disable */
 	u8 nap_state_lost;		/* NV GPR values lost in power7_idle */
+	u64 sprg3;			/* Saved user-visible sprg */
 
 #ifdef CONFIG_PPC_POWERNV
 	/* Pointer to OPAL machine check event structure set by the
diff --git a/arch/powerpc/include/asm/page_64.h b/arch/powerpc/include/asm/page_64.h
index fed85e6..cd915d6 100644
--- a/arch/powerpc/include/asm/page_64.h
+++ b/arch/powerpc/include/asm/page_64.h
@@ -78,11 +78,19 @@ extern u64 ppc64_pft_size;
 #define GET_LOW_SLICE_INDEX(addr)	((addr) >> SLICE_LOW_SHIFT)
 #define GET_HIGH_SLICE_INDEX(addr)	((addr) >> SLICE_HIGH_SHIFT)
 
+/*
+ * 1 bit per slice and we have one slice per 1TB
+ * Right now we support only 64TB.
+ * IF we change this we will have to change the type
+ * of high_slices
+ */
+#define SLICE_MASK_SIZE 8
+
 #ifndef __ASSEMBLY__
 
 struct slice_mask {
 	u16 low_slices;
-	u16 high_slices;
+	u64 high_slices;
 };
 
 struct mm_struct;
diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h
index 8cccbee..025a130 100644
--- a/arch/powerpc/include/asm/pci-bridge.h
+++ b/arch/powerpc/include/asm/pci-bridge.h
@@ -182,14 +182,25 @@ static inline int pci_device_from_OF_node(struct device_node *np,
 #if defined(CONFIG_EEH)
 static inline struct eeh_dev *of_node_to_eeh_dev(struct device_node *dn)
 {
+	/*
+	 * For those OF nodes whose parent isn't PCI bridge, they
+	 * don't have PCI_DN actually. So we have to skip them for
+	 * any EEH operations.
+	 */
+	if (!dn || !PCI_DN(dn))
+		return NULL;
+
 	return PCI_DN(dn)->edev;
 }
+#else
+#define of_node_to_eeh_dev(x) (NULL)
 #endif
 
 /** Find the bus corresponding to the indicated device node */
 extern struct pci_bus *pcibios_find_pci_bus(struct device_node *dn);
 
 /** Remove all of the PCI devices under this bus */
+extern void __pcibios_remove_pci_devices(struct pci_bus *bus, int purge_pe);
 extern void pcibios_remove_pci_devices(struct pci_bus *bus);
 
 /** Discover new pci devices under this bus, and add them */
diff --git a/arch/powerpc/include/asm/pgtable-ppc64-4k.h b/arch/powerpc/include/asm/pgtable-ppc64-4k.h
index 6eefdcf..12798c9 100644
--- a/arch/powerpc/include/asm/pgtable-ppc64-4k.h
+++ b/arch/powerpc/include/asm/pgtable-ppc64-4k.h
@@ -7,7 +7,7 @@
  */
 #define PTE_INDEX_SIZE  9
 #define PMD_INDEX_SIZE  7
-#define PUD_INDEX_SIZE  7
+#define PUD_INDEX_SIZE  9
 #define PGD_INDEX_SIZE  9
 
 #ifndef __ASSEMBLY__
@@ -19,7 +19,7 @@
 
 #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_PUD	(1 << PUD_INDEX_SIZE)
 #define PTRS_PER_PGD	(1 << PGD_INDEX_SIZE)
 
 /* PMD_SHIFT determines what a second-level page table entry can map */
diff --git a/arch/powerpc/include/asm/pgtable-ppc64-64k.h b/arch/powerpc/include/asm/pgtable-ppc64-64k.h
index 90533dd..be4e287 100644
--- a/arch/powerpc/include/asm/pgtable-ppc64-64k.h
+++ b/arch/powerpc/include/asm/pgtable-ppc64-64k.h
@@ -7,7 +7,7 @@
 #define PTE_INDEX_SIZE  12
 #define PMD_INDEX_SIZE  12
 #define PUD_INDEX_SIZE	0
-#define PGD_INDEX_SIZE  4
+#define PGD_INDEX_SIZE  6
 
 #ifndef __ASSEMBLY__
 #define PTE_TABLE_SIZE	(sizeof(real_pte_t) << PTE_INDEX_SIZE)
diff --git a/arch/powerpc/include/asm/pgtable-ppc64.h b/arch/powerpc/include/asm/pgtable-ppc64.h
index c420561..0182c20 100644
--- a/arch/powerpc/include/asm/pgtable-ppc64.h
+++ b/arch/powerpc/include/asm/pgtable-ppc64.h
@@ -21,17 +21,6 @@
 #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
-
-#ifdef CONFIG_PPC_STD_MMU_64
-#if TASK_SIZE_USER64 > (1UL << (USER_ESID_BITS + SID_SHIFT))
-#error TASK_SIZE_USER64 exceeds user VSID range
-#endif
-#endif
-
 /*
  * Define the address range of the kernel non-linear virtual area
  */
@@ -41,7 +30,7 @@
 #else
 #define KERN_VIRT_START ASM_CONST(0xD000000000000000)
 #endif
-#define KERN_VIRT_SIZE	PGTABLE_RANGE
+#define KERN_VIRT_SIZE	ASM_CONST(0x0000100000000000)
 
 /*
  * The vmalloc space starts at the beginning of that region, and
@@ -117,9 +106,6 @@
 
 #ifndef __ASSEMBLY__
 
-#include <linux/stddef.h>
-#include <asm/tlbflush.h>
-
 /*
  * This is the default implementation of various PTE accessors, it's
  * used in all cases except Book3S with 64K pages where we have a
@@ -198,7 +184,8 @@
 /* to find an entry in a kernel page-table-directory */
 /* This now only contains the vmalloc pages */
 #define pgd_offset_k(address) pgd_offset(&init_mm, address)
-
+extern void hpte_need_flush(struct mm_struct *mm, unsigned long addr,
+			    pte_t *ptep, unsigned long pte, int huge);
 
 /* Atomic PTE updates */
 static inline unsigned long pte_update(struct mm_struct *mm,
diff --git a/arch/powerpc/include/asm/pgtable.h b/arch/powerpc/include/asm/pgtable.h
index 2e0e411..a9cbd3b 100644
--- a/arch/powerpc/include/asm/pgtable.h
+++ b/arch/powerpc/include/asm/pgtable.h
@@ -9,14 +9,6 @@
 
 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)
@@ -27,6 +19,8 @@ static inline void assert_pte_locked(struct mm_struct *mm, unsigned long addr)
 
 #ifndef __ASSEMBLY__
 
+#include <asm/tlbflush.h>
+
 /* 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; }
diff --git a/arch/powerpc/include/asm/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h
index 4c25319..5f73ce6 100644
--- a/arch/powerpc/include/asm/ppc-opcode.h
+++ b/arch/powerpc/include/asm/ppc-opcode.h
@@ -126,6 +126,7 @@
 #define PPC_INST_TLBIVAX		0x7c000624
 #define PPC_INST_TLBSRX_DOT		0x7c0006a5
 #define PPC_INST_XXLOR			0xf0000510
+#define PPC_INST_XVCPSGNDP		0xf0000780
 
 #define PPC_INST_NAP			0x4c000364
 #define PPC_INST_SLEEP			0x4c0003a4
@@ -277,6 +278,8 @@
 					       VSX_XX1((s), a, b))
 #define XXLOR(t, a, b)		stringify_in_c(.long PPC_INST_XXLOR | \
 					       VSX_XX3((t), a, b))
+#define XVCPSGNDP(t, a, b)	stringify_in_c(.long (PPC_INST_XVCPSGNDP | \
+					       VSX_XX3((t), (a), (b))))
 
 #define PPC_NAP			stringify_in_c(.long PPC_INST_NAP)
 #define PPC_SLEEP		stringify_in_c(.long PPC_INST_SLEEP)
diff --git a/arch/powerpc/include/asm/ppc-pci.h b/arch/powerpc/include/asm/ppc-pci.h
index 80fa704..ed57fa7 100644
--- a/arch/powerpc/include/asm/ppc-pci.h
+++ b/arch/powerpc/include/asm/ppc-pci.h
@@ -47,19 +47,17 @@ extern int rtas_setup_phb(struct pci_controller *phb);
 
 #ifdef CONFIG_EEH
 
-void pci_addr_cache_build(void);
-void pci_addr_cache_insert_device(struct pci_dev *dev);
-void pci_addr_cache_remove_device(struct pci_dev *dev);
-struct pci_dev *pci_addr_cache_get_device(unsigned long addr);
-void eeh_slot_error_detail(struct eeh_dev *edev, int severity);
-int eeh_pci_enable(struct eeh_dev *edev, int function);
-int eeh_reset_pe(struct eeh_dev *);
-void eeh_restore_bars(struct eeh_dev *);
+void eeh_addr_cache_insert_dev(struct pci_dev *dev);
+void eeh_addr_cache_rmv_dev(struct pci_dev *dev);
+struct eeh_dev *eeh_addr_cache_get_dev(unsigned long addr);
+void eeh_slot_error_detail(struct eeh_pe *pe, int severity);
+int eeh_pci_enable(struct eeh_pe *pe, int function);
+int eeh_reset_pe(struct eeh_pe *);
+void eeh_save_bars(struct eeh_dev *edev);
 int rtas_write_config(struct pci_dn *, int where, int size, u32 val);
 int rtas_read_config(struct pci_dn *, int where, int size, u32 *val);
-void eeh_mark_slot(struct device_node *dn, int mode_flag);
-void eeh_clear_slot(struct device_node *dn, int mode_flag);
-struct device_node *eeh_find_device_pe(struct device_node *dn);
+void eeh_pe_state_mark(struct eeh_pe *pe, int state);
+void eeh_pe_state_clear(struct eeh_pe *pe, int state);
 
 void eeh_sysfs_add_device(struct pci_dev *pdev);
 void eeh_sysfs_remove_device(struct pci_dev *pdev);
diff --git a/arch/powerpc/include/asm/probes.h b/arch/powerpc/include/asm/probes.h
new file mode 100644
index 0000000..5f1e15b
--- /dev/null
+++ b/arch/powerpc/include/asm/probes.h
@@ -0,0 +1,42 @@
+#ifndef _ASM_POWERPC_PROBES_H
+#define _ASM_POWERPC_PROBES_H
+#ifdef __KERNEL__
+/*
+ * Definitions common to probes files
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 IBM Corporation, 2012
+ */
+#include <linux/types.h>
+
+typedef u32 ppc_opcode_t;
+#define BREAKPOINT_INSTRUCTION	0x7fe00008	/* trap */
+
+/* Trap definitions per ISA */
+#define IS_TW(instr)		(((instr) & 0xfc0007fe) == 0x7c000008)
+#define IS_TD(instr)		(((instr) & 0xfc0007fe) == 0x7c000088)
+#define IS_TDI(instr)		(((instr) & 0xfc000000) == 0x08000000)
+#define IS_TWI(instr)		(((instr) & 0xfc000000) == 0x0c000000)
+
+#ifdef CONFIG_PPC64
+#define is_trap(instr)		(IS_TW(instr) || IS_TD(instr) || \
+				IS_TWI(instr) || IS_TDI(instr))
+#else
+#define is_trap(instr)		(IS_TW(instr) || IS_TWI(instr))
+#endif /* CONFIG_PPC64 */
+
+#endif /* __KERNEL__ */
+#endif	/* _ASM_POWERPC_PROBES_H */
diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h
index 54b73a2..8734b38 100644
--- a/arch/powerpc/include/asm/processor.h
+++ b/arch/powerpc/include/asm/processor.h
@@ -74,9 +74,6 @@ struct task_struct;
 void start_thread(struct pt_regs *regs, unsigned long fdptr, unsigned long sp);
 void release_thread(struct task_struct *);
 
-/* Create a new kernel thread. */
-extern long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
-
 /* Lazy FPU handling on uni-processor */
 extern struct task_struct *last_task_used_math;
 extern struct task_struct *last_task_used_altivec;
@@ -97,8 +94,8 @@ extern struct task_struct *last_task_used_spe;
 #endif
 
 #ifdef CONFIG_PPC64
-/* 64-bit user address space is 44-bits (16TB user VM) */
-#define TASK_SIZE_USER64 (0x0000100000000000UL)
+/* 64-bit user address space is 46-bits (64TB user VM) */
+#define TASK_SIZE_USER64 (0x0000400000000000UL)
 
 /* 
  * 32-bit user address space is 4GB - 1 page 
@@ -219,6 +216,8 @@ struct thread_struct {
 #endif /* CONFIG_HAVE_HW_BREAKPOINT */
 #endif
 	unsigned long	dabr;		/* Data address breakpoint register */
+	unsigned long	dabrx;		/*      ... extension  */
+	unsigned long	trap_nr;	/* last trap # on this thread */
 #ifdef CONFIG_ALTIVEC
 	/* Complete AltiVec register set */
 	vector128	vr[32] __attribute__((aligned(16)));
diff --git a/arch/powerpc/include/asm/pte-hash64-64k.h b/arch/powerpc/include/asm/pte-hash64-64k.h
index 59247e8..eedf427 100644
--- a/arch/powerpc/include/asm/pte-hash64-64k.h
+++ b/arch/powerpc/include/asm/pte-hash64-64k.h
@@ -58,14 +58,16 @@
 /* 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_subpages(rpte, psize, vpn, index, shift)	\
+	do {								\
+		unsigned long __end = vpn + (1UL << (PAGE_SHIFT - VPN_SHIFT));	\
+		unsigned __split = (psize == MMU_PAGE_4K ||		\
+				    psize == MMU_PAGE_64K_AP);		\
+		shift = mmu_psize_defs[psize].shift;			\
+		for (index = 0; vpn < __end; index++,			\
+			     vpn += (1L << (shift - VPN_SHIFT))) {	\
+			if (!__split || __rpte_sub_valid(rpte, index))	\
+				do {
 
 #define pte_iterate_hashed_end() } while(0); } } while(0)
 
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index 6386086..a1096fb 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -208,6 +208,9 @@
 #define SPRN_DABRX	0x3F7	/* Data Address Breakpoint Register Extension */
 #define   DABRX_USER	(1UL << 0)
 #define   DABRX_KERNEL	(1UL << 1)
+#define   DABRX_HYP	(1UL << 2)
+#define   DABRX_BTI	(1UL << 3)
+#define   DABRX_ALL     (DABRX_BTI | DABRX_HYP | DABRX_KERNEL | DABRX_USER)
 #define SPRN_DAR	0x013	/* Data Address Register */
 #define SPRN_DBCR	0x136	/* e300 Data Breakpoint Control Reg */
 #define SPRN_DSISR	0x012	/* Data Storage Interrupt Status Register */
@@ -521,6 +524,7 @@
 
 #define SPRN_HSRR0	0x13A	/* Save/Restore Register 0 */
 #define SPRN_HSRR1	0x13B	/* Save/Restore Register 1 */
+#define   HSRR1_DENORM		0x00100000 /* Denorm exception */
 
 #define SPRN_TBCTL	0x35f	/* PA6T Timebase control register */
 #define   TBCTL_FREEZE		0x0000000000000000ull /* Freeze all tbs */
@@ -761,7 +765,8 @@
  * 64-bit embedded
  *	- SPRG0 generic exception scratch
  *	- SPRG2 TLB exception stack
- *	- SPRG3 CPU and NUMA node for VDSO getcpu (user visible)
+ *	- SPRG3 critical exception scratch and
+ *        CPU and NUMA node for VDSO getcpu (user visible)
  *	- SPRG4 unused (user visible)
  *	- SPRG6 TLB miss scratch (user visible, sorry !)
  *	- SPRG7 critical exception scratch
@@ -858,11 +863,12 @@
 
 #ifdef CONFIG_PPC_BOOK3E_64
 #define SPRN_SPRG_MC_SCRATCH	SPRN_SPRG8
-#define SPRN_SPRG_CRIT_SCRATCH	SPRN_SPRG7
+#define SPRN_SPRG_CRIT_SCRATCH	SPRN_SPRG3
 #define SPRN_SPRG_DBG_SCRATCH	SPRN_SPRG9
 #define SPRN_SPRG_TLB_EXFRAME	SPRN_SPRG2
 #define SPRN_SPRG_TLB_SCRATCH	SPRN_SPRG6
 #define SPRN_SPRG_GEN_SCRATCH	SPRN_SPRG0
+#define SPRN_SPRG_GDBELL_SCRATCH SPRN_SPRG_GEN_SCRATCH
 
 #define SET_PACA(rX)	mtspr	SPRN_SPRG_PACA,rX
 #define GET_PACA(rX)	mfspr	rX,SPRN_SPRG_PACA
@@ -937,7 +943,7 @@
 #define PVR_VER(pvr)	(((pvr) >>  16) & 0xFFFF)	/* Version field */
 #define PVR_REV(pvr)	(((pvr) >>   0) & 0xFFFF)	/* Revison field */
 
-#define __is_processor(pv)	(PVR_VER(mfspr(SPRN_PVR)) == (pv))
+#define pvr_version_is(pvr)	(PVR_VER(mfspr(SPRN_PVR)) == (pvr))
 
 /*
  * IBM has further subdivided the standard PowerPC 16-bit version and
@@ -1002,25 +1008,25 @@
 #define PVR_476_ISS	0x00052000
 
 /* 64-bit processors */
-/* XXX the prefix should be PVR_, we'll do a global sweep to fix it one day */
-#define PV_NORTHSTAR	0x0033
-#define PV_PULSAR	0x0034
-#define PV_POWER4	0x0035
-#define PV_ICESTAR	0x0036
-#define PV_SSTAR	0x0037
-#define PV_POWER4p	0x0038
-#define PV_970		0x0039
-#define PV_POWER5	0x003A
-#define PV_POWER5p	0x003B
-#define PV_970FX	0x003C
-#define PV_POWER6	0x003E
-#define PV_POWER7	0x003F
-#define PV_630		0x0040
-#define PV_630p	0x0041
-#define PV_970MP	0x0044
-#define PV_970GX	0x0045
-#define PV_BE		0x0070
-#define PV_PA6T		0x0090
+#define PVR_NORTHSTAR	0x0033
+#define PVR_PULSAR	0x0034
+#define PVR_POWER4	0x0035
+#define PVR_ICESTAR	0x0036
+#define PVR_SSTAR	0x0037
+#define PVR_POWER4p	0x0038
+#define PVR_970		0x0039
+#define PVR_POWER5	0x003A
+#define PVR_POWER5p	0x003B
+#define PVR_970FX	0x003C
+#define PVR_POWER6	0x003E
+#define PVR_POWER7	0x003F
+#define PVR_630		0x0040
+#define PVR_630p	0x0041
+#define PVR_970MP	0x0044
+#define PVR_970GX	0x0045
+#define PVR_POWER7p	0x004A
+#define PVR_BE		0x0070
+#define PVR_PA6T	0x0090
 
 /* Macros for setting and retrieving special purpose registers */
 #ifndef __ASSEMBLY__
diff --git a/arch/powerpc/include/asm/reg_booke.h b/arch/powerpc/include/asm/reg_booke.h
index 2d916c4..e07e6af 100644
--- a/arch/powerpc/include/asm/reg_booke.h
+++ b/arch/powerpc/include/asm/reg_booke.h
@@ -539,6 +539,13 @@
 #define TCR_FIE		0x00800000	/* FIT Interrupt Enable */
 #define TCR_ARE		0x00400000	/* Auto Reload Enable */
 
+#ifdef CONFIG_E500
+#define TCR_GET_WP(tcr)  ((((tcr) & 0xC0000000) >> 30) | \
+			      (((tcr) & 0x1E0000) >> 15))
+#else
+#define TCR_GET_WP(tcr)  (((tcr) & 0xC0000000) >> 30)
+#endif
+
 /* Bit definitions for the TSR. */
 #define TSR_ENW		0x80000000	/* Enable Next Watchdog */
 #define TSR_WIS		0x40000000	/* WDT Interrupt Status */
diff --git a/arch/powerpc/include/asm/setup.h b/arch/powerpc/include/asm/setup.h
index d084ce1..8b9a306 100644
--- a/arch/powerpc/include/asm/setup.h
+++ b/arch/powerpc/include/asm/setup.h
@@ -9,7 +9,7 @@ extern void ppc_printk_progress(char *s, unsigned short hex);
 extern unsigned int rtas_data;
 extern int mem_init_done;	/* set on boot once kmalloc can be called */
 extern int init_bootmem_done;	/* set once bootmem is available */
-extern phys_addr_t memory_limit;
+extern unsigned long long memory_limit;
 extern unsigned long klimit;
 extern void *zalloc_maybe_bootmem(size_t size, gfp_t mask);
 
diff --git a/arch/powerpc/include/asm/siginfo.h b/arch/powerpc/include/asm/siginfo.h
index 49495b0..ccce3ef 100644
--- a/arch/powerpc/include/asm/siginfo.h
+++ b/arch/powerpc/include/asm/siginfo.h
@@ -10,7 +10,6 @@
 
 #ifdef __powerpc64__
 #    define __ARCH_SI_PREAMBLE_SIZE	(4 * sizeof(int))
-#    define SI_PAD_SIZE32		((SI_MAX_SIZE/sizeof(int)) - 3)
 #endif
 
 #include <asm-generic/siginfo.h>
diff --git a/arch/powerpc/include/asm/smp.h b/arch/powerpc/include/asm/smp.h
index ebc24dc..e807e9d 100644
--- a/arch/powerpc/include/asm/smp.h
+++ b/arch/powerpc/include/asm/smp.h
@@ -65,6 +65,7 @@ int generic_cpu_disable(void);
 void generic_cpu_die(unsigned int cpu);
 void generic_mach_cpu_die(void);
 void generic_set_cpu_dead(unsigned int cpu);
+void generic_set_cpu_up(unsigned int cpu);
 int generic_check_cpu_restart(unsigned int cpu);
 #endif
 
@@ -190,6 +191,7 @@ extern unsigned long __secondary_hold_spinloop;
 extern unsigned long __secondary_hold_acknowledge;
 extern char __secondary_hold;
 
+extern void __early_start(void);
 #endif /* __ASSEMBLY__ */
 
 #endif /* __KERNEL__ */
diff --git a/arch/powerpc/include/asm/sparsemem.h b/arch/powerpc/include/asm/sparsemem.h
index 0c5fa31..f6fc0ee 100644
--- a/arch/powerpc/include/asm/sparsemem.h
+++ b/arch/powerpc/include/asm/sparsemem.h
@@ -10,8 +10,8 @@
  */
 #define SECTION_SIZE_BITS       24
 
-#define MAX_PHYSADDR_BITS       44
-#define MAX_PHYSMEM_BITS        44
+#define MAX_PHYSADDR_BITS       46
+#define MAX_PHYSMEM_BITS        46
 
 #endif /* CONFIG_SPARSEMEM */
 
diff --git a/arch/powerpc/include/asm/swiotlb.h b/arch/powerpc/include/asm/swiotlb.h
index 8979d4c..de99d6e 100644
--- a/arch/powerpc/include/asm/swiotlb.h
+++ b/arch/powerpc/include/asm/swiotlb.h
@@ -22,4 +22,10 @@ int __init swiotlb_setup_bus_notifier(void);
 
 extern void pci_dma_dev_setup_swiotlb(struct pci_dev *pdev);
 
+#ifdef CONFIG_SWIOTLB
+void swiotlb_detect_4g(void);
+#else
+static inline void swiotlb_detect_4g(void) {}
+#endif
+
 #endif /* __ASM_SWIOTLB_H */
diff --git a/arch/powerpc/include/asm/syscalls.h b/arch/powerpc/include/asm/syscalls.h
index 4084e56..329db4e 100644
--- a/arch/powerpc/include/asm/syscalls.h
+++ b/arch/powerpc/include/asm/syscalls.h
@@ -17,9 +17,6 @@ asmlinkage unsigned long sys_mmap(unsigned long addr, size_t len,
 asmlinkage unsigned long sys_mmap2(unsigned long addr, size_t len,
 		unsigned long prot, unsigned long flags,
 		unsigned long fd, unsigned long pgoff);
-asmlinkage int sys_execve(unsigned long a0, unsigned long a1,
-		unsigned long a2, unsigned long a3, unsigned long a4,
-		unsigned long a5, struct pt_regs *regs);
 asmlinkage int sys_clone(unsigned long clone_flags, unsigned long usp,
 		int __user *parent_tidp, void __user *child_threadptr,
 		int __user *child_tidp, int p6, struct pt_regs *regs);
diff --git a/arch/powerpc/include/asm/thread_info.h b/arch/powerpc/include/asm/thread_info.h
index faf9352..406b7b9 100644
--- a/arch/powerpc/include/asm/thread_info.h
+++ b/arch/powerpc/include/asm/thread_info.h
@@ -102,7 +102,10 @@ static inline struct thread_info *current_thread_info(void)
 #define TIF_RESTOREALL		11	/* Restore all regs (implies NOERROR) */
 #define TIF_NOERROR		12	/* Force successful syscall return */
 #define TIF_NOTIFY_RESUME	13	/* callback before returning to user */
+#define TIF_UPROBE		14	/* breakpointed or single-stepping */
 #define TIF_SYSCALL_TRACEPOINT	15	/* syscall tracepoint instrumentation */
+#define TIF_EMULATE_STACK_STORE	16	/* Is an instruction emulation
+						for stack store? */
 
 /* as above, but as bit values */
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
@@ -118,12 +121,14 @@ static inline struct thread_info *current_thread_info(void)
 #define _TIF_RESTOREALL		(1<<TIF_RESTOREALL)
 #define _TIF_NOERROR		(1<<TIF_NOERROR)
 #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
+#define _TIF_UPROBE		(1<<TIF_UPROBE)
 #define _TIF_SYSCALL_TRACEPOINT	(1<<TIF_SYSCALL_TRACEPOINT)
+#define _TIF_EMULATE_STACK_STORE	(1<<TIF_EMULATE_STACK_STORE)
 #define _TIF_SYSCALL_T_OR_A	(_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \
 				 _TIF_SECCOMP | _TIF_SYSCALL_TRACEPOINT)
 
 #define _TIF_USER_WORK_MASK	(_TIF_SIGPENDING | _TIF_NEED_RESCHED | \
-				 _TIF_NOTIFY_RESUME)
+				 _TIF_NOTIFY_RESUME | _TIF_UPROBE)
 #define _TIF_PERSYSCALL_MASK	(_TIF_RESTOREALL|_TIF_NOERROR)
 
 /* Bits in local_flags */
@@ -177,6 +182,8 @@ static inline bool test_thread_local_flags(unsigned int flags)
 #define is_32bit_task()	(1)
 #endif
 
+#define tsk_is_polling(t) test_tsk_thread_flag(t, TIF_POLLING_NRFLAG)
+
 #endif	/* !__ASSEMBLY__ */
 
 #endif /* __KERNEL__ */
diff --git a/arch/powerpc/include/asm/time.h b/arch/powerpc/include/asm/time.h
index 3b4b4a8..c1f2676 100644
--- a/arch/powerpc/include/asm/time.h
+++ b/arch/powerpc/include/asm/time.h
@@ -197,12 +197,6 @@ struct cpu_usage {
 
 DECLARE_PER_CPU(struct cpu_usage, cpu_usage_array);
 
-#if defined(CONFIG_VIRT_CPU_ACCOUNTING)
-#define account_process_vtime(tsk)		account_process_tick(tsk, 0)
-#else
-#define account_process_vtime(tsk)		do { } while (0)
-#endif
-
 extern void secondary_cpu_time_init(void);
 
 DECLARE_PER_CPU(u64, decrementers_next_tb);
diff --git a/arch/powerpc/include/asm/tlbflush.h b/arch/powerpc/include/asm/tlbflush.h
index 81143fc..61a5927 100644
--- a/arch/powerpc/include/asm/tlbflush.h
+++ b/arch/powerpc/include/asm/tlbflush.h
@@ -95,7 +95,7 @@ struct ppc64_tlb_batch {
 	unsigned long		index;
 	struct mm_struct	*mm;
 	real_pte_t		pte[PPC64_TLB_BATCH_NR];
-	unsigned long		vaddr[PPC64_TLB_BATCH_NR];
+	unsigned long		vpn[PPC64_TLB_BATCH_NR];
 	unsigned int		psize;
 	int			ssize;
 };
@@ -103,9 +103,6 @@ DECLARE_PER_CPU(struct ppc64_tlb_batch, ppc64_tlb_batch);
 
 extern void __flush_tlb_pending(struct ppc64_tlb_batch *batch);
 
-extern void hpte_need_flush(struct mm_struct *mm, unsigned long addr,
-			    pte_t *ptep, unsigned long pte, int huge);
-
 #define __HAVE_ARCH_ENTER_LAZY_MMU_MODE
 
 static inline void arch_enter_lazy_mmu_mode(void)
@@ -127,7 +124,7 @@ static inline void arch_leave_lazy_mmu_mode(void)
 #define arch_flush_lazy_mmu_mode()      do {} while (0)
 
 
-extern void flush_hash_page(unsigned long va, real_pte_t pte, int psize,
+extern void flush_hash_page(unsigned long vpn, real_pte_t pte, int psize,
 			    int ssize, int local);
 extern void flush_hash_range(unsigned long number, int local);
 
diff --git a/arch/powerpc/include/asm/uaccess.h b/arch/powerpc/include/asm/uaccess.h
index 17bb40c..4db4959 100644
--- a/arch/powerpc/include/asm/uaccess.h
+++ b/arch/powerpc/include/asm/uaccess.h
@@ -98,11 +98,6 @@ struct exception_table_entry {
  * PowerPC, we can just do these as direct assignments.  (Of course, the
  * exception handling means that it's no longer "just"...)
  *
- * The "user64" versions of the user access functions are versions that
- * allow access of 64-bit data. The "get_user" functions do not
- * properly handle 64-bit data because the value gets down cast to a long.
- * The "put_user" functions already handle 64-bit data properly but we add
- * "user64" versions for completeness
  */
 #define get_user(x, ptr) \
 	__get_user_check((x), (ptr), sizeof(*(ptr)))
@@ -114,12 +109,6 @@ struct exception_table_entry {
 #define __put_user(x, ptr) \
 	__put_user_nocheck((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)))
 
-#ifndef __powerpc64__
-#define __get_user64(x, ptr) \
-	__get_user64_nocheck((x), (ptr), sizeof(*(ptr)))
-#define __put_user64(x, ptr) __put_user(x, ptr)
-#endif
-
 #define __get_user_inatomic(x, ptr) \
 	__get_user_nosleep((x), (ptr), sizeof(*(ptr)))
 #define __put_user_inatomic(x, ptr) \
diff --git a/arch/powerpc/include/asm/unistd.h b/arch/powerpc/include/asm/unistd.h
index bd377a3..26a6825 100644
--- a/arch/powerpc/include/asm/unistd.h
+++ b/arch/powerpc/include/asm/unistd.h
@@ -420,6 +420,8 @@
 #define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
 #define __ARCH_WANT_SYS_NEWFSTATAT
 #endif
+#define __ARCH_WANT_SYS_EXECVE
+#define __ARCH_WANT_KERNEL_EXECVE
 
 /*
  * "Conditional" syscalls
diff --git a/arch/powerpc/include/asm/uprobes.h b/arch/powerpc/include/asm/uprobes.h
new file mode 100644
index 0000000..b532060
--- /dev/null
+++ b/arch/powerpc/include/asm/uprobes.h
@@ -0,0 +1,54 @@
+#ifndef _ASM_UPROBES_H
+#define _ASM_UPROBES_H
+/*
+ * User-space Probes (UProbes) for powerpc
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 IBM Corporation, 2007-2012
+ *
+ * Adapted from the x86 port by Ananth N Mavinakayanahalli <ananth@in.ibm.com>
+ */
+
+#include <linux/notifier.h>
+#include <asm/probes.h>
+
+typedef ppc_opcode_t uprobe_opcode_t;
+
+#define MAX_UINSN_BYTES		4
+#define UPROBE_XOL_SLOT_BYTES	(MAX_UINSN_BYTES)
+
+/* The following alias is needed for reference from arch-agnostic code */
+#define UPROBE_SWBP_INSN	BREAKPOINT_INSTRUCTION
+#define UPROBE_SWBP_INSN_SIZE	4 /* swbp insn size in bytes */
+
+struct arch_uprobe {
+	union {
+		u8	insn[MAX_UINSN_BYTES];
+		u32	ainsn;
+	};
+};
+
+struct arch_uprobe_task {
+	unsigned long	saved_trap_nr;
+};
+
+extern int  arch_uprobe_analyze_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long addr);
+extern int  arch_uprobe_pre_xol(struct arch_uprobe *aup, struct pt_regs *regs);
+extern int  arch_uprobe_post_xol(struct arch_uprobe *aup, struct pt_regs *regs);
+extern bool arch_uprobe_xol_was_trapped(struct task_struct *tsk);
+extern int  arch_uprobe_exception_notify(struct notifier_block *self, unsigned long val, void *data);
+extern void arch_uprobe_abort_xol(struct arch_uprobe *aup, struct pt_regs *regs);
+#endif	/* _ASM_UPROBES_H */
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index bb282dd..cde12f8 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -96,6 +96,7 @@ obj-$(CONFIG_MODULES)		+= ppc_ksyms.o
 obj-$(CONFIG_BOOTX_TEXT)	+= btext.o
 obj-$(CONFIG_SMP)		+= smp.o
 obj-$(CONFIG_KPROBES)		+= kprobes.o
+obj-$(CONFIG_UPROBES)		+= uprobes.o
 obj-$(CONFIG_PPC_UDBG_16550)	+= legacy_serial.o udbg_16550.o
 obj-$(CONFIG_STACKTRACE)	+= stacktrace.o
 obj-$(CONFIG_SWIOTLB)		+= dma-swiotlb.o
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index e899572..7523539 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -206,6 +206,7 @@ int main(void)
 	DEFINE(PACA_SYSTEM_TIME, offsetof(struct paca_struct, system_time));
 	DEFINE(PACA_TRAP_SAVE, offsetof(struct paca_struct, trap_save));
 	DEFINE(PACA_NAPSTATELOST, offsetof(struct paca_struct, nap_state_lost));
+	DEFINE(PACA_SPRG3, offsetof(struct paca_struct, sprg3));
 #endif /* CONFIG_PPC64 */
 
 	/* RTAS */
@@ -534,7 +535,6 @@ int main(void)
 	HSTATE_FIELD(HSTATE_VMHANDLER, vmhandler);
 	HSTATE_FIELD(HSTATE_SCRATCH0, scratch0);
 	HSTATE_FIELD(HSTATE_SCRATCH1, scratch1);
-	HSTATE_FIELD(HSTATE_SPRG3, sprg3);
 	HSTATE_FIELD(HSTATE_IN_GUEST, in_guest);
 	HSTATE_FIELD(HSTATE_RESTORE_HID5, restore_hid5);
 	HSTATE_FIELD(HSTATE_NAPPING, napping);
diff --git a/arch/powerpc/kernel/cpu_setup_fsl_booke.S b/arch/powerpc/kernel/cpu_setup_fsl_booke.S
index 69fdd23..dcd8819 100644
--- a/arch/powerpc/kernel/cpu_setup_fsl_booke.S
+++ b/arch/powerpc/kernel/cpu_setup_fsl_booke.S
@@ -16,6 +16,8 @@
 #include <asm/processor.h>
 #include <asm/cputable.h>
 #include <asm/ppc_asm.h>
+#include <asm/mmu-book3e.h>
+#include <asm/asm-offsets.h>
 
 _GLOBAL(__e500_icache_setup)
 	mfspr	r0, SPRN_L1CSR1
@@ -73,27 +75,81 @@ _GLOBAL(__setup_cpu_e500v2)
 	mtlr	r4
 	blr
 _GLOBAL(__setup_cpu_e500mc)
-	mr	r5, r4
-	mflr	r4
+_GLOBAL(__setup_cpu_e5500)
+	mflr	r5
 	bl	__e500_icache_setup
 	bl	__e500_dcache_setup
 	bl	__setup_e500mc_ivors
-	mtlr	r4
+	/*
+	 * We only want to touch IVOR38-41 if we're running on hardware
+	 * that supports category E.HV.  The architectural way to determine
+	 * this is MMUCFG[LPIDSIZE].
+	 */
+	mfspr	r3, SPRN_MMUCFG
+	rlwinm.	r3, r3, 0, MMUCFG_LPIDSIZE
+	beq	1f
+	bl	__setup_ehv_ivors
+	b	2f
+1:
+	lwz	r3, CPU_SPEC_FEATURES(r4)
+	/* We need this check as cpu_setup is also called for
+	 * the secondary cores. So, if we have already cleared
+	 * the feature on the primary core, avoid doing it on the
+	 * secondary core.
+	 */
+	andis.	r6, r3, CPU_FTR_EMB_HV@h
+	beq	2f
+	rlwinm	r3, r3, 0, ~CPU_FTR_EMB_HV
+	stw	r3, CPU_SPEC_FEATURES(r4)
+2:
+	mtlr	r5
 	blr
 #endif
-/* Right now, restore and setup are the same thing */
+
+#ifdef CONFIG_PPC_BOOK3E_64
 _GLOBAL(__restore_cpu_e5500)
-_GLOBAL(__setup_cpu_e5500)
 	mflr	r4
 	bl	__e500_icache_setup
 	bl	__e500_dcache_setup
-#ifdef CONFIG_PPC_BOOK3E_64
 	bl	.__setup_base_ivors
 	bl	.setup_perfmon_ivor
 	bl	.setup_doorbell_ivors
+	/*
+	 * We only want to touch IVOR38-41 if we're running on hardware
+	 * that supports category E.HV.  The architectural way to determine
+	 * this is MMUCFG[LPIDSIZE].
+	 */
+	mfspr	r10,SPRN_MMUCFG
+	rlwinm.	r10,r10,0,MMUCFG_LPIDSIZE
+	beq	1f
 	bl	.setup_ehv_ivors
-#else
-	bl	__setup_e500mc_ivors
-#endif
+1:
 	mtlr	r4
 	blr
+
+_GLOBAL(__setup_cpu_e5500)
+	mflr	r5
+	bl	__e500_icache_setup
+	bl	__e500_dcache_setup
+	bl	.__setup_base_ivors
+	bl	.setup_perfmon_ivor
+	bl	.setup_doorbell_ivors
+	/*
+	 * We only want to touch IVOR38-41 if we're running on hardware
+	 * that supports category E.HV.  The architectural way to determine
+	 * this is MMUCFG[LPIDSIZE].
+	 */
+	mfspr	r10,SPRN_MMUCFG
+	rlwinm.	r10,r10,0,MMUCFG_LPIDSIZE
+	beq	1f
+	bl	.setup_ehv_ivors
+	b	2f
+1:
+	ld	r10,CPU_SPEC_FEATURES(r4)
+	LOAD_REG_IMMEDIATE(r9,CPU_FTR_EMB_HV)
+	andc	r10,r10,r9
+	std	r10,CPU_SPEC_FEATURES(r4)
+2:
+	mtlr	r5
+	blr
+#endif
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index 455faa3..0514c21 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -2016,7 +2016,9 @@ static struct cpu_spec __initdata cpu_specs[] = {
 		.oprofile_cpu_type	= "ppc/e500mc",
 		.oprofile_type		= PPC_OPROFILE_FSL_EMB,
 		.cpu_setup		= __setup_cpu_e5500,
+#ifndef CONFIG_PPC32
 		.cpu_restore		= __restore_cpu_e5500,
+#endif
 		.machine_check		= machine_check_e500mc,
 		.platform		= "ppce5500",
 	},
@@ -2034,7 +2036,9 @@ static struct cpu_spec __initdata cpu_specs[] = {
 		.oprofile_cpu_type	= "ppc/e6500",
 		.oprofile_type		= PPC_OPROFILE_FSL_EMB,
 		.cpu_setup		= __setup_cpu_e5500,
+#ifndef CONFIG_PPC32
 		.cpu_restore		= __restore_cpu_e5500,
+#endif
 		.machine_check		= machine_check_e500mc,
 		.platform		= "ppce6500",
 	},
diff --git a/arch/powerpc/kernel/dma-swiotlb.c b/arch/powerpc/kernel/dma-swiotlb.c
index 4694365..bd1a2ab 100644
--- a/arch/powerpc/kernel/dma-swiotlb.c
+++ b/arch/powerpc/kernel/dma-swiotlb.c
@@ -12,6 +12,7 @@
  */
 
 #include <linux/dma-mapping.h>
+#include <linux/memblock.h>
 #include <linux/pfn.h>
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
@@ -20,7 +21,6 @@
 #include <asm/machdep.h>
 #include <asm/swiotlb.h>
 #include <asm/dma.h>
-#include <asm/abs_addr.h>
 
 unsigned int ppc_swiotlb_enable;
 
@@ -105,3 +105,23 @@ int __init swiotlb_setup_bus_notifier(void)
 			      &ppc_swiotlb_plat_bus_notifier);
 	return 0;
 }
+
+void swiotlb_detect_4g(void)
+{
+	if ((memblock_end_of_DRAM() - 1) > 0xffffffff)
+		ppc_swiotlb_enable = 1;
+}
+
+static int __init swiotlb_late_init(void)
+{
+	if (ppc_swiotlb_enable) {
+		swiotlb_print_info();
+		set_pci_dma_ops(&swiotlb_dma_ops);
+		ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb;
+	} else {
+		swiotlb_free();
+	}
+
+	return 0;
+}
+subsys_initcall(swiotlb_late_init);
diff --git a/arch/powerpc/kernel/dma.c b/arch/powerpc/kernel/dma.c
index 355b9d8..8032b97 100644
--- a/arch/powerpc/kernel/dma.c
+++ b/arch/powerpc/kernel/dma.c
@@ -14,7 +14,6 @@
 #include <linux/pci.h>
 #include <asm/vio.h>
 #include <asm/bug.h>
-#include <asm/abs_addr.h>
 #include <asm/machdep.h>
 
 /*
@@ -50,7 +49,7 @@ void *dma_direct_alloc_coherent(struct device *dev, size_t size,
 		return NULL;
 	ret = page_address(page);
 	memset(ret, 0, size);
-	*dma_handle = virt_to_abs(ret) + get_dma_offset(dev);
+	*dma_handle = __pa(ret) + get_dma_offset(dev);
 
 	return ret;
 #endif
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S
index ead5016..9499385 100644
--- a/arch/powerpc/kernel/entry_32.S
+++ b/arch/powerpc/kernel/entry_32.S
@@ -435,6 +435,22 @@ ret_from_fork:
 	li	r3,0
 	b	ret_from_syscall
 
+	.globl	ret_from_kernel_thread
+ret_from_kernel_thread:
+	REST_NVGPRS(r1)
+	bl	schedule_tail
+	mtlr	r14
+	mr	r3,r15
+	PPC440EP_ERR42
+	blrl
+	li	r3,0
+	b	do_exit		# no return
+
+	.globl	__ret_from_kernel_execve
+__ret_from_kernel_execve:
+	addi	r1,r3,-STACK_FRAME_OVERHEAD
+	b	ret_from_syscall
+
 /* Traced system call support */
 syscall_dotrace:
 	SAVE_NVGPRS(r1)
@@ -831,19 +847,56 @@ restore_user:
 	bnel-	load_dbcr0
 #endif
 
-#ifdef CONFIG_PREEMPT
 	b	restore
 
 /* N.B. the only way to get here is from the beq following ret_from_except. */
 resume_kernel:
-	/* check current_thread_info->preempt_count */
+	/* check current_thread_info, _TIF_EMULATE_STACK_STORE */
 	CURRENT_THREAD_INFO(r9, r1)
+	lwz	r8,TI_FLAGS(r9)
+	andis.	r8,r8,_TIF_EMULATE_STACK_STORE@h
+	beq+	1f
+
+	addi	r8,r1,INT_FRAME_SIZE	/* Get the kprobed function entry */
+
+	lwz	r3,GPR1(r1)
+	subi	r3,r3,INT_FRAME_SIZE	/* dst: Allocate a trampoline exception frame */
+	mr	r4,r1			/* src:  current exception frame */
+	mr	r1,r3			/* Reroute the trampoline frame to r1 */
+
+	/* Copy from the original to the trampoline. */
+	li	r5,INT_FRAME_SIZE/4	/* size: INT_FRAME_SIZE */
+	li	r6,0			/* start offset: 0 */
+	mtctr	r5
+2:	lwzx	r0,r6,r4
+	stwx	r0,r6,r3
+	addi	r6,r6,4
+	bdnz	2b
+
+	/* Do real store operation to complete stwu */
+	lwz	r5,GPR1(r1)
+	stw	r8,0(r5)
+
+	/* Clear _TIF_EMULATE_STACK_STORE flag */
+	lis	r11,_TIF_EMULATE_STACK_STORE@h
+	addi	r5,r9,TI_FLAGS
+0:	lwarx	r8,0,r5
+	andc	r8,r8,r11
+#ifdef CONFIG_IBM405_ERR77
+	dcbt	0,r5
+#endif
+	stwcx.	r8,0,r5
+	bne-	0b
+1:
+
+#ifdef CONFIG_PREEMPT
+	/* check current_thread_info->preempt_count */
 	lwz	r0,TI_PREEMPT(r9)
 	cmpwi	0,r0,0		/* if non-zero, just restore regs and return */
 	bne	restore
-	lwz	r0,TI_FLAGS(r9)
-	andi.	r0,r0,_TIF_NEED_RESCHED
+	andi.	r8,r8,_TIF_NEED_RESCHED
 	beq+	restore
+	lwz	r3,_MSR(r1)
 	andi.	r0,r3,MSR_EE	/* interrupts off? */
 	beq	restore		/* don't schedule if so */
 #ifdef CONFIG_TRACE_IRQFLAGS
@@ -864,8 +917,6 @@ resume_kernel:
 	 */
 	bl	trace_hardirqs_on
 #endif
-#else
-resume_kernel:
 #endif /* CONFIG_PREEMPT */
 
 	/* interrupts are hard-disabled at this point */
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
index b40e0b4..56e0ff0 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
@@ -370,6 +370,22 @@ _GLOBAL(ret_from_fork)
 	li	r3,0
 	b	syscall_exit
 
+_GLOBAL(ret_from_kernel_thread)
+	bl	.schedule_tail
+	REST_NVGPRS(r1)
+	REST_GPR(2,r1)
+	mtlr	r14
+	mr	r3,r15
+	blrl
+	li	r3,0
+	b	.do_exit	# no return
+
+_GLOBAL(__ret_from_kernel_execve)
+	addi	r1,r3,-STACK_FRAME_OVERHEAD
+	li	r10,1
+	std	r10,SOFTE(r1)
+	b	syscall_exit
+
 	.section	".toc","aw"
 DSCR_DEFAULT:
 	.tc dscr_default[TC],dscr_default
@@ -593,6 +609,41 @@ _GLOBAL(ret_from_except_lite)
 	b	.ret_from_except
 
 resume_kernel:
+	/* check current_thread_info, _TIF_EMULATE_STACK_STORE */
+	CURRENT_THREAD_INFO(r9, r1)
+	ld	r8,TI_FLAGS(r9)
+	andis.	r8,r8,_TIF_EMULATE_STACK_STORE@h
+	beq+	1f
+
+	addi	r8,r1,INT_FRAME_SIZE	/* Get the kprobed function entry */
+
+	lwz	r3,GPR1(r1)
+	subi	r3,r3,INT_FRAME_SIZE	/* dst: Allocate a trampoline exception frame */
+	mr	r4,r1			/* src:  current exception frame */
+	mr	r1,r3			/* Reroute the trampoline frame to r1 */
+
+	/* Copy from the original to the trampoline. */
+	li	r5,INT_FRAME_SIZE/8	/* size: INT_FRAME_SIZE */
+	li	r6,0			/* start offset: 0 */
+	mtctr	r5
+2:	ldx	r0,r6,r4
+	stdx	r0,r6,r3
+	addi	r6,r6,8
+	bdnz	2b
+
+	/* Do real store operation to complete stwu */
+	lwz	r5,GPR1(r1)
+	std	r8,0(r5)
+
+	/* Clear _TIF_EMULATE_STACK_STORE flag */
+	lis	r11,_TIF_EMULATE_STACK_STORE@h
+	addi	r5,r9,TI_FLAGS
+	ldarx	r4,0,r5
+	andc	r4,r4,r11
+	stdcx.	r4,0,r5
+	bne-	0b
+1:
+
 #ifdef CONFIG_PREEMPT
 	/* Check if we need to preempt */
 	andi.	r0,r4,_TIF_NEED_RESCHED
diff --git a/arch/powerpc/kernel/epapr_hcalls.S b/arch/powerpc/kernel/epapr_hcalls.S
index 697b390..62c0dc2 100644
--- a/arch/powerpc/kernel/epapr_hcalls.S
+++ b/arch/powerpc/kernel/epapr_hcalls.S
@@ -8,13 +8,41 @@
  */
 
 #include <linux/threads.h>
+#include <asm/epapr_hcalls.h>
 #include <asm/reg.h>
 #include <asm/page.h>
 #include <asm/cputable.h>
 #include <asm/thread_info.h>
 #include <asm/ppc_asm.h>
+#include <asm/asm-compat.h>
 #include <asm/asm-offsets.h>
 
+/* epapr_ev_idle() was derived from e500_idle() */
+_GLOBAL(epapr_ev_idle)
+	CURRENT_THREAD_INFO(r3, r1)
+	PPC_LL	r4, TI_LOCAL_FLAGS(r3)	/* set napping bit */
+	ori	r4, r4,_TLF_NAPPING	/* so when we take an exception */
+	PPC_STL	r4, TI_LOCAL_FLAGS(r3)	/* it will return to our caller */
+
+	wrteei	1
+
+idle_loop:
+	LOAD_REG_IMMEDIATE(r11, EV_HCALL_TOKEN(EV_IDLE))
+
+.global epapr_ev_idle_start
+epapr_ev_idle_start:
+	li	r3, -1
+	nop
+	nop
+	nop
+
+	/*
+	 * Guard against spurious wakeups from a hypervisor --
+	 * only interrupt will cause us to return to LR due to
+	 * _TLF_NAPPING.
+	 */
+	b	idle_loop
+
 /* Hypercall entry point. Will be patched with device tree instructions. */
 .global epapr_hypercall_start
 epapr_hypercall_start:
diff --git a/arch/powerpc/kernel/epapr_paravirt.c b/arch/powerpc/kernel/epapr_paravirt.c
index 028aeae..f3eab85 100644
--- a/arch/powerpc/kernel/epapr_paravirt.c
+++ b/arch/powerpc/kernel/epapr_paravirt.c
@@ -21,6 +21,10 @@
 #include <asm/epapr_hcalls.h>
 #include <asm/cacheflush.h>
 #include <asm/code-patching.h>
+#include <asm/machdep.h>
+
+extern void epapr_ev_idle(void);
+extern u32 epapr_ev_idle_start[];
 
 bool epapr_paravirt_enabled;
 
@@ -41,8 +45,13 @@ static int __init epapr_paravirt_init(void)
 	if (len % 4 || len > (4 * 4))
 		return -ENODEV;
 
-	for (i = 0; i < (len / 4); i++)
+	for (i = 0; i < (len / 4); i++) {
 		patch_instruction(epapr_hypercall_start + i, insts[i]);
+		patch_instruction(epapr_ev_idle_start + i, insts[i]);
+	}
+
+	if (of_get_property(hyper_node, "has-idle", NULL))
+		ppc_md.power_save = epapr_ev_idle;
 
 	epapr_paravirt_enabled = true;
 
diff --git a/arch/powerpc/kernel/exceptions-64e.S b/arch/powerpc/kernel/exceptions-64e.S
index 98be7f0..4684e33 100644
--- a/arch/powerpc/kernel/exceptions-64e.S
+++ b/arch/powerpc/kernel/exceptions-64e.S
@@ -25,6 +25,8 @@
 #include <asm/ppc-opcode.h>
 #include <asm/mmu.h>
 #include <asm/hw_irq.h>
+#include <asm/kvm_asm.h>
+#include <asm/kvm_booke_hv_asm.h>
 
 /* XXX This will ultimately add space for a special exception save
  *     structure used to save things like SRR0/SRR1, SPRGs, MAS, etc...
@@ -35,16 +37,18 @@
 #define	SPECIAL_EXC_FRAME_SIZE	INT_FRAME_SIZE
 
 /* Exception prolog code for all exceptions */
-#define EXCEPTION_PROLOG(n, type, addition)				    \
+#define EXCEPTION_PROLOG(n, intnum, type, addition)	    		    \
 	mtspr	SPRN_SPRG_##type##_SCRATCH,r13;	/* get spare registers */   \
 	mfspr	r13,SPRN_SPRG_PACA;	/* get PACA */			    \
 	std	r10,PACA_EX##type+EX_R10(r13);				    \
 	std	r11,PACA_EX##type+EX_R11(r13);				    \
+	PROLOG_STORE_RESTORE_SCRATCH_##type;				    \
 	mfcr	r10;			/* save CR */			    \
+	mfspr	r11,SPRN_##type##_SRR1;/* what are we coming from */	    \
+	DO_KVM	intnum,SPRN_##type##_SRR1;    /* KVM hook */		    \
+	stw	r10,PACA_EX##type+EX_CR(r13); /* save old CR in the PACA */ \
 	addition;			/* additional code for that exc. */ \
 	std	r1,PACA_EX##type+EX_R1(r13); /* save old r1 in the PACA */  \
-	stw	r10,PACA_EX##type+EX_CR(r13); /* save old CR in the PACA */ \
-	mfspr	r11,SPRN_##type##_SRR1;/* what are we coming from */	    \
 	type##_SET_KSTACK;		/* get special stack if necessary */\
 	andi.	r10,r11,MSR_PR;		/* save stack pointer */	    \
 	beq	1f;			/* branch around if supervisor */   \
@@ -59,6 +63,10 @@
 #define SPRN_GEN_SRR0	SPRN_SRR0
 #define SPRN_GEN_SRR1	SPRN_SRR1
 
+#define	GDBELL_SET_KSTACK	GEN_SET_KSTACK
+#define SPRN_GDBELL_SRR0	SPRN_GSRR0
+#define SPRN_GDBELL_SRR1	SPRN_GSRR1
+
 #define CRIT_SET_KSTACK						            \
 	ld	r1,PACA_CRIT_STACK(r13);				    \
 	subi	r1,r1,SPECIAL_EXC_FRAME_SIZE;
@@ -77,29 +85,46 @@
 #define SPRN_MC_SRR0	SPRN_MCSRR0
 #define SPRN_MC_SRR1	SPRN_MCSRR1
 
-#define NORMAL_EXCEPTION_PROLOG(n, addition)				    \
-	EXCEPTION_PROLOG(n, GEN, addition##_GEN(n))
+#define NORMAL_EXCEPTION_PROLOG(n, intnum, addition)			    \
+	EXCEPTION_PROLOG(n, intnum, GEN, addition##_GEN(n))
+
+#define CRIT_EXCEPTION_PROLOG(n, intnum, addition)			    \
+	EXCEPTION_PROLOG(n, intnum, CRIT, addition##_CRIT(n))
 
-#define CRIT_EXCEPTION_PROLOG(n, addition)				    \
-	EXCEPTION_PROLOG(n, CRIT, addition##_CRIT(n))
+#define DBG_EXCEPTION_PROLOG(n, intnum, addition)			    \
+	EXCEPTION_PROLOG(n, intnum, DBG, addition##_DBG(n))
 
-#define DBG_EXCEPTION_PROLOG(n, addition)				    \
-	EXCEPTION_PROLOG(n, DBG, addition##_DBG(n))
+#define MC_EXCEPTION_PROLOG(n, intnum, addition)			    \
+	EXCEPTION_PROLOG(n, intnum, MC, addition##_MC(n))
 
-#define MC_EXCEPTION_PROLOG(n, addition)				    \
-	EXCEPTION_PROLOG(n, MC, addition##_MC(n))
+#define GDBELL_EXCEPTION_PROLOG(n, intnum, addition)			    \
+	EXCEPTION_PROLOG(n, intnum, GDBELL, addition##_GDBELL(n))
 
+/*
+ * Store user-visible scratch in PACA exception slots and restore proper value
+ */
+#define PROLOG_STORE_RESTORE_SCRATCH_GEN
+#define PROLOG_STORE_RESTORE_SCRATCH_GDBELL
+#define PROLOG_STORE_RESTORE_SCRATCH_DBG
+#define PROLOG_STORE_RESTORE_SCRATCH_MC
+
+#define PROLOG_STORE_RESTORE_SCRATCH_CRIT				    \
+	mfspr	r10,SPRN_SPRG_CRIT_SCRATCH;	/* get r13 */		    \
+	std	r10,PACA_EXCRIT+EX_R13(r13);				    \
+	ld	r11,PACA_SPRG3(r13);					    \
+	mtspr	SPRN_SPRG_CRIT_SCRATCH,r11;
 
 /* Variants of the "addition" argument for the prolog
  */
 #define PROLOG_ADDITION_NONE_GEN(n)
+#define PROLOG_ADDITION_NONE_GDBELL(n)
 #define PROLOG_ADDITION_NONE_CRIT(n)
 #define PROLOG_ADDITION_NONE_DBG(n)
 #define PROLOG_ADDITION_NONE_MC(n)
 
 #define PROLOG_ADDITION_MASKABLE_GEN(n)					    \
-	lbz	r11,PACASOFTIRQEN(r13); /* are irqs soft-disabled ? */	    \
-	cmpwi	cr0,r11,0;		/* yes -> go out of line */	    \
+	lbz	r10,PACASOFTIRQEN(r13); /* are irqs soft-disabled ? */	    \
+	cmpwi	cr0,r10,0;		/* yes -> go out of line */	    \
 	beq	masked_interrupt_book3e_##n
 
 #define PROLOG_ADDITION_2REGS_GEN(n)					    \
@@ -233,9 +258,9 @@ exc_##n##_bad_stack:							    \
 1:
 
 
-#define MASKABLE_EXCEPTION(trapnum, label, hdlr, ack)			\
+#define MASKABLE_EXCEPTION(trapnum, intnum, label, hdlr, ack)		\
 	START_EXCEPTION(label);						\
-	NORMAL_EXCEPTION_PROLOG(trapnum, PROLOG_ADDITION_MASKABLE)	\
+	NORMAL_EXCEPTION_PROLOG(trapnum, intnum, PROLOG_ADDITION_MASKABLE)\
 	EXCEPTION_COMMON(trapnum, PACA_EXGEN, INTS_DISABLE)		\
 	ack(r8);							\
 	CHECK_NAPPING();						\
@@ -286,7 +311,8 @@ interrupt_end_book3e:
 
 /* Critical Input Interrupt */
 	START_EXCEPTION(critical_input);
-	CRIT_EXCEPTION_PROLOG(0x100, PROLOG_ADDITION_NONE)
+	CRIT_EXCEPTION_PROLOG(0x100, BOOKE_INTERRUPT_CRITICAL,
+			      PROLOG_ADDITION_NONE)
 //	EXCEPTION_COMMON(0x100, PACA_EXCRIT, INTS_DISABLE)
 //	bl	special_reg_save_crit
 //	CHECK_NAPPING();
@@ -297,7 +323,8 @@ interrupt_end_book3e:
 
 /* Machine Check Interrupt */
 	START_EXCEPTION(machine_check);
-	CRIT_EXCEPTION_PROLOG(0x200, PROLOG_ADDITION_NONE)
+	MC_EXCEPTION_PROLOG(0x200, BOOKE_INTERRUPT_MACHINE_CHECK,
+			    PROLOG_ADDITION_NONE)
 //	EXCEPTION_COMMON(0x200, PACA_EXMC, INTS_DISABLE)
 //	bl	special_reg_save_mc
 //	addi	r3,r1,STACK_FRAME_OVERHEAD
@@ -308,7 +335,8 @@ interrupt_end_book3e:
 
 /* Data Storage Interrupt */
 	START_EXCEPTION(data_storage)
-	NORMAL_EXCEPTION_PROLOG(0x300, PROLOG_ADDITION_2REGS)
+	NORMAL_EXCEPTION_PROLOG(0x300, BOOKE_INTERRUPT_DATA_STORAGE,
+				PROLOG_ADDITION_2REGS)
 	mfspr	r14,SPRN_DEAR
 	mfspr	r15,SPRN_ESR
 	EXCEPTION_COMMON(0x300, PACA_EXGEN, INTS_DISABLE)
@@ -316,18 +344,21 @@ interrupt_end_book3e:
 
 /* Instruction Storage Interrupt */
 	START_EXCEPTION(instruction_storage);
-	NORMAL_EXCEPTION_PROLOG(0x400, PROLOG_ADDITION_2REGS)
+	NORMAL_EXCEPTION_PROLOG(0x400, BOOKE_INTERRUPT_INST_STORAGE,
+				PROLOG_ADDITION_2REGS)
 	li	r15,0
 	mr	r14,r10
 	EXCEPTION_COMMON(0x400, PACA_EXGEN, INTS_DISABLE)
 	b	storage_fault_common
 
 /* External Input Interrupt */
-	MASKABLE_EXCEPTION(0x500, external_input, .do_IRQ, ACK_NONE)
+	MASKABLE_EXCEPTION(0x500, BOOKE_INTERRUPT_EXTERNAL,
+			   external_input, .do_IRQ, ACK_NONE)
 
 /* Alignment */
 	START_EXCEPTION(alignment);
-	NORMAL_EXCEPTION_PROLOG(0x600, PROLOG_ADDITION_2REGS)
+	NORMAL_EXCEPTION_PROLOG(0x600, BOOKE_INTERRUPT_ALIGNMENT,
+				PROLOG_ADDITION_2REGS)
 	mfspr	r14,SPRN_DEAR
 	mfspr	r15,SPRN_ESR
 	EXCEPTION_COMMON(0x600, PACA_EXGEN, INTS_KEEP)
@@ -335,7 +366,8 @@ interrupt_end_book3e:
 
 /* Program Interrupt */
 	START_EXCEPTION(program);
-	NORMAL_EXCEPTION_PROLOG(0x700, PROLOG_ADDITION_1REG)
+	NORMAL_EXCEPTION_PROLOG(0x700, BOOKE_INTERRUPT_PROGRAM,
+				PROLOG_ADDITION_1REG)
 	mfspr	r14,SPRN_ESR
 	EXCEPTION_COMMON(0x700, PACA_EXGEN, INTS_DISABLE)
 	std	r14,_DSISR(r1)
@@ -347,7 +379,8 @@ interrupt_end_book3e:
 
 /* Floating Point Unavailable Interrupt */
 	START_EXCEPTION(fp_unavailable);
-	NORMAL_EXCEPTION_PROLOG(0x800, PROLOG_ADDITION_NONE)
+	NORMAL_EXCEPTION_PROLOG(0x800, BOOKE_INTERRUPT_FP_UNAVAIL,
+				PROLOG_ADDITION_NONE)
 	/* we can probably do a shorter exception entry for that one... */
 	EXCEPTION_COMMON(0x800, PACA_EXGEN, INTS_KEEP)
 	ld	r12,_MSR(r1)
@@ -362,14 +395,17 @@ interrupt_end_book3e:
 	b	.ret_from_except
 
 /* Decrementer Interrupt */
-	MASKABLE_EXCEPTION(0x900, decrementer, .timer_interrupt, ACK_DEC)
+	MASKABLE_EXCEPTION(0x900, BOOKE_INTERRUPT_DECREMENTER,
+			   decrementer, .timer_interrupt, ACK_DEC)
 
 /* Fixed Interval Timer Interrupt */
-	MASKABLE_EXCEPTION(0x980, fixed_interval, .unknown_exception, ACK_FIT)
+	MASKABLE_EXCEPTION(0x980, BOOKE_INTERRUPT_FIT,
+			   fixed_interval, .unknown_exception, ACK_FIT)
 
 /* Watchdog Timer Interrupt */
 	START_EXCEPTION(watchdog);
-	CRIT_EXCEPTION_PROLOG(0x9f0, PROLOG_ADDITION_NONE)
+	CRIT_EXCEPTION_PROLOG(0x9f0, BOOKE_INTERRUPT_WATCHDOG,
+			      PROLOG_ADDITION_NONE)
 //	EXCEPTION_COMMON(0x9f0, PACA_EXCRIT, INTS_DISABLE)
 //	bl	special_reg_save_crit
 //	CHECK_NAPPING();
@@ -388,7 +424,8 @@ interrupt_end_book3e:
 
 /* Auxiliary Processor Unavailable Interrupt */
 	START_EXCEPTION(ap_unavailable);
-	NORMAL_EXCEPTION_PROLOG(0xf20, PROLOG_ADDITION_NONE)
+	NORMAL_EXCEPTION_PROLOG(0xf20, BOOKE_INTERRUPT_AP_UNAVAIL,
+				PROLOG_ADDITION_NONE)
 	EXCEPTION_COMMON(0xf20, PACA_EXGEN, INTS_DISABLE)
 	bl	.save_nvgprs
 	addi	r3,r1,STACK_FRAME_OVERHEAD
@@ -397,7 +434,8 @@ interrupt_end_book3e:
 
 /* Debug exception as a critical interrupt*/
 	START_EXCEPTION(debug_crit);
-	CRIT_EXCEPTION_PROLOG(0xd00, PROLOG_ADDITION_2REGS)
+	CRIT_EXCEPTION_PROLOG(0xd00, BOOKE_INTERRUPT_DEBUG,
+			      PROLOG_ADDITION_2REGS)
 
 	/*
 	 * If there is a single step or branch-taken exception in an
@@ -431,7 +469,7 @@ interrupt_end_book3e:
 	mtcr	r10
 	ld	r10,PACA_EXCRIT+EX_R10(r13)	/* restore registers */
 	ld	r11,PACA_EXCRIT+EX_R11(r13)
-	mfspr	r13,SPRN_SPRG_CRIT_SCRATCH
+	ld	r13,PACA_EXCRIT+EX_R13(r13)
 	rfci
 
 	/* Normal debug exception */
@@ -444,7 +482,7 @@ interrupt_end_book3e:
 	/* Now we mash up things to make it look like we are coming on a
 	 * normal exception
 	 */
-	mfspr	r15,SPRN_SPRG_CRIT_SCRATCH
+	ld	r15,PACA_EXCRIT+EX_R13(r13)
 	mtspr	SPRN_SPRG_GEN_SCRATCH,r15
 	mfspr	r14,SPRN_DBSR
 	EXCEPTION_COMMON(0xd00, PACA_EXCRIT, INTS_DISABLE)
@@ -462,7 +500,8 @@ kernel_dbg_exc:
 
 /* Debug exception as a debug interrupt*/
 	START_EXCEPTION(debug_debug);
-	DBG_EXCEPTION_PROLOG(0xd08, PROLOG_ADDITION_2REGS)
+	DBG_EXCEPTION_PROLOG(0xd00, BOOKE_INTERRUPT_DEBUG,
+						 PROLOG_ADDITION_2REGS)
 
 	/*
 	 * If there is a single step or branch-taken exception in an
@@ -523,18 +562,21 @@ kernel_dbg_exc:
 	b	.ret_from_except
 
 	START_EXCEPTION(perfmon);
-	NORMAL_EXCEPTION_PROLOG(0x260, PROLOG_ADDITION_NONE)
+	NORMAL_EXCEPTION_PROLOG(0x260, BOOKE_INTERRUPT_PERFORMANCE_MONITOR,
+				PROLOG_ADDITION_NONE)
 	EXCEPTION_COMMON(0x260, PACA_EXGEN, INTS_DISABLE)
 	addi	r3,r1,STACK_FRAME_OVERHEAD
 	bl	.performance_monitor_exception
 	b	.ret_from_except_lite
 
 /* Doorbell interrupt */
-	MASKABLE_EXCEPTION(0x280, doorbell, .doorbell_exception, ACK_NONE)
+	MASKABLE_EXCEPTION(0x280, BOOKE_INTERRUPT_DOORBELL,
+			   doorbell, .doorbell_exception, ACK_NONE)
 
 /* Doorbell critical Interrupt */
 	START_EXCEPTION(doorbell_crit);
-	CRIT_EXCEPTION_PROLOG(0x2a0, PROLOG_ADDITION_NONE)
+	CRIT_EXCEPTION_PROLOG(0x2a0, BOOKE_INTERRUPT_DOORBELL_CRITICAL,
+			      PROLOG_ADDITION_NONE)
 //	EXCEPTION_COMMON(0x2a0, PACA_EXCRIT, INTS_DISABLE)
 //	bl	special_reg_save_crit
 //	CHECK_NAPPING();
@@ -543,12 +585,24 @@ kernel_dbg_exc:
 //	b	ret_from_crit_except
 	b	.
 
-/* Guest Doorbell */
-	MASKABLE_EXCEPTION(0x2c0, guest_doorbell, .unknown_exception, ACK_NONE)
+/*
+ *	Guest doorbell interrupt
+ *	This general exception use GSRRx save/restore registers
+ */
+	START_EXCEPTION(guest_doorbell);
+	GDBELL_EXCEPTION_PROLOG(0x2c0, BOOKE_INTERRUPT_GUEST_DBELL,
+			        PROLOG_ADDITION_NONE)
+	EXCEPTION_COMMON(0x2c0, PACA_EXGEN, INTS_KEEP)
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	bl	.save_nvgprs
+	INTS_RESTORE_HARD
+	bl	.unknown_exception
+	b	.ret_from_except
 
 /* Guest Doorbell critical Interrupt */
 	START_EXCEPTION(guest_doorbell_crit);
-	CRIT_EXCEPTION_PROLOG(0x2e0, PROLOG_ADDITION_NONE)
+	CRIT_EXCEPTION_PROLOG(0x2e0, BOOKE_INTERRUPT_GUEST_DBELL_CRIT,
+			      PROLOG_ADDITION_NONE)
 //	EXCEPTION_COMMON(0x2e0, PACA_EXCRIT, INTS_DISABLE)
 //	bl	special_reg_save_crit
 //	CHECK_NAPPING();
@@ -559,7 +613,8 @@ kernel_dbg_exc:
 
 /* Hypervisor call */
 	START_EXCEPTION(hypercall);
-	NORMAL_EXCEPTION_PROLOG(0x310, PROLOG_ADDITION_NONE)
+	NORMAL_EXCEPTION_PROLOG(0x310, BOOKE_INTERRUPT_HV_SYSCALL,
+			        PROLOG_ADDITION_NONE)
 	EXCEPTION_COMMON(0x310, PACA_EXGEN, INTS_KEEP)
 	addi	r3,r1,STACK_FRAME_OVERHEAD
 	bl	.save_nvgprs
@@ -569,7 +624,8 @@ kernel_dbg_exc:
 
 /* Embedded Hypervisor priviledged  */
 	START_EXCEPTION(ehpriv);
-	NORMAL_EXCEPTION_PROLOG(0x320, PROLOG_ADDITION_NONE)
+	NORMAL_EXCEPTION_PROLOG(0x320, BOOKE_INTERRUPT_HV_PRIV,
+			        PROLOG_ADDITION_NONE)
 	EXCEPTION_COMMON(0x320, PACA_EXGEN, INTS_KEEP)
 	addi	r3,r1,STACK_FRAME_OVERHEAD
 	bl	.save_nvgprs
@@ -582,44 +638,42 @@ kernel_dbg_exc:
  * accordingly and if the interrupt is level sensitive, we hard disable
  */
 
+.macro masked_interrupt_book3e paca_irq full_mask
+	lbz	r10,PACAIRQHAPPENED(r13)
+	ori	r10,r10,\paca_irq
+	stb	r10,PACAIRQHAPPENED(r13)
+
+	.if \full_mask == 1
+	rldicl	r10,r11,48,1		/* clear MSR_EE */
+	rotldi	r11,r10,16
+	mtspr	SPRN_SRR1,r11
+	.endif
+
+	lwz	r11,PACA_EXGEN+EX_CR(r13)
+	mtcr	r11
+	ld	r10,PACA_EXGEN+EX_R10(r13)
+	ld	r11,PACA_EXGEN+EX_R11(r13)
+	mfspr	r13,SPRN_SPRG_GEN_SCRATCH
+	rfi
+	b	.
+.endm
+
 masked_interrupt_book3e_0x500:
-	/* XXX When adding support for EPR, use PACA_IRQ_EE_EDGE */
-	li	r11,PACA_IRQ_EE
-	b	masked_interrupt_book3e_full_mask
+	// XXX When adding support for EPR, use PACA_IRQ_EE_EDGE
+	masked_interrupt_book3e PACA_IRQ_EE 1
 
 masked_interrupt_book3e_0x900:
-	ACK_DEC(r11);
-	li	r11,PACA_IRQ_DEC
-	b	masked_interrupt_book3e_no_mask
+	ACK_DEC(r10);
+	masked_interrupt_book3e PACA_IRQ_DEC 0
+
 masked_interrupt_book3e_0x980:
-	ACK_FIT(r11);
-	li	r11,PACA_IRQ_DEC
-	b	masked_interrupt_book3e_no_mask
+	ACK_FIT(r10);
+	masked_interrupt_book3e PACA_IRQ_DEC 0
+
 masked_interrupt_book3e_0x280:
 masked_interrupt_book3e_0x2c0:
-	li	r11,PACA_IRQ_DBELL
-	b	masked_interrupt_book3e_no_mask
+	masked_interrupt_book3e PACA_IRQ_DBELL 0
 
-masked_interrupt_book3e_no_mask:
-	mtcr	r10
-	lbz	r10,PACAIRQHAPPENED(r13)
-	or	r10,r10,r11
-	stb	r10,PACAIRQHAPPENED(r13)
-	b	1f
-masked_interrupt_book3e_full_mask:
-	mtcr	r10
-	lbz	r10,PACAIRQHAPPENED(r13)
-	or	r10,r10,r11
-	stb	r10,PACAIRQHAPPENED(r13)
-	mfspr	r10,SPRN_SRR1
-	rldicl	r11,r10,48,1		/* clear MSR_EE */
-	rotldi	r10,r11,16
-	mtspr	SPRN_SRR1,r10
-1:	ld	r10,PACA_EXGEN+EX_R10(r13);
-	ld	r11,PACA_EXGEN+EX_R11(r13);
-	mfspr	r13,SPRN_SPRG_GEN_SCRATCH;
-	rfi
-	b	.
 /*
  * Called from arch_local_irq_enable when an interrupt needs
  * to be resent. r3 contains either 0x500,0x900,0x260 or 0x280
@@ -1302,25 +1356,11 @@ _GLOBAL(setup_perfmon_ivor)
 _GLOBAL(setup_doorbell_ivors)
 	SET_IVOR(36, 0x280) /* Processor Doorbell */
 	SET_IVOR(37, 0x2a0) /* Processor Doorbell Crit */
-
-	/* Check MMUCFG[LPIDSIZE] to determine if we have category E.HV */
-	mfspr	r10,SPRN_MMUCFG
-	rlwinm.	r10,r10,0,MMUCFG_LPIDSIZE
-	beqlr
-
-	SET_IVOR(38, 0x2c0) /* Guest Processor Doorbell */
-	SET_IVOR(39, 0x2e0) /* Guest Processor Doorbell Crit/MC */
 	blr
 
 _GLOBAL(setup_ehv_ivors)
-	/*
-	 * We may be running as a guest and lack E.HV even on a chip
-	 * that normally has it.
-	 */
-	mfspr	r10,SPRN_MMUCFG
-	rlwinm.	r10,r10,0,MMUCFG_LPIDSIZE
-	beqlr
-
 	SET_IVOR(40, 0x300) /* Embedded Hypervisor System Call */
 	SET_IVOR(41, 0x320) /* Embedded Hypervisor Privilege */
+	SET_IVOR(38, 0x2c0) /* Guest Processor Doorbell */
+	SET_IVOR(39, 0x2e0) /* Guest Processor Doorbell Crit/MC */
 	blr
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index 39aa97d..10b658a 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -275,6 +275,31 @@ vsx_unavailable_pSeries_1:
 	STD_EXCEPTION_PSERIES(0x1300, 0x1300, instruction_breakpoint)
 	KVM_HANDLER_PR_SKIP(PACA_EXGEN, EXC_STD, 0x1300)
 
+	. = 0x1500
+	.global denorm_Hypervisor
+denorm_exception_hv:
+	HMT_MEDIUM
+	mtspr	SPRN_SPRG_HSCRATCH0,r13
+	mfspr	r13,SPRN_SPRG_HPACA
+	std	r9,PACA_EXGEN+EX_R9(r13)
+	std	r10,PACA_EXGEN+EX_R10(r13)
+	std	r11,PACA_EXGEN+EX_R11(r13)
+	std	r12,PACA_EXGEN+EX_R12(r13)
+	mfspr	r9,SPRN_SPRG_HSCRATCH0
+	std	r9,PACA_EXGEN+EX_R13(r13)
+	mfcr	r9
+
+#ifdef CONFIG_PPC_DENORMALISATION
+	mfspr	r10,SPRN_HSRR1
+	mfspr	r11,SPRN_HSRR0		/* save HSRR0 */
+	andis.	r10,r10,(HSRR1_DENORM)@h /* denorm? */
+	addi	r11,r11,-4		/* HSRR0 is next instruction */
+	bne+	denorm_assist
+#endif
+
+	EXCEPTION_PROLOG_PSERIES_1(denorm_common, EXC_HV)
+	KVM_HANDLER_SKIP(PACA_EXGEN, EXC_STD, 0x1500)
+
 #ifdef CONFIG_CBE_RAS
 	STD_EXCEPTION_HV(0x1600, 0x1602, cbe_maintenance)
 	KVM_HANDLER_SKIP(PACA_EXGEN, EXC_HV, 0x1602)
@@ -336,6 +361,103 @@ do_stab_bolted_pSeries:
 	KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0x900)
 	KVM_HANDLER(PACA_EXGEN, EXC_HV, 0x982)
 
+#ifdef CONFIG_PPC_DENORMALISATION
+denorm_assist:
+BEGIN_FTR_SECTION
+/*
+ * To denormalise we need to move a copy of the register to itself.
+ * For POWER6 do that here for all FP regs.
+ */
+	mfmsr	r10
+	ori	r10,r10,(MSR_FP|MSR_FE0|MSR_FE1)
+	xori	r10,r10,(MSR_FE0|MSR_FE1)
+	mtmsrd	r10
+	sync
+	fmr	0,0
+	fmr	1,1
+	fmr	2,2
+	fmr	3,3
+	fmr	4,4
+	fmr	5,5
+	fmr	6,6
+	fmr	7,7
+	fmr	8,8
+	fmr	9,9
+	fmr	10,10
+	fmr	11,11
+	fmr	12,12
+	fmr	13,13
+	fmr	14,14
+	fmr	15,15
+	fmr	16,16
+	fmr	17,17
+	fmr	18,18
+	fmr	19,19
+	fmr	20,20
+	fmr	21,21
+	fmr	22,22
+	fmr	23,23
+	fmr	24,24
+	fmr	25,25
+	fmr	26,26
+	fmr	27,27
+	fmr	28,28
+	fmr	29,29
+	fmr	30,30
+	fmr	31,31
+FTR_SECTION_ELSE
+/*
+ * To denormalise we need to move a copy of the register to itself.
+ * For POWER7 do that here for the first 32 VSX registers only.
+ */
+	mfmsr	r10
+	oris	r10,r10,MSR_VSX@h
+	mtmsrd	r10
+	sync
+	XVCPSGNDP(0,0,0)
+	XVCPSGNDP(1,1,1)
+	XVCPSGNDP(2,2,2)
+	XVCPSGNDP(3,3,3)
+	XVCPSGNDP(4,4,4)
+	XVCPSGNDP(5,5,5)
+	XVCPSGNDP(6,6,6)
+	XVCPSGNDP(7,7,7)
+	XVCPSGNDP(8,8,8)
+	XVCPSGNDP(9,9,9)
+	XVCPSGNDP(10,10,10)
+	XVCPSGNDP(11,11,11)
+	XVCPSGNDP(12,12,12)
+	XVCPSGNDP(13,13,13)
+	XVCPSGNDP(14,14,14)
+	XVCPSGNDP(15,15,15)
+	XVCPSGNDP(16,16,16)
+	XVCPSGNDP(17,17,17)
+	XVCPSGNDP(18,18,18)
+	XVCPSGNDP(19,19,19)
+	XVCPSGNDP(20,20,20)
+	XVCPSGNDP(21,21,21)
+	XVCPSGNDP(22,22,22)
+	XVCPSGNDP(23,23,23)
+	XVCPSGNDP(24,24,24)
+	XVCPSGNDP(25,25,25)
+	XVCPSGNDP(26,26,26)
+	XVCPSGNDP(27,27,27)
+	XVCPSGNDP(28,28,28)
+	XVCPSGNDP(29,29,29)
+	XVCPSGNDP(30,30,30)
+	XVCPSGNDP(31,31,31)
+ALT_FTR_SECTION_END_IFCLR(CPU_FTR_ARCH_206)
+	mtspr	SPRN_HSRR0,r11
+	mtcrf	0x80,r9
+	ld	r9,PACA_EXGEN+EX_R9(r13)
+	ld	r10,PACA_EXGEN+EX_R10(r13)
+	ld	r11,PACA_EXGEN+EX_R11(r13)
+	ld	r12,PACA_EXGEN+EX_R12(r13)
+	ld	r13,PACA_EXGEN+EX_R13(r13)
+	HRFID
+	b	.
+#endif
+
 	.align	7
 	/* moved from 0xe00 */
 	STD_EXCEPTION_HV(., 0xe02, h_data_storage)
@@ -495,6 +617,7 @@ machine_check_common:
         STD_EXCEPTION_COMMON(0xe60, hmi_exception, .unknown_exception)
 	STD_EXCEPTION_COMMON_ASYNC(0xf00, performance_monitor, .performance_monitor_exception)
 	STD_EXCEPTION_COMMON(0x1300, instruction_breakpoint, .instruction_breakpoint_exception)
+	STD_EXCEPTION_COMMON(0x1502, denorm, .unknown_exception)
 #ifdef CONFIG_ALTIVEC
 	STD_EXCEPTION_COMMON(0x1700, altivec_assist, .altivec_assist_exception)
 #else
@@ -960,7 +1083,9 @@ _GLOBAL(do_stab_bolted)
 	rldimi	r10,r11,7,52	/* r10 = first ste of the group */
 
 	/* Calculate VSID */
-	/* This is a kernel address, so protovsid = ESID */
+	/* This is a kernel address, so protovsid = ESID | 1 << 37 */
+	li	r9,0x1
+	rldimi  r11,r9,(CONTEXT_BITS + USER_ESID_BITS),0
 	ASM_VSID_SCRAMBLE(r11, r9, 256M)
 	rldic	r9,r11,12,16	/* r9 = vsid << 12 */
 
diff --git a/arch/powerpc/kernel/fadump.c b/arch/powerpc/kernel/fadump.c
index 18bdf74..06c8202 100644
--- a/arch/powerpc/kernel/fadump.c
+++ b/arch/powerpc/kernel/fadump.c
@@ -289,8 +289,7 @@ int __init fadump_reserve_mem(void)
 		else
 			memory_limit = memblock_end_of_DRAM();
 		printk(KERN_INFO "Adjusted memory_limit for firmware-assisted"
-				" dump, now %#016llx\n",
-				(unsigned long long)memory_limit);
+				" dump, now %#016llx\n", memory_limit);
 	}
 	if (memory_limit)
 		memory_boundary = memory_limit;
diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S
index 0f59863..6f62a73 100644
--- a/arch/powerpc/kernel/head_fsl_booke.S
+++ b/arch/powerpc/kernel/head_fsl_booke.S
@@ -895,15 +895,11 @@ _GLOBAL(__setup_e500mc_ivors)
 	mtspr	SPRN_IVOR36,r3
 	li	r3,CriticalDoorbell@l
 	mtspr	SPRN_IVOR37,r3
+	sync
+	blr
 
-	/*
-	 * We only want to touch IVOR38-41 if we're running on hardware
-	 * that supports category E.HV.  The architectural way to determine
-	 * this is MMUCFG[LPIDSIZE].
-	 */
-	mfspr	r3, SPRN_MMUCFG
-	andis.	r3, r3, MMUCFG_LPIDSIZE@h
-	beq	no_hv
+/* setup ehv ivors for */
+_GLOBAL(__setup_ehv_ivors)
 	li	r3,GuestDoorbell@l
 	mtspr	SPRN_IVOR38,r3
 	li	r3,CriticalGuestDoorbell@l
@@ -912,14 +908,8 @@ _GLOBAL(__setup_e500mc_ivors)
 	mtspr	SPRN_IVOR40,r3
 	li	r3,Ehvpriv@l
 	mtspr	SPRN_IVOR41,r3
-skip_hv_ivors:
 	sync
 	blr
-no_hv:
-	lwz	r3, CPU_SPEC_FEATURES(r5)
-	rlwinm	r3, r3, 0, ~CPU_FTR_EMB_HV
-	stw	r3, CPU_SPEC_FEATURES(r5)
-	b	skip_hv_ivors
 
 #ifdef CONFIG_SPE
 /*
@@ -1043,6 +1033,34 @@ _GLOBAL(flush_dcache_L1)
 
 	blr
 
+/* Flush L1 d-cache, invalidate and disable d-cache and i-cache */
+_GLOBAL(__flush_disable_L1)
+	mflr	r10
+	bl	flush_dcache_L1	/* Flush L1 d-cache */
+	mtlr	r10
+
+	mfspr	r4, SPRN_L1CSR0	/* Invalidate and disable d-cache */
+	li	r5, 2
+	rlwimi	r4, r5, 0, 3
+
+	msync
+	isync
+	mtspr	SPRN_L1CSR0, r4
+	isync
+
+1:	mfspr	r4, SPRN_L1CSR0	/* Wait for the invalidate to finish */
+	andi.	r4, r4, 2
+	bne	1b
+
+	mfspr	r4, SPRN_L1CSR1	/* Invalidate and disable i-cache */
+	li	r5, 2
+	rlwimi	r4, r5, 0, 3
+
+	mtspr	SPRN_L1CSR1, r4
+	isync
+
+	blr
+
 #ifdef CONFIG_SMP
 /* When we get here, r24 needs to hold the CPU # */
 	.globl __secondary_start
diff --git a/arch/powerpc/kernel/hw_breakpoint.c b/arch/powerpc/kernel/hw_breakpoint.c
index 956a4c4..a89cae4 100644
--- a/arch/powerpc/kernel/hw_breakpoint.c
+++ b/arch/powerpc/kernel/hw_breakpoint.c
@@ -73,7 +73,7 @@ int arch_install_hw_breakpoint(struct perf_event *bp)
 	 * If so, DABR will be populated in single_step_dabr_instruction().
 	 */
 	if (current->thread.last_hit_ubp != bp)
-		set_dabr(info->address | info->type | DABR_TRANSLATION);
+		set_dabr(info->address | info->type | DABR_TRANSLATION, info->dabrx);
 
 	return 0;
 }
@@ -97,7 +97,7 @@ void arch_uninstall_hw_breakpoint(struct perf_event *bp)
 	}
 
 	*slot = NULL;
-	set_dabr(0);
+	set_dabr(0, 0);
 }
 
 /*
@@ -170,6 +170,13 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp)
 
 	info->address = bp->attr.bp_addr;
 	info->len = bp->attr.bp_len;
+	info->dabrx = DABRX_ALL;
+	if (bp->attr.exclude_user)
+		info->dabrx &= ~DABRX_USER;
+	if (bp->attr.exclude_kernel)
+		info->dabrx &= ~DABRX_KERNEL;
+	if (bp->attr.exclude_hv)
+		info->dabrx &= ~DABRX_HYP;
 
 	/*
 	 * Since breakpoint length can be a maximum of HW_BREAKPOINT_LEN(8)
@@ -197,7 +204,7 @@ void thread_change_pc(struct task_struct *tsk, struct pt_regs *regs)
 
 	info = counter_arch_bp(tsk->thread.last_hit_ubp);
 	regs->msr &= ~MSR_SE;
-	set_dabr(info->address | info->type | DABR_TRANSLATION);
+	set_dabr(info->address | info->type | DABR_TRANSLATION, info->dabrx);
 	tsk->thread.last_hit_ubp = NULL;
 }
 
@@ -215,7 +222,7 @@ int __kprobes hw_breakpoint_handler(struct die_args *args)
 	unsigned long dar = regs->dar;
 
 	/* Disable breakpoints during exception handling */
-	set_dabr(0);
+	set_dabr(0, 0);
 
 	/*
 	 * The counter may be concurrently released but that can only
@@ -281,7 +288,7 @@ int __kprobes hw_breakpoint_handler(struct die_args *args)
 	if (!info->extraneous_interrupt)
 		perf_bp_event(bp, regs);
 
-	set_dabr(info->address | info->type | DABR_TRANSLATION);
+	set_dabr(info->address | info->type | DABR_TRANSLATION, info->dabrx);
 out:
 	rcu_read_unlock();
 	return rc;
@@ -294,7 +301,7 @@ int __kprobes single_step_dabr_instruction(struct die_args *args)
 {
 	struct pt_regs *regs = args->regs;
 	struct perf_event *bp = NULL;
-	struct arch_hw_breakpoint *bp_info;
+	struct arch_hw_breakpoint *info;
 
 	bp = current->thread.last_hit_ubp;
 	/*
@@ -304,16 +311,16 @@ int __kprobes single_step_dabr_instruction(struct die_args *args)
 	if (!bp)
 		return NOTIFY_DONE;
 
-	bp_info = counter_arch_bp(bp);
+	info = counter_arch_bp(bp);
 
 	/*
 	 * We shall invoke the user-defined callback function in the single
 	 * stepping handler to confirm to 'trigger-after-execute' semantics
 	 */
-	if (!bp_info->extraneous_interrupt)
+	if (!info->extraneous_interrupt)
 		perf_bp_event(bp, regs);
 
-	set_dabr(bp_info->address | bp_info->type | DABR_TRANSLATION);
+	set_dabr(info->address | info->type | DABR_TRANSLATION, info->dabrx);
 	current->thread.last_hit_ubp = NULL;
 
 	/*
diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c
index b01d14e..8220baa 100644
--- a/arch/powerpc/kernel/ibmebus.c
+++ b/arch/powerpc/kernel/ibmebus.c
@@ -47,7 +47,6 @@
 #include <linux/stat.h>
 #include <linux/of_platform.h>
 #include <asm/ibmebus.h>
-#include <asm/abs_addr.h>
 
 static struct device ibmebus_bus_device = { /* fake "parent" device */
 	.init_name = "ibmebus",
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index 1f017bb..71413f4 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -489,10 +489,10 @@ void do_IRQ(struct pt_regs *regs)
 	struct pt_regs *old_regs = set_irq_regs(regs);
 	unsigned int irq;
 
-	trace_irq_entry(regs);
-
 	irq_enter();
 
+	trace_irq_entry(regs);
+
 	check_stack_overflow();
 
 	/*
@@ -511,10 +511,10 @@ void do_IRQ(struct pt_regs *regs)
 	else
 		__get_cpu_var(irq_stat).spurious_irqs++;
 
+	trace_irq_exit(regs);
+
 	irq_exit();
 	set_irq_regs(old_regs);
-
-	trace_irq_exit(regs);
 }
 
 void __init init_IRQ(void)
diff --git a/arch/powerpc/kernel/kvm.c b/arch/powerpc/kernel/kvm.c
index 867db1d..a61b133 100644
--- a/arch/powerpc/kernel/kvm.c
+++ b/arch/powerpc/kernel/kvm.c
@@ -419,7 +419,7 @@ static void kvm_map_magic_page(void *data)
 	in[0] = KVM_MAGIC_PAGE;
 	in[1] = KVM_MAGIC_PAGE;
 
-	kvm_hypercall(in, out, HC_VENDOR_KVM | KVM_HC_PPC_MAP_MAGIC_PAGE);
+	kvm_hypercall(in, out, KVM_HCALL_TOKEN(KVM_HC_PPC_MAP_MAGIC_PAGE));
 
 	*features = out[0];
 }
diff --git a/arch/powerpc/kernel/machine_kexec.c b/arch/powerpc/kernel/machine_kexec.c
index 5df7777..fa9f6c7 100644
--- a/arch/powerpc/kernel/machine_kexec.c
+++ b/arch/powerpc/kernel/machine_kexec.c
@@ -165,7 +165,7 @@ void __init reserve_crashkernel(void)
 	if (memory_limit && memory_limit <= crashk_res.end) {
 		memory_limit = crashk_res.end + 1;
 		printk("Adjusted memory limit for crashkernel, now 0x%llx\n",
-		       (unsigned long long)memory_limit);
+		       memory_limit);
 	}
 
 	printk(KERN_INFO "Reserving %ldMB of memory at %ldMB "
@@ -204,6 +204,12 @@ static struct property crashk_size_prop = {
 	.value = &crashk_size,
 };
 
+static struct property memory_limit_prop = {
+	.name = "linux,memory-limit",
+	.length = sizeof(unsigned long long),
+	.value = &memory_limit,
+};
+
 static void __init export_crashk_values(struct device_node *node)
 {
 	struct property *prop;
@@ -223,6 +229,12 @@ static void __init export_crashk_values(struct device_node *node)
 		crashk_size = resource_size(&crashk_res);
 		prom_add_property(node, &crashk_size_prop);
 	}
+
+	/*
+	 * memory_limit is required by the kexec-tools to limit the
+	 * crash regions to the actual memory used.
+	 */
+	prom_update_property(node, &memory_limit_prop);
 }
 
 static int __init kexec_setup(void)
diff --git a/arch/powerpc/kernel/misc.S b/arch/powerpc/kernel/misc.S
index ba16874..7ce26d4 100644
--- a/arch/powerpc/kernel/misc.S
+++ b/arch/powerpc/kernel/misc.S
@@ -54,13 +54,6 @@ _GLOBAL(add_reloc_offset)
 	.align	3
 2:	PPC_LONG 1b
 
-_GLOBAL(kernel_execve)
-	li	r0,__NR_execve
-	sc
-	bnslr
-	neg	r3,r3
-	blr
-
 _GLOBAL(setjmp)
 	mflr	r0
 	PPC_STL	r0,0(r3)
diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S
index 407e293..19e096b 100644
--- a/arch/powerpc/kernel/misc_32.S
+++ b/arch/powerpc/kernel/misc_32.S
@@ -663,39 +663,6 @@ _GLOBAL(abs)
 	sub	r3,r3,r4
 	blr
 
-/*
- * Create a kernel thread
- *   kernel_thread(fn, arg, flags)
- */
-_GLOBAL(kernel_thread)
-	stwu	r1,-16(r1)
-	stw	r30,8(r1)
-	stw	r31,12(r1)
-	mr	r30,r3		/* function */
-	mr	r31,r4		/* argument */
-	ori	r3,r5,CLONE_VM	/* flags */
-	oris	r3,r3,CLONE_UNTRACED>>16
-	li	r4,0		/* new sp (unused) */
-	li	r0,__NR_clone
-	sc
-	bns+	1f		/* did system call indicate error? */
-	neg	r3,r3		/* if so, make return code negative */
-1:	cmpwi	0,r3,0		/* parent or child? */
-	bne	2f		/* return if parent */
-	li	r0,0		/* make top-level stack frame */
-	stwu	r0,-16(r1)
-	mtlr	r30		/* fn addr in lr */
-	mr	r3,r31		/* load arg and call fn */
-	PPC440EP_ERR42
-	blrl
-	li	r0,__NR_exit	/* exit if function returns */
-	li	r3,0
-	sc
-2:	lwz	r30,8(r1)
-	lwz	r31,12(r1)
-	addi	r1,r1,16
-	blr
-
 #ifdef CONFIG_SMP
 _GLOBAL(start_secondary_resume)
 	/* Reset stack */
diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S
index 565b786..5cfa800 100644
--- a/arch/powerpc/kernel/misc_64.S
+++ b/arch/powerpc/kernel/misc_64.S
@@ -407,40 +407,6 @@ _GLOBAL(scom970_write)
 
 
 /*
- * Create a kernel thread
- *   kernel_thread(fn, arg, flags)
- */
-_GLOBAL(kernel_thread)
-	std	r29,-24(r1)
-	std	r30,-16(r1)
-	stdu	r1,-STACK_FRAME_OVERHEAD(r1)
-	mr	r29,r3
-	mr	r30,r4
-	ori	r3,r5,CLONE_VM	/* flags */
-	oris	r3,r3,(CLONE_UNTRACED>>16)
-	li	r4,0		/* new sp (unused) */
-	li	r0,__NR_clone
-	sc
-	bns+	1f		/* did system call indicate error? */
-	neg	r3,r3		/* if so, make return code negative */
-1:	cmpdi	0,r3,0		/* parent or child? */
-	bne	2f		/* return if parent */
-	li	r0,0
-	stdu	r0,-STACK_FRAME_OVERHEAD(r1)
-	ld	r2,8(r29)
-	ld	r29,0(r29)
-	mtlr	r29              /* fn addr in lr */
-	mr	r3,r30	        /* load arg and call fn */
-	blrl
-	li	r0,__NR_exit	/* exit after child exits */
-        li	r3,0
-	sc
-2:	addi	r1,r1,STACK_FRAME_OVERHEAD
-	ld	r29,-24(r1)
-	ld	r30,-16(r1)
-	blr
-
-/*
  * disable_kernel_fp()
  * Disable the FPU.
  */
diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c
index fbe1a12..cd6da85 100644
--- a/arch/powerpc/kernel/paca.c
+++ b/arch/powerpc/kernel/paca.c
@@ -142,6 +142,7 @@ void __init initialise_paca(struct paca_struct *new_paca, int cpu)
 	new_paca->hw_cpu_id = 0xffff;
 	new_paca->kexec_state = KEXEC_STATE_NONE;
 	new_paca->__current = &init_task;
+	new_paca->data_offset = 0xfeeeeeeeeeeeeeeeULL;
 #ifdef CONFIG_PPC_STD_MMU_64
 	new_paca->slb_shadow_ptr = &slb_shadow[cpu];
 #endif /* CONFIG_PPC_STD_MMU_64 */
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index 2aa04f2..7f94f76 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -99,6 +99,26 @@ void pcibios_free_controller(struct pci_controller *phb)
 		kfree(phb);
 }
 
+/*
+ * The function is used to return the minimal alignment
+ * for memory or I/O windows of the associated P2P bridge.
+ * By default, 4KiB alignment for I/O windows and 1MiB for
+ * memory windows.
+ */
+resource_size_t pcibios_window_alignment(struct pci_bus *bus,
+					 unsigned long type)
+{
+	if (ppc_md.pcibios_window_alignment)
+		return ppc_md.pcibios_window_alignment(bus, type);
+
+	/*
+	 * PCI core will figure out the default
+	 * alignment: 4KiB for I/O and 1MiB for
+	 * memory window.
+	 */
+	return 1;
+}
+
 static resource_size_t pcibios_io_size(const struct pci_controller *hose)
 {
 #ifdef CONFIG_PPC64
@@ -960,13 +980,14 @@ static void __devinit pcibios_fixup_bridge(struct pci_bus *bus)
 		if (i >= 3 && bus->self->transparent)
 			continue;
 
-		/* If we are going to re-assign everything, mark the resource
-		 * as unset and move it down to 0
+		/* If we're going to reassign everything, we can
+		 * shrink the P2P resource to have size as being
+		 * of 0 in order to save space.
 		 */
 		if (pci_has_flag(PCI_REASSIGN_ALL_RSRC)) {
 			res->flags |= IORESOURCE_UNSET;
-			res->end -= res->start;
 			res->start = 0;
+			res->end = -1;
 			continue;
 		}
 
@@ -1228,7 +1249,14 @@ void pcibios_allocate_bus_resources(struct pci_bus *bus)
 		pr_warning("PCI: Cannot allocate resource region "
 			   "%d of PCI bridge %d, will remap\n", i, bus->number);
 	clear_resource:
-		res->start = res->end = 0;
+		/* The resource might be figured out when doing
+		 * reassignment based on the resources required
+		 * by the downstream PCI devices. Here we set
+		 * the size of the resource to be 0 in order to
+		 * save more space.
+		 */
+		res->start = 0;
+		res->end = -1;
 		res->flags = 0;
 	}
 
diff --git a/arch/powerpc/kernel/ppc32.h b/arch/powerpc/kernel/ppc32.h
index dc16aef..02fb0ee 100644
--- a/arch/powerpc/kernel/ppc32.h
+++ b/arch/powerpc/kernel/ppc32.h
@@ -16,57 +16,6 @@
 
 /* These are here to support 32-bit syscalls on a 64-bit kernel. */
 
-typedef struct compat_siginfo {
-	int si_signo;
-	int si_errno;
-	int si_code;
-
-	union {
-		int _pad[SI_PAD_SIZE32];
-
-		/* kill() */
-		struct {
-			compat_pid_t _pid;		/* sender's pid */
-			compat_uid_t _uid;		/* sender's uid */
-		} _kill;
-
-		/* POSIX.1b timers */
-		struct {
-			compat_timer_t _tid;			/* timer id */
-			int _overrun;			/* overrun count */
-			compat_sigval_t _sigval;		/* same as below */
-			int _sys_private;		/* not to be passed to user */
-		} _timer;
-
-		/* POSIX.1b signals */
-		struct {
-			compat_pid_t _pid;		/* sender's pid */
-			compat_uid_t _uid;		/* sender's uid */
-			compat_sigval_t _sigval;
-		} _rt;
-
-		/* SIGCHLD */
-		struct {
-			compat_pid_t _pid;		/* which child */
-			compat_uid_t _uid;		/* sender's uid */
-			int _status;			/* exit code */
-			compat_clock_t _utime;
-			compat_clock_t _stime;
-		} _sigchld;
-
-		/* SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGEMT */
-		struct {
-			unsigned int _addr; /* faulting insn/memory ref. */
-		} _sigfault;
-
-		/* SIGPOLL */
-		struct {
-			int _band;	/* POLL_IN, POLL_OUT, POLL_MSG */
-			int _fd;
-		} _sigpoll;
-	} _sifields;
-} compat_siginfo_t;
-
 #define __old_sigaction32	old_sigaction32
 
 struct __old_sigaction32 {
diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c
index 3e40315..78b8766 100644
--- a/arch/powerpc/kernel/ppc_ksyms.c
+++ b/arch/powerpc/kernel/ppc_ksyms.c
@@ -43,6 +43,7 @@
 #include <asm/dcr.h>
 #include <asm/ftrace.h>
 #include <asm/switch_to.h>
+#include <asm/epapr_hcalls.h>
 
 #ifdef CONFIG_PPC32
 extern void transfer_to_handler(void);
@@ -94,7 +95,6 @@ EXPORT_SYMBOL(pci_dram_offset);
 #endif /* CONFIG_PCI */
 
 EXPORT_SYMBOL(start_thread);
-EXPORT_SYMBOL(kernel_thread);
 
 EXPORT_SYMBOL(giveup_fpu);
 #ifdef CONFIG_ALTIVEC
@@ -192,3 +192,7 @@ EXPORT_SYMBOL(__arch_hweight64);
 #ifdef CONFIG_PPC_BOOK3S_64
 EXPORT_SYMBOL_GPL(mmu_psize_defs);
 #endif
+
+#ifdef CONFIG_EPAPR_PARAVIRT
+EXPORT_SYMBOL(epapr_hypercall_start);
+#endif
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 1a1f2dd..ba48233 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -258,6 +258,7 @@ void do_send_trap(struct pt_regs *regs, unsigned long address,
 {
 	siginfo_t info;
 
+	current->thread.trap_nr = signal_code;
 	if (notify_die(DIE_DABR_MATCH, "dabr_match", regs, error_code,
 			11, SIGSEGV) == NOTIFY_STOP)
 		return;
@@ -275,6 +276,7 @@ void do_dabr(struct pt_regs *regs, unsigned long address,
 {
 	siginfo_t info;
 
+	current->thread.trap_nr = TRAP_HWBKPT;
 	if (notify_die(DIE_DABR_MATCH, "dabr_match", regs, error_code,
 			11, SIGSEGV) == NOTIFY_STOP)
 		return;
@@ -283,7 +285,7 @@ void do_dabr(struct pt_regs *regs, unsigned long address,
 		return;
 
 	/* Clear the DABR */
-	set_dabr(0);
+	set_dabr(0, 0);
 
 	/* Deliver the signal to userspace */
 	info.si_signo = SIGTRAP;
@@ -364,18 +366,19 @@ static void set_debug_reg_defaults(struct thread_struct *thread)
 {
 	if (thread->dabr) {
 		thread->dabr = 0;
-		set_dabr(0);
+		thread->dabrx = 0;
+		set_dabr(0, 0);
 	}
 }
 #endif /* !CONFIG_HAVE_HW_BREAKPOINT */
 #endif	/* CONFIG_PPC_ADV_DEBUG_REGS */
 
-int set_dabr(unsigned long dabr)
+int set_dabr(unsigned long dabr, unsigned long dabrx)
 {
 	__get_cpu_var(current_dabr) = dabr;
 
 	if (ppc_md.set_dabr)
-		return ppc_md.set_dabr(dabr);
+		return ppc_md.set_dabr(dabr, dabrx);
 
 	/* XXX should we have a CPU_FTR_HAS_DABR ? */
 #ifdef CONFIG_PPC_ADV_DEBUG_REGS
@@ -385,9 +388,8 @@ int set_dabr(unsigned long dabr)
 #endif
 #elif defined(CONFIG_PPC_BOOK3S)
 	mtspr(SPRN_DABR, dabr);
+	mtspr(SPRN_DABRX, dabrx);
 #endif
-
-
 	return 0;
 }
 
@@ -480,7 +482,7 @@ struct task_struct *__switch_to(struct task_struct *prev,
  */
 #ifndef CONFIG_HAVE_HW_BREAKPOINT
 	if (unlikely(__get_cpu_var(current_dabr) != new->thread.dabr))
-		set_dabr(new->thread.dabr);
+		set_dabr(new->thread.dabr, new->thread.dabrx);
 #endif /* CONFIG_HAVE_HW_BREAKPOINT */
 #endif
 
@@ -514,9 +516,6 @@ struct task_struct *__switch_to(struct task_struct *prev,
 
 	local_irq_save(flags);
 
-	account_system_vtime(current);
-	account_process_vtime(current);
-
 	/*
 	 * We can't take a PMU exception inside _switch() since there is a
 	 * window where the kernel stack SLB and the kernel stack are out
@@ -734,30 +733,39 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
 extern unsigned long dscr_default; /* defined in arch/powerpc/kernel/sysfs.c */
 
 int copy_thread(unsigned long clone_flags, unsigned long usp,
-		unsigned long unused, struct task_struct *p,
+		unsigned long arg, struct task_struct *p,
 		struct pt_regs *regs)
 {
 	struct pt_regs *childregs, *kregs;
 	extern void ret_from_fork(void);
+	extern void ret_from_kernel_thread(void);
+	void (*f)(void);
 	unsigned long sp = (unsigned long)task_stack_page(p) + THREAD_SIZE;
 
-	CHECK_FULL_REGS(regs);
 	/* Copy registers */
 	sp -= sizeof(struct pt_regs);
 	childregs = (struct pt_regs *) sp;
-	*childregs = *regs;
-	if ((childregs->msr & MSR_PR) == 0) {
+	if (!regs) {
 		/* for kernel thread, set `current' and stackptr in new task */
+		memset(childregs, 0, sizeof(struct pt_regs));
 		childregs->gpr[1] = sp + sizeof(struct pt_regs);
-#ifdef CONFIG_PPC32
-		childregs->gpr[2] = (unsigned long) p;
-#else
+#ifdef CONFIG_PPC64
+		childregs->gpr[14] = *(unsigned long *)usp;
+		childregs->gpr[2] = ((unsigned long *)usp)[1],
 		clear_tsk_thread_flag(p, TIF_32BIT);
+#else
+		childregs->gpr[14] = usp;	/* function */
+		childregs->gpr[2] = (unsigned long) p;
 #endif
+		childregs->gpr[15] = arg;
 		p->thread.regs = NULL;	/* no user register state */
+		f = ret_from_kernel_thread;
 	} else {
+		CHECK_FULL_REGS(regs);
+		*childregs = *regs;
 		childregs->gpr[1] = usp;
 		p->thread.regs = childregs;
+		childregs->gpr[3] = 0;  /* Result from fork() */
 		if (clone_flags & CLONE_SETTLS) {
 #ifdef CONFIG_PPC64
 			if (!is_32bit_task())
@@ -766,8 +774,9 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
 #endif
 				childregs->gpr[2] = childregs->gpr[6];
 		}
+
+		f = ret_from_fork;
 	}
-	childregs->gpr[3] = 0;  /* Result from fork() */
 	sp -= STACK_FRAME_OVERHEAD;
 
 	/*
@@ -806,19 +815,17 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
 		p->thread.dscr = current->thread.dscr;
 	}
 #endif
-
 	/*
 	 * The PPC64 ABI makes use of a TOC to contain function 
 	 * pointers.  The function (ret_from_except) is actually a pointer
 	 * to the TOC entry.  The first entry is a pointer to the actual
 	 * function.
- 	 */
+	 */
 #ifdef CONFIG_PPC64
-	kregs->nip = *((unsigned long *)ret_from_fork);
+	kregs->nip = *((unsigned long *)f);
 #else
-	kregs->nip = (unsigned long)ret_from_fork;
+	kregs->nip = (unsigned long)f;
 #endif
-
 	return 0;
 }
 
@@ -1056,26 +1063,13 @@ int sys_vfork(unsigned long p1, unsigned long p2, unsigned long p3,
 			regs, 0, NULL, NULL);
 }
 
-int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
-	       unsigned long a3, unsigned long a4, unsigned long a5,
-	       struct pt_regs *regs)
+void __ret_from_kernel_execve(struct pt_regs *normal)
+__noreturn;
+
+void ret_from_kernel_execve(struct pt_regs *normal)
 {
-	int error;
-	char *filename;
-
-	filename = getname((const char __user *) a0);
-	error = PTR_ERR(filename);
-	if (IS_ERR(filename))
-		goto out;
-	flush_fp_to_thread(current);
-	flush_altivec_to_thread(current);
-	flush_spe_to_thread(current);
-	error = do_execve(filename,
-			  (const char __user *const __user *) a1,
-			  (const char __user *const __user *) a2, regs);
-	putname(filename);
-out:
-	return error;
+	set_thread_flag(TIF_RESTOREALL);
+	__ret_from_kernel_execve(normal);
 }
 
 static inline int valid_irq_stack(unsigned long sp, struct task_struct *p,
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index f191bf0..37725e8 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -78,7 +78,7 @@ static int __init early_parse_mem(char *p)
 		return 1;
 
 	memory_limit = PAGE_ALIGN(memparse(p, &p));
-	DBG("memory limit = 0x%llx\n", (unsigned long long)memory_limit);
+	DBG("memory limit = 0x%llx\n", memory_limit);
 
 	return 0;
 }
@@ -661,7 +661,7 @@ void __init early_init_devtree(void *params)
 
 	/* make sure we've parsed cmdline for mem= before this */
 	if (memory_limit)
-		first_memblock_size = min(first_memblock_size, memory_limit);
+		first_memblock_size = min_t(u64, first_memblock_size, memory_limit);
 	setup_initial_memory_limit(memstart_addr, first_memblock_size);
 	/* Reserve MEMBLOCK regions used by kernel, initrd, dt, etc... */
 	memblock_reserve(PHYSICAL_START, __pa(klimit) - PHYSICAL_START);
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index 0794a30..cb6c123 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -705,6 +705,7 @@ static void __init early_cmdline_parse(void)
 #endif
 #define OV5_TYPE1_AFFINITY	0x80	/* Type 1 NUMA affinity */
 #define OV5_PFO_HW_RNG		0x80	/* PFO Random Number Generator */
+#define OV5_PFO_HW_842		0x40	/* PFO Compression Accelerator */
 #define OV5_PFO_HW_ENCR		0x20	/* PFO Encryption Accelerator */
 
 /* Option Vector 6: IBM PAPR hints */
@@ -774,8 +775,7 @@ static unsigned char ibm_architecture_vec[] = {
 	0,
 	0,
 	0,
-	OV5_PFO_HW_RNG | OV5_PFO_HW_ENCR,
-
+	OV5_PFO_HW_RNG | OV5_PFO_HW_ENCR | OV5_PFO_HW_842,
 	/* option vector 6: IBM PAPR hints */
 	4 - 2,				/* length */
 	0,
@@ -1624,6 +1624,63 @@ static void __init prom_instantiate_rtas(void)
 
 #ifdef CONFIG_PPC64
 /*
+ * Allocate room for and instantiate Stored Measurement Log (SML)
+ */
+static void __init prom_instantiate_sml(void)
+{
+	phandle ibmvtpm_node;
+	ihandle ibmvtpm_inst;
+	u32 entry = 0, size = 0;
+	u64 base;
+
+	prom_debug("prom_instantiate_sml: start...\n");
+
+	ibmvtpm_node = call_prom("finddevice", 1, 1, ADDR("/ibm,vtpm"));
+	prom_debug("ibmvtpm_node: %x\n", ibmvtpm_node);
+	if (!PHANDLE_VALID(ibmvtpm_node))
+		return;
+
+	ibmvtpm_inst = call_prom("open", 1, 1, ADDR("/ibm,vtpm"));
+	if (!IHANDLE_VALID(ibmvtpm_inst)) {
+		prom_printf("opening vtpm package failed (%x)\n", ibmvtpm_inst);
+		return;
+	}
+
+	if (call_prom_ret("call-method", 2, 2, &size,
+			  ADDR("sml-get-handover-size"),
+			  ibmvtpm_inst) != 0 || size == 0) {
+		prom_printf("SML get handover size failed\n");
+		return;
+	}
+
+	base = alloc_down(size, PAGE_SIZE, 0);
+	if (base == 0)
+		prom_panic("Could not allocate memory for sml\n");
+
+	prom_printf("instantiating sml at 0x%x...", base);
+
+	if (call_prom_ret("call-method", 4, 2, &entry,
+			  ADDR("sml-handover"),
+			  ibmvtpm_inst, size, base) != 0 || entry == 0) {
+		prom_printf("SML handover failed\n");
+		return;
+	}
+	prom_printf(" done\n");
+
+	reserve_mem(base, size);
+
+	prom_setprop(ibmvtpm_node, "/ibm,vtpm", "linux,sml-base",
+		     &base, sizeof(base));
+	prom_setprop(ibmvtpm_node, "/ibm,vtpm", "linux,sml-size",
+		     &size, sizeof(size));
+
+	prom_debug("sml base     = 0x%x\n", base);
+	prom_debug("sml size     = 0x%x\n", (long)size);
+
+	prom_debug("prom_instantiate_sml: end...\n");
+}
+
+/*
  * Allocate room for and initialize TCE tables
  */
 static void __init prom_initialize_tce_table(void)
@@ -1691,7 +1748,7 @@ static void __init prom_initialize_tce_table(void)
 		 * else will impact performance, so we always allocate 8MB.
 		 * Anton
 		 */
-		if (__is_processor(PV_POWER4) || __is_processor(PV_POWER4p))
+		if (pvr_version_is(PVR_POWER4) || pvr_version_is(PVR_POWER4p))
 			minsize = 8UL << 20;
 		else
 			minsize = 4UL << 20;
@@ -2916,6 +2973,11 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
 		prom_instantiate_opal();
 #endif
 
+#ifdef CONFIG_PPC64
+	/* instantiate sml */
+	prom_instantiate_sml();
+#endif
+
 	/*
 	 * On non-powermacs, put all CPUs in spin-loops.
 	 *
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index c10fc28..79d8e56 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -960,6 +960,7 @@ int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
 		thread->ptrace_bps[0] = bp;
 		ptrace_put_breakpoints(task);
 		thread->dabr = data;
+		thread->dabrx = DABRX_ALL;
 		return 0;
 	}
 
@@ -983,6 +984,7 @@ int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
 
 	/* Move contents to the DABR register */
 	task->thread.dabr = data;
+	task->thread.dabrx = DABRX_ALL;
 #else /* CONFIG_PPC_ADV_DEBUG_REGS */
 	/* As described above, it was assumed 3 bits were passed with the data
 	 *  address, but we will assume only the mode bits will be passed
@@ -1397,6 +1399,7 @@ static long ppc_set_hwdebug(struct task_struct *child,
 		dabr |= DABR_DATA_WRITE;
 
 	child->thread.dabr = dabr;
+	child->thread.dabrx = DABRX_ALL;
 
 	return 1;
 #endif /* !CONFIG_PPC_ADV_DEBUG_DVCS */
diff --git a/arch/powerpc/kernel/rtas_flash.c b/arch/powerpc/kernel/rtas_flash.c
index 2c0ee64..20b0120 100644
--- a/arch/powerpc/kernel/rtas_flash.c
+++ b/arch/powerpc/kernel/rtas_flash.c
@@ -21,7 +21,6 @@
 #include <asm/delay.h>
 #include <asm/uaccess.h>
 #include <asm/rtas.h>
-#include <asm/abs_addr.h>
 
 #define MODULE_VERS "1.0"
 #define MODULE_NAME "rtas_flash"
@@ -582,7 +581,7 @@ static void rtas_flash_firmware(int reboot_type)
 	flist = (struct flash_block_list *)&rtas_data_buf[0];
 	flist->num_blocks = 0;
 	flist->next = rtas_firmware_flash_list;
-	rtas_block_list = virt_to_abs(flist);
+	rtas_block_list = __pa(flist);
 	if (rtas_block_list >= 4UL*1024*1024*1024) {
 		printk(KERN_ALERT "FLASH: kernel bug...flash list header addr above 4GB\n");
 		spin_unlock(&rtas_data_buf_lock);
@@ -596,13 +595,13 @@ static void rtas_flash_firmware(int reboot_type)
 	for (f = flist; f; f = next) {
 		/* Translate data addrs to absolute */
 		for (i = 0; i < f->num_blocks; i++) {
-			f->blocks[i].data = (char *)virt_to_abs(f->blocks[i].data);
+			f->blocks[i].data = (char *)__pa(f->blocks[i].data);
 			image_size += f->blocks[i].length;
 		}
 		next = f->next;
 		/* Don't translate NULL pointer for last entry */
 		if (f->next)
-			f->next = (struct flash_block_list *)virt_to_abs(f->next);
+			f->next = (struct flash_block_list *)__pa(f->next);
 		else
 			f->next = NULL;
 		/* make num_blocks into the version/length field */
diff --git a/arch/powerpc/kernel/rtas_pci.c b/arch/powerpc/kernel/rtas_pci.c
index 179af90..6de63e3 100644
--- a/arch/powerpc/kernel/rtas_pci.c
+++ b/arch/powerpc/kernel/rtas_pci.c
@@ -81,7 +81,7 @@ int rtas_read_config(struct pci_dn *pdn, int where, int size, u32 *val)
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
 	if (returnval == EEH_IO_ERROR_VALUE(size) &&
-	    eeh_dn_check_failure (pdn->node, NULL))
+	    eeh_dev_check_failure(of_node_to_eeh_dev(pdn->node)))
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
 	return PCIBIOS_SUCCESSFUL;
@@ -275,9 +275,6 @@ void __init find_and_init_phbs(void)
 	of_node_put(root);
 	pci_devs_phb_init();
 
-	/* Create EEH devices for all PHBs */
-	eeh_dev_phb_init();
-
 	/*
 	 * PCI_PROBE_ONLY and PCI_REASSIGN_ALL_BUS can be set via properties
 	 * in chosen.
diff --git a/arch/powerpc/kernel/signal.c b/arch/powerpc/kernel/signal.c
index 5c023c9..a2dc757 100644
--- a/arch/powerpc/kernel/signal.c
+++ b/arch/powerpc/kernel/signal.c
@@ -11,6 +11,7 @@
 
 #include <linux/tracehook.h>
 #include <linux/signal.h>
+#include <linux/uprobes.h>
 #include <linux/key.h>
 #include <asm/hw_breakpoint.h>
 #include <asm/uaccess.h>
@@ -130,7 +131,7 @@ static int do_signal(struct pt_regs *regs)
 	 * triggered inside the kernel.
 	 */
 	if (current->thread.dabr)
-		set_dabr(current->thread.dabr);
+		set_dabr(current->thread.dabr, current->thread.dabrx);
 #endif
 	/* Re-enable the breakpoints for the signal stack */
 	thread_change_pc(current, regs);
@@ -157,6 +158,11 @@ static int do_signal(struct pt_regs *regs)
 
 void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags)
 {
+	if (thread_info_flags & _TIF_UPROBE) {
+		clear_thread_flag(TIF_UPROBE);
+		uprobe_notify_resume(regs);
+	}
+
 	if (thread_info_flags & _TIF_SIGPENDING)
 		do_signal(regs);
 
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
index 8b4c049..804e323 100644
--- a/arch/powerpc/kernel/signal_32.c
+++ b/arch/powerpc/kernel/signal_32.c
@@ -35,7 +35,6 @@
 #include <linux/stddef.h>
 #include <linux/tty.h>
 #include <linux/binfmts.h>
-#include <linux/freezer.h>
 #endif
 
 #include <asm/uaccess.h>
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index 8d4214a..2b952b5 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -102,7 +102,7 @@ int __devinit smp_generic_kick_cpu(int nr)
 	 * Ok it's not there, so it might be soft-unplugged, let's
 	 * try to bring it back
 	 */
-	per_cpu(cpu_state, nr) = CPU_UP_PREPARE;
+	generic_set_cpu_up(nr);
 	smp_wmb();
 	smp_send_reschedule(nr);
 #endif /* CONFIG_HOTPLUG_CPU */
@@ -171,7 +171,7 @@ int smp_request_message_ipi(int virq, int msg)
 	}
 #endif
 	err = request_irq(virq, smp_ipi_action[msg],
-			  IRQF_PERCPU | IRQF_NO_THREAD,
+			  IRQF_PERCPU | IRQF_NO_THREAD | IRQF_NO_SUSPEND,
 			  smp_ipi_name[msg], 0);
 	WARN(err < 0, "unable to request_irq %d for %s (rc %d)\n",
 		virq, smp_ipi_name[msg], err);
@@ -413,6 +413,16 @@ void generic_set_cpu_dead(unsigned int cpu)
 	per_cpu(cpu_state, cpu) = CPU_DEAD;
 }
 
+/*
+ * The cpu_state should be set to CPU_UP_PREPARE in kick_cpu(), otherwise
+ * the cpu_state is always CPU_DEAD after calling generic_set_cpu_dead(),
+ * which makes the delay in generic_cpu_die() not happen.
+ */
+void generic_set_cpu_up(unsigned int cpu)
+{
+	per_cpu(cpu_state, cpu) = CPU_UP_PREPARE;
+}
+
 int generic_check_cpu_restart(unsigned int cpu)
 {
 	return per_cpu(cpu_state, cpu) == CPU_UP_PREPARE;
diff --git a/arch/powerpc/kernel/sys_ppc32.c b/arch/powerpc/kernel/sys_ppc32.c
index 81c5706..a1ae73a 100644
--- a/arch/powerpc/kernel/sys_ppc32.c
+++ b/arch/powerpc/kernel/sys_ppc32.c
@@ -187,28 +187,6 @@ asmlinkage int compat_sys_sendfile64(int out_fd, int in_fd, compat_loff_t __user
 	return ret;
 }
 
-long compat_sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
-		  unsigned long a3, unsigned long a4, unsigned long a5,
-		  struct pt_regs *regs)
-{
-	int error;
-	char * filename;
-	
-	filename = getname((char __user *) a0);
-	error = PTR_ERR(filename);
-	if (IS_ERR(filename))
-		goto out;
-	flush_fp_to_thread(current);
-	flush_altivec_to_thread(current);
-
-	error = compat_do_execve(filename, compat_ptr(a1), compat_ptr(a2), regs);
-
-	putname(filename);
-
-out:
-	return error;
-}
-
 /* Note: it is necessary to treat option as an unsigned int, 
  * with the corresponding cast to a signed int to insure that the 
  * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index e49e931..1513ee4 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -366,6 +366,12 @@ void account_process_tick(struct task_struct *tsk, int user_tick)
 	account_user_time(tsk, utime, utimescaled);
 }
 
+void account_switch_vtime(struct task_struct *prev)
+{
+	account_system_vtime(prev);
+	account_process_tick(prev, 0);
+}
+
 #else /* ! CONFIG_VIRT_CPU_ACCOUNTING */
 #define calc_cputime_factors()
 #endif
@@ -493,8 +499,6 @@ void timer_interrupt(struct pt_regs * regs)
 	 */
 	may_hard_irq_enable();
 
-	trace_timer_interrupt_entry(regs);
-
 	__get_cpu_var(irq_stat).timer_irqs++;
 
 #if defined(CONFIG_PPC32) && defined(CONFIG_PMAC)
@@ -505,6 +509,8 @@ void timer_interrupt(struct pt_regs * regs)
 	old_regs = set_irq_regs(regs);
 	irq_enter();
 
+	trace_timer_interrupt_entry(regs);
+
 	if (test_irq_work_pending()) {
 		clear_irq_work_pending();
 		irq_work_run();
@@ -529,10 +535,10 @@ void timer_interrupt(struct pt_regs * regs)
 	}
 #endif
 
+	trace_timer_interrupt_exit(regs);
+
 	irq_exit();
 	set_irq_regs(old_regs);
-
-	trace_timer_interrupt_exit(regs);
 }
 
 /*
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index ae0843f..3251840 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -251,6 +251,7 @@ void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr)
 	if (arch_irqs_disabled() && !arch_irq_disabled_regs(regs))
 		local_irq_enable();
 
+	current->thread.trap_nr = code;
 	memset(&info, 0, sizeof(info));
 	info.si_signo = signr;
 	info.si_code = code;
diff --git a/arch/powerpc/kernel/uprobes.c b/arch/powerpc/kernel/uprobes.c
new file mode 100644
index 0000000..d2d46d1
--- /dev/null
+++ b/arch/powerpc/kernel/uprobes.c
@@ -0,0 +1,184 @@
+/*
+ * User-space Probes (UProbes) for powerpc
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 IBM Corporation, 2007-2012
+ *
+ * Adapted from the x86 port by Ananth N Mavinakayanahalli <ananth@in.ibm.com>
+ */
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/ptrace.h>
+#include <linux/uprobes.h>
+#include <linux/uaccess.h>
+#include <linux/kdebug.h>
+
+#include <asm/sstep.h>
+
+#define UPROBE_TRAP_NR	UINT_MAX
+
+/**
+ * arch_uprobe_analyze_insn
+ * @mm: the probed address space.
+ * @arch_uprobe: the probepoint information.
+ * @addr: vaddr to probe.
+ * Return 0 on success or a -ve number on error.
+ */
+int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe,
+		struct mm_struct *mm, unsigned long addr)
+{
+	if (addr & 0x03)
+		return -EINVAL;
+
+	/*
+	 * We currently don't support a uprobe on an already
+	 * existing breakpoint instruction underneath
+	 */
+	if (is_trap(auprobe->ainsn))
+		return -ENOTSUPP;
+	return 0;
+}
+
+/*
+ * arch_uprobe_pre_xol - prepare to execute out of line.
+ * @auprobe: the probepoint information.
+ * @regs: reflects the saved user state of current task.
+ */
+int arch_uprobe_pre_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
+{
+	struct arch_uprobe_task *autask = &current->utask->autask;
+
+	autask->saved_trap_nr = current->thread.trap_nr;
+	current->thread.trap_nr = UPROBE_TRAP_NR;
+	regs->nip = current->utask->xol_vaddr;
+	return 0;
+}
+
+/**
+ * uprobe_get_swbp_addr - compute address of swbp given post-swbp regs
+ * @regs: Reflects the saved state of the task after it has hit a breakpoint
+ * instruction.
+ * Return the address of the breakpoint instruction.
+ */
+unsigned long uprobe_get_swbp_addr(struct pt_regs *regs)
+{
+	return instruction_pointer(regs);
+}
+
+/*
+ * If xol insn itself traps and generates a signal (SIGILL/SIGSEGV/etc),
+ * then detect the case where a singlestepped instruction jumps back to its
+ * own address. It is assumed that anything like do_page_fault/do_trap/etc
+ * sets thread.trap_nr != UINT_MAX.
+ *
+ * arch_uprobe_pre_xol/arch_uprobe_post_xol save/restore thread.trap_nr,
+ * arch_uprobe_xol_was_trapped() simply checks that ->trap_nr is not equal to
+ * UPROBE_TRAP_NR == UINT_MAX set by arch_uprobe_pre_xol().
+ */
+bool arch_uprobe_xol_was_trapped(struct task_struct *t)
+{
+	if (t->thread.trap_nr != UPROBE_TRAP_NR)
+		return true;
+
+	return false;
+}
+
+/*
+ * Called after single-stepping. To avoid the SMP problems that can
+ * occur when we temporarily put back the original opcode to
+ * single-step, we single-stepped a copy of the instruction.
+ *
+ * This function prepares to resume execution after the single-step.
+ */
+int arch_uprobe_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
+{
+	struct uprobe_task *utask = current->utask;
+
+	WARN_ON_ONCE(current->thread.trap_nr != UPROBE_TRAP_NR);
+
+	current->thread.trap_nr = utask->autask.saved_trap_nr;
+
+	/*
+	 * On powerpc, except for loads and stores, most instructions
+	 * including ones that alter code flow (branches, calls, returns)
+	 * are emulated in the kernel. We get here only if the emulation
+	 * support doesn't exist and have to fix-up the next instruction
+	 * to be executed.
+	 */
+	regs->nip = utask->vaddr + MAX_UINSN_BYTES;
+	return 0;
+}
+
+/* callback routine for handling exceptions. */
+int arch_uprobe_exception_notify(struct notifier_block *self,
+				unsigned long val, void *data)
+{
+	struct die_args *args = data;
+	struct pt_regs *regs = args->regs;
+
+	/* regs == NULL is a kernel bug */
+	if (WARN_ON(!regs))
+		return NOTIFY_DONE;
+
+	/* We are only interested in userspace traps */
+	if (!user_mode(regs))
+		return NOTIFY_DONE;
+
+	switch (val) {
+	case DIE_BPT:
+		if (uprobe_pre_sstep_notifier(regs))
+			return NOTIFY_STOP;
+		break;
+	case DIE_SSTEP:
+		if (uprobe_post_sstep_notifier(regs))
+			return NOTIFY_STOP;
+	default:
+		break;
+	}
+	return NOTIFY_DONE;
+}
+
+/*
+ * This function gets called when XOL instruction either gets trapped or
+ * the thread has a fatal signal, so reset the instruction pointer to its
+ * probed address.
+ */
+void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
+{
+	struct uprobe_task *utask = current->utask;
+
+	current->thread.trap_nr = utask->autask.saved_trap_nr;
+	instruction_pointer_set(regs, utask->vaddr);
+}
+
+/*
+ * See if the instruction can be emulated.
+ * Returns true if instruction was emulated, false otherwise.
+ */
+bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs)
+{
+	int ret;
+
+	/*
+	 * emulate_step() returns 1 if the insn was successfully emulated.
+	 * For all other cases, we need to single-step in hardware.
+	 */
+	ret = emulate_step(regs, auprobe->ainsn);
+	if (ret > 0)
+		return true;
+
+	return false;
+}
diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c
index b67db22..1b2076f 100644
--- a/arch/powerpc/kernel/vdso.c
+++ b/arch/powerpc/kernel/vdso.c
@@ -723,9 +723,7 @@ int __cpuinit vdso_getcpu_init(void)
 
 	val = (cpu & 0xfff) | ((node & 0xffff) << 16);
 	mtspr(SPRN_SPRG3, val);
-#ifdef CONFIG_KVM_BOOK3S_HANDLER
-	get_paca()->kvm_hstate.sprg3 = val;
-#endif
+	get_paca()->sprg3 = val;
 
 	put_cpu();
 
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c
index 02b3221..201ba59 100644
--- a/arch/powerpc/kernel/vio.c
+++ b/arch/powerpc/kernel/vio.c
@@ -33,7 +33,6 @@
 #include <asm/prom.h>
 #include <asm/firmware.h>
 #include <asm/tce.h>
-#include <asm/abs_addr.h>
 #include <asm/page.h>
 #include <asm/hvcall.h>
 
diff --git a/arch/powerpc/kvm/44x.c b/arch/powerpc/kvm/44x.c
index 50e7dbc..3d7fd21 100644
--- a/arch/powerpc/kvm/44x.c
+++ b/arch/powerpc/kvm/44x.c
@@ -83,6 +83,7 @@ int kvmppc_core_vcpu_setup(struct kvm_vcpu *vcpu)
 		vcpu_44x->shadow_refs[i].gtlb_index = -1;
 
 	vcpu->arch.cpu_type = KVM_CPU_440;
+	vcpu->arch.pvr = mfspr(SPRN_PVR);
 
 	return 0;
 }
diff --git a/arch/powerpc/kvm/44x_emulate.c b/arch/powerpc/kvm/44x_emulate.c
index c8c6157..1a793c4 100644
--- a/arch/powerpc/kvm/44x_emulate.c
+++ b/arch/powerpc/kvm/44x_emulate.c
@@ -27,12 +27,68 @@
 #include "booke.h"
 #include "44x_tlb.h"
 
+#define XOP_MFDCRX  259
 #define XOP_MFDCR   323
+#define XOP_MTDCRX  387
 #define XOP_MTDCR   451
 #define XOP_TLBSX   914
 #define XOP_ICCCI   966
 #define XOP_TLBWE   978
 
+static int emulate_mtdcr(struct kvm_vcpu *vcpu, int rs, int dcrn)
+{
+	/* emulate some access in kernel */
+	switch (dcrn) {
+	case DCRN_CPR0_CONFIG_ADDR:
+		vcpu->arch.cpr0_cfgaddr = kvmppc_get_gpr(vcpu, rs);
+		return EMULATE_DONE;
+	default:
+		vcpu->run->dcr.dcrn = dcrn;
+		vcpu->run->dcr.data = kvmppc_get_gpr(vcpu, rs);
+		vcpu->run->dcr.is_write = 1;
+		vcpu->arch.dcr_needed = 1;
+		kvmppc_account_exit(vcpu, DCR_EXITS);
+		return EMULATE_DO_DCR;
+	}
+}
+
+static int emulate_mfdcr(struct kvm_vcpu *vcpu, int rt, int dcrn)
+{
+	/* The guest may access CPR0 registers to determine the timebase
+	 * frequency, and it must know the real host frequency because it
+	 * can directly access the timebase registers.
+	 *
+	 * It would be possible to emulate those accesses in userspace,
+	 * but userspace can really only figure out the end frequency.
+	 * We could decompose that into the factors that compute it, but
+	 * that's tricky math, and it's easier to just report the real
+	 * CPR0 values.
+	 */
+	switch (dcrn) {
+	case DCRN_CPR0_CONFIG_ADDR:
+		kvmppc_set_gpr(vcpu, rt, vcpu->arch.cpr0_cfgaddr);
+		break;
+	case DCRN_CPR0_CONFIG_DATA:
+		local_irq_disable();
+		mtdcr(DCRN_CPR0_CONFIG_ADDR,
+			  vcpu->arch.cpr0_cfgaddr);
+		kvmppc_set_gpr(vcpu, rt,
+			       mfdcr(DCRN_CPR0_CONFIG_DATA));
+		local_irq_enable();
+		break;
+	default:
+		vcpu->run->dcr.dcrn = dcrn;
+		vcpu->run->dcr.data =  0;
+		vcpu->run->dcr.is_write = 0;
+		vcpu->arch.io_gpr = rt;
+		vcpu->arch.dcr_needed = 1;
+		kvmppc_account_exit(vcpu, DCR_EXITS);
+		return EMULATE_DO_DCR;
+	}
+
+	return EMULATE_DONE;
+}
+
 int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
                            unsigned int inst, int *advance)
 {
@@ -50,55 +106,21 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
 		switch (get_xop(inst)) {
 
 		case XOP_MFDCR:
-			/* The guest may access CPR0 registers to determine the timebase
-			 * frequency, and it must know the real host frequency because it
-			 * can directly access the timebase registers.
-			 *
-			 * It would be possible to emulate those accesses in userspace,
-			 * but userspace can really only figure out the end frequency.
-			 * We could decompose that into the factors that compute it, but
-			 * that's tricky math, and it's easier to just report the real
-			 * CPR0 values.
-			 */
-			switch (dcrn) {
-			case DCRN_CPR0_CONFIG_ADDR:
-				kvmppc_set_gpr(vcpu, rt, vcpu->arch.cpr0_cfgaddr);
-				break;
-			case DCRN_CPR0_CONFIG_DATA:
-				local_irq_disable();
-				mtdcr(DCRN_CPR0_CONFIG_ADDR,
-					  vcpu->arch.cpr0_cfgaddr);
-				kvmppc_set_gpr(vcpu, rt,
-					       mfdcr(DCRN_CPR0_CONFIG_DATA));
-				local_irq_enable();
-				break;
-			default:
-				run->dcr.dcrn = dcrn;
-				run->dcr.data =  0;
-				run->dcr.is_write = 0;
-				vcpu->arch.io_gpr = rt;
-				vcpu->arch.dcr_needed = 1;
-				kvmppc_account_exit(vcpu, DCR_EXITS);
-				emulated = EMULATE_DO_DCR;
-			}
+			emulated = emulate_mfdcr(vcpu, rt, dcrn);
+			break;
 
+		case XOP_MFDCRX:
+			emulated = emulate_mfdcr(vcpu, rt,
+					kvmppc_get_gpr(vcpu, ra));
 			break;
 
 		case XOP_MTDCR:
-			/* emulate some access in kernel */
-			switch (dcrn) {
-			case DCRN_CPR0_CONFIG_ADDR:
-				vcpu->arch.cpr0_cfgaddr = kvmppc_get_gpr(vcpu, rs);
-				break;
-			default:
-				run->dcr.dcrn = dcrn;
-				run->dcr.data = kvmppc_get_gpr(vcpu, rs);
-				run->dcr.is_write = 1;
-				vcpu->arch.dcr_needed = 1;
-				kvmppc_account_exit(vcpu, DCR_EXITS);
-				emulated = EMULATE_DO_DCR;
-			}
+			emulated = emulate_mtdcr(vcpu, rs, dcrn);
+			break;
 
+		case XOP_MTDCRX:
+			emulated = emulate_mtdcr(vcpu, rs,
+					kvmppc_get_gpr(vcpu, ra));
 			break;
 
 		case XOP_TLBWE:
diff --git a/arch/powerpc/kvm/44x_tlb.c b/arch/powerpc/kvm/44x_tlb.c
index 33aa715..5dd3ab4 100644
--- a/arch/powerpc/kvm/44x_tlb.c
+++ b/arch/powerpc/kvm/44x_tlb.c
@@ -319,7 +319,6 @@ void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 gvaddr, gpa_t gpaddr,
 	if (is_error_page(new_page)) {
 		printk(KERN_ERR "Couldn't get guest page for gfn %llx!\n",
 			(unsigned long long)gfn);
-		kvm_release_page_clean(new_page);
 		return;
 	}
 	hpaddr = page_to_phys(new_page);
diff --git a/arch/powerpc/kvm/Kconfig b/arch/powerpc/kvm/Kconfig
index f4dacb9..71f0cd9 100644
--- a/arch/powerpc/kvm/Kconfig
+++ b/arch/powerpc/kvm/Kconfig
@@ -36,6 +36,7 @@ config KVM_BOOK3S_64_HANDLER
 config KVM_BOOK3S_PR
 	bool
 	select KVM_MMIO
+	select MMU_NOTIFIER
 
 config KVM_BOOK3S_32
 	tristate "KVM support for PowerPC book3s_32 processors"
@@ -123,6 +124,7 @@ config KVM_E500V2
 	depends on EXPERIMENTAL && E500 && !PPC_E500MC
 	select KVM
 	select KVM_MMIO
+	select MMU_NOTIFIER
 	---help---
 	  Support running unmodified E500 guest kernels in virtual machines on
 	  E500v2 host processors.
@@ -138,6 +140,7 @@ config KVM_E500MC
 	select KVM
 	select KVM_MMIO
 	select KVM_BOOKE_HV
+	select MMU_NOTIFIER
 	---help---
 	  Support running unmodified E500MC/E5500 (32-bit) guest kernels in
 	  virtual machines on E500MC/E5500 host processors.
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
index 3f2a836..e946665 100644
--- a/arch/powerpc/kvm/book3s.c
+++ b/arch/powerpc/kvm/book3s.c
@@ -411,6 +411,15 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
 	return 0;
 }
 
+int kvmppc_subarch_vcpu_init(struct kvm_vcpu *vcpu)
+{
+	return 0;
+}
+
+void kvmppc_subarch_vcpu_uninit(struct kvm_vcpu *vcpu)
+{
+}
+
 int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
 {
 	int i;
diff --git a/arch/powerpc/kvm/book3s_32_mmu_host.c b/arch/powerpc/kvm/book3s_32_mmu_host.c
index 837f13e..f92d3ff 100644
--- a/arch/powerpc/kvm/book3s_32_mmu_host.c
+++ b/arch/powerpc/kvm/book3s_32_mmu_host.c
@@ -141,7 +141,7 @@ extern char etext[];
 int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte)
 {
 	pfn_t hpaddr;
-	u64 va;
+	u64 vpn;
 	u64 vsid;
 	struct kvmppc_sid_map *map;
 	volatile u32 *pteg;
@@ -173,7 +173,7 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte)
 	BUG_ON(!map);
 
 	vsid = map->host_vsid;
-	va = (vsid << SID_SHIFT) | (eaddr & ~ESID_MASK);
+	vpn = (vsid << (SID_SHIFT - VPN_SHIFT)) | ((eaddr & ~ESID_MASK) >> VPN_SHIFT)
 
 next_pteg:
 	if (rr == 16) {
@@ -244,16 +244,17 @@ next_pteg:
 	dprintk_mmu("KVM: %c%c Map 0x%llx: [%lx] 0x%llx (0x%llx) -> %lx\n",
 		    orig_pte->may_write ? 'w' : '-',
 		    orig_pte->may_execute ? 'x' : '-',
-		    orig_pte->eaddr, (ulong)pteg, va,
+		    orig_pte->eaddr, (ulong)pteg, vpn,
 		    orig_pte->vpage, hpaddr);
 
 	pte->slot = (ulong)&pteg[rr];
-	pte->host_va = va;
+	pte->host_vpn = vpn;
 	pte->pte = *orig_pte;
 	pte->pfn = hpaddr >> PAGE_SHIFT;
 
 	kvmppc_mmu_hpte_cache_map(vcpu, pte);
 
+	kvm_release_pfn_clean(hpaddr >> PAGE_SHIFT);
 out:
 	return r;
 }
diff --git a/arch/powerpc/kvm/book3s_64_mmu_host.c b/arch/powerpc/kvm/book3s_64_mmu_host.c
index 0688b6b..d0205a5 100644
--- a/arch/powerpc/kvm/book3s_64_mmu_host.c
+++ b/arch/powerpc/kvm/book3s_64_mmu_host.c
@@ -33,7 +33,7 @@
 
 void kvmppc_mmu_invalidate_pte(struct kvm_vcpu *vcpu, struct hpte_cache *pte)
 {
-	ppc_md.hpte_invalidate(pte->slot, pte->host_va,
+	ppc_md.hpte_invalidate(pte->slot, pte->host_vpn,
 			       MMU_PAGE_4K, MMU_SEGSIZE_256M,
 			       false);
 }
@@ -80,8 +80,9 @@ static struct kvmppc_sid_map *find_sid_vsid(struct kvm_vcpu *vcpu, u64 gvsid)
 
 int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte)
 {
+	unsigned long vpn;
 	pfn_t hpaddr;
-	ulong hash, hpteg, va;
+	ulong hash, hpteg;
 	u64 vsid;
 	int ret;
 	int rflags = 0x192;
@@ -117,7 +118,7 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte)
 	}
 
 	vsid = map->host_vsid;
-	va = hpt_va(orig_pte->eaddr, vsid, MMU_SEGSIZE_256M);
+	vpn = hpt_vpn(orig_pte->eaddr, vsid, MMU_SEGSIZE_256M);
 
 	if (!orig_pte->may_write)
 		rflags |= HPTE_R_PP;
@@ -129,7 +130,7 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte)
 	else
 		kvmppc_mmu_flush_icache(hpaddr >> PAGE_SHIFT);
 
-	hash = hpt_hash(va, PTE_SIZE, MMU_SEGSIZE_256M);
+	hash = hpt_hash(vpn, PTE_SIZE, MMU_SEGSIZE_256M);
 
 map_again:
 	hpteg = ((hash & htab_hash_mask) * HPTES_PER_GROUP);
@@ -141,7 +142,8 @@ map_again:
 			goto out;
 		}
 
-	ret = ppc_md.hpte_insert(hpteg, va, hpaddr, rflags, vflags, MMU_PAGE_4K, MMU_SEGSIZE_256M);
+	ret = ppc_md.hpte_insert(hpteg, vpn, hpaddr, rflags, vflags,
+				 MMU_PAGE_4K, MMU_SEGSIZE_256M);
 
 	if (ret < 0) {
 		/* If we couldn't map a primary PTE, try a secondary */
@@ -152,7 +154,8 @@ map_again:
 	} else {
 		struct hpte_cache *pte = kvmppc_mmu_hpte_cache_next(vcpu);
 
-		trace_kvm_book3s_64_mmu_map(rflags, hpteg, va, hpaddr, orig_pte);
+		trace_kvm_book3s_64_mmu_map(rflags, hpteg,
+					    vpn, hpaddr, orig_pte);
 
 		/* The ppc_md code may give us a secondary entry even though we
 		   asked for a primary. Fix up. */
@@ -162,12 +165,13 @@ map_again:
 		}
 
 		pte->slot = hpteg + (ret & 7);
-		pte->host_va = va;
+		pte->host_vpn = vpn;
 		pte->pte = *orig_pte;
 		pte->pfn = hpaddr >> PAGE_SHIFT;
 
 		kvmppc_mmu_hpte_cache_map(vcpu, pte);
 	}
+	kvm_release_pfn_clean(hpaddr >> PAGE_SHIFT);
 
 out:
 	return r;
diff --git a/arch/powerpc/kvm/book3s_64_mmu_hv.c b/arch/powerpc/kvm/book3s_64_mmu_hv.c
index d03eb6f..7a4aae9 100644
--- a/arch/powerpc/kvm/book3s_64_mmu_hv.c
+++ b/arch/powerpc/kvm/book3s_64_mmu_hv.c
@@ -24,6 +24,7 @@
 #include <linux/slab.h>
 #include <linux/hugetlb.h>
 #include <linux/vmalloc.h>
+#include <linux/srcu.h>
 
 #include <asm/tlbflush.h>
 #include <asm/kvm_ppc.h>
@@ -260,7 +261,7 @@ static void kvmppc_mmu_book3s_64_hv_reset_msr(struct kvm_vcpu *vcpu)
 
 /*
  * This is called to get a reference to a guest page if there isn't
- * one already in the kvm->arch.slot_phys[][] arrays.
+ * one already in the memslot->arch.slot_phys[] array.
  */
 static long kvmppc_get_guest_page(struct kvm *kvm, unsigned long gfn,
 				  struct kvm_memory_slot *memslot,
@@ -275,7 +276,7 @@ static long kvmppc_get_guest_page(struct kvm *kvm, unsigned long gfn,
 	struct vm_area_struct *vma;
 	unsigned long pfn, i, npages;
 
-	physp = kvm->arch.slot_phys[memslot->id];
+	physp = memslot->arch.slot_phys;
 	if (!physp)
 		return -EINVAL;
 	if (physp[gfn - memslot->base_gfn])
@@ -570,7 +571,7 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
 	struct kvm *kvm = vcpu->kvm;
 	unsigned long *hptep, hpte[3], r;
 	unsigned long mmu_seq, psize, pte_size;
-	unsigned long gfn, hva, pfn;
+	unsigned long gpa, gfn, hva, pfn;
 	struct kvm_memory_slot *memslot;
 	unsigned long *rmap;
 	struct revmap_entry *rev;
@@ -608,15 +609,14 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
 
 	/* Translate the logical address and get the page */
 	psize = hpte_page_size(hpte[0], r);
-	gfn = hpte_rpn(r, psize);
+	gpa = (r & HPTE_R_RPN & ~(psize - 1)) | (ea & (psize - 1));
+	gfn = gpa >> PAGE_SHIFT;
 	memslot = gfn_to_memslot(kvm, gfn);
 
 	/* No memslot means it's an emulated MMIO region */
-	if (!memslot || (memslot->flags & KVM_MEMSLOT_INVALID)) {
-		unsigned long gpa = (gfn << PAGE_SHIFT) | (ea & (psize - 1));
+	if (!memslot || (memslot->flags & KVM_MEMSLOT_INVALID))
 		return kvmppc_hv_emulate_mmio(run, vcpu, gpa, ea,
 					      dsisr & DSISR_ISSTORE);
-	}
 
 	if (!kvm->arch.using_mmu_notifiers)
 		return -EFAULT;		/* should never get here */
@@ -705,7 +705,7 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
 		goto out_unlock;
 	hpte[0] = (hpte[0] & ~HPTE_V_ABSENT) | HPTE_V_VALID;
 
-	rmap = &memslot->rmap[gfn - memslot->base_gfn];
+	rmap = &memslot->arch.rmap[gfn - memslot->base_gfn];
 	lock_rmap(rmap);
 
 	/* Check if we might have been invalidated; let the guest retry if so */
@@ -756,9 +756,12 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
 	goto out_put;
 }
 
-static int kvm_handle_hva(struct kvm *kvm, unsigned long hva,
-			  int (*handler)(struct kvm *kvm, unsigned long *rmapp,
-					 unsigned long gfn))
+static int kvm_handle_hva_range(struct kvm *kvm,
+				unsigned long start,
+				unsigned long end,
+				int (*handler)(struct kvm *kvm,
+					       unsigned long *rmapp,
+					       unsigned long gfn))
 {
 	int ret;
 	int retval = 0;
@@ -767,15 +770,25 @@ static int kvm_handle_hva(struct kvm *kvm, unsigned long hva,
 
 	slots = kvm_memslots(kvm);
 	kvm_for_each_memslot(memslot, slots) {
-		unsigned long start = memslot->userspace_addr;
-		unsigned long end;
+		unsigned long hva_start, hva_end;
+		gfn_t gfn, gfn_end;
 
-		end = start + (memslot->npages << PAGE_SHIFT);
-		if (hva >= start && hva < end) {
-			gfn_t gfn_offset = (hva - start) >> PAGE_SHIFT;
+		hva_start = max(start, memslot->userspace_addr);
+		hva_end = min(end, memslot->userspace_addr +
+					(memslot->npages << PAGE_SHIFT));
+		if (hva_start >= hva_end)
+			continue;
+		/*
+		 * {gfn(page) | page intersects with [hva_start, hva_end)} =
+		 * {gfn, gfn+1, ..., gfn_end-1}.
+		 */
+		gfn = hva_to_gfn_memslot(hva_start, memslot);
+		gfn_end = hva_to_gfn_memslot(hva_end + PAGE_SIZE - 1, memslot);
 
-			ret = handler(kvm, &memslot->rmap[gfn_offset],
-				      memslot->base_gfn + gfn_offset);
+		for (; gfn < gfn_end; ++gfn) {
+			gfn_t gfn_offset = gfn - memslot->base_gfn;
+
+			ret = handler(kvm, &memslot->arch.rmap[gfn_offset], gfn);
 			retval |= ret;
 		}
 	}
@@ -783,6 +796,13 @@ static int kvm_handle_hva(struct kvm *kvm, unsigned long hva,
 	return retval;
 }
 
+static int kvm_handle_hva(struct kvm *kvm, unsigned long hva,
+			  int (*handler)(struct kvm *kvm, unsigned long *rmapp,
+					 unsigned long gfn))
+{
+	return kvm_handle_hva_range(kvm, hva, hva + 1, handler);
+}
+
 static int kvm_unmap_rmapp(struct kvm *kvm, unsigned long *rmapp,
 			   unsigned long gfn)
 {
@@ -830,7 +850,8 @@ static int kvm_unmap_rmapp(struct kvm *kvm, unsigned long *rmapp,
 		psize = hpte_page_size(hptep[0], ptel);
 		if ((hptep[0] & HPTE_V_VALID) &&
 		    hpte_rpn(ptel, psize) == gfn) {
-			hptep[0] |= HPTE_V_ABSENT;
+			if (kvm->arch.using_mmu_notifiers)
+				hptep[0] |= HPTE_V_ABSENT;
 			kvmppc_invalidate_hpte(kvm, hptep, i);
 			/* Harvest R and C */
 			rcbits = hptep[1] & (HPTE_R_R | HPTE_R_C);
@@ -850,6 +871,35 @@ int kvm_unmap_hva(struct kvm *kvm, unsigned long hva)
 	return 0;
 }
 
+int kvm_unmap_hva_range(struct kvm *kvm, unsigned long start, unsigned long end)
+{
+	if (kvm->arch.using_mmu_notifiers)
+		kvm_handle_hva_range(kvm, start, end, kvm_unmap_rmapp);
+	return 0;
+}
+
+void kvmppc_core_flush_memslot(struct kvm *kvm, struct kvm_memory_slot *memslot)
+{
+	unsigned long *rmapp;
+	unsigned long gfn;
+	unsigned long n;
+
+	rmapp = memslot->arch.rmap;
+	gfn = memslot->base_gfn;
+	for (n = memslot->npages; n; --n) {
+		/*
+		 * Testing the present bit without locking is OK because
+		 * the memslot has been marked invalid already, and hence
+		 * no new HPTEs referencing this page can be created,
+		 * thus the present bit can't go from 0 to 1.
+		 */
+		if (*rmapp & KVMPPC_RMAP_PRESENT)
+			kvm_unmap_rmapp(kvm, rmapp, gfn);
+		++rmapp;
+		++gfn;
+	}
+}
+
 static int kvm_age_rmapp(struct kvm *kvm, unsigned long *rmapp,
 			 unsigned long gfn)
 {
@@ -1003,16 +1053,16 @@ static int kvm_test_clear_dirty(struct kvm *kvm, unsigned long *rmapp)
 	return ret;
 }
 
-long kvmppc_hv_get_dirty_log(struct kvm *kvm, struct kvm_memory_slot *memslot)
+long kvmppc_hv_get_dirty_log(struct kvm *kvm, struct kvm_memory_slot *memslot,
+			     unsigned long *map)
 {
 	unsigned long i;
-	unsigned long *rmapp, *map;
+	unsigned long *rmapp;
 
 	preempt_disable();
-	rmapp = memslot->rmap;
-	map = memslot->dirty_bitmap;
+	rmapp = memslot->arch.rmap;
 	for (i = 0; i < memslot->npages; ++i) {
-		if (kvm_test_clear_dirty(kvm, rmapp))
+		if (kvm_test_clear_dirty(kvm, rmapp) && map)
 			__set_bit_le(i, map);
 		++rmapp;
 	}
@@ -1030,20 +1080,22 @@ void *kvmppc_pin_guest_page(struct kvm *kvm, unsigned long gpa,
 	unsigned long hva, psize, offset;
 	unsigned long pa;
 	unsigned long *physp;
+	int srcu_idx;
 
+	srcu_idx = srcu_read_lock(&kvm->srcu);
 	memslot = gfn_to_memslot(kvm, gfn);
 	if (!memslot || (memslot->flags & KVM_MEMSLOT_INVALID))
-		return NULL;
+		goto err;
 	if (!kvm->arch.using_mmu_notifiers) {
-		physp = kvm->arch.slot_phys[memslot->id];
+		physp = memslot->arch.slot_phys;
 		if (!physp)
-			return NULL;
+			goto err;
 		physp += gfn - memslot->base_gfn;
 		pa = *physp;
 		if (!pa) {
 			if (kvmppc_get_guest_page(kvm, gfn, memslot,
 						  PAGE_SIZE) < 0)
-				return NULL;
+				goto err;
 			pa = *physp;
 		}
 		page = pfn_to_page(pa >> PAGE_SHIFT);
@@ -1052,9 +1104,11 @@ void *kvmppc_pin_guest_page(struct kvm *kvm, unsigned long gpa,
 		hva = gfn_to_hva_memslot(memslot, gfn);
 		npages = get_user_pages_fast(hva, 1, 1, pages);
 		if (npages < 1)
-			return NULL;
+			goto err;
 		page = pages[0];
 	}
+	srcu_read_unlock(&kvm->srcu, srcu_idx);
+
 	psize = PAGE_SIZE;
 	if (PageHuge(page)) {
 		page = compound_head(page);
@@ -1064,6 +1118,10 @@ void *kvmppc_pin_guest_page(struct kvm *kvm, unsigned long gpa,
 	if (nb_ret)
 		*nb_ret = psize - offset;
 	return page_address(page) + offset;
+
+ err:
+	srcu_read_unlock(&kvm->srcu, srcu_idx);
+	return NULL;
 }
 
 void kvmppc_unpin_guest_page(struct kvm *kvm, void *va)
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index 83e929e..9a151d1 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -30,6 +30,7 @@
 #include <linux/cpumask.h>
 #include <linux/spinlock.h>
 #include <linux/page-flags.h>
+#include <linux/srcu.h>
 
 #include <asm/reg.h>
 #include <asm/cputable.h>
@@ -366,13 +367,16 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu)
 	unsigned long req = kvmppc_get_gpr(vcpu, 3);
 	unsigned long target, ret = H_SUCCESS;
 	struct kvm_vcpu *tvcpu;
+	int idx;
 
 	switch (req) {
 	case H_ENTER:
+		idx = srcu_read_lock(&vcpu->kvm->srcu);
 		ret = kvmppc_virtmode_h_enter(vcpu, kvmppc_get_gpr(vcpu, 4),
 					      kvmppc_get_gpr(vcpu, 5),
 					      kvmppc_get_gpr(vcpu, 6),
 					      kvmppc_get_gpr(vcpu, 7));
+		srcu_read_unlock(&vcpu->kvm->srcu, idx);
 		break;
 	case H_CEDE:
 		break;
@@ -411,6 +415,7 @@ static int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
 			      struct task_struct *tsk)
 {
 	int r = RESUME_HOST;
+	int srcu_idx;
 
 	vcpu->stat.sum_exits++;
 
@@ -470,12 +475,16 @@ static int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
 	 * have been handled already.
 	 */
 	case BOOK3S_INTERRUPT_H_DATA_STORAGE:
+		srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
 		r = kvmppc_book3s_hv_page_fault(run, vcpu,
 				vcpu->arch.fault_dar, vcpu->arch.fault_dsisr);
+		srcu_read_unlock(&vcpu->kvm->srcu, srcu_idx);
 		break;
 	case BOOK3S_INTERRUPT_H_INST_STORAGE:
+		srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
 		r = kvmppc_book3s_hv_page_fault(run, vcpu,
 				kvmppc_get_pc(vcpu), 0);
+		srcu_read_unlock(&vcpu->kvm->srcu, srcu_idx);
 		break;
 	/*
 	 * This occurs if the guest executes an illegal instruction.
@@ -697,17 +706,11 @@ extern void xics_wake_cpu(int cpu);
 static void kvmppc_remove_runnable(struct kvmppc_vcore *vc,
 				   struct kvm_vcpu *vcpu)
 {
-	struct kvm_vcpu *v;
-
 	if (vcpu->arch.state != KVMPPC_VCPU_RUNNABLE)
 		return;
 	vcpu->arch.state = KVMPPC_VCPU_BUSY_IN_HOST;
 	--vc->n_runnable;
 	++vc->n_busy;
-	/* decrement the physical thread id of each following vcpu */
-	v = vcpu;
-	list_for_each_entry_continue(v, &vc->runnable_threads, arch.run_list)
-		--v->arch.ptid;
 	list_del(&vcpu->arch.run_list);
 }
 
@@ -820,6 +823,7 @@ static int kvmppc_run_core(struct kvmppc_vcore *vc)
 	long ret;
 	u64 now;
 	int ptid, i, need_vpa_update;
+	int srcu_idx;
 
 	/* don't start if any threads have a signal pending */
 	need_vpa_update = 0;
@@ -898,6 +902,9 @@ static int kvmppc_run_core(struct kvmppc_vcore *vc)
 	spin_unlock(&vc->lock);
 
 	kvm_guest_enter();
+
+	srcu_idx = srcu_read_lock(&vcpu0->kvm->srcu);
+
 	__kvmppc_vcore_entry(NULL, vcpu0);
 	for (i = 0; i < threads_per_core; ++i)
 		kvmppc_release_hwthread(vc->pcpu + i);
@@ -913,6 +920,8 @@ static int kvmppc_run_core(struct kvmppc_vcore *vc)
 	vc->vcore_state = VCORE_EXITING;
 	spin_unlock(&vc->lock);
 
+	srcu_read_unlock(&vcpu0->kvm->srcu, srcu_idx);
+
 	/* make sure updates to secondary vcpu structs are visible now */
 	smp_mb();
 	kvm_guest_exit();
@@ -1183,7 +1192,7 @@ static const struct vm_operations_struct kvm_rma_vm_ops = {
 
 static int kvm_rma_mmap(struct file *file, struct vm_area_struct *vma)
 {
-	vma->vm_flags |= VM_RESERVED;
+	vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
 	vma->vm_ops = &kvm_rma_vm_ops;
 	return 0;
 }
@@ -1273,7 +1282,7 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, struct kvm_dirty_log *log)
 	n = kvm_dirty_bitmap_bytes(memslot);
 	memset(memslot->dirty_bitmap, 0, n);
 
-	r = kvmppc_hv_get_dirty_log(kvm, memslot);
+	r = kvmppc_hv_get_dirty_log(kvm, memslot, memslot->dirty_bitmap);
 	if (r)
 		goto out;
 
@@ -1299,53 +1308,86 @@ static unsigned long slb_pgsize_encoding(unsigned long psize)
 	return senc;
 }
 
-int kvmppc_core_prepare_memory_region(struct kvm *kvm,
-				struct kvm_userspace_memory_region *mem)
+static void unpin_slot(struct kvm_memory_slot *memslot)
 {
-	unsigned long npages;
-	unsigned long *phys;
+	unsigned long *physp;
+	unsigned long j, npages, pfn;
+	struct page *page;
 
-	/* Allocate a slot_phys array */
-	phys = kvm->arch.slot_phys[mem->slot];
-	if (!kvm->arch.using_mmu_notifiers && !phys) {
-		npages = mem->memory_size >> PAGE_SHIFT;
-		phys = vzalloc(npages * sizeof(unsigned long));
-		if (!phys)
-			return -ENOMEM;
-		kvm->arch.slot_phys[mem->slot] = phys;
-		kvm->arch.slot_npages[mem->slot] = npages;
+	physp = memslot->arch.slot_phys;
+	npages = memslot->npages;
+	if (!physp)
+		return;
+	for (j = 0; j < npages; j++) {
+		if (!(physp[j] & KVMPPC_GOT_PAGE))
+			continue;
+		pfn = physp[j] >> PAGE_SHIFT;
+		page = pfn_to_page(pfn);
+		SetPageDirty(page);
+		put_page(page);
+	}
+}
+
+void kvmppc_core_free_memslot(struct kvm_memory_slot *free,
+			      struct kvm_memory_slot *dont)
+{
+	if (!dont || free->arch.rmap != dont->arch.rmap) {
+		vfree(free->arch.rmap);
+		free->arch.rmap = NULL;
 	}
+	if (!dont || free->arch.slot_phys != dont->arch.slot_phys) {
+		unpin_slot(free);
+		vfree(free->arch.slot_phys);
+		free->arch.slot_phys = NULL;
+	}
+}
+
+int kvmppc_core_create_memslot(struct kvm_memory_slot *slot,
+			       unsigned long npages)
+{
+	slot->arch.rmap = vzalloc(npages * sizeof(*slot->arch.rmap));
+	if (!slot->arch.rmap)
+		return -ENOMEM;
+	slot->arch.slot_phys = NULL;
 
 	return 0;
 }
 
-static void unpin_slot(struct kvm *kvm, int slot_id)
+int kvmppc_core_prepare_memory_region(struct kvm *kvm,
+				      struct kvm_memory_slot *memslot,
+				      struct kvm_userspace_memory_region *mem)
 {
-	unsigned long *physp;
-	unsigned long j, npages, pfn;
-	struct page *page;
+	unsigned long *phys;
 
-	physp = kvm->arch.slot_phys[slot_id];
-	npages = kvm->arch.slot_npages[slot_id];
-	if (physp) {
-		spin_lock(&kvm->arch.slot_phys_lock);
-		for (j = 0; j < npages; j++) {
-			if (!(physp[j] & KVMPPC_GOT_PAGE))
-				continue;
-			pfn = physp[j] >> PAGE_SHIFT;
-			page = pfn_to_page(pfn);
-			SetPageDirty(page);
-			put_page(page);
-		}
-		kvm->arch.slot_phys[slot_id] = NULL;
-		spin_unlock(&kvm->arch.slot_phys_lock);
-		vfree(physp);
+	/* Allocate a slot_phys array if needed */
+	phys = memslot->arch.slot_phys;
+	if (!kvm->arch.using_mmu_notifiers && !phys && memslot->npages) {
+		phys = vzalloc(memslot->npages * sizeof(unsigned long));
+		if (!phys)
+			return -ENOMEM;
+		memslot->arch.slot_phys = phys;
 	}
+
+	return 0;
 }
 
 void kvmppc_core_commit_memory_region(struct kvm *kvm,
-				struct kvm_userspace_memory_region *mem)
+				      struct kvm_userspace_memory_region *mem,
+				      struct kvm_memory_slot old)
 {
+	unsigned long npages = mem->memory_size >> PAGE_SHIFT;
+	struct kvm_memory_slot *memslot;
+
+	if (npages && old.npages) {
+		/*
+		 * If modifying a memslot, reset all the rmap dirty bits.
+		 * If this is a new memslot, we don't need to do anything
+		 * since the rmap array starts out as all zeroes,
+		 * i.e. no pages are dirty.
+		 */
+		memslot = id_to_memslot(kvm->memslots, mem->slot);
+		kvmppc_hv_get_dirty_log(kvm, memslot, NULL);
+	}
 }
 
 static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu)
@@ -1362,6 +1404,7 @@ static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu)
 	unsigned long rmls;
 	unsigned long *physp;
 	unsigned long i, npages;
+	int srcu_idx;
 
 	mutex_lock(&kvm->lock);
 	if (kvm->arch.rma_setup_done)
@@ -1377,12 +1420,13 @@ static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu)
 	}
 
 	/* Look up the memslot for guest physical address 0 */
+	srcu_idx = srcu_read_lock(&kvm->srcu);
 	memslot = gfn_to_memslot(kvm, 0);
 
 	/* We must have some memory at 0 by now */
 	err = -EINVAL;
 	if (!memslot || (memslot->flags & KVM_MEMSLOT_INVALID))
-		goto out;
+		goto out_srcu;
 
 	/* Look up the VMA for the start of this memory slot */
 	hva = memslot->userspace_addr;
@@ -1406,14 +1450,14 @@ static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu)
 		err = -EPERM;
 		if (cpu_has_feature(CPU_FTR_ARCH_201)) {
 			pr_err("KVM: CPU requires an RMO\n");
-			goto out;
+			goto out_srcu;
 		}
 
 		/* We can handle 4k, 64k or 16M pages in the VRMA */
 		err = -EINVAL;
 		if (!(psize == 0x1000 || psize == 0x10000 ||
 		      psize == 0x1000000))
-			goto out;
+			goto out_srcu;
 
 		/* Update VRMASD field in the LPCR */
 		senc = slb_pgsize_encoding(psize);
@@ -1436,7 +1480,7 @@ static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu)
 		err = -EINVAL;
 		if (rmls < 0) {
 			pr_err("KVM: Can't use RMA of 0x%lx bytes\n", rma_size);
-			goto out;
+			goto out_srcu;
 		}
 		atomic_inc(&ri->use_count);
 		kvm->arch.rma = ri;
@@ -1465,17 +1509,24 @@ static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu)
 		/* Initialize phys addrs of pages in RMO */
 		npages = ri->npages;
 		porder = __ilog2(npages);
-		physp = kvm->arch.slot_phys[memslot->id];
-		spin_lock(&kvm->arch.slot_phys_lock);
-		for (i = 0; i < npages; ++i)
-			physp[i] = ((ri->base_pfn + i) << PAGE_SHIFT) + porder;
-		spin_unlock(&kvm->arch.slot_phys_lock);
+		physp = memslot->arch.slot_phys;
+		if (physp) {
+			if (npages > memslot->npages)
+				npages = memslot->npages;
+			spin_lock(&kvm->arch.slot_phys_lock);
+			for (i = 0; i < npages; ++i)
+				physp[i] = ((ri->base_pfn + i) << PAGE_SHIFT) +
+					porder;
+			spin_unlock(&kvm->arch.slot_phys_lock);
+		}
 	}
 
 	/* Order updates to kvm->arch.lpcr etc. vs. rma_setup_done */
 	smp_wmb();
 	kvm->arch.rma_setup_done = 1;
 	err = 0;
+ out_srcu:
+	srcu_read_unlock(&kvm->srcu, srcu_idx);
  out:
 	mutex_unlock(&kvm->lock);
 	return err;
@@ -1528,12 +1579,6 @@ int kvmppc_core_init_vm(struct kvm *kvm)
 
 void kvmppc_core_destroy_vm(struct kvm *kvm)
 {
-	unsigned long i;
-
-	if (!kvm->arch.using_mmu_notifiers)
-		for (i = 0; i < KVM_MEM_SLOTS_NUM; i++)
-			unpin_slot(kvm, i);
-
 	if (kvm->arch.rma) {
 		kvm_release_rma(kvm->arch.rma);
 		kvm->arch.rma = NULL;
diff --git a/arch/powerpc/kvm/book3s_hv_builtin.c b/arch/powerpc/kvm/book3s_hv_builtin.c
index fb4eac2..ec0a9e5 100644
--- a/arch/powerpc/kvm/book3s_hv_builtin.c
+++ b/arch/powerpc/kvm/book3s_hv_builtin.c
@@ -157,8 +157,8 @@ static void __init kvm_linear_init_one(ulong size, int count, int type)
 	linear_info = alloc_bootmem(count * sizeof(struct kvmppc_linear_info));
 	for (i = 0; i < count; ++i) {
 		linear = alloc_bootmem_align(size, size);
-		pr_info("Allocated KVM %s at %p (%ld MB)\n", typestr, linear,
-			size >> 20);
+		pr_debug("Allocated KVM %s at %p (%ld MB)\n", typestr, linear,
+			 size >> 20);
 		linear_info[i].base_virt = linear;
 		linear_info[i].base_pfn = __pa(linear) >> PAGE_SHIFT;
 		linear_info[i].npages = npages;
diff --git a/arch/powerpc/kvm/book3s_hv_rm_mmu.c b/arch/powerpc/kvm/book3s_hv_rm_mmu.c
index 5c70d19..9955216 100644
--- a/arch/powerpc/kvm/book3s_hv_rm_mmu.c
+++ b/arch/powerpc/kvm/book3s_hv_rm_mmu.c
@@ -81,10 +81,10 @@ static void remove_revmap_chain(struct kvm *kvm, long pte_index,
 	ptel = rev->guest_rpte |= rcbits;
 	gfn = hpte_rpn(ptel, hpte_page_size(hpte_v, ptel));
 	memslot = __gfn_to_memslot(kvm_memslots(kvm), gfn);
-	if (!memslot || (memslot->flags & KVM_MEMSLOT_INVALID))
+	if (!memslot)
 		return;
 
-	rmap = real_vmalloc_addr(&memslot->rmap[gfn - memslot->base_gfn]);
+	rmap = real_vmalloc_addr(&memslot->arch.rmap[gfn - memslot->base_gfn]);
 	lock_rmap(rmap);
 
 	head = *rmap & KVMPPC_RMAP_INDEX;
@@ -180,10 +180,10 @@ long kvmppc_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
 	if (!slot_is_aligned(memslot, psize))
 		return H_PARAMETER;
 	slot_fn = gfn - memslot->base_gfn;
-	rmap = &memslot->rmap[slot_fn];
+	rmap = &memslot->arch.rmap[slot_fn];
 
 	if (!kvm->arch.using_mmu_notifiers) {
-		physp = kvm->arch.slot_phys[memslot->id];
+		physp = memslot->arch.slot_phys;
 		if (!physp)
 			return H_PARAMETER;
 		physp += slot_fn;
@@ -197,7 +197,7 @@ long kvmppc_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
 		pa &= PAGE_MASK;
 	} else {
 		/* Translate to host virtual address */
-		hva = gfn_to_hva_memslot(memslot, gfn);
+		hva = __gfn_to_hva_memslot(memslot, gfn);
 
 		/* Look up the Linux PTE for the backing page */
 		pte_size = psize;
diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
index 44b72fe..74a24bb 100644
--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
@@ -1065,7 +1065,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
 	mtspr	SPRN_DABRX,r6
 
 	/* Restore SPRG3 */
-	ld	r3,HSTATE_SPRG3(r13)
+	ld	r3,PACA_SPRG3(r13)
 	mtspr	SPRN_SPRG3,r3
 
 	/*
diff --git a/arch/powerpc/kvm/book3s_mmu_hpte.c b/arch/powerpc/kvm/book3s_mmu_hpte.c
index 41cb001..2c86b0d 100644
--- a/arch/powerpc/kvm/book3s_mmu_hpte.c
+++ b/arch/powerpc/kvm/book3s_mmu_hpte.c
@@ -114,11 +114,6 @@ static void invalidate_pte(struct kvm_vcpu *vcpu, struct hpte_cache *pte)
 	hlist_del_init_rcu(&pte->list_vpte);
 	hlist_del_init_rcu(&pte->list_vpte_long);
 
-	if (pte->pte.may_write)
-		kvm_release_pfn_dirty(pte->pfn);
-	else
-		kvm_release_pfn_clean(pte->pfn);
-
 	spin_unlock(&vcpu3s->mmu_lock);
 
 	vcpu3s->hpte_cache_count--;
diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c
index a1baec3..bf3ec5d 100644
--- a/arch/powerpc/kvm/book3s_pr.c
+++ b/arch/powerpc/kvm/book3s_pr.c
@@ -52,8 +52,6 @@ static int kvmppc_handle_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr,
 #define MSR_USER32 MSR_USER
 #define MSR_USER64 MSR_USER
 #define HW_PAGE_SIZE PAGE_SIZE
-#define __hard_irq_disable local_irq_disable
-#define __hard_irq_enable local_irq_enable
 #endif
 
 void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
@@ -66,7 +64,7 @@ void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
 	svcpu->slb_max = to_book3s(vcpu)->slb_shadow_max;
 	svcpu_put(svcpu);
 #endif
-
+	vcpu->cpu = smp_processor_id();
 #ifdef CONFIG_PPC_BOOK3S_32
 	current->thread.kvm_shadow_vcpu = to_book3s(vcpu)->shadow_vcpu;
 #endif
@@ -86,8 +84,64 @@ void kvmppc_core_vcpu_put(struct kvm_vcpu *vcpu)
 	kvmppc_giveup_ext(vcpu, MSR_FP);
 	kvmppc_giveup_ext(vcpu, MSR_VEC);
 	kvmppc_giveup_ext(vcpu, MSR_VSX);
+	vcpu->cpu = -1;
+}
+
+int kvmppc_core_check_requests(struct kvm_vcpu *vcpu)
+{
+	int r = 1; /* Indicate we want to get back into the guest */
+
+	/* We misuse TLB_FLUSH to indicate that we want to clear
+	   all shadow cache entries */
+	if (kvm_check_request(KVM_REQ_TLB_FLUSH, vcpu))
+		kvmppc_mmu_pte_flush(vcpu, 0, 0);
+
+	return r;
+}
+
+/************* MMU Notifiers *************/
+
+int kvm_unmap_hva(struct kvm *kvm, unsigned long hva)
+{
+	trace_kvm_unmap_hva(hva);
+
+	/*
+	 * Flush all shadow tlb entries everywhere. This is slow, but
+	 * we are 100% sure that we catch the to be unmapped page
+	 */
+	kvm_flush_remote_tlbs(kvm);
+
+	return 0;
+}
+
+int kvm_unmap_hva_range(struct kvm *kvm, unsigned long start, unsigned long end)
+{
+	/* kvm_unmap_hva flushes everything anyways */
+	kvm_unmap_hva(kvm, start);
+
+	return 0;
+}
+
+int kvm_age_hva(struct kvm *kvm, unsigned long hva)
+{
+	/* XXX could be more clever ;) */
+	return 0;
+}
+
+int kvm_test_age_hva(struct kvm *kvm, unsigned long hva)
+{
+	/* XXX could be more clever ;) */
+	return 0;
 }
 
+void kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte)
+{
+	/* The page will get remapped properly on its next fault */
+	kvm_unmap_hva(kvm, hva);
+}
+
+/*****************************************/
+
 static void kvmppc_recalc_shadow_msr(struct kvm_vcpu *vcpu)
 {
 	ulong smsr = vcpu->arch.shared->msr;
@@ -242,10 +296,8 @@ static void kvmppc_patch_dcbz(struct kvm_vcpu *vcpu, struct kvmppc_pte *pte)
 	int i;
 
 	hpage = gfn_to_page(vcpu->kvm, pte->raddr >> PAGE_SHIFT);
-	if (is_error_page(hpage)) {
-		kvm_release_page_clean(hpage);
+	if (is_error_page(hpage))
 		return;
-	}
 
 	hpage_offset = pte->raddr & ~PAGE_MASK;
 	hpage_offset &= ~0xFFFULL;
@@ -542,18 +594,18 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
                        unsigned int exit_nr)
 {
 	int r = RESUME_HOST;
+	int s;
 
 	vcpu->stat.sum_exits++;
 
 	run->exit_reason = KVM_EXIT_UNKNOWN;
 	run->ready_for_interrupt_injection = 1;
 
-	/* We get here with MSR.EE=0, so enable it to be a nice citizen */
-	__hard_irq_enable();
+	/* We get here with MSR.EE=1 */
+
+	trace_kvm_exit(exit_nr, vcpu);
+	kvm_guest_exit();
 
-	trace_kvm_book3s_exit(exit_nr, vcpu);
-	preempt_enable();
-	kvm_resched(vcpu);
 	switch (exit_nr) {
 	case BOOK3S_INTERRUPT_INST_STORAGE:
 	{
@@ -804,7 +856,6 @@ program_interrupt:
 	}
 	}
 
-	preempt_disable();
 	if (!(r & RESUME_HOST)) {
 		/* To avoid clobbering exit_reason, only check for signals if
 		 * we aren't already exiting to userspace for some other
@@ -816,20 +867,13 @@ program_interrupt:
 		 * and if we really did time things so badly, then we just exit
 		 * again due to a host external interrupt.
 		 */
-		__hard_irq_disable();
-		if (signal_pending(current)) {
-			__hard_irq_enable();
-#ifdef EXIT_DEBUG
-			printk(KERN_EMERG "KVM: Going back to host\n");
-#endif
-			vcpu->stat.signal_exits++;
-			run->exit_reason = KVM_EXIT_INTR;
-			r = -EINTR;
+		local_irq_disable();
+		s = kvmppc_prepare_to_enter(vcpu);
+		if (s <= 0) {
+			local_irq_enable();
+			r = s;
 		} else {
-			/* In case an interrupt came in that was triggered
-			 * from userspace (like DEC), we need to check what
-			 * to inject now! */
-			kvmppc_core_prepare_to_enter(vcpu);
+			kvmppc_lazy_ee_enable();
 		}
 	}
 
@@ -1022,8 +1066,6 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 #endif
 	ulong ext_msr;
 
-	preempt_disable();
-
 	/* Check if we can run the vcpu at all */
 	if (!vcpu->arch.sane) {
 		kvm_run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
@@ -1031,21 +1073,16 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 		goto out;
 	}
 
-	kvmppc_core_prepare_to_enter(vcpu);
-
 	/*
 	 * Interrupts could be timers for the guest which we have to inject
 	 * again, so let's postpone them until we're in the guest and if we
 	 * really did time things so badly, then we just exit again due to
 	 * a host external interrupt.
 	 */
-	__hard_irq_disable();
-
-	/* No need to go into the guest when all we do is going out */
-	if (signal_pending(current)) {
-		__hard_irq_enable();
-		kvm_run->exit_reason = KVM_EXIT_INTR;
-		ret = -EINTR;
+	local_irq_disable();
+	ret = kvmppc_prepare_to_enter(vcpu);
+	if (ret <= 0) {
+		local_irq_enable();
 		goto out;
 	}
 
@@ -1082,11 +1119,12 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 	if (vcpu->arch.shared->msr & MSR_FP)
 		kvmppc_handle_ext(vcpu, BOOK3S_INTERRUPT_FP_UNAVAIL, MSR_FP);
 
-	kvm_guest_enter();
+	kvmppc_lazy_ee_enable();
 
 	ret = __kvmppc_vcpu_run(kvm_run, vcpu);
 
-	kvm_guest_exit();
+	/* No need for kvm_guest_exit. It's done in handle_exit.
+	   We also get here with interrupts enabled. */
 
 	current->thread.regs->msr = ext_msr;
 
@@ -1115,7 +1153,7 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 #endif
 
 out:
-	preempt_enable();
+	vcpu->mode = OUTSIDE_GUEST_MODE;
 	return ret;
 }
 
@@ -1183,14 +1221,31 @@ int kvm_vm_ioctl_get_smmu_info(struct kvm *kvm, struct kvm_ppc_smmu_info *info)
 }
 #endif /* CONFIG_PPC64 */
 
+void kvmppc_core_free_memslot(struct kvm_memory_slot *free,
+			      struct kvm_memory_slot *dont)
+{
+}
+
+int kvmppc_core_create_memslot(struct kvm_memory_slot *slot,
+			       unsigned long npages)
+{
+	return 0;
+}
+
 int kvmppc_core_prepare_memory_region(struct kvm *kvm,
+				      struct kvm_memory_slot *memslot,
 				      struct kvm_userspace_memory_region *mem)
 {
 	return 0;
 }
 
 void kvmppc_core_commit_memory_region(struct kvm *kvm,
-				struct kvm_userspace_memory_region *mem)
+				struct kvm_userspace_memory_region *mem,
+				struct kvm_memory_slot old)
+{
+}
+
+void kvmppc_core_flush_memslot(struct kvm *kvm, struct kvm_memory_slot *memslot)
 {
 }
 
diff --git a/arch/powerpc/kvm/book3s_rmhandlers.S b/arch/powerpc/kvm/book3s_rmhandlers.S
index 9ecf6e3..b2f8258 100644
--- a/arch/powerpc/kvm/book3s_rmhandlers.S
+++ b/arch/powerpc/kvm/book3s_rmhandlers.S
@@ -170,20 +170,21 @@ kvmppc_handler_skip_ins:
  * Call kvmppc_handler_trampoline_enter in real mode
  *
  * On entry, r4 contains the guest shadow MSR
+ * MSR.EE has to be 0 when calling this function
  */
 _GLOBAL(kvmppc_entry_trampoline)
 	mfmsr	r5
 	LOAD_REG_ADDR(r7, kvmppc_handler_trampoline_enter)
 	toreal(r7)
 
-	li	r9, MSR_RI
-	ori	r9, r9, MSR_EE
-	andc	r9, r5, r9	/* Clear EE and RI in MSR value */
 	li	r6, MSR_IR | MSR_DR
-	ori	r6, r6, MSR_EE
-	andc	r6, r5, r6	/* Clear EE, DR and IR in MSR value */
-	MTMSR_EERI(r9)		/* Clear EE and RI in MSR */
-	mtsrr0	r7		/* before we set srr0/1 */
+	andc	r6, r5, r6	/* Clear DR and IR in MSR value */
+	/*
+	 * Set EE in HOST_MSR so that it's enabled when we get into our
+	 * C exit handler function
+	 */
+	ori	r5, r5, MSR_EE
+	mtsrr0	r7
 	mtsrr1	r6
 	RFI
 
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index d25a097..3d1f35d 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -39,6 +39,7 @@
 
 #include "timing.h"
 #include "booke.h"
+#include "trace.h"
 
 unsigned long kvmppc_booke_handlers;
 
@@ -62,6 +63,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
 	{ "halt_wakeup", VCPU_STAT(halt_wakeup) },
 	{ "doorbell", VCPU_STAT(dbell_exits) },
 	{ "guest doorbell", VCPU_STAT(gdbell_exits) },
+	{ "remote_tlb_flush", VM_STAT(remote_tlb_flush) },
 	{ NULL }
 };
 
@@ -120,6 +122,16 @@ static void kvmppc_vcpu_sync_spe(struct kvm_vcpu *vcpu)
 }
 #endif
 
+static void kvmppc_vcpu_sync_fpu(struct kvm_vcpu *vcpu)
+{
+#if defined(CONFIG_PPC_FPU) && !defined(CONFIG_KVM_BOOKE_HV)
+	/* We always treat the FP bit as enabled from the host
+	   perspective, so only need to adjust the shadow MSR */
+	vcpu->arch.shadow_msr &= ~MSR_FP;
+	vcpu->arch.shadow_msr |= vcpu->arch.shared->msr & MSR_FP;
+#endif
+}
+
 /*
  * Helper function for "full" MSR writes.  No need to call this if only
  * EE/CE/ME/DE/RI are changing.
@@ -136,11 +148,13 @@ void kvmppc_set_msr(struct kvm_vcpu *vcpu, u32 new_msr)
 
 	kvmppc_mmu_msr_notify(vcpu, old_msr);
 	kvmppc_vcpu_sync_spe(vcpu);
+	kvmppc_vcpu_sync_fpu(vcpu);
 }
 
 static void kvmppc_booke_queue_irqprio(struct kvm_vcpu *vcpu,
                                        unsigned int priority)
 {
+	trace_kvm_booke_queue_irqprio(vcpu, priority);
 	set_bit(priority, &vcpu->arch.pending_exceptions);
 }
 
@@ -206,6 +220,16 @@ void kvmppc_core_dequeue_external(struct kvm_vcpu *vcpu,
 	clear_bit(BOOKE_IRQPRIO_EXTERNAL_LEVEL, &vcpu->arch.pending_exceptions);
 }
 
+static void kvmppc_core_queue_watchdog(struct kvm_vcpu *vcpu)
+{
+	kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_WATCHDOG);
+}
+
+static void kvmppc_core_dequeue_watchdog(struct kvm_vcpu *vcpu)
+{
+	clear_bit(BOOKE_IRQPRIO_WATCHDOG, &vcpu->arch.pending_exceptions);
+}
+
 static void set_guest_srr(struct kvm_vcpu *vcpu, unsigned long srr0, u32 srr1)
 {
 #ifdef CONFIG_KVM_BOOKE_HV
@@ -325,6 +349,7 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,
 		msr_mask = MSR_CE | MSR_ME | MSR_DE;
 		int_class = INT_CLASS_NONCRIT;
 		break;
+	case BOOKE_IRQPRIO_WATCHDOG:
 	case BOOKE_IRQPRIO_CRITICAL:
 	case BOOKE_IRQPRIO_DBELL_CRIT:
 		allowed = vcpu->arch.shared->msr & MSR_CE;
@@ -404,12 +429,121 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,
 	return allowed;
 }
 
+/*
+ * Return the number of jiffies until the next timeout.  If the timeout is
+ * longer than the NEXT_TIMER_MAX_DELTA, then return NEXT_TIMER_MAX_DELTA
+ * because the larger value can break the timer APIs.
+ */
+static unsigned long watchdog_next_timeout(struct kvm_vcpu *vcpu)
+{
+	u64 tb, wdt_tb, wdt_ticks = 0;
+	u64 nr_jiffies = 0;
+	u32 period = TCR_GET_WP(vcpu->arch.tcr);
+
+	wdt_tb = 1ULL << (63 - period);
+	tb = get_tb();
+	/*
+	 * The watchdog timeout will hapeen when TB bit corresponding
+	 * to watchdog will toggle from 0 to 1.
+	 */
+	if (tb & wdt_tb)
+		wdt_ticks = wdt_tb;
+
+	wdt_ticks += wdt_tb - (tb & (wdt_tb - 1));
+
+	/* Convert timebase ticks to jiffies */
+	nr_jiffies = wdt_ticks;
+
+	if (do_div(nr_jiffies, tb_ticks_per_jiffy))
+		nr_jiffies++;
+
+	return min_t(unsigned long long, nr_jiffies, NEXT_TIMER_MAX_DELTA);
+}
+
+static void arm_next_watchdog(struct kvm_vcpu *vcpu)
+{
+	unsigned long nr_jiffies;
+	unsigned long flags;
+
+	/*
+	 * If TSR_ENW and TSR_WIS are not set then no need to exit to
+	 * userspace, so clear the KVM_REQ_WATCHDOG request.
+	 */
+	if ((vcpu->arch.tsr & (TSR_ENW | TSR_WIS)) != (TSR_ENW | TSR_WIS))
+		clear_bit(KVM_REQ_WATCHDOG, &vcpu->requests);
+
+	spin_lock_irqsave(&vcpu->arch.wdt_lock, flags);
+	nr_jiffies = watchdog_next_timeout(vcpu);
+	/*
+	 * If the number of jiffies of watchdog timer >= NEXT_TIMER_MAX_DELTA
+	 * then do not run the watchdog timer as this can break timer APIs.
+	 */
+	if (nr_jiffies < NEXT_TIMER_MAX_DELTA)
+		mod_timer(&vcpu->arch.wdt_timer, jiffies + nr_jiffies);
+	else
+		del_timer(&vcpu->arch.wdt_timer);
+	spin_unlock_irqrestore(&vcpu->arch.wdt_lock, flags);
+}
+
+void kvmppc_watchdog_func(unsigned long data)
+{
+	struct kvm_vcpu *vcpu = (struct kvm_vcpu *)data;
+	u32 tsr, new_tsr;
+	int final;
+
+	do {
+		new_tsr = tsr = vcpu->arch.tsr;
+		final = 0;
+
+		/* Time out event */
+		if (tsr & TSR_ENW) {
+			if (tsr & TSR_WIS)
+				final = 1;
+			else
+				new_tsr = tsr | TSR_WIS;
+		} else {
+			new_tsr = tsr | TSR_ENW;
+		}
+	} while (cmpxchg(&vcpu->arch.tsr, tsr, new_tsr) != tsr);
+
+	if (new_tsr & TSR_WIS) {
+		smp_wmb();
+		kvm_make_request(KVM_REQ_PENDING_TIMER, vcpu);
+		kvm_vcpu_kick(vcpu);
+	}
+
+	/*
+	 * If this is final watchdog expiry and some action is required
+	 * then exit to userspace.
+	 */
+	if (final && (vcpu->arch.tcr & TCR_WRC_MASK) &&
+	    vcpu->arch.watchdog_enabled) {
+		smp_wmb();
+		kvm_make_request(KVM_REQ_WATCHDOG, vcpu);
+		kvm_vcpu_kick(vcpu);
+	}
+
+	/*
+	 * Stop running the watchdog timer after final expiration to
+	 * prevent the host from being flooded with timers if the
+	 * guest sets a short period.
+	 * Timers will resume when TSR/TCR is updated next time.
+	 */
+	if (!final)
+		arm_next_watchdog(vcpu);
+}
+
 static void update_timer_ints(struct kvm_vcpu *vcpu)
 {
 	if ((vcpu->arch.tcr & TCR_DIE) && (vcpu->arch.tsr & TSR_DIS))
 		kvmppc_core_queue_dec(vcpu);
 	else
 		kvmppc_core_dequeue_dec(vcpu);
+
+	if ((vcpu->arch.tcr & TCR_WIE) && (vcpu->arch.tsr & TSR_WIS))
+		kvmppc_core_queue_watchdog(vcpu);
+	else
+		kvmppc_core_dequeue_watchdog(vcpu);
 }
 
 static void kvmppc_core_check_exceptions(struct kvm_vcpu *vcpu)
@@ -417,13 +551,6 @@ static void kvmppc_core_check_exceptions(struct kvm_vcpu *vcpu)
 	unsigned long *pending = &vcpu->arch.pending_exceptions;
 	unsigned int priority;
 
-	if (vcpu->requests) {
-		if (kvm_check_request(KVM_REQ_PENDING_TIMER, vcpu)) {
-			smp_mb();
-			update_timer_ints(vcpu);
-		}
-	}
-
 	priority = __ffs(*pending);
 	while (priority < BOOKE_IRQPRIO_MAX) {
 		if (kvmppc_booke_irqprio_deliver(vcpu, priority))
@@ -459,37 +586,20 @@ int kvmppc_core_prepare_to_enter(struct kvm_vcpu *vcpu)
 	return r;
 }
 
-/*
- * Common checks before entering the guest world.  Call with interrupts
- * disabled.
- *
- * returns !0 if a signal is pending and check_signal is true
- */
-static int kvmppc_prepare_to_enter(struct kvm_vcpu *vcpu)
+int kvmppc_core_check_requests(struct kvm_vcpu *vcpu)
 {
-	int r = 0;
-
-	WARN_ON_ONCE(!irqs_disabled());
-	while (true) {
-		if (need_resched()) {
-			local_irq_enable();
-			cond_resched();
-			local_irq_disable();
-			continue;
-		}
-
-		if (signal_pending(current)) {
-			r = 1;
-			break;
-		}
+	int r = 1; /* Indicate we want to get back into the guest */
 
-		if (kvmppc_core_prepare_to_enter(vcpu)) {
-			/* interrupts got enabled in between, so we
-			   are back at square 1 */
-			continue;
-		}
+	if (kvm_check_request(KVM_REQ_PENDING_TIMER, vcpu))
+		update_timer_ints(vcpu);
+#if defined(CONFIG_KVM_E500V2) || defined(CONFIG_KVM_E500MC)
+	if (kvm_check_request(KVM_REQ_TLB_FLUSH, vcpu))
+		kvmppc_core_flush_tlb(vcpu);
+#endif
 
-		break;
+	if (kvm_check_request(KVM_REQ_WATCHDOG, vcpu)) {
+		vcpu->run->exit_reason = KVM_EXIT_WATCHDOG;
+		r = 0;
 	}
 
 	return r;
@@ -497,7 +607,7 @@ static int kvmppc_prepare_to_enter(struct kvm_vcpu *vcpu)
 
 int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 {
-	int ret;
+	int ret, s;
 #ifdef CONFIG_PPC_FPU
 	unsigned int fpscr;
 	int fpexc_mode;
@@ -510,11 +620,13 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 	}
 
 	local_irq_disable();
-	if (kvmppc_prepare_to_enter(vcpu)) {
-		kvm_run->exit_reason = KVM_EXIT_INTR;
-		ret = -EINTR;
+	s = kvmppc_prepare_to_enter(vcpu);
+	if (s <= 0) {
+		local_irq_enable();
+		ret = s;
 		goto out;
 	}
+	kvmppc_lazy_ee_enable();
 
 	kvm_guest_enter();
 
@@ -542,6 +654,9 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 
 	ret = __kvmppc_vcpu_run(kvm_run, vcpu);
 
+	/* No need for kvm_guest_exit. It's done in handle_exit.
+	   We also get here with interrupts enabled. */
+
 #ifdef CONFIG_PPC_FPU
 	kvmppc_save_guest_fp(vcpu);
 
@@ -557,10 +672,8 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
 	current->thread.fpexc_mode = fpexc_mode;
 #endif
 
-	kvm_guest_exit();
-
 out:
-	local_irq_enable();
+	vcpu->mode = OUTSIDE_GUEST_MODE;
 	return ret;
 }
 
@@ -668,6 +781,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
                        unsigned int exit_nr)
 {
 	int r = RESUME_HOST;
+	int s;
 
 	/* update before a new last_exit_type is rewritten */
 	kvmppc_update_timing_stats(vcpu);
@@ -677,6 +791,9 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
 
 	local_irq_enable();
 
+	trace_kvm_exit(exit_nr, vcpu);
+	kvm_guest_exit();
+
 	run->exit_reason = KVM_EXIT_UNKNOWN;
 	run->ready_for_interrupt_injection = 1;
 
@@ -971,10 +1088,12 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
 	 */
 	if (!(r & RESUME_HOST)) {
 		local_irq_disable();
-		if (kvmppc_prepare_to_enter(vcpu)) {
-			run->exit_reason = KVM_EXIT_INTR;
-			r = (-EINTR << 2) | RESUME_HOST | (r & RESUME_FLAG_NV);
-			kvmppc_account_exit(vcpu, SIGNAL_EXITS);
+		s = kvmppc_prepare_to_enter(vcpu);
+		if (s <= 0) {
+			local_irq_enable();
+			r = (s << 2) | RESUME_HOST | (r & RESUME_FLAG_NV);
+		} else {
+			kvmppc_lazy_ee_enable();
 		}
 	}
 
@@ -1011,6 +1130,21 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
 	return r;
 }
 
+int kvmppc_subarch_vcpu_init(struct kvm_vcpu *vcpu)
+{
+	/* setup watchdog timer once */
+	spin_lock_init(&vcpu->arch.wdt_lock);
+	setup_timer(&vcpu->arch.wdt_timer, kvmppc_watchdog_func,
+		    (unsigned long)vcpu);
+
+	return 0;
+}
+
+void kvmppc_subarch_vcpu_uninit(struct kvm_vcpu *vcpu)
+{
+	del_timer_sync(&vcpu->arch.wdt_timer);
+}
+
 int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
 {
 	int i;
@@ -1106,7 +1240,13 @@ static int set_sregs_base(struct kvm_vcpu *vcpu,
 	}
 
 	if (sregs->u.e.update_special & KVM_SREGS_E_UPDATE_TSR) {
+		u32 old_tsr = vcpu->arch.tsr;
+
 		vcpu->arch.tsr = sregs->u.e.tsr;
+
+		if ((old_tsr ^ vcpu->arch.tsr) & (TSR_ENW | TSR_WIS))
+			arm_next_watchdog(vcpu);
+
 		update_timer_ints(vcpu);
 	}
 
@@ -1221,12 +1361,56 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
 
 int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
 {
-	return -EINVAL;
+	int r = -EINVAL;
+
+	switch (reg->id) {
+	case KVM_REG_PPC_IAC1:
+	case KVM_REG_PPC_IAC2:
+	case KVM_REG_PPC_IAC3:
+	case KVM_REG_PPC_IAC4: {
+		int iac = reg->id - KVM_REG_PPC_IAC1;
+		r = copy_to_user((u64 __user *)(long)reg->addr,
+				 &vcpu->arch.dbg_reg.iac[iac], sizeof(u64));
+		break;
+	}
+	case KVM_REG_PPC_DAC1:
+	case KVM_REG_PPC_DAC2: {
+		int dac = reg->id - KVM_REG_PPC_DAC1;
+		r = copy_to_user((u64 __user *)(long)reg->addr,
+				 &vcpu->arch.dbg_reg.dac[dac], sizeof(u64));
+		break;
+	}
+	default:
+		break;
+	}
+	return r;
 }
 
 int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
 {
-	return -EINVAL;
+	int r = -EINVAL;
+
+	switch (reg->id) {
+	case KVM_REG_PPC_IAC1:
+	case KVM_REG_PPC_IAC2:
+	case KVM_REG_PPC_IAC3:
+	case KVM_REG_PPC_IAC4: {
+		int iac = reg->id - KVM_REG_PPC_IAC1;
+		r = copy_from_user(&vcpu->arch.dbg_reg.iac[iac],
+			     (u64 __user *)(long)reg->addr, sizeof(u64));
+		break;
+	}
+	case KVM_REG_PPC_DAC1:
+	case KVM_REG_PPC_DAC2: {
+		int dac = reg->id - KVM_REG_PPC_DAC1;
+		r = copy_from_user(&vcpu->arch.dbg_reg.dac[dac],
+			     (u64 __user *)(long)reg->addr, sizeof(u64));
+		break;
+	}
+	default:
+		break;
+	}
+	return r;
 }
 
 int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
@@ -1253,20 +1437,38 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, struct kvm_dirty_log *log)
 	return -ENOTSUPP;
 }
 
+void kvmppc_core_free_memslot(struct kvm_memory_slot *free,
+			      struct kvm_memory_slot *dont)
+{
+}
+
+int kvmppc_core_create_memslot(struct kvm_memory_slot *slot,
+			       unsigned long npages)
+{
+	return 0;
+}
+
 int kvmppc_core_prepare_memory_region(struct kvm *kvm,
+				      struct kvm_memory_slot *memslot,
 				      struct kvm_userspace_memory_region *mem)
 {
 	return 0;
 }
 
 void kvmppc_core_commit_memory_region(struct kvm *kvm,
-				struct kvm_userspace_memory_region *mem)
+				struct kvm_userspace_memory_region *mem,
+				struct kvm_memory_slot old)
+{
+}
+
+void kvmppc_core_flush_memslot(struct kvm *kvm, struct kvm_memory_slot *memslot)
 {
 }
 
 void kvmppc_set_tcr(struct kvm_vcpu *vcpu, u32 new_tcr)
 {
 	vcpu->arch.tcr = new_tcr;
+	arm_next_watchdog(vcpu);
 	update_timer_ints(vcpu);
 }
 
@@ -1281,6 +1483,14 @@ void kvmppc_set_tsr_bits(struct kvm_vcpu *vcpu, u32 tsr_bits)
 void kvmppc_clr_tsr_bits(struct kvm_vcpu *vcpu, u32 tsr_bits)
 {
 	clear_bits(tsr_bits, &vcpu->arch.tsr);
+
+	/*
+	 * We may have stopped the watchdog due to
+	 * being stuck on final expiration.
+	 */
+	if (tsr_bits & (TSR_ENW | TSR_WIS))
+		arm_next_watchdog(vcpu);
+
 	update_timer_ints(vcpu);
 }
 
@@ -1298,12 +1508,14 @@ void kvmppc_decrementer_func(unsigned long data)
 
 void kvmppc_booke_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
 {
+	vcpu->cpu = smp_processor_id();
 	current->thread.kvm_vcpu = vcpu;
 }
 
 void kvmppc_booke_vcpu_put(struct kvm_vcpu *vcpu)
 {
 	current->thread.kvm_vcpu = NULL;
+	vcpu->cpu = -1;
 }
 
 int __init kvmppc_booke_init(void)
diff --git a/arch/powerpc/kvm/booke_emulate.c b/arch/powerpc/kvm/booke_emulate.c
index 12834bb..514790f 100644
--- a/arch/powerpc/kvm/booke_emulate.c
+++ b/arch/powerpc/kvm/booke_emulate.c
@@ -133,10 +133,10 @@ int kvmppc_booke_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, ulong spr_val)
 		vcpu->arch.csrr1 = spr_val;
 		break;
 	case SPRN_DBCR0:
-		vcpu->arch.dbcr0 = spr_val;
+		vcpu->arch.dbg_reg.dbcr0 = spr_val;
 		break;
 	case SPRN_DBCR1:
-		vcpu->arch.dbcr1 = spr_val;
+		vcpu->arch.dbg_reg.dbcr1 = spr_val;
 		break;
 	case SPRN_DBSR:
 		vcpu->arch.dbsr &= ~spr_val;
@@ -145,6 +145,14 @@ int kvmppc_booke_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, ulong spr_val)
 		kvmppc_clr_tsr_bits(vcpu, spr_val);
 		break;
 	case SPRN_TCR:
+		/*
+		 * WRC is a 2-bit field that is supposed to preserve its
+		 * value once written to non-zero.
+		 */
+		if (vcpu->arch.tcr & TCR_WRC_MASK) {
+			spr_val &= ~TCR_WRC_MASK;
+			spr_val |= vcpu->arch.tcr & TCR_WRC_MASK;
+		}
 		kvmppc_set_tcr(vcpu, spr_val);
 		break;
 
@@ -229,6 +237,9 @@ int kvmppc_booke_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, ulong spr_val)
 	case SPRN_IVOR15:
 		vcpu->arch.ivor[BOOKE_IRQPRIO_DEBUG] = spr_val;
 		break;
+	case SPRN_MCSR:
+		vcpu->arch.mcsr &= ~spr_val;
+		break;
 
 	default:
 		emulated = EMULATE_FAIL;
@@ -258,10 +269,10 @@ int kvmppc_booke_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val)
 		*spr_val = vcpu->arch.csrr1;
 		break;
 	case SPRN_DBCR0:
-		*spr_val = vcpu->arch.dbcr0;
+		*spr_val = vcpu->arch.dbg_reg.dbcr0;
 		break;
 	case SPRN_DBCR1:
-		*spr_val = vcpu->arch.dbcr1;
+		*spr_val = vcpu->arch.dbg_reg.dbcr1;
 		break;
 	case SPRN_DBSR:
 		*spr_val = vcpu->arch.dbsr;
@@ -321,6 +332,9 @@ int kvmppc_booke_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val)
 	case SPRN_IVOR15:
 		*spr_val = vcpu->arch.ivor[BOOKE_IRQPRIO_DEBUG];
 		break;
+	case SPRN_MCSR:
+		*spr_val = vcpu->arch.mcsr;
+		break;
 
 	default:
 		emulated = EMULATE_FAIL;
diff --git a/arch/powerpc/kvm/e500.h b/arch/powerpc/kvm/e500.h
index aa8b814..d162286 100644
--- a/arch/powerpc/kvm/e500.h
+++ b/arch/powerpc/kvm/e500.h
@@ -27,8 +27,7 @@
 #define E500_TLB_NUM   2
 
 #define E500_TLB_VALID 1
-#define E500_TLB_DIRTY 2
-#define E500_TLB_BITMAP 4
+#define E500_TLB_BITMAP 2
 
 struct tlbe_ref {
 	pfn_t pfn;
diff --git a/arch/powerpc/kvm/e500_tlb.c b/arch/powerpc/kvm/e500_tlb.c
index a2b6671..641f978 100644
--- a/arch/powerpc/kvm/e500_tlb.c
+++ b/arch/powerpc/kvm/e500_tlb.c
@@ -304,17 +304,13 @@ static inline void kvmppc_e500_ref_setup(struct tlbe_ref *ref,
 	ref->flags = E500_TLB_VALID;
 
 	if (tlbe_is_writable(gtlbe))
-		ref->flags |= E500_TLB_DIRTY;
+		kvm_set_pfn_dirty(pfn);
 }
 
 static inline void kvmppc_e500_ref_release(struct tlbe_ref *ref)
 {
 	if (ref->flags & E500_TLB_VALID) {
-		if (ref->flags & E500_TLB_DIRTY)
-			kvm_release_pfn_dirty(ref->pfn);
-		else
-			kvm_release_pfn_clean(ref->pfn);
-
+		trace_kvm_booke206_ref_release(ref->pfn, ref->flags);
 		ref->flags = 0;
 	}
 }
@@ -357,6 +353,13 @@ static void clear_tlb_refs(struct kvmppc_vcpu_e500 *vcpu_e500)
 	clear_tlb_privs(vcpu_e500);
 }
 
+void kvmppc_core_flush_tlb(struct kvm_vcpu *vcpu)
+{
+	struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
+	clear_tlb_refs(vcpu_e500);
+	clear_tlb1_bitmap(vcpu_e500);
+}
+
 static inline void kvmppc_e500_deliver_tlb_miss(struct kvm_vcpu *vcpu,
 		unsigned int eaddr, int as)
 {
@@ -520,11 +523,10 @@ static inline void kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500,
 
 	if (likely(!pfnmap)) {
 		unsigned long tsize_pages = 1 << (tsize + 10 - PAGE_SHIFT);
-		pfn = gfn_to_pfn_memslot(vcpu_e500->vcpu.kvm, slot, gfn);
+		pfn = gfn_to_pfn_memslot(slot, gfn);
 		if (is_error_pfn(pfn)) {
 			printk(KERN_ERR "Couldn't get real page for gfn %lx!\n",
 					(long)gfn);
-			kvm_release_pfn_clean(pfn);
 			return;
 		}
 
@@ -542,6 +544,9 @@ static inline void kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500,
 
 	/* Clear i-cache for new pages */
 	kvmppc_mmu_flush_icache(pfn);
+
+	/* Drop refcount on page, so that mmu notifiers can clear it */
+	kvm_release_pfn_clean(pfn);
 }
 
 /* XXX only map the one-one case, for now use TLB0 */
@@ -1040,8 +1045,12 @@ void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 eaddr, gpa_t gpaddr,
 		sesel = 0; /* unused */
 		priv = &vcpu_e500->gtlb_priv[tlbsel][esel];
 
-		kvmppc_e500_setup_stlbe(vcpu, gtlbe, BOOK3E_PAGESZ_4K,
-					&priv->ref, eaddr, &stlbe);
+		/* Only triggers after clear_tlb_refs */
+		if (unlikely(!(priv->ref.flags & E500_TLB_VALID)))
+			kvmppc_e500_tlb0_map(vcpu_e500, esel, &stlbe);
+		else
+			kvmppc_e500_setup_stlbe(vcpu, gtlbe, BOOK3E_PAGESZ_4K,
+						&priv->ref, eaddr, &stlbe);
 		break;
 
 	case 1: {
@@ -1061,6 +1070,49 @@ void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 eaddr, gpa_t gpaddr,
 	write_stlbe(vcpu_e500, gtlbe, &stlbe, stlbsel, sesel);
 }
 
+/************* MMU Notifiers *************/
+
+int kvm_unmap_hva(struct kvm *kvm, unsigned long hva)
+{
+	trace_kvm_unmap_hva(hva);
+
+	/*
+	 * Flush all shadow tlb entries everywhere. This is slow, but
+	 * we are 100% sure that we catch the to be unmapped page
+	 */
+	kvm_flush_remote_tlbs(kvm);
+
+	return 0;
+}
+
+int kvm_unmap_hva_range(struct kvm *kvm, unsigned long start, unsigned long end)
+{
+	/* kvm_unmap_hva flushes everything anyways */
+	kvm_unmap_hva(kvm, start);
+
+	return 0;
+}
+
+int kvm_age_hva(struct kvm *kvm, unsigned long hva)
+{
+	/* XXX could be more clever ;) */
+	return 0;
+}
+
+int kvm_test_age_hva(struct kvm *kvm, unsigned long hva)
+{
+	/* XXX could be more clever ;) */
+	return 0;
+}
+
+void kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte)
+{
+	/* The page will get remapped properly on its next fault */
+	kvm_unmap_hva(kvm, hva);
+}
+
+/*****************************************/
+
 static void free_gtlb(struct kvmppc_vcpu_e500 *vcpu_e500)
 {
 	int i;
@@ -1082,6 +1134,8 @@ static void free_gtlb(struct kvmppc_vcpu_e500 *vcpu_e500)
 		}
 
 		vcpu_e500->num_shared_tlb_pages = 0;
+
+		kfree(vcpu_e500->shared_tlb_pages);
 		vcpu_e500->shared_tlb_pages = NULL;
 	} else {
 		kfree(vcpu_e500->gtlb_arch);
@@ -1333,7 +1387,7 @@ int kvmppc_e500_tlb_init(struct kvmppc_vcpu_e500 *vcpu_e500)
 	if (!vcpu_e500->gtlb_priv[1])
 		goto err;
 
-	vcpu_e500->g2h_tlb1_map = kzalloc(sizeof(unsigned int) *
+	vcpu_e500->g2h_tlb1_map = kzalloc(sizeof(u64) *
 					  vcpu_e500->gtlb_params[1].entries,
 					  GFP_KERNEL);
 	if (!vcpu_e500->g2h_tlb1_map)
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index 87f4dc8..deb0d59 100644
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -30,6 +30,7 @@
 #include <asm/kvm_ppc.h>
 #include <asm/tlbflush.h>
 #include <asm/cputhreads.h>
+#include <asm/irqflags.h>
 #include "timing.h"
 #include "../mm/mmu_decl.h"
 
@@ -38,8 +39,7 @@
 
 int kvm_arch_vcpu_runnable(struct kvm_vcpu *v)
 {
-	return !(v->arch.shared->msr & MSR_WE) ||
-	       !!(v->arch.pending_exceptions) ||
+	return !!(v->arch.pending_exceptions) ||
 	       v->requests;
 }
 
@@ -48,6 +48,85 @@ int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu)
 	return 1;
 }
 
+#ifndef CONFIG_KVM_BOOK3S_64_HV
+/*
+ * Common checks before entering the guest world.  Call with interrupts
+ * disabled.
+ *
+ * returns:
+ *
+ * == 1 if we're ready to go into guest state
+ * <= 0 if we need to go back to the host with return value
+ */
+int kvmppc_prepare_to_enter(struct kvm_vcpu *vcpu)
+{
+	int r = 1;
+
+	WARN_ON_ONCE(!irqs_disabled());
+	while (true) {
+		if (need_resched()) {
+			local_irq_enable();
+			cond_resched();
+			local_irq_disable();
+			continue;
+		}
+
+		if (signal_pending(current)) {
+			kvmppc_account_exit(vcpu, SIGNAL_EXITS);
+			vcpu->run->exit_reason = KVM_EXIT_INTR;
+			r = -EINTR;
+			break;
+		}
+
+		vcpu->mode = IN_GUEST_MODE;
+
+		/*
+		 * Reading vcpu->requests must happen after setting vcpu->mode,
+		 * so we don't miss a request because the requester sees
+		 * OUTSIDE_GUEST_MODE and assumes we'll be checking requests
+		 * before next entering the guest (and thus doesn't IPI).
+		 */
+		smp_mb();
+
+		if (vcpu->requests) {
+			/* Make sure we process requests preemptable */
+			local_irq_enable();
+			trace_kvm_check_requests(vcpu);
+			r = kvmppc_core_check_requests(vcpu);
+			local_irq_disable();
+			if (r > 0)
+				continue;
+			break;
+		}
+
+		if (kvmppc_core_prepare_to_enter(vcpu)) {
+			/* interrupts got enabled in between, so we
+			   are back at square 1 */
+			continue;
+		}
+
+#ifdef CONFIG_PPC64
+		/* lazy EE magic */
+		hard_irq_disable();
+		if (lazy_irq_pending()) {
+			/* Got an interrupt in between, try again */
+			local_irq_enable();
+			local_irq_disable();
+			kvm_guest_exit();
+			continue;
+		}
+
+		trace_hardirqs_on();
+#endif
+
+		kvm_guest_enter();
+		break;
+	}
+
+	return r;
+}
+#endif /* CONFIG_KVM_BOOK3S_64_HV */
+
 int kvmppc_kvm_pv(struct kvm_vcpu *vcpu)
 {
 	int nr = kvmppc_get_gpr(vcpu, 11);
@@ -67,18 +146,18 @@ int kvmppc_kvm_pv(struct kvm_vcpu *vcpu)
 	}
 
 	switch (nr) {
-	case HC_VENDOR_KVM | KVM_HC_PPC_MAP_MAGIC_PAGE:
+	case KVM_HCALL_TOKEN(KVM_HC_PPC_MAP_MAGIC_PAGE):
 	{
 		vcpu->arch.magic_page_pa = param1;
 		vcpu->arch.magic_page_ea = param2;
 
 		r2 = KVM_MAGIC_FEAT_SR | KVM_MAGIC_FEAT_MAS0_TO_SPRG7;
 
-		r = HC_EV_SUCCESS;
+		r = EV_SUCCESS;
 		break;
 	}
-	case HC_VENDOR_KVM | KVM_HC_FEATURES:
-		r = HC_EV_SUCCESS;
+	case KVM_HCALL_TOKEN(KVM_HC_FEATURES):
+		r = EV_SUCCESS;
 #if defined(CONFIG_PPC_BOOK3S) || defined(CONFIG_KVM_E500V2)
 		/* XXX Missing magic page on 44x */
 		r2 |= (1 << KVM_FEATURE_MAGIC_PAGE);
@@ -86,8 +165,13 @@ int kvmppc_kvm_pv(struct kvm_vcpu *vcpu)
 
 		/* Second return value is in r4 */
 		break;
+	case EV_HCALL_TOKEN(EV_IDLE):
+		r = EV_SUCCESS;
+		kvm_vcpu_block(vcpu);
+		clear_bit(KVM_REQ_UNHALT, &vcpu->requests);
+		break;
 	default:
-		r = HC_EV_UNIMPLEMENTED;
+		r = EV_UNIMPLEMENTED;
 		break;
 	}
 
@@ -220,6 +304,7 @@ int kvm_dev_ioctl_check_extension(long ext)
 	switch (ext) {
 #ifdef CONFIG_BOOKE
 	case KVM_CAP_PPC_BOOKE_SREGS:
+	case KVM_CAP_PPC_BOOKE_WATCHDOG:
 #else
 	case KVM_CAP_PPC_SEGSTATE:
 	case KVM_CAP_PPC_HIOR:
@@ -260,10 +345,16 @@ int kvm_dev_ioctl_check_extension(long ext)
 		if (cpu_has_feature(CPU_FTR_ARCH_201))
 			r = 2;
 		break;
+#endif
 	case KVM_CAP_SYNC_MMU:
+#ifdef CONFIG_KVM_BOOK3S_64_HV
 		r = cpu_has_feature(CPU_FTR_ARCH_206) ? 1 : 0;
-		break;
+#elif defined(KVM_ARCH_WANT_MMU_NOTIFIER)
+		r = 1;
+#else
+		r = 0;
 #endif
+		break;
 	case KVM_CAP_NR_VCPUS:
 		/*
 		 * Recommending a number of CPUs is somewhat arbitrary; we
@@ -302,11 +393,12 @@ long kvm_arch_dev_ioctl(struct file *filp,
 void kvm_arch_free_memslot(struct kvm_memory_slot *free,
 			   struct kvm_memory_slot *dont)
 {
+	kvmppc_core_free_memslot(free, dont);
 }
 
 int kvm_arch_create_memslot(struct kvm_memory_slot *slot, unsigned long npages)
 {
-	return 0;
+	return kvmppc_core_create_memslot(slot, npages);
 }
 
 int kvm_arch_prepare_memory_region(struct kvm *kvm,
@@ -315,7 +407,7 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
                                    struct kvm_userspace_memory_region *mem,
                                    int user_alloc)
 {
-	return kvmppc_core_prepare_memory_region(kvm, mem);
+	return kvmppc_core_prepare_memory_region(kvm, memslot, mem);
 }
 
 void kvm_arch_commit_memory_region(struct kvm *kvm,
@@ -323,12 +415,17 @@ void kvm_arch_commit_memory_region(struct kvm *kvm,
                struct kvm_memory_slot old,
                int user_alloc)
 {
-	kvmppc_core_commit_memory_region(kvm, mem);
+	kvmppc_core_commit_memory_region(kvm, mem, old);
 }
 
+void kvm_arch_flush_shadow_all(struct kvm *kvm)
+{
+}
 
-void kvm_arch_flush_shadow(struct kvm *kvm)
+void kvm_arch_flush_shadow_memslot(struct kvm *kvm,
+				   struct kvm_memory_slot *slot)
 {
+	kvmppc_core_flush_memslot(kvm, slot);
 }
 
 struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id)
@@ -378,6 +475,8 @@ enum hrtimer_restart kvmppc_decrementer_wakeup(struct hrtimer *timer)
 
 int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
 {
+	int ret;
+
 	hrtimer_init(&vcpu->arch.dec_timer, CLOCK_REALTIME, HRTIMER_MODE_ABS);
 	tasklet_init(&vcpu->arch.tasklet, kvmppc_decrementer_func, (ulong)vcpu);
 	vcpu->arch.dec_timer.function = kvmppc_decrementer_wakeup;
@@ -386,13 +485,14 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
 #ifdef CONFIG_KVM_EXIT_TIMING
 	mutex_init(&vcpu->arch.exit_timing_lock);
 #endif
-
-	return 0;
+	ret = kvmppc_subarch_vcpu_init(vcpu);
+	return ret;
 }
 
 void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu)
 {
 	kvmppc_mmu_destroy(vcpu);
+	kvmppc_subarch_vcpu_uninit(vcpu);
 }
 
 void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
@@ -408,7 +508,6 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
 	mtspr(SPRN_VRSAVE, vcpu->arch.vrsave);
 #endif
 	kvmppc_core_vcpu_load(vcpu, cpu);
-	vcpu->cpu = smp_processor_id();
 }
 
 void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
@@ -417,7 +516,6 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
 #ifdef CONFIG_BOOKE
 	vcpu->arch.vrsave = mfspr(SPRN_VRSAVE);
 #endif
-	vcpu->cpu = -1;
 }
 
 int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu,
@@ -637,6 +735,12 @@ static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu,
 		r = 0;
 		vcpu->arch.papr_enabled = true;
 		break;
+#ifdef CONFIG_BOOKE
+	case KVM_CAP_PPC_BOOKE_WATCHDOG:
+		r = 0;
+		vcpu->arch.watchdog_enabled = true;
+		break;
+#endif
 #if defined(CONFIG_KVM_E500V2) || defined(CONFIG_KVM_E500MC)
 	case KVM_CAP_SW_TLB: {
 		struct kvm_config_tlb cfg;
@@ -739,9 +843,16 @@ int kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf)
 
 static int kvm_vm_ioctl_get_pvinfo(struct kvm_ppc_pvinfo *pvinfo)
 {
+	u32 inst_nop = 0x60000000;
+#ifdef CONFIG_KVM_BOOKE_HV
+	u32 inst_sc1 = 0x44000022;
+	pvinfo->hcall[0] = inst_sc1;
+	pvinfo->hcall[1] = inst_nop;
+	pvinfo->hcall[2] = inst_nop;
+	pvinfo->hcall[3] = inst_nop;
+#else
 	u32 inst_lis = 0x3c000000;
 	u32 inst_ori = 0x60000000;
-	u32 inst_nop = 0x60000000;
 	u32 inst_sc = 0x44000002;
 	u32 inst_imm_mask = 0xffff;
 
@@ -758,6 +869,9 @@ static int kvm_vm_ioctl_get_pvinfo(struct kvm_ppc_pvinfo *pvinfo)
 	pvinfo->hcall[1] = inst_ori | (KVM_SC_MAGIC_R0 & inst_imm_mask);
 	pvinfo->hcall[2] = inst_sc;
 	pvinfo->hcall[3] = inst_nop;
+#endif
+
+	pvinfo->flags = KVM_PPC_PVINFO_FLAGS_EV_IDLE;
 
 	return 0;
 }
diff --git a/arch/powerpc/kvm/trace.h b/arch/powerpc/kvm/trace.h
index 877186b..e326489 100644
--- a/arch/powerpc/kvm/trace.h
+++ b/arch/powerpc/kvm/trace.h
@@ -31,6 +31,126 @@ TRACE_EVENT(kvm_ppc_instr,
 		  __entry->inst, __entry->pc, __entry->emulate)
 );
 
+#ifdef CONFIG_PPC_BOOK3S
+#define kvm_trace_symbol_exit \
+	{0x100, "SYSTEM_RESET"}, \
+	{0x200, "MACHINE_CHECK"}, \
+	{0x300, "DATA_STORAGE"}, \
+	{0x380, "DATA_SEGMENT"}, \
+	{0x400, "INST_STORAGE"}, \
+	{0x480, "INST_SEGMENT"}, \
+	{0x500, "EXTERNAL"}, \
+	{0x501, "EXTERNAL_LEVEL"}, \
+	{0x502, "EXTERNAL_HV"}, \
+	{0x600, "ALIGNMENT"}, \
+	{0x700, "PROGRAM"}, \
+	{0x800, "FP_UNAVAIL"}, \
+	{0x900, "DECREMENTER"}, \
+	{0x980, "HV_DECREMENTER"}, \
+	{0xc00, "SYSCALL"}, \
+	{0xd00, "TRACE"}, \
+	{0xe00, "H_DATA_STORAGE"}, \
+	{0xe20, "H_INST_STORAGE"}, \
+	{0xe40, "H_EMUL_ASSIST"}, \
+	{0xf00, "PERFMON"}, \
+	{0xf20, "ALTIVEC"}, \
+	{0xf40, "VSX"}
+#else
+#define kvm_trace_symbol_exit \
+	{0, "CRITICAL"}, \
+	{1, "MACHINE_CHECK"}, \
+	{2, "DATA_STORAGE"}, \
+	{3, "INST_STORAGE"}, \
+	{4, "EXTERNAL"}, \
+	{5, "ALIGNMENT"}, \
+	{6, "PROGRAM"}, \
+	{7, "FP_UNAVAIL"}, \
+	{8, "SYSCALL"}, \
+	{9, "AP_UNAVAIL"}, \
+	{10, "DECREMENTER"}, \
+	{11, "FIT"}, \
+	{12, "WATCHDOG"}, \
+	{13, "DTLB_MISS"}, \
+	{14, "ITLB_MISS"}, \
+	{15, "DEBUG"}, \
+	{32, "SPE_UNAVAIL"}, \
+	{33, "SPE_FP_DATA"}, \
+	{34, "SPE_FP_ROUND"}, \
+	{35, "PERFORMANCE_MONITOR"}, \
+	{36, "DOORBELL"}, \
+	{37, "DOORBELL_CRITICAL"}, \
+	{38, "GUEST_DBELL"}, \
+	{39, "GUEST_DBELL_CRIT"}, \
+	{40, "HV_SYSCALL"}, \
+	{41, "HV_PRIV"}
+#endif
+
+TRACE_EVENT(kvm_exit,
+	TP_PROTO(unsigned int exit_nr, struct kvm_vcpu *vcpu),
+	TP_ARGS(exit_nr, vcpu),
+
+	TP_STRUCT__entry(
+		__field(	unsigned int,	exit_nr		)
+		__field(	unsigned long,	pc		)
+		__field(	unsigned long,	msr		)
+		__field(	unsigned long,	dar		)
+#ifdef CONFIG_KVM_BOOK3S_PR
+		__field(	unsigned long,	srr1		)
+#endif
+		__field(	unsigned long,	last_inst	)
+	),
+
+	TP_fast_assign(
+#ifdef CONFIG_KVM_BOOK3S_PR
+		struct kvmppc_book3s_shadow_vcpu *svcpu;
+#endif
+		__entry->exit_nr	= exit_nr;
+		__entry->pc		= kvmppc_get_pc(vcpu);
+		__entry->dar		= kvmppc_get_fault_dar(vcpu);
+		__entry->msr		= vcpu->arch.shared->msr;
+#ifdef CONFIG_KVM_BOOK3S_PR
+		svcpu = svcpu_get(vcpu);
+		__entry->srr1		= svcpu->shadow_srr1;
+		svcpu_put(svcpu);
+#endif
+		__entry->last_inst	= vcpu->arch.last_inst;
+	),
+
+	TP_printk("exit=%s"
+		" | pc=0x%lx"
+		" | msr=0x%lx"
+		" | dar=0x%lx"
+#ifdef CONFIG_KVM_BOOK3S_PR
+		" | srr1=0x%lx"
+#endif
+		" | last_inst=0x%lx"
+		,
+		__print_symbolic(__entry->exit_nr, kvm_trace_symbol_exit),
+		__entry->pc,
+		__entry->msr,
+		__entry->dar,
+#ifdef CONFIG_KVM_BOOK3S_PR
+		__entry->srr1,
+#endif
+		__entry->last_inst
+		)
+);
+
+TRACE_EVENT(kvm_unmap_hva,
+	TP_PROTO(unsigned long hva),
+	TP_ARGS(hva),
+
+	TP_STRUCT__entry(
+		__field(	unsigned long,	hva		)
+	),
+
+	TP_fast_assign(
+		__entry->hva		= hva;
+	),
+
+	TP_printk("unmap hva 0x%lx\n", __entry->hva)
+);
+
 TRACE_EVENT(kvm_stlb_inval,
 	TP_PROTO(unsigned int stlb_index),
 	TP_ARGS(stlb_index),
@@ -98,41 +218,31 @@ TRACE_EVENT(kvm_gtlb_write,
 		__entry->word1, __entry->word2)
 );
 
-
-/*************************************************************************
- *                         Book3S trace points                           *
- *************************************************************************/
-
-#ifdef CONFIG_KVM_BOOK3S_PR
-
-TRACE_EVENT(kvm_book3s_exit,
-	TP_PROTO(unsigned int exit_nr, struct kvm_vcpu *vcpu),
-	TP_ARGS(exit_nr, vcpu),
+TRACE_EVENT(kvm_check_requests,
+	TP_PROTO(struct kvm_vcpu *vcpu),
+	TP_ARGS(vcpu),
 
 	TP_STRUCT__entry(
-		__field(	unsigned int,	exit_nr		)
-		__field(	unsigned long,	pc		)
-		__field(	unsigned long,	msr		)
-		__field(	unsigned long,	dar		)
-		__field(	unsigned long,	srr1		)
+		__field(	__u32,	cpu_nr		)
+		__field(	__u32,	requests	)
 	),
 
 	TP_fast_assign(
-		struct kvmppc_book3s_shadow_vcpu *svcpu;
-		__entry->exit_nr	= exit_nr;
-		__entry->pc		= kvmppc_get_pc(vcpu);
-		__entry->dar		= kvmppc_get_fault_dar(vcpu);
-		__entry->msr		= vcpu->arch.shared->msr;
-		svcpu = svcpu_get(vcpu);
-		__entry->srr1		= svcpu->shadow_srr1;
-		svcpu_put(svcpu);
+		__entry->cpu_nr		= vcpu->vcpu_id;
+		__entry->requests	= vcpu->requests;
 	),
 
-	TP_printk("exit=0x%x | pc=0x%lx | msr=0x%lx | dar=0x%lx | srr1=0x%lx",
-		  __entry->exit_nr, __entry->pc, __entry->msr, __entry->dar,
-		  __entry->srr1)
+	TP_printk("vcpu=%x requests=%x",
+		__entry->cpu_nr, __entry->requests)
 );
 
+
+/*************************************************************************
+ *                         Book3S trace points                           *
+ *************************************************************************/
+
+#ifdef CONFIG_KVM_BOOK3S_PR
+
 TRACE_EVENT(kvm_book3s_reenter,
 	TP_PROTO(int r, struct kvm_vcpu *vcpu),
 	TP_ARGS(r, vcpu),
@@ -189,7 +299,7 @@ TRACE_EVENT(kvm_book3s_mmu_map,
 	TP_ARGS(pte),
 
 	TP_STRUCT__entry(
-		__field(	u64,		host_va		)
+		__field(	u64,		host_vpn	)
 		__field(	u64,		pfn		)
 		__field(	ulong,		eaddr		)
 		__field(	u64,		vpage		)
@@ -198,7 +308,7 @@ TRACE_EVENT(kvm_book3s_mmu_map,
 	),
 
 	TP_fast_assign(
-		__entry->host_va	= pte->host_va;
+		__entry->host_vpn	= pte->host_vpn;
 		__entry->pfn		= pte->pfn;
 		__entry->eaddr		= pte->pte.eaddr;
 		__entry->vpage		= pte->pte.vpage;
@@ -208,8 +318,8 @@ TRACE_EVENT(kvm_book3s_mmu_map,
 					  (pte->pte.may_execute ? 0x1 : 0);
 	),
 
-	TP_printk("Map: hva=%llx pfn=%llx ea=%lx vp=%llx ra=%lx [%x]",
-		  __entry->host_va, __entry->pfn, __entry->eaddr,
+	TP_printk("Map: hvpn=%llx pfn=%llx ea=%lx vp=%llx ra=%lx [%x]",
+		  __entry->host_vpn, __entry->pfn, __entry->eaddr,
 		  __entry->vpage, __entry->raddr, __entry->flags)
 );
 
@@ -218,7 +328,7 @@ TRACE_EVENT(kvm_book3s_mmu_invalidate,
 	TP_ARGS(pte),
 
 	TP_STRUCT__entry(
-		__field(	u64,		host_va		)
+		__field(	u64,		host_vpn	)
 		__field(	u64,		pfn		)
 		__field(	ulong,		eaddr		)
 		__field(	u64,		vpage		)
@@ -227,7 +337,7 @@ TRACE_EVENT(kvm_book3s_mmu_invalidate,
 	),
 
 	TP_fast_assign(
-		__entry->host_va	= pte->host_va;
+		__entry->host_vpn	= pte->host_vpn;
 		__entry->pfn		= pte->pfn;
 		__entry->eaddr		= pte->pte.eaddr;
 		__entry->vpage		= pte->pte.vpage;
@@ -238,7 +348,7 @@ TRACE_EVENT(kvm_book3s_mmu_invalidate,
 	),
 
 	TP_printk("Flush: hva=%llx pfn=%llx ea=%lx vp=%llx ra=%lx [%x]",
-		  __entry->host_va, __entry->pfn, __entry->eaddr,
+		  __entry->host_vpn, __entry->pfn, __entry->eaddr,
 		  __entry->vpage, __entry->raddr, __entry->flags)
 );
 
@@ -395,6 +505,44 @@ TRACE_EVENT(kvm_booke206_gtlb_write,
 		__entry->mas2, __entry->mas7_3)
 );
 
+TRACE_EVENT(kvm_booke206_ref_release,
+	TP_PROTO(__u64 pfn, __u32 flags),
+	TP_ARGS(pfn, flags),
+
+	TP_STRUCT__entry(
+		__field(	__u64,	pfn		)
+		__field(	__u32,	flags		)
+	),
+
+	TP_fast_assign(
+		__entry->pfn		= pfn;
+		__entry->flags		= flags;
+	),
+
+	TP_printk("pfn=%llx flags=%x",
+		__entry->pfn, __entry->flags)
+);
+
+TRACE_EVENT(kvm_booke_queue_irqprio,
+	TP_PROTO(struct kvm_vcpu *vcpu, unsigned int priority),
+	TP_ARGS(vcpu, priority),
+
+	TP_STRUCT__entry(
+		__field(	__u32,	cpu_nr		)
+		__field(	__u32,	priority		)
+		__field(	unsigned long,	pending		)
+	),
+
+	TP_fast_assign(
+		__entry->cpu_nr		= vcpu->vcpu_id;
+		__entry->priority	= priority;
+		__entry->pending	= vcpu->arch.pending_exceptions;
+	),
+
+	TP_printk("vcpu=%x prio=%x pending=%lx",
+		__entry->cpu_nr, __entry->priority, __entry->pending)
+);
+
 #endif
 
 #endif /* _TRACE_KVM_H */
diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
index 9a52349..e15c521 100644
--- a/arch/powerpc/lib/sstep.c
+++ b/arch/powerpc/lib/sstep.c
@@ -566,7 +566,7 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr)
 	unsigned long int ea;
 	unsigned int cr, mb, me, sh;
 	int err;
-	unsigned long old_ra;
+	unsigned long old_ra, val3;
 	long ival;
 
 	opcode = instr >> 26;
@@ -1486,11 +1486,43 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr)
 		goto ldst_done;
 
 	case 36:	/* stw */
-	case 37:	/* stwu */
 		val = regs->gpr[rd];
 		err = write_mem(val, dform_ea(instr, regs), 4, regs);
 		goto ldst_done;
 
+	case 37:	/* stwu */
+		val = regs->gpr[rd];
+		val3 = dform_ea(instr, regs);
+		/*
+		 * For PPC32 we always use stwu to change stack point with r1. So
+		 * this emulated store may corrupt the exception frame, now we
+		 * have to provide the exception frame trampoline, which is pushed
+		 * below the kprobed function stack. So we only update gpr[1] but
+		 * don't emulate the real store operation. We will do real store
+		 * operation safely in exception return code by checking this flag.
+		 */
+		if ((ra == 1) && !(regs->msr & MSR_PR) \
+			&& (val3 >= (regs->gpr[1] - STACK_INT_FRAME_SIZE))) {
+			/*
+			 * Check if we will touch kernel sack overflow
+			 */
+			if (val3 - STACK_INT_FRAME_SIZE <= current->thread.ksp_limit) {
+				printk(KERN_CRIT "Can't kprobe this since Kernel stack overflow.\n");
+				err = -EINVAL;
+				break;
+			}
+
+			/*
+			 * Check if we already set since that means we'll
+			 * lose the previous value.
+			 */
+			WARN_ON(test_thread_flag(TIF_EMULATE_STACK_STORE));
+			set_thread_flag(TIF_EMULATE_STACK_STORE);
+			err = 0;
+		} else
+			err = write_mem(val, val3, 4, regs);
+		goto ldst_done;
+
 	case 38:	/* stb */
 	case 39:	/* stbu */
 		val = regs->gpr[rd];
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
index 08ffcf5..0a6b283 100644
--- a/arch/powerpc/mm/fault.c
+++ b/arch/powerpc/mm/fault.c
@@ -133,6 +133,7 @@ static int do_sigbus(struct pt_regs *regs, unsigned long address)
 	up_read(&current->mm->mmap_sem);
 
 	if (user_mode(regs)) {
+		current->thread.trap_nr = BUS_ADRERR;
 		info.si_signo = SIGBUS;
 		info.si_errno = 0;
 		info.si_code = BUS_ADRERR;
@@ -450,6 +451,7 @@ good_area:
 			/* Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk
 			 * of starvation. */
 			flags &= ~FAULT_FLAG_ALLOW_RETRY;
+			flags |= FAULT_FLAG_TRIED;
 			goto retry;
 		}
 	}
@@ -470,7 +472,7 @@ bad_area_nosemaphore:
 	if (is_exec && (error_code & DSISR_PROTFAULT))
 		printk_ratelimited(KERN_CRIT "kernel tried to execute NX-protected"
 				   " page (%lx) - exploit attempt? (uid: %d)\n",
-				   address, current_uid());
+				   address, from_kuid(&init_user_ns, current_uid()));
 
 	return SIGSEGV;
 
diff --git a/arch/powerpc/mm/hash_low_64.S b/arch/powerpc/mm/hash_low_64.S
index 602aeb0..5658508 100644
--- a/arch/powerpc/mm/hash_low_64.S
+++ b/arch/powerpc/mm/hash_low_64.S
@@ -63,7 +63,7 @@ _GLOBAL(__hash_page_4K)
 	/* Save non-volatile registers.
 	 * r31 will hold "old PTE"
 	 * r30 is "new PTE"
-	 * r29 is "va"
+	 * r29 is vpn
 	 * r28 is a hash value
 	 * r27 is hashtab mask (maybe dynamic patched instead ?)
 	 */
@@ -111,10 +111,10 @@ BEGIN_FTR_SECTION
 	cmpdi	r9,0			/* check segment size */
 	bne	3f
 END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
-	/* Calc va and put it in r29 */
-	rldicr	r29,r5,28,63-28
-	rldicl	r3,r3,0,36
-	or	r29,r3,r29
+	/* Calc vpn and put it in r29 */
+	sldi	r29,r5,SID_SHIFT - VPN_SHIFT
+	rldicl  r28,r3,64 - VPN_SHIFT,64 - (SID_SHIFT - VPN_SHIFT)
+	or	r29,r28,r29
 
 	/* Calculate hash value for primary slot and store it in r28 */
 	rldicl	r5,r5,0,25		/* vsid & 0x0000007fffffffff */
@@ -122,14 +122,19 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
 	xor	r28,r5,r0
 	b	4f
 
-3:	/* Calc VA and hash in r29 and r28 for 1T segment */
-	sldi	r29,r5,40		/* vsid << 40 */
-	clrldi	r3,r3,24		/* ea & 0xffffffffff */
+3:	/* Calc vpn and put it in r29 */
+	sldi	r29,r5,SID_SHIFT_1T - VPN_SHIFT
+	rldicl  r28,r3,64 - VPN_SHIFT,64 - (SID_SHIFT_1T - VPN_SHIFT)
+	or	r29,r28,r29
+
+	/*
+	 * calculate hash value for primary slot and
+	 * store it in r28 for 1T segment
+	 */
 	rldic	r28,r5,25,25		/* (vsid << 25) & 0x7fffffffff */
 	clrldi	r5,r5,40		/* vsid & 0xffffff */
 	rldicl	r0,r3,64-12,36		/* (ea >> 12) & 0xfffffff */
 	xor	r28,r28,r5
-	or	r29,r3,r29		/* VA */
 	xor	r28,r28,r0		/* hash */
 
 	/* Convert linux PTE bits into HW equivalents */
@@ -185,7 +190,7 @@ htab_insert_pte:
 
 	/* Call ppc_md.hpte_insert */
 	ld	r6,STK_PARAM(R4)(r1)	/* Retrieve new pp bits */
-	mr	r4,r29			/* Retrieve va */
+	mr	r4,r29			/* Retrieve vpn */
 	li	r7,0			/* !bolted, !secondary */
 	li	r8,MMU_PAGE_4K		/* page size */
 	ld	r9,STK_PARAM(R9)(r1)	/* segment size */
@@ -208,7 +213,7 @@ _GLOBAL(htab_call_hpte_insert1)
 	
 	/* Call ppc_md.hpte_insert */
 	ld	r6,STK_PARAM(R4)(r1)	/* Retrieve new pp bits */
-	mr	r4,r29			/* Retrieve va */
+	mr	r4,r29			/* Retrieve vpn */
 	li	r7,HPTE_V_SECONDARY	/* !bolted, secondary */
 	li	r8,MMU_PAGE_4K		/* page size */
 	ld	r9,STK_PARAM(R9)(r1)	/* segment size */
@@ -278,7 +283,7 @@ htab_modify_pte:
 	add	r3,r0,r3	/* add slot idx */
 
 	/* Call ppc_md.hpte_updatepp */
-	mr	r5,r29			/* va */
+	mr	r5,r29			/* vpn */
 	li	r6,MMU_PAGE_4K		/* page size */
 	ld	r7,STK_PARAM(R9)(r1)	/* segment size */
 	ld	r8,STK_PARAM(R8)(r1)	/* get "local" param */
@@ -339,7 +344,7 @@ _GLOBAL(__hash_page_4K)
 	/* Save non-volatile registers.
 	 * r31 will hold "old PTE"
 	 * r30 is "new PTE"
-	 * r29 is "va"
+	 * r29 is vpn
 	 * r28 is a hash value
 	 * r27 is hashtab mask (maybe dynamic patched instead ?)
 	 * r26 is the hidx mask
@@ -394,10 +399,14 @@ BEGIN_FTR_SECTION
 	cmpdi	r9,0			/* check segment size */
 	bne	3f
 END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
-	/* Calc va and put it in r29 */
-	rldicr	r29,r5,28,63-28		/* r29 = (vsid << 28) */
-	rldicl	r3,r3,0,36		/* r3 = (ea & 0x0fffffff) */
-	or	r29,r3,r29		/* r29 = va */
+	/* Calc vpn and put it in r29 */
+	sldi	r29,r5,SID_SHIFT - VPN_SHIFT
+	/*
+	 * clrldi r3,r3,64 - SID_SHIFT -->  ea & 0xfffffff
+	 * srdi	 r28,r3,VPN_SHIFT
+	 */
+	rldicl  r28,r3,64 - VPN_SHIFT,64 - (SID_SHIFT - VPN_SHIFT)
+	or	r29,r28,r29
 
 	/* Calculate hash value for primary slot and store it in r28 */
 	rldicl	r5,r5,0,25		/* vsid & 0x0000007fffffffff */
@@ -405,14 +414,23 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
 	xor	r28,r5,r0
 	b	4f
 
-3:	/* Calc VA and hash in r29 and r28 for 1T segment */
-	sldi	r29,r5,40		/* vsid << 40 */
-	clrldi	r3,r3,24		/* ea & 0xffffffffff */
+3:	/* Calc vpn and put it in r29 */
+	sldi	r29,r5,SID_SHIFT_1T - VPN_SHIFT
+	/*
+	 * clrldi r3,r3,64 - SID_SHIFT_1T -->  ea & 0xffffffffff
+	 * srdi	r28,r3,VPN_SHIFT
+	 */
+	rldicl  r28,r3,64 - VPN_SHIFT,64 - (SID_SHIFT_1T - VPN_SHIFT)
+	or	r29,r28,r29
+
+	/*
+	 * Calculate hash value for primary slot and
+	 * store it in r28  for 1T segment
+	 */
 	rldic	r28,r5,25,25		/* (vsid << 25) & 0x7fffffffff */
 	clrldi	r5,r5,40		/* vsid & 0xffffff */
 	rldicl	r0,r3,64-12,36		/* (ea >> 12) & 0xfffffff */
 	xor	r28,r28,r5
-	or	r29,r3,r29		/* VA */
 	xor	r28,r28,r0		/* hash */
 
 	/* Convert linux PTE bits into HW equivalents */
@@ -488,7 +506,7 @@ htab_special_pfn:
 
 	/* Call ppc_md.hpte_insert */
 	ld	r6,STK_PARAM(R4)(r1)	/* Retrieve new pp bits */
-	mr	r4,r29			/* Retrieve va */
+	mr	r4,r29			/* Retrieve vpn */
 	li	r7,0			/* !bolted, !secondary */
 	li	r8,MMU_PAGE_4K		/* page size */
 	ld	r9,STK_PARAM(R9)(r1)	/* segment size */
@@ -515,7 +533,7 @@ _GLOBAL(htab_call_hpte_insert1)
 
 	/* Call ppc_md.hpte_insert */
 	ld	r6,STK_PARAM(R4)(r1)	/* Retrieve new pp bits */
-	mr	r4,r29			/* Retrieve va */
+	mr	r4,r29			/* Retrieve vpn */
 	li	r7,HPTE_V_SECONDARY	/* !bolted, secondary */
 	li	r8,MMU_PAGE_4K		/* page size */
 	ld	r9,STK_PARAM(R9)(r1)	/* segment size */
@@ -547,7 +565,7 @@ _GLOBAL(htab_call_hpte_remove)
 	 * useless now that the segment has been switched to 4k pages.
 	 */
 htab_inval_old_hpte:
-	mr	r3,r29			/* virtual addr */
+	mr	r3,r29			/* vpn */
 	mr	r4,r31			/* PTE.pte */
 	li	r5,0			/* PTE.hidx */
 	li	r6,MMU_PAGE_64K		/* psize */
@@ -620,7 +638,7 @@ htab_modify_pte:
 	add	r3,r0,r3	/* add slot idx */
 
 	/* Call ppc_md.hpte_updatepp */
-	mr	r5,r29			/* va */
+	mr	r5,r29			/* vpn */
 	li	r6,MMU_PAGE_4K		/* page size */
 	ld	r7,STK_PARAM(R9)(r1)	/* segment size */
 	ld	r8,STK_PARAM(R8)(r1)	/* get "local" param */
@@ -676,7 +694,7 @@ _GLOBAL(__hash_page_64K)
 	/* Save non-volatile registers.
 	 * r31 will hold "old PTE"
 	 * r30 is "new PTE"
-	 * r29 is "va"
+	 * r29 is vpn
 	 * r28 is a hash value
 	 * r27 is hashtab mask (maybe dynamic patched instead ?)
 	 */
@@ -729,10 +747,10 @@ BEGIN_FTR_SECTION
 	cmpdi	r9,0			/* check segment size */
 	bne	3f
 END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
-	/* Calc va and put it in r29 */
-	rldicr	r29,r5,28,63-28
-	rldicl	r3,r3,0,36
-	or	r29,r3,r29
+	/* Calc vpn and put it in r29 */
+	sldi	r29,r5,SID_SHIFT - VPN_SHIFT
+	rldicl  r28,r3,64 - VPN_SHIFT,64 - (SID_SHIFT - VPN_SHIFT)
+	or	r29,r28,r29
 
 	/* Calculate hash value for primary slot and store it in r28 */
 	rldicl	r5,r5,0,25		/* vsid & 0x0000007fffffffff */
@@ -740,14 +758,19 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
 	xor	r28,r5,r0
 	b	4f
 
-3:	/* Calc VA and hash in r29 and r28 for 1T segment */
-	sldi	r29,r5,40		/* vsid << 40 */
-	clrldi	r3,r3,24		/* ea & 0xffffffffff */
+3:	/* Calc vpn and put it in r29 */
+	sldi	r29,r5,SID_SHIFT_1T - VPN_SHIFT
+	rldicl  r28,r3,64 - VPN_SHIFT,64 - (SID_SHIFT_1T - VPN_SHIFT)
+	or	r29,r28,r29
+
+	/*
+	 * calculate hash value for primary slot and
+	 * store it in r28 for 1T segment
+	 */
 	rldic	r28,r5,25,25		/* (vsid << 25) & 0x7fffffffff */
 	clrldi	r5,r5,40		/* vsid & 0xffffff */
 	rldicl	r0,r3,64-16,40		/* (ea >> 16) & 0xffffff */
 	xor	r28,r28,r5
-	or	r29,r3,r29		/* VA */
 	xor	r28,r28,r0		/* hash */
 
 	/* Convert linux PTE bits into HW equivalents */
@@ -806,7 +829,7 @@ ht64_insert_pte:
 
 	/* Call ppc_md.hpte_insert */
 	ld	r6,STK_PARAM(R4)(r1)	/* Retrieve new pp bits */
-	mr	r4,r29			/* Retrieve va */
+	mr	r4,r29			/* Retrieve vpn */
 	li	r7,0			/* !bolted, !secondary */
 	li	r8,MMU_PAGE_64K
 	ld	r9,STK_PARAM(R9)(r1)	/* segment size */
@@ -829,7 +852,7 @@ _GLOBAL(ht64_call_hpte_insert1)
 
 	/* Call ppc_md.hpte_insert */
 	ld	r6,STK_PARAM(R4)(r1)	/* Retrieve new pp bits */
-	mr	r4,r29			/* Retrieve va */
+	mr	r4,r29			/* Retrieve vpn */
 	li	r7,HPTE_V_SECONDARY	/* !bolted, secondary */
 	li	r8,MMU_PAGE_64K
 	ld	r9,STK_PARAM(R9)(r1)	/* segment size */
@@ -899,7 +922,7 @@ ht64_modify_pte:
 	add	r3,r0,r3	/* add slot idx */
 
 	/* Call ppc_md.hpte_updatepp */
-	mr	r5,r29			/* va */
+	mr	r5,r29			/* vpn */
 	li	r6,MMU_PAGE_64K
 	ld	r7,STK_PARAM(R9)(r1)	/* segment size */
 	ld	r8,STK_PARAM(R8)(r1)	/* get "local" param */
diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c
index 90039bc..a4a1c72 100644
--- a/arch/powerpc/mm/hash_native_64.c
+++ b/arch/powerpc/mm/hash_native_64.c
@@ -14,10 +14,10 @@
 
 #include <linux/spinlock.h>
 #include <linux/bitops.h>
+#include <linux/of.h>
 #include <linux/threads.h>
 #include <linux/smp.h>
 
-#include <asm/abs_addr.h>
 #include <asm/machdep.h>
 #include <asm/mmu.h>
 #include <asm/mmu_context.h>
@@ -39,22 +39,35 @@
 
 DEFINE_RAW_SPINLOCK(native_tlbie_lock);
 
-static inline void __tlbie(unsigned long va, int psize, int ssize)
+static inline void __tlbie(unsigned long vpn, int psize, int ssize)
 {
+	unsigned long va;
 	unsigned int penc;
 
-	/* clear top 16 bits, non SLS segment */
+	/*
+	 * We need 14 to 65 bits of va for a tlibe of 4K page
+	 * With vpn we ignore the lower VPN_SHIFT bits already.
+	 * And top two bits are already ignored because we can
+	 * only accomadate 76 bits in a 64 bit vpn with a VPN_SHIFT
+	 * of 12.
+	 */
+	va = vpn << VPN_SHIFT;
+	/*
+	 * clear top 16 bits of 64bit va, non SLS segment
+	 * Older versions of the architecture (2.02 and earler) require the
+	 * masking of the top 16 bits.
+	 */
 	va &= ~(0xffffULL << 48);
 
 	switch (psize) {
 	case MMU_PAGE_4K:
-		va &= ~0xffful;
 		va |= ssize << 8;
 		asm volatile(ASM_FTR_IFCLR("tlbie %0,0", PPC_TLBIE(%1,%0), %2)
 			     : : "r" (va), "r"(0), "i" (CPU_FTR_ARCH_206)
 			     : "memory");
 		break;
 	default:
+		/* We need 14 to 14 + i bits of va */
 		penc = mmu_psize_defs[psize].penc;
 		va &= ~((1ul << mmu_psize_defs[psize].shift) - 1);
 		va |= penc << 12;
@@ -67,21 +80,28 @@ static inline void __tlbie(unsigned long va, int psize, int ssize)
 	}
 }
 
-static inline void __tlbiel(unsigned long va, int psize, int ssize)
+static inline void __tlbiel(unsigned long vpn, int psize, int ssize)
 {
+	unsigned long va;
 	unsigned int penc;
 
-	/* clear top 16 bits, non SLS segment */
+	/* VPN_SHIFT can be atmost 12 */
+	va = vpn << VPN_SHIFT;
+	/*
+	 * clear top 16 bits of 64 bit va, non SLS segment
+	 * Older versions of the architecture (2.02 and earler) require the
+	 * masking of the top 16 bits.
+	 */
 	va &= ~(0xffffULL << 48);
 
 	switch (psize) {
 	case MMU_PAGE_4K:
-		va &= ~0xffful;
 		va |= ssize << 8;
 		asm volatile(".long 0x7c000224 | (%0 << 11) | (0 << 21)"
 			     : : "r"(va) : "memory");
 		break;
 	default:
+		/* We need 14 to 14 + i bits of va */
 		penc = mmu_psize_defs[psize].penc;
 		va &= ~((1ul << mmu_psize_defs[psize].shift) - 1);
 		va |= penc << 12;
@@ -94,7 +114,7 @@ static inline void __tlbiel(unsigned long va, int psize, int ssize)
 
 }
 
-static inline void tlbie(unsigned long va, int psize, int ssize, int local)
+static inline void tlbie(unsigned long vpn, int psize, int ssize, int local)
 {
 	unsigned int use_local = local && mmu_has_feature(MMU_FTR_TLBIEL);
 	int lock_tlbie = !mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE);
@@ -105,10 +125,10 @@ static inline void tlbie(unsigned long va, int psize, int ssize, int local)
 		raw_spin_lock(&native_tlbie_lock);
 	asm volatile("ptesync": : :"memory");
 	if (use_local) {
-		__tlbiel(va, psize, ssize);
+		__tlbiel(vpn, psize, ssize);
 		asm volatile("ptesync": : :"memory");
 	} else {
-		__tlbie(va, psize, ssize);
+		__tlbie(vpn, psize, ssize);
 		asm volatile("eieio; tlbsync; ptesync": : :"memory");
 	}
 	if (lock_tlbie && !use_local)
@@ -134,7 +154,7 @@ static inline void native_unlock_hpte(struct hash_pte *hptep)
 	clear_bit_unlock(HPTE_LOCK_BIT, word);
 }
 
-static long native_hpte_insert(unsigned long hpte_group, unsigned long va,
+static long native_hpte_insert(unsigned long hpte_group, unsigned long vpn,
 			unsigned long pa, unsigned long rflags,
 			unsigned long vflags, int psize, int ssize)
 {
@@ -143,9 +163,9 @@ static long native_hpte_insert(unsigned long hpte_group, unsigned long va,
 	int i;
 
 	if (!(vflags & HPTE_V_BOLTED)) {
-		DBG_LOW("    insert(group=%lx, va=%016lx, pa=%016lx,"
+		DBG_LOW("    insert(group=%lx, vpn=%016lx, pa=%016lx,"
 			" rflags=%lx, vflags=%lx, psize=%d)\n",
-			hpte_group, va, pa, rflags, vflags, psize);
+			hpte_group, vpn, pa, rflags, vflags, psize);
 	}
 
 	for (i = 0; i < HPTES_PER_GROUP; i++) {
@@ -163,7 +183,7 @@ static long native_hpte_insert(unsigned long hpte_group, unsigned long va,
 	if (i == HPTES_PER_GROUP)
 		return -1;
 
-	hpte_v = hpte_encode_v(va, psize, ssize) | vflags | HPTE_V_VALID;
+	hpte_v = hpte_encode_v(vpn, psize, ssize) | vflags | HPTE_V_VALID;
 	hpte_r = hpte_encode_r(pa, psize) | rflags;
 
 	if (!(vflags & HPTE_V_BOLTED)) {
@@ -225,17 +245,17 @@ static long native_hpte_remove(unsigned long hpte_group)
 }
 
 static long native_hpte_updatepp(unsigned long slot, unsigned long newpp,
-				 unsigned long va, int psize, int ssize,
+				 unsigned long vpn, int psize, int ssize,
 				 int local)
 {
 	struct hash_pte *hptep = htab_address + slot;
 	unsigned long hpte_v, want_v;
 	int ret = 0;
 
-	want_v = hpte_encode_v(va, psize, ssize);
+	want_v = hpte_encode_v(vpn, psize, ssize);
 
-	DBG_LOW("    update(va=%016lx, avpnv=%016lx, hash=%016lx, newpp=%x)",
-		va, want_v & HPTE_V_AVPN, slot, newpp);
+	DBG_LOW("    update(vpn=%016lx, avpnv=%016lx, group=%lx, newpp=%lx)",
+		vpn, want_v & HPTE_V_AVPN, slot, newpp);
 
 	native_lock_hpte(hptep);
 
@@ -254,12 +274,12 @@ static long native_hpte_updatepp(unsigned long slot, unsigned long newpp,
 	native_unlock_hpte(hptep);
 
 	/* Ensure it is out of the tlb too. */
-	tlbie(va, psize, ssize, local);
+	tlbie(vpn, psize, ssize, local);
 
 	return ret;
 }
 
-static long native_hpte_find(unsigned long va, int psize, int ssize)
+static long native_hpte_find(unsigned long vpn, int psize, int ssize)
 {
 	struct hash_pte *hptep;
 	unsigned long hash;
@@ -267,8 +287,8 @@ static long native_hpte_find(unsigned long va, int psize, int ssize)
 	long slot;
 	unsigned long want_v, hpte_v;
 
-	hash = hpt_hash(va, mmu_psize_defs[psize].shift, ssize);
-	want_v = hpte_encode_v(va, psize, ssize);
+	hash = hpt_hash(vpn, mmu_psize_defs[psize].shift, ssize);
+	want_v = hpte_encode_v(vpn, psize, ssize);
 
 	/* Bolted mappings are only ever in the primary group */
 	slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
@@ -295,14 +315,15 @@ static long native_hpte_find(unsigned long va, int psize, int ssize)
 static void native_hpte_updateboltedpp(unsigned long newpp, unsigned long ea,
 				       int psize, int ssize)
 {
-	unsigned long vsid, va;
+	unsigned long vpn;
+	unsigned long vsid;
 	long slot;
 	struct hash_pte *hptep;
 
 	vsid = get_kernel_vsid(ea, ssize);
-	va = hpt_va(ea, vsid, ssize);
+	vpn = hpt_vpn(ea, vsid, ssize);
 
-	slot = native_hpte_find(va, psize, ssize);
+	slot = native_hpte_find(vpn, psize, ssize);
 	if (slot == -1)
 		panic("could not find page to bolt\n");
 	hptep = htab_address + slot;
@@ -312,10 +333,10 @@ static void native_hpte_updateboltedpp(unsigned long newpp, unsigned long ea,
 		(newpp & (HPTE_R_PP | HPTE_R_N));
 
 	/* Ensure it is out of the tlb too. */
-	tlbie(va, psize, ssize, 0);
+	tlbie(vpn, psize, ssize, 0);
 }
 
-static void native_hpte_invalidate(unsigned long slot, unsigned long va,
+static void native_hpte_invalidate(unsigned long slot, unsigned long vpn,
 				   int psize, int ssize, int local)
 {
 	struct hash_pte *hptep = htab_address + slot;
@@ -325,9 +346,9 @@ static void native_hpte_invalidate(unsigned long slot, unsigned long va,
 
 	local_irq_save(flags);
 
-	DBG_LOW("    invalidate(va=%016lx, hash: %x)\n", va, slot);
+	DBG_LOW("    invalidate(vpn=%016lx, hash: %lx)\n", vpn, slot);
 
-	want_v = hpte_encode_v(va, psize, ssize);
+	want_v = hpte_encode_v(vpn, psize, ssize);
 	native_lock_hpte(hptep);
 	hpte_v = hptep->v;
 
@@ -339,7 +360,7 @@ static void native_hpte_invalidate(unsigned long slot, unsigned long va,
 		hptep->v = 0;
 
 	/* Invalidate the TLB */
-	tlbie(va, psize, ssize, local);
+	tlbie(vpn, psize, ssize, local);
 
 	local_irq_restore(flags);
 }
@@ -349,11 +370,12 @@ static void native_hpte_invalidate(unsigned long slot, unsigned long va,
 #define LP_MASK(i)	((0xFF >> (i)) << LP_SHIFT)
 
 static void hpte_decode(struct hash_pte *hpte, unsigned long slot,
-			int *psize, int *ssize, unsigned long *va)
+			int *psize, int *ssize, unsigned long *vpn)
 {
+	unsigned long avpn, pteg, vpi;
 	unsigned long hpte_r = hpte->r;
 	unsigned long hpte_v = hpte->v;
-	unsigned long avpn;
+	unsigned long vsid, seg_off;
 	int i, size, shift, penc;
 
 	if (!(hpte_v & HPTE_V_LARGE))
@@ -380,32 +402,38 @@ static void hpte_decode(struct hash_pte *hpte, unsigned long slot,
 	}
 
 	/* This works for all page sizes, and for 256M and 1T segments */
+	*ssize = hpte_v >> HPTE_V_SSIZE_SHIFT;
 	shift = mmu_psize_defs[size].shift;
-	avpn = (HPTE_V_AVPN_VAL(hpte_v) & ~mmu_psize_defs[size].avpnm) << 23;
-
-	if (shift < 23) {
-		unsigned long vpi, vsid, pteg;
 
-		pteg = slot / HPTES_PER_GROUP;
-		if (hpte_v & HPTE_V_SECONDARY)
-			pteg = ~pteg;
-		switch (hpte_v >> HPTE_V_SSIZE_SHIFT) {
-		case MMU_SEGSIZE_256M:
-			vpi = ((avpn >> 28) ^ pteg) & htab_hash_mask;
-			break;
-		case MMU_SEGSIZE_1T:
-			vsid = avpn >> 40;
+	avpn = (HPTE_V_AVPN_VAL(hpte_v) & ~mmu_psize_defs[size].avpnm);
+	pteg = slot / HPTES_PER_GROUP;
+	if (hpte_v & HPTE_V_SECONDARY)
+		pteg = ~pteg;
+
+	switch (*ssize) {
+	case MMU_SEGSIZE_256M:
+		/* We only have 28 - 23 bits of seg_off in avpn */
+		seg_off = (avpn & 0x1f) << 23;
+		vsid    =  avpn >> 5;
+		/* We can find more bits from the pteg value */
+		if (shift < 23) {
+			vpi = (vsid ^ pteg) & htab_hash_mask;
+			seg_off |= vpi << shift;
+		}
+		*vpn = vsid << (SID_SHIFT - VPN_SHIFT) | seg_off >> VPN_SHIFT;
+	case MMU_SEGSIZE_1T:
+		/* We only have 40 - 23 bits of seg_off in avpn */
+		seg_off = (avpn & 0x1ffff) << 23;
+		vsid    = avpn >> 17;
+		if (shift < 23) {
 			vpi = (vsid ^ (vsid << 25) ^ pteg) & htab_hash_mask;
-			break;
-		default:
-			avpn = vpi = size = 0;
+			seg_off |= vpi << shift;
 		}
-		avpn |= (vpi << mmu_psize_defs[size].shift);
+		*vpn = vsid << (SID_SHIFT_1T - VPN_SHIFT) | seg_off >> VPN_SHIFT;
+	default:
+		*vpn = size = 0;
 	}
-
-	*va = avpn;
 	*psize = size;
-	*ssize = hpte_v >> HPTE_V_SSIZE_SHIFT;
 }
 
 /*
@@ -418,9 +446,10 @@ static void hpte_decode(struct hash_pte *hpte, unsigned long slot,
  */
 static void native_hpte_clear(void)
 {
+	unsigned long vpn = 0;
 	unsigned long slot, slots, flags;
 	struct hash_pte *hptep = htab_address;
-	unsigned long hpte_v, va;
+	unsigned long hpte_v;
 	unsigned long pteg_count;
 	int psize, ssize;
 
@@ -448,9 +477,9 @@ static void native_hpte_clear(void)
 		 * already hold the native_tlbie_lock.
 		 */
 		if (hpte_v & HPTE_V_VALID) {
-			hpte_decode(hptep, slot, &psize, &ssize, &va);
+			hpte_decode(hptep, slot, &psize, &ssize, &vpn);
 			hptep->v = 0;
-			__tlbie(va, psize, ssize);
+			__tlbie(vpn, psize, ssize);
 		}
 	}
 
@@ -465,7 +494,8 @@ static void native_hpte_clear(void)
  */
 static void native_flush_hash_range(unsigned long number, int local)
 {
-	unsigned long va, hash, index, hidx, shift, slot;
+	unsigned long vpn;
+	unsigned long hash, index, hidx, shift, slot;
 	struct hash_pte *hptep;
 	unsigned long hpte_v;
 	unsigned long want_v;
@@ -479,18 +509,18 @@ static void native_flush_hash_range(unsigned long number, int local)
 	local_irq_save(flags);
 
 	for (i = 0; i < number; i++) {
-		va = batch->vaddr[i];
+		vpn = batch->vpn[i];
 		pte = batch->pte[i];
 
-		pte_iterate_hashed_subpages(pte, psize, va, index, shift) {
-			hash = hpt_hash(va, shift, ssize);
+		pte_iterate_hashed_subpages(pte, psize, vpn, index, shift) {
+			hash = hpt_hash(vpn, shift, ssize);
 			hidx = __rpte_to_hidx(pte, index);
 			if (hidx & _PTEIDX_SECONDARY)
 				hash = ~hash;
 			slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
 			slot += hidx & _PTEIDX_GROUP_IX;
 			hptep = htab_address + slot;
-			want_v = hpte_encode_v(va, psize, ssize);
+			want_v = hpte_encode_v(vpn, psize, ssize);
 			native_lock_hpte(hptep);
 			hpte_v = hptep->v;
 			if (!HPTE_V_COMPARE(hpte_v, want_v) ||
@@ -505,12 +535,12 @@ static void native_flush_hash_range(unsigned long number, int local)
 	    mmu_psize_defs[psize].tlbiel && local) {
 		asm volatile("ptesync":::"memory");
 		for (i = 0; i < number; i++) {
-			va = batch->vaddr[i];
+			vpn = batch->vpn[i];
 			pte = batch->pte[i];
 
-			pte_iterate_hashed_subpages(pte, psize, va, index,
-						    shift) {
-				__tlbiel(va, psize, ssize);
+			pte_iterate_hashed_subpages(pte, psize,
+						    vpn, index, shift) {
+				__tlbiel(vpn, psize, ssize);
 			} pte_iterate_hashed_end();
 		}
 		asm volatile("ptesync":::"memory");
@@ -522,12 +552,12 @@ static void native_flush_hash_range(unsigned long number, int local)
 
 		asm volatile("ptesync":::"memory");
 		for (i = 0; i < number; i++) {
-			va = batch->vaddr[i];
+			vpn = batch->vpn[i];
 			pte = batch->pte[i];
 
-			pte_iterate_hashed_subpages(pte, psize, va, index,
-						    shift) {
-				__tlbie(va, psize, ssize);
+			pte_iterate_hashed_subpages(pte, psize,
+						    vpn, index, shift) {
+				__tlbie(vpn, psize, ssize);
 			} pte_iterate_hashed_end();
 		}
 		asm volatile("eieio; tlbsync; ptesync":::"memory");
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c
index 377e5cb..3a292be 100644
--- a/arch/powerpc/mm/hash_utils_64.c
+++ b/arch/powerpc/mm/hash_utils_64.c
@@ -43,7 +43,6 @@
 #include <asm/uaccess.h>
 #include <asm/machdep.h>
 #include <asm/prom.h>
-#include <asm/abs_addr.h>
 #include <asm/tlbflush.h>
 #include <asm/io.h>
 #include <asm/eeh.h>
@@ -192,18 +191,18 @@ int htab_bolt_mapping(unsigned long vstart, unsigned long vend,
 	     vaddr += step, paddr += step) {
 		unsigned long hash, hpteg;
 		unsigned long vsid = get_kernel_vsid(vaddr, ssize);
-		unsigned long va = hpt_va(vaddr, vsid, ssize);
+		unsigned long vpn  = hpt_vpn(vaddr, vsid, ssize);
 		unsigned long tprot = prot;
 
 		/* Make kernel text executable */
 		if (overlaps_kernel_text(vaddr, vaddr + step))
 			tprot &= ~HPTE_R_N;
 
-		hash = hpt_hash(va, shift, ssize);
+		hash = hpt_hash(vpn, shift, ssize);
 		hpteg = ((hash & htab_hash_mask) * HPTES_PER_GROUP);
 
 		BUG_ON(!ppc_md.hpte_insert);
-		ret = ppc_md.hpte_insert(hpteg, va, paddr, tprot,
+		ret = ppc_md.hpte_insert(hpteg, vpn, paddr, tprot,
 					 HPTE_V_BOLTED, psize, ssize);
 
 		if (ret < 0)
@@ -651,7 +650,7 @@ static void __init htab_initialize(void)
 		DBG("Hash table allocated at %lx, size: %lx\n", table,
 		    htab_size_bytes);
 
-		htab_address = abs_to_virt(table);
+		htab_address = __va(table);
 
 		/* htab absolute addr + encoded htabsize */
 		_SDR1 = table + __ilog2(pteg_count) - 11;
@@ -804,16 +803,19 @@ unsigned int hash_page_do_lazy_icache(unsigned int pp, pte_t pte, int trap)
 #ifdef CONFIG_PPC_MM_SLICES
 unsigned int get_paca_psize(unsigned long addr)
 {
-	unsigned long index, slices;
+	u64 lpsizes;
+	unsigned char *hpsizes;
+	unsigned long index, mask_index;
 
 	if (addr < SLICE_LOW_TOP) {
-		slices = get_paca()->context.low_slices_psize;
+		lpsizes = get_paca()->context.low_slices_psize;
 		index = GET_LOW_SLICE_INDEX(addr);
-	} else {
-		slices = get_paca()->context.high_slices_psize;
-		index = GET_HIGH_SLICE_INDEX(addr);
+		return (lpsizes >> (index * 4)) & 0xF;
 	}
-	return (slices >> (index * 4)) & 0xF;
+	hpsizes = get_paca()->context.high_slices_psize;
+	index = GET_HIGH_SLICE_INDEX(addr);
+	mask_index = index & 0x1;
+	return (hpsizes[index >> 1] >> (mask_index * 4)) & 0xF;
 }
 
 #else
@@ -1153,21 +1155,21 @@ void hash_preload(struct mm_struct *mm, unsigned long ea,
 /* WARNING: This is called from hash_low_64.S, if you change this prototype,
  *          do not forget to update the assembly call site !
  */
-void flush_hash_page(unsigned long va, real_pte_t pte, int psize, int ssize,
+void flush_hash_page(unsigned long vpn, real_pte_t pte, int psize, int ssize,
 		     int local)
 {
 	unsigned long hash, index, shift, hidx, slot;
 
-	DBG_LOW("flush_hash_page(va=%016lx)\n", va);
-	pte_iterate_hashed_subpages(pte, psize, va, index, shift) {
-		hash = hpt_hash(va, shift, ssize);
+	DBG_LOW("flush_hash_page(vpn=%016lx)\n", vpn);
+	pte_iterate_hashed_subpages(pte, psize, vpn, index, shift) {
+		hash = hpt_hash(vpn, shift, ssize);
 		hidx = __rpte_to_hidx(pte, index);
 		if (hidx & _PTEIDX_SECONDARY)
 			hash = ~hash;
 		slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
 		slot += hidx & _PTEIDX_GROUP_IX;
 		DBG_LOW(" sub %ld: hash=%lx, hidx=%lx\n", index, slot, hidx);
-		ppc_md.hpte_invalidate(slot, va, psize, ssize, local);
+		ppc_md.hpte_invalidate(slot, vpn, psize, ssize, local);
 	} pte_iterate_hashed_end();
 }
 
@@ -1181,7 +1183,7 @@ void flush_hash_range(unsigned long number, int local)
 			&__get_cpu_var(ppc64_tlb_batch);
 
 		for (i = 0; i < number; i++)
-			flush_hash_page(batch->vaddr[i], batch->pte[i],
+			flush_hash_page(batch->vpn[i], batch->pte[i],
 					batch->psize, batch->ssize, local);
 	}
 }
@@ -1208,14 +1210,14 @@ static void kernel_map_linear_page(unsigned long vaddr, unsigned long lmi)
 {
 	unsigned long hash, hpteg;
 	unsigned long vsid = get_kernel_vsid(vaddr, mmu_kernel_ssize);
-	unsigned long va = hpt_va(vaddr, vsid, mmu_kernel_ssize);
+	unsigned long vpn = hpt_vpn(vaddr, vsid, mmu_kernel_ssize);
 	unsigned long mode = htab_convert_pte_flags(PAGE_KERNEL);
 	int ret;
 
-	hash = hpt_hash(va, PAGE_SHIFT, mmu_kernel_ssize);
+	hash = hpt_hash(vpn, PAGE_SHIFT, mmu_kernel_ssize);
 	hpteg = ((hash & htab_hash_mask) * HPTES_PER_GROUP);
 
-	ret = ppc_md.hpte_insert(hpteg, va, __pa(vaddr),
+	ret = ppc_md.hpte_insert(hpteg, vpn, __pa(vaddr),
 				 mode, HPTE_V_BOLTED,
 				 mmu_linear_psize, mmu_kernel_ssize);
 	BUG_ON (ret < 0);
@@ -1229,9 +1231,9 @@ static void kernel_unmap_linear_page(unsigned long vaddr, unsigned long lmi)
 {
 	unsigned long hash, hidx, slot;
 	unsigned long vsid = get_kernel_vsid(vaddr, mmu_kernel_ssize);
-	unsigned long va = hpt_va(vaddr, vsid, mmu_kernel_ssize);
+	unsigned long vpn = hpt_vpn(vaddr, vsid, mmu_kernel_ssize);
 
-	hash = hpt_hash(va, PAGE_SHIFT, mmu_kernel_ssize);
+	hash = hpt_hash(vpn, PAGE_SHIFT, mmu_kernel_ssize);
 	spin_lock(&linear_map_hash_lock);
 	BUG_ON(!(linear_map_hash_slots[lmi] & 0x80));
 	hidx = linear_map_hash_slots[lmi] & 0x7f;
@@ -1241,7 +1243,7 @@ static void kernel_unmap_linear_page(unsigned long vaddr, unsigned long lmi)
 		hash = ~hash;
 	slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
 	slot += hidx & _PTEIDX_GROUP_IX;
-	ppc_md.hpte_invalidate(slot, va, mmu_linear_psize, mmu_kernel_ssize, 0);
+	ppc_md.hpte_invalidate(slot, vpn, mmu_linear_psize, mmu_kernel_ssize, 0);
 }
 
 void kernel_map_pages(struct page *page, int numpages, int enable)
diff --git a/arch/powerpc/mm/hugetlbpage-hash64.c b/arch/powerpc/mm/hugetlbpage-hash64.c
index cc5c273..cecad34 100644
--- a/arch/powerpc/mm/hugetlbpage-hash64.c
+++ b/arch/powerpc/mm/hugetlbpage-hash64.c
@@ -18,14 +18,15 @@ int __hash_page_huge(unsigned long ea, unsigned long access, unsigned long vsid,
 		     pte_t *ptep, unsigned long trap, int local, int ssize,
 		     unsigned int shift, unsigned int mmu_psize)
 {
+	unsigned long vpn;
 	unsigned long old_pte, new_pte;
-	unsigned long va, rflags, pa, sz;
+	unsigned long rflags, pa, sz;
 	long slot;
 
 	BUG_ON(shift != mmu_psize_defs[mmu_psize].shift);
 
 	/* Search the Linux page table for a match with va */
-	va = hpt_va(ea, vsid, ssize);
+	vpn = hpt_vpn(ea, vsid, ssize);
 
 	/* At this point, we have a pte (old_pte) which can be used to build
 	 * or update an HPTE. There are 2 cases:
@@ -69,19 +70,19 @@ int __hash_page_huge(unsigned long ea, unsigned long access, unsigned long vsid,
 		/* There MIGHT be an HPTE for this pte */
 		unsigned long hash, slot;
 
-		hash = hpt_hash(va, shift, ssize);
+		hash = hpt_hash(vpn, shift, ssize);
 		if (old_pte & _PAGE_F_SECOND)
 			hash = ~hash;
 		slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
 		slot += (old_pte & _PAGE_F_GIX) >> 12;
 
-		if (ppc_md.hpte_updatepp(slot, rflags, va, mmu_psize,
+		if (ppc_md.hpte_updatepp(slot, rflags, vpn, mmu_psize,
 					 ssize, local) == -1)
 			old_pte &= ~_PAGE_HPTEFLAGS;
 	}
 
 	if (likely(!(old_pte & _PAGE_HASHPTE))) {
-		unsigned long hash = hpt_hash(va, shift, ssize);
+		unsigned long hash = hpt_hash(vpn, shift, ssize);
 		unsigned long hpte_group;
 
 		pa = pte_pfn(__pte(old_pte)) << PAGE_SHIFT;
@@ -101,14 +102,14 @@ repeat:
 				      _PAGE_COHERENT | _PAGE_GUARDED));
 
 		/* Insert into the hash table, primary slot */
-		slot = ppc_md.hpte_insert(hpte_group, va, pa, rflags, 0,
+		slot = ppc_md.hpte_insert(hpte_group, vpn, pa, rflags, 0,
 					  mmu_psize, ssize);
 
 		/* Primary is full, try the secondary */
 		if (unlikely(slot == -1)) {
 			hpte_group = ((~hash & htab_hash_mask) *
 				      HPTES_PER_GROUP) & ~0x7UL;
-			slot = ppc_md.hpte_insert(hpte_group, va, pa, rflags,
+			slot = ppc_md.hpte_insert(hpte_group, vpn, pa, rflags,
 						  HPTE_V_SECONDARY,
 						  mmu_psize, ssize);
 			if (slot == -1) {
diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c
index 620b7ac..95a4529 100644
--- a/arch/powerpc/mm/init_64.c
+++ b/arch/powerpc/mm/init_64.c
@@ -62,7 +62,6 @@
 #include <asm/cputable.h>
 #include <asm/sections.h>
 #include <asm/iommu.h>
-#include <asm/abs_addr.h>
 #include <asm/vdso.h>
 
 #include "mmu_decl.h"
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c
index fbdad0e..0dba506 100644
--- a/arch/powerpc/mm/mem.c
+++ b/arch/powerpc/mm/mem.c
@@ -62,7 +62,7 @@
 
 int init_bootmem_done;
 int mem_init_done;
-phys_addr_t memory_limit;
+unsigned long long memory_limit;
 
 #ifdef CONFIG_HIGHMEM
 pte_t *kmap_pte;
@@ -300,8 +300,7 @@ void __init mem_init(void)
 	unsigned long reservedpages = 0, codesize, initsize, datasize, bsssize;
 
 #ifdef CONFIG_SWIOTLB
-	if (ppc_swiotlb_enable)
-		swiotlb_init(1);
+	swiotlb_init(0);
 #endif
 
 	num_physpages = memblock_phys_mem_size() >> PAGE_SHIFT;
diff --git a/arch/powerpc/mm/mmu_context_hash64.c b/arch/powerpc/mm/mmu_context_hash64.c
index 40677aa..40bc5b0 100644
--- a/arch/powerpc/mm/mmu_context_hash64.c
+++ b/arch/powerpc/mm/mmu_context_hash64.c
@@ -30,11 +30,13 @@ static DEFINE_SPINLOCK(mmu_context_lock);
 static DEFINE_IDA(mmu_context_ida);
 
 /*
- * The proto-VSID space has 2^35 - 1 segments available for user mappings.
- * Each segment contains 2^28 bytes.  Each context maps 2^44 bytes,
- * so we can support 2^19-1 contexts (19 == 35 + 28 - 44).
+ * 256MB segment
+ * The proto-VSID space has 2^(CONTEX_BITS + USER_ESID_BITS) - 1 segments
+ * available for user mappings. Each segment contains 2^28 bytes. Each
+ * context maps 2^46 bytes (64TB) so we can support 2^19-1 contexts
+ * (19 == 37 + 28 - 46).
  */
-#define MAX_CONTEXT	((1UL << 19) - 1)
+#define MAX_CONTEXT	((1UL << CONTEXT_BITS) - 1)
 
 int __init_new_context(void)
 {
diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c
index 249a063..e212a27 100644
--- a/arch/powerpc/mm/pgtable_64.c
+++ b/arch/powerpc/mm/pgtable_64.c
@@ -51,13 +51,22 @@
 #include <asm/processor.h>
 #include <asm/cputable.h>
 #include <asm/sections.h>
-#include <asm/abs_addr.h>
 #include <asm/firmware.h>
 
 #include "mmu_decl.h"
 
-unsigned long ioremap_bot = IOREMAP_BASE;
+/* Some sanity checking */
+#if TASK_SIZE_USER64 > PGTABLE_RANGE
+#error TASK_SIZE_USER64 exceeds pagetable range
+#endif
+
+#ifdef CONFIG_PPC_STD_MMU_64
+#if TASK_SIZE_USER64 > (1UL << (USER_ESID_BITS + SID_SHIFT))
+#error TASK_SIZE_USER64 exceeds user VSID range
+#endif
+#endif
 
+unsigned long ioremap_bot = IOREMAP_BASE;
 
 #ifdef CONFIG_PPC_MMU_NOHASH
 static void *early_alloc_pgtable(unsigned long size)
diff --git a/arch/powerpc/mm/slb_low.S b/arch/powerpc/mm/slb_low.S
index b9ee79ce..1a16ca2 100644
--- a/arch/powerpc/mm/slb_low.S
+++ b/arch/powerpc/mm/slb_low.S
@@ -56,6 +56,12 @@ _GLOBAL(slb_allocate_realmode)
 	 */
 _GLOBAL(slb_miss_kernel_load_linear)
 	li	r11,0
+	li	r9,0x1
+	/*
+	 * for 1T we shift 12 bits more.  slb_finish_load_1T will do
+	 * the necessary adjustment
+	 */
+	rldimi  r10,r9,(CONTEXT_BITS + USER_ESID_BITS),0
 BEGIN_FTR_SECTION
 	b	slb_finish_load
 END_MMU_FTR_SECTION_IFCLR(MMU_FTR_1T_SEGMENT)
@@ -85,6 +91,12 @@ _GLOBAL(slb_miss_kernel_load_vmemmap)
 	_GLOBAL(slb_miss_kernel_load_io)
 	li	r11,0
 6:
+	li	r9,0x1
+	/*
+	 * for 1T we shift 12 bits more.  slb_finish_load_1T will do
+	 * the necessary adjustment
+	 */
+	rldimi  r10,r9,(CONTEXT_BITS + USER_ESID_BITS),0
 BEGIN_FTR_SECTION
 	b	slb_finish_load
 END_MMU_FTR_SECTION_IFCLR(MMU_FTR_1T_SEGMENT)
@@ -108,17 +120,31 @@ END_MMU_FTR_SECTION_IFCLR(MMU_FTR_1T_SEGMENT)
 	 * between 4k and 64k standard page size
 	 */
 #ifdef CONFIG_PPC_MM_SLICES
+	/* r10 have esid */
 	cmpldi	r10,16
-
-	/* Get the slice index * 4 in r11 and matching slice size mask in r9 */
-	ld	r9,PACALOWSLICESPSIZE(r13)
-	sldi	r11,r10,2
+	/* below SLICE_LOW_TOP */
 	blt	5f
-	ld	r9,PACAHIGHSLICEPSIZE(r13)
-	srdi	r11,r10,(SLICE_HIGH_SHIFT - SLICE_LOW_SHIFT - 2)
-	andi.	r11,r11,0x3c
+	/*
+	 * Handle hpsizes,
+	 * r9 is get_paca()->context.high_slices_psize[index], r11 is mask_index
+	 */
+	srdi    r11,r10,(SLICE_HIGH_SHIFT - SLICE_LOW_SHIFT + 1) /* index */
+	addi	r9,r11,PACAHIGHSLICEPSIZE
+	lbzx	r9,r13,r9		/* r9 is hpsizes[r11] */
+	/* r11 = (r10 >> (SLICE_HIGH_SHIFT - SLICE_LOW_SHIFT)) & 0x1 */
+	rldicl	r11,r10,(64 - (SLICE_HIGH_SHIFT - SLICE_LOW_SHIFT)),63
+	b	6f
 
-5:	/* Extract the psize and multiply to get an array offset */
+5:
+	/*
+	 * Handle lpsizes
+	 * r9 is get_paca()->context.low_slices_psize, r11 is index
+	 */
+	ld	r9,PACALOWSLICESPSIZE(r13)
+	mr	r11,r10
+6:
+	sldi	r11,r11,2  /* index * 4 */
+	/* Extract the psize and multiply to get an array offset */
 	srd	r9,r9,r11
 	andi.	r9,r9,0xf
 	mulli	r9,r9,MMUPSIZEDEFSIZE
@@ -209,7 +235,11 @@ _GLOBAL(slb_allocate_user)
  */
 slb_finish_load:
 	ASM_VSID_SCRAMBLE(r10,r9,256M)
-	rldimi	r11,r10,SLB_VSID_SHIFT,16	/* combine VSID and flags */
+	/*
+	 * bits above VSID_BITS_256M need to be ignored from r10
+	 * also combine VSID and flags
+	 */
+	rldimi	r11,r10,SLB_VSID_SHIFT,(64 - (SLB_VSID_SHIFT + VSID_BITS_256M))
 
 	/* r3 = EA, r11 = VSID data */
 	/*
@@ -252,10 +282,10 @@ _GLOBAL(slb_compare_rr_to_size)
 	bge	1f
 
 	/* still room in the slb cache */
-	sldi	r11,r3,1		/* r11 = offset * sizeof(u16) */
-	rldicl	r10,r10,36,28		/* get low 16 bits of the ESID */
-	add	r11,r11,r13		/* r11 = (u16 *)paca + offset */
-	sth	r10,PACASLBCACHE(r11)	/* paca->slb_cache[offset] = esid */
+	sldi	r11,r3,2		/* r11 = offset * sizeof(u32) */
+	srdi    r10,r10,28		/* get the 36 bits of the ESID */
+	add	r11,r11,r13		/* r11 = (u32 *)paca + offset */
+	stw	r10,PACASLBCACHE(r11)	/* paca->slb_cache[offset] = esid */
 	addi	r3,r3,1			/* offset++ */
 	b	2f
 1:					/* offset >= SLB_CACHE_ENTRIES */
@@ -273,7 +303,11 @@ _GLOBAL(slb_compare_rr_to_size)
 slb_finish_load_1T:
 	srdi	r10,r10,40-28		/* get 1T ESID */
 	ASM_VSID_SCRAMBLE(r10,r9,1T)
-	rldimi	r11,r10,SLB_VSID_SHIFT_1T,16	/* combine VSID and flags */
+	/*
+	 * bits above VSID_BITS_1T need to be ignored from r10
+	 * also combine VSID and flags
+	 */
+	rldimi	r11,r10,SLB_VSID_SHIFT_1T,(64 - (SLB_VSID_SHIFT_1T + VSID_BITS_1T))
 	li	r10,MMU_SEGSIZE_1T
 	rldimi	r11,r10,SLB_VSID_SSIZE_SHIFT,0	/* insert segment size */
 
diff --git a/arch/powerpc/mm/slice.c b/arch/powerpc/mm/slice.c
index 73709f7..5829d2a 100644
--- a/arch/powerpc/mm/slice.c
+++ b/arch/powerpc/mm/slice.c
@@ -34,6 +34,11 @@
 #include <asm/mmu.h>
 #include <asm/spu.h>
 
+/* some sanity checks */
+#if (PGTABLE_RANGE >> 43) > SLICE_MASK_SIZE
+#error PGTABLE_RANGE exceeds slice_mask high_slices size
+#endif
+
 static DEFINE_SPINLOCK(slice_convert_lock);
 
 
@@ -42,7 +47,7 @@ int _slice_debug = 1;
 
 static void slice_print_mask(const char *label, struct slice_mask mask)
 {
-	char	*p, buf[16 + 3 + 16 + 1];
+	char	*p, buf[16 + 3 + 64 + 1];
 	int	i;
 
 	if (!_slice_debug)
@@ -54,7 +59,7 @@ static void slice_print_mask(const char *label, struct slice_mask mask)
 	*(p++) = '-';
 	*(p++) = ' ';
 	for (i = 0; i < SLICE_NUM_HIGH; i++)
-		*(p++) = (mask.high_slices & (1 << i)) ? '1' : '0';
+		*(p++) = (mask.high_slices & (1ul << i)) ? '1' : '0';
 	*(p++) = 0;
 
 	printk(KERN_DEBUG "%s:%s\n", label, buf);
@@ -84,8 +89,8 @@ static struct slice_mask slice_range_to_mask(unsigned long start,
 	}
 
 	if ((start + len) > SLICE_LOW_TOP)
-		ret.high_slices = (1u << (GET_HIGH_SLICE_INDEX(end) + 1))
-			- (1u << GET_HIGH_SLICE_INDEX(start));
+		ret.high_slices = (1ul << (GET_HIGH_SLICE_INDEX(end) + 1))
+			- (1ul << GET_HIGH_SLICE_INDEX(start));
 
 	return ret;
 }
@@ -135,26 +140,31 @@ static struct slice_mask slice_mask_for_free(struct mm_struct *mm)
 
 	for (i = 0; i < SLICE_NUM_HIGH; i++)
 		if (!slice_high_has_vma(mm, i))
-			ret.high_slices |= 1u << i;
+			ret.high_slices |= 1ul << i;
 
 	return ret;
 }
 
 static struct slice_mask slice_mask_for_size(struct mm_struct *mm, int psize)
 {
+	unsigned char *hpsizes;
+	int index, mask_index;
 	struct slice_mask ret = { 0, 0 };
 	unsigned long i;
-	u64 psizes;
+	u64 lpsizes;
 
-	psizes = mm->context.low_slices_psize;
+	lpsizes = mm->context.low_slices_psize;
 	for (i = 0; i < SLICE_NUM_LOW; i++)
-		if (((psizes >> (i * 4)) & 0xf) == psize)
+		if (((lpsizes >> (i * 4)) & 0xf) == psize)
 			ret.low_slices |= 1u << i;
 
-	psizes = mm->context.high_slices_psize;
-	for (i = 0; i < SLICE_NUM_HIGH; i++)
-		if (((psizes >> (i * 4)) & 0xf) == psize)
-			ret.high_slices |= 1u << i;
+	hpsizes = mm->context.high_slices_psize;
+	for (i = 0; i < SLICE_NUM_HIGH; i++) {
+		mask_index = i & 0x1;
+		index = i >> 1;
+		if (((hpsizes[index] >> (mask_index * 4)) & 0xf) == psize)
+			ret.high_slices |= 1ul << i;
+	}
 
 	return ret;
 }
@@ -183,8 +193,10 @@ static void slice_flush_segments(void *parm)
 
 static void slice_convert(struct mm_struct *mm, struct slice_mask mask, int psize)
 {
+	int index, mask_index;
 	/* Write the new slice psize bits */
-	u64 lpsizes, hpsizes;
+	unsigned char *hpsizes;
+	u64 lpsizes;
 	unsigned long i, flags;
 
 	slice_dbg("slice_convert(mm=%p, psize=%d)\n", mm, psize);
@@ -201,14 +213,18 @@ static void slice_convert(struct mm_struct *mm, struct slice_mask mask, int psiz
 			lpsizes = (lpsizes & ~(0xful << (i * 4))) |
 				(((unsigned long)psize) << (i * 4));
 
-	hpsizes = mm->context.high_slices_psize;
-	for (i = 0; i < SLICE_NUM_HIGH; i++)
-		if (mask.high_slices & (1u << i))
-			hpsizes = (hpsizes & ~(0xful << (i * 4))) |
-				(((unsigned long)psize) << (i * 4));
-
+	/* Assign the value back */
 	mm->context.low_slices_psize = lpsizes;
-	mm->context.high_slices_psize = hpsizes;
+
+	hpsizes = mm->context.high_slices_psize;
+	for (i = 0; i < SLICE_NUM_HIGH; i++) {
+		mask_index = i & 0x1;
+		index = i >> 1;
+		if (mask.high_slices & (1ul << i))
+			hpsizes[index] = (hpsizes[index] &
+					  ~(0xf << (mask_index * 4))) |
+				(((unsigned long)psize) << (mask_index * 4));
+	}
 
 	slice_dbg(" lsps=%lx, hsps=%lx\n",
 		  mm->context.low_slices_psize,
@@ -587,18 +603,19 @@ unsigned long arch_get_unmapped_area_topdown(struct file *filp,
 
 unsigned int get_slice_psize(struct mm_struct *mm, unsigned long addr)
 {
-	u64 psizes;
-	int index;
+	unsigned char *hpsizes;
+	int index, mask_index;
 
 	if (addr < SLICE_LOW_TOP) {
-		psizes = mm->context.low_slices_psize;
+		u64 lpsizes;
+		lpsizes = mm->context.low_slices_psize;
 		index = GET_LOW_SLICE_INDEX(addr);
-	} else {
-		psizes = mm->context.high_slices_psize;
-		index = GET_HIGH_SLICE_INDEX(addr);
+		return (lpsizes >> (index * 4)) & 0xf;
 	}
-
-	return (psizes >> (index * 4)) & 0xf;
+	hpsizes = mm->context.high_slices_psize;
+	index = GET_HIGH_SLICE_INDEX(addr);
+	mask_index = index & 0x1;
+	return (hpsizes[index >> 1] >> (mask_index * 4)) & 0xf;
 }
 EXPORT_SYMBOL_GPL(get_slice_psize);
 
@@ -618,7 +635,9 @@ EXPORT_SYMBOL_GPL(get_slice_psize);
  */
 void slice_set_user_psize(struct mm_struct *mm, unsigned int psize)
 {
-	unsigned long flags, lpsizes, hpsizes;
+	int index, mask_index;
+	unsigned char *hpsizes;
+	unsigned long flags, lpsizes;
 	unsigned int old_psize;
 	int i;
 
@@ -639,15 +658,21 @@ void slice_set_user_psize(struct mm_struct *mm, unsigned int psize)
 		if (((lpsizes >> (i * 4)) & 0xf) == old_psize)
 			lpsizes = (lpsizes & ~(0xful << (i * 4))) |
 				(((unsigned long)psize) << (i * 4));
+	/* Assign the value back */
+	mm->context.low_slices_psize = lpsizes;
 
 	hpsizes = mm->context.high_slices_psize;
-	for (i = 0; i < SLICE_NUM_HIGH; i++)
-		if (((hpsizes >> (i * 4)) & 0xf) == old_psize)
-			hpsizes = (hpsizes & ~(0xful << (i * 4))) |
-				(((unsigned long)psize) << (i * 4));
+	for (i = 0; i < SLICE_NUM_HIGH; i++) {
+		mask_index = i & 0x1;
+		index = i >> 1;
+		if (((hpsizes[index] >> (mask_index * 4)) & 0xf) == old_psize)
+			hpsizes[index] = (hpsizes[index] &
+					  ~(0xf << (mask_index * 4))) |
+				(((unsigned long)psize) << (mask_index * 4));
+	}
+
+
 
-	mm->context.low_slices_psize = lpsizes;
-	mm->context.high_slices_psize = hpsizes;
 
 	slice_dbg(" lsps=%lx, hsps=%lx\n",
 		  mm->context.low_slices_psize,
@@ -660,18 +685,27 @@ void slice_set_user_psize(struct mm_struct *mm, unsigned int psize)
 void slice_set_psize(struct mm_struct *mm, unsigned long address,
 		     unsigned int psize)
 {
+	unsigned char *hpsizes;
 	unsigned long i, flags;
-	u64 *p;
+	u64 *lpsizes;
 
 	spin_lock_irqsave(&slice_convert_lock, flags);
 	if (address < SLICE_LOW_TOP) {
 		i = GET_LOW_SLICE_INDEX(address);
-		p = &mm->context.low_slices_psize;
+		lpsizes = &mm->context.low_slices_psize;
+		*lpsizes = (*lpsizes & ~(0xful << (i * 4))) |
+			((unsigned long) psize << (i * 4));
 	} else {
+		int index, mask_index;
 		i = GET_HIGH_SLICE_INDEX(address);
-		p = &mm->context.high_slices_psize;
+		hpsizes = mm->context.high_slices_psize;
+		mask_index = i & 0x1;
+		index = i >> 1;
+		hpsizes[index] = (hpsizes[index] &
+				  ~(0xf << (mask_index * 4))) |
+			(((unsigned long)psize) << (mask_index * 4));
 	}
-	*p = (*p & ~(0xful << (i * 4))) | ((unsigned long) psize << (i * 4));
+
 	spin_unlock_irqrestore(&slice_convert_lock, flags);
 
 #ifdef CONFIG_SPU_BASE
diff --git a/arch/powerpc/mm/stab.c b/arch/powerpc/mm/stab.c
index 9106ebb..3f8efa6 100644
--- a/arch/powerpc/mm/stab.c
+++ b/arch/powerpc/mm/stab.c
@@ -20,7 +20,6 @@
 #include <asm/paca.h>
 #include <asm/cputable.h>
 #include <asm/prom.h>
-#include <asm/abs_addr.h>
 
 struct stab_entry {
 	unsigned long esid_data;
@@ -257,7 +256,7 @@ void __init stabs_alloc(void)
 		memset((void *)newstab, 0, HW_PAGE_SIZE);
 
 		paca[cpu].stab_addr = newstab;
-		paca[cpu].stab_real = virt_to_abs(newstab);
+		paca[cpu].stab_real = __pa(newstab);
 		printk(KERN_INFO "Segment table for CPU %d at 0x%llx "
 		       "virtual, 0x%llx absolute\n",
 		       cpu, paca[cpu].stab_addr, paca[cpu].stab_real);
diff --git a/arch/powerpc/mm/subpage-prot.c b/arch/powerpc/mm/subpage-prot.c
index e4f8f1f..7c415dd 100644
--- a/arch/powerpc/mm/subpage-prot.c
+++ b/arch/powerpc/mm/subpage-prot.c
@@ -95,7 +95,8 @@ static void subpage_prot_clear(unsigned long addr, unsigned long len)
 	struct mm_struct *mm = current->mm;
 	struct subpage_prot_table *spt = &mm->context.spt;
 	u32 **spm, *spp;
-	int i, nw;
+	unsigned long i;
+	size_t nw;
 	unsigned long next, limit;
 
 	down_write(&mm->mmap_sem);
@@ -144,7 +145,8 @@ long sys_subpage_prot(unsigned long addr, unsigned long len, u32 __user *map)
 	struct mm_struct *mm = current->mm;
 	struct subpage_prot_table *spt = &mm->context.spt;
 	u32 **spm, *spp;
-	int i, nw;
+	unsigned long i;
+	size_t nw;
 	unsigned long next, limit;
 	int err;
 
diff --git a/arch/powerpc/mm/tlb_hash64.c b/arch/powerpc/mm/tlb_hash64.c
index 31f1820..ae758b3 100644
--- a/arch/powerpc/mm/tlb_hash64.c
+++ b/arch/powerpc/mm/tlb_hash64.c
@@ -42,8 +42,9 @@ DEFINE_PER_CPU(struct ppc64_tlb_batch, ppc64_tlb_batch);
 void hpte_need_flush(struct mm_struct *mm, unsigned long addr,
 		     pte_t *ptep, unsigned long pte, int huge)
 {
+	unsigned long vpn;
 	struct ppc64_tlb_batch *batch = &get_cpu_var(ppc64_tlb_batch);
-	unsigned long vsid, vaddr;
+	unsigned long vsid;
 	unsigned int psize;
 	int ssize;
 	real_pte_t rpte;
@@ -86,7 +87,7 @@ void hpte_need_flush(struct mm_struct *mm, unsigned long addr,
 		vsid = get_kernel_vsid(addr, mmu_kernel_ssize);
 		ssize = mmu_kernel_ssize;
 	}
-	vaddr = hpt_va(addr, vsid, ssize);
+	vpn = hpt_vpn(addr, vsid, ssize);
 	rpte = __real_pte(__pte(pte), ptep);
 
 	/*
@@ -96,7 +97,7 @@ void hpte_need_flush(struct mm_struct *mm, unsigned long addr,
 	 * and decide to use local invalidates instead...
 	 */
 	if (!batch->active) {
-		flush_hash_page(vaddr, rpte, psize, ssize, 0);
+		flush_hash_page(vpn, rpte, psize, ssize, 0);
 		put_cpu_var(ppc64_tlb_batch);
 		return;
 	}
@@ -122,7 +123,7 @@ void hpte_need_flush(struct mm_struct *mm, unsigned long addr,
 		batch->ssize = ssize;
 	}
 	batch->pte[i] = rpte;
-	batch->vaddr[i] = vaddr;
+	batch->vpn[i] = vpn;
 	batch->index = ++i;
 	if (i >= PPC64_TLB_BATCH_NR)
 		__flush_tlb_pending(batch);
@@ -146,7 +147,7 @@ void __flush_tlb_pending(struct ppc64_tlb_batch *batch)
 	if (cpumask_equal(mm_cpumask(batch->mm), tmp))
 		local = 1;
 	if (i == 1)
-		flush_hash_page(batch->vaddr[0], batch->pte[0],
+		flush_hash_page(batch->vpn[0], batch->pte[0],
 				batch->psize, batch->ssize, local);
 	else
 		flush_hash_range(i, local);
diff --git a/arch/powerpc/mm/tlb_low_64e.S b/arch/powerpc/mm/tlb_low_64e.S
index f09d48e..b4113bf 100644
--- a/arch/powerpc/mm/tlb_low_64e.S
+++ b/arch/powerpc/mm/tlb_low_64e.S
@@ -20,6 +20,8 @@
 #include <asm/pgtable.h>
 #include <asm/exception-64e.h>
 #include <asm/ppc-opcode.h>
+#include <asm/kvm_asm.h>
+#include <asm/kvm_booke_hv_asm.h>
 
 #ifdef CONFIG_PPC_64K_PAGES
 #define VPTE_PMD_SHIFT	(PTE_INDEX_SIZE+1)
@@ -37,12 +39,18 @@
  *                                                                    *
  **********************************************************************/
 
-.macro tlb_prolog_bolted addr
-	mtspr	SPRN_SPRG_TLB_SCRATCH,r13
+.macro tlb_prolog_bolted intnum addr
+	mtspr	SPRN_SPRG_GEN_SCRATCH,r13
 	mfspr	r13,SPRN_SPRG_PACA
 	std	r10,PACA_EXTLB+EX_TLB_R10(r13)
 	mfcr	r10
 	std	r11,PACA_EXTLB+EX_TLB_R11(r13)
+#ifdef CONFIG_KVM_BOOKE_HV
+BEGIN_FTR_SECTION
+	mfspr	r11, SPRN_SRR1
+END_FTR_SECTION_IFSET(CPU_FTR_EMB_HV)
+#endif
+	DO_KVM	\intnum, SPRN_SRR1
 	std	r16,PACA_EXTLB+EX_TLB_R16(r13)
 	mfspr	r16,\addr		/* get faulting address */
 	std	r14,PACA_EXTLB+EX_TLB_R14(r13)
@@ -61,12 +69,12 @@
 	ld	r15,PACA_EXTLB+EX_TLB_R15(r13)
 	TLB_MISS_RESTORE_STATS_BOLTED
 	ld	r16,PACA_EXTLB+EX_TLB_R16(r13)
-	mfspr	r13,SPRN_SPRG_TLB_SCRATCH
+	mfspr	r13,SPRN_SPRG_GEN_SCRATCH
 .endm
 
 /* Data TLB miss */
 	START_EXCEPTION(data_tlb_miss_bolted)
-	tlb_prolog_bolted SPRN_DEAR
+	tlb_prolog_bolted BOOKE_INTERRUPT_DTLB_MISS SPRN_DEAR
 
 	/* We need _PAGE_PRESENT and  _PAGE_ACCESSED set */
 
@@ -214,7 +222,7 @@ itlb_miss_fault_bolted:
 
 /* Instruction TLB miss */
 	START_EXCEPTION(instruction_tlb_miss_bolted)
-	tlb_prolog_bolted SPRN_SRR0
+	tlb_prolog_bolted BOOKE_INTERRUPT_ITLB_MISS SPRN_SRR0
 
 	rldicl.	r10,r16,64-PGTABLE_EADDR_SIZE,PGTABLE_EADDR_SIZE+4
 	srdi	r15,r16,60		/* get region */
diff --git a/arch/powerpc/oprofile/cell/spu_task_sync.c b/arch/powerpc/oprofile/cell/spu_task_sync.c
index 642fca1..28f1af2 100644
--- a/arch/powerpc/oprofile/cell/spu_task_sync.c
+++ b/arch/powerpc/oprofile/cell/spu_task_sync.c
@@ -304,7 +304,7 @@ static inline unsigned long fast_get_dcookie(struct path *path)
 	return cookie;
 }
 
-/* Look up the dcookie for the task's first VM_EXECUTABLE mapping,
+/* Look up the dcookie for the task's mm->exe_file,
  * which corresponds loosely to "application name". Also, determine
  * the offset for the SPU ELF object.  If computed offset is
  * non-zero, it implies an embedded SPU object; otherwise, it's a
@@ -321,7 +321,6 @@ get_exec_dcookie_and_offset(struct spu *spu, unsigned int *offsetp,
 {
 	unsigned long app_cookie = 0;
 	unsigned int my_offset = 0;
-	struct file *app = NULL;
 	struct vm_area_struct *vma;
 	struct mm_struct *mm = spu->mm;
 
@@ -330,16 +329,10 @@ get_exec_dcookie_and_offset(struct spu *spu, unsigned int *offsetp,
 
 	down_read(&mm->mmap_sem);
 
-	for (vma = mm->mmap; vma; vma = vma->vm_next) {
-		if (!vma->vm_file)
-			continue;
-		if (!(vma->vm_flags & VM_EXECUTABLE))
-			continue;
-		app_cookie = fast_get_dcookie(&vma->vm_file->f_path);
+	if (mm->exe_file) {
+		app_cookie = fast_get_dcookie(&mm->exe_file->f_path);
 		pr_debug("got dcookie for %s\n",
-			 vma->vm_file->f_dentry->d_name.name);
-		app = vma->vm_file;
-		break;
+			 mm->exe_file->f_dentry->d_name.name);
 	}
 
 	for (vma = mm->mmap; vma; vma = vma->vm_next) {
diff --git a/arch/powerpc/oprofile/op_model_power4.c b/arch/powerpc/oprofile/op_model_power4.c
index 95ae77d..315f949 100644
--- a/arch/powerpc/oprofile/op_model_power4.c
+++ b/arch/powerpc/oprofile/op_model_power4.c
@@ -21,6 +21,13 @@
 #include <asm/reg.h>
 
 #define dbg(args...)
+#define OPROFILE_PM_PMCSEL_MSK      0xffULL
+#define OPROFILE_PM_UNIT_SHIFT      60
+#define OPROFILE_PM_UNIT_MSK        0xfULL
+#define OPROFILE_MAX_PMC_NUM        3
+#define OPROFILE_PMSEL_FIELD_WIDTH  8
+#define OPROFILE_UNIT_FIELD_WIDTH   4
+#define MMCRA_SIAR_VALID_MASK       0x10000000ULL
 
 static unsigned long reset_value[OP_MAX_COUNTER];
 
@@ -31,6 +38,61 @@ static int use_slot_nums;
 static u32 mmcr0_val;
 static u64 mmcr1_val;
 static u64 mmcra_val;
+static u32 cntr_marked_events;
+
+static int power7_marked_instr_event(u64 mmcr1)
+{
+	u64 psel, unit;
+	int pmc, cntr_marked_events = 0;
+
+	/* Given the MMCR1 value, look at the field for each counter to
+	 * determine if it is a marked event.  Code based on the function
+	 * power7_marked_instr_event() in file arch/powerpc/perf/power7-pmu.c.
+	 */
+	for (pmc = 0; pmc < 4; pmc++) {
+		psel = mmcr1 & (OPROFILE_PM_PMCSEL_MSK
+				<< (OPROFILE_MAX_PMC_NUM - pmc)
+				* OPROFILE_MAX_PMC_NUM);
+		psel = (psel >> ((OPROFILE_MAX_PMC_NUM - pmc)
+				 * OPROFILE_PMSEL_FIELD_WIDTH)) & ~1ULL;
+		unit = mmcr1 & (OPROFILE_PM_UNIT_MSK
+				<< (OPROFILE_PM_UNIT_SHIFT
+				    - (pmc * OPROFILE_PMSEL_FIELD_WIDTH )));
+		unit = unit >> (OPROFILE_PM_UNIT_SHIFT
+				- (pmc * OPROFILE_PMSEL_FIELD_WIDTH));
+
+		switch (psel >> 4) {
+		case 2:
+			cntr_marked_events |= (pmc == 1 || pmc == 3) << pmc;
+			break;
+		case 3:
+			if (psel == 0x3c) {
+				cntr_marked_events |= (pmc == 0) << pmc;
+				break;
+			}
+
+			if (psel == 0x3e) {
+				cntr_marked_events |= (pmc != 1) << pmc;
+				break;
+			}
+
+			cntr_marked_events |= 1 << pmc;
+			break;
+		case 4:
+		case 5:
+			cntr_marked_events |= (unit == 0xd) << pmc;
+			break;
+		case 6:
+			if (psel == 0x64)
+				cntr_marked_events |= (pmc >= 2) << pmc;
+			break;
+		case 8:
+			cntr_marked_events |= (unit == 0xd) << pmc;
+			break;
+		}
+	}
+	return cntr_marked_events;
+}
 
 static int power4_reg_setup(struct op_counter_config *ctr,
 			     struct op_system_config *sys,
@@ -47,6 +109,23 @@ static int power4_reg_setup(struct op_counter_config *ctr,
 	mmcr1_val = sys->mmcr1;
 	mmcra_val = sys->mmcra;
 
+	/* Power 7+ and newer architectures:
+	 * Determine which counter events in the group (the group of events is
+	 * specified by the bit settings in the MMCR1 register) are marked
+	 * events for use in the interrupt handler.  Do the calculation once
+	 * before OProfile starts.  Information is used in the interrupt
+	 * handler.  Starting with Power 7+ we only record the sample for
+	 * marked events if the SIAR valid bit is set.  For non marked events
+	 * the sample is always recorded.
+	 */
+	if (pvr_version_is(PVR_POWER7p))
+		cntr_marked_events = power7_marked_instr_event(mmcr1_val);
+	else
+		cntr_marked_events = 0; /* For older processors, set the bit map
+					 * to zero so the sample will always be
+					 * be recorded.
+					 */
+
 	for (i = 0; i < cur_cpu_spec->num_pmcs; ++i)
 		reset_value[i] = 0x80000000UL - ctr[i].count;
 
@@ -61,10 +140,10 @@ static int power4_reg_setup(struct op_counter_config *ctr,
 	else
 		mmcr0_val |= MMCR0_PROBLEM_DISABLE;
 
-	if (__is_processor(PV_POWER4) || __is_processor(PV_POWER4p) ||
-	    __is_processor(PV_970) || __is_processor(PV_970FX) ||
-	    __is_processor(PV_970MP) || __is_processor(PV_970GX) ||
-	    __is_processor(PV_POWER5) || __is_processor(PV_POWER5p))
+	if (pvr_version_is(PVR_POWER4) || pvr_version_is(PVR_POWER4p) ||
+	    pvr_version_is(PVR_970) || pvr_version_is(PVR_970FX) ||
+	    pvr_version_is(PVR_970MP) || pvr_version_is(PVR_970GX) ||
+	    pvr_version_is(PVR_POWER5) || pvr_version_is(PVR_POWER5p))
 		use_slot_nums = 1;
 
 	return 0;
@@ -84,9 +163,9 @@ extern void ppc_enable_pmcs(void);
  */
 static inline int mmcra_must_set_sample(void)
 {
-	if (__is_processor(PV_POWER4) || __is_processor(PV_POWER4p) ||
-	    __is_processor(PV_970) || __is_processor(PV_970FX) ||
-	    __is_processor(PV_970MP) || __is_processor(PV_970GX))
+	if (pvr_version_is(PVR_POWER4) || pvr_version_is(PVR_POWER4p) ||
+	    pvr_version_is(PVR_970) || pvr_version_is(PVR_970FX) ||
+	    pvr_version_is(PVR_970MP) || pvr_version_is(PVR_970GX))
 		return 1;
 
 	return 0;
@@ -276,7 +355,7 @@ static bool pmc_overflow(unsigned long val)
 	 * PMCs because a user might set a period of less than 256 and we
 	 * don't want to mistakenly reset them.
 	 */
-	if (__is_processor(PV_POWER7) && ((0x80000000 - val) <= 256))
+	if (pvr_version_is(PVR_POWER7) && ((0x80000000 - val) <= 256))
 		return true;
 
 	return false;
@@ -291,6 +370,7 @@ static void power4_handle_interrupt(struct pt_regs *regs,
 	int i;
 	unsigned int mmcr0;
 	unsigned long mmcra;
+	bool siar_valid = false;
 
 	mmcra = mfspr(SPRN_MMCRA);
 
@@ -300,11 +380,29 @@ static void power4_handle_interrupt(struct pt_regs *regs,
 	/* set the PMM bit (see comment below) */
 	mtmsrd(mfmsr() | MSR_PMM);
 
+	/* Check that the SIAR  valid bit in MMCRA is set to 1. */
+	if ((mmcra & MMCRA_SIAR_VALID_MASK) == MMCRA_SIAR_VALID_MASK)
+		siar_valid = true;
+
 	for (i = 0; i < cur_cpu_spec->num_pmcs; ++i) {
 		val = classic_ctr_read(i);
 		if (pmc_overflow(val)) {
 			if (oprofile_running && ctr[i].enabled) {
-				oprofile_add_ext_sample(pc, regs, i, is_kernel);
+				/* Power 7+ and newer architectures:
+				 * If the event is a marked event, then only
+				 * save the sample if the SIAR valid bit is
+				 * set.  If the event is not marked, then
+				 * always save the sample.
+				 * Note, the Sample enable bit in the MMCRA
+				 * register must be set to 1 if the group
+				 * contains a marked event.
+				 */
+				if ((siar_valid &&
+				     (cntr_marked_events & (1 << i)))
+				    || !(cntr_marked_events & (1 << i)))
+					oprofile_add_ext_sample(pc, regs, i,
+								is_kernel);
+
 				classic_ctr_write(i, reset_value[i]);
 			} else {
 				classic_ctr_write(i, 0);
diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
index 7cd2dbd..fb55da9 100644
--- a/arch/powerpc/perf/core-book3s.c
+++ b/arch/powerpc/perf/core-book3s.c
@@ -1396,7 +1396,7 @@ static bool pmc_overflow(unsigned long val)
 	 * PMCs because a user might set a period of less than 256 and we
 	 * don't want to mistakenly reset them.
 	 */
-	if (__is_processor(PV_POWER7) && ((0x80000000 - val) <= 256))
+	if (pvr_version_is(PVR_POWER7) && ((0x80000000 - val) <= 256))
 		return true;
 
 	return false;
diff --git a/arch/powerpc/platforms/40x/ppc40x_simple.c b/arch/powerpc/platforms/40x/ppc40x_simple.c
index 9761206..969dddc 100644
--- a/arch/powerpc/platforms/40x/ppc40x_simple.c
+++ b/arch/powerpc/platforms/40x/ppc40x_simple.c
@@ -50,7 +50,7 @@ machine_device_initcall(ppc40x_simple, ppc40x_device_probe);
  * Again, if your board needs to do things differently then create a
  * board.c file for it rather than adding it to this list.
  */
-static const char *board[] __initdata = {
+static const char * const board[] __initconst = {
 	"amcc,acadia",
 	"amcc,haleakala",
 	"amcc,kilauea",
diff --git a/arch/powerpc/platforms/44x/currituck.c b/arch/powerpc/platforms/44x/currituck.c
index 9f6c33d..6bd89a0 100644
--- a/arch/powerpc/platforms/44x/currituck.c
+++ b/arch/powerpc/platforms/44x/currituck.c
@@ -21,7 +21,6 @@
  */
 
 #include <linux/init.h>
-#include <linux/memblock.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
 #include <linux/rtc.h>
@@ -159,13 +158,8 @@ static void __init ppc47x_setup_arch(void)
 
 	/* No need to check the DMA config as we /know/ our windows are all of
  	 * RAM.  Lets hope that doesn't change */
-#ifdef CONFIG_SWIOTLB
-	if ((memblock_end_of_DRAM() - 1) > 0xffffffff) {
-		ppc_swiotlb_enable = 1;
-		set_pci_dma_ops(&swiotlb_dma_ops);
-		ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb;
-	}
-#endif
+	swiotlb_detect_4g();
+
 	ppc47x_smp_init();
 }
 
diff --git a/arch/powerpc/platforms/512x/Kconfig b/arch/powerpc/platforms/512x/Kconfig
index c169998..b62508b 100644
--- a/arch/powerpc/platforms/512x/Kconfig
+++ b/arch/powerpc/platforms/512x/Kconfig
@@ -2,6 +2,7 @@ config PPC_MPC512x
 	bool "512x-based boards"
 	depends on 6xx
 	select FSL_SOC
+	select FB_FSL_DIU
 	select IPIC
 	select PPC_CLOCK
 	select PPC_PCI_CHOICE
diff --git a/arch/powerpc/platforms/512x/clock.c b/arch/powerpc/platforms/512x/clock.c
index 1d8700f..9f771e0 100644
--- a/arch/powerpc/platforms/512x/clock.c
+++ b/arch/powerpc/platforms/512x/clock.c
@@ -54,14 +54,16 @@ static DEFINE_MUTEX(clocks_mutex);
 static struct clk *mpc5121_clk_get(struct device *dev, const char *id)
 {
 	struct clk *p, *clk = ERR_PTR(-ENOENT);
-	int dev_match = 0;
-	int id_match = 0;
+	int dev_match;
+	int id_match;
 
 	if (dev == NULL || id == NULL)
 		return clk;
 
 	mutex_lock(&clocks_mutex);
 	list_for_each_entry(p, &clocks, node) {
+		dev_match = id_match = 0;
+
 		if (dev == p->dev)
 			dev_match++;
 		if (strcmp(id, p->name) == 0)
diff --git a/arch/powerpc/platforms/512x/mpc5121_generic.c b/arch/powerpc/platforms/512x/mpc5121_generic.c
index 926731f..ca1ca66 100644
--- a/arch/powerpc/platforms/512x/mpc5121_generic.c
+++ b/arch/powerpc/platforms/512x/mpc5121_generic.c
@@ -26,7 +26,7 @@
 /*
  * list of supported boards
  */
-static const char *board[] __initdata = {
+static const char * const board[] __initconst = {
 	"prt,prtlvt",
 	NULL
 };
diff --git a/arch/powerpc/platforms/512x/mpc512x_shared.c b/arch/powerpc/platforms/512x/mpc512x_shared.c
index cfe958e..1650e09 100644
--- a/arch/powerpc/platforms/512x/mpc512x_shared.c
+++ b/arch/powerpc/platforms/512x/mpc512x_shared.c
@@ -191,8 +191,6 @@ mpc512x_valid_monitor_port(enum fsl_diu_monitor_port port)
 
 static struct fsl_diu_shared_fb __attribute__ ((__aligned__(8))) diu_shared_fb;
 
-#if defined(CONFIG_FB_FSL_DIU) || \
-    defined(CONFIG_FB_FSL_DIU_MODULE)
 static inline void mpc512x_free_bootmem(struct page *page)
 {
 	__ClearPageReserved(page);
@@ -220,7 +218,6 @@ void mpc512x_release_bootmem(void)
 	}
 	diu_ops.release_bootmem	= NULL;
 }
-#endif
 
 /*
  * Check if DIU was pre-initialized. If so, perform steps
@@ -323,15 +320,12 @@ void __init mpc512x_setup_diu(void)
 		}
 	}
 
-#if defined(CONFIG_FB_FSL_DIU) || \
-    defined(CONFIG_FB_FSL_DIU_MODULE)
 	diu_ops.get_pixel_format	= mpc512x_get_pixel_format;
 	diu_ops.set_gamma_table		= mpc512x_set_gamma_table;
 	diu_ops.set_monitor_port	= mpc512x_set_monitor_port;
 	diu_ops.set_pixel_clock		= mpc512x_set_pixel_clock;
 	diu_ops.valid_monitor_port	= mpc512x_valid_monitor_port;
 	diu_ops.release_bootmem		= mpc512x_release_bootmem;
-#endif
 }
 
 void __init mpc512x_init_IRQ(void)
diff --git a/arch/powerpc/platforms/52xx/lite5200.c b/arch/powerpc/platforms/52xx/lite5200.c
index 01ffa64..448d862 100644
--- a/arch/powerpc/platforms/52xx/lite5200.c
+++ b/arch/powerpc/platforms/52xx/lite5200.c
@@ -172,7 +172,7 @@ static void __init lite5200_setup_arch(void)
 	mpc52xx_setup_pci();
 }
 
-static const char *board[] __initdata = {
+static const char * const board[] __initconst = {
 	"fsl,lite5200",
 	"fsl,lite5200b",
 	NULL,
diff --git a/arch/powerpc/platforms/52xx/media5200.c b/arch/powerpc/platforms/52xx/media5200.c
index 17d91b7..070d315 100644
--- a/arch/powerpc/platforms/52xx/media5200.c
+++ b/arch/powerpc/platforms/52xx/media5200.c
@@ -232,7 +232,7 @@ static void __init media5200_setup_arch(void)
 }
 
 /* list of the supported boards */
-static const char *board[] __initdata = {
+static const char * const board[] __initconst = {
 	"fsl,media5200",
 	NULL
 };
diff --git a/arch/powerpc/platforms/52xx/mpc5200_simple.c b/arch/powerpc/platforms/52xx/mpc5200_simple.c
index c0aa040..9cf3602 100644
--- a/arch/powerpc/platforms/52xx/mpc5200_simple.c
+++ b/arch/powerpc/platforms/52xx/mpc5200_simple.c
@@ -52,6 +52,7 @@ static void __init mpc5200_simple_setup_arch(void)
 static const char *board[] __initdata = {
 	"anonymous,a4m072",
 	"anon,charon",
+	"ifm,o2d",
 	"intercontrol,digsy-mtc",
 	"manroland,mucmc52",
 	"manroland,uc101",
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c b/arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c
index d61fb1c..2351f9e 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c
@@ -170,7 +170,8 @@ static void mpc52xx_lpbfifo_kick(struct mpc52xx_lpbfifo_request *req)
 	out_be32(lpbfifo.regs + LPBFIFO_REG_CONTROL, bit_fields);
 
 	/* Kick it off */
-	out_8(lpbfifo.regs + LPBFIFO_REG_PACKET_SIZE, 0x01);
+	if (!lpbfifo.req->defer_xfer_start)
+		out_8(lpbfifo.regs + LPBFIFO_REG_PACKET_SIZE, 0x01);
 	if (dma)
 		bcom_enable(lpbfifo.bcom_cur_task);
 }
@@ -421,6 +422,38 @@ int mpc52xx_lpbfifo_submit(struct mpc52xx_lpbfifo_request *req)
 }
 EXPORT_SYMBOL(mpc52xx_lpbfifo_submit);
 
+int mpc52xx_lpbfifo_start_xfer(struct mpc52xx_lpbfifo_request *req)
+{
+	unsigned long flags;
+
+	if (!lpbfifo.regs)
+		return -ENODEV;
+
+	spin_lock_irqsave(&lpbfifo.lock, flags);
+
+	/*
+	 * If the req pointer is already set and a transfer was
+	 * started on submit, then this transfer is in progress
+	 */
+	if (lpbfifo.req && !lpbfifo.req->defer_xfer_start) {
+		spin_unlock_irqrestore(&lpbfifo.lock, flags);
+		return -EBUSY;
+	}
+
+	/*
+	 * If the req was previously submitted but not
+	 * started, start it now
+	 */
+	if (lpbfifo.req && lpbfifo.req == req &&
+	    lpbfifo.req->defer_xfer_start) {
+		out_8(lpbfifo.regs + LPBFIFO_REG_PACKET_SIZE, 0x01);
+	}
+
+	spin_unlock_irqrestore(&lpbfifo.lock, flags);
+	return 0;
+}
+EXPORT_SYMBOL(mpc52xx_lpbfifo_start_xfer);
+
 void mpc52xx_lpbfifo_abort(struct mpc52xx_lpbfifo_request *req)
 {
 	unsigned long flags;
diff --git a/arch/powerpc/platforms/83xx/mpc837x_rdb.c b/arch/powerpc/platforms/83xx/mpc837x_rdb.c
index 16c9c9c..eca1f09 100644
--- a/arch/powerpc/platforms/83xx/mpc837x_rdb.c
+++ b/arch/powerpc/platforms/83xx/mpc837x_rdb.c
@@ -60,7 +60,7 @@ static void __init mpc837x_rdb_setup_arch(void)
 
 machine_device_initcall(mpc837x_rdb, mpc83xx_declare_of_platform_devices);
 
-static const char *board[] __initdata = {
+static const char * const board[] __initconst = {
 	"fsl,mpc8377rdb",
 	"fsl,mpc8378rdb",
 	"fsl,mpc8379rdb",
diff --git a/arch/powerpc/platforms/83xx/suspend.c b/arch/powerpc/platforms/83xx/suspend.c
index 1a04671..1d769a2 100644
--- a/arch/powerpc/platforms/83xx/suspend.c
+++ b/arch/powerpc/platforms/83xx/suspend.c
@@ -326,7 +326,7 @@ static int pmc_probe(struct platform_device *ofdev)
 	const struct of_device_id *match;
 	struct device_node *np = ofdev->dev.of_node;
 	struct resource res;
-	struct pmc_type *type;
+	const struct pmc_type *type;
 	int ret = 0;
 
 	match = of_match_device(pmc_match, &ofdev->dev);
diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig
index 159c01e..02d02a0 100644
--- a/arch/powerpc/platforms/85xx/Kconfig
+++ b/arch/powerpc/platforms/85xx/Kconfig
@@ -104,6 +104,13 @@ config P1022_DS
 	help
 	  This option enables support for the Freescale P1022DS reference board.
 
+config P1022_RDK
+	bool "Freescale / iVeia P1022 RDK"
+	select DEFAULT_UIMAGE
+	help
+	  This option enables support for the Freescale / iVeia P1022RDK
+	  reference board.
+
 config P1023_RDS
 	bool "Freescale P1023 RDS"
 	select DEFAULT_UIMAGE
@@ -254,6 +261,20 @@ config P5020_DS
 	help
 	  This option enables support for the P5020 DS board
 
+config P5040_DS
+	bool "Freescale P5040 DS"
+	select DEFAULT_UIMAGE
+	select E500
+	select PPC_E500MC
+	select PHYS_64BIT
+	select SWIOTLB
+	select ARCH_REQUIRE_GPIOLIB
+	select GPIO_MPC8XXX
+	select HAS_RAPIDIO
+	select PPC_EPAPR_HV_PIC
+	help
+	  This option enables support for the P5040 DS board
+
 config PPC_QEMU_E500
 	bool "QEMU generic e500 platform"
 	depends on EXPERIMENTAL
diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile
index 3dfe811..76f679c 100644
--- a/arch/powerpc/platforms/85xx/Makefile
+++ b/arch/powerpc/platforms/85xx/Makefile
@@ -15,11 +15,13 @@ obj-$(CONFIG_MPC85xx_MDS) += mpc85xx_mds.o
 obj-$(CONFIG_MPC85xx_RDB) += mpc85xx_rdb.o
 obj-$(CONFIG_P1010_RDB)   += p1010rdb.o
 obj-$(CONFIG_P1022_DS)    += p1022_ds.o
+obj-$(CONFIG_P1022_RDK)   += p1022_rdk.o
 obj-$(CONFIG_P1023_RDS)   += p1023_rds.o
 obj-$(CONFIG_P2041_RDB)   += p2041_rdb.o corenet_ds.o
 obj-$(CONFIG_P3041_DS)    += p3041_ds.o corenet_ds.o
 obj-$(CONFIG_P4080_DS)    += p4080_ds.o corenet_ds.o
 obj-$(CONFIG_P5020_DS)    += p5020_ds.o corenet_ds.o
+obj-$(CONFIG_P5040_DS)    += p5040_ds.o corenet_ds.o
 obj-$(CONFIG_STX_GP3)	  += stx_gp3.o
 obj-$(CONFIG_TQM85xx)	  += tqm85xx.o
 obj-$(CONFIG_SBC8548)     += sbc8548.o
diff --git a/arch/powerpc/platforms/85xx/common.c b/arch/powerpc/platforms/85xx/common.c
index 67dac22..d0861a0 100644
--- a/arch/powerpc/platforms/85xx/common.c
+++ b/arch/powerpc/platforms/85xx/common.c
@@ -27,6 +27,16 @@ static struct of_device_id __initdata mpc85xx_common_ids[] = {
 	{ .compatible = "fsl,mpc8548-guts", },
 	/* Probably unnecessary? */
 	{ .compatible = "gpio-leds", },
+	/* For all PCI controllers */
+	{ .compatible = "fsl,mpc8540-pci", },
+	{ .compatible = "fsl,mpc8548-pcie", },
+	{ .compatible = "fsl,p1022-pcie", },
+	{ .compatible = "fsl,p1010-pcie", },
+	{ .compatible = "fsl,p1023-pcie", },
+	{ .compatible = "fsl,p4080-pcie", },
+	{ .compatible = "fsl,qoriq-pcie-v2.4", },
+	{ .compatible = "fsl,qoriq-pcie-v2.3", },
+	{ .compatible = "fsl,qoriq-pcie-v2.2", },
 	{},
 };
 
diff --git a/arch/powerpc/platforms/85xx/corenet_ds.c b/arch/powerpc/platforms/85xx/corenet_ds.c
index 925b028..ed69c92 100644
--- a/arch/powerpc/platforms/85xx/corenet_ds.c
+++ b/arch/powerpc/platforms/85xx/corenet_ds.c
@@ -16,7 +16,6 @@
 #include <linux/kdev_t.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
-#include <linux/memblock.h>
 
 #include <asm/time.h>
 #include <asm/machdep.h>
@@ -52,37 +51,16 @@ void __init corenet_ds_pic_init(void)
  */
 void __init corenet_ds_setup_arch(void)
 {
-#ifdef CONFIG_PCI
-	struct device_node *np;
-	struct pci_controller *hose;
-#endif
-	dma_addr_t max = 0xffffffff;
-
 	mpc85xx_smp_init();
 
-#ifdef CONFIG_PCI
-	for_each_node_by_type(np, "pci") {
-		if (of_device_is_compatible(np, "fsl,p4080-pcie") ||
-		    of_device_is_compatible(np, "fsl,qoriq-pcie-v2.2")) {
-			fsl_add_bridge(np, 0);
-			hose = pci_find_hose_for_OF_device(np);
-			max = min(max, hose->dma_window_base_cur +
-					hose->dma_window_size);
-		}
-	}
-
-#ifdef CONFIG_PPC64
+#if defined(CONFIG_PCI) && defined(CONFIG_PPC64)
 	pci_devs_phb_init();
 #endif
-#endif
 
-#ifdef CONFIG_SWIOTLB
-	if ((memblock_end_of_DRAM() - 1) > max) {
-		ppc_swiotlb_enable = 1;
-		set_pci_dma_ops(&swiotlb_dma_ops);
-		ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb;
-	}
-#endif
+	fsl_pci_assign_primary();
+
+	swiotlb_detect_4g();
+
 	pr_info("%s board from Freescale Semiconductor\n", ppc_md.name);
 }
 
@@ -99,6 +77,12 @@ static const struct of_device_id of_device_ids[] __devinitconst = {
 	{
 		.compatible	= "fsl,qoriq-pcie-v2.2",
 	},
+	{
+		.compatible	= "fsl,qoriq-pcie-v2.3",
+	},
+	{
+		.compatible	= "fsl,qoriq-pcie-v2.4",
+	},
 	/* The following two are for the Freescale hypervisor */
 	{
 		.name		= "hypervisor",
diff --git a/arch/powerpc/platforms/85xx/ge_imp3a.c b/arch/powerpc/platforms/85xx/ge_imp3a.c
index b6a728b..e6285ae 100644
--- a/arch/powerpc/platforms/85xx/ge_imp3a.c
+++ b/arch/powerpc/platforms/85xx/ge_imp3a.c
@@ -22,7 +22,6 @@
 #include <linux/seq_file.h>
 #include <linux/interrupt.h>
 #include <linux/of_platform.h>
-#include <linux/memblock.h>
 
 #include <asm/time.h>
 #include <asm/machdep.h>
@@ -84,53 +83,39 @@ void __init ge_imp3a_pic_init(void)
 	of_node_put(cascade_node);
 }
 
-#ifdef CONFIG_PCI
-static int primary_phb_addr;
-#endif	/* CONFIG_PCI */
-
-/*
- * Setup the architecture
- */
-static void __init ge_imp3a_setup_arch(void)
+static void ge_imp3a_pci_assign_primary(void)
 {
-	struct device_node *regs;
 #ifdef CONFIG_PCI
 	struct device_node *np;
-	struct pci_controller *hose;
-#endif
-	dma_addr_t max = 0xffffffff;
+	struct resource rsrc;
 
-	if (ppc_md.progress)
-		ppc_md.progress("ge_imp3a_setup_arch()", 0);
-
-#ifdef CONFIG_PCI
 	for_each_node_by_type(np, "pci") {
 		if (of_device_is_compatible(np, "fsl,mpc8540-pci") ||
 		    of_device_is_compatible(np, "fsl,mpc8548-pcie") ||
 		    of_device_is_compatible(np, "fsl,p2020-pcie")) {
-			struct resource rsrc;
 			of_address_to_resource(np, 0, &rsrc);
-			if ((rsrc.start & 0xfffff) == primary_phb_addr)
-				fsl_add_bridge(np, 1);
-			else
-				fsl_add_bridge(np, 0);
-
-			hose = pci_find_hose_for_OF_device(np);
-			max = min(max, hose->dma_window_base_cur +
-					hose->dma_window_size);
+			if ((rsrc.start & 0xfffff) == 0x9000)
+				fsl_pci_primary = np;
 		}
 	}
 #endif
+}
+
+/*
+ * Setup the architecture
+ */
+static void __init ge_imp3a_setup_arch(void)
+{
+	struct device_node *regs;
+
+	if (ppc_md.progress)
+		ppc_md.progress("ge_imp3a_setup_arch()", 0);
 
 	mpc85xx_smp_init();
 
-#ifdef CONFIG_SWIOTLB
-	if ((memblock_end_of_DRAM() - 1) > max) {
-		ppc_swiotlb_enable = 1;
-		set_pci_dma_ops(&swiotlb_dma_ops);
-		ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb;
-	}
-#endif
+	ge_imp3a_pci_assign_primary();
+
+	swiotlb_detect_4g();
 
 	/* Remap basic board registers */
 	regs = of_find_compatible_node(NULL, NULL, "ge,imp3a-fpga-regs");
@@ -215,17 +200,10 @@ static int __init ge_imp3a_probe(void)
 {
 	unsigned long root = of_get_flat_dt_root();
 
-	if (of_flat_dt_is_compatible(root, "ge,IMP3A")) {
-#ifdef CONFIG_PCI
-		primary_phb_addr = 0x9000;
-#endif
-		return 1;
-	}
-
-	return 0;
+	return of_flat_dt_is_compatible(root, "ge,IMP3A");
 }
 
-machine_device_initcall(ge_imp3a, mpc85xx_common_publish_devices);
+machine_arch_initcall(ge_imp3a, mpc85xx_common_publish_devices);
 
 machine_arch_initcall(ge_imp3a, swiotlb_setup_bus_notifier);
 
diff --git a/arch/powerpc/platforms/85xx/mpc8536_ds.c b/arch/powerpc/platforms/85xx/mpc8536_ds.c
index 767c7cf..15ce4b5 100644
--- a/arch/powerpc/platforms/85xx/mpc8536_ds.c
+++ b/arch/powerpc/platforms/85xx/mpc8536_ds.c
@@ -17,7 +17,6 @@
 #include <linux/seq_file.h>
 #include <linux/interrupt.h>
 #include <linux/of_platform.h>
-#include <linux/memblock.h>
 
 #include <asm/time.h>
 #include <asm/machdep.h>
@@ -46,46 +45,17 @@ void __init mpc8536_ds_pic_init(void)
  */
 static void __init mpc8536_ds_setup_arch(void)
 {
-#ifdef CONFIG_PCI
-	struct device_node *np;
-	struct pci_controller *hose;
-#endif
-	dma_addr_t max = 0xffffffff;
-
 	if (ppc_md.progress)
 		ppc_md.progress("mpc8536_ds_setup_arch()", 0);
 
-#ifdef CONFIG_PCI
-	for_each_node_by_type(np, "pci") {
-		if (of_device_is_compatible(np, "fsl,mpc8540-pci") ||
-		    of_device_is_compatible(np, "fsl,mpc8548-pcie")) {
-			struct resource rsrc;
-			of_address_to_resource(np, 0, &rsrc);
-			if ((rsrc.start & 0xfffff) == 0x8000)
-				fsl_add_bridge(np, 1);
-			else
-				fsl_add_bridge(np, 0);
-
-			hose = pci_find_hose_for_OF_device(np);
-			max = min(max, hose->dma_window_base_cur +
-					hose->dma_window_size);
-		}
-	}
-
-#endif
+	fsl_pci_assign_primary();
 
-#ifdef CONFIG_SWIOTLB
-	if ((memblock_end_of_DRAM() - 1) > max) {
-		ppc_swiotlb_enable = 1;
-		set_pci_dma_ops(&swiotlb_dma_ops);
-		ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb;
-	}
-#endif
+	swiotlb_detect_4g();
 
 	printk("MPC8536 DS board from Freescale Semiconductor\n");
 }
 
-machine_device_initcall(mpc8536_ds, mpc85xx_common_publish_devices);
+machine_arch_initcall(mpc8536_ds, mpc85xx_common_publish_devices);
 
 machine_arch_initcall(mpc8536_ds, swiotlb_setup_bus_notifier);
 
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ads.c b/arch/powerpc/platforms/85xx/mpc85xx_ads.c
index 29ee8fc..7d12a19 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_ads.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_ads.c
@@ -137,10 +137,6 @@ static void __init init_ioports(void)
 
 static void __init mpc85xx_ads_setup_arch(void)
 {
-#ifdef CONFIG_PCI
-	struct device_node *np;
-#endif
-
 	if (ppc_md.progress)
 		ppc_md.progress("mpc85xx_ads_setup_arch()", 0);
 
@@ -150,11 +146,10 @@ static void __init mpc85xx_ads_setup_arch(void)
 #endif
 
 #ifdef CONFIG_PCI
-	for_each_compatible_node(np, "pci", "fsl,mpc8540-pci")
-		fsl_add_bridge(np, 1);
-
 	ppc_md.pci_exclude_device = mpc85xx_exclude_device;
 #endif
+
+	fsl_pci_assign_primary();
 }
 
 static void mpc85xx_ads_show_cpuinfo(struct seq_file *m)
@@ -173,7 +168,7 @@ static void mpc85xx_ads_show_cpuinfo(struct seq_file *m)
 	seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f));
 }
 
-machine_device_initcall(mpc85xx_ads, mpc85xx_common_publish_devices);
+machine_arch_initcall(mpc85xx_ads, mpc85xx_common_publish_devices);
 
 /*
  * Called very early, device-tree isn't unflattened
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_cds.c b/arch/powerpc/platforms/85xx/mpc85xx_cds.c
index 11156fb..c474505 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_cds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_cds.c
@@ -276,6 +276,33 @@ machine_device_initcall(mpc85xx_cds, mpc85xx_cds_8259_attach);
 
 #endif /* CONFIG_PPC_I8259 */
 
+static void mpc85xx_cds_pci_assign_primary(void)
+{
+#ifdef CONFIG_PCI
+	struct device_node *np;
+
+	if (fsl_pci_primary)
+		return;
+
+	/*
+	 * MPC85xx_CDS has ISA bridge but unfortunately there is no
+	 * isa node in device tree. We now looking for i8259 node as
+	 * a workaround for such a broken device tree. This routine
+	 * is for complying to all device trees.
+	 */
+	np = of_find_node_by_name(NULL, "i8259");
+	while ((fsl_pci_primary = of_get_parent(np))) {
+		of_node_put(np);
+		np = fsl_pci_primary;
+
+		if ((of_device_is_compatible(np, "fsl,mpc8540-pci") ||
+		    of_device_is_compatible(np, "fsl,mpc8548-pcie")) &&
+		    of_device_is_available(np))
+			return;
+	}
+#endif
+}
+
 /*
  * Setup the architecture
  */
@@ -309,21 +336,12 @@ static void __init mpc85xx_cds_setup_arch(void)
 	}
 
 #ifdef CONFIG_PCI
-	for_each_node_by_type(np, "pci") {
-		if (of_device_is_compatible(np, "fsl,mpc8540-pci") ||
-		    of_device_is_compatible(np, "fsl,mpc8548-pcie")) {
-			struct resource rsrc;
-			of_address_to_resource(np, 0, &rsrc);
-			if ((rsrc.start & 0xfffff) == 0x8000)
-				fsl_add_bridge(np, 1);
-			else
-				fsl_add_bridge(np, 0);
-		}
-	}
-
 	ppc_md.pci_irq_fixup = mpc85xx_cds_pci_irq_fixup;
 	ppc_md.pci_exclude_device = mpc85xx_exclude_device;
 #endif
+
+	mpc85xx_cds_pci_assign_primary();
+	fsl_pci_assign_primary();
 }
 
 static void mpc85xx_cds_show_cpuinfo(struct seq_file *m)
@@ -355,7 +373,7 @@ static int __init mpc85xx_cds_probe(void)
         return of_flat_dt_is_compatible(root, "MPC85xxCDS");
 }
 
-machine_device_initcall(mpc85xx_cds, mpc85xx_common_publish_devices);
+machine_arch_initcall(mpc85xx_cds, mpc85xx_common_publish_devices);
 
 define_machine(mpc85xx_cds) {
 	.name		= "MPC85xx CDS",
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ds.c b/arch/powerpc/platforms/85xx/mpc85xx_ds.c
index 6d3265f..9ebb91e 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_ds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_ds.c
@@ -20,7 +20,6 @@
 #include <linux/seq_file.h>
 #include <linux/interrupt.h>
 #include <linux/of_platform.h>
-#include <linux/memblock.h>
 
 #include <asm/time.h>
 #include <asm/machdep.h>
@@ -129,13 +128,11 @@ static int mpc85xx_exclude_device(struct pci_controller *hose,
 }
 #endif	/* CONFIG_PCI */
 
-static void __init mpc85xx_ds_pci_init(void)
+static void __init mpc85xx_ds_uli_init(void)
 {
 #ifdef CONFIG_PCI
 	struct device_node *node;
 
-	fsl_pci_init();
-
 	/* See if we have a ULI under the primary */
 
 	node = of_find_node_by_name(NULL, "uli1575");
@@ -159,7 +156,9 @@ static void __init mpc85xx_ds_setup_arch(void)
 	if (ppc_md.progress)
 		ppc_md.progress("mpc85xx_ds_setup_arch()", 0);
 
-	mpc85xx_ds_pci_init();
+	swiotlb_detect_4g();
+	fsl_pci_assign_primary();
+	mpc85xx_ds_uli_init();
 	mpc85xx_smp_init();
 
 	printk("MPC85xx DS board from Freescale Semiconductor\n");
@@ -175,9 +174,9 @@ static int __init mpc8544_ds_probe(void)
 	return !!of_flat_dt_is_compatible(root, "MPC8544DS");
 }
 
-machine_device_initcall(mpc8544_ds, mpc85xx_common_publish_devices);
-machine_device_initcall(mpc8572_ds, mpc85xx_common_publish_devices);
-machine_device_initcall(p2020_ds, mpc85xx_common_publish_devices);
+machine_arch_initcall(mpc8544_ds, mpc85xx_common_publish_devices);
+machine_arch_initcall(mpc8572_ds, mpc85xx_common_publish_devices);
+machine_arch_initcall(p2020_ds, mpc85xx_common_publish_devices);
 
 machine_arch_initcall(mpc8544_ds, swiotlb_setup_bus_notifier);
 machine_arch_initcall(mpc8572_ds, swiotlb_setup_bus_notifier);
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
index 8e4b094..8498f73 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
@@ -327,44 +327,16 @@ static void __init mpc85xx_mds_qeic_init(void) { }
 
 static void __init mpc85xx_mds_setup_arch(void)
 {
-#ifdef CONFIG_PCI
-	struct pci_controller *hose;
-	struct device_node *np;
-#endif
-	dma_addr_t max = 0xffffffff;
-
 	if (ppc_md.progress)
 		ppc_md.progress("mpc85xx_mds_setup_arch()", 0);
 
-#ifdef CONFIG_PCI
-	for_each_node_by_type(np, "pci") {
-		if (of_device_is_compatible(np, "fsl,mpc8540-pci") ||
-		    of_device_is_compatible(np, "fsl,mpc8548-pcie")) {
-			struct resource rsrc;
-			of_address_to_resource(np, 0, &rsrc);
-			if ((rsrc.start & 0xfffff) == 0x8000)
-				fsl_add_bridge(np, 1);
-			else
-				fsl_add_bridge(np, 0);
-
-			hose = pci_find_hose_for_OF_device(np);
-			max = min(max, hose->dma_window_base_cur +
-					hose->dma_window_size);
-		}
-	}
-#endif
-
 	mpc85xx_smp_init();
 
 	mpc85xx_mds_qe_init();
 
-#ifdef CONFIG_SWIOTLB
-	if ((memblock_end_of_DRAM() - 1) > max) {
-		ppc_swiotlb_enable = 1;
-		set_pci_dma_ops(&swiotlb_dma_ops);
-		ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb;
-	}
-#endif
+	fsl_pci_assign_primary();
+
+	swiotlb_detect_4g();
 }
 
 
@@ -409,9 +381,9 @@ static int __init mpc85xx_publish_devices(void)
 	return mpc85xx_common_publish_devices();
 }
 
-machine_device_initcall(mpc8568_mds, mpc85xx_publish_devices);
-machine_device_initcall(mpc8569_mds, mpc85xx_publish_devices);
-machine_device_initcall(p1021_mds, mpc85xx_common_publish_devices);
+machine_arch_initcall(mpc8568_mds, mpc85xx_publish_devices);
+machine_arch_initcall(mpc8569_mds, mpc85xx_publish_devices);
+machine_arch_initcall(p1021_mds, mpc85xx_common_publish_devices);
 
 machine_arch_initcall(mpc8568_mds, swiotlb_setup_bus_notifier);
 machine_arch_initcall(mpc8569_mds, swiotlb_setup_bus_notifier);
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
index 1910fdc..ede8771 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
@@ -86,23 +86,17 @@ void __init mpc85xx_rdb_pic_init(void)
  */
 static void __init mpc85xx_rdb_setup_arch(void)
 {
-#if defined(CONFIG_PCI) || defined(CONFIG_QUICC_ENGINE)
+#ifdef CONFIG_QUICC_ENGINE
 	struct device_node *np;
 #endif
 
 	if (ppc_md.progress)
 		ppc_md.progress("mpc85xx_rdb_setup_arch()", 0);
 
-#ifdef CONFIG_PCI
-	for_each_node_by_type(np, "pci") {
-		if (of_device_is_compatible(np, "fsl,mpc8548-pcie"))
-			fsl_add_bridge(np, 0);
-	}
-
-#endif
-
 	mpc85xx_smp_init();
 
+	fsl_pci_assign_primary();
+
 #ifdef CONFIG_QUICC_ENGINE
 	np = of_find_compatible_node(NULL, NULL, "fsl,qe");
 	if (!np) {
@@ -161,15 +155,15 @@ qe_fail:
 	printk(KERN_INFO "MPC85xx RDB board from Freescale Semiconductor\n");
 }
 
-machine_device_initcall(p2020_rdb, mpc85xx_common_publish_devices);
-machine_device_initcall(p2020_rdb_pc, mpc85xx_common_publish_devices);
-machine_device_initcall(p1020_mbg_pc, mpc85xx_common_publish_devices);
-machine_device_initcall(p1020_rdb, mpc85xx_common_publish_devices);
-machine_device_initcall(p1020_rdb_pc, mpc85xx_common_publish_devices);
-machine_device_initcall(p1020_utm_pc, mpc85xx_common_publish_devices);
-machine_device_initcall(p1021_rdb_pc, mpc85xx_common_publish_devices);
-machine_device_initcall(p1025_rdb, mpc85xx_common_publish_devices);
-machine_device_initcall(p1024_rdb, mpc85xx_common_publish_devices);
+machine_arch_initcall(p2020_rdb, mpc85xx_common_publish_devices);
+machine_arch_initcall(p2020_rdb_pc, mpc85xx_common_publish_devices);
+machine_arch_initcall(p1020_mbg_pc, mpc85xx_common_publish_devices);
+machine_arch_initcall(p1020_rdb, mpc85xx_common_publish_devices);
+machine_arch_initcall(p1020_rdb_pc, mpc85xx_common_publish_devices);
+machine_arch_initcall(p1020_utm_pc, mpc85xx_common_publish_devices);
+machine_arch_initcall(p1021_rdb_pc, mpc85xx_common_publish_devices);
+machine_arch_initcall(p1025_rdb, mpc85xx_common_publish_devices);
+machine_arch_initcall(p1024_rdb, mpc85xx_common_publish_devices);
 
 /*
  * Called very early, device-tree isn't unflattened
diff --git a/arch/powerpc/platforms/85xx/p1010rdb.c b/arch/powerpc/platforms/85xx/p1010rdb.c
index dbaf443..0252961 100644
--- a/arch/powerpc/platforms/85xx/p1010rdb.c
+++ b/arch/powerpc/platforms/85xx/p1010rdb.c
@@ -46,25 +46,15 @@ void __init p1010_rdb_pic_init(void)
  */
 static void __init p1010_rdb_setup_arch(void)
 {
-#ifdef CONFIG_PCI
-	struct device_node *np;
-#endif
-
 	if (ppc_md.progress)
 		ppc_md.progress("p1010_rdb_setup_arch()", 0);
 
-#ifdef CONFIG_PCI
-	for_each_node_by_type(np, "pci") {
-		if (of_device_is_compatible(np, "fsl,p1010-pcie"))
-			fsl_add_bridge(np, 0);
-	}
-
-#endif
+	fsl_pci_assign_primary();
 
 	printk(KERN_INFO "P1010 RDB board from Freescale Semiconductor\n");
 }
 
-machine_device_initcall(p1010_rdb, mpc85xx_common_publish_devices);
+machine_arch_initcall(p1010_rdb, mpc85xx_common_publish_devices);
 machine_arch_initcall(p1010_rdb, swiotlb_setup_bus_notifier);
 
 /*
diff --git a/arch/powerpc/platforms/85xx/p1022_ds.c b/arch/powerpc/platforms/85xx/p1022_ds.c
index 3c732ac..848a3e9 100644
--- a/arch/powerpc/platforms/85xx/p1022_ds.c
+++ b/arch/powerpc/platforms/85xx/p1022_ds.c
@@ -18,7 +18,6 @@
 
 #include <linux/pci.h>
 #include <linux/of_platform.h>
-#include <linux/memblock.h>
 #include <asm/div64.h>
 #include <asm/mpic.h>
 #include <asm/swiotlb.h>
@@ -507,32 +506,9 @@ early_param("video", early_video_setup);
  */
 static void __init p1022_ds_setup_arch(void)
 {
-#ifdef CONFIG_PCI
-	struct device_node *np;
-#endif
-	dma_addr_t max = 0xffffffff;
-
 	if (ppc_md.progress)
 		ppc_md.progress("p1022_ds_setup_arch()", 0);
 
-#ifdef CONFIG_PCI
-	for_each_compatible_node(np, "pci", "fsl,p1022-pcie") {
-		struct resource rsrc;
-		struct pci_controller *hose;
-
-		of_address_to_resource(np, 0, &rsrc);
-
-		if ((rsrc.start & 0xfffff) == 0x8000)
-			fsl_add_bridge(np, 1);
-		else
-			fsl_add_bridge(np, 0);
-
-		hose = pci_find_hose_for_OF_device(np);
-		max = min(max, hose->dma_window_base_cur +
-			  hose->dma_window_size);
-	}
-#endif
-
 #if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
 	diu_ops.get_pixel_format	= p1022ds_get_pixel_format;
 	diu_ops.set_gamma_table		= p1022ds_set_gamma_table;
@@ -601,18 +577,14 @@ static void __init p1022_ds_setup_arch(void)
 
 	mpc85xx_smp_init();
 
-#ifdef CONFIG_SWIOTLB
-	if ((memblock_end_of_DRAM() - 1) > max) {
-		ppc_swiotlb_enable = 1;
-		set_pci_dma_ops(&swiotlb_dma_ops);
-		ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb;
-	}
-#endif
+	fsl_pci_assign_primary();
+
+	swiotlb_detect_4g();
 
 	pr_info("Freescale P1022 DS reference board\n");
 }
 
-machine_device_initcall(p1022_ds, mpc85xx_common_publish_devices);
+machine_arch_initcall(p1022_ds, mpc85xx_common_publish_devices);
 
 machine_arch_initcall(p1022_ds, swiotlb_setup_bus_notifier);
 
diff --git a/arch/powerpc/platforms/85xx/p1022_rdk.c b/arch/powerpc/platforms/85xx/p1022_rdk.c
new file mode 100644
index 0000000..55ffa1c
--- /dev/null
+++ b/arch/powerpc/platforms/85xx/p1022_rdk.c
@@ -0,0 +1,167 @@
+/*
+ * P1022 RDK board specific routines
+ *
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ *
+ * Author: Timur Tabi <timur@freescale.com>
+ *
+ * Based on p1022_ds.c
+ *
+ * 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/pci.h>
+#include <linux/of_platform.h>
+#include <asm/div64.h>
+#include <asm/mpic.h>
+#include <asm/swiotlb.h>
+
+#include <sysdev/fsl_soc.h>
+#include <sysdev/fsl_pci.h>
+#include <asm/udbg.h>
+#include <asm/fsl_guts.h>
+#include "smp.h"
+
+#include "mpc85xx.h"
+
+#if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
+
+/* DIU Pixel Clock bits of the CLKDVDR Global Utilities register */
+#define CLKDVDR_PXCKEN		0x80000000
+#define CLKDVDR_PXCKINV		0x10000000
+#define CLKDVDR_PXCKDLY		0x06000000
+#define CLKDVDR_PXCLK_MASK	0x00FF0000
+
+/**
+ * p1022rdk_set_monitor_port: switch the output to a different monitor port
+ */
+static void p1022rdk_set_monitor_port(enum fsl_diu_monitor_port port)
+{
+	if (port != FSL_DIU_PORT_DVI) {
+		pr_err("p1022rdk: unsupported monitor port %i\n", port);
+		return;
+	}
+}
+
+/**
+ * p1022rdk_set_pixel_clock: program the DIU's clock
+ *
+ * @pixclock: the wavelength, in picoseconds, of the clock
+ */
+void p1022rdk_set_pixel_clock(unsigned int pixclock)
+{
+	struct device_node *guts_np = NULL;
+	struct ccsr_guts __iomem *guts;
+	unsigned long freq;
+	u64 temp;
+	u32 pxclk;
+
+	/* Map the global utilities registers. */
+	guts_np = of_find_compatible_node(NULL, NULL, "fsl,p1022-guts");
+	if (!guts_np) {
+		pr_err("p1022rdk: missing global utilties device node\n");
+		return;
+	}
+
+	guts = of_iomap(guts_np, 0);
+	of_node_put(guts_np);
+	if (!guts) {
+		pr_err("p1022rdk: could not map global utilties device\n");
+		return;
+	}
+
+	/* Convert pixclock from a wavelength to a frequency */
+	temp = 1000000000000ULL;
+	do_div(temp, pixclock);
+	freq = temp;
+
+	/*
+	 * 'pxclk' is the ratio of the platform clock to the pixel clock.
+	 * This number is programmed into the CLKDVDR register, and the valid
+	 * range of values is 2-255.
+	 */
+	pxclk = DIV_ROUND_CLOSEST(fsl_get_sys_freq(), freq);
+	pxclk = clamp_t(u32, pxclk, 2, 255);
+
+	/* Disable the pixel clock, and set it to non-inverted and no delay */
+	clrbits32(&guts->clkdvdr,
+		  CLKDVDR_PXCKEN | CLKDVDR_PXCKDLY | CLKDVDR_PXCLK_MASK);
+
+	/* Enable the clock and set the pxclk */
+	setbits32(&guts->clkdvdr, CLKDVDR_PXCKEN | (pxclk << 16));
+
+	iounmap(guts);
+}
+
+/**
+ * p1022rdk_valid_monitor_port: set the monitor port for sysfs
+ */
+enum fsl_diu_monitor_port
+p1022rdk_valid_monitor_port(enum fsl_diu_monitor_port port)
+{
+	return FSL_DIU_PORT_DVI;
+}
+
+#endif
+
+void __init p1022_rdk_pic_init(void)
+{
+	struct mpic *mpic = mpic_alloc(NULL, 0, MPIC_BIG_ENDIAN |
+		MPIC_SINGLE_DEST_CPU,
+		0, 256, " OpenPIC  ");
+	BUG_ON(mpic == NULL);
+	mpic_init(mpic);
+}
+
+/*
+ * Setup the architecture
+ */
+static void __init p1022_rdk_setup_arch(void)
+{
+	if (ppc_md.progress)
+		ppc_md.progress("p1022_rdk_setup_arch()", 0);
+
+#if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
+	diu_ops.set_monitor_port	= p1022rdk_set_monitor_port;
+	diu_ops.set_pixel_clock		= p1022rdk_set_pixel_clock;
+	diu_ops.valid_monitor_port	= p1022rdk_valid_monitor_port;
+#endif
+
+	mpc85xx_smp_init();
+
+	fsl_pci_assign_primary();
+
+	swiotlb_detect_4g();
+
+	pr_info("Freescale / iVeia P1022 RDK reference board\n");
+}
+
+machine_arch_initcall(p1022_rdk, mpc85xx_common_publish_devices);
+
+machine_arch_initcall(p1022_rdk, swiotlb_setup_bus_notifier);
+
+/*
+ * Called very early, device-tree isn't unflattened
+ */
+static int __init p1022_rdk_probe(void)
+{
+	unsigned long root = of_get_flat_dt_root();
+
+	return of_flat_dt_is_compatible(root, "fsl,p1022rdk");
+}
+
+define_machine(p1022_rdk) {
+	.name			= "P1022 RDK",
+	.probe			= p1022_rdk_probe,
+	.setup_arch		= p1022_rdk_setup_arch,
+	.init_IRQ		= p1022_rdk_pic_init,
+#ifdef CONFIG_PCI
+	.pcibios_fixup_bus	= fsl_pcibios_fixup_bus,
+#endif
+	.get_irq		= mpic_get_irq,
+	.restart		= fsl_rstcr_restart,
+	.calibrate_decr		= generic_calibrate_decr,
+	.progress		= udbg_progress,
+};
diff --git a/arch/powerpc/platforms/85xx/p1023_rds.c b/arch/powerpc/platforms/85xx/p1023_rds.c
index 2990e8b..9cc60a7 100644
--- a/arch/powerpc/platforms/85xx/p1023_rds.c
+++ b/arch/powerpc/platforms/85xx/p1023_rds.c
@@ -80,15 +80,12 @@ static void __init mpc85xx_rds_setup_arch(void)
 		}
 	}
 
-#ifdef CONFIG_PCI
-	for_each_compatible_node(np, "pci", "fsl,p1023-pcie")
-		fsl_add_bridge(np, 0);
-#endif
-
 	mpc85xx_smp_init();
+
+	fsl_pci_assign_primary();
 }
 
-machine_device_initcall(p1023_rds, mpc85xx_common_publish_devices);
+machine_arch_initcall(p1023_rds, mpc85xx_common_publish_devices);
 
 static void __init mpc85xx_rds_pic_init(void)
 {
diff --git a/arch/powerpc/platforms/85xx/p2041_rdb.c b/arch/powerpc/platforms/85xx/p2041_rdb.c
index 6541fa2..000c089 100644
--- a/arch/powerpc/platforms/85xx/p2041_rdb.c
+++ b/arch/powerpc/platforms/85xx/p2041_rdb.c
@@ -80,7 +80,7 @@ define_machine(p2041_rdb) {
 	.power_save		= e500_idle,
 };
 
-machine_device_initcall(p2041_rdb, corenet_ds_publish_devices);
+machine_arch_initcall(p2041_rdb, corenet_ds_publish_devices);
 
 #ifdef CONFIG_SWIOTLB
 machine_arch_initcall(p2041_rdb, swiotlb_setup_bus_notifier);
diff --git a/arch/powerpc/platforms/85xx/p3041_ds.c b/arch/powerpc/platforms/85xx/p3041_ds.c
index f238efa..b3edc20 100644
--- a/arch/powerpc/platforms/85xx/p3041_ds.c
+++ b/arch/powerpc/platforms/85xx/p3041_ds.c
@@ -82,7 +82,7 @@ define_machine(p3041_ds) {
 	.power_save		= e500_idle,
 };
 
-machine_device_initcall(p3041_ds, corenet_ds_publish_devices);
+machine_arch_initcall(p3041_ds, corenet_ds_publish_devices);
 
 #ifdef CONFIG_SWIOTLB
 machine_arch_initcall(p3041_ds, swiotlb_setup_bus_notifier);
diff --git a/arch/powerpc/platforms/85xx/p4080_ds.c b/arch/powerpc/platforms/85xx/p4080_ds.c
index c92417d..54df106 100644
--- a/arch/powerpc/platforms/85xx/p4080_ds.c
+++ b/arch/powerpc/platforms/85xx/p4080_ds.c
@@ -81,7 +81,7 @@ define_machine(p4080_ds) {
 	.power_save		= e500_idle,
 };
 
-machine_device_initcall(p4080_ds, corenet_ds_publish_devices);
+machine_arch_initcall(p4080_ds, corenet_ds_publish_devices);
 #ifdef CONFIG_SWIOTLB
 machine_arch_initcall(p4080_ds, swiotlb_setup_bus_notifier);
 #endif
diff --git a/arch/powerpc/platforms/85xx/p5020_ds.c b/arch/powerpc/platforms/85xx/p5020_ds.c
index 17bef15..753a42c 100644
--- a/arch/powerpc/platforms/85xx/p5020_ds.c
+++ b/arch/powerpc/platforms/85xx/p5020_ds.c
@@ -91,7 +91,7 @@ define_machine(p5020_ds) {
 #endif
 };
 
-machine_device_initcall(p5020_ds, corenet_ds_publish_devices);
+machine_arch_initcall(p5020_ds, corenet_ds_publish_devices);
 
 #ifdef CONFIG_SWIOTLB
 machine_arch_initcall(p5020_ds, swiotlb_setup_bus_notifier);
diff --git a/arch/powerpc/platforms/85xx/p5040_ds.c b/arch/powerpc/platforms/85xx/p5040_ds.c
new file mode 100644
index 0000000..1138185
--- /dev/null
+++ b/arch/powerpc/platforms/85xx/p5040_ds.c
@@ -0,0 +1,89 @@
+/*
+ * P5040 DS Setup
+ *
+ * Copyright 2009-2010 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/kernel.h>
+#include <linux/pci.h>
+
+#include <asm/machdep.h>
+#include <asm/udbg.h>
+#include <asm/mpic.h>
+
+#include <linux/of_fdt.h>
+
+#include <sysdev/fsl_soc.h>
+#include <sysdev/fsl_pci.h>
+#include <asm/ehv_pic.h>
+
+#include "corenet_ds.h"
+
+/*
+ * Called very early, device-tree isn't unflattened
+ */
+static int __init p5040_ds_probe(void)
+{
+	unsigned long root = of_get_flat_dt_root();
+#ifdef CONFIG_SMP
+	extern struct smp_ops_t smp_85xx_ops;
+#endif
+
+	if (of_flat_dt_is_compatible(root, "fsl,P5040DS"))
+		return 1;
+
+	/* Check if we're running under the Freescale hypervisor */
+	if (of_flat_dt_is_compatible(root, "fsl,P5040DS-hv")) {
+		ppc_md.init_IRQ = ehv_pic_init;
+		ppc_md.get_irq = ehv_pic_get_irq;
+		ppc_md.restart = fsl_hv_restart;
+		ppc_md.power_off = fsl_hv_halt;
+		ppc_md.halt = fsl_hv_halt;
+#ifdef CONFIG_SMP
+		/*
+		 * Disable the timebase sync operations because we can't write
+		 * to the timebase registers under the hypervisor.
+		  */
+		smp_85xx_ops.give_timebase = NULL;
+		smp_85xx_ops.take_timebase = NULL;
+#endif
+		return 1;
+	}
+
+	return 0;
+}
+
+define_machine(p5040_ds) {
+	.name			= "P5040 DS",
+	.probe			= p5040_ds_probe,
+	.setup_arch		= corenet_ds_setup_arch,
+	.init_IRQ		= corenet_ds_pic_init,
+#ifdef CONFIG_PCI
+	.pcibios_fixup_bus	= fsl_pcibios_fixup_bus,
+#endif
+/* coreint doesn't play nice with lazy EE, use legacy mpic for now */
+#ifdef CONFIG_PPC64
+	.get_irq		= mpic_get_irq,
+#else
+	.get_irq		= mpic_get_coreint_irq,
+#endif
+	.restart		= fsl_rstcr_restart,
+	.calibrate_decr		= generic_calibrate_decr,
+	.progress		= udbg_progress,
+#ifdef CONFIG_PPC64
+	.power_save		= book3e_idle,
+#else
+	.power_save		= e500_idle,
+#endif
+};
+
+machine_arch_initcall(p5040_ds, corenet_ds_publish_devices);
+
+#ifdef CONFIG_SWIOTLB
+machine_arch_initcall(p5040_ds, swiotlb_setup_bus_notifier);
+#endif
diff --git a/arch/powerpc/platforms/85xx/qemu_e500.c b/arch/powerpc/platforms/85xx/qemu_e500.c
index 95a2e53..f6ea561 100644
--- a/arch/powerpc/platforms/85xx/qemu_e500.c
+++ b/arch/powerpc/platforms/85xx/qemu_e500.c
@@ -41,7 +41,8 @@ static void __init qemu_e500_setup_arch(void)
 {
 	ppc_md.progress("qemu_e500_setup_arch()", 0);
 
-	fsl_pci_init();
+	fsl_pci_assign_primary();
+	swiotlb_detect_4g();
 	mpc85xx_smp_init();
 }
 
@@ -55,7 +56,7 @@ static int __init qemu_e500_probe(void)
 	return !!of_flat_dt_is_compatible(root, "fsl,qemu-e500");
 }
 
-machine_device_initcall(qemu_e500, mpc85xx_common_publish_devices);
+machine_arch_initcall(qemu_e500, mpc85xx_common_publish_devices);
 
 define_machine(qemu_e500) {
 	.name			= "QEMU e500",
diff --git a/arch/powerpc/platforms/85xx/sbc8548.c b/arch/powerpc/platforms/85xx/sbc8548.c
index cd3a66b..f621218 100644
--- a/arch/powerpc/platforms/85xx/sbc8548.c
+++ b/arch/powerpc/platforms/85xx/sbc8548.c
@@ -88,26 +88,11 @@ static int __init sbc8548_hw_rev(void)
  */
 static void __init sbc8548_setup_arch(void)
 {
-#ifdef CONFIG_PCI
-	struct device_node *np;
-#endif
-
 	if (ppc_md.progress)
 		ppc_md.progress("sbc8548_setup_arch()", 0);
 
-#ifdef CONFIG_PCI
-	for_each_node_by_type(np, "pci") {
-		if (of_device_is_compatible(np, "fsl,mpc8540-pci") ||
-		    of_device_is_compatible(np, "fsl,mpc8548-pcie")) {
-			struct resource rsrc;
-			of_address_to_resource(np, 0, &rsrc);
-			if ((rsrc.start & 0xfffff) == 0x8000)
-				fsl_add_bridge(np, 1);
-			else
-				fsl_add_bridge(np, 0);
-		}
-	}
-#endif
+	fsl_pci_assign_primary();
+
 	sbc_rev = sbc8548_hw_rev();
 }
 
@@ -128,7 +113,7 @@ static void sbc8548_show_cpuinfo(struct seq_file *m)
 	seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f));
 }
 
-machine_device_initcall(sbc8548, mpc85xx_common_publish_devices);
+machine_arch_initcall(sbc8548, mpc85xx_common_publish_devices);
 
 /*
  * Called very early, device-tree isn't unflattened
diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c
index ff42490..6fcfa12 100644
--- a/arch/powerpc/platforms/85xx/smp.c
+++ b/arch/powerpc/platforms/85xx/smp.c
@@ -2,7 +2,7 @@
  * Author: Andy Fleming <afleming@freescale.com>
  * 	   Kumar Gala <galak@kernel.crashing.org>
  *
- * Copyright 2006-2008, 2011 Freescale Semiconductor Inc.
+ * Copyright 2006-2008, 2011-2012 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
@@ -17,6 +17,7 @@
 #include <linux/of.h>
 #include <linux/kexec.h>
 #include <linux/highmem.h>
+#include <linux/cpu.h>
 
 #include <asm/machdep.h>
 #include <asm/pgtable.h>
@@ -24,33 +25,118 @@
 #include <asm/mpic.h>
 #include <asm/cacheflush.h>
 #include <asm/dbell.h>
+#include <asm/fsl_guts.h>
 
 #include <sysdev/fsl_soc.h>
 #include <sysdev/mpic.h>
 #include "smp.h"
 
-extern void __early_start(void);
-
-#define BOOT_ENTRY_ADDR_UPPER	0
-#define BOOT_ENTRY_ADDR_LOWER	1
-#define BOOT_ENTRY_R3_UPPER	2
-#define BOOT_ENTRY_R3_LOWER	3
-#define BOOT_ENTRY_RESV		4
-#define BOOT_ENTRY_PIR		5
-#define BOOT_ENTRY_R6_UPPER	6
-#define BOOT_ENTRY_R6_LOWER	7
-#define NUM_BOOT_ENTRY		8
-#define SIZE_BOOT_ENTRY		(NUM_BOOT_ENTRY * sizeof(u32))
-
-static int __init
-smp_85xx_kick_cpu(int nr)
+struct epapr_spin_table {
+	u32	addr_h;
+	u32	addr_l;
+	u32	r3_h;
+	u32	r3_l;
+	u32	reserved;
+	u32	pir;
+};
+
+static struct ccsr_guts __iomem *guts;
+static u64 timebase;
+static int tb_req;
+static int tb_valid;
+
+static void mpc85xx_timebase_freeze(int freeze)
+{
+	uint32_t mask;
+
+	mask = CCSR_GUTS_DEVDISR_TB0 | CCSR_GUTS_DEVDISR_TB1;
+	if (freeze)
+		setbits32(&guts->devdisr, mask);
+	else
+		clrbits32(&guts->devdisr, mask);
+
+	in_be32(&guts->devdisr);
+}
+
+static void mpc85xx_give_timebase(void)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	while (!tb_req)
+		barrier();
+	tb_req = 0;
+
+	mpc85xx_timebase_freeze(1);
+	timebase = get_tb();
+	mb();
+	tb_valid = 1;
+
+	while (tb_valid)
+		barrier();
+
+	mpc85xx_timebase_freeze(0);
+
+	local_irq_restore(flags);
+}
+
+static void mpc85xx_take_timebase(void)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	tb_req = 1;
+	while (!tb_valid)
+		barrier();
+
+	set_tb(timebase >> 32, timebase & 0xffffffff);
+	isync();
+	tb_valid = 0;
+
+	local_irq_restore(flags);
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
+static void __cpuinit smp_85xx_mach_cpu_die(void)
+{
+	unsigned int cpu = smp_processor_id();
+	u32 tmp;
+
+	local_irq_disable();
+	idle_task_exit();
+	generic_set_cpu_dead(cpu);
+	mb();
+
+	mtspr(SPRN_TCR, 0);
+
+	__flush_disable_L1();
+	tmp = (mfspr(SPRN_HID0) & ~(HID0_DOZE|HID0_SLEEP)) | HID0_NAP;
+	mtspr(SPRN_HID0, tmp);
+	isync();
+
+	/* Enter NAP mode. */
+	tmp = mfmsr();
+	tmp |= MSR_WE;
+	mb();
+	mtmsr(tmp);
+	isync();
+
+	while (1)
+		;
+}
+#endif
+
+static int __cpuinit smp_85xx_kick_cpu(int nr)
 {
 	unsigned long flags;
 	const u64 *cpu_rel_addr;
-	__iomem u32 *bptr_vaddr;
+	__iomem struct epapr_spin_table *spin_table;
 	struct device_node *np;
-	int n = 0, hw_cpu = get_hard_smp_processor_id(nr);
+	int hw_cpu = get_hard_smp_processor_id(nr);
 	int ioremappable;
+	int ret = 0;
 
 	WARN_ON(nr < 0 || nr >= NR_CPUS);
 	WARN_ON(hw_cpu < 0 || hw_cpu >= NR_CPUS);
@@ -75,46 +161,81 @@ smp_85xx_kick_cpu(int nr)
 
 	/* Map the spin table */
 	if (ioremappable)
-		bptr_vaddr = ioremap(*cpu_rel_addr, SIZE_BOOT_ENTRY);
+		spin_table = ioremap(*cpu_rel_addr,
+				sizeof(struct epapr_spin_table));
 	else
-		bptr_vaddr = phys_to_virt(*cpu_rel_addr);
+		spin_table = phys_to_virt(*cpu_rel_addr);
 
 	local_irq_save(flags);
-
-	out_be32(bptr_vaddr + BOOT_ENTRY_PIR, hw_cpu);
 #ifdef CONFIG_PPC32
-	out_be32(bptr_vaddr + BOOT_ENTRY_ADDR_LOWER, __pa(__early_start));
+#ifdef CONFIG_HOTPLUG_CPU
+	/* Corresponding to generic_set_cpu_dead() */
+	generic_set_cpu_up(nr);
+
+	if (system_state == SYSTEM_RUNNING) {
+		out_be32(&spin_table->addr_l, 0);
+
+		/*
+		 * We don't set the BPTR register here since it already points
+		 * to the boot page properly.
+		 */
+		mpic_reset_core(hw_cpu);
+
+		/* wait until core is ready... */
+		if (!spin_event_timeout(in_be32(&spin_table->addr_l) == 1,
+						10000, 100)) {
+			pr_err("%s: timeout waiting for core %d to reset\n",
+							__func__, hw_cpu);
+			ret = -ENOENT;
+			goto out;
+		}
+
+		/*  clear the acknowledge status */
+		__secondary_hold_acknowledge = -1;
+	}
+#endif
+	out_be32(&spin_table->pir, hw_cpu);
+	out_be32(&spin_table->addr_l, __pa(__early_start));
 
 	if (!ioremappable)
-		flush_dcache_range((ulong)bptr_vaddr,
-				(ulong)(bptr_vaddr + SIZE_BOOT_ENTRY));
+		flush_dcache_range((ulong)spin_table,
+			(ulong)spin_table + sizeof(struct epapr_spin_table));
 
 	/* Wait a bit for the CPU to ack. */
-	while ((__secondary_hold_acknowledge != hw_cpu) && (++n < 1000))
-		mdelay(1);
+	if (!spin_event_timeout(__secondary_hold_acknowledge == hw_cpu,
+					10000, 100)) {
+		pr_err("%s: timeout waiting for core %d to ack\n",
+						__func__, hw_cpu);
+		ret = -ENOENT;
+		goto out;
+	}
+out:
 #else
 	smp_generic_kick_cpu(nr);
 
-	out_be64((u64 *)(bptr_vaddr + BOOT_ENTRY_ADDR_UPPER),
-		__pa((u64)*((unsigned long long *) generic_secondary_smp_init)));
+	out_be32(&spin_table->pir, hw_cpu);
+	out_be64((u64 *)(&spin_table->addr_h),
+	  __pa((u64)*((unsigned long long *)generic_secondary_smp_init)));
 
 	if (!ioremappable)
-		flush_dcache_range((ulong)bptr_vaddr,
-				(ulong)(bptr_vaddr + SIZE_BOOT_ENTRY));
+		flush_dcache_range((ulong)spin_table,
+			(ulong)spin_table + sizeof(struct epapr_spin_table));
 #endif
 
 	local_irq_restore(flags);
 
 	if (ioremappable)
-		iounmap(bptr_vaddr);
-
-	pr_debug("waited %d msecs for CPU #%d.\n", n, nr);
+		iounmap(spin_table);
 
-	return 0;
+	return ret;
 }
 
 struct smp_ops_t smp_85xx_ops = {
 	.kick_cpu = smp_85xx_kick_cpu,
+#ifdef CONFIG_HOTPLUG_CPU
+	.cpu_disable	= generic_cpu_disable,
+	.cpu_die	= generic_cpu_die,
+#endif
 #ifdef CONFIG_KEXEC
 	.give_timebase	= smp_generic_give_timebase,
 	.take_timebase	= smp_generic_take_timebase,
@@ -218,8 +339,7 @@ static void mpc85xx_smp_machine_kexec(struct kimage *image)
 }
 #endif /* CONFIG_KEXEC */
 
-static void __init
-smp_85xx_setup_cpu(int cpu_nr)
+static void __cpuinit smp_85xx_setup_cpu(int cpu_nr)
 {
 	if (smp_85xx_ops.probe == smp_mpic_probe)
 		mpic_setup_this_cpu();
@@ -228,6 +348,16 @@ smp_85xx_setup_cpu(int cpu_nr)
 		doorbell_setup_this_cpu();
 }
 
+static const struct of_device_id mpc85xx_smp_guts_ids[] = {
+	{ .compatible = "fsl,mpc8572-guts", },
+	{ .compatible = "fsl,p1020-guts", },
+	{ .compatible = "fsl,p1021-guts", },
+	{ .compatible = "fsl,p1022-guts", },
+	{ .compatible = "fsl,p1023-guts", },
+	{ .compatible = "fsl,p2020-guts", },
+	{},
+};
+
 void __init mpc85xx_smp_init(void)
 {
 	struct device_node *np;
@@ -249,6 +379,22 @@ void __init mpc85xx_smp_init(void)
 		smp_85xx_ops.cause_ipi = doorbell_cause_ipi;
 	}
 
+	np = of_find_matching_node(NULL, mpc85xx_smp_guts_ids);
+	if (np) {
+		guts = of_iomap(np, 0);
+		of_node_put(np);
+		if (!guts) {
+			pr_err("%s: Could not map guts node address\n",
+								__func__);
+			return;
+		}
+		smp_85xx_ops.give_timebase = mpc85xx_give_timebase;
+		smp_85xx_ops.take_timebase = mpc85xx_take_timebase;
+#ifdef CONFIG_HOTPLUG_CPU
+		ppc_md.cpu_die = smp_85xx_mach_cpu_die;
+#endif
+	}
+
 	smp_ops = &smp_85xx_ops;
 
 #ifdef CONFIG_KEXEC
diff --git a/arch/powerpc/platforms/85xx/socrates.c b/arch/powerpc/platforms/85xx/socrates.c
index b9c6daa..ae368e0 100644
--- a/arch/powerpc/platforms/85xx/socrates.c
+++ b/arch/powerpc/platforms/85xx/socrates.c
@@ -66,20 +66,13 @@ static void __init socrates_pic_init(void)
  */
 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
+	fsl_pci_assign_primary();
 }
 
-machine_device_initcall(socrates, mpc85xx_common_publish_devices);
+machine_arch_initcall(socrates, mpc85xx_common_publish_devices);
 
 /*
  * Called very early, device-tree isn't unflattened
diff --git a/arch/powerpc/platforms/85xx/stx_gp3.c b/arch/powerpc/platforms/85xx/stx_gp3.c
index e050800..6f4939b 100644
--- a/arch/powerpc/platforms/85xx/stx_gp3.c
+++ b/arch/powerpc/platforms/85xx/stx_gp3.c
@@ -60,21 +60,14 @@ static void __init stx_gp3_pic_init(void)
  */
 static void __init stx_gp3_setup_arch(void)
 {
-#ifdef CONFIG_PCI
-	struct device_node *np;
-#endif
-
 	if (ppc_md.progress)
 		ppc_md.progress("stx_gp3_setup_arch()", 0);
 
+	fsl_pci_assign_primary();
+
 #ifdef CONFIG_CPM2
 	cpm2_reset();
 #endif
-
-#ifdef CONFIG_PCI
-	for_each_compatible_node(np, "pci", "fsl,mpc8540-pci")
-		fsl_add_bridge(np, 1);
-#endif
 }
 
 static void stx_gp3_show_cpuinfo(struct seq_file *m)
@@ -93,7 +86,7 @@ static void stx_gp3_show_cpuinfo(struct seq_file *m)
 	seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f));
 }
 
-machine_device_initcall(stx_gp3, mpc85xx_common_publish_devices);
+machine_arch_initcall(stx_gp3, mpc85xx_common_publish_devices);
 
 /*
  * Called very early, device-tree isn't unflattened
diff --git a/arch/powerpc/platforms/85xx/tqm85xx.c b/arch/powerpc/platforms/85xx/tqm85xx.c
index 3e70a20..b4e58cd 100644
--- a/arch/powerpc/platforms/85xx/tqm85xx.c
+++ b/arch/powerpc/platforms/85xx/tqm85xx.c
@@ -59,10 +59,6 @@ static void __init tqm85xx_pic_init(void)
  */
 static void __init tqm85xx_setup_arch(void)
 {
-#ifdef CONFIG_PCI
-	struct device_node *np;
-#endif
-
 	if (ppc_md.progress)
 		ppc_md.progress("tqm85xx_setup_arch()", 0);
 
@@ -70,20 +66,7 @@ static void __init tqm85xx_setup_arch(void)
 	cpm2_reset();
 #endif
 
-#ifdef CONFIG_PCI
-	for_each_node_by_type(np, "pci") {
-		if (of_device_is_compatible(np, "fsl,mpc8540-pci") ||
-		    of_device_is_compatible(np, "fsl,mpc8548-pcie")) {
-			struct resource rsrc;
-			if (!of_address_to_resource(np, 0, &rsrc)) {
-				if ((rsrc.start & 0xfffff) == 0x8000)
-					fsl_add_bridge(np, 1);
-				else
-					fsl_add_bridge(np, 0);
-			}
-		}
-	}
-#endif
+	fsl_pci_assign_primary();
 }
 
 static void tqm85xx_show_cpuinfo(struct seq_file *m)
@@ -123,9 +106,9 @@ static void __devinit tqm85xx_ti1520_fixup(struct pci_dev *pdev)
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1520,
 		tqm85xx_ti1520_fixup);
 
-machine_device_initcall(tqm85xx, mpc85xx_common_publish_devices);
+machine_arch_initcall(tqm85xx, mpc85xx_common_publish_devices);
 
-static const char *board[] __initdata = {
+static const char * const board[] __initconst = {
 	"tqc,tqm8540",
 	"tqc,tqm8541",
 	"tqc,tqm8548",
diff --git a/arch/powerpc/platforms/85xx/xes_mpc85xx.c b/arch/powerpc/platforms/85xx/xes_mpc85xx.c
index 41c6875..dcbf7e4 100644
--- a/arch/powerpc/platforms/85xx/xes_mpc85xx.c
+++ b/arch/powerpc/platforms/85xx/xes_mpc85xx.c
@@ -111,18 +111,11 @@ static void xes_mpc85xx_fixups(void)
 	}
 }
 
-#ifdef CONFIG_PCI
-static int primary_phb_addr;
-#endif
-
 /*
  * Setup the architecture
  */
 static void __init xes_mpc85xx_setup_arch(void)
 {
-#ifdef CONFIG_PCI
-	struct device_node *np;
-#endif
 	struct device_node *root;
 	const char *model = "Unknown";
 
@@ -137,26 +130,14 @@ static void __init xes_mpc85xx_setup_arch(void)
 
 	xes_mpc85xx_fixups();
 
-#ifdef CONFIG_PCI
-	for_each_node_by_type(np, "pci") {
-		if (of_device_is_compatible(np, "fsl,mpc8540-pci") ||
-		    of_device_is_compatible(np, "fsl,mpc8548-pcie")) {
-			struct resource rsrc;
-			of_address_to_resource(np, 0, &rsrc);
-			if ((rsrc.start & 0xfffff) == primary_phb_addr)
-				fsl_add_bridge(np, 1);
-			else
-				fsl_add_bridge(np, 0);
-		}
-	}
-#endif
-
 	mpc85xx_smp_init();
+
+	fsl_pci_assign_primary();
 }
 
-machine_device_initcall(xes_mpc8572, mpc85xx_common_publish_devices);
-machine_device_initcall(xes_mpc8548, mpc85xx_common_publish_devices);
-machine_device_initcall(xes_mpc8540, mpc85xx_common_publish_devices);
+machine_arch_initcall(xes_mpc8572, mpc85xx_common_publish_devices);
+machine_arch_initcall(xes_mpc8548, mpc85xx_common_publish_devices);
+machine_arch_initcall(xes_mpc8540, mpc85xx_common_publish_devices);
 
 /*
  * Called very early, device-tree isn't unflattened
@@ -165,42 +146,21 @@ static int __init xes_mpc8572_probe(void)
 {
 	unsigned long root = of_get_flat_dt_root();
 
-	if (of_flat_dt_is_compatible(root, "xes,MPC8572")) {
-#ifdef CONFIG_PCI
-		primary_phb_addr = 0x8000;
-#endif
-		return 1;
-	} else {
-		return 0;
-	}
+	return of_flat_dt_is_compatible(root, "xes,MPC8572");
 }
 
 static int __init xes_mpc8548_probe(void)
 {
 	unsigned long root = of_get_flat_dt_root();
 
-	if (of_flat_dt_is_compatible(root, "xes,MPC8548")) {
-#ifdef CONFIG_PCI
-		primary_phb_addr = 0xb000;
-#endif
-		return 1;
-	} else {
-		return 0;
-	}
+	return of_flat_dt_is_compatible(root, "xes,MPC8548");
 }
 
 static int __init xes_mpc8540_probe(void)
 {
 	unsigned long root = of_get_flat_dt_root();
 
-	if (of_flat_dt_is_compatible(root, "xes,MPC8540")) {
-#ifdef CONFIG_PCI
-		primary_phb_addr = 0xb000;
-#endif
-		return 1;
-	} else {
-		return 0;
-	}
+	return of_flat_dt_is_compatible(root, "xes,MPC8540");
 }
 
 define_machine(xes_mpc8572) {
diff --git a/arch/powerpc/platforms/86xx/gef_ppc9a.c b/arch/powerpc/platforms/86xx/gef_ppc9a.c
index 563aafa8..bf53387 100644
--- a/arch/powerpc/platforms/86xx/gef_ppc9a.c
+++ b/arch/powerpc/platforms/86xx/gef_ppc9a.c
@@ -73,13 +73,6 @@ static void __init gef_ppc9a_init_irq(void)
 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 Intelligent Platforms PPC9A 6U VME SBC\n");
 
@@ -87,6 +80,8 @@ static void __init gef_ppc9a_setup_arch(void)
 	mpc86xx_smp_init();
 #endif
 
+	fsl_pci_assign_primary();
+
 	/* Remap basic board registers */
 	regs = of_find_compatible_node(NULL, NULL, "gef,ppc9a-fpga-regs");
 	if (regs) {
@@ -221,6 +216,7 @@ static long __init mpc86xx_time_init(void)
 static __initdata struct of_device_id of_bus_ids[] = {
 	{ .compatible = "simple-bus", },
 	{ .compatible = "gianfar", },
+	{ .compatible = "fsl,mpc8641-pcie", },
 	{},
 };
 
@@ -231,7 +227,7 @@ static int __init declare_of_platform_devices(void)
 
 	return 0;
 }
-machine_device_initcall(gef_ppc9a, declare_of_platform_devices);
+machine_arch_initcall(gef_ppc9a, declare_of_platform_devices);
 
 define_machine(gef_ppc9a) {
 	.name			= "GE PPC9A",
diff --git a/arch/powerpc/platforms/86xx/gef_sbc310.c b/arch/powerpc/platforms/86xx/gef_sbc310.c
index cc6a91a..0b78513 100644
--- a/arch/powerpc/platforms/86xx/gef_sbc310.c
+++ b/arch/powerpc/platforms/86xx/gef_sbc310.c
@@ -73,20 +73,14 @@ static void __init gef_sbc310_init_irq(void)
 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 Intelligent Platforms SBC310 6U VPX SBC\n");
 
 #ifdef CONFIG_SMP
 	mpc86xx_smp_init();
 #endif
 
+	fsl_pci_assign_primary();
+
 	/* Remap basic board registers */
 	regs = of_find_compatible_node(NULL, NULL, "gef,fpga-regs");
 	if (regs) {
@@ -209,6 +203,7 @@ static long __init mpc86xx_time_init(void)
 static __initdata struct of_device_id of_bus_ids[] = {
 	{ .compatible = "simple-bus", },
 	{ .compatible = "gianfar", },
+	{ .compatible = "fsl,mpc8641-pcie", },
 	{},
 };
 
@@ -219,7 +214,7 @@ static int __init declare_of_platform_devices(void)
 
 	return 0;
 }
-machine_device_initcall(gef_sbc310, declare_of_platform_devices);
+machine_arch_initcall(gef_sbc310, declare_of_platform_devices);
 
 define_machine(gef_sbc310) {
 	.name			= "GE SBC310",
diff --git a/arch/powerpc/platforms/86xx/gef_sbc610.c b/arch/powerpc/platforms/86xx/gef_sbc610.c
index aead6b3..b9eb174 100644
--- a/arch/powerpc/platforms/86xx/gef_sbc610.c
+++ b/arch/powerpc/platforms/86xx/gef_sbc610.c
@@ -73,13 +73,6 @@ static void __init gef_sbc610_init_irq(void)
 static void __init gef_sbc610_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 Intelligent Platforms SBC610 6U VPX SBC\n");
 
@@ -87,6 +80,8 @@ static void __init gef_sbc610_setup_arch(void)
 	mpc86xx_smp_init();
 #endif
 
+	fsl_pci_assign_primary();
+
 	/* Remap basic board registers */
 	regs = of_find_compatible_node(NULL, NULL, "gef,fpga-regs");
 	if (regs) {
@@ -198,6 +193,7 @@ static long __init mpc86xx_time_init(void)
 static __initdata struct of_device_id of_bus_ids[] = {
 	{ .compatible = "simple-bus", },
 	{ .compatible = "gianfar", },
+	{ .compatible = "fsl,mpc8641-pcie", },
 	{},
 };
 
@@ -208,7 +204,7 @@ static int __init declare_of_platform_devices(void)
 
 	return 0;
 }
-machine_device_initcall(gef_sbc610, declare_of_platform_devices);
+machine_arch_initcall(gef_sbc610, declare_of_platform_devices);
 
 define_machine(gef_sbc610) {
 	.name			= "GE SBC610",
diff --git a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
index 62cd3c5..a817398 100644
--- a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
+++ b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
@@ -91,6 +91,9 @@ static struct of_device_id __initdata mpc8610_ids[] = {
 	{ .compatible = "simple-bus", },
 	/* So that the DMA channel nodes can be probed individually: */
 	{ .compatible = "fsl,eloplus-dma", },
+	/* PCI controllers */
+	{ .compatible = "fsl,mpc8610-pci", },
+	{ .compatible = "fsl,mpc8641-pcie", },
 	{}
 };
 
@@ -107,7 +110,7 @@ static int __init mpc8610_declare_of_platform_devices(void)
 
 	return 0;
 }
-machine_device_initcall(mpc86xx_hpcd, mpc8610_declare_of_platform_devices);
+machine_arch_initcall(mpc86xx_hpcd, mpc8610_declare_of_platform_devices);
 
 #if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
 
@@ -278,25 +281,13 @@ mpc8610hpcd_valid_monitor_port(enum fsl_diu_monitor_port port)
 static void __init mpc86xx_hpcd_setup_arch(void)
 {
 	struct resource r;
-	struct device_node *np;
 	unsigned char *pixis;
 
 	if (ppc_md.progress)
 		ppc_md.progress("mpc86xx_hpcd_setup_arch()", 0);
 
-#ifdef CONFIG_PCI
-	for_each_node_by_type(np, "pci") {
-		if (of_device_is_compatible(np, "fsl,mpc8610-pci")
-		    || of_device_is_compatible(np, "fsl,mpc8641-pcie")) {
-			struct resource rsrc;
-			of_address_to_resource(np, 0, &rsrc);
-			if ((rsrc.start & 0xfffff) == 0xa000)
-				fsl_add_bridge(np, 1);
-			else
-				fsl_add_bridge(np, 0);
-		}
-        }
-#endif
+	fsl_pci_assign_primary();
+
 #if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
 	diu_ops.get_pixel_format	= mpc8610hpcd_get_pixel_format;
 	diu_ops.set_gamma_table		= mpc8610hpcd_set_gamma_table;
diff --git a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
index 817245b..e8bf3fa 100644
--- a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
+++ b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
@@ -19,7 +19,6 @@
 #include <linux/delay.h>
 #include <linux/seq_file.h>
 #include <linux/of_platform.h>
-#include <linux/memblock.h>
 
 #include <asm/time.h>
 #include <asm/machdep.h>
@@ -51,15 +50,8 @@ extern int uli_exclude_device(struct pci_controller *hose,
 static int mpc86xx_exclude_device(struct pci_controller *hose,
 				   u_char bus, u_char devfn)
 {
-	struct device_node* node;	
-	struct resource rsrc;
-
-	node = hose->dn;
-	of_address_to_resource(node, 0, &rsrc);
-
-	if ((rsrc.start & 0xfffff) == 0x8000) {
+	if (hose->dn == fsl_pci_primary)
 		return uli_exclude_device(hose, bus, devfn);
-	}
 
 	return PCIBIOS_SUCCESSFUL;
 }
@@ -69,30 +61,11 @@ static int mpc86xx_exclude_device(struct pci_controller *hose,
 static void __init
 mpc86xx_hpcn_setup_arch(void)
 {
-#ifdef CONFIG_PCI
-	struct device_node *np;
-	struct pci_controller *hose;
-#endif
-	dma_addr_t max = 0xffffffff;
-
 	if (ppc_md.progress)
 		ppc_md.progress("mpc86xx_hpcn_setup_arch()", 0);
 
 #ifdef CONFIG_PCI
-	for_each_compatible_node(np, "pci", "fsl,mpc8641-pcie") {
-		struct resource rsrc;
-		of_address_to_resource(np, 0, &rsrc);
-		if ((rsrc.start & 0xfffff) == 0x8000)
-			fsl_add_bridge(np, 1);
-		else
-			fsl_add_bridge(np, 0);
-		hose = pci_find_hose_for_OF_device(np);
-		max = min(max, hose->dma_window_base_cur +
-			  hose->dma_window_size);
-	}
-
 	ppc_md.pci_exclude_device = mpc86xx_exclude_device;
-
 #endif
 
 	printk("MPC86xx HPCN board from Freescale Semiconductor\n");
@@ -101,13 +74,9 @@ mpc86xx_hpcn_setup_arch(void)
 	mpc86xx_smp_init();
 #endif
 
-#ifdef CONFIG_SWIOTLB
-	if ((memblock_end_of_DRAM() - 1) > max) {
-		ppc_swiotlb_enable = 1;
-		set_pci_dma_ops(&swiotlb_dma_ops);
-		ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb;
-	}
-#endif
+	fsl_pci_assign_primary();
+
+	swiotlb_detect_4g();
 }
 
 
@@ -162,6 +131,7 @@ static __initdata struct of_device_id of_bus_ids[] = {
 	{ .compatible = "simple-bus", },
 	{ .compatible = "fsl,srio", },
 	{ .compatible = "gianfar", },
+	{ .compatible = "fsl,mpc8641-pcie", },
 	{},
 };
 
@@ -171,7 +141,7 @@ static int __init declare_of_platform_devices(void)
 
 	return 0;
 }
-machine_device_initcall(mpc86xx_hpcn, declare_of_platform_devices);
+machine_arch_initcall(mpc86xx_hpcn, declare_of_platform_devices);
 machine_arch_initcall(mpc86xx_hpcn, swiotlb_setup_bus_notifier);
 
 define_machine(mpc86xx_hpcn) {
diff --git a/arch/powerpc/platforms/86xx/sbc8641d.c b/arch/powerpc/platforms/86xx/sbc8641d.c
index e7007d0..b47a8fd 100644
--- a/arch/powerpc/platforms/86xx/sbc8641d.c
+++ b/arch/powerpc/platforms/86xx/sbc8641d.c
@@ -38,23 +38,16 @@
 static void __init
 sbc8641_setup_arch(void)
 {
-#ifdef CONFIG_PCI
-	struct device_node *np;
-#endif
-
 	if (ppc_md.progress)
 		ppc_md.progress("sbc8641_setup_arch()", 0);
 
-#ifdef CONFIG_PCI
-	for_each_compatible_node(np, "pci", "fsl,mpc8641-pcie")
-		fsl_add_bridge(np, 0);
-#endif
-
 	printk("SBC8641 board from Wind River\n");
 
 #ifdef CONFIG_SMP
 	mpc86xx_smp_init();
 #endif
+
+	fsl_pci_assign_primary();
 }
 
 
@@ -102,6 +95,7 @@ mpc86xx_time_init(void)
 static __initdata struct of_device_id of_bus_ids[] = {
 	{ .compatible = "simple-bus", },
 	{ .compatible = "gianfar", },
+	{ .compatible = "fsl,mpc8641-pcie", },
 	{},
 };
 
@@ -111,7 +105,7 @@ static int __init declare_of_platform_devices(void)
 
 	return 0;
 }
-machine_device_initcall(sbc8641, declare_of_platform_devices);
+machine_arch_initcall(sbc8641, declare_of_platform_devices);
 
 define_machine(sbc8641) {
 	.name			= "SBC8641D",
diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig
index e7a896a..48a920d 100644
--- a/arch/powerpc/platforms/Kconfig
+++ b/arch/powerpc/platforms/Kconfig
@@ -90,6 +90,7 @@ config MPIC
 config PPC_EPAPR_HV_PIC
 	bool
 	default n
+	select EPAPR_PARAVIRT
 
 config MPIC_WEIRD
 	bool
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype
index 30fd01d..72afd28 100644
--- a/arch/powerpc/platforms/Kconfig.cputype
+++ b/arch/powerpc/platforms/Kconfig.cputype
@@ -1,6 +1,7 @@
 config PPC64
 	bool "64-bit kernel"
 	default n
+	select HAVE_VIRT_CPU_ACCOUNTING
 	help
 	  This option selects whether a 32-bit or a 64-bit kernel
 	  will be built.
@@ -337,21 +338,6 @@ config PPC_MM_SLICES
 	default y if (!PPC_FSL_BOOK3E && PPC64 && HUGETLB_PAGE) || (PPC_STD_MMU_64 && PPC_64K_PAGES)
 	default n
 
-config VIRT_CPU_ACCOUNTING
-	bool "Deterministic task and CPU time accounting"
-	depends on PPC64
-	default y
-	help
-	  Select this option to enable more accurate task and CPU time
-	  accounting.  This is done by reading a CPU counter on each
-	  kernel entry and exit and on transitions within the kernel
-	  between system, softirq and hardirq state, so there is a
-	  small performance impact.  This also enables accounting of
-	  stolen time on logically-partitioned systems running on
-	  IBM POWER5-based machines.
-
-	  If in doubt, say Y here.
-
 config PPC_HAVE_PMU_SUPPORT
        bool
 
diff --git a/arch/powerpc/platforms/cell/beat.c b/arch/powerpc/platforms/cell/beat.c
index 852592b..affcf56 100644
--- a/arch/powerpc/platforms/cell/beat.c
+++ b/arch/powerpc/platforms/cell/beat.c
@@ -136,9 +136,9 @@ ssize_t beat_nvram_get_size(void)
 	return BEAT_NVRAM_SIZE;
 }
 
-int beat_set_xdabr(unsigned long dabr)
+int beat_set_xdabr(unsigned long dabr, unsigned long dabrx)
 {
-	if (beat_set_dabr(dabr, DABRX_KERNEL | DABRX_USER))
+	if (beat_set_dabr(dabr, dabrx))
 		return -1;
 	return 0;
 }
diff --git a/arch/powerpc/platforms/cell/beat.h b/arch/powerpc/platforms/cell/beat.h
index 32c8efc..bfcb8e3 100644
--- a/arch/powerpc/platforms/cell/beat.h
+++ b/arch/powerpc/platforms/cell/beat.h
@@ -32,7 +32,7 @@ void beat_get_rtc_time(struct rtc_time *);
 ssize_t beat_nvram_get_size(void);
 ssize_t beat_nvram_read(char *, size_t, loff_t *);
 ssize_t beat_nvram_write(char *, size_t, loff_t *);
-int beat_set_xdabr(unsigned long);
+int beat_set_xdabr(unsigned long, unsigned long);
 void beat_power_save(void);
 void beat_kexec_cpu_down(int, int);
 
diff --git a/arch/powerpc/platforms/cell/beat_htab.c b/arch/powerpc/platforms/cell/beat_htab.c
index 943c9d3..0f6f839 100644
--- a/arch/powerpc/platforms/cell/beat_htab.c
+++ b/arch/powerpc/platforms/cell/beat_htab.c
@@ -88,7 +88,7 @@ static inline unsigned int beat_read_mask(unsigned hpte_group)
 }
 
 static long beat_lpar_hpte_insert(unsigned long hpte_group,
-				  unsigned long va, unsigned long pa,
+				  unsigned long vpn, unsigned long pa,
 				  unsigned long rflags, unsigned long vflags,
 				  int psize, int ssize)
 {
@@ -103,7 +103,7 @@ static long beat_lpar_hpte_insert(unsigned long hpte_group,
 			"rflags=%lx, vflags=%lx, psize=%d)\n",
 		hpte_group, va, pa, rflags, vflags, psize);
 
-	hpte_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M) |
+	hpte_v = hpte_encode_v(vpn, psize, MMU_SEGSIZE_256M) |
 		vflags | HPTE_V_VALID;
 	hpte_r = hpte_encode_r(pa, psize) | rflags;
 
@@ -184,14 +184,14 @@ static void beat_lpar_hptab_clear(void)
  */
 static long beat_lpar_hpte_updatepp(unsigned long slot,
 				    unsigned long newpp,
-				    unsigned long va,
+				    unsigned long vpn,
 				    int psize, int ssize, int local)
 {
 	unsigned long lpar_rc;
 	u64 dummy0, dummy1;
 	unsigned long want_v;
 
-	want_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M);
+	want_v = hpte_encode_v(vpn, psize, MMU_SEGSIZE_256M);
 
 	DBG_LOW("    update: "
 		"avpnv=%016lx, slot=%016lx, psize: %d, newpp %016lx ... ",
@@ -220,15 +220,15 @@ static long beat_lpar_hpte_updatepp(unsigned long slot,
 	return 0;
 }
 
-static long beat_lpar_hpte_find(unsigned long va, int psize)
+static long beat_lpar_hpte_find(unsigned long vpn, int psize)
 {
 	unsigned long hash;
 	unsigned long i, j;
 	long slot;
 	unsigned long want_v, hpte_v;
 
-	hash = hpt_hash(va, mmu_psize_defs[psize].shift, MMU_SEGSIZE_256M);
-	want_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M);
+	hash = hpt_hash(vpn, mmu_psize_defs[psize].shift, MMU_SEGSIZE_256M);
+	want_v = hpte_encode_v(vpn, psize, MMU_SEGSIZE_256M);
 
 	for (j = 0; j < 2; j++) {
 		slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
@@ -255,14 +255,15 @@ static void beat_lpar_hpte_updateboltedpp(unsigned long newpp,
 					  unsigned long ea,
 					  int psize, int ssize)
 {
-	unsigned long lpar_rc, slot, vsid, va;
+	unsigned long vpn;
+	unsigned long lpar_rc, slot, vsid;
 	u64 dummy0, dummy1;
 
 	vsid = get_kernel_vsid(ea, MMU_SEGSIZE_256M);
-	va = (vsid << 28) | (ea & 0x0fffffff);
+	vpn = hpt_vpn(ea, vsid, MMU_SEGSIZE_256M);
 
 	raw_spin_lock(&beat_htab_lock);
-	slot = beat_lpar_hpte_find(va, psize);
+	slot = beat_lpar_hpte_find(vpn, psize);
 	BUG_ON(slot == -1);
 
 	lpar_rc = beat_write_htab_entry(0, slot, 0, newpp, 0, 7,
@@ -272,7 +273,7 @@ static void beat_lpar_hpte_updateboltedpp(unsigned long newpp,
 	BUG_ON(lpar_rc != 0);
 }
 
-static void beat_lpar_hpte_invalidate(unsigned long slot, unsigned long va,
+static void beat_lpar_hpte_invalidate(unsigned long slot, unsigned long vpn,
 					 int psize, int ssize, int local)
 {
 	unsigned long want_v;
@@ -282,7 +283,7 @@ static void beat_lpar_hpte_invalidate(unsigned long slot, unsigned long va,
 
 	DBG_LOW("    inval : slot=%lx, va=%016lx, psize: %d, local: %d\n",
 		slot, va, psize, local);
-	want_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M);
+	want_v = hpte_encode_v(vpn, psize, MMU_SEGSIZE_256M);
 
 	raw_spin_lock_irqsave(&beat_htab_lock, flags);
 	dummy1 = beat_lpar_hpte_getword0(slot);
@@ -311,7 +312,7 @@ void __init hpte_init_beat(void)
 }
 
 static long beat_lpar_hpte_insert_v3(unsigned long hpte_group,
-				  unsigned long va, unsigned long pa,
+				  unsigned long vpn, unsigned long pa,
 				  unsigned long rflags, unsigned long vflags,
 				  int psize, int ssize)
 {
@@ -322,11 +323,11 @@ static long beat_lpar_hpte_insert_v3(unsigned long hpte_group,
 		return -1;
 
 	if (!(vflags & HPTE_V_BOLTED))
-		DBG_LOW("hpte_insert(group=%lx, va=%016lx, pa=%016lx, "
+		DBG_LOW("hpte_insert(group=%lx, vpn=%016lx, pa=%016lx, "
 			"rflags=%lx, vflags=%lx, psize=%d)\n",
-		hpte_group, va, pa, rflags, vflags, psize);
+		hpte_group, vpn, pa, rflags, vflags, psize);
 
-	hpte_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M) |
+	hpte_v = hpte_encode_v(vpn, psize, MMU_SEGSIZE_256M) |
 		vflags | HPTE_V_VALID;
 	hpte_r = hpte_encode_r(pa, psize) | rflags;
 
@@ -364,14 +365,14 @@ static long beat_lpar_hpte_insert_v3(unsigned long hpte_group,
  */
 static long beat_lpar_hpte_updatepp_v3(unsigned long slot,
 				    unsigned long newpp,
-				    unsigned long va,
+				    unsigned long vpn,
 				    int psize, int ssize, int local)
 {
 	unsigned long lpar_rc;
 	unsigned long want_v;
 	unsigned long pss;
 
-	want_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M);
+	want_v = hpte_encode_v(vpn, psize, MMU_SEGSIZE_256M);
 	pss = (psize == MMU_PAGE_4K) ? -1UL : mmu_psize_defs[psize].penc;
 
 	DBG_LOW("    update: "
@@ -392,16 +393,16 @@ static long beat_lpar_hpte_updatepp_v3(unsigned long slot,
 	return 0;
 }
 
-static void beat_lpar_hpte_invalidate_v3(unsigned long slot, unsigned long va,
+static void beat_lpar_hpte_invalidate_v3(unsigned long slot, unsigned long vpn,
 					 int psize, int ssize, int local)
 {
 	unsigned long want_v;
 	unsigned long lpar_rc;
 	unsigned long pss;
 
-	DBG_LOW("    inval : slot=%lx, va=%016lx, psize: %d, local: %d\n",
-		slot, va, psize, local);
-	want_v = hpte_encode_v(va, psize, MMU_SEGSIZE_256M);
+	DBG_LOW("    inval : slot=%lx, vpn=%016lx, psize: %d, local: %d\n",
+		slot, vpn, psize, local);
+	want_v = hpte_encode_v(vpn, psize, MMU_SEGSIZE_256M);
 	pss = (psize == MMU_PAGE_4K) ? -1UL : mmu_psize_defs[psize].penc;
 
 	lpar_rc = beat_invalidate_htab_entry3(0, slot, want_v, pss);
diff --git a/arch/powerpc/platforms/cell/celleb_pci.c b/arch/powerpc/platforms/cell/celleb_pci.c
index 5822141..abc8af4 100644
--- a/arch/powerpc/platforms/cell/celleb_pci.c
+++ b/arch/powerpc/platforms/cell/celleb_pci.c
@@ -472,7 +472,7 @@ int __init celleb_setup_phb(struct pci_controller *phb)
 {
 	struct device_node *dev = phb->dn;
 	const struct of_device_id *match;
-	struct celleb_phb_spec *phb_spec;
+	const struct celleb_phb_spec *phb_spec;
 	int rc;
 
 	match = of_match_node(celleb_phb_match, dev);
diff --git a/arch/powerpc/platforms/cell/cpufreq_spudemand.c b/arch/powerpc/platforms/cell/cpufreq_spudemand.c
index 23bc9db..82607d6 100644
--- a/arch/powerpc/platforms/cell/cpufreq_spudemand.c
+++ b/arch/powerpc/platforms/cell/cpufreq_spudemand.c
@@ -76,7 +76,7 @@ static void spu_gov_work(struct work_struct *work)
 static void spu_gov_init_work(struct spu_gov_info_struct *info)
 {
 	int delay = usecs_to_jiffies(info->poll_int);
-	INIT_DELAYED_WORK_DEFERRABLE(&info->work, spu_gov_work);
+	INIT_DEFERRABLE_WORK(&info->work, spu_gov_work);
 	schedule_delayed_work_on(info->policy->cpu, &info->work, delay);
 }
 
diff --git a/arch/powerpc/platforms/cell/spu_syscalls.c b/arch/powerpc/platforms/cell/spu_syscalls.c
index 714bbfc..db4e638 100644
--- a/arch/powerpc/platforms/cell/spu_syscalls.c
+++ b/arch/powerpc/platforms/cell/spu_syscalls.c
@@ -69,8 +69,6 @@ SYSCALL_DEFINE4(spu_create, const char __user *, name, unsigned int, flags,
 	umode_t, mode, int, neighbor_fd)
 {
 	long ret;
-	struct file *neighbor;
-	int fput_needed;
 	struct spufs_calls *calls;
 
 	calls = spufs_calls_get();
@@ -78,11 +76,11 @@ SYSCALL_DEFINE4(spu_create, const char __user *, name, unsigned int, flags,
 		return -ENOSYS;
 
 	if (flags & SPU_CREATE_AFFINITY_SPU) {
+		struct fd neighbor = fdget(neighbor_fd);
 		ret = -EBADF;
-		neighbor = fget_light(neighbor_fd, &fput_needed);
-		if (neighbor) {
-			ret = calls->create_thread(name, flags, mode, neighbor);
-			fput_light(neighbor, fput_needed);
+		if (neighbor.file) {
+			ret = calls->create_thread(name, flags, mode, neighbor.file);
+			fdput(neighbor);
 		}
 	} else
 		ret = calls->create_thread(name, flags, mode, NULL);
@@ -94,8 +92,7 @@ SYSCALL_DEFINE4(spu_create, const char __user *, name, unsigned int, flags,
 asmlinkage long sys_spu_run(int fd, __u32 __user *unpc, __u32 __user *ustatus)
 {
 	long ret;
-	struct file *filp;
-	int fput_needed;
+	struct fd arg;
 	struct spufs_calls *calls;
 
 	calls = spufs_calls_get();
@@ -103,10 +100,10 @@ asmlinkage long sys_spu_run(int fd, __u32 __user *unpc, __u32 __user *ustatus)
 		return -ENOSYS;
 
 	ret = -EBADF;
-	filp = fget_light(fd, &fput_needed);
-	if (filp) {
-		ret = calls->spu_run(filp, unpc, ustatus);
-		fput_light(filp, fput_needed);
+	arg = fdget(fd);
+	if (arg.file) {
+		ret = calls->spu_run(arg.file, unpc, ustatus);
+		fdput(arg);
 	}
 
 	spufs_calls_put(calls);
diff --git a/arch/powerpc/platforms/cell/spufs/coredump.c b/arch/powerpc/platforms/cell/spufs/coredump.c
index c2c5b07..657e3f2 100644
--- a/arch/powerpc/platforms/cell/spufs/coredump.c
+++ b/arch/powerpc/platforms/cell/spufs/coredump.c
@@ -106,6 +106,17 @@ static int spufs_ctx_note_size(struct spu_context *ctx, int dfd)
 	return total;
 }
 
+static int match_context(const void *v, struct file *file, unsigned fd)
+{
+	struct spu_context *ctx;
+	if (file->f_op != &spufs_context_fops)
+		return 0;
+	ctx = SPUFS_I(file->f_dentry->d_inode)->i_ctx;
+	if (ctx->flags & SPU_CREATE_NOSCHED)
+		return 0;
+	return fd + 1;
+}
+
 /*
  * The additional architecture-specific notes for Cell are various
  * context files in the spu context.
@@ -115,29 +126,18 @@ static int spufs_ctx_note_size(struct spu_context *ctx, int dfd)
  * internal functionality to dump them without needing to actually
  * open the files.
  */
+/*
+ * descriptor table is not shared, so files can't change or go away.
+ */
 static struct spu_context *coredump_next_context(int *fd)
 {
-	struct fdtable *fdt = files_fdtable(current->files);
 	struct file *file;
-	struct spu_context *ctx = NULL;
-
-	for (; *fd < fdt->max_fds; (*fd)++) {
-		if (!fd_is_open(*fd, fdt))
-			continue;
-
-		file = fcheck(*fd);
-
-		if (!file || file->f_op != &spufs_context_fops)
-			continue;
-
-		ctx = SPUFS_I(file->f_dentry->d_inode)->i_ctx;
-		if (ctx->flags & SPU_CREATE_NOSCHED)
-			continue;
-
-		break;
-	}
-
-	return ctx;
+	int n = iterate_fd(current->files, *fd, match_context, NULL);
+	if (!n)
+		return NULL;
+	*fd = n - 1;
+	file = fcheck(*fd);
+	return SPUFS_I(file->f_dentry->d_inode)->i_ctx;
 }
 
 int spufs_coredump_extra_notes_size(void)
diff --git a/arch/powerpc/platforms/pasemi/iommu.c b/arch/powerpc/platforms/pasemi/iommu.c
index 14943ef..7d2d036 100644
--- a/arch/powerpc/platforms/pasemi/iommu.c
+++ b/arch/powerpc/platforms/pasemi/iommu.c
@@ -19,12 +19,12 @@
 
 #undef DEBUG
 
+#include <linux/memblock.h>
 #include <linux/types.h>
 #include <linux/spinlock.h>
 #include <linux/pci.h>
 #include <asm/iommu.h>
 #include <asm/machdep.h>
-#include <asm/abs_addr.h>
 #include <asm/firmware.h>
 
 #define IOBMAP_PAGE_SHIFT	12
@@ -99,7 +99,7 @@ static int iobmap_build(struct iommu_table *tbl, long index,
 	ip = ((u32 *)tbl->it_base) + index;
 
 	while (npages--) {
-		rpn = virt_to_abs(uaddr) >> IOBMAP_PAGE_SHIFT;
+		rpn = __pa(uaddr) >> IOBMAP_PAGE_SHIFT;
 
 		*(ip++) = IOBMAP_L2E_V | rpn;
 		/* invalidate tlb, can be optimized more */
@@ -258,7 +258,7 @@ void __init alloc_iobmap_l2(void)
 	return;
 #endif
 	/* For 2G space, 8x64 pages (2^21 bytes) is max total l2 size */
-	iob_l2_base = (u32 *)abs_to_virt(memblock_alloc_base(1UL<<21, 1UL<<21, 0x80000000));
+	iob_l2_base = (u32 *)__va(memblock_alloc_base(1UL<<21, 1UL<<21, 0x80000000));
 
 	printk(KERN_INFO "IOBMAP L2 allocated at: %p\n", iob_l2_base);
 }
diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c
index 9cda6a1..471aa3c 100644
--- a/arch/powerpc/platforms/powernv/pci-ioda.c
+++ b/arch/powerpc/platforms/powernv/pci-ioda.c
@@ -30,19 +30,10 @@
 #include <asm/opal.h>
 #include <asm/iommu.h>
 #include <asm/tce.h>
-#include <asm/abs_addr.h>
 
 #include "powernv.h"
 #include "pci.h"
 
-struct resource_wrap {
-	struct list_head	link;
-	resource_size_t		size;
-	resource_size_t		align;
-	struct pci_dev		*dev;	/* Set if it's a device */
-	struct pci_bus		*bus;	/* Set if it's a bridge */
-};
-
 static int __pe_printk(const char *level, const struct pnv_ioda_pe *pe,
 		       struct va_format *vaf)
 {
@@ -78,273 +69,6 @@ define_pe_printk_level(pe_err, KERN_ERR);
 define_pe_printk_level(pe_warn, KERN_WARNING);
 define_pe_printk_level(pe_info, KERN_INFO);
 
-
-/* Calculate resource usage & alignment requirement of a single
- * device. This will also assign all resources within the device
- * for a given type starting at 0 for the biggest one and then
- * assigning in decreasing order of size.
- */
-static void __devinit pnv_ioda_calc_dev(struct pci_dev *dev, unsigned int flags,
-					resource_size_t *size,
-					resource_size_t *align)
-{
-	resource_size_t start;
-	struct resource *r;
-	int i;
-
-	pr_devel("  -> CDR %s\n", pci_name(dev));
-
-	*size = *align = 0;
-
-	/* Clear the resources out and mark them all unset */
-	for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
-		r = &dev->resource[i];
-		if (!(r->flags & flags))
-		    continue;
-		if (r->start) {
-			r->end -= r->start;
-			r->start = 0;
-		}
-		r->flags |= IORESOURCE_UNSET;
-	}
-
-	/* We currently keep all memory resources together, we
-	 * will handle prefetch & 64-bit separately in the future
-	 * but for now we stick everybody in M32
-	 */
-	start = 0;
-	for (;;) {
-		resource_size_t max_size = 0;
-		int max_no = -1;
-
-		/* Find next biggest resource */
-		for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
-			r = &dev->resource[i];
-			if (!(r->flags & IORESOURCE_UNSET) ||
-			    !(r->flags & flags))
-				continue;
-			if (resource_size(r) > max_size) {
-				max_size = resource_size(r);
-				max_no = i;
-			}
-		}
-		if (max_no < 0)
-			break;
-		r = &dev->resource[max_no];
-		if (max_size > *align)
-			*align = max_size;
-		*size += max_size;
-		r->start = start;
-		start += max_size;
-		r->end = r->start + max_size - 1;
-		r->flags &= ~IORESOURCE_UNSET;
-		pr_devel("  ->     R%d %016llx..%016llx\n",
-			 max_no, r->start, r->end);
-	}
-	pr_devel("  <- CDR %s size=%llx align=%llx\n",
-		 pci_name(dev), *size, *align);
-}
-
-/* Allocate a resource "wrap" for a given device or bridge and
- * insert it at the right position in the sorted list
- */
-static void __devinit pnv_ioda_add_wrap(struct list_head *list,
-					struct pci_bus *bus,
-					struct pci_dev *dev,
-					resource_size_t size,
-					resource_size_t align)
-{
-	struct resource_wrap *w1, *w = kzalloc(sizeof(*w), GFP_KERNEL);
-
-	w->size = size;
-	w->align = align;
-	w->dev = dev;
-	w->bus = bus;
-
-	list_for_each_entry(w1, list, link) {
-		if (w1->align < align) {
-			list_add_tail(&w->link, &w1->link);
-			return;
-		}
-	}
-	list_add_tail(&w->link, list);
-}
-
-/* Offset device resources of a given type */
-static void __devinit pnv_ioda_offset_dev(struct pci_dev *dev,
-					  unsigned int flags,
-					  resource_size_t offset)
-{
-	struct resource *r;
-	int i;
-
-	pr_devel("  -> ODR %s [%x] +%016llx\n", pci_name(dev), flags, offset);
-
-	for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
-		r = &dev->resource[i];
-		if (r->flags & flags) {
-			dev->resource[i].start += offset;
-			dev->resource[i].end += offset;
-		}
-	}
-
-	pr_devel("  <- ODR %s [%x] +%016llx\n", pci_name(dev), flags, offset);
-}
-
-/* Offset bus resources (& all children) of a given type */
-static void __devinit pnv_ioda_offset_bus(struct pci_bus *bus,
-					  unsigned int flags,
-					  resource_size_t offset)
-{
-	struct resource *r;
-	struct pci_dev *dev;
-	struct pci_bus *cbus;
-	int i;
-
-	pr_devel("  -> OBR %s [%x] +%016llx\n",
-		 bus->self ? pci_name(bus->self) : "root", flags, offset);
-
-	pci_bus_for_each_resource(bus, r, i) {
-		if (r && (r->flags & flags)) {
-			r->start += offset;
-			r->end += offset;
-		}
-	}
-	list_for_each_entry(dev, &bus->devices, bus_list)
-		pnv_ioda_offset_dev(dev, flags, offset);
-	list_for_each_entry(cbus, &bus->children, node)
-		pnv_ioda_offset_bus(cbus, flags, offset);
-
-	pr_devel("  <- OBR %s [%x]\n",
-		 bus->self ? pci_name(bus->self) : "root", flags);
-}
-
-/* This is the guts of our IODA resource allocation. This is called
- * recursively for each bus in the system. It calculates all the
- * necessary size and requirements for children and assign them
- * resources such that:
- *
- *   - Each function fits in it's own contiguous set of IO/M32
- *     segment
- *
- *   - All segments behind a P2P bridge are contiguous and obey
- *     alignment constraints of those bridges
- */
-static void __devinit pnv_ioda_calc_bus(struct pci_bus *bus, unsigned int flags,
-					resource_size_t *size,
-					resource_size_t *align)
-{
-	struct pci_controller *hose = pci_bus_to_host(bus);
-	struct pnv_phb *phb = hose->private_data;
-	resource_size_t dev_size, dev_align, start;
-	resource_size_t min_align, min_balign;
-	struct pci_dev *cdev;
-	struct pci_bus *cbus;
-	struct list_head head;
-	struct resource_wrap *w;
-	unsigned int bres;
-
-	*size = *align = 0;
-
-	pr_devel("-> CBR %s [%x]\n",
-		 bus->self ? pci_name(bus->self) : "root", flags);
-
-	/* Calculate alignment requirements based on the type
-	 * of resource we are working on
-	 */
-	if (flags & IORESOURCE_IO) {
-		bres = 0;
-		min_align = phb->ioda.io_segsize;
-		min_balign = 0x1000;
-	} else {
-		bres = 1;
-		min_align = phb->ioda.m32_segsize;
-		min_balign = 0x100000;
-	}
-
-	/* Gather all our children resources ordered by alignment */
-	INIT_LIST_HEAD(&head);
-
-	/*   - Busses */
-	list_for_each_entry(cbus, &bus->children, node) {
-		pnv_ioda_calc_bus(cbus, flags, &dev_size, &dev_align);
-		pnv_ioda_add_wrap(&head, cbus, NULL, dev_size, dev_align);
-	}
-
-	/*   - Devices */
-	list_for_each_entry(cdev, &bus->devices, bus_list) {
-		pnv_ioda_calc_dev(cdev, flags, &dev_size, &dev_align);
-		/* Align them to segment size */
-		if (dev_align < min_align)
-			dev_align = min_align;
-		pnv_ioda_add_wrap(&head, NULL, cdev, dev_size, dev_align);
-	}
-	if (list_empty(&head))
-		goto empty;
-
-	/* Now we can do two things: assign offsets to them within that
-	 * level and get our total alignment & size requirements. The
-	 * assignment algorithm is going to be uber-trivial for now, we
-	 * can try to be smarter later at filling out holes.
-	 */
-	if (bus->self) {
-		/* No offset for downstream bridges */
-		start = 0;
-	} else {
-		/* Offset from the root */
-		if (flags & IORESOURCE_IO)
-			/* Don't hand out IO 0 */
-			start = hose->io_resource.start + 0x1000;
-		else
-			start = hose->mem_resources[0].start;
-	}
-	while(!list_empty(&head)) {
-		w = list_first_entry(&head, struct resource_wrap, link);
-		list_del(&w->link);
-		if (w->size) {
-			if (start) {
-				start = ALIGN(start, w->align);
-				if (w->dev)
-					pnv_ioda_offset_dev(w->dev,flags,start);
-				else if (w->bus)
-					pnv_ioda_offset_bus(w->bus,flags,start);
-			}
-			if (w->align > *align)
-				*align = w->align;
-		}
-		start += w->size;
-		kfree(w);
-	}
-	*size = start;
-
-	/* Align and setup bridge resources */
-	*align = max_t(resource_size_t, *align,
-		       max_t(resource_size_t, min_align, min_balign));
-	*size = ALIGN(*size,
-		      max_t(resource_size_t, min_align, min_balign));
- empty:
-	/* Only setup P2P's, not the PHB itself */
-	if (bus->self) {
-		struct resource *res = bus->resource[bres];
-
-		if (WARN_ON(res == NULL))
-			return;
-
-		/*
-		 * FIXME: We should probably export and call
-		 * pci_bridge_check_ranges() to properly re-initialize
-		 * the PCI portion of the flags here, and to detect
-		 * what the bridge actually supports.
-		 */
-		res->start = 0;
-		res->flags = (*size) ? flags : 0;
-		res->end = (*size) ? (*size - 1) : 0;
-	}
-
-	pr_devel("<- CBR %s [%x] *size=%016llx *align=%016llx\n",
-		 bus->self ? pci_name(bus->self) : "root", flags,*size,*align);
-}
-
 static struct pci_dn *pnv_ioda_get_pdn(struct pci_dev *dev)
 {
 	struct device_node *np;
@@ -355,172 +79,6 @@ static struct pci_dn *pnv_ioda_get_pdn(struct pci_dev *dev)
 	return PCI_DN(np);
 }
 
-static void __devinit pnv_ioda_setup_pe_segments(struct pci_dev *dev)
-{
-	struct pci_controller *hose = pci_bus_to_host(dev->bus);
-	struct pnv_phb *phb = hose->private_data;
-	struct pci_dn *pdn = pnv_ioda_get_pdn(dev);
-	unsigned int pe, i;
-	resource_size_t pos;
-	struct resource io_res;
-	struct resource m32_res;
-	struct pci_bus_region region;
-	int rc;
-
-	/* Anything not referenced in the device-tree gets PE#0 */
-	pe = pdn ? pdn->pe_number : 0;
-
-	/* Calculate the device min/max */
-	io_res.start = m32_res.start = (resource_size_t)-1;
-	io_res.end = m32_res.end = 0;
-	io_res.flags = IORESOURCE_IO;
-	m32_res.flags = IORESOURCE_MEM;
-
-	for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
-		struct resource *r = NULL;
-		if (dev->resource[i].flags & IORESOURCE_IO)
-			r = &io_res;
-		if (dev->resource[i].flags & IORESOURCE_MEM)
-			r = &m32_res;
-		if (!r)
-			continue;
-		if (dev->resource[i].start < r->start)
-			r->start = dev->resource[i].start;
-		if (dev->resource[i].end > r->end)
-			r->end = dev->resource[i].end;
-	}
-
-	/* Setup IO segments */
-	if (io_res.start < io_res.end) {
-		pcibios_resource_to_bus(dev, &region, &io_res);
-		pos = region.start;
-		i = pos / phb->ioda.io_segsize;
-		while(i < phb->ioda.total_pe && pos <= region.end) {
-			if (phb->ioda.io_segmap[i]) {
-				pr_err("%s: Trying to use IO seg #%d which is"
-				       " already used by PE# %d\n",
-				       pci_name(dev), i,
-				       phb->ioda.io_segmap[i]);
-				/* XXX DO SOMETHING TO DISABLE DEVICE ? */
-				break;
-			}
-			phb->ioda.io_segmap[i] = pe;
-			rc = opal_pci_map_pe_mmio_window(phb->opal_id, pe,
-							 OPAL_IO_WINDOW_TYPE,
-							 0, i);
-			if (rc != OPAL_SUCCESS) {
-				pr_err("%s: OPAL error %d setting up mapping"
-				       " for IO seg# %d\n",
-				       pci_name(dev), rc, i);
-				/* XXX DO SOMETHING TO DISABLE DEVICE ? */
-				break;
-			}
-			pos += phb->ioda.io_segsize;
-			i++;
-		};
-	}
-
-	/* Setup M32 segments */
-	if (m32_res.start < m32_res.end) {
-		pcibios_resource_to_bus(dev, &region, &m32_res);
-		pos = region.start;
-		i = pos / phb->ioda.m32_segsize;
-		while(i < phb->ioda.total_pe && pos <= region.end) {
-			if (phb->ioda.m32_segmap[i]) {
-				pr_err("%s: Trying to use M32 seg #%d which is"
-				       " already used by PE# %d\n",
-				       pci_name(dev), i,
-				       phb->ioda.m32_segmap[i]);
-				/* XXX DO SOMETHING TO DISABLE DEVICE ? */
-				break;
-			}
-			phb->ioda.m32_segmap[i] = pe;
-			rc = opal_pci_map_pe_mmio_window(phb->opal_id, pe,
-							 OPAL_M32_WINDOW_TYPE,
-							 0, i);
-			if (rc != OPAL_SUCCESS) {
-				pr_err("%s: OPAL error %d setting up mapping"
-				       " for M32 seg# %d\n",
-				       pci_name(dev), rc, i);
-				/* XXX DO SOMETHING TO DISABLE DEVICE ? */
-				break;
-			}
-			pos += phb->ioda.m32_segsize;
-			i++;
-		}
-	}
-}
-
-/* Check if a resource still fits in the total IO or M32 range
- * for a given PHB
- */
-static int __devinit pnv_ioda_resource_fit(struct pci_controller *hose,
-					   struct resource *r)
-{
-	struct resource *bounds;
-
-	if (r->flags & IORESOURCE_IO)
-		bounds = &hose->io_resource;
-	else if (r->flags & IORESOURCE_MEM)
-		bounds = &hose->mem_resources[0];
-	else
-		return 1;
-
-	if (r->start >= bounds->start && r->end <= bounds->end)
-		return 1;
-	r->flags = 0;
-	return 0;
-}
-
-static void __devinit pnv_ioda_update_resources(struct pci_bus *bus)
-{
-	struct pci_controller *hose = pci_bus_to_host(bus);
-	struct pci_bus *cbus;
-	struct pci_dev *cdev;
-	unsigned int i;
-
-	/* We used to clear all device enables here. However it looks like
-	 * clearing MEM enable causes Obsidian (IPR SCS) to go bonkers,
-	 * and shoot fatal errors to the PHB which in turns fences itself
-	 * and we can't recover from that ... yet. So for now, let's leave
-	 * the enables as-is and hope for the best.
-	 */
-
-	/* Check if bus resources fit in our IO or M32 range */
-	for (i = 0; bus->self && (i < 2); i++) {
-		struct resource *r = bus->resource[i];
-		if (r && !pnv_ioda_resource_fit(hose, r))
-			pr_err("%s: Bus %d resource %d disabled, no room\n",
-			       pci_name(bus->self), bus->number, i);
-	}
-
-	/* Update self if it's not a PHB */
-	if (bus->self)
-		pci_setup_bridge(bus);
-
-	/* Update child devices */
-	list_for_each_entry(cdev, &bus->devices, bus_list) {
-		/* Check if resource fits, if not, disabled it */
-		for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
-			struct resource *r = &cdev->resource[i];
-			if (!pnv_ioda_resource_fit(hose, r))
-				pr_err("%s: Resource %d disabled, no room\n",
-				       pci_name(cdev), i);
-		}
-
-		/* Assign segments */
-		pnv_ioda_setup_pe_segments(cdev);
-
-		/* Update HW BARs */
-		for (i = 0; i <= PCI_ROM_RESOURCE; i++)
-			pci_update_resource(cdev, i);
-	}
-
-	/* Update child busses */
-	list_for_each_entry(cbus, &bus->children, node)
-		pnv_ioda_update_resources(cbus);
-}
-
 static int __devinit pnv_ioda_alloc_pe(struct pnv_phb *phb)
 {
 	unsigned long pe;
@@ -548,7 +106,7 @@ static void __devinit pnv_ioda_free_pe(struct pnv_phb *phb, int pe)
  * but in the meantime, we need to protect them to avoid warnings
  */
 #ifdef CONFIG_PCI_MSI
-static struct pnv_ioda_pe * __devinit __pnv_ioda_get_one_pe(struct pci_dev *dev)
+static struct pnv_ioda_pe * __devinit pnv_ioda_get_pe(struct pci_dev *dev)
 {
 	struct pci_controller *hose = pci_bus_to_host(dev->bus);
 	struct pnv_phb *phb = hose->private_data;
@@ -560,19 +118,6 @@ static struct pnv_ioda_pe * __devinit __pnv_ioda_get_one_pe(struct pci_dev *dev)
 		return NULL;
 	return &phb->ioda.pe_array[pdn->pe_number];
 }
-
-static struct pnv_ioda_pe * __devinit pnv_ioda_get_pe(struct pci_dev *dev)
-{
-	struct pnv_ioda_pe *pe = __pnv_ioda_get_one_pe(dev);
-
-	while (!pe && dev->bus->self) {
-		dev = dev->bus->self;
-		pe = __pnv_ioda_get_one_pe(dev);
-		if (pe)
-			pe = pe->bus_pe;
-	}
-	return pe;
-}
 #endif /* CONFIG_PCI_MSI */
 
 static int __devinit pnv_ioda_configure_pe(struct pnv_phb *phb,
@@ -589,7 +134,11 @@ static int __devinit pnv_ioda_configure_pe(struct pnv_phb *phb,
 		dcomp = OPAL_IGNORE_RID_DEVICE_NUMBER;
 		fcomp = OPAL_IGNORE_RID_FUNCTION_NUMBER;
 		parent = pe->pbus->self;
-		count = pe->pbus->busn_res.end - pe->pbus->busn_res.start + 1;
+		if (pe->flags & PNV_IODA_PE_BUS_ALL)
+			count = pe->pbus->busn_res.end - pe->pbus->busn_res.start + 1;
+		else
+			count = 1;
+
 		switch(count) {
 		case  1: bcomp = OpalPciBusAll;		break;
 		case  2: bcomp = OpalPciBus7Bits;	break;
@@ -666,13 +215,13 @@ static void __devinit pnv_ioda_link_pe_by_weight(struct pnv_phb *phb,
 {
 	struct pnv_ioda_pe *lpe;
 
-	list_for_each_entry(lpe, &phb->ioda.pe_list, link) {
+	list_for_each_entry(lpe, &phb->ioda.pe_dma_list, dma_link) {
 		if (lpe->dma_weight < pe->dma_weight) {
-			list_add_tail(&pe->link, &lpe->link);
+			list_add_tail(&pe->dma_link, &lpe->dma_link);
 			return;
 		}
 	}
-	list_add_tail(&pe->link, &phb->ioda.pe_list);
+	list_add_tail(&pe->dma_link, &phb->ioda.pe_dma_list);
 }
 
 static unsigned int pnv_ioda_dma_weight(struct pci_dev *dev)
@@ -699,6 +248,7 @@ static unsigned int pnv_ioda_dma_weight(struct pci_dev *dev)
 	return 10;
 }
 
+#if 0
 static struct pnv_ioda_pe * __devinit pnv_ioda_setup_dev_PE(struct pci_dev *dev)
 {
 	struct pci_controller *hose = pci_bus_to_host(dev->bus);
@@ -767,6 +317,7 @@ static struct pnv_ioda_pe * __devinit pnv_ioda_setup_dev_PE(struct pci_dev *dev)
 
 	return pe;
 }
+#endif /* Useful for SRIOV case */
 
 static void pnv_ioda_setup_same_PE(struct pci_bus *bus, struct pnv_ioda_pe *pe)
 {
@@ -784,34 +335,33 @@ static void pnv_ioda_setup_same_PE(struct pci_bus *bus, struct pnv_ioda_pe *pe)
 		pdn->pcidev = dev;
 		pdn->pe_number = pe->pe_number;
 		pe->dma_weight += pnv_ioda_dma_weight(dev);
-		if (dev->subordinate)
+		if ((pe->flags & PNV_IODA_PE_BUS_ALL) && dev->subordinate)
 			pnv_ioda_setup_same_PE(dev->subordinate, pe);
 	}
 }
 
-static void __devinit pnv_ioda_setup_bus_PE(struct pci_dev *dev,
-					    struct pnv_ioda_pe *ppe)
+/*
+ * There're 2 types of PCI bus sensitive PEs: One that is compromised of
+ * single PCI bus. Another one that contains the primary PCI bus and its
+ * subordinate PCI devices and buses. The second type of PE is normally
+ * orgiriated by PCIe-to-PCI bridge or PLX switch downstream ports.
+ */
+static void __devinit pnv_ioda_setup_bus_PE(struct pci_bus *bus, int all)
 {
-	struct pci_controller *hose = pci_bus_to_host(dev->bus);
+	struct pci_controller *hose = pci_bus_to_host(bus);
 	struct pnv_phb *phb = hose->private_data;
-	struct pci_bus *bus = dev->subordinate;
 	struct pnv_ioda_pe *pe;
 	int pe_num;
 
-	if (!bus) {
-		pr_warning("%s: Bridge without a subordinate bus !\n",
-			   pci_name(dev));
-		return;
-	}
 	pe_num = pnv_ioda_alloc_pe(phb);
 	if (pe_num == IODA_INVALID_PE) {
-		pr_warning("%s: Not enough PE# available, disabling bus\n",
-			   pci_name(dev));
+		pr_warning("%s: Not enough PE# available for PCI bus %04x:%02x\n",
+			__func__, pci_domain_nr(bus), bus->number);
 		return;
 	}
 
 	pe = &phb->ioda.pe_array[pe_num];
-	ppe->bus_pe = pe;
+	pe->flags = (all ? PNV_IODA_PE_BUS_ALL : PNV_IODA_PE_BUS);
 	pe->pbus = bus;
 	pe->pdev = NULL;
 	pe->tce32_seg = -1;
@@ -819,8 +369,12 @@ static void __devinit pnv_ioda_setup_bus_PE(struct pci_dev *dev,
 	pe->rid = bus->busn_res.start << 8;
 	pe->dma_weight = 0;
 
-	pe_info(pe, "Secondary busses %pR associated with PE\n",
-		&bus->busn_res);
+	if (all)
+		pe_info(pe, "Secondary bus %d..%d associated with PE#%d\n",
+			bus->busn_res.start, bus->busn_res.end, pe_num);
+	else
+		pe_info(pe, "Secondary bus %d associated with PE#%d\n",
+			bus->busn_res.start, pe_num);
 
 	if (pnv_ioda_configure_pe(phb, pe)) {
 		/* XXX What do we do here ? */
@@ -833,6 +387,9 @@ static void __devinit pnv_ioda_setup_bus_PE(struct pci_dev *dev,
 	/* Associate it with all child devices */
 	pnv_ioda_setup_same_PE(bus, pe);
 
+	/* Put PE to the list */
+	list_add_tail(&pe->list, &phb->ioda.pe_list);
+
 	/* Account for one DMA PE if at least one DMA capable device exist
 	 * below the bridge
 	 */
@@ -848,17 +405,33 @@ static void __devinit pnv_ioda_setup_bus_PE(struct pci_dev *dev,
 static void __devinit pnv_ioda_setup_PEs(struct pci_bus *bus)
 {
 	struct pci_dev *dev;
-	struct pnv_ioda_pe *pe;
+
+	pnv_ioda_setup_bus_PE(bus, 0);
 
 	list_for_each_entry(dev, &bus->devices, bus_list) {
-		pe = pnv_ioda_setup_dev_PE(dev);
-		if (pe == NULL)
-			continue;
-		/* Leaving the PCIe domain ... single PE# */
-		if (dev->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE)
-			pnv_ioda_setup_bus_PE(dev, pe);
-		else if (dev->subordinate)
-			pnv_ioda_setup_PEs(dev->subordinate);
+		if (dev->subordinate) {
+			if (pci_pcie_type(dev) == PCI_EXP_TYPE_PCI_BRIDGE)
+				pnv_ioda_setup_bus_PE(dev->subordinate, 1);
+			else
+				pnv_ioda_setup_PEs(dev->subordinate);
+		}
+	}
+}
+
+/*
+ * Configure PEs so that the downstream PCI buses and devices
+ * could have their associated PE#. Unfortunately, we didn't
+ * figure out the way to identify the PLX bridge yet. So we
+ * simply put the PCI bus and the subordinate behind the root
+ * port to PE# here. The game rule here is expected to be changed
+ * as soon as we can detected PLX bridge correctly.
+ */
+static void __devinit pnv_pci_ioda_setup_PEs(void)
+{
+	struct pci_controller *hose, *tmp;
+
+	list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
+		pnv_ioda_setup_PEs(hose->bus);
 	}
 }
 
@@ -1000,7 +573,7 @@ static void __devinit pnv_ioda_setup_dma(struct pnv_phb *phb)
 	remaining = phb->ioda.tce32_count;
 	tw = phb->ioda.dma_weight;
 	base = 0;
-	list_for_each_entry(pe, &phb->ioda.pe_list, link) {
+	list_for_each_entry(pe, &phb->ioda.pe_dma_list, dma_link) {
 		if (!pe->dma_weight)
 			continue;
 		if (!remaining) {
@@ -1109,34 +682,151 @@ static void pnv_pci_init_ioda_msis(struct pnv_phb *phb)
 static void pnv_pci_init_ioda_msis(struct pnv_phb *phb) { }
 #endif /* CONFIG_PCI_MSI */
 
-/* This is the starting point of our IODA specific resource
- * allocation process
+/*
+ * This function is supposed to be called on basis of PE from top
+ * to bottom style. So the the I/O or MMIO segment assigned to
+ * parent PE could be overrided by its child PEs if necessary.
  */
-static void __devinit pnv_pci_ioda_fixup_phb(struct pci_controller *hose)
+static void __devinit pnv_ioda_setup_pe_seg(struct pci_controller *hose,
+				struct pnv_ioda_pe *pe)
 {
-	resource_size_t size, align;
-	struct pci_bus *child;
+	struct pnv_phb *phb = hose->private_data;
+	struct pci_bus_region region;
+	struct resource *res;
+	int i, index;
+	int rc;
 
-	/* Associate PEs per functions */
-	pnv_ioda_setup_PEs(hose->bus);
+	/*
+	 * NOTE: We only care PCI bus based PE for now. For PCI
+	 * device based PE, for example SRIOV sensitive VF should
+	 * be figured out later.
+	 */
+	BUG_ON(!(pe->flags & (PNV_IODA_PE_BUS | PNV_IODA_PE_BUS_ALL)));
+
+	pci_bus_for_each_resource(pe->pbus, res, i) {
+		if (!res || !res->flags ||
+		    res->start > res->end)
+			continue;
+
+		if (res->flags & IORESOURCE_IO) {
+			region.start = res->start - phb->ioda.io_pci_base;
+			region.end   = res->end - phb->ioda.io_pci_base;
+			index = region.start / phb->ioda.io_segsize;
+
+			while (index < phb->ioda.total_pe &&
+			       region.start <= region.end) {
+				phb->ioda.io_segmap[index] = pe->pe_number;
+				rc = opal_pci_map_pe_mmio_window(phb->opal_id,
+					pe->pe_number, OPAL_IO_WINDOW_TYPE, 0, index);
+				if (rc != OPAL_SUCCESS) {
+					pr_err("%s: OPAL error %d when mapping IO "
+					       "segment #%d to PE#%d\n",
+					       __func__, rc, index, pe->pe_number);
+					break;
+				}
+
+				region.start += phb->ioda.io_segsize;
+				index++;
+			}
+		} else if (res->flags & IORESOURCE_MEM) {
+			region.start = res->start -
+				       hose->pci_mem_offset -
+				       phb->ioda.m32_pci_base;
+			region.end   = res->end -
+				       hose->pci_mem_offset -
+				       phb->ioda.m32_pci_base;
+			index = region.start / phb->ioda.m32_segsize;
+
+			while (index < phb->ioda.total_pe &&
+			       region.start <= region.end) {
+				phb->ioda.m32_segmap[index] = pe->pe_number;
+				rc = opal_pci_map_pe_mmio_window(phb->opal_id,
+					pe->pe_number, OPAL_M32_WINDOW_TYPE, 0, index);
+				if (rc != OPAL_SUCCESS) {
+					pr_err("%s: OPAL error %d when mapping M32 "
+					       "segment#%d to PE#%d",
+					       __func__, rc, index, pe->pe_number);
+					break;
+				}
+
+				region.start += phb->ioda.m32_segsize;
+				index++;
+			}
+		}
+	}
+}
 
-	/* Calculate all resources */
-	pnv_ioda_calc_bus(hose->bus, IORESOURCE_IO, &size, &align);
-	pnv_ioda_calc_bus(hose->bus, IORESOURCE_MEM, &size, &align);
+static void __devinit pnv_pci_ioda_setup_seg(void)
+{
+	struct pci_controller *tmp, *hose;
+	struct pnv_phb *phb;
+	struct pnv_ioda_pe *pe;
 
-	/* Apply then to HW */
-	pnv_ioda_update_resources(hose->bus);
+	list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
+		phb = hose->private_data;
+		list_for_each_entry(pe, &phb->ioda.pe_list, list) {
+			pnv_ioda_setup_pe_seg(hose, pe);
+		}
+	}
+}
 
-	/* Setup DMA */
-	pnv_ioda_setup_dma(hose->private_data);
+static void __devinit pnv_pci_ioda_setup_DMA(void)
+{
+	struct pci_controller *hose, *tmp;
+	struct pnv_phb *phb;
 
-	/* Configure PCI Express settings */
-	list_for_each_entry(child, &hose->bus->children, node) {
-		struct pci_dev *self = child->self;
-		if (!self)
-			continue;
-		pcie_bus_configure_settings(child, self->pcie_mpss);
+	list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
+		pnv_ioda_setup_dma(hose->private_data);
+
+		/* Mark the PHB initialization done */
+		phb = hose->private_data;
+		phb->initialized = 1;
+	}
+}
+
+static void __devinit pnv_pci_ioda_fixup(void)
+{
+	pnv_pci_ioda_setup_PEs();
+	pnv_pci_ioda_setup_seg();
+	pnv_pci_ioda_setup_DMA();
+}
+
+/*
+ * Returns the alignment for I/O or memory windows for P2P
+ * bridges. That actually depends on how PEs are segmented.
+ * For now, we return I/O or M32 segment size for PE sensitive
+ * P2P bridges. Otherwise, the default values (4KiB for I/O,
+ * 1MiB for memory) will be returned.
+ *
+ * The current PCI bus might be put into one PE, which was
+ * create against the parent PCI bridge. For that case, we
+ * needn't enlarge the alignment so that we can save some
+ * resources.
+ */
+static resource_size_t pnv_pci_window_alignment(struct pci_bus *bus,
+						unsigned long type)
+{
+	struct pci_dev *bridge;
+	struct pci_controller *hose = pci_bus_to_host(bus);
+	struct pnv_phb *phb = hose->private_data;
+	int num_pci_bridges = 0;
+
+	bridge = bus->self;
+	while (bridge) {
+		if (pci_pcie_type(bridge) == PCI_EXP_TYPE_PCI_BRIDGE) {
+			num_pci_bridges++;
+			if (num_pci_bridges >= 2)
+				return 1;
+		}
+
+		bridge = bridge->bus->self;
 	}
+
+	/* We need support prefetchable memory window later */
+	if (type & IORESOURCE_MEM)
+		return phb->ioda.m32_segsize;
+
+	return phb->ioda.io_segsize;
 }
 
 /* Prevent enabling devices for which we couldn't properly
@@ -1144,10 +834,22 @@ static void __devinit pnv_pci_ioda_fixup_phb(struct pci_controller *hose)
  */
 static int __devinit pnv_pci_enable_device_hook(struct pci_dev *dev)
 {
-	struct pci_dn *pdn = pnv_ioda_get_pdn(dev);
+	struct pci_controller *hose = pci_bus_to_host(dev->bus);
+	struct pnv_phb *phb = hose->private_data;
+	struct pci_dn *pdn;
+
+	/* The function is probably called while the PEs have
+	 * not be created yet. For example, resource reassignment
+	 * during PCI probe period. We just skip the check if
+	 * PEs isn't ready.
+	 */
+	if (!phb->initialized)
+		return 0;
 
+	pdn = pnv_ioda_get_pdn(dev);
 	if (!pdn || pdn->pe_number == IODA_INVALID_PE)
 		return -EINVAL;
+
 	return 0;
 }
 
@@ -1238,9 +940,9 @@ void __init pnv_pci_init_ioda1_phb(struct device_node *np)
 	/* Allocate aux data & arrays */
 	size = _ALIGN_UP(phb->ioda.total_pe / 8, sizeof(unsigned long));
 	m32map_off = size;
-	size += phb->ioda.total_pe;
+	size += phb->ioda.total_pe * sizeof(phb->ioda.m32_segmap[0]);
 	iomap_off = size;
-	size += phb->ioda.total_pe;
+	size += phb->ioda.total_pe * sizeof(phb->ioda.io_segmap[0]);
 	pemap_off = size;
 	size += phb->ioda.total_pe * sizeof(struct pnv_ioda_pe);
 	aux = alloc_bootmem(size);
@@ -1251,6 +953,7 @@ void __init pnv_pci_init_ioda1_phb(struct device_node *np)
 	phb->ioda.pe_array = aux + pemap_off;
 	set_bit(0, phb->ioda.pe_alloc);
 
+	INIT_LIST_HEAD(&phb->ioda.pe_dma_list);
 	INIT_LIST_HEAD(&phb->ioda.pe_list);
 
 	/* Calculate how many 32-bit TCE segments we have */
@@ -1299,14 +1002,17 @@ void __init pnv_pci_init_ioda1_phb(struct device_node *np)
 	/* Setup MSI support */
 	pnv_pci_init_ioda_msis(phb);
 
-	/* We set both PCI_PROBE_ONLY and PCI_REASSIGN_ALL_RSRC. This is an
-	 * odd combination which essentially means that we skip all resource
-	 * fixups and assignments in the generic code, and do it all
-	 * ourselves here
+	/*
+	 * We pass the PCI probe flag PCI_REASSIGN_ALL_RSRC here
+	 * to let the PCI core do resource assignment. It's supposed
+	 * that the PCI core will do correct I/O and MMIO alignment
+	 * for the P2P bridge bars so that each PCI bus (excluding
+	 * the child P2P bridges) can form individual PE.
 	 */
-	ppc_md.pcibios_fixup_phb = pnv_pci_ioda_fixup_phb;
+	ppc_md.pcibios_fixup = pnv_pci_ioda_fixup;
 	ppc_md.pcibios_enable_device_hook = pnv_pci_enable_device_hook;
-	pci_add_flags(PCI_PROBE_ONLY | PCI_REASSIGN_ALL_RSRC);
+	ppc_md.pcibios_window_alignment = pnv_pci_window_alignment;
+	pci_add_flags(PCI_REASSIGN_ALL_RSRC);
 
 	/* Reset IODA tables to a clean state */
 	rc = opal_pci_reset(phb_id, OPAL_PCI_IODA_TABLE_RESET, OPAL_ASSERT_RESET);
diff --git a/arch/powerpc/platforms/powernv/pci-p5ioc2.c b/arch/powerpc/platforms/powernv/pci-p5ioc2.c
index 2649677..6b4bef4 100644
--- a/arch/powerpc/platforms/powernv/pci-p5ioc2.c
+++ b/arch/powerpc/platforms/powernv/pci-p5ioc2.c
@@ -30,7 +30,6 @@
 #include <asm/opal.h>
 #include <asm/iommu.h>
 #include <asm/tce.h>
-#include <asm/abs_addr.h>
 
 #include "powernv.h"
 #include "pci.h"
diff --git a/arch/powerpc/platforms/powernv/pci.c b/arch/powerpc/platforms/powernv/pci.c
index be3cfc5..c01688a 100644
--- a/arch/powerpc/platforms/powernv/pci.c
+++ b/arch/powerpc/platforms/powernv/pci.c
@@ -30,7 +30,6 @@
 #include <asm/opal.h>
 #include <asm/iommu.h>
 #include <asm/tce.h>
-#include <asm/abs_addr.h>
 #include <asm/firmware.h>
 
 #include "powernv.h"
@@ -447,6 +446,11 @@ static void pnv_tce_free(struct iommu_table *tbl, long index, long npages)
 		pnv_tce_invalidate(tbl, tces, tcep - 1);
 }
 
+static unsigned long pnv_tce_get(struct iommu_table *tbl, long index)
+{
+	return ((u64 *)tbl->it_base)[index - tbl->it_offset];
+}
+
 void pnv_pci_setup_iommu_table(struct iommu_table *tbl,
 			       void *tce_mem, u64 tce_size,
 			       u64 dma_offset)
@@ -597,6 +601,7 @@ void __init pnv_pci_init(void)
 	ppc_md.pci_dma_dev_setup = pnv_pci_dma_dev_setup;
 	ppc_md.tce_build = pnv_tce_build;
 	ppc_md.tce_free = pnv_tce_free;
+	ppc_md.tce_get = pnv_tce_get;
 	ppc_md.pci_probe_mode = pnv_pci_probe_mode;
 	set_pci_dma_ops(&dma_iommu_ops);
 
diff --git a/arch/powerpc/platforms/powernv/pci.h b/arch/powerpc/platforms/powernv/pci.h
index 8bc4796..7cfb7c8 100644
--- a/arch/powerpc/platforms/powernv/pci.h
+++ b/arch/powerpc/platforms/powernv/pci.h
@@ -17,9 +17,14 @@ enum pnv_phb_model {
 };
 
 #define PNV_PCI_DIAG_BUF_SIZE	4096
+#define PNV_IODA_PE_DEV		(1 << 0)	/* PE has single PCI device	*/
+#define PNV_IODA_PE_BUS		(1 << 1)	/* PE has primary PCI bus	*/
+#define PNV_IODA_PE_BUS_ALL	(1 << 2)	/* PE has subordinate buses	*/
 
 /* Data associated with a PE, including IOMMU tracking etc.. */
 struct pnv_ioda_pe {
+	unsigned long		flags;
+
 	/* A PE can be associated with a single device or an
 	 * entire bus (& children). In the former case, pdev
 	 * is populated, in the later case, pbus is.
@@ -40,11 +45,6 @@ struct pnv_ioda_pe {
 	 */
 	unsigned int		dma_weight;
 
-	/* This is a PCI-E -> PCI-X bridge, this points to the
-	 * corresponding bus PE
-	 */
-	struct pnv_ioda_pe	*bus_pe;
-
 	/* "Base" iommu table, ie, 4K TCEs, 32-bit DMA */
 	int			tce32_seg;
 	int			tce32_segcount;
@@ -59,7 +59,8 @@ struct pnv_ioda_pe {
 	int			mve_number;
 
 	/* Link in list of PE#s */
-	struct list_head	link;
+	struct list_head	dma_link;
+	struct list_head	list;
 };
 
 struct pnv_phb {
@@ -68,6 +69,7 @@ struct pnv_phb {
 	enum pnv_phb_model	model;
 	u64			opal_id;
 	void __iomem		*regs;
+	int			initialized;
 	spinlock_t		lock;
 
 #ifdef CONFIG_PCI_MSI
@@ -107,6 +109,11 @@ struct pnv_phb {
 			unsigned int		*io_segmap;
 			struct pnv_ioda_pe	*pe_array;
 
+			/* Sorted list of used PE's based
+			 * on the sequence of creation
+			 */
+			struct list_head	pe_list;
+
 			/* Reverse map of PEs, will have to extend if
 			 * we are to support more than 256 PEs, indexed
 			 * bus { bus, devfn }
@@ -125,7 +132,7 @@ struct pnv_phb {
 			/* Sorted list of used PE's, sorted at
 			 * boot for resource allocation purposes
 			 */
-			struct list_head	pe_list;
+			struct list_head	pe_dma_list;
 		} ioda;
 	};
 
diff --git a/arch/powerpc/platforms/ps3/htab.c b/arch/powerpc/platforms/ps3/htab.c
index 3124cf7..d00d7b0 100644
--- a/arch/powerpc/platforms/ps3/htab.c
+++ b/arch/powerpc/platforms/ps3/htab.c
@@ -43,7 +43,7 @@ enum ps3_lpar_vas_id {
 
 static DEFINE_SPINLOCK(ps3_htab_lock);
 
-static long ps3_hpte_insert(unsigned long hpte_group, unsigned long va,
+static long ps3_hpte_insert(unsigned long hpte_group, unsigned long vpn,
 	unsigned long pa, unsigned long rflags, unsigned long vflags,
 	int psize, int ssize)
 {
@@ -61,7 +61,7 @@ static long ps3_hpte_insert(unsigned long hpte_group, unsigned long va,
 	 */
 	vflags &= ~HPTE_V_SECONDARY;
 
-	hpte_v = hpte_encode_v(va, psize, ssize) | vflags | HPTE_V_VALID;
+	hpte_v = hpte_encode_v(vpn, psize, ssize) | vflags | HPTE_V_VALID;
 	hpte_r = hpte_encode_r(ps3_mm_phys_to_lpar(pa), psize) | rflags;
 
 	spin_lock_irqsave(&ps3_htab_lock, flags);
@@ -75,8 +75,8 @@ static long ps3_hpte_insert(unsigned long hpte_group, unsigned long va,
 
 	if (result) {
 		/* all entries bolted !*/
-		pr_info("%s:result=%d va=%lx pa=%lx ix=%lx v=%llx r=%llx\n",
-			__func__, result, va, pa, hpte_group, hpte_v, hpte_r);
+		pr_info("%s:result=%d vpn=%lx pa=%lx ix=%lx v=%llx r=%llx\n",
+			__func__, result, vpn, pa, hpte_group, hpte_v, hpte_r);
 		BUG();
 	}
 
@@ -107,7 +107,7 @@ static long ps3_hpte_remove(unsigned long hpte_group)
 }
 
 static long ps3_hpte_updatepp(unsigned long slot, unsigned long newpp,
-	unsigned long va, int psize, int ssize, int local)
+	unsigned long vpn, int psize, int ssize, int local)
 {
 	int result;
 	u64 hpte_v, want_v, hpte_rs;
@@ -115,7 +115,7 @@ static long ps3_hpte_updatepp(unsigned long slot, unsigned long newpp,
 	unsigned long flags;
 	long ret;
 
-	want_v = hpte_encode_v(va, psize, ssize);
+	want_v = hpte_encode_v(vpn, psize, ssize);
 
 	spin_lock_irqsave(&ps3_htab_lock, flags);
 
@@ -125,8 +125,8 @@ static long ps3_hpte_updatepp(unsigned long slot, unsigned long newpp,
 				       &hpte_rs);
 
 	if (result) {
-		pr_info("%s: res=%d read va=%lx slot=%lx psize=%d\n",
-			__func__, result, va, slot, psize);
+		pr_info("%s: res=%d read vpn=%lx slot=%lx psize=%d\n",
+			__func__, result, vpn, slot, psize);
 		BUG();
 	}
 
@@ -159,7 +159,7 @@ static void ps3_hpte_updateboltedpp(unsigned long newpp, unsigned long ea,
 	panic("ps3_hpte_updateboltedpp() not implemented");
 }
 
-static void ps3_hpte_invalidate(unsigned long slot, unsigned long va,
+static void ps3_hpte_invalidate(unsigned long slot, unsigned long vpn,
 	int psize, int ssize, int local)
 {
 	unsigned long flags;
@@ -170,8 +170,8 @@ static void ps3_hpte_invalidate(unsigned long slot, unsigned long va,
 	result = lv1_write_htab_entry(PS3_LPAR_VAS_ID_CURRENT, slot, 0, 0);
 
 	if (result) {
-		pr_info("%s: res=%d va=%lx slot=%lx psize=%d\n",
-			__func__, result, va, slot, psize);
+		pr_info("%s: res=%d vpn=%lx slot=%lx psize=%d\n",
+			__func__, result, vpn, slot, psize);
 		BUG();
 	}
 
diff --git a/arch/powerpc/platforms/ps3/setup.c b/arch/powerpc/platforms/ps3/setup.c
index 2d664c5..3f509f8 100644
--- a/arch/powerpc/platforms/ps3/setup.c
+++ b/arch/powerpc/platforms/ps3/setup.c
@@ -184,11 +184,15 @@ early_param("ps3flash", early_parse_ps3flash);
 #define prealloc_ps3flash_bounce_buffer()	do { } while (0)
 #endif
 
-static int ps3_set_dabr(unsigned long dabr)
+static int ps3_set_dabr(unsigned long dabr, unsigned long dabrx)
 {
-	enum {DABR_USER = 1, DABR_KERNEL = 2,};
+	/* Have to set at least one bit in the DABRX */
+	if (dabrx == 0 && dabr == 0)
+		dabrx = DABRX_USER;
+	/* hypervisor only allows us to set BTI, Kernel and user */
+	dabrx &= DABRX_BTI | DABRX_KERNEL | DABRX_USER;
 
-	return lv1_set_dabr(dabr, DABR_KERNEL | DABR_USER) ? -1 : 0;
+	return lv1_set_dabr(dabr, dabrx) ? -1 : 0;
 }
 
 static void __init ps3_setup_arch(void)
diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile
index c222189..890622b 100644
--- a/arch/powerpc/platforms/pseries/Makefile
+++ b/arch/powerpc/platforms/pseries/Makefile
@@ -6,8 +6,9 @@ obj-y			:= lpar.o hvCall.o nvram.o reconfig.o \
 			   firmware.o power.o dlpar.o mobility.o
 obj-$(CONFIG_SMP)	+= smp.o
 obj-$(CONFIG_SCANLOG)	+= scanlog.o
-obj-$(CONFIG_EEH)	+= eeh.o eeh_dev.o eeh_cache.o eeh_driver.o \
-			   eeh_event.o eeh_sysfs.o eeh_pseries.o
+obj-$(CONFIG_EEH)	+= eeh.o eeh_pe.o eeh_dev.o eeh_cache.o \
+			   eeh_driver.o eeh_event.o eeh_sysfs.o \
+			   eeh_pseries.o
 obj-$(CONFIG_KEXEC)	+= kexec.o
 obj-$(CONFIG_PCI)	+= pci.o pci_dlpar.o
 obj-$(CONFIG_PSERIES_MSI)	+= msi.o
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c
index ecd394c..9a04322 100644
--- a/arch/powerpc/platforms/pseries/eeh.c
+++ b/arch/powerpc/platforms/pseries/eeh.c
@@ -92,6 +92,20 @@ struct eeh_ops *eeh_ops = NULL;
 int eeh_subsystem_enabled;
 EXPORT_SYMBOL(eeh_subsystem_enabled);
 
+/*
+ * EEH probe mode support. The intention is to support multiple
+ * platforms for EEH. Some platforms like pSeries do PCI emunation
+ * based on device tree. However, other platforms like powernv probe
+ * PCI devices from hardware. The flag is used to distinguish that.
+ * In addition, struct eeh_ops::probe would be invoked for particular
+ * OF node or PCI device so that the corresponding PE would be created
+ * there.
+ */
+int eeh_probe_mode;
+
+/* Global EEH mutex */
+DEFINE_MUTEX(eeh_mutex);
+
 /* Lock to avoid races due to multiple reports of an error */
 static DEFINE_RAW_SPINLOCK(confirm_error_lock);
 
@@ -204,22 +218,12 @@ static size_t eeh_gather_pci_data(struct eeh_dev *edev, char * buf, size_t len)
 		}
 	}
 
-	/* Gather status on devices under the bridge */
-	if (dev->class >> 16 == PCI_BASE_CLASS_BRIDGE) {
-		struct device_node *child;
-
-		for_each_child_of_node(dn, child) {
-			if (of_node_to_eeh_dev(child))
-				n += eeh_gather_pci_data(of_node_to_eeh_dev(child), buf+n, len-n);
-		}
-	}
-
 	return n;
 }
 
 /**
  * eeh_slot_error_detail - Generate combined log including driver log and error log
- * @edev: device to report error log for
+ * @pe: EEH PE
  * @severity: temporary or permanent error log
  *
  * This routine should be called to generate the combined log, which
@@ -227,17 +231,22 @@ static size_t eeh_gather_pci_data(struct eeh_dev *edev, char * buf, size_t len)
  * out from the config space of the corresponding PCI device, while
  * the error log is fetched through platform dependent function call.
  */
-void eeh_slot_error_detail(struct eeh_dev *edev, int severity)
+void eeh_slot_error_detail(struct eeh_pe *pe, int severity)
 {
 	size_t loglen = 0;
-	pci_regs_buf[0] = 0;
+	struct eeh_dev *edev;
 
-	eeh_pci_enable(edev, EEH_OPT_THAW_MMIO);
-	eeh_ops->configure_bridge(eeh_dev_to_of_node(edev));
-	eeh_restore_bars(edev);
-	loglen = eeh_gather_pci_data(edev, pci_regs_buf, EEH_PCI_REGS_LOG_LEN);
+	eeh_pci_enable(pe, EEH_OPT_THAW_MMIO);
+	eeh_ops->configure_bridge(pe);
+	eeh_pe_restore_bars(pe);
 
-	eeh_ops->get_log(eeh_dev_to_of_node(edev), severity, pci_regs_buf, loglen);
+	pci_regs_buf[0] = 0;
+	eeh_pe_for_each_dev(pe, edev) {
+		loglen += eeh_gather_pci_data(edev, pci_regs_buf,
+				EEH_PCI_REGS_LOG_LEN);
+        }
+
+	eeh_ops->get_log(pe, severity, pci_regs_buf, loglen);
 }
 
 /**
@@ -261,126 +270,8 @@ static inline unsigned long eeh_token_to_phys(unsigned long token)
 }
 
 /**
- * eeh_find_device_pe - Retrieve the PE for the given device
- * @dn: device node
- *
- * Return the PE under which this device lies
- */
-struct device_node *eeh_find_device_pe(struct device_node *dn)
-{
-	while (dn->parent && of_node_to_eeh_dev(dn->parent) &&
-	       (of_node_to_eeh_dev(dn->parent)->mode & EEH_MODE_SUPPORTED)) {
-		dn = dn->parent;
-	}
-	return dn;
-}
-
-/**
- * __eeh_mark_slot - Mark all child devices as failed
- * @parent: parent device
- * @mode_flag: failure flag
- *
- * Mark all devices that are children of this device as failed.
- * Mark the device driver too, so that it can see the failure
- * immediately; this is critical, since some drivers poll
- * status registers in interrupts ... If a driver is polling,
- * and the slot is frozen, then the driver can deadlock in
- * an interrupt context, which is bad.
- */
-static void __eeh_mark_slot(struct device_node *parent, int mode_flag)
-{
-	struct device_node *dn;
-
-	for_each_child_of_node(parent, dn) {
-		if (of_node_to_eeh_dev(dn)) {
-			/* Mark the pci device driver too */
-			struct pci_dev *dev = of_node_to_eeh_dev(dn)->pdev;
-
-			of_node_to_eeh_dev(dn)->mode |= mode_flag;
-
-			if (dev && dev->driver)
-				dev->error_state = pci_channel_io_frozen;
-
-			__eeh_mark_slot(dn, mode_flag);
-		}
-	}
-}
-
-/**
- * eeh_mark_slot - Mark the indicated device and its children as failed
- * @dn: parent device
- * @mode_flag: failure flag
- *
- * Mark the indicated device and its child devices as failed.
- * The device drivers are marked as failed as well.
- */
-void eeh_mark_slot(struct device_node *dn, int mode_flag)
-{
-	struct pci_dev *dev;
-	dn = eeh_find_device_pe(dn);
-
-	/* Back up one, since config addrs might be shared */
-	if (!pcibios_find_pci_bus(dn) && of_node_to_eeh_dev(dn->parent))
-		dn = dn->parent;
-
-	of_node_to_eeh_dev(dn)->mode |= mode_flag;
-
-	/* Mark the pci device too */
-	dev = of_node_to_eeh_dev(dn)->pdev;
-	if (dev)
-		dev->error_state = pci_channel_io_frozen;
-
-	__eeh_mark_slot(dn, mode_flag);
-}
-
-/**
- * __eeh_clear_slot - Clear failure flag for the child devices
- * @parent: parent device
- * @mode_flag: flag to be cleared
- *
- * Clear failure flag for the child devices.
- */
-static void __eeh_clear_slot(struct device_node *parent, int mode_flag)
-{
-	struct device_node *dn;
-
-	for_each_child_of_node(parent, dn) {
-		if (of_node_to_eeh_dev(dn)) {
-			of_node_to_eeh_dev(dn)->mode &= ~mode_flag;
-			of_node_to_eeh_dev(dn)->check_count = 0;
-			__eeh_clear_slot(dn, mode_flag);
-		}
-	}
-}
-
-/**
- * eeh_clear_slot - Clear failure flag for the indicated device and its children
- * @dn: parent device
- * @mode_flag: flag to be cleared
- *
- * Clear failure flag for the indicated device and its children.
- */
-void eeh_clear_slot(struct device_node *dn, int mode_flag)
-{
-	unsigned long flags;
-	raw_spin_lock_irqsave(&confirm_error_lock, flags);
-	
-	dn = eeh_find_device_pe(dn);
-	
-	/* Back up one, since config addrs might be shared */
-	if (!pcibios_find_pci_bus(dn) && of_node_to_eeh_dev(dn->parent))
-		dn = dn->parent;
-
-	of_node_to_eeh_dev(dn)->mode &= ~mode_flag;
-	of_node_to_eeh_dev(dn)->check_count = 0;
-	__eeh_clear_slot(dn, mode_flag);
-	raw_spin_unlock_irqrestore(&confirm_error_lock, flags);
-}
-
-/**
- * eeh_dn_check_failure - Check if all 1's data is due to EEH slot freeze
- * @dn: device node
- * @dev: pci device, if known
+ * eeh_dev_check_failure - Check if all 1's data is due to EEH slot freeze
+ * @edev: eeh device
  *
  * Check for an EEH failure for the given device node.  Call this
  * routine if the result of a read was all 0xff's and you want to
@@ -392,11 +283,13 @@ void eeh_clear_slot(struct device_node *dn, int mode_flag)
  *
  * It is safe to call this routine in an interrupt context.
  */
-int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
+int eeh_dev_check_failure(struct eeh_dev *edev)
 {
 	int ret;
 	unsigned long flags;
-	struct eeh_dev *edev;
+	struct device_node *dn;
+	struct pci_dev *dev;
+	struct eeh_pe *pe;
 	int rc = 0;
 	const char *location;
 
@@ -405,23 +298,23 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
 	if (!eeh_subsystem_enabled)
 		return 0;
 
-	if (!dn) {
+	if (!edev) {
 		eeh_stats.no_dn++;
 		return 0;
 	}
-	dn = eeh_find_device_pe(dn);
-	edev = of_node_to_eeh_dev(dn);
+	dn = eeh_dev_to_of_node(edev);
+	dev = eeh_dev_to_pci_dev(edev);
+	pe = edev->pe;
 
 	/* Access to IO BARs might get this far and still not want checking. */
-	if (!(edev->mode & EEH_MODE_SUPPORTED) ||
-	    edev->mode & EEH_MODE_NOCHECK) {
+	if (!pe) {
 		eeh_stats.ignored_check++;
-		pr_debug("EEH: Ignored check (%x) for %s %s\n",
-			edev->mode, eeh_pci_name(dev), dn->full_name);
+		pr_debug("EEH: Ignored check for %s %s\n",
+			eeh_pci_name(dev), dn->full_name);
 		return 0;
 	}
 
-	if (!edev->config_addr && !edev->pe_config_addr) {
+	if (!pe->addr && !pe->config_addr) {
 		eeh_stats.no_cfg_addr++;
 		return 0;
 	}
@@ -434,13 +327,13 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
 	 */
 	raw_spin_lock_irqsave(&confirm_error_lock, flags);
 	rc = 1;
-	if (edev->mode & EEH_MODE_ISOLATED) {
-		edev->check_count++;
-		if (edev->check_count % EEH_MAX_FAILS == 0) {
+	if (pe->state & EEH_PE_ISOLATED) {
+		pe->check_count++;
+		if (pe->check_count % EEH_MAX_FAILS == 0) {
 			location = of_get_property(dn, "ibm,loc-code", NULL);
 			printk(KERN_ERR "EEH: %d reads ignored for recovering device at "
 				"location=%s driver=%s pci addr=%s\n",
-				edev->check_count, location,
+				pe->check_count, location,
 				eeh_driver_name(dev), eeh_pci_name(dev));
 			printk(KERN_ERR "EEH: Might be infinite loop in %s driver\n",
 				eeh_driver_name(dev));
@@ -456,7 +349,7 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
 	 * function zero of a multi-function device.
 	 * In any case they must share a common PHB.
 	 */
-	ret = eeh_ops->get_state(dn, NULL);
+	ret = eeh_ops->get_state(pe, NULL);
 
 	/* Note that config-io to empty slots may fail;
 	 * they are empty when they don't have children.
@@ -469,7 +362,7 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
 	    (ret & (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE)) ==
 	    (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE)) {
 		eeh_stats.false_positives++;
-		edev->false_positives ++;
+		pe->false_positives++;
 		rc = 0;
 		goto dn_unlock;
 	}
@@ -480,10 +373,10 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
 	 * with other functions on this device, and functions under
 	 * bridges.
 	 */
-	eeh_mark_slot(dn, EEH_MODE_ISOLATED);
+	eeh_pe_state_mark(pe, EEH_PE_ISOLATED);
 	raw_spin_unlock_irqrestore(&confirm_error_lock, flags);
 
-	eeh_send_failure_event(edev);
+	eeh_send_failure_event(pe);
 
 	/* Most EEH events are due to device driver bugs.  Having
 	 * a stack trace will help the device-driver authors figure
@@ -497,7 +390,7 @@ dn_unlock:
 	return rc;
 }
 
-EXPORT_SYMBOL_GPL(eeh_dn_check_failure);
+EXPORT_SYMBOL_GPL(eeh_dev_check_failure);
 
 /**
  * eeh_check_failure - Check if all 1's data is due to EEH slot freeze
@@ -514,21 +407,19 @@ EXPORT_SYMBOL_GPL(eeh_dn_check_failure);
 unsigned long eeh_check_failure(const volatile void __iomem *token, unsigned long val)
 {
 	unsigned long addr;
-	struct pci_dev *dev;
-	struct device_node *dn;
+	struct eeh_dev *edev;
 
 	/* Finding the phys addr + pci device; this is pretty quick. */
 	addr = eeh_token_to_phys((unsigned long __force) token);
-	dev = pci_addr_cache_get_device(addr);
-	if (!dev) {
+	edev = eeh_addr_cache_get_dev(addr);
+	if (!edev) {
 		eeh_stats.no_device++;
 		return val;
 	}
 
-	dn = pci_device_to_OF_node(dev);
-	eeh_dn_check_failure(dn, dev);
+	eeh_dev_check_failure(edev);
 
-	pci_dev_put(dev);
+	pci_dev_put(eeh_dev_to_pci_dev(edev));
 	return val;
 }
 
@@ -537,23 +428,22 @@ EXPORT_SYMBOL(eeh_check_failure);
 
 /**
  * eeh_pci_enable - Enable MMIO or DMA transfers for this slot
- * @edev: pci device node
+ * @pe: EEH PE
  *
  * This routine should be called to reenable frozen MMIO or DMA
  * so that it would work correctly again. It's useful while doing
  * recovery or log collection on the indicated device.
  */
-int eeh_pci_enable(struct eeh_dev *edev, int function)
+int eeh_pci_enable(struct eeh_pe *pe, int function)
 {
 	int rc;
-	struct device_node *dn = eeh_dev_to_of_node(edev);
 
-	rc = eeh_ops->set_option(dn, function);
+	rc = eeh_ops->set_option(pe, function);
 	if (rc)
-		printk(KERN_WARNING "EEH: Unexpected state change %d, err=%d dn=%s\n",
-		        function, rc, dn->full_name);
+		pr_warning("%s: Unexpected state change %d on PHB#%d-PE#%x, err=%d\n",
+			__func__, function, pe->phb->global_number, pe->addr, rc);
 
-	rc = eeh_ops->wait_state(dn, PCI_BUS_RESET_WAIT_MSEC);
+	rc = eeh_ops->wait_state(pe, PCI_BUS_RESET_WAIT_MSEC);
 	if (rc > 0 && (rc & EEH_STATE_MMIO_ENABLED) &&
 	   (function == EEH_OPT_THAW_MMIO))
 		return 0;
@@ -571,17 +461,24 @@ int eeh_pci_enable(struct eeh_dev *edev, int function)
  */
 int pcibios_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state state)
 {
-	struct device_node *dn = pci_device_to_OF_node(dev);
+	struct eeh_dev *edev = pci_dev_to_eeh_dev(dev);
+	struct eeh_pe *pe = edev->pe;
+
+	if (!pe) {
+		pr_err("%s: No PE found on PCI device %s\n",
+			__func__, pci_name(dev));
+		return -EINVAL;
+	}
 
 	switch (state) {
 	case pcie_deassert_reset:
-		eeh_ops->reset(dn, EEH_RESET_DEACTIVATE);
+		eeh_ops->reset(pe, EEH_RESET_DEACTIVATE);
 		break;
 	case pcie_hot_reset:
-		eeh_ops->reset(dn, EEH_RESET_HOT);
+		eeh_ops->reset(pe, EEH_RESET_HOT);
 		break;
 	case pcie_warm_reset:
-		eeh_ops->reset(dn, EEH_RESET_FUNDAMENTAL);
+		eeh_ops->reset(pe, EEH_RESET_FUNDAMENTAL);
 		break;
 	default:
 		return -EINVAL;
@@ -591,66 +488,37 @@ int pcibios_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state stat
 }
 
 /**
- * __eeh_set_pe_freset - Check the required reset for child devices
- * @parent: parent device
- * @freset: return value
- *
- * Each device might have its preferred reset type: fundamental or
- * hot reset. The routine is used to collect the information from
- * the child devices so that they could be reset accordingly.
- */
-void __eeh_set_pe_freset(struct device_node *parent, unsigned int *freset)
-{
-	struct device_node *dn;
-
-	for_each_child_of_node(parent, dn) {
-		if (of_node_to_eeh_dev(dn)) {
-			struct pci_dev *dev = of_node_to_eeh_dev(dn)->pdev;
-
-			if (dev && dev->driver)
-				*freset |= dev->needs_freset;
-
-			__eeh_set_pe_freset(dn, freset);
-		}
-	}
-}
-
-/**
- * eeh_set_pe_freset - Check the required reset for the indicated device and its children
- * @dn: parent device
- * @freset: return value
+ * eeh_set_pe_freset - Check the required reset for the indicated device
+ * @data: EEH device
+ * @flag: return value
  *
  * Each device might have its preferred reset type: fundamental or
  * hot reset. The routine is used to collected the information for
  * the indicated device and its children so that the bunch of the
  * devices could be reset properly.
  */
-void eeh_set_pe_freset(struct device_node *dn, unsigned int *freset)
+static void *eeh_set_dev_freset(void *data, void *flag)
 {
 	struct pci_dev *dev;
-	dn = eeh_find_device_pe(dn);
-
-	/* Back up one, since config addrs might be shared */
-	if (!pcibios_find_pci_bus(dn) && of_node_to_eeh_dev(dn->parent))
-		dn = dn->parent;
+	unsigned int *freset = (unsigned int *)flag;
+	struct eeh_dev *edev = (struct eeh_dev *)data;
 
-	dev = of_node_to_eeh_dev(dn)->pdev;
+	dev = eeh_dev_to_pci_dev(edev);
 	if (dev)
 		*freset |= dev->needs_freset;
 
-	__eeh_set_pe_freset(dn, freset);
+	return NULL;
 }
 
 /**
  * eeh_reset_pe_once - Assert the pci #RST line for 1/4 second
- * @edev: pci device node to be reset.
+ * @pe: EEH PE
  *
  * Assert the PCI #RST line for 1/4 second.
  */
-static void eeh_reset_pe_once(struct eeh_dev *edev)
+static void eeh_reset_pe_once(struct eeh_pe *pe)
 {
 	unsigned int freset = 0;
-	struct device_node *dn = eeh_dev_to_of_node(edev);
 
 	/* Determine type of EEH reset required for
 	 * Partitionable Endpoint, a hot-reset (1)
@@ -658,12 +526,12 @@ static void eeh_reset_pe_once(struct eeh_dev *edev)
 	 * A fundamental reset required by any device under
 	 * Partitionable Endpoint trumps hot-reset.
   	 */
-	eeh_set_pe_freset(dn, &freset);
+	eeh_pe_dev_traverse(pe, eeh_set_dev_freset, &freset);
 
 	if (freset)
-		eeh_ops->reset(dn, EEH_RESET_FUNDAMENTAL);
+		eeh_ops->reset(pe, EEH_RESET_FUNDAMENTAL);
 	else
-		eeh_ops->reset(dn, EEH_RESET_HOT);
+		eeh_ops->reset(pe, EEH_RESET_HOT);
 
 	/* The PCI bus requires that the reset be held high for at least
 	 * a 100 milliseconds. We wait a bit longer 'just in case'.
@@ -675,9 +543,9 @@ static void eeh_reset_pe_once(struct eeh_dev *edev)
 	 * pci slot reset line is dropped. Make sure we don't miss
 	 * these, and clear the flag now.
 	 */
-	eeh_clear_slot(dn, EEH_MODE_ISOLATED);
+	eeh_pe_state_clear(pe, EEH_PE_ISOLATED);
 
-	eeh_ops->reset(dn, EEH_RESET_DEACTIVATE);
+	eeh_ops->reset(pe, EEH_RESET_DEACTIVATE);
 
 	/* After a PCI slot has been reset, the PCI Express spec requires
 	 * a 1.5 second idle time for the bus to stabilize, before starting
@@ -689,116 +557,36 @@ static void eeh_reset_pe_once(struct eeh_dev *edev)
 
 /**
  * eeh_reset_pe - Reset the indicated PE
- * @edev: PCI device associated EEH device
+ * @pe: EEH PE
  *
  * This routine should be called to reset indicated device, including
  * PE. A PE might include multiple PCI devices and sometimes PCI bridges
  * might be involved as well.
  */
-int eeh_reset_pe(struct eeh_dev *edev)
+int eeh_reset_pe(struct eeh_pe *pe)
 {
 	int i, rc;
-	struct device_node *dn = eeh_dev_to_of_node(edev);
 
 	/* Take three shots at resetting the bus */
 	for (i=0; i<3; i++) {
-		eeh_reset_pe_once(edev);
+		eeh_reset_pe_once(pe);
 
-		rc = eeh_ops->wait_state(dn, PCI_BUS_RESET_WAIT_MSEC);
+		rc = eeh_ops->wait_state(pe, PCI_BUS_RESET_WAIT_MSEC);
 		if (rc == (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE))
 			return 0;
 
 		if (rc < 0) {
-			printk(KERN_ERR "EEH: unrecoverable slot failure %s\n",
-			       dn->full_name);
+			pr_err("%s: Unrecoverable slot failure on PHB#%d-PE#%x",
+				__func__, pe->phb->global_number, pe->addr);
 			return -1;
 		}
-		printk(KERN_ERR "EEH: bus reset %d failed on slot %s, rc=%d\n",
-		       i+1, dn->full_name, rc);
+		pr_err("EEH: bus reset %d failed on PHB#%d-PE#%x, rc=%d\n",
+			i+1, pe->phb->global_number, pe->addr, rc);
 	}
 
 	return -1;
 }
 
-/** Save and restore of PCI BARs
- *
- * Although firmware will set up BARs during boot, it doesn't
- * set up device BAR's after a device reset, although it will,
- * if requested, set up bridge configuration. Thus, we need to
- * configure the PCI devices ourselves.  
- */
-
-/**
- * eeh_restore_one_device_bars - Restore the Base Address Registers for one device
- * @edev: PCI device associated EEH device
- *
- * Loads the PCI configuration space base address registers,
- * the expansion ROM base address, the latency timer, and etc.
- * from the saved values in the device node.
- */
-static inline void eeh_restore_one_device_bars(struct eeh_dev *edev)
-{
-	int i;
-	u32 cmd;
-	struct device_node *dn = eeh_dev_to_of_node(edev);
-
-	if (!edev->phb)
-		return;
-
-	for (i=4; i<10; i++) {
-		eeh_ops->write_config(dn, i*4, 4, edev->config_space[i]);
-	}
-
-	/* 12 == Expansion ROM Address */
-	eeh_ops->write_config(dn, 12*4, 4, edev->config_space[12]);
-
-#define BYTE_SWAP(OFF) (8*((OFF)/4)+3-(OFF))
-#define SAVED_BYTE(OFF) (((u8 *)(edev->config_space))[BYTE_SWAP(OFF)])
-
-	eeh_ops->write_config(dn, PCI_CACHE_LINE_SIZE, 1,
-	            SAVED_BYTE(PCI_CACHE_LINE_SIZE));
-
-	eeh_ops->write_config(dn, PCI_LATENCY_TIMER, 1,
-	            SAVED_BYTE(PCI_LATENCY_TIMER));
-
-	/* max latency, min grant, interrupt pin and line */
-	eeh_ops->write_config(dn, 15*4, 4, edev->config_space[15]);
-
-	/* Restore PERR & SERR bits, some devices require it,
-	 * don't touch the other command bits
-	 */
-	eeh_ops->read_config(dn, PCI_COMMAND, 4, &cmd);
-	if (edev->config_space[1] & PCI_COMMAND_PARITY)
-		cmd |= PCI_COMMAND_PARITY;
-	else
-		cmd &= ~PCI_COMMAND_PARITY;
-	if (edev->config_space[1] & PCI_COMMAND_SERR)
-		cmd |= PCI_COMMAND_SERR;
-	else
-		cmd &= ~PCI_COMMAND_SERR;
-	eeh_ops->write_config(dn, PCI_COMMAND, 4, cmd);
-}
-
-/**
- * eeh_restore_bars - Restore the PCI config space info
- * @edev: EEH device
- *
- * This routine performs a recursive walk to the children
- * of this device as well.
- */
-void eeh_restore_bars(struct eeh_dev *edev)
-{
-	struct device_node *dn;
-	if (!edev)
-		return;
-	
-	if ((edev->mode & EEH_MODE_SUPPORTED) && !IS_BRIDGE(edev->class_code))
-		eeh_restore_one_device_bars(edev);
-
-	for_each_child_of_node(eeh_dev_to_of_node(edev), dn)
-		eeh_restore_bars(of_node_to_eeh_dev(dn));
-}
-
 /**
  * eeh_save_bars - Save device bars
  * @edev: PCI device associated EEH device
@@ -808,7 +596,7 @@ void eeh_restore_bars(struct eeh_dev *edev)
  * PCI devices are added individually; but, for the restore,
  * an entire slot is reset at a time.
  */
-static void eeh_save_bars(struct eeh_dev *edev)
+void eeh_save_bars(struct eeh_dev *edev)
 {
 	int i;
 	struct device_node *dn;
@@ -822,102 +610,6 @@ static void eeh_save_bars(struct eeh_dev *edev)
 }
 
 /**
- * eeh_early_enable - Early enable EEH on the indicated device
- * @dn: device node
- * @data: BUID
- *
- * Enable EEH functionality on the specified PCI device. The function
- * is expected to be called before real PCI probing is done. However,
- * the PHBs have been initialized at this point.
- */
-static void *eeh_early_enable(struct device_node *dn, void *data)
-{
-	int ret;
-	const u32 *class_code = of_get_property(dn, "class-code", NULL);
-	const u32 *vendor_id = of_get_property(dn, "vendor-id", NULL);
-	const u32 *device_id = of_get_property(dn, "device-id", NULL);
-	const u32 *regs;
-	int enable;
-	struct eeh_dev *edev = of_node_to_eeh_dev(dn);
-
-	edev->class_code = 0;
-	edev->mode = 0;
-	edev->check_count = 0;
-	edev->freeze_count = 0;
-	edev->false_positives = 0;
-
-	if (!of_device_is_available(dn))
-		return NULL;
-
-	/* Ignore bad nodes. */
-	if (!class_code || !vendor_id || !device_id)
-		return NULL;
-
-	/* There is nothing to check on PCI to ISA bridges */
-	if (dn->type && !strcmp(dn->type, "isa")) {
-		edev->mode |= EEH_MODE_NOCHECK;
-		return NULL;
-	}
-	edev->class_code = *class_code;
-
-	/* Ok... see if this device supports EEH.  Some do, some don't,
-	 * and the only way to find out is to check each and every one.
-	 */
-	regs = of_get_property(dn, "reg", NULL);
-	if (regs) {
-		/* First register entry is addr (00BBSS00)  */
-		/* Try to enable eeh */
-		ret = eeh_ops->set_option(dn, EEH_OPT_ENABLE);
-
-		enable = 0;
-		if (ret == 0) {
-			edev->config_addr = regs[0];
-
-			/* If the newer, better, ibm,get-config-addr-info is supported, 
-			 * then use that instead.
-			 */
-			edev->pe_config_addr = eeh_ops->get_pe_addr(dn);
-
-			/* Some older systems (Power4) allow the
-			 * ibm,set-eeh-option call to succeed even on nodes
-			 * where EEH is not supported. Verify support
-			 * explicitly.
-			 */
-			ret = eeh_ops->get_state(dn, NULL);
-			if (ret > 0 && ret != EEH_STATE_NOT_SUPPORT)
-				enable = 1;
-		}
-
-		if (enable) {
-			eeh_subsystem_enabled = 1;
-			edev->mode |= EEH_MODE_SUPPORTED;
-
-			pr_debug("EEH: %s: eeh enabled, config=%x pe_config=%x\n",
-				 dn->full_name, edev->config_addr,
-				 edev->pe_config_addr);
-		} else {
-
-			/* This device doesn't support EEH, but it may have an
-			 * EEH parent, in which case we mark it as supported.
-			 */
-			if (dn->parent && of_node_to_eeh_dev(dn->parent) &&
-			    (of_node_to_eeh_dev(dn->parent)->mode & EEH_MODE_SUPPORTED)) {
-				/* Parent supports EEH. */
-				edev->mode |= EEH_MODE_SUPPORTED;
-				edev->config_addr = of_node_to_eeh_dev(dn->parent)->config_addr;
-				return NULL;
-			}
-		}
-	} else {
-		printk(KERN_WARNING "EEH: %s: unable to get reg property.\n",
-		       dn->full_name);
-	}
-
-	eeh_save_bars(edev);
-	return NULL;
-}
-
-/**
  * eeh_ops_register - Register platform dependent EEH operations
  * @ops: platform dependent EEH operations
  *
@@ -982,7 +674,7 @@ int __exit eeh_ops_unregister(const char *name)
  * Even if force-off is set, the EEH hardware is still enabled, so that
  * newer systems can boot.
  */
-void __init eeh_init(void)
+static int __init eeh_init(void)
 {
 	struct pci_controller *hose, *tmp;
 	struct device_node *phb;
@@ -992,27 +684,34 @@ void __init eeh_init(void)
 	if (!eeh_ops) {
 		pr_warning("%s: Platform EEH operation not found\n",
 			__func__);
-		return;
+		return -EEXIST;
 	} else if ((ret = eeh_ops->init())) {
 		pr_warning("%s: Failed to call platform init function (%d)\n",
 			__func__, ret);
-		return;
+		return ret;
 	}
 
 	raw_spin_lock_init(&confirm_error_lock);
 
 	/* Enable EEH for all adapters */
-	list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
-		phb = hose->dn;
-		traverse_pci_devices(phb, eeh_early_enable, NULL);
+	if (eeh_probe_mode_devtree()) {
+		list_for_each_entry_safe(hose, tmp,
+			&hose_list, list_node) {
+			phb = hose->dn;
+			traverse_pci_devices(phb, eeh_ops->of_probe, NULL);
+		}
 	}
 
 	if (eeh_subsystem_enabled)
-		printk(KERN_INFO "EEH: PCI Enhanced I/O Error Handling Enabled\n");
+		pr_info("EEH: PCI Enhanced I/O Error Handling Enabled\n");
 	else
-		printk(KERN_WARNING "EEH: No capable adapters found\n");
+		pr_warning("EEH: No capable adapters found\n");
+
+	return ret;
 }
 
+core_initcall_sync(eeh_init);
+
 /**
  * eeh_add_device_early - Enable EEH for the indicated device_node
  * @dn: device node for which to set up EEH
@@ -1029,7 +728,7 @@ static void eeh_add_device_early(struct device_node *dn)
 {
 	struct pci_controller *phb;
 
-	if (!dn || !of_node_to_eeh_dev(dn))
+	if (!of_node_to_eeh_dev(dn))
 		return;
 	phb = of_node_to_eeh_dev(dn)->phb;
 
@@ -1037,7 +736,8 @@ static void eeh_add_device_early(struct device_node *dn)
 	if (NULL == phb || 0 == phb->buid)
 		return;
 
-	eeh_early_enable(dn, NULL);
+	/* FIXME: hotplug support on POWERNV */
+	eeh_ops->of_probe(dn, NULL);
 }
 
 /**
@@ -1087,7 +787,7 @@ static void eeh_add_device_late(struct pci_dev *dev)
 	edev->pdev = dev;
 	dev->dev.archdata.edev = edev;
 
-	pci_addr_cache_insert_device(dev);
+	eeh_addr_cache_insert_dev(dev);
 	eeh_sysfs_add_device(dev);
 }
 
@@ -1117,6 +817,7 @@ EXPORT_SYMBOL_GPL(eeh_add_device_tree_late);
 /**
  * eeh_remove_device - Undo EEH setup for the indicated pci device
  * @dev: pci device to be removed
+ * @purge_pe: remove the PE or not
  *
  * This routine should be called when a device is removed from
  * a running system (e.g. by hotplug or dlpar).  It unregisters
@@ -1124,7 +825,7 @@ EXPORT_SYMBOL_GPL(eeh_add_device_tree_late);
  * this device will no longer be detected after this call; thus,
  * i/o errors affecting this slot may leave this device unusable.
  */
-static void eeh_remove_device(struct pci_dev *dev)
+static void eeh_remove_device(struct pci_dev *dev, int purge_pe)
 {
 	struct eeh_dev *edev;
 
@@ -1143,28 +844,30 @@ static void eeh_remove_device(struct pci_dev *dev)
 	dev->dev.archdata.edev = NULL;
 	pci_dev_put(dev);
 
-	pci_addr_cache_remove_device(dev);
+	eeh_rmv_from_parent_pe(edev, purge_pe);
+	eeh_addr_cache_rmv_dev(dev);
 	eeh_sysfs_remove_device(dev);
 }
 
 /**
  * eeh_remove_bus_device - Undo EEH setup for the indicated PCI device
  * @dev: PCI device
+ * @purge_pe: remove the corresponding PE or not
  *
  * This routine must be called when a device is removed from the
  * running system through hotplug or dlpar. The corresponding
  * PCI address cache will be removed.
  */
-void eeh_remove_bus_device(struct pci_dev *dev)
+void eeh_remove_bus_device(struct pci_dev *dev, int purge_pe)
 {
 	struct pci_bus *bus = dev->subordinate;
 	struct pci_dev *child, *tmp;
 
-	eeh_remove_device(dev);
+	eeh_remove_device(dev, purge_pe);
 
 	if (bus && dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
 		list_for_each_entry_safe(child, tmp, &bus->devices, bus_list)
-			 eeh_remove_bus_device(child);
+			 eeh_remove_bus_device(child, purge_pe);
 	}
 }
 EXPORT_SYMBOL_GPL(eeh_remove_bus_device);
diff --git a/arch/powerpc/platforms/pseries/eeh_cache.c b/arch/powerpc/platforms/pseries/eeh_cache.c
index e5ae1c6..5a4c879 100644
--- a/arch/powerpc/platforms/pseries/eeh_cache.c
+++ b/arch/powerpc/platforms/pseries/eeh_cache.c
@@ -50,6 +50,7 @@ struct pci_io_addr_range {
 	struct rb_node rb_node;
 	unsigned long addr_lo;
 	unsigned long addr_hi;
+	struct eeh_dev *edev;
 	struct pci_dev *pcidev;
 	unsigned int flags;
 };
@@ -59,7 +60,7 @@ static struct pci_io_addr_cache {
 	spinlock_t piar_lock;
 } pci_io_addr_cache_root;
 
-static inline struct pci_dev *__pci_addr_cache_get_device(unsigned long addr)
+static inline struct eeh_dev *__eeh_addr_cache_get_device(unsigned long addr)
 {
 	struct rb_node *n = pci_io_addr_cache_root.rb_root.rb_node;
 
@@ -74,7 +75,7 @@ static inline struct pci_dev *__pci_addr_cache_get_device(unsigned long addr)
 				n = n->rb_right;
 			} else {
 				pci_dev_get(piar->pcidev);
-				return piar->pcidev;
+				return piar->edev;
 			}
 		}
 	}
@@ -83,7 +84,7 @@ static inline struct pci_dev *__pci_addr_cache_get_device(unsigned long addr)
 }
 
 /**
- * pci_addr_cache_get_device - Get device, given only address
+ * eeh_addr_cache_get_dev - Get device, given only address
  * @addr: mmio (PIO) phys address or i/o port number
  *
  * Given an mmio phys address, or a port number, find a pci device
@@ -92,15 +93,15 @@ static inline struct pci_dev *__pci_addr_cache_get_device(unsigned long addr)
  * from zero (that is, they do *not* have pci_io_addr added in).
  * It is safe to call this function within an interrupt.
  */
-struct pci_dev *pci_addr_cache_get_device(unsigned long addr)
+struct eeh_dev *eeh_addr_cache_get_dev(unsigned long addr)
 {
-	struct pci_dev *dev;
+	struct eeh_dev *edev;
 	unsigned long flags;
 
 	spin_lock_irqsave(&pci_io_addr_cache_root.piar_lock, flags);
-	dev = __pci_addr_cache_get_device(addr);
+	edev = __eeh_addr_cache_get_device(addr);
 	spin_unlock_irqrestore(&pci_io_addr_cache_root.piar_lock, flags);
-	return dev;
+	return edev;
 }
 
 #ifdef DEBUG
@@ -108,7 +109,7 @@ struct pci_dev *pci_addr_cache_get_device(unsigned long addr)
  * Handy-dandy debug print routine, does nothing more
  * than print out the contents of our addr cache.
  */
-static void pci_addr_cache_print(struct pci_io_addr_cache *cache)
+static void eeh_addr_cache_print(struct pci_io_addr_cache *cache)
 {
 	struct rb_node *n;
 	int cnt = 0;
@@ -117,7 +118,7 @@ static void pci_addr_cache_print(struct pci_io_addr_cache *cache)
 	while (n) {
 		struct pci_io_addr_range *piar;
 		piar = rb_entry(n, struct pci_io_addr_range, rb_node);
-		printk(KERN_DEBUG "PCI: %s addr range %d [%lx-%lx]: %s\n",
+		pr_debug("PCI: %s addr range %d [%lx-%lx]: %s\n",
 		       (piar->flags & IORESOURCE_IO) ? "i/o" : "mem", cnt,
 		       piar->addr_lo, piar->addr_hi, pci_name(piar->pcidev));
 		cnt++;
@@ -128,7 +129,7 @@ static void pci_addr_cache_print(struct pci_io_addr_cache *cache)
 
 /* Insert address range into the rb tree. */
 static struct pci_io_addr_range *
-pci_addr_cache_insert(struct pci_dev *dev, unsigned long alo,
+eeh_addr_cache_insert(struct pci_dev *dev, unsigned long alo,
 		      unsigned long ahi, unsigned int flags)
 {
 	struct rb_node **p = &pci_io_addr_cache_root.rb_root.rb_node;
@@ -146,23 +147,24 @@ pci_addr_cache_insert(struct pci_dev *dev, unsigned long alo,
 		} else {
 			if (dev != piar->pcidev ||
 			    alo != piar->addr_lo || ahi != piar->addr_hi) {
-				printk(KERN_WARNING "PIAR: overlapping address range\n");
+				pr_warning("PIAR: overlapping address range\n");
 			}
 			return piar;
 		}
 	}
-	piar = kmalloc(sizeof(struct pci_io_addr_range), GFP_ATOMIC);
+	piar = kzalloc(sizeof(struct pci_io_addr_range), GFP_ATOMIC);
 	if (!piar)
 		return NULL;
 
 	pci_dev_get(dev);
 	piar->addr_lo = alo;
 	piar->addr_hi = ahi;
+	piar->edev = pci_dev_to_eeh_dev(dev);
 	piar->pcidev = dev;
 	piar->flags = flags;
 
 #ifdef DEBUG
-	printk(KERN_DEBUG "PIAR: insert range=[%lx:%lx] dev=%s\n",
+	pr_debug("PIAR: insert range=[%lx:%lx] dev=%s\n",
 	                  alo, ahi, pci_name(dev));
 #endif
 
@@ -172,7 +174,7 @@ pci_addr_cache_insert(struct pci_dev *dev, unsigned long alo,
 	return piar;
 }
 
-static void __pci_addr_cache_insert_device(struct pci_dev *dev)
+static void __eeh_addr_cache_insert_dev(struct pci_dev *dev)
 {
 	struct device_node *dn;
 	struct eeh_dev *edev;
@@ -180,7 +182,7 @@ static void __pci_addr_cache_insert_device(struct pci_dev *dev)
 
 	dn = pci_device_to_OF_node(dev);
 	if (!dn) {
-		printk(KERN_WARNING "PCI: no pci dn found for dev=%s\n", pci_name(dev));
+		pr_warning("PCI: no pci dn found for dev=%s\n", pci_name(dev));
 		return;
 	}
 
@@ -192,8 +194,7 @@ static void __pci_addr_cache_insert_device(struct pci_dev *dev)
 	}
 
 	/* Skip any devices for which EEH is not enabled. */
-	if (!(edev->mode & EEH_MODE_SUPPORTED) ||
-	    edev->mode & EEH_MODE_NOCHECK) {
+	if (!edev->pe) {
 #ifdef DEBUG
 		pr_info("PCI: skip building address cache for=%s - %s\n",
 			pci_name(dev), dn->full_name);
@@ -212,19 +213,19 @@ static void __pci_addr_cache_insert_device(struct pci_dev *dev)
 			continue;
 		if (start == 0 || ~start == 0 || end == 0 || ~end == 0)
 			 continue;
-		pci_addr_cache_insert(dev, start, end, flags);
+		eeh_addr_cache_insert(dev, start, end, flags);
 	}
 }
 
 /**
- * pci_addr_cache_insert_device - Add a device to the address cache
+ * eeh_addr_cache_insert_dev - Add a device to the address cache
  * @dev: PCI device whose I/O addresses we are interested in.
  *
  * In order to support the fast lookup of devices based on addresses,
  * we maintain a cache of devices that can be quickly searched.
  * This routine adds a device to that cache.
  */
-void pci_addr_cache_insert_device(struct pci_dev *dev)
+void eeh_addr_cache_insert_dev(struct pci_dev *dev)
 {
 	unsigned long flags;
 
@@ -233,11 +234,11 @@ void pci_addr_cache_insert_device(struct pci_dev *dev)
 		return;
 
 	spin_lock_irqsave(&pci_io_addr_cache_root.piar_lock, flags);
-	__pci_addr_cache_insert_device(dev);
+	__eeh_addr_cache_insert_dev(dev);
 	spin_unlock_irqrestore(&pci_io_addr_cache_root.piar_lock, flags);
 }
 
-static inline void __pci_addr_cache_remove_device(struct pci_dev *dev)
+static inline void __eeh_addr_cache_rmv_dev(struct pci_dev *dev)
 {
 	struct rb_node *n;
 
@@ -258,7 +259,7 @@ restart:
 }
 
 /**
- * pci_addr_cache_remove_device - remove pci device from addr cache
+ * eeh_addr_cache_rmv_dev - remove pci device from addr cache
  * @dev: device to remove
  *
  * Remove a device from the addr-cache tree.
@@ -266,17 +267,17 @@ restart:
  * the tree multiple times (once per resource).
  * But so what; device removal doesn't need to be that fast.
  */
-void pci_addr_cache_remove_device(struct pci_dev *dev)
+void eeh_addr_cache_rmv_dev(struct pci_dev *dev)
 {
 	unsigned long flags;
 
 	spin_lock_irqsave(&pci_io_addr_cache_root.piar_lock, flags);
-	__pci_addr_cache_remove_device(dev);
+	__eeh_addr_cache_rmv_dev(dev);
 	spin_unlock_irqrestore(&pci_io_addr_cache_root.piar_lock, flags);
 }
 
 /**
- * pci_addr_cache_build - Build a cache of I/O addresses
+ * eeh_addr_cache_build - Build a cache of I/O addresses
  *
  * Build a cache of pci i/o addresses.  This cache will be used to
  * find the pci device that corresponds to a given address.
@@ -284,7 +285,7 @@ void pci_addr_cache_remove_device(struct pci_dev *dev)
  * Must be run late in boot process, after the pci controllers
  * have been scanned for devices (after all device resources are known).
  */
-void __init pci_addr_cache_build(void)
+void __init eeh_addr_cache_build(void)
 {
 	struct device_node *dn;
 	struct eeh_dev *edev;
@@ -293,7 +294,7 @@ void __init pci_addr_cache_build(void)
 	spin_lock_init(&pci_io_addr_cache_root.piar_lock);
 
 	for_each_pci_dev(dev) {
-		pci_addr_cache_insert_device(dev);
+		eeh_addr_cache_insert_dev(dev);
 
 		dn = pci_device_to_OF_node(dev);
 		if (!dn)
@@ -312,7 +313,7 @@ void __init pci_addr_cache_build(void)
 
 #ifdef DEBUG
 	/* Verify tree built up above, echo back the list of addrs. */
-	pci_addr_cache_print(&pci_io_addr_cache_root);
+	eeh_addr_cache_print(&pci_io_addr_cache_root);
 #endif
 }
 
diff --git a/arch/powerpc/platforms/pseries/eeh_dev.c b/arch/powerpc/platforms/pseries/eeh_dev.c
index c4507d0..6644234 100644
--- a/arch/powerpc/platforms/pseries/eeh_dev.c
+++ b/arch/powerpc/platforms/pseries/eeh_dev.c
@@ -55,7 +55,7 @@ void * __devinit eeh_dev_init(struct device_node *dn, void *data)
 	struct eeh_dev *edev;
 
 	/* Allocate EEH device */
-	edev = zalloc_maybe_bootmem(sizeof(*edev), GFP_KERNEL);
+	edev = kzalloc(sizeof(*edev), GFP_KERNEL);
 	if (!edev) {
 		pr_warning("%s: out of memory\n", __func__);
 		return NULL;
@@ -65,6 +65,7 @@ void * __devinit eeh_dev_init(struct device_node *dn, void *data)
 	PCI_DN(dn)->edev = edev;
 	edev->dn  = dn;
 	edev->phb = phb;
+	INIT_LIST_HEAD(&edev->list);
 
 	return NULL;
 }
@@ -80,6 +81,9 @@ void __devinit eeh_dev_phb_init_dynamic(struct pci_controller *phb)
 {
 	struct device_node *dn = phb->dn;
 
+	/* EEH PE for PHB */
+	eeh_phb_pe_create(phb);
+
 	/* EEH device for PHB */
 	eeh_dev_init(dn, phb);
 
@@ -93,10 +97,16 @@ void __devinit eeh_dev_phb_init_dynamic(struct pci_controller *phb)
  * Scan all the existing PHBs and create EEH devices for their OF
  * nodes and their children OF nodes
  */
-void __init eeh_dev_phb_init(void)
+static int __init eeh_dev_phb_init(void)
 {
 	struct pci_controller *phb, *tmp;
 
 	list_for_each_entry_safe(phb, tmp, &hose_list, list_node)
 		eeh_dev_phb_init_dynamic(phb);
+
+	pr_info("EEH: devices created\n");
+
+	return 0;
 }
+
+core_initcall(eeh_dev_phb_init);
diff --git a/arch/powerpc/platforms/pseries/eeh_driver.c b/arch/powerpc/platforms/pseries/eeh_driver.c
index baf92cd..a3fefb6 100644
--- a/arch/powerpc/platforms/pseries/eeh_driver.c
+++ b/arch/powerpc/platforms/pseries/eeh_driver.c
@@ -25,6 +25,7 @@
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
+#include <linux/module.h>
 #include <linux/pci.h>
 #include <asm/eeh.h>
 #include <asm/eeh_event.h>
@@ -47,6 +48,41 @@ static inline const char *eeh_pcid_name(struct pci_dev *pdev)
 	return "";
 }
 
+/**
+ * eeh_pcid_get - Get the PCI device driver
+ * @pdev: PCI device
+ *
+ * The function is used to retrieve the PCI device driver for
+ * the indicated PCI device. Besides, we will increase the reference
+ * of the PCI device driver to prevent that being unloaded on
+ * the fly. Otherwise, kernel crash would be seen.
+ */
+static inline struct pci_driver *eeh_pcid_get(struct pci_dev *pdev)
+{
+	if (!pdev || !pdev->driver)
+		return NULL;
+
+	if (!try_module_get(pdev->driver->driver.owner))
+		return NULL;
+
+	return pdev->driver;
+}
+
+/**
+ * eeh_pcid_put - Dereference on the PCI device driver
+ * @pdev: PCI device
+ *
+ * The function is called to do dereference on the PCI device
+ * driver of the indicated PCI device.
+ */
+static inline void eeh_pcid_put(struct pci_dev *pdev)
+{
+	if (!pdev || !pdev->driver)
+		return;
+
+	module_put(pdev->driver->driver.owner);
+}
+
 #if 0
 static void print_device_node_tree(struct pci_dn *pdn, int dent)
 {
@@ -93,7 +129,7 @@ static void eeh_disable_irq(struct pci_dev *dev)
 	if (!irq_has_action(dev->irq))
 		return;
 
-	edev->mode |= EEH_MODE_IRQ_DISABLED;
+	edev->mode |= EEH_DEV_IRQ_DISABLED;
 	disable_irq_nosync(dev->irq);
 }
 
@@ -108,36 +144,44 @@ static void eeh_enable_irq(struct pci_dev *dev)
 {
 	struct eeh_dev *edev = pci_dev_to_eeh_dev(dev);
 
-	if ((edev->mode) & EEH_MODE_IRQ_DISABLED) {
-		edev->mode &= ~EEH_MODE_IRQ_DISABLED;
+	if ((edev->mode) & EEH_DEV_IRQ_DISABLED) {
+		edev->mode &= ~EEH_DEV_IRQ_DISABLED;
 		enable_irq(dev->irq);
 	}
 }
 
 /**
  * eeh_report_error - Report pci error to each device driver
- * @dev: PCI device
+ * @data: eeh device
  * @userdata: return value
  * 
  * Report an EEH error to each device driver, collect up and 
  * merge the device driver responses. Cumulative response 
  * passed back in "userdata".
  */
-static int eeh_report_error(struct pci_dev *dev, void *userdata)
+static void *eeh_report_error(void *data, void *userdata)
 {
+	struct eeh_dev *edev = (struct eeh_dev *)data;
+	struct pci_dev *dev = eeh_dev_to_pci_dev(edev);
 	enum pci_ers_result rc, *res = userdata;
-	struct pci_driver *driver = dev->driver;
+	struct pci_driver *driver;
 
+	/* We might not have the associated PCI device,
+	 * then we should continue for next one.
+	 */
+	if (!dev) return NULL;
 	dev->error_state = pci_channel_io_frozen;
 
-	if (!driver)
-		return 0;
+	driver = eeh_pcid_get(dev);
+	if (!driver) return NULL;
 
 	eeh_disable_irq(dev);
 
 	if (!driver->err_handler ||
-	    !driver->err_handler->error_detected)
-		return 0;
+	    !driver->err_handler->error_detected) {
+		eeh_pcid_put(dev);
+		return NULL;
+	}
 
 	rc = driver->err_handler->error_detected(dev, pci_channel_io_frozen);
 
@@ -145,27 +189,34 @@ static int eeh_report_error(struct pci_dev *dev, void *userdata)
 	if (rc == PCI_ERS_RESULT_NEED_RESET) *res = rc;
 	if (*res == PCI_ERS_RESULT_NONE) *res = rc;
 
-	return 0;
+	eeh_pcid_put(dev);
+	return NULL;
 }
 
 /**
  * eeh_report_mmio_enabled - Tell drivers that MMIO has been enabled
- * @dev: PCI device
+ * @data: eeh device
  * @userdata: return value
  *
  * Tells each device driver that IO ports, MMIO and config space I/O
  * are now enabled. Collects up and merges the device driver responses.
  * Cumulative response passed back in "userdata".
  */
-static int eeh_report_mmio_enabled(struct pci_dev *dev, void *userdata)
+static void *eeh_report_mmio_enabled(void *data, void *userdata)
 {
+	struct eeh_dev *edev = (struct eeh_dev *)data;
+	struct pci_dev *dev = eeh_dev_to_pci_dev(edev);
 	enum pci_ers_result rc, *res = userdata;
-	struct pci_driver *driver = dev->driver;
+	struct pci_driver *driver;
 
-	if (!driver ||
-	    !driver->err_handler ||
-	    !driver->err_handler->mmio_enabled)
-		return 0;
+	driver = eeh_pcid_get(dev);
+	if (!driver) return NULL;
+
+	if (!driver->err_handler ||
+	    !driver->err_handler->mmio_enabled) {
+		eeh_pcid_put(dev);
+		return NULL;
+	}
 
 	rc = driver->err_handler->mmio_enabled(dev);
 
@@ -173,12 +224,13 @@ static int eeh_report_mmio_enabled(struct pci_dev *dev, void *userdata)
 	if (rc == PCI_ERS_RESULT_NEED_RESET) *res = rc;
 	if (*res == PCI_ERS_RESULT_NONE) *res = rc;
 
-	return 0;
+	eeh_pcid_put(dev);
+	return NULL;
 }
 
 /**
  * eeh_report_reset - Tell device that slot has been reset
- * @dev: PCI device
+ * @data: eeh device
  * @userdata: return value
  *
  * This routine must be called while EEH tries to reset particular
@@ -186,21 +238,26 @@ static int eeh_report_mmio_enabled(struct pci_dev *dev, void *userdata)
  * some actions, usually to save data the driver needs so that the
  * driver can work again while the device is recovered.
  */
-static int eeh_report_reset(struct pci_dev *dev, void *userdata)
+static void *eeh_report_reset(void *data, void *userdata)
 {
+	struct eeh_dev *edev = (struct eeh_dev *)data;
+	struct pci_dev *dev = eeh_dev_to_pci_dev(edev);
 	enum pci_ers_result rc, *res = userdata;
-	struct pci_driver *driver = dev->driver;
-
-	if (!driver)
-		return 0;
+	struct pci_driver *driver;
 
+	if (!dev) return NULL;
 	dev->error_state = pci_channel_io_normal;
 
+	driver = eeh_pcid_get(dev);
+	if (!driver) return NULL;
+
 	eeh_enable_irq(dev);
 
 	if (!driver->err_handler ||
-	    !driver->err_handler->slot_reset)
-		return 0;
+	    !driver->err_handler->slot_reset) {
+		eeh_pcid_put(dev);
+		return NULL;
+	}
 
 	rc = driver->err_handler->slot_reset(dev);
 	if ((*res == PCI_ERS_RESULT_NONE) ||
@@ -208,109 +265,115 @@ static int eeh_report_reset(struct pci_dev *dev, void *userdata)
 	if (*res == PCI_ERS_RESULT_DISCONNECT &&
 	     rc == PCI_ERS_RESULT_NEED_RESET) *res = rc;
 
-	return 0;
+	eeh_pcid_put(dev);
+	return NULL;
 }
 
 /**
  * eeh_report_resume - Tell device to resume normal operations
- * @dev: PCI device
+ * @data: eeh device
  * @userdata: return value
  *
  * This routine must be called to notify the device driver that it
  * could resume so that the device driver can do some initialization
  * to make the recovered device work again.
  */
-static int eeh_report_resume(struct pci_dev *dev, void *userdata)
+static void *eeh_report_resume(void *data, void *userdata)
 {
-	struct pci_driver *driver = dev->driver;
+	struct eeh_dev *edev = (struct eeh_dev *)data;
+	struct pci_dev *dev = eeh_dev_to_pci_dev(edev);
+	struct pci_driver *driver;
 
+	if (!dev) return NULL;
 	dev->error_state = pci_channel_io_normal;
 
-	if (!driver)
-		return 0;
+	driver = eeh_pcid_get(dev);
+	if (!driver) return NULL;
 
 	eeh_enable_irq(dev);
 
 	if (!driver->err_handler ||
-	    !driver->err_handler->resume)
-		return 0;
+	    !driver->err_handler->resume) {
+		eeh_pcid_put(dev);
+		return NULL;
+	}
 
 	driver->err_handler->resume(dev);
 
-	return 0;
+	eeh_pcid_put(dev);
+	return NULL;
 }
 
 /**
  * eeh_report_failure - Tell device driver that device is dead.
- * @dev: PCI device
+ * @data: eeh device
  * @userdata: return value
  *
  * This informs the device driver that the device is permanently
  * dead, and that no further recovery attempts will be made on it.
  */
-static int eeh_report_failure(struct pci_dev *dev, void *userdata)
+static void *eeh_report_failure(void *data, void *userdata)
 {
-	struct pci_driver *driver = dev->driver;
+	struct eeh_dev *edev = (struct eeh_dev *)data;
+	struct pci_dev *dev = eeh_dev_to_pci_dev(edev);
+	struct pci_driver *driver;
 
+	if (!dev) return NULL;
 	dev->error_state = pci_channel_io_perm_failure;
 
-	if (!driver)
-		return 0;
+	driver = eeh_pcid_get(dev);
+	if (!driver) return NULL;
 
 	eeh_disable_irq(dev);
 
 	if (!driver->err_handler ||
-	    !driver->err_handler->error_detected)
-		return 0;
+	    !driver->err_handler->error_detected) {
+		eeh_pcid_put(dev);
+		return NULL;
+	}
 
 	driver->err_handler->error_detected(dev, pci_channel_io_perm_failure);
 
-	return 0;
+	eeh_pcid_put(dev);
+	return NULL;
 }
 
 /**
  * eeh_reset_device - Perform actual reset of a pci slot
- * @edev: PE associated EEH device
+ * @pe: EEH PE
  * @bus: PCI bus corresponding to the isolcated slot
  *
  * This routine must be called to do reset on the indicated PE.
  * During the reset, udev might be invoked because those affected
  * PCI devices will be removed and then added.
  */
-static int eeh_reset_device(struct eeh_dev *edev, struct pci_bus *bus)
+static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus)
 {
-	struct device_node *dn;
 	int cnt, rc;
 
 	/* pcibios will clear the counter; save the value */
-	cnt = edev->freeze_count;
+	cnt = pe->freeze_count;
 
+	/*
+	 * We don't remove the corresponding PE instances because
+	 * we need the information afterwords. The attached EEH
+	 * devices are expected to be attached soon when calling
+	 * into pcibios_add_pci_devices().
+	 */
 	if (bus)
-		pcibios_remove_pci_devices(bus);
+		__pcibios_remove_pci_devices(bus, 0);
 
 	/* Reset the pci controller. (Asserts RST#; resets config space).
 	 * Reconfigure bridges and devices. Don't try to bring the system
 	 * up if the reset failed for some reason.
 	 */
-	rc = eeh_reset_pe(edev);
+	rc = eeh_reset_pe(pe);
 	if (rc)
 		return rc;
 
-	/* Walk over all functions on this device. */
-	dn = eeh_dev_to_of_node(edev);
-	if (!pcibios_find_pci_bus(dn) && of_node_to_eeh_dev(dn->parent))
-		dn = dn->parent->child;
-
-	while (dn) {
-		struct eeh_dev *pedev = of_node_to_eeh_dev(dn);
-
-		/* On Power4, always true because eeh_pe_config_addr=0 */
-		if (edev->pe_config_addr == pedev->pe_config_addr) {
-			eeh_ops->configure_bridge(dn);
-			eeh_restore_bars(pedev);
- 		}
-		dn = dn->sibling;
-	}
+	/* Restore PE */
+	eeh_ops->configure_bridge(pe);
+	eeh_pe_restore_bars(pe);
 
 	/* Give the system 5 seconds to finish running the user-space
 	 * hotplug shutdown scripts, e.g. ifdown for ethernet.  Yes, 
@@ -322,7 +385,7 @@ static int eeh_reset_device(struct eeh_dev *edev, struct pci_bus *bus)
 		ssleep(5);
 		pcibios_add_pci_devices(bus);
 	}
-	edev->freeze_count = cnt;
+	pe->freeze_count = cnt;
 
 	return 0;
 }
@@ -334,7 +397,7 @@ static int eeh_reset_device(struct eeh_dev *edev, struct pci_bus *bus)
 
 /**
  * eeh_handle_event - Reset a PCI device after hard lockup.
- * @event: EEH event
+ * @pe: EEH PE
  *
  * While PHB detects address or data parity errors on particular PCI
  * slot, the associated PE will be frozen. Besides, DMA's occurring
@@ -349,69 +412,24 @@ static int eeh_reset_device(struct eeh_dev *edev, struct pci_bus *bus)
  * drivers (which cause a second set of hotplug events to go out to
  * userspace).
  */
-struct eeh_dev *handle_eeh_events(struct eeh_event *event)
+void eeh_handle_event(struct eeh_pe *pe)
 {
-	struct device_node *frozen_dn;
-	struct eeh_dev *frozen_edev;
 	struct pci_bus *frozen_bus;
 	int rc = 0;
 	enum pci_ers_result result = PCI_ERS_RESULT_NONE;
-	const char *location, *pci_str, *drv_str, *bus_pci_str, *bus_drv_str;
-
-	frozen_dn = eeh_find_device_pe(eeh_dev_to_of_node(event->edev));
-	if (!frozen_dn) {
-		location = of_get_property(eeh_dev_to_of_node(event->edev), "ibm,loc-code", NULL);
-		location = location ? location : "unknown";
-		printk(KERN_ERR "EEH: Error: Cannot find partition endpoint "
-		                "for location=%s pci addr=%s\n",
-			location, eeh_pci_name(eeh_dev_to_pci_dev(event->edev)));
-		return NULL;
-	}
-
-	frozen_bus = pcibios_find_pci_bus(frozen_dn);
-	location = of_get_property(frozen_dn, "ibm,loc-code", NULL);
-	location = location ? location : "unknown";
-
-	/* There are two different styles for coming up with the PE.
-	 * In the old style, it was the highest EEH-capable device
-	 * which was always an EADS pci bridge.  In the new style,
-	 * there might not be any EADS bridges, and even when there are,
-	 * the firmware marks them as "EEH incapable". So another
-	 * two-step is needed to find the pci bus..
-	 */
-	if (!frozen_bus)
-		frozen_bus = pcibios_find_pci_bus(frozen_dn->parent);
 
+	frozen_bus = eeh_pe_bus_get(pe);
 	if (!frozen_bus) {
-		printk(KERN_ERR "EEH: Cannot find PCI bus "
-		        "for location=%s dn=%s\n",
-		        location, frozen_dn->full_name);
-		return NULL;
+		pr_err("%s: Cannot find PCI bus for PHB#%d-PE#%x\n",
+			__func__, pe->phb->global_number, pe->addr);
+		return;
 	}
 
-	frozen_edev = of_node_to_eeh_dev(frozen_dn);
-	frozen_edev->freeze_count++;
-	pci_str = eeh_pci_name(eeh_dev_to_pci_dev(event->edev));
-	drv_str = eeh_pcid_name(eeh_dev_to_pci_dev(event->edev));
-
-	if (frozen_edev->freeze_count > EEH_MAX_ALLOWED_FREEZES)
+	pe->freeze_count++;
+	if (pe->freeze_count > EEH_MAX_ALLOWED_FREEZES)
 		goto excess_failures;
-
-	printk(KERN_WARNING
-	   "EEH: This PCI device has failed %d times in the last hour:\n",
-		frozen_edev->freeze_count);
-
-	if (frozen_edev->pdev) {
-		bus_pci_str = pci_name(frozen_edev->pdev);
-		bus_drv_str = eeh_pcid_name(frozen_edev->pdev);
-		printk(KERN_WARNING
-			"EEH: Bus location=%s driver=%s pci addr=%s\n",
-			location, bus_drv_str, bus_pci_str);
-	}
-
-	printk(KERN_WARNING
-		"EEH: Device location=%s driver=%s pci addr=%s\n",
-		location, drv_str, pci_str);
+	pr_warning("EEH: This PCI device has failed %d times in the last hour\n",
+		pe->freeze_count);
 
 	/* Walk the various device drivers attached to this slot through
 	 * a reset sequence, giving each an opportunity to do what it needs
@@ -419,12 +437,12 @@ struct eeh_dev *handle_eeh_events(struct eeh_event *event)
 	 * status ... if any child can't handle the reset, then the entire
 	 * slot is dlpar removed and added.
 	 */
-	pci_walk_bus(frozen_bus, eeh_report_error, &result);
+	eeh_pe_dev_traverse(pe, eeh_report_error, &result);
 
 	/* Get the current PCI slot state. This can take a long time,
 	 * sometimes over 3 seconds for certain systems.
 	 */
-	rc = eeh_ops->wait_state(eeh_dev_to_of_node(frozen_edev), MAX_WAIT_FOR_RECOVERY*1000);
+	rc = eeh_ops->wait_state(pe, MAX_WAIT_FOR_RECOVERY*1000);
 	if (rc < 0 || rc == EEH_STATE_NOT_SUPPORT) {
 		printk(KERN_WARNING "EEH: Permanent failure\n");
 		goto hard_fail;
@@ -434,14 +452,14 @@ struct eeh_dev *handle_eeh_events(struct eeh_event *event)
 	 * don't post the error log until after all dev drivers
 	 * have been informed.
 	 */
-	eeh_slot_error_detail(frozen_edev, EEH_LOG_TEMP);
+	eeh_slot_error_detail(pe, EEH_LOG_TEMP);
 
 	/* If all device drivers were EEH-unaware, then shut
 	 * down all of the device drivers, and hope they
 	 * go down willingly, without panicing the system.
 	 */
 	if (result == PCI_ERS_RESULT_NONE) {
-		rc = eeh_reset_device(frozen_edev, frozen_bus);
+		rc = eeh_reset_device(pe, frozen_bus);
 		if (rc) {
 			printk(KERN_WARNING "EEH: Unable to reset, rc=%d\n", rc);
 			goto hard_fail;
@@ -450,7 +468,7 @@ struct eeh_dev *handle_eeh_events(struct eeh_event *event)
 
 	/* If all devices reported they can proceed, then re-enable MMIO */
 	if (result == PCI_ERS_RESULT_CAN_RECOVER) {
-		rc = eeh_pci_enable(frozen_edev, EEH_OPT_THAW_MMIO);
+		rc = eeh_pci_enable(pe, EEH_OPT_THAW_MMIO);
 
 		if (rc < 0)
 			goto hard_fail;
@@ -458,13 +476,13 @@ struct eeh_dev *handle_eeh_events(struct eeh_event *event)
 			result = PCI_ERS_RESULT_NEED_RESET;
 		} else {
 			result = PCI_ERS_RESULT_NONE;
-			pci_walk_bus(frozen_bus, eeh_report_mmio_enabled, &result);
+			eeh_pe_dev_traverse(pe, eeh_report_mmio_enabled, &result);
 		}
 	}
 
 	/* If all devices reported they can proceed, then re-enable DMA */
 	if (result == PCI_ERS_RESULT_CAN_RECOVER) {
-		rc = eeh_pci_enable(frozen_edev, EEH_OPT_THAW_DMA);
+		rc = eeh_pci_enable(pe, EEH_OPT_THAW_DMA);
 
 		if (rc < 0)
 			goto hard_fail;
@@ -482,13 +500,13 @@ struct eeh_dev *handle_eeh_events(struct eeh_event *event)
 
 	/* If any device called out for a reset, then reset the slot */
 	if (result == PCI_ERS_RESULT_NEED_RESET) {
-		rc = eeh_reset_device(frozen_edev, NULL);
+		rc = eeh_reset_device(pe, NULL);
 		if (rc) {
 			printk(KERN_WARNING "EEH: Cannot reset, rc=%d\n", rc);
 			goto hard_fail;
 		}
 		result = PCI_ERS_RESULT_NONE;
-		pci_walk_bus(frozen_bus, eeh_report_reset, &result);
+		eeh_pe_dev_traverse(pe, eeh_report_reset, &result);
 	}
 
 	/* All devices should claim they have recovered by now. */
@@ -499,9 +517,9 @@ struct eeh_dev *handle_eeh_events(struct eeh_event *event)
 	}
 
 	/* Tell all device drivers that they can resume operations */
-	pci_walk_bus(frozen_bus, eeh_report_resume, NULL);
+	eeh_pe_dev_traverse(pe, eeh_report_resume, NULL);
 
-	return frozen_edev;
+	return;
 	
 excess_failures:
 	/*
@@ -509,30 +527,26 @@ excess_failures:
 	 * are due to poorly seated PCI cards. Only 10% or so are
 	 * due to actual, failed cards.
 	 */
-	printk(KERN_ERR
-	   "EEH: PCI device at location=%s driver=%s pci addr=%s\n"
-		"has failed %d times in the last hour "
-		"and has been permanently disabled.\n"
-		"Please try reseating this device or replacing it.\n",
-		location, drv_str, pci_str, frozen_edev->freeze_count);
+	pr_err("EEH: PHB#%d-PE#%x has failed %d times in the\n"
+	       "last hour and has been permanently disabled.\n"
+	       "Please try reseating or replacing it.\n",
+		pe->phb->global_number, pe->addr,
+		pe->freeze_count);
 	goto perm_error;
 
 hard_fail:
-	printk(KERN_ERR
-	   "EEH: Unable to recover from failure of PCI device "
-	   "at location=%s driver=%s pci addr=%s\n"
-	   "Please try reseating this device or replacing it.\n",
-		location, drv_str, pci_str);
+	pr_err("EEH: Unable to recover from failure from PHB#%d-PE#%x.\n"
+	       "Please try reseating or replacing it\n",
+		pe->phb->global_number, pe->addr);
 
 perm_error:
-	eeh_slot_error_detail(frozen_edev, EEH_LOG_PERM);
+	eeh_slot_error_detail(pe, EEH_LOG_PERM);
 
 	/* Notify all devices that they're about to go down. */
-	pci_walk_bus(frozen_bus, eeh_report_failure, NULL);
+	eeh_pe_dev_traverse(pe, eeh_report_failure, NULL);
 
 	/* Shut down the device drivers for good. */
-	pcibios_remove_pci_devices(frozen_bus);
-
-	return NULL;
+	if (frozen_bus)
+		pcibios_remove_pci_devices(frozen_bus);
 }
 
diff --git a/arch/powerpc/platforms/pseries/eeh_event.c b/arch/powerpc/platforms/pseries/eeh_event.c
index fb50631..51faaac 100644
--- a/arch/powerpc/platforms/pseries/eeh_event.c
+++ b/arch/powerpc/platforms/pseries/eeh_event.c
@@ -57,7 +57,7 @@ static int eeh_event_handler(void * dummy)
 {
 	unsigned long flags;
 	struct eeh_event *event;
-	struct eeh_dev *edev;
+	struct eeh_pe *pe;
 
 	set_task_comm(current, "eehd");
 
@@ -76,28 +76,23 @@ static int eeh_event_handler(void * dummy)
 
 	/* Serialize processing of EEH events */
 	mutex_lock(&eeh_event_mutex);
-	edev = event->edev;
-	eeh_mark_slot(eeh_dev_to_of_node(edev), EEH_MODE_RECOVERING);
-
-	printk(KERN_INFO "EEH: Detected PCI bus error on device %s\n",
-	       eeh_pci_name(edev->pdev));
+	pe = event->pe;
+	eeh_pe_state_mark(pe, EEH_PE_RECOVERING);
+	pr_info("EEH: Detected PCI bus error on PHB#%d-PE#%x\n",
+		pe->phb->global_number, pe->addr);
 
 	set_current_state(TASK_INTERRUPTIBLE);	/* Don't add to load average */
-	edev = handle_eeh_events(event);
-
-	if (edev) {
-		eeh_clear_slot(eeh_dev_to_of_node(edev), EEH_MODE_RECOVERING);
-		pci_dev_put(edev->pdev);
-	}
+	eeh_handle_event(pe);
+	eeh_pe_state_clear(pe, EEH_PE_RECOVERING);
 
 	kfree(event);
 	mutex_unlock(&eeh_event_mutex);
 
 	/* If there are no new errors after an hour, clear the counter. */
-	if (edev && edev->freeze_count>0) {
+	if (pe && pe->freeze_count > 0) {
 		msleep_interruptible(3600*1000);
-		if (edev->freeze_count>0)
-			edev->freeze_count--;
+		if (pe->freeze_count > 0)
+			pe->freeze_count--;
 
 	}
 
@@ -119,36 +114,23 @@ static void eeh_thread_launcher(struct work_struct *dummy)
 
 /**
  * eeh_send_failure_event - Generate a PCI error event
- * @edev: EEH device
+ * @pe: EEH PE
  *
  * This routine can be called within an interrupt context;
  * the actual event will be delivered in a normal context
  * (from a workqueue).
  */
-int eeh_send_failure_event(struct eeh_dev *edev)
+int eeh_send_failure_event(struct eeh_pe *pe)
 {
 	unsigned long flags;
 	struct eeh_event *event;
-	struct device_node *dn = eeh_dev_to_of_node(edev);
-	const char *location;
-
-	if (!mem_init_done) {
-		printk(KERN_ERR "EEH: event during early boot not handled\n");
-		location = of_get_property(dn, "ibm,loc-code", NULL);
-		printk(KERN_ERR "EEH: device node = %s\n", dn->full_name);
-		printk(KERN_ERR "EEH: PCI location = %s\n", location);
-		return 1;
-	}
-	event = kmalloc(sizeof(*event), GFP_ATOMIC);
-	if (event == NULL) {
-		printk(KERN_ERR "EEH: out of memory, event not handled\n");
-		return 1;
- 	}
-
-	if (edev->pdev)
-		pci_dev_get(edev->pdev);
 
-	event->edev = edev;
+	event = kzalloc(sizeof(*event), GFP_ATOMIC);
+	if (!event) {
+		pr_err("EEH: out of memory, event not handled\n");
+		return -ENOMEM;
+	}
+	event->pe = pe;
 
 	/* We may or may not be called in an interrupt context */
 	spin_lock_irqsave(&eeh_eventlist_lock, flags);
diff --git a/arch/powerpc/platforms/pseries/eeh_pe.c b/arch/powerpc/platforms/pseries/eeh_pe.c
new file mode 100644
index 0000000..9d35543
--- /dev/null
+++ b/arch/powerpc/platforms/pseries/eeh_pe.c
@@ -0,0 +1,655 @@
+/*
+ * The file intends to implement PE based on the information from
+ * platforms. Basically, there have 3 types of PEs: PHB/Bus/Device.
+ * All the PEs should be organized as hierarchy tree. The first level
+ * of the tree will be associated to existing PHBs since the particular
+ * PE is only meaningful in one PHB domain.
+ *
+ * Copyright Benjamin Herrenschmidt & Gavin Shan, IBM Corporation 2012.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/export.h>
+#include <linux/gfp.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/string.h>
+
+#include <asm/pci-bridge.h>
+#include <asm/ppc-pci.h>
+
+static LIST_HEAD(eeh_phb_pe);
+
+/**
+ * eeh_pe_alloc - Allocate PE
+ * @phb: PCI controller
+ * @type: PE type
+ *
+ * Allocate PE instance dynamically.
+ */
+static struct eeh_pe *eeh_pe_alloc(struct pci_controller *phb, int type)
+{
+	struct eeh_pe *pe;
+
+	/* Allocate PHB PE */
+	pe = kzalloc(sizeof(struct eeh_pe), GFP_KERNEL);
+	if (!pe) return NULL;
+
+	/* Initialize PHB PE */
+	pe->type = type;
+	pe->phb = phb;
+	INIT_LIST_HEAD(&pe->child_list);
+	INIT_LIST_HEAD(&pe->child);
+	INIT_LIST_HEAD(&pe->edevs);
+
+	return pe;
+}
+
+/**
+ * eeh_phb_pe_create - Create PHB PE
+ * @phb: PCI controller
+ *
+ * The function should be called while the PHB is detected during
+ * system boot or PCI hotplug in order to create PHB PE.
+ */
+int __devinit eeh_phb_pe_create(struct pci_controller *phb)
+{
+	struct eeh_pe *pe;
+
+	/* Allocate PHB PE */
+	pe = eeh_pe_alloc(phb, EEH_PE_PHB);
+	if (!pe) {
+		pr_err("%s: out of memory!\n", __func__);
+		return -ENOMEM;
+	}
+
+	/* Put it into the list */
+	eeh_lock();
+	list_add_tail(&pe->child, &eeh_phb_pe);
+	eeh_unlock();
+
+	pr_debug("EEH: Add PE for PHB#%d\n", phb->global_number);
+
+	return 0;
+}
+
+/**
+ * eeh_phb_pe_get - Retrieve PHB PE based on the given PHB
+ * @phb: PCI controller
+ *
+ * The overall PEs form hierarchy tree. The first layer of the
+ * hierarchy tree is composed of PHB PEs. The function is used
+ * to retrieve the corresponding PHB PE according to the given PHB.
+ */
+static struct eeh_pe *eeh_phb_pe_get(struct pci_controller *phb)
+{
+	struct eeh_pe *pe;
+
+	list_for_each_entry(pe, &eeh_phb_pe, child) {
+		/*
+		 * Actually, we needn't check the type since
+		 * the PE for PHB has been determined when that
+		 * was created.
+		 */
+		if ((pe->type & EEH_PE_PHB) &&
+		    pe->phb == phb) {
+			eeh_unlock();
+			return pe;
+		}
+	}
+
+	return NULL;
+}
+
+/**
+ * eeh_pe_next - Retrieve the next PE in the tree
+ * @pe: current PE
+ * @root: root PE
+ *
+ * The function is used to retrieve the next PE in the
+ * hierarchy PE tree.
+ */
+static struct eeh_pe *eeh_pe_next(struct eeh_pe *pe,
+				  struct eeh_pe *root)
+{
+	struct list_head *next = pe->child_list.next;
+
+	if (next == &pe->child_list) {
+		while (1) {
+			if (pe == root)
+				return NULL;
+			next = pe->child.next;
+			if (next != &pe->parent->child_list)
+				break;
+			pe = pe->parent;
+		}
+	}
+
+	return list_entry(next, struct eeh_pe, child);
+}
+
+/**
+ * eeh_pe_traverse - Traverse PEs in the specified PHB
+ * @root: root PE
+ * @fn: callback
+ * @flag: extra parameter to callback
+ *
+ * The function is used to traverse the specified PE and its
+ * child PEs. The traversing is to be terminated once the
+ * callback returns something other than NULL, or no more PEs
+ * to be traversed.
+ */
+static void *eeh_pe_traverse(struct eeh_pe *root,
+			eeh_traverse_func fn, void *flag)
+{
+	struct eeh_pe *pe;
+	void *ret;
+
+	for (pe = root; pe; pe = eeh_pe_next(pe, root)) {
+		ret = fn(pe, flag);
+		if (ret) return ret;
+	}
+
+	return NULL;
+}
+
+/**
+ * eeh_pe_dev_traverse - Traverse the devices from the PE
+ * @root: EEH PE
+ * @fn: function callback
+ * @flag: extra parameter to callback
+ *
+ * The function is used to traverse the devices of the specified
+ * PE and its child PEs.
+ */
+void *eeh_pe_dev_traverse(struct eeh_pe *root,
+		eeh_traverse_func fn, void *flag)
+{
+	struct eeh_pe *pe;
+	struct eeh_dev *edev;
+	void *ret;
+
+	if (!root) {
+		pr_warning("%s: Invalid PE %p\n", __func__, root);
+		return NULL;
+	}
+
+	eeh_lock();
+
+	/* Traverse root PE */
+	for (pe = root; pe; pe = eeh_pe_next(pe, root)) {
+		eeh_pe_for_each_dev(pe, edev) {
+			ret = fn(edev, flag);
+			if (ret) {
+				eeh_unlock();
+				return ret;
+			}
+		}
+	}
+
+	eeh_unlock();
+
+	return NULL;
+}
+
+/**
+ * __eeh_pe_get - Check the PE address
+ * @data: EEH PE
+ * @flag: EEH device
+ *
+ * For one particular PE, it can be identified by PE address
+ * or tranditional BDF address. BDF address is composed of
+ * Bus/Device/Function number. The extra data referred by flag
+ * indicates which type of address should be used.
+ */
+static void *__eeh_pe_get(void *data, void *flag)
+{
+	struct eeh_pe *pe = (struct eeh_pe *)data;
+	struct eeh_dev *edev = (struct eeh_dev *)flag;
+
+	/* Unexpected PHB PE */
+	if (pe->type & EEH_PE_PHB)
+		return NULL;
+
+	/* We prefer PE address */
+	if (edev->pe_config_addr &&
+	   (edev->pe_config_addr == pe->addr))
+		return pe;
+
+	/* Try BDF address */
+	if (edev->pe_config_addr &&
+	   (edev->config_addr == pe->config_addr))
+		return pe;
+
+	return NULL;
+}
+
+/**
+ * eeh_pe_get - Search PE based on the given address
+ * @edev: EEH device
+ *
+ * Search the corresponding PE based on the specified address which
+ * is included in the eeh device. The function is used to check if
+ * the associated PE has been created against the PE address. It's
+ * notable that the PE address has 2 format: traditional PE address
+ * which is composed of PCI bus/device/function number, or unified
+ * PE address.
+ */
+static struct eeh_pe *eeh_pe_get(struct eeh_dev *edev)
+{
+	struct eeh_pe *root = eeh_phb_pe_get(edev->phb);
+	struct eeh_pe *pe;
+
+	pe = eeh_pe_traverse(root, __eeh_pe_get, edev);
+
+	return pe;
+}
+
+/**
+ * eeh_pe_get_parent - Retrieve the parent PE
+ * @edev: EEH device
+ *
+ * The whole PEs existing in the system are organized as hierarchy
+ * tree. The function is used to retrieve the parent PE according
+ * to the parent EEH device.
+ */
+static struct eeh_pe *eeh_pe_get_parent(struct eeh_dev *edev)
+{
+	struct device_node *dn;
+	struct eeh_dev *parent;
+
+	/*
+	 * It might have the case for the indirect parent
+	 * EEH device already having associated PE, but
+	 * the direct parent EEH device doesn't have yet.
+	 */
+	dn = edev->dn->parent;
+	while (dn) {
+		/* We're poking out of PCI territory */
+		if (!PCI_DN(dn)) return NULL;
+
+		parent = of_node_to_eeh_dev(dn);
+		/* We're poking out of PCI territory */
+		if (!parent) return NULL;
+
+		if (parent->pe)
+			return parent->pe;
+
+		dn = dn->parent;
+	}
+
+	return NULL;
+}
+
+/**
+ * eeh_add_to_parent_pe - Add EEH device to parent PE
+ * @edev: EEH device
+ *
+ * Add EEH device to the parent PE. If the parent PE already
+ * exists, the PE type will be changed to EEH_PE_BUS. Otherwise,
+ * we have to create new PE to hold the EEH device and the new
+ * PE will be linked to its parent PE as well.
+ */
+int eeh_add_to_parent_pe(struct eeh_dev *edev)
+{
+	struct eeh_pe *pe, *parent;
+
+	eeh_lock();
+
+	/*
+	 * Search the PE has been existing or not according
+	 * to the PE address. If that has been existing, the
+	 * PE should be composed of PCI bus and its subordinate
+	 * components.
+	 */
+	pe = eeh_pe_get(edev);
+	if (pe && !(pe->type & EEH_PE_INVALID)) {
+		if (!edev->pe_config_addr) {
+			eeh_unlock();
+			pr_err("%s: PE with addr 0x%x already exists\n",
+				__func__, edev->config_addr);
+			return -EEXIST;
+		}
+
+		/* Mark the PE as type of PCI bus */
+		pe->type = EEH_PE_BUS;
+		edev->pe = pe;
+
+		/* Put the edev to PE */
+		list_add_tail(&edev->list, &pe->edevs);
+		eeh_unlock();
+		pr_debug("EEH: Add %s to Bus PE#%x\n",
+			edev->dn->full_name, pe->addr);
+
+		return 0;
+	} else if (pe && (pe->type & EEH_PE_INVALID)) {
+		list_add_tail(&edev->list, &pe->edevs);
+		edev->pe = pe;
+		/*
+		 * We're running to here because of PCI hotplug caused by
+		 * EEH recovery. We need clear EEH_PE_INVALID until the top.
+		 */
+		parent = pe;
+		while (parent) {
+			if (!(parent->type & EEH_PE_INVALID))
+				break;
+			parent->type &= ~EEH_PE_INVALID;
+			parent = parent->parent;
+		}
+		eeh_unlock();
+		pr_debug("EEH: Add %s to Device PE#%x, Parent PE#%x\n",
+			edev->dn->full_name, pe->addr, pe->parent->addr);
+
+		return 0;
+	}
+
+	/* Create a new EEH PE */
+	pe = eeh_pe_alloc(edev->phb, EEH_PE_DEVICE);
+	if (!pe) {
+		eeh_unlock();
+		pr_err("%s: out of memory!\n", __func__);
+		return -ENOMEM;
+	}
+	pe->addr	= edev->pe_config_addr;
+	pe->config_addr	= edev->config_addr;
+
+	/*
+	 * Put the new EEH PE into hierarchy tree. If the parent
+	 * can't be found, the newly created PE will be attached
+	 * to PHB directly. Otherwise, we have to associate the
+	 * PE with its parent.
+	 */
+	parent = eeh_pe_get_parent(edev);
+	if (!parent) {
+		parent = eeh_phb_pe_get(edev->phb);
+		if (!parent) {
+			eeh_unlock();
+			pr_err("%s: No PHB PE is found (PHB Domain=%d)\n",
+				__func__, edev->phb->global_number);
+			edev->pe = NULL;
+			kfree(pe);
+			return -EEXIST;
+		}
+	}
+	pe->parent = parent;
+
+	/*
+	 * Put the newly created PE into the child list and
+	 * link the EEH device accordingly.
+	 */
+	list_add_tail(&pe->child, &parent->child_list);
+	list_add_tail(&edev->list, &pe->edevs);
+	edev->pe = pe;
+	eeh_unlock();
+	pr_debug("EEH: Add %s to Device PE#%x, Parent PE#%x\n",
+		edev->dn->full_name, pe->addr, pe->parent->addr);
+
+	return 0;
+}
+
+/**
+ * eeh_rmv_from_parent_pe - Remove one EEH device from the associated PE
+ * @edev: EEH device
+ * @purge_pe: remove PE or not
+ *
+ * The PE hierarchy tree might be changed when doing PCI hotplug.
+ * Also, the PCI devices or buses could be removed from the system
+ * during EEH recovery. So we have to call the function remove the
+ * corresponding PE accordingly if necessary.
+ */
+int eeh_rmv_from_parent_pe(struct eeh_dev *edev, int purge_pe)
+{
+	struct eeh_pe *pe, *parent, *child;
+	int cnt;
+
+	if (!edev->pe) {
+		pr_warning("%s: No PE found for EEH device %s\n",
+			__func__, edev->dn->full_name);
+		return -EEXIST;
+	}
+
+	eeh_lock();
+
+	/* Remove the EEH device */
+	pe = edev->pe;
+	edev->pe = NULL;
+	list_del(&edev->list);
+
+	/*
+	 * Check if the parent PE includes any EEH devices.
+	 * If not, we should delete that. Also, we should
+	 * delete the parent PE if it doesn't have associated
+	 * child PEs and EEH devices.
+	 */
+	while (1) {
+		parent = pe->parent;
+		if (pe->type & EEH_PE_PHB)
+			break;
+
+		if (purge_pe) {
+			if (list_empty(&pe->edevs) &&
+			    list_empty(&pe->child_list)) {
+				list_del(&pe->child);
+				kfree(pe);
+			} else {
+				break;
+			}
+		} else {
+			if (list_empty(&pe->edevs)) {
+				cnt = 0;
+				list_for_each_entry(child, &pe->child_list, child) {
+					if (!(pe->type & EEH_PE_INVALID)) {
+						cnt++;
+						break;
+					}
+				}
+
+				if (!cnt)
+					pe->type |= EEH_PE_INVALID;
+				else
+					break;
+			}
+		}
+
+		pe = parent;
+	}
+
+	eeh_unlock();
+
+	return 0;
+}
+
+/**
+ * __eeh_pe_state_mark - Mark the state for the PE
+ * @data: EEH PE
+ * @flag: state
+ *
+ * The function is used to mark the indicated state for the given
+ * PE. Also, the associated PCI devices will be put into IO frozen
+ * state as well.
+ */
+static void *__eeh_pe_state_mark(void *data, void *flag)
+{
+	struct eeh_pe *pe = (struct eeh_pe *)data;
+	int state = *((int *)flag);
+	struct eeh_dev *tmp;
+	struct pci_dev *pdev;
+
+	/*
+	 * Mark the PE with the indicated state. Also,
+	 * the associated PCI device will be put into
+	 * I/O frozen state to avoid I/O accesses from
+	 * the PCI device driver.
+	 */
+	pe->state |= state;
+	eeh_pe_for_each_dev(pe, tmp) {
+		pdev = eeh_dev_to_pci_dev(tmp);
+		if (pdev)
+			pdev->error_state = pci_channel_io_frozen;
+	}
+
+	return NULL;
+}
+
+/**
+ * eeh_pe_state_mark - Mark specified state for PE and its associated device
+ * @pe: EEH PE
+ *
+ * EEH error affects the current PE and its child PEs. The function
+ * is used to mark appropriate state for the affected PEs and the
+ * associated devices.
+ */
+void eeh_pe_state_mark(struct eeh_pe *pe, int state)
+{
+	eeh_lock();
+	eeh_pe_traverse(pe, __eeh_pe_state_mark, &state);
+	eeh_unlock();
+}
+
+/**
+ * __eeh_pe_state_clear - Clear state for the PE
+ * @data: EEH PE
+ * @flag: state
+ *
+ * The function is used to clear the indicated state from the
+ * given PE. Besides, we also clear the check count of the PE
+ * as well.
+ */
+static void *__eeh_pe_state_clear(void *data, void *flag)
+{
+	struct eeh_pe *pe = (struct eeh_pe *)data;
+	int state = *((int *)flag);
+
+	pe->state &= ~state;
+	pe->check_count = 0;
+
+	return NULL;
+}
+
+/**
+ * eeh_pe_state_clear - Clear state for the PE and its children
+ * @pe: PE
+ * @state: state to be cleared
+ *
+ * When the PE and its children has been recovered from error,
+ * we need clear the error state for that. The function is used
+ * for the purpose.
+ */
+void eeh_pe_state_clear(struct eeh_pe *pe, int state)
+{
+	eeh_lock();
+	eeh_pe_traverse(pe, __eeh_pe_state_clear, &state);
+	eeh_unlock();
+}
+
+/**
+ * eeh_restore_one_device_bars - Restore the Base Address Registers for one device
+ * @data: EEH device
+ * @flag: Unused
+ *
+ * Loads the PCI configuration space base address registers,
+ * the expansion ROM base address, the latency timer, and etc.
+ * from the saved values in the device node.
+ */
+static void *eeh_restore_one_device_bars(void *data, void *flag)
+{
+	int i;
+	u32 cmd;
+	struct eeh_dev *edev = (struct eeh_dev *)data;
+	struct device_node *dn = eeh_dev_to_of_node(edev);
+
+	for (i = 4; i < 10; i++)
+		eeh_ops->write_config(dn, i*4, 4, edev->config_space[i]);
+	/* 12 == Expansion ROM Address */
+	eeh_ops->write_config(dn, 12*4, 4, edev->config_space[12]);
+
+#define BYTE_SWAP(OFF) (8*((OFF)/4)+3-(OFF))
+#define SAVED_BYTE(OFF) (((u8 *)(edev->config_space))[BYTE_SWAP(OFF)])
+
+	eeh_ops->write_config(dn, PCI_CACHE_LINE_SIZE, 1,
+		SAVED_BYTE(PCI_CACHE_LINE_SIZE));
+	eeh_ops->write_config(dn, PCI_LATENCY_TIMER, 1,
+		SAVED_BYTE(PCI_LATENCY_TIMER));
+
+	/* max latency, min grant, interrupt pin and line */
+	eeh_ops->write_config(dn, 15*4, 4, edev->config_space[15]);
+
+	/*
+	 * Restore PERR & SERR bits, some devices require it,
+	 * don't touch the other command bits
+	 */
+	eeh_ops->read_config(dn, PCI_COMMAND, 4, &cmd);
+	if (edev->config_space[1] & PCI_COMMAND_PARITY)
+		cmd |= PCI_COMMAND_PARITY;
+	else
+		cmd &= ~PCI_COMMAND_PARITY;
+	if (edev->config_space[1] & PCI_COMMAND_SERR)
+		cmd |= PCI_COMMAND_SERR;
+	else
+		cmd &= ~PCI_COMMAND_SERR;
+	eeh_ops->write_config(dn, PCI_COMMAND, 4, cmd);
+
+	return NULL;
+}
+
+/**
+ * eeh_pe_restore_bars - Restore the PCI config space info
+ * @pe: EEH PE
+ *
+ * This routine performs a recursive walk to the children
+ * of this device as well.
+ */
+void eeh_pe_restore_bars(struct eeh_pe *pe)
+{
+	/*
+	 * We needn't take the EEH lock since eeh_pe_dev_traverse()
+	 * will take that.
+	 */
+	eeh_pe_dev_traverse(pe, eeh_restore_one_device_bars, NULL);
+}
+
+/**
+ * eeh_pe_bus_get - Retrieve PCI bus according to the given PE
+ * @pe: EEH PE
+ *
+ * Retrieve the PCI bus according to the given PE. Basically,
+ * there're 3 types of PEs: PHB/Bus/Device. For PHB PE, the
+ * primary PCI bus will be retrieved. The parent bus will be
+ * returned for BUS PE. However, we don't have associated PCI
+ * bus for DEVICE PE.
+ */
+struct pci_bus *eeh_pe_bus_get(struct eeh_pe *pe)
+{
+	struct pci_bus *bus = NULL;
+	struct eeh_dev *edev;
+	struct pci_dev *pdev;
+
+	eeh_lock();
+
+	if (pe->type & EEH_PE_PHB) {
+		bus = pe->phb->bus;
+	} else if (pe->type & EEH_PE_BUS) {
+		edev = list_first_entry(&pe->edevs, struct eeh_dev, list);
+		pdev = eeh_dev_to_pci_dev(edev);
+		if (pdev)
+			bus = pdev->bus;
+	}
+
+	eeh_unlock();
+
+	return bus;
+}
diff --git a/arch/powerpc/platforms/pseries/eeh_pseries.c b/arch/powerpc/platforms/pseries/eeh_pseries.c
index c33360ec..19506f9 100644
--- a/arch/powerpc/platforms/pseries/eeh_pseries.c
+++ b/arch/powerpc/platforms/pseries/eeh_pseries.c
@@ -129,27 +129,117 @@ static int pseries_eeh_init(void)
 		eeh_error_buf_size = RTAS_ERROR_LOG_MAX;
 	}
 
+	/* Set EEH probe mode */
+	eeh_probe_mode_set(EEH_PROBE_MODE_DEVTREE);
+
 	return 0;
 }
 
 /**
+ * pseries_eeh_of_probe - EEH probe on the given device
+ * @dn: OF node
+ * @flag: Unused
+ *
+ * When EEH module is installed during system boot, all PCI devices
+ * are checked one by one to see if it supports EEH. The function
+ * is introduced for the purpose.
+ */
+static void *pseries_eeh_of_probe(struct device_node *dn, void *flag)
+{
+	struct eeh_dev *edev;
+	struct eeh_pe pe;
+	const u32 *class_code, *vendor_id, *device_id;
+	const u32 *regs;
+	int enable = 0;
+	int ret;
+
+	/* Retrieve OF node and eeh device */
+	edev = of_node_to_eeh_dev(dn);
+	if (!of_device_is_available(dn))
+		return NULL;
+
+	/* Retrieve class/vendor/device IDs */
+	class_code = of_get_property(dn, "class-code", NULL);
+	vendor_id  = of_get_property(dn, "vendor-id", NULL);
+	device_id  = of_get_property(dn, "device-id", NULL);
+
+	/* Skip for bad OF node or PCI-ISA bridge */
+	if (!class_code || !vendor_id || !device_id)
+		return NULL;
+	if (dn->type && !strcmp(dn->type, "isa"))
+		return NULL;
+
+	/* Update class code and mode of eeh device */
+	edev->class_code = *class_code;
+	edev->mode = 0;
+
+	/* Retrieve the device address */
+	regs = of_get_property(dn, "reg", NULL);
+	if (!regs) {
+		pr_warning("%s: OF node property %s::reg not found\n",
+			__func__, dn->full_name);
+		return NULL;
+	}
+
+	/* Initialize the fake PE */
+	memset(&pe, 0, sizeof(struct eeh_pe));
+	pe.phb = edev->phb;
+	pe.config_addr = regs[0];
+
+	/* Enable EEH on the device */
+	ret = eeh_ops->set_option(&pe, EEH_OPT_ENABLE);
+	if (!ret) {
+		edev->config_addr = regs[0];
+		/* Retrieve PE address */
+		edev->pe_config_addr = eeh_ops->get_pe_addr(&pe);
+		pe.addr = edev->pe_config_addr;
+
+		/* Some older systems (Power4) allow the ibm,set-eeh-option
+		 * call to succeed even on nodes where EEH is not supported.
+		 * Verify support explicitly.
+		 */
+		ret = eeh_ops->get_state(&pe, NULL);
+		if (ret > 0 && ret != EEH_STATE_NOT_SUPPORT)
+			enable = 1;
+
+		if (enable) {
+			eeh_subsystem_enabled = 1;
+			eeh_add_to_parent_pe(edev);
+
+			pr_debug("%s: EEH enabled on %s PHB#%d-PE#%x, config addr#%x\n",
+				__func__, dn->full_name, pe.phb->global_number,
+				pe.addr, pe.config_addr);
+		} else if (dn->parent && of_node_to_eeh_dev(dn->parent) &&
+			   (of_node_to_eeh_dev(dn->parent))->pe) {
+			/* This device doesn't support EEH, but it may have an
+			 * EEH parent, in which case we mark it as supported.
+			 */
+			edev->config_addr = of_node_to_eeh_dev(dn->parent)->config_addr;
+			edev->pe_config_addr = of_node_to_eeh_dev(dn->parent)->pe_config_addr;
+			eeh_add_to_parent_pe(edev);
+		}
+	}
+
+	/* Save memory bars */
+	eeh_save_bars(edev);
+
+	return NULL;
+}
+
+/**
  * pseries_eeh_set_option - Initialize EEH or MMIO/DMA reenable
- * @dn: device node
+ * @pe: EEH PE
  * @option: operation to be issued
  *
  * The function is used to control the EEH functionality globally.
  * Currently, following options are support according to PAPR:
  * Enable EEH, Disable EEH, Enable MMIO and Enable DMA
  */
-static int pseries_eeh_set_option(struct device_node *dn, int option)
+static int pseries_eeh_set_option(struct eeh_pe *pe, int option)
 {
 	int ret = 0;
-	struct eeh_dev *edev;
-	const u32 *reg;
 	int config_addr;
 
-	edev = of_node_to_eeh_dev(dn);
-
 	/*
 	 * When we're enabling or disabling EEH functioality on
 	 * the particular PE, the PE config address is possibly
@@ -159,15 +249,11 @@ static int pseries_eeh_set_option(struct device_node *dn, int option)
 	switch (option) {
 	case EEH_OPT_DISABLE:
 	case EEH_OPT_ENABLE:
-		reg = of_get_property(dn, "reg", NULL);
-		config_addr = reg[0];
-		break;
-
 	case EEH_OPT_THAW_MMIO:
 	case EEH_OPT_THAW_DMA:
-		config_addr = edev->config_addr;
-		if (edev->pe_config_addr)
-			config_addr = edev->pe_config_addr;
+		config_addr = pe->config_addr;
+		if (pe->addr)
+			config_addr = pe->addr;
 		break;
 
 	default:
@@ -177,15 +263,15 @@ static int pseries_eeh_set_option(struct device_node *dn, int option)
 	}
 
 	ret = rtas_call(ibm_set_eeh_option, 4, 1, NULL,
-			config_addr, BUID_HI(edev->phb->buid),
-			BUID_LO(edev->phb->buid), option);
+			config_addr, BUID_HI(pe->phb->buid),
+			BUID_LO(pe->phb->buid), option);
 
 	return ret;
 }
 
 /**
  * pseries_eeh_get_pe_addr - Retrieve PE address
- * @dn: device node
+ * @pe: EEH PE
  *
  * Retrieve the assocated PE address. Actually, there're 2 RTAS
  * function calls dedicated for the purpose. We need implement
@@ -196,14 +282,11 @@ static int pseries_eeh_set_option(struct device_node *dn, int option)
  * It's notable that zero'ed return value means invalid PE config
  * address.
  */
-static int pseries_eeh_get_pe_addr(struct device_node *dn)
+static int pseries_eeh_get_pe_addr(struct eeh_pe *pe)
 {
-	struct eeh_dev *edev;
 	int ret = 0;
 	int rets[3];
 
-	edev = of_node_to_eeh_dev(dn);
-
 	if (ibm_get_config_addr_info2 != RTAS_UNKNOWN_SERVICE) {
 		/*
 		 * First of all, we need to make sure there has one PE
@@ -211,18 +294,18 @@ static int pseries_eeh_get_pe_addr(struct device_node *dn)
 		 * meaningless.
 		 */
 		ret = rtas_call(ibm_get_config_addr_info2, 4, 2, rets,
-				edev->config_addr, BUID_HI(edev->phb->buid),
-				BUID_LO(edev->phb->buid), 1);
+				pe->config_addr, BUID_HI(pe->phb->buid),
+				BUID_LO(pe->phb->buid), 1);
 		if (ret || (rets[0] == 0))
 			return 0;
 
 		/* Retrieve the associated PE config address */
 		ret = rtas_call(ibm_get_config_addr_info2, 4, 2, rets,
-				edev->config_addr, BUID_HI(edev->phb->buid),
-				BUID_LO(edev->phb->buid), 0);
+				pe->config_addr, BUID_HI(pe->phb->buid),
+				BUID_LO(pe->phb->buid), 0);
 		if (ret) {
-			pr_warning("%s: Failed to get PE address for %s\n",
-				__func__, dn->full_name);
+			pr_warning("%s: Failed to get address for PHB#%d-PE#%x\n",
+				__func__, pe->phb->global_number, pe->config_addr);
 			return 0;
 		}
 
@@ -231,11 +314,11 @@ static int pseries_eeh_get_pe_addr(struct device_node *dn)
 
 	if (ibm_get_config_addr_info != RTAS_UNKNOWN_SERVICE) {
 		ret = rtas_call(ibm_get_config_addr_info, 4, 2, rets,
-				edev->config_addr, BUID_HI(edev->phb->buid),
-				BUID_LO(edev->phb->buid), 0);
+				pe->config_addr, BUID_HI(pe->phb->buid),
+				BUID_LO(pe->phb->buid), 0);
 		if (ret) {
-			pr_warning("%s: Failed to get PE address for %s\n",
-				__func__, dn->full_name);
+			pr_warning("%s: Failed to get address for PHB#%d-PE#%x\n",
+				__func__, pe->phb->global_number, pe->config_addr);
 			return 0;
 		}
 
@@ -247,7 +330,7 @@ static int pseries_eeh_get_pe_addr(struct device_node *dn)
 
 /**
  * pseries_eeh_get_state - Retrieve PE state
- * @dn: PE associated device node
+ * @pe: EEH PE
  * @state: return value
  *
  * Retrieve the state of the specified PE. On RTAS compliant
@@ -258,30 +341,28 @@ static int pseries_eeh_get_pe_addr(struct device_node *dn)
  * RTAS calls for the purpose, we need to try the new one and back
  * to the old one if the new one couldn't work properly.
  */
-static int pseries_eeh_get_state(struct device_node *dn, int *state)
+static int pseries_eeh_get_state(struct eeh_pe *pe, int *state)
 {
-	struct eeh_dev *edev;
 	int config_addr;
 	int ret;
 	int rets[4];
 	int result;
 
 	/* Figure out PE config address if possible */
-	edev = of_node_to_eeh_dev(dn);
-	config_addr = edev->config_addr;
-	if (edev->pe_config_addr)
-		config_addr = edev->pe_config_addr;
+	config_addr = pe->config_addr;
+	if (pe->addr)
+		config_addr = pe->addr;
 
 	if (ibm_read_slot_reset_state2 != RTAS_UNKNOWN_SERVICE) {
 		ret = rtas_call(ibm_read_slot_reset_state2, 3, 4, rets,
-				config_addr, BUID_HI(edev->phb->buid),
-				BUID_LO(edev->phb->buid));
+				config_addr, BUID_HI(pe->phb->buid),
+				BUID_LO(pe->phb->buid));
 	} else if (ibm_read_slot_reset_state != RTAS_UNKNOWN_SERVICE) {
 		/* Fake PE unavailable info */
 		rets[2] = 0;
 		ret = rtas_call(ibm_read_slot_reset_state, 3, 3, rets,
-				config_addr, BUID_HI(edev->phb->buid),
-				BUID_LO(edev->phb->buid));
+				config_addr, BUID_HI(pe->phb->buid),
+				BUID_LO(pe->phb->buid));
 	} else {
 		return EEH_STATE_NOT_SUPPORT;
 	}
@@ -333,34 +414,32 @@ static int pseries_eeh_get_state(struct device_node *dn, int *state)
 
 /**
  * pseries_eeh_reset - Reset the specified PE
- * @dn: PE associated device node
+ * @pe: EEH PE
  * @option: reset option
  *
  * Reset the specified PE
  */
-static int pseries_eeh_reset(struct device_node *dn, int option)
+static int pseries_eeh_reset(struct eeh_pe *pe, int option)
 {
-	struct eeh_dev *edev;
 	int config_addr;
 	int ret;
 
 	/* Figure out PE address */
-	edev = of_node_to_eeh_dev(dn);
-	config_addr = edev->config_addr;
-	if (edev->pe_config_addr)
-		config_addr = edev->pe_config_addr;
+	config_addr = pe->config_addr;
+	if (pe->addr)
+		config_addr = pe->addr;
 
 	/* Reset PE through RTAS call */
 	ret = rtas_call(ibm_set_slot_reset, 4, 1, NULL,
-			config_addr, BUID_HI(edev->phb->buid),
-			BUID_LO(edev->phb->buid), option);
+			config_addr, BUID_HI(pe->phb->buid),
+			BUID_LO(pe->phb->buid), option);
 
 	/* If fundamental-reset not supported, try hot-reset */
 	if (option == EEH_RESET_FUNDAMENTAL &&
 	    ret == -8) {
 		ret = rtas_call(ibm_set_slot_reset, 4, 1, NULL,
-				config_addr, BUID_HI(edev->phb->buid),
-				BUID_LO(edev->phb->buid), EEH_RESET_HOT);
+				config_addr, BUID_HI(pe->phb->buid),
+				BUID_LO(pe->phb->buid), EEH_RESET_HOT);
 	}
 
 	return ret;
@@ -368,13 +447,13 @@ static int pseries_eeh_reset(struct device_node *dn, int option)
 
 /**
  * pseries_eeh_wait_state - Wait for PE state
- * @dn: PE associated device node
+ * @pe: EEH PE
  * @max_wait: maximal period in microsecond
  *
  * Wait for the state of associated PE. It might take some time
  * to retrieve the PE's state.
  */
-static int pseries_eeh_wait_state(struct device_node *dn, int max_wait)
+static int pseries_eeh_wait_state(struct eeh_pe *pe, int max_wait)
 {
 	int ret;
 	int mwait;
@@ -391,7 +470,7 @@ static int pseries_eeh_wait_state(struct device_node *dn, int max_wait)
 #define EEH_STATE_MAX_WAIT_TIME	(300 * 1000)
 
 	while (1) {
-		ret = pseries_eeh_get_state(dn, &mwait);
+		ret = pseries_eeh_get_state(pe, &mwait);
 
 		/*
 		 * If the PE's state is temporarily unavailable,
@@ -426,7 +505,7 @@ static int pseries_eeh_wait_state(struct device_node *dn, int max_wait)
 
 /**
  * pseries_eeh_get_log - Retrieve error log
- * @dn: device node
+ * @pe: EEH PE
  * @severity: temporary or permanent error log
  * @drv_log: driver log to be combined with retrieved error log
  * @len: length of driver log
@@ -435,24 +514,22 @@ static int pseries_eeh_wait_state(struct device_node *dn, int max_wait)
  * Actually, the error will be retrieved through the dedicated
  * RTAS call.
  */
-static int pseries_eeh_get_log(struct device_node *dn, int severity, char *drv_log, unsigned long len)
+static int pseries_eeh_get_log(struct eeh_pe *pe, int severity, char *drv_log, unsigned long len)
 {
-	struct eeh_dev *edev;
 	int config_addr;
 	unsigned long flags;
 	int ret;
 
-	edev = of_node_to_eeh_dev(dn);
 	spin_lock_irqsave(&slot_errbuf_lock, flags);
 	memset(slot_errbuf, 0, eeh_error_buf_size);
 
 	/* Figure out the PE address */
-	config_addr = edev->config_addr;
-	if (edev->pe_config_addr)
-		config_addr = edev->pe_config_addr;
+	config_addr = pe->config_addr;
+	if (pe->addr)
+		config_addr = pe->addr;
 
 	ret = rtas_call(ibm_slot_error_detail, 8, 1, NULL, config_addr,
-			BUID_HI(edev->phb->buid), BUID_LO(edev->phb->buid),
+			BUID_HI(pe->phb->buid), BUID_LO(pe->phb->buid),
 			virt_to_phys(drv_log), len,
 			virt_to_phys(slot_errbuf), eeh_error_buf_size,
 			severity);
@@ -465,40 +542,38 @@ static int pseries_eeh_get_log(struct device_node *dn, int severity, char *drv_l
 
 /**
  * pseries_eeh_configure_bridge - Configure PCI bridges in the indicated PE
- * @dn: PE associated device node
+ * @pe: EEH PE
  *
  * The function will be called to reconfigure the bridges included
  * in the specified PE so that the mulfunctional PE would be recovered
  * again.
  */
-static int pseries_eeh_configure_bridge(struct device_node *dn)
+static int pseries_eeh_configure_bridge(struct eeh_pe *pe)
 {
-	struct eeh_dev *edev;
 	int config_addr;
 	int ret;
 
 	/* Figure out the PE address */
-	edev = of_node_to_eeh_dev(dn);
-	config_addr = edev->config_addr;
-	if (edev->pe_config_addr)
-		config_addr = edev->pe_config_addr;
+	config_addr = pe->config_addr;
+	if (pe->addr)
+		config_addr = pe->addr;
 
 	/* Use new configure-pe function, if supported */
 	if (ibm_configure_pe != RTAS_UNKNOWN_SERVICE) {
 		ret = rtas_call(ibm_configure_pe, 3, 1, NULL,
-				config_addr, BUID_HI(edev->phb->buid),
-				BUID_LO(edev->phb->buid));
+				config_addr, BUID_HI(pe->phb->buid),
+				BUID_LO(pe->phb->buid));
 	} else if (ibm_configure_bridge != RTAS_UNKNOWN_SERVICE) {
 		ret = rtas_call(ibm_configure_bridge, 3, 1, NULL,
-				config_addr, BUID_HI(edev->phb->buid),
-				BUID_LO(edev->phb->buid));
+				config_addr, BUID_HI(pe->phb->buid),
+				BUID_LO(pe->phb->buid));
 	} else {
 		return -EFAULT;
 	}
 
 	if (ret)
-		pr_warning("%s: Unable to configure bridge %d for %s\n",
-			__func__, ret, dn->full_name);
+		pr_warning("%s: Unable to configure bridge PHB#%d-PE#%x (%d)\n",
+			__func__, pe->phb->global_number, pe->addr, ret);
 
 	return ret;
 }
@@ -542,6 +617,8 @@ static int pseries_eeh_write_config(struct device_node *dn, int where, int size,
 static struct eeh_ops pseries_eeh_ops = {
 	.name			= "pseries",
 	.init			= pseries_eeh_init,
+	.of_probe		= pseries_eeh_of_probe,
+	.dev_probe		= NULL,
 	.set_option		= pseries_eeh_set_option,
 	.get_pe_addr		= pseries_eeh_get_pe_addr,
 	.get_state		= pseries_eeh_get_state,
@@ -559,7 +636,21 @@ static struct eeh_ops pseries_eeh_ops = {
  * EEH initialization on pseries platform. This function should be
  * called before any EEH related functions.
  */
-int __init eeh_pseries_init(void)
+static int __init eeh_pseries_init(void)
 {
-	return eeh_ops_register(&pseries_eeh_ops);
+	int ret = -EINVAL;
+
+	if (!machine_is(pseries))
+		return ret;
+
+	ret = eeh_ops_register(&pseries_eeh_ops);
+	if (!ret)
+		pr_info("EEH: pSeries platform initialized\n");
+	else
+		pr_info("EEH: pSeries platform initialization failure (%d)\n",
+			ret);
+
+	return ret;
 }
+
+early_initcall(eeh_pseries_init);
diff --git a/arch/powerpc/platforms/pseries/eeh_sysfs.c b/arch/powerpc/platforms/pseries/eeh_sysfs.c
index 243b351..d377083 100644
--- a/arch/powerpc/platforms/pseries/eeh_sysfs.c
+++ b/arch/powerpc/platforms/pseries/eeh_sysfs.c
@@ -53,9 +53,6 @@ static DEVICE_ATTR(_name, S_IRUGO, eeh_show_##_name, NULL);
 EEH_SHOW_ATTR(eeh_mode,            mode,            "0x%x");
 EEH_SHOW_ATTR(eeh_config_addr,     config_addr,     "0x%x");
 EEH_SHOW_ATTR(eeh_pe_config_addr,  pe_config_addr,  "0x%x");
-EEH_SHOW_ATTR(eeh_check_count,     check_count,     "%d"  );
-EEH_SHOW_ATTR(eeh_freeze_count,    freeze_count,    "%d"  );
-EEH_SHOW_ATTR(eeh_false_positives, false_positives, "%d"  );
 
 void eeh_sysfs_add_device(struct pci_dev *pdev)
 {
@@ -64,9 +61,6 @@ void eeh_sysfs_add_device(struct pci_dev *pdev)
 	rc += device_create_file(&pdev->dev, &dev_attr_eeh_mode);
 	rc += device_create_file(&pdev->dev, &dev_attr_eeh_config_addr);
 	rc += device_create_file(&pdev->dev, &dev_attr_eeh_pe_config_addr);
-	rc += device_create_file(&pdev->dev, &dev_attr_eeh_check_count);
-	rc += device_create_file(&pdev->dev, &dev_attr_eeh_false_positives);
-	rc += device_create_file(&pdev->dev, &dev_attr_eeh_freeze_count);
 
 	if (rc)
 		printk(KERN_WARNING "EEH: Unable to create sysfs entries\n");
@@ -77,8 +71,5 @@ void eeh_sysfs_remove_device(struct pci_dev *pdev)
 	device_remove_file(&pdev->dev, &dev_attr_eeh_mode);
 	device_remove_file(&pdev->dev, &dev_attr_eeh_config_addr);
 	device_remove_file(&pdev->dev, &dev_attr_eeh_pe_config_addr);
-	device_remove_file(&pdev->dev, &dev_attr_eeh_check_count);
-	device_remove_file(&pdev->dev, &dev_attr_eeh_false_positives);
-	device_remove_file(&pdev->dev, &dev_attr_eeh_freeze_count);
 }
 
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
index bca220f..6153eea 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -28,6 +28,7 @@
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <linux/mm.h>
+#include <linux/memblock.h>
 #include <linux/spinlock.h>
 #include <linux/sched.h>	/* for show_stack */
 #include <linux/string.h>
@@ -41,7 +42,6 @@
 #include <asm/iommu.h>
 #include <asm/pci-bridge.h>
 #include <asm/machdep.h>
-#include <asm/abs_addr.h>
 #include <asm/pSeries_reconfig.h>
 #include <asm/firmware.h>
 #include <asm/tce.h>
@@ -99,7 +99,7 @@ static int tce_build_pSeries(struct iommu_table *tbl, long index,
 
 	while (npages--) {
 		/* can't move this out since we might cross MEMBLOCK boundary */
-		rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT;
+		rpn = __pa(uaddr) >> TCE_SHIFT;
 		*tcep = proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT;
 
 		uaddr += TCE_PAGE_SIZE;
@@ -148,7 +148,7 @@ static int tce_build_pSeriesLP(struct iommu_table *tbl, long tcenum,
 	int ret = 0;
 	long tcenum_start = tcenum, npages_start = npages;
 
-	rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT;
+	rpn = __pa(uaddr) >> TCE_SHIFT;
 	proto_tce = TCE_PCI_READ;
 	if (direction != DMA_TO_DEVICE)
 		proto_tce |= TCE_PCI_WRITE;
@@ -217,7 +217,7 @@ static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
 		__get_cpu_var(tce_page) = tcep;
 	}
 
-	rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT;
+	rpn = __pa(uaddr) >> TCE_SHIFT;
 	proto_tce = TCE_PCI_READ;
 	if (direction != DMA_TO_DEVICE)
 		proto_tce |= TCE_PCI_WRITE;
@@ -237,7 +237,7 @@ static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
 
 		rc = plpar_tce_put_indirect((u64)tbl->it_index,
 					    (u64)tcenum << 12,
-					    (u64)virt_to_abs(tcep),
+					    (u64)__pa(tcep),
 					    limit);
 
 		npages -= limit;
@@ -441,7 +441,7 @@ static int tce_setrange_multi_pSeriesLP(unsigned long start_pfn,
 
 		rc = plpar_tce_put_indirect(liobn,
 					    dma_offset,
-					    (u64)virt_to_abs(tcep),
+					    (u64)__pa(tcep),
 					    limit);
 
 		num_tce -= limit;
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
index 5f3ef87..0da39fe 100644
--- a/arch/powerpc/platforms/pseries/lpar.c
+++ b/arch/powerpc/platforms/pseries/lpar.c
@@ -31,7 +31,6 @@
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/machdep.h>
-#include <asm/abs_addr.h>
 #include <asm/mmu_context.h>
 #include <asm/iommu.h>
 #include <asm/tlbflush.h>
@@ -108,9 +107,9 @@ void vpa_init(int cpu)
 }
 
 static long pSeries_lpar_hpte_insert(unsigned long hpte_group,
- 			      unsigned long va, unsigned long pa,
- 			      unsigned long rflags, unsigned long vflags,
-			      int psize, int ssize)
+				     unsigned long vpn, unsigned long pa,
+				     unsigned long rflags, unsigned long vflags,
+				     int psize, int ssize)
 {
 	unsigned long lpar_rc;
 	unsigned long flags;
@@ -118,11 +117,11 @@ static long pSeries_lpar_hpte_insert(unsigned long hpte_group,
 	unsigned long hpte_v, hpte_r;
 
 	if (!(vflags & HPTE_V_BOLTED))
-		pr_devel("hpte_insert(group=%lx, va=%016lx, pa=%016lx, "
-			 "rflags=%lx, vflags=%lx, psize=%d)\n",
-			 hpte_group, va, pa, rflags, vflags, psize);
+		pr_devel("hpte_insert(group=%lx, vpn=%016lx, "
+			 "pa=%016lx, rflags=%lx, vflags=%lx, psize=%d)\n",
+			 hpte_group, vpn,  pa, rflags, vflags, psize);
 
-	hpte_v = hpte_encode_v(va, psize, ssize) | vflags | HPTE_V_VALID;
+	hpte_v = hpte_encode_v(vpn, psize, ssize) | vflags | HPTE_V_VALID;
 	hpte_r = hpte_encode_r(pa, psize) | rflags;
 
 	if (!(vflags & HPTE_V_BOLTED))
@@ -227,22 +226,6 @@ static void pSeries_lpar_hptab_clear(void)
 }
 
 /*
- * This computes the AVPN and B fields of the first dword of a HPTE,
- * for use when we want to match an existing PTE.  The bottom 7 bits
- * of the returned value are zero.
- */
-static inline unsigned long hpte_encode_avpn(unsigned long va, int psize,
-					     int ssize)
-{
-	unsigned long v;
-
-	v = (va >> 23) & ~(mmu_psize_defs[psize].avpnm);
-	v <<= HPTE_V_AVPN_SHIFT;
-	v |= ((unsigned long) ssize) << HPTE_V_SSIZE_SHIFT;
-	return v;
-}
-
-/*
  * NOTE: for updatepp ops we are fortunate that the linux "newpp" bits and
  * the low 3 bits of flags happen to line up.  So no transform is needed.
  * We can probably optimize here and assume the high bits of newpp are
@@ -250,14 +233,14 @@ static inline unsigned long hpte_encode_avpn(unsigned long va, int psize,
  */
 static long pSeries_lpar_hpte_updatepp(unsigned long slot,
 				       unsigned long newpp,
-				       unsigned long va,
+				       unsigned long vpn,
 				       int psize, int ssize, int local)
 {
 	unsigned long lpar_rc;
 	unsigned long flags = (newpp & 7) | H_AVPN;
 	unsigned long want_v;
 
-	want_v = hpte_encode_avpn(va, psize, ssize);
+	want_v = hpte_encode_avpn(vpn, psize, ssize);
 
 	pr_devel("    update: avpnv=%016lx, hash=%016lx, f=%lx, psize: %d ...",
 		 want_v, slot, flags, psize);
@@ -295,15 +278,15 @@ static unsigned long pSeries_lpar_hpte_getword0(unsigned long slot)
 	return dword0;
 }
 
-static long pSeries_lpar_hpte_find(unsigned long va, int psize, int ssize)
+static long pSeries_lpar_hpte_find(unsigned long vpn, int psize, int ssize)
 {
 	unsigned long hash;
 	unsigned long i;
 	long slot;
 	unsigned long want_v, hpte_v;
 
-	hash = hpt_hash(va, mmu_psize_defs[psize].shift, ssize);
-	want_v = hpte_encode_avpn(va, psize, ssize);
+	hash = hpt_hash(vpn, mmu_psize_defs[psize].shift, ssize);
+	want_v = hpte_encode_avpn(vpn, psize, ssize);
 
 	/* Bolted entries are always in the primary group */
 	slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
@@ -323,12 +306,13 @@ static void pSeries_lpar_hpte_updateboltedpp(unsigned long newpp,
 					     unsigned long ea,
 					     int psize, int ssize)
 {
-	unsigned long lpar_rc, slot, vsid, va, flags;
+	unsigned long vpn;
+	unsigned long lpar_rc, slot, vsid, flags;
 
 	vsid = get_kernel_vsid(ea, ssize);
-	va = hpt_va(ea, vsid, ssize);
+	vpn = hpt_vpn(ea, vsid, ssize);
 
-	slot = pSeries_lpar_hpte_find(va, psize, ssize);
+	slot = pSeries_lpar_hpte_find(vpn, psize, ssize);
 	BUG_ON(slot == -1);
 
 	flags = newpp & 7;
@@ -337,17 +321,17 @@ static void pSeries_lpar_hpte_updateboltedpp(unsigned long newpp,
 	BUG_ON(lpar_rc != H_SUCCESS);
 }
 
-static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va,
+static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long vpn,
 					 int psize, int ssize, int local)
 {
 	unsigned long want_v;
 	unsigned long lpar_rc;
 	unsigned long dummy1, dummy2;
 
-	pr_devel("    inval : slot=%lx, va=%016lx, psize: %d, local: %d\n",
-		 slot, va, psize, local);
+	pr_devel("    inval : slot=%lx, vpn=%016lx, psize: %d, local: %d\n",
+		 slot, vpn, psize, local);
 
-	want_v = hpte_encode_avpn(va, psize, ssize);
+	want_v = hpte_encode_avpn(vpn, psize, ssize);
 	lpar_rc = plpar_pte_remove(H_AVPN, slot, want_v, &dummy1, &dummy2);
 	if (lpar_rc == H_NOT_FOUND)
 		return;
@@ -358,15 +342,16 @@ static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va,
 static void pSeries_lpar_hpte_removebolted(unsigned long ea,
 					   int psize, int ssize)
 {
-	unsigned long slot, vsid, va;
+	unsigned long vpn;
+	unsigned long slot, vsid;
 
 	vsid = get_kernel_vsid(ea, ssize);
-	va = hpt_va(ea, vsid, ssize);
+	vpn = hpt_vpn(ea, vsid, ssize);
 
-	slot = pSeries_lpar_hpte_find(va, psize, ssize);
+	slot = pSeries_lpar_hpte_find(vpn, psize, ssize);
 	BUG_ON(slot == -1);
 
-	pSeries_lpar_hpte_invalidate(slot, va, psize, ssize, 0);
+	pSeries_lpar_hpte_invalidate(slot, vpn, psize, ssize, 0);
 }
 
 /* Flag bits for H_BULK_REMOVE */
@@ -382,12 +367,12 @@ static void pSeries_lpar_hpte_removebolted(unsigned long ea,
  */
 static void pSeries_lpar_flush_hash_range(unsigned long number, int local)
 {
+	unsigned long vpn;
 	unsigned long i, pix, rc;
 	unsigned long flags = 0;
 	struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch);
 	int lock_tlbie = !mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE);
 	unsigned long param[9];
-	unsigned long va;
 	unsigned long hash, index, shift, hidx, slot;
 	real_pte_t pte;
 	int psize, ssize;
@@ -399,21 +384,21 @@ static void pSeries_lpar_flush_hash_range(unsigned long number, int local)
 	ssize = batch->ssize;
 	pix = 0;
 	for (i = 0; i < number; i++) {
-		va = batch->vaddr[i];
+		vpn = batch->vpn[i];
 		pte = batch->pte[i];
-		pte_iterate_hashed_subpages(pte, psize, va, index, shift) {
-			hash = hpt_hash(va, shift, ssize);
+		pte_iterate_hashed_subpages(pte, psize, vpn, index, shift) {
+			hash = hpt_hash(vpn, shift, ssize);
 			hidx = __rpte_to_hidx(pte, index);
 			if (hidx & _PTEIDX_SECONDARY)
 				hash = ~hash;
 			slot = (hash & htab_hash_mask) * HPTES_PER_GROUP;
 			slot += hidx & _PTEIDX_GROUP_IX;
 			if (!firmware_has_feature(FW_FEATURE_BULK_REMOVE)) {
-				pSeries_lpar_hpte_invalidate(slot, va, psize,
+				pSeries_lpar_hpte_invalidate(slot, vpn, psize,
 							     ssize, local);
 			} else {
 				param[pix] = HBR_REQUEST | HBR_AVPN | slot;
-				param[pix+1] = hpte_encode_avpn(va, psize,
+				param[pix+1] = hpte_encode_avpn(vpn, psize,
 								ssize);
 				pix += 2;
 				if (pix == 8) {
diff --git a/arch/powerpc/platforms/pseries/msi.c b/arch/powerpc/platforms/pseries/msi.c
index 109fdb7..d19f497 100644
--- a/arch/powerpc/platforms/pseries/msi.c
+++ b/arch/powerpc/platforms/pseries/msi.c
@@ -210,6 +210,7 @@ static struct device_node *find_pe_total_msi(struct pci_dev *dev, int *total)
 static struct device_node *find_pe_dn(struct pci_dev *dev, int *total)
 {
 	struct device_node *dn;
+	struct eeh_dev *edev;
 
 	/* Found our PE and assume 8 at that point. */
 
@@ -217,7 +218,10 @@ static struct device_node *find_pe_dn(struct pci_dev *dev, int *total)
 	if (!dn)
 		return NULL;
 
-	dn = eeh_find_device_pe(dn);
+	/* Get the top level device in the PE */
+	edev = of_node_to_eeh_dev(dn);
+	edev = list_first_entry(&edev->pe->edevs, struct eeh_dev, list);
+	dn = eeh_dev_to_of_node(edev);
 	if (!dn)
 		return NULL;
 
@@ -387,12 +391,13 @@ static int check_msix_entries(struct pci_dev *pdev)
 	return 0;
 }
 
-static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
+static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec_in, int type)
 {
 	struct pci_dn *pdn;
 	int hwirq, virq, i, rc;
 	struct msi_desc *entry;
 	struct msi_msg msg;
+	int nvec = nvec_in;
 
 	pdn = get_pdn(pdev);
 	if (!pdn)
@@ -402,10 +407,23 @@ static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
 		return -EINVAL;
 
 	/*
+	 * Firmware currently refuse any non power of two allocation
+	 * so we round up if the quota will allow it.
+	 */
+	if (type == PCI_CAP_ID_MSIX) {
+		int m = roundup_pow_of_two(nvec);
+		int quota = msi_quota_for_device(pdev, m);
+
+		if (quota >= m)
+			nvec = m;
+	}
+
+	/*
 	 * Try the new more explicit firmware interface, if that fails fall
 	 * back to the old interface. The old interface is known to never
 	 * return MSI-Xs.
 	 */
+again:
 	if (type == PCI_CAP_ID_MSI) {
 		rc = rtas_change_msi(pdn, RTAS_CHANGE_MSI_FN, nvec);
 
@@ -417,6 +435,10 @@ static int rtas_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
 		rc = rtas_change_msi(pdn, RTAS_CHANGE_MSIX_FN, nvec);
 
 	if (rc != nvec) {
+		if (nvec != nvec_in) {
+			nvec = nvec_in;
+			goto again;
+		}
 		pr_debug("rtas_msi: rtas_change_msi() failed\n");
 		return rc;
 	}
diff --git a/arch/powerpc/platforms/pseries/pci.c b/arch/powerpc/platforms/pseries/pci.c
index 2c6ded2..56b864d 100644
--- a/arch/powerpc/platforms/pseries/pci.c
+++ b/arch/powerpc/platforms/pseries/pci.c
@@ -73,7 +73,7 @@ void __init pSeries_final_fixup(void)
 {
 	pSeries_request_regions();
 
-	pci_addr_cache_build();
+	eeh_addr_cache_build();
 }
 
 /*
diff --git a/arch/powerpc/platforms/pseries/pci_dlpar.c b/arch/powerpc/platforms/pseries/pci_dlpar.c
index 3ccebc8..261a577 100644
--- a/arch/powerpc/platforms/pseries/pci_dlpar.c
+++ b/arch/powerpc/platforms/pseries/pci_dlpar.c
@@ -65,27 +65,43 @@ pcibios_find_pci_bus(struct device_node *dn)
 EXPORT_SYMBOL_GPL(pcibios_find_pci_bus);
 
 /**
- * pcibios_remove_pci_devices - remove all devices under this bus
+ * __pcibios_remove_pci_devices - remove all devices under this bus
+ * @bus: the indicated PCI bus
+ * @purge_pe: destroy the PE on removal of PCI devices
  *
  * Remove all of the PCI devices under this bus both from the
  * linux pci device tree, and from the powerpc EEH address cache.
+ * By default, the corresponding PE will be destroied during the
+ * normal PCI hotplug path. For PCI hotplug during EEH recovery,
+ * the corresponding PE won't be destroied and deallocated.
  */
-void pcibios_remove_pci_devices(struct pci_bus *bus)
+void __pcibios_remove_pci_devices(struct pci_bus *bus, int purge_pe)
 {
- 	struct pci_dev *dev, *tmp;
+	struct pci_dev *dev, *tmp;
 	struct pci_bus *child_bus;
 
 	/* First go down child busses */
 	list_for_each_entry(child_bus, &bus->children, node)
-		pcibios_remove_pci_devices(child_bus);
+		__pcibios_remove_pci_devices(child_bus, purge_pe);
 
 	pr_debug("PCI: Removing devices on bus %04x:%02x\n",
-		 pci_domain_nr(bus),  bus->number);
+		pci_domain_nr(bus),  bus->number);
 	list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list) {
 		pr_debug("     * Removing %s...\n", pci_name(dev));
-		eeh_remove_bus_device(dev);
- 		pci_stop_and_remove_bus_device(dev);
- 	}
+		eeh_remove_bus_device(dev, purge_pe);
+		pci_stop_and_remove_bus_device(dev);
+	}
+}
+
+/**
+ * pcibios_remove_pci_devices - remove all devices under this bus
+ *
+ * Remove all of the PCI devices under this bus both from the
+ * linux pci device tree, and from the powerpc EEH address cache.
+ */
+void pcibios_remove_pci_devices(struct pci_bus *bus)
+{
+	__pcibios_remove_pci_devices(bus, 1);
 }
 EXPORT_SYMBOL_GPL(pcibios_remove_pci_devices);
 
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index 51ecac9..e3cb7ae 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -388,10 +388,8 @@ static void __init pSeries_setup_arch(void)
 
 	/* Find and initialize PCI host bridges */
 	init_pci_config_tokens();
-	eeh_pseries_init();
 	find_and_init_phbs();
 	pSeries_reconfig_notifier_register(&pci_dn_reconfig_nb);
-	eeh_init();
 
 	pSeries_nvram_init();
 
@@ -416,16 +414,20 @@ static int __init pSeries_init_panel(void)
 }
 machine_arch_initcall(pseries, pSeries_init_panel);
 
-static int pseries_set_dabr(unsigned long dabr)
+static int pseries_set_dabr(unsigned long dabr, unsigned long dabrx)
 {
 	return plpar_hcall_norets(H_SET_DABR, dabr);
 }
 
-static int pseries_set_xdabr(unsigned long dabr)
+static int pseries_set_xdabr(unsigned long dabr, unsigned long dabrx)
 {
-	/* We want to catch accesses from kernel and userspace */
-	return plpar_hcall_norets(H_SET_XDABR, dabr,
-			H_DABRX_KERNEL | H_DABRX_USER);
+	/* Have to set at least one bit in the DABRX according to PAPR */
+	if (dabrx == 0 && dabr == 0)
+		dabrx = DABRX_USER;
+	/* PAPR says we can only set kernel and user bits */
+	dabrx &= DABRX_KERNEL | DABRX_USER;
+
+	return plpar_hcall_norets(H_SET_XDABR, dabr, dabrx);
 }
 
 #define CMO_CHARACTERISTICS_TOKEN 44
@@ -529,10 +531,10 @@ static void __init pSeries_init_early(void)
 	if (firmware_has_feature(FW_FEATURE_LPAR))
 		hvc_vio_init_early();
 #endif
-	if (firmware_has_feature(FW_FEATURE_DABR))
-		ppc_md.set_dabr = pseries_set_dabr;
-	else if (firmware_has_feature(FW_FEATURE_XDABR))
+	if (firmware_has_feature(FW_FEATURE_XDABR))
 		ppc_md.set_dabr = pseries_set_xdabr;
+	else if (firmware_has_feature(FW_FEATURE_DABR))
+		ppc_md.set_dabr = pseries_set_dabr;
 
 	pSeries_cmo_feature_init();
 	iommu_init_early_pSeries();
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index 1bd7ecb..a57600b 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -15,7 +15,7 @@ obj-$(CONFIG_PPC_DCR_NATIVE)	+= dcr-low.o
 obj-$(CONFIG_PPC_PMI)		+= pmi.o
 obj-$(CONFIG_U3_DART)		+= dart_iommu.o
 obj-$(CONFIG_MMIO_NVRAM)	+= mmio_nvram.o
-obj-$(CONFIG_FSL_SOC)		+= fsl_soc.o
+obj-$(CONFIG_FSL_SOC)		+= fsl_soc.o fsl_mpic_err.o
 obj-$(CONFIG_FSL_PCI)		+= fsl_pci.o $(fsl-msi-obj-y)
 obj-$(CONFIG_FSL_PMC)		+= fsl_pmc.o
 obj-$(CONFIG_FSL_LBC)		+= fsl_lbc.o
diff --git a/arch/powerpc/sysdev/dart_iommu.c b/arch/powerpc/sysdev/dart_iommu.c
index 4f2680f..8ef63a0 100644
--- a/arch/powerpc/sysdev/dart_iommu.c
+++ b/arch/powerpc/sysdev/dart_iommu.c
@@ -43,7 +43,6 @@
 #include <asm/iommu.h>
 #include <asm/pci-bridge.h>
 #include <asm/machdep.h>
-#include <asm/abs_addr.h>
 #include <asm/cacheflush.h>
 #include <asm/ppc-pci.h>
 
@@ -167,7 +166,7 @@ static int dart_build(struct iommu_table *tbl, long index,
 	 */
 	l = npages;
 	while (l--) {
-		rpn = virt_to_abs(uaddr) >> DART_PAGE_SHIFT;
+		rpn = __pa(uaddr) >> DART_PAGE_SHIFT;
 
 		*(dp++) = DARTMAP_VALID | (rpn & DARTMAP_RPNMASK);
 
@@ -244,7 +243,7 @@ static int __init dart_init(struct device_node *dart_node)
 		panic("DART: Cannot map registers!");
 
 	/* Map in DART table */
-	dart_vbase = ioremap(virt_to_abs(dart_tablebase), dart_tablesize);
+	dart_vbase = ioremap(__pa(dart_tablebase), dart_tablesize);
 
 	/* Fill initial table */
 	for (i = 0; i < dart_tablesize/4; i++)
@@ -463,7 +462,7 @@ void __init alloc_dart_table(void)
 	 * will blow up an entire large page anyway in the kernel mapping
 	 */
 	dart_tablebase = (unsigned long)
-		abs_to_virt(memblock_alloc_base(1UL<<24, 1UL<<24, 0x80000000L));
+		__va(memblock_alloc_base(1UL<<24, 1UL<<24, 0x80000000L));
 
 	printk(KERN_INFO "DART table allocated at: %lx\n", dart_tablebase);
 }
diff --git a/arch/powerpc/sysdev/fsl_85xx_l2ctlr.c b/arch/powerpc/sysdev/fsl_85xx_l2ctlr.c
index 68ac3aa..d131c8a 100644
--- a/arch/powerpc/sysdev/fsl_85xx_l2ctlr.c
+++ b/arch/powerpc/sysdev/fsl_85xx_l2ctlr.c
@@ -193,6 +193,16 @@ static struct of_device_id mpc85xx_l2ctlr_of_match[] = {
 	{
 		.compatible = "fsl,mpc8548-l2-cache-controller",
 	},
+	{	.compatible = "fsl,mpc8544-l2-cache-controller",},
+	{	.compatible = "fsl,mpc8572-l2-cache-controller",},
+	{	.compatible = "fsl,mpc8536-l2-cache-controller",},
+	{	.compatible = "fsl,p1021-l2-cache-controller",},
+	{	.compatible = "fsl,p1012-l2-cache-controller",},
+	{	.compatible = "fsl,p1025-l2-cache-controller",},
+	{	.compatible = "fsl,p1016-l2-cache-controller",},
+	{	.compatible = "fsl,p1024-l2-cache-controller",},
+	{	.compatible = "fsl,p1015-l2-cache-controller",},
+	{	.compatible = "fsl,p1010-l2-cache-controller",},
 	{},
 };
 
diff --git a/arch/powerpc/sysdev/fsl_ifc.c b/arch/powerpc/sysdev/fsl_ifc.c
index b31f19f..097cc9d2 100644
--- a/arch/powerpc/sysdev/fsl_ifc.c
+++ b/arch/powerpc/sysdev/fsl_ifc.c
@@ -244,12 +244,6 @@ static int __devinit fsl_ifc_ctrl_probe(struct platform_device *dev)
 	/* get the nand machine irq */
 	fsl_ifc_ctrl_dev->nand_irq =
 			irq_of_parse_and_map(dev->dev.of_node, 1);
-	if (fsl_ifc_ctrl_dev->nand_irq == NO_IRQ) {
-		dev_err(&dev->dev, "failed to get irq resource "
-						"for NAND Machine\n");
-		ret = -ENODEV;
-		goto err;
-	}
 
 	fsl_ifc_ctrl_dev->dev = &dev->dev;
 
@@ -267,12 +261,14 @@ static int __devinit fsl_ifc_ctrl_probe(struct platform_device *dev)
 		goto err_irq;
 	}
 
-	ret = request_irq(fsl_ifc_ctrl_dev->nand_irq, fsl_ifc_nand_irq, 0,
-			  "fsl-ifc-nand", fsl_ifc_ctrl_dev);
-	if (ret != 0) {
-		dev_err(&dev->dev, "failed to install irq (%d)\n",
-			fsl_ifc_ctrl_dev->nand_irq);
-		goto err_nandirq;
+	if (fsl_ifc_ctrl_dev->nand_irq) {
+		ret = request_irq(fsl_ifc_ctrl_dev->nand_irq, fsl_ifc_nand_irq,
+				0, "fsl-ifc-nand", fsl_ifc_ctrl_dev);
+		if (ret != 0) {
+			dev_err(&dev->dev, "failed to install irq (%d)\n",
+				fsl_ifc_ctrl_dev->nand_irq);
+			goto err_nandirq;
+		}
 	}
 
 	return 0;
diff --git a/arch/powerpc/sysdev/fsl_mpic_err.c b/arch/powerpc/sysdev/fsl_mpic_err.c
new file mode 100644
index 0000000..b83f325
--- /dev/null
+++ b/arch/powerpc/sysdev/fsl_mpic_err.c
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2012 Freescale Semiconductor, Inc.
+ *
+ * Author: Varun Sethi <varun.sethi@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2 of the
+ * License.
+ *
+ */
+
+#include <linux/irq.h>
+#include <linux/smp.h>
+#include <linux/interrupt.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mpic.h>
+
+#include "mpic.h"
+
+#define MPIC_ERR_INT_BASE	0x3900
+#define MPIC_ERR_INT_EISR	0x0000
+#define MPIC_ERR_INT_EIMR	0x0010
+
+static inline u32 mpic_fsl_err_read(u32 __iomem *base, unsigned int err_reg)
+{
+	return in_be32(base + (err_reg >> 2));
+}
+
+static inline void mpic_fsl_err_write(u32 __iomem *base, u32 value)
+{
+	out_be32(base + (MPIC_ERR_INT_EIMR >> 2), value);
+}
+
+static void fsl_mpic_mask_err(struct irq_data *d)
+{
+	u32 eimr;
+	struct mpic *mpic = irq_data_get_irq_chip_data(d);
+	unsigned int src = virq_to_hw(d->irq) - mpic->err_int_vecs[0];
+
+	eimr = mpic_fsl_err_read(mpic->err_regs, MPIC_ERR_INT_EIMR);
+	eimr |= (1 << (31 - src));
+	mpic_fsl_err_write(mpic->err_regs, eimr);
+}
+
+static void fsl_mpic_unmask_err(struct irq_data *d)
+{
+	u32 eimr;
+	struct mpic *mpic = irq_data_get_irq_chip_data(d);
+	unsigned int src = virq_to_hw(d->irq) - mpic->err_int_vecs[0];
+
+	eimr = mpic_fsl_err_read(mpic->err_regs, MPIC_ERR_INT_EIMR);
+	eimr &= ~(1 << (31 - src));
+	mpic_fsl_err_write(mpic->err_regs, eimr);
+}
+
+static struct irq_chip fsl_mpic_err_chip = {
+	.irq_disable	= fsl_mpic_mask_err,
+	.irq_mask	= fsl_mpic_mask_err,
+	.irq_unmask	= fsl_mpic_unmask_err,
+};
+
+int mpic_setup_error_int(struct mpic *mpic, int intvec)
+{
+	int i;
+
+	mpic->err_regs = ioremap(mpic->paddr + MPIC_ERR_INT_BASE, 0x1000);
+	if (!mpic->err_regs) {
+		pr_err("could not map mpic error registers\n");
+		return -ENOMEM;
+	}
+	mpic->hc_err = fsl_mpic_err_chip;
+	mpic->hc_err.name = mpic->name;
+	mpic->flags |= MPIC_FSL_HAS_EIMR;
+	/* allocate interrupt vectors for error interrupts */
+	for (i = MPIC_MAX_ERR - 1; i >= 0; i--)
+		mpic->err_int_vecs[i] = --intvec;
+
+	return 0;
+}
+
+int mpic_map_error_int(struct mpic *mpic, unsigned int virq, irq_hw_number_t  hw)
+{
+	if ((mpic->flags & MPIC_FSL_HAS_EIMR) &&
+	    (hw >= mpic->err_int_vecs[0] &&
+	     hw <= mpic->err_int_vecs[MPIC_MAX_ERR - 1])) {
+		WARN_ON(mpic->flags & MPIC_SECONDARY);
+
+		pr_debug("mpic: mapping as Error Interrupt\n");
+		irq_set_chip_data(virq, mpic);
+		irq_set_chip_and_handler(virq, &mpic->hc_err,
+					 handle_level_irq);
+		return 1;
+	}
+
+	return 0;
+}
+
+static irqreturn_t fsl_error_int_handler(int irq, void *data)
+{
+	struct mpic *mpic = (struct mpic *) data;
+	u32 eisr, eimr;
+	int errint;
+	unsigned int cascade_irq;
+
+	eisr = mpic_fsl_err_read(mpic->err_regs, MPIC_ERR_INT_EISR);
+	eimr = mpic_fsl_err_read(mpic->err_regs, MPIC_ERR_INT_EIMR);
+
+	if (!(eisr & ~eimr))
+		return IRQ_NONE;
+
+	while (eisr) {
+		errint = __builtin_clz(eisr);
+		cascade_irq = irq_linear_revmap(mpic->irqhost,
+				 mpic->err_int_vecs[errint]);
+		WARN_ON(cascade_irq == NO_IRQ);
+		if (cascade_irq != NO_IRQ) {
+			generic_handle_irq(cascade_irq);
+		} else {
+			eimr |=  1 << (31 - errint);
+			mpic_fsl_err_write(mpic->err_regs, eimr);
+		}
+		eisr &= ~(1 << (31 - errint));
+	}
+
+	return IRQ_HANDLED;
+}
+
+void mpic_err_int_init(struct mpic *mpic, irq_hw_number_t irqnum)
+{
+	unsigned int virq;
+	int ret;
+
+	virq = irq_create_mapping(mpic->irqhost, irqnum);
+	if (virq == NO_IRQ) {
+		pr_err("Error interrupt setup failed\n");
+		return;
+	}
+
+	/* Mask all error interrupts */
+	mpic_fsl_err_write(mpic->err_regs, ~0);
+
+	ret = request_irq(virq, fsl_error_int_handler, IRQF_NO_THREAD,
+		    "mpic-error-int", mpic);
+	if (ret)
+		pr_err("Failed to register error interrupt handler\n");
+}
diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c
index 6e097de..63c5f04 100644
--- a/arch/powerpc/sysdev/fsl_msi.c
+++ b/arch/powerpc/sysdev/fsl_msi.c
@@ -236,7 +236,6 @@ static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc)
 	u32 intr_index;
 	u32 have_shift = 0;
 	struct fsl_msi_cascade_data *cascade_data;
-	unsigned int ret;
 
 	cascade_data = irq_get_handler_data(irq);
 	msi_data = cascade_data->msi_data;
@@ -268,7 +267,9 @@ static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc)
 	case FSL_PIC_IP_IPIC:
 		msir_value = fsl_msi_read(msi_data->msi_regs, msir_index * 0x4);
 		break;
-	case FSL_PIC_IP_VMPIC:
+#ifdef CONFIG_EPAPR_PARAVIRT
+	case FSL_PIC_IP_VMPIC: {
+		unsigned int ret;
 		ret = fh_vmpic_get_msir(virq_to_hw(irq), &msir_value);
 		if (ret) {
 			pr_err("fsl-msi: fh_vmpic_get_msir() failed for "
@@ -277,6 +278,8 @@ static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc)
 		}
 		break;
 	}
+#endif
+	}
 
 	while (msir_value) {
 		intr_index = ffs(msir_value) - 1;
@@ -368,7 +371,7 @@ static int __devinit fsl_of_msi_probe(struct platform_device *dev)
 	int err, i, j, irq_index, count;
 	int rc;
 	const u32 *p;
-	struct fsl_msi_feature *features;
+	const struct fsl_msi_feature *features;
 	int len;
 	u32 offset;
 	static const u32 all_avail[] = { 0, NR_MSI_IRQS };
@@ -502,16 +505,18 @@ static const struct fsl_msi_feature vmpic_msi_feature = {
 static const struct of_device_id fsl_of_msi_ids[] = {
 	{
 		.compatible = "fsl,mpic-msi",
-		.data = (void *)&mpic_msi_feature,
+		.data = &mpic_msi_feature,
 	},
 	{
 		.compatible = "fsl,ipic-msi",
-		.data = (void *)&ipic_msi_feature,
+		.data = &ipic_msi_feature,
 	},
+#ifdef CONFIG_EPAPR_PARAVIRT
 	{
 		.compatible = "fsl,vmpic-msi",
-		.data = (void *)&vmpic_msi_feature,
+		.data = &vmpic_msi_feature,
 	},
+#endif
 	{}
 };
 
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index c37f461..3d6f4d8 100644
--- a/arch/powerpc/sysdev/fsl_pci.c
+++ b/arch/powerpc/sysdev/fsl_pci.c
@@ -143,18 +143,20 @@ static void __init setup_pci_atmu(struct pci_controller *hose,
 	pr_debug("PCI memory map start 0x%016llx, size 0x%016llx\n",
 		 (u64)rsrc->start, (u64)resource_size(rsrc));
 
-	if (of_device_is_compatible(hose->dn, "fsl,qoriq-pcie-v2.2")) {
-		win_idx = 2;
-		start_idx = 0;
-		end_idx = 3;
-	}
-
 	pci = ioremap(rsrc->start, resource_size(rsrc));
 	if (!pci) {
 	    dev_err(hose->parent, "Unable to map ATMU registers\n");
 	    return;
 	}
 
+	if (early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP)) {
+		if (in_be32(&pci->block_rev1) >= PCIE_IP_REV_2_2) {
+			win_idx = 2;
+			start_idx = 0;
+			end_idx = 3;
+		}
+	}
+
 	/* Disable all windows (except powar0 since it's ignored) */
 	for(i = 1; i < 5; i++)
 		out_be32(&pci->pow[i].powar, 0);
@@ -818,6 +820,7 @@ static const struct of_device_id pci_ids[] = {
 	{ .compatible = "fsl,p1010-pcie", },
 	{ .compatible = "fsl,p1023-pcie", },
 	{ .compatible = "fsl,p4080-pcie", },
+	{ .compatible = "fsl,qoriq-pcie-v2.4", },
 	{ .compatible = "fsl,qoriq-pcie-v2.3", },
 	{ .compatible = "fsl,qoriq-pcie-v2.2", },
 	{},
@@ -825,57 +828,80 @@ static const struct of_device_id pci_ids[] = {
 
 struct device_node *fsl_pci_primary;
 
-void __devinit fsl_pci_init(void)
+void fsl_pci_assign_primary(void)
 {
-	int ret;
-	struct device_node *node;
-	struct pci_controller *hose;
-	dma_addr_t max = 0xffffffff;
+	struct device_node *np;
 
 	/* Callers can specify the primary bus using other means. */
-	if (!fsl_pci_primary) {
-		/* If a PCI host bridge contains an ISA node, it's primary. */
-		node = of_find_node_by_type(NULL, "isa");
-		while ((fsl_pci_primary = of_get_parent(node))) {
-			of_node_put(node);
-			node = fsl_pci_primary;
-
-			if (of_match_node(pci_ids, node))
-				break;
-		}
+	if (fsl_pci_primary)
+		return;
+
+	/* If a PCI host bridge contains an ISA node, it's primary. */
+	np = of_find_node_by_type(NULL, "isa");
+	while ((fsl_pci_primary = of_get_parent(np))) {
+		of_node_put(np);
+		np = fsl_pci_primary;
+
+		if (of_match_node(pci_ids, np) && of_device_is_available(np))
+			return;
 	}
 
-	node = NULL;
-	for_each_node_by_type(node, "pci") {
-		if (of_match_node(pci_ids, node)) {
-			/*
-			 * If there's no PCI host bridge with ISA, arbitrarily
-			 * designate one as primary.  This can go away once
-			 * various bugs with primary-less systems are fixed.
-			 */
-			if (!fsl_pci_primary)
-				fsl_pci_primary = node;
-
-			ret = fsl_add_bridge(node, fsl_pci_primary == node);
-			if (ret == 0) {
-				hose = pci_find_hose_for_OF_device(node);
-				max = min(max, hose->dma_window_base_cur +
-						hose->dma_window_size);
-			}
+	/*
+	 * If there's no PCI host bridge with ISA, arbitrarily
+	 * designate one as primary.  This can go away once
+	 * various bugs with primary-less systems are fixed.
+	 */
+	for_each_matching_node(np, pci_ids) {
+		if (of_device_is_available(np)) {
+			fsl_pci_primary = np;
+			of_node_put(np);
+			return;
 		}
 	}
+}
 
+static int __devinit fsl_pci_probe(struct platform_device *pdev)
+{
+	int ret;
+	struct device_node *node;
 #ifdef CONFIG_SWIOTLB
-	/*
-	 * if we couldn't map all of DRAM via the dma windows
-	 * we need SWIOTLB to handle buffers located outside of
-	 * dma capable memory region
-	 */
-	if (memblock_end_of_DRAM() - 1 > max) {
-		ppc_swiotlb_enable = 1;
-		set_pci_dma_ops(&swiotlb_dma_ops);
-		ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb;
+	struct pci_controller *hose;
+#endif
+
+	node = pdev->dev.of_node;
+	ret = fsl_add_bridge(node, fsl_pci_primary == node);
+
+#ifdef CONFIG_SWIOTLB
+	if (ret == 0) {
+		hose = pci_find_hose_for_OF_device(pdev->dev.of_node);
+
+		/*
+		 * if we couldn't map all of DRAM via the dma windows
+		 * we need SWIOTLB to handle buffers located outside of
+		 * dma capable memory region
+		 */
+		if (memblock_end_of_DRAM() - 1 > hose->dma_window_base_cur +
+				hose->dma_window_size)
+			ppc_swiotlb_enable = 1;
 	}
 #endif
+
+	mpc85xx_pci_err_probe(pdev);
+
+	return 0;
+}
+
+static struct platform_driver fsl_pci_driver = {
+	.driver = {
+		.name = "fsl-pci",
+		.of_match_table = pci_ids,
+	},
+	.probe = fsl_pci_probe,
+};
+
+static int __init fsl_pci_init(void)
+{
+	return platform_driver_register(&fsl_pci_driver);
 }
+arch_initcall(fsl_pci_init);
 #endif
diff --git a/arch/powerpc/sysdev/fsl_pci.h b/arch/powerpc/sysdev/fsl_pci.h
index baa0fd1..d078537 100644
--- a/arch/powerpc/sysdev/fsl_pci.h
+++ b/arch/powerpc/sysdev/fsl_pci.h
@@ -16,6 +16,7 @@
 
 #define PCIE_LTSSM	0x0404		/* PCIE Link Training and Status */
 #define PCIE_LTSSM_L0	0x16		/* L0 state */
+#define PCIE_IP_REV_2_2		0x02080202 /* PCIE IP block version Rev2.2 */
 #define PIWAR_EN		0x80000000	/* Enable */
 #define PIWAR_PF		0x20000000	/* prefetch */
 #define PIWAR_TGI_LOCAL		0x00f00000	/* target - local memory */
@@ -57,7 +58,9 @@ struct ccsr_pci {
 	__be32	pex_pme_mes_disr;	/* 0x.024 - PCIE PME and message disable register */
 	__be32	pex_pme_mes_ier;	/* 0x.028 - PCIE PME and message interrupt enable register */
 	__be32	pex_pmcr;		/* 0x.02c - PCIE power management command register */
-	u8	res3[3024];
+	u8	res3[3016];
+	__be32	block_rev1;	/* 0x.bf8 - PCIE Block Revision register 1 */
+	__be32	block_rev2;	/* 0x.bfc - PCIE Block Revision register 2 */
 
 /* PCI/PCI Express outbound window 0-4
  * Window 0 is the default window and is the only window enabled upon reset.
@@ -95,10 +98,19 @@ u64 fsl_pci_immrbar_base(struct pci_controller *hose);
 
 extern struct device_node *fsl_pci_primary;
 
-#ifdef CONFIG_FSL_PCI
-void fsl_pci_init(void);
+#ifdef CONFIG_PCI
+void fsl_pci_assign_primary(void);
 #else
-static inline void fsl_pci_init(void) {}
+static inline void fsl_pci_assign_primary(void) {}
+#endif
+
+#ifdef CONFIG_EDAC_MPC85XX
+int mpc85xx_pci_err_probe(struct platform_device *op);
+#else
+static inline int mpc85xx_pci_err_probe(struct platform_device *op)
+{
+	return -ENOTSUPP;
+}
 #endif
 
 #endif /* __POWERPC_FSL_PCI_H */
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
index c449dbd..97118dc 100644
--- a/arch/powerpc/sysdev/fsl_soc.c
+++ b/arch/powerpc/sysdev/fsl_soc.c
@@ -253,6 +253,7 @@ struct platform_diu_data_ops diu_ops;
 EXPORT_SYMBOL(diu_ops);
 #endif
 
+#ifdef CONFIG_EPAPR_PARAVIRT
 /*
  * Restart the current partition
  *
@@ -278,3 +279,4 @@ void fsl_hv_halt(void)
 	pr_info("hv exit\n");
 	fh_partition_stop(-1);
 }
+#endif
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index bfc6211..9c6e535 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -6,7 +6,7 @@
  *  with various broken implementations of this HW.
  *
  *  Copyright (C) 2004 Benjamin Herrenschmidt, IBM Corp.
- *  Copyright 2010-2011 Freescale Semiconductor, Inc.
+ *  Copyright 2010-2012 Freescale Semiconductor, Inc.
  *
  *  This file is subject to the terms and conditions of the GNU General Public
  *  License.  See the file COPYING in the main directory of this archive
@@ -221,24 +221,24 @@ static inline void _mpic_ipi_write(struct mpic *mpic, unsigned int ipi, u32 valu
 	_mpic_write(mpic->reg_type, &mpic->gregs, offset, value);
 }
 
-static inline u32 _mpic_tm_read(struct mpic *mpic, unsigned int tm)
+static inline unsigned int mpic_tm_offset(struct mpic *mpic, unsigned int tm)
 {
-	unsigned int offset = MPIC_INFO(TIMER_VECTOR_PRI) +
-			      ((tm & 3) * MPIC_INFO(TIMER_STRIDE));
+	return (tm >> 2) * MPIC_TIMER_GROUP_STRIDE +
+	       (tm & 3) * MPIC_INFO(TIMER_STRIDE);
+}
 
-	if (tm >= 4)
-		offset += 0x1000 / 4;
+static inline u32 _mpic_tm_read(struct mpic *mpic, unsigned int tm)
+{
+	unsigned int offset = mpic_tm_offset(mpic, tm) +
+			      MPIC_INFO(TIMER_VECTOR_PRI);
 
 	return _mpic_read(mpic->reg_type, &mpic->tmregs, offset);
 }
 
 static inline void _mpic_tm_write(struct mpic *mpic, unsigned int tm, u32 value)
 {
-	unsigned int offset = MPIC_INFO(TIMER_VECTOR_PRI) +
-			      ((tm & 3) * MPIC_INFO(TIMER_STRIDE));
-
-	if (tm >= 4)
-		offset += 0x1000 / 4;
+	unsigned int offset = mpic_tm_offset(mpic, tm) +
+			      MPIC_INFO(TIMER_VECTOR_PRI);
 
 	_mpic_write(mpic->reg_type, &mpic->tmregs, offset, value);
 }
@@ -1026,6 +1026,9 @@ static int mpic_host_map(struct irq_domain *h, unsigned int virq,
 		return 0;
 	}
 
+	if (mpic_map_error_int(mpic, virq, hw))
+		return 0;
+
 	if (hw >= mpic->num_sources)
 		return -EINVAL;
 
@@ -1085,7 +1088,16 @@ static int mpic_host_xlate(struct irq_domain *h, struct device_node *ct,
 		 */
 		switch (intspec[2]) {
 		case 0:
-		case 1: /* no EISR/EIMR support for now, treat as shared IRQ */
+			break;
+		case 1:
+			if (!(mpic->flags & MPIC_FSL_HAS_EIMR))
+				break;
+
+			if (intspec[3] >= ARRAY_SIZE(mpic->err_int_vecs))
+				return -EINVAL;
+
+			*out_hwirq = mpic->err_int_vecs[intspec[3]];
+
 			break;
 		case 2:
 			if (intspec[0] >= ARRAY_SIZE(mpic->ipi_vecs))
@@ -1301,6 +1313,42 @@ struct mpic * __init mpic_alloc(struct device_node *node,
 	mpic_map(mpic, mpic->paddr, &mpic->gregs, MPIC_INFO(GREG_BASE), 0x1000);
 	mpic_map(mpic, mpic->paddr, &mpic->tmregs, MPIC_INFO(TIMER_BASE), 0x1000);
 
+	if (mpic->flags & MPIC_FSL) {
+		u32 brr1, version;
+		int ret;
+
+		/*
+		 * Yes, Freescale really did put global registers in the
+		 * magic per-cpu area -- and they don't even show up in the
+		 * non-magic per-cpu copies that this driver normally uses.
+		 */
+		mpic_map(mpic, mpic->paddr, &mpic->thiscpuregs,
+			 MPIC_CPU_THISBASE, 0x1000);
+
+		brr1 = _mpic_read(mpic->reg_type, &mpic->thiscpuregs,
+				MPIC_FSL_BRR1);
+		version = brr1 & MPIC_FSL_BRR1_VER;
+
+		/* Error interrupt mask register (EIMR) is required for
+		 * handling individual device error interrupts. EIMR
+		 * was added in MPIC version 4.1.
+		 *
+		 * Over here we reserve vector number space for error
+		 * interrupt vectors. This space is stolen from the
+		 * global vector number space, as in case of ipis
+		 * and timer interrupts.
+		 *
+		 * Available vector space = intvec_top - 12, where 12
+		 * is the number of vectors which have been consumed by
+		 * ipis and timer interrupts.
+		 */
+		if (version >= 0x401) {
+			ret = mpic_setup_error_int(mpic, intvec_top - 12);
+			if (ret)
+				return NULL;
+		}
+	}
+
 	/* Reset */
 
 	/* When using a device-node, reset requests are only honored if the MPIC
@@ -1440,6 +1488,7 @@ void __init mpic_assign_isu(struct mpic *mpic, unsigned int isu_num,
 void __init mpic_init(struct mpic *mpic)
 {
 	int i, cpu;
+	int num_timers = 4;
 
 	BUG_ON(mpic->num_sources == 0);
 
@@ -1448,15 +1497,34 @@ void __init mpic_init(struct mpic *mpic)
 	/* Set current processor priority to max */
 	mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), 0xf);
 
+	if (mpic->flags & MPIC_FSL) {
+		u32 brr1 = _mpic_read(mpic->reg_type, &mpic->thiscpuregs,
+				      MPIC_FSL_BRR1);
+		u32 version = brr1 & MPIC_FSL_BRR1_VER;
+
+		/*
+		 * Timer group B is present at the latest in MPIC 3.1 (e.g.
+		 * mpc8536).  It is not present in MPIC 2.0 (e.g. mpc8544).
+		 * I don't know about the status of intermediate versions (or
+		 * whether they even exist).
+		 */
+		if (version >= 0x0301)
+			num_timers = 8;
+	}
+
+	/* FSL mpic error interrupt intialization */
+	if (mpic->flags & MPIC_FSL_HAS_EIMR)
+		mpic_err_int_init(mpic, MPIC_FSL_ERR_INT);
+
 	/* Initialize timers to our reserved vectors and mask them for now */
-	for (i = 0; i < 4; i++) {
+	for (i = 0; i < num_timers; i++) {
+		unsigned int offset = mpic_tm_offset(mpic, i);
+
 		mpic_write(mpic->tmregs,
-			   i * MPIC_INFO(TIMER_STRIDE) +
-			   MPIC_INFO(TIMER_DESTINATION),
+			   offset + MPIC_INFO(TIMER_DESTINATION),
 			   1 << hard_smp_processor_id());
 		mpic_write(mpic->tmregs,
-			   i * MPIC_INFO(TIMER_STRIDE) +
-			   MPIC_INFO(TIMER_VECTOR_PRI),
+			   offset + MPIC_INFO(TIMER_VECTOR_PRI),
 			   MPIC_VECPRI_MASK |
 			   (9 << MPIC_VECPRI_PRIORITY_SHIFT) |
 			   (mpic->timer_vecs[0] + i));
diff --git a/arch/powerpc/sysdev/mpic.h b/arch/powerpc/sysdev/mpic.h
index 13f3e89..24bf07a 100644
--- a/arch/powerpc/sysdev/mpic.h
+++ b/arch/powerpc/sysdev/mpic.h
@@ -40,4 +40,26 @@ extern int mpic_set_affinity(struct irq_data *d,
 			     const struct cpumask *cpumask, bool force);
 extern void mpic_reset_core(int cpu);
 
+#ifdef CONFIG_FSL_SOC
+extern int mpic_map_error_int(struct mpic *mpic, unsigned int virq, irq_hw_number_t  hw);
+extern void mpic_err_int_init(struct mpic *mpic, irq_hw_number_t irqnum);
+extern int mpic_setup_error_int(struct mpic *mpic, int intvec);
+#else
+static inline int mpic_map_error_int(struct mpic *mpic, unsigned int virq, irq_hw_number_t  hw)
+{
+	return 0;
+}
+
+
+static inline void mpic_err_int_init(struct mpic *mpic, irq_hw_number_t irqnum)
+{
+	return;
+}
+
+static inline int mpic_setup_error_int(struct mpic *mpic, int intvec)
+{
+	return -1;
+}
+#endif
+
 #endif /* _POWERPC_SYSDEV_MPIC_H */
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index 9b49c65..3a56a63 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -60,6 +60,8 @@ static cpumask_t cpus_in_xmon = CPU_MASK_NONE;
 static unsigned long xmon_taken = 1;
 static int xmon_owner;
 static int xmon_gate;
+#else
+#define xmon_owner 0
 #endif /* CONFIG_SMP */
 
 static unsigned long in_xmon __read_mostly = 0;
@@ -202,7 +204,13 @@ Commands:\n\
   di	dump instructions\n\
   df	dump float values\n\
   dd	dump double values\n\
-  dl    dump the kernel log buffer\n\
+  dl    dump the kernel log buffer\n"
+#ifdef CONFIG_PPC64
+  "\
+  dp[#]	dump paca for current cpu, or cpu #\n\
+  dpa	dump paca for all possible cpus\n"
+#endif
+  "\
   dr	dump stream of raw bytes\n\
   e	print exception information\n\
   f	flush cache\n\
@@ -740,7 +748,7 @@ static void insert_bpts(void)
 static void insert_cpu_bpts(void)
 {
 	if (dabr.enabled)
-		set_dabr(dabr.address | (dabr.enabled & 7));
+		set_dabr(dabr.address | (dabr.enabled & 7), DABRX_ALL);
 	if (iabr && cpu_has_feature(CPU_FTR_IABR))
 		mtspr(SPRN_IABR, iabr->address
 			 | (iabr->enabled & (BP_IABR|BP_IABR_TE)));
@@ -768,7 +776,7 @@ static void remove_bpts(void)
 
 static void remove_cpu_bpts(void)
 {
-	set_dabr(0);
+	set_dabr(0, 0);
 	if (cpu_has_feature(CPU_FTR_IABR))
 		mtspr(SPRN_IABR, 0);
 }
@@ -2009,6 +2017,95 @@ static void xmon_rawdump (unsigned long adrs, long ndump)
 	printf("\n");
 }
 
+#ifdef CONFIG_PPC64
+static void dump_one_paca(int cpu)
+{
+	struct paca_struct *p;
+
+	if (setjmp(bus_error_jmp) != 0) {
+		printf("*** Error dumping paca for cpu 0x%x!\n", cpu);
+		return;
+	}
+
+	catch_memory_errors = 1;
+	sync();
+
+	p = &paca[cpu];
+
+	printf("paca for cpu 0x%x @ %p:\n", cpu, p);
+
+	printf(" %-*s = %s\n", 16, "possible", cpu_possible(cpu) ? "yes" : "no");
+	printf(" %-*s = %s\n", 16, "present", cpu_present(cpu) ? "yes" : "no");
+	printf(" %-*s = %s\n", 16, "online", cpu_online(cpu) ? "yes" : "no");
+
+#define DUMP(paca, name, format) \
+	printf(" %-*s = %#-*"format"\t(0x%lx)\n", 16, #name, 18, paca->name, \
+		offsetof(struct paca_struct, name));
+
+	DUMP(p, lock_token, "x");
+	DUMP(p, paca_index, "x");
+	DUMP(p, kernel_toc, "lx");
+	DUMP(p, kernelbase, "lx");
+	DUMP(p, kernel_msr, "lx");
+#ifdef CONFIG_PPC_STD_MMU_64
+	DUMP(p, stab_real, "lx");
+	DUMP(p, stab_addr, "lx");
+#endif
+	DUMP(p, emergency_sp, "p");
+	DUMP(p, data_offset, "lx");
+	DUMP(p, hw_cpu_id, "x");
+	DUMP(p, cpu_start, "x");
+	DUMP(p, kexec_state, "x");
+	DUMP(p, __current, "p");
+	DUMP(p, kstack, "lx");
+	DUMP(p, stab_rr, "lx");
+	DUMP(p, saved_r1, "lx");
+	DUMP(p, trap_save, "x");
+	DUMP(p, soft_enabled, "x");
+	DUMP(p, irq_happened, "x");
+	DUMP(p, io_sync, "x");
+	DUMP(p, irq_work_pending, "x");
+	DUMP(p, nap_state_lost, "x");
+
+#undef DUMP
+
+	catch_memory_errors = 0;
+	sync();
+}
+
+static void dump_all_pacas(void)
+{
+	int cpu;
+
+	if (num_possible_cpus() == 0) {
+		printf("No possible cpus, use 'dp #' to dump individual cpus\n");
+		return;
+	}
+
+	for_each_possible_cpu(cpu)
+		dump_one_paca(cpu);
+}
+
+static void dump_pacas(void)
+{
+	unsigned long num;
+	int c;
+
+	c = inchar();
+	if (c == 'a') {
+		dump_all_pacas();
+		return;
+	}
+
+	termch = c;	/* Put c back, it wasn't 'a' */
+
+	if (scanhex(&num))
+		dump_one_paca(num);
+	else
+		dump_one_paca(xmon_owner);
+}
+#endif
+
 #define isxdigit(c)	(('0' <= (c) && (c) <= '9') \
 			 || ('a' <= (c) && (c) <= 'f') \
 			 || ('A' <= (c) && (c) <= 'F'))
@@ -2018,6 +2115,14 @@ dump(void)
 	int c;
 
 	c = inchar();
+
+#ifdef CONFIG_PPC64
+	if (c == 'p') {
+		dump_pacas();
+		return;
+	}
+#endif
+
 	if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n')
 		termch = c;
 	scanhex((void *)&adrs);
diff --git a/arch/s390/Kbuild b/arch/s390/Kbuild
index 9858476..cc45d25 100644
--- a/arch/s390/Kbuild
+++ b/arch/s390/Kbuild
@@ -5,3 +5,4 @@ obj-$(CONFIG_CRYPTO_HW)		+= crypto/
 obj-$(CONFIG_S390_HYPFS_FS)	+= hypfs/
 obj-$(CONFIG_APPLDATA_BASE)	+= appldata/
 obj-$(CONFIG_MATHEMU)		+= math-emu/
+obj-y				+= net/
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 107610e..18c7e63 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -49,10 +49,13 @@ config GENERIC_LOCKBREAK
 config PGSTE
 	def_bool y if KVM
 
-config VIRT_CPU_ACCOUNTING
+config ARCH_SUPPORTS_DEBUG_PAGEALLOC
 	def_bool y
 
-config ARCH_SUPPORTS_DEBUG_PAGEALLOC
+config KEXEC
+	def_bool y
+
+config AUDIT_ARCH
 	def_bool y
 
 config S390
@@ -84,11 +87,15 @@ config S390
 	select HAVE_KERNEL_XZ
 	select HAVE_ARCH_MUTEX_CPU_RELAX
 	select HAVE_ARCH_JUMP_LABEL if !MARCH_G5
+	select HAVE_BPF_JIT if 64BIT && PACK_STACK
 	select ARCH_SAVE_PAGE_KEYS if HIBERNATION
 	select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
 	select HAVE_MEMBLOCK
 	select HAVE_MEMBLOCK_NODE_MAP
 	select HAVE_CMPXCHG_LOCAL
+	select HAVE_CMPXCHG_DOUBLE
+	select HAVE_VIRT_CPU_ACCOUNTING
+	select VIRT_CPU_ACCOUNTING
 	select ARCH_DISCARD_MEMBLOCK
 	select BUILDTIME_EXTABLE_SORT
 	select ARCH_INLINE_SPIN_TRYLOCK
@@ -125,6 +132,9 @@ config S390
 	select GENERIC_CLOCKEVENTS
 	select KTIME_SCALAR if 32BIT
 	select HAVE_ARCH_SECCOMP_FILTER
+	select HAVE_MOD_ARCH_SPECIFIC
+	select MODULES_USE_ELF_RELA
+	select GENERIC_KERNEL_THREAD
 
 config SCHED_OMIT_FRAME_POINTER
 	def_bool y
@@ -133,9 +143,79 @@ source "init/Kconfig"
 
 source "kernel/Kconfig.freezer"
 
-menu "Base setup"
+menu "Processor type and features"
+
+config HAVE_MARCH_Z900_FEATURES
+	def_bool n
+
+config HAVE_MARCH_Z990_FEATURES
+	def_bool n
+	select HAVE_MARCH_Z900_FEATURES
+
+config HAVE_MARCH_Z9_109_FEATURES
+	def_bool n
+	select HAVE_MARCH_Z990_FEATURES
+
+config HAVE_MARCH_Z10_FEATURES
+	def_bool n
+	select HAVE_MARCH_Z9_109_FEATURES
+
+config HAVE_MARCH_Z196_FEATURES
+	def_bool n
+	select HAVE_MARCH_Z10_FEATURES
+
+choice
+	prompt "Processor type"
+	default MARCH_G5
+
+config MARCH_G5
+	bool "System/390 model G5 and G6"
+	depends on !64BIT
+	help
+	  Select this to build a 31 bit kernel that works
+	  on all ESA/390 and z/Architecture machines.
 
-comment "Processor type and features"
+config MARCH_Z900
+	bool "IBM zSeries model z800 and z900"
+	select HAVE_MARCH_Z900_FEATURES if 64BIT
+	help
+	  Select this to enable optimizations for model z800/z900 (2064 and
+	  2066 series). This will enable some optimizations that are not
+	  available on older ESA/390 (31 Bit) only CPUs.
+
+config MARCH_Z990
+	bool "IBM zSeries model z890 and z990"
+	select HAVE_MARCH_Z990_FEATURES if 64BIT
+	help
+	  Select this to enable optimizations for model z890/z990 (2084 and
+	  2086 series). The kernel will be slightly faster but will not work
+	  on older machines.
+
+config MARCH_Z9_109
+	bool "IBM System z9"
+	select HAVE_MARCH_Z9_109_FEATURES if 64BIT
+	help
+	  Select this to enable optimizations for IBM System z9 (2094 and
+	  2096 series). The kernel will be slightly faster but will not work
+	  on older machines.
+
+config MARCH_Z10
+	bool "IBM System z10"
+	select HAVE_MARCH_Z10_FEATURES if 64BIT
+	help
+	  Select this to enable optimizations for IBM System z10 (2097 and
+	  2098 series). The kernel will be slightly faster but will not work
+	  on older machines.
+
+config MARCH_Z196
+	bool "IBM zEnterprise 114 and 196"
+	select HAVE_MARCH_Z196_FEATURES if 64BIT
+	help
+	  Select this to enable optimizations for IBM zEnterprise 114 and 196
+	  (2818 and 2817 series). The kernel will be slightly faster but will
+	  not work on older machines.
+
+endchoice
 
 config 64BIT
 	def_bool y
@@ -147,6 +227,24 @@ config 64BIT
 config 32BIT
 	def_bool y if !64BIT
 
+config COMPAT
+	def_bool y
+	prompt "Kernel support for 31 bit emulation"
+	depends on 64BIT
+	select COMPAT_BINFMT_ELF if BINFMT_ELF
+	select ARCH_WANT_OLD_COMPAT_IPC
+	help
+	  Select this option if you want to enable your system kernel to
+	  handle system-calls from ELF binaries for 31 bit ESA.  This option
+	  (and some other stuff like libraries and such) is needed for
+	  executing 31 bit applications.  It is safe to say "Y".
+
+config SYSVIPC_COMPAT
+	def_bool y if COMPAT && SYSVIPC
+
+config KEYS_COMPAT
+	def_bool y if COMPAT && KEYS
+
 config SMP
 	def_bool y
 	prompt "Symmetric multi-processing support"
@@ -202,6 +300,8 @@ config SCHED_BOOK
 	  Book scheduler support improves the CPU scheduler's decision making
 	  when dealing with machines that have several books.
 
+source kernel/Kconfig.preempt
+
 config MATHEMU
 	def_bool y
 	prompt "IEEE FPU emulation"
@@ -211,100 +311,35 @@ config MATHEMU
 	  on older ESA/390 machines. Say Y unless you know your machine doesn't
 	  need this.
 
-config COMPAT
-	def_bool y
-	prompt "Kernel support for 31 bit emulation"
-	depends on 64BIT
-	select COMPAT_BINFMT_ELF if BINFMT_ELF
-	select ARCH_WANT_OLD_COMPAT_IPC
-	help
-	  Select this option if you want to enable your system kernel to
-	  handle system-calls from ELF binaries for 31 bit ESA.  This option
-	  (and some other stuff like libraries and such) is needed for
-	  executing 31 bit applications.  It is safe to say "Y".
+source kernel/Kconfig.hz
 
-config SYSVIPC_COMPAT
-	def_bool y if COMPAT && SYSVIPC
+endmenu
 
-config KEYS_COMPAT
-	def_bool y if COMPAT && KEYS
+menu "Memory setup"
 
-config AUDIT_ARCH
+config ARCH_SPARSEMEM_ENABLE
 	def_bool y
+	select SPARSEMEM_VMEMMAP_ENABLE
+	select SPARSEMEM_VMEMMAP
+	select SPARSEMEM_STATIC if !64BIT
 
-config HAVE_MARCH_Z900_FEATURES
-	def_bool n
-
-config HAVE_MARCH_Z990_FEATURES
-	def_bool n
-	select HAVE_MARCH_Z900_FEATURES
-
-config HAVE_MARCH_Z9_109_FEATURES
-	def_bool n
-	select HAVE_MARCH_Z990_FEATURES
-
-config HAVE_MARCH_Z10_FEATURES
-	def_bool n
-	select HAVE_MARCH_Z9_109_FEATURES
-
-config HAVE_MARCH_Z196_FEATURES
-	def_bool n
-	select HAVE_MARCH_Z10_FEATURES
-
-comment "Code generation options"
-
-choice
-	prompt "Processor type"
-	default MARCH_G5
-
-config MARCH_G5
-	bool "System/390 model G5 and G6"
-	depends on !64BIT
-	help
-	  Select this to build a 31 bit kernel that works
-	  on all ESA/390 and z/Architecture machines.
-
-config MARCH_Z900
-	bool "IBM zSeries model z800 and z900"
-	select HAVE_MARCH_Z900_FEATURES if 64BIT
-	help
-	  Select this to enable optimizations for model z800/z900 (2064 and
-	  2066 series). This will enable some optimizations that are not
-	  available on older ESA/390 (31 Bit) only CPUs.
+config ARCH_SPARSEMEM_DEFAULT
+	def_bool y
 
-config MARCH_Z990
-	bool "IBM zSeries model z890 and z990"
-	select HAVE_MARCH_Z990_FEATURES if 64BIT
-	help
-	  Select this to enable optimizations for model z890/z990 (2084 and
-	  2086 series). The kernel will be slightly faster but will not work
-	  on older machines.
+config ARCH_SELECT_MEMORY_MODEL
+	def_bool y
 
-config MARCH_Z9_109
-	bool "IBM System z9"
-	select HAVE_MARCH_Z9_109_FEATURES if 64BIT
-	help
-	  Select this to enable optimizations for IBM System z9 (2094 and
-	  2096 series). The kernel will be slightly faster but will not work
-	  on older machines.
+config ARCH_ENABLE_MEMORY_HOTPLUG
+	def_bool y if SPARSEMEM
 
-config MARCH_Z10
-	bool "IBM System z10"
-	select HAVE_MARCH_Z10_FEATURES if 64BIT
-	help
-	  Select this to enable optimizations for IBM System z10 (2097 and
-	  2098 series). The kernel will be slightly faster but will not work
-	  on older machines.
+config ARCH_ENABLE_MEMORY_HOTREMOVE
+	def_bool y
 
-config MARCH_Z196
-	bool "IBM zEnterprise 114 and 196"
-	select HAVE_MARCH_Z196_FEATURES if 64BIT
-	help
-	  Select this to enable optimizations for IBM zEnterprise 114 and 196
-	  (2818 and 2817 series). The kernel will be slightly faster but will
-	  not work on older machines.
+config FORCE_MAX_ZONEORDER
+	int
+	default "9"
 
-endchoice
+source "mm/Kconfig"
 
 config PACK_STACK
 	def_bool y
@@ -368,34 +403,9 @@ config WARN_DYNAMIC_STACK
 
 	  Say N if you are unsure.
 
-comment "Kernel preemption"
-
-source "kernel/Kconfig.preempt"
-
-config ARCH_SPARSEMEM_ENABLE
-	def_bool y
-	select SPARSEMEM_VMEMMAP_ENABLE
-	select SPARSEMEM_VMEMMAP
-	select SPARSEMEM_STATIC if !64BIT
-
-config ARCH_SPARSEMEM_DEFAULT
-	def_bool y
-
-config ARCH_SELECT_MEMORY_MODEL
-	def_bool y
-
-config ARCH_ENABLE_MEMORY_HOTPLUG
-	def_bool y if SPARSEMEM
-
-config ARCH_ENABLE_MEMORY_HOTREMOVE
-	def_bool y
-
-config ARCH_HIBERNATION_POSSIBLE
-	def_bool y if 64BIT
-
-source "mm/Kconfig"
+endmenu
 
-comment "I/O subsystem configuration"
+menu "I/O subsystem"
 
 config QDIO
 	def_tristate y
@@ -426,13 +436,102 @@ config CHSC_SCH
 
 	  If unsure, say N.
 
-comment "Misc"
+config SCM_BUS
+	def_bool y
+	depends on 64BIT
+	prompt "SCM bus driver"
+	help
+	  Bus driver for Storage Class Memory.
+
+config EADM_SCH
+	def_tristate m
+	prompt "Support for EADM subchannels"
+	depends on SCM_BUS
+	help
+	  This driver allows usage of EADM subchannels. EADM subchannels act
+	  as a communication vehicle for SCM increments.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called eadm_sch.
+
+endmenu
+
+menu "Dump support"
+
+config CRASH_DUMP
+	bool "kernel crash dumps"
+	depends on 64BIT && SMP
+	select KEXEC
+	help
+	  Generate crash dump after being started by kexec.
+	  Crash dump kernels are loaded in the main kernel with kexec-tools
+	  into a specially reserved region and then later executed after
+	  a crash by kdump/kexec.
+	  For more details see Documentation/kdump/kdump.txt
+
+config ZFCPDUMP
+	def_bool n
+	prompt "zfcpdump support"
+	select SMP
+	help
+	  Select this option if you want to build an zfcpdump enabled kernel.
+	  Refer to <file:Documentation/s390/zfcpdump.txt> for more details on this.
+
+endmenu
+
+menu "Executable file formats / Emulations"
 
 source "fs/Kconfig.binfmt"
 
-config FORCE_MAX_ZONEORDER
-	int
-	default "9"
+config SECCOMP
+	def_bool y
+	prompt "Enable seccomp to safely compute untrusted bytecode"
+	depends on PROC_FS
+	help
+	  This kernel feature is useful for number crunching applications
+	  that may need to compute untrusted bytecode during their
+	  execution. By using pipes or other transports made available to
+	  the process as file descriptors supporting the read/write
+	  syscalls, it's possible to isolate those applications in
+	  their own address space using seccomp. Once seccomp is
+	  enabled via /proc/<pid>/seccomp, it cannot be disabled
+	  and the task is only allowed to execute a few safe syscalls
+	  defined by each seccomp mode.
+
+	  If unsure, say Y.
+
+endmenu
+
+menu "Power Management"
+
+config ARCH_HIBERNATION_POSSIBLE
+	def_bool y if 64BIT
+
+source "kernel/power/Kconfig"
+
+endmenu
+
+source "net/Kconfig"
+
+config PCMCIA
+	def_bool n
+
+config CCW
+	def_bool y
+
+source "drivers/Kconfig"
+
+source "fs/Kconfig"
+
+source "arch/s390/Kconfig.debug"
+
+source "security/Kconfig"
+
+source "crypto/Kconfig"
+
+source "lib/Kconfig"
+
+menu "Virtualization"
 
 config PFAULT
 	def_bool y
@@ -544,8 +643,6 @@ config APPLDATA_NET_SUM
 	  This can also be compiled as a module, which will be called
 	  appldata_net_sum.o.
 
-source kernel/Kconfig.hz
-
 config S390_HYPFS_FS
 	def_bool y
 	prompt "s390 hypervisor file system support"
@@ -554,90 +651,20 @@ config S390_HYPFS_FS
 	  This is a virtual file system intended to provide accounting
 	  information in an s390 hypervisor environment.
 
-config KEXEC
-	def_bool n
-	prompt "kexec system call"
-	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
-	  but is independent of hardware/microcode support.
-
-config CRASH_DUMP
-	bool "kernel crash dumps"
-	depends on 64BIT && SMP
-	select KEXEC
-	help
-	  Generate crash dump after being started by kexec.
-	  Crash dump kernels are loaded in the main kernel with kexec-tools
-	  into a specially reserved region and then later executed after
-	  a crash by kdump/kexec.
-	  For more details see Documentation/kdump/kdump.txt
-
-config ZFCPDUMP
-	def_bool n
-	prompt "zfcpdump support"
-	select SMP
-	help
-	  Select this option if you want to build an zfcpdump enabled kernel.
-	  Refer to <file:Documentation/s390/zfcpdump.txt> for more details on this.
+source "arch/s390/kvm/Kconfig"
 
 config S390_GUEST
 	def_bool y
-	prompt "s390 guest support for KVM (EXPERIMENTAL)"
+	prompt "s390 support for virtio devices (EXPERIMENTAL)"
 	depends on 64BIT && EXPERIMENTAL
 	select VIRTUALIZATION
 	select VIRTIO
-	select VIRTIO_RING
 	select VIRTIO_CONSOLE
 	help
-	  Select this option if you want to run the kernel as a guest under
-	  the KVM hypervisor. This will add detection for KVM as well  as a
-	  virtio transport. If KVM is detected, the virtio console will be
-	  the default console.
-
-config SECCOMP
-	def_bool y
-	prompt "Enable seccomp to safely compute untrusted bytecode"
-	depends on PROC_FS
-	help
-	  This kernel feature is useful for number crunching applications
-	  that may need to compute untrusted bytecode during their
-	  execution. By using pipes or other transports made available to
-	  the process as file descriptors supporting the read/write
-	  syscalls, it's possible to isolate those applications in
-	  their own address space using seccomp. Once seccomp is
-	  enabled via /proc/<pid>/seccomp, it cannot be disabled
-	  and the task is only allowed to execute a few safe syscalls
-	  defined by each seccomp mode.
-
-	  If unsure, say Y.
-
-endmenu
+	  Enabling this option adds support for virtio based paravirtual device
+	  drivers on s390.
 
-menu "Power Management"
-
-source "kernel/power/Kconfig"
+	  Select this option if you want to run the kernel as a guest under
+	  the KVM hypervisor.
 
 endmenu
-
-source "net/Kconfig"
-
-config PCMCIA
-	def_bool n
-
-config CCW
-	def_bool y
-
-source "drivers/Kconfig"
-
-source "fs/Kconfig"
-
-source "arch/s390/Kconfig.debug"
-
-source "security/Kconfig"
-
-source "crypto/Kconfig"
-
-source "lib/Kconfig"
-
-source "arch/s390/kvm/Kconfig"
diff --git a/arch/s390/boot/compressed/Makefile b/arch/s390/boot/compressed/Makefile
index 10e22c4..3ad8f61 100644
--- a/arch/s390/boot/compressed/Makefile
+++ b/arch/s390/boot/compressed/Makefile
@@ -11,6 +11,7 @@ targets	:= vmlinux.lds vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 \
 	   sizes.h head$(BITS).o
 
 KBUILD_CFLAGS := -m$(BITS) -D__KERNEL__ $(LINUX_INCLUDE) -O2
+KBUILD_CFLAGS += -DDISABLE_BRANCH_PROFILING
 KBUILD_CFLAGS += $(cflags-y)
 KBUILD_CFLAGS += $(call cc-option,-mpacked-stack)
 KBUILD_CFLAGS += $(call cc-option,-ffreestanding)
diff --git a/arch/s390/boot/compressed/misc.c b/arch/s390/boot/compressed/misc.c
index 465eca7..c4c6a1c 100644
--- a/arch/s390/boot/compressed/misc.c
+++ b/arch/s390/boot/compressed/misc.c
@@ -71,34 +71,37 @@ void *memset(void *s, int c, size_t n)
 {
 	char *xs;
 
-	if (c == 0)
-		return __builtin_memset(s, 0, n);
-
-	xs = (char *) s;
-	if (n > 0)
-		do {
-			*xs++ = c;
-		} while (--n > 0);
+	xs = s;
+	while (n--)
+		*xs++ = c;
 	return s;
 }
 
-void *memcpy(void *__dest, __const void *__src, size_t __n)
+void *memcpy(void *dest, const void *src, size_t n)
 {
-	return __builtin_memcpy(__dest, __src, __n);
+	const char *s = src;
+	char *d = dest;
+
+	while (n--)
+		*d++ = *s++;
+	return dest;
 }
 
-void *memmove(void *__dest, __const void *__src, size_t __n)
+void *memmove(void *dest, const void *src, size_t n)
 {
-	char *d;
-	const char *s;
-
-	if (__dest <= __src)
-		return __builtin_memcpy(__dest, __src, __n);
-	d = __dest + __n;
-	s = __src + __n;
-	while (__n--)
-		*--d = *--s;
-	return __dest;
+	const char *s = src;
+	char *d = dest;
+
+	if (d <= s) {
+		while (n--)
+			*d++ = *s++;
+	} else {
+		d += n;
+		s += n;
+		while (n--)
+			*--d = *--s;
+	}
+	return dest;
 }
 
 static void error(char *x)
diff --git a/arch/s390/crypto/aes_s390.c b/arch/s390/crypto/aes_s390.c
index e402a9d..da3c1a7 100644
--- a/arch/s390/crypto/aes_s390.c
+++ b/arch/s390/crypto/aes_s390.c
@@ -216,7 +216,6 @@ static struct crypto_alg aes_alg = {
 	.cra_blocksize		=	AES_BLOCK_SIZE,
 	.cra_ctxsize		=	sizeof(struct s390_aes_ctx),
 	.cra_module		=	THIS_MODULE,
-	.cra_list		=	LIST_HEAD_INIT(aes_alg.cra_list),
 	.cra_init               =       fallback_init_cip,
 	.cra_exit               =       fallback_exit_cip,
 	.cra_u			=	{
@@ -398,7 +397,6 @@ static struct crypto_alg ecb_aes_alg = {
 	.cra_ctxsize		=	sizeof(struct s390_aes_ctx),
 	.cra_type		=	&crypto_blkcipher_type,
 	.cra_module		=	THIS_MODULE,
-	.cra_list		=	LIST_HEAD_INIT(ecb_aes_alg.cra_list),
 	.cra_init		=	fallback_init_blk,
 	.cra_exit		=	fallback_exit_blk,
 	.cra_u			=	{
@@ -508,7 +506,6 @@ static struct crypto_alg cbc_aes_alg = {
 	.cra_ctxsize		=	sizeof(struct s390_aes_ctx),
 	.cra_type		=	&crypto_blkcipher_type,
 	.cra_module		=	THIS_MODULE,
-	.cra_list		=	LIST_HEAD_INIT(cbc_aes_alg.cra_list),
 	.cra_init		=	fallback_init_blk,
 	.cra_exit		=	fallback_exit_blk,
 	.cra_u			=	{
@@ -710,7 +707,6 @@ static struct crypto_alg xts_aes_alg = {
 	.cra_ctxsize		=	sizeof(struct s390_xts_ctx),
 	.cra_type		=	&crypto_blkcipher_type,
 	.cra_module		=	THIS_MODULE,
-	.cra_list		=	LIST_HEAD_INIT(xts_aes_alg.cra_list),
 	.cra_init		=	xts_fallback_init,
 	.cra_exit		=	xts_fallback_exit,
 	.cra_u			=	{
@@ -832,7 +828,6 @@ static struct crypto_alg ctr_aes_alg = {
 	.cra_ctxsize		=	sizeof(struct s390_aes_ctx),
 	.cra_type		=	&crypto_blkcipher_type,
 	.cra_module		=	THIS_MODULE,
-	.cra_list		=	LIST_HEAD_INIT(ctr_aes_alg.cra_list),
 	.cra_u			=	{
 		.blkcipher = {
 			.min_keysize		=	AES_MIN_KEY_SIZE,
diff --git a/arch/s390/crypto/des_s390.c b/arch/s390/crypto/des_s390.c
index 1eaa371..b49fb96 100644
--- a/arch/s390/crypto/des_s390.c
+++ b/arch/s390/crypto/des_s390.c
@@ -70,7 +70,6 @@ static struct crypto_alg des_alg = {
 	.cra_blocksize		=	DES_BLOCK_SIZE,
 	.cra_ctxsize		=	sizeof(struct s390_des_ctx),
 	.cra_module		=	THIS_MODULE,
-	.cra_list		=	LIST_HEAD_INIT(des_alg.cra_list),
 	.cra_u			=	{
 		.cipher = {
 			.cia_min_keysize	=	DES_KEY_SIZE,
@@ -163,7 +162,6 @@ static struct crypto_alg ecb_des_alg = {
 	.cra_ctxsize		=	sizeof(struct s390_des_ctx),
 	.cra_type		=	&crypto_blkcipher_type,
 	.cra_module		=	THIS_MODULE,
-	.cra_list		=	LIST_HEAD_INIT(ecb_des_alg.cra_list),
 	.cra_u			=	{
 		.blkcipher = {
 			.min_keysize		=	DES_KEY_SIZE,
@@ -206,7 +204,6 @@ static struct crypto_alg cbc_des_alg = {
 	.cra_ctxsize		=	sizeof(struct s390_des_ctx),
 	.cra_type		=	&crypto_blkcipher_type,
 	.cra_module		=	THIS_MODULE,
-	.cra_list		=	LIST_HEAD_INIT(cbc_des_alg.cra_list),
 	.cra_u			=	{
 		.blkcipher = {
 			.min_keysize		=	DES_KEY_SIZE,
@@ -271,7 +268,6 @@ static struct crypto_alg des3_alg = {
 	.cra_blocksize		=	DES_BLOCK_SIZE,
 	.cra_ctxsize		=	sizeof(struct s390_des_ctx),
 	.cra_module		=	THIS_MODULE,
-	.cra_list		=	LIST_HEAD_INIT(des3_alg.cra_list),
 	.cra_u			=	{
 		.cipher = {
 			.cia_min_keysize	=	DES3_KEY_SIZE,
@@ -314,8 +310,6 @@ static struct crypto_alg ecb_des3_alg = {
 	.cra_ctxsize		=	sizeof(struct s390_des_ctx),
 	.cra_type		=	&crypto_blkcipher_type,
 	.cra_module		=	THIS_MODULE,
-	.cra_list		=	LIST_HEAD_INIT(
-						ecb_des3_alg.cra_list),
 	.cra_u			=	{
 		.blkcipher = {
 			.min_keysize		=	DES3_KEY_SIZE,
@@ -358,8 +352,6 @@ static struct crypto_alg cbc_des3_alg = {
 	.cra_ctxsize		=	sizeof(struct s390_des_ctx),
 	.cra_type		=	&crypto_blkcipher_type,
 	.cra_module		=	THIS_MODULE,
-	.cra_list		=	LIST_HEAD_INIT(
-						cbc_des3_alg.cra_list),
 	.cra_u			=	{
 		.blkcipher = {
 			.min_keysize		=	DES3_KEY_SIZE,
@@ -452,7 +444,6 @@ static struct crypto_alg ctr_des_alg = {
 	.cra_ctxsize		=	sizeof(struct s390_des_ctx),
 	.cra_type		=	&crypto_blkcipher_type,
 	.cra_module		=	THIS_MODULE,
-	.cra_list		=	LIST_HEAD_INIT(ctr_des_alg.cra_list),
 	.cra_u			=	{
 		.blkcipher = {
 			.min_keysize		=	DES_KEY_SIZE,
@@ -496,7 +487,6 @@ static struct crypto_alg ctr_des3_alg = {
 	.cra_ctxsize		=	sizeof(struct s390_des_ctx),
 	.cra_type		=	&crypto_blkcipher_type,
 	.cra_module		=	THIS_MODULE,
-	.cra_list		=	LIST_HEAD_INIT(ctr_des3_alg.cra_list),
 	.cra_u			=	{
 		.blkcipher = {
 			.min_keysize		=	DES3_KEY_SIZE,
diff --git a/arch/s390/crypto/ghash_s390.c b/arch/s390/crypto/ghash_s390.c
index b1bd170..1ebd3a1 100644
--- a/arch/s390/crypto/ghash_s390.c
+++ b/arch/s390/crypto/ghash_s390.c
@@ -135,7 +135,6 @@ static struct shash_alg ghash_alg = {
 		.cra_blocksize		= GHASH_BLOCK_SIZE,
 		.cra_ctxsize		= sizeof(struct ghash_ctx),
 		.cra_module		= THIS_MODULE,
-		.cra_list		= LIST_HEAD_INIT(ghash_alg.base.cra_list),
 	},
 };
 
diff --git a/arch/s390/defconfig b/arch/s390/defconfig
index f39cd71..4168c76 100644
--- a/arch/s390/defconfig
+++ b/arch/s390/defconfig
@@ -16,8 +16,8 @@ CONFIG_CGROUPS=y
 CONFIG_CPUSETS=y
 CONFIG_CGROUP_CPUACCT=y
 CONFIG_RESOURCE_COUNTERS=y
-CONFIG_CGROUP_MEMCG=y
-CONFIG_CGROUP_MEM_RES_CTLR_SWAP=y
+CONFIG_MEMCG=y
+CONFIG_MEMCG_SWAP=y
 CONFIG_CGROUP_SCHED=y
 CONFIG_RT_GROUP_SCHED=y
 CONFIG_BLK_CGROUP=y
@@ -38,14 +38,12 @@ CONFIG_MODVERSIONS=y
 CONFIG_PARTITION_ADVANCED=y
 CONFIG_IBM_PARTITION=y
 CONFIG_DEFAULT_DEADLINE=y
-CONFIG_PREEMPT=y
+CONFIG_HZ_100=y
 CONFIG_MEMORY_HOTPLUG=y
 CONFIG_MEMORY_HOTREMOVE=y
 CONFIG_KSM=y
-CONFIG_BINFMT_MISC=m
-CONFIG_CMM=m
-CONFIG_HZ_100=y
 CONFIG_CRASH_DUMP=y
+CONFIG_BINFMT_MISC=m
 CONFIG_HIBERNATION=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -75,6 +73,7 @@ CONFIG_NET_CLS_RSVP=m
 CONFIG_NET_CLS_RSVP6=m
 CONFIG_NET_CLS_ACT=y
 CONFIG_NET_ACT_POLICE=y
+CONFIG_BPF_JIT=y
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_DEVTMPFS=y
 CONFIG_BLK_DEV_LOOP=m
@@ -121,7 +120,6 @@ CONFIG_DEBUG_NOTIFIERS=y
 CONFIG_RCU_TRACE=y
 CONFIG_KPROBES_SANITY_TEST=y
 CONFIG_DEBUG_FORCE_WEAK_PER_CPU=y
-CONFIG_CPU_NOTIFIER_ERROR_INJECT=m
 CONFIG_LATENCYTOP=y
 CONFIG_DEBUG_PAGEALLOC=y
 CONFIG_BLK_DEV_IO_TRACE=y
@@ -173,3 +171,4 @@ CONFIG_CRYPTO_SHA512_S390=m
 CONFIG_CRYPTO_DES_S390=m
 CONFIG_CRYPTO_AES_S390=m
 CONFIG_CRC7=m
+CONFIG_CMM=m
diff --git a/arch/s390/hypfs/inode.c b/arch/s390/hypfs/inode.c
index 6767b43..124ec1a 100644
--- a/arch/s390/hypfs/inode.c
+++ b/arch/s390/hypfs/inode.c
@@ -31,8 +31,8 @@ static struct dentry *hypfs_create_update_file(struct super_block *sb,
 					       struct dentry *dir);
 
 struct hypfs_sb_info {
-	uid_t uid;			/* uid used for files and dirs */
-	gid_t gid;			/* gid used for files and dirs */
+	kuid_t uid;			/* uid used for files and dirs */
+	kgid_t gid;			/* gid used for files and dirs */
 	struct dentry *update_file;	/* file to trigger update */
 	time_t last_update;		/* last update time in secs since 1970 */
 	struct mutex lock;		/* lock to protect update process */
@@ -229,6 +229,8 @@ static int hypfs_parse_options(char *options, struct super_block *sb)
 {
 	char *str;
 	substring_t args[MAX_OPT_ARGS];
+	kuid_t uid;
+	kgid_t gid;
 
 	if (!options)
 		return 0;
@@ -243,12 +245,18 @@ static int hypfs_parse_options(char *options, struct super_block *sb)
 		case opt_uid:
 			if (match_int(&args[0], &option))
 				return -EINVAL;
-			hypfs_info->uid = option;
+			uid = make_kuid(current_user_ns(), option);
+			if (!uid_valid(uid))
+				return -EINVAL;
+			hypfs_info->uid = uid;
 			break;
 		case opt_gid:
 			if (match_int(&args[0], &option))
 				return -EINVAL;
-			hypfs_info->gid = option;
+			gid = make_kgid(current_user_ns(), option);
+			if (!gid_valid(gid))
+				return -EINVAL;
+			hypfs_info->gid = gid;
 			break;
 		case opt_err:
 		default:
@@ -263,8 +271,8 @@ static int hypfs_show_options(struct seq_file *s, struct dentry *root)
 {
 	struct hypfs_sb_info *hypfs_info = root->d_sb->s_fs_info;
 
-	seq_printf(s, ",uid=%u", hypfs_info->uid);
-	seq_printf(s, ",gid=%u", hypfs_info->gid);
+	seq_printf(s, ",uid=%u", from_kuid_munged(&init_user_ns, hypfs_info->uid));
+	seq_printf(s, ",gid=%u", from_kgid_munged(&init_user_ns, hypfs_info->gid));
 	return 0;
 }
 
diff --git a/arch/s390/include/asm/appldata.h b/arch/s390/include/asm/appldata.h
index f328294..32a7059 100644
--- a/arch/s390/include/asm/appldata.h
+++ b/arch/s390/include/asm/appldata.h
@@ -70,7 +70,7 @@ static inline int appldata_asm(struct appldata_product_id *id,
 	int ry;
 
 	if (!MACHINE_IS_VM)
-		return -ENOSYS;
+		return -EOPNOTSUPP;
 	parm_list.diag = 0xdc;
 	parm_list.function = fn;
 	parm_list.parlist_length = sizeof(parm_list);
diff --git a/arch/s390/include/asm/chsc.h b/arch/s390/include/asm/chsc.h
index bf115b4..aea451f 100644
--- a/arch/s390/include/asm/chsc.h
+++ b/arch/s390/include/asm/chsc.h
@@ -125,32 +125,4 @@ struct chsc_cpd_info {
 #define CHSC_INFO_CPD _IOWR(CHSC_IOCTL_MAGIC, 0x87, struct chsc_cpd_info)
 #define CHSC_INFO_DCAL _IOWR(CHSC_IOCTL_MAGIC, 0x88, struct chsc_dcal)
 
-#ifdef __KERNEL__
-
-struct css_general_char {
-	u64 : 12;
-	u32 dynio : 1;	 /* bit 12 */
-	u32 : 28;
-	u32 aif : 1;	 /* bit 41 */
-	u32 : 3;
-	u32 mcss : 1;	 /* bit 45 */
-	u32 fcs : 1;	 /* bit 46 */
-	u32 : 1;
-	u32 ext_mb : 1;  /* bit 48 */
-	u32 : 7;
-	u32 aif_tdd : 1; /* bit 56 */
-	u32 : 1;
-	u32 qebsm : 1;	 /* bit 58 */
-	u32 : 8;
-	u32 aif_osa : 1; /* bit 67 */
-	u32 : 14;
-	u32 cib : 1;	 /* bit 82 */
-	u32 : 5;
-	u32 fcx : 1;	 /* bit 88 */
-	u32 : 7;
-}__attribute__((packed));
-
-extern struct css_general_char css_general_characteristics;
-
-#endif /* __KERNEL__ */
 #endif
diff --git a/arch/s390/include/asm/cio.h b/arch/s390/include/asm/cio.h
index 77043aa..55bde60 100644
--- a/arch/s390/include/asm/cio.h
+++ b/arch/s390/include/asm/cio.h
@@ -80,6 +80,18 @@ struct erw {
 } __attribute__ ((packed));
 
 /**
+ * struct erw_eadm - EADM Subchannel extended report word
+ * @b: aob error
+ * @r: arsb error
+ */
+struct erw_eadm {
+	__u32 : 16;
+	__u32 b : 1;
+	__u32 r : 1;
+	__u32  : 14;
+} __packed;
+
+/**
  * struct sublog - subchannel logout area
  * @res0: reserved
  * @esf: extended status flags
@@ -170,9 +182,22 @@ struct esw3 {
 } __attribute__ ((packed));
 
 /**
+ * struct esw_eadm - EADM Subchannel Extended Status Word (ESW)
+ * @sublog: subchannel logout
+ * @erw: extended report word
+ */
+struct esw_eadm {
+	__u32 sublog;
+	struct erw_eadm erw;
+	__u32 : 32;
+	__u32 : 32;
+	__u32 : 32;
+} __packed;
+
+/**
  * struct irb - interruption response block
  * @scsw: subchannel status word
- * @esw: extened status word, 4 formats
+ * @esw: extened status word
  * @ecw: extended control word
  *
  * The irb that is handed to the device driver when an interrupt occurs. For
@@ -191,6 +216,7 @@ struct irb {
 		struct esw1 esw1;
 		struct esw2 esw2;
 		struct esw3 esw3;
+		struct esw_eadm eadm;
 	} esw;
 	__u8   ecw[32];
 } __attribute__ ((packed,aligned(4)));
diff --git a/arch/s390/include/asm/cmpxchg.h b/arch/s390/include/asm/cmpxchg.h
index 8d798e9..8c43d71 100644
--- a/arch/s390/include/asm/cmpxchg.h
+++ b/arch/s390/include/asm/cmpxchg.h
@@ -7,7 +7,9 @@
 #ifndef __ASM_CMPXCHG_H
 #define __ASM_CMPXCHG_H
 
+#include <linux/mmdebug.h>
 #include <linux/types.h>
+#include <linux/bug.h>
 
 extern void __xchg_called_with_bad_pointer(void);
 
@@ -203,6 +205,64 @@ static inline unsigned long long __cmpxchg64(void *ptr,
 })
 #endif /* CONFIG_64BIT */
 
+#define __cmpxchg_double_op(p1, p2, o1, o2, n1, n2, insn)		\
+({									\
+	register __typeof__(*(p1)) __old1 asm("2") = (o1);		\
+	register __typeof__(*(p2)) __old2 asm("3") = (o2);		\
+	register __typeof__(*(p1)) __new1 asm("4") = (n1);		\
+	register __typeof__(*(p2)) __new2 asm("5") = (n2);		\
+	int cc;								\
+	asm volatile(							\
+			insn   " %1,%3,%5\n"				\
+		"	ipm	%0\n"					\
+		"	srl	%0,28"					\
+		: "=d" (cc), "+d" (__old1), "+d" (__old2)		\
+		: "d" (__new1), "d" (__new2), "Q" (*(p1)), "Q" (*(p2))	\
+		: "memory", "cc");					\
+	!cc;								\
+})
+
+#define __cmpxchg_double_4(p1, p2, o1, o2, n1, n2) \
+	__cmpxchg_double_op(p1, p2, o1, o2, n1, n2, "cds")
+
+#define __cmpxchg_double_8(p1, p2, o1, o2, n1, n2) \
+	__cmpxchg_double_op(p1, p2, o1, o2, n1, n2, "cdsg")
+
+extern void __cmpxchg_double_called_with_bad_pointer(void);
+
+#define __cmpxchg_double(p1, p2, o1, o2, n1, n2)			\
+({									\
+	int __ret;							\
+	switch (sizeof(*(p1))) {					\
+	case 4:								\
+		__ret = __cmpxchg_double_4(p1, p2, o1, o2, n1, n2);	\
+		break;							\
+	case 8:								\
+		__ret = __cmpxchg_double_8(p1, p2, o1, o2, n1, n2);	\
+		break;							\
+	default:							\
+		__cmpxchg_double_called_with_bad_pointer();		\
+	}								\
+	__ret;								\
+})
+
+#define cmpxchg_double(p1, p2, o1, o2, n1, n2)				\
+({									\
+	__typeof__(p1) __p1 = (p1);					\
+	__typeof__(p2) __p2 = (p2);					\
+	int __ret;							\
+	BUILD_BUG_ON(sizeof(*(p1)) != sizeof(long));			\
+	BUILD_BUG_ON(sizeof(*(p2)) != sizeof(long));			\
+	VM_BUG_ON((unsigned long)((__p1) + 1) != (unsigned long)(__p2));\
+	if (sizeof(long) == 4)						\
+		__ret = __cmpxchg_double_4(__p1, __p2, o1, o2, n1, n2);	\
+	else								\
+		__ret = __cmpxchg_double_8(__p1, __p2, o1, o2, n1, n2);	\
+	__ret;								\
+})
+
+#define system_has_cmpxchg_double()	1
+
 #include <asm-generic/cmpxchg-local.h>
 
 static inline unsigned long __cmpxchg_local(void *ptr,
diff --git a/arch/s390/include/asm/compat.h b/arch/s390/include/asm/compat.h
index 234f1d8..a34a9d6 100644
--- a/arch/s390/include/asm/compat.h
+++ b/arch/s390/include/asm/compat.h
@@ -65,6 +65,7 @@ typedef s64		compat_s64;
 typedef u32		compat_uint_t;
 typedef u32		compat_ulong_t;
 typedef u64		compat_u64;
+typedef u32		compat_uptr_t;
 
 struct compat_timespec {
 	compat_time_t	tv_sec;
@@ -144,6 +145,79 @@ typedef u32		compat_old_sigset_t;	/* at least 32 bits */
 
 typedef u32		compat_sigset_word;
 
+typedef union compat_sigval {
+	compat_int_t	sival_int;
+	compat_uptr_t	sival_ptr;
+} compat_sigval_t;
+
+typedef struct compat_siginfo {
+	int	si_signo;
+	int	si_errno;
+	int	si_code;
+
+	union {
+		int _pad[128/sizeof(int) - 3];
+
+		/* kill() */
+		struct {
+			pid_t	_pid;	/* sender's pid */
+			uid_t	_uid;	/* sender's uid */
+		} _kill;
+
+		/* POSIX.1b timers */
+		struct {
+			compat_timer_t _tid;		/* timer id */
+			int _overrun;			/* overrun count */
+			compat_sigval_t _sigval;	/* same as below */
+			int _sys_private;	/* not to be passed to user */
+		} _timer;
+
+		/* POSIX.1b signals */
+		struct {
+			pid_t			_pid;	/* sender's pid */
+			uid_t			_uid;	/* sender's uid */
+			compat_sigval_t		_sigval;
+		} _rt;
+
+		/* SIGCHLD */
+		struct {
+			pid_t			_pid;	/* which child */
+			uid_t			_uid;	/* sender's uid */
+			int			_status;/* exit code */
+			compat_clock_t		_utime;
+			compat_clock_t		_stime;
+		} _sigchld;
+
+		/* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
+		struct {
+			__u32	_addr;	/* faulting insn/memory ref. - pointer */
+		} _sigfault;
+
+		/* SIGPOLL */
+		struct {
+			int	_band;	/* POLL_IN, POLL_OUT, POLL_MSG */
+			int	_fd;
+		} _sigpoll;
+	} _sifields;
+} compat_siginfo_t;
+
+/*
+ * How these fields are to be accessed.
+ */
+#define si_pid		_sifields._kill._pid
+#define si_uid		_sifields._kill._uid
+#define si_status	_sifields._sigchld._status
+#define si_utime	_sifields._sigchld._utime
+#define si_stime	_sifields._sigchld._stime
+#define si_value	_sifields._rt._sigval
+#define si_int		_sifields._rt._sigval.sival_int
+#define si_ptr		_sifields._rt._sigval.sival_ptr
+#define si_addr		_sifields._sigfault._addr
+#define si_band		_sifields._sigpoll._band
+#define si_fd		_sifields._sigpoll._fd
+#define si_tid		_sifields._timer._tid
+#define si_overrun	_sifields._timer._overrun
+
 #define COMPAT_OFF_T_MAX	0x7fffffff
 #define COMPAT_LOFF_T_MAX	0x7fffffffffffffffL
 
@@ -153,7 +227,6 @@ typedef u32		compat_sigset_word;
  * as pointers because the syscall entry code will have
  * appropriately converted them already.
  */
-typedef	u32		compat_uptr_t;
 
 static inline void __user *compat_ptr(compat_uptr_t uptr)
 {
diff --git a/arch/s390/include/asm/cpu_mf.h b/arch/s390/include/asm/cpu_mf.h
index a3afecd..35f0020 100644
--- a/arch/s390/include/asm/cpu_mf.h
+++ b/arch/s390/include/asm/cpu_mf.h
@@ -21,11 +21,15 @@
 #define CPU_MF_INT_SF_LSDA	(1 << 22)	/* loss of sample data alert */
 #define CPU_MF_INT_CF_CACA	(1 <<  7)	/* counter auth. change alert */
 #define CPU_MF_INT_CF_LCDA	(1 <<  6)	/* loss of counter data alert */
+#define CPU_MF_INT_RI_HALTED	(1 <<  5)	/* run-time instr. halted */
+#define CPU_MF_INT_RI_BUF_FULL	(1 <<  4)	/* run-time instr. program
+						   buffer full */
 
 #define CPU_MF_INT_CF_MASK	(CPU_MF_INT_CF_CACA|CPU_MF_INT_CF_LCDA)
 #define CPU_MF_INT_SF_MASK	(CPU_MF_INT_SF_IAE|CPU_MF_INT_SF_ISE|	\
 				 CPU_MF_INT_SF_PRA|CPU_MF_INT_SF_SACA|	\
 				 CPU_MF_INT_SF_LSDA)
+#define CPU_MF_INT_RI_MASK	(CPU_MF_INT_RI_HALTED|CPU_MF_INT_RI_BUF_FULL)
 
 /* CPU measurement facility support */
 static inline int cpum_cf_avail(void)
diff --git a/arch/s390/include/asm/css_chars.h b/arch/s390/include/asm/css_chars.h
new file mode 100644
index 0000000..a06ebc2
--- /dev/null
+++ b/arch/s390/include/asm/css_chars.h
@@ -0,0 +1,39 @@
+#ifndef _ASM_CSS_CHARS_H
+#define _ASM_CSS_CHARS_H
+
+#include <linux/types.h>
+
+#ifdef __KERNEL__
+
+struct css_general_char {
+	u64 : 12;
+	u32 dynio : 1;	 /* bit 12 */
+	u32 : 4;
+	u32 eadm : 1;	 /* bit 17 */
+	u32 : 23;
+	u32 aif : 1;	 /* bit 41 */
+	u32 : 3;
+	u32 mcss : 1;	 /* bit 45 */
+	u32 fcs : 1;	 /* bit 46 */
+	u32 : 1;
+	u32 ext_mb : 1;  /* bit 48 */
+	u32 : 7;
+	u32 aif_tdd : 1; /* bit 56 */
+	u32 : 1;
+	u32 qebsm : 1;	 /* bit 58 */
+	u32 : 8;
+	u32 aif_osa : 1; /* bit 67 */
+	u32 : 12;
+	u32 eadm_rf : 1; /* bit 80 */
+	u32 : 1;
+	u32 cib : 1;	 /* bit 82 */
+	u32 : 5;
+	u32 fcx : 1;	 /* bit 88 */
+	u32 : 19;
+	u32 alt_ssi : 1; /* bit 108 */
+} __packed;
+
+extern struct css_general_char css_general_characteristics;
+
+#endif /* __KERNEL__ */
+#endif
diff --git a/arch/s390/include/asm/eadm.h b/arch/s390/include/asm/eadm.h
new file mode 100644
index 0000000..8d48471
--- /dev/null
+++ b/arch/s390/include/asm/eadm.h
@@ -0,0 +1,124 @@
+#ifndef _ASM_S390_EADM_H
+#define _ASM_S390_EADM_H
+
+#include <linux/types.h>
+#include <linux/device.h>
+
+struct arqb {
+	u64 data;
+	u16 fmt:4;
+	u16:12;
+	u16 cmd_code;
+	u16:16;
+	u16 msb_count;
+	u32 reserved[12];
+} __packed;
+
+#define ARQB_CMD_MOVE	1
+
+struct arsb {
+	u16 fmt:4;
+	u32:28;
+	u8 ef;
+	u8:8;
+	u8 ecbi;
+	u8:8;
+	u8 fvf;
+	u16:16;
+	u8 eqc;
+	u32:32;
+	u64 fail_msb;
+	u64 fail_aidaw;
+	u64 fail_ms;
+	u64 fail_scm;
+	u32 reserved[4];
+} __packed;
+
+struct msb {
+	u8 fmt:4;
+	u8 oc:4;
+	u8 flags;
+	u16:12;
+	u16 bs:4;
+	u32 blk_count;
+	u64 data_addr;
+	u64 scm_addr;
+	u64:64;
+} __packed;
+
+struct aidaw {
+	u8 flags;
+	u32 :24;
+	u32 :32;
+	u64 data_addr;
+} __packed;
+
+#define MSB_OC_CLEAR	0
+#define MSB_OC_READ	1
+#define MSB_OC_WRITE	2
+#define MSB_OC_RELEASE	3
+
+#define MSB_FLAG_BNM	0x80
+#define MSB_FLAG_IDA	0x40
+
+#define MSB_BS_4K	0
+#define MSB_BS_1M	1
+
+#define AOB_NR_MSB	124
+
+struct aob {
+	struct arqb request;
+	struct arsb response;
+	struct msb msb[AOB_NR_MSB];
+} __packed __aligned(PAGE_SIZE);
+
+struct aob_rq_header {
+	struct scm_device *scmdev;
+	char data[0];
+};
+
+struct scm_device {
+	u64 address;
+	u64 size;
+	unsigned int nr_max_block;
+	struct device dev;
+	struct {
+		unsigned int persistence:4;
+		unsigned int oper_state:4;
+		unsigned int data_state:4;
+		unsigned int rank:4;
+		unsigned int release:1;
+		unsigned int res_id:8;
+	} __packed attrs;
+};
+
+#define OP_STATE_GOOD		1
+#define OP_STATE_TEMP_ERR	2
+#define OP_STATE_PERM_ERR	3
+
+struct scm_driver {
+	struct device_driver drv;
+	int (*probe) (struct scm_device *scmdev);
+	int (*remove) (struct scm_device *scmdev);
+	void (*notify) (struct scm_device *scmdev);
+	void (*handler) (struct scm_device *scmdev, void *data, int error);
+};
+
+int scm_driver_register(struct scm_driver *scmdrv);
+void scm_driver_unregister(struct scm_driver *scmdrv);
+
+int scm_start_aob(struct aob *aob);
+void scm_irq_handler(struct aob *aob, int error);
+
+struct eadm_ops {
+	int (*eadm_start) (struct aob *aob);
+	struct module *owner;
+};
+
+int scm_get_ref(void);
+void scm_put_ref(void);
+
+void register_eadm_ops(struct eadm_ops *ops);
+void unregister_eadm_ops(struct eadm_ops *ops);
+
+#endif /* _ASM_S390_EADM_H */
diff --git a/arch/s390/include/asm/elf.h b/arch/s390/include/asm/elf.h
index 9b94a16..178ff96 100644
--- a/arch/s390/include/asm/elf.h
+++ b/arch/s390/include/asm/elf.h
@@ -101,6 +101,7 @@
 #define HWCAP_S390_HPAGE	128
 #define HWCAP_S390_ETF3EH	256
 #define HWCAP_S390_HIGH_GPRS	512
+#define HWCAP_S390_TE		1024
 
 /*
  * These are used to set parameters in the core dumps.
@@ -212,4 +213,6 @@ int arch_setup_additional_pages(struct linux_binprm *, int);
 extern unsigned long arch_randomize_brk(struct mm_struct *mm);
 #define arch_randomize_brk arch_randomize_brk
 
+void *fill_cpu_elf_notes(void *ptr, struct save_area *sa);
+
 #endif
diff --git a/arch/s390/include/asm/etr.h b/arch/s390/include/asm/etr.h
index a24b03b..629b79a 100644
--- a/arch/s390/include/asm/etr.h
+++ b/arch/s390/include/asm/etr.h
@@ -140,7 +140,7 @@ struct etr_ptff_qto {
 /* Inline assembly helper functions */
 static inline int etr_setr(struct etr_eacr *ctrl)
 {
-	int rc = -ENOSYS;
+	int rc = -EOPNOTSUPP;
 
 	asm volatile(
 		"	.insn	s,0xb2160000,%1\n"
@@ -154,7 +154,7 @@ static inline int etr_setr(struct etr_eacr *ctrl)
 /* Stores a format 1 aib with 64 bytes */
 static inline int etr_stetr(struct etr_aib *aib)
 {
-	int rc = -ENOSYS;
+	int rc = -EOPNOTSUPP;
 
 	asm volatile(
 		"	.insn	s,0xb2170000,%1\n"
@@ -169,7 +169,7 @@ static inline int etr_stetr(struct etr_aib *aib)
 static inline int etr_steai(struct etr_aib *aib, unsigned int func)
 {
 	register unsigned int reg0 asm("0") = func;
-	int rc = -ENOSYS;
+	int rc = -EOPNOTSUPP;
 
 	asm volatile(
 		"	.insn	s,0xb2b30000,%1\n"
@@ -190,7 +190,7 @@ static inline int etr_ptff(void *ptff_block, unsigned int func)
 {
 	register unsigned int reg0 asm("0") = func;
 	register unsigned long reg1 asm("1") = (unsigned long) ptff_block;
-	int rc = -ENOSYS;
+	int rc = -EOPNOTSUPP;
 
 	asm volatile(
 		"	.word	0x0104\n"
diff --git a/arch/s390/include/asm/hugetlb.h b/arch/s390/include/asm/hugetlb.h
index 2d6e6e3..593753e 100644
--- a/arch/s390/include/asm/hugetlb.h
+++ b/arch/s390/include/asm/hugetlb.h
@@ -33,6 +33,7 @@ static inline int prepare_hugepage_range(struct file *file,
 }
 
 #define hugetlb_prefault_arch_hook(mm)		do { } while (0)
+#define arch_clear_hugepage_flags(page)		do { } while (0)
 
 int arch_prepare_hugepage(struct page *page);
 void arch_release_hugepage(struct page *page);
@@ -77,23 +78,6 @@ static inline void __pmd_csp(pmd_t *pmdp)
 		"	csp %1,%3"
 		: "=m" (*pmdp)
 		: "d" (reg2), "d" (reg3), "d" (reg4), "m" (*pmdp) : "cc");
-	pmd_val(*pmdp) = _SEGMENT_ENTRY_INV | _SEGMENT_ENTRY;
-}
-
-static inline void __pmd_idte(unsigned long address, pmd_t *pmdp)
-{
-	unsigned long sto = (unsigned long) pmdp -
-				pmd_index(address) * sizeof(pmd_t);
-
-	if (!(pmd_val(*pmdp) & _SEGMENT_ENTRY_INV)) {
-		asm volatile(
-			"	.insn	rrf,0xb98e0000,%2,%3,0,0"
-			: "=m" (*pmdp)
-			: "m" (*pmdp), "a" (sto),
-			  "a" ((address & HPAGE_MASK))
-		);
-	}
-	pmd_val(*pmdp) = _SEGMENT_ENTRY_INV | _SEGMENT_ENTRY;
 }
 
 static inline void huge_ptep_invalidate(struct mm_struct *mm,
@@ -105,6 +89,7 @@ static inline void huge_ptep_invalidate(struct mm_struct *mm,
 		__pmd_idte(address, pmdp);
 	else
 		__pmd_csp(pmdp);
+	pmd_val(*pmdp) = _SEGMENT_ENTRY_INV | _SEGMENT_ENTRY;
 }
 
 static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
diff --git a/arch/s390/include/asm/irq.h b/arch/s390/include/asm/irq.h
index 2b9d418..6703dd9 100644
--- a/arch/s390/include/asm/irq.h
+++ b/arch/s390/include/asm/irq.h
@@ -19,6 +19,7 @@ enum interruption_class {
 	EXTINT_IUC,
 	EXTINT_CMS,
 	EXTINT_CMC,
+	EXTINT_CMR,
 	IOINT_CIO,
 	IOINT_QAI,
 	IOINT_DAS,
@@ -30,6 +31,7 @@ enum interruption_class {
 	IOINT_CLW,
 	IOINT_CTC,
 	IOINT_APB,
+	IOINT_ADM,
 	IOINT_CSC,
 	NMI_NMI,
 	NR_IRQS,
diff --git a/arch/s390/include/asm/isc.h b/arch/s390/include/asm/isc.h
index 1420a11..5ae6064 100644
--- a/arch/s390/include/asm/isc.h
+++ b/arch/s390/include/asm/isc.h
@@ -14,6 +14,7 @@
 /* Regular I/O interrupts. */
 #define IO_SCH_ISC 3			/* regular I/O subchannels */
 #define CONSOLE_ISC 1			/* console I/O subchannel */
+#define EADM_SCH_ISC 4			/* EADM subchannels */
 #define CHSC_SCH_ISC 7			/* CHSC subchannels */
 /* Adapter interrupts. */
 #define QDIO_AIRQ_ISC IO_SCH_ISC	/* I/O subchannel in qdio mode */
diff --git a/arch/s390/include/asm/lowcore.h b/arch/s390/include/asm/lowcore.h
index aab5555..bbf8141 100644
--- a/arch/s390/include/asm/lowcore.h
+++ b/arch/s390/include/asm/lowcore.h
@@ -329,9 +329,13 @@ struct _lowcore {
 	__u8	pad_0x1338[0x1340-0x1338];	/* 0x1338 */
 	__u32	access_regs_save_area[16];	/* 0x1340 */
 	__u64	cregs_save_area[16];		/* 0x1380 */
+	__u8	pad_0x1400[0x1800-0x1400];	/* 0x1400 */
+
+	/* Transaction abort diagnostic block */
+	__u8	pgm_tdb[256];			/* 0x1800 */
 
 	/* align to the top of the prefix area */
-	__u8	pad_0x1400[0x2000-0x1400];	/* 0x1400 */
+	__u8	pad_0x1900[0x2000-0x1900];	/* 0x1900 */
 } __packed;
 
 #endif /* CONFIG_32BIT */
diff --git a/arch/s390/include/asm/mmu_context.h b/arch/s390/include/asm/mmu_context.h
index b749c57..084e775 100644
--- a/arch/s390/include/asm/mmu_context.h
+++ b/arch/s390/include/asm/mmu_context.h
@@ -57,7 +57,7 @@ static inline void update_mm(struct mm_struct *mm, struct task_struct *tsk)
 	pgd_t *pgd = mm->pgd;
 
 	S390_lowcore.user_asce = mm->context.asce_bits | __pa(pgd);
-	if (addressing_mode != HOME_SPACE_MODE) {
+	if (s390_user_mode != HOME_SPACE_MODE) {
 		/* Load primary space page table origin. */
 		asm volatile(LCTL_OPCODE" 1,1,%0\n"
 			     : : "m" (S390_lowcore.user_asce) );
diff --git a/arch/s390/include/asm/module.h b/arch/s390/include/asm/module.h
index f0b6b26..df1f861 100644
--- a/arch/s390/include/asm/module.h
+++ b/arch/s390/include/asm/module.h
@@ -1,5 +1,8 @@
 #ifndef _ASM_S390_MODULE_H
 #define _ASM_S390_MODULE_H
+
+#include <asm-generic/module.h>
+
 /*
  * This file contains the s390 architecture specific module code.
  */
@@ -28,19 +31,4 @@ struct mod_arch_specific
 	struct mod_arch_syminfo *syminfo;
 };
 
-#ifdef CONFIG_64BIT
-#define ElfW(x) Elf64_ ## x
-#define ELFW(x) ELF64_ ## x
-#else
-#define ElfW(x) Elf32_ ## x
-#define ELFW(x) ELF32_ ## x
-#endif
-
-#define Elf_Addr ElfW(Addr)
-#define Elf_Rela ElfW(Rela)
-#define Elf_Shdr ElfW(Shdr)
-#define Elf_Sym ElfW(Sym)
-#define Elf_Ehdr ElfW(Ehdr)
-#define ELF_R_SYM ELFW(R_SYM)
-#define ELF_R_TYPE ELFW(R_TYPE)
 #endif /* _ASM_S390_MODULE_H */
diff --git a/arch/s390/include/asm/percpu.h b/arch/s390/include/asm/percpu.h
index 6537e72..86fe0ee 100644
--- a/arch/s390/include/asm/percpu.h
+++ b/arch/s390/include/asm/percpu.h
@@ -20,7 +20,7 @@
 #endif
 
 #define arch_this_cpu_to_op(pcp, val, op)				\
-do {									\
+({									\
 	typedef typeof(pcp) pcp_op_T__;					\
 	pcp_op_T__ old__, new__, prev__;				\
 	pcp_op_T__ *ptr__;						\
@@ -39,13 +39,19 @@ do {									\
 		}							\
 	} while (prev__ != old__);					\
 	preempt_enable();						\
-} while (0)
+	new__;								\
+})
 
 #define this_cpu_add_1(pcp, val) arch_this_cpu_to_op(pcp, val, +)
 #define this_cpu_add_2(pcp, val) arch_this_cpu_to_op(pcp, val, +)
 #define this_cpu_add_4(pcp, val) arch_this_cpu_to_op(pcp, val, +)
 #define this_cpu_add_8(pcp, val) arch_this_cpu_to_op(pcp, val, +)
 
+#define this_cpu_add_return_1(pcp, val) arch_this_cpu_to_op(pcp, val, +)
+#define this_cpu_add_return_2(pcp, val) arch_this_cpu_to_op(pcp, val, +)
+#define this_cpu_add_return_4(pcp, val) arch_this_cpu_to_op(pcp, val, +)
+#define this_cpu_add_return_8(pcp, val) arch_this_cpu_to_op(pcp, val, +)
+
 #define this_cpu_and_1(pcp, val) arch_this_cpu_to_op(pcp, val, &)
 #define this_cpu_and_2(pcp, val) arch_this_cpu_to_op(pcp, val, &)
 #define this_cpu_and_4(pcp, val) arch_this_cpu_to_op(pcp, val, &)
@@ -61,7 +67,7 @@ do {									\
 #define this_cpu_xor_4(pcp, val) arch_this_cpu_to_op(pcp, val, ^)
 #define this_cpu_xor_8(pcp, val) arch_this_cpu_to_op(pcp, val, ^)
 
-#define arch_this_cpu_cmpxchg(pcp, oval, nval)			\
+#define arch_this_cpu_cmpxchg(pcp, oval, nval)				\
 ({									\
 	typedef typeof(pcp) pcp_op_T__;					\
 	pcp_op_T__ ret__;						\
@@ -84,6 +90,44 @@ do {									\
 #define this_cpu_cmpxchg_4(pcp, oval, nval) arch_this_cpu_cmpxchg(pcp, oval, nval)
 #define this_cpu_cmpxchg_8(pcp, oval, nval) arch_this_cpu_cmpxchg(pcp, oval, nval)
 
+#define arch_this_cpu_xchg(pcp, nval)					\
+({									\
+	typeof(pcp) *ptr__;						\
+	typeof(pcp) ret__;						\
+	preempt_disable();						\
+	ptr__ = __this_cpu_ptr(&(pcp));					\
+	ret__ = xchg(ptr__, nval);					\
+	preempt_enable();						\
+	ret__;								\
+})
+
+#define this_cpu_xchg_1(pcp, nval) arch_this_cpu_xchg(pcp, nval)
+#define this_cpu_xchg_2(pcp, nval) arch_this_cpu_xchg(pcp, nval)
+#define this_cpu_xchg_4(pcp, nval) arch_this_cpu_xchg(pcp, nval)
+#ifdef CONFIG_64BIT
+#define this_cpu_xchg_8(pcp, nval) arch_this_cpu_xchg(pcp, nval)
+#endif
+
+#define arch_this_cpu_cmpxchg_double(pcp1, pcp2, o1, o2, n1, n2)	\
+({									\
+	typeof(pcp1) o1__ = (o1), n1__ = (n1);				\
+	typeof(pcp2) o2__ = (o2), n2__ = (n2);				\
+	typeof(pcp1) *p1__;						\
+	typeof(pcp2) *p2__;						\
+	int ret__;							\
+	preempt_disable();						\
+	p1__ = __this_cpu_ptr(&(pcp1));					\
+	p2__ = __this_cpu_ptr(&(pcp2));					\
+	ret__ = __cmpxchg_double(p1__, p2__, o1__, o2__, n1__, n2__);	\
+	preempt_enable();						\
+	ret__;								\
+})
+
+#define this_cpu_cmpxchg_double_4 arch_this_cpu_cmpxchg_double
+#ifdef CONFIG_64BIT
+#define this_cpu_cmpxchg_double_8 arch_this_cpu_cmpxchg_double
+#endif
+
 #include <asm-generic/percpu.h>
 
 #endif /* __ARCH_S390_PERCPU__ */
diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h
index 6bd7d74..ed14fc2 100644
--- a/arch/s390/include/asm/pgtable.h
+++ b/arch/s390/include/asm/pgtable.h
@@ -347,6 +347,12 @@ extern struct page *vmemmap;
 
 #define _SEGMENT_ENTRY_LARGE	0x400	/* STE-format control, large page   */
 #define _SEGMENT_ENTRY_CO	0x100	/* change-recording override   */
+#define _SEGMENT_ENTRY_SPLIT_BIT 0	/* THP splitting bit number */
+#define _SEGMENT_ENTRY_SPLIT	(1UL << _SEGMENT_ENTRY_SPLIT_BIT)
+
+/* Set of bits not changed in pmd_modify */
+#define _SEGMENT_CHG_MASK	(_SEGMENT_ENTRY_ORIGIN | _SEGMENT_ENTRY_LARGE \
+				 | _SEGMENT_ENTRY_SPLIT | _SEGMENT_ENTRY_CO)
 
 /* Page status table bits for virtualization */
 #define RCP_ACC_BITS	0xf000000000000000UL
@@ -506,6 +512,30 @@ static inline int pmd_bad(pmd_t pmd)
 	return (pmd_val(pmd) & mask) != _SEGMENT_ENTRY;
 }
 
+#define __HAVE_ARCH_PMDP_SPLITTING_FLUSH
+extern void pmdp_splitting_flush(struct vm_area_struct *vma,
+				 unsigned long addr, pmd_t *pmdp);
+
+#define  __HAVE_ARCH_PMDP_SET_ACCESS_FLAGS
+extern int pmdp_set_access_flags(struct vm_area_struct *vma,
+				 unsigned long address, pmd_t *pmdp,
+				 pmd_t entry, int dirty);
+
+#define __HAVE_ARCH_PMDP_CLEAR_YOUNG_FLUSH
+extern int pmdp_clear_flush_young(struct vm_area_struct *vma,
+				  unsigned long address, pmd_t *pmdp);
+
+#define __HAVE_ARCH_PMD_WRITE
+static inline int pmd_write(pmd_t pmd)
+{
+	return (pmd_val(pmd) & _SEGMENT_ENTRY_RO) == 0;
+}
+
+static inline int pmd_young(pmd_t pmd)
+{
+	return 0;
+}
+
 static inline int pte_none(pte_t pte)
 {
 	return (pte_val(pte) & _PAGE_INVALID) && !(pte_val(pte) & _PAGE_SWT);
@@ -1159,6 +1189,185 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long address)
 #define pte_offset_map(pmd, address) pte_offset_kernel(pmd, address)
 #define pte_unmap(pte) do { } while (0)
 
+static inline void __pmd_idte(unsigned long address, pmd_t *pmdp)
+{
+	unsigned long sto = (unsigned long) pmdp -
+			    pmd_index(address) * sizeof(pmd_t);
+
+	if (!(pmd_val(*pmdp) & _SEGMENT_ENTRY_INV)) {
+		asm volatile(
+			"	.insn	rrf,0xb98e0000,%2,%3,0,0"
+			: "=m" (*pmdp)
+			: "m" (*pmdp), "a" (sto),
+			  "a" ((address & HPAGE_MASK))
+			: "cc"
+		);
+	}
+}
+
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+#define __HAVE_ARCH_PGTABLE_DEPOSIT
+extern void pgtable_trans_huge_deposit(struct mm_struct *mm, pgtable_t pgtable);
+
+#define __HAVE_ARCH_PGTABLE_WITHDRAW
+extern pgtable_t pgtable_trans_huge_withdraw(struct mm_struct *mm);
+
+static inline int pmd_trans_splitting(pmd_t pmd)
+{
+	return pmd_val(pmd) & _SEGMENT_ENTRY_SPLIT;
+}
+
+static inline void set_pmd_at(struct mm_struct *mm, unsigned long addr,
+			      pmd_t *pmdp, pmd_t entry)
+{
+	*pmdp = entry;
+}
+
+static inline unsigned long massage_pgprot_pmd(pgprot_t pgprot)
+{
+	unsigned long pgprot_pmd = 0;
+
+	if (pgprot_val(pgprot) & _PAGE_INVALID) {
+		if (pgprot_val(pgprot) & _PAGE_SWT)
+			pgprot_pmd |= _HPAGE_TYPE_NONE;
+		pgprot_pmd |= _SEGMENT_ENTRY_INV;
+	}
+	if (pgprot_val(pgprot) & _PAGE_RO)
+		pgprot_pmd |= _SEGMENT_ENTRY_RO;
+	return pgprot_pmd;
+}
+
+static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
+{
+	pmd_val(pmd) &= _SEGMENT_CHG_MASK;
+	pmd_val(pmd) |= massage_pgprot_pmd(newprot);
+	return pmd;
+}
+
+static inline pmd_t pmd_mkhuge(pmd_t pmd)
+{
+	pmd_val(pmd) |= _SEGMENT_ENTRY_LARGE;
+	return pmd;
+}
+
+static inline pmd_t pmd_mkwrite(pmd_t pmd)
+{
+	pmd_val(pmd) &= ~_SEGMENT_ENTRY_RO;
+	return pmd;
+}
+
+static inline pmd_t pmd_wrprotect(pmd_t pmd)
+{
+	pmd_val(pmd) |= _SEGMENT_ENTRY_RO;
+	return pmd;
+}
+
+static inline pmd_t pmd_mkdirty(pmd_t pmd)
+{
+	/* No dirty bit in the segment table entry. */
+	return pmd;
+}
+
+static inline pmd_t pmd_mkold(pmd_t pmd)
+{
+	/* No referenced bit in the segment table entry. */
+	return pmd;
+}
+
+static inline pmd_t pmd_mkyoung(pmd_t pmd)
+{
+	/* No referenced bit in the segment table entry. */
+	return pmd;
+}
+
+#define __HAVE_ARCH_PMDP_TEST_AND_CLEAR_YOUNG
+static inline int pmdp_test_and_clear_young(struct vm_area_struct *vma,
+					    unsigned long address, pmd_t *pmdp)
+{
+	unsigned long pmd_addr = pmd_val(*pmdp) & HPAGE_MASK;
+	long tmp, rc;
+	int counter;
+
+	rc = 0;
+	if (MACHINE_HAS_RRBM) {
+		counter = PTRS_PER_PTE >> 6;
+		asm volatile(
+			"0:	.insn	rre,0xb9ae0000,%0,%3\n"	/* rrbm */
+			"	ogr	%1,%0\n"
+			"	la	%3,0(%4,%3)\n"
+			"	brct	%2,0b\n"
+			: "=&d" (tmp), "+&d" (rc), "+d" (counter),
+			  "+a" (pmd_addr)
+			: "a" (64 * 4096UL) : "cc");
+		rc = !!rc;
+	} else {
+		counter = PTRS_PER_PTE;
+		asm volatile(
+			"0:	rrbe	0,%2\n"
+			"	la	%2,0(%3,%2)\n"
+			"	brc	12,1f\n"
+			"	lhi	%0,1\n"
+			"1:	brct	%1,0b\n"
+			: "+d" (rc), "+d" (counter), "+a" (pmd_addr)
+			: "a" (4096UL) : "cc");
+	}
+	return rc;
+}
+
+#define __HAVE_ARCH_PMDP_GET_AND_CLEAR
+static inline pmd_t pmdp_get_and_clear(struct mm_struct *mm,
+				       unsigned long address, pmd_t *pmdp)
+{
+	pmd_t pmd = *pmdp;
+
+	__pmd_idte(address, pmdp);
+	pmd_clear(pmdp);
+	return pmd;
+}
+
+#define __HAVE_ARCH_PMDP_CLEAR_FLUSH
+static inline pmd_t pmdp_clear_flush(struct vm_area_struct *vma,
+				     unsigned long address, pmd_t *pmdp)
+{
+	return pmdp_get_and_clear(vma->vm_mm, address, pmdp);
+}
+
+#define __HAVE_ARCH_PMDP_INVALIDATE
+static inline void pmdp_invalidate(struct vm_area_struct *vma,
+				   unsigned long address, pmd_t *pmdp)
+{
+	__pmd_idte(address, pmdp);
+}
+
+static inline pmd_t mk_pmd_phys(unsigned long physpage, pgprot_t pgprot)
+{
+	pmd_t __pmd;
+	pmd_val(__pmd) = physpage + massage_pgprot_pmd(pgprot);
+	return __pmd;
+}
+
+#define pfn_pmd(pfn, pgprot)	mk_pmd_phys(__pa((pfn) << PAGE_SHIFT), (pgprot))
+#define mk_pmd(page, pgprot)	pfn_pmd(page_to_pfn(page), (pgprot))
+
+static inline int pmd_trans_huge(pmd_t pmd)
+{
+	return pmd_val(pmd) & _SEGMENT_ENTRY_LARGE;
+}
+
+static inline int has_transparent_hugepage(void)
+{
+	return MACHINE_HAS_HPAGE ? 1 : 0;
+}
+
+static inline unsigned long pmd_pfn(pmd_t pmd)
+{
+	if (pmd_trans_huge(pmd))
+		return pmd_val(pmd) >> HPAGE_SHIFT;
+	else
+		return pmd_val(pmd) >> PAGE_SHIFT;
+}
+#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
+
 /*
  * 31 bit swap entry format:
  * A page-table entry has some bits we have to treat in a special way.
diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h
index 11e4e32..94e749c 100644
--- a/arch/s390/include/asm/processor.h
+++ b/arch/s390/include/asm/processor.h
@@ -11,12 +11,15 @@
 #ifndef __ASM_S390_PROCESSOR_H
 #define __ASM_S390_PROCESSOR_H
 
+#ifndef __ASSEMBLY__
+
 #include <linux/linkage.h>
 #include <linux/irqflags.h>
 #include <asm/cpu.h>
 #include <asm/page.h>
 #include <asm/ptrace.h>
 #include <asm/setup.h>
+#include <asm/runtime_instr.h>
 
 /*
  * Default implementation of macro that returns current
@@ -32,6 +35,7 @@ static inline void get_cpu_id(struct cpuid *ptr)
 extern void s390_adjust_jiffies(void);
 extern const struct seq_operations cpuinfo_op;
 extern int sysctl_ieee_emulation_warnings;
+extern void execve_tail(void);
 
 /*
  * User space process size: 2GB for 31 bit, 4TB or 8PT for 64 bit.
@@ -75,11 +79,20 @@ struct thread_struct {
 	unsigned long gmap_addr;	/* address of last gmap fault. */
 	struct per_regs per_user;	/* User specified PER registers */
 	struct per_event per_event;	/* Cause of the last PER trap */
+	unsigned long per_flags;	/* Flags to control debug behavior */
         /* pfault_wait is used to block the process on a pfault event */
 	unsigned long pfault_wait;
 	struct list_head list;
+	/* cpu runtime instrumentation */
+	struct runtime_instr_cb *ri_cb;
+	int ri_signum;
+#ifdef CONFIG_64BIT
+	unsigned char trap_tdb[256];	/* Transaction abort diagnose block */
+#endif
 };
 
+#define PER_FLAG_NO_TE		1UL	/* Flag to disable transactions. */
+
 typedef struct thread_struct thread_struct;
 
 /*
@@ -114,6 +127,7 @@ struct stack_frame {
 	regs->psw.mask	= psw_user_bits | PSW_MASK_EA | PSW_MASK_BA;	\
 	regs->psw.addr	= new_psw | PSW_ADDR_AMODE;			\
 	regs->gprs[15]	= new_stackp;					\
+	execve_tail();							\
 } while (0)
 
 #define start_thread31(regs, new_psw, new_stackp) do {			\
@@ -123,6 +137,7 @@ struct stack_frame {
 	__tlb_flush_mm(current->mm);					\
 	crst_table_downgrade(current->mm, 1UL << 31);			\
 	update_mm(current->mm, current);				\
+	execve_tail();							\
 } while (0)
 
 /* Forward declaration, a strange C thing */
@@ -130,9 +145,14 @@ struct task_struct;
 struct mm_struct;
 struct seq_file;
 
+#ifdef CONFIG_64BIT
+extern void show_cacheinfo(struct seq_file *m);
+#else
+static inline void show_cacheinfo(struct seq_file *m) { }
+#endif
+
 /* Free all resources held by a thread. */
 extern void release_thread(struct task_struct *);
-extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
 
 /*
  * Return saved PC of a blocked thread.
@@ -140,6 +160,8 @@ extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
 extern unsigned long thread_saved_pc(struct task_struct *t);
 
 extern void show_code(struct pt_regs *regs);
+extern void print_fn_code(unsigned char *code, unsigned long len);
+extern int insn_to_mnemonic(unsigned char *instruction, char buf[8]);
 
 unsigned long get_wchan(struct task_struct *p);
 #define task_pt_regs(tsk) ((struct pt_regs *) \
@@ -331,23 +353,6 @@ extern void (*s390_base_ext_handler_fn)(void);
 
 #define ARCH_LOW_ADDRESS_LIMIT	0x7fffffffUL
 
-/*
- * Helper macro for exception table entries
- */
-#ifndef CONFIG_64BIT
-#define EX_TABLE(_fault,_target)			\
-	".section __ex_table,\"a\"\n"			\
-	"	.align 4\n"				\
-	"	.long  " #_fault "," #_target "\n"	\
-	".previous\n"
-#else
-#define EX_TABLE(_fault,_target)			\
-	".section __ex_table,\"a\"\n"			\
-	"	.align 8\n"				\
-	"	.quad  " #_fault "," #_target "\n"	\
-	".previous\n"
-#endif
-
 extern int memcpy_real(void *, void *, size_t);
 extern void memcpy_absolute(void *, void *, size_t);
 
@@ -358,4 +363,25 @@ extern void memcpy_absolute(void *, void *, size_t);
 	memcpy_absolute(&(dest), &__tmp, sizeof(__tmp));	\
 }
 
-#endif                                 /* __ASM_S390_PROCESSOR_H           */
+/*
+ * Helper macro for exception table entries
+ */
+#define EX_TABLE(_fault, _target)	\
+	".section __ex_table,\"a\"\n"	\
+	".align	4\n"			\
+	".long	(" #_fault ") - .\n"	\
+	".long	(" #_target ") - .\n"	\
+	".previous\n"
+
+#else /* __ASSEMBLY__ */
+
+#define EX_TABLE(_fault, _target)	\
+	.section __ex_table,"a"	;	\
+	.align	4 ;			\
+	.long	(_fault) - . ;		\
+	.long	(_target) - . ;		\
+	.previous
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __ASM_S390_PROCESSOR_H */
diff --git a/arch/s390/include/asm/ptrace.h b/arch/s390/include/asm/ptrace.h
index d5f08ea..ce20a53 100644
--- a/arch/s390/include/asm/ptrace.h
+++ b/arch/s390/include/asm/ptrace.h
@@ -235,6 +235,7 @@ typedef struct
 #define PSW_MASK_ASC		0x0000C000UL
 #define PSW_MASK_CC		0x00003000UL
 #define PSW_MASK_PM		0x00000F00UL
+#define PSW_MASK_RI		0x00000000UL
 #define PSW_MASK_EA		0x00000000UL
 #define PSW_MASK_BA		0x00000000UL
 
@@ -264,10 +265,11 @@ typedef struct
 #define PSW_MASK_ASC		0x0000C00000000000UL
 #define PSW_MASK_CC		0x0000300000000000UL
 #define PSW_MASK_PM		0x00000F0000000000UL
+#define PSW_MASK_RI		0x0000008000000000UL
 #define PSW_MASK_EA		0x0000000100000000UL
 #define PSW_MASK_BA		0x0000000080000000UL
 
-#define PSW_MASK_USER		0x00003F0180000000UL
+#define PSW_MASK_USER		0x00003F8180000000UL
 
 #define PSW_ADDR_AMODE		0x0000000000000000UL
 #define PSW_ADDR_INSN		0xFFFFFFFFFFFFFFFFUL
@@ -359,17 +361,19 @@ struct per_struct_kernel {
 	unsigned char access_id;	/* PER trap access identification */
 };
 
-#define PER_EVENT_MASK			0xE9000000UL
+#define PER_EVENT_MASK			0xEB000000UL
 
 #define PER_EVENT_BRANCH		0x80000000UL
 #define PER_EVENT_IFETCH		0x40000000UL
 #define PER_EVENT_STORE			0x20000000UL
 #define PER_EVENT_STORE_REAL		0x08000000UL
+#define PER_EVENT_TRANSACTION_END	0x02000000UL
 #define PER_EVENT_NULLIFICATION		0x01000000UL
 
-#define PER_CONTROL_MASK		0x00a00000UL
+#define PER_CONTROL_MASK		0x00e00000UL
 
 #define PER_CONTROL_BRANCH_ADDRESS	0x00800000UL
+#define PER_CONTROL_SUSPENSION		0x00400000UL
 #define PER_CONTROL_ALTERATION		0x00200000UL
 
 #endif
@@ -483,6 +487,8 @@ typedef struct
 #define PTRACE_GET_LAST_BREAK	      0x5006
 #define PTRACE_PEEK_SYSTEM_CALL       0x5007
 #define PTRACE_POKE_SYSTEM_CALL	      0x5008
+#define PTRACE_ENABLE_TE	      0x5009
+#define PTRACE_DISABLE_TE	      0x5010
 
 /*
  * PT_PROT definition is loosely based on hppa bsd definition in
diff --git a/arch/s390/include/asm/runtime_instr.h b/arch/s390/include/asm/runtime_instr.h
new file mode 100644
index 0000000..830da73
--- /dev/null
+++ b/arch/s390/include/asm/runtime_instr.h
@@ -0,0 +1,98 @@
+#ifndef _RUNTIME_INSTR_H
+#define _RUNTIME_INSTR_H
+
+#define S390_RUNTIME_INSTR_START	0x1
+#define S390_RUNTIME_INSTR_STOP		0x2
+
+struct runtime_instr_cb {
+	__u64 buf_current;
+	__u64 buf_origin;
+	__u64 buf_limit;
+
+	__u32 valid		: 1;
+	__u32 pstate		: 1;
+	__u32 pstate_set_buf	: 1;
+	__u32 home_space	: 1;
+	__u32 altered		: 1;
+	__u32			: 3;
+	__u32 pstate_sample	: 1;
+	__u32 sstate_sample	: 1;
+	__u32 pstate_collect	: 1;
+	__u32 sstate_collect	: 1;
+	__u32			: 1;
+	__u32 halted_int	: 1;
+	__u32 int_requested	: 1;
+	__u32 buffer_full_int	: 1;
+	__u32 key		: 4;
+	__u32			: 9;
+	__u32 rgs		: 3;
+
+	__u32 mode		: 4;
+	__u32 next		: 1;
+	__u32 mae		: 1;
+	__u32			: 2;
+	__u32 call_type_br	: 1;
+	__u32 return_type_br	: 1;
+	__u32 other_type_br	: 1;
+	__u32 bc_other_type	: 1;
+	__u32 emit		: 1;
+	__u32 tx_abort		: 1;
+	__u32			: 2;
+	__u32 bp_xn		: 1;
+	__u32 bp_xt		: 1;
+	__u32 bp_ti		: 1;
+	__u32 bp_ni		: 1;
+	__u32 suppr_y		: 1;
+	__u32 suppr_z		: 1;
+
+	__u32 dc_miss_extra	: 1;
+	__u32 lat_lev_ignore	: 1;
+	__u32 ic_lat_lev	: 4;
+	__u32 dc_lat_lev	: 4;
+
+	__u64 reserved1;
+	__u64 scaling_factor;
+	__u64 rsic;
+	__u64 reserved2;
+} __packed __aligned(8);
+
+extern struct runtime_instr_cb runtime_instr_empty_cb;
+
+static inline void load_runtime_instr_cb(struct runtime_instr_cb *cb)
+{
+	asm volatile(".insn	rsy,0xeb0000000060,0,0,%0"	/* LRIC */
+		: : "Q" (*cb));
+}
+
+static inline void store_runtime_instr_cb(struct runtime_instr_cb *cb)
+{
+	asm volatile(".insn	rsy,0xeb0000000061,0,0,%0"	/* STRIC */
+		: "=Q" (*cb) : : "cc");
+}
+
+static inline void save_ri_cb(struct runtime_instr_cb *cb_prev)
+{
+#ifdef CONFIG_64BIT
+	if (cb_prev)
+		store_runtime_instr_cb(cb_prev);
+#endif
+}
+
+static inline void restore_ri_cb(struct runtime_instr_cb *cb_next,
+				 struct runtime_instr_cb *cb_prev)
+{
+#ifdef CONFIG_64BIT
+	if (cb_next)
+		load_runtime_instr_cb(cb_next);
+	else if (cb_prev)
+		load_runtime_instr_cb(&runtime_instr_empty_cb);
+#endif
+}
+
+#ifdef CONFIG_64BIT
+extern void exit_thread_runtime_instr(void);
+#else
+static inline void exit_thread_runtime_instr(void) { }
+#endif
+
+#endif /* _RUNTIME_INSTR_H */
diff --git a/arch/s390/include/asm/scsw.h b/arch/s390/include/asm/scsw.h
index 4071d00..4af99cd 100644
--- a/arch/s390/include/asm/scsw.h
+++ b/arch/s390/include/asm/scsw.h
@@ -1,7 +1,7 @@
 /*
  *  Helper functions for scsw access.
  *
- *    Copyright IBM Corp. 2008, 2009
+ *    Copyright IBM Corp. 2008, 2012
  *    Author(s): Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
  */
 
@@ -9,7 +9,7 @@
 #define _ASM_S390_SCSW_H_
 
 #include <linux/types.h>
-#include <asm/chsc.h>
+#include <asm/css_chars.h>
 #include <asm/cio.h>
 
 /**
@@ -100,14 +100,46 @@ struct tm_scsw {
 } __attribute__ ((packed));
 
 /**
+ * struct eadm_scsw - subchannel status word for eadm subchannels
+ * @key: subchannel key
+ * @eswf: esw format
+ * @cc: deferred condition code
+ * @ectl: extended control
+ * @fctl: function control
+ * @actl: activity control
+ * @stctl: status control
+ * @aob: AOB address
+ * @dstat: device status
+ * @cstat: subchannel status
+ */
+struct eadm_scsw {
+	u32 key:4;
+	u32:1;
+	u32 eswf:1;
+	u32 cc:2;
+	u32:6;
+	u32 ectl:1;
+	u32:2;
+	u32 fctl:3;
+	u32 actl:7;
+	u32 stctl:5;
+	u32 aob;
+	u32 dstat:8;
+	u32 cstat:8;
+	u32:16;
+} __packed;
+
+/**
  * union scsw - subchannel status word
  * @cmd: command-mode SCSW
  * @tm: transport-mode SCSW
+ * @eadm: eadm SCSW
  */
 union scsw {
 	struct cmd_scsw cmd;
 	struct tm_scsw tm;
-} __attribute__ ((packed));
+	struct eadm_scsw eadm;
+} __packed;
 
 #define SCSW_FCTL_CLEAR_FUNC	 0x1
 #define SCSW_FCTL_HALT_FUNC	 0x2
diff --git a/arch/s390/include/asm/setup.h b/arch/s390/include/asm/setup.h
index e6859d1..8cfd731 100644
--- a/arch/s390/include/asm/setup.h
+++ b/arch/s390/include/asm/setup.h
@@ -60,7 +60,7 @@ void create_mem_hole(struct mem_chunk memory_chunk[], unsigned long addr,
 #define SECONDARY_SPACE_MODE	2
 #define HOME_SPACE_MODE		3
 
-extern unsigned int addressing_mode;
+extern unsigned int s390_user_mode;
 
 /*
  * Machine features detected in head.S
@@ -80,6 +80,8 @@ extern unsigned int addressing_mode;
 #define MACHINE_FLAG_LPAR	(1UL << 12)
 #define MACHINE_FLAG_SPP	(1UL << 13)
 #define MACHINE_FLAG_TOPOLOGY	(1UL << 14)
+#define MACHINE_FLAG_TE		(1UL << 15)
+#define MACHINE_FLAG_RRBM	(1UL << 16)
 
 #define MACHINE_IS_VM		(S390_lowcore.machine_flags & MACHINE_FLAG_VM)
 #define MACHINE_IS_KVM		(S390_lowcore.machine_flags & MACHINE_FLAG_KVM)
@@ -98,6 +100,8 @@ extern unsigned int addressing_mode;
 #define MACHINE_HAS_PFMF	(0)
 #define MACHINE_HAS_SPP		(0)
 #define MACHINE_HAS_TOPOLOGY	(0)
+#define MACHINE_HAS_TE		(0)
+#define MACHINE_HAS_RRBM	(0)
 #else /* CONFIG_64BIT */
 #define MACHINE_HAS_IEEE	(1)
 #define MACHINE_HAS_CSP		(1)
@@ -109,6 +113,8 @@ extern unsigned int addressing_mode;
 #define MACHINE_HAS_PFMF	(S390_lowcore.machine_flags & MACHINE_FLAG_PFMF)
 #define MACHINE_HAS_SPP		(S390_lowcore.machine_flags & MACHINE_FLAG_SPP)
 #define MACHINE_HAS_TOPOLOGY	(S390_lowcore.machine_flags & MACHINE_FLAG_TOPOLOGY)
+#define MACHINE_HAS_TE		(S390_lowcore.machine_flags & MACHINE_FLAG_TE)
+#define MACHINE_HAS_RRBM	(S390_lowcore.machine_flags & MACHINE_FLAG_RRBM)
 #endif /* CONFIG_64BIT */
 
 #define ZFCPDUMP_HSA_SIZE	(32UL<<20)
diff --git a/arch/s390/include/asm/smp.h b/arch/s390/include/asm/smp.h
index ce26ac3..b64f15c 100644
--- a/arch/s390/include/asm/smp.h
+++ b/arch/s390/include/asm/smp.h
@@ -30,6 +30,8 @@ extern int smp_vcpu_scheduled(int cpu);
 extern void smp_yield_cpu(int cpu);
 extern void smp_yield(void);
 extern void smp_stop_cpu(void);
+extern void smp_cpu_set_polarization(int cpu, int val);
+extern int smp_cpu_get_polarization(int cpu);
 
 #else /* CONFIG_SMP */
 
@@ -43,7 +45,7 @@ static inline void smp_call_online_cpu(void (*func)(void *), void *data)
 	func(data);
 }
 
-static inline int smp_find_processor_id(int address) { return 0; }
+static inline int smp_find_processor_id(u16 address) { return 0; }
 static inline int smp_store_status(int cpu) { return 0; }
 static inline int smp_vcpu_scheduled(int cpu) { return 1; }
 static inline void smp_yield_cpu(int cpu) { }
diff --git a/arch/s390/include/asm/string.h b/arch/s390/include/asm/string.h
index 1bd1352..7e2dcd7 100644
--- a/arch/s390/include/asm/string.h
+++ b/arch/s390/include/asm/string.h
@@ -96,7 +96,6 @@ static inline char *strcat(char *dst, const char *src)
 
 static inline char *strcpy(char *dst, const char *src)
 {
-#if __GNUC__ < 4
 	register int r0 asm("0") = 0;
 	char *ret = dst;
 
@@ -106,14 +105,10 @@ static inline char *strcpy(char *dst, const char *src)
 		: "+&a" (dst), "+&a" (src) : "d" (r0)
 		: "cc", "memory");
 	return ret;
-#else
-	return __builtin_strcpy(dst, src);
-#endif
 }
 
 static inline size_t strlen(const char *s)
 {
-#if __GNUC__ < 4
 	register unsigned long r0 asm("0") = 0;
 	const char *tmp = s;
 
@@ -122,9 +117,6 @@ static inline size_t strlen(const char *s)
 		"	jo	0b"
 		: "+d" (r0), "+a" (tmp) :  : "cc");
 	return r0 - (unsigned long) s;
-#else
-	return __builtin_strlen(s);
-#endif
 }
 
 static inline size_t strnlen(const char * s, size_t n)
diff --git a/arch/s390/include/asm/switch_to.h b/arch/s390/include/asm/switch_to.h
index f223068..f3a9e0f 100644
--- a/arch/s390/include/asm/switch_to.h
+++ b/arch/s390/include/asm/switch_to.h
@@ -80,21 +80,19 @@ static inline void restore_access_regs(unsigned int *acrs)
 	if (prev->mm) {							\
 		save_fp_regs(&prev->thread.fp_regs);			\
 		save_access_regs(&prev->thread.acrs[0]);		\
+		save_ri_cb(prev->thread.ri_cb);				\
 	}								\
 	if (next->mm) {							\
 		restore_fp_regs(&next->thread.fp_regs);			\
 		restore_access_regs(&next->thread.acrs[0]);		\
+		restore_ri_cb(next->thread.ri_cb, prev->thread.ri_cb);	\
 		update_per_regs(next);					\
 	}								\
 	prev = __switch_to(prev,next);					\
 } while (0)
 
-extern void account_vtime(struct task_struct *, struct task_struct *);
-extern void account_tick_vtime(struct task_struct *);
-
 #define finish_arch_switch(prev) do {					     \
 	set_fs(current->thread.mm_segment);				     \
-	account_vtime(prev, current);					     \
 } while (0)
 
 #endif /* __ASM_SWITCH_TO_H */
diff --git a/arch/s390/include/asm/sysinfo.h b/arch/s390/include/asm/sysinfo.h
index 282ee36..f92428e 100644
--- a/arch/s390/include/asm/sysinfo.h
+++ b/arch/s390/include/asm/sysinfo.h
@@ -17,7 +17,10 @@
 #include <asm/bitsperlong.h>
 
 struct sysinfo_1_1_1 {
-	unsigned short :16;
+	unsigned char p:1;
+	unsigned char :6;
+	unsigned char t:1;
+	unsigned char :8;
 	unsigned char ccr;
 	unsigned char cai;
 	char reserved_0[28];
@@ -30,9 +33,14 @@ struct sysinfo_1_1_1 {
 	char model[16];
 	char model_perm_cap[16];
 	char model_temp_cap[16];
-	char model_cap_rating[4];
-	char model_perm_cap_rating[4];
-	char model_temp_cap_rating[4];
+	unsigned int model_cap_rating;
+	unsigned int model_perm_cap_rating;
+	unsigned int model_temp_cap_rating;
+	unsigned char typepct[5];
+	unsigned char reserved_2[3];
+	unsigned int ncr;
+	unsigned int npr;
+	unsigned int ntr;
 };
 
 struct sysinfo_1_2_1 {
@@ -47,8 +55,9 @@ struct sysinfo_1_2_2 {
 	char format;
 	char reserved_0[1];
 	unsigned short acc_offset;
-	char reserved_1[24];
-	unsigned int secondary_capability;
+	char reserved_1[20];
+	unsigned int nominal_cap;
+	unsigned int secondary_cap;
 	unsigned int capability;
 	unsigned short cpus_total;
 	unsigned short cpus_configured;
@@ -109,6 +118,8 @@ struct sysinfo_3_2_2 {
 	char reserved_544[3552];
 };
 
+extern int topology_max_mnest;
+
 #define TOPOLOGY_CPU_BITS	64
 #define TOPOLOGY_NR_MAG		6
 
@@ -142,21 +153,7 @@ struct sysinfo_15_1_x {
 	union topology_entry tle[0];
 };
 
-static inline int stsi(void *sysinfo, int fc, int sel1, int sel2)
-{
-	register int r0 asm("0") = (fc << 28) | sel1;
-	register int r1 asm("1") = sel2;
-
-	asm volatile(
-		"   stsi 0(%2)\n"
-		"0: jz   2f\n"
-		"1: lhi  %0,%3\n"
-		"2:\n"
-		EX_TABLE(0b, 1b)
-		: "+d" (r0) : "d" (r1), "a" (sysinfo), "K" (-ENOSYS)
-		: "cc", "memory");
-	return r0;
-}
+int stsi(void *sysinfo, int fc, int sel1, int sel2);
 
 /*
  * Service level reporting interface.
diff --git a/arch/s390/include/asm/thread_info.h b/arch/s390/include/asm/thread_info.h
index bb08e2a..9e2cfe0 100644
--- a/arch/s390/include/asm/thread_info.h
+++ b/arch/s390/include/asm/thread_info.h
@@ -91,8 +91,6 @@ static inline struct thread_info *current_thread_info(void)
 #define TIF_SYSCALL_AUDIT	9	/* syscall auditing active */
 #define TIF_SECCOMP		10	/* secure computing */
 #define TIF_SYSCALL_TRACEPOINT	11	/* syscall tracepoint instrumentation */
-#define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling
-					   TIF_NEED_RESCHED */
 #define TIF_31BIT		17	/* 32bit process */
 #define TIF_MEMDIE		18	/* is terminating due to OOM killer */
 #define TIF_RESTORE_SIGMASK	19	/* restore signal mask in do_signal() */
@@ -100,7 +98,6 @@ static inline struct thread_info *current_thread_info(void)
 
 #define _TIF_SYSCALL		(1<<TIF_SYSCALL)
 #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
-#define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
 #define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
 #define _TIF_PER_TRAP		(1<<TIF_PER_TRAP)
@@ -109,7 +106,6 @@ static inline struct thread_info *current_thread_info(void)
 #define _TIF_SYSCALL_AUDIT	(1<<TIF_SYSCALL_AUDIT)
 #define _TIF_SECCOMP		(1<<TIF_SECCOMP)
 #define _TIF_SYSCALL_TRACEPOINT	(1<<TIF_SYSCALL_TRACEPOINT)
-#define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
 #define _TIF_31BIT		(1<<TIF_31BIT)
 #define _TIF_SINGLE_STEP	(1<<TIF_SINGLE_STEP)
 
diff --git a/arch/s390/include/asm/tlb.h b/arch/s390/include/asm/tlb.h
index 06e5acb..b75d7d6 100644
--- a/arch/s390/include/asm/tlb.h
+++ b/arch/s390/include/asm/tlb.h
@@ -137,6 +137,7 @@ static inline void pud_free_tlb(struct mmu_gather *tlb, pud_t *pud,
 #define tlb_start_vma(tlb, vma)			do { } while (0)
 #define tlb_end_vma(tlb, vma)			do { } while (0)
 #define tlb_remove_tlb_entry(tlb, ptep, addr)	do { } while (0)
+#define tlb_remove_pmd_tlb_entry(tlb, pmdp, addr)	do { } while (0)
 #define tlb_migrate_finish(mm)			do { } while (0)
 
 #endif /* _S390_TLB_H */
diff --git a/arch/s390/include/asm/topology.h b/arch/s390/include/asm/topology.h
index 0837de8..9ca3053 100644
--- a/arch/s390/include/asm/topology.h
+++ b/arch/s390/include/asm/topology.h
@@ -2,8 +2,8 @@
 #define _ASM_S390_TOPOLOGY_H
 
 #include <linux/cpumask.h>
-#include <asm/sysinfo.h>
 
+struct sysinfo_15_1_x;
 struct cpu;
 
 #ifdef CONFIG_SCHED_BOOK
@@ -51,24 +51,6 @@ static inline void topology_expect_change(void) { }
 #define POLARIZATION_VM		(2)
 #define POLARIZATION_VH		(3)
 
-extern int cpu_polarization[];
-
-static inline void cpu_set_polarization(int cpu, int val)
-{
-#ifdef CONFIG_SCHED_BOOK
-	cpu_polarization[cpu] = val;
-#endif
-}
-
-static inline int cpu_read_polarization(int cpu)
-{
-#ifdef CONFIG_SCHED_BOOK
-	return cpu_polarization[cpu];
-#else
-	return POLARIZATION_HRZ;
-#endif
-}
-
 #ifdef CONFIG_SCHED_BOOK
 void s390_init_cpu_topology(void);
 #else
diff --git a/arch/s390/include/asm/uaccess.h b/arch/s390/include/asm/uaccess.h
index a8ab18b..34268df 100644
--- a/arch/s390/include/asm/uaccess.h
+++ b/arch/s390/include/asm/uaccess.h
@@ -76,9 +76,22 @@ static inline int __range_ok(unsigned long addr, unsigned long size)
 
 struct exception_table_entry
 {
-        unsigned long insn, fixup;
+	int insn, fixup;
 };
 
+static inline unsigned long extable_insn(const struct exception_table_entry *x)
+{
+	return (unsigned long)&x->insn + x->insn;
+}
+
+static inline unsigned long extable_fixup(const struct exception_table_entry *x)
+{
+	return (unsigned long)&x->fixup + x->fixup;
+}
+
+#define ARCH_HAS_SORT_EXTABLE
+#define ARCH_HAS_SEARCH_EXTABLE
+
 struct uaccess_ops {
 	size_t (*copy_from_user)(size_t, const void __user *, void *);
 	size_t (*copy_from_user_small)(size_t, const void __user *, void *);
diff --git a/arch/s390/include/asm/unistd.h b/arch/s390/include/asm/unistd.h
index 6756e78..8192e29 100644
--- a/arch/s390/include/asm/unistd.h
+++ b/arch/s390/include/asm/unistd.h
@@ -277,7 +277,9 @@
 #define __NR_setns		339
 #define __NR_process_vm_readv	340
 #define __NR_process_vm_writev	341
-#define NR_syscalls 342
+#define __NR_s390_runtime_instr 342
+#define __NR_kcmp		343
+#define NR_syscalls 344
 
 /* 
  * There are some system calls that are not present on 64 bit, some
@@ -415,6 +417,8 @@
 #   define __ARCH_WANT_COMPAT_SYS_TIME
 #   define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
 # endif
+#define __ARCH_WANT_SYS_EXECVE
+#define __ARCH_WANT_KERNEL_EXECVE
 
 /*
  * "Conditional" syscalls
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile
index 9733b3f..4da52fe 100644
--- a/arch/s390/kernel/Makefile
+++ b/arch/s390/kernel/Makefile
@@ -23,10 +23,11 @@ CFLAGS_sysinfo.o += -Iinclude/math-emu -Iarch/s390/math-emu -w
 obj-y	:=  bitmap.o traps.o time.o process.o base.o early.o setup.o vtime.o \
 	    processor.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o nmi.o \
 	    debug.o irq.o ipl.o dis.o diag.o mem_detect.o sclp.o vdso.o \
-	    sysinfo.o jump_label.o lgr.o os_info.o
+	    sysinfo.o jump_label.o lgr.o os_info.o machine_kexec.o
 
 obj-y	+= $(if $(CONFIG_64BIT),entry64.o,entry.o)
 obj-y	+= $(if $(CONFIG_64BIT),reipl64.o,reipl.o)
+obj-y	+= $(if $(CONFIG_64BIT),relocate_kernel64.o,relocate_kernel.o)
 
 extra-y				+= head.o vmlinux.lds
 extra-y				+= $(if $(CONFIG_64BIT),head64.o,head31.o)
@@ -48,12 +49,11 @@ obj-$(CONFIG_DYNAMIC_FTRACE)	+= ftrace.o
 obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o
 obj-$(CONFIG_FTRACE_SYSCALLS)  += ftrace.o
 obj-$(CONFIG_CRASH_DUMP)	+= crash_dump.o
-obj-$(CONFIG_PERF_EVENTS)	+= perf_event.o perf_cpum_cf.o
 
-# Kexec part
-S390_KEXEC_OBJS := machine_kexec.o crash.o
-S390_KEXEC_OBJS += $(if $(CONFIG_64BIT),relocate_kernel64.o,relocate_kernel.o)
-obj-$(CONFIG_KEXEC) += $(S390_KEXEC_OBJS)
+ifdef CONFIG_64BIT
+obj-$(CONFIG_PERF_EVENTS)	+= perf_event.o perf_cpum_cf.o
+obj-y				+= runtime_instr.o cache.o
+endif
 
 # vdso
 obj-$(CONFIG_64BIT)		+= vdso64/
diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c
index 45ef1a7..fface87 100644
--- a/arch/s390/kernel/asm-offsets.c
+++ b/arch/s390/kernel/asm-offsets.c
@@ -157,6 +157,8 @@ int main(void)
 	DEFINE(__LC_LAST_BREAK, offsetof(struct _lowcore, breaking_event_addr));
 	DEFINE(__LC_VDSO_PER_CPU, offsetof(struct _lowcore, vdso_per_cpu_data));
 	DEFINE(__LC_GMAP, offsetof(struct _lowcore, gmap));
+	DEFINE(__LC_PGM_TDB, offsetof(struct _lowcore, pgm_tdb));
+	DEFINE(__THREAD_trap_tdb, offsetof(struct task_struct, thread.trap_tdb));
 	DEFINE(__GMAP_ASCE, offsetof(struct gmap, asce));
 #endif /* CONFIG_32BIT */
 	return 0;
diff --git a/arch/s390/kernel/cache.c b/arch/s390/kernel/cache.c
new file mode 100644
index 0000000..8df8d8a1
--- /dev/null
+++ b/arch/s390/kernel/cache.c
@@ -0,0 +1,385 @@
+/*
+ * Extract CPU cache information and expose them via sysfs.
+ *
+ *    Copyright IBM Corp. 2012
+ *    Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
+ */
+
+#include <linux/notifier.h>
+#include <linux/seq_file.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/cpu.h>
+#include <asm/facility.h>
+
+struct cache {
+	unsigned long size;
+	unsigned int line_size;
+	unsigned int associativity;
+	unsigned int nr_sets;
+	unsigned int level   : 3;
+	unsigned int type    : 2;
+	unsigned int private : 1;
+	struct list_head list;
+};
+
+struct cache_dir {
+	struct kobject *kobj;
+	struct cache_index_dir *index;
+};
+
+struct cache_index_dir {
+	struct kobject kobj;
+	int cpu;
+	struct cache *cache;
+	struct cache_index_dir *next;
+};
+
+enum {
+	CACHE_SCOPE_NOTEXISTS,
+	CACHE_SCOPE_PRIVATE,
+	CACHE_SCOPE_SHARED,
+	CACHE_SCOPE_RESERVED,
+};
+
+enum {
+	CACHE_TYPE_SEPARATE,
+	CACHE_TYPE_DATA,
+	CACHE_TYPE_INSTRUCTION,
+	CACHE_TYPE_UNIFIED,
+};
+
+enum {
+	EXTRACT_TOPOLOGY,
+	EXTRACT_LINE_SIZE,
+	EXTRACT_SIZE,
+	EXTRACT_ASSOCIATIVITY,
+};
+
+enum {
+	CACHE_TI_UNIFIED = 0,
+	CACHE_TI_INSTRUCTION = 0,
+	CACHE_TI_DATA,
+};
+
+struct cache_info {
+	unsigned char	    : 4;
+	unsigned char scope : 2;
+	unsigned char type  : 2;
+};
+
+#define CACHE_MAX_LEVEL 8
+
+union cache_topology {
+	struct cache_info ci[CACHE_MAX_LEVEL];
+	unsigned long long raw;
+};
+
+static const char * const cache_type_string[] = {
+	"Data",
+	"Instruction",
+	"Unified",
+};
+
+static struct cache_dir *cache_dir_cpu[NR_CPUS];
+static LIST_HEAD(cache_list);
+
+void show_cacheinfo(struct seq_file *m)
+{
+	struct cache *cache;
+	int index = 0;
+
+	list_for_each_entry(cache, &cache_list, list) {
+		seq_printf(m, "cache%-11d: ", index);
+		seq_printf(m, "level=%d ", cache->level);
+		seq_printf(m, "type=%s ", cache_type_string[cache->type]);
+		seq_printf(m, "scope=%s ", cache->private ? "Private" : "Shared");
+		seq_printf(m, "size=%luK ", cache->size >> 10);
+		seq_printf(m, "line_size=%u ", cache->line_size);
+		seq_printf(m, "associativity=%d", cache->associativity);
+		seq_puts(m, "\n");
+		index++;
+	}
+}
+
+static inline unsigned long ecag(int ai, int li, int ti)
+{
+	unsigned long cmd, val;
+
+	cmd = ai << 4 | li << 1 | ti;
+	asm volatile(".insn	rsy,0xeb000000004c,%0,0,0(%1)" /* ecag */
+		     : "=d" (val) : "a" (cmd));
+	return val;
+}
+
+static int __init cache_add(int level, int private, int type)
+{
+	struct cache *cache;
+	int ti;
+
+	cache = kzalloc(sizeof(*cache), GFP_KERNEL);
+	if (!cache)
+		return -ENOMEM;
+	ti = type == CACHE_TYPE_DATA ? CACHE_TI_DATA : CACHE_TI_UNIFIED;
+	cache->size = ecag(EXTRACT_SIZE, level, ti);
+	cache->line_size = ecag(EXTRACT_LINE_SIZE, level, ti);
+	cache->associativity = ecag(EXTRACT_ASSOCIATIVITY, level, ti);
+	cache->nr_sets = cache->size / cache->associativity;
+	cache->nr_sets /= cache->line_size;
+	cache->private = private;
+	cache->level = level + 1;
+	cache->type = type - 1;
+	list_add_tail(&cache->list, &cache_list);
+	return 0;
+}
+
+static void __init cache_build_info(void)
+{
+	struct cache *cache, *next;
+	union cache_topology ct;
+	int level, private, rc;
+
+	ct.raw = ecag(EXTRACT_TOPOLOGY, 0, 0);
+	for (level = 0; level < CACHE_MAX_LEVEL; level++) {
+		switch (ct.ci[level].scope) {
+		case CACHE_SCOPE_NOTEXISTS:
+		case CACHE_SCOPE_RESERVED:
+			return;
+		case CACHE_SCOPE_SHARED:
+			private = 0;
+			break;
+		case CACHE_SCOPE_PRIVATE:
+			private = 1;
+			break;
+		}
+		if (ct.ci[level].type == CACHE_TYPE_SEPARATE) {
+			rc  = cache_add(level, private, CACHE_TYPE_DATA);
+			rc |= cache_add(level, private, CACHE_TYPE_INSTRUCTION);
+		} else {
+			rc = cache_add(level, private, ct.ci[level].type);
+		}
+		if (rc)
+			goto error;
+	}
+	return;
+error:
+	list_for_each_entry_safe(cache, next, &cache_list, list) {
+		list_del(&cache->list);
+		kfree(cache);
+	}
+}
+
+static struct cache_dir *__cpuinit cache_create_cache_dir(int cpu)
+{
+	struct cache_dir *cache_dir;
+	struct kobject *kobj = NULL;
+	struct device *dev;
+
+	dev = get_cpu_device(cpu);
+	if (!dev)
+		goto out;
+	kobj = kobject_create_and_add("cache", &dev->kobj);
+	if (!kobj)
+		goto out;
+	cache_dir = kzalloc(sizeof(*cache_dir), GFP_KERNEL);
+	if (!cache_dir)
+		goto out;
+	cache_dir->kobj = kobj;
+	cache_dir_cpu[cpu] = cache_dir;
+	return cache_dir;
+out:
+	kobject_put(kobj);
+	return NULL;
+}
+
+static struct cache_index_dir *kobj_to_cache_index_dir(struct kobject *kobj)
+{
+	return container_of(kobj, struct cache_index_dir, kobj);
+}
+
+static void cache_index_release(struct kobject *kobj)
+{
+	struct cache_index_dir *index;
+
+	index = kobj_to_cache_index_dir(kobj);
+	kfree(index);
+}
+
+static ssize_t cache_index_show(struct kobject *kobj,
+				struct attribute *attr, char *buf)
+{
+	struct kobj_attribute *kobj_attr;
+
+	kobj_attr = container_of(attr, struct kobj_attribute, attr);
+	return kobj_attr->show(kobj, kobj_attr, buf);
+}
+
+#define DEFINE_CACHE_ATTR(_name, _format, _value)			\
+static ssize_t cache_##_name##_show(struct kobject *kobj,		\
+				    struct kobj_attribute *attr,	\
+				    char *buf)				\
+{									\
+	struct cache_index_dir *index;					\
+									\
+	index = kobj_to_cache_index_dir(kobj);				\
+	return sprintf(buf, _format, _value);				\
+}									\
+static struct kobj_attribute cache_##_name##_attr =			\
+	__ATTR(_name, 0444, cache_##_name##_show, NULL);
+
+DEFINE_CACHE_ATTR(size, "%luK\n", index->cache->size >> 10);
+DEFINE_CACHE_ATTR(coherency_line_size, "%u\n", index->cache->line_size);
+DEFINE_CACHE_ATTR(number_of_sets, "%u\n", index->cache->nr_sets);
+DEFINE_CACHE_ATTR(ways_of_associativity, "%u\n", index->cache->associativity);
+DEFINE_CACHE_ATTR(type, "%s\n", cache_type_string[index->cache->type]);
+DEFINE_CACHE_ATTR(level, "%d\n", index->cache->level);
+
+static ssize_t shared_cpu_map_func(struct kobject *kobj, int type, char *buf)
+{
+	struct cache_index_dir *index;
+	int len;
+
+	index = kobj_to_cache_index_dir(kobj);
+	len = type ?
+		cpulist_scnprintf(buf, PAGE_SIZE - 2, cpumask_of(index->cpu)) :
+		cpumask_scnprintf(buf, PAGE_SIZE - 2, cpumask_of(index->cpu));
+	len += sprintf(&buf[len], "\n");
+	return len;
+}
+
+static ssize_t shared_cpu_map_show(struct kobject *kobj,
+				   struct kobj_attribute *attr, char *buf)
+{
+	return shared_cpu_map_func(kobj, 0, buf);
+}
+static struct kobj_attribute cache_shared_cpu_map_attr =
+	__ATTR(shared_cpu_map, 0444, shared_cpu_map_show, NULL);
+
+static ssize_t shared_cpu_list_show(struct kobject *kobj,
+				    struct kobj_attribute *attr, char *buf)
+{
+	return shared_cpu_map_func(kobj, 1, buf);
+}
+static struct kobj_attribute cache_shared_cpu_list_attr =
+	__ATTR(shared_cpu_list, 0444, shared_cpu_list_show, NULL);
+
+static struct attribute *cache_index_default_attrs[] = {
+	&cache_type_attr.attr,
+	&cache_size_attr.attr,
+	&cache_number_of_sets_attr.attr,
+	&cache_ways_of_associativity_attr.attr,
+	&cache_level_attr.attr,
+	&cache_coherency_line_size_attr.attr,
+	&cache_shared_cpu_map_attr.attr,
+	&cache_shared_cpu_list_attr.attr,
+	NULL,
+};
+
+static const struct sysfs_ops cache_index_ops = {
+	.show = cache_index_show,
+};
+
+static struct kobj_type cache_index_type = {
+	.sysfs_ops = &cache_index_ops,
+	.release = cache_index_release,
+	.default_attrs = cache_index_default_attrs,
+};
+
+static int __cpuinit cache_create_index_dir(struct cache_dir *cache_dir,
+					    struct cache *cache, int index,
+					    int cpu)
+{
+	struct cache_index_dir *index_dir;
+	int rc;
+
+	index_dir = kzalloc(sizeof(*index_dir), GFP_KERNEL);
+	if (!index_dir)
+		return -ENOMEM;
+	index_dir->cache = cache;
+	index_dir->cpu = cpu;
+	rc = kobject_init_and_add(&index_dir->kobj, &cache_index_type,
+				  cache_dir->kobj, "index%d", index);
+	if (rc)
+		goto out;
+	index_dir->next = cache_dir->index;
+	cache_dir->index = index_dir;
+	return 0;
+out:
+	kfree(index_dir);
+	return rc;
+}
+
+static int __cpuinit cache_add_cpu(int cpu)
+{
+	struct cache_dir *cache_dir;
+	struct cache *cache;
+	int rc, index = 0;
+
+	if (list_empty(&cache_list))
+		return 0;
+	cache_dir = cache_create_cache_dir(cpu);
+	if (!cache_dir)
+		return -ENOMEM;
+	list_for_each_entry(cache, &cache_list, list) {
+		if (!cache->private)
+			break;
+		rc = cache_create_index_dir(cache_dir, cache, index, cpu);
+		if (rc)
+			return rc;
+		index++;
+	}
+	return 0;
+}
+
+static void __cpuinit cache_remove_cpu(int cpu)
+{
+	struct cache_index_dir *index, *next;
+	struct cache_dir *cache_dir;
+
+	cache_dir = cache_dir_cpu[cpu];
+	if (!cache_dir)
+		return;
+	index = cache_dir->index;
+	while (index) {
+		next = index->next;
+		kobject_put(&index->kobj);
+		index = next;
+	}
+	kobject_put(cache_dir->kobj);
+	kfree(cache_dir);
+	cache_dir_cpu[cpu] = NULL;
+}
+
+static int __cpuinit cache_hotplug(struct notifier_block *nfb,
+				   unsigned long action, void *hcpu)
+{
+	int cpu = (long)hcpu;
+	int rc = 0;
+
+	switch (action & ~CPU_TASKS_FROZEN) {
+	case CPU_ONLINE:
+		rc = cache_add_cpu(cpu);
+		if (rc)
+			cache_remove_cpu(cpu);
+		break;
+	case CPU_DEAD:
+		cache_remove_cpu(cpu);
+		break;
+	}
+	return rc ? NOTIFY_BAD : NOTIFY_OK;
+}
+
+static int __init cache_init(void)
+{
+	int cpu;
+
+	if (!test_facility(34))
+		return 0;
+	cache_build_info();
+	for_each_online_cpu(cpu)
+		cache_add_cpu(cpu);
+	hotcpu_notifier(cache_hotplug, 0);
+	return 0;
+}
+device_initcall(cache_init);
diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c
index f606d93..65cca95 100644
--- a/arch/s390/kernel/compat_linux.c
+++ b/arch/s390/kernel/compat_linux.c
@@ -131,13 +131,19 @@ asmlinkage long sys32_setresuid16(u16 ruid, u16 euid, u16 suid)
 		low2highuid(suid));
 }
 
-asmlinkage long sys32_getresuid16(u16 __user *ruid, u16 __user *euid, u16 __user *suid)
+asmlinkage long sys32_getresuid16(u16 __user *ruidp, u16 __user *euidp, u16 __user *suidp)
 {
+	const struct cred *cred = current_cred();
 	int retval;
+	u16 ruid, euid, suid;
 
-	if (!(retval = put_user(high2lowuid(current->cred->uid), ruid)) &&
-	    !(retval = put_user(high2lowuid(current->cred->euid), euid)))
-		retval = put_user(high2lowuid(current->cred->suid), suid);
+	ruid = high2lowuid(from_kuid_munged(cred->user_ns, cred->uid));
+	euid = high2lowuid(from_kuid_munged(cred->user_ns, cred->euid));
+	suid = high2lowuid(from_kuid_munged(cred->user_ns, cred->suid));
+
+	if (!(retval   = put_user(ruid, ruidp)) &&
+	    !(retval   = put_user(euid, euidp)))
+		retval = put_user(suid, suidp);
 
 	return retval;
 }
@@ -148,13 +154,19 @@ asmlinkage long sys32_setresgid16(u16 rgid, u16 egid, u16 sgid)
 		low2highgid(sgid));
 }
 
-asmlinkage long sys32_getresgid16(u16 __user *rgid, u16 __user *egid, u16 __user *sgid)
+asmlinkage long sys32_getresgid16(u16 __user *rgidp, u16 __user *egidp, u16 __user *sgidp)
 {
+	const struct cred *cred = current_cred();
 	int retval;
+	u16 rgid, egid, sgid;
+
+	rgid = high2lowgid(from_kgid_munged(cred->user_ns, cred->gid));
+	egid = high2lowgid(from_kgid_munged(cred->user_ns, cred->egid));
+	sgid = high2lowgid(from_kgid_munged(cred->user_ns, cred->sgid));
 
-	if (!(retval = put_user(high2lowgid(current->cred->gid), rgid)) &&
-	    !(retval = put_user(high2lowgid(current->cred->egid), egid)))
-		retval = put_user(high2lowgid(current->cred->sgid), sgid);
+	if (!(retval   = put_user(rgid, rgidp)) &&
+	    !(retval   = put_user(egid, egidp)))
+		retval = put_user(sgid, sgidp);
 
 	return retval;
 }
@@ -258,22 +270,22 @@ asmlinkage long sys32_setgroups16(int gidsetsize, u16 __user *grouplist)
 
 asmlinkage long sys32_getuid16(void)
 {
-	return high2lowuid(current->cred->uid);
+	return high2lowuid(from_kuid_munged(current_user_ns(), current_uid()));
 }
 
 asmlinkage long sys32_geteuid16(void)
 {
-	return high2lowuid(current->cred->euid);
+	return high2lowuid(from_kuid_munged(current_user_ns(), current_euid()));
 }
 
 asmlinkage long sys32_getgid16(void)
 {
-	return high2lowgid(current->cred->gid);
+	return high2lowgid(from_kgid_munged(current_user_ns(), current_gid()));
 }
 
 asmlinkage long sys32_getegid16(void)
 {
-	return high2lowgid(current->cred->egid);
+	return high2lowgid(from_kgid_munged(current_user_ns(), current_egid()));
 }
 
 /*
@@ -420,32 +432,6 @@ sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t __user *uinfo)
 	return ret;
 }
 
-/*
- * sys32_execve() executes a new program after the asm stub has set
- * things up for us.  This should basically do what I want it to.
- */
-asmlinkage long sys32_execve(const char __user *name, compat_uptr_t __user *argv,
-			     compat_uptr_t __user *envp)
-{
-	struct pt_regs *regs = task_pt_regs(current);
-	char *filename;
-	long rc;
-
-	filename = getname(name);
-	rc = PTR_ERR(filename);
-	if (IS_ERR(filename))
-		return rc;
-	rc = compat_do_execve(filename, argv, envp, regs);
-	if (rc)
-		goto out;
-	current->thread.fp_regs.fpc=0;
-	asm volatile("sfpc %0,0" : : "d" (0));
-	rc = regs->gprs[2];
-out:
-	putname(filename);
-	return rc;
-}
-
 asmlinkage long sys32_pread64(unsigned int fd, char __user *ubuf,
 				size_t count, u32 poshi, u32 poslo)
 {
diff --git a/arch/s390/kernel/compat_linux.h b/arch/s390/kernel/compat_linux.h
index 9635d75..d4d0239 100644
--- a/arch/s390/kernel/compat_linux.h
+++ b/arch/s390/kernel/compat_linux.h
@@ -23,74 +23,6 @@ struct old_sigaction32 {
        __u32			sa_flags;
        __u32			sa_restorer;	/* Another 32 bit pointer */
 };
- 
-typedef struct compat_siginfo {
-	int	si_signo;
-	int	si_errno;
-	int	si_code;
-
-	union {
-		int _pad[((128/sizeof(int)) - 3)];
-
-		/* kill() */
-		struct {
-			pid_t	_pid;	/* sender's pid */
-			uid_t	_uid;	/* sender's uid */
-		} _kill;
-
-		/* POSIX.1b timers */
-		struct {
-			compat_timer_t _tid;		/* timer id */
-			int _overrun;		/* overrun count */
-			compat_sigval_t _sigval;	/* same as below */
-			int _sys_private;       /* not to be passed to user */
-		} _timer;
-
-		/* POSIX.1b signals */
-		struct {
-			pid_t			_pid;	/* sender's pid */
-			uid_t			_uid;	/* sender's uid */
-			compat_sigval_t		_sigval;
-		} _rt;
-
-		/* SIGCHLD */
-		struct {
-			pid_t			_pid;	/* which child */
-			uid_t			_uid;	/* sender's uid */
-			int			_status;/* exit code */
-			compat_clock_t		_utime;
-			compat_clock_t		_stime;
-		} _sigchld;
-
-		/* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
-		struct {
-			__u32	_addr;	/* faulting insn/memory ref. - pointer */
-		} _sigfault;
-                          
-		/* SIGPOLL */
-		struct {
-			int	_band;	/* POLL_IN, POLL_OUT, POLL_MSG */
-			int	_fd;
-		} _sigpoll;
-	} _sifields;
-} compat_siginfo_t;
-
-/*
- * How these fields are to be accessed.
- */
-#define si_pid		_sifields._kill._pid
-#define si_uid		_sifields._kill._uid
-#define si_status	_sifields._sigchld._status
-#define si_utime	_sifields._sigchld._utime
-#define si_stime	_sifields._sigchld._stime
-#define si_value	_sifields._rt._sigval
-#define si_int		_sifields._rt._sigval.sival_int
-#define si_ptr		_sifields._rt._sigval.sival_ptr
-#define si_addr		_sifields._sigfault._addr
-#define si_band		_sifields._sigpoll._band
-#define si_fd		_sifields._sigpoll._fd    
-#define si_tid		_sifields._timer._tid
-#define si_overrun	_sifields._timer._overrun
 
 /* asm/sigcontext.h */
 typedef union
@@ -193,8 +125,6 @@ long sys32_rt_sigprocmask(int how, compat_sigset_t __user *set,
 			  compat_sigset_t __user *oset, size_t sigsetsize);
 long sys32_rt_sigpending(compat_sigset_t __user *set, size_t sigsetsize);
 long sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t __user *uinfo);
-long sys32_execve(const char __user *name, compat_uptr_t __user *argv,
-		  compat_uptr_t __user *envp);
 long sys32_init_module(void __user *umod, unsigned long len,
 		       const char __user *uargs);
 long sys32_delete_module(const char __user *name_user, unsigned int flags);
diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S
index 2d82cfc..ad79b84 100644
--- a/arch/s390/kernel/compat_wrapper.S
+++ b/arch/s390/kernel/compat_wrapper.S
@@ -1576,7 +1576,7 @@ ENTRY(sys32_execve_wrapper)
 	llgtr	%r2,%r2			# char *
 	llgtr	%r3,%r3			# compat_uptr_t *
 	llgtr	%r4,%r4			# compat_uptr_t *
-	jg	sys32_execve		# branch to system call
+	jg	compat_sys_execve	# branch to system call
 
 ENTRY(sys_fanotify_init_wrapper)
 	llgfr	%r2,%r2			# unsigned int
@@ -1646,3 +1646,16 @@ ENTRY(compat_sys_process_vm_writev_wrapper)
 	llgf	%r0,164(%r15)		# unsigned long
 	stg	%r0,160(%r15)
 	jg	compat_sys_process_vm_writev
+
+ENTRY(sys_s390_runtime_instr_wrapper)
+	lgfr	%r2,%r2			# int
+	lgfr	%r3,%r3			# int
+	jg	sys_s390_runtime_instr
+
+ENTRY(sys_kcmp_wrapper)
+	lgfr	%r2,%r2			# pid_t
+	lgfr	%r3,%r3			# pid_t
+	lgfr	%r4,%r4			# int
+	llgfr	%r5,%r5			# unsigned long
+	llgfr	%r6,%r6			# unsigned long
+	jg	sys_kcmp
diff --git a/arch/s390/kernel/crash.c b/arch/s390/kernel/crash.c
deleted file mode 100644
index 3819153..0000000
--- a/arch/s390/kernel/crash.c
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Copyright IBM Corp. 2005
- *
- * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
- *
- */
-
-#include <linux/threads.h>
-#include <linux/kexec.h>
-#include <linux/reboot.h>
-
-void machine_crash_shutdown(struct pt_regs *regs)
-{
-}
diff --git a/arch/s390/kernel/crash_dump.c b/arch/s390/kernel/crash_dump.c
index cc1172b..fb8d878 100644
--- a/arch/s390/kernel/crash_dump.c
+++ b/arch/s390/kernel/crash_dump.c
@@ -13,8 +13,9 @@
 #include <linux/slab.h>
 #include <linux/bootmem.h>
 #include <linux/elf.h>
-#include <asm/ipl.h>
 #include <asm/os_info.h>
+#include <asm/elf.h>
+#include <asm/ipl.h>
 
 #define PTR_ADD(x, y) (((char *) (x)) + ((unsigned long) (y)))
 #define PTR_SUB(x, y) (((char *) (x)) - ((unsigned long) (y)))
diff --git a/arch/s390/kernel/dis.c b/arch/s390/kernel/dis.c
index 619c5d3..76d2305 100644
--- a/arch/s390/kernel/dis.c
+++ b/arch/s390/kernel/dis.c
@@ -315,6 +315,11 @@ enum {
 	LONG_INSN_POPCNT,
 	LONG_INSN_RISBHG,
 	LONG_INSN_RISBLG,
+	LONG_INSN_RINEXT,
+	LONG_INSN_RIEMIT,
+	LONG_INSN_TABORT,
+	LONG_INSN_TBEGIN,
+	LONG_INSN_TBEGINC,
 };
 
 static char *long_insn_name[] = {
@@ -330,6 +335,11 @@ static char *long_insn_name[] = {
 	[LONG_INSN_POPCNT] = "popcnt",
 	[LONG_INSN_RISBHG] = "risbhg",
 	[LONG_INSN_RISBLG] = "risblk",
+	[LONG_INSN_RINEXT] = "rinext",
+	[LONG_INSN_RIEMIT] = "riemit",
+	[LONG_INSN_TABORT] = "tabort",
+	[LONG_INSN_TBEGIN] = "tbegin",
+	[LONG_INSN_TBEGINC] = "tbeginc",
 };
 
 static struct insn opcode[] = {
@@ -582,6 +592,17 @@ static struct insn opcode_a7[] = {
 	{ "", 0, INSTR_INVALID }
 };
 
+static struct insn opcode_aa[] = {
+#ifdef CONFIG_64BIT
+	{ { 0, LONG_INSN_RINEXT }, 0x00, INSTR_RI_RI },
+	{ "rion", 0x01, INSTR_RI_RI },
+	{ "tric", 0x02, INSTR_RI_RI },
+	{ "rioff", 0x03, INSTR_RI_RI },
+	{ { 0, LONG_INSN_RIEMIT }, 0x04, INSTR_RI_RI },
+#endif
+	{ "", 0, INSTR_INVALID }
+};
+
 static struct insn opcode_b2[] = {
 #ifdef CONFIG_64BIT
 	{ "sske", 0x2b, INSTR_RRF_M0RR },
@@ -594,6 +615,9 @@ static struct insn opcode_b2[] = {
 	{ "lpswe", 0xb2, INSTR_S_RD },
 	{ "srnmt", 0xb9, INSTR_S_RD },
 	{ "lfas", 0xbd, INSTR_S_RD },
+	{ "etndg", 0xec, INSTR_RRE_R0 },
+	{ { 0, LONG_INSN_TABORT }, 0xfc, INSTR_S_RD },
+	{ "tend", 0xf8, INSTR_S_RD },
 #endif
 	{ "stidp", 0x02, INSTR_S_RD },
 	{ "sck", 0x04, INSTR_S_RD },
@@ -1150,6 +1174,7 @@ static struct insn opcode_e3[] = {
 	{ "stfh", 0xcb, INSTR_RXY_RRRD },
 	{ "chf", 0xcd, INSTR_RXY_RRRD },
 	{ "clhf", 0xcf, INSTR_RXY_RRRD },
+	{ "ntstg", 0x25, INSTR_RXY_RRRD },
 #endif
 	{ "lrv", 0x1e, INSTR_RXY_RRRD },
 	{ "lrvh", 0x1f, INSTR_RXY_RRRD },
@@ -1173,6 +1198,8 @@ static struct insn opcode_e5[] = {
 	{ "mvhhi", 0x44, INSTR_SIL_RDI },
 	{ "mvhi", 0x4c, INSTR_SIL_RDI },
 	{ "mvghi", 0x48, INSTR_SIL_RDI },
+	{ { 0, LONG_INSN_TBEGIN }, 0x60, INSTR_SIL_RDU },
+	{ { 0, LONG_INSN_TBEGINC }, 0x61, INSTR_SIL_RDU },
 #endif
 	{ "lasp", 0x00, INSTR_SSE_RDRD },
 	{ "tprot", 0x01, INSTR_SSE_RDRD },
@@ -1210,6 +1237,9 @@ static struct insn opcode_eb[] = {
 	{ "cliy", 0x55, INSTR_SIY_URD },
 	{ "oiy", 0x56, INSTR_SIY_URD },
 	{ "xiy", 0x57, INSTR_SIY_URD },
+	{ "lric", 0x60, INSTR_RSY_RDRM },
+	{ "stric", 0x61, INSTR_RSY_RDRM },
+	{ "mric", 0x62, INSTR_RSY_RDRM },
 	{ "icmh", 0x80, INSTR_RSE_RURD },
 	{ "icmh", 0x80, INSTR_RSY_RURD },
 	{ "icmy", 0x81, INSTR_RSY_RURD },
@@ -1408,6 +1438,9 @@ static struct insn *find_insn(unsigned char *code)
 	case 0xa7:
 		table = opcode_a7;
 		break;
+	case 0xaa:
+		table = opcode_aa;
+		break;
 	case 0xb2:
 		table = opcode_b2;
 		break;
@@ -1468,6 +1501,33 @@ static struct insn *find_insn(unsigned char *code)
 	return NULL;
 }
 
+/**
+ * insn_to_mnemonic - decode an s390 instruction
+ * @instruction: instruction to decode
+ * @buf: buffer to fill with mnemonic
+ *
+ * Decode the instruction at @instruction and store the corresponding
+ * mnemonic into @buf.
+ * @buf is left unchanged if the instruction could not be decoded.
+ * Returns:
+ *  %0 on success, %-ENOENT if the instruction was not found.
+ */
+int insn_to_mnemonic(unsigned char *instruction, char buf[8])
+{
+	struct insn *insn;
+
+	insn = find_insn(instruction);
+	if (!insn)
+		return -ENOENT;
+	if (insn->name[0] == '\0')
+		snprintf(buf, sizeof(buf), "%s",
+			 long_insn_name[(int) insn->name[1]]);
+	else
+		snprintf(buf, sizeof(buf), "%.5s", insn->name);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(insn_to_mnemonic);
+
 static int print_insn(char *buffer, unsigned char *code, unsigned long addr)
 {
 	struct insn *insn;
@@ -1601,3 +1661,26 @@ void show_code(struct pt_regs *regs)
 	}
 	printk("\n");
 }
+
+void print_fn_code(unsigned char *code, unsigned long len)
+{
+	char buffer[64], *ptr;
+	int opsize, i;
+
+	while (len) {
+		ptr = buffer;
+		opsize = insn_length(*code);
+		ptr += sprintf(ptr, "%p: ", code);
+		for (i = 0; i < opsize; i++)
+			ptr += sprintf(ptr, "%02x", code[i]);
+		*ptr++ = '\t';
+		if (i < 4)
+			*ptr++ = '\t';
+		ptr += print_insn(ptr, code, (unsigned long) code);
+		*ptr++ = '\n';
+		*ptr++ = 0;
+		printk(buffer);
+		code += opsize;
+		len -= opsize;
+	}
+}
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c
index 83c3271..00d1144 100644
--- a/arch/s390/kernel/early.c
+++ b/arch/s390/kernel/early.c
@@ -215,36 +215,54 @@ static noinline __init void init_kernel_storage_key(void)
 				     PAGE_DEFAULT_KEY, 0);
 }
 
-static __initdata struct sysinfo_3_2_2 vmms __aligned(PAGE_SIZE);
+static __initdata char sysinfo_page[PAGE_SIZE] __aligned(PAGE_SIZE);
 
 static noinline __init void detect_machine_type(void)
 {
+	struct sysinfo_3_2_2 *vmms = (struct sysinfo_3_2_2 *)&sysinfo_page;
+
 	/* Check current-configuration-level */
-	if ((stsi(NULL, 0, 0, 0) >> 28) <= 2) {
+	if (stsi(NULL, 0, 0, 0) <= 2) {
 		S390_lowcore.machine_flags |= MACHINE_FLAG_LPAR;
 		return;
 	}
 	/* Get virtual-machine cpu information. */
-	if (stsi(&vmms, 3, 2, 2) == -ENOSYS || !vmms.count)
+	if (stsi(vmms, 3, 2, 2) || !vmms->count)
 		return;
 
 	/* Running under KVM? If not we assume z/VM */
-	if (!memcmp(vmms.vm[0].cpi, "\xd2\xe5\xd4", 3))
+	if (!memcmp(vmms->vm[0].cpi, "\xd2\xe5\xd4", 3))
 		S390_lowcore.machine_flags |= MACHINE_FLAG_KVM;
 	else
 		S390_lowcore.machine_flags |= MACHINE_FLAG_VM;
 }
 
+static __init void setup_topology(void)
+{
+#ifdef CONFIG_64BIT
+	int max_mnest;
+
+	if (!test_facility(11))
+		return;
+	S390_lowcore.machine_flags |= MACHINE_FLAG_TOPOLOGY;
+	for (max_mnest = 6; max_mnest > 1; max_mnest--) {
+		if (stsi(&sysinfo_page, 15, 1, max_mnest) == 0)
+			break;
+	}
+	topology_max_mnest = max_mnest;
+#endif
+}
+
 static void early_pgm_check_handler(void)
 {
-	unsigned long addr;
 	const struct exception_table_entry *fixup;
+	unsigned long addr;
 
 	addr = S390_lowcore.program_old_psw.addr;
 	fixup = search_exception_tables(addr & PSW_ADDR_INSN);
 	if (!fixup)
 		disabled_wait(0);
-	S390_lowcore.program_old_psw.addr = fixup->fixup | PSW_ADDR_AMODE;
+	S390_lowcore.program_old_psw.addr = extable_fixup(fixup)|PSW_ADDR_AMODE;
 }
 
 static noinline __init void setup_lowcore_early(void)
@@ -267,12 +285,10 @@ static noinline __init void setup_facility_list(void)
 
 static noinline __init void setup_hpage(void)
 {
-#ifndef CONFIG_DEBUG_PAGEALLOC
 	if (!test_facility(2) || !test_facility(8))
 		return;
 	S390_lowcore.machine_flags |= MACHINE_FLAG_HPAGE;
 	__ctl_set_bit(0, 23);
-#endif
 }
 
 static __init void detect_mvpg(void)
@@ -366,12 +382,14 @@ static __init void detect_machine_facilities(void)
 		S390_lowcore.machine_flags |= MACHINE_FLAG_IDTE;
 	if (test_facility(8))
 		S390_lowcore.machine_flags |= MACHINE_FLAG_PFMF;
-	if (test_facility(11))
-		S390_lowcore.machine_flags |= MACHINE_FLAG_TOPOLOGY;
 	if (test_facility(27))
 		S390_lowcore.machine_flags |= MACHINE_FLAG_MVCOS;
 	if (test_facility(40))
 		S390_lowcore.machine_flags |= MACHINE_FLAG_SPP;
+	if (test_facility(50) && test_facility(73))
+		S390_lowcore.machine_flags |= MACHINE_FLAG_TE;
+	if (test_facility(66))
+		S390_lowcore.machine_flags |= MACHINE_FLAG_RRBM;
 #endif
 }
 
@@ -441,7 +459,6 @@ static void __init setup_boot_command_line(void)
 	append_to_cmdline(append_ipl_scpdata);
 }
 
-
 /*
  * Save ipl parameters, clear bss memory, initialize storage keys
  * and create a kernel NSS at startup if the SAVESYS= parm is defined
@@ -468,6 +485,7 @@ void __init startup_init(void)
 	detect_diag44();
 	detect_machine_facilities();
 	setup_hpage();
+	setup_topology();
 	sclp_facilities_detect();
 	detect_memory_layout(memory_chunk);
 #ifdef CONFIG_DYNAMIC_FTRACE
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index 870bad6..ef46f66 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -331,45 +331,38 @@ ENTRY(ret_from_fork)
 	l	%r12,__LC_THREAD_INFO
 	l	%r13,__LC_SVC_NEW_PSW+4
 	tm	__PT_PSW+1(%r11),0x01	# forking a kernel thread ?
-	jo	0f
-	st	%r15,__PT_R15(%r11)	# store stack pointer for new kthread
-0:	l	%r1,BASED(.Lschedule_tail)
+	je	1f
+	l	%r1,BASED(.Lschedule_tail)
 	basr	%r14,%r1		# call schedule_tail
 	TRACE_IRQS_ON
 	ssm	__LC_SVC_NEW_PSW	# reenable interrupts
 	j	sysc_tracenogo
 
+1:	# it's a kernel thread
+	st	%r15,__PT_R15(%r11)	# store stack pointer for new kthread
+	l	%r1,BASED(.Lschedule_tail)
+	basr	%r14,%r1		# call schedule_tail
+	TRACE_IRQS_ON
+	ssm	__LC_SVC_NEW_PSW	# reenable interrupts
+	lm	%r9,%r11,__PT_R9(%r11)	# load gprs
+ENTRY(kernel_thread_starter)
+	la	%r2,0(%r10)
+	basr	%r14,%r9
+	la	%r2,0
+	br	%r11			# do_exit
+
 #
 # kernel_execve function needs to deal with pt_regs that is not
 # at the usual place
 #
-ENTRY(kernel_execve)
-	stm	%r12,%r15,48(%r15)
-	lr	%r14,%r15
-	l	%r13,__LC_SVC_NEW_PSW+4
-	ahi	%r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
-	st	%r14,__SF_BACKCHAIN(%r15)
-	la	%r12,STACK_FRAME_OVERHEAD(%r15)
-	xc	0(__PT_SIZE,%r12),0(%r12)
-	l	%r1,BASED(.Ldo_execve)
-	lr	%r5,%r12
-	basr	%r14,%r1		# call do_execve
-	ltr	%r2,%r2
-	je	0f
-	ahi	%r15,(STACK_FRAME_OVERHEAD + __PT_SIZE)
-	lm	%r12,%r15,48(%r15)
-	br	%r14
-	# execve succeeded.
-0:	ssm	__LC_PGM_NEW_PSW	# disable I/O and ext. interrupts
-	l	%r15,__LC_KERNEL_STACK	# load ksp
-	ahi	%r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
-	la	%r11,STACK_FRAME_OVERHEAD(%r15)
-	mvc	0(__PT_SIZE,%r11),0(%r12)	# copy pt_regs
-	l	%r12,__LC_THREAD_INFO
+ENTRY(ret_from_kernel_execve)
+	ssm	__LC_PGM_NEW_PSW	# disable I/O and ext. interrupts
+	lr	%r15,%r2
+	lr	%r11,%r2
+	ahi	%r15,-STACK_FRAME_OVERHEAD
 	xc	__SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15)
+	l	%r12,__LC_THREAD_INFO
 	ssm	__LC_SVC_NEW_PSW	# reenable interrupts
-	l	%r1,BASED(.Lexecve_tail)
-	basr	%r14,%r1		# call execve_tail
 	j	sysc_return
 
 /*
@@ -931,8 +924,6 @@ cleanup_idle_wait:
 .Ldo_signal:		.long	do_signal
 .Ldo_notify_resume:	.long	do_notify_resume
 .Ldo_per_trap:		.long	do_per_trap
-.Ldo_execve:		.long	do_execve
-.Lexecve_tail:		.long	execve_tail
 .Ljump_table:		.long	pgm_check_table
 .Lschedule:		.long	schedule
 #ifdef CONFIG_PREEMPT
diff --git a/arch/s390/kernel/entry.h b/arch/s390/kernel/entry.h
index a5f4dc4..d0d3f69 100644
--- a/arch/s390/kernel/entry.h
+++ b/arch/s390/kernel/entry.h
@@ -58,9 +58,6 @@ long sys_fork(void);
 long sys_clone(unsigned long newsp, unsigned long clone_flags,
 	       int __user *parent_tidptr, int __user *child_tidptr);
 long sys_vfork(void);
-void execve_tail(void);
-long sys_execve(const char __user *name, const char __user *const __user *argv,
-		const char __user *const __user *envp);
 long sys_sigsuspend(int history0, int history1, old_sigset_t mask);
 long sys_sigaction(int sig, const struct old_sigaction __user *act,
 		   struct old_sigaction __user *oact);
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
index 349b7ee..f9761f8 100644
--- a/arch/s390/kernel/entry64.S
+++ b/arch/s390/kernel/entry64.S
@@ -10,6 +10,7 @@
 
 #include <linux/init.h>
 #include <linux/linkage.h>
+#include <asm/processor.h>
 #include <asm/cache.h>
 #include <asm/errno.h>
 #include <asm/ptrace.h>
@@ -352,41 +353,31 @@ ENTRY(ret_from_fork)
 	la	%r11,STACK_FRAME_OVERHEAD(%r15)
 	lg	%r12,__LC_THREAD_INFO
 	tm	__PT_PSW+1(%r11),0x01	# forking a kernel thread ?
-	jo	0f
-	stg	%r15,__PT_R15(%r11)	# store stack pointer for new kthread
-0:	brasl	%r14,schedule_tail
+	je	1f
+	brasl	%r14,schedule_tail
 	TRACE_IRQS_ON
 	ssm	__LC_SVC_NEW_PSW	# reenable interrupts
 	j	sysc_tracenogo
-
-#
-# kernel_execve function needs to deal with pt_regs that is not
-# at the usual place
-#
-ENTRY(kernel_execve)
-	stmg	%r12,%r15,96(%r15)
-	lgr	%r14,%r15
-	aghi	%r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
-	stg	%r14,__SF_BACKCHAIN(%r15)
-	la	%r12,STACK_FRAME_OVERHEAD(%r15)
-	xc	0(__PT_SIZE,%r12),0(%r12)
-	lgr	%r5,%r12
-	brasl	%r14,do_execve
-	ltgfr	%r2,%r2
-	je	0f
-	aghi	%r15,(STACK_FRAME_OVERHEAD + __PT_SIZE)
-	lmg	%r12,%r15,96(%r15)
-	br	%r14
-	# execve succeeded.
-0:	ssm	__LC_PGM_NEW_PSW	# disable I/O and ext. interrupts
-	lg	%r15,__LC_KERNEL_STACK	# load ksp
-	aghi	%r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
-	la	%r11,STACK_FRAME_OVERHEAD(%r15)
-	mvc	0(__PT_SIZE,%r11),0(%r12)	# copy pt_regs
-	lg	%r12,__LC_THREAD_INFO
+1:	# it's a kernel thread
+	stg	%r15,__PT_R15(%r11)	# store stack pointer for new kthread
+	brasl	%r14,schedule_tail
+	TRACE_IRQS_ON
+	ssm	__LC_SVC_NEW_PSW	# reenable interrupts
+	lmg	%r9,%r11,__PT_R9(%r11)	# load gprs
+ENTRY(kernel_thread_starter)
+	la	%r2,0(%r10)
+	basr	%r14,%r9
+	la	%r2,0
+	br	%r11			# do_exit
+
+ENTRY(ret_from_kernel_execve)
+	ssm	__LC_PGM_NEW_PSW	# disable I/O and ext. interrupts
+	lgr	%r15,%r2
+	lgr	%r11,%r2
+	aghi	%r15,-STACK_FRAME_OVERHEAD
 	xc	__SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
+	lg	%r12,__LC_THREAD_INFO
 	ssm	__LC_SVC_NEW_PSW	# reenable interrupts
-	brasl	%r14,execve_tail
 	j	sysc_return
 
 /*
@@ -412,6 +403,11 @@ ENTRY(pgm_check_handler)
 1:	UPDATE_VTIME %r14,__LC_SYNC_ENTER_TIMER
 	LAST_BREAK %r14
 	lg	%r15,__LC_KERNEL_STACK
+	lg	%r14,__TI_task(%r12)
+	lghi	%r13,__LC_PGM_TDB
+	tm	__LC_PGM_ILC+2,0x02	# check for transaction abort
+	jz	2f
+	mvc	__THREAD_trap_tdb(256,%r14),0(%r13)
 2:	aghi	%r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
 	la	%r11,STACK_FRAME_OVERHEAD(%r15)
 	stmg	%r0,%r7,__PT_R0(%r11)
@@ -422,13 +418,12 @@ ENTRY(pgm_check_handler)
 	stg	%r10,__PT_ARGS(%r11)
 	tm	__LC_PGM_ILC+3,0x80	# check for per exception
 	jz	0f
-	lg	%r1,__TI_task(%r12)
 	tmhh	%r8,0x0001		# kernel per event ?
 	jz	pgm_kprobe
 	oi	__TI_flags+7(%r12),_TIF_PER_TRAP
-	mvc	__THREAD_per_address(8,%r1),__LC_PER_ADDRESS
-	mvc	__THREAD_per_cause(2,%r1),__LC_PER_CAUSE
-	mvc	__THREAD_per_paid(1,%r1),__LC_PER_PAID
+	mvc	__THREAD_per_address(8,%r14),__LC_PER_ADDRESS
+	mvc	__THREAD_per_cause(2,%r14),__LC_PER_CAUSE
+	mvc	__THREAD_per_paid(1,%r14),__LC_PER_PAID
 0:	REENABLE_IRQS
 	xc	__SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
 	larl	%r1,pgm_check_table
@@ -1004,9 +999,7 @@ sie_fault:
 .Lhost_id:
 	.quad	0
 
-	.section __ex_table,"a"
-	.quad	sie_loop,sie_fault
-	.previous
+	EX_TABLE(sie_loop,sie_fault)
 #endif
 
 		.section .rodata, "a"
diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c
index dd7630d..6cdc55b 100644
--- a/arch/s390/kernel/irq.c
+++ b/arch/s390/kernel/irq.c
@@ -30,33 +30,35 @@ struct irq_class {
 };
 
 static const struct irq_class intrclass_names[] = {
-	{.name = "EXT" },
-	{.name = "I/O" },
-	{.name = "CLK", .desc = "[EXT] Clock Comparator" },
-	{.name = "EXC", .desc = "[EXT] External Call" },
-	{.name = "EMS", .desc = "[EXT] Emergency Signal" },
-	{.name = "TMR", .desc = "[EXT] CPU Timer" },
-	{.name = "TAL", .desc = "[EXT] Timing Alert" },
-	{.name = "PFL", .desc = "[EXT] Pseudo Page Fault" },
-	{.name = "DSD", .desc = "[EXT] DASD Diag" },
-	{.name = "VRT", .desc = "[EXT] Virtio" },
-	{.name = "SCP", .desc = "[EXT] Service Call" },
-	{.name = "IUC", .desc = "[EXT] IUCV" },
-	{.name = "CMS", .desc = "[EXT] CPU-Measurement: Sampling" },
-	{.name = "CMC", .desc = "[EXT] CPU-Measurement: Counter" },
-	{.name = "CIO", .desc = "[I/O] Common I/O Layer Interrupt" },
-	{.name = "QAI", .desc = "[I/O] QDIO Adapter Interrupt" },
-	{.name = "DAS", .desc = "[I/O] DASD" },
-	{.name = "C15", .desc = "[I/O] 3215" },
-	{.name = "C70", .desc = "[I/O] 3270" },
-	{.name = "TAP", .desc = "[I/O] Tape" },
-	{.name = "VMR", .desc = "[I/O] Unit Record Devices" },
-	{.name = "LCS", .desc = "[I/O] LCS" },
-	{.name = "CLW", .desc = "[I/O] CLAW" },
-	{.name = "CTC", .desc = "[I/O] CTC" },
-	{.name = "APB", .desc = "[I/O] AP Bus" },
-	{.name = "CSC", .desc = "[I/O] CHSC Subchannel" },
-	{.name = "NMI", .desc = "[NMI] Machine Check" },
+	[EXTERNAL_INTERRUPT] = {.name = "EXT"},
+	[IO_INTERRUPT]	     = {.name = "I/O"},
+	[EXTINT_CLK] = {.name = "CLK", .desc = "[EXT] Clock Comparator"},
+	[EXTINT_EXC] = {.name = "EXC", .desc = "[EXT] External Call"},
+	[EXTINT_EMS] = {.name = "EMS", .desc = "[EXT] Emergency Signal"},
+	[EXTINT_TMR] = {.name = "TMR", .desc = "[EXT] CPU Timer"},
+	[EXTINT_TLA] = {.name = "TAL", .desc = "[EXT] Timing Alert"},
+	[EXTINT_PFL] = {.name = "PFL", .desc = "[EXT] Pseudo Page Fault"},
+	[EXTINT_DSD] = {.name = "DSD", .desc = "[EXT] DASD Diag"},
+	[EXTINT_VRT] = {.name = "VRT", .desc = "[EXT] Virtio"},
+	[EXTINT_SCP] = {.name = "SCP", .desc = "[EXT] Service Call"},
+	[EXTINT_IUC] = {.name = "IUC", .desc = "[EXT] IUCV"},
+	[EXTINT_CMS] = {.name = "CMS", .desc = "[EXT] CPU-Measurement: Sampling"},
+	[EXTINT_CMC] = {.name = "CMC", .desc = "[EXT] CPU-Measurement: Counter"},
+	[EXTINT_CMR] = {.name = "CMR", .desc = "[EXT] CPU-Measurement: RI"},
+	[IOINT_CIO]  = {.name = "CIO", .desc = "[I/O] Common I/O Layer Interrupt"},
+	[IOINT_QAI]  = {.name = "QAI", .desc = "[I/O] QDIO Adapter Interrupt"},
+	[IOINT_DAS]  = {.name = "DAS", .desc = "[I/O] DASD"},
+	[IOINT_C15]  = {.name = "C15", .desc = "[I/O] 3215"},
+	[IOINT_C70]  = {.name = "C70", .desc = "[I/O] 3270"},
+	[IOINT_TAP]  = {.name = "TAP", .desc = "[I/O] Tape"},
+	[IOINT_VMR]  = {.name = "VMR", .desc = "[I/O] Unit Record Devices"},
+	[IOINT_LCS]  = {.name = "LCS", .desc = "[I/O] LCS"},
+	[IOINT_CLW]  = {.name = "CLW", .desc = "[I/O] CLAW"},
+	[IOINT_CTC]  = {.name = "CTC", .desc = "[I/O] CTC"},
+	[IOINT_APB]  = {.name = "APB", .desc = "[I/O] AP Bus"},
+	[IOINT_ADM]  = {.name = "ADM", .desc = "[I/O] EADM Subchannel"},
+	[IOINT_CSC]  = {.name = "CSC", .desc = "[I/O] CHSC Subchannel"},
+	[NMI_NMI]    = {.name = "NMI", .desc = "[NMI] Machine Check"},
 };
 
 /*
diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c
index 8aa634f..d1c7214 100644
--- a/arch/s390/kernel/kprobes.c
+++ b/arch/s390/kernel/kprobes.c
@@ -547,7 +547,7 @@ static int __kprobes kprobe_trap_handler(struct pt_regs *regs, int trapnr)
 		 */
 		entry = search_exception_tables(regs->psw.addr & PSW_ADDR_INSN);
 		if (entry) {
-			regs->psw.addr = entry->fixup | PSW_ADDR_AMODE;
+			regs->psw.addr = extable_fixup(entry) | PSW_ADDR_AMODE;
 			return 1;
 		}
 
diff --git a/arch/s390/kernel/lgr.c b/arch/s390/kernel/lgr.c
index eca94e7..6ea6d69 100644
--- a/arch/s390/kernel/lgr.c
+++ b/arch/s390/kernel/lgr.c
@@ -51,16 +51,6 @@ static struct lgr_info lgr_info_cur;
 static struct debug_info *lgr_dbf;
 
 /*
- * Return number of valid stsi levels
- */
-static inline int stsi_0(void)
-{
-	int rc = stsi(NULL, 0, 0, 0);
-
-	return rc == -ENOSYS ? rc : (((unsigned int) rc) >> 28);
-}
-
-/*
  * Copy buffer and then convert it to ASCII
  */
 static void cpascii(char *dst, char *src, int size)
@@ -76,7 +66,7 @@ static void lgr_stsi_1_1_1(struct lgr_info *lgr_info)
 {
 	struct sysinfo_1_1_1 *si = (void *) lgr_page;
 
-	if (stsi(si, 1, 1, 1) == -ENOSYS)
+	if (stsi(si, 1, 1, 1))
 		return;
 	cpascii(lgr_info->manufacturer, si->manufacturer,
 		sizeof(si->manufacturer));
@@ -93,7 +83,7 @@ static void lgr_stsi_2_2_2(struct lgr_info *lgr_info)
 {
 	struct sysinfo_2_2_2 *si = (void *) lgr_page;
 
-	if (stsi(si, 2, 2, 2) == -ENOSYS)
+	if (stsi(si, 2, 2, 2))
 		return;
 	cpascii(lgr_info->name, si->name, sizeof(si->name));
 	memcpy(&lgr_info->lpar_number, &si->lpar_number,
@@ -108,7 +98,7 @@ static void lgr_stsi_3_2_2(struct lgr_info *lgr_info)
 	struct sysinfo_3_2_2 *si = (void *) lgr_page;
 	int i;
 
-	if (stsi(si, 3, 2, 2) == -ENOSYS)
+	if (stsi(si, 3, 2, 2))
 		return;
 	for (i = 0; i < min_t(u8, si->count, VM_LEVEL_MAX); i++) {
 		cpascii(lgr_info->vm[i].name, si->vm[i].name,
@@ -124,16 +114,17 @@ static void lgr_stsi_3_2_2(struct lgr_info *lgr_info)
  */
 static void lgr_info_get(struct lgr_info *lgr_info)
 {
+	int level;
+
 	memset(lgr_info, 0, sizeof(*lgr_info));
 	stfle(lgr_info->stfle_fac_list, ARRAY_SIZE(lgr_info->stfle_fac_list));
-	lgr_info->level = stsi_0();
-	if (lgr_info->level == -ENOSYS)
-		return;
-	if (lgr_info->level >= 1)
+	level = stsi(NULL, 0, 0, 0);
+	lgr_info->level = level;
+	if (level >= 1)
 		lgr_stsi_1_1_1(lgr_info);
-	if (lgr_info->level >= 2)
+	if (level >= 2)
 		lgr_stsi_2_2_2(lgr_info);
-	if (lgr_info->level >= 3)
+	if (level >= 3)
 		lgr_stsi_3_2_2(lgr_info);
 }
 
diff --git a/arch/s390/kernel/machine_kexec.c b/arch/s390/kernel/machine_kexec.c
index 493304b..b3de277 100644
--- a/arch/s390/kernel/machine_kexec.c
+++ b/arch/s390/kernel/machine_kexec.c
@@ -21,6 +21,7 @@
 #include <asm/reset.h>
 #include <asm/ipl.h>
 #include <asm/diag.h>
+#include <asm/elf.h>
 #include <asm/asm-offsets.h>
 #include <asm/os_info.h>
 
@@ -31,8 +32,6 @@ extern const unsigned long long relocate_kernel_len;
 
 #ifdef CONFIG_CRASH_DUMP
 
-void *fill_cpu_elf_notes(void *ptr, struct save_area *sa);
-
 /*
  * Create ELF notes for one CPU
  */
@@ -159,7 +158,7 @@ int machine_kexec_prepare(struct kimage *image)
 
 	/* Can't replace kernel image since it is read-only. */
 	if (ipl_flags & IPL_NSS_VALID)
-		return -ENOSYS;
+		return -EOPNOTSUPP;
 
 	if (image->type == KEXEC_TYPE_CRASH)
 		return machine_kexec_prepare_kdump();
@@ -191,6 +190,10 @@ void machine_shutdown(void)
 {
 }
 
+void machine_crash_shutdown(struct pt_regs *regs)
+{
+}
+
 /*
  * Do normal kexec
  */
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c
index 7331753..cd31ad4 100644
--- a/arch/s390/kernel/process.c
+++ b/arch/s390/kernel/process.c
@@ -26,10 +26,12 @@
 #include <asm/io.h>
 #include <asm/processor.h>
 #include <asm/vtimer.h>
+#include <asm/exec.h>
 #include <asm/irq.h>
 #include <asm/nmi.h>
 #include <asm/smp.h>
 #include <asm/switch_to.h>
+#include <asm/runtime_instr.h>
 #include "entry.h"
 
 asmlinkage void ret_from_fork(void) asm ("ret_from_fork");
@@ -98,40 +100,12 @@ void cpu_idle(void)
 
 extern void __kprobes kernel_thread_starter(void);
 
-asm(
-	".section .kprobes.text, \"ax\"\n"
-	".global kernel_thread_starter\n"
-	"kernel_thread_starter:\n"
-	"    la    2,0(10)\n"
-	"    basr  14,9\n"
-	"    la    2,0\n"
-	"    br    11\n"
-	".previous\n");
-
-int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
-{
-	struct pt_regs regs;
-
-	memset(&regs, 0, sizeof(regs));
-	regs.psw.mask = psw_kernel_bits |
-		PSW_MASK_DAT | PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK;
-	regs.psw.addr = (unsigned long) kernel_thread_starter | PSW_ADDR_AMODE;
-	regs.gprs[9] = (unsigned long) fn;
-	regs.gprs[10] = (unsigned long) arg;
-	regs.gprs[11] = (unsigned long) do_exit;
-	regs.orig_gpr2 = -1;
-
-	/* Ok, create the new process.. */
-	return do_fork(flags | CLONE_VM | CLONE_UNTRACED,
-		       0, &regs, 0, NULL, NULL);
-}
-EXPORT_SYMBOL(kernel_thread);
-
 /*
  * Free current thread data structures etc..
  */
 void exit_thread(void)
 {
+	exit_thread_runtime_instr();
 }
 
 void flush_thread(void)
@@ -143,7 +117,7 @@ void release_thread(struct task_struct *dead_task)
 }
 
 int copy_thread(unsigned long clone_flags, unsigned long new_stackp,
-		unsigned long unused,
+		unsigned long arg,
 		struct task_struct *p, struct pt_regs *regs)
 {
 	struct thread_info *ti;
@@ -155,20 +129,49 @@ int copy_thread(unsigned long clone_flags, unsigned long new_stackp,
 
 	frame = container_of(task_pt_regs(p), struct fake_frame, childregs);
 	p->thread.ksp = (unsigned long) frame;
-	/* Store access registers to kernel stack of new process. */
-	frame->childregs = *regs;
-	frame->childregs.gprs[2] = 0;	/* child returns 0 on fork. */
-	frame->childregs.gprs[15] = new_stackp;
-	frame->sf.back_chain = 0;
+	/* Save access registers to new thread structure. */
+	save_access_regs(&p->thread.acrs[0]);
+	/* start new process with ar4 pointing to the correct address space */
+	p->thread.mm_segment = get_fs();
+	/* Don't copy debug registers */
+	memset(&p->thread.per_user, 0, sizeof(p->thread.per_user));
+	memset(&p->thread.per_event, 0, sizeof(p->thread.per_event));
+	clear_tsk_thread_flag(p, TIF_SINGLE_STEP);
+	clear_tsk_thread_flag(p, TIF_PER_TRAP);
+	/* Initialize per thread user and system timer values */
+	ti = task_thread_info(p);
+	ti->user_timer = 0;
+	ti->system_timer = 0;
 
+	frame->sf.back_chain = 0;
 	/* new return point is ret_from_fork */
 	frame->sf.gprs[8] = (unsigned long) ret_from_fork;
-
 	/* fake return stack for resume(), don't go back to schedule */
 	frame->sf.gprs[9] = (unsigned long) frame;
 
-	/* Save access registers to new thread structure. */
-	save_access_regs(&p->thread.acrs[0]);
+	/* Store access registers to kernel stack of new process. */
+	if (unlikely(!regs)) {
+		/* kernel thread */
+		memset(&frame->childregs, 0, sizeof(struct pt_regs));
+		frame->childregs.psw.mask = psw_kernel_bits | PSW_MASK_DAT |
+				PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK;
+		frame->childregs.psw.addr = PSW_ADDR_AMODE |
+				(unsigned long) kernel_thread_starter;
+		frame->childregs.gprs[9] = new_stackp; /* function */
+		frame->childregs.gprs[10] = arg;
+		frame->childregs.gprs[11] = (unsigned long) do_exit;
+		frame->childregs.orig_gpr2 = -1;
+
+		return 0;
+	}
+	frame->childregs = *regs;
+	frame->childregs.gprs[2] = 0;	/* child returns 0 on fork. */
+	frame->childregs.gprs[15] = new_stackp;
+
+	/* Don't copy runtime instrumentation info */
+	p->thread.ri_cb = NULL;
+	p->thread.ri_signum = 0;
+	frame->childregs.psw.mask &= ~PSW_MASK_RI;
 
 #ifndef CONFIG_64BIT
 	/*
@@ -194,17 +197,6 @@ int copy_thread(unsigned long clone_flags, unsigned long new_stackp,
 		}
 	}
 #endif /* CONFIG_64BIT */
-	/* start new process with ar4 pointing to the correct address space */
-	p->thread.mm_segment = get_fs();
-	/* Don't copy debug registers */
-	memset(&p->thread.per_user, 0, sizeof(p->thread.per_user));
-	memset(&p->thread.per_event, 0, sizeof(p->thread.per_event));
-	clear_tsk_thread_flag(p, TIF_SINGLE_STEP);
-	clear_tsk_thread_flag(p, TIF_PER_TRAP);
-	/* Initialize per thread user and system timer values */
-	ti = task_thread_info(p);
-	ti->user_timer = 0;
-	ti->system_timer = 0;
 	return 0;
 }
 
@@ -250,31 +242,6 @@ asmlinkage void execve_tail(void)
 }
 
 /*
- * sys_execve() executes a new program.
- */
-SYSCALL_DEFINE3(execve, const char __user *, name,
-		const char __user *const __user *, argv,
-		const char __user *const __user *, envp)
-{
-	struct pt_regs *regs = task_pt_regs(current);
-	char *filename;
-	long rc;
-
-	filename = getname(name);
-	rc = PTR_ERR(filename);
-	if (IS_ERR(filename))
-		return rc;
-	rc = do_execve(filename, argv, envp, regs);
-	if (rc)
-		goto out;
-	execve_tail();
-	rc = regs->gprs[2];
-out:
-	putname(filename);
-	return rc;
-}
-
-/*
  * fill in the FPU structure for a core dump.
  */
 int dump_fpu (struct pt_regs * regs, s390_fp_regs *fpregs)
diff --git a/arch/s390/kernel/processor.c b/arch/s390/kernel/processor.c
index 572d4c9..753c41d 100644
--- a/arch/s390/kernel/processor.c
+++ b/arch/s390/kernel/processor.c
@@ -39,9 +39,9 @@ void __cpuinit cpu_init(void)
  */
 static int show_cpuinfo(struct seq_file *m, void *v)
 {
-	static const char *hwcap_str[10] = {
+	static const char *hwcap_str[] = {
 		"esan3", "zarch", "stfle", "msa", "ldisp", "eimm", "dfp",
-		"edat", "etf3eh", "highgprs"
+		"edat", "etf3eh", "highgprs", "te"
 	};
 	unsigned long n = (unsigned long) v - 1;
 	int i;
@@ -54,10 +54,11 @@ static int show_cpuinfo(struct seq_file *m, void *v)
 			   num_online_cpus(), loops_per_jiffy/(500000/HZ),
 			   (loops_per_jiffy/(5000/HZ))%100);
 		seq_puts(m, "features\t: ");
-		for (i = 0; i < 10; i++)
+		for (i = 0; i < ARRAY_SIZE(hwcap_str); i++)
 			if (hwcap_str[i] && (elf_hwcap & (1UL << i)))
 				seq_printf(m, "%s ", hwcap_str[i]);
 		seq_puts(m, "\n");
+		show_cacheinfo(m);
 	}
 	get_online_cpus();
 	if (cpu_online(n)) {
diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c
index e4be113..a314c57 100644
--- a/arch/s390/kernel/ptrace.c
+++ b/arch/s390/kernel/ptrace.c
@@ -42,6 +42,7 @@ enum s390_regset {
 	REGSET_GENERAL,
 	REGSET_FP,
 	REGSET_LAST_BREAK,
+	REGSET_TDB,
 	REGSET_SYSTEM_CALL,
 	REGSET_GENERAL_EXTENDED,
 };
@@ -52,6 +53,22 @@ void update_per_regs(struct task_struct *task)
 	struct thread_struct *thread = &task->thread;
 	struct per_regs old, new;
 
+#ifdef CONFIG_64BIT
+	/* Take care of the enable/disable of transactional execution. */
+	if (MACHINE_HAS_TE) {
+		unsigned long cr0, cr0_new;
+
+		__ctl_store(cr0, 0, 0);
+		/* set or clear transaction execution bits 8 and 9. */
+		if (task->thread.per_flags & PER_FLAG_NO_TE)
+			cr0_new = cr0 & ~(3UL << 54);
+		else
+			cr0_new = cr0 | (3UL << 54);
+		/* Only load control register 0 if necessary. */
+		if (cr0 != cr0_new)
+			__ctl_load(cr0_new, 0, 0);
+	}
+#endif
 	/* Copy user specified PER registers */
 	new.control = thread->per_user.control;
 	new.start = thread->per_user.start;
@@ -60,6 +77,10 @@ void update_per_regs(struct task_struct *task)
 	/* merge TIF_SINGLE_STEP into user specified PER registers. */
 	if (test_tsk_thread_flag(task, TIF_SINGLE_STEP)) {
 		new.control |= PER_EVENT_IFETCH;
+#ifdef CONFIG_64BIT
+		new.control |= PER_CONTROL_SUSPENSION;
+		new.control |= PER_EVENT_TRANSACTION_END;
+#endif
 		new.start = 0;
 		new.end = PSW_ADDR_INSN;
 	}
@@ -100,6 +121,7 @@ void ptrace_disable(struct task_struct *task)
 	memset(&task->thread.per_event, 0, sizeof(task->thread.per_event));
 	clear_tsk_thread_flag(task, TIF_SINGLE_STEP);
 	clear_tsk_thread_flag(task, TIF_PER_TRAP);
+	task->thread.per_flags = 0;
 }
 
 #ifndef CONFIG_64BIT
@@ -416,6 +438,16 @@ long arch_ptrace(struct task_struct *child, long request,
 		put_user(task_thread_info(child)->last_break,
 			 (unsigned long __user *) data);
 		return 0;
+	case PTRACE_ENABLE_TE:
+		if (!MACHINE_HAS_TE)
+			return -EIO;
+		child->thread.per_flags &= ~PER_FLAG_NO_TE;
+		return 0;
+	case PTRACE_DISABLE_TE:
+		if (!MACHINE_HAS_TE)
+			return -EIO;
+		child->thread.per_flags |= PER_FLAG_NO_TE;
+		return 0;
 	default:
 		/* Removing high order bit from addr (only for 31 bit). */
 		addr &= PSW_ADDR_INSN;
@@ -903,6 +935,28 @@ static int s390_last_break_set(struct task_struct *target,
 	return 0;
 }
 
+static int s390_tdb_get(struct task_struct *target,
+			const struct user_regset *regset,
+			unsigned int pos, unsigned int count,
+			void *kbuf, void __user *ubuf)
+{
+	struct pt_regs *regs = task_pt_regs(target);
+	unsigned char *data;
+
+	if (!(regs->int_code & 0x200))
+		return -ENODATA;
+	data = target->thread.trap_tdb;
+	return user_regset_copyout(&pos, &count, &kbuf, &ubuf, data, 0, 256);
+}
+
+static int s390_tdb_set(struct task_struct *target,
+			const struct user_regset *regset,
+			unsigned int pos, unsigned int count,
+			const void *kbuf, const void __user *ubuf)
+{
+	return 0;
+}
+
 #endif
 
 static int s390_system_call_get(struct task_struct *target,
@@ -951,6 +1005,14 @@ static const struct user_regset s390_regsets[] = {
 		.get = s390_last_break_get,
 		.set = s390_last_break_set,
 	},
+	[REGSET_TDB] = {
+		.core_note_type = NT_S390_TDB,
+		.n = 1,
+		.size = 256,
+		.align = 1,
+		.get = s390_tdb_get,
+		.set = s390_tdb_set,
+	},
 #endif
 	[REGSET_SYSTEM_CALL] = {
 		.core_note_type = NT_S390_SYSTEM_CALL,
@@ -1148,6 +1210,14 @@ static const struct user_regset s390_compat_regsets[] = {
 		.get = s390_compat_last_break_get,
 		.set = s390_compat_last_break_set,
 	},
+	[REGSET_TDB] = {
+		.core_note_type = NT_S390_TDB,
+		.n = 1,
+		.size = 256,
+		.align = 1,
+		.get = s390_tdb_get,
+		.set = s390_tdb_set,
+	},
 	[REGSET_SYSTEM_CALL] = {
 		.core_note_type = NT_S390_SYSTEM_CALL,
 		.n = 1,
diff --git a/arch/s390/kernel/runtime_instr.c b/arch/s390/kernel/runtime_instr.c
new file mode 100644
index 0000000..61066f6
--- /dev/null
+++ b/arch/s390/kernel/runtime_instr.c
@@ -0,0 +1,150 @@
+/*
+ * Copyright IBM Corp. 2012
+ * Author(s): Jan Glauber <jang@linux.vnet.ibm.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/syscalls.h>
+#include <linux/signal.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/kernel_stat.h>
+#include <asm/runtime_instr.h>
+#include <asm/cpu_mf.h>
+#include <asm/irq.h>
+
+/* empty control block to disable RI by loading it */
+struct runtime_instr_cb runtime_instr_empty_cb;
+
+static int runtime_instr_avail(void)
+{
+	return test_facility(64);
+}
+
+static void disable_runtime_instr(void)
+{
+	struct pt_regs *regs = task_pt_regs(current);
+
+	load_runtime_instr_cb(&runtime_instr_empty_cb);
+
+	/*
+	 * Make sure the RI bit is deleted from the PSW. If the user did not
+	 * switch off RI before the system call the process will get a
+	 * specification exception otherwise.
+	 */
+	regs->psw.mask &= ~PSW_MASK_RI;
+}
+
+static void init_runtime_instr_cb(struct runtime_instr_cb *cb)
+{
+	cb->buf_limit = 0xfff;
+	if (s390_user_mode == HOME_SPACE_MODE)
+		cb->home_space = 1;
+	cb->int_requested = 1;
+	cb->pstate = 1;
+	cb->pstate_set_buf = 1;
+	cb->pstate_sample = 1;
+	cb->pstate_collect = 1;
+	cb->key = PAGE_DEFAULT_KEY;
+	cb->valid = 1;
+}
+
+void exit_thread_runtime_instr(void)
+{
+	struct task_struct *task = current;
+
+	if (!task->thread.ri_cb)
+		return;
+	disable_runtime_instr();
+	kfree(task->thread.ri_cb);
+	task->thread.ri_signum = 0;
+	task->thread.ri_cb = NULL;
+}
+
+static void runtime_instr_int_handler(struct ext_code ext_code,
+				unsigned int param32, unsigned long param64)
+{
+	struct siginfo info;
+
+	if (!(param32 & CPU_MF_INT_RI_MASK))
+		return;
+
+	kstat_cpu(smp_processor_id()).irqs[EXTINT_CMR]++;
+
+	if (!current->thread.ri_cb)
+		return;
+	if (current->thread.ri_signum < SIGRTMIN ||
+	    current->thread.ri_signum > SIGRTMAX) {
+		WARN_ON_ONCE(1);
+		return;
+	}
+
+	memset(&info, 0, sizeof(info));
+	info.si_signo = current->thread.ri_signum;
+	info.si_code = SI_QUEUE;
+	if (param32 & CPU_MF_INT_RI_BUF_FULL)
+		info.si_int = ENOBUFS;
+	else if (param32 & CPU_MF_INT_RI_HALTED)
+		info.si_int = ECANCELED;
+	else
+		return; /* unknown reason */
+
+	send_sig_info(current->thread.ri_signum, &info, current);
+}
+
+SYSCALL_DEFINE2(s390_runtime_instr, int, command, int, signum)
+{
+	struct runtime_instr_cb *cb;
+
+	if (!runtime_instr_avail())
+		return -EOPNOTSUPP;
+
+	if (command == S390_RUNTIME_INSTR_STOP) {
+		preempt_disable();
+		exit_thread_runtime_instr();
+		preempt_enable();
+		return 0;
+	}
+
+	if (command != S390_RUNTIME_INSTR_START ||
+	    (signum < SIGRTMIN || signum > SIGRTMAX))
+		return -EINVAL;
+
+	if (!current->thread.ri_cb) {
+		cb = kzalloc(sizeof(*cb), GFP_KERNEL);
+		if (!cb)
+			return -ENOMEM;
+	} else {
+		cb = current->thread.ri_cb;
+		memset(cb, 0, sizeof(*cb));
+	}
+
+	init_runtime_instr_cb(cb);
+	current->thread.ri_signum = signum;
+
+	/* now load the control block to make it available */
+	preempt_disable();
+	current->thread.ri_cb = cb;
+	load_runtime_instr_cb(cb);
+	preempt_enable();
+	return 0;
+}
+
+static int __init runtime_instr_init(void)
+{
+	int rc;
+
+	if (!runtime_instr_avail())
+		return 0;
+
+	measurement_alert_subclass_register();
+	rc = register_external_interrupt(0x1407, runtime_instr_int_handler);
+	if (rc)
+		measurement_alert_subclass_unregister();
+	else
+		pr_info("Runtime instrumentation facility initialized\n");
+	return rc;
+}
+device_initcall(runtime_instr_init);
diff --git a/arch/s390/kernel/s390_ksyms.c b/arch/s390/kernel/s390_ksyms.c
index 57b5366..9bdbcef 100644
--- a/arch/s390/kernel/s390_ksyms.c
+++ b/arch/s390/kernel/s390_ksyms.c
@@ -8,3 +8,5 @@ EXPORT_SYMBOL(_mcount);
 #if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
 EXPORT_SYMBOL(sie64a);
 #endif
+EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(memset);
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index 40b5769..afa9fdb 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -302,10 +302,10 @@ static int __init parse_vmalloc(char *arg)
 }
 early_param("vmalloc", parse_vmalloc);
 
-unsigned int addressing_mode = HOME_SPACE_MODE;
-EXPORT_SYMBOL_GPL(addressing_mode);
+unsigned int s390_user_mode = PRIMARY_SPACE_MODE;
+EXPORT_SYMBOL_GPL(s390_user_mode);
 
-static int set_amode_primary(void)
+static void __init set_user_mode_primary(void)
 {
 	psw_kernel_bits = (psw_kernel_bits & ~PSW_MASK_ASC) | PSW_ASC_HOME;
 	psw_user_bits = (psw_user_bits & ~PSW_MASK_ASC) | PSW_ASC_PRIMARY;
@@ -313,48 +313,30 @@ static int set_amode_primary(void)
 	psw32_user_bits =
 		(psw32_user_bits & ~PSW32_MASK_ASC) | PSW32_ASC_PRIMARY;
 #endif
-
-	if (MACHINE_HAS_MVCOS) {
-		memcpy(&uaccess, &uaccess_mvcos_switch, sizeof(uaccess));
-		return 1;
-	} else {
-		memcpy(&uaccess, &uaccess_pt, sizeof(uaccess));
-		return 0;
-	}
-}
-
-/*
- * Switch kernel/user addressing modes?
- */
-static int __init early_parse_switch_amode(char *p)
-{
-	addressing_mode = PRIMARY_SPACE_MODE;
-	return 0;
+	uaccess = MACHINE_HAS_MVCOS ? uaccess_mvcos_switch : uaccess_pt;
 }
-early_param("switch_amode", early_parse_switch_amode);
 
 static int __init early_parse_user_mode(char *p)
 {
 	if (p && strcmp(p, "primary") == 0)
-		addressing_mode = PRIMARY_SPACE_MODE;
+		s390_user_mode = PRIMARY_SPACE_MODE;
 	else if (!p || strcmp(p, "home") == 0)
-		addressing_mode = HOME_SPACE_MODE;
+		s390_user_mode = HOME_SPACE_MODE;
 	else
 		return 1;
 	return 0;
 }
 early_param("user_mode", early_parse_user_mode);
 
-static void setup_addressing_mode(void)
+static void __init setup_addressing_mode(void)
 {
-	if (addressing_mode == PRIMARY_SPACE_MODE) {
-		if (set_amode_primary())
-			pr_info("Address spaces switched, "
-				"mvcos available\n");
-		else
-			pr_info("Address spaces switched, "
-				"mvcos not available\n");
-	}
+	if (s390_user_mode != PRIMARY_SPACE_MODE)
+		return;
+	set_user_mode_primary();
+	if (MACHINE_HAS_MVCOS)
+		pr_info("Address spaces switched, mvcos available\n");
+	else
+		pr_info("Address spaces switched, mvcos not available\n");
 }
 
 void *restart_stack __attribute__((__section__(".data")));
@@ -602,9 +584,7 @@ static void __init setup_memory_end(void)
 
 static void __init setup_vmcoreinfo(void)
 {
-#ifdef CONFIG_KEXEC
 	mem_assign_absolute(S390_lowcore.vmcore_info, paddr_vmcoreinfo_note());
-#endif
 }
 
 #ifdef CONFIG_CRASH_DUMP
@@ -980,6 +960,12 @@ static void __init setup_hwcaps(void)
 	 * HWCAP_S390_HIGH_GPRS is bit 9.
 	 */
 	elf_hwcap |= HWCAP_S390_HIGH_GPRS;
+
+	/*
+	 * Transactional execution support HWCAP_S390_TE is bit 10.
+	 */
+	if (test_facility(50) && test_facility(73))
+		elf_hwcap |= HWCAP_S390_TE;
 #endif
 
 	get_cpu_id(&cpu_id);
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 720fda1..ea431e5 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -66,7 +66,7 @@ struct pcpu {
 	unsigned long panic_stack;	/* panic stack for the cpu */
 	unsigned long ec_mask;		/* bit mask for ec_xxx functions */
 	int state;			/* physical cpu state */
-	u32 status;			/* last status received via sigp */
+	int polarization;		/* physical polarization */
 	u16 address;			/* physical cpu address */
 };
 
@@ -74,6 +74,10 @@ static u8 boot_cpu_type;
 static u16 boot_cpu_address;
 static struct pcpu pcpu_devices[NR_CPUS];
 
+/*
+ * The smp_cpu_state_mutex must be held when changing the state or polarization
+ * member of a pcpu data structure within the pcpu_devices arreay.
+ */
 DEFINE_MUTEX(smp_cpu_state_mutex);
 
 /*
@@ -99,7 +103,7 @@ static inline int __pcpu_sigp_relax(u16 addr, u8 order, u32 parm, u32 *status)
 	int cc;
 
 	while (1) {
-		cc = __pcpu_sigp(addr, order, parm, status);
+		cc = __pcpu_sigp(addr, order, parm, NULL);
 		if (cc != SIGP_CC_BUSY)
 			return cc;
 		cpu_relax();
@@ -111,7 +115,7 @@ static int pcpu_sigp_retry(struct pcpu *pcpu, u8 order, u32 parm)
 	int cc, retry;
 
 	for (retry = 0; ; retry++) {
-		cc = __pcpu_sigp(pcpu->address, order, parm, &pcpu->status);
+		cc = __pcpu_sigp(pcpu->address, order, parm, NULL);
 		if (cc != SIGP_CC_BUSY)
 			break;
 		if (retry >= 3)
@@ -122,16 +126,18 @@ static int pcpu_sigp_retry(struct pcpu *pcpu, u8 order, u32 parm)
 
 static inline int pcpu_stopped(struct pcpu *pcpu)
 {
+	u32 uninitialized_var(status);
+
 	if (__pcpu_sigp(pcpu->address, SIGP_SENSE,
-			0, &pcpu->status) != SIGP_CC_STATUS_STORED)
+			0, &status) != SIGP_CC_STATUS_STORED)
 		return 0;
-	return !!(pcpu->status & (SIGP_STATUS_CHECK_STOP|SIGP_STATUS_STOPPED));
+	return !!(status & (SIGP_STATUS_CHECK_STOP|SIGP_STATUS_STOPPED));
 }
 
 static inline int pcpu_running(struct pcpu *pcpu)
 {
 	if (__pcpu_sigp(pcpu->address, SIGP_SENSE_RUNNING,
-			0, &pcpu->status) != SIGP_CC_STATUS_STORED)
+			0, NULL) != SIGP_CC_STATUS_STORED)
 		return 1;
 	/* Status stored condition code is equivalent to cpu not running. */
 	return 0;
@@ -586,6 +592,16 @@ static inline void smp_get_save_area(int cpu, u16 address) { }
 
 #endif /* CONFIG_ZFCPDUMP || CONFIG_CRASH_DUMP */
 
+void smp_cpu_set_polarization(int cpu, int val)
+{
+	pcpu_devices[cpu].polarization = val;
+}
+
+int smp_cpu_get_polarization(int cpu)
+{
+	return pcpu_devices[cpu].polarization;
+}
+
 static struct sclp_cpu_info *smp_get_cpu_info(void)
 {
 	static int use_sigp_detection;
@@ -628,7 +644,7 @@ static int __devinit __smp_rescan_cpus(struct sclp_cpu_info *info,
 		pcpu->address = info->cpu[i].address;
 		pcpu->state = (cpu >= info->configured) ?
 			CPU_STATE_STANDBY : CPU_STATE_CONFIGURED;
-		cpu_set_polarization(cpu, POLARIZATION_UNKNOWN);
+		smp_cpu_set_polarization(cpu, POLARIZATION_UNKNOWN);
 		set_cpu_present(cpu, true);
 		if (sysfs_add && smp_add_present_cpu(cpu) != 0)
 			set_cpu_present(cpu, false);
@@ -796,7 +812,7 @@ void __init smp_prepare_boot_cpu(void)
 	pcpu->async_stack = S390_lowcore.async_stack - ASYNC_SIZE;
 	pcpu->panic_stack = S390_lowcore.panic_stack - PAGE_SIZE;
 	S390_lowcore.percpu_offset = __per_cpu_offset[0];
-	cpu_set_polarization(0, POLARIZATION_UNKNOWN);
+	smp_cpu_set_polarization(0, POLARIZATION_UNKNOWN);
 	set_cpu_present(0, true);
 	set_cpu_online(0, true);
 }
@@ -862,7 +878,7 @@ static ssize_t cpu_configure_store(struct device *dev,
 		if (rc)
 			break;
 		pcpu->state = CPU_STATE_STANDBY;
-		cpu_set_polarization(cpu, POLARIZATION_UNKNOWN);
+		smp_cpu_set_polarization(cpu, POLARIZATION_UNKNOWN);
 		topology_expect_change();
 		break;
 	case 1:
@@ -872,7 +888,7 @@ static ssize_t cpu_configure_store(struct device *dev,
 		if (rc)
 			break;
 		pcpu->state = CPU_STATE_CONFIGURED;
-		cpu_set_polarization(cpu, POLARIZATION_UNKNOWN);
+		smp_cpu_set_polarization(cpu, POLARIZATION_UNKNOWN);
 		topology_expect_change();
 		break;
 	default:
@@ -959,23 +975,17 @@ static int __cpuinit smp_cpu_notify(struct notifier_block *self,
 	struct device *s = &c->dev;
 	int err = 0;
 
-	switch (action) {
+	switch (action & ~CPU_TASKS_FROZEN) {
 	case CPU_ONLINE:
-	case CPU_ONLINE_FROZEN:
 		err = sysfs_create_group(&s->kobj, &cpu_online_attr_group);
 		break;
 	case CPU_DEAD:
-	case CPU_DEAD_FROZEN:
 		sysfs_remove_group(&s->kobj, &cpu_online_attr_group);
 		break;
 	}
 	return notifier_from_errno(err);
 }
 
-static struct notifier_block __cpuinitdata smp_cpu_nb = {
-	.notifier_call = smp_cpu_notify,
-};
-
 static int __devinit smp_add_present_cpu(int cpu)
 {
 	struct cpu *c = &pcpu_devices[cpu].cpu;
@@ -1050,7 +1060,7 @@ static int __init s390_smp_init(void)
 {
 	int cpu, rc;
 
-	register_cpu_notifier(&smp_cpu_nb);
+	hotcpu_notifier(smp_cpu_notify, 0);
 #ifdef CONFIG_HOTPLUG_CPU
 	rc = device_create_file(cpu_subsys.dev_root, &dev_attr_rescan);
 	if (rc)
diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S
index bcab2f0..4817485 100644
--- a/arch/s390/kernel/syscalls.S
+++ b/arch/s390/kernel/syscalls.S
@@ -350,3 +350,5 @@ SYSCALL(sys_syncfs,sys_syncfs,sys_syncfs_wrapper)
 SYSCALL(sys_setns,sys_setns,sys_setns_wrapper)
 SYSCALL(sys_process_vm_readv,sys_process_vm_readv,compat_sys_process_vm_readv_wrapper) /* 340 */
 SYSCALL(sys_process_vm_writev,sys_process_vm_writev,compat_sys_process_vm_writev_wrapper)
+SYSCALL(sys_ni_syscall,sys_s390_runtime_instr,sys_s390_runtime_instr_wrapper)
+SYSCALL(sys_kcmp,sys_kcmp,sys_kcmp_wrapper)
diff --git a/arch/s390/kernel/sysinfo.c b/arch/s390/kernel/sysinfo.c
index fa0eb23..62f89d9 100644
--- a/arch/s390/kernel/sysinfo.c
+++ b/arch/s390/kernel/sysinfo.c
@@ -22,17 +22,41 @@
 #include <math-emu/soft-fp.h>
 #include <math-emu/single.h>
 
-static inline int stsi_0(void)
+int topology_max_mnest;
+
+/*
+ * stsi - store system information
+ *
+ * Returns the current configuration level if function code 0 was specified.
+ * Otherwise returns 0 on success or a negative value on error.
+ */
+int stsi(void *sysinfo, int fc, int sel1, int sel2)
 {
-	int rc = stsi(NULL, 0, 0, 0);
-	return rc == -ENOSYS ? rc : (((unsigned int) rc) >> 28);
+	register int r0 asm("0") = (fc << 28) | sel1;
+	register int r1 asm("1") = sel2;
+	int rc = 0;
+
+	asm volatile(
+		"	stsi	0(%3)\n"
+		"0:	jz	2f\n"
+		"1:	lhi	%1,%4\n"
+		"2:\n"
+		EX_TABLE(0b, 1b)
+		: "+d" (r0), "+d" (rc)
+		: "d" (r1), "a" (sysinfo), "K" (-EOPNOTSUPP)
+		: "cc", "memory");
+	if (rc)
+		return rc;
+	return fc ? 0 : ((unsigned int) r0) >> 28;
 }
+EXPORT_SYMBOL(stsi);
 
-static int stsi_1_1_1(struct sysinfo_1_1_1 *info, char *page, int len)
+static void stsi_1_1_1(struct seq_file *m, struct sysinfo_1_1_1 *info)
 {
-	if (stsi(info, 1, 1, 1) == -ENOSYS)
-		return len;
+	int i;
 
+	if (stsi(info, 1, 1, 1))
+		return;
 	EBCASC(info->manufacturer, sizeof(info->manufacturer));
 	EBCASC(info->type, sizeof(info->type));
 	EBCASC(info->model, sizeof(info->model));
@@ -41,242 +65,197 @@ static int stsi_1_1_1(struct sysinfo_1_1_1 *info, char *page, int len)
 	EBCASC(info->model_capacity, sizeof(info->model_capacity));
 	EBCASC(info->model_perm_cap, sizeof(info->model_perm_cap));
 	EBCASC(info->model_temp_cap, sizeof(info->model_temp_cap));
-	len += sprintf(page + len, "Manufacturer:         %-16.16s\n",
-		       info->manufacturer);
-	len += sprintf(page + len, "Type:                 %-4.4s\n",
-		       info->type);
+	seq_printf(m, "Manufacturer:         %-16.16s\n", info->manufacturer);
+	seq_printf(m, "Type:                 %-4.4s\n", info->type);
+	/*
+	 * Sigh: the model field has been renamed with System z9
+	 * to model_capacity and a new model field has been added
+	 * after the plant field. To avoid confusing older programs
+	 * the "Model:" prints "model_capacity model" or just
+	 * "model_capacity" if the model string is empty .
+	 */
+	seq_printf(m, "Model:                %-16.16s", info->model_capacity);
 	if (info->model[0] != '\0')
-		/*
-		 * Sigh: the model field has been renamed with System z9
-		 * to model_capacity and a new model field has been added
-		 * after the plant field. To avoid confusing older programs
-		 * the "Model:" prints "model_capacity model" or just
-		 * "model_capacity" if the model string is empty .
-		 */
-		len += sprintf(page + len,
-			       "Model:                %-16.16s %-16.16s\n",
-			       info->model_capacity, info->model);
-	else
-		len += sprintf(page + len, "Model:                %-16.16s\n",
-			       info->model_capacity);
-	len += sprintf(page + len, "Sequence Code:        %-16.16s\n",
-		       info->sequence);
-	len += sprintf(page + len, "Plant:                %-4.4s\n",
-		       info->plant);
-	len += sprintf(page + len, "Model Capacity:       %-16.16s %08u\n",
-		       info->model_capacity, *(u32 *) info->model_cap_rating);
-	if (info->model_perm_cap[0] != '\0')
-		len += sprintf(page + len,
-			       "Model Perm. Capacity: %-16.16s %08u\n",
-			       info->model_perm_cap,
-			       *(u32 *) info->model_perm_cap_rating);
-	if (info->model_temp_cap[0] != '\0')
-		len += sprintf(page + len,
-			       "Model Temp. Capacity: %-16.16s %08u\n",
-			       info->model_temp_cap,
-			       *(u32 *) info->model_temp_cap_rating);
+		seq_printf(m, " %-16.16s", info->model);
+	seq_putc(m, '\n');
+	seq_printf(m, "Sequence Code:        %-16.16s\n", info->sequence);
+	seq_printf(m, "Plant:                %-4.4s\n", info->plant);
+	seq_printf(m, "Model Capacity:       %-16.16s %08u\n",
+		   info->model_capacity, info->model_cap_rating);
+	if (info->model_perm_cap_rating)
+		seq_printf(m, "Model Perm. Capacity: %-16.16s %08u\n",
+			   info->model_perm_cap,
+			   info->model_perm_cap_rating);
+	if (info->model_temp_cap_rating)
+		seq_printf(m, "Model Temp. Capacity: %-16.16s %08u\n",
+			   info->model_temp_cap,
+			   info->model_temp_cap_rating);
+	if (info->ncr)
+		seq_printf(m, "Nominal Cap. Rating:  %08u\n", info->ncr);
+	if (info->npr)
+		seq_printf(m, "Nominal Perm. Rating: %08u\n", info->npr);
+	if (info->ntr)
+		seq_printf(m, "Nominal Temp. Rating: %08u\n", info->ntr);
 	if (info->cai) {
-		len += sprintf(page + len,
-			       "Capacity Adj. Ind.:   %d\n",
-			       info->cai);
-		len += sprintf(page + len, "Capacity Ch. Reason:  %d\n",
-			       info->ccr);
+		seq_printf(m, "Capacity Adj. Ind.:   %d\n", info->cai);
+		seq_printf(m, "Capacity Ch. Reason:  %d\n", info->ccr);
+		seq_printf(m, "Capacity Transient:   %d\n", info->t);
+	}
+	if (info->p) {
+		for (i = 1; i <= ARRAY_SIZE(info->typepct); i++) {
+			seq_printf(m, "Type %d Percentage:    %d\n",
+				   i, info->typepct[i - 1]);
+		}
 	}
-	return len;
 }
 
-static int stsi_15_1_x(struct sysinfo_15_1_x *info, char *page, int len)
+static void stsi_15_1_x(struct seq_file *m, struct sysinfo_15_1_x *info)
 {
 	static int max_mnest;
 	int i, rc;
 
-	len += sprintf(page + len, "\n");
+	seq_putc(m, '\n');
 	if (!MACHINE_HAS_TOPOLOGY)
-		return len;
-	if (max_mnest) {
-		stsi(info, 15, 1, max_mnest);
-	} else {
-		for (max_mnest = 6; max_mnest > 1; max_mnest--) {
-			rc = stsi(info, 15, 1, max_mnest);
-			if (rc != -ENOSYS)
-				break;
-		}
-	}
-	len += sprintf(page + len, "CPU Topology HW:     ");
+		return;
+	if (stsi(info, 15, 1, topology_max_mnest))
+		return;
+	seq_printf(m, "CPU Topology HW:     ");
 	for (i = 0; i < TOPOLOGY_NR_MAG; i++)
-		len += sprintf(page + len, " %d", info->mag[i]);
-	len += sprintf(page + len, "\n");
+		seq_printf(m, " %d", info->mag[i]);
+	seq_putc(m, '\n');
 #ifdef CONFIG_SCHED_MC
 	store_topology(info);
-	len += sprintf(page + len, "CPU Topology SW:     ");
+	seq_printf(m, "CPU Topology SW:     ");
 	for (i = 0; i < TOPOLOGY_NR_MAG; i++)
-		len += sprintf(page + len, " %d", info->mag[i]);
-	len += sprintf(page + len, "\n");
+		seq_printf(m, " %d", info->mag[i]);
+	seq_putc(m, '\n');
 #endif
-	return len;
 }
 
-static int stsi_1_2_2(struct sysinfo_1_2_2 *info, char *page, int len)
+static void stsi_1_2_2(struct seq_file *m, struct sysinfo_1_2_2 *info)
 {
 	struct sysinfo_1_2_2_extension *ext;
 	int i;
 
-	if (stsi(info, 1, 2, 2) == -ENOSYS)
-		return len;
+	if (stsi(info, 1, 2, 2))
+		return;
 	ext = (struct sysinfo_1_2_2_extension *)
 		((unsigned long) info + info->acc_offset);
-
-	len += sprintf(page + len, "CPUs Total:           %d\n",
-		       info->cpus_total);
-	len += sprintf(page + len, "CPUs Configured:      %d\n",
-		       info->cpus_configured);
-	len += sprintf(page + len, "CPUs Standby:         %d\n",
-		       info->cpus_standby);
-	len += sprintf(page + len, "CPUs Reserved:        %d\n",
-		       info->cpus_reserved);
-
-	if (info->format == 1) {
-		/*
-		 * Sigh 2. According to the specification the alternate
-		 * capability field is a 32 bit floating point number
-		 * if the higher order 8 bits are not zero. Printing
-		 * a floating point number in the kernel is a no-no,
-		 * always print the number as 32 bit unsigned integer.
-		 * The user-space needs to know about the strange
-		 * encoding of the alternate cpu capability.
-		 */
-		len += sprintf(page + len, "Capability:           %u %u\n",
-			       info->capability, ext->alt_capability);
-		for (i = 2; i <= info->cpus_total; i++)
-			len += sprintf(page + len,
-				       "Adjustment %02d-way:    %u %u\n",
-				       i, info->adjustment[i-2],
-				       ext->alt_adjustment[i-2]);
-
-	} else {
-		len += sprintf(page + len, "Capability:           %u\n",
-			       info->capability);
-		for (i = 2; i <= info->cpus_total; i++)
-			len += sprintf(page + len,
-				       "Adjustment %02d-way:    %u\n",
-				       i, info->adjustment[i-2]);
+	seq_printf(m, "CPUs Total:           %d\n", info->cpus_total);
+	seq_printf(m, "CPUs Configured:      %d\n", info->cpus_configured);
+	seq_printf(m, "CPUs Standby:         %d\n", info->cpus_standby);
+	seq_printf(m, "CPUs Reserved:        %d\n", info->cpus_reserved);
+	/*
+	 * Sigh 2. According to the specification the alternate
+	 * capability field is a 32 bit floating point number
+	 * if the higher order 8 bits are not zero. Printing
+	 * a floating point number in the kernel is a no-no,
+	 * always print the number as 32 bit unsigned integer.
+	 * The user-space needs to know about the strange
+	 * encoding of the alternate cpu capability.
+	 */
+	seq_printf(m, "Capability:           %u", info->capability);
+	if (info->format == 1)
+		seq_printf(m, " %u", ext->alt_capability);
+	seq_putc(m, '\n');
+	if (info->nominal_cap)
+		seq_printf(m, "Nominal Capability:   %d\n", info->nominal_cap);
+	if (info->secondary_cap)
+		seq_printf(m, "Secondary Capability: %d\n", info->secondary_cap);
+	for (i = 2; i <= info->cpus_total; i++) {
+		seq_printf(m, "Adjustment %02d-way:    %u",
+			   i, info->adjustment[i-2]);
+		if (info->format == 1)
+			seq_printf(m, " %u", ext->alt_adjustment[i-2]);
+		seq_putc(m, '\n');
 	}
-
-	if (info->secondary_capability != 0)
-		len += sprintf(page + len, "Secondary Capability: %d\n",
-			       info->secondary_capability);
-	return len;
 }
 
-static int stsi_2_2_2(struct sysinfo_2_2_2 *info, char *page, int len)
+static void stsi_2_2_2(struct seq_file *m, struct sysinfo_2_2_2 *info)
 {
-	if (stsi(info, 2, 2, 2) == -ENOSYS)
-		return len;
-
+	if (stsi(info, 2, 2, 2))
+		return;
 	EBCASC(info->name, sizeof(info->name));
-
-	len += sprintf(page + len, "\n");
-	len += sprintf(page + len, "LPAR Number:          %d\n",
-		       info->lpar_number);
-
-	len += sprintf(page + len, "LPAR Characteristics: ");
+	seq_putc(m, '\n');
+	seq_printf(m, "LPAR Number:          %d\n", info->lpar_number);
+	seq_printf(m, "LPAR Characteristics: ");
 	if (info->characteristics & LPAR_CHAR_DEDICATED)
-		len += sprintf(page + len, "Dedicated ");
+		seq_printf(m, "Dedicated ");
 	if (info->characteristics & LPAR_CHAR_SHARED)
-		len += sprintf(page + len, "Shared ");
+		seq_printf(m, "Shared ");
 	if (info->characteristics & LPAR_CHAR_LIMITED)
-		len += sprintf(page + len, "Limited ");
-	len += sprintf(page + len, "\n");
-
-	len += sprintf(page + len, "LPAR Name:            %-8.8s\n",
-		       info->name);
-
-	len += sprintf(page + len, "LPAR Adjustment:      %d\n",
-		       info->caf);
-
-	len += sprintf(page + len, "LPAR CPUs Total:      %d\n",
-		       info->cpus_total);
-	len += sprintf(page + len, "LPAR CPUs Configured: %d\n",
-		       info->cpus_configured);
-	len += sprintf(page + len, "LPAR CPUs Standby:    %d\n",
-		       info->cpus_standby);
-	len += sprintf(page + len, "LPAR CPUs Reserved:   %d\n",
-		       info->cpus_reserved);
-	len += sprintf(page + len, "LPAR CPUs Dedicated:  %d\n",
-		       info->cpus_dedicated);
-	len += sprintf(page + len, "LPAR CPUs Shared:     %d\n",
-		       info->cpus_shared);
-	return len;
+		seq_printf(m, "Limited ");
+	seq_putc(m, '\n');
+	seq_printf(m, "LPAR Name:            %-8.8s\n", info->name);
+	seq_printf(m, "LPAR Adjustment:      %d\n", info->caf);
+	seq_printf(m, "LPAR CPUs Total:      %d\n", info->cpus_total);
+	seq_printf(m, "LPAR CPUs Configured: %d\n", info->cpus_configured);
+	seq_printf(m, "LPAR CPUs Standby:    %d\n", info->cpus_standby);
+	seq_printf(m, "LPAR CPUs Reserved:   %d\n", info->cpus_reserved);
+	seq_printf(m, "LPAR CPUs Dedicated:  %d\n", info->cpus_dedicated);
+	seq_printf(m, "LPAR CPUs Shared:     %d\n", info->cpus_shared);
 }
 
-static int stsi_3_2_2(struct sysinfo_3_2_2 *info, char *page, int len)
+static void stsi_3_2_2(struct seq_file *m, struct sysinfo_3_2_2 *info)
 {
 	int i;
 
-	if (stsi(info, 3, 2, 2) == -ENOSYS)
-		return len;
+	if (stsi(info, 3, 2, 2))
+		return;
 	for (i = 0; i < info->count; i++) {
 		EBCASC(info->vm[i].name, sizeof(info->vm[i].name));
 		EBCASC(info->vm[i].cpi, sizeof(info->vm[i].cpi));
-		len += sprintf(page + len, "\n");
-		len += sprintf(page + len, "VM%02d Name:            %-8.8s\n",
-			       i, info->vm[i].name);
-		len += sprintf(page + len, "VM%02d Control Program: %-16.16s\n",
-			       i, info->vm[i].cpi);
-
-		len += sprintf(page + len, "VM%02d Adjustment:      %d\n",
-			       i, info->vm[i].caf);
-
-		len += sprintf(page + len, "VM%02d CPUs Total:      %d\n",
-			       i, info->vm[i].cpus_total);
-		len += sprintf(page + len, "VM%02d CPUs Configured: %d\n",
-			       i, info->vm[i].cpus_configured);
-		len += sprintf(page + len, "VM%02d CPUs Standby:    %d\n",
-			       i, info->vm[i].cpus_standby);
-		len += sprintf(page + len, "VM%02d CPUs Reserved:   %d\n",
-			       i, info->vm[i].cpus_reserved);
+		seq_putc(m, '\n');
+		seq_printf(m, "VM%02d Name:            %-8.8s\n", i, info->vm[i].name);
+		seq_printf(m, "VM%02d Control Program: %-16.16s\n", i, info->vm[i].cpi);
+		seq_printf(m, "VM%02d Adjustment:      %d\n", i, info->vm[i].caf);
+		seq_printf(m, "VM%02d CPUs Total:      %d\n", i, info->vm[i].cpus_total);
+		seq_printf(m, "VM%02d CPUs Configured: %d\n", i, info->vm[i].cpus_configured);
+		seq_printf(m, "VM%02d CPUs Standby:    %d\n", i, info->vm[i].cpus_standby);
+		seq_printf(m, "VM%02d CPUs Reserved:   %d\n", i, info->vm[i].cpus_reserved);
 	}
-	return len;
 }
 
-static int proc_read_sysinfo(char *page, char **start,
-			     off_t off, int count,
-			     int *eof, void *data)
+static int sysinfo_show(struct seq_file *m, void *v)
 {
-	unsigned long info = get_zeroed_page(GFP_KERNEL);
-	int level, len;
+	void *info = (void *)get_zeroed_page(GFP_KERNEL);
+	int level;
 
 	if (!info)
 		return 0;
-
-	len = 0;
-	level = stsi_0();
+	level = stsi(NULL, 0, 0, 0);
 	if (level >= 1)
-		len = stsi_1_1_1((struct sysinfo_1_1_1 *) info, page, len);
-
+		stsi_1_1_1(m, info);
 	if (level >= 1)
-		len = stsi_15_1_x((struct sysinfo_15_1_x *) info, page, len);
-
+		stsi_15_1_x(m, info);
 	if (level >= 1)
-		len = stsi_1_2_2((struct sysinfo_1_2_2 *) info, page, len);
-
+		stsi_1_2_2(m, info);
 	if (level >= 2)
-		len = stsi_2_2_2((struct sysinfo_2_2_2 *) info, page, len);
-
+		stsi_2_2_2(m, info);
 	if (level >= 3)
-		len = stsi_3_2_2((struct sysinfo_3_2_2 *) info, page, len);
+		stsi_3_2_2(m, info);
+	free_page((unsigned long)info);
+	return 0;
+}
 
-	free_page(info);
-	return len;
+static int sysinfo_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, sysinfo_show, NULL);
 }
 
-static __init int create_proc_sysinfo(void)
+static const struct file_operations sysinfo_fops = {
+	.open		= sysinfo_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static int __init sysinfo_create_proc(void)
 {
-	create_proc_read_entry("sysinfo", 0444, NULL,
-			       proc_read_sysinfo, NULL);
+	proc_create("sysinfo", 0444, NULL, &sysinfo_fops);
 	return 0;
 }
-device_initcall(create_proc_sysinfo);
+device_initcall(sysinfo_create_proc);
 
 /*
  * Service levels interface.
@@ -407,7 +386,7 @@ void s390_adjust_jiffies(void)
 	if (!info)
 		return;
 
-	if (stsi(info, 1, 2, 2) != -ENOSYS) {
+	if (stsi(info, 1, 2, 2) == 0) {
 		/*
 		 * Major sigh. The cpu capability encoding is "special".
 		 * If the first 9 bits of info->capability are 0 then it
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
index dcec960..2db1011 100644
--- a/arch/s390/kernel/time.c
+++ b/arch/s390/kernel/time.c
@@ -329,7 +329,7 @@ static unsigned long clock_sync_flags;
  * The synchronous get_clock function. It will write the current clock
  * value to the clock pointer and return 0 if the clock is in sync with
  * the external time source. If the clock mode is local it will return
- * -ENOSYS and -EAGAIN if the clock is not in sync with the external
+ * -EOPNOTSUPP and -EAGAIN if the clock is not in sync with the external
  * reference.
  */
 int get_sync_clock(unsigned long long *clock)
@@ -347,7 +347,7 @@ int get_sync_clock(unsigned long long *clock)
 		return 0;
 	if (!test_bit(CLOCK_SYNC_HAS_ETR, &clock_sync_flags) &&
 	    !test_bit(CLOCK_SYNC_HAS_STP, &clock_sync_flags))
-		return -ENOSYS;
+		return -EOPNOTSUPP;
 	if (!test_bit(CLOCK_SYNC_ETR, &clock_sync_flags) &&
 	    !test_bit(CLOCK_SYNC_STP, &clock_sync_flags))
 		return -EACCES;
diff --git a/arch/s390/kernel/topology.c b/arch/s390/kernel/topology.c
index 05151e0..54d93f4 100644
--- a/arch/s390/kernel/topology.c
+++ b/arch/s390/kernel/topology.c
@@ -17,6 +17,7 @@
 #include <linux/cpu.h>
 #include <linux/smp.h>
 #include <linux/mm.h>
+#include <asm/sysinfo.h>
 
 #define PTF_HORIZONTAL	(0UL)
 #define PTF_VERTICAL	(1UL)
@@ -44,9 +45,6 @@ static struct mask_info book_info;
 cpumask_t cpu_book_map[NR_CPUS];
 unsigned char cpu_book_id[NR_CPUS];
 
-/* smp_cpu_state_mutex must be held when accessing this array */
-int cpu_polarization[NR_CPUS];
-
 static cpumask_t cpu_group_map(struct mask_info *info, unsigned int cpu)
 {
 	cpumask_t mask;
@@ -75,10 +73,7 @@ static struct mask_info *add_cpus_to_mask(struct topology_cpu *tl_cpu,
 {
 	unsigned int cpu;
 
-	for (cpu = find_first_bit(&tl_cpu->mask[0], TOPOLOGY_CPU_BITS);
-	     cpu < TOPOLOGY_CPU_BITS;
-	     cpu = find_next_bit(&tl_cpu->mask[0], TOPOLOGY_CPU_BITS, cpu + 1))
-	{
+	for_each_set_bit(cpu, &tl_cpu->mask[0], TOPOLOGY_CPU_BITS) {
 		unsigned int rcpu;
 		int lcpu;
 
@@ -94,7 +89,7 @@ static struct mask_info *add_cpus_to_mask(struct topology_cpu *tl_cpu,
 			} else {
 				cpu_core_id[lcpu] = core->id;
 			}
-			cpu_set_polarization(lcpu, tl_cpu->pp);
+			smp_cpu_set_polarization(lcpu, tl_cpu->pp);
 		}
 	}
 	return core;
@@ -201,7 +196,7 @@ static void topology_update_polarization_simple(void)
 
 	mutex_lock(&smp_cpu_state_mutex);
 	for_each_possible_cpu(cpu)
-		cpu_set_polarization(cpu, POLARIZATION_HRZ);
+		smp_cpu_set_polarization(cpu, POLARIZATION_HRZ);
 	mutex_unlock(&smp_cpu_state_mutex);
 }
 
@@ -231,7 +226,7 @@ int topology_set_cpu_management(int fc)
 	if (rc)
 		return -EBUSY;
 	for_each_possible_cpu(cpu)
-		cpu_set_polarization(cpu, POLARIZATION_UNKNOWN);
+		smp_cpu_set_polarization(cpu, POLARIZATION_UNKNOWN);
 	return rc;
 }
 
@@ -250,12 +245,10 @@ static void update_cpu_core_map(void)
 
 void store_topology(struct sysinfo_15_1_x *info)
 {
-	int rc;
-
-	rc = stsi(info, 15, 1, 3);
-	if (rc != -ENOSYS)
-		return;
-	stsi(info, 15, 1, 2);
+	if (topology_max_mnest >= 3)
+		stsi(info, 15, 1, 3);
+	else
+		stsi(info, 15, 1, 2);
 }
 
 int arch_update_cpu_topology(void)
@@ -415,7 +408,7 @@ static ssize_t cpu_polarization_show(struct device *dev,
 	ssize_t count;
 
 	mutex_lock(&smp_cpu_state_mutex);
-	switch (cpu_read_polarization(cpu)) {
+	switch (smp_cpu_get_polarization(cpu)) {
 	case POLARIZATION_HRZ:
 		count = sprintf(buf, "horizontal\n");
 		break;
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c
index 01775c0..befc761 100644
--- a/arch/s390/kernel/traps.c
+++ b/arch/s390/kernel/traps.c
@@ -57,6 +57,23 @@ static int kstack_depth_to_print = 12;
 static int kstack_depth_to_print = 20;
 #endif /* CONFIG_64BIT */
 
+static inline void __user *get_trap_ip(struct pt_regs *regs)
+{
+#ifdef CONFIG_64BIT
+	unsigned long address;
+
+	if (regs->int_code & 0x200)
+		address = *(unsigned long *)(current->thread.trap_tdb + 24);
+	else
+		address = regs->psw.addr;
+	return (void __user *)
+		((address - (regs->int_code >> 16)) & PSW_ADDR_INSN);
+#else
+	return (void __user *)
+		((regs->psw.addr - (regs->int_code >> 16)) & PSW_ADDR_INSN);
+#endif
+}
+
 /*
  * For show_trace we have tree different stack to consider:
  *   - the panic stack which is used if the kernel stack has overflown
@@ -285,12 +302,6 @@ int is_valid_bugaddr(unsigned long addr)
 	return 1;
 }
 
-static inline void __user *get_psw_address(struct pt_regs *regs)
-{
-	return (void __user *)
-		((regs->psw.addr - (regs->int_code >> 16)) & PSW_ADDR_INSN);
-}
-
 static void __kprobes do_trap(struct pt_regs *regs,
 			      int si_signo, int si_code, char *str)
 {
@@ -304,14 +315,14 @@ static void __kprobes do_trap(struct pt_regs *regs,
 		info.si_signo = si_signo;
 		info.si_errno = 0;
 		info.si_code = si_code;
-		info.si_addr = get_psw_address(regs);
+		info.si_addr = get_trap_ip(regs);
 		force_sig_info(si_signo, &info, current);
 		report_user_fault(regs, si_signo);
         } else {
                 const struct exception_table_entry *fixup;
                 fixup = search_exception_tables(regs->psw.addr & PSW_ADDR_INSN);
                 if (fixup)
-                        regs->psw.addr = fixup->fixup | PSW_ADDR_AMODE;
+			regs->psw.addr = extable_fixup(fixup) | PSW_ADDR_AMODE;
 		else {
 			enum bug_trap_type btt;
 
@@ -381,6 +392,11 @@ DO_ERROR_INFO(special_op_exception, SIGILL, ILL_ILLOPN,
 DO_ERROR_INFO(translation_exception, SIGILL, ILL_ILLOPN,
 	      "translation exception")
 
+#ifdef CONFIG_64BIT
+DO_ERROR_INFO(transaction_exception, SIGILL, ILL_ILLOPN,
+	      "transaction constraint exception")
+#endif
+
 static inline void do_fp_trap(struct pt_regs *regs, int fpc)
 {
 	int si_code = 0;
@@ -408,7 +424,7 @@ static void __kprobes illegal_op(struct pt_regs *regs)
 	__u16 __user *location;
 	int signal = 0;
 
-	location = get_psw_address(regs);
+	location = get_trap_ip(regs);
 
 	if (user_mode(regs)) {
 		if (get_user(*((__u16 *) opcode), (__u16 __user *) location))
@@ -476,7 +492,7 @@ void specification_exception(struct pt_regs *regs)
 	__u16 __user *location = NULL;
 	int signal = 0;
 
-	location = (__u16 __user *) get_psw_address(regs);
+	location = (__u16 __user *) get_trap_ip(regs);
 
 	if (user_mode(regs)) {
 		get_user(*((__u16 *) opcode), location);
@@ -525,7 +541,7 @@ static void data_exception(struct pt_regs *regs)
 	__u16 __user *location;
 	int signal = 0;
 
-	location = get_psw_address(regs);
+	location = get_trap_ip(regs);
 
 	if (MACHINE_HAS_IEEE)
 		asm volatile("stfpc %0" : "=m" (current->thread.fp_regs.fpc));
@@ -641,6 +657,7 @@ void __init trap_init(void)
         pgm_check_table[0x12] = &translation_exception;
         pgm_check_table[0x13] = &special_op_exception;
 #ifdef CONFIG_64BIT
+	pgm_check_table[0x18] = &transaction_exception;
 	pgm_check_table[0x38] = &do_asce_exception;
 	pgm_check_table[0x39] = &do_dat_exception;
 	pgm_check_table[0x3A] = &do_dat_exception;
diff --git a/arch/s390/kernel/vdso.c b/arch/s390/kernel/vdso.c
index 9a19ca3..d777628 100644
--- a/arch/s390/kernel/vdso.c
+++ b/arch/s390/kernel/vdso.c
@@ -85,7 +85,7 @@ struct vdso_data *vdso_data = &vdso_data_store.data;
 static void vdso_init_data(struct vdso_data *vd)
 {
 	vd->ectg_available =
-		addressing_mode != HOME_SPACE_MODE && test_facility(31);
+		s390_user_mode != HOME_SPACE_MODE && test_facility(31);
 }
 
 #ifdef CONFIG_64BIT
@@ -102,7 +102,7 @@ int vdso_alloc_per_cpu(struct _lowcore *lowcore)
 
 	lowcore->vdso_per_cpu_data = __LC_PASTE;
 
-	if (addressing_mode == HOME_SPACE_MODE || !vdso_enabled)
+	if (s390_user_mode == HOME_SPACE_MODE || !vdso_enabled)
 		return 0;
 
 	segment_table = __get_free_pages(GFP_KERNEL, SEGMENT_ORDER);
@@ -147,7 +147,7 @@ void vdso_free_per_cpu(struct _lowcore *lowcore)
 	unsigned long segment_table, page_table, page_frame;
 	u32 *psal, *aste;
 
-	if (addressing_mode == HOME_SPACE_MODE || !vdso_enabled)
+	if (s390_user_mode == HOME_SPACE_MODE || !vdso_enabled)
 		return;
 
 	psal = (u32 *)(addr_t) lowcore->paste[4];
@@ -165,7 +165,7 @@ static void vdso_init_cr5(void)
 {
 	unsigned long cr5;
 
-	if (addressing_mode == HOME_SPACE_MODE || !vdso_enabled)
+	if (s390_user_mode == HOME_SPACE_MODE || !vdso_enabled)
 		return;
 	cr5 = offsetof(struct _lowcore, paste);
 	__ctl_load(cr5, 5, 5);
diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c
index 4fc97b4..cfb21fd 100644
--- a/arch/s390/kernel/vtime.c
+++ b/arch/s390/kernel/vtime.c
@@ -99,7 +99,7 @@ static int do_account_vtime(struct task_struct *tsk, int hardirq_offset)
 	return virt_timer_forward(user + system);
 }
 
-void account_vtime(struct task_struct *prev, struct task_struct *next)
+void account_switch_vtime(struct task_struct *prev)
 {
 	struct thread_info *ti;
 
@@ -107,7 +107,7 @@ void account_vtime(struct task_struct *prev, struct task_struct *next)
 	ti = task_thread_info(prev);
 	ti->user_timer = S390_lowcore.user_timer;
 	ti->system_timer = S390_lowcore.system_timer;
-	ti = task_thread_info(next);
+	ti = task_thread_info(current);
 	S390_lowcore.user_timer = ti->user_timer;
 	S390_lowcore.system_timer = ti->system_timer;
 }
@@ -378,9 +378,8 @@ static int __cpuinit s390_nohz_notify(struct notifier_block *self,
 	long cpu = (long) hcpu;
 
 	idle = &per_cpu(s390_idle, cpu);
-	switch (action) {
+	switch (action & ~CPU_TASKS_FROZEN) {
 	case CPU_DYING:
-	case CPU_DYING_FROZEN:
 		idle->nohz_delay = 0;
 	default:
 		break;
diff --git a/arch/s390/kvm/Kconfig b/arch/s390/kvm/Kconfig
index 78eb984..b58dd86 100644
--- a/arch/s390/kvm/Kconfig
+++ b/arch/s390/kvm/Kconfig
@@ -5,7 +5,7 @@ source "virt/kvm/Kconfig"
 
 menuconfig VIRTUALIZATION
 	def_bool y
-	prompt "Virtualization"
+	prompt "KVM"
 	---help---
 	  Say Y here to get to see options for using your Linux host to run other
 	  operating systems inside virtual machines (guests).
@@ -21,6 +21,7 @@ config KVM
 	depends on HAVE_KVM && EXPERIMENTAL
 	select PREEMPT_NOTIFIERS
 	select ANON_INODES
+	select HAVE_KVM_CPU_RELAX_INTERCEPT
 	---help---
 	  Support hosting paravirtualized guest machines using the SIE
 	  virtualization capability on the mainframe. This should work
diff --git a/arch/s390/kvm/diag.c b/arch/s390/kvm/diag.c
index c88bb77..a390687 100644
--- a/arch/s390/kvm/diag.c
+++ b/arch/s390/kvm/diag.c
@@ -14,6 +14,8 @@
 #include <linux/kvm.h>
 #include <linux/kvm_host.h>
 #include "kvm-s390.h"
+#include "trace.h"
+#include "trace-s390.h"
 
 static int diag_release_pages(struct kvm_vcpu *vcpu)
 {
@@ -98,6 +100,7 @@ static int __diag_ipl_functions(struct kvm_vcpu *vcpu)
 	vcpu->run->exit_reason = KVM_EXIT_S390_RESET;
 	VCPU_EVENT(vcpu, 3, "requesting userspace resets %llx",
 	  vcpu->run->s390_reset_flags);
+	trace_kvm_s390_request_resets(vcpu->run->s390_reset_flags);
 	return -EREMOTE;
 }
 
@@ -105,6 +108,7 @@ int kvm_s390_handle_diag(struct kvm_vcpu *vcpu)
 {
 	int code = (vcpu->arch.sie_block->ipb & 0xfff0000) >> 16;
 
+	trace_kvm_s390_handle_diag(vcpu, code);
 	switch (code) {
 	case 0x10:
 		return diag_release_pages(vcpu);
diff --git a/arch/s390/kvm/intercept.c b/arch/s390/kvm/intercept.c
index adae539..22798ec 100644
--- a/arch/s390/kvm/intercept.c
+++ b/arch/s390/kvm/intercept.c
@@ -19,6 +19,8 @@
 
 #include "kvm-s390.h"
 #include "gaccess.h"
+#include "trace.h"
+#include "trace-s390.h"
 
 static int handle_lctlg(struct kvm_vcpu *vcpu)
 {
@@ -45,6 +47,7 @@ static int handle_lctlg(struct kvm_vcpu *vcpu)
 
 	VCPU_EVENT(vcpu, 5, "lctlg r1:%x, r3:%x,b2:%x,d2:%x", reg1, reg3, base2,
 		   disp2);
+	trace_kvm_s390_handle_lctl(vcpu, 1, reg1, reg3, useraddr);
 
 	do {
 		rc = get_guest_u64(vcpu, useraddr,
@@ -82,6 +85,7 @@ static int handle_lctl(struct kvm_vcpu *vcpu)
 
 	VCPU_EVENT(vcpu, 5, "lctl r1:%x, r3:%x,b2:%x,d2:%x", reg1, reg3, base2,
 		   disp2);
+	trace_kvm_s390_handle_lctl(vcpu, 0, reg1, reg3, useraddr);
 
 	reg = reg1;
 	do {
@@ -135,6 +139,8 @@ static int handle_stop(struct kvm_vcpu *vcpu)
 	vcpu->stat.exit_stop_request++;
 	spin_lock_bh(&vcpu->arch.local_int.lock);
 
+	trace_kvm_s390_stop_request(vcpu->arch.local_int.action_bits);
+
 	if (vcpu->arch.local_int.action_bits & ACTION_RELOADVCPU_ON_STOP) {
 		vcpu->arch.local_int.action_bits &= ~ACTION_RELOADVCPU_ON_STOP;
 		rc = SIE_INTERCEPT_RERUNVCPU;
@@ -171,6 +177,7 @@ static int handle_validity(struct kvm_vcpu *vcpu)
 	int rc;
 
 	vcpu->stat.exit_validity++;
+	trace_kvm_s390_intercept_validity(vcpu, viwhy);
 	if (viwhy == 0x37) {
 		vmaddr = gmap_fault(vcpu->arch.sie_block->prefix,
 				    vcpu->arch.gmap);
@@ -213,6 +220,9 @@ static int handle_instruction(struct kvm_vcpu *vcpu)
 	intercept_handler_t handler;
 
 	vcpu->stat.exit_instruction++;
+	trace_kvm_s390_intercept_instruction(vcpu,
+					     vcpu->arch.sie_block->ipa,
+					     vcpu->arch.sie_block->ipb);
 	handler = instruction_handlers[vcpu->arch.sie_block->ipa >> 8];
 	if (handler)
 		return handler(vcpu);
@@ -222,6 +232,7 @@ static int handle_instruction(struct kvm_vcpu *vcpu)
 static int handle_prog(struct kvm_vcpu *vcpu)
 {
 	vcpu->stat.exit_program_interruption++;
+	trace_kvm_s390_intercept_prog(vcpu, vcpu->arch.sie_block->iprcc);
 	return kvm_s390_inject_program_int(vcpu, vcpu->arch.sie_block->iprcc);
 }
 
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
index b7bc1aa..7556231 100644
--- a/arch/s390/kvm/interrupt.c
+++ b/arch/s390/kvm/interrupt.c
@@ -19,6 +19,7 @@
 #include <asm/uaccess.h>
 #include "kvm-s390.h"
 #include "gaccess.h"
+#include "trace-s390.h"
 
 static int psw_extint_disabled(struct kvm_vcpu *vcpu)
 {
@@ -130,6 +131,8 @@ static void __do_deliver_interrupt(struct kvm_vcpu *vcpu,
 	case KVM_S390_INT_EMERGENCY:
 		VCPU_EVENT(vcpu, 4, "%s", "interrupt: sigp emerg");
 		vcpu->stat.deliver_emergency_signal++;
+		trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type,
+						 inti->emerg.code, 0);
 		rc = put_guest_u16(vcpu, __LC_EXT_INT_CODE, 0x1201);
 		if (rc == -EFAULT)
 			exception = 1;
@@ -152,6 +155,8 @@ static void __do_deliver_interrupt(struct kvm_vcpu *vcpu,
 	case KVM_S390_INT_EXTERNAL_CALL:
 		VCPU_EVENT(vcpu, 4, "%s", "interrupt: sigp ext call");
 		vcpu->stat.deliver_external_call++;
+		trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type,
+						 inti->extcall.code, 0);
 		rc = put_guest_u16(vcpu, __LC_EXT_INT_CODE, 0x1202);
 		if (rc == -EFAULT)
 			exception = 1;
@@ -175,6 +180,8 @@ static void __do_deliver_interrupt(struct kvm_vcpu *vcpu,
 		VCPU_EVENT(vcpu, 4, "interrupt: sclp parm:%x",
 			   inti->ext.ext_params);
 		vcpu->stat.deliver_service_signal++;
+		trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type,
+						 inti->ext.ext_params, 0);
 		rc = put_guest_u16(vcpu, __LC_EXT_INT_CODE, 0x2401);
 		if (rc == -EFAULT)
 			exception = 1;
@@ -198,6 +205,9 @@ static void __do_deliver_interrupt(struct kvm_vcpu *vcpu,
 		VCPU_EVENT(vcpu, 4, "interrupt: virtio parm:%x,parm64:%llx",
 			   inti->ext.ext_params, inti->ext.ext_params2);
 		vcpu->stat.deliver_virtio_interrupt++;
+		trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type,
+						 inti->ext.ext_params,
+						 inti->ext.ext_params2);
 		rc = put_guest_u16(vcpu, __LC_EXT_INT_CODE, 0x2603);
 		if (rc == -EFAULT)
 			exception = 1;
@@ -229,6 +239,8 @@ static void __do_deliver_interrupt(struct kvm_vcpu *vcpu,
 	case KVM_S390_SIGP_STOP:
 		VCPU_EVENT(vcpu, 4, "%s", "interrupt: cpu stop");
 		vcpu->stat.deliver_stop_signal++;
+		trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type,
+						 0, 0);
 		__set_intercept_indicator(vcpu, inti);
 		break;
 
@@ -236,12 +248,16 @@ static void __do_deliver_interrupt(struct kvm_vcpu *vcpu,
 		VCPU_EVENT(vcpu, 4, "interrupt: set prefix to %x",
 			   inti->prefix.address);
 		vcpu->stat.deliver_prefix_signal++;
+		trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type,
+						 inti->prefix.address, 0);
 		kvm_s390_set_prefix(vcpu, inti->prefix.address);
 		break;
 
 	case KVM_S390_RESTART:
 		VCPU_EVENT(vcpu, 4, "%s", "interrupt: cpu restart");
 		vcpu->stat.deliver_restart_signal++;
+		trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type,
+						 0, 0);
 		rc = copy_to_guest(vcpu, offsetof(struct _lowcore,
 		  restart_old_psw), &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
 		if (rc == -EFAULT)
@@ -259,6 +275,8 @@ static void __do_deliver_interrupt(struct kvm_vcpu *vcpu,
 			   inti->pgm.code,
 			   table[vcpu->arch.sie_block->ipa >> 14]);
 		vcpu->stat.deliver_program_int++;
+		trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type,
+						 inti->pgm.code, 0);
 		rc = put_guest_u16(vcpu, __LC_PGM_INT_CODE, inti->pgm.code);
 		if (rc == -EFAULT)
 			exception = 1;
@@ -515,6 +533,7 @@ int kvm_s390_inject_program_int(struct kvm_vcpu *vcpu, u16 code)
 	inti->pgm.code = code;
 
 	VCPU_EVENT(vcpu, 3, "inject: program check %d (from kernel)", code);
+	trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, inti->type, code, 0, 1);
 	spin_lock_bh(&li->lock);
 	list_add(&inti->list, &li->list);
 	atomic_set(&li->active, 1);
@@ -556,6 +575,8 @@ int kvm_s390_inject_vm(struct kvm *kvm,
 		kfree(inti);
 		return -EINVAL;
 	}
+	trace_kvm_s390_inject_vm(s390int->type, s390int->parm, s390int->parm64,
+				 2);
 
 	mutex_lock(&kvm->lock);
 	fi = &kvm->arch.float_int;
@@ -621,6 +642,8 @@ int kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu,
 		kfree(inti);
 		return -EINVAL;
 	}
+	trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, s390int->type, s390int->parm,
+				   s390int->parm64, 2);
 
 	mutex_lock(&vcpu->kvm->lock);
 	li = &vcpu->arch.local_int;
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index d470ccb..ecced9d 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -32,6 +32,10 @@
 #include "kvm-s390.h"
 #include "gaccess.h"
 
+#define CREATE_TRACE_POINTS
+#include "trace.h"
+#include "trace-s390.h"
+
 #define VCPU_STAT(x) offsetof(struct kvm_vcpu, stat.x), KVM_STAT_VCPU
 
 struct kvm_stats_debugfs_item debugfs_entries[] = {
@@ -242,6 +246,7 @@ out_err:
 void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
 {
 	VCPU_EVENT(vcpu, 3, "%s", "free cpu");
+	trace_kvm_s390_destroy_vcpu(vcpu->vcpu_id);
 	if (!kvm_is_ucontrol(vcpu->kvm)) {
 		clear_bit(63 - vcpu->vcpu_id,
 			  (unsigned long *) &vcpu->kvm->arch.sca->mcn);
@@ -417,6 +422,7 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm,
 		goto out_free_sie_block;
 	VM_EVENT(kvm, 3, "create cpu %d at %p, sie block at %p", id, vcpu,
 		 vcpu->arch.sie_block);
+	trace_kvm_s390_create_vcpu(id, vcpu, vcpu->arch.sie_block);
 
 	return vcpu;
 out_free_sie_block:
@@ -607,18 +613,22 @@ static int __vcpu_run(struct kvm_vcpu *vcpu)
 	local_irq_enable();
 	VCPU_EVENT(vcpu, 6, "entering sie flags %x",
 		   atomic_read(&vcpu->arch.sie_block->cpuflags));
+	trace_kvm_s390_sie_enter(vcpu,
+				 atomic_read(&vcpu->arch.sie_block->cpuflags));
 	rc = sie64a(vcpu->arch.sie_block, vcpu->run->s.regs.gprs);
 	if (rc) {
 		if (kvm_is_ucontrol(vcpu->kvm)) {
 			rc = SIE_INTERCEPT_UCONTROL;
 		} else {
 			VCPU_EVENT(vcpu, 3, "%s", "fault in sie instruction");
+			trace_kvm_s390_sie_fault(vcpu);
 			kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
 			rc = 0;
 		}
 	}
 	VCPU_EVENT(vcpu, 6, "exit sie icptcode %d",
 		   vcpu->arch.sie_block->icptcode);
+	trace_kvm_s390_sie_exit(vcpu, vcpu->arch.sie_block->icptcode);
 	local_irq_disable();
 	kvm_guest_exit();
 	local_irq_enable();
@@ -959,7 +969,12 @@ void kvm_arch_commit_memory_region(struct kvm *kvm,
 	return;
 }
 
-void kvm_arch_flush_shadow(struct kvm *kvm)
+void kvm_arch_flush_shadow_all(struct kvm *kvm)
+{
+}
+
+void kvm_arch_flush_shadow_memslot(struct kvm *kvm,
+				   struct kvm_memory_slot *slot)
 {
 }
 
diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c
index 60da903..d768906 100644
--- a/arch/s390/kvm/priv.c
+++ b/arch/s390/kvm/priv.c
@@ -20,6 +20,7 @@
 #include <asm/sysinfo.h>
 #include "gaccess.h"
 #include "kvm-s390.h"
+#include "trace.h"
 
 static int handle_set_prefix(struct kvm_vcpu *vcpu)
 {
@@ -59,6 +60,7 @@ static int handle_set_prefix(struct kvm_vcpu *vcpu)
 	kvm_s390_set_prefix(vcpu, address);
 
 	VCPU_EVENT(vcpu, 5, "setting prefix to %x", address);
+	trace_kvm_s390_handle_prefix(vcpu, 1, address);
 out:
 	return 0;
 }
@@ -91,6 +93,7 @@ static int handle_store_prefix(struct kvm_vcpu *vcpu)
 	}
 
 	VCPU_EVENT(vcpu, 5, "storing prefix to %x", address);
+	trace_kvm_s390_handle_prefix(vcpu, 0, address);
 out:
 	return 0;
 }
@@ -119,6 +122,7 @@ static int handle_store_cpu_address(struct kvm_vcpu *vcpu)
 	}
 
 	VCPU_EVENT(vcpu, 5, "storing cpu address to %llx", useraddr);
+	trace_kvm_s390_handle_stap(vcpu, useraddr);
 out:
 	return 0;
 }
@@ -164,9 +168,11 @@ static int handle_stfl(struct kvm_vcpu *vcpu)
 			   &facility_list, sizeof(facility_list));
 	if (rc == -EFAULT)
 		kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
-	else
+	else {
 		VCPU_EVENT(vcpu, 5, "store facility list value %x",
 			   facility_list);
+		trace_kvm_s390_handle_stfl(vcpu, facility_list);
+	}
 	return 0;
 }
 
@@ -211,7 +217,7 @@ static void handle_stsi_3_2_2(struct kvm_vcpu *vcpu, struct sysinfo_3_2_2 *mem)
 	spin_unlock(&fi->lock);
 
 	/* deal with other level 3 hypervisors */
-	if (stsi(mem, 3, 2, 2) == -ENOSYS)
+	if (stsi(mem, 3, 2, 2))
 		mem->count = 0;
 	if (mem->count < 8)
 		mem->count++;
@@ -259,7 +265,7 @@ static int handle_stsi(struct kvm_vcpu *vcpu)
 		mem = get_zeroed_page(GFP_KERNEL);
 		if (!mem)
 			goto out_fail;
-		if (stsi((void *) mem, fc, sel1, sel2) == -ENOSYS)
+		if (stsi((void *) mem, fc, sel1, sel2))
 			goto out_mem;
 		break;
 	case 3:
@@ -278,6 +284,7 @@ static int handle_stsi(struct kvm_vcpu *vcpu)
 		kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
 		goto out_mem;
 	}
+	trace_kvm_s390_handle_stsi(vcpu, fc, sel1, sel2, operand2);
 	free_page(mem);
 	vcpu->arch.sie_block->gpsw.mask &= ~(3ul << 44);
 	vcpu->run->s.regs.gprs[0] = 0;
diff --git a/arch/s390/kvm/sigp.c b/arch/s390/kvm/sigp.c
index 56f80e1..566ddf6 100644
--- a/arch/s390/kvm/sigp.c
+++ b/arch/s390/kvm/sigp.c
@@ -18,6 +18,7 @@
 #include <asm/sigp.h>
 #include "gaccess.h"
 #include "kvm-s390.h"
+#include "trace.h"
 
 static int __sigp_sense(struct kvm_vcpu *vcpu, u16 cpu_addr,
 			u64 *reg)
@@ -344,6 +345,7 @@ int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu)
 	else
 		parameter = vcpu->run->s.regs.gprs[r1 + 1];
 
+	trace_kvm_s390_handle_sigp(vcpu, order_code, cpu_addr, parameter);
 	switch (order_code) {
 	case SIGP_SENSE:
 		vcpu->stat.instruction_sigp_sense++;
diff --git a/arch/s390/kvm/trace-s390.h b/arch/s390/kvm/trace-s390.h
new file mode 100644
index 0000000..90fdf85
--- /dev/null
+++ b/arch/s390/kvm/trace-s390.h
@@ -0,0 +1,210 @@
+#if !defined(_TRACE_KVMS390_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_KVMS390_H
+
+#include <linux/tracepoint.h>
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM kvm-s390
+#define TRACE_INCLUDE_PATH .
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE trace-s390
+
+/*
+ * Trace point for the creation of the kvm instance.
+ */
+TRACE_EVENT(kvm_s390_create_vm,
+	    TP_PROTO(unsigned long type),
+	    TP_ARGS(type),
+
+	    TP_STRUCT__entry(
+		    __field(unsigned long, type)
+		    ),
+
+	    TP_fast_assign(
+		    __entry->type = type;
+		    ),
+
+	    TP_printk("create vm%s",
+		      __entry->type & KVM_VM_S390_UCONTROL ? " (UCONTROL)" : "")
+	);
+
+/*
+ * Trace points for creation and destruction of vpcus.
+ */
+TRACE_EVENT(kvm_s390_create_vcpu,
+	    TP_PROTO(unsigned int id, struct kvm_vcpu *vcpu,
+		     struct kvm_s390_sie_block *sie_block),
+	    TP_ARGS(id, vcpu, sie_block),
+
+	    TP_STRUCT__entry(
+		    __field(unsigned int, id)
+		    __field(struct kvm_vcpu *, vcpu)
+		    __field(struct kvm_s390_sie_block *, sie_block)
+		    ),
+
+	    TP_fast_assign(
+		    __entry->id = id;
+		    __entry->vcpu = vcpu;
+		    __entry->sie_block = sie_block;
+		    ),
+
+	    TP_printk("create cpu %d at %p, sie block at %p", __entry->id,
+		      __entry->vcpu, __entry->sie_block)
+	);
+
+TRACE_EVENT(kvm_s390_destroy_vcpu,
+	    TP_PROTO(unsigned int id),
+	    TP_ARGS(id),
+
+	    TP_STRUCT__entry(
+		    __field(unsigned int, id)
+		    ),
+
+	    TP_fast_assign(
+		    __entry->id = id;
+		    ),
+
+	    TP_printk("destroy cpu %d", __entry->id)
+	);
+
+/*
+ * Trace points for injection of interrupts, either per machine or
+ * per vcpu.
+ */
+
+#define kvm_s390_int_type						\
+	{KVM_S390_SIGP_STOP, "sigp stop"},				\
+	{KVM_S390_PROGRAM_INT, "program interrupt"},			\
+	{KVM_S390_SIGP_SET_PREFIX, "sigp set prefix"},			\
+	{KVM_S390_RESTART, "sigp restart"},				\
+	{KVM_S390_INT_VIRTIO, "virtio interrupt"},			\
+	{KVM_S390_INT_SERVICE, "sclp interrupt"},			\
+	{KVM_S390_INT_EMERGENCY, "sigp emergency"},			\
+	{KVM_S390_INT_EXTERNAL_CALL, "sigp ext call"}
+
+TRACE_EVENT(kvm_s390_inject_vm,
+	    TP_PROTO(__u64 type, __u32 parm, __u64 parm64, int who),
+	    TP_ARGS(type, parm, parm64, who),
+
+	    TP_STRUCT__entry(
+		    __field(__u32, inttype)
+		    __field(__u32, parm)
+		    __field(__u64, parm64)
+		    __field(int, who)
+		    ),
+
+	    TP_fast_assign(
+		    __entry->inttype = type & 0x00000000ffffffff;
+		    __entry->parm = parm;
+		    __entry->parm64 = parm64;
+		    __entry->who = who;
+		    ),
+
+	    TP_printk("inject%s: type:%x (%s) parm:%x parm64:%llx",
+		      (__entry->who == 1) ? " (from kernel)" :
+		      (__entry->who == 2) ? " (from user)" : "",
+		      __entry->inttype,
+		      __print_symbolic(__entry->inttype, kvm_s390_int_type),
+		      __entry->parm, __entry->parm64)
+	);
+
+TRACE_EVENT(kvm_s390_inject_vcpu,
+	    TP_PROTO(unsigned int id, __u64 type, __u32 parm, __u64 parm64, \
+		     int who),
+	    TP_ARGS(id, type, parm, parm64, who),
+
+	    TP_STRUCT__entry(
+		    __field(int, id)
+		    __field(__u32, inttype)
+		    __field(__u32, parm)
+		    __field(__u64, parm64)
+		    __field(int, who)
+		    ),
+
+	    TP_fast_assign(
+		    __entry->id = id;
+		    __entry->inttype = type & 0x00000000ffffffff;
+		    __entry->parm = parm;
+		    __entry->parm64 = parm64;
+		    __entry->who = who;
+		    ),
+
+	    TP_printk("inject%s (vcpu %d): type:%x (%s) parm:%x parm64:%llx",
+		      (__entry->who == 1) ? " (from kernel)" :
+		      (__entry->who == 2) ? " (from user)" : "",
+		      __entry->id, __entry->inttype,
+		      __print_symbolic(__entry->inttype, kvm_s390_int_type),
+		      __entry->parm, __entry->parm64)
+	);
+
+/*
+ * Trace point for the actual delivery of interrupts.
+ */
+TRACE_EVENT(kvm_s390_deliver_interrupt,
+	    TP_PROTO(unsigned int id, __u64 type, __u32 data0, __u64 data1),
+	    TP_ARGS(id, type, data0, data1),
+
+	    TP_STRUCT__entry(
+		    __field(int, id)
+		    __field(__u32, inttype)
+		    __field(__u32, data0)
+		    __field(__u64, data1)
+		    ),
+
+	    TP_fast_assign(
+		    __entry->id = id;
+		    __entry->inttype = type & 0x00000000ffffffff;
+		    __entry->data0 = data0;
+		    __entry->data1 = data1;
+		    ),
+
+	    TP_printk("deliver interrupt (vcpu %d): type:%x (%s) "	\
+		      "data:%08x %016llx",
+		      __entry->id, __entry->inttype,
+		      __print_symbolic(__entry->inttype, kvm_s390_int_type),
+		      __entry->data0, __entry->data1)
+	);
+
+/*
+ * Trace point for resets that may be requested from userspace.
+ */
+TRACE_EVENT(kvm_s390_request_resets,
+	    TP_PROTO(__u64 resets),
+	    TP_ARGS(resets),
+
+	    TP_STRUCT__entry(
+		    __field(__u64, resets)
+		    ),
+
+	    TP_fast_assign(
+		    __entry->resets = resets;
+		    ),
+
+	    TP_printk("requesting userspace resets %llx",
+		      __entry->resets)
+	);
+
+/*
+ * Trace point for a vcpu's stop requests.
+ */
+TRACE_EVENT(kvm_s390_stop_request,
+	    TP_PROTO(unsigned int action_bits),
+	    TP_ARGS(action_bits),
+
+	    TP_STRUCT__entry(
+		    __field(unsigned int, action_bits)
+		    ),
+
+	    TP_fast_assign(
+		    __entry->action_bits = action_bits;
+		    ),
+
+	    TP_printk("stop request, action_bits = %08x",
+		      __entry->action_bits)
+	);
+
+
+#endif /* _TRACE_KVMS390_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff --git a/arch/s390/kvm/trace.h b/arch/s390/kvm/trace.h
new file mode 100644
index 0000000..2b29e62
--- /dev/null
+++ b/arch/s390/kvm/trace.h
@@ -0,0 +1,341 @@
+#if !defined(_TRACE_KVM_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_KVM_H
+
+#include <linux/tracepoint.h>
+#include <asm/sigp.h>
+#include <asm/debug.h>
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM kvm
+#define TRACE_INCLUDE_PATH .
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE trace
+
+/*
+ * Helpers for vcpu-specific tracepoints containing the same information
+ * as s390dbf VCPU_EVENTs.
+ */
+#define VCPU_PROTO_COMMON struct kvm_vcpu *vcpu
+#define VCPU_ARGS_COMMON vcpu
+#define VCPU_FIELD_COMMON __field(int, id)			\
+	__field(unsigned long, pswmask)				\
+	__field(unsigned long, pswaddr)
+#define VCPU_ASSIGN_COMMON do {						\
+	__entry->id = vcpu->vcpu_id;					\
+	__entry->pswmask = vcpu->arch.sie_block->gpsw.mask;		\
+	__entry->pswaddr = vcpu->arch.sie_block->gpsw.addr;		\
+	} while (0);
+#define VCPU_TP_PRINTK(p_str, p_args...)				\
+	TP_printk("%02d[%016lx-%016lx]: " p_str, __entry->id,		\
+		  __entry->pswmask, __entry->pswaddr, p_args)
+
+/*
+ * Tracepoints for SIE entry and exit.
+ */
+TRACE_EVENT(kvm_s390_sie_enter,
+	    TP_PROTO(VCPU_PROTO_COMMON, int cpuflags),
+	    TP_ARGS(VCPU_ARGS_COMMON, cpuflags),
+
+	    TP_STRUCT__entry(
+		    VCPU_FIELD_COMMON
+		    __field(int, cpuflags)
+		    ),
+
+	    TP_fast_assign(
+		    VCPU_ASSIGN_COMMON
+		    __entry->cpuflags = cpuflags;
+		    ),
+
+	    VCPU_TP_PRINTK("entering sie flags %x", __entry->cpuflags)
+	);
+
+TRACE_EVENT(kvm_s390_sie_fault,
+	    TP_PROTO(VCPU_PROTO_COMMON),
+	    TP_ARGS(VCPU_ARGS_COMMON),
+
+	    TP_STRUCT__entry(
+		    VCPU_FIELD_COMMON
+		    ),
+
+	    TP_fast_assign(
+		    VCPU_ASSIGN_COMMON
+		    ),
+
+	    VCPU_TP_PRINTK("%s", "fault in sie instruction")
+	);
+
+#define sie_intercept_code				\
+	{0x04, "Instruction"},				\
+	{0x08, "Program interruption"},			\
+	{0x0C, "Instruction and program interuption"},	\
+	{0x10, "External request"},			\
+	{0x14, "External interruption"},		\
+	{0x18, "I/O request"},				\
+	{0x1C, "Wait state"},				\
+	{0x20, "Validity"},				\
+	{0x28, "Stop request"}
+
+TRACE_EVENT(kvm_s390_sie_exit,
+	    TP_PROTO(VCPU_PROTO_COMMON, u8 icptcode),
+	    TP_ARGS(VCPU_ARGS_COMMON, icptcode),
+
+	    TP_STRUCT__entry(
+		    VCPU_FIELD_COMMON
+		    __field(u8, icptcode)
+		    ),
+
+	    TP_fast_assign(
+		    VCPU_ASSIGN_COMMON
+		    __entry->icptcode = icptcode;
+		    ),
+
+	    VCPU_TP_PRINTK("exit sie icptcode %d (%s)", __entry->icptcode,
+			   __print_symbolic(__entry->icptcode,
+					    sie_intercept_code))
+	);
+
+/*
+ * Trace point for intercepted instructions.
+ */
+TRACE_EVENT(kvm_s390_intercept_instruction,
+	    TP_PROTO(VCPU_PROTO_COMMON, __u16 ipa, __u32 ipb),
+	    TP_ARGS(VCPU_ARGS_COMMON, ipa, ipb),
+
+	    TP_STRUCT__entry(
+		    VCPU_FIELD_COMMON
+		    __field(__u64, instruction)
+		    __field(char, insn[8])
+		    ),
+
+	    TP_fast_assign(
+		    VCPU_ASSIGN_COMMON
+		    __entry->instruction = ((__u64)ipa << 48) |
+		    ((__u64)ipb << 16);
+		    ),
+
+	    VCPU_TP_PRINTK("intercepted instruction %016llx (%s)",
+			   __entry->instruction,
+			   insn_to_mnemonic((unsigned char *)
+					    &__entry->instruction,
+					 __entry->insn) ?
+			   "unknown" : __entry->insn)
+	);
+
+/*
+ * Trace point for intercepted program interruptions.
+ */
+TRACE_EVENT(kvm_s390_intercept_prog,
+	    TP_PROTO(VCPU_PROTO_COMMON, __u16 code),
+	    TP_ARGS(VCPU_ARGS_COMMON, code),
+
+	    TP_STRUCT__entry(
+		    VCPU_FIELD_COMMON
+		    __field(__u16, code)
+		    ),
+
+	    TP_fast_assign(
+		    VCPU_ASSIGN_COMMON
+		    __entry->code = code;
+		    ),
+
+	    VCPU_TP_PRINTK("intercepted program interruption %04x",
+			   __entry->code)
+	);
+
+/*
+ * Trace point for validity intercepts.
+ */
+TRACE_EVENT(kvm_s390_intercept_validity,
+	    TP_PROTO(VCPU_PROTO_COMMON, __u16 viwhy),
+	    TP_ARGS(VCPU_ARGS_COMMON, viwhy),
+
+	    TP_STRUCT__entry(
+		    VCPU_FIELD_COMMON
+		    __field(__u16, viwhy)
+		    ),
+
+	    TP_fast_assign(
+		    VCPU_ASSIGN_COMMON
+		    __entry->viwhy = viwhy;
+		    ),
+
+	    VCPU_TP_PRINTK("got validity intercept %04x", __entry->viwhy)
+	);
+
+/*
+ * Trace points for instructions that are of special interest.
+ */
+
+#define sigp_order_codes					\
+	{SIGP_SENSE, "sense"},					\
+	{SIGP_EXTERNAL_CALL, "external call"},			\
+	{SIGP_EMERGENCY_SIGNAL, "emergency signal"},		\
+	{SIGP_STOP, "stop"},					\
+	{SIGP_STOP_AND_STORE_STATUS, "stop and store status"},	\
+	{SIGP_SET_ARCHITECTURE, "set architecture"},		\
+	{SIGP_SET_PREFIX, "set prefix"},			\
+	{SIGP_SENSE_RUNNING, "sense running"},			\
+	{SIGP_RESTART, "restart"}
+
+TRACE_EVENT(kvm_s390_handle_sigp,
+	    TP_PROTO(VCPU_PROTO_COMMON, __u8 order_code, __u16 cpu_addr, \
+		     __u32 parameter),
+	    TP_ARGS(VCPU_ARGS_COMMON, order_code, cpu_addr, parameter),
+
+	    TP_STRUCT__entry(
+		    VCPU_FIELD_COMMON
+		    __field(__u8, order_code)
+		    __field(__u16, cpu_addr)
+		    __field(__u32, parameter)
+		    ),
+
+	    TP_fast_assign(
+		    VCPU_ASSIGN_COMMON
+		    __entry->order_code = order_code;
+		    __entry->cpu_addr = cpu_addr;
+		    __entry->parameter = parameter;
+		    ),
+
+	    VCPU_TP_PRINTK("handle sigp order %02x (%s), cpu address %04x, " \
+			   "parameter %08x", __entry->order_code,
+			   __print_symbolic(__entry->order_code,
+					    sigp_order_codes),
+			   __entry->cpu_addr, __entry->parameter)
+	);
+
+#define diagnose_codes				\
+	{0x10, "release pages"},		\
+	{0x44, "time slice end"},		\
+	{0x308, "ipl functions"},		\
+	{0x500, "kvm hypercall"},		\
+	{0x501, "kvm breakpoint"}
+
+TRACE_EVENT(kvm_s390_handle_diag,
+	    TP_PROTO(VCPU_PROTO_COMMON, __u16 code),
+	    TP_ARGS(VCPU_ARGS_COMMON, code),
+
+	    TP_STRUCT__entry(
+		    VCPU_FIELD_COMMON
+		    __field(__u16, code)
+		    ),
+
+	    TP_fast_assign(
+		    VCPU_ASSIGN_COMMON
+		    __entry->code = code;
+		    ),
+
+	    VCPU_TP_PRINTK("handle diagnose call %04x (%s)", __entry->code,
+			   __print_symbolic(__entry->code, diagnose_codes))
+	);
+
+TRACE_EVENT(kvm_s390_handle_lctl,
+	    TP_PROTO(VCPU_PROTO_COMMON, int g, int reg1, int reg3, u64 addr),
+	    TP_ARGS(VCPU_ARGS_COMMON, g, reg1, reg3, addr),
+
+	    TP_STRUCT__entry(
+		    VCPU_FIELD_COMMON
+		    __field(int, g)
+		    __field(int, reg1)
+		    __field(int, reg3)
+		    __field(u64, addr)
+		    ),
+
+	    TP_fast_assign(
+		    VCPU_ASSIGN_COMMON
+		    __entry->g = g;
+		    __entry->reg1 = reg1;
+		    __entry->reg3 = reg3;
+		    __entry->addr = addr;
+		    ),
+
+	    VCPU_TP_PRINTK("%s: loading cr %x-%x from %016llx",
+			   __entry->g ? "lctlg" : "lctl",
+			   __entry->reg1, __entry->reg3, __entry->addr)
+	);
+
+TRACE_EVENT(kvm_s390_handle_prefix,
+	    TP_PROTO(VCPU_PROTO_COMMON, int set, u32 address),
+	    TP_ARGS(VCPU_ARGS_COMMON, set, address),
+
+	    TP_STRUCT__entry(
+		    VCPU_FIELD_COMMON
+		    __field(int, set)
+		    __field(u32, address)
+		    ),
+
+	    TP_fast_assign(
+		    VCPU_ASSIGN_COMMON
+		    __entry->set = set;
+		    __entry->address = address;
+		    ),
+
+	    VCPU_TP_PRINTK("%s prefix to %08x",
+			   __entry->set ? "setting" : "storing",
+			   __entry->address)
+	);
+
+TRACE_EVENT(kvm_s390_handle_stap,
+	    TP_PROTO(VCPU_PROTO_COMMON, u64 address),
+	    TP_ARGS(VCPU_ARGS_COMMON, address),
+
+	    TP_STRUCT__entry(
+		    VCPU_FIELD_COMMON
+		    __field(u64, address)
+		    ),
+
+	    TP_fast_assign(
+		    VCPU_ASSIGN_COMMON
+		    __entry->address = address;
+		    ),
+
+	    VCPU_TP_PRINTK("storing cpu address to %016llx",
+			   __entry->address)
+	);
+
+TRACE_EVENT(kvm_s390_handle_stfl,
+	    TP_PROTO(VCPU_PROTO_COMMON, unsigned int facility_list),
+	    TP_ARGS(VCPU_ARGS_COMMON, facility_list),
+
+	    TP_STRUCT__entry(
+		    VCPU_FIELD_COMMON
+		    __field(unsigned int, facility_list)
+		    ),
+
+	    TP_fast_assign(
+		    VCPU_ASSIGN_COMMON
+		    __entry->facility_list = facility_list;
+		    ),
+
+	    VCPU_TP_PRINTK("store facility list value %08x",
+			   __entry->facility_list)
+	);
+
+TRACE_EVENT(kvm_s390_handle_stsi,
+	    TP_PROTO(VCPU_PROTO_COMMON, int fc, int sel1, int sel2, u64 addr),
+	    TP_ARGS(VCPU_ARGS_COMMON, fc, sel1, sel2, addr),
+
+	    TP_STRUCT__entry(
+		    VCPU_FIELD_COMMON
+		    __field(int, fc)
+		    __field(int, sel1)
+		    __field(int, sel2)
+		    __field(u64, addr)
+		    ),
+
+	    TP_fast_assign(
+		    VCPU_ASSIGN_COMMON
+		    __entry->fc = fc;
+		    __entry->sel1 = sel1;
+		    __entry->sel2 = sel2;
+		    __entry->addr = addr;
+		    ),
+
+	    VCPU_TP_PRINTK("STSI %d.%d.%d information stored to %016llx",
+			   __entry->fc, __entry->sel1, __entry->sel2,
+			   __entry->addr)
+	);
+
+#endif /* _TRACE_KVM_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff --git a/arch/s390/lib/Makefile b/arch/s390/lib/Makefile
index 761ab8b..6ab0d0b 100644
--- a/arch/s390/lib/Makefile
+++ b/arch/s390/lib/Makefile
@@ -4,6 +4,7 @@
 
 lib-y += delay.o string.o uaccess_std.o uaccess_pt.o
 obj-y += usercopy.o
-obj-$(CONFIG_32BIT) += div64.o qrnnd.o ucmpdi2.o
+obj-$(CONFIG_32BIT) += div64.o qrnnd.o ucmpdi2.o mem32.o
+obj-$(CONFIG_64BIT) += mem64.o
 lib-$(CONFIG_64BIT) += uaccess_mvcos.o
 lib-$(CONFIG_SMP) += spinlock.o
diff --git a/arch/s390/lib/mem32.S b/arch/s390/lib/mem32.S
new file mode 100644
index 0000000..14ca924
--- /dev/null
+++ b/arch/s390/lib/mem32.S
@@ -0,0 +1,92 @@
+/*
+ * String handling functions.
+ *
+ * Copyright IBM Corp. 2012
+ */
+
+#include <linux/linkage.h>
+
+/*
+ * memset implementation
+ *
+ * This code corresponds to the C construct below. We do distinguish
+ * between clearing (c == 0) and setting a memory array (c != 0) simply
+ * because nearly all memset invocations in the kernel clear memory and
+ * the xc instruction is preferred in such cases.
+ *
+ * void *memset(void *s, int c, size_t n)
+ * {
+ *	if (likely(c == 0))
+ *		return __builtin_memset(s, 0, n);
+ *	return __builtin_memset(s, c, n);
+ * }
+ */
+ENTRY(memset)
+	basr	%r5,%r0
+.Lmemset_base:
+	ltr	%r4,%r4
+	bzr	%r14
+	ltr	%r3,%r3
+	jnz	.Lmemset_fill
+	ahi	%r4,-1
+	lr	%r3,%r4
+	srl	%r3,8
+	ltr	%r3,%r3
+	lr	%r1,%r2
+	je	.Lmemset_clear_rest
+.Lmemset_clear_loop:
+	xc	0(256,%r1),0(%r1)
+	la	%r1,256(%r1)
+	brct	%r3,.Lmemset_clear_loop
+.Lmemset_clear_rest:
+	ex	%r4,.Lmemset_xc-.Lmemset_base(%r5)
+	br	%r14
+.Lmemset_fill:
+	stc	%r3,0(%r2)
+	chi	%r4,1
+	lr	%r1,%r2
+	ber	%r14
+	ahi	%r4,-2
+	lr	%r3,%r4
+	srl	%r3,8
+	ltr	%r3,%r3
+	je	.Lmemset_fill_rest
+.Lmemset_fill_loop:
+	mvc	1(256,%r1),0(%r1)
+	la	%r1,256(%r1)
+	brct	%r3,.Lmemset_fill_loop
+.Lmemset_fill_rest:
+	ex	%r4,.Lmemset_mvc-.Lmemset_base(%r5)
+	br	%r14
+.Lmemset_xc:
+	xc	0(1,%r1),0(%r1)
+.Lmemset_mvc:
+	mvc	1(1,%r1),0(%r1)
+
+/*
+ * memcpy implementation
+ *
+ * void *memcpy(void *dest, const void *src, size_t n)
+ */
+ENTRY(memcpy)
+	basr	%r5,%r0
+.Lmemcpy_base:
+	ltr	%r4,%r4
+	bzr	%r14
+	ahi	%r4,-1
+	lr	%r0,%r4
+	srl	%r0,8
+	ltr	%r0,%r0
+	lr	%r1,%r2
+	jnz	.Lmemcpy_loop
+.Lmemcpy_rest:
+	ex	%r4,.Lmemcpy_mvc-.Lmemcpy_base(%r5)
+	br	%r14
+.Lmemcpy_loop:
+	mvc	0(256,%r1),0(%r3)
+	la	%r1,256(%r1)
+	la	%r3,256(%r3)
+	brct	%r0,.Lmemcpy_loop
+	j	.Lmemcpy_rest
+.Lmemcpy_mvc:
+	mvc	0(1,%r1),0(%r3)
diff --git a/arch/s390/lib/mem64.S b/arch/s390/lib/mem64.S
new file mode 100644
index 0000000..c6d553e
--- /dev/null
+++ b/arch/s390/lib/mem64.S
@@ -0,0 +1,88 @@
+/*
+ * String handling functions.
+ *
+ * Copyright IBM Corp. 2012
+ */
+
+#include <linux/linkage.h>
+
+/*
+ * memset implementation
+ *
+ * This code corresponds to the C construct below. We do distinguish
+ * between clearing (c == 0) and setting a memory array (c != 0) simply
+ * because nearly all memset invocations in the kernel clear memory and
+ * the xc instruction is preferred in such cases.
+ *
+ * void *memset(void *s, int c, size_t n)
+ * {
+ *	if (likely(c == 0))
+ *		return __builtin_memset(s, 0, n);
+ *	return __builtin_memset(s, c, n);
+ * }
+ */
+ENTRY(memset)
+	ltgr	%r4,%r4
+	bzr	%r14
+	ltgr	%r3,%r3
+	jnz	.Lmemset_fill
+	aghi	%r4,-1
+	srlg	%r3,%r4,8
+	ltgr	%r3,%r3
+	lgr	%r1,%r2
+	jz	.Lmemset_clear_rest
+.Lmemset_clear_loop:
+	xc	0(256,%r1),0(%r1)
+	la	%r1,256(%r1)
+	brctg	%r3,.Lmemset_clear_loop
+.Lmemset_clear_rest:
+	larl	%r3,.Lmemset_xc
+	ex	%r4,0(%r3)
+	br	%r14
+.Lmemset_fill:
+	stc	%r3,0(%r2)
+	cghi	%r4,1
+	lgr	%r1,%r2
+	ber	%r14
+	aghi	%r4,-2
+	srlg	%r3,%r4,8
+	ltgr	%r3,%r3
+	jz	.Lmemset_fill_rest
+.Lmemset_fill_loop:
+	mvc	1(256,%r1),0(%r1)
+	la	%r1,256(%r1)
+	brctg	%r3,.Lmemset_fill_loop
+.Lmemset_fill_rest:
+	larl	%r3,.Lmemset_mvc
+	ex	%r4,0(%r3)
+	br	%r14
+.Lmemset_xc:
+	xc	0(1,%r1),0(%r1)
+.Lmemset_mvc:
+	mvc	1(1,%r1),0(%r1)
+
+/*
+ * memcpy implementation
+ *
+ * void *memcpy(void *dest, const void *src, size_t n)
+ */
+ENTRY(memcpy)
+	ltgr	%r4,%r4
+	bzr	%r14
+	aghi	%r4,-1
+	srlg	%r5,%r4,8
+	ltgr	%r5,%r5
+	lgr	%r1,%r2
+	jnz	.Lmemcpy_loop
+.Lmemcpy_rest:
+	larl	%r5,.Lmemcpy_mvc
+	ex	%r4,0(%r5)
+	br	%r14
+.Lmemcpy_loop:
+	mvc	0(256,%r1),0(%r3)
+	la	%r1,256(%r1)
+	la	%r3,256(%r3)
+	brctg	%r5,.Lmemcpy_loop
+	j	.Lmemcpy_rest
+.Lmemcpy_mvc:
+	mvc	0(1,%r1),0(%r3)
diff --git a/arch/s390/lib/string.c b/arch/s390/lib/string.c
index 846ec64..b647d5f 100644
--- a/arch/s390/lib/string.c
+++ b/arch/s390/lib/string.c
@@ -43,11 +43,7 @@ static inline char *__strnend(const char *s, size_t n)
  */
 size_t strlen(const char *s)
 {
-#if __GNUC__ < 4
 	return __strend(s) - s;
-#else
-	return __builtin_strlen(s);
-#endif
 }
 EXPORT_SYMBOL(strlen);
 
@@ -73,7 +69,6 @@ EXPORT_SYMBOL(strnlen);
  */
 char *strcpy(char *dest, const char *src)
 {
-#if __GNUC__ < 4
 	register int r0 asm("0") = 0;
 	char *ret = dest;
 
@@ -82,9 +77,6 @@ char *strcpy(char *dest, const char *src)
 		      : "+&a" (dest), "+&a" (src) : "d" (r0)
 		      : "cc", "memory" );
 	return ret;
-#else
-	return __builtin_strcpy(dest, src);
-#endif
 }
 EXPORT_SYMBOL(strcpy);
 
@@ -106,7 +98,7 @@ size_t strlcpy(char *dest, const char *src, size_t size)
 	if (size) {
 		size_t len = (ret >= size) ? size-1 : ret;
 		dest[len] = '\0';
-		__builtin_memcpy(dest, src, len);
+		memcpy(dest, src, len);
 	}
 	return ret;
 }
@@ -124,8 +116,8 @@ EXPORT_SYMBOL(strlcpy);
 char *strncpy(char *dest, const char *src, size_t n)
 {
 	size_t len = __strnend(src, n) - src;
-	__builtin_memset(dest + len, 0, n - len);
-	__builtin_memcpy(dest, src, len);
+	memset(dest + len, 0, n - len);
+	memcpy(dest, src, len);
 	return dest;
 }
 EXPORT_SYMBOL(strncpy);
@@ -171,7 +163,7 @@ size_t strlcat(char *dest, const char *src, size_t n)
 		if (len >= n)
 			len = n - 1;
 		dest[len] = '\0';
-		__builtin_memcpy(dest, src, len);
+		memcpy(dest, src, len);
 	}
 	return res;
 }
@@ -194,7 +186,7 @@ char *strncat(char *dest, const char *src, size_t n)
 	char *p = __strend(dest);
 
 	p[len] = '\0';
-	__builtin_memcpy(p, src, len);
+	memcpy(p, src, len);
 	return dest;
 }
 EXPORT_SYMBOL(strncat);
@@ -348,41 +340,3 @@ void *memscan(void *s, int c, size_t n)
 	return (void *) ret;
 }
 EXPORT_SYMBOL(memscan);
-
-/**
- * memcpy - Copy one area of memory to another
- * @dest: Where to copy to
- * @src: Where to copy from
- * @n: The size of the area.
- *
- * returns a pointer to @dest
- */
-void *memcpy(void *dest, const void *src, size_t n)
-{
-	return __builtin_memcpy(dest, src, n);
-}
-EXPORT_SYMBOL(memcpy);
-
-/**
- * memset - Fill a region of memory with the given value
- * @s: Pointer to the start of the area.
- * @c: The byte to fill the area with
- * @n: The size of the area.
- *
- * returns a pointer to @s
- */
-void *memset(void *s, int c, size_t n)
-{
-	char *xs;
-
-	if (c == 0)
-		return __builtin_memset(s, 0, n);
-
-	xs = (char *) s;
-	if (n > 0)
-		do {
-			*xs++ = c;
-		} while (--n > 0);
-	return s;
-}
-EXPORT_SYMBOL(memset);
diff --git a/arch/s390/mm/Makefile b/arch/s390/mm/Makefile
index d98fe90..0f5536b 100644
--- a/arch/s390/mm/Makefile
+++ b/arch/s390/mm/Makefile
@@ -3,7 +3,7 @@
 #
 
 obj-y	 := init.o fault.o extmem.o mmap.o vmem.o pgtable.o maccess.o \
-	    page-states.o gup.o
+	    page-states.o gup.o extable.o
 obj-$(CONFIG_CMM) += cmm.o
 obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
 obj-$(CONFIG_DEBUG_SET_MODULE_RONX) += pageattr.o
diff --git a/arch/s390/mm/extable.c b/arch/s390/mm/extable.c
new file mode 100644
index 0000000..4d1ee88
--- /dev/null
+++ b/arch/s390/mm/extable.c
@@ -0,0 +1,81 @@
+#include <linux/module.h>
+#include <linux/sort.h>
+#include <asm/uaccess.h>
+
+/*
+ * Search one exception table for an entry corresponding to the
+ * given instruction address, and return the address of the entry,
+ * or NULL if none is found.
+ * We use a binary search, and thus we assume that the table is
+ * already sorted.
+ */
+const struct exception_table_entry *
+search_extable(const struct exception_table_entry *first,
+	       const struct exception_table_entry *last,
+	       unsigned long value)
+{
+	const struct exception_table_entry *mid;
+	unsigned long addr;
+
+	while (first <= last) {
+		mid = ((last - first) >> 1) + first;
+		addr = extable_insn(mid);
+		if (addr < value)
+			first = mid + 1;
+		else if (addr > value)
+			last = mid - 1;
+		else
+			return mid;
+	}
+	return NULL;
+}
+
+/*
+ * The exception table needs to be sorted so that the binary
+ * search that we use to find entries in it works properly.
+ * This is used both for the kernel exception table and for
+ * the exception tables of modules that get loaded.
+ *
+ */
+static int cmp_ex(const void *a, const void *b)
+{
+	const struct exception_table_entry *x = a, *y = b;
+
+	/* This compare is only valid after normalization. */
+	return x->insn - y->insn;
+}
+
+void sort_extable(struct exception_table_entry *start,
+		  struct exception_table_entry *finish)
+{
+	struct exception_table_entry *p;
+	int i;
+
+	/* Normalize entries to being relative to the start of the section */
+	for (p = start, i = 0; p < finish; p++, i += 8)
+		p->insn += i;
+	sort(start, finish - start, sizeof(*start), cmp_ex, NULL);
+	/* Denormalize all entries */
+	for (p = start, i = 0; p < finish; p++, i += 8)
+		p->insn -= i;
+}
+
+#ifdef CONFIG_MODULES
+/*
+ * If the exception table is sorted, any referring to the module init
+ * will be at the beginning or the end.
+ */
+void trim_init_extable(struct module *m)
+{
+	/* Trim the beginning */
+	while (m->num_exentries &&
+	       within_module_init(extable_insn(&m->extable[0]), m)) {
+		m->extable++;
+		m->num_exentries--;
+	}
+	/* Trim the end */
+	while (m->num_exentries &&
+	       within_module_init(extable_insn(&m->extable[m->num_exentries-1]), m))
+		m->num_exentries--;
+}
+#endif /* CONFIG_MODULES */
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index 6c013f5..04ad400 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -111,7 +111,7 @@ static inline int user_space_fault(unsigned long trans_exc_code)
 	if (trans_exc_code == 2)
 		/* Access via secondary space, set_fs setting decides */
 		return current->thread.mm_segment.ar4;
-	if (addressing_mode == HOME_SPACE_MODE)
+	if (s390_user_mode == HOME_SPACE_MODE)
 		/* User space if the access has been done via home space. */
 		return trans_exc_code == 3;
 	/*
@@ -163,7 +163,7 @@ static noinline void do_no_context(struct pt_regs *regs)
 	/* Are we prepared to handle this kernel fault?  */
 	fixup = search_exception_tables(regs->psw.addr & PSW_ADDR_INSN);
 	if (fixup) {
-		regs->psw.addr = fixup->fixup | PSW_ADDR_AMODE;
+		regs->psw.addr = extable_fixup(fixup) | PSW_ADDR_AMODE;
 		return;
 	}
 
@@ -367,6 +367,7 @@ retry:
 			/* Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk
 			 * of starvation. */
 			flags &= ~FAULT_FLAG_ALLOW_RETRY;
+			flags |= FAULT_FLAG_TRIED;
 			down_read(&mm->mmap_sem);
 			goto retry;
 		}
@@ -628,9 +629,8 @@ static int __cpuinit pfault_cpu_notify(struct notifier_block *self,
 	struct thread_struct *thread, *next;
 	struct task_struct *tsk;
 
-	switch (action) {
+	switch (action & ~CPU_TASKS_FROZEN) {
 	case CPU_DEAD:
-	case CPU_DEAD_FROZEN:
 		spin_lock_irq(&pfault_lock);
 		list_for_each_entry_safe(thread, next, &pfault_list, list) {
 			thread->pfault_wait = 0;
diff --git a/arch/s390/mm/gup.c b/arch/s390/mm/gup.c
index 65cb06e..60acb93 100644
--- a/arch/s390/mm/gup.c
+++ b/arch/s390/mm/gup.c
@@ -115,7 +115,16 @@ static inline int gup_pmd_range(pud_t *pudp, pud_t pud, unsigned long addr,
 		pmd = *pmdp;
 		barrier();
 		next = pmd_addr_end(addr, end);
-		if (pmd_none(pmd))
+		/*
+		 * The pmd_trans_splitting() check below explains why
+		 * pmdp_splitting_flush() has to serialize with
+		 * smp_call_function() against our disabled IRQs, to stop
+		 * this gup-fast code from running while we set the
+		 * splitting bit in the pmd. Returning zero will take
+		 * the slow path that will call wait_split_huge_page()
+		 * if the pmd is still in splitting state.
+		 */
+		if (pmd_none(pmd) || pmd_trans_splitting(pmd))
 			return 0;
 		if (unlikely(pmd_huge(pmd))) {
 			if (!gup_huge_pmd(pmdp, pmd, addr, next,
@@ -154,6 +163,43 @@ static inline int gup_pud_range(pgd_t *pgdp, pgd_t pgd, unsigned long addr,
 	return 1;
 }
 
+/*
+ * Like get_user_pages_fast() except its IRQ-safe in that it won't fall
+ * back to the regular GUP.
+ */
+int __get_user_pages_fast(unsigned long start, int nr_pages, int write,
+			  struct page **pages)
+{
+	struct mm_struct *mm = current->mm;
+	unsigned long addr, len, end;
+	unsigned long next, flags;
+	pgd_t *pgdp, pgd;
+	int nr = 0;
+
+	start &= PAGE_MASK;
+	addr = start;
+	len = (unsigned long) nr_pages << PAGE_SHIFT;
+	end = start + len;
+	if (unlikely(!access_ok(write ? VERIFY_WRITE : VERIFY_READ,
+					(void __user *)start, len)))
+		return 0;
+
+	local_irq_save(flags);
+	pgdp = pgd_offset(mm, addr);
+	do {
+		pgd = *pgdp;
+		barrier();
+		next = pgd_addr_end(addr, end);
+		if (pgd_none(pgd))
+			break;
+		if (!gup_pud_range(pgdp, pgd, addr, next, write, pages, &nr))
+			break;
+	} while (pgdp++, addr = next, addr != end);
+	local_irq_restore(flags);
+
+	return nr;
+}
+
 /**
  * get_user_pages_fast() - pin user pages in memory
  * @start:	starting user address
diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c
index 18df31d..c8188a1 100644
--- a/arch/s390/mm/pgtable.c
+++ b/arch/s390/mm/pgtable.c
@@ -609,8 +609,8 @@ static inline unsigned int atomic_xor_bits(atomic_t *v, unsigned int bits)
  */
 unsigned long *page_table_alloc(struct mm_struct *mm, unsigned long vmaddr)
 {
-	struct page *page;
-	unsigned long *table;
+	unsigned long *uninitialized_var(table);
+	struct page *uninitialized_var(page);
 	unsigned int mask, bit;
 
 	if (mm_has_pgste(mm))
@@ -787,6 +787,30 @@ void tlb_remove_table(struct mmu_gather *tlb, void *table)
 		tlb_table_flush(tlb);
 }
 
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+void thp_split_vma(struct vm_area_struct *vma)
+{
+	unsigned long addr;
+	struct page *page;
+
+	for (addr = vma->vm_start; addr < vma->vm_end; addr += PAGE_SIZE) {
+		page = follow_page(vma, addr, FOLL_SPLIT);
+	}
+}
+
+void thp_split_mm(struct mm_struct *mm)
+{
+	struct vm_area_struct *vma = mm->mmap;
+
+	while (vma != NULL) {
+		thp_split_vma(vma);
+		vma->vm_flags &= ~VM_HUGEPAGE;
+		vma->vm_flags |= VM_NOHUGEPAGE;
+		vma = vma->vm_next;
+	}
+}
+#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
+
 /*
  * switch on pgstes for its userspace process (for kvm)
  */
@@ -796,7 +820,7 @@ int s390_enable_sie(void)
 	struct mm_struct *mm, *old_mm;
 
 	/* Do we have switched amode? If no, we cannot do sie */
-	if (addressing_mode == HOME_SPACE_MODE)
+	if (s390_user_mode == HOME_SPACE_MODE)
 		return -EINVAL;
 
 	/* Do we have pgstes? if yes, we are done */
@@ -824,6 +848,12 @@ int s390_enable_sie(void)
 	if (!mm)
 		return -ENOMEM;
 
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+	/* split thp mappings and disable thp for future mappings */
+	thp_split_mm(mm);
+	mm->def_flags |= VM_NOHUGEPAGE;
+#endif
+
 	/* Now lets check again if something happened */
 	task_lock(tsk);
 	if (!tsk->mm || atomic_read(&tsk->mm->mm_users) > 1 ||
@@ -866,3 +896,81 @@ bool kernel_page_present(struct page *page)
 	return cc == 0;
 }
 #endif /* CONFIG_HIBERNATION && CONFIG_DEBUG_PAGEALLOC */
+
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+int pmdp_clear_flush_young(struct vm_area_struct *vma, unsigned long address,
+			   pmd_t *pmdp)
+{
+	VM_BUG_ON(address & ~HPAGE_PMD_MASK);
+	/* No need to flush TLB
+	 * On s390 reference bits are in storage key and never in TLB */
+	return pmdp_test_and_clear_young(vma, address, pmdp);
+}
+
+int pmdp_set_access_flags(struct vm_area_struct *vma,
+			  unsigned long address, pmd_t *pmdp,
+			  pmd_t entry, int dirty)
+{
+	VM_BUG_ON(address & ~HPAGE_PMD_MASK);
+
+	if (pmd_same(*pmdp, entry))
+		return 0;
+	pmdp_invalidate(vma, address, pmdp);
+	set_pmd_at(vma->vm_mm, address, pmdp, entry);
+	return 1;
+}
+
+static void pmdp_splitting_flush_sync(void *arg)
+{
+	/* Simply deliver the interrupt */
+}
+
+void pmdp_splitting_flush(struct vm_area_struct *vma, unsigned long address,
+			  pmd_t *pmdp)
+{
+	VM_BUG_ON(address & ~HPAGE_PMD_MASK);
+	if (!test_and_set_bit(_SEGMENT_ENTRY_SPLIT_BIT,
+			      (unsigned long *) pmdp)) {
+		/* need to serialize against gup-fast (IRQ disabled) */
+		smp_call_function(pmdp_splitting_flush_sync, NULL, 1);
+	}
+}
+
+void pgtable_trans_huge_deposit(struct mm_struct *mm, pgtable_t pgtable)
+{
+	struct list_head *lh = (struct list_head *) pgtable;
+
+	assert_spin_locked(&mm->page_table_lock);
+
+	/* FIFO */
+	if (!mm->pmd_huge_pte)
+		INIT_LIST_HEAD(lh);
+	else
+		list_add(lh, (struct list_head *) mm->pmd_huge_pte);
+	mm->pmd_huge_pte = pgtable;
+}
+
+pgtable_t pgtable_trans_huge_withdraw(struct mm_struct *mm)
+{
+	struct list_head *lh;
+	pgtable_t pgtable;
+	pte_t *ptep;
+
+	assert_spin_locked(&mm->page_table_lock);
+
+	/* FIFO */
+	pgtable = mm->pmd_huge_pte;
+	lh = (struct list_head *) pgtable;
+	if (list_empty(lh))
+		mm->pmd_huge_pte = NULL;
+	else {
+		mm->pmd_huge_pte = (pgtable_t) lh->next;
+		list_del(lh);
+	}
+	ptep = (pte_t *) pgtable;
+	pte_val(*ptep) = _PAGE_TYPE_EMPTY;
+	ptep++;
+	pte_val(*ptep) = _PAGE_TYPE_EMPTY;
+	return pgtable;
+}
+#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
diff --git a/arch/s390/mm/vmem.c b/arch/s390/mm/vmem.c
index 6f896e7..c22abf9 100644
--- a/arch/s390/mm/vmem.c
+++ b/arch/s390/mm/vmem.c
@@ -107,7 +107,7 @@ static int vmem_add_mem(unsigned long start, unsigned long size, int ro)
 		pte = mk_pte_phys(address, __pgprot(ro ? _PAGE_RO : 0));
 		pm_dir = pmd_offset(pu_dir, address);
 
-#ifdef CONFIG_64BIT
+#if defined(CONFIG_64BIT) && !defined(CONFIG_DEBUG_PAGEALLOC)
 		if (MACHINE_HAS_HPAGE && !(address & ~HPAGE_MASK) &&
 		    (address + HPAGE_SIZE <= start + size) &&
 		    (address >= HPAGE_SIZE)) {
diff --git a/arch/s390/net/Makefile b/arch/s390/net/Makefile
new file mode 100644
index 0000000..90568c3
--- /dev/null
+++ b/arch/s390/net/Makefile
@@ -0,0 +1,4 @@
+#
+# Arch-specific network modules
+#
+obj-$(CONFIG_BPF_JIT) += bpf_jit.o bpf_jit_comp.o
diff --git a/arch/s390/net/bpf_jit.S b/arch/s390/net/bpf_jit.S
new file mode 100644
index 0000000..7e45d13
--- /dev/null
+++ b/arch/s390/net/bpf_jit.S
@@ -0,0 +1,130 @@
+/*
+ * BPF Jit compiler for s390, help functions.
+ *
+ * Copyright IBM Corp. 2012
+ *
+ * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
+ */
+#include <linux/linkage.h>
+
+/*
+ * Calling convention:
+ * registers %r2, %r6-%r8, %r10-%r11, %r13, %r15 are call saved
+ *   %r2: skb pointer
+ *   %r3: offset parameter
+ *   %r5: BPF A accumulator
+ *   %r8: return address
+ *   %r9: save register for skb pointer
+ *   %r10: skb->data
+ *   %r11: skb->len - skb->data_len (headlen)
+ *   %r12: BPF X accumulator
+ *
+ * skb_copy_bits takes 4 parameters:
+ *   %r2 = skb pointer
+ *   %r3 = offset into skb data
+ *   %r4 = length to copy
+ *   %r5 = pointer to temp buffer
+ */
+#define SKBDATA	%r8
+
+	/* A = *(u32 *) (skb->data+K+X) */
+ENTRY(sk_load_word_ind)
+	ar	%r3,%r12		# offset += X
+	bmr	%r8			# < 0 -> return with cc
+
+	/* A = *(u32 *) (skb->data+K) */
+ENTRY(sk_load_word)
+	llgfr	%r1,%r3			# extend offset
+	ahi	%r3,4			# offset + 4
+	clr	%r11,%r3		# hlen <= offset + 4 ?
+	jl	sk_load_word_slow
+	l	%r5,0(%r1,%r10)		# get word from skb
+	xr	%r1,%r1			# set cc to zero
+	br	%r8
+
+sk_load_word_slow:
+	lgr	%r9,%r2			# save %r2
+	lhi	%r4,4			# 4 bytes
+	la	%r5,160(%r15)		# pointer to temp buffer
+	brasl	%r14,skb_copy_bits	# get data from skb
+	l	%r5,160(%r15)		# load result from temp buffer
+	ltgr	%r2,%r2			# set cc to (%r2 != 0)
+	lgr	%r2,%r9			# restore %r2
+	br	%r8
+
+	/* A = *(u16 *) (skb->data+K+X) */
+ENTRY(sk_load_half_ind)
+	ar	%r3,%r12		# offset += X
+	bmr	%r8			# < 0 -> return with cc
+
+	/* A = *(u16 *) (skb->data+K) */
+ENTRY(sk_load_half)
+	llgfr	%r1,%r3			# extend offset
+	ahi	%r3,2			# offset + 2
+	clr	%r11,%r3		# hlen <= offset + 2 ?
+	jl	sk_load_half_slow
+	llgh	%r5,0(%r1,%r10)		# get half from skb
+	xr	%r1,%r1			# set cc to zero
+	br	%r8
+
+sk_load_half_slow:
+	lgr	%r9,%r2			# save %r2
+	lhi	%r4,2			# 2 bytes
+	la	%r5,162(%r15)		# pointer to temp buffer
+	brasl	%r14,skb_copy_bits	# get data from skb
+	xc	160(2,%r15),160(%r15)
+	l	%r5,160(%r15)		# load result from temp buffer
+	ltgr	%r2,%r2			# set cc to (%r2 != 0)
+	lgr	%r2,%r9			# restore %r2
+	br	%r8
+
+	/* A = *(u8 *) (skb->data+K+X) */
+ENTRY(sk_load_byte_ind)
+	ar	%r3,%r12		# offset += X
+	bmr	%r8			# < 0 -> return with cc
+
+	/* A = *(u8 *) (skb->data+K) */
+ENTRY(sk_load_byte)
+	llgfr	%r1,%r3			# extend offset
+	clr	%r11,%r3		# hlen < offset ?
+	jle	sk_load_byte_slow
+	lhi	%r5,0
+	ic	%r5,0(%r1,%r10)		# get byte from skb
+	xr	%r1,%r1			# set cc to zero
+	br	%r8
+
+sk_load_byte_slow:
+	lgr	%r9,%r2			# save %r2
+	lhi	%r4,1			# 1 bytes
+	la	%r5,163(%r15)		# pointer to temp buffer
+	brasl	%r14,skb_copy_bits	# get data from skb
+	xc	160(3,%r15),160(%r15)
+	l	%r5,160(%r15)		# load result from temp buffer
+	ltgr	%r2,%r2			# set cc to (%r2 != 0)
+	lgr	%r2,%r9			# restore %r2
+	br	%r8
+
+	/* A = (*(u8 *)(skb->data+K) & 0xf) << 2 */
+ENTRY(sk_load_byte_msh)
+	llgfr	%r1,%r3			# extend offset
+	clr	%r11,%r3		# hlen < offset ?
+	jle	sk_load_byte_slow
+	lhi	%r12,0
+	ic	%r12,0(%r1,%r10)	# get byte from skb
+	nill	%r12,0x0f
+	sll	%r12,2
+	xr	%r1,%r1			# set cc to zero
+	br	%r8
+
+sk_load_byte_msh_slow:
+	lgr	%r9,%r2			# save %r2
+	lhi	%r4,2			# 2 bytes
+	la	%r5,162(%r15)		# pointer to temp buffer
+	brasl	%r14,skb_copy_bits	# get data from skb
+	xc	160(3,%r15),160(%r15)
+	l	%r12,160(%r15)		# load result from temp buffer
+	nill	%r12,0x0f
+	sll	%r12,2
+	ltgr	%r2,%r2			# set cc to (%r2 != 0)
+	lgr	%r2,%r9			# restore %r2
+	br	%r8
diff --git a/arch/s390/net/bpf_jit_comp.c b/arch/s390/net/bpf_jit_comp.c
new file mode 100644
index 0000000..f57f0c3
--- /dev/null
+++ b/arch/s390/net/bpf_jit_comp.c
@@ -0,0 +1,771 @@
+/*
+ * BPF Jit compiler for s390.
+ *
+ * Copyright IBM Corp. 2012
+ *
+ * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
+ */
+#include <linux/moduleloader.h>
+#include <linux/netdevice.h>
+#include <linux/filter.h>
+#include <asm/cacheflush.h>
+#include <asm/processor.h>
+#include <asm/facility.h>
+
+/*
+ * Conventions:
+ *   %r2 = skb pointer
+ *   %r3 = offset parameter
+ *   %r4 = scratch register / length parameter
+ *   %r5 = BPF A accumulator
+ *   %r8 = return address
+ *   %r9 = save register for skb pointer
+ *   %r10 = skb->data
+ *   %r11 = skb->len - skb->data_len (headlen)
+ *   %r12 = BPF X accumulator
+ *   %r13 = literal pool pointer
+ *   0(%r15) - 63(%r15) scratch memory array with BPF_MEMWORDS
+ */
+int bpf_jit_enable __read_mostly;
+
+/*
+ * assembly code in arch/x86/net/bpf_jit.S
+ */
+extern u8 sk_load_word[], sk_load_half[], sk_load_byte[], sk_load_byte_msh[];
+extern u8 sk_load_word_ind[], sk_load_half_ind[], sk_load_byte_ind[];
+
+struct bpf_jit {
+	unsigned int seen;
+	u8 *start;
+	u8 *prg;
+	u8 *mid;
+	u8 *lit;
+	u8 *end;
+	u8 *base_ip;
+	u8 *ret0_ip;
+	u8 *exit_ip;
+	unsigned int off_load_word;
+	unsigned int off_load_half;
+	unsigned int off_load_byte;
+	unsigned int off_load_bmsh;
+	unsigned int off_load_iword;
+	unsigned int off_load_ihalf;
+	unsigned int off_load_ibyte;
+};
+
+#define BPF_SIZE_MAX	4096	/* Max size for program */
+
+#define SEEN_DATAREF	1	/* might call external helpers */
+#define SEEN_XREG	2	/* ebx is used */
+#define SEEN_MEM	4	/* use mem[] for temporary storage */
+#define SEEN_RET0	8	/* pc_ret0 points to a valid return 0 */
+#define SEEN_LITERAL	16	/* code uses literals */
+#define SEEN_LOAD_WORD	32	/* code uses sk_load_word */
+#define SEEN_LOAD_HALF	64	/* code uses sk_load_half */
+#define SEEN_LOAD_BYTE	128	/* code uses sk_load_byte */
+#define SEEN_LOAD_BMSH	256	/* code uses sk_load_byte_msh */
+#define SEEN_LOAD_IWORD	512	/* code uses sk_load_word_ind */
+#define SEEN_LOAD_IHALF	1024	/* code uses sk_load_half_ind */
+#define SEEN_LOAD_IBYTE	2048	/* code uses sk_load_byte_ind */
+
+#define EMIT2(op)					\
+({							\
+	if (jit->prg + 2 <= jit->mid)			\
+		*(u16 *) jit->prg = op;			\
+	jit->prg += 2;					\
+})
+
+#define EMIT4(op)					\
+({							\
+	if (jit->prg + 4 <= jit->mid)			\
+		*(u32 *) jit->prg = op;			\
+	jit->prg += 4;					\
+})
+
+#define EMIT4_DISP(op, disp)				\
+({							\
+	unsigned int __disp = (disp) & 0xfff;		\
+	EMIT4(op | __disp);				\
+})
+
+#define EMIT4_IMM(op, imm)				\
+({							\
+	unsigned int __imm = (imm) & 0xffff;		\
+	EMIT4(op | __imm);				\
+})
+
+#define EMIT4_PCREL(op, pcrel)				\
+({							\
+	long __pcrel = ((pcrel) >> 1) & 0xffff;		\
+	EMIT4(op | __pcrel);				\
+})
+
+#define EMIT6(op1, op2)					\
+({							\
+	if (jit->prg + 6 <= jit->mid) {			\
+		*(u32 *) jit->prg = op1;		\
+		*(u16 *) (jit->prg + 4) = op2;		\
+	}						\
+	jit->prg += 6;					\
+})
+
+#define EMIT6_DISP(op1, op2, disp)			\
+({							\
+	unsigned int __disp = (disp) & 0xfff;		\
+	EMIT6(op1 | __disp, op2);			\
+})
+
+#define EMIT6_IMM(op, imm)				\
+({							\
+	unsigned int __imm = (imm);			\
+	EMIT6(op | (__imm >> 16), __imm & 0xffff);	\
+})
+
+#define EMIT_CONST(val)					\
+({							\
+	unsigned int ret;				\
+	ret = (unsigned int) (jit->lit - jit->base_ip);	\
+	jit->seen |= SEEN_LITERAL;			\
+	if (jit->lit + 4 <= jit->end)			\
+		*(u32 *) jit->lit = val;		\
+	jit->lit += 4;					\
+	ret;						\
+})
+
+#define EMIT_FN_CONST(bit, fn)				\
+({							\
+	unsigned int ret;				\
+	ret = (unsigned int) (jit->lit - jit->base_ip);	\
+	if (jit->seen & bit) {				\
+		jit->seen |= SEEN_LITERAL;		\
+		if (jit->lit + 8 <= jit->end)		\
+			*(void **) jit->lit = fn;	\
+		jit->lit += 8;				\
+	}						\
+	ret;						\
+})
+
+static void bpf_jit_prologue(struct bpf_jit *jit)
+{
+	/* Save registers and create stack frame if necessary */
+	if (jit->seen & SEEN_DATAREF) {
+		/* stmg %r8,%r15,88(%r15) */
+		EMIT6(0xeb8ff058, 0x0024);
+		/* lgr %r14,%r15 */
+		EMIT4(0xb90400ef);
+		/* ahi %r15,<offset> */
+		EMIT4_IMM(0xa7fa0000, (jit->seen & SEEN_MEM) ? -112 : -80);
+		/* stg %r14,152(%r15) */
+		EMIT6(0xe3e0f098, 0x0024);
+	} else if ((jit->seen & SEEN_XREG) && (jit->seen & SEEN_LITERAL))
+		/* stmg %r12,%r13,120(%r15) */
+		EMIT6(0xebcdf078, 0x0024);
+	else if (jit->seen & SEEN_XREG)
+		/* stg %r12,120(%r15) */
+		EMIT6(0xe3c0f078, 0x0024);
+	else if (jit->seen & SEEN_LITERAL)
+		/* stg %r13,128(%r15) */
+		EMIT6(0xe3d0f080, 0x0024);
+
+	/* Setup literal pool */
+	if (jit->seen & SEEN_LITERAL) {
+		/* basr %r13,0 */
+		EMIT2(0x0dd0);
+		jit->base_ip = jit->prg;
+	}
+	jit->off_load_word = EMIT_FN_CONST(SEEN_LOAD_WORD, sk_load_word);
+	jit->off_load_half = EMIT_FN_CONST(SEEN_LOAD_HALF, sk_load_half);
+	jit->off_load_byte = EMIT_FN_CONST(SEEN_LOAD_BYTE, sk_load_byte);
+	jit->off_load_bmsh = EMIT_FN_CONST(SEEN_LOAD_BMSH, sk_load_byte_msh);
+	jit->off_load_iword = EMIT_FN_CONST(SEEN_LOAD_IWORD, sk_load_word_ind);
+	jit->off_load_ihalf = EMIT_FN_CONST(SEEN_LOAD_IHALF, sk_load_half_ind);
+	jit->off_load_ibyte = EMIT_FN_CONST(SEEN_LOAD_IBYTE, sk_load_byte_ind);
+
+	/* Filter needs to access skb data */
+	if (jit->seen & SEEN_DATAREF) {
+		/* l %r11,<len>(%r2) */
+		EMIT4_DISP(0x58b02000, offsetof(struct sk_buff, len));
+		/* s %r11,<data_len>(%r2) */
+		EMIT4_DISP(0x5bb02000, offsetof(struct sk_buff, data_len));
+		/* lg %r10,<data>(%r2) */
+		EMIT6_DISP(0xe3a02000, 0x0004,
+			   offsetof(struct sk_buff, data));
+	}
+}
+
+static void bpf_jit_epilogue(struct bpf_jit *jit)
+{
+	/* Return 0 */
+	if (jit->seen & SEEN_RET0) {
+		jit->ret0_ip = jit->prg;
+		/* lghi %r2,0 */
+		EMIT4(0xa7290000);
+	}
+	jit->exit_ip = jit->prg;
+	/* Restore registers */
+	if (jit->seen & SEEN_DATAREF)
+		/* lmg %r8,%r15,<offset>(%r15) */
+		EMIT6_DISP(0xeb8ff000, 0x0004,
+			   (jit->seen & SEEN_MEM) ? 200 : 168);
+	else if ((jit->seen & SEEN_XREG) && (jit->seen & SEEN_LITERAL))
+		/* lmg %r12,%r13,120(%r15) */
+		EMIT6(0xebcdf078, 0x0004);
+	else if (jit->seen & SEEN_XREG)
+		/* lg %r12,120(%r15) */
+		EMIT6(0xe3c0f078, 0x0004);
+	else if (jit->seen & SEEN_LITERAL)
+		/* lg %r13,128(%r15) */
+		EMIT6(0xe3d0f080, 0x0004);
+	/* br %r14 */
+	EMIT2(0x07fe);
+}
+
+/*
+ * make sure we dont leak kernel information to user
+ */
+static void bpf_jit_noleaks(struct bpf_jit *jit, struct sock_filter *filter)
+{
+	/* Clear temporary memory if (seen & SEEN_MEM) */
+	if (jit->seen & SEEN_MEM)
+		/* xc 0(64,%r15),0(%r15) */
+		EMIT6(0xd73ff000, 0xf000);
+	/* Clear X if (seen & SEEN_XREG) */
+	if (jit->seen & SEEN_XREG)
+		/* lhi %r12,0 */
+		EMIT4(0xa7c80000);
+	/* Clear A if the first register does not set it. */
+	switch (filter[0].code) {
+	case BPF_S_LD_W_ABS:
+	case BPF_S_LD_H_ABS:
+	case BPF_S_LD_B_ABS:
+	case BPF_S_LD_W_LEN:
+	case BPF_S_LD_W_IND:
+	case BPF_S_LD_H_IND:
+	case BPF_S_LD_B_IND:
+	case BPF_S_LDX_B_MSH:
+	case BPF_S_LD_IMM:
+	case BPF_S_LD_MEM:
+	case BPF_S_MISC_TXA:
+	case BPF_S_ANC_PROTOCOL:
+	case BPF_S_ANC_PKTTYPE:
+	case BPF_S_ANC_IFINDEX:
+	case BPF_S_ANC_MARK:
+	case BPF_S_ANC_QUEUE:
+	case BPF_S_ANC_HATYPE:
+	case BPF_S_ANC_RXHASH:
+	case BPF_S_ANC_CPU:
+	case BPF_S_RET_K:
+		/* first instruction sets A register */
+		break;
+	default: /* A = 0 */
+		/* lhi %r5,0 */
+		EMIT4(0xa7580000);
+	}
+}
+
+static int bpf_jit_insn(struct bpf_jit *jit, struct sock_filter *filter,
+			unsigned int *addrs, int i, int last)
+{
+	unsigned int K;
+	int offset;
+	unsigned int mask;
+
+	K = filter->k;
+	switch (filter->code) {
+	case BPF_S_ALU_ADD_X: /* A += X */
+		jit->seen |= SEEN_XREG;
+		/* ar %r5,%r12 */
+		EMIT2(0x1a5c);
+		break;
+	case BPF_S_ALU_ADD_K: /* A += K */
+		if (!K)
+			break;
+		if (K <= 16383)
+			/* ahi %r5,<K> */
+			EMIT4_IMM(0xa75a0000, K);
+		else if (test_facility(21))
+			/* alfi %r5,<K> */
+			EMIT6_IMM(0xc25b0000, K);
+		else
+			/* a %r5,<d(K)>(%r13) */
+			EMIT4_DISP(0x5a50d000, EMIT_CONST(K));
+		break;
+	case BPF_S_ALU_SUB_X: /* A -= X */
+		jit->seen |= SEEN_XREG;
+		/* sr %r5,%r12 */
+		EMIT2(0x1b5c);
+		break;
+	case BPF_S_ALU_SUB_K: /* A -= K */
+		if (!K)
+			break;
+		if (K <= 16384)
+			/* ahi %r5,-K */
+			EMIT4_IMM(0xa75a0000, -K);
+		else if (test_facility(21))
+			/* alfi %r5,-K */
+			EMIT6_IMM(0xc25b0000, -K);
+		else
+			/* s %r5,<d(K)>(%r13) */
+			EMIT4_DISP(0x5b50d000, EMIT_CONST(K));
+		break;
+	case BPF_S_ALU_MUL_X: /* A *= X */
+		jit->seen |= SEEN_XREG;
+		/* msr %r5,%r12 */
+		EMIT4(0xb252005c);
+		break;
+	case BPF_S_ALU_MUL_K: /* A *= K */
+		if (K <= 16383)
+			/* mhi %r5,K */
+			EMIT4_IMM(0xa75c0000, K);
+		else if (test_facility(34))
+			/* msfi %r5,<K> */
+			EMIT6_IMM(0xc2510000, K);
+		else
+			/* ms %r5,<d(K)>(%r13) */
+			EMIT4_DISP(0x7150d000, EMIT_CONST(K));
+		break;
+	case BPF_S_ALU_DIV_X: /* A /= X */
+		jit->seen |= SEEN_XREG | SEEN_RET0;
+		/* ltr %r12,%r12 */
+		EMIT2(0x12cc);
+		/* jz <ret0> */
+		EMIT4_PCREL(0xa7840000, (jit->ret0_ip - jit->prg));
+		/* lhi %r4,0 */
+		EMIT4(0xa7480000);
+		/* dr %r4,%r12 */
+		EMIT2(0x1d4c);
+		break;
+	case BPF_S_ALU_DIV_K: /* A = reciprocal_divide(A, K) */
+		/* m %r4,<d(K)>(%r13) */
+		EMIT4_DISP(0x5c40d000, EMIT_CONST(K));
+		/* lr %r5,%r4 */
+		EMIT2(0x1854);
+		break;
+	case BPF_S_ALU_AND_X: /* A &= X */
+		jit->seen |= SEEN_XREG;
+		/* nr %r5,%r12 */
+		EMIT2(0x145c);
+		break;
+	case BPF_S_ALU_AND_K: /* A &= K */
+		if (test_facility(21))
+			/* nilf %r5,<K> */
+			EMIT6_IMM(0xc05b0000, K);
+		else
+			/* n %r5,<d(K)>(%r13) */
+			EMIT4_DISP(0x5450d000, EMIT_CONST(K));
+		break;
+	case BPF_S_ALU_OR_X: /* A |= X */
+		jit->seen |= SEEN_XREG;
+		/* or %r5,%r12 */
+		EMIT2(0x165c);
+		break;
+	case BPF_S_ALU_OR_K: /* A |= K */
+		if (test_facility(21))
+			/* oilf %r5,<K> */
+			EMIT6_IMM(0xc05d0000, K);
+		else
+			/* o %r5,<d(K)>(%r13) */
+			EMIT4_DISP(0x5650d000, EMIT_CONST(K));
+		break;
+	case BPF_S_ALU_LSH_X: /* A <<= X; */
+		jit->seen |= SEEN_XREG;
+		/* sll %r5,0(%r12) */
+		EMIT4(0x8950c000);
+		break;
+	case BPF_S_ALU_LSH_K: /* A <<= K */
+		if (K == 0)
+			break;
+		/* sll %r5,K */
+		EMIT4_DISP(0x89500000, K);
+		break;
+	case BPF_S_ALU_RSH_X: /* A >>= X; */
+		jit->seen |= SEEN_XREG;
+		/* srl %r5,0(%r12) */
+		EMIT4(0x8850c000);
+		break;
+	case BPF_S_ALU_RSH_K: /* A >>= K; */
+		if (K == 0)
+			break;
+		/* srl %r5,K */
+		EMIT4_DISP(0x88500000, K);
+		break;
+	case BPF_S_ALU_NEG: /* A = -A */
+		/* lnr %r5,%r5 */
+		EMIT2(0x1155);
+		break;
+	case BPF_S_JMP_JA: /* ip += K */
+		offset = addrs[i + K] + jit->start - jit->prg;
+		EMIT4_PCREL(0xa7f40000, offset);
+		break;
+	case BPF_S_JMP_JGT_K: /* ip += (A > K) ? jt : jf */
+		mask = 0x200000; /* jh */
+		goto kbranch;
+	case BPF_S_JMP_JGE_K: /* ip += (A >= K) ? jt : jf */
+		mask = 0xa00000; /* jhe */
+		goto kbranch;
+	case BPF_S_JMP_JEQ_K: /* ip += (A == K) ? jt : jf */
+		mask = 0x800000; /* je */
+kbranch:	/* Emit compare if the branch targets are different */
+		if (filter->jt != filter->jf) {
+			if (K <= 16383)
+				/* chi %r5,<K> */
+				EMIT4_IMM(0xa75e0000, K);
+			else if (test_facility(21))
+				/* clfi %r5,<K> */
+				EMIT6_IMM(0xc25f0000, K);
+			else
+				/* c %r5,<d(K)>(%r13) */
+				EMIT4_DISP(0x5950d000, EMIT_CONST(K));
+		}
+branch:		if (filter->jt == filter->jf) {
+			if (filter->jt == 0)
+				break;
+			/* j <jt> */
+			offset = addrs[i + filter->jt] + jit->start - jit->prg;
+			EMIT4_PCREL(0xa7f40000, offset);
+			break;
+		}
+		if (filter->jt != 0) {
+			/* brc	<mask>,<jt> */
+			offset = addrs[i + filter->jt] + jit->start - jit->prg;
+			EMIT4_PCREL(0xa7040000 | mask, offset);
+		}
+		if (filter->jf != 0) {
+			/* brc	<mask^15>,<jf> */
+			offset = addrs[i + filter->jf] + jit->start - jit->prg;
+			EMIT4_PCREL(0xa7040000 | (mask ^ 0xf00000), offset);
+		}
+		break;
+	case BPF_S_JMP_JSET_K: /* ip += (A & K) ? jt : jf */
+		mask = 0x700000; /* jnz */
+		/* Emit test if the branch targets are different */
+		if (filter->jt != filter->jf) {
+			if (K > 65535) {
+				/* lr %r4,%r5 */
+				EMIT2(0x1845);
+				/* n %r4,<d(K)>(%r13) */
+				EMIT4_DISP(0x5440d000, EMIT_CONST(K));
+			} else
+				/* tmll %r5,K */
+				EMIT4_IMM(0xa7510000, K);
+		}
+		goto branch;
+	case BPF_S_JMP_JGT_X: /* ip += (A > X) ? jt : jf */
+		mask = 0x200000; /* jh */
+		goto xbranch;
+	case BPF_S_JMP_JGE_X: /* ip += (A >= X) ? jt : jf */
+		mask = 0xa00000; /* jhe */
+		goto xbranch;
+	case BPF_S_JMP_JEQ_X: /* ip += (A == X) ? jt : jf */
+		mask = 0x800000; /* je */
+xbranch:	/* Emit compare if the branch targets are different */
+		if (filter->jt != filter->jf) {
+			jit->seen |= SEEN_XREG;
+			/* cr %r5,%r12 */
+			EMIT2(0x195c);
+		}
+		goto branch;
+	case BPF_S_JMP_JSET_X: /* ip += (A & X) ? jt : jf */
+		mask = 0x700000; /* jnz */
+		/* Emit test if the branch targets are different */
+		if (filter->jt != filter->jf) {
+			jit->seen |= SEEN_XREG;
+			/* lr %r4,%r5 */
+			EMIT2(0x1845);
+			/* nr %r4,%r12 */
+			EMIT2(0x144c);
+		}
+		goto branch;
+	case BPF_S_LD_W_ABS: /* A = *(u32 *) (skb->data+K) */
+		jit->seen |= SEEN_DATAREF | SEEN_RET0 | SEEN_LOAD_WORD;
+		offset = jit->off_load_word;
+		goto load_abs;
+	case BPF_S_LD_H_ABS: /* A = *(u16 *) (skb->data+K) */
+		jit->seen |= SEEN_DATAREF | SEEN_RET0 | SEEN_LOAD_HALF;
+		offset = jit->off_load_half;
+		goto load_abs;
+	case BPF_S_LD_B_ABS: /* A = *(u8 *) (skb->data+K) */
+		jit->seen |= SEEN_DATAREF | SEEN_RET0 | SEEN_LOAD_BYTE;
+		offset = jit->off_load_byte;
+load_abs:	if ((int) K < 0)
+			goto out;
+call_fn:	/* lg %r1,<d(function)>(%r13) */
+		EMIT6_DISP(0xe310d000, 0x0004, offset);
+		/* l %r3,<d(K)>(%r13) */
+		EMIT4_DISP(0x5830d000, EMIT_CONST(K));
+		/* basr %r8,%r1 */
+		EMIT2(0x0d81);
+		/* jnz <ret0> */
+		EMIT4_PCREL(0xa7740000, (jit->ret0_ip - jit->prg));
+		break;
+	case BPF_S_LD_W_IND: /* A = *(u32 *) (skb->data+K+X) */
+		jit->seen |= SEEN_DATAREF | SEEN_RET0 | SEEN_LOAD_IWORD;
+		offset = jit->off_load_iword;
+		goto call_fn;
+	case BPF_S_LD_H_IND: /* A = *(u16 *) (skb->data+K+X) */
+		jit->seen |= SEEN_DATAREF | SEEN_RET0 | SEEN_LOAD_IHALF;
+		offset = jit->off_load_ihalf;
+		goto call_fn;
+	case BPF_S_LD_B_IND: /* A = *(u8 *) (skb->data+K+X) */
+		jit->seen |= SEEN_DATAREF | SEEN_RET0 | SEEN_LOAD_IBYTE;
+		offset = jit->off_load_ibyte;
+		goto call_fn;
+	case BPF_S_LDX_B_MSH:
+		/* X = (*(u8 *)(skb->data+K) & 0xf) << 2 */
+		jit->seen |= SEEN_RET0;
+		if ((int) K < 0) {
+			/* j <ret0> */
+			EMIT4_PCREL(0xa7f40000, (jit->ret0_ip - jit->prg));
+			break;
+		}
+		jit->seen |= SEEN_DATAREF | SEEN_LOAD_BMSH;
+		offset = jit->off_load_bmsh;
+		goto call_fn;
+	case BPF_S_LD_W_LEN: /*	A = skb->len; */
+		BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, len) != 4);
+		/* l %r5,<d(len)>(%r2) */
+		EMIT4_DISP(0x58502000, offsetof(struct sk_buff, len));
+		break;
+	case BPF_S_LDX_W_LEN: /* X = skb->len; */
+		jit->seen |= SEEN_XREG;
+		/* l %r12,<d(len)>(%r2) */
+		EMIT4_DISP(0x58c02000, offsetof(struct sk_buff, len));
+		break;
+	case BPF_S_LD_IMM: /* A = K */
+		if (K <= 16383)
+			/* lhi %r5,K */
+			EMIT4_IMM(0xa7580000, K);
+		else if (test_facility(21))
+			/* llilf %r5,<K> */
+			EMIT6_IMM(0xc05f0000, K);
+		else
+			/* l %r5,<d(K)>(%r13) */
+			EMIT4_DISP(0x5850d000, EMIT_CONST(K));
+		break;
+	case BPF_S_LDX_IMM: /* X = K */
+		jit->seen |= SEEN_XREG;
+		if (K <= 16383)
+			/* lhi %r12,<K> */
+			EMIT4_IMM(0xa7c80000, K);
+		else if (test_facility(21))
+			/* llilf %r12,<K> */
+			EMIT6_IMM(0xc0cf0000, K);
+		else
+			/* l %r12,<d(K)>(%r13) */
+			EMIT4_DISP(0x58c0d000, EMIT_CONST(K));
+		break;
+	case BPF_S_LD_MEM: /* A = mem[K] */
+		jit->seen |= SEEN_MEM;
+		/* l %r5,<K>(%r15) */
+		EMIT4_DISP(0x5850f000,
+			   (jit->seen & SEEN_DATAREF) ? 160 + K*4 : K*4);
+		break;
+	case BPF_S_LDX_MEM: /* X = mem[K] */
+		jit->seen |= SEEN_XREG | SEEN_MEM;
+		/* l %r12,<K>(%r15) */
+		EMIT4_DISP(0x58c0f000,
+			   (jit->seen & SEEN_DATAREF) ? 160 + K*4 : K*4);
+		break;
+	case BPF_S_MISC_TAX: /* X = A */
+		jit->seen |= SEEN_XREG;
+		/* lr %r12,%r5 */
+		EMIT2(0x18c5);
+		break;
+	case BPF_S_MISC_TXA: /* A = X */
+		jit->seen |= SEEN_XREG;
+		/* lr %r5,%r12 */
+		EMIT2(0x185c);
+		break;
+	case BPF_S_RET_K:
+		if (K == 0) {
+			jit->seen |= SEEN_RET0;
+			if (last)
+				break;
+			/* j <ret0> */
+			EMIT4_PCREL(0xa7f40000, jit->ret0_ip - jit->prg);
+		} else {
+			if (K <= 16383)
+				/* lghi %r2,K */
+				EMIT4_IMM(0xa7290000, K);
+			else
+				/* llgf %r2,<K>(%r13) */
+				EMIT6_DISP(0xe320d000, 0x0016, EMIT_CONST(K));
+			/* j <exit> */
+			if (last && !(jit->seen & SEEN_RET0))
+				break;
+			EMIT4_PCREL(0xa7f40000, jit->exit_ip - jit->prg);
+		}
+		break;
+	case BPF_S_RET_A:
+		/* llgfr %r2,%r5 */
+		EMIT4(0xb9160025);
+		/* j <exit> */
+		EMIT4_PCREL(0xa7f40000, jit->exit_ip - jit->prg);
+		break;
+	case BPF_S_ST: /* mem[K] = A */
+		jit->seen |= SEEN_MEM;
+		/* st %r5,<K>(%r15) */
+		EMIT4_DISP(0x5050f000,
+			   (jit->seen & SEEN_DATAREF) ? 160 + K*4 : K*4);
+		break;
+	case BPF_S_STX: /* mem[K] = X : mov %ebx,off8(%rbp) */
+		jit->seen |= SEEN_XREG | SEEN_MEM;
+		/* st %r12,<K>(%r15) */
+		EMIT4_DISP(0x50c0f000,
+			   (jit->seen & SEEN_DATAREF) ? 160 + K*4 : K*4);
+		break;
+	case BPF_S_ANC_PROTOCOL: /* A = ntohs(skb->protocol); */
+		BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, protocol) != 2);
+		/* lhi %r5,0 */
+		EMIT4(0xa7580000);
+		/* icm	%r5,3,<d(protocol)>(%r2) */
+		EMIT4_DISP(0xbf532000, offsetof(struct sk_buff, protocol));
+		break;
+	case BPF_S_ANC_IFINDEX:	/* if (!skb->dev) return 0;
+				 * A = skb->dev->ifindex */
+		BUILD_BUG_ON(FIELD_SIZEOF(struct net_device, ifindex) != 4);
+		jit->seen |= SEEN_RET0;
+		/* lg %r1,<d(dev)>(%r2) */
+		EMIT6_DISP(0xe3102000, 0x0004, offsetof(struct sk_buff, dev));
+		/* ltgr %r1,%r1 */
+		EMIT4(0xb9020011);
+		/* jz <ret0> */
+		EMIT4_PCREL(0xa7840000, jit->ret0_ip - jit->prg);
+		/* l %r5,<d(ifindex)>(%r1) */
+		EMIT4_DISP(0x58501000, offsetof(struct net_device, ifindex));
+		break;
+	case BPF_S_ANC_MARK: /* A = skb->mark */
+		BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, mark) != 4);
+		/* l %r5,<d(mark)>(%r2) */
+		EMIT4_DISP(0x58502000, offsetof(struct sk_buff, mark));
+		break;
+	case BPF_S_ANC_QUEUE: /* A = skb->queue_mapping */
+		BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, queue_mapping) != 2);
+		/* lhi %r5,0 */
+		EMIT4(0xa7580000);
+		/* icm	%r5,3,<d(queue_mapping)>(%r2) */
+		EMIT4_DISP(0xbf532000, offsetof(struct sk_buff, queue_mapping));
+		break;
+	case BPF_S_ANC_HATYPE:	/* if (!skb->dev) return 0;
+				 * A = skb->dev->type */
+		BUILD_BUG_ON(FIELD_SIZEOF(struct net_device, type) != 2);
+		jit->seen |= SEEN_RET0;
+		/* lg %r1,<d(dev)>(%r2) */
+		EMIT6_DISP(0xe3102000, 0x0004, offsetof(struct sk_buff, dev));
+		/* ltgr %r1,%r1 */
+		EMIT4(0xb9020011);
+		/* jz <ret0> */
+		EMIT4_PCREL(0xa7840000, jit->ret0_ip - jit->prg);
+		/* lhi %r5,0 */
+		EMIT4(0xa7580000);
+		/* icm	%r5,3,<d(type)>(%r1) */
+		EMIT4_DISP(0xbf531000, offsetof(struct net_device, type));
+		break;
+	case BPF_S_ANC_RXHASH: /* A = skb->rxhash */
+		BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, rxhash) != 4);
+		/* l %r5,<d(rxhash)>(%r2) */
+		EMIT4_DISP(0x58502000, offsetof(struct sk_buff, rxhash));
+		break;
+	case BPF_S_ANC_CPU: /* A = smp_processor_id() */
+#ifdef CONFIG_SMP
+		/* l %r5,<d(cpu_nr)> */
+		EMIT4_DISP(0x58500000, offsetof(struct _lowcore, cpu_nr));
+#else
+		/* lhi %r5,0 */
+		EMIT4(0xa7580000);
+#endif
+		break;
+	default: /* too complex, give up */
+		goto out;
+	}
+	addrs[i] = jit->prg - jit->start;
+	return 0;
+out:
+	return -1;
+}
+
+void bpf_jit_compile(struct sk_filter *fp)
+{
+	unsigned long size, prg_len, lit_len;
+	struct bpf_jit jit, cjit;
+	unsigned int *addrs;
+	int pass, i;
+
+	if (!bpf_jit_enable)
+		return;
+	addrs = kmalloc(fp->len * sizeof(*addrs), GFP_KERNEL);
+	if (addrs == NULL)
+		return;
+	memset(addrs, 0, fp->len * sizeof(*addrs));
+	memset(&jit, 0, sizeof(cjit));
+	memset(&cjit, 0, sizeof(cjit));
+
+	for (pass = 0; pass < 10; pass++) {
+		jit.prg = jit.start;
+		jit.lit = jit.mid;
+
+		bpf_jit_prologue(&jit);
+		bpf_jit_noleaks(&jit, fp->insns);
+		for (i = 0; i < fp->len; i++) {
+			if (bpf_jit_insn(&jit, fp->insns + i, addrs, i,
+					 i == fp->len - 1))
+				goto out;
+		}
+		bpf_jit_epilogue(&jit);
+		if (jit.start) {
+			WARN_ON(jit.prg > cjit.prg || jit.lit > cjit.lit);
+			if (memcmp(&jit, &cjit, sizeof(jit)) == 0)
+				break;
+		} else if (jit.prg == cjit.prg && jit.lit == cjit.lit) {
+			prg_len = jit.prg - jit.start;
+			lit_len = jit.lit - jit.mid;
+			size = max_t(unsigned long, prg_len + lit_len,
+				     sizeof(struct work_struct));
+			if (size >= BPF_SIZE_MAX)
+				goto out;
+			jit.start = module_alloc(size);
+			if (!jit.start)
+				goto out;
+			jit.prg = jit.mid = jit.start + prg_len;
+			jit.lit = jit.end = jit.start + prg_len + lit_len;
+			jit.base_ip += (unsigned long) jit.start;
+			jit.exit_ip += (unsigned long) jit.start;
+			jit.ret0_ip += (unsigned long) jit.start;
+		}
+		cjit = jit;
+	}
+	if (bpf_jit_enable > 1) {
+		pr_err("flen=%d proglen=%lu pass=%d image=%p\n",
+		       fp->len, jit.end - jit.start, pass, jit.start);
+		if (jit.start) {
+			printk(KERN_ERR "JIT code:\n");
+			print_fn_code(jit.start, jit.mid - jit.start);
+			print_hex_dump(KERN_ERR, "JIT literals:\n",
+				       DUMP_PREFIX_ADDRESS, 16, 1,
+				       jit.mid, jit.end - jit.mid, false);
+		}
+	}
+	if (jit.start)
+		fp->bpf_func = (void *) jit.start;
+out:
+	kfree(addrs);
+}
+
+static void jit_free_defer(struct work_struct *arg)
+{
+	module_free(NULL, arg);
+}
+
+/* run from softirq, we must use a work_struct to call
+ * module_free() from process context
+ */
+void bpf_jit_free(struct sk_filter *fp)
+{
+	struct work_struct *work;
+
+	if (fp->bpf_func == sk_run_filter)
+		return;
+	work = (struct work_struct *)fp->bpf_func;
+	INIT_WORK(work, jit_free_defer);
+	schedule_work(work);
+}
diff --git a/arch/score/Kconfig b/arch/score/Kconfig
index ba0f412..fbf9db5 100644
--- a/arch/score/Kconfig
+++ b/arch/score/Kconfig
@@ -6,10 +6,13 @@ config SCORE
        select GENERIC_IRQ_SHOW
        select GENERIC_IOMAP
        select HAVE_MEMBLOCK
+       select GENERIC_ATOMIC64
        select HAVE_MEMBLOCK_NODE_MAP
        select ARCH_DISCARD_MEMBLOCK
        select GENERIC_CPU_DEVICES
        select GENERIC_CLOCKEVENTS
+       select HAVE_MOD_ARCH_SPECIFIC
+       select MODULES_USE_ELF_REL
 
 choice
 	prompt "System type"
diff --git a/arch/score/include/asm/elf.h b/arch/score/include/asm/elf.h
index f478ce9..5d566c7 100644
--- a/arch/score/include/asm/elf.h
+++ b/arch/score/include/asm/elf.h
@@ -54,7 +54,7 @@ typedef elf_fpreg_t	elf_fpregset_t;
 
 #define SET_PERSONALITY(ex)					\
 do {								\
-	set_personality(PER_LINUX);				\
+	set_personality(PER_LINUX | (current->personality & (~PER_MASK))); \
 } while (0)
 
 struct task_struct;
diff --git a/arch/score/include/asm/module.h b/arch/score/include/asm/module.h
index f0b5dc0..abf395b 100644
--- a/arch/score/include/asm/module.h
+++ b/arch/score/include/asm/module.h
@@ -3,6 +3,7 @@
 
 #include <linux/list.h>
 #include <asm/uaccess.h>
+#include <asm-generic/module.h>
 
 struct mod_arch_specific {
 	/* Data Bus Error exception tables */
@@ -13,11 +14,6 @@ struct mod_arch_specific {
 
 typedef uint8_t Elf64_Byte;		/* Type for a 8-bit quantity. */
 
-#define Elf_Shdr	Elf32_Shdr
-#define Elf_Sym		Elf32_Sym
-#define Elf_Ehdr	Elf32_Ehdr
-#define Elf_Addr	Elf32_Addr
-
 /* Given an address, look for it in the exception tables. */
 #ifdef CONFIG_MODULES
 const struct exception_table_entry *search_module_dbetables(unsigned long addr);
diff --git a/arch/score/include/asm/thread_info.h b/arch/score/include/asm/thread_info.h
index a18006e9..1425cc0 100644
--- a/arch/score/include/asm/thread_info.h
+++ b/arch/score/include/asm/thread_info.h
@@ -86,16 +86,12 @@ register struct thread_info *__current_thread_info __asm__("r28");
 #define TIF_NEED_RESCHED	2	/* rescheduling necessary */
 #define TIF_NOTIFY_RESUME	5	/* callback before returning to user */
 #define TIF_RESTORE_SIGMASK	9	/* restore signal mask in do_signal() */
-#define TIF_POLLING_NRFLAG	17	/* true if poll_idle() is polling
-						 TIF_NEED_RESCHED */
 #define TIF_MEMDIE		18	/* is terminating due to OOM killer */
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
 #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
-#define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
-#define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
 
 #define _TIF_WORK_MASK		(0x0000ffff)
 
diff --git a/arch/score/kernel/module.c b/arch/score/kernel/module.c
index 469e3b6..1378d99 100644
--- a/arch/score/kernel/module.c
+++ b/arch/score/kernel/module.c
@@ -125,16 +125,6 @@ int apply_relocate(Elf_Shdr *sechdrs, const char *strtab,
 	return 0;
 }
 
-int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
-		unsigned int symindex, unsigned int relsec,
-		struct module *me)
-{
-	/* Non-standard return value... most other arch's return -ENOEXEC
-	 * for an unsupported relocation variant
-	 */
-	return 0;
-}
-
 /* Given an address, look for it in the module exception tables. */
 const struct exception_table_entry *search_module_dbetables(unsigned long addr)
 {
diff --git a/arch/score/kernel/process.c b/arch/score/kernel/process.c
index 2707023..637970c 100644
--- a/arch/score/kernel/process.c
+++ b/arch/score/kernel/process.c
@@ -27,6 +27,7 @@
 #include <linux/reboot.h>
 #include <linux/elfcore.h>
 #include <linux/pm.h>
+#include <linux/rcupdate.h>
 
 void (*pm_power_off)(void);
 EXPORT_SYMBOL(pm_power_off);
@@ -50,9 +51,10 @@ void __noreturn cpu_idle(void)
 {
 	/* endless idle loop with no priority at all */
 	while (1) {
+		rcu_idle_enter();
 		while (!need_resched())
 			barrier();
-
+		rcu_idle_exit();
 		schedule_preempt_disabled();
 	}
 }
diff --git a/arch/score/kernel/signal.c b/arch/score/kernel/signal.c
index e382c52..c268bbf 100644
--- a/arch/score/kernel/signal.c
+++ b/arch/score/kernel/signal.c
@@ -174,6 +174,7 @@ score_rt_sigreturn(struct pt_regs *regs)
 	/* It is more difficult to avoid calling this function than to
 	   call it and ignore errors.  */
 	do_sigaltstack((stack_t __user *)&st, NULL, regs->regs[0]);
+	regs->is_syscall = 0;
 
 	__asm__ __volatile__(
 		"mv\tr0, %0\n\t"
diff --git a/arch/score/kernel/sys_score.c b/arch/score/kernel/sys_score.c
index e478bf9..21e8679 100644
--- a/arch/score/kernel/sys_score.c
+++ b/arch/score/kernel/sys_score.c
@@ -112,6 +112,7 @@ score_execve(struct pt_regs *regs)
  * Do a system call from kernel instead of calling sys_execve so we
  * end up with proper pt_regs.
  */
+asmlinkage
 int kernel_execve(const char *filename,
 		  const char *const argv[],
 		  const char *const envp[])
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index 36f5141..656329a 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -35,6 +35,8 @@ config SUPERH
 	select GENERIC_CMOS_UPDATE if SH_SH03 || SH_DREAMCAST
 	select GENERIC_STRNCPY_FROM_USER
 	select GENERIC_STRNLEN_USER
+	select HAVE_MOD_ARCH_SPECIFIC if DWARF_UNWINDER
+	select MODULES_USE_ELF_RELA
 	help
 	  The SuperH is a RISC processor targeted for use in embedded systems
 	  and consumer electronics; it was also used in the Sega Dreamcast
diff --git a/arch/sh/drivers/pci/pci.c b/arch/sh/drivers/pci/pci.c
index 40db2d0..a7e078f 100644
--- a/arch/sh/drivers/pci/pci.c
+++ b/arch/sh/drivers/pci/pci.c
@@ -192,11 +192,6 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
 	return pci_enable_resources(dev, mask);
 }
 
-void __init pcibios_update_irq(struct pci_dev *dev, int irq)
-{
-	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
-}
-
 static void __init
 pcibios_bus_report_status_early(struct pci_channel *hose,
 				int top_bus, int current_bus,
diff --git a/arch/sh/drivers/push-switch.c b/arch/sh/drivers/push-switch.c
index 637b79b..5bfb341 100644
--- a/arch/sh/drivers/push-switch.c
+++ b/arch/sh/drivers/push-switch.c
@@ -107,7 +107,7 @@ static int switch_drv_remove(struct platform_device *pdev)
 		device_remove_file(&pdev->dev, &dev_attr_switch);
 
 	platform_set_drvdata(pdev, NULL);
-	flush_work_sync(&psw->work);
+	flush_work(&psw->work);
 	del_timer_sync(&psw->debounce);
 	free_irq(irq, pdev);
 
diff --git a/arch/sh/include/asm/Kbuild b/arch/sh/include/asm/Kbuild
index 7b673dd..86eadce 100644
--- a/arch/sh/include/asm/Kbuild
+++ b/arch/sh/include/asm/Kbuild
@@ -7,6 +7,7 @@ generic-y += delay.h
 generic-y += div64.h
 generic-y += emergency-restart.h
 generic-y += errno.h
+generic-y += exec.h
 generic-y += fcntl.h
 generic-y += ioctl.h
 generic-y += ipcbuf.h
diff --git a/arch/sh/include/asm/elf.h b/arch/sh/include/asm/elf.h
index f38112b..37924af 100644
--- a/arch/sh/include/asm/elf.h
+++ b/arch/sh/include/asm/elf.h
@@ -183,7 +183,8 @@ do {									\
 } while (0)
 #endif
 
-#define SET_PERSONALITY(ex) set_personality(PER_LINUX_32BIT)
+#define SET_PERSONALITY(ex) \
+	set_personality(PER_LINUX_32BIT | (current->personality & (~PER_MASK)))
 
 #ifdef CONFIG_VSYSCALL
 /* vDSO has arch_setup_additional_pages */
diff --git a/arch/sh/include/asm/exec.h b/arch/sh/include/asm/exec.h
deleted file mode 100644
index 69486a9..0000000
--- a/arch/sh/include/asm/exec.h
+++ /dev/null
@@ -1,10 +0,0 @@
-/*
- * Copyright (C) 1999, 2000  Niibe Yutaka  &  Kaz Kojima
- * Copyright (C) 2002 Paul Mundt
- */
-#ifndef __ASM_SH_EXEC_H
-#define __ASM_SH_EXEC_H
-
-#define arch_align_stack(x) (x)
-
-#endif /* __ASM_SH_EXEC_H */
diff --git a/arch/sh/include/asm/hugetlb.h b/arch/sh/include/asm/hugetlb.h
index 967068f..b3808c7 100644
--- a/arch/sh/include/asm/hugetlb.h
+++ b/arch/sh/include/asm/hugetlb.h
@@ -1,6 +1,7 @@
 #ifndef _ASM_SH_HUGETLB_H
 #define _ASM_SH_HUGETLB_H
 
+#include <asm/cacheflush.h>
 #include <asm/page.h>
 
 
@@ -89,4 +90,9 @@ static inline void arch_release_hugepage(struct page *page)
 {
 }
 
+static inline void arch_clear_hugepage_flags(struct page *page)
+{
+	clear_bit(PG_dcache_clean, &page->flags);
+}
+
 #endif /* _ASM_SH_HUGETLB_H */
diff --git a/arch/sh/include/asm/io.h b/arch/sh/include/asm/io.h
index 0cf60a6..73a23f4 100644
--- a/arch/sh/include/asm/io.h
+++ b/arch/sh/include/asm/io.h
@@ -134,7 +134,7 @@ __BUILD_MEMORY_STRING(__raw_, q, u64)
  * load/store instructions. sh_io_port_base is the virtual address to
  * which all ports are being mapped.
  */
-extern const unsigned long sh_io_port_base;
+extern unsigned long sh_io_port_base;
 
 static inline void __set_io_port_base(unsigned long pbase)
 {
diff --git a/arch/sh/include/asm/module.h b/arch/sh/include/asm/module.h
index b7927de..81300d8b 100644
--- a/arch/sh/include/asm/module.h
+++ b/arch/sh/include/asm/module.h
@@ -1,21 +1,13 @@
 #ifndef _ASM_SH_MODULE_H
 #define _ASM_SH_MODULE_H
 
-struct mod_arch_specific {
+#include <asm-generic/module.h>
+
 #ifdef CONFIG_DWARF_UNWINDER
+struct mod_arch_specific {
 	struct list_head fde_list;
 	struct list_head cie_list;
-#endif
 };
-
-#ifdef CONFIG_64BIT
-#define Elf_Shdr Elf64_Shdr
-#define Elf_Sym Elf64_Sym
-#define Elf_Ehdr Elf64_Ehdr
-#else
-#define Elf_Shdr Elf32_Shdr
-#define Elf_Sym Elf32_Sym
-#define Elf_Ehdr Elf32_Ehdr
 #endif
 
 #ifdef CONFIG_CPU_LITTLE_ENDIAN
diff --git a/arch/sh/include/asm/thread_info.h b/arch/sh/include/asm/thread_info.h
index bc13b57..7d5ac4e 100644
--- a/arch/sh/include/asm/thread_info.h
+++ b/arch/sh/include/asm/thread_info.h
@@ -206,6 +206,9 @@ static inline bool test_and_clear_restore_sigmask(void)
 	ti->status &= ~TS_RESTORE_SIGMASK;
 	return true;
 }
+
+#define tsk_is_polling(t) test_tsk_thread_flag(t, TIF_POLLING_NRFLAG)
+
 #endif	/* !__ASSEMBLY__ */
 
 #endif /* __KERNEL__ */
diff --git a/arch/sh/kernel/ioport.c b/arch/sh/kernel/ioport.c
index e3ad610..cca14ba 100644
--- a/arch/sh/kernel/ioport.c
+++ b/arch/sh/kernel/ioport.c
@@ -11,7 +11,7 @@
 #include <linux/module.h>
 #include <linux/io.h>
 
-const unsigned long sh_io_port_base __read_mostly = -1;
+unsigned long sh_io_port_base __read_mostly = -1;
 EXPORT_SYMBOL(sh_io_port_base);
 
 void __iomem *__ioport_map(unsigned long addr, unsigned int size)
diff --git a/arch/sh/kernel/signal_32.c b/arch/sh/kernel/signal_32.c
index d6b7b61..2f1f653 100644
--- a/arch/sh/kernel/signal_32.c
+++ b/arch/sh/kernel/signal_32.c
@@ -22,7 +22,6 @@
 #include <linux/elf.h>
 #include <linux/personality.h>
 #include <linux/binfmts.h>
-#include <linux/freezer.h>
 #include <linux/io.h>
 #include <linux/tracehook.h>
 #include <asm/ucontext.h>
diff --git a/arch/sh/kernel/signal_64.c b/arch/sh/kernel/signal_64.c
index 6b5b3df..2385381 100644
--- a/arch/sh/kernel/signal_64.c
+++ b/arch/sh/kernel/signal_64.c
@@ -18,7 +18,6 @@
 #include <linux/errno.h>
 #include <linux/wait.h>
 #include <linux/personality.h>
-#include <linux/freezer.h>
 #include <linux/ptrace.h>
 #include <linux/unistd.h>
 #include <linux/stddef.h>
diff --git a/arch/sh/mm/fault.c b/arch/sh/mm/fault.c
index 3bdc1ad..cbbdcad 100644
--- a/arch/sh/mm/fault.c
+++ b/arch/sh/mm/fault.c
@@ -504,6 +504,7 @@ good_area:
 		}
 		if (fault & VM_FAULT_RETRY) {
 			flags &= ~FAULT_FLAG_ALLOW_RETRY;
+			flags |= FAULT_FLAG_TRIED;
 
 			/*
 			 * No need to up_read(&mm->mmap_sem) as we would
diff --git a/arch/sparc/Kbuild b/arch/sparc/Kbuild
index 5cd0116..675afa2 100644
--- a/arch/sparc/Kbuild
+++ b/arch/sparc/Kbuild
@@ -6,3 +6,4 @@ obj-y += kernel/
 obj-y += mm/
 obj-y += math-emu/
 obj-y += net/
+obj-y += crypto/
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index 67f1f6f..a244e70 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -37,6 +37,7 @@ config SPARC
 	select GENERIC_CLOCKEVENTS
 	select GENERIC_STRNCPY_FROM_USER
 	select GENERIC_STRNLEN_USER
+	select MODULES_USE_ELF_RELA
 
 config SPARC32
 	def_bool !64BIT
diff --git a/arch/sparc/crypto/Makefile b/arch/sparc/crypto/Makefile
new file mode 100644
index 0000000..6ae1ad5
--- /dev/null
+++ b/arch/sparc/crypto/Makefile
@@ -0,0 +1,25 @@
+#
+# Arch-specific CryptoAPI modules.
+#
+
+obj-$(CONFIG_CRYPTO_SHA1_SPARC64) += sha1-sparc64.o
+obj-$(CONFIG_CRYPTO_SHA256_SPARC64) += sha256-sparc64.o
+obj-$(CONFIG_CRYPTO_SHA512_SPARC64) += sha512-sparc64.o
+obj-$(CONFIG_CRYPTO_MD5_SPARC64) += md5-sparc64.o
+
+obj-$(CONFIG_CRYPTO_AES_SPARC64) += aes-sparc64.o
+obj-$(CONFIG_CRYPTO_DES_SPARC64) += des-sparc64.o
+obj-$(CONFIG_CRYPTO_DES_SPARC64) += camellia-sparc64.o
+
+obj-$(CONFIG_CRYPTO_CRC32C_SPARC64) += crc32c-sparc64.o
+
+sha1-sparc64-y := sha1_asm.o sha1_glue.o crop_devid.o
+sha256-sparc64-y := sha256_asm.o sha256_glue.o crop_devid.o
+sha512-sparc64-y := sha512_asm.o sha512_glue.o crop_devid.o
+md5-sparc64-y := md5_asm.o md5_glue.o crop_devid.o
+
+aes-sparc64-y := aes_asm.o aes_glue.o crop_devid.o
+des-sparc64-y := des_asm.o des_glue.o crop_devid.o
+camellia-sparc64-y := camellia_asm.o camellia_glue.o crop_devid.o
+
+crc32c-sparc64-y := crc32c_asm.o crc32c_glue.o crop_devid.o
diff --git a/arch/sparc/crypto/aes_asm.S b/arch/sparc/crypto/aes_asm.S
new file mode 100644
index 0000000..23f6cbb
--- /dev/null
+++ b/arch/sparc/crypto/aes_asm.S
@@ -0,0 +1,1535 @@
+#include <linux/linkage.h>
+#include <asm/visasm.h>
+
+#include "opcodes.h"
+
+#define ENCRYPT_TWO_ROUNDS(KEY_BASE, I0, I1, T0, T1) \
+	AES_EROUND01(KEY_BASE +  0, I0, I1, T0) \
+	AES_EROUND23(KEY_BASE +  2, I0, I1, T1) \
+	AES_EROUND01(KEY_BASE +  4, T0, T1, I0) \
+	AES_EROUND23(KEY_BASE +  6, T0, T1, I1)
+
+#define ENCRYPT_TWO_ROUNDS_2(KEY_BASE, I0, I1, I2, I3, T0, T1, T2, T3) \
+	AES_EROUND01(KEY_BASE +  0, I0, I1, T0) \
+	AES_EROUND23(KEY_BASE +  2, I0, I1, T1) \
+	AES_EROUND01(KEY_BASE +  0, I2, I3, T2) \
+	AES_EROUND23(KEY_BASE +  2, I2, I3, T3) \
+	AES_EROUND01(KEY_BASE +  4, T0, T1, I0) \
+	AES_EROUND23(KEY_BASE +  6, T0, T1, I1) \
+	AES_EROUND01(KEY_BASE +  4, T2, T3, I2) \
+	AES_EROUND23(KEY_BASE +  6, T2, T3, I3)
+
+#define ENCRYPT_TWO_ROUNDS_LAST(KEY_BASE, I0, I1, T0, T1) \
+	AES_EROUND01(KEY_BASE +  0, I0, I1, T0) \
+	AES_EROUND23(KEY_BASE +  2, I0, I1, T1) \
+	AES_EROUND01_L(KEY_BASE +  4, T0, T1, I0) \
+	AES_EROUND23_L(KEY_BASE +  6, T0, T1, I1)
+
+#define ENCRYPT_TWO_ROUNDS_LAST_2(KEY_BASE, I0, I1, I2, I3, T0, T1, T2, T3) \
+	AES_EROUND01(KEY_BASE +  0, I0, I1, T0) \
+	AES_EROUND23(KEY_BASE +  2, I0, I1, T1) \
+	AES_EROUND01(KEY_BASE +  0, I2, I3, T2) \
+	AES_EROUND23(KEY_BASE +  2, I2, I3, T3) \
+	AES_EROUND01_L(KEY_BASE +  4, T0, T1, I0) \
+	AES_EROUND23_L(KEY_BASE +  6, T0, T1, I1) \
+	AES_EROUND01_L(KEY_BASE +  4, T2, T3, I2) \
+	AES_EROUND23_L(KEY_BASE +  6, T2, T3, I3)
+
+	/* 10 rounds */
+#define ENCRYPT_128(KEY_BASE, I0, I1, T0, T1) \
+	ENCRYPT_TWO_ROUNDS(KEY_BASE +  0, I0, I1, T0, T1) \
+	ENCRYPT_TWO_ROUNDS(KEY_BASE +  8, I0, I1, T0, T1) \
+	ENCRYPT_TWO_ROUNDS(KEY_BASE + 16, I0, I1, T0, T1) \
+	ENCRYPT_TWO_ROUNDS(KEY_BASE + 24, I0, I1, T0, T1) \
+	ENCRYPT_TWO_ROUNDS_LAST(KEY_BASE + 32, I0, I1, T0, T1)
+
+#define ENCRYPT_128_2(KEY_BASE, I0, I1, I2, I3, T0, T1, T2, T3) \
+	ENCRYPT_TWO_ROUNDS_2(KEY_BASE +  0, I0, I1, I2, I3, T0, T1, T2, T3) \
+	ENCRYPT_TWO_ROUNDS_2(KEY_BASE +  8, I0, I1, I2, I3, T0, T1, T2, T3) \
+	ENCRYPT_TWO_ROUNDS_2(KEY_BASE + 16, I0, I1, I2, I3, T0, T1, T2, T3) \
+	ENCRYPT_TWO_ROUNDS_2(KEY_BASE + 24, I0, I1, I2, I3, T0, T1, T2, T3) \
+	ENCRYPT_TWO_ROUNDS_LAST_2(KEY_BASE + 32, I0, I1, I2, I3, T0, T1, T2, T3)
+
+	/* 12 rounds */
+#define ENCRYPT_192(KEY_BASE, I0, I1, T0, T1) \
+	ENCRYPT_TWO_ROUNDS(KEY_BASE +  0, I0, I1, T0, T1) \
+	ENCRYPT_TWO_ROUNDS(KEY_BASE +  8, I0, I1, T0, T1) \
+	ENCRYPT_TWO_ROUNDS(KEY_BASE + 16, I0, I1, T0, T1) \
+	ENCRYPT_TWO_ROUNDS(KEY_BASE + 24, I0, I1, T0, T1) \
+	ENCRYPT_TWO_ROUNDS(KEY_BASE + 32, I0, I1, T0, T1) \
+	ENCRYPT_TWO_ROUNDS_LAST(KEY_BASE + 40, I0, I1, T0, T1)
+
+#define ENCRYPT_192_2(KEY_BASE, I0, I1, I2, I3, T0, T1, T2, T3) \
+	ENCRYPT_TWO_ROUNDS_2(KEY_BASE +  0, I0, I1, I2, I3, T0, T1, T2, T3) \
+	ENCRYPT_TWO_ROUNDS_2(KEY_BASE +  8, I0, I1, I2, I3, T0, T1, T2, T3) \
+	ENCRYPT_TWO_ROUNDS_2(KEY_BASE + 16, I0, I1, I2, I3, T0, T1, T2, T3) \
+	ENCRYPT_TWO_ROUNDS_2(KEY_BASE + 24, I0, I1, I2, I3, T0, T1, T2, T3) \
+	ENCRYPT_TWO_ROUNDS_2(KEY_BASE + 32, I0, I1, I2, I3, T0, T1, T2, T3) \
+	ENCRYPT_TWO_ROUNDS_LAST_2(KEY_BASE + 40, I0, I1, I2, I3, T0, T1, T2, T3)
+
+	/* 14 rounds */
+#define ENCRYPT_256(KEY_BASE, I0, I1, T0, T1) \
+	ENCRYPT_TWO_ROUNDS(KEY_BASE +  0, I0, I1, T0, T1) \
+	ENCRYPT_TWO_ROUNDS(KEY_BASE +  8, I0, I1, T0, T1) \
+	ENCRYPT_TWO_ROUNDS(KEY_BASE + 16, I0, I1, T0, T1) \
+	ENCRYPT_TWO_ROUNDS(KEY_BASE + 24, I0, I1, T0, T1) \
+	ENCRYPT_TWO_ROUNDS(KEY_BASE + 32, I0, I1, T0, T1) \
+	ENCRYPT_TWO_ROUNDS(KEY_BASE + 40, I0, I1, T0, T1) \
+	ENCRYPT_TWO_ROUNDS_LAST(KEY_BASE + 48, I0, I1, T0, T1)
+
+#define ENCRYPT_256_TWO_ROUNDS_2(KEY_BASE, I0, I1, I2, I3, TMP_BASE) \
+	ENCRYPT_TWO_ROUNDS_2(KEY_BASE, I0, I1, I2, I3, \
+			     TMP_BASE + 0, TMP_BASE + 2, TMP_BASE + 4, TMP_BASE + 6)
+
+#define ENCRYPT_256_2(KEY_BASE, I0, I1, I2, I3) \
+	ENCRYPT_256_TWO_ROUNDS_2(KEY_BASE +  0, I0, I1, I2, I3, KEY_BASE + 48) \
+	ldd	[%o0 + 0xd0], %f56; \
+	ldd	[%o0 + 0xd8], %f58; \
+	ENCRYPT_256_TWO_ROUNDS_2(KEY_BASE +  8, I0, I1, I2, I3, KEY_BASE +  0) \
+	ldd	[%o0 + 0xe0], %f60; \
+	ldd	[%o0 + 0xe8], %f62; \
+	ENCRYPT_256_TWO_ROUNDS_2(KEY_BASE + 16, I0, I1, I2, I3, KEY_BASE +  0) \
+	ENCRYPT_256_TWO_ROUNDS_2(KEY_BASE + 24, I0, I1, I2, I3, KEY_BASE +  0) \
+	ENCRYPT_256_TWO_ROUNDS_2(KEY_BASE + 32, I0, I1, I2, I3, KEY_BASE +  0) \
+	ENCRYPT_256_TWO_ROUNDS_2(KEY_BASE + 40, I0, I1, I2, I3, KEY_BASE +  0) \
+	AES_EROUND01(KEY_BASE +  48, I0, I1, KEY_BASE + 0) \
+	AES_EROUND23(KEY_BASE +  50, I0, I1, KEY_BASE + 2) \
+	AES_EROUND01(KEY_BASE +  48, I2, I3, KEY_BASE + 4) \
+	AES_EROUND23(KEY_BASE +  50, I2, I3, KEY_BASE + 6) \
+	AES_EROUND01_L(KEY_BASE +  52, KEY_BASE + 0, KEY_BASE + 2, I0) \
+	AES_EROUND23_L(KEY_BASE +  54, KEY_BASE + 0, KEY_BASE + 2, I1) \
+	ldd	[%o0 + 0x10], %f8; \
+	ldd	[%o0 + 0x18], %f10; \
+	AES_EROUND01_L(KEY_BASE +  52, KEY_BASE + 4, KEY_BASE + 6, I2) \
+	AES_EROUND23_L(KEY_BASE +  54, KEY_BASE + 4, KEY_BASE + 6, I3) \
+	ldd	[%o0 + 0x20], %f12; \
+	ldd	[%o0 + 0x28], %f14;
+
+#define DECRYPT_TWO_ROUNDS(KEY_BASE, I0, I1, T0, T1) \
+	AES_DROUND23(KEY_BASE +  0, I0, I1, T1) \
+	AES_DROUND01(KEY_BASE +  2, I0, I1, T0) \
+	AES_DROUND23(KEY_BASE +  4, T0, T1, I1) \
+	AES_DROUND01(KEY_BASE +  6, T0, T1, I0)
+
+#define DECRYPT_TWO_ROUNDS_2(KEY_BASE, I0, I1, I2, I3, T0, T1, T2, T3) \
+	AES_DROUND23(KEY_BASE +  0, I0, I1, T1) \
+	AES_DROUND01(KEY_BASE +  2, I0, I1, T0) \
+	AES_DROUND23(KEY_BASE +  0, I2, I3, T3) \
+	AES_DROUND01(KEY_BASE +  2, I2, I3, T2) \
+	AES_DROUND23(KEY_BASE +  4, T0, T1, I1) \
+	AES_DROUND01(KEY_BASE +  6, T0, T1, I0) \
+	AES_DROUND23(KEY_BASE +  4, T2, T3, I3) \
+	AES_DROUND01(KEY_BASE +  6, T2, T3, I2)
+
+#define DECRYPT_TWO_ROUNDS_LAST(KEY_BASE, I0, I1, T0, T1) \
+	AES_DROUND23(KEY_BASE +  0, I0, I1, T1) \
+	AES_DROUND01(KEY_BASE +  2, I0, I1, T0) \
+	AES_DROUND23_L(KEY_BASE +  4, T0, T1, I1) \
+	AES_DROUND01_L(KEY_BASE +  6, T0, T1, I0)
+
+#define DECRYPT_TWO_ROUNDS_LAST_2(KEY_BASE, I0, I1, I2, I3, T0, T1, T2, T3) \
+	AES_DROUND23(KEY_BASE +  0, I0, I1, T1) \
+	AES_DROUND01(KEY_BASE +  2, I0, I1, T0) \
+	AES_DROUND23(KEY_BASE +  0, I2, I3, T3) \
+	AES_DROUND01(KEY_BASE +  2, I2, I3, T2) \
+	AES_DROUND23_L(KEY_BASE +  4, T0, T1, I1) \
+	AES_DROUND01_L(KEY_BASE +  6, T0, T1, I0) \
+	AES_DROUND23_L(KEY_BASE +  4, T2, T3, I3) \
+	AES_DROUND01_L(KEY_BASE +  6, T2, T3, I2)
+
+	/* 10 rounds */
+#define DECRYPT_128(KEY_BASE, I0, I1, T0, T1) \
+	DECRYPT_TWO_ROUNDS(KEY_BASE +  0, I0, I1, T0, T1) \
+	DECRYPT_TWO_ROUNDS(KEY_BASE +  8, I0, I1, T0, T1) \
+	DECRYPT_TWO_ROUNDS(KEY_BASE + 16, I0, I1, T0, T1) \
+	DECRYPT_TWO_ROUNDS(KEY_BASE + 24, I0, I1, T0, T1) \
+	DECRYPT_TWO_ROUNDS_LAST(KEY_BASE + 32, I0, I1, T0, T1)
+
+#define DECRYPT_128_2(KEY_BASE, I0, I1, I2, I3, T0, T1, T2, T3) \
+	DECRYPT_TWO_ROUNDS_2(KEY_BASE +  0, I0, I1, I2, I3, T0, T1, T2, T3) \
+	DECRYPT_TWO_ROUNDS_2(KEY_BASE +  8, I0, I1, I2, I3, T0, T1, T2, T3) \
+	DECRYPT_TWO_ROUNDS_2(KEY_BASE + 16, I0, I1, I2, I3, T0, T1, T2, T3) \
+	DECRYPT_TWO_ROUNDS_2(KEY_BASE + 24, I0, I1, I2, I3, T0, T1, T2, T3) \
+	DECRYPT_TWO_ROUNDS_LAST_2(KEY_BASE + 32, I0, I1, I2, I3, T0, T1, T2, T3)
+
+	/* 12 rounds */
+#define DECRYPT_192(KEY_BASE, I0, I1, T0, T1) \
+	DECRYPT_TWO_ROUNDS(KEY_BASE +  0, I0, I1, T0, T1) \
+	DECRYPT_TWO_ROUNDS(KEY_BASE +  8, I0, I1, T0, T1) \
+	DECRYPT_TWO_ROUNDS(KEY_BASE + 16, I0, I1, T0, T1) \
+	DECRYPT_TWO_ROUNDS(KEY_BASE + 24, I0, I1, T0, T1) \
+	DECRYPT_TWO_ROUNDS(KEY_BASE + 32, I0, I1, T0, T1) \
+	DECRYPT_TWO_ROUNDS_LAST(KEY_BASE + 40, I0, I1, T0, T1)
+
+#define DECRYPT_192_2(KEY_BASE, I0, I1, I2, I3, T0, T1, T2, T3) \
+	DECRYPT_TWO_ROUNDS_2(KEY_BASE +  0, I0, I1, I2, I3, T0, T1, T2, T3) \
+	DECRYPT_TWO_ROUNDS_2(KEY_BASE +  8, I0, I1, I2, I3, T0, T1, T2, T3) \
+	DECRYPT_TWO_ROUNDS_2(KEY_BASE + 16, I0, I1, I2, I3, T0, T1, T2, T3) \
+	DECRYPT_TWO_ROUNDS_2(KEY_BASE + 24, I0, I1, I2, I3, T0, T1, T2, T3) \
+	DECRYPT_TWO_ROUNDS_2(KEY_BASE + 32, I0, I1, I2, I3, T0, T1, T2, T3) \
+	DECRYPT_TWO_ROUNDS_LAST_2(KEY_BASE + 40, I0, I1, I2, I3, T0, T1, T2, T3)
+
+	/* 14 rounds */
+#define DECRYPT_256(KEY_BASE, I0, I1, T0, T1) \
+	DECRYPT_TWO_ROUNDS(KEY_BASE +  0, I0, I1, T0, T1) \
+	DECRYPT_TWO_ROUNDS(KEY_BASE +  8, I0, I1, T0, T1) \
+	DECRYPT_TWO_ROUNDS(KEY_BASE + 16, I0, I1, T0, T1) \
+	DECRYPT_TWO_ROUNDS(KEY_BASE + 24, I0, I1, T0, T1) \
+	DECRYPT_TWO_ROUNDS(KEY_BASE + 32, I0, I1, T0, T1) \
+	DECRYPT_TWO_ROUNDS(KEY_BASE + 40, I0, I1, T0, T1) \
+	DECRYPT_TWO_ROUNDS_LAST(KEY_BASE + 48, I0, I1, T0, T1)
+
+#define DECRYPT_256_TWO_ROUNDS_2(KEY_BASE, I0, I1, I2, I3, TMP_BASE) \
+	DECRYPT_TWO_ROUNDS_2(KEY_BASE, I0, I1, I2, I3, \
+			     TMP_BASE + 0, TMP_BASE + 2, TMP_BASE + 4, TMP_BASE + 6)
+
+#define DECRYPT_256_2(KEY_BASE, I0, I1, I2, I3) \
+	DECRYPT_256_TWO_ROUNDS_2(KEY_BASE +  0, I0, I1, I2, I3, KEY_BASE + 48) \
+	ldd	[%o0 + 0x18], %f56; \
+	ldd	[%o0 + 0x10], %f58; \
+	DECRYPT_256_TWO_ROUNDS_2(KEY_BASE +  8, I0, I1, I2, I3, KEY_BASE +  0) \
+	ldd	[%o0 + 0x08], %f60; \
+	ldd	[%o0 + 0x00], %f62; \
+	DECRYPT_256_TWO_ROUNDS_2(KEY_BASE + 16, I0, I1, I2, I3, KEY_BASE +  0) \
+	DECRYPT_256_TWO_ROUNDS_2(KEY_BASE + 24, I0, I1, I2, I3, KEY_BASE +  0) \
+	DECRYPT_256_TWO_ROUNDS_2(KEY_BASE + 32, I0, I1, I2, I3, KEY_BASE +  0) \
+	DECRYPT_256_TWO_ROUNDS_2(KEY_BASE + 40, I0, I1, I2, I3, KEY_BASE +  0) \
+	AES_DROUND23(KEY_BASE +  48, I0, I1, KEY_BASE + 2) \
+	AES_DROUND01(KEY_BASE +  50, I0, I1, KEY_BASE + 0) \
+	AES_DROUND23(KEY_BASE +  48, I2, I3, KEY_BASE + 6) \
+	AES_DROUND01(KEY_BASE +  50, I2, I3, KEY_BASE + 4) \
+	AES_DROUND23_L(KEY_BASE +  52, KEY_BASE + 0, KEY_BASE + 2, I1) \
+	AES_DROUND01_L(KEY_BASE +  54, KEY_BASE + 0, KEY_BASE + 2, I0) \
+	ldd	[%o0 + 0xd8], %f8; \
+	ldd	[%o0 + 0xd0], %f10; \
+	AES_DROUND23_L(KEY_BASE +  52, KEY_BASE + 4, KEY_BASE + 6, I3) \
+	AES_DROUND01_L(KEY_BASE +  54, KEY_BASE + 4, KEY_BASE + 6, I2) \
+	ldd	[%o0 + 0xc8], %f12; \
+	ldd	[%o0 + 0xc0], %f14;
+
+	.align	32
+ENTRY(aes_sparc64_key_expand)
+	/* %o0=input_key, %o1=output_key, %o2=key_len */
+	VISEntry
+	ld	[%o0 + 0x00], %f0
+	ld	[%o0 + 0x04], %f1
+	ld	[%o0 + 0x08], %f2
+	ld	[%o0 + 0x0c], %f3
+
+	std	%f0, [%o1 + 0x00]
+	std	%f2, [%o1 + 0x08]
+	add	%o1, 0x10, %o1
+
+	cmp	%o2, 24
+	bl	2f
+	 nop
+
+	be	1f
+	 nop
+
+	/* 256-bit key expansion */
+	ld	[%o0 + 0x10], %f4
+	ld	[%o0 + 0x14], %f5
+	ld	[%o0 + 0x18], %f6
+	ld	[%o0 + 0x1c], %f7
+
+	std	%f4, [%o1 + 0x00]
+	std	%f6, [%o1 + 0x08]
+	add	%o1, 0x10, %o1
+
+	AES_KEXPAND1(0, 6, 0x0, 8)
+	AES_KEXPAND2(2, 8, 10)
+	AES_KEXPAND0(4, 10, 12)
+	AES_KEXPAND2(6, 12, 14)
+	AES_KEXPAND1(8, 14, 0x1, 16)
+	AES_KEXPAND2(10, 16, 18)
+	AES_KEXPAND0(12, 18, 20)
+	AES_KEXPAND2(14, 20, 22)
+	AES_KEXPAND1(16, 22, 0x2, 24)
+	AES_KEXPAND2(18, 24, 26)
+	AES_KEXPAND0(20, 26, 28)
+	AES_KEXPAND2(22, 28, 30)
+	AES_KEXPAND1(24, 30, 0x3, 32)
+	AES_KEXPAND2(26, 32, 34)
+	AES_KEXPAND0(28, 34, 36)
+	AES_KEXPAND2(30, 36, 38)
+	AES_KEXPAND1(32, 38, 0x4, 40)
+	AES_KEXPAND2(34, 40, 42)
+	AES_KEXPAND0(36, 42, 44)
+	AES_KEXPAND2(38, 44, 46)
+	AES_KEXPAND1(40, 46, 0x5, 48)
+	AES_KEXPAND2(42, 48, 50)
+	AES_KEXPAND0(44, 50, 52)
+	AES_KEXPAND2(46, 52, 54)
+	AES_KEXPAND1(48, 54, 0x6, 56)
+	AES_KEXPAND2(50, 56, 58)
+
+	std	%f8, [%o1 + 0x00]
+	std	%f10, [%o1 + 0x08]
+	std	%f12, [%o1 + 0x10]
+	std	%f14, [%o1 + 0x18]
+	std	%f16, [%o1 + 0x20]
+	std	%f18, [%o1 + 0x28]
+	std	%f20, [%o1 + 0x30]
+	std	%f22, [%o1 + 0x38]
+	std	%f24, [%o1 + 0x40]
+	std	%f26, [%o1 + 0x48]
+	std	%f28, [%o1 + 0x50]
+	std	%f30, [%o1 + 0x58]
+	std	%f32, [%o1 + 0x60]
+	std	%f34, [%o1 + 0x68]
+	std	%f36, [%o1 + 0x70]
+	std	%f38, [%o1 + 0x78]
+	std	%f40, [%o1 + 0x80]
+	std	%f42, [%o1 + 0x88]
+	std	%f44, [%o1 + 0x90]
+	std	%f46, [%o1 + 0x98]
+	std	%f48, [%o1 + 0xa0]
+	std	%f50, [%o1 + 0xa8]
+	std	%f52, [%o1 + 0xb0]
+	std	%f54, [%o1 + 0xb8]
+	std	%f56, [%o1 + 0xc0]
+	ba,pt	%xcc, 80f
+	 std	%f58, [%o1 + 0xc8]
+
+1:	
+	/* 192-bit key expansion */
+	ld	[%o0 + 0x10], %f4
+	ld	[%o0 + 0x14], %f5
+
+	std	%f4, [%o1 + 0x00]
+	add	%o1, 0x08, %o1
+
+	AES_KEXPAND1(0, 4, 0x0, 6)
+	AES_KEXPAND2(2, 6, 8)
+	AES_KEXPAND2(4, 8, 10)
+	AES_KEXPAND1(6, 10, 0x1, 12)
+	AES_KEXPAND2(8, 12, 14)
+	AES_KEXPAND2(10, 14, 16)
+	AES_KEXPAND1(12, 16, 0x2, 18)
+	AES_KEXPAND2(14, 18, 20)
+	AES_KEXPAND2(16, 20, 22)
+	AES_KEXPAND1(18, 22, 0x3, 24)
+	AES_KEXPAND2(20, 24, 26)
+	AES_KEXPAND2(22, 26, 28)
+	AES_KEXPAND1(24, 28, 0x4, 30)
+	AES_KEXPAND2(26, 30, 32)
+	AES_KEXPAND2(28, 32, 34)
+	AES_KEXPAND1(30, 34, 0x5, 36)
+	AES_KEXPAND2(32, 36, 38)
+	AES_KEXPAND2(34, 38, 40)
+	AES_KEXPAND1(36, 40, 0x6, 42)
+	AES_KEXPAND2(38, 42, 44)
+	AES_KEXPAND2(40, 44, 46)
+	AES_KEXPAND1(42, 46, 0x7, 48)
+	AES_KEXPAND2(44, 48, 50)
+
+	std	%f6, [%o1 + 0x00]
+	std	%f8, [%o1 + 0x08]
+	std	%f10, [%o1 + 0x10]
+	std	%f12, [%o1 + 0x18]
+	std	%f14, [%o1 + 0x20]
+	std	%f16, [%o1 + 0x28]
+	std	%f18, [%o1 + 0x30]
+	std	%f20, [%o1 + 0x38]
+	std	%f22, [%o1 + 0x40]
+	std	%f24, [%o1 + 0x48]
+	std	%f26, [%o1 + 0x50]
+	std	%f28, [%o1 + 0x58]
+	std	%f30, [%o1 + 0x60]
+	std	%f32, [%o1 + 0x68]
+	std	%f34, [%o1 + 0x70]
+	std	%f36, [%o1 + 0x78]
+	std	%f38, [%o1 + 0x80]
+	std	%f40, [%o1 + 0x88]
+	std	%f42, [%o1 + 0x90]
+	std	%f44, [%o1 + 0x98]
+	std	%f46, [%o1 + 0xa0]
+	std	%f48, [%o1 + 0xa8]
+	ba,pt	%xcc, 80f
+	 std	%f50, [%o1 + 0xb0]
+
+2:
+	/* 128-bit key expansion */
+	AES_KEXPAND1(0, 2, 0x0, 4)
+	AES_KEXPAND2(2, 4, 6)
+	AES_KEXPAND1(4, 6, 0x1, 8)
+	AES_KEXPAND2(6, 8, 10)
+	AES_KEXPAND1(8, 10, 0x2, 12)
+	AES_KEXPAND2(10, 12, 14)
+	AES_KEXPAND1(12, 14, 0x3, 16)
+	AES_KEXPAND2(14, 16, 18)
+	AES_KEXPAND1(16, 18, 0x4, 20)
+	AES_KEXPAND2(18, 20, 22)
+	AES_KEXPAND1(20, 22, 0x5, 24)
+	AES_KEXPAND2(22, 24, 26)
+	AES_KEXPAND1(24, 26, 0x6, 28)
+	AES_KEXPAND2(26, 28, 30)
+	AES_KEXPAND1(28, 30, 0x7, 32)
+	AES_KEXPAND2(30, 32, 34)
+	AES_KEXPAND1(32, 34, 0x8, 36)
+	AES_KEXPAND2(34, 36, 38)
+	AES_KEXPAND1(36, 38, 0x9, 40)
+	AES_KEXPAND2(38, 40, 42)
+
+	std	%f4, [%o1 + 0x00]
+	std	%f6, [%o1 + 0x08]
+	std	%f8, [%o1 + 0x10]
+	std	%f10, [%o1 + 0x18]
+	std	%f12, [%o1 + 0x20]
+	std	%f14, [%o1 + 0x28]
+	std	%f16, [%o1 + 0x30]
+	std	%f18, [%o1 + 0x38]
+	std	%f20, [%o1 + 0x40]
+	std	%f22, [%o1 + 0x48]
+	std	%f24, [%o1 + 0x50]
+	std	%f26, [%o1 + 0x58]
+	std	%f28, [%o1 + 0x60]
+	std	%f30, [%o1 + 0x68]
+	std	%f32, [%o1 + 0x70]
+	std	%f34, [%o1 + 0x78]
+	std	%f36, [%o1 + 0x80]
+	std	%f38, [%o1 + 0x88]
+	std	%f40, [%o1 + 0x90]
+	std	%f42, [%o1 + 0x98]
+80:
+	retl
+	 VISExit
+ENDPROC(aes_sparc64_key_expand)
+
+	.align		32
+ENTRY(aes_sparc64_encrypt_128)
+	/* %o0=key, %o1=input, %o2=output */
+	VISEntry
+	ld		[%o1 + 0x00], %f4
+	ld		[%o1 + 0x04], %f5
+	ld		[%o1 + 0x08], %f6
+	ld		[%o1 + 0x0c], %f7
+	ldd		[%o0 + 0x00], %f8
+	ldd		[%o0 + 0x08], %f10
+	ldd		[%o0 + 0x10], %f12
+	ldd		[%o0 + 0x18], %f14
+	ldd		[%o0 + 0x20], %f16
+	ldd		[%o0 + 0x28], %f18
+	ldd		[%o0 + 0x30], %f20
+	ldd		[%o0 + 0x38], %f22
+	ldd		[%o0 + 0x40], %f24
+	ldd		[%o0 + 0x48], %f26
+	ldd		[%o0 + 0x50], %f28
+	ldd		[%o0 + 0x58], %f30
+	ldd		[%o0 + 0x60], %f32
+	ldd		[%o0 + 0x68], %f34
+	ldd		[%o0 + 0x70], %f36
+	ldd		[%o0 + 0x78], %f38
+	ldd		[%o0 + 0x80], %f40
+	ldd		[%o0 + 0x88], %f42
+	ldd		[%o0 + 0x90], %f44
+	ldd		[%o0 + 0x98], %f46
+	ldd		[%o0 + 0xa0], %f48
+	ldd		[%o0 + 0xa8], %f50
+	fxor		%f8, %f4, %f4
+	fxor		%f10, %f6, %f6
+	ENCRYPT_128(12, 4, 6, 0, 2)
+	st		%f4, [%o2 + 0x00]
+	st		%f5, [%o2 + 0x04]
+	st		%f6, [%o2 + 0x08]
+	st		%f7, [%o2 + 0x0c]
+	retl
+	 VISExit
+ENDPROC(aes_sparc64_encrypt_128)
+
+	.align		32
+ENTRY(aes_sparc64_encrypt_192)
+	/* %o0=key, %o1=input, %o2=output */
+	VISEntry
+	ld		[%o1 + 0x00], %f4
+	ld		[%o1 + 0x04], %f5
+	ld		[%o1 + 0x08], %f6
+	ld		[%o1 + 0x0c], %f7
+
+	ldd		[%o0 + 0x00], %f8
+	ldd		[%o0 + 0x08], %f10
+
+	fxor		%f8, %f4, %f4
+	fxor		%f10, %f6, %f6
+
+	ldd		[%o0 + 0x10], %f8
+	ldd		[%o0 + 0x18], %f10
+	ldd		[%o0 + 0x20], %f12
+	ldd		[%o0 + 0x28], %f14
+	add		%o0, 0x20, %o0
+
+	ENCRYPT_TWO_ROUNDS(8, 4, 6, 0, 2)
+
+	ldd		[%o0 + 0x10], %f12
+	ldd		[%o0 + 0x18], %f14
+	ldd		[%o0 + 0x20], %f16
+	ldd		[%o0 + 0x28], %f18
+	ldd		[%o0 + 0x30], %f20
+	ldd		[%o0 + 0x38], %f22
+	ldd		[%o0 + 0x40], %f24
+	ldd		[%o0 + 0x48], %f26
+	ldd		[%o0 + 0x50], %f28
+	ldd		[%o0 + 0x58], %f30
+	ldd		[%o0 + 0x60], %f32
+	ldd		[%o0 + 0x68], %f34
+	ldd		[%o0 + 0x70], %f36
+	ldd		[%o0 + 0x78], %f38
+	ldd		[%o0 + 0x80], %f40
+	ldd		[%o0 + 0x88], %f42
+	ldd		[%o0 + 0x90], %f44
+	ldd		[%o0 + 0x98], %f46
+	ldd		[%o0 + 0xa0], %f48
+	ldd		[%o0 + 0xa8], %f50
+
+
+	ENCRYPT_128(12, 4, 6, 0, 2)
+
+	st		%f4, [%o2 + 0x00]
+	st		%f5, [%o2 + 0x04]
+	st		%f6, [%o2 + 0x08]
+	st		%f7, [%o2 + 0x0c]
+
+	retl
+	 VISExit
+ENDPROC(aes_sparc64_encrypt_192)
+
+	.align		32
+ENTRY(aes_sparc64_encrypt_256)
+	/* %o0=key, %o1=input, %o2=output */
+	VISEntry
+	ld		[%o1 + 0x00], %f4
+	ld		[%o1 + 0x04], %f5
+	ld		[%o1 + 0x08], %f6
+	ld		[%o1 + 0x0c], %f7
+
+	ldd		[%o0 + 0x00], %f8
+	ldd		[%o0 + 0x08], %f10
+
+	fxor		%f8, %f4, %f4
+	fxor		%f10, %f6, %f6
+
+	ldd		[%o0 + 0x10], %f8
+
+	ldd		[%o0 + 0x18], %f10
+	ldd		[%o0 + 0x20], %f12
+	ldd		[%o0 + 0x28], %f14
+	add		%o0, 0x20, %o0
+
+	ENCRYPT_TWO_ROUNDS(8, 4, 6, 0, 2)
+
+	ldd		[%o0 + 0x10], %f8
+
+	ldd		[%o0 + 0x18], %f10
+	ldd		[%o0 + 0x20], %f12
+	ldd		[%o0 + 0x28], %f14
+	add		%o0, 0x20, %o0
+
+	ENCRYPT_TWO_ROUNDS(8, 4, 6, 0, 2)
+
+	ldd		[%o0 + 0x10], %f12
+	ldd		[%o0 + 0x18], %f14
+	ldd		[%o0 + 0x20], %f16
+	ldd		[%o0 + 0x28], %f18
+	ldd		[%o0 + 0x30], %f20
+	ldd		[%o0 + 0x38], %f22
+	ldd		[%o0 + 0x40], %f24
+	ldd		[%o0 + 0x48], %f26
+	ldd		[%o0 + 0x50], %f28
+	ldd		[%o0 + 0x58], %f30
+	ldd		[%o0 + 0x60], %f32
+	ldd		[%o0 + 0x68], %f34
+	ldd		[%o0 + 0x70], %f36
+	ldd		[%o0 + 0x78], %f38
+	ldd		[%o0 + 0x80], %f40
+	ldd		[%o0 + 0x88], %f42
+	ldd		[%o0 + 0x90], %f44
+	ldd		[%o0 + 0x98], %f46
+	ldd		[%o0 + 0xa0], %f48
+	ldd		[%o0 + 0xa8], %f50
+
+	ENCRYPT_128(12, 4, 6, 0, 2)
+
+	st		%f4, [%o2 + 0x00]
+	st		%f5, [%o2 + 0x04]
+	st		%f6, [%o2 + 0x08]
+	st		%f7, [%o2 + 0x0c]
+
+	retl
+	 VISExit
+ENDPROC(aes_sparc64_encrypt_256)
+
+	.align		32
+ENTRY(aes_sparc64_decrypt_128)
+	/* %o0=key, %o1=input, %o2=output */
+	VISEntry
+	ld		[%o1 + 0x00], %f4
+	ld		[%o1 + 0x04], %f5
+	ld		[%o1 + 0x08], %f6
+	ld		[%o1 + 0x0c], %f7
+	ldd		[%o0 + 0xa0], %f8
+	ldd		[%o0 + 0xa8], %f10
+	ldd		[%o0 + 0x98], %f12
+	ldd		[%o0 + 0x90], %f14
+	ldd		[%o0 + 0x88], %f16
+	ldd		[%o0 + 0x80], %f18
+	ldd		[%o0 + 0x78], %f20
+	ldd		[%o0 + 0x70], %f22
+	ldd		[%o0 + 0x68], %f24
+	ldd		[%o0 + 0x60], %f26
+	ldd		[%o0 + 0x58], %f28
+	ldd		[%o0 + 0x50], %f30
+	ldd		[%o0 + 0x48], %f32
+	ldd		[%o0 + 0x40], %f34
+	ldd		[%o0 + 0x38], %f36
+	ldd		[%o0 + 0x30], %f38
+	ldd		[%o0 + 0x28], %f40
+	ldd		[%o0 + 0x20], %f42
+	ldd		[%o0 + 0x18], %f44
+	ldd		[%o0 + 0x10], %f46
+	ldd		[%o0 + 0x08], %f48
+	ldd		[%o0 + 0x00], %f50
+	fxor		%f8, %f4, %f4
+	fxor		%f10, %f6, %f6
+	DECRYPT_128(12, 4, 6, 0, 2)
+	st		%f4, [%o2 + 0x00]
+	st		%f5, [%o2 + 0x04]
+	st		%f6, [%o2 + 0x08]
+	st		%f7, [%o2 + 0x0c]
+	retl
+	 VISExit
+ENDPROC(aes_sparc64_decrypt_128)
+
+	.align		32
+ENTRY(aes_sparc64_decrypt_192)
+	/* %o0=key, %o1=input, %o2=output */
+	VISEntry
+	ld		[%o1 + 0x00], %f4
+	ld		[%o1 + 0x04], %f5
+	ld		[%o1 + 0x08], %f6
+	ld		[%o1 + 0x0c], %f7
+	ldd		[%o0 + 0xc0], %f8
+	ldd		[%o0 + 0xc8], %f10
+	ldd		[%o0 + 0xb8], %f12
+	ldd		[%o0 + 0xb0], %f14
+	ldd		[%o0 + 0xa8], %f16
+	ldd		[%o0 + 0xa0], %f18
+	fxor		%f8, %f4, %f4
+	fxor		%f10, %f6, %f6
+	ldd		[%o0 + 0x98], %f20
+	ldd		[%o0 + 0x90], %f22
+	ldd		[%o0 + 0x88], %f24
+	ldd		[%o0 + 0x80], %f26
+	DECRYPT_TWO_ROUNDS(12, 4, 6, 0, 2)
+	ldd		[%o0 + 0x78], %f28
+	ldd		[%o0 + 0x70], %f30
+	ldd		[%o0 + 0x68], %f32
+	ldd		[%o0 + 0x60], %f34
+	ldd		[%o0 + 0x58], %f36
+	ldd		[%o0 + 0x50], %f38
+	ldd		[%o0 + 0x48], %f40
+	ldd		[%o0 + 0x40], %f42
+	ldd		[%o0 + 0x38], %f44
+	ldd		[%o0 + 0x30], %f46
+	ldd		[%o0 + 0x28], %f48
+	ldd		[%o0 + 0x20], %f50
+	ldd		[%o0 + 0x18], %f52
+	ldd		[%o0 + 0x10], %f54
+	ldd		[%o0 + 0x08], %f56
+	ldd		[%o0 + 0x00], %f58
+	DECRYPT_128(20, 4, 6, 0, 2)
+	st		%f4, [%o2 + 0x00]
+	st		%f5, [%o2 + 0x04]
+	st		%f6, [%o2 + 0x08]
+	st		%f7, [%o2 + 0x0c]
+	retl
+	 VISExit
+ENDPROC(aes_sparc64_decrypt_192)
+
+	.align		32
+ENTRY(aes_sparc64_decrypt_256)
+	/* %o0=key, %o1=input, %o2=output */
+	VISEntry
+	ld		[%o1 + 0x00], %f4
+	ld		[%o1 + 0x04], %f5
+	ld		[%o1 + 0x08], %f6
+	ld		[%o1 + 0x0c], %f7
+	ldd		[%o0 + 0xe0], %f8
+	ldd		[%o0 + 0xe8], %f10
+	ldd		[%o0 + 0xd8], %f12
+	ldd		[%o0 + 0xd0], %f14
+	ldd		[%o0 + 0xc8], %f16
+	fxor		%f8, %f4, %f4
+	ldd		[%o0 + 0xc0], %f18
+	fxor		%f10, %f6, %f6
+	ldd		[%o0 + 0xb8], %f20
+	AES_DROUND23(12, 4, 6, 2)
+	ldd		[%o0 + 0xb0], %f22
+	AES_DROUND01(14, 4, 6, 0)
+	ldd		[%o0 + 0xa8], %f24
+	AES_DROUND23(16, 0, 2, 6)
+	ldd		[%o0 + 0xa0], %f26
+	AES_DROUND01(18, 0, 2, 4)
+	ldd		[%o0 + 0x98], %f12
+	AES_DROUND23(20, 4, 6, 2)
+	ldd		[%o0 + 0x90], %f14
+	AES_DROUND01(22, 4, 6, 0)
+	ldd		[%o0 + 0x88], %f16
+	AES_DROUND23(24, 0, 2, 6)
+	ldd		[%o0 + 0x80], %f18
+	AES_DROUND01(26, 0, 2, 4)
+	ldd		[%o0 + 0x78], %f20
+	AES_DROUND23(12, 4, 6, 2)
+	ldd		[%o0 + 0x70], %f22
+	AES_DROUND01(14, 4, 6, 0)
+	ldd		[%o0 + 0x68], %f24
+	AES_DROUND23(16, 0, 2, 6)
+	ldd		[%o0 + 0x60], %f26
+	AES_DROUND01(18, 0, 2, 4)
+	ldd		[%o0 + 0x58], %f28
+	AES_DROUND23(20, 4, 6, 2)
+	ldd		[%o0 + 0x50], %f30
+	AES_DROUND01(22, 4, 6, 0)
+	ldd		[%o0 + 0x48], %f32
+	AES_DROUND23(24, 0, 2, 6)
+	ldd		[%o0 + 0x40], %f34
+	AES_DROUND01(26, 0, 2, 4)
+	ldd		[%o0 + 0x38], %f36
+	AES_DROUND23(28, 4, 6, 2)
+	ldd		[%o0 + 0x30], %f38
+	AES_DROUND01(30, 4, 6, 0)
+	ldd		[%o0 + 0x28], %f40
+	AES_DROUND23(32, 0, 2, 6)
+	ldd		[%o0 + 0x20], %f42
+	AES_DROUND01(34, 0, 2, 4)
+	ldd		[%o0 + 0x18], %f44
+	AES_DROUND23(36, 4, 6, 2)
+	ldd		[%o0 + 0x10], %f46
+	AES_DROUND01(38, 4, 6, 0)
+	ldd		[%o0 + 0x08], %f48
+	AES_DROUND23(40, 0, 2, 6)
+	ldd		[%o0 + 0x00], %f50
+	AES_DROUND01(42, 0, 2, 4)
+	AES_DROUND23(44, 4, 6, 2)
+	AES_DROUND01(46, 4, 6, 0)
+	AES_DROUND23_L(48, 0, 2, 6)
+	AES_DROUND01_L(50, 0, 2, 4)
+	st		%f4, [%o2 + 0x00]
+	st		%f5, [%o2 + 0x04]
+	st		%f6, [%o2 + 0x08]
+	st		%f7, [%o2 + 0x0c]
+	retl
+	 VISExit
+ENDPROC(aes_sparc64_decrypt_256)
+
+	.align		32
+ENTRY(aes_sparc64_load_encrypt_keys_128)
+	/* %o0=key */
+	VISEntry
+	ldd		[%o0 + 0x10], %f8
+	ldd		[%o0 + 0x18], %f10
+	ldd		[%o0 + 0x20], %f12
+	ldd		[%o0 + 0x28], %f14
+	ldd		[%o0 + 0x30], %f16
+	ldd		[%o0 + 0x38], %f18
+	ldd		[%o0 + 0x40], %f20
+	ldd		[%o0 + 0x48], %f22
+	ldd		[%o0 + 0x50], %f24
+	ldd		[%o0 + 0x58], %f26
+	ldd		[%o0 + 0x60], %f28
+	ldd		[%o0 + 0x68], %f30
+	ldd		[%o0 + 0x70], %f32
+	ldd		[%o0 + 0x78], %f34
+	ldd		[%o0 + 0x80], %f36
+	ldd		[%o0 + 0x88], %f38
+	ldd		[%o0 + 0x90], %f40
+	ldd		[%o0 + 0x98], %f42
+	ldd		[%o0 + 0xa0], %f44
+	retl
+	 ldd		[%o0 + 0xa8], %f46
+ENDPROC(aes_sparc64_load_encrypt_keys_128)
+
+	.align		32
+ENTRY(aes_sparc64_load_encrypt_keys_192)
+	/* %o0=key */
+	VISEntry
+	ldd		[%o0 + 0x10], %f8
+	ldd		[%o0 + 0x18], %f10
+	ldd		[%o0 + 0x20], %f12
+	ldd		[%o0 + 0x28], %f14
+	ldd		[%o0 + 0x30], %f16
+	ldd		[%o0 + 0x38], %f18
+	ldd		[%o0 + 0x40], %f20
+	ldd		[%o0 + 0x48], %f22
+	ldd		[%o0 + 0x50], %f24
+	ldd		[%o0 + 0x58], %f26
+	ldd		[%o0 + 0x60], %f28
+	ldd		[%o0 + 0x68], %f30
+	ldd		[%o0 + 0x70], %f32
+	ldd		[%o0 + 0x78], %f34
+	ldd		[%o0 + 0x80], %f36
+	ldd		[%o0 + 0x88], %f38
+	ldd		[%o0 + 0x90], %f40
+	ldd		[%o0 + 0x98], %f42
+	ldd		[%o0 + 0xa0], %f44
+	ldd		[%o0 + 0xa8], %f46
+	ldd		[%o0 + 0xb0], %f48
+	ldd		[%o0 + 0xb8], %f50
+	ldd		[%o0 + 0xc0], %f52
+	retl
+	 ldd		[%o0 + 0xc8], %f54
+ENDPROC(aes_sparc64_load_encrypt_keys_192)
+
+	.align		32
+ENTRY(aes_sparc64_load_encrypt_keys_256)
+	/* %o0=key */
+	VISEntry
+	ldd		[%o0 + 0x10], %f8
+	ldd		[%o0 + 0x18], %f10
+	ldd		[%o0 + 0x20], %f12
+	ldd		[%o0 + 0x28], %f14
+	ldd		[%o0 + 0x30], %f16
+	ldd		[%o0 + 0x38], %f18
+	ldd		[%o0 + 0x40], %f20
+	ldd		[%o0 + 0x48], %f22
+	ldd		[%o0 + 0x50], %f24
+	ldd		[%o0 + 0x58], %f26
+	ldd		[%o0 + 0x60], %f28
+	ldd		[%o0 + 0x68], %f30
+	ldd		[%o0 + 0x70], %f32
+	ldd		[%o0 + 0x78], %f34
+	ldd		[%o0 + 0x80], %f36
+	ldd		[%o0 + 0x88], %f38
+	ldd		[%o0 + 0x90], %f40
+	ldd		[%o0 + 0x98], %f42
+	ldd		[%o0 + 0xa0], %f44
+	ldd		[%o0 + 0xa8], %f46
+	ldd		[%o0 + 0xb0], %f48
+	ldd		[%o0 + 0xb8], %f50
+	ldd		[%o0 + 0xc0], %f52
+	ldd		[%o0 + 0xc8], %f54
+	ldd		[%o0 + 0xd0], %f56
+	ldd		[%o0 + 0xd8], %f58
+	ldd		[%o0 + 0xe0], %f60
+	retl
+	 ldd		[%o0 + 0xe8], %f62
+ENDPROC(aes_sparc64_load_encrypt_keys_256)
+
+	.align		32
+ENTRY(aes_sparc64_load_decrypt_keys_128)
+	/* %o0=key */
+	VISEntry
+	ldd		[%o0 + 0x98], %f8
+	ldd		[%o0 + 0x90], %f10
+	ldd		[%o0 + 0x88], %f12
+	ldd		[%o0 + 0x80], %f14
+	ldd		[%o0 + 0x78], %f16
+	ldd		[%o0 + 0x70], %f18
+	ldd		[%o0 + 0x68], %f20
+	ldd		[%o0 + 0x60], %f22
+	ldd		[%o0 + 0x58], %f24
+	ldd		[%o0 + 0x50], %f26
+	ldd		[%o0 + 0x48], %f28
+	ldd		[%o0 + 0x40], %f30
+	ldd		[%o0 + 0x38], %f32
+	ldd		[%o0 + 0x30], %f34
+	ldd		[%o0 + 0x28], %f36
+	ldd		[%o0 + 0x20], %f38
+	ldd		[%o0 + 0x18], %f40
+	ldd		[%o0 + 0x10], %f42
+	ldd		[%o0 + 0x08], %f44
+	retl
+	 ldd		[%o0 + 0x00], %f46
+ENDPROC(aes_sparc64_load_decrypt_keys_128)
+
+	.align		32
+ENTRY(aes_sparc64_load_decrypt_keys_192)
+	/* %o0=key */
+	VISEntry
+	ldd		[%o0 + 0xb8], %f8
+	ldd		[%o0 + 0xb0], %f10
+	ldd		[%o0 + 0xa8], %f12
+	ldd		[%o0 + 0xa0], %f14
+	ldd		[%o0 + 0x98], %f16
+	ldd		[%o0 + 0x90], %f18
+	ldd		[%o0 + 0x88], %f20
+	ldd		[%o0 + 0x80], %f22
+	ldd		[%o0 + 0x78], %f24
+	ldd		[%o0 + 0x70], %f26
+	ldd		[%o0 + 0x68], %f28
+	ldd		[%o0 + 0x60], %f30
+	ldd		[%o0 + 0x58], %f32
+	ldd		[%o0 + 0x50], %f34
+	ldd		[%o0 + 0x48], %f36
+	ldd		[%o0 + 0x40], %f38
+	ldd		[%o0 + 0x38], %f40
+	ldd		[%o0 + 0x30], %f42
+	ldd		[%o0 + 0x28], %f44
+	ldd		[%o0 + 0x20], %f46
+	ldd		[%o0 + 0x18], %f48
+	ldd		[%o0 + 0x10], %f50
+	ldd		[%o0 + 0x08], %f52
+	retl
+	 ldd		[%o0 + 0x00], %f54
+ENDPROC(aes_sparc64_load_decrypt_keys_192)
+
+	.align		32
+ENTRY(aes_sparc64_load_decrypt_keys_256)
+	/* %o0=key */
+	VISEntry
+	ldd		[%o0 + 0xd8], %f8
+	ldd		[%o0 + 0xd0], %f10
+	ldd		[%o0 + 0xc8], %f12
+	ldd		[%o0 + 0xc0], %f14
+	ldd		[%o0 + 0xb8], %f16
+	ldd		[%o0 + 0xb0], %f18
+	ldd		[%o0 + 0xa8], %f20
+	ldd		[%o0 + 0xa0], %f22
+	ldd		[%o0 + 0x98], %f24
+	ldd		[%o0 + 0x90], %f26
+	ldd		[%o0 + 0x88], %f28
+	ldd		[%o0 + 0x80], %f30
+	ldd		[%o0 + 0x78], %f32
+	ldd		[%o0 + 0x70], %f34
+	ldd		[%o0 + 0x68], %f36
+	ldd		[%o0 + 0x60], %f38
+	ldd		[%o0 + 0x58], %f40
+	ldd		[%o0 + 0x50], %f42
+	ldd		[%o0 + 0x48], %f44
+	ldd		[%o0 + 0x40], %f46
+	ldd		[%o0 + 0x38], %f48
+	ldd		[%o0 + 0x30], %f50
+	ldd		[%o0 + 0x28], %f52
+	ldd		[%o0 + 0x20], %f54
+	ldd		[%o0 + 0x18], %f56
+	ldd		[%o0 + 0x10], %f58
+	ldd		[%o0 + 0x08], %f60
+	retl
+	 ldd		[%o0 + 0x00], %f62
+ENDPROC(aes_sparc64_load_decrypt_keys_256)
+
+	.align		32
+ENTRY(aes_sparc64_ecb_encrypt_128)
+	/* %o0=key, %o1=input, %o2=output, %o3=len */
+	ldx		[%o0 + 0x00], %g1
+	subcc		%o3, 0x10, %o3
+	be		10f
+	 ldx		[%o0 + 0x08], %g2
+1:	ldx		[%o1 + 0x00], %g3
+	ldx		[%o1 + 0x08], %g7
+	ldx		[%o1 + 0x10], %o4
+	ldx		[%o1 + 0x18], %o5
+	xor		%g1, %g3, %g3
+	xor		%g2, %g7, %g7
+	MOVXTOD_G3_F4
+	MOVXTOD_G7_F6
+	xor		%g1, %o4, %g3
+	xor		%g2, %o5, %g7
+	MOVXTOD_G3_F60
+	MOVXTOD_G7_F62
+	ENCRYPT_128_2(8, 4, 6, 60, 62, 0, 2, 56, 58)
+	std		%f4, [%o2 + 0x00]
+	std		%f6, [%o2 + 0x08]
+	std		%f60, [%o2 + 0x10]
+	std		%f62, [%o2 + 0x18]
+	sub		%o3, 0x20, %o3
+	add		%o1, 0x20, %o1
+	brgz		%o3, 1b
+	 add		%o2, 0x20, %o2
+	brlz,pt		%o3, 11f
+	 nop
+10:	ldx		[%o1 + 0x00], %g3
+	ldx		[%o1 + 0x08], %g7
+	xor		%g1, %g3, %g3
+	xor		%g2, %g7, %g7
+	MOVXTOD_G3_F4
+	MOVXTOD_G7_F6
+	ENCRYPT_128(8, 4, 6, 0, 2)
+	std		%f4, [%o2 + 0x00]
+	std		%f6, [%o2 + 0x08]
+11:	retl
+	 nop
+ENDPROC(aes_sparc64_ecb_encrypt_128)
+
+	.align		32
+ENTRY(aes_sparc64_ecb_encrypt_192)
+	/* %o0=key, %o1=input, %o2=output, %o3=len */
+	ldx		[%o0 + 0x00], %g1
+	subcc		%o3, 0x10, %o3
+	be		10f
+	 ldx		[%o0 + 0x08], %g2
+1:	ldx		[%o1 + 0x00], %g3
+	ldx		[%o1 + 0x08], %g7
+	ldx		[%o1 + 0x10], %o4
+	ldx		[%o1 + 0x18], %o5
+	xor		%g1, %g3, %g3
+	xor		%g2, %g7, %g7
+	MOVXTOD_G3_F4
+	MOVXTOD_G7_F6
+	xor		%g1, %o4, %g3
+	xor		%g2, %o5, %g7
+	MOVXTOD_G3_F60
+	MOVXTOD_G7_F62
+	ENCRYPT_192_2(8, 4, 6, 60, 62, 0, 2, 56, 58)
+	std		%f4, [%o2 + 0x00]
+	std		%f6, [%o2 + 0x08]
+	std		%f60, [%o2 + 0x10]
+	std		%f62, [%o2 + 0x18]
+	sub		%o3, 0x20, %o3
+	add		%o1, 0x20, %o1
+	brgz		%o3, 1b
+	 add		%o2, 0x20, %o2
+	brlz,pt		%o3, 11f
+	 nop
+10:	ldx		[%o1 + 0x00], %g3
+	ldx		[%o1 + 0x08], %g7
+	xor		%g1, %g3, %g3
+	xor		%g2, %g7, %g7
+	MOVXTOD_G3_F4
+	MOVXTOD_G7_F6
+	ENCRYPT_192(8, 4, 6, 0, 2)
+	std		%f4, [%o2 + 0x00]
+	std		%f6, [%o2 + 0x08]
+11:	retl
+	 nop
+ENDPROC(aes_sparc64_ecb_encrypt_192)
+
+	.align		32
+ENTRY(aes_sparc64_ecb_encrypt_256)
+	/* %o0=key, %o1=input, %o2=output, %o3=len */
+	ldx		[%o0 + 0x00], %g1
+	subcc		%o3, 0x10, %o3
+	be		10f
+	 ldx		[%o0 + 0x08], %g2
+1:	ldx		[%o1 + 0x00], %g3
+	ldx		[%o1 + 0x08], %g7
+	ldx		[%o1 + 0x10], %o4
+	ldx		[%o1 + 0x18], %o5
+	xor		%g1, %g3, %g3
+	xor		%g2, %g7, %g7
+	MOVXTOD_G3_F4
+	MOVXTOD_G7_F6
+	xor		%g1, %o4, %g3
+	xor		%g2, %o5, %g7
+	MOVXTOD_G3_F0
+	MOVXTOD_G7_F2
+	ENCRYPT_256_2(8, 4, 6, 0, 2)
+	std		%f4, [%o2 + 0x00]
+	std		%f6, [%o2 + 0x08]
+	std		%f0, [%o2 + 0x10]
+	std		%f2, [%o2 + 0x18]
+	sub		%o3, 0x20, %o3
+	add		%o1, 0x20, %o1
+	brgz		%o3, 1b
+	 add		%o2, 0x20, %o2
+	brlz,pt		%o3, 11f
+	 nop
+10:	ldx		[%o1 + 0x00], %g3
+	ldx		[%o1 + 0x08], %g7
+	xor		%g1, %g3, %g3
+	xor		%g2, %g7, %g7
+	MOVXTOD_G3_F4
+	MOVXTOD_G7_F6
+	ENCRYPT_256(8, 4, 6, 0, 2)
+	std		%f4, [%o2 + 0x00]
+	std		%f6, [%o2 + 0x08]
+11:	retl
+	 nop
+ENDPROC(aes_sparc64_ecb_encrypt_256)
+
+	.align		32
+ENTRY(aes_sparc64_ecb_decrypt_128)
+	/* %o0=&key[key_len], %o1=input, %o2=output, %o3=len */
+	ldx		[%o0 - 0x10], %g1
+	subcc		%o3, 0x10, %o3
+	be		10f
+	 ldx		[%o0 - 0x08], %g2
+1:	ldx		[%o1 + 0x00], %g3
+	ldx		[%o1 + 0x08], %g7
+	ldx		[%o1 + 0x10], %o4
+	ldx		[%o1 + 0x18], %o5
+	xor		%g1, %g3, %g3
+	xor		%g2, %g7, %g7
+	MOVXTOD_G3_F4
+	MOVXTOD_G7_F6
+	xor		%g1, %o4, %g3
+	xor		%g2, %o5, %g7
+	MOVXTOD_G3_F60
+	MOVXTOD_G7_F62
+	DECRYPT_128_2(8, 4, 6, 60, 62, 0, 2, 56, 58)
+	std		%f4, [%o2 + 0x00]
+	std		%f6, [%o2 + 0x08]
+	std		%f60, [%o2 + 0x10]
+	std		%f62, [%o2 + 0x18]
+	sub		%o3, 0x20, %o3
+	add		%o1, 0x20, %o1
+	brgz,pt		%o3, 1b
+	 add		%o2, 0x20, %o2
+	brlz,pt		%o3, 11f
+	 nop
+10:	ldx		[%o1 + 0x00], %g3
+	ldx		[%o1 + 0x08], %g7
+	xor		%g1, %g3, %g3
+	xor		%g2, %g7, %g7
+	MOVXTOD_G3_F4
+	MOVXTOD_G7_F6
+	DECRYPT_128(8, 4, 6, 0, 2)
+	std		%f4, [%o2 + 0x00]
+	std		%f6, [%o2 + 0x08]
+11:	retl
+	 nop
+ENDPROC(aes_sparc64_ecb_decrypt_128)
+
+	.align		32
+ENTRY(aes_sparc64_ecb_decrypt_192)
+	/* %o0=&key[key_len], %o1=input, %o2=output, %o3=len */
+	ldx		[%o0 - 0x10], %g1
+	subcc		%o3, 0x10, %o3
+	be		10f
+	 ldx		[%o0 - 0x08], %g2
+1:	ldx		[%o1 + 0x00], %g3
+	ldx		[%o1 + 0x08], %g7
+	ldx		[%o1 + 0x10], %o4
+	ldx		[%o1 + 0x18], %o5
+	xor		%g1, %g3, %g3
+	xor		%g2, %g7, %g7
+	MOVXTOD_G3_F4
+	MOVXTOD_G7_F6
+	xor		%g1, %o4, %g3
+	xor		%g2, %o5, %g7
+	MOVXTOD_G3_F60
+	MOVXTOD_G7_F62
+	DECRYPT_192_2(8, 4, 6, 60, 62, 0, 2, 56, 58)
+	std		%f4, [%o2 + 0x00]
+	std		%f6, [%o2 + 0x08]
+	std		%f60, [%o2 + 0x10]
+	std		%f62, [%o2 + 0x18]
+	sub		%o3, 0x20, %o3
+	add		%o1, 0x20, %o1
+	brgz,pt		%o3, 1b
+	 add		%o2, 0x20, %o2
+	brlz,pt		%o3, 11f
+	 nop
+10:	ldx		[%o1 + 0x00], %g3
+	ldx		[%o1 + 0x08], %g7
+	xor		%g1, %g3, %g3
+	xor		%g2, %g7, %g7
+	MOVXTOD_G3_F4
+	MOVXTOD_G7_F6
+	DECRYPT_192(8, 4, 6, 0, 2)
+	std		%f4, [%o2 + 0x00]
+	std		%f6, [%o2 + 0x08]
+11:	retl
+	 nop
+ENDPROC(aes_sparc64_ecb_decrypt_192)
+
+	.align		32
+ENTRY(aes_sparc64_ecb_decrypt_256)
+	/* %o0=&key[key_len], %o1=input, %o2=output, %o3=len */
+	ldx		[%o0 - 0x10], %g1
+	subcc		%o3, 0x10, %o3
+	be		10f
+	 ldx		[%o0 - 0x08], %g2
+	sub		%o0, 0xf0, %o0
+1:	ldx		[%o1 + 0x00], %g3
+	ldx		[%o1 + 0x08], %g7
+	ldx		[%o1 + 0x10], %o4
+	ldx		[%o1 + 0x18], %o5
+	xor		%g1, %g3, %g3
+	xor		%g2, %g7, %g7
+	MOVXTOD_G3_F4
+	MOVXTOD_G7_F6
+	xor		%g1, %o4, %g3
+	xor		%g2, %o5, %g7
+	MOVXTOD_G3_F0
+	MOVXTOD_G7_F2
+	DECRYPT_256_2(8, 4, 6, 0, 2)
+	std		%f4, [%o2 + 0x00]
+	std		%f6, [%o2 + 0x08]
+	std		%f0, [%o2 + 0x10]
+	std		%f2, [%o2 + 0x18]
+	sub		%o3, 0x20, %o3
+	add		%o1, 0x20, %o1
+	brgz,pt		%o3, 1b
+	 add		%o2, 0x20, %o2
+	brlz,pt		%o3, 11f
+	 nop
+10:	ldx		[%o1 + 0x00], %g3
+	ldx		[%o1 + 0x08], %g7
+	xor		%g1, %g3, %g3
+	xor		%g2, %g7, %g7
+	MOVXTOD_G3_F4
+	MOVXTOD_G7_F6
+	DECRYPT_256(8, 4, 6, 0, 2)
+	std		%f4, [%o2 + 0x00]
+	std		%f6, [%o2 + 0x08]
+11:	retl
+	 nop
+ENDPROC(aes_sparc64_ecb_decrypt_256)
+
+	.align		32
+ENTRY(aes_sparc64_cbc_encrypt_128)
+	/* %o0=key, %o1=input, %o2=output, %o3=len, %o4=IV */
+	ldd		[%o4 + 0x00], %f4
+	ldd		[%o4 + 0x08], %f6
+	ldx		[%o0 + 0x00], %g1
+	ldx		[%o0 + 0x08], %g2
+1:	ldx		[%o1 + 0x00], %g3
+	ldx		[%o1 + 0x08], %g7
+	add		%o1, 0x10, %o1
+	xor		%g1, %g3, %g3
+	xor		%g2, %g7, %g7
+	MOVXTOD_G3_F0
+	MOVXTOD_G7_F2
+	fxor		%f4, %f0, %f4
+	fxor		%f6, %f2, %f6
+	ENCRYPT_128(8, 4, 6, 0, 2)
+	std		%f4, [%o2 + 0x00]
+	std		%f6, [%o2 + 0x08]
+	subcc		%o3, 0x10, %o3
+	bne,pt		%xcc, 1b
+	 add		%o2, 0x10, %o2
+	std		%f4, [%o4 + 0x00]
+	std		%f6, [%o4 + 0x08]
+	retl
+	 nop
+ENDPROC(aes_sparc64_cbc_encrypt_128)
+
+	.align		32
+ENTRY(aes_sparc64_cbc_encrypt_192)
+	/* %o0=key, %o1=input, %o2=output, %o3=len, %o4=IV */
+	ldd		[%o4 + 0x00], %f4
+	ldd		[%o4 + 0x08], %f6
+	ldx		[%o0 + 0x00], %g1
+	ldx		[%o0 + 0x08], %g2
+1:	ldx		[%o1 + 0x00], %g3
+	ldx		[%o1 + 0x08], %g7
+	add		%o1, 0x10, %o1
+	xor		%g1, %g3, %g3
+	xor		%g2, %g7, %g7
+	MOVXTOD_G3_F0
+	MOVXTOD_G7_F2
+	fxor		%f4, %f0, %f4
+	fxor		%f6, %f2, %f6
+	ENCRYPT_192(8, 4, 6, 0, 2)
+	std		%f4, [%o2 + 0x00]
+	std		%f6, [%o2 + 0x08]
+	subcc		%o3, 0x10, %o3
+	bne,pt		%xcc, 1b
+	 add		%o2, 0x10, %o2
+	std		%f4, [%o4 + 0x00]
+	std		%f6, [%o4 + 0x08]
+	retl
+	 nop
+ENDPROC(aes_sparc64_cbc_encrypt_192)
+
+	.align		32
+ENTRY(aes_sparc64_cbc_encrypt_256)
+	/* %o0=key, %o1=input, %o2=output, %o3=len, %o4=IV */
+	ldd		[%o4 + 0x00], %f4
+	ldd		[%o4 + 0x08], %f6
+	ldx		[%o0 + 0x00], %g1
+	ldx		[%o0 + 0x08], %g2
+1:	ldx		[%o1 + 0x00], %g3
+	ldx		[%o1 + 0x08], %g7
+	add		%o1, 0x10, %o1
+	xor		%g1, %g3, %g3
+	xor		%g2, %g7, %g7
+	MOVXTOD_G3_F0
+	MOVXTOD_G7_F2
+	fxor		%f4, %f0, %f4
+	fxor		%f6, %f2, %f6
+	ENCRYPT_256(8, 4, 6, 0, 2)
+	std		%f4, [%o2 + 0x00]
+	std		%f6, [%o2 + 0x08]
+	subcc		%o3, 0x10, %o3
+	bne,pt		%xcc, 1b
+	 add		%o2, 0x10, %o2
+	std		%f4, [%o4 + 0x00]
+	std		%f6, [%o4 + 0x08]
+	retl
+	 nop
+ENDPROC(aes_sparc64_cbc_encrypt_256)
+
+	.align		32
+ENTRY(aes_sparc64_cbc_decrypt_128)
+	/* %o0=&key[key_len], %o1=input, %o2=output, %o3=len, %o4=iv */
+	ldx		[%o0 - 0x10], %g1
+	ldx		[%o0 - 0x08], %g2
+	ldx		[%o4 + 0x00], %o0
+	ldx		[%o4 + 0x08], %o5
+1:	ldx		[%o1 + 0x00], %g3
+	ldx		[%o1 + 0x08], %g7
+	add		%o1, 0x10, %o1
+	xor		%g1, %g3, %g3
+	xor		%g2, %g7, %g7
+	MOVXTOD_G3_F4
+	MOVXTOD_G7_F6
+	DECRYPT_128(8, 4, 6, 0, 2)
+	MOVXTOD_O0_F0
+	MOVXTOD_O5_F2
+	xor		%g1, %g3, %o0
+	xor		%g2, %g7, %o5
+	fxor		%f4, %f0, %f4
+	fxor		%f6, %f2, %f6
+	std		%f4, [%o2 + 0x00]
+	std		%f6, [%o2 + 0x08]
+	subcc		%o3, 0x10, %o3
+	bne,pt		%xcc, 1b
+	 add		%o2, 0x10, %o2
+	stx		%o0, [%o4 + 0x00]
+	stx		%o5, [%o4 + 0x08]
+	retl
+	 nop
+ENDPROC(aes_sparc64_cbc_decrypt_128)
+
+	.align		32
+ENTRY(aes_sparc64_cbc_decrypt_192)
+	/* %o0=&key[key_len], %o1=input, %o2=output, %o3=len, %o4=iv */
+	ldx		[%o0 - 0x10], %g1
+	ldx		[%o0 - 0x08], %g2
+	ldx		[%o4 + 0x00], %o0
+	ldx		[%o4 + 0x08], %o5
+1:	ldx		[%o1 + 0x00], %g3
+	ldx		[%o1 + 0x08], %g7
+	add		%o1, 0x10, %o1
+	xor		%g1, %g3, %g3
+	xor		%g2, %g7, %g7
+	MOVXTOD_G3_F4
+	MOVXTOD_G7_F6
+	DECRYPT_192(8, 4, 6, 0, 2)
+	MOVXTOD_O0_F0
+	MOVXTOD_O5_F2
+	xor		%g1, %g3, %o0
+	xor		%g2, %g7, %o5
+	fxor		%f4, %f0, %f4
+	fxor		%f6, %f2, %f6
+	std		%f4, [%o2 + 0x00]
+	std		%f6, [%o2 + 0x08]
+	subcc		%o3, 0x10, %o3
+	bne,pt		%xcc, 1b
+	 add		%o2, 0x10, %o2
+	stx		%o0, [%o4 + 0x00]
+	stx		%o5, [%o4 + 0x08]
+	retl
+	 nop
+ENDPROC(aes_sparc64_cbc_decrypt_192)
+
+	.align		32
+ENTRY(aes_sparc64_cbc_decrypt_256)
+	/* %o0=&key[key_len], %o1=input, %o2=output, %o3=len, %o4=iv */
+	ldx		[%o0 - 0x10], %g1
+	ldx		[%o0 - 0x08], %g2
+	ldx		[%o4 + 0x00], %o0
+	ldx		[%o4 + 0x08], %o5
+1:	ldx		[%o1 + 0x00], %g3
+	ldx		[%o1 + 0x08], %g7
+	add		%o1, 0x10, %o1
+	xor		%g1, %g3, %g3
+	xor		%g2, %g7, %g7
+	MOVXTOD_G3_F4
+	MOVXTOD_G7_F6
+	DECRYPT_256(8, 4, 6, 0, 2)
+	MOVXTOD_O0_F0
+	MOVXTOD_O5_F2
+	xor		%g1, %g3, %o0
+	xor		%g2, %g7, %o5
+	fxor		%f4, %f0, %f4
+	fxor		%f6, %f2, %f6
+	std		%f4, [%o2 + 0x00]
+	std		%f6, [%o2 + 0x08]
+	subcc		%o3, 0x10, %o3
+	bne,pt		%xcc, 1b
+	 add		%o2, 0x10, %o2
+	stx		%o0, [%o4 + 0x00]
+	stx		%o5, [%o4 + 0x08]
+	retl
+	 nop
+ENDPROC(aes_sparc64_cbc_decrypt_256)
+
+	.align		32
+ENTRY(aes_sparc64_ctr_crypt_128)
+	/* %o0=key, %o1=input, %o2=output, %o3=len, %o4=IV */
+	ldx		[%o4 + 0x00], %g3
+	ldx		[%o4 + 0x08], %g7
+	subcc		%o3, 0x10, %o3
+	ldx		[%o0 + 0x00], %g1
+	be		10f
+	 ldx		[%o0 + 0x08], %g2
+1:	xor		%g1, %g3, %o5
+	MOVXTOD_O5_F0
+	xor		%g2, %g7, %o5
+	MOVXTOD_O5_F2
+	add		%g7, 1, %g7
+	add		%g3, 1, %o5
+	movrz		%g7, %o5, %g3
+	xor		%g1, %g3, %o5
+	MOVXTOD_O5_F4
+	xor		%g2, %g7, %o5
+	MOVXTOD_O5_F6
+	add		%g7, 1, %g7
+	add		%g3, 1, %o5
+	movrz		%g7, %o5, %g3
+	ENCRYPT_128_2(8, 0, 2, 4, 6, 56, 58, 60, 62)
+	ldd		[%o1 + 0x00], %f56
+	ldd		[%o1 + 0x08], %f58
+	ldd		[%o1 + 0x10], %f60
+	ldd		[%o1 + 0x18], %f62
+	fxor		%f56, %f0, %f56
+	fxor		%f58, %f2, %f58
+	fxor		%f60, %f4, %f60
+	fxor		%f62, %f6, %f62
+	std		%f56, [%o2 + 0x00]
+	std		%f58, [%o2 + 0x08]
+	std		%f60, [%o2 + 0x10]
+	std		%f62, [%o2 + 0x18]
+	subcc		%o3, 0x20, %o3
+	add		%o1, 0x20, %o1
+	brgz		%o3, 1b
+	 add		%o2, 0x20, %o2
+	brlz,pt		%o3, 11f
+	 nop
+10:	xor		%g1, %g3, %o5
+	MOVXTOD_O5_F0
+	xor		%g2, %g7, %o5
+	MOVXTOD_O5_F2
+	add		%g7, 1, %g7
+	add		%g3, 1, %o5
+	movrz		%g7, %o5, %g3
+	ENCRYPT_128(8, 0, 2, 4, 6)
+	ldd		[%o1 + 0x00], %f4
+	ldd		[%o1 + 0x08], %f6
+	fxor		%f4, %f0, %f4
+	fxor		%f6, %f2, %f6
+	std		%f4, [%o2 + 0x00]
+	std		%f6, [%o2 + 0x08]
+11:	stx		%g3, [%o4 + 0x00]
+	retl
+	 stx		%g7, [%o4 + 0x08]
+ENDPROC(aes_sparc64_ctr_crypt_128)
+
+	.align		32
+ENTRY(aes_sparc64_ctr_crypt_192)
+	/* %o0=key, %o1=input, %o2=output, %o3=len, %o4=IV */
+	ldx		[%o4 + 0x00], %g3
+	ldx		[%o4 + 0x08], %g7
+	subcc		%o3, 0x10, %o3
+	ldx		[%o0 + 0x00], %g1
+	be		10f
+	 ldx		[%o0 + 0x08], %g2
+1:	xor		%g1, %g3, %o5
+	MOVXTOD_O5_F0
+	xor		%g2, %g7, %o5
+	MOVXTOD_O5_F2
+	add		%g7, 1, %g7
+	add		%g3, 1, %o5
+	movrz		%g7, %o5, %g3
+	xor		%g1, %g3, %o5
+	MOVXTOD_O5_F4
+	xor		%g2, %g7, %o5
+	MOVXTOD_O5_F6
+	add		%g7, 1, %g7
+	add		%g3, 1, %o5
+	movrz		%g7, %o5, %g3
+	ENCRYPT_192_2(8, 0, 2, 4, 6, 56, 58, 60, 62)
+	ldd		[%o1 + 0x00], %f56
+	ldd		[%o1 + 0x08], %f58
+	ldd		[%o1 + 0x10], %f60
+	ldd		[%o1 + 0x18], %f62
+	fxor		%f56, %f0, %f56
+	fxor		%f58, %f2, %f58
+	fxor		%f60, %f4, %f60
+	fxor		%f62, %f6, %f62
+	std		%f56, [%o2 + 0x00]
+	std		%f58, [%o2 + 0x08]
+	std		%f60, [%o2 + 0x10]
+	std		%f62, [%o2 + 0x18]
+	subcc		%o3, 0x20, %o3
+	add		%o1, 0x20, %o1
+	brgz		%o3, 1b
+	 add		%o2, 0x20, %o2
+	brlz,pt		%o3, 11f
+	 nop
+10:	xor		%g1, %g3, %o5
+	MOVXTOD_O5_F0
+	xor		%g2, %g7, %o5
+	MOVXTOD_O5_F2
+	add		%g7, 1, %g7
+	add		%g3, 1, %o5
+	movrz		%g7, %o5, %g3
+	ENCRYPT_192(8, 0, 2, 4, 6)
+	ldd		[%o1 + 0x00], %f4
+	ldd		[%o1 + 0x08], %f6
+	fxor		%f4, %f0, %f4
+	fxor		%f6, %f2, %f6
+	std		%f4, [%o2 + 0x00]
+	std		%f6, [%o2 + 0x08]
+11:	stx		%g3, [%o4 + 0x00]
+	retl
+	 stx		%g7, [%o4 + 0x08]
+ENDPROC(aes_sparc64_ctr_crypt_192)
+
+	.align		32
+ENTRY(aes_sparc64_ctr_crypt_256)
+	/* %o0=key, %o1=input, %o2=output, %o3=len, %o4=IV */
+	ldx		[%o4 + 0x00], %g3
+	ldx		[%o4 + 0x08], %g7
+	subcc		%o3, 0x10, %o3
+	ldx		[%o0 + 0x00], %g1
+	be		10f
+	 ldx		[%o0 + 0x08], %g2
+1:	xor		%g1, %g3, %o5
+	MOVXTOD_O5_F0
+	xor		%g2, %g7, %o5
+	MOVXTOD_O5_F2
+	add		%g7, 1, %g7
+	add		%g3, 1, %o5
+	movrz		%g7, %o5, %g3
+	xor		%g1, %g3, %o5
+	MOVXTOD_O5_F4
+	xor		%g2, %g7, %o5
+	MOVXTOD_O5_F6
+	add		%g7, 1, %g7
+	add		%g3, 1, %o5
+	movrz		%g7, %o5, %g3
+	ENCRYPT_256_2(8, 0, 2, 4, 6)
+	ldd		[%o1 + 0x00], %f56
+	ldd		[%o1 + 0x08], %f58
+	ldd		[%o1 + 0x10], %f60
+	ldd		[%o1 + 0x18], %f62
+	fxor		%f56, %f0, %f56
+	fxor		%f58, %f2, %f58
+	fxor		%f60, %f4, %f60
+	fxor		%f62, %f6, %f62
+	std		%f56, [%o2 + 0x00]
+	std		%f58, [%o2 + 0x08]
+	std		%f60, [%o2 + 0x10]
+	std		%f62, [%o2 + 0x18]
+	subcc		%o3, 0x20, %o3
+	add		%o1, 0x20, %o1
+	brgz		%o3, 1b
+	 add		%o2, 0x20, %o2
+	brlz,pt		%o3, 11f
+	 nop
+	ldd		[%o0 + 0xd0], %f56
+	ldd		[%o0 + 0xd8], %f58
+	ldd		[%o0 + 0xe0], %f60
+	ldd		[%o0 + 0xe8], %f62
+10:	xor		%g1, %g3, %o5
+	MOVXTOD_O5_F0
+	xor		%g2, %g7, %o5
+	MOVXTOD_O5_F2
+	add		%g7, 1, %g7
+	add		%g3, 1, %o5
+	movrz		%g7, %o5, %g3
+	ENCRYPT_256(8, 0, 2, 4, 6)
+	ldd		[%o1 + 0x00], %f4
+	ldd		[%o1 + 0x08], %f6
+	fxor		%f4, %f0, %f4
+	fxor		%f6, %f2, %f6
+	std		%f4, [%o2 + 0x00]
+	std		%f6, [%o2 + 0x08]
+11:	stx		%g3, [%o4 + 0x00]
+	retl
+	 stx		%g7, [%o4 + 0x08]
+ENDPROC(aes_sparc64_ctr_crypt_256)
diff --git a/arch/sparc/crypto/aes_glue.c b/arch/sparc/crypto/aes_glue.c
new file mode 100644
index 0000000..8f1c998
--- /dev/null
+++ b/arch/sparc/crypto/aes_glue.c
@@ -0,0 +1,477 @@
+/* Glue code for AES encryption optimized for sparc64 crypto opcodes.
+ *
+ * This is based largely upon arch/x86/crypto/aesni-intel_glue.c
+ *
+ * Copyright (C) 2008, Intel Corp.
+ *    Author: Huang Ying <ying.huang@intel.com>
+ *
+ * Added RFC4106 AES-GCM support for 128-bit keys under the AEAD
+ * interface for 64-bit kernels.
+ *    Authors: Adrian Hoban <adrian.hoban@intel.com>
+ *             Gabriele Paoloni <gabriele.paoloni@intel.com>
+ *             Tadeusz Struk (tadeusz.struk@intel.com)
+ *             Aidan O'Mahony (aidan.o.mahony@intel.com)
+ *    Copyright (c) 2010, Intel Corporation.
+ */
+
+#define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
+
+#include <linux/crypto.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/types.h>
+#include <crypto/algapi.h>
+#include <crypto/aes.h>
+
+#include <asm/fpumacro.h>
+#include <asm/pstate.h>
+#include <asm/elf.h>
+
+#include "opcodes.h"
+
+struct aes_ops {
+	void (*encrypt)(const u64 *key, const u32 *input, u32 *output);
+	void (*decrypt)(const u64 *key, const u32 *input, u32 *output);
+	void (*load_encrypt_keys)(const u64 *key);
+	void (*load_decrypt_keys)(const u64 *key);
+	void (*ecb_encrypt)(const u64 *key, const u64 *input, u64 *output,
+			    unsigned int len);
+	void (*ecb_decrypt)(const u64 *key, const u64 *input, u64 *output,
+			    unsigned int len);
+	void (*cbc_encrypt)(const u64 *key, const u64 *input, u64 *output,
+			    unsigned int len, u64 *iv);
+	void (*cbc_decrypt)(const u64 *key, const u64 *input, u64 *output,
+			    unsigned int len, u64 *iv);
+	void (*ctr_crypt)(const u64 *key, const u64 *input, u64 *output,
+			  unsigned int len, u64 *iv);
+};
+
+struct crypto_sparc64_aes_ctx {
+	struct aes_ops *ops;
+	u64 key[AES_MAX_KEYLENGTH / sizeof(u64)];
+	u32 key_length;
+	u32 expanded_key_length;
+};
+
+extern void aes_sparc64_encrypt_128(const u64 *key, const u32 *input,
+				    u32 *output);
+extern void aes_sparc64_encrypt_192(const u64 *key, const u32 *input,
+				    u32 *output);
+extern void aes_sparc64_encrypt_256(const u64 *key, const u32 *input,
+				    u32 *output);
+
+extern void aes_sparc64_decrypt_128(const u64 *key, const u32 *input,
+				    u32 *output);
+extern void aes_sparc64_decrypt_192(const u64 *key, const u32 *input,
+				    u32 *output);
+extern void aes_sparc64_decrypt_256(const u64 *key, const u32 *input,
+				    u32 *output);
+
+extern void aes_sparc64_load_encrypt_keys_128(const u64 *key);
+extern void aes_sparc64_load_encrypt_keys_192(const u64 *key);
+extern void aes_sparc64_load_encrypt_keys_256(const u64 *key);
+
+extern void aes_sparc64_load_decrypt_keys_128(const u64 *key);
+extern void aes_sparc64_load_decrypt_keys_192(const u64 *key);
+extern void aes_sparc64_load_decrypt_keys_256(const u64 *key);
+
+extern void aes_sparc64_ecb_encrypt_128(const u64 *key, const u64 *input,
+					u64 *output, unsigned int len);
+extern void aes_sparc64_ecb_encrypt_192(const u64 *key, const u64 *input,
+					u64 *output, unsigned int len);
+extern void aes_sparc64_ecb_encrypt_256(const u64 *key, const u64 *input,
+					u64 *output, unsigned int len);
+
+extern void aes_sparc64_ecb_decrypt_128(const u64 *key, const u64 *input,
+					u64 *output, unsigned int len);
+extern void aes_sparc64_ecb_decrypt_192(const u64 *key, const u64 *input,
+					u64 *output, unsigned int len);
+extern void aes_sparc64_ecb_decrypt_256(const u64 *key, const u64 *input,
+					u64 *output, unsigned int len);
+
+extern void aes_sparc64_cbc_encrypt_128(const u64 *key, const u64 *input,
+					u64 *output, unsigned int len,
+					u64 *iv);
+
+extern void aes_sparc64_cbc_encrypt_192(const u64 *key, const u64 *input,
+					u64 *output, unsigned int len,
+					u64 *iv);
+
+extern void aes_sparc64_cbc_encrypt_256(const u64 *key, const u64 *input,
+					u64 *output, unsigned int len,
+					u64 *iv);
+
+extern void aes_sparc64_cbc_decrypt_128(const u64 *key, const u64 *input,
+					u64 *output, unsigned int len,
+					u64 *iv);
+
+extern void aes_sparc64_cbc_decrypt_192(const u64 *key, const u64 *input,
+					u64 *output, unsigned int len,
+					u64 *iv);
+
+extern void aes_sparc64_cbc_decrypt_256(const u64 *key, const u64 *input,
+					u64 *output, unsigned int len,
+					u64 *iv);
+
+extern void aes_sparc64_ctr_crypt_128(const u64 *key, const u64 *input,
+				      u64 *output, unsigned int len,
+				      u64 *iv);
+extern void aes_sparc64_ctr_crypt_192(const u64 *key, const u64 *input,
+				      u64 *output, unsigned int len,
+				      u64 *iv);
+extern void aes_sparc64_ctr_crypt_256(const u64 *key, const u64 *input,
+				      u64 *output, unsigned int len,
+				      u64 *iv);
+
+struct aes_ops aes128_ops = {
+	.encrypt		= aes_sparc64_encrypt_128,
+	.decrypt		= aes_sparc64_decrypt_128,
+	.load_encrypt_keys	= aes_sparc64_load_encrypt_keys_128,
+	.load_decrypt_keys	= aes_sparc64_load_decrypt_keys_128,
+	.ecb_encrypt		= aes_sparc64_ecb_encrypt_128,
+	.ecb_decrypt		= aes_sparc64_ecb_decrypt_128,
+	.cbc_encrypt		= aes_sparc64_cbc_encrypt_128,
+	.cbc_decrypt		= aes_sparc64_cbc_decrypt_128,
+	.ctr_crypt		= aes_sparc64_ctr_crypt_128,
+};
+
+struct aes_ops aes192_ops = {
+	.encrypt		= aes_sparc64_encrypt_192,
+	.decrypt		= aes_sparc64_decrypt_192,
+	.load_encrypt_keys	= aes_sparc64_load_encrypt_keys_192,
+	.load_decrypt_keys	= aes_sparc64_load_decrypt_keys_192,
+	.ecb_encrypt		= aes_sparc64_ecb_encrypt_192,
+	.ecb_decrypt		= aes_sparc64_ecb_decrypt_192,
+	.cbc_encrypt		= aes_sparc64_cbc_encrypt_192,
+	.cbc_decrypt		= aes_sparc64_cbc_decrypt_192,
+	.ctr_crypt		= aes_sparc64_ctr_crypt_192,
+};
+
+struct aes_ops aes256_ops = {
+	.encrypt		= aes_sparc64_encrypt_256,
+	.decrypt		= aes_sparc64_decrypt_256,
+	.load_encrypt_keys	= aes_sparc64_load_encrypt_keys_256,
+	.load_decrypt_keys	= aes_sparc64_load_decrypt_keys_256,
+	.ecb_encrypt		= aes_sparc64_ecb_encrypt_256,
+	.ecb_decrypt		= aes_sparc64_ecb_decrypt_256,
+	.cbc_encrypt		= aes_sparc64_cbc_encrypt_256,
+	.cbc_decrypt		= aes_sparc64_cbc_decrypt_256,
+	.ctr_crypt		= aes_sparc64_ctr_crypt_256,
+};
+
+extern void aes_sparc64_key_expand(const u32 *in_key, u64 *output_key,
+				   unsigned int key_len);
+
+static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
+		       unsigned int key_len)
+{
+	struct crypto_sparc64_aes_ctx *ctx = crypto_tfm_ctx(tfm);
+	u32 *flags = &tfm->crt_flags;
+
+	switch (key_len) {
+	case AES_KEYSIZE_128:
+		ctx->expanded_key_length = 0xb0;
+		ctx->ops = &aes128_ops;
+		break;
+
+	case AES_KEYSIZE_192:
+		ctx->expanded_key_length = 0xd0;
+		ctx->ops = &aes192_ops;
+		break;
+
+	case AES_KEYSIZE_256:
+		ctx->expanded_key_length = 0xf0;
+		ctx->ops = &aes256_ops;
+		break;
+
+	default:
+		*flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+		return -EINVAL;
+	}
+
+	aes_sparc64_key_expand((const u32 *)in_key, &ctx->key[0], key_len);
+	ctx->key_length = key_len;
+
+	return 0;
+}
+
+static void aes_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
+{
+	struct crypto_sparc64_aes_ctx *ctx = crypto_tfm_ctx(tfm);
+
+	ctx->ops->encrypt(&ctx->key[0], (const u32 *) src, (u32 *) dst);
+}
+
+static void aes_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
+{
+	struct crypto_sparc64_aes_ctx *ctx = crypto_tfm_ctx(tfm);
+
+	ctx->ops->decrypt(&ctx->key[0], (const u32 *) src, (u32 *) dst);
+}
+
+#define AES_BLOCK_MASK	(~(AES_BLOCK_SIZE-1))
+
+static int ecb_encrypt(struct blkcipher_desc *desc,
+		       struct scatterlist *dst, struct scatterlist *src,
+		       unsigned int nbytes)
+{
+	struct crypto_sparc64_aes_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	struct blkcipher_walk walk;
+	int err;
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	err = blkcipher_walk_virt(desc, &walk);
+
+	ctx->ops->load_encrypt_keys(&ctx->key[0]);
+	while ((nbytes = walk.nbytes)) {
+		unsigned int block_len = nbytes & AES_BLOCK_MASK;
+
+		if (likely(block_len)) {
+			ctx->ops->ecb_encrypt(&ctx->key[0],
+					      (const u64 *)walk.src.virt.addr,
+					      (u64 *) walk.dst.virt.addr,
+					      block_len);
+		}
+		nbytes &= AES_BLOCK_SIZE - 1;
+		err = blkcipher_walk_done(desc, &walk, nbytes);
+	}
+	fprs_write(0);
+	return err;
+}
+
+static int ecb_decrypt(struct blkcipher_desc *desc,
+		       struct scatterlist *dst, struct scatterlist *src,
+		       unsigned int nbytes)
+{
+	struct crypto_sparc64_aes_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	struct blkcipher_walk walk;
+	u64 *key_end;
+	int err;
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	err = blkcipher_walk_virt(desc, &walk);
+
+	ctx->ops->load_decrypt_keys(&ctx->key[0]);
+	key_end = &ctx->key[ctx->expanded_key_length / sizeof(u64)];
+	while ((nbytes = walk.nbytes)) {
+		unsigned int block_len = nbytes & AES_BLOCK_MASK;
+
+		if (likely(block_len)) {
+			ctx->ops->ecb_decrypt(key_end,
+					      (const u64 *) walk.src.virt.addr,
+					      (u64 *) walk.dst.virt.addr, block_len);
+		}
+		nbytes &= AES_BLOCK_SIZE - 1;
+		err = blkcipher_walk_done(desc, &walk, nbytes);
+	}
+	fprs_write(0);
+
+	return err;
+}
+
+static int cbc_encrypt(struct blkcipher_desc *desc,
+		       struct scatterlist *dst, struct scatterlist *src,
+		       unsigned int nbytes)
+{
+	struct crypto_sparc64_aes_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	struct blkcipher_walk walk;
+	int err;
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	err = blkcipher_walk_virt(desc, &walk);
+
+	ctx->ops->load_encrypt_keys(&ctx->key[0]);
+	while ((nbytes = walk.nbytes)) {
+		unsigned int block_len = nbytes & AES_BLOCK_MASK;
+
+		if (likely(block_len)) {
+			ctx->ops->cbc_encrypt(&ctx->key[0],
+					      (const u64 *)walk.src.virt.addr,
+					      (u64 *) walk.dst.virt.addr,
+					      block_len, (u64 *) walk.iv);
+		}
+		nbytes &= AES_BLOCK_SIZE - 1;
+		err = blkcipher_walk_done(desc, &walk, nbytes);
+	}
+	fprs_write(0);
+	return err;
+}
+
+static int cbc_decrypt(struct blkcipher_desc *desc,
+		       struct scatterlist *dst, struct scatterlist *src,
+		       unsigned int nbytes)
+{
+	struct crypto_sparc64_aes_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	struct blkcipher_walk walk;
+	u64 *key_end;
+	int err;
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	err = blkcipher_walk_virt(desc, &walk);
+
+	ctx->ops->load_decrypt_keys(&ctx->key[0]);
+	key_end = &ctx->key[ctx->expanded_key_length / sizeof(u64)];
+	while ((nbytes = walk.nbytes)) {
+		unsigned int block_len = nbytes & AES_BLOCK_MASK;
+
+		if (likely(block_len)) {
+			ctx->ops->cbc_decrypt(key_end,
+					      (const u64 *) walk.src.virt.addr,
+					      (u64 *) walk.dst.virt.addr,
+					      block_len, (u64 *) walk.iv);
+		}
+		nbytes &= AES_BLOCK_SIZE - 1;
+		err = blkcipher_walk_done(desc, &walk, nbytes);
+	}
+	fprs_write(0);
+
+	return err;
+}
+
+static int ctr_crypt(struct blkcipher_desc *desc,
+		     struct scatterlist *dst, struct scatterlist *src,
+		     unsigned int nbytes)
+{
+	struct crypto_sparc64_aes_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	struct blkcipher_walk walk;
+	int err;
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	err = blkcipher_walk_virt(desc, &walk);
+
+	ctx->ops->load_encrypt_keys(&ctx->key[0]);
+	while ((nbytes = walk.nbytes)) {
+		unsigned int block_len = nbytes & AES_BLOCK_MASK;
+
+		if (likely(block_len)) {
+			ctx->ops->ctr_crypt(&ctx->key[0],
+					    (const u64 *)walk.src.virt.addr,
+					    (u64 *) walk.dst.virt.addr,
+					    block_len, (u64 *) walk.iv);
+		}
+		nbytes &= AES_BLOCK_SIZE - 1;
+		err = blkcipher_walk_done(desc, &walk, nbytes);
+	}
+	fprs_write(0);
+	return err;
+}
+
+static struct crypto_alg algs[] = { {
+	.cra_name		= "aes",
+	.cra_driver_name	= "aes-sparc64",
+	.cra_priority		= SPARC_CR_OPCODE_PRIORITY,
+	.cra_flags		= CRYPTO_ALG_TYPE_CIPHER,
+	.cra_blocksize		= AES_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct crypto_sparc64_aes_ctx),
+	.cra_alignmask		= 3,
+	.cra_module		= THIS_MODULE,
+	.cra_u	= {
+		.cipher	= {
+			.cia_min_keysize	= AES_MIN_KEY_SIZE,
+			.cia_max_keysize	= AES_MAX_KEY_SIZE,
+			.cia_setkey		= aes_set_key,
+			.cia_encrypt		= aes_encrypt,
+			.cia_decrypt		= aes_decrypt
+		}
+	}
+}, {
+	.cra_name		= "ecb(aes)",
+	.cra_driver_name	= "ecb-aes-sparc64",
+	.cra_priority		= SPARC_CR_OPCODE_PRIORITY,
+	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER,
+	.cra_blocksize		= AES_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct crypto_sparc64_aes_ctx),
+	.cra_alignmask		= 7,
+	.cra_type		= &crypto_blkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_u = {
+		.blkcipher = {
+			.min_keysize	= AES_MIN_KEY_SIZE,
+			.max_keysize	= AES_MAX_KEY_SIZE,
+			.setkey		= aes_set_key,
+			.encrypt	= ecb_encrypt,
+			.decrypt	= ecb_decrypt,
+		},
+	},
+}, {
+	.cra_name		= "cbc(aes)",
+	.cra_driver_name	= "cbc-aes-sparc64",
+	.cra_priority		= SPARC_CR_OPCODE_PRIORITY,
+	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER,
+	.cra_blocksize		= AES_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct crypto_sparc64_aes_ctx),
+	.cra_alignmask		= 7,
+	.cra_type		= &crypto_blkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_u = {
+		.blkcipher = {
+			.min_keysize	= AES_MIN_KEY_SIZE,
+			.max_keysize	= AES_MAX_KEY_SIZE,
+			.setkey		= aes_set_key,
+			.encrypt	= cbc_encrypt,
+			.decrypt	= cbc_decrypt,
+		},
+	},
+}, {
+	.cra_name		= "ctr(aes)",
+	.cra_driver_name	= "ctr-aes-sparc64",
+	.cra_priority		= SPARC_CR_OPCODE_PRIORITY,
+	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER,
+	.cra_blocksize		= AES_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct crypto_sparc64_aes_ctx),
+	.cra_alignmask		= 7,
+	.cra_type		= &crypto_blkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_u = {
+		.blkcipher = {
+			.min_keysize	= AES_MIN_KEY_SIZE,
+			.max_keysize	= AES_MAX_KEY_SIZE,
+			.setkey		= aes_set_key,
+			.encrypt	= ctr_crypt,
+			.decrypt	= ctr_crypt,
+		},
+	},
+} };
+
+static bool __init sparc64_has_aes_opcode(void)
+{
+	unsigned long cfr;
+
+	if (!(sparc64_elf_hwcap & HWCAP_SPARC_CRYPTO))
+		return false;
+
+	__asm__ __volatile__("rd %%asr26, %0" : "=r" (cfr));
+	if (!(cfr & CFR_AES))
+		return false;
+
+	return true;
+}
+
+static int __init aes_sparc64_mod_init(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(algs); i++)
+		INIT_LIST_HEAD(&algs[i].cra_list);
+
+	if (sparc64_has_aes_opcode()) {
+		pr_info("Using sparc64 aes opcodes optimized AES implementation\n");
+		return crypto_register_algs(algs, ARRAY_SIZE(algs));
+	}
+	pr_info("sparc64 aes opcodes not available.\n");
+	return -ENODEV;
+}
+
+static void __exit aes_sparc64_mod_fini(void)
+{
+	crypto_unregister_algs(algs, ARRAY_SIZE(algs));
+}
+
+module_init(aes_sparc64_mod_init);
+module_exit(aes_sparc64_mod_fini);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("AES Secure Hash Algorithm, sparc64 aes opcode accelerated");
+
+MODULE_ALIAS("aes");
diff --git a/arch/sparc/crypto/camellia_asm.S b/arch/sparc/crypto/camellia_asm.S
new file mode 100644
index 0000000..cc39553
--- /dev/null
+++ b/arch/sparc/crypto/camellia_asm.S
@@ -0,0 +1,563 @@
+#include <linux/linkage.h>
+#include <asm/visasm.h>
+
+#include "opcodes.h"
+
+#define CAMELLIA_6ROUNDS(KEY_BASE, I0, I1) \
+	CAMELLIA_F(KEY_BASE +  0, I1, I0, I1) \
+	CAMELLIA_F(KEY_BASE +  2, I0, I1, I0) \
+	CAMELLIA_F(KEY_BASE +  4, I1, I0, I1) \
+	CAMELLIA_F(KEY_BASE +  6, I0, I1, I0) \
+	CAMELLIA_F(KEY_BASE +  8, I1, I0, I1) \
+	CAMELLIA_F(KEY_BASE + 10, I0, I1, I0)
+
+#define CAMELLIA_6ROUNDS_FL_FLI(KEY_BASE, I0, I1) \
+	CAMELLIA_6ROUNDS(KEY_BASE, I0, I1) \
+	CAMELLIA_FL(KEY_BASE + 12, I0, I0) \
+	CAMELLIA_FLI(KEY_BASE + 14, I1, I1)
+
+	.data
+
+	.align	8
+SIGMA:	.xword	0xA09E667F3BCC908B
+	.xword	0xB67AE8584CAA73B2
+	.xword	0xC6EF372FE94F82BE
+	.xword	0x54FF53A5F1D36F1C
+	.xword	0x10E527FADE682D1D
+	.xword	0xB05688C2B3E6C1FD
+
+	.text
+
+	.align	32
+ENTRY(camellia_sparc64_key_expand)
+	/* %o0=in_key, %o1=encrypt_key, %o2=key_len, %o3=decrypt_key */
+	VISEntry
+	ld	[%o0 + 0x00], %f0	! i0, k[0]
+	ld	[%o0 + 0x04], %f1	! i1, k[1]
+	ld	[%o0 + 0x08], %f2	! i2, k[2]
+	ld	[%o0 + 0x0c], %f3	! i3, k[3]
+	std	%f0, [%o1 + 0x00]	! k[0, 1]
+	fsrc2	%f0, %f28
+	std	%f2, [%o1 + 0x08]	! k[2, 3]
+	cmp	%o2, 16
+	be	10f
+	 fsrc2	%f2, %f30
+
+	ld	[%o0 + 0x10], %f0
+	ld	[%o0 + 0x14], %f1
+	std	%f0, [%o1 + 0x20]	! k[8, 9]
+	cmp	%o2, 24
+	fone	%f10
+	be,a	1f
+	 fxor	%f10, %f0, %f2
+	ld	[%o0 + 0x18], %f2
+	ld	[%o0 + 0x1c], %f3
+1:
+	std	%f2, [%o1 + 0x28]	! k[10, 11]
+	fxor	%f28, %f0, %f0
+	fxor	%f30, %f2, %f2
+
+10:
+	sethi	%hi(SIGMA), %g3
+	or	%g3, %lo(SIGMA), %g3
+	ldd	[%g3 + 0x00], %f16
+	ldd	[%g3 + 0x08], %f18
+	ldd	[%g3 + 0x10], %f20
+	ldd	[%g3 + 0x18], %f22
+	ldd	[%g3 + 0x20], %f24
+	ldd	[%g3 + 0x28], %f26
+	CAMELLIA_F(16, 2, 0, 2)
+	CAMELLIA_F(18, 0, 2, 0)
+	fxor	%f28, %f0, %f0
+	fxor	%f30, %f2, %f2
+	CAMELLIA_F(20, 2, 0, 2)
+	CAMELLIA_F(22, 0, 2, 0)
+
+#define ROTL128(S01, S23, TMP1, TMP2, N)	\
+	srlx	S01, (64 - N), TMP1;		\
+	sllx	S01, N, S01;			\
+	srlx	S23, (64 - N), TMP2;		\
+	sllx	S23, N, S23;			\
+	or	S01, TMP2, S01;			\
+	or	S23, TMP1, S23
+
+	cmp	%o2, 16
+	bne	1f
+	 nop
+	/* 128-bit key */
+	std	%f0, [%o1 + 0x10]	! k[ 4,  5]
+	std	%f2, [%o1 + 0x18]	! k[ 6,  7]
+	MOVDTOX_F0_O4
+	MOVDTOX_F2_O5
+	ROTL128(%o4, %o5, %g2, %g3, 15)
+	stx	%o4, [%o1 + 0x30]	! k[12, 13]
+	stx	%o5, [%o1 + 0x38]	! k[14, 15]
+	ROTL128(%o4, %o5, %g2, %g3, 15)
+	stx	%o4, [%o1 + 0x40]	! k[16, 17]
+	stx	%o5, [%o1 + 0x48]	! k[18, 19]
+	ROTL128(%o4, %o5, %g2, %g3, 15)
+	stx	%o4, [%o1 + 0x60]	! k[24, 25]
+	ROTL128(%o4, %o5, %g2, %g3, 15)
+	stx	%o4, [%o1 + 0x70]	! k[28, 29]
+	stx	%o5, [%o1 + 0x78]	! k[30, 31]
+	ROTL128(%o4, %o5, %g2, %g3, 34)
+	stx	%o4, [%o1 + 0xa0]	! k[40, 41]
+	stx	%o5, [%o1 + 0xa8]	! k[42, 43]
+	ROTL128(%o4, %o5, %g2, %g3, 17)
+	stx	%o4, [%o1 + 0xc0]	! k[48, 49]
+	stx	%o5, [%o1 + 0xc8]	! k[50, 51]
+
+	ldx	[%o1 + 0x00], %o4	! k[ 0,  1]
+	ldx	[%o1 + 0x08], %o5	! k[ 2,  3]
+	ROTL128(%o4, %o5, %g2, %g3, 15)
+	stx	%o4, [%o1 + 0x20]	! k[ 8,  9]
+	stx	%o5, [%o1 + 0x28]	! k[10, 11]
+	ROTL128(%o4, %o5, %g2, %g3, 30)
+	stx	%o4, [%o1 + 0x50]	! k[20, 21]
+	stx	%o5, [%o1 + 0x58]	! k[22, 23]
+	ROTL128(%o4, %o5, %g2, %g3, 15)
+	stx	%o5, [%o1 + 0x68]	! k[26, 27]
+	ROTL128(%o4, %o5, %g2, %g3, 17)
+	stx	%o4, [%o1 + 0x80]	! k[32, 33]
+	stx	%o5, [%o1 + 0x88]	! k[34, 35]
+	ROTL128(%o4, %o5, %g2, %g3, 17)
+	stx	%o4, [%o1 + 0x90]	! k[36, 37]
+	stx	%o5, [%o1 + 0x98]	! k[38, 39]
+	ROTL128(%o4, %o5, %g2, %g3, 17)
+	stx	%o4, [%o1 + 0xb0]	! k[44, 45]
+	stx	%o5, [%o1 + 0xb8]	! k[46, 47]
+
+	ba,pt	%xcc, 2f
+	 mov	(3 * 16 * 4), %o0
+
+1:
+	/* 192-bit or 256-bit key */
+	std	%f0, [%o1 + 0x30]	! k[12, 13]
+	std	%f2, [%o1 + 0x38]	! k[14, 15]
+	ldd	[%o1 + 0x20], %f4	! k[ 8,  9]
+	ldd	[%o1 + 0x28], %f6	! k[10, 11]
+	fxor	%f0, %f4, %f0
+	fxor	%f2, %f6, %f2
+	CAMELLIA_F(24, 2, 0, 2)
+	CAMELLIA_F(26, 0, 2, 0)
+	std	%f0, [%o1 + 0x10]	! k[ 4,  5]
+	std	%f2, [%o1 + 0x18]	! k[ 6,  7]
+	MOVDTOX_F0_O4
+	MOVDTOX_F2_O5
+	ROTL128(%o4, %o5, %g2, %g3, 30)
+	stx	%o4, [%o1 + 0x50]	! k[20, 21]
+	stx	%o5, [%o1 + 0x58]	! k[22, 23]
+	ROTL128(%o4, %o5, %g2, %g3, 30)
+	stx	%o4, [%o1 + 0xa0]	! k[40, 41]
+	stx	%o5, [%o1 + 0xa8]	! k[42, 43]
+	ROTL128(%o4, %o5, %g2, %g3, 51)
+	stx	%o4, [%o1 + 0x100]	! k[64, 65]
+	stx	%o5, [%o1 + 0x108]	! k[66, 67]
+	ldx	[%o1 + 0x20], %o4	! k[ 8,  9]
+	ldx	[%o1 + 0x28], %o5	! k[10, 11]
+	ROTL128(%o4, %o5, %g2, %g3, 15)
+	stx	%o4, [%o1 + 0x20]	! k[ 8,  9]
+	stx	%o5, [%o1 + 0x28]	! k[10, 11]
+	ROTL128(%o4, %o5, %g2, %g3, 15)
+	stx	%o4, [%o1 + 0x40]	! k[16, 17]
+	stx	%o5, [%o1 + 0x48]	! k[18, 19]
+	ROTL128(%o4, %o5, %g2, %g3, 30)
+	stx	%o4, [%o1 + 0x90]	! k[36, 37]
+	stx	%o5, [%o1 + 0x98]	! k[38, 39]
+	ROTL128(%o4, %o5, %g2, %g3, 34)
+	stx	%o4, [%o1 + 0xd0]	! k[52, 53]
+	stx	%o5, [%o1 + 0xd8]	! k[54, 55]
+	ldx	[%o1 + 0x30], %o4	! k[12, 13]
+	ldx	[%o1 + 0x38], %o5	! k[14, 15]
+	ROTL128(%o4, %o5, %g2, %g3, 15)
+	stx	%o4, [%o1 + 0x30]	! k[12, 13]
+	stx	%o5, [%o1 + 0x38]	! k[14, 15]
+	ROTL128(%o4, %o5, %g2, %g3, 30)
+	stx	%o4, [%o1 + 0x70]	! k[28, 29]
+	stx	%o5, [%o1 + 0x78]	! k[30, 31]
+	srlx	%o4, 32, %g2
+	srlx	%o5, 32, %g3
+	stw	%o4, [%o1 + 0xc0]	! k[48]
+	stw	%g3, [%o1 + 0xc4]	! k[49]
+	stw	%o5, [%o1 + 0xc8]	! k[50]
+	stw	%g2, [%o1 + 0xcc]	! k[51]
+	ROTL128(%o4, %o5, %g2, %g3, 49)
+	stx	%o4, [%o1 + 0xe0]	! k[56, 57]
+	stx	%o5, [%o1 + 0xe8]	! k[58, 59]
+	ldx	[%o1 + 0x00], %o4	! k[ 0,  1]
+	ldx	[%o1 + 0x08], %o5	! k[ 2,  3]
+	ROTL128(%o4, %o5, %g2, %g3, 45)
+	stx	%o4, [%o1 + 0x60]	! k[24, 25]
+	stx	%o5, [%o1 + 0x68]	! k[26, 27]
+	ROTL128(%o4, %o5, %g2, %g3, 15)
+	stx	%o4, [%o1 + 0x80]	! k[32, 33]
+	stx	%o5, [%o1 + 0x88]	! k[34, 35]
+	ROTL128(%o4, %o5, %g2, %g3, 17)
+	stx	%o4, [%o1 + 0xb0]	! k[44, 45]
+	stx	%o5, [%o1 + 0xb8]	! k[46, 47]
+	ROTL128(%o4, %o5, %g2, %g3, 34)
+	stx	%o4, [%o1 + 0xf0]	! k[60, 61]
+	stx	%o5, [%o1 + 0xf8]	! k[62, 63]
+	mov	(4 * 16 * 4), %o0
+2:
+	add	%o1, %o0, %o1
+	ldd	[%o1 + 0x00], %f0
+	ldd	[%o1 + 0x08], %f2
+	std	%f0, [%o3 + 0x00]
+	std	%f2, [%o3 + 0x08]
+	add	%o3, 0x10, %o3
+1:
+	sub	%o1, (16 * 4), %o1
+	ldd	[%o1 + 0x38], %f0
+	ldd	[%o1 + 0x30], %f2
+	ldd	[%o1 + 0x28], %f4
+	ldd	[%o1 + 0x20], %f6
+	ldd	[%o1 + 0x18], %f8
+	ldd	[%o1 + 0x10], %f10
+	std	%f0, [%o3 + 0x00]
+	std	%f2, [%o3 + 0x08]
+	std	%f4, [%o3 + 0x10]
+	std	%f6, [%o3 + 0x18]
+	std	%f8, [%o3 + 0x20]
+	std	%f10, [%o3 + 0x28]
+
+	ldd	[%o1 + 0x08], %f0
+	ldd	[%o1 + 0x00], %f2
+	std	%f0, [%o3 + 0x30]
+	std	%f2, [%o3 + 0x38]
+	subcc	%o0, (16 * 4), %o0
+	bne,pt	%icc, 1b
+	 add	%o3, (16 * 4), %o3
+
+	std	%f2, [%o3 - 0x10]
+	std	%f0, [%o3 - 0x08]
+
+	retl
+	 VISExit
+ENDPROC(camellia_sparc64_key_expand)
+
+	.align	32
+ENTRY(camellia_sparc64_crypt)
+	/* %o0=key, %o1=input, %o2=output, %o3=key_len */
+	VISEntry
+
+	ld	[%o1 + 0x00], %f0
+	ld	[%o1 + 0x04], %f1
+	ld	[%o1 + 0x08], %f2
+	ld	[%o1 + 0x0c], %f3
+
+	ldd	[%o0 + 0x00], %f4
+	ldd	[%o0 + 0x08], %f6
+
+	cmp	%o3, 16
+	fxor	%f4, %f0, %f0
+	be	1f
+	 fxor	%f6, %f2, %f2
+
+	ldd	[%o0 + 0x10], %f8
+	ldd	[%o0 + 0x18], %f10
+	ldd	[%o0 + 0x20], %f12
+	ldd	[%o0 + 0x28], %f14
+	ldd	[%o0 + 0x30], %f16
+	ldd	[%o0 + 0x38], %f18
+	ldd	[%o0 + 0x40], %f20
+	ldd	[%o0 + 0x48], %f22
+	add	%o0, 0x40, %o0
+
+	CAMELLIA_6ROUNDS_FL_FLI( 8, 0, 2)
+
+1:
+	ldd	[%o0 + 0x10], %f8
+	ldd	[%o0 + 0x18], %f10
+	ldd	[%o0 + 0x20], %f12
+	ldd	[%o0 + 0x28], %f14
+	ldd	[%o0 + 0x30], %f16
+	ldd	[%o0 + 0x38], %f18
+	ldd	[%o0 + 0x40], %f20
+	ldd	[%o0 + 0x48], %f22
+	ldd	[%o0 + 0x50], %f24
+	ldd	[%o0 + 0x58], %f26
+	ldd	[%o0 + 0x60], %f28
+	ldd	[%o0 + 0x68], %f30
+	ldd	[%o0 + 0x70], %f32
+	ldd	[%o0 + 0x78], %f34
+	ldd	[%o0 + 0x80], %f36
+	ldd	[%o0 + 0x88], %f38
+	ldd	[%o0 + 0x90], %f40
+	ldd	[%o0 + 0x98], %f42
+	ldd	[%o0 + 0xa0], %f44
+	ldd	[%o0 + 0xa8], %f46
+	ldd	[%o0 + 0xb0], %f48
+	ldd	[%o0 + 0xb8], %f50
+	ldd	[%o0 + 0xc0], %f52
+	ldd	[%o0 + 0xc8], %f54
+
+	CAMELLIA_6ROUNDS_FL_FLI( 8, 0, 2)
+	CAMELLIA_6ROUNDS_FL_FLI(24, 0, 2)
+	CAMELLIA_6ROUNDS(40, 0, 2)
+	fxor	%f52, %f2, %f2
+	fxor	%f54, %f0, %f0
+
+	st	%f2, [%o2 + 0x00]
+	st	%f3, [%o2 + 0x04]
+	st	%f0, [%o2 + 0x08]
+	st	%f1, [%o2 + 0x0c]
+
+	retl
+	 VISExit
+ENDPROC(camellia_sparc64_crypt)
+
+	.align	32
+ENTRY(camellia_sparc64_load_keys)
+	/* %o0=key, %o1=key_len */
+	VISEntry
+	ldd	[%o0 + 0x00], %f4
+	ldd	[%o0 + 0x08], %f6
+	ldd	[%o0 + 0x10], %f8
+	ldd	[%o0 + 0x18], %f10
+	ldd	[%o0 + 0x20], %f12
+	ldd	[%o0 + 0x28], %f14
+	ldd	[%o0 + 0x30], %f16
+	ldd	[%o0 + 0x38], %f18
+	ldd	[%o0 + 0x40], %f20
+	ldd	[%o0 + 0x48], %f22
+	ldd	[%o0 + 0x50], %f24
+	ldd	[%o0 + 0x58], %f26
+	ldd	[%o0 + 0x60], %f28
+	ldd	[%o0 + 0x68], %f30
+	ldd	[%o0 + 0x70], %f32
+	ldd	[%o0 + 0x78], %f34
+	ldd	[%o0 + 0x80], %f36
+	ldd	[%o0 + 0x88], %f38
+	ldd	[%o0 + 0x90], %f40
+	ldd	[%o0 + 0x98], %f42
+	ldd	[%o0 + 0xa0], %f44
+	ldd	[%o0 + 0xa8], %f46
+	ldd	[%o0 + 0xb0], %f48
+	ldd	[%o0 + 0xb8], %f50
+	ldd	[%o0 + 0xc0], %f52
+	retl
+	 ldd	[%o0 + 0xc8], %f54
+ENDPROC(camellia_sparc64_load_keys)
+
+	.align	32
+ENTRY(camellia_sparc64_ecb_crypt_3_grand_rounds)
+	/* %o0=input, %o1=output, %o2=len, %o3=key */
+1:	ldd	[%o0 + 0x00], %f0
+	ldd	[%o0 + 0x08], %f2
+	add	%o0, 0x10, %o0
+	fxor	%f4, %f0, %f0
+	fxor	%f6, %f2, %f2
+	CAMELLIA_6ROUNDS_FL_FLI( 8, 0, 2)
+	CAMELLIA_6ROUNDS_FL_FLI(24, 0, 2)
+	CAMELLIA_6ROUNDS(40, 0, 2)
+	fxor	%f52, %f2, %f2
+	fxor	%f54, %f0, %f0
+	std	%f2, [%o1 + 0x00]
+	std	%f0, [%o1 + 0x08]
+	subcc	%o2, 0x10, %o2
+	bne,pt	%icc, 1b
+	 add	%o1, 0x10, %o1
+	retl
+	 nop
+ENDPROC(camellia_sparc64_ecb_crypt_3_grand_rounds)
+
+	.align	32
+ENTRY(camellia_sparc64_ecb_crypt_4_grand_rounds)
+	/* %o0=input, %o1=output, %o2=len, %o3=key */
+1:	ldd	[%o0 + 0x00], %f0
+	ldd	[%o0 + 0x08], %f2
+	add	%o0, 0x10, %o0
+	fxor	%f4, %f0, %f0
+	fxor	%f6, %f2, %f2
+	CAMELLIA_6ROUNDS_FL_FLI( 8, 0, 2)
+	ldd	[%o3 + 0xd0], %f8
+	ldd	[%o3 + 0xd8], %f10
+	ldd	[%o3 + 0xe0], %f12
+	ldd	[%o3 + 0xe8], %f14
+	ldd	[%o3 + 0xf0], %f16
+	ldd	[%o3 + 0xf8], %f18
+	ldd	[%o3 + 0x100], %f20
+	ldd	[%o3 + 0x108], %f22
+	CAMELLIA_6ROUNDS_FL_FLI(24, 0, 2)
+	CAMELLIA_6ROUNDS_FL_FLI(40, 0, 2)
+	CAMELLIA_F(8, 2, 0, 2)
+	CAMELLIA_F(10, 0, 2, 0)
+	ldd	[%o3 + 0x10], %f8
+	ldd	[%o3 + 0x18], %f10
+	CAMELLIA_F(12, 2, 0, 2)
+	CAMELLIA_F(14, 0, 2, 0)
+	ldd	[%o3 + 0x20], %f12
+	ldd	[%o3 + 0x28], %f14
+	CAMELLIA_F(16, 2, 0, 2)
+	CAMELLIA_F(18, 0, 2, 0)
+	ldd	[%o3 + 0x30], %f16
+	ldd	[%o3 + 0x38], %f18
+	fxor	%f20, %f2, %f2
+	fxor	%f22, %f0, %f0
+	ldd	[%o3 + 0x40], %f20
+	ldd	[%o3 + 0x48], %f22
+	std	%f2, [%o1 + 0x00]
+	std	%f0, [%o1 + 0x08]
+	subcc	%o2, 0x10, %o2
+	bne,pt	%icc, 1b
+	 add	%o1, 0x10, %o1
+	retl
+	 nop
+ENDPROC(camellia_sparc64_ecb_crypt_4_grand_rounds)
+
+	.align	32
+ENTRY(camellia_sparc64_cbc_encrypt_3_grand_rounds)
+	/* %o0=input, %o1=output, %o2=len, %o3=key, %o4=IV */
+	ldd	[%o4 + 0x00], %f60
+	ldd	[%o4 + 0x08], %f62
+1:	ldd	[%o0 + 0x00], %f0
+	ldd	[%o0 + 0x08], %f2
+	add	%o0, 0x10, %o0
+	fxor	%f60, %f0, %f0
+	fxor	%f62, %f2, %f2
+	fxor	%f4, %f0, %f0
+	fxor	%f6, %f2, %f2
+	CAMELLIA_6ROUNDS_FL_FLI( 8, 0, 2)
+	CAMELLIA_6ROUNDS_FL_FLI(24, 0, 2)
+	CAMELLIA_6ROUNDS(40, 0, 2)
+	fxor	%f52, %f2, %f60
+	fxor	%f54, %f0, %f62
+	std	%f60, [%o1 + 0x00]
+	std	%f62, [%o1 + 0x08]
+	subcc	%o2, 0x10, %o2
+	bne,pt	%icc, 1b
+	 add	%o1, 0x10, %o1
+	std	%f60, [%o4 + 0x00]
+	retl
+	 std	%f62, [%o4 + 0x08]
+ENDPROC(camellia_sparc64_cbc_encrypt_3_grand_rounds)
+
+	.align	32
+ENTRY(camellia_sparc64_cbc_encrypt_4_grand_rounds)
+	/* %o0=input, %o1=output, %o2=len, %o3=key, %o4=IV */
+	ldd	[%o4 + 0x00], %f60
+	ldd	[%o4 + 0x08], %f62
+1:	ldd	[%o0 + 0x00], %f0
+	ldd	[%o0 + 0x08], %f2
+	add	%o0, 0x10, %o0
+	fxor	%f60, %f0, %f0
+	fxor	%f62, %f2, %f2
+	fxor	%f4, %f0, %f0
+	fxor	%f6, %f2, %f2
+	CAMELLIA_6ROUNDS_FL_FLI( 8, 0, 2)
+	ldd	[%o3 + 0xd0], %f8
+	ldd	[%o3 + 0xd8], %f10
+	ldd	[%o3 + 0xe0], %f12
+	ldd	[%o3 + 0xe8], %f14
+	ldd	[%o3 + 0xf0], %f16
+	ldd	[%o3 + 0xf8], %f18
+	ldd	[%o3 + 0x100], %f20
+	ldd	[%o3 + 0x108], %f22
+	CAMELLIA_6ROUNDS_FL_FLI(24, 0, 2)
+	CAMELLIA_6ROUNDS_FL_FLI(40, 0, 2)
+	CAMELLIA_F(8, 2, 0, 2)
+	CAMELLIA_F(10, 0, 2, 0)
+	ldd	[%o3 + 0x10], %f8
+	ldd	[%o3 + 0x18], %f10
+	CAMELLIA_F(12, 2, 0, 2)
+	CAMELLIA_F(14, 0, 2, 0)
+	ldd	[%o3 + 0x20], %f12
+	ldd	[%o3 + 0x28], %f14
+	CAMELLIA_F(16, 2, 0, 2)
+	CAMELLIA_F(18, 0, 2, 0)
+	ldd	[%o3 + 0x30], %f16
+	ldd	[%o3 + 0x38], %f18
+	fxor	%f20, %f2, %f60
+	fxor	%f22, %f0, %f62
+	ldd	[%o3 + 0x40], %f20
+	ldd	[%o3 + 0x48], %f22
+	std	%f60, [%o1 + 0x00]
+	std	%f62, [%o1 + 0x08]
+	subcc	%o2, 0x10, %o2
+	bne,pt	%icc, 1b
+	 add	%o1, 0x10, %o1
+	std	%f60, [%o4 + 0x00]
+	retl
+	 std	%f62, [%o4 + 0x08]
+ENDPROC(camellia_sparc64_cbc_encrypt_4_grand_rounds)
+
+	.align	32
+ENTRY(camellia_sparc64_cbc_decrypt_3_grand_rounds)
+	/* %o0=input, %o1=output, %o2=len, %o3=key, %o4=IV */
+	ldd	[%o4 + 0x00], %f60
+	ldd	[%o4 + 0x08], %f62
+1:	ldd	[%o0 + 0x00], %f56
+	ldd	[%o0 + 0x08], %f58
+	add	%o0, 0x10, %o0
+	fxor	%f4, %f56, %f0
+	fxor	%f6, %f58, %f2
+	CAMELLIA_6ROUNDS_FL_FLI( 8, 0, 2)
+	CAMELLIA_6ROUNDS_FL_FLI(24, 0, 2)
+	CAMELLIA_6ROUNDS(40, 0, 2)
+	fxor	%f52, %f2, %f2
+	fxor	%f54, %f0, %f0
+	fxor	%f60, %f2, %f2
+	fxor	%f62, %f0, %f0
+	fsrc2	%f56, %f60
+	fsrc2	%f58, %f62
+	std	%f2, [%o1 + 0x00]
+	std	%f0, [%o1 + 0x08]
+	subcc	%o2, 0x10, %o2
+	bne,pt	%icc, 1b
+	 add	%o1, 0x10, %o1
+	std	%f60, [%o4 + 0x00]
+	retl
+	 std	%f62, [%o4 + 0x08]
+ENDPROC(camellia_sparc64_cbc_decrypt_3_grand_rounds)
+
+	.align	32
+ENTRY(camellia_sparc64_cbc_decrypt_4_grand_rounds)
+	/* %o0=input, %o1=output, %o2=len, %o3=key, %o4=IV */
+	ldd	[%o4 + 0x00], %f60
+	ldd	[%o4 + 0x08], %f62
+1:	ldd	[%o0 + 0x00], %f56
+	ldd	[%o0 + 0x08], %f58
+	add	%o0, 0x10, %o0
+	fxor	%f4, %f56, %f0
+	fxor	%f6, %f58, %f2
+	CAMELLIA_6ROUNDS_FL_FLI( 8, 0, 2)
+	ldd	[%o3 + 0xd0], %f8
+	ldd	[%o3 + 0xd8], %f10
+	ldd	[%o3 + 0xe0], %f12
+	ldd	[%o3 + 0xe8], %f14
+	ldd	[%o3 + 0xf0], %f16
+	ldd	[%o3 + 0xf8], %f18
+	ldd	[%o3 + 0x100], %f20
+	ldd	[%o3 + 0x108], %f22
+	CAMELLIA_6ROUNDS_FL_FLI(24, 0, 2)
+	CAMELLIA_6ROUNDS_FL_FLI(40, 0, 2)
+	CAMELLIA_F(8, 2, 0, 2)
+	CAMELLIA_F(10, 0, 2, 0)
+	ldd	[%o3 + 0x10], %f8
+	ldd	[%o3 + 0x18], %f10
+	CAMELLIA_F(12, 2, 0, 2)
+	CAMELLIA_F(14, 0, 2, 0)
+	ldd	[%o3 + 0x20], %f12
+	ldd	[%o3 + 0x28], %f14
+	CAMELLIA_F(16, 2, 0, 2)
+	CAMELLIA_F(18, 0, 2, 0)
+	ldd	[%o3 + 0x30], %f16
+	ldd	[%o3 + 0x38], %f18
+	fxor	%f20, %f2, %f2
+	fxor	%f22, %f0, %f0
+	ldd	[%o3 + 0x40], %f20
+	ldd	[%o3 + 0x48], %f22
+	fxor	%f60, %f2, %f2
+	fxor	%f62, %f0, %f0
+	fsrc2	%f56, %f60
+	fsrc2	%f58, %f62
+	std	%f2, [%o1 + 0x00]
+	std	%f0, [%o1 + 0x08]
+	subcc	%o2, 0x10, %o2
+	bne,pt	%icc, 1b
+	 add	%o1, 0x10, %o1
+	std	%f60, [%o4 + 0x00]
+	retl
+	 std	%f62, [%o4 + 0x08]
+ENDPROC(camellia_sparc64_cbc_decrypt_4_grand_rounds)
diff --git a/arch/sparc/crypto/camellia_glue.c b/arch/sparc/crypto/camellia_glue.c
new file mode 100644
index 0000000..42905c0
--- /dev/null
+++ b/arch/sparc/crypto/camellia_glue.c
@@ -0,0 +1,322 @@
+/* Glue code for CAMELLIA encryption optimized for sparc64 crypto opcodes.
+ *
+ * Copyright (C) 2012 David S. Miller <davem@davemloft.net>
+ */
+
+#define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
+
+#include <linux/crypto.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/types.h>
+#include <crypto/algapi.h>
+
+#include <asm/fpumacro.h>
+#include <asm/pstate.h>
+#include <asm/elf.h>
+
+#include "opcodes.h"
+
+#define CAMELLIA_MIN_KEY_SIZE        16
+#define CAMELLIA_MAX_KEY_SIZE        32
+#define CAMELLIA_BLOCK_SIZE          16
+#define CAMELLIA_TABLE_BYTE_LEN     272
+
+struct camellia_sparc64_ctx {
+	u64 encrypt_key[CAMELLIA_TABLE_BYTE_LEN / sizeof(u64)];
+	u64 decrypt_key[CAMELLIA_TABLE_BYTE_LEN / sizeof(u64)];
+	int key_len;
+};
+
+extern void camellia_sparc64_key_expand(const u32 *in_key, u64 *encrypt_key,
+					unsigned int key_len, u64 *decrypt_key);
+
+static int camellia_set_key(struct crypto_tfm *tfm, const u8 *_in_key,
+			    unsigned int key_len)
+{
+	struct camellia_sparc64_ctx *ctx = crypto_tfm_ctx(tfm);
+	const u32 *in_key = (const u32 *) _in_key;
+	u32 *flags = &tfm->crt_flags;
+
+	if (key_len != 16 && key_len != 24 && key_len != 32) {
+		*flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+		return -EINVAL;
+	}
+
+	ctx->key_len = key_len;
+
+	camellia_sparc64_key_expand(in_key, &ctx->encrypt_key[0],
+				    key_len, &ctx->decrypt_key[0]);
+	return 0;
+}
+
+extern void camellia_sparc64_crypt(const u64 *key, const u32 *input,
+				   u32 *output, unsigned int key_len);
+
+static void camellia_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
+{
+	struct camellia_sparc64_ctx *ctx = crypto_tfm_ctx(tfm);
+
+	camellia_sparc64_crypt(&ctx->encrypt_key[0],
+			       (const u32 *) src,
+			       (u32 *) dst, ctx->key_len);
+}
+
+static void camellia_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
+{
+	struct camellia_sparc64_ctx *ctx = crypto_tfm_ctx(tfm);
+
+	camellia_sparc64_crypt(&ctx->decrypt_key[0],
+			       (const u32 *) src,
+			       (u32 *) dst, ctx->key_len);
+}
+
+extern void camellia_sparc64_load_keys(const u64 *key, unsigned int key_len);
+
+typedef void ecb_crypt_op(const u64 *input, u64 *output, unsigned int len,
+			  const u64 *key);
+
+extern ecb_crypt_op camellia_sparc64_ecb_crypt_3_grand_rounds;
+extern ecb_crypt_op camellia_sparc64_ecb_crypt_4_grand_rounds;
+
+#define CAMELLIA_BLOCK_MASK	(~(CAMELLIA_BLOCK_SIZE - 1))
+
+static int __ecb_crypt(struct blkcipher_desc *desc,
+		       struct scatterlist *dst, struct scatterlist *src,
+		       unsigned int nbytes, bool encrypt)
+{
+	struct camellia_sparc64_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	struct blkcipher_walk walk;
+	ecb_crypt_op *op;
+	const u64 *key;
+	int err;
+
+	op = camellia_sparc64_ecb_crypt_3_grand_rounds;
+	if (ctx->key_len != 16)
+		op = camellia_sparc64_ecb_crypt_4_grand_rounds;
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	err = blkcipher_walk_virt(desc, &walk);
+
+	if (encrypt)
+		key = &ctx->encrypt_key[0];
+	else
+		key = &ctx->decrypt_key[0];
+	camellia_sparc64_load_keys(key, ctx->key_len);
+	while ((nbytes = walk.nbytes)) {
+		unsigned int block_len = nbytes & CAMELLIA_BLOCK_MASK;
+
+		if (likely(block_len)) {
+			const u64 *src64;
+			u64 *dst64;
+
+			src64 = (const u64 *)walk.src.virt.addr;
+			dst64 = (u64 *) walk.dst.virt.addr;
+			op(src64, dst64, block_len, key);
+		}
+		nbytes &= CAMELLIA_BLOCK_SIZE - 1;
+		err = blkcipher_walk_done(desc, &walk, nbytes);
+	}
+	fprs_write(0);
+	return err;
+}
+
+static int ecb_encrypt(struct blkcipher_desc *desc,
+		       struct scatterlist *dst, struct scatterlist *src,
+		       unsigned int nbytes)
+{
+	return __ecb_crypt(desc, dst, src, nbytes, true);
+}
+
+static int ecb_decrypt(struct blkcipher_desc *desc,
+		       struct scatterlist *dst, struct scatterlist *src,
+		       unsigned int nbytes)
+{
+	return __ecb_crypt(desc, dst, src, nbytes, false);
+}
+
+typedef void cbc_crypt_op(const u64 *input, u64 *output, unsigned int len,
+			  const u64 *key, u64 *iv);
+
+extern cbc_crypt_op camellia_sparc64_cbc_encrypt_3_grand_rounds;
+extern cbc_crypt_op camellia_sparc64_cbc_encrypt_4_grand_rounds;
+extern cbc_crypt_op camellia_sparc64_cbc_decrypt_3_grand_rounds;
+extern cbc_crypt_op camellia_sparc64_cbc_decrypt_4_grand_rounds;
+
+static int cbc_encrypt(struct blkcipher_desc *desc,
+		       struct scatterlist *dst, struct scatterlist *src,
+		       unsigned int nbytes)
+{
+	struct camellia_sparc64_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	struct blkcipher_walk walk;
+	cbc_crypt_op *op;
+	const u64 *key;
+	int err;
+
+	op = camellia_sparc64_cbc_encrypt_3_grand_rounds;
+	if (ctx->key_len != 16)
+		op = camellia_sparc64_cbc_encrypt_4_grand_rounds;
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	err = blkcipher_walk_virt(desc, &walk);
+
+	key = &ctx->encrypt_key[0];
+	camellia_sparc64_load_keys(key, ctx->key_len);
+	while ((nbytes = walk.nbytes)) {
+		unsigned int block_len = nbytes & CAMELLIA_BLOCK_MASK;
+
+		if (likely(block_len)) {
+			const u64 *src64;
+			u64 *dst64;
+
+			src64 = (const u64 *)walk.src.virt.addr;
+			dst64 = (u64 *) walk.dst.virt.addr;
+			op(src64, dst64, block_len, key,
+			   (u64 *) walk.iv);
+		}
+		nbytes &= CAMELLIA_BLOCK_SIZE - 1;
+		err = blkcipher_walk_done(desc, &walk, nbytes);
+	}
+	fprs_write(0);
+	return err;
+}
+
+static int cbc_decrypt(struct blkcipher_desc *desc,
+		       struct scatterlist *dst, struct scatterlist *src,
+		       unsigned int nbytes)
+{
+	struct camellia_sparc64_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	struct blkcipher_walk walk;
+	cbc_crypt_op *op;
+	const u64 *key;
+	int err;
+
+	op = camellia_sparc64_cbc_decrypt_3_grand_rounds;
+	if (ctx->key_len != 16)
+		op = camellia_sparc64_cbc_decrypt_4_grand_rounds;
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	err = blkcipher_walk_virt(desc, &walk);
+
+	key = &ctx->decrypt_key[0];
+	camellia_sparc64_load_keys(key, ctx->key_len);
+	while ((nbytes = walk.nbytes)) {
+		unsigned int block_len = nbytes & CAMELLIA_BLOCK_MASK;
+
+		if (likely(block_len)) {
+			const u64 *src64;
+			u64 *dst64;
+
+			src64 = (const u64 *)walk.src.virt.addr;
+			dst64 = (u64 *) walk.dst.virt.addr;
+			op(src64, dst64, block_len, key,
+			   (u64 *) walk.iv);
+		}
+		nbytes &= CAMELLIA_BLOCK_SIZE - 1;
+		err = blkcipher_walk_done(desc, &walk, nbytes);
+	}
+	fprs_write(0);
+	return err;
+}
+
+static struct crypto_alg algs[] = { {
+	.cra_name		= "camellia",
+	.cra_driver_name	= "camellia-sparc64",
+	.cra_priority		= SPARC_CR_OPCODE_PRIORITY,
+	.cra_flags		= CRYPTO_ALG_TYPE_CIPHER,
+	.cra_blocksize		= CAMELLIA_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct camellia_sparc64_ctx),
+	.cra_alignmask		= 3,
+	.cra_module		= THIS_MODULE,
+	.cra_u	= {
+		.cipher	= {
+			.cia_min_keysize	= CAMELLIA_MIN_KEY_SIZE,
+			.cia_max_keysize	= CAMELLIA_MAX_KEY_SIZE,
+			.cia_setkey		= camellia_set_key,
+			.cia_encrypt		= camellia_encrypt,
+			.cia_decrypt		= camellia_decrypt
+		}
+	}
+}, {
+	.cra_name		= "ecb(camellia)",
+	.cra_driver_name	= "ecb-camellia-sparc64",
+	.cra_priority		= SPARC_CR_OPCODE_PRIORITY,
+	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER,
+	.cra_blocksize		= CAMELLIA_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct camellia_sparc64_ctx),
+	.cra_alignmask		= 7,
+	.cra_type		= &crypto_blkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_u = {
+		.blkcipher = {
+			.min_keysize	= CAMELLIA_MIN_KEY_SIZE,
+			.max_keysize	= CAMELLIA_MAX_KEY_SIZE,
+			.setkey		= camellia_set_key,
+			.encrypt	= ecb_encrypt,
+			.decrypt	= ecb_decrypt,
+		},
+	},
+}, {
+	.cra_name		= "cbc(camellia)",
+	.cra_driver_name	= "cbc-camellia-sparc64",
+	.cra_priority		= SPARC_CR_OPCODE_PRIORITY,
+	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER,
+	.cra_blocksize		= CAMELLIA_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct camellia_sparc64_ctx),
+	.cra_alignmask		= 7,
+	.cra_type		= &crypto_blkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_u = {
+		.blkcipher = {
+			.min_keysize	= CAMELLIA_MIN_KEY_SIZE,
+			.max_keysize	= CAMELLIA_MAX_KEY_SIZE,
+			.setkey		= camellia_set_key,
+			.encrypt	= cbc_encrypt,
+			.decrypt	= cbc_decrypt,
+		},
+	},
+}
+};
+
+static bool __init sparc64_has_camellia_opcode(void)
+{
+	unsigned long cfr;
+
+	if (!(sparc64_elf_hwcap & HWCAP_SPARC_CRYPTO))
+		return false;
+
+	__asm__ __volatile__("rd %%asr26, %0" : "=r" (cfr));
+	if (!(cfr & CFR_CAMELLIA))
+		return false;
+
+	return true;
+}
+
+static int __init camellia_sparc64_mod_init(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(algs); i++)
+		INIT_LIST_HEAD(&algs[i].cra_list);
+
+	if (sparc64_has_camellia_opcode()) {
+		pr_info("Using sparc64 camellia opcodes optimized CAMELLIA implementation\n");
+		return crypto_register_algs(algs, ARRAY_SIZE(algs));
+	}
+	pr_info("sparc64 camellia opcodes not available.\n");
+	return -ENODEV;
+}
+
+static void __exit camellia_sparc64_mod_fini(void)
+{
+	crypto_unregister_algs(algs, ARRAY_SIZE(algs));
+}
+
+module_init(camellia_sparc64_mod_init);
+module_exit(camellia_sparc64_mod_fini);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Camellia Cipher Algorithm, sparc64 camellia opcode accelerated");
+
+MODULE_ALIAS("aes");
diff --git a/arch/sparc/crypto/crc32c_asm.S b/arch/sparc/crypto/crc32c_asm.S
new file mode 100644
index 0000000..2b1976e
--- /dev/null
+++ b/arch/sparc/crypto/crc32c_asm.S
@@ -0,0 +1,20 @@
+#include <linux/linkage.h>
+#include <asm/visasm.h>
+#include <asm/asi.h>
+
+#include "opcodes.h"
+
+ENTRY(crc32c_sparc64)
+	/* %o0=crc32p, %o1=data_ptr, %o2=len */
+	VISEntryHalf
+	lda	[%o0] ASI_PL, %f1
+1:	ldd	[%o1], %f2
+	CRC32C(0,2,0)
+	subcc	%o2, 8, %o2
+	bne,pt	%icc, 1b
+	 add	%o1, 0x8, %o1
+	sta	%f1, [%o0] ASI_PL
+	VISExitHalf
+2:	retl
+	 nop
+ENDPROC(crc32c_sparc64)
diff --git a/arch/sparc/crypto/crc32c_glue.c b/arch/sparc/crypto/crc32c_glue.c
new file mode 100644
index 0000000..0bd89ce
--- /dev/null
+++ b/arch/sparc/crypto/crc32c_glue.c
@@ -0,0 +1,179 @@
+/* Glue code for CRC32C optimized for sparc64 crypto opcodes.
+ *
+ * This is based largely upon arch/x86/crypto/crc32c-intel.c
+ *
+ * Copyright (C) 2008 Intel Corporation
+ * Authors: Austin Zhang <austin_zhang@linux.intel.com>
+ *          Kent Liu <kent.liu@intel.com>
+ */
+
+#define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/crc32.h>
+
+#include <crypto/internal/hash.h>
+
+#include <asm/pstate.h>
+#include <asm/elf.h>
+
+#include "opcodes.h"
+
+/*
+ * Setting the seed allows arbitrary accumulators and flexible XOR policy
+ * If your algorithm starts with ~0, then XOR with ~0 before you set
+ * the seed.
+ */
+static int crc32c_sparc64_setkey(struct crypto_shash *hash, const u8 *key,
+				 unsigned int keylen)
+{
+	u32 *mctx = crypto_shash_ctx(hash);
+
+	if (keylen != sizeof(u32)) {
+		crypto_shash_set_flags(hash, CRYPTO_TFM_RES_BAD_KEY_LEN);
+		return -EINVAL;
+	}
+	*(__le32 *)mctx = le32_to_cpup((__le32 *)key);
+	return 0;
+}
+
+static int crc32c_sparc64_init(struct shash_desc *desc)
+{
+	u32 *mctx = crypto_shash_ctx(desc->tfm);
+	u32 *crcp = shash_desc_ctx(desc);
+
+	*crcp = *mctx;
+
+	return 0;
+}
+
+extern void crc32c_sparc64(u32 *crcp, const u64 *data, unsigned int len);
+
+static void crc32c_compute(u32 *crcp, const u64 *data, unsigned int len)
+{
+	unsigned int asm_len;
+
+	asm_len = len & ~7U;
+	if (asm_len) {
+		crc32c_sparc64(crcp, data, asm_len);
+		data += asm_len / 8;
+		len -= asm_len;
+	}
+	if (len)
+		*crcp = __crc32c_le(*crcp, (const unsigned char *) data, len);
+}
+
+static int crc32c_sparc64_update(struct shash_desc *desc, const u8 *data,
+				 unsigned int len)
+{
+	u32 *crcp = shash_desc_ctx(desc);
+
+	crc32c_compute(crcp, (const u64 *) data, len);
+
+	return 0;
+}
+
+static int __crc32c_sparc64_finup(u32 *crcp, const u8 *data, unsigned int len,
+				  u8 *out)
+{
+	u32 tmp = *crcp;
+
+	crc32c_compute(&tmp, (const u64 *) data, len);
+
+	*(__le32 *) out = ~cpu_to_le32(tmp);
+	return 0;
+}
+
+static int crc32c_sparc64_finup(struct shash_desc *desc, const u8 *data,
+				unsigned int len, u8 *out)
+{
+	return __crc32c_sparc64_finup(shash_desc_ctx(desc), data, len, out);
+}
+
+static int crc32c_sparc64_final(struct shash_desc *desc, u8 *out)
+{
+	u32 *crcp = shash_desc_ctx(desc);
+
+	*(__le32 *) out = ~cpu_to_le32p(crcp);
+	return 0;
+}
+
+static int crc32c_sparc64_digest(struct shash_desc *desc, const u8 *data,
+				 unsigned int len, u8 *out)
+{
+	return __crc32c_sparc64_finup(crypto_shash_ctx(desc->tfm), data, len,
+				      out);
+}
+
+static int crc32c_sparc64_cra_init(struct crypto_tfm *tfm)
+{
+	u32 *key = crypto_tfm_ctx(tfm);
+
+	*key = ~0;
+
+	return 0;
+}
+
+#define CHKSUM_BLOCK_SIZE	1
+#define CHKSUM_DIGEST_SIZE	4
+
+static struct shash_alg alg = {
+	.setkey			=	crc32c_sparc64_setkey,
+	.init			=	crc32c_sparc64_init,
+	.update			=	crc32c_sparc64_update,
+	.final			=	crc32c_sparc64_final,
+	.finup			=	crc32c_sparc64_finup,
+	.digest			=	crc32c_sparc64_digest,
+	.descsize		=	sizeof(u32),
+	.digestsize		=	CHKSUM_DIGEST_SIZE,
+	.base			=	{
+		.cra_name		=	"crc32c",
+		.cra_driver_name	=	"crc32c-sparc64",
+		.cra_priority		=	SPARC_CR_OPCODE_PRIORITY,
+		.cra_blocksize		=	CHKSUM_BLOCK_SIZE,
+		.cra_ctxsize		=	sizeof(u32),
+		.cra_alignmask		=	7,
+		.cra_module		=	THIS_MODULE,
+		.cra_init		=	crc32c_sparc64_cra_init,
+	}
+};
+
+static bool __init sparc64_has_crc32c_opcode(void)
+{
+	unsigned long cfr;
+
+	if (!(sparc64_elf_hwcap & HWCAP_SPARC_CRYPTO))
+		return false;
+
+	__asm__ __volatile__("rd %%asr26, %0" : "=r" (cfr));
+	if (!(cfr & CFR_CRC32C))
+		return false;
+
+	return true;
+}
+
+static int __init crc32c_sparc64_mod_init(void)
+{
+	if (sparc64_has_crc32c_opcode()) {
+		pr_info("Using sparc64 crc32c opcode optimized CRC32C implementation\n");
+		return crypto_register_shash(&alg);
+	}
+	pr_info("sparc64 crc32c opcode not available.\n");
+	return -ENODEV;
+}
+
+static void __exit crc32c_sparc64_mod_fini(void)
+{
+	crypto_unregister_shash(&alg);
+}
+
+module_init(crc32c_sparc64_mod_init);
+module_exit(crc32c_sparc64_mod_fini);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("CRC32c (Castagnoli), sparc64 crc32c opcode accelerated");
+
+MODULE_ALIAS("crc32c");
diff --git a/arch/sparc/crypto/crop_devid.c b/arch/sparc/crypto/crop_devid.c
new file mode 100644
index 0000000..5f5724a
--- /dev/null
+++ b/arch/sparc/crypto/crop_devid.c
@@ -0,0 +1,14 @@
+#include <linux/module.h>
+#include <linux/of_device.h>
+
+/* This is a dummy device table linked into all of the crypto
+ * opcode drivers.  It serves to trigger the module autoloading
+ * mechanisms in userspace which scan the OF device tree and
+ * load any modules which have device table entries that
+ * match OF device nodes.
+ */
+static const struct of_device_id crypto_opcode_match[] = {
+	{ .name = "cpu", .compatible = "sun4v", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, crypto_opcode_match);
diff --git a/arch/sparc/crypto/des_asm.S b/arch/sparc/crypto/des_asm.S
new file mode 100644
index 0000000..30b6e90
--- /dev/null
+++ b/arch/sparc/crypto/des_asm.S
@@ -0,0 +1,418 @@
+#include <linux/linkage.h>
+#include <asm/visasm.h>
+
+#include "opcodes.h"
+
+	.align	32
+ENTRY(des_sparc64_key_expand)
+	/* %o0=input_key, %o1=output_key */
+	VISEntryHalf
+	ld	[%o0 + 0x00], %f0
+	ld	[%o0 + 0x04], %f1
+	DES_KEXPAND(0, 0, 0)
+	DES_KEXPAND(0, 1, 2)
+	DES_KEXPAND(2, 3, 6)
+	DES_KEXPAND(2, 2, 4)
+	DES_KEXPAND(6, 3, 10)
+	DES_KEXPAND(6, 2, 8)
+	DES_KEXPAND(10, 3, 14)
+	DES_KEXPAND(10, 2, 12)
+	DES_KEXPAND(14, 1, 16)
+	DES_KEXPAND(16, 3, 20)
+	DES_KEXPAND(16, 2, 18)
+	DES_KEXPAND(20, 3, 24)
+	DES_KEXPAND(20, 2, 22)
+	DES_KEXPAND(24, 3, 28)
+	DES_KEXPAND(24, 2, 26)
+	DES_KEXPAND(28, 1, 30)
+	std	%f0, [%o1 + 0x00]
+	std	%f2, [%o1 + 0x08]
+	std	%f4, [%o1 + 0x10]
+	std	%f6, [%o1 + 0x18]
+	std	%f8, [%o1 + 0x20]
+	std	%f10, [%o1 + 0x28]
+	std	%f12, [%o1 + 0x30]
+	std	%f14, [%o1 + 0x38]
+	std	%f16, [%o1 + 0x40]
+	std	%f18, [%o1 + 0x48]
+	std	%f20, [%o1 + 0x50]
+	std	%f22, [%o1 + 0x58]
+	std	%f24, [%o1 + 0x60]
+	std	%f26, [%o1 + 0x68]
+	std	%f28, [%o1 + 0x70]
+	std	%f30, [%o1 + 0x78]
+	retl
+	 VISExitHalf
+ENDPROC(des_sparc64_key_expand)
+
+	.align	32
+ENTRY(des_sparc64_crypt)
+	/* %o0=key, %o1=input, %o2=output */
+	VISEntry
+	ldd	[%o1 + 0x00], %f32
+	ldd	[%o0 + 0x00], %f0
+	ldd	[%o0 + 0x08], %f2
+	ldd	[%o0 + 0x10], %f4
+	ldd	[%o0 + 0x18], %f6
+	ldd	[%o0 + 0x20], %f8
+	ldd	[%o0 + 0x28], %f10
+	ldd	[%o0 + 0x30], %f12
+	ldd	[%o0 + 0x38], %f14
+	ldd	[%o0 + 0x40], %f16
+	ldd	[%o0 + 0x48], %f18
+	ldd	[%o0 + 0x50], %f20
+	ldd	[%o0 + 0x58], %f22
+	ldd	[%o0 + 0x60], %f24
+	ldd	[%o0 + 0x68], %f26
+	ldd	[%o0 + 0x70], %f28
+	ldd	[%o0 + 0x78], %f30
+	DES_IP(32, 32)
+	DES_ROUND(0, 2, 32, 32)
+	DES_ROUND(4, 6, 32, 32)
+	DES_ROUND(8, 10, 32, 32)
+	DES_ROUND(12, 14, 32, 32)
+	DES_ROUND(16, 18, 32, 32)
+	DES_ROUND(20, 22, 32, 32)
+	DES_ROUND(24, 26, 32, 32)
+	DES_ROUND(28, 30, 32, 32)
+	DES_IIP(32, 32)
+	std	%f32, [%o2 + 0x00]
+	retl
+	 VISExit
+ENDPROC(des_sparc64_crypt)
+
+	.align	32
+ENTRY(des_sparc64_load_keys)
+	/* %o0=key */
+	VISEntry
+	ldd	[%o0 + 0x00], %f0
+	ldd	[%o0 + 0x08], %f2
+	ldd	[%o0 + 0x10], %f4
+	ldd	[%o0 + 0x18], %f6
+	ldd	[%o0 + 0x20], %f8
+	ldd	[%o0 + 0x28], %f10
+	ldd	[%o0 + 0x30], %f12
+	ldd	[%o0 + 0x38], %f14
+	ldd	[%o0 + 0x40], %f16
+	ldd	[%o0 + 0x48], %f18
+	ldd	[%o0 + 0x50], %f20
+	ldd	[%o0 + 0x58], %f22
+	ldd	[%o0 + 0x60], %f24
+	ldd	[%o0 + 0x68], %f26
+	ldd	[%o0 + 0x70], %f28
+	retl
+	 ldd	[%o0 + 0x78], %f30
+ENDPROC(des_sparc64_load_keys)
+
+	.align	32
+ENTRY(des_sparc64_ecb_crypt)
+	/* %o0=input, %o1=output, %o2=len */
+1:	ldd	[%o0 + 0x00], %f32
+	add	%o0, 0x08, %o0
+	DES_IP(32, 32)
+	DES_ROUND(0, 2, 32, 32)
+	DES_ROUND(4, 6, 32, 32)
+	DES_ROUND(8, 10, 32, 32)
+	DES_ROUND(12, 14, 32, 32)
+	DES_ROUND(16, 18, 32, 32)
+	DES_ROUND(20, 22, 32, 32)
+	DES_ROUND(24, 26, 32, 32)
+	DES_ROUND(28, 30, 32, 32)
+	DES_IIP(32, 32)
+	std	%f32, [%o1 + 0x00]
+	subcc	%o2, 0x08, %o2
+	bne,pt	%icc, 1b
+	 add	%o1, 0x08, %o1
+	retl
+	 nop
+ENDPROC(des_sparc64_ecb_crypt)
+
+	.align	32
+ENTRY(des_sparc64_cbc_encrypt)
+	/* %o0=input, %o1=output, %o2=len, %o3=IV */
+	ldd	[%o3 + 0x00], %f32
+1:	ldd	[%o0 + 0x00], %f34
+	fxor	%f32, %f34, %f32
+	DES_IP(32, 32)
+	DES_ROUND(0, 2, 32, 32)
+	DES_ROUND(4, 6, 32, 32)
+	DES_ROUND(8, 10, 32, 32)
+	DES_ROUND(12, 14, 32, 32)
+	DES_ROUND(16, 18, 32, 32)
+	DES_ROUND(20, 22, 32, 32)
+	DES_ROUND(24, 26, 32, 32)
+	DES_ROUND(28, 30, 32, 32)
+	DES_IIP(32, 32)
+	std	%f32, [%o1 + 0x00]
+	add	%o0, 0x08, %o0
+	subcc	%o2, 0x08, %o2
+	bne,pt	%icc, 1b
+	 add	%o1, 0x08, %o1
+	retl
+	 std	%f32, [%o3 + 0x00]
+ENDPROC(des_sparc64_cbc_encrypt)
+
+	.align	32
+ENTRY(des_sparc64_cbc_decrypt)
+	/* %o0=input, %o1=output, %o2=len, %o3=IV */
+	ldd	[%o3 + 0x00], %f34
+1:	ldd	[%o0 + 0x00], %f36
+	DES_IP(36, 32)
+	DES_ROUND(0, 2, 32, 32)
+	DES_ROUND(4, 6, 32, 32)
+	DES_ROUND(8, 10, 32, 32)
+	DES_ROUND(12, 14, 32, 32)
+	DES_ROUND(16, 18, 32, 32)
+	DES_ROUND(20, 22, 32, 32)
+	DES_ROUND(24, 26, 32, 32)
+	DES_ROUND(28, 30, 32, 32)
+	DES_IIP(32, 32)
+	fxor	%f32, %f34, %f32
+	fsrc2	%f36, %f34
+	std	%f32, [%o1 + 0x00]
+	add	%o0, 0x08, %o0
+	subcc	%o2, 0x08, %o2
+	bne,pt	%icc, 1b
+	 add	%o1, 0x08, %o1
+	retl
+	 std	%f36, [%o3 + 0x00]
+ENDPROC(des_sparc64_cbc_decrypt)
+
+	.align	32
+ENTRY(des3_ede_sparc64_crypt)
+	/* %o0=key, %o1=input, %o2=output */
+	VISEntry
+	ldd	[%o1 + 0x00], %f32
+	ldd	[%o0 + 0x00], %f0
+	ldd	[%o0 + 0x08], %f2
+	ldd	[%o0 + 0x10], %f4
+	ldd	[%o0 + 0x18], %f6
+	ldd	[%o0 + 0x20], %f8
+	ldd	[%o0 + 0x28], %f10
+	ldd	[%o0 + 0x30], %f12
+	ldd	[%o0 + 0x38], %f14
+	ldd	[%o0 + 0x40], %f16
+	ldd	[%o0 + 0x48], %f18
+	ldd	[%o0 + 0x50], %f20
+	ldd	[%o0 + 0x58], %f22
+	ldd	[%o0 + 0x60], %f24
+	ldd	[%o0 + 0x68], %f26
+	ldd	[%o0 + 0x70], %f28
+	ldd	[%o0 + 0x78], %f30
+	DES_IP(32, 32)
+	DES_ROUND(0, 2, 32, 32)
+	ldd	[%o0 + 0x80], %f0
+	ldd	[%o0 + 0x88], %f2
+	DES_ROUND(4, 6, 32, 32)
+	ldd	[%o0 + 0x90], %f4
+	ldd	[%o0 + 0x98], %f6
+	DES_ROUND(8, 10, 32, 32)
+	ldd	[%o0 + 0xa0], %f8
+	ldd	[%o0 + 0xa8], %f10
+	DES_ROUND(12, 14, 32, 32)
+	ldd	[%o0 + 0xb0], %f12
+	ldd	[%o0 + 0xb8], %f14
+	DES_ROUND(16, 18, 32, 32)
+	ldd	[%o0 + 0xc0], %f16
+	ldd	[%o0 + 0xc8], %f18
+	DES_ROUND(20, 22, 32, 32)
+	ldd	[%o0 + 0xd0], %f20
+	ldd	[%o0 + 0xd8], %f22
+	DES_ROUND(24, 26, 32, 32)
+	ldd	[%o0 + 0xe0], %f24
+	ldd	[%o0 + 0xe8], %f26
+	DES_ROUND(28, 30, 32, 32)
+	ldd	[%o0 + 0xf0], %f28
+	ldd	[%o0 + 0xf8], %f30
+	DES_IIP(32, 32)
+	DES_IP(32, 32)
+	DES_ROUND(0, 2, 32, 32)
+	ldd	[%o0 + 0x100], %f0
+	ldd	[%o0 + 0x108], %f2
+	DES_ROUND(4, 6, 32, 32)
+	ldd	[%o0 + 0x110], %f4
+	ldd	[%o0 + 0x118], %f6
+	DES_ROUND(8, 10, 32, 32)
+	ldd	[%o0 + 0x120], %f8
+	ldd	[%o0 + 0x128], %f10
+	DES_ROUND(12, 14, 32, 32)
+	ldd	[%o0 + 0x130], %f12
+	ldd	[%o0 + 0x138], %f14
+	DES_ROUND(16, 18, 32, 32)
+	ldd	[%o0 + 0x140], %f16
+	ldd	[%o0 + 0x148], %f18
+	DES_ROUND(20, 22, 32, 32)
+	ldd	[%o0 + 0x150], %f20
+	ldd	[%o0 + 0x158], %f22
+	DES_ROUND(24, 26, 32, 32)
+	ldd	[%o0 + 0x160], %f24
+	ldd	[%o0 + 0x168], %f26
+	DES_ROUND(28, 30, 32, 32)
+	ldd	[%o0 + 0x170], %f28
+	ldd	[%o0 + 0x178], %f30
+	DES_IIP(32, 32)
+	DES_IP(32, 32)
+	DES_ROUND(0, 2, 32, 32)
+	DES_ROUND(4, 6, 32, 32)
+	DES_ROUND(8, 10, 32, 32)
+	DES_ROUND(12, 14, 32, 32)
+	DES_ROUND(16, 18, 32, 32)
+	DES_ROUND(20, 22, 32, 32)
+	DES_ROUND(24, 26, 32, 32)
+	DES_ROUND(28, 30, 32, 32)
+	DES_IIP(32, 32)
+
+	std	%f32, [%o2 + 0x00]
+	retl
+	 VISExit
+ENDPROC(des3_ede_sparc64_crypt)
+
+	.align	32
+ENTRY(des3_ede_sparc64_load_keys)
+	/* %o0=key */
+	VISEntry
+	ldd	[%o0 + 0x00], %f0
+	ldd	[%o0 + 0x08], %f2
+	ldd	[%o0 + 0x10], %f4
+	ldd	[%o0 + 0x18], %f6
+	ldd	[%o0 + 0x20], %f8
+	ldd	[%o0 + 0x28], %f10
+	ldd	[%o0 + 0x30], %f12
+	ldd	[%o0 + 0x38], %f14
+	ldd	[%o0 + 0x40], %f16
+	ldd	[%o0 + 0x48], %f18
+	ldd	[%o0 + 0x50], %f20
+	ldd	[%o0 + 0x58], %f22
+	ldd	[%o0 + 0x60], %f24
+	ldd	[%o0 + 0x68], %f26
+	ldd	[%o0 + 0x70], %f28
+	ldd	[%o0 + 0x78], %f30
+	ldd	[%o0 + 0x80], %f32
+	ldd	[%o0 + 0x88], %f34
+	ldd	[%o0 + 0x90], %f36
+	ldd	[%o0 + 0x98], %f38
+	ldd	[%o0 + 0xa0], %f40
+	ldd	[%o0 + 0xa8], %f42
+	ldd	[%o0 + 0xb0], %f44
+	ldd	[%o0 + 0xb8], %f46
+	ldd	[%o0 + 0xc0], %f48
+	ldd	[%o0 + 0xc8], %f50
+	ldd	[%o0 + 0xd0], %f52
+	ldd	[%o0 + 0xd8], %f54
+	ldd	[%o0 + 0xe0], %f56
+	retl
+	 ldd	[%o0 + 0xe8], %f58
+ENDPROC(des3_ede_sparc64_load_keys)
+
+#define DES3_LOOP_BODY(X) \
+	DES_IP(X, X) \
+	DES_ROUND(0, 2, X, X) \
+	DES_ROUND(4, 6, X, X) \
+	DES_ROUND(8, 10, X, X) \
+	DES_ROUND(12, 14, X, X) \
+	DES_ROUND(16, 18, X, X) \
+	ldd	[%o0 + 0xf0], %f16; \
+	ldd	[%o0 + 0xf8], %f18; \
+	DES_ROUND(20, 22, X, X) \
+	ldd	[%o0 + 0x100], %f20; \
+	ldd	[%o0 + 0x108], %f22; \
+	DES_ROUND(24, 26, X, X) \
+	ldd	[%o0 + 0x110], %f24; \
+	ldd	[%o0 + 0x118], %f26; \
+	DES_ROUND(28, 30, X, X) \
+	ldd	[%o0 + 0x120], %f28; \
+	ldd	[%o0 + 0x128], %f30; \
+	DES_IIP(X, X) \
+	DES_IP(X, X) \
+	DES_ROUND(32, 34, X, X) \
+	ldd	[%o0 + 0x130], %f0; \
+	ldd	[%o0 + 0x138], %f2; \
+	DES_ROUND(36, 38, X, X) \
+	ldd	[%o0 + 0x140], %f4; \
+	ldd	[%o0 + 0x148], %f6; \
+	DES_ROUND(40, 42, X, X) \
+	ldd	[%o0 + 0x150], %f8; \
+	ldd	[%o0 + 0x158], %f10; \
+	DES_ROUND(44, 46, X, X) \
+	ldd	[%o0 + 0x160], %f12; \
+	ldd	[%o0 + 0x168], %f14; \
+	DES_ROUND(48, 50, X, X) \
+	DES_ROUND(52, 54, X, X) \
+	DES_ROUND(56, 58, X, X) \
+	DES_ROUND(16, 18, X, X) \
+	ldd	[%o0 + 0x170], %f16; \
+	ldd	[%o0 + 0x178], %f18; \
+	DES_IIP(X, X) \
+	DES_IP(X, X) \
+	DES_ROUND(20, 22, X, X) \
+	ldd	[%o0 + 0x50], %f20; \
+	ldd	[%o0 + 0x58], %f22; \
+	DES_ROUND(24, 26, X, X) \
+	ldd	[%o0 + 0x60], %f24; \
+	ldd	[%o0 + 0x68], %f26; \
+	DES_ROUND(28, 30, X, X) \
+	ldd	[%o0 + 0x70], %f28; \
+	ldd	[%o0 + 0x78], %f30; \
+	DES_ROUND(0, 2, X, X) \
+	ldd	[%o0 + 0x00], %f0; \
+	ldd	[%o0 + 0x08], %f2; \
+	DES_ROUND(4, 6, X, X) \
+	ldd	[%o0 + 0x10], %f4; \
+	ldd	[%o0 + 0x18], %f6; \
+	DES_ROUND(8, 10, X, X) \
+	ldd	[%o0 + 0x20], %f8; \
+	ldd	[%o0 + 0x28], %f10; \
+	DES_ROUND(12, 14, X, X) \
+	ldd	[%o0 + 0x30], %f12; \
+	ldd	[%o0 + 0x38], %f14; \
+	DES_ROUND(16, 18, X, X) \
+	ldd	[%o0 + 0x40], %f16; \
+	ldd	[%o0 + 0x48], %f18; \
+	DES_IIP(X, X)
+
+	.align	32
+ENTRY(des3_ede_sparc64_ecb_crypt)
+	/* %o0=key, %o1=input, %o2=output, %o3=len */
+1:	ldd	[%o1 + 0x00], %f60
+	DES3_LOOP_BODY(60)
+	std	%f60, [%o2 + 0x00]
+	subcc	%o3, 0x08, %o3
+	bne,pt	%icc, 1b
+	 add	%o2, 0x08, %o2
+	retl
+	 nop
+ENDPROC(des3_ede_sparc64_ecb_crypt)
+
+	.align	32
+ENTRY(des3_ede_sparc64_cbc_encrypt)
+	/* %o0=key, %o1=input, %o2=output, %o3=len, %o4=IV */
+	ldd	[%o4 + 0x00], %f60
+1:	ldd	[%o1 + 0x00], %f62
+	fxor	%f60, %f62, %f60
+	DES3_LOOP_BODY(60)
+	std	%f60, [%o2 + 0x00]
+	add	%o1, 0x08, %o1
+	subcc	%o3, 0x08, %o3
+	bne,pt	%icc, 1b
+	 add	%o2, 0x08, %o2
+	retl
+	 std	%f60, [%o4 + 0x00]
+ENDPROC(des3_ede_sparc64_cbc_encrypt)
+
+	.align	32
+ENTRY(des3_ede_sparc64_cbc_decrypt)
+	/* %o0=key, %o1=input, %o2=output, %o3=len, %o4=IV */
+	ldd	[%o4 + 0x00], %f62
+1:	ldx	[%o1 + 0x00], %g1
+	MOVXTOD_G1_F60
+	DES3_LOOP_BODY(60)
+	fxor	%f62, %f60, %f60
+	MOVXTOD_G1_F62
+	std	%f60, [%o2 + 0x00]
+	add	%o1, 0x08, %o1
+	subcc	%o3, 0x08, %o3
+	bne,pt	%icc, 1b
+	 add	%o2, 0x08, %o2
+	retl
+	 stx	%g1, [%o4 + 0x00]
+ENDPROC(des3_ede_sparc64_cbc_decrypt)
diff --git a/arch/sparc/crypto/des_glue.c b/arch/sparc/crypto/des_glue.c
new file mode 100644
index 0000000..c4940c2
--- /dev/null
+++ b/arch/sparc/crypto/des_glue.c
@@ -0,0 +1,529 @@
+/* Glue code for DES encryption optimized for sparc64 crypto opcodes.
+ *
+ * Copyright (C) 2012 David S. Miller <davem@davemloft.net>
+ */
+
+#define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
+
+#include <linux/crypto.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/types.h>
+#include <crypto/algapi.h>
+#include <crypto/des.h>
+
+#include <asm/fpumacro.h>
+#include <asm/pstate.h>
+#include <asm/elf.h>
+
+#include "opcodes.h"
+
+struct des_sparc64_ctx {
+	u64 encrypt_expkey[DES_EXPKEY_WORDS / 2];
+	u64 decrypt_expkey[DES_EXPKEY_WORDS / 2];
+};
+
+struct des3_ede_sparc64_ctx {
+	u64 encrypt_expkey[DES3_EDE_EXPKEY_WORDS / 2];
+	u64 decrypt_expkey[DES3_EDE_EXPKEY_WORDS / 2];
+};
+
+static void encrypt_to_decrypt(u64 *d, const u64 *e)
+{
+	const u64 *s = e + (DES_EXPKEY_WORDS / 2) - 1;
+	int i;
+
+	for (i = 0; i < DES_EXPKEY_WORDS / 2; i++)
+		*d++ = *s--;
+}
+
+extern void des_sparc64_key_expand(const u32 *input_key, u64 *key);
+
+static int des_set_key(struct crypto_tfm *tfm, const u8 *key,
+		       unsigned int keylen)
+{
+	struct des_sparc64_ctx *dctx = crypto_tfm_ctx(tfm);
+	u32 *flags = &tfm->crt_flags;
+	u32 tmp[DES_EXPKEY_WORDS];
+	int ret;
+
+	/* Even though we have special instructions for key expansion,
+	 * we call des_ekey() so that we don't have to write our own
+	 * weak key detection code.
+	 */
+	ret = des_ekey(tmp, key);
+	if (unlikely(ret == 0) && (*flags & CRYPTO_TFM_REQ_WEAK_KEY)) {
+		*flags |= CRYPTO_TFM_RES_WEAK_KEY;
+		return -EINVAL;
+	}
+
+	des_sparc64_key_expand((const u32 *) key, &dctx->encrypt_expkey[0]);
+	encrypt_to_decrypt(&dctx->decrypt_expkey[0], &dctx->encrypt_expkey[0]);
+
+	return 0;
+}
+
+extern void des_sparc64_crypt(const u64 *key, const u64 *input,
+			      u64 *output);
+
+static void des_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
+{
+	struct des_sparc64_ctx *ctx = crypto_tfm_ctx(tfm);
+	const u64 *K = ctx->encrypt_expkey;
+
+	des_sparc64_crypt(K, (const u64 *) src, (u64 *) dst);
+}
+
+static void des_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
+{
+	struct des_sparc64_ctx *ctx = crypto_tfm_ctx(tfm);
+	const u64 *K = ctx->decrypt_expkey;
+
+	des_sparc64_crypt(K, (const u64 *) src, (u64 *) dst);
+}
+
+extern void des_sparc64_load_keys(const u64 *key);
+
+extern void des_sparc64_ecb_crypt(const u64 *input, u64 *output,
+				  unsigned int len);
+
+#define DES_BLOCK_MASK	(~(DES_BLOCK_SIZE - 1))
+
+static int __ecb_crypt(struct blkcipher_desc *desc,
+		       struct scatterlist *dst, struct scatterlist *src,
+		       unsigned int nbytes, bool encrypt)
+{
+	struct des_sparc64_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	struct blkcipher_walk walk;
+	int err;
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	err = blkcipher_walk_virt(desc, &walk);
+
+	if (encrypt)
+		des_sparc64_load_keys(&ctx->encrypt_expkey[0]);
+	else
+		des_sparc64_load_keys(&ctx->decrypt_expkey[0]);
+	while ((nbytes = walk.nbytes)) {
+		unsigned int block_len = nbytes & DES_BLOCK_MASK;
+
+		if (likely(block_len)) {
+			des_sparc64_ecb_crypt((const u64 *)walk.src.virt.addr,
+					      (u64 *) walk.dst.virt.addr,
+					      block_len);
+		}
+		nbytes &= DES_BLOCK_SIZE - 1;
+		err = blkcipher_walk_done(desc, &walk, nbytes);
+	}
+	fprs_write(0);
+	return err;
+}
+
+static int ecb_encrypt(struct blkcipher_desc *desc,
+		       struct scatterlist *dst, struct scatterlist *src,
+		       unsigned int nbytes)
+{
+	return __ecb_crypt(desc, dst, src, nbytes, true);
+}
+
+static int ecb_decrypt(struct blkcipher_desc *desc,
+		       struct scatterlist *dst, struct scatterlist *src,
+		       unsigned int nbytes)
+{
+	return __ecb_crypt(desc, dst, src, nbytes, false);
+}
+
+extern void des_sparc64_cbc_encrypt(const u64 *input, u64 *output,
+				    unsigned int len, u64 *iv);
+
+static int cbc_encrypt(struct blkcipher_desc *desc,
+		       struct scatterlist *dst, struct scatterlist *src,
+		       unsigned int nbytes)
+{
+	struct des_sparc64_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	struct blkcipher_walk walk;
+	int err;
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	err = blkcipher_walk_virt(desc, &walk);
+
+	des_sparc64_load_keys(&ctx->encrypt_expkey[0]);
+	while ((nbytes = walk.nbytes)) {
+		unsigned int block_len = nbytes & DES_BLOCK_MASK;
+
+		if (likely(block_len)) {
+			des_sparc64_cbc_encrypt((const u64 *)walk.src.virt.addr,
+						(u64 *) walk.dst.virt.addr,
+						block_len, (u64 *) walk.iv);
+		}
+		nbytes &= DES_BLOCK_SIZE - 1;
+		err = blkcipher_walk_done(desc, &walk, nbytes);
+	}
+	fprs_write(0);
+	return err;
+}
+
+extern void des_sparc64_cbc_decrypt(const u64 *input, u64 *output,
+				    unsigned int len, u64 *iv);
+
+static int cbc_decrypt(struct blkcipher_desc *desc,
+		       struct scatterlist *dst, struct scatterlist *src,
+		       unsigned int nbytes)
+{
+	struct des_sparc64_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	struct blkcipher_walk walk;
+	int err;
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	err = blkcipher_walk_virt(desc, &walk);
+
+	des_sparc64_load_keys(&ctx->decrypt_expkey[0]);
+	while ((nbytes = walk.nbytes)) {
+		unsigned int block_len = nbytes & DES_BLOCK_MASK;
+
+		if (likely(block_len)) {
+			des_sparc64_cbc_decrypt((const u64 *)walk.src.virt.addr,
+						(u64 *) walk.dst.virt.addr,
+						block_len, (u64 *) walk.iv);
+		}
+		nbytes &= DES_BLOCK_SIZE - 1;
+		err = blkcipher_walk_done(desc, &walk, nbytes);
+	}
+	fprs_write(0);
+	return err;
+}
+
+static int des3_ede_set_key(struct crypto_tfm *tfm, const u8 *key,
+			    unsigned int keylen)
+{
+	struct des3_ede_sparc64_ctx *dctx = crypto_tfm_ctx(tfm);
+	const u32 *K = (const u32 *)key;
+	u32 *flags = &tfm->crt_flags;
+	u64 k1[DES_EXPKEY_WORDS / 2];
+	u64 k2[DES_EXPKEY_WORDS / 2];
+	u64 k3[DES_EXPKEY_WORDS / 2];
+
+	if (unlikely(!((K[0] ^ K[2]) | (K[1] ^ K[3])) ||
+		     !((K[2] ^ K[4]) | (K[3] ^ K[5]))) &&
+		     (*flags & CRYPTO_TFM_REQ_WEAK_KEY)) {
+		*flags |= CRYPTO_TFM_RES_WEAK_KEY;
+		return -EINVAL;
+	}
+
+	des_sparc64_key_expand((const u32 *)key, k1);
+	key += DES_KEY_SIZE;
+	des_sparc64_key_expand((const u32 *)key, k2);
+	key += DES_KEY_SIZE;
+	des_sparc64_key_expand((const u32 *)key, k3);
+
+	memcpy(&dctx->encrypt_expkey[0], &k1[0], sizeof(k1));
+	encrypt_to_decrypt(&dctx->encrypt_expkey[DES_EXPKEY_WORDS / 2], &k2[0]);
+	memcpy(&dctx->encrypt_expkey[(DES_EXPKEY_WORDS / 2) * 2],
+	       &k3[0], sizeof(k3));
+
+	encrypt_to_decrypt(&dctx->decrypt_expkey[0], &k3[0]);
+	memcpy(&dctx->decrypt_expkey[DES_EXPKEY_WORDS / 2],
+	       &k2[0], sizeof(k2));
+	encrypt_to_decrypt(&dctx->decrypt_expkey[(DES_EXPKEY_WORDS / 2) * 2],
+			   &k1[0]);
+
+	return 0;
+}
+
+extern void des3_ede_sparc64_crypt(const u64 *key, const u64 *input,
+				   u64 *output);
+
+static void des3_ede_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
+{
+	struct des3_ede_sparc64_ctx *ctx = crypto_tfm_ctx(tfm);
+	const u64 *K = ctx->encrypt_expkey;
+
+	des3_ede_sparc64_crypt(K, (const u64 *) src, (u64 *) dst);
+}
+
+static void des3_ede_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
+{
+	struct des3_ede_sparc64_ctx *ctx = crypto_tfm_ctx(tfm);
+	const u64 *K = ctx->decrypt_expkey;
+
+	des3_ede_sparc64_crypt(K, (const u64 *) src, (u64 *) dst);
+}
+
+extern void des3_ede_sparc64_load_keys(const u64 *key);
+
+extern void des3_ede_sparc64_ecb_crypt(const u64 *expkey, const u64 *input,
+				       u64 *output, unsigned int len);
+
+static int __ecb3_crypt(struct blkcipher_desc *desc,
+			struct scatterlist *dst, struct scatterlist *src,
+			unsigned int nbytes, bool encrypt)
+{
+	struct des3_ede_sparc64_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	struct blkcipher_walk walk;
+	const u64 *K;
+	int err;
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	err = blkcipher_walk_virt(desc, &walk);
+
+	if (encrypt)
+		K = &ctx->encrypt_expkey[0];
+	else
+		K = &ctx->decrypt_expkey[0];
+	des3_ede_sparc64_load_keys(K);
+	while ((nbytes = walk.nbytes)) {
+		unsigned int block_len = nbytes & DES_BLOCK_MASK;
+
+		if (likely(block_len)) {
+			const u64 *src64 = (const u64 *)walk.src.virt.addr;
+			des3_ede_sparc64_ecb_crypt(K, src64,
+						   (u64 *) walk.dst.virt.addr,
+						   block_len);
+		}
+		nbytes &= DES_BLOCK_SIZE - 1;
+		err = blkcipher_walk_done(desc, &walk, nbytes);
+	}
+	fprs_write(0);
+	return err;
+}
+
+static int ecb3_encrypt(struct blkcipher_desc *desc,
+		       struct scatterlist *dst, struct scatterlist *src,
+		       unsigned int nbytes)
+{
+	return __ecb3_crypt(desc, dst, src, nbytes, true);
+}
+
+static int ecb3_decrypt(struct blkcipher_desc *desc,
+		       struct scatterlist *dst, struct scatterlist *src,
+		       unsigned int nbytes)
+{
+	return __ecb3_crypt(desc, dst, src, nbytes, false);
+}
+
+extern void des3_ede_sparc64_cbc_encrypt(const u64 *expkey, const u64 *input,
+					 u64 *output, unsigned int len,
+					 u64 *iv);
+
+static int cbc3_encrypt(struct blkcipher_desc *desc,
+			struct scatterlist *dst, struct scatterlist *src,
+			unsigned int nbytes)
+{
+	struct des3_ede_sparc64_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	struct blkcipher_walk walk;
+	const u64 *K;
+	int err;
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	err = blkcipher_walk_virt(desc, &walk);
+
+	K = &ctx->encrypt_expkey[0];
+	des3_ede_sparc64_load_keys(K);
+	while ((nbytes = walk.nbytes)) {
+		unsigned int block_len = nbytes & DES_BLOCK_MASK;
+
+		if (likely(block_len)) {
+			const u64 *src64 = (const u64 *)walk.src.virt.addr;
+			des3_ede_sparc64_cbc_encrypt(K, src64,
+						     (u64 *) walk.dst.virt.addr,
+						     block_len,
+						     (u64 *) walk.iv);
+		}
+		nbytes &= DES_BLOCK_SIZE - 1;
+		err = blkcipher_walk_done(desc, &walk, nbytes);
+	}
+	fprs_write(0);
+	return err;
+}
+
+extern void des3_ede_sparc64_cbc_decrypt(const u64 *expkey, const u64 *input,
+					 u64 *output, unsigned int len,
+					 u64 *iv);
+
+static int cbc3_decrypt(struct blkcipher_desc *desc,
+			struct scatterlist *dst, struct scatterlist *src,
+			unsigned int nbytes)
+{
+	struct des3_ede_sparc64_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	struct blkcipher_walk walk;
+	const u64 *K;
+	int err;
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	err = blkcipher_walk_virt(desc, &walk);
+
+	K = &ctx->decrypt_expkey[0];
+	des3_ede_sparc64_load_keys(K);
+	while ((nbytes = walk.nbytes)) {
+		unsigned int block_len = nbytes & DES_BLOCK_MASK;
+
+		if (likely(block_len)) {
+			const u64 *src64 = (const u64 *)walk.src.virt.addr;
+			des3_ede_sparc64_cbc_decrypt(K, src64,
+						     (u64 *) walk.dst.virt.addr,
+						     block_len,
+						     (u64 *) walk.iv);
+		}
+		nbytes &= DES_BLOCK_SIZE - 1;
+		err = blkcipher_walk_done(desc, &walk, nbytes);
+	}
+	fprs_write(0);
+	return err;
+}
+
+static struct crypto_alg algs[] = { {
+	.cra_name		= "des",
+	.cra_driver_name	= "des-sparc64",
+	.cra_priority		= SPARC_CR_OPCODE_PRIORITY,
+	.cra_flags		= CRYPTO_ALG_TYPE_CIPHER,
+	.cra_blocksize		= DES_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct des_sparc64_ctx),
+	.cra_alignmask		= 7,
+	.cra_module		= THIS_MODULE,
+	.cra_u	= {
+		.cipher	= {
+			.cia_min_keysize	= DES_KEY_SIZE,
+			.cia_max_keysize	= DES_KEY_SIZE,
+			.cia_setkey		= des_set_key,
+			.cia_encrypt		= des_encrypt,
+			.cia_decrypt		= des_decrypt
+		}
+	}
+}, {
+	.cra_name		= "ecb(des)",
+	.cra_driver_name	= "ecb-des-sparc64",
+	.cra_priority		= SPARC_CR_OPCODE_PRIORITY,
+	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER,
+	.cra_blocksize		= DES_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct des_sparc64_ctx),
+	.cra_alignmask		= 7,
+	.cra_type		= &crypto_blkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_u = {
+		.blkcipher = {
+			.min_keysize	= DES_KEY_SIZE,
+			.max_keysize	= DES_KEY_SIZE,
+			.setkey		= des_set_key,
+			.encrypt	= ecb_encrypt,
+			.decrypt	= ecb_decrypt,
+		},
+	},
+}, {
+	.cra_name		= "cbc(des)",
+	.cra_driver_name	= "cbc-des-sparc64",
+	.cra_priority		= SPARC_CR_OPCODE_PRIORITY,
+	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER,
+	.cra_blocksize		= DES_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct des_sparc64_ctx),
+	.cra_alignmask		= 7,
+	.cra_type		= &crypto_blkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_u = {
+		.blkcipher = {
+			.min_keysize	= DES_KEY_SIZE,
+			.max_keysize	= DES_KEY_SIZE,
+			.setkey		= des_set_key,
+			.encrypt	= cbc_encrypt,
+			.decrypt	= cbc_decrypt,
+		},
+	},
+}, {
+	.cra_name		= "des3_ede",
+	.cra_driver_name	= "des3_ede-sparc64",
+	.cra_priority		= SPARC_CR_OPCODE_PRIORITY,
+	.cra_flags		= CRYPTO_ALG_TYPE_CIPHER,
+	.cra_blocksize		= DES3_EDE_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct des3_ede_sparc64_ctx),
+	.cra_alignmask		= 7,
+	.cra_module		= THIS_MODULE,
+	.cra_u	= {
+		.cipher	= {
+			.cia_min_keysize	= DES3_EDE_KEY_SIZE,
+			.cia_max_keysize	= DES3_EDE_KEY_SIZE,
+			.cia_setkey		= des3_ede_set_key,
+			.cia_encrypt		= des3_ede_encrypt,
+			.cia_decrypt		= des3_ede_decrypt
+		}
+	}
+}, {
+	.cra_name		= "ecb(des3_ede)",
+	.cra_driver_name	= "ecb-des3_ede-sparc64",
+	.cra_priority		= SPARC_CR_OPCODE_PRIORITY,
+	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER,
+	.cra_blocksize		= DES3_EDE_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct des3_ede_sparc64_ctx),
+	.cra_alignmask		= 7,
+	.cra_type		= &crypto_blkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_u = {
+		.blkcipher = {
+			.min_keysize	= DES3_EDE_KEY_SIZE,
+			.max_keysize	= DES3_EDE_KEY_SIZE,
+			.setkey		= des3_ede_set_key,
+			.encrypt	= ecb3_encrypt,
+			.decrypt	= ecb3_decrypt,
+		},
+	},
+}, {
+	.cra_name		= "cbc(des3_ede)",
+	.cra_driver_name	= "cbc-des3_ede-sparc64",
+	.cra_priority		= SPARC_CR_OPCODE_PRIORITY,
+	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER,
+	.cra_blocksize		= DES3_EDE_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct des3_ede_sparc64_ctx),
+	.cra_alignmask		= 7,
+	.cra_type		= &crypto_blkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_u = {
+		.blkcipher = {
+			.min_keysize	= DES3_EDE_KEY_SIZE,
+			.max_keysize	= DES3_EDE_KEY_SIZE,
+			.setkey		= des3_ede_set_key,
+			.encrypt	= cbc3_encrypt,
+			.decrypt	= cbc3_decrypt,
+		},
+	},
+} };
+
+static bool __init sparc64_has_des_opcode(void)
+{
+	unsigned long cfr;
+
+	if (!(sparc64_elf_hwcap & HWCAP_SPARC_CRYPTO))
+		return false;
+
+	__asm__ __volatile__("rd %%asr26, %0" : "=r" (cfr));
+	if (!(cfr & CFR_DES))
+		return false;
+
+	return true;
+}
+
+static int __init des_sparc64_mod_init(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(algs); i++)
+		INIT_LIST_HEAD(&algs[i].cra_list);
+
+	if (sparc64_has_des_opcode()) {
+		pr_info("Using sparc64 des opcodes optimized DES implementation\n");
+		return crypto_register_algs(algs, ARRAY_SIZE(algs));
+	}
+	pr_info("sparc64 des opcodes not available.\n");
+	return -ENODEV;
+}
+
+static void __exit des_sparc64_mod_fini(void)
+{
+	crypto_unregister_algs(algs, ARRAY_SIZE(algs));
+}
+
+module_init(des_sparc64_mod_init);
+module_exit(des_sparc64_mod_fini);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("DES & Triple DES EDE Cipher Algorithms, sparc64 des opcode accelerated");
+
+MODULE_ALIAS("des");
diff --git a/arch/sparc/crypto/md5_asm.S b/arch/sparc/crypto/md5_asm.S
new file mode 100644
index 0000000..3150404
--- /dev/null
+++ b/arch/sparc/crypto/md5_asm.S
@@ -0,0 +1,70 @@
+#include <linux/linkage.h>
+#include <asm/visasm.h>
+
+#include "opcodes.h"
+
+ENTRY(md5_sparc64_transform)
+	/* %o0 = digest, %o1 = data, %o2 = rounds */
+	VISEntryHalf
+	ld	[%o0 + 0x00], %f0
+	ld	[%o0 + 0x04], %f1
+	andcc	%o1, 0x7, %g0
+	ld	[%o0 + 0x08], %f2
+	bne,pn	%xcc, 10f
+	 ld	[%o0 + 0x0c], %f3
+
+1:
+	ldd	[%o1 + 0x00], %f8
+	ldd	[%o1 + 0x08], %f10
+	ldd	[%o1 + 0x10], %f12
+	ldd	[%o1 + 0x18], %f14
+	ldd	[%o1 + 0x20], %f16
+	ldd	[%o1 + 0x28], %f18
+	ldd	[%o1 + 0x30], %f20
+	ldd	[%o1 + 0x38], %f22
+
+	MD5
+
+	subcc	%o2, 1, %o2
+	bne,pt	%xcc, 1b
+	 add	%o1, 0x40, %o1
+
+5:
+	st	%f0, [%o0 + 0x00]
+	st	%f1, [%o0 + 0x04]
+	st	%f2, [%o0 + 0x08]
+	st	%f3, [%o0 + 0x0c]
+	retl
+	 VISExitHalf
+10:
+	alignaddr %o1, %g0, %o1
+
+	ldd	[%o1 + 0x00], %f10
+1:
+	ldd	[%o1 + 0x08], %f12
+	ldd	[%o1 + 0x10], %f14
+	ldd	[%o1 + 0x18], %f16
+	ldd	[%o1 + 0x20], %f18
+	ldd	[%o1 + 0x28], %f20
+	ldd	[%o1 + 0x30], %f22
+	ldd	[%o1 + 0x38], %f24
+	ldd	[%o1 + 0x40], %f26
+
+	faligndata %f10, %f12, %f8
+	faligndata %f12, %f14, %f10
+	faligndata %f14, %f16, %f12
+	faligndata %f16, %f18, %f14
+	faligndata %f18, %f20, %f16
+	faligndata %f20, %f22, %f18
+	faligndata %f22, %f24, %f20
+	faligndata %f24, %f26, %f22
+
+	MD5
+
+	subcc	%o2, 1, %o2
+	fsrc2	%f26, %f10
+	bne,pt	%xcc, 1b
+	 add	%o1, 0x40, %o1
+
+	ba,a,pt	%xcc, 5b
+ENDPROC(md5_sparc64_transform)
diff --git a/arch/sparc/crypto/md5_glue.c b/arch/sparc/crypto/md5_glue.c
new file mode 100644
index 0000000..603d723
--- /dev/null
+++ b/arch/sparc/crypto/md5_glue.c
@@ -0,0 +1,188 @@
+/* Glue code for MD5 hashing optimized for sparc64 crypto opcodes.
+ *
+ * This is based largely upon arch/x86/crypto/sha1_ssse3_glue.c
+ * and crypto/md5.c which are:
+ *
+ * Copyright (c) Alan Smithee.
+ * Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk>
+ * Copyright (c) Jean-Francois Dive <jef@linuxbe.org>
+ * Copyright (c) Mathias Krause <minipli@googlemail.com>
+ * Copyright (c) Cryptoapi developers.
+ * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
+ */
+
+#define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
+
+#include <crypto/internal/hash.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/cryptohash.h>
+#include <linux/types.h>
+#include <crypto/md5.h>
+
+#include <asm/pstate.h>
+#include <asm/elf.h>
+
+#include "opcodes.h"
+
+asmlinkage void md5_sparc64_transform(u32 *digest, const char *data,
+				      unsigned int rounds);
+
+static int md5_sparc64_init(struct shash_desc *desc)
+{
+	struct md5_state *mctx = shash_desc_ctx(desc);
+
+	mctx->hash[0] = cpu_to_le32(0x67452301);
+	mctx->hash[1] = cpu_to_le32(0xefcdab89);
+	mctx->hash[2] = cpu_to_le32(0x98badcfe);
+	mctx->hash[3] = cpu_to_le32(0x10325476);
+	mctx->byte_count = 0;
+
+	return 0;
+}
+
+static void __md5_sparc64_update(struct md5_state *sctx, const u8 *data,
+				 unsigned int len, unsigned int partial)
+{
+	unsigned int done = 0;
+
+	sctx->byte_count += len;
+	if (partial) {
+		done = MD5_HMAC_BLOCK_SIZE - partial;
+		memcpy((u8 *)sctx->block + partial, data, done);
+		md5_sparc64_transform(sctx->hash, (u8 *)sctx->block, 1);
+	}
+	if (len - done >= MD5_HMAC_BLOCK_SIZE) {
+		const unsigned int rounds = (len - done) / MD5_HMAC_BLOCK_SIZE;
+
+		md5_sparc64_transform(sctx->hash, data + done, rounds);
+		done += rounds * MD5_HMAC_BLOCK_SIZE;
+	}
+
+	memcpy(sctx->block, data + done, len - done);
+}
+
+static int md5_sparc64_update(struct shash_desc *desc, const u8 *data,
+			      unsigned int len)
+{
+	struct md5_state *sctx = shash_desc_ctx(desc);
+	unsigned int partial = sctx->byte_count % MD5_HMAC_BLOCK_SIZE;
+
+	/* Handle the fast case right here */
+	if (partial + len < MD5_HMAC_BLOCK_SIZE) {
+		sctx->byte_count += len;
+		memcpy((u8 *)sctx->block + partial, data, len);
+	} else
+		__md5_sparc64_update(sctx, data, len, partial);
+
+	return 0;
+}
+
+/* Add padding and return the message digest. */
+static int md5_sparc64_final(struct shash_desc *desc, u8 *out)
+{
+	struct md5_state *sctx = shash_desc_ctx(desc);
+	unsigned int i, index, padlen;
+	u32 *dst = (u32 *)out;
+	__le64 bits;
+	static const u8 padding[MD5_HMAC_BLOCK_SIZE] = { 0x80, };
+
+	bits = cpu_to_le64(sctx->byte_count << 3);
+
+	/* Pad out to 56 mod 64 and append length */
+	index = sctx->byte_count % MD5_HMAC_BLOCK_SIZE;
+	padlen = (index < 56) ? (56 - index) : ((MD5_HMAC_BLOCK_SIZE+56) - index);
+
+	/* We need to fill a whole block for __md5_sparc64_update() */
+	if (padlen <= 56) {
+		sctx->byte_count += padlen;
+		memcpy((u8 *)sctx->block + index, padding, padlen);
+	} else {
+		__md5_sparc64_update(sctx, padding, padlen, index);
+	}
+	__md5_sparc64_update(sctx, (const u8 *)&bits, sizeof(bits), 56);
+
+	/* Store state in digest */
+	for (i = 0; i < MD5_HASH_WORDS; i++)
+		dst[i] = sctx->hash[i];
+
+	/* Wipe context */
+	memset(sctx, 0, sizeof(*sctx));
+
+	return 0;
+}
+
+static int md5_sparc64_export(struct shash_desc *desc, void *out)
+{
+	struct md5_state *sctx = shash_desc_ctx(desc);
+
+	memcpy(out, sctx, sizeof(*sctx));
+
+	return 0;
+}
+
+static int md5_sparc64_import(struct shash_desc *desc, const void *in)
+{
+	struct md5_state *sctx = shash_desc_ctx(desc);
+
+	memcpy(sctx, in, sizeof(*sctx));
+
+	return 0;
+}
+
+static struct shash_alg alg = {
+	.digestsize	=	MD5_DIGEST_SIZE,
+	.init		=	md5_sparc64_init,
+	.update		=	md5_sparc64_update,
+	.final		=	md5_sparc64_final,
+	.export		=	md5_sparc64_export,
+	.import		=	md5_sparc64_import,
+	.descsize	=	sizeof(struct md5_state),
+	.statesize	=	sizeof(struct md5_state),
+	.base		=	{
+		.cra_name	=	"md5",
+		.cra_driver_name=	"md5-sparc64",
+		.cra_priority	=	SPARC_CR_OPCODE_PRIORITY,
+		.cra_flags	=	CRYPTO_ALG_TYPE_SHASH,
+		.cra_blocksize	=	MD5_HMAC_BLOCK_SIZE,
+		.cra_module	=	THIS_MODULE,
+	}
+};
+
+static bool __init sparc64_has_md5_opcode(void)
+{
+	unsigned long cfr;
+
+	if (!(sparc64_elf_hwcap & HWCAP_SPARC_CRYPTO))
+		return false;
+
+	__asm__ __volatile__("rd %%asr26, %0" : "=r" (cfr));
+	if (!(cfr & CFR_MD5))
+		return false;
+
+	return true;
+}
+
+static int __init md5_sparc64_mod_init(void)
+{
+	if (sparc64_has_md5_opcode()) {
+		pr_info("Using sparc64 md5 opcode optimized MD5 implementation\n");
+		return crypto_register_shash(&alg);
+	}
+	pr_info("sparc64 md5 opcode not available.\n");
+	return -ENODEV;
+}
+
+static void __exit md5_sparc64_mod_fini(void)
+{
+	crypto_unregister_shash(&alg);
+}
+
+module_init(md5_sparc64_mod_init);
+module_exit(md5_sparc64_mod_fini);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("MD5 Secure Hash Algorithm, sparc64 md5 opcode accelerated");
+
+MODULE_ALIAS("md5");
diff --git a/arch/sparc/crypto/opcodes.h b/arch/sparc/crypto/opcodes.h
new file mode 100644
index 0000000..19cbaea
--- /dev/null
+++ b/arch/sparc/crypto/opcodes.h
@@ -0,0 +1,99 @@
+#ifndef _OPCODES_H
+#define _OPCODES_H
+
+#define SPARC_CR_OPCODE_PRIORITY	300
+
+#define F3F(x,y,z)	(((x)<<30)|((y)<<19)|((z)<<5))
+
+#define FPD_ENCODE(x)	(((x) >> 5) | ((x) & ~(0x20)))
+
+#define RS1(x)		(FPD_ENCODE(x) << 14)
+#define RS2(x)		(FPD_ENCODE(x) <<  0)
+#define RS3(x)		(FPD_ENCODE(x) <<  9)
+#define RD(x)		(FPD_ENCODE(x) << 25)
+#define IMM5_0(x)	((x)           <<  0)
+#define IMM5_9(x)	((x)           <<  9)
+
+#define CRC32C(a,b,c)	\
+	.word		(F3F(2,0x36,0x147)|RS1(a)|RS2(b)|RD(c));
+
+#define MD5		\
+	.word	0x81b02800;
+#define SHA1		\
+	.word	0x81b02820;
+#define SHA256		\
+	.word	0x81b02840;
+#define SHA512		\
+	.word	0x81b02860;
+
+#define AES_EROUND01(a,b,c,d)	\
+	.word	(F3F(2, 0x19, 0)|RS1(a)|RS2(b)|RS3(c)|RD(d));
+#define AES_EROUND23(a,b,c,d)	\
+	.word	(F3F(2, 0x19, 1)|RS1(a)|RS2(b)|RS3(c)|RD(d));
+#define AES_DROUND01(a,b,c,d)	\
+	.word	(F3F(2, 0x19, 2)|RS1(a)|RS2(b)|RS3(c)|RD(d));
+#define AES_DROUND23(a,b,c,d)	\
+	.word	(F3F(2, 0x19, 3)|RS1(a)|RS2(b)|RS3(c)|RD(d));
+#define AES_EROUND01_L(a,b,c,d)	\
+	.word	(F3F(2, 0x19, 4)|RS1(a)|RS2(b)|RS3(c)|RD(d));
+#define AES_EROUND23_L(a,b,c,d)	\
+	.word	(F3F(2, 0x19, 5)|RS1(a)|RS2(b)|RS3(c)|RD(d));
+#define AES_DROUND01_L(a,b,c,d)	\
+	.word	(F3F(2, 0x19, 6)|RS1(a)|RS2(b)|RS3(c)|RD(d));
+#define AES_DROUND23_L(a,b,c,d)	\
+	.word	(F3F(2, 0x19, 7)|RS1(a)|RS2(b)|RS3(c)|RD(d));
+#define AES_KEXPAND1(a,b,c,d)	\
+	.word	(F3F(2, 0x19, 8)|RS1(a)|RS2(b)|IMM5_9(c)|RD(d));
+#define AES_KEXPAND0(a,b,c)	\
+	.word	(F3F(2, 0x36, 0x130)|RS1(a)|RS2(b)|RD(c));
+#define AES_KEXPAND2(a,b,c)	\
+	.word	(F3F(2, 0x36, 0x131)|RS1(a)|RS2(b)|RD(c));
+
+#define DES_IP(a,b)		\
+	.word		(F3F(2, 0x36, 0x134)|RS1(a)|RD(b));
+#define DES_IIP(a,b)		\
+	.word		(F3F(2, 0x36, 0x135)|RS1(a)|RD(b));
+#define DES_KEXPAND(a,b,c)	\
+	.word		(F3F(2, 0x36, 0x136)|RS1(a)|IMM5_0(b)|RD(c));
+#define DES_ROUND(a,b,c,d)	\
+	.word		(F3F(2, 0x19, 0x009)|RS1(a)|RS2(b)|RS3(c)|RD(d));
+
+#define CAMELLIA_F(a,b,c,d)		\
+	.word		(F3F(2, 0x19, 0x00c)|RS1(a)|RS2(b)|RS3(c)|RD(d));
+#define CAMELLIA_FL(a,b,c)		\
+	.word		(F3F(2, 0x36, 0x13c)|RS1(a)|RS2(b)|RD(c));
+#define CAMELLIA_FLI(a,b,c)		\
+	.word		(F3F(2, 0x36, 0x13d)|RS1(a)|RS2(b)|RD(c));
+
+#define MOVDTOX_F0_O4		\
+	.word	0x99b02200
+#define MOVDTOX_F2_O5		\
+	.word	0x9bb02202
+#define MOVXTOD_G1_F60 		\
+	.word	0xbbb02301
+#define MOVXTOD_G1_F62 		\
+	.word	0xbfb02301
+#define MOVXTOD_G3_F4		\
+	.word	0x89b02303;
+#define MOVXTOD_G7_F6		\
+	.word	0x8db02307;
+#define MOVXTOD_G3_F0		\
+	.word	0x81b02303;
+#define MOVXTOD_G7_F2		\
+	.word	0x85b02307;
+#define MOVXTOD_O0_F0		\
+	.word	0x81b02308;
+#define MOVXTOD_O5_F0		\
+	.word	0x81b0230d;
+#define MOVXTOD_O5_F2		\
+	.word	0x85b0230d;
+#define MOVXTOD_O5_F4		\
+	.word	0x89b0230d;
+#define MOVXTOD_O5_F6		\
+	.word	0x8db0230d;
+#define MOVXTOD_G3_F60		\
+	.word	0xbbb02303;
+#define MOVXTOD_G7_F62		\
+	.word	0xbfb02307;
+
+#endif /* _OPCODES_H */
diff --git a/arch/sparc/crypto/sha1_asm.S b/arch/sparc/crypto/sha1_asm.S
new file mode 100644
index 0000000..219d10c
--- /dev/null
+++ b/arch/sparc/crypto/sha1_asm.S
@@ -0,0 +1,72 @@
+#include <linux/linkage.h>
+#include <asm/visasm.h>
+
+#include "opcodes.h"
+
+ENTRY(sha1_sparc64_transform)
+	/* %o0 = digest, %o1 = data, %o2 = rounds */
+	VISEntryHalf
+	ld	[%o0 + 0x00], %f0
+	ld	[%o0 + 0x04], %f1
+	ld	[%o0 + 0x08], %f2
+	andcc	%o1, 0x7, %g0
+	ld	[%o0 + 0x0c], %f3
+	bne,pn	%xcc, 10f
+	 ld	[%o0 + 0x10], %f4
+
+1:
+	ldd	[%o1 + 0x00], %f8
+	ldd	[%o1 + 0x08], %f10
+	ldd	[%o1 + 0x10], %f12
+	ldd	[%o1 + 0x18], %f14
+	ldd	[%o1 + 0x20], %f16
+	ldd	[%o1 + 0x28], %f18
+	ldd	[%o1 + 0x30], %f20
+	ldd	[%o1 + 0x38], %f22
+
+	SHA1
+
+	subcc	%o2, 1, %o2
+	bne,pt	%xcc, 1b
+	 add	%o1, 0x40, %o1
+
+5:
+	st	%f0, [%o0 + 0x00]
+	st	%f1, [%o0 + 0x04]
+	st	%f2, [%o0 + 0x08]
+	st	%f3, [%o0 + 0x0c]
+	st	%f4, [%o0 + 0x10]
+	retl
+	 VISExitHalf
+10:
+	alignaddr %o1, %g0, %o1
+
+	ldd	[%o1 + 0x00], %f10
+1:
+	ldd	[%o1 + 0x08], %f12
+	ldd	[%o1 + 0x10], %f14
+	ldd	[%o1 + 0x18], %f16
+	ldd	[%o1 + 0x20], %f18
+	ldd	[%o1 + 0x28], %f20
+	ldd	[%o1 + 0x30], %f22
+	ldd	[%o1 + 0x38], %f24
+	ldd	[%o1 + 0x40], %f26
+
+	faligndata %f10, %f12, %f8
+	faligndata %f12, %f14, %f10
+	faligndata %f14, %f16, %f12
+	faligndata %f16, %f18, %f14
+	faligndata %f18, %f20, %f16
+	faligndata %f20, %f22, %f18
+	faligndata %f22, %f24, %f20
+	faligndata %f24, %f26, %f22
+
+	SHA1
+
+	subcc	%o2, 1, %o2
+	fsrc2	%f26, %f10
+	bne,pt	%xcc, 1b
+	 add	%o1, 0x40, %o1
+
+	ba,a,pt	%xcc, 5b
+ENDPROC(sha1_sparc64_transform)
diff --git a/arch/sparc/crypto/sha1_glue.c b/arch/sparc/crypto/sha1_glue.c
new file mode 100644
index 0000000..2bbb20b
--- /dev/null
+++ b/arch/sparc/crypto/sha1_glue.c
@@ -0,0 +1,183 @@
+/* Glue code for SHA1 hashing optimized for sparc64 crypto opcodes.
+ *
+ * This is based largely upon arch/x86/crypto/sha1_ssse3_glue.c
+ *
+ * Copyright (c) Alan Smithee.
+ * Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk>
+ * Copyright (c) Jean-Francois Dive <jef@linuxbe.org>
+ * Copyright (c) Mathias Krause <minipli@googlemail.com>
+ */
+
+#define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
+
+#include <crypto/internal/hash.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/cryptohash.h>
+#include <linux/types.h>
+#include <crypto/sha.h>
+
+#include <asm/pstate.h>
+#include <asm/elf.h>
+
+#include "opcodes.h"
+
+asmlinkage void sha1_sparc64_transform(u32 *digest, const char *data,
+				       unsigned int rounds);
+
+static int sha1_sparc64_init(struct shash_desc *desc)
+{
+	struct sha1_state *sctx = shash_desc_ctx(desc);
+
+	*sctx = (struct sha1_state){
+		.state = { SHA1_H0, SHA1_H1, SHA1_H2, SHA1_H3, SHA1_H4 },
+	};
+
+	return 0;
+}
+
+static void __sha1_sparc64_update(struct sha1_state *sctx, const u8 *data,
+				  unsigned int len, unsigned int partial)
+{
+	unsigned int done = 0;
+
+	sctx->count += len;
+	if (partial) {
+		done = SHA1_BLOCK_SIZE - partial;
+		memcpy(sctx->buffer + partial, data, done);
+		sha1_sparc64_transform(sctx->state, sctx->buffer, 1);
+	}
+	if (len - done >= SHA1_BLOCK_SIZE) {
+		const unsigned int rounds = (len - done) / SHA1_BLOCK_SIZE;
+
+		sha1_sparc64_transform(sctx->state, data + done, rounds);
+		done += rounds * SHA1_BLOCK_SIZE;
+	}
+
+	memcpy(sctx->buffer, data + done, len - done);
+}
+
+static int sha1_sparc64_update(struct shash_desc *desc, const u8 *data,
+			       unsigned int len)
+{
+	struct sha1_state *sctx = shash_desc_ctx(desc);
+	unsigned int partial = sctx->count % SHA1_BLOCK_SIZE;
+
+	/* Handle the fast case right here */
+	if (partial + len < SHA1_BLOCK_SIZE) {
+		sctx->count += len;
+		memcpy(sctx->buffer + partial, data, len);
+	} else
+		__sha1_sparc64_update(sctx, data, len, partial);
+
+	return 0;
+}
+
+/* Add padding and return the message digest. */
+static int sha1_sparc64_final(struct shash_desc *desc, u8 *out)
+{
+	struct sha1_state *sctx = shash_desc_ctx(desc);
+	unsigned int i, index, padlen;
+	__be32 *dst = (__be32 *)out;
+	__be64 bits;
+	static const u8 padding[SHA1_BLOCK_SIZE] = { 0x80, };
+
+	bits = cpu_to_be64(sctx->count << 3);
+
+	/* Pad out to 56 mod 64 and append length */
+	index = sctx->count % SHA1_BLOCK_SIZE;
+	padlen = (index < 56) ? (56 - index) : ((SHA1_BLOCK_SIZE+56) - index);
+
+	/* We need to fill a whole block for __sha1_sparc64_update() */
+	if (padlen <= 56) {
+		sctx->count += padlen;
+		memcpy(sctx->buffer + index, padding, padlen);
+	} else {
+		__sha1_sparc64_update(sctx, padding, padlen, index);
+	}
+	__sha1_sparc64_update(sctx, (const u8 *)&bits, sizeof(bits), 56);
+
+	/* Store state in digest */
+	for (i = 0; i < 5; i++)
+		dst[i] = cpu_to_be32(sctx->state[i]);
+
+	/* Wipe context */
+	memset(sctx, 0, sizeof(*sctx));
+
+	return 0;
+}
+
+static int sha1_sparc64_export(struct shash_desc *desc, void *out)
+{
+	struct sha1_state *sctx = shash_desc_ctx(desc);
+
+	memcpy(out, sctx, sizeof(*sctx));
+
+	return 0;
+}
+
+static int sha1_sparc64_import(struct shash_desc *desc, const void *in)
+{
+	struct sha1_state *sctx = shash_desc_ctx(desc);
+
+	memcpy(sctx, in, sizeof(*sctx));
+
+	return 0;
+}
+
+static struct shash_alg alg = {
+	.digestsize	=	SHA1_DIGEST_SIZE,
+	.init		=	sha1_sparc64_init,
+	.update		=	sha1_sparc64_update,
+	.final		=	sha1_sparc64_final,
+	.export		=	sha1_sparc64_export,
+	.import		=	sha1_sparc64_import,
+	.descsize	=	sizeof(struct sha1_state),
+	.statesize	=	sizeof(struct sha1_state),
+	.base		=	{
+		.cra_name	=	"sha1",
+		.cra_driver_name=	"sha1-sparc64",
+		.cra_priority	=	SPARC_CR_OPCODE_PRIORITY,
+		.cra_flags	=	CRYPTO_ALG_TYPE_SHASH,
+		.cra_blocksize	=	SHA1_BLOCK_SIZE,
+		.cra_module	=	THIS_MODULE,
+	}
+};
+
+static bool __init sparc64_has_sha1_opcode(void)
+{
+	unsigned long cfr;
+
+	if (!(sparc64_elf_hwcap & HWCAP_SPARC_CRYPTO))
+		return false;
+
+	__asm__ __volatile__("rd %%asr26, %0" : "=r" (cfr));
+	if (!(cfr & CFR_SHA1))
+		return false;
+
+	return true;
+}
+
+static int __init sha1_sparc64_mod_init(void)
+{
+	if (sparc64_has_sha1_opcode()) {
+		pr_info("Using sparc64 sha1 opcode optimized SHA-1 implementation\n");
+		return crypto_register_shash(&alg);
+	}
+	pr_info("sparc64 sha1 opcode not available.\n");
+	return -ENODEV;
+}
+
+static void __exit sha1_sparc64_mod_fini(void)
+{
+	crypto_unregister_shash(&alg);
+}
+
+module_init(sha1_sparc64_mod_init);
+module_exit(sha1_sparc64_mod_fini);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm, sparc64 sha1 opcode accelerated");
+
+MODULE_ALIAS("sha1");
diff --git a/arch/sparc/crypto/sha256_asm.S b/arch/sparc/crypto/sha256_asm.S
new file mode 100644
index 0000000..b5f3d58
--- /dev/null
+++ b/arch/sparc/crypto/sha256_asm.S
@@ -0,0 +1,78 @@
+#include <linux/linkage.h>
+#include <asm/visasm.h>
+
+#include "opcodes.h"
+
+ENTRY(sha256_sparc64_transform)
+	/* %o0 = digest, %o1 = data, %o2 = rounds */
+	VISEntryHalf
+	ld	[%o0 + 0x00], %f0
+	ld	[%o0 + 0x04], %f1
+	ld	[%o0 + 0x08], %f2
+	ld	[%o0 + 0x0c], %f3
+	ld	[%o0 + 0x10], %f4
+	ld	[%o0 + 0x14], %f5
+	andcc	%o1, 0x7, %g0
+	ld	[%o0 + 0x18], %f6
+	bne,pn	%xcc, 10f
+	 ld	[%o0 + 0x1c], %f7
+
+1:
+	ldd	[%o1 + 0x00], %f8
+	ldd	[%o1 + 0x08], %f10
+	ldd	[%o1 + 0x10], %f12
+	ldd	[%o1 + 0x18], %f14
+	ldd	[%o1 + 0x20], %f16
+	ldd	[%o1 + 0x28], %f18
+	ldd	[%o1 + 0x30], %f20
+	ldd	[%o1 + 0x38], %f22
+
+	SHA256
+
+	subcc	%o2, 1, %o2
+	bne,pt	%xcc, 1b
+	 add	%o1, 0x40, %o1
+
+5:
+	st	%f0, [%o0 + 0x00]
+	st	%f1, [%o0 + 0x04]
+	st	%f2, [%o0 + 0x08]
+	st	%f3, [%o0 + 0x0c]
+	st	%f4, [%o0 + 0x10]
+	st	%f5, [%o0 + 0x14]
+	st	%f6, [%o0 + 0x18]
+	st	%f7, [%o0 + 0x1c]
+	retl
+	 VISExitHalf
+10:
+	alignaddr %o1, %g0, %o1
+
+	ldd	[%o1 + 0x00], %f10
+1:
+	ldd	[%o1 + 0x08], %f12
+	ldd	[%o1 + 0x10], %f14
+	ldd	[%o1 + 0x18], %f16
+	ldd	[%o1 + 0x20], %f18
+	ldd	[%o1 + 0x28], %f20
+	ldd	[%o1 + 0x30], %f22
+	ldd	[%o1 + 0x38], %f24
+	ldd	[%o1 + 0x40], %f26
+
+	faligndata %f10, %f12, %f8
+	faligndata %f12, %f14, %f10
+	faligndata %f14, %f16, %f12
+	faligndata %f16, %f18, %f14
+	faligndata %f18, %f20, %f16
+	faligndata %f20, %f22, %f18
+	faligndata %f22, %f24, %f20
+	faligndata %f24, %f26, %f22
+
+	SHA256
+
+	subcc	%o2, 1, %o2
+	fsrc2	%f26, %f10
+	bne,pt	%xcc, 1b
+	 add	%o1, 0x40, %o1
+
+	ba,a,pt	%xcc, 5b
+ENDPROC(sha256_sparc64_transform)
diff --git a/arch/sparc/crypto/sha256_glue.c b/arch/sparc/crypto/sha256_glue.c
new file mode 100644
index 0000000..591e656
--- /dev/null
+++ b/arch/sparc/crypto/sha256_glue.c
@@ -0,0 +1,241 @@
+/* Glue code for SHA256 hashing optimized for sparc64 crypto opcodes.
+ *
+ * This is based largely upon crypto/sha256_generic.c
+ *
+ * Copyright (c) Jean-Luc Cooke <jlcooke@certainkey.com>
+ * Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk>
+ * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
+ * SHA224 Support Copyright 2007 Intel Corporation <jonathan.lynch@intel.com>
+ */
+
+#define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
+
+#include <crypto/internal/hash.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/cryptohash.h>
+#include <linux/types.h>
+#include <crypto/sha.h>
+
+#include <asm/pstate.h>
+#include <asm/elf.h>
+
+#include "opcodes.h"
+
+asmlinkage void sha256_sparc64_transform(u32 *digest, const char *data,
+					 unsigned int rounds);
+
+static int sha224_sparc64_init(struct shash_desc *desc)
+{
+	struct sha256_state *sctx = shash_desc_ctx(desc);
+	sctx->state[0] = SHA224_H0;
+	sctx->state[1] = SHA224_H1;
+	sctx->state[2] = SHA224_H2;
+	sctx->state[3] = SHA224_H3;
+	sctx->state[4] = SHA224_H4;
+	sctx->state[5] = SHA224_H5;
+	sctx->state[6] = SHA224_H6;
+	sctx->state[7] = SHA224_H7;
+	sctx->count = 0;
+
+	return 0;
+}
+
+static int sha256_sparc64_init(struct shash_desc *desc)
+{
+	struct sha256_state *sctx = shash_desc_ctx(desc);
+	sctx->state[0] = SHA256_H0;
+	sctx->state[1] = SHA256_H1;
+	sctx->state[2] = SHA256_H2;
+	sctx->state[3] = SHA256_H3;
+	sctx->state[4] = SHA256_H4;
+	sctx->state[5] = SHA256_H5;
+	sctx->state[6] = SHA256_H6;
+	sctx->state[7] = SHA256_H7;
+	sctx->count = 0;
+
+	return 0;
+}
+
+static void __sha256_sparc64_update(struct sha256_state *sctx, const u8 *data,
+				    unsigned int len, unsigned int partial)
+{
+	unsigned int done = 0;
+
+	sctx->count += len;
+	if (partial) {
+		done = SHA256_BLOCK_SIZE - partial;
+		memcpy(sctx->buf + partial, data, done);
+		sha256_sparc64_transform(sctx->state, sctx->buf, 1);
+	}
+	if (len - done >= SHA256_BLOCK_SIZE) {
+		const unsigned int rounds = (len - done) / SHA256_BLOCK_SIZE;
+
+		sha256_sparc64_transform(sctx->state, data + done, rounds);
+		done += rounds * SHA256_BLOCK_SIZE;
+	}
+
+	memcpy(sctx->buf, data + done, len - done);
+}
+
+static int sha256_sparc64_update(struct shash_desc *desc, const u8 *data,
+				 unsigned int len)
+{
+	struct sha256_state *sctx = shash_desc_ctx(desc);
+	unsigned int partial = sctx->count % SHA256_BLOCK_SIZE;
+
+	/* Handle the fast case right here */
+	if (partial + len < SHA256_BLOCK_SIZE) {
+		sctx->count += len;
+		memcpy(sctx->buf + partial, data, len);
+	} else
+		__sha256_sparc64_update(sctx, data, len, partial);
+
+	return 0;
+}
+
+static int sha256_sparc64_final(struct shash_desc *desc, u8 *out)
+{
+	struct sha256_state *sctx = shash_desc_ctx(desc);
+	unsigned int i, index, padlen;
+	__be32 *dst = (__be32 *)out;
+	__be64 bits;
+	static const u8 padding[SHA256_BLOCK_SIZE] = { 0x80, };
+
+	bits = cpu_to_be64(sctx->count << 3);
+
+	/* Pad out to 56 mod 64 and append length */
+	index = sctx->count % SHA256_BLOCK_SIZE;
+	padlen = (index < 56) ? (56 - index) : ((SHA256_BLOCK_SIZE+56) - index);
+
+	/* We need to fill a whole block for __sha256_sparc64_update() */
+	if (padlen <= 56) {
+		sctx->count += padlen;
+		memcpy(sctx->buf + index, padding, padlen);
+	} else {
+		__sha256_sparc64_update(sctx, padding, padlen, index);
+	}
+	__sha256_sparc64_update(sctx, (const u8 *)&bits, sizeof(bits), 56);
+
+	/* Store state in digest */
+	for (i = 0; i < 8; i++)
+		dst[i] = cpu_to_be32(sctx->state[i]);
+
+	/* Wipe context */
+	memset(sctx, 0, sizeof(*sctx));
+
+	return 0;
+}
+
+static int sha224_sparc64_final(struct shash_desc *desc, u8 *hash)
+{
+	u8 D[SHA256_DIGEST_SIZE];
+
+	sha256_sparc64_final(desc, D);
+
+	memcpy(hash, D, SHA224_DIGEST_SIZE);
+	memset(D, 0, SHA256_DIGEST_SIZE);
+
+	return 0;
+}
+
+static int sha256_sparc64_export(struct shash_desc *desc, void *out)
+{
+	struct sha256_state *sctx = shash_desc_ctx(desc);
+
+	memcpy(out, sctx, sizeof(*sctx));
+	return 0;
+}
+
+static int sha256_sparc64_import(struct shash_desc *desc, const void *in)
+{
+	struct sha256_state *sctx = shash_desc_ctx(desc);
+
+	memcpy(sctx, in, sizeof(*sctx));
+	return 0;
+}
+
+static struct shash_alg sha256 = {
+	.digestsize	=	SHA256_DIGEST_SIZE,
+	.init		=	sha256_sparc64_init,
+	.update		=	sha256_sparc64_update,
+	.final		=	sha256_sparc64_final,
+	.export		=	sha256_sparc64_export,
+	.import		=	sha256_sparc64_import,
+	.descsize	=	sizeof(struct sha256_state),
+	.statesize	=	sizeof(struct sha256_state),
+	.base		=	{
+		.cra_name	=	"sha256",
+		.cra_driver_name=	"sha256-sparc64",
+		.cra_priority	=	SPARC_CR_OPCODE_PRIORITY,
+		.cra_flags	=	CRYPTO_ALG_TYPE_SHASH,
+		.cra_blocksize	=	SHA256_BLOCK_SIZE,
+		.cra_module	=	THIS_MODULE,
+	}
+};
+
+static struct shash_alg sha224 = {
+	.digestsize	=	SHA224_DIGEST_SIZE,
+	.init		=	sha224_sparc64_init,
+	.update		=	sha256_sparc64_update,
+	.final		=	sha224_sparc64_final,
+	.descsize	=	sizeof(struct sha256_state),
+	.base		=	{
+		.cra_name	=	"sha224",
+		.cra_driver_name=	"sha224-sparc64",
+		.cra_priority	=	SPARC_CR_OPCODE_PRIORITY,
+		.cra_flags	=	CRYPTO_ALG_TYPE_SHASH,
+		.cra_blocksize	=	SHA224_BLOCK_SIZE,
+		.cra_module	=	THIS_MODULE,
+	}
+};
+
+static bool __init sparc64_has_sha256_opcode(void)
+{
+	unsigned long cfr;
+
+	if (!(sparc64_elf_hwcap & HWCAP_SPARC_CRYPTO))
+		return false;
+
+	__asm__ __volatile__("rd %%asr26, %0" : "=r" (cfr));
+	if (!(cfr & CFR_SHA256))
+		return false;
+
+	return true;
+}
+
+static int __init sha256_sparc64_mod_init(void)
+{
+	if (sparc64_has_sha256_opcode()) {
+		int ret = crypto_register_shash(&sha224);
+		if (ret < 0)
+			return ret;
+
+		ret = crypto_register_shash(&sha256);
+		if (ret < 0) {
+			crypto_unregister_shash(&sha224);
+			return ret;
+		}
+
+		pr_info("Using sparc64 sha256 opcode optimized SHA-256/SHA-224 implementation\n");
+		return 0;
+	}
+	pr_info("sparc64 sha256 opcode not available.\n");
+	return -ENODEV;
+}
+
+static void __exit sha256_sparc64_mod_fini(void)
+{
+	crypto_unregister_shash(&sha224);
+	crypto_unregister_shash(&sha256);
+}
+
+module_init(sha256_sparc64_mod_init);
+module_exit(sha256_sparc64_mod_fini);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("SHA-224 and SHA-256 Secure Hash Algorithm, sparc64 sha256 opcode accelerated");
+
+MODULE_ALIAS("sha224");
+MODULE_ALIAS("sha256");
diff --git a/arch/sparc/crypto/sha512_asm.S b/arch/sparc/crypto/sha512_asm.S
new file mode 100644
index 0000000..54bfba7
--- /dev/null
+++ b/arch/sparc/crypto/sha512_asm.S
@@ -0,0 +1,102 @@
+#include <linux/linkage.h>
+#include <asm/visasm.h>
+
+#include "opcodes.h"
+
+ENTRY(sha512_sparc64_transform)
+	/* %o0 = digest, %o1 = data, %o2 = rounds */
+	VISEntry
+	ldd	[%o0 + 0x00], %f0
+	ldd	[%o0 + 0x08], %f2
+	ldd	[%o0 + 0x10], %f4
+	ldd	[%o0 + 0x18], %f6
+	ldd	[%o0 + 0x20], %f8
+	ldd	[%o0 + 0x28], %f10
+	andcc	%o1, 0x7, %g0
+	ldd	[%o0 + 0x30], %f12
+	bne,pn	%xcc, 10f
+	 ldd	[%o0 + 0x38], %f14
+
+1:
+	ldd	[%o1 + 0x00], %f16
+	ldd	[%o1 + 0x08], %f18
+	ldd	[%o1 + 0x10], %f20
+	ldd	[%o1 + 0x18], %f22
+	ldd	[%o1 + 0x20], %f24
+	ldd	[%o1 + 0x28], %f26
+	ldd	[%o1 + 0x30], %f28
+	ldd	[%o1 + 0x38], %f30
+	ldd	[%o1 + 0x40], %f32
+	ldd	[%o1 + 0x48], %f34
+	ldd	[%o1 + 0x50], %f36
+	ldd	[%o1 + 0x58], %f38
+	ldd	[%o1 + 0x60], %f40
+	ldd	[%o1 + 0x68], %f42
+	ldd	[%o1 + 0x70], %f44
+	ldd	[%o1 + 0x78], %f46
+
+	SHA512
+
+	subcc	%o2, 1, %o2
+	bne,pt	%xcc, 1b
+	 add	%o1, 0x80, %o1
+
+5:
+	std	%f0, [%o0 + 0x00]
+	std	%f2, [%o0 + 0x08]
+	std	%f4, [%o0 + 0x10]
+	std	%f6, [%o0 + 0x18]
+	std	%f8, [%o0 + 0x20]
+	std	%f10, [%o0 + 0x28]
+	std	%f12, [%o0 + 0x30]
+	std	%f14, [%o0 + 0x38]
+	retl
+	 VISExit
+10:
+	alignaddr %o1, %g0, %o1
+
+	ldd	[%o1 + 0x00], %f18
+1:
+	ldd	[%o1 + 0x08], %f20
+	ldd	[%o1 + 0x10], %f22
+	ldd	[%o1 + 0x18], %f24
+	ldd	[%o1 + 0x20], %f26
+	ldd	[%o1 + 0x28], %f28
+	ldd	[%o1 + 0x30], %f30
+	ldd	[%o1 + 0x38], %f32
+	ldd	[%o1 + 0x40], %f34
+	ldd	[%o1 + 0x48], %f36
+	ldd	[%o1 + 0x50], %f38
+	ldd	[%o1 + 0x58], %f40
+	ldd	[%o1 + 0x60], %f42
+	ldd	[%o1 + 0x68], %f44
+	ldd	[%o1 + 0x70], %f46
+	ldd	[%o1 + 0x78], %f48
+	ldd	[%o1 + 0x80], %f50
+
+	faligndata %f18, %f20, %f16
+	faligndata %f20, %f22, %f18
+	faligndata %f22, %f24, %f20
+	faligndata %f24, %f26, %f22
+	faligndata %f26, %f28, %f24
+	faligndata %f28, %f30, %f26
+	faligndata %f30, %f32, %f28
+	faligndata %f32, %f34, %f30
+	faligndata %f34, %f36, %f32
+	faligndata %f36, %f38, %f34
+	faligndata %f38, %f40, %f36
+	faligndata %f40, %f42, %f38
+	faligndata %f42, %f44, %f40
+	faligndata %f44, %f46, %f42
+	faligndata %f46, %f48, %f44
+	faligndata %f48, %f50, %f46
+
+	SHA512
+
+	subcc	%o2, 1, %o2
+	fsrc2	%f50, %f18
+	bne,pt	%xcc, 1b
+	 add	%o1, 0x80, %o1
+
+	ba,a,pt	%xcc, 5b
+ENDPROC(sha512_sparc64_transform)
diff --git a/arch/sparc/crypto/sha512_glue.c b/arch/sparc/crypto/sha512_glue.c
new file mode 100644
index 0000000..486f0a2
--- /dev/null
+++ b/arch/sparc/crypto/sha512_glue.c
@@ -0,0 +1,226 @@
+/* Glue code for SHA512 hashing optimized for sparc64 crypto opcodes.
+ *
+ * This is based largely upon crypto/sha512_generic.c
+ *
+ * Copyright (c) Jean-Luc Cooke <jlcooke@certainkey.com>
+ * Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk>
+ * Copyright (c) 2003 Kyle McMartin <kyle@debian.org>
+ */
+
+#define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
+
+#include <crypto/internal/hash.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/cryptohash.h>
+#include <linux/types.h>
+#include <crypto/sha.h>
+
+#include <asm/pstate.h>
+#include <asm/elf.h>
+
+#include "opcodes.h"
+
+asmlinkage void sha512_sparc64_transform(u64 *digest, const char *data,
+					 unsigned int rounds);
+
+static int sha512_sparc64_init(struct shash_desc *desc)
+{
+	struct sha512_state *sctx = shash_desc_ctx(desc);
+	sctx->state[0] = SHA512_H0;
+	sctx->state[1] = SHA512_H1;
+	sctx->state[2] = SHA512_H2;
+	sctx->state[3] = SHA512_H3;
+	sctx->state[4] = SHA512_H4;
+	sctx->state[5] = SHA512_H5;
+	sctx->state[6] = SHA512_H6;
+	sctx->state[7] = SHA512_H7;
+	sctx->count[0] = sctx->count[1] = 0;
+
+	return 0;
+}
+
+static int sha384_sparc64_init(struct shash_desc *desc)
+{
+	struct sha512_state *sctx = shash_desc_ctx(desc);
+	sctx->state[0] = SHA384_H0;
+	sctx->state[1] = SHA384_H1;
+	sctx->state[2] = SHA384_H2;
+	sctx->state[3] = SHA384_H3;
+	sctx->state[4] = SHA384_H4;
+	sctx->state[5] = SHA384_H5;
+	sctx->state[6] = SHA384_H6;
+	sctx->state[7] = SHA384_H7;
+	sctx->count[0] = sctx->count[1] = 0;
+
+	return 0;
+}
+
+static void __sha512_sparc64_update(struct sha512_state *sctx, const u8 *data,
+				    unsigned int len, unsigned int partial)
+{
+	unsigned int done = 0;
+
+	if ((sctx->count[0] += len) < len)
+		sctx->count[1]++;
+	if (partial) {
+		done = SHA512_BLOCK_SIZE - partial;
+		memcpy(sctx->buf + partial, data, done);
+		sha512_sparc64_transform(sctx->state, sctx->buf, 1);
+	}
+	if (len - done >= SHA512_BLOCK_SIZE) {
+		const unsigned int rounds = (len - done) / SHA512_BLOCK_SIZE;
+
+		sha512_sparc64_transform(sctx->state, data + done, rounds);
+		done += rounds * SHA512_BLOCK_SIZE;
+	}
+
+	memcpy(sctx->buf, data + done, len - done);
+}
+
+static int sha512_sparc64_update(struct shash_desc *desc, const u8 *data,
+				 unsigned int len)
+{
+	struct sha512_state *sctx = shash_desc_ctx(desc);
+	unsigned int partial = sctx->count[0] % SHA512_BLOCK_SIZE;
+
+	/* Handle the fast case right here */
+	if (partial + len < SHA512_BLOCK_SIZE) {
+		if ((sctx->count[0] += len) < len)
+			sctx->count[1]++;
+		memcpy(sctx->buf + partial, data, len);
+	} else
+		__sha512_sparc64_update(sctx, data, len, partial);
+
+	return 0;
+}
+
+static int sha512_sparc64_final(struct shash_desc *desc, u8 *out)
+{
+	struct sha512_state *sctx = shash_desc_ctx(desc);
+	unsigned int i, index, padlen;
+	__be64 *dst = (__be64 *)out;
+	__be64 bits[2];
+	static const u8 padding[SHA512_BLOCK_SIZE] = { 0x80, };
+
+	/* Save number of bits */
+	bits[1] = cpu_to_be64(sctx->count[0] << 3);
+	bits[0] = cpu_to_be64(sctx->count[1] << 3 | sctx->count[0] >> 61);
+
+	/* Pad out to 112 mod 128 and append length */
+	index = sctx->count[0] % SHA512_BLOCK_SIZE;
+	padlen = (index < 112) ? (112 - index) : ((SHA512_BLOCK_SIZE+112) - index);
+
+	/* We need to fill a whole block for __sha512_sparc64_update() */
+	if (padlen <= 112) {
+		if ((sctx->count[0] += padlen) < padlen)
+			sctx->count[1]++;
+		memcpy(sctx->buf + index, padding, padlen);
+	} else {
+		__sha512_sparc64_update(sctx, padding, padlen, index);
+	}
+	__sha512_sparc64_update(sctx, (const u8 *)&bits, sizeof(bits), 112);
+
+	/* Store state in digest */
+	for (i = 0; i < 8; i++)
+		dst[i] = cpu_to_be64(sctx->state[i]);
+
+	/* Wipe context */
+	memset(sctx, 0, sizeof(*sctx));
+
+	return 0;
+}
+
+static int sha384_sparc64_final(struct shash_desc *desc, u8 *hash)
+{
+	u8 D[64];
+
+	sha512_sparc64_final(desc, D);
+
+	memcpy(hash, D, 48);
+	memset(D, 0, 64);
+
+	return 0;
+}
+
+static struct shash_alg sha512 = {
+	.digestsize	=	SHA512_DIGEST_SIZE,
+	.init		=	sha512_sparc64_init,
+	.update		=	sha512_sparc64_update,
+	.final		=	sha512_sparc64_final,
+	.descsize	=	sizeof(struct sha512_state),
+	.base		=	{
+		.cra_name	=	"sha512",
+		.cra_driver_name=	"sha512-sparc64",
+		.cra_priority	=	SPARC_CR_OPCODE_PRIORITY,
+		.cra_flags	=	CRYPTO_ALG_TYPE_SHASH,
+		.cra_blocksize	=	SHA512_BLOCK_SIZE,
+		.cra_module	=	THIS_MODULE,
+	}
+};
+
+static struct shash_alg sha384 = {
+	.digestsize	=	SHA384_DIGEST_SIZE,
+	.init		=	sha384_sparc64_init,
+	.update		=	sha512_sparc64_update,
+	.final		=	sha384_sparc64_final,
+	.descsize	=	sizeof(struct sha512_state),
+	.base		=	{
+		.cra_name	=	"sha384",
+		.cra_driver_name=	"sha384-sparc64",
+		.cra_priority	=	SPARC_CR_OPCODE_PRIORITY,
+		.cra_flags	=	CRYPTO_ALG_TYPE_SHASH,
+		.cra_blocksize	=	SHA384_BLOCK_SIZE,
+		.cra_module	=	THIS_MODULE,
+	}
+};
+
+static bool __init sparc64_has_sha512_opcode(void)
+{
+	unsigned long cfr;
+
+	if (!(sparc64_elf_hwcap & HWCAP_SPARC_CRYPTO))
+		return false;
+
+	__asm__ __volatile__("rd %%asr26, %0" : "=r" (cfr));
+	if (!(cfr & CFR_SHA512))
+		return false;
+
+	return true;
+}
+
+static int __init sha512_sparc64_mod_init(void)
+{
+	if (sparc64_has_sha512_opcode()) {
+		int ret = crypto_register_shash(&sha384);
+		if (ret < 0)
+			return ret;
+
+		ret = crypto_register_shash(&sha512);
+		if (ret < 0) {
+			crypto_unregister_shash(&sha384);
+			return ret;
+		}
+
+		pr_info("Using sparc64 sha512 opcode optimized SHA-512/SHA-384 implementation\n");
+		return 0;
+	}
+	pr_info("sparc64 sha512 opcode not available.\n");
+	return -ENODEV;
+}
+
+static void __exit sha512_sparc64_mod_fini(void)
+{
+	crypto_unregister_shash(&sha384);
+	crypto_unregister_shash(&sha512);
+}
+
+module_init(sha512_sparc64_mod_init);
+module_exit(sha512_sparc64_mod_fini);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("SHA-384 and SHA-512 Secure Hash Algorithm, sparc64 sha512 opcode accelerated");
+
+MODULE_ALIAS("sha384");
+MODULE_ALIAS("sha512");
diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild
index 67f83e0..c5833f4 100644
--- a/arch/sparc/include/asm/Kbuild
+++ b/arch/sparc/include/asm/Kbuild
@@ -18,7 +18,9 @@ header-y += utrap.h
 header-y += watchdog.h
 
 generic-y += div64.h
+generic-y += exec.h
 generic-y += local64.h
 generic-y += irq_regs.h
 generic-y += local.h
+generic-y += module.h
 generic-y += word-at-a-time.h
diff --git a/arch/sparc/include/asm/asi.h b/arch/sparc/include/asm/asi.h
index 61ebe74..cc0006d 100644
--- a/arch/sparc/include/asm/asi.h
+++ b/arch/sparc/include/asm/asi.h
@@ -141,7 +141,8 @@
 /* SpitFire and later extended ASIs.  The "(III)" marker designates
  * UltraSparc-III and later specific ASIs.  The "(CMT)" marker designates
  * Chip Multi Threading specific ASIs.  "(NG)" designates Niagara specific
- * ASIs, "(4V)" designates SUN4V specific ASIs.
+ * ASIs, "(4V)" designates SUN4V specific ASIs.  "(NG4)" designates SPARC-T4
+ * and later ASIs.
  */
 #define ASI_PHYS_USE_EC		0x14 /* PADDR, E-cachable		*/
 #define ASI_PHYS_BYPASS_EC_E	0x15 /* PADDR, E-bit			*/
@@ -243,6 +244,7 @@
 #define ASI_UDBL_CONTROL_R	0x7f /* External UDB control regs rd low*/
 #define ASI_INTR_R		0x7f /* IRQ vector dispatch read	*/
 #define ASI_INTR_DATAN_R	0x7f /* (III) In irq vector data reg N	*/
+#define ASI_PIC			0xb0 /* (NG4) PIC registers		*/
 #define ASI_PST8_P		0xc0 /* Primary, 8 8-bit, partial	*/
 #define ASI_PST8_S		0xc1 /* Secondary, 8 8-bit, partial	*/
 #define ASI_PST16_P		0xc2 /* Primary, 4 16-bit, partial	*/
diff --git a/arch/sparc/include/asm/compat.h b/arch/sparc/include/asm/compat.h
index b8be20d..cef99fb 100644
--- a/arch/sparc/include/asm/compat.h
+++ b/arch/sparc/include/asm/compat.h
@@ -36,6 +36,7 @@ typedef s64		compat_s64;
 typedef u32		compat_uint_t;
 typedef u32		compat_ulong_t;
 typedef u64		compat_u64;
+typedef u32		compat_uptr_t;
 
 struct compat_timespec {
 	compat_time_t	tv_sec;
@@ -147,6 +148,65 @@ typedef u32		compat_old_sigset_t;
 
 typedef u32		compat_sigset_word;
 
+typedef union compat_sigval {
+	compat_int_t	sival_int;
+	compat_uptr_t	sival_ptr;
+} compat_sigval_t;
+
+#define SI_PAD_SIZE32	(128/sizeof(int) - 3)
+
+typedef struct compat_siginfo {
+	int si_signo;
+	int si_errno;
+	int si_code;
+
+	union {
+		int _pad[SI_PAD_SIZE32];
+
+		/* kill() */
+		struct {
+			compat_pid_t _pid;		/* sender's pid */
+			unsigned int _uid;		/* sender's uid */
+		} _kill;
+
+		/* POSIX.1b timers */
+		struct {
+			compat_timer_t _tid;		/* timer id */
+			int _overrun;			/* overrun count */
+			compat_sigval_t _sigval;	/* same as below */
+			int _sys_private;	/* not to be passed to user */
+		} _timer;
+
+		/* POSIX.1b signals */
+		struct {
+			compat_pid_t _pid;		/* sender's pid */
+			unsigned int _uid;		/* sender's uid */
+			compat_sigval_t _sigval;
+		} _rt;
+
+		/* SIGCHLD */
+		struct {
+			compat_pid_t _pid;		/* which child */
+			unsigned int _uid;		/* sender's uid */
+			int _status;			/* exit code */
+			compat_clock_t _utime;
+			compat_clock_t _stime;
+		} _sigchld;
+
+		/* SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGEMT */
+		struct {
+			u32 _addr; /* faulting insn/memory ref. */
+			int _trapno;
+		} _sigfault;
+
+		/* SIGPOLL */
+		struct {
+			int _band;	/* POLL_IN, POLL_OUT, POLL_MSG */
+			int _fd;
+		} _sigpoll;
+	} _sifields;
+} compat_siginfo_t;
+
 #define COMPAT_OFF_T_MAX	0x7fffffff
 #define COMPAT_LOFF_T_MAX	0x7fffffffffffffffL
 
@@ -156,7 +216,6 @@ typedef u32		compat_sigset_word;
  * as pointers because the syscall entry code will have
  * appropriately converted them already.
  */
-typedef	u32		compat_uptr_t;
 
 static inline void __user *compat_ptr(compat_uptr_t uptr)
 {
diff --git a/arch/sparc/include/asm/elf_32.h b/arch/sparc/include/asm/elf_32.h
index 2d4d755..ac74a2c 100644
--- a/arch/sparc/include/asm/elf_32.h
+++ b/arch/sparc/include/asm/elf_32.h
@@ -128,6 +128,7 @@ typedef struct {
 
 #define ELF_PLATFORM	(NULL)
 
-#define SET_PERSONALITY(ex) set_personality(PER_LINUX)
+#define SET_PERSONALITY(ex) \
+	set_personality(PER_LINUX | (current->personality & (~PER_MASK)))
 
 #endif /* !(__ASMSPARC_ELF_H) */
diff --git a/arch/sparc/include/asm/elf_64.h b/arch/sparc/include/asm/elf_64.h
index 7df8b7f..370ca1e 100644
--- a/arch/sparc/include/asm/elf_64.h
+++ b/arch/sparc/include/asm/elf_64.h
@@ -86,6 +86,15 @@
 #define AV_SPARC_IMA		0x00400000 /* integer multiply-add */
 #define AV_SPARC_ASI_CACHE_SPARING \
 				0x00800000 /* cache sparing ASIs available */
+#define AV_SPARC_PAUSE		0x01000000 /* PAUSE available */
+#define AV_SPARC_CBCOND		0x02000000 /* CBCOND insns available */
+
+/* Solaris decided to enumerate every single crypto instruction type
+ * in the AT_HWCAP bits.  This is wasteful, since if crypto is present,
+ * you still need to look in the CFR register to see if the opcode is
+ * really available.  So we simply advertise only "crypto" support.
+ */
+#define HWCAP_SPARC_CRYPTO	0x04000000 /* CRYPTO insns available */
 
 #define CORE_DUMP_USE_REGSET
 
diff --git a/arch/sparc/include/asm/exec.h b/arch/sparc/include/asm/exec.h
deleted file mode 100644
index 2e08588..0000000
--- a/arch/sparc/include/asm/exec.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __SPARC_EXEC_H
-#define __SPARC_EXEC_H
-
-#define arch_align_stack(x) (x)
-
-#endif /* __SPARC_EXEC_H */
diff --git a/arch/sparc/include/asm/hugetlb.h b/arch/sparc/include/asm/hugetlb.h
index 1770610..e7927c9 100644
--- a/arch/sparc/include/asm/hugetlb.h
+++ b/arch/sparc/include/asm/hugetlb.h
@@ -82,4 +82,8 @@ static inline void arch_release_hugepage(struct page *page)
 {
 }
 
+static inline void arch_clear_hugepage_flags(struct page *page)
+{
+}
+
 #endif /* _ASM_SPARC64_HUGETLB_H */
diff --git a/arch/sparc/include/asm/hypervisor.h b/arch/sparc/include/asm/hypervisor.h
index 015a761..ca121f0 100644
--- a/arch/sparc/include/asm/hypervisor.h
+++ b/arch/sparc/include/asm/hypervisor.h
@@ -2934,6 +2934,16 @@ extern unsigned long sun4v_reboot_data_set(unsigned long ra,
 					   unsigned long len);
 #endif
 
+#define HV_FAST_VT_GET_PERFREG		0x184
+#define HV_FAST_VT_SET_PERFREG		0x185
+
+#ifndef __ASSEMBLY__
+extern unsigned long sun4v_vt_get_perfreg(unsigned long reg_num,
+					  unsigned long *reg_val);
+extern unsigned long sun4v_vt_set_perfreg(unsigned long reg_num,
+					  unsigned long reg_val);
+#endif
+
 /* Function numbers for HV_CORE_TRAP.  */
 #define HV_CORE_SET_VER			0x00
 #define HV_CORE_PUTCHAR			0x01
@@ -2964,6 +2974,7 @@ extern unsigned long sun4v_reboot_data_set(unsigned long ra,
 #define HV_GRP_NIU			0x0204
 #define HV_GRP_VF_CPU			0x0205
 #define HV_GRP_KT_CPU			0x0209
+#define HV_GRP_VT_CPU			0x020c
 #define HV_GRP_DIAG			0x0300
 
 #ifndef __ASSEMBLY__
diff --git a/arch/sparc/include/asm/mdesc.h b/arch/sparc/include/asm/mdesc.h
index 9faa046..139097f 100644
--- a/arch/sparc/include/asm/mdesc.h
+++ b/arch/sparc/include/asm/mdesc.h
@@ -73,6 +73,7 @@ extern void mdesc_register_notifier(struct mdesc_notifier_client *client);
 
 extern void mdesc_fill_in_cpu_data(cpumask_t *mask);
 extern void mdesc_populate_present_mask(cpumask_t *mask);
+extern void mdesc_get_page_sizes(cpumask_t *mask, unsigned long *pgsz_mask);
 
 extern void sun4v_mdesc_init(void);
 
diff --git a/arch/sparc/include/asm/module.h b/arch/sparc/include/asm/module.h
deleted file mode 100644
index ff8e02d..0000000
--- a/arch/sparc/include/asm/module.h
+++ /dev/null
@@ -1,24 +0,0 @@
-#ifndef __SPARC_MODULE_H
-#define __SPARC_MODULE_H
-struct mod_arch_specific { };
-
-/*
- * Use some preprocessor magic to define the correct symbol
- * for sparc32 and sparc64.
- * Elf_Addr becomes Elf32_Addr for sparc32 and Elf64_Addr for sparc64
- */
-#define ___ELF(a, b, c) a##b##c
-#define __ELF(a, b, c)  ___ELF(a, b, c)
-#define  _Elf(t)        __ELF(Elf, CONFIG_BITS, t)
-#define  _ELF(t)        __ELF(ELF, CONFIG_BITS, t)
-
-#define Elf_Shdr     _Elf(_Shdr)
-#define Elf_Sym      _Elf(_Sym)
-#define Elf_Ehdr     _Elf(_Ehdr)
-#define Elf_Rela     _Elf(_Rela)
-#define Elf_Addr     _Elf(_Addr)
-
-#define ELF_R_SYM    _ELF(_R_SYM)
-#define ELF_R_TYPE   _ELF(_R_TYPE)
-
-#endif /* __SPARC_MODULE_H */
diff --git a/arch/sparc/include/asm/pcr.h b/arch/sparc/include/asm/pcr.h
index 288d7be..942bb17 100644
--- a/arch/sparc/include/asm/pcr.h
+++ b/arch/sparc/include/asm/pcr.h
@@ -2,8 +2,13 @@
 #define __PCR_H
 
 struct pcr_ops {
-	u64 (*read)(void);
-	void (*write)(u64);
+	u64 (*read_pcr)(unsigned long);
+	void (*write_pcr)(unsigned long, u64);
+	u64 (*read_pic)(unsigned long);
+	void (*write_pic)(unsigned long, u64);
+	u64 (*nmi_picl_value)(unsigned int nmi_hz);
+	u64 pcr_nmi_enable;
+	u64 pcr_nmi_disable;
 };
 extern const struct pcr_ops *pcr_ops;
 
@@ -27,21 +32,18 @@ extern void schedule_deferred_pcr_work(void);
 #define PCR_N2_SL1_SHIFT	27
 #define PCR_N2_OV1		0x80000000
 
-extern unsigned int picl_shift;
-
-/* In order to commonize as much of the implementation as
- * possible, we use PICH as our counter.  Mostly this is
- * to accommodate Niagara-1 which can only count insn cycles
- * in PICH.
- */
-static inline u64 picl_value(unsigned int nmi_hz)
-{
-	u32 delta = local_cpu_data().clock_tick / (nmi_hz << picl_shift);
-
-	return ((u64)((0 - delta) & 0xffffffff)) << 32;
-}
-
-extern u64 pcr_enable;
+#define PCR_N4_OV		0x00000001 /* PIC overflow             */
+#define PCR_N4_TOE		0x00000002 /* Trap On Event            */
+#define PCR_N4_UTRACE		0x00000004 /* Trace user events        */
+#define PCR_N4_STRACE		0x00000008 /* Trace supervisor events  */
+#define PCR_N4_HTRACE		0x00000010 /* Trace hypervisor events  */
+#define PCR_N4_MASK		0x000007e0 /* Event mask               */
+#define PCR_N4_MASK_SHIFT	5
+#define PCR_N4_SL		0x0000f800 /* Event Select             */
+#define PCR_N4_SL_SHIFT		11
+#define PCR_N4_PICNPT		0x00010000 /* PIC non-privileged trap  */
+#define PCR_N4_PICNHT		0x00020000 /* PIC non-hypervisor trap  */
+#define PCR_N4_NTC		0x00040000 /* Next-To-Commit wrap      */
 
 extern int pcr_arch_init(void);
 
diff --git a/arch/sparc/include/asm/perfctr.h b/arch/sparc/include/asm/perfctr.h
index 3332d2c..214feef 100644
--- a/arch/sparc/include/asm/perfctr.h
+++ b/arch/sparc/include/asm/perfctr.h
@@ -54,11 +54,6 @@ enum perfctr_opcode {
 	PERFCTR_GETPCR
 };
 
-/* I don't want the kernel's namespace to be polluted with this
- * stuff when this file is included.  --DaveM
- */
-#ifndef __KERNEL__
-
 #define  PRIV 0x00000001
 #define  SYS  0x00000002
 #define  USR  0x00000004
@@ -168,29 +163,4 @@ struct vcounter_struct {
   unsigned long long vcnt1;
 };
 
-#else /* !(__KERNEL__) */
-
-#ifndef CONFIG_SPARC32
-
-/* Performance counter register access. */
-#define read_pcr(__p)  __asm__ __volatile__("rd	%%pcr, %0" : "=r" (__p))
-#define write_pcr(__p) __asm__ __volatile__("wr	%0, 0x0, %%pcr" : : "r" (__p))
-#define read_pic(__p)  __asm__ __volatile__("rd %%pic, %0" : "=r" (__p))
-
-/* Blackbird errata workaround.  See commentary in
- * arch/sparc64/kernel/smp.c:smp_percpu_timer_interrupt()
- * for more information.
- */
-#define write_pic(__p)  					\
-	__asm__ __volatile__("ba,pt	%%xcc, 99f\n\t"		\
-			     " nop\n\t"				\
-			     ".align	64\n"			\
-			  "99:wr	%0, 0x0, %%pic\n\t"	\
-			     "rd	%%pic, %%g0" : : "r" (__p))
-#define reset_pic()	write_pic(0)
-
-#endif /* !CONFIG_SPARC32 */
-
-#endif /* !(__KERNEL__) */
-
 #endif /* !(PERF_COUNTER_API) */
diff --git a/arch/sparc/include/asm/pstate.h b/arch/sparc/include/asm/pstate.h
index a26a537..4b6b998 100644
--- a/arch/sparc/include/asm/pstate.h
+++ b/arch/sparc/include/asm/pstate.h
@@ -88,4 +88,18 @@
 #define VERS_MAXTL	_AC(0x000000000000ff00,UL) /* Max Trap Level.	*/
 #define VERS_MAXWIN	_AC(0x000000000000001f,UL) /* Max RegWindow Idx.*/
 
+/* Compatability Feature Register (%asr26), SPARC-T4 and later  */
+#define CFR_AES		_AC(0x0000000000000001,UL) /* Supports AES opcodes     */
+#define CFR_DES		_AC(0x0000000000000002,UL) /* Supports DES opcodes     */
+#define CFR_KASUMI	_AC(0x0000000000000004,UL) /* Supports KASUMI opcodes  */
+#define CFR_CAMELLIA	_AC(0x0000000000000008,UL) /* Supports CAMELLIA opcodes*/
+#define CFR_MD5		_AC(0x0000000000000010,UL) /* Supports MD5 opcodes     */
+#define CFR_SHA1	_AC(0x0000000000000020,UL) /* Supports SHA1 opcodes    */
+#define CFR_SHA256	_AC(0x0000000000000040,UL) /* Supports SHA256 opcodes  */
+#define CFR_SHA512	_AC(0x0000000000000080,UL) /* Supports SHA512 opcodes  */
+#define CFR_MPMUL	_AC(0x0000000000000100,UL) /* Supports MPMUL opcodes   */
+#define CFR_MONTMUL	_AC(0x0000000000000200,UL) /* Supports MONTMUL opcodes */
+#define CFR_MONTSQR	_AC(0x0000000000000400,UL) /* Supports MONTSQR opcodes */
+#define CFR_CRC32C	_AC(0x0000000000000800,UL) /* Supports CRC32C opcodes  */
+
 #endif /* !(_SPARC64_PSTATE_H) */
diff --git a/arch/sparc/include/asm/siginfo.h b/arch/sparc/include/asm/siginfo.h
index 215900f..dbc182c 100644
--- a/arch/sparc/include/asm/siginfo.h
+++ b/arch/sparc/include/asm/siginfo.h
@@ -3,7 +3,6 @@
 
 #if defined(__sparc__) && defined(__arch64__)
 
-#define SI_PAD_SIZE32	((SI_MAX_SIZE/sizeof(int)) - 3)
 #define __ARCH_SI_PREAMBLE_SIZE	(4 * sizeof(int))
 #define __ARCH_SI_BAND_T int
 
diff --git a/arch/sparc/include/asm/thread_info_32.h b/arch/sparc/include/asm/thread_info_32.h
index e6cd224..25849ae 100644
--- a/arch/sparc/include/asm/thread_info_32.h
+++ b/arch/sparc/include/asm/thread_info_32.h
@@ -126,13 +126,14 @@ register struct thread_info *current_thread_info_reg asm("g6");
 #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
 #define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
-#define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
 #define _TIF_USEDFPU		(1<<TIF_USEDFPU)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
 
 #define _TIF_DO_NOTIFY_RESUME_MASK	(_TIF_NOTIFY_RESUME | \
 					 _TIF_SIGPENDING)
 
+#define tsk_is_polling(t) test_tsk_thread_flag(t, TIF_POLLING_NRFLAG)
+
 #endif /* __KERNEL__ */
 
 #endif /* _ASM_THREAD_INFO_H */
diff --git a/arch/sparc/include/asm/thread_info_64.h b/arch/sparc/include/asm/thread_info_64.h
index cfa8c38..4e22766 100644
--- a/arch/sparc/include/asm/thread_info_64.h
+++ b/arch/sparc/include/asm/thread_info_64.h
@@ -256,6 +256,9 @@ static inline bool test_and_clear_restore_sigmask(void)
 	ti->status &= ~TS_RESTORE_SIGMASK;
 	return true;
 }
+
+#define tsk_is_polling(t) test_tsk_thread_flag(t, TIF_POLLING_NRFLAG)
+
 #endif	/* !__ASSEMBLY__ */
 
 #endif /* __KERNEL__ */
diff --git a/arch/sparc/kernel/hvapi.c b/arch/sparc/kernel/hvapi.c
index 8593672..1032df4 100644
--- a/arch/sparc/kernel/hvapi.c
+++ b/arch/sparc/kernel/hvapi.c
@@ -45,6 +45,7 @@ static struct api_info api_table[] = {
 	{ .group = HV_GRP_NIU,					},
 	{ .group = HV_GRP_VF_CPU,				},
 	{ .group = HV_GRP_KT_CPU,				},
+	{ .group = HV_GRP_VT_CPU,				},
 	{ .group = HV_GRP_DIAG,		.flags = FLAG_PRE_API	},
 };
 
diff --git a/arch/sparc/kernel/hvcalls.S b/arch/sparc/kernel/hvcalls.S
index 58d60de..f3ab509 100644
--- a/arch/sparc/kernel/hvcalls.S
+++ b/arch/sparc/kernel/hvcalls.S
@@ -805,3 +805,19 @@ ENTRY(sun4v_reboot_data_set)
 	retl
 	 nop
 ENDPROC(sun4v_reboot_data_set)
+
+ENTRY(sun4v_vt_get_perfreg)
+	mov	%o1, %o4
+	mov	HV_FAST_VT_GET_PERFREG, %o5
+	ta	HV_FAST_TRAP
+	stx	%o1, [%o4]
+	retl
+	 nop
+ENDPROC(sun4v_vt_get_perfreg)
+
+ENTRY(sun4v_vt_set_perfreg)
+	mov	HV_FAST_VT_SET_PERFREG, %o5
+	ta	HV_FAST_TRAP
+	retl
+	 nop
+ENDPROC(sun4v_vt_set_perfreg)
diff --git a/arch/sparc/kernel/ktlb.S b/arch/sparc/kernel/ktlb.S
index 79f3103..0746e5e 100644
--- a/arch/sparc/kernel/ktlb.S
+++ b/arch/sparc/kernel/ktlb.S
@@ -188,31 +188,26 @@ valid_addr_bitmap_patch:
 	be,pn		%xcc, kvmap_dtlb_longpath
 
 2:	 sethi		%hi(kpte_linear_bitmap), %g2
-	or		%g2, %lo(kpte_linear_bitmap), %g2
 
 	/* Get the 256MB physical address index. */
 	sllx		%g4, 21, %g5
-	mov		1, %g7
+	or		%g2, %lo(kpte_linear_bitmap), %g2
 	srlx		%g5, 21 + 28, %g5
+	and		%g5, (32 - 1), %g7
 
-	/* Don't try this at home kids... this depends upon srlx
-	 * only taking the low 6 bits of the shift count in %g5.
-	 */
-	sllx		%g7, %g5, %g7
-
-	/* Divide by 64 to get the offset into the bitmask.  */
-	srlx		%g5, 6, %g5
+	/* Divide by 32 to get the offset into the bitmask.  */
+	srlx		%g5, 5, %g5
+	add		%g7, %g7, %g7
 	sllx		%g5, 3, %g5
 
-	/* kern_linear_pte_xor[((mask & bit) ? 1 : 0)] */
+	/* kern_linear_pte_xor[(mask >> shift) & 3)] */
 	ldx		[%g2 + %g5], %g2
-	andcc		%g2, %g7, %g0
+	srlx		%g2, %g7, %g7
 	sethi		%hi(kern_linear_pte_xor), %g5
+	and		%g7, 3, %g7
 	or		%g5, %lo(kern_linear_pte_xor), %g5
-	bne,a,pt	%xcc, 1f
-	 add		%g5, 8, %g5
-
-1:	ldx		[%g5], %g2
+	sllx		%g7, 3, %g7
+	ldx		[%g5 + %g7], %g2
 
 	.globl		kvmap_linear_patch
 kvmap_linear_patch:
diff --git a/arch/sparc/kernel/leon_pci.c b/arch/sparc/kernel/leon_pci.c
index 21dcda7..fc05211 100644
--- a/arch/sparc/kernel/leon_pci.c
+++ b/arch/sparc/kernel/leon_pci.c
@@ -102,15 +102,6 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
 	return pci_enable_resources(dev, mask);
 }
 
-void __devinit pcibios_update_irq(struct pci_dev *dev, int irq)
-{
-#ifdef CONFIG_PCI_DEBUG
-	printk(KERN_DEBUG "LEONPCI: Assigning IRQ %02d to %s\n", irq,
-		pci_name(dev));
-#endif
-	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
-}
-
 /* in/out routines taken from pcic.c
  *
  * This probably belongs here rather than ioport.c because
diff --git a/arch/sparc/kernel/mdesc.c b/arch/sparc/kernel/mdesc.c
index 6dc7962..831c001 100644
--- a/arch/sparc/kernel/mdesc.c
+++ b/arch/sparc/kernel/mdesc.c
@@ -817,6 +817,30 @@ void __cpuinit mdesc_populate_present_mask(cpumask_t *mask)
 	mdesc_iterate_over_cpus(record_one_cpu, NULL, mask);
 }
 
+static void * __init check_one_pgsz(struct mdesc_handle *hp, u64 mp, int cpuid, void *arg)
+{
+	const u64 *pgsz_prop = mdesc_get_property(hp, mp, "mmu-page-size-list", NULL);
+	unsigned long *pgsz_mask = arg;
+	u64 val;
+
+	val = (HV_PGSZ_MASK_8K | HV_PGSZ_MASK_64K |
+	       HV_PGSZ_MASK_512K | HV_PGSZ_MASK_4MB);
+	if (pgsz_prop)
+		val = *pgsz_prop;
+
+	if (!*pgsz_mask)
+		*pgsz_mask = val;
+	else
+		*pgsz_mask &= val;
+	return NULL;
+}
+
+void __init mdesc_get_page_sizes(cpumask_t *mask, unsigned long *pgsz_mask)
+{
+	*pgsz_mask = 0;
+	mdesc_iterate_over_cpus(check_one_pgsz, pgsz_mask, mask);
+}
+
 static void * __cpuinit fill_in_one_cpu(struct mdesc_handle *hp, u64 mp, int cpuid, void *arg)
 {
 	const u64 *cfreq = mdesc_get_property(hp, mp, "clock-frequency", NULL);
diff --git a/arch/sparc/kernel/nmi.c b/arch/sparc/kernel/nmi.c
index eb1c1f0..6479256 100644
--- a/arch/sparc/kernel/nmi.c
+++ b/arch/sparc/kernel/nmi.c
@@ -22,7 +22,6 @@
 #include <asm/perf_event.h>
 #include <asm/ptrace.h>
 #include <asm/pcr.h>
-#include <asm/perfctr.h>
 
 #include "kstack.h"
 
@@ -109,7 +108,7 @@ notrace __kprobes void perfctr_irq(int irq, struct pt_regs *regs)
 		       pt_regs_trap_type(regs), SIGINT) == NOTIFY_STOP)
 		touched = 1;
 	else
-		pcr_ops->write(PCR_PIC_PRIV);
+		pcr_ops->write_pcr(0, pcr_ops->pcr_nmi_disable);
 
 	sum = local_cpu_data().irq0_irqs;
 	if (__get_cpu_var(nmi_touch)) {
@@ -126,8 +125,8 @@ notrace __kprobes void perfctr_irq(int irq, struct pt_regs *regs)
 		__this_cpu_write(alert_counter, 0);
 	}
 	if (__get_cpu_var(wd_enabled)) {
-		write_pic(picl_value(nmi_hz));
-		pcr_ops->write(pcr_enable);
+		pcr_ops->write_pic(0, pcr_ops->nmi_picl_value(nmi_hz));
+		pcr_ops->write_pcr(0, pcr_ops->pcr_nmi_enable);
 	}
 
 	restore_hardirq_stack(orig_sp);
@@ -166,7 +165,7 @@ static void report_broken_nmi(int cpu, int *prev_nmi_count)
 
 void stop_nmi_watchdog(void *unused)
 {
-	pcr_ops->write(PCR_PIC_PRIV);
+	pcr_ops->write_pcr(0, pcr_ops->pcr_nmi_disable);
 	__get_cpu_var(wd_enabled) = 0;
 	atomic_dec(&nmi_active);
 }
@@ -223,10 +222,10 @@ void start_nmi_watchdog(void *unused)
 	__get_cpu_var(wd_enabled) = 1;
 	atomic_inc(&nmi_active);
 
-	pcr_ops->write(PCR_PIC_PRIV);
-	write_pic(picl_value(nmi_hz));
+	pcr_ops->write_pcr(0, pcr_ops->pcr_nmi_disable);
+	pcr_ops->write_pic(0, pcr_ops->nmi_picl_value(nmi_hz));
 
-	pcr_ops->write(pcr_enable);
+	pcr_ops->write_pcr(0, pcr_ops->pcr_nmi_enable);
 }
 
 static void nmi_adjust_hz_one(void *unused)
@@ -234,10 +233,10 @@ static void nmi_adjust_hz_one(void *unused)
 	if (!__get_cpu_var(wd_enabled))
 		return;
 
-	pcr_ops->write(PCR_PIC_PRIV);
-	write_pic(picl_value(nmi_hz));
+	pcr_ops->write_pcr(0, pcr_ops->pcr_nmi_disable);
+	pcr_ops->write_pic(0, pcr_ops->nmi_picl_value(nmi_hz));
 
-	pcr_ops->write(pcr_enable);
+	pcr_ops->write_pcr(0, pcr_ops->pcr_nmi_enable);
 }
 
 void nmi_adjust_hz(unsigned int new_hz)
diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c
index 065b88c..75b31bc 100644
--- a/arch/sparc/kernel/pci.c
+++ b/arch/sparc/kernel/pci.c
@@ -622,10 +622,6 @@ void __devinit pcibios_fixup_bus(struct pci_bus *pbus)
 {
 }
 
-void pcibios_update_irq(struct pci_dev *pdev, int irq)
-{
-}
-
 resource_size_t pcibios_align_resource(void *data, const struct resource *res,
 				resource_size_t size, resource_size_t align)
 {
@@ -783,7 +779,7 @@ static int __pci_mmap_make_offset(struct pci_dev *pdev,
 static void __pci_mmap_set_flags(struct pci_dev *dev, struct vm_area_struct *vma,
 					    enum pci_mmap_state mmap_state)
 {
-	vma->vm_flags |= (VM_IO | VM_RESERVED);
+	vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP;
 }
 
 /* Set vm_page_prot of VMA, as appropriate for this architecture, for a pci
diff --git a/arch/sparc/kernel/pci_sun4v.c b/arch/sparc/kernel/pci_sun4v.c
index 7661e84..051b69c 100644
--- a/arch/sparc/kernel/pci_sun4v.c
+++ b/arch/sparc/kernel/pci_sun4v.c
@@ -594,7 +594,7 @@ static int __devinit pci_sun4v_iommu_init(struct pci_pbm_info *pbm)
 		printk(KERN_ERR PFX "Strange virtual-dma[%08x:%08x].\n",
 		       vdma[0], vdma[1]);
 		return -EINVAL;
-	};
+	}
 
 	dma_mask = (roundup_pow_of_two(vdma[1]) - 1UL);
 	num_tsb_entries = vdma[1] / IO_PAGE_SIZE;
diff --git a/arch/sparc/kernel/pcr.c b/arch/sparc/kernel/pcr.c
index 0ce0dd2..269af58 100644
--- a/arch/sparc/kernel/pcr.c
+++ b/arch/sparc/kernel/pcr.c
@@ -13,23 +13,14 @@
 #include <asm/pil.h>
 #include <asm/pcr.h>
 #include <asm/nmi.h>
+#include <asm/asi.h>
 #include <asm/spitfire.h>
-#include <asm/perfctr.h>
 
 /* This code is shared between various users of the performance
  * counters.  Users will be oprofile, pseudo-NMI watchdog, and the
  * perf_event support layer.
  */
 
-#define PCR_SUN4U_ENABLE	(PCR_PIC_PRIV | PCR_STRACE | PCR_UTRACE)
-#define PCR_N2_ENABLE		(PCR_PIC_PRIV | PCR_STRACE | PCR_UTRACE | \
-				 PCR_N2_TOE_OV1 | \
-				 (2 << PCR_N2_SL1_SHIFT) | \
-				 (0xff << PCR_N2_MASK1_SHIFT))
-
-u64 pcr_enable;
-unsigned int picl_shift;
-
 /* Performance counter interrupts run unmasked at PIL level 15.
  * Therefore we can't do things like wakeups and other work
  * that expects IRQ disabling to be adhered to in locking etc.
@@ -60,39 +51,144 @@ void arch_irq_work_raise(void)
 const struct pcr_ops *pcr_ops;
 EXPORT_SYMBOL_GPL(pcr_ops);
 
-static u64 direct_pcr_read(void)
+static u64 direct_pcr_read(unsigned long reg_num)
 {
 	u64 val;
 
-	read_pcr(val);
+	WARN_ON_ONCE(reg_num != 0);
+	__asm__ __volatile__("rd %%pcr, %0" : "=r" (val));
 	return val;
 }
 
-static void direct_pcr_write(u64 val)
+static void direct_pcr_write(unsigned long reg_num, u64 val)
+{
+	WARN_ON_ONCE(reg_num != 0);
+	__asm__ __volatile__("wr %0, 0x0, %%pcr" : : "r" (val));
+}
+
+static u64 direct_pic_read(unsigned long reg_num)
 {
-	write_pcr(val);
+	u64 val;
+
+	WARN_ON_ONCE(reg_num != 0);
+	__asm__ __volatile__("rd %%pic, %0" : "=r" (val));
+	return val;
+}
+
+static void direct_pic_write(unsigned long reg_num, u64 val)
+{
+	WARN_ON_ONCE(reg_num != 0);
+
+	/* Blackbird errata workaround.  See commentary in
+	 * arch/sparc64/kernel/smp.c:smp_percpu_timer_interrupt()
+	 * for more information.
+	 */
+	__asm__ __volatile__("ba,pt	%%xcc, 99f\n\t"
+			     " nop\n\t"
+			     ".align	64\n"
+			  "99:wr	%0, 0x0, %%pic\n\t"
+			     "rd	%%pic, %%g0" : : "r" (val));
+}
+
+static u64 direct_picl_value(unsigned int nmi_hz)
+{
+	u32 delta = local_cpu_data().clock_tick / nmi_hz;
+
+	return ((u64)((0 - delta) & 0xffffffff)) << 32;
 }
 
 static const struct pcr_ops direct_pcr_ops = {
-	.read	= direct_pcr_read,
-	.write	= direct_pcr_write,
+	.read_pcr		= direct_pcr_read,
+	.write_pcr		= direct_pcr_write,
+	.read_pic		= direct_pic_read,
+	.write_pic		= direct_pic_write,
+	.nmi_picl_value		= direct_picl_value,
+	.pcr_nmi_enable		= (PCR_PIC_PRIV | PCR_STRACE | PCR_UTRACE),
+	.pcr_nmi_disable	= PCR_PIC_PRIV,
 };
 
-static void n2_pcr_write(u64 val)
+static void n2_pcr_write(unsigned long reg_num, u64 val)
 {
 	unsigned long ret;
 
+	WARN_ON_ONCE(reg_num != 0);
 	if (val & PCR_N2_HTRACE) {
 		ret = sun4v_niagara2_setperf(HV_N2_PERF_SPARC_CTL, val);
 		if (ret != HV_EOK)
-			write_pcr(val);
+			direct_pcr_write(reg_num, val);
 	} else
-		write_pcr(val);
+		direct_pcr_write(reg_num, val);
+}
+
+static u64 n2_picl_value(unsigned int nmi_hz)
+{
+	u32 delta = local_cpu_data().clock_tick / (nmi_hz << 2);
+
+	return ((u64)((0 - delta) & 0xffffffff)) << 32;
 }
 
 static const struct pcr_ops n2_pcr_ops = {
-	.read	= direct_pcr_read,
-	.write	= n2_pcr_write,
+	.read_pcr		= direct_pcr_read,
+	.write_pcr		= n2_pcr_write,
+	.read_pic		= direct_pic_read,
+	.write_pic		= direct_pic_write,
+	.nmi_picl_value		= n2_picl_value,
+	.pcr_nmi_enable		= (PCR_PIC_PRIV | PCR_STRACE | PCR_UTRACE |
+				   PCR_N2_TOE_OV1 |
+				   (2 << PCR_N2_SL1_SHIFT) |
+				   (0xff << PCR_N2_MASK1_SHIFT)),
+	.pcr_nmi_disable	= PCR_PIC_PRIV,
+};
+
+static u64 n4_pcr_read(unsigned long reg_num)
+{
+	unsigned long val;
+
+	(void) sun4v_vt_get_perfreg(reg_num, &val);
+
+	return val;
+}
+
+static void n4_pcr_write(unsigned long reg_num, u64 val)
+{
+	(void) sun4v_vt_set_perfreg(reg_num, val);
+}
+
+static u64 n4_pic_read(unsigned long reg_num)
+{
+	unsigned long val;
+
+	__asm__ __volatile__("ldxa [%1] %2, %0"
+			     : "=r" (val)
+			     : "r" (reg_num * 0x8UL), "i" (ASI_PIC));
+
+	return val;
+}
+
+static void n4_pic_write(unsigned long reg_num, u64 val)
+{
+	__asm__ __volatile__("stxa %0, [%1] %2"
+			     : /* no outputs */
+			     : "r" (val), "r" (reg_num * 0x8UL), "i" (ASI_PIC));
+}
+
+static u64 n4_picl_value(unsigned int nmi_hz)
+{
+	u32 delta = local_cpu_data().clock_tick / (nmi_hz << 2);
+
+	return ((u64)((0 - delta) & 0xffffffff));
+}
+
+static const struct pcr_ops n4_pcr_ops = {
+	.read_pcr		= n4_pcr_read,
+	.write_pcr		= n4_pcr_write,
+	.read_pic		= n4_pic_read,
+	.write_pic		= n4_pic_write,
+	.nmi_picl_value		= n4_picl_value,
+	.pcr_nmi_enable		= (PCR_N4_PICNPT | PCR_N4_STRACE |
+				   PCR_N4_UTRACE | PCR_N4_TOE |
+				   (26 << PCR_N4_SL_SHIFT)),
+	.pcr_nmi_disable	= PCR_N4_PICNPT,
 };
 
 static unsigned long perf_hsvc_group;
@@ -115,6 +211,10 @@ static int __init register_perf_hsvc(void)
 			perf_hsvc_group = HV_GRP_KT_CPU;
 			break;
 
+		case SUN4V_CHIP_NIAGARA4:
+			perf_hsvc_group = HV_GRP_VT_CPU;
+			break;
+
 		default:
 			return -ENODEV;
 		}
@@ -139,6 +239,29 @@ static void __init unregister_perf_hsvc(void)
 	sun4v_hvapi_unregister(perf_hsvc_group);
 }
 
+static int __init setup_sun4v_pcr_ops(void)
+{
+	int ret = 0;
+
+	switch (sun4v_chip_type) {
+	case SUN4V_CHIP_NIAGARA1:
+	case SUN4V_CHIP_NIAGARA2:
+	case SUN4V_CHIP_NIAGARA3:
+		pcr_ops = &n2_pcr_ops;
+		break;
+
+	case SUN4V_CHIP_NIAGARA4:
+		pcr_ops = &n4_pcr_ops;
+		break;
+
+	default:
+		ret = -ENODEV;
+		break;
+	}
+
+	return ret;
+}
+
 int __init pcr_arch_init(void)
 {
 	int err = register_perf_hsvc();
@@ -148,15 +271,14 @@ int __init pcr_arch_init(void)
 
 	switch (tlb_type) {
 	case hypervisor:
-		pcr_ops = &n2_pcr_ops;
-		pcr_enable = PCR_N2_ENABLE;
-		picl_shift = 2;
+		err = setup_sun4v_pcr_ops();
+		if (err)
+			goto out_unregister;
 		break;
 
 	case cheetah:
 	case cheetah_plus:
 		pcr_ops = &direct_pcr_ops;
-		pcr_enable = PCR_SUN4U_ENABLE;
 		break;
 
 	case spitfire:
diff --git a/arch/sparc/kernel/perf_event.c b/arch/sparc/kernel/perf_event.c
index 5713957..e48651d 100644
--- a/arch/sparc/kernel/perf_event.c
+++ b/arch/sparc/kernel/perf_event.c
@@ -25,36 +25,48 @@
 #include <linux/atomic.h>
 #include <asm/nmi.h>
 #include <asm/pcr.h>
-#include <asm/perfctr.h>
 #include <asm/cacheflush.h>
 
 #include "kernel.h"
 #include "kstack.h"
 
-/* Sparc64 chips have two performance counters, 32-bits each, with
- * overflow interrupts generated on transition from 0xffffffff to 0.
- * The counters are accessed in one go using a 64-bit register.
+/* Two classes of sparc64 chips currently exist.  All of which have
+ * 32-bit counters which can generate overflow interrupts on the
+ * transition from 0xffffffff to 0.
  *
- * Both counters are controlled using a single control register.  The
- * only way to stop all sampling is to clear all of the context (user,
- * supervisor, hypervisor) sampling enable bits.  But these bits apply
- * to both counters, thus the two counters can't be enabled/disabled
- * individually.
+ * All chips upto and including SPARC-T3 have two performance
+ * counters.  The two 32-bit counters are accessed in one go using a
+ * single 64-bit register.
  *
- * The control register has two event fields, one for each of the two
- * counters.  It's thus nearly impossible to have one counter going
- * while keeping the other one stopped.  Therefore it is possible to
- * get overflow interrupts for counters not currently "in use" and
- * that condition must be checked in the overflow interrupt handler.
+ * On these older chips both counters are controlled using a single
+ * control register.  The only way to stop all sampling is to clear
+ * all of the context (user, supervisor, hypervisor) sampling enable
+ * bits.  But these bits apply to both counters, thus the two counters
+ * can't be enabled/disabled individually.
+ *
+ * Furthermore, the control register on these older chips have two
+ * event fields, one for each of the two counters.  It's thus nearly
+ * impossible to have one counter going while keeping the other one
+ * stopped.  Therefore it is possible to get overflow interrupts for
+ * counters not currently "in use" and that condition must be checked
+ * in the overflow interrupt handler.
  *
  * So we use a hack, in that we program inactive counters with the
  * "sw_count0" and "sw_count1" events.  These count how many times
  * the instruction "sethi %hi(0xfc000), %g0" is executed.  It's an
  * unusual way to encode a NOP and therefore will not trigger in
  * normal code.
+ *
+ * Starting with SPARC-T4 we have one control register per counter.
+ * And the counters are stored in individual registers.  The registers
+ * for the counters are 64-bit but only a 32-bit counter is
+ * implemented.  The event selections on SPARC-T4 lack any
+ * restrictions, therefore we can elide all of the complicated
+ * conflict resolution code we have for SPARC-T3 and earlier chips.
  */
 
-#define MAX_HWEVENTS			2
+#define MAX_HWEVENTS			4
+#define MAX_PCRS			4
 #define MAX_PERIOD			((1UL << 32) - 1)
 
 #define PIC_UPPER_INDEX			0
@@ -90,8 +102,8 @@ struct cpu_hw_events {
 	 */
 	int			current_idx[MAX_HWEVENTS];
 
-	/* Software copy of %pcr register on this cpu.  */
-	u64			pcr;
+	/* Software copy of %pcr register(s) on this cpu.  */
+	u64			pcr[MAX_HWEVENTS];
 
 	/* Enabled/disable state.  */
 	int			enabled;
@@ -103,6 +115,8 @@ DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events) = { .enabled = 1, };
 /* An event map describes the characteristics of a performance
  * counter event.  In particular it gives the encoding as well as
  * a mask telling which counters the event can be measured on.
+ *
+ * The mask is unused on SPARC-T4 and later.
  */
 struct perf_event_map {
 	u16	encoding;
@@ -142,15 +156,53 @@ struct sparc_pmu {
 	const struct perf_event_map	*(*event_map)(int);
 	const cache_map_t		*cache_map;
 	int				max_events;
+	u32				(*read_pmc)(int);
+	void				(*write_pmc)(int, u64);
 	int				upper_shift;
 	int				lower_shift;
 	int				event_mask;
+	int				user_bit;
+	int				priv_bit;
 	int				hv_bit;
 	int				irq_bit;
 	int				upper_nop;
 	int				lower_nop;
+	unsigned int			flags;
+#define SPARC_PMU_ALL_EXCLUDES_SAME	0x00000001
+#define SPARC_PMU_HAS_CONFLICTS		0x00000002
+	int				max_hw_events;
+	int				num_pcrs;
+	int				num_pic_regs;
 };
 
+static u32 sparc_default_read_pmc(int idx)
+{
+	u64 val;
+
+	val = pcr_ops->read_pic(0);
+	if (idx == PIC_UPPER_INDEX)
+		val >>= 32;
+
+	return val & 0xffffffff;
+}
+
+static void sparc_default_write_pmc(int idx, u64 val)
+{
+	u64 shift, mask, pic;
+
+	shift = 0;
+	if (idx == PIC_UPPER_INDEX)
+		shift = 32;
+
+	mask = ((u64) 0xffffffff) << shift;
+	val <<= shift;
+
+	pic = pcr_ops->read_pic(0);
+	pic &= ~mask;
+	pic |= val;
+	pcr_ops->write_pic(0, pic);
+}
+
 static const struct perf_event_map ultra3_perfmon_event_map[] = {
 	[PERF_COUNT_HW_CPU_CYCLES] = { 0x0000, PIC_UPPER | PIC_LOWER },
 	[PERF_COUNT_HW_INSTRUCTIONS] = { 0x0001, PIC_UPPER | PIC_LOWER },
@@ -268,11 +320,20 @@ static const struct sparc_pmu ultra3_pmu = {
 	.event_map	= ultra3_event_map,
 	.cache_map	= &ultra3_cache_map,
 	.max_events	= ARRAY_SIZE(ultra3_perfmon_event_map),
+	.read_pmc	= sparc_default_read_pmc,
+	.write_pmc	= sparc_default_write_pmc,
 	.upper_shift	= 11,
 	.lower_shift	= 4,
 	.event_mask	= 0x3f,
+	.user_bit	= PCR_UTRACE,
+	.priv_bit	= PCR_STRACE,
 	.upper_nop	= 0x1c,
 	.lower_nop	= 0x14,
+	.flags		= (SPARC_PMU_ALL_EXCLUDES_SAME |
+			   SPARC_PMU_HAS_CONFLICTS),
+	.max_hw_events	= 2,
+	.num_pcrs	= 1,
+	.num_pic_regs	= 1,
 };
 
 /* Niagara1 is very limited.  The upper PIC is hard-locked to count
@@ -397,11 +458,20 @@ static const struct sparc_pmu niagara1_pmu = {
 	.event_map	= niagara1_event_map,
 	.cache_map	= &niagara1_cache_map,
 	.max_events	= ARRAY_SIZE(niagara1_perfmon_event_map),
+	.read_pmc	= sparc_default_read_pmc,
+	.write_pmc	= sparc_default_write_pmc,
 	.upper_shift	= 0,
 	.lower_shift	= 4,
 	.event_mask	= 0x7,
+	.user_bit	= PCR_UTRACE,
+	.priv_bit	= PCR_STRACE,
 	.upper_nop	= 0x0,
 	.lower_nop	= 0x0,
+	.flags		= (SPARC_PMU_ALL_EXCLUDES_SAME |
+			   SPARC_PMU_HAS_CONFLICTS),
+	.max_hw_events	= 2,
+	.num_pcrs	= 1,
+	.num_pic_regs	= 1,
 };
 
 static const struct perf_event_map niagara2_perfmon_event_map[] = {
@@ -523,13 +593,203 @@ static const struct sparc_pmu niagara2_pmu = {
 	.event_map	= niagara2_event_map,
 	.cache_map	= &niagara2_cache_map,
 	.max_events	= ARRAY_SIZE(niagara2_perfmon_event_map),
+	.read_pmc	= sparc_default_read_pmc,
+	.write_pmc	= sparc_default_write_pmc,
 	.upper_shift	= 19,
 	.lower_shift	= 6,
 	.event_mask	= 0xfff,
-	.hv_bit		= 0x8,
+	.user_bit	= PCR_UTRACE,
+	.priv_bit	= PCR_STRACE,
+	.hv_bit		= PCR_N2_HTRACE,
 	.irq_bit	= 0x30,
 	.upper_nop	= 0x220,
 	.lower_nop	= 0x220,
+	.flags		= (SPARC_PMU_ALL_EXCLUDES_SAME |
+			   SPARC_PMU_HAS_CONFLICTS),
+	.max_hw_events	= 2,
+	.num_pcrs	= 1,
+	.num_pic_regs	= 1,
+};
+
+static const struct perf_event_map niagara4_perfmon_event_map[] = {
+	[PERF_COUNT_HW_CPU_CYCLES] = { (26 << 6) },
+	[PERF_COUNT_HW_INSTRUCTIONS] = { (3 << 6) | 0x3f },
+	[PERF_COUNT_HW_CACHE_REFERENCES] = { (3 << 6) | 0x04 },
+	[PERF_COUNT_HW_CACHE_MISSES] = { (16 << 6) | 0x07 },
+	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = { (4 << 6) | 0x01 },
+	[PERF_COUNT_HW_BRANCH_MISSES] = { (25 << 6) | 0x0f },
+};
+
+static const struct perf_event_map *niagara4_event_map(int event_id)
+{
+	return &niagara4_perfmon_event_map[event_id];
+}
+
+static const cache_map_t niagara4_cache_map = {
+[C(L1D)] = {
+	[C(OP_READ)] = {
+		[C(RESULT_ACCESS)] = { (3 << 6) | 0x04 },
+		[C(RESULT_MISS)] = { (16 << 6) | 0x07 },
+	},
+	[C(OP_WRITE)] = {
+		[C(RESULT_ACCESS)] = { (3 << 6) | 0x08 },
+		[C(RESULT_MISS)] = { (16 << 6) | 0x07 },
+	},
+	[C(OP_PREFETCH)] = {
+		[C(RESULT_ACCESS)] = { CACHE_OP_UNSUPPORTED },
+		[C(RESULT_MISS)] = { CACHE_OP_UNSUPPORTED },
+	},
+},
+[C(L1I)] = {
+	[C(OP_READ)] = {
+		[C(RESULT_ACCESS)] = { (3 << 6) | 0x3f },
+		[C(RESULT_MISS)] = { (11 << 6) | 0x03 },
+	},
+	[ C(OP_WRITE) ] = {
+		[ C(RESULT_ACCESS) ] = { CACHE_OP_NONSENSE },
+		[ C(RESULT_MISS)   ] = { CACHE_OP_NONSENSE },
+	},
+	[ C(OP_PREFETCH) ] = {
+		[ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED },
+		[ C(RESULT_MISS)   ] = { CACHE_OP_UNSUPPORTED },
+	},
+},
+[C(LL)] = {
+	[C(OP_READ)] = {
+		[C(RESULT_ACCESS)] = { (3 << 6) | 0x04 },
+		[C(RESULT_MISS)] = { CACHE_OP_UNSUPPORTED },
+	},
+	[C(OP_WRITE)] = {
+		[C(RESULT_ACCESS)] = { (3 << 6) | 0x08 },
+		[C(RESULT_MISS)] = { CACHE_OP_UNSUPPORTED },
+	},
+	[C(OP_PREFETCH)] = {
+		[C(RESULT_ACCESS)] = { CACHE_OP_UNSUPPORTED },
+		[C(RESULT_MISS)] = { CACHE_OP_UNSUPPORTED },
+	},
+},
+[C(DTLB)] = {
+	[C(OP_READ)] = {
+		[C(RESULT_ACCESS)] = { CACHE_OP_UNSUPPORTED },
+		[C(RESULT_MISS)] = { (17 << 6) | 0x3f },
+	},
+	[ C(OP_WRITE) ] = {
+		[ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED },
+		[ C(RESULT_MISS)   ] = { CACHE_OP_UNSUPPORTED },
+	},
+	[ C(OP_PREFETCH) ] = {
+		[ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED },
+		[ C(RESULT_MISS)   ] = { CACHE_OP_UNSUPPORTED },
+	},
+},
+[C(ITLB)] = {
+	[C(OP_READ)] = {
+		[C(RESULT_ACCESS)] = { CACHE_OP_UNSUPPORTED },
+		[C(RESULT_MISS)] = { (6 << 6) | 0x3f },
+	},
+	[ C(OP_WRITE) ] = {
+		[ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED },
+		[ C(RESULT_MISS)   ] = { CACHE_OP_UNSUPPORTED },
+	},
+	[ C(OP_PREFETCH) ] = {
+		[ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED },
+		[ C(RESULT_MISS)   ] = { CACHE_OP_UNSUPPORTED },
+	},
+},
+[C(BPU)] = {
+	[C(OP_READ)] = {
+		[C(RESULT_ACCESS)] = { CACHE_OP_UNSUPPORTED },
+		[C(RESULT_MISS)] = { CACHE_OP_UNSUPPORTED },
+	},
+	[ C(OP_WRITE) ] = {
+		[ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED },
+		[ C(RESULT_MISS)   ] = { CACHE_OP_UNSUPPORTED },
+	},
+	[ C(OP_PREFETCH) ] = {
+		[ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED },
+		[ C(RESULT_MISS)   ] = { CACHE_OP_UNSUPPORTED },
+	},
+},
+[C(NODE)] = {
+	[C(OP_READ)] = {
+		[C(RESULT_ACCESS)] = { CACHE_OP_UNSUPPORTED },
+		[C(RESULT_MISS)  ] = { CACHE_OP_UNSUPPORTED },
+	},
+	[ C(OP_WRITE) ] = {
+		[ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED },
+		[ C(RESULT_MISS)   ] = { CACHE_OP_UNSUPPORTED },
+	},
+	[ C(OP_PREFETCH) ] = {
+		[ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED },
+		[ C(RESULT_MISS)   ] = { CACHE_OP_UNSUPPORTED },
+	},
+},
+};
+
+static u32 sparc_vt_read_pmc(int idx)
+{
+	u64 val = pcr_ops->read_pic(idx);
+
+	return val & 0xffffffff;
+}
+
+static void sparc_vt_write_pmc(int idx, u64 val)
+{
+	u64 pcr;
+
+	/* There seems to be an internal latch on the overflow event
+	 * on SPARC-T4 that prevents it from triggering unless you
+	 * update the PIC exactly as we do here.  The requirement
+	 * seems to be that you have to turn off event counting in the
+	 * PCR around the PIC update.
+	 *
+	 * For example, after the following sequence:
+	 *
+	 * 1) set PIC to -1
+	 * 2) enable event counting and overflow reporting in PCR
+	 * 3) overflow triggers, softint 15 handler invoked
+	 * 4) clear OV bit in PCR
+	 * 5) write PIC to -1
+	 *
+	 * a subsequent overflow event will not trigger.  This
+	 * sequence works on SPARC-T3 and previous chips.
+	 */
+	pcr = pcr_ops->read_pcr(idx);
+	pcr_ops->write_pcr(idx, PCR_N4_PICNPT);
+
+	pcr_ops->write_pic(idx, val & 0xffffffff);
+
+	pcr_ops->write_pcr(idx, pcr);
+}
+
+static const struct sparc_pmu niagara4_pmu = {
+	.event_map	= niagara4_event_map,
+	.cache_map	= &niagara4_cache_map,
+	.max_events	= ARRAY_SIZE(niagara4_perfmon_event_map),
+	.read_pmc	= sparc_vt_read_pmc,
+	.write_pmc	= sparc_vt_write_pmc,
+	.upper_shift	= 5,
+	.lower_shift	= 5,
+	.event_mask	= 0x7ff,
+	.user_bit	= PCR_N4_UTRACE,
+	.priv_bit	= PCR_N4_STRACE,
+
+	/* We explicitly don't support hypervisor tracing.  The T4
+	 * generates the overflow event for precise events via a trap
+	 * which will not be generated (ie. it's completely lost) if
+	 * we happen to be in the hypervisor when the event triggers.
+	 * Essentially, the overflow event reporting is completely
+	 * unusable when you have hypervisor mode tracing enabled.
+	 */
+	.hv_bit		= 0,
+
+	.irq_bit	= PCR_N4_TOE,
+	.upper_nop	= 0,
+	.lower_nop	= 0,
+	.flags		= 0,
+	.max_hw_events	= 4,
+	.num_pcrs	= 4,
+	.num_pic_regs	= 4,
 };
 
 static const struct sparc_pmu *sparc_pmu __read_mostly;
@@ -558,55 +818,35 @@ static u64 nop_for_index(int idx)
 static inline void sparc_pmu_enable_event(struct cpu_hw_events *cpuc, struct hw_perf_event *hwc, int idx)
 {
 	u64 val, mask = mask_for_index(idx);
+	int pcr_index = 0;
 
-	val = cpuc->pcr;
+	if (sparc_pmu->num_pcrs > 1)
+		pcr_index = idx;
+
+	val = cpuc->pcr[pcr_index];
 	val &= ~mask;
 	val |= hwc->config;
-	cpuc->pcr = val;
+	cpuc->pcr[pcr_index] = val;
 
-	pcr_ops->write(cpuc->pcr);
+	pcr_ops->write_pcr(pcr_index, cpuc->pcr[pcr_index]);
 }
 
 static inline void sparc_pmu_disable_event(struct cpu_hw_events *cpuc, struct hw_perf_event *hwc, int idx)
 {
 	u64 mask = mask_for_index(idx);
 	u64 nop = nop_for_index(idx);
+	int pcr_index = 0;
 	u64 val;
 
-	val = cpuc->pcr;
+	if (sparc_pmu->num_pcrs > 1)
+		pcr_index = idx;
+
+	val = cpuc->pcr[pcr_index];
 	val &= ~mask;
 	val |= nop;
-	cpuc->pcr = val;
+	cpuc->pcr[pcr_index] = val;
 
-	pcr_ops->write(cpuc->pcr);
-}
-
-static u32 read_pmc(int idx)
-{
-	u64 val;
-
-	read_pic(val);
-	if (idx == PIC_UPPER_INDEX)
-		val >>= 32;
-
-	return val & 0xffffffff;
-}
-
-static void write_pmc(int idx, u64 val)
-{
-	u64 shift, mask, pic;
-
-	shift = 0;
-	if (idx == PIC_UPPER_INDEX)
-		shift = 32;
-
-	mask = ((u64) 0xffffffff) << shift;
-	val <<= shift;
-
-	read_pic(pic);
-	pic &= ~mask;
-	pic |= val;
-	write_pic(pic);
+	pcr_ops->write_pcr(pcr_index, cpuc->pcr[pcr_index]);
 }
 
 static u64 sparc_perf_event_update(struct perf_event *event,
@@ -618,7 +858,7 @@ static u64 sparc_perf_event_update(struct perf_event *event,
 
 again:
 	prev_raw_count = local64_read(&hwc->prev_count);
-	new_raw_count = read_pmc(idx);
+	new_raw_count = sparc_pmu->read_pmc(idx);
 
 	if (local64_cmpxchg(&hwc->prev_count, prev_raw_count,
 			     new_raw_count) != prev_raw_count)
@@ -658,25 +898,17 @@ static int sparc_perf_event_set_period(struct perf_event *event,
 
 	local64_set(&hwc->prev_count, (u64)-left);
 
-	write_pmc(idx, (u64)(-left) & 0xffffffff);
+	sparc_pmu->write_pmc(idx, (u64)(-left) & 0xffffffff);
 
 	perf_event_update_userpage(event);
 
 	return ret;
 }
 
-/* If performance event entries have been added, move existing
- * events around (if necessary) and then assign new entries to
- * counters.
- */
-static u64 maybe_change_configuration(struct cpu_hw_events *cpuc, u64 pcr)
+static void read_in_all_counters(struct cpu_hw_events *cpuc)
 {
 	int i;
 
-	if (!cpuc->n_added)
-		goto out;
-
-	/* Read in the counters which are moving.  */
 	for (i = 0; i < cpuc->n_events; i++) {
 		struct perf_event *cp = cpuc->event[i];
 
@@ -687,6 +919,20 @@ static u64 maybe_change_configuration(struct cpu_hw_events *cpuc, u64 pcr)
 			cpuc->current_idx[i] = PIC_NO_INDEX;
 		}
 	}
+}
+
+/* On this PMU all PICs are programmed using a single PCR.  Calculate
+ * the combined control register value.
+ *
+ * For such chips we require that all of the events have the same
+ * configuration, so just fetch the settings from the first entry.
+ */
+static void calculate_single_pcr(struct cpu_hw_events *cpuc)
+{
+	int i;
+
+	if (!cpuc->n_added)
+		goto out;
 
 	/* Assign to counters all unassigned events.  */
 	for (i = 0; i < cpuc->n_events; i++) {
@@ -702,20 +948,71 @@ static u64 maybe_change_configuration(struct cpu_hw_events *cpuc, u64 pcr)
 		cpuc->current_idx[i] = idx;
 
 		enc = perf_event_get_enc(cpuc->events[i]);
-		pcr &= ~mask_for_index(idx);
+		cpuc->pcr[0] &= ~mask_for_index(idx);
 		if (hwc->state & PERF_HES_STOPPED)
-			pcr |= nop_for_index(idx);
+			cpuc->pcr[0] |= nop_for_index(idx);
 		else
-			pcr |= event_encoding(enc, idx);
+			cpuc->pcr[0] |= event_encoding(enc, idx);
 	}
 out:
-	return pcr;
+	cpuc->pcr[0] |= cpuc->event[0]->hw.config_base;
+}
+
+/* On this PMU each PIC has it's own PCR control register.  */
+static void calculate_multiple_pcrs(struct cpu_hw_events *cpuc)
+{
+	int i;
+
+	if (!cpuc->n_added)
+		goto out;
+
+	for (i = 0; i < cpuc->n_events; i++) {
+		struct perf_event *cp = cpuc->event[i];
+		struct hw_perf_event *hwc = &cp->hw;
+		int idx = hwc->idx;
+		u64 enc;
+
+		if (cpuc->current_idx[i] != PIC_NO_INDEX)
+			continue;
+
+		sparc_perf_event_set_period(cp, hwc, idx);
+		cpuc->current_idx[i] = idx;
+
+		enc = perf_event_get_enc(cpuc->events[i]);
+		cpuc->pcr[idx] &= ~mask_for_index(idx);
+		if (hwc->state & PERF_HES_STOPPED)
+			cpuc->pcr[idx] |= nop_for_index(idx);
+		else
+			cpuc->pcr[idx] |= event_encoding(enc, idx);
+	}
+out:
+	for (i = 0; i < cpuc->n_events; i++) {
+		struct perf_event *cp = cpuc->event[i];
+		int idx = cp->hw.idx;
+
+		cpuc->pcr[idx] |= cp->hw.config_base;
+	}
+}
+
+/* If performance event entries have been added, move existing events
+ * around (if necessary) and then assign new entries to counters.
+ */
+static void update_pcrs_for_enable(struct cpu_hw_events *cpuc)
+{
+	if (cpuc->n_added)
+		read_in_all_counters(cpuc);
+
+	if (sparc_pmu->num_pcrs == 1) {
+		calculate_single_pcr(cpuc);
+	} else {
+		calculate_multiple_pcrs(cpuc);
+	}
 }
 
 static void sparc_pmu_enable(struct pmu *pmu)
 {
 	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
-	u64 pcr;
+	int i;
 
 	if (cpuc->enabled)
 		return;
@@ -723,26 +1020,17 @@ static void sparc_pmu_enable(struct pmu *pmu)
 	cpuc->enabled = 1;
 	barrier();
 
-	pcr = cpuc->pcr;
-	if (!cpuc->n_events) {
-		pcr = 0;
-	} else {
-		pcr = maybe_change_configuration(cpuc, pcr);
-
-		/* We require that all of the events have the same
-		 * configuration, so just fetch the settings from the
-		 * first entry.
-		 */
-		cpuc->pcr = pcr | cpuc->event[0]->hw.config_base;
-	}
+	if (cpuc->n_events)
+		update_pcrs_for_enable(cpuc);
 
-	pcr_ops->write(cpuc->pcr);
+	for (i = 0; i < sparc_pmu->num_pcrs; i++)
+		pcr_ops->write_pcr(i, cpuc->pcr[i]);
 }
 
 static void sparc_pmu_disable(struct pmu *pmu)
 {
 	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
-	u64 val;
+	int i;
 
 	if (!cpuc->enabled)
 		return;
@@ -750,12 +1038,14 @@ static void sparc_pmu_disable(struct pmu *pmu)
 	cpuc->enabled = 0;
 	cpuc->n_added = 0;
 
-	val = cpuc->pcr;
-	val &= ~(PCR_UTRACE | PCR_STRACE |
-		 sparc_pmu->hv_bit | sparc_pmu->irq_bit);
-	cpuc->pcr = val;
+	for (i = 0; i < sparc_pmu->num_pcrs; i++) {
+		u64 val = cpuc->pcr[i];
 
-	pcr_ops->write(cpuc->pcr);
+		val &= ~(sparc_pmu->user_bit | sparc_pmu->priv_bit |
+			 sparc_pmu->hv_bit | sparc_pmu->irq_bit);
+		cpuc->pcr[i] = val;
+		pcr_ops->write_pcr(i, cpuc->pcr[i]);
+	}
 }
 
 static int active_event_index(struct cpu_hw_events *cpuc,
@@ -854,9 +1144,11 @@ static DEFINE_MUTEX(pmc_grab_mutex);
 static void perf_stop_nmi_watchdog(void *unused)
 {
 	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+	int i;
 
 	stop_nmi_watchdog(NULL);
-	cpuc->pcr = pcr_ops->read();
+	for (i = 0; i < sparc_pmu->num_pcrs; i++)
+		cpuc->pcr[i] = pcr_ops->read_pcr(i);
 }
 
 void perf_event_grab_pmc(void)
@@ -942,9 +1234,17 @@ static int sparc_check_constraints(struct perf_event **evts,
 	if (!n_ev)
 		return 0;
 
-	if (n_ev > MAX_HWEVENTS)
+	if (n_ev > sparc_pmu->max_hw_events)
 		return -1;
 
+	if (!(sparc_pmu->flags & SPARC_PMU_HAS_CONFLICTS)) {
+		int i;
+
+		for (i = 0; i < n_ev; i++)
+			evts[i]->hw.idx = i;
+		return 0;
+	}
+
 	msk0 = perf_event_get_msk(events[0]);
 	if (n_ev == 1) {
 		if (msk0 & PIC_LOWER)
@@ -1000,6 +1300,9 @@ static int check_excludes(struct perf_event **evts, int n_prev, int n_new)
 	struct perf_event *event;
 	int i, n, first;
 
+	if (!(sparc_pmu->flags & SPARC_PMU_ALL_EXCLUDES_SAME))
+		return 0;
+
 	n = n_prev + n_new;
 	if (n <= 1)
 		return 0;
@@ -1059,7 +1362,7 @@ static int sparc_pmu_add(struct perf_event *event, int ef_flags)
 	perf_pmu_disable(event->pmu);
 
 	n0 = cpuc->n_events;
-	if (n0 >= MAX_HWEVENTS)
+	if (n0 >= sparc_pmu->max_hw_events)
 		goto out;
 
 	cpuc->event[n0] = event;
@@ -1146,16 +1449,16 @@ static int sparc_pmu_event_init(struct perf_event *event)
 	/* We save the enable bits in the config_base.  */
 	hwc->config_base = sparc_pmu->irq_bit;
 	if (!attr->exclude_user)
-		hwc->config_base |= PCR_UTRACE;
+		hwc->config_base |= sparc_pmu->user_bit;
 	if (!attr->exclude_kernel)
-		hwc->config_base |= PCR_STRACE;
+		hwc->config_base |= sparc_pmu->priv_bit;
 	if (!attr->exclude_hv)
 		hwc->config_base |= sparc_pmu->hv_bit;
 
 	n = 0;
 	if (event->group_leader != event) {
 		n = collect_events(event->group_leader,
-				   MAX_HWEVENTS - 1,
+				   sparc_pmu->max_hw_events - 1,
 				   evts, events, current_idx_dmy);
 		if (n < 0)
 			return -EINVAL;
@@ -1254,8 +1557,7 @@ static struct pmu pmu = {
 void perf_event_print_debug(void)
 {
 	unsigned long flags;
-	u64 pcr, pic;
-	int cpu;
+	int cpu, i;
 
 	if (!sparc_pmu)
 		return;
@@ -1264,12 +1566,13 @@ void perf_event_print_debug(void)
 
 	cpu = smp_processor_id();
 
-	pcr = pcr_ops->read();
-	read_pic(pic);
-
 	pr_info("\n");
-	pr_info("CPU#%d: PCR[%016llx] PIC[%016llx]\n",
-		cpu, pcr, pic);
+	for (i = 0; i < sparc_pmu->num_pcrs; i++)
+		pr_info("CPU#%d: PCR%d[%016llx]\n",
+			cpu, i, pcr_ops->read_pcr(i));
+	for (i = 0; i < sparc_pmu->num_pic_regs; i++)
+		pr_info("CPU#%d: PIC%d[%016llx]\n",
+			cpu, i, pcr_ops->read_pic(i));
 
 	local_irq_restore(flags);
 }
@@ -1305,8 +1608,9 @@ static int __kprobes perf_event_nmi_handler(struct notifier_block *self,
 	 * Do this before we peek at the counters to determine
 	 * overflow so we don't lose any events.
 	 */
-	if (sparc_pmu->irq_bit)
-		pcr_ops->write(cpuc->pcr);
+	if (sparc_pmu->irq_bit &&
+	    sparc_pmu->num_pcrs == 1)
+		pcr_ops->write_pcr(0, cpuc->pcr[0]);
 
 	for (i = 0; i < cpuc->n_events; i++) {
 		struct perf_event *event = cpuc->event[i];
@@ -1314,6 +1618,10 @@ static int __kprobes perf_event_nmi_handler(struct notifier_block *self,
 		struct hw_perf_event *hwc;
 		u64 val;
 
+		if (sparc_pmu->irq_bit &&
+		    sparc_pmu->num_pcrs > 1)
+			pcr_ops->write_pcr(idx, cpuc->pcr[idx]);
+
 		hwc = &event->hw;
 		val = sparc_perf_event_update(event, hwc, idx);
 		if (val & (1ULL << 31))
@@ -1352,6 +1660,10 @@ static bool __init supported_pmu(void)
 		sparc_pmu = &niagara2_pmu;
 		return true;
 	}
+	if (!strcmp(sparc_pmu_type, "niagara4")) {
+		sparc_pmu = &niagara4_pmu;
+		return true;
+	}
 	return false;
 }
 
diff --git a/arch/sparc/kernel/setup_64.c b/arch/sparc/kernel/setup_64.c
index 1414d16..0800e71 100644
--- a/arch/sparc/kernel/setup_64.c
+++ b/arch/sparc/kernel/setup_64.c
@@ -340,7 +340,12 @@ static const char *hwcaps[] = {
 	 */
 	"mul32", "div32", "fsmuld", "v8plus", "popc", "vis", "vis2",
 	"ASIBlkInit", "fmaf", "vis3", "hpc", "random", "trans", "fjfmau",
-	"ima", "cspare",
+	"ima", "cspare", "pause", "cbcond",
+};
+
+static const char *crypto_hwcaps[] = {
+	"aes", "des", "kasumi", "camellia", "md5", "sha1", "sha256",
+	"sha512", "mpmul", "montmul", "montsqr", "crc32c",
 };
 
 void cpucap_info(struct seq_file *m)
@@ -357,27 +362,61 @@ void cpucap_info(struct seq_file *m)
 			printed++;
 		}
 	}
+	if (caps & HWCAP_SPARC_CRYPTO) {
+		unsigned long cfr;
+
+		__asm__ __volatile__("rd %%asr26, %0" : "=r" (cfr));
+		for (i = 0; i < ARRAY_SIZE(crypto_hwcaps); i++) {
+			unsigned long bit = 1UL << i;
+			if (cfr & bit) {
+				seq_printf(m, "%s%s",
+					   printed ? "," : "", crypto_hwcaps[i]);
+				printed++;
+			}
+		}
+	}
 	seq_putc(m, '\n');
 }
 
+static void __init report_one_hwcap(int *printed, const char *name)
+{
+	if ((*printed) == 0)
+		printk(KERN_INFO "CPU CAPS: [");
+	printk(KERN_CONT "%s%s",
+	       (*printed) ? "," : "", name);
+	if (++(*printed) == 8) {
+		printk(KERN_CONT "]\n");
+		*printed = 0;
+	}
+}
+
+static void __init report_crypto_hwcaps(int *printed)
+{
+	unsigned long cfr;
+	int i;
+
+	__asm__ __volatile__("rd %%asr26, %0" : "=r" (cfr));
+
+	for (i = 0; i < ARRAY_SIZE(crypto_hwcaps); i++) {
+		unsigned long bit = 1UL << i;
+		if (cfr & bit)
+			report_one_hwcap(printed, crypto_hwcaps[i]);
+	}
+}
+
 static void __init report_hwcaps(unsigned long caps)
 {
 	int i, printed = 0;
 
-	printk(KERN_INFO "CPU CAPS: [");
 	for (i = 0; i < ARRAY_SIZE(hwcaps); i++) {
 		unsigned long bit = 1UL << i;
-		if (caps & bit) {
-			printk(KERN_CONT "%s%s",
-			       printed ? "," : "", hwcaps[i]);
-			if (++printed == 8) {
-				printk(KERN_CONT "]\n");
-				printk(KERN_INFO "CPU CAPS: [");
-				printed = 0;
-			}
-		}
+		if (caps & bit)
+			report_one_hwcap(&printed, hwcaps[i]);
 	}
-	printk(KERN_CONT "]\n");
+	if (caps & HWCAP_SPARC_CRYPTO)
+		report_crypto_hwcaps(&printed);
+	if (printed != 0)
+		printk(KERN_CONT "]\n");
 }
 
 static unsigned long __init mdesc_cpu_hwcap_list(void)
@@ -411,6 +450,10 @@ static unsigned long __init mdesc_cpu_hwcap_list(void)
 				break;
 			}
 		}
+		for (i = 0; i < ARRAY_SIZE(crypto_hwcaps); i++) {
+			if (!strcmp(prop, crypto_hwcaps[i]))
+				caps |= HWCAP_SPARC_CRYPTO;
+		}
 
 		plen = strlen(prop) + 1;
 		prop += plen;
diff --git a/arch/sparc/kernel/signal32.c b/arch/sparc/kernel/signal32.c
index a53e0a5..53e48f7 100644
--- a/arch/sparc/kernel/signal32.c
+++ b/arch/sparc/kernel/signal32.c
@@ -54,58 +54,6 @@ struct signal_frame32 {
 	/* __siginfo_rwin_t * */u32 rwin_save;
 } __attribute__((aligned(8)));
 
-typedef struct compat_siginfo{
-	int si_signo;
-	int si_errno;
-	int si_code;
-
-	union {
-		int _pad[SI_PAD_SIZE32];
-
-		/* kill() */
-		struct {
-			compat_pid_t _pid;		/* sender's pid */
-			unsigned int _uid;		/* sender's uid */
-		} _kill;
-
-		/* POSIX.1b timers */
-		struct {
-			compat_timer_t _tid;			/* timer id */
-			int _overrun;			/* overrun count */
-			compat_sigval_t _sigval;		/* same as below */
-			int _sys_private;		/* not to be passed to user */
-		} _timer;
-
-		/* POSIX.1b signals */
-		struct {
-			compat_pid_t _pid;		/* sender's pid */
-			unsigned int _uid;		/* sender's uid */
-			compat_sigval_t _sigval;
-		} _rt;
-
-		/* SIGCHLD */
-		struct {
-			compat_pid_t _pid;		/* which child */
-			unsigned int _uid;		/* sender's uid */
-			int _status;			/* exit code */
-			compat_clock_t _utime;
-			compat_clock_t _stime;
-		} _sigchld;
-
-		/* SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGEMT */
-		struct {
-			u32 _addr; /* faulting insn/memory ref. */
-			int _trapno;
-		} _sigfault;
-
-		/* SIGPOLL */
-		struct {
-			int _band;	/* POLL_IN, POLL_OUT, POLL_MSG */
-			int _fd;
-		} _sigpoll;
-	} _sifields;
-}compat_siginfo_t;
-
 struct rt_signal_frame32 {
 	struct sparc_stackf32	ss;
 	compat_siginfo_t	info;
diff --git a/arch/sparc/lib/ksyms.c b/arch/sparc/lib/ksyms.c
index 3b31218..ee31b88 100644
--- a/arch/sparc/lib/ksyms.c
+++ b/arch/sparc/lib/ksyms.c
@@ -134,6 +134,10 @@ EXPORT_SYMBOL(copy_user_page);
 void VISenter(void);
 EXPORT_SYMBOL(VISenter);
 
+/* CRYPTO code needs this */
+void VISenterhalf(void);
+EXPORT_SYMBOL(VISenterhalf);
+
 extern void xor_vis_2(unsigned long, unsigned long *, unsigned long *);
 extern void xor_vis_3(unsigned long, unsigned long *, unsigned long *,
 		unsigned long *);
diff --git a/arch/sparc/mm/fault_32.c b/arch/sparc/mm/fault_32.c
index 77ac917..e98bfda 100644
--- a/arch/sparc/mm/fault_32.c
+++ b/arch/sparc/mm/fault_32.c
@@ -265,6 +265,7 @@ good_area:
 		}
 		if (fault & VM_FAULT_RETRY) {
 			flags &= ~FAULT_FLAG_ALLOW_RETRY;
+			flags |= FAULT_FLAG_TRIED;
 
 			/* No need to up_read(&mm->mmap_sem) as we would
 			 * have already released it in __lock_page_or_retry
diff --git a/arch/sparc/mm/fault_64.c b/arch/sparc/mm/fault_64.c
index 1fe0429..413d292 100644
--- a/arch/sparc/mm/fault_64.c
+++ b/arch/sparc/mm/fault_64.c
@@ -452,6 +452,7 @@ good_area:
 		}
 		if (fault & VM_FAULT_RETRY) {
 			flags &= ~FAULT_FLAG_ALLOW_RETRY;
+			flags |= FAULT_FLAG_TRIED;
 
 			/* No need to up_read(&mm->mmap_sem) as we would
 			 * have already released it in __lock_page_or_retry
diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c
index d58edf5..696bb09 100644
--- a/arch/sparc/mm/init_64.c
+++ b/arch/sparc/mm/init_64.c
@@ -51,22 +51,40 @@
 
 #include "init_64.h"
 
-unsigned long kern_linear_pte_xor[2] __read_mostly;
+unsigned long kern_linear_pte_xor[4] __read_mostly;
 
-/* A bitmap, one bit for every 256MB of physical memory.  If the bit
- * is clear, we should use a 4MB page (via kern_linear_pte_xor[0]) else
- * if set we should use a 256MB page (via kern_linear_pte_xor[1]).
+/* A bitmap, two bits for every 256MB of physical memory.  These two
+ * bits determine what page size we use for kernel linear
+ * translations.  They form an index into kern_linear_pte_xor[].  The
+ * value in the indexed slot is XOR'd with the TLB miss virtual
+ * address to form the resulting TTE.  The mapping is:
+ *
+ *	0	==>	4MB
+ *	1	==>	256MB
+ *	2	==>	2GB
+ *	3	==>	16GB
+ *
+ * All sun4v chips support 256MB pages.  Only SPARC-T4 and later
+ * support 2GB pages, and hopefully future cpus will support the 16GB
+ * pages as well.  For slots 2 and 3, we encode a 256MB TTE xor there
+ * if these larger page sizes are not supported by the cpu.
+ *
+ * It would be nice to determine this from the machine description
+ * 'cpu' properties, but we need to have this table setup before the
+ * MDESC is initialized.
  */
 unsigned long kpte_linear_bitmap[KPTE_BITMAP_BYTES / sizeof(unsigned long)];
 
 #ifndef CONFIG_DEBUG_PAGEALLOC
-/* A special kernel TSB for 4MB and 256MB linear mappings.
- * Space is allocated for this right after the trap table
- * in arch/sparc64/kernel/head.S
+/* A special kernel TSB for 4MB, 256MB, 2GB and 16GB linear mappings.
+ * Space is allocated for this right after the trap table in
+ * arch/sparc64/kernel/head.S
  */
 extern struct tsb swapper_4m_tsb[KERNEL_TSB4M_NENTRIES];
 #endif
 
+static unsigned long cpu_pgsz_mask;
+
 #define MAX_BANKS	32
 
 static struct linux_prom64_registers pavail[MAX_BANKS] __devinitdata;
@@ -403,6 +421,12 @@ EXPORT_SYMBOL(flush_icache_range);
 
 void mmu_info(struct seq_file *m)
 {
+	static const char *pgsz_strings[] = {
+		"8K", "64K", "512K", "4MB", "32MB",
+		"256MB", "2GB", "16GB",
+	};
+	int i, printed;
+
 	if (tlb_type == cheetah)
 		seq_printf(m, "MMU Type\t: Cheetah\n");
 	else if (tlb_type == cheetah_plus)
@@ -414,6 +438,17 @@ void mmu_info(struct seq_file *m)
 	else
 		seq_printf(m, "MMU Type\t: ???\n");
 
+	seq_printf(m, "MMU PGSZs\t: ");
+	printed = 0;
+	for (i = 0; i < ARRAY_SIZE(pgsz_strings); i++) {
+		if (cpu_pgsz_mask & (1UL << i)) {
+			seq_printf(m, "%s%s",
+				   printed ? "," : "", pgsz_strings[i]);
+			printed++;
+		}
+	}
+	seq_putc(m, '\n');
+
 #ifdef CONFIG_DEBUG_DCFLUSH
 	seq_printf(m, "DCPageFlushes\t: %d\n",
 		   atomic_read(&dcpage_flushes));
@@ -1358,32 +1393,75 @@ static unsigned long __ref kernel_map_range(unsigned long pstart,
 extern unsigned int kvmap_linear_patch[1];
 #endif /* CONFIG_DEBUG_PAGEALLOC */
 
-static void __init mark_kpte_bitmap(unsigned long start, unsigned long end)
+static void __init kpte_set_val(unsigned long index, unsigned long val)
 {
-	const unsigned long shift_256MB = 28;
-	const unsigned long mask_256MB = ((1UL << shift_256MB) - 1UL);
-	const unsigned long size_256MB = (1UL << shift_256MB);
+	unsigned long *ptr = kpte_linear_bitmap;
 
-	while (start < end) {
-		long remains;
+	val <<= ((index % (BITS_PER_LONG / 2)) * 2);
+	ptr += (index / (BITS_PER_LONG / 2));
 
-		remains = end - start;
-		if (remains < size_256MB)
-			break;
+	*ptr |= val;
+}
 
-		if (start & mask_256MB) {
-			start = (start + size_256MB) & ~mask_256MB;
-			continue;
-		}
+static const unsigned long kpte_shift_min = 28; /* 256MB */
+static const unsigned long kpte_shift_max = 34; /* 16GB */
+static const unsigned long kpte_shift_incr = 3;
+
+static unsigned long kpte_mark_using_shift(unsigned long start, unsigned long end,
+					   unsigned long shift)
+{
+	unsigned long size = (1UL << shift);
+	unsigned long mask = (size - 1UL);
+	unsigned long remains = end - start;
+	unsigned long val;
+
+	if (remains < size || (start & mask))
+		return start;
+
+	/* VAL maps:
+	 *
+	 *	shift 28 --> kern_linear_pte_xor index 1
+	 *	shift 31 --> kern_linear_pte_xor index 2
+	 *	shift 34 --> kern_linear_pte_xor index 3
+	 */
+	val = ((shift - kpte_shift_min) / kpte_shift_incr) + 1;
+
+	remains &= ~mask;
+	if (shift != kpte_shift_max)
+		remains = size;
 
-		while (remains >= size_256MB) {
-			unsigned long index = start >> shift_256MB;
+	while (remains) {
+		unsigned long index = start >> kpte_shift_min;
 
-			__set_bit(index, kpte_linear_bitmap);
+		kpte_set_val(index, val);
 
-			start += size_256MB;
-			remains -= size_256MB;
+		start += 1UL << kpte_shift_min;
+		remains -= 1UL << kpte_shift_min;
+	}
+
+	return start;
+}
+
+static void __init mark_kpte_bitmap(unsigned long start, unsigned long end)
+{
+	unsigned long smallest_size, smallest_mask;
+	unsigned long s;
+
+	smallest_size = (1UL << kpte_shift_min);
+	smallest_mask = (smallest_size - 1UL);
+
+	while (start < end) {
+		unsigned long orig_start = start;
+
+		for (s = kpte_shift_max; s >= kpte_shift_min; s -= kpte_shift_incr) {
+			start = kpte_mark_using_shift(start, end, s);
+
+			if (start != orig_start)
+				break;
 		}
+
+		if (start == orig_start)
+			start = (start + smallest_size) & ~smallest_mask;
 	}
 }
 
@@ -1577,13 +1655,16 @@ static void __init sun4v_ktsb_init(void)
 	ktsb_descr[0].resv = 0;
 
 #ifndef CONFIG_DEBUG_PAGEALLOC
-	/* Second KTSB for 4MB/256MB mappings.  */
+	/* Second KTSB for 4MB/256MB/2GB/16GB mappings.  */
 	ktsb_pa = (kern_base +
 		   ((unsigned long)&swapper_4m_tsb[0] - KERNBASE));
 
 	ktsb_descr[1].pgsz_idx = HV_PGSZ_IDX_4MB;
-	ktsb_descr[1].pgsz_mask = (HV_PGSZ_MASK_4MB |
-				   HV_PGSZ_MASK_256MB);
+	ktsb_descr[1].pgsz_mask = ((HV_PGSZ_MASK_4MB |
+				    HV_PGSZ_MASK_256MB |
+				    HV_PGSZ_MASK_2GB |
+				    HV_PGSZ_MASK_16GB) &
+				   cpu_pgsz_mask);
 	ktsb_descr[1].assoc = 1;
 	ktsb_descr[1].num_ttes = KERNEL_TSB4M_NENTRIES;
 	ktsb_descr[1].ctx_idx = 0;
@@ -1606,6 +1687,47 @@ void __cpuinit sun4v_ktsb_register(void)
 	}
 }
 
+static void __init sun4u_linear_pte_xor_finalize(void)
+{
+#ifndef CONFIG_DEBUG_PAGEALLOC
+	/* This is where we would add Panther support for
+	 * 32MB and 256MB pages.
+	 */
+#endif
+}
+
+static void __init sun4v_linear_pte_xor_finalize(void)
+{
+#ifndef CONFIG_DEBUG_PAGEALLOC
+	if (cpu_pgsz_mask & HV_PGSZ_MASK_256MB) {
+		kern_linear_pte_xor[1] = (_PAGE_VALID | _PAGE_SZ256MB_4V) ^
+			0xfffff80000000000UL;
+		kern_linear_pte_xor[1] |= (_PAGE_CP_4V | _PAGE_CV_4V |
+					   _PAGE_P_4V | _PAGE_W_4V);
+	} else {
+		kern_linear_pte_xor[1] = kern_linear_pte_xor[0];
+	}
+
+	if (cpu_pgsz_mask & HV_PGSZ_MASK_2GB) {
+		kern_linear_pte_xor[2] = (_PAGE_VALID | _PAGE_SZ2GB_4V) ^
+			0xfffff80000000000UL;
+		kern_linear_pte_xor[2] |= (_PAGE_CP_4V | _PAGE_CV_4V |
+					   _PAGE_P_4V | _PAGE_W_4V);
+	} else {
+		kern_linear_pte_xor[2] = kern_linear_pte_xor[1];
+	}
+
+	if (cpu_pgsz_mask & HV_PGSZ_MASK_16GB) {
+		kern_linear_pte_xor[3] = (_PAGE_VALID | _PAGE_SZ16GB_4V) ^
+			0xfffff80000000000UL;
+		kern_linear_pte_xor[3] |= (_PAGE_CP_4V | _PAGE_CV_4V |
+					   _PAGE_P_4V | _PAGE_W_4V);
+	} else {
+		kern_linear_pte_xor[3] = kern_linear_pte_xor[2];
+	}
+#endif
+}
+
 /* paging_init() sets up the page tables */
 
 static unsigned long last_valid_pfn;
@@ -1665,10 +1787,8 @@ void __init paging_init(void)
 		ktsb_phys_patch();
 	}
 
-	if (tlb_type == hypervisor) {
+	if (tlb_type == hypervisor)
 		sun4v_patch_tlb_handlers();
-		sun4v_ktsb_init();
-	}
 
 	/* Find available physical memory...
 	 *
@@ -1727,9 +1847,6 @@ void __init paging_init(void)
 
 	__flush_tlb_all();
 
-	if (tlb_type == hypervisor)
-		sun4v_ktsb_register();
-
 	prom_build_devicetree();
 	of_populate_present_mask();
 #ifndef CONFIG_SMP
@@ -1742,8 +1859,36 @@ void __init paging_init(void)
 #ifndef CONFIG_SMP
 		mdesc_fill_in_cpu_data(cpu_all_mask);
 #endif
+		mdesc_get_page_sizes(cpu_all_mask, &cpu_pgsz_mask);
+
+		sun4v_linear_pte_xor_finalize();
+
+		sun4v_ktsb_init();
+		sun4v_ktsb_register();
+	} else {
+		unsigned long impl, ver;
+
+		cpu_pgsz_mask = (HV_PGSZ_MASK_8K | HV_PGSZ_MASK_64K |
+				 HV_PGSZ_MASK_512K | HV_PGSZ_MASK_4MB);
+
+		__asm__ __volatile__("rdpr %%ver, %0" : "=r" (ver));
+		impl = ((ver >> 32) & 0xffff);
+		if (impl == PANTHER_IMPL)
+			cpu_pgsz_mask |= (HV_PGSZ_MASK_32MB |
+					  HV_PGSZ_MASK_256MB);
+
+		sun4u_linear_pte_xor_finalize();
 	}
 
+	/* Flush the TLBs and the 4M TSB so that the updated linear
+	 * pte XOR settings are realized for all mappings.
+	 */
+	__flush_tlb_all();
+#ifndef CONFIG_DEBUG_PAGEALLOC
+	memset(swapper_4m_tsb, 0x40, sizeof(swapper_4m_tsb));
+#endif
+	__flush_tlb_all();
+
 	/* Setup bootmem... */
 	last_valid_pfn = end_pfn = bootmem_init(phys_base);
 
@@ -2110,6 +2255,7 @@ static void __init sun4u_pgprot_init(void)
 {
 	unsigned long page_none, page_shared, page_copy, page_readonly;
 	unsigned long page_exec_bit;
+	int i;
 
 	PAGE_KERNEL = __pgprot (_PAGE_PRESENT_4U | _PAGE_VALID |
 				_PAGE_CACHE_4U | _PAGE_P_4U |
@@ -2137,8 +2283,8 @@ static void __init sun4u_pgprot_init(void)
 	kern_linear_pte_xor[0] |= (_PAGE_CP_4U | _PAGE_CV_4U |
 				   _PAGE_P_4U | _PAGE_W_4U);
 
-	/* XXX Should use 256MB on Panther. XXX */
-	kern_linear_pte_xor[1] = kern_linear_pte_xor[0];
+	for (i = 1; i < 4; i++)
+		kern_linear_pte_xor[i] = kern_linear_pte_xor[0];
 
 	_PAGE_SZBITS = _PAGE_SZBITS_4U;
 	_PAGE_ALL_SZ_BITS =  (_PAGE_SZ4MB_4U | _PAGE_SZ512K_4U |
@@ -2164,6 +2310,7 @@ static void __init sun4v_pgprot_init(void)
 {
 	unsigned long page_none, page_shared, page_copy, page_readonly;
 	unsigned long page_exec_bit;
+	int i;
 
 	PAGE_KERNEL = __pgprot (_PAGE_PRESENT_4V | _PAGE_VALID |
 				_PAGE_CACHE_4V | _PAGE_P_4V |
@@ -2185,15 +2332,8 @@ static void __init sun4v_pgprot_init(void)
 	kern_linear_pte_xor[0] |= (_PAGE_CP_4V | _PAGE_CV_4V |
 				   _PAGE_P_4V | _PAGE_W_4V);
 
-#ifdef CONFIG_DEBUG_PAGEALLOC
-	kern_linear_pte_xor[1] = (_PAGE_VALID | _PAGE_SZBITS_4V) ^
-		0xfffff80000000000UL;
-#else
-	kern_linear_pte_xor[1] = (_PAGE_VALID | _PAGE_SZ256MB_4V) ^
-		0xfffff80000000000UL;
-#endif
-	kern_linear_pte_xor[1] |= (_PAGE_CP_4V | _PAGE_CV_4V |
-				   _PAGE_P_4V | _PAGE_W_4V);
+	for (i = 1; i < 4; i++)
+		kern_linear_pte_xor[i] = kern_linear_pte_xor[0];
 
 	pg_iobits = (_PAGE_VALID | _PAGE_PRESENT_4V | __DIRTY_BITS_4V |
 		     __ACCESS_BITS_4V | _PAGE_E_4V);
diff --git a/arch/sparc/mm/init_64.h b/arch/sparc/mm/init_64.h
index 3e1ac8b..0661aa6 100644
--- a/arch/sparc/mm/init_64.h
+++ b/arch/sparc/mm/init_64.h
@@ -8,12 +8,12 @@
 #define MAX_PHYS_ADDRESS	(1UL << 41UL)
 #define KPTE_BITMAP_CHUNK_SZ		(256UL * 1024UL * 1024UL)
 #define KPTE_BITMAP_BYTES	\
-	((MAX_PHYS_ADDRESS / KPTE_BITMAP_CHUNK_SZ) / 8)
+	((MAX_PHYS_ADDRESS / KPTE_BITMAP_CHUNK_SZ) / 4)
 #define VALID_ADDR_BITMAP_CHUNK_SZ	(4UL * 1024UL * 1024UL)
 #define VALID_ADDR_BITMAP_BYTES	\
 	((MAX_PHYS_ADDRESS / VALID_ADDR_BITMAP_CHUNK_SZ) / 8)
 
-extern unsigned long kern_linear_pte_xor[2];
+extern unsigned long kern_linear_pte_xor[4];
 extern unsigned long kpte_linear_bitmap[KPTE_BITMAP_BYTES / sizeof(unsigned long)];
 extern unsigned int sparc64_highest_unlocked_tlb_ent;
 extern unsigned long sparc64_kern_pri_context;
diff --git a/arch/tile/Kconfig b/arch/tile/Kconfig
index 932e443..8e018e2 100644
--- a/arch/tile/Kconfig
+++ b/arch/tile/Kconfig
@@ -17,6 +17,7 @@ config TILE
 	select SYS_HYPERVISOR
 	select ARCH_HAVE_NMI_SAFE_CMPXCHG
 	select GENERIC_CLOCKEVENTS
+	select MODULES_USE_ELF_RELA
 
 # FIXME: investigate whether we need/want these options.
 #	select HAVE_IOREMAP_PROT
@@ -412,14 +413,6 @@ config TILE_USB
 config NEED_BOUNCE_POOL
 	def_bool USB_OHCI_HCD
 
-config HOTPLUG
-	bool "Support for hot-pluggable devices"
-	---help---
-	  Say Y here if you want to plug devices into your computer while
-	  the system is running, and be able to use them quickly.  In many
-	  cases, the devices can likewise be unplugged at any time too.
-	  One well-known example of this is USB.
-
 source "drivers/pci/hotplug/Kconfig"
 
 endmenu
diff --git a/arch/tile/configs/tilegx_defconfig b/arch/tile/configs/tilegx_defconfig
index 0270620..8c5eff6 100644
--- a/arch/tile/configs/tilegx_defconfig
+++ b/arch/tile/configs/tilegx_defconfig
@@ -134,7 +134,6 @@ CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m
 CONFIG_NETFILTER_XT_TARGET_MARK=m
 CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
-CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
 CONFIG_NETFILTER_XT_TARGET_TEE=m
 CONFIG_NETFILTER_XT_TARGET_TPROXY=m
 CONFIG_NETFILTER_XT_TARGET_TRACE=m
diff --git a/arch/tile/configs/tilepro_defconfig b/arch/tile/configs/tilepro_defconfig
index c11de27..e7a3dfc 100644
--- a/arch/tile/configs/tilepro_defconfig
+++ b/arch/tile/configs/tilepro_defconfig
@@ -132,7 +132,6 @@ CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m
 CONFIG_NETFILTER_XT_TARGET_MARK=m
 CONFIG_NETFILTER_XT_TARGET_NFLOG=m
 CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
-CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
 CONFIG_NETFILTER_XT_TARGET_TEE=m
 CONFIG_NETFILTER_XT_TARGET_TPROXY=m
 CONFIG_NETFILTER_XT_TARGET_TRACE=m
diff --git a/arch/tile/include/asm/Kbuild b/arch/tile/include/asm/Kbuild
index 5bd7199..5a5e679 100644
--- a/arch/tile/include/asm/Kbuild
+++ b/arch/tile/include/asm/Kbuild
@@ -12,6 +12,7 @@ generic-y += cputime.h
 generic-y += div64.h
 generic-y += emergency-restart.h
 generic-y += errno.h
+generic-y += exec.h
 generic-y += fb.h
 generic-y += fcntl.h
 generic-y += ioctl.h
diff --git a/arch/tile/include/asm/compat.h b/arch/tile/include/asm/compat.h
index 6e74450..3063e6f 100644
--- a/arch/tile/include/asm/compat.h
+++ b/arch/tile/include/asm/compat.h
@@ -110,6 +110,68 @@ struct compat_flock64 {
 
 typedef u32               compat_sigset_word;
 
+typedef union compat_sigval {
+	compat_int_t	sival_int;
+	compat_uptr_t	sival_ptr;
+} compat_sigval_t;
+
+#define COMPAT_SI_PAD_SIZE	(128/sizeof(int) - 3)
+
+typedef struct compat_siginfo {
+	int si_signo;
+	int si_errno;
+	int si_code;
+
+	union {
+		int _pad[COMPAT_SI_PAD_SIZE];
+
+		/* kill() */
+		struct {
+			unsigned int _pid;	/* sender's pid */
+			unsigned int _uid;	/* sender's uid */
+		} _kill;
+
+		/* POSIX.1b timers */
+		struct {
+			compat_timer_t _tid;	/* timer id */
+			int _overrun;		/* overrun count */
+			compat_sigval_t _sigval;	/* same as below */
+			int _sys_private;	/* not to be passed to user */
+			int _overrun_incr;	/* amount to add to overrun */
+		} _timer;
+
+		/* POSIX.1b signals */
+		struct {
+			unsigned int _pid;	/* sender's pid */
+			unsigned int _uid;	/* sender's uid */
+			compat_sigval_t _sigval;
+		} _rt;
+
+		/* SIGCHLD */
+		struct {
+			unsigned int _pid;	/* which child */
+			unsigned int _uid;	/* sender's uid */
+			int _status;		/* exit code */
+			compat_clock_t _utime;
+			compat_clock_t _stime;
+		} _sigchld;
+
+		/* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
+		struct {
+			unsigned int _addr;	/* faulting insn/memory ref. */
+#ifdef __ARCH_SI_TRAPNO
+			int _trapno;	/* TRAP # which caused the signal */
+#endif
+		} _sigfault;
+
+		/* SIGPOLL */
+		struct {
+			int _band;	/* POLL_IN, POLL_OUT, POLL_MSG */
+			int _fd;
+		} _sigpoll;
+	} _sifields;
+} compat_siginfo_t;
+
 #define COMPAT_OFF_T_MAX	0x7fffffff
 #define COMPAT_LOFF_T_MAX	0x7fffffffffffffffL
 
diff --git a/arch/tile/include/asm/elf.h b/arch/tile/include/asm/elf.h
index d16d006..f8ccf08 100644
--- a/arch/tile/include/asm/elf.h
+++ b/arch/tile/include/asm/elf.h
@@ -156,12 +156,12 @@ extern int arch_setup_additional_pages(struct linux_binprm *bprm,
 #undef SET_PERSONALITY
 #define SET_PERSONALITY(ex) \
 do { \
-	current->personality = PER_LINUX; \
+	set_personality(PER_LINUX | (current->personality & (~PER_MASK))); \
 	current_thread_info()->status &= ~TS_COMPAT; \
 } while (0)
 #define COMPAT_SET_PERSONALITY(ex) \
 do { \
-	current->personality = PER_LINUX_32BIT; \
+	set_personality(PER_LINUX | (current->personality & (~PER_MASK))); \
 	current_thread_info()->status |= TS_COMPAT; \
 } while (0)
 
diff --git a/arch/tile/include/asm/exec.h b/arch/tile/include/asm/exec.h
deleted file mode 100644
index a714e19..0000000
--- a/arch/tile/include/asm/exec.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright 2010 Tilera Corporation. All Rights Reserved.
- *
- *   This program is free software; you can redistribute it and/or
- *   modify it under the terms of the GNU General Public License
- *   as published by the Free Software Foundation, version 2.
- *
- *   This program is distributed in the hope that it will be useful, but
- *   WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- *   NON INFRINGEMENT.  See the GNU General Public License for
- *   more details.
- */
-
-#ifndef _ASM_TILE_EXEC_H
-#define _ASM_TILE_EXEC_H
-
-#define arch_align_stack(x) (x)
-
-#endif /* _ASM_TILE_EXEC_H */
diff --git a/arch/tile/include/asm/hugetlb.h b/arch/tile/include/asm/hugetlb.h
index b204238..0f885af 100644
--- a/arch/tile/include/asm/hugetlb.h
+++ b/arch/tile/include/asm/hugetlb.h
@@ -106,6 +106,10 @@ static inline void arch_release_hugepage(struct page *page)
 {
 }
 
+static inline void arch_clear_hugepage_flags(struct page *page)
+{
+}
+
 #ifdef CONFIG_HUGETLB_SUPER_PAGES
 static inline pte_t arch_make_huge_pte(pte_t entry, struct vm_area_struct *vma,
 				       struct page *page, int writable)
diff --git a/arch/tile/include/asm/topology.h b/arch/tile/include/asm/topology.h
index 7a7ce39..d5e86c9 100644
--- a/arch/tile/include/asm/topology.h
+++ b/arch/tile/include/asm/topology.h
@@ -69,7 +69,6 @@ static inline const struct cpumask *cpumask_of_node(int node)
 				| 1*SD_BALANCE_FORK			\
 				| 0*SD_BALANCE_WAKE			\
 				| 0*SD_WAKE_AFFINE			\
-				| 0*SD_PREFER_LOCAL			\
 				| 0*SD_SHARE_CPUPOWER			\
 				| 0*SD_SHARE_PKG_RESOURCES		\
 				| 0*SD_SERIALIZE			\
diff --git a/arch/tile/include/gxio/iorpc_trio.h b/arch/tile/include/gxio/iorpc_trio.h
index 15fb779..58105c3 100644
--- a/arch/tile/include/gxio/iorpc_trio.h
+++ b/arch/tile/include/gxio/iorpc_trio.h
@@ -25,21 +25,23 @@
 #include <linux/module.h>
 #include <asm/pgtable.h>
 
-#define GXIO_TRIO_OP_ALLOC_ASIDS       IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1400)
+#define GXIO_TRIO_OP_DEALLOC_ASID      IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1400)
+#define GXIO_TRIO_OP_ALLOC_ASIDS       IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1401)
 
-#define GXIO_TRIO_OP_ALLOC_MEMORY_MAPS IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1402)
+#define GXIO_TRIO_OP_ALLOC_MEMORY_MAPS IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1404)
 
-#define GXIO_TRIO_OP_ALLOC_PIO_REGIONS IORPC_OPCODE(IORPC_FORMAT_NONE, 0x140e)
-#define GXIO_TRIO_OP_INIT_PIO_REGION_AUX IORPC_OPCODE(IORPC_FORMAT_NONE, 0x140f)
+#define GXIO_TRIO_OP_ALLOC_PIO_REGIONS IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1412)
 
-#define GXIO_TRIO_OP_INIT_MEMORY_MAP_MMU_AUX IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x1417)
-#define GXIO_TRIO_OP_GET_PORT_PROPERTY IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x1418)
-#define GXIO_TRIO_OP_CONFIG_LEGACY_INTR IORPC_OPCODE(IORPC_FORMAT_KERNEL_INTERRUPT, 0x1419)
-#define GXIO_TRIO_OP_CONFIG_MSI_INTR   IORPC_OPCODE(IORPC_FORMAT_KERNEL_INTERRUPT, 0x141a)
+#define GXIO_TRIO_OP_INIT_PIO_REGION_AUX IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1414)
 
-#define GXIO_TRIO_OP_SET_MPS_MRS       IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x141c)
-#define GXIO_TRIO_OP_FORCE_RC_LINK_UP  IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x141d)
-#define GXIO_TRIO_OP_FORCE_EP_LINK_UP  IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x141e)
+#define GXIO_TRIO_OP_INIT_MEMORY_MAP_MMU_AUX IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x141e)
+#define GXIO_TRIO_OP_GET_PORT_PROPERTY IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x141f)
+#define GXIO_TRIO_OP_CONFIG_LEGACY_INTR IORPC_OPCODE(IORPC_FORMAT_KERNEL_INTERRUPT, 0x1420)
+#define GXIO_TRIO_OP_CONFIG_MSI_INTR   IORPC_OPCODE(IORPC_FORMAT_KERNEL_INTERRUPT, 0x1421)
+
+#define GXIO_TRIO_OP_SET_MPS_MRS       IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x1423)
+#define GXIO_TRIO_OP_FORCE_RC_LINK_UP  IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x1424)
+#define GXIO_TRIO_OP_FORCE_EP_LINK_UP  IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x1425)
 #define GXIO_TRIO_OP_GET_MMIO_BASE     IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x8000)
 #define GXIO_TRIO_OP_CHECK_MMIO_OFFSET IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x8001)
 
diff --git a/arch/tile/kernel/compat_signal.c b/arch/tile/kernel/compat_signal.c
index 474571b..08b4fe1 100644
--- a/arch/tile/kernel/compat_signal.c
+++ b/arch/tile/kernel/compat_signal.c
@@ -55,63 +55,6 @@ struct compat_ucontext {
 	sigset_t	  uc_sigmask;	/* mask last for extensibility */
 };
 
-#define COMPAT_SI_PAD_SIZE	((SI_MAX_SIZE - 3 * sizeof(int)) / sizeof(int))
-
-struct compat_siginfo {
-	int si_signo;
-	int si_errno;
-	int si_code;
-
-	union {
-		int _pad[COMPAT_SI_PAD_SIZE];
-
-		/* kill() */
-		struct {
-			unsigned int _pid;	/* sender's pid */
-			unsigned int _uid;	/* sender's uid */
-		} _kill;
-
-		/* POSIX.1b timers */
-		struct {
-			compat_timer_t _tid;	/* timer id */
-			int _overrun;		/* overrun count */
-			compat_sigval_t _sigval;	/* same as below */
-			int _sys_private;	/* not to be passed to user */
-			int _overrun_incr;	/* amount to add to overrun */
-		} _timer;
-
-		/* POSIX.1b signals */
-		struct {
-			unsigned int _pid;	/* sender's pid */
-			unsigned int _uid;	/* sender's uid */
-			compat_sigval_t _sigval;
-		} _rt;
-
-		/* SIGCHLD */
-		struct {
-			unsigned int _pid;	/* which child */
-			unsigned int _uid;	/* sender's uid */
-			int _status;		/* exit code */
-			compat_clock_t _utime;
-			compat_clock_t _stime;
-		} _sigchld;
-
-		/* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
-		struct {
-			unsigned int _addr;	/* faulting insn/memory ref. */
-#ifdef __ARCH_SI_TRAPNO
-			int _trapno;	/* TRAP # which caused the signal */
-#endif
-		} _sigfault;
-
-		/* SIGPOLL */
-		struct {
-			int _band;	/* POLL_IN, POLL_OUT, POLL_MSG */
-			int _fd;
-		} _sigpoll;
-	} _sifields;
-};
-
 struct compat_rt_sigframe {
 	unsigned char save_area[C_ABI_SAVE_AREA_SIZE]; /* caller save area */
 	struct compat_siginfo info;
@@ -411,15 +354,6 @@ int compat_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 	regs->regs[1] = ptr_to_compat_reg(&frame->info);
 	regs->regs[2] = ptr_to_compat_reg(&frame->uc);
 	regs->flags |= PT_FLAGS_CALLER_SAVES;
-
-	/*
-	 * Notify any tracer that was single-stepping it.
-	 * The tracer may want to single-step inside the
-	 * handler too.
-	 */
-	if (test_thread_flag(TIF_SINGLESTEP))
-		ptrace_notify(SIGTRAP);
-
 	return 0;
 
 give_sigsegv:
diff --git a/arch/tile/kernel/pci.c b/arch/tile/kernel/pci.c
index 33c1086..7598226 100644
--- a/arch/tile/kernel/pci.c
+++ b/arch/tile/kernel/pci.c
@@ -246,16 +246,13 @@ static void __devinit fixup_read_and_payload_sizes(void)
 
 	/* Scan for the smallest maximum payload size. */
 	while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
-		int pcie_caps_offset;
 		u32 devcap;
 		int max_payload;
 
-		pcie_caps_offset = pci_find_capability(dev, PCI_CAP_ID_EXP);
-		if (pcie_caps_offset == 0)
+		if (!pci_is_pcie(dev))
 			continue;
 
-		pci_read_config_dword(dev, pcie_caps_offset + PCI_EXP_DEVCAP,
-				      &devcap);
+		pcie_capability_read_dword(dev, PCI_EXP_DEVCAP, &devcap);
 		max_payload = devcap & PCI_EXP_DEVCAP_PAYLOAD;
 		if (max_payload < smallest_max_payload)
 			smallest_max_payload = max_payload;
@@ -263,21 +260,10 @@ static void __devinit fixup_read_and_payload_sizes(void)
 
 	/* Now, set the max_payload_size for all devices to that value. */
 	new_values = (max_read_size << 12) | (smallest_max_payload << 5);
-	while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
-		int pcie_caps_offset;
-		u16 devctl;
-
-		pcie_caps_offset = pci_find_capability(dev, PCI_CAP_ID_EXP);
-		if (pcie_caps_offset == 0)
-			continue;
-
-		pci_read_config_word(dev, pcie_caps_offset + PCI_EXP_DEVCTL,
-				     &devctl);
-		devctl &= ~(PCI_EXP_DEVCTL_PAYLOAD | PCI_EXP_DEVCTL_READRQ);
-		devctl |= new_values;
-		pci_write_config_word(dev, pcie_caps_offset + PCI_EXP_DEVCTL,
-				      devctl);
-	}
+	while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL)
+		pcie_capability_clear_and_set_word(dev, PCI_EXP_DEVCTL,
+				PCI_EXP_DEVCTL_PAYLOAD | PCI_EXP_DEVCTL_READRQ,
+				new_values);
 }
 
 
@@ -404,14 +390,6 @@ void pcibios_set_master(struct pci_dev *dev)
 }
 
 /*
- * This is called from the generic Linux layer.
- */
-void __devinit pcibios_update_irq(struct pci_dev *dev, int irq)
-{
-	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
-}
-
-/*
  * Enable memory and/or address decoding, as appropriate, for the
  * device described by the 'dev' struct.
  *
diff --git a/arch/tile/kernel/pci_gx.c b/arch/tile/kernel/pci_gx.c
index 0e213e3..2ba6d05 100644
--- a/arch/tile/kernel/pci_gx.c
+++ b/arch/tile/kernel/pci_gx.c
@@ -1034,14 +1034,6 @@ char __devinit *pcibios_setup(char *str)
 }
 
 /*
- * This is called from the generic Linux layer.
- */
-void __devinit pcibios_update_irq(struct pci_dev *dev, int irq)
-{
-	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
-}
-
-/*
  * Enable memory address decoding, as appropriate, for the
  * device described by the 'dev' struct. The I/O decoding
  * is disabled, though the TILE-Gx supports I/O addressing.
diff --git a/arch/tile/kernel/signal.c b/arch/tile/kernel/signal.c
index e29b055..67efb65 100644
--- a/arch/tile/kernel/signal.c
+++ b/arch/tile/kernel/signal.c
@@ -219,15 +219,6 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 	regs->regs[1] = (unsigned long) &frame->info;
 	regs->regs[2] = (unsigned long) &frame->uc;
 	regs->flags |= PT_FLAGS_CALLER_SAVES;
-
-	/*
-	 * Notify any tracer that was single-stepping it.
-	 * The tracer may want to single-step inside the
-	 * handler too.
-	 */
-	if (test_thread_flag(TIF_SINGLESTEP))
-		ptrace_notify(SIGTRAP);
-
 	return 0;
 
 give_sigsegv:
@@ -278,7 +269,8 @@ static void handle_signal(unsigned long sig, siginfo_t *info,
 		ret = setup_rt_frame(sig, ka, info, oldset, regs);
 	if (ret)
 		return;
-	signal_delivered(sig, info, ka, regs, 0);
+	signal_delivered(sig, info, ka, regs,
+			test_thread_flag(TIF_SINGLESTEP));
 }
 
 /*
diff --git a/arch/tile/mm/elf.c b/arch/tile/mm/elf.c
index 758b603..3cfa98b 100644
--- a/arch/tile/mm/elf.c
+++ b/arch/tile/mm/elf.c
@@ -36,19 +36,14 @@ static void sim_notify_exec(const char *binary_name)
 	} while (c);
 }
 
-static int notify_exec(void)
+static int notify_exec(struct mm_struct *mm)
 {
 	int retval = 0;  /* failure */
-	struct vm_area_struct *vma = current->mm->mmap;
-	while (vma) {
-		if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file)
-			break;
-		vma = vma->vm_next;
-	}
-	if (vma) {
+
+	if (mm->exe_file) {
 		char *buf = (char *) __get_free_page(GFP_KERNEL);
 		if (buf) {
-			char *path = d_path(&vma->vm_file->f_path,
+			char *path = d_path(&mm->exe_file->f_path,
 					    buf, PAGE_SIZE);
 			if (!IS_ERR(path)) {
 				sim_notify_exec(path);
@@ -106,16 +101,16 @@ int arch_setup_additional_pages(struct linux_binprm *bprm,
 	unsigned long vdso_base;
 	int retval = 0;
 
+	down_write(&mm->mmap_sem);
+
 	/*
 	 * Notify the simulator that an exec just occurred.
 	 * If we can't find the filename of the mapping, just use
 	 * whatever was passed as the linux_binprm filename.
 	 */
-	if (!notify_exec())
+	if (!notify_exec(mm))
 		sim_notify_exec(bprm->filename);
 
-	down_write(&mm->mmap_sem);
-
 	/*
 	 * MAYWRITE to allow gdb to COW and set breakpoints
 	 */
diff --git a/arch/tile/mm/fault.c b/arch/tile/mm/fault.c
index 84ce7ab..fe811fa 100644
--- a/arch/tile/mm/fault.c
+++ b/arch/tile/mm/fault.c
@@ -454,6 +454,7 @@ good_area:
 			tsk->min_flt++;
 		if (fault & VM_FAULT_RETRY) {
 			flags &= ~FAULT_FLAG_ALLOW_RETRY;
+			flags |= FAULT_FLAG_TRIED;
 
 			 /*
 			  * No need to up_read(&mm->mmap_sem) as we would
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index bbaf2c5..457475f 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -409,7 +409,8 @@ int setup_one_line(struct line *lines, int n, char *init,
 		line->valid = 1;
 		err = parse_chan_pair(new, line, n, opts, error_out);
 		if (!err) {
-			struct device *d = tty_register_device(driver, n, NULL);
+			struct device *d = tty_port_register_device(&line->port,
+					driver, n, NULL);
 			if (IS_ERR(d)) {
 				*error_out = "Failed to register device";
 				err = PTR_ERR(d);
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c
index 664a60e..495e5a7 100644
--- a/arch/um/drivers/mconsole_kern.c
+++ b/arch/um/drivers/mconsole_kern.c
@@ -21,6 +21,9 @@
 #include <linux/un.h>
 #include <linux/workqueue.h>
 #include <linux/mutex.h>
+#include <linux/fs.h>
+#include <linux/mount.h>
+#include <linux/file.h>
 #include <asm/uaccess.h>
 #include <asm/switch_to.h>
 
@@ -118,90 +121,38 @@ void mconsole_log(struct mc_request *req)
 	mconsole_reply(req, "", 0, 0);
 }
 
-/* This is a more convoluted version of mconsole_proc, which has some stability
- * problems; however, we need it fixed, because it is expected that UML users
- * mount HPPFS instead of procfs on /proc. And we want mconsole_proc to still
- * show the real procfs content, not the ones from hppfs.*/
-#if 0
 void mconsole_proc(struct mc_request *req)
 {
 	struct vfsmount *mnt = current->nsproxy->pid_ns->proc_mnt;
-	struct file *file;
-	int n;
-	char *ptr = req->request.data, *buf;
-	mm_segment_t old_fs = get_fs();
-
-	ptr += strlen("proc");
-	ptr = skip_spaces(ptr);
-
-	file = file_open_root(mnt->mnt_root, mnt, ptr, O_RDONLY);
-	if (IS_ERR(file)) {
-		mconsole_reply(req, "Failed to open file", 1, 0);
-		goto out;
-	}
-
-	buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
-	if (buf == NULL) {
-		mconsole_reply(req, "Failed to allocate buffer", 1, 0);
-		goto out_fput;
-	}
-
-	if (file->f_op->read) {
-		do {
-			loff_t pos;
-			set_fs(KERNEL_DS);
-			n = vfs_read(file, buf, PAGE_SIZE - 1, &pos);
-			file_pos_write(file, pos);
-			set_fs(old_fs);
-			if (n >= 0) {
-				buf[n] = '\0';
-				mconsole_reply(req, buf, 0, (n > 0));
-			}
-			else {
-				mconsole_reply(req, "Read of file failed",
-					       1, 0);
-				goto out_free;
-			}
-		} while (n > 0);
-	}
-	else mconsole_reply(req, "", 0, 0);
-
- out_free:
-	kfree(buf);
- out_fput:
-	fput(file);
- out: ;
-}
-#endif
-
-void mconsole_proc(struct mc_request *req)
-{
-	char path[64];
 	char *buf;
 	int len;
-	int fd;
+	struct file *file;
 	int first_chunk = 1;
 	char *ptr = req->request.data;
 
 	ptr += strlen("proc");
 	ptr = skip_spaces(ptr);
-	snprintf(path, sizeof(path), "/proc/%s", ptr);
 
-	fd = sys_open(path, 0, 0);
-	if (fd < 0) {
+	file = file_open_root(mnt->mnt_root, mnt, ptr, O_RDONLY);
+	if (IS_ERR(file)) {
 		mconsole_reply(req, "Failed to open file", 1, 0);
-		printk(KERN_ERR "open %s: %d\n",path,fd);
+		printk(KERN_ERR "open /proc/%s: %ld\n", ptr, PTR_ERR(file));
 		goto out;
 	}
 
 	buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
 	if (buf == NULL) {
 		mconsole_reply(req, "Failed to allocate buffer", 1, 0);
-		goto out_close;
+		goto out_fput;
 	}
 
-	for (;;) {
-		len = sys_read(fd, buf, PAGE_SIZE-1);
+	do {
+		loff_t pos;
+		mm_segment_t old_fs = get_fs();
+		set_fs(KERNEL_DS);
+		len = vfs_read(file, buf, PAGE_SIZE - 1, &pos);
+		set_fs(old_fs);
+		file->f_pos = pos;
 		if (len < 0) {
 			mconsole_reply(req, "Read of file failed", 1, 0);
 			goto out_free;
@@ -211,22 +162,14 @@ void mconsole_proc(struct mc_request *req)
 			mconsole_reply(req, "\n", 0, 1);
 			first_chunk = 0;
 		}
-		if (len == PAGE_SIZE-1) {
-			buf[len] = '\0';
-			mconsole_reply(req, buf, 0, 1);
-		} else {
-			buf[len] = '\0';
-			mconsole_reply(req, buf, 0, 0);
-			break;
-		}
-	}
-
+		buf[len] = '\0';
+		mconsole_reply(req, buf, 0, (len > 0));
+	} while (len > 0);
  out_free:
 	kfree(buf);
- out_close:
-	sys_close(fd);
- out:
-	/* nothing */;
+ out_fput:
+	fput(file);
+ out: ;
 }
 
 #define UML_MCONSOLE_HELPTEXT \
diff --git a/arch/um/include/asm/processor-generic.h b/arch/um/include/asm/processor-generic.h
index 69f1c57..5d9ab0c 100644
--- a/arch/um/include/asm/processor-generic.h
+++ b/arch/um/include/asm/processor-generic.h
@@ -20,14 +20,6 @@ struct mm_struct;
 
 struct thread_struct {
 	struct task_struct *saved_task;
-	/*
-	 * This flag is set to 1 before calling do_fork (and analyzed in
-	 * copy_thread) to mark that we are begin called from userspace (fork /
-	 * vfork / clone), and reset to 0 after. It is left to 0 when called
-	 * from kernelspace (i.e. kernel_thread() or fork_idle(),
-	 * as of 2.6.11).
-	 */
-	int forking;
 	struct pt_regs regs;
 	int singlestep_syscall;
 	void *fault_addr;
@@ -58,7 +50,6 @@ struct thread_struct {
 
 #define INIT_THREAD \
 { \
-	.forking		= 0, \
 	.regs		   	= EMPTY_REGS,	\
 	.fault_addr		= NULL, \
 	.prev_sched		= NULL, \
@@ -72,8 +63,6 @@ static inline void release_thread(struct task_struct *task)
 {
 }
 
-extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
-
 extern unsigned long thread_saved_pc(struct task_struct *t);
 
 static inline void mm_copy_segments(struct mm_struct *from_mm,
diff --git a/arch/um/include/asm/thread_info.h b/arch/um/include/asm/thread_info.h
index c04e5ab..2c8eeb2 100644
--- a/arch/um/include/asm/thread_info.h
+++ b/arch/um/include/asm/thread_info.h
@@ -65,8 +65,6 @@ static inline struct thread_info *current_thread_info(void)
 #define TIF_SYSCALL_TRACE	0	/* syscall trace active */
 #define TIF_SIGPENDING		1	/* signal pending */
 #define TIF_NEED_RESCHED	2	/* rescheduling necessary */
-#define TIF_POLLING_NRFLAG      3       /* true if poll_idle() is polling
-					 * TIF_NEED_RESCHED */
 #define TIF_RESTART_BLOCK	4
 #define TIF_MEMDIE		5	/* is terminating due to OOM killer */
 #define TIF_SYSCALL_AUDIT	6
@@ -76,7 +74,6 @@ static inline struct thread_info *current_thread_info(void)
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1 << TIF_NEED_RESCHED)
-#define _TIF_POLLING_NRFLAG     (1 << TIF_POLLING_NRFLAG)
 #define _TIF_MEMDIE		(1 << TIF_MEMDIE)
 #define _TIF_SYSCALL_AUDIT	(1 << TIF_SYSCALL_AUDIT)
 
diff --git a/arch/um/kernel/exec.c b/arch/um/kernel/exec.c
index 6cade93..e427301 100644
--- a/arch/um/kernel/exec.c
+++ b/arch/um/kernel/exec.c
@@ -16,7 +16,6 @@
 #include "mem_user.h"
 #include "skas.h"
 #include "os.h"
-#include "internal.h"
 
 void flush_thread(void)
 {
@@ -39,50 +38,17 @@ void flush_thread(void)
 
 void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp)
 {
+	get_safe_registers(regs->regs.gp, regs->regs.fp);
 	PT_REGS_IP(regs) = eip;
 	PT_REGS_SP(regs) = esp;
-}
-EXPORT_SYMBOL(start_thread);
-
-static long execve1(const char *file,
-		    const char __user *const __user *argv,
-		    const char __user *const __user *env)
-{
-	long error;
-
-	error = do_execve(file, argv, env, &current->thread.regs);
-	if (error == 0) {
-		task_lock(current);
-		current->ptrace &= ~PT_DTRACE;
+	current->ptrace &= ~PT_DTRACE;
 #ifdef SUBARCH_EXECVE1
-		SUBARCH_EXECVE1(&current->thread.regs.regs);
+	SUBARCH_EXECVE1(regs->regs);
 #endif
-		task_unlock(current);
-	}
-	return error;
-}
-
-long um_execve(const char *file, const char __user *const __user *argv, const char __user *const __user *env)
-{
-	long err;
-
-	err = execve1(file, argv, env);
-	if (!err)
-		UML_LONGJMP(current->thread.exec_buf, 1);
-	return err;
 }
+EXPORT_SYMBOL(start_thread);
 
-long sys_execve(const char __user *file, const char __user *const __user *argv,
-		const char __user *const __user *env)
+void __noreturn ret_from_kernel_execve(struct pt_regs *unused)
 {
-	long error;
-	char *filename;
-
-	filename = getname(file);
-	error = PTR_ERR(filename);
-	if (IS_ERR(filename)) goto out;
-	error = execve1(filename, argv, env);
-	putname(filename);
- out:
-	return error;
+	UML_LONGJMP(current->thread.exec_buf, 1);
 }
diff --git a/arch/um/kernel/internal.h b/arch/um/kernel/internal.h
deleted file mode 100644
index 5bf97db..0000000
--- a/arch/um/kernel/internal.h
+++ /dev/null
@@ -1 +0,0 @@
-extern long um_execve(const char *file, const char __user *const __user *argv, const char __user *const __user *env);
diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c
index 57fc702..a1b50ad 100644
--- a/arch/um/kernel/process.c
+++ b/arch/um/kernel/process.c
@@ -69,18 +69,6 @@ unsigned long alloc_stack(int order, int atomic)
 	return page;
 }
 
-int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
-{
-	int pid;
-
-	current->thread.request.u.thread.proc = fn;
-	current->thread.request.u.thread.arg = arg;
-	pid = do_fork(CLONE_VM | CLONE_UNTRACED | flags, 0,
-		      &current->thread.regs, 0, NULL, NULL);
-	return pid;
-}
-EXPORT_SYMBOL(kernel_thread);
-
 static inline void set_current(struct task_struct *task)
 {
 	cpu_tasks[task_thread_info(task)->cpu] = ((struct cpu_task)
@@ -177,15 +165,16 @@ void fork_handler(void)
 }
 
 int copy_thread(unsigned long clone_flags, unsigned long sp,
-		unsigned long stack_top, struct task_struct * p,
+		unsigned long arg, struct task_struct * p,
 		struct pt_regs *regs)
 {
 	void (*handler)(void);
+	int kthread = current->flags & PF_KTHREAD;
 	int ret = 0;
 
 	p->thread = (struct thread_struct) INIT_THREAD;
 
-	if (current->thread.forking) {
+	if (!kthread) {
 	  	memcpy(&p->thread.regs.regs, &regs->regs,
 		       sizeof(p->thread.regs.regs));
 		PT_REGS_SET_SYSCALL_RETURN(&p->thread.regs, 0);
@@ -195,16 +184,16 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
 		handler = fork_handler;
 
 		arch_copy_thread(&current->thread.arch, &p->thread.arch);
-	}
-	else {
+	} else {
 		get_safe_registers(p->thread.regs.regs.gp, p->thread.regs.regs.fp);
-		p->thread.request.u.thread = current->thread.request.u.thread;
+		p->thread.request.u.thread.proc = (int (*)(void *))sp;
+		p->thread.request.u.thread.arg = (void *)arg;
 		handler = new_thread_handler;
 	}
 
 	new_thread(task_stack_page(p), &p->thread.switch_buf, handler);
 
-	if (current->thread.forking) {
+	if (!kthread) {
 		clear_flushed_tls(p);
 
 		/*
diff --git a/arch/um/kernel/signal.c b/arch/um/kernel/signal.c
index 7362d58..cc9c235 100644
--- a/arch/um/kernel/signal.c
+++ b/arch/um/kernel/signal.c
@@ -22,9 +22,13 @@ static void handle_signal(struct pt_regs *regs, unsigned long signr,
 			 struct k_sigaction *ka, siginfo_t *info)
 {
 	sigset_t *oldset = sigmask_to_save();
+	int singlestep = 0;
 	unsigned long sp;
 	int err;
 
+	if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED))
+		singlestep = 1;
+
 	/* Did we come from a system call? */
 	if (PT_REGS_SYSCALL_NR(regs) >= 0) {
 		/* If so, check system call restarting.. */
@@ -61,7 +65,7 @@ static void handle_signal(struct pt_regs *regs, unsigned long signr,
 	if (err)
 		force_sigsegv(signr, current);
 	else
-		signal_delivered(signr, info, ka, regs, 0);
+		signal_delivered(signr, info, ka, regs, singlestep);
 }
 
 static int kern_do_signal(struct pt_regs *regs)
diff --git a/arch/um/kernel/syscall.c b/arch/um/kernel/syscall.c
index f958cb8..a5639c4 100644
--- a/arch/um/kernel/syscall.c
+++ b/arch/um/kernel/syscall.c
@@ -13,29 +13,28 @@
 #include "asm/mman.h"
 #include "asm/uaccess.h"
 #include "asm/unistd.h"
-#include "internal.h"
 
 long sys_fork(void)
 {
-	long ret;
-
-	current->thread.forking = 1;
-	ret = do_fork(SIGCHLD, UPT_SP(&current->thread.regs.regs),
+	return do_fork(SIGCHLD, UPT_SP(&current->thread.regs.regs),
 		      &current->thread.regs, 0, NULL, NULL);
-	current->thread.forking = 0;
-	return ret;
 }
 
 long sys_vfork(void)
 {
-	long ret;
-
-	current->thread.forking = 1;
-	ret = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD,
+	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD,
 		      UPT_SP(&current->thread.regs.regs),
 		      &current->thread.regs, 0, NULL, NULL);
-	current->thread.forking = 0;
-	return ret;
+}
+
+long sys_clone(unsigned long clone_flags, unsigned long newsp,
+	       void __user *parent_tid, void __user *child_tid)
+{
+	if (!newsp)
+		newsp = UPT_SP(&current->thread.regs.regs);
+
+	return do_fork(clone_flags, newsp, &current->thread.regs, 0, parent_tid,
+		      child_tid);
 }
 
 long old_mmap(unsigned long addr, unsigned long len,
@@ -50,19 +49,3 @@ long old_mmap(unsigned long addr, unsigned long len,
  out:
 	return err;
 }
-
-int kernel_execve(const char *filename,
-		  const char *const argv[],
-		  const char *const envp[])
-{
-	mm_segment_t fs;
-	int ret;
-
-	fs = get_fs();
-	set_fs(KERNEL_DS);
-	ret = um_execve(filename, (const char __user *const __user *)argv,
-			(const char __user *const __user *) envp);
-	set_fs(fs);
-
-	return ret;
-}
diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c
index 0353b98..0f00e9c 100644
--- a/arch/um/kernel/trap.c
+++ b/arch/um/kernel/trap.c
@@ -89,6 +89,7 @@ good_area:
 				current->min_flt++;
 			if (fault & VM_FAULT_RETRY) {
 				flags &= ~FAULT_FLAG_ALLOW_RETRY;
+				flags |= FAULT_FLAG_TRIED;
 
 				goto retry;
 			}
diff --git a/arch/unicore32/Kconfig b/arch/unicore32/Kconfig
index b0a4743..957f968 100644
--- a/arch/unicore32/Kconfig
+++ b/arch/unicore32/Kconfig
@@ -6,6 +6,7 @@ config UNICORE32
 	select HAVE_DMA_ATTRS
 	select HAVE_KERNEL_GZIP
 	select HAVE_KERNEL_BZIP2
+	select GENERIC_ATOMIC64
 	select HAVE_KERNEL_LZO
 	select HAVE_KERNEL_LZMA
 	select ARCH_HAVE_CUSTOM_GPIO_H
@@ -14,6 +15,7 @@ config UNICORE32
 	select GENERIC_IRQ_SHOW
 	select ARCH_WANT_FRAME_POINTERS
 	select GENERIC_IOMAP
+	select MODULES_USE_ELF_REL
 	help
 	  UniCore-32 is 32-bit Instruction Set Architecture,
 	  including a series of low-power-consumption RISC chip
@@ -65,6 +67,9 @@ config GENERIC_CALIBRATE_DELAY
 config ARCH_MAY_HAVE_PC_FDC
 	bool
 
+config ZONE_DMA
+	def_bool y
+
 config NEED_DMA_MAP_STATE
        def_bool y
 
diff --git a/arch/unicore32/include/asm/Kbuild b/arch/unicore32/include/asm/Kbuild
index 34b789b..90a01c8 100644
--- a/arch/unicore32/include/asm/Kbuild
+++ b/arch/unicore32/include/asm/Kbuild
@@ -10,6 +10,7 @@ generic-y += device.h
 generic-y += div64.h
 generic-y += emergency-restart.h
 generic-y += errno.h
+generic-y += exec.h
 generic-y += fb.h
 generic-y += fcntl.h
 generic-y += ftrace.h
diff --git a/arch/unicore32/include/asm/bug.h b/arch/unicore32/include/asm/bug.h
index b1ff8ca..93a56f3 100644
--- a/arch/unicore32/include/asm/bug.h
+++ b/arch/unicore32/include/asm/bug.h
@@ -19,9 +19,4 @@ extern void die(const char *msg, struct pt_regs *regs, int err);
 extern void uc32_notify_die(const char *str, struct pt_regs *regs,
 		struct siginfo *info, unsigned long err, unsigned long trap);
 
-extern asmlinkage void __backtrace(void);
-extern asmlinkage void c_backtrace(unsigned long fp, int pmode);
-
-extern void __show_regs(struct pt_regs *);
-
 #endif /* __UNICORE_BUG_H__ */
diff --git a/arch/unicore32/include/asm/cmpxchg.h b/arch/unicore32/include/asm/cmpxchg.h
index df4d5ac..8e797ad 100644
--- a/arch/unicore32/include/asm/cmpxchg.h
+++ b/arch/unicore32/include/asm/cmpxchg.h
@@ -35,7 +35,7 @@ static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
 			: "memory", "cc");
 		break;
 	default:
-		ret = __xchg_bad_pointer();
+		__xchg_bad_pointer();
 	}
 
 	return ret;
diff --git a/arch/unicore32/include/asm/exec.h b/arch/unicore32/include/asm/exec.h
deleted file mode 100644
index 06d1f0f..0000000
--- a/arch/unicore32/include/asm/exec.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * Process execution bits for PKUnity SoC and UniCore ISA
- *
- * Copyright (C) 2001-2012 GUAN Xue-tao
- *
- * This program is free software; you can 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 __UNICORE_EXEC_H__
-#define __UNICORE_EXEC_H__
-
-#define arch_align_stack(x)		(x)
-
-#endif /* __UNICORE_EXEC_H__ */
diff --git a/arch/unicore32/include/asm/thread_info.h b/arch/unicore32/include/asm/thread_info.h
index 89f7557..818b4a1 100644
--- a/arch/unicore32/include/asm/thread_info.h
+++ b/arch/unicore32/include/asm/thread_info.h
@@ -141,12 +141,12 @@ static inline struct thread_info *current_thread_info(void)
 #define _TIF_NEED_RESCHED	(1 << TIF_NEED_RESCHED)
 #define _TIF_NOTIFY_RESUME	(1 << TIF_NOTIFY_RESUME)
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
-#define _TIF_RESTORE_SIGMASK	(1 << TIF_RESTORE_SIGMASK)
 
 /*
  * Change these and you break ASM code in entry-common.S
  */
-#define _TIF_WORK_MASK		0x000000ff
+#define _TIF_WORK_MASK \
+	(_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_NOTIFY_RESUME)
 
 #endif /* __KERNEL__ */
 #endif /* __UNICORE_THREAD_INFO_H__ */
diff --git a/arch/unicore32/kernel/entry.S b/arch/unicore32/kernel/entry.S
index 00a259f..dcb87ab 100644
--- a/arch/unicore32/kernel/entry.S
+++ b/arch/unicore32/kernel/entry.S
@@ -544,8 +544,6 @@ fast_work_pending:
 work_pending:
 	cand.a	r1, #_TIF_NEED_RESCHED
 	bne	work_resched
-	cand.a	r1, #_TIF_SIGPENDING|_TIF_NOTIFY_RESUME
-	beq	no_work_pending
 	mov	r0, sp				@ 'regs'
 	mov	r2, why				@ 'syscall'
 	cand.a	r1, #_TIF_SIGPENDING		@ delivering a signal?
diff --git a/arch/unicore32/kernel/pci.c b/arch/unicore32/kernel/pci.c
index 46cb6c9..b0056f6 100644
--- a/arch/unicore32/kernel/pci.c
+++ b/arch/unicore32/kernel/pci.c
@@ -154,14 +154,6 @@ void __init puv3_pci_adjust_zones(unsigned long *zone_size,
 	zhole_size[0] = 0;
 }
 
-void __devinit pcibios_update_irq(struct pci_dev *dev, int irq)
-{
-	if (debug_pci)
-		printk(KERN_DEBUG "PCI: Assigning IRQ %02d to %s\n",
-				irq, pci_name(dev));
-	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
-}
-
 /*
  * If the bus contains any of these devices, then we must not turn on
  * parity checking of any kind.
diff --git a/arch/unicore32/kernel/process.c b/arch/unicore32/kernel/process.c
index b6f0458..b008586 100644
--- a/arch/unicore32/kernel/process.c
+++ b/arch/unicore32/kernel/process.c
@@ -380,7 +380,7 @@ int vectors_user_mapping(void)
 	return install_special_mapping(mm, 0xffff0000, PAGE_SIZE,
 				       VM_READ | VM_EXEC |
 				       VM_MAYREAD | VM_MAYEXEC |
-				       VM_RESERVED,
+				       VM_DONTEXPAND | VM_DONTDUMP,
 				       NULL);
 }
 
diff --git a/arch/unicore32/kernel/setup.h b/arch/unicore32/kernel/setup.h
index f239550..30f749d 100644
--- a/arch/unicore32/kernel/setup.h
+++ b/arch/unicore32/kernel/setup.h
@@ -30,4 +30,10 @@ extern char __vectors_start[], __vectors_end[];
 extern void kernel_thread_helper(void);
 
 extern void __init early_signal_init(void);
+
+extern asmlinkage void __backtrace(void);
+extern asmlinkage void c_backtrace(unsigned long fp, int pmode);
+
+extern void __show_regs(struct pt_regs *);
+
 #endif
diff --git a/arch/unicore32/kernel/signal.c b/arch/unicore32/kernel/signal.c
index 8adedb3..b8b2ffd 100644
--- a/arch/unicore32/kernel/signal.c
+++ b/arch/unicore32/kernel/signal.c
@@ -12,7 +12,6 @@
 #include <linux/errno.h>
 #include <linux/signal.h>
 #include <linux/personality.h>
-#include <linux/freezer.h>
 #include <linux/uaccess.h>
 #include <linux/tracehook.h>
 #include <linux/elf.h>
diff --git a/arch/unicore32/kernel/sys.c b/arch/unicore32/kernel/sys.c
index 3afe60a..5fd9af7 100644
--- a/arch/unicore32/kernel/sys.c
+++ b/arch/unicore32/kernel/sys.c
@@ -104,7 +104,6 @@ int kernel_execve(const char *filename,
  out:
 	return ret;
 }
-EXPORT_SYMBOL(kernel_execve);
 
 /* Note: used by the compat code even in 64-bit Linux. */
 SYSCALL_DEFINE6(mmap2, unsigned long, addr, unsigned long, len,
diff --git a/arch/unicore32/mm/fault.c b/arch/unicore32/mm/fault.c
index 2eeb9c0..f9b5c10 100644
--- a/arch/unicore32/mm/fault.c
+++ b/arch/unicore32/mm/fault.c
@@ -168,7 +168,7 @@ static inline bool access_error(unsigned int fsr, struct vm_area_struct *vma)
 }
 
 static int __do_pf(struct mm_struct *mm, unsigned long addr, unsigned int fsr,
-		struct task_struct *tsk)
+		unsigned int flags, struct task_struct *tsk)
 {
 	struct vm_area_struct *vma;
 	int fault;
@@ -194,14 +194,7 @@ good_area:
 	 * If for any reason at all we couldn't handle the fault, make
 	 * sure we exit gracefully rather than endlessly redo the fault.
 	 */
-	fault = handle_mm_fault(mm, vma, addr & PAGE_MASK,
-			    (!(fsr ^ 0x12)) ? FAULT_FLAG_WRITE : 0);
-	if (unlikely(fault & VM_FAULT_ERROR))
-		return fault;
-	if (fault & VM_FAULT_MAJOR)
-		tsk->maj_flt++;
-	else
-		tsk->min_flt++;
+	fault = handle_mm_fault(mm, vma, addr & PAGE_MASK, flags);
 	return fault;
 
 check_stack:
@@ -216,6 +209,8 @@ static int do_pf(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
 	struct task_struct *tsk;
 	struct mm_struct *mm;
 	int fault, sig, code;
+	unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE |
+				 ((!(fsr ^ 0x12)) ? FAULT_FLAG_WRITE : 0);
 
 	tsk = current;
 	mm = tsk->mm;
@@ -236,6 +231,7 @@ static int do_pf(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
 		if (!user_mode(regs)
 		    && !search_exception_tables(regs->UCreg_pc))
 			goto no_context;
+retry:
 		down_read(&mm->mmap_sem);
 	} else {
 		/*
@@ -251,7 +247,28 @@ static int do_pf(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
 #endif
 	}
 
-	fault = __do_pf(mm, addr, fsr, tsk);
+	fault = __do_pf(mm, addr, fsr, flags, tsk);
+
+	/* If we need to retry but a fatal signal is pending, handle the
+	 * signal first. We do not need to release the mmap_sem because
+	 * it would already be released in __lock_page_or_retry in
+	 * mm/filemap.c. */
+	if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current))
+		return 0;
+
+	if (!(fault & VM_FAULT_ERROR) && (flags & FAULT_FLAG_ALLOW_RETRY)) {
+		if (fault & VM_FAULT_MAJOR)
+			tsk->maj_flt++;
+		else
+			tsk->min_flt++;
+		if (fault & VM_FAULT_RETRY) {
+			/* Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk
+			* of starvation. */
+			flags &= ~FAULT_FLAG_ALLOW_RETRY;
+			goto retry;
+		}
+	}
+
 	up_read(&mm->mmap_sem);
 
 	/*
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 50a1d1f..f49380f 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -7,11 +7,13 @@ config 64BIT
 	  Say no to build a 32-bit kernel - formerly known as i386
 
 config X86_32
-	def_bool !64BIT
+	def_bool y
+	depends on !64BIT
 	select CLKSRC_I8253
 
 config X86_64
-	def_bool 64BIT
+	def_bool y
+	depends on 64BIT
 	select X86_DEV_DMA_OPS
 
 ### Arch settings
@@ -36,6 +38,7 @@ config X86
 	select HAVE_KRETPROBES
 	select HAVE_OPTPROBES
 	select HAVE_FTRACE_MCOUNT_RECORD
+	select HAVE_FENTRY if X86_64
 	select HAVE_C_RECORDMCOUNT
 	select HAVE_DYNAMIC_FTRACE
 	select HAVE_FUNCTION_TRACER
@@ -60,6 +63,8 @@ config X86
 	select HAVE_MIXED_BREAKPOINTS_REGS
 	select PERF_EVENTS
 	select HAVE_PERF_EVENTS_NMI
+	select HAVE_PERF_REGS
+	select HAVE_PERF_USER_STACK_DUMP
 	select ANON_INODES
 	select HAVE_ALIGNED_STRUCT_PAGE if SLUB && !M386
 	select HAVE_CMPXCHG_LOCAL if !M386
@@ -80,6 +85,7 @@ config X86
 	select IRQ_FORCED_THREADING
 	select USE_GENERIC_SMP_HELPERS if SMP
 	select HAVE_BPF_JIT if X86_64
+	select HAVE_ARCH_TRANSPARENT_HUGEPAGE
 	select CLKEVT_I8253
 	select ARCH_HAVE_NMI_SAFE_CMPXCHG
 	select GENERIC_IOMAP
@@ -97,9 +103,13 @@ config X86
 	select KTIME_SCALAR if X86_32
 	select GENERIC_STRNCPY_FROM_USER
 	select GENERIC_STRNLEN_USER
+	select MODULES_USE_ELF_REL if X86_32
+	select MODULES_USE_ELF_RELA if X86_64
+	select GENERIC_KERNEL_THREAD
 
 config INSTRUCTION_DECODER
-	def_bool (KPROBES || PERF_EVENTS || UPROBES)
+	def_bool y
+	depends on KPROBES || PERF_EVENTS || UPROBES
 
 config OUTPUT_FORMAT
 	string
@@ -127,13 +137,15 @@ config SBUS
 	bool
 
 config NEED_DMA_MAP_STATE
-       def_bool (X86_64 || INTEL_IOMMU || DMA_API_DEBUG)
+	def_bool y
+	depends on X86_64 || INTEL_IOMMU || DMA_API_DEBUG
 
 config NEED_SG_DMA_LENGTH
 	def_bool y
 
 config GENERIC_ISA_DMA
-	def_bool ISA_DMA_API
+	def_bool y
+	depends on ISA_DMA_API
 
 config GENERIC_BUG
 	def_bool y
@@ -150,13 +162,16 @@ config GENERIC_GPIO
 	bool
 
 config ARCH_MAY_HAVE_PC_FDC
-	def_bool ISA_DMA_API
+	def_bool y
+	depends on ISA_DMA_API
 
 config RWSEM_GENERIC_SPINLOCK
-	def_bool !X86_XADD
+	def_bool y
+	depends on !X86_XADD
 
 config RWSEM_XCHGADD_ALGORITHM
-	def_bool X86_XADD
+	def_bool y
+	depends on X86_XADD
 
 config GENERIC_CALIBRATE_DELAY
 	def_bool y
@@ -549,6 +564,37 @@ config SCHED_OMIT_FRAME_POINTER
 
 	  If in doubt, say "Y".
 
+config KVMTOOL_TEST_ENABLE
+	bool "Enable options to create a bootable tools/kvm/ kernel"
+	select NET
+	select NETDEVICES
+	select PCI
+	select BLOCK
+	select BLK_DEV
+	select NETWORK_FILESYSTEMS
+	select INET
+	select EXPERIMENTAL
+	select SERIAL_8250
+	select SERIAL_8250_CONSOLE
+	select IP_PNP
+	select IP_PNP_DHCP
+	select BINFMT_ELF
+	select PCI_MSI
+	select HAVE_ARCH_KGDB
+	select DEBUG_KERNEL
+	select KGDB
+	select KGDB_SERIAL_CONSOLE
+	select VIRTUALIZATION
+	select VIRTIO
+	select VIRTIO_RING
+	select VIRTIO_PCI
+	select VIRTIO_BLK
+	select VIRTIO_CONSOLE
+	select VIRTIO_NET
+	select 9P_FS
+	select NET_9P
+	select NET_9P_VIRTIO
+
 menuconfig PARAVIRT_GUEST
 	bool "Paravirtualized guest support"
 	---help---
@@ -573,23 +619,18 @@ config PARAVIRT_TIME_ACCOUNTING
 
 source "arch/x86/xen/Kconfig"
 
-config KVM_CLOCK
-	bool "KVM paravirtualized clock"
-	select PARAVIRT
-	select PARAVIRT_CLOCK
-	---help---
-	  Turning on this option will allow you to run a paravirtualized clock
-	  when running over the KVM hypervisor. Instead of relying on a PIT
-	  (or probably other) emulation by the underlying device model, the host
-	  provides the guest with timing infrastructure such as time of day, and
-	  system time
-
 config KVM_GUEST
-	bool "KVM Guest support"
+	bool "KVM Guest support (including kvmclock)"
+	select PARAVIRT
 	select PARAVIRT
+	select PARAVIRT_CLOCK
+	default y if PARAVIRT_GUEST
 	---help---
 	  This option enables various optimizations for running under the KVM
-	  hypervisor.
+	  hypervisor. It includes a paravirtualized clock, so that instead
+	  of relying on a PIT (or probably other) emulation by the
+	  underlying device model, the host provides the guest with
+	  timing infrastructure such as time of day, and system time
 
 source "arch/x86/lguest/Kconfig"
 
@@ -752,7 +793,8 @@ config SWIOTLB
 	  If unsure, say Y.
 
 config IOMMU_HELPER
-	def_bool (CALGARY_IOMMU || GART_IOMMU || SWIOTLB || AMD_IOMMU)
+	def_bool y
+	depends on CALGARY_IOMMU || GART_IOMMU || SWIOTLB || AMD_IOMMU
 
 config MAXSMP
 	bool "Enable Maximum number of SMP Processors and NUMA Nodes"
@@ -871,6 +913,7 @@ config X86_REROUTE_FOR_BROKEN_BOOT_IRQS
 
 config X86_MCE
 	bool "Machine Check / overheating reporting"
+	default y
 	---help---
 	  Machine Check support allows the processor to notify the
 	  kernel if it detects a problem (e.g. overheating, data corruption).
@@ -982,25 +1025,25 @@ config X86_REBOOTFIXUPS
 	  Say N otherwise.
 
 config MICROCODE
-	tristate "/dev/cpu/microcode - microcode support"
+	tristate "CPU microcode loading support"
 	select FW_LOADER
 	---help---
+
 	  If you say Y here, you will be able to update the microcode on
 	  certain Intel and AMD processors. The Intel support is for the
-	  IA32 family, e.g. Pentium Pro, Pentium II, Pentium III,
-	  Pentium 4, Xeon etc. The AMD support is for family 0x10 and
-	  0x11 processors, e.g. Opteron, Phenom and Turion 64 Ultra.
-	  You will obviously need the actual microcode binary data itself
-	  which is not shipped with the Linux kernel.
+	  IA32 family, e.g. Pentium Pro, Pentium II, Pentium III, Pentium 4,
+	  Xeon etc. The AMD support is for families 0x10 and later. You will
+	  obviously need the actual microcode binary data itself which is not
+	  shipped with the Linux kernel.
 
 	  This option selects the general module only, you need to select
 	  at least one vendor specific module as well.
 
-	  To compile this driver as a module, choose M here: the
-	  module will be called microcode.
+	  To compile this driver as a module, choose M here: the module
+	  will be called microcode.
 
 config MICROCODE_INTEL
-	bool "Intel microcode patch loading support"
+	bool "Intel microcode loading support"
 	depends on MICROCODE
 	default MICROCODE
 	select FW_LOADER
@@ -1013,7 +1056,7 @@ config MICROCODE_INTEL
 	  <http://www.urbanmyth.org/microcode/>.
 
 config MICROCODE_AMD
-	bool "AMD microcode patch loading support"
+	bool "AMD microcode loading support"
 	depends on MICROCODE
 	select FW_LOADER
 	---help---
@@ -1159,10 +1202,12 @@ config X86_PAE
 	  consumes more pagetable space per process.
 
 config ARCH_PHYS_ADDR_T_64BIT
-	def_bool X86_64 || X86_PAE
+	def_bool y
+	depends on X86_64 || X86_PAE
 
 config ARCH_DMA_ADDR_T_64BIT
-	def_bool X86_64 || HIGHMEM64G
+	def_bool y
+	depends on X86_64 || HIGHMEM64G
 
 config DIRECT_GBPAGES
 	bool "Enable 1GB pages for kernel pagetables" if EXPERT
@@ -1285,8 +1330,8 @@ config ARCH_SELECT_MEMORY_MODEL
 	depends on ARCH_SPARSEMEM_ENABLE
 
 config ARCH_MEMORY_PROBE
-	def_bool X86_64
-	depends on MEMORY_HOTPLUG
+	def_bool y
+	depends on X86_64 && MEMORY_HOTPLUG
 
 config ARCH_PROC_KCORE_TEXT
 	def_bool y
@@ -1487,6 +1532,17 @@ config ARCH_RANDOM
 	  If supported, this is a high bandwidth, cryptographically
 	  secure hardware random number generator.
 
+config X86_SMAP
+	def_bool y
+	prompt "Supervisor Mode Access Prevention" if EXPERT
+	---help---
+	  Supervisor Mode Access Prevention (SMAP) is a security
+	  feature in newer Intel processors.  There is a small
+	  performance cost if this enabled and turned on; there is
+	  also a small increase in the kernel size if this is enabled.
+
+	  If unsure, say Y.
+
 config EFI
 	bool "EFI runtime service support"
 	depends on ACPI
@@ -1975,7 +2031,6 @@ config PCI_MMCONFIG
 
 config PCI_CNB20LE_QUIRK
 	bool "Read CNB20LE Host Bridge Windows" if EXPERT
-	default n
 	depends on PCI && EXPERIMENTAL
 	help
 	  Read the PCI windows out of the CNB20LE host bridge. This allows
@@ -2186,18 +2241,18 @@ config COMPAT
 	depends on IA32_EMULATION || X86_X32
 	select ARCH_WANT_OLD_COMPAT_IPC
 
+if COMPAT
 config COMPAT_FOR_U64_ALIGNMENT
-	def_bool COMPAT
-	depends on X86_64
+	def_bool y
 
 config SYSVIPC_COMPAT
 	def_bool y
-	depends on COMPAT && SYSVIPC
+	depends on SYSVIPC
 
 config KEYS_COMPAT
-	bool
-	depends on COMPAT && KEYS
-	default y
+	def_bool y
+	depends on KEYS
+endif
 
 endmenu
 
diff --git a/arch/x86/Kconfig.cpu b/arch/x86/Kconfig.cpu
index 706e12e..f3b86d0 100644
--- a/arch/x86/Kconfig.cpu
+++ b/arch/x86/Kconfig.cpu
@@ -306,7 +306,8 @@ config X86_INTERNODE_CACHE_SHIFT
 	default X86_L1_CACHE_SHIFT
 
 config X86_CMPXCHG
-	def_bool X86_64 || (X86_32 && !M386)
+	def_bool y
+	depends on X86_64 || (X86_32 && !M386)
 
 config X86_L1_CACHE_SHIFT
 	int
@@ -317,7 +318,7 @@ config X86_L1_CACHE_SHIFT
 
 config X86_XADD
 	def_bool y
-	depends on X86_64 || !M386
+	depends on !M386
 
 config X86_PPRO_FENCE
 	bool "PentiumPro memory ordering errata workaround"
diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile
index e398bb5..8a84501 100644
--- a/arch/x86/boot/compressed/Makefile
+++ b/arch/x86/boot/compressed/Makefile
@@ -28,6 +28,9 @@ VMLINUX_OBJS = $(obj)/vmlinux.lds $(obj)/head_$(BITS).o $(obj)/misc.o \
 	$(obj)/string.o $(obj)/cmdline.o $(obj)/early_serial_console.o \
 	$(obj)/piggy.o
 
+$(obj)/eboot.o: KBUILD_CFLAGS += -fshort-wchar -mno-red-zone
+$(obj)/efi_stub_$(BITS).o: KBUILD_CLFAGS += -fshort-wchar -mno-red-zone
+
 ifeq ($(CONFIG_EFI_STUB), y)
 	VMLINUX_OBJS += $(obj)/eboot.o $(obj)/efi_stub_$(BITS).o
 endif
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index b3e0227..c760e07 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -276,8 +276,9 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
 	nr_gops = size / sizeof(void *);
 	for (i = 0; i < nr_gops; i++) {
 		struct efi_graphics_output_mode_info *info;
-		efi_guid_t pciio_proto = EFI_PCI_IO_PROTOCOL_GUID;
-		void *pciio;
+		efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID;
+		bool conout_found = false;
+		void *dummy;
 		void *h = gop_handle[i];
 
 		status = efi_call_phys3(sys_table->boottime->handle_protocol,
@@ -285,19 +286,21 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
 		if (status != EFI_SUCCESS)
 			continue;
 
-		efi_call_phys3(sys_table->boottime->handle_protocol,
-			       h, &pciio_proto, &pciio);
+		status = efi_call_phys3(sys_table->boottime->handle_protocol,
+					h, &conout_proto, &dummy);
+
+		if (status == EFI_SUCCESS)
+			conout_found = true;
 
 		status = efi_call_phys4(gop->query_mode, gop,
 					gop->mode->mode, &size, &info);
-		if (status == EFI_SUCCESS && (!first_gop || pciio)) {
+		if (status == EFI_SUCCESS && (!first_gop || conout_found)) {
 			/*
-			 * Apple provide GOPs that are not backed by
-			 * real hardware (they're used to handle
-			 * multiple displays). The workaround is to
-			 * search for a GOP implementing the PCIIO
-			 * protocol, and if one isn't found, to just
-			 * fallback to the first GOP.
+			 * Systems that use the UEFI Console Splitter may
+			 * provide multiple GOP devices, not all of which are
+			 * backed by real hardware. The workaround is to search
+			 * for a GOP implementing the ConOut protocol, and if
+			 * one isn't found, to just fall back to the first GOP.
 			 */
 			width = info->horizontal_resolution;
 			height = info->vertical_resolution;
@@ -308,10 +311,10 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
 			pixels_per_scan_line = info->pixels_per_scan_line;
 
 			/*
-			 * Once we've found a GOP supporting PCIIO,
+			 * Once we've found a GOP supporting ConOut,
 			 * don't bother looking any further.
 			 */
-			if (pciio)
+			if (conout_found)
 				break;
 
 			first_gop = gop;
@@ -328,7 +331,6 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
 	si->lfb_width = width;
 	si->lfb_height = height;
 	si->lfb_base = fb_base;
-	si->lfb_size = fb_size;
 	si->pages = 1;
 
 	if (pixel_format == PIXEL_RGB_RESERVED_8BIT_PER_COLOR) {
@@ -376,6 +378,10 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
 		si->rsvd_pos = 0;
 	}
 
+	si->lfb_size = si->lfb_linelength * si->lfb_height;
+
+	si->capabilities |= VIDEO_CAPABILITY_SKIP_QUIRKS;
+
 free_handle:
 	efi_call_phys1(sys_table->boottime->free_pool, gop_handle);
 	return status;
diff --git a/arch/x86/boot/compressed/eboot.h b/arch/x86/boot/compressed/eboot.h
index 3b6e156..e5b0a8f 100644
--- a/arch/x86/boot/compressed/eboot.h
+++ b/arch/x86/boot/compressed/eboot.h
@@ -14,6 +14,10 @@
 #define EFI_PAGE_SIZE		(1UL << EFI_PAGE_SHIFT)
 #define EFI_READ_CHUNK_SIZE	(1024 * 1024)
 
+#define EFI_CONSOLE_OUT_DEVICE_GUID    \
+	EFI_GUID(0xd3b36f2c, 0xd551, 0x11d4, 0x9a, 0x46, 0x0, 0x90, 0x27, \
+		  0x3f, 0xc1, 0x4d)
+
 #define PIXEL_RGB_RESERVED_8BIT_PER_COLOR		0
 #define PIXEL_BGR_RESERVED_8BIT_PER_COLOR		1
 #define PIXEL_BIT_MASK					2
diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S
index b4e15dd..2a01744 100644
--- a/arch/x86/boot/header.S
+++ b/arch/x86/boot/header.S
@@ -32,10 +32,6 @@ SYSSEG		= 0x1000		/* historical load address >> 4 */
 #define SVGA_MODE ASK_VGA
 #endif
 
-#ifndef RAMDISK
-#define RAMDISK 0
-#endif
-
 #ifndef ROOT_RDONLY
 #define ROOT_RDONLY 1
 #endif
diff --git a/arch/x86/configs/i386_defconfig b/arch/x86/configs/i386_defconfig
index 119db67..5598547 100644
--- a/arch/x86/configs/i386_defconfig
+++ b/arch/x86/configs/i386_defconfig
@@ -8,6 +8,8 @@ CONFIG_TASK_DELAY_ACCT=y
 CONFIG_TASK_XACCT=y
 CONFIG_TASK_IO_ACCOUNTING=y
 CONFIG_AUDIT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
 CONFIG_LOG_BUF_SHIFT=18
 CONFIG_CGROUPS=y
 CONFIG_CGROUP_FREEZER=y
@@ -34,8 +36,6 @@ CONFIG_SGI_PARTITION=y
 CONFIG_SUN_PARTITION=y
 CONFIG_KARMA_PARTITION=y
 CONFIG_EFI_PARTITION=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
 CONFIG_SMP=y
 CONFIG_X86_GENERIC=y
 CONFIG_HPET_TIMER=y
@@ -144,8 +144,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_DEBUG_DEVRES=y
 CONFIG_CONNECTOR=y
 CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=16384
 CONFIG_BLK_DEV_SD=y
 CONFIG_BLK_DEV_SR=y
 CONFIG_BLK_DEV_SR_VENDOR=y
@@ -231,8 +229,6 @@ CONFIG_SND_HRTIMER=y
 CONFIG_SND_HDA_INTEL=y
 CONFIG_SND_HDA_HWDEP=y
 CONFIG_HIDRAW=y
-CONFIG_HID_PID=y
-CONFIG_USB_HIDDEV=y
 CONFIG_HID_GYRATION=y
 CONFIG_LOGITECH_FF=y
 CONFIG_HID_NTRIG=y
@@ -243,11 +239,11 @@ CONFIG_HID_SAMSUNG=y
 CONFIG_HID_SONY=y
 CONFIG_HID_SUNPLUS=y
 CONFIG_HID_TOPSEED=y
+CONFIG_HID_PID=y
+CONFIG_USB_HIDDEV=y
 CONFIG_USB=y
 CONFIG_USB_DEBUG=y
 CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
-CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_DEVICE_CLASS is not set
 CONFIG_USB_MON=y
 CONFIG_USB_EHCI_HCD=y
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
@@ -262,10 +258,9 @@ CONFIG_RTC_CLASS=y
 CONFIG_DMADEVICES=y
 CONFIG_EEEPC_LAPTOP=y
 CONFIG_EFI_VARS=y
-CONFIG_EXT3_FS=y
-# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
-CONFIG_EXT3_FS_POSIX_ACL=y
-CONFIG_EXT3_FS_SECURITY=y
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
 CONFIG_QUOTA=y
 CONFIG_QUOTA_NETLINK_INTERFACE=y
 # CONFIG_PRINT_QUOTA_WARNING is not set
@@ -280,7 +275,6 @@ CONFIG_PROC_KCORE=y
 CONFIG_TMPFS_POSIX_ACL=y
 CONFIG_HUGETLBFS=y
 CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
 CONFIG_NFS_V3_ACL=y
 CONFIG_NFS_V4=y
 CONFIG_ROOT_NFS=y
@@ -299,13 +293,11 @@ CONFIG_DEBUG_KERNEL=y
 CONFIG_SCHEDSTATS=y
 CONFIG_TIMER_STATS=y
 CONFIG_DEBUG_STACK_USAGE=y
-CONFIG_SYSCTL_SYSCALL_CHECK=y
 CONFIG_BLK_DEV_IO_TRACE=y
 CONFIG_PROVIDE_OHCI1394_DMA_INIT=y
 CONFIG_EARLY_PRINTK_DBGP=y
 CONFIG_DEBUG_STACKOVERFLOW=y
 # CONFIG_DEBUG_RODATA_TEST is not set
-CONFIG_DEBUG_NX_TEST=m
 CONFIG_DEBUG_BOOT_PARAMS=y
 CONFIG_OPTIMIZE_INLINING=y
 CONFIG_KEYS_DEBUG_PROC_KEYS=y
@@ -316,4 +308,3 @@ CONFIG_SECURITY_SELINUX_BOOTPARAM=y
 CONFIG_SECURITY_SELINUX_DISABLE=y
 CONFIG_CRYPTO_AES_586=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
-CONFIG_CRC_T10DIF=y
diff --git a/arch/x86/configs/x86_64_defconfig b/arch/x86/configs/x86_64_defconfig
index 76eb290..671524d 100644
--- a/arch/x86/configs/x86_64_defconfig
+++ b/arch/x86/configs/x86_64_defconfig
@@ -8,6 +8,8 @@ CONFIG_TASK_DELAY_ACCT=y
 CONFIG_TASK_XACCT=y
 CONFIG_TASK_IO_ACCOUNTING=y
 CONFIG_AUDIT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
 CONFIG_LOG_BUF_SHIFT=18
 CONFIG_CGROUPS=y
 CONFIG_CGROUP_FREEZER=y
@@ -34,8 +36,6 @@ CONFIG_SGI_PARTITION=y
 CONFIG_SUN_PARTITION=y
 CONFIG_KARMA_PARTITION=y
 CONFIG_EFI_PARTITION=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
 CONFIG_SMP=y
 CONFIG_CALGARY_IOMMU=y
 CONFIG_NR_CPUS=64
@@ -144,8 +144,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_DEBUG_DEVRES=y
 CONFIG_CONNECTOR=y
 CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=16384
 CONFIG_BLK_DEV_SD=y
 CONFIG_BLK_DEV_SR=y
 CONFIG_BLK_DEV_SR_VENDOR=y
@@ -227,8 +225,6 @@ CONFIG_SND_HRTIMER=y
 CONFIG_SND_HDA_INTEL=y
 CONFIG_SND_HDA_HWDEP=y
 CONFIG_HIDRAW=y
-CONFIG_HID_PID=y
-CONFIG_USB_HIDDEV=y
 CONFIG_HID_GYRATION=y
 CONFIG_LOGITECH_FF=y
 CONFIG_HID_NTRIG=y
@@ -239,11 +235,11 @@ CONFIG_HID_SAMSUNG=y
 CONFIG_HID_SONY=y
 CONFIG_HID_SUNPLUS=y
 CONFIG_HID_TOPSEED=y
+CONFIG_HID_PID=y
+CONFIG_USB_HIDDEV=y
 CONFIG_USB=y
 CONFIG_USB_DEBUG=y
 CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
-CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_DEVICE_CLASS is not set
 CONFIG_USB_MON=y
 CONFIG_USB_EHCI_HCD=y
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
@@ -262,10 +258,9 @@ CONFIG_AMD_IOMMU_STATS=y
 CONFIG_INTEL_IOMMU=y
 # CONFIG_INTEL_IOMMU_DEFAULT_ON is not set
 CONFIG_EFI_VARS=y
-CONFIG_EXT3_FS=y
-# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
-CONFIG_EXT3_FS_POSIX_ACL=y
-CONFIG_EXT3_FS_SECURITY=y
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
 CONFIG_QUOTA=y
 CONFIG_QUOTA_NETLINK_INTERFACE=y
 # CONFIG_PRINT_QUOTA_WARNING is not set
@@ -280,7 +275,6 @@ CONFIG_PROC_KCORE=y
 CONFIG_TMPFS_POSIX_ACL=y
 CONFIG_HUGETLBFS=y
 CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
 CONFIG_NFS_V3_ACL=y
 CONFIG_NFS_V4=y
 CONFIG_ROOT_NFS=y
@@ -298,13 +292,11 @@ CONFIG_DEBUG_KERNEL=y
 CONFIG_SCHEDSTATS=y
 CONFIG_TIMER_STATS=y
 CONFIG_DEBUG_STACK_USAGE=y
-CONFIG_SYSCTL_SYSCALL_CHECK=y
 CONFIG_BLK_DEV_IO_TRACE=y
 CONFIG_PROVIDE_OHCI1394_DMA_INIT=y
 CONFIG_EARLY_PRINTK_DBGP=y
 CONFIG_DEBUG_STACKOVERFLOW=y
 # CONFIG_DEBUG_RODATA_TEST is not set
-CONFIG_DEBUG_NX_TEST=m
 CONFIG_DEBUG_BOOT_PARAMS=y
 CONFIG_OPTIMIZE_INLINING=y
 CONFIG_KEYS_DEBUG_PROC_KEYS=y
@@ -314,4 +306,3 @@ CONFIG_SECURITY_SELINUX=y
 CONFIG_SECURITY_SELINUX_BOOTPARAM=y
 CONFIG_SECURITY_SELINUX_DISABLE=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
-CONFIG_CRC_T10DIF=y
diff --git a/arch/x86/crypto/Makefile b/arch/x86/crypto/Makefile
index e908e5d..5bacb4a 100644
--- a/arch/x86/crypto/Makefile
+++ b/arch/x86/crypto/Makefile
@@ -12,6 +12,8 @@ obj-$(CONFIG_CRYPTO_SERPENT_SSE2_586) += serpent-sse2-i586.o
 
 obj-$(CONFIG_CRYPTO_AES_X86_64) += aes-x86_64.o
 obj-$(CONFIG_CRYPTO_CAMELLIA_X86_64) += camellia-x86_64.o
+obj-$(CONFIG_CRYPTO_CAST5_AVX_X86_64) += cast5-avx-x86_64.o
+obj-$(CONFIG_CRYPTO_CAST6_AVX_X86_64) += cast6-avx-x86_64.o
 obj-$(CONFIG_CRYPTO_BLOWFISH_X86_64) += blowfish-x86_64.o
 obj-$(CONFIG_CRYPTO_TWOFISH_X86_64) += twofish-x86_64.o
 obj-$(CONFIG_CRYPTO_TWOFISH_X86_64_3WAY) += twofish-x86_64-3way.o
@@ -32,6 +34,8 @@ serpent-sse2-i586-y := serpent-sse2-i586-asm_32.o serpent_sse2_glue.o
 
 aes-x86_64-y := aes-x86_64-asm_64.o aes_glue.o
 camellia-x86_64-y := camellia-x86_64-asm_64.o camellia_glue.o
+cast5-avx-x86_64-y := cast5-avx-x86_64-asm_64.o cast5_avx_glue.o
+cast6-avx-x86_64-y := cast6-avx-x86_64-asm_64.o cast6_avx_glue.o
 blowfish-x86_64-y := blowfish-x86_64-asm_64.o blowfish_glue.o
 twofish-x86_64-y := twofish-x86_64-asm_64.o twofish_glue.o
 twofish-x86_64-3way-y := twofish-x86_64-asm_64-3way.o twofish_glue_3way.o
diff --git a/arch/x86/crypto/aes_glue.c b/arch/x86/crypto/aes_glue.c
index 59b37de..aafe8ce 100644
--- a/arch/x86/crypto/aes_glue.c
+++ b/arch/x86/crypto/aes_glue.c
@@ -40,7 +40,6 @@ static struct crypto_alg aes_alg = {
 	.cra_blocksize		= AES_BLOCK_SIZE,
 	.cra_ctxsize		= sizeof(struct crypto_aes_ctx),
 	.cra_module		= THIS_MODULE,
-	.cra_list		= LIST_HEAD_INIT(aes_alg.cra_list),
 	.cra_u	= {
 		.cipher	= {
 			.cia_min_keysize	= AES_MIN_KEY_SIZE,
diff --git a/arch/x86/crypto/aesni-intel_glue.c b/arch/x86/crypto/aesni-intel_glue.c
index 34fdcff..7c04d0d 100644
--- a/arch/x86/crypto/aesni-intel_glue.c
+++ b/arch/x86/crypto/aesni-intel_glue.c
@@ -28,6 +28,9 @@
 #include <crypto/aes.h>
 #include <crypto/cryptd.h>
 #include <crypto/ctr.h>
+#include <crypto/b128ops.h>
+#include <crypto/lrw.h>
+#include <crypto/xts.h>
 #include <asm/cpu_device_id.h>
 #include <asm/i387.h>
 #include <asm/crypto/aes.h>
@@ -41,18 +44,10 @@
 #define HAS_CTR
 #endif
 
-#if defined(CONFIG_CRYPTO_LRW) || defined(CONFIG_CRYPTO_LRW_MODULE)
-#define HAS_LRW
-#endif
-
 #if defined(CONFIG_CRYPTO_PCBC) || defined(CONFIG_CRYPTO_PCBC_MODULE)
 #define HAS_PCBC
 #endif
 
-#if defined(CONFIG_CRYPTO_XTS) || defined(CONFIG_CRYPTO_XTS_MODULE)
-#define HAS_XTS
-#endif
-
 /* This data is stored at the end of the crypto_tfm struct.
  * It's a type of per "session" data storage location.
  * This needs to be 16 byte aligned.
@@ -79,6 +74,16 @@ struct aesni_hash_subkey_req_data {
 #define AES_BLOCK_MASK	(~(AES_BLOCK_SIZE-1))
 #define RFC4106_HASH_SUBKEY_SIZE 16
 
+struct aesni_lrw_ctx {
+	struct lrw_table_ctx lrw_table;
+	u8 raw_aes_ctx[sizeof(struct crypto_aes_ctx) + AESNI_ALIGN - 1];
+};
+
+struct aesni_xts_ctx {
+	u8 raw_tweak_ctx[sizeof(struct crypto_aes_ctx) + AESNI_ALIGN - 1];
+	u8 raw_crypt_ctx[sizeof(struct crypto_aes_ctx) + AESNI_ALIGN - 1];
+};
+
 asmlinkage int aesni_set_key(struct crypto_aes_ctx *ctx, const u8 *in_key,
 			     unsigned int key_len);
 asmlinkage void aesni_enc(struct crypto_aes_ctx *ctx, u8 *out,
@@ -398,13 +403,6 @@ static int ablk_rfc3686_ctr_init(struct crypto_tfm *tfm)
 #endif
 #endif
 
-#ifdef HAS_LRW
-static int ablk_lrw_init(struct crypto_tfm *tfm)
-{
-	return ablk_init_common(tfm, "fpu(lrw(__driver-aes-aesni))");
-}
-#endif
-
 #ifdef HAS_PCBC
 static int ablk_pcbc_init(struct crypto_tfm *tfm)
 {
@@ -412,12 +410,160 @@ static int ablk_pcbc_init(struct crypto_tfm *tfm)
 }
 #endif
 
-#ifdef HAS_XTS
-static int ablk_xts_init(struct crypto_tfm *tfm)
+static void lrw_xts_encrypt_callback(void *ctx, u8 *blks, unsigned int nbytes)
 {
-	return ablk_init_common(tfm, "fpu(xts(__driver-aes-aesni))");
+	aesni_ecb_enc(ctx, blks, blks, nbytes);
+}
+
+static void lrw_xts_decrypt_callback(void *ctx, u8 *blks, unsigned int nbytes)
+{
+	aesni_ecb_dec(ctx, blks, blks, nbytes);
+}
+
+static int lrw_aesni_setkey(struct crypto_tfm *tfm, const u8 *key,
+			    unsigned int keylen)
+{
+	struct aesni_lrw_ctx *ctx = crypto_tfm_ctx(tfm);
+	int err;
+
+	err = aes_set_key_common(tfm, ctx->raw_aes_ctx, key,
+				 keylen - AES_BLOCK_SIZE);
+	if (err)
+		return err;
+
+	return lrw_init_table(&ctx->lrw_table, key + keylen - AES_BLOCK_SIZE);
+}
+
+static void lrw_aesni_exit_tfm(struct crypto_tfm *tfm)
+{
+	struct aesni_lrw_ctx *ctx = crypto_tfm_ctx(tfm);
+
+	lrw_free_table(&ctx->lrw_table);
+}
+
+static int lrw_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		       struct scatterlist *src, unsigned int nbytes)
+{
+	struct aesni_lrw_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	be128 buf[8];
+	struct lrw_crypt_req req = {
+		.tbuf = buf,
+		.tbuflen = sizeof(buf),
+
+		.table_ctx = &ctx->lrw_table,
+		.crypt_ctx = aes_ctx(ctx->raw_aes_ctx),
+		.crypt_fn = lrw_xts_encrypt_callback,
+	};
+	int ret;
+
+	desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
+
+	kernel_fpu_begin();
+	ret = lrw_crypt(desc, dst, src, nbytes, &req);
+	kernel_fpu_end();
+
+	return ret;
+}
+
+static int lrw_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		       struct scatterlist *src, unsigned int nbytes)
+{
+	struct aesni_lrw_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	be128 buf[8];
+	struct lrw_crypt_req req = {
+		.tbuf = buf,
+		.tbuflen = sizeof(buf),
+
+		.table_ctx = &ctx->lrw_table,
+		.crypt_ctx = aes_ctx(ctx->raw_aes_ctx),
+		.crypt_fn = lrw_xts_decrypt_callback,
+	};
+	int ret;
+
+	desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
+
+	kernel_fpu_begin();
+	ret = lrw_crypt(desc, dst, src, nbytes, &req);
+	kernel_fpu_end();
+
+	return ret;
+}
+
+static int xts_aesni_setkey(struct crypto_tfm *tfm, const u8 *key,
+			    unsigned int keylen)
+{
+	struct aesni_xts_ctx *ctx = crypto_tfm_ctx(tfm);
+	u32 *flags = &tfm->crt_flags;
+	int err;
+
+	/* key consists of keys of equal size concatenated, therefore
+	 * the length must be even
+	 */
+	if (keylen % 2) {
+		*flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+		return -EINVAL;
+	}
+
+	/* first half of xts-key is for crypt */
+	err = aes_set_key_common(tfm, ctx->raw_crypt_ctx, key, keylen / 2);
+	if (err)
+		return err;
+
+	/* second half of xts-key is for tweak */
+	return aes_set_key_common(tfm, ctx->raw_tweak_ctx, key + keylen / 2,
+				  keylen / 2);
+}
+
+
+static int xts_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		       struct scatterlist *src, unsigned int nbytes)
+{
+	struct aesni_xts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	be128 buf[8];
+	struct xts_crypt_req req = {
+		.tbuf = buf,
+		.tbuflen = sizeof(buf),
+
+		.tweak_ctx = aes_ctx(ctx->raw_tweak_ctx),
+		.tweak_fn = XTS_TWEAK_CAST(aesni_enc),
+		.crypt_ctx = aes_ctx(ctx->raw_crypt_ctx),
+		.crypt_fn = lrw_xts_encrypt_callback,
+	};
+	int ret;
+
+	desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
+
+	kernel_fpu_begin();
+	ret = xts_crypt(desc, dst, src, nbytes, &req);
+	kernel_fpu_end();
+
+	return ret;
+}
+
+static int xts_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		       struct scatterlist *src, unsigned int nbytes)
+{
+	struct aesni_xts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	be128 buf[8];
+	struct xts_crypt_req req = {
+		.tbuf = buf,
+		.tbuflen = sizeof(buf),
+
+		.tweak_ctx = aes_ctx(ctx->raw_tweak_ctx),
+		.tweak_fn = XTS_TWEAK_CAST(aesni_enc),
+		.crypt_ctx = aes_ctx(ctx->raw_crypt_ctx),
+		.crypt_fn = lrw_xts_decrypt_callback,
+	};
+	int ret;
+
+	desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
+
+	kernel_fpu_begin();
+	ret = xts_crypt(desc, dst, src, nbytes, &req);
+	kernel_fpu_end();
+
+	return ret;
 }
-#endif
 
 #ifdef CONFIG_X86_64
 static int rfc4106_init(struct crypto_tfm *tfm)
@@ -1035,10 +1181,10 @@ static struct crypto_alg aesni_algs[] = { {
 	},
 #endif
 #endif
-#ifdef HAS_LRW
+#ifdef HAS_PCBC
 }, {
-	.cra_name		= "lrw(aes)",
-	.cra_driver_name	= "lrw-aes-aesni",
+	.cra_name		= "pcbc(aes)",
+	.cra_driver_name	= "pcbc-aes-aesni",
 	.cra_priority		= 400,
 	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
 	.cra_blocksize		= AES_BLOCK_SIZE,
@@ -1046,12 +1192,12 @@ static struct crypto_alg aesni_algs[] = { {
 	.cra_alignmask		= 0,
 	.cra_type		= &crypto_ablkcipher_type,
 	.cra_module		= THIS_MODULE,
-	.cra_init		= ablk_lrw_init,
+	.cra_init		= ablk_pcbc_init,
 	.cra_exit		= ablk_exit,
 	.cra_u = {
 		.ablkcipher = {
-			.min_keysize	= AES_MIN_KEY_SIZE + AES_BLOCK_SIZE,
-			.max_keysize	= AES_MAX_KEY_SIZE + AES_BLOCK_SIZE,
+			.min_keysize	= AES_MIN_KEY_SIZE,
+			.max_keysize	= AES_MAX_KEY_SIZE,
 			.ivsize		= AES_BLOCK_SIZE,
 			.setkey		= ablk_set_key,
 			.encrypt	= ablk_encrypt,
@@ -1059,10 +1205,50 @@ static struct crypto_alg aesni_algs[] = { {
 		},
 	},
 #endif
-#ifdef HAS_PCBC
 }, {
-	.cra_name		= "pcbc(aes)",
-	.cra_driver_name	= "pcbc-aes-aesni",
+	.cra_name		= "__lrw-aes-aesni",
+	.cra_driver_name	= "__driver-lrw-aes-aesni",
+	.cra_priority		= 0,
+	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER,
+	.cra_blocksize		= AES_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct aesni_lrw_ctx),
+	.cra_alignmask		= 0,
+	.cra_type		= &crypto_blkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_exit		= lrw_aesni_exit_tfm,
+	.cra_u = {
+		.blkcipher = {
+			.min_keysize	= AES_MIN_KEY_SIZE + AES_BLOCK_SIZE,
+			.max_keysize	= AES_MAX_KEY_SIZE + AES_BLOCK_SIZE,
+			.ivsize		= AES_BLOCK_SIZE,
+			.setkey		= lrw_aesni_setkey,
+			.encrypt	= lrw_encrypt,
+			.decrypt	= lrw_decrypt,
+		},
+	},
+}, {
+	.cra_name		= "__xts-aes-aesni",
+	.cra_driver_name	= "__driver-xts-aes-aesni",
+	.cra_priority		= 0,
+	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER,
+	.cra_blocksize		= AES_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct aesni_xts_ctx),
+	.cra_alignmask		= 0,
+	.cra_type		= &crypto_blkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_u = {
+		.blkcipher = {
+			.min_keysize	= 2 * AES_MIN_KEY_SIZE,
+			.max_keysize	= 2 * AES_MAX_KEY_SIZE,
+			.ivsize		= AES_BLOCK_SIZE,
+			.setkey		= xts_aesni_setkey,
+			.encrypt	= xts_encrypt,
+			.decrypt	= xts_decrypt,
+		},
+	},
+}, {
+	.cra_name		= "lrw(aes)",
+	.cra_driver_name	= "lrw-aes-aesni",
 	.cra_priority		= 400,
 	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
 	.cra_blocksize		= AES_BLOCK_SIZE,
@@ -1070,20 +1256,18 @@ static struct crypto_alg aesni_algs[] = { {
 	.cra_alignmask		= 0,
 	.cra_type		= &crypto_ablkcipher_type,
 	.cra_module		= THIS_MODULE,
-	.cra_init		= ablk_pcbc_init,
+	.cra_init		= ablk_init,
 	.cra_exit		= ablk_exit,
 	.cra_u = {
 		.ablkcipher = {
-			.min_keysize	= AES_MIN_KEY_SIZE,
-			.max_keysize	= AES_MAX_KEY_SIZE,
+			.min_keysize	= AES_MIN_KEY_SIZE + AES_BLOCK_SIZE,
+			.max_keysize	= AES_MAX_KEY_SIZE + AES_BLOCK_SIZE,
 			.ivsize		= AES_BLOCK_SIZE,
 			.setkey		= ablk_set_key,
 			.encrypt	= ablk_encrypt,
 			.decrypt	= ablk_decrypt,
 		},
 	},
-#endif
-#ifdef HAS_XTS
 }, {
 	.cra_name		= "xts(aes)",
 	.cra_driver_name	= "xts-aes-aesni",
@@ -1094,7 +1278,7 @@ static struct crypto_alg aesni_algs[] = { {
 	.cra_alignmask		= 0,
 	.cra_type		= &crypto_ablkcipher_type,
 	.cra_module		= THIS_MODULE,
-	.cra_init		= ablk_xts_init,
+	.cra_init		= ablk_init,
 	.cra_exit		= ablk_exit,
 	.cra_u = {
 		.ablkcipher = {
@@ -1106,7 +1290,6 @@ static struct crypto_alg aesni_algs[] = { {
 			.decrypt	= ablk_decrypt,
 		},
 	},
-#endif
 } };
 
 
@@ -1118,7 +1301,7 @@ MODULE_DEVICE_TABLE(x86cpu, aesni_cpu_id);
 
 static int __init aesni_init(void)
 {
-	int err, i;
+	int err;
 
 	if (!x86_match_cpu(aesni_cpu_id))
 		return -ENODEV;
@@ -1127,9 +1310,6 @@ static int __init aesni_init(void)
 	if (err)
 		return err;
 
-	for (i = 0; i < ARRAY_SIZE(aesni_algs); i++)
-		INIT_LIST_HEAD(&aesni_algs[i].cra_list);
-
 	return crypto_register_algs(aesni_algs, ARRAY_SIZE(aesni_algs));
 }
 
diff --git a/arch/x86/crypto/blowfish_glue.c b/arch/x86/crypto/blowfish_glue.c
index 7967474..50ec333 100644
--- a/arch/x86/crypto/blowfish_glue.c
+++ b/arch/x86/crypto/blowfish_glue.c
@@ -367,7 +367,6 @@ static struct crypto_alg bf_algs[4] = { {
 	.cra_ctxsize		= sizeof(struct bf_ctx),
 	.cra_alignmask		= 0,
 	.cra_module		= THIS_MODULE,
-	.cra_list		= LIST_HEAD_INIT(bf_algs[0].cra_list),
 	.cra_u = {
 		.cipher = {
 			.cia_min_keysize	= BF_MIN_KEY_SIZE,
@@ -387,7 +386,6 @@ static struct crypto_alg bf_algs[4] = { {
 	.cra_alignmask		= 0,
 	.cra_type		= &crypto_blkcipher_type,
 	.cra_module		= THIS_MODULE,
-	.cra_list		= LIST_HEAD_INIT(bf_algs[1].cra_list),
 	.cra_u = {
 		.blkcipher = {
 			.min_keysize	= BF_MIN_KEY_SIZE,
@@ -407,7 +405,6 @@ static struct crypto_alg bf_algs[4] = { {
 	.cra_alignmask		= 0,
 	.cra_type		= &crypto_blkcipher_type,
 	.cra_module		= THIS_MODULE,
-	.cra_list		= LIST_HEAD_INIT(bf_algs[2].cra_list),
 	.cra_u = {
 		.blkcipher = {
 			.min_keysize	= BF_MIN_KEY_SIZE,
@@ -428,7 +425,6 @@ static struct crypto_alg bf_algs[4] = { {
 	.cra_alignmask		= 0,
 	.cra_type		= &crypto_blkcipher_type,
 	.cra_module		= THIS_MODULE,
-	.cra_list		= LIST_HEAD_INIT(bf_algs[3].cra_list),
 	.cra_u = {
 		.blkcipher = {
 			.min_keysize	= BF_MIN_KEY_SIZE,
diff --git a/arch/x86/crypto/camellia_glue.c b/arch/x86/crypto/camellia_glue.c
index eeb2b3b..42ffd2b 100644
--- a/arch/x86/crypto/camellia_glue.c
+++ b/arch/x86/crypto/camellia_glue.c
@@ -92,715 +92,715 @@ static void camellia_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
 
 /* camellia sboxes */
 const u64 camellia_sp10011110[256] = {
-	0x7000007070707000, 0x8200008282828200, 0x2c00002c2c2c2c00,
-	0xec0000ecececec00, 0xb30000b3b3b3b300, 0x2700002727272700,
-	0xc00000c0c0c0c000, 0xe50000e5e5e5e500, 0xe40000e4e4e4e400,
-	0x8500008585858500, 0x5700005757575700, 0x3500003535353500,
-	0xea0000eaeaeaea00, 0x0c00000c0c0c0c00, 0xae0000aeaeaeae00,
-	0x4100004141414100, 0x2300002323232300, 0xef0000efefefef00,
-	0x6b00006b6b6b6b00, 0x9300009393939300, 0x4500004545454500,
-	0x1900001919191900, 0xa50000a5a5a5a500, 0x2100002121212100,
-	0xed0000edededed00, 0x0e00000e0e0e0e00, 0x4f00004f4f4f4f00,
-	0x4e00004e4e4e4e00, 0x1d00001d1d1d1d00, 0x6500006565656500,
-	0x9200009292929200, 0xbd0000bdbdbdbd00, 0x8600008686868600,
-	0xb80000b8b8b8b800, 0xaf0000afafafaf00, 0x8f00008f8f8f8f00,
-	0x7c00007c7c7c7c00, 0xeb0000ebebebeb00, 0x1f00001f1f1f1f00,
-	0xce0000cececece00, 0x3e00003e3e3e3e00, 0x3000003030303000,
-	0xdc0000dcdcdcdc00, 0x5f00005f5f5f5f00, 0x5e00005e5e5e5e00,
-	0xc50000c5c5c5c500, 0x0b00000b0b0b0b00, 0x1a00001a1a1a1a00,
-	0xa60000a6a6a6a600, 0xe10000e1e1e1e100, 0x3900003939393900,
-	0xca0000cacacaca00, 0xd50000d5d5d5d500, 0x4700004747474700,
-	0x5d00005d5d5d5d00, 0x3d00003d3d3d3d00, 0xd90000d9d9d9d900,
-	0x0100000101010100, 0x5a00005a5a5a5a00, 0xd60000d6d6d6d600,
-	0x5100005151515100, 0x5600005656565600, 0x6c00006c6c6c6c00,
-	0x4d00004d4d4d4d00, 0x8b00008b8b8b8b00, 0x0d00000d0d0d0d00,
-	0x9a00009a9a9a9a00, 0x6600006666666600, 0xfb0000fbfbfbfb00,
-	0xcc0000cccccccc00, 0xb00000b0b0b0b000, 0x2d00002d2d2d2d00,
-	0x7400007474747400, 0x1200001212121200, 0x2b00002b2b2b2b00,
-	0x2000002020202000, 0xf00000f0f0f0f000, 0xb10000b1b1b1b100,
-	0x8400008484848400, 0x9900009999999900, 0xdf0000dfdfdfdf00,
-	0x4c00004c4c4c4c00, 0xcb0000cbcbcbcb00, 0xc20000c2c2c2c200,
-	0x3400003434343400, 0x7e00007e7e7e7e00, 0x7600007676767600,
-	0x0500000505050500, 0x6d00006d6d6d6d00, 0xb70000b7b7b7b700,
-	0xa90000a9a9a9a900, 0x3100003131313100, 0xd10000d1d1d1d100,
-	0x1700001717171700, 0x0400000404040400, 0xd70000d7d7d7d700,
-	0x1400001414141400, 0x5800005858585800, 0x3a00003a3a3a3a00,
-	0x6100006161616100, 0xde0000dededede00, 0x1b00001b1b1b1b00,
-	0x1100001111111100, 0x1c00001c1c1c1c00, 0x3200003232323200,
-	0x0f00000f0f0f0f00, 0x9c00009c9c9c9c00, 0x1600001616161600,
-	0x5300005353535300, 0x1800001818181800, 0xf20000f2f2f2f200,
-	0x2200002222222200, 0xfe0000fefefefe00, 0x4400004444444400,
-	0xcf0000cfcfcfcf00, 0xb20000b2b2b2b200, 0xc30000c3c3c3c300,
-	0xb50000b5b5b5b500, 0x7a00007a7a7a7a00, 0x9100009191919100,
-	0x2400002424242400, 0x0800000808080800, 0xe80000e8e8e8e800,
-	0xa80000a8a8a8a800, 0x6000006060606000, 0xfc0000fcfcfcfc00,
-	0x6900006969696900, 0x5000005050505000, 0xaa0000aaaaaaaa00,
-	0xd00000d0d0d0d000, 0xa00000a0a0a0a000, 0x7d00007d7d7d7d00,
-	0xa10000a1a1a1a100, 0x8900008989898900, 0x6200006262626200,
-	0x9700009797979700, 0x5400005454545400, 0x5b00005b5b5b5b00,
-	0x1e00001e1e1e1e00, 0x9500009595959500, 0xe00000e0e0e0e000,
-	0xff0000ffffffff00, 0x6400006464646400, 0xd20000d2d2d2d200,
-	0x1000001010101000, 0xc40000c4c4c4c400, 0x0000000000000000,
-	0x4800004848484800, 0xa30000a3a3a3a300, 0xf70000f7f7f7f700,
-	0x7500007575757500, 0xdb0000dbdbdbdb00, 0x8a00008a8a8a8a00,
-	0x0300000303030300, 0xe60000e6e6e6e600, 0xda0000dadadada00,
-	0x0900000909090900, 0x3f00003f3f3f3f00, 0xdd0000dddddddd00,
-	0x9400009494949400, 0x8700008787878700, 0x5c00005c5c5c5c00,
-	0x8300008383838300, 0x0200000202020200, 0xcd0000cdcdcdcd00,
-	0x4a00004a4a4a4a00, 0x9000009090909000, 0x3300003333333300,
-	0x7300007373737300, 0x6700006767676700, 0xf60000f6f6f6f600,
-	0xf30000f3f3f3f300, 0x9d00009d9d9d9d00, 0x7f00007f7f7f7f00,
-	0xbf0000bfbfbfbf00, 0xe20000e2e2e2e200, 0x5200005252525200,
-	0x9b00009b9b9b9b00, 0xd80000d8d8d8d800, 0x2600002626262600,
-	0xc80000c8c8c8c800, 0x3700003737373700, 0xc60000c6c6c6c600,
-	0x3b00003b3b3b3b00, 0x8100008181818100, 0x9600009696969600,
-	0x6f00006f6f6f6f00, 0x4b00004b4b4b4b00, 0x1300001313131300,
-	0xbe0000bebebebe00, 0x6300006363636300, 0x2e00002e2e2e2e00,
-	0xe90000e9e9e9e900, 0x7900007979797900, 0xa70000a7a7a7a700,
-	0x8c00008c8c8c8c00, 0x9f00009f9f9f9f00, 0x6e00006e6e6e6e00,
-	0xbc0000bcbcbcbc00, 0x8e00008e8e8e8e00, 0x2900002929292900,
-	0xf50000f5f5f5f500, 0xf90000f9f9f9f900, 0xb60000b6b6b6b600,
-	0x2f00002f2f2f2f00, 0xfd0000fdfdfdfd00, 0xb40000b4b4b4b400,
-	0x5900005959595900, 0x7800007878787800, 0x9800009898989800,
-	0x0600000606060600, 0x6a00006a6a6a6a00, 0xe70000e7e7e7e700,
-	0x4600004646464600, 0x7100007171717100, 0xba0000babababa00,
-	0xd40000d4d4d4d400, 0x2500002525252500, 0xab0000abababab00,
-	0x4200004242424200, 0x8800008888888800, 0xa20000a2a2a2a200,
-	0x8d00008d8d8d8d00, 0xfa0000fafafafa00, 0x7200007272727200,
-	0x0700000707070700, 0xb90000b9b9b9b900, 0x5500005555555500,
-	0xf80000f8f8f8f800, 0xee0000eeeeeeee00, 0xac0000acacacac00,
-	0x0a00000a0a0a0a00, 0x3600003636363600, 0x4900004949494900,
-	0x2a00002a2a2a2a00, 0x6800006868686800, 0x3c00003c3c3c3c00,
-	0x3800003838383800, 0xf10000f1f1f1f100, 0xa40000a4a4a4a400,
-	0x4000004040404000, 0x2800002828282800, 0xd30000d3d3d3d300,
-	0x7b00007b7b7b7b00, 0xbb0000bbbbbbbb00, 0xc90000c9c9c9c900,
-	0x4300004343434300, 0xc10000c1c1c1c100, 0x1500001515151500,
-	0xe30000e3e3e3e300, 0xad0000adadadad00, 0xf40000f4f4f4f400,
-	0x7700007777777700, 0xc70000c7c7c7c700, 0x8000008080808000,
-	0x9e00009e9e9e9e00,
+	0x7000007070707000ULL, 0x8200008282828200ULL, 0x2c00002c2c2c2c00ULL,
+	0xec0000ecececec00ULL, 0xb30000b3b3b3b300ULL, 0x2700002727272700ULL,
+	0xc00000c0c0c0c000ULL, 0xe50000e5e5e5e500ULL, 0xe40000e4e4e4e400ULL,
+	0x8500008585858500ULL, 0x5700005757575700ULL, 0x3500003535353500ULL,
+	0xea0000eaeaeaea00ULL, 0x0c00000c0c0c0c00ULL, 0xae0000aeaeaeae00ULL,
+	0x4100004141414100ULL, 0x2300002323232300ULL, 0xef0000efefefef00ULL,
+	0x6b00006b6b6b6b00ULL, 0x9300009393939300ULL, 0x4500004545454500ULL,
+	0x1900001919191900ULL, 0xa50000a5a5a5a500ULL, 0x2100002121212100ULL,
+	0xed0000edededed00ULL, 0x0e00000e0e0e0e00ULL, 0x4f00004f4f4f4f00ULL,
+	0x4e00004e4e4e4e00ULL, 0x1d00001d1d1d1d00ULL, 0x6500006565656500ULL,
+	0x9200009292929200ULL, 0xbd0000bdbdbdbd00ULL, 0x8600008686868600ULL,
+	0xb80000b8b8b8b800ULL, 0xaf0000afafafaf00ULL, 0x8f00008f8f8f8f00ULL,
+	0x7c00007c7c7c7c00ULL, 0xeb0000ebebebeb00ULL, 0x1f00001f1f1f1f00ULL,
+	0xce0000cececece00ULL, 0x3e00003e3e3e3e00ULL, 0x3000003030303000ULL,
+	0xdc0000dcdcdcdc00ULL, 0x5f00005f5f5f5f00ULL, 0x5e00005e5e5e5e00ULL,
+	0xc50000c5c5c5c500ULL, 0x0b00000b0b0b0b00ULL, 0x1a00001a1a1a1a00ULL,
+	0xa60000a6a6a6a600ULL, 0xe10000e1e1e1e100ULL, 0x3900003939393900ULL,
+	0xca0000cacacaca00ULL, 0xd50000d5d5d5d500ULL, 0x4700004747474700ULL,
+	0x5d00005d5d5d5d00ULL, 0x3d00003d3d3d3d00ULL, 0xd90000d9d9d9d900ULL,
+	0x0100000101010100ULL, 0x5a00005a5a5a5a00ULL, 0xd60000d6d6d6d600ULL,
+	0x5100005151515100ULL, 0x5600005656565600ULL, 0x6c00006c6c6c6c00ULL,
+	0x4d00004d4d4d4d00ULL, 0x8b00008b8b8b8b00ULL, 0x0d00000d0d0d0d00ULL,
+	0x9a00009a9a9a9a00ULL, 0x6600006666666600ULL, 0xfb0000fbfbfbfb00ULL,
+	0xcc0000cccccccc00ULL, 0xb00000b0b0b0b000ULL, 0x2d00002d2d2d2d00ULL,
+	0x7400007474747400ULL, 0x1200001212121200ULL, 0x2b00002b2b2b2b00ULL,
+	0x2000002020202000ULL, 0xf00000f0f0f0f000ULL, 0xb10000b1b1b1b100ULL,
+	0x8400008484848400ULL, 0x9900009999999900ULL, 0xdf0000dfdfdfdf00ULL,
+	0x4c00004c4c4c4c00ULL, 0xcb0000cbcbcbcb00ULL, 0xc20000c2c2c2c200ULL,
+	0x3400003434343400ULL, 0x7e00007e7e7e7e00ULL, 0x7600007676767600ULL,
+	0x0500000505050500ULL, 0x6d00006d6d6d6d00ULL, 0xb70000b7b7b7b700ULL,
+	0xa90000a9a9a9a900ULL, 0x3100003131313100ULL, 0xd10000d1d1d1d100ULL,
+	0x1700001717171700ULL, 0x0400000404040400ULL, 0xd70000d7d7d7d700ULL,
+	0x1400001414141400ULL, 0x5800005858585800ULL, 0x3a00003a3a3a3a00ULL,
+	0x6100006161616100ULL, 0xde0000dededede00ULL, 0x1b00001b1b1b1b00ULL,
+	0x1100001111111100ULL, 0x1c00001c1c1c1c00ULL, 0x3200003232323200ULL,
+	0x0f00000f0f0f0f00ULL, 0x9c00009c9c9c9c00ULL, 0x1600001616161600ULL,
+	0x5300005353535300ULL, 0x1800001818181800ULL, 0xf20000f2f2f2f200ULL,
+	0x2200002222222200ULL, 0xfe0000fefefefe00ULL, 0x4400004444444400ULL,
+	0xcf0000cfcfcfcf00ULL, 0xb20000b2b2b2b200ULL, 0xc30000c3c3c3c300ULL,
+	0xb50000b5b5b5b500ULL, 0x7a00007a7a7a7a00ULL, 0x9100009191919100ULL,
+	0x2400002424242400ULL, 0x0800000808080800ULL, 0xe80000e8e8e8e800ULL,
+	0xa80000a8a8a8a800ULL, 0x6000006060606000ULL, 0xfc0000fcfcfcfc00ULL,
+	0x6900006969696900ULL, 0x5000005050505000ULL, 0xaa0000aaaaaaaa00ULL,
+	0xd00000d0d0d0d000ULL, 0xa00000a0a0a0a000ULL, 0x7d00007d7d7d7d00ULL,
+	0xa10000a1a1a1a100ULL, 0x8900008989898900ULL, 0x6200006262626200ULL,
+	0x9700009797979700ULL, 0x5400005454545400ULL, 0x5b00005b5b5b5b00ULL,
+	0x1e00001e1e1e1e00ULL, 0x9500009595959500ULL, 0xe00000e0e0e0e000ULL,
+	0xff0000ffffffff00ULL, 0x6400006464646400ULL, 0xd20000d2d2d2d200ULL,
+	0x1000001010101000ULL, 0xc40000c4c4c4c400ULL, 0x0000000000000000ULL,
+	0x4800004848484800ULL, 0xa30000a3a3a3a300ULL, 0xf70000f7f7f7f700ULL,
+	0x7500007575757500ULL, 0xdb0000dbdbdbdb00ULL, 0x8a00008a8a8a8a00ULL,
+	0x0300000303030300ULL, 0xe60000e6e6e6e600ULL, 0xda0000dadadada00ULL,
+	0x0900000909090900ULL, 0x3f00003f3f3f3f00ULL, 0xdd0000dddddddd00ULL,
+	0x9400009494949400ULL, 0x8700008787878700ULL, 0x5c00005c5c5c5c00ULL,
+	0x8300008383838300ULL, 0x0200000202020200ULL, 0xcd0000cdcdcdcd00ULL,
+	0x4a00004a4a4a4a00ULL, 0x9000009090909000ULL, 0x3300003333333300ULL,
+	0x7300007373737300ULL, 0x6700006767676700ULL, 0xf60000f6f6f6f600ULL,
+	0xf30000f3f3f3f300ULL, 0x9d00009d9d9d9d00ULL, 0x7f00007f7f7f7f00ULL,
+	0xbf0000bfbfbfbf00ULL, 0xe20000e2e2e2e200ULL, 0x5200005252525200ULL,
+	0x9b00009b9b9b9b00ULL, 0xd80000d8d8d8d800ULL, 0x2600002626262600ULL,
+	0xc80000c8c8c8c800ULL, 0x3700003737373700ULL, 0xc60000c6c6c6c600ULL,
+	0x3b00003b3b3b3b00ULL, 0x8100008181818100ULL, 0x9600009696969600ULL,
+	0x6f00006f6f6f6f00ULL, 0x4b00004b4b4b4b00ULL, 0x1300001313131300ULL,
+	0xbe0000bebebebe00ULL, 0x6300006363636300ULL, 0x2e00002e2e2e2e00ULL,
+	0xe90000e9e9e9e900ULL, 0x7900007979797900ULL, 0xa70000a7a7a7a700ULL,
+	0x8c00008c8c8c8c00ULL, 0x9f00009f9f9f9f00ULL, 0x6e00006e6e6e6e00ULL,
+	0xbc0000bcbcbcbc00ULL, 0x8e00008e8e8e8e00ULL, 0x2900002929292900ULL,
+	0xf50000f5f5f5f500ULL, 0xf90000f9f9f9f900ULL, 0xb60000b6b6b6b600ULL,
+	0x2f00002f2f2f2f00ULL, 0xfd0000fdfdfdfd00ULL, 0xb40000b4b4b4b400ULL,
+	0x5900005959595900ULL, 0x7800007878787800ULL, 0x9800009898989800ULL,
+	0x0600000606060600ULL, 0x6a00006a6a6a6a00ULL, 0xe70000e7e7e7e700ULL,
+	0x4600004646464600ULL, 0x7100007171717100ULL, 0xba0000babababa00ULL,
+	0xd40000d4d4d4d400ULL, 0x2500002525252500ULL, 0xab0000abababab00ULL,
+	0x4200004242424200ULL, 0x8800008888888800ULL, 0xa20000a2a2a2a200ULL,
+	0x8d00008d8d8d8d00ULL, 0xfa0000fafafafa00ULL, 0x7200007272727200ULL,
+	0x0700000707070700ULL, 0xb90000b9b9b9b900ULL, 0x5500005555555500ULL,
+	0xf80000f8f8f8f800ULL, 0xee0000eeeeeeee00ULL, 0xac0000acacacac00ULL,
+	0x0a00000a0a0a0a00ULL, 0x3600003636363600ULL, 0x4900004949494900ULL,
+	0x2a00002a2a2a2a00ULL, 0x6800006868686800ULL, 0x3c00003c3c3c3c00ULL,
+	0x3800003838383800ULL, 0xf10000f1f1f1f100ULL, 0xa40000a4a4a4a400ULL,
+	0x4000004040404000ULL, 0x2800002828282800ULL, 0xd30000d3d3d3d300ULL,
+	0x7b00007b7b7b7b00ULL, 0xbb0000bbbbbbbb00ULL, 0xc90000c9c9c9c900ULL,
+	0x4300004343434300ULL, 0xc10000c1c1c1c100ULL, 0x1500001515151500ULL,
+	0xe30000e3e3e3e300ULL, 0xad0000adadadad00ULL, 0xf40000f4f4f4f400ULL,
+	0x7700007777777700ULL, 0xc70000c7c7c7c700ULL, 0x8000008080808000ULL,
+	0x9e00009e9e9e9e00ULL,
 };
 
 const u64 camellia_sp22000222[256] = {
-	0xe0e0000000e0e0e0, 0x0505000000050505, 0x5858000000585858,
-	0xd9d9000000d9d9d9, 0x6767000000676767, 0x4e4e0000004e4e4e,
-	0x8181000000818181, 0xcbcb000000cbcbcb, 0xc9c9000000c9c9c9,
-	0x0b0b0000000b0b0b, 0xaeae000000aeaeae, 0x6a6a0000006a6a6a,
-	0xd5d5000000d5d5d5, 0x1818000000181818, 0x5d5d0000005d5d5d,
-	0x8282000000828282, 0x4646000000464646, 0xdfdf000000dfdfdf,
-	0xd6d6000000d6d6d6, 0x2727000000272727, 0x8a8a0000008a8a8a,
-	0x3232000000323232, 0x4b4b0000004b4b4b, 0x4242000000424242,
-	0xdbdb000000dbdbdb, 0x1c1c0000001c1c1c, 0x9e9e0000009e9e9e,
-	0x9c9c0000009c9c9c, 0x3a3a0000003a3a3a, 0xcaca000000cacaca,
-	0x2525000000252525, 0x7b7b0000007b7b7b, 0x0d0d0000000d0d0d,
-	0x7171000000717171, 0x5f5f0000005f5f5f, 0x1f1f0000001f1f1f,
-	0xf8f8000000f8f8f8, 0xd7d7000000d7d7d7, 0x3e3e0000003e3e3e,
-	0x9d9d0000009d9d9d, 0x7c7c0000007c7c7c, 0x6060000000606060,
-	0xb9b9000000b9b9b9, 0xbebe000000bebebe, 0xbcbc000000bcbcbc,
-	0x8b8b0000008b8b8b, 0x1616000000161616, 0x3434000000343434,
-	0x4d4d0000004d4d4d, 0xc3c3000000c3c3c3, 0x7272000000727272,
-	0x9595000000959595, 0xabab000000ababab, 0x8e8e0000008e8e8e,
-	0xbaba000000bababa, 0x7a7a0000007a7a7a, 0xb3b3000000b3b3b3,
-	0x0202000000020202, 0xb4b4000000b4b4b4, 0xadad000000adadad,
-	0xa2a2000000a2a2a2, 0xacac000000acacac, 0xd8d8000000d8d8d8,
-	0x9a9a0000009a9a9a, 0x1717000000171717, 0x1a1a0000001a1a1a,
-	0x3535000000353535, 0xcccc000000cccccc, 0xf7f7000000f7f7f7,
-	0x9999000000999999, 0x6161000000616161, 0x5a5a0000005a5a5a,
-	0xe8e8000000e8e8e8, 0x2424000000242424, 0x5656000000565656,
-	0x4040000000404040, 0xe1e1000000e1e1e1, 0x6363000000636363,
-	0x0909000000090909, 0x3333000000333333, 0xbfbf000000bfbfbf,
-	0x9898000000989898, 0x9797000000979797, 0x8585000000858585,
-	0x6868000000686868, 0xfcfc000000fcfcfc, 0xecec000000ececec,
-	0x0a0a0000000a0a0a, 0xdada000000dadada, 0x6f6f0000006f6f6f,
-	0x5353000000535353, 0x6262000000626262, 0xa3a3000000a3a3a3,
-	0x2e2e0000002e2e2e, 0x0808000000080808, 0xafaf000000afafaf,
-	0x2828000000282828, 0xb0b0000000b0b0b0, 0x7474000000747474,
-	0xc2c2000000c2c2c2, 0xbdbd000000bdbdbd, 0x3636000000363636,
-	0x2222000000222222, 0x3838000000383838, 0x6464000000646464,
-	0x1e1e0000001e1e1e, 0x3939000000393939, 0x2c2c0000002c2c2c,
-	0xa6a6000000a6a6a6, 0x3030000000303030, 0xe5e5000000e5e5e5,
-	0x4444000000444444, 0xfdfd000000fdfdfd, 0x8888000000888888,
-	0x9f9f0000009f9f9f, 0x6565000000656565, 0x8787000000878787,
-	0x6b6b0000006b6b6b, 0xf4f4000000f4f4f4, 0x2323000000232323,
-	0x4848000000484848, 0x1010000000101010, 0xd1d1000000d1d1d1,
-	0x5151000000515151, 0xc0c0000000c0c0c0, 0xf9f9000000f9f9f9,
-	0xd2d2000000d2d2d2, 0xa0a0000000a0a0a0, 0x5555000000555555,
-	0xa1a1000000a1a1a1, 0x4141000000414141, 0xfafa000000fafafa,
-	0x4343000000434343, 0x1313000000131313, 0xc4c4000000c4c4c4,
-	0x2f2f0000002f2f2f, 0xa8a8000000a8a8a8, 0xb6b6000000b6b6b6,
-	0x3c3c0000003c3c3c, 0x2b2b0000002b2b2b, 0xc1c1000000c1c1c1,
-	0xffff000000ffffff, 0xc8c8000000c8c8c8, 0xa5a5000000a5a5a5,
-	0x2020000000202020, 0x8989000000898989, 0x0000000000000000,
-	0x9090000000909090, 0x4747000000474747, 0xefef000000efefef,
-	0xeaea000000eaeaea, 0xb7b7000000b7b7b7, 0x1515000000151515,
-	0x0606000000060606, 0xcdcd000000cdcdcd, 0xb5b5000000b5b5b5,
-	0x1212000000121212, 0x7e7e0000007e7e7e, 0xbbbb000000bbbbbb,
-	0x2929000000292929, 0x0f0f0000000f0f0f, 0xb8b8000000b8b8b8,
-	0x0707000000070707, 0x0404000000040404, 0x9b9b0000009b9b9b,
-	0x9494000000949494, 0x2121000000212121, 0x6666000000666666,
-	0xe6e6000000e6e6e6, 0xcece000000cecece, 0xeded000000ededed,
-	0xe7e7000000e7e7e7, 0x3b3b0000003b3b3b, 0xfefe000000fefefe,
-	0x7f7f0000007f7f7f, 0xc5c5000000c5c5c5, 0xa4a4000000a4a4a4,
-	0x3737000000373737, 0xb1b1000000b1b1b1, 0x4c4c0000004c4c4c,
-	0x9191000000919191, 0x6e6e0000006e6e6e, 0x8d8d0000008d8d8d,
-	0x7676000000767676, 0x0303000000030303, 0x2d2d0000002d2d2d,
-	0xdede000000dedede, 0x9696000000969696, 0x2626000000262626,
-	0x7d7d0000007d7d7d, 0xc6c6000000c6c6c6, 0x5c5c0000005c5c5c,
-	0xd3d3000000d3d3d3, 0xf2f2000000f2f2f2, 0x4f4f0000004f4f4f,
-	0x1919000000191919, 0x3f3f0000003f3f3f, 0xdcdc000000dcdcdc,
-	0x7979000000797979, 0x1d1d0000001d1d1d, 0x5252000000525252,
-	0xebeb000000ebebeb, 0xf3f3000000f3f3f3, 0x6d6d0000006d6d6d,
-	0x5e5e0000005e5e5e, 0xfbfb000000fbfbfb, 0x6969000000696969,
-	0xb2b2000000b2b2b2, 0xf0f0000000f0f0f0, 0x3131000000313131,
-	0x0c0c0000000c0c0c, 0xd4d4000000d4d4d4, 0xcfcf000000cfcfcf,
-	0x8c8c0000008c8c8c, 0xe2e2000000e2e2e2, 0x7575000000757575,
-	0xa9a9000000a9a9a9, 0x4a4a0000004a4a4a, 0x5757000000575757,
-	0x8484000000848484, 0x1111000000111111, 0x4545000000454545,
-	0x1b1b0000001b1b1b, 0xf5f5000000f5f5f5, 0xe4e4000000e4e4e4,
-	0x0e0e0000000e0e0e, 0x7373000000737373, 0xaaaa000000aaaaaa,
-	0xf1f1000000f1f1f1, 0xdddd000000dddddd, 0x5959000000595959,
-	0x1414000000141414, 0x6c6c0000006c6c6c, 0x9292000000929292,
-	0x5454000000545454, 0xd0d0000000d0d0d0, 0x7878000000787878,
-	0x7070000000707070, 0xe3e3000000e3e3e3, 0x4949000000494949,
-	0x8080000000808080, 0x5050000000505050, 0xa7a7000000a7a7a7,
-	0xf6f6000000f6f6f6, 0x7777000000777777, 0x9393000000939393,
-	0x8686000000868686, 0x8383000000838383, 0x2a2a0000002a2a2a,
-	0xc7c7000000c7c7c7, 0x5b5b0000005b5b5b, 0xe9e9000000e9e9e9,
-	0xeeee000000eeeeee, 0x8f8f0000008f8f8f, 0x0101000000010101,
-	0x3d3d0000003d3d3d,
+	0xe0e0000000e0e0e0ULL, 0x0505000000050505ULL, 0x5858000000585858ULL,
+	0xd9d9000000d9d9d9ULL, 0x6767000000676767ULL, 0x4e4e0000004e4e4eULL,
+	0x8181000000818181ULL, 0xcbcb000000cbcbcbULL, 0xc9c9000000c9c9c9ULL,
+	0x0b0b0000000b0b0bULL, 0xaeae000000aeaeaeULL, 0x6a6a0000006a6a6aULL,
+	0xd5d5000000d5d5d5ULL, 0x1818000000181818ULL, 0x5d5d0000005d5d5dULL,
+	0x8282000000828282ULL, 0x4646000000464646ULL, 0xdfdf000000dfdfdfULL,
+	0xd6d6000000d6d6d6ULL, 0x2727000000272727ULL, 0x8a8a0000008a8a8aULL,
+	0x3232000000323232ULL, 0x4b4b0000004b4b4bULL, 0x4242000000424242ULL,
+	0xdbdb000000dbdbdbULL, 0x1c1c0000001c1c1cULL, 0x9e9e0000009e9e9eULL,
+	0x9c9c0000009c9c9cULL, 0x3a3a0000003a3a3aULL, 0xcaca000000cacacaULL,
+	0x2525000000252525ULL, 0x7b7b0000007b7b7bULL, 0x0d0d0000000d0d0dULL,
+	0x7171000000717171ULL, 0x5f5f0000005f5f5fULL, 0x1f1f0000001f1f1fULL,
+	0xf8f8000000f8f8f8ULL, 0xd7d7000000d7d7d7ULL, 0x3e3e0000003e3e3eULL,
+	0x9d9d0000009d9d9dULL, 0x7c7c0000007c7c7cULL, 0x6060000000606060ULL,
+	0xb9b9000000b9b9b9ULL, 0xbebe000000bebebeULL, 0xbcbc000000bcbcbcULL,
+	0x8b8b0000008b8b8bULL, 0x1616000000161616ULL, 0x3434000000343434ULL,
+	0x4d4d0000004d4d4dULL, 0xc3c3000000c3c3c3ULL, 0x7272000000727272ULL,
+	0x9595000000959595ULL, 0xabab000000abababULL, 0x8e8e0000008e8e8eULL,
+	0xbaba000000bababaULL, 0x7a7a0000007a7a7aULL, 0xb3b3000000b3b3b3ULL,
+	0x0202000000020202ULL, 0xb4b4000000b4b4b4ULL, 0xadad000000adadadULL,
+	0xa2a2000000a2a2a2ULL, 0xacac000000acacacULL, 0xd8d8000000d8d8d8ULL,
+	0x9a9a0000009a9a9aULL, 0x1717000000171717ULL, 0x1a1a0000001a1a1aULL,
+	0x3535000000353535ULL, 0xcccc000000ccccccULL, 0xf7f7000000f7f7f7ULL,
+	0x9999000000999999ULL, 0x6161000000616161ULL, 0x5a5a0000005a5a5aULL,
+	0xe8e8000000e8e8e8ULL, 0x2424000000242424ULL, 0x5656000000565656ULL,
+	0x4040000000404040ULL, 0xe1e1000000e1e1e1ULL, 0x6363000000636363ULL,
+	0x0909000000090909ULL, 0x3333000000333333ULL, 0xbfbf000000bfbfbfULL,
+	0x9898000000989898ULL, 0x9797000000979797ULL, 0x8585000000858585ULL,
+	0x6868000000686868ULL, 0xfcfc000000fcfcfcULL, 0xecec000000ecececULL,
+	0x0a0a0000000a0a0aULL, 0xdada000000dadadaULL, 0x6f6f0000006f6f6fULL,
+	0x5353000000535353ULL, 0x6262000000626262ULL, 0xa3a3000000a3a3a3ULL,
+	0x2e2e0000002e2e2eULL, 0x0808000000080808ULL, 0xafaf000000afafafULL,
+	0x2828000000282828ULL, 0xb0b0000000b0b0b0ULL, 0x7474000000747474ULL,
+	0xc2c2000000c2c2c2ULL, 0xbdbd000000bdbdbdULL, 0x3636000000363636ULL,
+	0x2222000000222222ULL, 0x3838000000383838ULL, 0x6464000000646464ULL,
+	0x1e1e0000001e1e1eULL, 0x3939000000393939ULL, 0x2c2c0000002c2c2cULL,
+	0xa6a6000000a6a6a6ULL, 0x3030000000303030ULL, 0xe5e5000000e5e5e5ULL,
+	0x4444000000444444ULL, 0xfdfd000000fdfdfdULL, 0x8888000000888888ULL,
+	0x9f9f0000009f9f9fULL, 0x6565000000656565ULL, 0x8787000000878787ULL,
+	0x6b6b0000006b6b6bULL, 0xf4f4000000f4f4f4ULL, 0x2323000000232323ULL,
+	0x4848000000484848ULL, 0x1010000000101010ULL, 0xd1d1000000d1d1d1ULL,
+	0x5151000000515151ULL, 0xc0c0000000c0c0c0ULL, 0xf9f9000000f9f9f9ULL,
+	0xd2d2000000d2d2d2ULL, 0xa0a0000000a0a0a0ULL, 0x5555000000555555ULL,
+	0xa1a1000000a1a1a1ULL, 0x4141000000414141ULL, 0xfafa000000fafafaULL,
+	0x4343000000434343ULL, 0x1313000000131313ULL, 0xc4c4000000c4c4c4ULL,
+	0x2f2f0000002f2f2fULL, 0xa8a8000000a8a8a8ULL, 0xb6b6000000b6b6b6ULL,
+	0x3c3c0000003c3c3cULL, 0x2b2b0000002b2b2bULL, 0xc1c1000000c1c1c1ULL,
+	0xffff000000ffffffULL, 0xc8c8000000c8c8c8ULL, 0xa5a5000000a5a5a5ULL,
+	0x2020000000202020ULL, 0x8989000000898989ULL, 0x0000000000000000ULL,
+	0x9090000000909090ULL, 0x4747000000474747ULL, 0xefef000000efefefULL,
+	0xeaea000000eaeaeaULL, 0xb7b7000000b7b7b7ULL, 0x1515000000151515ULL,
+	0x0606000000060606ULL, 0xcdcd000000cdcdcdULL, 0xb5b5000000b5b5b5ULL,
+	0x1212000000121212ULL, 0x7e7e0000007e7e7eULL, 0xbbbb000000bbbbbbULL,
+	0x2929000000292929ULL, 0x0f0f0000000f0f0fULL, 0xb8b8000000b8b8b8ULL,
+	0x0707000000070707ULL, 0x0404000000040404ULL, 0x9b9b0000009b9b9bULL,
+	0x9494000000949494ULL, 0x2121000000212121ULL, 0x6666000000666666ULL,
+	0xe6e6000000e6e6e6ULL, 0xcece000000cececeULL, 0xeded000000edededULL,
+	0xe7e7000000e7e7e7ULL, 0x3b3b0000003b3b3bULL, 0xfefe000000fefefeULL,
+	0x7f7f0000007f7f7fULL, 0xc5c5000000c5c5c5ULL, 0xa4a4000000a4a4a4ULL,
+	0x3737000000373737ULL, 0xb1b1000000b1b1b1ULL, 0x4c4c0000004c4c4cULL,
+	0x9191000000919191ULL, 0x6e6e0000006e6e6eULL, 0x8d8d0000008d8d8dULL,
+	0x7676000000767676ULL, 0x0303000000030303ULL, 0x2d2d0000002d2d2dULL,
+	0xdede000000dededeULL, 0x9696000000969696ULL, 0x2626000000262626ULL,
+	0x7d7d0000007d7d7dULL, 0xc6c6000000c6c6c6ULL, 0x5c5c0000005c5c5cULL,
+	0xd3d3000000d3d3d3ULL, 0xf2f2000000f2f2f2ULL, 0x4f4f0000004f4f4fULL,
+	0x1919000000191919ULL, 0x3f3f0000003f3f3fULL, 0xdcdc000000dcdcdcULL,
+	0x7979000000797979ULL, 0x1d1d0000001d1d1dULL, 0x5252000000525252ULL,
+	0xebeb000000ebebebULL, 0xf3f3000000f3f3f3ULL, 0x6d6d0000006d6d6dULL,
+	0x5e5e0000005e5e5eULL, 0xfbfb000000fbfbfbULL, 0x6969000000696969ULL,
+	0xb2b2000000b2b2b2ULL, 0xf0f0000000f0f0f0ULL, 0x3131000000313131ULL,
+	0x0c0c0000000c0c0cULL, 0xd4d4000000d4d4d4ULL, 0xcfcf000000cfcfcfULL,
+	0x8c8c0000008c8c8cULL, 0xe2e2000000e2e2e2ULL, 0x7575000000757575ULL,
+	0xa9a9000000a9a9a9ULL, 0x4a4a0000004a4a4aULL, 0x5757000000575757ULL,
+	0x8484000000848484ULL, 0x1111000000111111ULL, 0x4545000000454545ULL,
+	0x1b1b0000001b1b1bULL, 0xf5f5000000f5f5f5ULL, 0xe4e4000000e4e4e4ULL,
+	0x0e0e0000000e0e0eULL, 0x7373000000737373ULL, 0xaaaa000000aaaaaaULL,
+	0xf1f1000000f1f1f1ULL, 0xdddd000000ddddddULL, 0x5959000000595959ULL,
+	0x1414000000141414ULL, 0x6c6c0000006c6c6cULL, 0x9292000000929292ULL,
+	0x5454000000545454ULL, 0xd0d0000000d0d0d0ULL, 0x7878000000787878ULL,
+	0x7070000000707070ULL, 0xe3e3000000e3e3e3ULL, 0x4949000000494949ULL,
+	0x8080000000808080ULL, 0x5050000000505050ULL, 0xa7a7000000a7a7a7ULL,
+	0xf6f6000000f6f6f6ULL, 0x7777000000777777ULL, 0x9393000000939393ULL,
+	0x8686000000868686ULL, 0x8383000000838383ULL, 0x2a2a0000002a2a2aULL,
+	0xc7c7000000c7c7c7ULL, 0x5b5b0000005b5b5bULL, 0xe9e9000000e9e9e9ULL,
+	0xeeee000000eeeeeeULL, 0x8f8f0000008f8f8fULL, 0x0101000000010101ULL,
+	0x3d3d0000003d3d3dULL,
 };
 
 const u64 camellia_sp03303033[256] = {
-	0x0038380038003838, 0x0041410041004141, 0x0016160016001616,
-	0x0076760076007676, 0x00d9d900d900d9d9, 0x0093930093009393,
-	0x0060600060006060, 0x00f2f200f200f2f2, 0x0072720072007272,
-	0x00c2c200c200c2c2, 0x00abab00ab00abab, 0x009a9a009a009a9a,
-	0x0075750075007575, 0x0006060006000606, 0x0057570057005757,
-	0x00a0a000a000a0a0, 0x0091910091009191, 0x00f7f700f700f7f7,
-	0x00b5b500b500b5b5, 0x00c9c900c900c9c9, 0x00a2a200a200a2a2,
-	0x008c8c008c008c8c, 0x00d2d200d200d2d2, 0x0090900090009090,
-	0x00f6f600f600f6f6, 0x0007070007000707, 0x00a7a700a700a7a7,
-	0x0027270027002727, 0x008e8e008e008e8e, 0x00b2b200b200b2b2,
-	0x0049490049004949, 0x00dede00de00dede, 0x0043430043004343,
-	0x005c5c005c005c5c, 0x00d7d700d700d7d7, 0x00c7c700c700c7c7,
-	0x003e3e003e003e3e, 0x00f5f500f500f5f5, 0x008f8f008f008f8f,
-	0x0067670067006767, 0x001f1f001f001f1f, 0x0018180018001818,
-	0x006e6e006e006e6e, 0x00afaf00af00afaf, 0x002f2f002f002f2f,
-	0x00e2e200e200e2e2, 0x0085850085008585, 0x000d0d000d000d0d,
-	0x0053530053005353, 0x00f0f000f000f0f0, 0x009c9c009c009c9c,
-	0x0065650065006565, 0x00eaea00ea00eaea, 0x00a3a300a300a3a3,
-	0x00aeae00ae00aeae, 0x009e9e009e009e9e, 0x00ecec00ec00ecec,
-	0x0080800080008080, 0x002d2d002d002d2d, 0x006b6b006b006b6b,
-	0x00a8a800a800a8a8, 0x002b2b002b002b2b, 0x0036360036003636,
-	0x00a6a600a600a6a6, 0x00c5c500c500c5c5, 0x0086860086008686,
-	0x004d4d004d004d4d, 0x0033330033003333, 0x00fdfd00fd00fdfd,
-	0x0066660066006666, 0x0058580058005858, 0x0096960096009696,
-	0x003a3a003a003a3a, 0x0009090009000909, 0x0095950095009595,
-	0x0010100010001010, 0x0078780078007878, 0x00d8d800d800d8d8,
-	0x0042420042004242, 0x00cccc00cc00cccc, 0x00efef00ef00efef,
-	0x0026260026002626, 0x00e5e500e500e5e5, 0x0061610061006161,
-	0x001a1a001a001a1a, 0x003f3f003f003f3f, 0x003b3b003b003b3b,
-	0x0082820082008282, 0x00b6b600b600b6b6, 0x00dbdb00db00dbdb,
-	0x00d4d400d400d4d4, 0x0098980098009898, 0x00e8e800e800e8e8,
-	0x008b8b008b008b8b, 0x0002020002000202, 0x00ebeb00eb00ebeb,
-	0x000a0a000a000a0a, 0x002c2c002c002c2c, 0x001d1d001d001d1d,
-	0x00b0b000b000b0b0, 0x006f6f006f006f6f, 0x008d8d008d008d8d,
-	0x0088880088008888, 0x000e0e000e000e0e, 0x0019190019001919,
-	0x0087870087008787, 0x004e4e004e004e4e, 0x000b0b000b000b0b,
-	0x00a9a900a900a9a9, 0x000c0c000c000c0c, 0x0079790079007979,
-	0x0011110011001111, 0x007f7f007f007f7f, 0x0022220022002222,
-	0x00e7e700e700e7e7, 0x0059590059005959, 0x00e1e100e100e1e1,
-	0x00dada00da00dada, 0x003d3d003d003d3d, 0x00c8c800c800c8c8,
-	0x0012120012001212, 0x0004040004000404, 0x0074740074007474,
-	0x0054540054005454, 0x0030300030003030, 0x007e7e007e007e7e,
-	0x00b4b400b400b4b4, 0x0028280028002828, 0x0055550055005555,
-	0x0068680068006868, 0x0050500050005050, 0x00bebe00be00bebe,
-	0x00d0d000d000d0d0, 0x00c4c400c400c4c4, 0x0031310031003131,
-	0x00cbcb00cb00cbcb, 0x002a2a002a002a2a, 0x00adad00ad00adad,
-	0x000f0f000f000f0f, 0x00caca00ca00caca, 0x0070700070007070,
-	0x00ffff00ff00ffff, 0x0032320032003232, 0x0069690069006969,
-	0x0008080008000808, 0x0062620062006262, 0x0000000000000000,
-	0x0024240024002424, 0x00d1d100d100d1d1, 0x00fbfb00fb00fbfb,
-	0x00baba00ba00baba, 0x00eded00ed00eded, 0x0045450045004545,
-	0x0081810081008181, 0x0073730073007373, 0x006d6d006d006d6d,
-	0x0084840084008484, 0x009f9f009f009f9f, 0x00eeee00ee00eeee,
-	0x004a4a004a004a4a, 0x00c3c300c300c3c3, 0x002e2e002e002e2e,
-	0x00c1c100c100c1c1, 0x0001010001000101, 0x00e6e600e600e6e6,
-	0x0025250025002525, 0x0048480048004848, 0x0099990099009999,
-	0x00b9b900b900b9b9, 0x00b3b300b300b3b3, 0x007b7b007b007b7b,
-	0x00f9f900f900f9f9, 0x00cece00ce00cece, 0x00bfbf00bf00bfbf,
-	0x00dfdf00df00dfdf, 0x0071710071007171, 0x0029290029002929,
-	0x00cdcd00cd00cdcd, 0x006c6c006c006c6c, 0x0013130013001313,
-	0x0064640064006464, 0x009b9b009b009b9b, 0x0063630063006363,
-	0x009d9d009d009d9d, 0x00c0c000c000c0c0, 0x004b4b004b004b4b,
-	0x00b7b700b700b7b7, 0x00a5a500a500a5a5, 0x0089890089008989,
-	0x005f5f005f005f5f, 0x00b1b100b100b1b1, 0x0017170017001717,
-	0x00f4f400f400f4f4, 0x00bcbc00bc00bcbc, 0x00d3d300d300d3d3,
-	0x0046460046004646, 0x00cfcf00cf00cfcf, 0x0037370037003737,
-	0x005e5e005e005e5e, 0x0047470047004747, 0x0094940094009494,
-	0x00fafa00fa00fafa, 0x00fcfc00fc00fcfc, 0x005b5b005b005b5b,
-	0x0097970097009797, 0x00fefe00fe00fefe, 0x005a5a005a005a5a,
-	0x00acac00ac00acac, 0x003c3c003c003c3c, 0x004c4c004c004c4c,
-	0x0003030003000303, 0x0035350035003535, 0x00f3f300f300f3f3,
-	0x0023230023002323, 0x00b8b800b800b8b8, 0x005d5d005d005d5d,
-	0x006a6a006a006a6a, 0x0092920092009292, 0x00d5d500d500d5d5,
-	0x0021210021002121, 0x0044440044004444, 0x0051510051005151,
-	0x00c6c600c600c6c6, 0x007d7d007d007d7d, 0x0039390039003939,
-	0x0083830083008383, 0x00dcdc00dc00dcdc, 0x00aaaa00aa00aaaa,
-	0x007c7c007c007c7c, 0x0077770077007777, 0x0056560056005656,
-	0x0005050005000505, 0x001b1b001b001b1b, 0x00a4a400a400a4a4,
-	0x0015150015001515, 0x0034340034003434, 0x001e1e001e001e1e,
-	0x001c1c001c001c1c, 0x00f8f800f800f8f8, 0x0052520052005252,
-	0x0020200020002020, 0x0014140014001414, 0x00e9e900e900e9e9,
-	0x00bdbd00bd00bdbd, 0x00dddd00dd00dddd, 0x00e4e400e400e4e4,
-	0x00a1a100a100a1a1, 0x00e0e000e000e0e0, 0x008a8a008a008a8a,
-	0x00f1f100f100f1f1, 0x00d6d600d600d6d6, 0x007a7a007a007a7a,
-	0x00bbbb00bb00bbbb, 0x00e3e300e300e3e3, 0x0040400040004040,
-	0x004f4f004f004f4f,
+	0x0038380038003838ULL, 0x0041410041004141ULL, 0x0016160016001616ULL,
+	0x0076760076007676ULL, 0x00d9d900d900d9d9ULL, 0x0093930093009393ULL,
+	0x0060600060006060ULL, 0x00f2f200f200f2f2ULL, 0x0072720072007272ULL,
+	0x00c2c200c200c2c2ULL, 0x00abab00ab00ababULL, 0x009a9a009a009a9aULL,
+	0x0075750075007575ULL, 0x0006060006000606ULL, 0x0057570057005757ULL,
+	0x00a0a000a000a0a0ULL, 0x0091910091009191ULL, 0x00f7f700f700f7f7ULL,
+	0x00b5b500b500b5b5ULL, 0x00c9c900c900c9c9ULL, 0x00a2a200a200a2a2ULL,
+	0x008c8c008c008c8cULL, 0x00d2d200d200d2d2ULL, 0x0090900090009090ULL,
+	0x00f6f600f600f6f6ULL, 0x0007070007000707ULL, 0x00a7a700a700a7a7ULL,
+	0x0027270027002727ULL, 0x008e8e008e008e8eULL, 0x00b2b200b200b2b2ULL,
+	0x0049490049004949ULL, 0x00dede00de00dedeULL, 0x0043430043004343ULL,
+	0x005c5c005c005c5cULL, 0x00d7d700d700d7d7ULL, 0x00c7c700c700c7c7ULL,
+	0x003e3e003e003e3eULL, 0x00f5f500f500f5f5ULL, 0x008f8f008f008f8fULL,
+	0x0067670067006767ULL, 0x001f1f001f001f1fULL, 0x0018180018001818ULL,
+	0x006e6e006e006e6eULL, 0x00afaf00af00afafULL, 0x002f2f002f002f2fULL,
+	0x00e2e200e200e2e2ULL, 0x0085850085008585ULL, 0x000d0d000d000d0dULL,
+	0x0053530053005353ULL, 0x00f0f000f000f0f0ULL, 0x009c9c009c009c9cULL,
+	0x0065650065006565ULL, 0x00eaea00ea00eaeaULL, 0x00a3a300a300a3a3ULL,
+	0x00aeae00ae00aeaeULL, 0x009e9e009e009e9eULL, 0x00ecec00ec00ececULL,
+	0x0080800080008080ULL, 0x002d2d002d002d2dULL, 0x006b6b006b006b6bULL,
+	0x00a8a800a800a8a8ULL, 0x002b2b002b002b2bULL, 0x0036360036003636ULL,
+	0x00a6a600a600a6a6ULL, 0x00c5c500c500c5c5ULL, 0x0086860086008686ULL,
+	0x004d4d004d004d4dULL, 0x0033330033003333ULL, 0x00fdfd00fd00fdfdULL,
+	0x0066660066006666ULL, 0x0058580058005858ULL, 0x0096960096009696ULL,
+	0x003a3a003a003a3aULL, 0x0009090009000909ULL, 0x0095950095009595ULL,
+	0x0010100010001010ULL, 0x0078780078007878ULL, 0x00d8d800d800d8d8ULL,
+	0x0042420042004242ULL, 0x00cccc00cc00ccccULL, 0x00efef00ef00efefULL,
+	0x0026260026002626ULL, 0x00e5e500e500e5e5ULL, 0x0061610061006161ULL,
+	0x001a1a001a001a1aULL, 0x003f3f003f003f3fULL, 0x003b3b003b003b3bULL,
+	0x0082820082008282ULL, 0x00b6b600b600b6b6ULL, 0x00dbdb00db00dbdbULL,
+	0x00d4d400d400d4d4ULL, 0x0098980098009898ULL, 0x00e8e800e800e8e8ULL,
+	0x008b8b008b008b8bULL, 0x0002020002000202ULL, 0x00ebeb00eb00ebebULL,
+	0x000a0a000a000a0aULL, 0x002c2c002c002c2cULL, 0x001d1d001d001d1dULL,
+	0x00b0b000b000b0b0ULL, 0x006f6f006f006f6fULL, 0x008d8d008d008d8dULL,
+	0x0088880088008888ULL, 0x000e0e000e000e0eULL, 0x0019190019001919ULL,
+	0x0087870087008787ULL, 0x004e4e004e004e4eULL, 0x000b0b000b000b0bULL,
+	0x00a9a900a900a9a9ULL, 0x000c0c000c000c0cULL, 0x0079790079007979ULL,
+	0x0011110011001111ULL, 0x007f7f007f007f7fULL, 0x0022220022002222ULL,
+	0x00e7e700e700e7e7ULL, 0x0059590059005959ULL, 0x00e1e100e100e1e1ULL,
+	0x00dada00da00dadaULL, 0x003d3d003d003d3dULL, 0x00c8c800c800c8c8ULL,
+	0x0012120012001212ULL, 0x0004040004000404ULL, 0x0074740074007474ULL,
+	0x0054540054005454ULL, 0x0030300030003030ULL, 0x007e7e007e007e7eULL,
+	0x00b4b400b400b4b4ULL, 0x0028280028002828ULL, 0x0055550055005555ULL,
+	0x0068680068006868ULL, 0x0050500050005050ULL, 0x00bebe00be00bebeULL,
+	0x00d0d000d000d0d0ULL, 0x00c4c400c400c4c4ULL, 0x0031310031003131ULL,
+	0x00cbcb00cb00cbcbULL, 0x002a2a002a002a2aULL, 0x00adad00ad00adadULL,
+	0x000f0f000f000f0fULL, 0x00caca00ca00cacaULL, 0x0070700070007070ULL,
+	0x00ffff00ff00ffffULL, 0x0032320032003232ULL, 0x0069690069006969ULL,
+	0x0008080008000808ULL, 0x0062620062006262ULL, 0x0000000000000000ULL,
+	0x0024240024002424ULL, 0x00d1d100d100d1d1ULL, 0x00fbfb00fb00fbfbULL,
+	0x00baba00ba00babaULL, 0x00eded00ed00ededULL, 0x0045450045004545ULL,
+	0x0081810081008181ULL, 0x0073730073007373ULL, 0x006d6d006d006d6dULL,
+	0x0084840084008484ULL, 0x009f9f009f009f9fULL, 0x00eeee00ee00eeeeULL,
+	0x004a4a004a004a4aULL, 0x00c3c300c300c3c3ULL, 0x002e2e002e002e2eULL,
+	0x00c1c100c100c1c1ULL, 0x0001010001000101ULL, 0x00e6e600e600e6e6ULL,
+	0x0025250025002525ULL, 0x0048480048004848ULL, 0x0099990099009999ULL,
+	0x00b9b900b900b9b9ULL, 0x00b3b300b300b3b3ULL, 0x007b7b007b007b7bULL,
+	0x00f9f900f900f9f9ULL, 0x00cece00ce00ceceULL, 0x00bfbf00bf00bfbfULL,
+	0x00dfdf00df00dfdfULL, 0x0071710071007171ULL, 0x0029290029002929ULL,
+	0x00cdcd00cd00cdcdULL, 0x006c6c006c006c6cULL, 0x0013130013001313ULL,
+	0x0064640064006464ULL, 0x009b9b009b009b9bULL, 0x0063630063006363ULL,
+	0x009d9d009d009d9dULL, 0x00c0c000c000c0c0ULL, 0x004b4b004b004b4bULL,
+	0x00b7b700b700b7b7ULL, 0x00a5a500a500a5a5ULL, 0x0089890089008989ULL,
+	0x005f5f005f005f5fULL, 0x00b1b100b100b1b1ULL, 0x0017170017001717ULL,
+	0x00f4f400f400f4f4ULL, 0x00bcbc00bc00bcbcULL, 0x00d3d300d300d3d3ULL,
+	0x0046460046004646ULL, 0x00cfcf00cf00cfcfULL, 0x0037370037003737ULL,
+	0x005e5e005e005e5eULL, 0x0047470047004747ULL, 0x0094940094009494ULL,
+	0x00fafa00fa00fafaULL, 0x00fcfc00fc00fcfcULL, 0x005b5b005b005b5bULL,
+	0x0097970097009797ULL, 0x00fefe00fe00fefeULL, 0x005a5a005a005a5aULL,
+	0x00acac00ac00acacULL, 0x003c3c003c003c3cULL, 0x004c4c004c004c4cULL,
+	0x0003030003000303ULL, 0x0035350035003535ULL, 0x00f3f300f300f3f3ULL,
+	0x0023230023002323ULL, 0x00b8b800b800b8b8ULL, 0x005d5d005d005d5dULL,
+	0x006a6a006a006a6aULL, 0x0092920092009292ULL, 0x00d5d500d500d5d5ULL,
+	0x0021210021002121ULL, 0x0044440044004444ULL, 0x0051510051005151ULL,
+	0x00c6c600c600c6c6ULL, 0x007d7d007d007d7dULL, 0x0039390039003939ULL,
+	0x0083830083008383ULL, 0x00dcdc00dc00dcdcULL, 0x00aaaa00aa00aaaaULL,
+	0x007c7c007c007c7cULL, 0x0077770077007777ULL, 0x0056560056005656ULL,
+	0x0005050005000505ULL, 0x001b1b001b001b1bULL, 0x00a4a400a400a4a4ULL,
+	0x0015150015001515ULL, 0x0034340034003434ULL, 0x001e1e001e001e1eULL,
+	0x001c1c001c001c1cULL, 0x00f8f800f800f8f8ULL, 0x0052520052005252ULL,
+	0x0020200020002020ULL, 0x0014140014001414ULL, 0x00e9e900e900e9e9ULL,
+	0x00bdbd00bd00bdbdULL, 0x00dddd00dd00ddddULL, 0x00e4e400e400e4e4ULL,
+	0x00a1a100a100a1a1ULL, 0x00e0e000e000e0e0ULL, 0x008a8a008a008a8aULL,
+	0x00f1f100f100f1f1ULL, 0x00d6d600d600d6d6ULL, 0x007a7a007a007a7aULL,
+	0x00bbbb00bb00bbbbULL, 0x00e3e300e300e3e3ULL, 0x0040400040004040ULL,
+	0x004f4f004f004f4fULL,
 };
 
 const u64 camellia_sp00444404[256] = {
-	0x0000707070700070, 0x00002c2c2c2c002c, 0x0000b3b3b3b300b3,
-	0x0000c0c0c0c000c0, 0x0000e4e4e4e400e4, 0x0000575757570057,
-	0x0000eaeaeaea00ea, 0x0000aeaeaeae00ae, 0x0000232323230023,
-	0x00006b6b6b6b006b, 0x0000454545450045, 0x0000a5a5a5a500a5,
-	0x0000edededed00ed, 0x00004f4f4f4f004f, 0x00001d1d1d1d001d,
-	0x0000929292920092, 0x0000868686860086, 0x0000afafafaf00af,
-	0x00007c7c7c7c007c, 0x00001f1f1f1f001f, 0x00003e3e3e3e003e,
-	0x0000dcdcdcdc00dc, 0x00005e5e5e5e005e, 0x00000b0b0b0b000b,
-	0x0000a6a6a6a600a6, 0x0000393939390039, 0x0000d5d5d5d500d5,
-	0x00005d5d5d5d005d, 0x0000d9d9d9d900d9, 0x00005a5a5a5a005a,
-	0x0000515151510051, 0x00006c6c6c6c006c, 0x00008b8b8b8b008b,
-	0x00009a9a9a9a009a, 0x0000fbfbfbfb00fb, 0x0000b0b0b0b000b0,
-	0x0000747474740074, 0x00002b2b2b2b002b, 0x0000f0f0f0f000f0,
-	0x0000848484840084, 0x0000dfdfdfdf00df, 0x0000cbcbcbcb00cb,
-	0x0000343434340034, 0x0000767676760076, 0x00006d6d6d6d006d,
-	0x0000a9a9a9a900a9, 0x0000d1d1d1d100d1, 0x0000040404040004,
-	0x0000141414140014, 0x00003a3a3a3a003a, 0x0000dededede00de,
-	0x0000111111110011, 0x0000323232320032, 0x00009c9c9c9c009c,
-	0x0000535353530053, 0x0000f2f2f2f200f2, 0x0000fefefefe00fe,
-	0x0000cfcfcfcf00cf, 0x0000c3c3c3c300c3, 0x00007a7a7a7a007a,
-	0x0000242424240024, 0x0000e8e8e8e800e8, 0x0000606060600060,
-	0x0000696969690069, 0x0000aaaaaaaa00aa, 0x0000a0a0a0a000a0,
-	0x0000a1a1a1a100a1, 0x0000626262620062, 0x0000545454540054,
-	0x00001e1e1e1e001e, 0x0000e0e0e0e000e0, 0x0000646464640064,
-	0x0000101010100010, 0x0000000000000000, 0x0000a3a3a3a300a3,
-	0x0000757575750075, 0x00008a8a8a8a008a, 0x0000e6e6e6e600e6,
-	0x0000090909090009, 0x0000dddddddd00dd, 0x0000878787870087,
-	0x0000838383830083, 0x0000cdcdcdcd00cd, 0x0000909090900090,
-	0x0000737373730073, 0x0000f6f6f6f600f6, 0x00009d9d9d9d009d,
-	0x0000bfbfbfbf00bf, 0x0000525252520052, 0x0000d8d8d8d800d8,
-	0x0000c8c8c8c800c8, 0x0000c6c6c6c600c6, 0x0000818181810081,
-	0x00006f6f6f6f006f, 0x0000131313130013, 0x0000636363630063,
-	0x0000e9e9e9e900e9, 0x0000a7a7a7a700a7, 0x00009f9f9f9f009f,
-	0x0000bcbcbcbc00bc, 0x0000292929290029, 0x0000f9f9f9f900f9,
-	0x00002f2f2f2f002f, 0x0000b4b4b4b400b4, 0x0000787878780078,
-	0x0000060606060006, 0x0000e7e7e7e700e7, 0x0000717171710071,
-	0x0000d4d4d4d400d4, 0x0000abababab00ab, 0x0000888888880088,
-	0x00008d8d8d8d008d, 0x0000727272720072, 0x0000b9b9b9b900b9,
-	0x0000f8f8f8f800f8, 0x0000acacacac00ac, 0x0000363636360036,
-	0x00002a2a2a2a002a, 0x00003c3c3c3c003c, 0x0000f1f1f1f100f1,
-	0x0000404040400040, 0x0000d3d3d3d300d3, 0x0000bbbbbbbb00bb,
-	0x0000434343430043, 0x0000151515150015, 0x0000adadadad00ad,
-	0x0000777777770077, 0x0000808080800080, 0x0000828282820082,
-	0x0000ecececec00ec, 0x0000272727270027, 0x0000e5e5e5e500e5,
-	0x0000858585850085, 0x0000353535350035, 0x00000c0c0c0c000c,
-	0x0000414141410041, 0x0000efefefef00ef, 0x0000939393930093,
-	0x0000191919190019, 0x0000212121210021, 0x00000e0e0e0e000e,
-	0x00004e4e4e4e004e, 0x0000656565650065, 0x0000bdbdbdbd00bd,
-	0x0000b8b8b8b800b8, 0x00008f8f8f8f008f, 0x0000ebebebeb00eb,
-	0x0000cececece00ce, 0x0000303030300030, 0x00005f5f5f5f005f,
-	0x0000c5c5c5c500c5, 0x00001a1a1a1a001a, 0x0000e1e1e1e100e1,
-	0x0000cacacaca00ca, 0x0000474747470047, 0x00003d3d3d3d003d,
-	0x0000010101010001, 0x0000d6d6d6d600d6, 0x0000565656560056,
-	0x00004d4d4d4d004d, 0x00000d0d0d0d000d, 0x0000666666660066,
-	0x0000cccccccc00cc, 0x00002d2d2d2d002d, 0x0000121212120012,
-	0x0000202020200020, 0x0000b1b1b1b100b1, 0x0000999999990099,
-	0x00004c4c4c4c004c, 0x0000c2c2c2c200c2, 0x00007e7e7e7e007e,
-	0x0000050505050005, 0x0000b7b7b7b700b7, 0x0000313131310031,
-	0x0000171717170017, 0x0000d7d7d7d700d7, 0x0000585858580058,
-	0x0000616161610061, 0x00001b1b1b1b001b, 0x00001c1c1c1c001c,
-	0x00000f0f0f0f000f, 0x0000161616160016, 0x0000181818180018,
-	0x0000222222220022, 0x0000444444440044, 0x0000b2b2b2b200b2,
-	0x0000b5b5b5b500b5, 0x0000919191910091, 0x0000080808080008,
-	0x0000a8a8a8a800a8, 0x0000fcfcfcfc00fc, 0x0000505050500050,
-	0x0000d0d0d0d000d0, 0x00007d7d7d7d007d, 0x0000898989890089,
-	0x0000979797970097, 0x00005b5b5b5b005b, 0x0000959595950095,
-	0x0000ffffffff00ff, 0x0000d2d2d2d200d2, 0x0000c4c4c4c400c4,
-	0x0000484848480048, 0x0000f7f7f7f700f7, 0x0000dbdbdbdb00db,
-	0x0000030303030003, 0x0000dadadada00da, 0x00003f3f3f3f003f,
-	0x0000949494940094, 0x00005c5c5c5c005c, 0x0000020202020002,
-	0x00004a4a4a4a004a, 0x0000333333330033, 0x0000676767670067,
-	0x0000f3f3f3f300f3, 0x00007f7f7f7f007f, 0x0000e2e2e2e200e2,
-	0x00009b9b9b9b009b, 0x0000262626260026, 0x0000373737370037,
-	0x00003b3b3b3b003b, 0x0000969696960096, 0x00004b4b4b4b004b,
-	0x0000bebebebe00be, 0x00002e2e2e2e002e, 0x0000797979790079,
-	0x00008c8c8c8c008c, 0x00006e6e6e6e006e, 0x00008e8e8e8e008e,
-	0x0000f5f5f5f500f5, 0x0000b6b6b6b600b6, 0x0000fdfdfdfd00fd,
-	0x0000595959590059, 0x0000989898980098, 0x00006a6a6a6a006a,
-	0x0000464646460046, 0x0000babababa00ba, 0x0000252525250025,
-	0x0000424242420042, 0x0000a2a2a2a200a2, 0x0000fafafafa00fa,
-	0x0000070707070007, 0x0000555555550055, 0x0000eeeeeeee00ee,
-	0x00000a0a0a0a000a, 0x0000494949490049, 0x0000686868680068,
-	0x0000383838380038, 0x0000a4a4a4a400a4, 0x0000282828280028,
-	0x00007b7b7b7b007b, 0x0000c9c9c9c900c9, 0x0000c1c1c1c100c1,
-	0x0000e3e3e3e300e3, 0x0000f4f4f4f400f4, 0x0000c7c7c7c700c7,
-	0x00009e9e9e9e009e,
+	0x0000707070700070ULL, 0x00002c2c2c2c002cULL, 0x0000b3b3b3b300b3ULL,
+	0x0000c0c0c0c000c0ULL, 0x0000e4e4e4e400e4ULL, 0x0000575757570057ULL,
+	0x0000eaeaeaea00eaULL, 0x0000aeaeaeae00aeULL, 0x0000232323230023ULL,
+	0x00006b6b6b6b006bULL, 0x0000454545450045ULL, 0x0000a5a5a5a500a5ULL,
+	0x0000edededed00edULL, 0x00004f4f4f4f004fULL, 0x00001d1d1d1d001dULL,
+	0x0000929292920092ULL, 0x0000868686860086ULL, 0x0000afafafaf00afULL,
+	0x00007c7c7c7c007cULL, 0x00001f1f1f1f001fULL, 0x00003e3e3e3e003eULL,
+	0x0000dcdcdcdc00dcULL, 0x00005e5e5e5e005eULL, 0x00000b0b0b0b000bULL,
+	0x0000a6a6a6a600a6ULL, 0x0000393939390039ULL, 0x0000d5d5d5d500d5ULL,
+	0x00005d5d5d5d005dULL, 0x0000d9d9d9d900d9ULL, 0x00005a5a5a5a005aULL,
+	0x0000515151510051ULL, 0x00006c6c6c6c006cULL, 0x00008b8b8b8b008bULL,
+	0x00009a9a9a9a009aULL, 0x0000fbfbfbfb00fbULL, 0x0000b0b0b0b000b0ULL,
+	0x0000747474740074ULL, 0x00002b2b2b2b002bULL, 0x0000f0f0f0f000f0ULL,
+	0x0000848484840084ULL, 0x0000dfdfdfdf00dfULL, 0x0000cbcbcbcb00cbULL,
+	0x0000343434340034ULL, 0x0000767676760076ULL, 0x00006d6d6d6d006dULL,
+	0x0000a9a9a9a900a9ULL, 0x0000d1d1d1d100d1ULL, 0x0000040404040004ULL,
+	0x0000141414140014ULL, 0x00003a3a3a3a003aULL, 0x0000dededede00deULL,
+	0x0000111111110011ULL, 0x0000323232320032ULL, 0x00009c9c9c9c009cULL,
+	0x0000535353530053ULL, 0x0000f2f2f2f200f2ULL, 0x0000fefefefe00feULL,
+	0x0000cfcfcfcf00cfULL, 0x0000c3c3c3c300c3ULL, 0x00007a7a7a7a007aULL,
+	0x0000242424240024ULL, 0x0000e8e8e8e800e8ULL, 0x0000606060600060ULL,
+	0x0000696969690069ULL, 0x0000aaaaaaaa00aaULL, 0x0000a0a0a0a000a0ULL,
+	0x0000a1a1a1a100a1ULL, 0x0000626262620062ULL, 0x0000545454540054ULL,
+	0x00001e1e1e1e001eULL, 0x0000e0e0e0e000e0ULL, 0x0000646464640064ULL,
+	0x0000101010100010ULL, 0x0000000000000000ULL, 0x0000a3a3a3a300a3ULL,
+	0x0000757575750075ULL, 0x00008a8a8a8a008aULL, 0x0000e6e6e6e600e6ULL,
+	0x0000090909090009ULL, 0x0000dddddddd00ddULL, 0x0000878787870087ULL,
+	0x0000838383830083ULL, 0x0000cdcdcdcd00cdULL, 0x0000909090900090ULL,
+	0x0000737373730073ULL, 0x0000f6f6f6f600f6ULL, 0x00009d9d9d9d009dULL,
+	0x0000bfbfbfbf00bfULL, 0x0000525252520052ULL, 0x0000d8d8d8d800d8ULL,
+	0x0000c8c8c8c800c8ULL, 0x0000c6c6c6c600c6ULL, 0x0000818181810081ULL,
+	0x00006f6f6f6f006fULL, 0x0000131313130013ULL, 0x0000636363630063ULL,
+	0x0000e9e9e9e900e9ULL, 0x0000a7a7a7a700a7ULL, 0x00009f9f9f9f009fULL,
+	0x0000bcbcbcbc00bcULL, 0x0000292929290029ULL, 0x0000f9f9f9f900f9ULL,
+	0x00002f2f2f2f002fULL, 0x0000b4b4b4b400b4ULL, 0x0000787878780078ULL,
+	0x0000060606060006ULL, 0x0000e7e7e7e700e7ULL, 0x0000717171710071ULL,
+	0x0000d4d4d4d400d4ULL, 0x0000abababab00abULL, 0x0000888888880088ULL,
+	0x00008d8d8d8d008dULL, 0x0000727272720072ULL, 0x0000b9b9b9b900b9ULL,
+	0x0000f8f8f8f800f8ULL, 0x0000acacacac00acULL, 0x0000363636360036ULL,
+	0x00002a2a2a2a002aULL, 0x00003c3c3c3c003cULL, 0x0000f1f1f1f100f1ULL,
+	0x0000404040400040ULL, 0x0000d3d3d3d300d3ULL, 0x0000bbbbbbbb00bbULL,
+	0x0000434343430043ULL, 0x0000151515150015ULL, 0x0000adadadad00adULL,
+	0x0000777777770077ULL, 0x0000808080800080ULL, 0x0000828282820082ULL,
+	0x0000ecececec00ecULL, 0x0000272727270027ULL, 0x0000e5e5e5e500e5ULL,
+	0x0000858585850085ULL, 0x0000353535350035ULL, 0x00000c0c0c0c000cULL,
+	0x0000414141410041ULL, 0x0000efefefef00efULL, 0x0000939393930093ULL,
+	0x0000191919190019ULL, 0x0000212121210021ULL, 0x00000e0e0e0e000eULL,
+	0x00004e4e4e4e004eULL, 0x0000656565650065ULL, 0x0000bdbdbdbd00bdULL,
+	0x0000b8b8b8b800b8ULL, 0x00008f8f8f8f008fULL, 0x0000ebebebeb00ebULL,
+	0x0000cececece00ceULL, 0x0000303030300030ULL, 0x00005f5f5f5f005fULL,
+	0x0000c5c5c5c500c5ULL, 0x00001a1a1a1a001aULL, 0x0000e1e1e1e100e1ULL,
+	0x0000cacacaca00caULL, 0x0000474747470047ULL, 0x00003d3d3d3d003dULL,
+	0x0000010101010001ULL, 0x0000d6d6d6d600d6ULL, 0x0000565656560056ULL,
+	0x00004d4d4d4d004dULL, 0x00000d0d0d0d000dULL, 0x0000666666660066ULL,
+	0x0000cccccccc00ccULL, 0x00002d2d2d2d002dULL, 0x0000121212120012ULL,
+	0x0000202020200020ULL, 0x0000b1b1b1b100b1ULL, 0x0000999999990099ULL,
+	0x00004c4c4c4c004cULL, 0x0000c2c2c2c200c2ULL, 0x00007e7e7e7e007eULL,
+	0x0000050505050005ULL, 0x0000b7b7b7b700b7ULL, 0x0000313131310031ULL,
+	0x0000171717170017ULL, 0x0000d7d7d7d700d7ULL, 0x0000585858580058ULL,
+	0x0000616161610061ULL, 0x00001b1b1b1b001bULL, 0x00001c1c1c1c001cULL,
+	0x00000f0f0f0f000fULL, 0x0000161616160016ULL, 0x0000181818180018ULL,
+	0x0000222222220022ULL, 0x0000444444440044ULL, 0x0000b2b2b2b200b2ULL,
+	0x0000b5b5b5b500b5ULL, 0x0000919191910091ULL, 0x0000080808080008ULL,
+	0x0000a8a8a8a800a8ULL, 0x0000fcfcfcfc00fcULL, 0x0000505050500050ULL,
+	0x0000d0d0d0d000d0ULL, 0x00007d7d7d7d007dULL, 0x0000898989890089ULL,
+	0x0000979797970097ULL, 0x00005b5b5b5b005bULL, 0x0000959595950095ULL,
+	0x0000ffffffff00ffULL, 0x0000d2d2d2d200d2ULL, 0x0000c4c4c4c400c4ULL,
+	0x0000484848480048ULL, 0x0000f7f7f7f700f7ULL, 0x0000dbdbdbdb00dbULL,
+	0x0000030303030003ULL, 0x0000dadadada00daULL, 0x00003f3f3f3f003fULL,
+	0x0000949494940094ULL, 0x00005c5c5c5c005cULL, 0x0000020202020002ULL,
+	0x00004a4a4a4a004aULL, 0x0000333333330033ULL, 0x0000676767670067ULL,
+	0x0000f3f3f3f300f3ULL, 0x00007f7f7f7f007fULL, 0x0000e2e2e2e200e2ULL,
+	0x00009b9b9b9b009bULL, 0x0000262626260026ULL, 0x0000373737370037ULL,
+	0x00003b3b3b3b003bULL, 0x0000969696960096ULL, 0x00004b4b4b4b004bULL,
+	0x0000bebebebe00beULL, 0x00002e2e2e2e002eULL, 0x0000797979790079ULL,
+	0x00008c8c8c8c008cULL, 0x00006e6e6e6e006eULL, 0x00008e8e8e8e008eULL,
+	0x0000f5f5f5f500f5ULL, 0x0000b6b6b6b600b6ULL, 0x0000fdfdfdfd00fdULL,
+	0x0000595959590059ULL, 0x0000989898980098ULL, 0x00006a6a6a6a006aULL,
+	0x0000464646460046ULL, 0x0000babababa00baULL, 0x0000252525250025ULL,
+	0x0000424242420042ULL, 0x0000a2a2a2a200a2ULL, 0x0000fafafafa00faULL,
+	0x0000070707070007ULL, 0x0000555555550055ULL, 0x0000eeeeeeee00eeULL,
+	0x00000a0a0a0a000aULL, 0x0000494949490049ULL, 0x0000686868680068ULL,
+	0x0000383838380038ULL, 0x0000a4a4a4a400a4ULL, 0x0000282828280028ULL,
+	0x00007b7b7b7b007bULL, 0x0000c9c9c9c900c9ULL, 0x0000c1c1c1c100c1ULL,
+	0x0000e3e3e3e300e3ULL, 0x0000f4f4f4f400f4ULL, 0x0000c7c7c7c700c7ULL,
+	0x00009e9e9e9e009eULL,
 };
 
 const u64 camellia_sp02220222[256] = {
-	0x00e0e0e000e0e0e0, 0x0005050500050505, 0x0058585800585858,
-	0x00d9d9d900d9d9d9, 0x0067676700676767, 0x004e4e4e004e4e4e,
-	0x0081818100818181, 0x00cbcbcb00cbcbcb, 0x00c9c9c900c9c9c9,
-	0x000b0b0b000b0b0b, 0x00aeaeae00aeaeae, 0x006a6a6a006a6a6a,
-	0x00d5d5d500d5d5d5, 0x0018181800181818, 0x005d5d5d005d5d5d,
-	0x0082828200828282, 0x0046464600464646, 0x00dfdfdf00dfdfdf,
-	0x00d6d6d600d6d6d6, 0x0027272700272727, 0x008a8a8a008a8a8a,
-	0x0032323200323232, 0x004b4b4b004b4b4b, 0x0042424200424242,
-	0x00dbdbdb00dbdbdb, 0x001c1c1c001c1c1c, 0x009e9e9e009e9e9e,
-	0x009c9c9c009c9c9c, 0x003a3a3a003a3a3a, 0x00cacaca00cacaca,
-	0x0025252500252525, 0x007b7b7b007b7b7b, 0x000d0d0d000d0d0d,
-	0x0071717100717171, 0x005f5f5f005f5f5f, 0x001f1f1f001f1f1f,
-	0x00f8f8f800f8f8f8, 0x00d7d7d700d7d7d7, 0x003e3e3e003e3e3e,
-	0x009d9d9d009d9d9d, 0x007c7c7c007c7c7c, 0x0060606000606060,
-	0x00b9b9b900b9b9b9, 0x00bebebe00bebebe, 0x00bcbcbc00bcbcbc,
-	0x008b8b8b008b8b8b, 0x0016161600161616, 0x0034343400343434,
-	0x004d4d4d004d4d4d, 0x00c3c3c300c3c3c3, 0x0072727200727272,
-	0x0095959500959595, 0x00ababab00ababab, 0x008e8e8e008e8e8e,
-	0x00bababa00bababa, 0x007a7a7a007a7a7a, 0x00b3b3b300b3b3b3,
-	0x0002020200020202, 0x00b4b4b400b4b4b4, 0x00adadad00adadad,
-	0x00a2a2a200a2a2a2, 0x00acacac00acacac, 0x00d8d8d800d8d8d8,
-	0x009a9a9a009a9a9a, 0x0017171700171717, 0x001a1a1a001a1a1a,
-	0x0035353500353535, 0x00cccccc00cccccc, 0x00f7f7f700f7f7f7,
-	0x0099999900999999, 0x0061616100616161, 0x005a5a5a005a5a5a,
-	0x00e8e8e800e8e8e8, 0x0024242400242424, 0x0056565600565656,
-	0x0040404000404040, 0x00e1e1e100e1e1e1, 0x0063636300636363,
-	0x0009090900090909, 0x0033333300333333, 0x00bfbfbf00bfbfbf,
-	0x0098989800989898, 0x0097979700979797, 0x0085858500858585,
-	0x0068686800686868, 0x00fcfcfc00fcfcfc, 0x00ececec00ececec,
-	0x000a0a0a000a0a0a, 0x00dadada00dadada, 0x006f6f6f006f6f6f,
-	0x0053535300535353, 0x0062626200626262, 0x00a3a3a300a3a3a3,
-	0x002e2e2e002e2e2e, 0x0008080800080808, 0x00afafaf00afafaf,
-	0x0028282800282828, 0x00b0b0b000b0b0b0, 0x0074747400747474,
-	0x00c2c2c200c2c2c2, 0x00bdbdbd00bdbdbd, 0x0036363600363636,
-	0x0022222200222222, 0x0038383800383838, 0x0064646400646464,
-	0x001e1e1e001e1e1e, 0x0039393900393939, 0x002c2c2c002c2c2c,
-	0x00a6a6a600a6a6a6, 0x0030303000303030, 0x00e5e5e500e5e5e5,
-	0x0044444400444444, 0x00fdfdfd00fdfdfd, 0x0088888800888888,
-	0x009f9f9f009f9f9f, 0x0065656500656565, 0x0087878700878787,
-	0x006b6b6b006b6b6b, 0x00f4f4f400f4f4f4, 0x0023232300232323,
-	0x0048484800484848, 0x0010101000101010, 0x00d1d1d100d1d1d1,
-	0x0051515100515151, 0x00c0c0c000c0c0c0, 0x00f9f9f900f9f9f9,
-	0x00d2d2d200d2d2d2, 0x00a0a0a000a0a0a0, 0x0055555500555555,
-	0x00a1a1a100a1a1a1, 0x0041414100414141, 0x00fafafa00fafafa,
-	0x0043434300434343, 0x0013131300131313, 0x00c4c4c400c4c4c4,
-	0x002f2f2f002f2f2f, 0x00a8a8a800a8a8a8, 0x00b6b6b600b6b6b6,
-	0x003c3c3c003c3c3c, 0x002b2b2b002b2b2b, 0x00c1c1c100c1c1c1,
-	0x00ffffff00ffffff, 0x00c8c8c800c8c8c8, 0x00a5a5a500a5a5a5,
-	0x0020202000202020, 0x0089898900898989, 0x0000000000000000,
-	0x0090909000909090, 0x0047474700474747, 0x00efefef00efefef,
-	0x00eaeaea00eaeaea, 0x00b7b7b700b7b7b7, 0x0015151500151515,
-	0x0006060600060606, 0x00cdcdcd00cdcdcd, 0x00b5b5b500b5b5b5,
-	0x0012121200121212, 0x007e7e7e007e7e7e, 0x00bbbbbb00bbbbbb,
-	0x0029292900292929, 0x000f0f0f000f0f0f, 0x00b8b8b800b8b8b8,
-	0x0007070700070707, 0x0004040400040404, 0x009b9b9b009b9b9b,
-	0x0094949400949494, 0x0021212100212121, 0x0066666600666666,
-	0x00e6e6e600e6e6e6, 0x00cecece00cecece, 0x00ededed00ededed,
-	0x00e7e7e700e7e7e7, 0x003b3b3b003b3b3b, 0x00fefefe00fefefe,
-	0x007f7f7f007f7f7f, 0x00c5c5c500c5c5c5, 0x00a4a4a400a4a4a4,
-	0x0037373700373737, 0x00b1b1b100b1b1b1, 0x004c4c4c004c4c4c,
-	0x0091919100919191, 0x006e6e6e006e6e6e, 0x008d8d8d008d8d8d,
-	0x0076767600767676, 0x0003030300030303, 0x002d2d2d002d2d2d,
-	0x00dedede00dedede, 0x0096969600969696, 0x0026262600262626,
-	0x007d7d7d007d7d7d, 0x00c6c6c600c6c6c6, 0x005c5c5c005c5c5c,
-	0x00d3d3d300d3d3d3, 0x00f2f2f200f2f2f2, 0x004f4f4f004f4f4f,
-	0x0019191900191919, 0x003f3f3f003f3f3f, 0x00dcdcdc00dcdcdc,
-	0x0079797900797979, 0x001d1d1d001d1d1d, 0x0052525200525252,
-	0x00ebebeb00ebebeb, 0x00f3f3f300f3f3f3, 0x006d6d6d006d6d6d,
-	0x005e5e5e005e5e5e, 0x00fbfbfb00fbfbfb, 0x0069696900696969,
-	0x00b2b2b200b2b2b2, 0x00f0f0f000f0f0f0, 0x0031313100313131,
-	0x000c0c0c000c0c0c, 0x00d4d4d400d4d4d4, 0x00cfcfcf00cfcfcf,
-	0x008c8c8c008c8c8c, 0x00e2e2e200e2e2e2, 0x0075757500757575,
-	0x00a9a9a900a9a9a9, 0x004a4a4a004a4a4a, 0x0057575700575757,
-	0x0084848400848484, 0x0011111100111111, 0x0045454500454545,
-	0x001b1b1b001b1b1b, 0x00f5f5f500f5f5f5, 0x00e4e4e400e4e4e4,
-	0x000e0e0e000e0e0e, 0x0073737300737373, 0x00aaaaaa00aaaaaa,
-	0x00f1f1f100f1f1f1, 0x00dddddd00dddddd, 0x0059595900595959,
-	0x0014141400141414, 0x006c6c6c006c6c6c, 0x0092929200929292,
-	0x0054545400545454, 0x00d0d0d000d0d0d0, 0x0078787800787878,
-	0x0070707000707070, 0x00e3e3e300e3e3e3, 0x0049494900494949,
-	0x0080808000808080, 0x0050505000505050, 0x00a7a7a700a7a7a7,
-	0x00f6f6f600f6f6f6, 0x0077777700777777, 0x0093939300939393,
-	0x0086868600868686, 0x0083838300838383, 0x002a2a2a002a2a2a,
-	0x00c7c7c700c7c7c7, 0x005b5b5b005b5b5b, 0x00e9e9e900e9e9e9,
-	0x00eeeeee00eeeeee, 0x008f8f8f008f8f8f, 0x0001010100010101,
-	0x003d3d3d003d3d3d,
+	0x00e0e0e000e0e0e0ULL, 0x0005050500050505ULL, 0x0058585800585858ULL,
+	0x00d9d9d900d9d9d9ULL, 0x0067676700676767ULL, 0x004e4e4e004e4e4eULL,
+	0x0081818100818181ULL, 0x00cbcbcb00cbcbcbULL, 0x00c9c9c900c9c9c9ULL,
+	0x000b0b0b000b0b0bULL, 0x00aeaeae00aeaeaeULL, 0x006a6a6a006a6a6aULL,
+	0x00d5d5d500d5d5d5ULL, 0x0018181800181818ULL, 0x005d5d5d005d5d5dULL,
+	0x0082828200828282ULL, 0x0046464600464646ULL, 0x00dfdfdf00dfdfdfULL,
+	0x00d6d6d600d6d6d6ULL, 0x0027272700272727ULL, 0x008a8a8a008a8a8aULL,
+	0x0032323200323232ULL, 0x004b4b4b004b4b4bULL, 0x0042424200424242ULL,
+	0x00dbdbdb00dbdbdbULL, 0x001c1c1c001c1c1cULL, 0x009e9e9e009e9e9eULL,
+	0x009c9c9c009c9c9cULL, 0x003a3a3a003a3a3aULL, 0x00cacaca00cacacaULL,
+	0x0025252500252525ULL, 0x007b7b7b007b7b7bULL, 0x000d0d0d000d0d0dULL,
+	0x0071717100717171ULL, 0x005f5f5f005f5f5fULL, 0x001f1f1f001f1f1fULL,
+	0x00f8f8f800f8f8f8ULL, 0x00d7d7d700d7d7d7ULL, 0x003e3e3e003e3e3eULL,
+	0x009d9d9d009d9d9dULL, 0x007c7c7c007c7c7cULL, 0x0060606000606060ULL,
+	0x00b9b9b900b9b9b9ULL, 0x00bebebe00bebebeULL, 0x00bcbcbc00bcbcbcULL,
+	0x008b8b8b008b8b8bULL, 0x0016161600161616ULL, 0x0034343400343434ULL,
+	0x004d4d4d004d4d4dULL, 0x00c3c3c300c3c3c3ULL, 0x0072727200727272ULL,
+	0x0095959500959595ULL, 0x00ababab00abababULL, 0x008e8e8e008e8e8eULL,
+	0x00bababa00bababaULL, 0x007a7a7a007a7a7aULL, 0x00b3b3b300b3b3b3ULL,
+	0x0002020200020202ULL, 0x00b4b4b400b4b4b4ULL, 0x00adadad00adadadULL,
+	0x00a2a2a200a2a2a2ULL, 0x00acacac00acacacULL, 0x00d8d8d800d8d8d8ULL,
+	0x009a9a9a009a9a9aULL, 0x0017171700171717ULL, 0x001a1a1a001a1a1aULL,
+	0x0035353500353535ULL, 0x00cccccc00ccccccULL, 0x00f7f7f700f7f7f7ULL,
+	0x0099999900999999ULL, 0x0061616100616161ULL, 0x005a5a5a005a5a5aULL,
+	0x00e8e8e800e8e8e8ULL, 0x0024242400242424ULL, 0x0056565600565656ULL,
+	0x0040404000404040ULL, 0x00e1e1e100e1e1e1ULL, 0x0063636300636363ULL,
+	0x0009090900090909ULL, 0x0033333300333333ULL, 0x00bfbfbf00bfbfbfULL,
+	0x0098989800989898ULL, 0x0097979700979797ULL, 0x0085858500858585ULL,
+	0x0068686800686868ULL, 0x00fcfcfc00fcfcfcULL, 0x00ececec00ecececULL,
+	0x000a0a0a000a0a0aULL, 0x00dadada00dadadaULL, 0x006f6f6f006f6f6fULL,
+	0x0053535300535353ULL, 0x0062626200626262ULL, 0x00a3a3a300a3a3a3ULL,
+	0x002e2e2e002e2e2eULL, 0x0008080800080808ULL, 0x00afafaf00afafafULL,
+	0x0028282800282828ULL, 0x00b0b0b000b0b0b0ULL, 0x0074747400747474ULL,
+	0x00c2c2c200c2c2c2ULL, 0x00bdbdbd00bdbdbdULL, 0x0036363600363636ULL,
+	0x0022222200222222ULL, 0x0038383800383838ULL, 0x0064646400646464ULL,
+	0x001e1e1e001e1e1eULL, 0x0039393900393939ULL, 0x002c2c2c002c2c2cULL,
+	0x00a6a6a600a6a6a6ULL, 0x0030303000303030ULL, 0x00e5e5e500e5e5e5ULL,
+	0x0044444400444444ULL, 0x00fdfdfd00fdfdfdULL, 0x0088888800888888ULL,
+	0x009f9f9f009f9f9fULL, 0x0065656500656565ULL, 0x0087878700878787ULL,
+	0x006b6b6b006b6b6bULL, 0x00f4f4f400f4f4f4ULL, 0x0023232300232323ULL,
+	0x0048484800484848ULL, 0x0010101000101010ULL, 0x00d1d1d100d1d1d1ULL,
+	0x0051515100515151ULL, 0x00c0c0c000c0c0c0ULL, 0x00f9f9f900f9f9f9ULL,
+	0x00d2d2d200d2d2d2ULL, 0x00a0a0a000a0a0a0ULL, 0x0055555500555555ULL,
+	0x00a1a1a100a1a1a1ULL, 0x0041414100414141ULL, 0x00fafafa00fafafaULL,
+	0x0043434300434343ULL, 0x0013131300131313ULL, 0x00c4c4c400c4c4c4ULL,
+	0x002f2f2f002f2f2fULL, 0x00a8a8a800a8a8a8ULL, 0x00b6b6b600b6b6b6ULL,
+	0x003c3c3c003c3c3cULL, 0x002b2b2b002b2b2bULL, 0x00c1c1c100c1c1c1ULL,
+	0x00ffffff00ffffffULL, 0x00c8c8c800c8c8c8ULL, 0x00a5a5a500a5a5a5ULL,
+	0x0020202000202020ULL, 0x0089898900898989ULL, 0x0000000000000000ULL,
+	0x0090909000909090ULL, 0x0047474700474747ULL, 0x00efefef00efefefULL,
+	0x00eaeaea00eaeaeaULL, 0x00b7b7b700b7b7b7ULL, 0x0015151500151515ULL,
+	0x0006060600060606ULL, 0x00cdcdcd00cdcdcdULL, 0x00b5b5b500b5b5b5ULL,
+	0x0012121200121212ULL, 0x007e7e7e007e7e7eULL, 0x00bbbbbb00bbbbbbULL,
+	0x0029292900292929ULL, 0x000f0f0f000f0f0fULL, 0x00b8b8b800b8b8b8ULL,
+	0x0007070700070707ULL, 0x0004040400040404ULL, 0x009b9b9b009b9b9bULL,
+	0x0094949400949494ULL, 0x0021212100212121ULL, 0x0066666600666666ULL,
+	0x00e6e6e600e6e6e6ULL, 0x00cecece00cececeULL, 0x00ededed00edededULL,
+	0x00e7e7e700e7e7e7ULL, 0x003b3b3b003b3b3bULL, 0x00fefefe00fefefeULL,
+	0x007f7f7f007f7f7fULL, 0x00c5c5c500c5c5c5ULL, 0x00a4a4a400a4a4a4ULL,
+	0x0037373700373737ULL, 0x00b1b1b100b1b1b1ULL, 0x004c4c4c004c4c4cULL,
+	0x0091919100919191ULL, 0x006e6e6e006e6e6eULL, 0x008d8d8d008d8d8dULL,
+	0x0076767600767676ULL, 0x0003030300030303ULL, 0x002d2d2d002d2d2dULL,
+	0x00dedede00dededeULL, 0x0096969600969696ULL, 0x0026262600262626ULL,
+	0x007d7d7d007d7d7dULL, 0x00c6c6c600c6c6c6ULL, 0x005c5c5c005c5c5cULL,
+	0x00d3d3d300d3d3d3ULL, 0x00f2f2f200f2f2f2ULL, 0x004f4f4f004f4f4fULL,
+	0x0019191900191919ULL, 0x003f3f3f003f3f3fULL, 0x00dcdcdc00dcdcdcULL,
+	0x0079797900797979ULL, 0x001d1d1d001d1d1dULL, 0x0052525200525252ULL,
+	0x00ebebeb00ebebebULL, 0x00f3f3f300f3f3f3ULL, 0x006d6d6d006d6d6dULL,
+	0x005e5e5e005e5e5eULL, 0x00fbfbfb00fbfbfbULL, 0x0069696900696969ULL,
+	0x00b2b2b200b2b2b2ULL, 0x00f0f0f000f0f0f0ULL, 0x0031313100313131ULL,
+	0x000c0c0c000c0c0cULL, 0x00d4d4d400d4d4d4ULL, 0x00cfcfcf00cfcfcfULL,
+	0x008c8c8c008c8c8cULL, 0x00e2e2e200e2e2e2ULL, 0x0075757500757575ULL,
+	0x00a9a9a900a9a9a9ULL, 0x004a4a4a004a4a4aULL, 0x0057575700575757ULL,
+	0x0084848400848484ULL, 0x0011111100111111ULL, 0x0045454500454545ULL,
+	0x001b1b1b001b1b1bULL, 0x00f5f5f500f5f5f5ULL, 0x00e4e4e400e4e4e4ULL,
+	0x000e0e0e000e0e0eULL, 0x0073737300737373ULL, 0x00aaaaaa00aaaaaaULL,
+	0x00f1f1f100f1f1f1ULL, 0x00dddddd00ddddddULL, 0x0059595900595959ULL,
+	0x0014141400141414ULL, 0x006c6c6c006c6c6cULL, 0x0092929200929292ULL,
+	0x0054545400545454ULL, 0x00d0d0d000d0d0d0ULL, 0x0078787800787878ULL,
+	0x0070707000707070ULL, 0x00e3e3e300e3e3e3ULL, 0x0049494900494949ULL,
+	0x0080808000808080ULL, 0x0050505000505050ULL, 0x00a7a7a700a7a7a7ULL,
+	0x00f6f6f600f6f6f6ULL, 0x0077777700777777ULL, 0x0093939300939393ULL,
+	0x0086868600868686ULL, 0x0083838300838383ULL, 0x002a2a2a002a2a2aULL,
+	0x00c7c7c700c7c7c7ULL, 0x005b5b5b005b5b5bULL, 0x00e9e9e900e9e9e9ULL,
+	0x00eeeeee00eeeeeeULL, 0x008f8f8f008f8f8fULL, 0x0001010100010101ULL,
+	0x003d3d3d003d3d3dULL,
 };
 
 const u64 camellia_sp30333033[256] = {
-	0x3800383838003838, 0x4100414141004141, 0x1600161616001616,
-	0x7600767676007676, 0xd900d9d9d900d9d9, 0x9300939393009393,
-	0x6000606060006060, 0xf200f2f2f200f2f2, 0x7200727272007272,
-	0xc200c2c2c200c2c2, 0xab00ababab00abab, 0x9a009a9a9a009a9a,
-	0x7500757575007575, 0x0600060606000606, 0x5700575757005757,
-	0xa000a0a0a000a0a0, 0x9100919191009191, 0xf700f7f7f700f7f7,
-	0xb500b5b5b500b5b5, 0xc900c9c9c900c9c9, 0xa200a2a2a200a2a2,
-	0x8c008c8c8c008c8c, 0xd200d2d2d200d2d2, 0x9000909090009090,
-	0xf600f6f6f600f6f6, 0x0700070707000707, 0xa700a7a7a700a7a7,
-	0x2700272727002727, 0x8e008e8e8e008e8e, 0xb200b2b2b200b2b2,
-	0x4900494949004949, 0xde00dedede00dede, 0x4300434343004343,
-	0x5c005c5c5c005c5c, 0xd700d7d7d700d7d7, 0xc700c7c7c700c7c7,
-	0x3e003e3e3e003e3e, 0xf500f5f5f500f5f5, 0x8f008f8f8f008f8f,
-	0x6700676767006767, 0x1f001f1f1f001f1f, 0x1800181818001818,
-	0x6e006e6e6e006e6e, 0xaf00afafaf00afaf, 0x2f002f2f2f002f2f,
-	0xe200e2e2e200e2e2, 0x8500858585008585, 0x0d000d0d0d000d0d,
-	0x5300535353005353, 0xf000f0f0f000f0f0, 0x9c009c9c9c009c9c,
-	0x6500656565006565, 0xea00eaeaea00eaea, 0xa300a3a3a300a3a3,
-	0xae00aeaeae00aeae, 0x9e009e9e9e009e9e, 0xec00ececec00ecec,
-	0x8000808080008080, 0x2d002d2d2d002d2d, 0x6b006b6b6b006b6b,
-	0xa800a8a8a800a8a8, 0x2b002b2b2b002b2b, 0x3600363636003636,
-	0xa600a6a6a600a6a6, 0xc500c5c5c500c5c5, 0x8600868686008686,
-	0x4d004d4d4d004d4d, 0x3300333333003333, 0xfd00fdfdfd00fdfd,
-	0x6600666666006666, 0x5800585858005858, 0x9600969696009696,
-	0x3a003a3a3a003a3a, 0x0900090909000909, 0x9500959595009595,
-	0x1000101010001010, 0x7800787878007878, 0xd800d8d8d800d8d8,
-	0x4200424242004242, 0xcc00cccccc00cccc, 0xef00efefef00efef,
-	0x2600262626002626, 0xe500e5e5e500e5e5, 0x6100616161006161,
-	0x1a001a1a1a001a1a, 0x3f003f3f3f003f3f, 0x3b003b3b3b003b3b,
-	0x8200828282008282, 0xb600b6b6b600b6b6, 0xdb00dbdbdb00dbdb,
-	0xd400d4d4d400d4d4, 0x9800989898009898, 0xe800e8e8e800e8e8,
-	0x8b008b8b8b008b8b, 0x0200020202000202, 0xeb00ebebeb00ebeb,
-	0x0a000a0a0a000a0a, 0x2c002c2c2c002c2c, 0x1d001d1d1d001d1d,
-	0xb000b0b0b000b0b0, 0x6f006f6f6f006f6f, 0x8d008d8d8d008d8d,
-	0x8800888888008888, 0x0e000e0e0e000e0e, 0x1900191919001919,
-	0x8700878787008787, 0x4e004e4e4e004e4e, 0x0b000b0b0b000b0b,
-	0xa900a9a9a900a9a9, 0x0c000c0c0c000c0c, 0x7900797979007979,
-	0x1100111111001111, 0x7f007f7f7f007f7f, 0x2200222222002222,
-	0xe700e7e7e700e7e7, 0x5900595959005959, 0xe100e1e1e100e1e1,
-	0xda00dadada00dada, 0x3d003d3d3d003d3d, 0xc800c8c8c800c8c8,
-	0x1200121212001212, 0x0400040404000404, 0x7400747474007474,
-	0x5400545454005454, 0x3000303030003030, 0x7e007e7e7e007e7e,
-	0xb400b4b4b400b4b4, 0x2800282828002828, 0x5500555555005555,
-	0x6800686868006868, 0x5000505050005050, 0xbe00bebebe00bebe,
-	0xd000d0d0d000d0d0, 0xc400c4c4c400c4c4, 0x3100313131003131,
-	0xcb00cbcbcb00cbcb, 0x2a002a2a2a002a2a, 0xad00adadad00adad,
-	0x0f000f0f0f000f0f, 0xca00cacaca00caca, 0x7000707070007070,
-	0xff00ffffff00ffff, 0x3200323232003232, 0x6900696969006969,
-	0x0800080808000808, 0x6200626262006262, 0x0000000000000000,
-	0x2400242424002424, 0xd100d1d1d100d1d1, 0xfb00fbfbfb00fbfb,
-	0xba00bababa00baba, 0xed00ededed00eded, 0x4500454545004545,
-	0x8100818181008181, 0x7300737373007373, 0x6d006d6d6d006d6d,
-	0x8400848484008484, 0x9f009f9f9f009f9f, 0xee00eeeeee00eeee,
-	0x4a004a4a4a004a4a, 0xc300c3c3c300c3c3, 0x2e002e2e2e002e2e,
-	0xc100c1c1c100c1c1, 0x0100010101000101, 0xe600e6e6e600e6e6,
-	0x2500252525002525, 0x4800484848004848, 0x9900999999009999,
-	0xb900b9b9b900b9b9, 0xb300b3b3b300b3b3, 0x7b007b7b7b007b7b,
-	0xf900f9f9f900f9f9, 0xce00cecece00cece, 0xbf00bfbfbf00bfbf,
-	0xdf00dfdfdf00dfdf, 0x7100717171007171, 0x2900292929002929,
-	0xcd00cdcdcd00cdcd, 0x6c006c6c6c006c6c, 0x1300131313001313,
-	0x6400646464006464, 0x9b009b9b9b009b9b, 0x6300636363006363,
-	0x9d009d9d9d009d9d, 0xc000c0c0c000c0c0, 0x4b004b4b4b004b4b,
-	0xb700b7b7b700b7b7, 0xa500a5a5a500a5a5, 0x8900898989008989,
-	0x5f005f5f5f005f5f, 0xb100b1b1b100b1b1, 0x1700171717001717,
-	0xf400f4f4f400f4f4, 0xbc00bcbcbc00bcbc, 0xd300d3d3d300d3d3,
-	0x4600464646004646, 0xcf00cfcfcf00cfcf, 0x3700373737003737,
-	0x5e005e5e5e005e5e, 0x4700474747004747, 0x9400949494009494,
-	0xfa00fafafa00fafa, 0xfc00fcfcfc00fcfc, 0x5b005b5b5b005b5b,
-	0x9700979797009797, 0xfe00fefefe00fefe, 0x5a005a5a5a005a5a,
-	0xac00acacac00acac, 0x3c003c3c3c003c3c, 0x4c004c4c4c004c4c,
-	0x0300030303000303, 0x3500353535003535, 0xf300f3f3f300f3f3,
-	0x2300232323002323, 0xb800b8b8b800b8b8, 0x5d005d5d5d005d5d,
-	0x6a006a6a6a006a6a, 0x9200929292009292, 0xd500d5d5d500d5d5,
-	0x2100212121002121, 0x4400444444004444, 0x5100515151005151,
-	0xc600c6c6c600c6c6, 0x7d007d7d7d007d7d, 0x3900393939003939,
-	0x8300838383008383, 0xdc00dcdcdc00dcdc, 0xaa00aaaaaa00aaaa,
-	0x7c007c7c7c007c7c, 0x7700777777007777, 0x5600565656005656,
-	0x0500050505000505, 0x1b001b1b1b001b1b, 0xa400a4a4a400a4a4,
-	0x1500151515001515, 0x3400343434003434, 0x1e001e1e1e001e1e,
-	0x1c001c1c1c001c1c, 0xf800f8f8f800f8f8, 0x5200525252005252,
-	0x2000202020002020, 0x1400141414001414, 0xe900e9e9e900e9e9,
-	0xbd00bdbdbd00bdbd, 0xdd00dddddd00dddd, 0xe400e4e4e400e4e4,
-	0xa100a1a1a100a1a1, 0xe000e0e0e000e0e0, 0x8a008a8a8a008a8a,
-	0xf100f1f1f100f1f1, 0xd600d6d6d600d6d6, 0x7a007a7a7a007a7a,
-	0xbb00bbbbbb00bbbb, 0xe300e3e3e300e3e3, 0x4000404040004040,
-	0x4f004f4f4f004f4f,
+	0x3800383838003838ULL, 0x4100414141004141ULL, 0x1600161616001616ULL,
+	0x7600767676007676ULL, 0xd900d9d9d900d9d9ULL, 0x9300939393009393ULL,
+	0x6000606060006060ULL, 0xf200f2f2f200f2f2ULL, 0x7200727272007272ULL,
+	0xc200c2c2c200c2c2ULL, 0xab00ababab00ababULL, 0x9a009a9a9a009a9aULL,
+	0x7500757575007575ULL, 0x0600060606000606ULL, 0x5700575757005757ULL,
+	0xa000a0a0a000a0a0ULL, 0x9100919191009191ULL, 0xf700f7f7f700f7f7ULL,
+	0xb500b5b5b500b5b5ULL, 0xc900c9c9c900c9c9ULL, 0xa200a2a2a200a2a2ULL,
+	0x8c008c8c8c008c8cULL, 0xd200d2d2d200d2d2ULL, 0x9000909090009090ULL,
+	0xf600f6f6f600f6f6ULL, 0x0700070707000707ULL, 0xa700a7a7a700a7a7ULL,
+	0x2700272727002727ULL, 0x8e008e8e8e008e8eULL, 0xb200b2b2b200b2b2ULL,
+	0x4900494949004949ULL, 0xde00dedede00dedeULL, 0x4300434343004343ULL,
+	0x5c005c5c5c005c5cULL, 0xd700d7d7d700d7d7ULL, 0xc700c7c7c700c7c7ULL,
+	0x3e003e3e3e003e3eULL, 0xf500f5f5f500f5f5ULL, 0x8f008f8f8f008f8fULL,
+	0x6700676767006767ULL, 0x1f001f1f1f001f1fULL, 0x1800181818001818ULL,
+	0x6e006e6e6e006e6eULL, 0xaf00afafaf00afafULL, 0x2f002f2f2f002f2fULL,
+	0xe200e2e2e200e2e2ULL, 0x8500858585008585ULL, 0x0d000d0d0d000d0dULL,
+	0x5300535353005353ULL, 0xf000f0f0f000f0f0ULL, 0x9c009c9c9c009c9cULL,
+	0x6500656565006565ULL, 0xea00eaeaea00eaeaULL, 0xa300a3a3a300a3a3ULL,
+	0xae00aeaeae00aeaeULL, 0x9e009e9e9e009e9eULL, 0xec00ececec00ececULL,
+	0x8000808080008080ULL, 0x2d002d2d2d002d2dULL, 0x6b006b6b6b006b6bULL,
+	0xa800a8a8a800a8a8ULL, 0x2b002b2b2b002b2bULL, 0x3600363636003636ULL,
+	0xa600a6a6a600a6a6ULL, 0xc500c5c5c500c5c5ULL, 0x8600868686008686ULL,
+	0x4d004d4d4d004d4dULL, 0x3300333333003333ULL, 0xfd00fdfdfd00fdfdULL,
+	0x6600666666006666ULL, 0x5800585858005858ULL, 0x9600969696009696ULL,
+	0x3a003a3a3a003a3aULL, 0x0900090909000909ULL, 0x9500959595009595ULL,
+	0x1000101010001010ULL, 0x7800787878007878ULL, 0xd800d8d8d800d8d8ULL,
+	0x4200424242004242ULL, 0xcc00cccccc00ccccULL, 0xef00efefef00efefULL,
+	0x2600262626002626ULL, 0xe500e5e5e500e5e5ULL, 0x6100616161006161ULL,
+	0x1a001a1a1a001a1aULL, 0x3f003f3f3f003f3fULL, 0x3b003b3b3b003b3bULL,
+	0x8200828282008282ULL, 0xb600b6b6b600b6b6ULL, 0xdb00dbdbdb00dbdbULL,
+	0xd400d4d4d400d4d4ULL, 0x9800989898009898ULL, 0xe800e8e8e800e8e8ULL,
+	0x8b008b8b8b008b8bULL, 0x0200020202000202ULL, 0xeb00ebebeb00ebebULL,
+	0x0a000a0a0a000a0aULL, 0x2c002c2c2c002c2cULL, 0x1d001d1d1d001d1dULL,
+	0xb000b0b0b000b0b0ULL, 0x6f006f6f6f006f6fULL, 0x8d008d8d8d008d8dULL,
+	0x8800888888008888ULL, 0x0e000e0e0e000e0eULL, 0x1900191919001919ULL,
+	0x8700878787008787ULL, 0x4e004e4e4e004e4eULL, 0x0b000b0b0b000b0bULL,
+	0xa900a9a9a900a9a9ULL, 0x0c000c0c0c000c0cULL, 0x7900797979007979ULL,
+	0x1100111111001111ULL, 0x7f007f7f7f007f7fULL, 0x2200222222002222ULL,
+	0xe700e7e7e700e7e7ULL, 0x5900595959005959ULL, 0xe100e1e1e100e1e1ULL,
+	0xda00dadada00dadaULL, 0x3d003d3d3d003d3dULL, 0xc800c8c8c800c8c8ULL,
+	0x1200121212001212ULL, 0x0400040404000404ULL, 0x7400747474007474ULL,
+	0x5400545454005454ULL, 0x3000303030003030ULL, 0x7e007e7e7e007e7eULL,
+	0xb400b4b4b400b4b4ULL, 0x2800282828002828ULL, 0x5500555555005555ULL,
+	0x6800686868006868ULL, 0x5000505050005050ULL, 0xbe00bebebe00bebeULL,
+	0xd000d0d0d000d0d0ULL, 0xc400c4c4c400c4c4ULL, 0x3100313131003131ULL,
+	0xcb00cbcbcb00cbcbULL, 0x2a002a2a2a002a2aULL, 0xad00adadad00adadULL,
+	0x0f000f0f0f000f0fULL, 0xca00cacaca00cacaULL, 0x7000707070007070ULL,
+	0xff00ffffff00ffffULL, 0x3200323232003232ULL, 0x6900696969006969ULL,
+	0x0800080808000808ULL, 0x6200626262006262ULL, 0x0000000000000000ULL,
+	0x2400242424002424ULL, 0xd100d1d1d100d1d1ULL, 0xfb00fbfbfb00fbfbULL,
+	0xba00bababa00babaULL, 0xed00ededed00ededULL, 0x4500454545004545ULL,
+	0x8100818181008181ULL, 0x7300737373007373ULL, 0x6d006d6d6d006d6dULL,
+	0x8400848484008484ULL, 0x9f009f9f9f009f9fULL, 0xee00eeeeee00eeeeULL,
+	0x4a004a4a4a004a4aULL, 0xc300c3c3c300c3c3ULL, 0x2e002e2e2e002e2eULL,
+	0xc100c1c1c100c1c1ULL, 0x0100010101000101ULL, 0xe600e6e6e600e6e6ULL,
+	0x2500252525002525ULL, 0x4800484848004848ULL, 0x9900999999009999ULL,
+	0xb900b9b9b900b9b9ULL, 0xb300b3b3b300b3b3ULL, 0x7b007b7b7b007b7bULL,
+	0xf900f9f9f900f9f9ULL, 0xce00cecece00ceceULL, 0xbf00bfbfbf00bfbfULL,
+	0xdf00dfdfdf00dfdfULL, 0x7100717171007171ULL, 0x2900292929002929ULL,
+	0xcd00cdcdcd00cdcdULL, 0x6c006c6c6c006c6cULL, 0x1300131313001313ULL,
+	0x6400646464006464ULL, 0x9b009b9b9b009b9bULL, 0x6300636363006363ULL,
+	0x9d009d9d9d009d9dULL, 0xc000c0c0c000c0c0ULL, 0x4b004b4b4b004b4bULL,
+	0xb700b7b7b700b7b7ULL, 0xa500a5a5a500a5a5ULL, 0x8900898989008989ULL,
+	0x5f005f5f5f005f5fULL, 0xb100b1b1b100b1b1ULL, 0x1700171717001717ULL,
+	0xf400f4f4f400f4f4ULL, 0xbc00bcbcbc00bcbcULL, 0xd300d3d3d300d3d3ULL,
+	0x4600464646004646ULL, 0xcf00cfcfcf00cfcfULL, 0x3700373737003737ULL,
+	0x5e005e5e5e005e5eULL, 0x4700474747004747ULL, 0x9400949494009494ULL,
+	0xfa00fafafa00fafaULL, 0xfc00fcfcfc00fcfcULL, 0x5b005b5b5b005b5bULL,
+	0x9700979797009797ULL, 0xfe00fefefe00fefeULL, 0x5a005a5a5a005a5aULL,
+	0xac00acacac00acacULL, 0x3c003c3c3c003c3cULL, 0x4c004c4c4c004c4cULL,
+	0x0300030303000303ULL, 0x3500353535003535ULL, 0xf300f3f3f300f3f3ULL,
+	0x2300232323002323ULL, 0xb800b8b8b800b8b8ULL, 0x5d005d5d5d005d5dULL,
+	0x6a006a6a6a006a6aULL, 0x9200929292009292ULL, 0xd500d5d5d500d5d5ULL,
+	0x2100212121002121ULL, 0x4400444444004444ULL, 0x5100515151005151ULL,
+	0xc600c6c6c600c6c6ULL, 0x7d007d7d7d007d7dULL, 0x3900393939003939ULL,
+	0x8300838383008383ULL, 0xdc00dcdcdc00dcdcULL, 0xaa00aaaaaa00aaaaULL,
+	0x7c007c7c7c007c7cULL, 0x7700777777007777ULL, 0x5600565656005656ULL,
+	0x0500050505000505ULL, 0x1b001b1b1b001b1bULL, 0xa400a4a4a400a4a4ULL,
+	0x1500151515001515ULL, 0x3400343434003434ULL, 0x1e001e1e1e001e1eULL,
+	0x1c001c1c1c001c1cULL, 0xf800f8f8f800f8f8ULL, 0x5200525252005252ULL,
+	0x2000202020002020ULL, 0x1400141414001414ULL, 0xe900e9e9e900e9e9ULL,
+	0xbd00bdbdbd00bdbdULL, 0xdd00dddddd00ddddULL, 0xe400e4e4e400e4e4ULL,
+	0xa100a1a1a100a1a1ULL, 0xe000e0e0e000e0e0ULL, 0x8a008a8a8a008a8aULL,
+	0xf100f1f1f100f1f1ULL, 0xd600d6d6d600d6d6ULL, 0x7a007a7a7a007a7aULL,
+	0xbb00bbbbbb00bbbbULL, 0xe300e3e3e300e3e3ULL, 0x4000404040004040ULL,
+	0x4f004f4f4f004f4fULL,
 };
 
 const u64 camellia_sp44044404[256] = {
-	0x7070007070700070, 0x2c2c002c2c2c002c, 0xb3b300b3b3b300b3,
-	0xc0c000c0c0c000c0, 0xe4e400e4e4e400e4, 0x5757005757570057,
-	0xeaea00eaeaea00ea, 0xaeae00aeaeae00ae, 0x2323002323230023,
-	0x6b6b006b6b6b006b, 0x4545004545450045, 0xa5a500a5a5a500a5,
-	0xeded00ededed00ed, 0x4f4f004f4f4f004f, 0x1d1d001d1d1d001d,
-	0x9292009292920092, 0x8686008686860086, 0xafaf00afafaf00af,
-	0x7c7c007c7c7c007c, 0x1f1f001f1f1f001f, 0x3e3e003e3e3e003e,
-	0xdcdc00dcdcdc00dc, 0x5e5e005e5e5e005e, 0x0b0b000b0b0b000b,
-	0xa6a600a6a6a600a6, 0x3939003939390039, 0xd5d500d5d5d500d5,
-	0x5d5d005d5d5d005d, 0xd9d900d9d9d900d9, 0x5a5a005a5a5a005a,
-	0x5151005151510051, 0x6c6c006c6c6c006c, 0x8b8b008b8b8b008b,
-	0x9a9a009a9a9a009a, 0xfbfb00fbfbfb00fb, 0xb0b000b0b0b000b0,
-	0x7474007474740074, 0x2b2b002b2b2b002b, 0xf0f000f0f0f000f0,
-	0x8484008484840084, 0xdfdf00dfdfdf00df, 0xcbcb00cbcbcb00cb,
-	0x3434003434340034, 0x7676007676760076, 0x6d6d006d6d6d006d,
-	0xa9a900a9a9a900a9, 0xd1d100d1d1d100d1, 0x0404000404040004,
-	0x1414001414140014, 0x3a3a003a3a3a003a, 0xdede00dedede00de,
-	0x1111001111110011, 0x3232003232320032, 0x9c9c009c9c9c009c,
-	0x5353005353530053, 0xf2f200f2f2f200f2, 0xfefe00fefefe00fe,
-	0xcfcf00cfcfcf00cf, 0xc3c300c3c3c300c3, 0x7a7a007a7a7a007a,
-	0x2424002424240024, 0xe8e800e8e8e800e8, 0x6060006060600060,
-	0x6969006969690069, 0xaaaa00aaaaaa00aa, 0xa0a000a0a0a000a0,
-	0xa1a100a1a1a100a1, 0x6262006262620062, 0x5454005454540054,
-	0x1e1e001e1e1e001e, 0xe0e000e0e0e000e0, 0x6464006464640064,
-	0x1010001010100010, 0x0000000000000000, 0xa3a300a3a3a300a3,
-	0x7575007575750075, 0x8a8a008a8a8a008a, 0xe6e600e6e6e600e6,
-	0x0909000909090009, 0xdddd00dddddd00dd, 0x8787008787870087,
-	0x8383008383830083, 0xcdcd00cdcdcd00cd, 0x9090009090900090,
-	0x7373007373730073, 0xf6f600f6f6f600f6, 0x9d9d009d9d9d009d,
-	0xbfbf00bfbfbf00bf, 0x5252005252520052, 0xd8d800d8d8d800d8,
-	0xc8c800c8c8c800c8, 0xc6c600c6c6c600c6, 0x8181008181810081,
-	0x6f6f006f6f6f006f, 0x1313001313130013, 0x6363006363630063,
-	0xe9e900e9e9e900e9, 0xa7a700a7a7a700a7, 0x9f9f009f9f9f009f,
-	0xbcbc00bcbcbc00bc, 0x2929002929290029, 0xf9f900f9f9f900f9,
-	0x2f2f002f2f2f002f, 0xb4b400b4b4b400b4, 0x7878007878780078,
-	0x0606000606060006, 0xe7e700e7e7e700e7, 0x7171007171710071,
-	0xd4d400d4d4d400d4, 0xabab00ababab00ab, 0x8888008888880088,
-	0x8d8d008d8d8d008d, 0x7272007272720072, 0xb9b900b9b9b900b9,
-	0xf8f800f8f8f800f8, 0xacac00acacac00ac, 0x3636003636360036,
-	0x2a2a002a2a2a002a, 0x3c3c003c3c3c003c, 0xf1f100f1f1f100f1,
-	0x4040004040400040, 0xd3d300d3d3d300d3, 0xbbbb00bbbbbb00bb,
-	0x4343004343430043, 0x1515001515150015, 0xadad00adadad00ad,
-	0x7777007777770077, 0x8080008080800080, 0x8282008282820082,
-	0xecec00ececec00ec, 0x2727002727270027, 0xe5e500e5e5e500e5,
-	0x8585008585850085, 0x3535003535350035, 0x0c0c000c0c0c000c,
-	0x4141004141410041, 0xefef00efefef00ef, 0x9393009393930093,
-	0x1919001919190019, 0x2121002121210021, 0x0e0e000e0e0e000e,
-	0x4e4e004e4e4e004e, 0x6565006565650065, 0xbdbd00bdbdbd00bd,
-	0xb8b800b8b8b800b8, 0x8f8f008f8f8f008f, 0xebeb00ebebeb00eb,
-	0xcece00cecece00ce, 0x3030003030300030, 0x5f5f005f5f5f005f,
-	0xc5c500c5c5c500c5, 0x1a1a001a1a1a001a, 0xe1e100e1e1e100e1,
-	0xcaca00cacaca00ca, 0x4747004747470047, 0x3d3d003d3d3d003d,
-	0x0101000101010001, 0xd6d600d6d6d600d6, 0x5656005656560056,
-	0x4d4d004d4d4d004d, 0x0d0d000d0d0d000d, 0x6666006666660066,
-	0xcccc00cccccc00cc, 0x2d2d002d2d2d002d, 0x1212001212120012,
-	0x2020002020200020, 0xb1b100b1b1b100b1, 0x9999009999990099,
-	0x4c4c004c4c4c004c, 0xc2c200c2c2c200c2, 0x7e7e007e7e7e007e,
-	0x0505000505050005, 0xb7b700b7b7b700b7, 0x3131003131310031,
-	0x1717001717170017, 0xd7d700d7d7d700d7, 0x5858005858580058,
-	0x6161006161610061, 0x1b1b001b1b1b001b, 0x1c1c001c1c1c001c,
-	0x0f0f000f0f0f000f, 0x1616001616160016, 0x1818001818180018,
-	0x2222002222220022, 0x4444004444440044, 0xb2b200b2b2b200b2,
-	0xb5b500b5b5b500b5, 0x9191009191910091, 0x0808000808080008,
-	0xa8a800a8a8a800a8, 0xfcfc00fcfcfc00fc, 0x5050005050500050,
-	0xd0d000d0d0d000d0, 0x7d7d007d7d7d007d, 0x8989008989890089,
-	0x9797009797970097, 0x5b5b005b5b5b005b, 0x9595009595950095,
-	0xffff00ffffff00ff, 0xd2d200d2d2d200d2, 0xc4c400c4c4c400c4,
-	0x4848004848480048, 0xf7f700f7f7f700f7, 0xdbdb00dbdbdb00db,
-	0x0303000303030003, 0xdada00dadada00da, 0x3f3f003f3f3f003f,
-	0x9494009494940094, 0x5c5c005c5c5c005c, 0x0202000202020002,
-	0x4a4a004a4a4a004a, 0x3333003333330033, 0x6767006767670067,
-	0xf3f300f3f3f300f3, 0x7f7f007f7f7f007f, 0xe2e200e2e2e200e2,
-	0x9b9b009b9b9b009b, 0x2626002626260026, 0x3737003737370037,
-	0x3b3b003b3b3b003b, 0x9696009696960096, 0x4b4b004b4b4b004b,
-	0xbebe00bebebe00be, 0x2e2e002e2e2e002e, 0x7979007979790079,
-	0x8c8c008c8c8c008c, 0x6e6e006e6e6e006e, 0x8e8e008e8e8e008e,
-	0xf5f500f5f5f500f5, 0xb6b600b6b6b600b6, 0xfdfd00fdfdfd00fd,
-	0x5959005959590059, 0x9898009898980098, 0x6a6a006a6a6a006a,
-	0x4646004646460046, 0xbaba00bababa00ba, 0x2525002525250025,
-	0x4242004242420042, 0xa2a200a2a2a200a2, 0xfafa00fafafa00fa,
-	0x0707000707070007, 0x5555005555550055, 0xeeee00eeeeee00ee,
-	0x0a0a000a0a0a000a, 0x4949004949490049, 0x6868006868680068,
-	0x3838003838380038, 0xa4a400a4a4a400a4, 0x2828002828280028,
-	0x7b7b007b7b7b007b, 0xc9c900c9c9c900c9, 0xc1c100c1c1c100c1,
-	0xe3e300e3e3e300e3, 0xf4f400f4f4f400f4, 0xc7c700c7c7c700c7,
-	0x9e9e009e9e9e009e,
+	0x7070007070700070ULL, 0x2c2c002c2c2c002cULL, 0xb3b300b3b3b300b3ULL,
+	0xc0c000c0c0c000c0ULL, 0xe4e400e4e4e400e4ULL, 0x5757005757570057ULL,
+	0xeaea00eaeaea00eaULL, 0xaeae00aeaeae00aeULL, 0x2323002323230023ULL,
+	0x6b6b006b6b6b006bULL, 0x4545004545450045ULL, 0xa5a500a5a5a500a5ULL,
+	0xeded00ededed00edULL, 0x4f4f004f4f4f004fULL, 0x1d1d001d1d1d001dULL,
+	0x9292009292920092ULL, 0x8686008686860086ULL, 0xafaf00afafaf00afULL,
+	0x7c7c007c7c7c007cULL, 0x1f1f001f1f1f001fULL, 0x3e3e003e3e3e003eULL,
+	0xdcdc00dcdcdc00dcULL, 0x5e5e005e5e5e005eULL, 0x0b0b000b0b0b000bULL,
+	0xa6a600a6a6a600a6ULL, 0x3939003939390039ULL, 0xd5d500d5d5d500d5ULL,
+	0x5d5d005d5d5d005dULL, 0xd9d900d9d9d900d9ULL, 0x5a5a005a5a5a005aULL,
+	0x5151005151510051ULL, 0x6c6c006c6c6c006cULL, 0x8b8b008b8b8b008bULL,
+	0x9a9a009a9a9a009aULL, 0xfbfb00fbfbfb00fbULL, 0xb0b000b0b0b000b0ULL,
+	0x7474007474740074ULL, 0x2b2b002b2b2b002bULL, 0xf0f000f0f0f000f0ULL,
+	0x8484008484840084ULL, 0xdfdf00dfdfdf00dfULL, 0xcbcb00cbcbcb00cbULL,
+	0x3434003434340034ULL, 0x7676007676760076ULL, 0x6d6d006d6d6d006dULL,
+	0xa9a900a9a9a900a9ULL, 0xd1d100d1d1d100d1ULL, 0x0404000404040004ULL,
+	0x1414001414140014ULL, 0x3a3a003a3a3a003aULL, 0xdede00dedede00deULL,
+	0x1111001111110011ULL, 0x3232003232320032ULL, 0x9c9c009c9c9c009cULL,
+	0x5353005353530053ULL, 0xf2f200f2f2f200f2ULL, 0xfefe00fefefe00feULL,
+	0xcfcf00cfcfcf00cfULL, 0xc3c300c3c3c300c3ULL, 0x7a7a007a7a7a007aULL,
+	0x2424002424240024ULL, 0xe8e800e8e8e800e8ULL, 0x6060006060600060ULL,
+	0x6969006969690069ULL, 0xaaaa00aaaaaa00aaULL, 0xa0a000a0a0a000a0ULL,
+	0xa1a100a1a1a100a1ULL, 0x6262006262620062ULL, 0x5454005454540054ULL,
+	0x1e1e001e1e1e001eULL, 0xe0e000e0e0e000e0ULL, 0x6464006464640064ULL,
+	0x1010001010100010ULL, 0x0000000000000000ULL, 0xa3a300a3a3a300a3ULL,
+	0x7575007575750075ULL, 0x8a8a008a8a8a008aULL, 0xe6e600e6e6e600e6ULL,
+	0x0909000909090009ULL, 0xdddd00dddddd00ddULL, 0x8787008787870087ULL,
+	0x8383008383830083ULL, 0xcdcd00cdcdcd00cdULL, 0x9090009090900090ULL,
+	0x7373007373730073ULL, 0xf6f600f6f6f600f6ULL, 0x9d9d009d9d9d009dULL,
+	0xbfbf00bfbfbf00bfULL, 0x5252005252520052ULL, 0xd8d800d8d8d800d8ULL,
+	0xc8c800c8c8c800c8ULL, 0xc6c600c6c6c600c6ULL, 0x8181008181810081ULL,
+	0x6f6f006f6f6f006fULL, 0x1313001313130013ULL, 0x6363006363630063ULL,
+	0xe9e900e9e9e900e9ULL, 0xa7a700a7a7a700a7ULL, 0x9f9f009f9f9f009fULL,
+	0xbcbc00bcbcbc00bcULL, 0x2929002929290029ULL, 0xf9f900f9f9f900f9ULL,
+	0x2f2f002f2f2f002fULL, 0xb4b400b4b4b400b4ULL, 0x7878007878780078ULL,
+	0x0606000606060006ULL, 0xe7e700e7e7e700e7ULL, 0x7171007171710071ULL,
+	0xd4d400d4d4d400d4ULL, 0xabab00ababab00abULL, 0x8888008888880088ULL,
+	0x8d8d008d8d8d008dULL, 0x7272007272720072ULL, 0xb9b900b9b9b900b9ULL,
+	0xf8f800f8f8f800f8ULL, 0xacac00acacac00acULL, 0x3636003636360036ULL,
+	0x2a2a002a2a2a002aULL, 0x3c3c003c3c3c003cULL, 0xf1f100f1f1f100f1ULL,
+	0x4040004040400040ULL, 0xd3d300d3d3d300d3ULL, 0xbbbb00bbbbbb00bbULL,
+	0x4343004343430043ULL, 0x1515001515150015ULL, 0xadad00adadad00adULL,
+	0x7777007777770077ULL, 0x8080008080800080ULL, 0x8282008282820082ULL,
+	0xecec00ececec00ecULL, 0x2727002727270027ULL, 0xe5e500e5e5e500e5ULL,
+	0x8585008585850085ULL, 0x3535003535350035ULL, 0x0c0c000c0c0c000cULL,
+	0x4141004141410041ULL, 0xefef00efefef00efULL, 0x9393009393930093ULL,
+	0x1919001919190019ULL, 0x2121002121210021ULL, 0x0e0e000e0e0e000eULL,
+	0x4e4e004e4e4e004eULL, 0x6565006565650065ULL, 0xbdbd00bdbdbd00bdULL,
+	0xb8b800b8b8b800b8ULL, 0x8f8f008f8f8f008fULL, 0xebeb00ebebeb00ebULL,
+	0xcece00cecece00ceULL, 0x3030003030300030ULL, 0x5f5f005f5f5f005fULL,
+	0xc5c500c5c5c500c5ULL, 0x1a1a001a1a1a001aULL, 0xe1e100e1e1e100e1ULL,
+	0xcaca00cacaca00caULL, 0x4747004747470047ULL, 0x3d3d003d3d3d003dULL,
+	0x0101000101010001ULL, 0xd6d600d6d6d600d6ULL, 0x5656005656560056ULL,
+	0x4d4d004d4d4d004dULL, 0x0d0d000d0d0d000dULL, 0x6666006666660066ULL,
+	0xcccc00cccccc00ccULL, 0x2d2d002d2d2d002dULL, 0x1212001212120012ULL,
+	0x2020002020200020ULL, 0xb1b100b1b1b100b1ULL, 0x9999009999990099ULL,
+	0x4c4c004c4c4c004cULL, 0xc2c200c2c2c200c2ULL, 0x7e7e007e7e7e007eULL,
+	0x0505000505050005ULL, 0xb7b700b7b7b700b7ULL, 0x3131003131310031ULL,
+	0x1717001717170017ULL, 0xd7d700d7d7d700d7ULL, 0x5858005858580058ULL,
+	0x6161006161610061ULL, 0x1b1b001b1b1b001bULL, 0x1c1c001c1c1c001cULL,
+	0x0f0f000f0f0f000fULL, 0x1616001616160016ULL, 0x1818001818180018ULL,
+	0x2222002222220022ULL, 0x4444004444440044ULL, 0xb2b200b2b2b200b2ULL,
+	0xb5b500b5b5b500b5ULL, 0x9191009191910091ULL, 0x0808000808080008ULL,
+	0xa8a800a8a8a800a8ULL, 0xfcfc00fcfcfc00fcULL, 0x5050005050500050ULL,
+	0xd0d000d0d0d000d0ULL, 0x7d7d007d7d7d007dULL, 0x8989008989890089ULL,
+	0x9797009797970097ULL, 0x5b5b005b5b5b005bULL, 0x9595009595950095ULL,
+	0xffff00ffffff00ffULL, 0xd2d200d2d2d200d2ULL, 0xc4c400c4c4c400c4ULL,
+	0x4848004848480048ULL, 0xf7f700f7f7f700f7ULL, 0xdbdb00dbdbdb00dbULL,
+	0x0303000303030003ULL, 0xdada00dadada00daULL, 0x3f3f003f3f3f003fULL,
+	0x9494009494940094ULL, 0x5c5c005c5c5c005cULL, 0x0202000202020002ULL,
+	0x4a4a004a4a4a004aULL, 0x3333003333330033ULL, 0x6767006767670067ULL,
+	0xf3f300f3f3f300f3ULL, 0x7f7f007f7f7f007fULL, 0xe2e200e2e2e200e2ULL,
+	0x9b9b009b9b9b009bULL, 0x2626002626260026ULL, 0x3737003737370037ULL,
+	0x3b3b003b3b3b003bULL, 0x9696009696960096ULL, 0x4b4b004b4b4b004bULL,
+	0xbebe00bebebe00beULL, 0x2e2e002e2e2e002eULL, 0x7979007979790079ULL,
+	0x8c8c008c8c8c008cULL, 0x6e6e006e6e6e006eULL, 0x8e8e008e8e8e008eULL,
+	0xf5f500f5f5f500f5ULL, 0xb6b600b6b6b600b6ULL, 0xfdfd00fdfdfd00fdULL,
+	0x5959005959590059ULL, 0x9898009898980098ULL, 0x6a6a006a6a6a006aULL,
+	0x4646004646460046ULL, 0xbaba00bababa00baULL, 0x2525002525250025ULL,
+	0x4242004242420042ULL, 0xa2a200a2a2a200a2ULL, 0xfafa00fafafa00faULL,
+	0x0707000707070007ULL, 0x5555005555550055ULL, 0xeeee00eeeeee00eeULL,
+	0x0a0a000a0a0a000aULL, 0x4949004949490049ULL, 0x6868006868680068ULL,
+	0x3838003838380038ULL, 0xa4a400a4a4a400a4ULL, 0x2828002828280028ULL,
+	0x7b7b007b7b7b007bULL, 0xc9c900c9c9c900c9ULL, 0xc1c100c1c1c100c1ULL,
+	0xe3e300e3e3e300e3ULL, 0xf4f400f4f4f400f4ULL, 0xc7c700c7c7c700c7ULL,
+	0x9e9e009e9e9e009eULL,
 };
 
 const u64 camellia_sp11101110[256] = {
-	0x7070700070707000, 0x8282820082828200, 0x2c2c2c002c2c2c00,
-	0xececec00ececec00, 0xb3b3b300b3b3b300, 0x2727270027272700,
-	0xc0c0c000c0c0c000, 0xe5e5e500e5e5e500, 0xe4e4e400e4e4e400,
-	0x8585850085858500, 0x5757570057575700, 0x3535350035353500,
-	0xeaeaea00eaeaea00, 0x0c0c0c000c0c0c00, 0xaeaeae00aeaeae00,
-	0x4141410041414100, 0x2323230023232300, 0xefefef00efefef00,
-	0x6b6b6b006b6b6b00, 0x9393930093939300, 0x4545450045454500,
-	0x1919190019191900, 0xa5a5a500a5a5a500, 0x2121210021212100,
-	0xededed00ededed00, 0x0e0e0e000e0e0e00, 0x4f4f4f004f4f4f00,
-	0x4e4e4e004e4e4e00, 0x1d1d1d001d1d1d00, 0x6565650065656500,
-	0x9292920092929200, 0xbdbdbd00bdbdbd00, 0x8686860086868600,
-	0xb8b8b800b8b8b800, 0xafafaf00afafaf00, 0x8f8f8f008f8f8f00,
-	0x7c7c7c007c7c7c00, 0xebebeb00ebebeb00, 0x1f1f1f001f1f1f00,
-	0xcecece00cecece00, 0x3e3e3e003e3e3e00, 0x3030300030303000,
-	0xdcdcdc00dcdcdc00, 0x5f5f5f005f5f5f00, 0x5e5e5e005e5e5e00,
-	0xc5c5c500c5c5c500, 0x0b0b0b000b0b0b00, 0x1a1a1a001a1a1a00,
-	0xa6a6a600a6a6a600, 0xe1e1e100e1e1e100, 0x3939390039393900,
-	0xcacaca00cacaca00, 0xd5d5d500d5d5d500, 0x4747470047474700,
-	0x5d5d5d005d5d5d00, 0x3d3d3d003d3d3d00, 0xd9d9d900d9d9d900,
-	0x0101010001010100, 0x5a5a5a005a5a5a00, 0xd6d6d600d6d6d600,
-	0x5151510051515100, 0x5656560056565600, 0x6c6c6c006c6c6c00,
-	0x4d4d4d004d4d4d00, 0x8b8b8b008b8b8b00, 0x0d0d0d000d0d0d00,
-	0x9a9a9a009a9a9a00, 0x6666660066666600, 0xfbfbfb00fbfbfb00,
-	0xcccccc00cccccc00, 0xb0b0b000b0b0b000, 0x2d2d2d002d2d2d00,
-	0x7474740074747400, 0x1212120012121200, 0x2b2b2b002b2b2b00,
-	0x2020200020202000, 0xf0f0f000f0f0f000, 0xb1b1b100b1b1b100,
-	0x8484840084848400, 0x9999990099999900, 0xdfdfdf00dfdfdf00,
-	0x4c4c4c004c4c4c00, 0xcbcbcb00cbcbcb00, 0xc2c2c200c2c2c200,
-	0x3434340034343400, 0x7e7e7e007e7e7e00, 0x7676760076767600,
-	0x0505050005050500, 0x6d6d6d006d6d6d00, 0xb7b7b700b7b7b700,
-	0xa9a9a900a9a9a900, 0x3131310031313100, 0xd1d1d100d1d1d100,
-	0x1717170017171700, 0x0404040004040400, 0xd7d7d700d7d7d700,
-	0x1414140014141400, 0x5858580058585800, 0x3a3a3a003a3a3a00,
-	0x6161610061616100, 0xdedede00dedede00, 0x1b1b1b001b1b1b00,
-	0x1111110011111100, 0x1c1c1c001c1c1c00, 0x3232320032323200,
-	0x0f0f0f000f0f0f00, 0x9c9c9c009c9c9c00, 0x1616160016161600,
-	0x5353530053535300, 0x1818180018181800, 0xf2f2f200f2f2f200,
-	0x2222220022222200, 0xfefefe00fefefe00, 0x4444440044444400,
-	0xcfcfcf00cfcfcf00, 0xb2b2b200b2b2b200, 0xc3c3c300c3c3c300,
-	0xb5b5b500b5b5b500, 0x7a7a7a007a7a7a00, 0x9191910091919100,
-	0x2424240024242400, 0x0808080008080800, 0xe8e8e800e8e8e800,
-	0xa8a8a800a8a8a800, 0x6060600060606000, 0xfcfcfc00fcfcfc00,
-	0x6969690069696900, 0x5050500050505000, 0xaaaaaa00aaaaaa00,
-	0xd0d0d000d0d0d000, 0xa0a0a000a0a0a000, 0x7d7d7d007d7d7d00,
-	0xa1a1a100a1a1a100, 0x8989890089898900, 0x6262620062626200,
-	0x9797970097979700, 0x5454540054545400, 0x5b5b5b005b5b5b00,
-	0x1e1e1e001e1e1e00, 0x9595950095959500, 0xe0e0e000e0e0e000,
-	0xffffff00ffffff00, 0x6464640064646400, 0xd2d2d200d2d2d200,
-	0x1010100010101000, 0xc4c4c400c4c4c400, 0x0000000000000000,
-	0x4848480048484800, 0xa3a3a300a3a3a300, 0xf7f7f700f7f7f700,
-	0x7575750075757500, 0xdbdbdb00dbdbdb00, 0x8a8a8a008a8a8a00,
-	0x0303030003030300, 0xe6e6e600e6e6e600, 0xdadada00dadada00,
-	0x0909090009090900, 0x3f3f3f003f3f3f00, 0xdddddd00dddddd00,
-	0x9494940094949400, 0x8787870087878700, 0x5c5c5c005c5c5c00,
-	0x8383830083838300, 0x0202020002020200, 0xcdcdcd00cdcdcd00,
-	0x4a4a4a004a4a4a00, 0x9090900090909000, 0x3333330033333300,
-	0x7373730073737300, 0x6767670067676700, 0xf6f6f600f6f6f600,
-	0xf3f3f300f3f3f300, 0x9d9d9d009d9d9d00, 0x7f7f7f007f7f7f00,
-	0xbfbfbf00bfbfbf00, 0xe2e2e200e2e2e200, 0x5252520052525200,
-	0x9b9b9b009b9b9b00, 0xd8d8d800d8d8d800, 0x2626260026262600,
-	0xc8c8c800c8c8c800, 0x3737370037373700, 0xc6c6c600c6c6c600,
-	0x3b3b3b003b3b3b00, 0x8181810081818100, 0x9696960096969600,
-	0x6f6f6f006f6f6f00, 0x4b4b4b004b4b4b00, 0x1313130013131300,
-	0xbebebe00bebebe00, 0x6363630063636300, 0x2e2e2e002e2e2e00,
-	0xe9e9e900e9e9e900, 0x7979790079797900, 0xa7a7a700a7a7a700,
-	0x8c8c8c008c8c8c00, 0x9f9f9f009f9f9f00, 0x6e6e6e006e6e6e00,
-	0xbcbcbc00bcbcbc00, 0x8e8e8e008e8e8e00, 0x2929290029292900,
-	0xf5f5f500f5f5f500, 0xf9f9f900f9f9f900, 0xb6b6b600b6b6b600,
-	0x2f2f2f002f2f2f00, 0xfdfdfd00fdfdfd00, 0xb4b4b400b4b4b400,
-	0x5959590059595900, 0x7878780078787800, 0x9898980098989800,
-	0x0606060006060600, 0x6a6a6a006a6a6a00, 0xe7e7e700e7e7e700,
-	0x4646460046464600, 0x7171710071717100, 0xbababa00bababa00,
-	0xd4d4d400d4d4d400, 0x2525250025252500, 0xababab00ababab00,
-	0x4242420042424200, 0x8888880088888800, 0xa2a2a200a2a2a200,
-	0x8d8d8d008d8d8d00, 0xfafafa00fafafa00, 0x7272720072727200,
-	0x0707070007070700, 0xb9b9b900b9b9b900, 0x5555550055555500,
-	0xf8f8f800f8f8f800, 0xeeeeee00eeeeee00, 0xacacac00acacac00,
-	0x0a0a0a000a0a0a00, 0x3636360036363600, 0x4949490049494900,
-	0x2a2a2a002a2a2a00, 0x6868680068686800, 0x3c3c3c003c3c3c00,
-	0x3838380038383800, 0xf1f1f100f1f1f100, 0xa4a4a400a4a4a400,
-	0x4040400040404000, 0x2828280028282800, 0xd3d3d300d3d3d300,
-	0x7b7b7b007b7b7b00, 0xbbbbbb00bbbbbb00, 0xc9c9c900c9c9c900,
-	0x4343430043434300, 0xc1c1c100c1c1c100, 0x1515150015151500,
-	0xe3e3e300e3e3e300, 0xadadad00adadad00, 0xf4f4f400f4f4f400,
-	0x7777770077777700, 0xc7c7c700c7c7c700, 0x8080800080808000,
-	0x9e9e9e009e9e9e00,
+	0x7070700070707000ULL, 0x8282820082828200ULL, 0x2c2c2c002c2c2c00ULL,
+	0xececec00ececec00ULL, 0xb3b3b300b3b3b300ULL, 0x2727270027272700ULL,
+	0xc0c0c000c0c0c000ULL, 0xe5e5e500e5e5e500ULL, 0xe4e4e400e4e4e400ULL,
+	0x8585850085858500ULL, 0x5757570057575700ULL, 0x3535350035353500ULL,
+	0xeaeaea00eaeaea00ULL, 0x0c0c0c000c0c0c00ULL, 0xaeaeae00aeaeae00ULL,
+	0x4141410041414100ULL, 0x2323230023232300ULL, 0xefefef00efefef00ULL,
+	0x6b6b6b006b6b6b00ULL, 0x9393930093939300ULL, 0x4545450045454500ULL,
+	0x1919190019191900ULL, 0xa5a5a500a5a5a500ULL, 0x2121210021212100ULL,
+	0xededed00ededed00ULL, 0x0e0e0e000e0e0e00ULL, 0x4f4f4f004f4f4f00ULL,
+	0x4e4e4e004e4e4e00ULL, 0x1d1d1d001d1d1d00ULL, 0x6565650065656500ULL,
+	0x9292920092929200ULL, 0xbdbdbd00bdbdbd00ULL, 0x8686860086868600ULL,
+	0xb8b8b800b8b8b800ULL, 0xafafaf00afafaf00ULL, 0x8f8f8f008f8f8f00ULL,
+	0x7c7c7c007c7c7c00ULL, 0xebebeb00ebebeb00ULL, 0x1f1f1f001f1f1f00ULL,
+	0xcecece00cecece00ULL, 0x3e3e3e003e3e3e00ULL, 0x3030300030303000ULL,
+	0xdcdcdc00dcdcdc00ULL, 0x5f5f5f005f5f5f00ULL, 0x5e5e5e005e5e5e00ULL,
+	0xc5c5c500c5c5c500ULL, 0x0b0b0b000b0b0b00ULL, 0x1a1a1a001a1a1a00ULL,
+	0xa6a6a600a6a6a600ULL, 0xe1e1e100e1e1e100ULL, 0x3939390039393900ULL,
+	0xcacaca00cacaca00ULL, 0xd5d5d500d5d5d500ULL, 0x4747470047474700ULL,
+	0x5d5d5d005d5d5d00ULL, 0x3d3d3d003d3d3d00ULL, 0xd9d9d900d9d9d900ULL,
+	0x0101010001010100ULL, 0x5a5a5a005a5a5a00ULL, 0xd6d6d600d6d6d600ULL,
+	0x5151510051515100ULL, 0x5656560056565600ULL, 0x6c6c6c006c6c6c00ULL,
+	0x4d4d4d004d4d4d00ULL, 0x8b8b8b008b8b8b00ULL, 0x0d0d0d000d0d0d00ULL,
+	0x9a9a9a009a9a9a00ULL, 0x6666660066666600ULL, 0xfbfbfb00fbfbfb00ULL,
+	0xcccccc00cccccc00ULL, 0xb0b0b000b0b0b000ULL, 0x2d2d2d002d2d2d00ULL,
+	0x7474740074747400ULL, 0x1212120012121200ULL, 0x2b2b2b002b2b2b00ULL,
+	0x2020200020202000ULL, 0xf0f0f000f0f0f000ULL, 0xb1b1b100b1b1b100ULL,
+	0x8484840084848400ULL, 0x9999990099999900ULL, 0xdfdfdf00dfdfdf00ULL,
+	0x4c4c4c004c4c4c00ULL, 0xcbcbcb00cbcbcb00ULL, 0xc2c2c200c2c2c200ULL,
+	0x3434340034343400ULL, 0x7e7e7e007e7e7e00ULL, 0x7676760076767600ULL,
+	0x0505050005050500ULL, 0x6d6d6d006d6d6d00ULL, 0xb7b7b700b7b7b700ULL,
+	0xa9a9a900a9a9a900ULL, 0x3131310031313100ULL, 0xd1d1d100d1d1d100ULL,
+	0x1717170017171700ULL, 0x0404040004040400ULL, 0xd7d7d700d7d7d700ULL,
+	0x1414140014141400ULL, 0x5858580058585800ULL, 0x3a3a3a003a3a3a00ULL,
+	0x6161610061616100ULL, 0xdedede00dedede00ULL, 0x1b1b1b001b1b1b00ULL,
+	0x1111110011111100ULL, 0x1c1c1c001c1c1c00ULL, 0x3232320032323200ULL,
+	0x0f0f0f000f0f0f00ULL, 0x9c9c9c009c9c9c00ULL, 0x1616160016161600ULL,
+	0x5353530053535300ULL, 0x1818180018181800ULL, 0xf2f2f200f2f2f200ULL,
+	0x2222220022222200ULL, 0xfefefe00fefefe00ULL, 0x4444440044444400ULL,
+	0xcfcfcf00cfcfcf00ULL, 0xb2b2b200b2b2b200ULL, 0xc3c3c300c3c3c300ULL,
+	0xb5b5b500b5b5b500ULL, 0x7a7a7a007a7a7a00ULL, 0x9191910091919100ULL,
+	0x2424240024242400ULL, 0x0808080008080800ULL, 0xe8e8e800e8e8e800ULL,
+	0xa8a8a800a8a8a800ULL, 0x6060600060606000ULL, 0xfcfcfc00fcfcfc00ULL,
+	0x6969690069696900ULL, 0x5050500050505000ULL, 0xaaaaaa00aaaaaa00ULL,
+	0xd0d0d000d0d0d000ULL, 0xa0a0a000a0a0a000ULL, 0x7d7d7d007d7d7d00ULL,
+	0xa1a1a100a1a1a100ULL, 0x8989890089898900ULL, 0x6262620062626200ULL,
+	0x9797970097979700ULL, 0x5454540054545400ULL, 0x5b5b5b005b5b5b00ULL,
+	0x1e1e1e001e1e1e00ULL, 0x9595950095959500ULL, 0xe0e0e000e0e0e000ULL,
+	0xffffff00ffffff00ULL, 0x6464640064646400ULL, 0xd2d2d200d2d2d200ULL,
+	0x1010100010101000ULL, 0xc4c4c400c4c4c400ULL, 0x0000000000000000ULL,
+	0x4848480048484800ULL, 0xa3a3a300a3a3a300ULL, 0xf7f7f700f7f7f700ULL,
+	0x7575750075757500ULL, 0xdbdbdb00dbdbdb00ULL, 0x8a8a8a008a8a8a00ULL,
+	0x0303030003030300ULL, 0xe6e6e600e6e6e600ULL, 0xdadada00dadada00ULL,
+	0x0909090009090900ULL, 0x3f3f3f003f3f3f00ULL, 0xdddddd00dddddd00ULL,
+	0x9494940094949400ULL, 0x8787870087878700ULL, 0x5c5c5c005c5c5c00ULL,
+	0x8383830083838300ULL, 0x0202020002020200ULL, 0xcdcdcd00cdcdcd00ULL,
+	0x4a4a4a004a4a4a00ULL, 0x9090900090909000ULL, 0x3333330033333300ULL,
+	0x7373730073737300ULL, 0x6767670067676700ULL, 0xf6f6f600f6f6f600ULL,
+	0xf3f3f300f3f3f300ULL, 0x9d9d9d009d9d9d00ULL, 0x7f7f7f007f7f7f00ULL,
+	0xbfbfbf00bfbfbf00ULL, 0xe2e2e200e2e2e200ULL, 0x5252520052525200ULL,
+	0x9b9b9b009b9b9b00ULL, 0xd8d8d800d8d8d800ULL, 0x2626260026262600ULL,
+	0xc8c8c800c8c8c800ULL, 0x3737370037373700ULL, 0xc6c6c600c6c6c600ULL,
+	0x3b3b3b003b3b3b00ULL, 0x8181810081818100ULL, 0x9696960096969600ULL,
+	0x6f6f6f006f6f6f00ULL, 0x4b4b4b004b4b4b00ULL, 0x1313130013131300ULL,
+	0xbebebe00bebebe00ULL, 0x6363630063636300ULL, 0x2e2e2e002e2e2e00ULL,
+	0xe9e9e900e9e9e900ULL, 0x7979790079797900ULL, 0xa7a7a700a7a7a700ULL,
+	0x8c8c8c008c8c8c00ULL, 0x9f9f9f009f9f9f00ULL, 0x6e6e6e006e6e6e00ULL,
+	0xbcbcbc00bcbcbc00ULL, 0x8e8e8e008e8e8e00ULL, 0x2929290029292900ULL,
+	0xf5f5f500f5f5f500ULL, 0xf9f9f900f9f9f900ULL, 0xb6b6b600b6b6b600ULL,
+	0x2f2f2f002f2f2f00ULL, 0xfdfdfd00fdfdfd00ULL, 0xb4b4b400b4b4b400ULL,
+	0x5959590059595900ULL, 0x7878780078787800ULL, 0x9898980098989800ULL,
+	0x0606060006060600ULL, 0x6a6a6a006a6a6a00ULL, 0xe7e7e700e7e7e700ULL,
+	0x4646460046464600ULL, 0x7171710071717100ULL, 0xbababa00bababa00ULL,
+	0xd4d4d400d4d4d400ULL, 0x2525250025252500ULL, 0xababab00ababab00ULL,
+	0x4242420042424200ULL, 0x8888880088888800ULL, 0xa2a2a200a2a2a200ULL,
+	0x8d8d8d008d8d8d00ULL, 0xfafafa00fafafa00ULL, 0x7272720072727200ULL,
+	0x0707070007070700ULL, 0xb9b9b900b9b9b900ULL, 0x5555550055555500ULL,
+	0xf8f8f800f8f8f800ULL, 0xeeeeee00eeeeee00ULL, 0xacacac00acacac00ULL,
+	0x0a0a0a000a0a0a00ULL, 0x3636360036363600ULL, 0x4949490049494900ULL,
+	0x2a2a2a002a2a2a00ULL, 0x6868680068686800ULL, 0x3c3c3c003c3c3c00ULL,
+	0x3838380038383800ULL, 0xf1f1f100f1f1f100ULL, 0xa4a4a400a4a4a400ULL,
+	0x4040400040404000ULL, 0x2828280028282800ULL, 0xd3d3d300d3d3d300ULL,
+	0x7b7b7b007b7b7b00ULL, 0xbbbbbb00bbbbbb00ULL, 0xc9c9c900c9c9c900ULL,
+	0x4343430043434300ULL, 0xc1c1c100c1c1c100ULL, 0x1515150015151500ULL,
+	0xe3e3e300e3e3e300ULL, 0xadadad00adadad00ULL, 0xf4f4f400f4f4f400ULL,
+	0x7777770077777700ULL, 0xc7c7c700c7c7c700ULL, 0x8080800080808000ULL,
+	0x9e9e9e009e9e9e00ULL,
 };
 
 /* key constants */
@@ -1601,7 +1601,6 @@ static struct crypto_alg camellia_algs[6] = { {
 	.cra_ctxsize		= sizeof(struct camellia_ctx),
 	.cra_alignmask		= 0,
 	.cra_module		= THIS_MODULE,
-	.cra_list		= LIST_HEAD_INIT(camellia_algs[0].cra_list),
 	.cra_u			= {
 		.cipher = {
 			.cia_min_keysize = CAMELLIA_MIN_KEY_SIZE,
@@ -1621,7 +1620,6 @@ static struct crypto_alg camellia_algs[6] = { {
 	.cra_alignmask		= 0,
 	.cra_type		= &crypto_blkcipher_type,
 	.cra_module		= THIS_MODULE,
-	.cra_list		= LIST_HEAD_INIT(camellia_algs[1].cra_list),
 	.cra_u = {
 		.blkcipher = {
 			.min_keysize	= CAMELLIA_MIN_KEY_SIZE,
@@ -1641,7 +1639,6 @@ static struct crypto_alg camellia_algs[6] = { {
 	.cra_alignmask		= 0,
 	.cra_type		= &crypto_blkcipher_type,
 	.cra_module		= THIS_MODULE,
-	.cra_list		= LIST_HEAD_INIT(camellia_algs[2].cra_list),
 	.cra_u = {
 		.blkcipher = {
 			.min_keysize	= CAMELLIA_MIN_KEY_SIZE,
@@ -1662,7 +1659,6 @@ static struct crypto_alg camellia_algs[6] = { {
 	.cra_alignmask		= 0,
 	.cra_type		= &crypto_blkcipher_type,
 	.cra_module		= THIS_MODULE,
-	.cra_list		= LIST_HEAD_INIT(camellia_algs[3].cra_list),
 	.cra_u = {
 		.blkcipher = {
 			.min_keysize	= CAMELLIA_MIN_KEY_SIZE,
@@ -1683,7 +1679,6 @@ static struct crypto_alg camellia_algs[6] = { {
 	.cra_alignmask		= 0,
 	.cra_type		= &crypto_blkcipher_type,
 	.cra_module		= THIS_MODULE,
-	.cra_list		= LIST_HEAD_INIT(camellia_algs[4].cra_list),
 	.cra_exit		= lrw_exit_tfm,
 	.cra_u = {
 		.blkcipher = {
@@ -1707,7 +1702,6 @@ static struct crypto_alg camellia_algs[6] = { {
 	.cra_alignmask		= 0,
 	.cra_type		= &crypto_blkcipher_type,
 	.cra_module		= THIS_MODULE,
-	.cra_list		= LIST_HEAD_INIT(camellia_algs[5].cra_list),
 	.cra_u = {
 		.blkcipher = {
 			.min_keysize	= CAMELLIA_MIN_KEY_SIZE * 2,
diff --git a/arch/x86/crypto/cast5-avx-x86_64-asm_64.S b/arch/x86/crypto/cast5-avx-x86_64-asm_64.S
new file mode 100644
index 0000000..a41a3aa
--- /dev/null
+++ b/arch/x86/crypto/cast5-avx-x86_64-asm_64.S
@@ -0,0 +1,376 @@
+/*
+ * Cast5 Cipher 16-way parallel algorithm (AVX/x86_64)
+ *
+ * Copyright (C) 2012 Johannes Goetzfried
+ *     <Johannes.Goetzfried@informatik.stud.uni-erlangen.de>
+ *
+ * Copyright © 2012 Jussi Kivilinna <jussi.kivilinna@mbnet.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., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+ * USA
+ *
+ */
+
+.file "cast5-avx-x86_64-asm_64.S"
+
+.extern cast5_s1
+.extern cast5_s2
+.extern cast5_s3
+.extern cast5_s4
+
+/* structure of crypto context */
+#define km	0
+#define kr	(16*4)
+#define rr	((16*4)+16)
+
+/* s-boxes */
+#define s1	cast5_s1
+#define s2	cast5_s2
+#define s3	cast5_s3
+#define s4	cast5_s4
+
+/**********************************************************************
+  16-way AVX cast5
+ **********************************************************************/
+#define CTX %rdi
+
+#define RL1 %xmm0
+#define RR1 %xmm1
+#define RL2 %xmm2
+#define RR2 %xmm3
+#define RL3 %xmm4
+#define RR3 %xmm5
+#define RL4 %xmm6
+#define RR4 %xmm7
+
+#define RX %xmm8
+
+#define RKM  %xmm9
+#define RKR  %xmm10
+#define RKRF %xmm11
+#define RKRR %xmm12
+
+#define R32  %xmm13
+#define R1ST %xmm14
+
+#define RTMP %xmm15
+
+#define RID1  %rbp
+#define RID1d %ebp
+#define RID2  %rsi
+#define RID2d %esi
+
+#define RGI1   %rdx
+#define RGI1bl %dl
+#define RGI1bh %dh
+#define RGI2   %rcx
+#define RGI2bl %cl
+#define RGI2bh %ch
+
+#define RGI3   %rax
+#define RGI3bl %al
+#define RGI3bh %ah
+#define RGI4   %rbx
+#define RGI4bl %bl
+#define RGI4bh %bh
+
+#define RFS1  %r8
+#define RFS1d %r8d
+#define RFS2  %r9
+#define RFS2d %r9d
+#define RFS3  %r10
+#define RFS3d %r10d
+
+
+#define lookup_32bit(src, dst, op1, op2, op3, interleave_op, il_reg) \
+	movzbl		src ## bh,     RID1d;    \
+	movzbl		src ## bl,     RID2d;    \
+	shrq $16,	src;                     \
+	movl		s1(, RID1, 4), dst ## d; \
+	op1		s2(, RID2, 4), dst ## d; \
+	movzbl		src ## bh,     RID1d;    \
+	movzbl		src ## bl,     RID2d;    \
+	interleave_op(il_reg);			 \
+	op2		s3(, RID1, 4), dst ## d; \
+	op3		s4(, RID2, 4), dst ## d;
+
+#define dummy(d) /* do nothing */
+
+#define shr_next(reg) \
+	shrq $16,	reg;
+
+#define F_head(a, x, gi1, gi2, op0) \
+	op0	a,	RKM,  x;                 \
+	vpslld	RKRF,	x,    RTMP;              \
+	vpsrld	RKRR,	x,    x;                 \
+	vpor	RTMP,	x,    x;                 \
+	\
+	vmovq		x,    gi1;               \
+	vpextrq $1,	x,    gi2;
+
+#define F_tail(a, x, gi1, gi2, op1, op2, op3) \
+	lookup_32bit(##gi1, RFS1, op1, op2, op3, shr_next, ##gi1); \
+	lookup_32bit(##gi2, RFS3, op1, op2, op3, shr_next, ##gi2); \
+	\
+	lookup_32bit(##gi1, RFS2, op1, op2, op3, dummy, none);     \
+	shlq $32,	RFS2;                                      \
+	orq		RFS1, RFS2;                                \
+	lookup_32bit(##gi2, RFS1, op1, op2, op3, dummy, none);     \
+	shlq $32,	RFS1;                                      \
+	orq		RFS1, RFS3;                                \
+	\
+	vmovq		RFS2, x;                                   \
+	vpinsrq $1,	RFS3, x, x;
+
+#define F_2(a1, b1, a2, b2, op0, op1, op2, op3) \
+	F_head(b1, RX, RGI1, RGI2, op0);              \
+	F_head(b2, RX, RGI3, RGI4, op0);              \
+	\
+	F_tail(b1, RX, RGI1, RGI2, op1, op2, op3);    \
+	F_tail(b2, RTMP, RGI3, RGI4, op1, op2, op3);  \
+	\
+	vpxor		a1, RX,   a1;                 \
+	vpxor		a2, RTMP, a2;
+
+#define F1_2(a1, b1, a2, b2) \
+	F_2(a1, b1, a2, b2, vpaddd, xorl, subl, addl)
+#define F2_2(a1, b1, a2, b2) \
+	F_2(a1, b1, a2, b2, vpxor, subl, addl, xorl)
+#define F3_2(a1, b1, a2, b2) \
+	F_2(a1, b1, a2, b2, vpsubd, addl, xorl, subl)
+
+#define subround(a1, b1, a2, b2, f) \
+	F ## f ## _2(a1, b1, a2, b2);
+
+#define round(l, r, n, f) \
+	vbroadcastss 	(km+(4*n))(CTX), RKM;        \
+	vpand		R1ST,            RKR,  RKRF; \
+	vpsubq		RKRF,            R32,  RKRR; \
+	vpsrldq $1,	RKR,             RKR;        \
+	subround(l ## 1, r ## 1, l ## 2, r ## 2, f); \
+	subround(l ## 3, r ## 3, l ## 4, r ## 4, f);
+
+#define enc_preload_rkr() \
+	vbroadcastss	.L16_mask,                RKR;      \
+	/* add 16-bit rotation to key rotations (mod 32) */ \
+	vpxor		kr(CTX),                  RKR, RKR;
+
+#define dec_preload_rkr() \
+	vbroadcastss	.L16_mask,                RKR;      \
+	/* add 16-bit rotation to key rotations (mod 32) */ \
+	vpxor		kr(CTX),                  RKR, RKR; \
+	vpshufb		.Lbswap128_mask,          RKR, RKR;
+
+#define transpose_2x4(x0, x1, t0, t1) \
+	vpunpckldq		x1, x0, t0; \
+	vpunpckhdq		x1, x0, t1; \
+	\
+	vpunpcklqdq		t1, t0, x0; \
+	vpunpckhqdq		t1, t0, x1;
+
+#define inpack_blocks(in, x0, x1, t0, t1, rmask) \
+	vmovdqu (0*4*4)(in),	x0; \
+	vmovdqu (1*4*4)(in),	x1; \
+	vpshufb rmask, 	x0,	x0; \
+	vpshufb rmask, 	x1,	x1; \
+	\
+	transpose_2x4(x0, x1, t0, t1)
+
+#define outunpack_blocks(out, x0, x1, t0, t1, rmask) \
+	transpose_2x4(x0, x1, t0, t1) \
+	\
+	vpshufb rmask,	x0, x0;           \
+	vpshufb rmask,	x1, x1;           \
+	vmovdqu 	x0, (0*4*4)(out); \
+	vmovdqu		x1, (1*4*4)(out);
+
+#define outunpack_xor_blocks(out, x0, x1, t0, t1, rmask) \
+	transpose_2x4(x0, x1, t0, t1) \
+	\
+	vpshufb rmask,	x0, x0;               \
+	vpshufb rmask,	x1, x1;               \
+	vpxor		(0*4*4)(out), x0, x0; \
+	vmovdqu 	x0, (0*4*4)(out);     \
+	vpxor		(1*4*4)(out), x1, x1; \
+	vmovdqu	        x1, (1*4*4)(out);
+
+.data
+
+.align 16
+.Lbswap_mask:
+	.byte 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12
+.Lbswap128_mask:
+	.byte 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
+.L16_mask:
+	.byte 16, 16, 16, 16
+.L32_mask:
+	.byte 32, 0, 0, 0
+.Lfirst_mask:
+	.byte 0x1f, 0, 0, 0
+
+.text
+
+.align 16
+.global __cast5_enc_blk_16way
+.type   __cast5_enc_blk_16way,@function;
+
+__cast5_enc_blk_16way:
+	/* input:
+	 *	%rdi: ctx, CTX
+	 *	%rsi: dst
+	 *	%rdx: src
+	 *	%rcx: bool, if true: xor output
+	 */
+
+	pushq %rbp;
+	pushq %rbx;
+	pushq %rcx;
+
+	vmovdqa .Lbswap_mask, RKM;
+	vmovd .Lfirst_mask, R1ST;
+	vmovd .L32_mask, R32;
+	enc_preload_rkr();
+
+	leaq 1*(2*4*4)(%rdx), %rax;
+	inpack_blocks(%rdx, RL1, RR1, RTMP, RX, RKM);
+	inpack_blocks(%rax, RL2, RR2, RTMP, RX, RKM);
+	leaq 2*(2*4*4)(%rdx), %rax;
+	inpack_blocks(%rax, RL3, RR3, RTMP, RX, RKM);
+	leaq 3*(2*4*4)(%rdx), %rax;
+	inpack_blocks(%rax, RL4, RR4, RTMP, RX, RKM);
+
+	movq %rsi, %r11;
+
+	round(RL, RR, 0, 1);
+	round(RR, RL, 1, 2);
+	round(RL, RR, 2, 3);
+	round(RR, RL, 3, 1);
+	round(RL, RR, 4, 2);
+	round(RR, RL, 5, 3);
+	round(RL, RR, 6, 1);
+	round(RR, RL, 7, 2);
+	round(RL, RR, 8, 3);
+	round(RR, RL, 9, 1);
+	round(RL, RR, 10, 2);
+	round(RR, RL, 11, 3);
+
+	movzbl rr(CTX), %eax;
+	testl %eax, %eax;
+	jnz __skip_enc;
+
+	round(RL, RR, 12, 1);
+	round(RR, RL, 13, 2);
+	round(RL, RR, 14, 3);
+	round(RR, RL, 15, 1);
+
+__skip_enc:
+	popq %rcx;
+	popq %rbx;
+	popq %rbp;
+
+	vmovdqa .Lbswap_mask, RKM;
+	leaq 1*(2*4*4)(%r11), %rax;
+
+	testb %cl, %cl;
+	jnz __enc_xor16;
+
+	outunpack_blocks(%r11, RR1, RL1, RTMP, RX, RKM);
+	outunpack_blocks(%rax, RR2, RL2, RTMP, RX, RKM);
+	leaq 2*(2*4*4)(%r11), %rax;
+	outunpack_blocks(%rax, RR3, RL3, RTMP, RX, RKM);
+	leaq 3*(2*4*4)(%r11), %rax;
+	outunpack_blocks(%rax, RR4, RL4, RTMP, RX, RKM);
+
+	ret;
+
+__enc_xor16:
+	outunpack_xor_blocks(%r11, RR1, RL1, RTMP, RX, RKM);
+	outunpack_xor_blocks(%rax, RR2, RL2, RTMP, RX, RKM);
+	leaq 2*(2*4*4)(%r11), %rax;
+	outunpack_xor_blocks(%rax, RR3, RL3, RTMP, RX, RKM);
+	leaq 3*(2*4*4)(%r11), %rax;
+	outunpack_xor_blocks(%rax, RR4, RL4, RTMP, RX, RKM);
+
+	ret;
+
+.align 16
+.global cast5_dec_blk_16way
+.type   cast5_dec_blk_16way,@function;
+
+cast5_dec_blk_16way:
+	/* input:
+	 *	%rdi: ctx, CTX
+	 *	%rsi: dst
+	 *	%rdx: src
+	 */
+
+	pushq %rbp;
+	pushq %rbx;
+
+	vmovdqa .Lbswap_mask, RKM;
+	vmovd .Lfirst_mask, R1ST;
+	vmovd .L32_mask, R32;
+	dec_preload_rkr();
+
+	leaq 1*(2*4*4)(%rdx), %rax;
+	inpack_blocks(%rdx, RL1, RR1, RTMP, RX, RKM);
+	inpack_blocks(%rax, RL2, RR2, RTMP, RX, RKM);
+	leaq 2*(2*4*4)(%rdx), %rax;
+	inpack_blocks(%rax, RL3, RR3, RTMP, RX, RKM);
+	leaq 3*(2*4*4)(%rdx), %rax;
+	inpack_blocks(%rax, RL4, RR4, RTMP, RX, RKM);
+
+	movq %rsi, %r11;
+
+	movzbl rr(CTX), %eax;
+	testl %eax, %eax;
+	jnz __skip_dec;
+
+	round(RL, RR, 15, 1);
+	round(RR, RL, 14, 3);
+	round(RL, RR, 13, 2);
+	round(RR, RL, 12, 1);
+
+__dec_tail:
+	round(RL, RR, 11, 3);
+	round(RR, RL, 10, 2);
+	round(RL, RR, 9, 1);
+	round(RR, RL, 8, 3);
+	round(RL, RR, 7, 2);
+	round(RR, RL, 6, 1);
+	round(RL, RR, 5, 3);
+	round(RR, RL, 4, 2);
+	round(RL, RR, 3, 1);
+	round(RR, RL, 2, 3);
+	round(RL, RR, 1, 2);
+	round(RR, RL, 0, 1);
+
+	vmovdqa .Lbswap_mask, RKM;
+	popq %rbx;
+	popq %rbp;
+
+	leaq 1*(2*4*4)(%r11), %rax;
+	outunpack_blocks(%r11, RR1, RL1, RTMP, RX, RKM);
+	outunpack_blocks(%rax, RR2, RL2, RTMP, RX, RKM);
+	leaq 2*(2*4*4)(%r11), %rax;
+	outunpack_blocks(%rax, RR3, RL3, RTMP, RX, RKM);
+	leaq 3*(2*4*4)(%r11), %rax;
+	outunpack_blocks(%rax, RR4, RL4, RTMP, RX, RKM);
+
+	ret;
+
+__skip_dec:
+	vpsrldq $4, RKR, RKR;
+	jmp __dec_tail;
diff --git a/arch/x86/crypto/cast5_avx_glue.c b/arch/x86/crypto/cast5_avx_glue.c
new file mode 100644
index 0000000..445aab0
--- /dev/null
+++ b/arch/x86/crypto/cast5_avx_glue.c
@@ -0,0 +1,530 @@
+/*
+ * Glue Code for the AVX assembler implemention of the Cast5 Cipher
+ *
+ * Copyright (C) 2012 Johannes Goetzfried
+ *     <Johannes.Goetzfried@informatik.stud.uni-erlangen.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., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+ * USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/hardirq.h>
+#include <linux/types.h>
+#include <linux/crypto.h>
+#include <linux/err.h>
+#include <crypto/algapi.h>
+#include <crypto/cast5.h>
+#include <crypto/cryptd.h>
+#include <crypto/ctr.h>
+#include <asm/xcr.h>
+#include <asm/xsave.h>
+#include <asm/crypto/ablk_helper.h>
+#include <asm/crypto/glue_helper.h>
+
+#define CAST5_PARALLEL_BLOCKS 16
+
+asmlinkage void __cast5_enc_blk_16way(struct cast5_ctx *ctx, u8 *dst,
+				      const u8 *src, bool xor);
+asmlinkage void cast5_dec_blk_16way(struct cast5_ctx *ctx, u8 *dst,
+				    const u8 *src);
+
+static inline void cast5_enc_blk_xway(struct cast5_ctx *ctx, u8 *dst,
+				      const u8 *src)
+{
+	__cast5_enc_blk_16way(ctx, dst, src, false);
+}
+
+static inline void cast5_enc_blk_xway_xor(struct cast5_ctx *ctx, u8 *dst,
+					  const u8 *src)
+{
+	__cast5_enc_blk_16way(ctx, dst, src, true);
+}
+
+static inline void cast5_dec_blk_xway(struct cast5_ctx *ctx, u8 *dst,
+				      const u8 *src)
+{
+	cast5_dec_blk_16way(ctx, dst, src);
+}
+
+
+static inline bool cast5_fpu_begin(bool fpu_enabled, unsigned int nbytes)
+{
+	return glue_fpu_begin(CAST5_BLOCK_SIZE, CAST5_PARALLEL_BLOCKS,
+			      NULL, fpu_enabled, nbytes);
+}
+
+static inline void cast5_fpu_end(bool fpu_enabled)
+{
+	return glue_fpu_end(fpu_enabled);
+}
+
+static int ecb_crypt(struct blkcipher_desc *desc, struct blkcipher_walk *walk,
+		     bool enc)
+{
+	bool fpu_enabled = false;
+	struct cast5_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	const unsigned int bsize = CAST5_BLOCK_SIZE;
+	unsigned int nbytes;
+	int err;
+
+	err = blkcipher_walk_virt(desc, walk);
+	desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
+
+	while ((nbytes = walk->nbytes)) {
+		u8 *wsrc = walk->src.virt.addr;
+		u8 *wdst = walk->dst.virt.addr;
+
+		fpu_enabled = cast5_fpu_begin(fpu_enabled, nbytes);
+
+		/* Process multi-block batch */
+		if (nbytes >= bsize * CAST5_PARALLEL_BLOCKS) {
+			do {
+				if (enc)
+					cast5_enc_blk_xway(ctx, wdst, wsrc);
+				else
+					cast5_dec_blk_xway(ctx, wdst, wsrc);
+
+				wsrc += bsize * CAST5_PARALLEL_BLOCKS;
+				wdst += bsize * CAST5_PARALLEL_BLOCKS;
+				nbytes -= bsize * CAST5_PARALLEL_BLOCKS;
+			} while (nbytes >= bsize * CAST5_PARALLEL_BLOCKS);
+
+			if (nbytes < bsize)
+				goto done;
+		}
+
+		/* Handle leftovers */
+		do {
+			if (enc)
+				__cast5_encrypt(ctx, wdst, wsrc);
+			else
+				__cast5_decrypt(ctx, wdst, wsrc);
+
+			wsrc += bsize;
+			wdst += bsize;
+			nbytes -= bsize;
+		} while (nbytes >= bsize);
+
+done:
+		err = blkcipher_walk_done(desc, walk, nbytes);
+	}
+
+	cast5_fpu_end(fpu_enabled);
+	return err;
+}
+
+static int ecb_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		       struct scatterlist *src, unsigned int nbytes)
+{
+	struct blkcipher_walk walk;
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	return ecb_crypt(desc, &walk, true);
+}
+
+static int ecb_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		       struct scatterlist *src, unsigned int nbytes)
+{
+	struct blkcipher_walk walk;
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	return ecb_crypt(desc, &walk, false);
+}
+
+static unsigned int __cbc_encrypt(struct blkcipher_desc *desc,
+				  struct blkcipher_walk *walk)
+{
+	struct cast5_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	const unsigned int bsize = CAST5_BLOCK_SIZE;
+	unsigned int nbytes = walk->nbytes;
+	u64 *src = (u64 *)walk->src.virt.addr;
+	u64 *dst = (u64 *)walk->dst.virt.addr;
+	u64 *iv = (u64 *)walk->iv;
+
+	do {
+		*dst = *src ^ *iv;
+		__cast5_encrypt(ctx, (u8 *)dst, (u8 *)dst);
+		iv = dst;
+
+		src += 1;
+		dst += 1;
+		nbytes -= bsize;
+	} while (nbytes >= bsize);
+
+	*(u64 *)walk->iv ^= *iv;
+	return nbytes;
+}
+
+static int cbc_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		       struct scatterlist *src, unsigned int nbytes)
+{
+	struct blkcipher_walk walk;
+	int err;
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	err = blkcipher_walk_virt(desc, &walk);
+
+	while ((nbytes = walk.nbytes)) {
+		nbytes = __cbc_encrypt(desc, &walk);
+		err = blkcipher_walk_done(desc, &walk, nbytes);
+	}
+
+	return err;
+}
+
+static unsigned int __cbc_decrypt(struct blkcipher_desc *desc,
+				  struct blkcipher_walk *walk)
+{
+	struct cast5_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	const unsigned int bsize = CAST5_BLOCK_SIZE;
+	unsigned int nbytes = walk->nbytes;
+	u64 *src = (u64 *)walk->src.virt.addr;
+	u64 *dst = (u64 *)walk->dst.virt.addr;
+	u64 ivs[CAST5_PARALLEL_BLOCKS - 1];
+	u64 last_iv;
+	int i;
+
+	/* Start of the last block. */
+	src += nbytes / bsize - 1;
+	dst += nbytes / bsize - 1;
+
+	last_iv = *src;
+
+	/* Process multi-block batch */
+	if (nbytes >= bsize * CAST5_PARALLEL_BLOCKS) {
+		do {
+			nbytes -= bsize * (CAST5_PARALLEL_BLOCKS - 1);
+			src -= CAST5_PARALLEL_BLOCKS - 1;
+			dst -= CAST5_PARALLEL_BLOCKS - 1;
+
+			for (i = 0; i < CAST5_PARALLEL_BLOCKS - 1; i++)
+				ivs[i] = src[i];
+
+			cast5_dec_blk_xway(ctx, (u8 *)dst, (u8 *)src);
+
+			for (i = 0; i < CAST5_PARALLEL_BLOCKS - 1; i++)
+				*(dst + (i + 1)) ^= *(ivs + i);
+
+			nbytes -= bsize;
+			if (nbytes < bsize)
+				goto done;
+
+			*dst ^= *(src - 1);
+			src -= 1;
+			dst -= 1;
+		} while (nbytes >= bsize * CAST5_PARALLEL_BLOCKS);
+
+		if (nbytes < bsize)
+			goto done;
+	}
+
+	/* Handle leftovers */
+	for (;;) {
+		__cast5_decrypt(ctx, (u8 *)dst, (u8 *)src);
+
+		nbytes -= bsize;
+		if (nbytes < bsize)
+			break;
+
+		*dst ^= *(src - 1);
+		src -= 1;
+		dst -= 1;
+	}
+
+done:
+	*dst ^= *(u64 *)walk->iv;
+	*(u64 *)walk->iv = last_iv;
+
+	return nbytes;
+}
+
+static int cbc_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		       struct scatterlist *src, unsigned int nbytes)
+{
+	bool fpu_enabled = false;
+	struct blkcipher_walk walk;
+	int err;
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	err = blkcipher_walk_virt(desc, &walk);
+	desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
+
+	while ((nbytes = walk.nbytes)) {
+		fpu_enabled = cast5_fpu_begin(fpu_enabled, nbytes);
+		nbytes = __cbc_decrypt(desc, &walk);
+		err = blkcipher_walk_done(desc, &walk, nbytes);
+	}
+
+	cast5_fpu_end(fpu_enabled);
+	return err;
+}
+
+static void ctr_crypt_final(struct blkcipher_desc *desc,
+			    struct blkcipher_walk *walk)
+{
+	struct cast5_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	u8 *ctrblk = walk->iv;
+	u8 keystream[CAST5_BLOCK_SIZE];
+	u8 *src = walk->src.virt.addr;
+	u8 *dst = walk->dst.virt.addr;
+	unsigned int nbytes = walk->nbytes;
+
+	__cast5_encrypt(ctx, keystream, ctrblk);
+	crypto_xor(keystream, src, nbytes);
+	memcpy(dst, keystream, nbytes);
+
+	crypto_inc(ctrblk, CAST5_BLOCK_SIZE);
+}
+
+static unsigned int __ctr_crypt(struct blkcipher_desc *desc,
+				struct blkcipher_walk *walk)
+{
+	struct cast5_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	const unsigned int bsize = CAST5_BLOCK_SIZE;
+	unsigned int nbytes = walk->nbytes;
+	u64 *src = (u64 *)walk->src.virt.addr;
+	u64 *dst = (u64 *)walk->dst.virt.addr;
+	u64 ctrblk = be64_to_cpu(*(__be64 *)walk->iv);
+	__be64 ctrblocks[CAST5_PARALLEL_BLOCKS];
+	int i;
+
+	/* Process multi-block batch */
+	if (nbytes >= bsize * CAST5_PARALLEL_BLOCKS) {
+		do {
+			/* create ctrblks for parallel encrypt */
+			for (i = 0; i < CAST5_PARALLEL_BLOCKS; i++) {
+				if (dst != src)
+					dst[i] = src[i];
+
+				ctrblocks[i] = cpu_to_be64(ctrblk++);
+			}
+
+			cast5_enc_blk_xway_xor(ctx, (u8 *)dst,
+					       (u8 *)ctrblocks);
+
+			src += CAST5_PARALLEL_BLOCKS;
+			dst += CAST5_PARALLEL_BLOCKS;
+			nbytes -= bsize * CAST5_PARALLEL_BLOCKS;
+		} while (nbytes >= bsize * CAST5_PARALLEL_BLOCKS);
+
+		if (nbytes < bsize)
+			goto done;
+	}
+
+	/* Handle leftovers */
+	do {
+		if (dst != src)
+			*dst = *src;
+
+		ctrblocks[0] = cpu_to_be64(ctrblk++);
+
+		__cast5_encrypt(ctx, (u8 *)ctrblocks, (u8 *)ctrblocks);
+		*dst ^= ctrblocks[0];
+
+		src += 1;
+		dst += 1;
+		nbytes -= bsize;
+	} while (nbytes >= bsize);
+
+done:
+	*(__be64 *)walk->iv = cpu_to_be64(ctrblk);
+	return nbytes;
+}
+
+static int ctr_crypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		     struct scatterlist *src, unsigned int nbytes)
+{
+	bool fpu_enabled = false;
+	struct blkcipher_walk walk;
+	int err;
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	err = blkcipher_walk_virt_block(desc, &walk, CAST5_BLOCK_SIZE);
+	desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
+
+	while ((nbytes = walk.nbytes) >= CAST5_BLOCK_SIZE) {
+		fpu_enabled = cast5_fpu_begin(fpu_enabled, nbytes);
+		nbytes = __ctr_crypt(desc, &walk);
+		err = blkcipher_walk_done(desc, &walk, nbytes);
+	}
+
+	cast5_fpu_end(fpu_enabled);
+
+	if (walk.nbytes) {
+		ctr_crypt_final(desc, &walk);
+		err = blkcipher_walk_done(desc, &walk, 0);
+	}
+
+	return err;
+}
+
+
+static struct crypto_alg cast5_algs[6] = { {
+	.cra_name		= "__ecb-cast5-avx",
+	.cra_driver_name	= "__driver-ecb-cast5-avx",
+	.cra_priority		= 0,
+	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER,
+	.cra_blocksize		= CAST5_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct cast5_ctx),
+	.cra_alignmask		= 0,
+	.cra_type		= &crypto_blkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_u = {
+		.blkcipher = {
+			.min_keysize	= CAST5_MIN_KEY_SIZE,
+			.max_keysize	= CAST5_MAX_KEY_SIZE,
+			.setkey		= cast5_setkey,
+			.encrypt	= ecb_encrypt,
+			.decrypt	= ecb_decrypt,
+		},
+	},
+}, {
+	.cra_name		= "__cbc-cast5-avx",
+	.cra_driver_name	= "__driver-cbc-cast5-avx",
+	.cra_priority		= 0,
+	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER,
+	.cra_blocksize		= CAST5_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct cast5_ctx),
+	.cra_alignmask		= 0,
+	.cra_type		= &crypto_blkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_u = {
+		.blkcipher = {
+			.min_keysize	= CAST5_MIN_KEY_SIZE,
+			.max_keysize	= CAST5_MAX_KEY_SIZE,
+			.setkey		= cast5_setkey,
+			.encrypt	= cbc_encrypt,
+			.decrypt	= cbc_decrypt,
+		},
+	},
+}, {
+	.cra_name		= "__ctr-cast5-avx",
+	.cra_driver_name	= "__driver-ctr-cast5-avx",
+	.cra_priority		= 0,
+	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER,
+	.cra_blocksize		= 1,
+	.cra_ctxsize		= sizeof(struct cast5_ctx),
+	.cra_alignmask		= 0,
+	.cra_type		= &crypto_blkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_u = {
+		.blkcipher = {
+			.min_keysize	= CAST5_MIN_KEY_SIZE,
+			.max_keysize	= CAST5_MAX_KEY_SIZE,
+			.ivsize		= CAST5_BLOCK_SIZE,
+			.setkey		= cast5_setkey,
+			.encrypt	= ctr_crypt,
+			.decrypt	= ctr_crypt,
+		},
+	},
+}, {
+	.cra_name		= "ecb(cast5)",
+	.cra_driver_name	= "ecb-cast5-avx",
+	.cra_priority		= 200,
+	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
+	.cra_blocksize		= CAST5_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct async_helper_ctx),
+	.cra_alignmask		= 0,
+	.cra_type		= &crypto_ablkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_init		= ablk_init,
+	.cra_exit		= ablk_exit,
+	.cra_u = {
+		.ablkcipher = {
+			.min_keysize	= CAST5_MIN_KEY_SIZE,
+			.max_keysize	= CAST5_MAX_KEY_SIZE,
+			.setkey		= ablk_set_key,
+			.encrypt	= ablk_encrypt,
+			.decrypt	= ablk_decrypt,
+		},
+	},
+}, {
+	.cra_name		= "cbc(cast5)",
+	.cra_driver_name	= "cbc-cast5-avx",
+	.cra_priority		= 200,
+	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
+	.cra_blocksize		= CAST5_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct async_helper_ctx),
+	.cra_alignmask		= 0,
+	.cra_type		= &crypto_ablkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_init		= ablk_init,
+	.cra_exit		= ablk_exit,
+	.cra_u = {
+		.ablkcipher = {
+			.min_keysize	= CAST5_MIN_KEY_SIZE,
+			.max_keysize	= CAST5_MAX_KEY_SIZE,
+			.ivsize		= CAST5_BLOCK_SIZE,
+			.setkey		= ablk_set_key,
+			.encrypt	= __ablk_encrypt,
+			.decrypt	= ablk_decrypt,
+		},
+	},
+}, {
+	.cra_name		= "ctr(cast5)",
+	.cra_driver_name	= "ctr-cast5-avx",
+	.cra_priority		= 200,
+	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
+	.cra_blocksize		= 1,
+	.cra_ctxsize		= sizeof(struct async_helper_ctx),
+	.cra_alignmask		= 0,
+	.cra_type		= &crypto_ablkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_init		= ablk_init,
+	.cra_exit		= ablk_exit,
+	.cra_u = {
+		.ablkcipher = {
+			.min_keysize	= CAST5_MIN_KEY_SIZE,
+			.max_keysize	= CAST5_MAX_KEY_SIZE,
+			.ivsize		= CAST5_BLOCK_SIZE,
+			.setkey		= ablk_set_key,
+			.encrypt	= ablk_encrypt,
+			.decrypt	= ablk_encrypt,
+			.geniv		= "chainiv",
+		},
+	},
+} };
+
+static int __init cast5_init(void)
+{
+	u64 xcr0;
+
+	if (!cpu_has_avx || !cpu_has_osxsave) {
+		pr_info("AVX instructions are not detected.\n");
+		return -ENODEV;
+	}
+
+	xcr0 = xgetbv(XCR_XFEATURE_ENABLED_MASK);
+	if ((xcr0 & (XSTATE_SSE | XSTATE_YMM)) != (XSTATE_SSE | XSTATE_YMM)) {
+		pr_info("AVX detected but unusable.\n");
+		return -ENODEV;
+	}
+
+	return crypto_register_algs(cast5_algs, ARRAY_SIZE(cast5_algs));
+}
+
+static void __exit cast5_exit(void)
+{
+	crypto_unregister_algs(cast5_algs, ARRAY_SIZE(cast5_algs));
+}
+
+module_init(cast5_init);
+module_exit(cast5_exit);
+
+MODULE_DESCRIPTION("Cast5 Cipher Algorithm, AVX optimized");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("cast5");
diff --git a/arch/x86/crypto/cast6-avx-x86_64-asm_64.S b/arch/x86/crypto/cast6-avx-x86_64-asm_64.S
new file mode 100644
index 0000000..218d283
--- /dev/null
+++ b/arch/x86/crypto/cast6-avx-x86_64-asm_64.S
@@ -0,0 +1,383 @@
+/*
+ * Cast6 Cipher 8-way parallel algorithm (AVX/x86_64)
+ *
+ * Copyright (C) 2012 Johannes Goetzfried
+ *     <Johannes.Goetzfried@informatik.stud.uni-erlangen.de>
+ *
+ * Copyright © 2012 Jussi Kivilinna <jussi.kivilinna@mbnet.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., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+ * USA
+ *
+ */
+
+.file "cast6-avx-x86_64-asm_64.S"
+
+.extern cast6_s1
+.extern cast6_s2
+.extern cast6_s3
+.extern cast6_s4
+
+/* structure of crypto context */
+#define km	0
+#define kr	(12*4*4)
+
+/* s-boxes */
+#define s1	cast6_s1
+#define s2	cast6_s2
+#define s3	cast6_s3
+#define s4	cast6_s4
+
+/**********************************************************************
+  8-way AVX cast6
+ **********************************************************************/
+#define CTX %rdi
+
+#define RA1 %xmm0
+#define RB1 %xmm1
+#define RC1 %xmm2
+#define RD1 %xmm3
+
+#define RA2 %xmm4
+#define RB2 %xmm5
+#define RC2 %xmm6
+#define RD2 %xmm7
+
+#define RX  %xmm8
+
+#define RKM  %xmm9
+#define RKR  %xmm10
+#define RKRF %xmm11
+#define RKRR %xmm12
+#define R32  %xmm13
+#define R1ST %xmm14
+
+#define RTMP %xmm15
+
+#define RID1  %rbp
+#define RID1d %ebp
+#define RID2  %rsi
+#define RID2d %esi
+
+#define RGI1   %rdx
+#define RGI1bl %dl
+#define RGI1bh %dh
+#define RGI2   %rcx
+#define RGI2bl %cl
+#define RGI2bh %ch
+
+#define RGI3   %rax
+#define RGI3bl %al
+#define RGI3bh %ah
+#define RGI4   %rbx
+#define RGI4bl %bl
+#define RGI4bh %bh
+
+#define RFS1  %r8
+#define RFS1d %r8d
+#define RFS2  %r9
+#define RFS2d %r9d
+#define RFS3  %r10
+#define RFS3d %r10d
+
+
+#define lookup_32bit(src, dst, op1, op2, op3, interleave_op, il_reg) \
+	movzbl		src ## bh,     RID1d;    \
+	movzbl		src ## bl,     RID2d;    \
+	shrq $16,	src;                     \
+	movl		s1(, RID1, 4), dst ## d; \
+	op1		s2(, RID2, 4), dst ## d; \
+	movzbl		src ## bh,     RID1d;    \
+	movzbl		src ## bl,     RID2d;    \
+	interleave_op(il_reg);			 \
+	op2		s3(, RID1, 4), dst ## d; \
+	op3		s4(, RID2, 4), dst ## d;
+
+#define dummy(d) /* do nothing */
+
+#define shr_next(reg) \
+	shrq $16,	reg;
+
+#define F_head(a, x, gi1, gi2, op0) \
+	op0	a,	RKM,  x;                 \
+	vpslld	RKRF,	x,    RTMP;              \
+	vpsrld	RKRR,	x,    x;                 \
+	vpor	RTMP,	x,    x;                 \
+	\
+	vmovq		x,    gi1;               \
+	vpextrq $1,	x,    gi2;
+
+#define F_tail(a, x, gi1, gi2, op1, op2, op3) \
+	lookup_32bit(##gi1, RFS1, op1, op2, op3, shr_next, ##gi1); \
+	lookup_32bit(##gi2, RFS3, op1, op2, op3, shr_next, ##gi2); \
+	\
+	lookup_32bit(##gi1, RFS2, op1, op2, op3, dummy, none);     \
+	shlq $32,	RFS2;                                      \
+	orq		RFS1, RFS2;                                \
+	lookup_32bit(##gi2, RFS1, op1, op2, op3, dummy, none);     \
+	shlq $32,	RFS1;                                      \
+	orq		RFS1, RFS3;                                \
+	\
+	vmovq		RFS2, x;                                   \
+	vpinsrq $1,	RFS3, x, x;
+
+#define F_2(a1, b1, a2, b2, op0, op1, op2, op3) \
+	F_head(b1, RX, RGI1, RGI2, op0);              \
+	F_head(b2, RX, RGI3, RGI4, op0);              \
+	\
+	F_tail(b1, RX, RGI1, RGI2, op1, op2, op3);    \
+	F_tail(b2, RTMP, RGI3, RGI4, op1, op2, op3);  \
+	\
+	vpxor		a1, RX,   a1;                 \
+	vpxor		a2, RTMP, a2;
+
+#define F1_2(a1, b1, a2, b2) \
+	F_2(a1, b1, a2, b2, vpaddd, xorl, subl, addl)
+#define F2_2(a1, b1, a2, b2) \
+	F_2(a1, b1, a2, b2, vpxor, subl, addl, xorl)
+#define F3_2(a1, b1, a2, b2) \
+	F_2(a1, b1, a2, b2, vpsubd, addl, xorl, subl)
+
+#define qop(in, out, f) \
+	F ## f ## _2(out ## 1, in ## 1, out ## 2, in ## 2);
+
+#define get_round_keys(nn) \
+	vbroadcastss	(km+(4*(nn)))(CTX), RKM;        \
+	vpand		R1ST,               RKR,  RKRF; \
+	vpsubq		RKRF,               R32,  RKRR; \
+	vpsrldq $1,	RKR,                RKR;
+
+#define Q(n) \
+	get_round_keys(4*n+0); \
+	qop(RD, RC, 1);        \
+	\
+	get_round_keys(4*n+1); \
+	qop(RC, RB, 2);        \
+	\
+	get_round_keys(4*n+2); \
+	qop(RB, RA, 3);        \
+	\
+	get_round_keys(4*n+3); \
+	qop(RA, RD, 1);
+
+#define QBAR(n) \
+	get_round_keys(4*n+3); \
+	qop(RA, RD, 1);        \
+	\
+	get_round_keys(4*n+2); \
+	qop(RB, RA, 3);        \
+	\
+	get_round_keys(4*n+1); \
+	qop(RC, RB, 2);        \
+	\
+	get_round_keys(4*n+0); \
+	qop(RD, RC, 1);
+
+#define shuffle(mask) \
+	vpshufb		mask,            RKR, RKR;
+
+#define preload_rkr(n, do_mask, mask) \
+	vbroadcastss	.L16_mask,                RKR;      \
+	/* add 16-bit rotation to key rotations (mod 32) */ \
+	vpxor		(kr+n*16)(CTX),           RKR, RKR; \
+	do_mask(mask);
+
+#define transpose_4x4(x0, x1, x2, x3, t0, t1, t2) \
+	vpunpckldq		x1, x0, t0; \
+	vpunpckhdq		x1, x0, t2; \
+	vpunpckldq		x3, x2, t1; \
+	vpunpckhdq		x3, x2, x3; \
+	\
+	vpunpcklqdq		t1, t0, x0; \
+	vpunpckhqdq		t1, t0, x1; \
+	vpunpcklqdq		x3, t2, x2; \
+	vpunpckhqdq		x3, t2, x3;
+
+#define inpack_blocks(in, x0, x1, x2, x3, t0, t1, t2, rmask) \
+	vmovdqu (0*4*4)(in),	x0; \
+	vmovdqu (1*4*4)(in),	x1; \
+	vmovdqu (2*4*4)(in),	x2; \
+	vmovdqu (3*4*4)(in),	x3; \
+	vpshufb rmask, x0,	x0; \
+	vpshufb rmask, x1,	x1; \
+	vpshufb rmask, x2,	x2; \
+	vpshufb rmask, x3,	x3; \
+	\
+	transpose_4x4(x0, x1, x2, x3, t0, t1, t2)
+
+#define outunpack_blocks(out, x0, x1, x2, x3, t0, t1, t2, rmask) \
+	transpose_4x4(x0, x1, x2, x3, t0, t1, t2) \
+	\
+	vpshufb rmask,		x0, x0;       \
+	vpshufb rmask,		x1, x1;       \
+	vpshufb rmask,		x2, x2;       \
+	vpshufb rmask,		x3, x3;       \
+	vmovdqu x0,		(0*4*4)(out); \
+	vmovdqu	x1,		(1*4*4)(out); \
+	vmovdqu	x2,		(2*4*4)(out); \
+	vmovdqu	x3,		(3*4*4)(out);
+
+#define outunpack_xor_blocks(out, x0, x1, x2, x3, t0, t1, t2, rmask) \
+	transpose_4x4(x0, x1, x2, x3, t0, t1, t2) \
+	\
+	vpshufb rmask,		x0, x0;       \
+	vpshufb rmask,		x1, x1;       \
+	vpshufb rmask,		x2, x2;       \
+	vpshufb rmask,		x3, x3;       \
+	vpxor (0*4*4)(out),	x0, x0;       \
+	vmovdqu	x0,		(0*4*4)(out); \
+	vpxor (1*4*4)(out),	x1, x1;       \
+	vmovdqu	x1,		(1*4*4)(out); \
+	vpxor (2*4*4)(out),	x2, x2;       \
+	vmovdqu x2,		(2*4*4)(out); \
+	vpxor (3*4*4)(out),	x3, x3;       \
+	vmovdqu x3,		(3*4*4)(out);
+
+.data
+
+.align 16
+.Lbswap_mask:
+	.byte 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12
+.Lrkr_enc_Q_Q_QBAR_QBAR:
+	.byte 0, 1, 2, 3, 4, 5, 6, 7, 11, 10, 9, 8, 15, 14, 13, 12
+.Lrkr_enc_QBAR_QBAR_QBAR_QBAR:
+	.byte 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12
+.Lrkr_dec_Q_Q_Q_Q:
+	.byte 12, 13, 14, 15, 8, 9, 10, 11, 4, 5, 6, 7, 0, 1, 2, 3
+.Lrkr_dec_Q_Q_QBAR_QBAR:
+	.byte 12, 13, 14, 15, 8, 9, 10, 11, 7, 6, 5, 4, 3, 2, 1, 0
+.Lrkr_dec_QBAR_QBAR_QBAR_QBAR:
+	.byte 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
+.L16_mask:
+	.byte 16, 16, 16, 16
+.L32_mask:
+	.byte 32, 0, 0, 0
+.Lfirst_mask:
+	.byte 0x1f, 0, 0, 0
+
+.text
+
+.align 16
+.global __cast6_enc_blk_8way
+.type   __cast6_enc_blk_8way,@function;
+
+__cast6_enc_blk_8way:
+	/* input:
+	 *	%rdi: ctx, CTX
+	 *	%rsi: dst
+	 *	%rdx: src
+	 *	%rcx: bool, if true: xor output
+	 */
+
+	pushq %rbp;
+	pushq %rbx;
+	pushq %rcx;
+
+	vmovdqa .Lbswap_mask, RKM;
+	vmovd .Lfirst_mask, R1ST;
+	vmovd .L32_mask, R32;
+
+	leaq (4*4*4)(%rdx), %rax;
+	inpack_blocks(%rdx, RA1, RB1, RC1, RD1, RTMP, RX, RKRF, RKM);
+	inpack_blocks(%rax, RA2, RB2, RC2, RD2, RTMP, RX, RKRF, RKM);
+
+	movq %rsi, %r11;
+
+	preload_rkr(0, dummy, none);
+	Q(0);
+	Q(1);
+	Q(2);
+	Q(3);
+	preload_rkr(1, shuffle, .Lrkr_enc_Q_Q_QBAR_QBAR);
+	Q(4);
+	Q(5);
+	QBAR(6);
+	QBAR(7);
+	preload_rkr(2, shuffle, .Lrkr_enc_QBAR_QBAR_QBAR_QBAR);
+	QBAR(8);
+	QBAR(9);
+	QBAR(10);
+	QBAR(11);
+
+	popq %rcx;
+	popq %rbx;
+	popq %rbp;
+
+	vmovdqa .Lbswap_mask, RKM;
+	leaq (4*4*4)(%r11), %rax;
+
+	testb %cl, %cl;
+	jnz __enc_xor8;
+
+	outunpack_blocks(%r11, RA1, RB1, RC1, RD1, RTMP, RX, RKRF, RKM);
+	outunpack_blocks(%rax, RA2, RB2, RC2, RD2, RTMP, RX, RKRF, RKM);
+
+	ret;
+
+__enc_xor8:
+	outunpack_xor_blocks(%r11, RA1, RB1, RC1, RD1, RTMP, RX, RKRF, RKM);
+	outunpack_xor_blocks(%rax, RA2, RB2, RC2, RD2, RTMP, RX, RKRF, RKM);
+
+	ret;
+
+.align 16
+.global cast6_dec_blk_8way
+.type   cast6_dec_blk_8way,@function;
+
+cast6_dec_blk_8way:
+	/* input:
+	 *	%rdi: ctx, CTX
+	 *	%rsi: dst
+	 *	%rdx: src
+	 */
+
+	pushq %rbp;
+	pushq %rbx;
+
+	vmovdqa .Lbswap_mask, RKM;
+	vmovd .Lfirst_mask, R1ST;
+	vmovd .L32_mask, R32;
+
+	leaq (4*4*4)(%rdx), %rax;
+	inpack_blocks(%rdx, RA1, RB1, RC1, RD1, RTMP, RX, RKRF, RKM);
+	inpack_blocks(%rax, RA2, RB2, RC2, RD2, RTMP, RX, RKRF, RKM);
+
+	movq %rsi, %r11;
+
+	preload_rkr(2, shuffle, .Lrkr_dec_Q_Q_Q_Q);
+	Q(11);
+	Q(10);
+	Q(9);
+	Q(8);
+	preload_rkr(1, shuffle, .Lrkr_dec_Q_Q_QBAR_QBAR);
+	Q(7);
+	Q(6);
+	QBAR(5);
+	QBAR(4);
+	preload_rkr(0, shuffle, .Lrkr_dec_QBAR_QBAR_QBAR_QBAR);
+	QBAR(3);
+	QBAR(2);
+	QBAR(1);
+	QBAR(0);
+
+	popq %rbx;
+	popq %rbp;
+
+	vmovdqa .Lbswap_mask, RKM;
+	leaq (4*4*4)(%r11), %rax;
+	outunpack_blocks(%r11, RA1, RB1, RC1, RD1, RTMP, RX, RKRF, RKM);
+	outunpack_blocks(%rax, RA2, RB2, RC2, RD2, RTMP, RX, RKRF, RKM);
+
+	ret;
diff --git a/arch/x86/crypto/cast6_avx_glue.c b/arch/x86/crypto/cast6_avx_glue.c
new file mode 100644
index 0000000..15e5f85
--- /dev/null
+++ b/arch/x86/crypto/cast6_avx_glue.c
@@ -0,0 +1,648 @@
+/*
+ * Glue Code for the AVX assembler implemention of the Cast6 Cipher
+ *
+ * Copyright (C) 2012 Johannes Goetzfried
+ *     <Johannes.Goetzfried@informatik.stud.uni-erlangen.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., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+ * USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/hardirq.h>
+#include <linux/types.h>
+#include <linux/crypto.h>
+#include <linux/err.h>
+#include <crypto/algapi.h>
+#include <crypto/cast6.h>
+#include <crypto/cryptd.h>
+#include <crypto/b128ops.h>
+#include <crypto/ctr.h>
+#include <crypto/lrw.h>
+#include <crypto/xts.h>
+#include <asm/xcr.h>
+#include <asm/xsave.h>
+#include <asm/crypto/ablk_helper.h>
+#include <asm/crypto/glue_helper.h>
+
+#define CAST6_PARALLEL_BLOCKS 8
+
+asmlinkage void __cast6_enc_blk_8way(struct cast6_ctx *ctx, u8 *dst,
+				     const u8 *src, bool xor);
+asmlinkage void cast6_dec_blk_8way(struct cast6_ctx *ctx, u8 *dst,
+				   const u8 *src);
+
+static inline void cast6_enc_blk_xway(struct cast6_ctx *ctx, u8 *dst,
+				      const u8 *src)
+{
+	__cast6_enc_blk_8way(ctx, dst, src, false);
+}
+
+static inline void cast6_enc_blk_xway_xor(struct cast6_ctx *ctx, u8 *dst,
+					  const u8 *src)
+{
+	__cast6_enc_blk_8way(ctx, dst, src, true);
+}
+
+static inline void cast6_dec_blk_xway(struct cast6_ctx *ctx, u8 *dst,
+				      const u8 *src)
+{
+	cast6_dec_blk_8way(ctx, dst, src);
+}
+
+
+static void cast6_decrypt_cbc_xway(void *ctx, u128 *dst, const u128 *src)
+{
+	u128 ivs[CAST6_PARALLEL_BLOCKS - 1];
+	unsigned int j;
+
+	for (j = 0; j < CAST6_PARALLEL_BLOCKS - 1; j++)
+		ivs[j] = src[j];
+
+	cast6_dec_blk_xway(ctx, (u8 *)dst, (u8 *)src);
+
+	for (j = 0; j < CAST6_PARALLEL_BLOCKS - 1; j++)
+		u128_xor(dst + (j + 1), dst + (j + 1), ivs + j);
+}
+
+static void cast6_crypt_ctr(void *ctx, u128 *dst, const u128 *src, u128 *iv)
+{
+	be128 ctrblk;
+
+	u128_to_be128(&ctrblk, iv);
+	u128_inc(iv);
+
+	__cast6_encrypt(ctx, (u8 *)&ctrblk, (u8 *)&ctrblk);
+	u128_xor(dst, src, (u128 *)&ctrblk);
+}
+
+static void cast6_crypt_ctr_xway(void *ctx, u128 *dst, const u128 *src,
+				   u128 *iv)
+{
+	be128 ctrblks[CAST6_PARALLEL_BLOCKS];
+	unsigned int i;
+
+	for (i = 0; i < CAST6_PARALLEL_BLOCKS; i++) {
+		if (dst != src)
+			dst[i] = src[i];
+
+		u128_to_be128(&ctrblks[i], iv);
+		u128_inc(iv);
+	}
+
+	cast6_enc_blk_xway_xor(ctx, (u8 *)dst, (u8 *)ctrblks);
+}
+
+static const struct common_glue_ctx cast6_enc = {
+	.num_funcs = 2,
+	.fpu_blocks_limit = CAST6_PARALLEL_BLOCKS,
+
+	.funcs = { {
+		.num_blocks = CAST6_PARALLEL_BLOCKS,
+		.fn_u = { .ecb = GLUE_FUNC_CAST(cast6_enc_blk_xway) }
+	}, {
+		.num_blocks = 1,
+		.fn_u = { .ecb = GLUE_FUNC_CAST(__cast6_encrypt) }
+	} }
+};
+
+static const struct common_glue_ctx cast6_ctr = {
+	.num_funcs = 2,
+	.fpu_blocks_limit = CAST6_PARALLEL_BLOCKS,
+
+	.funcs = { {
+		.num_blocks = CAST6_PARALLEL_BLOCKS,
+		.fn_u = { .ctr = GLUE_CTR_FUNC_CAST(cast6_crypt_ctr_xway) }
+	}, {
+		.num_blocks = 1,
+		.fn_u = { .ctr = GLUE_CTR_FUNC_CAST(cast6_crypt_ctr) }
+	} }
+};
+
+static const struct common_glue_ctx cast6_dec = {
+	.num_funcs = 2,
+	.fpu_blocks_limit = CAST6_PARALLEL_BLOCKS,
+
+	.funcs = { {
+		.num_blocks = CAST6_PARALLEL_BLOCKS,
+		.fn_u = { .ecb = GLUE_FUNC_CAST(cast6_dec_blk_xway) }
+	}, {
+		.num_blocks = 1,
+		.fn_u = { .ecb = GLUE_FUNC_CAST(__cast6_decrypt) }
+	} }
+};
+
+static const struct common_glue_ctx cast6_dec_cbc = {
+	.num_funcs = 2,
+	.fpu_blocks_limit = CAST6_PARALLEL_BLOCKS,
+
+	.funcs = { {
+		.num_blocks = CAST6_PARALLEL_BLOCKS,
+		.fn_u = { .cbc = GLUE_CBC_FUNC_CAST(cast6_decrypt_cbc_xway) }
+	}, {
+		.num_blocks = 1,
+		.fn_u = { .cbc = GLUE_CBC_FUNC_CAST(__cast6_decrypt) }
+	} }
+};
+
+static int ecb_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		       struct scatterlist *src, unsigned int nbytes)
+{
+	return glue_ecb_crypt_128bit(&cast6_enc, desc, dst, src, nbytes);
+}
+
+static int ecb_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		       struct scatterlist *src, unsigned int nbytes)
+{
+	return glue_ecb_crypt_128bit(&cast6_dec, desc, dst, src, nbytes);
+}
+
+static int cbc_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		       struct scatterlist *src, unsigned int nbytes)
+{
+	return glue_cbc_encrypt_128bit(GLUE_FUNC_CAST(__cast6_encrypt), desc,
+				       dst, src, nbytes);
+}
+
+static int cbc_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		       struct scatterlist *src, unsigned int nbytes)
+{
+	return glue_cbc_decrypt_128bit(&cast6_dec_cbc, desc, dst, src,
+				       nbytes);
+}
+
+static int ctr_crypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		     struct scatterlist *src, unsigned int nbytes)
+{
+	return glue_ctr_crypt_128bit(&cast6_ctr, desc, dst, src, nbytes);
+}
+
+static inline bool cast6_fpu_begin(bool fpu_enabled, unsigned int nbytes)
+{
+	return glue_fpu_begin(CAST6_BLOCK_SIZE, CAST6_PARALLEL_BLOCKS,
+			      NULL, fpu_enabled, nbytes);
+}
+
+static inline void cast6_fpu_end(bool fpu_enabled)
+{
+	glue_fpu_end(fpu_enabled);
+}
+
+struct crypt_priv {
+	struct cast6_ctx *ctx;
+	bool fpu_enabled;
+};
+
+static void encrypt_callback(void *priv, u8 *srcdst, unsigned int nbytes)
+{
+	const unsigned int bsize = CAST6_BLOCK_SIZE;
+	struct crypt_priv *ctx = priv;
+	int i;
+
+	ctx->fpu_enabled = cast6_fpu_begin(ctx->fpu_enabled, nbytes);
+
+	if (nbytes == bsize * CAST6_PARALLEL_BLOCKS) {
+		cast6_enc_blk_xway(ctx->ctx, srcdst, srcdst);
+		return;
+	}
+
+	for (i = 0; i < nbytes / bsize; i++, srcdst += bsize)
+		__cast6_encrypt(ctx->ctx, srcdst, srcdst);
+}
+
+static void decrypt_callback(void *priv, u8 *srcdst, unsigned int nbytes)
+{
+	const unsigned int bsize = CAST6_BLOCK_SIZE;
+	struct crypt_priv *ctx = priv;
+	int i;
+
+	ctx->fpu_enabled = cast6_fpu_begin(ctx->fpu_enabled, nbytes);
+
+	if (nbytes == bsize * CAST6_PARALLEL_BLOCKS) {
+		cast6_dec_blk_xway(ctx->ctx, srcdst, srcdst);
+		return;
+	}
+
+	for (i = 0; i < nbytes / bsize; i++, srcdst += bsize)
+		__cast6_decrypt(ctx->ctx, srcdst, srcdst);
+}
+
+struct cast6_lrw_ctx {
+	struct lrw_table_ctx lrw_table;
+	struct cast6_ctx cast6_ctx;
+};
+
+static int lrw_cast6_setkey(struct crypto_tfm *tfm, const u8 *key,
+			      unsigned int keylen)
+{
+	struct cast6_lrw_ctx *ctx = crypto_tfm_ctx(tfm);
+	int err;
+
+	err = __cast6_setkey(&ctx->cast6_ctx, key, keylen - CAST6_BLOCK_SIZE,
+			     &tfm->crt_flags);
+	if (err)
+		return err;
+
+	return lrw_init_table(&ctx->lrw_table, key + keylen - CAST6_BLOCK_SIZE);
+}
+
+static int lrw_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		       struct scatterlist *src, unsigned int nbytes)
+{
+	struct cast6_lrw_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	be128 buf[CAST6_PARALLEL_BLOCKS];
+	struct crypt_priv crypt_ctx = {
+		.ctx = &ctx->cast6_ctx,
+		.fpu_enabled = false,
+	};
+	struct lrw_crypt_req req = {
+		.tbuf = buf,
+		.tbuflen = sizeof(buf),
+
+		.table_ctx = &ctx->lrw_table,
+		.crypt_ctx = &crypt_ctx,
+		.crypt_fn = encrypt_callback,
+	};
+	int ret;
+
+	desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
+	ret = lrw_crypt(desc, dst, src, nbytes, &req);
+	cast6_fpu_end(crypt_ctx.fpu_enabled);
+
+	return ret;
+}
+
+static int lrw_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		       struct scatterlist *src, unsigned int nbytes)
+{
+	struct cast6_lrw_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	be128 buf[CAST6_PARALLEL_BLOCKS];
+	struct crypt_priv crypt_ctx = {
+		.ctx = &ctx->cast6_ctx,
+		.fpu_enabled = false,
+	};
+	struct lrw_crypt_req req = {
+		.tbuf = buf,
+		.tbuflen = sizeof(buf),
+
+		.table_ctx = &ctx->lrw_table,
+		.crypt_ctx = &crypt_ctx,
+		.crypt_fn = decrypt_callback,
+	};
+	int ret;
+
+	desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
+	ret = lrw_crypt(desc, dst, src, nbytes, &req);
+	cast6_fpu_end(crypt_ctx.fpu_enabled);
+
+	return ret;
+}
+
+static void lrw_exit_tfm(struct crypto_tfm *tfm)
+{
+	struct cast6_lrw_ctx *ctx = crypto_tfm_ctx(tfm);
+
+	lrw_free_table(&ctx->lrw_table);
+}
+
+struct cast6_xts_ctx {
+	struct cast6_ctx tweak_ctx;
+	struct cast6_ctx crypt_ctx;
+};
+
+static int xts_cast6_setkey(struct crypto_tfm *tfm, const u8 *key,
+			      unsigned int keylen)
+{
+	struct cast6_xts_ctx *ctx = crypto_tfm_ctx(tfm);
+	u32 *flags = &tfm->crt_flags;
+	int err;
+
+	/* key consists of keys of equal size concatenated, therefore
+	 * the length must be even
+	 */
+	if (keylen % 2) {
+		*flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+		return -EINVAL;
+	}
+
+	/* first half of xts-key is for crypt */
+	err = __cast6_setkey(&ctx->crypt_ctx, key, keylen / 2, flags);
+	if (err)
+		return err;
+
+	/* second half of xts-key is for tweak */
+	return __cast6_setkey(&ctx->tweak_ctx, key + keylen / 2, keylen / 2,
+			      flags);
+}
+
+static int xts_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		       struct scatterlist *src, unsigned int nbytes)
+{
+	struct cast6_xts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	be128 buf[CAST6_PARALLEL_BLOCKS];
+	struct crypt_priv crypt_ctx = {
+		.ctx = &ctx->crypt_ctx,
+		.fpu_enabled = false,
+	};
+	struct xts_crypt_req req = {
+		.tbuf = buf,
+		.tbuflen = sizeof(buf),
+
+		.tweak_ctx = &ctx->tweak_ctx,
+		.tweak_fn = XTS_TWEAK_CAST(__cast6_encrypt),
+		.crypt_ctx = &crypt_ctx,
+		.crypt_fn = encrypt_callback,
+	};
+	int ret;
+
+	desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
+	ret = xts_crypt(desc, dst, src, nbytes, &req);
+	cast6_fpu_end(crypt_ctx.fpu_enabled);
+
+	return ret;
+}
+
+static int xts_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
+		       struct scatterlist *src, unsigned int nbytes)
+{
+	struct cast6_xts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	be128 buf[CAST6_PARALLEL_BLOCKS];
+	struct crypt_priv crypt_ctx = {
+		.ctx = &ctx->crypt_ctx,
+		.fpu_enabled = false,
+	};
+	struct xts_crypt_req req = {
+		.tbuf = buf,
+		.tbuflen = sizeof(buf),
+
+		.tweak_ctx = &ctx->tweak_ctx,
+		.tweak_fn = XTS_TWEAK_CAST(__cast6_encrypt),
+		.crypt_ctx = &crypt_ctx,
+		.crypt_fn = decrypt_callback,
+	};
+	int ret;
+
+	desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
+	ret = xts_crypt(desc, dst, src, nbytes, &req);
+	cast6_fpu_end(crypt_ctx.fpu_enabled);
+
+	return ret;
+}
+
+static struct crypto_alg cast6_algs[10] = { {
+	.cra_name		= "__ecb-cast6-avx",
+	.cra_driver_name	= "__driver-ecb-cast6-avx",
+	.cra_priority		= 0,
+	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER,
+	.cra_blocksize		= CAST6_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct cast6_ctx),
+	.cra_alignmask		= 0,
+	.cra_type		= &crypto_blkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_u = {
+		.blkcipher = {
+			.min_keysize	= CAST6_MIN_KEY_SIZE,
+			.max_keysize	= CAST6_MAX_KEY_SIZE,
+			.setkey		= cast6_setkey,
+			.encrypt	= ecb_encrypt,
+			.decrypt	= ecb_decrypt,
+		},
+	},
+}, {
+	.cra_name		= "__cbc-cast6-avx",
+	.cra_driver_name	= "__driver-cbc-cast6-avx",
+	.cra_priority		= 0,
+	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER,
+	.cra_blocksize		= CAST6_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct cast6_ctx),
+	.cra_alignmask		= 0,
+	.cra_type		= &crypto_blkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_u = {
+		.blkcipher = {
+			.min_keysize	= CAST6_MIN_KEY_SIZE,
+			.max_keysize	= CAST6_MAX_KEY_SIZE,
+			.setkey		= cast6_setkey,
+			.encrypt	= cbc_encrypt,
+			.decrypt	= cbc_decrypt,
+		},
+	},
+}, {
+	.cra_name		= "__ctr-cast6-avx",
+	.cra_driver_name	= "__driver-ctr-cast6-avx",
+	.cra_priority		= 0,
+	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER,
+	.cra_blocksize		= 1,
+	.cra_ctxsize		= sizeof(struct cast6_ctx),
+	.cra_alignmask		= 0,
+	.cra_type		= &crypto_blkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_u = {
+		.blkcipher = {
+			.min_keysize	= CAST6_MIN_KEY_SIZE,
+			.max_keysize	= CAST6_MAX_KEY_SIZE,
+			.ivsize		= CAST6_BLOCK_SIZE,
+			.setkey		= cast6_setkey,
+			.encrypt	= ctr_crypt,
+			.decrypt	= ctr_crypt,
+		},
+	},
+}, {
+	.cra_name		= "__lrw-cast6-avx",
+	.cra_driver_name	= "__driver-lrw-cast6-avx",
+	.cra_priority		= 0,
+	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER,
+	.cra_blocksize		= CAST6_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct cast6_lrw_ctx),
+	.cra_alignmask		= 0,
+	.cra_type		= &crypto_blkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_exit		= lrw_exit_tfm,
+	.cra_u = {
+		.blkcipher = {
+			.min_keysize	= CAST6_MIN_KEY_SIZE +
+					  CAST6_BLOCK_SIZE,
+			.max_keysize	= CAST6_MAX_KEY_SIZE +
+					  CAST6_BLOCK_SIZE,
+			.ivsize		= CAST6_BLOCK_SIZE,
+			.setkey		= lrw_cast6_setkey,
+			.encrypt	= lrw_encrypt,
+			.decrypt	= lrw_decrypt,
+		},
+	},
+}, {
+	.cra_name		= "__xts-cast6-avx",
+	.cra_driver_name	= "__driver-xts-cast6-avx",
+	.cra_priority		= 0,
+	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER,
+	.cra_blocksize		= CAST6_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct cast6_xts_ctx),
+	.cra_alignmask		= 0,
+	.cra_type		= &crypto_blkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_u = {
+		.blkcipher = {
+			.min_keysize	= CAST6_MIN_KEY_SIZE * 2,
+			.max_keysize	= CAST6_MAX_KEY_SIZE * 2,
+			.ivsize		= CAST6_BLOCK_SIZE,
+			.setkey		= xts_cast6_setkey,
+			.encrypt	= xts_encrypt,
+			.decrypt	= xts_decrypt,
+		},
+	},
+}, {
+	.cra_name		= "ecb(cast6)",
+	.cra_driver_name	= "ecb-cast6-avx",
+	.cra_priority		= 200,
+	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
+	.cra_blocksize		= CAST6_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct async_helper_ctx),
+	.cra_alignmask		= 0,
+	.cra_type		= &crypto_ablkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_init		= ablk_init,
+	.cra_exit		= ablk_exit,
+	.cra_u = {
+		.ablkcipher = {
+			.min_keysize	= CAST6_MIN_KEY_SIZE,
+			.max_keysize	= CAST6_MAX_KEY_SIZE,
+			.setkey		= ablk_set_key,
+			.encrypt	= ablk_encrypt,
+			.decrypt	= ablk_decrypt,
+		},
+	},
+}, {
+	.cra_name		= "cbc(cast6)",
+	.cra_driver_name	= "cbc-cast6-avx",
+	.cra_priority		= 200,
+	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
+	.cra_blocksize		= CAST6_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct async_helper_ctx),
+	.cra_alignmask		= 0,
+	.cra_type		= &crypto_ablkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_init		= ablk_init,
+	.cra_exit		= ablk_exit,
+	.cra_u = {
+		.ablkcipher = {
+			.min_keysize	= CAST6_MIN_KEY_SIZE,
+			.max_keysize	= CAST6_MAX_KEY_SIZE,
+			.ivsize		= CAST6_BLOCK_SIZE,
+			.setkey		= ablk_set_key,
+			.encrypt	= __ablk_encrypt,
+			.decrypt	= ablk_decrypt,
+		},
+	},
+}, {
+	.cra_name		= "ctr(cast6)",
+	.cra_driver_name	= "ctr-cast6-avx",
+	.cra_priority		= 200,
+	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
+	.cra_blocksize		= 1,
+	.cra_ctxsize		= sizeof(struct async_helper_ctx),
+	.cra_alignmask		= 0,
+	.cra_type		= &crypto_ablkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_init		= ablk_init,
+	.cra_exit		= ablk_exit,
+	.cra_u = {
+		.ablkcipher = {
+			.min_keysize	= CAST6_MIN_KEY_SIZE,
+			.max_keysize	= CAST6_MAX_KEY_SIZE,
+			.ivsize		= CAST6_BLOCK_SIZE,
+			.setkey		= ablk_set_key,
+			.encrypt	= ablk_encrypt,
+			.decrypt	= ablk_encrypt,
+			.geniv		= "chainiv",
+		},
+	},
+}, {
+	.cra_name		= "lrw(cast6)",
+	.cra_driver_name	= "lrw-cast6-avx",
+	.cra_priority		= 200,
+	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
+	.cra_blocksize		= CAST6_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct async_helper_ctx),
+	.cra_alignmask		= 0,
+	.cra_type		= &crypto_ablkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_init		= ablk_init,
+	.cra_exit		= ablk_exit,
+	.cra_u = {
+		.ablkcipher = {
+			.min_keysize	= CAST6_MIN_KEY_SIZE +
+					  CAST6_BLOCK_SIZE,
+			.max_keysize	= CAST6_MAX_KEY_SIZE +
+					  CAST6_BLOCK_SIZE,
+			.ivsize		= CAST6_BLOCK_SIZE,
+			.setkey		= ablk_set_key,
+			.encrypt	= ablk_encrypt,
+			.decrypt	= ablk_decrypt,
+		},
+	},
+}, {
+	.cra_name		= "xts(cast6)",
+	.cra_driver_name	= "xts-cast6-avx",
+	.cra_priority		= 200,
+	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
+	.cra_blocksize		= CAST6_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct async_helper_ctx),
+	.cra_alignmask		= 0,
+	.cra_type		= &crypto_ablkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_init		= ablk_init,
+	.cra_exit		= ablk_exit,
+	.cra_u = {
+		.ablkcipher = {
+			.min_keysize	= CAST6_MIN_KEY_SIZE * 2,
+			.max_keysize	= CAST6_MAX_KEY_SIZE * 2,
+			.ivsize		= CAST6_BLOCK_SIZE,
+			.setkey		= ablk_set_key,
+			.encrypt	= ablk_encrypt,
+			.decrypt	= ablk_decrypt,
+		},
+	},
+} };
+
+static int __init cast6_init(void)
+{
+	u64 xcr0;
+
+	if (!cpu_has_avx || !cpu_has_osxsave) {
+		pr_info("AVX instructions are not detected.\n");
+		return -ENODEV;
+	}
+
+	xcr0 = xgetbv(XCR_XFEATURE_ENABLED_MASK);
+	if ((xcr0 & (XSTATE_SSE | XSTATE_YMM)) != (XSTATE_SSE | XSTATE_YMM)) {
+		pr_info("AVX detected but unusable.\n");
+		return -ENODEV;
+	}
+
+	return crypto_register_algs(cast6_algs, ARRAY_SIZE(cast6_algs));
+}
+
+static void __exit cast6_exit(void)
+{
+	crypto_unregister_algs(cast6_algs, ARRAY_SIZE(cast6_algs));
+}
+
+module_init(cast6_init);
+module_exit(cast6_exit);
+
+MODULE_DESCRIPTION("Cast6 Cipher Algorithm, AVX optimized");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("cast6");
diff --git a/arch/x86/crypto/ghash-clmulni-intel_glue.c b/arch/x86/crypto/ghash-clmulni-intel_glue.c
index b4bf0a6..6759dd1 100644
--- a/arch/x86/crypto/ghash-clmulni-intel_glue.c
+++ b/arch/x86/crypto/ghash-clmulni-intel_glue.c
@@ -150,7 +150,6 @@ static struct shash_alg ghash_alg = {
 		.cra_blocksize		= GHASH_BLOCK_SIZE,
 		.cra_ctxsize		= sizeof(struct ghash_ctx),
 		.cra_module		= THIS_MODULE,
-		.cra_list		= LIST_HEAD_INIT(ghash_alg.base.cra_list),
 	},
 };
 
@@ -288,7 +287,6 @@ static struct ahash_alg ghash_async_alg = {
 			.cra_blocksize		= GHASH_BLOCK_SIZE,
 			.cra_type		= &crypto_ahash_type,
 			.cra_module		= THIS_MODULE,
-			.cra_list		= LIST_HEAD_INIT(ghash_async_alg.halg.base.cra_list),
 			.cra_init		= ghash_async_init_tfm,
 			.cra_exit		= ghash_async_exit_tfm,
 		},
diff --git a/arch/x86/crypto/salsa20_glue.c b/arch/x86/crypto/salsa20_glue.c
index bccb76d..a3a3c02 100644
--- a/arch/x86/crypto/salsa20_glue.c
+++ b/arch/x86/crypto/salsa20_glue.c
@@ -97,7 +97,6 @@ static struct crypto_alg alg = {
 	.cra_ctxsize        =   sizeof(struct salsa20_ctx),
 	.cra_alignmask      =	3,
 	.cra_module         =   THIS_MODULE,
-	.cra_list           =   LIST_HEAD_INIT(alg.cra_list),
 	.cra_u              =   {
 		.blkcipher = {
 			.setkey         =   setkey,
diff --git a/arch/x86/crypto/serpent_avx_glue.c b/arch/x86/crypto/serpent_avx_glue.c
index b36bdac..3f543a0 100644
--- a/arch/x86/crypto/serpent_avx_glue.c
+++ b/arch/x86/crypto/serpent_avx_glue.c
@@ -390,7 +390,6 @@ static struct crypto_alg serpent_algs[10] = { {
 	.cra_alignmask		= 0,
 	.cra_type		= &crypto_blkcipher_type,
 	.cra_module		= THIS_MODULE,
-	.cra_list		= LIST_HEAD_INIT(serpent_algs[0].cra_list),
 	.cra_u = {
 		.blkcipher = {
 			.min_keysize	= SERPENT_MIN_KEY_SIZE,
@@ -410,7 +409,6 @@ static struct crypto_alg serpent_algs[10] = { {
 	.cra_alignmask		= 0,
 	.cra_type		= &crypto_blkcipher_type,
 	.cra_module		= THIS_MODULE,
-	.cra_list		= LIST_HEAD_INIT(serpent_algs[1].cra_list),
 	.cra_u = {
 		.blkcipher = {
 			.min_keysize	= SERPENT_MIN_KEY_SIZE,
@@ -430,7 +428,6 @@ static struct crypto_alg serpent_algs[10] = { {
 	.cra_alignmask		= 0,
 	.cra_type		= &crypto_blkcipher_type,
 	.cra_module		= THIS_MODULE,
-	.cra_list		= LIST_HEAD_INIT(serpent_algs[2].cra_list),
 	.cra_u = {
 		.blkcipher = {
 			.min_keysize	= SERPENT_MIN_KEY_SIZE,
@@ -451,7 +448,6 @@ static struct crypto_alg serpent_algs[10] = { {
 	.cra_alignmask		= 0,
 	.cra_type		= &crypto_blkcipher_type,
 	.cra_module		= THIS_MODULE,
-	.cra_list		= LIST_HEAD_INIT(serpent_algs[3].cra_list),
 	.cra_exit		= lrw_exit_tfm,
 	.cra_u = {
 		.blkcipher = {
@@ -475,7 +471,6 @@ static struct crypto_alg serpent_algs[10] = { {
 	.cra_alignmask		= 0,
 	.cra_type		= &crypto_blkcipher_type,
 	.cra_module		= THIS_MODULE,
-	.cra_list		= LIST_HEAD_INIT(serpent_algs[4].cra_list),
 	.cra_u = {
 		.blkcipher = {
 			.min_keysize	= SERPENT_MIN_KEY_SIZE * 2,
@@ -496,7 +491,6 @@ static struct crypto_alg serpent_algs[10] = { {
 	.cra_alignmask		= 0,
 	.cra_type		= &crypto_ablkcipher_type,
 	.cra_module		= THIS_MODULE,
-	.cra_list		= LIST_HEAD_INIT(serpent_algs[5].cra_list),
 	.cra_init		= ablk_init,
 	.cra_exit		= ablk_exit,
 	.cra_u = {
@@ -518,7 +512,6 @@ static struct crypto_alg serpent_algs[10] = { {
 	.cra_alignmask		= 0,
 	.cra_type		= &crypto_ablkcipher_type,
 	.cra_module		= THIS_MODULE,
-	.cra_list		= LIST_HEAD_INIT(serpent_algs[6].cra_list),
 	.cra_init		= ablk_init,
 	.cra_exit		= ablk_exit,
 	.cra_u = {
@@ -541,7 +534,6 @@ static struct crypto_alg serpent_algs[10] = { {
 	.cra_alignmask		= 0,
 	.cra_type		= &crypto_ablkcipher_type,
 	.cra_module		= THIS_MODULE,
-	.cra_list		= LIST_HEAD_INIT(serpent_algs[7].cra_list),
 	.cra_init		= ablk_init,
 	.cra_exit		= ablk_exit,
 	.cra_u = {
@@ -565,7 +557,6 @@ static struct crypto_alg serpent_algs[10] = { {
 	.cra_alignmask		= 0,
 	.cra_type		= &crypto_ablkcipher_type,
 	.cra_module		= THIS_MODULE,
-	.cra_list		= LIST_HEAD_INIT(serpent_algs[8].cra_list),
 	.cra_init		= ablk_init,
 	.cra_exit		= ablk_exit,
 	.cra_u = {
@@ -590,7 +581,6 @@ static struct crypto_alg serpent_algs[10] = { {
 	.cra_alignmask		= 0,
 	.cra_type		= &crypto_ablkcipher_type,
 	.cra_module		= THIS_MODULE,
-	.cra_list		= LIST_HEAD_INIT(serpent_algs[9].cra_list),
 	.cra_init		= ablk_init,
 	.cra_exit		= ablk_exit,
 	.cra_u = {
diff --git a/arch/x86/crypto/serpent_sse2_glue.c b/arch/x86/crypto/serpent_sse2_glue.c
index d679c86..9107a99 100644
--- a/arch/x86/crypto/serpent_sse2_glue.c
+++ b/arch/x86/crypto/serpent_sse2_glue.c
@@ -393,7 +393,6 @@ static struct crypto_alg serpent_algs[10] = { {
 	.cra_alignmask		= 0,
 	.cra_type		= &crypto_blkcipher_type,
 	.cra_module		= THIS_MODULE,
-	.cra_list		= LIST_HEAD_INIT(serpent_algs[0].cra_list),
 	.cra_u = {
 		.blkcipher = {
 			.min_keysize	= SERPENT_MIN_KEY_SIZE,
@@ -413,7 +412,6 @@ static struct crypto_alg serpent_algs[10] = { {
 	.cra_alignmask		= 0,
 	.cra_type		= &crypto_blkcipher_type,
 	.cra_module		= THIS_MODULE,
-	.cra_list		= LIST_HEAD_INIT(serpent_algs[1].cra_list),
 	.cra_u = {
 		.blkcipher = {
 			.min_keysize	= SERPENT_MIN_KEY_SIZE,
@@ -433,7 +431,6 @@ static struct crypto_alg serpent_algs[10] = { {
 	.cra_alignmask		= 0,
 	.cra_type		= &crypto_blkcipher_type,
 	.cra_module		= THIS_MODULE,
-	.cra_list		= LIST_HEAD_INIT(serpent_algs[2].cra_list),
 	.cra_u = {
 		.blkcipher = {
 			.min_keysize	= SERPENT_MIN_KEY_SIZE,
@@ -454,7 +451,6 @@ static struct crypto_alg serpent_algs[10] = { {
 	.cra_alignmask		= 0,
 	.cra_type		= &crypto_blkcipher_type,
 	.cra_module		= THIS_MODULE,
-	.cra_list		= LIST_HEAD_INIT(serpent_algs[3].cra_list),
 	.cra_exit		= lrw_exit_tfm,
 	.cra_u = {
 		.blkcipher = {
@@ -478,7 +474,6 @@ static struct crypto_alg serpent_algs[10] = { {
 	.cra_alignmask		= 0,
 	.cra_type		= &crypto_blkcipher_type,
 	.cra_module		= THIS_MODULE,
-	.cra_list		= LIST_HEAD_INIT(serpent_algs[4].cra_list),
 	.cra_u = {
 		.blkcipher = {
 			.min_keysize	= SERPENT_MIN_KEY_SIZE * 2,
@@ -499,7 +494,6 @@ static struct crypto_alg serpent_algs[10] = { {
 	.cra_alignmask		= 0,
 	.cra_type		= &crypto_ablkcipher_type,
 	.cra_module		= THIS_MODULE,
-	.cra_list		= LIST_HEAD_INIT(serpent_algs[5].cra_list),
 	.cra_init		= ablk_init,
 	.cra_exit		= ablk_exit,
 	.cra_u = {
@@ -521,7 +515,6 @@ static struct crypto_alg serpent_algs[10] = { {
 	.cra_alignmask		= 0,
 	.cra_type		= &crypto_ablkcipher_type,
 	.cra_module		= THIS_MODULE,
-	.cra_list		= LIST_HEAD_INIT(serpent_algs[6].cra_list),
 	.cra_init		= ablk_init,
 	.cra_exit		= ablk_exit,
 	.cra_u = {
@@ -544,7 +537,6 @@ static struct crypto_alg serpent_algs[10] = { {
 	.cra_alignmask		= 0,
 	.cra_type		= &crypto_ablkcipher_type,
 	.cra_module		= THIS_MODULE,
-	.cra_list		= LIST_HEAD_INIT(serpent_algs[7].cra_list),
 	.cra_init		= ablk_init,
 	.cra_exit		= ablk_exit,
 	.cra_u = {
@@ -568,7 +560,6 @@ static struct crypto_alg serpent_algs[10] = { {
 	.cra_alignmask		= 0,
 	.cra_type		= &crypto_ablkcipher_type,
 	.cra_module		= THIS_MODULE,
-	.cra_list		= LIST_HEAD_INIT(serpent_algs[8].cra_list),
 	.cra_init		= ablk_init,
 	.cra_exit		= ablk_exit,
 	.cra_u = {
@@ -593,7 +584,6 @@ static struct crypto_alg serpent_algs[10] = { {
 	.cra_alignmask		= 0,
 	.cra_type		= &crypto_ablkcipher_type,
 	.cra_module		= THIS_MODULE,
-	.cra_list		= LIST_HEAD_INIT(serpent_algs[9].cra_list),
 	.cra_init		= ablk_init,
 	.cra_exit		= ablk_exit,
 	.cra_u = {
diff --git a/arch/x86/crypto/twofish-avx-x86_64-asm_64.S b/arch/x86/crypto/twofish-avx-x86_64-asm_64.S
index 35f4557..1585abb 100644
--- a/arch/x86/crypto/twofish-avx-x86_64-asm_64.S
+++ b/arch/x86/crypto/twofish-avx-x86_64-asm_64.S
@@ -4,6 +4,8 @@
  * Copyright (C) 2012 Johannes Goetzfried
  *     <Johannes.Goetzfried@informatik.stud.uni-erlangen.de>
  *
+ * Copyright © 2012 Jussi Kivilinna <jussi.kivilinna@mbnet.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
@@ -47,16 +49,22 @@
 #define RC2 %xmm6
 #define RD2 %xmm7
 
-#define RX %xmm8
-#define RY %xmm9
+#define RX0 %xmm8
+#define RY0 %xmm9
+
+#define RX1 %xmm10
+#define RY1 %xmm11
 
-#define RK1 %xmm10
-#define RK2 %xmm11
+#define RK1 %xmm12
+#define RK2 %xmm13
 
-#define RID1  %rax
-#define RID1b %al
-#define RID2  %rbx
-#define RID2b %bl
+#define RT %xmm14
+#define RR %xmm15
+
+#define RID1  %rbp
+#define RID1d %ebp
+#define RID2  %rsi
+#define RID2d %esi
 
 #define RGI1   %rdx
 #define RGI1bl %dl
@@ -65,6 +73,13 @@
 #define RGI2bl %cl
 #define RGI2bh %ch
 
+#define RGI3   %rax
+#define RGI3bl %al
+#define RGI3bh %ah
+#define RGI4   %rbx
+#define RGI4bl %bl
+#define RGI4bh %bh
+
 #define RGS1  %r8
 #define RGS1d %r8d
 #define RGS2  %r9
@@ -73,89 +88,123 @@
 #define RGS3d %r10d
 
 
-#define lookup_32bit(t0, t1, t2, t3, src, dst) \
-	movb		src ## bl,        RID1b;     \
-	movb		src ## bh,        RID2b;     \
-	movl		t0(CTX, RID1, 4), dst ## d;  \
-	xorl		t1(CTX, RID2, 4), dst ## d;  \
+#define lookup_32bit(t0, t1, t2, t3, src, dst, interleave_op, il_reg) \
+	movzbl		src ## bl,        RID1d;     \
+	movzbl		src ## bh,        RID2d;     \
 	shrq $16,	src;                         \
-	movb		src ## bl,        RID1b;     \
-	movb		src ## bh,        RID2b;     \
+	movl		t0(CTX, RID1, 4), dst ## d;  \
+	movl		t1(CTX, RID2, 4), RID2d;     \
+	movzbl		src ## bl,        RID1d;     \
+	xorl		RID2d,            dst ## d;  \
+	movzbl		src ## bh,        RID2d;     \
+	interleave_op(il_reg);			     \
 	xorl		t2(CTX, RID1, 4), dst ## d;  \
 	xorl		t3(CTX, RID2, 4), dst ## d;
 
-#define G(a, x, t0, t1, t2, t3) \
-	vmovq		a,    RGI1;               \
-	vpsrldq $8,	a,    x;                  \
-	vmovq		x,    RGI2;               \
+#define dummy(d) /* do nothing */
+
+#define shr_next(reg) \
+	shrq $16,	reg;
+
+#define G(gi1, gi2, x, t0, t1, t2, t3) \
+	lookup_32bit(t0, t1, t2, t3, ##gi1, RGS1, shr_next, ##gi1);  \
+	lookup_32bit(t0, t1, t2, t3, ##gi2, RGS3, shr_next, ##gi2);  \
+	\
+	lookup_32bit(t0, t1, t2, t3, ##gi1, RGS2, dummy, none);      \
+	shlq $32,	RGS2;                                        \
+	orq		RGS1, RGS2;                                  \
+	lookup_32bit(t0, t1, t2, t3, ##gi2, RGS1, dummy, none);      \
+	shlq $32,	RGS1;                                        \
+	orq		RGS1, RGS3;
+
+#define round_head_2(a, b, x1, y1, x2, y2) \
+	vmovq		b ## 1, RGI3;           \
+	vpextrq $1,	b ## 1, RGI4;           \
 	\
-	lookup_32bit(t0, t1, t2, t3, RGI1, RGS1); \
-	shrq $16,	RGI1;                     \
-	lookup_32bit(t0, t1, t2, t3, RGI1, RGS2); \
-	shlq $32,	RGS2;                     \
-	orq		RGS1, RGS2;               \
+	G(RGI1, RGI2, x1, s0, s1, s2, s3);      \
+	vmovq		a ## 2, RGI1;           \
+	vpextrq $1,	a ## 2, RGI2;           \
+	vmovq		RGS2, x1;               \
+	vpinsrq $1,	RGS3, x1, x1;           \
 	\
-	lookup_32bit(t0, t1, t2, t3, RGI2, RGS1); \
-	shrq $16,	RGI2;                     \
-	lookup_32bit(t0, t1, t2, t3, RGI2, RGS3); \
-	shlq $32,	RGS3;                     \
-	orq		RGS1, RGS3;               \
+	G(RGI3, RGI4, y1, s1, s2, s3, s0);      \
+	vmovq		b ## 2, RGI3;           \
+	vpextrq $1,	b ## 2, RGI4;           \
+	vmovq		RGS2, y1;               \
+	vpinsrq $1,	RGS3, y1, y1;           \
 	\
-	vmovq		RGS2, x;                  \
-	vpinsrq $1,	RGS3, x, x;
+	G(RGI1, RGI2, x2, s0, s1, s2, s3);      \
+	vmovq		RGS2, x2;               \
+	vpinsrq $1,	RGS3, x2, x2;           \
+	\
+	G(RGI3, RGI4, y2, s1, s2, s3, s0);      \
+	vmovq		RGS2, y2;               \
+	vpinsrq $1,	RGS3, y2, y2;
 
-#define encround(a, b, c, d, x, y) \
-	G(a, x, s0, s1, s2, s3);           \
-	G(b, y, s1, s2, s3, s0);           \
+#define encround_tail(a, b, c, d, x, y, prerotate) \
 	vpaddd			x, y,   x; \
+	vpaddd			x, RK1, RT;\
+	prerotate(b);			   \
+	vpxor			RT, c,  c; \
 	vpaddd			y, x,   y; \
-	vpaddd			x, RK1, x; \
 	vpaddd			y, RK2, y; \
-	vpxor			x, c,   c; \
-	vpsrld $1,		c, x;      \
+	vpsrld $1,		c, RT;     \
 	vpslld $(32 - 1),	c, c;      \
-	vpor			c, x,   c; \
-	vpslld $1,		d, x;      \
-	vpsrld $(32 - 1),	d, d;      \
-	vpor			d, x,   d; \
-	vpxor			d, y,   d;
-
-#define decround(a, b, c, d, x, y) \
-	G(a, x, s0, s1, s2, s3);           \
-	G(b, y, s1, s2, s3, s0);           \
+	vpor			c, RT,  c; \
+	vpxor			d, y,   d; \
+
+#define decround_tail(a, b, c, d, x, y, prerotate) \
 	vpaddd			x, y,   x; \
+	vpaddd			x, RK1, RT;\
+	prerotate(a);			   \
+	vpxor			RT, c,  c; \
 	vpaddd			y, x,   y; \
 	vpaddd			y, RK2, y; \
 	vpxor			d, y,   d; \
 	vpsrld $1,		d, y;      \
 	vpslld $(32 - 1),	d, d;      \
 	vpor			d, y,   d; \
-	vpslld $1,		c, y;      \
-	vpsrld $(32 - 1),	c, c;      \
-	vpor			c, y,   c; \
-	vpaddd			x, RK1, x; \
-	vpxor			x, c,   c;
-
-#define encrypt_round(n, a, b, c, d) \
-	vbroadcastss (k+4*(2*(n)))(CTX),   RK1;           \
-	vbroadcastss (k+4*(2*(n)+1))(CTX), RK2;           \
-	encround(a ## 1, b ## 1, c ## 1, d ## 1, RX, RY); \
-	encround(a ## 2, b ## 2, c ## 2, d ## 2, RX, RY);
-
-#define decrypt_round(n, a, b, c, d) \
-	vbroadcastss (k+4*(2*(n)))(CTX),   RK1;           \
-	vbroadcastss (k+4*(2*(n)+1))(CTX), RK2;           \
-	decround(a ## 1, b ## 1, c ## 1, d ## 1, RX, RY); \
-	decround(a ## 2, b ## 2, c ## 2, d ## 2, RX, RY);
+
+#define rotate_1l(x) \
+	vpslld $1,		x, RR;     \
+	vpsrld $(32 - 1),	x, x;      \
+	vpor			x, RR,  x;
+
+#define preload_rgi(c) \
+	vmovq			c, RGI1; \
+	vpextrq $1,		c, RGI2;
+
+#define encrypt_round(n, a, b, c, d, preload, prerotate) \
+	vbroadcastss (k+4*(2*(n)))(CTX),   RK1;                  \
+	vbroadcastss (k+4*(2*(n)+1))(CTX), RK2;                  \
+	round_head_2(a, b, RX0, RY0, RX1, RY1);                  \
+	encround_tail(a ## 1, b ## 1, c ## 1, d ## 1, RX0, RY0, prerotate); \
+	preload(c ## 1);                                         \
+	encround_tail(a ## 2, b ## 2, c ## 2, d ## 2, RX1, RY1, prerotate);
+
+#define decrypt_round(n, a, b, c, d, preload, prerotate) \
+	vbroadcastss (k+4*(2*(n)))(CTX),   RK1;                  \
+	vbroadcastss (k+4*(2*(n)+1))(CTX), RK2;                  \
+	round_head_2(a, b, RX0, RY0, RX1, RY1);                  \
+	decround_tail(a ## 1, b ## 1, c ## 1, d ## 1, RX0, RY0, prerotate); \
+	preload(c ## 1);                                         \
+	decround_tail(a ## 2, b ## 2, c ## 2, d ## 2, RX1, RY1, prerotate);
 
 #define encrypt_cycle(n) \
-	encrypt_round((2*n), RA, RB, RC, RD);       \
-	encrypt_round(((2*n) + 1), RC, RD, RA, RB);
+	encrypt_round((2*n), RA, RB, RC, RD, preload_rgi, rotate_1l); \
+	encrypt_round(((2*n) + 1), RC, RD, RA, RB, preload_rgi, rotate_1l);
+
+#define encrypt_cycle_last(n) \
+	encrypt_round((2*n), RA, RB, RC, RD, preload_rgi, rotate_1l); \
+	encrypt_round(((2*n) + 1), RC, RD, RA, RB, dummy, dummy);
 
 #define decrypt_cycle(n) \
-	decrypt_round(((2*n) + 1), RC, RD, RA, RB); \
-	decrypt_round((2*n), RA, RB, RC, RD);
+	decrypt_round(((2*n) + 1), RC, RD, RA, RB, preload_rgi, rotate_1l); \
+	decrypt_round((2*n), RA, RB, RC, RD, preload_rgi, rotate_1l);
 
+#define decrypt_cycle_last(n) \
+	decrypt_round(((2*n) + 1), RC, RD, RA, RB, preload_rgi, rotate_1l); \
+	decrypt_round((2*n), RA, RB, RC, RD, dummy, dummy);
 
 #define transpose_4x4(x0, x1, x2, x3, t0, t1, t2) \
 	vpunpckldq		x1, x0, t0; \
@@ -216,17 +265,20 @@ __twofish_enc_blk_8way:
 	 *	%rcx: bool, if true: xor output
 	 */
 
+	pushq %rbp;
 	pushq %rbx;
 	pushq %rcx;
 
 	vmovdqu w(CTX), RK1;
 
 	leaq (4*4*4)(%rdx), %rax;
-	inpack_blocks(%rdx, RA1, RB1, RC1, RD1, RK1, RX, RY, RK2);
-	inpack_blocks(%rax, RA2, RB2, RC2, RD2, RK1, RX, RY, RK2);
+	inpack_blocks(%rdx, RA1, RB1, RC1, RD1, RK1, RX0, RY0, RK2);
+	preload_rgi(RA1);
+	rotate_1l(RD1);
+	inpack_blocks(%rax, RA2, RB2, RC2, RD2, RK1, RX0, RY0, RK2);
+	rotate_1l(RD2);
 
-	xorq RID1, RID1;
-	xorq RID2, RID2;
+	movq %rsi, %r11;
 
 	encrypt_cycle(0);
 	encrypt_cycle(1);
@@ -235,26 +287,27 @@ __twofish_enc_blk_8way:
 	encrypt_cycle(4);
 	encrypt_cycle(5);
 	encrypt_cycle(6);
-	encrypt_cycle(7);
+	encrypt_cycle_last(7);
 
 	vmovdqu (w+4*4)(CTX), RK1;
 
 	popq %rcx;
 	popq %rbx;
+	popq %rbp;
 
-	leaq (4*4*4)(%rsi), %rax;
+	leaq (4*4*4)(%r11), %rax;
 
 	testb %cl, %cl;
 	jnz __enc_xor8;
 
-	outunpack_blocks(%rsi, RC1, RD1, RA1, RB1, RK1, RX, RY, RK2);
-	outunpack_blocks(%rax, RC2, RD2, RA2, RB2, RK1, RX, RY, RK2);
+	outunpack_blocks(%r11, RC1, RD1, RA1, RB1, RK1, RX0, RY0, RK2);
+	outunpack_blocks(%rax, RC2, RD2, RA2, RB2, RK1, RX0, RY0, RK2);
 
 	ret;
 
 __enc_xor8:
-	outunpack_xor_blocks(%rsi, RC1, RD1, RA1, RB1, RK1, RX, RY, RK2);
-	outunpack_xor_blocks(%rax, RC2, RD2, RA2, RB2, RK1, RX, RY, RK2);
+	outunpack_xor_blocks(%r11, RC1, RD1, RA1, RB1, RK1, RX0, RY0, RK2);
+	outunpack_xor_blocks(%rax, RC2, RD2, RA2, RB2, RK1, RX0, RY0, RK2);
 
 	ret;
 
@@ -269,16 +322,19 @@ twofish_dec_blk_8way:
 	 *	%rdx: src
 	 */
 
+	pushq %rbp;
 	pushq %rbx;
 
 	vmovdqu (w+4*4)(CTX), RK1;
 
 	leaq (4*4*4)(%rdx), %rax;
-	inpack_blocks(%rdx, RC1, RD1, RA1, RB1, RK1, RX, RY, RK2);
-	inpack_blocks(%rax, RC2, RD2, RA2, RB2, RK1, RX, RY, RK2);
+	inpack_blocks(%rdx, RC1, RD1, RA1, RB1, RK1, RX0, RY0, RK2);
+	preload_rgi(RC1);
+	rotate_1l(RA1);
+	inpack_blocks(%rax, RC2, RD2, RA2, RB2, RK1, RX0, RY0, RK2);
+	rotate_1l(RA2);
 
-	xorq RID1, RID1;
-	xorq RID2, RID2;
+	movq %rsi, %r11;
 
 	decrypt_cycle(7);
 	decrypt_cycle(6);
@@ -287,14 +343,15 @@ twofish_dec_blk_8way:
 	decrypt_cycle(3);
 	decrypt_cycle(2);
 	decrypt_cycle(1);
-	decrypt_cycle(0);
+	decrypt_cycle_last(0);
 
 	vmovdqu (w)(CTX), RK1;
 
 	popq %rbx;
+	popq %rbp;
 
-	leaq (4*4*4)(%rsi), %rax;
-	outunpack_blocks(%rsi, RA1, RB1, RC1, RD1, RK1, RX, RY, RK2);
-	outunpack_blocks(%rax, RA2, RB2, RC2, RD2, RK1, RX, RY, RK2);
+	leaq (4*4*4)(%r11), %rax;
+	outunpack_blocks(%r11, RA1, RB1, RC1, RD1, RK1, RX0, RY0, RK2);
+	outunpack_blocks(%rax, RA2, RB2, RC2, RD2, RK1, RX0, RY0, RK2);
 
 	ret;
diff --git a/arch/x86/crypto/twofish_avx_glue.c b/arch/x86/crypto/twofish_avx_glue.c
index 782b67d..e7708b5 100644
--- a/arch/x86/crypto/twofish_avx_glue.c
+++ b/arch/x86/crypto/twofish_avx_glue.c
@@ -378,7 +378,6 @@ static struct crypto_alg twofish_algs[10] = { {
 	.cra_alignmask		= 0,
 	.cra_type		= &crypto_blkcipher_type,
 	.cra_module		= THIS_MODULE,
-	.cra_list		= LIST_HEAD_INIT(twofish_algs[0].cra_list),
 	.cra_u = {
 		.blkcipher = {
 			.min_keysize	= TF_MIN_KEY_SIZE,
@@ -398,7 +397,6 @@ static struct crypto_alg twofish_algs[10] = { {
 	.cra_alignmask		= 0,
 	.cra_type		= &crypto_blkcipher_type,
 	.cra_module		= THIS_MODULE,
-	.cra_list		= LIST_HEAD_INIT(twofish_algs[1].cra_list),
 	.cra_u = {
 		.blkcipher = {
 			.min_keysize	= TF_MIN_KEY_SIZE,
@@ -418,7 +416,6 @@ static struct crypto_alg twofish_algs[10] = { {
 	.cra_alignmask		= 0,
 	.cra_type		= &crypto_blkcipher_type,
 	.cra_module		= THIS_MODULE,
-	.cra_list		= LIST_HEAD_INIT(twofish_algs[2].cra_list),
 	.cra_u = {
 		.blkcipher = {
 			.min_keysize	= TF_MIN_KEY_SIZE,
@@ -439,7 +436,6 @@ static struct crypto_alg twofish_algs[10] = { {
 	.cra_alignmask		= 0,
 	.cra_type		= &crypto_blkcipher_type,
 	.cra_module		= THIS_MODULE,
-	.cra_list		= LIST_HEAD_INIT(twofish_algs[3].cra_list),
 	.cra_exit		= lrw_twofish_exit_tfm,
 	.cra_u = {
 		.blkcipher = {
@@ -463,7 +459,6 @@ static struct crypto_alg twofish_algs[10] = { {
 	.cra_alignmask		= 0,
 	.cra_type		= &crypto_blkcipher_type,
 	.cra_module		= THIS_MODULE,
-	.cra_list		= LIST_HEAD_INIT(twofish_algs[4].cra_list),
 	.cra_u = {
 		.blkcipher = {
 			.min_keysize	= TF_MIN_KEY_SIZE * 2,
@@ -484,7 +479,6 @@ static struct crypto_alg twofish_algs[10] = { {
 	.cra_alignmask		= 0,
 	.cra_type		= &crypto_ablkcipher_type,
 	.cra_module		= THIS_MODULE,
-	.cra_list		= LIST_HEAD_INIT(twofish_algs[5].cra_list),
 	.cra_init		= ablk_init,
 	.cra_exit		= ablk_exit,
 	.cra_u = {
@@ -506,7 +500,6 @@ static struct crypto_alg twofish_algs[10] = { {
 	.cra_alignmask		= 0,
 	.cra_type		= &crypto_ablkcipher_type,
 	.cra_module		= THIS_MODULE,
-	.cra_list		= LIST_HEAD_INIT(twofish_algs[6].cra_list),
 	.cra_init		= ablk_init,
 	.cra_exit		= ablk_exit,
 	.cra_u = {
@@ -529,7 +522,6 @@ static struct crypto_alg twofish_algs[10] = { {
 	.cra_alignmask		= 0,
 	.cra_type		= &crypto_ablkcipher_type,
 	.cra_module		= THIS_MODULE,
-	.cra_list		= LIST_HEAD_INIT(twofish_algs[7].cra_list),
 	.cra_init		= ablk_init,
 	.cra_exit		= ablk_exit,
 	.cra_u = {
@@ -553,7 +545,6 @@ static struct crypto_alg twofish_algs[10] = { {
 	.cra_alignmask		= 0,
 	.cra_type		= &crypto_ablkcipher_type,
 	.cra_module		= THIS_MODULE,
-	.cra_list		= LIST_HEAD_INIT(twofish_algs[8].cra_list),
 	.cra_init		= ablk_init,
 	.cra_exit		= ablk_exit,
 	.cra_u = {
@@ -578,7 +569,6 @@ static struct crypto_alg twofish_algs[10] = { {
 	.cra_alignmask		= 0,
 	.cra_type		= &crypto_ablkcipher_type,
 	.cra_module		= THIS_MODULE,
-	.cra_list		= LIST_HEAD_INIT(twofish_algs[9].cra_list),
 	.cra_init		= ablk_init,
 	.cra_exit		= ablk_exit,
 	.cra_u = {
diff --git a/arch/x86/crypto/twofish_glue.c b/arch/x86/crypto/twofish_glue.c
index 359ae08..0a52023 100644
--- a/arch/x86/crypto/twofish_glue.c
+++ b/arch/x86/crypto/twofish_glue.c
@@ -70,7 +70,6 @@ static struct crypto_alg alg = {
 	.cra_ctxsize		=	sizeof(struct twofish_ctx),
 	.cra_alignmask		=	0,
 	.cra_module		=	THIS_MODULE,
-	.cra_list		=	LIST_HEAD_INIT(alg.cra_list),
 	.cra_u			=	{
 		.cipher = {
 			.cia_min_keysize	=	TF_MIN_KEY_SIZE,
diff --git a/arch/x86/crypto/twofish_glue_3way.c b/arch/x86/crypto/twofish_glue_3way.c
index 15f9347..aa3eb35 100644
--- a/arch/x86/crypto/twofish_glue_3way.c
+++ b/arch/x86/crypto/twofish_glue_3way.c
@@ -342,7 +342,6 @@ static struct crypto_alg tf_algs[5] = { {
 	.cra_alignmask		= 0,
 	.cra_type		= &crypto_blkcipher_type,
 	.cra_module		= THIS_MODULE,
-	.cra_list		= LIST_HEAD_INIT(tf_algs[0].cra_list),
 	.cra_u = {
 		.blkcipher = {
 			.min_keysize	= TF_MIN_KEY_SIZE,
@@ -362,7 +361,6 @@ static struct crypto_alg tf_algs[5] = { {
 	.cra_alignmask		= 0,
 	.cra_type		= &crypto_blkcipher_type,
 	.cra_module		= THIS_MODULE,
-	.cra_list		= LIST_HEAD_INIT(tf_algs[1].cra_list),
 	.cra_u = {
 		.blkcipher = {
 			.min_keysize	= TF_MIN_KEY_SIZE,
@@ -383,7 +381,6 @@ static struct crypto_alg tf_algs[5] = { {
 	.cra_alignmask		= 0,
 	.cra_type		= &crypto_blkcipher_type,
 	.cra_module		= THIS_MODULE,
-	.cra_list		= LIST_HEAD_INIT(tf_algs[2].cra_list),
 	.cra_u = {
 		.blkcipher = {
 			.min_keysize	= TF_MIN_KEY_SIZE,
@@ -404,7 +401,6 @@ static struct crypto_alg tf_algs[5] = { {
 	.cra_alignmask		= 0,
 	.cra_type		= &crypto_blkcipher_type,
 	.cra_module		= THIS_MODULE,
-	.cra_list		= LIST_HEAD_INIT(tf_algs[3].cra_list),
 	.cra_exit		= lrw_twofish_exit_tfm,
 	.cra_u = {
 		.blkcipher = {
@@ -426,7 +422,6 @@ static struct crypto_alg tf_algs[5] = { {
 	.cra_alignmask		= 0,
 	.cra_type		= &crypto_blkcipher_type,
 	.cra_module		= THIS_MODULE,
-	.cra_list		= LIST_HEAD_INIT(tf_algs[4].cra_list),
 	.cra_u = {
 		.blkcipher = {
 			.min_keysize	= TF_MIN_KEY_SIZE * 2,
diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c
index 673ac9b..efc6a95 100644
--- a/arch/x86/ia32/ia32_signal.c
+++ b/arch/x86/ia32/ia32_signal.c
@@ -32,6 +32,7 @@
 #include <asm/sigframe.h>
 #include <asm/sighandling.h>
 #include <asm/sys_ia32.h>
+#include <asm/smap.h>
 
 #define FIX_EFLAGS	__FIX_EFLAGS
 
@@ -162,7 +163,8 @@ asmlinkage long sys32_sigaltstack(const stack_ia32_t __user *uss_ptr,
 	}
 	seg = get_fs();
 	set_fs(KERNEL_DS);
-	ret = do_sigaltstack(uss_ptr ? &uss : NULL, &uoss, regs->sp);
+	ret = do_sigaltstack((stack_t __force __user *) (uss_ptr ? &uss : NULL),
+			     (stack_t __force __user *) &uoss, regs->sp);
 	set_fs(seg);
 	if (ret >= 0 && uoss_ptr)  {
 		if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(stack_ia32_t)))
@@ -250,11 +252,12 @@ static int ia32_restore_sigcontext(struct pt_regs *regs,
 
 		get_user_ex(tmp, &sc->fpstate);
 		buf = compat_ptr(tmp);
-		err |= restore_i387_xstate_ia32(buf);
 
 		get_user_ex(*pax, &sc->ax);
 	} get_user_catch(err);
 
+	err |= restore_xstate_sig(buf, 1);
+
 	return err;
 }
 
@@ -361,7 +364,7 @@ static int ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc,
  */
 static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
 				 size_t frame_size,
-				 void **fpstate)
+				 void __user **fpstate)
 {
 	unsigned long sp;
 
@@ -381,9 +384,12 @@ static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
 		sp = (unsigned long) ka->sa.sa_restorer;
 
 	if (used_math()) {
-		sp = sp - sig_xstate_ia32_size;
-		*fpstate = (struct _fpstate_ia32 *) sp;
-		if (save_i387_xstate_ia32(*fpstate) < 0)
+		unsigned long fx_aligned, math_size;
+
+		sp = alloc_mathframe(sp, 1, &fx_aligned, &math_size);
+		*fpstate = (struct _fpstate_ia32 __user *) sp;
+		if (save_xstate_sig(*fpstate, (void __user *)fx_aligned,
+				    math_size) < 0)
 			return (void __user *) -1L;
 	}
 
@@ -448,7 +454,7 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka,
 		 * These are actually not used anymore, but left because some
 		 * gdb versions depend on them as a marker.
 		 */
-		put_user_ex(*((u64 *)&code), (u64 *)frame->retcode);
+		put_user_ex(*((u64 *)&code), (u64 __user *)frame->retcode);
 	} put_user_catch(err);
 
 	if (err)
@@ -502,7 +508,6 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 		put_user_ex(sig, &frame->sig);
 		put_user_ex(ptr_to_compat(&frame->info), &frame->pinfo);
 		put_user_ex(ptr_to_compat(&frame->uc), &frame->puc);
-		err |= copy_siginfo_to_user32(&frame->info, info);
 
 		/* Create the ucontext.  */
 		if (cpu_has_xsave)
@@ -514,9 +519,6 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 		put_user_ex(sas_ss_flags(regs->sp),
 			    &frame->uc.uc_stack.ss_flags);
 		put_user_ex(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
-		err |= ia32_setup_sigcontext(&frame->uc.uc_mcontext, fpstate,
-					     regs, set->sig[0]);
-		err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
 
 		if (ka->sa.sa_flags & SA_RESTORER)
 			restorer = ka->sa.sa_restorer;
@@ -529,9 +531,14 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 		 * Not actually used anymore, but left because some gdb
 		 * versions need it.
 		 */
-		put_user_ex(*((u64 *)&code), (u64 *)frame->retcode);
+		put_user_ex(*((u64 *)&code), (u64 __user *)frame->retcode);
 	} put_user_catch(err);
 
+	err |= copy_siginfo_to_user32(&frame->info, info);
+	err |= ia32_setup_sigcontext(&frame->uc.uc_mcontext, fpstate,
+				     regs, set->sig[0]);
+	err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
+
 	if (err)
 		return -EFAULT;
 
diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S
index 20e5f7b..076745f 100644
--- a/arch/x86/ia32/ia32entry.S
+++ b/arch/x86/ia32/ia32entry.S
@@ -14,6 +14,7 @@
 #include <asm/segment.h>
 #include <asm/irqflags.h>
 #include <asm/asm.h>
+#include <asm/smap.h>
 #include <linux/linkage.h>
 #include <linux/err.h>
 
@@ -146,8 +147,10 @@ ENTRY(ia32_sysenter_target)
 	SAVE_ARGS 0,1,0
  	/* no need to do an access_ok check here because rbp has been
  	   32bit zero extended */ 
+	ASM_STAC
 1:	movl	(%rbp),%ebp
 	_ASM_EXTABLE(1b,ia32_badarg)
+	ASM_CLAC
 	orl     $TS_COMPAT,TI_status+THREAD_INFO(%rsp,RIP-ARGOFFSET)
 	testl   $_TIF_WORK_SYSCALL_ENTRY,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)
 	CFI_REMEMBER_STATE
@@ -301,8 +304,10 @@ ENTRY(ia32_cstar_target)
 	/* no need to do an access_ok check here because r8 has been
 	   32bit zero extended */ 
 	/* hardware stack frame is complete now */	
+	ASM_STAC
 1:	movl	(%r8),%r9d
 	_ASM_EXTABLE(1b,ia32_badarg)
+	ASM_CLAC
 	orl     $TS_COMPAT,TI_status+THREAD_INFO(%rsp,RIP-ARGOFFSET)
 	testl   $_TIF_WORK_SYSCALL_ENTRY,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)
 	CFI_REMEMBER_STATE
@@ -365,6 +370,7 @@ cstar_tracesys:
 END(ia32_cstar_target)
 				
 ia32_badarg:
+	ASM_CLAC
 	movq $-EFAULT,%rax
 	jmp ia32_sysret
 	CFI_ENDPROC
@@ -459,7 +465,7 @@ GLOBAL(\label)
 	PTREGSCALL stub32_rt_sigreturn, sys32_rt_sigreturn, %rdi
 	PTREGSCALL stub32_sigreturn, sys32_sigreturn, %rdi
 	PTREGSCALL stub32_sigaltstack, sys32_sigaltstack, %rdx
-	PTREGSCALL stub32_execve, sys32_execve, %rcx
+	PTREGSCALL stub32_execve, compat_sys_execve, %rcx
 	PTREGSCALL stub32_fork, sys_fork, %rdi
 	PTREGSCALL stub32_clone, sys32_clone, %rdx
 	PTREGSCALL stub32_vfork, sys_vfork, %rdi
diff --git a/arch/x86/ia32/sys_ia32.c b/arch/x86/ia32/sys_ia32.c
index 4540bec..86d68d1 100644
--- a/arch/x86/ia32/sys_ia32.c
+++ b/arch/x86/ia32/sys_ia32.c
@@ -287,7 +287,7 @@ asmlinkage long sys32_sigaction(int sig, struct old_sigaction32 __user *act,
 	return ret;
 }
 
-asmlinkage long sys32_waitpid(compat_pid_t pid, unsigned int *stat_addr,
+asmlinkage long sys32_waitpid(compat_pid_t pid, unsigned int __user *stat_addr,
 			      int options)
 {
 	return compat_sys_wait4(pid, stat_addr, options, NULL);
@@ -385,21 +385,6 @@ asmlinkage long sys32_sendfile(int out_fd, int in_fd,
 	return ret;
 }
 
-asmlinkage long sys32_execve(const char __user *name, compat_uptr_t __user *argv,
-			     compat_uptr_t __user *envp, struct pt_regs *regs)
-{
-	long error;
-	char *filename;
-
-	filename = getname(name);
-	error = PTR_ERR(filename);
-	if (IS_ERR(filename))
-		return error;
-	error = compat_do_execve(filename, argv, envp, regs);
-	putname(filename);
-	return error;
-}
-
 asmlinkage long sys32_clone(unsigned int clone_flags, unsigned int newsp,
 			    struct pt_regs *regs)
 {
diff --git a/arch/x86/include/asm/alternative-asm.h b/arch/x86/include/asm/alternative-asm.h
index 952bd01..372231c 100644
--- a/arch/x86/include/asm/alternative-asm.h
+++ b/arch/x86/include/asm/alternative-asm.h
@@ -1,3 +1,6 @@
+#ifndef _ASM_X86_ALTERNATIVE_ASM_H
+#define _ASM_X86_ALTERNATIVE_ASM_H
+
 #ifdef __ASSEMBLY__
 
 #include <asm/asm.h>
@@ -5,10 +8,10 @@
 #ifdef CONFIG_SMP
 	.macro LOCK_PREFIX
 672:	lock
-	.section .smp_locks,"a"
+	.pushsection .smp_locks,"a"
 	.balign 4
 	.long 672b - .
-	.previous
+	.popsection
 	.endm
 #else
 	.macro LOCK_PREFIX
@@ -24,3 +27,5 @@
 .endm
 
 #endif  /*  __ASSEMBLY__  */
+
+#endif /* _ASM_X86_ALTERNATIVE_ASM_H */
diff --git a/arch/x86/include/asm/alternative.h b/arch/x86/include/asm/alternative.h
index 7078068..58ed6d9 100644
--- a/arch/x86/include/asm/alternative.h
+++ b/arch/x86/include/asm/alternative.h
@@ -29,10 +29,10 @@
 
 #ifdef CONFIG_SMP
 #define LOCK_PREFIX_HERE \
-		".section .smp_locks,\"a\"\n"	\
-		".balign 4\n"			\
-		".long 671f - .\n" /* offset */	\
-		".previous\n"			\
+		".pushsection .smp_locks,\"a\"\n"	\
+		".balign 4\n"				\
+		".long 671f - .\n" /* offset */		\
+		".popsection\n"				\
 		"671:"
 
 #define LOCK_PREFIX LOCK_PREFIX_HERE "\n\tlock; "
@@ -60,7 +60,7 @@ extern void alternatives_smp_module_add(struct module *mod, char *name,
 					void *locks, void *locks_end,
 					void *text, void *text_end);
 extern void alternatives_smp_module_del(struct module *mod);
-extern void alternatives_smp_switch(int smp);
+extern void alternatives_enable_smp(void);
 extern int alternatives_text_reserved(void *start, void *end);
 extern bool skip_smp_alternatives;
 #else
@@ -68,7 +68,7 @@ static inline void alternatives_smp_module_add(struct module *mod, char *name,
 					       void *locks, void *locks_end,
 					       void *text, void *text_end) {}
 static inline void alternatives_smp_module_del(struct module *mod) {}
-static inline void alternatives_smp_switch(int smp) {}
+static inline void alternatives_enable_smp(void) {}
 static inline int alternatives_text_reserved(void *start, void *end)
 {
 	return 0;
@@ -99,30 +99,30 @@ static inline int alternatives_text_reserved(void *start, void *end)
 /* alternative assembly primitive: */
 #define ALTERNATIVE(oldinstr, newinstr, feature)			\
 	OLDINSTR(oldinstr)						\
-	".section .altinstructions,\"a\"\n"				\
+	".pushsection .altinstructions,\"a\"\n"				\
 	ALTINSTR_ENTRY(feature, 1)					\
-	".previous\n"							\
-	".section .discard,\"aw\",@progbits\n"				\
+	".popsection\n"							\
+	".pushsection .discard,\"aw\",@progbits\n"			\
 	DISCARD_ENTRY(1)						\
-	".previous\n"							\
-	".section .altinstr_replacement, \"ax\"\n"			\
+	".popsection\n"							\
+	".pushsection .altinstr_replacement, \"ax\"\n"			\
 	ALTINSTR_REPLACEMENT(newinstr, feature, 1)			\
-	".previous"
+	".popsection"
 
 #define ALTERNATIVE_2(oldinstr, newinstr1, feature1, newinstr2, feature2)\
 	OLDINSTR(oldinstr)						\
-	".section .altinstructions,\"a\"\n"				\
+	".pushsection .altinstructions,\"a\"\n"				\
 	ALTINSTR_ENTRY(feature1, 1)					\
 	ALTINSTR_ENTRY(feature2, 2)					\
-	".previous\n"							\
-	".section .discard,\"aw\",@progbits\n"				\
+	".popsection\n"							\
+	".pushsection .discard,\"aw\",@progbits\n"			\
 	DISCARD_ENTRY(1)						\
 	DISCARD_ENTRY(2)						\
-	".previous\n"							\
-	".section .altinstr_replacement, \"ax\"\n"			\
+	".popsection\n"							\
+	".pushsection .altinstr_replacement, \"ax\"\n"			\
 	ALTINSTR_REPLACEMENT(newinstr1, feature1, 1)			\
 	ALTINSTR_REPLACEMENT(newinstr2, feature2, 2)			\
-	".previous"
+	".popsection"
 
 /*
  * This must be included *after* the definition of ALTERNATIVE due to
diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
index f342612..3388034 100644
--- a/arch/x86/include/asm/apic.h
+++ b/arch/x86/include/asm/apic.h
@@ -409,7 +409,7 @@ extern struct apic *apic;
  * to enforce the order with in them.
  */
 #define apic_driver(sym)					\
-	static struct apic *__apicdrivers_##sym __used		\
+	static const struct apic *__apicdrivers_##sym __used		\
 	__aligned(sizeof(struct apic *))			\
 	__section(.apicdrivers) = { &sym }
 
diff --git a/arch/x86/include/asm/atomic.h b/arch/x86/include/asm/atomic.h
index 58cb6d4..2faac43 100644
--- a/arch/x86/include/asm/atomic.h
+++ b/arch/x86/include/asm/atomic.h
@@ -240,30 +240,6 @@ static inline int __atomic_add_unless(atomic_t *v, int a, int u)
 	return c;
 }
 
-
-/*
- * atomic_dec_if_positive - decrement by 1 if old value positive
- * @v: pointer of type atomic_t
- *
- * The function returns the old value of *v minus 1, even if
- * the atomic variable, v, was not decremented.
- */
-static inline int atomic_dec_if_positive(atomic_t *v)
-{
-	int c, old, dec;
-	c = atomic_read(v);
-	for (;;) {
-		dec = c - 1;
-		if (unlikely(dec < 0))
-			break;
-		old = atomic_cmpxchg((v), c, dec);
-		if (likely(old == c))
-			break;
-		c = old;
-	}
-	return dec;
-}
-
 /**
  * atomic_inc_short - increment of a short integer
  * @v: pointer to type int
diff --git a/arch/x86/include/asm/bitops.h b/arch/x86/include/asm/bitops.h
index 72f5009..6dfd019 100644
--- a/arch/x86/include/asm/bitops.h
+++ b/arch/x86/include/asm/bitops.h
@@ -355,7 +355,7 @@ static int test_bit(int nr, const volatile unsigned long *addr);
  */
 static inline unsigned long __ffs(unsigned long word)
 {
-	asm("bsf %1,%0"
+	asm("rep; bsf %1,%0"
 		: "=r" (word)
 		: "rm" (word));
 	return word;
@@ -369,7 +369,7 @@ static inline unsigned long __ffs(unsigned long word)
  */
 static inline unsigned long ffz(unsigned long word)
 {
-	asm("bsf %1,%0"
+	asm("rep; bsf %1,%0"
 		: "=r" (word)
 		: "r" (~word));
 	return word;
@@ -417,10 +417,9 @@ static inline int ffs(int x)
 	 * We cannot do this on 32 bits because at the very least some
 	 * 486 CPUs did not behave this way.
 	 */
-	long tmp = -1;
 	asm("bsfl %1,%0"
 	    : "=r" (r)
-	    : "rm" (x), "0" (tmp));
+	    : "rm" (x), "0" (-1));
 #elif defined(CONFIG_X86_CMOV)
 	asm("bsfl %1,%0\n\t"
 	    "cmovzl %2,%0"
@@ -459,10 +458,9 @@ static inline int fls(int x)
 	 * We cannot do this on 32 bits because at the very least some
 	 * 486 CPUs did not behave this way.
 	 */
-	long tmp = -1;
 	asm("bsrl %1,%0"
 	    : "=r" (r)
-	    : "rm" (x), "0" (tmp));
+	    : "rm" (x), "0" (-1));
 #elif defined(CONFIG_X86_CMOV)
 	asm("bsrl %1,%0\n\t"
 	    "cmovzl %2,%0"
@@ -490,13 +488,13 @@ static inline int fls(int x)
 #ifdef CONFIG_X86_64
 static __always_inline int fls64(__u64 x)
 {
-	long bitpos = -1;
+	int bitpos = -1;
 	/*
 	 * AMD64 says BSRQ won't clobber the dest reg if x==0; Intel64 says the
 	 * dest reg is undefined if x==0, but their CPU architect says its
 	 * value is written to set it to the same as before.
 	 */
-	asm("bsrq %1,%0"
+	asm("bsrq %1,%q0"
 	    : "+r" (bitpos)
 	    : "rm" (x));
 	return bitpos + 1;
diff --git a/arch/x86/include/asm/compat.h b/arch/x86/include/asm/compat.h
index fedf32b..59c6c40 100644
--- a/arch/x86/include/asm/compat.h
+++ b/arch/x86/include/asm/compat.h
@@ -41,6 +41,7 @@ typedef s64 __attribute__((aligned(4))) compat_s64;
 typedef u32		compat_uint_t;
 typedef u32		compat_ulong_t;
 typedef u64 __attribute__((aligned(4))) compat_u64;
+typedef u32		compat_uptr_t;
 
 struct compat_timespec {
 	compat_time_t	tv_sec;
@@ -124,6 +125,78 @@ typedef u32		compat_old_sigset_t;	/* at least 32 bits */
 
 typedef u32               compat_sigset_word;
 
+typedef union compat_sigval {
+	compat_int_t	sival_int;
+	compat_uptr_t	sival_ptr;
+} compat_sigval_t;
+
+typedef struct compat_siginfo {
+	int si_signo;
+	int si_errno;
+	int si_code;
+
+	union {
+		int _pad[128/sizeof(int) - 3];
+
+		/* kill() */
+		struct {
+			unsigned int _pid;	/* sender's pid */
+			unsigned int _uid;	/* sender's uid */
+		} _kill;
+
+		/* POSIX.1b timers */
+		struct {
+			compat_timer_t _tid;	/* timer id */
+			int _overrun;		/* overrun count */
+			compat_sigval_t _sigval;	/* same as below */
+			int _sys_private;	/* not to be passed to user */
+			int _overrun_incr;	/* amount to add to overrun */
+		} _timer;
+
+		/* POSIX.1b signals */
+		struct {
+			unsigned int _pid;	/* sender's pid */
+			unsigned int _uid;	/* sender's uid */
+			compat_sigval_t _sigval;
+		} _rt;
+
+		/* SIGCHLD */
+		struct {
+			unsigned int _pid;	/* which child */
+			unsigned int _uid;	/* sender's uid */
+			int _status;		/* exit code */
+			compat_clock_t _utime;
+			compat_clock_t _stime;
+		} _sigchld;
+
+		/* SIGCHLD (x32 version) */
+		struct {
+			unsigned int _pid;	/* which child */
+			unsigned int _uid;	/* sender's uid */
+			int _status;		/* exit code */
+			compat_s64 _utime;
+			compat_s64 _stime;
+		} _sigchld_x32;
+
+		/* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
+		struct {
+			unsigned int _addr;	/* faulting insn/memory ref. */
+		} _sigfault;
+
+		/* SIGPOLL */
+		struct {
+			int _band;	/* POLL_IN, POLL_OUT, POLL_MSG */
+			int _fd;
+		} _sigpoll;
+
+		struct {
+			unsigned int _call_addr; /* calling insn */
+			int _syscall;	/* triggering system call number */
+			unsigned int _arch;	/* AUDIT_ARCH_* of syscall */
+		} _sigsys;
+	} _sifields;
+} compat_siginfo_t;
+
 #define COMPAT_OFF_T_MAX	0x7fffffff
 #define COMPAT_LOFF_T_MAX	0x7fffffffffffffffL
 
@@ -209,7 +282,6 @@ typedef struct user_regs_struct32 compat_elf_gregset_t;
  * as pointers because the syscall entry code will have
  * appropriately converted them already.
  */
-typedef	u32		compat_uptr_t;
 
 static inline void __user *compat_ptr(compat_uptr_t uptr)
 {
diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h
index 6b7ee5f..16cae42 100644
--- a/arch/x86/include/asm/cpufeature.h
+++ b/arch/x86/include/asm/cpufeature.h
@@ -97,6 +97,7 @@
 #define X86_FEATURE_EXTD_APICID	(3*32+26) /* has extended APICID (8 bits) */
 #define X86_FEATURE_AMD_DCM     (3*32+27) /* multi-node processor */
 #define X86_FEATURE_APERFMPERF	(3*32+28) /* APERFMPERF */
+#define X86_FEATURE_EAGER_FPU	(3*32+29) /* "eagerfpu" Non lazy FPU restore */
 
 /* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */
 #define X86_FEATURE_XMM3	(4*32+ 0) /* "pni" SSE-3 */
@@ -209,6 +210,7 @@
 #define X86_FEATURE_RTM		(9*32+11) /* Restricted Transactional Memory */
 #define X86_FEATURE_RDSEED	(9*32+18) /* The RDSEED instruction */
 #define X86_FEATURE_ADX		(9*32+19) /* The ADCX and ADOX instructions */
+#define X86_FEATURE_SMAP	(9*32+20) /* Supervisor Mode Access Prevention */
 
 #if defined(__KERNEL__) && !defined(__ASSEMBLY__)
 
@@ -299,12 +301,14 @@ extern const char * const x86_power_flags[32];
 #define cpu_has_xmm4_2		boot_cpu_has(X86_FEATURE_XMM4_2)
 #define cpu_has_x2apic		boot_cpu_has(X86_FEATURE_X2APIC)
 #define cpu_has_xsave		boot_cpu_has(X86_FEATURE_XSAVE)
+#define cpu_has_xsaveopt	boot_cpu_has(X86_FEATURE_XSAVEOPT)
 #define cpu_has_osxsave		boot_cpu_has(X86_FEATURE_OSXSAVE)
 #define cpu_has_hypervisor	boot_cpu_has(X86_FEATURE_HYPERVISOR)
 #define cpu_has_pclmulqdq	boot_cpu_has(X86_FEATURE_PCLMULQDQ)
 #define cpu_has_perfctr_core	boot_cpu_has(X86_FEATURE_PERFCTR_CORE)
 #define cpu_has_cx8		boot_cpu_has(X86_FEATURE_CX8)
 #define cpu_has_cx16		boot_cpu_has(X86_FEATURE_CX16)
+#define cpu_has_eager_fpu	boot_cpu_has(X86_FEATURE_EAGER_FPU)
 
 #if defined(CONFIG_X86_INVLPG) || defined(CONFIG_X86_64)
 # define cpu_has_invlpg		1
diff --git a/arch/x86/include/asm/fpu-internal.h b/arch/x86/include/asm/fpu-internal.h
index 75f4c6d..409b9cc 100644
--- a/arch/x86/include/asm/fpu-internal.h
+++ b/arch/x86/include/asm/fpu-internal.h
@@ -12,6 +12,7 @@
 
 #include <linux/kernel_stat.h>
 #include <linux/regset.h>
+#include <linux/compat.h>
 #include <linux/slab.h>
 #include <asm/asm.h>
 #include <asm/cpufeature.h>
@@ -20,43 +21,76 @@
 #include <asm/user.h>
 #include <asm/uaccess.h>
 #include <asm/xsave.h>
+#include <asm/smap.h>
 
-extern unsigned int sig_xstate_size;
+#ifdef CONFIG_X86_64
+# include <asm/sigcontext32.h>
+# include <asm/user32.h>
+int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+			compat_sigset_t *set, struct pt_regs *regs);
+int ia32_setup_frame(int sig, struct k_sigaction *ka,
+		     compat_sigset_t *set, struct pt_regs *regs);
+#else
+# define user_i387_ia32_struct	user_i387_struct
+# define user32_fxsr_struct	user_fxsr_struct
+# define ia32_setup_frame	__setup_frame
+# define ia32_setup_rt_frame	__setup_rt_frame
+#endif
+
+extern unsigned int mxcsr_feature_mask;
 extern void fpu_init(void);
+extern void eager_fpu_init(void);
 
 DECLARE_PER_CPU(struct task_struct *, fpu_owner_task);
 
+extern void convert_from_fxsr(struct user_i387_ia32_struct *env,
+			      struct task_struct *tsk);
+extern void convert_to_fxsr(struct task_struct *tsk,
+			    const struct user_i387_ia32_struct *env);
+
 extern user_regset_active_fn fpregs_active, xfpregs_active;
 extern user_regset_get_fn fpregs_get, xfpregs_get, fpregs_soft_get,
 				xstateregs_get;
 extern user_regset_set_fn fpregs_set, xfpregs_set, fpregs_soft_set,
 				 xstateregs_set;
 
-
 /*
  * xstateregs_active == fpregs_active. Please refer to the comment
  * at the definition of fpregs_active.
  */
 #define xstateregs_active	fpregs_active
 
-extern struct _fpx_sw_bytes fx_sw_reserved;
-#ifdef CONFIG_IA32_EMULATION
-extern unsigned int sig_xstate_ia32_size;
-extern struct _fpx_sw_bytes fx_sw_reserved_ia32;
-struct _fpstate_ia32;
-struct _xstate_ia32;
-extern int save_i387_xstate_ia32(void __user *buf);
-extern int restore_i387_xstate_ia32(void __user *buf);
-#endif
-
 #ifdef CONFIG_MATH_EMULATION
+# define HAVE_HWFP		(boot_cpu_data.hard_math)
 extern void finit_soft_fpu(struct i387_soft_struct *soft);
 #else
+# define HAVE_HWFP		1
 static inline void finit_soft_fpu(struct i387_soft_struct *soft) {}
 #endif
 
+static inline int is_ia32_compat_frame(void)
+{
+	return config_enabled(CONFIG_IA32_EMULATION) &&
+	       test_thread_flag(TIF_IA32);
+}
+
+static inline int is_ia32_frame(void)
+{
+	return config_enabled(CONFIG_X86_32) || is_ia32_compat_frame();
+}
+
+static inline int is_x32_frame(void)
+{
+	return config_enabled(CONFIG_X86_X32_ABI) && test_thread_flag(TIF_X32);
+}
+
 #define X87_FSW_ES (1 << 7)	/* Exception Summary */
 
+static __always_inline __pure bool use_eager_fpu(void)
+{
+	return static_cpu_has(X86_FEATURE_EAGER_FPU);
+}
+
 static __always_inline __pure bool use_xsaveopt(void)
 {
 	return static_cpu_has(X86_FEATURE_XSAVEOPT);
@@ -72,6 +106,13 @@ static __always_inline __pure bool use_fxsr(void)
         return static_cpu_has(X86_FEATURE_FXSR);
 }
 
+static inline void fx_finit(struct i387_fxsave_struct *fx)
+{
+	memset(fx, 0, xstate_size);
+	fx->cwd = 0x37f;
+	fx->mxcsr = MXCSR_DEFAULT;
+}
+
 extern void __sanitize_i387_state(struct task_struct *);
 
 static inline void sanitize_i387_state(struct task_struct *tsk)
@@ -81,131 +122,104 @@ static inline void sanitize_i387_state(struct task_struct *tsk)
 	__sanitize_i387_state(tsk);
 }
 
-#ifdef CONFIG_X86_64
-static inline int fxrstor_checking(struct i387_fxsave_struct *fx)
-{
-	int err;
-
-	/* See comment in fxsave() below. */
-#ifdef CONFIG_AS_FXSAVEQ
-	asm volatile("1:  fxrstorq %[fx]\n\t"
-		     "2:\n"
-		     ".section .fixup,\"ax\"\n"
-		     "3:  movl $-1,%[err]\n"
-		     "    jmp  2b\n"
-		     ".previous\n"
-		     _ASM_EXTABLE(1b, 3b)
-		     : [err] "=r" (err)
-		     : [fx] "m" (*fx), "0" (0));
-#else
-	asm volatile("1:  rex64/fxrstor (%[fx])\n\t"
-		     "2:\n"
-		     ".section .fixup,\"ax\"\n"
-		     "3:  movl $-1,%[err]\n"
-		     "    jmp  2b\n"
-		     ".previous\n"
-		     _ASM_EXTABLE(1b, 3b)
-		     : [err] "=r" (err)
-		     : [fx] "R" (fx), "m" (*fx), "0" (0));
-#endif
-	return err;
+#define user_insn(insn, output, input...)				\
+({									\
+	int err;							\
+	asm volatile(ASM_STAC "\n"					\
+		     "1:" #insn "\n\t"					\
+		     "2: " ASM_CLAC "\n"				\
+		     ".section .fixup,\"ax\"\n"				\
+		     "3:  movl $-1,%[err]\n"				\
+		     "    jmp  2b\n"					\
+		     ".previous\n"					\
+		     _ASM_EXTABLE(1b, 3b)				\
+		     : [err] "=r" (err), output				\
+		     : "0"(0), input);					\
+	err;								\
+})
+
+#define check_insn(insn, output, input...)				\
+({									\
+	int err;							\
+	asm volatile("1:" #insn "\n\t"					\
+		     "2:\n"						\
+		     ".section .fixup,\"ax\"\n"				\
+		     "3:  movl $-1,%[err]\n"				\
+		     "    jmp  2b\n"					\
+		     ".previous\n"					\
+		     _ASM_EXTABLE(1b, 3b)				\
+		     : [err] "=r" (err), output				\
+		     : "0"(0), input);					\
+	err;								\
+})
+
+static inline int fsave_user(struct i387_fsave_struct __user *fx)
+{
+	return user_insn(fnsave %[fx]; fwait,  [fx] "=m" (*fx), "m" (*fx));
 }
 
 static inline int fxsave_user(struct i387_fxsave_struct __user *fx)
 {
-	int err;
+	if (config_enabled(CONFIG_X86_32))
+		return user_insn(fxsave %[fx], [fx] "=m" (*fx), "m" (*fx));
+	else if (config_enabled(CONFIG_AS_FXSAVEQ))
+		return user_insn(fxsaveq %[fx], [fx] "=m" (*fx), "m" (*fx));
 
-	/*
-	 * Clear the bytes not touched by the fxsave and reserved
-	 * for the SW usage.
-	 */
-	err = __clear_user(&fx->sw_reserved,
-			   sizeof(struct _fpx_sw_bytes));
-	if (unlikely(err))
-		return -EFAULT;
-
-	/* See comment in fxsave() below. */
-#ifdef CONFIG_AS_FXSAVEQ
-	asm volatile("1:  fxsaveq %[fx]\n\t"
-		     "2:\n"
-		     ".section .fixup,\"ax\"\n"
-		     "3:  movl $-1,%[err]\n"
-		     "    jmp  2b\n"
-		     ".previous\n"
-		     _ASM_EXTABLE(1b, 3b)
-		     : [err] "=r" (err), [fx] "=m" (*fx)
-		     : "0" (0));
-#else
-	asm volatile("1:  rex64/fxsave (%[fx])\n\t"
-		     "2:\n"
-		     ".section .fixup,\"ax\"\n"
-		     "3:  movl $-1,%[err]\n"
-		     "    jmp  2b\n"
-		     ".previous\n"
-		     _ASM_EXTABLE(1b, 3b)
-		     : [err] "=r" (err), "=m" (*fx)
-		     : [fx] "R" (fx), "0" (0));
-#endif
-	if (unlikely(err) &&
-	    __clear_user(fx, sizeof(struct i387_fxsave_struct)))
-		err = -EFAULT;
-	/* No need to clear here because the caller clears USED_MATH */
-	return err;
+	/* See comment in fpu_fxsave() below. */
+	return user_insn(rex64/fxsave (%[fx]), "=m" (*fx), [fx] "R" (fx));
 }
 
-static inline void fpu_fxsave(struct fpu *fpu)
+static inline int fxrstor_checking(struct i387_fxsave_struct *fx)
 {
-	/* Using "rex64; fxsave %0" is broken because, if the memory operand
-	   uses any extended registers for addressing, a second REX prefix
-	   will be generated (to the assembler, rex64 followed by semicolon
-	   is a separate instruction), and hence the 64-bitness is lost. */
+	if (config_enabled(CONFIG_X86_32))
+		return check_insn(fxrstor %[fx], "=m" (*fx), [fx] "m" (*fx));
+	else if (config_enabled(CONFIG_AS_FXSAVEQ))
+		return check_insn(fxrstorq %[fx], "=m" (*fx), [fx] "m" (*fx));
 
-#ifdef CONFIG_AS_FXSAVEQ
-	/* Using "fxsaveq %0" would be the ideal choice, but is only supported
-	   starting with gas 2.16. */
-	__asm__ __volatile__("fxsaveq %0"
-			     : "=m" (fpu->state->fxsave));
-#else
-	/* Using, as a workaround, the properly prefixed form below isn't
-	   accepted by any binutils version so far released, complaining that
-	   the same type of prefix is used twice if an extended register is
-	   needed for addressing (fix submitted to mainline 2005-11-21).
-	asm volatile("rex64/fxsave %0"
-		     : "=m" (fpu->state->fxsave));
-	   This, however, we can work around by forcing the compiler to select
-	   an addressing mode that doesn't require extended registers. */
-	asm volatile("rex64/fxsave (%[fx])"
-		     : "=m" (fpu->state->fxsave)
-		     : [fx] "R" (&fpu->state->fxsave));
-#endif
+	/* See comment in fpu_fxsave() below. */
+	return check_insn(rex64/fxrstor (%[fx]), "=m" (*fx), [fx] "R" (fx),
+			  "m" (*fx));
 }
 
-#else  /* CONFIG_X86_32 */
-
-/* perform fxrstor iff the processor has extended states, otherwise frstor */
-static inline int fxrstor_checking(struct i387_fxsave_struct *fx)
+static inline int frstor_checking(struct i387_fsave_struct *fx)
 {
-	/*
-	 * The "nop" is needed to make the instructions the same
-	 * length.
-	 */
-	alternative_input(
-		"nop ; frstor %1",
-		"fxrstor %1",
-		X86_FEATURE_FXSR,
-		"m" (*fx));
-
-	return 0;
+	return check_insn(frstor %[fx], "=m" (*fx), [fx] "m" (*fx));
 }
 
 static inline void fpu_fxsave(struct fpu *fpu)
 {
-	asm volatile("fxsave %[fx]"
-		     : [fx] "=m" (fpu->state->fxsave));
+	if (config_enabled(CONFIG_X86_32))
+		asm volatile( "fxsave %[fx]" : [fx] "=m" (fpu->state->fxsave));
+	else if (config_enabled(CONFIG_AS_FXSAVEQ))
+		asm volatile("fxsaveq %0" : "=m" (fpu->state->fxsave));
+	else {
+		/* Using "rex64; fxsave %0" is broken because, if the memory
+		 * operand uses any extended registers for addressing, a second
+		 * REX prefix will be generated (to the assembler, rex64
+		 * followed by semicolon is a separate instruction), and hence
+		 * the 64-bitness is lost.
+		 *
+		 * Using "fxsaveq %0" would be the ideal choice, but is only
+		 * supported starting with gas 2.16.
+		 *
+		 * Using, as a workaround, the properly prefixed form below
+		 * isn't accepted by any binutils version so far released,
+		 * complaining that the same type of prefix is used twice if
+		 * an extended register is needed for addressing (fix submitted
+		 * to mainline 2005-11-21).
+		 *
+		 *  asm volatile("rex64/fxsave %0" : "=m" (fpu->state->fxsave));
+		 *
+		 * This, however, we can work around by forcing the compiler to
+		 * select an addressing mode that doesn't require extended
+		 * registers.
+		 */
+		asm volatile( "rex64/fxsave (%[fx])"
+			     : "=m" (fpu->state->fxsave)
+			     : [fx] "R" (&fpu->state->fxsave));
+	}
 }
 
-#endif	/* CONFIG_X86_64 */
-
 /*
  * These must be called with preempt disabled. Returns
  * 'true' if the FPU state is still intact.
@@ -248,17 +262,14 @@ static inline int __save_init_fpu(struct task_struct *tsk)
 	return fpu_save_init(&tsk->thread.fpu);
 }
 
-static inline int fpu_fxrstor_checking(struct fpu *fpu)
-{
-	return fxrstor_checking(&fpu->state->fxsave);
-}
-
 static inline int fpu_restore_checking(struct fpu *fpu)
 {
 	if (use_xsave())
-		return fpu_xrstor_checking(fpu);
+		return fpu_xrstor_checking(&fpu->state->xsave);
+	else if (use_fxsr())
+		return fxrstor_checking(&fpu->state->fxsave);
 	else
-		return fpu_fxrstor_checking(fpu);
+		return frstor_checking(&fpu->state->fsave);
 }
 
 static inline int restore_fpu_checking(struct task_struct *tsk)
@@ -310,15 +321,52 @@ static inline void __thread_set_has_fpu(struct task_struct *tsk)
 static inline void __thread_fpu_end(struct task_struct *tsk)
 {
 	__thread_clear_has_fpu(tsk);
-	stts();
+	if (!use_eager_fpu())
+		stts();
 }
 
 static inline void __thread_fpu_begin(struct task_struct *tsk)
 {
-	clts();
+	if (!use_eager_fpu())
+		clts();
 	__thread_set_has_fpu(tsk);
 }
 
+static inline void __drop_fpu(struct task_struct *tsk)
+{
+	if (__thread_has_fpu(tsk)) {
+		/* Ignore delayed exceptions from user space */
+		asm volatile("1: fwait\n"
+			     "2:\n"
+			     _ASM_EXTABLE(1b, 2b));
+		__thread_fpu_end(tsk);
+	}
+}
+
+static inline void drop_fpu(struct task_struct *tsk)
+{
+	/*
+	 * Forget coprocessor state..
+	 */
+	preempt_disable();
+	tsk->fpu_counter = 0;
+	__drop_fpu(tsk);
+	clear_used_math();
+	preempt_enable();
+}
+
+static inline void drop_init_fpu(struct task_struct *tsk)
+{
+	if (!use_eager_fpu())
+		drop_fpu(tsk);
+	else {
+		if (use_xsave())
+			xrstor_state(init_xstate_buf, -1);
+		else
+			fxrstor_checking(&init_xstate_buf->i387);
+	}
+}
+
 /*
  * FPU state switching for scheduling.
  *
@@ -352,7 +400,12 @@ static inline fpu_switch_t switch_fpu_prepare(struct task_struct *old, struct ta
 {
 	fpu_switch_t fpu;
 
-	fpu.preload = tsk_used_math(new) && new->fpu_counter > 5;
+	/*
+	 * If the task has used the math, pre-load the FPU on xsave processors
+	 * or if the past 5 consecutive context-switches used math.
+	 */
+	fpu.preload = tsk_used_math(new) && (use_eager_fpu() ||
+					     new->fpu_counter > 5);
 	if (__thread_has_fpu(old)) {
 		if (!__save_init_fpu(old))
 			cpu = ~0;
@@ -364,14 +417,14 @@ static inline fpu_switch_t switch_fpu_prepare(struct task_struct *old, struct ta
 			new->fpu_counter++;
 			__thread_set_has_fpu(new);
 			prefetch(new->thread.fpu.state);
-		} else
+		} else if (!use_eager_fpu())
 			stts();
 	} else {
 		old->fpu_counter = 0;
 		old->thread.fpu.last_cpu = ~0;
 		if (fpu.preload) {
 			new->fpu_counter++;
-			if (fpu_lazy_restore(new, cpu))
+			if (!use_eager_fpu() && fpu_lazy_restore(new, cpu))
 				fpu.preload = 0;
 			else
 				prefetch(new->thread.fpu.state);
@@ -391,44 +444,40 @@ static inline void switch_fpu_finish(struct task_struct *new, fpu_switch_t fpu)
 {
 	if (fpu.preload) {
 		if (unlikely(restore_fpu_checking(new)))
-			__thread_fpu_end(new);
+			drop_init_fpu(new);
 	}
 }
 
 /*
  * Signal frame handlers...
  */
-extern int save_i387_xstate(void __user *buf);
-extern int restore_i387_xstate(void __user *buf);
+extern int save_xstate_sig(void __user *buf, void __user *fx, int size);
+extern int __restore_xstate_sig(void __user *buf, void __user *fx, int size);
 
-static inline void __clear_fpu(struct task_struct *tsk)
+static inline int xstate_sigframe_size(void)
 {
-	if (__thread_has_fpu(tsk)) {
-		/* Ignore delayed exceptions from user space */
-		asm volatile("1: fwait\n"
-			     "2:\n"
-			     _ASM_EXTABLE(1b, 2b));
-		__thread_fpu_end(tsk);
+	return use_xsave() ? xstate_size + FP_XSTATE_MAGIC2_SIZE : xstate_size;
+}
+
+static inline int restore_xstate_sig(void __user *buf, int ia32_frame)
+{
+	void __user *buf_fx = buf;
+	int size = xstate_sigframe_size();
+
+	if (ia32_frame && use_fxsr()) {
+		buf_fx = buf + sizeof(struct i387_fsave_struct);
+		size += sizeof(struct i387_fsave_struct);
 	}
+
+	return __restore_xstate_sig(buf, buf_fx, size);
 }
 
 /*
- * The actual user_fpu_begin/end() functions
- * need to be preemption-safe.
+ * Need to be preemption-safe.
  *
- * NOTE! user_fpu_end() must be used only after you
- * have saved the FP state, and user_fpu_begin() must
- * be used only immediately before restoring it.
- * These functions do not do any save/restore on
- * their own.
+ * NOTE! user_fpu_begin() must be used only immediately before restoring
+ * it. This function does not do any save/restore on their own.
  */
-static inline void user_fpu_end(void)
-{
-	preempt_disable();
-	__thread_fpu_end(current);
-	preempt_enable();
-}
-
 static inline void user_fpu_begin(void)
 {
 	preempt_disable();
@@ -437,25 +486,32 @@ static inline void user_fpu_begin(void)
 	preempt_enable();
 }
 
+static inline void __save_fpu(struct task_struct *tsk)
+{
+	if (use_xsave())
+		xsave_state(&tsk->thread.fpu.state->xsave, -1);
+	else
+		fpu_fxsave(&tsk->thread.fpu);
+}
+
 /*
  * These disable preemption on their own and are safe
  */
 static inline void save_init_fpu(struct task_struct *tsk)
 {
 	WARN_ON_ONCE(!__thread_has_fpu(tsk));
+
+	if (use_eager_fpu()) {
+		__save_fpu(tsk);
+		return;
+	}
+
 	preempt_disable();
 	__save_init_fpu(tsk);
 	__thread_fpu_end(tsk);
 	preempt_enable();
 }
 
-static inline void clear_fpu(struct task_struct *tsk)
-{
-	preempt_disable();
-	__clear_fpu(tsk);
-	preempt_enable();
-}
-
 /*
  * i387 state interaction
  */
@@ -510,11 +566,34 @@ static inline void fpu_free(struct fpu *fpu)
 	}
 }
 
-static inline void fpu_copy(struct fpu *dst, struct fpu *src)
+static inline void fpu_copy(struct task_struct *dst, struct task_struct *src)
 {
-	memcpy(dst->state, src->state, xstate_size);
+	if (use_eager_fpu()) {
+		memset(&dst->thread.fpu.state->xsave, 0, xstate_size);
+		__save_fpu(dst);
+	} else {
+		struct fpu *dfpu = &dst->thread.fpu;
+		struct fpu *sfpu = &src->thread.fpu;
+
+		unlazy_fpu(src);
+		memcpy(dfpu->state, sfpu->state, xstate_size);
+	}
 }
 
-extern void fpu_finit(struct fpu *fpu);
+static inline unsigned long
+alloc_mathframe(unsigned long sp, int ia32_frame, unsigned long *buf_fx,
+		unsigned long *size)
+{
+	unsigned long frame_size = xstate_sigframe_size();
+
+	*buf_fx = sp = round_down(sp - frame_size, 64);
+	if (ia32_frame && use_fxsr()) {
+		frame_size += sizeof(struct i387_fsave_struct);
+		sp -= sizeof(struct i387_fsave_struct);
+	}
+
+	*size = frame_size;
+	return sp;
+}
 
 #endif
diff --git a/arch/x86/include/asm/ftrace.h b/arch/x86/include/asm/ftrace.h
index b0767bc..9a25b52 100644
--- a/arch/x86/include/asm/ftrace.h
+++ b/arch/x86/include/asm/ftrace.h
@@ -3,38 +3,54 @@
 
 #ifdef __ASSEMBLY__
 
-	.macro MCOUNT_SAVE_FRAME
-	/* taken from glibc */
-	subq $0x38, %rsp
-	movq %rax, (%rsp)
-	movq %rcx, 8(%rsp)
-	movq %rdx, 16(%rsp)
-	movq %rsi, 24(%rsp)
-	movq %rdi, 32(%rsp)
-	movq %r8, 40(%rsp)
-	movq %r9, 48(%rsp)
+	/* skip is set if the stack was already partially adjusted */
+	.macro MCOUNT_SAVE_FRAME skip=0
+	 /*
+	  * We add enough stack to save all regs.
+	  */
+	subq $(SS+8-\skip), %rsp
+	movq %rax, RAX(%rsp)
+	movq %rcx, RCX(%rsp)
+	movq %rdx, RDX(%rsp)
+	movq %rsi, RSI(%rsp)
+	movq %rdi, RDI(%rsp)
+	movq %r8, R8(%rsp)
+	movq %r9, R9(%rsp)
+	 /* Move RIP to its proper location */
+	movq SS+8(%rsp), %rdx
+	movq %rdx, RIP(%rsp)
 	.endm
 
-	.macro MCOUNT_RESTORE_FRAME
-	movq 48(%rsp), %r9
-	movq 40(%rsp), %r8
-	movq 32(%rsp), %rdi
-	movq 24(%rsp), %rsi
-	movq 16(%rsp), %rdx
-	movq 8(%rsp), %rcx
-	movq (%rsp), %rax
-	addq $0x38, %rsp
+	.macro MCOUNT_RESTORE_FRAME skip=0
+	movq R9(%rsp), %r9
+	movq R8(%rsp), %r8
+	movq RDI(%rsp), %rdi
+	movq RSI(%rsp), %rsi
+	movq RDX(%rsp), %rdx
+	movq RCX(%rsp), %rcx
+	movq RAX(%rsp), %rax
+	addq $(SS+8-\skip), %rsp
 	.endm
 
 #endif
 
 #ifdef CONFIG_FUNCTION_TRACER
-#define MCOUNT_ADDR		((long)(mcount))
+#ifdef CC_USING_FENTRY
+# define MCOUNT_ADDR		((long)(__fentry__))
+#else
+# define MCOUNT_ADDR		((long)(mcount))
+#endif
 #define MCOUNT_INSN_SIZE	5 /* sizeof mcount call */
 
+#ifdef CONFIG_DYNAMIC_FTRACE
+#define ARCH_SUPPORTS_FTRACE_OPS 1
+#define ARCH_SUPPORTS_FTRACE_SAVE_REGS
+#endif
+
 #ifndef __ASSEMBLY__
 extern void mcount(void);
 extern atomic_t modifying_ftrace_code;
+extern void __fentry__(void);
 
 static inline unsigned long ftrace_call_adjust(unsigned long addr)
 {
diff --git a/arch/x86/include/asm/futex.h b/arch/x86/include/asm/futex.h
index 71ecbcb..f373046 100644
--- a/arch/x86/include/asm/futex.h
+++ b/arch/x86/include/asm/futex.h
@@ -9,10 +9,13 @@
 #include <asm/asm.h>
 #include <asm/errno.h>
 #include <asm/processor.h>
+#include <asm/smap.h>
 
 #define __futex_atomic_op1(insn, ret, oldval, uaddr, oparg)	\
-	asm volatile("1:\t" insn "\n"				\
-		     "2:\t.section .fixup,\"ax\"\n"		\
+	asm volatile("\t" ASM_STAC "\n"				\
+		     "1:\t" insn "\n"				\
+		     "2:\t" ASM_CLAC "\n"			\
+		     "\t.section .fixup,\"ax\"\n"		\
 		     "3:\tmov\t%3, %1\n"			\
 		     "\tjmp\t2b\n"				\
 		     "\t.previous\n"				\
@@ -21,12 +24,14 @@
 		     : "i" (-EFAULT), "0" (oparg), "1" (0))
 
 #define __futex_atomic_op2(insn, ret, oldval, uaddr, oparg)	\
-	asm volatile("1:\tmovl	%2, %0\n"			\
+	asm volatile("\t" ASM_STAC "\n"				\
+		     "1:\tmovl	%2, %0\n"			\
 		     "\tmovl\t%0, %3\n"				\
 		     "\t" insn "\n"				\
 		     "2:\t" LOCK_PREFIX "cmpxchgl %3, %2\n"	\
 		     "\tjnz\t1b\n"				\
-		     "3:\t.section .fixup,\"ax\"\n"		\
+		     "3:\t" ASM_CLAC "\n"			\
+		     "\t.section .fixup,\"ax\"\n"		\
 		     "4:\tmov\t%5, %1\n"			\
 		     "\tjmp\t3b\n"				\
 		     "\t.previous\n"				\
@@ -122,8 +127,10 @@ static inline int futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
 	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
-	asm volatile("1:\t" LOCK_PREFIX "cmpxchgl %4, %2\n"
-		     "2:\t.section .fixup, \"ax\"\n"
+	asm volatile("\t" ASM_STAC "\n"
+		     "1:\t" LOCK_PREFIX "cmpxchgl %4, %2\n"
+		     "2:\t" ASM_CLAC "\n"
+		     "\t.section .fixup, \"ax\"\n"
 		     "3:\tmov     %3, %0\n"
 		     "\tjmp     2b\n"
 		     "\t.previous\n"
diff --git a/arch/x86/include/asm/hpet.h b/arch/x86/include/asm/hpet.h
index 2c392d6..434e210 100644
--- a/arch/x86/include/asm/hpet.h
+++ b/arch/x86/include/asm/hpet.h
@@ -35,8 +35,6 @@
 #define	HPET_ID_NUMBER_SHIFT	8
 #define HPET_ID_VENDOR_SHIFT	16
 
-#define HPET_ID_VENDOR_8086	0x8086
-
 #define HPET_CFG_ENABLE		0x001
 #define HPET_CFG_LEGACY		0x002
 #define	HPET_LEGACY_8254	2
diff --git a/arch/x86/include/asm/hugetlb.h b/arch/x86/include/asm/hugetlb.h
index 439a9ac..bdd35db 100644
--- a/arch/x86/include/asm/hugetlb.h
+++ b/arch/x86/include/asm/hugetlb.h
@@ -90,4 +90,8 @@ static inline void arch_release_hugepage(struct page *page)
 {
 }
 
+static inline void arch_clear_hugepage_flags(struct page *page)
+{
+}
+
 #endif /* _ASM_X86_HUGETLB_H */
diff --git a/arch/x86/include/asm/i387.h b/arch/x86/include/asm/i387.h
index 257d9cc..ed8089d 100644
--- a/arch/x86/include/asm/i387.h
+++ b/arch/x86/include/asm/i387.h
@@ -19,12 +19,37 @@ struct pt_regs;
 struct user_i387_struct;
 
 extern int init_fpu(struct task_struct *child);
+extern void fpu_finit(struct fpu *fpu);
 extern int dump_fpu(struct pt_regs *, struct user_i387_struct *);
 extern void math_state_restore(void);
 
 extern bool irq_fpu_usable(void);
-extern void kernel_fpu_begin(void);
-extern void kernel_fpu_end(void);
+
+/*
+ * Careful: __kernel_fpu_begin/end() must be called with preempt disabled
+ * and they don't touch the preempt state on their own.
+ * If you enable preemption after __kernel_fpu_begin(), preempt notifier
+ * should call the __kernel_fpu_end() to prevent the kernel/user FPU
+ * state from getting corrupted. KVM for example uses this model.
+ *
+ * All other cases use kernel_fpu_begin/end() which disable preemption
+ * during kernel FPU usage.
+ */
+extern void __kernel_fpu_begin(void);
+extern void __kernel_fpu_end(void);
+
+static inline void kernel_fpu_begin(void)
+{
+	WARN_ON_ONCE(!irq_fpu_usable());
+	preempt_disable();
+	__kernel_fpu_begin();
+}
+
+static inline void kernel_fpu_end(void)
+{
+	__kernel_fpu_end();
+	preempt_enable();
+}
 
 /*
  * Some instructions like VIA's padlock instructions generate a spurious
diff --git a/arch/x86/include/asm/ia32.h b/arch/x86/include/asm/ia32.h
index b04cbdb..e623277 100644
--- a/arch/x86/include/asm/ia32.h
+++ b/arch/x86/include/asm/ia32.h
@@ -86,73 +86,6 @@ struct stat64 {
 	unsigned long long	st_ino;
 } __attribute__((packed));
 
-typedef struct compat_siginfo {
-	int si_signo;
-	int si_errno;
-	int si_code;
-
-	union {
-		int _pad[((128 / sizeof(int)) - 3)];
-
-		/* kill() */
-		struct {
-			unsigned int _pid;	/* sender's pid */
-			unsigned int _uid;	/* sender's uid */
-		} _kill;
-
-		/* POSIX.1b timers */
-		struct {
-			compat_timer_t _tid;	/* timer id */
-			int _overrun;		/* overrun count */
-			compat_sigval_t _sigval;	/* same as below */
-			int _sys_private;	/* not to be passed to user */
-			int _overrun_incr;	/* amount to add to overrun */
-		} _timer;
-
-		/* POSIX.1b signals */
-		struct {
-			unsigned int _pid;	/* sender's pid */
-			unsigned int _uid;	/* sender's uid */
-			compat_sigval_t _sigval;
-		} _rt;
-
-		/* SIGCHLD */
-		struct {
-			unsigned int _pid;	/* which child */
-			unsigned int _uid;	/* sender's uid */
-			int _status;		/* exit code */
-			compat_clock_t _utime;
-			compat_clock_t _stime;
-		} _sigchld;
-
-		/* SIGCHLD (x32 version) */
-		struct {
-			unsigned int _pid;	/* which child */
-			unsigned int _uid;	/* sender's uid */
-			int _status;		/* exit code */
-			compat_s64 _utime;
-			compat_s64 _stime;
-		} _sigchld_x32;
-
-		/* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
-		struct {
-			unsigned int _addr;	/* faulting insn/memory ref. */
-		} _sigfault;
-
-		/* SIGPOLL */
-		struct {
-			int _band;	/* POLL_IN, POLL_OUT, POLL_MSG */
-			int _fd;
-		} _sigpoll;
-
-		struct {
-			unsigned int _call_addr; /* calling insn */
-			int _syscall;	/* triggering system call number */
-			unsigned int _arch;	/* AUDIT_ARCH_* of syscall */
-		} _sigsys;
-	} _sifields;
-} compat_siginfo_t;
-
 #define IA32_STACK_TOP IA32_PAGE_OFFSET
 
 #ifdef __KERNEL__
diff --git a/arch/x86/include/asm/iommu_table.h b/arch/x86/include/asm/iommu_table.h
index f229b13..f42a047 100644
--- a/arch/x86/include/asm/iommu_table.h
+++ b/arch/x86/include/asm/iommu_table.h
@@ -48,7 +48,7 @@ struct iommu_table_entry {
 
 
 #define __IOMMU_INIT(_detect, _depend, _early_init, _late_init, _finish)\
-	static const struct iommu_table_entry const			\
+	static const struct iommu_table_entry				\
 		__iommu_entry_##_detect __used				\
 	__attribute__ ((unused, __section__(".iommu_table"),		\
 			aligned((sizeof(void *)))))	\
@@ -63,10 +63,10 @@ struct iommu_table_entry {
  * to stop detecting the other IOMMUs after yours has been detected.
  */
 #define IOMMU_INIT_POST(_detect)					\
-	__IOMMU_INIT(_detect, pci_swiotlb_detect_4gb,  0, 0, 0)
+	__IOMMU_INIT(_detect, pci_swiotlb_detect_4gb,  NULL, NULL, 0)
 
 #define IOMMU_INIT_POST_FINISH(detect)					\
-	__IOMMU_INIT(_detect, pci_swiotlb_detect_4gb,  0, 0, 1)
+	__IOMMU_INIT(_detect, pci_swiotlb_detect_4gb,  NULL, NULL, 1)
 
 /*
  * A more sophisticated version of IOMMU_INIT. This variant requires:
diff --git a/arch/x86/include/asm/kprobes.h b/arch/x86/include/asm/kprobes.h
index 5478825..d3ddd17 100644
--- a/arch/x86/include/asm/kprobes.h
+++ b/arch/x86/include/asm/kprobes.h
@@ -27,6 +27,7 @@
 #include <asm/insn.h>
 
 #define  __ARCH_WANT_KPROBES_INSN_SLOT
+#define  ARCH_SUPPORTS_KPROBES_ON_FTRACE
 
 struct pt_regs;
 struct kprobe;
diff --git a/arch/x86/include/asm/kvm.h b/arch/x86/include/asm/kvm.h
index 246617e..521bf25 100644
--- a/arch/x86/include/asm/kvm.h
+++ b/arch/x86/include/asm/kvm.h
@@ -25,6 +25,7 @@
 #define __KVM_HAVE_DEBUGREGS
 #define __KVM_HAVE_XSAVE
 #define __KVM_HAVE_XCRS
+#define __KVM_HAVE_READONLY_MEM
 
 /* Architectural interrupt line count. */
 #define KVM_NR_INTERRUPTS 256
diff --git a/arch/x86/include/asm/kvm_emulate.h b/arch/x86/include/asm/kvm_emulate.h
index c764f43..15f960c 100644
--- a/arch/x86/include/asm/kvm_emulate.h
+++ b/arch/x86/include/asm/kvm_emulate.h
@@ -86,6 +86,19 @@ struct x86_instruction_info {
 
 struct x86_emulate_ops {
 	/*
+	 * read_gpr: read a general purpose register (rax - r15)
+	 *
+	 * @reg: gpr number.
+	 */
+	ulong (*read_gpr)(struct x86_emulate_ctxt *ctxt, unsigned reg);
+	/*
+	 * write_gpr: write a general purpose register (rax - r15)
+	 *
+	 * @reg: gpr number.
+	 * @val: value to write.
+	 */
+	void (*write_gpr)(struct x86_emulate_ctxt *ctxt, unsigned reg, ulong val);
+	/*
 	 * read_std: Read bytes of standard (non-emulated/special) memory.
 	 *           Used for descriptor reading.
 	 *  @addr:  [IN ] Linear address from which to read.
@@ -200,8 +213,9 @@ typedef u32 __attribute__((vector_size(16))) sse128_t;
 
 /* Type, address-of, and value of an instruction's operand. */
 struct operand {
-	enum { OP_REG, OP_MEM, OP_IMM, OP_XMM, OP_MM, OP_NONE } type;
+	enum { OP_REG, OP_MEM, OP_MEM_STR, OP_IMM, OP_XMM, OP_MM, OP_NONE } type;
 	unsigned int bytes;
+	unsigned int count;
 	union {
 		unsigned long orig_val;
 		u64 orig_val64;
@@ -221,6 +235,7 @@ struct operand {
 		char valptr[sizeof(unsigned long) + 2];
 		sse128_t vec_val;
 		u64 mm_val;
+		void *data;
 	};
 };
 
@@ -236,14 +251,23 @@ struct read_cache {
 	unsigned long end;
 };
 
+/* Execution mode, passed to the emulator. */
+enum x86emul_mode {
+	X86EMUL_MODE_REAL,	/* Real mode.             */
+	X86EMUL_MODE_VM86,	/* Virtual 8086 mode.     */
+	X86EMUL_MODE_PROT16,	/* 16-bit protected mode. */
+	X86EMUL_MODE_PROT32,	/* 32-bit protected mode. */
+	X86EMUL_MODE_PROT64,	/* 64-bit (long) mode.    */
+};
+
 struct x86_emulate_ctxt {
-	struct x86_emulate_ops *ops;
+	const struct x86_emulate_ops *ops;
 
 	/* Register state before/after emulation. */
 	unsigned long eflags;
 	unsigned long eip; /* eip before instruction emulation */
 	/* Emulated execution mode, represented by an X86EMUL_MODE value. */
-	int mode;
+	enum x86emul_mode mode;
 
 	/* interruptibility state, as a result of execution of STI or MOV SS */
 	int interruptibility;
@@ -281,8 +305,10 @@ struct x86_emulate_ctxt {
 	bool rip_relative;
 	unsigned long _eip;
 	struct operand memop;
+	u32 regs_valid;  /* bitmaps of registers in _regs[] that can be read */
+	u32 regs_dirty;  /* bitmaps of registers in _regs[] that have been written */
 	/* Fields above regs are cleared together. */
-	unsigned long regs[NR_VCPU_REGS];
+	unsigned long _regs[NR_VCPU_REGS];
 	struct operand *memopp;
 	struct fetch_cache fetch;
 	struct read_cache io_read;
@@ -293,17 +319,6 @@ struct x86_emulate_ctxt {
 #define REPE_PREFIX	0xf3
 #define REPNE_PREFIX	0xf2
 
-/* Execution mode, passed to the emulator. */
-#define X86EMUL_MODE_REAL     0	/* Real mode.             */
-#define X86EMUL_MODE_VM86     1	/* Virtual 8086 mode.     */
-#define X86EMUL_MODE_PROT16   2	/* 16-bit protected mode. */
-#define X86EMUL_MODE_PROT32   4	/* 32-bit protected mode. */
-#define X86EMUL_MODE_PROT64   8	/* 64-bit (long) mode.    */
-
-/* any protected mode   */
-#define X86EMUL_MODE_PROT     (X86EMUL_MODE_PROT16|X86EMUL_MODE_PROT32| \
-			       X86EMUL_MODE_PROT64)
-
 /* CPUID vendors */
 #define X86EMUL_CPUID_VENDOR_AuthenticAMD_ebx 0x68747541
 #define X86EMUL_CPUID_VENDOR_AuthenticAMD_ecx 0x444d4163
@@ -394,4 +409,7 @@ int emulator_task_switch(struct x86_emulate_ctxt *ctxt,
 			 u16 tss_selector, int idt_index, int reason,
 			 bool has_error_code, u32 error_code);
 int emulate_int_real(struct x86_emulate_ctxt *ctxt, int irq);
+void emulator_invalidate_register_cache(struct x86_emulate_ctxt *ctxt);
+void emulator_writeback_register_cache(struct x86_emulate_ctxt *ctxt);
+
 #endif /* _ASM_X86_KVM_X86_EMULATE_H */
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 09155d6..0b902c9 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -287,10 +287,24 @@ struct kvm_mmu {
 	union kvm_mmu_page_role base_role;
 	bool direct_map;
 
+	/*
+	 * Bitmap; bit set = permission fault
+	 * Byte index: page fault error code [4:1]
+	 * Bit index: pte permissions in ACC_* format
+	 */
+	u8 permissions[16];
+
 	u64 *pae_root;
 	u64 *lm_root;
 	u64 rsvd_bits_mask[2][4];
 
+	/*
+	 * Bitmap: bit set = last pte in walk
+	 * index[0:1]: level (zero-based)
+	 * index[2]: pte.ps
+	 */
+	u8 last_pte_bitmap;
+
 	bool nx;
 
 	u64 pdptrs[4]; /* pae */
@@ -414,12 +428,15 @@ struct kvm_vcpu_arch {
 	struct x86_emulate_ctxt emulate_ctxt;
 	bool emulate_regs_need_sync_to_vcpu;
 	bool emulate_regs_need_sync_from_vcpu;
+	int (*complete_userspace_io)(struct kvm_vcpu *vcpu);
 
 	gpa_t time;
 	struct pvclock_vcpu_time_info hv_clock;
 	unsigned int hw_tsc_khz;
 	unsigned int time_offset;
 	struct page *time_page;
+	/* set guest stopped flag in pvclock flags field */
+	bool pvclock_set_guest_stopped_request;
 
 	struct {
 		u64 msr_val;
@@ -500,14 +517,24 @@ struct kvm_vcpu_arch {
 };
 
 struct kvm_lpage_info {
-	unsigned long rmap_pde;
 	int write_count;
 };
 
 struct kvm_arch_memory_slot {
+	unsigned long *rmap[KVM_NR_PAGE_SIZES];
 	struct kvm_lpage_info *lpage_info[KVM_NR_PAGE_SIZES - 1];
 };
 
+struct kvm_apic_map {
+	struct rcu_head rcu;
+	u8 ldr_bits;
+	/* fields bellow are used to decode ldr values in different modes */
+	u32 cid_shift, cid_mask, lid_mask;
+	struct kvm_lapic *phys_map[256];
+	/* first index is cluster id second is cpu id in a cluster */
+	struct kvm_lapic *logical_map[16][16];
+};
+
 struct kvm_arch {
 	unsigned int n_used_mmu_pages;
 	unsigned int n_requested_mmu_pages;
@@ -525,6 +552,8 @@ struct kvm_arch {
 	struct kvm_ioapic *vioapic;
 	struct kvm_pit *vpit;
 	int vapics_in_nmi_mode;
+	struct mutex apic_map_lock;
+	struct kvm_apic_map *apic_map;
 
 	unsigned int tss_addr;
 	struct page *apic_access_page;
@@ -957,6 +986,7 @@ extern bool kvm_rebooting;
 
 #define KVM_ARCH_WANT_MMU_NOTIFIER
 int kvm_unmap_hva(struct kvm *kvm, unsigned long hva);
+int kvm_unmap_hva_range(struct kvm *kvm, unsigned long start, unsigned long end);
 int kvm_age_hva(struct kvm *kvm, unsigned long hva);
 int kvm_test_age_hva(struct kvm *kvm, unsigned long hva);
 void kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte);
diff --git a/arch/x86/include/asm/kvm_para.h b/arch/x86/include/asm/kvm_para.h
index 2f7712e..eb3e9d8 100644
--- a/arch/x86/include/asm/kvm_para.h
+++ b/arch/x86/include/asm/kvm_para.h
@@ -102,21 +102,21 @@ struct kvm_vcpu_pv_apf_data {
 extern void kvmclock_init(void);
 extern int kvm_register_clock(char *txt);
 
-#ifdef CONFIG_KVM_CLOCK
+#ifdef CONFIG_KVM_GUEST
 bool kvm_check_and_clear_guest_paused(void);
 #else
 static inline bool kvm_check_and_clear_guest_paused(void)
 {
 	return false;
 }
-#endif /* CONFIG_KVMCLOCK */
+#endif /* CONFIG_KVM_GUEST */
 
 /* This instruction is vmcall.  On non-VT architectures, it will generate a
  * trap that we will then rewrite to the appropriate instruction.
  */
 #define KVM_HYPERCALL ".byte 0x0f,0x01,0xc1"
 
-/* For KVM hypercalls, a three-byte sequence of either the vmrun or the vmmrun
+/* For KVM hypercalls, a three-byte sequence of either the vmcall or the vmmcall
  * instruction.  The hypervisor may replace it with something else but only the
  * instructions are guaranteed to be supported.
  *
diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h
index a3ac52b..ccaf7c5 100644
--- a/arch/x86/include/asm/mce.h
+++ b/arch/x86/include/asm/mce.h
@@ -116,19 +116,9 @@ struct mce_log {
 /* Software defined banks */
 #define MCE_EXTENDED_BANK	128
 #define MCE_THERMAL_BANK	MCE_EXTENDED_BANK + 0
-
-#define K8_MCE_THRESHOLD_BASE      (MCE_EXTENDED_BANK + 1)      /* MCE_AMD */
-#define K8_MCE_THRESHOLD_BANK_0    (MCE_THRESHOLD_BASE + 0 * 9)
-#define K8_MCE_THRESHOLD_BANK_1    (MCE_THRESHOLD_BASE + 1 * 9)
-#define K8_MCE_THRESHOLD_BANK_2    (MCE_THRESHOLD_BASE + 2 * 9)
-#define K8_MCE_THRESHOLD_BANK_3    (MCE_THRESHOLD_BASE + 3 * 9)
-#define K8_MCE_THRESHOLD_BANK_4    (MCE_THRESHOLD_BASE + 4 * 9)
-#define K8_MCE_THRESHOLD_BANK_5    (MCE_THRESHOLD_BASE + 5 * 9)
-#define K8_MCE_THRESHOLD_DRAM_ECC  (MCE_THRESHOLD_BANK_4 + 0)
-
+#define K8_MCE_THRESHOLD_BASE      (MCE_EXTENDED_BANK + 1)
 
 #ifdef __KERNEL__
-
 extern void mce_register_decode_chain(struct notifier_block *nb);
 extern void mce_unregister_decode_chain(struct notifier_block *nb);
 
diff --git a/arch/x86/include/asm/microcode.h b/arch/x86/include/asm/microcode.h
index 4ebe157..43d921b 100644
--- a/arch/x86/include/asm/microcode.h
+++ b/arch/x86/include/asm/microcode.h
@@ -15,8 +15,8 @@ struct microcode_ops {
 	enum ucode_state (*request_microcode_user) (int cpu,
 				const void __user *buf, size_t size);
 
-	enum ucode_state (*request_microcode_fw) (int cpu,
-				struct device *device);
+	enum ucode_state (*request_microcode_fw) (int cpu, struct device *,
+						  bool refresh_fw);
 
 	void (*microcode_fini_cpu) (int cpu);
 
@@ -49,12 +49,6 @@ static inline struct microcode_ops * __init init_intel_microcode(void)
 #ifdef CONFIG_MICROCODE_AMD
 extern struct microcode_ops * __init init_amd_microcode(void);
 extern void __exit exit_amd_microcode(void);
-
-static inline void get_ucode_data(void *to, const u8 *from, size_t n)
-{
-	memcpy(to, from, n);
-}
-
 #else
 static inline struct microcode_ops * __init init_amd_microcode(void)
 {
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index 957ec87..fbee971 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -248,6 +248,9 @@
 
 #define MSR_IA32_PERF_STATUS		0x00000198
 #define MSR_IA32_PERF_CTL		0x00000199
+#define MSR_AMD_PSTATE_DEF_BASE		0xc0010064
+#define MSR_AMD_PERF_STATUS		0xc0010063
+#define MSR_AMD_PERF_CTL		0xc0010062
 
 #define MSR_IA32_MPERF			0x000000e7
 #define MSR_IA32_APERF			0x000000e8
diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_event.h
index cb4e43b..4fabcdf 100644
--- a/arch/x86/include/asm/perf_event.h
+++ b/arch/x86/include/asm/perf_event.h
@@ -262,4 +262,6 @@ static inline void perf_check_microcode(void) { }
  static inline void amd_pmu_disable_virt(void) { }
 #endif
 
+#define arch_perf_out_copy_user copy_from_user_nmi
+
 #endif /* _ASM_X86_PERF_EVENT_H */
diff --git a/arch/x86/include/asm/perf_regs.h b/arch/x86/include/asm/perf_regs.h
new file mode 100644
index 0000000..3f2207b
--- /dev/null
+++ b/arch/x86/include/asm/perf_regs.h
@@ -0,0 +1,33 @@
+#ifndef _ASM_X86_PERF_REGS_H
+#define _ASM_X86_PERF_REGS_H
+
+enum perf_event_x86_regs {
+	PERF_REG_X86_AX,
+	PERF_REG_X86_BX,
+	PERF_REG_X86_CX,
+	PERF_REG_X86_DX,
+	PERF_REG_X86_SI,
+	PERF_REG_X86_DI,
+	PERF_REG_X86_BP,
+	PERF_REG_X86_SP,
+	PERF_REG_X86_IP,
+	PERF_REG_X86_FLAGS,
+	PERF_REG_X86_CS,
+	PERF_REG_X86_SS,
+	PERF_REG_X86_DS,
+	PERF_REG_X86_ES,
+	PERF_REG_X86_FS,
+	PERF_REG_X86_GS,
+	PERF_REG_X86_R8,
+	PERF_REG_X86_R9,
+	PERF_REG_X86_R10,
+	PERF_REG_X86_R11,
+	PERF_REG_X86_R12,
+	PERF_REG_X86_R13,
+	PERF_REG_X86_R14,
+	PERF_REG_X86_R15,
+
+	PERF_REG_X86_32_MAX = PERF_REG_X86_GS + 1,
+	PERF_REG_X86_64_MAX = PERF_REG_X86_R15 + 1,
+};
+#endif /* _ASM_X86_PERF_REGS_H */
diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h
index 49afb3f..c3520d7 100644
--- a/arch/x86/include/asm/pgtable.h
+++ b/arch/x86/include/asm/pgtable.h
@@ -146,8 +146,7 @@ static inline unsigned long pmd_pfn(pmd_t pmd)
 
 static inline int pmd_large(pmd_t pte)
 {
-	return (pmd_flags(pte) & (_PAGE_PSE | _PAGE_PRESENT)) ==
-		(_PAGE_PSE | _PAGE_PRESENT);
+	return pmd_flags(pte) & _PAGE_PSE;
 }
 
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
@@ -415,7 +414,13 @@ static inline int pte_hidden(pte_t pte)
 
 static inline int pmd_present(pmd_t pmd)
 {
-	return pmd_flags(pmd) & _PAGE_PRESENT;
+	/*
+	 * Checking for _PAGE_PSE is needed too because
+	 * split_huge_page will temporarily clear the present bit (but
+	 * the _PAGE_PSE flag will remain set at all times while the
+	 * _PAGE_PRESENT bit is clear).
+	 */
+	return pmd_flags(pmd) & (_PAGE_PRESENT | _PAGE_PROTNONE | _PAGE_PSE);
 }
 
 static inline int pmd_none(pmd_t pmd)
diff --git a/arch/x86/include/asm/pgtable_types.h b/arch/x86/include/asm/pgtable_types.h
index 013286a..db8fec6 100644
--- a/arch/x86/include/asm/pgtable_types.h
+++ b/arch/x86/include/asm/pgtable_types.h
@@ -303,11 +303,9 @@ void set_pte_vaddr(unsigned long vaddr, pte_t pte);
 
 extern void native_pagetable_reserve(u64 start, u64 end);
 #ifdef CONFIG_X86_32
-extern void native_pagetable_setup_start(pgd_t *base);
-extern void native_pagetable_setup_done(pgd_t *base);
+extern void native_pagetable_init(void);
 #else
-#define native_pagetable_setup_start x86_init_pgd_noop
-#define native_pagetable_setup_done  x86_init_pgd_noop
+#define native_pagetable_init        paging_init
 #endif
 
 struct seq_file;
diff --git a/arch/x86/include/asm/processor-flags.h b/arch/x86/include/asm/processor-flags.h
index aea1d1d..680cf09 100644
--- a/arch/x86/include/asm/processor-flags.h
+++ b/arch/x86/include/asm/processor-flags.h
@@ -65,6 +65,7 @@
 #define X86_CR4_PCIDE	0x00020000 /* enable PCID support */
 #define X86_CR4_OSXSAVE 0x00040000 /* enable xsave and xrestore */
 #define X86_CR4_SMEP	0x00100000 /* enable SMEP support */
+#define X86_CR4_SMAP	0x00200000 /* enable SMAP support */
 
 /*
  * x86-64 Task Priority Register, CR8
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index d048cad..ad1fc85 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -423,7 +423,6 @@ 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
@@ -589,11 +588,6 @@ typedef struct {
 } mm_segment_t;
 
 
-/*
- * create a kernel thread without removing it from tasklists
- */
-extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
-
 /* Free all resources held by a thread. */
 extern void release_thread(struct task_struct *);
 
@@ -759,6 +753,8 @@ static inline void update_debugctlmsr(unsigned long debugctlmsr)
 	wrmsrl(MSR_IA32_DEBUGCTLMSR, debugctlmsr);
 }
 
+extern void set_task_blockstep(struct task_struct *task, bool on);
+
 /*
  * from system description table in BIOS. Mostly for MCA use, but
  * others may find it useful:
diff --git a/arch/x86/include/asm/signal.h b/arch/x86/include/asm/signal.h
index 598457c..323973f 100644
--- a/arch/x86/include/asm/signal.h
+++ b/arch/x86/include/asm/signal.h
@@ -31,6 +31,10 @@ typedef struct {
 	unsigned long sig[_NSIG_WORDS];
 } sigset_t;
 
+#ifndef CONFIG_COMPAT
+typedef sigset_t compat_sigset_t;
+#endif
+
 #else
 /* Here we must cater to libcs that poke about in kernel headers.  */
 
diff --git a/arch/x86/include/asm/smap.h b/arch/x86/include/asm/smap.h
new file mode 100644
index 0000000..8d3120f
--- /dev/null
+++ b/arch/x86/include/asm/smap.h
@@ -0,0 +1,91 @@
+/*
+ * Supervisor Mode Access Prevention support
+ *
+ * Copyright (C) 2012 Intel Corporation
+ * Author: H. Peter Anvin <hpa@linux.intel.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+
+#ifndef _ASM_X86_SMAP_H
+#define _ASM_X86_SMAP_H
+
+#include <linux/stringify.h>
+#include <asm/nops.h>
+#include <asm/cpufeature.h>
+
+/* "Raw" instruction opcodes */
+#define __ASM_CLAC	.byte 0x0f,0x01,0xca
+#define __ASM_STAC	.byte 0x0f,0x01,0xcb
+
+#ifdef __ASSEMBLY__
+
+#include <asm/alternative-asm.h>
+
+#ifdef CONFIG_X86_SMAP
+
+#define ASM_CLAC							\
+	661: ASM_NOP3 ;							\
+	.pushsection .altinstr_replacement, "ax" ;			\
+	662: __ASM_CLAC ;						\
+	.popsection ;							\
+	.pushsection .altinstructions, "a" ;				\
+	altinstruction_entry 661b, 662b, X86_FEATURE_SMAP, 3, 3 ;	\
+	.popsection
+
+#define ASM_STAC							\
+	661: ASM_NOP3 ;							\
+	.pushsection .altinstr_replacement, "ax" ;			\
+	662: __ASM_STAC ;						\
+	.popsection ;							\
+	.pushsection .altinstructions, "a" ;				\
+	altinstruction_entry 661b, 662b, X86_FEATURE_SMAP, 3, 3 ;	\
+	.popsection
+
+#else /* CONFIG_X86_SMAP */
+
+#define ASM_CLAC
+#define ASM_STAC
+
+#endif /* CONFIG_X86_SMAP */
+
+#else /* __ASSEMBLY__ */
+
+#include <asm/alternative.h>
+
+#ifdef CONFIG_X86_SMAP
+
+static __always_inline void clac(void)
+{
+	/* Note: a barrier is implicit in alternative() */
+	alternative(ASM_NOP3, __stringify(__ASM_CLAC), X86_FEATURE_SMAP);
+}
+
+static __always_inline void stac(void)
+{
+	/* Note: a barrier is implicit in alternative() */
+	alternative(ASM_NOP3, __stringify(__ASM_STAC), X86_FEATURE_SMAP);
+}
+
+/* These macros can be used in asm() statements */
+#define ASM_CLAC \
+	ALTERNATIVE(ASM_NOP3, __stringify(__ASM_CLAC), X86_FEATURE_SMAP)
+#define ASM_STAC \
+	ALTERNATIVE(ASM_NOP3, __stringify(__ASM_STAC), X86_FEATURE_SMAP)
+
+#else /* CONFIG_X86_SMAP */
+
+static inline void clac(void) { }
+static inline void stac(void) { }
+
+#define ASM_CLAC
+#define ASM_STAC
+
+#endif /* CONFIG_X86_SMAP */
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _ASM_X86_SMAP_H */
diff --git a/arch/x86/include/asm/sys_ia32.h b/arch/x86/include/asm/sys_ia32.h
index 3fda9db4..a9a8cf3 100644
--- a/arch/x86/include/asm/sys_ia32.h
+++ b/arch/x86/include/asm/sys_ia32.h
@@ -40,7 +40,7 @@ asmlinkage long sys32_sigaction(int, struct old_sigaction32 __user *,
 				struct old_sigaction32 __user *);
 asmlinkage long sys32_alarm(unsigned int);
 
-asmlinkage long sys32_waitpid(compat_pid_t, unsigned int *, int);
+asmlinkage long sys32_waitpid(compat_pid_t, unsigned int __user *, int);
 asmlinkage long sys32_sysfs(int, u32, u32);
 
 asmlinkage long sys32_sched_rr_get_interval(compat_pid_t,
@@ -54,8 +54,6 @@ asmlinkage long sys32_pwrite(unsigned int, const char __user *, u32, u32, u32);
 asmlinkage long sys32_personality(unsigned long);
 asmlinkage long sys32_sendfile(int, int, compat_off_t __user *, s32);
 
-asmlinkage long sys32_execve(const char __user *, compat_uptr_t __user *,
-			     compat_uptr_t __user *, struct pt_regs *);
 asmlinkage long sys32_clone(unsigned int, unsigned int, struct pt_regs *);
 
 long sys32_lseek(unsigned int, int, unsigned int);
diff --git a/arch/x86/include/asm/syscalls.h b/arch/x86/include/asm/syscalls.h
index f1d8b44..2be0b88 100644
--- a/arch/x86/include/asm/syscalls.h
+++ b/arch/x86/include/asm/syscalls.h
@@ -25,7 +25,7 @@ int sys_fork(struct pt_regs *);
 int sys_vfork(struct pt_regs *);
 long sys_execve(const char __user *,
 		const char __user *const __user *,
-		const char __user *const __user *, struct pt_regs *);
+		const char __user *const __user *);
 long sys_clone(unsigned long, unsigned long, void __user *,
 	       void __user *, struct pt_regs *);
 
diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h
index 89f794f..c509d07 100644
--- a/arch/x86/include/asm/thread_info.h
+++ b/arch/x86/include/asm/thread_info.h
@@ -79,7 +79,6 @@ struct thread_info {
 #define TIF_SIGPENDING		2	/* signal pending */
 #define TIF_NEED_RESCHED	3	/* rescheduling necessary */
 #define TIF_SINGLESTEP		4	/* reenable singlestep on user return*/
-#define TIF_IRET		5	/* force IRET */
 #define TIF_SYSCALL_EMU		6	/* syscall emulation active */
 #define TIF_SYSCALL_AUDIT	7	/* syscall auditing active */
 #define TIF_SECCOMP		8	/* secure computing */
@@ -104,7 +103,6 @@ struct thread_info {
 #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
 #define _TIF_SINGLESTEP		(1 << TIF_SINGLESTEP)
 #define _TIF_NEED_RESCHED	(1 << TIF_NEED_RESCHED)
-#define _TIF_IRET		(1 << TIF_IRET)
 #define _TIF_SYSCALL_EMU	(1 << TIF_SYSCALL_EMU)
 #define _TIF_SYSCALL_AUDIT	(1 << TIF_SYSCALL_AUDIT)
 #define _TIF_SECCOMP		(1 << TIF_SECCOMP)
diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h
index e1f3a17..a91acfb 100644
--- a/arch/x86/include/asm/uaccess.h
+++ b/arch/x86/include/asm/uaccess.h
@@ -9,6 +9,7 @@
 #include <linux/string.h>
 #include <asm/asm.h>
 #include <asm/page.h>
+#include <asm/smap.h>
 
 #define VERIFY_READ 0
 #define VERIFY_WRITE 1
@@ -192,9 +193,10 @@ extern int __get_user_bad(void);
 
 #ifdef CONFIG_X86_32
 #define __put_user_asm_u64(x, addr, err, errret)			\
-	asm volatile("1:	movl %%eax,0(%2)\n"			\
+	asm volatile(ASM_STAC "\n"					\
+		     "1:	movl %%eax,0(%2)\n"			\
 		     "2:	movl %%edx,4(%2)\n"			\
-		     "3:\n"						\
+		     "3: " ASM_CLAC "\n"				\
 		     ".section .fixup,\"ax\"\n"				\
 		     "4:	movl %3,%0\n"				\
 		     "	jmp 3b\n"					\
@@ -205,9 +207,10 @@ extern int __get_user_bad(void);
 		     : "A" (x), "r" (addr), "i" (errret), "0" (err))
 
 #define __put_user_asm_ex_u64(x, addr)					\
-	asm volatile("1:	movl %%eax,0(%1)\n"			\
+	asm volatile(ASM_STAC "\n"					\
+		     "1:	movl %%eax,0(%1)\n"			\
 		     "2:	movl %%edx,4(%1)\n"			\
-		     "3:\n"						\
+		     "3: " ASM_CLAC "\n"				\
 		     _ASM_EXTABLE_EX(1b, 2b)				\
 		     _ASM_EXTABLE_EX(2b, 3b)				\
 		     : : "A" (x), "r" (addr))
@@ -379,8 +382,9 @@ do {									\
 } while (0)
 
 #define __get_user_asm(x, addr, err, itype, rtype, ltype, errret)	\
-	asm volatile("1:	mov"itype" %2,%"rtype"1\n"		\
-		     "2:\n"						\
+	asm volatile(ASM_STAC "\n"					\
+		     "1:	mov"itype" %2,%"rtype"1\n"		\
+		     "2: " ASM_CLAC "\n"				\
 		     ".section .fixup,\"ax\"\n"				\
 		     "3:	mov %3,%0\n"				\
 		     "	xor"itype" %"rtype"1,%"rtype"1\n"		\
@@ -443,8 +447,9 @@ struct __large_struct { unsigned long buf[100]; };
  * aliasing issues.
  */
 #define __put_user_asm(x, addr, err, itype, rtype, ltype, errret)	\
-	asm volatile("1:	mov"itype" %"rtype"1,%2\n"		\
-		     "2:\n"						\
+	asm volatile(ASM_STAC "\n"					\
+		     "1:	mov"itype" %"rtype"1,%2\n"		\
+		     "2: " ASM_CLAC "\n"				\
 		     ".section .fixup,\"ax\"\n"				\
 		     "3:	mov %3,%0\n"				\
 		     "	jmp 2b\n"					\
@@ -463,13 +468,13 @@ struct __large_struct { unsigned long buf[100]; };
  * uaccess_try and catch
  */
 #define uaccess_try	do {						\
-	int prev_err = current_thread_info()->uaccess_err;		\
 	current_thread_info()->uaccess_err = 0;				\
+	stac();								\
 	barrier();
 
 #define uaccess_catch(err)						\
+	clac();								\
 	(err) |= (current_thread_info()->uaccess_err ? -EFAULT : 0);	\
-	current_thread_info()->uaccess_err = prev_err;			\
 } while (0)
 
 /**
@@ -569,6 +574,9 @@ strncpy_from_user(char *dst, const char __user *src, long count);
 extern __must_check long strlen_user(const char __user *str);
 extern __must_check long strnlen_user(const char __user *str, long n);
 
+unsigned long __must_check clear_user(void __user *mem, unsigned long len);
+unsigned long __must_check __clear_user(void __user *mem, unsigned long len);
+
 /*
  * movsl can be slow when source and dest are not both 8-byte aligned
  */
diff --git a/arch/x86/include/asm/uaccess_32.h b/arch/x86/include/asm/uaccess_32.h
index 576e39b..7f760a9 100644
--- a/arch/x86/include/asm/uaccess_32.h
+++ b/arch/x86/include/asm/uaccess_32.h
@@ -213,7 +213,4 @@ static inline unsigned long __must_check copy_from_user(void *to,
 	return n;
 }
 
-unsigned long __must_check clear_user(void __user *mem, unsigned long len);
-unsigned long __must_check __clear_user(void __user *mem, unsigned long len);
-
 #endif /* _ASM_X86_UACCESS_32_H */
diff --git a/arch/x86/include/asm/uaccess_64.h b/arch/x86/include/asm/uaccess_64.h
index d8def8b..142810c 100644
--- a/arch/x86/include/asm/uaccess_64.h
+++ b/arch/x86/include/asm/uaccess_64.h
@@ -217,9 +217,6 @@ int __copy_in_user(void __user *dst, const void __user *src, unsigned size)
 	}
 }
 
-__must_check unsigned long clear_user(void __user *mem, unsigned long len);
-__must_check unsigned long __clear_user(void __user *mem, unsigned long len);
-
 static __must_check __always_inline int
 __copy_from_user_inatomic(void *dst, const void __user *src, unsigned size)
 {
diff --git a/arch/x86/include/asm/unistd.h b/arch/x86/include/asm/unistd.h
index 0d9776e..55d1555 100644
--- a/arch/x86/include/asm/unistd.h
+++ b/arch/x86/include/asm/unistd.h
@@ -50,6 +50,8 @@
 # define __ARCH_WANT_SYS_TIME
 # define __ARCH_WANT_SYS_UTIME
 # define __ARCH_WANT_SYS_WAITPID
+# define __ARCH_WANT_SYS_EXECVE
+# define __ARCH_WANT_KERNEL_EXECVE
 
 /*
  * "Conditional" syscalls
diff --git a/arch/x86/include/asm/uprobes.h b/arch/x86/include/asm/uprobes.h
index f3971bb..8ff8be7 100644
--- a/arch/x86/include/asm/uprobes.h
+++ b/arch/x86/include/asm/uprobes.h
@@ -42,10 +42,11 @@ struct arch_uprobe {
 };
 
 struct arch_uprobe_task {
-	unsigned long			saved_trap_nr;
 #ifdef CONFIG_X86_64
 	unsigned long			saved_scratch_register;
 #endif
+	unsigned int			saved_trap_nr;
+	unsigned int			saved_tf;
 };
 
 extern int  arch_uprobe_analyze_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long addr);
diff --git a/arch/x86/include/asm/vdso.h b/arch/x86/include/asm/vdso.h
index bb05228..fddb53d 100644
--- a/arch/x86/include/asm/vdso.h
+++ b/arch/x86/include/asm/vdso.h
@@ -11,7 +11,8 @@ extern const char VDSO32_PRELINK[];
 #define VDSO32_SYMBOL(base, name)					\
 ({									\
 	extern const char VDSO32_##name[];				\
-	(void *)(VDSO32_##name - VDSO32_PRELINK + (unsigned long)(base)); \
+	(void __user *)(VDSO32_##name - VDSO32_PRELINK +		\
+			(unsigned long)(base));				\
 })
 #endif
 
diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h
index 38155f6..5769349 100644
--- a/arch/x86/include/asm/x86_init.h
+++ b/arch/x86/include/asm/x86_init.h
@@ -81,12 +81,13 @@ struct x86_init_mapping {
 
 /**
  * struct x86_init_paging - platform specific paging functions
- * @pagetable_setup_start:	platform specific pre paging_init() call
- * @pagetable_setup_done:	platform specific post paging_init() call
+ * @pagetable_init:	platform specific paging initialization call to setup
+ *			the kernel pagetables and prepare accessors functions.
+ *			Callback must call paging_init(). Called once after the
+ *			direct mapping for phys memory is available.
  */
 struct x86_init_paging {
-	void (*pagetable_setup_start)(pgd_t *base);
-	void (*pagetable_setup_done)(pgd_t *base);
+	void (*pagetable_init)(void);
 };
 
 /**
diff --git a/arch/x86/include/asm/xen/interface.h b/arch/x86/include/asm/xen/interface.h
index cbf0c9d..3546317 100644
--- a/arch/x86/include/asm/xen/interface.h
+++ b/arch/x86/include/asm/xen/interface.h
@@ -47,6 +47,10 @@
 #endif
 
 #ifndef __ASSEMBLY__
+/* Explicitly size integers that represent pfns in the public interface
+ * with Xen so that on ARM we can have one ABI that works for 32 and 64
+ * bit guests. */
+typedef unsigned long xen_pfn_t;
 /* Guest handles for primitive C types. */
 __DEFINE_GUEST_HANDLE(uchar, unsigned char);
 __DEFINE_GUEST_HANDLE(uint,  unsigned int);
@@ -57,6 +61,7 @@ DEFINE_GUEST_HANDLE(long);
 DEFINE_GUEST_HANDLE(void);
 DEFINE_GUEST_HANDLE(uint64_t);
 DEFINE_GUEST_HANDLE(uint32_t);
+DEFINE_GUEST_HANDLE(xen_pfn_t);
 #endif
 
 #ifndef HYPERVISOR_VIRT_START
@@ -121,6 +126,8 @@ struct arch_shared_info {
 #include "interface_64.h"
 #endif
 
+#include <asm/pvclock-abi.h>
+
 #ifndef __ASSEMBLY__
 /*
  * The following is all CPU context. Note that the fpu_ctxt block is filled
@@ -136,7 +143,8 @@ struct vcpu_guest_context {
     struct cpu_user_regs user_regs;         /* User-level CPU registers     */
     struct trap_info trap_ctxt[256];        /* Virtual IDT                  */
     unsigned long ldt_base, ldt_ents;       /* LDT (linear address, # ents) */
-    unsigned long gdt_frames[16], gdt_ents; /* GDT (machine frames, # ents) */
+    unsigned long gdt_frames[16], gdt_ents; /* GDT (machine frames, # ents).*
+					     * PV in HVM: it's GDTR addr/sz */
     unsigned long kernel_ss, kernel_sp;     /* Virtual TSS (only SS1/SP1)   */
     /* NB. User pagetable on x86/64 is placed in ctrlreg[1]. */
     unsigned long ctrlreg[8];               /* CR0-CR7 (control registers)  */
diff --git a/arch/x86/include/asm/xen/page.h b/arch/x86/include/asm/xen/page.h
index 472b9b7..6af440d 100644
--- a/arch/x86/include/asm/xen/page.h
+++ b/arch/x86/include/asm/xen/page.h
@@ -159,6 +159,9 @@ static inline xpaddr_t machine_to_phys(xmaddr_t machine)
 static inline unsigned long mfn_to_local_pfn(unsigned long mfn)
 {
 	unsigned long pfn = mfn_to_pfn(mfn);
+
+	if (xen_feature(XENFEAT_auto_translated_physmap))
+		return mfn;
 	if (get_phys_to_machine(pfn) != mfn)
 		return -1; /* force !pfn_valid() */
 	return pfn;
diff --git a/arch/x86/include/asm/xen/swiotlb-xen.h b/arch/x86/include/asm/xen/swiotlb-xen.h
index 1be1ab7..ee52fca 100644
--- a/arch/x86/include/asm/xen/swiotlb-xen.h
+++ b/arch/x86/include/asm/xen/swiotlb-xen.h
@@ -5,10 +5,12 @@
 extern int xen_swiotlb;
 extern int __init pci_xen_swiotlb_detect(void);
 extern void __init pci_xen_swiotlb_init(void);
+extern int pci_xen_swiotlb_init_late(void);
 #else
 #define xen_swiotlb (0)
 static inline int __init pci_xen_swiotlb_detect(void) { return 0; }
 static inline void __init pci_xen_swiotlb_init(void) { }
+static inline int pci_xen_swiotlb_init_late(void) { return -ENXIO; }
 #endif
 
 #endif /* _ASM_X86_SWIOTLB_XEN_H */
diff --git a/arch/x86/include/asm/xor_32.h b/arch/x86/include/asm/xor_32.h
index 4545708..aabd585 100644
--- a/arch/x86/include/asm/xor_32.h
+++ b/arch/x86/include/asm/xor_32.h
@@ -534,38 +534,6 @@ static struct xor_block_template xor_block_p5_mmx = {
  * Copyright (C) 1999 Zach Brown (with obvious credit due Ingo)
  */
 
-#define XMMS_SAVE				\
-do {						\
-	preempt_disable();			\
-	cr0 = read_cr0();			\
-	clts();					\
-	asm volatile(				\
-		"movups %%xmm0,(%0)	;\n\t"	\
-		"movups %%xmm1,0x10(%0)	;\n\t"	\
-		"movups %%xmm2,0x20(%0)	;\n\t"	\
-		"movups %%xmm3,0x30(%0)	;\n\t"	\
-		:				\
-		: "r" (xmm_save) 		\
-		: "memory");			\
-} while (0)
-
-#define XMMS_RESTORE				\
-do {						\
-	asm volatile(				\
-		"sfence			;\n\t"	\
-		"movups (%0),%%xmm0	;\n\t"	\
-		"movups 0x10(%0),%%xmm1	;\n\t"	\
-		"movups 0x20(%0),%%xmm2	;\n\t"	\
-		"movups 0x30(%0),%%xmm3	;\n\t"	\
-		:				\
-		: "r" (xmm_save)		\
-		: "memory");			\
-	write_cr0(cr0);				\
-	preempt_enable();			\
-} while (0)
-
-#define ALIGN16 __attribute__((aligned(16)))
-
 #define OFFS(x)		"16*("#x")"
 #define PF_OFFS(x)	"256+16*("#x")"
 #define	PF0(x)		"	prefetchnta "PF_OFFS(x)"(%1)		;\n"
@@ -587,10 +555,8 @@ static void
 xor_sse_2(unsigned long bytes, unsigned long *p1, unsigned long *p2)
 {
 	unsigned long lines = bytes >> 8;
-	char xmm_save[16*4] ALIGN16;
-	int cr0;
 
-	XMMS_SAVE;
+	kernel_fpu_begin();
 
 	asm volatile(
 #undef BLOCK
@@ -633,7 +599,7 @@ xor_sse_2(unsigned long bytes, unsigned long *p1, unsigned long *p2)
 	:
 	: "memory");
 
-	XMMS_RESTORE;
+	kernel_fpu_end();
 }
 
 static void
@@ -641,10 +607,8 @@ xor_sse_3(unsigned long bytes, unsigned long *p1, unsigned long *p2,
 	  unsigned long *p3)
 {
 	unsigned long lines = bytes >> 8;
-	char xmm_save[16*4] ALIGN16;
-	int cr0;
 
-	XMMS_SAVE;
+	kernel_fpu_begin();
 
 	asm volatile(
 #undef BLOCK
@@ -694,7 +658,7 @@ xor_sse_3(unsigned long bytes, unsigned long *p1, unsigned long *p2,
 	:
 	: "memory" );
 
-	XMMS_RESTORE;
+	kernel_fpu_end();
 }
 
 static void
@@ -702,10 +666,8 @@ xor_sse_4(unsigned long bytes, unsigned long *p1, unsigned long *p2,
 	  unsigned long *p3, unsigned long *p4)
 {
 	unsigned long lines = bytes >> 8;
-	char xmm_save[16*4] ALIGN16;
-	int cr0;
 
-	XMMS_SAVE;
+	kernel_fpu_begin();
 
 	asm volatile(
 #undef BLOCK
@@ -762,7 +724,7 @@ xor_sse_4(unsigned long bytes, unsigned long *p1, unsigned long *p2,
 	:
 	: "memory" );
 
-	XMMS_RESTORE;
+	kernel_fpu_end();
 }
 
 static void
@@ -770,10 +732,8 @@ xor_sse_5(unsigned long bytes, unsigned long *p1, unsigned long *p2,
 	  unsigned long *p3, unsigned long *p4, unsigned long *p5)
 {
 	unsigned long lines = bytes >> 8;
-	char xmm_save[16*4] ALIGN16;
-	int cr0;
 
-	XMMS_SAVE;
+	kernel_fpu_begin();
 
 	/* Make sure GCC forgets anything it knows about p4 or p5,
 	   such that it won't pass to the asm volatile below a
@@ -850,7 +810,7 @@ xor_sse_5(unsigned long bytes, unsigned long *p1, unsigned long *p2,
 	   like assuming they have some legal value.  */
 	asm("" : "=r" (p4), "=r" (p5));
 
-	XMMS_RESTORE;
+	kernel_fpu_end();
 }
 
 static struct xor_block_template xor_block_pIII_sse = {
diff --git a/arch/x86/include/asm/xor_64.h b/arch/x86/include/asm/xor_64.h
index b9b2323..5fc06d0 100644
--- a/arch/x86/include/asm/xor_64.h
+++ b/arch/x86/include/asm/xor_64.h
@@ -34,41 +34,7 @@
  * no advantages to be gotten from x86-64 here anyways.
  */
 
-typedef struct {
-	unsigned long a, b;
-} __attribute__((aligned(16))) xmm_store_t;
-
-/* Doesn't use gcc to save the XMM registers, because there is no easy way to
-   tell it to do a clts before the register saving. */
-#define XMMS_SAVE				\
-do {						\
-	preempt_disable();			\
-	asm volatile(				\
-		"movq %%cr0,%0		;\n\t"	\
-		"clts			;\n\t"	\
-		"movups %%xmm0,(%1)	;\n\t"	\
-		"movups %%xmm1,0x10(%1)	;\n\t"	\
-		"movups %%xmm2,0x20(%1)	;\n\t"	\
-		"movups %%xmm3,0x30(%1)	;\n\t"	\
-		: "=&r" (cr0)			\
-		: "r" (xmm_save) 		\
-		: "memory");			\
-} while (0)
-
-#define XMMS_RESTORE				\
-do {						\
-	asm volatile(				\
-		"sfence			;\n\t"	\
-		"movups (%1),%%xmm0	;\n\t"	\
-		"movups 0x10(%1),%%xmm1	;\n\t"	\
-		"movups 0x20(%1),%%xmm2	;\n\t"	\
-		"movups 0x30(%1),%%xmm3	;\n\t"	\
-		"movq 	%0,%%cr0	;\n\t"	\
-		:				\
-		: "r" (cr0), "r" (xmm_save)	\
-		: "memory");			\
-	preempt_enable();			\
-} while (0)
+#include <asm/i387.h>
 
 #define OFFS(x)		"16*("#x")"
 #define PF_OFFS(x)	"256+16*("#x")"
@@ -91,10 +57,8 @@ static void
 xor_sse_2(unsigned long bytes, unsigned long *p1, unsigned long *p2)
 {
 	unsigned int lines = bytes >> 8;
-	unsigned long cr0;
-	xmm_store_t xmm_save[4];
 
-	XMMS_SAVE;
+	kernel_fpu_begin();
 
 	asm volatile(
 #undef BLOCK
@@ -135,7 +99,7 @@ xor_sse_2(unsigned long bytes, unsigned long *p1, unsigned long *p2)
 	: [inc] "r" (256UL)
 	: "memory");
 
-	XMMS_RESTORE;
+	kernel_fpu_end();
 }
 
 static void
@@ -143,11 +107,8 @@ xor_sse_3(unsigned long bytes, unsigned long *p1, unsigned long *p2,
 	  unsigned long *p3)
 {
 	unsigned int lines = bytes >> 8;
-	xmm_store_t xmm_save[4];
-	unsigned long cr0;
-
-	XMMS_SAVE;
 
+	kernel_fpu_begin();
 	asm volatile(
 #undef BLOCK
 #define BLOCK(i) \
@@ -194,7 +155,7 @@ xor_sse_3(unsigned long bytes, unsigned long *p1, unsigned long *p2,
 	  [p1] "+r" (p1), [p2] "+r" (p2), [p3] "+r" (p3)
 	: [inc] "r" (256UL)
 	: "memory");
-	XMMS_RESTORE;
+	kernel_fpu_end();
 }
 
 static void
@@ -202,10 +163,8 @@ xor_sse_4(unsigned long bytes, unsigned long *p1, unsigned long *p2,
 	  unsigned long *p3, unsigned long *p4)
 {
 	unsigned int lines = bytes >> 8;
-	xmm_store_t xmm_save[4];
-	unsigned long cr0;
 
-	XMMS_SAVE;
+	kernel_fpu_begin();
 
 	asm volatile(
 #undef BLOCK
@@ -261,7 +220,7 @@ xor_sse_4(unsigned long bytes, unsigned long *p1, unsigned long *p2,
 	: [inc] "r" (256UL)
 	: "memory" );
 
-	XMMS_RESTORE;
+	kernel_fpu_end();
 }
 
 static void
@@ -269,10 +228,8 @@ xor_sse_5(unsigned long bytes, unsigned long *p1, unsigned long *p2,
 	  unsigned long *p3, unsigned long *p4, unsigned long *p5)
 {
 	unsigned int lines = bytes >> 8;
-	xmm_store_t xmm_save[4];
-	unsigned long cr0;
 
-	XMMS_SAVE;
+	kernel_fpu_begin();
 
 	asm volatile(
 #undef BLOCK
@@ -336,7 +293,7 @@ xor_sse_5(unsigned long bytes, unsigned long *p1, unsigned long *p2,
 	: [inc] "r" (256UL)
 	: "memory");
 
-	XMMS_RESTORE;
+	kernel_fpu_end();
 }
 
 static struct xor_block_template xor_block_sse = {
diff --git a/arch/x86/include/asm/xor_avx.h b/arch/x86/include/asm/xor_avx.h
index 2510d35..7ea79c5 100644
--- a/arch/x86/include/asm/xor_avx.h
+++ b/arch/x86/include/asm/xor_avx.h
@@ -20,32 +20,6 @@
 #include <linux/compiler.h>
 #include <asm/i387.h>
 
-#define ALIGN32 __aligned(32)
-
-#define YMM_SAVED_REGS 4
-
-#define YMMS_SAVE \
-do { \
-	preempt_disable(); \
-	cr0 = read_cr0(); \
-	clts(); \
-	asm volatile("vmovaps %%ymm0, %0" : "=m" (ymm_save[0]) : : "memory"); \
-	asm volatile("vmovaps %%ymm1, %0" : "=m" (ymm_save[32]) : : "memory"); \
-	asm volatile("vmovaps %%ymm2, %0" : "=m" (ymm_save[64]) : : "memory"); \
-	asm volatile("vmovaps %%ymm3, %0" : "=m" (ymm_save[96]) : : "memory"); \
-} while (0);
-
-#define YMMS_RESTORE \
-do { \
-	asm volatile("sfence" : : : "memory"); \
-	asm volatile("vmovaps %0, %%ymm3" : : "m" (ymm_save[96])); \
-	asm volatile("vmovaps %0, %%ymm2" : : "m" (ymm_save[64])); \
-	asm volatile("vmovaps %0, %%ymm1" : : "m" (ymm_save[32])); \
-	asm volatile("vmovaps %0, %%ymm0" : : "m" (ymm_save[0])); \
-	write_cr0(cr0); \
-	preempt_enable(); \
-} while (0);
-
 #define BLOCK4(i) \
 		BLOCK(32 * i, 0) \
 		BLOCK(32 * (i + 1), 1) \
@@ -60,10 +34,9 @@ do { \
 
 static void xor_avx_2(unsigned long bytes, unsigned long *p0, unsigned long *p1)
 {
-	unsigned long cr0, lines = bytes >> 9;
-	char ymm_save[32 * YMM_SAVED_REGS] ALIGN32;
+	unsigned long lines = bytes >> 9;
 
-	YMMS_SAVE
+	kernel_fpu_begin();
 
 	while (lines--) {
 #undef BLOCK
@@ -82,16 +55,15 @@ do { \
 		p1 = (unsigned long *)((uintptr_t)p1 + 512);
 	}
 
-	YMMS_RESTORE
+	kernel_fpu_end();
 }
 
 static void xor_avx_3(unsigned long bytes, unsigned long *p0, unsigned long *p1,
 	unsigned long *p2)
 {
-	unsigned long cr0, lines = bytes >> 9;
-	char ymm_save[32 * YMM_SAVED_REGS] ALIGN32;
+	unsigned long lines = bytes >> 9;
 
-	YMMS_SAVE
+	kernel_fpu_begin();
 
 	while (lines--) {
 #undef BLOCK
@@ -113,16 +85,15 @@ do { \
 		p2 = (unsigned long *)((uintptr_t)p2 + 512);
 	}
 
-	YMMS_RESTORE
+	kernel_fpu_end();
 }
 
 static void xor_avx_4(unsigned long bytes, unsigned long *p0, unsigned long *p1,
 	unsigned long *p2, unsigned long *p3)
 {
-	unsigned long cr0, lines = bytes >> 9;
-	char ymm_save[32 * YMM_SAVED_REGS] ALIGN32;
+	unsigned long lines = bytes >> 9;
 
-	YMMS_SAVE
+	kernel_fpu_begin();
 
 	while (lines--) {
 #undef BLOCK
@@ -147,16 +118,15 @@ do { \
 		p3 = (unsigned long *)((uintptr_t)p3 + 512);
 	}
 
-	YMMS_RESTORE
+	kernel_fpu_end();
 }
 
 static void xor_avx_5(unsigned long bytes, unsigned long *p0, unsigned long *p1,
 	unsigned long *p2, unsigned long *p3, unsigned long *p4)
 {
-	unsigned long cr0, lines = bytes >> 9;
-	char ymm_save[32 * YMM_SAVED_REGS] ALIGN32;
+	unsigned long lines = bytes >> 9;
 
-	YMMS_SAVE
+	kernel_fpu_begin();
 
 	while (lines--) {
 #undef BLOCK
@@ -184,7 +154,7 @@ do { \
 		p4 = (unsigned long *)((uintptr_t)p4 + 512);
 	}
 
-	YMMS_RESTORE
+	kernel_fpu_end();
 }
 
 static struct xor_block_template xor_block_avx = {
diff --git a/arch/x86/include/asm/xsave.h b/arch/x86/include/asm/xsave.h
index 8a1b6f9..0415cda 100644
--- a/arch/x86/include/asm/xsave.h
+++ b/arch/x86/include/asm/xsave.h
@@ -34,17 +34,14 @@
 extern unsigned int xstate_size;
 extern u64 pcntxt_mask;
 extern u64 xstate_fx_sw_bytes[USER_XSTATE_FX_SW_WORDS];
+extern struct xsave_struct *init_xstate_buf;
 
 extern void xsave_init(void);
 extern void update_regset_xstate_info(unsigned int size, u64 xstate_mask);
 extern int init_fpu(struct task_struct *child);
-extern int check_for_xstate(struct i387_fxsave_struct __user *buf,
-			    void __user *fpstate,
-			    struct _fpx_sw_bytes *sw);
 
-static inline int fpu_xrstor_checking(struct fpu *fpu)
+static inline int fpu_xrstor_checking(struct xsave_struct *fx)
 {
-	struct xsave_struct *fx = &fpu->state->xsave;
 	int err;
 
 	asm volatile("1: .byte " REX_PREFIX "0x0f,0xae,0x2f\n\t"
@@ -69,13 +66,13 @@ static inline int xsave_user(struct xsave_struct __user *buf)
 	 * Clear the xsave header first, so that reserved fields are
 	 * initialized to zero.
 	 */
-	err = __clear_user(&buf->xsave_hdr,
-			   sizeof(struct xsave_hdr_struct));
+	err = __clear_user(&buf->xsave_hdr, sizeof(buf->xsave_hdr));
 	if (unlikely(err))
 		return -EFAULT;
 
-	__asm__ __volatile__("1: .byte " REX_PREFIX "0x0f,0xae,0x27\n"
-			     "2:\n"
+	__asm__ __volatile__(ASM_STAC "\n"
+			     "1: .byte " REX_PREFIX "0x0f,0xae,0x27\n"
+			     "2: " ASM_CLAC "\n"
 			     ".section .fixup,\"ax\"\n"
 			     "3:  movl $-1,%[err]\n"
 			     "    jmp  2b\n"
@@ -84,9 +81,6 @@ static inline int xsave_user(struct xsave_struct __user *buf)
 			     : [err] "=r" (err)
 			     : "D" (buf), "a" (-1), "d" (-1), "0" (0)
 			     : "memory");
-	if (unlikely(err) && __clear_user(buf, xstate_size))
-		err = -EFAULT;
-	/* No need to clear here because the caller clears USED_MATH */
 	return err;
 }
 
@@ -97,8 +91,9 @@ static inline int xrestore_user(struct xsave_struct __user *buf, u64 mask)
 	u32 lmask = mask;
 	u32 hmask = mask >> 32;
 
-	__asm__ __volatile__("1: .byte " REX_PREFIX "0x0f,0xae,0x2f\n"
-			     "2:\n"
+	__asm__ __volatile__(ASM_STAC "\n"
+			     "1: .byte " REX_PREFIX "0x0f,0xae,0x2f\n"
+			     "2: " ASM_CLAC "\n"
 			     ".section .fixup,\"ax\"\n"
 			     "3:  movl $-1,%[err]\n"
 			     "    jmp  2b\n"
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 8215e56..91ce48f 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -23,7 +23,7 @@ obj-y			+= time.o ioport.o ldt.o dumpstack.o nmi.o
 obj-y			+= setup.o x86_init.o i8259.o irqinit.o jump_label.o
 obj-$(CONFIG_IRQ_WORK)  += irq_work.o
 obj-y			+= probe_roms.o
-obj-$(CONFIG_X86_32)	+= sys_i386_32.o i386_ksyms_32.o
+obj-$(CONFIG_X86_32)	+= i386_ksyms_32.o
 obj-$(CONFIG_X86_64)	+= sys_x86_64.o x8664_ksyms_64.o
 obj-y			+= syscall_$(BITS).o
 obj-$(CONFIG_X86_64)	+= vsyscall_64.o
@@ -81,8 +81,7 @@ obj-$(CONFIG_DEBUG_RODATA_TEST)	+= test_rodata.o
 obj-$(CONFIG_DEBUG_NX_TEST)	+= test_nx.o
 obj-$(CONFIG_DEBUG_NMI_SELFTEST) += nmi_selftest.o
 
-obj-$(CONFIG_KVM_GUEST)		+= kvm.o
-obj-$(CONFIG_KVM_CLOCK)		+= kvmclock.o
+obj-$(CONFIG_KVM_GUEST)		+= kvm.o kvmclock.o
 obj-$(CONFIG_PARAVIRT)		+= paravirt.o paravirt_patch_$(BITS).o
 obj-$(CONFIG_PARAVIRT_SPINLOCKS)+= paravirt-spinlocks.o
 obj-$(CONFIG_PARAVIRT_CLOCK)	+= pvclock.o
@@ -100,6 +99,8 @@ obj-$(CONFIG_SWIOTLB)			+= pci-swiotlb.o
 obj-$(CONFIG_OF)			+= devicetree.o
 obj-$(CONFIG_UPROBES)			+= uprobes.o
 
+obj-$(CONFIG_PERF_EVENTS)		+= perf_regs.o
+
 ###
 # 64 bit specific files
 ifeq ($(CONFIG_X86_64),y)
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index b2297e5..0d0d856 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -689,8 +689,13 @@ int __ref acpi_map_lsapic(acpi_handle handle, int *pcpu)
 }
 EXPORT_SYMBOL(acpi_map_lsapic);
 
-int acpi_unmap_lsapic(int cpu)
+int __ref acpi_unmap_lsapic(int cpu)
 {
+#ifdef CONFIG_ACPI_NUMA
+	set_apicid_to_node(per_cpu(x86_cpu_to_apicid, cpu), NUMA_NO_NODE);
+	numa_clear_node(cpu);
+#endif
+
 	per_cpu(x86_cpu_to_apicid, cpu) = -1;
 	set_cpu_present(cpu, false);
 	num_processors--;
diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c
index ced4534..ef5ccca 100644
--- a/arch/x86/kernel/alternative.c
+++ b/arch/x86/kernel/alternative.c
@@ -23,19 +23,6 @@
 
 #define MAX_PATCH_LEN (255-1)
 
-#ifdef CONFIG_HOTPLUG_CPU
-static int smp_alt_once;
-
-static int __init bootonly(char *str)
-{
-	smp_alt_once = 1;
-	return 1;
-}
-__setup("smp-alt-boot", bootonly);
-#else
-#define smp_alt_once 1
-#endif
-
 static int __initdata_or_module debug_alternative;
 
 static int __init debug_alt(char *str)
@@ -317,7 +304,7 @@ static void alternatives_smp_lock(const s32 *start, const s32 *end,
 		/* turn DS segment override prefix into lock prefix */
 		if (*ptr == 0x3e)
 			text_poke(ptr, ((unsigned char []){0xf0}), 1);
-	};
+	}
 	mutex_unlock(&text_mutex);
 }
 
@@ -326,9 +313,6 @@ static void alternatives_smp_unlock(const s32 *start, const s32 *end,
 {
 	const s32 *poff;
 
-	if (noreplace_smp)
-		return;
-
 	mutex_lock(&text_mutex);
 	for (poff = start; poff < end; poff++) {
 		u8 *ptr = (u8 *)poff + *poff;
@@ -338,7 +322,7 @@ static void alternatives_smp_unlock(const s32 *start, const s32 *end,
 		/* turn lock prefix into DS segment override prefix */
 		if (*ptr == 0xf0)
 			text_poke(ptr, ((unsigned char []){0x3E}), 1);
-	};
+	}
 	mutex_unlock(&text_mutex);
 }
 
@@ -359,7 +343,7 @@ struct smp_alt_module {
 };
 static LIST_HEAD(smp_alt_modules);
 static DEFINE_MUTEX(smp_alt);
-static int smp_mode = 1;	/* protected by smp_alt */
+static bool uniproc_patched = false;	/* protected by smp_alt */
 
 void __init_or_module alternatives_smp_module_add(struct module *mod,
 						  char *name,
@@ -368,19 +352,18 @@ void __init_or_module alternatives_smp_module_add(struct module *mod,
 {
 	struct smp_alt_module *smp;
 
-	if (noreplace_smp)
-		return;
+	mutex_lock(&smp_alt);
+	if (!uniproc_patched)
+		goto unlock;
 
-	if (smp_alt_once) {
-		if (boot_cpu_has(X86_FEATURE_UP))
-			alternatives_smp_unlock(locks, locks_end,
-						text, text_end);
-		return;
-	}
+	if (num_possible_cpus() == 1)
+		/* Don't bother remembering, we'll never have to undo it. */
+		goto smp_unlock;
 
 	smp = kzalloc(sizeof(*smp), GFP_KERNEL);
 	if (NULL == smp)
-		return; /* we'll run the (safe but slow) SMP code then ... */
+		/* we'll run the (safe but slow) SMP code then ... */
+		goto unlock;
 
 	smp->mod	= mod;
 	smp->name	= name;
@@ -392,11 +375,10 @@ void __init_or_module alternatives_smp_module_add(struct module *mod,
 		__func__, smp->locks, smp->locks_end,
 		smp->text, smp->text_end, smp->name);
 
-	mutex_lock(&smp_alt);
 	list_add_tail(&smp->next, &smp_alt_modules);
-	if (boot_cpu_has(X86_FEATURE_UP))
-		alternatives_smp_unlock(smp->locks, smp->locks_end,
-					smp->text, smp->text_end);
+smp_unlock:
+	alternatives_smp_unlock(locks, locks_end, text, text_end);
+unlock:
 	mutex_unlock(&smp_alt);
 }
 
@@ -404,24 +386,18 @@ void __init_or_module alternatives_smp_module_del(struct module *mod)
 {
 	struct smp_alt_module *item;
 
-	if (smp_alt_once || noreplace_smp)
-		return;
-
 	mutex_lock(&smp_alt);
 	list_for_each_entry(item, &smp_alt_modules, next) {
 		if (mod != item->mod)
 			continue;
 		list_del(&item->next);
-		mutex_unlock(&smp_alt);
-		DPRINTK("%s: %s\n", __func__, item->name);
 		kfree(item);
-		return;
+		break;
 	}
 	mutex_unlock(&smp_alt);
 }
 
-bool skip_smp_alternatives;
-void alternatives_smp_switch(int smp)
+void alternatives_enable_smp(void)
 {
 	struct smp_alt_module *mod;
 
@@ -436,34 +412,21 @@ void alternatives_smp_switch(int smp)
 	pr_info("lockdep: fixing up alternatives\n");
 #endif
 
-	if (noreplace_smp || smp_alt_once || skip_smp_alternatives)
-		return;
-	BUG_ON(!smp && (num_online_cpus() > 1));
+	/* Why bother if there are no other CPUs? */
+	BUG_ON(num_possible_cpus() == 1);
 
 	mutex_lock(&smp_alt);
 
-	/*
-	 * Avoid unnecessary switches because it forces JIT based VMs to
-	 * throw away all cached translations, which can be quite costly.
-	 */
-	if (smp == smp_mode) {
-		/* nothing */
-	} else if (smp) {
+	if (uniproc_patched) {
 		pr_info("switching to SMP code\n");
+		BUG_ON(num_online_cpus() != 1);
 		clear_cpu_cap(&boot_cpu_data, X86_FEATURE_UP);
 		clear_cpu_cap(&cpu_data(0), X86_FEATURE_UP);
 		list_for_each_entry(mod, &smp_alt_modules, next)
 			alternatives_smp_lock(mod->locks, mod->locks_end,
 					      mod->text, mod->text_end);
-	} else {
-		pr_info("switching to UP code\n");
-		set_cpu_cap(&boot_cpu_data, X86_FEATURE_UP);
-		set_cpu_cap(&cpu_data(0), X86_FEATURE_UP);
-		list_for_each_entry(mod, &smp_alt_modules, next)
-			alternatives_smp_unlock(mod->locks, mod->locks_end,
-						mod->text, mod->text_end);
+		uniproc_patched = false;
 	}
-	smp_mode = smp;
 	mutex_unlock(&smp_alt);
 }
 
@@ -540,40 +503,22 @@ void __init alternative_instructions(void)
 
 	apply_alternatives(__alt_instructions, __alt_instructions_end);
 
-	/* switch to patch-once-at-boottime-only mode and free the
-	 * tables in case we know the number of CPUs will never ever
-	 * change */
-#ifdef CONFIG_HOTPLUG_CPU
-	if (num_possible_cpus() < 2)
-		smp_alt_once = 1;
-#endif
-
 #ifdef CONFIG_SMP
-	if (smp_alt_once) {
-		if (1 == num_possible_cpus()) {
-			pr_info("switching to UP code\n");
-			set_cpu_cap(&boot_cpu_data, X86_FEATURE_UP);
-			set_cpu_cap(&cpu_data(0), X86_FEATURE_UP);
-
-			alternatives_smp_unlock(__smp_locks, __smp_locks_end,
-						_text, _etext);
-		}
-	} else {
+	/* Patch to UP if other cpus not imminent. */
+	if (!noreplace_smp && (num_present_cpus() == 1 || setup_max_cpus <= 1)) {
+		uniproc_patched = true;
 		alternatives_smp_module_add(NULL, "core kernel",
 					    __smp_locks, __smp_locks_end,
 					    _text, _etext);
-
-		/* Only switch to UP mode if we don't immediately boot others */
-		if (num_present_cpus() == 1 || setup_max_cpus <= 1)
-			alternatives_smp_switch(0);
 	}
-#endif
- 	apply_paravirt(__parainstructions, __parainstructions_end);
 
-	if (smp_alt_once)
+	if (!uniproc_patched || num_possible_cpus() == 1)
 		free_init_pages("SMP alternatives",
 				(unsigned long)__smp_locks,
 				(unsigned long)__smp_locks_end);
+#endif
+
+	apply_paravirt(__parainstructions, __parainstructions_end);
 
 	restart_nmi();
 }
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index 24deb30..b17416e 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -1934,7 +1934,7 @@ void smp_error_interrupt(struct pt_regs *regs)
 			apic_printk(APIC_DEBUG, KERN_CONT " : %s", error_interrupt_reason[i]);
 		i++;
 		v1 >>= 1;
-	};
+	}
 
 	apic_printk(APIC_DEBUG, KERN_CONT "\n");
 
diff --git a/arch/x86/kernel/apic/apic_numachip.c b/arch/x86/kernel/apic/apic_numachip.c
index bc552cf..a65829a 100644
--- a/arch/x86/kernel/apic/apic_numachip.c
+++ b/arch/x86/kernel/apic/apic_numachip.c
@@ -30,7 +30,7 @@
 
 static int numachip_system __read_mostly;
 
-static struct apic apic_numachip __read_mostly;
+static const struct apic apic_numachip __read_mostly;
 
 static unsigned int get_apic_id(unsigned long x)
 {
@@ -199,7 +199,7 @@ static int numachip_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
 	return 0;
 }
 
-static struct apic apic_numachip __refconst = {
+static const struct apic apic_numachip __refconst = {
 
 	.name				= "NumaConnect system",
 	.probe				= numachip_probe,
diff --git a/arch/x86/kernel/asm-offsets.c b/arch/x86/kernel/asm-offsets.c
index 68de2dc..2861082 100644
--- a/arch/x86/kernel/asm-offsets.c
+++ b/arch/x86/kernel/asm-offsets.c
@@ -69,4 +69,7 @@ void common(void) {
 	OFFSET(BP_kernel_alignment, boot_params, hdr.kernel_alignment);
 	OFFSET(BP_pref_address, boot_params, hdr.pref_address);
 	OFFSET(BP_code32_start, boot_params, hdr.code32_start);
+
+	BLANK();
+	DEFINE(PTREGS_SIZE, sizeof(struct pt_regs));
 }
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index 9d92e19..f7e98a2 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -737,6 +737,72 @@ static unsigned int __cpuinit amd_size_cache(struct cpuinfo_x86 *c,
 }
 #endif
 
+static void __cpuinit cpu_set_tlb_flushall_shift(struct cpuinfo_x86 *c)
+{
+	if (!cpu_has_invlpg)
+		return;
+
+	tlb_flushall_shift = 5;
+
+	if (c->x86 <= 0x11)
+		tlb_flushall_shift = 4;
+}
+
+static void __cpuinit cpu_detect_tlb_amd(struct cpuinfo_x86 *c)
+{
+	u32 ebx, eax, ecx, edx;
+	u16 mask = 0xfff;
+
+	if (c->x86 < 0xf)
+		return;
+
+	if (c->extended_cpuid_level < 0x80000006)
+		return;
+
+	cpuid(0x80000006, &eax, &ebx, &ecx, &edx);
+
+	tlb_lld_4k[ENTRIES] = (ebx >> 16) & mask;
+	tlb_lli_4k[ENTRIES] = ebx & mask;
+
+	/*
+	 * K8 doesn't have 2M/4M entries in the L2 TLB so read out the L1 TLB
+	 * characteristics from the CPUID function 0x80000005 instead.
+	 */
+	if (c->x86 == 0xf) {
+		cpuid(0x80000005, &eax, &ebx, &ecx, &edx);
+		mask = 0xff;
+	}
+
+	/* Handle DTLB 2M and 4M sizes, fall back to L1 if L2 is disabled */
+	if (!((eax >> 16) & mask)) {
+		u32 a, b, c, d;
+
+		cpuid(0x80000005, &a, &b, &c, &d);
+		tlb_lld_2m[ENTRIES] = (a >> 16) & 0xff;
+	} else {
+		tlb_lld_2m[ENTRIES] = (eax >> 16) & mask;
+	}
+
+	/* a 4M entry uses two 2M entries */
+	tlb_lld_4m[ENTRIES] = tlb_lld_2m[ENTRIES] >> 1;
+
+	/* Handle ITLB 2M and 4M sizes, fall back to L1 if L2 is disabled */
+	if (!(eax & mask)) {
+		/* Erratum 658 */
+		if (c->x86 == 0x15 && c->x86_model <= 0x1f) {
+			tlb_lli_2m[ENTRIES] = 1024;
+		} else {
+			cpuid(0x80000005, &eax, &ebx, &ecx, &edx);
+			tlb_lli_2m[ENTRIES] = eax & 0xff;
+		}
+	} else
+		tlb_lli_2m[ENTRIES] = eax & mask;
+
+	tlb_lli_4m[ENTRIES] = tlb_lli_2m[ENTRIES] >> 1;
+
+	cpu_set_tlb_flushall_shift(c);
+}
+
 static const struct cpu_dev __cpuinitconst amd_cpu_dev = {
 	.c_vendor	= "AMD",
 	.c_ident	= { "AuthenticAMD" },
@@ -756,6 +822,7 @@ static const struct cpu_dev __cpuinitconst amd_cpu_dev = {
 	.c_size_cache	= amd_size_cache,
 #endif
 	.c_early_init   = early_init_amd,
+	.c_detect_tlb	= cpu_detect_tlb_amd,
 	.c_bsp_init	= bsp_init_amd,
 	.c_init		= init_amd,
 	.c_x86_vendor	= X86_VENDOR_AMD,
diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
index c97bb7b..d0e910d 100644
--- a/arch/x86/kernel/cpu/bugs.c
+++ b/arch/x86/kernel/cpu/bugs.c
@@ -165,10 +165,15 @@ void __init check_bugs(void)
 	print_cpu_info(&boot_cpu_data);
 #endif
 	check_config();
-	check_fpu();
 	check_hlt();
 	check_popad();
 	init_utsname()->machine[1] =
 		'0' + (boot_cpu_data.x86 > 6 ? 6 : boot_cpu_data.x86);
 	alternative_instructions();
+
+	/*
+	 * kernel_fpu_begin/end() in check_fpu() relies on the patched
+	 * alternative instructions.
+	 */
+	check_fpu();
 }
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index a5fbc3c..683933f 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -278,6 +278,31 @@ static __cpuinit void setup_smep(struct cpuinfo_x86 *c)
 	}
 }
 
+static int disable_smap __cpuinitdata;
+static __init int setup_disable_smap(char *arg)
+{
+	disable_smap = 1;
+	return 1;
+}
+__setup("nosmap", setup_disable_smap);
+
+static __cpuinit void setup_smap(struct cpuinfo_x86 *c)
+{
+	if (cpu_has(c, X86_FEATURE_SMAP)) {
+		if (unlikely(disable_smap)) {
+			setup_clear_cpu_cap(X86_FEATURE_SMAP);
+			clear_in_cr4(X86_CR4_SMAP);
+		} else {
+			set_in_cr4(X86_CR4_SMAP);
+			/*
+			 * Don't use clac() here since alternatives
+			 * haven't run yet...
+			 */
+			asm volatile(__stringify(__ASM_CLAC) ::: "memory");
+		}
+	}
+}
+
 /*
  * Some CPU features depend on higher CPUID levels, which may not always
  * be available due to CPUID level capping or broken virtualization
@@ -476,7 +501,7 @@ void __cpuinit cpu_detect_tlb(struct cpuinfo_x86 *c)
 
 	printk(KERN_INFO "Last level iTLB entries: 4KB %d, 2MB %d, 4MB %d\n" \
 		"Last level dTLB entries: 4KB %d, 2MB %d, 4MB %d\n"	     \
-		"tlb_flushall_shift is 0x%x\n",
+		"tlb_flushall_shift: %d\n",
 		tlb_lli_4k[ENTRIES], tlb_lli_2m[ENTRIES],
 		tlb_lli_4m[ENTRIES], tlb_lld_4k[ENTRIES],
 		tlb_lld_2m[ENTRIES], tlb_lld_4m[ENTRIES],
@@ -713,6 +738,7 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c)
 	filter_cpuid_features(c, false);
 
 	setup_smep(c);
+	setup_smap(c);
 
 	if (this_cpu->c_bsp_init)
 		this_cpu->c_bsp_init(c);
@@ -942,8 +968,7 @@ void __init identify_boot_cpu(void)
 #else
 	vgetcpu_set_mode();
 #endif
-	if (boot_cpu_data.cpuid_level >= 2)
-		cpu_detect_tlb(&boot_cpu_data);
+	cpu_detect_tlb(&boot_cpu_data);
 }
 
 void __cpuinit identify_secondary_cpu(struct cpuinfo_x86 *c)
@@ -1023,14 +1048,16 @@ void __cpuinit print_cpu_info(struct cpuinfo_x86 *c)
 		printk(KERN_CONT "%s ", vendor);
 
 	if (c->x86_model_id[0])
-		printk(KERN_CONT "%s", c->x86_model_id);
+		printk(KERN_CONT "%s", strim(c->x86_model_id));
 	else
 		printk(KERN_CONT "%d86", c->x86);
 
+	printk(KERN_CONT " (fam: %02x, model: %02x", c->x86, c->x86_model);
+
 	if (c->x86_mask || c->cpuid_level >= 0)
-		printk(KERN_CONT " stepping %02x\n", c->x86_mask);
+		printk(KERN_CONT ", stepping: %02x)\n", c->x86_mask);
 	else
-		printk(KERN_CONT "\n");
+		printk(KERN_CONT ")\n");
 
 	print_cpu_msr(c);
 }
@@ -1113,11 +1140,10 @@ void syscall_init(void)
 
 	/* Flags to clear on syscall */
 	wrmsrl(MSR_SYSCALL_MASK,
-	       X86_EFLAGS_TF|X86_EFLAGS_DF|X86_EFLAGS_IF|X86_EFLAGS_IOPL);
+	       X86_EFLAGS_TF|X86_EFLAGS_DF|X86_EFLAGS_IF|
+	       X86_EFLAGS_IOPL|X86_EFLAGS_AC);
 }
 
-unsigned long kernel_eflags;
-
 /*
  * Copies of the original ist values from the tss are only accessed during
  * debugging, no special alignment required.
@@ -1297,9 +1323,6 @@ void __cpuinit cpu_init(void)
 	dbg_restore_debug_regs();
 
 	fpu_init();
-	xsave_init();
-
-	raw_local_save_flags(kernel_eflags);
 
 	if (is_uv_system())
 		uv_cpu_init();
@@ -1352,6 +1375,5 @@ void __cpuinit cpu_init(void)
 	dbg_restore_debug_regs();
 
 	fpu_init();
-	xsave_init();
 }
 #endif
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
index 0a4ce29..198e019 100644
--- a/arch/x86/kernel/cpu/intel.c
+++ b/arch/x86/kernel/cpu/intel.c
@@ -648,6 +648,10 @@ static void __cpuinit intel_detect_tlb(struct cpuinfo_x86 *c)
 	int i, j, n;
 	unsigned int regs[4];
 	unsigned char *desc = (unsigned char *)regs;
+
+	if (c->cpuid_level < 2)
+		return;
+
 	/* Number of times to iterate */
 	n = cpuid_eax(2) & 0xFF;
 
diff --git a/arch/x86/kernel/cpu/mcheck/mce-inject.c b/arch/x86/kernel/cpu/mcheck/mce-inject.c
index fc4beb3..ddc72f8 100644
--- a/arch/x86/kernel/cpu/mcheck/mce-inject.c
+++ b/arch/x86/kernel/cpu/mcheck/mce-inject.c
@@ -78,6 +78,7 @@ static void raise_exception(struct mce *m, struct pt_regs *pregs)
 }
 
 static cpumask_var_t mce_inject_cpumask;
+static DEFINE_MUTEX(mce_inject_mutex);
 
 static int mce_raise_notify(unsigned int cmd, struct pt_regs *regs)
 {
@@ -194,7 +195,11 @@ static void raise_mce(struct mce *m)
 		put_online_cpus();
 	} else
 #endif
+	{
+		preempt_disable();
 		raise_local();
+		preempt_enable();
+	}
 }
 
 /* Error injection interface */
@@ -225,7 +230,10 @@ static ssize_t mce_write(struct file *filp, const char __user *ubuf,
 	 * so do it a jiffie or two later everywhere.
 	 */
 	schedule_timeout(2);
+
+	mutex_lock(&mce_inject_mutex);
 	raise_mce(&m);
+	mutex_unlock(&mce_inject_mutex);
 	return usize;
 }
 
diff --git a/arch/x86/kernel/cpu/mcheck/mce-internal.h b/arch/x86/kernel/cpu/mcheck/mce-internal.h
index ed44c8a..6a05c1d 100644
--- a/arch/x86/kernel/cpu/mcheck/mce-internal.h
+++ b/arch/x86/kernel/cpu/mcheck/mce-internal.h
@@ -28,6 +28,18 @@ extern int mce_ser;
 
 extern struct mce_bank *mce_banks;
 
+#ifdef CONFIG_X86_MCE_INTEL
+unsigned long mce_intel_adjust_timer(unsigned long interval);
+void mce_intel_cmci_poll(void);
+void mce_intel_hcpu_update(unsigned long cpu);
+#else
+# define mce_intel_adjust_timer mce_adjust_timer_default
+static inline void mce_intel_cmci_poll(void) { }
+static inline void mce_intel_hcpu_update(unsigned long cpu) { }
+#endif
+
+void mce_timer_kick(unsigned long interval);
+
 #ifdef CONFIG_ACPI_APEI
 int apei_write_mce(struct mce *m);
 ssize_t apei_read_mce(struct mce *m, u64 *record_id);
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index 292d025..c311122 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -1266,6 +1266,14 @@ static unsigned long check_interval = 5 * 60; /* 5 minutes */
 static DEFINE_PER_CPU(unsigned long, mce_next_interval); /* in jiffies */
 static DEFINE_PER_CPU(struct timer_list, mce_timer);
 
+static unsigned long mce_adjust_timer_default(unsigned long interval)
+{
+	return interval;
+}
+
+static unsigned long (*mce_adjust_timer)(unsigned long interval) =
+	mce_adjust_timer_default;
+
 static void mce_timer_fn(unsigned long data)
 {
 	struct timer_list *t = &__get_cpu_var(mce_timer);
@@ -1276,6 +1284,7 @@ static void mce_timer_fn(unsigned long data)
 	if (mce_available(__this_cpu_ptr(&cpu_info))) {
 		machine_check_poll(MCP_TIMESTAMP,
 				&__get_cpu_var(mce_poll_banks));
+		mce_intel_cmci_poll();
 	}
 
 	/*
@@ -1283,14 +1292,38 @@ static void mce_timer_fn(unsigned long data)
 	 * polling interval, otherwise increase the polling interval.
 	 */
 	iv = __this_cpu_read(mce_next_interval);
-	if (mce_notify_irq())
+	if (mce_notify_irq()) {
 		iv = max(iv / 2, (unsigned long) HZ/100);
-	else
+	} else {
 		iv = min(iv * 2, round_jiffies_relative(check_interval * HZ));
+		iv = mce_adjust_timer(iv);
+	}
 	__this_cpu_write(mce_next_interval, iv);
+	/* Might have become 0 after CMCI storm subsided */
+	if (iv) {
+		t->expires = jiffies + iv;
+		add_timer_on(t, smp_processor_id());
+	}
+}
 
-	t->expires = jiffies + iv;
-	add_timer_on(t, smp_processor_id());
+/*
+ * Ensure that the timer is firing in @interval from now.
+ */
+void mce_timer_kick(unsigned long interval)
+{
+	struct timer_list *t = &__get_cpu_var(mce_timer);
+	unsigned long when = jiffies + interval;
+	unsigned long iv = __this_cpu_read(mce_next_interval);
+
+	if (timer_pending(t)) {
+		if (time_before(when, t->expires))
+			mod_timer_pinned(t, when);
+	} else {
+		t->expires = round_jiffies(when);
+		add_timer_on(t, smp_processor_id());
+	}
+	if (interval < iv)
+		__this_cpu_write(mce_next_interval, interval);
 }
 
 /* Must not be called in IRQ context where del_timer_sync() can deadlock */
@@ -1585,6 +1618,7 @@ static void __mcheck_cpu_init_vendor(struct cpuinfo_x86 *c)
 	switch (c->x86_vendor) {
 	case X86_VENDOR_INTEL:
 		mce_intel_feature_init(c);
+		mce_adjust_timer = mce_intel_adjust_timer;
 		break;
 	case X86_VENDOR_AMD:
 		mce_amd_feature_init(c);
@@ -1594,23 +1628,28 @@ static void __mcheck_cpu_init_vendor(struct cpuinfo_x86 *c)
 	}
 }
 
-static void __mcheck_cpu_init_timer(void)
+static void mce_start_timer(unsigned int cpu, struct timer_list *t)
 {
-	struct timer_list *t = &__get_cpu_var(mce_timer);
-	unsigned long iv = check_interval * HZ;
+	unsigned long iv = mce_adjust_timer(check_interval * HZ);
 
-	setup_timer(t, mce_timer_fn, smp_processor_id());
+	__this_cpu_write(mce_next_interval, iv);
 
-	if (mce_ignore_ce)
+	if (mce_ignore_ce || !iv)
 		return;
 
-	__this_cpu_write(mce_next_interval, iv);
-	if (!iv)
-		return;
 	t->expires = round_jiffies(jiffies + iv);
 	add_timer_on(t, smp_processor_id());
 }
 
+static void __mcheck_cpu_init_timer(void)
+{
+	struct timer_list *t = &__get_cpu_var(mce_timer);
+	unsigned int cpu = smp_processor_id();
+
+	setup_timer(t, mce_timer_fn, cpu);
+	mce_start_timer(cpu, t);
+}
+
 /* Handle unconfigured int18 (should never happen) */
 static void unexpected_machine_check(struct pt_regs *regs, long error_code)
 {
@@ -2294,38 +2333,33 @@ 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) {
+	switch (action & ~CPU_TASKS_FROZEN) {
 	case CPU_ONLINE:
-	case CPU_ONLINE_FROZEN:
 		mce_device_create(cpu);
 		if (threshold_cpu_callback)
 			threshold_cpu_callback(action, cpu);
 		break;
 	case CPU_DEAD:
-	case CPU_DEAD_FROZEN:
 		if (threshold_cpu_callback)
 			threshold_cpu_callback(action, cpu);
 		mce_device_remove(cpu);
+		mce_intel_hcpu_update(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);
+		del_timer_sync(t);
 		break;
 	case CPU_DOWN_FAILED:
-	case CPU_DOWN_FAILED_FROZEN:
-		if (!mce_ignore_ce && check_interval) {
-			t->expires = round_jiffies(jiffies +
-					per_cpu(mce_next_interval, cpu));
-			add_timer_on(t, cpu);
-		}
 		smp_call_function_single(cpu, mce_reenable_cpu, &action, 1);
+		mce_start_timer(cpu, t);
 		break;
-	case CPU_POST_DEAD:
+	}
+
+	if (action == CPU_POST_DEAD) {
 		/* intentionally ignoring frozen here */
 		cmci_rediscover(cpu);
-		break;
 	}
+
 	return NOTIFY_OK;
 }
 
diff --git a/arch/x86/kernel/cpu/mcheck/mce_intel.c b/arch/x86/kernel/cpu/mcheck/mce_intel.c
index 38e49bc..098386f 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_intel.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_intel.c
@@ -15,6 +15,8 @@
 #include <asm/msr.h>
 #include <asm/mce.h>
 
+#include "mce-internal.h"
+
 /*
  * Support for Intel Correct Machine Check Interrupts. This allows
  * the CPU to raise an interrupt when a corrected machine check happened.
@@ -30,7 +32,22 @@ static DEFINE_PER_CPU(mce_banks_t, mce_banks_owned);
  */
 static DEFINE_RAW_SPINLOCK(cmci_discover_lock);
 
-#define CMCI_THRESHOLD 1
+#define CMCI_THRESHOLD		1
+#define CMCI_POLL_INTERVAL	(30 * HZ)
+#define CMCI_STORM_INTERVAL	(1 * HZ)
+#define CMCI_STORM_THRESHOLD	15
+
+static DEFINE_PER_CPU(unsigned long, cmci_time_stamp);
+static DEFINE_PER_CPU(unsigned int, cmci_storm_cnt);
+static DEFINE_PER_CPU(unsigned int, cmci_storm_state);
+
+enum {
+	CMCI_STORM_NONE,
+	CMCI_STORM_ACTIVE,
+	CMCI_STORM_SUBSIDED,
+};
+
+static atomic_t cmci_storm_on_cpus;
 
 static int cmci_supported(int *banks)
 {
@@ -53,6 +70,93 @@ static int cmci_supported(int *banks)
 	return !!(cap & MCG_CMCI_P);
 }
 
+void mce_intel_cmci_poll(void)
+{
+	if (__this_cpu_read(cmci_storm_state) == CMCI_STORM_NONE)
+		return;
+	machine_check_poll(MCP_TIMESTAMP, &__get_cpu_var(mce_banks_owned));
+}
+
+void mce_intel_hcpu_update(unsigned long cpu)
+{
+	if (per_cpu(cmci_storm_state, cpu) == CMCI_STORM_ACTIVE)
+		atomic_dec(&cmci_storm_on_cpus);
+
+	per_cpu(cmci_storm_state, cpu) = CMCI_STORM_NONE;
+}
+
+unsigned long mce_intel_adjust_timer(unsigned long interval)
+{
+	int r;
+
+	if (interval < CMCI_POLL_INTERVAL)
+		return interval;
+
+	switch (__this_cpu_read(cmci_storm_state)) {
+	case CMCI_STORM_ACTIVE:
+		/*
+		 * We switch back to interrupt mode once the poll timer has
+		 * silenced itself. That means no events recorded and the
+		 * timer interval is back to our poll interval.
+		 */
+		__this_cpu_write(cmci_storm_state, CMCI_STORM_SUBSIDED);
+		r = atomic_sub_return(1, &cmci_storm_on_cpus);
+		if (r == 0)
+			pr_notice("CMCI storm subsided: switching to interrupt mode\n");
+		/* FALLTHROUGH */
+
+	case CMCI_STORM_SUBSIDED:
+		/*
+		 * We wait for all cpus to go back to SUBSIDED
+		 * state. When that happens we switch back to
+		 * interrupt mode.
+		 */
+		if (!atomic_read(&cmci_storm_on_cpus)) {
+			__this_cpu_write(cmci_storm_state, CMCI_STORM_NONE);
+			cmci_reenable();
+			cmci_recheck();
+		}
+		return CMCI_POLL_INTERVAL;
+	default:
+		/*
+		 * We have shiny weather. Let the poll do whatever it
+		 * thinks.
+		 */
+		return interval;
+	}
+}
+
+static bool cmci_storm_detect(void)
+{
+	unsigned int cnt = __this_cpu_read(cmci_storm_cnt);
+	unsigned long ts = __this_cpu_read(cmci_time_stamp);
+	unsigned long now = jiffies;
+	int r;
+
+	if (__this_cpu_read(cmci_storm_state) != CMCI_STORM_NONE)
+		return true;
+
+	if (time_before_eq(now, ts + CMCI_STORM_INTERVAL)) {
+		cnt++;
+	} else {
+		cnt = 1;
+		__this_cpu_write(cmci_time_stamp, now);
+	}
+	__this_cpu_write(cmci_storm_cnt, cnt);
+
+	if (cnt <= CMCI_STORM_THRESHOLD)
+		return false;
+
+	cmci_clear();
+	__this_cpu_write(cmci_storm_state, CMCI_STORM_ACTIVE);
+	r = atomic_add_return(1, &cmci_storm_on_cpus);
+	mce_timer_kick(CMCI_POLL_INTERVAL);
+
+	if (r == 1)
+		pr_notice("CMCI storm detected: switching to poll mode\n");
+	return true;
+}
+
 /*
  * The interrupt handler. This is called on every event.
  * Just call the poller directly to log any events.
@@ -61,28 +165,21 @@ static int cmci_supported(int *banks)
  */
 static void intel_threshold_interrupt(void)
 {
+	if (cmci_storm_detect())
+		return;
 	machine_check_poll(MCP_TIMESTAMP, &__get_cpu_var(mce_banks_owned));
 	mce_notify_irq();
 }
 
-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)
+static void cmci_discover(int banks)
 {
 	unsigned long *owned = (void *)&__get_cpu_var(mce_banks_owned);
 	unsigned long flags;
-	int hdr = 0;
 	int i;
 
 	raw_spin_lock_irqsave(&cmci_discover_lock, flags);
@@ -96,8 +193,7 @@ static void cmci_discover(int banks, int boot)
 
 		/* Already owned by someone else? */
 		if (val & MCI_CTL2_CMCI_EN) {
-			if (test_and_clear_bit(i, owned) && !boot)
-				print_update("SHD", &hdr, i);
+			clear_bit(i, owned);
 			__clear_bit(i, __get_cpu_var(mce_poll_banks));
 			continue;
 		}
@@ -109,16 +205,13 @@ static void cmci_discover(int banks, int boot)
 
 		/* Did the enable bit stick? -- the bank supports CMCI */
 		if (val & MCI_CTL2_CMCI_EN) {
-			if (!test_and_set_bit(i, owned) && !boot)
-				print_update("CMCI", &hdr, i);
+			set_bit(i, owned);
 			__clear_bit(i, __get_cpu_var(mce_poll_banks));
 		} else {
 			WARN_ON(!test_bit(i, __get_cpu_var(mce_poll_banks)));
 		}
 	}
 	raw_spin_unlock_irqrestore(&cmci_discover_lock, flags);
-	if (hdr)
-		printk(KERN_CONT "\n");
 }
 
 /*
@@ -186,7 +279,7 @@ void cmci_rediscover(int dying)
 			continue;
 		/* Recheck banks in case CPUs don't all have the same */
 		if (cmci_supported(&banks))
-			cmci_discover(banks, 0);
+			cmci_discover(banks);
 	}
 
 	set_cpus_allowed_ptr(current, old);
@@ -200,7 +293,7 @@ void cmci_reenable(void)
 {
 	int banks;
 	if (cmci_supported(&banks))
-		cmci_discover(banks, 0);
+		cmci_discover(banks);
 }
 
 static void intel_init_cmci(void)
@@ -211,7 +304,7 @@ static void intel_init_cmci(void)
 		return;
 
 	mce_threshold_vector = intel_threshold_interrupt;
-	cmci_discover(banks, 1);
+	cmci_discover(banks);
 	/*
 	 * For CPU #0 this runs with still disabled APIC, but that's
 	 * ok because only the vector is set up. We still do another
diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.c b/arch/x86/kernel/cpu/perf_event_intel_uncore.c
index 38e4894..db917ec 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_uncore.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.c
@@ -2347,6 +2347,27 @@ int uncore_pmu_event_init(struct perf_event *event)
 	return ret;
 }
 
+static ssize_t uncore_get_attr_cpumask(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	int n = cpulist_scnprintf(buf, PAGE_SIZE - 2, &uncore_cpu_mask);
+
+	buf[n++] = '\n';
+	buf[n] = '\0';
+	return n;
+}
+
+static DEVICE_ATTR(cpumask, S_IRUGO, uncore_get_attr_cpumask, NULL);
+
+static struct attribute *uncore_pmu_attrs[] = {
+	&dev_attr_cpumask.attr,
+	NULL,
+};
+
+static struct attribute_group uncore_pmu_attr_group = {
+	.attrs = uncore_pmu_attrs,
+};
+
 static int __init uncore_pmu_register(struct intel_uncore_pmu *pmu)
 {
 	int ret;
@@ -2384,8 +2405,8 @@ static void __init uncore_type_exit(struct intel_uncore_type *type)
 		free_percpu(type->pmus[i].box);
 	kfree(type->pmus);
 	type->pmus = NULL;
-	kfree(type->attr_groups[1]);
-	type->attr_groups[1] = NULL;
+	kfree(type->events_group);
+	type->events_group = NULL;
 }
 
 static void __init uncore_types_exit(struct intel_uncore_type **types)
@@ -2437,9 +2458,10 @@ static int __init uncore_type_init(struct intel_uncore_type *type)
 		for (j = 0; j < i; j++)
 			attrs[j] = &type->event_descs[j].attr.attr;
 
-		type->attr_groups[1] = events_group;
+		type->events_group = events_group;
 	}
 
+	type->pmu_group = &uncore_pmu_attr_group;
 	type->pmus = pmus;
 	return 0;
 fail:
diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.h b/arch/x86/kernel/cpu/perf_event_intel_uncore.h
index 5b81c18..e68a455 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_uncore.h
+++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.h
@@ -369,10 +369,12 @@ struct intel_uncore_type {
 	struct intel_uncore_pmu *pmus;
 	struct intel_uncore_ops *ops;
 	struct uncore_event_desc *event_descs;
-	const struct attribute_group *attr_groups[3];
+	const struct attribute_group *attr_groups[4];
 };
 
-#define format_group attr_groups[0]
+#define pmu_group attr_groups[0]
+#define format_group attr_groups[1]
+#define events_group attr_groups[2]
 
 struct intel_uncore_ops {
 	void (*init_box)(struct intel_uncore_box *);
diff --git a/arch/x86/kernel/cpuid.c b/arch/x86/kernel/cpuid.c
index 39472dd..60c7891 100644
--- a/arch/x86/kernel/cpuid.c
+++ b/arch/x86/kernel/cpuid.c
@@ -199,12 +199,14 @@ static int __init cpuid_init(void)
 		goto out_chrdev;
 	}
 	cpuid_class->devnode = cpuid_devnode;
+	get_online_cpus();
 	for_each_online_cpu(i) {
 		err = cpuid_device_create(i);
 		if (err != 0)
 			goto out_class;
 	}
 	register_hotcpu_notifier(&cpuid_class_cpu_notifier);
+	put_online_cpus();
 
 	err = 0;
 	goto out;
@@ -214,6 +216,7 @@ out_class:
 	for_each_online_cpu(i) {
 		cpuid_device_destroy(i);
 	}
+	put_online_cpus();
 	class_destroy(cpuid_class);
 out_chrdev:
 	__unregister_chrdev(CPUID_MAJOR, 0, NR_CPUS, "cpu/cpuid");
@@ -225,11 +228,13 @@ static void __exit cpuid_exit(void)
 {
 	int cpu = 0;
 
+	get_online_cpus();
 	for_each_online_cpu(cpu)
 		cpuid_device_destroy(cpu);
 	class_destroy(cpuid_class);
 	__unregister_chrdev(CPUID_MAJOR, 0, NR_CPUS, "cpu/cpuid");
 	unregister_hotcpu_notifier(&cpuid_class_cpu_notifier);
+	put_online_cpus();
 }
 
 module_init(cpuid_init);
diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c
index 3ae2ced..b158152 100644
--- a/arch/x86/kernel/devicetree.c
+++ b/arch/x86/kernel/devicetree.c
@@ -342,6 +342,47 @@ const struct irq_domain_ops ioapic_irq_domain_ops = {
 	.xlate = ioapic_xlate,
 };
 
+static void dt_add_ioapic_domain(unsigned int ioapic_num,
+		struct device_node *np)
+{
+	struct irq_domain *id;
+	struct mp_ioapic_gsi *gsi_cfg;
+	int ret;
+	int num;
+
+	gsi_cfg = mp_ioapic_gsi_routing(ioapic_num);
+	num = gsi_cfg->gsi_end - gsi_cfg->gsi_base + 1;
+
+	id = irq_domain_add_linear(np, num, &ioapic_irq_domain_ops,
+			(void *)ioapic_num);
+	BUG_ON(!id);
+	if (gsi_cfg->gsi_base == 0) {
+		/*
+		 * The first NR_IRQS_LEGACY irq descs are allocated in
+		 * early_irq_init() and need just a mapping. The
+		 * remaining irqs need both. All of them are preallocated
+		 * and assigned so we can keep the 1:1 mapping which the ioapic
+		 * is having.
+		 */
+		ret = irq_domain_associate_many(id, 0, 0, NR_IRQS_LEGACY);
+		if (ret)
+			pr_err("Error mapping legacy IRQs: %d\n", ret);
+
+		if (num > NR_IRQS_LEGACY) {
+			ret = irq_create_strict_mappings(id, NR_IRQS_LEGACY,
+					NR_IRQS_LEGACY, num - NR_IRQS_LEGACY);
+			if (ret)
+				pr_err("Error creating mapping for the "
+						"remaining IRQs: %d\n", ret);
+		}
+		irq_set_default_host(id);
+	} else {
+		ret = irq_create_strict_mappings(id, gsi_cfg->gsi_base, 0, num);
+		if (ret)
+			pr_err("Error creating IRQ mapping: %d\n", ret);
+	}
+}
+
 static void __init ioapic_add_ofnode(struct device_node *np)
 {
 	struct resource r;
@@ -356,15 +397,7 @@ static void __init ioapic_add_ofnode(struct device_node *np)
 
 	for (i = 0; i < nr_ioapics; i++) {
 		if (r.start == mpc_ioapic_addr(i)) {
-			struct irq_domain *id;
-			struct mp_ioapic_gsi *gsi_cfg;
-
-			gsi_cfg = mp_ioapic_gsi_routing(i);
-
-			id = irq_domain_add_legacy(np, 32, gsi_cfg->gsi_base, 0,
-						   &ioapic_irq_domain_ops,
-						   (void*)i);
-			BUG_ON(!id);
+			dt_add_ioapic_domain(i, np);
 			return;
 		}
 	}
diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S
index 623f288..2c63407 100644
--- a/arch/x86/kernel/entry_32.S
+++ b/arch/x86/kernel/entry_32.S
@@ -57,6 +57,7 @@
 #include <asm/cpufeature.h>
 #include <asm/alternative-asm.h>
 #include <asm/asm.h>
+#include <asm/smap.h>
 
 /* Avoid __ASSEMBLER__'ifying <linux/audit.h> just for this.  */
 #include <linux/elf-em.h>
@@ -298,6 +299,13 @@ ENTRY(ret_from_fork)
 	CFI_ENDPROC
 END(ret_from_fork)
 
+ENTRY(ret_from_kernel_execve)
+	movl %eax, %esp
+	movl $0,PT_EAX(%esp)
+	GET_THREAD_INFO(%ebp)
+	jmp syscall_exit
+END(ret_from_kernel_execve)
+
 /*
  * Interrupt exit functions should be protected against kprobes
  */
@@ -322,8 +330,7 @@ ret_from_intr:
 	andl $(X86_EFLAGS_VM | SEGMENT_RPL_MASK), %eax
 #else
 	/*
-	 * We can be coming here from a syscall done in the kernel space,
-	 * e.g. a failed kernel_execve().
+	 * We can be coming here from child spawned by kernel_thread().
 	 */
 	movl PT_CS(%esp), %eax
 	andl $SEGMENT_RPL_MASK, %eax
@@ -407,7 +414,9 @@ sysenter_past_esp:
  */
 	cmpl $__PAGE_OFFSET-3,%ebp
 	jae syscall_fault
+	ASM_STAC
 1:	movl (%ebp),%ebp
+	ASM_CLAC
 	movl %ebp,PT_EBP(%esp)
 	_ASM_EXTABLE(1b,syscall_fault)
 
@@ -488,6 +497,7 @@ ENDPROC(ia32_sysenter_target)
 	# system call handler stub
 ENTRY(system_call)
 	RING0_INT_FRAME			# can't unwind into user space anyway
+	ASM_CLAC
 	pushl_cfi %eax			# save orig_eax
 	SAVE_ALL
 	GET_THREAD_INFO(%ebp)
@@ -612,6 +622,10 @@ work_notifysig:				# deal with pending signals and
 	movl %esp, %eax
 	jne work_notifysig_v86		# returning to kernel-space or
 					# vm86-space
+1:
+#else
+	movl %esp, %eax
+#endif
 	TRACE_IRQS_ON
 	ENABLE_INTERRUPTS(CLBR_NONE)
 	movb PT_CS(%esp), %bl
@@ -622,24 +636,15 @@ work_notifysig:				# deal with pending signals and
 	call do_notify_resume
 	jmp resume_userspace
 
+#ifdef CONFIG_VM86
 	ALIGN
 work_notifysig_v86:
 	pushl_cfi %ecx			# save ti_flags for do_notify_resume
 	call save_v86_state		# %eax contains pt_regs pointer
 	popl_cfi %ecx
 	movl %eax, %esp
-#else
-	movl %esp, %eax
+	jmp 1b
 #endif
-	TRACE_IRQS_ON
-	ENABLE_INTERRUPTS(CLBR_NONE)
-	movb PT_CS(%esp), %bl
-	andb $SEGMENT_RPL_MASK, %bl
-	cmpb $USER_RPL, %bl
-	jb resume_kernel
-	xorl %edx, %edx
-	call do_notify_resume
-	jmp resume_userspace
 END(work_pending)
 
 	# perform syscall exit tracing
@@ -670,6 +675,7 @@ END(syscall_exit_work)
 
 	RING0_INT_FRAME			# can't unwind into user space anyway
 syscall_fault:
+	ASM_CLAC
 	GET_THREAD_INFO(%ebp)
 	movl $-EFAULT,PT_EAX(%esp)
 	jmp resume_userspace
@@ -727,7 +733,6 @@ ENDPROC(ptregs_##name)
 PTREGSCALL1(iopl)
 PTREGSCALL0(fork)
 PTREGSCALL0(vfork)
-PTREGSCALL3(execve)
 PTREGSCALL2(sigaltstack)
 PTREGSCALL0(sigreturn)
 PTREGSCALL0(rt_sigreturn)
@@ -825,6 +830,7 @@ END(interrupt)
  */
 	.p2align CONFIG_X86_L1_CACHE_SHIFT
 common_interrupt:
+	ASM_CLAC
 	addl $-0x80,(%esp)	/* Adjust vector into the [-256,-1] range */
 	SAVE_ALL
 	TRACE_IRQS_OFF
@@ -841,6 +847,7 @@ ENDPROC(common_interrupt)
 #define BUILD_INTERRUPT3(name, nr, fn)	\
 ENTRY(name)				\
 	RING0_INT_FRAME;		\
+	ASM_CLAC;			\
 	pushl_cfi $~(nr);		\
 	SAVE_ALL;			\
 	TRACE_IRQS_OFF			\
@@ -857,6 +864,7 @@ ENDPROC(name)
 
 ENTRY(coprocessor_error)
 	RING0_INT_FRAME
+	ASM_CLAC
 	pushl_cfi $0
 	pushl_cfi $do_coprocessor_error
 	jmp error_code
@@ -865,6 +873,7 @@ END(coprocessor_error)
 
 ENTRY(simd_coprocessor_error)
 	RING0_INT_FRAME
+	ASM_CLAC
 	pushl_cfi $0
 #ifdef CONFIG_X86_INVD_BUG
 	/* AMD 486 bug: invd from userspace calls exception 19 instead of #GP */
@@ -886,6 +895,7 @@ END(simd_coprocessor_error)
 
 ENTRY(device_not_available)
 	RING0_INT_FRAME
+	ASM_CLAC
 	pushl_cfi $-1			# mark this as an int
 	pushl_cfi $do_device_not_available
 	jmp error_code
@@ -906,6 +916,7 @@ END(native_irq_enable_sysexit)
 
 ENTRY(overflow)
 	RING0_INT_FRAME
+	ASM_CLAC
 	pushl_cfi $0
 	pushl_cfi $do_overflow
 	jmp error_code
@@ -914,6 +925,7 @@ END(overflow)
 
 ENTRY(bounds)
 	RING0_INT_FRAME
+	ASM_CLAC
 	pushl_cfi $0
 	pushl_cfi $do_bounds
 	jmp error_code
@@ -922,6 +934,7 @@ END(bounds)
 
 ENTRY(invalid_op)
 	RING0_INT_FRAME
+	ASM_CLAC
 	pushl_cfi $0
 	pushl_cfi $do_invalid_op
 	jmp error_code
@@ -930,6 +943,7 @@ END(invalid_op)
 
 ENTRY(coprocessor_segment_overrun)
 	RING0_INT_FRAME
+	ASM_CLAC
 	pushl_cfi $0
 	pushl_cfi $do_coprocessor_segment_overrun
 	jmp error_code
@@ -938,6 +952,7 @@ END(coprocessor_segment_overrun)
 
 ENTRY(invalid_TSS)
 	RING0_EC_FRAME
+	ASM_CLAC
 	pushl_cfi $do_invalid_TSS
 	jmp error_code
 	CFI_ENDPROC
@@ -945,6 +960,7 @@ END(invalid_TSS)
 
 ENTRY(segment_not_present)
 	RING0_EC_FRAME
+	ASM_CLAC
 	pushl_cfi $do_segment_not_present
 	jmp error_code
 	CFI_ENDPROC
@@ -952,6 +968,7 @@ END(segment_not_present)
 
 ENTRY(stack_segment)
 	RING0_EC_FRAME
+	ASM_CLAC
 	pushl_cfi $do_stack_segment
 	jmp error_code
 	CFI_ENDPROC
@@ -959,6 +976,7 @@ END(stack_segment)
 
 ENTRY(alignment_check)
 	RING0_EC_FRAME
+	ASM_CLAC
 	pushl_cfi $do_alignment_check
 	jmp error_code
 	CFI_ENDPROC
@@ -966,6 +984,7 @@ END(alignment_check)
 
 ENTRY(divide_error)
 	RING0_INT_FRAME
+	ASM_CLAC
 	pushl_cfi $0			# no error code
 	pushl_cfi $do_divide_error
 	jmp error_code
@@ -975,6 +994,7 @@ END(divide_error)
 #ifdef CONFIG_X86_MCE
 ENTRY(machine_check)
 	RING0_INT_FRAME
+	ASM_CLAC
 	pushl_cfi $0
 	pushl_cfi machine_check_vector
 	jmp error_code
@@ -984,6 +1004,7 @@ END(machine_check)
 
 ENTRY(spurious_interrupt_bug)
 	RING0_INT_FRAME
+	ASM_CLAC
 	pushl_cfi $0
 	pushl_cfi $do_spurious_interrupt_bug
 	jmp error_code
@@ -994,15 +1015,20 @@ END(spurious_interrupt_bug)
  */
 	.popsection
 
-ENTRY(kernel_thread_helper)
-	pushl $0		# fake return address for unwinder
+ENTRY(ret_from_kernel_thread)
 	CFI_STARTPROC
-	movl %edi,%eax
-	call *%esi
+	pushl_cfi %eax
+	call schedule_tail
+	GET_THREAD_INFO(%ebp)
+	popl_cfi %eax
+	pushl_cfi $0x0202		# Reset kernel eflags
+	popfl_cfi
+	movl PT_EBP(%esp),%eax
+	call *PT_EBX(%esp)
 	call do_exit
 	ud2			# padding for call trace
 	CFI_ENDPROC
-ENDPROC(kernel_thread_helper)
+ENDPROC(ret_from_kernel_thread)
 
 #ifdef CONFIG_XEN
 /* Xen doesn't set %esp to be precisely what the normal sysenter
@@ -1109,17 +1135,21 @@ ENTRY(ftrace_caller)
 	pushl %eax
 	pushl %ecx
 	pushl %edx
-	movl 0xc(%esp), %eax
+	pushl $0	/* Pass NULL as regs pointer */
+	movl 4*4(%esp), %eax
 	movl 0x4(%ebp), %edx
+	leal function_trace_op, %ecx
 	subl $MCOUNT_INSN_SIZE, %eax
 
 .globl ftrace_call
 ftrace_call:
 	call ftrace_stub
 
+	addl $4,%esp	/* skip NULL pointer */
 	popl %edx
 	popl %ecx
 	popl %eax
+ftrace_ret:
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 .globl ftrace_graph_call
 ftrace_graph_call:
@@ -1131,6 +1161,71 @@ ftrace_stub:
 	ret
 END(ftrace_caller)
 
+ENTRY(ftrace_regs_caller)
+	pushf	/* push flags before compare (in cs location) */
+	cmpl $0, function_trace_stop
+	jne ftrace_restore_flags
+
+	/*
+	 * i386 does not save SS and ESP when coming from kernel.
+	 * Instead, to get sp, &regs->sp is used (see ptrace.h).
+	 * Unfortunately, that means eflags must be at the same location
+	 * as the current return ip is. We move the return ip into the
+	 * ip location, and move flags into the return ip location.
+	 */
+	pushl 4(%esp)	/* save return ip into ip slot */
+
+	pushl $0	/* Load 0 into orig_ax */
+	pushl %gs
+	pushl %fs
+	pushl %es
+	pushl %ds
+	pushl %eax
+	pushl %ebp
+	pushl %edi
+	pushl %esi
+	pushl %edx
+	pushl %ecx
+	pushl %ebx
+
+	movl 13*4(%esp), %eax	/* Get the saved flags */
+	movl %eax, 14*4(%esp)	/* Move saved flags into regs->flags location */
+				/* clobbering return ip */
+	movl $__KERNEL_CS,13*4(%esp)
+
+	movl 12*4(%esp), %eax	/* Load ip (1st parameter) */
+	subl $MCOUNT_INSN_SIZE, %eax	/* Adjust ip */
+	movl 0x4(%ebp), %edx	/* Load parent ip (2nd parameter) */
+	leal function_trace_op, %ecx /* Save ftrace_pos in 3rd parameter */
+	pushl %esp		/* Save pt_regs as 4th parameter */
+
+GLOBAL(ftrace_regs_call)
+	call ftrace_stub
+
+	addl $4, %esp		/* Skip pt_regs */
+	movl 14*4(%esp), %eax	/* Move flags back into cs */
+	movl %eax, 13*4(%esp)	/* Needed to keep addl from modifying flags */
+	movl 12*4(%esp), %eax	/* Get return ip from regs->ip */
+	movl %eax, 14*4(%esp)	/* Put return ip back for ret */
+
+	popl %ebx
+	popl %ecx
+	popl %edx
+	popl %esi
+	popl %edi
+	popl %ebp
+	popl %eax
+	popl %ds
+	popl %es
+	popl %fs
+	popl %gs
+	addl $8, %esp		/* Skip orig_ax and ip */
+	popf			/* Pop flags at end (no addl to corrupt flags) */
+	jmp ftrace_ret
+
+ftrace_restore_flags:
+	popf
+	jmp  ftrace_stub
 #else /* ! CONFIG_DYNAMIC_FTRACE */
 
 ENTRY(mcount)
@@ -1171,9 +1266,6 @@ END(mcount)
 
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 ENTRY(ftrace_graph_caller)
-	cmpl $0, function_trace_stop
-	jne ftrace_stub
-
 	pushl %eax
 	pushl %ecx
 	pushl %edx
@@ -1207,6 +1299,7 @@ return_to_handler:
 
 ENTRY(page_fault)
 	RING0_EC_FRAME
+	ASM_CLAC
 	pushl_cfi $do_page_fault
 	ALIGN
 error_code:
@@ -1279,6 +1372,7 @@ END(page_fault)
 
 ENTRY(debug)
 	RING0_INT_FRAME
+	ASM_CLAC
 	cmpl $ia32_sysenter_target,(%esp)
 	jne debug_stack_correct
 	FIX_STACK 12, debug_stack_correct, debug_esp_fix_insn
@@ -1303,6 +1397,7 @@ END(debug)
  */
 ENTRY(nmi)
 	RING0_INT_FRAME
+	ASM_CLAC
 	pushl_cfi %eax
 	movl %ss, %eax
 	cmpw $__ESPFIX_SS, %ax
@@ -1373,6 +1468,7 @@ END(nmi)
 
 ENTRY(int3)
 	RING0_INT_FRAME
+	ASM_CLAC
 	pushl_cfi $-1			# mark this as an int
 	SAVE_ALL
 	TRACE_IRQS_OFF
@@ -1393,6 +1489,7 @@ END(general_protection)
 #ifdef CONFIG_KVM_GUEST
 ENTRY(async_page_fault)
 	RING0_EC_FRAME
+	ASM_CLAC
 	pushl_cfi $do_async_page_fault
 	jmp error_code
 	CFI_ENDPROC
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index 69babd8..9cfd381 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -56,6 +56,7 @@
 #include <asm/ftrace.h>
 #include <asm/percpu.h>
 #include <asm/asm.h>
+#include <asm/smap.h>
 #include <linux/err.h>
 
 /* Avoid __ASSEMBLER__'ifying <linux/audit.h> just for this.  */
@@ -68,25 +69,51 @@
 	.section .entry.text, "ax"
 
 #ifdef CONFIG_FUNCTION_TRACER
+
+#ifdef CC_USING_FENTRY
+# define function_hook	__fentry__
+#else
+# define function_hook	mcount
+#endif
+
 #ifdef CONFIG_DYNAMIC_FTRACE
-ENTRY(mcount)
+
+ENTRY(function_hook)
 	retq
-END(mcount)
+END(function_hook)
+
+/* skip is set if stack has been adjusted */
+.macro ftrace_caller_setup skip=0
+	MCOUNT_SAVE_FRAME \skip
+
+	/* Load the ftrace_ops into the 3rd parameter */
+	leaq function_trace_op, %rdx
+
+	/* Load ip into the first parameter */
+	movq RIP(%rsp), %rdi
+	subq $MCOUNT_INSN_SIZE, %rdi
+	/* Load the parent_ip into the second parameter */
+#ifdef CC_USING_FENTRY
+	movq SS+16(%rsp), %rsi
+#else
+	movq 8(%rbp), %rsi
+#endif
+.endm
 
 ENTRY(ftrace_caller)
+	/* Check if tracing was disabled (quick check) */
 	cmpl $0, function_trace_stop
 	jne  ftrace_stub
 
-	MCOUNT_SAVE_FRAME
-
-	movq 0x38(%rsp), %rdi
-	movq 8(%rbp), %rsi
-	subq $MCOUNT_INSN_SIZE, %rdi
+	ftrace_caller_setup
+	/* regs go into 4th parameter (but make it NULL) */
+	movq $0, %rcx
 
 GLOBAL(ftrace_call)
 	call ftrace_stub
 
 	MCOUNT_RESTORE_FRAME
+ftrace_return:
 
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 GLOBAL(ftrace_graph_call)
@@ -97,8 +124,78 @@ GLOBAL(ftrace_stub)
 	retq
 END(ftrace_caller)
 
+ENTRY(ftrace_regs_caller)
+	/* Save the current flags before compare (in SS location)*/
+	pushfq
+
+	/* Check if tracing was disabled (quick check) */
+	cmpl $0, function_trace_stop
+	jne  ftrace_restore_flags
+
+	/* skip=8 to skip flags saved in SS */
+	ftrace_caller_setup 8
+
+	/* Save the rest of pt_regs */
+	movq %r15, R15(%rsp)
+	movq %r14, R14(%rsp)
+	movq %r13, R13(%rsp)
+	movq %r12, R12(%rsp)
+	movq %r11, R11(%rsp)
+	movq %r10, R10(%rsp)
+	movq %rbp, RBP(%rsp)
+	movq %rbx, RBX(%rsp)
+	/* Copy saved flags */
+	movq SS(%rsp), %rcx
+	movq %rcx, EFLAGS(%rsp)
+	/* Kernel segments */
+	movq $__KERNEL_DS, %rcx
+	movq %rcx, SS(%rsp)
+	movq $__KERNEL_CS, %rcx
+	movq %rcx, CS(%rsp)
+	/* Stack - skipping return address */
+	leaq SS+16(%rsp), %rcx
+	movq %rcx, RSP(%rsp)
+
+	/* regs go into 4th parameter */
+	leaq (%rsp), %rcx
+
+GLOBAL(ftrace_regs_call)
+	call ftrace_stub
+
+	/* Copy flags back to SS, to restore them */
+	movq EFLAGS(%rsp), %rax
+	movq %rax, SS(%rsp)
+
+	/* Handlers can change the RIP */
+	movq RIP(%rsp), %rax
+	movq %rax, SS+8(%rsp)
+
+	/* restore the rest of pt_regs */
+	movq R15(%rsp), %r15
+	movq R14(%rsp), %r14
+	movq R13(%rsp), %r13
+	movq R12(%rsp), %r12
+	movq R10(%rsp), %r10
+	movq RBP(%rsp), %rbp
+	movq RBX(%rsp), %rbx
+
+	/* skip=8 to skip flags saved in SS */
+	MCOUNT_RESTORE_FRAME 8
+
+	/* Restore flags */
+	popfq
+
+	jmp ftrace_return
+ftrace_restore_flags:
+	popfq
+	jmp  ftrace_stub
+
+END(ftrace_regs_caller)
+
+
 #else /* ! CONFIG_DYNAMIC_FTRACE */
-ENTRY(mcount)
+
+ENTRY(function_hook)
 	cmpl $0, function_trace_stop
 	jne  ftrace_stub
 
@@ -119,8 +216,12 @@ GLOBAL(ftrace_stub)
 trace:
 	MCOUNT_SAVE_FRAME
 
-	movq 0x38(%rsp), %rdi
+	movq RIP(%rsp), %rdi
+#ifdef CC_USING_FENTRY
+	movq SS+16(%rsp), %rsi
+#else
 	movq 8(%rbp), %rsi
+#endif
 	subq $MCOUNT_INSN_SIZE, %rdi
 
 	call   *ftrace_trace_function
@@ -128,20 +229,22 @@ trace:
 	MCOUNT_RESTORE_FRAME
 
 	jmp ftrace_stub
-END(mcount)
+END(function_hook)
 #endif /* CONFIG_DYNAMIC_FTRACE */
 #endif /* CONFIG_FUNCTION_TRACER */
 
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 ENTRY(ftrace_graph_caller)
-	cmpl $0, function_trace_stop
-	jne ftrace_stub
-
 	MCOUNT_SAVE_FRAME
 
+#ifdef CC_USING_FENTRY
+	leaq SS+16(%rsp), %rdi
+	movq $0, %rdx	/* No framepointers needed */
+#else
 	leaq 8(%rbp), %rdi
-	movq 0x38(%rsp), %rsi
 	movq (%rbp), %rdx
+#endif
+	movq RIP(%rsp), %rsi
 	subq $MCOUNT_INSN_SIZE, %rsi
 
 	call	prepare_ftrace_return
@@ -440,7 +543,7 @@ ENTRY(ret_from_fork)
 
 	LOCK ; btr $TIF_FORK,TI_flags(%r8)
 
-	pushq_cfi kernel_eflags(%rip)
+	pushq_cfi $0x0002
 	popfq_cfi				# reset kernel eflags
 
 	call schedule_tail			# rdi: 'prev' task parameter
@@ -450,7 +553,7 @@ ENTRY(ret_from_fork)
 	RESTORE_REST
 
 	testl $3, CS-ARGOFFSET(%rsp)		# from kernel_thread?
-	jz   retint_restore_args
+	jz   1f
 
 	testl $_TIF_IA32, TI_flags(%rcx)	# 32-bit compat task needs IRET
 	jnz  int_ret_from_sys_call
@@ -458,6 +561,16 @@ ENTRY(ret_from_fork)
 	RESTORE_TOP_OF_STACK %rdi, -ARGOFFSET
 	jmp ret_from_sys_call			# go to the SYSRET fastpath
 
+1:
+	subq $REST_SKIP, %rsp	# move the stack pointer back
+	CFI_ADJUST_CFA_OFFSET	REST_SKIP
+	movq %rbp, %rdi
+	call *%rbx
+	# exit
+	mov %eax, %edi
+	call do_exit
+	ud2			# padding for call trace
+
 	CFI_ENDPROC
 END(ret_from_fork)
 
@@ -465,7 +578,8 @@ END(ret_from_fork)
  * System call entry. Up to 6 arguments in registers are supported.
  *
  * SYSCALL does not save anything on the stack and does not change the
- * stack pointer.
+ * stack pointer.  However, it does mask the flags register for us, so
+ * CLD and CLAC are not needed.
  */
 
 /*
@@ -757,7 +871,6 @@ ENTRY(stub_execve)
 	PARTIAL_FRAME 0
 	SAVE_REST
 	FIXUP_TOP_OF_STACK %r11
-	movq %rsp, %rcx
 	call sys_execve
 	RESTORE_TOP_OF_STACK %r11
 	movq %rax,RAX(%rsp)
@@ -807,8 +920,7 @@ ENTRY(stub_x32_execve)
 	PARTIAL_FRAME 0
 	SAVE_REST
 	FIXUP_TOP_OF_STACK %r11
-	movq %rsp, %rcx
-	call sys32_execve
+	call compat_sys_execve
 	RESTORE_TOP_OF_STACK %r11
 	movq %rax,RAX(%rsp)
 	RESTORE_REST
@@ -884,6 +996,7 @@ END(interrupt)
 	 */
 	.p2align CONFIG_X86_L1_CACHE_SHIFT
 common_interrupt:
+	ASM_CLAC
 	XCPT_FRAME
 	addq $-0x80,(%rsp)		/* Adjust vector to [-256,-1] range */
 	interrupt do_IRQ
@@ -1023,6 +1136,7 @@ END(common_interrupt)
  */
 .macro apicinterrupt num sym do_sym
 ENTRY(\sym)
+	ASM_CLAC
 	INTR_FRAME
 	pushq_cfi $~(\num)
 .Lcommon_\sym:
@@ -1077,6 +1191,7 @@ apicinterrupt IRQ_WORK_VECTOR \
  */
 .macro zeroentry sym do_sym
 ENTRY(\sym)
+	ASM_CLAC
 	INTR_FRAME
 	PARAVIRT_ADJUST_EXCEPTION_FRAME
 	pushq_cfi $-1		/* ORIG_RAX: no syscall to restart */
@@ -1094,6 +1209,7 @@ END(\sym)
 
 .macro paranoidzeroentry sym do_sym
 ENTRY(\sym)
+	ASM_CLAC
 	INTR_FRAME
 	PARAVIRT_ADJUST_EXCEPTION_FRAME
 	pushq_cfi $-1		/* ORIG_RAX: no syscall to restart */
@@ -1112,6 +1228,7 @@ END(\sym)
 #define INIT_TSS_IST(x) PER_CPU_VAR(init_tss) + (TSS_ist + ((x) - 1) * 8)
 .macro paranoidzeroentry_ist sym do_sym ist
 ENTRY(\sym)
+	ASM_CLAC
 	INTR_FRAME
 	PARAVIRT_ADJUST_EXCEPTION_FRAME
 	pushq_cfi $-1		/* ORIG_RAX: no syscall to restart */
@@ -1131,6 +1248,7 @@ END(\sym)
 
 .macro errorentry sym do_sym
 ENTRY(\sym)
+	ASM_CLAC
 	XCPT_FRAME
 	PARAVIRT_ADJUST_EXCEPTION_FRAME
 	subq $ORIG_RAX-R15, %rsp
@@ -1149,6 +1267,7 @@ END(\sym)
 	/* error code is on the stack already */
 .macro paranoiderrorentry sym do_sym
 ENTRY(\sym)
+	ASM_CLAC
 	XCPT_FRAME
 	PARAVIRT_ADJUST_EXCEPTION_FRAME
 	subq $ORIG_RAX-R15, %rsp
@@ -1206,51 +1325,19 @@ bad_gs:
 	jmp  2b
 	.previous
 
-ENTRY(kernel_thread_helper)
-	pushq $0		# fake return address
-	CFI_STARTPROC
-	/*
-	 * Here we are in the child and the registers are set as they were
-	 * at kernel_thread() invocation in the parent.
-	 */
-	call *%rsi
-	# exit
-	mov %eax, %edi
-	call do_exit
-	ud2			# padding for call trace
-	CFI_ENDPROC
-END(kernel_thread_helper)
-
-/*
- * execve(). This function needs to use IRET, not SYSRET, to set up all state properly.
- *
- * C extern interface:
- *	 extern long execve(const char *name, char **argv, char **envp)
- *
- * asm input arguments:
- *	rdi: name, rsi: argv, rdx: envp
- *
- * We want to fallback into:
- *	extern long sys_execve(const char *name, char **argv,char **envp, struct pt_regs *regs)
- *
- * do_sys_execve asm fallback arguments:
- *	rdi: name, rsi: argv, rdx: envp, rcx: fake frame on the stack
- */
-ENTRY(kernel_execve)
-	CFI_STARTPROC
-	FAKE_STACK_FRAME $0
-	SAVE_ALL
-	movq %rsp,%rcx
-	call sys_execve
-	movq %rax, RAX(%rsp)
-	RESTORE_REST
-	testq %rax,%rax
-	je int_ret_from_sys_call
-	RESTORE_ARGS
-	UNFAKE_STACK_FRAME
-	ret
-	CFI_ENDPROC
-END(kernel_execve)
+ENTRY(ret_from_kernel_execve)
+	movq %rdi, %rsp
+	movl $0, RAX(%rsp)
+	// RESTORE_REST
+	movq 0*8(%rsp), %r15
+	movq 1*8(%rsp), %r14
+	movq 2*8(%rsp), %r13
+	movq 3*8(%rsp), %r12
+	movq 4*8(%rsp), %rbp
+	movq 5*8(%rsp), %rbx
+	addq $(6*8), %rsp
+	jmp int_ret_from_sys_call
+END(ret_from_kernel_execve)
 
 /* Call softirq on interrupt stack. Interrupts are off. */
 ENTRY(call_softirq)
diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c
index c3a7cb4..1d41402 100644
--- a/arch/x86/kernel/ftrace.c
+++ b/arch/x86/kernel/ftrace.c
@@ -206,6 +206,21 @@ static int
 ftrace_modify_code(unsigned long ip, unsigned const char *old_code,
 		   unsigned const char *new_code);
 
+/*
+ * Should never be called:
+ *  As it is only called by __ftrace_replace_code() which is called by
+ *  ftrace_replace_code() that x86 overrides, and by ftrace_update_code()
+ *  which is called to turn mcount into nops or nops into function calls
+ *  but not to convert a function from not using regs to one that uses
+ *  regs, which ftrace_modify_call() is for.
+ */
+int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,
+				 unsigned long addr)
+{
+	WARN_ON(1);
+	return -EINVAL;
+}
+
 int ftrace_update_ftrace_func(ftrace_func_t func)
 {
 	unsigned long ip = (unsigned long)(&ftrace_call);
@@ -220,6 +235,14 @@ int ftrace_update_ftrace_func(ftrace_func_t func)
 
 	ret = ftrace_modify_code(ip, old, new);
 
+	/* Also update the regs callback function */
+	if (!ret) {
+		ip = (unsigned long)(&ftrace_regs_call);
+		memcpy(old, &ftrace_regs_call, MCOUNT_INSN_SIZE);
+		new = ftrace_call_replace(ip, (unsigned long)func);
+		ret = ftrace_modify_code(ip, old, new);
+	}
+
 	atomic_dec(&modifying_ftrace_code);
 
 	return ret;
@@ -299,6 +322,32 @@ static int add_brk_on_nop(struct dyn_ftrace *rec)
 	return add_break(rec->ip, old);
 }
 
+/*
+ * If the record has the FTRACE_FL_REGS set, that means that it
+ * wants to convert to a callback that saves all regs. If FTRACE_FL_REGS
+ * is not not set, then it wants to convert to the normal callback.
+ */
+static unsigned long get_ftrace_addr(struct dyn_ftrace *rec)
+{
+	if (rec->flags & FTRACE_FL_REGS)
+		return (unsigned long)FTRACE_REGS_ADDR;
+	else
+		return (unsigned long)FTRACE_ADDR;
+}
+
+/*
+ * The FTRACE_FL_REGS_EN is set when the record already points to
+ * a function that saves all the regs. Basically the '_EN' version
+ * represents the current state of the function.
+ */
+static unsigned long get_ftrace_old_addr(struct dyn_ftrace *rec)
+{
+	if (rec->flags & FTRACE_FL_REGS_EN)
+		return (unsigned long)FTRACE_REGS_ADDR;
+	else
+		return (unsigned long)FTRACE_ADDR;
+}
+
 static int add_breakpoints(struct dyn_ftrace *rec, int enable)
 {
 	unsigned long ftrace_addr;
@@ -306,7 +355,7 @@ static int add_breakpoints(struct dyn_ftrace *rec, int enable)
 
 	ret = ftrace_test_record(rec, enable);
 
-	ftrace_addr = (unsigned long)FTRACE_ADDR;
+	ftrace_addr = get_ftrace_addr(rec);
 
 	switch (ret) {
 	case FTRACE_UPDATE_IGNORE:
@@ -316,6 +365,10 @@ static int add_breakpoints(struct dyn_ftrace *rec, int enable)
 		/* converting nop to call */
 		return add_brk_on_nop(rec);
 
+	case FTRACE_UPDATE_MODIFY_CALL_REGS:
+	case FTRACE_UPDATE_MODIFY_CALL:
+		ftrace_addr = get_ftrace_old_addr(rec);
+		/* fall through */
 	case FTRACE_UPDATE_MAKE_NOP:
 		/* converting a call to a nop */
 		return add_brk_on_call(rec, ftrace_addr);
@@ -360,13 +413,21 @@ static int remove_breakpoint(struct dyn_ftrace *rec)
 		 * If not, don't touch the breakpoint, we make just create
 		 * a disaster.
 		 */
-		ftrace_addr = (unsigned long)FTRACE_ADDR;
+		ftrace_addr = get_ftrace_addr(rec);
+		nop = ftrace_call_replace(ip, ftrace_addr);
+
+		if (memcmp(&ins[1], &nop[1], MCOUNT_INSN_SIZE - 1) == 0)
+			goto update;
+
+		/* Check both ftrace_addr and ftrace_old_addr */
+		ftrace_addr = get_ftrace_old_addr(rec);
 		nop = ftrace_call_replace(ip, ftrace_addr);
 
 		if (memcmp(&ins[1], &nop[1], MCOUNT_INSN_SIZE - 1) != 0)
 			return -EINVAL;
 	}
 
+ update:
 	return probe_kernel_write((void *)ip, &nop[0], 1);
 }
 
@@ -405,12 +466,14 @@ static int add_update(struct dyn_ftrace *rec, int enable)
 
 	ret = ftrace_test_record(rec, enable);
 
-	ftrace_addr = (unsigned long)FTRACE_ADDR;
+	ftrace_addr  = get_ftrace_addr(rec);
 
 	switch (ret) {
 	case FTRACE_UPDATE_IGNORE:
 		return 0;
 
+	case FTRACE_UPDATE_MODIFY_CALL_REGS:
+	case FTRACE_UPDATE_MODIFY_CALL:
 	case FTRACE_UPDATE_MAKE_CALL:
 		/* converting nop to call */
 		return add_update_call(rec, ftrace_addr);
@@ -455,12 +518,14 @@ static int finish_update(struct dyn_ftrace *rec, int enable)
 
 	ret = ftrace_update_record(rec, enable);
 
-	ftrace_addr = (unsigned long)FTRACE_ADDR;
+	ftrace_addr = get_ftrace_addr(rec);
 
 	switch (ret) {
 	case FTRACE_UPDATE_IGNORE:
 		return 0;
 
+	case FTRACE_UPDATE_MODIFY_CALL_REGS:
+	case FTRACE_UPDATE_MODIFY_CALL:
 	case FTRACE_UPDATE_MAKE_CALL:
 		/* converting nop to call */
 		return finish_update_call(rec, ftrace_addr);
diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c
index f250431..675a050 100644
--- a/arch/x86/kernel/i387.c
+++ b/arch/x86/kernel/i387.c
@@ -19,24 +19,17 @@
 #include <asm/fpu-internal.h>
 #include <asm/user.h>
 
-#ifdef CONFIG_X86_64
-# include <asm/sigcontext32.h>
-# include <asm/user32.h>
-#else
-# define save_i387_xstate_ia32		save_i387_xstate
-# define restore_i387_xstate_ia32	restore_i387_xstate
-# define _fpstate_ia32		_fpstate
-# define _xstate_ia32		_xstate
-# define sig_xstate_ia32_size   sig_xstate_size
-# define fx_sw_reserved_ia32	fx_sw_reserved
-# define user_i387_ia32_struct	user_i387_struct
-# define user32_fxsr_struct	user_fxsr_struct
-#endif
-
 /*
  * Were we in an interrupt that interrupted kernel mode?
  *
- * We can do a kernel_fpu_begin/end() pair *ONLY* if that
+ * For now, with eagerfpu we will return interrupted kernel FPU
+ * state as not-idle. TBD: Ideally we can change the return value
+ * to something like __thread_has_fpu(current). But we need to
+ * be careful of doing __thread_clear_has_fpu() before saving
+ * the FPU etc for supporting nested uses etc. For now, take
+ * the simple route!
+ *
+ * On others, we can do a kernel_fpu_begin/end() pair *ONLY* if that
  * pair does nothing at all: the thread must not have fpu (so
  * that we don't try to save the FPU state), and TS must
  * be set (so that the clts/stts pair does nothing that is
@@ -44,6 +37,9 @@
  */
 static inline bool interrupted_kernel_fpu_idle(void)
 {
+	if (use_eager_fpu())
+		return 0;
+
 	return !__thread_has_fpu(current) &&
 		(read_cr0() & X86_CR0_TS);
 }
@@ -77,29 +73,29 @@ bool irq_fpu_usable(void)
 }
 EXPORT_SYMBOL(irq_fpu_usable);
 
-void kernel_fpu_begin(void)
+void __kernel_fpu_begin(void)
 {
 	struct task_struct *me = current;
 
-	WARN_ON_ONCE(!irq_fpu_usable());
-	preempt_disable();
 	if (__thread_has_fpu(me)) {
 		__save_init_fpu(me);
 		__thread_clear_has_fpu(me);
-		/* We do 'stts()' in kernel_fpu_end() */
-	} else {
+		/* We do 'stts()' in __kernel_fpu_end() */
+	} else if (!use_eager_fpu()) {
 		this_cpu_write(fpu_owner_task, NULL);
 		clts();
 	}
 }
-EXPORT_SYMBOL(kernel_fpu_begin);
+EXPORT_SYMBOL(__kernel_fpu_begin);
 
-void kernel_fpu_end(void)
+void __kernel_fpu_end(void)
 {
-	stts();
-	preempt_enable();
+	if (use_eager_fpu())
+		math_state_restore();
+	else
+		stts();
 }
-EXPORT_SYMBOL(kernel_fpu_end);
+EXPORT_SYMBOL(__kernel_fpu_end);
 
 void unlazy_fpu(struct task_struct *tsk)
 {
@@ -113,23 +109,15 @@ void unlazy_fpu(struct task_struct *tsk)
 }
 EXPORT_SYMBOL(unlazy_fpu);
 
-#ifdef CONFIG_MATH_EMULATION
-# define HAVE_HWFP		(boot_cpu_data.hard_math)
-#else
-# define HAVE_HWFP		1
-#endif
-
-static unsigned int		mxcsr_feature_mask __read_mostly = 0xffffffffu;
+unsigned int mxcsr_feature_mask __read_mostly = 0xffffffffu;
 unsigned int xstate_size;
 EXPORT_SYMBOL_GPL(xstate_size);
-unsigned int sig_xstate_ia32_size = sizeof(struct _fpstate_ia32);
 static struct i387_fxsave_struct fx_scratch __cpuinitdata;
 
 static void __cpuinit mxcsr_feature_mask_init(void)
 {
 	unsigned long mask = 0;
 
-	clts();
 	if (cpu_has_fxsr) {
 		memset(&fx_scratch, 0, sizeof(struct i387_fxsave_struct));
 		asm volatile("fxsave %0" : : "m" (fx_scratch));
@@ -138,7 +126,6 @@ static void __cpuinit mxcsr_feature_mask_init(void)
 			mask = 0x0000ffbf;
 	}
 	mxcsr_feature_mask &= mask;
-	stts();
 }
 
 static void __cpuinit init_thread_xstate(void)
@@ -192,9 +179,8 @@ void __cpuinit fpu_init(void)
 		init_thread_xstate();
 
 	mxcsr_feature_mask_init();
-	/* clean state in init */
-	current_thread_info()->status = 0;
-	clear_used_math();
+	xsave_init();
+	eager_fpu_init();
 }
 
 void fpu_finit(struct fpu *fpu)
@@ -205,12 +191,7 @@ void fpu_finit(struct fpu *fpu)
 	}
 
 	if (cpu_has_fxsr) {
-		struct i387_fxsave_struct *fx = &fpu->state->fxsave;
-
-		memset(fx, 0, xstate_size);
-		fx->cwd = 0x37f;
-		if (cpu_has_xmm)
-			fx->mxcsr = MXCSR_DEFAULT;
+		fx_finit(&fpu->state->fxsave);
 	} else {
 		struct i387_fsave_struct *fp = &fpu->state->fsave;
 		memset(fp, 0, xstate_size);
@@ -454,7 +435,7 @@ static inline u32 twd_fxsr_to_i387(struct i387_fxsave_struct *fxsave)
  * FXSR floating point environment conversions.
  */
 
-static void
+void
 convert_from_fxsr(struct user_i387_ia32_struct *env, struct task_struct *tsk)
 {
 	struct i387_fxsave_struct *fxsave = &tsk->thread.fpu.state->fxsave;
@@ -491,8 +472,8 @@ convert_from_fxsr(struct user_i387_ia32_struct *env, struct task_struct *tsk)
 		memcpy(&to[i], &from[i], sizeof(to[0]));
 }
 
-static void convert_to_fxsr(struct task_struct *tsk,
-			    const struct user_i387_ia32_struct *env)
+void convert_to_fxsr(struct task_struct *tsk,
+		     const struct user_i387_ia32_struct *env)
 
 {
 	struct i387_fxsave_struct *fxsave = &tsk->thread.fpu.state->fxsave;
@@ -589,223 +570,6 @@ int fpregs_set(struct task_struct *target, const struct user_regset *regset,
 }
 
 /*
- * Signal frame handlers.
- */
-
-static inline int save_i387_fsave(struct _fpstate_ia32 __user *buf)
-{
-	struct task_struct *tsk = current;
-	struct i387_fsave_struct *fp = &tsk->thread.fpu.state->fsave;
-
-	fp->status = fp->swd;
-	if (__copy_to_user(buf, fp, sizeof(struct i387_fsave_struct)))
-		return -1;
-	return 1;
-}
-
-static int save_i387_fxsave(struct _fpstate_ia32 __user *buf)
-{
-	struct task_struct *tsk = current;
-	struct i387_fxsave_struct *fx = &tsk->thread.fpu.state->fxsave;
-	struct user_i387_ia32_struct env;
-	int err = 0;
-
-	convert_from_fxsr(&env, tsk);
-	if (__copy_to_user(buf, &env, sizeof(env)))
-		return -1;
-
-	err |= __put_user(fx->swd, &buf->status);
-	err |= __put_user(X86_FXSR_MAGIC, &buf->magic);
-	if (err)
-		return -1;
-
-	if (__copy_to_user(&buf->_fxsr_env[0], fx, xstate_size))
-		return -1;
-	return 1;
-}
-
-static int save_i387_xsave(void __user *buf)
-{
-	struct task_struct *tsk = current;
-	struct _fpstate_ia32 __user *fx = buf;
-	int err = 0;
-
-
-	sanitize_i387_state(tsk);
-
-	/*
-	 * For legacy compatible, we always set FP/SSE bits in the bit
-	 * vector while saving the state to the user context.
-	 * This will enable us capturing any changes(during sigreturn) to
-	 * the FP/SSE bits by the legacy applications which don't touch
-	 * xstate_bv in the xsave header.
-	 *
-	 * xsave aware applications can change the xstate_bv in the xsave
-	 * header as well as change any contents in the memory layout.
-	 * xrestore as part of sigreturn will capture all the changes.
-	 */
-	tsk->thread.fpu.state->xsave.xsave_hdr.xstate_bv |= XSTATE_FPSSE;
-
-	if (save_i387_fxsave(fx) < 0)
-		return -1;
-
-	err = __copy_to_user(&fx->sw_reserved, &fx_sw_reserved_ia32,
-			     sizeof(struct _fpx_sw_bytes));
-	err |= __put_user(FP_XSTATE_MAGIC2,
-			  (__u32 __user *) (buf + sig_xstate_ia32_size
-					    - FP_XSTATE_MAGIC2_SIZE));
-	if (err)
-		return -1;
-
-	return 1;
-}
-
-int save_i387_xstate_ia32(void __user *buf)
-{
-	struct _fpstate_ia32 __user *fp = (struct _fpstate_ia32 __user *) buf;
-	struct task_struct *tsk = current;
-
-	if (!used_math())
-		return 0;
-
-	if (!access_ok(VERIFY_WRITE, buf, sig_xstate_ia32_size))
-		return -EACCES;
-	/*
-	 * This will cause a "finit" to be triggered by the next
-	 * attempted FPU operation by the 'current' process.
-	 */
-	clear_used_math();
-
-	if (!HAVE_HWFP) {
-		return fpregs_soft_get(current, NULL,
-				       0, sizeof(struct user_i387_ia32_struct),
-				       NULL, fp) ? -1 : 1;
-	}
-
-	unlazy_fpu(tsk);
-
-	if (cpu_has_xsave)
-		return save_i387_xsave(fp);
-	if (cpu_has_fxsr)
-		return save_i387_fxsave(fp);
-	else
-		return save_i387_fsave(fp);
-}
-
-static inline int restore_i387_fsave(struct _fpstate_ia32 __user *buf)
-{
-	struct task_struct *tsk = current;
-
-	return __copy_from_user(&tsk->thread.fpu.state->fsave, buf,
-				sizeof(struct i387_fsave_struct));
-}
-
-static int restore_i387_fxsave(struct _fpstate_ia32 __user *buf,
-			       unsigned int size)
-{
-	struct task_struct *tsk = current;
-	struct user_i387_ia32_struct env;
-	int err;
-
-	err = __copy_from_user(&tsk->thread.fpu.state->fxsave, &buf->_fxsr_env[0],
-			       size);
-	/* mxcsr reserved bits must be masked to zero for security reasons */
-	tsk->thread.fpu.state->fxsave.mxcsr &= mxcsr_feature_mask;
-	if (err || __copy_from_user(&env, buf, sizeof(env)))
-		return 1;
-	convert_to_fxsr(tsk, &env);
-
-	return 0;
-}
-
-static int restore_i387_xsave(void __user *buf)
-{
-	struct _fpx_sw_bytes fx_sw_user;
-	struct _fpstate_ia32 __user *fx_user =
-			((struct _fpstate_ia32 __user *) buf);
-	struct i387_fxsave_struct __user *fx =
-		(struct i387_fxsave_struct __user *) &fx_user->_fxsr_env[0];
-	struct xsave_hdr_struct *xsave_hdr =
-				&current->thread.fpu.state->xsave.xsave_hdr;
-	u64 mask;
-	int err;
-
-	if (check_for_xstate(fx, buf, &fx_sw_user))
-		goto fx_only;
-
-	mask = fx_sw_user.xstate_bv;
-
-	err = restore_i387_fxsave(buf, fx_sw_user.xstate_size);
-
-	xsave_hdr->xstate_bv &= pcntxt_mask;
-	/*
-	 * These bits must be zero.
-	 */
-	xsave_hdr->reserved1[0] = xsave_hdr->reserved1[1] = 0;
-
-	/*
-	 * Init the state that is not present in the memory layout
-	 * and enabled by the OS.
-	 */
-	mask = ~(pcntxt_mask & ~mask);
-	xsave_hdr->xstate_bv &= mask;
-
-	return err;
-fx_only:
-	/*
-	 * Couldn't find the extended state information in the memory
-	 * layout. Restore the FP/SSE and init the other extended state
-	 * enabled by the OS.
-	 */
-	xsave_hdr->xstate_bv = XSTATE_FPSSE;
-	return restore_i387_fxsave(buf, sizeof(struct i387_fxsave_struct));
-}
-
-int restore_i387_xstate_ia32(void __user *buf)
-{
-	int err;
-	struct task_struct *tsk = current;
-	struct _fpstate_ia32 __user *fp = (struct _fpstate_ia32 __user *) buf;
-
-	if (HAVE_HWFP)
-		clear_fpu(tsk);
-
-	if (!buf) {
-		if (used_math()) {
-			clear_fpu(tsk);
-			clear_used_math();
-		}
-
-		return 0;
-	} else
-		if (!access_ok(VERIFY_READ, buf, sig_xstate_ia32_size))
-			return -EACCES;
-
-	if (!used_math()) {
-		err = init_fpu(tsk);
-		if (err)
-			return err;
-	}
-
-	if (HAVE_HWFP) {
-		if (cpu_has_xsave)
-			err = restore_i387_xsave(buf);
-		else if (cpu_has_fxsr)
-			err = restore_i387_fxsave(fp, sizeof(struct
-							   i387_fxsave_struct));
-		else
-			err = restore_i387_fsave(fp);
-	} else {
-		err = fpregs_soft_set(current, NULL,
-				      0, sizeof(struct user_i387_ia32_struct),
-				      NULL, fp) != 0;
-	}
-	set_used_math();
-
-	return err;
-}
-
-/*
  * FPU state for core dumps.
  * This is only used for a.out dumps now.
  * It is declared generically using elf_fpregset_t (which is
diff --git a/arch/x86/kernel/i8259.c b/arch/x86/kernel/i8259.c
index 36d1853..9a5c460 100644
--- a/arch/x86/kernel/i8259.c
+++ b/arch/x86/kernel/i8259.c
@@ -263,7 +263,7 @@ static void i8259A_shutdown(void)
 	 * out of.
 	 */
 	outb(0xff, PIC_MASTER_IMR);	/* mask all of 8259A-1 */
-	outb(0xff, PIC_SLAVE_IMR);	/* mask all of 8259A-1 */
+	outb(0xff, PIC_SLAVE_IMR);	/* mask all of 8259A-2 */
 }
 
 static struct syscore_ops i8259_syscore_ops = {
diff --git a/arch/x86/kernel/kgdb.c b/arch/x86/kernel/kgdb.c
index 3f61904..836f832 100644
--- a/arch/x86/kernel/kgdb.c
+++ b/arch/x86/kernel/kgdb.c
@@ -746,7 +746,9 @@ void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long ip)
 int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt)
 {
 	int err;
+#ifdef CONFIG_DEBUG_RODATA
 	char opc[BREAK_INSTR_SIZE];
+#endif /* CONFIG_DEBUG_RODATA */
 
 	bpt->type = BP_BREAKPOINT;
 	err = probe_kernel_read(bpt->saved_instr, (char *)bpt->bpt_addr,
diff --git a/arch/x86/kernel/kprobes.c b/arch/x86/kernel/kprobes.c
index e2f751e..57916c0 100644
--- a/arch/x86/kernel/kprobes.c
+++ b/arch/x86/kernel/kprobes.c
@@ -541,6 +541,23 @@ reenter_kprobe(struct kprobe *p, struct pt_regs *regs, struct kprobe_ctlblk *kcb
 	return 1;
 }
 
+#ifdef KPROBES_CAN_USE_FTRACE
+static void __kprobes skip_singlestep(struct kprobe *p, struct pt_regs *regs,
+				      struct kprobe_ctlblk *kcb)
+{
+	/*
+	 * Emulate singlestep (and also recover regs->ip)
+	 * as if there is a 5byte nop
+	 */
+	regs->ip = (unsigned long)p->addr + MCOUNT_INSN_SIZE;
+	if (unlikely(p->post_handler)) {
+		kcb->kprobe_status = KPROBE_HIT_SSDONE;
+		p->post_handler(p, regs, 0);
+	}
+	__this_cpu_write(current_kprobe, NULL);
+}
+#endif
+
 /*
  * Interrupts are disabled on entry as trap3 is an interrupt gate and they
  * remain disabled throughout this function.
@@ -599,6 +616,12 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
 	} else if (kprobe_running()) {
 		p = __this_cpu_read(current_kprobe);
 		if (p->break_handler && p->break_handler(p, regs)) {
+#ifdef KPROBES_CAN_USE_FTRACE
+			if (kprobe_ftrace(p)) {
+				skip_singlestep(p, regs, kcb);
+				return 1;
+			}
+#endif
 			setup_singlestep(p, regs, kcb, 0);
 			return 1;
 		}
@@ -1052,6 +1075,50 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
 	return 0;
 }
 
+#ifdef KPROBES_CAN_USE_FTRACE
+/* Ftrace callback handler for kprobes */
+void __kprobes kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
+				     struct ftrace_ops *ops, struct pt_regs *regs)
+{
+	struct kprobe *p;
+	struct kprobe_ctlblk *kcb;
+	unsigned long flags;
+
+	/* Disable irq for emulating a breakpoint and avoiding preempt */
+	local_irq_save(flags);
+
+	p = get_kprobe((kprobe_opcode_t *)ip);
+	if (unlikely(!p) || kprobe_disabled(p))
+		goto end;
+
+	kcb = get_kprobe_ctlblk();
+	if (kprobe_running()) {
+		kprobes_inc_nmissed_count(p);
+	} else {
+		/* Kprobe handler expects regs->ip = ip + 1 as breakpoint hit */
+		regs->ip = ip + sizeof(kprobe_opcode_t);
+
+		__this_cpu_write(current_kprobe, p);
+		kcb->kprobe_status = KPROBE_HIT_ACTIVE;
+		if (!p->pre_handler || !p->pre_handler(p, regs))
+			skip_singlestep(p, regs, kcb);
+		/*
+		 * If pre_handler returns !0, it sets regs->ip and
+		 * resets current kprobe.
+		 */
+	}
+end:
+	local_irq_restore(flags);
+}
+
+int __kprobes arch_prepare_kprobe_ftrace(struct kprobe *p)
+{
+	p->ainsn.insn = NULL;
+	p->ainsn.boostable = -1;
+	return 0;
+}
+#endif
+
 int __init arch_init_kprobes(void)
 {
 	return arch_init_optprobes();
diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c
index c1d61ee..b3e5e51 100644
--- a/arch/x86/kernel/kvm.c
+++ b/arch/x86/kernel/kvm.c
@@ -354,6 +354,7 @@ static void kvm_pv_guest_cpu_reboot(void *unused)
 	if (kvm_para_has_feature(KVM_FEATURE_PV_EOI))
 		wrmsrl(MSR_KVM_PV_EOI_EN, 0);
 	kvm_pv_disable_apf();
+	kvm_disable_steal_time();
 }
 
 static int kvm_pv_reboot_notify(struct notifier_block *nb,
@@ -396,9 +397,7 @@ void kvm_disable_steal_time(void)
 #ifdef CONFIG_SMP
 static void __init kvm_smp_prepare_boot_cpu(void)
 {
-#ifdef CONFIG_KVM_CLOCK
 	WARN_ON(kvm_register_clock("primary cpu clock"));
-#endif
 	kvm_guest_cpu_init();
 	native_smp_prepare_boot_cpu();
 }
diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c
index 82746f9..7720ff5 100644
--- a/arch/x86/kernel/microcode_amd.c
+++ b/arch/x86/kernel/microcode_amd.c
@@ -75,20 +75,113 @@ struct microcode_amd {
 
 static struct equiv_cpu_entry *equiv_cpu_table;
 
-/* page-sized ucode patch buffer */
-void *patch;
+struct ucode_patch {
+	struct list_head plist;
+	void *data;
+	u32 patch_id;
+	u16 equiv_cpu;
+};
+
+static LIST_HEAD(pcache);
+
+static u16 find_equiv_id(unsigned int cpu)
+{
+	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
+	int i = 0;
+
+	if (!equiv_cpu_table)
+		return 0;
+
+	while (equiv_cpu_table[i].installed_cpu != 0) {
+		if (uci->cpu_sig.sig == equiv_cpu_table[i].installed_cpu)
+			return equiv_cpu_table[i].equiv_cpu;
+
+		i++;
+	}
+	return 0;
+}
+
+static u32 find_cpu_family_by_equiv_cpu(u16 equiv_cpu)
+{
+	int i = 0;
+
+	BUG_ON(!equiv_cpu_table);
+
+	while (equiv_cpu_table[i].equiv_cpu != 0) {
+		if (equiv_cpu == equiv_cpu_table[i].equiv_cpu)
+			return equiv_cpu_table[i].installed_cpu;
+		i++;
+	}
+	return 0;
+}
+
+/*
+ * a small, trivial cache of per-family ucode patches
+ */
+static struct ucode_patch *cache_find_patch(u16 equiv_cpu)
+{
+	struct ucode_patch *p;
+
+	list_for_each_entry(p, &pcache, plist)
+		if (p->equiv_cpu == equiv_cpu)
+			return p;
+	return NULL;
+}
+
+static void update_cache(struct ucode_patch *new_patch)
+{
+	struct ucode_patch *p;
+
+	list_for_each_entry(p, &pcache, plist) {
+		if (p->equiv_cpu == new_patch->equiv_cpu) {
+			if (p->patch_id >= new_patch->patch_id)
+				/* we already have the latest patch */
+				return;
+
+			list_replace(&p->plist, &new_patch->plist);
+			kfree(p->data);
+			kfree(p);
+			return;
+		}
+	}
+	/* no patch found, add it */
+	list_add_tail(&new_patch->plist, &pcache);
+}
+
+static void free_cache(void)
+{
+	struct ucode_patch *p, *tmp;
+
+	list_for_each_entry_safe(p, tmp, &pcache, plist) {
+		__list_del(p->plist.prev, p->plist.next);
+		kfree(p->data);
+		kfree(p);
+	}
+}
+
+static struct ucode_patch *find_patch(unsigned int cpu)
+{
+	u16 equiv_id;
+
+	equiv_id = find_equiv_id(cpu);
+	if (!equiv_id)
+		return NULL;
+
+	return cache_find_patch(equiv_id);
+}
 
 static int collect_cpu_info_amd(int cpu, struct cpu_signature *csig)
 {
 	struct cpuinfo_x86 *c = &cpu_data(cpu);
 
+	csig->sig = cpuid_eax(0x00000001);
 	csig->rev = c->microcode;
 	pr_info("CPU%d: patch_level=0x%08x\n", cpu, csig->rev);
 
 	return 0;
 }
 
-static unsigned int verify_ucode_size(int cpu, u32 patch_size,
+static unsigned int verify_patch_size(int cpu, u32 patch_size,
 				      unsigned int size)
 {
 	struct cpuinfo_x86 *c = &cpu_data(cpu);
@@ -118,95 +211,37 @@ static unsigned int verify_ucode_size(int cpu, u32 patch_size,
 	return patch_size;
 }
 
-static u16 find_equiv_id(void)
+static int apply_microcode_amd(int cpu)
 {
-	unsigned int current_cpu_id, i = 0;
-
-	BUG_ON(equiv_cpu_table == NULL);
-
-	current_cpu_id = cpuid_eax(0x00000001);
-
-	while (equiv_cpu_table[i].installed_cpu != 0) {
-		if (current_cpu_id == equiv_cpu_table[i].installed_cpu)
-			return equiv_cpu_table[i].equiv_cpu;
-
-		i++;
-	}
-	return 0;
-}
+	struct cpuinfo_x86 *c = &cpu_data(cpu);
+	struct microcode_amd *mc_amd;
+	struct ucode_cpu_info *uci;
+	struct ucode_patch *p;
+	u32 rev, dummy;
 
-/*
- * we signal a good patch is found by returning its size > 0
- */
-static int get_matching_microcode(int cpu, const u8 *ucode_ptr,
-				  unsigned int leftover_size, int rev,
-				  unsigned int *current_size)
-{
-	struct microcode_header_amd *mc_hdr;
-	unsigned int actual_size, patch_size;
-	u16 equiv_cpu_id;
+	BUG_ON(raw_smp_processor_id() != cpu);
 
-	/* size of the current patch we're staring at */
-	patch_size = *(u32 *)(ucode_ptr + 4);
-	*current_size = patch_size + SECTION_HDR_SIZE;
+	uci = ucode_cpu_info + cpu;
 
-	equiv_cpu_id = find_equiv_id();
-	if (!equiv_cpu_id)
+	p = find_patch(cpu);
+	if (!p)
 		return 0;
 
-	/*
-	 * let's look at the patch header itself now
-	 */
-	mc_hdr = (struct microcode_header_amd *)(ucode_ptr + SECTION_HDR_SIZE);
+	mc_amd  = p->data;
+	uci->mc = p->data;
 
-	if (mc_hdr->processor_rev_id != equiv_cpu_id)
-		return 0;
+	rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);
 
-	/* ucode might be chipset specific -- currently we don't support this */
-	if (mc_hdr->nb_dev_id || mc_hdr->sb_dev_id) {
-		pr_err("CPU%d: chipset specific code not yet supported\n",
-		       cpu);
+	/* need to apply patch? */
+	if (rev >= mc_amd->hdr.patch_id) {
+		c->microcode = rev;
 		return 0;
 	}
 
-	if (mc_hdr->patch_id <= rev)
-		return 0;
-
-	/*
-	 * now that the header looks sane, verify its size
-	 */
-	actual_size = verify_ucode_size(cpu, patch_size, leftover_size);
-	if (!actual_size)
-		return 0;
-
-	/* clear the patch buffer */
-	memset(patch, 0, PAGE_SIZE);
-
-	/* all looks ok, get the binary patch */
-	get_ucode_data(patch, ucode_ptr + SECTION_HDR_SIZE, actual_size);
-
-	return actual_size;
-}
-
-static int apply_microcode_amd(int cpu)
-{
-	u32 rev, dummy;
-	int cpu_num = raw_smp_processor_id();
-	struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
-	struct microcode_amd *mc_amd = uci->mc;
-	struct cpuinfo_x86 *c = &cpu_data(cpu);
-
-	/* We should bind the task to the CPU */
-	BUG_ON(cpu_num != cpu);
-
-	if (mc_amd == NULL)
-		return 0;
-
 	wrmsrl(MSR_AMD64_PATCH_LOADER, (u64)(long)&mc_amd->hdr.data_code);
-	/* get patch id after patching */
-	rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);
 
-	/* check current patch id and patch's id for match */
+	/* verify patch application was successful */
+	rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);
 	if (rev != mc_amd->hdr.patch_id) {
 		pr_err("CPU%d: update failed for patch_level=0x%08x\n",
 		       cpu, mc_amd->hdr.patch_id);
@@ -238,7 +273,7 @@ static int install_equiv_cpu_table(const u8 *buf)
 		return -ENOMEM;
 	}
 
-	get_ucode_data(equiv_cpu_table, buf + CONTAINER_HDR_SZ, size);
+	memcpy(equiv_cpu_table, buf + CONTAINER_HDR_SZ, size);
 
 	/* add header length */
 	return size + CONTAINER_HDR_SZ;
@@ -250,61 +285,113 @@ static void free_equiv_cpu_table(void)
 	equiv_cpu_table = NULL;
 }
 
-static enum ucode_state
-generic_load_microcode(int cpu, const u8 *data, size_t size)
+static void cleanup(void)
 {
-	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
-	struct microcode_header_amd *mc_hdr = NULL;
-	unsigned int mc_size, leftover, current_size = 0;
+	free_equiv_cpu_table();
+	free_cache();
+}
+
+/*
+ * We return the current size even if some of the checks failed so that
+ * we can skip over the next patch. If we return a negative value, we
+ * signal a grave error like a memory allocation has failed and the
+ * driver cannot continue functioning normally. In such cases, we tear
+ * down everything we've used up so far and exit.
+ */
+static int verify_and_add_patch(unsigned int cpu, u8 *fw, unsigned int leftover)
+{
+	struct cpuinfo_x86 *c = &cpu_data(cpu);
+	struct microcode_header_amd *mc_hdr;
+	struct ucode_patch *patch;
+	unsigned int patch_size, crnt_size, ret;
+	u32 proc_fam;
+	u16 proc_id;
+
+	patch_size  = *(u32 *)(fw + 4);
+	crnt_size   = patch_size + SECTION_HDR_SIZE;
+	mc_hdr	    = (struct microcode_header_amd *)(fw + SECTION_HDR_SIZE);
+	proc_id	    = mc_hdr->processor_rev_id;
+
+	proc_fam = find_cpu_family_by_equiv_cpu(proc_id);
+	if (!proc_fam) {
+		pr_err("No patch family for equiv ID: 0x%04x\n", proc_id);
+		return crnt_size;
+	}
+
+	/* check if patch is for the current family */
+	proc_fam = ((proc_fam >> 8) & 0xf) + ((proc_fam >> 20) & 0xff);
+	if (proc_fam != c->x86)
+		return crnt_size;
+
+	if (mc_hdr->nb_dev_id || mc_hdr->sb_dev_id) {
+		pr_err("Patch-ID 0x%08x: chipset-specific code unsupported.\n",
+			mc_hdr->patch_id);
+		return crnt_size;
+	}
+
+	ret = verify_patch_size(cpu, patch_size, leftover);
+	if (!ret) {
+		pr_err("Patch-ID 0x%08x: size mismatch.\n", mc_hdr->patch_id);
+		return crnt_size;
+	}
+
+	patch = kzalloc(sizeof(*patch), GFP_KERNEL);
+	if (!patch) {
+		pr_err("Patch allocation failure.\n");
+		return -EINVAL;
+	}
+
+	patch->data = kzalloc(patch_size, GFP_KERNEL);
+	if (!patch->data) {
+		pr_err("Patch data allocation failure.\n");
+		kfree(patch);
+		return -EINVAL;
+	}
+
+	/* All looks ok, copy patch... */
+	memcpy(patch->data, fw + SECTION_HDR_SIZE, patch_size);
+	INIT_LIST_HEAD(&patch->plist);
+	patch->patch_id  = mc_hdr->patch_id;
+	patch->equiv_cpu = proc_id;
+
+	/* ... and add to cache. */
+	update_cache(patch);
+
+	return crnt_size;
+}
+
+static enum ucode_state load_microcode_amd(int cpu, const u8 *data, size_t size)
+{
+	enum ucode_state ret = UCODE_ERROR;
+	unsigned int leftover;
+	u8 *fw = (u8 *)data;
+	int crnt_size = 0;
 	int offset;
-	const u8 *ucode_ptr = data;
-	void *new_mc = NULL;
-	unsigned int new_rev = uci->cpu_sig.rev;
-	enum ucode_state state = UCODE_ERROR;
 
-	offset = install_equiv_cpu_table(ucode_ptr);
+	offset = install_equiv_cpu_table(data);
 	if (offset < 0) {
 		pr_err("failed to create equivalent cpu table\n");
-		goto out;
+		return ret;
 	}
-	ucode_ptr += offset;
+	fw += offset;
 	leftover = size - offset;
 
-	if (*(u32 *)ucode_ptr != UCODE_UCODE_TYPE) {
+	if (*(u32 *)fw != UCODE_UCODE_TYPE) {
 		pr_err("invalid type field in container file section header\n");
-		goto free_table;
+		free_equiv_cpu_table();
+		return ret;
 	}
 
 	while (leftover) {
-		mc_size = get_matching_microcode(cpu, ucode_ptr, leftover,
-						 new_rev, &current_size);
-		if (mc_size) {
-			mc_hdr  = patch;
-			new_mc  = patch;
-			new_rev = mc_hdr->patch_id;
-			goto out_ok;
-		}
-
-		ucode_ptr += current_size;
-		leftover  -= current_size;
-	}
+		crnt_size = verify_and_add_patch(cpu, fw, leftover);
+		if (crnt_size < 0)
+			return ret;
 
-	if (!new_mc) {
-		state = UCODE_NFOUND;
-		goto free_table;
+		fw	 += crnt_size;
+		leftover -= crnt_size;
 	}
 
-out_ok:
-	uci->mc = new_mc;
-	state = UCODE_OK;
-	pr_debug("CPU%d update ucode (0x%08x -> 0x%08x)\n",
-		 cpu, uci->cpu_sig.rev, new_rev);
-
-free_table:
-	free_equiv_cpu_table();
-
-out:
-	return state;
+	return UCODE_OK;
 }
 
 /*
@@ -315,7 +402,7 @@ out:
  *
  * This legacy file is always smaller than 2K in size.
  *
- * Starting at family 15h they are in family specific firmware files:
+ * Beginning with family 15h, they are in family-specific firmware files:
  *
  *    amd-ucode/microcode_amd_fam15h.bin
  *    amd-ucode/microcode_amd_fam16h.bin
@@ -323,12 +410,17 @@ out:
  *
  * These might be larger than 2K.
  */
-static enum ucode_state request_microcode_amd(int cpu, struct device *device)
+static enum ucode_state request_microcode_amd(int cpu, struct device *device,
+					      bool refresh_fw)
 {
 	char fw_name[36] = "amd-ucode/microcode_amd.bin";
-	const struct firmware *fw;
-	enum ucode_state ret = UCODE_NFOUND;
 	struct cpuinfo_x86 *c = &cpu_data(cpu);
+	enum ucode_state ret = UCODE_NFOUND;
+	const struct firmware *fw;
+
+	/* reload ucode container only on the boot cpu */
+	if (!refresh_fw || c->cpu_index != boot_cpu_data.cpu_index)
+		return UCODE_OK;
 
 	if (c->x86 >= 0x15)
 		snprintf(fw_name, sizeof(fw_name), "amd-ucode/microcode_amd_fam%.2xh.bin", c->x86);
@@ -344,12 +436,17 @@ static enum ucode_state request_microcode_amd(int cpu, struct device *device)
 		goto fw_release;
 	}
 
-	ret = generic_load_microcode(cpu, fw->data, fw->size);
+	/* free old equiv table */
+	free_equiv_cpu_table();
+
+	ret = load_microcode_amd(cpu, fw->data, fw->size);
+	if (ret != UCODE_OK)
+		cleanup();
 
-fw_release:
+ fw_release:
 	release_firmware(fw);
 
-out:
+ out:
 	return ret;
 }
 
@@ -383,14 +480,10 @@ struct microcode_ops * __init init_amd_microcode(void)
 		return NULL;
 	}
 
-	patch = (void *)get_zeroed_page(GFP_KERNEL);
-	if (!patch)
-		return NULL;
-
 	return &microcode_amd_ops;
 }
 
 void __exit exit_amd_microcode(void)
 {
-	free_page((unsigned long)patch);
+	cleanup();
 }
diff --git a/arch/x86/kernel/microcode_core.c b/arch/x86/kernel/microcode_core.c
index 9e5bcf1..3a04b22 100644
--- a/arch/x86/kernel/microcode_core.c
+++ b/arch/x86/kernel/microcode_core.c
@@ -279,19 +279,18 @@ static struct platform_device	*microcode_pdev;
 static int reload_for_cpu(int cpu)
 {
 	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
+	enum ucode_state ustate;
 	int err = 0;
 
-	if (uci->valid) {
-		enum ucode_state ustate;
-
-		ustate = microcode_ops->request_microcode_fw(cpu, &microcode_pdev->dev);
-		if (ustate == UCODE_OK)
-			apply_microcode_on_target(cpu);
-		else
-			if (ustate == UCODE_ERROR)
-				err = -EINVAL;
-	}
+	if (!uci->valid)
+		return err;
 
+	ustate = microcode_ops->request_microcode_fw(cpu, &microcode_pdev->dev, true);
+	if (ustate == UCODE_OK)
+		apply_microcode_on_target(cpu);
+	else
+		if (ustate == UCODE_ERROR)
+			err = -EINVAL;
 	return err;
 }
 
@@ -373,18 +372,15 @@ static void microcode_fini_cpu(int cpu)
 
 static enum ucode_state microcode_resume_cpu(int cpu)
 {
-	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
-
-	if (!uci->mc)
-		return UCODE_NFOUND;
-
 	pr_debug("CPU%d updated upon resume\n", cpu);
-	apply_microcode_on_target(cpu);
+
+	if (apply_microcode_on_target(cpu))
+		return UCODE_ERROR;
 
 	return UCODE_OK;
 }
 
-static enum ucode_state microcode_init_cpu(int cpu)
+static enum ucode_state microcode_init_cpu(int cpu, bool refresh_fw)
 {
 	enum ucode_state ustate;
 
@@ -395,7 +391,8 @@ static enum ucode_state microcode_init_cpu(int cpu)
 	if (system_state != SYSTEM_RUNNING)
 		return UCODE_NFOUND;
 
-	ustate = microcode_ops->request_microcode_fw(cpu, &microcode_pdev->dev);
+	ustate = microcode_ops->request_microcode_fw(cpu, &microcode_pdev->dev,
+						     refresh_fw);
 
 	if (ustate == UCODE_OK) {
 		pr_debug("CPU%d updated upon init\n", cpu);
@@ -408,14 +405,11 @@ static enum ucode_state microcode_init_cpu(int cpu)
 static enum ucode_state microcode_update_cpu(int cpu)
 {
 	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
-	enum ucode_state ustate;
 
 	if (uci->valid)
-		ustate = microcode_resume_cpu(cpu);
-	else
-		ustate = microcode_init_cpu(cpu);
+		return microcode_resume_cpu(cpu);
 
-	return ustate;
+	return microcode_init_cpu(cpu, false);
 }
 
 static int mc_device_add(struct device *dev, struct subsys_interface *sif)
@@ -431,7 +425,7 @@ static int mc_device_add(struct device *dev, struct subsys_interface *sif)
 	if (err)
 		return err;
 
-	if (microcode_init_cpu(cpu) == UCODE_ERROR)
+	if (microcode_init_cpu(cpu, true) == UCODE_ERROR)
 		return -EINVAL;
 
 	return err;
@@ -480,34 +474,41 @@ mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu)
 	struct device *dev;
 
 	dev = get_cpu_device(cpu);
-	switch (action) {
+
+	switch (action & ~CPU_TASKS_FROZEN) {
 	case CPU_ONLINE:
-	case CPU_ONLINE_FROZEN:
 		microcode_update_cpu(cpu);
-	case CPU_DOWN_FAILED:
-	case CPU_DOWN_FAILED_FROZEN:
 		pr_debug("CPU%d added\n", cpu);
+		/*
+		 * "break" is missing on purpose here because we want to fall
+		 * through in order to create the sysfs group.
+		 */
+
+	case CPU_DOWN_FAILED:
 		if (sysfs_create_group(&dev->kobj, &mc_attr_group))
 			pr_err("Failed to create group for CPU%d\n", cpu);
 		break;
+
 	case CPU_DOWN_PREPARE:
-	case CPU_DOWN_PREPARE_FROZEN:
 		/* Suspend is in progress, only remove the interface */
 		sysfs_remove_group(&dev->kobj, &mc_attr_group);
 		pr_debug("CPU%d removed\n", cpu);
 		break;
 
 	/*
+	 * case CPU_DEAD:
+	 *
 	 * When a CPU goes offline, don't free up or invalidate the copy of
 	 * the microcode in kernel memory, so that we can reuse it when the
 	 * CPU comes back online without unnecessarily requesting the userspace
 	 * for it again.
 	 */
-	case CPU_UP_CANCELED_FROZEN:
-		/* The CPU refused to come up during a system resume */
-		microcode_fini_cpu(cpu);
-		break;
 	}
+
+	/* The CPU refused to come up during a system resume */
+	if (action == CPU_UP_CANCELED_FROZEN)
+		microcode_fini_cpu(cpu);
+
 	return NOTIFY_OK;
 }
 
diff --git a/arch/x86/kernel/microcode_intel.c b/arch/x86/kernel/microcode_intel.c
index 0327e2b..3544aed 100644
--- a/arch/x86/kernel/microcode_intel.c
+++ b/arch/x86/kernel/microcode_intel.c
@@ -405,7 +405,8 @@ static int get_ucode_fw(void *to, const void *from, size_t n)
 	return 0;
 }
 
-static enum ucode_state request_microcode_fw(int cpu, struct device *device)
+static enum ucode_state request_microcode_fw(int cpu, struct device *device,
+					     bool refresh_fw)
 {
 	char name[30];
 	struct cpuinfo_x86 *c = &cpu_data(cpu);
diff --git a/arch/x86/kernel/msr.c b/arch/x86/kernel/msr.c
index eb11369..a7c5661 100644
--- a/arch/x86/kernel/msr.c
+++ b/arch/x86/kernel/msr.c
@@ -257,12 +257,14 @@ static int __init msr_init(void)
 		goto out_chrdev;
 	}
 	msr_class->devnode = msr_devnode;
+	get_online_cpus();
 	for_each_online_cpu(i) {
 		err = msr_device_create(i);
 		if (err != 0)
 			goto out_class;
 	}
 	register_hotcpu_notifier(&msr_class_cpu_notifier);
+	put_online_cpus();
 
 	err = 0;
 	goto out;
@@ -271,6 +273,7 @@ out_class:
 	i = 0;
 	for_each_online_cpu(i)
 		msr_device_destroy(i);
+	put_online_cpus();
 	class_destroy(msr_class);
 out_chrdev:
 	__unregister_chrdev(MSR_MAJOR, 0, NR_CPUS, "cpu/msr");
@@ -281,11 +284,13 @@ out:
 static void __exit msr_exit(void)
 {
 	int cpu = 0;
+	get_online_cpus();
 	for_each_online_cpu(cpu)
 		msr_device_destroy(cpu);
 	class_destroy(msr_class);
 	__unregister_chrdev(MSR_MAJOR, 0, NR_CPUS, "cpu/msr");
 	unregister_hotcpu_notifier(&msr_class_cpu_notifier);
+	put_online_cpus();
 }
 
 module_init(msr_init);
diff --git a/arch/x86/kernel/perf_regs.c b/arch/x86/kernel/perf_regs.c
new file mode 100644
index 0000000..e309cc5
--- /dev/null
+++ b/arch/x86/kernel/perf_regs.c
@@ -0,0 +1,105 @@
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/perf_event.h>
+#include <linux/bug.h>
+#include <linux/stddef.h>
+#include <asm/perf_regs.h>
+#include <asm/ptrace.h>
+
+#ifdef CONFIG_X86_32
+#define PERF_REG_X86_MAX PERF_REG_X86_32_MAX
+#else
+#define PERF_REG_X86_MAX PERF_REG_X86_64_MAX
+#endif
+
+#define PT_REGS_OFFSET(id, r) [id] = offsetof(struct pt_regs, r)
+
+static unsigned int pt_regs_offset[PERF_REG_X86_MAX] = {
+	PT_REGS_OFFSET(PERF_REG_X86_AX, ax),
+	PT_REGS_OFFSET(PERF_REG_X86_BX, bx),
+	PT_REGS_OFFSET(PERF_REG_X86_CX, cx),
+	PT_REGS_OFFSET(PERF_REG_X86_DX, dx),
+	PT_REGS_OFFSET(PERF_REG_X86_SI, si),
+	PT_REGS_OFFSET(PERF_REG_X86_DI, di),
+	PT_REGS_OFFSET(PERF_REG_X86_BP, bp),
+	PT_REGS_OFFSET(PERF_REG_X86_SP, sp),
+	PT_REGS_OFFSET(PERF_REG_X86_IP, ip),
+	PT_REGS_OFFSET(PERF_REG_X86_FLAGS, flags),
+	PT_REGS_OFFSET(PERF_REG_X86_CS, cs),
+	PT_REGS_OFFSET(PERF_REG_X86_SS, ss),
+#ifdef CONFIG_X86_32
+	PT_REGS_OFFSET(PERF_REG_X86_DS, ds),
+	PT_REGS_OFFSET(PERF_REG_X86_ES, es),
+	PT_REGS_OFFSET(PERF_REG_X86_FS, fs),
+	PT_REGS_OFFSET(PERF_REG_X86_GS, gs),
+#else
+	/*
+	 * The pt_regs struct does not store
+	 * ds, es, fs, gs in 64 bit mode.
+	 */
+	(unsigned int) -1,
+	(unsigned int) -1,
+	(unsigned int) -1,
+	(unsigned int) -1,
+#endif
+#ifdef CONFIG_X86_64
+	PT_REGS_OFFSET(PERF_REG_X86_R8, r8),
+	PT_REGS_OFFSET(PERF_REG_X86_R9, r9),
+	PT_REGS_OFFSET(PERF_REG_X86_R10, r10),
+	PT_REGS_OFFSET(PERF_REG_X86_R11, r11),
+	PT_REGS_OFFSET(PERF_REG_X86_R12, r12),
+	PT_REGS_OFFSET(PERF_REG_X86_R13, r13),
+	PT_REGS_OFFSET(PERF_REG_X86_R14, r14),
+	PT_REGS_OFFSET(PERF_REG_X86_R15, r15),
+#endif
+};
+
+u64 perf_reg_value(struct pt_regs *regs, int idx)
+{
+	if (WARN_ON_ONCE(idx >= ARRAY_SIZE(pt_regs_offset)))
+		return 0;
+
+	return regs_get_register(regs, pt_regs_offset[idx]);
+}
+
+#define REG_RESERVED (~((1ULL << PERF_REG_X86_MAX) - 1ULL))
+
+#ifdef CONFIG_X86_32
+int perf_reg_validate(u64 mask)
+{
+	if (!mask || mask & REG_RESERVED)
+		return -EINVAL;
+
+	return 0;
+}
+
+u64 perf_reg_abi(struct task_struct *task)
+{
+	return PERF_SAMPLE_REGS_ABI_32;
+}
+#else /* CONFIG_X86_64 */
+#define REG_NOSUPPORT ((1ULL << PERF_REG_X86_DS) | \
+		       (1ULL << PERF_REG_X86_ES) | \
+		       (1ULL << PERF_REG_X86_FS) | \
+		       (1ULL << PERF_REG_X86_GS))
+
+int perf_reg_validate(u64 mask)
+{
+	if (!mask || mask & REG_RESERVED)
+		return -EINVAL;
+
+	if (mask & REG_NOSUPPORT)
+		return -EINVAL;
+
+	return 0;
+}
+
+u64 perf_reg_abi(struct task_struct *task)
+{
+	if (test_tsk_thread_flag(task, TIF_IA32))
+		return PERF_SAMPLE_REGS_ABI_32;
+	else
+		return PERF_SAMPLE_REGS_ABI_64;
+}
+#endif /* CONFIG_X86_32 */
diff --git a/arch/x86/kernel/probe_roms.c b/arch/x86/kernel/probe_roms.c
index 0bc72e2..d5f15c3 100644
--- a/arch/x86/kernel/probe_roms.c
+++ b/arch/x86/kernel/probe_roms.c
@@ -150,7 +150,7 @@ static struct resource *find_oprom(struct pci_dev *pdev)
 	return oprom;
 }
 
-void *pci_map_biosrom(struct pci_dev *pdev)
+void __iomem *pci_map_biosrom(struct pci_dev *pdev)
 {
 	struct resource *oprom = find_oprom(pdev);
 
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index ef6a845..b644e1c 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -66,15 +66,13 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
 {
 	int ret;
 
-	unlazy_fpu(src);
-
 	*dst = *src;
 	if (fpu_allocated(&src->thread.fpu)) {
 		memset(&dst->thread.fpu, 0, sizeof(dst->thread.fpu));
 		ret = fpu_alloc(&dst->thread.fpu);
 		if (ret)
 			return ret;
-		fpu_copy(&dst->thread.fpu, &src->thread.fpu);
+		fpu_copy(dst, src);
 	}
 	return 0;
 }
@@ -97,16 +95,6 @@ void arch_task_cache_init(void)
 				  SLAB_PANIC | SLAB_NOTRACK, NULL);
 }
 
-static inline void drop_fpu(struct task_struct *tsk)
-{
-	/*
-	 * Forget coprocessor state..
-	 */
-	tsk->fpu_counter = 0;
-	clear_fpu(tsk);
-	clear_used_math();
-}
-
 /*
  * Free current thread data structures etc..
  */
@@ -163,7 +151,13 @@ void flush_thread(void)
 
 	flush_ptrace_hw_breakpoint(tsk);
 	memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array));
-	drop_fpu(tsk);
+	drop_init_fpu(tsk);
+	/*
+	 * Free the FPU state for non xsave platforms. They get reallocated
+	 * lazily at the first use.
+	 */
+	if (!use_eager_fpu())
+		free_thread_xstate(tsk);
 }
 
 static void hard_disable_TSC(void)
@@ -299,71 +293,6 @@ sys_clone(unsigned long clone_flags, unsigned long newsp,
 }
 
 /*
- * This gets run with %si containing the
- * function to call, and %di containing
- * the "args".
- */
-extern void kernel_thread_helper(void);
-
-/*
- * Create a kernel thread
- */
-int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
-{
-	struct pt_regs regs;
-
-	memset(&regs, 0, sizeof(regs));
-
-	regs.si = (unsigned long) fn;
-	regs.di = (unsigned long) arg;
-
-#ifdef CONFIG_X86_32
-	regs.ds = __USER_DS;
-	regs.es = __USER_DS;
-	regs.fs = __KERNEL_PERCPU;
-	regs.gs = __KERNEL_STACK_CANARY;
-#else
-	regs.ss = __KERNEL_DS;
-#endif
-
-	regs.orig_ax = -1;
-	regs.ip = (unsigned long) kernel_thread_helper;
-	regs.cs = __KERNEL_CS | get_kernel_rpl();
-	regs.flags = X86_EFLAGS_IF | X86_EFLAGS_BIT1;
-
-	/* Ok, create the new process.. */
-	return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
-}
-EXPORT_SYMBOL(kernel_thread);
-
-/*
- * sys_execve() executes a new program.
- */
-long sys_execve(const char __user *name,
-		const char __user *const __user *argv,
-		const char __user *const __user *envp, struct pt_regs *regs)
-{
-	long error;
-	char *filename;
-
-	filename = getname(name);
-	error = PTR_ERR(filename);
-	if (IS_ERR(filename))
-		return error;
-	error = do_execve(filename, argv, envp, regs);
-
-#ifdef CONFIG_X86_32
-	if (error == 0) {
-		/* Make sure we don't return using sysenter.. */
-                set_thread_flag(TIF_IRET);
-        }
-#endif
-
-	putname(filename);
-	return error;
-}
-
-/*
  * Idle related variables and functions
  */
 unsigned long boot_option_idle_override = IDLE_NO_OVERRIDE;
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c
index 516fa18..44e0bff 100644
--- a/arch/x86/kernel/process_32.c
+++ b/arch/x86/kernel/process_32.c
@@ -57,6 +57,7 @@
 #include <asm/switch_to.h>
 
 asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
+asmlinkage void ret_from_kernel_thread(void) __asm__("ret_from_kernel_thread");
 
 /*
  * Return saved PC of a blocked thread.
@@ -127,23 +128,39 @@ void release_thread(struct task_struct *dead_task)
 }
 
 int copy_thread(unsigned long clone_flags, unsigned long sp,
-	unsigned long unused,
+	unsigned long arg,
 	struct task_struct *p, struct pt_regs *regs)
 {
-	struct pt_regs *childregs;
+	struct pt_regs *childregs = task_pt_regs(p);
 	struct task_struct *tsk;
 	int err;
 
-	childregs = task_pt_regs(p);
+	p->thread.sp = (unsigned long) childregs;
+	p->thread.sp0 = (unsigned long) (childregs+1);
+
+	if (unlikely(!regs)) {
+		/* kernel thread */
+		memset(childregs, 0, sizeof(struct pt_regs));
+		p->thread.ip = (unsigned long) ret_from_kernel_thread;
+		task_user_gs(p) = __KERNEL_STACK_CANARY;
+		childregs->ds = __USER_DS;
+		childregs->es = __USER_DS;
+		childregs->fs = __KERNEL_PERCPU;
+		childregs->bx = sp;	/* function */
+		childregs->bp = arg;
+		childregs->orig_ax = -1;
+		childregs->cs = __KERNEL_CS | get_kernel_rpl();
+		childregs->flags = X86_EFLAGS_IF | X86_EFLAGS_BIT1;
+		p->fpu_counter = 0;
+		p->thread.io_bitmap_ptr = NULL;
+		memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps));
+		return 0;
+	}
 	*childregs = *regs;
 	childregs->ax = 0;
 	childregs->sp = sp;
 
-	p->thread.sp = (unsigned long) childregs;
-	p->thread.sp0 = (unsigned long) (childregs+1);
-
 	p->thread.ip = (unsigned long) ret_from_fork;
-
 	task_user_gs(p) = get_user_gs(regs);
 
 	p->fpu_counter = 0;
@@ -190,10 +207,12 @@ start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp)
 	regs->cs		= __USER_CS;
 	regs->ip		= new_ip;
 	regs->sp		= new_sp;
+	regs->flags		= X86_EFLAGS_IF;
 	/*
-	 * Free the old FP and other extended state
+	 * force it to the iret return path by making it look as if there was
+	 * some work pending.
 	 */
-	free_thread_xstate(current);
+	set_thread_flag(TIF_NOTIFY_RESUME);
 }
 EXPORT_SYMBOL_GPL(start_thread);
 
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index 0a980c9..16c6365 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -146,29 +146,18 @@ static inline u32 read_32bit_tls(struct task_struct *t, int tls)
 }
 
 int copy_thread(unsigned long clone_flags, unsigned long sp,
-		unsigned long unused,
+		unsigned long arg,
 	struct task_struct *p, struct pt_regs *regs)
 {
 	int err;
 	struct pt_regs *childregs;
 	struct task_struct *me = current;
 
-	childregs = ((struct pt_regs *)
-			(THREAD_SIZE + task_stack_page(p))) - 1;
-	*childregs = *regs;
-
-	childregs->ax = 0;
-	if (user_mode(regs))
-		childregs->sp = sp;
-	else
-		childregs->sp = (unsigned long)childregs;
-
+	p->thread.sp0 = (unsigned long)task_stack_page(p) + THREAD_SIZE;
+	childregs = task_pt_regs(p);
 	p->thread.sp = (unsigned long) childregs;
-	p->thread.sp0 = (unsigned long) (childregs+1);
 	p->thread.usersp = me->thread.usersp;
-
 	set_tsk_thread_flag(p, TIF_FORK);
-
 	p->fpu_counter = 0;
 	p->thread.io_bitmap_ptr = NULL;
 
@@ -178,6 +167,24 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
 	p->thread.fs = p->thread.fsindex ? 0 : me->thread.fs;
 	savesegment(es, p->thread.es);
 	savesegment(ds, p->thread.ds);
+	memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps));
+
+	if (unlikely(!regs)) {
+		/* kernel thread */
+		memset(childregs, 0, sizeof(struct pt_regs));
+		childregs->sp = (unsigned long)childregs;
+		childregs->ss = __KERNEL_DS;
+		childregs->bx = sp; /* function */
+		childregs->bp = arg;
+		childregs->orig_ax = -1;
+		childregs->cs = __KERNEL_CS | get_kernel_rpl();
+		childregs->flags = X86_EFLAGS_IF | X86_EFLAGS_BIT1;
+		return 0;
+	}
+	*childregs = *regs;
+
+	childregs->ax = 0;
+	childregs->sp = sp;
 
 	err = -ENOMEM;
 	memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps));
@@ -232,10 +239,6 @@ start_thread_common(struct pt_regs *regs, unsigned long new_ip,
 	regs->cs		= _cs;
 	regs->ss		= _ss;
 	regs->flags		= X86_EFLAGS_IF;
-	/*
-	 * Free the old FP and other extended state
-	 */
-	free_thread_xstate(current);
 }
 
 void
diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c
index c4c6a5c..861a9d1 100644
--- a/arch/x86/kernel/ptrace.c
+++ b/arch/x86/kernel/ptrace.c
@@ -1332,9 +1332,6 @@ static const struct user_regset_view user_x86_64_view = {
 #define genregs32_get		genregs_get
 #define genregs32_set		genregs_set
 
-#define user_i387_ia32_struct	user_i387_struct
-#define user32_fxsr_struct	user_fxsr_struct
-
 #endif	/* CONFIG_X86_64 */
 
 #if defined CONFIG_X86_32 || defined CONFIG_IA32_EMULATION
diff --git a/arch/x86/kernel/rtc.c b/arch/x86/kernel/rtc.c
index af6db6e..4929c1b 100644
--- a/arch/x86/kernel/rtc.c
+++ b/arch/x86/kernel/rtc.c
@@ -225,7 +225,7 @@ static struct platform_device rtc_device = {
 static __init int add_rtc_cmos(void)
 {
 #ifdef CONFIG_PNP
-	static const char *ids[] __initconst =
+	static const char * const  const ids[] __initconst =
 	    { "PNP0b00", "PNP0b01", "PNP0b02", };
 	struct pnp_dev *dev;
 	struct pnp_id *id;
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index f4b9b80..d609be0 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -957,13 +957,11 @@ void __init setup_arch(char **cmdline_p)
 	initmem_init();
 	memblock_find_dma_reserve();
 
-#ifdef CONFIG_KVM_CLOCK
+#ifdef CONFIG_KVM_GUEST
 	kvmclock_init();
 #endif
 
-	x86_init.paging.pagetable_setup_start(swapper_pg_dir);
-	paging_init();
-	x86_init.paging.pagetable_setup_done(swapper_pg_dir);
+	x86_init.paging.pagetable_init();
 
 	if (boot_cpu_data.cpuid_level >= 0) {
 		/* A CPU has %cr4 if and only if it has CPUID */
diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c
index b280908..91bca6d 100644
--- a/arch/x86/kernel/signal.c
+++ b/arch/x86/kernel/signal.c
@@ -114,11 +114,12 @@ int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
 		regs->orig_ax = -1;		/* disable syscall checks */
 
 		get_user_ex(buf, &sc->fpstate);
-		err |= restore_i387_xstate(buf);
 
 		get_user_ex(*pax, &sc->ax);
 	} get_user_catch(err);
 
+	err |= restore_xstate_sig(buf, config_enabled(CONFIG_X86_32));
+
 	return err;
 }
 
@@ -206,35 +207,32 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size,
 	     void __user **fpstate)
 {
 	/* Default to using normal stack */
+	unsigned long math_size = 0;
 	unsigned long sp = regs->sp;
+	unsigned long buf_fx = 0;
 	int onsigstack = on_sig_stack(sp);
 
-#ifdef CONFIG_X86_64
 	/* redzone */
-	sp -= 128;
-#endif /* CONFIG_X86_64 */
+	if (config_enabled(CONFIG_X86_64))
+		sp -= 128;
 
 	if (!onsigstack) {
 		/* This is the X/Open sanctioned signal stack switching.  */
 		if (ka->sa.sa_flags & SA_ONSTACK) {
 			if (current->sas_ss_size)
 				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)
+		} else if (config_enabled(CONFIG_X86_32) &&
+			   (regs->ss & 0xffff) != __USER_DS &&
+			   !(ka->sa.sa_flags & SA_RESTORER) &&
+			   ka->sa.sa_restorer) {
+				/* This is the legacy signal stack switching. */
 				sp = (unsigned long) ka->sa.sa_restorer;
-#endif /* CONFIG_X86_32 */
 		}
 	}
 
 	if (used_math()) {
-		sp -= sig_xstate_size;
-#ifdef CONFIG_X86_64
-		sp = round_down(sp, 64);
-#endif /* CONFIG_X86_64 */
+		sp = alloc_mathframe(sp, config_enabled(CONFIG_X86_32),
+				     &buf_fx, &math_size);
 		*fpstate = (void __user *)sp;
 	}
 
@@ -247,8 +245,9 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size,
 	if (onsigstack && !likely(on_sig_stack(sp)))
 		return (void __user *)-1L;
 
-	/* save i387 state */
-	if (used_math() && save_i387_xstate(*fpstate) < 0)
+	/* save i387 and extended state */
+	if (used_math() &&
+	    save_xstate_sig(*fpstate, (void __user *)buf_fx, math_size) < 0)
 		return (void __user *)-1L;
 
 	return (void __user *)sp;
@@ -357,7 +356,6 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 		put_user_ex(sig, &frame->sig);
 		put_user_ex(&frame->info, &frame->pinfo);
 		put_user_ex(&frame->uc, &frame->puc);
-		err |= copy_siginfo_to_user(&frame->info, info);
 
 		/* Create the ucontext.  */
 		if (cpu_has_xsave)
@@ -369,9 +367,6 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 		put_user_ex(sas_ss_flags(regs->sp),
 			    &frame->uc.uc_stack.ss_flags);
 		put_user_ex(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
-		err |= setup_sigcontext(&frame->uc.uc_mcontext, fpstate,
-					regs, set->sig[0]);
-		err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
 
 		/* Set up to return from userspace.  */
 		restorer = VDSO32_SYMBOL(current->mm->context.vdso, rt_sigreturn);
@@ -388,6 +383,11 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 		 */
 		put_user_ex(*((u64 *)&rt_retcode), (u64 *)frame->retcode);
 	} put_user_catch(err);
+	
+	err |= copy_siginfo_to_user(&frame->info, info);
+	err |= setup_sigcontext(&frame->uc.uc_mcontext, fpstate,
+				regs, set->sig[0]);
+	err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
 
 	if (err)
 		return -EFAULT;
@@ -436,8 +436,6 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 		put_user_ex(sas_ss_flags(regs->sp),
 			    &frame->uc.uc_stack.ss_flags);
 		put_user_ex(me->sas_ss_size, &frame->uc.uc_stack.ss_size);
-		err |= setup_sigcontext(&frame->uc.uc_mcontext, fp, regs, set->sig[0]);
-		err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
 
 		/* Set up to return from userspace.  If provided, use a stub
 		   already in userspace.  */
@@ -450,6 +448,9 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 		}
 	} put_user_catch(err);
 
+	err |= setup_sigcontext(&frame->uc.uc_mcontext, fp, regs, set->sig[0]);
+	err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
+
 	if (err)
 		return -EFAULT;
 
@@ -474,6 +475,75 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 }
 #endif /* CONFIG_X86_32 */
 
+static int x32_setup_rt_frame(int sig, struct k_sigaction *ka,
+			      siginfo_t *info, compat_sigset_t *set,
+			      struct pt_regs *regs)
+{
+#ifdef CONFIG_X86_X32_ABI
+	struct rt_sigframe_x32 __user *frame;
+	void __user *restorer;
+	int err = 0;
+	void __user *fpstate = NULL;
+
+	frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate);
+
+	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
+		return -EFAULT;
+
+	if (ka->sa.sa_flags & SA_SIGINFO) {
+		if (copy_siginfo_to_user32(&frame->info, info))
+			return -EFAULT;
+	}
+
+	put_user_try {
+		/* Create the ucontext.  */
+		if (cpu_has_xsave)
+			put_user_ex(UC_FP_XSTATE, &frame->uc.uc_flags);
+		else
+			put_user_ex(0, &frame->uc.uc_flags);
+		put_user_ex(0, &frame->uc.uc_link);
+		put_user_ex(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
+		put_user_ex(sas_ss_flags(regs->sp),
+			    &frame->uc.uc_stack.ss_flags);
+		put_user_ex(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
+		put_user_ex(0, &frame->uc.uc__pad0);
+
+		if (ka->sa.sa_flags & SA_RESTORER) {
+			restorer = ka->sa.sa_restorer;
+		} else {
+			/* could use a vstub here */
+			restorer = NULL;
+			err |= -EFAULT;
+		}
+		put_user_ex(restorer, &frame->pretcode);
+	} put_user_catch(err);
+
+	err |= setup_sigcontext(&frame->uc.uc_mcontext, fpstate,
+				regs, set->sig[0]);
+	err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
+
+	if (err)
+		return -EFAULT;
+
+	/* Set up registers for signal handler */
+	regs->sp = (unsigned long) frame;
+	regs->ip = (unsigned long) ka->sa.sa_handler;
+
+	/* We use the x32 calling convention here... */
+	regs->di = sig;
+	regs->si = (unsigned long) &frame->info;
+	regs->dx = (unsigned long) &frame->uc;
+
+	loadsegment(ds, __USER_DS);
+	loadsegment(es, __USER_DS);
+
+	regs->cs = __USER_CS;
+	regs->ss = __USER_DS;
+#endif	/* CONFIG_X86_X32_ABI */
+
+	return 0;
+}
+
 #ifdef CONFIG_X86_32
 /*
  * Atomically swap in the new signal mask, and wait for a signal.
@@ -612,55 +682,22 @@ static int signr_convert(int sig)
 	return sig;
 }
 
-#ifdef CONFIG_X86_32
-
-#define is_ia32	1
-#define ia32_setup_frame	__setup_frame
-#define ia32_setup_rt_frame	__setup_rt_frame
-
-#else /* !CONFIG_X86_32 */
-
-#ifdef CONFIG_IA32_EMULATION
-#define is_ia32	test_thread_flag(TIF_IA32)
-#else /* !CONFIG_IA32_EMULATION */
-#define is_ia32	0
-#endif /* CONFIG_IA32_EMULATION */
-
-#ifdef CONFIG_X86_X32_ABI
-#define is_x32	test_thread_flag(TIF_X32)
-
-static int x32_setup_rt_frame(int sig, struct k_sigaction *ka,
-			      siginfo_t *info, compat_sigset_t *set,
-			      struct pt_regs *regs);
-#else /* !CONFIG_X86_X32_ABI */
-#define is_x32	0
-#endif /* CONFIG_X86_X32_ABI */
-
-int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
-		sigset_t *set, struct pt_regs *regs);
-int ia32_setup_frame(int sig, struct k_sigaction *ka,
-		sigset_t *set, struct pt_regs *regs);
-
-#endif /* CONFIG_X86_32 */
-
 static int
 setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 		struct pt_regs *regs)
 {
 	int usig = signr_convert(sig);
 	sigset_t *set = sigmask_to_save();
+	compat_sigset_t *cset = (compat_sigset_t *) set;
 
 	/* Set up the stack frame */
-	if (is_ia32) {
+	if (is_ia32_frame()) {
 		if (ka->sa.sa_flags & SA_SIGINFO)
-			return ia32_setup_rt_frame(usig, ka, info, set, regs);
+			return ia32_setup_rt_frame(usig, ka, info, cset, regs);
 		else
-			return ia32_setup_frame(usig, ka, set, regs);
-#ifdef CONFIG_X86_X32_ABI
-	} else if (is_x32) {
-		return x32_setup_rt_frame(usig, ka, info,
-					 (compat_sigset_t *)set, regs);
-#endif
+			return ia32_setup_frame(usig, ka, cset, regs);
+	} else if (is_x32_frame()) {
+		return x32_setup_rt_frame(usig, ka, info, cset, regs);
 	} else {
 		return __setup_rt_frame(sig, ka, info, set, regs);
 	}
@@ -800,10 +837,6 @@ do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags)
 	}
 	if (thread_info_flags & _TIF_USER_RETURN_NOTIFY)
 		fire_user_return_notifiers();
-
-#ifdef CONFIG_X86_32
-	clear_thread_flag(TIF_IRET);
-#endif /* CONFIG_X86_32 */
 }
 
 void signal_fault(struct pt_regs *regs, void __user *frame, char *where)
@@ -824,72 +857,6 @@ void signal_fault(struct pt_regs *regs, void __user *frame, char *where)
 }
 
 #ifdef CONFIG_X86_X32_ABI
-static int x32_setup_rt_frame(int sig, struct k_sigaction *ka,
-			      siginfo_t *info, compat_sigset_t *set,
-			      struct pt_regs *regs)
-{
-	struct rt_sigframe_x32 __user *frame;
-	void __user *restorer;
-	int err = 0;
-	void __user *fpstate = NULL;
-
-	frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate);
-
-	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
-		return -EFAULT;
-
-	if (ka->sa.sa_flags & SA_SIGINFO) {
-		if (copy_siginfo_to_user32(&frame->info, info))
-			return -EFAULT;
-	}
-
-	put_user_try {
-		/* Create the ucontext.  */
-		if (cpu_has_xsave)
-			put_user_ex(UC_FP_XSTATE, &frame->uc.uc_flags);
-		else
-			put_user_ex(0, &frame->uc.uc_flags);
-		put_user_ex(0, &frame->uc.uc_link);
-		put_user_ex(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
-		put_user_ex(sas_ss_flags(regs->sp),
-			    &frame->uc.uc_stack.ss_flags);
-		put_user_ex(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
-		put_user_ex(0, &frame->uc.uc__pad0);
-		err |= setup_sigcontext(&frame->uc.uc_mcontext, fpstate,
-					regs, set->sig[0]);
-		err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
-
-		if (ka->sa.sa_flags & SA_RESTORER) {
-			restorer = ka->sa.sa_restorer;
-		} else {
-			/* could use a vstub here */
-			restorer = NULL;
-			err |= -EFAULT;
-		}
-		put_user_ex(restorer, &frame->pretcode);
-	} put_user_catch(err);
-
-	if (err)
-		return -EFAULT;
-
-	/* Set up registers for signal handler */
-	regs->sp = (unsigned long) frame;
-	regs->ip = (unsigned long) ka->sa.sa_handler;
-
-	/* We use the x32 calling convention here... */
-	regs->di = sig;
-	regs->si = (unsigned long) &frame->info;
-	regs->dx = (unsigned long) &frame->uc;
-
-	loadsegment(ds, __USER_DS);
-	loadsegment(es, __USER_DS);
-
-	regs->cs = __USER_CS;
-	regs->ss = __USER_DS;
-
-	return 0;
-}
-
 asmlinkage long sys32_x32_rt_sigreturn(struct pt_regs *regs)
 {
 	struct rt_sigframe_x32 __user *frame;
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index 7c5a8c3..c80a33b 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -665,7 +665,8 @@ static int __cpuinit do_boot_cpu(int apicid, int cpu, struct task_struct *idle)
 	unsigned long boot_error = 0;
 	int timeout;
 
-	alternatives_smp_switch(1);
+	/* Just in case we booted with a single CPU. */
+	alternatives_enable_smp();
 
 	idle->thread.sp = (unsigned long) (((struct pt_regs *)
 			  (THREAD_SIZE +  task_stack_page(idle))) - 1);
@@ -1053,20 +1054,6 @@ out:
 	preempt_enable();
 }
 
-void arch_disable_nonboot_cpus_begin(void)
-{
-	/*
-	 * Avoid the smp alternatives switch during the disable_nonboot_cpus().
-	 * In the suspend path, we will be back in the SMP mode shortly anyways.
-	 */
-	skip_smp_alternatives = true;
-}
-
-void arch_disable_nonboot_cpus_end(void)
-{
-	skip_smp_alternatives = false;
-}
-
 void arch_enable_nonboot_cpus_begin(void)
 {
 	set_mtrr_aps_delayed_init();
@@ -1256,9 +1243,6 @@ void native_cpu_die(unsigned int cpu)
 		if (per_cpu(cpu_state, cpu) == CPU_DEAD) {
 			if (system_state == SYSTEM_RUNNING)
 				pr_info("CPU %u is now offline\n", cpu);
-
-			if (1 == num_online_cpus())
-				alternatives_smp_switch(0);
 			return;
 		}
 		msleep(100);
diff --git a/arch/x86/kernel/step.c b/arch/x86/kernel/step.c
index c346d11..cd3b243 100644
--- a/arch/x86/kernel/step.c
+++ b/arch/x86/kernel/step.c
@@ -157,6 +157,33 @@ static int enable_single_step(struct task_struct *child)
 	return 1;
 }
 
+void set_task_blockstep(struct task_struct *task, bool on)
+{
+	unsigned long debugctl;
+
+	/*
+	 * Ensure irq/preemption can't change debugctl in between.
+	 * Note also that both TIF_BLOCKSTEP and debugctl should
+	 * be changed atomically wrt preemption.
+	 * FIXME: this means that set/clear TIF_BLOCKSTEP is simply
+	 * wrong if task != current, SIGKILL can wakeup the stopped
+	 * tracee and set/clear can play with the running task, this
+	 * can confuse the next __switch_to_xtra().
+	 */
+	local_irq_disable();
+	debugctl = get_debugctlmsr();
+	if (on) {
+		debugctl |= DEBUGCTLMSR_BTF;
+		set_tsk_thread_flag(task, TIF_BLOCKSTEP);
+	} else {
+		debugctl &= ~DEBUGCTLMSR_BTF;
+		clear_tsk_thread_flag(task, TIF_BLOCKSTEP);
+	}
+	if (task == current)
+		update_debugctlmsr(debugctl);
+	local_irq_enable();
+}
+
 /*
  * Enable single or block step.
  */
@@ -169,19 +196,10 @@ static void enable_step(struct task_struct *child, bool block)
 	 * So no one should try to use debugger block stepping in a program
 	 * that uses user-mode single stepping itself.
 	 */
-	if (enable_single_step(child) && block) {
-		unsigned long debugctl = get_debugctlmsr();
-
-		debugctl |= DEBUGCTLMSR_BTF;
-		update_debugctlmsr(debugctl);
-		set_tsk_thread_flag(child, TIF_BLOCKSTEP);
-	} else if (test_tsk_thread_flag(child, TIF_BLOCKSTEP)) {
-		unsigned long debugctl = get_debugctlmsr();
-
-		debugctl &= ~DEBUGCTLMSR_BTF;
-		update_debugctlmsr(debugctl);
-		clear_tsk_thread_flag(child, TIF_BLOCKSTEP);
-	}
+	if (enable_single_step(child) && block)
+		set_task_blockstep(child, true);
+	else if (test_tsk_thread_flag(child, TIF_BLOCKSTEP))
+		set_task_blockstep(child, false);
 }
 
 void user_enable_single_step(struct task_struct *child)
@@ -199,13 +217,8 @@ void user_disable_single_step(struct task_struct *child)
 	/*
 	 * Make sure block stepping (BTF) is disabled.
 	 */
-	if (test_tsk_thread_flag(child, TIF_BLOCKSTEP)) {
-		unsigned long debugctl = get_debugctlmsr();
-
-		debugctl &= ~DEBUGCTLMSR_BTF;
-		update_debugctlmsr(debugctl);
-		clear_tsk_thread_flag(child, TIF_BLOCKSTEP);
-	}
+	if (test_tsk_thread_flag(child, TIF_BLOCKSTEP))
+		set_task_blockstep(child, false);
 
 	/* Always clear TIF_SINGLESTEP... */
 	clear_tsk_thread_flag(child, TIF_SINGLESTEP);
diff --git a/arch/x86/kernel/sys_i386_32.c b/arch/x86/kernel/sys_i386_32.c
deleted file mode 100644
index 0b0cb5f..0000000
--- a/arch/x86/kernel/sys_i386_32.c
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * This file contains various random system calls that
- * have a non-standard calling sequence on the Linux/i386
- * platform.
- */
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/fs.h>
-#include <linux/smp.h>
-#include <linux/sem.h>
-#include <linux/msg.h>
-#include <linux/shm.h>
-#include <linux/stat.h>
-#include <linux/syscalls.h>
-#include <linux/mman.h>
-#include <linux/file.h>
-#include <linux/utsname.h>
-#include <linux/ipc.h>
-
-#include <linux/uaccess.h>
-#include <linux/unistd.h>
-
-#include <asm/syscalls.h>
-
-/*
- * Do a system call from kernel instead of calling sys_execve so we
- * end up with proper pt_regs.
- */
-int kernel_execve(const char *filename,
-		  const char *const argv[],
-		  const char *const envp[])
-{
-	long __res;
-	asm volatile ("int $0x80"
-	: "=a" (__res)
-	: "0" (__NR_execve), "b" (filename), "c" (argv), "d" (envp) : "memory");
-	return __res;
-}
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index b481341..4f4aba0 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -613,11 +613,12 @@ void math_state_restore(void)
 	}
 
 	__thread_fpu_begin(tsk);
+
 	/*
 	 * Paranoid restore. send a SIGSEGV if we fail to restore the state.
 	 */
 	if (unlikely(restore_fpu_checking(tsk))) {
-		__thread_fpu_end(tsk);
+		drop_init_fpu(tsk);
 		force_sig(SIGSEGV, tsk);
 		return;
 	}
@@ -629,6 +630,8 @@ EXPORT_SYMBOL_GPL(math_state_restore);
 dotraplinkage void __kprobes
 do_device_not_available(struct pt_regs *regs, long error_code)
 {
+	BUG_ON(use_eager_fpu());
+
 #ifdef CONFIG_MATH_EMULATION
 	if (read_cr0() & X86_CR0_EM) {
 		struct math_emu_info info = { };
diff --git a/arch/x86/kernel/uprobes.c b/arch/x86/kernel/uprobes.c
index 36fd420..9538f00 100644
--- a/arch/x86/kernel/uprobes.c
+++ b/arch/x86/kernel/uprobes.c
@@ -41,6 +41,9 @@
 /* Adjust the return address of a call insn */
 #define UPROBE_FIX_CALL	0x2
 
+/* Instruction will modify TF, don't change it */
+#define UPROBE_FIX_SETF	0x4
+
 #define UPROBE_FIX_RIP_AX	0x8000
 #define UPROBE_FIX_RIP_CX	0x4000
 
@@ -239,6 +242,10 @@ static void prepare_fixups(struct arch_uprobe *auprobe, struct insn *insn)
 	insn_get_opcode(insn);	/* should be a nop */
 
 	switch (OPCODE1(insn)) {
+	case 0x9d:
+		/* popf */
+		auprobe->fixups |= UPROBE_FIX_SETF;
+		break;
 	case 0xc3:		/* ret/lret */
 	case 0xcb:
 	case 0xc2:
@@ -646,7 +653,7 @@ void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
  * Skip these instructions as per the currently known x86 ISA.
  * 0x66* { 0x90 | 0x0f 0x1f | 0x0f 0x19 | 0x87 0xc0 }
  */
-bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs)
+static bool __skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs)
 {
 	int i;
 
@@ -673,3 +680,46 @@ bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs)
 	}
 	return false;
 }
+
+bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs)
+{
+	bool ret = __skip_sstep(auprobe, regs);
+	if (ret && (regs->flags & X86_EFLAGS_TF))
+		send_sig(SIGTRAP, current, 0);
+	return ret;
+}
+
+void arch_uprobe_enable_step(struct arch_uprobe *auprobe)
+{
+	struct task_struct *task = current;
+	struct arch_uprobe_task	*autask	= &task->utask->autask;
+	struct pt_regs *regs = task_pt_regs(task);
+
+	autask->saved_tf = !!(regs->flags & X86_EFLAGS_TF);
+
+	regs->flags |= X86_EFLAGS_TF;
+	if (test_tsk_thread_flag(task, TIF_BLOCKSTEP))
+		set_task_blockstep(task, false);
+}
+
+void arch_uprobe_disable_step(struct arch_uprobe *auprobe)
+{
+	struct task_struct *task = current;
+	struct arch_uprobe_task	*autask	= &task->utask->autask;
+	bool trapped = (task->utask->state == UTASK_SSTEP_TRAPPED);
+	struct pt_regs *regs = task_pt_regs(task);
+	/*
+	 * The state of TIF_BLOCKSTEP was not saved so we can get an extra
+	 * SIGTRAP if we do not clear TF. We need to examine the opcode to
+	 * make it right.
+	 */
+	if (unlikely(trapped)) {
+		if (!autask->saved_tf)
+			regs->flags &= ~X86_EFLAGS_TF;
+	} else {
+		if (autask->saved_tf)
+			send_sig(SIGTRAP, task, 0);
+		else if (!(auprobe->fixups & UPROBE_FIX_SETF))
+			regs->flags &= ~X86_EFLAGS_TF;
+	}
+}
diff --git a/arch/x86/kernel/vm86_32.c b/arch/x86/kernel/vm86_32.c
index 54abcc0..5c9687b 100644
--- a/arch/x86/kernel/vm86_32.c
+++ b/arch/x86/kernel/vm86_32.c
@@ -561,9 +561,9 @@ int handle_vm86_trap(struct kernel_vm86_regs *regs, long error_code, int trapno)
 		if ((trapno == 3) || (trapno == 1)) {
 			KVM86->regs32->ax = VM86_TRAP + (trapno << 8);
 			/* setting this flag forces the code in entry_32.S to
-			   call save_v86_state() and change the stack pointer
-			   to KVM86->regs32 */
-			set_thread_flag(TIF_IRET);
+			   the path where we call save_v86_state() and change
+			   the stack pointer to KVM86->regs32 */
+			set_thread_flag(TIF_NOTIFY_RESUME);
 			return 0;
 		}
 		do_int(regs, trapno, (unsigned char __user *) (regs->pt.ss << 4), SP(regs));
diff --git a/arch/x86/kernel/x8664_ksyms_64.c b/arch/x86/kernel/x8664_ksyms_64.c
index 6020f6f..1330dd1 100644
--- a/arch/x86/kernel/x8664_ksyms_64.c
+++ b/arch/x86/kernel/x8664_ksyms_64.c
@@ -13,9 +13,13 @@
 #include <asm/ftrace.h>
 
 #ifdef CONFIG_FUNCTION_TRACER
-/* mcount is defined in assembly */
+/* mcount and __fentry__ are defined in assembly */
+#ifdef CC_USING_FENTRY
+EXPORT_SYMBOL(__fentry__);
+#else
 EXPORT_SYMBOL(mcount);
 #endif
+#endif
 
 EXPORT_SYMBOL(__get_user_1);
 EXPORT_SYMBOL(__get_user_2);
diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c
index 9f3167e..7a3d075 100644
--- a/arch/x86/kernel/x86_init.c
+++ b/arch/x86/kernel/x86_init.c
@@ -26,7 +26,6 @@
 
 void __cpuinit x86_init_noop(void) { }
 void __init x86_init_uint_noop(unsigned int unused) { }
-void __init x86_init_pgd_noop(pgd_t *unused) { }
 int __init iommu_init_noop(void) { return 0; }
 void iommu_shutdown_noop(void) { }
 
@@ -68,8 +67,7 @@ struct x86_init_ops x86_init __initdata = {
 	},
 
 	.paging = {
-		.pagetable_setup_start	= native_pagetable_setup_start,
-		.pagetable_setup_done	= native_pagetable_setup_done,
+		.pagetable_init		= native_pagetable_init,
 	},
 
 	.timers = {
diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c
index 3d3e207..4e89b3d 100644
--- a/arch/x86/kernel/xsave.c
+++ b/arch/x86/kernel/xsave.c
@@ -10,9 +10,7 @@
 #include <linux/compat.h>
 #include <asm/i387.h>
 #include <asm/fpu-internal.h>
-#ifdef CONFIG_IA32_EMULATION
-#include <asm/sigcontext32.h>
-#endif
+#include <asm/sigframe.h>
 #include <asm/xcr.h>
 
 /*
@@ -23,13 +21,9 @@ u64 pcntxt_mask;
 /*
  * Represents init state for the supported extended state.
  */
-static struct xsave_struct *init_xstate_buf;
-
-struct _fpx_sw_bytes fx_sw_reserved;
-#ifdef CONFIG_IA32_EMULATION
-struct _fpx_sw_bytes fx_sw_reserved_ia32;
-#endif
+struct xsave_struct *init_xstate_buf;
 
+static struct _fpx_sw_bytes fx_sw_reserved, fx_sw_reserved_ia32;
 static unsigned int *xstate_offsets, *xstate_sizes, xstate_features;
 
 /*
@@ -44,9 +38,9 @@ static unsigned int *xstate_offsets, *xstate_sizes, xstate_features;
  */
 void __sanitize_i387_state(struct task_struct *tsk)
 {
-	u64 xstate_bv;
-	int feature_bit = 0x2;
 	struct i387_fxsave_struct *fx = &tsk->thread.fpu.state->fxsave;
+	int feature_bit = 0x2;
+	u64 xstate_bv;
 
 	if (!fx)
 		return;
@@ -104,213 +98,326 @@ void __sanitize_i387_state(struct task_struct *tsk)
  * Check for the presence of extended state information in the
  * user fpstate pointer in the sigcontext.
  */
-int check_for_xstate(struct i387_fxsave_struct __user *buf,
-		     void __user *fpstate,
-		     struct _fpx_sw_bytes *fx_sw_user)
+static inline int check_for_xstate(struct i387_fxsave_struct __user *buf,
+				   void __user *fpstate,
+				   struct _fpx_sw_bytes *fx_sw)
 {
 	int min_xstate_size = sizeof(struct i387_fxsave_struct) +
 			      sizeof(struct xsave_hdr_struct);
 	unsigned int magic2;
-	int err;
 
-	err = __copy_from_user(fx_sw_user, &buf->sw_reserved[0],
-			       sizeof(struct _fpx_sw_bytes));
-	if (err)
-		return -EFAULT;
+	if (__copy_from_user(fx_sw, &buf->sw_reserved[0], sizeof(*fx_sw)))
+		return -1;
 
-	/*
-	 * First Magic check failed.
-	 */
-	if (fx_sw_user->magic1 != FP_XSTATE_MAGIC1)
-		return -EINVAL;
+	/* Check for the first magic field and other error scenarios. */
+	if (fx_sw->magic1 != FP_XSTATE_MAGIC1 ||
+	    fx_sw->xstate_size < min_xstate_size ||
+	    fx_sw->xstate_size > xstate_size ||
+	    fx_sw->xstate_size > fx_sw->extended_size)
+		return -1;
 
 	/*
-	 * Check for error scenarios.
-	 */
-	if (fx_sw_user->xstate_size < min_xstate_size ||
-	    fx_sw_user->xstate_size > xstate_size ||
-	    fx_sw_user->xstate_size > fx_sw_user->extended_size)
-		return -EINVAL;
-
-	err = __get_user(magic2, (__u32 *) (((void *)fpstate) +
-					    fx_sw_user->extended_size -
-					    FP_XSTATE_MAGIC2_SIZE));
-	if (err)
-		return err;
-	/*
 	 * Check for the presence of second magic word at the end of memory
 	 * layout. This detects the case where the user just copied the legacy
 	 * fpstate layout with out copying the extended state information
 	 * in the memory layout.
 	 */
-	if (magic2 != FP_XSTATE_MAGIC2)
-		return -EFAULT;
+	if (__get_user(magic2, (__u32 __user *)(fpstate + fx_sw->xstate_size))
+	    || magic2 != FP_XSTATE_MAGIC2)
+		return -1;
 
 	return 0;
 }
 
-#ifdef CONFIG_X86_64
 /*
  * Signal frame handlers.
  */
-
-int save_i387_xstate(void __user *buf)
+static inline int save_fsave_header(struct task_struct *tsk, void __user *buf)
 {
-	struct task_struct *tsk = current;
-	int err = 0;
-
-	if (!access_ok(VERIFY_WRITE, buf, sig_xstate_size))
-		return -EACCES;
+	if (use_fxsr()) {
+		struct xsave_struct *xsave = &tsk->thread.fpu.state->xsave;
+		struct user_i387_ia32_struct env;
+		struct _fpstate_ia32 __user *fp = buf;
 
-	BUG_ON(sig_xstate_size < xstate_size);
+		convert_from_fxsr(&env, tsk);
 
-	if ((unsigned long)buf % 64)
-		pr_err("%s: bad fpstate %p\n", __func__, buf);
-
-	if (!used_math())
-		return 0;
-
-	if (user_has_fpu()) {
-		if (use_xsave())
-			err = xsave_user(buf);
-		else
-			err = fxsave_user(buf);
-
-		if (err)
-			return err;
-		user_fpu_end();
+		if (__copy_to_user(buf, &env, sizeof(env)) ||
+		    __put_user(xsave->i387.swd, &fp->status) ||
+		    __put_user(X86_FXSR_MAGIC, &fp->magic))
+			return -1;
 	} else {
-		sanitize_i387_state(tsk);
-		if (__copy_to_user(buf, &tsk->thread.fpu.state->fxsave,
-				   xstate_size))
+		struct i387_fsave_struct __user *fp = buf;
+		u32 swd;
+		if (__get_user(swd, &fp->swd) || __put_user(swd, &fp->status))
 			return -1;
 	}
 
-	clear_used_math(); /* trigger finit */
+	return 0;
+}
 
-	if (use_xsave()) {
-		struct _fpstate __user *fx = buf;
-		struct _xstate __user *x = buf;
-		u64 xstate_bv;
+static inline int save_xstate_epilog(void __user *buf, int ia32_frame)
+{
+	struct xsave_struct __user *x = buf;
+	struct _fpx_sw_bytes *sw_bytes;
+	u32 xstate_bv;
+	int err;
 
-		err = __copy_to_user(&fx->sw_reserved, &fx_sw_reserved,
-				     sizeof(struct _fpx_sw_bytes));
+	/* Setup the bytes not touched by the [f]xsave and reserved for SW. */
+	sw_bytes = ia32_frame ? &fx_sw_reserved_ia32 : &fx_sw_reserved;
+	err = __copy_to_user(&x->i387.sw_reserved, sw_bytes, sizeof(*sw_bytes));
 
-		err |= __put_user(FP_XSTATE_MAGIC2,
-				  (__u32 __user *) (buf + sig_xstate_size
-						    - FP_XSTATE_MAGIC2_SIZE));
+	if (!use_xsave())
+		return err;
 
-		/*
-		 * Read the xstate_bv which we copied (directly from the cpu or
-		 * from the state in task struct) to the user buffers and
-		 * set the FP/SSE bits.
-		 */
-		err |= __get_user(xstate_bv, &x->xstate_hdr.xstate_bv);
+	err |= __put_user(FP_XSTATE_MAGIC2, (__u32 *)(buf + xstate_size));
 
-		/*
-		 * For legacy compatible, we always set FP/SSE bits in the bit
-		 * vector while saving the state to the user context. This will
-		 * enable us capturing any changes(during sigreturn) to
-		 * the FP/SSE bits by the legacy applications which don't touch
-		 * xstate_bv in the xsave header.
-		 *
-		 * xsave aware apps can change the xstate_bv in the xsave
-		 * header as well as change any contents in the memory layout.
-		 * xrestore as part of sigreturn will capture all the changes.
-		 */
-		xstate_bv |= XSTATE_FPSSE;
+	/*
+	 * Read the xstate_bv which we copied (directly from the cpu or
+	 * from the state in task struct) to the user buffers.
+	 */
+	err |= __get_user(xstate_bv, (__u32 *)&x->xsave_hdr.xstate_bv);
 
-		err |= __put_user(xstate_bv, &x->xstate_hdr.xstate_bv);
+	/*
+	 * For legacy compatible, we always set FP/SSE bits in the bit
+	 * vector while saving the state to the user context. This will
+	 * enable us capturing any changes(during sigreturn) to
+	 * the FP/SSE bits by the legacy applications which don't touch
+	 * xstate_bv in the xsave header.
+	 *
+	 * xsave aware apps can change the xstate_bv in the xsave
+	 * header as well as change any contents in the memory layout.
+	 * xrestore as part of sigreturn will capture all the changes.
+	 */
+	xstate_bv |= XSTATE_FPSSE;
 
-		if (err)
-			return err;
-	}
+	err |= __put_user(xstate_bv, (__u32 *)&x->xsave_hdr.xstate_bv);
 
-	return 1;
+	return err;
+}
+
+static inline int save_user_xstate(struct xsave_struct __user *buf)
+{
+	int err;
+
+	if (use_xsave())
+		err = xsave_user(buf);
+	else if (use_fxsr())
+		err = fxsave_user((struct i387_fxsave_struct __user *) buf);
+	else
+		err = fsave_user((struct i387_fsave_struct __user *) buf);
+
+	if (unlikely(err) && __clear_user(buf, xstate_size))
+		err = -EFAULT;
+	return err;
 }
 
 /*
- * Restore the extended state if present. Otherwise, restore the FP/SSE
- * state.
+ * Save the fpu, extended register state to the user signal frame.
+ *
+ * 'buf_fx' is the 64-byte aligned pointer at which the [f|fx|x]save
+ *  state is copied.
+ *  'buf' points to the 'buf_fx' or to the fsave header followed by 'buf_fx'.
+ *
+ *	buf == buf_fx for 64-bit frames and 32-bit fsave frame.
+ *	buf != buf_fx for 32-bit frames with fxstate.
+ *
+ * If the fpu, extended register state is live, save the state directly
+ * to the user frame pointed by the aligned pointer 'buf_fx'. Otherwise,
+ * copy the thread's fpu state to the user frame starting at 'buf_fx'.
+ *
+ * If this is a 32-bit frame with fxstate, put a fsave header before
+ * the aligned state at 'buf_fx'.
+ *
+ * For [f]xsave state, update the SW reserved fields in the [f]xsave frame
+ * indicating the absence/presence of the extended state to the user.
  */
-static int restore_user_xstate(void __user *buf)
+int save_xstate_sig(void __user *buf, void __user *buf_fx, int size)
 {
-	struct _fpx_sw_bytes fx_sw_user;
-	u64 mask;
-	int err;
+	struct xsave_struct *xsave = &current->thread.fpu.state->xsave;
+	struct task_struct *tsk = current;
+	int ia32_fxstate = (buf != buf_fx);
 
-	if (((unsigned long)buf % 64) ||
-	     check_for_xstate(buf, buf, &fx_sw_user))
-		goto fx_only;
+	ia32_fxstate &= (config_enabled(CONFIG_X86_32) ||
+			 config_enabled(CONFIG_IA32_EMULATION));
 
-	mask = fx_sw_user.xstate_bv;
+	if (!access_ok(VERIFY_WRITE, buf, size))
+		return -EACCES;
 
-	/*
-	 * restore the state passed by the user.
-	 */
-	err = xrestore_user(buf, mask);
-	if (err)
-		return err;
+	if (!HAVE_HWFP)
+		return fpregs_soft_get(current, NULL, 0,
+			sizeof(struct user_i387_ia32_struct), NULL,
+			(struct _fpstate_ia32 __user *) buf) ? -1 : 1;
 
-	/*
-	 * init the state skipped by the user.
-	 */
-	mask = pcntxt_mask & ~mask;
-	if (unlikely(mask))
-		xrstor_state(init_xstate_buf, mask);
+	if (user_has_fpu()) {
+		/* Save the live register state to the user directly. */
+		if (save_user_xstate(buf_fx))
+			return -1;
+		/* Update the thread's fxstate to save the fsave header. */
+		if (ia32_fxstate)
+			fpu_fxsave(&tsk->thread.fpu);
+	} else {
+		sanitize_i387_state(tsk);
+		if (__copy_to_user(buf_fx, xsave, xstate_size))
+			return -1;
+	}
+
+	/* Save the fsave header for the 32-bit frames. */
+	if ((ia32_fxstate || !use_fxsr()) && save_fsave_header(tsk, buf))
+		return -1;
+
+	if (use_fxsr() && save_xstate_epilog(buf_fx, ia32_fxstate))
+		return -1;
+
+	drop_init_fpu(tsk);	/* trigger finit */
 
 	return 0;
+}
 
-fx_only:
-	/*
-	 * couldn't find the extended state information in the
-	 * memory layout. Restore just the FP/SSE and init all
-	 * the other extended state.
-	 */
-	xrstor_state(init_xstate_buf, pcntxt_mask & ~XSTATE_FPSSE);
-	return fxrstor_checking((__force struct i387_fxsave_struct *)buf);
+static inline void
+sanitize_restored_xstate(struct task_struct *tsk,
+			 struct user_i387_ia32_struct *ia32_env,
+			 u64 xstate_bv, int fx_only)
+{
+	struct xsave_struct *xsave = &tsk->thread.fpu.state->xsave;
+	struct xsave_hdr_struct *xsave_hdr = &xsave->xsave_hdr;
+
+	if (use_xsave()) {
+		/* These bits must be zero. */
+		xsave_hdr->reserved1[0] = xsave_hdr->reserved1[1] = 0;
+
+		/*
+		 * Init the state that is not present in the memory
+		 * layout and not enabled by the OS.
+		 */
+		if (fx_only)
+			xsave_hdr->xstate_bv = XSTATE_FPSSE;
+		else
+			xsave_hdr->xstate_bv &= (pcntxt_mask & xstate_bv);
+	}
+
+	if (use_fxsr()) {
+		/*
+		 * mscsr reserved bits must be masked to zero for security
+		 * reasons.
+		 */
+		xsave->i387.mxcsr &= mxcsr_feature_mask;
+
+		convert_to_fxsr(tsk, ia32_env);
+	}
 }
 
 /*
- * This restores directly out of user space. Exceptions are handled.
+ * Restore the extended state if present. Otherwise, restore the FP/SSE state.
  */
-int restore_i387_xstate(void __user *buf)
+static inline int restore_user_xstate(void __user *buf, u64 xbv, int fx_only)
 {
+	if (use_xsave()) {
+		if ((unsigned long)buf % 64 || fx_only) {
+			u64 init_bv = pcntxt_mask & ~XSTATE_FPSSE;
+			xrstor_state(init_xstate_buf, init_bv);
+			return fxrstor_checking((__force void *) buf);
+		} else {
+			u64 init_bv = pcntxt_mask & ~xbv;
+			if (unlikely(init_bv))
+				xrstor_state(init_xstate_buf, init_bv);
+			return xrestore_user(buf, xbv);
+		}
+	} else if (use_fxsr()) {
+		return fxrstor_checking((__force void *) buf);
+	} else
+		return frstor_checking((__force void *) buf);
+}
+
+int __restore_xstate_sig(void __user *buf, void __user *buf_fx, int size)
+{
+	int ia32_fxstate = (buf != buf_fx);
 	struct task_struct *tsk = current;
-	int err = 0;
+	int state_size = xstate_size;
+	u64 xstate_bv = 0;
+	int fx_only = 0;
+
+	ia32_fxstate &= (config_enabled(CONFIG_X86_32) ||
+			 config_enabled(CONFIG_IA32_EMULATION));
 
 	if (!buf) {
-		if (used_math())
-			goto clear;
+		drop_init_fpu(tsk);
 		return 0;
-	} else
-		if (!access_ok(VERIFY_READ, buf, sig_xstate_size))
-			return -EACCES;
+	}
 
-	if (!used_math()) {
-		err = init_fpu(tsk);
-		if (err)
-			return err;
+	if (!access_ok(VERIFY_READ, buf, size))
+		return -EACCES;
+
+	if (!used_math() && init_fpu(tsk))
+		return -1;
+
+	if (!HAVE_HWFP) {
+		return fpregs_soft_set(current, NULL,
+				       0, sizeof(struct user_i387_ia32_struct),
+				       NULL, buf) != 0;
 	}
 
-	user_fpu_begin();
-	if (use_xsave())
-		err = restore_user_xstate(buf);
-	else
-		err = fxrstor_checking((__force struct i387_fxsave_struct *)
-				       buf);
-	if (unlikely(err)) {
+	if (use_xsave()) {
+		struct _fpx_sw_bytes fx_sw_user;
+		if (unlikely(check_for_xstate(buf_fx, buf_fx, &fx_sw_user))) {
+			/*
+			 * Couldn't find the extended state information in the
+			 * memory layout. Restore just the FP/SSE and init all
+			 * the other extended state.
+			 */
+			state_size = sizeof(struct i387_fxsave_struct);
+			fx_only = 1;
+		} else {
+			state_size = fx_sw_user.xstate_size;
+			xstate_bv = fx_sw_user.xstate_bv;
+		}
+	}
+
+	if (ia32_fxstate) {
+		/*
+		 * For 32-bit frames with fxstate, copy the user state to the
+		 * thread's fpu state, reconstruct fxstate from the fsave
+		 * header. Sanitize the copied state etc.
+		 */
+		struct xsave_struct *xsave = &tsk->thread.fpu.state->xsave;
+		struct user_i387_ia32_struct env;
+		int err = 0;
+
+		/*
+		 * Drop the current fpu which clears used_math(). This ensures
+		 * that any context-switch during the copy of the new state,
+		 * avoids the intermediate state from getting restored/saved.
+		 * Thus avoiding the new restored state from getting corrupted.
+		 * We will be ready to restore/save the state only after
+		 * set_used_math() is again set.
+		 */
+		drop_fpu(tsk);
+
+		if (__copy_from_user(xsave, buf_fx, state_size) ||
+		    __copy_from_user(&env, buf, sizeof(env))) {
+			err = -1;
+		} else {
+			sanitize_restored_xstate(tsk, &env, xstate_bv, fx_only);
+			set_used_math();
+		}
+
+		if (use_eager_fpu())
+			math_state_restore();
+
+		return err;
+	} else {
 		/*
-		 * Encountered an error while doing the restore from the
-		 * user buffer, clear the fpu state.
+		 * For 64-bit frames and 32-bit fsave frames, restore the user
+		 * state to the registers directly (with exceptions handled).
 		 */
-clear:
-		clear_fpu(tsk);
-		clear_used_math();
+		user_fpu_begin();
+		if (restore_user_xstate(buf_fx, xstate_bv, fx_only)) {
+			drop_init_fpu(tsk);
+			return -1;
+		}
 	}
-	return err;
+
+	return 0;
 }
-#endif
 
 /*
  * Prepare the SW reserved portion of the fxsave memory layout, indicating
@@ -321,31 +428,22 @@ clear:
  */
 static void prepare_fx_sw_frame(void)
 {
-	int size_extended = (xstate_size - sizeof(struct i387_fxsave_struct)) +
-			     FP_XSTATE_MAGIC2_SIZE;
+	int fsave_header_size = sizeof(struct i387_fsave_struct);
+	int size = xstate_size + FP_XSTATE_MAGIC2_SIZE;
 
-	sig_xstate_size = sizeof(struct _fpstate) + size_extended;
-
-#ifdef CONFIG_IA32_EMULATION
-	sig_xstate_ia32_size = sizeof(struct _fpstate_ia32) + size_extended;
-#endif
-
-	memset(&fx_sw_reserved, 0, sizeof(fx_sw_reserved));
+	if (config_enabled(CONFIG_X86_32))
+		size += fsave_header_size;
 
 	fx_sw_reserved.magic1 = FP_XSTATE_MAGIC1;
-	fx_sw_reserved.extended_size = sig_xstate_size;
+	fx_sw_reserved.extended_size = size;
 	fx_sw_reserved.xstate_bv = pcntxt_mask;
 	fx_sw_reserved.xstate_size = xstate_size;
-#ifdef CONFIG_IA32_EMULATION
-	memcpy(&fx_sw_reserved_ia32, &fx_sw_reserved,
-	       sizeof(struct _fpx_sw_bytes));
-	fx_sw_reserved_ia32.extended_size = sig_xstate_ia32_size;
-#endif
-}
 
-#ifdef CONFIG_X86_64
-unsigned int sig_xstate_size = sizeof(struct _fpstate);
-#endif
+	if (config_enabled(CONFIG_IA32_EMULATION)) {
+		fx_sw_reserved_ia32 = fx_sw_reserved;
+		fx_sw_reserved_ia32.extended_size += fsave_header_size;
+	}
+}
 
 /*
  * Enable the extended processor state save/restore feature
@@ -384,19 +482,21 @@ static void __init setup_xstate_features(void)
 /*
  * setup the xstate image representing the init state
  */
-static void __init setup_xstate_init(void)
+static void __init setup_init_fpu_buf(void)
 {
-	setup_xstate_features();
-
 	/*
 	 * Setup init_xstate_buf to represent the init state of
 	 * all the features managed by the xsave
 	 */
 	init_xstate_buf = alloc_bootmem_align(xstate_size,
 					      __alignof__(struct xsave_struct));
-	init_xstate_buf->i387.mxcsr = MXCSR_DEFAULT;
+	fx_finit(&init_xstate_buf->i387);
+
+	if (!cpu_has_xsave)
+		return;
+
+	setup_xstate_features();
 
-	clts();
 	/*
 	 * Init all the features state with header_bv being 0x0
 	 */
@@ -406,9 +506,21 @@ static void __init setup_xstate_init(void)
 	 * of any feature which is not represented by all zero's.
 	 */
 	xsave_state(init_xstate_buf, -1);
-	stts();
 }
 
+static enum { AUTO, ENABLE, DISABLE } eagerfpu = AUTO;
+static int __init eager_fpu_setup(char *s)
+{
+	if (!strcmp(s, "on"))
+		eagerfpu = ENABLE;
+	else if (!strcmp(s, "off"))
+		eagerfpu = DISABLE;
+	else if (!strcmp(s, "auto"))
+		eagerfpu = AUTO;
+	return 1;
+}
+__setup("eagerfpu=", eager_fpu_setup);
+
 /*
  * Enable and initialize the xsave feature.
  */
@@ -445,8 +557,11 @@ static void __init xstate_enable_boot_cpu(void)
 
 	update_regset_xstate_info(xstate_size, pcntxt_mask);
 	prepare_fx_sw_frame();
+	setup_init_fpu_buf();
 
-	setup_xstate_init();
+	/* Auto enable eagerfpu for xsaveopt */
+	if (cpu_has_xsaveopt && eagerfpu != DISABLE)
+		eagerfpu = ENABLE;
 
 	pr_info("enabled xstate_bv 0x%llx, cntxt size 0x%x\n",
 		pcntxt_mask, xstate_size);
@@ -471,3 +586,43 @@ void __cpuinit xsave_init(void)
 	next_func = xstate_enable;
 	this_func();
 }
+
+static inline void __init eager_fpu_init_bp(void)
+{
+	current->thread.fpu.state =
+	    alloc_bootmem_align(xstate_size, __alignof__(struct xsave_struct));
+	if (!init_xstate_buf)
+		setup_init_fpu_buf();
+}
+
+void __cpuinit eager_fpu_init(void)
+{
+	static __refdata void (*boot_func)(void) = eager_fpu_init_bp;
+
+	clear_used_math();
+	current_thread_info()->status = 0;
+
+	if (eagerfpu == ENABLE)
+		setup_force_cpu_cap(X86_FEATURE_EAGER_FPU);
+
+	if (!cpu_has_eager_fpu) {
+		stts();
+		return;
+	}
+
+	if (boot_func) {
+		boot_func();
+		boot_func = NULL;
+	}
+
+	/*
+	 * This is same as math_state_restore(). But use_xsave() is
+	 * not yet patched to use math_state_restore().
+	 */
+	init_fpu(current);
+	__thread_fpu_begin(current);
+	if (cpu_has_xsave)
+		xrstor_state(init_xstate_buf, -1);
+	else
+		fxrstor_checking(&init_xstate_buf->i387);
+}
diff --git a/arch/x86/kvm/Kconfig b/arch/x86/kvm/Kconfig
index a28f338..586f000 100644
--- a/arch/x86/kvm/Kconfig
+++ b/arch/x86/kvm/Kconfig
@@ -20,6 +20,7 @@ if VIRTUALIZATION
 config KVM
 	tristate "Kernel-based Virtual Machine (KVM) support"
 	depends on HAVE_KVM
+	depends on HIGH_RES_TIMERS
 	# for device assignment:
 	depends on PCI
 	# for TASKSTATS/TASK_DELAY_ACCT:
@@ -37,6 +38,7 @@ config KVM
 	select TASK_DELAY_ACCT
 	select PERF_EVENTS
 	select HAVE_KVM_MSI
+	select HAVE_KVM_CPU_RELAX_INTERCEPT
 	---help---
 	  Support hosting fully virtualized guest machines using hardware
 	  virtualization extensions.  You will need a fairly recent
diff --git a/arch/x86/kvm/Makefile b/arch/x86/kvm/Makefile
index 4f579e8..04d3040 100644
--- a/arch/x86/kvm/Makefile
+++ b/arch/x86/kvm/Makefile
@@ -12,7 +12,7 @@ kvm-$(CONFIG_IOMMU_API)	+= $(addprefix ../../../virt/kvm/, iommu.o)
 kvm-$(CONFIG_KVM_ASYNC_PF)	+= $(addprefix ../../../virt/kvm/, async_pf.o)
 
 kvm-y			+= x86.o mmu.o emulate.o i8259.o irq.o lapic.o \
-			   i8254.o timer.o cpuid.o pmu.o
+			   i8254.o cpuid.o pmu.o
 kvm-intel-y		+= vmx.o
 kvm-amd-y		+= svm.o
 
diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
index 0595f13..ec79e77 100644
--- a/arch/x86/kvm/cpuid.c
+++ b/arch/x86/kvm/cpuid.c
@@ -316,7 +316,7 @@ static int do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
 	}
 	case 7: {
 		entry->flags |= KVM_CPUID_FLAG_SIGNIFCANT_INDEX;
-		/* Mask ebx against host capbability word 9 */
+		/* Mask ebx against host capability word 9 */
 		if (index == 0) {
 			entry->ebx &= kvm_supported_word9_x86_features;
 			cpuid_mask(&entry->ebx, 9);
@@ -397,8 +397,8 @@ static int do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
 		break;
 	}
 	case KVM_CPUID_SIGNATURE: {
-		char signature[12] = "KVMKVMKVM\0\0";
-		u32 *sigptr = (u32 *)signature;
+		static const char signature[12] = "KVMKVMKVM\0\0";
+		const u32 *sigptr = (const u32 *)signature;
 		entry->eax = KVM_CPUID_FEATURES;
 		entry->ebx = sigptr[0];
 		entry->ecx = sigptr[1];
@@ -484,10 +484,10 @@ struct kvm_cpuid_param {
 	u32 func;
 	u32 idx;
 	bool has_leaf_count;
-	bool (*qualifier)(struct kvm_cpuid_param *param);
+	bool (*qualifier)(const struct kvm_cpuid_param *param);
 };
 
-static bool is_centaur_cpu(struct kvm_cpuid_param *param)
+static bool is_centaur_cpu(const struct kvm_cpuid_param *param)
 {
 	return boot_cpu_data.x86_vendor == X86_VENDOR_CENTAUR;
 }
@@ -498,7 +498,7 @@ int kvm_dev_ioctl_get_supported_cpuid(struct kvm_cpuid2 *cpuid,
 	struct kvm_cpuid_entry2 *cpuid_entries;
 	int limit, nent = 0, r = -E2BIG, i;
 	u32 func;
-	static struct kvm_cpuid_param param[] = {
+	static const struct kvm_cpuid_param param[] = {
 		{ .func = 0, .has_leaf_count = true },
 		{ .func = 0x80000000, .has_leaf_count = true },
 		{ .func = 0xC0000000, .qualifier = is_centaur_cpu, .has_leaf_count = true },
@@ -517,7 +517,7 @@ int kvm_dev_ioctl_get_supported_cpuid(struct kvm_cpuid2 *cpuid,
 
 	r = 0;
 	for (i = 0; i < ARRAY_SIZE(param); i++) {
-		struct kvm_cpuid_param *ent = &param[i];
+		const struct kvm_cpuid_param *ent = &param[i];
 
 		if (ent->qualifier && !ent->qualifier(ent))
 			continue;
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index a3b57a2..39171cb 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -161,9 +161,9 @@ struct opcode {
 	u64 intercept : 8;
 	union {
 		int (*execute)(struct x86_emulate_ctxt *ctxt);
-		struct opcode *group;
-		struct group_dual *gdual;
-		struct gprefix *gprefix;
+		const struct opcode *group;
+		const struct group_dual *gdual;
+		const struct gprefix *gprefix;
 	} u;
 	int (*check_perm)(struct x86_emulate_ctxt *ctxt);
 };
@@ -202,6 +202,42 @@ struct gprefix {
 #define EFLG_RESERVED_ZEROS_MASK 0xffc0802a
 #define EFLG_RESERVED_ONE_MASK 2
 
+static ulong reg_read(struct x86_emulate_ctxt *ctxt, unsigned nr)
+{
+	if (!(ctxt->regs_valid & (1 << nr))) {
+		ctxt->regs_valid |= 1 << nr;
+		ctxt->_regs[nr] = ctxt->ops->read_gpr(ctxt, nr);
+	}
+	return ctxt->_regs[nr];
+}
+
+static ulong *reg_write(struct x86_emulate_ctxt *ctxt, unsigned nr)
+{
+	ctxt->regs_valid |= 1 << nr;
+	ctxt->regs_dirty |= 1 << nr;
+	return &ctxt->_regs[nr];
+}
+
+static ulong *reg_rmw(struct x86_emulate_ctxt *ctxt, unsigned nr)
+{
+	reg_read(ctxt, nr);
+	return reg_write(ctxt, nr);
+}
+
+static void writeback_registers(struct x86_emulate_ctxt *ctxt)
+{
+	unsigned reg;
+
+	for_each_set_bit(reg, (ulong *)&ctxt->regs_dirty, 16)
+		ctxt->ops->write_gpr(ctxt, reg, ctxt->_regs[reg]);
+}
+
+static void invalidate_registers(struct x86_emulate_ctxt *ctxt)
+{
+	ctxt->regs_dirty = 0;
+	ctxt->regs_valid = 0;
+}
+
 /*
  * Instruction emulation:
  * Most instructions are emulated directly via a fragment of inline assembly
@@ -374,8 +410,8 @@ struct gprefix {
 #define __emulate_1op_rax_rdx(ctxt, _op, _suffix, _ex)			\
 	do {								\
 		unsigned long _tmp;					\
-		ulong *rax = &(ctxt)->regs[VCPU_REGS_RAX];		\
-		ulong *rdx = &(ctxt)->regs[VCPU_REGS_RDX];		\
+		ulong *rax = reg_rmw((ctxt), VCPU_REGS_RAX);		\
+		ulong *rdx = reg_rmw((ctxt), VCPU_REGS_RDX);		\
 									\
 		__asm__ __volatile__ (					\
 			_PRE_EFLAGS("0", "5", "1")			\
@@ -494,7 +530,7 @@ register_address_increment(struct x86_emulate_ctxt *ctxt, unsigned long *reg, in
 
 static void rsp_increment(struct x86_emulate_ctxt *ctxt, int inc)
 {
-	masked_increment(&ctxt->regs[VCPU_REGS_RSP], stack_mask(ctxt), inc);
+	masked_increment(reg_rmw(ctxt, VCPU_REGS_RSP), stack_mask(ctxt), inc);
 }
 
 static inline void jmp_rel(struct x86_emulate_ctxt *ctxt, int rel)
@@ -632,8 +668,6 @@ static int __linearize(struct x86_emulate_ctxt *ctxt,
 
 	la = seg_base(ctxt, addr.seg) + addr.ea;
 	switch (ctxt->mode) {
-	case X86EMUL_MODE_REAL:
-		break;
 	case X86EMUL_MODE_PROT64:
 		if (((signed long)la << 16) >> 16 != la)
 			return emulate_gp(ctxt, 0);
@@ -655,7 +689,7 @@ static int __linearize(struct x86_emulate_ctxt *ctxt,
 			if (addr.ea > lim || (u32)(addr.ea + size - 1) > lim)
 				goto bad;
 		} else {
-			/* exapand-down segment */
+			/* expand-down segment */
 			if (addr.ea <= lim || (u32)(addr.ea + size - 1) <= lim)
 				goto bad;
 			lim = desc.d ? 0xffffffff : 0xffff;
@@ -663,7 +697,10 @@ static int __linearize(struct x86_emulate_ctxt *ctxt,
 				goto bad;
 		}
 		cpl = ctxt->ops->cpl(ctxt);
-		rpl = sel & 3;
+		if (ctxt->mode == X86EMUL_MODE_REAL)
+			rpl = 0;
+		else
+			rpl = sel & 3;
 		cpl = max(cpl, rpl);
 		if (!(desc.type & 8)) {
 			/* data segment */
@@ -688,9 +725,9 @@ static int __linearize(struct x86_emulate_ctxt *ctxt,
 	return X86EMUL_CONTINUE;
 bad:
 	if (addr.seg == VCPU_SREG_SS)
-		return emulate_ss(ctxt, addr.seg);
+		return emulate_ss(ctxt, sel);
 	else
-		return emulate_gp(ctxt, addr.seg);
+		return emulate_gp(ctxt, sel);
 }
 
 static int linearize(struct x86_emulate_ctxt *ctxt,
@@ -786,14 +823,15 @@ static int do_insn_fetch(struct x86_emulate_ctxt *ctxt,
  * pointer into the block that addresses the relevant register.
  * @highbyte_regs specifies whether to decode AH,CH,DH,BH.
  */
-static void *decode_register(u8 modrm_reg, unsigned long *regs,
+static void *decode_register(struct x86_emulate_ctxt *ctxt, u8 modrm_reg,
 			     int highbyte_regs)
 {
 	void *p;
 
-	p = &regs[modrm_reg];
 	if (highbyte_regs && modrm_reg >= 4 && modrm_reg < 8)
-		p = (unsigned char *)&regs[modrm_reg & 3] + 1;
+		p = (unsigned char *)reg_rmw(ctxt, modrm_reg & 3) + 1;
+	else
+		p = reg_rmw(ctxt, modrm_reg);
 	return p;
 }
 
@@ -871,23 +909,23 @@ static void read_sse_reg(struct x86_emulate_ctxt *ctxt, sse128_t *data, int reg)
 {
 	ctxt->ops->get_fpu(ctxt);
 	switch (reg) {
-	case 0: asm("movdqu %%xmm0, %0" : "=m"(*data)); break;
-	case 1: asm("movdqu %%xmm1, %0" : "=m"(*data)); break;
-	case 2: asm("movdqu %%xmm2, %0" : "=m"(*data)); break;
-	case 3: asm("movdqu %%xmm3, %0" : "=m"(*data)); break;
-	case 4: asm("movdqu %%xmm4, %0" : "=m"(*data)); break;
-	case 5: asm("movdqu %%xmm5, %0" : "=m"(*data)); break;
-	case 6: asm("movdqu %%xmm6, %0" : "=m"(*data)); break;
-	case 7: asm("movdqu %%xmm7, %0" : "=m"(*data)); break;
+	case 0: asm("movdqa %%xmm0, %0" : "=m"(*data)); break;
+	case 1: asm("movdqa %%xmm1, %0" : "=m"(*data)); break;
+	case 2: asm("movdqa %%xmm2, %0" : "=m"(*data)); break;
+	case 3: asm("movdqa %%xmm3, %0" : "=m"(*data)); break;
+	case 4: asm("movdqa %%xmm4, %0" : "=m"(*data)); break;
+	case 5: asm("movdqa %%xmm5, %0" : "=m"(*data)); break;
+	case 6: asm("movdqa %%xmm6, %0" : "=m"(*data)); break;
+	case 7: asm("movdqa %%xmm7, %0" : "=m"(*data)); break;
 #ifdef CONFIG_X86_64
-	case 8: asm("movdqu %%xmm8, %0" : "=m"(*data)); break;
-	case 9: asm("movdqu %%xmm9, %0" : "=m"(*data)); break;
-	case 10: asm("movdqu %%xmm10, %0" : "=m"(*data)); break;
-	case 11: asm("movdqu %%xmm11, %0" : "=m"(*data)); break;
-	case 12: asm("movdqu %%xmm12, %0" : "=m"(*data)); break;
-	case 13: asm("movdqu %%xmm13, %0" : "=m"(*data)); break;
-	case 14: asm("movdqu %%xmm14, %0" : "=m"(*data)); break;
-	case 15: asm("movdqu %%xmm15, %0" : "=m"(*data)); break;
+	case 8: asm("movdqa %%xmm8, %0" : "=m"(*data)); break;
+	case 9: asm("movdqa %%xmm9, %0" : "=m"(*data)); break;
+	case 10: asm("movdqa %%xmm10, %0" : "=m"(*data)); break;
+	case 11: asm("movdqa %%xmm11, %0" : "=m"(*data)); break;
+	case 12: asm("movdqa %%xmm12, %0" : "=m"(*data)); break;
+	case 13: asm("movdqa %%xmm13, %0" : "=m"(*data)); break;
+	case 14: asm("movdqa %%xmm14, %0" : "=m"(*data)); break;
+	case 15: asm("movdqa %%xmm15, %0" : "=m"(*data)); break;
 #endif
 	default: BUG();
 	}
@@ -899,23 +937,23 @@ static void write_sse_reg(struct x86_emulate_ctxt *ctxt, sse128_t *data,
 {
 	ctxt->ops->get_fpu(ctxt);
 	switch (reg) {
-	case 0: asm("movdqu %0, %%xmm0" : : "m"(*data)); break;
-	case 1: asm("movdqu %0, %%xmm1" : : "m"(*data)); break;
-	case 2: asm("movdqu %0, %%xmm2" : : "m"(*data)); break;
-	case 3: asm("movdqu %0, %%xmm3" : : "m"(*data)); break;
-	case 4: asm("movdqu %0, %%xmm4" : : "m"(*data)); break;
-	case 5: asm("movdqu %0, %%xmm5" : : "m"(*data)); break;
-	case 6: asm("movdqu %0, %%xmm6" : : "m"(*data)); break;
-	case 7: asm("movdqu %0, %%xmm7" : : "m"(*data)); break;
+	case 0: asm("movdqa %0, %%xmm0" : : "m"(*data)); break;
+	case 1: asm("movdqa %0, %%xmm1" : : "m"(*data)); break;
+	case 2: asm("movdqa %0, %%xmm2" : : "m"(*data)); break;
+	case 3: asm("movdqa %0, %%xmm3" : : "m"(*data)); break;
+	case 4: asm("movdqa %0, %%xmm4" : : "m"(*data)); break;
+	case 5: asm("movdqa %0, %%xmm5" : : "m"(*data)); break;
+	case 6: asm("movdqa %0, %%xmm6" : : "m"(*data)); break;
+	case 7: asm("movdqa %0, %%xmm7" : : "m"(*data)); break;
 #ifdef CONFIG_X86_64
-	case 8: asm("movdqu %0, %%xmm8" : : "m"(*data)); break;
-	case 9: asm("movdqu %0, %%xmm9" : : "m"(*data)); break;
-	case 10: asm("movdqu %0, %%xmm10" : : "m"(*data)); break;
-	case 11: asm("movdqu %0, %%xmm11" : : "m"(*data)); break;
-	case 12: asm("movdqu %0, %%xmm12" : : "m"(*data)); break;
-	case 13: asm("movdqu %0, %%xmm13" : : "m"(*data)); break;
-	case 14: asm("movdqu %0, %%xmm14" : : "m"(*data)); break;
-	case 15: asm("movdqu %0, %%xmm15" : : "m"(*data)); break;
+	case 8: asm("movdqa %0, %%xmm8" : : "m"(*data)); break;
+	case 9: asm("movdqa %0, %%xmm9" : : "m"(*data)); break;
+	case 10: asm("movdqa %0, %%xmm10" : : "m"(*data)); break;
+	case 11: asm("movdqa %0, %%xmm11" : : "m"(*data)); break;
+	case 12: asm("movdqa %0, %%xmm12" : : "m"(*data)); break;
+	case 13: asm("movdqa %0, %%xmm13" : : "m"(*data)); break;
+	case 14: asm("movdqa %0, %%xmm14" : : "m"(*data)); break;
+	case 15: asm("movdqa %0, %%xmm15" : : "m"(*data)); break;
 #endif
 	default: BUG();
 	}
@@ -982,10 +1020,10 @@ static void decode_register_operand(struct x86_emulate_ctxt *ctxt,
 
 	op->type = OP_REG;
 	if (ctxt->d & ByteOp) {
-		op->addr.reg = decode_register(reg, ctxt->regs, highbyte_regs);
+		op->addr.reg = decode_register(ctxt, reg, highbyte_regs);
 		op->bytes = 1;
 	} else {
-		op->addr.reg = decode_register(reg, ctxt->regs, 0);
+		op->addr.reg = decode_register(ctxt, reg, 0);
 		op->bytes = ctxt->op_bytes;
 	}
 	fetch_register_operand(op);
@@ -1020,8 +1058,7 @@ static int decode_modrm(struct x86_emulate_ctxt *ctxt,
 	if (ctxt->modrm_mod == 3) {
 		op->type = OP_REG;
 		op->bytes = (ctxt->d & ByteOp) ? 1 : ctxt->op_bytes;
-		op->addr.reg = decode_register(ctxt->modrm_rm,
-					       ctxt->regs, ctxt->d & ByteOp);
+		op->addr.reg = decode_register(ctxt, ctxt->modrm_rm, ctxt->d & ByteOp);
 		if (ctxt->d & Sse) {
 			op->type = OP_XMM;
 			op->bytes = 16;
@@ -1042,10 +1079,10 @@ static int decode_modrm(struct x86_emulate_ctxt *ctxt,
 	op->type = OP_MEM;
 
 	if (ctxt->ad_bytes == 2) {
-		unsigned bx = ctxt->regs[VCPU_REGS_RBX];
-		unsigned bp = ctxt->regs[VCPU_REGS_RBP];
-		unsigned si = ctxt->regs[VCPU_REGS_RSI];
-		unsigned di = ctxt->regs[VCPU_REGS_RDI];
+		unsigned bx = reg_read(ctxt, VCPU_REGS_RBX);
+		unsigned bp = reg_read(ctxt, VCPU_REGS_RBP);
+		unsigned si = reg_read(ctxt, VCPU_REGS_RSI);
+		unsigned di = reg_read(ctxt, VCPU_REGS_RDI);
 
 		/* 16-bit ModR/M decode. */
 		switch (ctxt->modrm_mod) {
@@ -1102,17 +1139,17 @@ static int decode_modrm(struct x86_emulate_ctxt *ctxt,
 			if ((base_reg & 7) == 5 && ctxt->modrm_mod == 0)
 				modrm_ea += insn_fetch(s32, ctxt);
 			else {
-				modrm_ea += ctxt->regs[base_reg];
+				modrm_ea += reg_read(ctxt, base_reg);
 				adjust_modrm_seg(ctxt, base_reg);
 			}
 			if (index_reg != 4)
-				modrm_ea += ctxt->regs[index_reg] << scale;
+				modrm_ea += reg_read(ctxt, index_reg) << scale;
 		} else if ((ctxt->modrm_rm & 7) == 5 && ctxt->modrm_mod == 0) {
 			if (ctxt->mode == X86EMUL_MODE_PROT64)
 				ctxt->rip_relative = 1;
 		} else {
 			base_reg = ctxt->modrm_rm;
-			modrm_ea += ctxt->regs[base_reg];
+			modrm_ea += reg_read(ctxt, base_reg);
 			adjust_modrm_seg(ctxt, base_reg);
 		}
 		switch (ctxt->modrm_mod) {
@@ -1179,24 +1216,21 @@ static int read_emulated(struct x86_emulate_ctxt *ctxt,
 	int rc;
 	struct read_cache *mc = &ctxt->mem_read;
 
-	while (size) {
-		int n = min(size, 8u);
-		size -= n;
-		if (mc->pos < mc->end)
-			goto read_cached;
+	if (mc->pos < mc->end)
+		goto read_cached;
 
-		rc = ctxt->ops->read_emulated(ctxt, addr, mc->data + mc->end, n,
-					      &ctxt->exception);
-		if (rc != X86EMUL_CONTINUE)
-			return rc;
-		mc->end += n;
+	WARN_ON((mc->end + size) >= sizeof(mc->data));
 
-	read_cached:
-		memcpy(dest, mc->data + mc->pos, n);
-		mc->pos += n;
-		dest += n;
-		addr += n;
-	}
+	rc = ctxt->ops->read_emulated(ctxt, addr, mc->data + mc->end, size,
+				      &ctxt->exception);
+	if (rc != X86EMUL_CONTINUE)
+		return rc;
+
+	mc->end += size;
+
+read_cached:
+	memcpy(dest, mc->data + mc->pos, size);
+	mc->pos += size;
 	return X86EMUL_CONTINUE;
 }
 
@@ -1253,10 +1287,10 @@ static int pio_in_emulated(struct x86_emulate_ctxt *ctxt,
 	if (rc->pos == rc->end) { /* refill pio read ahead */
 		unsigned int in_page, n;
 		unsigned int count = ctxt->rep_prefix ?
-			address_mask(ctxt, ctxt->regs[VCPU_REGS_RCX]) : 1;
+			address_mask(ctxt, reg_read(ctxt, VCPU_REGS_RCX)) : 1;
 		in_page = (ctxt->eflags & EFLG_DF) ?
-			offset_in_page(ctxt->regs[VCPU_REGS_RDI]) :
-			PAGE_SIZE - offset_in_page(ctxt->regs[VCPU_REGS_RDI]);
+			offset_in_page(reg_read(ctxt, VCPU_REGS_RDI)) :
+			PAGE_SIZE - offset_in_page(reg_read(ctxt, VCPU_REGS_RDI));
 		n = min(min(in_page, (unsigned int)sizeof(rc->data)) / size,
 			count);
 		if (n == 0)
@@ -1267,8 +1301,15 @@ static int pio_in_emulated(struct x86_emulate_ctxt *ctxt,
 		rc->end = n * size;
 	}
 
-	memcpy(dest, rc->data + rc->pos, size);
-	rc->pos += size;
+	if (ctxt->rep_prefix && !(ctxt->eflags & EFLG_DF)) {
+		ctxt->dst.data = rc->data + rc->pos;
+		ctxt->dst.type = OP_MEM_STR;
+		ctxt->dst.count = (rc->end - rc->pos) / size;
+		rc->pos = rc->end;
+	} else {
+		memcpy(dest, rc->data + rc->pos, size);
+		rc->pos += size;
+	}
 	return 1;
 }
 
@@ -1291,7 +1332,7 @@ static int read_interrupt_descriptor(struct x86_emulate_ctxt *ctxt,
 static void get_descriptor_table_ptr(struct x86_emulate_ctxt *ctxt,
 				     u16 selector, struct desc_ptr *dt)
 {
-	struct x86_emulate_ops *ops = ctxt->ops;
+	const struct x86_emulate_ops *ops = ctxt->ops;
 
 	if (selector & 1 << 2) {
 		struct desc_struct desc;
@@ -1355,19 +1396,15 @@ static int load_segment_descriptor(struct x86_emulate_ctxt *ctxt,
 	bool null_selector = !(selector & ~0x3); /* 0000-0003 are null */
 	ulong desc_addr;
 	int ret;
+	u16 dummy;
 
 	memset(&seg_desc, 0, sizeof seg_desc);
 
 	if ((seg <= VCPU_SREG_GS && ctxt->mode == X86EMUL_MODE_VM86)
 	    || ctxt->mode == X86EMUL_MODE_REAL) {
 		/* set real mode segment descriptor */
+		ctxt->ops->get_segment(ctxt, &dummy, &seg_desc, NULL, seg);
 		set_desc_base(&seg_desc, selector << 4);
-		set_desc_limit(&seg_desc, 0xffff);
-		seg_desc.type = 3;
-		seg_desc.p = 1;
-		seg_desc.s = 1;
-		if (ctxt->mode == X86EMUL_MODE_VM86)
-			seg_desc.dpl = 3;
 		goto load;
 	}
 
@@ -1396,7 +1433,7 @@ static int load_segment_descriptor(struct x86_emulate_ctxt *ctxt,
 	err_code = selector & 0xfffc;
 	err_vec = GP_VECTOR;
 
-	/* can't load system descriptor into segment selecor */
+	/* can't load system descriptor into segment selector */
 	if (seg <= VCPU_SREG_GS && !seg_desc.s)
 		goto exception;
 
@@ -1516,6 +1553,14 @@ static int writeback(struct x86_emulate_ctxt *ctxt)
 		if (rc != X86EMUL_CONTINUE)
 			return rc;
 		break;
+	case OP_MEM_STR:
+		rc = segmented_write(ctxt,
+				ctxt->dst.addr.mem,
+				ctxt->dst.data,
+				ctxt->dst.bytes * ctxt->dst.count);
+		if (rc != X86EMUL_CONTINUE)
+			return rc;
+		break;
 	case OP_XMM:
 		write_sse_reg(ctxt, &ctxt->dst.vec_val, ctxt->dst.addr.xmm);
 		break;
@@ -1536,7 +1581,7 @@ static int push(struct x86_emulate_ctxt *ctxt, void *data, int bytes)
 	struct segmented_address addr;
 
 	rsp_increment(ctxt, -bytes);
-	addr.ea = ctxt->regs[VCPU_REGS_RSP] & stack_mask(ctxt);
+	addr.ea = reg_read(ctxt, VCPU_REGS_RSP) & stack_mask(ctxt);
 	addr.seg = VCPU_SREG_SS;
 
 	return segmented_write(ctxt, addr, data, bytes);
@@ -1555,7 +1600,7 @@ static int emulate_pop(struct x86_emulate_ctxt *ctxt,
 	int rc;
 	struct segmented_address addr;
 
-	addr.ea = ctxt->regs[VCPU_REGS_RSP] & stack_mask(ctxt);
+	addr.ea = reg_read(ctxt, VCPU_REGS_RSP) & stack_mask(ctxt);
 	addr.seg = VCPU_SREG_SS;
 	rc = segmented_read(ctxt, addr, dest, len);
 	if (rc != X86EMUL_CONTINUE)
@@ -1623,26 +1668,28 @@ static int em_enter(struct x86_emulate_ctxt *ctxt)
 	int rc;
 	unsigned frame_size = ctxt->src.val;
 	unsigned nesting_level = ctxt->src2.val & 31;
+	ulong rbp;
 
 	if (nesting_level)
 		return X86EMUL_UNHANDLEABLE;
 
-	rc = push(ctxt, &ctxt->regs[VCPU_REGS_RBP], stack_size(ctxt));
+	rbp = reg_read(ctxt, VCPU_REGS_RBP);
+	rc = push(ctxt, &rbp, stack_size(ctxt));
 	if (rc != X86EMUL_CONTINUE)
 		return rc;
-	assign_masked(&ctxt->regs[VCPU_REGS_RBP], ctxt->regs[VCPU_REGS_RSP],
+	assign_masked(reg_rmw(ctxt, VCPU_REGS_RBP), reg_read(ctxt, VCPU_REGS_RSP),
 		      stack_mask(ctxt));
-	assign_masked(&ctxt->regs[VCPU_REGS_RSP],
-		      ctxt->regs[VCPU_REGS_RSP] - frame_size,
+	assign_masked(reg_rmw(ctxt, VCPU_REGS_RSP),
+		      reg_read(ctxt, VCPU_REGS_RSP) - frame_size,
 		      stack_mask(ctxt));
 	return X86EMUL_CONTINUE;
 }
 
 static int em_leave(struct x86_emulate_ctxt *ctxt)
 {
-	assign_masked(&ctxt->regs[VCPU_REGS_RSP], ctxt->regs[VCPU_REGS_RBP],
+	assign_masked(reg_rmw(ctxt, VCPU_REGS_RSP), reg_read(ctxt, VCPU_REGS_RBP),
 		      stack_mask(ctxt));
-	return emulate_pop(ctxt, &ctxt->regs[VCPU_REGS_RBP], ctxt->op_bytes);
+	return emulate_pop(ctxt, reg_rmw(ctxt, VCPU_REGS_RBP), ctxt->op_bytes);
 }
 
 static int em_push_sreg(struct x86_emulate_ctxt *ctxt)
@@ -1670,13 +1717,13 @@ static int em_pop_sreg(struct x86_emulate_ctxt *ctxt)
 
 static int em_pusha(struct x86_emulate_ctxt *ctxt)
 {
-	unsigned long old_esp = ctxt->regs[VCPU_REGS_RSP];
+	unsigned long old_esp = reg_read(ctxt, VCPU_REGS_RSP);
 	int rc = X86EMUL_CONTINUE;
 	int reg = VCPU_REGS_RAX;
 
 	while (reg <= VCPU_REGS_RDI) {
 		(reg == VCPU_REGS_RSP) ?
-		(ctxt->src.val = old_esp) : (ctxt->src.val = ctxt->regs[reg]);
+		(ctxt->src.val = old_esp) : (ctxt->src.val = reg_read(ctxt, reg));
 
 		rc = em_push(ctxt);
 		if (rc != X86EMUL_CONTINUE)
@@ -1705,7 +1752,7 @@ static int em_popa(struct x86_emulate_ctxt *ctxt)
 			--reg;
 		}
 
-		rc = emulate_pop(ctxt, &ctxt->regs[reg], ctxt->op_bytes);
+		rc = emulate_pop(ctxt, reg_rmw(ctxt, reg), ctxt->op_bytes);
 		if (rc != X86EMUL_CONTINUE)
 			break;
 		--reg;
@@ -1713,9 +1760,9 @@ static int em_popa(struct x86_emulate_ctxt *ctxt)
 	return rc;
 }
 
-int emulate_int_real(struct x86_emulate_ctxt *ctxt, int irq)
+static int __emulate_int_real(struct x86_emulate_ctxt *ctxt, int irq)
 {
-	struct x86_emulate_ops *ops = ctxt->ops;
+	const struct x86_emulate_ops *ops = ctxt->ops;
 	int rc;
 	struct desc_ptr dt;
 	gva_t cs_addr;
@@ -1762,11 +1809,22 @@ int emulate_int_real(struct x86_emulate_ctxt *ctxt, int irq)
 	return rc;
 }
 
+int emulate_int_real(struct x86_emulate_ctxt *ctxt, int irq)
+{
+	int rc;
+
+	invalidate_registers(ctxt);
+	rc = __emulate_int_real(ctxt, irq);
+	if (rc == X86EMUL_CONTINUE)
+		writeback_registers(ctxt);
+	return rc;
+}
+
 static int emulate_int(struct x86_emulate_ctxt *ctxt, int irq)
 {
 	switch(ctxt->mode) {
 	case X86EMUL_MODE_REAL:
-		return emulate_int_real(ctxt, irq);
+		return __emulate_int_real(ctxt, irq);
 	case X86EMUL_MODE_VM86:
 	case X86EMUL_MODE_PROT16:
 	case X86EMUL_MODE_PROT32:
@@ -1973,14 +2031,14 @@ static int em_cmpxchg8b(struct x86_emulate_ctxt *ctxt)
 {
 	u64 old = ctxt->dst.orig_val64;
 
-	if (((u32) (old >> 0) != (u32) ctxt->regs[VCPU_REGS_RAX]) ||
-	    ((u32) (old >> 32) != (u32) ctxt->regs[VCPU_REGS_RDX])) {
-		ctxt->regs[VCPU_REGS_RAX] = (u32) (old >> 0);
-		ctxt->regs[VCPU_REGS_RDX] = (u32) (old >> 32);
+	if (((u32) (old >> 0) != (u32) reg_read(ctxt, VCPU_REGS_RAX)) ||
+	    ((u32) (old >> 32) != (u32) reg_read(ctxt, VCPU_REGS_RDX))) {
+		*reg_write(ctxt, VCPU_REGS_RAX) = (u32) (old >> 0);
+		*reg_write(ctxt, VCPU_REGS_RDX) = (u32) (old >> 32);
 		ctxt->eflags &= ~EFLG_ZF;
 	} else {
-		ctxt->dst.val64 = ((u64)ctxt->regs[VCPU_REGS_RCX] << 32) |
-			(u32) ctxt->regs[VCPU_REGS_RBX];
+		ctxt->dst.val64 = ((u64)reg_read(ctxt, VCPU_REGS_RCX) << 32) |
+			(u32) reg_read(ctxt, VCPU_REGS_RBX);
 
 		ctxt->eflags |= EFLG_ZF;
 	}
@@ -2016,7 +2074,7 @@ static int em_cmpxchg(struct x86_emulate_ctxt *ctxt)
 {
 	/* Save real source value, then compare EAX against destination. */
 	ctxt->src.orig_val = ctxt->src.val;
-	ctxt->src.val = ctxt->regs[VCPU_REGS_RAX];
+	ctxt->src.val = reg_read(ctxt, VCPU_REGS_RAX);
 	emulate_2op_SrcV(ctxt, "cmp");
 
 	if (ctxt->eflags & EFLG_ZF) {
@@ -2025,7 +2083,7 @@ static int em_cmpxchg(struct x86_emulate_ctxt *ctxt)
 	} else {
 		/* Failure: write the value we saw to EAX. */
 		ctxt->dst.type = OP_REG;
-		ctxt->dst.addr.reg = (unsigned long *)&ctxt->regs[VCPU_REGS_RAX];
+		ctxt->dst.addr.reg = reg_rmw(ctxt, VCPU_REGS_RAX);
 	}
 	return X86EMUL_CONTINUE;
 }
@@ -2050,12 +2108,6 @@ static void
 setup_syscalls_segments(struct x86_emulate_ctxt *ctxt,
 			struct desc_struct *cs, struct desc_struct *ss)
 {
-	u16 selector;
-
-	memset(cs, 0, sizeof(struct desc_struct));
-	ctxt->ops->get_segment(ctxt, &selector, cs, NULL, VCPU_SREG_CS);
-	memset(ss, 0, sizeof(struct desc_struct));
-
 	cs->l = 0;		/* will be adjusted later */
 	set_desc_base(cs, 0);	/* flat segment */
 	cs->g = 1;		/* 4kb granularity */
@@ -2065,6 +2117,7 @@ setup_syscalls_segments(struct x86_emulate_ctxt *ctxt,
 	cs->dpl = 0;		/* will be adjusted later */
 	cs->p = 1;
 	cs->d = 1;
+	cs->avl = 0;
 
 	set_desc_base(ss, 0);	/* flat segment */
 	set_desc_limit(ss, 0xfffff);	/* 4GB limit */
@@ -2074,6 +2127,8 @@ setup_syscalls_segments(struct x86_emulate_ctxt *ctxt,
 	ss->d = 1;		/* 32bit stack segment */
 	ss->dpl = 0;
 	ss->p = 1;
+	ss->l = 0;
+	ss->avl = 0;
 }
 
 static bool vendor_intel(struct x86_emulate_ctxt *ctxt)
@@ -2089,7 +2144,7 @@ static bool vendor_intel(struct x86_emulate_ctxt *ctxt)
 
 static bool em_syscall_is_enabled(struct x86_emulate_ctxt *ctxt)
 {
-	struct x86_emulate_ops *ops = ctxt->ops;
+	const struct x86_emulate_ops *ops = ctxt->ops;
 	u32 eax, ebx, ecx, edx;
 
 	/*
@@ -2133,7 +2188,7 @@ static bool em_syscall_is_enabled(struct x86_emulate_ctxt *ctxt)
 
 static int em_syscall(struct x86_emulate_ctxt *ctxt)
 {
-	struct x86_emulate_ops *ops = ctxt->ops;
+	const struct x86_emulate_ops *ops = ctxt->ops;
 	struct desc_struct cs, ss;
 	u64 msr_data;
 	u16 cs_sel, ss_sel;
@@ -2165,10 +2220,10 @@ static int em_syscall(struct x86_emulate_ctxt *ctxt)
 	ops->set_segment(ctxt, cs_sel, &cs, 0, VCPU_SREG_CS);
 	ops->set_segment(ctxt, ss_sel, &ss, 0, VCPU_SREG_SS);
 
-	ctxt->regs[VCPU_REGS_RCX] = ctxt->_eip;
+	*reg_write(ctxt, VCPU_REGS_RCX) = ctxt->_eip;
 	if (efer & EFER_LMA) {
 #ifdef CONFIG_X86_64
-		ctxt->regs[VCPU_REGS_R11] = ctxt->eflags & ~EFLG_RF;
+		*reg_write(ctxt, VCPU_REGS_R11) = ctxt->eflags & ~EFLG_RF;
 
 		ops->get_msr(ctxt,
 			     ctxt->mode == X86EMUL_MODE_PROT64 ?
@@ -2191,7 +2246,7 @@ static int em_syscall(struct x86_emulate_ctxt *ctxt)
 
 static int em_sysenter(struct x86_emulate_ctxt *ctxt)
 {
-	struct x86_emulate_ops *ops = ctxt->ops;
+	const struct x86_emulate_ops *ops = ctxt->ops;
 	struct desc_struct cs, ss;
 	u64 msr_data;
 	u16 cs_sel, ss_sel;
@@ -2228,6 +2283,8 @@ static int em_sysenter(struct x86_emulate_ctxt *ctxt)
 		if (msr_data == 0x0)
 			return emulate_gp(ctxt, 0);
 		break;
+	default:
+		break;
 	}
 
 	ctxt->eflags &= ~(EFLG_VM | EFLG_IF | EFLG_RF);
@@ -2247,14 +2304,14 @@ static int em_sysenter(struct x86_emulate_ctxt *ctxt)
 	ctxt->_eip = msr_data;
 
 	ops->get_msr(ctxt, MSR_IA32_SYSENTER_ESP, &msr_data);
-	ctxt->regs[VCPU_REGS_RSP] = msr_data;
+	*reg_write(ctxt, VCPU_REGS_RSP) = msr_data;
 
 	return X86EMUL_CONTINUE;
 }
 
 static int em_sysexit(struct x86_emulate_ctxt *ctxt)
 {
-	struct x86_emulate_ops *ops = ctxt->ops;
+	const struct x86_emulate_ops *ops = ctxt->ops;
 	struct desc_struct cs, ss;
 	u64 msr_data;
 	int usermode;
@@ -2297,8 +2354,8 @@ static int em_sysexit(struct x86_emulate_ctxt *ctxt)
 	ops->set_segment(ctxt, cs_sel, &cs, 0, VCPU_SREG_CS);
 	ops->set_segment(ctxt, ss_sel, &ss, 0, VCPU_SREG_SS);
 
-	ctxt->_eip = ctxt->regs[VCPU_REGS_RDX];
-	ctxt->regs[VCPU_REGS_RSP] = ctxt->regs[VCPU_REGS_RCX];
+	ctxt->_eip = reg_read(ctxt, VCPU_REGS_RDX);
+	*reg_write(ctxt, VCPU_REGS_RSP) = reg_read(ctxt, VCPU_REGS_RCX);
 
 	return X86EMUL_CONTINUE;
 }
@@ -2317,7 +2374,7 @@ static bool emulator_bad_iopl(struct x86_emulate_ctxt *ctxt)
 static bool emulator_io_port_access_allowed(struct x86_emulate_ctxt *ctxt,
 					    u16 port, u16 len)
 {
-	struct x86_emulate_ops *ops = ctxt->ops;
+	const struct x86_emulate_ops *ops = ctxt->ops;
 	struct desc_struct tr_seg;
 	u32 base3;
 	int r;
@@ -2367,14 +2424,14 @@ static void save_state_to_tss16(struct x86_emulate_ctxt *ctxt,
 {
 	tss->ip = ctxt->_eip;
 	tss->flag = ctxt->eflags;
-	tss->ax = ctxt->regs[VCPU_REGS_RAX];
-	tss->cx = ctxt->regs[VCPU_REGS_RCX];
-	tss->dx = ctxt->regs[VCPU_REGS_RDX];
-	tss->bx = ctxt->regs[VCPU_REGS_RBX];
-	tss->sp = ctxt->regs[VCPU_REGS_RSP];
-	tss->bp = ctxt->regs[VCPU_REGS_RBP];
-	tss->si = ctxt->regs[VCPU_REGS_RSI];
-	tss->di = ctxt->regs[VCPU_REGS_RDI];
+	tss->ax = reg_read(ctxt, VCPU_REGS_RAX);
+	tss->cx = reg_read(ctxt, VCPU_REGS_RCX);
+	tss->dx = reg_read(ctxt, VCPU_REGS_RDX);
+	tss->bx = reg_read(ctxt, VCPU_REGS_RBX);
+	tss->sp = reg_read(ctxt, VCPU_REGS_RSP);
+	tss->bp = reg_read(ctxt, VCPU_REGS_RBP);
+	tss->si = reg_read(ctxt, VCPU_REGS_RSI);
+	tss->di = reg_read(ctxt, VCPU_REGS_RDI);
 
 	tss->es = get_segment_selector(ctxt, VCPU_SREG_ES);
 	tss->cs = get_segment_selector(ctxt, VCPU_SREG_CS);
@@ -2390,14 +2447,14 @@ static int load_state_from_tss16(struct x86_emulate_ctxt *ctxt,
 
 	ctxt->_eip = tss->ip;
 	ctxt->eflags = tss->flag | 2;
-	ctxt->regs[VCPU_REGS_RAX] = tss->ax;
-	ctxt->regs[VCPU_REGS_RCX] = tss->cx;
-	ctxt->regs[VCPU_REGS_RDX] = tss->dx;
-	ctxt->regs[VCPU_REGS_RBX] = tss->bx;
-	ctxt->regs[VCPU_REGS_RSP] = tss->sp;
-	ctxt->regs[VCPU_REGS_RBP] = tss->bp;
-	ctxt->regs[VCPU_REGS_RSI] = tss->si;
-	ctxt->regs[VCPU_REGS_RDI] = tss->di;
+	*reg_write(ctxt, VCPU_REGS_RAX) = tss->ax;
+	*reg_write(ctxt, VCPU_REGS_RCX) = tss->cx;
+	*reg_write(ctxt, VCPU_REGS_RDX) = tss->dx;
+	*reg_write(ctxt, VCPU_REGS_RBX) = tss->bx;
+	*reg_write(ctxt, VCPU_REGS_RSP) = tss->sp;
+	*reg_write(ctxt, VCPU_REGS_RBP) = tss->bp;
+	*reg_write(ctxt, VCPU_REGS_RSI) = tss->si;
+	*reg_write(ctxt, VCPU_REGS_RDI) = tss->di;
 
 	/*
 	 * SDM says that segment selectors are loaded before segment
@@ -2410,7 +2467,7 @@ static int load_state_from_tss16(struct x86_emulate_ctxt *ctxt,
 	set_segment_selector(ctxt, tss->ds, VCPU_SREG_DS);
 
 	/*
-	 * Now load segment descriptors. If fault happenes at this stage
+	 * Now load segment descriptors. If fault happens at this stage
 	 * it is handled in a context of new task
 	 */
 	ret = load_segment_descriptor(ctxt, tss->ldt, VCPU_SREG_LDTR);
@@ -2436,7 +2493,7 @@ static int task_switch_16(struct x86_emulate_ctxt *ctxt,
 			  u16 tss_selector, u16 old_tss_sel,
 			  ulong old_tss_base, struct desc_struct *new_desc)
 {
-	struct x86_emulate_ops *ops = ctxt->ops;
+	const struct x86_emulate_ops *ops = ctxt->ops;
 	struct tss_segment_16 tss_seg;
 	int ret;
 	u32 new_tss_base = get_desc_base(new_desc);
@@ -2482,14 +2539,14 @@ static void save_state_to_tss32(struct x86_emulate_ctxt *ctxt,
 	tss->cr3 = ctxt->ops->get_cr(ctxt, 3);
 	tss->eip = ctxt->_eip;
 	tss->eflags = ctxt->eflags;
-	tss->eax = ctxt->regs[VCPU_REGS_RAX];
-	tss->ecx = ctxt->regs[VCPU_REGS_RCX];
-	tss->edx = ctxt->regs[VCPU_REGS_RDX];
-	tss->ebx = ctxt->regs[VCPU_REGS_RBX];
-	tss->esp = ctxt->regs[VCPU_REGS_RSP];
-	tss->ebp = ctxt->regs[VCPU_REGS_RBP];
-	tss->esi = ctxt->regs[VCPU_REGS_RSI];
-	tss->edi = ctxt->regs[VCPU_REGS_RDI];
+	tss->eax = reg_read(ctxt, VCPU_REGS_RAX);
+	tss->ecx = reg_read(ctxt, VCPU_REGS_RCX);
+	tss->edx = reg_read(ctxt, VCPU_REGS_RDX);
+	tss->ebx = reg_read(ctxt, VCPU_REGS_RBX);
+	tss->esp = reg_read(ctxt, VCPU_REGS_RSP);
+	tss->ebp = reg_read(ctxt, VCPU_REGS_RBP);
+	tss->esi = reg_read(ctxt, VCPU_REGS_RSI);
+	tss->edi = reg_read(ctxt, VCPU_REGS_RDI);
 
 	tss->es = get_segment_selector(ctxt, VCPU_SREG_ES);
 	tss->cs = get_segment_selector(ctxt, VCPU_SREG_CS);
@@ -2511,14 +2568,14 @@ static int load_state_from_tss32(struct x86_emulate_ctxt *ctxt,
 	ctxt->eflags = tss->eflags | 2;
 
 	/* General purpose registers */
-	ctxt->regs[VCPU_REGS_RAX] = tss->eax;
-	ctxt->regs[VCPU_REGS_RCX] = tss->ecx;
-	ctxt->regs[VCPU_REGS_RDX] = tss->edx;
-	ctxt->regs[VCPU_REGS_RBX] = tss->ebx;
-	ctxt->regs[VCPU_REGS_RSP] = tss->esp;
-	ctxt->regs[VCPU_REGS_RBP] = tss->ebp;
-	ctxt->regs[VCPU_REGS_RSI] = tss->esi;
-	ctxt->regs[VCPU_REGS_RDI] = tss->edi;
+	*reg_write(ctxt, VCPU_REGS_RAX) = tss->eax;
+	*reg_write(ctxt, VCPU_REGS_RCX) = tss->ecx;
+	*reg_write(ctxt, VCPU_REGS_RDX) = tss->edx;
+	*reg_write(ctxt, VCPU_REGS_RBX) = tss->ebx;
+	*reg_write(ctxt, VCPU_REGS_RSP) = tss->esp;
+	*reg_write(ctxt, VCPU_REGS_RBP) = tss->ebp;
+	*reg_write(ctxt, VCPU_REGS_RSI) = tss->esi;
+	*reg_write(ctxt, VCPU_REGS_RDI) = tss->edi;
 
 	/*
 	 * SDM says that segment selectors are loaded before segment
@@ -2583,7 +2640,7 @@ static int task_switch_32(struct x86_emulate_ctxt *ctxt,
 			  u16 tss_selector, u16 old_tss_sel,
 			  ulong old_tss_base, struct desc_struct *new_desc)
 {
-	struct x86_emulate_ops *ops = ctxt->ops;
+	const struct x86_emulate_ops *ops = ctxt->ops;
 	struct tss_segment_32 tss_seg;
 	int ret;
 	u32 new_tss_base = get_desc_base(new_desc);
@@ -2627,7 +2684,7 @@ static int emulator_do_task_switch(struct x86_emulate_ctxt *ctxt,
 				   u16 tss_selector, int idt_index, int reason,
 				   bool has_error_code, u32 error_code)
 {
-	struct x86_emulate_ops *ops = ctxt->ops;
+	const struct x86_emulate_ops *ops = ctxt->ops;
 	struct desc_struct curr_tss_desc, next_tss_desc;
 	int ret;
 	u16 old_tss_sel = get_segment_selector(ctxt, VCPU_SREG_TR);
@@ -2652,7 +2709,7 @@ static int emulator_do_task_switch(struct x86_emulate_ctxt *ctxt,
 	 *
 	 * 1. jmp/call/int to task gate: Check against DPL of the task gate
 	 * 2. Exception/IRQ/iret: No check is performed
-	 * 3. jmp/call to TSS: Check agains DPL of the TSS
+	 * 3. jmp/call to TSS: Check against DPL of the TSS
 	 */
 	if (reason == TASK_SWITCH_GATE) {
 		if (idt_index != -1) {
@@ -2693,7 +2750,7 @@ static int emulator_do_task_switch(struct x86_emulate_ctxt *ctxt,
 		ctxt->eflags = ctxt->eflags & ~X86_EFLAGS_NT;
 
 	/* set back link to prev task only if NT bit is set in eflags
-	   note that old_tss_sel is not used afetr this point */
+	   note that old_tss_sel is not used after this point */
 	if (reason != TASK_SWITCH_CALL && reason != TASK_SWITCH_GATE)
 		old_tss_sel = 0xffff;
 
@@ -2733,26 +2790,28 @@ int emulator_task_switch(struct x86_emulate_ctxt *ctxt,
 {
 	int rc;
 
+	invalidate_registers(ctxt);
 	ctxt->_eip = ctxt->eip;
 	ctxt->dst.type = OP_NONE;
 
 	rc = emulator_do_task_switch(ctxt, tss_selector, idt_index, reason,
 				     has_error_code, error_code);
 
-	if (rc == X86EMUL_CONTINUE)
+	if (rc == X86EMUL_CONTINUE) {
 		ctxt->eip = ctxt->_eip;
+		writeback_registers(ctxt);
+	}
 
 	return (rc == X86EMUL_UNHANDLEABLE) ? EMULATION_FAILED : EMULATION_OK;
 }
 
-static void string_addr_inc(struct x86_emulate_ctxt *ctxt, unsigned seg,
-			    int reg, struct operand *op)
+static void string_addr_inc(struct x86_emulate_ctxt *ctxt, int reg,
+		struct operand *op)
 {
-	int df = (ctxt->eflags & EFLG_DF) ? -1 : 1;
+	int df = (ctxt->eflags & EFLG_DF) ? -op->count : op->count;
 
-	register_address_increment(ctxt, &ctxt->regs[reg], df * op->bytes);
-	op->addr.mem.ea = register_address(ctxt, ctxt->regs[reg]);
-	op->addr.mem.seg = seg;
+	register_address_increment(ctxt, reg_rmw(ctxt, reg), df * op->bytes);
+	op->addr.mem.ea = register_address(ctxt, reg_read(ctxt, reg));
 }
 
 static int em_das(struct x86_emulate_ctxt *ctxt)
@@ -2927,7 +2986,7 @@ static int em_cwd(struct x86_emulate_ctxt *ctxt)
 {
 	ctxt->dst.type = OP_REG;
 	ctxt->dst.bytes = ctxt->src.bytes;
-	ctxt->dst.addr.reg = &ctxt->regs[VCPU_REGS_RDX];
+	ctxt->dst.addr.reg = reg_rmw(ctxt, VCPU_REGS_RDX);
 	ctxt->dst.val = ~((ctxt->src.val >> (ctxt->src.bytes * 8 - 1)) - 1);
 
 	return X86EMUL_CONTINUE;
@@ -2938,8 +2997,8 @@ static int em_rdtsc(struct x86_emulate_ctxt *ctxt)
 	u64 tsc = 0;
 
 	ctxt->ops->get_msr(ctxt, MSR_IA32_TSC, &tsc);
-	ctxt->regs[VCPU_REGS_RAX] = (u32)tsc;
-	ctxt->regs[VCPU_REGS_RDX] = tsc >> 32;
+	*reg_write(ctxt, VCPU_REGS_RAX) = (u32)tsc;
+	*reg_write(ctxt, VCPU_REGS_RDX) = tsc >> 32;
 	return X86EMUL_CONTINUE;
 }
 
@@ -2947,10 +3006,10 @@ static int em_rdpmc(struct x86_emulate_ctxt *ctxt)
 {
 	u64 pmc;
 
-	if (ctxt->ops->read_pmc(ctxt, ctxt->regs[VCPU_REGS_RCX], &pmc))
+	if (ctxt->ops->read_pmc(ctxt, reg_read(ctxt, VCPU_REGS_RCX), &pmc))
 		return emulate_gp(ctxt, 0);
-	ctxt->regs[VCPU_REGS_RAX] = (u32)pmc;
-	ctxt->regs[VCPU_REGS_RDX] = pmc >> 32;
+	*reg_write(ctxt, VCPU_REGS_RAX) = (u32)pmc;
+	*reg_write(ctxt, VCPU_REGS_RDX) = pmc >> 32;
 	return X86EMUL_CONTINUE;
 }
 
@@ -2992,9 +3051,9 @@ static int em_wrmsr(struct x86_emulate_ctxt *ctxt)
 {
 	u64 msr_data;
 
-	msr_data = (u32)ctxt->regs[VCPU_REGS_RAX]
-		| ((u64)ctxt->regs[VCPU_REGS_RDX] << 32);
-	if (ctxt->ops->set_msr(ctxt, ctxt->regs[VCPU_REGS_RCX], msr_data))
+	msr_data = (u32)reg_read(ctxt, VCPU_REGS_RAX)
+		| ((u64)reg_read(ctxt, VCPU_REGS_RDX) << 32);
+	if (ctxt->ops->set_msr(ctxt, reg_read(ctxt, VCPU_REGS_RCX), msr_data))
 		return emulate_gp(ctxt, 0);
 
 	return X86EMUL_CONTINUE;
@@ -3004,11 +3063,11 @@ static int em_rdmsr(struct x86_emulate_ctxt *ctxt)
 {
 	u64 msr_data;
 
-	if (ctxt->ops->get_msr(ctxt, ctxt->regs[VCPU_REGS_RCX], &msr_data))
+	if (ctxt->ops->get_msr(ctxt, reg_read(ctxt, VCPU_REGS_RCX), &msr_data))
 		return emulate_gp(ctxt, 0);
 
-	ctxt->regs[VCPU_REGS_RAX] = (u32)msr_data;
-	ctxt->regs[VCPU_REGS_RDX] = msr_data >> 32;
+	*reg_write(ctxt, VCPU_REGS_RAX) = (u32)msr_data;
+	*reg_write(ctxt, VCPU_REGS_RDX) = msr_data >> 32;
 	return X86EMUL_CONTINUE;
 }
 
@@ -3188,8 +3247,8 @@ static int em_lmsw(struct x86_emulate_ctxt *ctxt)
 
 static int em_loop(struct x86_emulate_ctxt *ctxt)
 {
-	register_address_increment(ctxt, &ctxt->regs[VCPU_REGS_RCX], -1);
-	if ((address_mask(ctxt, ctxt->regs[VCPU_REGS_RCX]) != 0) &&
+	register_address_increment(ctxt, reg_rmw(ctxt, VCPU_REGS_RCX), -1);
+	if ((address_mask(ctxt, reg_read(ctxt, VCPU_REGS_RCX)) != 0) &&
 	    (ctxt->b == 0xe2 || test_cc(ctxt->b ^ 0x5, ctxt->eflags)))
 		jmp_rel(ctxt, ctxt->src.val);
 
@@ -3198,7 +3257,7 @@ static int em_loop(struct x86_emulate_ctxt *ctxt)
 
 static int em_jcxz(struct x86_emulate_ctxt *ctxt)
 {
-	if (address_mask(ctxt, ctxt->regs[VCPU_REGS_RCX]) == 0)
+	if (address_mask(ctxt, reg_read(ctxt, VCPU_REGS_RCX)) == 0)
 		jmp_rel(ctxt, ctxt->src.val);
 
 	return X86EMUL_CONTINUE;
@@ -3286,20 +3345,20 @@ static int em_cpuid(struct x86_emulate_ctxt *ctxt)
 {
 	u32 eax, ebx, ecx, edx;
 
-	eax = ctxt->regs[VCPU_REGS_RAX];
-	ecx = ctxt->regs[VCPU_REGS_RCX];
+	eax = reg_read(ctxt, VCPU_REGS_RAX);
+	ecx = reg_read(ctxt, VCPU_REGS_RCX);
 	ctxt->ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx);
-	ctxt->regs[VCPU_REGS_RAX] = eax;
-	ctxt->regs[VCPU_REGS_RBX] = ebx;
-	ctxt->regs[VCPU_REGS_RCX] = ecx;
-	ctxt->regs[VCPU_REGS_RDX] = edx;
+	*reg_write(ctxt, VCPU_REGS_RAX) = eax;
+	*reg_write(ctxt, VCPU_REGS_RBX) = ebx;
+	*reg_write(ctxt, VCPU_REGS_RCX) = ecx;
+	*reg_write(ctxt, VCPU_REGS_RDX) = edx;
 	return X86EMUL_CONTINUE;
 }
 
 static int em_lahf(struct x86_emulate_ctxt *ctxt)
 {
-	ctxt->regs[VCPU_REGS_RAX] &= ~0xff00UL;
-	ctxt->regs[VCPU_REGS_RAX] |= (ctxt->eflags & 0xff) << 8;
+	*reg_rmw(ctxt, VCPU_REGS_RAX) &= ~0xff00UL;
+	*reg_rmw(ctxt, VCPU_REGS_RAX) |= (ctxt->eflags & 0xff) << 8;
 	return X86EMUL_CONTINUE;
 }
 
@@ -3456,7 +3515,7 @@ static int check_svme(struct x86_emulate_ctxt *ctxt)
 
 static int check_svme_pa(struct x86_emulate_ctxt *ctxt)
 {
-	u64 rax = ctxt->regs[VCPU_REGS_RAX];
+	u64 rax = reg_read(ctxt, VCPU_REGS_RAX);
 
 	/* Valid physical address? */
 	if (rax & 0xffff000000000000ULL)
@@ -3478,7 +3537,7 @@ static int check_rdtsc(struct x86_emulate_ctxt *ctxt)
 static int check_rdpmc(struct x86_emulate_ctxt *ctxt)
 {
 	u64 cr4 = ctxt->ops->get_cr(ctxt, 4);
-	u64 rcx = ctxt->regs[VCPU_REGS_RCX];
+	u64 rcx = reg_read(ctxt, VCPU_REGS_RCX);
 
 	if ((!(cr4 & X86_CR4_PCE) && ctxt->ops->cpl(ctxt)) ||
 	    (rcx > 3))
@@ -3531,13 +3590,13 @@ static int check_perm_out(struct x86_emulate_ctxt *ctxt)
 		I2bv(((_f) | DstReg | SrcMem | ModRM) & ~Lock, _e),	\
 		I2bv(((_f) & ~Lock) | DstAcc | SrcImm, _e)
 
-static struct opcode group7_rm1[] = {
+static const struct opcode group7_rm1[] = {
 	DI(SrcNone | Priv, monitor),
 	DI(SrcNone | Priv, mwait),
 	N, N, N, N, N, N,
 };
 
-static struct opcode group7_rm3[] = {
+static const struct opcode group7_rm3[] = {
 	DIP(SrcNone | Prot | Priv,		vmrun,		check_svme_pa),
 	II(SrcNone  | Prot | VendorSpecific,	em_vmmcall,	vmmcall),
 	DIP(SrcNone | Prot | Priv,		vmload,		check_svme_pa),
@@ -3548,13 +3607,13 @@ static struct opcode group7_rm3[] = {
 	DIP(SrcNone | Prot | Priv,		invlpga,	check_svme),
 };
 
-static struct opcode group7_rm7[] = {
+static const struct opcode group7_rm7[] = {
 	N,
 	DIP(SrcNone, rdtscp, check_rdtsc),
 	N, N, N, N, N, N,
 };
 
-static struct opcode group1[] = {
+static const struct opcode group1[] = {
 	I(Lock, em_add),
 	I(Lock | PageTable, em_or),
 	I(Lock, em_adc),
@@ -3565,11 +3624,11 @@ static struct opcode group1[] = {
 	I(0, em_cmp),
 };
 
-static struct opcode group1A[] = {
+static const struct opcode group1A[] = {
 	I(DstMem | SrcNone | Mov | Stack, em_pop), N, N, N, N, N, N, N,
 };
 
-static struct opcode group3[] = {
+static const struct opcode group3[] = {
 	I(DstMem | SrcImm, em_test),
 	I(DstMem | SrcImm, em_test),
 	I(DstMem | SrcNone | Lock, em_not),
@@ -3580,13 +3639,13 @@ static struct opcode group3[] = {
 	I(SrcMem, em_idiv_ex),
 };
 
-static struct opcode group4[] = {
+static const struct opcode group4[] = {
 	I(ByteOp | DstMem | SrcNone | Lock, em_grp45),
 	I(ByteOp | DstMem | SrcNone | Lock, em_grp45),
 	N, N, N, N, N, N,
 };
 
-static struct opcode group5[] = {
+static const struct opcode group5[] = {
 	I(DstMem | SrcNone | Lock,		em_grp45),
 	I(DstMem | SrcNone | Lock,		em_grp45),
 	I(SrcMem | Stack,			em_grp45),
@@ -3596,7 +3655,7 @@ static struct opcode group5[] = {
 	I(SrcMem | Stack,			em_grp45), N,
 };
 
-static struct opcode group6[] = {
+static const struct opcode group6[] = {
 	DI(Prot,	sldt),
 	DI(Prot,	str),
 	II(Prot | Priv | SrcMem16, em_lldt, lldt),
@@ -3604,7 +3663,7 @@ static struct opcode group6[] = {
 	N, N, N, N,
 };
 
-static struct group_dual group7 = { {
+static const struct group_dual group7 = { {
 	II(Mov | DstMem | Priv,			em_sgdt, sgdt),
 	II(Mov | DstMem | Priv,			em_sidt, sidt),
 	II(SrcMem | Priv,			em_lgdt, lgdt),
@@ -3621,7 +3680,7 @@ static struct group_dual group7 = { {
 	EXT(0, group7_rm7),
 } };
 
-static struct opcode group8[] = {
+static const struct opcode group8[] = {
 	N, N, N, N,
 	I(DstMem | SrcImmByte,				em_bt),
 	I(DstMem | SrcImmByte | Lock | PageTable,	em_bts),
@@ -3629,26 +3688,26 @@ static struct opcode group8[] = {
 	I(DstMem | SrcImmByte | Lock | PageTable,	em_btc),
 };
 
-static struct group_dual group9 = { {
+static const struct group_dual group9 = { {
 	N, I(DstMem64 | Lock | PageTable, em_cmpxchg8b), N, N, N, N, N, N,
 }, {
 	N, N, N, N, N, N, N, N,
 } };
 
-static struct opcode group11[] = {
+static const struct opcode group11[] = {
 	I(DstMem | SrcImm | Mov | PageTable, em_mov),
 	X7(D(Undefined)),
 };
 
-static struct gprefix pfx_0f_6f_0f_7f = {
+static const struct gprefix pfx_0f_6f_0f_7f = {
 	I(Mmx, em_mov), I(Sse | Aligned, em_mov), N, I(Sse | Unaligned, em_mov),
 };
 
-static struct gprefix pfx_vmovntpx = {
+static const struct gprefix pfx_vmovntpx = {
 	I(0, em_mov), N, N, N,
 };
 
-static struct opcode opcode_table[256] = {
+static const struct opcode opcode_table[256] = {
 	/* 0x00 - 0x07 */
 	I6ALU(Lock, em_add),
 	I(ImplicitOps | Stack | No64 | Src2ES, em_push_sreg),
@@ -3689,7 +3748,7 @@ static struct opcode opcode_table[256] = {
 	I(DstReg | SrcMem | ModRM | Src2Imm, em_imul_3op),
 	I(SrcImmByte | Mov | Stack, em_push),
 	I(DstReg | SrcMem | ModRM | Src2ImmByte, em_imul_3op),
-	I2bvIP(DstDI | SrcDX | Mov | String, em_in, ins, check_perm_in), /* insb, insw/insd */
+	I2bvIP(DstDI | SrcDX | Mov | String | Unaligned, em_in, ins, check_perm_in), /* insb, insw/insd */
 	I2bvIP(SrcSI | DstDX | String, em_out, outs, check_perm_out), /* outsb, outsw/outsd */
 	/* 0x70 - 0x7F */
 	X16(D(SrcImmByte)),
@@ -3765,7 +3824,7 @@ static struct opcode opcode_table[256] = {
 	D(ImplicitOps), D(ImplicitOps), G(0, group4), G(0, group5),
 };
 
-static struct opcode twobyte_table[256] = {
+static const struct opcode twobyte_table[256] = {
 	/* 0x00 - 0x0F */
 	G(0, group6), GD(0, &group7), N, N,
 	N, I(ImplicitOps | VendorSpecific, em_syscall),
@@ -3936,7 +3995,7 @@ static int decode_operand(struct x86_emulate_ctxt *ctxt, struct operand *op,
 	case OpAcc:
 		op->type = OP_REG;
 		op->bytes = (ctxt->d & ByteOp) ? 1 : ctxt->op_bytes;
-		op->addr.reg = &ctxt->regs[VCPU_REGS_RAX];
+		op->addr.reg = reg_rmw(ctxt, VCPU_REGS_RAX);
 		fetch_register_operand(op);
 		op->orig_val = op->val;
 		break;
@@ -3944,19 +4003,20 @@ static int decode_operand(struct x86_emulate_ctxt *ctxt, struct operand *op,
 		op->type = OP_MEM;
 		op->bytes = (ctxt->d & ByteOp) ? 1 : ctxt->op_bytes;
 		op->addr.mem.ea =
-			register_address(ctxt, ctxt->regs[VCPU_REGS_RDI]);
+			register_address(ctxt, reg_read(ctxt, VCPU_REGS_RDI));
 		op->addr.mem.seg = VCPU_SREG_ES;
 		op->val = 0;
+		op->count = 1;
 		break;
 	case OpDX:
 		op->type = OP_REG;
 		op->bytes = 2;
-		op->addr.reg = &ctxt->regs[VCPU_REGS_RDX];
+		op->addr.reg = reg_rmw(ctxt, VCPU_REGS_RDX);
 		fetch_register_operand(op);
 		break;
 	case OpCL:
 		op->bytes = 1;
-		op->val = ctxt->regs[VCPU_REGS_RCX] & 0xff;
+		op->val = reg_read(ctxt, VCPU_REGS_RCX) & 0xff;
 		break;
 	case OpImmByte:
 		rc = decode_imm(ctxt, op, 1, true);
@@ -3987,9 +4047,10 @@ static int decode_operand(struct x86_emulate_ctxt *ctxt, struct operand *op,
 		op->type = OP_MEM;
 		op->bytes = (ctxt->d & ByteOp) ? 1 : ctxt->op_bytes;
 		op->addr.mem.ea =
-			register_address(ctxt, ctxt->regs[VCPU_REGS_RSI]);
+			register_address(ctxt, reg_read(ctxt, VCPU_REGS_RSI));
 		op->addr.mem.seg = seg_override(ctxt);
 		op->val = 0;
+		op->count = 1;
 		break;
 	case OpImmFAddr:
 		op->type = OP_IMM;
@@ -4293,9 +4354,10 @@ static void fetch_possible_mmx_operand(struct x86_emulate_ctxt *ctxt,
 		read_mmx_reg(ctxt, &op->mm_val, op->addr.mm);
 }
 
+
 int x86_emulate_insn(struct x86_emulate_ctxt *ctxt)
 {
-	struct x86_emulate_ops *ops = ctxt->ops;
+	const struct x86_emulate_ops *ops = ctxt->ops;
 	int rc = X86EMUL_CONTINUE;
 	int saved_dst_type = ctxt->dst.type;
 
@@ -4356,7 +4418,7 @@ int x86_emulate_insn(struct x86_emulate_ctxt *ctxt)
 	}
 
 	/* Instruction can only be executed in protected mode */
-	if ((ctxt->d & Prot) && !(ctxt->mode & X86EMUL_MODE_PROT)) {
+	if ((ctxt->d & Prot) && ctxt->mode < X86EMUL_MODE_PROT16) {
 		rc = emulate_ud(ctxt);
 		goto done;
 	}
@@ -4377,7 +4439,7 @@ int x86_emulate_insn(struct x86_emulate_ctxt *ctxt)
 
 	if (ctxt->rep_prefix && (ctxt->d & String)) {
 		/* All REP prefixes have the same first termination condition */
-		if (address_mask(ctxt, ctxt->regs[VCPU_REGS_RCX]) == 0) {
+		if (address_mask(ctxt, reg_read(ctxt, VCPU_REGS_RCX)) == 0) {
 			ctxt->eip = ctxt->_eip;
 			goto done;
 		}
@@ -4450,7 +4512,7 @@ special_insn:
 		ctxt->dst.val = ctxt->src.addr.mem.ea;
 		break;
 	case 0x90 ... 0x97: /* nop / xchg reg, rax */
-		if (ctxt->dst.addr.reg == &ctxt->regs[VCPU_REGS_RAX])
+		if (ctxt->dst.addr.reg == reg_rmw(ctxt, VCPU_REGS_RAX))
 			break;
 		rc = em_xchg(ctxt);
 		break;
@@ -4478,7 +4540,7 @@ special_insn:
 		rc = em_grp2(ctxt);
 		break;
 	case 0xd2 ... 0xd3:	/* Grp2 */
-		ctxt->src.val = ctxt->regs[VCPU_REGS_RCX];
+		ctxt->src.val = reg_read(ctxt, VCPU_REGS_RCX);
 		rc = em_grp2(ctxt);
 		break;
 	case 0xe9: /* jmp rel */
@@ -4524,23 +4586,27 @@ writeback:
 	ctxt->dst.type = saved_dst_type;
 
 	if ((ctxt->d & SrcMask) == SrcSI)
-		string_addr_inc(ctxt, seg_override(ctxt),
-				VCPU_REGS_RSI, &ctxt->src);
+		string_addr_inc(ctxt, VCPU_REGS_RSI, &ctxt->src);
 
 	if ((ctxt->d & DstMask) == DstDI)
-		string_addr_inc(ctxt, VCPU_SREG_ES, VCPU_REGS_RDI,
-				&ctxt->dst);
+		string_addr_inc(ctxt, VCPU_REGS_RDI, &ctxt->dst);
 
 	if (ctxt->rep_prefix && (ctxt->d & String)) {
+		unsigned int count;
 		struct read_cache *r = &ctxt->io_read;
-		register_address_increment(ctxt, &ctxt->regs[VCPU_REGS_RCX], -1);
+		if ((ctxt->d & SrcMask) == SrcSI)
+			count = ctxt->src.count;
+		else
+			count = ctxt->dst.count;
+		register_address_increment(ctxt, reg_rmw(ctxt, VCPU_REGS_RCX),
+				-count);
 
 		if (!string_insn_completed(ctxt)) {
 			/*
 			 * Re-enter guest when pio read ahead buffer is empty
 			 * or, if it is not used, after each 1024 iteration.
 			 */
-			if ((r->end != 0 || ctxt->regs[VCPU_REGS_RCX] & 0x3ff) &&
+			if ((r->end != 0 || reg_read(ctxt, VCPU_REGS_RCX) & 0x3ff) &&
 			    (r->end == 0 || r->end != r->pos)) {
 				/*
 				 * Reset read cache. Usually happens before
@@ -4548,6 +4614,7 @@ writeback:
 				 * we have to do it here.
 				 */
 				ctxt->mem_read.end = 0;
+				writeback_registers(ctxt);
 				return EMULATION_RESTART;
 			}
 			goto done; /* skip rip writeback */
@@ -4562,6 +4629,9 @@ done:
 	if (rc == X86EMUL_INTERCEPTED)
 		return EMULATION_INTERCEPTED;
 
+	if (rc == X86EMUL_CONTINUE)
+		writeback_registers(ctxt);
+
 	return (rc == X86EMUL_UNHANDLEABLE) ? EMULATION_FAILED : EMULATION_OK;
 
 twobyte_insn:
@@ -4634,3 +4704,13 @@ twobyte_insn:
 cannot_emulate:
 	return EMULATION_FAILED;
 }
+
+void emulator_invalidate_register_cache(struct x86_emulate_ctxt *ctxt)
+{
+	invalidate_registers(ctxt);
+}
+
+void emulator_writeback_register_cache(struct x86_emulate_ctxt *ctxt)
+{
+	writeback_registers(ctxt);
+}
diff --git a/arch/x86/kvm/i8254.c b/arch/x86/kvm/i8254.c
index adba28f..11300d2 100644
--- a/arch/x86/kvm/i8254.c
+++ b/arch/x86/kvm/i8254.c
@@ -108,7 +108,7 @@ static s64 __kpit_elapsed(struct kvm *kvm)
 	ktime_t remaining;
 	struct kvm_kpit_state *ps = &kvm->arch.vpit->pit_state;
 
-	if (!ps->pit_timer.period)
+	if (!ps->period)
 		return 0;
 
 	/*
@@ -120,9 +120,9 @@ static s64 __kpit_elapsed(struct kvm *kvm)
 	 * itself with the initial count and continues counting
 	 * from there.
 	 */
-	remaining = hrtimer_get_remaining(&ps->pit_timer.timer);
-	elapsed = ps->pit_timer.period - ktime_to_ns(remaining);
-	elapsed = mod_64(elapsed, ps->pit_timer.period);
+	remaining = hrtimer_get_remaining(&ps->timer);
+	elapsed = ps->period - ktime_to_ns(remaining);
+	elapsed = mod_64(elapsed, ps->period);
 
 	return elapsed;
 }
@@ -238,12 +238,12 @@ static void kvm_pit_ack_irq(struct kvm_irq_ack_notifier *kian)
 	int value;
 
 	spin_lock(&ps->inject_lock);
-	value = atomic_dec_return(&ps->pit_timer.pending);
+	value = atomic_dec_return(&ps->pending);
 	if (value < 0)
 		/* spurious acks can be generated if, for example, the
 		 * PIC is being reset.  Handle it gracefully here
 		 */
-		atomic_inc(&ps->pit_timer.pending);
+		atomic_inc(&ps->pending);
 	else if (value > 0)
 		/* in this case, we had multiple outstanding pit interrupts
 		 * that we needed to inject.  Reinject
@@ -261,28 +261,17 @@ void __kvm_migrate_pit_timer(struct kvm_vcpu *vcpu)
 	if (!kvm_vcpu_is_bsp(vcpu) || !pit)
 		return;
 
-	timer = &pit->pit_state.pit_timer.timer;
+	timer = &pit->pit_state.timer;
 	if (hrtimer_cancel(timer))
 		hrtimer_start_expires(timer, HRTIMER_MODE_ABS);
 }
 
 static void destroy_pit_timer(struct kvm_pit *pit)
 {
-	hrtimer_cancel(&pit->pit_state.pit_timer.timer);
+	hrtimer_cancel(&pit->pit_state.timer);
 	flush_kthread_work(&pit->expired);
 }
 
-static bool kpit_is_periodic(struct kvm_timer *ktimer)
-{
-	struct kvm_kpit_state *ps = container_of(ktimer, struct kvm_kpit_state,
-						 pit_timer);
-	return ps->is_periodic;
-}
-
-static struct kvm_timer_ops kpit_ops = {
-	.is_periodic = kpit_is_periodic,
-};
-
 static void pit_do_work(struct kthread_work *work)
 {
 	struct kvm_pit *pit = container_of(work, struct kvm_pit, expired);
@@ -322,16 +311,16 @@ static void pit_do_work(struct kthread_work *work)
 
 static enum hrtimer_restart pit_timer_fn(struct hrtimer *data)
 {
-	struct kvm_timer *ktimer = container_of(data, struct kvm_timer, timer);
-	struct kvm_pit *pt = ktimer->kvm->arch.vpit;
+	struct kvm_kpit_state *ps = container_of(data, struct kvm_kpit_state, timer);
+	struct kvm_pit *pt = ps->kvm->arch.vpit;
 
-	if (ktimer->reinject || !atomic_read(&ktimer->pending)) {
-		atomic_inc(&ktimer->pending);
+	if (ps->reinject || !atomic_read(&ps->pending)) {
+		atomic_inc(&ps->pending);
 		queue_kthread_work(&pt->worker, &pt->expired);
 	}
 
-	if (ktimer->t_ops->is_periodic(ktimer)) {
-		hrtimer_add_expires_ns(&ktimer->timer, ktimer->period);
+	if (ps->is_periodic) {
+		hrtimer_add_expires_ns(&ps->timer, ps->period);
 		return HRTIMER_RESTART;
 	} else
 		return HRTIMER_NORESTART;
@@ -340,7 +329,6 @@ static enum hrtimer_restart pit_timer_fn(struct hrtimer *data)
 static void create_pit_timer(struct kvm *kvm, u32 val, int is_period)
 {
 	struct kvm_kpit_state *ps = &kvm->arch.vpit->pit_state;
-	struct kvm_timer *pt = &ps->pit_timer;
 	s64 interval;
 
 	if (!irqchip_in_kernel(kvm) || ps->flags & KVM_PIT_FLAGS_HPET_LEGACY)
@@ -351,19 +339,18 @@ static void create_pit_timer(struct kvm *kvm, u32 val, int is_period)
 	pr_debug("create pit timer, interval is %llu nsec\n", interval);
 
 	/* TODO The new value only affected after the retriggered */
-	hrtimer_cancel(&pt->timer);
+	hrtimer_cancel(&ps->timer);
 	flush_kthread_work(&ps->pit->expired);
-	pt->period = interval;
+	ps->period = interval;
 	ps->is_periodic = is_period;
 
-	pt->timer.function = pit_timer_fn;
-	pt->t_ops = &kpit_ops;
-	pt->kvm = ps->pit->kvm;
+	ps->timer.function = pit_timer_fn;
+	ps->kvm = ps->pit->kvm;
 
-	atomic_set(&pt->pending, 0);
+	atomic_set(&ps->pending, 0);
 	ps->irq_ack = 1;
 
-	hrtimer_start(&pt->timer, ktime_add_ns(ktime_get(), interval),
+	hrtimer_start(&ps->timer, ktime_add_ns(ktime_get(), interval),
 		      HRTIMER_MODE_ABS);
 }
 
@@ -639,7 +626,7 @@ void kvm_pit_reset(struct kvm_pit *pit)
 	}
 	mutex_unlock(&pit->pit_state.lock);
 
-	atomic_set(&pit->pit_state.pit_timer.pending, 0);
+	atomic_set(&pit->pit_state.pending, 0);
 	pit->pit_state.irq_ack = 1;
 }
 
@@ -648,7 +635,7 @@ static void pit_mask_notifer(struct kvm_irq_mask_notifier *kimn, bool mask)
 	struct kvm_pit *pit = container_of(kimn, struct kvm_pit, mask_notifier);
 
 	if (!mask) {
-		atomic_set(&pit->pit_state.pit_timer.pending, 0);
+		atomic_set(&pit->pit_state.pending, 0);
 		pit->pit_state.irq_ack = 1;
 	}
 }
@@ -706,12 +693,11 @@ struct kvm_pit *kvm_create_pit(struct kvm *kvm, u32 flags)
 
 	pit_state = &pit->pit_state;
 	pit_state->pit = pit;
-	hrtimer_init(&pit_state->pit_timer.timer,
-		     CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
+	hrtimer_init(&pit_state->timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
 	pit_state->irq_ack_notifier.gsi = 0;
 	pit_state->irq_ack_notifier.irq_acked = kvm_pit_ack_irq;
 	kvm_register_irq_ack_notifier(kvm, &pit_state->irq_ack_notifier);
-	pit_state->pit_timer.reinject = true;
+	pit_state->reinject = true;
 	mutex_unlock(&pit->pit_state.lock);
 
 	kvm_pit_reset(pit);
@@ -761,7 +747,7 @@ void kvm_free_pit(struct kvm *kvm)
 		kvm_unregister_irq_ack_notifier(kvm,
 				&kvm->arch.vpit->pit_state.irq_ack_notifier);
 		mutex_lock(&kvm->arch.vpit->pit_state.lock);
-		timer = &kvm->arch.vpit->pit_state.pit_timer.timer;
+		timer = &kvm->arch.vpit->pit_state.timer;
 		hrtimer_cancel(timer);
 		flush_kthread_work(&kvm->arch.vpit->expired);
 		kthread_stop(kvm->arch.vpit->worker_task);
diff --git a/arch/x86/kvm/i8254.h b/arch/x86/kvm/i8254.h
index fdf4042..dd1b16b 100644
--- a/arch/x86/kvm/i8254.h
+++ b/arch/x86/kvm/i8254.h
@@ -24,8 +24,12 @@ struct kvm_kpit_channel_state {
 struct kvm_kpit_state {
 	struct kvm_kpit_channel_state channels[3];
 	u32 flags;
-	struct kvm_timer pit_timer;
 	bool is_periodic;
+	s64 period; 				/* unit: ns */
+	struct hrtimer timer;
+	atomic_t pending;			/* accumulated triggered timers */
+	bool reinject;
+	struct kvm *kvm;
 	u32    speaker_data_on;
 	struct mutex lock;
 	struct kvm_pit *pit;
diff --git a/arch/x86/kvm/i8259.c b/arch/x86/kvm/i8259.c
index 9fc9aa7..848206d 100644
--- a/arch/x86/kvm/i8259.c
+++ b/arch/x86/kvm/i8259.c
@@ -190,17 +190,17 @@ void kvm_pic_update_irq(struct kvm_pic *s)
 
 int kvm_pic_set_irq(struct kvm_pic *s, int irq, int irq_source_id, int level)
 {
-	int ret = -1;
+	int ret, irq_level;
+
+	BUG_ON(irq < 0 || irq >= PIC_NUM_PINS);
 
 	pic_lock(s);
-	if (irq >= 0 && irq < PIC_NUM_PINS) {
-		int irq_level = __kvm_irq_line_state(&s->irq_states[irq],
-						     irq_source_id, level);
-		ret = pic_set_irq1(&s->pics[irq >> 3], irq & 7, irq_level);
-		pic_update_irq(s);
-		trace_kvm_pic_set_irq(irq >> 3, irq & 7, s->pics[irq >> 3].elcr,
-				      s->pics[irq >> 3].imr, ret == 0);
-	}
+	irq_level = __kvm_irq_line_state(&s->irq_states[irq],
+					 irq_source_id, level);
+	ret = pic_set_irq1(&s->pics[irq >> 3], irq & 7, irq_level);
+	pic_update_irq(s);
+	trace_kvm_pic_set_irq(irq >> 3, irq & 7, s->pics[irq >> 3].elcr,
+			      s->pics[irq >> 3].imr, ret == 0);
 	pic_unlock(s);
 
 	return ret;
@@ -275,23 +275,20 @@ void kvm_pic_reset(struct kvm_kpic_state *s)
 {
 	int irq, i;
 	struct kvm_vcpu *vcpu;
-	u8 irr = s->irr, isr = s->imr;
+	u8 edge_irr = s->irr & ~s->elcr;
 	bool found = false;
 
 	s->last_irr = 0;
-	s->irr = 0;
+	s->irr &= s->elcr;
 	s->imr = 0;
-	s->isr = 0;
 	s->priority_add = 0;
-	s->irq_base = 0;
-	s->read_reg_select = 0;
-	s->poll = 0;
 	s->special_mask = 0;
-	s->init_state = 0;
-	s->auto_eoi = 0;
-	s->rotate_on_auto_eoi = 0;
-	s->special_fully_nested_mode = 0;
-	s->init4 = 0;
+	s->read_reg_select = 0;
+	if (!s->init4) {
+		s->special_fully_nested_mode = 0;
+		s->auto_eoi = 0;
+	}
+	s->init_state = 1;
 
 	kvm_for_each_vcpu(i, vcpu, s->pics_state->kvm)
 		if (kvm_apic_accept_pic_intr(vcpu)) {
@@ -304,7 +301,7 @@ void kvm_pic_reset(struct kvm_kpic_state *s)
 		return;
 
 	for (irq = 0; irq < PIC_NUM_PINS/2; irq++)
-		if (irr & (1 << irq) || isr & (1 << irq))
+		if (edge_irr & (1 << irq))
 			pic_clear_isr(s, irq);
 }
 
@@ -316,40 +313,13 @@ static void pic_ioport_write(void *opaque, u32 addr, u32 val)
 	addr &= 1;
 	if (addr == 0) {
 		if (val & 0x10) {
-			u8 edge_irr = s->irr & ~s->elcr;
-			int i;
-			bool found = false;
-			struct kvm_vcpu *vcpu;
-
 			s->init4 = val & 1;
-			s->last_irr = 0;
-			s->irr &= s->elcr;
-			s->imr = 0;
-			s->priority_add = 0;
-			s->special_mask = 0;
-			s->read_reg_select = 0;
-			if (!s->init4) {
-				s->special_fully_nested_mode = 0;
-				s->auto_eoi = 0;
-			}
-			s->init_state = 1;
 			if (val & 0x02)
 				pr_pic_unimpl("single mode not supported");
 			if (val & 0x08)
 				pr_pic_unimpl(
-					"level sensitive irq not supported");
-
-			kvm_for_each_vcpu(i, vcpu, s->pics_state->kvm)
-				if (kvm_apic_accept_pic_intr(vcpu)) {
-					found = true;
-					break;
-				}
-
-
-			if (found)
-				for (irq = 0; irq < PIC_NUM_PINS/2; irq++)
-					if (edge_irr & (1 << irq))
-						pic_clear_isr(s, irq);
+						"level sensitive irq not supported");
+			kvm_pic_reset(s);
 		} else if (val & 0x08) {
 			if (val & 0x04)
 				s->poll = 1;
diff --git a/arch/x86/kvm/irq.h b/arch/x86/kvm/irq.h
index 2086f2b..2d03568 100644
--- a/arch/x86/kvm/irq.h
+++ b/arch/x86/kvm/irq.h
@@ -70,7 +70,7 @@ struct kvm_pic {
 	struct kvm_io_device dev_slave;
 	struct kvm_io_device dev_eclr;
 	void (*ack_notifier)(void *opaque, int irq);
-	unsigned long irq_states[16];
+	unsigned long irq_states[PIC_NUM_PINS];
 };
 
 struct kvm_pic *kvm_create_pic(struct kvm *kvm);
diff --git a/arch/x86/kvm/kvm_timer.h b/arch/x86/kvm/kvm_timer.h
deleted file mode 100644
index 497dbaa..0000000
--- a/arch/x86/kvm/kvm_timer.h
+++ /dev/null
@@ -1,18 +0,0 @@
-
-struct kvm_timer {
-	struct hrtimer timer;
-	s64 period; 				/* unit: ns */
-	u32 timer_mode_mask;
-	u64 tscdeadline;
-	atomic_t pending;			/* accumulated triggered timers */
-	bool reinject;
-	struct kvm_timer_ops *t_ops;
-	struct kvm *kvm;
-	struct kvm_vcpu *vcpu;
-};
-
-struct kvm_timer_ops {
-	bool (*is_periodic)(struct kvm_timer *);
-};
-
-enum hrtimer_restart kvm_timer_fn(struct hrtimer *data);
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index ce87878..c6e6b72 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -34,6 +34,7 @@
 #include <asm/current.h>
 #include <asm/apicdef.h>
 #include <linux/atomic.h>
+#include <linux/jump_label.h>
 #include "kvm_cache_regs.h"
 #include "irq.h"
 #include "trace.h"
@@ -65,6 +66,7 @@
 #define APIC_DEST_NOSHORT		0x0
 #define APIC_DEST_MASK			0x800
 #define MAX_APIC_VECTOR			256
+#define APIC_VECTORS_PER_REG		32
 
 #define VEC_POS(v) ((v) & (32 - 1))
 #define REG_POS(v) (((v) >> 5) << 4)
@@ -72,11 +74,6 @@
 static unsigned int min_timer_period_us = 500;
 module_param(min_timer_period_us, uint, S_IRUGO | S_IWUSR);
 
-static inline u32 apic_get_reg(struct kvm_lapic *apic, int reg_off)
-{
-	return *((u32 *) (apic->regs + reg_off));
-}
-
 static inline void apic_set_reg(struct kvm_lapic *apic, int reg_off, u32 val)
 {
 	*((u32 *) (apic->regs + reg_off)) = val;
@@ -117,19 +114,23 @@ static inline int __apic_test_and_clear_vector(int vec, void *bitmap)
 	return __test_and_clear_bit(VEC_POS(vec), (bitmap) + REG_POS(vec));
 }
 
-static inline int apic_hw_enabled(struct kvm_lapic *apic)
-{
-	return (apic)->vcpu->arch.apic_base & MSR_IA32_APICBASE_ENABLE;
-}
+struct static_key_deferred apic_hw_disabled __read_mostly;
+struct static_key_deferred apic_sw_disabled __read_mostly;
 
-static inline int  apic_sw_enabled(struct kvm_lapic *apic)
+static inline void apic_set_spiv(struct kvm_lapic *apic, u32 val)
 {
-	return apic_get_reg(apic, APIC_SPIV) & APIC_SPIV_APIC_ENABLED;
+	if ((kvm_apic_get_reg(apic, APIC_SPIV) ^ val) & APIC_SPIV_APIC_ENABLED) {
+		if (val & APIC_SPIV_APIC_ENABLED)
+			static_key_slow_dec_deferred(&apic_sw_disabled);
+		else
+			static_key_slow_inc(&apic_sw_disabled.key);
+	}
+	apic_set_reg(apic, APIC_SPIV, val);
 }
 
 static inline int apic_enabled(struct kvm_lapic *apic)
 {
-	return apic_sw_enabled(apic) &&	apic_hw_enabled(apic);
+	return kvm_apic_sw_enabled(apic) &&	kvm_apic_hw_enabled(apic);
 }
 
 #define LVT_MASK	\
@@ -139,36 +140,135 @@ static inline int apic_enabled(struct kvm_lapic *apic)
 	(LVT_MASK | APIC_MODE_MASK | APIC_INPUT_POLARITY | \
 	 APIC_LVT_REMOTE_IRR | APIC_LVT_LEVEL_TRIGGER)
 
+static inline int apic_x2apic_mode(struct kvm_lapic *apic)
+{
+	return apic->vcpu->arch.apic_base & X2APIC_ENABLE;
+}
+
 static inline int kvm_apic_id(struct kvm_lapic *apic)
 {
-	return (apic_get_reg(apic, APIC_ID) >> 24) & 0xff;
+	return (kvm_apic_get_reg(apic, APIC_ID) >> 24) & 0xff;
+}
+
+static inline u16 apic_cluster_id(struct kvm_apic_map *map, u32 ldr)
+{
+	u16 cid;
+	ldr >>= 32 - map->ldr_bits;
+	cid = (ldr >> map->cid_shift) & map->cid_mask;
+
+	BUG_ON(cid >= ARRAY_SIZE(map->logical_map));
+
+	return cid;
+}
+
+static inline u16 apic_logical_id(struct kvm_apic_map *map, u32 ldr)
+{
+	ldr >>= (32 - map->ldr_bits);
+	return ldr & map->lid_mask;
+}
+
+static void recalculate_apic_map(struct kvm *kvm)
+{
+	struct kvm_apic_map *new, *old = NULL;
+	struct kvm_vcpu *vcpu;
+	int i;
+
+	new = kzalloc(sizeof(struct kvm_apic_map), GFP_KERNEL);
+
+	mutex_lock(&kvm->arch.apic_map_lock);
+
+	if (!new)
+		goto out;
+
+	new->ldr_bits = 8;
+	/* flat mode is default */
+	new->cid_shift = 8;
+	new->cid_mask = 0;
+	new->lid_mask = 0xff;
+
+	kvm_for_each_vcpu(i, vcpu, kvm) {
+		struct kvm_lapic *apic = vcpu->arch.apic;
+		u16 cid, lid;
+		u32 ldr;
+
+		if (!kvm_apic_present(vcpu))
+			continue;
+
+		/*
+		 * All APICs have to be configured in the same mode by an OS.
+		 * We take advatage of this while building logical id loockup
+		 * table. After reset APICs are in xapic/flat mode, so if we
+		 * find apic with different setting we assume this is the mode
+		 * OS wants all apics to be in; build lookup table accordingly.
+		 */
+		if (apic_x2apic_mode(apic)) {
+			new->ldr_bits = 32;
+			new->cid_shift = 16;
+			new->cid_mask = new->lid_mask = 0xffff;
+		} else if (kvm_apic_sw_enabled(apic) &&
+				!new->cid_mask /* flat mode */ &&
+				kvm_apic_get_reg(apic, APIC_DFR) == APIC_DFR_CLUSTER) {
+			new->cid_shift = 4;
+			new->cid_mask = 0xf;
+			new->lid_mask = 0xf;
+		}
+
+		new->phys_map[kvm_apic_id(apic)] = apic;
+
+		ldr = kvm_apic_get_reg(apic, APIC_LDR);
+		cid = apic_cluster_id(new, ldr);
+		lid = apic_logical_id(new, ldr);
+
+		if (lid)
+			new->logical_map[cid][ffs(lid) - 1] = apic;
+	}
+out:
+	old = rcu_dereference_protected(kvm->arch.apic_map,
+			lockdep_is_held(&kvm->arch.apic_map_lock));
+	rcu_assign_pointer(kvm->arch.apic_map, new);
+	mutex_unlock(&kvm->arch.apic_map_lock);
+
+	if (old)
+		kfree_rcu(old, rcu);
+}
+
+static inline void kvm_apic_set_id(struct kvm_lapic *apic, u8 id)
+{
+	apic_set_reg(apic, APIC_ID, id << 24);
+	recalculate_apic_map(apic->vcpu->kvm);
+}
+
+static inline void kvm_apic_set_ldr(struct kvm_lapic *apic, u32 id)
+{
+	apic_set_reg(apic, APIC_LDR, id);
+	recalculate_apic_map(apic->vcpu->kvm);
 }
 
 static inline int apic_lvt_enabled(struct kvm_lapic *apic, int lvt_type)
 {
-	return !(apic_get_reg(apic, lvt_type) & APIC_LVT_MASKED);
+	return !(kvm_apic_get_reg(apic, lvt_type) & APIC_LVT_MASKED);
 }
 
 static inline int apic_lvt_vector(struct kvm_lapic *apic, int lvt_type)
 {
-	return apic_get_reg(apic, lvt_type) & APIC_VECTOR_MASK;
+	return kvm_apic_get_reg(apic, lvt_type) & APIC_VECTOR_MASK;
 }
 
 static inline int apic_lvtt_oneshot(struct kvm_lapic *apic)
 {
-	return ((apic_get_reg(apic, APIC_LVTT) &
+	return ((kvm_apic_get_reg(apic, APIC_LVTT) &
 		apic->lapic_timer.timer_mode_mask) == APIC_LVT_TIMER_ONESHOT);
 }
 
 static inline int apic_lvtt_period(struct kvm_lapic *apic)
 {
-	return ((apic_get_reg(apic, APIC_LVTT) &
+	return ((kvm_apic_get_reg(apic, APIC_LVTT) &
 		apic->lapic_timer.timer_mode_mask) == APIC_LVT_TIMER_PERIODIC);
 }
 
 static inline int apic_lvtt_tscdeadline(struct kvm_lapic *apic)
 {
-	return ((apic_get_reg(apic, APIC_LVTT) &
+	return ((kvm_apic_get_reg(apic, APIC_LVTT) &
 		apic->lapic_timer.timer_mode_mask) ==
 			APIC_LVT_TIMER_TSCDEADLINE);
 }
@@ -184,7 +284,7 @@ void kvm_apic_set_version(struct kvm_vcpu *vcpu)
 	struct kvm_cpuid_entry2 *feat;
 	u32 v = APIC_VERSION;
 
-	if (!irqchip_in_kernel(vcpu->kvm))
+	if (!kvm_vcpu_has_lapic(vcpu))
 		return;
 
 	feat = kvm_find_cpuid_entry(apic->vcpu, 0x1, 0);
@@ -193,12 +293,7 @@ void kvm_apic_set_version(struct kvm_vcpu *vcpu)
 	apic_set_reg(apic, APIC_LVR, v);
 }
 
-static inline int apic_x2apic_mode(struct kvm_lapic *apic)
-{
-	return apic->vcpu->arch.apic_base & X2APIC_ENABLE;
-}
-
-static unsigned int apic_lvt_mask[APIC_LVT_NUM] = {
+static const unsigned int apic_lvt_mask[APIC_LVT_NUM] = {
 	LVT_MASK ,      /* part LVTT mask, timer mode mask added at runtime */
 	LVT_MASK | APIC_MODE_MASK,	/* LVTTHMR */
 	LVT_MASK | APIC_MODE_MASK,	/* LVTPC */
@@ -208,25 +303,30 @@ static unsigned int apic_lvt_mask[APIC_LVT_NUM] = {
 
 static int find_highest_vector(void *bitmap)
 {
-	u32 *word = bitmap;
-	int word_offset = MAX_APIC_VECTOR >> 5;
+	int vec;
+	u32 *reg;
 
-	while ((word_offset != 0) && (word[(--word_offset) << 2] == 0))
-		continue;
+	for (vec = MAX_APIC_VECTOR - APIC_VECTORS_PER_REG;
+	     vec >= 0; vec -= APIC_VECTORS_PER_REG) {
+		reg = bitmap + REG_POS(vec);
+		if (*reg)
+			return fls(*reg) - 1 + vec;
+	}
 
-	if (likely(!word_offset && !word[0]))
-		return -1;
-	else
-		return fls(word[word_offset << 2]) - 1 + (word_offset << 5);
+	return -1;
 }
 
 static u8 count_vectors(void *bitmap)
 {
-	u32 *word = bitmap;
-	int word_offset;
+	int vec;
+	u32 *reg;
 	u8 count = 0;
-	for (word_offset = 0; word_offset < MAX_APIC_VECTOR >> 5; ++word_offset)
-		count += hweight32(word[word_offset << 2]);
+
+	for (vec = 0; vec < MAX_APIC_VECTOR; vec += APIC_VECTORS_PER_REG) {
+		reg = bitmap + REG_POS(vec);
+		count += hweight32(*reg);
+	}
+
 	return count;
 }
 
@@ -285,7 +385,6 @@ static inline void apic_clear_isr(int vec, struct kvm_lapic *apic)
 
 int kvm_lapic_find_highest_irr(struct kvm_vcpu *vcpu)
 {
-	struct kvm_lapic *apic = vcpu->arch.apic;
 	int highest_irr;
 
 	/* This may race with setting of irr in __apic_accept_irq() and
@@ -293,9 +392,9 @@ int kvm_lapic_find_highest_irr(struct kvm_vcpu *vcpu)
 	 * will cause vmexit immediately and the value will be recalculated
 	 * on the next vmentry.
 	 */
-	if (!apic)
+	if (!kvm_vcpu_has_lapic(vcpu))
 		return 0;
-	highest_irr = apic_find_highest_irr(apic);
+	highest_irr = apic_find_highest_irr(vcpu->arch.apic);
 
 	return highest_irr;
 }
@@ -378,8 +477,8 @@ static void apic_update_ppr(struct kvm_lapic *apic)
 	u32 tpr, isrv, ppr, old_ppr;
 	int isr;
 
-	old_ppr = apic_get_reg(apic, APIC_PROCPRI);
-	tpr = apic_get_reg(apic, APIC_TASKPRI);
+	old_ppr = kvm_apic_get_reg(apic, APIC_PROCPRI);
+	tpr = kvm_apic_get_reg(apic, APIC_TASKPRI);
 	isr = apic_find_highest_isr(apic);
 	isrv = (isr != -1) ? isr : 0;
 
@@ -415,13 +514,13 @@ int kvm_apic_match_logical_addr(struct kvm_lapic *apic, u8 mda)
 	u32 logical_id;
 
 	if (apic_x2apic_mode(apic)) {
-		logical_id = apic_get_reg(apic, APIC_LDR);
+		logical_id = kvm_apic_get_reg(apic, APIC_LDR);
 		return logical_id & mda;
 	}
 
-	logical_id = GET_APIC_LOGICAL_ID(apic_get_reg(apic, APIC_LDR));
+	logical_id = GET_APIC_LOGICAL_ID(kvm_apic_get_reg(apic, APIC_LDR));
 
-	switch (apic_get_reg(apic, APIC_DFR)) {
+	switch (kvm_apic_get_reg(apic, APIC_DFR)) {
 	case APIC_DFR_FLAT:
 		if (logical_id & mda)
 			result = 1;
@@ -433,7 +532,7 @@ int kvm_apic_match_logical_addr(struct kvm_lapic *apic, u8 mda)
 		break;
 	default:
 		apic_debug("Bad DFR vcpu %d: %08x\n",
-			   apic->vcpu->vcpu_id, apic_get_reg(apic, APIC_DFR));
+			   apic->vcpu->vcpu_id, kvm_apic_get_reg(apic, APIC_DFR));
 		break;
 	}
 
@@ -478,6 +577,72 @@ int kvm_apic_match_dest(struct kvm_vcpu *vcpu, struct kvm_lapic *source,
 	return result;
 }
 
+bool kvm_irq_delivery_to_apic_fast(struct kvm *kvm, struct kvm_lapic *src,
+		struct kvm_lapic_irq *irq, int *r)
+{
+	struct kvm_apic_map *map;
+	unsigned long bitmap = 1;
+	struct kvm_lapic **dst;
+	int i;
+	bool ret = false;
+
+	*r = -1;
+
+	if (irq->shorthand == APIC_DEST_SELF) {
+		*r = kvm_apic_set_irq(src->vcpu, irq);
+		return true;
+	}
+
+	if (irq->shorthand)
+		return false;
+
+	rcu_read_lock();
+	map = rcu_dereference(kvm->arch.apic_map);
+
+	if (!map)
+		goto out;
+
+	if (irq->dest_mode == 0) { /* physical mode */
+		if (irq->delivery_mode == APIC_DM_LOWEST ||
+				irq->dest_id == 0xff)
+			goto out;
+		dst = &map->phys_map[irq->dest_id & 0xff];
+	} else {
+		u32 mda = irq->dest_id << (32 - map->ldr_bits);
+
+		dst = map->logical_map[apic_cluster_id(map, mda)];
+
+		bitmap = apic_logical_id(map, mda);
+
+		if (irq->delivery_mode == APIC_DM_LOWEST) {
+			int l = -1;
+			for_each_set_bit(i, &bitmap, 16) {
+				if (!dst[i])
+					continue;
+				if (l < 0)
+					l = i;
+				else if (kvm_apic_compare_prio(dst[i]->vcpu, dst[l]->vcpu) < 0)
+					l = i;
+			}
+
+			bitmap = (l >= 0) ? 1 << l : 0;
+		}
+	}
+
+	for_each_set_bit(i, &bitmap, 16) {
+		if (!dst[i])
+			continue;
+		if (*r < 0)
+			*r = 0;
+		*r += kvm_apic_set_irq(dst[i]->vcpu, irq);
+	}
+
+	ret = true;
+out:
+	rcu_read_unlock();
+	return ret;
+}
+
 /*
  * Add a pending IRQ into lapic.
  * Return 1 if successfully added and 0 if discarded.
@@ -591,7 +756,7 @@ static int apic_set_eoi(struct kvm_lapic *apic)
 	apic_clear_isr(vector, apic);
 	apic_update_ppr(apic);
 
-	if (!(apic_get_reg(apic, APIC_SPIV) & APIC_SPIV_DIRECTED_EOI) &&
+	if (!(kvm_apic_get_reg(apic, APIC_SPIV) & APIC_SPIV_DIRECTED_EOI) &&
 	    kvm_ioapic_handles_vector(apic->vcpu->kvm, vector)) {
 		int trigger_mode;
 		if (apic_test_vector(vector, apic->regs + APIC_TMR))
@@ -606,8 +771,8 @@ static int apic_set_eoi(struct kvm_lapic *apic)
 
 static void apic_send_ipi(struct kvm_lapic *apic)
 {
-	u32 icr_low = apic_get_reg(apic, APIC_ICR);
-	u32 icr_high = apic_get_reg(apic, APIC_ICR2);
+	u32 icr_low = kvm_apic_get_reg(apic, APIC_ICR);
+	u32 icr_high = kvm_apic_get_reg(apic, APIC_ICR2);
 	struct kvm_lapic_irq irq;
 
 	irq.vector = icr_low & APIC_VECTOR_MASK;
@@ -642,7 +807,7 @@ static u32 apic_get_tmcct(struct kvm_lapic *apic)
 	ASSERT(apic != NULL);
 
 	/* if initial count is 0, current count should also be 0 */
-	if (apic_get_reg(apic, APIC_TMICT) == 0)
+	if (kvm_apic_get_reg(apic, APIC_TMICT) == 0)
 		return 0;
 
 	remaining = hrtimer_get_remaining(&apic->lapic_timer.timer);
@@ -696,13 +861,15 @@ static u32 __apic_read(struct kvm_lapic *apic, unsigned int offset)
 
 		val = apic_get_tmcct(apic);
 		break;
-
+	case APIC_PROCPRI:
+		apic_update_ppr(apic);
+		val = kvm_apic_get_reg(apic, offset);
+		break;
 	case APIC_TASKPRI:
 		report_tpr_access(apic, false);
 		/* fall thru */
 	default:
-		apic_update_ppr(apic);
-		val = apic_get_reg(apic, offset);
+		val = kvm_apic_get_reg(apic, offset);
 		break;
 	}
 
@@ -719,7 +886,7 @@ static int apic_reg_read(struct kvm_lapic *apic, u32 offset, int len,
 {
 	unsigned char alignment = offset & 0xf;
 	u32 result;
-	/* this bitmask has a bit cleared for each reserver register */
+	/* this bitmask has a bit cleared for each reserved register */
 	static const u64 rmask = 0x43ff01ffffffe70cULL;
 
 	if ((alignment + len) > 4) {
@@ -754,7 +921,7 @@ static int apic_reg_read(struct kvm_lapic *apic, u32 offset, int len,
 
 static int apic_mmio_in_range(struct kvm_lapic *apic, gpa_t addr)
 {
-	return apic_hw_enabled(apic) &&
+	return kvm_apic_hw_enabled(apic) &&
 	    addr >= apic->base_address &&
 	    addr < apic->base_address + LAPIC_MMIO_LENGTH;
 }
@@ -777,7 +944,7 @@ static void update_divide_count(struct kvm_lapic *apic)
 {
 	u32 tmp1, tmp2, tdcr;
 
-	tdcr = apic_get_reg(apic, APIC_TDCR);
+	tdcr = kvm_apic_get_reg(apic, APIC_TDCR);
 	tmp1 = tdcr & 0xf;
 	tmp2 = ((tmp1 & 0x3) | ((tmp1 & 0x8) >> 1)) + 1;
 	apic->divide_count = 0x1 << (tmp2 & 0x7);
@@ -792,9 +959,9 @@ static void start_apic_timer(struct kvm_lapic *apic)
 	atomic_set(&apic->lapic_timer.pending, 0);
 
 	if (apic_lvtt_period(apic) || apic_lvtt_oneshot(apic)) {
-		/* lapic timer in oneshot or peroidic mode */
+		/* lapic timer in oneshot or periodic mode */
 		now = apic->lapic_timer.timer.base->get_time();
-		apic->lapic_timer.period = (u64)apic_get_reg(apic, APIC_TMICT)
+		apic->lapic_timer.period = (u64)kvm_apic_get_reg(apic, APIC_TMICT)
 			    * APIC_BUS_CYCLE_NS * apic->divide_count;
 
 		if (!apic->lapic_timer.period)
@@ -826,7 +993,7 @@ static void start_apic_timer(struct kvm_lapic *apic)
 			   "timer initial count 0x%x, period %lldns, "
 			   "expire @ 0x%016" PRIx64 ".\n", __func__,
 			   APIC_BUS_CYCLE_NS, ktime_to_ns(now),
-			   apic_get_reg(apic, APIC_TMICT),
+			   kvm_apic_get_reg(apic, APIC_TMICT),
 			   apic->lapic_timer.period,
 			   ktime_to_ns(ktime_add_ns(now,
 					apic->lapic_timer.period)));
@@ -858,7 +1025,7 @@ static void start_apic_timer(struct kvm_lapic *apic)
 
 static void apic_manage_nmi_watchdog(struct kvm_lapic *apic, u32 lvt0_val)
 {
-	int nmi_wd_enabled = apic_lvt_nmi_mode(apic_get_reg(apic, APIC_LVT0));
+	int nmi_wd_enabled = apic_lvt_nmi_mode(kvm_apic_get_reg(apic, APIC_LVT0));
 
 	if (apic_lvt_nmi_mode(lvt0_val)) {
 		if (!nmi_wd_enabled) {
@@ -879,7 +1046,7 @@ static int apic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val)
 	switch (reg) {
 	case APIC_ID:		/* Local APIC ID */
 		if (!apic_x2apic_mode(apic))
-			apic_set_reg(apic, APIC_ID, val);
+			kvm_apic_set_id(apic, val >> 24);
 		else
 			ret = 1;
 		break;
@@ -895,29 +1062,30 @@ static int apic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val)
 
 	case APIC_LDR:
 		if (!apic_x2apic_mode(apic))
-			apic_set_reg(apic, APIC_LDR, val & APIC_LDR_MASK);
+			kvm_apic_set_ldr(apic, val & APIC_LDR_MASK);
 		else
 			ret = 1;
 		break;
 
 	case APIC_DFR:
-		if (!apic_x2apic_mode(apic))
+		if (!apic_x2apic_mode(apic)) {
 			apic_set_reg(apic, APIC_DFR, val | 0x0FFFFFFF);
-		else
+			recalculate_apic_map(apic->vcpu->kvm);
+		} else
 			ret = 1;
 		break;
 
 	case APIC_SPIV: {
 		u32 mask = 0x3ff;
-		if (apic_get_reg(apic, APIC_LVR) & APIC_LVR_DIRECTED_EOI)
+		if (kvm_apic_get_reg(apic, APIC_LVR) & APIC_LVR_DIRECTED_EOI)
 			mask |= APIC_SPIV_DIRECTED_EOI;
-		apic_set_reg(apic, APIC_SPIV, val & mask);
+		apic_set_spiv(apic, val & mask);
 		if (!(val & APIC_SPIV_APIC_ENABLED)) {
 			int i;
 			u32 lvt_val;
 
 			for (i = 0; i < APIC_LVT_NUM; i++) {
-				lvt_val = apic_get_reg(apic,
+				lvt_val = kvm_apic_get_reg(apic,
 						       APIC_LVTT + 0x10 * i);
 				apic_set_reg(apic, APIC_LVTT + 0x10 * i,
 					     lvt_val | APIC_LVT_MASKED);
@@ -946,7 +1114,7 @@ static int apic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val)
 	case APIC_LVT1:
 	case APIC_LVTERR:
 		/* TODO: Check vector */
-		if (!apic_sw_enabled(apic))
+		if (!kvm_apic_sw_enabled(apic))
 			val |= APIC_LVT_MASKED;
 
 		val &= apic_lvt_mask[(reg - APIC_LVTT) >> 4];
@@ -955,12 +1123,12 @@ static int apic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val)
 		break;
 
 	case APIC_LVTT:
-		if ((apic_get_reg(apic, APIC_LVTT) &
+		if ((kvm_apic_get_reg(apic, APIC_LVTT) &
 		    apic->lapic_timer.timer_mode_mask) !=
 		   (val & apic->lapic_timer.timer_mode_mask))
 			hrtimer_cancel(&apic->lapic_timer.timer);
 
-		if (!apic_sw_enabled(apic))
+		if (!kvm_apic_sw_enabled(apic))
 			val |= APIC_LVT_MASKED;
 		val &= (apic_lvt_mask[0] | apic->lapic_timer.timer_mode_mask);
 		apic_set_reg(apic, APIC_LVTT, val);
@@ -1039,24 +1207,30 @@ static int apic_mmio_write(struct kvm_io_device *this,
 
 void kvm_lapic_set_eoi(struct kvm_vcpu *vcpu)
 {
-	struct kvm_lapic *apic = vcpu->arch.apic;
-
-	if (apic)
+	if (kvm_vcpu_has_lapic(vcpu))
 		apic_reg_write(vcpu->arch.apic, APIC_EOI, 0);
 }
 EXPORT_SYMBOL_GPL(kvm_lapic_set_eoi);
 
 void kvm_free_lapic(struct kvm_vcpu *vcpu)
 {
+	struct kvm_lapic *apic = vcpu->arch.apic;
+
 	if (!vcpu->arch.apic)
 		return;
 
-	hrtimer_cancel(&vcpu->arch.apic->lapic_timer.timer);
+	hrtimer_cancel(&apic->lapic_timer.timer);
+
+	if (!(vcpu->arch.apic_base & MSR_IA32_APICBASE_ENABLE))
+		static_key_slow_dec_deferred(&apic_hw_disabled);
+
+	if (!(kvm_apic_get_reg(apic, APIC_SPIV) & APIC_SPIV_APIC_ENABLED))
+		static_key_slow_dec_deferred(&apic_sw_disabled);
 
-	if (vcpu->arch.apic->regs)
-		free_page((unsigned long)vcpu->arch.apic->regs);
+	if (apic->regs)
+		free_page((unsigned long)apic->regs);
 
-	kfree(vcpu->arch.apic);
+	kfree(apic);
 }
 
 /*
@@ -1068,10 +1242,9 @@ void kvm_free_lapic(struct kvm_vcpu *vcpu)
 u64 kvm_get_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu)
 {
 	struct kvm_lapic *apic = vcpu->arch.apic;
-	if (!apic)
-		return 0;
 
-	if (apic_lvtt_oneshot(apic) || apic_lvtt_period(apic))
+	if (!kvm_vcpu_has_lapic(vcpu) || apic_lvtt_oneshot(apic) ||
+			apic_lvtt_period(apic))
 		return 0;
 
 	return apic->lapic_timer.tscdeadline;
@@ -1080,10 +1253,9 @@ u64 kvm_get_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu)
 void kvm_set_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu, u64 data)
 {
 	struct kvm_lapic *apic = vcpu->arch.apic;
-	if (!apic)
-		return;
 
-	if (apic_lvtt_oneshot(apic) || apic_lvtt_period(apic))
+	if (!kvm_vcpu_has_lapic(vcpu) || apic_lvtt_oneshot(apic) ||
+			apic_lvtt_period(apic))
 		return;
 
 	hrtimer_cancel(&apic->lapic_timer.timer);
@@ -1095,20 +1267,21 @@ void kvm_lapic_set_tpr(struct kvm_vcpu *vcpu, unsigned long cr8)
 {
 	struct kvm_lapic *apic = vcpu->arch.apic;
 
-	if (!apic)
+	if (!kvm_vcpu_has_lapic(vcpu))
 		return;
+
 	apic_set_tpr(apic, ((cr8 & 0x0f) << 4)
-		     | (apic_get_reg(apic, APIC_TASKPRI) & 4));
+		     | (kvm_apic_get_reg(apic, APIC_TASKPRI) & 4));
 }
 
 u64 kvm_lapic_get_cr8(struct kvm_vcpu *vcpu)
 {
-	struct kvm_lapic *apic = vcpu->arch.apic;
 	u64 tpr;
 
-	if (!apic)
+	if (!kvm_vcpu_has_lapic(vcpu))
 		return 0;
-	tpr = (u64) apic_get_reg(apic, APIC_TASKPRI);
+
+	tpr = (u64) kvm_apic_get_reg(vcpu->arch.apic, APIC_TASKPRI);
 
 	return (tpr & 0xf0) >> 4;
 }
@@ -1123,6 +1296,15 @@ void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value)
 		return;
 	}
 
+	/* update jump label if enable bit changes */
+	if ((vcpu->arch.apic_base ^ value) & MSR_IA32_APICBASE_ENABLE) {
+		if (value & MSR_IA32_APICBASE_ENABLE)
+			static_key_slow_dec_deferred(&apic_hw_disabled);
+		else
+			static_key_slow_inc(&apic_hw_disabled.key);
+		recalculate_apic_map(vcpu->kvm);
+	}
+
 	if (!kvm_vcpu_is_bsp(apic->vcpu))
 		value &= ~MSR_IA32_APICBASE_BSP;
 
@@ -1130,7 +1312,7 @@ void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value)
 	if (apic_x2apic_mode(apic)) {
 		u32 id = kvm_apic_id(apic);
 		u32 ldr = ((id & ~0xf) << 16) | (1 << (id & 0xf));
-		apic_set_reg(apic, APIC_LDR, ldr);
+		kvm_apic_set_ldr(apic, ldr);
 	}
 	apic->base_address = apic->vcpu->arch.apic_base &
 			     MSR_IA32_APICBASE_BASE;
@@ -1155,7 +1337,7 @@ void kvm_lapic_reset(struct kvm_vcpu *vcpu)
 	/* Stop the timer in case it's a reset to an active apic */
 	hrtimer_cancel(&apic->lapic_timer.timer);
 
-	apic_set_reg(apic, APIC_ID, vcpu->vcpu_id << 24);
+	kvm_apic_set_id(apic, vcpu->vcpu_id);
 	kvm_apic_set_version(apic->vcpu);
 
 	for (i = 0; i < APIC_LVT_NUM; i++)
@@ -1164,9 +1346,9 @@ void kvm_lapic_reset(struct kvm_vcpu *vcpu)
 		     SET_APIC_DELIVERY_MODE(0, APIC_MODE_EXTINT));
 
 	apic_set_reg(apic, APIC_DFR, 0xffffffffU);
-	apic_set_reg(apic, APIC_SPIV, 0xff);
+	apic_set_spiv(apic, 0xff);
 	apic_set_reg(apic, APIC_TASKPRI, 0);
-	apic_set_reg(apic, APIC_LDR, 0);
+	kvm_apic_set_ldr(apic, 0);
 	apic_set_reg(apic, APIC_ESR, 0);
 	apic_set_reg(apic, APIC_ICR, 0);
 	apic_set_reg(apic, APIC_ICR2, 0);
@@ -1183,7 +1365,8 @@ void kvm_lapic_reset(struct kvm_vcpu *vcpu)
 	update_divide_count(apic);
 	atomic_set(&apic->lapic_timer.pending, 0);
 	if (kvm_vcpu_is_bsp(vcpu))
-		vcpu->arch.apic_base |= MSR_IA32_APICBASE_BSP;
+		kvm_lapic_set_base(vcpu,
+				vcpu->arch.apic_base | MSR_IA32_APICBASE_BSP);
 	vcpu->arch.pv_eoi.msr_val = 0;
 	apic_update_ppr(apic);
 
@@ -1196,45 +1379,34 @@ void kvm_lapic_reset(struct kvm_vcpu *vcpu)
 		   vcpu->arch.apic_base, apic->base_address);
 }
 
-bool kvm_apic_present(struct kvm_vcpu *vcpu)
-{
-	return vcpu->arch.apic && apic_hw_enabled(vcpu->arch.apic);
-}
-
-int kvm_lapic_enabled(struct kvm_vcpu *vcpu)
-{
-	return kvm_apic_present(vcpu) && apic_sw_enabled(vcpu->arch.apic);
-}
-
 /*
  *----------------------------------------------------------------------
  * timer interface
  *----------------------------------------------------------------------
  */
 
-static bool lapic_is_periodic(struct kvm_timer *ktimer)
+static bool lapic_is_periodic(struct kvm_lapic *apic)
 {
-	struct kvm_lapic *apic = container_of(ktimer, struct kvm_lapic,
-					      lapic_timer);
 	return apic_lvtt_period(apic);
 }
 
 int apic_has_pending_timer(struct kvm_vcpu *vcpu)
 {
-	struct kvm_lapic *lapic = vcpu->arch.apic;
+	struct kvm_lapic *apic = vcpu->arch.apic;
 
-	if (lapic && apic_enabled(lapic) && apic_lvt_enabled(lapic, APIC_LVTT))
-		return atomic_read(&lapic->lapic_timer.pending);
+	if (kvm_vcpu_has_lapic(vcpu) && apic_enabled(apic) &&
+			apic_lvt_enabled(apic, APIC_LVTT))
+		return atomic_read(&apic->lapic_timer.pending);
 
 	return 0;
 }
 
 int kvm_apic_local_deliver(struct kvm_lapic *apic, int lvt_type)
 {
-	u32 reg = apic_get_reg(apic, lvt_type);
+	u32 reg = kvm_apic_get_reg(apic, lvt_type);
 	int vector, mode, trig_mode;
 
-	if (apic_hw_enabled(apic) && !(reg & APIC_LVT_MASKED)) {
+	if (kvm_apic_hw_enabled(apic) && !(reg & APIC_LVT_MASKED)) {
 		vector = reg & APIC_VECTOR_MASK;
 		mode = reg & APIC_MODE_MASK;
 		trig_mode = reg & APIC_LVT_LEVEL_TRIGGER;
@@ -1251,15 +1423,40 @@ void kvm_apic_nmi_wd_deliver(struct kvm_vcpu *vcpu)
 		kvm_apic_local_deliver(apic, APIC_LVT0);
 }
 
-static struct kvm_timer_ops lapic_timer_ops = {
-	.is_periodic = lapic_is_periodic,
-};
-
 static const struct kvm_io_device_ops apic_mmio_ops = {
 	.read     = apic_mmio_read,
 	.write    = apic_mmio_write,
 };
 
+static enum hrtimer_restart apic_timer_fn(struct hrtimer *data)
+{
+	struct kvm_timer *ktimer = container_of(data, struct kvm_timer, timer);
+	struct kvm_lapic *apic = container_of(ktimer, struct kvm_lapic, lapic_timer);
+	struct kvm_vcpu *vcpu = apic->vcpu;
+	wait_queue_head_t *q = &vcpu->wq;
+
+	/*
+	 * There is a race window between reading and incrementing, but we do
+	 * not care about potentially losing timer events in the !reinject
+	 * case anyway. Note: KVM_REQ_PENDING_TIMER is implicitly checked
+	 * in vcpu_enter_guest.
+	 */
+	if (!atomic_read(&ktimer->pending)) {
+		atomic_inc(&ktimer->pending);
+		/* FIXME: this code should not know anything about vcpus */
+		kvm_make_request(KVM_REQ_PENDING_TIMER, vcpu);
+	}
+
+	if (waitqueue_active(q))
+		wake_up_interruptible(q);
+
+	if (lapic_is_periodic(apic)) {
+		hrtimer_add_expires_ns(&ktimer->timer, ktimer->period);
+		return HRTIMER_RESTART;
+	} else
+		return HRTIMER_NORESTART;
+}
+
 int kvm_create_lapic(struct kvm_vcpu *vcpu)
 {
 	struct kvm_lapic *apic;
@@ -1283,14 +1480,17 @@ int kvm_create_lapic(struct kvm_vcpu *vcpu)
 
 	hrtimer_init(&apic->lapic_timer.timer, CLOCK_MONOTONIC,
 		     HRTIMER_MODE_ABS);
-	apic->lapic_timer.timer.function = kvm_timer_fn;
-	apic->lapic_timer.t_ops = &lapic_timer_ops;
-	apic->lapic_timer.kvm = vcpu->kvm;
-	apic->lapic_timer.vcpu = vcpu;
+	apic->lapic_timer.timer.function = apic_timer_fn;
 
-	apic->base_address = APIC_DEFAULT_PHYS_BASE;
-	vcpu->arch.apic_base = APIC_DEFAULT_PHYS_BASE;
+	/*
+	 * APIC is created enabled. This will prevent kvm_lapic_set_base from
+	 * thinking that APIC satet has changed.
+	 */
+	vcpu->arch.apic_base = MSR_IA32_APICBASE_ENABLE;
+	kvm_lapic_set_base(vcpu,
+			APIC_DEFAULT_PHYS_BASE | MSR_IA32_APICBASE_ENABLE);
 
+	static_key_slow_inc(&apic_sw_disabled.key); /* sw disabled at reset */
 	kvm_lapic_reset(vcpu);
 	kvm_iodevice_init(&apic->dev, &apic_mmio_ops);
 
@@ -1306,23 +1506,23 @@ int kvm_apic_has_interrupt(struct kvm_vcpu *vcpu)
 	struct kvm_lapic *apic = vcpu->arch.apic;
 	int highest_irr;
 
-	if (!apic || !apic_enabled(apic))
+	if (!kvm_vcpu_has_lapic(vcpu) || !apic_enabled(apic))
 		return -1;
 
 	apic_update_ppr(apic);
 	highest_irr = apic_find_highest_irr(apic);
 	if ((highest_irr == -1) ||
-	    ((highest_irr & 0xF0) <= apic_get_reg(apic, APIC_PROCPRI)))
+	    ((highest_irr & 0xF0) <= kvm_apic_get_reg(apic, APIC_PROCPRI)))
 		return -1;
 	return highest_irr;
 }
 
 int kvm_apic_accept_pic_intr(struct kvm_vcpu *vcpu)
 {
-	u32 lvt0 = apic_get_reg(vcpu->arch.apic, APIC_LVT0);
+	u32 lvt0 = kvm_apic_get_reg(vcpu->arch.apic, APIC_LVT0);
 	int r = 0;
 
-	if (!apic_hw_enabled(vcpu->arch.apic))
+	if (!kvm_apic_hw_enabled(vcpu->arch.apic))
 		r = 1;
 	if ((lvt0 & APIC_LVT_MASKED) == 0 &&
 	    GET_APIC_DELIVERY_MODE(lvt0) == APIC_MODE_EXTINT)
@@ -1334,7 +1534,10 @@ void kvm_inject_apic_timer_irqs(struct kvm_vcpu *vcpu)
 {
 	struct kvm_lapic *apic = vcpu->arch.apic;
 
-	if (apic && atomic_read(&apic->lapic_timer.pending) > 0) {
+	if (!kvm_vcpu_has_lapic(vcpu))
+		return;
+
+	if (atomic_read(&apic->lapic_timer.pending) > 0) {
 		if (kvm_apic_local_deliver(apic, APIC_LVTT))
 			atomic_dec(&apic->lapic_timer.pending);
 	}
@@ -1354,12 +1557,17 @@ int kvm_get_apic_interrupt(struct kvm_vcpu *vcpu)
 	return vector;
 }
 
-void kvm_apic_post_state_restore(struct kvm_vcpu *vcpu)
+void kvm_apic_post_state_restore(struct kvm_vcpu *vcpu,
+		struct kvm_lapic_state *s)
 {
 	struct kvm_lapic *apic = vcpu->arch.apic;
 
-	apic->base_address = vcpu->arch.apic_base &
-			     MSR_IA32_APICBASE_BASE;
+	kvm_lapic_set_base(vcpu, vcpu->arch.apic_base);
+	/* set SPIV separately to get count of SW disabled APICs right */
+	apic_set_spiv(apic, *((u32 *)(s->regs + APIC_SPIV)));
+	memcpy(vcpu->arch.apic->regs, s->regs, sizeof *s);
+	/* call kvm_apic_set_id() to put apic into apic_map */
+	kvm_apic_set_id(apic, kvm_apic_id(apic));
 	kvm_apic_set_version(vcpu);
 
 	apic_update_ppr(apic);
@@ -1374,13 +1582,12 @@ void kvm_apic_post_state_restore(struct kvm_vcpu *vcpu)
 
 void __kvm_migrate_apic_timer(struct kvm_vcpu *vcpu)
 {
-	struct kvm_lapic *apic = vcpu->arch.apic;
 	struct hrtimer *timer;
 
-	if (!apic)
+	if (!kvm_vcpu_has_lapic(vcpu))
 		return;
 
-	timer = &apic->lapic_timer.timer;
+	timer = &vcpu->arch.apic->lapic_timer.timer;
 	if (hrtimer_cancel(timer))
 		hrtimer_start_expires(timer, HRTIMER_MODE_ABS);
 }
@@ -1478,7 +1685,7 @@ void kvm_lapic_sync_to_vapic(struct kvm_vcpu *vcpu)
 	if (!test_bit(KVM_APIC_CHECK_VAPIC, &vcpu->arch.apic_attention))
 		return;
 
-	tpr = apic_get_reg(apic, APIC_TASKPRI) & 0xff;
+	tpr = kvm_apic_get_reg(apic, APIC_TASKPRI) & 0xff;
 	max_irr = apic_find_highest_irr(apic);
 	if (max_irr < 0)
 		max_irr = 0;
@@ -1537,7 +1744,7 @@ int kvm_hv_vapic_msr_write(struct kvm_vcpu *vcpu, u32 reg, u64 data)
 {
 	struct kvm_lapic *apic = vcpu->arch.apic;
 
-	if (!irqchip_in_kernel(vcpu->kvm))
+	if (!kvm_vcpu_has_lapic(vcpu))
 		return 1;
 
 	/* if this is ICR write vector before command */
@@ -1551,7 +1758,7 @@ int kvm_hv_vapic_msr_read(struct kvm_vcpu *vcpu, u32 reg, u64 *data)
 	struct kvm_lapic *apic = vcpu->arch.apic;
 	u32 low, high = 0;
 
-	if (!irqchip_in_kernel(vcpu->kvm))
+	if (!kvm_vcpu_has_lapic(vcpu))
 		return 1;
 
 	if (apic_reg_read(apic, reg, 4, &low))
@@ -1576,3 +1783,10 @@ int kvm_lapic_enable_pv_eoi(struct kvm_vcpu *vcpu, u64 data)
 	return kvm_gfn_to_hva_cache_init(vcpu->kvm, &vcpu->arch.pv_eoi.data,
 					 addr);
 }
+
+void kvm_lapic_init(void)
+{
+	/* do not patch jump label more than once per second */
+	jump_label_rate_limit(&apic_hw_disabled, HZ);
+	jump_label_rate_limit(&apic_sw_disabled, HZ);
+}
diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h
index 4af5405..e5ebf9f 100644
--- a/arch/x86/kvm/lapic.h
+++ b/arch/x86/kvm/lapic.h
@@ -2,10 +2,17 @@
 #define __KVM_X86_LAPIC_H
 
 #include "iodev.h"
-#include "kvm_timer.h"
 
 #include <linux/kvm_host.h>
 
+struct kvm_timer {
+	struct hrtimer timer;
+	s64 period; 				/* unit: ns */
+	u32 timer_mode_mask;
+	u64 tscdeadline;
+	atomic_t pending;			/* accumulated triggered timers */
+};
+
 struct kvm_lapic {
 	unsigned long base_address;
 	struct kvm_io_device dev;
@@ -45,11 +52,13 @@ int kvm_apic_match_logical_addr(struct kvm_lapic *apic, u8 mda);
 int kvm_apic_set_irq(struct kvm_vcpu *vcpu, struct kvm_lapic_irq *irq);
 int kvm_apic_local_deliver(struct kvm_lapic *apic, int lvt_type);
 
+bool kvm_irq_delivery_to_apic_fast(struct kvm *kvm, struct kvm_lapic *src,
+		struct kvm_lapic_irq *irq, int *r);
+
 u64 kvm_get_apic_base(struct kvm_vcpu *vcpu);
 void kvm_set_apic_base(struct kvm_vcpu *vcpu, u64 data);
-void kvm_apic_post_state_restore(struct kvm_vcpu *vcpu);
-int kvm_lapic_enabled(struct kvm_vcpu *vcpu);
-bool kvm_apic_present(struct kvm_vcpu *vcpu);
+void kvm_apic_post_state_restore(struct kvm_vcpu *vcpu,
+		struct kvm_lapic_state *s);
 int kvm_lapic_find_highest_irr(struct kvm_vcpu *vcpu);
 
 u64 kvm_get_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu);
@@ -71,4 +80,48 @@ static inline bool kvm_hv_vapic_assist_page_enabled(struct kvm_vcpu *vcpu)
 }
 
 int kvm_lapic_enable_pv_eoi(struct kvm_vcpu *vcpu, u64 data);
+void kvm_lapic_init(void);
+
+static inline u32 kvm_apic_get_reg(struct kvm_lapic *apic, int reg_off)
+{
+	        return *((u32 *) (apic->regs + reg_off));
+}
+
+extern struct static_key kvm_no_apic_vcpu;
+
+static inline bool kvm_vcpu_has_lapic(struct kvm_vcpu *vcpu)
+{
+	if (static_key_false(&kvm_no_apic_vcpu))
+		return vcpu->arch.apic;
+	return true;
+}
+
+extern struct static_key_deferred apic_hw_disabled;
+
+static inline int kvm_apic_hw_enabled(struct kvm_lapic *apic)
+{
+	if (static_key_false(&apic_hw_disabled.key))
+		return apic->vcpu->arch.apic_base & MSR_IA32_APICBASE_ENABLE;
+	return MSR_IA32_APICBASE_ENABLE;
+}
+
+extern struct static_key_deferred apic_sw_disabled;
+
+static inline int kvm_apic_sw_enabled(struct kvm_lapic *apic)
+{
+	if (static_key_false(&apic_sw_disabled.key))
+		return kvm_apic_get_reg(apic, APIC_SPIV) & APIC_SPIV_APIC_ENABLED;
+	return APIC_SPIV_APIC_ENABLED;
+}
+
+static inline bool kvm_apic_present(struct kvm_vcpu *vcpu)
+{
+	return kvm_vcpu_has_lapic(vcpu) && kvm_apic_hw_enabled(vcpu->arch.apic);
+}
+
+static inline int kvm_lapic_enabled(struct kvm_vcpu *vcpu)
+{
+	return kvm_apic_present(vcpu) && kvm_apic_sw_enabled(vcpu->arch.apic);
+}
+
 #endif
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index 7fbd0d2..d289fee 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -556,6 +556,14 @@ static int mmu_spte_clear_track_bits(u64 *sptep)
 		return 0;
 
 	pfn = spte_to_pfn(old_spte);
+
+	/*
+	 * KVM does not hold the refcount of the page used by
+	 * kvm mmu, before reclaiming the page, we should
+	 * unmap it from mmu first.
+	 */
+	WARN_ON(!kvm_is_mmio_pfn(pfn) && !page_count(pfn_to_page(pfn)));
+
 	if (!shadow_accessed_mask || old_spte & shadow_accessed_mask)
 		kvm_set_pfn_accessed(pfn);
 	if (!shadow_dirty_mask || (old_spte & shadow_dirty_mask))
@@ -960,13 +968,10 @@ static void pte_list_walk(unsigned long *pte_list, pte_list_walk_fn fn)
 static unsigned long *__gfn_to_rmap(gfn_t gfn, int level,
 				    struct kvm_memory_slot *slot)
 {
-	struct kvm_lpage_info *linfo;
-
-	if (likely(level == PT_PAGE_TABLE_LEVEL))
-		return &slot->rmap[gfn - slot->base_gfn];
+	unsigned long idx;
 
-	linfo = lpage_info_slot(gfn, slot, level);
-	return &linfo->rmap_pde;
+	idx = gfn_to_index(gfn, slot->base_gfn, level);
+	return &slot->arch.rmap[level - PT_PAGE_TABLE_LEVEL][idx];
 }
 
 /*
@@ -1173,7 +1178,8 @@ void kvm_mmu_write_protect_pt_masked(struct kvm *kvm,
 	unsigned long *rmapp;
 
 	while (mask) {
-		rmapp = &slot->rmap[gfn_offset + __ffs(mask)];
+		rmapp = __gfn_to_rmap(slot->base_gfn + gfn_offset + __ffs(mask),
+				      PT_PAGE_TABLE_LEVEL, slot);
 		__rmap_write_protect(kvm, rmapp, PT_PAGE_TABLE_LEVEL, false);
 
 		/* clear the first set bit */
@@ -1200,7 +1206,7 @@ static bool rmap_write_protect(struct kvm *kvm, u64 gfn)
 }
 
 static int kvm_unmap_rmapp(struct kvm *kvm, unsigned long *rmapp,
-			   unsigned long data)
+			   struct kvm_memory_slot *slot, unsigned long data)
 {
 	u64 *sptep;
 	struct rmap_iterator iter;
@@ -1218,7 +1224,7 @@ static int kvm_unmap_rmapp(struct kvm *kvm, unsigned long *rmapp,
 }
 
 static int kvm_set_pte_rmapp(struct kvm *kvm, unsigned long *rmapp,
-			     unsigned long data)
+			     struct kvm_memory_slot *slot, unsigned long data)
 {
 	u64 *sptep;
 	struct rmap_iterator iter;
@@ -1259,43 +1265,67 @@ static int kvm_set_pte_rmapp(struct kvm *kvm, unsigned long *rmapp,
 	return 0;
 }
 
-static int kvm_handle_hva(struct kvm *kvm, unsigned long hva,
-			  unsigned long data,
-			  int (*handler)(struct kvm *kvm, unsigned long *rmapp,
-					 unsigned long data))
+static int kvm_handle_hva_range(struct kvm *kvm,
+				unsigned long start,
+				unsigned long end,
+				unsigned long data,
+				int (*handler)(struct kvm *kvm,
+					       unsigned long *rmapp,
+					       struct kvm_memory_slot *slot,
+					       unsigned long data))
 {
 	int j;
-	int ret;
-	int retval = 0;
+	int ret = 0;
 	struct kvm_memslots *slots;
 	struct kvm_memory_slot *memslot;
 
 	slots = kvm_memslots(kvm);
 
 	kvm_for_each_memslot(memslot, slots) {
-		unsigned long start = memslot->userspace_addr;
-		unsigned long end;
+		unsigned long hva_start, hva_end;
+		gfn_t gfn_start, gfn_end;
 
-		end = start + (memslot->npages << PAGE_SHIFT);
-		if (hva >= start && hva < end) {
-			gfn_t gfn_offset = (hva - start) >> PAGE_SHIFT;
-			gfn_t gfn = memslot->base_gfn + gfn_offset;
+		hva_start = max(start, memslot->userspace_addr);
+		hva_end = min(end, memslot->userspace_addr +
+					(memslot->npages << PAGE_SHIFT));
+		if (hva_start >= hva_end)
+			continue;
+		/*
+		 * {gfn(page) | page intersects with [hva_start, hva_end)} =
+		 * {gfn_start, gfn_start+1, ..., gfn_end-1}.
+		 */
+		gfn_start = hva_to_gfn_memslot(hva_start, memslot);
+		gfn_end = hva_to_gfn_memslot(hva_end + PAGE_SIZE - 1, memslot);
 
-			ret = handler(kvm, &memslot->rmap[gfn_offset], data);
+		for (j = PT_PAGE_TABLE_LEVEL;
+		     j < PT_PAGE_TABLE_LEVEL + KVM_NR_PAGE_SIZES; ++j) {
+			unsigned long idx, idx_end;
+			unsigned long *rmapp;
 
-			for (j = 0; j < KVM_NR_PAGE_SIZES - 1; ++j) {
-				struct kvm_lpage_info *linfo;
+			/*
+			 * {idx(page_j) | page_j intersects with
+			 *  [hva_start, hva_end)} = {idx, idx+1, ..., idx_end}.
+			 */
+			idx = gfn_to_index(gfn_start, memslot->base_gfn, j);
+			idx_end = gfn_to_index(gfn_end - 1, memslot->base_gfn, j);
 
-				linfo = lpage_info_slot(gfn, memslot,
-							PT_DIRECTORY_LEVEL + j);
-				ret |= handler(kvm, &linfo->rmap_pde, data);
-			}
-			trace_kvm_age_page(hva, memslot, ret);
-			retval |= ret;
+			rmapp = __gfn_to_rmap(gfn_start, j, memslot);
+
+			for (; idx <= idx_end; ++idx)
+				ret |= handler(kvm, rmapp++, memslot, data);
 		}
 	}
 
-	return retval;
+	return ret;
+}
+
+static int kvm_handle_hva(struct kvm *kvm, unsigned long hva,
+			  unsigned long data,
+			  int (*handler)(struct kvm *kvm, unsigned long *rmapp,
+					 struct kvm_memory_slot *slot,
+					 unsigned long data))
+{
+	return kvm_handle_hva_range(kvm, hva, hva + 1, data, handler);
 }
 
 int kvm_unmap_hva(struct kvm *kvm, unsigned long hva)
@@ -1303,13 +1333,18 @@ int kvm_unmap_hva(struct kvm *kvm, unsigned long hva)
 	return kvm_handle_hva(kvm, hva, 0, kvm_unmap_rmapp);
 }
 
+int kvm_unmap_hva_range(struct kvm *kvm, unsigned long start, unsigned long end)
+{
+	return kvm_handle_hva_range(kvm, start, end, 0, kvm_unmap_rmapp);
+}
+
 void kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte)
 {
 	kvm_handle_hva(kvm, hva, (unsigned long)&pte, kvm_set_pte_rmapp);
 }
 
 static int kvm_age_rmapp(struct kvm *kvm, unsigned long *rmapp,
-			 unsigned long data)
+			 struct kvm_memory_slot *slot, unsigned long data)
 {
 	u64 *sptep;
 	struct rmap_iterator uninitialized_var(iter);
@@ -1323,8 +1358,10 @@ static int kvm_age_rmapp(struct kvm *kvm, unsigned long *rmapp,
 	 * This has some overhead, but not as much as the cost of swapping
 	 * out actively used pages or breaking up actively used hugepages.
 	 */
-	if (!shadow_accessed_mask)
-		return kvm_unmap_rmapp(kvm, rmapp, data);
+	if (!shadow_accessed_mask) {
+		young = kvm_unmap_rmapp(kvm, rmapp, slot, data);
+		goto out;
+	}
 
 	for (sptep = rmap_get_first(*rmapp, &iter); sptep;
 	     sptep = rmap_get_next(&iter)) {
@@ -1336,12 +1373,14 @@ static int kvm_age_rmapp(struct kvm *kvm, unsigned long *rmapp,
 				 (unsigned long *)sptep);
 		}
 	}
-
+out:
+	/* @data has hva passed to kvm_age_hva(). */
+	trace_kvm_age_page(data, slot, young);
 	return young;
 }
 
 static int kvm_test_age_rmapp(struct kvm *kvm, unsigned long *rmapp,
-			      unsigned long data)
+			      struct kvm_memory_slot *slot, unsigned long data)
 {
 	u64 *sptep;
 	struct rmap_iterator iter;
@@ -1379,13 +1418,13 @@ static void rmap_recycle(struct kvm_vcpu *vcpu, u64 *spte, gfn_t gfn)
 
 	rmapp = gfn_to_rmap(vcpu->kvm, gfn, sp->role.level);
 
-	kvm_unmap_rmapp(vcpu->kvm, rmapp, 0);
+	kvm_unmap_rmapp(vcpu->kvm, rmapp, NULL, 0);
 	kvm_flush_remote_tlbs(vcpu->kvm);
 }
 
 int kvm_age_hva(struct kvm *kvm, unsigned long hva)
 {
-	return kvm_handle_hva(kvm, hva, 0, kvm_age_rmapp);
+	return kvm_handle_hva(kvm, hva, hva, kvm_age_rmapp);
 }
 
 int kvm_test_age_hva(struct kvm *kvm, unsigned long hva)
@@ -2457,7 +2496,9 @@ static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *sptep,
 				rmap_recycle(vcpu, sptep, gfn);
 		}
 	}
-	kvm_release_pfn_clean(pfn);
+
+	if (!is_error_pfn(pfn))
+		kvm_release_pfn_clean(pfn);
 }
 
 static void nonpaging_new_cr3(struct kvm_vcpu *vcpu)
@@ -2469,17 +2510,12 @@ static pfn_t pte_prefetch_gfn_to_pfn(struct kvm_vcpu *vcpu, gfn_t gfn,
 				     bool no_dirty_log)
 {
 	struct kvm_memory_slot *slot;
-	unsigned long hva;
 
 	slot = gfn_to_memslot_dirty_bitmap(vcpu, gfn, no_dirty_log);
-	if (!slot) {
-		get_page(fault_page);
-		return page_to_pfn(fault_page);
-	}
+	if (!slot)
+		return KVM_PFN_ERR_FAULT;
 
-	hva = gfn_to_hva_memslot(slot, gfn);
-
-	return hva_to_pfn_atomic(vcpu->kvm, hva);
+	return gfn_to_pfn_memslot_atomic(slot, gfn);
 }
 
 static int direct_pte_prefetch_many(struct kvm_vcpu *vcpu,
@@ -2580,11 +2616,6 @@ static int __direct_map(struct kvm_vcpu *vcpu, gpa_t v, int write,
 			sp = kvm_mmu_get_page(vcpu, pseudo_gfn, iterator.addr,
 					      iterator.level - 1,
 					      1, ACC_ALL, iterator.sptep);
-			if (!sp) {
-				pgprintk("nonpaging_map: ENOMEM\n");
-				kvm_release_pfn_clean(pfn);
-				return -ENOMEM;
-			}
 
 			mmu_spte_set(iterator.sptep,
 				     __pa(sp->spt)
@@ -2611,8 +2642,16 @@ static void kvm_send_hwpoison_signal(unsigned long address, struct task_struct *
 
 static int kvm_handle_bad_page(struct kvm_vcpu *vcpu, gfn_t gfn, pfn_t pfn)
 {
-	kvm_release_pfn_clean(pfn);
-	if (is_hwpoison_pfn(pfn)) {
+	/*
+	 * Do not cache the mmio info caused by writing the readonly gfn
+	 * into the spte otherwise read access on readonly gfn also can
+	 * caused mmio page fault and treat it as mmio access.
+	 * Return 1 to tell kvm to emulate it.
+	 */
+	if (pfn == KVM_PFN_ERR_RO_FAULT)
+		return 1;
+
+	if (pfn == KVM_PFN_ERR_HWPOISON) {
 		kvm_send_hwpoison_signal(gfn_to_hva(vcpu->kvm, gfn), current);
 		return 0;
 	}
@@ -3236,8 +3275,6 @@ static bool try_async_pf(struct kvm_vcpu *vcpu, bool prefault, gfn_t gfn,
 	if (!async)
 		return false; /* *pfn has correct page already */
 
-	put_page(pfn_to_page(*pfn));
-
 	if (!prefault && can_do_async_pf(vcpu)) {
 		trace_kvm_try_async_get_page(gva, gfn);
 		if (kvm_find_async_pf_gfn(vcpu, gfn)) {
@@ -3371,6 +3408,18 @@ static bool is_rsvd_bits_set(struct kvm_mmu *mmu, u64 gpte, int level)
 	return (gpte & mmu->rsvd_bits_mask[bit7][level-1]) != 0;
 }
 
+static inline void protect_clean_gpte(unsigned *access, unsigned gpte)
+{
+	unsigned mask;
+
+	BUILD_BUG_ON(PT_WRITABLE_MASK != ACC_WRITE_MASK);
+
+	mask = (unsigned)~ACC_WRITE_MASK;
+	/* Allow write access to dirty gptes */
+	mask |= (gpte >> (PT_DIRTY_SHIFT - PT_WRITABLE_SHIFT)) & PT_WRITABLE_MASK;
+	*access &= mask;
+}
+
 static bool sync_mmio_spte(u64 *sptep, gfn_t gfn, unsigned access,
 			   int *nr_present)
 {
@@ -3388,6 +3437,25 @@ static bool sync_mmio_spte(u64 *sptep, gfn_t gfn, unsigned access,
 	return false;
 }
 
+static inline unsigned gpte_access(struct kvm_vcpu *vcpu, u64 gpte)
+{
+	unsigned access;
+
+	access = (gpte & (PT_WRITABLE_MASK | PT_USER_MASK)) | ACC_EXEC_MASK;
+	access &= ~(gpte >> PT64_NX_SHIFT);
+
+	return access;
+}
+
+static inline bool is_last_gpte(struct kvm_mmu *mmu, unsigned level, unsigned gpte)
+{
+	unsigned index;
+
+	index = level - 1;
+	index |= (gpte & PT_PAGE_SIZE_MASK) >> (PT_PAGE_SIZE_SHIFT - 2);
+	return mmu->last_pte_bitmap & (1 << index);
+}
+
 #define PTTYPE 64
 #include "paging_tmpl.h"
 #undef PTTYPE
@@ -3457,6 +3525,56 @@ static void reset_rsvds_bits_mask(struct kvm_vcpu *vcpu,
 	}
 }
 
+static void update_permission_bitmask(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu)
+{
+	unsigned bit, byte, pfec;
+	u8 map;
+	bool fault, x, w, u, wf, uf, ff, smep;
+
+	smep = kvm_read_cr4_bits(vcpu, X86_CR4_SMEP);
+	for (byte = 0; byte < ARRAY_SIZE(mmu->permissions); ++byte) {
+		pfec = byte << 1;
+		map = 0;
+		wf = pfec & PFERR_WRITE_MASK;
+		uf = pfec & PFERR_USER_MASK;
+		ff = pfec & PFERR_FETCH_MASK;
+		for (bit = 0; bit < 8; ++bit) {
+			x = bit & ACC_EXEC_MASK;
+			w = bit & ACC_WRITE_MASK;
+			u = bit & ACC_USER_MASK;
+
+			/* Not really needed: !nx will cause pte.nx to fault */
+			x |= !mmu->nx;
+			/* Allow supervisor writes if !cr0.wp */
+			w |= !is_write_protection(vcpu) && !uf;
+			/* Disallow supervisor fetches of user code if cr4.smep */
+			x &= !(smep && u && !uf);
+
+			fault = (ff && !x) || (uf && !u) || (wf && !w);
+			map |= fault << bit;
+		}
+		mmu->permissions[byte] = map;
+	}
+}
+
+static void update_last_pte_bitmap(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu)
+{
+	u8 map;
+	unsigned level, root_level = mmu->root_level;
+	const unsigned ps_set_index = 1 << 2;  /* bit 2 of index: ps */
+
+	if (root_level == PT32E_ROOT_LEVEL)
+		--root_level;
+	/* PT_PAGE_TABLE_LEVEL always terminates */
+	map = 1 | (1 << ps_set_index);
+	for (level = PT_DIRECTORY_LEVEL; level <= root_level; ++level) {
+		if (level <= PT_PDPE_LEVEL
+		    && (mmu->root_level >= PT32E_ROOT_LEVEL || is_pse(vcpu)))
+			map |= 1 << (ps_set_index | (level - 1));
+	}
+	mmu->last_pte_bitmap = map;
+}
+
 static int paging64_init_context_common(struct kvm_vcpu *vcpu,
 					struct kvm_mmu *context,
 					int level)
@@ -3465,6 +3583,8 @@ static int paging64_init_context_common(struct kvm_vcpu *vcpu,
 	context->root_level = level;
 
 	reset_rsvds_bits_mask(vcpu, context);
+	update_permission_bitmask(vcpu, context);
+	update_last_pte_bitmap(vcpu, context);
 
 	ASSERT(is_pae(vcpu));
 	context->new_cr3 = paging_new_cr3;
@@ -3493,6 +3613,8 @@ static int paging32_init_context(struct kvm_vcpu *vcpu,
 	context->root_level = PT32_ROOT_LEVEL;
 
 	reset_rsvds_bits_mask(vcpu, context);
+	update_permission_bitmask(vcpu, context);
+	update_last_pte_bitmap(vcpu, context);
 
 	context->new_cr3 = paging_new_cr3;
 	context->page_fault = paging32_page_fault;
@@ -3553,6 +3675,9 @@ static int init_kvm_tdp_mmu(struct kvm_vcpu *vcpu)
 		context->gva_to_gpa = paging32_gva_to_gpa;
 	}
 
+	update_permission_bitmask(vcpu, context);
+	update_last_pte_bitmap(vcpu, context);
+
 	return 0;
 }
 
@@ -3628,6 +3753,9 @@ static int init_kvm_nested_mmu(struct kvm_vcpu *vcpu)
 		g_context->gva_to_gpa = paging32_gva_to_gpa_nested;
 	}
 
+	update_permission_bitmask(vcpu, g_context);
+	update_last_pte_bitmap(vcpu, g_context);
+
 	return 0;
 }
 
diff --git a/arch/x86/kvm/mmu.h b/arch/x86/kvm/mmu.h
index e374db9..6987108 100644
--- a/arch/x86/kvm/mmu.h
+++ b/arch/x86/kvm/mmu.h
@@ -18,8 +18,10 @@
 #define PT_PCD_MASK (1ULL << 4)
 #define PT_ACCESSED_SHIFT 5
 #define PT_ACCESSED_MASK (1ULL << PT_ACCESSED_SHIFT)
-#define PT_DIRTY_MASK (1ULL << 6)
-#define PT_PAGE_SIZE_MASK (1ULL << 7)
+#define PT_DIRTY_SHIFT 6
+#define PT_DIRTY_MASK (1ULL << PT_DIRTY_SHIFT)
+#define PT_PAGE_SIZE_SHIFT 7
+#define PT_PAGE_SIZE_MASK (1ULL << PT_PAGE_SIZE_SHIFT)
 #define PT_PAT_MASK (1ULL << 7)
 #define PT_GLOBAL_MASK (1ULL << 8)
 #define PT64_NX_SHIFT 63
@@ -88,17 +90,14 @@ static inline bool is_write_protection(struct kvm_vcpu *vcpu)
 	return kvm_read_cr0_bits(vcpu, X86_CR0_WP);
 }
 
-static inline bool check_write_user_access(struct kvm_vcpu *vcpu,
-					   bool write_fault, bool user_fault,
-					   unsigned long pte)
+/*
+ * Will a fault with a given page-fault error code (pfec) cause a permission
+ * fault with the given access (in ACC_* format)?
+ */
+static inline bool permission_fault(struct kvm_mmu *mmu, unsigned pte_access,
+				    unsigned pfec)
 {
-	if (unlikely(write_fault && !is_writable_pte(pte)
-	      && (user_fault || is_write_protection(vcpu))))
-		return false;
-
-	if (unlikely(user_fault && !(pte & PT_USER_MASK)))
-		return false;
-
-	return true;
+	return (mmu->permissions[pfec >> 1] >> pte_access) & 1;
 }
+
 #endif
diff --git a/arch/x86/kvm/mmu_audit.c b/arch/x86/kvm/mmu_audit.c
index 7d7d0b9..daff69e 100644
--- a/arch/x86/kvm/mmu_audit.c
+++ b/arch/x86/kvm/mmu_audit.c
@@ -116,10 +116,8 @@ static void audit_mappings(struct kvm_vcpu *vcpu, u64 *sptep, int level)
 	gfn = kvm_mmu_page_get_gfn(sp, sptep - sp->spt);
 	pfn = gfn_to_pfn_atomic(vcpu->kvm, gfn);
 
-	if (is_error_pfn(pfn)) {
-		kvm_release_pfn_clean(pfn);
+	if (is_error_pfn(pfn))
 		return;
-	}
 
 	hpa =  pfn << PAGE_SHIFT;
 	if ((*sptep & PT64_BASE_ADDR_MASK) != hpa)
@@ -190,7 +188,6 @@ static void check_mappings_rmap(struct kvm *kvm, struct kvm_mmu_page *sp)
 
 static void audit_write_protection(struct kvm *kvm, struct kvm_mmu_page *sp)
 {
-	struct kvm_memory_slot *slot;
 	unsigned long *rmapp;
 	u64 *sptep;
 	struct rmap_iterator iter;
@@ -198,8 +195,7 @@ static void audit_write_protection(struct kvm *kvm, struct kvm_mmu_page *sp)
 	if (sp->role.direct || sp->unsync || sp->role.invalid)
 		return;
 
-	slot = gfn_to_memslot(kvm, sp->gfn);
-	rmapp = &slot->rmap[sp->gfn - slot->base_gfn];
+	rmapp = gfn_to_rmap(kvm, sp->gfn, PT_PAGE_TABLE_LEVEL);
 
 	for (sptep = rmap_get_first(*rmapp, &iter); sptep;
 	     sptep = rmap_get_next(&iter)) {
diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h
index bb7cf01..714e2c0 100644
--- a/arch/x86/kvm/paging_tmpl.h
+++ b/arch/x86/kvm/paging_tmpl.h
@@ -63,10 +63,12 @@
  */
 struct guest_walker {
 	int level;
+	unsigned max_level;
 	gfn_t table_gfn[PT_MAX_FULL_LEVELS];
 	pt_element_t ptes[PT_MAX_FULL_LEVELS];
 	pt_element_t prefetch_ptes[PTE_PREFETCH_NUM];
 	gpa_t pte_gpa[PT_MAX_FULL_LEVELS];
+	pt_element_t __user *ptep_user[PT_MAX_FULL_LEVELS];
 	unsigned pt_access;
 	unsigned pte_access;
 	gfn_t gfn;
@@ -101,38 +103,41 @@ static int FNAME(cmpxchg_gpte)(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu,
 	return (ret != orig_pte);
 }
 
-static unsigned FNAME(gpte_access)(struct kvm_vcpu *vcpu, pt_element_t gpte,
-				   bool last)
+static int FNAME(update_accessed_dirty_bits)(struct kvm_vcpu *vcpu,
+					     struct kvm_mmu *mmu,
+					     struct guest_walker *walker,
+					     int write_fault)
 {
-	unsigned access;
-
-	access = (gpte & (PT_WRITABLE_MASK | PT_USER_MASK)) | ACC_EXEC_MASK;
-	if (last && !is_dirty_gpte(gpte))
-		access &= ~ACC_WRITE_MASK;
-
-#if PTTYPE == 64
-	if (vcpu->arch.mmu.nx)
-		access &= ~(gpte >> PT64_NX_SHIFT);
-#endif
-	return access;
-}
-
-static bool FNAME(is_last_gpte)(struct guest_walker *walker,
-				struct kvm_vcpu *vcpu, struct kvm_mmu *mmu,
-				pt_element_t gpte)
-{
-	if (walker->level == PT_PAGE_TABLE_LEVEL)
-		return true;
-
-	if ((walker->level == PT_DIRECTORY_LEVEL) && is_large_pte(gpte) &&
-	    (PTTYPE == 64 || is_pse(vcpu)))
-		return true;
+	unsigned level, index;
+	pt_element_t pte, orig_pte;
+	pt_element_t __user *ptep_user;
+	gfn_t table_gfn;
+	int ret;
+
+	for (level = walker->max_level; level >= walker->level; --level) {
+		pte = orig_pte = walker->ptes[level - 1];
+		table_gfn = walker->table_gfn[level - 1];
+		ptep_user = walker->ptep_user[level - 1];
+		index = offset_in_page(ptep_user) / sizeof(pt_element_t);
+		if (!(pte & PT_ACCESSED_MASK)) {
+			trace_kvm_mmu_set_accessed_bit(table_gfn, index, sizeof(pte));
+			pte |= PT_ACCESSED_MASK;
+		}
+		if (level == walker->level && write_fault && !is_dirty_gpte(pte)) {
+			trace_kvm_mmu_set_dirty_bit(table_gfn, index, sizeof(pte));
+			pte |= PT_DIRTY_MASK;
+		}
+		if (pte == orig_pte)
+			continue;
 
-	if ((walker->level == PT_PDPE_LEVEL) && is_large_pte(gpte) &&
-	    (mmu->root_level == PT64_ROOT_LEVEL))
-		return true;
+		ret = FNAME(cmpxchg_gpte)(vcpu, mmu, ptep_user, index, orig_pte, pte);
+		if (ret)
+			return ret;
 
-	return false;
+		mark_page_dirty(vcpu->kvm, table_gfn);
+		walker->ptes[level] = pte;
+	}
+	return 0;
 }
 
 /*
@@ -142,21 +147,22 @@ static int FNAME(walk_addr_generic)(struct guest_walker *walker,
 				    struct kvm_vcpu *vcpu, struct kvm_mmu *mmu,
 				    gva_t addr, u32 access)
 {
+	int ret;
 	pt_element_t pte;
 	pt_element_t __user *uninitialized_var(ptep_user);
 	gfn_t table_gfn;
-	unsigned index, pt_access, uninitialized_var(pte_access);
+	unsigned index, pt_access, pte_access, accessed_dirty, shift;
 	gpa_t pte_gpa;
-	bool eperm, last_gpte;
 	int offset;
 	const int write_fault = access & PFERR_WRITE_MASK;
 	const int user_fault  = access & PFERR_USER_MASK;
 	const int fetch_fault = access & PFERR_FETCH_MASK;
 	u16 errcode = 0;
+	gpa_t real_gpa;
+	gfn_t gfn;
 
 	trace_kvm_mmu_pagetable_walk(addr, access);
 retry_walk:
-	eperm = false;
 	walker->level = mmu->root_level;
 	pte           = mmu->get_cr3(vcpu);
 
@@ -169,15 +175,21 @@ retry_walk:
 		--walker->level;
 	}
 #endif
+	walker->max_level = walker->level;
 	ASSERT((!is_long_mode(vcpu) && is_pae(vcpu)) ||
 	       (mmu->get_cr3(vcpu) & CR3_NONPAE_RESERVED_BITS) == 0);
 
-	pt_access = ACC_ALL;
+	accessed_dirty = PT_ACCESSED_MASK;
+	pt_access = pte_access = ACC_ALL;
+	++walker->level;
 
-	for (;;) {
+	do {
 		gfn_t real_gfn;
 		unsigned long host_addr;
 
+		pt_access &= pte_access;
+		--walker->level;
+
 		index = PT_INDEX(addr, walker->level);
 
 		table_gfn = gpte_to_gfn(pte);
@@ -199,6 +211,7 @@ retry_walk:
 		ptep_user = (pt_element_t __user *)((void *)host_addr + offset);
 		if (unlikely(__copy_from_user(&pte, ptep_user, sizeof(pte))))
 			goto error;
+		walker->ptep_user[walker->level - 1] = ptep_user;
 
 		trace_kvm_mmu_paging_element(pte, walker->level);
 
@@ -211,92 +224,48 @@ retry_walk:
 			goto error;
 		}
 
-		if (!check_write_user_access(vcpu, write_fault, user_fault,
-					  pte))
-			eperm = true;
-
-#if PTTYPE == 64
-		if (unlikely(fetch_fault && (pte & PT64_NX_MASK)))
-			eperm = true;
-#endif
-
-		last_gpte = FNAME(is_last_gpte)(walker, vcpu, mmu, pte);
-		if (last_gpte) {
-			pte_access = pt_access &
-				     FNAME(gpte_access)(vcpu, pte, true);
-			/* check if the kernel is fetching from user page */
-			if (unlikely(pte_access & PT_USER_MASK) &&
-			    kvm_read_cr4_bits(vcpu, X86_CR4_SMEP))
-				if (fetch_fault && !user_fault)
-					eperm = true;
-		}
-
-		if (!eperm && unlikely(!(pte & PT_ACCESSED_MASK))) {
-			int ret;
-			trace_kvm_mmu_set_accessed_bit(table_gfn, index,
-						       sizeof(pte));
-			ret = FNAME(cmpxchg_gpte)(vcpu, mmu, ptep_user, index,
-						  pte, pte|PT_ACCESSED_MASK);
-			if (unlikely(ret < 0))
-				goto error;
-			else if (ret)
-				goto retry_walk;
-
-			mark_page_dirty(vcpu->kvm, table_gfn);
-			pte |= PT_ACCESSED_MASK;
-		}
+		accessed_dirty &= pte;
+		pte_access = pt_access & gpte_access(vcpu, pte);
 
 		walker->ptes[walker->level - 1] = pte;
+	} while (!is_last_gpte(mmu, walker->level, pte));
 
-		if (last_gpte) {
-			int lvl = walker->level;
-			gpa_t real_gpa;
-			gfn_t gfn;
-			u32 ac;
-
-			gfn = gpte_to_gfn_lvl(pte, lvl);
-			gfn += (addr & PT_LVL_OFFSET_MASK(lvl)) >> PAGE_SHIFT;
-
-			if (PTTYPE == 32 &&
-			    walker->level == PT_DIRECTORY_LEVEL &&
-			    is_cpuid_PSE36())
-				gfn += pse36_gfn_delta(pte);
-
-			ac = write_fault | fetch_fault | user_fault;
+	if (unlikely(permission_fault(mmu, pte_access, access))) {
+		errcode |= PFERR_PRESENT_MASK;
+		goto error;
+	}
 
-			real_gpa = mmu->translate_gpa(vcpu, gfn_to_gpa(gfn),
-						      ac);
-			if (real_gpa == UNMAPPED_GVA)
-				return 0;
+	gfn = gpte_to_gfn_lvl(pte, walker->level);
+	gfn += (addr & PT_LVL_OFFSET_MASK(walker->level)) >> PAGE_SHIFT;
 
-			walker->gfn = real_gpa >> PAGE_SHIFT;
+	if (PTTYPE == 32 && walker->level == PT_DIRECTORY_LEVEL && is_cpuid_PSE36())
+		gfn += pse36_gfn_delta(pte);
 
-			break;
-		}
+	real_gpa = mmu->translate_gpa(vcpu, gfn_to_gpa(gfn), access);
+	if (real_gpa == UNMAPPED_GVA)
+		return 0;
 
-		pt_access &= FNAME(gpte_access)(vcpu, pte, false);
-		--walker->level;
-	}
+	walker->gfn = real_gpa >> PAGE_SHIFT;
 
-	if (unlikely(eperm)) {
-		errcode |= PFERR_PRESENT_MASK;
-		goto error;
-	}
+	if (!write_fault)
+		protect_clean_gpte(&pte_access, pte);
 
-	if (write_fault && unlikely(!is_dirty_gpte(pte))) {
-		int ret;
+	/*
+	 * On a write fault, fold the dirty bit into accessed_dirty by shifting it one
+	 * place right.
+	 *
+	 * On a read fault, do nothing.
+	 */
+	shift = write_fault >> ilog2(PFERR_WRITE_MASK);
+	shift *= PT_DIRTY_SHIFT - PT_ACCESSED_SHIFT;
+	accessed_dirty &= pte >> shift;
 
-		trace_kvm_mmu_set_dirty_bit(table_gfn, index, sizeof(pte));
-		ret = FNAME(cmpxchg_gpte)(vcpu, mmu, ptep_user, index,
-					  pte, pte|PT_DIRTY_MASK);
+	if (unlikely(!accessed_dirty)) {
+		ret = FNAME(update_accessed_dirty_bits)(vcpu, mmu, walker, write_fault);
 		if (unlikely(ret < 0))
 			goto error;
 		else if (ret)
 			goto retry_walk;
-
-		mark_page_dirty(vcpu->kvm, table_gfn);
-		pte |= PT_DIRTY_MASK;
-		walker->ptes[walker->level - 1] = pte;
 	}
 
 	walker->pt_access = pt_access;
@@ -368,12 +337,11 @@ static void FNAME(update_pte)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp,
 		return;
 
 	pgprintk("%s: gpte %llx spte %p\n", __func__, (u64)gpte, spte);
-	pte_access = sp->role.access & FNAME(gpte_access)(vcpu, gpte, true);
+	pte_access = sp->role.access & gpte_access(vcpu, gpte);
+	protect_clean_gpte(&pte_access, gpte);
 	pfn = gfn_to_pfn_atomic(vcpu->kvm, gpte_to_gfn(gpte));
-	if (mmu_invalid_pfn(pfn)) {
-		kvm_release_pfn_clean(pfn);
+	if (mmu_invalid_pfn(pfn))
 		return;
-	}
 
 	/*
 	 * we call mmu_set_spte() with host_writable = true because that
@@ -443,15 +411,13 @@ static void FNAME(pte_prefetch)(struct kvm_vcpu *vcpu, struct guest_walker *gw,
 		if (FNAME(prefetch_invalid_gpte)(vcpu, sp, spte, gpte))
 			continue;
 
-		pte_access = sp->role.access & FNAME(gpte_access)(vcpu, gpte,
-								  true);
+		pte_access = sp->role.access & gpte_access(vcpu, gpte);
+		protect_clean_gpte(&pte_access, gpte);
 		gfn = gpte_to_gfn(gpte);
 		pfn = pte_prefetch_gfn_to_pfn(vcpu, gfn,
 				      pte_access & ACC_WRITE_MASK);
-		if (mmu_invalid_pfn(pfn)) {
-			kvm_release_pfn_clean(pfn);
+		if (mmu_invalid_pfn(pfn))
 			break;
-		}
 
 		mmu_set_spte(vcpu, spte, sp->role.access, pte_access, 0, 0,
 			     NULL, PT_PAGE_TABLE_LEVEL, gfn,
@@ -798,7 +764,8 @@ static int FNAME(sync_page)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp)
 
 		gfn = gpte_to_gfn(gpte);
 		pte_access = sp->role.access;
-		pte_access &= FNAME(gpte_access)(vcpu, gpte, true);
+		pte_access &= gpte_access(vcpu, gpte);
+		protect_clean_gpte(&pte_access, gpte);
 
 		if (sync_mmio_spte(&sp->spt[i], gfn, pte_access, &nr_present))
 			continue;
diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c
index 9b7ec11..cfc258a 100644
--- a/arch/x86/kvm/pmu.c
+++ b/arch/x86/kvm/pmu.c
@@ -1,5 +1,5 @@
 /*
- * Kernel-based Virtual Machine -- Performane Monitoring Unit support
+ * Kernel-based Virtual Machine -- Performance Monitoring Unit support
  *
  * Copyright 2011 Red Hat, Inc. and/or its affiliates.
  *
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index baead95..818fceb 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -163,7 +163,7 @@ static DEFINE_PER_CPU(u64, current_tsc_ratio);
 
 #define MSR_INVALID			0xffffffffU
 
-static struct svm_direct_access_msrs {
+static const struct svm_direct_access_msrs {
 	u32 index;   /* Index of the MSR */
 	bool always; /* True if intercept is always on */
 } direct_access_msrs[] = {
@@ -400,7 +400,7 @@ struct svm_init_data {
 	int r;
 };
 
-static u32 msrpm_ranges[] = {0, 0xc0000000, 0xc0010000};
+static const u32 msrpm_ranges[] = {0, 0xc0000000, 0xc0010000};
 
 #define NUM_MSR_MAPS ARRAY_SIZE(msrpm_ranges)
 #define MSRS_RANGE_SIZE 2048
@@ -2063,7 +2063,7 @@ static inline bool nested_svm_intr(struct vcpu_svm *svm)
 	if (svm->nested.intercept & 1ULL) {
 		/*
 		 * The #vmexit can't be emulated here directly because this
-		 * code path runs with irqs and preemtion disabled. A
+		 * code path runs with irqs and preemption disabled. A
 		 * #vmexit emulation might sleep. Only signal request for
 		 * the #vmexit here.
 		 */
@@ -2105,7 +2105,6 @@ static void *nested_svm_map(struct vcpu_svm *svm, u64 gpa, struct page **_page)
 	return kmap(page);
 
 error:
-	kvm_release_page_clean(page);
 	kvm_inject_gp(&svm->vcpu, 0);
 
 	return NULL;
@@ -2409,7 +2408,7 @@ static bool nested_svm_vmrun_msrpm(struct vcpu_svm *svm)
 {
 	/*
 	 * This function merges the msr permission bitmaps of kvm and the
-	 * nested vmcb. It is omptimized in that it only merges the parts where
+	 * nested vmcb. It is optimized in that it only merges the parts where
 	 * the kvm msr permission bitmap may contain zero bits
 	 */
 	int i;
@@ -3268,7 +3267,7 @@ static int pause_interception(struct vcpu_svm *svm)
 	return 1;
 }
 
-static int (*svm_exit_handlers[])(struct vcpu_svm *svm) = {
+static int (*const svm_exit_handlers[])(struct vcpu_svm *svm) = {
 	[SVM_EXIT_READ_CR0]			= cr_interception,
 	[SVM_EXIT_READ_CR3]			= cr_interception,
 	[SVM_EXIT_READ_CR4]			= cr_interception,
@@ -3783,12 +3782,6 @@ static void svm_cancel_injection(struct kvm_vcpu *vcpu)
 	svm_complete_interrupts(svm);
 }
 
-#ifdef CONFIG_X86_64
-#define R "r"
-#else
-#define R "e"
-#endif
-
 static void svm_vcpu_run(struct kvm_vcpu *vcpu)
 {
 	struct vcpu_svm *svm = to_svm(vcpu);
@@ -3815,13 +3808,13 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu)
 	local_irq_enable();
 
 	asm volatile (
-		"push %%"R"bp; \n\t"
-		"mov %c[rbx](%[svm]), %%"R"bx \n\t"
-		"mov %c[rcx](%[svm]), %%"R"cx \n\t"
-		"mov %c[rdx](%[svm]), %%"R"dx \n\t"
-		"mov %c[rsi](%[svm]), %%"R"si \n\t"
-		"mov %c[rdi](%[svm]), %%"R"di \n\t"
-		"mov %c[rbp](%[svm]), %%"R"bp \n\t"
+		"push %%" _ASM_BP "; \n\t"
+		"mov %c[rbx](%[svm]), %%" _ASM_BX " \n\t"
+		"mov %c[rcx](%[svm]), %%" _ASM_CX " \n\t"
+		"mov %c[rdx](%[svm]), %%" _ASM_DX " \n\t"
+		"mov %c[rsi](%[svm]), %%" _ASM_SI " \n\t"
+		"mov %c[rdi](%[svm]), %%" _ASM_DI " \n\t"
+		"mov %c[rbp](%[svm]), %%" _ASM_BP " \n\t"
 #ifdef CONFIG_X86_64
 		"mov %c[r8](%[svm]),  %%r8  \n\t"
 		"mov %c[r9](%[svm]),  %%r9  \n\t"
@@ -3834,20 +3827,20 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu)
 #endif
 
 		/* Enter guest mode */
-		"push %%"R"ax \n\t"
-		"mov %c[vmcb](%[svm]), %%"R"ax \n\t"
+		"push %%" _ASM_AX " \n\t"
+		"mov %c[vmcb](%[svm]), %%" _ASM_AX " \n\t"
 		__ex(SVM_VMLOAD) "\n\t"
 		__ex(SVM_VMRUN) "\n\t"
 		__ex(SVM_VMSAVE) "\n\t"
-		"pop %%"R"ax \n\t"
+		"pop %%" _ASM_AX " \n\t"
 
 		/* Save guest registers, load host registers */
-		"mov %%"R"bx, %c[rbx](%[svm]) \n\t"
-		"mov %%"R"cx, %c[rcx](%[svm]) \n\t"
-		"mov %%"R"dx, %c[rdx](%[svm]) \n\t"
-		"mov %%"R"si, %c[rsi](%[svm]) \n\t"
-		"mov %%"R"di, %c[rdi](%[svm]) \n\t"
-		"mov %%"R"bp, %c[rbp](%[svm]) \n\t"
+		"mov %%" _ASM_BX ", %c[rbx](%[svm]) \n\t"
+		"mov %%" _ASM_CX ", %c[rcx](%[svm]) \n\t"
+		"mov %%" _ASM_DX ", %c[rdx](%[svm]) \n\t"
+		"mov %%" _ASM_SI ", %c[rsi](%[svm]) \n\t"
+		"mov %%" _ASM_DI ", %c[rdi](%[svm]) \n\t"
+		"mov %%" _ASM_BP ", %c[rbp](%[svm]) \n\t"
 #ifdef CONFIG_X86_64
 		"mov %%r8,  %c[r8](%[svm]) \n\t"
 		"mov %%r9,  %c[r9](%[svm]) \n\t"
@@ -3858,7 +3851,7 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu)
 		"mov %%r14, %c[r14](%[svm]) \n\t"
 		"mov %%r15, %c[r15](%[svm]) \n\t"
 #endif
-		"pop %%"R"bp"
+		"pop %%" _ASM_BP
 		:
 		: [svm]"a"(svm),
 		  [vmcb]"i"(offsetof(struct vcpu_svm, vmcb_pa)),
@@ -3879,9 +3872,11 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu)
 		  [r15]"i"(offsetof(struct vcpu_svm, vcpu.arch.regs[VCPU_REGS_R15]))
 #endif
 		: "cc", "memory"
-		, R"bx", R"cx", R"dx", R"si", R"di"
 #ifdef CONFIG_X86_64
+		, "rbx", "rcx", "rdx", "rsi", "rdi"
 		, "r8", "r9", "r10", "r11" , "r12", "r13", "r14", "r15"
+#else
+		, "ebx", "ecx", "edx", "esi", "edi"
 #endif
 		);
 
@@ -3941,8 +3936,6 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu)
 	mark_all_clean(svm->vmcb);
 }
 
-#undef R
-
 static void svm_set_cr3(struct kvm_vcpu *vcpu, unsigned long root)
 {
 	struct vcpu_svm *svm = to_svm(vcpu);
@@ -4069,7 +4062,7 @@ static void svm_fpu_deactivate(struct kvm_vcpu *vcpu)
 #define POST_MEM(exit) { .exit_code = (exit), \
 			.stage = X86_ICPT_POST_MEMACCESS, }
 
-static struct __x86_intercept {
+static const struct __x86_intercept {
 	u32 exit_code;
 	enum x86_intercept_stage stage;
 } x86_intercept_map[] = {
diff --git a/arch/x86/kvm/timer.c b/arch/x86/kvm/timer.c
deleted file mode 100644
index 6b85cc6..0000000
--- a/arch/x86/kvm/timer.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Kernel-based Virtual Machine driver for Linux
- *
- * This module enables machines with Intel VT-x extensions to run virtual
- * machines without emulation or binary translation.
- *
- * timer support
- *
- * Copyright 2010 Red Hat, Inc. and/or its affiliates.
- *
- * This work is licensed under the terms of the GNU GPL, version 2.  See
- * the COPYING file in the top-level directory.
- */
-
-#include <linux/kvm_host.h>
-#include <linux/kvm.h>
-#include <linux/hrtimer.h>
-#include <linux/atomic.h>
-#include "kvm_timer.h"
-
-enum hrtimer_restart kvm_timer_fn(struct hrtimer *data)
-{
-	struct kvm_timer *ktimer = container_of(data, struct kvm_timer, timer);
-	struct kvm_vcpu *vcpu = ktimer->vcpu;
-	wait_queue_head_t *q = &vcpu->wq;
-
-	/*
-	 * There is a race window between reading and incrementing, but we do
-	 * not care about potentially losing timer events in the !reinject
-	 * case anyway. Note: KVM_REQ_PENDING_TIMER is implicitly checked
-	 * in vcpu_enter_guest.
-	 */
-	if (ktimer->reinject || !atomic_read(&ktimer->pending)) {
-		atomic_inc(&ktimer->pending);
-		/* FIXME: this code should not know anything about vcpus */
-		kvm_make_request(KVM_REQ_PENDING_TIMER, vcpu);
-	}
-
-	if (waitqueue_active(q))
-		wake_up_interruptible(q);
-
-	if (ktimer->t_ops->is_periodic(ktimer)) {
-		hrtimer_add_expires_ns(&ktimer->timer, ktimer->period);
-		return HRTIMER_RESTART;
-	} else
-		return HRTIMER_NORESTART;
-}
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index b1eb202..c8b28c4 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -127,6 +127,8 @@ module_param(ple_gap, int, S_IRUGO);
 static int ple_window = KVM_VMX_DEFAULT_PLE_WINDOW;
 module_param(ple_window, int, S_IRUGO);
 
+extern const ulong vmx_return;
+
 #define NR_AUTOLOAD_MSRS 8
 #define VMCS02_POOL_SIZE 1
 
@@ -405,16 +407,16 @@ struct vcpu_vmx {
 	struct {
 		int vm86_active;
 		ulong save_rflags;
+		struct kvm_segment segs[8];
+	} rmode;
+	struct {
+		u32 bitmask; /* 4 bits per segment (1 bit per field) */
 		struct kvm_save_segment {
 			u16 selector;
 			unsigned long base;
 			u32 limit;
 			u32 ar;
-		} tr, es, ds, fs, gs;
-	} rmode;
-	struct {
-		u32 bitmask; /* 4 bits per segment (1 bit per field) */
-		struct kvm_save_segment seg[8];
+		} seg[8];
 	} segment_cache;
 	int vpid;
 	bool emulation_required;
@@ -450,7 +452,7 @@ static inline struct vcpu_vmx *to_vmx(struct kvm_vcpu *vcpu)
 #define FIELD64(number, name)	[number] = VMCS12_OFFSET(name), \
 				[number##_HIGH] = VMCS12_OFFSET(name)+4
 
-static unsigned short vmcs_field_to_offset_table[] = {
+static const unsigned short vmcs_field_to_offset_table[] = {
 	FIELD(VIRTUAL_PROCESSOR_ID, virtual_processor_id),
 	FIELD(GUEST_ES_SELECTOR, guest_es_selector),
 	FIELD(GUEST_CS_SELECTOR, guest_cs_selector),
@@ -596,10 +598,9 @@ static inline struct vmcs12 *get_vmcs12(struct kvm_vcpu *vcpu)
 static struct page *nested_get_page(struct kvm_vcpu *vcpu, gpa_t addr)
 {
 	struct page *page = gfn_to_page(vcpu->kvm, addr >> PAGE_SHIFT);
-	if (is_error_page(page)) {
-		kvm_release_page_clean(page);
+	if (is_error_page(page))
 		return NULL;
-	}
+
 	return page;
 }
 
@@ -667,7 +668,7 @@ static struct vmx_capability {
 		.ar_bytes = GUEST_##seg##_AR_BYTES,	   	\
 	}
 
-static struct kvm_vmx_segment_field {
+static const struct kvm_vmx_segment_field {
 	unsigned selector;
 	unsigned base;
 	unsigned limit;
@@ -1343,7 +1344,7 @@ static bool update_transition_efer(struct vcpu_vmx *vmx, int efer_offset)
 	guest_efer = vmx->vcpu.arch.efer;
 
 	/*
-	 * NX is emulated; LMA and LME handled by hardware; SCE meaninless
+	 * NX is emulated; LMA and LME handled by hardware; SCE meaningless
 	 * outside long mode
 	 */
 	ignore_bits = EFER_NX | EFER_SCE;
@@ -1493,8 +1494,12 @@ static void __vmx_load_host_state(struct vcpu_vmx *vmx)
 #ifdef CONFIG_X86_64
 	wrmsrl(MSR_KERNEL_GS_BASE, vmx->msr_host_kernel_gs_base);
 #endif
-	if (user_has_fpu())
-		clts();
+	/*
+	 * If the FPU is not active (through the host task or
+	 * the guest vcpu), then restore the cr0.TS bit.
+	 */
+	if (!user_has_fpu() && !vmx->vcpu.guest_fpu_loaded)
+		stts();
 	load_gdt(&__get_cpu_var(host_gdt));
 }
 
@@ -1991,7 +1996,7 @@ static __init void nested_vmx_setup_ctls_msrs(void)
 #endif
 		CPU_BASED_MOV_DR_EXITING | CPU_BASED_UNCOND_IO_EXITING |
 		CPU_BASED_USE_IO_BITMAPS | CPU_BASED_MONITOR_EXITING |
-		CPU_BASED_RDPMC_EXITING |
+		CPU_BASED_RDPMC_EXITING | CPU_BASED_RDTSC_EXITING |
 		CPU_BASED_ACTIVATE_SECONDARY_CONTROLS;
 	/*
 	 * We can allow some features even when not supported by the
@@ -2694,20 +2699,17 @@ static __exit void hardware_unsetup(void)
 	free_kvm_area();
 }
 
-static void fix_pmode_dataseg(int seg, struct kvm_save_segment *save)
+static void fix_pmode_dataseg(struct kvm_vcpu *vcpu, int seg, struct kvm_segment *save)
 {
-	struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg];
+	const struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg];
+	struct kvm_segment tmp = *save;
 
-	if (vmcs_readl(sf->base) == save->base && (save->base & AR_S_MASK)) {
-		vmcs_write16(sf->selector, save->selector);
-		vmcs_writel(sf->base, save->base);
-		vmcs_write32(sf->limit, save->limit);
-		vmcs_write32(sf->ar_bytes, save->ar);
-	} else {
-		u32 dpl = (vmcs_read16(sf->selector) & SELECTOR_RPL_MASK)
-			<< AR_DPL_SHIFT;
-		vmcs_write32(sf->ar_bytes, 0x93 | dpl);
+	if (!(vmcs_readl(sf->base) == tmp.base && tmp.s)) {
+		tmp.base = vmcs_readl(sf->base);
+		tmp.selector = vmcs_read16(sf->selector);
+		tmp.s = 1;
 	}
+	vmx_set_segment(vcpu, &tmp, seg);
 }
 
 static void enter_pmode(struct kvm_vcpu *vcpu)
@@ -2720,10 +2722,7 @@ static void enter_pmode(struct kvm_vcpu *vcpu)
 
 	vmx_segment_cache_clear(vmx);
 
-	vmcs_write16(GUEST_TR_SELECTOR, vmx->rmode.tr.selector);
-	vmcs_writel(GUEST_TR_BASE, vmx->rmode.tr.base);
-	vmcs_write32(GUEST_TR_LIMIT, vmx->rmode.tr.limit);
-	vmcs_write32(GUEST_TR_AR_BYTES, vmx->rmode.tr.ar);
+	vmx_set_segment(vcpu, &vmx->rmode.segs[VCPU_SREG_TR], VCPU_SREG_TR);
 
 	flags = vmcs_readl(GUEST_RFLAGS);
 	flags &= RMODE_GUEST_OWNED_EFLAGS_BITS;
@@ -2738,10 +2737,10 @@ static void enter_pmode(struct kvm_vcpu *vcpu)
 	if (emulate_invalid_guest_state)
 		return;
 
-	fix_pmode_dataseg(VCPU_SREG_ES, &vmx->rmode.es);
-	fix_pmode_dataseg(VCPU_SREG_DS, &vmx->rmode.ds);
-	fix_pmode_dataseg(VCPU_SREG_GS, &vmx->rmode.gs);
-	fix_pmode_dataseg(VCPU_SREG_FS, &vmx->rmode.fs);
+	fix_pmode_dataseg(vcpu, VCPU_SREG_ES, &vmx->rmode.segs[VCPU_SREG_ES]);
+	fix_pmode_dataseg(vcpu, VCPU_SREG_DS, &vmx->rmode.segs[VCPU_SREG_DS]);
+	fix_pmode_dataseg(vcpu, VCPU_SREG_FS, &vmx->rmode.segs[VCPU_SREG_FS]);
+	fix_pmode_dataseg(vcpu, VCPU_SREG_GS, &vmx->rmode.segs[VCPU_SREG_GS]);
 
 	vmx_segment_cache_clear(vmx);
 
@@ -2769,14 +2768,10 @@ static gva_t rmode_tss_base(struct kvm *kvm)
 	return kvm->arch.tss_addr;
 }
 
-static void fix_rmode_seg(int seg, struct kvm_save_segment *save)
+static void fix_rmode_seg(int seg, struct kvm_segment *save)
 {
-	struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg];
+	const struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg];
 
-	save->selector = vmcs_read16(sf->selector);
-	save->base = vmcs_readl(sf->base);
-	save->limit = vmcs_read32(sf->limit);
-	save->ar = vmcs_read32(sf->ar_bytes);
 	vmcs_write16(sf->selector, save->base >> 4);
 	vmcs_write32(sf->base, save->base & 0xffff0);
 	vmcs_write32(sf->limit, 0xffff);
@@ -2796,9 +2791,16 @@ static void enter_rmode(struct kvm_vcpu *vcpu)
 	if (enable_unrestricted_guest)
 		return;
 
+	vmx_get_segment(vcpu, &vmx->rmode.segs[VCPU_SREG_TR], VCPU_SREG_TR);
+	vmx_get_segment(vcpu, &vmx->rmode.segs[VCPU_SREG_ES], VCPU_SREG_ES);
+	vmx_get_segment(vcpu, &vmx->rmode.segs[VCPU_SREG_DS], VCPU_SREG_DS);
+	vmx_get_segment(vcpu, &vmx->rmode.segs[VCPU_SREG_FS], VCPU_SREG_FS);
+	vmx_get_segment(vcpu, &vmx->rmode.segs[VCPU_SREG_GS], VCPU_SREG_GS);
+
 	vmx->emulation_required = 1;
 	vmx->rmode.vm86_active = 1;
 
+
 	/*
 	 * Very old userspace does not call KVM_SET_TSS_ADDR before entering
 	 * vcpu. Call it here with phys address pointing 16M below 4G.
@@ -2813,14 +2815,8 @@ static void enter_rmode(struct kvm_vcpu *vcpu)
 
 	vmx_segment_cache_clear(vmx);
 
-	vmx->rmode.tr.selector = vmcs_read16(GUEST_TR_SELECTOR);
-	vmx->rmode.tr.base = vmcs_readl(GUEST_TR_BASE);
 	vmcs_writel(GUEST_TR_BASE, rmode_tss_base(vcpu->kvm));
-
-	vmx->rmode.tr.limit = vmcs_read32(GUEST_TR_LIMIT);
 	vmcs_write32(GUEST_TR_LIMIT, RMODE_TSS_SIZE - 1);
-
-	vmx->rmode.tr.ar = vmcs_read32(GUEST_TR_AR_BYTES);
 	vmcs_write32(GUEST_TR_AR_BYTES, 0x008b);
 
 	flags = vmcs_readl(GUEST_RFLAGS);
@@ -3113,35 +3109,24 @@ static void vmx_get_segment(struct kvm_vcpu *vcpu,
 			    struct kvm_segment *var, int seg)
 {
 	struct vcpu_vmx *vmx = to_vmx(vcpu);
-	struct kvm_save_segment *save;
 	u32 ar;
 
 	if (vmx->rmode.vm86_active
 	    && (seg == VCPU_SREG_TR || seg == VCPU_SREG_ES
 		|| seg == VCPU_SREG_DS || seg == VCPU_SREG_FS
-		|| seg == VCPU_SREG_GS)
-	    && !emulate_invalid_guest_state) {
-		switch (seg) {
-		case VCPU_SREG_TR: save = &vmx->rmode.tr; break;
-		case VCPU_SREG_ES: save = &vmx->rmode.es; break;
-		case VCPU_SREG_DS: save = &vmx->rmode.ds; break;
-		case VCPU_SREG_FS: save = &vmx->rmode.fs; break;
-		case VCPU_SREG_GS: save = &vmx->rmode.gs; break;
-		default: BUG();
-		}
-		var->selector = save->selector;
-		var->base = save->base;
-		var->limit = save->limit;
-		ar = save->ar;
+		|| seg == VCPU_SREG_GS)) {
+		*var = vmx->rmode.segs[seg];
 		if (seg == VCPU_SREG_TR
 		    || var->selector == vmx_read_guest_seg_selector(vmx, seg))
-			goto use_saved_rmode_seg;
+			return;
+		var->base = vmx_read_guest_seg_base(vmx, seg);
+		var->selector = vmx_read_guest_seg_selector(vmx, seg);
+		return;
 	}
 	var->base = vmx_read_guest_seg_base(vmx, seg);
 	var->limit = vmx_read_guest_seg_limit(vmx, seg);
 	var->selector = vmx_read_guest_seg_selector(vmx, seg);
 	ar = vmx_read_guest_seg_ar(vmx, seg);
-use_saved_rmode_seg:
 	if ((ar & AR_UNUSABLE_MASK) && !emulate_invalid_guest_state)
 		ar = 0;
 	var->type = ar & 15;
@@ -3223,23 +3208,21 @@ static void vmx_set_segment(struct kvm_vcpu *vcpu,
 			    struct kvm_segment *var, int seg)
 {
 	struct vcpu_vmx *vmx = to_vmx(vcpu);
-	struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg];
+	const struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg];
 	u32 ar;
 
 	vmx_segment_cache_clear(vmx);
 
 	if (vmx->rmode.vm86_active && seg == VCPU_SREG_TR) {
 		vmcs_write16(sf->selector, var->selector);
-		vmx->rmode.tr.selector = var->selector;
-		vmx->rmode.tr.base = var->base;
-		vmx->rmode.tr.limit = var->limit;
-		vmx->rmode.tr.ar = vmx_segment_access_rights(var);
+		vmx->rmode.segs[VCPU_SREG_TR] = *var;
 		return;
 	}
 	vmcs_writel(sf->base, var->base);
 	vmcs_write32(sf->limit, var->limit);
 	vmcs_write16(sf->selector, var->selector);
 	if (vmx->rmode.vm86_active && var->s) {
+		vmx->rmode.segs[seg] = *var;
 		/*
 		 * Hack real-mode segments into vm86 compatibility.
 		 */
@@ -3254,7 +3237,7 @@ static void vmx_set_segment(struct kvm_vcpu *vcpu,
 	 * qemu binaries.
 	 *   IA32 arch specifies that at the time of processor reset the
 	 * "Accessed" bit in the AR field of segment registers is 1. And qemu
-	 * is setting it to 0 in the usedland code. This causes invalid guest
+	 * is setting it to 0 in the userland code. This causes invalid guest
 	 * state vmexit when "unrestricted guest" mode is turned on.
 	 *    Fix for this setup issue in cpu_reset is being pushed in the qemu
 	 * tree. Newer qemu binaries with that qemu fix would not need this
@@ -3284,16 +3267,10 @@ static void vmx_set_segment(struct kvm_vcpu *vcpu,
 				     vmcs_readl(GUEST_CS_BASE) >> 4);
 			break;
 		case VCPU_SREG_ES:
-			fix_rmode_seg(VCPU_SREG_ES, &vmx->rmode.es);
-			break;
 		case VCPU_SREG_DS:
-			fix_rmode_seg(VCPU_SREG_DS, &vmx->rmode.ds);
-			break;
 		case VCPU_SREG_GS:
-			fix_rmode_seg(VCPU_SREG_GS, &vmx->rmode.gs);
-			break;
 		case VCPU_SREG_FS:
-			fix_rmode_seg(VCPU_SREG_FS, &vmx->rmode.fs);
+			fix_rmode_seg(seg, &vmx->rmode.segs[seg]);
 			break;
 		case VCPU_SREG_SS:
 			vmcs_write16(GUEST_SS_SELECTOR,
@@ -3347,9 +3324,9 @@ static bool rmode_segment_valid(struct kvm_vcpu *vcpu, int seg)
 
 	if (var.base != (var.selector << 4))
 		return false;
-	if (var.limit != 0xffff)
+	if (var.limit < 0xffff)
 		return false;
-	if (ar != 0xf3)
+	if (((ar | (3 << AR_DPL_SHIFT)) & ~(AR_G_MASK | AR_DB_MASK)) != 0xf3)
 		return false;
 
 	return true;
@@ -3601,7 +3578,7 @@ out:
 
 static void seg_setup(int seg)
 {
-	struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg];
+	const struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg];
 	unsigned int ar;
 
 	vmcs_write16(sf->selector, 0);
@@ -3743,7 +3720,7 @@ static void vmx_set_constant_host_state(void)
 	unsigned long tmpl;
 	struct desc_ptr dt;
 
-	vmcs_writel(HOST_CR0, read_cr0() | X86_CR0_TS);  /* 22.2.3 */
+	vmcs_writel(HOST_CR0, read_cr0() & ~X86_CR0_TS);  /* 22.2.3 */
 	vmcs_writel(HOST_CR4, read_cr4());  /* 22.2.3, 22.2.5 */
 	vmcs_writel(HOST_CR3, read_cr3());  /* 22.2.3  FIXME: shadow tables */
 
@@ -3766,8 +3743,7 @@ static void vmx_set_constant_host_state(void)
 	native_store_idt(&dt);
 	vmcs_writel(HOST_IDTR_BASE, dt.address);   /* 22.2.4 */
 
-	asm("mov $.Lkvm_vmx_return, %0" : "=r"(tmpl));
-	vmcs_writel(HOST_RIP, tmpl); /* 22.2.5 */
+	vmcs_writel(HOST_RIP, vmx_return); /* 22.2.5 */
 
 	rdmsr(MSR_IA32_SYSENTER_CS, low32, high32);
 	vmcs_write32(HOST_IA32_SYSENTER_CS, low32);
@@ -4452,7 +4428,7 @@ vmx_patch_hypercall(struct kvm_vcpu *vcpu, unsigned char *hypercall)
 	hypercall[2] = 0xc1;
 }
 
-/* called to set cr0 as approriate for a mov-to-cr0 exit. */
+/* called to set cr0 as appropriate for a mov-to-cr0 exit. */
 static int handle_set_cr0(struct kvm_vcpu *vcpu, unsigned long val)
 {
 	if (to_vmx(vcpu)->nested.vmxon &&
@@ -4543,7 +4519,7 @@ static int handle_cr(struct kvm_vcpu *vcpu)
 				vcpu->run->exit_reason = KVM_EXIT_SET_TPR;
 				return 0;
 			}
-		};
+		}
 		break;
 	case 2: /* clts */
 		handle_clts(vcpu);
@@ -5697,7 +5673,7 @@ static int handle_vmptrst(struct kvm_vcpu *vcpu)
  * may resume.  Otherwise they set the kvm_run parameter to indicate what needs
  * to be done to userspace and return 0.
  */
-static int (*kvm_vmx_exit_handlers[])(struct kvm_vcpu *vcpu) = {
+static int (*const kvm_vmx_exit_handlers[])(struct kvm_vcpu *vcpu) = {
 	[EXIT_REASON_EXCEPTION_NMI]           = handle_exception,
 	[EXIT_REASON_EXTERNAL_INTERRUPT]      = handle_external_interrupt,
 	[EXIT_REASON_TRIPLE_FAULT]            = handle_triple_fault,
@@ -6225,17 +6201,10 @@ static void atomic_switch_perf_msrs(struct vcpu_vmx *vmx)
 					msrs[i].host);
 }
 
-#ifdef CONFIG_X86_64
-#define R "r"
-#define Q "q"
-#else
-#define R "e"
-#define Q "l"
-#endif
-
 static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu)
 {
 	struct vcpu_vmx *vmx = to_vmx(vcpu);
+	unsigned long debugctlmsr;
 
 	if (is_guest_mode(vcpu) && !vmx->nested.nested_run_pending) {
 		struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
@@ -6275,34 +6244,35 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu)
 		vmx_set_interrupt_shadow(vcpu, 0);
 
 	atomic_switch_perf_msrs(vmx);
+	debugctlmsr = get_debugctlmsr();
 
 	vmx->__launched = vmx->loaded_vmcs->launched;
 	asm(
 		/* Store host registers */
-		"push %%"R"dx; push %%"R"bp;"
-		"push %%"R"cx \n\t" /* placeholder for guest rcx */
-		"push %%"R"cx \n\t"
-		"cmp %%"R"sp, %c[host_rsp](%0) \n\t"
+		"push %%" _ASM_DX "; push %%" _ASM_BP ";"
+		"push %%" _ASM_CX " \n\t" /* placeholder for guest rcx */
+		"push %%" _ASM_CX " \n\t"
+		"cmp %%" _ASM_SP ", %c[host_rsp](%0) \n\t"
 		"je 1f \n\t"
-		"mov %%"R"sp, %c[host_rsp](%0) \n\t"
+		"mov %%" _ASM_SP ", %c[host_rsp](%0) \n\t"
 		__ex(ASM_VMX_VMWRITE_RSP_RDX) "\n\t"
 		"1: \n\t"
 		/* Reload cr2 if changed */
-		"mov %c[cr2](%0), %%"R"ax \n\t"
-		"mov %%cr2, %%"R"dx \n\t"
-		"cmp %%"R"ax, %%"R"dx \n\t"
+		"mov %c[cr2](%0), %%" _ASM_AX " \n\t"
+		"mov %%cr2, %%" _ASM_DX " \n\t"
+		"cmp %%" _ASM_AX ", %%" _ASM_DX " \n\t"
 		"je 2f \n\t"
-		"mov %%"R"ax, %%cr2 \n\t"
+		"mov %%" _ASM_AX", %%cr2 \n\t"
 		"2: \n\t"
 		/* Check if vmlaunch of vmresume is needed */
 		"cmpl $0, %c[launched](%0) \n\t"
 		/* Load guest registers.  Don't clobber flags. */
-		"mov %c[rax](%0), %%"R"ax \n\t"
-		"mov %c[rbx](%0), %%"R"bx \n\t"
-		"mov %c[rdx](%0), %%"R"dx \n\t"
-		"mov %c[rsi](%0), %%"R"si \n\t"
-		"mov %c[rdi](%0), %%"R"di \n\t"
-		"mov %c[rbp](%0), %%"R"bp \n\t"
+		"mov %c[rax](%0), %%" _ASM_AX " \n\t"
+		"mov %c[rbx](%0), %%" _ASM_BX " \n\t"
+		"mov %c[rdx](%0), %%" _ASM_DX " \n\t"
+		"mov %c[rsi](%0), %%" _ASM_SI " \n\t"
+		"mov %c[rdi](%0), %%" _ASM_DI " \n\t"
+		"mov %c[rbp](%0), %%" _ASM_BP " \n\t"
 #ifdef CONFIG_X86_64
 		"mov %c[r8](%0),  %%r8  \n\t"
 		"mov %c[r9](%0),  %%r9  \n\t"
@@ -6313,24 +6283,24 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu)
 		"mov %c[r14](%0), %%r14 \n\t"
 		"mov %c[r15](%0), %%r15 \n\t"
 #endif
-		"mov %c[rcx](%0), %%"R"cx \n\t" /* kills %0 (ecx) */
+		"mov %c[rcx](%0), %%" _ASM_CX " \n\t" /* kills %0 (ecx) */
 
 		/* Enter guest mode */
-		"jne .Llaunched \n\t"
+		"jne 1f \n\t"
 		__ex(ASM_VMX_VMLAUNCH) "\n\t"
-		"jmp .Lkvm_vmx_return \n\t"
-		".Llaunched: " __ex(ASM_VMX_VMRESUME) "\n\t"
-		".Lkvm_vmx_return: "
+		"jmp 2f \n\t"
+		"1: " __ex(ASM_VMX_VMRESUME) "\n\t"
+		"2: "
 		/* Save guest registers, load host registers, keep flags */
-		"mov %0, %c[wordsize](%%"R"sp) \n\t"
+		"mov %0, %c[wordsize](%%" _ASM_SP ") \n\t"
 		"pop %0 \n\t"
-		"mov %%"R"ax, %c[rax](%0) \n\t"
-		"mov %%"R"bx, %c[rbx](%0) \n\t"
-		"pop"Q" %c[rcx](%0) \n\t"
-		"mov %%"R"dx, %c[rdx](%0) \n\t"
-		"mov %%"R"si, %c[rsi](%0) \n\t"
-		"mov %%"R"di, %c[rdi](%0) \n\t"
-		"mov %%"R"bp, %c[rbp](%0) \n\t"
+		"mov %%" _ASM_AX ", %c[rax](%0) \n\t"
+		"mov %%" _ASM_BX ", %c[rbx](%0) \n\t"
+		__ASM_SIZE(pop) " %c[rcx](%0) \n\t"
+		"mov %%" _ASM_DX ", %c[rdx](%0) \n\t"
+		"mov %%" _ASM_SI ", %c[rsi](%0) \n\t"
+		"mov %%" _ASM_DI ", %c[rdi](%0) \n\t"
+		"mov %%" _ASM_BP ", %c[rbp](%0) \n\t"
 #ifdef CONFIG_X86_64
 		"mov %%r8,  %c[r8](%0) \n\t"
 		"mov %%r9,  %c[r9](%0) \n\t"
@@ -6341,11 +6311,15 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu)
 		"mov %%r14, %c[r14](%0) \n\t"
 		"mov %%r15, %c[r15](%0) \n\t"
 #endif
-		"mov %%cr2, %%"R"ax   \n\t"
-		"mov %%"R"ax, %c[cr2](%0) \n\t"
+		"mov %%cr2, %%" _ASM_AX "   \n\t"
+		"mov %%" _ASM_AX ", %c[cr2](%0) \n\t"
 
-		"pop  %%"R"bp; pop  %%"R"dx \n\t"
+		"pop  %%" _ASM_BP "; pop  %%" _ASM_DX " \n\t"
 		"setbe %c[fail](%0) \n\t"
+		".pushsection .rodata \n\t"
+		".global vmx_return \n\t"
+		"vmx_return: " _ASM_PTR " 2b \n\t"
+		".popsection"
 	      : : "c"(vmx), "d"((unsigned long)HOST_RSP),
 		[launched]"i"(offsetof(struct vcpu_vmx, __launched)),
 		[fail]"i"(offsetof(struct vcpu_vmx, fail)),
@@ -6370,12 +6344,18 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu)
 		[cr2]"i"(offsetof(struct vcpu_vmx, vcpu.arch.cr2)),
 		[wordsize]"i"(sizeof(ulong))
 	      : "cc", "memory"
-		, R"ax", R"bx", R"di", R"si"
 #ifdef CONFIG_X86_64
+		, "rax", "rbx", "rdi", "rsi"
 		, "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
+#else
+		, "eax", "ebx", "edi", "esi"
 #endif
 	      );
 
+	/* MSR_IA32_DEBUGCTLMSR is zeroed on vmexit. Restore it if needed */
+	if (debugctlmsr)
+		update_debugctlmsr(debugctlmsr);
+
 #ifndef CONFIG_X86_64
 	/*
 	 * The sysexit path does not restore ds/es, so we must set them to
@@ -6420,9 +6400,6 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu)
 	vmx_complete_interrupts(vmx);
 }
 
-#undef R
-#undef Q
-
 static void vmx_free_vcpu(struct kvm_vcpu *vcpu)
 {
 	struct vcpu_vmx *vmx = to_vmx(vcpu);
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 2966c84..9532240 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -246,20 +246,14 @@ static void drop_user_return_notifiers(void *ignore)
 
 u64 kvm_get_apic_base(struct kvm_vcpu *vcpu)
 {
-	if (irqchip_in_kernel(vcpu->kvm))
-		return vcpu->arch.apic_base;
-	else
-		return vcpu->arch.apic_base;
+	return vcpu->arch.apic_base;
 }
 EXPORT_SYMBOL_GPL(kvm_get_apic_base);
 
 void kvm_set_apic_base(struct kvm_vcpu *vcpu, u64 data)
 {
 	/* TODO: reserve bits check */
-	if (irqchip_in_kernel(vcpu->kvm))
-		kvm_lapic_set_base(vcpu, data);
-	else
-		vcpu->arch.apic_base = data;
+	kvm_lapic_set_base(vcpu, data);
 }
 EXPORT_SYMBOL_GPL(kvm_set_apic_base);
 
@@ -823,7 +817,7 @@ static u32 msrs_to_save[] = {
 
 static unsigned num_msrs_to_save;
 
-static u32 emulated_msrs[] = {
+static const u32 emulated_msrs[] = {
 	MSR_IA32_TSCDEADLINE,
 	MSR_IA32_MISC_ENABLE,
 	MSR_IA32_MCG_STATUS,
@@ -1097,7 +1091,7 @@ void kvm_write_tsc(struct kvm_vcpu *vcpu, u64 data)
 		 * For each generation, we track the original measured
 		 * nanosecond time, offset, and write, so if TSCs are in
 		 * sync, we can match exact offset, and if not, we can match
-		 * exact software computaion in compute_guest_tsc()
+		 * exact software computation in compute_guest_tsc()
 		 *
 		 * These values are tracked in kvm->arch.cur_xxx variables.
 		 */
@@ -1140,6 +1134,7 @@ static int kvm_guest_time_update(struct kvm_vcpu *v)
 	unsigned long this_tsc_khz;
 	s64 kernel_ns, max_kernel_ns;
 	u64 tsc_timestamp;
+	u8 pvclock_flags;
 
 	/* Keep irq disabled to prevent changes to the clock */
 	local_irq_save(flags);
@@ -1221,7 +1216,14 @@ static int kvm_guest_time_update(struct kvm_vcpu *v)
 	vcpu->hv_clock.system_time = kernel_ns + v->kvm->arch.kvmclock_offset;
 	vcpu->last_kernel_ns = kernel_ns;
 	vcpu->last_guest_tsc = tsc_timestamp;
-	vcpu->hv_clock.flags = 0;
+
+	pvclock_flags = 0;
+	if (vcpu->pvclock_set_guest_stopped_request) {
+		pvclock_flags |= PVCLOCK_GUEST_STOPPED;
+		vcpu->pvclock_set_guest_stopped_request = false;
+	}
+
+	vcpu->hv_clock.flags = pvclock_flags;
 
 	/*
 	 * The interface expects us to write an even number signaling that the
@@ -1504,7 +1506,7 @@ static int kvm_pv_enable_async_pf(struct kvm_vcpu *vcpu, u64 data)
 {
 	gpa_t gpa = data & ~0x3f;
 
-	/* Bits 2:5 are resrved, Should be zero */
+	/* Bits 2:5 are reserved, Should be zero */
 	if (data & 0x3c)
 		return 1;
 
@@ -1639,10 +1641,9 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data)
 		vcpu->arch.time_page =
 				gfn_to_page(vcpu->kvm, data >> PAGE_SHIFT);
 
-		if (is_error_page(vcpu->arch.time_page)) {
-			kvm_release_page_clean(vcpu->arch.time_page);
+		if (is_error_page(vcpu->arch.time_page))
 			vcpu->arch.time_page = NULL;
-		}
+
 		break;
 	}
 	case MSR_KVM_ASYNC_PF_EN:
@@ -1727,7 +1728,7 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data)
 		 * Ignore all writes to this no longer documented MSR.
 		 * Writes are only relevant for old K7 processors,
 		 * all pre-dating SVM, but a recommended workaround from
-		 * AMD for these chips. It is possible to speicify the
+		 * AMD for these chips. It is possible to specify the
 		 * affected processor models on the command line, hence
 		 * the need to ignore the workaround.
 		 */
@@ -2177,6 +2178,7 @@ int kvm_dev_ioctl_check_extension(long ext)
 	case KVM_CAP_GET_TSC_KHZ:
 	case KVM_CAP_PCI_2_3:
 	case KVM_CAP_KVMCLOCK_CTRL:
+	case KVM_CAP_READONLY_MEM:
 		r = 1;
 		break;
 	case KVM_CAP_COALESCED_MMIO:
@@ -2358,8 +2360,7 @@ static int kvm_vcpu_ioctl_get_lapic(struct kvm_vcpu *vcpu,
 static int kvm_vcpu_ioctl_set_lapic(struct kvm_vcpu *vcpu,
 				    struct kvm_lapic_state *s)
 {
-	memcpy(vcpu->arch.apic->regs, s->regs, sizeof *s);
-	kvm_apic_post_state_restore(vcpu);
+	kvm_apic_post_state_restore(vcpu, s);
 	update_cr8_intercept(vcpu);
 
 	return 0;
@@ -2368,7 +2369,7 @@ static int kvm_vcpu_ioctl_set_lapic(struct kvm_vcpu *vcpu,
 static int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu,
 				    struct kvm_interrupt *irq)
 {
-	if (irq->irq < 0 || irq->irq >= 256)
+	if (irq->irq < 0 || irq->irq >= KVM_NR_INTERRUPTS)
 		return -EINVAL;
 	if (irqchip_in_kernel(vcpu->kvm))
 		return -ENXIO;
@@ -2635,11 +2636,9 @@ static int kvm_vcpu_ioctl_x86_set_xcrs(struct kvm_vcpu *vcpu,
  */
 static int kvm_set_guest_paused(struct kvm_vcpu *vcpu)
 {
-	struct pvclock_vcpu_time_info *src = &vcpu->arch.hv_clock;
 	if (!vcpu->arch.time_page)
 		return -EINVAL;
-	src->flags |= PVCLOCK_GUEST_STOPPED;
-	mark_page_dirty(vcpu->kvm, vcpu->arch.time >> PAGE_SHIFT);
+	vcpu->arch.pvclock_set_guest_stopped_request = true;
 	kvm_make_request(KVM_REQ_CLOCK_UPDATE, vcpu);
 	return 0;
 }
@@ -3090,7 +3089,7 @@ static int kvm_vm_ioctl_reinject(struct kvm *kvm,
 	if (!kvm->arch.vpit)
 		return -ENXIO;
 	mutex_lock(&kvm->arch.vpit->pit_state.lock);
-	kvm->arch.vpit->pit_state.pit_timer.reinject = control->pit_reinject;
+	kvm->arch.vpit->pit_state.reinject = control->pit_reinject;
 	mutex_unlock(&kvm->arch.vpit->pit_state.lock);
 	return 0;
 }
@@ -3173,6 +3172,16 @@ out:
 	return r;
 }
 
+int kvm_vm_ioctl_irq_line(struct kvm *kvm, struct kvm_irq_level *irq_event)
+{
+	if (!irqchip_in_kernel(kvm))
+		return -ENXIO;
+
+	irq_event->status = kvm_set_irq(kvm, KVM_USERSPACE_IRQ_SOURCE_ID,
+					irq_event->irq, irq_event->level);
+	return 0;
+}
+
 long kvm_arch_vm_ioctl(struct file *filp,
 		       unsigned int ioctl, unsigned long arg)
 {
@@ -3279,29 +3288,6 @@ long kvm_arch_vm_ioctl(struct file *filp,
 	create_pit_unlock:
 		mutex_unlock(&kvm->slots_lock);
 		break;
-	case KVM_IRQ_LINE_STATUS:
-	case KVM_IRQ_LINE: {
-		struct kvm_irq_level irq_event;
-
-		r = -EFAULT;
-		if (copy_from_user(&irq_event, argp, sizeof irq_event))
-			goto out;
-		r = -ENXIO;
-		if (irqchip_in_kernel(kvm)) {
-			__s32 status;
-			status = kvm_set_irq(kvm, KVM_USERSPACE_IRQ_SOURCE_ID,
-					irq_event.irq, irq_event.level);
-			if (ioctl == KVM_IRQ_LINE_STATUS) {
-				r = -EFAULT;
-				irq_event.status = status;
-				if (copy_to_user(argp, &irq_event,
-							sizeof irq_event))
-					goto out;
-			}
-			r = 0;
-		}
-		break;
-	}
 	case KVM_GET_IRQCHIP: {
 		/* 0: PIC master, 1: PIC slave, 2: IOAPIC */
 		struct kvm_irqchip *chip;
@@ -3689,20 +3675,17 @@ static int vcpu_mmio_gva_to_gpa(struct kvm_vcpu *vcpu, unsigned long gva,
 				gpa_t *gpa, struct x86_exception *exception,
 				bool write)
 {
-	u32 access = (kvm_x86_ops->get_cpl(vcpu) == 3) ? PFERR_USER_MASK : 0;
+	u32 access = ((kvm_x86_ops->get_cpl(vcpu) == 3) ? PFERR_USER_MASK : 0)
+		| (write ? PFERR_WRITE_MASK : 0);
 
-	if (vcpu_match_mmio_gva(vcpu, gva) &&
-		  check_write_user_access(vcpu, write, access,
-		  vcpu->arch.access)) {
+	if (vcpu_match_mmio_gva(vcpu, gva)
+	    && !permission_fault(vcpu->arch.walk_mmu, vcpu->arch.access, access)) {
 		*gpa = vcpu->arch.mmio_gfn << PAGE_SHIFT |
 					(gva & (PAGE_SIZE - 1));
 		trace_vcpu_match_mmio(gva, *gpa, write, false);
 		return 1;
 	}
 
-	if (write)
-		access |= PFERR_WRITE_MASK;
-
 	*gpa = vcpu->arch.walk_mmu->gva_to_gpa(vcpu, gva, access, exception);
 
 	if (*gpa == UNMAPPED_GVA)
@@ -3790,14 +3773,14 @@ static int write_exit_mmio(struct kvm_vcpu *vcpu, gpa_t gpa,
 	return X86EMUL_CONTINUE;
 }
 
-static struct read_write_emulator_ops read_emultor = {
+static const struct read_write_emulator_ops read_emultor = {
 	.read_write_prepare = read_prepare,
 	.read_write_emulate = read_emulate,
 	.read_write_mmio = vcpu_mmio_read,
 	.read_write_exit_mmio = read_exit_mmio,
 };
 
-static struct read_write_emulator_ops write_emultor = {
+static const struct read_write_emulator_ops write_emultor = {
 	.read_write_emulate = write_emulate,
 	.read_write_mmio = write_mmio,
 	.read_write_exit_mmio = write_exit_mmio,
@@ -3808,7 +3791,7 @@ static int emulator_read_write_onepage(unsigned long addr, void *val,
 				       unsigned int bytes,
 				       struct x86_exception *exception,
 				       struct kvm_vcpu *vcpu,
-				       struct read_write_emulator_ops *ops)
+				       const struct read_write_emulator_ops *ops)
 {
 	gpa_t gpa;
 	int handled, ret;
@@ -3857,7 +3840,7 @@ mmio:
 int emulator_read_write(struct x86_emulate_ctxt *ctxt, unsigned long addr,
 			void *val, unsigned int bytes,
 			struct x86_exception *exception,
-			struct read_write_emulator_ops *ops)
+			const struct read_write_emulator_ops *ops)
 {
 	struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt);
 	gpa_t gpa;
@@ -3962,10 +3945,8 @@ static int emulator_cmpxchg_emulated(struct x86_emulate_ctxt *ctxt,
 		goto emul_write;
 
 	page = gfn_to_page(vcpu->kvm, gpa >> PAGE_SHIFT);
-	if (is_error_page(page)) {
-		kvm_release_page_clean(page);
+	if (is_error_page(page))
 		goto emul_write;
-	}
 
 	kaddr = kmap_atomic(page);
 	kaddr += offset_in_page(gpa);
@@ -4332,7 +4313,19 @@ static void emulator_get_cpuid(struct x86_emulate_ctxt *ctxt,
 	kvm_cpuid(emul_to_vcpu(ctxt), eax, ebx, ecx, edx);
 }
 
-static struct x86_emulate_ops emulate_ops = {
+static ulong emulator_read_gpr(struct x86_emulate_ctxt *ctxt, unsigned reg)
+{
+	return kvm_register_read(emul_to_vcpu(ctxt), reg);
+}
+
+static void emulator_write_gpr(struct x86_emulate_ctxt *ctxt, unsigned reg, ulong val)
+{
+	kvm_register_write(emul_to_vcpu(ctxt), reg, val);
+}
+
+static const struct x86_emulate_ops emulate_ops = {
+	.read_gpr            = emulator_read_gpr,
+	.write_gpr           = emulator_write_gpr,
 	.read_std            = kvm_read_guest_virt_system,
 	.write_std           = kvm_write_guest_virt_system,
 	.fetch               = kvm_fetch_guest_virt,
@@ -4367,14 +4360,6 @@ static struct x86_emulate_ops emulate_ops = {
 	.get_cpuid           = emulator_get_cpuid,
 };
 
-static void cache_all_regs(struct kvm_vcpu *vcpu)
-{
-	kvm_register_read(vcpu, VCPU_REGS_RAX);
-	kvm_register_read(vcpu, VCPU_REGS_RSP);
-	kvm_register_read(vcpu, VCPU_REGS_RIP);
-	vcpu->arch.regs_dirty = ~0;
-}
-
 static void toggle_interruptibility(struct kvm_vcpu *vcpu, u32 mask)
 {
 	u32 int_shadow = kvm_x86_ops->get_interrupt_shadow(vcpu, mask);
@@ -4401,12 +4386,10 @@ static void inject_emulated_exception(struct kvm_vcpu *vcpu)
 		kvm_queue_exception(vcpu, ctxt->exception.vector);
 }
 
-static void init_decode_cache(struct x86_emulate_ctxt *ctxt,
-			      const unsigned long *regs)
+static void init_decode_cache(struct x86_emulate_ctxt *ctxt)
 {
 	memset(&ctxt->twobyte, 0,
-	       (void *)&ctxt->regs - (void *)&ctxt->twobyte);
-	memcpy(ctxt->regs, regs, sizeof(ctxt->regs));
+	       (void *)&ctxt->_regs - (void *)&ctxt->twobyte);
 
 	ctxt->fetch.start = 0;
 	ctxt->fetch.end = 0;
@@ -4421,14 +4404,6 @@ static void init_emulate_ctxt(struct kvm_vcpu *vcpu)
 	struct x86_emulate_ctxt *ctxt = &vcpu->arch.emulate_ctxt;
 	int cs_db, cs_l;
 
-	/*
-	 * TODO: fix emulate.c to use guest_read/write_register
-	 * instead of direct ->regs accesses, can save hundred cycles
-	 * on Intel for instructions that don't read/change RSP, for
-	 * for example.
-	 */
-	cache_all_regs(vcpu);
-
 	kvm_x86_ops->get_cs_db_l_bits(vcpu, &cs_db, &cs_l);
 
 	ctxt->eflags = kvm_get_rflags(vcpu);
@@ -4440,7 +4415,7 @@ static void init_emulate_ctxt(struct kvm_vcpu *vcpu)
 							  X86EMUL_MODE_PROT16;
 	ctxt->guest_mode = is_guest_mode(vcpu);
 
-	init_decode_cache(ctxt, vcpu->arch.regs);
+	init_decode_cache(ctxt);
 	vcpu->arch.emulate_regs_need_sync_from_vcpu = false;
 }
 
@@ -4460,7 +4435,6 @@ int kvm_inject_realmode_interrupt(struct kvm_vcpu *vcpu, int irq, int inc_eip)
 		return EMULATE_FAIL;
 
 	ctxt->eip = ctxt->_eip;
-	memcpy(vcpu->arch.regs, ctxt->regs, sizeof ctxt->regs);
 	kvm_rip_write(vcpu, ctxt->eip);
 	kvm_set_rflags(vcpu, ctxt->eflags);
 
@@ -4493,13 +4467,14 @@ static int handle_emulation_failure(struct kvm_vcpu *vcpu)
 static bool reexecute_instruction(struct kvm_vcpu *vcpu, gva_t gva)
 {
 	gpa_t gpa;
+	pfn_t pfn;
 
 	if (tdp_enabled)
 		return false;
 
 	/*
 	 * if emulation was due to access to shadowed page table
-	 * and it failed try to unshadow page and re-entetr the
+	 * and it failed try to unshadow page and re-enter the
 	 * guest to let CPU execute the instruction.
 	 */
 	if (kvm_mmu_unprotect_page_virt(vcpu, gva))
@@ -4510,8 +4485,17 @@ static bool reexecute_instruction(struct kvm_vcpu *vcpu, gva_t gva)
 	if (gpa == UNMAPPED_GVA)
 		return true; /* let cpu generate fault */
 
-	if (!kvm_is_error_hva(gfn_to_hva(vcpu->kvm, gpa >> PAGE_SHIFT)))
+	/*
+	 * Do not retry the unhandleable instruction if it faults on the
+	 * readonly host memory, otherwise it will goto a infinite loop:
+	 * retry instruction -> write #PF -> emulation fail -> retry
+	 * instruction -> ...
+	 */
+	pfn = gfn_to_pfn(vcpu->kvm, gpa_to_gfn(gpa));
+	if (!is_error_pfn(pfn)) {
+		kvm_release_pfn_clean(pfn);
 		return true;
+	}
 
 	return false;
 }
@@ -4560,6 +4544,9 @@ static bool retry_instruction(struct x86_emulate_ctxt *ctxt,
 	return true;
 }
 
+static int complete_emulated_mmio(struct kvm_vcpu *vcpu);
+static int complete_emulated_pio(struct kvm_vcpu *vcpu);
+
 int x86_emulate_instruction(struct kvm_vcpu *vcpu,
 			    unsigned long cr2,
 			    int emulation_type,
@@ -4608,7 +4595,7 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu,
 	   changes registers values  during IO operation */
 	if (vcpu->arch.emulate_regs_need_sync_from_vcpu) {
 		vcpu->arch.emulate_regs_need_sync_from_vcpu = false;
-		memcpy(ctxt->regs, vcpu->arch.regs, sizeof ctxt->regs);
+		emulator_invalidate_register_cache(ctxt);
 	}
 
 restart:
@@ -4630,13 +4617,16 @@ restart:
 	} else if (vcpu->arch.pio.count) {
 		if (!vcpu->arch.pio.in)
 			vcpu->arch.pio.count = 0;
-		else
+		else {
 			writeback = false;
+			vcpu->arch.complete_userspace_io = complete_emulated_pio;
+		}
 		r = EMULATE_DO_MMIO;
 	} else if (vcpu->mmio_needed) {
 		if (!vcpu->mmio_is_write)
 			writeback = false;
 		r = EMULATE_DO_MMIO;
+		vcpu->arch.complete_userspace_io = complete_emulated_mmio;
 	} else if (r == EMULATION_RESTART)
 		goto restart;
 	else
@@ -4646,7 +4636,6 @@ restart:
 		toggle_interruptibility(vcpu, ctxt->interruptibility);
 		kvm_set_rflags(vcpu, ctxt->eflags);
 		kvm_make_request(KVM_REQ_EVENT, vcpu);
-		memcpy(vcpu->arch.regs, ctxt->regs, sizeof ctxt->regs);
 		vcpu->arch.emulate_regs_need_sync_to_vcpu = false;
 		kvm_rip_write(vcpu, ctxt->eip);
 	} else
@@ -4929,6 +4918,7 @@ int kvm_arch_init(void *opaque)
 	if (cpu_has_xsave)
 		host_xcr0 = xgetbv(XCR_XFEATURE_ENABLED_MASK);
 
+	kvm_lapic_init();
 	return 0;
 
 out:
@@ -5499,6 +5489,24 @@ static int __vcpu_run(struct kvm_vcpu *vcpu)
 	return r;
 }
 
+static inline int complete_emulated_io(struct kvm_vcpu *vcpu)
+{
+	int r;
+	vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
+	r = emulate_instruction(vcpu, EMULTYPE_NO_DECODE);
+	srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx);
+	if (r != EMULATE_DONE)
+		return 0;
+	return 1;
+}
+
+static int complete_emulated_pio(struct kvm_vcpu *vcpu)
+{
+	BUG_ON(!vcpu->arch.pio.count);
+
+	return complete_emulated_io(vcpu);
+}
+
 /*
  * Implements the following, as a state machine:
  *
@@ -5515,47 +5523,37 @@ static int __vcpu_run(struct kvm_vcpu *vcpu)
  *      copy data
  *      exit
  */
-static int complete_mmio(struct kvm_vcpu *vcpu)
+static int complete_emulated_mmio(struct kvm_vcpu *vcpu)
 {
 	struct kvm_run *run = vcpu->run;
 	struct kvm_mmio_fragment *frag;
-	int r;
 
-	if (!(vcpu->arch.pio.count || vcpu->mmio_needed))
-		return 1;
+	BUG_ON(!vcpu->mmio_needed);
 
-	if (vcpu->mmio_needed) {
-		/* Complete previous fragment */
-		frag = &vcpu->mmio_fragments[vcpu->mmio_cur_fragment++];
-		if (!vcpu->mmio_is_write)
-			memcpy(frag->data, run->mmio.data, frag->len);
-		if (vcpu->mmio_cur_fragment == vcpu->mmio_nr_fragments) {
-			vcpu->mmio_needed = 0;
-			if (vcpu->mmio_is_write)
-				return 1;
-			vcpu->mmio_read_completed = 1;
-			goto done;
-		}
-		/* Initiate next fragment */
-		++frag;
-		run->exit_reason = KVM_EXIT_MMIO;
-		run->mmio.phys_addr = frag->gpa;
+	/* Complete previous fragment */
+	frag = &vcpu->mmio_fragments[vcpu->mmio_cur_fragment++];
+	if (!vcpu->mmio_is_write)
+		memcpy(frag->data, run->mmio.data, frag->len);
+	if (vcpu->mmio_cur_fragment == vcpu->mmio_nr_fragments) {
+		vcpu->mmio_needed = 0;
 		if (vcpu->mmio_is_write)
-			memcpy(run->mmio.data, frag->data, frag->len);
-		run->mmio.len = frag->len;
-		run->mmio.is_write = vcpu->mmio_is_write;
-		return 0;
-
-	}
-done:
-	vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
-	r = emulate_instruction(vcpu, EMULTYPE_NO_DECODE);
-	srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx);
-	if (r != EMULATE_DONE)
-		return 0;
-	return 1;
+			return 1;
+		vcpu->mmio_read_completed = 1;
+		return complete_emulated_io(vcpu);
+	}
+	/* Initiate next fragment */
+	++frag;
+	run->exit_reason = KVM_EXIT_MMIO;
+	run->mmio.phys_addr = frag->gpa;
+	if (vcpu->mmio_is_write)
+		memcpy(run->mmio.data, frag->data, frag->len);
+	run->mmio.len = frag->len;
+	run->mmio.is_write = vcpu->mmio_is_write;
+	vcpu->arch.complete_userspace_io = complete_emulated_mmio;
+	return 0;
 }
 
+
 int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 {
 	int r;
@@ -5582,9 +5580,14 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 		}
 	}
 
-	r = complete_mmio(vcpu);
-	if (r <= 0)
-		goto out;
+	if (unlikely(vcpu->arch.complete_userspace_io)) {
+		int (*cui)(struct kvm_vcpu *) = vcpu->arch.complete_userspace_io;
+		vcpu->arch.complete_userspace_io = NULL;
+		r = cui(vcpu);
+		if (r <= 0)
+			goto out;
+	} else
+		WARN_ON(vcpu->arch.pio.count || vcpu->mmio_needed);
 
 	r = __vcpu_run(vcpu);
 
@@ -5602,12 +5605,11 @@ int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
 		/*
 		 * We are here if userspace calls get_regs() in the middle of
 		 * instruction emulation. Registers state needs to be copied
-		 * back from emulation context to vcpu. Usrapace shouldn't do
+		 * back from emulation context to vcpu. Userspace shouldn't do
 		 * that usually, but some bad designed PV devices (vmware
 		 * backdoor interface) need this to work
 		 */
-		struct x86_emulate_ctxt *ctxt = &vcpu->arch.emulate_ctxt;
-		memcpy(vcpu->arch.regs, ctxt->regs, sizeof ctxt->regs);
+		emulator_writeback_register_cache(&vcpu->arch.emulate_ctxt);
 		vcpu->arch.emulate_regs_need_sync_to_vcpu = false;
 	}
 	regs->rax = kvm_register_read(vcpu, VCPU_REGS_RAX);
@@ -5747,7 +5749,6 @@ int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int idt_index,
 	if (ret)
 		return EMULATE_FAIL;
 
-	memcpy(vcpu->arch.regs, ctxt->regs, sizeof ctxt->regs);
 	kvm_rip_write(vcpu, ctxt->eip);
 	kvm_set_rflags(vcpu, ctxt->eflags);
 	kvm_make_request(KVM_REQ_EVENT, vcpu);
@@ -5799,7 +5800,7 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
 	if (mmu_reset_needed)
 		kvm_mmu_reset_context(vcpu);
 
-	max_bits = (sizeof sregs->interrupt_bitmap) << 3;
+	max_bits = KVM_NR_INTERRUPTS;
 	pending_vec = find_first_bit(
 		(const unsigned long *)sregs->interrupt_bitmap, max_bits);
 	if (pending_vec < max_bits) {
@@ -5979,7 +5980,7 @@ void kvm_load_guest_fpu(struct kvm_vcpu *vcpu)
 	 */
 	kvm_put_guest_xcr0(vcpu);
 	vcpu->guest_fpu_loaded = 1;
-	unlazy_fpu(current);
+	__kernel_fpu_begin();
 	fpu_restore_checking(&vcpu->arch.guest_fpu);
 	trace_kvm_fpu(1);
 }
@@ -5993,6 +5994,7 @@ void kvm_put_guest_fpu(struct kvm_vcpu *vcpu)
 
 	vcpu->guest_fpu_loaded = 0;
 	fpu_save_init(&vcpu->arch.guest_fpu);
+	__kernel_fpu_end();
 	++vcpu->stat.fpu_reload;
 	kvm_make_request(KVM_REQ_DEACTIVATE_FPU, vcpu);
 	trace_kvm_fpu(0);
@@ -6022,7 +6024,9 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
 	int r;
 
 	vcpu->arch.mtrr_state.have_fixed = 1;
-	vcpu_load(vcpu);
+	r = vcpu_load(vcpu);
+	if (r)
+		return r;
 	r = kvm_arch_vcpu_reset(vcpu);
 	if (r == 0)
 		r = kvm_mmu_setup(vcpu);
@@ -6033,9 +6037,11 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
 
 void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
 {
+	int r;
 	vcpu->arch.apf.msr_val = 0;
 
-	vcpu_load(vcpu);
+	r = vcpu_load(vcpu);
+	BUG_ON(r);
 	kvm_mmu_unload(vcpu);
 	vcpu_put(vcpu);
 
@@ -6131,7 +6137,7 @@ int kvm_arch_hardware_enable(void *garbage)
 	 * as we reset last_host_tsc on all VCPUs to stop this from being
 	 * called multiple times (one for each physical CPU bringup).
 	 *
-	 * Platforms with unnreliable TSCs don't have to deal with this, they
+	 * Platforms with unreliable TSCs don't have to deal with this, they
 	 * will be compensated by the logic in vcpu_load, which sets the TSC to
 	 * catchup mode.  This will catchup all VCPUs to real time, but cannot
 	 * guarantee that they stay in perfect synchronization.
@@ -6184,6 +6190,8 @@ bool kvm_vcpu_compatible(struct kvm_vcpu *vcpu)
 	return irqchip_in_kernel(vcpu->kvm) == (vcpu->arch.apic != NULL);
 }
 
+struct static_key kvm_no_apic_vcpu __read_mostly;
+
 int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
 {
 	struct page *page;
@@ -6216,7 +6224,8 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
 		r = kvm_create_lapic(vcpu);
 		if (r < 0)
 			goto fail_mmu_destroy;
-	}
+	} else
+		static_key_slow_inc(&kvm_no_apic_vcpu);
 
 	vcpu->arch.mce_banks = kzalloc(KVM_MAX_MCE_BANKS * sizeof(u64) * 4,
 				       GFP_KERNEL);
@@ -6256,6 +6265,8 @@ void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu)
 	kvm_mmu_destroy(vcpu);
 	srcu_read_unlock(&vcpu->kvm->srcu, idx);
 	free_page((unsigned long)vcpu->arch.pio_data);
+	if (!irqchip_in_kernel(vcpu->kvm))
+		static_key_slow_dec(&kvm_no_apic_vcpu);
 }
 
 int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
@@ -6270,13 +6281,16 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
 	set_bit(KVM_USERSPACE_IRQ_SOURCE_ID, &kvm->arch.irq_sources_bitmap);
 
 	raw_spin_lock_init(&kvm->arch.tsc_write_lock);
+	mutex_init(&kvm->arch.apic_map_lock);
 
 	return 0;
 }
 
 static void kvm_unload_vcpu_mmu(struct kvm_vcpu *vcpu)
 {
-	vcpu_load(vcpu);
+	int r;
+	r = vcpu_load(vcpu);
+	BUG_ON(r);
 	kvm_mmu_unload(vcpu);
 	vcpu_put(vcpu);
 }
@@ -6320,6 +6334,7 @@ void kvm_arch_destroy_vm(struct kvm *kvm)
 		put_page(kvm->arch.apic_access_page);
 	if (kvm->arch.ept_identity_pagetable)
 		put_page(kvm->arch.ept_identity_pagetable);
+	kfree(rcu_dereference_check(kvm->arch.apic_map, 1));
 }
 
 void kvm_arch_free_memslot(struct kvm_memory_slot *free,
@@ -6327,10 +6342,18 @@ void kvm_arch_free_memslot(struct kvm_memory_slot *free,
 {
 	int i;
 
-	for (i = 0; i < KVM_NR_PAGE_SIZES - 1; ++i) {
-		if (!dont || free->arch.lpage_info[i] != dont->arch.lpage_info[i]) {
-			kvm_kvfree(free->arch.lpage_info[i]);
-			free->arch.lpage_info[i] = NULL;
+	for (i = 0; i < KVM_NR_PAGE_SIZES; ++i) {
+		if (!dont || free->arch.rmap[i] != dont->arch.rmap[i]) {
+			kvm_kvfree(free->arch.rmap[i]);
+			free->arch.rmap[i] = NULL;
+		}
+		if (i == 0)
+			continue;
+
+		if (!dont || free->arch.lpage_info[i - 1] !=
+			     dont->arch.lpage_info[i - 1]) {
+			kvm_kvfree(free->arch.lpage_info[i - 1]);
+			free->arch.lpage_info[i - 1] = NULL;
 		}
 	}
 }
@@ -6339,23 +6362,30 @@ int kvm_arch_create_memslot(struct kvm_memory_slot *slot, unsigned long npages)
 {
 	int i;
 
-	for (i = 0; i < KVM_NR_PAGE_SIZES - 1; ++i) {
+	for (i = 0; i < KVM_NR_PAGE_SIZES; ++i) {
 		unsigned long ugfn;
 		int lpages;
-		int level = i + 2;
+		int level = i + 1;
 
 		lpages = gfn_to_index(slot->base_gfn + npages - 1,
 				      slot->base_gfn, level) + 1;
 
-		slot->arch.lpage_info[i] =
-			kvm_kvzalloc(lpages * sizeof(*slot->arch.lpage_info[i]));
-		if (!slot->arch.lpage_info[i])
+		slot->arch.rmap[i] =
+			kvm_kvzalloc(lpages * sizeof(*slot->arch.rmap[i]));
+		if (!slot->arch.rmap[i])
+			goto out_free;
+		if (i == 0)
+			continue;
+
+		slot->arch.lpage_info[i - 1] = kvm_kvzalloc(lpages *
+					sizeof(*slot->arch.lpage_info[i - 1]));
+		if (!slot->arch.lpage_info[i - 1])
 			goto out_free;
 
 		if (slot->base_gfn & (KVM_PAGES_PER_HPAGE(level) - 1))
-			slot->arch.lpage_info[i][0].write_count = 1;
+			slot->arch.lpage_info[i - 1][0].write_count = 1;
 		if ((slot->base_gfn + npages) & (KVM_PAGES_PER_HPAGE(level) - 1))
-			slot->arch.lpage_info[i][lpages - 1].write_count = 1;
+			slot->arch.lpage_info[i - 1][lpages - 1].write_count = 1;
 		ugfn = slot->userspace_addr >> PAGE_SHIFT;
 		/*
 		 * If the gfn and userspace address are not aligned wrt each
@@ -6367,16 +6397,21 @@ int kvm_arch_create_memslot(struct kvm_memory_slot *slot, unsigned long npages)
 			unsigned long j;
 
 			for (j = 0; j < lpages; ++j)
-				slot->arch.lpage_info[i][j].write_count = 1;
+				slot->arch.lpage_info[i - 1][j].write_count = 1;
 		}
 	}
 
 	return 0;
 
 out_free:
-	for (i = 0; i < KVM_NR_PAGE_SIZES - 1; ++i) {
-		kvm_kvfree(slot->arch.lpage_info[i]);
-		slot->arch.lpage_info[i] = NULL;
+	for (i = 0; i < KVM_NR_PAGE_SIZES; ++i) {
+		kvm_kvfree(slot->arch.rmap[i]);
+		slot->arch.rmap[i] = NULL;
+		if (i == 0)
+			continue;
+
+		kvm_kvfree(slot->arch.lpage_info[i - 1]);
+		slot->arch.lpage_info[i - 1] = NULL;
 	}
 	return -ENOMEM;
 }
@@ -6395,10 +6430,10 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
 		map_flags = MAP_SHARED | MAP_ANONYMOUS;
 
 	/*To keep backward compatibility with older userspace,
-	 *x86 needs to hanlde !user_alloc case.
+	 *x86 needs to handle !user_alloc case.
 	 */
 	if (!user_alloc) {
-		if (npages && !old.rmap) {
+		if (npages && !old.npages) {
 			unsigned long userspace_addr;
 
 			userspace_addr = vm_mmap(NULL, 0,
@@ -6426,7 +6461,7 @@ void kvm_arch_commit_memory_region(struct kvm *kvm,
 
 	int nr_mmu_pages = 0, npages = mem->memory_size >> PAGE_SHIFT;
 
-	if (!user_alloc && !old.user_alloc && old.rmap && !npages) {
+	if (!user_alloc && !old.user_alloc && old.npages && !npages) {
 		int ret;
 
 		ret = vm_munmap(old.userspace_addr,
@@ -6445,14 +6480,28 @@ void kvm_arch_commit_memory_region(struct kvm *kvm,
 		kvm_mmu_change_mmu_pages(kvm, nr_mmu_pages);
 	kvm_mmu_slot_remove_write_access(kvm, mem->slot);
 	spin_unlock(&kvm->mmu_lock);
+	/*
+	 * If memory slot is created, or moved, we need to clear all
+	 * mmio sptes.
+	 */
+	if (npages && old.base_gfn != mem->guest_phys_addr >> PAGE_SHIFT) {
+		kvm_mmu_zap_all(kvm);
+		kvm_reload_remote_mmus(kvm);
+	}
 }
 
-void kvm_arch_flush_shadow(struct kvm *kvm)
+void kvm_arch_flush_shadow_all(struct kvm *kvm)
 {
 	kvm_mmu_zap_all(kvm);
 	kvm_reload_remote_mmus(kvm);
 }
 
+void kvm_arch_flush_shadow_memslot(struct kvm *kvm,
+				   struct kvm_memory_slot *slot)
+{
+	kvm_arch_flush_shadow_all(kvm);
+}
+
 int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu)
 {
 	return (vcpu->arch.mp_state == KVM_MP_STATE_RUNNABLE &&
diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h
index 3d1134d..2b5219c 100644
--- a/arch/x86/kvm/x86.h
+++ b/arch/x86/kvm/x86.h
@@ -124,4 +124,5 @@ int kvm_write_guest_virt_system(struct x86_emulate_ctxt *ctxt,
 
 extern u64 host_xcr0;
 
+extern struct static_key kvm_no_apic_vcpu;
 #endif
diff --git a/arch/x86/lguest/Kconfig b/arch/x86/lguest/Kconfig
index 6e121a2..7872a33 100644
--- a/arch/x86/lguest/Kconfig
+++ b/arch/x86/lguest/Kconfig
@@ -4,7 +4,6 @@ config LGUEST_GUEST
 	depends on X86_32
 	select VIRTUALIZATION
 	select VIRTIO
-	select VIRTIO_RING
 	select VIRTIO_CONSOLE
 	help
 	  Lguest is a tiny in-kernel hypervisor.  Selecting this will
diff --git a/arch/x86/lib/copy_user_64.S b/arch/x86/lib/copy_user_64.S
index 5b2995f..a30ca15 100644
--- a/arch/x86/lib/copy_user_64.S
+++ b/arch/x86/lib/copy_user_64.S
@@ -17,6 +17,7 @@
 #include <asm/cpufeature.h>
 #include <asm/alternative-asm.h>
 #include <asm/asm.h>
+#include <asm/smap.h>
 
 /*
  * By placing feature2 after feature1 in altinstructions section, we logically
@@ -130,6 +131,7 @@ ENDPROC(bad_from_user)
  */
 ENTRY(copy_user_generic_unrolled)
 	CFI_STARTPROC
+	ASM_STAC
 	cmpl $8,%edx
 	jb 20f		/* less then 8 bytes, go to byte copy loop */
 	ALIGN_DESTINATION
@@ -177,6 +179,7 @@ ENTRY(copy_user_generic_unrolled)
 	decl %ecx
 	jnz 21b
 23:	xor %eax,%eax
+	ASM_CLAC
 	ret
 
 	.section .fixup,"ax"
@@ -232,6 +235,7 @@ ENDPROC(copy_user_generic_unrolled)
  */
 ENTRY(copy_user_generic_string)
 	CFI_STARTPROC
+	ASM_STAC
 	andl %edx,%edx
 	jz 4f
 	cmpl $8,%edx
@@ -246,6 +250,7 @@ ENTRY(copy_user_generic_string)
 3:	rep
 	movsb
 4:	xorl %eax,%eax
+	ASM_CLAC
 	ret
 
 	.section .fixup,"ax"
@@ -273,12 +278,14 @@ ENDPROC(copy_user_generic_string)
  */
 ENTRY(copy_user_enhanced_fast_string)
 	CFI_STARTPROC
+	ASM_STAC
 	andl %edx,%edx
 	jz 2f
 	movl %edx,%ecx
 1:	rep
 	movsb
 2:	xorl %eax,%eax
+	ASM_CLAC
 	ret
 
 	.section .fixup,"ax"
diff --git a/arch/x86/lib/copy_user_nocache_64.S b/arch/x86/lib/copy_user_nocache_64.S
index cacddc7..6a4f43c 100644
--- a/arch/x86/lib/copy_user_nocache_64.S
+++ b/arch/x86/lib/copy_user_nocache_64.S
@@ -15,6 +15,7 @@
 #include <asm/asm-offsets.h>
 #include <asm/thread_info.h>
 #include <asm/asm.h>
+#include <asm/smap.h>
 
 	.macro ALIGN_DESTINATION
 #ifdef FIX_ALIGNMENT
@@ -48,6 +49,7 @@
  */
 ENTRY(__copy_user_nocache)
 	CFI_STARTPROC
+	ASM_STAC
 	cmpl $8,%edx
 	jb 20f		/* less then 8 bytes, go to byte copy loop */
 	ALIGN_DESTINATION
@@ -95,6 +97,7 @@ ENTRY(__copy_user_nocache)
 	decl %ecx
 	jnz 21b
 23:	xorl %eax,%eax
+	ASM_CLAC
 	sfence
 	ret
 
diff --git a/arch/x86/lib/getuser.S b/arch/x86/lib/getuser.S
index b33b1fb..156b9c8 100644
--- a/arch/x86/lib/getuser.S
+++ b/arch/x86/lib/getuser.S
@@ -33,6 +33,7 @@
 #include <asm/asm-offsets.h>
 #include <asm/thread_info.h>
 #include <asm/asm.h>
+#include <asm/smap.h>
 
 	.text
 ENTRY(__get_user_1)
@@ -40,8 +41,10 @@ ENTRY(__get_user_1)
 	GET_THREAD_INFO(%_ASM_DX)
 	cmp TI_addr_limit(%_ASM_DX),%_ASM_AX
 	jae bad_get_user
+	ASM_STAC
 1:	movzb (%_ASM_AX),%edx
 	xor %eax,%eax
+	ASM_CLAC
 	ret
 	CFI_ENDPROC
 ENDPROC(__get_user_1)
@@ -53,8 +56,10 @@ ENTRY(__get_user_2)
 	GET_THREAD_INFO(%_ASM_DX)
 	cmp TI_addr_limit(%_ASM_DX),%_ASM_AX
 	jae bad_get_user
+	ASM_STAC
 2:	movzwl -1(%_ASM_AX),%edx
 	xor %eax,%eax
+	ASM_CLAC
 	ret
 	CFI_ENDPROC
 ENDPROC(__get_user_2)
@@ -66,8 +71,10 @@ ENTRY(__get_user_4)
 	GET_THREAD_INFO(%_ASM_DX)
 	cmp TI_addr_limit(%_ASM_DX),%_ASM_AX
 	jae bad_get_user
+	ASM_STAC
 3:	mov -3(%_ASM_AX),%edx
 	xor %eax,%eax
+	ASM_CLAC
 	ret
 	CFI_ENDPROC
 ENDPROC(__get_user_4)
@@ -80,8 +87,10 @@ ENTRY(__get_user_8)
 	GET_THREAD_INFO(%_ASM_DX)
 	cmp TI_addr_limit(%_ASM_DX),%_ASM_AX
 	jae	bad_get_user
+	ASM_STAC
 4:	movq -7(%_ASM_AX),%_ASM_DX
 	xor %eax,%eax
+	ASM_CLAC
 	ret
 	CFI_ENDPROC
 ENDPROC(__get_user_8)
@@ -91,6 +100,7 @@ bad_get_user:
 	CFI_STARTPROC
 	xor %edx,%edx
 	mov $(-EFAULT),%_ASM_AX
+	ASM_CLAC
 	ret
 	CFI_ENDPROC
 END(bad_get_user)
diff --git a/arch/x86/lib/putuser.S b/arch/x86/lib/putuser.S
index 7f951c8..fc6ba17 100644
--- a/arch/x86/lib/putuser.S
+++ b/arch/x86/lib/putuser.S
@@ -15,6 +15,7 @@
 #include <asm/thread_info.h>
 #include <asm/errno.h>
 #include <asm/asm.h>
+#include <asm/smap.h>
 
 
 /*
@@ -31,7 +32,8 @@
 
 #define ENTER	CFI_STARTPROC ; \
 		GET_THREAD_INFO(%_ASM_BX)
-#define EXIT	ret ; \
+#define EXIT	ASM_CLAC ;	\
+		ret ;		\
 		CFI_ENDPROC
 
 .text
@@ -39,6 +41,7 @@ ENTRY(__put_user_1)
 	ENTER
 	cmp TI_addr_limit(%_ASM_BX),%_ASM_CX
 	jae bad_put_user
+	ASM_STAC
 1:	movb %al,(%_ASM_CX)
 	xor %eax,%eax
 	EXIT
@@ -50,6 +53,7 @@ ENTRY(__put_user_2)
 	sub $1,%_ASM_BX
 	cmp %_ASM_BX,%_ASM_CX
 	jae bad_put_user
+	ASM_STAC
 2:	movw %ax,(%_ASM_CX)
 	xor %eax,%eax
 	EXIT
@@ -61,6 +65,7 @@ ENTRY(__put_user_4)
 	sub $3,%_ASM_BX
 	cmp %_ASM_BX,%_ASM_CX
 	jae bad_put_user
+	ASM_STAC
 3:	movl %eax,(%_ASM_CX)
 	xor %eax,%eax
 	EXIT
@@ -72,6 +77,7 @@ ENTRY(__put_user_8)
 	sub $7,%_ASM_BX
 	cmp %_ASM_BX,%_ASM_CX
 	jae bad_put_user
+	ASM_STAC
 4:	mov %_ASM_AX,(%_ASM_CX)
 #ifdef CONFIG_X86_32
 5:	movl %edx,4(%_ASM_CX)
diff --git a/arch/x86/lib/usercopy_32.c b/arch/x86/lib/usercopy_32.c
index 1781b2f..98f6d6b6 100644
--- a/arch/x86/lib/usercopy_32.c
+++ b/arch/x86/lib/usercopy_32.c
@@ -42,10 +42,11 @@ do {									\
 	int __d0;							\
 	might_fault();							\
 	__asm__ __volatile__(						\
+		ASM_STAC "\n"						\
 		"0:	rep; stosl\n"					\
 		"	movl %2,%0\n"					\
 		"1:	rep; stosb\n"					\
-		"2:\n"							\
+		"2: " ASM_CLAC "\n"					\
 		".section .fixup,\"ax\"\n"				\
 		"3:	lea 0(%2,%0,4),%0\n"				\
 		"	jmp 2b\n"					\
@@ -626,10 +627,12 @@ survive:
 		return n;
 	}
 #endif
+	stac();
 	if (movsl_is_ok(to, from, n))
 		__copy_user(to, from, n);
 	else
 		n = __copy_user_intel(to, from, n);
+	clac();
 	return n;
 }
 EXPORT_SYMBOL(__copy_to_user_ll);
@@ -637,10 +640,12 @@ EXPORT_SYMBOL(__copy_to_user_ll);
 unsigned long __copy_from_user_ll(void *to, const void __user *from,
 					unsigned long n)
 {
+	stac();
 	if (movsl_is_ok(to, from, n))
 		__copy_user_zeroing(to, from, n);
 	else
 		n = __copy_user_zeroing_intel(to, from, n);
+	clac();
 	return n;
 }
 EXPORT_SYMBOL(__copy_from_user_ll);
@@ -648,11 +653,13 @@ EXPORT_SYMBOL(__copy_from_user_ll);
 unsigned long __copy_from_user_ll_nozero(void *to, const void __user *from,
 					 unsigned long n)
 {
+	stac();
 	if (movsl_is_ok(to, from, n))
 		__copy_user(to, from, n);
 	else
 		n = __copy_user_intel((void __user *)to,
 				      (const void *)from, n);
+	clac();
 	return n;
 }
 EXPORT_SYMBOL(__copy_from_user_ll_nozero);
@@ -660,6 +667,7 @@ EXPORT_SYMBOL(__copy_from_user_ll_nozero);
 unsigned long __copy_from_user_ll_nocache(void *to, const void __user *from,
 					unsigned long n)
 {
+	stac();
 #ifdef CONFIG_X86_INTEL_USERCOPY
 	if (n > 64 && cpu_has_xmm2)
 		n = __copy_user_zeroing_intel_nocache(to, from, n);
@@ -668,6 +676,7 @@ unsigned long __copy_from_user_ll_nocache(void *to, const void __user *from,
 #else
 	__copy_user_zeroing(to, from, n);
 #endif
+	clac();
 	return n;
 }
 EXPORT_SYMBOL(__copy_from_user_ll_nocache);
@@ -675,6 +684,7 @@ EXPORT_SYMBOL(__copy_from_user_ll_nocache);
 unsigned long __copy_from_user_ll_nocache_nozero(void *to, const void __user *from,
 					unsigned long n)
 {
+	stac();
 #ifdef CONFIG_X86_INTEL_USERCOPY
 	if (n > 64 && cpu_has_xmm2)
 		n = __copy_user_intel_nocache(to, from, n);
@@ -683,6 +693,7 @@ unsigned long __copy_from_user_ll_nocache_nozero(void *to, const void __user *fr
 #else
 	__copy_user(to, from, n);
 #endif
+	clac();
 	return n;
 }
 EXPORT_SYMBOL(__copy_from_user_ll_nocache_nozero);
diff --git a/arch/x86/lib/usercopy_64.c b/arch/x86/lib/usercopy_64.c
index e5b130b..05928aa 100644
--- a/arch/x86/lib/usercopy_64.c
+++ b/arch/x86/lib/usercopy_64.c
@@ -18,6 +18,7 @@ unsigned long __clear_user(void __user *addr, unsigned long size)
 	might_fault();
 	/* no memory constraint because it doesn't change any memory gcc knows
 	   about */
+	stac();
 	asm volatile(
 		"	testq  %[size8],%[size8]\n"
 		"	jz     4f\n"
@@ -40,6 +41,7 @@ unsigned long __clear_user(void __user *addr, unsigned long size)
 		: [size8] "=&c"(size), [dst] "=&D" (__d0)
 		: [size1] "r"(size & 7), "[size8]" (size / 8), "[dst]"(addr),
 		  [zero] "r" (0UL), [eight] "r" (8UL));
+	clac();
 	return size;
 }
 EXPORT_SYMBOL(__clear_user);
@@ -82,5 +84,6 @@ copy_user_handle_tail(char *to, char *from, unsigned len, unsigned zerorest)
 	for (c = 0, zero_len = len; zerorest && zero_len; --zero_len)
 		if (__put_user_nocheck(c, to++, sizeof(char)))
 			break;
+	clac();
 	return len;
 }
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index 76dcd9d..56e33b8 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -995,6 +995,17 @@ static int fault_in_kernel_space(unsigned long address)
 	return address >= TASK_SIZE_MAX;
 }
 
+static inline bool smap_violation(int error_code, struct pt_regs *regs)
+{
+	if (error_code & PF_USER)
+		return false;
+
+	if (!user_mode_vm(regs) && (regs->flags & X86_EFLAGS_AC))
+		return false;
+
+	return true;
+}
+
 /*
  * This routine handles page faults.  It determines the address,
  * and the problem, and then passes it off to one of the appropriate
@@ -1088,6 +1099,13 @@ do_page_fault(struct pt_regs *regs, unsigned long error_code)
 	if (unlikely(error_code & PF_RSVD))
 		pgtable_bad(regs, error_code, address);
 
+	if (static_cpu_has(X86_FEATURE_SMAP)) {
+		if (unlikely(smap_violation(error_code, regs))) {
+			bad_area_nosemaphore(regs, error_code, address);
+			return;
+		}
+	}
+
 	perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
 
 	/*
@@ -1201,6 +1219,7 @@ good_area:
 			/* Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk
 			 * of starvation. */
 			flags &= ~FAULT_FLAG_ALLOW_RETRY;
+			flags |= FAULT_FLAG_TRIED;
 			goto retry;
 		}
 	}
diff --git a/arch/x86/mm/hugetlbpage.c b/arch/x86/mm/hugetlbpage.c
index b91e485..937bff5 100644
--- a/arch/x86/mm/hugetlbpage.c
+++ b/arch/x86/mm/hugetlbpage.c
@@ -71,7 +71,6 @@ huge_pmd_share(struct mm_struct *mm, unsigned long addr, pud_t *pud)
 	struct address_space *mapping = vma->vm_file->f_mapping;
 	pgoff_t idx = ((addr - vma->vm_start) >> PAGE_SHIFT) +
 			vma->vm_pgoff;
-	struct prio_tree_iter iter;
 	struct vm_area_struct *svma;
 	unsigned long saddr;
 	pte_t *spte = NULL;
@@ -81,7 +80,7 @@ huge_pmd_share(struct mm_struct *mm, unsigned long addr, pud_t *pud)
 		return (pte_t *)pmd_alloc(mm, pud, addr);
 
 	mutex_lock(&mapping->i_mmap_mutex);
-	vma_prio_tree_foreach(svma, &iter, &mapping->i_mmap, idx, idx) {
+	vma_interval_tree_foreach(svma, &mapping->i_mmap, idx, idx) {
 		if (svma == vma)
 			continue;
 
diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c
index 575d86f..11a5800 100644
--- a/arch/x86/mm/init_32.c
+++ b/arch/x86/mm/init_32.c
@@ -445,10 +445,10 @@ static inline void permanent_kmaps_init(pgd_t *pgd_base)
 }
 #endif /* CONFIG_HIGHMEM */
 
-void __init native_pagetable_setup_start(pgd_t *base)
+void __init native_pagetable_init(void)
 {
 	unsigned long pfn, va;
-	pgd_t *pgd;
+	pgd_t *pgd, *base = swapper_pg_dir;
 	pud_t *pud;
 	pmd_t *pmd;
 	pte_t *pte;
@@ -475,10 +475,7 @@ void __init native_pagetable_setup_start(pgd_t *base)
 		pte_clear(NULL, va, pte);
 	}
 	paravirt_alloc_pmd(&init_mm, __pa(base) >> PAGE_SHIFT);
-}
-
-void __init native_pagetable_setup_done(pgd_t *base)
-{
+	paging_init();
 }
 
 /*
@@ -493,7 +490,7 @@ void __init native_pagetable_setup_done(pgd_t *base)
  * If we're booting paravirtualized under a hypervisor, then there are
  * more options: we may already be running PAE, and the pagetable may
  * or may not be based in swapper_pg_dir.  In any case,
- * paravirt_pagetable_setup_start() will set up swapper_pg_dir
+ * paravirt_pagetable_init() will set up swapper_pg_dir
  * appropriately for the rest of the initialization to work.
  *
  * In general, pagetable_init() assumes that the pagetable may already
@@ -712,7 +709,7 @@ static void __init test_wp_bit(void)
   "Checking if this processor honours the WP bit even in supervisor mode...");
 
 	/* Any page-aligned address will do, the test is non-destructive */
-	__set_fixmap(FIX_WP_TEST, __pa(&swapper_pg_dir), PAGE_READONLY);
+	__set_fixmap(FIX_WP_TEST, __pa(&swapper_pg_dir), PAGE_KERNEL_RO);
 	boot_cpu_data.wp_works_ok = do_test_wp_bit();
 	clear_fixmap(FIX_WP_TEST);
 
diff --git a/arch/x86/mm/numa.c b/arch/x86/mm/numa.c
index 2d125be..21d02f0 100644
--- a/arch/x86/mm/numa.c
+++ b/arch/x86/mm/numa.c
@@ -97,8 +97,7 @@ void __cpuinit numa_set_node(int cpu, int node)
 #endif
 	per_cpu(x86_cpu_to_node_map, cpu) = node;
 
-	if (node != NUMA_NO_NODE)
-		set_cpu_numa_node(cpu, node);
+	set_cpu_numa_node(cpu, node);
 }
 
 void __cpuinit numa_clear_node(int cpu)
diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c
index 3d68ef6..0eb572e 100644
--- a/arch/x86/mm/pat.c
+++ b/arch/x86/mm/pat.c
@@ -664,20 +664,20 @@ static void free_pfn_range(u64 paddr, unsigned long size)
 }
 
 /*
- * track_pfn_vma_copy is called when vma that is covering the pfnmap gets
+ * track_pfn_copy is called when vma that is covering the pfnmap gets
  * copied through copy_page_range().
  *
  * If the vma has a linear pfn mapping for the entire range, we get the prot
  * from pte and reserve the entire vma range with single reserve_pfn_range call.
  */
-int track_pfn_vma_copy(struct vm_area_struct *vma)
+int track_pfn_copy(struct vm_area_struct *vma)
 {
 	resource_size_t paddr;
 	unsigned long prot;
 	unsigned long vma_size = vma->vm_end - vma->vm_start;
 	pgprot_t pgprot;
 
-	if (is_linear_pfn_mapping(vma)) {
+	if (vma->vm_flags & VM_PAT) {
 		/*
 		 * reserve the whole chunk covered by vma. We need the
 		 * starting address and protection from pte.
@@ -694,31 +694,59 @@ int track_pfn_vma_copy(struct vm_area_struct *vma)
 }
 
 /*
- * track_pfn_vma_new is called when a _new_ pfn mapping is being established
- * for physical range indicated by pfn and size.
- *
  * prot is passed in as a parameter for the new mapping. If the vma has a
  * linear pfn mapping for the entire range reserve the entire vma range with
  * single reserve_pfn_range call.
  */
-int track_pfn_vma_new(struct vm_area_struct *vma, pgprot_t *prot,
-			unsigned long pfn, unsigned long size)
+int track_pfn_remap(struct vm_area_struct *vma, pgprot_t *prot,
+		    unsigned long pfn, unsigned long addr, unsigned long size)
 {
+	resource_size_t paddr = (resource_size_t)pfn << PAGE_SHIFT;
 	unsigned long flags;
-	resource_size_t paddr;
-	unsigned long vma_size = vma->vm_end - vma->vm_start;
 
-	if (is_linear_pfn_mapping(vma)) {
-		/* reserve the whole chunk starting from vm_pgoff */
-		paddr = (resource_size_t)vma->vm_pgoff << PAGE_SHIFT;
-		return reserve_pfn_range(paddr, vma_size, prot, 0);
+	/* reserve the whole chunk starting from paddr */
+	if (addr == vma->vm_start && size == (vma->vm_end - vma->vm_start)) {
+		int ret;
+
+		ret = reserve_pfn_range(paddr, size, prot, 0);
+		if (!ret)
+			vma->vm_flags |= VM_PAT;
+		return ret;
 	}
 
 	if (!pat_enabled)
 		return 0;
 
-	/* for vm_insert_pfn and friends, we set prot based on lookup */
-	flags = lookup_memtype(pfn << PAGE_SHIFT);
+	/*
+	 * For anything smaller than the vma size we set prot based on the
+	 * lookup.
+	 */
+	flags = lookup_memtype(paddr);
+
+	/* Check memtype for the remaining pages */
+	while (size > PAGE_SIZE) {
+		size -= PAGE_SIZE;
+		paddr += PAGE_SIZE;
+		if (flags != lookup_memtype(paddr))
+			return -EINVAL;
+	}
+
+	*prot = __pgprot((pgprot_val(vma->vm_page_prot) & (~_PAGE_CACHE_MASK)) |
+			 flags);
+
+	return 0;
+}
+
+int track_pfn_insert(struct vm_area_struct *vma, pgprot_t *prot,
+		     unsigned long pfn)
+{
+	unsigned long flags;
+
+	if (!pat_enabled)
+		return 0;
+
+	/* Set prot based on lookup */
+	flags = lookup_memtype((resource_size_t)pfn << PAGE_SHIFT);
 	*prot = __pgprot((pgprot_val(vma->vm_page_prot) & (~_PAGE_CACHE_MASK)) |
 			 flags);
 
@@ -726,22 +754,31 @@ int track_pfn_vma_new(struct vm_area_struct *vma, pgprot_t *prot,
 }
 
 /*
- * untrack_pfn_vma is called while unmapping a pfnmap for a region.
+ * untrack_pfn is called while unmapping a pfnmap for a region.
  * untrack can be called for a specific region indicated by pfn and size or
- * can be for the entire vma (in which case size can be zero).
+ * can be for the entire vma (in which case pfn, size are zero).
  */
-void untrack_pfn_vma(struct vm_area_struct *vma, unsigned long pfn,
-			unsigned long size)
+void untrack_pfn(struct vm_area_struct *vma, unsigned long pfn,
+		 unsigned long size)
 {
 	resource_size_t paddr;
-	unsigned long vma_size = vma->vm_end - vma->vm_start;
+	unsigned long prot;
 
-	if (is_linear_pfn_mapping(vma)) {
-		/* free the whole chunk starting from vm_pgoff */
-		paddr = (resource_size_t)vma->vm_pgoff << PAGE_SHIFT;
-		free_pfn_range(paddr, vma_size);
+	if (!(vma->vm_flags & VM_PAT))
 		return;
+
+	/* free the chunk starting from pfn or the whole chunk */
+	paddr = (resource_size_t)pfn << PAGE_SHIFT;
+	if (!paddr && !size) {
+		if (follow_phys(vma, vma->vm_start, 0, &prot, &paddr)) {
+			WARN_ON_ONCE(1);
+			return;
+		}
+
+		size = vma->vm_end - vma->vm_start;
 	}
+	free_pfn_range(paddr, size);
+	vma->vm_flags &= ~VM_PAT;
 }
 
 pgprot_t pgprot_writecombine(pgprot_t prot)
diff --git a/arch/x86/mm/pat_rbtree.c b/arch/x86/mm/pat_rbtree.c
index 8acaddd..415f6c4 100644
--- a/arch/x86/mm/pat_rbtree.c
+++ b/arch/x86/mm/pat_rbtree.c
@@ -12,7 +12,7 @@
 #include <linux/debugfs.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/rbtree.h>
+#include <linux/rbtree_augmented.h>
 #include <linux/sched.h>
 #include <linux/gfp.h>
 
@@ -54,29 +54,24 @@ static u64 get_subtree_max_end(struct rb_node *node)
 	return ret;
 }
 
-/* Update 'subtree_max_end' for a node, based on node and its children */
-static void memtype_rb_augment_cb(struct rb_node *node, void *__unused)
+static u64 compute_subtree_max_end(struct memtype *data)
 {
-	struct memtype *data;
-	u64 max_end, child_max_end;
-
-	if (!node)
-		return;
+	u64 max_end = data->end, child_max_end;
 
-	data = container_of(node, struct memtype, rb);
-	max_end = data->end;
-
-	child_max_end = get_subtree_max_end(node->rb_right);
+	child_max_end = get_subtree_max_end(data->rb.rb_right);
 	if (child_max_end > max_end)
 		max_end = child_max_end;
 
-	child_max_end = get_subtree_max_end(node->rb_left);
+	child_max_end = get_subtree_max_end(data->rb.rb_left);
 	if (child_max_end > max_end)
 		max_end = child_max_end;
 
-	data->subtree_max_end = max_end;
+	return max_end;
 }
 
+RB_DECLARE_CALLBACKS(static, memtype_rb_augment_cb, struct memtype, rb,
+		     u64, subtree_max_end, compute_subtree_max_end)
+
 /* Find the first (lowest start addr) overlapping range from rb tree */
 static struct memtype *memtype_rb_lowest_match(struct rb_root *root,
 				u64 start, u64 end)
@@ -179,15 +174,17 @@ static void memtype_rb_insert(struct rb_root *root, struct memtype *newdata)
 		struct memtype *data = container_of(*node, struct memtype, rb);
 
 		parent = *node;
+		if (data->subtree_max_end < newdata->end)
+			data->subtree_max_end = newdata->end;
 		if (newdata->start <= data->start)
 			node = &((*node)->rb_left);
 		else if (newdata->start > data->start)
 			node = &((*node)->rb_right);
 	}
 
+	newdata->subtree_max_end = newdata->end;
 	rb_link_node(&newdata->rb, parent, node);
-	rb_insert_color(&newdata->rb, root);
-	rb_augment_insert(&newdata->rb, memtype_rb_augment_cb, NULL);
+	rb_insert_augmented(&newdata->rb, root, &memtype_rb_augment_cb);
 }
 
 int rbt_memtype_check_insert(struct memtype *new, unsigned long *ret_type)
@@ -209,16 +206,13 @@ int rbt_memtype_check_insert(struct memtype *new, unsigned long *ret_type)
 
 struct memtype *rbt_memtype_erase(u64 start, u64 end)
 {
-	struct rb_node *deepest;
 	struct memtype *data;
 
 	data = memtype_rb_exact_match(&memtype_rbroot, start, end);
 	if (!data)
 		goto out;
 
-	deepest = rb_augment_erase_begin(&data->rb);
-	rb_erase(&data->rb, &memtype_rbroot);
-	rb_augment_erase_end(deepest, memtype_rb_augment_cb, NULL);
+	rb_erase_augmented(&data->rb, &memtype_rbroot, &memtype_rb_augment_cb);
 out:
 	return data;
 }
diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c
index 613cd83..a085c56 100644
--- a/arch/x86/mm/tlb.c
+++ b/arch/x86/mm/tlb.c
@@ -320,7 +320,7 @@ static ssize_t tlbflush_write_file(struct file *file,
 	if (kstrtos8(buf, 0, &shift))
 		return -EINVAL;
 
-	if (shift > 64)
+	if (shift < -1 || shift >= BITS_PER_LONG)
 		return -EINVAL;
 
 	tlb_flushall_shift = shift;
diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
index 33643a8..520d2bd 100644
--- a/arch/x86/net/bpf_jit_comp.c
+++ b/arch/x86/net/bpf_jit_comp.c
@@ -280,6 +280,31 @@ void bpf_jit_compile(struct sk_filter *fp)
 				}
 				EMIT4(0x31, 0xd2, 0xf7, 0xf3); /* xor %edx,%edx; div %ebx */
 				break;
+			case BPF_S_ALU_MOD_X: /* A %= X; */
+				seen |= SEEN_XREG;
+				EMIT2(0x85, 0xdb);	/* test %ebx,%ebx */
+				if (pc_ret0 > 0) {
+					/* addrs[pc_ret0 - 1] is start address of target
+					 * (addrs[i] - 6) is the address following this jmp
+					 * ("xor %edx,%edx; div %ebx;mov %edx,%eax" being 6 bytes long)
+					 */
+					EMIT_COND_JMP(X86_JE, addrs[pc_ret0 - 1] -
+								(addrs[i] - 6));
+				} else {
+					EMIT_COND_JMP(X86_JNE, 2 + 5);
+					CLEAR_A();
+					EMIT1_off32(0xe9, cleanup_addr - (addrs[i] - 6)); /* jmp .+off32 */
+				}
+				EMIT2(0x31, 0xd2);	/* xor %edx,%edx */
+				EMIT2(0xf7, 0xf3);	/* div %ebx */
+				EMIT2(0x89, 0xd0);	/* mov %edx,%eax */
+				break;
+			case BPF_S_ALU_MOD_K: /* A %= K; */
+				EMIT2(0x31, 0xd2);	/* xor %edx,%edx */
+				EMIT1(0xb9);EMIT(K, 4);	/* mov imm32,%ecx */
+				EMIT2(0xf7, 0xf1);	/* div %ecx */
+				EMIT2(0x89, 0xd0);	/* mov %edx,%eax */
+				break;
 			case BPF_S_ALU_DIV_K: /* A = reciprocal_divide(A, K); */
 				EMIT3(0x48, 0x69, 0xc0); /* imul imm32,%rax,%rax */
 				EMIT(K, 4);
@@ -310,9 +335,18 @@ void bpf_jit_compile(struct sk_filter *fp)
 					EMIT1_off32(0x0d, K);	/* or imm32,%eax */
 				break;
 			case BPF_S_ANC_ALU_XOR_X: /* A ^= X; */
+			case BPF_S_ALU_XOR_X:
 				seen |= SEEN_XREG;
 				EMIT2(0x31, 0xd8);		/* xor %ebx,%eax */
 				break;
+			case BPF_S_ALU_XOR_K: /* A ^= K; */
+				if (K == 0)
+					break;
+				if (is_imm8(K))
+					EMIT3(0x83, 0xf0, K);	/* xor imm8,%eax */
+				else
+					EMIT1_off32(0x35, K);	/* xor imm32,%eax */
+				break;
 			case BPF_S_ALU_LSH_X: /* A <<= X; */
 				seen |= SEEN_XREG;
 				EMIT4(0x89, 0xd9, 0xd3, 0xe0);	/* mov %ebx,%ecx; shl %cl,%eax */
diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
index 505acdd..192397c 100644
--- a/arch/x86/pci/acpi.c
+++ b/arch/x86/pci/acpi.c
@@ -305,7 +305,6 @@ setup_resource(struct acpi_resource *acpi_res, void *data)
 	res->flags = flags;
 	res->start = start;
 	res->end = end;
-	res->child = NULL;
 
 	if (!pci_use_crs) {
 		dev_printk(KERN_DEBUG, &info->bridge->dev,
@@ -434,7 +433,7 @@ probe_pci_root_info(struct pci_root_info *info, struct acpi_device *device,
 
 	size = sizeof(*info->res) * info->res_num;
 	info->res_num = 0;
-	info->res = kmalloc(size, GFP_KERNEL);
+	info->res = kzalloc(size, GFP_KERNEL);
 	if (!info->res)
 		return;
 
diff --git a/arch/x86/pci/mmconfig-shared.c b/arch/x86/pci/mmconfig-shared.c
index 937bcec..704b9ec 100644
--- a/arch/x86/pci/mmconfig-shared.c
+++ b/arch/x86/pci/mmconfig-shared.c
@@ -585,7 +585,7 @@ static int __init pci_parse_mcfg(struct acpi_table_header *header)
 	while (i >= sizeof(struct acpi_mcfg_allocation)) {
 		entries++;
 		i -= sizeof(struct acpi_mcfg_allocation);
-	};
+	}
 	if (entries == 0) {
 		pr_err(PREFIX "MMCONFIG has no entries\n");
 		return -ENODEV;
diff --git a/arch/x86/pci/visws.c b/arch/x86/pci/visws.c
index 6f2f8ee..3e6d2a6 100644
--- a/arch/x86/pci/visws.c
+++ b/arch/x86/pci/visws.c
@@ -62,11 +62,6 @@ out:
 	return irq;
 }
 
-void __init pcibios_update_irq(struct pci_dev *dev, int irq)
-{
-	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
-}
-
 int __init pci_visws_init(void)
 {
 	pcibios_enable_irq = &pci_visws_enable_irq;
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index 92660eda..f55a4ce 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -890,6 +890,7 @@ void __init efi_enter_virtual_mode(void)
 	 *
 	 * Call EFI services through wrapper functions.
 	 */
+	efi.runtime_version = efi_systab.fw_revision;
 	efi.get_time = virt_efi_get_time;
 	efi.set_time = virt_efi_set_time;
 	efi.get_wakeup_time = virt_efi_get_wakeup_time;
diff --git a/arch/x86/platform/iris/iris.c b/arch/x86/platform/iris/iris.c
index 5917eb5..e6cb80f 100644
--- a/arch/x86/platform/iris/iris.c
+++ b/arch/x86/platform/iris/iris.c
@@ -23,6 +23,7 @@
 
 #include <linux/moduleparam.h>
 #include <linux/module.h>
+#include <linux/platform_device.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/delay.h>
@@ -62,29 +63,75 @@ static void iris_power_off(void)
  * by reading its input port and seeing whether the read value is
  * meaningful.
  */
-static int iris_init(void)
+static int iris_probe(struct platform_device *pdev)
 {
-	unsigned char status;
-	if (force != 1) {
-		printk(KERN_ERR "The force parameter has not been set to 1 so the Iris poweroff handler will not be installed.\n");
-		return -ENODEV;
-	}
-	status = inb(IRIS_GIO_INPUT);
+	unsigned char status = inb(IRIS_GIO_INPUT);
 	if (status == IRIS_GIO_NODEV) {
-		printk(KERN_ERR "This machine does not seem to be an Iris. Power_off handler not installed.\n");
+		printk(KERN_ERR "This machine does not seem to be an Iris. "
+			"Power off handler not installed.\n");
 		return -ENODEV;
 	}
 	old_pm_power_off = pm_power_off;
 	pm_power_off = &iris_power_off;
 	printk(KERN_INFO "Iris power_off handler installed.\n");
-
 	return 0;
 }
 
-static void iris_exit(void)
+static int iris_remove(struct platform_device *pdev)
 {
 	pm_power_off = old_pm_power_off;
 	printk(KERN_INFO "Iris power_off handler uninstalled.\n");
+	return 0;
+}
+
+static struct platform_driver iris_driver = {
+	.driver		= {
+		.name   = "iris",
+		.owner  = THIS_MODULE,
+	},
+	.probe          = iris_probe,
+	.remove         = iris_remove,
+};
+
+static struct resource iris_resources[] = {
+	{
+		.start  = IRIS_GIO_BASE,
+		.end    = IRIS_GIO_OUTPUT,
+		.flags  = IORESOURCE_IO,
+		.name   = "address"
+	}
+};
+
+static struct platform_device *iris_device;
+
+static int iris_init(void)
+{
+	int ret;
+	if (force != 1) {
+		printk(KERN_ERR "The force parameter has not been set to 1."
+			" The Iris poweroff handler will not be installed.\n");
+		return -ENODEV;
+	}
+	ret = platform_driver_register(&iris_driver);
+	if (ret < 0) {
+		printk(KERN_ERR "Failed to register iris platform driver: %d\n",
+			ret);
+		return ret;
+	}
+	iris_device = platform_device_register_simple("iris", (-1),
+				iris_resources, ARRAY_SIZE(iris_resources));
+	if (IS_ERR(iris_device)) {
+		printk(KERN_ERR "Failed to register iris platform device\n");
+		platform_driver_unregister(&iris_driver);
+		return PTR_ERR(iris_device);
+	}
+	return 0;
+}
+
+static void iris_exit(void)
+{
+	platform_device_unregister(iris_device);
+	platform_driver_unregister(&iris_driver);
 }
 
 module_init(iris_init);
diff --git a/arch/x86/syscalls/syscall_32.tbl b/arch/x86/syscalls/syscall_32.tbl
index 7a35a6e..a47103f 100644
--- a/arch/x86/syscalls/syscall_32.tbl
+++ b/arch/x86/syscalls/syscall_32.tbl
@@ -17,7 +17,7 @@
 8	i386	creat			sys_creat
 9	i386	link			sys_link
 10	i386	unlink			sys_unlink
-11	i386	execve			ptregs_execve			stub32_execve
+11	i386	execve			sys_execve			stub32_execve
 12	i386	chdir			sys_chdir
 13	i386	time			sys_time			compat_sys_time
 14	i386	mknod			sys_mknod
diff --git a/arch/x86/tools/insn_sanity.c b/arch/x86/tools/insn_sanity.c
index cc2f8c1..872eb60 100644
--- a/arch/x86/tools/insn_sanity.c
+++ b/arch/x86/tools/insn_sanity.c
@@ -55,7 +55,7 @@ static FILE		*input_file;	/* Input file name */
 static void usage(const char *err)
 {
 	if (err)
-		fprintf(stderr, "Error: %s\n\n", err);
+		fprintf(stderr, "%s: Error: %s\n\n", prog, err);
 	fprintf(stderr, "Usage: %s [-y|-n|-v] [-s seed[,no]] [-m max] [-i input]\n", prog);
 	fprintf(stderr, "\t-y	64bit mode\n");
 	fprintf(stderr, "\t-n	32bit mode\n");
@@ -269,7 +269,13 @@ int main(int argc, char **argv)
 		insns++;
 	}
 
-	fprintf(stdout, "%s: decoded and checked %d %s instructions with %d errors (seed:0x%x)\n", (errors) ? "Failure" : "Success", insns, (input_file) ? "given" : "random", errors, seed);
+	fprintf(stdout, "%s: %s: decoded and checked %d %s instructions with %d errors (seed:0x%x)\n",
+		prog,
+		(errors) ? "Failure" : "Success",
+		insns,
+		(input_file) ? "given" : "random",
+		errors,
+		seed);
 
 	return errors ? 1 : 0;
 }
diff --git a/arch/x86/um/Kconfig b/arch/x86/um/Kconfig
index 9926e11..d049ace 100644
--- a/arch/x86/um/Kconfig
+++ b/arch/x86/um/Kconfig
@@ -13,6 +13,7 @@ endmenu
 config UML_X86
 	def_bool y
 	select GENERIC_FIND_FIRST_BIT
+	select GENERIC_KERNEL_THREAD
 
 config 64BIT
 	bool "64-bit kernel" if SUBARCH = "x86"
@@ -21,9 +22,11 @@ config 64BIT
 config X86_32
 	def_bool !64BIT
 	select HAVE_AOUT
+	select MODULES_USE_ELF_REL
 
 config X86_64
 	def_bool 64BIT
+	select MODULES_USE_ELF_RELA
 
 config RWSEM_XCHGADD_ALGORITHM
 	def_bool X86_XADD && 64BIT
diff --git a/arch/x86/um/shared/sysdep/syscalls.h b/arch/x86/um/shared/sysdep/syscalls.h
index bd9a89b..ca255a8 100644
--- a/arch/x86/um/shared/sysdep/syscalls.h
+++ b/arch/x86/um/shared/sysdep/syscalls.h
@@ -1,3 +1,5 @@
+extern long sys_clone(unsigned long clone_flags, unsigned long newsp,
+	       void __user *parent_tid, void __user *child_tid);
 #ifdef __i386__
 #include "syscalls_32.h"
 #else
diff --git a/arch/x86/um/signal.c b/arch/x86/um/signal.c
index a508cea..ba7363e 100644
--- a/arch/x86/um/signal.c
+++ b/arch/x86/um/signal.c
@@ -416,9 +416,6 @@ int setup_signal_stack_sc(unsigned long stack_top, int sig,
 	PT_REGS_AX(regs) = (unsigned long) sig;
 	PT_REGS_DX(regs) = (unsigned long) 0;
 	PT_REGS_CX(regs) = (unsigned long) 0;
-
-	if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED))
-		ptrace_notify(SIGTRAP);
 	return 0;
 }
 
@@ -466,9 +463,6 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
 	PT_REGS_AX(regs) = (unsigned long) sig;
 	PT_REGS_DX(regs) = (unsigned long) &frame->info;
 	PT_REGS_CX(regs) = (unsigned long) &frame->uc;
-
-	if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED))
-		ptrace_notify(SIGTRAP);
 	return 0;
 }
 
diff --git a/arch/x86/um/sys_call_table_32.c b/arch/x86/um/sys_call_table_32.c
index 68d1dc9..232e605 100644
--- a/arch/x86/um/sys_call_table_32.c
+++ b/arch/x86/um/sys_call_table_32.c
@@ -25,10 +25,9 @@
 #define old_mmap sys_old_mmap
 
 #define ptregs_fork sys_fork
-#define ptregs_execve sys_execve
 #define ptregs_iopl sys_iopl
 #define ptregs_vm86old sys_vm86old
-#define ptregs_clone sys_clone
+#define ptregs_clone i386_clone
 #define ptregs_vm86 sys_vm86
 #define ptregs_sigaltstack sys_sigaltstack
 #define ptregs_vfork sys_vfork
diff --git a/arch/x86/um/syscalls_32.c b/arch/x86/um/syscalls_32.c
index b853e86..db444c7 100644
--- a/arch/x86/um/syscalls_32.c
+++ b/arch/x86/um/syscalls_32.c
@@ -3,37 +3,24 @@
  * Licensed under the GPL
  */
 
-#include "linux/sched.h"
-#include "linux/shm.h"
-#include "linux/ipc.h"
-#include "linux/syscalls.h"
-#include "asm/mman.h"
-#include "asm/uaccess.h"
-#include "asm/unistd.h"
+#include <linux/syscalls.h>
+#include <sysdep/syscalls.h>
 
 /*
  * The prototype on i386 is:
  *
- *     int clone(int flags, void * child_stack, int * parent_tidptr, struct user_desc * newtls, int * child_tidptr)
+ *     int clone(int flags, void * child_stack, int * parent_tidptr, struct user_desc * newtls
  *
  * and the "newtls" arg. on i386 is read by copy_thread directly from the
  * register saved on the stack.
  */
-long sys_clone(unsigned long clone_flags, unsigned long newsp,
-	       int __user *parent_tid, void *newtls, int __user *child_tid)
+long i386_clone(unsigned long clone_flags, unsigned long newsp,
+		int __user *parent_tid, void *newtls, int __user *child_tid)
 {
-	long ret;
-
-	if (!newsp)
-		newsp = UPT_SP(&current->thread.regs.regs);
-
-	current->thread.forking = 1;
-	ret = do_fork(clone_flags, newsp, &current->thread.regs, 0, parent_tid,
-		      child_tid);
-	current->thread.forking = 0;
-	return ret;
+	return sys_clone(clone_flags, newsp, parent_tid, child_tid);
 }
 
+
 long sys_sigaction(int sig, const struct old_sigaction __user *act,
 			 struct old_sigaction __user *oact)
 {
diff --git a/arch/x86/um/syscalls_64.c b/arch/x86/um/syscalls_64.c
index f3d82bb..adb08eb 100644
--- a/arch/x86/um/syscalls_64.c
+++ b/arch/x86/um/syscalls_64.c
@@ -5,12 +5,9 @@
  * Licensed under the GPL
  */
 
-#include "linux/linkage.h"
-#include "linux/personality.h"
-#include "linux/utsname.h"
-#include "asm/prctl.h" /* XXX This should get the constants from libc */
-#include "asm/uaccess.h"
-#include "os.h"
+#include <linux/sched.h>
+#include <asm/prctl.h> /* XXX This should get the constants from libc */
+#include <os.h>
 
 long arch_prctl(struct task_struct *task, int code, unsigned long __user *addr)
 {
@@ -79,20 +76,6 @@ long sys_arch_prctl(int code, unsigned long addr)
 	return arch_prctl(current, code, (unsigned long __user *) addr);
 }
 
-long sys_clone(unsigned long clone_flags, unsigned long newsp,
-	       void __user *parent_tid, void __user *child_tid)
-{
-	long ret;
-
-	if (!newsp)
-		newsp = UPT_SP(&current->thread.regs.regs);
-	current->thread.forking = 1;
-	ret = do_fork(clone_flags, newsp, &current->thread.regs, 0, parent_tid,
-		      child_tid);
-	current->thread.forking = 0;
-	return ret;
-}
-
 void arch_switch_to(struct task_struct *to)
 {
 	if ((to->thread.arch.fs == 0) || (to->mm == NULL))
diff --git a/arch/x86/xen/apic.c b/arch/x86/xen/apic.c
index ec57bd3..7005ced 100644
--- a/arch/x86/xen/apic.c
+++ b/arch/x86/xen/apic.c
@@ -6,8 +6,9 @@
 
 #include <xen/xen.h>
 #include <xen/interface/physdev.h>
+#include "xen-ops.h"
 
-unsigned int xen_io_apic_read(unsigned apic, unsigned reg)
+static unsigned int xen_io_apic_read(unsigned apic, unsigned reg)
 {
 	struct physdev_apic apic_op;
 	int ret;
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index 1fbe75a..2d932c3 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -80,6 +80,8 @@
 #include "smp.h"
 #include "multicalls.h"
 
+#include <xen/events.h>
+
 EXPORT_SYMBOL_GPL(hypercall_page);
 
 DEFINE_PER_CPU(struct vcpu_info *, xen_vcpu);
@@ -1288,7 +1290,6 @@ asmlinkage void __init xen_start_kernel(void)
 {
 	struct physdev_set_iopl set_iopl;
 	int rc;
-	pgd_t *pgd;
 
 	if (!xen_start_info)
 		return;
@@ -1380,8 +1381,6 @@ asmlinkage void __init xen_start_kernel(void)
 	acpi_numa = -1;
 #endif
 
-	pgd = (pgd_t *)xen_start_info->pt_base;
-
 	/* Don't do the full vcpu_info placement stuff until we have a
 	   possible map and a non-dummy shared_info. */
 	per_cpu(xen_vcpu, 0) = &HYPERVISOR_shared_info->vcpu_info[0];
@@ -1390,7 +1389,7 @@ asmlinkage void __init xen_start_kernel(void)
 	early_boot_irqs_disabled = true;
 
 	xen_raw_console_write("mapping kernel into physical memory\n");
-	pgd = xen_setup_kernel_pagetable(pgd, xen_start_info->nr_pages);
+	xen_setup_kernel_pagetable((pgd_t *)xen_start_info->pt_base, xen_start_info->nr_pages);
 
 	/* Allocate and initialize top and mid mfn levels for p2m structure */
 	xen_build_mfn_list_list();
@@ -1441,11 +1440,19 @@ asmlinkage void __init xen_start_kernel(void)
 		const struct dom0_vga_console_info *info =
 			(void *)((char *)xen_start_info +
 				 xen_start_info->console.dom0.info_off);
+		struct xen_platform_op op = {
+			.cmd = XENPF_firmware_info,
+			.interface_version = XENPF_INTERFACE_VERSION,
+			.u.firmware_info.type = XEN_FW_KBD_SHIFT_FLAGS,
+		};
 
 		xen_init_vga(info, xen_start_info->console.dom0.info_size);
 		xen_start_info->console.domU.mfn = 0;
 		xen_start_info->console.domU.evtchn = 0;
 
+		if (HYPERVISOR_dom0_op(&op) == 0)
+			boot_params.kbd_status = op.u.firmware_info.u.kbd_shift_flags;
+
 		xen_init_apic();
 
 		/* Make sure ACS will be enabled */
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
index 5141d80..fd28d86 100644
--- a/arch/x86/xen/mmu.c
+++ b/arch/x86/xen/mmu.c
@@ -84,6 +84,7 @@
  */
 DEFINE_SPINLOCK(xen_reservation_lock);
 
+#ifdef CONFIG_X86_32
 /*
  * Identity map, in addition to plain kernel map.  This needs to be
  * large enough to allocate page table pages to allocate the rest.
@@ -91,7 +92,7 @@ DEFINE_SPINLOCK(xen_reservation_lock);
  */
 #define LEVEL1_IDENT_ENTRIES	(PTRS_PER_PTE * 4)
 static RESERVE_BRK_ARRAY(pte_t, level1_ident_pgt, LEVEL1_IDENT_ENTRIES);
-
+#endif
 #ifdef CONFIG_X86_64
 /* l3 pud for userspace vsyscall mapping */
 static pud_t level3_user_vsyscall[PTRS_PER_PUD] __page_aligned_bss;
@@ -1174,9 +1175,7 @@ static void xen_exit_mmap(struct mm_struct *mm)
 	spin_unlock(&mm->page_table_lock);
 }
 
-static void __init xen_pagetable_setup_start(pgd_t *base)
-{
-}
+static void xen_post_allocator_init(void);
 
 static __init void xen_mapping_pagetable_reserve(u64 start, u64 end)
 {
@@ -1192,14 +1191,87 @@ static __init void xen_mapping_pagetable_reserve(u64 start, u64 end)
 	}
 }
 
-static void xen_post_allocator_init(void);
+#ifdef CONFIG_X86_64
+static void __init xen_cleanhighmap(unsigned long vaddr,
+				    unsigned long vaddr_end)
+{
+	unsigned long kernel_end = roundup((unsigned long)_brk_end, PMD_SIZE) - 1;
+	pmd_t *pmd = level2_kernel_pgt + pmd_index(vaddr);
 
-static void __init xen_pagetable_setup_done(pgd_t *base)
+	/* NOTE: The loop is more greedy than the cleanup_highmap variant.
+	 * We include the PMD passed in on _both_ boundaries. */
+	for (; vaddr <= vaddr_end && (pmd < (level2_kernel_pgt + PAGE_SIZE));
+			pmd++, vaddr += PMD_SIZE) {
+		if (pmd_none(*pmd))
+			continue;
+		if (vaddr < (unsigned long) _text || vaddr > kernel_end)
+			set_pmd(pmd, __pmd(0));
+	}
+	/* In case we did something silly, we should crash in this function
+	 * instead of somewhere later and be confusing. */
+	xen_mc_flush();
+}
+#endif
+static void __init xen_pagetable_init(void)
 {
+#ifdef CONFIG_X86_64
+	unsigned long size;
+	unsigned long addr;
+#endif
+	paging_init();
 	xen_setup_shared_info();
+#ifdef CONFIG_X86_64
+	if (!xen_feature(XENFEAT_auto_translated_physmap)) {
+		unsigned long new_mfn_list;
+
+		size = PAGE_ALIGN(xen_start_info->nr_pages * sizeof(unsigned long));
+
+		/* On 32-bit, we get zero so this never gets executed. */
+		new_mfn_list = xen_revector_p2m_tree();
+		if (new_mfn_list && new_mfn_list != xen_start_info->mfn_list) {
+			/* using __ka address and sticking INVALID_P2M_ENTRY! */
+			memset((void *)xen_start_info->mfn_list, 0xff, size);
+
+			/* We should be in __ka space. */
+			BUG_ON(xen_start_info->mfn_list < __START_KERNEL_map);
+			addr = xen_start_info->mfn_list;
+			/* We roundup to the PMD, which means that if anybody at this stage is
+			 * using the __ka address of xen_start_info or xen_start_info->shared_info
+			 * they are in going to crash. Fortunatly we have already revectored
+			 * in xen_setup_kernel_pagetable and in xen_setup_shared_info. */
+			size = roundup(size, PMD_SIZE);
+			xen_cleanhighmap(addr, addr + size);
+
+			size = PAGE_ALIGN(xen_start_info->nr_pages * sizeof(unsigned long));
+			memblock_free(__pa(xen_start_info->mfn_list), size);
+			/* And revector! Bye bye old array */
+			xen_start_info->mfn_list = new_mfn_list;
+		} else
+			goto skip;
+	}
+	/* At this stage, cleanup_highmap has already cleaned __ka space
+	 * from _brk_limit way up to the max_pfn_mapped (which is the end of
+	 * the ramdisk). We continue on, erasing PMD entries that point to page
+	 * tables - do note that they are accessible at this stage via __va.
+	 * For good measure we also round up to the PMD - which means that if
+	 * anybody is using __ka address to the initial boot-stack - and try
+	 * to use it - they are going to crash. The xen_start_info has been
+	 * taken care of already in xen_setup_kernel_pagetable. */
+	addr = xen_start_info->pt_base;
+	size = roundup(xen_start_info->nr_pt_frames * PAGE_SIZE, PMD_SIZE);
+
+	xen_cleanhighmap(addr, addr + size);
+	xen_start_info->pt_base = (unsigned long)__va(__pa(xen_start_info->pt_base));
+#ifdef DEBUG
+	/* This is superflous and is not neccessary, but you know what
+	 * lets do it. The MODULES_VADDR -> MODULES_END should be clear of
+	 * anything at this stage. */
+	xen_cleanhighmap(MODULES_VADDR, roundup(MODULES_VADDR, PUD_SIZE) - 1);
+#endif
+skip:
+#endif
 	xen_post_allocator_init();
 }
-
 static void xen_write_cr2(unsigned long cr2)
 {
 	this_cpu_read(xen_vcpu)->arch.cr2 = cr2;
@@ -1655,7 +1727,7 @@ static void set_page_prot(void *addr, pgprot_t prot)
 	if (HYPERVISOR_update_va_mapping((unsigned long)addr, pte, 0))
 		BUG();
 }
-
+#ifdef CONFIG_X86_32
 static void __init xen_map_identity_early(pmd_t *pmd, unsigned long max_pfn)
 {
 	unsigned pmdidx, pteidx;
@@ -1706,7 +1778,7 @@ static void __init xen_map_identity_early(pmd_t *pmd, unsigned long max_pfn)
 
 	set_page_prot(pmd, PAGE_KERNEL_RO);
 }
-
+#endif
 void __init xen_setup_machphys_mapping(void)
 {
 	struct xen_machphys_mapping mapping;
@@ -1734,7 +1806,20 @@ static void convert_pfn_mfn(void *v)
 	for (i = 0; i < PTRS_PER_PTE; i++)
 		pte[i] = xen_make_pte(pte[i].pte);
 }
-
+static void __init check_pt_base(unsigned long *pt_base, unsigned long *pt_end,
+				 unsigned long addr)
+{
+	if (*pt_base == PFN_DOWN(__pa(addr))) {
+		set_page_prot((void *)addr, PAGE_KERNEL);
+		clear_page((void *)addr);
+		(*pt_base)++;
+	}
+	if (*pt_end == PFN_DOWN(__pa(addr))) {
+		set_page_prot((void *)addr, PAGE_KERNEL);
+		clear_page((void *)addr);
+		(*pt_end)--;
+	}
+}
 /*
  * Set up the initial kernel pagetable.
  *
@@ -1746,11 +1831,13 @@ static void convert_pfn_mfn(void *v)
  * of the physical mapping once some sort of allocator has been set
  * up.
  */
-pgd_t * __init xen_setup_kernel_pagetable(pgd_t *pgd,
-					 unsigned long max_pfn)
+void __init xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn)
 {
 	pud_t *l3;
 	pmd_t *l2;
+	unsigned long addr[3];
+	unsigned long pt_base, pt_end;
+	unsigned i;
 
 	/* max_pfn_mapped is the last pfn mapped in the initial memory
 	 * mappings. Considering that on Xen after the kernel mappings we
@@ -1758,32 +1845,53 @@ pgd_t * __init xen_setup_kernel_pagetable(pgd_t *pgd,
 	 * set max_pfn_mapped to the last real pfn mapped. */
 	max_pfn_mapped = PFN_DOWN(__pa(xen_start_info->mfn_list));
 
+	pt_base = PFN_DOWN(__pa(xen_start_info->pt_base));
+	pt_end = pt_base + xen_start_info->nr_pt_frames;
+
 	/* Zap identity mapping */
 	init_level4_pgt[0] = __pgd(0);
 
 	/* Pre-constructed entries are in pfn, so convert to mfn */
+	/* L4[272] -> level3_ident_pgt
+	 * L4[511] -> level3_kernel_pgt */
 	convert_pfn_mfn(init_level4_pgt);
+
+	/* L3_i[0] -> level2_ident_pgt */
 	convert_pfn_mfn(level3_ident_pgt);
+	/* L3_k[510] -> level2_kernel_pgt
+	 * L3_i[511] -> level2_fixmap_pgt */
 	convert_pfn_mfn(level3_kernel_pgt);
 
+	/* We get [511][511] and have Xen's version of level2_kernel_pgt */
 	l3 = m2v(pgd[pgd_index(__START_KERNEL_map)].pgd);
 	l2 = m2v(l3[pud_index(__START_KERNEL_map)].pud);
 
-	memcpy(level2_ident_pgt, l2, sizeof(pmd_t) * PTRS_PER_PMD);
-	memcpy(level2_kernel_pgt, l2, sizeof(pmd_t) * PTRS_PER_PMD);
-
+	addr[0] = (unsigned long)pgd;
+	addr[1] = (unsigned long)l3;
+	addr[2] = (unsigned long)l2;
+	/* Graft it onto L4[272][0]. Note that we creating an aliasing problem:
+	 * Both L4[272][0] and L4[511][511] have entries that point to the same
+	 * L2 (PMD) tables. Meaning that if you modify it in __va space
+	 * it will be also modified in the __ka space! (But if you just
+	 * modify the PMD table to point to other PTE's or none, then you
+	 * are OK - which is what cleanup_highmap does) */
+	copy_page(level2_ident_pgt, l2);
+	/* Graft it onto L4[511][511] */
+	copy_page(level2_kernel_pgt, l2);
+
+	/* Get [511][510] and graft that in level2_fixmap_pgt */
 	l3 = m2v(pgd[pgd_index(__START_KERNEL_map + PMD_SIZE)].pgd);
 	l2 = m2v(l3[pud_index(__START_KERNEL_map + PMD_SIZE)].pud);
-	memcpy(level2_fixmap_pgt, l2, sizeof(pmd_t) * PTRS_PER_PMD);
-
-	/* Set up identity map */
-	xen_map_identity_early(level2_ident_pgt, max_pfn);
+	copy_page(level2_fixmap_pgt, l2);
+	/* Note that we don't do anything with level1_fixmap_pgt which
+	 * we don't need. */
 
 	/* Make pagetable pieces RO */
 	set_page_prot(init_level4_pgt, PAGE_KERNEL_RO);
 	set_page_prot(level3_ident_pgt, PAGE_KERNEL_RO);
 	set_page_prot(level3_kernel_pgt, PAGE_KERNEL_RO);
 	set_page_prot(level3_user_vsyscall, PAGE_KERNEL_RO);
+	set_page_prot(level2_ident_pgt, PAGE_KERNEL_RO);
 	set_page_prot(level2_kernel_pgt, PAGE_KERNEL_RO);
 	set_page_prot(level2_fixmap_pgt, PAGE_KERNEL_RO);
 
@@ -1794,22 +1902,28 @@ pgd_t * __init xen_setup_kernel_pagetable(pgd_t *pgd,
 	/* Unpin Xen-provided one */
 	pin_pagetable_pfn(MMUEXT_UNPIN_TABLE, PFN_DOWN(__pa(pgd)));
 
-	/* Switch over */
-	pgd = init_level4_pgt;
-
 	/*
 	 * At this stage there can be no user pgd, and no page
 	 * structure to attach it to, so make sure we just set kernel
 	 * pgd.
 	 */
 	xen_mc_batch();
-	__xen_write_cr3(true, __pa(pgd));
+	__xen_write_cr3(true, __pa(init_level4_pgt));
 	xen_mc_issue(PARAVIRT_LAZY_CPU);
 
-	memblock_reserve(__pa(xen_start_info->pt_base),
-			 xen_start_info->nr_pt_frames * PAGE_SIZE);
+	/* We can't that easily rip out L3 and L2, as the Xen pagetables are
+	 * set out this way: [L4], [L1], [L2], [L3], [L1], [L1] ...  for
+	 * the initial domain. For guests using the toolstack, they are in:
+	 * [L4], [L3], [L2], [L1], [L1], order .. So for dom0 we can only
+	 * rip out the [L4] (pgd), but for guests we shave off three pages.
+	 */
+	for (i = 0; i < ARRAY_SIZE(addr); i++)
+		check_pt_base(&pt_base, &pt_end, addr[i]);
 
-	return pgd;
+	/* Our (by three pages) smaller Xen pagetable that we are using */
+	memblock_reserve(PFN_PHYS(pt_base), (pt_end - pt_base) * PAGE_SIZE);
+	/* Revector the xen_start_info */
+	xen_start_info = (struct start_info *)__va(__pa(xen_start_info));
 }
 #else	/* !CONFIG_X86_64 */
 static RESERVE_BRK_ARRAY(pmd_t, initial_kernel_pmd, PTRS_PER_PMD);
@@ -1834,8 +1948,7 @@ static void __init xen_write_cr3_init(unsigned long cr3)
 	 */
 	swapper_kernel_pmd =
 		extend_brk(sizeof(pmd_t) * PTRS_PER_PMD, PAGE_SIZE);
-	memcpy(swapper_kernel_pmd, initial_kernel_pmd,
-	       sizeof(pmd_t) * PTRS_PER_PMD);
+	copy_page(swapper_kernel_pmd, initial_kernel_pmd);
 	swapper_pg_dir[KERNEL_PGD_BOUNDARY] =
 		__pgd(__pa(swapper_kernel_pmd) | _PAGE_PRESENT);
 	set_page_prot(swapper_kernel_pmd, PAGE_KERNEL_RO);
@@ -1852,8 +1965,7 @@ static void __init xen_write_cr3_init(unsigned long cr3)
 	pv_mmu_ops.write_cr3 = &xen_write_cr3;
 }
 
-pgd_t * __init xen_setup_kernel_pagetable(pgd_t *pgd,
-					 unsigned long max_pfn)
+void __init xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn)
 {
 	pmd_t *kernel_pmd;
 
@@ -1865,11 +1977,11 @@ pgd_t * __init xen_setup_kernel_pagetable(pgd_t *pgd,
 				  512*1024);
 
 	kernel_pmd = m2v(pgd[KERNEL_PGD_BOUNDARY].pgd);
-	memcpy(initial_kernel_pmd, kernel_pmd, sizeof(pmd_t) * PTRS_PER_PMD);
+	copy_page(initial_kernel_pmd, kernel_pmd);
 
 	xen_map_identity_early(initial_kernel_pmd, max_pfn);
 
-	memcpy(initial_page_table, pgd, sizeof(pgd_t) * PTRS_PER_PGD);
+	copy_page(initial_page_table, pgd);
 	initial_page_table[KERNEL_PGD_BOUNDARY] =
 		__pgd(__pa(initial_kernel_pmd) | _PAGE_PRESENT);
 
@@ -1885,8 +1997,6 @@ pgd_t * __init xen_setup_kernel_pagetable(pgd_t *pgd,
 
 	memblock_reserve(__pa(xen_start_info->pt_base),
 			 xen_start_info->nr_pt_frames * PAGE_SIZE);
-
-	return initial_page_table;
 }
 #endif	/* CONFIG_X86_64 */
 
@@ -2068,8 +2178,7 @@ static const struct pv_mmu_ops xen_mmu_ops __initconst = {
 void __init xen_init_mmu_ops(void)
 {
 	x86_init.mapping.pagetable_reserve = xen_mapping_pagetable_reserve;
-	x86_init.paging.pagetable_setup_start = xen_pagetable_setup_start;
-	x86_init.paging.pagetable_setup_done = xen_pagetable_setup_done;
+	x86_init.paging.pagetable_init = xen_pagetable_init;
 	pv_mmu_ops = xen_mmu_ops;
 
 	memset(dummy_mapping, 0xff, PAGE_SIZE);
@@ -2337,10 +2446,12 @@ int xen_remap_domain_mfn_range(struct vm_area_struct *vma,
 	unsigned long range;
 	int err = 0;
 
+	if (xen_feature(XENFEAT_auto_translated_physmap))
+		return -EINVAL;
+
 	prot = __pgprot(pgprot_val(prot) | _PAGE_IOMAP);
 
-	BUG_ON(!((vma->vm_flags & (VM_PFNMAP | VM_RESERVED | VM_IO)) ==
-				(VM_PFNMAP | VM_RESERVED | VM_IO)));
+	BUG_ON(!((vma->vm_flags & (VM_PFNMAP | VM_IO)) == (VM_PFNMAP | VM_IO)));
 
 	rmd.mfn = mfn;
 	rmd.prot = prot;
@@ -2355,8 +2466,8 @@ int xen_remap_domain_mfn_range(struct vm_area_struct *vma,
 		if (err)
 			goto out;
 
-		err = -EFAULT;
-		if (HYPERVISOR_mmu_update(mmu_update, batch, NULL, domid) < 0)
+		err = HYPERVISOR_mmu_update(mmu_update, batch, NULL, domid);
+		if (err < 0)
 			goto out;
 
 		nr -= batch;
diff --git a/arch/x86/xen/p2m.c b/arch/x86/xen/p2m.c
index 72213da..95fb2aa 100644
--- a/arch/x86/xen/p2m.c
+++ b/arch/x86/xen/p2m.c
@@ -22,7 +22,7 @@
  *
  * P2M_PER_PAGE depends on the architecture, as a mfn is always
  * unsigned long (8 bytes on 64-bit, 4 bytes on 32), leading to
- * 512 and 1024 entries respectively. 
+ * 512 and 1024 entries respectively.
  *
  * In short, these structures contain the Machine Frame Number (MFN) of the PFN.
  *
@@ -139,11 +139,11 @@
  *      /    | ~0, ~0, ....  |
  *     |     \---------------/
  *     |
- *     p2m_missing             p2m_missing
- * /------------------\     /------------\
- * | [p2m_mid_missing]+---->| ~0, ~0, ~0 |
- * | [p2m_mid_missing]+---->| ..., ~0    |
- * \------------------/     \------------/
+ *   p2m_mid_missing           p2m_missing
+ * /-----------------\     /------------\
+ * | [p2m_missing]   +---->| ~0, ~0, ~0 |
+ * | [p2m_missing]   +---->| ..., ~0    |
+ * \-----------------/     \------------/
  *
  * where ~0 is INVALID_P2M_ENTRY. IDENTITY is (PFN | IDENTITY_BIT)
  */
@@ -396,7 +396,85 @@ void __init xen_build_dynamic_phys_to_machine(void)
 
 	m2p_override_init();
 }
+#ifdef CONFIG_X86_64
+#include <linux/bootmem.h>
+unsigned long __init xen_revector_p2m_tree(void)
+{
+	unsigned long va_start;
+	unsigned long va_end;
+	unsigned long pfn;
+	unsigned long pfn_free = 0;
+	unsigned long *mfn_list = NULL;
+	unsigned long size;
+
+	va_start = xen_start_info->mfn_list;
+	/*We copy in increments of P2M_PER_PAGE * sizeof(unsigned long),
+	 * so make sure it is rounded up to that */
+	size = PAGE_ALIGN(xen_start_info->nr_pages * sizeof(unsigned long));
+	va_end = va_start + size;
+
+	/* If we were revectored already, don't do it again. */
+	if (va_start <= __START_KERNEL_map && va_start >= __PAGE_OFFSET)
+		return 0;
+
+	mfn_list = alloc_bootmem_align(size, PAGE_SIZE);
+	if (!mfn_list) {
+		pr_warn("Could not allocate space for a new P2M tree!\n");
+		return xen_start_info->mfn_list;
+	}
+	/* Fill it out with INVALID_P2M_ENTRY value */
+	memset(mfn_list, 0xFF, size);
+
+	for (pfn = 0; pfn < ALIGN(MAX_DOMAIN_PAGES, P2M_PER_PAGE); pfn += P2M_PER_PAGE) {
+		unsigned topidx = p2m_top_index(pfn);
+		unsigned mididx;
+		unsigned long *mid_p;
+
+		if (!p2m_top[topidx])
+			continue;
+
+		if (p2m_top[topidx] == p2m_mid_missing)
+			continue;
+
+		mididx = p2m_mid_index(pfn);
+		mid_p = p2m_top[topidx][mididx];
+		if (!mid_p)
+			continue;
+		if ((mid_p == p2m_missing) || (mid_p == p2m_identity))
+			continue;
+
+		if ((unsigned long)mid_p == INVALID_P2M_ENTRY)
+			continue;
+
+		/* The old va. Rebase it on mfn_list */
+		if (mid_p >= (unsigned long *)va_start && mid_p <= (unsigned long *)va_end) {
+			unsigned long *new;
+
+			if (pfn_free  > (size / sizeof(unsigned long))) {
+				WARN(1, "Only allocated for %ld pages, but we want %ld!\n",
+				     size / sizeof(unsigned long), pfn_free);
+				return 0;
+			}
+			new = &mfn_list[pfn_free];
+
+			copy_page(new, mid_p);
+			p2m_top[topidx][mididx] = &mfn_list[pfn_free];
+			p2m_top_mfn_p[topidx][mididx] = virt_to_mfn(&mfn_list[pfn_free]);
+
+			pfn_free += P2M_PER_PAGE;
 
+		}
+		/* This should be the leafs allocated for identity from _brk. */
+	}
+	return (unsigned long)mfn_list;
+
+}
+#else
+unsigned long __init xen_revector_p2m_tree(void)
+{
+	return 0;
+}
+#endif
 unsigned long get_phys_to_machine(unsigned long pfn)
 {
 	unsigned topidx, mididx, idx;
@@ -430,7 +508,7 @@ static void free_p2m_page(void *p)
 	free_page((unsigned long)p);
 }
 
-/* 
+/*
  * Fully allocate the p2m structure for a given pfn.  We need to check
  * that both the top and mid levels are allocated, and make sure the
  * parallel mfn tree is kept in sync.  We may race with other cpus, so
diff --git a/arch/x86/xen/pci-swiotlb-xen.c b/arch/x86/xen/pci-swiotlb-xen.c
index 967633a..9695704 100644
--- a/arch/x86/xen/pci-swiotlb-xen.c
+++ b/arch/x86/xen/pci-swiotlb-xen.c
@@ -8,6 +8,14 @@
 #include <xen/xen.h>
 #include <asm/iommu_table.h>
 
+
+#include <asm/xen/swiotlb-xen.h>
+#ifdef CONFIG_X86_64
+#include <asm/iommu.h>
+#include <asm/dma.h>
+#endif
+#include <linux/export.h>
+
 int xen_swiotlb __read_mostly;
 
 static struct dma_map_ops xen_swiotlb_dma_ops = {
@@ -34,34 +42,64 @@ static struct dma_map_ops xen_swiotlb_dma_ops = {
 int __init pci_xen_swiotlb_detect(void)
 {
 
+	if (!xen_pv_domain())
+		return 0;
+
 	/* If running as PV guest, either iommu=soft, or swiotlb=force will
 	 * activate this IOMMU. If running as PV privileged, activate it
 	 * irregardless.
 	 */
-	if ((xen_initial_domain() || swiotlb || swiotlb_force) &&
-	    (xen_pv_domain()))
+	if ((xen_initial_domain() || swiotlb || swiotlb_force))
 		xen_swiotlb = 1;
 
 	/* If we are running under Xen, we MUST disable the native SWIOTLB.
 	 * Don't worry about swiotlb_force flag activating the native, as
 	 * the 'swiotlb' flag is the only one turning it on. */
-	if (xen_pv_domain())
-		swiotlb = 0;
+	swiotlb = 0;
 
+#ifdef CONFIG_X86_64
+	/* pci_swiotlb_detect_4gb turns on native SWIOTLB if no_iommu == 0
+	 * (so no iommu=X command line over-writes).
+	 * Considering that PV guests do not want the *native SWIOTLB* but
+	 * only Xen SWIOTLB it is not useful to us so set no_iommu=1 here.
+	 */
+	if (max_pfn > MAX_DMA32_PFN)
+		no_iommu = 1;
+#endif
 	return xen_swiotlb;
 }
 
 void __init pci_xen_swiotlb_init(void)
 {
 	if (xen_swiotlb) {
-		xen_swiotlb_init(1);
+		xen_swiotlb_init(1, true /* early */);
 		dma_ops = &xen_swiotlb_dma_ops;
 
 		/* Make sure ACS will be enabled */
 		pci_request_acs();
 	}
 }
+
+int pci_xen_swiotlb_init_late(void)
+{
+	int rc;
+
+	if (xen_swiotlb)
+		return 0;
+
+	rc = xen_swiotlb_init(1, false /* late */);
+	if (rc)
+		return rc;
+
+	dma_ops = &xen_swiotlb_dma_ops;
+	/* Make sure ACS will be enabled */
+	pci_request_acs();
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(pci_xen_swiotlb_init_late);
+
 IOMMU_INIT_FINISH(pci_xen_swiotlb_detect,
-		  0,
+		  NULL,
 		  pci_xen_swiotlb_init,
-		  0);
+		  NULL);
diff --git a/arch/x86/xen/platform-pci-unplug.c b/arch/x86/xen/platform-pci-unplug.c
index ffcf261..0a78524 100644
--- a/arch/x86/xen/platform-pci-unplug.c
+++ b/arch/x86/xen/platform-pci-unplug.c
@@ -24,6 +24,7 @@
 #include <linux/module.h>
 
 #include <xen/platform_pci.h>
+#include "xen-ops.h"
 
 #define XEN_PLATFORM_ERR_MAGIC -1
 #define XEN_PLATFORM_ERR_PROTOCOL -2
diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c
index d11ca11..d12f7d3 100644
--- a/arch/x86/xen/setup.c
+++ b/arch/x86/xen/setup.c
@@ -17,6 +17,7 @@
 #include <asm/e820.h>
 #include <asm/setup.h>
 #include <asm/acpi.h>
+#include <asm/numa.h>
 #include <asm/xen/hypervisor.h>
 #include <asm/xen/hypercall.h>
 
@@ -431,6 +432,24 @@ char * __init xen_memory_setup(void)
 	 *  - mfn_list
 	 *  - xen_start_info
 	 * See comment above "struct start_info" in <xen/interface/xen.h>
+	 * We tried to make the the memblock_reserve more selective so
+	 * that it would be clear what region is reserved. Sadly we ran
+	 * in the problem wherein on a 64-bit hypervisor with a 32-bit
+	 * initial domain, the pt_base has the cr3 value which is not
+	 * neccessarily where the pagetable starts! As Jan put it: "
+	 * Actually, the adjustment turns out to be correct: The page
+	 * tables for a 32-on-64 dom0 get allocated in the order "first L1",
+	 * "first L2", "first L3", so the offset to the page table base is
+	 * indeed 2. When reading xen/include/public/xen.h's comment
+	 * very strictly, this is not a violation (since there nothing is said
+	 * that the first thing in the page table space is pointed to by
+	 * pt_base; I admit that this seems to be implied though, namely
+	 * do I think that it is implied that the page table space is the
+	 * range [pt_base, pt_base + nt_pt_frames), whereas that
+	 * range here indeed is [pt_base - 2, pt_base - 2 + nt_pt_frames),
+	 * which - without a priori knowledge - the kernel would have
+	 * difficulty to figure out)." - so lets just fall back to the
+	 * easy way and reserve the whole region.
 	 */
 	memblock_reserve(__pa(xen_start_info->mfn_list),
 			 xen_start_info->pt_base - xen_start_info->mfn_list);
@@ -507,10 +526,9 @@ void __cpuinit xen_enable_syscall(void)
 #endif /* CONFIG_X86_64 */
 }
 
-void __init xen_arch_setup(void)
+/* Normal PV domain not running in HVM container */
+static __init void inline xen_non_pvh_arch_setup(void)
 {
-	xen_panic_handler_init();
-
 	HYPERVISOR_vm_assist(VMASST_CMD_enable, VMASST_TYPE_4gb_segments);
 	HYPERVISOR_vm_assist(VMASST_CMD_enable, VMASST_TYPE_writable_pagetables);
 
@@ -524,6 +542,14 @@ void __init xen_arch_setup(void)
 
 	xen_enable_sysenter();
 	xen_enable_syscall();
+}
+
+void __init xen_arch_setup(void)
+{
+	xen_panic_handler_init();
+
+	if (!xen_pvh_domain())
+		xen_non_pvh_arch_setup();
 
 #ifdef CONFIG_ACPI
 	if (!(xen_start_info->flags & SIF_INITDOMAIN)) {
@@ -544,4 +570,7 @@ void __init xen_arch_setup(void)
 	disable_cpufreq();
 	WARN_ON(set_pm_idle_to_default());
 	fiddle_vdso();
+#ifdef CONFIG_NUMA
+	numa_off = 1;
+#endif
 }
diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c
index f58dca7..620e5a2 100644
--- a/arch/x86/xen/smp.c
+++ b/arch/x86/xen/smp.c
@@ -300,8 +300,6 @@ cpu_initialize_context(unsigned int cpu, struct task_struct *idle)
 	gdt = get_cpu_gdt_table(cpu);
 
 	ctxt->flags = VGCF_IN_KERNEL;
-	ctxt->user_regs.ds = __USER_DS;
-	ctxt->user_regs.es = __USER_DS;
 	ctxt->user_regs.ss = __KERNEL_DS;
 #ifdef CONFIG_X86_32
 	ctxt->user_regs.fs = __KERNEL_PERCPU;
@@ -314,31 +312,36 @@ cpu_initialize_context(unsigned int cpu, struct task_struct *idle)
 
 	memset(&ctxt->fpu_ctxt, 0, sizeof(ctxt->fpu_ctxt));
 
-	xen_copy_trap_info(ctxt->trap_ctxt);
+		ctxt->user_regs.ds = __USER_DS;
+		ctxt->user_regs.es = __USER_DS;
 
-	ctxt->ldt_ents = 0;
+		xen_copy_trap_info(ctxt->trap_ctxt);
 
-	BUG_ON((unsigned long)gdt & ~PAGE_MASK);
+		ctxt->ldt_ents = 0;
 
-	gdt_mfn = arbitrary_virt_to_mfn(gdt);
-	make_lowmem_page_readonly(gdt);
-	make_lowmem_page_readonly(mfn_to_virt(gdt_mfn));
+		BUG_ON((unsigned long)gdt & ~PAGE_MASK);
 
-	ctxt->gdt_frames[0] = gdt_mfn;
-	ctxt->gdt_ents      = GDT_ENTRIES;
+		gdt_mfn = arbitrary_virt_to_mfn(gdt);
+		make_lowmem_page_readonly(gdt);
+		make_lowmem_page_readonly(mfn_to_virt(gdt_mfn));
 
-	ctxt->user_regs.cs = __KERNEL_CS;
-	ctxt->user_regs.esp = idle->thread.sp0 - sizeof(struct pt_regs);
+		ctxt->gdt_frames[0] = gdt_mfn;
+		ctxt->gdt_ents      = GDT_ENTRIES;
 
-	ctxt->kernel_ss = __KERNEL_DS;
-	ctxt->kernel_sp = idle->thread.sp0;
+		ctxt->kernel_ss = __KERNEL_DS;
+		ctxt->kernel_sp = idle->thread.sp0;
 
 #ifdef CONFIG_X86_32
-	ctxt->event_callback_cs     = __KERNEL_CS;
-	ctxt->failsafe_callback_cs  = __KERNEL_CS;
+		ctxt->event_callback_cs     = __KERNEL_CS;
+		ctxt->failsafe_callback_cs  = __KERNEL_CS;
 #endif
-	ctxt->event_callback_eip    = (unsigned long)xen_hypervisor_callback;
-	ctxt->failsafe_callback_eip = (unsigned long)xen_failsafe_callback;
+		ctxt->event_callback_eip    =
+					(unsigned long)xen_hypervisor_callback;
+		ctxt->failsafe_callback_eip =
+					(unsigned long)xen_failsafe_callback;
+
+	ctxt->user_regs.cs = __KERNEL_CS;
+	ctxt->user_regs.esp = idle->thread.sp0 - sizeof(struct pt_regs);
 
 	per_cpu(xen_cr3, cpu) = __pa(swapper_pg_dir);
 	ctxt->ctrlreg[3] = xen_pfn_to_cr3(virt_to_mfn(swapper_pg_dir));
@@ -377,7 +380,8 @@ static int __cpuinit xen_cpu_up(unsigned int cpu, struct task_struct *idle)
 		return rc;
 
 	if (num_online_cpus() == 1)
-		alternatives_smp_switch(1);
+		/* Just in case we booted with a single CPU. */
+		alternatives_enable_smp();
 
 	rc = xen_smp_intr_init(cpu);
 	if (rc)
@@ -424,9 +428,6 @@ static void xen_cpu_die(unsigned int cpu)
 	unbind_from_irqhandler(per_cpu(xen_irq_work, cpu), NULL);
 	xen_uninit_lock_cpu(cpu);
 	xen_teardown_timer(cpu);
-
-	if (num_online_cpus() == 1)
-		alternatives_smp_switch(0);
 }
 
 static void __cpuinit xen_play_dead(void) /* used only with HOTPLUG_CPU */
diff --git a/arch/x86/xen/vga.c b/arch/x86/xen/vga.c
index 1cd7f4d..6722e37 100644
--- a/arch/x86/xen/vga.c
+++ b/arch/x86/xen/vga.c
@@ -35,6 +35,7 @@ void __init xen_init_vga(const struct dom0_vga_console_info *info, size_t size)
 			info->u.text_mode_3.font_height;
 		break;
 
+	case XEN_VGATYPE_EFI_LFB:
 	case XEN_VGATYPE_VESA_LFB:
 		if (size < offsetof(struct dom0_vga_console_info,
 				    u.vesa_lfb.gbl_caps))
@@ -54,6 +55,12 @@ void __init xen_init_vga(const struct dom0_vga_console_info *info, size_t size)
 		screen_info->blue_pos = info->u.vesa_lfb.blue_pos;
 		screen_info->rsvd_size = info->u.vesa_lfb.rsvd_size;
 		screen_info->rsvd_pos = info->u.vesa_lfb.rsvd_pos;
+
+		if (info->video_type == XEN_VGATYPE_EFI_LFB) {
+			screen_info->orig_video_isVGA = VIDEO_TYPE_EFI;
+			break;
+		}
+
 		if (size >= offsetof(struct dom0_vga_console_info,
 				     u.vesa_lfb.gbl_caps)
 		    + sizeof(info->u.vesa_lfb.gbl_caps))
diff --git a/arch/x86/xen/xen-head.S b/arch/x86/xen/xen-head.S
index aaa7291..7faed58 100644
--- a/arch/x86/xen/xen-head.S
+++ b/arch/x86/xen/xen-head.S
@@ -28,9 +28,61 @@ ENTRY(startup_xen)
 	__FINIT
 
 .pushsection .text
-	.align PAGE_SIZE
+	.balign PAGE_SIZE
 ENTRY(hypercall_page)
-	.skip PAGE_SIZE
+#define NEXT_HYPERCALL(x) \
+	ENTRY(xen_hypercall_##x) \
+	.skip 32
+
+NEXT_HYPERCALL(set_trap_table)
+NEXT_HYPERCALL(mmu_update)
+NEXT_HYPERCALL(set_gdt)
+NEXT_HYPERCALL(stack_switch)
+NEXT_HYPERCALL(set_callbacks)
+NEXT_HYPERCALL(fpu_taskswitch)
+NEXT_HYPERCALL(sched_op_compat)
+NEXT_HYPERCALL(platform_op)
+NEXT_HYPERCALL(set_debugreg)
+NEXT_HYPERCALL(get_debugreg)
+NEXT_HYPERCALL(update_descriptor)
+NEXT_HYPERCALL(ni)
+NEXT_HYPERCALL(memory_op)
+NEXT_HYPERCALL(multicall)
+NEXT_HYPERCALL(update_va_mapping)
+NEXT_HYPERCALL(set_timer_op)
+NEXT_HYPERCALL(event_channel_op_compat)
+NEXT_HYPERCALL(xen_version)
+NEXT_HYPERCALL(console_io)
+NEXT_HYPERCALL(physdev_op_compat)
+NEXT_HYPERCALL(grant_table_op)
+NEXT_HYPERCALL(vm_assist)
+NEXT_HYPERCALL(update_va_mapping_otherdomain)
+NEXT_HYPERCALL(iret)
+NEXT_HYPERCALL(vcpu_op)
+NEXT_HYPERCALL(set_segment_base)
+NEXT_HYPERCALL(mmuext_op)
+NEXT_HYPERCALL(xsm_op)
+NEXT_HYPERCALL(nmi_op)
+NEXT_HYPERCALL(sched_op)
+NEXT_HYPERCALL(callback_op)
+NEXT_HYPERCALL(xenoprof_op)
+NEXT_HYPERCALL(event_channel_op)
+NEXT_HYPERCALL(physdev_op)
+NEXT_HYPERCALL(hvm_op)
+NEXT_HYPERCALL(sysctl)
+NEXT_HYPERCALL(domctl)
+NEXT_HYPERCALL(kexec_op)
+NEXT_HYPERCALL(tmem_op) /* 38 */
+ENTRY(xen_hypercall_rsvr)
+	.skip 320
+NEXT_HYPERCALL(mca) /* 48 */
+NEXT_HYPERCALL(arch_1)
+NEXT_HYPERCALL(arch_2)
+NEXT_HYPERCALL(arch_3)
+NEXT_HYPERCALL(arch_4)
+NEXT_HYPERCALL(arch_5)
+NEXT_HYPERCALL(arch_6)
+	.balign PAGE_SIZE
 .popsection
 
 	ELFNOTE(Xen, XEN_ELFNOTE_GUEST_OS,       .asciz "linux")
diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h
index 202d4c1..bb5a810 100644
--- a/arch/x86/xen/xen-ops.h
+++ b/arch/x86/xen/xen-ops.h
@@ -27,7 +27,7 @@ void xen_setup_mfn_list_list(void);
 void xen_setup_shared_info(void);
 void xen_build_mfn_list_list(void);
 void xen_setup_machphys_mapping(void);
-pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn);
+void xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn);
 void xen_reserve_top(void);
 extern unsigned long xen_max_p2m_pfn;
 
@@ -45,6 +45,7 @@ void xen_hvm_init_shared_info(void);
 void xen_unplug_emulated_devices(void);
 
 void __init xen_build_dynamic_phys_to_machine(void);
+unsigned long __init xen_revector_p2m_tree(void);
 
 void xen_init_irq_ops(void);
 void xen_setup_timer(int cpu);
diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig
index 8ed64cf..9cb878c 100644
--- a/arch/xtensa/Kconfig
+++ b/arch/xtensa/Kconfig
@@ -11,6 +11,9 @@ config XTENSA
 	select HAVE_GENERIC_HARDIRQS
 	select GENERIC_IRQ_SHOW
 	select GENERIC_CPU_DEVICES
+	select MODULES_USE_ELF_RELA
+	select GENERIC_PCI_IOMAP
+	select ARCH_WANT_OPTIONAL_GPIOLIB
 	help
 	  Xtensa processors are 32-bit RISC machines designed by Tensilica
 	  primarily for embedded systems.  These processors are both
@@ -35,7 +38,7 @@ config ARCH_HAS_ILOG2_U64
 	def_bool n
 
 config NO_IOPORT
-	def_bool y
+	def_bool n
 
 config HZ
 	int
@@ -142,6 +145,7 @@ config XTENSA_PLATFORM_XT2000
 config XTENSA_PLATFORM_S6105
 	bool "S6105"
 	select SERIAL_CONSOLE
+	select NO_IOPORT
 
 endchoice
 
@@ -172,24 +176,6 @@ config CMDLINE
 
 source "mm/Kconfig"
 
-config HOTPLUG
-	bool "Support for hot-pluggable devices"
-	help
-	  Say Y here if you want to plug devices into your computer while
-	  the system is running, and be able to use them quickly.  In many
-	  cases, the devices can likewise be unplugged at any time too.
-
-	  One well known example of this is PCMCIA- or PC-cards, credit-card
-	  size devices such as network cards, modems or hard drives which are
-	  plugged into slots found on all modern laptop computers.  Another
-	  example, used on modern desktops as well as laptops, is USB.
-
-	  Enable HOTPLUG and build a modular kernel.  Get agent software
-	  (from <http://linux-hotplug.sourceforge.net/>) and install it.
-	  Then your kernel will automatically call out to a user mode "policy
-	  agent" (/sbin/hotplug) to load modules and set up software needed
-	  to use devices as you hotplug them.
-
 source "drivers/pcmcia/Kconfig"
 
 source "drivers/pci/hotplug/Kconfig"
diff --git a/arch/xtensa/Makefile b/arch/xtensa/Makefile
index f973754..b201d44 100644
--- a/arch/xtensa/Makefile
+++ b/arch/xtensa/Makefile
@@ -31,7 +31,7 @@ PLATFORM = $(platform-y)
 export PLATFORM
 
 # temporarily until string.h is fixed
-KBUILD_CFLAGS += -ffreestanding
+KBUILD_CFLAGS += -ffreestanding -D__linux__
 
 KBUILD_CFLAGS += -pipe -mlongcalls
 
diff --git a/arch/xtensa/boot/boot-elf/Makefile b/arch/xtensa/boot/boot-elf/Makefile
index 08e8814..4bbc26f 100644
--- a/arch/xtensa/boot/boot-elf/Makefile
+++ b/arch/xtensa/boot/boot-elf/Makefile
@@ -20,9 +20,11 @@ boot-y		:= bootstrap.o
 
 OBJS		:= $(addprefix $(obj)/,$(boot-y))
 
-Image:	vmlinux $(OBJS) arch/$(ARCH)/boot/boot-elf/boot.lds
+vmlinux.tmp: vmlinux
 	$(OBJCOPY) --strip-all -R .comment -R .note.gnu.build-id -O binary \
-		vmlinux vmlinux.tmp
+		$^ $@
+
+Image:	vmlinux.tmp $(OBJS) arch/$(ARCH)/boot/boot-elf/boot.lds
 	$(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \
 		--add-section image=vmlinux.tmp \
 		--set-section-flags image=contents,alloc,load,load,data \
@@ -30,7 +32,6 @@ Image:	vmlinux $(OBJS) arch/$(ARCH)/boot/boot-elf/boot.lds
 	$(LD) $(LDFLAGS) $(LDFLAGS_vmlinux) \
 		-T arch/$(ARCH)/boot/boot-elf/boot.lds \
 		-o arch/$(ARCH)/boot/$@.elf $@.tmp
-	rm -f $@.tmp vmlinux.tmp
 
 Image.initrd:	vmlinux $(OBJS)
 	$(OBJCOPY) --strip-all -R .comment -R .note.gnu.build-id -O binary \
@@ -44,7 +45,7 @@ Image.initrd:	vmlinux $(OBJS)
 	$(LD) $(LDFLAGS) $(LDFLAGS_vmlinux) \
 		-T $(srctree)/arch/$(ARCH)/boot/boot-elf/boot.ld \
 		-o arch/$(ARCH)/boot/$@.elf $@.tmp
-	rm -f $@.tmp vmlinux.tmp
+#rm -f $@.tmp vmlinux.tmp
 
 
 zImage:	Image
diff --git a/arch/xtensa/boot/boot-redboot/Makefile b/arch/xtensa/boot/boot-redboot/Makefile
index 872029b..25a78c6 100644
--- a/arch/xtensa/boot/boot-redboot/Makefile
+++ b/arch/xtensa/boot/boot-redboot/Makefile
@@ -21,15 +21,17 @@ LIBS	:= arch/xtensa/boot/lib/lib.a arch/xtensa/lib/lib.a
 
 LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name)
 
-zImage: vmlinux $(OBJS) $(LIBS)
+vmlinux.tmp: vmlinux
 	$(OBJCOPY) --strip-all -R .comment -R .note.gnu.build-id -O binary \
-		vmlinux vmlinux.tmp
-	gzip -vf9 vmlinux.tmp
+		$^ $@
+
+vmlinux.tmp.gz: vmlinux.tmp
+	$(GZIP) $(GZIP_FLAGS) $^ > $@
+
+zImage: vmlinux.tmp.gz $(OBJS) $(LIBS)
 	$(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \
 		--add-section image=vmlinux.tmp.gz \
 		--set-section-flags image=contents,alloc,load,load,data \
 		$(OBJS) $@.tmp
 	$(LD) $(LD_ARGS) -o $@.elf $@.tmp $(LIBS) -L/xtensa-elf/lib $(LIBGCC)
 	$(OBJCOPY) -S -O binary $@.elf arch/$(ARCH)/boot/$@.redboot
-	rm -f $@.tmp $@.elf vmlinux.tmp.gz
-
diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild
index c68e168..7083403 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -1 +1,3 @@
 include include/asm-generic/Kbuild.asm
+
+generic-y += exec.h
diff --git a/arch/xtensa/include/asm/elf.h b/arch/xtensa/include/asm/elf.h
index 6e65ead..5293312 100644
--- a/arch/xtensa/include/asm/elf.h
+++ b/arch/xtensa/include/asm/elf.h
@@ -189,7 +189,8 @@ typedef struct {
 #endif
 } elf_xtregs_t;
 
-#define SET_PERSONALITY(ex) set_personality(PER_LINUX_32BIT)
+#define SET_PERSONALITY(ex) \
+	set_personality(PER_LINUX_32BIT | (current->personality & (~PER_MASK)))
 
 struct task_struct;
 
diff --git a/arch/xtensa/include/asm/exec.h b/arch/xtensa/include/asm/exec.h
deleted file mode 100644
index af949e2..0000000
--- a/arch/xtensa/include/asm/exec.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2001 - 2005 Tensilica Inc.
- */
-
-#ifndef _XTENSA_EXEC_H
-#define _XTENSA_EXEC_H
-
-#define arch_align_stack(x) (x)
-
-#endif /* _XTENSA_EXEC_H */
diff --git a/arch/xtensa/include/asm/io.h b/arch/xtensa/include/asm/io.h
index 4beb43c..e6be5b9 100644
--- a/arch/xtensa/include/asm/io.h
+++ b/arch/xtensa/include/asm/io.h
@@ -25,184 +25,54 @@
 #define XCHAL_KIO_SIZE		0x10000000
 
 #define IOADDR(x)		(XCHAL_KIO_BYPASS_VADDR + (x))
+#define IO_SPACE_LIMIT ~0
 
+#ifdef CONFIG_MMU
 /*
- * swap functions to change byte order from little-endian to big-endian and
- * vice versa.
- */
-
-static inline unsigned short _swapw (unsigned short v)
-{
-	return (v << 8) | (v >> 8);
-}
-
-static inline unsigned int _swapl (unsigned int v)
-{
-	return (v << 24) | ((v & 0xff00) << 8) | ((v >> 8) & 0xff00) | (v >> 24);
-}
-
-/*
- * Change virtual addresses to physical addresses and vv.
- * These are trivial on the 1:1 Linux/Xtensa mapping
- */
-
-static inline unsigned long virt_to_phys(volatile void * address)
-{
-	return __pa(address);
-}
-
-static inline void * phys_to_virt(unsigned long address)
-{
-	return __va(address);
-}
-
-/*
- * virt_to_bus and bus_to_virt are deprecated.
- */
-
-#define virt_to_bus(x)	virt_to_phys(x)
-#define bus_to_virt(x)	phys_to_virt(x)
-
-/*
- * Return the virtual (cached) address for the specified bus memory.
+ * Return the virtual address for the specified bus memory.
  * Note that we currently don't support any address outside the KIO segment.
  */
-
-static inline void *ioremap(unsigned long offset, unsigned long size)
+static inline void __iomem *ioremap_nocache(unsigned long offset,
+		unsigned long size)
 {
-#ifdef CONFIG_MMU
 	if (offset >= XCHAL_KIO_PADDR
-	    && offset < XCHAL_KIO_PADDR + XCHAL_KIO_SIZE)
+	    && offset - XCHAL_KIO_PADDR < XCHAL_KIO_SIZE)
 		return (void*)(offset-XCHAL_KIO_PADDR+XCHAL_KIO_BYPASS_VADDR);
 	else
 		BUG();
-#else
-	return (void *)offset;
-#endif
 }
 
-static inline void *ioremap_nocache(unsigned long offset, unsigned long size)
+static inline void __iomem *ioremap_cache(unsigned long offset,
+		unsigned long size)
 {
-#ifdef CONFIG_MMU
 	if (offset >= XCHAL_KIO_PADDR
-	    && offset < XCHAL_KIO_PADDR + XCHAL_KIO_SIZE)
+	    && offset - XCHAL_KIO_PADDR < XCHAL_KIO_SIZE)
 		return (void*)(offset-XCHAL_KIO_PADDR+XCHAL_KIO_CACHED_VADDR);
 	else
 		BUG();
-#else
-	return (void *)offset;
-#endif
-}
-
-static inline void iounmap(void *addr)
-{
 }
 
-/*
- * Generic I/O
- */
-
-#define readb(addr) \
-	({ unsigned char __v = (*(volatile unsigned char *)(addr)); __v; })
-#define readw(addr) \
-	({ unsigned short __v = (*(volatile unsigned short *)(addr)); __v; })
-#define readl(addr) \
-	({ unsigned int __v = (*(volatile unsigned int *)(addr)); __v; })
-#define writeb(b, addr) (void)((*(volatile unsigned char *)(addr)) = (b))
-#define writew(b, addr) (void)((*(volatile unsigned short *)(addr)) = (b))
-#define writel(b, addr) (void)((*(volatile unsigned int *)(addr)) = (b))
+#define ioremap_wc ioremap_nocache
 
-static inline __u8 __raw_readb(const volatile void __iomem *addr)
-{
-          return *(__force volatile __u8 *)(addr);
-}
-static inline __u16 __raw_readw(const volatile void __iomem *addr)
-{
-          return *(__force volatile __u16 *)(addr);
-}
-static inline __u32 __raw_readl(const volatile void __iomem *addr)
+static inline void __iomem *ioremap(unsigned long offset, unsigned long size)
 {
-          return *(__force volatile __u32 *)(addr);
+	return ioremap_nocache(offset, size);
 }
-static inline void __raw_writeb(__u8 b, volatile void __iomem *addr)
-{
-          *(__force volatile __u8 *)(addr) = b;
-}
-static inline void __raw_writew(__u16 b, volatile void __iomem *addr)
-{
-          *(__force volatile __u16 *)(addr) = b;
-}
-static inline void __raw_writel(__u32 b, volatile void __iomem *addr)
+
+static inline void iounmap(volatile void __iomem *addr)
 {
-          *(__force volatile __u32 *)(addr) = b;
 }
-
-/* These are the definitions for the x86 IO instructions
- * inb/inw/inl/outb/outw/outl, the "string" versions
- * insb/insw/insl/outsb/outsw/outsl, and the "pausing" versions
- * inb_p/inw_p/...
- * The macros don't do byte-swapping.
- */
-
-#define inb(port)		readb((u8 *)((port)))
-#define outb(val, port)		writeb((val),(u8 *)((unsigned long)(port)))
-#define inw(port)		readw((u16 *)((port)))
-#define outw(val, port)		writew((val),(u16 *)((unsigned long)(port)))
-#define inl(port)		readl((u32 *)((port)))
-#define outl(val, port)		writel((val),(u32 *)((unsigned long)(port)))
-
-#define inb_p(port)		inb((port))
-#define outb_p(val, port)	outb((val), (port))
-#define inw_p(port)		inw((port))
-#define outw_p(val, port)	outw((val), (port))
-#define inl_p(port)		inl((port))
-#define outl_p(val, port)	outl((val), (port))
-
-extern void insb (unsigned long port, void *dst, unsigned long count);
-extern void insw (unsigned long port, void *dst, unsigned long count);
-extern void insl (unsigned long port, void *dst, unsigned long count);
-extern void outsb (unsigned long port, const void *src, unsigned long count);
-extern void outsw (unsigned long port, const void *src, unsigned long count);
-extern void outsl (unsigned long port, const void *src, unsigned long count);
-
-#define IO_SPACE_LIMIT ~0
-
-#define memset_io(a,b,c)       memset((void *)(a),(b),(c))
-#define memcpy_fromio(a,b,c)   memcpy((a),(void *)(b),(c))
-#define memcpy_toio(a,b,c)      memcpy((void *)(a),(b),(c))
-
-/* At this point the Xtensa doesn't provide byte swap instructions */
-
-#ifdef __XTENSA_EB__
-# define in_8(addr) (*(u8*)(addr))
-# define in_le16(addr) _swapw(*(u16*)(addr))
-# define in_le32(addr) _swapl(*(u32*)(addr))
-# define out_8(b, addr) *(u8*)(addr) = (b)
-# define out_le16(b, addr) *(u16*)(addr) = _swapw(b)
-# define out_le32(b, addr) *(u32*)(addr) = _swapl(b)
-#elif defined(__XTENSA_EL__)
-# define in_8(addr)  (*(u8*)(addr))
-# define in_le16(addr) (*(u16*)(addr))
-# define in_le32(addr) (*(u32*)(addr))
-# define out_8(b, addr) *(u8*)(addr) = (b)
-# define out_le16(b, addr) *(u16*)(addr) = (b)
-# define out_le32(b, addr) *(u32*)(addr) = (b)
-#else
-# error processor byte order undefined!
-#endif
-
-
-/*
- * Convert a physical pointer to a virtual kernel pointer for /dev/mem access
- */
-#define xlate_dev_mem_ptr(p)    __va(p)
+#endif /* CONFIG_MMU */
 
 /*
- * Convert a virtual cached pointer to an uncached pointer
+ * Generic I/O
  */
-#define xlate_dev_kmem_ptr(p)   p
-
+#define readb_relaxed readb
+#define readw_relaxed readw
+#define readl_relaxed readl
 
 #endif	/* __KERNEL__ */
 
+#include <asm-generic/io.h>
+
 #endif	/* _XTENSA_IO_H */
diff --git a/arch/xtensa/include/asm/module.h b/arch/xtensa/include/asm/module.h
index d9b34be..488b40c 100644
--- a/arch/xtensa/include/asm/module.h
+++ b/arch/xtensa/include/asm/module.h
@@ -13,15 +13,8 @@
 #ifndef _XTENSA_MODULE_H
 #define _XTENSA_MODULE_H
 
-struct mod_arch_specific
-{
-	/* No special elements, yet. */
-};
-
 #define MODULE_ARCH_VERMAGIC "xtensa-" __stringify(XCHAL_CORE_ID) " "
 
-#define Elf_Shdr Elf32_Shdr
-#define Elf_Sym Elf32_Sym
-#define Elf_Ehdr Elf32_Ehdr
+#include <asm-generic/module.h>
 
 #endif	/* _XTENSA_MODULE_H */
diff --git a/arch/xtensa/include/asm/regs.h b/arch/xtensa/include/asm/regs.h
index d4baed2..a3075b1 100644
--- a/arch/xtensa/include/asm/regs.h
+++ b/arch/xtensa/include/asm/regs.h
@@ -66,7 +66,7 @@
 #define ICOUNTLEVEL	237
 #define EXCVADDR	238
 #define CCOMPARE	240
-#define MISC		244
+#define MISC_SR		244
 
 /*  Special names for read-only and write-only interrupt registers.  */
 
diff --git a/arch/xtensa/include/asm/thread_info.h b/arch/xtensa/include/asm/thread_info.h
index 81abfd5..9481004 100644
--- a/arch/xtensa/include/asm/thread_info.h
+++ b/arch/xtensa/include/asm/thread_info.h
@@ -128,19 +128,14 @@ static inline struct thread_info *current_thread_info(void)
 #define TIF_SIGPENDING		1	/* signal pending */
 #define TIF_NEED_RESCHED	2	/* rescheduling necessary */
 #define TIF_SINGLESTEP		3	/* restore singlestep on return to user mode */
-#define TIF_IRET		4	/* return with iret */
 #define TIF_MEMDIE		5	/* is terminating due to OOM killer */
 #define TIF_RESTORE_SIGMASK	6	/* restore signal mask in do_signal() */
 #define TIF_NOTIFY_RESUME	7	/* callback before returning to user */
-#define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
 #define _TIF_SINGLESTEP		(1<<TIF_SINGLESTEP)
-#define _TIF_IRET		(1<<TIF_IRET)
-#define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
-#define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
 
 #define _TIF_WORK_MASK		0x0000FFFE	/* work to do on interrupt/exception return */
 #define _TIF_ALLWORK_MASK	0x0000FFFF	/* work to do on any return to u-space */
diff --git a/arch/xtensa/kernel/Makefile b/arch/xtensa/kernel/Makefile
index 59fc3fe..f36cef5 100644
--- a/arch/xtensa/kernel/Makefile
+++ b/arch/xtensa/kernel/Makefile
@@ -6,7 +6,7 @@ extra-y := head.o vmlinux.lds
 
 obj-y := align.o entry.o irq.o coprocessor.o process.o ptrace.o \
 	 setup.o signal.o syscall.o time.o traps.o vectors.o platform.o  \
-	 pci-dma.o io.o
+	 pci-dma.o
 
 obj-$(CONFIG_KGDB) += xtensa-stub.o
 obj-$(CONFIG_PCI) += pci.o
@@ -24,6 +24,7 @@ obj-$(CONFIG_MODULES) += xtensa_ksyms.o module.o
 # Replicate rules in scripts/Makefile.build
 
 sed-y = -e 's/\*(\(\.[a-z]*it\|\.ref\|\)\.text)/*(\1.literal \1.text)/g'    \
+	-e 's/\.text\.unlikely/.literal.unlikely .text.unlikely/g' \
 	-e 's/\*(\(\.text\.[a-z]*\))/*(\1.literal \1)/g'
 
 quiet_cmd__cpp_lds_S = LDS     $@
diff --git a/arch/xtensa/kernel/io.c b/arch/xtensa/kernel/io.c
deleted file mode 100644
index 5b65269..0000000
--- a/arch/xtensa/kernel/io.c
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * arch/xtensa/io.c
- *
- * IO primitives
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- *
- * Copied from sparc.
- *
- * Chris Zankel <chris@zankel.net>
- *
- */
-
-#include <asm/io.h>
-#include <asm/byteorder.h>
-
-void outsb(unsigned long addr, const void *src, unsigned long count) {
-        while (count) {
-                count -= 1;
-                writeb(*(const char *)src, addr);
-                src += 1;
-                addr += 1;
-        }
-}
-
-void outsw(unsigned long addr, const void *src, unsigned long count) {
-        while (count) {
-                count -= 2;
-                writew(*(const short *)src, addr);
-                src += 2;
-                addr += 2;
-        }
-}
-
-void outsl(unsigned long addr, const void *src, unsigned long count) {
-        while (count) {
-                count -= 4;
-                writel(*(const long *)src, addr);
-                src += 4;
-                addr += 4;
-        }
-}
-
-void insb(unsigned long addr, void *dst, unsigned long count) {
-        while (count) {
-                count -= 1;
-                *(unsigned char *)dst = readb(addr);
-                dst += 1;
-                addr += 1;
-        }
-}
-
-void insw(unsigned long addr, void *dst, unsigned long count) {
-        while (count) {
-                count -= 2;
-                *(unsigned short *)dst = readw(addr);
-                dst += 2;
-                addr += 2;
-        }
-}
-
-void insl(unsigned long addr, void *dst, unsigned long count) {
-        while (count) {
-                count -= 4;
-                /*
-                 * XXX I am sure we are in for an unaligned trap here.
-                 */
-                *(unsigned long *)dst = readl(addr);
-                dst += 4;
-                addr += 4;
-        }
-}
diff --git a/arch/xtensa/kernel/irq.c b/arch/xtensa/kernel/irq.c
index 4340ee0..98e77c3 100644
--- a/arch/xtensa/kernel/irq.c
+++ b/arch/xtensa/kernel/irq.c
@@ -84,12 +84,12 @@ static void xtensa_irq_unmask(struct irq_data *d)
 static void xtensa_irq_enable(struct irq_data *d)
 {
 	variant_irq_enable(d->irq);
-	xtensa_irq_unmask(d->irq);
+	xtensa_irq_unmask(d);
 }
 
 static void xtensa_irq_disable(struct irq_data *d)
 {
-	xtensa_irq_mask(d->irq);
+	xtensa_irq_mask(d);
 	variant_irq_disable(d->irq);
 }
 
diff --git a/arch/xtensa/kernel/pci-dma.c b/arch/xtensa/kernel/pci-dma.c
index 2783fda..2d9cc6d 100644
--- a/arch/xtensa/kernel/pci-dma.c
+++ b/arch/xtensa/kernel/pci-dma.c
@@ -21,6 +21,7 @@
 #include <linux/string.h>
 #include <linux/pci.h>
 #include <linux/gfp.h>
+#include <linux/module.h>
 #include <asm/io.h>
 #include <asm/cacheflush.h>
 
@@ -62,6 +63,7 @@ dma_alloc_coherent(struct device *dev,size_t size,dma_addr_t *handle,gfp_t flag)
 
 	return (void*)uncached;
 }
+EXPORT_SYMBOL(dma_alloc_coherent);
 
 void dma_free_coherent(struct device *hwdev, size_t size,
 			 void *vaddr, dma_addr_t dma_handle)
@@ -73,6 +75,7 @@ void dma_free_coherent(struct device *hwdev, size_t size,
 
 	free_pages(addr, get_order(size));
 }
+EXPORT_SYMBOL(dma_free_coherent);
 
 
 void consistent_sync(void *vaddr, size_t size, int direction)
@@ -92,3 +95,4 @@ void consistent_sync(void *vaddr, size_t size, int direction)
 		break;
 	}
 }
+EXPORT_SYMBOL(consistent_sync);
diff --git a/arch/xtensa/kernel/pci.c b/arch/xtensa/kernel/pci.c
index 69759e9..126c188 100644
--- a/arch/xtensa/kernel/pci.c
+++ b/arch/xtensa/kernel/pci.c
@@ -210,14 +210,6 @@ void pcibios_set_master(struct pci_dev *dev)
 	/* No special bus mastering setup handling */
 }
 
-/* the next one is stolen from the alpha port... */
-
-void __init
-pcibios_update_irq(struct pci_dev *dev, int irq)
-{
-	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
-}
-
 int pcibios_enable_device(struct pci_dev *dev, int mask)
 {
 	u16 cmd, old_cmd;
@@ -341,7 +333,7 @@ __pci_mmap_set_pgprot(struct pci_dev *dev, struct vm_area_struct *vma,
 	int prot = pgprot_val(vma->vm_page_prot);
 
 	/* Set to write-through */
-	prot &= ~_PAGE_NO_CACHE;
+	prot = (prot & _PAGE_CA_MASK) | _PAGE_CA_WT;
 #if 0
 	if (!write_combine)
 		prot |= _PAGE_WRITETHRU;
diff --git a/arch/xtensa/kernel/platform.c b/arch/xtensa/kernel/platform.c
index 1b91a97..97230e4 100644
--- a/arch/xtensa/kernel/platform.c
+++ b/arch/xtensa/kernel/platform.c
@@ -40,8 +40,8 @@ _F(int,  pcibios_fixup, (void), { return 0; });
 #ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT
 _F(void, calibrate_ccount, (void),
 {
-  printk ("ERROR: Cannot calibrate cpu frequency! Assuming 100MHz.\n");
-  ccount_per_jiffy = 100 * (1000000UL/HZ);
+	pr_err("ERROR: Cannot calibrate cpu frequency! Assuming 10MHz.\n");
+	ccount_per_jiffy = 10 * (1000000UL/HZ);
 });
 #endif
 
diff --git a/arch/xtensa/kernel/process.c b/arch/xtensa/kernel/process.c
index 2c8d6a3..bc44311 100644
--- a/arch/xtensa/kernel/process.c
+++ b/arch/xtensa/kernel/process.c
@@ -31,6 +31,7 @@
 #include <linux/mqueue.h>
 #include <linux/fs.h>
 #include <linux/slab.h>
+#include <linux/rcupdate.h>
 
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
@@ -110,8 +111,10 @@ void cpu_idle(void)
 
 	/* endless idle loop with no priority at all */
 	while (1) {
+		rcu_idle_enter();
 		while (!need_resched())
 			platform_idle();
+		rcu_idle_exit();
 		schedule_preempt_disabled();
 	}
 }
diff --git a/arch/xtensa/kernel/signal.c b/arch/xtensa/kernel/signal.c
index efe4e85..63c566f 100644
--- a/arch/xtensa/kernel/signal.c
+++ b/arch/xtensa/kernel/signal.c
@@ -19,7 +19,6 @@
 #include <linux/errno.h>
 #include <linux/ptrace.h>
 #include <linux/personality.h>
-#include <linux/freezer.h>
 #include <linux/tracehook.h>
 
 #include <asm/ucontext.h>
@@ -527,9 +526,6 @@ static void do_signal(struct pt_regs *regs)
 
 void do_notify_resume(struct pt_regs *regs)
 {
-	if (!user_mode(regs))
-		return;
-
 	if (test_thread_flag(TIF_SIGPENDING))
 		do_signal(regs);
 
diff --git a/arch/xtensa/kernel/xtensa_ksyms.c b/arch/xtensa/kernel/xtensa_ksyms.c
index c9a7c5b..88fe2f2 100644
--- a/arch/xtensa/kernel/xtensa_ksyms.c
+++ b/arch/xtensa/kernel/xtensa_ksyms.c
@@ -39,8 +39,12 @@
 EXPORT_SYMBOL(memset);
 EXPORT_SYMBOL(memcpy);
 EXPORT_SYMBOL(memmove);
+EXPORT_SYMBOL(__strncpy_user);
+EXPORT_SYMBOL(clear_page);
+EXPORT_SYMBOL(copy_page);
 
 EXPORT_SYMBOL(kernel_thread);
+EXPORT_SYMBOL(empty_zero_page);
 
 /*
  * gcc internal math functions
@@ -56,6 +60,7 @@ extern unsigned int __udivsi3(unsigned int, unsigned int);
 extern unsigned int __umodsi3(unsigned int, unsigned int);
 extern unsigned long long __umoddi3(unsigned long long, unsigned long long);
 extern unsigned long long __udivdi3(unsigned long long, unsigned long long);
+extern int __ucmpdi2(int, int);
 
 EXPORT_SYMBOL(__ashldi3);
 EXPORT_SYMBOL(__ashrdi3);
@@ -68,11 +73,14 @@ EXPORT_SYMBOL(__udivsi3);
 EXPORT_SYMBOL(__umodsi3);
 EXPORT_SYMBOL(__udivdi3);
 EXPORT_SYMBOL(__umoddi3);
+EXPORT_SYMBOL(__ucmpdi2);
+EXPORT_SYMBOL(__xtensa_libgcc_window_spill);
 
 #ifdef CONFIG_NET
 /*
  * Networking support
  */
+EXPORT_SYMBOL(csum_partial);
 EXPORT_SYMBOL(csum_partial_copy_generic);
 #endif /* CONFIG_NET */
 
diff --git a/arch/xtensa/mm/fault.c b/arch/xtensa/mm/fault.c
index 5a74c53..2c2f710 100644
--- a/arch/xtensa/mm/fault.c
+++ b/arch/xtensa/mm/fault.c
@@ -126,6 +126,7 @@ good_area:
 			current->min_flt++;
 		if (fault & VM_FAULT_RETRY) {
 			flags &= ~FAULT_FLAG_ALLOW_RETRY;
+			flags |= FAULT_FLAG_TRIED;
 
 			 /* No need to up_read(&mm->mmap_sem) as we would
 			 * have already released it in __lock_page_or_retry
diff --git a/arch/xtensa/platforms/iss/Makefile b/arch/xtensa/platforms/iss/Makefile
index af96e31..b7d1a5c 100644
--- a/arch/xtensa/platforms/iss/Makefile
+++ b/arch/xtensa/platforms/iss/Makefile
@@ -4,5 +4,5 @@
 # "prom monitor" library routines under Linux.
 #
 
-obj-y			= io.o console.o setup.o network.o
-
+obj-y			= console.o setup.o
+obj-$(CONFIG_NET)	+= network.o
diff --git a/arch/xtensa/platforms/iss/console.c b/arch/xtensa/platforms/iss/console.c
index f9726f6..8ab47ed 100644
--- a/arch/xtensa/platforms/iss/console.c
+++ b/arch/xtensa/platforms/iss/console.c
@@ -33,7 +33,7 @@
 #endif
 
 #define SERIAL_MAX_NUM_LINES 1
-#define SERIAL_TIMER_VALUE (20 * HZ)
+#define SERIAL_TIMER_VALUE (HZ / 10)
 
 static struct tty_driver *serial_driver;
 static struct tty_port serial_port;
@@ -41,19 +41,6 @@ static struct timer_list serial_timer;
 
 static DEFINE_SPINLOCK(timer_lock);
 
-int errno;
-
-static int __simc (int a, int b, int c, int d, int e, int f) __attribute__((__noinline__));
-static int __simc (int a, int b, int c, int d, int e, int f)
-{
-	int ret;
-	__asm__ __volatile__ ("simcall\n"
-			"mov %0, a2\n"
-			"mov %1, a3\n" : "=a" (ret), "=a" (errno)
-			: : "a2", "a3");
-	return ret;
-}
-
 static char *serial_version = "0.1";
 static char *serial_name = "ISS serial driver";
 
@@ -223,6 +210,7 @@ int __init rs_init(void)
 	serial_driver->flags = TTY_DRIVER_REAL_RAW;
 
 	tty_set_operations(serial_driver, &serial_ops);
+	tty_port_link_device(&serial_port, serial_driver, 0);
 
 	if (tty_register_driver(serial_driver))
 		panic("Couldn't register serial driver\n");
diff --git a/arch/xtensa/platforms/iss/include/platform/serial.h b/arch/xtensa/platforms/iss/include/platform/serial.h
new file mode 100644
index 0000000..e69de29
diff --git a/arch/xtensa/platforms/iss/include/platform/simcall.h b/arch/xtensa/platforms/iss/include/platform/simcall.h
index b7952c0..8c43bfea 100644
--- a/arch/xtensa/platforms/iss/include/platform/simcall.h
+++ b/arch/xtensa/platforms/iss/include/platform/simcall.h
@@ -57,6 +57,59 @@
 #define  XTISS_SELECT_ONE_WRITE   2
 #define  XTISS_SELECT_ONE_EXCEPT  3
 
+static int errno;
+
+static inline int __simc(int a, int b, int c, int d, int e, int f)
+{
+	int ret;
+	register int a1 asm("a2") = a;
+	register int b1 asm("a3") = b;
+	register int c1 asm("a4") = c;
+	register int d1 asm("a5") = d;
+	register int e1 asm("a6") = e;
+	register int f1 asm("a7") = f;
+	__asm__ __volatile__ (
+			"simcall\n"
+			"mov %0, a2\n"
+			"mov %1, a3\n"
+			: "=a" (ret), "=a" (errno), "+r"(a1), "+r"(b1)
+			: "r"(c1), "r"(d1), "r"(e1), "r"(f1)
+			: );
+	return ret;
+}
+
+static inline int simc_open(char *file, int flags, int mode)
+{
+	return __simc(SYS_open, (int) file, flags, mode, 0, 0);
+}
+
+static inline int simc_close(int fd)
+{
+	return __simc(SYS_close, fd, 0, 0, 0, 0);
+}
+
+static inline int simc_ioctl(int fd, int request, void *arg)
+{
+	return __simc(SYS_ioctl, fd, request, (int) arg, 0, 0);
+}
+
+static inline int simc_read(int fd, void *buf, size_t count)
+{
+	return __simc(SYS_read, fd, (int) buf, count, 0, 0);
+}
+
+static inline int simc_write(int fd, void *buf, size_t count)
+{
+	return __simc(SYS_write, fd, (int) buf, count, 0, 0);
+}
+
+static inline int simc_poll(int fd)
+{
+	struct timeval tv = { .tv_sec = 0, .tv_usec = 0 };
+
+	return __simc(SYS_select_one, fd, XTISS_SELECT_ONE_READ, (int)&tv,
+			0, 0);
+}
 
 #endif /* _XTENSA_PLATFORM_ISS_SIMCALL_H */
 
diff --git a/arch/xtensa/platforms/iss/io.c b/arch/xtensa/platforms/iss/io.c
deleted file mode 100644
index 571d0b2..0000000
--- a/arch/xtensa/platforms/iss/io.c
+++ /dev/null
@@ -1,32 +0,0 @@
-/* This file isn't really needed right now. */
-
-#if 0
-
-#include <asm/io.h>
-#include <platform/platform-iss/simcall.h>
-
-extern int __simc ();
-
-
-char iss_serial_getc()
-{
-  char c;
-  __simc( SYS_read, 0, &c, 1 );
-  return c;
-}
-
-void iss_serial_putc( char c )
-{
-  __simc( SYS_write, 1, &c, 1 );
-}
-
-void iss_serial_puts( char *s )
-{
-  if( s != 0 && *s != 0 )
-    __simc( SYS_write, 1, s, strlen(s) );
-}
-
-/*#error Need I/O ports to specific hardware!*/
-
-#endif
-
diff --git a/arch/xtensa/platforms/iss/network.c b/arch/xtensa/platforms/iss/network.c
index 7dde244..7d0fea6 100644
--- a/arch/xtensa/platforms/iss/network.c
+++ b/arch/xtensa/platforms/iss/network.c
@@ -101,55 +101,6 @@ struct iss_net_private {
 
 };
 
-/* ======================= ISS SIMCALL INTERFACE =========================== */
-
-/* Note: __simc must _not_ be declared inline! */
-
-static int errno;
-
-static int __simc (int a, int b, int c, int d, int e, int f) __attribute__((__noinline__));
-static int __simc (int a, int b, int c, int d, int e, int f)
-{
-	int ret;
-	__asm__ __volatile__ ("simcall\n"
-	    		      "mov %0, a2\n"
-			      "mov %1, a3\n" : "=a" (ret), "=a" (errno)
-			      : : "a2", "a3");
-	return ret;
-}
-
-static int inline simc_open(char *file, int flags, int mode)
-{
-	return __simc(SYS_open, (int) file, flags, mode, 0, 0);
-}
-
-static int inline simc_close(int fd)
-{
-	return __simc(SYS_close, fd, 0, 0, 0, 0);
-}
-
-static int inline simc_ioctl(int fd, int request, void *arg)
-{
-	return __simc(SYS_ioctl, fd, request, (int) arg, 0, 0);
-}
-
-static int inline simc_read(int fd, void *buf, size_t count)
-{
-	return __simc(SYS_read, fd, (int) buf, count, 0, 0);
-}
-
-static int inline simc_write(int fd, void *buf, size_t count)
-{
-	return __simc(SYS_write, fd, (int) buf, count, 0, 0);
-}
-
-static int inline simc_poll(int fd)
-{
-	struct timeval tv = { .tv_sec = 0, .tv_usec = 0 };
-
-	return __simc(SYS_select_one, fd, XTISS_SELECT_ONE_READ, (int)&tv,0,0);
-}
-
 /* ================================ HELPERS ================================ */
 
 
diff --git a/arch/xtensa/platforms/iss/setup.c b/arch/xtensa/platforms/iss/setup.c
index f60c8cf..927acf3 100644
--- a/arch/xtensa/platforms/iss/setup.c
+++ b/arch/xtensa/platforms/iss/setup.c
@@ -38,16 +38,22 @@ void __init platform_init(bp_tag_t* bootparam)
 
 }
 
+#ifdef CONFIG_PCI
+void platform_pcibios_init(void)
+{
+}
+#endif
+
 void platform_halt(void)
 {
-	printk (" ** Called platform_halt(), looping forever! **\n");
-	while (1);
+	pr_info(" ** Called platform_halt() **\n");
+	__asm__ __volatile__("movi a2, 1\nsimcall\n");
 }
 
 void platform_power_off(void)
 {
-	printk (" ** Called platform_power_off(), looping forever! **\n");
-	while (1);
+	pr_info(" ** Called platform_power_off() **\n");
+	__asm__ __volatile__("movi a2, 1\nsimcall\n");
 }
 void platform_restart(void)
 {
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
index f3b44a6..cafcd74 100644
--- a/block/blk-cgroup.c
+++ b/block/blk-cgroup.c
@@ -737,6 +737,14 @@ struct cgroup_subsys blkio_subsys = {
 	.subsys_id = blkio_subsys_id,
 	.base_cftypes = blkcg_files,
 	.module = THIS_MODULE,
+
+	/*
+	 * blkio subsystem is utterly broken in terms of hierarchy support.
+	 * It treats all cgroups equally regardless of where they're
+	 * located in the hierarchy - all cgroups are treated as if they're
+	 * right below the root.  Fix it and remove the following.
+	 */
+	.broken_hierarchy = true,
 };
 EXPORT_SYMBOL_GPL(blkio_subsys);
 
diff --git a/block/blk-core.c b/block/blk-core.c
index ee3cb3a..b421289 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -40,6 +40,7 @@
 EXPORT_TRACEPOINT_SYMBOL_GPL(block_bio_remap);
 EXPORT_TRACEPOINT_SYMBOL_GPL(block_rq_remap);
 EXPORT_TRACEPOINT_SYMBOL_GPL(block_bio_complete);
+EXPORT_TRACEPOINT_SYMBOL_GPL(block_unplug);
 
 DEFINE_IDA(blk_queue_ida);
 
@@ -262,7 +263,7 @@ EXPORT_SYMBOL(blk_start_queue);
  **/
 void blk_stop_queue(struct request_queue *q)
 {
-	__cancel_delayed_work(&q->delay_work);
+	cancel_delayed_work(&q->delay_work);
 	queue_flag_set(QUEUE_FLAG_STOPPED, q);
 }
 EXPORT_SYMBOL(blk_stop_queue);
@@ -319,10 +320,8 @@ EXPORT_SYMBOL(__blk_run_queue);
  */
 void blk_run_queue_async(struct request_queue *q)
 {
-	if (likely(!blk_queue_stopped(q))) {
-		__cancel_delayed_work(&q->delay_work);
-		queue_delayed_work(kblockd_workqueue, &q->delay_work, 0);
-	}
+	if (likely(!blk_queue_stopped(q)))
+		mod_delayed_work(kblockd_workqueue, &q->delay_work, 0);
 }
 EXPORT_SYMBOL(blk_run_queue_async);
 
@@ -608,8 +607,8 @@ struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id)
 	/*
 	 * A queue starts its life with bypass turned on to avoid
 	 * unnecessary bypass on/off overhead and nasty surprises during
-	 * init.  The initial bypass will be finished at the end of
-	 * blk_init_allocated_queue().
+	 * init.  The initial bypass will be finished when the queue is
+	 * registered by blk_register_queue().
 	 */
 	q->bypass_depth = 1;
 	__set_bit(QUEUE_FLAG_BYPASS, &q->queue_flags);
@@ -696,7 +695,7 @@ blk_init_allocated_queue(struct request_queue *q, request_fn_proc *rfn,
 	q->request_fn		= rfn;
 	q->prep_rq_fn		= NULL;
 	q->unprep_rq_fn		= NULL;
-	q->queue_flags		= QUEUE_FLAG_DEFAULT;
+	q->queue_flags		|= QUEUE_FLAG_DEFAULT;
 
 	/* Override internal queue lock with supplied lock pointer */
 	if (lock)
@@ -712,11 +711,6 @@ blk_init_allocated_queue(struct request_queue *q, request_fn_proc *rfn,
 	/* init elevator */
 	if (elevator_init(q, NULL))
 		return NULL;
-
-	blk_queue_congestion_threshold(q);
-
-	/* all done, end the initial bypass */
-	blk_queue_bypass_end(q);
 	return q;
 }
 EXPORT_SYMBOL(blk_init_allocated_queue);
@@ -1659,8 +1653,8 @@ generic_make_request_checks(struct bio *bio)
 		goto end_io;
 	}
 
-	if (unlikely(!(bio->bi_rw & REQ_DISCARD) &&
-		     nr_sectors > queue_max_hw_sectors(q))) {
+	if (likely(bio_is_rw(bio) &&
+		   nr_sectors > queue_max_hw_sectors(q))) {
 		printk(KERN_ERR "bio too big device %s (%u > %u)\n",
 		       bdevname(bio->bi_bdev, b),
 		       bio_sectors(bio),
@@ -1701,8 +1695,12 @@ generic_make_request_checks(struct bio *bio)
 
 	if ((bio->bi_rw & REQ_DISCARD) &&
 	    (!blk_queue_discard(q) ||
-	     ((bio->bi_rw & REQ_SECURE) &&
-	      !blk_queue_secdiscard(q)))) {
+	     ((bio->bi_rw & REQ_SECURE) && !blk_queue_secdiscard(q)))) {
+		err = -EOPNOTSUPP;
+		goto end_io;
+	}
+
+	if (bio->bi_rw & REQ_WRITE_SAME && !bdev_write_same(bio->bi_bdev)) {
 		err = -EOPNOTSUPP;
 		goto end_io;
 	}
@@ -1812,15 +1810,20 @@ EXPORT_SYMBOL(generic_make_request);
  */
 void submit_bio(int rw, struct bio *bio)
 {
-	int count = bio_sectors(bio);
-
 	bio->bi_rw |= rw;
 
 	/*
 	 * If it's a regular read/write or a barrier with data attached,
 	 * go through the normal accounting stuff before submission.
 	 */
-	if (bio_has_data(bio) && !(rw & REQ_DISCARD)) {
+	if (bio_has_data(bio)) {
+		unsigned int count;
+
+		if (unlikely(rw & REQ_WRITE_SAME))
+			count = bdev_logical_block_size(bio->bi_bdev) >> 9;
+		else
+			count = bio_sectors(bio);
+
 		if (rw & WRITE) {
 			count_vm_events(PGPGOUT, count);
 		} else {
@@ -1866,11 +1869,10 @@ EXPORT_SYMBOL(submit_bio);
  */
 int blk_rq_check_limits(struct request_queue *q, struct request *rq)
 {
-	if (rq->cmd_flags & REQ_DISCARD)
+	if (!rq_mergeable(rq))
 		return 0;
 
-	if (blk_rq_sectors(rq) > queue_max_sectors(q) ||
-	    blk_rq_bytes(rq) > queue_max_hw_sectors(q) << 9) {
+	if (blk_rq_sectors(rq) > blk_queue_get_max_sectors(q, rq->cmd_flags)) {
 		printk(KERN_ERR "%s: over max size limit.\n", __func__);
 		return -EIO;
 	}
@@ -2342,7 +2344,7 @@ bool blk_update_request(struct request *req, int error, unsigned int nr_bytes)
 	req->buffer = bio_data(req->bio);
 
 	/* update sector only for requests with clear definition of sector */
-	if (req->cmd_type == REQ_TYPE_FS || (req->cmd_flags & REQ_DISCARD))
+	if (req->cmd_type == REQ_TYPE_FS)
 		req->__sector += total_bytes >> 9;
 
 	/* mixed attributes always follow the first bio */
@@ -2783,16 +2785,10 @@ int blk_rq_prep_clone(struct request *rq, struct request *rq_src,
 	blk_rq_init(NULL, rq);
 
 	__rq_for_each_bio(bio_src, rq_src) {
-		bio = bio_alloc_bioset(gfp_mask, bio_src->bi_max_vecs, bs);
+		bio = bio_clone_bioset(bio_src, gfp_mask, bs);
 		if (!bio)
 			goto free_and_out;
 
-		__bio_clone(bio, bio_src);
-
-		if (bio_integrity(bio_src) &&
-		    bio_integrity_clone(bio, bio_src, gfp_mask, bs))
-			goto free_and_out;
-
 		if (bio_ctr && bio_ctr(bio, bio_src, data))
 			goto free_and_out;
 
@@ -2809,7 +2805,7 @@ int blk_rq_prep_clone(struct request *rq, struct request *rq_src,
 
 free_and_out:
 	if (bio)
-		bio_free(bio, bs);
+		bio_put(bio);
 	blk_rq_unprep_clone(rq);
 
 	return -ENOMEM;
diff --git a/block/blk-lib.c b/block/blk-lib.c
index 19cc761..9373b58 100644
--- a/block/blk-lib.c
+++ b/block/blk-lib.c
@@ -130,6 +130,80 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector,
 EXPORT_SYMBOL(blkdev_issue_discard);
 
 /**
+ * blkdev_issue_write_same - queue a write same operation
+ * @bdev:	target blockdev
+ * @sector:	start sector
+ * @nr_sects:	number of sectors to write
+ * @gfp_mask:	memory allocation flags (for bio_alloc)
+ * @page:	page containing data to write
+ *
+ * Description:
+ *    Issue a write same request for the sectors in question.
+ */
+int blkdev_issue_write_same(struct block_device *bdev, sector_t sector,
+			    sector_t nr_sects, gfp_t gfp_mask,
+			    struct page *page)
+{
+	DECLARE_COMPLETION_ONSTACK(wait);
+	struct request_queue *q = bdev_get_queue(bdev);
+	unsigned int max_write_same_sectors;
+	struct bio_batch bb;
+	struct bio *bio;
+	int ret = 0;
+
+	if (!q)
+		return -ENXIO;
+
+	max_write_same_sectors = q->limits.max_write_same_sectors;
+
+	if (max_write_same_sectors == 0)
+		return -EOPNOTSUPP;
+
+	atomic_set(&bb.done, 1);
+	bb.flags = 1 << BIO_UPTODATE;
+	bb.wait = &wait;
+
+	while (nr_sects) {
+		bio = bio_alloc(gfp_mask, 1);
+		if (!bio) {
+			ret = -ENOMEM;
+			break;
+		}
+
+		bio->bi_sector = sector;
+		bio->bi_end_io = bio_batch_end_io;
+		bio->bi_bdev = bdev;
+		bio->bi_private = &bb;
+		bio->bi_vcnt = 1;
+		bio->bi_io_vec->bv_page = page;
+		bio->bi_io_vec->bv_offset = 0;
+		bio->bi_io_vec->bv_len = bdev_logical_block_size(bdev);
+
+		if (nr_sects > max_write_same_sectors) {
+			bio->bi_size = max_write_same_sectors << 9;
+			nr_sects -= max_write_same_sectors;
+			sector += max_write_same_sectors;
+		} else {
+			bio->bi_size = nr_sects << 9;
+			nr_sects = 0;
+		}
+
+		atomic_inc(&bb.done);
+		submit_bio(REQ_WRITE | REQ_WRITE_SAME, bio);
+	}
+
+	/* Wait for bios in-flight */
+	if (!atomic_dec_and_test(&bb.done))
+		wait_for_completion(&wait);
+
+	if (!test_bit(BIO_UPTODATE, &bb.flags))
+		ret = -ENOTSUPP;
+
+	return ret;
+}
+EXPORT_SYMBOL(blkdev_issue_write_same);
+
+/**
  * blkdev_issue_zeroout - generate number of zero filed write bios
  * @bdev:	blockdev to issue
  * @sector:	start sector
@@ -140,7 +214,7 @@ EXPORT_SYMBOL(blkdev_issue_discard);
  *  Generate and issue number of bios with zerofiled pages.
  */
 
-int blkdev_issue_zeroout(struct block_device *bdev, sector_t sector,
+int __blkdev_issue_zeroout(struct block_device *bdev, sector_t sector,
 			sector_t nr_sects, gfp_t gfp_mask)
 {
 	int ret;
@@ -190,4 +264,32 @@ int blkdev_issue_zeroout(struct block_device *bdev, sector_t sector,
 
 	return ret;
 }
+
+/**
+ * blkdev_issue_zeroout - zero-fill a block range
+ * @bdev:	blockdev to write
+ * @sector:	start sector
+ * @nr_sects:	number of sectors to write
+ * @gfp_mask:	memory allocation flags (for bio_alloc)
+ *
+ * Description:
+ *  Generate and issue number of bios with zerofiled pages.
+ */
+
+int blkdev_issue_zeroout(struct block_device *bdev, sector_t sector,
+			 sector_t nr_sects, gfp_t gfp_mask)
+{
+	if (bdev_write_same(bdev)) {
+		unsigned char bdn[BDEVNAME_SIZE];
+
+		if (!blkdev_issue_write_same(bdev, sector, nr_sects, gfp_mask,
+					     ZERO_PAGE(0)))
+			return 0;
+
+		bdevname(bdev, bdn);
+		pr_err("%s: WRITE SAME failed. Manually zeroing.\n", bdn);
+	}
+
+	return __blkdev_issue_zeroout(bdev, sector, nr_sects, gfp_mask);
+}
 EXPORT_SYMBOL(blkdev_issue_zeroout);
diff --git a/block/blk-merge.c b/block/blk-merge.c
index e76279e..936a110 100644
--- a/block/blk-merge.c
+++ b/block/blk-merge.c
@@ -275,14 +275,8 @@ no_merge:
 int ll_back_merge_fn(struct request_queue *q, struct request *req,
 		     struct bio *bio)
 {
-	unsigned short max_sectors;
-
-	if (unlikely(req->cmd_type == REQ_TYPE_BLOCK_PC))
-		max_sectors = queue_max_hw_sectors(q);
-	else
-		max_sectors = queue_max_sectors(q);
-
-	if (blk_rq_sectors(req) + bio_sectors(bio) > max_sectors) {
+	if (blk_rq_sectors(req) + bio_sectors(bio) >
+	    blk_rq_get_max_sectors(req)) {
 		req->cmd_flags |= REQ_NOMERGE;
 		if (req == q->last_merge)
 			q->last_merge = NULL;
@@ -299,15 +293,8 @@ int ll_back_merge_fn(struct request_queue *q, struct request *req,
 int ll_front_merge_fn(struct request_queue *q, struct request *req,
 		      struct bio *bio)
 {
-	unsigned short max_sectors;
-
-	if (unlikely(req->cmd_type == REQ_TYPE_BLOCK_PC))
-		max_sectors = queue_max_hw_sectors(q);
-	else
-		max_sectors = queue_max_sectors(q);
-
-
-	if (blk_rq_sectors(req) + bio_sectors(bio) > max_sectors) {
+	if (blk_rq_sectors(req) + bio_sectors(bio) >
+	    blk_rq_get_max_sectors(req)) {
 		req->cmd_flags |= REQ_NOMERGE;
 		if (req == q->last_merge)
 			q->last_merge = NULL;
@@ -338,7 +325,8 @@ static int ll_merge_requests_fn(struct request_queue *q, struct request *req,
 	/*
 	 * Will it become too large?
 	 */
-	if ((blk_rq_sectors(req) + blk_rq_sectors(next)) > queue_max_sectors(q))
+	if ((blk_rq_sectors(req) + blk_rq_sectors(next)) >
+	    blk_rq_get_max_sectors(req))
 		return 0;
 
 	total_phys_segments = req->nr_phys_segments + next->nr_phys_segments;
@@ -417,16 +405,7 @@ static int attempt_merge(struct request_queue *q, struct request *req,
 	if (!rq_mergeable(req) || !rq_mergeable(next))
 		return 0;
 
-	/*
-	 * Don't merge file system requests and discard requests
-	 */
-	if ((req->cmd_flags & REQ_DISCARD) != (next->cmd_flags & REQ_DISCARD))
-		return 0;
-
-	/*
-	 * Don't merge discard requests and secure discard requests
-	 */
-	if ((req->cmd_flags & REQ_SECURE) != (next->cmd_flags & REQ_SECURE))
+	if (!blk_check_merge_flags(req->cmd_flags, next->cmd_flags))
 		return 0;
 
 	/*
@@ -440,6 +419,10 @@ static int attempt_merge(struct request_queue *q, struct request *req,
 	    || next->special)
 		return 0;
 
+	if (req->cmd_flags & REQ_WRITE_SAME &&
+	    !blk_write_same_mergeable(req->bio, next->bio))
+		return 0;
+
 	/*
 	 * If we are allowed to merge, then append bio list
 	 * from next to rq and release next. merge_requests_fn
@@ -521,15 +504,10 @@ int blk_attempt_req_merge(struct request_queue *q, struct request *rq,
 
 bool blk_rq_merge_ok(struct request *rq, struct bio *bio)
 {
-	if (!rq_mergeable(rq))
+	if (!rq_mergeable(rq) || !bio_mergeable(bio))
 		return false;
 
-	/* don't merge file system requests and discard requests */
-	if ((bio->bi_rw & REQ_DISCARD) != (rq->bio->bi_rw & REQ_DISCARD))
-		return false;
-
-	/* don't merge discard requests and secure discard requests */
-	if ((bio->bi_rw & REQ_SECURE) != (rq->bio->bi_rw & REQ_SECURE))
+	if (!blk_check_merge_flags(rq->cmd_flags, bio->bi_rw))
 		return false;
 
 	/* different data direction or already started, don't merge */
@@ -544,6 +522,11 @@ bool blk_rq_merge_ok(struct request *rq, struct bio *bio)
 	if (bio_integrity(bio) != blk_integrity_rq(rq))
 		return false;
 
+	/* must be using the same buffer */
+	if (rq->cmd_flags & REQ_WRITE_SAME &&
+	    !blk_write_same_mergeable(rq->bio, bio))
+		return false;
+
 	return true;
 }
 
diff --git a/block/blk-settings.c b/block/blk-settings.c
index 565a678..779bb76 100644
--- a/block/blk-settings.c
+++ b/block/blk-settings.c
@@ -113,6 +113,7 @@ void blk_set_default_limits(struct queue_limits *lim)
 	lim->seg_boundary_mask = BLK_SEG_BOUNDARY_MASK;
 	lim->max_segment_size = BLK_MAX_SEGMENT_SIZE;
 	lim->max_sectors = lim->max_hw_sectors = BLK_SAFE_MAX_SECTORS;
+	lim->max_write_same_sectors = 0;
 	lim->max_discard_sectors = 0;
 	lim->discard_granularity = 0;
 	lim->discard_alignment = 0;
@@ -144,6 +145,7 @@ void blk_set_stacking_limits(struct queue_limits *lim)
 	lim->max_segments = USHRT_MAX;
 	lim->max_hw_sectors = UINT_MAX;
 	lim->max_sectors = UINT_MAX;
+	lim->max_write_same_sectors = UINT_MAX;
 }
 EXPORT_SYMBOL(blk_set_stacking_limits);
 
@@ -286,6 +288,18 @@ void blk_queue_max_discard_sectors(struct request_queue *q,
 EXPORT_SYMBOL(blk_queue_max_discard_sectors);
 
 /**
+ * blk_queue_max_write_same_sectors - set max sectors for a single write same
+ * @q:  the request queue for the device
+ * @max_write_same_sectors: maximum number of sectors to write per command
+ **/
+void blk_queue_max_write_same_sectors(struct request_queue *q,
+				      unsigned int max_write_same_sectors)
+{
+	q->limits.max_write_same_sectors = max_write_same_sectors;
+}
+EXPORT_SYMBOL(blk_queue_max_write_same_sectors);
+
+/**
  * blk_queue_max_segments - set max hw segments for a request for this queue
  * @q:  the request queue for the device
  * @max_segments:  max number of segments
@@ -510,6 +524,8 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b,
 
 	t->max_sectors = min_not_zero(t->max_sectors, b->max_sectors);
 	t->max_hw_sectors = min_not_zero(t->max_hw_sectors, b->max_hw_sectors);
+	t->max_write_same_sectors = min(t->max_write_same_sectors,
+					b->max_write_same_sectors);
 	t->bounce_pfn = min_not_zero(t->bounce_pfn, b->bounce_pfn);
 
 	t->seg_boundary_mask = min_not_zero(t->seg_boundary_mask,
diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c
index 9628b29..ce62046 100644
--- a/block/blk-sysfs.c
+++ b/block/blk-sysfs.c
@@ -26,9 +26,15 @@ queue_var_show(unsigned long var, char *page)
 static ssize_t
 queue_var_store(unsigned long *var, const char *page, size_t count)
 {
-	char *p = (char *) page;
+	int err;
+	unsigned long v;
+
+	err = strict_strtoul(page, 10, &v);
+	if (err || v > UINT_MAX)
+		return -EINVAL;
+
+	*var = v;
 
-	*var = simple_strtoul(p, &p, 10);
 	return count;
 }
 
@@ -48,6 +54,9 @@ queue_requests_store(struct request_queue *q, const char *page, size_t count)
 		return -EINVAL;
 
 	ret = queue_var_store(&nr, page, count);
+	if (ret < 0)
+		return ret;
+
 	if (nr < BLKDEV_MIN_RQ)
 		nr = BLKDEV_MIN_RQ;
 
@@ -102,6 +111,9 @@ queue_ra_store(struct request_queue *q, const char *page, size_t count)
 	unsigned long ra_kb;
 	ssize_t ret = queue_var_store(&ra_kb, page, count);
 
+	if (ret < 0)
+		return ret;
+
 	q->backing_dev_info.ra_pages = ra_kb >> (PAGE_CACHE_SHIFT - 10);
 
 	return ret;
@@ -168,6 +180,13 @@ static ssize_t queue_discard_zeroes_data_show(struct request_queue *q, char *pag
 	return queue_var_show(queue_discard_zeroes_data(q), page);
 }
 
+static ssize_t queue_write_same_max_show(struct request_queue *q, char *page)
+{
+	return sprintf(page, "%llu\n",
+		(unsigned long long)q->limits.max_write_same_sectors << 9);
+}
+
+
 static ssize_t
 queue_max_sectors_store(struct request_queue *q, const char *page, size_t count)
 {
@@ -176,6 +195,9 @@ queue_max_sectors_store(struct request_queue *q, const char *page, size_t count)
 			page_kb = 1 << (PAGE_CACHE_SHIFT - 10);
 	ssize_t ret = queue_var_store(&max_sectors_kb, page, count);
 
+	if (ret < 0)
+		return ret;
+
 	if (max_sectors_kb > max_hw_sectors_kb || max_sectors_kb < page_kb)
 		return -EINVAL;
 
@@ -236,6 +258,9 @@ static ssize_t queue_nomerges_store(struct request_queue *q, const char *page,
 	unsigned long nm;
 	ssize_t ret = queue_var_store(&nm, page, count);
 
+	if (ret < 0)
+		return ret;
+
 	spin_lock_irq(q->queue_lock);
 	queue_flag_clear(QUEUE_FLAG_NOMERGES, q);
 	queue_flag_clear(QUEUE_FLAG_NOXMERGES, q);
@@ -264,6 +289,9 @@ queue_rq_affinity_store(struct request_queue *q, const char *page, size_t count)
 	unsigned long val;
 
 	ret = queue_var_store(&val, page, count);
+	if (ret < 0)
+		return ret;
+
 	spin_lock_irq(q->queue_lock);
 	if (val == 2) {
 		queue_flag_set(QUEUE_FLAG_SAME_COMP, q);
@@ -364,6 +392,11 @@ static struct queue_sysfs_entry queue_discard_zeroes_data_entry = {
 	.show = queue_discard_zeroes_data_show,
 };
 
+static struct queue_sysfs_entry queue_write_same_max_entry = {
+	.attr = {.name = "write_same_max_bytes", .mode = S_IRUGO },
+	.show = queue_write_same_max_show,
+};
+
 static struct queue_sysfs_entry queue_nonrot_entry = {
 	.attr = {.name = "rotational", .mode = S_IRUGO | S_IWUSR },
 	.show = queue_show_nonrot,
@@ -411,6 +444,7 @@ static struct attribute *default_attrs[] = {
 	&queue_discard_granularity_entry.attr,
 	&queue_discard_max_entry.attr,
 	&queue_discard_zeroes_data_entry.attr,
+	&queue_write_same_max_entry.attr,
 	&queue_nonrot_entry.attr,
 	&queue_nomerges_entry.attr,
 	&queue_rq_affinity_entry.attr,
@@ -527,6 +561,12 @@ int blk_register_queue(struct gendisk *disk)
 	if (WARN_ON(!q))
 		return -ENXIO;
 
+	/*
+	 * Initialization must be complete by now.  Finish the initial
+	 * bypass from queue allocation.
+	 */
+	blk_queue_bypass_end(q);
+
 	ret = blk_trace_init_sysfs(dev);
 	if (ret)
 		return ret;
diff --git a/block/blk-tag.c b/block/blk-tag.c
index 4af6f5c..cc345e1 100644
--- a/block/blk-tag.c
+++ b/block/blk-tag.c
@@ -186,7 +186,8 @@ int blk_queue_init_tags(struct request_queue *q, int depth,
 		tags = __blk_queue_init_tags(q, depth);
 
 		if (!tags)
-			goto fail;
+			return -ENOMEM;
+
 	} else if (q->queue_tags) {
 		rc = blk_queue_resize_tags(q, depth);
 		if (rc)
@@ -203,9 +204,6 @@ int blk_queue_init_tags(struct request_queue *q, int depth,
 	queue_flag_set_unlocked(QUEUE_FLAG_QUEUED, q);
 	INIT_LIST_HEAD(&q->tag_busy_list);
 	return 0;
-fail:
-	kfree(tags);
-	return -ENOMEM;
 }
 EXPORT_SYMBOL(blk_queue_init_tags);
 
diff --git a/block/blk-throttle.c b/block/blk-throttle.c
index e287c19..a9664fa 100644
--- a/block/blk-throttle.c
+++ b/block/blk-throttle.c
@@ -180,7 +180,7 @@ static inline unsigned int total_nr_queued(struct throtl_data *td)
 
 /*
  * Worker for allocating per cpu stat for tgs. This is scheduled on the
- * system_nrt_wq once there are some groups on the alloc_list waiting for
+ * system_wq once there are some groups on the alloc_list waiting for
  * allocation.
  */
 static void tg_stats_alloc_fn(struct work_struct *work)
@@ -194,8 +194,7 @@ alloc_stats:
 		stats_cpu = alloc_percpu(struct tg_stats_cpu);
 		if (!stats_cpu) {
 			/* allocation failed, try again after some time */
-			queue_delayed_work(system_nrt_wq, dwork,
-					   msecs_to_jiffies(10));
+			schedule_delayed_work(dwork, msecs_to_jiffies(10));
 			return;
 		}
 	}
@@ -238,7 +237,7 @@ static void throtl_pd_init(struct blkcg_gq *blkg)
 	 */
 	spin_lock_irqsave(&tg_stats_alloc_lock, flags);
 	list_add(&tg->stats_alloc_node, &tg_stats_alloc_list);
-	queue_delayed_work(system_nrt_wq, &tg_stats_alloc_work, 0);
+	schedule_delayed_work(&tg_stats_alloc_work, 0);
 	spin_unlock_irqrestore(&tg_stats_alloc_lock, flags);
 }
 
@@ -930,12 +929,7 @@ throtl_schedule_delayed_work(struct throtl_data *td, unsigned long delay)
 
 	/* schedule work if limits changed even if no bio is queued */
 	if (total_nr_queued(td) || td->limits_changed) {
-		/*
-		 * We might have a work scheduled to be executed in future.
-		 * Cancel that and schedule a new one.
-		 */
-		__cancel_delayed_work(dwork);
-		queue_delayed_work(kthrotld_workqueue, dwork, delay);
+		mod_delayed_work(kthrotld_workqueue, dwork, delay);
 		throtl_log(td, "schedule work. delay=%lu jiffies=%lu",
 				delay, jiffies);
 	}
diff --git a/block/blk.h b/block/blk.h
index 2a0ea32..ca51543 100644
--- a/block/blk.h
+++ b/block/blk.h
@@ -171,14 +171,13 @@ static inline int queue_congestion_off_threshold(struct request_queue *q)
  *
  *	a) it's attached to a gendisk, and
  *	b) the queue had IO stats enabled when this request was started, and
- *	c) it's a file system request or a discard request
+ *	c) it's a file system request
  */
 static inline int blk_do_io_stat(struct request *rq)
 {
 	return rq->rq_disk &&
 	       (rq->cmd_flags & REQ_IO_STAT) &&
-	       (rq->cmd_type == REQ_TYPE_FS ||
-	        (rq->cmd_flags & REQ_DISCARD));
+		(rq->cmd_type == REQ_TYPE_FS);
 }
 
 /*
diff --git a/block/elevator.c b/block/elevator.c
index 6a55d41..9b1d42b 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -562,8 +562,7 @@ void __elv_add_request(struct request_queue *q, struct request *rq, int where)
 
 	if (rq->cmd_flags & REQ_SOFTBARRIER) {
 		/* barriers are scheduling boundary, update end_sector */
-		if (rq->cmd_type == REQ_TYPE_FS ||
-		    (rq->cmd_flags & REQ_DISCARD)) {
+		if (rq->cmd_type == REQ_TYPE_FS) {
 			q->end_sector = rq_end_sector(rq);
 			q->boundary_rq = rq;
 		}
@@ -605,8 +604,7 @@ void __elv_add_request(struct request_queue *q, struct request *rq, int where)
 		if (elv_attempt_insert_merge(q, rq))
 			break;
 	case ELEVATOR_INSERT_SORT:
-		BUG_ON(rq->cmd_type != REQ_TYPE_FS &&
-		       !(rq->cmd_flags & REQ_DISCARD));
+		BUG_ON(rq->cmd_type != REQ_TYPE_FS);
 		rq->cmd_flags |= REQ_SORTED;
 		q->nr_sorted++;
 		if (rq_mergeable(rq)) {
diff --git a/block/genhd.c b/block/genhd.c
index d839723..9e02cd6 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -587,8 +587,6 @@ void add_disk(struct gendisk *disk)
 	WARN_ON(disk->minors && !(disk->major || disk->first_minor));
 	WARN_ON(!disk->minors && !(disk->flags & GENHD_FL_EXT_DEVT));
 
-	disk->flags |= GENHD_FL_UP;
-
 	retval = blk_alloc_devt(&disk->part0, &devt);
 	if (retval) {
 		WARN_ON(1);
@@ -596,6 +594,8 @@ void add_disk(struct gendisk *disk)
 	}
 	disk_to_dev(disk)->devt = devt;
 
+	disk->flags |= GENHD_FL_UP;
+
 	/* ->major and ->first_minor aren't supposed to be
 	 * dereferenced from here on, but set them just in case.
 	 */
@@ -743,7 +743,6 @@ void __init printk_all_partitions(void)
 		struct hd_struct *part;
 		char name_buf[BDEVNAME_SIZE];
 		char devt_buf[BDEVT_SIZE];
-		char uuid_buf[PARTITION_META_INFO_UUIDLTH * 2 + 5];
 
 		/*
 		 * Don't show empty devices or things that have been
@@ -762,16 +761,11 @@ void __init printk_all_partitions(void)
 		while ((part = disk_part_iter_next(&piter))) {
 			bool is_part0 = part == &disk->part0;
 
-			uuid_buf[0] = '\0';
-			if (part->info)
-				snprintf(uuid_buf, sizeof(uuid_buf), "%pU",
-					 part->info->uuid);
-
 			printk("%s%s %10llu %s %s", is_part0 ? "" : "  ",
 			       bdevt_str(part_devt(part), devt_buf),
 			       (unsigned long long)part_nr_sects_read(part) >> 1
 			       , disk_name(disk, part->partno, name_buf),
-			       uuid_buf);
+			       part->info ? part->info->uuid : "");
 			if (is_part0) {
 				if (disk->driverfs_dev != NULL &&
 				    disk->driverfs_dev->driver != NULL)
@@ -1105,7 +1099,7 @@ static void disk_release(struct device *dev)
 	disk_replace_part_tbl(disk, NULL);
 	free_part_stats(&disk->part0);
 	free_part_info(&disk->part0);
-	if (disk->queue)
+	if (disk->queue && disk->flags & GENHD_FL_UP)
 		blk_put_queue(disk->queue);
 	kfree(disk);
 }
@@ -1490,9 +1484,9 @@ static void __disk_unblock_events(struct gendisk *disk, bool check_now)
 	intv = disk_events_poll_jiffies(disk);
 	set_timer_slack(&ev->dwork.timer, intv / 4);
 	if (check_now)
-		queue_delayed_work(system_nrt_freezable_wq, &ev->dwork, 0);
+		queue_delayed_work(system_freezable_wq, &ev->dwork, 0);
 	else if (intv)
-		queue_delayed_work(system_nrt_freezable_wq, &ev->dwork, intv);
+		queue_delayed_work(system_freezable_wq, &ev->dwork, intv);
 out_unlock:
 	spin_unlock_irqrestore(&ev->lock, flags);
 }
@@ -1534,10 +1528,8 @@ void disk_flush_events(struct gendisk *disk, unsigned int mask)
 
 	spin_lock_irq(&ev->lock);
 	ev->clearing |= mask;
-	if (!ev->block) {
-		cancel_delayed_work(&ev->dwork);
-		queue_delayed_work(system_nrt_freezable_wq, &ev->dwork, 0);
-	}
+	if (!ev->block)
+		mod_delayed_work(system_freezable_wq, &ev->dwork, 0);
 	spin_unlock_irq(&ev->lock);
 }
 
@@ -1573,7 +1565,7 @@ unsigned int disk_clear_events(struct gendisk *disk, unsigned int mask)
 
 	/* uncondtionally schedule event check and wait for it to finish */
 	disk_block_events(disk);
-	queue_delayed_work(system_nrt_freezable_wq, &ev->dwork, 0);
+	queue_delayed_work(system_freezable_wq, &ev->dwork, 0);
 	flush_delayed_work(&ev->dwork);
 	__disk_unblock_events(disk, false);
 
@@ -1610,7 +1602,7 @@ static void disk_events_workfn(struct work_struct *work)
 
 	intv = disk_events_poll_jiffies(disk);
 	if (!ev->block && intv)
-		queue_delayed_work(system_nrt_freezable_wq, &ev->dwork, intv);
+		queue_delayed_work(system_freezable_wq, &ev->dwork, intv);
 
 	spin_unlock_irq(&ev->lock);
 
diff --git a/block/ioctl.c b/block/ioctl.c
index 4a85096..a31d91d 100644
--- a/block/ioctl.c
+++ b/block/ioctl.c
@@ -185,6 +185,22 @@ static int blk_ioctl_discard(struct block_device *bdev, uint64_t start,
 	return blkdev_issue_discard(bdev, start, len, GFP_KERNEL, flags);
 }
 
+static int blk_ioctl_zeroout(struct block_device *bdev, uint64_t start,
+			     uint64_t len)
+{
+	if (start & 511)
+		return -EINVAL;
+	if (len & 511)
+		return -EINVAL;
+	start >>= 9;
+	len >>= 9;
+
+	if (start + len > (i_size_read(bdev->bd_inode) >> 9))
+		return -EINVAL;
+
+	return blkdev_issue_zeroout(bdev, start, len, GFP_KERNEL);
+}
+
 static int put_ushort(unsigned long arg, unsigned short val)
 {
 	return put_user(val, (unsigned short __user *)arg);
@@ -300,6 +316,17 @@ int blkdev_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd,
 		return blk_ioctl_discard(bdev, range[0], range[1],
 					 cmd == BLKSECDISCARD);
 	}
+	case BLKZEROOUT: {
+		uint64_t range[2];
+
+		if (!(mode & FMODE_WRITE))
+			return -EBADF;
+
+		if (copy_from_user(range, (void __user *)arg, sizeof(range)))
+			return -EFAULT;
+
+		return blk_ioctl_zeroout(bdev, range[0], range[1]);
+	}
 
 	case HDIO_GETGEO: {
 		struct hd_geometry geo;
diff --git a/block/partitions/efi.c b/block/partitions/efi.c
index 6296b40..b62fb88 100644
--- a/block/partitions/efi.c
+++ b/block/partitions/efi.c
@@ -620,7 +620,6 @@ int efi_partition(struct parsed_partitions *state)
 	gpt_entry *ptes = NULL;
 	u32 i;
 	unsigned ssz = bdev_logical_block_size(state->bdev) / 512;
-	u8 unparsed_guid[37];
 
 	if (!find_valid_gpt(state, &gpt, &ptes) || !gpt || !ptes) {
 		kfree(gpt);
@@ -649,11 +648,7 @@ int efi_partition(struct parsed_partitions *state)
 			state->parts[i + 1].flags = ADDPART_FLAG_RAID;
 
 		info = &state->parts[i + 1].info;
-		/* Instead of doing a manual swap to big endian, reuse the
-		 * common ASCII hex format as the interim.
-		 */
-		efi_guid_unparse(&ptes[i].unique_partition_guid, unparsed_guid);
-		part_pack_uuid(unparsed_guid, info->uuid);
+		efi_guid_unparse(&ptes[i].unique_partition_guid, info->uuid);
 
 		/* Naively convert UTF16-LE to 7 bits. */
 		label_max = min(sizeof(info->volname) - 1,
diff --git a/block/partitions/ibm.c b/block/partitions/ibm.c
index 1104aca..47a6147 100644
--- a/block/partitions/ibm.c
+++ b/block/partitions/ibm.c
@@ -1,9 +1,8 @@
 /*
- * File...........: linux/fs/partitions/ibm.c
  * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
  *                  Volker Sameske <sameske@de.ibm.com>
  * Bugreports.to..: <Linux390@de.ibm.com>
- * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
+ * Copyright IBM Corp. 1999, 2012
  */
 
 #include <linux/buffer_head.h>
@@ -17,17 +16,23 @@
 #include "check.h"
 #include "ibm.h"
 
+
+union label_t {
+	struct vtoc_volume_label_cdl vol;
+	struct vtoc_volume_label_ldl lnx;
+	struct vtoc_cms_label cms;
+};
+
 /*
  * compute the block number from a
  * cyl-cyl-head-head structure
  */
-static sector_t
-cchh2blk (struct vtoc_cchh *ptr, struct hd_geometry *geo) {
-
+static sector_t cchh2blk(struct vtoc_cchh *ptr, struct hd_geometry *geo)
+{
 	sector_t cyl;
 	__u16 head;
 
-	/*decode cylinder and heads for large volumes */
+	/* decode cylinder and heads for large volumes */
 	cyl = ptr->hh & 0xFFF0;
 	cyl <<= 12;
 	cyl |= ptr->cc;
@@ -40,13 +45,12 @@ cchh2blk (struct vtoc_cchh *ptr, struct hd_geometry *geo) {
  * compute the block number from a
  * cyl-cyl-head-head-block structure
  */
-static sector_t
-cchhb2blk (struct vtoc_cchhb *ptr, struct hd_geometry *geo) {
-
+static sector_t cchhb2blk(struct vtoc_cchhb *ptr, struct hd_geometry *geo)
+{
 	sector_t cyl;
 	__u16 head;
 
-	/*decode cylinder and heads for large volumes */
+	/* decode cylinder and heads for large volumes */
 	cyl = ptr->hh & 0xFFF0;
 	cyl <<= 12;
 	cyl |= ptr->cc;
@@ -56,26 +60,243 @@ cchhb2blk (struct vtoc_cchhb *ptr, struct hd_geometry *geo) {
 		ptr->b;
 }
 
+static int find_label(struct parsed_partitions *state,
+		      dasd_information2_t *info,
+		      struct hd_geometry *geo,
+		      int blocksize,
+		      sector_t *labelsect,
+		      char name[],
+		      char type[],
+		      union label_t *label)
+{
+	Sector sect;
+	unsigned char *data;
+	sector_t testsect[3];
+	unsigned char temp[5];
+	int found = 0;
+	int i, testcount;
+
+	/* There a three places where we may find a valid label:
+	 * - on an ECKD disk it's block 2
+	 * - on an FBA disk it's block 1
+	 * - on an CMS formatted FBA disk it is sector 1, even if the block size
+	 *   is larger than 512 bytes (possible if the DIAG discipline is used)
+	 * If we have a valid info structure, then we know exactly which case we
+	 * have, otherwise we just search through all possebilities.
+	 */
+	if (info) {
+		if ((info->cu_type == 0x6310 && info->dev_type == 0x9336) ||
+		    (info->cu_type == 0x3880 && info->dev_type == 0x3370))
+			testsect[0] = info->label_block;
+		else
+			testsect[0] = info->label_block * (blocksize >> 9);
+		testcount = 1;
+	} else {
+		testsect[0] = 1;
+		testsect[1] = (blocksize >> 9);
+		testsect[2] = 2 * (blocksize >> 9);
+		testcount = 3;
+	}
+	for (i = 0; i < testcount; ++i) {
+		data = read_part_sector(state, testsect[i], &sect);
+		if (data == NULL)
+			continue;
+		memcpy(label, data, sizeof(*label));
+		memcpy(temp, data, 4);
+		temp[4] = 0;
+		EBCASC(temp, 4);
+		put_dev_sector(sect);
+		if (!strcmp(temp, "VOL1") ||
+		    !strcmp(temp, "LNX1") ||
+		    !strcmp(temp, "CMS1")) {
+			if (!strcmp(temp, "VOL1")) {
+				strncpy(type, label->vol.vollbl, 4);
+				strncpy(name, label->vol.volid, 6);
+			} else {
+				strncpy(type, label->lnx.vollbl, 4);
+				strncpy(name, label->lnx.volid, 6);
+			}
+			EBCASC(type, 4);
+			EBCASC(name, 6);
+			*labelsect = testsect[i];
+			found = 1;
+			break;
+		}
+	}
+	if (!found)
+		memset(label, 0, sizeof(*label));
+
+	return found;
+}
+
+static int find_vol1_partitions(struct parsed_partitions *state,
+				struct hd_geometry *geo,
+				int blocksize,
+				char name[],
+				union label_t *label)
+{
+	sector_t blk;
+	int counter;
+	char tmp[64];
+	Sector sect;
+	unsigned char *data;
+	loff_t offset, size;
+	struct vtoc_format1_label f1;
+	int secperblk;
+
+	snprintf(tmp, sizeof(tmp), "VOL1/%8s:", name);
+	strlcat(state->pp_buf, tmp, PAGE_SIZE);
+	/*
+	 * get start of VTOC from the disk label and then search for format1
+	 * and format8 labels
+	 */
+	secperblk = blocksize >> 9;
+	blk = cchhb2blk(&label->vol.vtoc, geo) + 1;
+	counter = 0;
+	data = read_part_sector(state, blk * secperblk, &sect);
+	while (data != NULL) {
+		memcpy(&f1, data, sizeof(struct vtoc_format1_label));
+		put_dev_sector(sect);
+		/* skip FMT4 / FMT5 / FMT7 labels */
+		if (f1.DS1FMTID == _ascebc['4']
+		    || f1.DS1FMTID == _ascebc['5']
+		    || f1.DS1FMTID == _ascebc['7']
+		    || f1.DS1FMTID == _ascebc['9']) {
+			blk++;
+			data = read_part_sector(state, blk * secperblk, &sect);
+			continue;
+		}
+		/* only FMT1 and 8 labels valid at this point */
+		if (f1.DS1FMTID != _ascebc['1'] &&
+		    f1.DS1FMTID != _ascebc['8'])
+			break;
+		/* OK, we got valid partition data */
+		offset = cchh2blk(&f1.DS1EXT1.llimit, geo);
+		size  = cchh2blk(&f1.DS1EXT1.ulimit, geo) -
+			offset + geo->sectors;
+		offset *= secperblk;
+		size *= secperblk;
+		if (counter >= state->limit)
+			break;
+		put_partition(state, counter + 1, offset, size);
+		counter++;
+		blk++;
+		data = read_part_sector(state, blk * secperblk, &sect);
+	}
+	strlcat(state->pp_buf, "\n", PAGE_SIZE);
+
+	if (!data)
+		return -1;
+
+	return 1;
+}
+
+static int find_lnx1_partitions(struct parsed_partitions *state,
+				struct hd_geometry *geo,
+				int blocksize,
+				char name[],
+				union label_t *label,
+				sector_t labelsect,
+				loff_t i_size,
+				dasd_information2_t *info)
+{
+	loff_t offset, geo_size, size;
+	char tmp[64];
+	int secperblk;
+
+	snprintf(tmp, sizeof(tmp), "LNX1/%8s:", name);
+	strlcat(state->pp_buf, tmp, PAGE_SIZE);
+	secperblk = blocksize >> 9;
+	if (label->lnx.ldl_version == 0xf2) {
+		size = label->lnx.formatted_blocks * secperblk;
+	} else {
+		/*
+		 * Formated w/o large volume support. If the sanity check
+		 * 'size based on geo == size based on i_size' is true, then
+		 * we can safely assume that we know the formatted size of
+		 * the disk, otherwise we need additional information
+		 * that we can only get from a real DASD device.
+		 */
+		geo_size = geo->cylinders * geo->heads
+			* geo->sectors * secperblk;
+		size = i_size >> 9;
+		if (size != geo_size) {
+			if (!info) {
+				strlcat(state->pp_buf, "\n", PAGE_SIZE);
+				return 1;
+			}
+			if (!strcmp(info->type, "ECKD"))
+				if (geo_size < size)
+					size = geo_size;
+			/* else keep size based on i_size */
+		}
+	}
+	/* first and only partition starts in the first block after the label */
+	offset = labelsect + secperblk;
+	put_partition(state, 1, offset, size - offset);
+	strlcat(state->pp_buf, "\n", PAGE_SIZE);
+	return 1;
+}
+
+static int find_cms1_partitions(struct parsed_partitions *state,
+				struct hd_geometry *geo,
+				int blocksize,
+				char name[],
+				union label_t *label,
+				sector_t labelsect)
+{
+	loff_t offset, size;
+	char tmp[64];
+	int secperblk;
+
+	/*
+	 * VM style CMS1 labeled disk
+	 */
+	blocksize = label->cms.block_size;
+	secperblk = blocksize >> 9;
+	if (label->cms.disk_offset != 0) {
+		snprintf(tmp, sizeof(tmp), "CMS1/%8s(MDSK):", name);
+		strlcat(state->pp_buf, tmp, PAGE_SIZE);
+		/* disk is reserved minidisk */
+		offset = label->cms.disk_offset * secperblk;
+		size = (label->cms.block_count - 1) * secperblk;
+	} else {
+		snprintf(tmp, sizeof(tmp), "CMS1/%8s:", name);
+		strlcat(state->pp_buf, tmp, PAGE_SIZE);
+		/*
+		 * Special case for FBA devices:
+		 * If an FBA device is CMS formatted with blocksize > 512 byte
+		 * and the DIAG discipline is used, then the CMS label is found
+		 * in sector 1 instead of block 1. However, the partition is
+		 * still supposed to start in block 2.
+		 */
+		if (labelsect == 1)
+			offset = 2 * secperblk;
+		else
+			offset = labelsect + secperblk;
+		size = label->cms.block_count * secperblk;
+	}
+
+	put_partition(state, 1, offset, size-offset);
+	strlcat(state->pp_buf, "\n", PAGE_SIZE);
+	return 1;
+}
+
+
 /*
+ * This is the main function, called by check.c
  */
 int ibm_partition(struct parsed_partitions *state)
 {
 	struct block_device *bdev = state->bdev;
 	int blocksize, res;
-	loff_t i_size, offset, size, fmt_size;
+	loff_t i_size, offset, size;
 	dasd_information2_t *info;
 	struct hd_geometry *geo;
 	char type[5] = {0,};
 	char name[7] = {0,};
-	union label_t {
-		struct vtoc_volume_label_cdl vol;
-		struct vtoc_volume_label_ldl lnx;
-		struct vtoc_cms_label cms;
-	} *label;
-	unsigned char *data;
-	Sector sect;
 	sector_t labelsect;
-	char tmp[64];
+	union label_t *label;
 
 	res = 0;
 	blocksize = bdev_logical_block_size(bdev);
@@ -84,7 +305,6 @@ int ibm_partition(struct parsed_partitions *state)
 	i_size = i_size_read(bdev->bd_inode);
 	if (i_size == 0)
 		goto out_exit;
-
 	info = kmalloc(sizeof(dasd_information2_t), GFP_KERNEL);
 	if (info == NULL)
 		goto out_exit;
@@ -94,176 +314,45 @@ int ibm_partition(struct parsed_partitions *state)
 	label = kmalloc(sizeof(union label_t), GFP_KERNEL);
 	if (label == NULL)
 		goto out_nolab;
-
-	if (ioctl_by_bdev(bdev, BIODASDINFO2, (unsigned long)info) != 0 ||
-	    ioctl_by_bdev(bdev, HDIO_GETGEO, (unsigned long)geo) != 0)
+	if (ioctl_by_bdev(bdev, HDIO_GETGEO, (unsigned long)geo) != 0)
 		goto out_freeall;
-
-	/*
-	 * Special case for FBA disks: label sector does not depend on
-	 * blocksize.
-	 */
-	if ((info->cu_type == 0x6310 && info->dev_type == 0x9336) ||
-	    (info->cu_type == 0x3880 && info->dev_type == 0x3370))
-		labelsect = info->label_block;
-	else
-		labelsect = info->label_block * (blocksize >> 9);
-
-	/*
-	 * Get volume label, extract name and type.
-	 */
-	data = read_part_sector(state, labelsect, &sect);
-	if (data == NULL)
-		goto out_readerr;
-
-	memcpy(label, data, sizeof(union label_t));
-	put_dev_sector(sect);
-
-	if ((!info->FBA_layout) && (!strcmp(info->type, "ECKD"))) {
-		strncpy(type, label->vol.vollbl, 4);
-		strncpy(name, label->vol.volid, 6);
-	} else {
-		strncpy(type, label->lnx.vollbl, 4);
-		strncpy(name, label->lnx.volid, 6);
+	if (ioctl_by_bdev(bdev, BIODASDINFO2, (unsigned long)info) != 0) {
+		kfree(info);
+		info = NULL;
 	}
-	EBCASC(type, 4);
-	EBCASC(name, 6);
-
-	res = 1;
 
-	/*
-	 * Three different formats: LDL, CDL and unformated disk
-	 *
-	 * identified by info->format
-	 *
-	 * unformated disks we do not have to care about
-	 */
-	if (info->format == DASD_FORMAT_LDL) {
-		if (strncmp(type, "CMS1", 4) == 0) {
-			/*
-			 * VM style CMS1 labeled disk
-			 */
-			blocksize = label->cms.block_size;
-			if (label->cms.disk_offset != 0) {
-				snprintf(tmp, sizeof(tmp), "CMS1/%8s(MDSK):", name);
-				strlcat(state->pp_buf, tmp, PAGE_SIZE);
-				/* disk is reserved minidisk */
-				offset = label->cms.disk_offset;
-				size = (label->cms.block_count - 1)
-					* (blocksize >> 9);
-			} else {
-				snprintf(tmp, sizeof(tmp), "CMS1/%8s:", name);
-				strlcat(state->pp_buf, tmp, PAGE_SIZE);
-				offset = (info->label_block + 1);
-				size = label->cms.block_count
-					* (blocksize >> 9);
-			}
-			put_partition(state, 1, offset*(blocksize >> 9),
-				      size-offset*(blocksize >> 9));
-		} else {
-			if (strncmp(type, "LNX1", 4) == 0) {
-				snprintf(tmp, sizeof(tmp), "LNX1/%8s:", name);
-				strlcat(state->pp_buf, tmp, PAGE_SIZE);
-				if (label->lnx.ldl_version == 0xf2) {
-					fmt_size = label->lnx.formatted_blocks
-						* (blocksize >> 9);
-				} else if (!strcmp(info->type, "ECKD")) {
-					/* formated w/o large volume support */
-					fmt_size = geo->cylinders * geo->heads
-					      * geo->sectors * (blocksize >> 9);
-				} else {
-					/* old label and no usable disk geometry
-					 * (e.g. DIAG) */
-					fmt_size = i_size >> 9;
-				}
-				size = i_size >> 9;
-				if (fmt_size < size)
-					size = fmt_size;
-				offset = (info->label_block + 1);
-			} else {
-				/* unlabeled disk */
-				strlcat(state->pp_buf, "(nonl)", PAGE_SIZE);
-				size = i_size >> 9;
-				offset = (info->label_block + 1);
-			}
-			put_partition(state, 1, offset*(blocksize >> 9),
-				      size-offset*(blocksize >> 9));
+	if (find_label(state, info, geo, blocksize, &labelsect, name, type,
+		       label)) {
+		if (!strncmp(type, "VOL1", 4)) {
+			res = find_vol1_partitions(state, geo, blocksize, name,
+						   label);
+		} else if (!strncmp(type, "LNX1", 4)) {
+			res = find_lnx1_partitions(state, geo, blocksize, name,
+						   label, labelsect, i_size,
+						   info);
+		} else if (!strncmp(type, "CMS1", 4)) {
+			res = find_cms1_partitions(state, geo, blocksize, name,
+						   label, labelsect);
 		}
-	} else if (info->format == DASD_FORMAT_CDL) {
-		/*
-		 * New style CDL formatted disk
-		 */
-		sector_t blk;
-		int counter;
-
+	} else if (info) {
 		/*
-		 * check if VOL1 label is available
-		 * if not, something is wrong, skipping partition detection
+		 * ugly but needed for backward compatibility:
+		 * If the block device is a DASD (i.e. BIODASDINFO2 works),
+		 * then we claim it in any case, even though it has no valid
+		 * label. If it has the LDL format, then we simply define a
+		 * partition as if it had an LNX1 label.
 		 */
-		if (strncmp(type, "VOL1",  4) == 0) {
-			snprintf(tmp, sizeof(tmp), "VOL1/%8s:", name);
-			strlcat(state->pp_buf, tmp, PAGE_SIZE);
-			/*
-			 * get block number and read then go through format1
-			 * labels
-			 */
-			blk = cchhb2blk(&label->vol.vtoc, geo) + 1;
-			counter = 0;
-			data = read_part_sector(state, blk * (blocksize/512),
-						&sect);
-			while (data != NULL) {
-				struct vtoc_format1_label f1;
-
-				memcpy(&f1, data,
-				       sizeof(struct vtoc_format1_label));
-				put_dev_sector(sect);
-
-				/* skip FMT4 / FMT5 / FMT7 labels */
-				if (f1.DS1FMTID == _ascebc['4']
-				    || f1.DS1FMTID == _ascebc['5']
-				    || f1.DS1FMTID == _ascebc['7']
-				    || f1.DS1FMTID == _ascebc['9']) {
-					blk++;
-					data = read_part_sector(state,
-						blk * (blocksize/512), &sect);
-					continue;
-				}
-
-				/* only FMT1 and 8 labels valid at this point */
-				if (f1.DS1FMTID != _ascebc['1'] &&
-				    f1.DS1FMTID != _ascebc['8'])
-					break;
-
-				/* OK, we got valid partition data */
-				offset = cchh2blk(&f1.DS1EXT1.llimit, geo);
-				size  = cchh2blk(&f1.DS1EXT1.ulimit, geo) -
-					offset + geo->sectors;
-				if (counter >= state->limit)
-					break;
-				put_partition(state, counter + 1,
-					      offset * (blocksize >> 9),
-					      size * (blocksize >> 9));
-				counter++;
-				blk++;
-				data = read_part_sector(state,
-						blk * (blocksize/512), &sect);
-			}
-
-			if (!data)
-				/* Are we not supposed to report this ? */
-				goto out_readerr;
-		} else
-			printk(KERN_INFO "Expected Label VOL1 not "
-			       "found, treating as CDL formated Disk");
-
-	}
-
-	strlcat(state->pp_buf, "\n", PAGE_SIZE);
-	goto out_freeall;
-
+		res = 1;
+		if (info->format == DASD_FORMAT_LDL) {
+			strlcat(state->pp_buf, "(nonl)", PAGE_SIZE);
+			size = i_size >> 9;
+			offset = (info->label_block + 1) * (blocksize >> 9);
+			put_partition(state, 1, offset, size-offset);
+			strlcat(state->pp_buf, "\n", PAGE_SIZE);
+		}
+	} else
+		res = 0;
 
-out_readerr:
-	res = -1;
 out_freeall:
 	kfree(label);
 out_nolab:
diff --git a/block/partitions/msdos.c b/block/partitions/msdos.c
index 5f79a66..8752a5d 100644
--- a/block/partitions/msdos.c
+++ b/block/partitions/msdos.c
@@ -94,6 +94,17 @@ static int aix_magic_present(struct parsed_partitions *state, unsigned char *p)
 	return ret;
 }
 
+static void set_info(struct parsed_partitions *state, int slot,
+		     u32 disksig)
+{
+	struct partition_meta_info *info = &state->parts[slot].info;
+
+	snprintf(info->uuid, sizeof(info->uuid), "%08x-%02x", disksig,
+		 slot);
+	info->volname[0] = 0;
+	state->parts[slot].has_info = true;
+}
+
 /*
  * Create devices for each logical partition in an extended partition.
  * The logical partitions form a linked list, with each entry being
@@ -106,7 +117,8 @@ static int aix_magic_present(struct parsed_partitions *state, unsigned char *p)
  */
 
 static void parse_extended(struct parsed_partitions *state,
-			   sector_t first_sector, sector_t first_size)
+			   sector_t first_sector, sector_t first_size,
+			   u32 disksig)
 {
 	struct partition *p;
 	Sector sect;
@@ -166,6 +178,7 @@ static void parse_extended(struct parsed_partitions *state,
 			}
 
 			put_partition(state, state->next, next, size);
+			set_info(state, state->next, disksig);
 			if (SYS_IND(p) == LINUX_RAID_PARTITION)
 				state->parts[state->next].flags = ADDPART_FLAG_RAID;
 			loopct = 0;
@@ -437,6 +450,7 @@ int msdos_partition(struct parsed_partitions *state)
 	struct partition *p;
 	struct fat_boot_sector *fb;
 	int slot;
+	u32 disksig;
 
 	data = read_part_sector(state, 0, &sect);
 	if (!data)
@@ -491,6 +505,8 @@ int msdos_partition(struct parsed_partitions *state)
 #endif
 	p = (struct partition *) (data + 0x1be);
 
+	disksig = le32_to_cpup((__le32 *)(data + 0x1b8));
+
 	/*
 	 * Look for partitions in two passes:
 	 * First find the primary and DOS-type extended partitions.
@@ -515,11 +531,12 @@ int msdos_partition(struct parsed_partitions *state)
 			put_partition(state, slot, start, n);
 
 			strlcat(state->pp_buf, " <", PAGE_SIZE);
-			parse_extended(state, start, size);
+			parse_extended(state, start, size, disksig);
 			strlcat(state->pp_buf, " >", PAGE_SIZE);
 			continue;
 		}
 		put_partition(state, slot, start, size);
+		set_info(state, slot, disksig);
 		if (SYS_IND(p) == LINUX_RAID_PARTITION)
 			state->parts[slot].flags = ADDPART_FLAG_RAID;
 		if (SYS_IND(p) == DM6_PARTITION)
diff --git a/crypto/842.c b/crypto/842.c
new file mode 100644
index 0000000..65c7a89c
--- /dev/null
+++ b/crypto/842.c
@@ -0,0 +1,182 @@
+/*
+ * Cryptographic API for the 842 compression algorithm.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ * Copyright (C) IBM Corporation, 2011
+ *
+ * Authors: Robert Jennings <rcj@linux.vnet.ibm.com>
+ *          Seth Jennings <sjenning@linux.vnet.ibm.com>
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/crypto.h>
+#include <linux/vmalloc.h>
+#include <linux/nx842.h>
+#include <linux/lzo.h>
+#include <linux/timer.h>
+
+static int nx842_uselzo;
+
+struct nx842_ctx {
+	void *nx842_wmem; /* working memory for 842/lzo */
+};
+
+enum nx842_crypto_type {
+	NX842_CRYPTO_TYPE_842,
+	NX842_CRYPTO_TYPE_LZO
+};
+
+#define NX842_SENTINEL 0xdeadbeef
+
+struct nx842_crypto_header {
+	unsigned int sentinel; /* debug */
+	enum nx842_crypto_type type;
+};
+
+static int nx842_init(struct crypto_tfm *tfm)
+{
+	struct nx842_ctx *ctx = crypto_tfm_ctx(tfm);
+	int wmemsize;
+
+	wmemsize = max_t(int, nx842_get_workmem_size(), LZO1X_MEM_COMPRESS);
+	ctx->nx842_wmem = kmalloc(wmemsize, GFP_NOFS);
+	if (!ctx->nx842_wmem)
+		return -ENOMEM;
+
+	return 0;
+}
+
+static void nx842_exit(struct crypto_tfm *tfm)
+{
+	struct nx842_ctx *ctx = crypto_tfm_ctx(tfm);
+
+	kfree(ctx->nx842_wmem);
+}
+
+static void nx842_reset_uselzo(unsigned long data)
+{
+	nx842_uselzo = 0;
+}
+
+static DEFINE_TIMER(failover_timer, nx842_reset_uselzo, 0, 0);
+
+static int nx842_crypto_compress(struct crypto_tfm *tfm, const u8 *src,
+			    unsigned int slen, u8 *dst, unsigned int *dlen)
+{
+	struct nx842_ctx *ctx = crypto_tfm_ctx(tfm);
+	struct nx842_crypto_header *hdr;
+	unsigned int tmp_len = *dlen;
+	size_t lzodlen; /* needed for lzo */
+	int err;
+
+	*dlen = 0;
+	hdr = (struct nx842_crypto_header *)dst;
+	hdr->sentinel = NX842_SENTINEL; /* debug */
+	dst += sizeof(struct nx842_crypto_header);
+	tmp_len -= sizeof(struct nx842_crypto_header);
+	lzodlen = tmp_len;
+
+	if (likely(!nx842_uselzo)) {
+		err = nx842_compress(src, slen, dst, &tmp_len, ctx->nx842_wmem);
+
+		if (likely(!err)) {
+			hdr->type = NX842_CRYPTO_TYPE_842;
+			*dlen = tmp_len + sizeof(struct nx842_crypto_header);
+			return 0;
+		}
+
+		/* hardware failed */
+		nx842_uselzo = 1;
+
+		/* set timer to check for hardware again in 1 second */
+		mod_timer(&failover_timer, jiffies + msecs_to_jiffies(1000));
+	}
+
+	/* no hardware, use lzo */
+	err = lzo1x_1_compress(src, slen, dst, &lzodlen, ctx->nx842_wmem);
+	if (err != LZO_E_OK)
+		return -EINVAL;
+
+	hdr->type = NX842_CRYPTO_TYPE_LZO;
+	*dlen = lzodlen + sizeof(struct nx842_crypto_header);
+	return 0;
+}
+
+static int nx842_crypto_decompress(struct crypto_tfm *tfm, const u8 *src,
+			      unsigned int slen, u8 *dst, unsigned int *dlen)
+{
+	struct nx842_ctx *ctx = crypto_tfm_ctx(tfm);
+	struct nx842_crypto_header *hdr;
+	unsigned int tmp_len = *dlen;
+	size_t lzodlen; /* needed for lzo */
+	int err;
+
+	*dlen = 0;
+	hdr = (struct nx842_crypto_header *)src;
+
+	if (unlikely(hdr->sentinel != NX842_SENTINEL))
+		return -EINVAL;
+
+	src += sizeof(struct nx842_crypto_header);
+	slen -= sizeof(struct nx842_crypto_header);
+
+	if (likely(hdr->type == NX842_CRYPTO_TYPE_842)) {
+		err = nx842_decompress(src, slen, dst, &tmp_len,
+			ctx->nx842_wmem);
+		if (err)
+			return -EINVAL;
+		*dlen = tmp_len;
+	} else if (hdr->type == NX842_CRYPTO_TYPE_LZO) {
+		lzodlen = tmp_len;
+		err = lzo1x_decompress_safe(src, slen, dst, &lzodlen);
+		if (err != LZO_E_OK)
+			return -EINVAL;
+		*dlen = lzodlen;
+	} else
+		return -EINVAL;
+
+	return 0;
+}
+
+static struct crypto_alg alg = {
+	.cra_name		= "842",
+	.cra_flags		= CRYPTO_ALG_TYPE_COMPRESS,
+	.cra_ctxsize		= sizeof(struct nx842_ctx),
+	.cra_module		= THIS_MODULE,
+	.cra_init		= nx842_init,
+	.cra_exit		= nx842_exit,
+	.cra_u			= { .compress = {
+	.coa_compress		= nx842_crypto_compress,
+	.coa_decompress		= nx842_crypto_decompress } }
+};
+
+static int __init nx842_mod_init(void)
+{
+	del_timer(&failover_timer);
+	return crypto_register_alg(&alg);
+}
+
+static void __exit nx842_mod_exit(void)
+{
+	crypto_unregister_alg(&alg);
+}
+
+module_init(nx842_mod_init);
+module_exit(nx842_mod_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("842 Compression Algorithm");
diff --git a/crypto/Kconfig b/crypto/Kconfig
index a323805..8a19730 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -336,6 +336,15 @@ config CRYPTO_CRC32C_INTEL
 	  gain performance compared with software implementation.
 	  Module will be crc32c-intel.
 
+config CRYPTO_CRC32C_SPARC64
+	tristate "CRC32c CRC algorithm (SPARC64)"
+	depends on SPARC64
+	select CRYPTO_HASH
+	select CRC32
+	help
+	  CRC32c CRC algorithm implemented using sparc64 crypto instructions,
+	  when available.
+
 config CRYPTO_GHASH
 	tristate "GHASH digest algorithm"
 	select CRYPTO_GF128MUL
@@ -354,6 +363,15 @@ config CRYPTO_MD5
 	help
 	  MD5 message digest algorithm (RFC1321).
 
+config CRYPTO_MD5_SPARC64
+	tristate "MD5 digest algorithm (SPARC64)"
+	depends on SPARC64
+	select CRYPTO_MD5
+	select CRYPTO_HASH
+	help
+	  MD5 message digest algorithm (RFC1321) implemented
+	  using sparc64 crypto instructions, when available.
+
 config CRYPTO_MICHAEL_MIC
 	tristate "Michael MIC keyed digest algorithm"
 	select CRYPTO_HASH
@@ -433,6 +451,24 @@ config CRYPTO_SHA1_SSSE3
 	  using Supplemental SSE3 (SSSE3) instructions or Advanced Vector
 	  Extensions (AVX), when available.
 
+config CRYPTO_SHA1_ARM
+	tristate "SHA1 digest algorithm (ARM-asm)"
+	depends on ARM
+	select CRYPTO_SHA1
+	select CRYPTO_HASH
+	help
+	  SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2) implemented
+	  using optimized ARM assembler.
+
+config CRYPTO_SHA1_SPARC64
+	tristate "SHA1 digest algorithm (SPARC64)"
+	depends on SPARC64
+	select CRYPTO_SHA1
+	select CRYPTO_HASH
+	help
+	  SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2) implemented
+	  using sparc64 crypto instructions, when available.
+
 config CRYPTO_SHA256
 	tristate "SHA224 and SHA256 digest algorithm"
 	select CRYPTO_HASH
@@ -445,6 +481,15 @@ config CRYPTO_SHA256
 	  This code also includes SHA-224, a 224 bit hash with 112 bits
 	  of security against collision attacks.
 
+config CRYPTO_SHA256_SPARC64
+	tristate "SHA224 and SHA256 digest algorithm (SPARC64)"
+	depends on SPARC64
+	select CRYPTO_SHA256
+	select CRYPTO_HASH
+	help
+	  SHA-256 secure hash standard (DFIPS 180-2) implemented
+	  using sparc64 crypto instructions, when available.
+
 config CRYPTO_SHA512
 	tristate "SHA384 and SHA512 digest algorithms"
 	select CRYPTO_HASH
@@ -457,6 +502,15 @@ config CRYPTO_SHA512
 	  This code also includes SHA-384, a 384 bit hash with 192 bits
 	  of security against collision attacks.
 
+config CRYPTO_SHA512_SPARC64
+	tristate "SHA384 and SHA512 digest algorithm (SPARC64)"
+	depends on SPARC64
+	select CRYPTO_SHA512
+	select CRYPTO_HASH
+	help
+	  SHA-512 secure hash standard (DFIPS 180-2) implemented
+	  using sparc64 crypto instructions, when available.
+
 config CRYPTO_TGR192
 	tristate "Tiger digest algorithms"
 	select CRYPTO_HASH
@@ -564,6 +618,8 @@ config CRYPTO_AES_NI_INTEL
 	select CRYPTO_CRYPTD
 	select CRYPTO_ABLK_HELPER_X86
 	select CRYPTO_ALGAPI
+	select CRYPTO_LRW
+	select CRYPTO_XTS
 	help
 	  Use Intel AES-NI instructions for AES algorithm.
 
@@ -588,6 +644,58 @@ config CRYPTO_AES_NI_INTEL
 	  ECB, CBC, LRW, PCBC, XTS. The 64 bit version has additional
 	  acceleration for CTR.
 
+config CRYPTO_AES_ARM
+	tristate "AES cipher algorithms (ARM-asm)"
+	depends on ARM
+	select CRYPTO_ALGAPI
+	select CRYPTO_AES
+	help
+	  Use optimized AES assembler routines for ARM platforms.
+
+	  AES cipher algorithms (FIPS-197). AES uses the Rijndael
+	  algorithm.
+
+	  Rijndael appears to be consistently a very good performer in
+	  both hardware and software across a wide range of computing
+	  environments regardless of its use in feedback or non-feedback
+	  modes. Its key setup time is excellent, and its key agility is
+	  good. Rijndael's very low memory requirements make it very well
+	  suited for restricted-space environments, in which it also
+	  demonstrates excellent performance. Rijndael's operations are
+	  among the easiest to defend against power and timing attacks.
+
+	  The AES specifies three key sizes: 128, 192 and 256 bits
+
+	  See <http://csrc.nist.gov/encryption/aes/> for more information.
+
+config CRYPTO_AES_SPARC64
+	tristate "AES cipher algorithms (SPARC64)"
+	depends on SPARC64
+	select CRYPTO_CRYPTD
+	select CRYPTO_ALGAPI
+	help
+	  Use SPARC64 crypto opcodes for AES algorithm.
+
+	  AES cipher algorithms (FIPS-197). AES uses the Rijndael
+	  algorithm.
+
+	  Rijndael appears to be consistently a very good performer in
+	  both hardware and software across a wide range of computing
+	  environments regardless of its use in feedback or non-feedback
+	  modes. Its key setup time is excellent, and its key agility is
+	  good. Rijndael's very low memory requirements make it very well
+	  suited for restricted-space environments, in which it also
+	  demonstrates excellent performance. Rijndael's operations are
+	  among the easiest to defend against power and timing attacks.
+
+	  The AES specifies three key sizes: 128, 192 and 256 bits
+
+	  See <http://csrc.nist.gov/encryption/aes/> for more information.
+
+	  In addition to AES cipher algorithm support, the acceleration
+	  for some popular block cipher mode is supported too, including
+	  ECB and CBC.
+
 config CRYPTO_ANUBIS
 	tristate "Anubis cipher algorithm"
 	select CRYPTO_ALGAPI
@@ -685,6 +793,22 @@ config CRYPTO_CAMELLIA_X86_64
 	  See also:
 	  <https://info.isl.ntt.co.jp/crypt/eng/camellia/index_s.html>
 
+config CRYPTO_CAMELLIA_SPARC64
+	tristate "Camellia cipher algorithm (SPARC64)"
+	depends on SPARC64
+	depends on CRYPTO
+	select CRYPTO_ALGAPI
+	help
+	  Camellia cipher algorithm module (SPARC64).
+
+	  Camellia is a symmetric key block cipher developed jointly
+	  at NTT and Mitsubishi Electric Corporation.
+
+	  The Camellia specifies three key sizes: 128, 192 and 256 bits.
+
+	  See also:
+	  <https://info.isl.ntt.co.jp/crypt/eng/camellia/index_s.html>
+
 config CRYPTO_CAST5
 	tristate "CAST5 (CAST-128) cipher algorithm"
 	select CRYPTO_ALGAPI
@@ -692,6 +816,20 @@ config CRYPTO_CAST5
 	  The CAST5 encryption algorithm (synonymous with CAST-128) is
 	  described in RFC2144.
 
+config CRYPTO_CAST5_AVX_X86_64
+	tristate "CAST5 (CAST-128) cipher algorithm (x86_64/AVX)"
+	depends on X86 && 64BIT
+	select CRYPTO_ALGAPI
+	select CRYPTO_CRYPTD
+	select CRYPTO_ABLK_HELPER_X86
+	select CRYPTO_CAST5
+	help
+	  The CAST5 encryption algorithm (synonymous with CAST-128) is
+	  described in RFC2144.
+
+	  This module provides the Cast5 cipher algorithm that processes
+	  sixteen blocks parallel using the AVX instruction set.
+
 config CRYPTO_CAST6
 	tristate "CAST6 (CAST-256) cipher algorithm"
 	select CRYPTO_ALGAPI
@@ -699,12 +837,37 @@ config CRYPTO_CAST6
 	  The CAST6 encryption algorithm (synonymous with CAST-256) is
 	  described in RFC2612.
 
+config CRYPTO_CAST6_AVX_X86_64
+	tristate "CAST6 (CAST-256) cipher algorithm (x86_64/AVX)"
+	depends on X86 && 64BIT
+	select CRYPTO_ALGAPI
+	select CRYPTO_CRYPTD
+	select CRYPTO_ABLK_HELPER_X86
+	select CRYPTO_GLUE_HELPER_X86
+	select CRYPTO_CAST6
+	select CRYPTO_LRW
+	select CRYPTO_XTS
+	help
+	  The CAST6 encryption algorithm (synonymous with CAST-256) is
+	  described in RFC2612.
+
+	  This module provides the Cast6 cipher algorithm that processes
+	  eight blocks parallel using the AVX instruction set.
+
 config CRYPTO_DES
 	tristate "DES and Triple DES EDE cipher algorithms"
 	select CRYPTO_ALGAPI
 	help
 	  DES cipher algorithm (FIPS 46-2), and Triple DES EDE (FIPS 46-3).
 
+config CRYPTO_DES_SPARC64
+	tristate "DES and Triple DES EDE cipher algorithms (SPARC64)"
+	select CRYPTO_ALGAPI
+	select CRYPTO_DES
+	help
+	  DES cipher algorithm (FIPS 46-2), and Triple DES EDE (FIPS 46-3),
+	  optimized using SPARC64 crypto opcodes.
+
 config CRYPTO_FCRYPT
 	tristate "FCrypt cipher algorithm"
 	select CRYPTO_ALGAPI
@@ -1008,6 +1171,15 @@ config CRYPTO_LZO
 	help
 	  This is the LZO algorithm.
 
+config CRYPTO_842
+	tristate "842 compression algorithm"
+	depends on CRYPTO_DEV_NX_COMPRESS
+	# 842 uses lzo if the hardware becomes unavailable
+	select LZO_COMPRESS
+	select LZO_DECOMPRESS
+	help
+	  This is the 842 algorithm.
+
 comment "Random Number Generation"
 
 config CRYPTO_ANSI_CPRNG
diff --git a/crypto/Makefile b/crypto/Makefile
index 30f33d6..a301ad2 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -68,8 +68,8 @@ obj-$(CONFIG_CRYPTO_TWOFISH_COMMON) += twofish_common.o
 obj-$(CONFIG_CRYPTO_SERPENT) += serpent_generic.o
 obj-$(CONFIG_CRYPTO_AES) += aes_generic.o
 obj-$(CONFIG_CRYPTO_CAMELLIA) += camellia_generic.o
-obj-$(CONFIG_CRYPTO_CAST5) += cast5.o
-obj-$(CONFIG_CRYPTO_CAST6) += cast6.o
+obj-$(CONFIG_CRYPTO_CAST5) += cast5_generic.o
+obj-$(CONFIG_CRYPTO_CAST6) += cast6_generic.o
 obj-$(CONFIG_CRYPTO_ARC4) += arc4.o
 obj-$(CONFIG_CRYPTO_TEA) += tea.o
 obj-$(CONFIG_CRYPTO_KHAZAD) += khazad.o
@@ -82,6 +82,7 @@ obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += michael_mic.o
 obj-$(CONFIG_CRYPTO_CRC32C) += crc32c.o
 obj-$(CONFIG_CRYPTO_AUTHENC) += authenc.o authencesn.o
 obj-$(CONFIG_CRYPTO_LZO) += lzo.o
+obj-$(CONFIG_CRYPTO_842) += 842.o
 obj-$(CONFIG_CRYPTO_RNG2) += rng.o
 obj-$(CONFIG_CRYPTO_RNG2) += krng.o
 obj-$(CONFIG_CRYPTO_ANSI_CPRNG) += ansi_cprng.o
diff --git a/crypto/aes_generic.c b/crypto/aes_generic.c
index a68c73d..47f2e5c 100644
--- a/crypto/aes_generic.c
+++ b/crypto/aes_generic.c
@@ -1448,7 +1448,6 @@ static struct crypto_alg aes_alg = {
 	.cra_ctxsize		=	sizeof(struct crypto_aes_ctx),
 	.cra_alignmask		=	3,
 	.cra_module		=	THIS_MODULE,
-	.cra_list		=	LIST_HEAD_INIT(aes_alg.cra_list),
 	.cra_u			=	{
 		.cipher = {
 			.cia_min_keysize	=	AES_MIN_KEY_SIZE,
diff --git a/crypto/ansi_cprng.c b/crypto/ansi_cprng.c
index 6ddd99e..c0bb377 100644
--- a/crypto/ansi_cprng.c
+++ b/crypto/ansi_cprng.c
@@ -382,26 +382,6 @@ static int cprng_reset(struct crypto_rng *tfm, u8 *seed, unsigned int slen)
 	return 0;
 }
 
-static struct crypto_alg rng_alg = {
-	.cra_name		= "stdrng",
-	.cra_driver_name	= "ansi_cprng",
-	.cra_priority		= 100,
-	.cra_flags		= CRYPTO_ALG_TYPE_RNG,
-	.cra_ctxsize		= sizeof(struct prng_context),
-	.cra_type		= &crypto_rng_type,
-	.cra_module		= THIS_MODULE,
-	.cra_list		= LIST_HEAD_INIT(rng_alg.cra_list),
-	.cra_init		= cprng_init,
-	.cra_exit		= cprng_exit,
-	.cra_u			= {
-		.rng = {
-			.rng_make_random	= cprng_get_random,
-			.rng_reset		= cprng_reset,
-			.seedsize = DEFAULT_PRNG_KSZ + 2*DEFAULT_BLK_SZ,
-		}
-	}
-};
-
 #ifdef CONFIG_CRYPTO_FIPS
 static int fips_cprng_get_random(struct crypto_rng *tfm, u8 *rdata,
 			    unsigned int dlen)
@@ -438,8 +418,27 @@ static int fips_cprng_reset(struct crypto_rng *tfm, u8 *seed, unsigned int slen)
 out:
 	return rc;
 }
+#endif
 
-static struct crypto_alg fips_rng_alg = {
+static struct crypto_alg rng_algs[] = { {
+	.cra_name		= "stdrng",
+	.cra_driver_name	= "ansi_cprng",
+	.cra_priority		= 100,
+	.cra_flags		= CRYPTO_ALG_TYPE_RNG,
+	.cra_ctxsize		= sizeof(struct prng_context),
+	.cra_type		= &crypto_rng_type,
+	.cra_module		= THIS_MODULE,
+	.cra_init		= cprng_init,
+	.cra_exit		= cprng_exit,
+	.cra_u			= {
+		.rng = {
+			.rng_make_random	= cprng_get_random,
+			.rng_reset		= cprng_reset,
+			.seedsize = DEFAULT_PRNG_KSZ + 2*DEFAULT_BLK_SZ,
+		}
+	}
+#ifdef CONFIG_CRYPTO_FIPS
+}, {
 	.cra_name		= "fips(ansi_cprng)",
 	.cra_driver_name	= "fips_ansi_cprng",
 	.cra_priority		= 300,
@@ -447,7 +446,6 @@ static struct crypto_alg fips_rng_alg = {
 	.cra_ctxsize		= sizeof(struct prng_context),
 	.cra_type		= &crypto_rng_type,
 	.cra_module		= THIS_MODULE,
-	.cra_list		= LIST_HEAD_INIT(rng_alg.cra_list),
 	.cra_init		= cprng_init,
 	.cra_exit		= cprng_exit,
 	.cra_u			= {
@@ -457,33 +455,18 @@ static struct crypto_alg fips_rng_alg = {
 			.seedsize = DEFAULT_PRNG_KSZ + 2*DEFAULT_BLK_SZ,
 		}
 	}
-};
 #endif
+} };
 
 /* Module initalization */
 static int __init prng_mod_init(void)
 {
-	int rc = 0;
-
-	rc = crypto_register_alg(&rng_alg);
-#ifdef CONFIG_CRYPTO_FIPS
-	if (rc)
-		goto out;
-
-	rc = crypto_register_alg(&fips_rng_alg);
-
-out:
-#endif
-	return rc;
+	return crypto_register_algs(rng_algs, ARRAY_SIZE(rng_algs));
 }
 
 static void __exit prng_mod_fini(void)
 {
-	crypto_unregister_alg(&rng_alg);
-#ifdef CONFIG_CRYPTO_FIPS
-	crypto_unregister_alg(&fips_rng_alg);
-#endif
-	return;
+	crypto_unregister_algs(rng_algs, ARRAY_SIZE(rng_algs));
 }
 
 MODULE_LICENSE("GPL");
diff --git a/crypto/anubis.c b/crypto/anubis.c
index 77530d5..008c8a4 100644
--- a/crypto/anubis.c
+++ b/crypto/anubis.c
@@ -678,7 +678,6 @@ static struct crypto_alg anubis_alg = {
 	.cra_ctxsize		=	sizeof (struct anubis_ctx),
 	.cra_alignmask		=	3,
 	.cra_module		=	THIS_MODULE,
-	.cra_list		=	LIST_HEAD_INIT(anubis_alg.cra_list),
 	.cra_u			=	{ .cipher = {
 	.cia_min_keysize	=	ANUBIS_MIN_KEY_SIZE,
 	.cia_max_keysize	=	ANUBIS_MAX_KEY_SIZE,
diff --git a/crypto/blowfish_generic.c b/crypto/blowfish_generic.c
index 6f269b5..8baf544 100644
--- a/crypto/blowfish_generic.c
+++ b/crypto/blowfish_generic.c
@@ -115,7 +115,6 @@ static struct crypto_alg alg = {
 	.cra_ctxsize		=	sizeof(struct bf_ctx),
 	.cra_alignmask		=	3,
 	.cra_module		=	THIS_MODULE,
-	.cra_list		=	LIST_HEAD_INIT(alg.cra_list),
 	.cra_u			=	{ .cipher = {
 	.cia_min_keysize	=	BF_MIN_KEY_SIZE,
 	.cia_max_keysize	=	BF_MAX_KEY_SIZE,
diff --git a/crypto/camellia_generic.c b/crypto/camellia_generic.c
index f7aaaaf..75efa20 100644
--- a/crypto/camellia_generic.c
+++ b/crypto/camellia_generic.c
@@ -1072,7 +1072,6 @@ static struct crypto_alg camellia_alg = {
 	.cra_ctxsize		=	sizeof(struct camellia_ctx),
 	.cra_alignmask		=	3,
 	.cra_module		=	THIS_MODULE,
-	.cra_list		=	LIST_HEAD_INIT(camellia_alg.cra_list),
 	.cra_u			=	{
 		.cipher = {
 			.cia_min_keysize	=	CAMELLIA_MIN_KEY_SIZE,
diff --git a/crypto/cast5.c b/crypto/cast5.c
deleted file mode 100644
index 4a230dd..0000000
--- a/crypto/cast5.c
+++ /dev/null
@@ -1,809 +0,0 @@
-/* Kernel cryptographic api.
-* cast5.c - Cast5 cipher algorithm (rfc2144).
-*
-* Derived from GnuPG implementation of cast5.
-*
-* Major Changes.
-* 	Complete conformance to rfc2144.
-* 	Supports key size from 40 to 128 bits.
-*
-* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
-* Copyright (C) 2003 Kartikey Mahendra Bhatt <kartik_me@hotmail.com>.
-*
-* This program is free software; you can redistribute it and/or modify it
-* under the terms of 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
-*/
-
-
-#include <asm/byteorder.h>
-#include <linux/init.h>
-#include <linux/crypto.h>
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/types.h>
-
-#define CAST5_BLOCK_SIZE 8
-#define CAST5_MIN_KEY_SIZE 5
-#define CAST5_MAX_KEY_SIZE 16
-
-struct cast5_ctx {
-	u32 Km[16];
-	u8 Kr[16];
-	int rr;	/* rr?number of rounds = 16:number of rounds = 12; (rfc 2144) */
-};
-
-
-static const u32 s1[256] = {
-	0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f,
-	0x9c004dd3, 0x6003e540, 0xcf9fc949,
-	0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675, 0x6e63a0e0,
-	0x15c361d2, 0xc2e7661d, 0x22d4ff8e,
-	0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2, 0x43c340d3,
-	0xdf2f8656, 0x887ca41a, 0xa2d2bd2d,
-	0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f, 0x2abe32e1,
-	0xaa54166b, 0x22568e3a, 0xa2d341d0,
-	0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de, 0x97943fac,
-	0x4a97c1d8, 0x527644b7, 0xb5f437a7,
-	0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f, 0x827b68d0,
-	0x90ecf52e, 0x22b0c054, 0xbc8e5935,
-	0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d, 0xb7332290,
-	0xe93b159f, 0xb48ee411, 0x4bff345d,
-	0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, 0xd5b1caad,
-	0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50,
-	0x882240f2, 0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272, 0x564c1d2f,
-	0xc59c5319, 0xb949e354, 0xb04669fe,
-	0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d, 0x57538ad5,
-	0x6a390493, 0xe63d37e0, 0x2a54f6b3,
-	0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, 0x29f9d4d5,
-	0xf61b1891, 0xbb72275e, 0xaa508167,
-	0x38901091, 0xc6b505eb, 0x84c7cb8c, 0x2ad75a0f, 0x874a1427,
-	0xa2d1936b, 0x2ad286af, 0xaa56d291,
-	0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, 0x6c00b32d,
-	0x73e2bb14, 0xa0bebc3c, 0x54623779,
-	0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6, 0x04ee002e,
-	0x89fe78e6, 0x3fab0950, 0x325ff6c2,
-	0x81383f05, 0x6963c5c8, 0x76cb5ad6, 0xd49974c9, 0xca180dcf,
-	0x380782d5, 0xc7fa5cf6, 0x8ac31511,
-	0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, 0x31366241,
-	0x051ef495, 0xaa573b04, 0x4a805d8d,
-	0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e, 0x75c6372b,
-	0x50afd341, 0xa7c13275, 0x915a0bf5,
-	0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82, 0xf7fbf265,
-	0xab85c5f3, 0x1b55db94, 0xaad4e324,
-	0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, 0xeadf55b3,
-	0xd5bd9e98, 0xe31231b2, 0x2ad5ad6c,
-	0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f, 0xaa786bf6,
-	0x22513f1e, 0xaa51a79b, 0x2ad344cc,
-	0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491, 0xb4c332e6,
-	0x032268d4, 0xc9600acc, 0xce387e6d,
-	0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de, 0xe01063da,
-	0x4736f464, 0x5ad328d8, 0xb347cc96,
-	0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, 0xe11f0abc,
-	0xbfc5fe4a, 0xa70aec10, 0xac39570a,
-	0x3f04442f, 0x6188b153, 0xe0397a2e, 0x5727cb79, 0x9ceb418f,
-	0x1cacd68d, 0x2ad37c96, 0x0175cb9d,
-	0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779, 0x4744ead4,
-	0xb11c3274, 0xdd24cb9e, 0x7e1c54bd,
-	0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, 0xd47c27af,
-	0x51c85f4d, 0x56907596, 0xa5bb15e6,
-	0x580304f0, 0xca042cf1, 0x011a37ea, 0x8dbfaadb, 0x35ba3e4a,
-	0x3526ffa0, 0xc37b4d09, 0xbc306ed9,
-	0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, 0x7c63b2cf,
-	0x700b45e1, 0xd5ea50f1, 0x85a92872,
-	0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79, 0x42e04198,
-	0x0cd0ede7, 0x26470db8, 0xf881814c,
-	0x474d6ad7, 0x7c0c5e5c, 0xd1231959, 0x381b7298, 0xf5d2f4db,
-	0xab838653, 0x6e2f1e23, 0x83719c9e,
-	0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, 0x962bda1c,
-	0xe1e696ff, 0xb141ab08, 0x7cca89b9,
-	0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d, 0x427b169c,
-	0x5ac9f049, 0xdd8f0f00, 0x5c8165bf
-};
-static const u32 s2[256] = {
-	0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, 0xfe61cf7a,
-	0xeec5207a, 0x55889c94, 0x72fc0651,
-	0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba, 0x99c430ef,
-	0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3,
-	0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909, 0xdc440086,
-	0xef944459, 0xba83ccb3, 0xe0c3cdfb,
-	0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, 0x01420ddb,
-	0xe4e7ef5b, 0x25a1ff41, 0xe180f806,
-	0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4, 0x98de8b7f,
-	0x77e83f4e, 0x79929269, 0x24fa9f7b,
-	0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f, 0x62143154,
-	0x0d554b63, 0x5d681121, 0xc866c359,
-	0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21, 0x071f6181,
-	0x39f7627f, 0x361e3084, 0xe4eb573b,
-	0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, 0x2701f50c,
-	0x99847ab4, 0xa0e3df79, 0xba6cf38c,
-	0x10843094, 0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f, 0x208cfb6a,
-	0x8f458c74, 0xd9e0a227, 0x4ec73a34,
-	0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d, 0x8a45388c,
-	0x1d804366, 0x721d9bfd, 0xa58684bb,
-	0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, 0xce280ae1,
-	0x27e19ba5, 0xd5a6c252, 0xe49754bd,
-	0xc5d655dd, 0xeb667064, 0x77840b4d, 0xa1b6a801, 0x84db26a9,
-	0xe0b56714, 0x21f043b7, 0xe5d05860,
-	0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, 0xb5625dbf,
-	0x68561be6, 0x83ca6b94, 0x2d6ed23b,
-	0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, 0x33b4a34c,
-	0x397bc8d6, 0x5ee22b95, 0x5f0e5304,
-	0x81ed6f61, 0x20e74364, 0xb45e1378, 0xde18639b, 0x881ca122,
-	0xb96726d1, 0x8049a7e8, 0x22b7da7b,
-	0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, 0x488cb402,
-	0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf,
-	0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9, 0x0beeff53,
-	0xe3214517, 0xb4542835, 0x9f63293c,
-	0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3, 0xf33401c6,
-	0x30a22c95, 0x31a70850, 0x60930f13,
-	0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9, 0xcdff33a6,
-	0xa02b1741, 0x7cbad9a2, 0x2180036f,
-	0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab, 0x80342676,
-	0x25a75e7b, 0xe4e6d1fc, 0x20c710e6,
-	0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4, 0x2ccb49eb,
-	0x846a3bae, 0x8ff77888, 0xee5d60f6,
-	0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43, 0xb3faec54,
-	0x157fd7fa, 0xef8579cc, 0xd152de58,
-	0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, 0x99319ad5,
-	0xc242fa0f, 0xa7e3ebb0, 0xc68e4906,
-	0xb8da230c, 0x80823028, 0xdcdef3c8, 0xd35fb171, 0x088a1bc8,
-	0xbec0c560, 0x61a3c9e8, 0xbca8f54d,
-	0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89, 0x8b1c34bc,
-	0x301e16e6, 0x273be979, 0xb0ffeaa6,
-	0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, 0x43daf65a,
-	0xf7e19798, 0x7619b72f, 0x8f1c9ba4,
-	0xdc8637a0, 0x16a7d3b1, 0x9fc393b7, 0xa7136eeb, 0xc6bcc63e,
-	0x1a513742, 0xef6828bc, 0x520365d6,
-	0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, 0xdb92f2fb,
-	0x5eea29cb, 0x145892f5, 0x91584f7f,
-	0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea, 0x833860d4,
-	0x0d23e0f9, 0x6c387e8a, 0x0ae6d249,
-	0xb284600c, 0xd835731d, 0xdcb1c647, 0xac4c56ea, 0x3ebd81b3,
-	0x230eabb0, 0x6438bc87, 0xf0b5b1fa,
-	0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, 0x649da589,
-	0xa345415e, 0x5c038323, 0x3e5d3bb9,
-	0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef, 0x7160a539,
-	0x73bfbe70, 0x83877605, 0x4523ecf1
-};
-static const u32 s3[256] = {
-	0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, 0x47607fff,
-	0x369fe44b, 0x8c1fc644, 0xaececa90,
-	0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae, 0x920e8806,
-	0xf0ad0548, 0xe13c8d83, 0x927010d5,
-	0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e, 0xb9afa820,
-	0xfade82e0, 0xa067268b, 0x8272792e,
-	0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc, 0x21fffcee,
-	0x825b1bfd, 0x9255c5ed, 0x1257a240,
-	0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e, 0x3373f7bf,
-	0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5,
-	0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f, 0x40fff7c1,
-	0x1fb78dfc, 0x8e6bd2c1, 0x437be59b,
-	0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99, 0xa197c81c,
-	0x4a012d6e, 0xc5884a28, 0xccc36f71,
-	0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, 0x2f7fe850,
-	0xd7c07f7e, 0x02507fbf, 0x5afb9a04,
-	0xa747d2d0, 0x1651192e, 0xaf70bf3e, 0x58c31380, 0x5f98302e,
-	0x727cc3c4, 0x0a0fb402, 0x0f7fef82,
-	0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8, 0x8427f4a0,
-	0x1eac5790, 0x796fb449, 0x8252dc15,
-	0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, 0xfa5d7403,
-	0xe83ec305, 0x4f91751a, 0x925669c2,
-	0x23efe941, 0xa903f12e, 0x60270df2, 0x0276e4b6, 0x94fd6574,
-	0x927985b2, 0x8276dbcb, 0x02778176,
-	0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, 0x842f7d83,
-	0x340ce5c8, 0x96bbb682, 0x93b4b148,
-	0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d, 0x224d1e20,
-	0x8437aa88, 0x7d29dc96, 0x2756d3dc,
-	0x8b907cee, 0xb51fd240, 0xe7c07ce3, 0xe566b4a1, 0xc3e9615e,
-	0x3cf8209d, 0x6094d1e3, 0xcd9ca341,
-	0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, 0xf76cedd9,
-	0xbda8229c, 0x127dadaa, 0x438a074e,
-	0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15, 0x97b03cff,
-	0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51,
-	0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4, 0xdd7ef86a,
-	0x76a2e214, 0xb9a40368, 0x925d958f,
-	0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b, 0x6d498623,
-	0x193cbcfa, 0x27627545, 0x825cf47a,
-	0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392, 0x10428db7,
-	0x8272a972, 0x9270c4a8, 0x127de50b,
-	0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231, 0x428929fb,
-	0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b,
-	0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889, 0x694bcc11,
-	0x236a5cae, 0x12deca4d, 0x2c3f8cc5,
-	0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, 0x494a488c,
-	0xb9b6a80c, 0x5c8f82bc, 0x89d36b45,
-	0x3a609437, 0xec00c9a9, 0x44715253, 0x0a874b49, 0xd773bc40,
-	0x7c34671c, 0x02717ef6, 0x4feb5536,
-	0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d, 0x07478cd1,
-	0x006e1888, 0xa2e53f55, 0xb9e6d4bc,
-	0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, 0x72f87b33,
-	0xabcc4f33, 0x7688c55d, 0x7b00a6b0,
-	0x947b0001, 0x570075d2, 0xf9bb88f8, 0x8942019e, 0x4264a5ff,
-	0x856302e0, 0x72dbd92b, 0xee971b69,
-	0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, 0xcf1febd2,
-	0x61efc8c2, 0xf1ac2571, 0xcc8239c2,
-	0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, 0xf90a5c38,
-	0x0ff0443d, 0x606e6dc6, 0x60543a49,
-	0x5727c148, 0x2be98a1d, 0x8ab41738, 0x20e1be24, 0xaf96da0f,
-	0x68458425, 0x99833be5, 0x600d457d,
-	0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, 0x642b1e31,
-	0x9c305a00, 0x52bce688, 0x1b03588a,
-	0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5, 0xdfef4636,
-	0xa133c501, 0xe9d3531c, 0xee353783
-};
-static const u32 s4[256] = {
-	0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, 0x4a4f7bdb,
-	0x64ad8c57, 0x85510443, 0xfa020ed1,
-	0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120, 0xfd059d43,
-	0x6497b7b1, 0xf3641f63, 0x241e4adf,
-	0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220, 0xfdd30b30,
-	0xc0a5374f, 0x1d2d00d9, 0x24147b15,
-	0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe, 0x1a05645f,
-	0x0c13fefe, 0x081b08ca, 0x05170121,
-	0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701, 0xd2b8ee5f,
-	0x06df4261, 0xbb9e9b8a, 0x7293ea25,
-	0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b, 0x7ed48400,
-	0x547eebe6, 0x446d4ca0, 0x6cf3d6f5,
-	0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93, 0xd3772061,
-	0x11b638e1, 0x72500e03, 0xf80eb2bb,
-	0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, 0xc9335400,
-	0x6920318f, 0x081dbb99, 0xffc304a5,
-	0x4d351805, 0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9, 0xdaec6fea,
-	0x9f926f91, 0x9f46222f, 0x3991467d,
-	0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb, 0x022083b8,
-	0x3fb6180c, 0x18f8931e, 0x281658e6,
-	0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, 0xf32d0a25,
-	0x79098b02, 0xe4eabb81, 0x28123b23,
-	0x69dead38, 0x1574ca16, 0xdf871b62, 0x211c40b7, 0xa51a9ef9,
-	0x0014377b, 0x041e8ac8, 0x09114003,
-	0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, 0x557be8de,
-	0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6,
-	0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327, 0x99afc8b0,
-	0x56c8c391, 0x6b65811c, 0x5e146119,
-	0x6e85cb75, 0xbe07c002, 0xc2325577, 0x893ff4ec, 0x5bbfc92d,
-	0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24,
-	0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, 0xaac9548a,
-	0xeca1d7c7, 0x041afa32, 0x1d16625a,
-	0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031, 0x36cc6fdb,
-	0xc70b8b46, 0xd9e66a48, 0x56e55a79,
-	0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5, 0x8674cde3,
-	0xedda04eb, 0x17a9be04, 0x2c18f4df,
-	0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c, 0x1741a254,
-	0xe5b6a035, 0x213d42f6, 0x2c1c7c26,
-	0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69, 0xd8167fa2,
-	0x0418f2c8, 0x001a96a6, 0x0d1526ab,
-	0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9, 0x8d0dbd86,
-	0x311170a7, 0x3e9b640c, 0xcc3e10d7,
-	0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff, 0x71eae2a1,
-	0x1f9af36e, 0xcfcbd12f, 0xc1de8417,
-	0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, 0xb1c52fca,
-	0xb4be31cd, 0xd8782806, 0x12a3a4e2,
-	0x6f7de532, 0x58fd7eb6, 0xd01ee900, 0x24adffc2, 0xf4990fc5,
-	0x9711aac5, 0x001d7b95, 0x82e5e7d2,
-	0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff, 0x29908415,
-	0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a,
-	0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, 0xd49e2ce7,
-	0x0ce454a9, 0xd60acd86, 0x015f1919,
-	0x77079103, 0xdea03af6, 0x78a8565e, 0xdee356df, 0x21f05cbe,
-	0x8b75e387, 0xb3c50651, 0xb8a5c3ef,
-	0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, 0xafe67afb,
-	0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876,
-	0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367, 0xa99144f8,
-	0x296b299e, 0x492fc295, 0x9266beab,
-	0xb5676e69, 0x9bd3ddda, 0xdf7e052f, 0xdb25701c, 0x1b5e51ee,
-	0xf65324e6, 0x6afce36c, 0x0316cc04,
-	0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, 0x41823979,
-	0x932bcdf6, 0xb657c34d, 0x4edfd282,
-	0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e, 0x13ecf0b0,
-	0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2
-};
-static const u32 s5[256] = {
-	0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911, 0xb86a7fff,
-	0x1dd358f5, 0x44dd9d44, 0x1731167f,
-	0x08fbf1fa, 0xe7f511cc, 0xd2051b00, 0x735aba00, 0x2ab722d8,
-	0x386381cb, 0xacf6243a, 0x69befd7a,
-	0xe6a2e77f, 0xf0c720cd, 0xc4494816, 0xccf5c180, 0x38851640,
-	0x15b0a848, 0xe68b18cb, 0x4caadeff,
-	0x5f480a01, 0x0412b2aa, 0x259814fc, 0x41d0efe2, 0x4e40b48d,
-	0x248eb6fb, 0x8dba1cfe, 0x41a99b02,
-	0x1a550a04, 0xba8f65cb, 0x7251f4e7, 0x95a51725, 0xc106ecd7,
-	0x97a5980a, 0xc539b9aa, 0x4d79fe6a,
-	0xf2f3f763, 0x68af8040, 0xed0c9e56, 0x11b4958b, 0xe1eb5a88,
-	0x8709e6b0, 0xd7e07156, 0x4e29fea7,
-	0x6366e52d, 0x02d1c000, 0xc4ac8e05, 0x9377f571, 0x0c05372a,
-	0x578535f2, 0x2261be02, 0xd642a0c9,
-	0xdf13a280, 0x74b55bd2, 0x682199c0, 0xd421e5ec, 0x53fb3ce8,
-	0xc8adedb3, 0x28a87fc9, 0x3d959981,
-	0x5c1ff900, 0xfe38d399, 0x0c4eff0b, 0x062407ea, 0xaa2f4fb1,
-	0x4fb96976, 0x90c79505, 0xb0a8a774,
-	0xef55a1ff, 0xe59ca2c2, 0xa6b62d27, 0xe66a4263, 0xdf65001f,
-	0x0ec50966, 0xdfdd55bc, 0x29de0655,
-	0x911e739a, 0x17af8975, 0x32c7911c, 0x89f89468, 0x0d01e980,
-	0x524755f4, 0x03b63cc9, 0x0cc844b2,
-	0xbcf3f0aa, 0x87ac36e9, 0xe53a7426, 0x01b3d82b, 0x1a9e7449,
-	0x64ee2d7e, 0xcddbb1da, 0x01c94910,
-	0xb868bf80, 0x0d26f3fd, 0x9342ede7, 0x04a5c284, 0x636737b6,
-	0x50f5b616, 0xf24766e3, 0x8eca36c1,
-	0x136e05db, 0xfef18391, 0xfb887a37, 0xd6e7f7d4, 0xc7fb7dc9,
-	0x3063fcdf, 0xb6f589de, 0xec2941da,
-	0x26e46695, 0xb7566419, 0xf654efc5, 0xd08d58b7, 0x48925401,
-	0xc1bacb7f, 0xe5ff550f, 0xb6083049,
-	0x5bb5d0e8, 0x87d72e5a, 0xab6a6ee1, 0x223a66ce, 0xc62bf3cd,
-	0x9e0885f9, 0x68cb3e47, 0x086c010f,
-	0xa21de820, 0xd18b69de, 0xf3f65777, 0xfa02c3f6, 0x407edac3,
-	0xcbb3d550, 0x1793084d, 0xb0d70eba,
-	0x0ab378d5, 0xd951fb0c, 0xded7da56, 0x4124bbe4, 0x94ca0b56,
-	0x0f5755d1, 0xe0e1e56e, 0x6184b5be,
-	0x580a249f, 0x94f74bc0, 0xe327888e, 0x9f7b5561, 0xc3dc0280,
-	0x05687715, 0x646c6bd7, 0x44904db3,
-	0x66b4f0a3, 0xc0f1648a, 0x697ed5af, 0x49e92ff6, 0x309e374f,
-	0x2cb6356a, 0x85808573, 0x4991f840,
-	0x76f0ae02, 0x083be84d, 0x28421c9a, 0x44489406, 0x736e4cb8,
-	0xc1092910, 0x8bc95fc6, 0x7d869cf4,
-	0x134f616f, 0x2e77118d, 0xb31b2be1, 0xaa90b472, 0x3ca5d717,
-	0x7d161bba, 0x9cad9010, 0xaf462ba2,
-	0x9fe459d2, 0x45d34559, 0xd9f2da13, 0xdbc65487, 0xf3e4f94e,
-	0x176d486f, 0x097c13ea, 0x631da5c7,
-	0x445f7382, 0x175683f4, 0xcdc66a97, 0x70be0288, 0xb3cdcf72,
-	0x6e5dd2f3, 0x20936079, 0x459b80a5,
-	0xbe60e2db, 0xa9c23101, 0xeba5315c, 0x224e42f2, 0x1c5c1572,
-	0xf6721b2c, 0x1ad2fff3, 0x8c25404e,
-	0x324ed72f, 0x4067b7fd, 0x0523138e, 0x5ca3bc78, 0xdc0fd66e,
-	0x75922283, 0x784d6b17, 0x58ebb16e,
-	0x44094f85, 0x3f481d87, 0xfcfeae7b, 0x77b5ff76, 0x8c2302bf,
-	0xaaf47556, 0x5f46b02a, 0x2b092801,
-	0x3d38f5f7, 0x0ca81f36, 0x52af4a8a, 0x66d5e7c0, 0xdf3b0874,
-	0x95055110, 0x1b5ad7a8, 0xf61ed5ad,
-	0x6cf6e479, 0x20758184, 0xd0cefa65, 0x88f7be58, 0x4a046826,
-	0x0ff6f8f3, 0xa09c7f70, 0x5346aba0,
-	0x5ce96c28, 0xe176eda3, 0x6bac307f, 0x376829d2, 0x85360fa9,
-	0x17e3fe2a, 0x24b79767, 0xf5a96b20,
-	0xd6cd2595, 0x68ff1ebf, 0x7555442c, 0xf19f06be, 0xf9e0659a,
-	0xeeb9491d, 0x34010718, 0xbb30cab8,
-	0xe822fe15, 0x88570983, 0x750e6249, 0xda627e55, 0x5e76ffa8,
-	0xb1534546, 0x6d47de08, 0xefe9e7d4
-};
-static const u32 s6[256] = {
-	0xf6fa8f9d, 0x2cac6ce1, 0x4ca34867, 0xe2337f7c, 0x95db08e7,
-	0x016843b4, 0xeced5cbc, 0x325553ac,
-	0xbf9f0960, 0xdfa1e2ed, 0x83f0579d, 0x63ed86b9, 0x1ab6a6b8,
-	0xde5ebe39, 0xf38ff732, 0x8989b138,
-	0x33f14961, 0xc01937bd, 0xf506c6da, 0xe4625e7e, 0xa308ea99,
-	0x4e23e33c, 0x79cbd7cc, 0x48a14367,
-	0xa3149619, 0xfec94bd5, 0xa114174a, 0xeaa01866, 0xa084db2d,
-	0x09a8486f, 0xa888614a, 0x2900af98,
-	0x01665991, 0xe1992863, 0xc8f30c60, 0x2e78ef3c, 0xd0d51932,
-	0xcf0fec14, 0xf7ca07d2, 0xd0a82072,
-	0xfd41197e, 0x9305a6b0, 0xe86be3da, 0x74bed3cd, 0x372da53c,
-	0x4c7f4448, 0xdab5d440, 0x6dba0ec3,
-	0x083919a7, 0x9fbaeed9, 0x49dbcfb0, 0x4e670c53, 0x5c3d9c01,
-	0x64bdb941, 0x2c0e636a, 0xba7dd9cd,
-	0xea6f7388, 0xe70bc762, 0x35f29adb, 0x5c4cdd8d, 0xf0d48d8c,
-	0xb88153e2, 0x08a19866, 0x1ae2eac8,
-	0x284caf89, 0xaa928223, 0x9334be53, 0x3b3a21bf, 0x16434be3,
-	0x9aea3906, 0xefe8c36e, 0xf890cdd9,
-	0x80226dae, 0xc340a4a3, 0xdf7e9c09, 0xa694a807, 0x5b7c5ecc,
-	0x221db3a6, 0x9a69a02f, 0x68818a54,
-	0xceb2296f, 0x53c0843a, 0xfe893655, 0x25bfe68a, 0xb4628abc,
-	0xcf222ebf, 0x25ac6f48, 0xa9a99387,
-	0x53bddb65, 0xe76ffbe7, 0xe967fd78, 0x0ba93563, 0x8e342bc1,
-	0xe8a11be9, 0x4980740d, 0xc8087dfc,
-	0x8de4bf99, 0xa11101a0, 0x7fd37975, 0xda5a26c0, 0xe81f994f,
-	0x9528cd89, 0xfd339fed, 0xb87834bf,
-	0x5f04456d, 0x22258698, 0xc9c4c83b, 0x2dc156be, 0x4f628daa,
-	0x57f55ec5, 0xe2220abe, 0xd2916ebf,
-	0x4ec75b95, 0x24f2c3c0, 0x42d15d99, 0xcd0d7fa0, 0x7b6e27ff,
-	0xa8dc8af0, 0x7345c106, 0xf41e232f,
-	0x35162386, 0xe6ea8926, 0x3333b094, 0x157ec6f2, 0x372b74af,
-	0x692573e4, 0xe9a9d848, 0xf3160289,
-	0x3a62ef1d, 0xa787e238, 0xf3a5f676, 0x74364853, 0x20951063,
-	0x4576698d, 0xb6fad407, 0x592af950,
-	0x36f73523, 0x4cfb6e87, 0x7da4cec0, 0x6c152daa, 0xcb0396a8,
-	0xc50dfe5d, 0xfcd707ab, 0x0921c42f,
-	0x89dff0bb, 0x5fe2be78, 0x448f4f33, 0x754613c9, 0x2b05d08d,
-	0x48b9d585, 0xdc049441, 0xc8098f9b,
-	0x7dede786, 0xc39a3373, 0x42410005, 0x6a091751, 0x0ef3c8a6,
-	0x890072d6, 0x28207682, 0xa9a9f7be,
-	0xbf32679d, 0xd45b5b75, 0xb353fd00, 0xcbb0e358, 0x830f220a,
-	0x1f8fb214, 0xd372cf08, 0xcc3c4a13,
-	0x8cf63166, 0x061c87be, 0x88c98f88, 0x6062e397, 0x47cf8e7a,
-	0xb6c85283, 0x3cc2acfb, 0x3fc06976,
-	0x4e8f0252, 0x64d8314d, 0xda3870e3, 0x1e665459, 0xc10908f0,
-	0x513021a5, 0x6c5b68b7, 0x822f8aa0,
-	0x3007cd3e, 0x74719eef, 0xdc872681, 0x073340d4, 0x7e432fd9,
-	0x0c5ec241, 0x8809286c, 0xf592d891,
-	0x08a930f6, 0x957ef305, 0xb7fbffbd, 0xc266e96f, 0x6fe4ac98,
-	0xb173ecc0, 0xbc60b42a, 0x953498da,
-	0xfba1ae12, 0x2d4bd736, 0x0f25faab, 0xa4f3fceb, 0xe2969123,
-	0x257f0c3d, 0x9348af49, 0x361400bc,
-	0xe8816f4a, 0x3814f200, 0xa3f94043, 0x9c7a54c2, 0xbc704f57,
-	0xda41e7f9, 0xc25ad33a, 0x54f4a084,
-	0xb17f5505, 0x59357cbe, 0xedbd15c8, 0x7f97c5ab, 0xba5ac7b5,
-	0xb6f6deaf, 0x3a479c3a, 0x5302da25,
-	0x653d7e6a, 0x54268d49, 0x51a477ea, 0x5017d55b, 0xd7d25d88,
-	0x44136c76, 0x0404a8c8, 0xb8e5a121,
-	0xb81a928a, 0x60ed5869, 0x97c55b96, 0xeaec991b, 0x29935913,
-	0x01fdb7f1, 0x088e8dfa, 0x9ab6f6f5,
-	0x3b4cbf9f, 0x4a5de3ab, 0xe6051d35, 0xa0e1d855, 0xd36b4cf1,
-	0xf544edeb, 0xb0e93524, 0xbebb8fbd,
-	0xa2d762cf, 0x49c92f54, 0x38b5f331, 0x7128a454, 0x48392905,
-	0xa65b1db8, 0x851c97bd, 0xd675cf2f
-};
-static const u32 s7[256] = {
-	0x85e04019, 0x332bf567, 0x662dbfff, 0xcfc65693, 0x2a8d7f6f,
-	0xab9bc912, 0xde6008a1, 0x2028da1f,
-	0x0227bce7, 0x4d642916, 0x18fac300, 0x50f18b82, 0x2cb2cb11,
-	0xb232e75c, 0x4b3695f2, 0xb28707de,
-	0xa05fbcf6, 0xcd4181e9, 0xe150210c, 0xe24ef1bd, 0xb168c381,
-	0xfde4e789, 0x5c79b0d8, 0x1e8bfd43,
-	0x4d495001, 0x38be4341, 0x913cee1d, 0x92a79c3f, 0x089766be,
-	0xbaeeadf4, 0x1286becf, 0xb6eacb19,
-	0x2660c200, 0x7565bde4, 0x64241f7a, 0x8248dca9, 0xc3b3ad66,
-	0x28136086, 0x0bd8dfa8, 0x356d1cf2,
-	0x107789be, 0xb3b2e9ce, 0x0502aa8f, 0x0bc0351e, 0x166bf52a,
-	0xeb12ff82, 0xe3486911, 0xd34d7516,
-	0x4e7b3aff, 0x5f43671b, 0x9cf6e037, 0x4981ac83, 0x334266ce,
-	0x8c9341b7, 0xd0d854c0, 0xcb3a6c88,
-	0x47bc2829, 0x4725ba37, 0xa66ad22b, 0x7ad61f1e, 0x0c5cbafa,
-	0x4437f107, 0xb6e79962, 0x42d2d816,
-	0x0a961288, 0xe1a5c06e, 0x13749e67, 0x72fc081a, 0xb1d139f7,
-	0xf9583745, 0xcf19df58, 0xbec3f756,
-	0xc06eba30, 0x07211b24, 0x45c28829, 0xc95e317f, 0xbc8ec511,
-	0x38bc46e9, 0xc6e6fa14, 0xbae8584a,
-	0xad4ebc46, 0x468f508b, 0x7829435f, 0xf124183b, 0x821dba9f,
-	0xaff60ff4, 0xea2c4e6d, 0x16e39264,
-	0x92544a8b, 0x009b4fc3, 0xaba68ced, 0x9ac96f78, 0x06a5b79a,
-	0xb2856e6e, 0x1aec3ca9, 0xbe838688,
-	0x0e0804e9, 0x55f1be56, 0xe7e5363b, 0xb3a1f25d, 0xf7debb85,
-	0x61fe033c, 0x16746233, 0x3c034c28,
-	0xda6d0c74, 0x79aac56c, 0x3ce4e1ad, 0x51f0c802, 0x98f8f35a,
-	0x1626a49f, 0xeed82b29, 0x1d382fe3,
-	0x0c4fb99a, 0xbb325778, 0x3ec6d97b, 0x6e77a6a9, 0xcb658b5c,
-	0xd45230c7, 0x2bd1408b, 0x60c03eb7,
-	0xb9068d78, 0xa33754f4, 0xf430c87d, 0xc8a71302, 0xb96d8c32,
-	0xebd4e7be, 0xbe8b9d2d, 0x7979fb06,
-	0xe7225308, 0x8b75cf77, 0x11ef8da4, 0xe083c858, 0x8d6b786f,
-	0x5a6317a6, 0xfa5cf7a0, 0x5dda0033,
-	0xf28ebfb0, 0xf5b9c310, 0xa0eac280, 0x08b9767a, 0xa3d9d2b0,
-	0x79d34217, 0x021a718d, 0x9ac6336a,
-	0x2711fd60, 0x438050e3, 0x069908a8, 0x3d7fedc4, 0x826d2bef,
-	0x4eeb8476, 0x488dcf25, 0x36c9d566,
-	0x28e74e41, 0xc2610aca, 0x3d49a9cf, 0xbae3b9df, 0xb65f8de6,
-	0x92aeaf64, 0x3ac7d5e6, 0x9ea80509,
-	0xf22b017d, 0xa4173f70, 0xdd1e16c3, 0x15e0d7f9, 0x50b1b887,
-	0x2b9f4fd5, 0x625aba82, 0x6a017962,
-	0x2ec01b9c, 0x15488aa9, 0xd716e740, 0x40055a2c, 0x93d29a22,
-	0xe32dbf9a, 0x058745b9, 0x3453dc1e,
-	0xd699296e, 0x496cff6f, 0x1c9f4986, 0xdfe2ed07, 0xb87242d1,
-	0x19de7eae, 0x053e561a, 0x15ad6f8c,
-	0x66626c1c, 0x7154c24c, 0xea082b2a, 0x93eb2939, 0x17dcb0f0,
-	0x58d4f2ae, 0x9ea294fb, 0x52cf564c,
-	0x9883fe66, 0x2ec40581, 0x763953c3, 0x01d6692e, 0xd3a0c108,
-	0xa1e7160e, 0xe4f2dfa6, 0x693ed285,
-	0x74904698, 0x4c2b0edd, 0x4f757656, 0x5d393378, 0xa132234f,
-	0x3d321c5d, 0xc3f5e194, 0x4b269301,
-	0xc79f022f, 0x3c997e7e, 0x5e4f9504, 0x3ffafbbd, 0x76f7ad0e,
-	0x296693f4, 0x3d1fce6f, 0xc61e45be,
-	0xd3b5ab34, 0xf72bf9b7, 0x1b0434c0, 0x4e72b567, 0x5592a33d,
-	0xb5229301, 0xcfd2a87f, 0x60aeb767,
-	0x1814386b, 0x30bcc33d, 0x38a0c07d, 0xfd1606f2, 0xc363519b,
-	0x589dd390, 0x5479f8e6, 0x1cb8d647,
-	0x97fd61a9, 0xea7759f4, 0x2d57539d, 0x569a58cf, 0xe84e63ad,
-	0x462e1b78, 0x6580f87e, 0xf3817914,
-	0x91da55f4, 0x40a230f3, 0xd1988f35, 0xb6e318d2, 0x3ffa50bc,
-	0x3d40f021, 0xc3c0bdae, 0x4958c24c,
-	0x518f36b2, 0x84b1d370, 0x0fedce83, 0x878ddada, 0xf2a279c7,
-	0x94e01be8, 0x90716f4b, 0x954b8aa3
-};
-static const u32 sb8[256] = {
-	0xe216300d, 0xbbddfffc, 0xa7ebdabd, 0x35648095, 0x7789f8b7,
-	0xe6c1121b, 0x0e241600, 0x052ce8b5,
-	0x11a9cfb0, 0xe5952f11, 0xece7990a, 0x9386d174, 0x2a42931c,
-	0x76e38111, 0xb12def3a, 0x37ddddfc,
-	0xde9adeb1, 0x0a0cc32c, 0xbe197029, 0x84a00940, 0xbb243a0f,
-	0xb4d137cf, 0xb44e79f0, 0x049eedfd,
-	0x0b15a15d, 0x480d3168, 0x8bbbde5a, 0x669ded42, 0xc7ece831,
-	0x3f8f95e7, 0x72df191b, 0x7580330d,
-	0x94074251, 0x5c7dcdfa, 0xabbe6d63, 0xaa402164, 0xb301d40a,
-	0x02e7d1ca, 0x53571dae, 0x7a3182a2,
-	0x12a8ddec, 0xfdaa335d, 0x176f43e8, 0x71fb46d4, 0x38129022,
-	0xce949ad4, 0xb84769ad, 0x965bd862,
-	0x82f3d055, 0x66fb9767, 0x15b80b4e, 0x1d5b47a0, 0x4cfde06f,
-	0xc28ec4b8, 0x57e8726e, 0x647a78fc,
-	0x99865d44, 0x608bd593, 0x6c200e03, 0x39dc5ff6, 0x5d0b00a3,
-	0xae63aff2, 0x7e8bd632, 0x70108c0c,
-	0xbbd35049, 0x2998df04, 0x980cf42a, 0x9b6df491, 0x9e7edd53,
-	0x06918548, 0x58cb7e07, 0x3b74ef2e,
-	0x522fffb1, 0xd24708cc, 0x1c7e27cd, 0xa4eb215b, 0x3cf1d2e2,
-	0x19b47a38, 0x424f7618, 0x35856039,
-	0x9d17dee7, 0x27eb35e6, 0xc9aff67b, 0x36baf5b8, 0x09c467cd,
-	0xc18910b1, 0xe11dbf7b, 0x06cd1af8,
-	0x7170c608, 0x2d5e3354, 0xd4de495a, 0x64c6d006, 0xbcc0c62c,
-	0x3dd00db3, 0x708f8f34, 0x77d51b42,
-	0x264f620f, 0x24b8d2bf, 0x15c1b79e, 0x46a52564, 0xf8d7e54e,
-	0x3e378160, 0x7895cda5, 0x859c15a5,
-	0xe6459788, 0xc37bc75f, 0xdb07ba0c, 0x0676a3ab, 0x7f229b1e,
-	0x31842e7b, 0x24259fd7, 0xf8bef472,
-	0x835ffcb8, 0x6df4c1f2, 0x96f5b195, 0xfd0af0fc, 0xb0fe134c,
-	0xe2506d3d, 0x4f9b12ea, 0xf215f225,
-	0xa223736f, 0x9fb4c428, 0x25d04979, 0x34c713f8, 0xc4618187,
-	0xea7a6e98, 0x7cd16efc, 0x1436876c,
-	0xf1544107, 0xbedeee14, 0x56e9af27, 0xa04aa441, 0x3cf7c899,
-	0x92ecbae6, 0xdd67016d, 0x151682eb,
-	0xa842eedf, 0xfdba60b4, 0xf1907b75, 0x20e3030f, 0x24d8c29e,
-	0xe139673b, 0xefa63fb8, 0x71873054,
-	0xb6f2cf3b, 0x9f326442, 0xcb15a4cc, 0xb01a4504, 0xf1e47d8d,
-	0x844a1be5, 0xbae7dfdc, 0x42cbda70,
-	0xcd7dae0a, 0x57e85b7a, 0xd53f5af6, 0x20cf4d8c, 0xcea4d428,
-	0x79d130a4, 0x3486ebfb, 0x33d3cddc,
-	0x77853b53, 0x37effcb5, 0xc5068778, 0xe580b3e6, 0x4e68b8f4,
-	0xc5c8b37e, 0x0d809ea2, 0x398feb7c,
-	0x132a4f94, 0x43b7950e, 0x2fee7d1c, 0x223613bd, 0xdd06caa2,
-	0x37df932b, 0xc4248289, 0xacf3ebc3,
-	0x5715f6b7, 0xef3478dd, 0xf267616f, 0xc148cbe4, 0x9052815e,
-	0x5e410fab, 0xb48a2465, 0x2eda7fa4,
-	0xe87b40e4, 0xe98ea084, 0x5889e9e1, 0xefd390fc, 0xdd07d35b,
-	0xdb485694, 0x38d7e5b2, 0x57720101,
-	0x730edebc, 0x5b643113, 0x94917e4f, 0x503c2fba, 0x646f1282,
-	0x7523d24a, 0xe0779695, 0xf9c17a8f,
-	0x7a5b2121, 0xd187b896, 0x29263a4d, 0xba510cdf, 0x81f47c9f,
-	0xad1163ed, 0xea7b5965, 0x1a00726e,
-	0x11403092, 0x00da6d77, 0x4a0cdd61, 0xad1f4603, 0x605bdfb0,
-	0x9eedc364, 0x22ebe6a8, 0xcee7d28a,
-	0xa0e736a0, 0x5564a6b9, 0x10853209, 0xc7eb8f37, 0x2de705ca,
-	0x8951570f, 0xdf09822b, 0xbd691a6c,
-	0xaa12e4f2, 0x87451c0f, 0xe0f6a27a, 0x3ada4819, 0x4cf1764f,
-	0x0d771c2b, 0x67cdb156, 0x350d8384,
-	0x5938fa0f, 0x42399ef3, 0x36997b07, 0x0e84093d, 0x4aa93e61,
-	0x8360d87b, 0x1fa98b0c, 0x1149382c,
-	0xe97625a5, 0x0614d1b7, 0x0e25244b, 0x0c768347, 0x589e8d82,
-	0x0d2059d1, 0xa466bb1e, 0xf8da0a82,
-	0x04f19130, 0xba6e4ec0, 0x99265164, 0x1ee7230d, 0x50b2ad80,
-	0xeaee6801, 0x8db2a283, 0xea8bf59e
-};
-
-#define F1(D, m, r)  ((I = ((m) + (D))), (I = rol32(I, (r))),   \
-    (((s1[I >> 24] ^ s2[(I>>16)&0xff]) - s3[(I>>8)&0xff]) + s4[I&0xff]))
-#define F2(D, m, r)  ((I = ((m) ^ (D))), (I = rol32(I, (r))),   \
-    (((s1[I >> 24] - s2[(I>>16)&0xff]) + s3[(I>>8)&0xff]) ^ s4[I&0xff]))
-#define F3(D, m, r)  ((I = ((m) - (D))), (I = rol32(I, (r))),   \
-    (((s1[I >> 24] + s2[(I>>16)&0xff]) ^ s3[(I>>8)&0xff]) - s4[I&0xff]))
-
-
-static void cast5_encrypt(struct crypto_tfm *tfm, u8 *outbuf, const u8 *inbuf)
-{
-	struct cast5_ctx *c = crypto_tfm_ctx(tfm);
-	const __be32 *src = (const __be32 *)inbuf;
-	__be32 *dst = (__be32 *)outbuf;
-	u32 l, r, t;
-	u32 I;			/* used by the Fx macros */
-	u32 *Km;
-	u8 *Kr;
-
-	Km = c->Km;
-	Kr = c->Kr;
-
-	/* (L0,R0) <-- (m1...m64).  (Split the plaintext into left and
-	 * right 32-bit halves L0 = m1...m32 and R0 = m33...m64.)
-	 */
-	l = be32_to_cpu(src[0]);
-	r = be32_to_cpu(src[1]);
-
-	/* (16 rounds) for i from 1 to 16, compute Li and Ri as follows:
-	 *  Li = Ri-1;
-	 *  Ri = Li-1 ^ f(Ri-1,Kmi,Kri), where f is defined in Section 2.2
-	 * Rounds 1, 4, 7, 10, 13, and 16 use f function Type 1.
-	 * Rounds 2, 5, 8, 11, and 14 use f function Type 2.
-	 * Rounds 3, 6, 9, 12, and 15 use f function Type 3.
-	 */
-
-	t = l; l = r; r = t ^ F1(r, Km[0], Kr[0]);
-	t = l; l = r; r = t ^ F2(r, Km[1], Kr[1]);
-	t = l; l = r; r = t ^ F3(r, Km[2], Kr[2]);
-	t = l; l = r; r = t ^ F1(r, Km[3], Kr[3]);
-	t = l; l = r; r = t ^ F2(r, Km[4], Kr[4]);
-	t = l; l = r; r = t ^ F3(r, Km[5], Kr[5]);
-	t = l; l = r; r = t ^ F1(r, Km[6], Kr[6]);
-	t = l; l = r; r = t ^ F2(r, Km[7], Kr[7]);
-	t = l; l = r; r = t ^ F3(r, Km[8], Kr[8]);
-	t = l; l = r; r = t ^ F1(r, Km[9], Kr[9]);
-	t = l; l = r; r = t ^ F2(r, Km[10], Kr[10]);
-	t = l; l = r; r = t ^ F3(r, Km[11], Kr[11]);
-	if (!(c->rr)) {
-		t = l; l = r; r = t ^ F1(r, Km[12], Kr[12]);
-		t = l; l = r; r = t ^ F2(r, Km[13], Kr[13]);
-		t = l; l = r; r = t ^ F3(r, Km[14], Kr[14]);
-		t = l; l = r; r = t ^ F1(r, Km[15], Kr[15]);
-	}
-
-	/* c1...c64 <-- (R16,L16).  (Exchange final blocks L16, R16 and
-	 *  concatenate to form the ciphertext.) */
-	dst[0] = cpu_to_be32(r);
-	dst[1] = cpu_to_be32(l);
-}
-
-static void cast5_decrypt(struct crypto_tfm *tfm, u8 *outbuf, const u8 *inbuf)
-{
-	struct cast5_ctx *c = crypto_tfm_ctx(tfm);
-	const __be32 *src = (const __be32 *)inbuf;
-	__be32 *dst = (__be32 *)outbuf;
-	u32 l, r, t;
-	u32 I;
-	u32 *Km;
-	u8 *Kr;
-
-	Km = c->Km;
-	Kr = c->Kr;
-
-	l = be32_to_cpu(src[0]);
-	r = be32_to_cpu(src[1]);
-
-	if (!(c->rr)) {
-		t = l; l = r; r = t ^ F1(r, Km[15], Kr[15]);
-		t = l; l = r; r = t ^ F3(r, Km[14], Kr[14]);
-		t = l; l = r; r = t ^ F2(r, Km[13], Kr[13]);
-		t = l; l = r; r = t ^ F1(r, Km[12], Kr[12]);
-	}
-	t = l; l = r; r = t ^ F3(r, Km[11], Kr[11]);
-	t = l; l = r; r = t ^ F2(r, Km[10], Kr[10]);
-	t = l; l = r; r = t ^ F1(r, Km[9], Kr[9]);
-	t = l; l = r; r = t ^ F3(r, Km[8], Kr[8]);
-	t = l; l = r; r = t ^ F2(r, Km[7], Kr[7]);
-	t = l; l = r; r = t ^ F1(r, Km[6], Kr[6]);
-	t = l; l = r; r = t ^ F3(r, Km[5], Kr[5]);
-	t = l; l = r; r = t ^ F2(r, Km[4], Kr[4]);
-	t = l; l = r; r = t ^ F1(r, Km[3], Kr[3]);
-	t = l; l = r; r = t ^ F3(r, Km[2], Kr[2]);
-	t = l; l = r; r = t ^ F2(r, Km[1], Kr[1]);
-	t = l; l = r; r = t ^ F1(r, Km[0], Kr[0]);
-
-	dst[0] = cpu_to_be32(r);
-	dst[1] = cpu_to_be32(l);
-}
-
-static void key_schedule(u32 *x, u32 *z, u32 *k)
-{
-
-#define xi(i)   ((x[(i)/4] >> (8*(3-((i)%4)))) & 0xff)
-#define zi(i)   ((z[(i)/4] >> (8*(3-((i)%4)))) & 0xff)
-
-	z[0] = x[0] ^ s5[xi(13)] ^ s6[xi(15)] ^ s7[xi(12)] ^ sb8[xi(14)] ^
-	    s7[xi(8)];
-	z[1] = x[2] ^ s5[zi(0)] ^ s6[zi(2)] ^ s7[zi(1)] ^ sb8[zi(3)] ^
-	    sb8[xi(10)];
-	z[2] = x[3] ^ s5[zi(7)] ^ s6[zi(6)] ^ s7[zi(5)] ^ sb8[zi(4)] ^
-	    s5[xi(9)];
-	z[3] = x[1] ^ s5[zi(10)] ^ s6[zi(9)] ^ s7[zi(11)] ^ sb8[zi(8)] ^
-	    s6[xi(11)];
-	k[0] = s5[zi(8)] ^ s6[zi(9)] ^ s7[zi(7)] ^ sb8[zi(6)] ^ s5[zi(2)];
-	k[1] = s5[zi(10)] ^ s6[zi(11)] ^ s7[zi(5)] ^ sb8[zi(4)] ^
-	    s6[zi(6)];
-	k[2] = s5[zi(12)] ^ s6[zi(13)] ^ s7[zi(3)] ^ sb8[zi(2)] ^
-	    s7[zi(9)];
-	k[3] = s5[zi(14)] ^ s6[zi(15)] ^ s7[zi(1)] ^ sb8[zi(0)] ^
-	    sb8[zi(12)];
-
-	x[0] = z[2] ^ s5[zi(5)] ^ s6[zi(7)] ^ s7[zi(4)] ^ sb8[zi(6)] ^
-	    s7[zi(0)];
-	x[1] = z[0] ^ s5[xi(0)] ^ s6[xi(2)] ^ s7[xi(1)] ^ sb8[xi(3)] ^
-	    sb8[zi(2)];
-	x[2] = z[1] ^ s5[xi(7)] ^ s6[xi(6)] ^ s7[xi(5)] ^ sb8[xi(4)] ^
-	    s5[zi(1)];
-	x[3] = z[3] ^ s5[xi(10)] ^ s6[xi(9)] ^ s7[xi(11)] ^ sb8[xi(8)] ^
-	    s6[zi(3)];
-	k[4] = s5[xi(3)] ^ s6[xi(2)] ^ s7[xi(12)] ^ sb8[xi(13)] ^
-	    s5[xi(8)];
-	k[5] = s5[xi(1)] ^ s6[xi(0)] ^ s7[xi(14)] ^ sb8[xi(15)] ^
-	    s6[xi(13)];
-	k[6] = s5[xi(7)] ^ s6[xi(6)] ^ s7[xi(8)] ^ sb8[xi(9)] ^ s7[xi(3)];
-	k[7] = s5[xi(5)] ^ s6[xi(4)] ^ s7[xi(10)] ^ sb8[xi(11)] ^
-	    sb8[xi(7)];
-
-	z[0] = x[0] ^ s5[xi(13)] ^ s6[xi(15)] ^ s7[xi(12)] ^ sb8[xi(14)] ^
-	    s7[xi(8)];
-	z[1] = x[2] ^ s5[zi(0)] ^ s6[zi(2)] ^ s7[zi(1)] ^ sb8[zi(3)] ^
-	    sb8[xi(10)];
-	z[2] = x[3] ^ s5[zi(7)] ^ s6[zi(6)] ^ s7[zi(5)] ^ sb8[zi(4)] ^
-	    s5[xi(9)];
-	z[3] = x[1] ^ s5[zi(10)] ^ s6[zi(9)] ^ s7[zi(11)] ^ sb8[zi(8)] ^
-	    s6[xi(11)];
-	k[8] = s5[zi(3)] ^ s6[zi(2)] ^ s7[zi(12)] ^ sb8[zi(13)] ^
-	    s5[zi(9)];
-	k[9] = s5[zi(1)] ^ s6[zi(0)] ^ s7[zi(14)] ^ sb8[zi(15)] ^
-	    s6[zi(12)];
-	k[10] = s5[zi(7)] ^ s6[zi(6)] ^ s7[zi(8)] ^ sb8[zi(9)] ^ s7[zi(2)];
-	k[11] = s5[zi(5)] ^ s6[zi(4)] ^ s7[zi(10)] ^ sb8[zi(11)] ^
-	    sb8[zi(6)];
-
-	x[0] = z[2] ^ s5[zi(5)] ^ s6[zi(7)] ^ s7[zi(4)] ^ sb8[zi(6)] ^
-	    s7[zi(0)];
-	x[1] = z[0] ^ s5[xi(0)] ^ s6[xi(2)] ^ s7[xi(1)] ^ sb8[xi(3)] ^
-	    sb8[zi(2)];
-	x[2] = z[1] ^ s5[xi(7)] ^ s6[xi(6)] ^ s7[xi(5)] ^ sb8[xi(4)] ^
-	    s5[zi(1)];
-	x[3] = z[3] ^ s5[xi(10)] ^ s6[xi(9)] ^ s7[xi(11)] ^ sb8[xi(8)] ^
-	    s6[zi(3)];
-	k[12] = s5[xi(8)] ^ s6[xi(9)] ^ s7[xi(7)] ^ sb8[xi(6)] ^ s5[xi(3)];
-	k[13] = s5[xi(10)] ^ s6[xi(11)] ^ s7[xi(5)] ^ sb8[xi(4)] ^
-	    s6[xi(7)];
-	k[14] = s5[xi(12)] ^ s6[xi(13)] ^ s7[xi(3)] ^ sb8[xi(2)] ^
-	    s7[xi(8)];
-	k[15] = s5[xi(14)] ^ s6[xi(15)] ^ s7[xi(1)] ^ sb8[xi(0)] ^
-	    sb8[xi(13)];
-
-#undef xi
-#undef zi
-}
-
-
-static int cast5_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned key_len)
-{
-	struct cast5_ctx *c = crypto_tfm_ctx(tfm);
-	int i;
-	u32 x[4];
-	u32 z[4];
-	u32 k[16];
-	__be32 p_key[4];
-
-	c->rr = key_len <= 10 ? 1 : 0;
-
-	memset(p_key, 0, 16);
-	memcpy(p_key, key, key_len);
-
-
-	x[0] = be32_to_cpu(p_key[0]);
-	x[1] = be32_to_cpu(p_key[1]);
-	x[2] = be32_to_cpu(p_key[2]);
-	x[3] = be32_to_cpu(p_key[3]);
-
-	key_schedule(x, z, k);
-	for (i = 0; i < 16; i++)
-		c->Km[i] = k[i];
-	key_schedule(x, z, k);
-	for (i = 0; i < 16; i++)
-		c->Kr[i] = k[i] & 0x1f;
-	return 0;
-}
-
-static struct crypto_alg alg = {
-	.cra_name 	= "cast5",
-	.cra_flags 	= CRYPTO_ALG_TYPE_CIPHER,
-	.cra_blocksize 	= CAST5_BLOCK_SIZE,
-	.cra_ctxsize 	= sizeof(struct cast5_ctx),
-	.cra_alignmask	= 3,
-	.cra_module 	= THIS_MODULE,
-	.cra_list 	= LIST_HEAD_INIT(alg.cra_list),
-	.cra_u 		= {
-		.cipher = {
-			.cia_min_keysize = CAST5_MIN_KEY_SIZE,
-			.cia_max_keysize = CAST5_MAX_KEY_SIZE,
-			.cia_setkey = cast5_setkey,
-			.cia_encrypt = cast5_encrypt,
-			.cia_decrypt = cast5_decrypt
-		}
-	}
-};
-
-static int __init cast5_mod_init(void)
-{
-	return crypto_register_alg(&alg);
-}
-
-static void __exit cast5_mod_fini(void)
-{
-	crypto_unregister_alg(&alg);
-}
-
-module_init(cast5_mod_init);
-module_exit(cast5_mod_fini);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Cast5 Cipher Algorithm");
-
diff --git a/crypto/cast5_generic.c b/crypto/cast5_generic.c
new file mode 100644
index 0000000..bc525db
--- /dev/null
+++ b/crypto/cast5_generic.c
@@ -0,0 +1,821 @@
+/* Kernel cryptographic api.
+* cast5.c - Cast5 cipher algorithm (rfc2144).
+*
+* Derived from GnuPG implementation of cast5.
+*
+* Major Changes.
+*	Complete conformance to rfc2144.
+*	Supports key size from 40 to 128 bits.
+*
+* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+* Copyright (C) 2003 Kartikey Mahendra Bhatt <kartik_me@hotmail.com>.
+*
+* This program is free software; you can redistribute it and/or modify it
+* under the terms of 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+*/
+
+
+#include <asm/byteorder.h>
+#include <linux/init.h>
+#include <linux/crypto.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <crypto/cast5.h>
+
+
+const u32 cast5_s1[256] = {
+	0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f,
+	0x9c004dd3, 0x6003e540, 0xcf9fc949,
+	0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675, 0x6e63a0e0,
+	0x15c361d2, 0xc2e7661d, 0x22d4ff8e,
+	0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2, 0x43c340d3,
+	0xdf2f8656, 0x887ca41a, 0xa2d2bd2d,
+	0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f, 0x2abe32e1,
+	0xaa54166b, 0x22568e3a, 0xa2d341d0,
+	0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de, 0x97943fac,
+	0x4a97c1d8, 0x527644b7, 0xb5f437a7,
+	0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f, 0x827b68d0,
+	0x90ecf52e, 0x22b0c054, 0xbc8e5935,
+	0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d, 0xb7332290,
+	0xe93b159f, 0xb48ee411, 0x4bff345d,
+	0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, 0xd5b1caad,
+	0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50,
+	0x882240f2, 0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272, 0x564c1d2f,
+	0xc59c5319, 0xb949e354, 0xb04669fe,
+	0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d, 0x57538ad5,
+	0x6a390493, 0xe63d37e0, 0x2a54f6b3,
+	0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, 0x29f9d4d5,
+	0xf61b1891, 0xbb72275e, 0xaa508167,
+	0x38901091, 0xc6b505eb, 0x84c7cb8c, 0x2ad75a0f, 0x874a1427,
+	0xa2d1936b, 0x2ad286af, 0xaa56d291,
+	0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, 0x6c00b32d,
+	0x73e2bb14, 0xa0bebc3c, 0x54623779,
+	0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6, 0x04ee002e,
+	0x89fe78e6, 0x3fab0950, 0x325ff6c2,
+	0x81383f05, 0x6963c5c8, 0x76cb5ad6, 0xd49974c9, 0xca180dcf,
+	0x380782d5, 0xc7fa5cf6, 0x8ac31511,
+	0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, 0x31366241,
+	0x051ef495, 0xaa573b04, 0x4a805d8d,
+	0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e, 0x75c6372b,
+	0x50afd341, 0xa7c13275, 0x915a0bf5,
+	0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82, 0xf7fbf265,
+	0xab85c5f3, 0x1b55db94, 0xaad4e324,
+	0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, 0xeadf55b3,
+	0xd5bd9e98, 0xe31231b2, 0x2ad5ad6c,
+	0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f, 0xaa786bf6,
+	0x22513f1e, 0xaa51a79b, 0x2ad344cc,
+	0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491, 0xb4c332e6,
+	0x032268d4, 0xc9600acc, 0xce387e6d,
+	0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de, 0xe01063da,
+	0x4736f464, 0x5ad328d8, 0xb347cc96,
+	0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, 0xe11f0abc,
+	0xbfc5fe4a, 0xa70aec10, 0xac39570a,
+	0x3f04442f, 0x6188b153, 0xe0397a2e, 0x5727cb79, 0x9ceb418f,
+	0x1cacd68d, 0x2ad37c96, 0x0175cb9d,
+	0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779, 0x4744ead4,
+	0xb11c3274, 0xdd24cb9e, 0x7e1c54bd,
+	0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, 0xd47c27af,
+	0x51c85f4d, 0x56907596, 0xa5bb15e6,
+	0x580304f0, 0xca042cf1, 0x011a37ea, 0x8dbfaadb, 0x35ba3e4a,
+	0x3526ffa0, 0xc37b4d09, 0xbc306ed9,
+	0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, 0x7c63b2cf,
+	0x700b45e1, 0xd5ea50f1, 0x85a92872,
+	0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79, 0x42e04198,
+	0x0cd0ede7, 0x26470db8, 0xf881814c,
+	0x474d6ad7, 0x7c0c5e5c, 0xd1231959, 0x381b7298, 0xf5d2f4db,
+	0xab838653, 0x6e2f1e23, 0x83719c9e,
+	0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, 0x962bda1c,
+	0xe1e696ff, 0xb141ab08, 0x7cca89b9,
+	0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d, 0x427b169c,
+	0x5ac9f049, 0xdd8f0f00, 0x5c8165bf
+};
+EXPORT_SYMBOL_GPL(cast5_s1);
+const u32 cast5_s2[256] = {
+	0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, 0xfe61cf7a,
+	0xeec5207a, 0x55889c94, 0x72fc0651,
+	0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba, 0x99c430ef,
+	0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3,
+	0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909, 0xdc440086,
+	0xef944459, 0xba83ccb3, 0xe0c3cdfb,
+	0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, 0x01420ddb,
+	0xe4e7ef5b, 0x25a1ff41, 0xe180f806,
+	0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4, 0x98de8b7f,
+	0x77e83f4e, 0x79929269, 0x24fa9f7b,
+	0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f, 0x62143154,
+	0x0d554b63, 0x5d681121, 0xc866c359,
+	0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21, 0x071f6181,
+	0x39f7627f, 0x361e3084, 0xe4eb573b,
+	0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, 0x2701f50c,
+	0x99847ab4, 0xa0e3df79, 0xba6cf38c,
+	0x10843094, 0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f, 0x208cfb6a,
+	0x8f458c74, 0xd9e0a227, 0x4ec73a34,
+	0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d, 0x8a45388c,
+	0x1d804366, 0x721d9bfd, 0xa58684bb,
+	0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, 0xce280ae1,
+	0x27e19ba5, 0xd5a6c252, 0xe49754bd,
+	0xc5d655dd, 0xeb667064, 0x77840b4d, 0xa1b6a801, 0x84db26a9,
+	0xe0b56714, 0x21f043b7, 0xe5d05860,
+	0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, 0xb5625dbf,
+	0x68561be6, 0x83ca6b94, 0x2d6ed23b,
+	0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, 0x33b4a34c,
+	0x397bc8d6, 0x5ee22b95, 0x5f0e5304,
+	0x81ed6f61, 0x20e74364, 0xb45e1378, 0xde18639b, 0x881ca122,
+	0xb96726d1, 0x8049a7e8, 0x22b7da7b,
+	0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, 0x488cb402,
+	0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf,
+	0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9, 0x0beeff53,
+	0xe3214517, 0xb4542835, 0x9f63293c,
+	0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3, 0xf33401c6,
+	0x30a22c95, 0x31a70850, 0x60930f13,
+	0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9, 0xcdff33a6,
+	0xa02b1741, 0x7cbad9a2, 0x2180036f,
+	0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab, 0x80342676,
+	0x25a75e7b, 0xe4e6d1fc, 0x20c710e6,
+	0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4, 0x2ccb49eb,
+	0x846a3bae, 0x8ff77888, 0xee5d60f6,
+	0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43, 0xb3faec54,
+	0x157fd7fa, 0xef8579cc, 0xd152de58,
+	0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, 0x99319ad5,
+	0xc242fa0f, 0xa7e3ebb0, 0xc68e4906,
+	0xb8da230c, 0x80823028, 0xdcdef3c8, 0xd35fb171, 0x088a1bc8,
+	0xbec0c560, 0x61a3c9e8, 0xbca8f54d,
+	0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89, 0x8b1c34bc,
+	0x301e16e6, 0x273be979, 0xb0ffeaa6,
+	0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, 0x43daf65a,
+	0xf7e19798, 0x7619b72f, 0x8f1c9ba4,
+	0xdc8637a0, 0x16a7d3b1, 0x9fc393b7, 0xa7136eeb, 0xc6bcc63e,
+	0x1a513742, 0xef6828bc, 0x520365d6,
+	0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, 0xdb92f2fb,
+	0x5eea29cb, 0x145892f5, 0x91584f7f,
+	0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea, 0x833860d4,
+	0x0d23e0f9, 0x6c387e8a, 0x0ae6d249,
+	0xb284600c, 0xd835731d, 0xdcb1c647, 0xac4c56ea, 0x3ebd81b3,
+	0x230eabb0, 0x6438bc87, 0xf0b5b1fa,
+	0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, 0x649da589,
+	0xa345415e, 0x5c038323, 0x3e5d3bb9,
+	0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef, 0x7160a539,
+	0x73bfbe70, 0x83877605, 0x4523ecf1
+};
+EXPORT_SYMBOL_GPL(cast5_s2);
+const u32 cast5_s3[256] = {
+	0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, 0x47607fff,
+	0x369fe44b, 0x8c1fc644, 0xaececa90,
+	0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae, 0x920e8806,
+	0xf0ad0548, 0xe13c8d83, 0x927010d5,
+	0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e, 0xb9afa820,
+	0xfade82e0, 0xa067268b, 0x8272792e,
+	0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc, 0x21fffcee,
+	0x825b1bfd, 0x9255c5ed, 0x1257a240,
+	0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e, 0x3373f7bf,
+	0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5,
+	0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f, 0x40fff7c1,
+	0x1fb78dfc, 0x8e6bd2c1, 0x437be59b,
+	0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99, 0xa197c81c,
+	0x4a012d6e, 0xc5884a28, 0xccc36f71,
+	0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, 0x2f7fe850,
+	0xd7c07f7e, 0x02507fbf, 0x5afb9a04,
+	0xa747d2d0, 0x1651192e, 0xaf70bf3e, 0x58c31380, 0x5f98302e,
+	0x727cc3c4, 0x0a0fb402, 0x0f7fef82,
+	0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8, 0x8427f4a0,
+	0x1eac5790, 0x796fb449, 0x8252dc15,
+	0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, 0xfa5d7403,
+	0xe83ec305, 0x4f91751a, 0x925669c2,
+	0x23efe941, 0xa903f12e, 0x60270df2, 0x0276e4b6, 0x94fd6574,
+	0x927985b2, 0x8276dbcb, 0x02778176,
+	0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, 0x842f7d83,
+	0x340ce5c8, 0x96bbb682, 0x93b4b148,
+	0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d, 0x224d1e20,
+	0x8437aa88, 0x7d29dc96, 0x2756d3dc,
+	0x8b907cee, 0xb51fd240, 0xe7c07ce3, 0xe566b4a1, 0xc3e9615e,
+	0x3cf8209d, 0x6094d1e3, 0xcd9ca341,
+	0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, 0xf76cedd9,
+	0xbda8229c, 0x127dadaa, 0x438a074e,
+	0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15, 0x97b03cff,
+	0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51,
+	0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4, 0xdd7ef86a,
+	0x76a2e214, 0xb9a40368, 0x925d958f,
+	0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b, 0x6d498623,
+	0x193cbcfa, 0x27627545, 0x825cf47a,
+	0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392, 0x10428db7,
+	0x8272a972, 0x9270c4a8, 0x127de50b,
+	0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231, 0x428929fb,
+	0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b,
+	0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889, 0x694bcc11,
+	0x236a5cae, 0x12deca4d, 0x2c3f8cc5,
+	0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, 0x494a488c,
+	0xb9b6a80c, 0x5c8f82bc, 0x89d36b45,
+	0x3a609437, 0xec00c9a9, 0x44715253, 0x0a874b49, 0xd773bc40,
+	0x7c34671c, 0x02717ef6, 0x4feb5536,
+	0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d, 0x07478cd1,
+	0x006e1888, 0xa2e53f55, 0xb9e6d4bc,
+	0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, 0x72f87b33,
+	0xabcc4f33, 0x7688c55d, 0x7b00a6b0,
+	0x947b0001, 0x570075d2, 0xf9bb88f8, 0x8942019e, 0x4264a5ff,
+	0x856302e0, 0x72dbd92b, 0xee971b69,
+	0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, 0xcf1febd2,
+	0x61efc8c2, 0xf1ac2571, 0xcc8239c2,
+	0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, 0xf90a5c38,
+	0x0ff0443d, 0x606e6dc6, 0x60543a49,
+	0x5727c148, 0x2be98a1d, 0x8ab41738, 0x20e1be24, 0xaf96da0f,
+	0x68458425, 0x99833be5, 0x600d457d,
+	0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, 0x642b1e31,
+	0x9c305a00, 0x52bce688, 0x1b03588a,
+	0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5, 0xdfef4636,
+	0xa133c501, 0xe9d3531c, 0xee353783
+};
+EXPORT_SYMBOL_GPL(cast5_s3);
+const u32 cast5_s4[256] = {
+	0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, 0x4a4f7bdb,
+	0x64ad8c57, 0x85510443, 0xfa020ed1,
+	0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120, 0xfd059d43,
+	0x6497b7b1, 0xf3641f63, 0x241e4adf,
+	0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220, 0xfdd30b30,
+	0xc0a5374f, 0x1d2d00d9, 0x24147b15,
+	0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe, 0x1a05645f,
+	0x0c13fefe, 0x081b08ca, 0x05170121,
+	0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701, 0xd2b8ee5f,
+	0x06df4261, 0xbb9e9b8a, 0x7293ea25,
+	0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b, 0x7ed48400,
+	0x547eebe6, 0x446d4ca0, 0x6cf3d6f5,
+	0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93, 0xd3772061,
+	0x11b638e1, 0x72500e03, 0xf80eb2bb,
+	0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, 0xc9335400,
+	0x6920318f, 0x081dbb99, 0xffc304a5,
+	0x4d351805, 0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9, 0xdaec6fea,
+	0x9f926f91, 0x9f46222f, 0x3991467d,
+	0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb, 0x022083b8,
+	0x3fb6180c, 0x18f8931e, 0x281658e6,
+	0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, 0xf32d0a25,
+	0x79098b02, 0xe4eabb81, 0x28123b23,
+	0x69dead38, 0x1574ca16, 0xdf871b62, 0x211c40b7, 0xa51a9ef9,
+	0x0014377b, 0x041e8ac8, 0x09114003,
+	0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, 0x557be8de,
+	0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6,
+	0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327, 0x99afc8b0,
+	0x56c8c391, 0x6b65811c, 0x5e146119,
+	0x6e85cb75, 0xbe07c002, 0xc2325577, 0x893ff4ec, 0x5bbfc92d,
+	0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24,
+	0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, 0xaac9548a,
+	0xeca1d7c7, 0x041afa32, 0x1d16625a,
+	0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031, 0x36cc6fdb,
+	0xc70b8b46, 0xd9e66a48, 0x56e55a79,
+	0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5, 0x8674cde3,
+	0xedda04eb, 0x17a9be04, 0x2c18f4df,
+	0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c, 0x1741a254,
+	0xe5b6a035, 0x213d42f6, 0x2c1c7c26,
+	0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69, 0xd8167fa2,
+	0x0418f2c8, 0x001a96a6, 0x0d1526ab,
+	0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9, 0x8d0dbd86,
+	0x311170a7, 0x3e9b640c, 0xcc3e10d7,
+	0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff, 0x71eae2a1,
+	0x1f9af36e, 0xcfcbd12f, 0xc1de8417,
+	0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, 0xb1c52fca,
+	0xb4be31cd, 0xd8782806, 0x12a3a4e2,
+	0x6f7de532, 0x58fd7eb6, 0xd01ee900, 0x24adffc2, 0xf4990fc5,
+	0x9711aac5, 0x001d7b95, 0x82e5e7d2,
+	0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff, 0x29908415,
+	0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a,
+	0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, 0xd49e2ce7,
+	0x0ce454a9, 0xd60acd86, 0x015f1919,
+	0x77079103, 0xdea03af6, 0x78a8565e, 0xdee356df, 0x21f05cbe,
+	0x8b75e387, 0xb3c50651, 0xb8a5c3ef,
+	0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, 0xafe67afb,
+	0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876,
+	0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367, 0xa99144f8,
+	0x296b299e, 0x492fc295, 0x9266beab,
+	0xb5676e69, 0x9bd3ddda, 0xdf7e052f, 0xdb25701c, 0x1b5e51ee,
+	0xf65324e6, 0x6afce36c, 0x0316cc04,
+	0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, 0x41823979,
+	0x932bcdf6, 0xb657c34d, 0x4edfd282,
+	0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e, 0x13ecf0b0,
+	0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2
+};
+EXPORT_SYMBOL_GPL(cast5_s4);
+static const u32 s5[256] = {
+	0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911, 0xb86a7fff,
+	0x1dd358f5, 0x44dd9d44, 0x1731167f,
+	0x08fbf1fa, 0xe7f511cc, 0xd2051b00, 0x735aba00, 0x2ab722d8,
+	0x386381cb, 0xacf6243a, 0x69befd7a,
+	0xe6a2e77f, 0xf0c720cd, 0xc4494816, 0xccf5c180, 0x38851640,
+	0x15b0a848, 0xe68b18cb, 0x4caadeff,
+	0x5f480a01, 0x0412b2aa, 0x259814fc, 0x41d0efe2, 0x4e40b48d,
+	0x248eb6fb, 0x8dba1cfe, 0x41a99b02,
+	0x1a550a04, 0xba8f65cb, 0x7251f4e7, 0x95a51725, 0xc106ecd7,
+	0x97a5980a, 0xc539b9aa, 0x4d79fe6a,
+	0xf2f3f763, 0x68af8040, 0xed0c9e56, 0x11b4958b, 0xe1eb5a88,
+	0x8709e6b0, 0xd7e07156, 0x4e29fea7,
+	0x6366e52d, 0x02d1c000, 0xc4ac8e05, 0x9377f571, 0x0c05372a,
+	0x578535f2, 0x2261be02, 0xd642a0c9,
+	0xdf13a280, 0x74b55bd2, 0x682199c0, 0xd421e5ec, 0x53fb3ce8,
+	0xc8adedb3, 0x28a87fc9, 0x3d959981,
+	0x5c1ff900, 0xfe38d399, 0x0c4eff0b, 0x062407ea, 0xaa2f4fb1,
+	0x4fb96976, 0x90c79505, 0xb0a8a774,
+	0xef55a1ff, 0xe59ca2c2, 0xa6b62d27, 0xe66a4263, 0xdf65001f,
+	0x0ec50966, 0xdfdd55bc, 0x29de0655,
+	0x911e739a, 0x17af8975, 0x32c7911c, 0x89f89468, 0x0d01e980,
+	0x524755f4, 0x03b63cc9, 0x0cc844b2,
+	0xbcf3f0aa, 0x87ac36e9, 0xe53a7426, 0x01b3d82b, 0x1a9e7449,
+	0x64ee2d7e, 0xcddbb1da, 0x01c94910,
+	0xb868bf80, 0x0d26f3fd, 0x9342ede7, 0x04a5c284, 0x636737b6,
+	0x50f5b616, 0xf24766e3, 0x8eca36c1,
+	0x136e05db, 0xfef18391, 0xfb887a37, 0xd6e7f7d4, 0xc7fb7dc9,
+	0x3063fcdf, 0xb6f589de, 0xec2941da,
+	0x26e46695, 0xb7566419, 0xf654efc5, 0xd08d58b7, 0x48925401,
+	0xc1bacb7f, 0xe5ff550f, 0xb6083049,
+	0x5bb5d0e8, 0x87d72e5a, 0xab6a6ee1, 0x223a66ce, 0xc62bf3cd,
+	0x9e0885f9, 0x68cb3e47, 0x086c010f,
+	0xa21de820, 0xd18b69de, 0xf3f65777, 0xfa02c3f6, 0x407edac3,
+	0xcbb3d550, 0x1793084d, 0xb0d70eba,
+	0x0ab378d5, 0xd951fb0c, 0xded7da56, 0x4124bbe4, 0x94ca0b56,
+	0x0f5755d1, 0xe0e1e56e, 0x6184b5be,
+	0x580a249f, 0x94f74bc0, 0xe327888e, 0x9f7b5561, 0xc3dc0280,
+	0x05687715, 0x646c6bd7, 0x44904db3,
+	0x66b4f0a3, 0xc0f1648a, 0x697ed5af, 0x49e92ff6, 0x309e374f,
+	0x2cb6356a, 0x85808573, 0x4991f840,
+	0x76f0ae02, 0x083be84d, 0x28421c9a, 0x44489406, 0x736e4cb8,
+	0xc1092910, 0x8bc95fc6, 0x7d869cf4,
+	0x134f616f, 0x2e77118d, 0xb31b2be1, 0xaa90b472, 0x3ca5d717,
+	0x7d161bba, 0x9cad9010, 0xaf462ba2,
+	0x9fe459d2, 0x45d34559, 0xd9f2da13, 0xdbc65487, 0xf3e4f94e,
+	0x176d486f, 0x097c13ea, 0x631da5c7,
+	0x445f7382, 0x175683f4, 0xcdc66a97, 0x70be0288, 0xb3cdcf72,
+	0x6e5dd2f3, 0x20936079, 0x459b80a5,
+	0xbe60e2db, 0xa9c23101, 0xeba5315c, 0x224e42f2, 0x1c5c1572,
+	0xf6721b2c, 0x1ad2fff3, 0x8c25404e,
+	0x324ed72f, 0x4067b7fd, 0x0523138e, 0x5ca3bc78, 0xdc0fd66e,
+	0x75922283, 0x784d6b17, 0x58ebb16e,
+	0x44094f85, 0x3f481d87, 0xfcfeae7b, 0x77b5ff76, 0x8c2302bf,
+	0xaaf47556, 0x5f46b02a, 0x2b092801,
+	0x3d38f5f7, 0x0ca81f36, 0x52af4a8a, 0x66d5e7c0, 0xdf3b0874,
+	0x95055110, 0x1b5ad7a8, 0xf61ed5ad,
+	0x6cf6e479, 0x20758184, 0xd0cefa65, 0x88f7be58, 0x4a046826,
+	0x0ff6f8f3, 0xa09c7f70, 0x5346aba0,
+	0x5ce96c28, 0xe176eda3, 0x6bac307f, 0x376829d2, 0x85360fa9,
+	0x17e3fe2a, 0x24b79767, 0xf5a96b20,
+	0xd6cd2595, 0x68ff1ebf, 0x7555442c, 0xf19f06be, 0xf9e0659a,
+	0xeeb9491d, 0x34010718, 0xbb30cab8,
+	0xe822fe15, 0x88570983, 0x750e6249, 0xda627e55, 0x5e76ffa8,
+	0xb1534546, 0x6d47de08, 0xefe9e7d4
+};
+static const u32 s6[256] = {
+	0xf6fa8f9d, 0x2cac6ce1, 0x4ca34867, 0xe2337f7c, 0x95db08e7,
+	0x016843b4, 0xeced5cbc, 0x325553ac,
+	0xbf9f0960, 0xdfa1e2ed, 0x83f0579d, 0x63ed86b9, 0x1ab6a6b8,
+	0xde5ebe39, 0xf38ff732, 0x8989b138,
+	0x33f14961, 0xc01937bd, 0xf506c6da, 0xe4625e7e, 0xa308ea99,
+	0x4e23e33c, 0x79cbd7cc, 0x48a14367,
+	0xa3149619, 0xfec94bd5, 0xa114174a, 0xeaa01866, 0xa084db2d,
+	0x09a8486f, 0xa888614a, 0x2900af98,
+	0x01665991, 0xe1992863, 0xc8f30c60, 0x2e78ef3c, 0xd0d51932,
+	0xcf0fec14, 0xf7ca07d2, 0xd0a82072,
+	0xfd41197e, 0x9305a6b0, 0xe86be3da, 0x74bed3cd, 0x372da53c,
+	0x4c7f4448, 0xdab5d440, 0x6dba0ec3,
+	0x083919a7, 0x9fbaeed9, 0x49dbcfb0, 0x4e670c53, 0x5c3d9c01,
+	0x64bdb941, 0x2c0e636a, 0xba7dd9cd,
+	0xea6f7388, 0xe70bc762, 0x35f29adb, 0x5c4cdd8d, 0xf0d48d8c,
+	0xb88153e2, 0x08a19866, 0x1ae2eac8,
+	0x284caf89, 0xaa928223, 0x9334be53, 0x3b3a21bf, 0x16434be3,
+	0x9aea3906, 0xefe8c36e, 0xf890cdd9,
+	0x80226dae, 0xc340a4a3, 0xdf7e9c09, 0xa694a807, 0x5b7c5ecc,
+	0x221db3a6, 0x9a69a02f, 0x68818a54,
+	0xceb2296f, 0x53c0843a, 0xfe893655, 0x25bfe68a, 0xb4628abc,
+	0xcf222ebf, 0x25ac6f48, 0xa9a99387,
+	0x53bddb65, 0xe76ffbe7, 0xe967fd78, 0x0ba93563, 0x8e342bc1,
+	0xe8a11be9, 0x4980740d, 0xc8087dfc,
+	0x8de4bf99, 0xa11101a0, 0x7fd37975, 0xda5a26c0, 0xe81f994f,
+	0x9528cd89, 0xfd339fed, 0xb87834bf,
+	0x5f04456d, 0x22258698, 0xc9c4c83b, 0x2dc156be, 0x4f628daa,
+	0x57f55ec5, 0xe2220abe, 0xd2916ebf,
+	0x4ec75b95, 0x24f2c3c0, 0x42d15d99, 0xcd0d7fa0, 0x7b6e27ff,
+	0xa8dc8af0, 0x7345c106, 0xf41e232f,
+	0x35162386, 0xe6ea8926, 0x3333b094, 0x157ec6f2, 0x372b74af,
+	0x692573e4, 0xe9a9d848, 0xf3160289,
+	0x3a62ef1d, 0xa787e238, 0xf3a5f676, 0x74364853, 0x20951063,
+	0x4576698d, 0xb6fad407, 0x592af950,
+	0x36f73523, 0x4cfb6e87, 0x7da4cec0, 0x6c152daa, 0xcb0396a8,
+	0xc50dfe5d, 0xfcd707ab, 0x0921c42f,
+	0x89dff0bb, 0x5fe2be78, 0x448f4f33, 0x754613c9, 0x2b05d08d,
+	0x48b9d585, 0xdc049441, 0xc8098f9b,
+	0x7dede786, 0xc39a3373, 0x42410005, 0x6a091751, 0x0ef3c8a6,
+	0x890072d6, 0x28207682, 0xa9a9f7be,
+	0xbf32679d, 0xd45b5b75, 0xb353fd00, 0xcbb0e358, 0x830f220a,
+	0x1f8fb214, 0xd372cf08, 0xcc3c4a13,
+	0x8cf63166, 0x061c87be, 0x88c98f88, 0x6062e397, 0x47cf8e7a,
+	0xb6c85283, 0x3cc2acfb, 0x3fc06976,
+	0x4e8f0252, 0x64d8314d, 0xda3870e3, 0x1e665459, 0xc10908f0,
+	0x513021a5, 0x6c5b68b7, 0x822f8aa0,
+	0x3007cd3e, 0x74719eef, 0xdc872681, 0x073340d4, 0x7e432fd9,
+	0x0c5ec241, 0x8809286c, 0xf592d891,
+	0x08a930f6, 0x957ef305, 0xb7fbffbd, 0xc266e96f, 0x6fe4ac98,
+	0xb173ecc0, 0xbc60b42a, 0x953498da,
+	0xfba1ae12, 0x2d4bd736, 0x0f25faab, 0xa4f3fceb, 0xe2969123,
+	0x257f0c3d, 0x9348af49, 0x361400bc,
+	0xe8816f4a, 0x3814f200, 0xa3f94043, 0x9c7a54c2, 0xbc704f57,
+	0xda41e7f9, 0xc25ad33a, 0x54f4a084,
+	0xb17f5505, 0x59357cbe, 0xedbd15c8, 0x7f97c5ab, 0xba5ac7b5,
+	0xb6f6deaf, 0x3a479c3a, 0x5302da25,
+	0x653d7e6a, 0x54268d49, 0x51a477ea, 0x5017d55b, 0xd7d25d88,
+	0x44136c76, 0x0404a8c8, 0xb8e5a121,
+	0xb81a928a, 0x60ed5869, 0x97c55b96, 0xeaec991b, 0x29935913,
+	0x01fdb7f1, 0x088e8dfa, 0x9ab6f6f5,
+	0x3b4cbf9f, 0x4a5de3ab, 0xe6051d35, 0xa0e1d855, 0xd36b4cf1,
+	0xf544edeb, 0xb0e93524, 0xbebb8fbd,
+	0xa2d762cf, 0x49c92f54, 0x38b5f331, 0x7128a454, 0x48392905,
+	0xa65b1db8, 0x851c97bd, 0xd675cf2f
+};
+static const u32 s7[256] = {
+	0x85e04019, 0x332bf567, 0x662dbfff, 0xcfc65693, 0x2a8d7f6f,
+	0xab9bc912, 0xde6008a1, 0x2028da1f,
+	0x0227bce7, 0x4d642916, 0x18fac300, 0x50f18b82, 0x2cb2cb11,
+	0xb232e75c, 0x4b3695f2, 0xb28707de,
+	0xa05fbcf6, 0xcd4181e9, 0xe150210c, 0xe24ef1bd, 0xb168c381,
+	0xfde4e789, 0x5c79b0d8, 0x1e8bfd43,
+	0x4d495001, 0x38be4341, 0x913cee1d, 0x92a79c3f, 0x089766be,
+	0xbaeeadf4, 0x1286becf, 0xb6eacb19,
+	0x2660c200, 0x7565bde4, 0x64241f7a, 0x8248dca9, 0xc3b3ad66,
+	0x28136086, 0x0bd8dfa8, 0x356d1cf2,
+	0x107789be, 0xb3b2e9ce, 0x0502aa8f, 0x0bc0351e, 0x166bf52a,
+	0xeb12ff82, 0xe3486911, 0xd34d7516,
+	0x4e7b3aff, 0x5f43671b, 0x9cf6e037, 0x4981ac83, 0x334266ce,
+	0x8c9341b7, 0xd0d854c0, 0xcb3a6c88,
+	0x47bc2829, 0x4725ba37, 0xa66ad22b, 0x7ad61f1e, 0x0c5cbafa,
+	0x4437f107, 0xb6e79962, 0x42d2d816,
+	0x0a961288, 0xe1a5c06e, 0x13749e67, 0x72fc081a, 0xb1d139f7,
+	0xf9583745, 0xcf19df58, 0xbec3f756,
+	0xc06eba30, 0x07211b24, 0x45c28829, 0xc95e317f, 0xbc8ec511,
+	0x38bc46e9, 0xc6e6fa14, 0xbae8584a,
+	0xad4ebc46, 0x468f508b, 0x7829435f, 0xf124183b, 0x821dba9f,
+	0xaff60ff4, 0xea2c4e6d, 0x16e39264,
+	0x92544a8b, 0x009b4fc3, 0xaba68ced, 0x9ac96f78, 0x06a5b79a,
+	0xb2856e6e, 0x1aec3ca9, 0xbe838688,
+	0x0e0804e9, 0x55f1be56, 0xe7e5363b, 0xb3a1f25d, 0xf7debb85,
+	0x61fe033c, 0x16746233, 0x3c034c28,
+	0xda6d0c74, 0x79aac56c, 0x3ce4e1ad, 0x51f0c802, 0x98f8f35a,
+	0x1626a49f, 0xeed82b29, 0x1d382fe3,
+	0x0c4fb99a, 0xbb325778, 0x3ec6d97b, 0x6e77a6a9, 0xcb658b5c,
+	0xd45230c7, 0x2bd1408b, 0x60c03eb7,
+	0xb9068d78, 0xa33754f4, 0xf430c87d, 0xc8a71302, 0xb96d8c32,
+	0xebd4e7be, 0xbe8b9d2d, 0x7979fb06,
+	0xe7225308, 0x8b75cf77, 0x11ef8da4, 0xe083c858, 0x8d6b786f,
+	0x5a6317a6, 0xfa5cf7a0, 0x5dda0033,
+	0xf28ebfb0, 0xf5b9c310, 0xa0eac280, 0x08b9767a, 0xa3d9d2b0,
+	0x79d34217, 0x021a718d, 0x9ac6336a,
+	0x2711fd60, 0x438050e3, 0x069908a8, 0x3d7fedc4, 0x826d2bef,
+	0x4eeb8476, 0x488dcf25, 0x36c9d566,
+	0x28e74e41, 0xc2610aca, 0x3d49a9cf, 0xbae3b9df, 0xb65f8de6,
+	0x92aeaf64, 0x3ac7d5e6, 0x9ea80509,
+	0xf22b017d, 0xa4173f70, 0xdd1e16c3, 0x15e0d7f9, 0x50b1b887,
+	0x2b9f4fd5, 0x625aba82, 0x6a017962,
+	0x2ec01b9c, 0x15488aa9, 0xd716e740, 0x40055a2c, 0x93d29a22,
+	0xe32dbf9a, 0x058745b9, 0x3453dc1e,
+	0xd699296e, 0x496cff6f, 0x1c9f4986, 0xdfe2ed07, 0xb87242d1,
+	0x19de7eae, 0x053e561a, 0x15ad6f8c,
+	0x66626c1c, 0x7154c24c, 0xea082b2a, 0x93eb2939, 0x17dcb0f0,
+	0x58d4f2ae, 0x9ea294fb, 0x52cf564c,
+	0x9883fe66, 0x2ec40581, 0x763953c3, 0x01d6692e, 0xd3a0c108,
+	0xa1e7160e, 0xe4f2dfa6, 0x693ed285,
+	0x74904698, 0x4c2b0edd, 0x4f757656, 0x5d393378, 0xa132234f,
+	0x3d321c5d, 0xc3f5e194, 0x4b269301,
+	0xc79f022f, 0x3c997e7e, 0x5e4f9504, 0x3ffafbbd, 0x76f7ad0e,
+	0x296693f4, 0x3d1fce6f, 0xc61e45be,
+	0xd3b5ab34, 0xf72bf9b7, 0x1b0434c0, 0x4e72b567, 0x5592a33d,
+	0xb5229301, 0xcfd2a87f, 0x60aeb767,
+	0x1814386b, 0x30bcc33d, 0x38a0c07d, 0xfd1606f2, 0xc363519b,
+	0x589dd390, 0x5479f8e6, 0x1cb8d647,
+	0x97fd61a9, 0xea7759f4, 0x2d57539d, 0x569a58cf, 0xe84e63ad,
+	0x462e1b78, 0x6580f87e, 0xf3817914,
+	0x91da55f4, 0x40a230f3, 0xd1988f35, 0xb6e318d2, 0x3ffa50bc,
+	0x3d40f021, 0xc3c0bdae, 0x4958c24c,
+	0x518f36b2, 0x84b1d370, 0x0fedce83, 0x878ddada, 0xf2a279c7,
+	0x94e01be8, 0x90716f4b, 0x954b8aa3
+};
+static const u32 sb8[256] = {
+	0xe216300d, 0xbbddfffc, 0xa7ebdabd, 0x35648095, 0x7789f8b7,
+	0xe6c1121b, 0x0e241600, 0x052ce8b5,
+	0x11a9cfb0, 0xe5952f11, 0xece7990a, 0x9386d174, 0x2a42931c,
+	0x76e38111, 0xb12def3a, 0x37ddddfc,
+	0xde9adeb1, 0x0a0cc32c, 0xbe197029, 0x84a00940, 0xbb243a0f,
+	0xb4d137cf, 0xb44e79f0, 0x049eedfd,
+	0x0b15a15d, 0x480d3168, 0x8bbbde5a, 0x669ded42, 0xc7ece831,
+	0x3f8f95e7, 0x72df191b, 0x7580330d,
+	0x94074251, 0x5c7dcdfa, 0xabbe6d63, 0xaa402164, 0xb301d40a,
+	0x02e7d1ca, 0x53571dae, 0x7a3182a2,
+	0x12a8ddec, 0xfdaa335d, 0x176f43e8, 0x71fb46d4, 0x38129022,
+	0xce949ad4, 0xb84769ad, 0x965bd862,
+	0x82f3d055, 0x66fb9767, 0x15b80b4e, 0x1d5b47a0, 0x4cfde06f,
+	0xc28ec4b8, 0x57e8726e, 0x647a78fc,
+	0x99865d44, 0x608bd593, 0x6c200e03, 0x39dc5ff6, 0x5d0b00a3,
+	0xae63aff2, 0x7e8bd632, 0x70108c0c,
+	0xbbd35049, 0x2998df04, 0x980cf42a, 0x9b6df491, 0x9e7edd53,
+	0x06918548, 0x58cb7e07, 0x3b74ef2e,
+	0x522fffb1, 0xd24708cc, 0x1c7e27cd, 0xa4eb215b, 0x3cf1d2e2,
+	0x19b47a38, 0x424f7618, 0x35856039,
+	0x9d17dee7, 0x27eb35e6, 0xc9aff67b, 0x36baf5b8, 0x09c467cd,
+	0xc18910b1, 0xe11dbf7b, 0x06cd1af8,
+	0x7170c608, 0x2d5e3354, 0xd4de495a, 0x64c6d006, 0xbcc0c62c,
+	0x3dd00db3, 0x708f8f34, 0x77d51b42,
+	0x264f620f, 0x24b8d2bf, 0x15c1b79e, 0x46a52564, 0xf8d7e54e,
+	0x3e378160, 0x7895cda5, 0x859c15a5,
+	0xe6459788, 0xc37bc75f, 0xdb07ba0c, 0x0676a3ab, 0x7f229b1e,
+	0x31842e7b, 0x24259fd7, 0xf8bef472,
+	0x835ffcb8, 0x6df4c1f2, 0x96f5b195, 0xfd0af0fc, 0xb0fe134c,
+	0xe2506d3d, 0x4f9b12ea, 0xf215f225,
+	0xa223736f, 0x9fb4c428, 0x25d04979, 0x34c713f8, 0xc4618187,
+	0xea7a6e98, 0x7cd16efc, 0x1436876c,
+	0xf1544107, 0xbedeee14, 0x56e9af27, 0xa04aa441, 0x3cf7c899,
+	0x92ecbae6, 0xdd67016d, 0x151682eb,
+	0xa842eedf, 0xfdba60b4, 0xf1907b75, 0x20e3030f, 0x24d8c29e,
+	0xe139673b, 0xefa63fb8, 0x71873054,
+	0xb6f2cf3b, 0x9f326442, 0xcb15a4cc, 0xb01a4504, 0xf1e47d8d,
+	0x844a1be5, 0xbae7dfdc, 0x42cbda70,
+	0xcd7dae0a, 0x57e85b7a, 0xd53f5af6, 0x20cf4d8c, 0xcea4d428,
+	0x79d130a4, 0x3486ebfb, 0x33d3cddc,
+	0x77853b53, 0x37effcb5, 0xc5068778, 0xe580b3e6, 0x4e68b8f4,
+	0xc5c8b37e, 0x0d809ea2, 0x398feb7c,
+	0x132a4f94, 0x43b7950e, 0x2fee7d1c, 0x223613bd, 0xdd06caa2,
+	0x37df932b, 0xc4248289, 0xacf3ebc3,
+	0x5715f6b7, 0xef3478dd, 0xf267616f, 0xc148cbe4, 0x9052815e,
+	0x5e410fab, 0xb48a2465, 0x2eda7fa4,
+	0xe87b40e4, 0xe98ea084, 0x5889e9e1, 0xefd390fc, 0xdd07d35b,
+	0xdb485694, 0x38d7e5b2, 0x57720101,
+	0x730edebc, 0x5b643113, 0x94917e4f, 0x503c2fba, 0x646f1282,
+	0x7523d24a, 0xe0779695, 0xf9c17a8f,
+	0x7a5b2121, 0xd187b896, 0x29263a4d, 0xba510cdf, 0x81f47c9f,
+	0xad1163ed, 0xea7b5965, 0x1a00726e,
+	0x11403092, 0x00da6d77, 0x4a0cdd61, 0xad1f4603, 0x605bdfb0,
+	0x9eedc364, 0x22ebe6a8, 0xcee7d28a,
+	0xa0e736a0, 0x5564a6b9, 0x10853209, 0xc7eb8f37, 0x2de705ca,
+	0x8951570f, 0xdf09822b, 0xbd691a6c,
+	0xaa12e4f2, 0x87451c0f, 0xe0f6a27a, 0x3ada4819, 0x4cf1764f,
+	0x0d771c2b, 0x67cdb156, 0x350d8384,
+	0x5938fa0f, 0x42399ef3, 0x36997b07, 0x0e84093d, 0x4aa93e61,
+	0x8360d87b, 0x1fa98b0c, 0x1149382c,
+	0xe97625a5, 0x0614d1b7, 0x0e25244b, 0x0c768347, 0x589e8d82,
+	0x0d2059d1, 0xa466bb1e, 0xf8da0a82,
+	0x04f19130, 0xba6e4ec0, 0x99265164, 0x1ee7230d, 0x50b2ad80,
+	0xeaee6801, 0x8db2a283, 0xea8bf59e
+};
+
+#define s1 cast5_s1
+#define s2 cast5_s2
+#define s3 cast5_s3
+#define s4 cast5_s4
+
+#define F1(D, m, r)  ((I = ((m) + (D))), (I = rol32(I, (r))),   \
+	(((s1[I >> 24] ^ s2[(I>>16)&0xff]) - s3[(I>>8)&0xff]) + s4[I&0xff]))
+#define F2(D, m, r)  ((I = ((m) ^ (D))), (I = rol32(I, (r))),   \
+	(((s1[I >> 24] - s2[(I>>16)&0xff]) + s3[(I>>8)&0xff]) ^ s4[I&0xff]))
+#define F3(D, m, r)  ((I = ((m) - (D))), (I = rol32(I, (r))),   \
+	(((s1[I >> 24] + s2[(I>>16)&0xff]) ^ s3[(I>>8)&0xff]) - s4[I&0xff]))
+
+
+void __cast5_encrypt(struct cast5_ctx *c, u8 *outbuf, const u8 *inbuf)
+{
+	const __be32 *src = (const __be32 *)inbuf;
+	__be32 *dst = (__be32 *)outbuf;
+	u32 l, r, t;
+	u32 I;			/* used by the Fx macros */
+	u32 *Km;
+	u8 *Kr;
+
+	Km = c->Km;
+	Kr = c->Kr;
+
+	/* (L0,R0) <-- (m1...m64).  (Split the plaintext into left and
+	 * right 32-bit halves L0 = m1...m32 and R0 = m33...m64.)
+	 */
+	l = be32_to_cpu(src[0]);
+	r = be32_to_cpu(src[1]);
+
+	/* (16 rounds) for i from 1 to 16, compute Li and Ri as follows:
+	 *  Li = Ri-1;
+	 *  Ri = Li-1 ^ f(Ri-1,Kmi,Kri), where f is defined in Section 2.2
+	 * Rounds 1, 4, 7, 10, 13, and 16 use f function Type 1.
+	 * Rounds 2, 5, 8, 11, and 14 use f function Type 2.
+	 * Rounds 3, 6, 9, 12, and 15 use f function Type 3.
+	 */
+
+	t = l; l = r; r = t ^ F1(r, Km[0], Kr[0]);
+	t = l; l = r; r = t ^ F2(r, Km[1], Kr[1]);
+	t = l; l = r; r = t ^ F3(r, Km[2], Kr[2]);
+	t = l; l = r; r = t ^ F1(r, Km[3], Kr[3]);
+	t = l; l = r; r = t ^ F2(r, Km[4], Kr[4]);
+	t = l; l = r; r = t ^ F3(r, Km[5], Kr[5]);
+	t = l; l = r; r = t ^ F1(r, Km[6], Kr[6]);
+	t = l; l = r; r = t ^ F2(r, Km[7], Kr[7]);
+	t = l; l = r; r = t ^ F3(r, Km[8], Kr[8]);
+	t = l; l = r; r = t ^ F1(r, Km[9], Kr[9]);
+	t = l; l = r; r = t ^ F2(r, Km[10], Kr[10]);
+	t = l; l = r; r = t ^ F3(r, Km[11], Kr[11]);
+	if (!(c->rr)) {
+		t = l; l = r; r = t ^ F1(r, Km[12], Kr[12]);
+		t = l; l = r; r = t ^ F2(r, Km[13], Kr[13]);
+		t = l; l = r; r = t ^ F3(r, Km[14], Kr[14]);
+		t = l; l = r; r = t ^ F1(r, Km[15], Kr[15]);
+	}
+
+	/* c1...c64 <-- (R16,L16).  (Exchange final blocks L16, R16 and
+	 *  concatenate to form the ciphertext.) */
+	dst[0] = cpu_to_be32(r);
+	dst[1] = cpu_to_be32(l);
+}
+EXPORT_SYMBOL_GPL(__cast5_encrypt);
+
+static void cast5_encrypt(struct crypto_tfm *tfm, u8 *outbuf, const u8 *inbuf)
+{
+	__cast5_encrypt(crypto_tfm_ctx(tfm), outbuf, inbuf);
+}
+
+void __cast5_decrypt(struct cast5_ctx *c, u8 *outbuf, const u8 *inbuf)
+{
+	const __be32 *src = (const __be32 *)inbuf;
+	__be32 *dst = (__be32 *)outbuf;
+	u32 l, r, t;
+	u32 I;
+	u32 *Km;
+	u8 *Kr;
+
+	Km = c->Km;
+	Kr = c->Kr;
+
+	l = be32_to_cpu(src[0]);
+	r = be32_to_cpu(src[1]);
+
+	if (!(c->rr)) {
+		t = l; l = r; r = t ^ F1(r, Km[15], Kr[15]);
+		t = l; l = r; r = t ^ F3(r, Km[14], Kr[14]);
+		t = l; l = r; r = t ^ F2(r, Km[13], Kr[13]);
+		t = l; l = r; r = t ^ F1(r, Km[12], Kr[12]);
+	}
+	t = l; l = r; r = t ^ F3(r, Km[11], Kr[11]);
+	t = l; l = r; r = t ^ F2(r, Km[10], Kr[10]);
+	t = l; l = r; r = t ^ F1(r, Km[9], Kr[9]);
+	t = l; l = r; r = t ^ F3(r, Km[8], Kr[8]);
+	t = l; l = r; r = t ^ F2(r, Km[7], Kr[7]);
+	t = l; l = r; r = t ^ F1(r, Km[6], Kr[6]);
+	t = l; l = r; r = t ^ F3(r, Km[5], Kr[5]);
+	t = l; l = r; r = t ^ F2(r, Km[4], Kr[4]);
+	t = l; l = r; r = t ^ F1(r, Km[3], Kr[3]);
+	t = l; l = r; r = t ^ F3(r, Km[2], Kr[2]);
+	t = l; l = r; r = t ^ F2(r, Km[1], Kr[1]);
+	t = l; l = r; r = t ^ F1(r, Km[0], Kr[0]);
+
+	dst[0] = cpu_to_be32(r);
+	dst[1] = cpu_to_be32(l);
+}
+EXPORT_SYMBOL_GPL(__cast5_decrypt);
+
+static void cast5_decrypt(struct crypto_tfm *tfm, u8 *outbuf, const u8 *inbuf)
+{
+	__cast5_decrypt(crypto_tfm_ctx(tfm), outbuf, inbuf);
+}
+
+static void key_schedule(u32 *x, u32 *z, u32 *k)
+{
+
+#define xi(i)   ((x[(i)/4] >> (8*(3-((i)%4)))) & 0xff)
+#define zi(i)   ((z[(i)/4] >> (8*(3-((i)%4)))) & 0xff)
+
+	z[0] = x[0] ^ s5[xi(13)] ^ s6[xi(15)] ^ s7[xi(12)] ^ sb8[xi(14)] ^
+	    s7[xi(8)];
+	z[1] = x[2] ^ s5[zi(0)] ^ s6[zi(2)] ^ s7[zi(1)] ^ sb8[zi(3)] ^
+	    sb8[xi(10)];
+	z[2] = x[3] ^ s5[zi(7)] ^ s6[zi(6)] ^ s7[zi(5)] ^ sb8[zi(4)] ^
+	    s5[xi(9)];
+	z[3] = x[1] ^ s5[zi(10)] ^ s6[zi(9)] ^ s7[zi(11)] ^ sb8[zi(8)] ^
+	    s6[xi(11)];
+	k[0] = s5[zi(8)] ^ s6[zi(9)] ^ s7[zi(7)] ^ sb8[zi(6)] ^ s5[zi(2)];
+	k[1] = s5[zi(10)] ^ s6[zi(11)] ^ s7[zi(5)] ^ sb8[zi(4)] ^
+	    s6[zi(6)];
+	k[2] = s5[zi(12)] ^ s6[zi(13)] ^ s7[zi(3)] ^ sb8[zi(2)] ^
+	    s7[zi(9)];
+	k[3] = s5[zi(14)] ^ s6[zi(15)] ^ s7[zi(1)] ^ sb8[zi(0)] ^
+	    sb8[zi(12)];
+
+	x[0] = z[2] ^ s5[zi(5)] ^ s6[zi(7)] ^ s7[zi(4)] ^ sb8[zi(6)] ^
+	    s7[zi(0)];
+	x[1] = z[0] ^ s5[xi(0)] ^ s6[xi(2)] ^ s7[xi(1)] ^ sb8[xi(3)] ^
+	    sb8[zi(2)];
+	x[2] = z[1] ^ s5[xi(7)] ^ s6[xi(6)] ^ s7[xi(5)] ^ sb8[xi(4)] ^
+	    s5[zi(1)];
+	x[3] = z[3] ^ s5[xi(10)] ^ s6[xi(9)] ^ s7[xi(11)] ^ sb8[xi(8)] ^
+	    s6[zi(3)];
+	k[4] = s5[xi(3)] ^ s6[xi(2)] ^ s7[xi(12)] ^ sb8[xi(13)] ^
+	    s5[xi(8)];
+	k[5] = s5[xi(1)] ^ s6[xi(0)] ^ s7[xi(14)] ^ sb8[xi(15)] ^
+	    s6[xi(13)];
+	k[6] = s5[xi(7)] ^ s6[xi(6)] ^ s7[xi(8)] ^ sb8[xi(9)] ^ s7[xi(3)];
+	k[7] = s5[xi(5)] ^ s6[xi(4)] ^ s7[xi(10)] ^ sb8[xi(11)] ^
+	    sb8[xi(7)];
+
+	z[0] = x[0] ^ s5[xi(13)] ^ s6[xi(15)] ^ s7[xi(12)] ^ sb8[xi(14)] ^
+	    s7[xi(8)];
+	z[1] = x[2] ^ s5[zi(0)] ^ s6[zi(2)] ^ s7[zi(1)] ^ sb8[zi(3)] ^
+	    sb8[xi(10)];
+	z[2] = x[3] ^ s5[zi(7)] ^ s6[zi(6)] ^ s7[zi(5)] ^ sb8[zi(4)] ^
+	    s5[xi(9)];
+	z[3] = x[1] ^ s5[zi(10)] ^ s6[zi(9)] ^ s7[zi(11)] ^ sb8[zi(8)] ^
+	    s6[xi(11)];
+	k[8] = s5[zi(3)] ^ s6[zi(2)] ^ s7[zi(12)] ^ sb8[zi(13)] ^
+	    s5[zi(9)];
+	k[9] = s5[zi(1)] ^ s6[zi(0)] ^ s7[zi(14)] ^ sb8[zi(15)] ^
+	    s6[zi(12)];
+	k[10] = s5[zi(7)] ^ s6[zi(6)] ^ s7[zi(8)] ^ sb8[zi(9)] ^ s7[zi(2)];
+	k[11] = s5[zi(5)] ^ s6[zi(4)] ^ s7[zi(10)] ^ sb8[zi(11)] ^
+	    sb8[zi(6)];
+
+	x[0] = z[2] ^ s5[zi(5)] ^ s6[zi(7)] ^ s7[zi(4)] ^ sb8[zi(6)] ^
+	    s7[zi(0)];
+	x[1] = z[0] ^ s5[xi(0)] ^ s6[xi(2)] ^ s7[xi(1)] ^ sb8[xi(3)] ^
+	    sb8[zi(2)];
+	x[2] = z[1] ^ s5[xi(7)] ^ s6[xi(6)] ^ s7[xi(5)] ^ sb8[xi(4)] ^
+	    s5[zi(1)];
+	x[3] = z[3] ^ s5[xi(10)] ^ s6[xi(9)] ^ s7[xi(11)] ^ sb8[xi(8)] ^
+	    s6[zi(3)];
+	k[12] = s5[xi(8)] ^ s6[xi(9)] ^ s7[xi(7)] ^ sb8[xi(6)] ^ s5[xi(3)];
+	k[13] = s5[xi(10)] ^ s6[xi(11)] ^ s7[xi(5)] ^ sb8[xi(4)] ^
+	    s6[xi(7)];
+	k[14] = s5[xi(12)] ^ s6[xi(13)] ^ s7[xi(3)] ^ sb8[xi(2)] ^
+	    s7[xi(8)];
+	k[15] = s5[xi(14)] ^ s6[xi(15)] ^ s7[xi(1)] ^ sb8[xi(0)] ^
+	    sb8[xi(13)];
+
+#undef xi
+#undef zi
+}
+
+
+int cast5_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int key_len)
+{
+	struct cast5_ctx *c = crypto_tfm_ctx(tfm);
+	int i;
+	u32 x[4];
+	u32 z[4];
+	u32 k[16];
+	__be32 p_key[4];
+
+	c->rr = key_len <= 10 ? 1 : 0;
+
+	memset(p_key, 0, 16);
+	memcpy(p_key, key, key_len);
+
+
+	x[0] = be32_to_cpu(p_key[0]);
+	x[1] = be32_to_cpu(p_key[1]);
+	x[2] = be32_to_cpu(p_key[2]);
+	x[3] = be32_to_cpu(p_key[3]);
+
+	key_schedule(x, z, k);
+	for (i = 0; i < 16; i++)
+		c->Km[i] = k[i];
+	key_schedule(x, z, k);
+	for (i = 0; i < 16; i++)
+		c->Kr[i] = k[i] & 0x1f;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(cast5_setkey);
+
+static struct crypto_alg alg = {
+	.cra_name		= "cast5",
+	.cra_driver_name	= "cast5-generic",
+	.cra_priority		= 100,
+	.cra_flags		= CRYPTO_ALG_TYPE_CIPHER,
+	.cra_blocksize		= CAST5_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct cast5_ctx),
+	.cra_alignmask		= 3,
+	.cra_module		= THIS_MODULE,
+	.cra_u			= {
+		.cipher = {
+			.cia_min_keysize = CAST5_MIN_KEY_SIZE,
+			.cia_max_keysize = CAST5_MAX_KEY_SIZE,
+			.cia_setkey  = cast5_setkey,
+			.cia_encrypt = cast5_encrypt,
+			.cia_decrypt = cast5_decrypt
+		}
+	}
+};
+
+static int __init cast5_mod_init(void)
+{
+	return crypto_register_alg(&alg);
+}
+
+static void __exit cast5_mod_fini(void)
+{
+	crypto_unregister_alg(&alg);
+}
+
+module_init(cast5_mod_init);
+module_exit(cast5_mod_fini);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Cast5 Cipher Algorithm");
+MODULE_ALIAS("cast5");
diff --git a/crypto/cast6.c b/crypto/cast6.c
deleted file mode 100644
index e0c15a6..0000000
--- a/crypto/cast6.c
+++ /dev/null
@@ -1,547 +0,0 @@
-/* Kernel cryptographic api.
- * cast6.c - Cast6 cipher algorithm [rfc2612].
- *
- * CAST-256 (*cast6*) is a DES like Substitution-Permutation Network (SPN)
- * cryptosystem built upon the CAST-128 (*cast5*) [rfc2144] encryption
- * algorithm.
- *
- * Copyright (C) 2003 Kartikey Mahendra Bhatt <kartik_me@hotmail.com>.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
-
-
-#include <asm/byteorder.h>
-#include <linux/init.h>
-#include <linux/crypto.h>
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/types.h>
-
-#define CAST6_BLOCK_SIZE 16
-#define CAST6_MIN_KEY_SIZE 16
-#define CAST6_MAX_KEY_SIZE 32
-
-struct cast6_ctx {
-	u32 Km[12][4];
-	u8 Kr[12][4];
-};
-
-#define F1(D, r, m)  ((I = ((m) + (D))), (I = rol32(I, (r))),   \
-    (((s1[I >> 24] ^ s2[(I>>16)&0xff]) - s3[(I>>8)&0xff]) + s4[I&0xff]))
-#define F2(D, r, m)  ((I = ((m) ^ (D))), (I = rol32(I, (r))),   \
-    (((s1[I >> 24] - s2[(I>>16)&0xff]) + s3[(I>>8)&0xff]) ^ s4[I&0xff]))
-#define F3(D, r, m)  ((I = ((m) - (D))), (I = rol32(I, (r))),   \
-    (((s1[I >> 24] + s2[(I>>16)&0xff]) ^ s3[(I>>8)&0xff]) - s4[I&0xff]))
-
-static const u32 s1[256] = {
-	0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f,
-	0x9c004dd3, 0x6003e540, 0xcf9fc949,
-	0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675, 0x6e63a0e0,
-	0x15c361d2, 0xc2e7661d, 0x22d4ff8e,
-	0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2, 0x43c340d3,
-	0xdf2f8656, 0x887ca41a, 0xa2d2bd2d,
-	0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f, 0x2abe32e1,
-	0xaa54166b, 0x22568e3a, 0xa2d341d0,
-	0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de, 0x97943fac,
-	0x4a97c1d8, 0x527644b7, 0xb5f437a7,
-	0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f, 0x827b68d0,
-	0x90ecf52e, 0x22b0c054, 0xbc8e5935,
-	0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d, 0xb7332290,
-	0xe93b159f, 0xb48ee411, 0x4bff345d,
-	0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, 0xd5b1caad,
-	0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50,
-	0x882240f2, 0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272, 0x564c1d2f,
-	0xc59c5319, 0xb949e354, 0xb04669fe,
-	0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d, 0x57538ad5,
-	0x6a390493, 0xe63d37e0, 0x2a54f6b3,
-	0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, 0x29f9d4d5,
-	0xf61b1891, 0xbb72275e, 0xaa508167,
-	0x38901091, 0xc6b505eb, 0x84c7cb8c, 0x2ad75a0f, 0x874a1427,
-	0xa2d1936b, 0x2ad286af, 0xaa56d291,
-	0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, 0x6c00b32d,
-	0x73e2bb14, 0xa0bebc3c, 0x54623779,
-	0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6, 0x04ee002e,
-	0x89fe78e6, 0x3fab0950, 0x325ff6c2,
-	0x81383f05, 0x6963c5c8, 0x76cb5ad6, 0xd49974c9, 0xca180dcf,
-	0x380782d5, 0xc7fa5cf6, 0x8ac31511,
-	0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, 0x31366241,
-	0x051ef495, 0xaa573b04, 0x4a805d8d,
-	0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e, 0x75c6372b,
-	0x50afd341, 0xa7c13275, 0x915a0bf5,
-	0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82, 0xf7fbf265,
-	0xab85c5f3, 0x1b55db94, 0xaad4e324,
-	0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, 0xeadf55b3,
-	0xd5bd9e98, 0xe31231b2, 0x2ad5ad6c,
-	0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f, 0xaa786bf6,
-	0x22513f1e, 0xaa51a79b, 0x2ad344cc,
-	0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491, 0xb4c332e6,
-	0x032268d4, 0xc9600acc, 0xce387e6d,
-	0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de, 0xe01063da,
-	0x4736f464, 0x5ad328d8, 0xb347cc96,
-	0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, 0xe11f0abc,
-	0xbfc5fe4a, 0xa70aec10, 0xac39570a,
-	0x3f04442f, 0x6188b153, 0xe0397a2e, 0x5727cb79, 0x9ceb418f,
-	0x1cacd68d, 0x2ad37c96, 0x0175cb9d,
-	0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779, 0x4744ead4,
-	0xb11c3274, 0xdd24cb9e, 0x7e1c54bd,
-	0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, 0xd47c27af,
-	0x51c85f4d, 0x56907596, 0xa5bb15e6,
-	0x580304f0, 0xca042cf1, 0x011a37ea, 0x8dbfaadb, 0x35ba3e4a,
-	0x3526ffa0, 0xc37b4d09, 0xbc306ed9,
-	0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, 0x7c63b2cf,
-	0x700b45e1, 0xd5ea50f1, 0x85a92872,
-	0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79, 0x42e04198,
-	0x0cd0ede7, 0x26470db8, 0xf881814c,
-	0x474d6ad7, 0x7c0c5e5c, 0xd1231959, 0x381b7298, 0xf5d2f4db,
-	0xab838653, 0x6e2f1e23, 0x83719c9e,
-	0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, 0x962bda1c,
-	0xe1e696ff, 0xb141ab08, 0x7cca89b9,
-	0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d, 0x427b169c,
-	0x5ac9f049, 0xdd8f0f00, 0x5c8165bf
-};
-
-static const u32 s2[256] = {
-	0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, 0xfe61cf7a,
-	0xeec5207a, 0x55889c94, 0x72fc0651,
-	0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba, 0x99c430ef,
-	0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3,
-	0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909, 0xdc440086,
-	0xef944459, 0xba83ccb3, 0xe0c3cdfb,
-	0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, 0x01420ddb,
-	0xe4e7ef5b, 0x25a1ff41, 0xe180f806,
-	0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4, 0x98de8b7f,
-	0x77e83f4e, 0x79929269, 0x24fa9f7b,
-	0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f, 0x62143154,
-	0x0d554b63, 0x5d681121, 0xc866c359,
-	0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21, 0x071f6181,
-	0x39f7627f, 0x361e3084, 0xe4eb573b,
-	0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, 0x2701f50c,
-	0x99847ab4, 0xa0e3df79, 0xba6cf38c,
-	0x10843094, 0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f, 0x208cfb6a,
-	0x8f458c74, 0xd9e0a227, 0x4ec73a34,
-	0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d, 0x8a45388c,
-	0x1d804366, 0x721d9bfd, 0xa58684bb,
-	0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, 0xce280ae1,
-	0x27e19ba5, 0xd5a6c252, 0xe49754bd,
-	0xc5d655dd, 0xeb667064, 0x77840b4d, 0xa1b6a801, 0x84db26a9,
-	0xe0b56714, 0x21f043b7, 0xe5d05860,
-	0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, 0xb5625dbf,
-	0x68561be6, 0x83ca6b94, 0x2d6ed23b,
-	0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, 0x33b4a34c,
-	0x397bc8d6, 0x5ee22b95, 0x5f0e5304,
-	0x81ed6f61, 0x20e74364, 0xb45e1378, 0xde18639b, 0x881ca122,
-	0xb96726d1, 0x8049a7e8, 0x22b7da7b,
-	0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, 0x488cb402,
-	0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf,
-	0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9, 0x0beeff53,
-	0xe3214517, 0xb4542835, 0x9f63293c,
-	0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3, 0xf33401c6,
-	0x30a22c95, 0x31a70850, 0x60930f13,
-	0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9, 0xcdff33a6,
-	0xa02b1741, 0x7cbad9a2, 0x2180036f,
-	0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab, 0x80342676,
-	0x25a75e7b, 0xe4e6d1fc, 0x20c710e6,
-	0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4, 0x2ccb49eb,
-	0x846a3bae, 0x8ff77888, 0xee5d60f6,
-	0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43, 0xb3faec54,
-	0x157fd7fa, 0xef8579cc, 0xd152de58,
-	0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, 0x99319ad5,
-	0xc242fa0f, 0xa7e3ebb0, 0xc68e4906,
-	0xb8da230c, 0x80823028, 0xdcdef3c8, 0xd35fb171, 0x088a1bc8,
-	0xbec0c560, 0x61a3c9e8, 0xbca8f54d,
-	0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89, 0x8b1c34bc,
-	0x301e16e6, 0x273be979, 0xb0ffeaa6,
-	0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, 0x43daf65a,
-	0xf7e19798, 0x7619b72f, 0x8f1c9ba4,
-	0xdc8637a0, 0x16a7d3b1, 0x9fc393b7, 0xa7136eeb, 0xc6bcc63e,
-	0x1a513742, 0xef6828bc, 0x520365d6,
-	0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, 0xdb92f2fb,
-	0x5eea29cb, 0x145892f5, 0x91584f7f,
-	0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea, 0x833860d4,
-	0x0d23e0f9, 0x6c387e8a, 0x0ae6d249,
-	0xb284600c, 0xd835731d, 0xdcb1c647, 0xac4c56ea, 0x3ebd81b3,
-	0x230eabb0, 0x6438bc87, 0xf0b5b1fa,
-	0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, 0x649da589,
-	0xa345415e, 0x5c038323, 0x3e5d3bb9,
-	0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef, 0x7160a539,
-	0x73bfbe70, 0x83877605, 0x4523ecf1
-};
-
-static const u32 s3[256] = {
-	0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, 0x47607fff,
-	0x369fe44b, 0x8c1fc644, 0xaececa90,
-	0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae, 0x920e8806,
-	0xf0ad0548, 0xe13c8d83, 0x927010d5,
-	0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e, 0xb9afa820,
-	0xfade82e0, 0xa067268b, 0x8272792e,
-	0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc, 0x21fffcee,
-	0x825b1bfd, 0x9255c5ed, 0x1257a240,
-	0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e, 0x3373f7bf,
-	0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5,
-	0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f, 0x40fff7c1,
-	0x1fb78dfc, 0x8e6bd2c1, 0x437be59b,
-	0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99, 0xa197c81c,
-	0x4a012d6e, 0xc5884a28, 0xccc36f71,
-	0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, 0x2f7fe850,
-	0xd7c07f7e, 0x02507fbf, 0x5afb9a04,
-	0xa747d2d0, 0x1651192e, 0xaf70bf3e, 0x58c31380, 0x5f98302e,
-	0x727cc3c4, 0x0a0fb402, 0x0f7fef82,
-	0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8, 0x8427f4a0,
-	0x1eac5790, 0x796fb449, 0x8252dc15,
-	0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, 0xfa5d7403,
-	0xe83ec305, 0x4f91751a, 0x925669c2,
-	0x23efe941, 0xa903f12e, 0x60270df2, 0x0276e4b6, 0x94fd6574,
-	0x927985b2, 0x8276dbcb, 0x02778176,
-	0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, 0x842f7d83,
-	0x340ce5c8, 0x96bbb682, 0x93b4b148,
-	0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d, 0x224d1e20,
-	0x8437aa88, 0x7d29dc96, 0x2756d3dc,
-	0x8b907cee, 0xb51fd240, 0xe7c07ce3, 0xe566b4a1, 0xc3e9615e,
-	0x3cf8209d, 0x6094d1e3, 0xcd9ca341,
-	0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, 0xf76cedd9,
-	0xbda8229c, 0x127dadaa, 0x438a074e,
-	0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15, 0x97b03cff,
-	0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51,
-	0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4, 0xdd7ef86a,
-	0x76a2e214, 0xb9a40368, 0x925d958f,
-	0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b, 0x6d498623,
-	0x193cbcfa, 0x27627545, 0x825cf47a,
-	0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392, 0x10428db7,
-	0x8272a972, 0x9270c4a8, 0x127de50b,
-	0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231, 0x428929fb,
-	0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b,
-	0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889, 0x694bcc11,
-	0x236a5cae, 0x12deca4d, 0x2c3f8cc5,
-	0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, 0x494a488c,
-	0xb9b6a80c, 0x5c8f82bc, 0x89d36b45,
-	0x3a609437, 0xec00c9a9, 0x44715253, 0x0a874b49, 0xd773bc40,
-	0x7c34671c, 0x02717ef6, 0x4feb5536,
-	0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d, 0x07478cd1,
-	0x006e1888, 0xa2e53f55, 0xb9e6d4bc,
-	0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, 0x72f87b33,
-	0xabcc4f33, 0x7688c55d, 0x7b00a6b0,
-	0x947b0001, 0x570075d2, 0xf9bb88f8, 0x8942019e, 0x4264a5ff,
-	0x856302e0, 0x72dbd92b, 0xee971b69,
-	0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, 0xcf1febd2,
-	0x61efc8c2, 0xf1ac2571, 0xcc8239c2,
-	0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, 0xf90a5c38,
-	0x0ff0443d, 0x606e6dc6, 0x60543a49,
-	0x5727c148, 0x2be98a1d, 0x8ab41738, 0x20e1be24, 0xaf96da0f,
-	0x68458425, 0x99833be5, 0x600d457d,
-	0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, 0x642b1e31,
-	0x9c305a00, 0x52bce688, 0x1b03588a,
-	0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5, 0xdfef4636,
-	0xa133c501, 0xe9d3531c, 0xee353783
-};
-
-static const u32 s4[256] = {
-	0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, 0x4a4f7bdb,
-	0x64ad8c57, 0x85510443, 0xfa020ed1,
-	0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120, 0xfd059d43,
-	0x6497b7b1, 0xf3641f63, 0x241e4adf,
-	0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220, 0xfdd30b30,
-	0xc0a5374f, 0x1d2d00d9, 0x24147b15,
-	0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe, 0x1a05645f,
-	0x0c13fefe, 0x081b08ca, 0x05170121,
-	0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701, 0xd2b8ee5f,
-	0x06df4261, 0xbb9e9b8a, 0x7293ea25,
-	0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b, 0x7ed48400,
-	0x547eebe6, 0x446d4ca0, 0x6cf3d6f5,
-	0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93, 0xd3772061,
-	0x11b638e1, 0x72500e03, 0xf80eb2bb,
-	0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, 0xc9335400,
-	0x6920318f, 0x081dbb99, 0xffc304a5,
-	0x4d351805, 0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9, 0xdaec6fea,
-	0x9f926f91, 0x9f46222f, 0x3991467d,
-	0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb, 0x022083b8,
-	0x3fb6180c, 0x18f8931e, 0x281658e6,
-	0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, 0xf32d0a25,
-	0x79098b02, 0xe4eabb81, 0x28123b23,
-	0x69dead38, 0x1574ca16, 0xdf871b62, 0x211c40b7, 0xa51a9ef9,
-	0x0014377b, 0x041e8ac8, 0x09114003,
-	0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, 0x557be8de,
-	0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6,
-	0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327, 0x99afc8b0,
-	0x56c8c391, 0x6b65811c, 0x5e146119,
-	0x6e85cb75, 0xbe07c002, 0xc2325577, 0x893ff4ec, 0x5bbfc92d,
-	0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24,
-	0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, 0xaac9548a,
-	0xeca1d7c7, 0x041afa32, 0x1d16625a,
-	0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031, 0x36cc6fdb,
-	0xc70b8b46, 0xd9e66a48, 0x56e55a79,
-	0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5, 0x8674cde3,
-	0xedda04eb, 0x17a9be04, 0x2c18f4df,
-	0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c, 0x1741a254,
-	0xe5b6a035, 0x213d42f6, 0x2c1c7c26,
-	0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69, 0xd8167fa2,
-	0x0418f2c8, 0x001a96a6, 0x0d1526ab,
-	0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9, 0x8d0dbd86,
-	0x311170a7, 0x3e9b640c, 0xcc3e10d7,
-	0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff, 0x71eae2a1,
-	0x1f9af36e, 0xcfcbd12f, 0xc1de8417,
-	0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, 0xb1c52fca,
-	0xb4be31cd, 0xd8782806, 0x12a3a4e2,
-	0x6f7de532, 0x58fd7eb6, 0xd01ee900, 0x24adffc2, 0xf4990fc5,
-	0x9711aac5, 0x001d7b95, 0x82e5e7d2,
-	0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff, 0x29908415,
-	0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a,
-	0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, 0xd49e2ce7,
-	0x0ce454a9, 0xd60acd86, 0x015f1919,
-	0x77079103, 0xdea03af6, 0x78a8565e, 0xdee356df, 0x21f05cbe,
-	0x8b75e387, 0xb3c50651, 0xb8a5c3ef,
-	0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, 0xafe67afb,
-	0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876,
-	0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367, 0xa99144f8,
-	0x296b299e, 0x492fc295, 0x9266beab,
-	0xb5676e69, 0x9bd3ddda, 0xdf7e052f, 0xdb25701c, 0x1b5e51ee,
-	0xf65324e6, 0x6afce36c, 0x0316cc04,
-	0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, 0x41823979,
-	0x932bcdf6, 0xb657c34d, 0x4edfd282,
-	0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e, 0x13ecf0b0,
-	0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2
-};
-
-static const u32 Tm[24][8] = {
-	{ 0x5a827999, 0xc95c653a, 0x383650db, 0xa7103c7c, 0x15ea281d,
-		0x84c413be, 0xf39dff5f, 0x6277eb00 } ,
-	{ 0xd151d6a1, 0x402bc242, 0xaf05ade3, 0x1ddf9984, 0x8cb98525,
-		0xfb9370c6, 0x6a6d5c67, 0xd9474808 } ,
-	{ 0x482133a9, 0xb6fb1f4a, 0x25d50aeb, 0x94aef68c, 0x0388e22d,
-		0x7262cdce, 0xe13cb96f, 0x5016a510 } ,
-	{ 0xbef090b1, 0x2dca7c52, 0x9ca467f3, 0x0b7e5394, 0x7a583f35,
-		0xe9322ad6, 0x580c1677, 0xc6e60218 } ,
-	{ 0x35bfedb9, 0xa499d95a, 0x1373c4fb, 0x824db09c, 0xf1279c3d,
-		0x600187de, 0xcedb737f, 0x3db55f20 } ,
-	{ 0xac8f4ac1, 0x1b693662, 0x8a432203, 0xf91d0da4, 0x67f6f945,
-		0xd6d0e4e6, 0x45aad087, 0xb484bc28 } ,
-	{ 0x235ea7c9, 0x9238936a, 0x01127f0b, 0x6fec6aac, 0xdec6564d,
-		0x4da041ee, 0xbc7a2d8f, 0x2b541930 } ,
-	{ 0x9a2e04d1, 0x0907f072, 0x77e1dc13, 0xe6bbc7b4, 0x5595b355,
-		0xc46f9ef6, 0x33498a97, 0xa2237638 } ,
-	{ 0x10fd61d9, 0x7fd74d7a, 0xeeb1391b, 0x5d8b24bc, 0xcc65105d,
-		0x3b3efbfe, 0xaa18e79f, 0x18f2d340 } ,
-	{ 0x87ccbee1, 0xf6a6aa82, 0x65809623, 0xd45a81c4, 0x43346d65,
-		0xb20e5906, 0x20e844a7, 0x8fc23048 } ,
-	{ 0xfe9c1be9, 0x6d76078a, 0xdc4ff32b, 0x4b29decc, 0xba03ca6d,
-		0x28ddb60e, 0x97b7a1af, 0x06918d50 } ,
-	{ 0x756b78f1, 0xe4456492, 0x531f5033, 0xc1f93bd4, 0x30d32775,
-		0x9fad1316, 0x0e86feb7, 0x7d60ea58 } ,
-	{ 0xec3ad5f9, 0x5b14c19a, 0xc9eead3b, 0x38c898dc, 0xa7a2847d,
-		0x167c701e, 0x85565bbf, 0xf4304760 } ,
-	{ 0x630a3301, 0xd1e41ea2, 0x40be0a43, 0xaf97f5e4, 0x1e71e185,
-		0x8d4bcd26, 0xfc25b8c7, 0x6affa468 } ,
-	{ 0xd9d99009, 0x48b37baa, 0xb78d674b, 0x266752ec, 0x95413e8d,
-		0x041b2a2e, 0x72f515cf, 0xe1cf0170 } ,
-	{ 0x50a8ed11, 0xbf82d8b2, 0x2e5cc453, 0x9d36aff4, 0x0c109b95,
-		0x7aea8736, 0xe9c472d7, 0x589e5e78 } ,
-	{ 0xc7784a19, 0x365235ba, 0xa52c215b, 0x14060cfc, 0x82dff89d,
-		0xf1b9e43e, 0x6093cfdf, 0xcf6dbb80 } ,
-	{ 0x3e47a721, 0xad2192c2, 0x1bfb7e63, 0x8ad56a04, 0xf9af55a5,
-		0x68894146, 0xd7632ce7, 0x463d1888 } ,
-	{ 0xb5170429, 0x23f0efca, 0x92cadb6b, 0x01a4c70c, 0x707eb2ad,
-		0xdf589e4e, 0x4e3289ef, 0xbd0c7590 } ,
-	{ 0x2be66131, 0x9ac04cd2, 0x099a3873, 0x78742414, 0xe74e0fb5,
-		0x5627fb56, 0xc501e6f7, 0x33dbd298 } ,
-	{ 0xa2b5be39, 0x118fa9da, 0x8069957b, 0xef43811c, 0x5e1d6cbd,
-		0xccf7585e, 0x3bd143ff, 0xaaab2fa0 } ,
-	{ 0x19851b41, 0x885f06e2, 0xf738f283, 0x6612de24, 0xd4ecc9c5,
-		0x43c6b566, 0xb2a0a107, 0x217a8ca8 } ,
-	{ 0x90547849, 0xff2e63ea, 0x6e084f8b, 0xdce23b2c, 0x4bbc26cd,
-		0xba96126e, 0x296ffe0f, 0x9849e9b0 } ,
-	{ 0x0723d551, 0x75fdc0f2, 0xe4d7ac93, 0x53b19834, 0xc28b83d5,
-		0x31656f76, 0xa03f5b17, 0x0f1946b8 }
-};
-
-static const u8 Tr[4][8] = {
-	{ 0x13, 0x04, 0x15, 0x06, 0x17, 0x08, 0x19, 0x0a } ,
-	{ 0x1b, 0x0c, 0x1d, 0x0e, 0x1f, 0x10, 0x01, 0x12 } ,
-	{ 0x03, 0x14, 0x05, 0x16, 0x07, 0x18, 0x09, 0x1a } ,
-	{ 0x0b, 0x1c, 0x0d, 0x1e, 0x0f, 0x00, 0x11, 0x02 }
-};
-
-/* forward octave */
-static void W(u32 *key, unsigned int i)
-{
-	u32 I;
-	key[6] ^= F1(key[7], Tr[i % 4][0], Tm[i][0]);
-	key[5] ^= F2(key[6], Tr[i % 4][1], Tm[i][1]);
-	key[4] ^= F3(key[5], Tr[i % 4][2], Tm[i][2]);
-	key[3] ^= F1(key[4], Tr[i % 4][3], Tm[i][3]);
-	key[2] ^= F2(key[3], Tr[i % 4][4], Tm[i][4]);
-	key[1] ^= F3(key[2], Tr[i % 4][5], Tm[i][5]);
-	key[0] ^= F1(key[1], Tr[i % 4][6], Tm[i][6]);
-	key[7] ^= F2(key[0], Tr[i % 4][7], Tm[i][7]);
-}
-
-static int cast6_setkey(struct crypto_tfm *tfm, const u8 *in_key,
-			unsigned key_len)
-{
-	int i;
-	u32 key[8];
-	__be32 p_key[8]; /* padded key */
-	struct cast6_ctx *c = crypto_tfm_ctx(tfm);
-	u32 *flags = &tfm->crt_flags;
-
-	if (key_len % 4 != 0) {
-		*flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
-		return -EINVAL;
-	}
-
-	memset(p_key, 0, 32);
-	memcpy(p_key, in_key, key_len);
-
-	key[0] = be32_to_cpu(p_key[0]);		/* A */
-	key[1] = be32_to_cpu(p_key[1]);		/* B */
-	key[2] = be32_to_cpu(p_key[2]);		/* C */
-	key[3] = be32_to_cpu(p_key[3]);		/* D */
-	key[4] = be32_to_cpu(p_key[4]);		/* E */
-	key[5] = be32_to_cpu(p_key[5]);		/* F */
-	key[6] = be32_to_cpu(p_key[6]);		/* G */
-	key[7] = be32_to_cpu(p_key[7]);		/* H */
-
-	for (i = 0; i < 12; i++) {
-		W(key, 2 * i);
-		W(key, 2 * i + 1);
-
-		c->Kr[i][0] = key[0] & 0x1f;
-		c->Kr[i][1] = key[2] & 0x1f;
-		c->Kr[i][2] = key[4] & 0x1f;
-		c->Kr[i][3] = key[6] & 0x1f;
-
-		c->Km[i][0] = key[7];
-		c->Km[i][1] = key[5];
-		c->Km[i][2] = key[3];
-		c->Km[i][3] = key[1];
-	}
-
-	return 0;
-}
-
-/*forward quad round*/
-static void Q(u32 *block, u8 *Kr, u32 *Km)
-{
-	u32 I;
-	block[2] ^= F1(block[3], Kr[0], Km[0]);
-	block[1] ^= F2(block[2], Kr[1], Km[1]);
-	block[0] ^= F3(block[1], Kr[2], Km[2]);
-	block[3] ^= F1(block[0], Kr[3], Km[3]);
-}
-
-/*reverse quad round*/
-static void QBAR(u32 *block, u8 *Kr, u32 *Km)
-{
-	u32 I;
-	block[3] ^= F1(block[0], Kr[3], Km[3]);
-	block[0] ^= F3(block[1], Kr[2], Km[2]);
-	block[1] ^= F2(block[2], Kr[1], Km[1]);
-	block[2] ^= F1(block[3], Kr[0], Km[0]);
-}
-
-static void cast6_encrypt(struct crypto_tfm *tfm, u8 *outbuf, const u8 *inbuf)
-{
-	struct cast6_ctx *c = crypto_tfm_ctx(tfm);
-	const __be32 *src = (const __be32 *)inbuf;
-	__be32 *dst = (__be32 *)outbuf;
-	u32 block[4];
-	u32 *Km;
-	u8 *Kr;
-
-	block[0] = be32_to_cpu(src[0]);
-	block[1] = be32_to_cpu(src[1]);
-	block[2] = be32_to_cpu(src[2]);
-	block[3] = be32_to_cpu(src[3]);
-
-	Km = c->Km[0]; Kr = c->Kr[0]; Q(block, Kr, Km);
-	Km = c->Km[1]; Kr = c->Kr[1]; Q(block, Kr, Km);
-	Km = c->Km[2]; Kr = c->Kr[2]; Q(block, Kr, Km);
-	Km = c->Km[3]; Kr = c->Kr[3]; Q(block, Kr, Km);
-	Km = c->Km[4]; Kr = c->Kr[4]; Q(block, Kr, Km);
-	Km = c->Km[5]; Kr = c->Kr[5]; Q(block, Kr, Km);
-	Km = c->Km[6]; Kr = c->Kr[6]; QBAR(block, Kr, Km);
-	Km = c->Km[7]; Kr = c->Kr[7]; QBAR(block, Kr, Km);
-	Km = c->Km[8]; Kr = c->Kr[8]; QBAR(block, Kr, Km);
-	Km = c->Km[9]; Kr = c->Kr[9]; QBAR(block, Kr, Km);
-	Km = c->Km[10]; Kr = c->Kr[10]; QBAR(block, Kr, Km);
-	Km = c->Km[11]; Kr = c->Kr[11]; QBAR(block, Kr, Km);
-
-	dst[0] = cpu_to_be32(block[0]);
-	dst[1] = cpu_to_be32(block[1]);
-	dst[2] = cpu_to_be32(block[2]);
-	dst[3] = cpu_to_be32(block[3]);
-}
-
-static void cast6_decrypt(struct crypto_tfm *tfm, u8 *outbuf, const u8 *inbuf)
-{
-	struct cast6_ctx *c = crypto_tfm_ctx(tfm);
-	const __be32 *src = (const __be32 *)inbuf;
-	__be32 *dst = (__be32 *)outbuf;
-	u32 block[4];
-	u32 *Km;
-	u8 *Kr;
-
-	block[0] = be32_to_cpu(src[0]);
-	block[1] = be32_to_cpu(src[1]);
-	block[2] = be32_to_cpu(src[2]);
-	block[3] = be32_to_cpu(src[3]);
-
-	Km = c->Km[11]; Kr = c->Kr[11]; Q(block, Kr, Km);
-	Km = c->Km[10]; Kr = c->Kr[10]; Q(block, Kr, Km);
-	Km = c->Km[9]; Kr = c->Kr[9]; Q(block, Kr, Km);
-	Km = c->Km[8]; Kr = c->Kr[8]; Q(block, Kr, Km);
-	Km = c->Km[7]; Kr = c->Kr[7]; Q(block, Kr, Km);
-	Km = c->Km[6]; Kr = c->Kr[6]; Q(block, Kr, Km);
-	Km = c->Km[5]; Kr = c->Kr[5]; QBAR(block, Kr, Km);
-	Km = c->Km[4]; Kr = c->Kr[4]; QBAR(block, Kr, Km);
-	Km = c->Km[3]; Kr = c->Kr[3]; QBAR(block, Kr, Km);
-	Km = c->Km[2]; Kr = c->Kr[2]; QBAR(block, Kr, Km);
-	Km = c->Km[1]; Kr = c->Kr[1]; QBAR(block, Kr, Km);
-	Km = c->Km[0]; Kr = c->Kr[0]; QBAR(block, Kr, Km);
-
-	dst[0] = cpu_to_be32(block[0]);
-	dst[1] = cpu_to_be32(block[1]);
-	dst[2] = cpu_to_be32(block[2]);
-	dst[3] = cpu_to_be32(block[3]);
-}
-
-static struct crypto_alg alg = {
-	.cra_name = "cast6",
-	.cra_flags = CRYPTO_ALG_TYPE_CIPHER,
-	.cra_blocksize = CAST6_BLOCK_SIZE,
-	.cra_ctxsize = sizeof(struct cast6_ctx),
-	.cra_alignmask = 3,
-	.cra_module = THIS_MODULE,
-	.cra_list = LIST_HEAD_INIT(alg.cra_list),
-	.cra_u = {
-		  .cipher = {
-			     .cia_min_keysize = CAST6_MIN_KEY_SIZE,
-			     .cia_max_keysize = CAST6_MAX_KEY_SIZE,
-			     .cia_setkey = cast6_setkey,
-			     .cia_encrypt = cast6_encrypt,
-			     .cia_decrypt = cast6_decrypt}
-		  }
-};
-
-static int __init cast6_mod_init(void)
-{
-	return crypto_register_alg(&alg);
-}
-
-static void __exit cast6_mod_fini(void)
-{
-	crypto_unregister_alg(&alg);
-}
-
-module_init(cast6_mod_init);
-module_exit(cast6_mod_fini);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Cast6 Cipher Algorithm");
diff --git a/crypto/cast6_generic.c b/crypto/cast6_generic.c
new file mode 100644
index 0000000..1acd2f1
--- /dev/null
+++ b/crypto/cast6_generic.c
@@ -0,0 +1,566 @@
+/* Kernel cryptographic api.
+ * cast6.c - Cast6 cipher algorithm [rfc2612].
+ *
+ * CAST-256 (*cast6*) is a DES like Substitution-Permutation Network (SPN)
+ * cryptosystem built upon the CAST-128 (*cast5*) [rfc2144] encryption
+ * algorithm.
+ *
+ * Copyright (C) 2003 Kartikey Mahendra Bhatt <kartik_me@hotmail.com>.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+
+#include <asm/byteorder.h>
+#include <linux/init.h>
+#include <linux/crypto.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <crypto/cast6.h>
+
+#define s1 cast6_s1
+#define s2 cast6_s2
+#define s3 cast6_s3
+#define s4 cast6_s4
+
+#define F1(D, r, m)  ((I = ((m) + (D))), (I = rol32(I, (r))),   \
+	(((s1[I >> 24] ^ s2[(I>>16)&0xff]) - s3[(I>>8)&0xff]) + s4[I&0xff]))
+#define F2(D, r, m)  ((I = ((m) ^ (D))), (I = rol32(I, (r))),   \
+	(((s1[I >> 24] - s2[(I>>16)&0xff]) + s3[(I>>8)&0xff]) ^ s4[I&0xff]))
+#define F3(D, r, m)  ((I = ((m) - (D))), (I = rol32(I, (r))),   \
+	(((s1[I >> 24] + s2[(I>>16)&0xff]) ^ s3[(I>>8)&0xff]) - s4[I&0xff]))
+
+const u32 cast6_s1[256] = {
+	0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f,
+	0x9c004dd3, 0x6003e540, 0xcf9fc949,
+	0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675, 0x6e63a0e0,
+	0x15c361d2, 0xc2e7661d, 0x22d4ff8e,
+	0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2, 0x43c340d3,
+	0xdf2f8656, 0x887ca41a, 0xa2d2bd2d,
+	0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f, 0x2abe32e1,
+	0xaa54166b, 0x22568e3a, 0xa2d341d0,
+	0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de, 0x97943fac,
+	0x4a97c1d8, 0x527644b7, 0xb5f437a7,
+	0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f, 0x827b68d0,
+	0x90ecf52e, 0x22b0c054, 0xbc8e5935,
+	0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d, 0xb7332290,
+	0xe93b159f, 0xb48ee411, 0x4bff345d,
+	0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, 0xd5b1caad,
+	0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50,
+	0x882240f2, 0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272, 0x564c1d2f,
+	0xc59c5319, 0xb949e354, 0xb04669fe,
+	0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d, 0x57538ad5,
+	0x6a390493, 0xe63d37e0, 0x2a54f6b3,
+	0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, 0x29f9d4d5,
+	0xf61b1891, 0xbb72275e, 0xaa508167,
+	0x38901091, 0xc6b505eb, 0x84c7cb8c, 0x2ad75a0f, 0x874a1427,
+	0xa2d1936b, 0x2ad286af, 0xaa56d291,
+	0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, 0x6c00b32d,
+	0x73e2bb14, 0xa0bebc3c, 0x54623779,
+	0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6, 0x04ee002e,
+	0x89fe78e6, 0x3fab0950, 0x325ff6c2,
+	0x81383f05, 0x6963c5c8, 0x76cb5ad6, 0xd49974c9, 0xca180dcf,
+	0x380782d5, 0xc7fa5cf6, 0x8ac31511,
+	0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, 0x31366241,
+	0x051ef495, 0xaa573b04, 0x4a805d8d,
+	0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e, 0x75c6372b,
+	0x50afd341, 0xa7c13275, 0x915a0bf5,
+	0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82, 0xf7fbf265,
+	0xab85c5f3, 0x1b55db94, 0xaad4e324,
+	0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, 0xeadf55b3,
+	0xd5bd9e98, 0xe31231b2, 0x2ad5ad6c,
+	0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f, 0xaa786bf6,
+	0x22513f1e, 0xaa51a79b, 0x2ad344cc,
+	0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491, 0xb4c332e6,
+	0x032268d4, 0xc9600acc, 0xce387e6d,
+	0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de, 0xe01063da,
+	0x4736f464, 0x5ad328d8, 0xb347cc96,
+	0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, 0xe11f0abc,
+	0xbfc5fe4a, 0xa70aec10, 0xac39570a,
+	0x3f04442f, 0x6188b153, 0xe0397a2e, 0x5727cb79, 0x9ceb418f,
+	0x1cacd68d, 0x2ad37c96, 0x0175cb9d,
+	0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779, 0x4744ead4,
+	0xb11c3274, 0xdd24cb9e, 0x7e1c54bd,
+	0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, 0xd47c27af,
+	0x51c85f4d, 0x56907596, 0xa5bb15e6,
+	0x580304f0, 0xca042cf1, 0x011a37ea, 0x8dbfaadb, 0x35ba3e4a,
+	0x3526ffa0, 0xc37b4d09, 0xbc306ed9,
+	0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, 0x7c63b2cf,
+	0x700b45e1, 0xd5ea50f1, 0x85a92872,
+	0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79, 0x42e04198,
+	0x0cd0ede7, 0x26470db8, 0xf881814c,
+	0x474d6ad7, 0x7c0c5e5c, 0xd1231959, 0x381b7298, 0xf5d2f4db,
+	0xab838653, 0x6e2f1e23, 0x83719c9e,
+	0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, 0x962bda1c,
+	0xe1e696ff, 0xb141ab08, 0x7cca89b9,
+	0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d, 0x427b169c,
+	0x5ac9f049, 0xdd8f0f00, 0x5c8165bf
+};
+EXPORT_SYMBOL_GPL(cast6_s1);
+
+const u32 cast6_s2[256] = {
+	0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, 0xfe61cf7a,
+	0xeec5207a, 0x55889c94, 0x72fc0651,
+	0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba, 0x99c430ef,
+	0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3,
+	0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909, 0xdc440086,
+	0xef944459, 0xba83ccb3, 0xe0c3cdfb,
+	0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, 0x01420ddb,
+	0xe4e7ef5b, 0x25a1ff41, 0xe180f806,
+	0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4, 0x98de8b7f,
+	0x77e83f4e, 0x79929269, 0x24fa9f7b,
+	0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f, 0x62143154,
+	0x0d554b63, 0x5d681121, 0xc866c359,
+	0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21, 0x071f6181,
+	0x39f7627f, 0x361e3084, 0xe4eb573b,
+	0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, 0x2701f50c,
+	0x99847ab4, 0xa0e3df79, 0xba6cf38c,
+	0x10843094, 0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f, 0x208cfb6a,
+	0x8f458c74, 0xd9e0a227, 0x4ec73a34,
+	0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d, 0x8a45388c,
+	0x1d804366, 0x721d9bfd, 0xa58684bb,
+	0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, 0xce280ae1,
+	0x27e19ba5, 0xd5a6c252, 0xe49754bd,
+	0xc5d655dd, 0xeb667064, 0x77840b4d, 0xa1b6a801, 0x84db26a9,
+	0xe0b56714, 0x21f043b7, 0xe5d05860,
+	0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, 0xb5625dbf,
+	0x68561be6, 0x83ca6b94, 0x2d6ed23b,
+	0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, 0x33b4a34c,
+	0x397bc8d6, 0x5ee22b95, 0x5f0e5304,
+	0x81ed6f61, 0x20e74364, 0xb45e1378, 0xde18639b, 0x881ca122,
+	0xb96726d1, 0x8049a7e8, 0x22b7da7b,
+	0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, 0x488cb402,
+	0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf,
+	0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9, 0x0beeff53,
+	0xe3214517, 0xb4542835, 0x9f63293c,
+	0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3, 0xf33401c6,
+	0x30a22c95, 0x31a70850, 0x60930f13,
+	0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9, 0xcdff33a6,
+	0xa02b1741, 0x7cbad9a2, 0x2180036f,
+	0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab, 0x80342676,
+	0x25a75e7b, 0xe4e6d1fc, 0x20c710e6,
+	0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4, 0x2ccb49eb,
+	0x846a3bae, 0x8ff77888, 0xee5d60f6,
+	0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43, 0xb3faec54,
+	0x157fd7fa, 0xef8579cc, 0xd152de58,
+	0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, 0x99319ad5,
+	0xc242fa0f, 0xa7e3ebb0, 0xc68e4906,
+	0xb8da230c, 0x80823028, 0xdcdef3c8, 0xd35fb171, 0x088a1bc8,
+	0xbec0c560, 0x61a3c9e8, 0xbca8f54d,
+	0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89, 0x8b1c34bc,
+	0x301e16e6, 0x273be979, 0xb0ffeaa6,
+	0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, 0x43daf65a,
+	0xf7e19798, 0x7619b72f, 0x8f1c9ba4,
+	0xdc8637a0, 0x16a7d3b1, 0x9fc393b7, 0xa7136eeb, 0xc6bcc63e,
+	0x1a513742, 0xef6828bc, 0x520365d6,
+	0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, 0xdb92f2fb,
+	0x5eea29cb, 0x145892f5, 0x91584f7f,
+	0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea, 0x833860d4,
+	0x0d23e0f9, 0x6c387e8a, 0x0ae6d249,
+	0xb284600c, 0xd835731d, 0xdcb1c647, 0xac4c56ea, 0x3ebd81b3,
+	0x230eabb0, 0x6438bc87, 0xf0b5b1fa,
+	0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, 0x649da589,
+	0xa345415e, 0x5c038323, 0x3e5d3bb9,
+	0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef, 0x7160a539,
+	0x73bfbe70, 0x83877605, 0x4523ecf1
+};
+EXPORT_SYMBOL_GPL(cast6_s2);
+
+const u32 cast6_s3[256] = {
+	0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, 0x47607fff,
+	0x369fe44b, 0x8c1fc644, 0xaececa90,
+	0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae, 0x920e8806,
+	0xf0ad0548, 0xe13c8d83, 0x927010d5,
+	0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e, 0xb9afa820,
+	0xfade82e0, 0xa067268b, 0x8272792e,
+	0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc, 0x21fffcee,
+	0x825b1bfd, 0x9255c5ed, 0x1257a240,
+	0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e, 0x3373f7bf,
+	0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5,
+	0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f, 0x40fff7c1,
+	0x1fb78dfc, 0x8e6bd2c1, 0x437be59b,
+	0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99, 0xa197c81c,
+	0x4a012d6e, 0xc5884a28, 0xccc36f71,
+	0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, 0x2f7fe850,
+	0xd7c07f7e, 0x02507fbf, 0x5afb9a04,
+	0xa747d2d0, 0x1651192e, 0xaf70bf3e, 0x58c31380, 0x5f98302e,
+	0x727cc3c4, 0x0a0fb402, 0x0f7fef82,
+	0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8, 0x8427f4a0,
+	0x1eac5790, 0x796fb449, 0x8252dc15,
+	0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, 0xfa5d7403,
+	0xe83ec305, 0x4f91751a, 0x925669c2,
+	0x23efe941, 0xa903f12e, 0x60270df2, 0x0276e4b6, 0x94fd6574,
+	0x927985b2, 0x8276dbcb, 0x02778176,
+	0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, 0x842f7d83,
+	0x340ce5c8, 0x96bbb682, 0x93b4b148,
+	0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d, 0x224d1e20,
+	0x8437aa88, 0x7d29dc96, 0x2756d3dc,
+	0x8b907cee, 0xb51fd240, 0xe7c07ce3, 0xe566b4a1, 0xc3e9615e,
+	0x3cf8209d, 0x6094d1e3, 0xcd9ca341,
+	0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, 0xf76cedd9,
+	0xbda8229c, 0x127dadaa, 0x438a074e,
+	0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15, 0x97b03cff,
+	0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51,
+	0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4, 0xdd7ef86a,
+	0x76a2e214, 0xb9a40368, 0x925d958f,
+	0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b, 0x6d498623,
+	0x193cbcfa, 0x27627545, 0x825cf47a,
+	0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392, 0x10428db7,
+	0x8272a972, 0x9270c4a8, 0x127de50b,
+	0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231, 0x428929fb,
+	0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b,
+	0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889, 0x694bcc11,
+	0x236a5cae, 0x12deca4d, 0x2c3f8cc5,
+	0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, 0x494a488c,
+	0xb9b6a80c, 0x5c8f82bc, 0x89d36b45,
+	0x3a609437, 0xec00c9a9, 0x44715253, 0x0a874b49, 0xd773bc40,
+	0x7c34671c, 0x02717ef6, 0x4feb5536,
+	0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d, 0x07478cd1,
+	0x006e1888, 0xa2e53f55, 0xb9e6d4bc,
+	0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, 0x72f87b33,
+	0xabcc4f33, 0x7688c55d, 0x7b00a6b0,
+	0x947b0001, 0x570075d2, 0xf9bb88f8, 0x8942019e, 0x4264a5ff,
+	0x856302e0, 0x72dbd92b, 0xee971b69,
+	0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, 0xcf1febd2,
+	0x61efc8c2, 0xf1ac2571, 0xcc8239c2,
+	0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, 0xf90a5c38,
+	0x0ff0443d, 0x606e6dc6, 0x60543a49,
+	0x5727c148, 0x2be98a1d, 0x8ab41738, 0x20e1be24, 0xaf96da0f,
+	0x68458425, 0x99833be5, 0x600d457d,
+	0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, 0x642b1e31,
+	0x9c305a00, 0x52bce688, 0x1b03588a,
+	0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5, 0xdfef4636,
+	0xa133c501, 0xe9d3531c, 0xee353783
+};
+EXPORT_SYMBOL_GPL(cast6_s3);
+
+const u32 cast6_s4[256] = {
+	0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, 0x4a4f7bdb,
+	0x64ad8c57, 0x85510443, 0xfa020ed1,
+	0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120, 0xfd059d43,
+	0x6497b7b1, 0xf3641f63, 0x241e4adf,
+	0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220, 0xfdd30b30,
+	0xc0a5374f, 0x1d2d00d9, 0x24147b15,
+	0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe, 0x1a05645f,
+	0x0c13fefe, 0x081b08ca, 0x05170121,
+	0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701, 0xd2b8ee5f,
+	0x06df4261, 0xbb9e9b8a, 0x7293ea25,
+	0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b, 0x7ed48400,
+	0x547eebe6, 0x446d4ca0, 0x6cf3d6f5,
+	0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93, 0xd3772061,
+	0x11b638e1, 0x72500e03, 0xf80eb2bb,
+	0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, 0xc9335400,
+	0x6920318f, 0x081dbb99, 0xffc304a5,
+	0x4d351805, 0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9, 0xdaec6fea,
+	0x9f926f91, 0x9f46222f, 0x3991467d,
+	0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb, 0x022083b8,
+	0x3fb6180c, 0x18f8931e, 0x281658e6,
+	0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, 0xf32d0a25,
+	0x79098b02, 0xe4eabb81, 0x28123b23,
+	0x69dead38, 0x1574ca16, 0xdf871b62, 0x211c40b7, 0xa51a9ef9,
+	0x0014377b, 0x041e8ac8, 0x09114003,
+	0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, 0x557be8de,
+	0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6,
+	0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327, 0x99afc8b0,
+	0x56c8c391, 0x6b65811c, 0x5e146119,
+	0x6e85cb75, 0xbe07c002, 0xc2325577, 0x893ff4ec, 0x5bbfc92d,
+	0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24,
+	0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, 0xaac9548a,
+	0xeca1d7c7, 0x041afa32, 0x1d16625a,
+	0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031, 0x36cc6fdb,
+	0xc70b8b46, 0xd9e66a48, 0x56e55a79,
+	0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5, 0x8674cde3,
+	0xedda04eb, 0x17a9be04, 0x2c18f4df,
+	0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c, 0x1741a254,
+	0xe5b6a035, 0x213d42f6, 0x2c1c7c26,
+	0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69, 0xd8167fa2,
+	0x0418f2c8, 0x001a96a6, 0x0d1526ab,
+	0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9, 0x8d0dbd86,
+	0x311170a7, 0x3e9b640c, 0xcc3e10d7,
+	0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff, 0x71eae2a1,
+	0x1f9af36e, 0xcfcbd12f, 0xc1de8417,
+	0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, 0xb1c52fca,
+	0xb4be31cd, 0xd8782806, 0x12a3a4e2,
+	0x6f7de532, 0x58fd7eb6, 0xd01ee900, 0x24adffc2, 0xf4990fc5,
+	0x9711aac5, 0x001d7b95, 0x82e5e7d2,
+	0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff, 0x29908415,
+	0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a,
+	0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, 0xd49e2ce7,
+	0x0ce454a9, 0xd60acd86, 0x015f1919,
+	0x77079103, 0xdea03af6, 0x78a8565e, 0xdee356df, 0x21f05cbe,
+	0x8b75e387, 0xb3c50651, 0xb8a5c3ef,
+	0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, 0xafe67afb,
+	0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876,
+	0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367, 0xa99144f8,
+	0x296b299e, 0x492fc295, 0x9266beab,
+	0xb5676e69, 0x9bd3ddda, 0xdf7e052f, 0xdb25701c, 0x1b5e51ee,
+	0xf65324e6, 0x6afce36c, 0x0316cc04,
+	0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, 0x41823979,
+	0x932bcdf6, 0xb657c34d, 0x4edfd282,
+	0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e, 0x13ecf0b0,
+	0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2
+};
+EXPORT_SYMBOL_GPL(cast6_s4);
+
+static const u32 Tm[24][8] = {
+	{ 0x5a827999, 0xc95c653a, 0x383650db, 0xa7103c7c, 0x15ea281d,
+		0x84c413be, 0xf39dff5f, 0x6277eb00 } ,
+	{ 0xd151d6a1, 0x402bc242, 0xaf05ade3, 0x1ddf9984, 0x8cb98525,
+		0xfb9370c6, 0x6a6d5c67, 0xd9474808 } ,
+	{ 0x482133a9, 0xb6fb1f4a, 0x25d50aeb, 0x94aef68c, 0x0388e22d,
+		0x7262cdce, 0xe13cb96f, 0x5016a510 } ,
+	{ 0xbef090b1, 0x2dca7c52, 0x9ca467f3, 0x0b7e5394, 0x7a583f35,
+		0xe9322ad6, 0x580c1677, 0xc6e60218 } ,
+	{ 0x35bfedb9, 0xa499d95a, 0x1373c4fb, 0x824db09c, 0xf1279c3d,
+		0x600187de, 0xcedb737f, 0x3db55f20 } ,
+	{ 0xac8f4ac1, 0x1b693662, 0x8a432203, 0xf91d0da4, 0x67f6f945,
+		0xd6d0e4e6, 0x45aad087, 0xb484bc28 } ,
+	{ 0x235ea7c9, 0x9238936a, 0x01127f0b, 0x6fec6aac, 0xdec6564d,
+		0x4da041ee, 0xbc7a2d8f, 0x2b541930 } ,
+	{ 0x9a2e04d1, 0x0907f072, 0x77e1dc13, 0xe6bbc7b4, 0x5595b355,
+		0xc46f9ef6, 0x33498a97, 0xa2237638 } ,
+	{ 0x10fd61d9, 0x7fd74d7a, 0xeeb1391b, 0x5d8b24bc, 0xcc65105d,
+		0x3b3efbfe, 0xaa18e79f, 0x18f2d340 } ,
+	{ 0x87ccbee1, 0xf6a6aa82, 0x65809623, 0xd45a81c4, 0x43346d65,
+		0xb20e5906, 0x20e844a7, 0x8fc23048 } ,
+	{ 0xfe9c1be9, 0x6d76078a, 0xdc4ff32b, 0x4b29decc, 0xba03ca6d,
+		0x28ddb60e, 0x97b7a1af, 0x06918d50 } ,
+	{ 0x756b78f1, 0xe4456492, 0x531f5033, 0xc1f93bd4, 0x30d32775,
+		0x9fad1316, 0x0e86feb7, 0x7d60ea58 } ,
+	{ 0xec3ad5f9, 0x5b14c19a, 0xc9eead3b, 0x38c898dc, 0xa7a2847d,
+		0x167c701e, 0x85565bbf, 0xf4304760 } ,
+	{ 0x630a3301, 0xd1e41ea2, 0x40be0a43, 0xaf97f5e4, 0x1e71e185,
+		0x8d4bcd26, 0xfc25b8c7, 0x6affa468 } ,
+	{ 0xd9d99009, 0x48b37baa, 0xb78d674b, 0x266752ec, 0x95413e8d,
+		0x041b2a2e, 0x72f515cf, 0xe1cf0170 } ,
+	{ 0x50a8ed11, 0xbf82d8b2, 0x2e5cc453, 0x9d36aff4, 0x0c109b95,
+		0x7aea8736, 0xe9c472d7, 0x589e5e78 } ,
+	{ 0xc7784a19, 0x365235ba, 0xa52c215b, 0x14060cfc, 0x82dff89d,
+		0xf1b9e43e, 0x6093cfdf, 0xcf6dbb80 } ,
+	{ 0x3e47a721, 0xad2192c2, 0x1bfb7e63, 0x8ad56a04, 0xf9af55a5,
+		0x68894146, 0xd7632ce7, 0x463d1888 } ,
+	{ 0xb5170429, 0x23f0efca, 0x92cadb6b, 0x01a4c70c, 0x707eb2ad,
+		0xdf589e4e, 0x4e3289ef, 0xbd0c7590 } ,
+	{ 0x2be66131, 0x9ac04cd2, 0x099a3873, 0x78742414, 0xe74e0fb5,
+		0x5627fb56, 0xc501e6f7, 0x33dbd298 } ,
+	{ 0xa2b5be39, 0x118fa9da, 0x8069957b, 0xef43811c, 0x5e1d6cbd,
+		0xccf7585e, 0x3bd143ff, 0xaaab2fa0 } ,
+	{ 0x19851b41, 0x885f06e2, 0xf738f283, 0x6612de24, 0xd4ecc9c5,
+		0x43c6b566, 0xb2a0a107, 0x217a8ca8 } ,
+	{ 0x90547849, 0xff2e63ea, 0x6e084f8b, 0xdce23b2c, 0x4bbc26cd,
+		0xba96126e, 0x296ffe0f, 0x9849e9b0 } ,
+	{ 0x0723d551, 0x75fdc0f2, 0xe4d7ac93, 0x53b19834, 0xc28b83d5,
+		0x31656f76, 0xa03f5b17, 0x0f1946b8 }
+};
+
+static const u8 Tr[4][8] = {
+	{ 0x13, 0x04, 0x15, 0x06, 0x17, 0x08, 0x19, 0x0a } ,
+	{ 0x1b, 0x0c, 0x1d, 0x0e, 0x1f, 0x10, 0x01, 0x12 } ,
+	{ 0x03, 0x14, 0x05, 0x16, 0x07, 0x18, 0x09, 0x1a } ,
+	{ 0x0b, 0x1c, 0x0d, 0x1e, 0x0f, 0x00, 0x11, 0x02 }
+};
+
+/* forward octave */
+static inline void W(u32 *key, unsigned int i)
+{
+	u32 I;
+	key[6] ^= F1(key[7], Tr[i % 4][0], Tm[i][0]);
+	key[5] ^= F2(key[6], Tr[i % 4][1], Tm[i][1]);
+	key[4] ^= F3(key[5], Tr[i % 4][2], Tm[i][2]);
+	key[3] ^= F1(key[4], Tr[i % 4][3], Tm[i][3]);
+	key[2] ^= F2(key[3], Tr[i % 4][4], Tm[i][4]);
+	key[1] ^= F3(key[2], Tr[i % 4][5], Tm[i][5]);
+	key[0] ^= F1(key[1], Tr[i % 4][6], Tm[i][6]);
+	key[7] ^= F2(key[0], Tr[i % 4][7], Tm[i][7]);
+}
+
+int __cast6_setkey(struct cast6_ctx *c, const u8 *in_key,
+		   unsigned key_len, u32 *flags)
+{
+	int i;
+	u32 key[8];
+	__be32 p_key[8]; /* padded key */
+
+	if (key_len % 4 != 0) {
+		*flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+		return -EINVAL;
+	}
+
+	memset(p_key, 0, 32);
+	memcpy(p_key, in_key, key_len);
+
+	key[0] = be32_to_cpu(p_key[0]);		/* A */
+	key[1] = be32_to_cpu(p_key[1]);		/* B */
+	key[2] = be32_to_cpu(p_key[2]);		/* C */
+	key[3] = be32_to_cpu(p_key[3]);		/* D */
+	key[4] = be32_to_cpu(p_key[4]);		/* E */
+	key[5] = be32_to_cpu(p_key[5]);		/* F */
+	key[6] = be32_to_cpu(p_key[6]);		/* G */
+	key[7] = be32_to_cpu(p_key[7]);		/* H */
+
+	for (i = 0; i < 12; i++) {
+		W(key, 2 * i);
+		W(key, 2 * i + 1);
+
+		c->Kr[i][0] = key[0] & 0x1f;
+		c->Kr[i][1] = key[2] & 0x1f;
+		c->Kr[i][2] = key[4] & 0x1f;
+		c->Kr[i][3] = key[6] & 0x1f;
+
+		c->Km[i][0] = key[7];
+		c->Km[i][1] = key[5];
+		c->Km[i][2] = key[3];
+		c->Km[i][3] = key[1];
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(__cast6_setkey);
+
+int cast6_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen)
+{
+	return __cast6_setkey(crypto_tfm_ctx(tfm), key, keylen,
+			      &tfm->crt_flags);
+}
+EXPORT_SYMBOL_GPL(cast6_setkey);
+
+/*forward quad round*/
+static inline void Q(u32 *block, u8 *Kr, u32 *Km)
+{
+	u32 I;
+	block[2] ^= F1(block[3], Kr[0], Km[0]);
+	block[1] ^= F2(block[2], Kr[1], Km[1]);
+	block[0] ^= F3(block[1], Kr[2], Km[2]);
+	block[3] ^= F1(block[0], Kr[3], Km[3]);
+}
+
+/*reverse quad round*/
+static inline void QBAR(u32 *block, u8 *Kr, u32 *Km)
+{
+	u32 I;
+	block[3] ^= F1(block[0], Kr[3], Km[3]);
+	block[0] ^= F3(block[1], Kr[2], Km[2]);
+	block[1] ^= F2(block[2], Kr[1], Km[1]);
+	block[2] ^= F1(block[3], Kr[0], Km[0]);
+}
+
+void __cast6_encrypt(struct cast6_ctx *c, u8 *outbuf, const u8 *inbuf)
+{
+	const __be32 *src = (const __be32 *)inbuf;
+	__be32 *dst = (__be32 *)outbuf;
+	u32 block[4];
+	u32 *Km;
+	u8 *Kr;
+
+	block[0] = be32_to_cpu(src[0]);
+	block[1] = be32_to_cpu(src[1]);
+	block[2] = be32_to_cpu(src[2]);
+	block[3] = be32_to_cpu(src[3]);
+
+	Km = c->Km[0]; Kr = c->Kr[0]; Q(block, Kr, Km);
+	Km = c->Km[1]; Kr = c->Kr[1]; Q(block, Kr, Km);
+	Km = c->Km[2]; Kr = c->Kr[2]; Q(block, Kr, Km);
+	Km = c->Km[3]; Kr = c->Kr[3]; Q(block, Kr, Km);
+	Km = c->Km[4]; Kr = c->Kr[4]; Q(block, Kr, Km);
+	Km = c->Km[5]; Kr = c->Kr[5]; Q(block, Kr, Km);
+	Km = c->Km[6]; Kr = c->Kr[6]; QBAR(block, Kr, Km);
+	Km = c->Km[7]; Kr = c->Kr[7]; QBAR(block, Kr, Km);
+	Km = c->Km[8]; Kr = c->Kr[8]; QBAR(block, Kr, Km);
+	Km = c->Km[9]; Kr = c->Kr[9]; QBAR(block, Kr, Km);
+	Km = c->Km[10]; Kr = c->Kr[10]; QBAR(block, Kr, Km);
+	Km = c->Km[11]; Kr = c->Kr[11]; QBAR(block, Kr, Km);
+
+	dst[0] = cpu_to_be32(block[0]);
+	dst[1] = cpu_to_be32(block[1]);
+	dst[2] = cpu_to_be32(block[2]);
+	dst[3] = cpu_to_be32(block[3]);
+}
+EXPORT_SYMBOL_GPL(__cast6_encrypt);
+
+static void cast6_encrypt(struct crypto_tfm *tfm, u8 *outbuf, const u8 *inbuf)
+{
+	__cast6_encrypt(crypto_tfm_ctx(tfm), outbuf, inbuf);
+}
+
+void __cast6_decrypt(struct cast6_ctx *c, u8 *outbuf, const u8 *inbuf)
+{
+	const __be32 *src = (const __be32 *)inbuf;
+	__be32 *dst = (__be32 *)outbuf;
+	u32 block[4];
+	u32 *Km;
+	u8 *Kr;
+
+	block[0] = be32_to_cpu(src[0]);
+	block[1] = be32_to_cpu(src[1]);
+	block[2] = be32_to_cpu(src[2]);
+	block[3] = be32_to_cpu(src[3]);
+
+	Km = c->Km[11]; Kr = c->Kr[11]; Q(block, Kr, Km);
+	Km = c->Km[10]; Kr = c->Kr[10]; Q(block, Kr, Km);
+	Km = c->Km[9]; Kr = c->Kr[9]; Q(block, Kr, Km);
+	Km = c->Km[8]; Kr = c->Kr[8]; Q(block, Kr, Km);
+	Km = c->Km[7]; Kr = c->Kr[7]; Q(block, Kr, Km);
+	Km = c->Km[6]; Kr = c->Kr[6]; Q(block, Kr, Km);
+	Km = c->Km[5]; Kr = c->Kr[5]; QBAR(block, Kr, Km);
+	Km = c->Km[4]; Kr = c->Kr[4]; QBAR(block, Kr, Km);
+	Km = c->Km[3]; Kr = c->Kr[3]; QBAR(block, Kr, Km);
+	Km = c->Km[2]; Kr = c->Kr[2]; QBAR(block, Kr, Km);
+	Km = c->Km[1]; Kr = c->Kr[1]; QBAR(block, Kr, Km);
+	Km = c->Km[0]; Kr = c->Kr[0]; QBAR(block, Kr, Km);
+
+	dst[0] = cpu_to_be32(block[0]);
+	dst[1] = cpu_to_be32(block[1]);
+	dst[2] = cpu_to_be32(block[2]);
+	dst[3] = cpu_to_be32(block[3]);
+}
+EXPORT_SYMBOL_GPL(__cast6_decrypt);
+
+static void cast6_decrypt(struct crypto_tfm *tfm, u8 *outbuf, const u8 *inbuf)
+{
+	__cast6_decrypt(crypto_tfm_ctx(tfm), outbuf, inbuf);
+}
+
+static struct crypto_alg alg = {
+	.cra_name = "cast6",
+	.cra_driver_name = "cast6-generic",
+	.cra_priority = 100,
+	.cra_flags = CRYPTO_ALG_TYPE_CIPHER,
+	.cra_blocksize = CAST6_BLOCK_SIZE,
+	.cra_ctxsize = sizeof(struct cast6_ctx),
+	.cra_alignmask = 3,
+	.cra_module = THIS_MODULE,
+	.cra_u = {
+		  .cipher = {
+			     .cia_min_keysize = CAST6_MIN_KEY_SIZE,
+			     .cia_max_keysize = CAST6_MAX_KEY_SIZE,
+			     .cia_setkey = cast6_setkey,
+			     .cia_encrypt = cast6_encrypt,
+			     .cia_decrypt = cast6_decrypt}
+		  }
+};
+
+static int __init cast6_mod_init(void)
+{
+	return crypto_register_alg(&alg);
+}
+
+static void __exit cast6_mod_fini(void)
+{
+	crypto_unregister_alg(&alg);
+}
+
+module_init(cast6_mod_init);
+module_exit(cast6_mod_fini);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Cast6 Cipher Algorithm");
+MODULE_ALIAS("cast6");
diff --git a/crypto/crypto_null.c b/crypto/crypto_null.c
index 07a8a96..fee7265 100644
--- a/crypto/crypto_null.c
+++ b/crypto/crypto_null.c
@@ -94,18 +94,6 @@ static int skcipher_null_crypt(struct blkcipher_desc *desc,
 	return err;
 }
 
-static struct crypto_alg compress_null = {
-	.cra_name		=	"compress_null",
-	.cra_flags		=	CRYPTO_ALG_TYPE_COMPRESS,
-	.cra_blocksize		=	NULL_BLOCK_SIZE,
-	.cra_ctxsize		=	0,
-	.cra_module		=	THIS_MODULE,
-	.cra_list		=       LIST_HEAD_INIT(compress_null.cra_list),
-	.cra_u			=	{ .compress = {
-	.coa_compress 		=	null_compress,
-	.coa_decompress		=	null_compress } }
-};
-
 static struct shash_alg digest_null = {
 	.digestsize		=	NULL_DIGEST_SIZE,
 	.setkey   		=	null_hash_setkey,
@@ -122,22 +110,19 @@ static struct shash_alg digest_null = {
 	}
 };
 
-static struct crypto_alg cipher_null = {
+static struct crypto_alg null_algs[3] = { {
 	.cra_name		=	"cipher_null",
 	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
 	.cra_blocksize		=	NULL_BLOCK_SIZE,
 	.cra_ctxsize		=	0,
 	.cra_module		=	THIS_MODULE,
-	.cra_list		=	LIST_HEAD_INIT(cipher_null.cra_list),
 	.cra_u			=	{ .cipher = {
 	.cia_min_keysize	=	NULL_KEY_SIZE,
 	.cia_max_keysize	=	NULL_KEY_SIZE,
 	.cia_setkey		= 	null_setkey,
 	.cia_encrypt		=	null_crypt,
 	.cia_decrypt		=	null_crypt } }
-};
-
-static struct crypto_alg skcipher_null = {
+}, {
 	.cra_name		=	"ecb(cipher_null)",
 	.cra_driver_name	=	"ecb-cipher_null",
 	.cra_priority		=	100,
@@ -146,7 +131,6 @@ static struct crypto_alg skcipher_null = {
 	.cra_type		=	&crypto_blkcipher_type,
 	.cra_ctxsize		=	0,
 	.cra_module		=	THIS_MODULE,
-	.cra_list		=	LIST_HEAD_INIT(skcipher_null.cra_list),
 	.cra_u			=	{ .blkcipher = {
 	.min_keysize		=	NULL_KEY_SIZE,
 	.max_keysize		=	NULL_KEY_SIZE,
@@ -154,7 +138,16 @@ static struct crypto_alg skcipher_null = {
 	.setkey			= 	null_setkey,
 	.encrypt		=	skcipher_null_crypt,
 	.decrypt		=	skcipher_null_crypt } }
-};
+}, {
+	.cra_name		=	"compress_null",
+	.cra_flags		=	CRYPTO_ALG_TYPE_COMPRESS,
+	.cra_blocksize		=	NULL_BLOCK_SIZE,
+	.cra_ctxsize		=	0,
+	.cra_module		=	THIS_MODULE,
+	.cra_u			=	{ .compress = {
+	.coa_compress		=	null_compress,
+	.coa_decompress		=	null_compress } }
+} };
 
 MODULE_ALIAS("compress_null");
 MODULE_ALIAS("digest_null");
@@ -164,40 +157,26 @@ static int __init crypto_null_mod_init(void)
 {
 	int ret = 0;
 
-	ret = crypto_register_alg(&cipher_null);
+	ret = crypto_register_algs(null_algs, ARRAY_SIZE(null_algs));
 	if (ret < 0)
 		goto out;
 
-	ret = crypto_register_alg(&skcipher_null);
-	if (ret < 0)
-		goto out_unregister_cipher;
-
 	ret = crypto_register_shash(&digest_null);
 	if (ret < 0)
-		goto out_unregister_skcipher;
+		goto out_unregister_algs;
 
-	ret = crypto_register_alg(&compress_null);
-	if (ret < 0)
-		goto out_unregister_digest;
+	return 0;
 
+out_unregister_algs:
+	crypto_unregister_algs(null_algs, ARRAY_SIZE(null_algs));
 out:
 	return ret;
-
-out_unregister_digest:
-	crypto_unregister_shash(&digest_null);
-out_unregister_skcipher:
-	crypto_unregister_alg(&skcipher_null);
-out_unregister_cipher:
-	crypto_unregister_alg(&cipher_null);
-	goto out;
 }
 
 static void __exit crypto_null_mod_fini(void)
 {
-	crypto_unregister_alg(&compress_null);
 	crypto_unregister_shash(&digest_null);
-	crypto_unregister_alg(&skcipher_null);
-	crypto_unregister_alg(&cipher_null);
+	crypto_unregister_algs(null_algs, ARRAY_SIZE(null_algs));
 }
 
 module_init(crypto_null_mod_init);
diff --git a/crypto/crypto_user.c b/crypto/crypto_user.c
index ba2c611..35d700a 100644
--- a/crypto/crypto_user.c
+++ b/crypto/crypto_user.c
@@ -30,7 +30,7 @@
 
 #include "internal.h"
 
-DEFINE_MUTEX(crypto_cfg_mutex);
+static DEFINE_MUTEX(crypto_cfg_mutex);
 
 /* The crypto netlink socket */
 static struct sock *crypto_nlsk;
@@ -166,7 +166,7 @@ static int crypto_report_alg(struct crypto_alg *alg,
 	struct crypto_user_alg *ualg;
 	int err = 0;
 
-	nlh = nlmsg_put(skb, NETLINK_CB(in_skb).pid, info->nlmsg_seq,
+	nlh = nlmsg_put(skb, NETLINK_CB(in_skb).portid, info->nlmsg_seq,
 			CRYPTO_MSG_GETALG, sizeof(*ualg), info->nlmsg_flags);
 	if (!nlh) {
 		err = -EMSGSIZE;
@@ -216,7 +216,7 @@ static int crypto_report(struct sk_buff *in_skb, struct nlmsghdr *in_nlh,
 	if (err)
 		return err;
 
-	return nlmsg_unicast(crypto_nlsk, skb, NETLINK_CB(in_skb).pid);
+	return nlmsg_unicast(crypto_nlsk, skb, NETLINK_CB(in_skb).portid);
 }
 
 static int crypto_dump_report(struct sk_buff *skb, struct netlink_callback *cb)
@@ -500,8 +500,7 @@ static int __init crypto_user_init(void)
 		.input	= crypto_netlink_rcv,
 	};
 
-	crypto_nlsk = netlink_kernel_create(&init_net, NETLINK_CRYPTO,
-					    THIS_MODULE, &cfg);
+	crypto_nlsk = netlink_kernel_create(&init_net, NETLINK_CRYPTO, &cfg);
 	if (!crypto_nlsk)
 		return -ENOMEM;
 
diff --git a/crypto/deflate.c b/crypto/deflate.c
index b0165ec..b57d70e 100644
--- a/crypto/deflate.c
+++ b/crypto/deflate.c
@@ -199,7 +199,6 @@ static struct crypto_alg alg = {
 	.cra_flags		= CRYPTO_ALG_TYPE_COMPRESS,
 	.cra_ctxsize		= sizeof(struct deflate_ctx),
 	.cra_module		= THIS_MODULE,
-	.cra_list		= LIST_HEAD_INIT(alg.cra_list),
 	.cra_init		= deflate_init,
 	.cra_exit		= deflate_exit,
 	.cra_u			= { .compress = {
diff --git a/crypto/des_generic.c b/crypto/des_generic.c
index 873818d..f6cf63f 100644
--- a/crypto/des_generic.c
+++ b/crypto/des_generic.c
@@ -943,59 +943,44 @@ static void des3_ede_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
 	d[1] = cpu_to_le32(L);
 }
 
-static struct crypto_alg des_alg = {
+static struct crypto_alg des_algs[2] = { {
 	.cra_name		=	"des",
 	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
 	.cra_blocksize		=	DES_BLOCK_SIZE,
 	.cra_ctxsize		=	sizeof(struct des_ctx),
 	.cra_module		=	THIS_MODULE,
 	.cra_alignmask		=	3,
-	.cra_list		=	LIST_HEAD_INIT(des_alg.cra_list),
 	.cra_u			=	{ .cipher = {
 	.cia_min_keysize	=	DES_KEY_SIZE,
 	.cia_max_keysize	=	DES_KEY_SIZE,
 	.cia_setkey		=	des_setkey,
 	.cia_encrypt		=	des_encrypt,
 	.cia_decrypt		=	des_decrypt } }
-};
-
-static struct crypto_alg des3_ede_alg = {
+}, {
 	.cra_name		=	"des3_ede",
 	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
 	.cra_blocksize		=	DES3_EDE_BLOCK_SIZE,
 	.cra_ctxsize		=	sizeof(struct des3_ede_ctx),
 	.cra_module		=	THIS_MODULE,
 	.cra_alignmask		=	3,
-	.cra_list		=	LIST_HEAD_INIT(des3_ede_alg.cra_list),
 	.cra_u			=	{ .cipher = {
 	.cia_min_keysize	=	DES3_EDE_KEY_SIZE,
 	.cia_max_keysize	=	DES3_EDE_KEY_SIZE,
 	.cia_setkey		=	des3_ede_setkey,
 	.cia_encrypt		=	des3_ede_encrypt,
 	.cia_decrypt		=	des3_ede_decrypt } }
-};
+} };
 
 MODULE_ALIAS("des3_ede");
 
 static int __init des_generic_mod_init(void)
 {
-	int ret = 0;
-
-	ret = crypto_register_alg(&des_alg);
-	if (ret < 0)
-		goto out;
-
-	ret = crypto_register_alg(&des3_ede_alg);
-	if (ret < 0)
-		crypto_unregister_alg(&des_alg);
-out:
-	return ret;
+	return crypto_register_algs(des_algs, ARRAY_SIZE(des_algs));
 }
 
 static void __exit des_generic_mod_fini(void)
 {
-	crypto_unregister_alg(&des3_ede_alg);
-	crypto_unregister_alg(&des_alg);
+	crypto_unregister_algs(des_algs, ARRAY_SIZE(des_algs));
 }
 
 module_init(des_generic_mod_init);
diff --git a/crypto/fcrypt.c b/crypto/fcrypt.c
index c33107e..3b2cf56 100644
--- a/crypto/fcrypt.c
+++ b/crypto/fcrypt.c
@@ -396,7 +396,6 @@ static struct crypto_alg fcrypt_alg = {
 	.cra_ctxsize		=	sizeof(struct fcrypt_ctx),
 	.cra_module		=	THIS_MODULE,
 	.cra_alignmask		=	3,
-	.cra_list		=	LIST_HEAD_INIT(fcrypt_alg.cra_list),
 	.cra_u			=	{ .cipher = {
 	.cia_min_keysize	=	8,
 	.cia_max_keysize	=	8,
diff --git a/crypto/ghash-generic.c b/crypto/ghash-generic.c
index 7835b8f..9d3f0c6 100644
--- a/crypto/ghash-generic.c
+++ b/crypto/ghash-generic.c
@@ -153,7 +153,6 @@ static struct shash_alg ghash_alg = {
 		.cra_blocksize		= GHASH_BLOCK_SIZE,
 		.cra_ctxsize		= sizeof(struct ghash_ctx),
 		.cra_module		= THIS_MODULE,
-		.cra_list		= LIST_HEAD_INIT(ghash_alg.base.cra_list),
 		.cra_exit		= ghash_exit_tfm,
 	},
 };
diff --git a/crypto/khazad.c b/crypto/khazad.c
index 527e4e3..60e7cd6 100644
--- a/crypto/khazad.c
+++ b/crypto/khazad.c
@@ -853,7 +853,6 @@ static struct crypto_alg khazad_alg = {
 	.cra_ctxsize		=	sizeof (struct khazad_ctx),
 	.cra_alignmask		=	7,
 	.cra_module		=	THIS_MODULE,
-	.cra_list		=	LIST_HEAD_INIT(khazad_alg.cra_list),
 	.cra_u			=	{ .cipher = {
 	.cia_min_keysize	=	KHAZAD_KEY_SIZE,
 	.cia_max_keysize	=	KHAZAD_KEY_SIZE,
diff --git a/crypto/krng.c b/crypto/krng.c
index 4328bb3..a2d2b72 100644
--- a/crypto/krng.c
+++ b/crypto/krng.c
@@ -35,7 +35,6 @@ static struct crypto_alg krng_alg = {
 	.cra_ctxsize		= 0,
 	.cra_type		= &crypto_rng_type,
 	.cra_module		= THIS_MODULE,
-	.cra_list		= LIST_HEAD_INIT(krng_alg.cra_list),
 	.cra_u			= {
 		.rng = {
 			.rng_make_random	= krng_get_random,
diff --git a/crypto/lzo.c b/crypto/lzo.c
index b5e7707..1c2aa69 100644
--- a/crypto/lzo.c
+++ b/crypto/lzo.c
@@ -81,7 +81,6 @@ static struct crypto_alg alg = {
 	.cra_flags		= CRYPTO_ALG_TYPE_COMPRESS,
 	.cra_ctxsize		= sizeof(struct lzo_ctx),
 	.cra_module		= THIS_MODULE,
-	.cra_list		= LIST_HEAD_INIT(alg.cra_list),
 	.cra_init		= lzo_init,
 	.cra_exit		= lzo_exit,
 	.cra_u			= { .compress = {
diff --git a/crypto/salsa20_generic.c b/crypto/salsa20_generic.c
index eac10c1..9a4770c 100644
--- a/crypto/salsa20_generic.c
+++ b/crypto/salsa20_generic.c
@@ -221,7 +221,6 @@ static struct crypto_alg alg = {
 	.cra_ctxsize        =   sizeof(struct salsa20_ctx),
 	.cra_alignmask      =	3,
 	.cra_module         =   THIS_MODULE,
-	.cra_list           =   LIST_HEAD_INIT(alg.cra_list),
 	.cra_u              =   {
 		.blkcipher = {
 			.setkey         =   setkey,
diff --git a/crypto/seed.c b/crypto/seed.c
index d3e422f..9c904d6 100644
--- a/crypto/seed.c
+++ b/crypto/seed.c
@@ -449,7 +449,6 @@ static struct crypto_alg seed_alg = {
 	.cra_ctxsize		=	sizeof(struct seed_ctx),
 	.cra_alignmask		=	3,
 	.cra_module		=	THIS_MODULE,
-	.cra_list		=	LIST_HEAD_INIT(seed_alg.cra_list),
 	.cra_u			=	{
 		.cipher = {
 			.cia_min_keysize	=	SEED_KEY_SIZE,
diff --git a/crypto/serpent_generic.c b/crypto/serpent_generic.c
index 8f32cf3..7ddbd7e 100644
--- a/crypto/serpent_generic.c
+++ b/crypto/serpent_generic.c
@@ -567,24 +567,6 @@ static void serpent_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
 	__serpent_decrypt(ctx, dst, src);
 }
 
-static struct crypto_alg serpent_alg = {
-	.cra_name		=	"serpent",
-	.cra_driver_name	=	"serpent-generic",
-	.cra_priority		=	100,
-	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
-	.cra_blocksize		=	SERPENT_BLOCK_SIZE,
-	.cra_ctxsize		=	sizeof(struct serpent_ctx),
-	.cra_alignmask		=	3,
-	.cra_module		=	THIS_MODULE,
-	.cra_list		=	LIST_HEAD_INIT(serpent_alg.cra_list),
-	.cra_u			=	{ .cipher = {
-	.cia_min_keysize	=	SERPENT_MIN_KEY_SIZE,
-	.cia_max_keysize	=	SERPENT_MAX_KEY_SIZE,
-	.cia_setkey		=	serpent_setkey,
-	.cia_encrypt		=	serpent_encrypt,
-	.cia_decrypt		=	serpent_decrypt } }
-};
-
 static int tnepres_setkey(struct crypto_tfm *tfm, const u8 *key,
 			  unsigned int keylen)
 {
@@ -637,41 +619,44 @@ static void tnepres_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
 	d[3] = swab32(rd[0]);
 }
 
-static struct crypto_alg tnepres_alg = {
+static struct crypto_alg srp_algs[2] = { {
+	.cra_name		=	"serpent",
+	.cra_driver_name	=	"serpent-generic",
+	.cra_priority		=	100,
+	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
+	.cra_blocksize		=	SERPENT_BLOCK_SIZE,
+	.cra_ctxsize		=	sizeof(struct serpent_ctx),
+	.cra_alignmask		=	3,
+	.cra_module		=	THIS_MODULE,
+	.cra_u			=	{ .cipher = {
+	.cia_min_keysize	=	SERPENT_MIN_KEY_SIZE,
+	.cia_max_keysize	=	SERPENT_MAX_KEY_SIZE,
+	.cia_setkey		=	serpent_setkey,
+	.cia_encrypt		=	serpent_encrypt,
+	.cia_decrypt		=	serpent_decrypt } }
+}, {
 	.cra_name		=	"tnepres",
 	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
 	.cra_blocksize		=	SERPENT_BLOCK_SIZE,
 	.cra_ctxsize		=	sizeof(struct serpent_ctx),
 	.cra_alignmask		=	3,
 	.cra_module		=	THIS_MODULE,
-	.cra_list		=	LIST_HEAD_INIT(serpent_alg.cra_list),
 	.cra_u			=	{ .cipher = {
 	.cia_min_keysize	=	SERPENT_MIN_KEY_SIZE,
 	.cia_max_keysize	=	SERPENT_MAX_KEY_SIZE,
 	.cia_setkey		=	tnepres_setkey,
 	.cia_encrypt		=	tnepres_encrypt,
 	.cia_decrypt		=	tnepres_decrypt } }
-};
+} };
 
 static int __init serpent_mod_init(void)
 {
-	int ret = crypto_register_alg(&serpent_alg);
-
-	if (ret)
-		return ret;
-
-	ret = crypto_register_alg(&tnepres_alg);
-
-	if (ret)
-		crypto_unregister_alg(&serpent_alg);
-
-	return ret;
+	return crypto_register_algs(srp_algs, ARRAY_SIZE(srp_algs));
 }
 
 static void __exit serpent_mod_fini(void)
 {
-	crypto_unregister_alg(&tnepres_alg);
-	crypto_unregister_alg(&serpent_alg);
+	crypto_unregister_algs(srp_algs, ARRAY_SIZE(srp_algs));
 }
 
 module_init(serpent_mod_init);
diff --git a/crypto/sha256_generic.c b/crypto/sha256_generic.c
index c48459e..c3ed4ec 100644
--- a/crypto/sha256_generic.c
+++ b/crypto/sha256_generic.c
@@ -336,7 +336,7 @@ static int sha256_import(struct shash_desc *desc, const void *in)
 	return 0;
 }
 
-static struct shash_alg sha256 = {
+static struct shash_alg sha256_algs[2] = { {
 	.digestsize	=	SHA256_DIGEST_SIZE,
 	.init		=	sha256_init,
 	.update		=	sha256_update,
@@ -352,9 +352,7 @@ static struct shash_alg sha256 = {
 		.cra_blocksize	=	SHA256_BLOCK_SIZE,
 		.cra_module	=	THIS_MODULE,
 	}
-};
-
-static struct shash_alg sha224 = {
+}, {
 	.digestsize	=	SHA224_DIGEST_SIZE,
 	.init		=	sha224_init,
 	.update		=	sha256_update,
@@ -367,29 +365,16 @@ static struct shash_alg sha224 = {
 		.cra_blocksize	=	SHA224_BLOCK_SIZE,
 		.cra_module	=	THIS_MODULE,
 	}
-};
+} };
 
 static int __init sha256_generic_mod_init(void)
 {
-	int ret = 0;
-
-	ret = crypto_register_shash(&sha224);
-
-	if (ret < 0)
-		return ret;
-
-	ret = crypto_register_shash(&sha256);
-
-	if (ret < 0)
-		crypto_unregister_shash(&sha224);
-
-	return ret;
+	return crypto_register_shashes(sha256_algs, ARRAY_SIZE(sha256_algs));
 }
 
 static void __exit sha256_generic_mod_fini(void)
 {
-	crypto_unregister_shash(&sha224);
-	crypto_unregister_shash(&sha256);
+	crypto_unregister_shashes(sha256_algs, ARRAY_SIZE(sha256_algs));
 }
 
 module_init(sha256_generic_mod_init);
diff --git a/crypto/sha512_generic.c b/crypto/sha512_generic.c
index dd30f40..71fcf36 100644
--- a/crypto/sha512_generic.c
+++ b/crypto/sha512_generic.c
@@ -242,7 +242,7 @@ static int sha384_final(struct shash_desc *desc, u8 *hash)
 	return 0;
 }
 
-static struct shash_alg sha512 = {
+static struct shash_alg sha512_algs[2] = { {
 	.digestsize	=	SHA512_DIGEST_SIZE,
 	.init		=	sha512_init,
 	.update		=	sha512_update,
@@ -254,9 +254,7 @@ static struct shash_alg sha512 = {
 		.cra_blocksize	=	SHA512_BLOCK_SIZE,
 		.cra_module	=	THIS_MODULE,
 	}
-};
-
-static struct shash_alg sha384 = {
+}, {
 	.digestsize	=	SHA384_DIGEST_SIZE,
 	.init		=	sha384_init,
 	.update		=	sha512_update,
@@ -268,24 +266,16 @@ static struct shash_alg sha384 = {
 		.cra_blocksize	=	SHA384_BLOCK_SIZE,
 		.cra_module	=	THIS_MODULE,
 	}
-};
+} };
 
 static int __init sha512_generic_mod_init(void)
 {
-        int ret = 0;
-
-        if ((ret = crypto_register_shash(&sha384)) < 0)
-                goto out;
-        if ((ret = crypto_register_shash(&sha512)) < 0)
-                crypto_unregister_shash(&sha384);
-out:
-        return ret;
+	return crypto_register_shashes(sha512_algs, ARRAY_SIZE(sha512_algs));
 }
 
 static void __exit sha512_generic_mod_fini(void)
 {
-        crypto_unregister_shash(&sha384);
-        crypto_unregister_shash(&sha512);
+	crypto_unregister_shashes(sha512_algs, ARRAY_SIZE(sha512_algs));
 }
 
 module_init(sha512_generic_mod_init);
diff --git a/crypto/shash.c b/crypto/shash.c
index 32067f4..f426330f 100644
--- a/crypto/shash.c
+++ b/crypto/shash.c
@@ -629,6 +629,42 @@ int crypto_unregister_shash(struct shash_alg *alg)
 }
 EXPORT_SYMBOL_GPL(crypto_unregister_shash);
 
+int crypto_register_shashes(struct shash_alg *algs, int count)
+{
+	int i, ret;
+
+	for (i = 0; i < count; i++) {
+		ret = crypto_register_shash(&algs[i]);
+		if (ret)
+			goto err;
+	}
+
+	return 0;
+
+err:
+	for (--i; i >= 0; --i)
+		crypto_unregister_shash(&algs[i]);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(crypto_register_shashes);
+
+int crypto_unregister_shashes(struct shash_alg *algs, int count)
+{
+	int i, ret;
+
+	for (i = count - 1; i >= 0; --i) {
+		ret = crypto_unregister_shash(&algs[i]);
+		if (ret)
+			pr_err("Failed to unregister %s %s: %d\n",
+			       algs[i].base.cra_driver_name,
+			       algs[i].base.cra_name, ret);
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(crypto_unregister_shashes);
+
 int shash_register_instance(struct crypto_template *tmpl,
 			    struct shash_instance *inst)
 {
diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c
index 5cf2ccb..871076b 100644
--- a/crypto/tcrypt.c
+++ b/crypto/tcrypt.c
@@ -1037,10 +1037,16 @@ static int do_test(int m)
 
 	case 14:
 		ret += tcrypt_test("ecb(cast5)");
+		ret += tcrypt_test("cbc(cast5)");
+		ret += tcrypt_test("ctr(cast5)");
 		break;
 
 	case 15:
 		ret += tcrypt_test("ecb(cast6)");
+		ret += tcrypt_test("cbc(cast6)");
+		ret += tcrypt_test("ctr(cast6)");
+		ret += tcrypt_test("lrw(cast6)");
+		ret += tcrypt_test("xts(cast6)");
 		break;
 
 	case 16:
@@ -1359,6 +1365,44 @@ static int do_test(int m)
 				  speed_template_8);
 		break;
 
+	case 209:
+		test_cipher_speed("ecb(cast5)", ENCRYPT, sec, NULL, 0,
+				  speed_template_8_16);
+		test_cipher_speed("ecb(cast5)", DECRYPT, sec, NULL, 0,
+				  speed_template_8_16);
+		test_cipher_speed("cbc(cast5)", ENCRYPT, sec, NULL, 0,
+				  speed_template_8_16);
+		test_cipher_speed("cbc(cast5)", DECRYPT, sec, NULL, 0,
+				  speed_template_8_16);
+		test_cipher_speed("ctr(cast5)", ENCRYPT, sec, NULL, 0,
+				  speed_template_8_16);
+		test_cipher_speed("ctr(cast5)", DECRYPT, sec, NULL, 0,
+				  speed_template_8_16);
+		break;
+
+	case 210:
+		test_cipher_speed("ecb(cast6)", ENCRYPT, sec, NULL, 0,
+				  speed_template_16_32);
+		test_cipher_speed("ecb(cast6)", DECRYPT, sec, NULL, 0,
+				  speed_template_16_32);
+		test_cipher_speed("cbc(cast6)", ENCRYPT, sec, NULL, 0,
+				  speed_template_16_32);
+		test_cipher_speed("cbc(cast6)", DECRYPT, sec, NULL, 0,
+				  speed_template_16_32);
+		test_cipher_speed("ctr(cast6)", ENCRYPT, sec, NULL, 0,
+				  speed_template_16_32);
+		test_cipher_speed("ctr(cast6)", DECRYPT, sec, NULL, 0,
+				  speed_template_16_32);
+		test_cipher_speed("lrw(cast6)", ENCRYPT, sec, NULL, 0,
+				  speed_template_32_48);
+		test_cipher_speed("lrw(cast6)", DECRYPT, sec, NULL, 0,
+				  speed_template_32_48);
+		test_cipher_speed("xts(cast6)", ENCRYPT, sec, NULL, 0,
+				  speed_template_32_64);
+		test_cipher_speed("xts(cast6)", DECRYPT, sec, NULL, 0,
+				  speed_template_32_64);
+		break;
+
 	case 300:
 		/* fall through */
 
@@ -1639,6 +1683,44 @@ static int do_test(int m)
 				   speed_template_8);
 		break;
 
+	case 506:
+		test_acipher_speed("ecb(cast5)", ENCRYPT, sec, NULL, 0,
+				   speed_template_8_16);
+		test_acipher_speed("ecb(cast5)", DECRYPT, sec, NULL, 0,
+				   speed_template_8_16);
+		test_acipher_speed("cbc(cast5)", ENCRYPT, sec, NULL, 0,
+				   speed_template_8_16);
+		test_acipher_speed("cbc(cast5)", DECRYPT, sec, NULL, 0,
+				   speed_template_8_16);
+		test_acipher_speed("ctr(cast5)", ENCRYPT, sec, NULL, 0,
+				   speed_template_8_16);
+		test_acipher_speed("ctr(cast5)", DECRYPT, sec, NULL, 0,
+				   speed_template_8_16);
+		break;
+
+	case 507:
+		test_acipher_speed("ecb(cast6)", ENCRYPT, sec, NULL, 0,
+				   speed_template_16_32);
+		test_acipher_speed("ecb(cast6)", DECRYPT, sec, NULL, 0,
+				   speed_template_16_32);
+		test_acipher_speed("cbc(cast6)", ENCRYPT, sec, NULL, 0,
+				   speed_template_16_32);
+		test_acipher_speed("cbc(cast6)", DECRYPT, sec, NULL, 0,
+				   speed_template_16_32);
+		test_acipher_speed("ctr(cast6)", ENCRYPT, sec, NULL, 0,
+				   speed_template_16_32);
+		test_acipher_speed("ctr(cast6)", DECRYPT, sec, NULL, 0,
+				   speed_template_16_32);
+		test_acipher_speed("lrw(cast6)", ENCRYPT, sec, NULL, 0,
+				   speed_template_32_48);
+		test_acipher_speed("lrw(cast6)", DECRYPT, sec, NULL, 0,
+				   speed_template_32_48);
+		test_acipher_speed("xts(cast6)", ENCRYPT, sec, NULL, 0,
+				   speed_template_32_64);
+		test_acipher_speed("xts(cast6)", DECRYPT, sec, NULL, 0,
+				   speed_template_32_64);
+		break;
+
 	case 1000:
 		test_available();
 		break;
diff --git a/crypto/tcrypt.h b/crypto/tcrypt.h
index 5be1fc8..cd20685 100644
--- a/crypto/tcrypt.h
+++ b/crypto/tcrypt.h
@@ -47,6 +47,7 @@ static struct cipher_speed_template des3_speed_template[] = {
  */
 static u8 speed_template_8[] = {8, 0};
 static u8 speed_template_24[] = {24, 0};
+static u8 speed_template_8_16[] = {8, 16, 0};
 static u8 speed_template_8_32[] = {8, 32, 0};
 static u8 speed_template_16_32[] = {16, 32, 0};
 static u8 speed_template_16_24_32[] = {16, 24, 32, 0};
diff --git a/crypto/tea.c b/crypto/tea.c
index 412bc74..0a57232 100644
--- a/crypto/tea.c
+++ b/crypto/tea.c
@@ -219,84 +219,55 @@ static void xeta_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
 	out[1] = cpu_to_le32(z);
 }
 
-static struct crypto_alg tea_alg = {
+static struct crypto_alg tea_algs[3] = { {
 	.cra_name		=	"tea",
 	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
 	.cra_blocksize		=	TEA_BLOCK_SIZE,
 	.cra_ctxsize		=	sizeof (struct tea_ctx),
 	.cra_alignmask		=	3,
 	.cra_module		=	THIS_MODULE,
-	.cra_list		=	LIST_HEAD_INIT(tea_alg.cra_list),
 	.cra_u			=	{ .cipher = {
 	.cia_min_keysize	=	TEA_KEY_SIZE,
 	.cia_max_keysize	=	TEA_KEY_SIZE,
 	.cia_setkey		= 	tea_setkey,
 	.cia_encrypt		=	tea_encrypt,
 	.cia_decrypt		=	tea_decrypt } }
-};
-
-static struct crypto_alg xtea_alg = {
+}, {
 	.cra_name		=	"xtea",
 	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
 	.cra_blocksize		=	XTEA_BLOCK_SIZE,
 	.cra_ctxsize		=	sizeof (struct xtea_ctx),
 	.cra_alignmask		=	3,
 	.cra_module		=	THIS_MODULE,
-	.cra_list		=	LIST_HEAD_INIT(xtea_alg.cra_list),
 	.cra_u			=	{ .cipher = {
 	.cia_min_keysize	=	XTEA_KEY_SIZE,
 	.cia_max_keysize	=	XTEA_KEY_SIZE,
 	.cia_setkey		= 	xtea_setkey,
 	.cia_encrypt		=	xtea_encrypt,
 	.cia_decrypt		=	xtea_decrypt } }
-};
-
-static struct crypto_alg xeta_alg = {
+}, {
 	.cra_name		=	"xeta",
 	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
 	.cra_blocksize		=	XTEA_BLOCK_SIZE,
 	.cra_ctxsize		=	sizeof (struct xtea_ctx),
 	.cra_alignmask		=	3,
 	.cra_module		=	THIS_MODULE,
-	.cra_list		=	LIST_HEAD_INIT(xtea_alg.cra_list),
 	.cra_u			=	{ .cipher = {
 	.cia_min_keysize	=	XTEA_KEY_SIZE,
 	.cia_max_keysize	=	XTEA_KEY_SIZE,
 	.cia_setkey		= 	xtea_setkey,
 	.cia_encrypt		=	xeta_encrypt,
 	.cia_decrypt		=	xeta_decrypt } }
-};
+} };
 
 static int __init tea_mod_init(void)
 {
-	int ret = 0;
-	
-	ret = crypto_register_alg(&tea_alg);
-	if (ret < 0)
-		goto out;
-
-	ret = crypto_register_alg(&xtea_alg);
-	if (ret < 0) {
-		crypto_unregister_alg(&tea_alg);
-		goto out;
-	}
-
-	ret = crypto_register_alg(&xeta_alg);
-	if (ret < 0) {
-		crypto_unregister_alg(&tea_alg);
-		crypto_unregister_alg(&xtea_alg);
-		goto out;
-	}
-
-out:	
-	return ret;
+	return crypto_register_algs(tea_algs, ARRAY_SIZE(tea_algs));
 }
 
 static void __exit tea_mod_fini(void)
 {
-	crypto_unregister_alg(&tea_alg);
-	crypto_unregister_alg(&xtea_alg);
-	crypto_unregister_alg(&xeta_alg);
+	crypto_unregister_algs(tea_algs, ARRAY_SIZE(tea_algs));
 }
 
 MODULE_ALIAS("xtea");
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index a2ca743..575b57c 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -1534,6 +1534,36 @@ static int alg_test_null(const struct alg_test_desc *desc,
 /* Please keep this list sorted by algorithm name. */
 static const struct alg_test_desc alg_test_descs[] = {
 	{
+		.alg = "__cbc-cast5-avx",
+		.test = alg_test_null,
+		.suite = {
+			.cipher = {
+				.enc = {
+					.vecs = NULL,
+					.count = 0
+				},
+				.dec = {
+					.vecs = NULL,
+					.count = 0
+				}
+			}
+		}
+	}, {
+		.alg = "__cbc-cast6-avx",
+		.test = alg_test_null,
+		.suite = {
+			.cipher = {
+				.enc = {
+					.vecs = NULL,
+					.count = 0
+				},
+				.dec = {
+					.vecs = NULL,
+					.count = 0
+				}
+			}
+		}
+	}, {
 		.alg = "__cbc-serpent-avx",
 		.test = alg_test_null,
 		.suite = {
@@ -1595,6 +1625,36 @@ static const struct alg_test_desc alg_test_descs[] = {
 			}
 		}
 	}, {
+		.alg = "__driver-cbc-cast5-avx",
+		.test = alg_test_null,
+		.suite = {
+			.cipher = {
+				.enc = {
+					.vecs = NULL,
+					.count = 0
+				},
+				.dec = {
+					.vecs = NULL,
+					.count = 0
+				}
+			}
+		}
+	}, {
+		.alg = "__driver-cbc-cast6-avx",
+		.test = alg_test_null,
+		.suite = {
+			.cipher = {
+				.enc = {
+					.vecs = NULL,
+					.count = 0
+				},
+				.dec = {
+					.vecs = NULL,
+					.count = 0
+				}
+			}
+		}
+	}, {
 		.alg = "__driver-cbc-serpent-avx",
 		.test = alg_test_null,
 		.suite = {
@@ -1656,6 +1716,36 @@ static const struct alg_test_desc alg_test_descs[] = {
 			}
 		}
 	}, {
+		.alg = "__driver-ecb-cast5-avx",
+		.test = alg_test_null,
+		.suite = {
+			.cipher = {
+				.enc = {
+					.vecs = NULL,
+					.count = 0
+				},
+				.dec = {
+					.vecs = NULL,
+					.count = 0
+				}
+			}
+		}
+	}, {
+		.alg = "__driver-ecb-cast6-avx",
+		.test = alg_test_null,
+		.suite = {
+			.cipher = {
+				.enc = {
+					.vecs = NULL,
+					.count = 0
+				},
+				.dec = {
+					.vecs = NULL,
+					.count = 0
+				}
+			}
+		}
+	}, {
 		.alg = "__driver-ecb-serpent-avx",
 		.test = alg_test_null,
 		.suite = {
@@ -1818,6 +1908,36 @@ static const struct alg_test_desc alg_test_descs[] = {
 			}
 		}
 	}, {
+		.alg = "cbc(cast5)",
+		.test = alg_test_skcipher,
+		.suite = {
+			.cipher = {
+				.enc = {
+					.vecs = cast5_cbc_enc_tv_template,
+					.count = CAST5_CBC_ENC_TEST_VECTORS
+				},
+				.dec = {
+					.vecs = cast5_cbc_dec_tv_template,
+					.count = CAST5_CBC_DEC_TEST_VECTORS
+				}
+			}
+		}
+	}, {
+		.alg = "cbc(cast6)",
+		.test = alg_test_skcipher,
+		.suite = {
+			.cipher = {
+				.enc = {
+					.vecs = cast6_cbc_enc_tv_template,
+					.count = CAST6_CBC_ENC_TEST_VECTORS
+				},
+				.dec = {
+					.vecs = cast6_cbc_dec_tv_template,
+					.count = CAST6_CBC_DEC_TEST_VECTORS
+				}
+			}
+		}
+	}, {
 		.alg = "cbc(des)",
 		.test = alg_test_skcipher,
 		.suite = {
@@ -1937,6 +2057,36 @@ static const struct alg_test_desc alg_test_descs[] = {
 			}
 		}
 	}, {
+		.alg = "cryptd(__driver-ecb-cast5-avx)",
+		.test = alg_test_null,
+		.suite = {
+			.cipher = {
+				.enc = {
+					.vecs = NULL,
+					.count = 0
+				},
+				.dec = {
+					.vecs = NULL,
+					.count = 0
+				}
+			}
+		}
+	}, {
+		.alg = "cryptd(__driver-ecb-cast6-avx)",
+		.test = alg_test_null,
+		.suite = {
+			.cipher = {
+				.enc = {
+					.vecs = NULL,
+					.count = 0
+				},
+				.dec = {
+					.vecs = NULL,
+					.count = 0
+				}
+			}
+		}
+	}, {
 		.alg = "cryptd(__driver-ecb-serpent-avx)",
 		.test = alg_test_null,
 		.suite = {
@@ -2054,6 +2204,36 @@ static const struct alg_test_desc alg_test_descs[] = {
 			}
 		}
 	}, {
+		.alg = "ctr(cast5)",
+		.test = alg_test_skcipher,
+		.suite = {
+			.cipher = {
+				.enc = {
+					.vecs = cast5_ctr_enc_tv_template,
+					.count = CAST5_CTR_ENC_TEST_VECTORS
+				},
+				.dec = {
+					.vecs = cast5_ctr_dec_tv_template,
+					.count = CAST5_CTR_DEC_TEST_VECTORS
+				}
+			}
+		}
+	}, {
+		.alg = "ctr(cast6)",
+		.test = alg_test_skcipher,
+		.suite = {
+			.cipher = {
+				.enc = {
+					.vecs = cast6_ctr_enc_tv_template,
+					.count = CAST6_CTR_ENC_TEST_VECTORS
+				},
+				.dec = {
+					.vecs = cast6_ctr_dec_tv_template,
+					.count = CAST6_CTR_DEC_TEST_VECTORS
+				}
+			}
+		}
+	}, {
 		.alg = "ctr(serpent)",
 		.test = alg_test_skcipher,
 		.suite = {
@@ -2530,6 +2710,21 @@ static const struct alg_test_desc alg_test_descs[] = {
 			}
 		}
 	}, {
+		.alg = "lrw(cast6)",
+		.test = alg_test_skcipher,
+		.suite = {
+			.cipher = {
+				.enc = {
+					.vecs = cast6_lrw_enc_tv_template,
+					.count = CAST6_LRW_ENC_TEST_VECTORS
+				},
+				.dec = {
+					.vecs = cast6_lrw_dec_tv_template,
+					.count = CAST6_LRW_DEC_TEST_VECTORS
+				}
+			}
+		}
+	}, {
 		.alg = "lrw(serpent)",
 		.test = alg_test_skcipher,
 		.suite = {
@@ -2882,6 +3077,21 @@ static const struct alg_test_desc alg_test_descs[] = {
 			}
 		}
 	}, {
+		.alg = "xts(cast6)",
+		.test = alg_test_skcipher,
+		.suite = {
+			.cipher = {
+				.enc = {
+					.vecs = cast6_xts_enc_tv_template,
+					.count = CAST6_XTS_ENC_TEST_VECTORS
+				},
+				.dec = {
+					.vecs = cast6_xts_dec_tv_template,
+					.count = CAST6_XTS_DEC_TEST_VECTORS
+				}
+			}
+		}
+	}, {
 		.alg = "xts(serpent)",
 		.test = alg_test_skcipher,
 		.suite = {
diff --git a/crypto/testmgr.h b/crypto/testmgr.h
index f8179e0..6eb3ef5 100644
--- a/crypto/testmgr.h
+++ b/crypto/testmgr.h
@@ -6896,8 +6896,16 @@ static struct cipher_testvec serpent_xts_dec_tv_template[] = {
 };
 
 /* Cast6 test vectors from RFC 2612 */
-#define CAST6_ENC_TEST_VECTORS	3
-#define CAST6_DEC_TEST_VECTORS  3
+#define CAST6_ENC_TEST_VECTORS		4
+#define CAST6_DEC_TEST_VECTORS		4
+#define CAST6_CBC_ENC_TEST_VECTORS	1
+#define CAST6_CBC_DEC_TEST_VECTORS	1
+#define CAST6_CTR_ENC_TEST_VECTORS	1
+#define CAST6_CTR_DEC_TEST_VECTORS	1
+#define CAST6_LRW_ENC_TEST_VECTORS	1
+#define CAST6_LRW_DEC_TEST_VECTORS	1
+#define CAST6_XTS_ENC_TEST_VECTORS	1
+#define CAST6_XTS_DEC_TEST_VECTORS	1
 
 static struct cipher_testvec cast6_enc_tv_template[] = {
 	{
@@ -6930,6 +6938,140 @@ static struct cipher_testvec cast6_enc_tv_template[] = {
 		.result	= "\x4f\x6a\x20\x38\x28\x68\x97\xb9"
 			  "\xc9\x87\x01\x36\x55\x33\x17\xfa",
 		.rlen	= 16,
+	}, { /* Generated from TF test vectors */
+		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
+			  "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
+			  "\x78\xBE\x9B\x78\x55\x32\x0F\x55",
+		.klen	= 32,
+		.iv	= "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F"
+			  "\xC4\x29\x8E\xF3\x35\x9A\xFF\x64",
+		.input	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+			  "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+			  "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+			  "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+			  "\xC3\x37\xCE\x65\xFC\x70\x07\x9E"
+			  "\x12\xA9\x40\xD7\x4B\xE2\x79\x10"
+			  "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F"
+			  "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1"
+			  "\x68\xFF\x73\x0A\xA1\x15\xAC\x43"
+			  "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5"
+			  "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
+			  "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
+			  "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
+			  "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+			  "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+			  "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+			  "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+			  "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+			  "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+			  "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+			  "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+			  "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+			  "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+			  "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+			  "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+			  "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+			  "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+			  "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+			  "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+			  "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+			  "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+			  "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+			  "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+			  "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+			  "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+			  "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+			  "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+			  "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+			  "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+			  "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+			  "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+			  "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+			  "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+			  "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+			  "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+			  "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+			  "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+			  "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+			  "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+			  "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+			  "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+			  "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+			  "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+			  "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+			  "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+			  "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+			  "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+			  "\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
+		.ilen	= 496,
+		.result	= "\xC3\x70\x22\x32\xF5\x80\xCB\x54"
+			  "\xFC\x30\xE0\xF6\xEB\x39\x57\xA6"
+			  "\xB6\xB9\xC5\xA4\x91\x55\x14\x97"
+			  "\xC1\x20\xFF\x6C\x5C\xF0\x67\xEA"
+			  "\x2F\xED\xD8\xC9\xFB\x38\x3F\xFE"
+			  "\x93\xBE\xDC\x00\xD3\x7F\xAD\x4C"
+			  "\x5A\x08\x92\xD1\x47\x0C\xFA\x6C"
+			  "\xD0\x6A\x99\x10\x72\xF8\x47\x62"
+			  "\x81\x42\xF8\xD8\xF5\xBB\x94\x08"
+			  "\xAA\x97\xA2\x8B\x69\xB3\xD2\x7E"
+			  "\xBC\xB5\x00\x0C\xE5\x44\x4B\x58"
+			  "\xE8\x63\xDC\xB3\xC4\xE5\x23\x12"
+			  "\x5A\x72\x85\x47\x8B\xEC\x9F\x26"
+			  "\x84\xB6\xED\x10\x33\x63\x9B\x5F"
+			  "\x4D\x53\xEE\x94\x45\x8B\x60\x58"
+			  "\x86\x20\xF9\x1E\x82\x08\x3E\x58"
+			  "\x60\x1B\x34\x19\x02\xBE\x4E\x09"
+			  "\xBB\x7C\x15\xCC\x60\x27\x55\x7A"
+			  "\x12\xB8\xD8\x08\x89\x3C\xA6\xF3"
+			  "\xF1\xDD\xA7\x07\xA3\x12\x85\x28"
+			  "\xE9\x57\xAC\x80\x0C\x5C\x0F\x3A"
+			  "\x5D\xC2\x91\xC7\x90\xE4\x8C\x43"
+			  "\x92\xE4\x7C\x26\x69\x4D\x83\x68"
+			  "\x14\x96\x42\x47\xBD\xA9\xE4\x8A"
+			  "\x33\x19\xEB\x54\x8E\x0D\x4B\x6E"
+			  "\x91\x51\xB5\x36\x08\xDE\x1C\x06"
+			  "\x03\xBD\xDE\x81\x26\xF7\x99\xC2"
+			  "\xBA\xF7\x6D\x87\x0D\xE4\xA6\xCF"
+			  "\xC1\xF5\x27\x05\xB8\x02\x57\x72"
+			  "\xE6\x42\x13\x0B\xC6\x47\x05\x74"
+			  "\x24\x15\xF7\x0D\xC2\x23\x9D\xB9"
+			  "\x3C\x77\x18\x93\xBA\xB4\xFC\x8C"
+			  "\x98\x82\x67\x67\xB4\xD7\xD3\x43"
+			  "\x23\x08\x02\xB7\x9B\x99\x05\xFB"
+			  "\xD3\xB5\x00\x0A\xA9\x9D\x66\xD6"
+			  "\x2E\x49\x58\xD0\xA8\x57\x29\x7F"
+			  "\x0A\x0E\x7D\xFC\x92\x83\xCC\x67"
+			  "\xA2\xB1\x70\x3A\x8F\x87\x4A\x8D"
+			  "\x17\xE2\x58\x2B\x88\x0D\x68\x62"
+			  "\xBF\x35\xD1\x6F\xC0\xF0\x18\x62"
+			  "\xB2\xC7\x2D\x58\xC7\x16\xDE\x08"
+			  "\xEB\x84\x1D\x25\xA7\x38\x94\x06"
+			  "\x93\x9D\xF8\xFE\x88\x71\xE7\x84"
+			  "\x2C\xA0\x38\xA3\x1D\x48\xCF\x29"
+			  "\x0B\xBC\xD8\x50\x99\x1A\x26\xFB"
+			  "\x8E\x75\x3D\x73\xEB\x6A\xED\x29"
+			  "\xE0\x8E\xED\xFC\xFE\x6F\xF6\xBA"
+			  "\x41\xE2\x10\x4C\x01\x8B\x69\x2B"
+			  "\x25\x3F\x4D\x70\x7B\x92\xD6\x3B"
+			  "\xAC\xF9\x77\x18\xD9\x6A\x30\xA6"
+			  "\x2E\xFA\x30\xFF\xC8\xD5\x1D\x06"
+			  "\x59\x28\x1D\x86\x43\x04\x5D\x3B"
+			  "\x99\x4C\x04\x5A\x21\x17\x8B\x76"
+			  "\x8F\x72\xCB\xA1\x9C\x29\x4C\xC3"
+			  "\x65\xA2\x58\x2A\xC5\x66\x24\xBF"
+			  "\xBA\xE6\x0C\xDD\x34\x24\x74\xC8"
+			  "\x84\x0A\x66\x2C\xBE\x8F\x32\xA9"
+			  "\xE7\xE4\xA1\xD7\xDA\xAB\x23\x1E"
+			  "\xEB\xEE\x6C\x94\x6F\x9C\x2E\xD1"
+			  "\x49\x2C\xF3\xD4\x90\xCC\x93\x4C"
+			  "\x84\x52\x6D\x68\xDE\xC6\x64\xB2"
+			  "\x11\x74\x93\x57\xB4\x7E\xC6\x00",
+		.rlen	= 496,
 	},
 };
 
@@ -6964,122 +7106,1388 @@ static struct cipher_testvec cast6_dec_tv_template[] = {
 		.ilen	= 16,
 		.result	= zeroed_string,
 		.rlen	= 16,
-	},
-};
-
-
-/*
- * AES test vectors.
- */
-#define AES_ENC_TEST_VECTORS 3
-#define AES_DEC_TEST_VECTORS 3
-#define AES_CBC_ENC_TEST_VECTORS 4
-#define AES_CBC_DEC_TEST_VECTORS 4
-#define HMAC_SHA1_AES_CBC_ENC_TEST_VECTORS 7
-#define HMAC_SHA256_AES_CBC_ENC_TEST_VECTORS 7
-#define HMAC_SHA512_AES_CBC_ENC_TEST_VECTORS 7
-#define AES_LRW_ENC_TEST_VECTORS 8
-#define AES_LRW_DEC_TEST_VECTORS 8
-#define AES_XTS_ENC_TEST_VECTORS 5
-#define AES_XTS_DEC_TEST_VECTORS 5
-#define AES_CTR_ENC_TEST_VECTORS 3
-#define AES_CTR_DEC_TEST_VECTORS 3
-#define AES_OFB_ENC_TEST_VECTORS 1
-#define AES_OFB_DEC_TEST_VECTORS 1
-#define AES_CTR_3686_ENC_TEST_VECTORS 7
-#define AES_CTR_3686_DEC_TEST_VECTORS 6
-#define AES_GCM_ENC_TEST_VECTORS 9
-#define AES_GCM_DEC_TEST_VECTORS 8
-#define AES_GCM_4106_ENC_TEST_VECTORS 7
-#define AES_GCM_4106_DEC_TEST_VECTORS 7
-#define AES_CCM_ENC_TEST_VECTORS 7
-#define AES_CCM_DEC_TEST_VECTORS 7
-#define AES_CCM_4309_ENC_TEST_VECTORS 7
-#define AES_CCM_4309_DEC_TEST_VECTORS 10
-
-static struct cipher_testvec aes_enc_tv_template[] = {
-	{ /* From FIPS-197 */
-		.key	= "\x00\x01\x02\x03\x04\x05\x06\x07"
-			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
-		.klen	= 16,
-		.input	= "\x00\x11\x22\x33\x44\x55\x66\x77"
-			  "\x88\x99\xaa\xbb\xcc\xdd\xee\xff",
-		.ilen	= 16,
-		.result	= "\x69\xc4\xe0\xd8\x6a\x7b\x04\x30"
-			  "\xd8\xcd\xb7\x80\x70\xb4\xc5\x5a",
-		.rlen	= 16,
-	}, {
-		.key	= "\x00\x01\x02\x03\x04\x05\x06\x07"
-			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
-			  "\x10\x11\x12\x13\x14\x15\x16\x17",
-		.klen	= 24,
-		.input	= "\x00\x11\x22\x33\x44\x55\x66\x77"
-			  "\x88\x99\xaa\xbb\xcc\xdd\xee\xff",
-		.ilen	= 16,
-		.result	= "\xdd\xa9\x7c\xa4\x86\x4c\xdf\xe0"
-			  "\x6e\xaf\x70\xa0\xec\x0d\x71\x91",
-		.rlen	= 16,
-	}, {
-		.key	= "\x00\x01\x02\x03\x04\x05\x06\x07"
-			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
-			  "\x10\x11\x12\x13\x14\x15\x16\x17"
-			  "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
+	}, { /* Generated from TF test vectors */
+		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
+			  "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
+			  "\x78\xBE\x9B\x78\x55\x32\x0F\x55",
 		.klen	= 32,
-		.input	= "\x00\x11\x22\x33\x44\x55\x66\x77"
-			  "\x88\x99\xaa\xbb\xcc\xdd\xee\xff",
-		.ilen	= 16,
-		.result	= "\x8e\xa2\xb7\xca\x51\x67\x45\xbf"
-			  "\xea\xfc\x49\x90\x4b\x49\x60\x89",
-		.rlen	= 16,
+		.iv	= "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F"
+			  "\xC4\x29\x8E\xF3\x35\x9A\xFF\x64",
+		.input	= "\xC3\x70\x22\x32\xF5\x80\xCB\x54"
+			  "\xFC\x30\xE0\xF6\xEB\x39\x57\xA6"
+			  "\xB6\xB9\xC5\xA4\x91\x55\x14\x97"
+			  "\xC1\x20\xFF\x6C\x5C\xF0\x67\xEA"
+			  "\x2F\xED\xD8\xC9\xFB\x38\x3F\xFE"
+			  "\x93\xBE\xDC\x00\xD3\x7F\xAD\x4C"
+			  "\x5A\x08\x92\xD1\x47\x0C\xFA\x6C"
+			  "\xD0\x6A\x99\x10\x72\xF8\x47\x62"
+			  "\x81\x42\xF8\xD8\xF5\xBB\x94\x08"
+			  "\xAA\x97\xA2\x8B\x69\xB3\xD2\x7E"
+			  "\xBC\xB5\x00\x0C\xE5\x44\x4B\x58"
+			  "\xE8\x63\xDC\xB3\xC4\xE5\x23\x12"
+			  "\x5A\x72\x85\x47\x8B\xEC\x9F\x26"
+			  "\x84\xB6\xED\x10\x33\x63\x9B\x5F"
+			  "\x4D\x53\xEE\x94\x45\x8B\x60\x58"
+			  "\x86\x20\xF9\x1E\x82\x08\x3E\x58"
+			  "\x60\x1B\x34\x19\x02\xBE\x4E\x09"
+			  "\xBB\x7C\x15\xCC\x60\x27\x55\x7A"
+			  "\x12\xB8\xD8\x08\x89\x3C\xA6\xF3"
+			  "\xF1\xDD\xA7\x07\xA3\x12\x85\x28"
+			  "\xE9\x57\xAC\x80\x0C\x5C\x0F\x3A"
+			  "\x5D\xC2\x91\xC7\x90\xE4\x8C\x43"
+			  "\x92\xE4\x7C\x26\x69\x4D\x83\x68"
+			  "\x14\x96\x42\x47\xBD\xA9\xE4\x8A"
+			  "\x33\x19\xEB\x54\x8E\x0D\x4B\x6E"
+			  "\x91\x51\xB5\x36\x08\xDE\x1C\x06"
+			  "\x03\xBD\xDE\x81\x26\xF7\x99\xC2"
+			  "\xBA\xF7\x6D\x87\x0D\xE4\xA6\xCF"
+			  "\xC1\xF5\x27\x05\xB8\x02\x57\x72"
+			  "\xE6\x42\x13\x0B\xC6\x47\x05\x74"
+			  "\x24\x15\xF7\x0D\xC2\x23\x9D\xB9"
+			  "\x3C\x77\x18\x93\xBA\xB4\xFC\x8C"
+			  "\x98\x82\x67\x67\xB4\xD7\xD3\x43"
+			  "\x23\x08\x02\xB7\x9B\x99\x05\xFB"
+			  "\xD3\xB5\x00\x0A\xA9\x9D\x66\xD6"
+			  "\x2E\x49\x58\xD0\xA8\x57\x29\x7F"
+			  "\x0A\x0E\x7D\xFC\x92\x83\xCC\x67"
+			  "\xA2\xB1\x70\x3A\x8F\x87\x4A\x8D"
+			  "\x17\xE2\x58\x2B\x88\x0D\x68\x62"
+			  "\xBF\x35\xD1\x6F\xC0\xF0\x18\x62"
+			  "\xB2\xC7\x2D\x58\xC7\x16\xDE\x08"
+			  "\xEB\x84\x1D\x25\xA7\x38\x94\x06"
+			  "\x93\x9D\xF8\xFE\x88\x71\xE7\x84"
+			  "\x2C\xA0\x38\xA3\x1D\x48\xCF\x29"
+			  "\x0B\xBC\xD8\x50\x99\x1A\x26\xFB"
+			  "\x8E\x75\x3D\x73\xEB\x6A\xED\x29"
+			  "\xE0\x8E\xED\xFC\xFE\x6F\xF6\xBA"
+			  "\x41\xE2\x10\x4C\x01\x8B\x69\x2B"
+			  "\x25\x3F\x4D\x70\x7B\x92\xD6\x3B"
+			  "\xAC\xF9\x77\x18\xD9\x6A\x30\xA6"
+			  "\x2E\xFA\x30\xFF\xC8\xD5\x1D\x06"
+			  "\x59\x28\x1D\x86\x43\x04\x5D\x3B"
+			  "\x99\x4C\x04\x5A\x21\x17\x8B\x76"
+			  "\x8F\x72\xCB\xA1\x9C\x29\x4C\xC3"
+			  "\x65\xA2\x58\x2A\xC5\x66\x24\xBF"
+			  "\xBA\xE6\x0C\xDD\x34\x24\x74\xC8"
+			  "\x84\x0A\x66\x2C\xBE\x8F\x32\xA9"
+			  "\xE7\xE4\xA1\xD7\xDA\xAB\x23\x1E"
+			  "\xEB\xEE\x6C\x94\x6F\x9C\x2E\xD1"
+			  "\x49\x2C\xF3\xD4\x90\xCC\x93\x4C"
+			  "\x84\x52\x6D\x68\xDE\xC6\x64\xB2"
+			  "\x11\x74\x93\x57\xB4\x7E\xC6\x00",
+		.ilen	= 496,
+		.result	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+			  "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+			  "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+			  "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+			  "\xC3\x37\xCE\x65\xFC\x70\x07\x9E"
+			  "\x12\xA9\x40\xD7\x4B\xE2\x79\x10"
+			  "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F"
+			  "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1"
+			  "\x68\xFF\x73\x0A\xA1\x15\xAC\x43"
+			  "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5"
+			  "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
+			  "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
+			  "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
+			  "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+			  "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+			  "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+			  "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+			  "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+			  "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+			  "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+			  "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+			  "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+			  "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+			  "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+			  "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+			  "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+			  "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+			  "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+			  "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+			  "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+			  "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+			  "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+			  "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+			  "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+			  "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+			  "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+			  "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+			  "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+			  "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+			  "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+			  "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+			  "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+			  "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+			  "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+			  "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+			  "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+			  "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+			  "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+			  "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+			  "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+			  "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+			  "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+			  "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+			  "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+			  "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+			  "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+			  "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+			  "\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
+		.rlen	= 496,
 	},
 };
 
-static struct cipher_testvec aes_dec_tv_template[] = {
-	{ /* From FIPS-197 */
-		.key	= "\x00\x01\x02\x03\x04\x05\x06\x07"
-			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
-		.klen	= 16,
-		.input	= "\x69\xc4\xe0\xd8\x6a\x7b\x04\x30"
-			  "\xd8\xcd\xb7\x80\x70\xb4\xc5\x5a",
-		.ilen	= 16,
-		.result	= "\x00\x11\x22\x33\x44\x55\x66\x77"
-			  "\x88\x99\xaa\xbb\xcc\xdd\xee\xff",
-		.rlen	= 16,
-	}, {
-		.key	= "\x00\x01\x02\x03\x04\x05\x06\x07"
-			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
-			  "\x10\x11\x12\x13\x14\x15\x16\x17",
-		.klen	= 24,
-		.input	= "\xdd\xa9\x7c\xa4\x86\x4c\xdf\xe0"
-			  "\x6e\xaf\x70\xa0\xec\x0d\x71\x91",
-		.ilen	= 16,
-		.result	= "\x00\x11\x22\x33\x44\x55\x66\x77"
-			  "\x88\x99\xaa\xbb\xcc\xdd\xee\xff",
-		.rlen	= 16,
-	}, {
-		.key	= "\x00\x01\x02\x03\x04\x05\x06\x07"
-			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
-			  "\x10\x11\x12\x13\x14\x15\x16\x17"
-			  "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
+static struct cipher_testvec cast6_cbc_enc_tv_template[] = {
+	{ /* Generated from TF test vectors */
+		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
+			  "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
+			  "\x78\xBE\x9B\x78\x55\x32\x0F\x55",
 		.klen	= 32,
-		.input	= "\x8e\xa2\xb7\xca\x51\x67\x45\xbf"
-			  "\xea\xfc\x49\x90\x4b\x49\x60\x89",
-		.ilen	= 16,
-		.result	= "\x00\x11\x22\x33\x44\x55\x66\x77"
-			  "\x88\x99\xaa\xbb\xcc\xdd\xee\xff",
-		.rlen	= 16,
-	},
-};
-
-static struct cipher_testvec aes_cbc_enc_tv_template[] = {
-	{ /* From RFC 3602 */
-		.key    = "\x06\xa9\x21\x40\x36\xb8\xa1\x5b"
-			  "\x51\x2e\x03\xd5\x34\x12\x00\x06",
-		.klen   = 16,
-		.iv	= "\x3d\xaf\xba\x42\x9d\x9e\xb4\x30"
-			  "\xb4\x22\xda\x80\x2c\x9f\xac\x41",
-		.input	= "Single block msg",
-		.ilen   = 16,
+		.iv	= "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F"
+			  "\xC4\x29\x8E\xF3\x35\x9A\xFF\x64",
+		.input	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+			  "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+			  "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+			  "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+			  "\xC3\x37\xCE\x65\xFC\x70\x07\x9E"
+			  "\x12\xA9\x40\xD7\x4B\xE2\x79\x10"
+			  "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F"
+			  "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1"
+			  "\x68\xFF\x73\x0A\xA1\x15\xAC\x43"
+			  "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5"
+			  "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
+			  "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
+			  "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
+			  "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+			  "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+			  "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+			  "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+			  "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+			  "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+			  "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+			  "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+			  "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+			  "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+			  "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+			  "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+			  "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+			  "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+			  "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+			  "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+			  "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+			  "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+			  "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+			  "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+			  "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+			  "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+			  "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+			  "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+			  "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+			  "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+			  "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+			  "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+			  "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+			  "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+			  "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+			  "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+			  "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+			  "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+			  "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+			  "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+			  "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+			  "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+			  "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+			  "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+			  "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+			  "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+			  "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+			  "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+			  "\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
+		.ilen	= 496,
+		.result	= "\xDF\x77\x68\x96\xC7\xBA\xF8\xE2"
+			  "\x0E\x24\x99\x1A\xAA\xF3\xC6\x9F"
+			  "\xA0\x73\xB3\x70\xC3\x68\x64\x70"
+			  "\xAD\x33\x02\xFB\x88\x74\xAA\x78"
+			  "\xC7\x47\x1A\x18\x61\x2D\xAC\x9F"
+			  "\x7E\x6F\xDF\x05\x13\x76\xA6\x72"
+			  "\xB7\x13\x09\x0F\x7D\x38\xDF\x25"
+			  "\x4E\xFD\x50\x45\xFA\x35\x6A\xC0"
+			  "\x57\x95\xE1\x21\x26\x10\x9A\x21"
+			  "\xA1\x8A\x51\x05\xD1\xB1\x78\x35"
+			  "\x98\xF5\xAE\xC0\xC1\x8B\x94\xFF"
+			  "\xD0\x69\x3F\x42\xC2\x01\xA7\x9B"
+			  "\x23\x16\x47\x72\x81\x13\x3A\x72"
+			  "\xEC\xD9\x40\x88\x00\x9C\xB0\xA8"
+			  "\x9C\xAC\xCE\x11\x73\x7B\x63\x3E"
+			  "\xA3\x63\x98\x7D\x35\xE4\xD9\x83"
+			  "\xE2\xD0\x52\x87\x0C\x1F\xB0\xB3"
+			  "\x41\x1A\x93\x8D\x76\x31\x9F\xF2"
+			  "\xFE\x09\xA3\x8F\x22\x6A\x3B\xB9"
+			  "\x6C\x9E\xE4\xA1\xA0\xC4\xE7\xA1"
+			  "\x21\x9C\x1A\xCA\x65\xDE\x44\x03"
+			  "\x99\xF2\xD2\x39\xE3\x3F\x0F\x37"
+			  "\x53\x50\x23\xA4\x81\x6E\xDA\xFB"
+			  "\xF8\x7B\x01\xD7\xB2\x32\x9C\xB8"
+			  "\xB1\x0E\x99\x17\xB5\x38\xF9\xD7"
+			  "\x86\x2D\x6E\x94\x5C\x99\x9D\xB3"
+			  "\xD3\x63\x4B\x2A\x7D\x44\x6A\xB2"
+			  "\xC1\x03\xE6\x5A\x37\xD8\x64\x18"
+			  "\xAA\x32\xCE\x29\xED\xC0\xA2\xCB"
+			  "\x8D\xAF\xCD\xBE\x8F\xB6\xEC\xB4"
+			  "\x89\x05\x81\x6E\x71\x4F\xC3\x28"
+			  "\x10\xC1\x62\xC4\x41\xE9\xD2\x39"
+			  "\xF3\x22\x39\x12\x2C\xC2\x95\x2D"
+			  "\xBF\x93\x58\x4B\x04\xD1\x8D\x57"
+			  "\xAE\xEB\x60\x03\x56\x35\xAD\x5A"
+			  "\xE9\xC3\xFF\x4E\x31\xE1\x37\xF8"
+			  "\x7D\xEE\x65\x8A\xB6\x88\x1A\x3E"
+			  "\x07\x09\x82\xBA\xF0\x80\x8A\xD0"
+			  "\xA0\x3F\x6A\xE9\x24\x87\x19\x65"
+			  "\x73\x3F\x12\x91\x47\x54\xBA\x39"
+			  "\x30\x5B\x1E\xE5\xC2\xF9\x3F\xEF"
+			  "\xD6\x75\xF9\xB8\x7C\x8B\x05\x76"
+			  "\xEE\xB7\x08\x25\x4B\xB6\x7B\x47"
+			  "\x72\xC0\x4C\xD4\xDA\xE0\x75\xF1"
+			  "\x7C\xE8\x94\x9E\x16\x6E\xB8\x12"
+			  "\xA1\xC1\x6E\x3B\x1C\x59\x41\x2D"
+			  "\x23\xFA\x7D\x77\xB8\x46\x75\xFE"
+			  "\x4F\x10\xD3\x09\x60\xA1\x36\x96"
+			  "\x5B\xC2\xDC\x6E\x84\x7D\x9B\x14"
+			  "\x80\x21\x83\x58\x3C\x76\xFD\x28"
+			  "\x1D\xF9\x93\x13\xD7\x0E\x62\x14"
+			  "\x5A\xC5\x4E\x08\xA5\x56\xA4\x3C"
+			  "\x68\x93\x44\x70\xDF\xCF\x4A\x51"
+			  "\x0B\x81\x29\x41\xE5\x62\x4D\x36"
+			  "\xB3\xEA\x94\xA6\xB9\xDD\x3F\x09"
+			  "\x62\x34\xA0\x6A\x7E\x7D\xF5\xF6"
+			  "\x01\x91\xB4\x27\xDA\x59\xD6\x17"
+			  "\x56\x4D\x82\x62\x37\xA3\x48\x01"
+			  "\x99\x91\x77\xB2\x08\x6B\x2C\x37"
+			  "\xC5\x5C\xAD\xB6\x07\xB6\x84\xF3"
+			  "\x4D\x59\x7D\xC5\x28\x69\xFA\x92"
+			  "\x22\x46\x89\x2D\x0F\x2B\x08\x24",
+		.rlen	= 496,
+	},
+};
+
+static struct cipher_testvec cast6_cbc_dec_tv_template[] = {
+	{ /* Generated from TF test vectors */
+		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
+			  "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
+			  "\x78\xBE\x9B\x78\x55\x32\x0F\x55",
+		.klen	= 32,
+		.iv	= "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F"
+			  "\xC4\x29\x8E\xF3\x35\x9A\xFF\x64",
+		.input	= "\xDF\x77\x68\x96\xC7\xBA\xF8\xE2"
+			  "\x0E\x24\x99\x1A\xAA\xF3\xC6\x9F"
+			  "\xA0\x73\xB3\x70\xC3\x68\x64\x70"
+			  "\xAD\x33\x02\xFB\x88\x74\xAA\x78"
+			  "\xC7\x47\x1A\x18\x61\x2D\xAC\x9F"
+			  "\x7E\x6F\xDF\x05\x13\x76\xA6\x72"
+			  "\xB7\x13\x09\x0F\x7D\x38\xDF\x25"
+			  "\x4E\xFD\x50\x45\xFA\x35\x6A\xC0"
+			  "\x57\x95\xE1\x21\x26\x10\x9A\x21"
+			  "\xA1\x8A\x51\x05\xD1\xB1\x78\x35"
+			  "\x98\xF5\xAE\xC0\xC1\x8B\x94\xFF"
+			  "\xD0\x69\x3F\x42\xC2\x01\xA7\x9B"
+			  "\x23\x16\x47\x72\x81\x13\x3A\x72"
+			  "\xEC\xD9\x40\x88\x00\x9C\xB0\xA8"
+			  "\x9C\xAC\xCE\x11\x73\x7B\x63\x3E"
+			  "\xA3\x63\x98\x7D\x35\xE4\xD9\x83"
+			  "\xE2\xD0\x52\x87\x0C\x1F\xB0\xB3"
+			  "\x41\x1A\x93\x8D\x76\x31\x9F\xF2"
+			  "\xFE\x09\xA3\x8F\x22\x6A\x3B\xB9"
+			  "\x6C\x9E\xE4\xA1\xA0\xC4\xE7\xA1"
+			  "\x21\x9C\x1A\xCA\x65\xDE\x44\x03"
+			  "\x99\xF2\xD2\x39\xE3\x3F\x0F\x37"
+			  "\x53\x50\x23\xA4\x81\x6E\xDA\xFB"
+			  "\xF8\x7B\x01\xD7\xB2\x32\x9C\xB8"
+			  "\xB1\x0E\x99\x17\xB5\x38\xF9\xD7"
+			  "\x86\x2D\x6E\x94\x5C\x99\x9D\xB3"
+			  "\xD3\x63\x4B\x2A\x7D\x44\x6A\xB2"
+			  "\xC1\x03\xE6\x5A\x37\xD8\x64\x18"
+			  "\xAA\x32\xCE\x29\xED\xC0\xA2\xCB"
+			  "\x8D\xAF\xCD\xBE\x8F\xB6\xEC\xB4"
+			  "\x89\x05\x81\x6E\x71\x4F\xC3\x28"
+			  "\x10\xC1\x62\xC4\x41\xE9\xD2\x39"
+			  "\xF3\x22\x39\x12\x2C\xC2\x95\x2D"
+			  "\xBF\x93\x58\x4B\x04\xD1\x8D\x57"
+			  "\xAE\xEB\x60\x03\x56\x35\xAD\x5A"
+			  "\xE9\xC3\xFF\x4E\x31\xE1\x37\xF8"
+			  "\x7D\xEE\x65\x8A\xB6\x88\x1A\x3E"
+			  "\x07\x09\x82\xBA\xF0\x80\x8A\xD0"
+			  "\xA0\x3F\x6A\xE9\x24\x87\x19\x65"
+			  "\x73\x3F\x12\x91\x47\x54\xBA\x39"
+			  "\x30\x5B\x1E\xE5\xC2\xF9\x3F\xEF"
+			  "\xD6\x75\xF9\xB8\x7C\x8B\x05\x76"
+			  "\xEE\xB7\x08\x25\x4B\xB6\x7B\x47"
+			  "\x72\xC0\x4C\xD4\xDA\xE0\x75\xF1"
+			  "\x7C\xE8\x94\x9E\x16\x6E\xB8\x12"
+			  "\xA1\xC1\x6E\x3B\x1C\x59\x41\x2D"
+			  "\x23\xFA\x7D\x77\xB8\x46\x75\xFE"
+			  "\x4F\x10\xD3\x09\x60\xA1\x36\x96"
+			  "\x5B\xC2\xDC\x6E\x84\x7D\x9B\x14"
+			  "\x80\x21\x83\x58\x3C\x76\xFD\x28"
+			  "\x1D\xF9\x93\x13\xD7\x0E\x62\x14"
+			  "\x5A\xC5\x4E\x08\xA5\x56\xA4\x3C"
+			  "\x68\x93\x44\x70\xDF\xCF\x4A\x51"
+			  "\x0B\x81\x29\x41\xE5\x62\x4D\x36"
+			  "\xB3\xEA\x94\xA6\xB9\xDD\x3F\x09"
+			  "\x62\x34\xA0\x6A\x7E\x7D\xF5\xF6"
+			  "\x01\x91\xB4\x27\xDA\x59\xD6\x17"
+			  "\x56\x4D\x82\x62\x37\xA3\x48\x01"
+			  "\x99\x91\x77\xB2\x08\x6B\x2C\x37"
+			  "\xC5\x5C\xAD\xB6\x07\xB6\x84\xF3"
+			  "\x4D\x59\x7D\xC5\x28\x69\xFA\x92"
+			  "\x22\x46\x89\x2D\x0F\x2B\x08\x24",
+		.ilen	= 496,
+		.result	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+			  "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+			  "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+			  "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+			  "\xC3\x37\xCE\x65\xFC\x70\x07\x9E"
+			  "\x12\xA9\x40\xD7\x4B\xE2\x79\x10"
+			  "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F"
+			  "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1"
+			  "\x68\xFF\x73\x0A\xA1\x15\xAC\x43"
+			  "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5"
+			  "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
+			  "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
+			  "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
+			  "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+			  "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+			  "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+			  "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+			  "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+			  "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+			  "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+			  "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+			  "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+			  "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+			  "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+			  "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+			  "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+			  "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+			  "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+			  "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+			  "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+			  "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+			  "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+			  "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+			  "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+			  "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+			  "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+			  "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+			  "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+			  "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+			  "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+			  "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+			  "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+			  "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+			  "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+			  "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+			  "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+			  "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+			  "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+			  "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+			  "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+			  "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+			  "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+			  "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+			  "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+			  "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+			  "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+			  "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+			  "\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
+		.rlen	= 496,
+	},
+};
+
+static struct cipher_testvec cast6_ctr_enc_tv_template[] = {
+	{ /* Generated from TF test vectors */
+		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
+			  "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
+			  "\x78\xBE\x9B\x78\x55\x32\x0F\x55",
+		.klen	= 32,
+		.iv	= "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F"
+			  "\xC4\x29\x8E\xF3\x35\x9A\xFF\x64",
+		.input	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+			  "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+			  "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+			  "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+			  "\xC3\x37\xCE\x65\xFC\x70\x07\x9E"
+			  "\x12\xA9\x40\xD7\x4B\xE2\x79\x10"
+			  "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F"
+			  "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1"
+			  "\x68\xFF\x73\x0A\xA1\x15\xAC\x43"
+			  "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5"
+			  "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
+			  "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
+			  "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
+			  "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+			  "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+			  "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+			  "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+			  "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+			  "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+			  "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+			  "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+			  "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+			  "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+			  "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+			  "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+			  "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+			  "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+			  "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+			  "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+			  "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+			  "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+			  "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+			  "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+			  "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+			  "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+			  "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+			  "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+			  "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+			  "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+			  "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+			  "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+			  "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+			  "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+			  "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+			  "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+			  "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+			  "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+			  "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+			  "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+			  "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+			  "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+			  "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+			  "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+			  "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+			  "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+			  "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+			  "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+			  "\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
+		.ilen	= 496,
+		.result	= "\x26\x0A\xF1\xE2\x3F\x8A\xEF\xA3"
+			  "\x53\x9A\x5E\x1B\x2A\x1A\xC6\x0A"
+			  "\x57\xA3\xEF\x47\x2A\xE8\x88\xA7"
+			  "\x3C\xD0\xEC\xB9\x94\x50\x7D\x56"
+			  "\xBC\xE1\xC1\xF5\xE1\xEE\x12\xF8"
+			  "\x4F\x03\x82\x3A\x93\x6B\x4C\xD3"
+			  "\xE3\xF3\xFA\xC2\x23\x55\x98\x20"
+			  "\x49\x76\x9B\x6B\xC1\x23\xBF\xE5"
+			  "\xD4\xC4\x2F\x61\xE1\x67\x2A\x30"
+			  "\x6F\x29\xCA\x54\xF8\x1B\xA6\x7D"
+			  "\x66\x45\xEE\xC8\x19\xBE\x50\xF0"
+			  "\x5F\x65\xF8\x1E\x4D\x07\x87\xD9"
+			  "\xD3\xD9\x1B\x09\x89\xFD\x42\xC5"
+			  "\xDB\xEB\x86\xF1\x67\x04\x0F\x5C"
+			  "\x81\xDF\x82\x12\xC7\x4C\x1B\x07"
+			  "\xDE\xE6\xFA\x29\x86\xD1\xB0\xBA"
+			  "\x3D\x6A\x69\x76\xEC\x0F\xB4\xE6"
+			  "\xCD\xA7\xF8\xA8\xB8\xE0\x33\xF5"
+			  "\x49\x61\x22\x52\x64\x8C\x46\x41"
+			  "\x1F\x48\x5F\x4F\xA2\x89\x36\x17"
+			  "\x20\xF8\x2F\x8F\x4B\xFA\xF2\xC0"
+			  "\x1E\x18\xA2\xF8\xB7\x6D\x98\xE3"
+			  "\x00\x14\x15\x59\xC1\x30\x64\xAF"
+			  "\xA8\x01\x38\xAB\xD4\x8B\xEC\x7C"
+			  "\x44\x9A\xC6\x2C\x2E\x2B\x2B\xF4"
+			  "\x02\x37\xC4\x69\xEF\x36\xC1\xF3"
+			  "\xA0\xFB\xFE\x29\xAD\x39\xCF\xD0"
+			  "\x51\x73\xA3\x22\x42\x41\xAB\xD2"
+			  "\x0F\x50\x14\xB9\x54\xD3\xD4\xFA"
+			  "\xBF\xC9\xBB\xCE\xC4\x1D\x2D\xAF"
+			  "\xC9\x3F\x07\x87\x42\x4B\x3A\x54"
+			  "\x34\x8E\x37\xA3\x03\x6F\x65\x66"
+			  "\xDB\x44\xC3\xE8\xD7\xDD\x7D\xDD"
+			  "\x61\xB4\x2B\x80\xA3\x98\x13\xF5"
+			  "\x5A\xD3\x34\x58\xC3\x6E\xF6\xB8"
+			  "\x0A\xC6\x50\x01\x8E\xD5\x6C\x7D"
+			  "\xFE\x16\xB6\xCF\xFC\x51\x40\xAE"
+			  "\xB3\x15\xAC\x90\x6F\x0B\x28\x3A"
+			  "\x60\x40\x38\x90\x20\x46\xC7\xB3"
+			  "\x0B\x12\x6D\x3B\x15\x14\xF9\xF4"
+			  "\x11\x41\x76\x6B\xB3\x60\x82\x3C"
+			  "\x84\xFB\x08\x2E\x92\x25\xCB\x79"
+			  "\x6F\x58\xC5\x94\x00\x00\x47\xB6"
+			  "\x9E\xDC\x0F\x29\x70\x46\x20\x76"
+			  "\x65\x75\x66\x5C\x00\x96\xB3\xE1"
+			  "\x0B\xA7\x11\x8B\x2E\x61\x4E\x45"
+			  "\x73\xFC\x91\xAB\x79\x41\x23\x14"
+			  "\x13\xB6\x72\x6C\x46\xB3\x03\x11"
+			  "\xE4\xF1\xEE\xC9\x7A\xCF\x96\x32"
+			  "\xB6\xF0\x8B\x97\xB4\xCF\x82\xB7"
+			  "\x15\x48\x44\x99\x09\xF6\xE0\xD7"
+			  "\xBC\xF1\x5B\x91\x4F\x30\x22\xA2"
+			  "\x45\xC4\x68\x55\xC2\xBE\xA7\xD2"
+			  "\x12\x53\x35\x9C\xF9\xE7\x35\x5D"
+			  "\x81\xE4\x86\x42\xC3\x58\xFB\xF0"
+			  "\x38\x9B\x8E\x5A\xEF\x83\x33\x0F"
+			  "\x00\x4E\x3F\x9F\xF5\x84\x62\xC4"
+			  "\x19\x35\x88\x22\x45\x59\x0E\x8F"
+			  "\xEC\x27\xDD\x4A\xA4\x1F\xBC\x41"
+			  "\x9B\x66\x8D\x32\xBA\x81\x34\x87"
+			  "\x0E\x74\x33\x30\x62\xB9\x89\xDF"
+			  "\xF9\xC5\xDD\x27\xB3\x39\xCB\xCB",
+		.rlen	= 496,
+	},
+};
+
+static struct cipher_testvec cast6_ctr_dec_tv_template[] = {
+	{ /* Generated from TF test vectors */
+		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A"
+			  "\x27\x04\xE1\x27\x04\xE1\xBE\x9B"
+			  "\x78\xBE\x9B\x78\x55\x32\x0F\x55",
+		.klen	= 32,
+		.iv	= "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F"
+			  "\xC4\x29\x8E\xF3\x35\x9A\xFF\x64",
+		.input	= "\x26\x0A\xF1\xE2\x3F\x8A\xEF\xA3"
+			  "\x53\x9A\x5E\x1B\x2A\x1A\xC6\x0A"
+			  "\x57\xA3\xEF\x47\x2A\xE8\x88\xA7"
+			  "\x3C\xD0\xEC\xB9\x94\x50\x7D\x56"
+			  "\xBC\xE1\xC1\xF5\xE1\xEE\x12\xF8"
+			  "\x4F\x03\x82\x3A\x93\x6B\x4C\xD3"
+			  "\xE3\xF3\xFA\xC2\x23\x55\x98\x20"
+			  "\x49\x76\x9B\x6B\xC1\x23\xBF\xE5"
+			  "\xD4\xC4\x2F\x61\xE1\x67\x2A\x30"
+			  "\x6F\x29\xCA\x54\xF8\x1B\xA6\x7D"
+			  "\x66\x45\xEE\xC8\x19\xBE\x50\xF0"
+			  "\x5F\x65\xF8\x1E\x4D\x07\x87\xD9"
+			  "\xD3\xD9\x1B\x09\x89\xFD\x42\xC5"
+			  "\xDB\xEB\x86\xF1\x67\x04\x0F\x5C"
+			  "\x81\xDF\x82\x12\xC7\x4C\x1B\x07"
+			  "\xDE\xE6\xFA\x29\x86\xD1\xB0\xBA"
+			  "\x3D\x6A\x69\x76\xEC\x0F\xB4\xE6"
+			  "\xCD\xA7\xF8\xA8\xB8\xE0\x33\xF5"
+			  "\x49\x61\x22\x52\x64\x8C\x46\x41"
+			  "\x1F\x48\x5F\x4F\xA2\x89\x36\x17"
+			  "\x20\xF8\x2F\x8F\x4B\xFA\xF2\xC0"
+			  "\x1E\x18\xA2\xF8\xB7\x6D\x98\xE3"
+			  "\x00\x14\x15\x59\xC1\x30\x64\xAF"
+			  "\xA8\x01\x38\xAB\xD4\x8B\xEC\x7C"
+			  "\x44\x9A\xC6\x2C\x2E\x2B\x2B\xF4"
+			  "\x02\x37\xC4\x69\xEF\x36\xC1\xF3"
+			  "\xA0\xFB\xFE\x29\xAD\x39\xCF\xD0"
+			  "\x51\x73\xA3\x22\x42\x41\xAB\xD2"
+			  "\x0F\x50\x14\xB9\x54\xD3\xD4\xFA"
+			  "\xBF\xC9\xBB\xCE\xC4\x1D\x2D\xAF"
+			  "\xC9\x3F\x07\x87\x42\x4B\x3A\x54"
+			  "\x34\x8E\x37\xA3\x03\x6F\x65\x66"
+			  "\xDB\x44\xC3\xE8\xD7\xDD\x7D\xDD"
+			  "\x61\xB4\x2B\x80\xA3\x98\x13\xF5"
+			  "\x5A\xD3\x34\x58\xC3\x6E\xF6\xB8"
+			  "\x0A\xC6\x50\x01\x8E\xD5\x6C\x7D"
+			  "\xFE\x16\xB6\xCF\xFC\x51\x40\xAE"
+			  "\xB3\x15\xAC\x90\x6F\x0B\x28\x3A"
+			  "\x60\x40\x38\x90\x20\x46\xC7\xB3"
+			  "\x0B\x12\x6D\x3B\x15\x14\xF9\xF4"
+			  "\x11\x41\x76\x6B\xB3\x60\x82\x3C"
+			  "\x84\xFB\x08\x2E\x92\x25\xCB\x79"
+			  "\x6F\x58\xC5\x94\x00\x00\x47\xB6"
+			  "\x9E\xDC\x0F\x29\x70\x46\x20\x76"
+			  "\x65\x75\x66\x5C\x00\x96\xB3\xE1"
+			  "\x0B\xA7\x11\x8B\x2E\x61\x4E\x45"
+			  "\x73\xFC\x91\xAB\x79\x41\x23\x14"
+			  "\x13\xB6\x72\x6C\x46\xB3\x03\x11"
+			  "\xE4\xF1\xEE\xC9\x7A\xCF\x96\x32"
+			  "\xB6\xF0\x8B\x97\xB4\xCF\x82\xB7"
+			  "\x15\x48\x44\x99\x09\xF6\xE0\xD7"
+			  "\xBC\xF1\x5B\x91\x4F\x30\x22\xA2"
+			  "\x45\xC4\x68\x55\xC2\xBE\xA7\xD2"
+			  "\x12\x53\x35\x9C\xF9\xE7\x35\x5D"
+			  "\x81\xE4\x86\x42\xC3\x58\xFB\xF0"
+			  "\x38\x9B\x8E\x5A\xEF\x83\x33\x0F"
+			  "\x00\x4E\x3F\x9F\xF5\x84\x62\xC4"
+			  "\x19\x35\x88\x22\x45\x59\x0E\x8F"
+			  "\xEC\x27\xDD\x4A\xA4\x1F\xBC\x41"
+			  "\x9B\x66\x8D\x32\xBA\x81\x34\x87"
+			  "\x0E\x74\x33\x30\x62\xB9\x89\xDF"
+			  "\xF9\xC5\xDD\x27\xB3\x39\xCB\xCB",
+		.ilen	= 496,
+		.result	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+			  "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+			  "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+			  "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+			  "\xC3\x37\xCE\x65\xFC\x70\x07\x9E"
+			  "\x12\xA9\x40\xD7\x4B\xE2\x79\x10"
+			  "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F"
+			  "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1"
+			  "\x68\xFF\x73\x0A\xA1\x15\xAC\x43"
+			  "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5"
+			  "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
+			  "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
+			  "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
+			  "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+			  "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+			  "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+			  "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+			  "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+			  "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+			  "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+			  "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+			  "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+			  "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+			  "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+			  "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+			  "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+			  "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+			  "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+			  "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+			  "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+			  "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+			  "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+			  "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+			  "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+			  "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+			  "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+			  "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+			  "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+			  "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+			  "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+			  "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+			  "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+			  "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+			  "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+			  "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+			  "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+			  "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+			  "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+			  "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+			  "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+			  "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+			  "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+			  "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+			  "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+			  "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+			  "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+			  "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+			  "\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
+		.rlen	= 496,
+	},
+};
+
+static struct cipher_testvec cast6_lrw_enc_tv_template[] = {
+	{ /* Generated from TF test vectors */
+		.key	= "\xf8\xd4\x76\xff\xd6\x46\xee\x6c"
+			  "\x23\x84\xcb\x1c\x77\xd6\x19\x5d"
+			  "\xfe\xf1\xa9\xf3\x7b\xbc\x8d\x21"
+			  "\xa7\x9c\x21\xf8\xcb\x90\x02\x89"
+			  "\xa8\x45\x34\x8e\xc8\xc5\xb5\xf1"
+			  "\x26\xf5\x0e\x76\xfe\xfd\x1b\x1e",
+		.klen	= 48,
+		.iv	= "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x01",
+		.input	= "\x05\x11\xb7\x18\xab\xc6\x2d\xac"
+			  "\x70\x5d\xf6\x22\x94\xcd\xe5\x6c"
+			  "\x17\x6b\xf6\x1c\xf0\xf3\x6e\xf8"
+			  "\x50\x38\x1f\x71\x49\xb6\x57\xd6"
+			  "\x8f\xcb\x8d\x6b\xe3\xa6\x29\x90"
+			  "\xfe\x2a\x62\x82\xae\x6d\x8b\xf6"
+			  "\xad\x1e\x9e\x20\x5f\x38\xbe\x04"
+			  "\xda\x10\x8e\xed\xa2\xa4\x87\xab"
+			  "\xda\x6b\xb4\x0c\x75\xba\xd3\x7c"
+			  "\xc9\xac\x42\x31\x95\x7c\xc9\x04"
+			  "\xeb\xd5\x6e\x32\x69\x8a\xdb\xa6"
+			  "\x15\xd7\x3f\x4f\x2f\x66\x69\x03"
+			  "\x9c\x1f\x54\x0f\xde\x1f\xf3\x65"
+			  "\x4c\x96\x12\xed\x7c\x92\x03\x01"
+			  "\x6f\xbc\x35\x93\xac\xf1\x27\xf1"
+			  "\xb4\x96\x82\x5a\x5f\xb0\xa0\x50"
+			  "\x89\xa4\x8e\x66\x44\x85\xcc\xfd"
+			  "\x33\x14\x70\xe3\x96\xb2\xc3\xd3"
+			  "\xbb\x54\x5a\x1a\xf9\x74\xa2\xc5"
+			  "\x2d\x64\x75\xdd\xb4\x54\xe6\x74"
+			  "\x8c\xd3\x9d\x9e\x86\xab\x51\x53"
+			  "\xb7\x93\x3e\x6f\xd0\x4e\x2c\x40"
+			  "\xf6\xa8\x2e\x3e\x9d\xf4\x66\xa5"
+			  "\x76\x12\x73\x44\x1a\x56\xd7\x72"
+			  "\x88\xcd\x21\x8c\x4c\x0f\xfe\xda"
+			  "\x95\xe0\x3a\xa6\xa5\x84\x46\xcd"
+			  "\xd5\x3e\x9d\x3a\xe2\x67\xe6\x60"
+			  "\x1a\xe2\x70\x85\x58\xc2\x1b\x09"
+			  "\xe1\xd7\x2c\xca\xad\xa8\x8f\xf9"
+			  "\xac\xb3\x0e\xdb\xca\x2e\xe2\xb8"
+			  "\x51\x71\xd9\x3c\x6c\xf1\x56\xf8"
+			  "\xea\x9c\xf1\xfb\x0c\xe6\xb7\x10"
+			  "\x1c\xf8\xa9\x7c\xe8\x53\x35\xc1"
+			  "\x90\x3e\x76\x4a\x74\xa4\x21\x2c"
+			  "\xf6\x2c\x4e\x0f\x94\x3a\x88\x2e"
+			  "\x41\x09\x6a\x33\x7d\xf6\xdd\x3f"
+			  "\x8d\x23\x31\x74\x84\xeb\x88\x6e"
+			  "\xcc\xb9\xbc\x22\x83\x19\x07\x22"
+			  "\xa5\x2d\xdf\xa5\xf3\x80\x85\x78"
+			  "\x84\x39\x6a\x6d\x6a\x99\x4f\xa5"
+			  "\x15\xfe\x46\xb0\xe4\x6c\xa5\x41"
+			  "\x3c\xce\x8f\x42\x60\x71\xa7\x75"
+			  "\x08\x40\x65\x8a\x82\xbf\xf5\x43"
+			  "\x71\x96\xa9\x4d\x44\x8a\x20\xbe"
+			  "\xfa\x4d\xbb\xc0\x7d\x31\x96\x65"
+			  "\xe7\x75\xe5\x3e\xfd\x92\x3b\xc9"
+			  "\x55\xbb\x16\x7e\xf7\xc2\x8c\xa4"
+			  "\x40\x1d\xe5\xef\x0e\xdf\xe4\x9a"
+			  "\x62\x73\x65\xfd\x46\x63\x25\x3d"
+			  "\x2b\xaf\xe5\x64\xfe\xa5\x5c\xcf"
+			  "\x24\xf3\xb4\xac\x64\xba\xdf\x4b"
+			  "\xc6\x96\x7d\x81\x2d\x8d\x97\xf7"
+			  "\xc5\x68\x77\x84\x32\x2b\xcc\x85"
+			  "\x74\x96\xf0\x12\x77\x61\xb9\xeb"
+			  "\x71\xaa\x82\xcb\x1c\xdb\x89\xc8"
+			  "\xc6\xb5\xe3\x5c\x7d\x39\x07\x24"
+			  "\xda\x39\x87\x45\xc0\x2b\xbb\x01"
+			  "\xac\xbc\x2a\x5c\x7f\xfc\xe8\xce"
+			  "\x6d\x9c\x6f\xed\xd3\xc1\xa1\xd6"
+			  "\xc5\x55\xa9\x66\x2f\xe1\xc8\x32"
+			  "\xa6\x5d\xa4\x3a\x98\x73\xe8\x45"
+			  "\xa4\xc7\xa8\xb4\xf6\x13\x03\xf6"
+			  "\xe9\x2e\xc4\x29\x0f\x84\xdb\xc4"
+			  "\x21\xc4\xc2\x75\x67\x89\x37\x0a",
+		.ilen	= 512,
+		.result	= "\x55\x25\x09\x8B\xB5\xD5\xF8\xBF"
+			  "\x37\x4A\xFE\x3C\x47\xD8\xE6\xEB"
+			  "\xCA\xA4\x9B\xB0\xAB\x6D\x64\xCA"
+			  "\x58\xB6\x73\xF0\xD7\x52\x34\xEF"
+			  "\xFB\x3E\x96\x81\xB7\x71\x34\xA4"
+			  "\x55\x20\xBE\x39\x5A\x2B\xF9\xD1"
+			  "\x65\x0B\xDA\xD3\x7E\xB3\xA6\xF7"
+			  "\x2E\x0B\x5A\x52\xDB\x39\x8C\x9B"
+			  "\x61\x17\x5F\xAF\xB6\x5A\xC8\x08"
+			  "\xA7\xB7\x2A\x11\x7C\x97\x38\x9D"
+			  "\x59\x0E\x66\x59\x5E\xD8\x8B\xCE"
+			  "\x70\xE0\xC3\x42\xB0\x8C\x0F\xBA"
+			  "\xB2\x0D\x81\xB6\xBE\x61\x1C\x2D"
+			  "\x7E\xEA\x91\x25\xAC\xEC\xF8\x28"
+			  "\x80\x1D\xF0\x30\xBA\x62\x77\x7D"
+			  "\xDB\x15\x69\xDF\xFA\x2A\x81\x64"
+			  "\x95\x5B\xA4\x7F\x3E\x4F\xE3\x30"
+			  "\xB0\x5C\xC2\x05\xF8\xF0\x29\xE7"
+			  "\x0A\xA0\x66\xB2\x5D\x0F\x39\x2B"
+			  "\xB4\xB3\x00\xA9\xD0\xAB\x63\x61"
+			  "\x5E\xDB\xFC\x11\x74\x25\x96\x65"
+			  "\xE8\xE2\x34\x57\x77\x15\x5E\x70"
+			  "\xFF\x10\x90\xC3\x64\xF0\x11\x0A"
+			  "\x63\x3A\xD3\x55\x92\x15\x4B\x0C"
+			  "\xC7\x08\x89\x17\x3B\x99\xAD\x63"
+			  "\xE7\x06\xDF\x52\xBC\x15\x64\x45"
+			  "\x9D\x7A\xFB\x69\xBC\x2D\x6E\xA9"
+			  "\x35\xD9\xD8\xF5\x0C\xC4\xA2\x23"
+			  "\x9C\x18\x8B\xA8\x8C\xFE\xF8\x0E"
+			  "\xBD\xAB\x60\x1A\x51\x17\x54\x27"
+			  "\xB6\xE8\xBE\x0F\xA9\xA5\x82\x19"
+			  "\x2F\x6F\x20\xA7\x47\xED\x74\x6C"
+			  "\x4E\xC1\xF8\x8C\x14\xF3\xBB\x1F"
+			  "\xED\x4D\x8F\x7C\x37\xEF\x19\xA1"
+			  "\x07\x16\xDE\x76\xCC\x5E\x94\x02"
+			  "\xFB\xBF\xE4\x81\x50\xCE\xFC\x0F"
+			  "\x9E\xCF\x3D\xF6\x67\x00\xBF\xA7"
+			  "\x6E\x21\x58\x36\x06\xDE\xB3\xD4"
+			  "\xA2\xFA\xD8\x4E\xE0\xB9\x7F\x23"
+			  "\x51\x21\x2B\x32\x68\xAA\xF8\xA8"
+			  "\x93\x08\xB5\x6D\xE6\x43\x2C\xB7"
+			  "\x31\xB2\x0F\xD0\xA2\x51\xC0\x25"
+			  "\x30\xC7\x10\x3F\x97\x27\x01\x8E"
+			  "\xFA\xD8\x4F\x78\xD8\x2E\x1D\xEB"
+			  "\xA1\x37\x52\x0F\x7B\x5E\x87\xA8"
+			  "\x22\xE2\xE6\x92\xA7\x5F\x11\x32"
+			  "\xCC\x93\x34\xFC\xD1\x7E\xAE\x54"
+			  "\xBC\x6A\x1B\x91\xD1\x2E\x21\xEC"
+			  "\x5D\xF1\xC4\xF1\x55\x20\xBF\xE5"
+			  "\x96\x3D\x69\x91\x20\x4E\xF2\x61"
+			  "\xDA\x77\xFE\xEE\xC3\x74\x57\x2A"
+			  "\x78\x39\xB0\xE0\xCF\x12\x56\xD6"
+			  "\x05\xDC\xF9\x19\x66\x44\x1D\xF9"
+			  "\x82\x37\xD4\xC2\x60\xB6\x31\xDF"
+			  "\x0C\xAF\xBC\x8B\x55\x9A\xC8\x2D"
+			  "\xAB\xA7\x88\x7B\x41\xE8\x29\xC9"
+			  "\x9B\x8D\xA7\x00\x86\x25\xB6\x14"
+			  "\xF5\x13\x73\xD7\x4B\x6B\x83\xF3"
+			  "\xAF\x96\x00\xE4\xB7\x3C\x65\xA6"
+			  "\x15\xB7\x94\x7D\x4E\x70\x4C\x75"
+			  "\xF3\xB4\x02\xA9\x17\x1C\x7A\x0A"
+			  "\xC0\xD5\x33\x11\x56\xDE\xDC\xF5"
+			  "\x8D\xD9\xCD\x3B\x22\x67\x18\xC7"
+			  "\xC4\xF5\x99\x61\xBC\xBB\x5B\x46",
+		.rlen	= 512,
+	},
+};
+
+static struct cipher_testvec cast6_lrw_dec_tv_template[] = {
+	{ /* Generated from TF test vectors */
+		.key	= "\xf8\xd4\x76\xff\xd6\x46\xee\x6c"
+			  "\x23\x84\xcb\x1c\x77\xd6\x19\x5d"
+			  "\xfe\xf1\xa9\xf3\x7b\xbc\x8d\x21"
+			  "\xa7\x9c\x21\xf8\xcb\x90\x02\x89"
+			  "\xa8\x45\x34\x8e\xc8\xc5\xb5\xf1"
+			  "\x26\xf5\x0e\x76\xfe\xfd\x1b\x1e",
+		.klen	= 48,
+		.iv	= "\x00\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x01",
+		.input	= "\x55\x25\x09\x8B\xB5\xD5\xF8\xBF"
+			  "\x37\x4A\xFE\x3C\x47\xD8\xE6\xEB"
+			  "\xCA\xA4\x9B\xB0\xAB\x6D\x64\xCA"
+			  "\x58\xB6\x73\xF0\xD7\x52\x34\xEF"
+			  "\xFB\x3E\x96\x81\xB7\x71\x34\xA4"
+			  "\x55\x20\xBE\x39\x5A\x2B\xF9\xD1"
+			  "\x65\x0B\xDA\xD3\x7E\xB3\xA6\xF7"
+			  "\x2E\x0B\x5A\x52\xDB\x39\x8C\x9B"
+			  "\x61\x17\x5F\xAF\xB6\x5A\xC8\x08"
+			  "\xA7\xB7\x2A\x11\x7C\x97\x38\x9D"
+			  "\x59\x0E\x66\x59\x5E\xD8\x8B\xCE"
+			  "\x70\xE0\xC3\x42\xB0\x8C\x0F\xBA"
+			  "\xB2\x0D\x81\xB6\xBE\x61\x1C\x2D"
+			  "\x7E\xEA\x91\x25\xAC\xEC\xF8\x28"
+			  "\x80\x1D\xF0\x30\xBA\x62\x77\x7D"
+			  "\xDB\x15\x69\xDF\xFA\x2A\x81\x64"
+			  "\x95\x5B\xA4\x7F\x3E\x4F\xE3\x30"
+			  "\xB0\x5C\xC2\x05\xF8\xF0\x29\xE7"
+			  "\x0A\xA0\x66\xB2\x5D\x0F\x39\x2B"
+			  "\xB4\xB3\x00\xA9\xD0\xAB\x63\x61"
+			  "\x5E\xDB\xFC\x11\x74\x25\x96\x65"
+			  "\xE8\xE2\x34\x57\x77\x15\x5E\x70"
+			  "\xFF\x10\x90\xC3\x64\xF0\x11\x0A"
+			  "\x63\x3A\xD3\x55\x92\x15\x4B\x0C"
+			  "\xC7\x08\x89\x17\x3B\x99\xAD\x63"
+			  "\xE7\x06\xDF\x52\xBC\x15\x64\x45"
+			  "\x9D\x7A\xFB\x69\xBC\x2D\x6E\xA9"
+			  "\x35\xD9\xD8\xF5\x0C\xC4\xA2\x23"
+			  "\x9C\x18\x8B\xA8\x8C\xFE\xF8\x0E"
+			  "\xBD\xAB\x60\x1A\x51\x17\x54\x27"
+			  "\xB6\xE8\xBE\x0F\xA9\xA5\x82\x19"
+			  "\x2F\x6F\x20\xA7\x47\xED\x74\x6C"
+			  "\x4E\xC1\xF8\x8C\x14\xF3\xBB\x1F"
+			  "\xED\x4D\x8F\x7C\x37\xEF\x19\xA1"
+			  "\x07\x16\xDE\x76\xCC\x5E\x94\x02"
+			  "\xFB\xBF\xE4\x81\x50\xCE\xFC\x0F"
+			  "\x9E\xCF\x3D\xF6\x67\x00\xBF\xA7"
+			  "\x6E\x21\x58\x36\x06\xDE\xB3\xD4"
+			  "\xA2\xFA\xD8\x4E\xE0\xB9\x7F\x23"
+			  "\x51\x21\x2B\x32\x68\xAA\xF8\xA8"
+			  "\x93\x08\xB5\x6D\xE6\x43\x2C\xB7"
+			  "\x31\xB2\x0F\xD0\xA2\x51\xC0\x25"
+			  "\x30\xC7\x10\x3F\x97\x27\x01\x8E"
+			  "\xFA\xD8\x4F\x78\xD8\x2E\x1D\xEB"
+			  "\xA1\x37\x52\x0F\x7B\x5E\x87\xA8"
+			  "\x22\xE2\xE6\x92\xA7\x5F\x11\x32"
+			  "\xCC\x93\x34\xFC\xD1\x7E\xAE\x54"
+			  "\xBC\x6A\x1B\x91\xD1\x2E\x21\xEC"
+			  "\x5D\xF1\xC4\xF1\x55\x20\xBF\xE5"
+			  "\x96\x3D\x69\x91\x20\x4E\xF2\x61"
+			  "\xDA\x77\xFE\xEE\xC3\x74\x57\x2A"
+			  "\x78\x39\xB0\xE0\xCF\x12\x56\xD6"
+			  "\x05\xDC\xF9\x19\x66\x44\x1D\xF9"
+			  "\x82\x37\xD4\xC2\x60\xB6\x31\xDF"
+			  "\x0C\xAF\xBC\x8B\x55\x9A\xC8\x2D"
+			  "\xAB\xA7\x88\x7B\x41\xE8\x29\xC9"
+			  "\x9B\x8D\xA7\x00\x86\x25\xB6\x14"
+			  "\xF5\x13\x73\xD7\x4B\x6B\x83\xF3"
+			  "\xAF\x96\x00\xE4\xB7\x3C\x65\xA6"
+			  "\x15\xB7\x94\x7D\x4E\x70\x4C\x75"
+			  "\xF3\xB4\x02\xA9\x17\x1C\x7A\x0A"
+			  "\xC0\xD5\x33\x11\x56\xDE\xDC\xF5"
+			  "\x8D\xD9\xCD\x3B\x22\x67\x18\xC7"
+			  "\xC4\xF5\x99\x61\xBC\xBB\x5B\x46",
+		.ilen	= 512,
+		.result	= "\x05\x11\xb7\x18\xab\xc6\x2d\xac"
+			  "\x70\x5d\xf6\x22\x94\xcd\xe5\x6c"
+			  "\x17\x6b\xf6\x1c\xf0\xf3\x6e\xf8"
+			  "\x50\x38\x1f\x71\x49\xb6\x57\xd6"
+			  "\x8f\xcb\x8d\x6b\xe3\xa6\x29\x90"
+			  "\xfe\x2a\x62\x82\xae\x6d\x8b\xf6"
+			  "\xad\x1e\x9e\x20\x5f\x38\xbe\x04"
+			  "\xda\x10\x8e\xed\xa2\xa4\x87\xab"
+			  "\xda\x6b\xb4\x0c\x75\xba\xd3\x7c"
+			  "\xc9\xac\x42\x31\x95\x7c\xc9\x04"
+			  "\xeb\xd5\x6e\x32\x69\x8a\xdb\xa6"
+			  "\x15\xd7\x3f\x4f\x2f\x66\x69\x03"
+			  "\x9c\x1f\x54\x0f\xde\x1f\xf3\x65"
+			  "\x4c\x96\x12\xed\x7c\x92\x03\x01"
+			  "\x6f\xbc\x35\x93\xac\xf1\x27\xf1"
+			  "\xb4\x96\x82\x5a\x5f\xb0\xa0\x50"
+			  "\x89\xa4\x8e\x66\x44\x85\xcc\xfd"
+			  "\x33\x14\x70\xe3\x96\xb2\xc3\xd3"
+			  "\xbb\x54\x5a\x1a\xf9\x74\xa2\xc5"
+			  "\x2d\x64\x75\xdd\xb4\x54\xe6\x74"
+			  "\x8c\xd3\x9d\x9e\x86\xab\x51\x53"
+			  "\xb7\x93\x3e\x6f\xd0\x4e\x2c\x40"
+			  "\xf6\xa8\x2e\x3e\x9d\xf4\x66\xa5"
+			  "\x76\x12\x73\x44\x1a\x56\xd7\x72"
+			  "\x88\xcd\x21\x8c\x4c\x0f\xfe\xda"
+			  "\x95\xe0\x3a\xa6\xa5\x84\x46\xcd"
+			  "\xd5\x3e\x9d\x3a\xe2\x67\xe6\x60"
+			  "\x1a\xe2\x70\x85\x58\xc2\x1b\x09"
+			  "\xe1\xd7\x2c\xca\xad\xa8\x8f\xf9"
+			  "\xac\xb3\x0e\xdb\xca\x2e\xe2\xb8"
+			  "\x51\x71\xd9\x3c\x6c\xf1\x56\xf8"
+			  "\xea\x9c\xf1\xfb\x0c\xe6\xb7\x10"
+			  "\x1c\xf8\xa9\x7c\xe8\x53\x35\xc1"
+			  "\x90\x3e\x76\x4a\x74\xa4\x21\x2c"
+			  "\xf6\x2c\x4e\x0f\x94\x3a\x88\x2e"
+			  "\x41\x09\x6a\x33\x7d\xf6\xdd\x3f"
+			  "\x8d\x23\x31\x74\x84\xeb\x88\x6e"
+			  "\xcc\xb9\xbc\x22\x83\x19\x07\x22"
+			  "\xa5\x2d\xdf\xa5\xf3\x80\x85\x78"
+			  "\x84\x39\x6a\x6d\x6a\x99\x4f\xa5"
+			  "\x15\xfe\x46\xb0\xe4\x6c\xa5\x41"
+			  "\x3c\xce\x8f\x42\x60\x71\xa7\x75"
+			  "\x08\x40\x65\x8a\x82\xbf\xf5\x43"
+			  "\x71\x96\xa9\x4d\x44\x8a\x20\xbe"
+			  "\xfa\x4d\xbb\xc0\x7d\x31\x96\x65"
+			  "\xe7\x75\xe5\x3e\xfd\x92\x3b\xc9"
+			  "\x55\xbb\x16\x7e\xf7\xc2\x8c\xa4"
+			  "\x40\x1d\xe5\xef\x0e\xdf\xe4\x9a"
+			  "\x62\x73\x65\xfd\x46\x63\x25\x3d"
+			  "\x2b\xaf\xe5\x64\xfe\xa5\x5c\xcf"
+			  "\x24\xf3\xb4\xac\x64\xba\xdf\x4b"
+			  "\xc6\x96\x7d\x81\x2d\x8d\x97\xf7"
+			  "\xc5\x68\x77\x84\x32\x2b\xcc\x85"
+			  "\x74\x96\xf0\x12\x77\x61\xb9\xeb"
+			  "\x71\xaa\x82\xcb\x1c\xdb\x89\xc8"
+			  "\xc6\xb5\xe3\x5c\x7d\x39\x07\x24"
+			  "\xda\x39\x87\x45\xc0\x2b\xbb\x01"
+			  "\xac\xbc\x2a\x5c\x7f\xfc\xe8\xce"
+			  "\x6d\x9c\x6f\xed\xd3\xc1\xa1\xd6"
+			  "\xc5\x55\xa9\x66\x2f\xe1\xc8\x32"
+			  "\xa6\x5d\xa4\x3a\x98\x73\xe8\x45"
+			  "\xa4\xc7\xa8\xb4\xf6\x13\x03\xf6"
+			  "\xe9\x2e\xc4\x29\x0f\x84\xdb\xc4"
+			  "\x21\xc4\xc2\x75\x67\x89\x37\x0a",
+		.rlen	= 512,
+	},
+};
+
+static struct cipher_testvec cast6_xts_enc_tv_template[] = {
+	{ /* Generated from TF test vectors */
+		.key	= "\x27\x18\x28\x18\x28\x45\x90\x45"
+			  "\x23\x53\x60\x28\x74\x71\x35\x26"
+			  "\x62\x49\x77\x57\x24\x70\x93\x69"
+			  "\x99\x59\x57\x49\x66\x96\x76\x27"
+			  "\x31\x41\x59\x26\x53\x58\x97\x93"
+			  "\x23\x84\x62\x64\x33\x83\x27\x95"
+			  "\x02\x88\x41\x97\x16\x93\x99\x37"
+			  "\x51\x05\x82\x09\x74\x94\x45\x92",
+		.klen	= 64,
+		.iv	= "\xff\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00",
+		.input	= "\x00\x01\x02\x03\x04\x05\x06\x07"
+			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+			  "\x10\x11\x12\x13\x14\x15\x16\x17"
+			  "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
+			  "\x20\x21\x22\x23\x24\x25\x26\x27"
+			  "\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f"
+			  "\x30\x31\x32\x33\x34\x35\x36\x37"
+			  "\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f"
+			  "\x40\x41\x42\x43\x44\x45\x46\x47"
+			  "\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f"
+			  "\x50\x51\x52\x53\x54\x55\x56\x57"
+			  "\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f"
+			  "\x60\x61\x62\x63\x64\x65\x66\x67"
+			  "\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f"
+			  "\x70\x71\x72\x73\x74\x75\x76\x77"
+			  "\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f"
+			  "\x80\x81\x82\x83\x84\x85\x86\x87"
+			  "\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f"
+			  "\x90\x91\x92\x93\x94\x95\x96\x97"
+			  "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f"
+			  "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7"
+			  "\xa8\xa9\xaa\xab\xac\xad\xae\xaf"
+			  "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7"
+			  "\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf"
+			  "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7"
+			  "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf"
+			  "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7"
+			  "\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf"
+			  "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7"
+			  "\xe8\xe9\xea\xeb\xec\xed\xee\xef"
+			  "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7"
+			  "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"
+			  "\x00\x01\x02\x03\x04\x05\x06\x07"
+			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+			  "\x10\x11\x12\x13\x14\x15\x16\x17"
+			  "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
+			  "\x20\x21\x22\x23\x24\x25\x26\x27"
+			  "\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f"
+			  "\x30\x31\x32\x33\x34\x35\x36\x37"
+			  "\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f"
+			  "\x40\x41\x42\x43\x44\x45\x46\x47"
+			  "\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f"
+			  "\x50\x51\x52\x53\x54\x55\x56\x57"
+			  "\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f"
+			  "\x60\x61\x62\x63\x64\x65\x66\x67"
+			  "\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f"
+			  "\x70\x71\x72\x73\x74\x75\x76\x77"
+			  "\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f"
+			  "\x80\x81\x82\x83\x84\x85\x86\x87"
+			  "\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f"
+			  "\x90\x91\x92\x93\x94\x95\x96\x97"
+			  "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f"
+			  "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7"
+			  "\xa8\xa9\xaa\xab\xac\xad\xae\xaf"
+			  "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7"
+			  "\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf"
+			  "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7"
+			  "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf"
+			  "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7"
+			  "\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf"
+			  "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7"
+			  "\xe8\xe9\xea\xeb\xec\xed\xee\xef"
+			  "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7"
+			  "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
+		.ilen	= 512,
+		.result	= "\xDE\x6F\x22\xA5\xE8\x39\xE8\x78"
+			  "\x88\x5A\x4F\x8D\x82\x76\x52\x6D"
+			  "\xB2\x41\x16\xF4\x2B\xA6\xEB\xF6"
+			  "\xE2\xC5\x62\x8D\x61\xA1\x01\xED"
+			  "\xD9\x38\x01\xC1\x43\x63\x4E\x88"
+			  "\xC9\x4B\x5A\x88\x80\xB7\x5C\x71"
+			  "\x47\xEE\x11\xD8\xB7\x2D\x5D\x13"
+			  "\x1A\xB1\x68\x5B\x61\xA7\xA9\x81"
+			  "\x8B\x83\xA1\x6A\xAA\x36\xD6\xB6"
+			  "\x60\x54\x09\x32\xFE\x6A\x76\x2E"
+			  "\x28\xFF\xD5\xD6\xDD\x1D\x45\x7D"
+			  "\xF0\x8B\xF3\x32\x4E\x6C\x12\xCB"
+			  "\xB8\x25\x70\xF8\x40\xBC\x90\x1B"
+			  "\x11\xC3\x59\xAF\xF0\x2F\x92\xDD"
+			  "\xD3\x3B\xCF\x60\xA1\x78\x94\x57"
+			  "\xAF\x76\xC1\x67\xA6\x3C\xCD\x98"
+			  "\xB1\xF7\x27\xB9\xA3\xBD\x10\xEA"
+			  "\xCD\x8B\xC2\xF2\x14\xF2\xB2\x67"
+			  "\x05\xDD\x1D\x58\x6E\x2F\x95\x08"
+			  "\x3A\xF8\x78\x76\x82\x56\xA7\xEC"
+			  "\x51\x4B\x85\x77\xC2\x4C\x4A\x34"
+			  "\x71\x38\x17\x91\x44\xE8\xFC\x65"
+			  "\x99\x0D\x52\x91\xEE\xF8\xEF\x27"
+			  "\x2A\x9E\x6E\x78\xC4\x26\x87\xF4"
+			  "\x8A\xF0\x2D\x04\xE8\x14\x92\x5D"
+			  "\x59\x22\x9B\x29\x5C\x18\xF0\xC3"
+			  "\x47\xF3\x76\xD8\xE4\xF3\x1B\xD1"
+			  "\x70\xA3\x0D\xB5\x70\x02\x1D\xA3"
+			  "\x91\x3B\x49\x73\x18\xAB\xD4\xC9"
+			  "\xC3\x1E\xEF\x1F\xFE\xD5\x59\x8A"
+			  "\xD7\xF6\xC9\x71\x67\x79\xD7\x0E"
+			  "\xBE\x1F\x8E\xEC\x55\x7E\x4F\x24"
+			  "\xE6\x87\xEA\xFE\x96\x25\x67\x8E"
+			  "\x93\x03\xFA\xFF\xCE\xAF\xB2\x3C"
+			  "\x6F\xEB\x57\xFB\xD3\x28\x87\xA9"
+			  "\xCE\xC2\xF5\x9C\xC6\x67\xB5\x97"
+			  "\x49\xF7\x04\xCB\xEF\x84\x98\x33"
+			  "\xAF\x38\xD3\x04\x1C\x24\x71\x38"
+			  "\xC7\x71\xDD\x43\x0D\x12\x4A\x18"
+			  "\xBA\xC4\xAF\xBA\xB2\x5B\xEB\x95"
+			  "\x02\x43\x5D\xCE\x19\xCC\xCD\x66"
+			  "\x91\x0B\x8C\x7F\x51\xC4\xBF\x3C"
+			  "\x8B\xF1\xCC\xAA\x29\xD7\x87\xCB"
+			  "\x3E\xC5\xF3\xC9\x75\xE8\xA3\x5B"
+			  "\x30\x45\xA9\xB7\xAF\x80\x64\x6F"
+			  "\x75\x4A\xA7\xC0\x6D\x19\x6B\xDE"
+			  "\x17\xDE\x6D\xEA\x87\x9F\x95\xAE"
+			  "\xF5\x3C\xEE\x54\xB8\x27\x84\xF8"
+			  "\x97\xA3\xE1\x6F\x38\x24\x34\x88"
+			  "\xCE\xBD\x32\x52\xE0\x00\x6C\x94"
+			  "\xC9\xD7\x5D\x37\x81\x33\x2E\x7F"
+			  "\x4F\x7E\x2E\x0D\x94\xBD\xEA\x59"
+			  "\x34\x39\xA8\x35\x12\xB7\xBC\xAC"
+			  "\xEA\x52\x9C\x78\x02\x6D\x92\x36"
+			  "\xFB\x59\x2B\xA4\xEA\x7B\x1B\x83"
+			  "\xE1\x4D\x5E\x2A\x7E\x92\xB1\x64"
+			  "\xDE\xE0\x27\x4B\x0A\x6F\x4C\xE3"
+			  "\xB0\xEB\x31\xE4\x69\x95\xAB\x35"
+			  "\x8B\x2C\xF5\x6B\x7F\xF1\xA2\x82"
+			  "\xF8\xD9\x47\x82\xA9\x82\x03\x91"
+			  "\x69\x1F\xBE\x4C\xE7\xC7\x34\x2F"
+			  "\x45\x72\x80\x17\x81\xBD\x9D\x62"
+			  "\xA1\xAC\xE8\xCF\xC6\x74\xCF\xDC"
+			  "\x22\x60\x4E\xE8\xA4\x5D\x85\xB9",
+		.rlen	= 512,
+	},
+};
+
+static struct cipher_testvec cast6_xts_dec_tv_template[] = {
+	{ /* Generated from TF test vectors */
+		.key	= "\x27\x18\x28\x18\x28\x45\x90\x45"
+			  "\x23\x53\x60\x28\x74\x71\x35\x26"
+			  "\x62\x49\x77\x57\x24\x70\x93\x69"
+			  "\x99\x59\x57\x49\x66\x96\x76\x27"
+			  "\x31\x41\x59\x26\x53\x58\x97\x93"
+			  "\x23\x84\x62\x64\x33\x83\x27\x95"
+			  "\x02\x88\x41\x97\x16\x93\x99\x37"
+			  "\x51\x05\x82\x09\x74\x94\x45\x92",
+		.klen	= 64,
+		.iv	= "\xff\x00\x00\x00\x00\x00\x00\x00"
+			  "\x00\x00\x00\x00\x00\x00\x00\x00",
+		.input	= "\xDE\x6F\x22\xA5\xE8\x39\xE8\x78"
+			  "\x88\x5A\x4F\x8D\x82\x76\x52\x6D"
+			  "\xB2\x41\x16\xF4\x2B\xA6\xEB\xF6"
+			  "\xE2\xC5\x62\x8D\x61\xA1\x01\xED"
+			  "\xD9\x38\x01\xC1\x43\x63\x4E\x88"
+			  "\xC9\x4B\x5A\x88\x80\xB7\x5C\x71"
+			  "\x47\xEE\x11\xD8\xB7\x2D\x5D\x13"
+			  "\x1A\xB1\x68\x5B\x61\xA7\xA9\x81"
+			  "\x8B\x83\xA1\x6A\xAA\x36\xD6\xB6"
+			  "\x60\x54\x09\x32\xFE\x6A\x76\x2E"
+			  "\x28\xFF\xD5\xD6\xDD\x1D\x45\x7D"
+			  "\xF0\x8B\xF3\x32\x4E\x6C\x12\xCB"
+			  "\xB8\x25\x70\xF8\x40\xBC\x90\x1B"
+			  "\x11\xC3\x59\xAF\xF0\x2F\x92\xDD"
+			  "\xD3\x3B\xCF\x60\xA1\x78\x94\x57"
+			  "\xAF\x76\xC1\x67\xA6\x3C\xCD\x98"
+			  "\xB1\xF7\x27\xB9\xA3\xBD\x10\xEA"
+			  "\xCD\x8B\xC2\xF2\x14\xF2\xB2\x67"
+			  "\x05\xDD\x1D\x58\x6E\x2F\x95\x08"
+			  "\x3A\xF8\x78\x76\x82\x56\xA7\xEC"
+			  "\x51\x4B\x85\x77\xC2\x4C\x4A\x34"
+			  "\x71\x38\x17\x91\x44\xE8\xFC\x65"
+			  "\x99\x0D\x52\x91\xEE\xF8\xEF\x27"
+			  "\x2A\x9E\x6E\x78\xC4\x26\x87\xF4"
+			  "\x8A\xF0\x2D\x04\xE8\x14\x92\x5D"
+			  "\x59\x22\x9B\x29\x5C\x18\xF0\xC3"
+			  "\x47\xF3\x76\xD8\xE4\xF3\x1B\xD1"
+			  "\x70\xA3\x0D\xB5\x70\x02\x1D\xA3"
+			  "\x91\x3B\x49\x73\x18\xAB\xD4\xC9"
+			  "\xC3\x1E\xEF\x1F\xFE\xD5\x59\x8A"
+			  "\xD7\xF6\xC9\x71\x67\x79\xD7\x0E"
+			  "\xBE\x1F\x8E\xEC\x55\x7E\x4F\x24"
+			  "\xE6\x87\xEA\xFE\x96\x25\x67\x8E"
+			  "\x93\x03\xFA\xFF\xCE\xAF\xB2\x3C"
+			  "\x6F\xEB\x57\xFB\xD3\x28\x87\xA9"
+			  "\xCE\xC2\xF5\x9C\xC6\x67\xB5\x97"
+			  "\x49\xF7\x04\xCB\xEF\x84\x98\x33"
+			  "\xAF\x38\xD3\x04\x1C\x24\x71\x38"
+			  "\xC7\x71\xDD\x43\x0D\x12\x4A\x18"
+			  "\xBA\xC4\xAF\xBA\xB2\x5B\xEB\x95"
+			  "\x02\x43\x5D\xCE\x19\xCC\xCD\x66"
+			  "\x91\x0B\x8C\x7F\x51\xC4\xBF\x3C"
+			  "\x8B\xF1\xCC\xAA\x29\xD7\x87\xCB"
+			  "\x3E\xC5\xF3\xC9\x75\xE8\xA3\x5B"
+			  "\x30\x45\xA9\xB7\xAF\x80\x64\x6F"
+			  "\x75\x4A\xA7\xC0\x6D\x19\x6B\xDE"
+			  "\x17\xDE\x6D\xEA\x87\x9F\x95\xAE"
+			  "\xF5\x3C\xEE\x54\xB8\x27\x84\xF8"
+			  "\x97\xA3\xE1\x6F\x38\x24\x34\x88"
+			  "\xCE\xBD\x32\x52\xE0\x00\x6C\x94"
+			  "\xC9\xD7\x5D\x37\x81\x33\x2E\x7F"
+			  "\x4F\x7E\x2E\x0D\x94\xBD\xEA\x59"
+			  "\x34\x39\xA8\x35\x12\xB7\xBC\xAC"
+			  "\xEA\x52\x9C\x78\x02\x6D\x92\x36"
+			  "\xFB\x59\x2B\xA4\xEA\x7B\x1B\x83"
+			  "\xE1\x4D\x5E\x2A\x7E\x92\xB1\x64"
+			  "\xDE\xE0\x27\x4B\x0A\x6F\x4C\xE3"
+			  "\xB0\xEB\x31\xE4\x69\x95\xAB\x35"
+			  "\x8B\x2C\xF5\x6B\x7F\xF1\xA2\x82"
+			  "\xF8\xD9\x47\x82\xA9\x82\x03\x91"
+			  "\x69\x1F\xBE\x4C\xE7\xC7\x34\x2F"
+			  "\x45\x72\x80\x17\x81\xBD\x9D\x62"
+			  "\xA1\xAC\xE8\xCF\xC6\x74\xCF\xDC"
+			  "\x22\x60\x4E\xE8\xA4\x5D\x85\xB9",
+		.ilen	= 512,
+		.result	= "\x00\x01\x02\x03\x04\x05\x06\x07"
+			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+			  "\x10\x11\x12\x13\x14\x15\x16\x17"
+			  "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
+			  "\x20\x21\x22\x23\x24\x25\x26\x27"
+			  "\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f"
+			  "\x30\x31\x32\x33\x34\x35\x36\x37"
+			  "\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f"
+			  "\x40\x41\x42\x43\x44\x45\x46\x47"
+			  "\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f"
+			  "\x50\x51\x52\x53\x54\x55\x56\x57"
+			  "\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f"
+			  "\x60\x61\x62\x63\x64\x65\x66\x67"
+			  "\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f"
+			  "\x70\x71\x72\x73\x74\x75\x76\x77"
+			  "\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f"
+			  "\x80\x81\x82\x83\x84\x85\x86\x87"
+			  "\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f"
+			  "\x90\x91\x92\x93\x94\x95\x96\x97"
+			  "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f"
+			  "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7"
+			  "\xa8\xa9\xaa\xab\xac\xad\xae\xaf"
+			  "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7"
+			  "\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf"
+			  "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7"
+			  "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf"
+			  "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7"
+			  "\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf"
+			  "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7"
+			  "\xe8\xe9\xea\xeb\xec\xed\xee\xef"
+			  "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7"
+			  "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"
+			  "\x00\x01\x02\x03\x04\x05\x06\x07"
+			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+			  "\x10\x11\x12\x13\x14\x15\x16\x17"
+			  "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
+			  "\x20\x21\x22\x23\x24\x25\x26\x27"
+			  "\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f"
+			  "\x30\x31\x32\x33\x34\x35\x36\x37"
+			  "\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f"
+			  "\x40\x41\x42\x43\x44\x45\x46\x47"
+			  "\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f"
+			  "\x50\x51\x52\x53\x54\x55\x56\x57"
+			  "\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f"
+			  "\x60\x61\x62\x63\x64\x65\x66\x67"
+			  "\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f"
+			  "\x70\x71\x72\x73\x74\x75\x76\x77"
+			  "\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f"
+			  "\x80\x81\x82\x83\x84\x85\x86\x87"
+			  "\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f"
+			  "\x90\x91\x92\x93\x94\x95\x96\x97"
+			  "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f"
+			  "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7"
+			  "\xa8\xa9\xaa\xab\xac\xad\xae\xaf"
+			  "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7"
+			  "\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf"
+			  "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7"
+			  "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf"
+			  "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7"
+			  "\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf"
+			  "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7"
+			  "\xe8\xe9\xea\xeb\xec\xed\xee\xef"
+			  "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7"
+			  "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
+		.rlen	= 512,
+	},
+};
+
+
+/*
+ * AES test vectors.
+ */
+#define AES_ENC_TEST_VECTORS 3
+#define AES_DEC_TEST_VECTORS 3
+#define AES_CBC_ENC_TEST_VECTORS 4
+#define AES_CBC_DEC_TEST_VECTORS 4
+#define HMAC_SHA1_AES_CBC_ENC_TEST_VECTORS 7
+#define HMAC_SHA256_AES_CBC_ENC_TEST_VECTORS 7
+#define HMAC_SHA512_AES_CBC_ENC_TEST_VECTORS 7
+#define AES_LRW_ENC_TEST_VECTORS 8
+#define AES_LRW_DEC_TEST_VECTORS 8
+#define AES_XTS_ENC_TEST_VECTORS 5
+#define AES_XTS_DEC_TEST_VECTORS 5
+#define AES_CTR_ENC_TEST_VECTORS 3
+#define AES_CTR_DEC_TEST_VECTORS 3
+#define AES_OFB_ENC_TEST_VECTORS 1
+#define AES_OFB_DEC_TEST_VECTORS 1
+#define AES_CTR_3686_ENC_TEST_VECTORS 7
+#define AES_CTR_3686_DEC_TEST_VECTORS 6
+#define AES_GCM_ENC_TEST_VECTORS 9
+#define AES_GCM_DEC_TEST_VECTORS 8
+#define AES_GCM_4106_ENC_TEST_VECTORS 7
+#define AES_GCM_4106_DEC_TEST_VECTORS 7
+#define AES_CCM_ENC_TEST_VECTORS 7
+#define AES_CCM_DEC_TEST_VECTORS 7
+#define AES_CCM_4309_ENC_TEST_VECTORS 7
+#define AES_CCM_4309_DEC_TEST_VECTORS 10
+
+static struct cipher_testvec aes_enc_tv_template[] = {
+	{ /* From FIPS-197 */
+		.key	= "\x00\x01\x02\x03\x04\x05\x06\x07"
+			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+		.klen	= 16,
+		.input	= "\x00\x11\x22\x33\x44\x55\x66\x77"
+			  "\x88\x99\xaa\xbb\xcc\xdd\xee\xff",
+		.ilen	= 16,
+		.result	= "\x69\xc4\xe0\xd8\x6a\x7b\x04\x30"
+			  "\xd8\xcd\xb7\x80\x70\xb4\xc5\x5a",
+		.rlen	= 16,
+	}, {
+		.key	= "\x00\x01\x02\x03\x04\x05\x06\x07"
+			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+			  "\x10\x11\x12\x13\x14\x15\x16\x17",
+		.klen	= 24,
+		.input	= "\x00\x11\x22\x33\x44\x55\x66\x77"
+			  "\x88\x99\xaa\xbb\xcc\xdd\xee\xff",
+		.ilen	= 16,
+		.result	= "\xdd\xa9\x7c\xa4\x86\x4c\xdf\xe0"
+			  "\x6e\xaf\x70\xa0\xec\x0d\x71\x91",
+		.rlen	= 16,
+	}, {
+		.key	= "\x00\x01\x02\x03\x04\x05\x06\x07"
+			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+			  "\x10\x11\x12\x13\x14\x15\x16\x17"
+			  "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
+		.klen	= 32,
+		.input	= "\x00\x11\x22\x33\x44\x55\x66\x77"
+			  "\x88\x99\xaa\xbb\xcc\xdd\xee\xff",
+		.ilen	= 16,
+		.result	= "\x8e\xa2\xb7\xca\x51\x67\x45\xbf"
+			  "\xea\xfc\x49\x90\x4b\x49\x60\x89",
+		.rlen	= 16,
+	},
+};
+
+static struct cipher_testvec aes_dec_tv_template[] = {
+	{ /* From FIPS-197 */
+		.key	= "\x00\x01\x02\x03\x04\x05\x06\x07"
+			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+		.klen	= 16,
+		.input	= "\x69\xc4\xe0\xd8\x6a\x7b\x04\x30"
+			  "\xd8\xcd\xb7\x80\x70\xb4\xc5\x5a",
+		.ilen	= 16,
+		.result	= "\x00\x11\x22\x33\x44\x55\x66\x77"
+			  "\x88\x99\xaa\xbb\xcc\xdd\xee\xff",
+		.rlen	= 16,
+	}, {
+		.key	= "\x00\x01\x02\x03\x04\x05\x06\x07"
+			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+			  "\x10\x11\x12\x13\x14\x15\x16\x17",
+		.klen	= 24,
+		.input	= "\xdd\xa9\x7c\xa4\x86\x4c\xdf\xe0"
+			  "\x6e\xaf\x70\xa0\xec\x0d\x71\x91",
+		.ilen	= 16,
+		.result	= "\x00\x11\x22\x33\x44\x55\x66\x77"
+			  "\x88\x99\xaa\xbb\xcc\xdd\xee\xff",
+		.rlen	= 16,
+	}, {
+		.key	= "\x00\x01\x02\x03\x04\x05\x06\x07"
+			  "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+			  "\x10\x11\x12\x13\x14\x15\x16\x17"
+			  "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
+		.klen	= 32,
+		.input	= "\x8e\xa2\xb7\xca\x51\x67\x45\xbf"
+			  "\xea\xfc\x49\x90\x4b\x49\x60\x89",
+		.ilen	= 16,
+		.result	= "\x00\x11\x22\x33\x44\x55\x66\x77"
+			  "\x88\x99\xaa\xbb\xcc\xdd\xee\xff",
+		.rlen	= 16,
+	},
+};
+
+static struct cipher_testvec aes_cbc_enc_tv_template[] = {
+	{ /* From RFC 3602 */
+		.key    = "\x06\xa9\x21\x40\x36\xb8\xa1\x5b"
+			  "\x51\x2e\x03\xd5\x34\x12\x00\x06",
+		.klen   = 16,
+		.iv	= "\x3d\xaf\xba\x42\x9d\x9e\xb4\x30"
+			  "\xb4\x22\xda\x80\x2c\x9f\xac\x41",
+		.input	= "Single block msg",
+		.ilen   = 16,
 		.result = "\xe3\x53\x77\x9c\x10\x79\xae\xb8"
 			  "\x27\x08\x94\x2d\xbe\x77\x18\x1a",
 		.rlen   = 16,
@@ -12124,61 +13532,867 @@ static struct cprng_testvec ansi_cprng_aes_tv_template[] = {
 	},
 };
 
-/* Cast5 test vectors from RFC 2144 */
-#define CAST5_ENC_TEST_VECTORS	3
-#define CAST5_DEC_TEST_VECTORS	3
+/* Cast5 test vectors from RFC 2144 */
+#define CAST5_ENC_TEST_VECTORS		4
+#define CAST5_DEC_TEST_VECTORS		4
+#define CAST5_CBC_ENC_TEST_VECTORS	1
+#define CAST5_CBC_DEC_TEST_VECTORS	1
+#define CAST5_CTR_ENC_TEST_VECTORS	1
+#define CAST5_CTR_DEC_TEST_VECTORS	1
+
+static struct cipher_testvec cast5_enc_tv_template[] = {
+	{
+		.key	= "\x01\x23\x45\x67\x12\x34\x56\x78"
+			  "\x23\x45\x67\x89\x34\x56\x78\x9a",
+		.klen	= 16,
+		.input	= "\x01\x23\x45\x67\x89\xab\xcd\xef",
+		.ilen	= 8,
+		.result	= "\x23\x8b\x4f\xe5\x84\x7e\x44\xb2",
+		.rlen	= 8,
+	}, {
+		.key	= "\x01\x23\x45\x67\x12\x34\x56\x78"
+			  "\x23\x45",
+		.klen	= 10,
+		.input	= "\x01\x23\x45\x67\x89\xab\xcd\xef",
+		.ilen	= 8,
+		.result	= "\xeb\x6a\x71\x1a\x2c\x02\x27\x1b",
+		.rlen	= 8,
+	}, {
+		.key	= "\x01\x23\x45\x67\x12",
+		.klen	= 5,
+		.input	= "\x01\x23\x45\x67\x89\xab\xcd\xef",
+		.ilen	= 8,
+		.result	= "\x7a\xc8\x16\xd1\x6e\x9b\x30\x2e",
+		.rlen	= 8,
+	}, { /* Generated from TF test vectors */
+		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A",
+		.klen	= 16,
+		.iv	= "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F",
+		.input	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+			  "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+			  "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+			  "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+			  "\xC3\x37\xCE\x65\xFC\x70\x07\x9E"
+			  "\x12\xA9\x40\xD7\x4B\xE2\x79\x10"
+			  "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F"
+			  "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1"
+			  "\x68\xFF\x73\x0A\xA1\x15\xAC\x43"
+			  "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5"
+			  "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
+			  "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
+			  "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
+			  "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+			  "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+			  "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+			  "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+			  "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+			  "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+			  "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+			  "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+			  "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+			  "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+			  "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+			  "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+			  "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+			  "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+			  "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+			  "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+			  "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+			  "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+			  "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+			  "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+			  "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+			  "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+			  "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+			  "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+			  "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+			  "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+			  "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+			  "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+			  "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+			  "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+			  "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+			  "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+			  "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+			  "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+			  "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+			  "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+			  "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+			  "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+			  "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+			  "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+			  "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+			  "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+			  "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+			  "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+			  "\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
+		.ilen	= 496,
+		.result	= "\x8D\xFC\x81\x9C\xCB\xAA\x5A\x1C"
+			  "\x7E\x95\xCF\x40\xAB\x4D\x6F\xEA"
+			  "\xD3\xD9\xB0\x9A\xB7\xC7\xE0\x2E"
+			  "\xD1\x39\x34\x92\x8F\xFA\x14\xF1"
+			  "\xD5\xD2\x7B\x59\x1F\x35\x28\xC2"
+			  "\x20\xD9\x42\x06\xC9\x0B\x10\x04"
+			  "\xF8\x79\xCD\x32\x86\x75\x4C\xB6"
+			  "\x7B\x1C\x52\xB1\x91\x64\x22\x4B"
+			  "\x13\xC7\xAE\x98\x0E\xB5\xCF\x6F"
+			  "\x3F\xF4\x43\x96\x73\x0D\xA2\x05"
+			  "\xDB\xFD\x28\x90\x2C\x56\xB9\x37"
+			  "\x5B\x69\x0C\xAD\x84\x67\xFF\x15"
+			  "\x4A\xD4\xA7\xD3\xDD\x99\x47\x3A"
+			  "\xED\x34\x35\x78\x6B\x91\xC9\x32"
+			  "\xE1\xBF\xBC\xB4\x04\x85\x6A\x39"
+			  "\xC0\xBA\x51\xD0\x0F\x4E\xD1\xE2"
+			  "\x1C\xFD\x0E\x05\x07\xF4\x10\xED"
+			  "\xA2\x17\xFF\xF5\x64\xC6\x1A\x22"
+			  "\xAD\x78\xE7\xD7\x11\xE9\x99\xB9"
+			  "\xAA\xEC\x6F\xF8\x3B\xBF\xCE\x77"
+			  "\x93\xE8\xAD\x1D\x50\x6C\xAE\xBC"
+			  "\xBA\x5C\x80\xD1\x91\x65\x51\x1B"
+			  "\xE8\x0A\xCD\x99\x96\x71\x3D\xB6"
+			  "\x78\x75\x37\x55\xC1\xF5\x90\x40"
+			  "\x34\xF4\x7E\xC8\xCC\x3A\x5F\x6E"
+			  "\x36\xA1\xA1\xC2\x3A\x72\x42\x8E"
+			  "\x0E\x37\x88\xE8\xCE\x83\xCB\xAD"
+			  "\xE0\x69\x77\x50\xC7\x0C\x99\xCA"
+			  "\x19\x5B\x30\x25\x9A\xEF\x9B\x0C"
+			  "\xEF\x8F\x74\x4C\xCF\x49\x4E\xB9"
+			  "\xC5\xAE\x9E\x2E\x78\x9A\xB9\x48"
+			  "\xD5\x81\xE4\x37\x1D\xBF\x27\xD9"
+			  "\xC5\xD6\x65\x43\x45\x8C\xBB\xB6"
+			  "\x55\xF4\x06\xBB\x49\x53\x8B\x1B"
+			  "\x07\xA9\x96\x69\x5B\xCB\x0F\xBC"
+			  "\x93\x85\x90\x0F\x0A\x68\x40\x2A"
+			  "\x95\xED\x2D\x88\xBF\x71\xD0\xBB"
+			  "\xEC\xB0\x77\x6C\x79\xFC\x3C\x05"
+			  "\x49\x3F\xB8\x24\xEF\x8E\x09\xA2"
+			  "\x1D\xEF\x92\x02\x96\xD4\x7F\xC8"
+			  "\x03\xB2\xCA\xDB\x17\x5C\x52\xCF"
+			  "\xDD\x70\x37\x63\xAA\xA5\x83\x20"
+			  "\x52\x02\xF6\xB9\xE7\x6E\x0A\xB6"
+			  "\x79\x03\xA0\xDA\xA3\x79\x21\xBD"
+			  "\xE3\x37\x3A\xC0\xF7\x2C\x32\xBE"
+			  "\x8B\xE8\xA6\x00\xC7\x32\xD5\x06"
+			  "\xBB\xE3\xAB\x06\x21\x82\xB8\x32"
+			  "\x31\x34\x2A\xA7\x1F\x64\x99\xBF"
+			  "\xFA\xDA\x3D\x75\xF7\x48\xD5\x48"
+			  "\x4B\x52\x7E\xF6\x7C\xAB\x67\x59"
+			  "\xC5\xDC\xA8\xC6\x63\x85\x4A\xDF"
+			  "\xF0\x40\x5F\xCF\xE3\x58\x52\x67"
+			  "\x7A\x24\x32\xC5\xEC\x9E\xA9\x6F"
+			  "\x58\x56\xDD\x94\x1F\x71\x8D\xF4"
+			  "\x6E\xFF\x2C\xA7\xA5\xD8\xBA\xAF"
+			  "\x1D\x8B\xA2\x46\xB5\xC4\x9F\x57"
+			  "\x8D\xD8\xB3\x3C\x02\x0D\xBB\x84"
+			  "\xC7\xBD\xB4\x9A\x6E\xBB\xB1\x37"
+			  "\x95\x79\xC4\xA7\xEA\x1D\xDC\x33"
+			  "\x5D\x0B\x3F\x03\x8F\x30\xF9\xAE"
+			  "\x4F\xFE\x24\x9C\x9A\x02\xE5\x57"
+			  "\xF5\xBC\x25\xD6\x02\x56\x57\x1C",
+		.rlen	= 496,
+	},
+};
+
+static struct cipher_testvec cast5_dec_tv_template[] = {
+	{
+		.key	= "\x01\x23\x45\x67\x12\x34\x56\x78"
+			  "\x23\x45\x67\x89\x34\x56\x78\x9a",
+		.klen	= 16,
+		.input	= "\x23\x8b\x4f\xe5\x84\x7e\x44\xb2",
+		.ilen	= 8,
+		.result	= "\x01\x23\x45\x67\x89\xab\xcd\xef",
+		.rlen	= 8,
+	}, {
+		.key	= "\x01\x23\x45\x67\x12\x34\x56\x78"
+			  "\x23\x45",
+		.klen	= 10,
+		.input	= "\xeb\x6a\x71\x1a\x2c\x02\x27\x1b",
+		.ilen	= 8,
+		.result	= "\x01\x23\x45\x67\x89\xab\xcd\xef",
+		.rlen	= 8,
+	}, {
+		.key	= "\x01\x23\x45\x67\x12",
+		.klen	= 5,
+		.input	= "\x7a\xc8\x16\xd1\x6e\x9b\x30\x2e",
+		.ilen	= 8,
+		.result	= "\x01\x23\x45\x67\x89\xab\xcd\xef",
+		.rlen	= 8,
+	}, { /* Generated from TF test vectors */
+		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A",
+		.klen	= 16,
+		.iv	= "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F",
+		.input	= "\x8D\xFC\x81\x9C\xCB\xAA\x5A\x1C"
+			  "\x7E\x95\xCF\x40\xAB\x4D\x6F\xEA"
+			  "\xD3\xD9\xB0\x9A\xB7\xC7\xE0\x2E"
+			  "\xD1\x39\x34\x92\x8F\xFA\x14\xF1"
+			  "\xD5\xD2\x7B\x59\x1F\x35\x28\xC2"
+			  "\x20\xD9\x42\x06\xC9\x0B\x10\x04"
+			  "\xF8\x79\xCD\x32\x86\x75\x4C\xB6"
+			  "\x7B\x1C\x52\xB1\x91\x64\x22\x4B"
+			  "\x13\xC7\xAE\x98\x0E\xB5\xCF\x6F"
+			  "\x3F\xF4\x43\x96\x73\x0D\xA2\x05"
+			  "\xDB\xFD\x28\x90\x2C\x56\xB9\x37"
+			  "\x5B\x69\x0C\xAD\x84\x67\xFF\x15"
+			  "\x4A\xD4\xA7\xD3\xDD\x99\x47\x3A"
+			  "\xED\x34\x35\x78\x6B\x91\xC9\x32"
+			  "\xE1\xBF\xBC\xB4\x04\x85\x6A\x39"
+			  "\xC0\xBA\x51\xD0\x0F\x4E\xD1\xE2"
+			  "\x1C\xFD\x0E\x05\x07\xF4\x10\xED"
+			  "\xA2\x17\xFF\xF5\x64\xC6\x1A\x22"
+			  "\xAD\x78\xE7\xD7\x11\xE9\x99\xB9"
+			  "\xAA\xEC\x6F\xF8\x3B\xBF\xCE\x77"
+			  "\x93\xE8\xAD\x1D\x50\x6C\xAE\xBC"
+			  "\xBA\x5C\x80\xD1\x91\x65\x51\x1B"
+			  "\xE8\x0A\xCD\x99\x96\x71\x3D\xB6"
+			  "\x78\x75\x37\x55\xC1\xF5\x90\x40"
+			  "\x34\xF4\x7E\xC8\xCC\x3A\x5F\x6E"
+			  "\x36\xA1\xA1\xC2\x3A\x72\x42\x8E"
+			  "\x0E\x37\x88\xE8\xCE\x83\xCB\xAD"
+			  "\xE0\x69\x77\x50\xC7\x0C\x99\xCA"
+			  "\x19\x5B\x30\x25\x9A\xEF\x9B\x0C"
+			  "\xEF\x8F\x74\x4C\xCF\x49\x4E\xB9"
+			  "\xC5\xAE\x9E\x2E\x78\x9A\xB9\x48"
+			  "\xD5\x81\xE4\x37\x1D\xBF\x27\xD9"
+			  "\xC5\xD6\x65\x43\x45\x8C\xBB\xB6"
+			  "\x55\xF4\x06\xBB\x49\x53\x8B\x1B"
+			  "\x07\xA9\x96\x69\x5B\xCB\x0F\xBC"
+			  "\x93\x85\x90\x0F\x0A\x68\x40\x2A"
+			  "\x95\xED\x2D\x88\xBF\x71\xD0\xBB"
+			  "\xEC\xB0\x77\x6C\x79\xFC\x3C\x05"
+			  "\x49\x3F\xB8\x24\xEF\x8E\x09\xA2"
+			  "\x1D\xEF\x92\x02\x96\xD4\x7F\xC8"
+			  "\x03\xB2\xCA\xDB\x17\x5C\x52\xCF"
+			  "\xDD\x70\x37\x63\xAA\xA5\x83\x20"
+			  "\x52\x02\xF6\xB9\xE7\x6E\x0A\xB6"
+			  "\x79\x03\xA0\xDA\xA3\x79\x21\xBD"
+			  "\xE3\x37\x3A\xC0\xF7\x2C\x32\xBE"
+			  "\x8B\xE8\xA6\x00\xC7\x32\xD5\x06"
+			  "\xBB\xE3\xAB\x06\x21\x82\xB8\x32"
+			  "\x31\x34\x2A\xA7\x1F\x64\x99\xBF"
+			  "\xFA\xDA\x3D\x75\xF7\x48\xD5\x48"
+			  "\x4B\x52\x7E\xF6\x7C\xAB\x67\x59"
+			  "\xC5\xDC\xA8\xC6\x63\x85\x4A\xDF"
+			  "\xF0\x40\x5F\xCF\xE3\x58\x52\x67"
+			  "\x7A\x24\x32\xC5\xEC\x9E\xA9\x6F"
+			  "\x58\x56\xDD\x94\x1F\x71\x8D\xF4"
+			  "\x6E\xFF\x2C\xA7\xA5\xD8\xBA\xAF"
+			  "\x1D\x8B\xA2\x46\xB5\xC4\x9F\x57"
+			  "\x8D\xD8\xB3\x3C\x02\x0D\xBB\x84"
+			  "\xC7\xBD\xB4\x9A\x6E\xBB\xB1\x37"
+			  "\x95\x79\xC4\xA7\xEA\x1D\xDC\x33"
+			  "\x5D\x0B\x3F\x03\x8F\x30\xF9\xAE"
+			  "\x4F\xFE\x24\x9C\x9A\x02\xE5\x57"
+			  "\xF5\xBC\x25\xD6\x02\x56\x57\x1C",
+		.ilen	= 496,
+		.result	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+			  "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+			  "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+			  "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+			  "\xC3\x37\xCE\x65\xFC\x70\x07\x9E"
+			  "\x12\xA9\x40\xD7\x4B\xE2\x79\x10"
+			  "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F"
+			  "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1"
+			  "\x68\xFF\x73\x0A\xA1\x15\xAC\x43"
+			  "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5"
+			  "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
+			  "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
+			  "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
+			  "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+			  "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+			  "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+			  "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+			  "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+			  "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+			  "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+			  "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+			  "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+			  "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+			  "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+			  "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+			  "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+			  "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+			  "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+			  "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+			  "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+			  "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+			  "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+			  "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+			  "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+			  "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+			  "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+			  "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+			  "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+			  "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+			  "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+			  "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+			  "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+			  "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+			  "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+			  "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+			  "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+			  "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+			  "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+			  "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+			  "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+			  "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+			  "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+			  "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+			  "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+			  "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+			  "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+			  "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+			  "\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
+		.rlen	= 496,
+	},
+};
+
+static struct cipher_testvec cast5_cbc_enc_tv_template[] = {
+	{ /* Generated from TF test vectors */
+		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A",
+		.klen	= 16,
+		.iv	= "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F",
+		.input	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+			  "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+			  "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+			  "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+			  "\xC3\x37\xCE\x65\xFC\x70\x07\x9E"
+			  "\x12\xA9\x40\xD7\x4B\xE2\x79\x10"
+			  "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F"
+			  "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1"
+			  "\x68\xFF\x73\x0A\xA1\x15\xAC\x43"
+			  "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5"
+			  "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
+			  "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
+			  "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
+			  "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+			  "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+			  "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+			  "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+			  "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+			  "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+			  "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+			  "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+			  "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+			  "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+			  "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+			  "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+			  "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+			  "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+			  "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+			  "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+			  "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+			  "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+			  "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+			  "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+			  "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+			  "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+			  "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+			  "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+			  "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+			  "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+			  "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+			  "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+			  "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+			  "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+			  "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+			  "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+			  "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+			  "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+			  "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+			  "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+			  "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+			  "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+			  "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+			  "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+			  "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+			  "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+			  "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+			  "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+			  "\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
+		.ilen	= 496,
+		.result	= "\x05\x28\xCE\x61\x90\x80\xE1\x78"
+			  "\xB9\x2A\x97\x7C\xB0\x83\xD8\x1A"
+			  "\xDE\x58\x7F\xD7\xFD\x72\xB8\xFB"
+			  "\xDA\xF0\x6E\x77\x14\x47\x82\xBA"
+			  "\x29\x0E\x25\x6E\xB4\x39\xD9\x7F"
+			  "\x05\xA7\xA7\x3A\xC1\x5D\x9E\x39"
+			  "\xA7\xFB\x0D\x05\x00\xF3\x58\x67"
+			  "\x60\xEC\x73\x77\x46\x85\x9B\x6A"
+			  "\x08\x3E\xBE\x59\xFB\xE4\x96\x34"
+			  "\xB4\x05\x49\x1A\x97\x43\xAD\xA0"
+			  "\xA9\x1E\x6E\x74\xF1\x94\xEC\xA8"
+			  "\xB5\x8A\x20\xEA\x89\x6B\x19\xAA"
+			  "\xA7\xF1\x33\x67\x90\x23\x0D\xEE"
+			  "\x81\xD5\x78\x4F\xD3\x63\xEA\x46"
+			  "\xB5\xB2\x6E\xBB\xCA\x76\x06\x10"
+			  "\x96\x2A\x0A\xBA\xF9\x41\x5A\x1D"
+			  "\x36\x7C\x56\x14\x54\x83\xFA\xA1"
+			  "\x27\xDD\xBA\x8A\x90\x29\xD6\xA6"
+			  "\xFA\x48\x3E\x1E\x23\x6E\x98\xA8"
+			  "\xA7\xD9\x67\x92\x5C\x13\xB4\x71"
+			  "\xA8\xAA\x89\x4A\xA4\xB3\x49\x7C"
+			  "\x7D\x7F\xCE\x6F\x29\x2E\x7E\x37"
+			  "\xC8\x52\x60\xD9\xE7\xCA\x60\x98"
+			  "\xED\xCD\xE8\x60\x83\xAD\x34\x4D"
+			  "\x96\x4A\x99\x2B\xB7\x14\x75\x66"
+			  "\x6C\x2C\x1A\xBA\x4B\xBB\x49\x56"
+			  "\xE1\x86\xA2\x0E\xD0\xF0\x07\xD3"
+			  "\x18\x38\x09\x9C\x0E\x8B\x86\x07"
+			  "\x90\x12\x37\x49\x27\x98\x69\x18"
+			  "\xB0\xCC\xFB\xD3\xBD\x04\xA0\x85"
+			  "\x4B\x22\x97\x07\xB6\x97\xE9\x95"
+			  "\x0F\x88\x36\xA9\x44\x00\xC6\xE9"
+			  "\x27\x53\x5C\x5B\x1F\xD3\xE2\xEE"
+			  "\xD0\xCD\x63\x30\xA9\xC0\xDD\x49"
+			  "\xFE\x16\xA4\x07\x0D\xE2\x5D\x97"
+			  "\xDE\x89\xBA\x2E\xF3\xA9\x5E\xBE"
+			  "\x03\x55\x0E\x02\x41\x4A\x45\x06"
+			  "\xBE\xEA\x32\xF2\xDC\x91\x5C\x20"
+			  "\x94\x02\x30\xD2\xFC\x29\xFA\x8E"
+			  "\x34\xA0\x31\xB8\x34\xBA\xAE\x54"
+			  "\xB5\x88\x1F\xDC\x43\xDC\x22\x9F"
+			  "\xDC\xCE\xD3\xFA\xA4\xA8\xBC\x8A"
+			  "\xC7\x5A\x43\x21\xA5\xB1\xDB\xC3"
+			  "\x84\x3B\xB4\x9B\xB5\xA7\xF1\x0A"
+			  "\xB6\x37\x21\x19\x55\xC2\xBD\x99"
+			  "\x49\x24\xBB\x7C\xB3\x8E\xEF\xD2"
+			  "\x3A\xCF\xA0\x31\x28\x0E\x25\xA2"
+			  "\x11\xB4\x18\x17\x1A\x65\x92\x56"
+			  "\xE8\xE0\x52\x9C\x61\x18\x2A\xB1"
+			  "\x1A\x01\x22\x45\x17\x62\x52\x6C"
+			  "\x91\x44\xCF\x98\xC7\xC0\x79\x26"
+			  "\x32\x66\x6F\x23\x7F\x94\x36\x88"
+			  "\x3C\xC9\xD0\xB7\x45\x30\x31\x86"
+			  "\x3D\xC6\xA3\x98\x62\x84\x1A\x8B"
+			  "\x16\x88\xC7\xA3\xE9\x4F\xE0\x86"
+			  "\xA4\x93\xA8\x34\x5A\xCA\xDF\xCA"
+			  "\x46\x38\xD2\xF4\xE0\x2D\x1E\xC9"
+			  "\x7C\xEF\x53\xB7\x60\x72\x41\xBF"
+			  "\x29\x00\x87\x02\xAF\x44\x4C\xB7"
+			  "\x8C\xF5\x3F\x19\xF4\x80\x45\xA7"
+			  "\x15\x5F\xDB\xE9\xB1\x83\xD2\xE6"
+			  "\x1D\x18\x66\x44\x5B\x8F\x14\xEB",
+		.rlen	= 496,
+	},
+};
+
+static struct cipher_testvec cast5_cbc_dec_tv_template[] = {
+	{ /* Generated from TF test vectors */
+		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A",
+		.klen	= 16,
+		.iv	= "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F",
+		.input	= "\x05\x28\xCE\x61\x90\x80\xE1\x78"
+			  "\xB9\x2A\x97\x7C\xB0\x83\xD8\x1A"
+			  "\xDE\x58\x7F\xD7\xFD\x72\xB8\xFB"
+			  "\xDA\xF0\x6E\x77\x14\x47\x82\xBA"
+			  "\x29\x0E\x25\x6E\xB4\x39\xD9\x7F"
+			  "\x05\xA7\xA7\x3A\xC1\x5D\x9E\x39"
+			  "\xA7\xFB\x0D\x05\x00\xF3\x58\x67"
+			  "\x60\xEC\x73\x77\x46\x85\x9B\x6A"
+			  "\x08\x3E\xBE\x59\xFB\xE4\x96\x34"
+			  "\xB4\x05\x49\x1A\x97\x43\xAD\xA0"
+			  "\xA9\x1E\x6E\x74\xF1\x94\xEC\xA8"
+			  "\xB5\x8A\x20\xEA\x89\x6B\x19\xAA"
+			  "\xA7\xF1\x33\x67\x90\x23\x0D\xEE"
+			  "\x81\xD5\x78\x4F\xD3\x63\xEA\x46"
+			  "\xB5\xB2\x6E\xBB\xCA\x76\x06\x10"
+			  "\x96\x2A\x0A\xBA\xF9\x41\x5A\x1D"
+			  "\x36\x7C\x56\x14\x54\x83\xFA\xA1"
+			  "\x27\xDD\xBA\x8A\x90\x29\xD6\xA6"
+			  "\xFA\x48\x3E\x1E\x23\x6E\x98\xA8"
+			  "\xA7\xD9\x67\x92\x5C\x13\xB4\x71"
+			  "\xA8\xAA\x89\x4A\xA4\xB3\x49\x7C"
+			  "\x7D\x7F\xCE\x6F\x29\x2E\x7E\x37"
+			  "\xC8\x52\x60\xD9\xE7\xCA\x60\x98"
+			  "\xED\xCD\xE8\x60\x83\xAD\x34\x4D"
+			  "\x96\x4A\x99\x2B\xB7\x14\x75\x66"
+			  "\x6C\x2C\x1A\xBA\x4B\xBB\x49\x56"
+			  "\xE1\x86\xA2\x0E\xD0\xF0\x07\xD3"
+			  "\x18\x38\x09\x9C\x0E\x8B\x86\x07"
+			  "\x90\x12\x37\x49\x27\x98\x69\x18"
+			  "\xB0\xCC\xFB\xD3\xBD\x04\xA0\x85"
+			  "\x4B\x22\x97\x07\xB6\x97\xE9\x95"
+			  "\x0F\x88\x36\xA9\x44\x00\xC6\xE9"
+			  "\x27\x53\x5C\x5B\x1F\xD3\xE2\xEE"
+			  "\xD0\xCD\x63\x30\xA9\xC0\xDD\x49"
+			  "\xFE\x16\xA4\x07\x0D\xE2\x5D\x97"
+			  "\xDE\x89\xBA\x2E\xF3\xA9\x5E\xBE"
+			  "\x03\x55\x0E\x02\x41\x4A\x45\x06"
+			  "\xBE\xEA\x32\xF2\xDC\x91\x5C\x20"
+			  "\x94\x02\x30\xD2\xFC\x29\xFA\x8E"
+			  "\x34\xA0\x31\xB8\x34\xBA\xAE\x54"
+			  "\xB5\x88\x1F\xDC\x43\xDC\x22\x9F"
+			  "\xDC\xCE\xD3\xFA\xA4\xA8\xBC\x8A"
+			  "\xC7\x5A\x43\x21\xA5\xB1\xDB\xC3"
+			  "\x84\x3B\xB4\x9B\xB5\xA7\xF1\x0A"
+			  "\xB6\x37\x21\x19\x55\xC2\xBD\x99"
+			  "\x49\x24\xBB\x7C\xB3\x8E\xEF\xD2"
+			  "\x3A\xCF\xA0\x31\x28\x0E\x25\xA2"
+			  "\x11\xB4\x18\x17\x1A\x65\x92\x56"
+			  "\xE8\xE0\x52\x9C\x61\x18\x2A\xB1"
+			  "\x1A\x01\x22\x45\x17\x62\x52\x6C"
+			  "\x91\x44\xCF\x98\xC7\xC0\x79\x26"
+			  "\x32\x66\x6F\x23\x7F\x94\x36\x88"
+			  "\x3C\xC9\xD0\xB7\x45\x30\x31\x86"
+			  "\x3D\xC6\xA3\x98\x62\x84\x1A\x8B"
+			  "\x16\x88\xC7\xA3\xE9\x4F\xE0\x86"
+			  "\xA4\x93\xA8\x34\x5A\xCA\xDF\xCA"
+			  "\x46\x38\xD2\xF4\xE0\x2D\x1E\xC9"
+			  "\x7C\xEF\x53\xB7\x60\x72\x41\xBF"
+			  "\x29\x00\x87\x02\xAF\x44\x4C\xB7"
+			  "\x8C\xF5\x3F\x19\xF4\x80\x45\xA7"
+			  "\x15\x5F\xDB\xE9\xB1\x83\xD2\xE6"
+			  "\x1D\x18\x66\x44\x5B\x8F\x14\xEB",
+		.ilen	= 496,
+		.result	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+			  "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+			  "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+			  "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+			  "\xC3\x37\xCE\x65\xFC\x70\x07\x9E"
+			  "\x12\xA9\x40\xD7\x4B\xE2\x79\x10"
+			  "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F"
+			  "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1"
+			  "\x68\xFF\x73\x0A\xA1\x15\xAC\x43"
+			  "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5"
+			  "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
+			  "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
+			  "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
+			  "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+			  "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+			  "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+			  "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+			  "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+			  "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+			  "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+			  "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+			  "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+			  "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+			  "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+			  "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+			  "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+			  "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+			  "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+			  "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+			  "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+			  "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+			  "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+			  "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+			  "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+			  "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+			  "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+			  "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+			  "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+			  "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+			  "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+			  "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+			  "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+			  "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+			  "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+			  "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+			  "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+			  "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+			  "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+			  "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+			  "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+			  "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+			  "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+			  "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+			  "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+			  "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+			  "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+			  "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+			  "\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
+		.rlen	= 496,
+	},
+};
 
-static struct cipher_testvec cast5_enc_tv_template[] = {
-	{
-		.key	= "\x01\x23\x45\x67\x12\x34\x56\x78"
-			  "\x23\x45\x67\x89\x34\x56\x78\x9a",
+static struct cipher_testvec cast5_ctr_enc_tv_template[] = {
+	{ /* Generated from TF test vectors */
+		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A",
 		.klen	= 16,
-		.input	= "\x01\x23\x45\x67\x89\xab\xcd\xef",
-		.ilen	= 8,
-		.result	= "\x23\x8b\x4f\xe5\x84\x7e\x44\xb2",
-		.rlen	= 8,
-	}, {
-		.key	= "\x01\x23\x45\x67\x12\x34\x56\x78"
-			  "\x23\x45",
-		.klen	= 10,
-		.input	= "\x01\x23\x45\x67\x89\xab\xcd\xef",
-		.ilen	= 8,
-		.result	= "\xeb\x6a\x71\x1a\x2c\x02\x27\x1b",
-		.rlen	= 8,
-	}, {
-		.key	= "\x01\x23\x45\x67\x12",
-		.klen	= 5,
-		.input	= "\x01\x23\x45\x67\x89\xab\xcd\xef",
-		.ilen	= 8,
-		.result	= "\x7a\xc8\x16\xd1\x6e\x9b\x30\x2e",
-		.rlen	= 8,
+		.iv	= "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F",
+		.input	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+			  "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+			  "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+			  "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+			  "\xC3\x37\xCE\x65\xFC\x70\x07\x9E"
+			  "\x12\xA9\x40\xD7\x4B\xE2\x79\x10"
+			  "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F"
+			  "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1"
+			  "\x68\xFF\x73\x0A\xA1\x15\xAC\x43"
+			  "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5"
+			  "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
+			  "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
+			  "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
+			  "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+			  "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+			  "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+			  "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+			  "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+			  "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+			  "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+			  "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+			  "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+			  "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+			  "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+			  "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+			  "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+			  "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+			  "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+			  "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+			  "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+			  "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+			  "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+			  "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+			  "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+			  "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+			  "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+			  "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+			  "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+			  "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+			  "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+			  "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+			  "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+			  "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+			  "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+			  "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+			  "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+			  "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+			  "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+			  "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+			  "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+			  "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+			  "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+			  "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+			  "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+			  "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+			  "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+			  "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+			  "\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
+		.ilen	= 496,
+		.result	= "\xFF\xC4\x2E\x82\x3D\xF8\xA8\x39"
+			  "\x7C\x52\xC4\xD3\xBB\x62\xC6\xA8"
+			  "\x0C\x63\xA5\x55\xE3\xF8\x1C\x7F"
+			  "\xDC\x59\xF9\xA0\x52\xAD\x83\xDF"
+			  "\xD5\x3B\x53\x4A\xAA\x1F\x49\x44"
+			  "\xE8\x20\xCC\xF8\x97\xE6\xE0\x3C"
+			  "\x5A\xD2\x83\xEC\xEE\x25\x3F\xCF"
+			  "\x0D\xC2\x79\x80\x99\x6E\xFF\x7B"
+			  "\x64\xB0\x7B\x86\x29\x1D\x9F\x17"
+			  "\x10\xA5\xA5\xEB\x16\x55\x9E\xE3"
+			  "\x88\x18\x52\x56\x48\x58\xD1\x6B"
+			  "\xE8\x74\x6E\x48\xB0\x2E\x69\x63"
+			  "\x32\xAA\xAC\x26\x55\x45\x94\xDE"
+			  "\x30\x26\x26\xE6\x08\x82\x2F\x5F"
+			  "\xA7\x15\x94\x07\x75\x2D\xC6\x3A"
+			  "\x1B\xA0\x39\xFB\xBA\xB9\x06\x56"
+			  "\xF6\x9F\xF1\x2F\x9B\xF3\x89\x8B"
+			  "\x08\xC8\x9D\x5E\x6B\x95\x09\xC7"
+			  "\x98\xB7\x62\xA4\x1D\x25\xFA\xC5"
+			  "\x62\xC8\x5D\x6B\xB4\x85\x88\x7F"
+			  "\x3B\x29\xF9\xB4\x32\x62\x69\xBF"
+			  "\x32\xB8\xEB\xFD\x0E\x26\xAA\xA3"
+			  "\x44\x67\x90\x20\xAC\x41\xDF\x43"
+			  "\xC6\xC7\x19\x9F\x2C\x28\x74\xEB"
+			  "\x3E\x7F\x7A\x80\x5B\xE4\x08\x60"
+			  "\xC7\xC9\x71\x34\x44\xCE\x05\xFD"
+			  "\xA8\x91\xA8\x44\x5E\xD3\x89\x2C"
+			  "\xAE\x59\x0F\x07\x88\x79\x53\x26"
+			  "\xAF\xAC\xCB\x1D\x6F\x08\x25\x62"
+			  "\xD0\x82\x65\x66\xE4\x2A\x29\x1C"
+			  "\x9C\x64\x5F\x49\x9D\xF8\x62\xF9"
+			  "\xED\xC4\x13\x52\x75\xDC\xE4\xF9"
+			  "\x68\x0F\x8A\xCD\xA6\x8D\x75\xAA"
+			  "\x49\xA1\x86\x86\x37\x5C\x6B\x3D"
+			  "\x56\xE5\x6F\xBE\x27\xC0\x10\xF8"
+			  "\x3C\x4D\x17\x35\x14\xDC\x1C\xA0"
+			  "\x6E\xAE\xD1\x10\xDD\x83\x06\xC2"
+			  "\x23\xD3\xC7\x27\x15\x04\x2C\x27"
+			  "\xDD\x1F\x2E\x97\x09\x9C\x33\x7D"
+			  "\xAC\x50\x1B\x2E\xC9\x52\x0C\x14"
+			  "\x4B\x78\xC4\xDE\x07\x6A\x12\x02"
+			  "\x6E\xD7\x4B\x91\xB9\x88\x4D\x02"
+			  "\xC3\xB5\x04\xBC\xE0\x67\xCA\x18"
+			  "\x22\xA1\xAE\x9A\x21\xEF\xB2\x06"
+			  "\x35\xCD\xEC\x37\x70\x2D\xFC\x1E"
+			  "\xA8\x31\xE7\xFC\xE5\x8E\x88\x66"
+			  "\x16\xB5\xC8\x45\x21\x37\xBD\x24"
+			  "\xA9\xD5\x36\x12\x9F\x6E\x67\x80"
+			  "\x87\x54\xD5\xAF\x97\xE1\x15\xA7"
+			  "\x11\xF0\x63\x7B\xE1\x44\x14\x1C"
+			  "\x06\x32\x05\x8C\x6C\xDB\x9B\x36"
+			  "\x6A\x6B\xAD\x3A\x27\x55\x20\x4C"
+			  "\x76\x36\x43\xE8\x16\x60\xB5\xF3"
+			  "\xDF\x5A\xC6\xA5\x69\x78\x59\x51"
+			  "\x54\x68\x65\x06\x84\xDE\x3D\xAE"
+			  "\x38\x91\xBD\xCC\xA2\x8A\xEC\xE6"
+			  "\x9E\x83\xAE\x1E\x8E\x34\x5D\xDE"
+			  "\x91\xCE\x8F\xED\x40\xF7\xC8\x8B"
+			  "\x9A\x13\x4C\xAD\x89\x97\x9E\xD1"
+			  "\x91\x01\xD7\x21\x23\x28\x1E\xCC"
+			  "\x8C\x98\xDB\xDE\xFC\x72\x94\xAA"
+			  "\xC0\x0D\x96\xAA\x23\xF8\xFE\x13",
+		.rlen	= 496,
 	},
 };
 
-static struct cipher_testvec cast5_dec_tv_template[] = {
-	{
-		.key	= "\x01\x23\x45\x67\x12\x34\x56\x78"
-			  "\x23\x45\x67\x89\x34\x56\x78\x9a",
+static struct cipher_testvec cast5_ctr_dec_tv_template[] = {
+	{ /* Generated from TF test vectors */
+		.key	= "\x85\x62\x3F\x1C\xF9\xD6\x1C\xF9"
+			  "\xD6\xB3\x90\x6D\x4A\x90\x6D\x4A",
 		.klen	= 16,
-		.input	= "\x23\x8b\x4f\xe5\x84\x7e\x44\xb2",
-		.ilen	= 8,
-		.result	= "\x01\x23\x45\x67\x89\xab\xcd\xef",
-		.rlen	= 8,
-	}, {
-		.key	= "\x01\x23\x45\x67\x12\x34\x56\x78"
-			  "\x23\x45",
-		.klen	= 10,
-		.input	= "\xeb\x6a\x71\x1a\x2c\x02\x27\x1b",
-		.ilen	= 8,
-		.result	= "\x01\x23\x45\x67\x89\xab\xcd\xef",
-		.rlen	= 8,
-	}, {
-		.key	= "\x01\x23\x45\x67\x12",
-		.klen	= 5,
-		.input	= "\x7a\xc8\x16\xd1\x6e\x9b\x30\x2e",
-		.ilen	= 8,
-		.result	= "\x01\x23\x45\x67\x89\xab\xcd\xef",
-		.rlen	= 8,
+		.iv	= "\xE2\x24\x89\xEE\x53\xB8\x1D\x5F",
+		.input	= "\xFF\xC4\x2E\x82\x3D\xF8\xA8\x39"
+			  "\x7C\x52\xC4\xD3\xBB\x62\xC6\xA8"
+			  "\x0C\x63\xA5\x55\xE3\xF8\x1C\x7F"
+			  "\xDC\x59\xF9\xA0\x52\xAD\x83\xDF"
+			  "\xD5\x3B\x53\x4A\xAA\x1F\x49\x44"
+			  "\xE8\x20\xCC\xF8\x97\xE6\xE0\x3C"
+			  "\x5A\xD2\x83\xEC\xEE\x25\x3F\xCF"
+			  "\x0D\xC2\x79\x80\x99\x6E\xFF\x7B"
+			  "\x64\xB0\x7B\x86\x29\x1D\x9F\x17"
+			  "\x10\xA5\xA5\xEB\x16\x55\x9E\xE3"
+			  "\x88\x18\x52\x56\x48\x58\xD1\x6B"
+			  "\xE8\x74\x6E\x48\xB0\x2E\x69\x63"
+			  "\x32\xAA\xAC\x26\x55\x45\x94\xDE"
+			  "\x30\x26\x26\xE6\x08\x82\x2F\x5F"
+			  "\xA7\x15\x94\x07\x75\x2D\xC6\x3A"
+			  "\x1B\xA0\x39\xFB\xBA\xB9\x06\x56"
+			  "\xF6\x9F\xF1\x2F\x9B\xF3\x89\x8B"
+			  "\x08\xC8\x9D\x5E\x6B\x95\x09\xC7"
+			  "\x98\xB7\x62\xA4\x1D\x25\xFA\xC5"
+			  "\x62\xC8\x5D\x6B\xB4\x85\x88\x7F"
+			  "\x3B\x29\xF9\xB4\x32\x62\x69\xBF"
+			  "\x32\xB8\xEB\xFD\x0E\x26\xAA\xA3"
+			  "\x44\x67\x90\x20\xAC\x41\xDF\x43"
+			  "\xC6\xC7\x19\x9F\x2C\x28\x74\xEB"
+			  "\x3E\x7F\x7A\x80\x5B\xE4\x08\x60"
+			  "\xC7\xC9\x71\x34\x44\xCE\x05\xFD"
+			  "\xA8\x91\xA8\x44\x5E\xD3\x89\x2C"
+			  "\xAE\x59\x0F\x07\x88\x79\x53\x26"
+			  "\xAF\xAC\xCB\x1D\x6F\x08\x25\x62"
+			  "\xD0\x82\x65\x66\xE4\x2A\x29\x1C"
+			  "\x9C\x64\x5F\x49\x9D\xF8\x62\xF9"
+			  "\xED\xC4\x13\x52\x75\xDC\xE4\xF9"
+			  "\x68\x0F\x8A\xCD\xA6\x8D\x75\xAA"
+			  "\x49\xA1\x86\x86\x37\x5C\x6B\x3D"
+			  "\x56\xE5\x6F\xBE\x27\xC0\x10\xF8"
+			  "\x3C\x4D\x17\x35\x14\xDC\x1C\xA0"
+			  "\x6E\xAE\xD1\x10\xDD\x83\x06\xC2"
+			  "\x23\xD3\xC7\x27\x15\x04\x2C\x27"
+			  "\xDD\x1F\x2E\x97\x09\x9C\x33\x7D"
+			  "\xAC\x50\x1B\x2E\xC9\x52\x0C\x14"
+			  "\x4B\x78\xC4\xDE\x07\x6A\x12\x02"
+			  "\x6E\xD7\x4B\x91\xB9\x88\x4D\x02"
+			  "\xC3\xB5\x04\xBC\xE0\x67\xCA\x18"
+			  "\x22\xA1\xAE\x9A\x21\xEF\xB2\x06"
+			  "\x35\xCD\xEC\x37\x70\x2D\xFC\x1E"
+			  "\xA8\x31\xE7\xFC\xE5\x8E\x88\x66"
+			  "\x16\xB5\xC8\x45\x21\x37\xBD\x24"
+			  "\xA9\xD5\x36\x12\x9F\x6E\x67\x80"
+			  "\x87\x54\xD5\xAF\x97\xE1\x15\xA7"
+			  "\x11\xF0\x63\x7B\xE1\x44\x14\x1C"
+			  "\x06\x32\x05\x8C\x6C\xDB\x9B\x36"
+			  "\x6A\x6B\xAD\x3A\x27\x55\x20\x4C"
+			  "\x76\x36\x43\xE8\x16\x60\xB5\xF3"
+			  "\xDF\x5A\xC6\xA5\x69\x78\x59\x51"
+			  "\x54\x68\x65\x06\x84\xDE\x3D\xAE"
+			  "\x38\x91\xBD\xCC\xA2\x8A\xEC\xE6"
+			  "\x9E\x83\xAE\x1E\x8E\x34\x5D\xDE"
+			  "\x91\xCE\x8F\xED\x40\xF7\xC8\x8B"
+			  "\x9A\x13\x4C\xAD\x89\x97\x9E\xD1"
+			  "\x91\x01\xD7\x21\x23\x28\x1E\xCC"
+			  "\x8C\x98\xDB\xDE\xFC\x72\x94\xAA"
+			  "\xC0\x0D\x96\xAA\x23\xF8\xFE\x13",
+		.ilen	= 496,
+		.result	= "\x56\xED\x84\x1B\x8F\x26\xBD\x31"
+			  "\xC8\x5F\xF6\x6A\x01\x98\x0C\xA3"
+			  "\x3A\xD1\x45\xDC\x73\x0A\x7E\x15"
+			  "\xAC\x20\xB7\x4E\xE5\x59\xF0\x87"
+			  "\x1E\x92\x29\xC0\x34\xCB\x62\xF9"
+			  "\x6D\x04\x9B\x0F\xA6\x3D\xD4\x48"
+			  "\xDF\x76\x0D\x81\x18\xAF\x23\xBA"
+			  "\x51\xE8\x5C\xF3\x8A\x21\x95\x2C"
+			  "\xC3\x37\xCE\x65\xFC\x70\x07\x9E"
+			  "\x12\xA9\x40\xD7\x4B\xE2\x79\x10"
+			  "\x84\x1B\xB2\x26\xBD\x54\xEB\x5F"
+			  "\xF6\x8D\x01\x98\x2F\xC6\x3A\xD1"
+			  "\x68\xFF\x73\x0A\xA1\x15\xAC\x43"
+			  "\xDA\x4E\xE5\x7C\x13\x87\x1E\xB5"
+			  "\x29\xC0\x57\xEE\x62\xF9\x90\x04"
+			  "\x9B\x32\xC9\x3D\xD4\x6B\x02\x76"
+			  "\x0D\xA4\x18\xAF\x46\xDD\x51\xE8"
+			  "\x7F\x16\x8A\x21\xB8\x2C\xC3\x5A"
+			  "\xF1\x65\xFC\x93\x07\x9E\x35\xCC"
+			  "\x40\xD7\x6E\x05\x79\x10\xA7\x1B"
+			  "\xB2\x49\xE0\x54\xEB\x82\x19\x8D"
+			  "\x24\xBB\x2F\xC6\x5D\xF4\x68\xFF"
+			  "\x96\x0A\xA1\x38\xCF\x43\xDA\x71"
+			  "\x08\x7C\x13\xAA\x1E\xB5\x4C\xE3"
+			  "\x57\xEE\x85\x1C\x90\x27\xBE\x32"
+			  "\xC9\x60\xF7\x6B\x02\x99\x0D\xA4"
+			  "\x3B\xD2\x46\xDD\x74\x0B\x7F\x16"
+			  "\xAD\x21\xB8\x4F\xE6\x5A\xF1\x88"
+			  "\x1F\x93\x2A\xC1\x35\xCC\x63\xFA"
+			  "\x6E\x05\x9C\x10\xA7\x3E\xD5\x49"
+			  "\xE0\x77\x0E\x82\x19\xB0\x24\xBB"
+			  "\x52\xE9\x5D\xF4\x8B\x22\x96\x2D"
+			  "\xC4\x38\xCF\x66\xFD\x71\x08\x9F"
+			  "\x13\xAA\x41\xD8\x4C\xE3\x7A\x11"
+			  "\x85\x1C\xB3\x27\xBE\x55\xEC\x60"
+			  "\xF7\x8E\x02\x99\x30\xC7\x3B\xD2"
+			  "\x69\x00\x74\x0B\xA2\x16\xAD\x44"
+			  "\xDB\x4F\xE6\x7D\x14\x88\x1F\xB6"
+			  "\x2A\xC1\x58\xEF\x63\xFA\x91\x05"
+			  "\x9C\x33\xCA\x3E\xD5\x6C\x03\x77"
+			  "\x0E\xA5\x19\xB0\x47\xDE\x52\xE9"
+			  "\x80\x17\x8B\x22\xB9\x2D\xC4\x5B"
+			  "\xF2\x66\xFD\x94\x08\x9F\x36\xCD"
+			  "\x41\xD8\x6F\x06\x7A\x11\xA8\x1C"
+			  "\xB3\x4A\xE1\x55\xEC\x83\x1A\x8E"
+			  "\x25\xBC\x30\xC7\x5E\xF5\x69\x00"
+			  "\x97\x0B\xA2\x39\xD0\x44\xDB\x72"
+			  "\x09\x7D\x14\xAB\x1F\xB6\x4D\xE4"
+			  "\x58\xEF\x86\x1D\x91\x28\xBF\x33"
+			  "\xCA\x61\xF8\x6C\x03\x9A\x0E\xA5"
+			  "\x3C\xD3\x47\xDE\x75\x0C\x80\x17"
+			  "\xAE\x22\xB9\x50\xE7\x5B\xF2\x89"
+			  "\x20\x94\x2B\xC2\x36\xCD\x64\xFB"
+			  "\x6F\x06\x9D\x11\xA8\x3F\xD6\x4A"
+			  "\xE1\x78\x0F\x83\x1A\xB1\x25\xBC"
+			  "\x53\xEA\x5E\xF5\x8C\x00\x97\x2E"
+			  "\xC5\x39\xD0\x67\xFE\x72\x09\xA0"
+			  "\x14\xAB\x42\xD9\x4D\xE4\x7B\x12"
+			  "\x86\x1D\xB4\x28\xBF\x56\xED\x61"
+			  "\xF8\x8F\x03\x9A\x31\xC8\x3C\xD3"
+			  "\x6A\x01\x75\x0C\xA3\x17\xAE\x45"
+			  "\xDC\x50\xE7\x7E\x15\x89\x20\xB7",
+		.rlen	= 496,
 	},
 };
 
diff --git a/crypto/tgr192.c b/crypto/tgr192.c
index cbca4f2..8740355 100644
--- a/crypto/tgr192.c
+++ b/crypto/tgr192.c
@@ -628,7 +628,7 @@ static int tgr128_final(struct shash_desc *desc, u8 * out)
 	return 0;
 }
 
-static struct shash_alg tgr192 = {
+static struct shash_alg tgr_algs[3] = { {
 	.digestsize	=	TGR192_DIGEST_SIZE,
 	.init		=	tgr192_init,
 	.update		=	tgr192_update,
@@ -640,9 +640,7 @@ static struct shash_alg tgr192 = {
 		.cra_blocksize	=	TGR192_BLOCK_SIZE,
 		.cra_module	=	THIS_MODULE,
 	}
-};
-
-static struct shash_alg tgr160 = {
+}, {
 	.digestsize	=	TGR160_DIGEST_SIZE,
 	.init		=	tgr192_init,
 	.update		=	tgr192_update,
@@ -654,9 +652,7 @@ static struct shash_alg tgr160 = {
 		.cra_blocksize	=	TGR192_BLOCK_SIZE,
 		.cra_module	=	THIS_MODULE,
 	}
-};
-
-static struct shash_alg tgr128 = {
+}, {
 	.digestsize	=	TGR128_DIGEST_SIZE,
 	.init		=	tgr192_init,
 	.update		=	tgr192_update,
@@ -668,38 +664,16 @@ static struct shash_alg tgr128 = {
 		.cra_blocksize	=	TGR192_BLOCK_SIZE,
 		.cra_module	=	THIS_MODULE,
 	}
-};
+} };
 
 static int __init tgr192_mod_init(void)
 {
-	int ret = 0;
-
-	ret = crypto_register_shash(&tgr192);
-
-	if (ret < 0) {
-		goto out;
-	}
-
-	ret = crypto_register_shash(&tgr160);
-	if (ret < 0) {
-		crypto_unregister_shash(&tgr192);
-		goto out;
-	}
-
-	ret = crypto_register_shash(&tgr128);
-	if (ret < 0) {
-		crypto_unregister_shash(&tgr192);
-		crypto_unregister_shash(&tgr160);
-	}
-      out:
-	return ret;
+	return crypto_register_shashes(tgr_algs, ARRAY_SIZE(tgr_algs));
 }
 
 static void __exit tgr192_mod_fini(void)
 {
-	crypto_unregister_shash(&tgr192);
-	crypto_unregister_shash(&tgr160);
-	crypto_unregister_shash(&tgr128);
+	crypto_unregister_shashes(tgr_algs, ARRAY_SIZE(tgr_algs));
 }
 
 MODULE_ALIAS("tgr160");
diff --git a/crypto/twofish_generic.c b/crypto/twofish_generic.c
index 1f07b84..2d50005 100644
--- a/crypto/twofish_generic.c
+++ b/crypto/twofish_generic.c
@@ -188,7 +188,6 @@ static struct crypto_alg alg = {
 	.cra_ctxsize        =   sizeof(struct twofish_ctx),
 	.cra_alignmask      =	3,
 	.cra_module         =   THIS_MODULE,
-	.cra_list           =   LIST_HEAD_INIT(alg.cra_list),
 	.cra_u              =   { .cipher = {
 	.cia_min_keysize    =   TF_MIN_KEY_SIZE,
 	.cia_max_keysize    =   TF_MAX_KEY_SIZE,
diff --git a/crypto/vmac.c b/crypto/vmac.c
index 4243905..f2338ca 100644
--- a/crypto/vmac.c
+++ b/crypto/vmac.c
@@ -38,11 +38,11 @@
  * Constants and masks
  */
 #define UINT64_C(x) x##ULL
-const u64 p64   = UINT64_C(0xfffffffffffffeff);  /* 2^64 - 257 prime  */
-const u64 m62   = UINT64_C(0x3fffffffffffffff);  /* 62-bit mask       */
-const u64 m63   = UINT64_C(0x7fffffffffffffff);  /* 63-bit mask       */
-const u64 m64   = UINT64_C(0xffffffffffffffff);  /* 64-bit mask       */
-const u64 mpoly = UINT64_C(0x1fffffff1fffffff);  /* Poly key mask     */
+static const u64 p64   = UINT64_C(0xfffffffffffffeff);	/* 2^64 - 257 prime  */
+static const u64 m62   = UINT64_C(0x3fffffffffffffff);	/* 62-bit mask       */
+static const u64 m63   = UINT64_C(0x7fffffffffffffff);	/* 63-bit mask       */
+static const u64 m64   = UINT64_C(0xffffffffffffffff);	/* 64-bit mask       */
+static const u64 mpoly = UINT64_C(0x1fffffff1fffffff);	/* Poly key mask     */
 
 #define pe64_to_cpup le64_to_cpup		/* Prefer little endian */
 
diff --git a/crypto/wp512.c b/crypto/wp512.c
index 71719a2..180f1d6 100644
--- a/crypto/wp512.c
+++ b/crypto/wp512.c
@@ -1119,7 +1119,7 @@ static int wp256_final(struct shash_desc *desc, u8 *out)
 	return 0;
 }
 
-static struct shash_alg wp512 = {
+static struct shash_alg wp_algs[3] = { {
 	.digestsize	=	WP512_DIGEST_SIZE,
 	.init		=	wp512_init,
 	.update		=	wp512_update,
@@ -1131,9 +1131,7 @@ static struct shash_alg wp512 = {
 		.cra_blocksize	=	WP512_BLOCK_SIZE,
 		.cra_module	=	THIS_MODULE,
 	}
-};
-
-static struct shash_alg wp384 = {
+}, {
 	.digestsize	=	WP384_DIGEST_SIZE,
 	.init		=	wp512_init,
 	.update		=	wp512_update,
@@ -1145,9 +1143,7 @@ static struct shash_alg wp384 = {
 		.cra_blocksize	=	WP512_BLOCK_SIZE,
 		.cra_module	=	THIS_MODULE,
 	}
-};
-
-static struct shash_alg wp256 = {
+}, {
 	.digestsize	=	WP256_DIGEST_SIZE,
 	.init		=	wp512_init,
 	.update		=	wp512_update,
@@ -1159,39 +1155,16 @@ static struct shash_alg wp256 = {
 		.cra_blocksize	=	WP512_BLOCK_SIZE,
 		.cra_module	=	THIS_MODULE,
 	}
-};
+} };
 
 static int __init wp512_mod_init(void)
 {
-	int ret = 0;
-
-	ret = crypto_register_shash(&wp512);
-
-	if (ret < 0)
-		goto out;
-
-	ret = crypto_register_shash(&wp384);
-	if (ret < 0)
-	{
-		crypto_unregister_shash(&wp512);
-		goto out;
-	}
-
-	ret = crypto_register_shash(&wp256);
-	if (ret < 0)
-	{
-		crypto_unregister_shash(&wp512);
-		crypto_unregister_shash(&wp384);
-	}
-out:
-	return ret;
+	return crypto_register_shashes(wp_algs, ARRAY_SIZE(wp_algs));
 }
 
 static void __exit wp512_mod_fini(void)
 {
-	crypto_unregister_shash(&wp512);
-	crypto_unregister_shash(&wp384);
-	crypto_unregister_shash(&wp256);
+	crypto_unregister_shashes(wp_algs, ARRAY_SIZE(wp_algs));
 }
 
 MODULE_ALIAS("wp384");
diff --git a/crypto/xor.c b/crypto/xor.c
index 65c7b41..35d6b3a 100644
--- a/crypto/xor.c
+++ b/crypto/xor.c
@@ -56,11 +56,11 @@ xor_blocks(unsigned int src_count, unsigned int bytes, void *dest, void **srcs)
 EXPORT_SYMBOL(xor_blocks);
 
 /* Set of all registered templates.  */
-static struct xor_block_template *template_list;
+static struct xor_block_template *__initdata template_list;
 
 #define BENCH_SIZE (PAGE_SIZE)
 
-static void
+static void __init
 do_xor_speed(struct xor_block_template *tmpl, void *b1, void *b2)
 {
 	int speed;
diff --git a/drivers/Kconfig b/drivers/Kconfig
index ece958d..dbdefa3 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -2,6 +2,8 @@ menu "Device Drivers"
 
 source "drivers/base/Kconfig"
 
+source "drivers/bus/Kconfig"
+
 source "drivers/connector/Kconfig"
 
 source "drivers/mtd/Kconfig"
@@ -152,4 +154,6 @@ source "drivers/vme/Kconfig"
 
 source "drivers/pwm/Kconfig"
 
+source "drivers/irqchip/Kconfig"
+
 endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index 5b42184..03da5b6 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -5,6 +5,9 @@
 # Rewritten to use lists instead of if-statements.
 #
 
+obj-y				+= irqchip/
+obj-y				+= bus/
+
 # GPIO must come after pinctrl as gpios may need to mux pins etc
 obj-y				+= pinctrl/
 obj-y				+= gpio/
@@ -120,7 +123,6 @@ obj-$(CONFIG_VHOST_NET)		+= vhost/
 obj-$(CONFIG_VLYNQ)		+= vlynq/
 obj-$(CONFIG_STAGING)		+= staging/
 obj-y				+= platform/
-obj-y				+= ieee802154/
 #common clk code
 obj-y				+= clk/
 
diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c
index 24c807f..05be17a 100644
--- a/drivers/acpi/acpi_memhotplug.c
+++ b/drivers/acpi/acpi_memhotplug.c
@@ -52,6 +52,9 @@ MODULE_LICENSE("GPL");
 #define MEMORY_POWER_ON_STATE	1
 #define MEMORY_POWER_OFF_STATE	2
 
+static bool auto_probe;
+module_param(auto_probe, bool, S_IRUGO | S_IWUSR);
+
 static int acpi_memory_device_add(struct acpi_device *device);
 static int acpi_memory_device_remove(struct acpi_device *device, int type);
 
@@ -78,6 +81,7 @@ struct acpi_memory_info {
 	unsigned short caching;	/* memory cache attribute */
 	unsigned short write_protect;	/* memory read/write attribute */
 	unsigned int enabled:1;
+	unsigned int failed:1;
 };
 
 struct acpi_memory_device {
@@ -86,8 +90,6 @@ struct acpi_memory_device {
 	struct list_head res_list;
 };
 
-static int acpi_hotmem_initialized;
-
 static acpi_status
 acpi_memory_get_resource(struct acpi_resource *resource, void *context)
 {
@@ -125,12 +127,20 @@ acpi_memory_get_resource(struct acpi_resource *resource, void *context)
 	return AE_OK;
 }
 
+static void
+acpi_memory_free_device_resources(struct acpi_memory_device *mem_device)
+{
+	struct acpi_memory_info *info, *n;
+
+	list_for_each_entry_safe(info, n, &mem_device->res_list, list)
+		kfree(info);
+	INIT_LIST_HEAD(&mem_device->res_list);
+}
+
 static int
 acpi_memory_get_device_resources(struct acpi_memory_device *mem_device)
 {
 	acpi_status status;
-	struct acpi_memory_info *info, *n;
-
 
 	if (!list_empty(&mem_device->res_list))
 		return 0;
@@ -138,9 +148,7 @@ acpi_memory_get_device_resources(struct acpi_memory_device *mem_device)
 	status = acpi_walk_resources(mem_device->device->handle, METHOD_NAME__CRS,
 				     acpi_memory_get_resource, mem_device);
 	if (ACPI_FAILURE(status)) {
-		list_for_each_entry_safe(info, n, &mem_device->res_list, list)
-			kfree(info);
-		INIT_LIST_HEAD(&mem_device->res_list);
+		acpi_memory_free_device_resources(mem_device);
 		return -EINVAL;
 	}
 
@@ -251,9 +259,23 @@ static int acpi_memory_enable_device(struct acpi_memory_device *mem_device)
 			node = memory_add_physaddr_to_nid(info->start_addr);
 
 		result = add_memory(node, info->start_addr, info->length);
-		if (result)
+
+		/*
+		 * If the memory block has been used by the kernel, add_memory()
+		 * returns -EEXIST. If add_memory() returns the other error, it
+		 * means that this memory block is not used by the kernel.
+		 */
+		if (result && result != -EEXIST) {
+			info->failed = 1;
 			continue;
-		info->enabled = 1;
+		}
+
+		if (!result)
+			info->enabled = 1;
+		/*
+		 * Add num_enable even if add_memory() returns -EEXIST, so the
+		 * device is bound to this driver.
+		 */
 		num_enabled++;
 	}
 	if (!num_enabled) {
@@ -317,11 +339,21 @@ static int acpi_memory_disable_device(struct acpi_memory_device *mem_device)
 	 * Note: Assume that this function returns zero on success
 	 */
 	list_for_each_entry_safe(info, n, &mem_device->res_list, list) {
-		if (info->enabled) {
-			result = remove_memory(info->start_addr, info->length);
-			if (result)
-				return result;
-		}
+		if (info->failed)
+			/* The kernel does not use this memory block */
+			continue;
+
+		if (!info->enabled)
+			/*
+			 * The kernel uses this memory block, but it may be not
+			 * managed by us.
+			 */
+			return -EBUSY;
+
+		result = remove_memory(info->start_addr, info->length);
+		if (result)
+			return result;
+		list_del(&info->list);
 		kfree(info);
 	}
 
@@ -420,6 +452,15 @@ static void acpi_memory_device_notify(acpi_handle handle, u32 event, void *data)
 	return;
 }
 
+static void acpi_memory_device_free(struct acpi_memory_device *mem_device)
+{
+	if (!mem_device)
+		return;
+
+	acpi_memory_free_device_resources(mem_device);
+	kfree(mem_device);
+}
+
 static int acpi_memory_device_add(struct acpi_device *device)
 {
 	int result;
@@ -451,35 +492,24 @@ static int acpi_memory_device_add(struct acpi_device *device)
 
 	printk(KERN_DEBUG "%s \n", acpi_device_name(device));
 
-	/*
-	 * Early boot code has recognized memory area by EFI/E820.
-	 * If DSDT shows these memory devices on boot, hotplug is not necessary
-	 * for them. So, it just returns until completion of this driver's
-	 * start up.
-	 */
-	if (!acpi_hotmem_initialized)
-		return 0;
-
 	if (!acpi_memory_check_device(mem_device)) {
 		/* call add_memory func */
 		result = acpi_memory_enable_device(mem_device);
-		if (result)
+		if (result) {
 			printk(KERN_ERR PREFIX
 				"Error in acpi_memory_enable_device\n");
+			acpi_memory_device_free(mem_device);
+		}
 	}
 	return result;
 }
 
 static int acpi_memory_device_remove(struct acpi_device *device, int type)
 {
-	struct acpi_memory_device *mem_device = NULL;
-
-
 	if (!device || !acpi_driver_data(device))
 		return -EINVAL;
 
-	mem_device = acpi_driver_data(device);
-	kfree(mem_device);
+	acpi_memory_device_free(acpi_driver_data(device));
 
 	return 0;
 }
@@ -516,12 +546,44 @@ acpi_memory_register_notify_handler(acpi_handle handle,
 				    u32 level, void *ctxt, void **retv)
 {
 	acpi_status status;
-
+	struct acpi_memory_device *mem_device = NULL;
+	unsigned long long current_status;
 
 	status = is_memory_device(handle);
 	if (ACPI_FAILURE(status))
 		return AE_OK;	/* continue */
 
+	if (auto_probe) {
+		/* Get device present/absent information from the _STA */
+		status = acpi_evaluate_integer(handle, "_STA", NULL,
+					       &current_status);
+		if (ACPI_FAILURE(status))
+			goto install;
+
+		/*
+		 * Check for device status. Device should be
+		 * present/enabled/functioning.
+		 */
+		if (!(current_status &
+		      (ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_ENABLED |
+		       ACPI_STA_DEVICE_FUNCTIONING)))
+			goto install;
+
+		if (acpi_memory_get_device(handle, &mem_device))
+			goto install;
+
+		/* We have bound this device while we register the driver */
+		if (mem_device->state == MEMORY_POWER_ON_STATE)
+			goto install;
+
+		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+				  "\nauto probe memory device\n"));
+
+		if (acpi_memory_enable_device(mem_device))
+			pr_err(PREFIX "Cannot enable memory device\n");
+	}
+
+install:
 	status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
 					     acpi_memory_device_notify, NULL);
 	/* continue */
@@ -568,7 +630,6 @@ static int __init acpi_memory_device_init(void)
 		return -ENODEV;
 	}
 
-	acpi_hotmem_initialized = 1;
 	return 0;
 }
 
diff --git a/drivers/acpi/acpica/Makefile b/drivers/acpi/acpica/Makefile
index 0a1b343..7f1d407 100644
--- a/drivers/acpi/acpica/Makefile
+++ b/drivers/acpi/acpica/Makefile
@@ -158,5 +158,6 @@ acpi-y +=		\
 	utresrc.o	\
 	utstate.o	\
 	utxface.o	\
+	utxfinit.o	\
 	utxferror.o	\
 	utxfmutex.o
diff --git a/drivers/acpi/acpica/achware.h b/drivers/acpi/acpica/achware.h
index 5de4ec7..d902d31 100644
--- a/drivers/acpi/acpica/achware.h
+++ b/drivers/acpi/acpica/achware.h
@@ -110,8 +110,7 @@ acpi_status acpi_hw_write_port(acpi_io_address address, u32 value, u32 width);
 /*
  * hwgpe - GPE support
  */
-u32 acpi_hw_get_gpe_register_bit(struct acpi_gpe_event_info *gpe_event_info,
-			     struct acpi_gpe_register_info *gpe_register_info);
+u32 acpi_hw_get_gpe_register_bit(struct acpi_gpe_event_info *gpe_event_info);
 
 acpi_status
 acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u32 action);
diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h
index cc80fe1..c816ee6 100644
--- a/drivers/acpi/acpica/aclocal.h
+++ b/drivers/acpi/acpica/aclocal.h
@@ -707,15 +707,18 @@ union acpi_parse_value {
 	u8                              disasm_opcode;  /* Subtype used for disassembly */\
 	char                            aml_op_name[16])	/* Op name (debug only) */
 
-#define ACPI_DASM_BUFFER                0x00
-#define ACPI_DASM_RESOURCE              0x01
-#define ACPI_DASM_STRING                0x02
-#define ACPI_DASM_UNICODE               0x03
-#define ACPI_DASM_EISAID                0x04
-#define ACPI_DASM_MATCHOP               0x05
-#define ACPI_DASM_LNOT_PREFIX           0x06
-#define ACPI_DASM_LNOT_SUFFIX           0x07
-#define ACPI_DASM_IGNORE                0x08
+/* Flags for disasm_flags field above */
+
+#define ACPI_DASM_BUFFER                0x00	/* Buffer is a simple data buffer */
+#define ACPI_DASM_RESOURCE              0x01	/* Buffer is a Resource Descriptor */
+#define ACPI_DASM_STRING                0x02	/* Buffer is a ASCII string */
+#define ACPI_DASM_UNICODE               0x03	/* Buffer is a Unicode string */
+#define ACPI_DASM_PLD_METHOD            0x04	/* Buffer is a _PLD method bit-packed buffer */
+#define ACPI_DASM_EISAID                0x05	/* Integer is an EISAID */
+#define ACPI_DASM_MATCHOP               0x06	/* Parent opcode is a Match() operator */
+#define ACPI_DASM_LNOT_PREFIX           0x07	/* Start of a Lnot_equal (etc.) pair of opcodes */
+#define ACPI_DASM_LNOT_SUFFIX           0x08	/* End  of a Lnot_equal (etc.) pair of opcodes */
+#define ACPI_DASM_IGNORE                0x09	/* Not used at this time */
 
 /*
  * Generic operation (for example:  If, While, Store)
@@ -932,6 +935,7 @@ struct acpi_bit_register_info {
 #define ACPI_OSI_WIN_VISTA_SP1          0x09
 #define ACPI_OSI_WIN_VISTA_SP2          0x0A
 #define ACPI_OSI_WIN_7                  0x0B
+#define ACPI_OSI_WIN_8                  0x0C
 
 #define ACPI_ALWAYS_ILLEGAL             0x00
 
@@ -1024,6 +1028,7 @@ struct acpi_port_info {
  ****************************************************************************/
 
 struct acpi_db_method_info {
+	acpi_handle method;
 	acpi_handle main_thread_gate;
 	acpi_handle thread_complete_gate;
 	acpi_thread_id *threads;
diff --git a/drivers/acpi/acpica/acmacros.h b/drivers/acpi/acpica/acmacros.h
index 832b619..a7f68c4 100644
--- a/drivers/acpi/acpica/acmacros.h
+++ b/drivers/acpi/acpica/acmacros.h
@@ -277,10 +277,33 @@
 
 /* Bitfields within ACPI registers */
 
-#define ACPI_REGISTER_PREPARE_BITS(val, pos, mask)      ((val << pos) & mask)
-#define ACPI_REGISTER_INSERT_VALUE(reg, pos, mask, val)  reg = (reg & (~(mask))) | ACPI_REGISTER_PREPARE_BITS(val, pos, mask)
+#define ACPI_REGISTER_PREPARE_BITS(val, pos, mask) \
+	((val << pos) & mask)
 
-#define ACPI_INSERT_BITS(target, mask, source)          target = ((target & (~(mask))) | (source & mask))
+#define ACPI_REGISTER_INSERT_VALUE(reg, pos, mask, val) \
+	reg = (reg & (~(mask))) | ACPI_REGISTER_PREPARE_BITS(val, pos, mask)
+
+#define ACPI_INSERT_BITS(target, mask, source) \
+	target = ((target & (~(mask))) | (source & mask))
+
+/* Generic bitfield macros and masks */
+
+#define ACPI_GET_BITS(source_ptr, position, mask) \
+	((*source_ptr >> position) & mask)
+
+#define ACPI_SET_BITS(target_ptr, position, mask, value) \
+	(*target_ptr |= ((value & mask) << position))
+
+#define ACPI_1BIT_MASK      0x00000001
+#define ACPI_2BIT_MASK      0x00000003
+#define ACPI_3BIT_MASK      0x00000007
+#define ACPI_4BIT_MASK      0x0000000F
+#define ACPI_5BIT_MASK      0x0000001F
+#define ACPI_6BIT_MASK      0x0000003F
+#define ACPI_7BIT_MASK      0x0000007F
+#define ACPI_8BIT_MASK      0x000000FF
+#define ACPI_16BIT_MASK     0x0000FFFF
+#define ACPI_24BIT_MASK     0x00FFFFFF
 
 /*
  * An object of type struct acpi_namespace_node can appear in some contexts
diff --git a/drivers/acpi/acpica/dswload.c b/drivers/acpi/acpica/dswload.c
index 552aa3a..5575100 100644
--- a/drivers/acpi/acpica/dswload.c
+++ b/drivers/acpi/acpica/dswload.c
@@ -230,6 +230,20 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state,
 			walk_state->scope_info->common.value = ACPI_TYPE_ANY;
 			break;
 
+		case ACPI_TYPE_METHOD:
+
+			/*
+			 * Allow scope change to root during execution of module-level
+			 * code. Root is typed METHOD during this time.
+			 */
+			if ((node == acpi_gbl_root_node) &&
+			    (walk_state->
+			     parse_flags & ACPI_PARSE_MODULE_LEVEL)) {
+				break;
+			}
+
+			/*lint -fallthrough */
+
 		default:
 
 			/* All other types are an error */
diff --git a/drivers/acpi/acpica/dswload2.c b/drivers/acpi/acpica/dswload2.c
index ae71477..89c0114 100644
--- a/drivers/acpi/acpica/dswload2.c
+++ b/drivers/acpi/acpica/dswload2.c
@@ -230,6 +230,20 @@ acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state,
 			walk_state->scope_info->common.value = ACPI_TYPE_ANY;
 			break;
 
+		case ACPI_TYPE_METHOD:
+
+			/*
+			 * Allow scope change to root during execution of module-level
+			 * code. Root is typed METHOD during this time.
+			 */
+			if ((node == acpi_gbl_root_node) &&
+			    (walk_state->
+			     parse_flags & ACPI_PARSE_MODULE_LEVEL)) {
+				break;
+			}
+
+			/*lint -fallthrough */
+
 		default:
 
 			/* All other types are an error */
diff --git a/drivers/acpi/acpica/evgpe.c b/drivers/acpi/acpica/evgpe.c
index afbd5cb..ef0193d 100644
--- a/drivers/acpi/acpica/evgpe.c
+++ b/drivers/acpi/acpica/evgpe.c
@@ -80,8 +80,7 @@ acpi_ev_update_gpe_enable_mask(struct acpi_gpe_event_info *gpe_event_info)
 		return_ACPI_STATUS(AE_NOT_EXIST);
 	}
 
-	register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info,
-						gpe_register_info);
+	register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info);
 
 	/* Clear the run bit up front */
 
@@ -379,6 +378,18 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list)
 			 */
 			if (!(gpe_register_info->enable_for_run |
 			      gpe_register_info->enable_for_wake)) {
+				ACPI_DEBUG_PRINT((ACPI_DB_INTERRUPTS,
+						  "Ignore disabled registers for GPE%02X-GPE%02X: "
+						  "RunEnable=%02X, WakeEnable=%02X\n",
+						  gpe_register_info->
+						  base_gpe_number,
+						  gpe_register_info->
+						  base_gpe_number +
+						  (ACPI_GPE_REGISTER_WIDTH - 1),
+						  gpe_register_info->
+						  enable_for_run,
+						  gpe_register_info->
+						  enable_for_wake));
 				continue;
 			}
 
@@ -401,9 +412,14 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list)
 			}
 
 			ACPI_DEBUG_PRINT((ACPI_DB_INTERRUPTS,
-					  "Read GPE Register at GPE%02X: Status=%02X, Enable=%02X\n",
+					  "Read registers for GPE%02X-GPE%02X: Status=%02X, Enable=%02X, "
+					  "RunEnable=%02X, WakeEnable=%02X\n",
 					  gpe_register_info->base_gpe_number,
-					  status_reg, enable_reg));
+					  gpe_register_info->base_gpe_number +
+					  (ACPI_GPE_REGISTER_WIDTH - 1),
+					  status_reg, enable_reg,
+					  gpe_register_info->enable_for_run,
+					  gpe_register_info->enable_for_wake));
 
 			/* Check if there is anything active at all in this register */
 
diff --git a/drivers/acpi/acpica/evxfgpe.c b/drivers/acpi/acpica/evxfgpe.c
index 6affbdb..87c5f23 100644
--- a/drivers/acpi/acpica/evxfgpe.c
+++ b/drivers/acpi/acpica/evxfgpe.c
@@ -357,8 +357,7 @@ acpi_status acpi_set_gpe_wake_mask(acpi_handle gpe_device, u32 gpe_number, u8 ac
 		goto unlock_and_exit;
 	}
 
-	register_bit =
-	    acpi_hw_get_gpe_register_bit(gpe_event_info, gpe_register_info);
+	register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info);
 
 	/* Perform the action */
 
diff --git a/drivers/acpi/acpica/hwgpe.c b/drivers/acpi/acpica/hwgpe.c
index 25bd28c..db40765 100644
--- a/drivers/acpi/acpica/hwgpe.c
+++ b/drivers/acpi/acpica/hwgpe.c
@@ -60,7 +60,6 @@ acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
  * FUNCTION:	acpi_hw_get_gpe_register_bit
  *
  * PARAMETERS:	gpe_event_info	    - Info block for the GPE
- *		gpe_register_info   - Info block for the GPE register
  *
  * RETURN:	Register mask with a one in the GPE bit position
  *
@@ -69,11 +68,10 @@ acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
  *
  ******************************************************************************/
 
-u32 acpi_hw_get_gpe_register_bit(struct acpi_gpe_event_info *gpe_event_info,
-			     struct acpi_gpe_register_info *gpe_register_info)
+u32 acpi_hw_get_gpe_register_bit(struct acpi_gpe_event_info *gpe_event_info)
 {
 	return (u32)1 << (gpe_event_info->gpe_number -
-				gpe_register_info->base_gpe_number);
+		 gpe_event_info->register_info->base_gpe_number);
 }
 
 /******************************************************************************
@@ -115,8 +113,7 @@ acpi_hw_low_set_gpe(struct acpi_gpe_event_info *gpe_event_info, u32 action)
 
 	/* Set or clear just the bit that corresponds to this GPE */
 
-	register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info,
-						gpe_register_info);
+	register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info);
 	switch (action) {
 	case ACPI_GPE_CONDITIONAL_ENABLE:
 
@@ -178,8 +175,7 @@ acpi_status acpi_hw_clear_gpe(struct acpi_gpe_event_info * gpe_event_info)
 	 * Write a one to the appropriate bit in the status register to
 	 * clear this GPE.
 	 */
-	register_bit =
-	    acpi_hw_get_gpe_register_bit(gpe_event_info, gpe_register_info);
+	register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info);
 
 	status = acpi_hw_write(register_bit,
 			       &gpe_register_info->status_address);
@@ -222,8 +218,7 @@ acpi_hw_get_gpe_status(struct acpi_gpe_event_info * gpe_event_info,
 
 	/* Get the register bitmask for this GPE */
 
-	register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info,
-						gpe_register_info);
+	register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info);
 
 	/* GPE currently enabled? (enabled for runtime?) */
 
diff --git a/drivers/acpi/acpica/hwxfsleep.c b/drivers/acpi/acpica/hwxfsleep.c
index 1f165a7..0ff1ece 100644
--- a/drivers/acpi/acpica/hwxfsleep.c
+++ b/drivers/acpi/acpica/hwxfsleep.c
@@ -381,7 +381,6 @@ ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state)
  * FUNCTION:    acpi_leave_sleep_state_prep
  *
  * PARAMETERS:  sleep_state         - Which sleep state we are exiting
- *              flags               - ACPI_EXECUTE_BFS to run optional method
  *
  * RETURN:      Status
  *
diff --git a/drivers/acpi/acpica/nsdump.c b/drivers/acpi/acpica/nsdump.c
index 7ee4e6a..2526aaf 100644
--- a/drivers/acpi/acpica/nsdump.c
+++ b/drivers/acpi/acpica/nsdump.c
@@ -264,7 +264,7 @@ acpi_ns_dump_one_object(acpi_handle obj_handle,
 		switch (type) {
 		case ACPI_TYPE_PROCESSOR:
 
-			acpi_os_printf("ID %X Len %.4X Addr %p\n",
+			acpi_os_printf("ID %02X Len %02X Addr %p\n",
 				       obj_desc->processor.proc_id,
 				       obj_desc->processor.length,
 				       ACPI_CAST_PTR(void,
diff --git a/drivers/acpi/acpica/tbinstal.c b/drivers/acpi/acpica/tbinstal.c
index 74f97d7..70f9d78 100644
--- a/drivers/acpi/acpica/tbinstal.c
+++ b/drivers/acpi/acpica/tbinstal.c
@@ -350,6 +350,7 @@ struct acpi_table_header *acpi_tb_table_override(struct acpi_table_header
 acpi_status acpi_tb_resize_root_table_list(void)
 {
 	struct acpi_table_desc *tables;
+	u32 table_count;
 
 	ACPI_FUNCTION_TRACE(tb_resize_root_table_list);
 
@@ -363,8 +364,13 @@ acpi_status acpi_tb_resize_root_table_list(void)
 
 	/* Increase the Table Array size */
 
-	tables = ACPI_ALLOCATE_ZEROED(((acpi_size) acpi_gbl_root_table_list.
-				       max_table_count +
+	if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) {
+		table_count = acpi_gbl_root_table_list.max_table_count;
+	} else {
+		table_count = acpi_gbl_root_table_list.current_table_count;
+	}
+
+	tables = ACPI_ALLOCATE_ZEROED(((acpi_size) table_count +
 				       ACPI_ROOT_TABLE_SIZE_INCREMENT) *
 				      sizeof(struct acpi_table_desc));
 	if (!tables) {
@@ -377,8 +383,8 @@ acpi_status acpi_tb_resize_root_table_list(void)
 
 	if (acpi_gbl_root_table_list.tables) {
 		ACPI_MEMCPY(tables, acpi_gbl_root_table_list.tables,
-			    (acpi_size) acpi_gbl_root_table_list.
-			    max_table_count * sizeof(struct acpi_table_desc));
+			    (acpi_size) table_count *
+			    sizeof(struct acpi_table_desc));
 
 		if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) {
 			ACPI_FREE(acpi_gbl_root_table_list.tables);
@@ -386,9 +392,9 @@ acpi_status acpi_tb_resize_root_table_list(void)
 	}
 
 	acpi_gbl_root_table_list.tables = tables;
-	acpi_gbl_root_table_list.max_table_count +=
-	    ACPI_ROOT_TABLE_SIZE_INCREMENT;
-	acpi_gbl_root_table_list.flags |= (u8)ACPI_ROOT_ORIGIN_ALLOCATED;
+	acpi_gbl_root_table_list.max_table_count =
+	    table_count + ACPI_ROOT_TABLE_SIZE_INCREMENT;
+	acpi_gbl_root_table_list.flags |= ACPI_ROOT_ORIGIN_ALLOCATED;
 
 	return_ACPI_STATUS(AE_OK);
 }
diff --git a/drivers/acpi/acpica/tbxface.c b/drivers/acpi/acpica/tbxface.c
index 29e51bc..2110126 100644
--- a/drivers/acpi/acpica/tbxface.c
+++ b/drivers/acpi/acpica/tbxface.c
@@ -159,14 +159,12 @@ acpi_initialize_tables(struct acpi_table_desc * initial_table_array,
  * DESCRIPTION: Reallocate Root Table List into dynamic memory. Copies the
  *              root list from the previously provided scratch area. Should
  *              be called once dynamic memory allocation is available in the
- *              kernel
+ *              kernel.
  *
  ******************************************************************************/
 acpi_status acpi_reallocate_root_table(void)
 {
-	struct acpi_table_desc *tables;
-	acpi_size new_size;
-	acpi_size current_size;
+	acpi_status status;
 
 	ACPI_FUNCTION_TRACE(acpi_reallocate_root_table);
 
@@ -178,39 +176,10 @@ acpi_status acpi_reallocate_root_table(void)
 		return_ACPI_STATUS(AE_SUPPORT);
 	}
 
-	/*
-	 * Get the current size of the root table and add the default
-	 * increment to create the new table size.
-	 */
-	current_size = (acpi_size)
-	    acpi_gbl_root_table_list.current_table_count *
-	    sizeof(struct acpi_table_desc);
-
-	new_size = current_size +
-	    (ACPI_ROOT_TABLE_SIZE_INCREMENT * sizeof(struct acpi_table_desc));
-
-	/* Create new array and copy the old array */
-
-	tables = ACPI_ALLOCATE_ZEROED(new_size);
-	if (!tables) {
-		return_ACPI_STATUS(AE_NO_MEMORY);
-	}
+	acpi_gbl_root_table_list.flags |= ACPI_ROOT_ALLOW_RESIZE;
 
-	ACPI_MEMCPY(tables, acpi_gbl_root_table_list.tables, current_size);
-
-	/*
-	 * Update the root table descriptor. The new size will be the current
-	 * number of tables plus the increment, independent of the reserved
-	 * size of the original table list.
-	 */
-	acpi_gbl_root_table_list.tables = tables;
-	acpi_gbl_root_table_list.max_table_count =
-	    acpi_gbl_root_table_list.current_table_count +
-	    ACPI_ROOT_TABLE_SIZE_INCREMENT;
-	acpi_gbl_root_table_list.flags =
-	    ACPI_ROOT_ORIGIN_ALLOCATED | ACPI_ROOT_ALLOW_RESIZE;
-
-	return_ACPI_STATUS(AE_OK);
+	status = acpi_tb_resize_root_table_list();
+	return_ACPI_STATUS(status);
 }
 
 /*******************************************************************************
diff --git a/drivers/acpi/acpica/utosi.c b/drivers/acpi/acpica/utosi.c
index 34ef0bd..676285d 100644
--- a/drivers/acpi/acpica/utosi.c
+++ b/drivers/acpi/acpica/utosi.c
@@ -73,6 +73,7 @@ static struct acpi_interface_info acpi_default_supported_interfaces[] = {
 	{"Windows 2006 SP1", NULL, 0, ACPI_OSI_WIN_VISTA_SP1},	/* Windows Vista SP1 - Added 09/2009 */
 	{"Windows 2006 SP2", NULL, 0, ACPI_OSI_WIN_VISTA_SP2},	/* Windows Vista SP2 - Added 09/2010 */
 	{"Windows 2009", NULL, 0, ACPI_OSI_WIN_7},	/* Windows 7 and Server 2008 R2 - Added 09/2009 */
+	{"Windows 2012", NULL, 0, ACPI_OSI_WIN_8},	/* Windows 8 and Server 2012 - Added 08/2012 */
 
 	/* Feature Group Strings */
 
diff --git a/drivers/acpi/acpica/utxface.c b/drivers/acpi/acpica/utxface.c
index 534179f..b09632b 100644
--- a/drivers/acpi/acpica/utxface.c
+++ b/drivers/acpi/acpica/utxface.c
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Module Name: utxface - External interfaces for "global" ACPI functions
+ * Module Name: utxface - External interfaces, miscellaneous utility functions
  *
  *****************************************************************************/
 
@@ -53,271 +53,6 @@
 #define _COMPONENT          ACPI_UTILITIES
 ACPI_MODULE_NAME("utxface")
 
-#ifndef ACPI_ASL_COMPILER
-/*******************************************************************************
- *
- * FUNCTION:    acpi_initialize_subsystem
- *
- * PARAMETERS:  None
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Initializes all global variables.  This is the first function
- *              called, so any early initialization belongs here.
- *
- ******************************************************************************/
-acpi_status __init acpi_initialize_subsystem(void)
-{
-	acpi_status status;
-
-	ACPI_FUNCTION_TRACE(acpi_initialize_subsystem);
-
-	acpi_gbl_startup_flags = ACPI_SUBSYSTEM_INITIALIZE;
-	ACPI_DEBUG_EXEC(acpi_ut_init_stack_ptr_trace());
-
-	/* Initialize the OS-Dependent layer */
-
-	status = acpi_os_initialize();
-	if (ACPI_FAILURE(status)) {
-		ACPI_EXCEPTION((AE_INFO, status, "During OSL initialization"));
-		return_ACPI_STATUS(status);
-	}
-
-	/* Initialize all globals used by the subsystem */
-
-	status = acpi_ut_init_globals();
-	if (ACPI_FAILURE(status)) {
-		ACPI_EXCEPTION((AE_INFO, status,
-				"During initialization of globals"));
-		return_ACPI_STATUS(status);
-	}
-
-	/* Create the default mutex objects */
-
-	status = acpi_ut_mutex_initialize();
-	if (ACPI_FAILURE(status)) {
-		ACPI_EXCEPTION((AE_INFO, status,
-				"During Global Mutex creation"));
-		return_ACPI_STATUS(status);
-	}
-
-	/*
-	 * Initialize the namespace manager and
-	 * the root of the namespace tree
-	 */
-	status = acpi_ns_root_initialize();
-	if (ACPI_FAILURE(status)) {
-		ACPI_EXCEPTION((AE_INFO, status,
-				"During Namespace initialization"));
-		return_ACPI_STATUS(status);
-	}
-
-	/* Initialize the global OSI interfaces list with the static names */
-
-	status = acpi_ut_initialize_interfaces();
-	if (ACPI_FAILURE(status)) {
-		ACPI_EXCEPTION((AE_INFO, status,
-				"During OSI interfaces initialization"));
-		return_ACPI_STATUS(status);
-	}
-
-	/* If configured, initialize the AML debugger */
-
-	ACPI_DEBUGGER_EXEC(status = acpi_db_initialize());
-	return_ACPI_STATUS(status);
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_enable_subsystem
- *
- * PARAMETERS:  flags           - Init/enable Options
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Completes the subsystem initialization including hardware.
- *              Puts system into ACPI mode if it isn't already.
- *
- ******************************************************************************/
-acpi_status acpi_enable_subsystem(u32 flags)
-{
-	acpi_status status = AE_OK;
-
-	ACPI_FUNCTION_TRACE(acpi_enable_subsystem);
-
-#if (!ACPI_REDUCED_HARDWARE)
-
-	/* Enable ACPI mode */
-
-	if (!(flags & ACPI_NO_ACPI_ENABLE)) {
-		ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
-				  "[Init] Going into ACPI mode\n"));
-
-		acpi_gbl_original_mode = acpi_hw_get_mode();
-
-		status = acpi_enable();
-		if (ACPI_FAILURE(status)) {
-			ACPI_WARNING((AE_INFO, "AcpiEnable failed"));
-			return_ACPI_STATUS(status);
-		}
-	}
-
-	/*
-	 * Obtain a permanent mapping for the FACS. This is required for the
-	 * Global Lock and the Firmware Waking Vector
-	 */
-	status = acpi_tb_initialize_facs();
-	if (ACPI_FAILURE(status)) {
-		ACPI_WARNING((AE_INFO, "Could not map the FACS table"));
-		return_ACPI_STATUS(status);
-	}
-#endif				/* !ACPI_REDUCED_HARDWARE */
-
-	/*
-	 * Install the default op_region handlers. These are installed unless
-	 * other handlers have already been installed via the
-	 * install_address_space_handler interface.
-	 */
-	if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) {
-		ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
-				  "[Init] Installing default address space handlers\n"));
-
-		status = acpi_ev_install_region_handlers();
-		if (ACPI_FAILURE(status)) {
-			return_ACPI_STATUS(status);
-		}
-	}
-#if (!ACPI_REDUCED_HARDWARE)
-	/*
-	 * Initialize ACPI Event handling (Fixed and General Purpose)
-	 *
-	 * Note1: We must have the hardware and events initialized before we can
-	 * execute any control methods safely. Any control method can require
-	 * ACPI hardware support, so the hardware must be fully initialized before
-	 * any method execution!
-	 *
-	 * Note2: Fixed events are initialized and enabled here. GPEs are
-	 * initialized, but cannot be enabled until after the hardware is
-	 * completely initialized (SCI and global_lock activated)
-	 */
-	if (!(flags & ACPI_NO_EVENT_INIT)) {
-		ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
-				  "[Init] Initializing ACPI events\n"));
-
-		status = acpi_ev_initialize_events();
-		if (ACPI_FAILURE(status)) {
-			return_ACPI_STATUS(status);
-		}
-	}
-
-	/*
-	 * Install the SCI handler and Global Lock handler. This completes the
-	 * hardware initialization.
-	 */
-	if (!(flags & ACPI_NO_HANDLER_INIT)) {
-		ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
-				  "[Init] Installing SCI/GL handlers\n"));
-
-		status = acpi_ev_install_xrupt_handlers();
-		if (ACPI_FAILURE(status)) {
-			return_ACPI_STATUS(status);
-		}
-	}
-#endif				/* !ACPI_REDUCED_HARDWARE */
-
-	return_ACPI_STATUS(status);
-}
-
-ACPI_EXPORT_SYMBOL(acpi_enable_subsystem)
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_initialize_objects
- *
- * PARAMETERS:  flags           - Init/enable Options
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Completes namespace initialization by initializing device
- *              objects and executing AML code for Regions, buffers, etc.
- *
- ******************************************************************************/
-acpi_status acpi_initialize_objects(u32 flags)
-{
-	acpi_status status = AE_OK;
-
-	ACPI_FUNCTION_TRACE(acpi_initialize_objects);
-
-	/*
-	 * Run all _REG methods
-	 *
-	 * Note: Any objects accessed by the _REG methods will be automatically
-	 * initialized, even if they contain executable AML (see the call to
-	 * acpi_ns_initialize_objects below).
-	 */
-	if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) {
-		ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
-				  "[Init] Executing _REG OpRegion methods\n"));
-
-		status = acpi_ev_initialize_op_regions();
-		if (ACPI_FAILURE(status)) {
-			return_ACPI_STATUS(status);
-		}
-	}
-
-	/*
-	 * Execute any module-level code that was detected during the table load
-	 * phase. Although illegal since ACPI 2.0, there are many machines that
-	 * contain this type of code. Each block of detected executable AML code
-	 * outside of any control method is wrapped with a temporary control
-	 * method object and placed on a global list. The methods on this list
-	 * are executed below.
-	 */
-	acpi_ns_exec_module_code_list();
-
-	/*
-	 * Initialize the objects that remain uninitialized. This runs the
-	 * executable AML that may be part of the declaration of these objects:
-	 * operation_regions, buffer_fields, Buffers, and Packages.
-	 */
-	if (!(flags & ACPI_NO_OBJECT_INIT)) {
-		ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
-				  "[Init] Completing Initialization of ACPI Objects\n"));
-
-		status = acpi_ns_initialize_objects();
-		if (ACPI_FAILURE(status)) {
-			return_ACPI_STATUS(status);
-		}
-	}
-
-	/*
-	 * Initialize all device objects in the namespace. This runs the device
-	 * _STA and _INI methods.
-	 */
-	if (!(flags & ACPI_NO_DEVICE_INIT)) {
-		ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
-				  "[Init] Initializing ACPI Devices\n"));
-
-		status = acpi_ns_initialize_devices();
-		if (ACPI_FAILURE(status)) {
-			return_ACPI_STATUS(status);
-		}
-	}
-
-	/*
-	 * Empty the caches (delete the cached objects) on the assumption that
-	 * the table load filled them up more than they will be at runtime --
-	 * thus wasting non-paged memory.
-	 */
-	status = acpi_purge_cached_objects();
-
-	acpi_gbl_startup_flags |= ACPI_INITIALIZED_OK;
-	return_ACPI_STATUS(status);
-}
-
-ACPI_EXPORT_SYMBOL(acpi_initialize_objects)
-
-#endif
 /*******************************************************************************
  *
  * FUNCTION:    acpi_terminate
@@ -683,3 +418,90 @@ acpi_check_address_range(acpi_adr_space_type space_id,
 
 ACPI_EXPORT_SYMBOL(acpi_check_address_range)
 #endif				/* !ACPI_ASL_COMPILER */
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_decode_pld_buffer
+ *
+ * PARAMETERS:  in_buffer           - Buffer returned by _PLD method
+ *              length              - Length of the in_buffer
+ *              return_buffer       - Where the decode buffer is returned
+ *
+ * RETURN:      Status and the decoded _PLD buffer. User must deallocate
+ *              the buffer via ACPI_FREE.
+ *
+ * DESCRIPTION: Decode the bit-packed buffer returned by the _PLD method into
+ *              a local struct that is much more useful to an ACPI driver.
+ *
+ ******************************************************************************/
+acpi_status
+acpi_decode_pld_buffer(u8 *in_buffer,
+		       acpi_size length, struct acpi_pld_info ** return_buffer)
+{
+	struct acpi_pld_info *pld_info;
+	u32 *buffer = ACPI_CAST_PTR(u32, in_buffer);
+	u32 dword;
+
+	/* Parameter validation */
+
+	if (!in_buffer || !return_buffer || (length < 16)) {
+		return (AE_BAD_PARAMETER);
+	}
+
+	pld_info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_pld_info));
+	if (!pld_info) {
+		return (AE_NO_MEMORY);
+	}
+
+	/* First 32-bit DWord */
+
+	ACPI_MOVE_32_TO_32(&dword, &buffer[0]);
+	pld_info->revision = ACPI_PLD_GET_REVISION(&dword);
+	pld_info->ignore_color = ACPI_PLD_GET_IGNORE_COLOR(&dword);
+	pld_info->color = ACPI_PLD_GET_COLOR(&dword);
+
+	/* Second 32-bit DWord */
+
+	ACPI_MOVE_32_TO_32(&dword, &buffer[1]);
+	pld_info->width = ACPI_PLD_GET_WIDTH(&dword);
+	pld_info->height = ACPI_PLD_GET_HEIGHT(&dword);
+
+	/* Third 32-bit DWord */
+
+	ACPI_MOVE_32_TO_32(&dword, &buffer[2]);
+	pld_info->user_visible = ACPI_PLD_GET_USER_VISIBLE(&dword);
+	pld_info->dock = ACPI_PLD_GET_DOCK(&dword);
+	pld_info->lid = ACPI_PLD_GET_LID(&dword);
+	pld_info->panel = ACPI_PLD_GET_PANEL(&dword);
+	pld_info->vertical_position = ACPI_PLD_GET_VERTICAL(&dword);
+	pld_info->horizontal_position = ACPI_PLD_GET_HORIZONTAL(&dword);
+	pld_info->shape = ACPI_PLD_GET_SHAPE(&dword);
+	pld_info->group_orientation = ACPI_PLD_GET_ORIENTATION(&dword);
+	pld_info->group_token = ACPI_PLD_GET_TOKEN(&dword);
+	pld_info->group_position = ACPI_PLD_GET_POSITION(&dword);
+	pld_info->bay = ACPI_PLD_GET_BAY(&dword);
+
+	/* Fourth 32-bit DWord */
+
+	ACPI_MOVE_32_TO_32(&dword, &buffer[3]);
+	pld_info->ejectable = ACPI_PLD_GET_EJECTABLE(&dword);
+	pld_info->ospm_eject_required = ACPI_PLD_GET_OSPM_EJECT(&dword);
+	pld_info->cabinet_number = ACPI_PLD_GET_CABINET(&dword);
+	pld_info->card_cage_number = ACPI_PLD_GET_CARD_CAGE(&dword);
+	pld_info->reference = ACPI_PLD_GET_REFERENCE(&dword);
+	pld_info->rotation = ACPI_PLD_GET_ROTATION(&dword);
+	pld_info->order = ACPI_PLD_GET_ORDER(&dword);
+
+	if (length >= ACPI_PLD_BUFFER_SIZE) {
+
+		/* Fifth 32-bit DWord (Revision 2 of _PLD) */
+
+		ACPI_MOVE_32_TO_32(&dword, &buffer[4]);
+		pld_info->vertical_offset = ACPI_PLD_GET_VERT_OFFSET(&dword);
+		pld_info->horizontal_offset = ACPI_PLD_GET_HORIZ_OFFSET(&dword);
+	}
+
+	*return_buffer = pld_info;
+	return (AE_OK);
+}
+
+ACPI_EXPORT_SYMBOL(acpi_decode_pld_buffer)
diff --git a/drivers/acpi/acpica/utxfinit.c b/drivers/acpi/acpica/utxfinit.c
new file mode 100644
index 0000000..14f5236
--- /dev/null
+++ b/drivers/acpi/acpica/utxfinit.c
@@ -0,0 +1,317 @@
+/******************************************************************************
+ *
+ * Module Name: utxfinit - External interfaces for ACPICA initialization
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2012, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ *    substantially similar to the "NO WARRANTY" disclaimer below
+ *    ("Disclaimer") and any redistribution must be conditioned upon
+ *    including a substantially similar Disclaimer requirement for further
+ *    binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ *    of any contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ */
+
+#include <linux/export.h>
+#include <acpi/acpi.h>
+#include "accommon.h"
+#include "acevents.h"
+#include "acnamesp.h"
+#include "acdebug.h"
+#include "actables.h"
+
+#define _COMPONENT          ACPI_UTILITIES
+ACPI_MODULE_NAME("utxfinit")
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_initialize_subsystem
+ *
+ * PARAMETERS:  None
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Initializes all global variables. This is the first function
+ *              called, so any early initialization belongs here.
+ *
+ ******************************************************************************/
+acpi_status acpi_initialize_subsystem(void)
+{
+	acpi_status status;
+
+	ACPI_FUNCTION_TRACE(acpi_initialize_subsystem);
+
+	acpi_gbl_startup_flags = ACPI_SUBSYSTEM_INITIALIZE;
+	ACPI_DEBUG_EXEC(acpi_ut_init_stack_ptr_trace());
+
+	/* Initialize the OS-Dependent layer */
+
+	status = acpi_os_initialize();
+	if (ACPI_FAILURE(status)) {
+		ACPI_EXCEPTION((AE_INFO, status, "During OSL initialization"));
+		return_ACPI_STATUS(status);
+	}
+
+	/* Initialize all globals used by the subsystem */
+
+	status = acpi_ut_init_globals();
+	if (ACPI_FAILURE(status)) {
+		ACPI_EXCEPTION((AE_INFO, status,
+				"During initialization of globals"));
+		return_ACPI_STATUS(status);
+	}
+
+	/* Create the default mutex objects */
+
+	status = acpi_ut_mutex_initialize();
+	if (ACPI_FAILURE(status)) {
+		ACPI_EXCEPTION((AE_INFO, status,
+				"During Global Mutex creation"));
+		return_ACPI_STATUS(status);
+	}
+
+	/*
+	 * Initialize the namespace manager and
+	 * the root of the namespace tree
+	 */
+	status = acpi_ns_root_initialize();
+	if (ACPI_FAILURE(status)) {
+		ACPI_EXCEPTION((AE_INFO, status,
+				"During Namespace initialization"));
+		return_ACPI_STATUS(status);
+	}
+
+	/* Initialize the global OSI interfaces list with the static names */
+
+	status = acpi_ut_initialize_interfaces();
+	if (ACPI_FAILURE(status)) {
+		ACPI_EXCEPTION((AE_INFO, status,
+				"During OSI interfaces initialization"));
+		return_ACPI_STATUS(status);
+	}
+
+	/* If configured, initialize the AML debugger */
+
+	ACPI_DEBUGGER_EXEC(status = acpi_db_initialize());
+	return_ACPI_STATUS(status);
+}
+ACPI_EXPORT_SYMBOL(acpi_initialize_subsystem)
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_enable_subsystem
+ *
+ * PARAMETERS:  flags               - Init/enable Options
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Completes the subsystem initialization including hardware.
+ *              Puts system into ACPI mode if it isn't already.
+ *
+ ******************************************************************************/
+acpi_status acpi_enable_subsystem(u32 flags)
+{
+	acpi_status status = AE_OK;
+
+	ACPI_FUNCTION_TRACE(acpi_enable_subsystem);
+
+#if (!ACPI_REDUCED_HARDWARE)
+
+	/* Enable ACPI mode */
+
+	if (!(flags & ACPI_NO_ACPI_ENABLE)) {
+		ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+				  "[Init] Going into ACPI mode\n"));
+
+		acpi_gbl_original_mode = acpi_hw_get_mode();
+
+		status = acpi_enable();
+		if (ACPI_FAILURE(status)) {
+			ACPI_WARNING((AE_INFO, "AcpiEnable failed"));
+			return_ACPI_STATUS(status);
+		}
+	}
+
+	/*
+	 * Obtain a permanent mapping for the FACS. This is required for the
+	 * Global Lock and the Firmware Waking Vector
+	 */
+	status = acpi_tb_initialize_facs();
+	if (ACPI_FAILURE(status)) {
+		ACPI_WARNING((AE_INFO, "Could not map the FACS table"));
+		return_ACPI_STATUS(status);
+	}
+#endif				/* !ACPI_REDUCED_HARDWARE */
+
+	/*
+	 * Install the default op_region handlers. These are installed unless
+	 * other handlers have already been installed via the
+	 * install_address_space_handler interface.
+	 */
+	if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) {
+		ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+				  "[Init] Installing default address space handlers\n"));
+
+		status = acpi_ev_install_region_handlers();
+		if (ACPI_FAILURE(status)) {
+			return_ACPI_STATUS(status);
+		}
+	}
+#if (!ACPI_REDUCED_HARDWARE)
+	/*
+	 * Initialize ACPI Event handling (Fixed and General Purpose)
+	 *
+	 * Note1: We must have the hardware and events initialized before we can
+	 * execute any control methods safely. Any control method can require
+	 * ACPI hardware support, so the hardware must be fully initialized before
+	 * any method execution!
+	 *
+	 * Note2: Fixed events are initialized and enabled here. GPEs are
+	 * initialized, but cannot be enabled until after the hardware is
+	 * completely initialized (SCI and global_lock activated) and the various
+	 * initialization control methods are run (_REG, _STA, _INI) on the
+	 * entire namespace.
+	 */
+	if (!(flags & ACPI_NO_EVENT_INIT)) {
+		ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+				  "[Init] Initializing ACPI events\n"));
+
+		status = acpi_ev_initialize_events();
+		if (ACPI_FAILURE(status)) {
+			return_ACPI_STATUS(status);
+		}
+	}
+
+	/*
+	 * Install the SCI handler and Global Lock handler. This completes the
+	 * hardware initialization.
+	 */
+	if (!(flags & ACPI_NO_HANDLER_INIT)) {
+		ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+				  "[Init] Installing SCI/GL handlers\n"));
+
+		status = acpi_ev_install_xrupt_handlers();
+		if (ACPI_FAILURE(status)) {
+			return_ACPI_STATUS(status);
+		}
+	}
+#endif				/* !ACPI_REDUCED_HARDWARE */
+
+	return_ACPI_STATUS(status);
+}
+ACPI_EXPORT_SYMBOL(acpi_enable_subsystem)
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_initialize_objects
+ *
+ * PARAMETERS:  flags               - Init/enable Options
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Completes namespace initialization by initializing device
+ *              objects and executing AML code for Regions, buffers, etc.
+ *
+ ******************************************************************************/
+acpi_status acpi_initialize_objects(u32 flags)
+{
+	acpi_status status = AE_OK;
+
+	ACPI_FUNCTION_TRACE(acpi_initialize_objects);
+
+	/*
+	 * Run all _REG methods
+	 *
+	 * Note: Any objects accessed by the _REG methods will be automatically
+	 * initialized, even if they contain executable AML (see the call to
+	 * acpi_ns_initialize_objects below).
+	 */
+	if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) {
+		ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+				  "[Init] Executing _REG OpRegion methods\n"));
+
+		status = acpi_ev_initialize_op_regions();
+		if (ACPI_FAILURE(status)) {
+			return_ACPI_STATUS(status);
+		}
+	}
+
+	/*
+	 * Execute any module-level code that was detected during the table load
+	 * phase. Although illegal since ACPI 2.0, there are many machines that
+	 * contain this type of code. Each block of detected executable AML code
+	 * outside of any control method is wrapped with a temporary control
+	 * method object and placed on a global list. The methods on this list
+	 * are executed below.
+	 */
+	acpi_ns_exec_module_code_list();
+
+	/*
+	 * Initialize the objects that remain uninitialized. This runs the
+	 * executable AML that may be part of the declaration of these objects:
+	 * operation_regions, buffer_fields, Buffers, and Packages.
+	 */
+	if (!(flags & ACPI_NO_OBJECT_INIT)) {
+		ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+				  "[Init] Completing Initialization of ACPI Objects\n"));
+
+		status = acpi_ns_initialize_objects();
+		if (ACPI_FAILURE(status)) {
+			return_ACPI_STATUS(status);
+		}
+	}
+
+	/*
+	 * Initialize all device objects in the namespace. This runs the device
+	 * _STA and _INI methods.
+	 */
+	if (!(flags & ACPI_NO_DEVICE_INIT)) {
+		ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+				  "[Init] Initializing ACPI Devices\n"));
+
+		status = acpi_ns_initialize_devices();
+		if (ACPI_FAILURE(status)) {
+			return_ACPI_STATUS(status);
+		}
+	}
+
+	/*
+	 * Empty the caches (delete the cached objects) on the assumption that
+	 * the table load filled them up more than they will be at runtime --
+	 * thus wasting non-paged memory.
+	 */
+	status = acpi_purge_cached_objects();
+
+	acpi_gbl_startup_flags |= ACPI_INITIALIZED_OK;
+	return_ACPI_STATUS(status);
+}
+ACPI_EXPORT_SYMBOL(acpi_initialize_objects)
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index e059695..d59175e 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -994,8 +994,6 @@ static int __init acpi_bus_init(void)
 	status = acpi_ec_ecdt_probe();
 	/* Ignore result. Not having an ECDT is not fatal. */
 
-	acpi_bus_osc_support();
-
 	status = acpi_initialize_objects(ACPI_FULL_INITIALIZATION);
 	if (ACPI_FAILURE(status)) {
 		printk(KERN_ERR PREFIX "Unable to initialize ACPI objects\n");
@@ -1003,6 +1001,12 @@ static int __init acpi_bus_init(void)
 	}
 
 	/*
+	 * _OSC method may exist in module level code,
+	 * so it must be run after ACPI_FULL_INITIALIZATION
+	 */
+	acpi_bus_osc_support();
+
+	/*
 	 * _PDC control method may load dynamic SSDT tables,
 	 * and we need to install the table handler before that.
 	 */
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index 314a3b8..f0d936b 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -450,15 +450,4 @@ static int acpi_button_remove(struct acpi_device *device, int type)
 	return 0;
 }
 
-static int __init acpi_button_init(void)
-{
-	return acpi_bus_register_driver(&acpi_button_driver);
-}
-
-static void __exit acpi_button_exit(void)
-{
-	acpi_bus_unregister_driver(&acpi_button_driver);
-}
-
-module_init(acpi_button_init);
-module_exit(acpi_button_exit);
+module_acpi_driver(acpi_button_driver);
diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c
index bc36a47..3bd6a54 100644
--- a/drivers/acpi/fan.c
+++ b/drivers/acpi/fan.c
@@ -212,24 +212,4 @@ static int acpi_fan_resume(struct device *dev)
 }
 #endif
 
-static int __init acpi_fan_init(void)
-{
-	int result = 0;
-
-	result = acpi_bus_register_driver(&acpi_fan_driver);
-	if (result < 0)
-		return -ENODEV;
-
-	return 0;
-}
-
-static void __exit acpi_fan_exit(void)
-{
-
-	acpi_bus_unregister_driver(&acpi_fan_driver);
-
-	return;
-}
-
-module_init(acpi_fan_init);
-module_exit(acpi_fan_exit);
+module_acpi_driver(acpi_fan_driver);
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c
index 243ee85..d1a2d74 100644
--- a/drivers/acpi/glue.c
+++ b/drivers/acpi/glue.c
@@ -25,6 +25,8 @@
 static LIST_HEAD(bus_type_list);
 static DECLARE_RWSEM(bus_type_sem);
 
+#define PHYSICAL_NODE_STRING "physical_node"
+
 int register_acpi_bus_type(struct acpi_bus_type *type)
 {
 	if (acpi_disabled)
@@ -124,84 +126,119 @@ acpi_handle acpi_get_child(acpi_handle parent, u64 address)
 
 EXPORT_SYMBOL(acpi_get_child);
 
-/* Link ACPI devices with physical devices */
-static void acpi_glue_data_handler(acpi_handle handle,
-				   void *context)
-{
-	/* we provide an empty handler */
-}
-
-/* Note: a success call will increase reference count by one */
-struct device *acpi_get_physical_device(acpi_handle handle)
-{
-	acpi_status status;
-	struct device *dev;
-
-	status = acpi_get_data(handle, acpi_glue_data_handler, (void **)&dev);
-	if (ACPI_SUCCESS(status))
-		return get_device(dev);
-	return NULL;
-}
-
-EXPORT_SYMBOL(acpi_get_physical_device);
-
 static int acpi_bind_one(struct device *dev, acpi_handle handle)
 {
 	struct acpi_device *acpi_dev;
 	acpi_status status;
+	struct acpi_device_physical_node *physical_node;
+	char physical_node_name[sizeof(PHYSICAL_NODE_STRING) + 2];
+	int retval = -EINVAL;
 
 	if (dev->archdata.acpi_handle) {
 		dev_warn(dev, "Drivers changed 'acpi_handle'\n");
 		return -EINVAL;
 	}
+
 	get_device(dev);
-	status = acpi_attach_data(handle, acpi_glue_data_handler, dev);
-	if (ACPI_FAILURE(status)) {
-		put_device(dev);
-		return -EINVAL;
+	status = acpi_bus_get_device(handle, &acpi_dev);
+	if (ACPI_FAILURE(status))
+		goto err;
+
+	physical_node = kzalloc(sizeof(struct acpi_device_physical_node),
+		GFP_KERNEL);
+	if (!physical_node) {
+		retval = -ENOMEM;
+		goto err;
 	}
-	dev->archdata.acpi_handle = handle;
 
-	status = acpi_bus_get_device(handle, &acpi_dev);
-	if (!ACPI_FAILURE(status)) {
-		int ret;
-
-		ret = sysfs_create_link(&dev->kobj, &acpi_dev->dev.kobj,
-				"firmware_node");
-		ret = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj,
-				"physical_node");
-		if (acpi_dev->wakeup.flags.valid)
-			device_set_wakeup_capable(dev, true);
+	mutex_lock(&acpi_dev->physical_node_lock);
+	/* allocate physical node id according to physical_node_id_bitmap */
+	physical_node->node_id =
+		find_first_zero_bit(acpi_dev->physical_node_id_bitmap,
+		ACPI_MAX_PHYSICAL_NODE);
+	if (physical_node->node_id >= ACPI_MAX_PHYSICAL_NODE) {
+		retval = -ENOSPC;
+		mutex_unlock(&acpi_dev->physical_node_lock);
+		goto err;
 	}
 
+	set_bit(physical_node->node_id, acpi_dev->physical_node_id_bitmap);
+	physical_node->dev = dev;
+	list_add_tail(&physical_node->node, &acpi_dev->physical_node_list);
+	acpi_dev->physical_node_count++;
+	mutex_unlock(&acpi_dev->physical_node_lock);
+
+	dev->archdata.acpi_handle = handle;
+
+	if (!physical_node->node_id)
+		strcpy(physical_node_name, PHYSICAL_NODE_STRING);
+	else
+		sprintf(physical_node_name,
+			"physical_node%d", physical_node->node_id);
+	retval = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj,
+			physical_node_name);
+	retval = sysfs_create_link(&dev->kobj, &acpi_dev->dev.kobj,
+		"firmware_node");
+
+	if (acpi_dev->wakeup.flags.valid)
+		device_set_wakeup_capable(dev, true);
+
 	return 0;
+
+ err:
+	put_device(dev);
+	return retval;
 }
 
 static int acpi_unbind_one(struct device *dev)
 {
+	struct acpi_device_physical_node *entry;
+	struct acpi_device *acpi_dev;
+	acpi_status status;
+	struct list_head *node, *next;
+
 	if (!dev->archdata.acpi_handle)
 		return 0;
-	if (dev == acpi_get_physical_device(dev->archdata.acpi_handle)) {
-		struct acpi_device *acpi_dev;
 
-		/* acpi_get_physical_device increase refcnt by one */
-		put_device(dev);
+	status = acpi_bus_get_device(dev->archdata.acpi_handle,
+		&acpi_dev);
+	if (ACPI_FAILURE(status))
+		goto err;
 
-		if (!acpi_bus_get_device(dev->archdata.acpi_handle,
-					&acpi_dev)) {
-			sysfs_remove_link(&dev->kobj, "firmware_node");
-			sysfs_remove_link(&acpi_dev->dev.kobj, "physical_node");
-		}
+	mutex_lock(&acpi_dev->physical_node_lock);
+	list_for_each_safe(node, next, &acpi_dev->physical_node_list) {
+		char physical_node_name[sizeof(PHYSICAL_NODE_STRING) + 2];
+
+		entry = list_entry(node, struct acpi_device_physical_node,
+			node);
+		if (entry->dev != dev)
+			continue;
+
+		list_del(node);
+		clear_bit(entry->node_id, acpi_dev->physical_node_id_bitmap);
 
-		acpi_detach_data(dev->archdata.acpi_handle,
-				 acpi_glue_data_handler);
+		acpi_dev->physical_node_count--;
+
+		if (!entry->node_id)
+			strcpy(physical_node_name, PHYSICAL_NODE_STRING);
+		else
+			sprintf(physical_node_name,
+				"physical_node%d", entry->node_id);
+
+		sysfs_remove_link(&acpi_dev->dev.kobj, physical_node_name);
+		sysfs_remove_link(&dev->kobj, "firmware_node");
 		dev->archdata.acpi_handle = NULL;
 		/* acpi_bind_one increase refcnt by one */
 		put_device(dev);
-	} else {
-		dev_err(dev, "Oops, 'acpi_handle' corrupt\n");
+		kfree(entry);
 	}
+	mutex_unlock(&acpi_dev->physical_node_lock);
+
 	return 0;
+
+err:
+	dev_err(dev, "Oops, 'acpi_handle' corrupt\n");
+	return -EINVAL;
 }
 
 static int acpi_platform_notify(struct device *dev)
diff --git a/drivers/acpi/hed.c b/drivers/acpi/hed.c
index d0c1967..20a0f2c 100644
--- a/drivers/acpi/hed.c
+++ b/drivers/acpi/hed.c
@@ -86,25 +86,7 @@ static struct acpi_driver acpi_hed_driver = {
 		.notify = acpi_hed_notify,
 	},
 };
-
-static int __init acpi_hed_init(void)
-{
-	if (acpi_disabled)
-		return -ENODEV;
-
-	if (acpi_bus_register_driver(&acpi_hed_driver) < 0)
-		return -ENODEV;
-
-	return 0;
-}
-
-static void __exit acpi_hed_exit(void)
-{
-	acpi_bus_unregister_driver(&acpi_hed_driver);
-}
-
-module_init(acpi_hed_init);
-module_exit(acpi_hed_exit);
+module_acpi_driver(acpi_hed_driver);
 
 ACPI_MODULE_NAME("hed");
 MODULE_AUTHOR("Huang Ying");
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index 72a2c98..bce469c 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -27,7 +27,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/types.h>
-#include <linux/spinlock.h>
+#include <linux/mutex.h>
 #include <linux/pm.h>
 #include <linux/pm_runtime.h>
 #include <linux/pci.h>
@@ -71,9 +71,11 @@ static struct acpi_driver acpi_pci_root_driver = {
 		},
 };
 
+/* Lock to protect both acpi_pci_roots and acpi_pci_drivers lists */
+static DEFINE_MUTEX(acpi_pci_root_lock);
 static LIST_HEAD(acpi_pci_roots);
+static LIST_HEAD(acpi_pci_drivers);
 
-static struct acpi_pci_driver *sub_driver;
 static DEFINE_MUTEX(osc_lock);
 
 int acpi_pci_register_driver(struct acpi_pci_driver *driver)
@@ -81,55 +83,46 @@ int acpi_pci_register_driver(struct acpi_pci_driver *driver)
 	int n = 0;
 	struct acpi_pci_root *root;
 
-	struct acpi_pci_driver **pptr = &sub_driver;
-	while (*pptr)
-		pptr = &(*pptr)->next;
-	*pptr = driver;
-
-	if (!driver->add)
-		return 0;
-
-	list_for_each_entry(root, &acpi_pci_roots, node) {
-		driver->add(root->device->handle);
-		n++;
-	}
+	mutex_lock(&acpi_pci_root_lock);
+	list_add_tail(&driver->node, &acpi_pci_drivers);
+	if (driver->add)
+		list_for_each_entry(root, &acpi_pci_roots, node) {
+			driver->add(root);
+			n++;
+		}
+	mutex_unlock(&acpi_pci_root_lock);
 
 	return n;
 }
-
 EXPORT_SYMBOL(acpi_pci_register_driver);
 
 void acpi_pci_unregister_driver(struct acpi_pci_driver *driver)
 {
 	struct acpi_pci_root *root;
 
-	struct acpi_pci_driver **pptr = &sub_driver;
-	while (*pptr) {
-		if (*pptr == driver)
-			break;
-		pptr = &(*pptr)->next;
-	}
-	BUG_ON(!*pptr);
-	*pptr = (*pptr)->next;
-
-	if (!driver->remove)
-		return;
-
-	list_for_each_entry(root, &acpi_pci_roots, node)
-		driver->remove(root->device->handle);
+	mutex_lock(&acpi_pci_root_lock);
+	list_del(&driver->node);
+	if (driver->remove)
+		list_for_each_entry(root, &acpi_pci_roots, node)
+			driver->remove(root);
+	mutex_unlock(&acpi_pci_root_lock);
 }
-
 EXPORT_SYMBOL(acpi_pci_unregister_driver);
 
 acpi_handle acpi_get_pci_rootbridge_handle(unsigned int seg, unsigned int bus)
 {
 	struct acpi_pci_root *root;
+	acpi_handle handle = NULL;
 	
+	mutex_lock(&acpi_pci_root_lock);
 	list_for_each_entry(root, &acpi_pci_roots, node)
 		if ((root->segment == (u16) seg) &&
-		    (root->secondary.start == (u16) bus))
-			return root->device->handle;
-	return NULL;		
+		    (root->secondary.start == (u16) bus)) {
+			handle = root->device->handle;
+			break;
+		}
+	mutex_unlock(&acpi_pci_root_lock);
+	return handle;
 }
 
 EXPORT_SYMBOL_GPL(acpi_get_pci_rootbridge_handle);
@@ -277,12 +270,15 @@ static acpi_status acpi_pci_osc_support(struct acpi_pci_root *root, u32 flags)
 struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle)
 {
 	struct acpi_pci_root *root;
+	struct acpi_device *device;
 
-	list_for_each_entry(root, &acpi_pci_roots, node) {
-		if (root->device->handle == handle)
-			return root;
-	}
-	return NULL;
+	if (acpi_bus_get_device(handle, &device) ||
+	    acpi_match_device_ids(device, root_device_ids))
+		return NULL;
+
+	root = acpi_driver_data(device);
+
+	return root;
 }
 EXPORT_SYMBOL_GPL(acpi_pci_find_root);
 
@@ -518,8 +514,9 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
 	 * TBD: Need PCI interface for enumeration/configuration of roots.
 	 */
 
-	/* TBD: Locking */
+	mutex_lock(&acpi_pci_root_lock);
 	list_add_tail(&root->node, &acpi_pci_roots);
+	mutex_unlock(&acpi_pci_root_lock);
 
 	printk(KERN_INFO PREFIX "%s [%s] (domain %04x %pR)\n",
 	       acpi_device_name(device), acpi_device_bid(device),
@@ -538,7 +535,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
 			    "Bus %04x:%02x not present in PCI namespace\n",
 			    root->segment, (unsigned int)root->secondary.start);
 		result = -ENODEV;
-		goto end;
+		goto out_del_root;
 	}
 
 	/*
@@ -548,7 +545,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
 	 */
 	result = acpi_pci_bind_root(device);
 	if (result)
-		goto end;
+		goto out_del_root;
 
 	/*
 	 * PCI Routing Table
@@ -633,9 +630,11 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
 
 	return 0;
 
+out_del_root:
+	mutex_lock(&acpi_pci_root_lock);
+	list_del(&root->node);
+	mutex_unlock(&acpi_pci_root_lock);
 end:
-	if (!list_empty(&root->node))
-		list_del(&root->node);
 	kfree(root);
 	return result;
 }
@@ -643,18 +642,34 @@ end:
 static int acpi_pci_root_start(struct acpi_device *device)
 {
 	struct acpi_pci_root *root = acpi_driver_data(device);
+	struct acpi_pci_driver *driver;
+
+	mutex_lock(&acpi_pci_root_lock);
+	list_for_each_entry(driver, &acpi_pci_drivers, node)
+		if (driver->add)
+			driver->add(root);
+	mutex_unlock(&acpi_pci_root_lock);
 
 	pci_bus_add_devices(root->bus);
+
 	return 0;
 }
 
 static int acpi_pci_root_remove(struct acpi_device *device, int type)
 {
 	struct acpi_pci_root *root = acpi_driver_data(device);
+	struct acpi_pci_driver *driver;
+
+	mutex_lock(&acpi_pci_root_lock);
+	list_for_each_entry(driver, &acpi_pci_drivers, node)
+		if (driver->remove)
+			driver->remove(root);
 
 	device_set_run_wake(root->bus->bridge, false);
 	pci_acpi_remove_bus_pm_notifier(device);
 
+	list_del(&root->node);
+	mutex_unlock(&acpi_pci_root_lock);
 	kfree(root);
 	return 0;
 }
diff --git a/drivers/acpi/pci_slot.c b/drivers/acpi/pci_slot.c
index e50e31a..d22585f 100644
--- a/drivers/acpi/pci_slot.c
+++ b/drivers/acpi/pci_slot.c
@@ -67,8 +67,8 @@ struct acpi_pci_slot {
 	struct list_head list;		/* node in the list of slots */
 };
 
-static int acpi_pci_slot_add(acpi_handle handle);
-static void acpi_pci_slot_remove(acpi_handle handle);
+static int acpi_pci_slot_add(struct acpi_pci_root *root);
+static void acpi_pci_slot_remove(struct acpi_pci_root *root);
 
 static LIST_HEAD(slot_list);
 static DEFINE_MUTEX(slot_list_lock);
@@ -233,45 +233,20 @@ out:
 
 /*
  * walk_root_bridge - generic root bridge walker
- * @handle: points to an acpi_pci_root
+ * @root: poiner of an acpi_pci_root
  * @user_function: user callback for slot objects
  *
  * Call user_function for all objects underneath this root bridge.
  * Walk p2p bridges underneath us and call user_function on those too.
  */
 static int
-walk_root_bridge(acpi_handle handle, acpi_walk_callback user_function)
+walk_root_bridge(struct acpi_pci_root *root, acpi_walk_callback user_function)
 {
-	int seg, bus;
-	unsigned long long tmp;
 	acpi_status status;
-	acpi_handle dummy_handle;
-	struct pci_bus *pci_bus;
+	acpi_handle handle = root->device->handle;
+	struct pci_bus *pci_bus = root->bus;
 	struct callback_args context;
 
-	/* If the bridge doesn't have _STA, we assume it is always there */
-	status = acpi_get_handle(handle, "_STA", &dummy_handle);
-	if (ACPI_SUCCESS(status)) {
-		status = acpi_evaluate_integer(handle, "_STA", NULL, &tmp);
-		if (ACPI_FAILURE(status)) {
-			info("%s: _STA evaluation failure\n", __func__);
-			return 0;
-		}
-		if ((tmp & ACPI_STA_DEVICE_FUNCTIONING) == 0)
-			/* don't register this object */
-			return 0;
-	}
-
-	status = acpi_evaluate_integer(handle, "_SEG", NULL, &tmp);
-	seg = ACPI_SUCCESS(status) ? tmp : 0;
-
-	status = acpi_evaluate_integer(handle, "_BBN", NULL, &tmp);
-	bus = ACPI_SUCCESS(status) ? tmp : 0;
-
-	pci_bus = pci_find_bus(seg, bus);
-	if (!pci_bus)
-		return 0;
-
 	context.pci_bus = pci_bus;
 	context.user_function = user_function;
 	context.root_handle = handle;
@@ -295,11 +270,11 @@ walk_root_bridge(acpi_handle handle, acpi_walk_callback user_function)
  * @handle: points to an acpi_pci_root
  */
 static int
-acpi_pci_slot_add(acpi_handle handle)
+acpi_pci_slot_add(struct acpi_pci_root *root)
 {
 	acpi_status status;
 
-	status = walk_root_bridge(handle, register_slot);
+	status = walk_root_bridge(root, register_slot);
 	if (ACPI_FAILURE(status))
 		err("%s: register_slot failure - %d\n", __func__, status);
 
@@ -311,10 +286,11 @@ acpi_pci_slot_add(acpi_handle handle)
  * @handle: points to an acpi_pci_root
  */
 static void
-acpi_pci_slot_remove(acpi_handle handle)
+acpi_pci_slot_remove(struct acpi_pci_root *root)
 {
 	struct acpi_pci_slot *slot, *tmp;
 	struct pci_bus *pbus;
+	acpi_handle handle = root->device->handle;
 
 	mutex_lock(&slot_list_lock);
 	list_for_each_entry_safe(slot, tmp, &slot_list, list) {
diff --git a/drivers/acpi/proc.c b/drivers/acpi/proc.c
index 251c7b62..27adb09 100644
--- a/drivers/acpi/proc.c
+++ b/drivers/acpi/proc.c
@@ -302,26 +302,41 @@ acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset)
 	list_for_each_safe(node, next, &acpi_wakeup_device_list) {
 		struct acpi_device *dev =
 		    container_of(node, struct acpi_device, wakeup_list);
-		struct device *ldev;
+		struct acpi_device_physical_node *entry;
 
 		if (!dev->wakeup.flags.valid)
 			continue;
 
-		ldev = acpi_get_physical_device(dev->handle);
-		seq_printf(seq, "%s\t  S%d\t%c%-8s  ",
+		seq_printf(seq, "%s\t  S%d\t",
 			   dev->pnp.bus_id,
-			   (u32) dev->wakeup.sleep_state,
-			   dev->wakeup.flags.run_wake ? '*' : ' ',
-			   (device_may_wakeup(&dev->dev)
-			     || (ldev && device_may_wakeup(ldev))) ?
-			       "enabled" : "disabled");
-		if (ldev)
-			seq_printf(seq, "%s:%s",
-				   ldev->bus ? ldev->bus->name : "no-bus",
-				   dev_name(ldev));
-		seq_printf(seq, "\n");
-		put_device(ldev);
-
+			   (u32) dev->wakeup.sleep_state);
+
+		if (!dev->physical_node_count)
+			seq_printf(seq, "%c%-8s\n",
+				dev->wakeup.flags.run_wake ?
+				'*' : ' ', "disabled");
+		else {
+			struct device *ldev;
+			list_for_each_entry(entry, &dev->physical_node_list,
+					node) {
+				ldev = get_device(entry->dev);
+				if (!ldev)
+					continue;
+
+				if (&entry->node !=
+						dev->physical_node_list.next)
+					seq_printf(seq, "\t\t");
+
+				seq_printf(seq, "%c%-8s  %s:%s\n",
+					dev->wakeup.flags.run_wake ? '*' : ' ',
+					(device_may_wakeup(&dev->dev) ||
+					(ldev && device_may_wakeup(ldev))) ?
+					"enabled" : "disabled",
+					ldev->bus ? ldev->bus->name :
+					"no-bus", dev_name(ldev));
+				put_device(ldev);
+			}
+		}
 	}
 	mutex_unlock(&acpi_device_lock);
 	return 0;
@@ -329,12 +344,14 @@ acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset)
 
 static void physical_device_enable_wakeup(struct acpi_device *adev)
 {
-	struct device *dev = acpi_get_physical_device(adev->handle);
+	struct acpi_device_physical_node *entry;
 
-	if (dev && device_can_wakeup(dev)) {
-		bool enable = !device_may_wakeup(dev);
-		device_set_wakeup_enable(dev, enable);
-	}
+	list_for_each_entry(entry,
+		&adev->physical_node_list, node)
+		if (entry->dev && device_can_wakeup(entry->dev)) {
+			bool enable = !device_may_wakeup(entry->dev);
+			device_set_wakeup_enable(entry->dev, enable);
+		}
 }
 
 static ssize_t
diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c
index bfc31cb..e78c2a5 100644
--- a/drivers/acpi/processor_driver.c
+++ b/drivers/acpi/processor_driver.c
@@ -475,7 +475,7 @@ static __ref int acpi_processor_start(struct acpi_processor *pr)
 	acpi_processor_get_limit_info(pr);
 
 	if (!cpuidle_get_driver() || cpuidle_get_driver() == &acpi_idle_driver)
-		acpi_processor_power_init(pr, device);
+		acpi_processor_power_init(pr);
 
 	pr->cdev = thermal_cooling_device_register("Processor", device,
 						   &processor_cooling_ops);
@@ -509,7 +509,7 @@ err_remove_sysfs_thermal:
 err_thermal_unregister:
 	thermal_cooling_device_unregister(pr->cdev);
 err_power_exit:
-	acpi_processor_power_exit(pr, device);
+	acpi_processor_power_exit(pr);
 
 	return result;
 }
@@ -620,7 +620,7 @@ static int acpi_processor_remove(struct acpi_device *device, int type)
 			return -EINVAL;
 	}
 
-	acpi_processor_power_exit(pr, device);
+	acpi_processor_power_exit(pr);
 
 	sysfs_remove_link(&device->dev.kobj, "sysdev");
 
@@ -905,8 +905,6 @@ static int __init acpi_processor_init(void)
 	if (acpi_disabled)
 		return 0;
 
-	memset(&errata, 0, sizeof(errata));
-
 	result = acpi_bus_register_driver(&acpi_processor_driver);
 	if (result < 0)
 		return result;
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index ad3730b..3655ab9 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -79,6 +79,8 @@ module_param(bm_check_disable, uint, 0000);
 static unsigned int latency_factor __read_mostly = 2;
 module_param(latency_factor, uint, 0644);
 
+static DEFINE_PER_CPU(struct cpuidle_device *, acpi_cpuidle_device);
+
 static int disabled_by_idle_boot_param(void)
 {
 	return boot_option_idle_override == IDLE_POLL ||
@@ -483,8 +485,6 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr)
 		if (obj->type != ACPI_TYPE_INTEGER)
 			continue;
 
-		cx.power = obj->integer.value;
-
 		current_count++;
 		memcpy(&(pr->power.states[current_count]), &cx, sizeof(cx));
 
@@ -1000,7 +1000,7 @@ static int acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr)
 	int i, count = CPUIDLE_DRIVER_STATE_START;
 	struct acpi_processor_cx *cx;
 	struct cpuidle_state_usage *state_usage;
-	struct cpuidle_device *dev = &pr->power.dev;
+	struct cpuidle_device *dev = per_cpu(acpi_cpuidle_device, pr->id);
 
 	if (!pr->flags.power_setup_done)
 		return -EINVAL;
@@ -1132,6 +1132,7 @@ static int acpi_processor_setup_cpuidle_states(struct acpi_processor *pr)
 int acpi_processor_hotplug(struct acpi_processor *pr)
 {
 	int ret = 0;
+	struct cpuidle_device *dev = per_cpu(acpi_cpuidle_device, pr->id);
 
 	if (disabled_by_idle_boot_param())
 		return 0;
@@ -1147,11 +1148,11 @@ int acpi_processor_hotplug(struct acpi_processor *pr)
 		return -ENODEV;
 
 	cpuidle_pause_and_lock();
-	cpuidle_disable_device(&pr->power.dev);
+	cpuidle_disable_device(dev);
 	acpi_processor_get_power_info(pr);
 	if (pr->flags.power) {
 		acpi_processor_setup_cpuidle_cx(pr);
-		ret = cpuidle_enable_device(&pr->power.dev);
+		ret = cpuidle_enable_device(dev);
 	}
 	cpuidle_resume_and_unlock();
 
@@ -1162,6 +1163,7 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr)
 {
 	int cpu;
 	struct acpi_processor *_pr;
+	struct cpuidle_device *dev;
 
 	if (disabled_by_idle_boot_param())
 		return 0;
@@ -1192,7 +1194,8 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr)
 			_pr = per_cpu(processors, cpu);
 			if (!_pr || !_pr->flags.power_setup_done)
 				continue;
-			cpuidle_disable_device(&_pr->power.dev);
+			dev = per_cpu(acpi_cpuidle_device, cpu);
+			cpuidle_disable_device(dev);
 		}
 
 		/* Populate Updated C-state information */
@@ -1206,7 +1209,8 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr)
 			acpi_processor_get_power_info(_pr);
 			if (_pr->flags.power) {
 				acpi_processor_setup_cpuidle_cx(_pr);
-				cpuidle_enable_device(&_pr->power.dev);
+				dev = per_cpu(acpi_cpuidle_device, cpu);
+				cpuidle_enable_device(dev);
 			}
 		}
 		put_online_cpus();
@@ -1218,11 +1222,11 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr)
 
 static int acpi_processor_registered;
 
-int __cpuinit acpi_processor_power_init(struct acpi_processor *pr,
-			      struct acpi_device *device)
+int __cpuinit acpi_processor_power_init(struct acpi_processor *pr)
 {
 	acpi_status status = 0;
 	int retval;
+	struct cpuidle_device *dev;
 	static int first_run;
 
 	if (disabled_by_idle_boot_param())
@@ -1268,11 +1272,18 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr,
 			printk(KERN_DEBUG "ACPI: %s registered with cpuidle\n",
 					acpi_idle_driver.name);
 		}
+
+		dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+		if (!dev)
+			return -ENOMEM;
+		per_cpu(acpi_cpuidle_device, pr->id) = dev;
+
+		acpi_processor_setup_cpuidle_cx(pr);
+
 		/* Register per-cpu cpuidle_device. Cpuidle driver
 		 * must already be registered before registering device
 		 */
-		acpi_processor_setup_cpuidle_cx(pr);
-		retval = cpuidle_register_device(&pr->power.dev);
+		retval = cpuidle_register_device(dev);
 		if (retval) {
 			if (acpi_processor_registered == 0)
 				cpuidle_unregister_driver(&acpi_idle_driver);
@@ -1283,14 +1294,15 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr,
 	return 0;
 }
 
-int acpi_processor_power_exit(struct acpi_processor *pr,
-			      struct acpi_device *device)
+int acpi_processor_power_exit(struct acpi_processor *pr)
 {
+	struct cpuidle_device *dev = per_cpu(acpi_cpuidle_device, pr->id);
+
 	if (disabled_by_idle_boot_param())
 		return 0;
 
 	if (pr->flags.power) {
-		cpuidle_unregister_device(&pr->power.dev);
+		cpuidle_unregister_device(dev);
 		acpi_processor_registered--;
 		if (acpi_processor_registered == 0)
 			cpuidle_unregister_driver(&acpi_idle_driver);
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c
index a093dc1..836bfe0 100644
--- a/drivers/acpi/processor_perflib.c
+++ b/drivers/acpi/processor_perflib.c
@@ -324,6 +324,34 @@ static int acpi_processor_get_performance_control(struct acpi_processor *pr)
 	return result;
 }
 
+#ifdef CONFIG_X86
+/*
+ * Some AMDs have 50MHz frequency multiples, but only provide 100MHz rounding
+ * in their ACPI data. Calculate the real values and fix up the _PSS data.
+ */
+static void amd_fixup_frequency(struct acpi_processor_px *px, int i)
+{
+	u32 hi, lo, fid, did;
+	int index = px->control & 0x00000007;
+
+	if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
+		return;
+
+	if ((boot_cpu_data.x86 == 0x10 && boot_cpu_data.x86_model < 10)
+	    || boot_cpu_data.x86 == 0x11) {
+		rdmsr(MSR_AMD_PSTATE_DEF_BASE + index, lo, hi);
+		fid = lo & 0x3f;
+		did = (lo >> 6) & 7;
+		if (boot_cpu_data.x86 == 0x10)
+			px->core_frequency = (100 * (fid + 0x10)) >> did;
+		else
+			px->core_frequency = (100 * (fid + 8)) >> did;
+	}
+}
+#else
+static void amd_fixup_frequency(struct acpi_processor_px *px, int i) {};
+#endif
+
 static int acpi_processor_get_performance_states(struct acpi_processor *pr)
 {
 	int result = 0;
@@ -379,6 +407,8 @@ static int acpi_processor_get_performance_states(struct acpi_processor *pr)
 			goto end;
 		}
 
+		amd_fixup_frequency(px, i);
+
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
 				  "State [%d]: core_frequency[%d] power[%d] transition_latency[%d] bus_master_latency[%d] control[0x%x] status[0x%x]\n",
 				  i,
diff --git a/drivers/acpi/sbshc.c b/drivers/acpi/sbshc.c
index f8d2a47..cf6129a 100644
--- a/drivers/acpi/sbshc.c
+++ b/drivers/acpi/sbshc.c
@@ -310,23 +310,7 @@ static int acpi_smbus_hc_remove(struct acpi_device *device, int type)
 	return 0;
 }
 
-static int __init acpi_smb_hc_init(void)
-{
-	int result;
-
-	result = acpi_bus_register_driver(&acpi_smb_hc_driver);
-	if (result < 0)
-		return -ENODEV;
-	return 0;
-}
-
-static void __exit acpi_smb_hc_exit(void)
-{
-	acpi_bus_unregister_driver(&acpi_smb_hc_driver);
-}
-
-module_init(acpi_smb_hc_init);
-module_exit(acpi_smb_hc_exit);
+module_acpi_driver(acpi_smb_hc_driver);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Alexey Starikovskiy");
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index d1ecca2..d730a93 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -481,6 +481,8 @@ static int acpi_device_register(struct acpi_device *device)
 	INIT_LIST_HEAD(&device->children);
 	INIT_LIST_HEAD(&device->node);
 	INIT_LIST_HEAD(&device->wakeup_list);
+	INIT_LIST_HEAD(&device->physical_node_list);
+	mutex_init(&device->physical_node_lock);
 
 	new_bus_id = kzalloc(sizeof(struct acpi_device_bus_id), GFP_KERNEL);
 	if (!new_bus_id) {
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index edda74a..1794468 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -708,6 +708,40 @@ static int thermal_get_crit_temp(struct thermal_zone_device *thermal,
 		return -EINVAL;
 }
 
+static int thermal_get_trend(struct thermal_zone_device *thermal,
+				int trip, enum thermal_trend *trend)
+{
+	struct acpi_thermal *tz = thermal->devdata;
+	enum thermal_trip_type type;
+	int i;
+
+	if (thermal_get_trip_type(thermal, trip, &type))
+		return -EINVAL;
+
+	if (type == THERMAL_TRIP_ACTIVE) {
+		/* aggressive active cooling */
+		*trend = THERMAL_TREND_RAISING;
+		return 0;
+	}
+
+	/*
+	 * tz->temperature has already been updated by generic thermal layer,
+	 * before this callback being invoked
+	 */
+	i = (tz->trips.passive.tc1 * (tz->temperature - tz->last_temperature))
+		+ (tz->trips.passive.tc2
+		* (tz->temperature - tz->trips.passive.temperature));
+
+	if (i > 0)
+		*trend = THERMAL_TREND_RAISING;
+	else if (i < 0)
+		*trend = THERMAL_TREND_DROPPING;
+	else
+		*trend = THERMAL_TREND_STABLE;
+	return 0;
+}
+
+
 static int thermal_notify(struct thermal_zone_device *thermal, int trip,
 			   enum thermal_trip_type trip_type)
 {
@@ -731,11 +765,9 @@ static int thermal_notify(struct thermal_zone_device *thermal, int trip,
 	return 0;
 }
 
-typedef int (*cb)(struct thermal_zone_device *, int,
-		  struct thermal_cooling_device *);
 static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal,
 					struct thermal_cooling_device *cdev,
-					cb action)
+					bool bind)
 {
 	struct acpi_device *device = cdev->devdata;
 	struct acpi_thermal *tz = thermal->devdata;
@@ -759,11 +791,19 @@ static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal,
 		    i++) {
 			handle = tz->trips.passive.devices.handles[i];
 			status = acpi_bus_get_device(handle, &dev);
-			if (ACPI_SUCCESS(status) && (dev == device)) {
-				result = action(thermal, trip, cdev);
-				if (result)
-					goto failed;
-			}
+			if (ACPI_FAILURE(status) || dev != device)
+				continue;
+			if (bind)
+				result =
+					thermal_zone_bind_cooling_device
+					(thermal, trip, cdev,
+					 THERMAL_NO_LIMIT, THERMAL_NO_LIMIT);
+			else
+				result =
+					thermal_zone_unbind_cooling_device
+					(thermal, trip, cdev);
+			if (result)
+				goto failed;
 		}
 	}
 
@@ -776,11 +816,17 @@ static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal,
 		    j++) {
 			handle = tz->trips.active[i].devices.handles[j];
 			status = acpi_bus_get_device(handle, &dev);
-			if (ACPI_SUCCESS(status) && (dev == device)) {
-				result = action(thermal, trip, cdev);
-				if (result)
-					goto failed;
-			}
+			if (ACPI_FAILURE(status) || dev != device)
+				continue;
+			if (bind)
+				result = thermal_zone_bind_cooling_device
+					(thermal, trip, cdev,
+					 THERMAL_NO_LIMIT, THERMAL_NO_LIMIT);
+			else
+				result = thermal_zone_unbind_cooling_device
+					(thermal, trip, cdev);
+			if (result)
+				goto failed;
 		}
 	}
 
@@ -788,7 +834,14 @@ static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal,
 		handle = tz->devices.handles[i];
 		status = acpi_bus_get_device(handle, &dev);
 		if (ACPI_SUCCESS(status) && (dev == device)) {
-			result = action(thermal, -1, cdev);
+			if (bind)
+				result = thermal_zone_bind_cooling_device
+						(thermal, -1, cdev,
+						 THERMAL_NO_LIMIT,
+						 THERMAL_NO_LIMIT);
+			else
+				result = thermal_zone_unbind_cooling_device
+						(thermal, -1, cdev);
 			if (result)
 				goto failed;
 		}
@@ -802,16 +855,14 @@ static int
 acpi_thermal_bind_cooling_device(struct thermal_zone_device *thermal,
 					struct thermal_cooling_device *cdev)
 {
-	return acpi_thermal_cooling_device_cb(thermal, cdev,
-				thermal_zone_bind_cooling_device);
+	return acpi_thermal_cooling_device_cb(thermal, cdev, true);
 }
 
 static int
 acpi_thermal_unbind_cooling_device(struct thermal_zone_device *thermal,
 					struct thermal_cooling_device *cdev)
 {
-	return acpi_thermal_cooling_device_cb(thermal, cdev,
-				thermal_zone_unbind_cooling_device);
+	return acpi_thermal_cooling_device_cb(thermal, cdev, false);
 }
 
 static const struct thermal_zone_device_ops acpi_thermal_zone_ops = {
@@ -823,6 +874,7 @@ static const struct thermal_zone_device_ops acpi_thermal_zone_ops = {
 	.get_trip_type = thermal_get_trip_type,
 	.get_trip_temp = thermal_get_trip_temp,
 	.get_crit_temp = thermal_get_crit_temp,
+	.get_trend = thermal_get_trend,
 	.notify = thermal_notify,
 };
 
@@ -848,17 +900,14 @@ static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz)
 	if (tz->trips.passive.flags.valid)
 		tz->thermal_zone =
 			thermal_zone_device_register("acpitz", trips, 0, tz,
-						     &acpi_thermal_zone_ops,
-						     tz->trips.passive.tc1,
-						     tz->trips.passive.tc2,
+						&acpi_thermal_zone_ops, NULL,
 						     tz->trips.passive.tsp*100,
 						     tz->polling_frequency*100);
 	else
 		tz->thermal_zone =
 			thermal_zone_device_register("acpitz", trips, 0, tz,
-						     &acpi_thermal_zone_ops,
-						     0, 0, 0,
-						     tz->polling_frequency*100);
+						&acpi_thermal_zone_ops, NULL,
+						0, tz->polling_frequency*100);
 	if (IS_ERR(tz->thermal_zone))
 		return -ENODEV;
 
diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c
index 3e87c9c..462f7e3 100644
--- a/drivers/acpi/utils.c
+++ b/drivers/acpi/utils.c
@@ -384,7 +384,7 @@ acpi_evaluate_reference(acpi_handle handle,
 EXPORT_SYMBOL(acpi_evaluate_reference);
 
 acpi_status
-acpi_get_physical_device_location(acpi_handle handle, struct acpi_pld *pld)
+acpi_get_physical_device_location(acpi_handle handle, struct acpi_pld_info **pld)
 {
 	acpi_status status;
 	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
@@ -400,13 +400,16 @@ acpi_get_physical_device_location(acpi_handle handle, struct acpi_pld *pld)
 	if (!output || output->type != ACPI_TYPE_PACKAGE
 	    || !output->package.count
 	    || output->package.elements[0].type != ACPI_TYPE_BUFFER
-	    || output->package.elements[0].buffer.length > sizeof(*pld)) {
+	    || output->package.elements[0].buffer.length < ACPI_PLD_REV1_BUFFER_SIZE) {
 		status = AE_TYPE;
 		goto out;
 	}
 
-	memcpy(pld, output->package.elements[0].buffer.pointer,
-	       output->package.elements[0].buffer.length);
+	status = acpi_decode_pld_buffer(
+			output->package.elements[0].buffer.pointer,
+			output->package.elements[0].buffer.length,
+			pld);
+
 out:
 	kfree(buffer.pointer);
 	return status;
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index 27cecd3..e08d322 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -214,6 +214,14 @@ config SATA_DWC_VDEBUG
 	help
 	  This option enables the taskfile dumping and NCQ debugging.
 
+config SATA_HIGHBANK
+	tristate "Calxeda Highbank SATA support"
+	help
+	  This option enables support for the Calxeda Highbank SoC's
+	  onboard SATA.
+
+	  If unsure, say N.
+
 config SATA_MV
 	tristate "Marvell SATA support"
 	help
diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
index a454a13..8b384f1 100644
--- a/drivers/ata/Makefile
+++ b/drivers/ata/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_SATA_FSL)		+= sata_fsl.o
 obj-$(CONFIG_SATA_INIC162X)	+= sata_inic162x.o
 obj-$(CONFIG_SATA_SIL24)	+= sata_sil24.o
 obj-$(CONFIG_SATA_DWC)		+= sata_dwc_460ex.o
+obj-$(CONFIG_SATA_HIGHBANK)	+= sata_highbank.o
 
 # SFF w/ custom DMA
 obj-$(CONFIG_PDC_ADMA)		+= pdc_adma.o
diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
index 57eb1c2..9be4712 100644
--- a/drivers/ata/ahci.h
+++ b/drivers/ata/ahci.h
@@ -35,6 +35,7 @@
 #ifndef _AHCI_H
 #define _AHCI_H
 
+#include <linux/clk.h>
 #include <linux/libata.h>
 
 /* Enclosure Management Control */
@@ -115,6 +116,9 @@ enum {
 	HOST_CAP2_BOH		= (1 << 0),  /* BIOS/OS handoff supported */
 	HOST_CAP2_NVMHCI	= (1 << 1),  /* NVMHCI supported */
 	HOST_CAP2_APST		= (1 << 2),  /* Automatic partial to slumber */
+	HOST_CAP2_SDS		= (1 << 3),  /* Support device sleep */
+	HOST_CAP2_SADM		= (1 << 4),  /* Support aggressive DevSlp */
+	HOST_CAP2_DESO		= (1 << 5),  /* DevSlp from slumber only */
 
 	/* registers for each SATA port */
 	PORT_LST_ADDR		= 0x00, /* command list DMA addr */
@@ -133,6 +137,7 @@ enum {
 	PORT_SCR_ACT		= 0x34, /* SATA phy register: SActive */
 	PORT_SCR_NTF		= 0x3c, /* SATA phy register: SNotification */
 	PORT_FBS		= 0x40, /* FIS-based Switching */
+	PORT_DEVSLP		= 0x44, /* device sleep */
 
 	/* PORT_IRQ_{STAT,MASK} bits */
 	PORT_IRQ_COLD_PRES	= (1 << 31), /* cold presence detect */
@@ -186,6 +191,7 @@ enum {
 	PORT_CMD_ICC_PARTIAL	= (0x2 << 28), /* Put i/f in partial state */
 	PORT_CMD_ICC_SLUMBER	= (0x6 << 28), /* Put i/f in slumber state */
 
+	/* PORT_FBS bits */
 	PORT_FBS_DWE_OFFSET	= 16, /* FBS device with error offset */
 	PORT_FBS_ADO_OFFSET	= 12, /* FBS active dev optimization offset */
 	PORT_FBS_DEV_OFFSET	= 8,  /* FBS device to issue offset */
@@ -194,6 +200,15 @@ enum {
 	PORT_FBS_DEC		= (1 << 1), /* FBS device error clear */
 	PORT_FBS_EN		= (1 << 0), /* Enable FBS */
 
+	/* PORT_DEVSLP bits */
+	PORT_DEVSLP_DM_OFFSET	= 25,             /* DITO multiplier offset */
+	PORT_DEVSLP_DM_MASK	= (0xf << 25),    /* DITO multiplier mask */
+	PORT_DEVSLP_DITO_OFFSET	= 15,             /* DITO offset */
+	PORT_DEVSLP_MDAT_OFFSET	= 10,             /* Minimum assertion time */
+	PORT_DEVSLP_DETO_OFFSET	= 2,              /* DevSlp exit timeout */
+	PORT_DEVSLP_DSP		= (1 << 1),       /* DevSlp present */
+	PORT_DEVSLP_ADSE	= (1 << 0),       /* Aggressive DevSlp enable */
+
 	/* hpriv->flags bits */
 
 #define AHCI_HFLAGS(flags)		.private_data	= (void *)(flags)
@@ -302,6 +317,7 @@ struct ahci_host_priv {
 	u32 			em_loc; /* enclosure management location */
 	u32			em_buf_sz;	/* EM buffer size in byte */
 	u32			em_msg_type;	/* EM message type */
+	struct clk		*clk;		/* Only for platforms supporting clk */
 };
 
 extern int ahci_ignore_sss;
diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
index 09728e0..b1ae480 100644
--- a/drivers/ata/ahci_platform.c
+++ b/drivers/ata/ahci_platform.c
@@ -12,6 +12,7 @@
  * any later version.
  */
 
+#include <linux/clk.h>
 #include <linux/kernel.h>
 #include <linux/gfp.h>
 #include <linux/module.h>
@@ -118,6 +119,17 @@ static int __init ahci_probe(struct platform_device *pdev)
 		return -ENOMEM;
 	}
 
+	hpriv->clk = clk_get(dev, NULL);
+	if (IS_ERR(hpriv->clk)) {
+		dev_err(dev, "can't get clock\n");
+	} else {
+		rc = clk_prepare_enable(hpriv->clk);
+		if (rc) {
+			dev_err(dev, "clock prepare enable failed");
+			goto free_clk;
+		}
+	}
+
 	/*
 	 * Some platforms might need to prepare for mmio region access,
 	 * which could be done in the following init call. So, the mmio
@@ -127,7 +139,7 @@ static int __init ahci_probe(struct platform_device *pdev)
 	if (pdata && pdata->init) {
 		rc = pdata->init(dev, hpriv->mmio);
 		if (rc)
-			return rc;
+			goto disable_unprepare_clk;
 	}
 
 	ahci_save_initial_config(dev, hpriv,
@@ -153,7 +165,7 @@ static int __init ahci_probe(struct platform_device *pdev)
 	host = ata_host_alloc_pinfo(dev, ppi, n_ports);
 	if (!host) {
 		rc = -ENOMEM;
-		goto err0;
+		goto pdata_exit;
 	}
 
 	host->private_data = hpriv;
@@ -183,7 +195,7 @@ static int __init ahci_probe(struct platform_device *pdev)
 
 	rc = ahci_reset_controller(host);
 	if (rc)
-		goto err0;
+		goto pdata_exit;
 
 	ahci_init_controller(host);
 	ahci_print_info(host, "platform");
@@ -191,12 +203,18 @@ static int __init ahci_probe(struct platform_device *pdev)
 	rc = ata_host_activate(host, irq, ahci_interrupt, IRQF_SHARED,
 			       &ahci_platform_sht);
 	if (rc)
-		goto err0;
+		goto pdata_exit;
 
 	return 0;
-err0:
+pdata_exit:
 	if (pdata && pdata->exit)
 		pdata->exit(dev);
+disable_unprepare_clk:
+	if (!IS_ERR(hpriv->clk))
+		clk_disable_unprepare(hpriv->clk);
+free_clk:
+	if (!IS_ERR(hpriv->clk))
+		clk_put(hpriv->clk);
 	return rc;
 }
 
@@ -205,12 +223,18 @@ static int __devexit ahci_remove(struct platform_device *pdev)
 	struct device *dev = &pdev->dev;
 	struct ahci_platform_data *pdata = dev_get_platdata(dev);
 	struct ata_host *host = dev_get_drvdata(dev);
+	struct ahci_host_priv *hpriv = host->private_data;
 
 	ata_host_detach(host);
 
 	if (pdata && pdata->exit)
 		pdata->exit(dev);
 
+	if (!IS_ERR(hpriv->clk)) {
+		clk_disable_unprepare(hpriv->clk);
+		clk_put(hpriv->clk);
+	}
+
 	return 0;
 }
 
@@ -245,6 +269,10 @@ static int ahci_suspend(struct device *dev)
 
 	if (pdata && pdata->suspend)
 		return pdata->suspend(dev);
+
+	if (!IS_ERR(hpriv->clk))
+		clk_disable_unprepare(hpriv->clk);
+
 	return 0;
 }
 
@@ -252,18 +280,27 @@ static int ahci_resume(struct device *dev)
 {
 	struct ahci_platform_data *pdata = dev_get_platdata(dev);
 	struct ata_host *host = dev_get_drvdata(dev);
+	struct ahci_host_priv *hpriv = host->private_data;
 	int rc;
 
+	if (!IS_ERR(hpriv->clk)) {
+		rc = clk_prepare_enable(hpriv->clk);
+		if (rc) {
+			dev_err(dev, "clock prepare enable failed");
+			return rc;
+		}
+	}
+
 	if (pdata && pdata->resume) {
 		rc = pdata->resume(dev);
 		if (rc)
-			return rc;
+			goto disable_unprepare_clk;
 	}
 
 	if (dev->power.power_state.event == PM_EVENT_SUSPEND) {
 		rc = ahci_reset_controller(host);
 		if (rc)
-			return rc;
+			goto disable_unprepare_clk;
 
 		ahci_init_controller(host);
 	}
@@ -271,13 +308,18 @@ static int ahci_resume(struct device *dev)
 	ata_host_resume(host);
 
 	return 0;
+
+disable_unprepare_clk:
+	if (!IS_ERR(hpriv->clk))
+		clk_disable_unprepare(hpriv->clk);
+
+	return rc;
 }
 #endif
 
 SIMPLE_DEV_PM_OPS(ahci_pm_ops, ahci_suspend, ahci_resume);
 
 static const struct of_device_id ahci_of_match[] = {
-	{ .compatible = "calxeda,hb-ahci", },
 	{ .compatible = "snps,spear-ahci", },
 	{},
 };
diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
index 555c07a..4201e53 100644
--- a/drivers/ata/libahci.c
+++ b/drivers/ata/libahci.c
@@ -45,6 +45,7 @@
 #include <scsi/scsi_cmnd.h>
 #include <linux/libata.h>
 #include "ahci.h"
+#include "libata.h"
 
 static int ahci_skip_host_reset;
 int ahci_ignore_sss;
@@ -76,6 +77,7 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc);
 static int ahci_pmp_qc_defer(struct ata_queued_cmd *qc);
 static void ahci_freeze(struct ata_port *ap);
 static void ahci_thaw(struct ata_port *ap);
+static void ahci_set_aggressive_devslp(struct ata_port *ap, bool sleep);
 static void ahci_enable_fbs(struct ata_port *ap);
 static void ahci_disable_fbs(struct ata_port *ap);
 static void ahci_pmp_attach(struct ata_port *ap);
@@ -193,6 +195,10 @@ module_param(ahci_em_messages, int, 0444);
 MODULE_PARM_DESC(ahci_em_messages,
 	"AHCI Enclosure Management Message control (0 = off, 1 = on)");
 
+int devslp_idle_timeout = 1000;	/* device sleep idle timeout in ms */
+module_param(devslp_idle_timeout, int, 0644);
+MODULE_PARM_DESC(devslp_idle_timeout, "device sleep idle timeout");
+
 static void ahci_enable_ahci(void __iomem *mmio)
 {
 	int i;
@@ -702,6 +708,16 @@ static int ahci_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
 		}
 	}
 
+	/* set aggressive device sleep */
+	if ((hpriv->cap2 & HOST_CAP2_SDS) &&
+	    (hpriv->cap2 & HOST_CAP2_SADM) &&
+	    (link->device->flags & ATA_DFLAG_DEVSLP)) {
+		if (policy == ATA_LPM_MIN_POWER)
+			ahci_set_aggressive_devslp(ap, true);
+		else
+			ahci_set_aggressive_devslp(ap, false);
+	}
+
 	if (policy == ATA_LPM_MAX_POWER) {
 		sata_link_scr_lpm(link, policy, false);
 
@@ -1890,6 +1906,81 @@ static void ahci_post_internal_cmd(struct ata_queued_cmd *qc)
 		ahci_kick_engine(ap);
 }
 
+static void ahci_set_aggressive_devslp(struct ata_port *ap, bool sleep)
+{
+	void __iomem *port_mmio = ahci_port_base(ap);
+	struct ata_device *dev = ap->link.device;
+	u32 devslp, dm, dito, mdat, deto;
+	int rc;
+	unsigned int err_mask;
+
+	devslp = readl(port_mmio + PORT_DEVSLP);
+	if (!(devslp & PORT_DEVSLP_DSP)) {
+		dev_err(ap->host->dev, "port does not support device sleep\n");
+		return;
+	}
+
+	/* disable device sleep */
+	if (!sleep) {
+		if (devslp & PORT_DEVSLP_ADSE) {
+			writel(devslp & ~PORT_DEVSLP_ADSE,
+			       port_mmio + PORT_DEVSLP);
+			err_mask = ata_dev_set_feature(dev,
+						       SETFEATURES_SATA_DISABLE,
+						       SATA_DEVSLP);
+			if (err_mask && err_mask != AC_ERR_DEV)
+				ata_dev_warn(dev, "failed to disable DEVSLP\n");
+		}
+		return;
+	}
+
+	/* device sleep was already enabled */
+	if (devslp & PORT_DEVSLP_ADSE)
+		return;
+
+	/* set DITO, MDAT, DETO and enable DevSlp, need to stop engine first */
+	rc = ahci_stop_engine(ap);
+	if (rc)
+		return;
+
+	dm = (devslp & PORT_DEVSLP_DM_MASK) >> PORT_DEVSLP_DM_OFFSET;
+	dito = devslp_idle_timeout / (dm + 1);
+	if (dito > 0x3ff)
+		dito = 0x3ff;
+
+	/* Use the nominal value 10 ms if the read MDAT is zero,
+	 * the nominal value of DETO is 20 ms.
+	 */
+	if (dev->sata_settings[ATA_LOG_DEVSLP_VALID] &
+	    ATA_LOG_DEVSLP_VALID_MASK) {
+		mdat = dev->sata_settings[ATA_LOG_DEVSLP_MDAT] &
+		       ATA_LOG_DEVSLP_MDAT_MASK;
+		if (!mdat)
+			mdat = 10;
+		deto = dev->sata_settings[ATA_LOG_DEVSLP_DETO];
+		if (!deto)
+			deto = 20;
+	} else {
+		mdat = 10;
+		deto = 20;
+	}
+
+	devslp |= ((dito << PORT_DEVSLP_DITO_OFFSET) |
+		   (mdat << PORT_DEVSLP_MDAT_OFFSET) |
+		   (deto << PORT_DEVSLP_DETO_OFFSET) |
+		   PORT_DEVSLP_ADSE);
+	writel(devslp, port_mmio + PORT_DEVSLP);
+
+	ahci_start_engine(ap);
+
+	/* enable device sleep feature for the drive */
+	err_mask = ata_dev_set_feature(dev,
+				       SETFEATURES_SATA_ENABLE,
+				       SATA_DEVSLP);
+	if (err_mask && err_mask != AC_ERR_DEV)
+		ata_dev_warn(dev, "failed to enable DEVSLP\n");
+}
+
 static void ahci_enable_fbs(struct ata_port *ap)
 {
 	struct ahci_port_priv *pp = ap->private_data;
@@ -2164,7 +2255,8 @@ void ahci_print_info(struct ata_host *host, const char *scc_s)
 		"flags: "
 		"%s%s%s%s%s%s%s"
 		"%s%s%s%s%s%s%s"
-		"%s%s%s%s%s%s\n"
+		"%s%s%s%s%s%s%s"
+		"%s%s\n"
 		,
 
 		cap & HOST_CAP_64 ? "64bit " : "",
@@ -2184,6 +2276,9 @@ void ahci_print_info(struct ata_host *host, const char *scc_s)
 		cap & HOST_CAP_CCC ? "ccc " : "",
 		cap & HOST_CAP_EMS ? "ems " : "",
 		cap & HOST_CAP_SXS ? "sxs " : "",
+		cap2 & HOST_CAP2_DESO ? "deso " : "",
+		cap2 & HOST_CAP2_SADM ? "sadm " : "",
+		cap2 & HOST_CAP2_SDS ? "sds " : "",
 		cap2 & HOST_CAP2_APST ? "apst " : "",
 		cap2 & HOST_CAP2_NVMHCI ? "nvmp " : "",
 		cap2 & HOST_CAP2_BOH ? "boh " : ""
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 8e1039c..3cc7096 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -774,7 +774,7 @@ int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev,
 		tf->lbam = (block >> 8) & 0xff;
 		tf->lbal = block & 0xff;
 
-		tf->device = 1 << 6;
+		tf->device = ATA_LBA;
 		if (tf->flags & ATA_TFLAG_FUA)
 			tf->device |= 1 << 7;
 	} else if (dev->flags & ATA_DFLAG_LBA) {
@@ -2155,6 +2155,7 @@ int ata_dev_configure(struct ata_device *dev)
 	int print_info = ehc->i.flags & ATA_EHI_PRINTINFO;
 	const u16 *id = dev->id;
 	unsigned long xfer_mask;
+	unsigned int err_mask;
 	char revbuf[7];		/* XYZ-99\0 */
 	char fwrevbuf[ATA_ID_FW_REV_LEN+1];
 	char modelbuf[ATA_ID_PROD_LEN+1];
@@ -2323,6 +2324,26 @@ int ata_dev_configure(struct ata_device *dev)
 			}
 		}
 
+		/* check and mark DevSlp capability */
+		if (ata_id_has_devslp(dev->id))
+			dev->flags |= ATA_DFLAG_DEVSLP;
+
+		/* Obtain SATA Settings page from Identify Device Data Log,
+		 * which contains DevSlp timing variables etc.
+		 * Exclude old devices with ata_id_has_ncq()
+		 */
+		if (ata_id_has_ncq(dev->id)) {
+			err_mask = ata_read_log_page(dev,
+						     ATA_LOG_SATA_ID_DEV_DATA,
+						     ATA_LOG_SATA_SETTINGS,
+						     dev->sata_settings,
+						     1);
+			if (err_mask)
+				ata_dev_dbg(dev,
+					    "failed to get Identify Device Data, Emask 0x%x\n",
+					    err_mask);
+		}
+
 		dev->cdb_len = 16;
 	}
 
@@ -2351,8 +2372,6 @@ int ata_dev_configure(struct ata_device *dev)
 		    (ap->flags & ATA_FLAG_AN) && ata_id_has_atapi_AN(id) &&
 		    (!sata_pmp_attached(ap) ||
 		     sata_scr_read(&ap->link, SCR_NOTIFICATION, &sntf) == 0)) {
-			unsigned int err_mask;
-
 			/* issue SET feature command to turn this on */
 			err_mask = ata_dev_set_feature(dev,
 					SETFEATURES_SATA_ENABLE, SATA_AN);
@@ -3598,7 +3617,7 @@ int sata_link_scr_lpm(struct ata_link *link, enum ata_lpm_policy policy,
 	switch (policy) {
 	case ATA_LPM_MAX_POWER:
 		/* disable all LPM transitions */
-		scontrol |= (0x3 << 8);
+		scontrol |= (0x7 << 8);
 		/* initiate transition to active state */
 		if (spm_wakeup) {
 			scontrol |= (0x4 << 12);
@@ -3608,12 +3627,12 @@ int sata_link_scr_lpm(struct ata_link *link, enum ata_lpm_policy policy,
 	case ATA_LPM_MED_POWER:
 		/* allow LPM to PARTIAL */
 		scontrol &= ~(0x1 << 8);
-		scontrol |= (0x2 << 8);
+		scontrol |= (0x6 << 8);
 		break;
 	case ATA_LPM_MIN_POWER:
 		if (ata_link_nr_enabled(link) > 0)
 			/* no restrictions on LPM transitions */
-			scontrol &= ~(0x3 << 8);
+			scontrol &= ~(0x7 << 8);
 		else {
 			/* empty port, power off */
 			scontrol &= ~0xf;
@@ -4472,6 +4491,7 @@ unsigned int ata_dev_set_feature(struct ata_device *dev, u8 enable, u8 feature)
 	DPRINTK("EXIT, err_mask=%x\n", err_mask);
 	return err_mask;
 }
+EXPORT_SYMBOL_GPL(ata_dev_set_feature);
 
 /**
  *	ata_dev_init_params - Issue INIT DEV PARAMS command
@@ -5253,16 +5273,20 @@ bool ata_link_offline(struct ata_link *link)
 #ifdef CONFIG_PM
 static int ata_port_request_pm(struct ata_port *ap, pm_message_t mesg,
 			       unsigned int action, unsigned int ehi_flags,
-			       int wait)
+			       int *async)
 {
 	struct ata_link *link;
 	unsigned long flags;
-	int rc;
+	int rc = 0;
 
 	/* Previous resume operation might still be in
 	 * progress.  Wait for PM_PENDING to clear.
 	 */
 	if (ap->pflags & ATA_PFLAG_PM_PENDING) {
+		if (async) {
+			*async = -EAGAIN;
+			return 0;
+		}
 		ata_port_wait_eh(ap);
 		WARN_ON(ap->pflags & ATA_PFLAG_PM_PENDING);
 	}
@@ -5271,10 +5295,10 @@ static int ata_port_request_pm(struct ata_port *ap, pm_message_t mesg,
 	spin_lock_irqsave(ap->lock, flags);
 
 	ap->pm_mesg = mesg;
-	if (wait) {
-		rc = 0;
+	if (async)
+		ap->pm_result = async;
+	else
 		ap->pm_result = &rc;
-	}
 
 	ap->pflags |= ATA_PFLAG_PM_PENDING;
 	ata_for_each_link(link, ap, HOST_FIRST) {
@@ -5287,7 +5311,7 @@ static int ata_port_request_pm(struct ata_port *ap, pm_message_t mesg,
 	spin_unlock_irqrestore(ap->lock, flags);
 
 	/* wait and check result */
-	if (wait) {
+	if (!async) {
 		ata_port_wait_eh(ap);
 		WARN_ON(ap->pflags & ATA_PFLAG_PM_PENDING);
 	}
@@ -5295,9 +5319,8 @@ static int ata_port_request_pm(struct ata_port *ap, pm_message_t mesg,
 	return rc;
 }
 
-static int ata_port_suspend_common(struct device *dev, pm_message_t mesg)
+static int __ata_port_suspend_common(struct ata_port *ap, pm_message_t mesg, int *async)
 {
-	struct ata_port *ap = to_ata_port(dev);
 	unsigned int ehi_flags = ATA_EHI_QUIET;
 	int rc;
 
@@ -5312,10 +5335,17 @@ static int ata_port_suspend_common(struct device *dev, pm_message_t mesg)
 	if (mesg.event == PM_EVENT_SUSPEND)
 		ehi_flags |= ATA_EHI_NO_AUTOPSY | ATA_EHI_NO_RECOVERY;
 
-	rc = ata_port_request_pm(ap, mesg, 0, ehi_flags, 1);
+	rc = ata_port_request_pm(ap, mesg, 0, ehi_flags, async);
 	return rc;
 }
 
+static int ata_port_suspend_common(struct device *dev, pm_message_t mesg)
+{
+	struct ata_port *ap = to_ata_port(dev);
+
+	return __ata_port_suspend_common(ap, mesg, NULL);
+}
+
 static int ata_port_suspend(struct device *dev)
 {
 	if (pm_runtime_suspended(dev))
@@ -5340,16 +5370,22 @@ static int ata_port_poweroff(struct device *dev)
 	return ata_port_suspend_common(dev, PMSG_HIBERNATE);
 }
 
-static int ata_port_resume_common(struct device *dev)
+static int __ata_port_resume_common(struct ata_port *ap, int *async)
 {
-	struct ata_port *ap = to_ata_port(dev);
 	int rc;
 
 	rc = ata_port_request_pm(ap, PMSG_ON, ATA_EH_RESET,
-		ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET, 1);
+		ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET, async);
 	return rc;
 }
 
+static int ata_port_resume_common(struct device *dev)
+{
+	struct ata_port *ap = to_ata_port(dev);
+
+	return __ata_port_resume_common(ap, NULL);
+}
+
 static int ata_port_resume(struct device *dev)
 {
 	int rc;
@@ -5382,6 +5418,24 @@ static const struct dev_pm_ops ata_port_pm_ops = {
 	.runtime_idle = ata_port_runtime_idle,
 };
 
+/* sas ports don't participate in pm runtime management of ata_ports,
+ * and need to resume ata devices at the domain level, not the per-port
+ * level. sas suspend/resume is async to allow parallel port recovery
+ * since sas has multiple ata_port instances per Scsi_Host.
+ */
+int ata_sas_port_async_suspend(struct ata_port *ap, int *async)
+{
+	return __ata_port_suspend_common(ap, PMSG_SUSPEND, async);
+}
+EXPORT_SYMBOL_GPL(ata_sas_port_async_suspend);
+
+int ata_sas_port_async_resume(struct ata_port *ap, int *async)
+{
+	return __ata_port_resume_common(ap, async);
+}
+EXPORT_SYMBOL_GPL(ata_sas_port_async_resume);
+
+
 /**
  *	ata_host_suspend - suspend host
  *	@host: host to suspend
@@ -5927,24 +5981,18 @@ int ata_host_start(struct ata_host *host)
 }
 
 /**
- *	ata_sas_host_init - Initialize a host struct
+ *	ata_sas_host_init - Initialize a host struct for sas (ipr, libsas)
  *	@host:	host to initialize
  *	@dev:	device host is attached to
- *	@flags:	host flags
  *	@ops:	port_ops
  *
- *	LOCKING:
- *	PCI/etc. bus probe sem.
- *
  */
-/* KILLME - the only user left is ipr */
 void ata_host_init(struct ata_host *host, struct device *dev,
-		   unsigned long flags, struct ata_port_operations *ops)
+		   struct ata_port_operations *ops)
 {
 	spin_lock_init(&host->lock);
 	mutex_init(&host->eh_mutex);
 	host->dev = dev;
-	host->flags = flags;
 	host->ops = ops;
 }
 
@@ -6388,6 +6436,7 @@ static int __init ata_parse_force_one(char **cur,
 		{ "nohrst",	.lflags		= ATA_LFLAG_NO_HRST },
 		{ "nosrst",	.lflags		= ATA_LFLAG_NO_SRST },
 		{ "norst",	.lflags		= ATA_LFLAG_NO_HRST | ATA_LFLAG_NO_SRST },
+		{ "rstonce",	.lflags		= ATA_LFLAG_RST_ONCE },
 	};
 	char *start = *cur, *p = *cur;
 	char *id, *val, *endp;
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 7d4535e..e60437c 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -1487,6 +1487,7 @@ static const char *ata_err_string(unsigned int err_mask)
 /**
  *	ata_read_log_page - read a specific log page
  *	@dev: target device
+ *	@log: log to read
  *	@page: page to read
  *	@buf: buffer to store read page
  *	@sectors: number of sectors to read
@@ -1499,17 +1500,18 @@ static const char *ata_err_string(unsigned int err_mask)
  *	RETURNS:
  *	0 on success, AC_ERR_* mask otherwise.
  */
-static unsigned int ata_read_log_page(struct ata_device *dev,
-				      u8 page, void *buf, unsigned int sectors)
+unsigned int ata_read_log_page(struct ata_device *dev, u8 log,
+			       u8 page, void *buf, unsigned int sectors)
 {
 	struct ata_taskfile tf;
 	unsigned int err_mask;
 
-	DPRINTK("read log page - page %d\n", page);
+	DPRINTK("read log page - log 0x%x, page 0x%x\n", log, page);
 
 	ata_tf_init(dev, &tf);
 	tf.command = ATA_CMD_READ_LOG_EXT;
-	tf.lbal = page;
+	tf.lbal = log;
+	tf.lbam = page;
 	tf.nsect = sectors;
 	tf.hob_nsect = sectors >> 8;
 	tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_LBA48 | ATA_TFLAG_DEVICE;
@@ -1545,7 +1547,7 @@ static int ata_eh_read_log_10h(struct ata_device *dev,
 	u8 csum;
 	int i;
 
-	err_mask = ata_read_log_page(dev, ATA_LOG_SATA_NCQ, buf, 1);
+	err_mask = ata_read_log_page(dev, ATA_LOG_SATA_NCQ, 0, buf, 1);
 	if (err_mask)
 		return -EIO;
 
@@ -2623,6 +2625,8 @@ int ata_eh_reset(struct ata_link *link, int classify,
 	 */
 	while (ata_eh_reset_timeouts[max_tries] != ULONG_MAX)
 		max_tries++;
+	if (link->flags & ATA_LFLAG_RST_ONCE)
+		max_tries = 1;
 	if (link->flags & ATA_LFLAG_NO_HRST)
 		hardreset = NULL;
 	if (link->flags & ATA_LFLAG_NO_SRST)
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 8ec81ca..e3bda07 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -1655,7 +1655,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc)
 		if (unlikely(scmd->cmd_len < 10))
 			goto invalid_fld;
 		scsi_10_lba_len(cdb, &block, &n_block);
-		if (unlikely(cdb[1] & (1 << 3)))
+		if (cdb[1] & (1 << 3))
 			tf_flags |= ATA_TFLAG_FUA;
 		break;
 	case READ_6:
@@ -1675,7 +1675,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc)
 		if (unlikely(scmd->cmd_len < 16))
 			goto invalid_fld;
 		scsi_16_lba_len(cdb, &block, &n_block);
-		if (unlikely(cdb[1] & (1 << 3)))
+		if (cdb[1] & (1 << 3))
 			tf_flags |= ATA_TFLAG_FUA;
 		break;
 	default:
@@ -2205,9 +2205,33 @@ static unsigned int ata_scsiop_noop(struct ata_scsi_args *args, u8 *rbuf)
 }
 
 /**
+ *	modecpy - Prepare response for MODE SENSE
+ *	@dest: output buffer
+ *	@src: data being copied
+ *	@n: length of mode page
+ *	@changeable: whether changeable parameters are requested
+ *
+ *	Generate a generic MODE SENSE page for either current or changeable
+ *	parameters.
+ *
+ *	LOCKING:
+ *	None.
+ */
+static void modecpy(u8 *dest, const u8 *src, int n, bool changeable)
+{
+	if (changeable) {
+		memcpy(dest, src, 2);
+		memset(dest + 2, 0, n - 2);
+	} else {
+		memcpy(dest, src, n);
+	}
+}
+
+/**
  *	ata_msense_caching - Simulate MODE SENSE caching info page
  *	@id: device IDENTIFY data
  *	@buf: output buffer
+ *	@changeable: whether changeable parameters are requested
  *
  *	Generate a caching info page, which conditionally indicates
  *	write caching to the SCSI layer, depending on device
@@ -2216,12 +2240,12 @@ static unsigned int ata_scsiop_noop(struct ata_scsi_args *args, u8 *rbuf)
  *	LOCKING:
  *	None.
  */
-static unsigned int ata_msense_caching(u16 *id, u8 *buf)
+static unsigned int ata_msense_caching(u16 *id, u8 *buf, bool changeable)
 {
-	memcpy(buf, def_cache_mpage, sizeof(def_cache_mpage));
-	if (ata_id_wcache_enabled(id))
+	modecpy(buf, def_cache_mpage, sizeof(def_cache_mpage), changeable);
+	if (changeable || ata_id_wcache_enabled(id))
 		buf[2] |= (1 << 2);	/* write cache enable */
-	if (!ata_id_rahead_enabled(id))
+	if (!changeable && !ata_id_rahead_enabled(id))
 		buf[12] |= (1 << 5);	/* disable read ahead */
 	return sizeof(def_cache_mpage);
 }
@@ -2229,30 +2253,33 @@ static unsigned int ata_msense_caching(u16 *id, u8 *buf)
 /**
  *	ata_msense_ctl_mode - Simulate MODE SENSE control mode page
  *	@buf: output buffer
+ *	@changeable: whether changeable parameters are requested
  *
  *	Generate a generic MODE SENSE control mode page.
  *
  *	LOCKING:
  *	None.
  */
-static unsigned int ata_msense_ctl_mode(u8 *buf)
+static unsigned int ata_msense_ctl_mode(u8 *buf, bool changeable)
 {
-	memcpy(buf, def_control_mpage, sizeof(def_control_mpage));
+	modecpy(buf, def_control_mpage, sizeof(def_control_mpage), changeable);
 	return sizeof(def_control_mpage);
 }
 
 /**
  *	ata_msense_rw_recovery - Simulate MODE SENSE r/w error recovery page
  *	@buf: output buffer
+ *	@changeable: whether changeable parameters are requested
  *
  *	Generate a generic MODE SENSE r/w error recovery page.
  *
  *	LOCKING:
  *	None.
  */
-static unsigned int ata_msense_rw_recovery(u8 *buf)
+static unsigned int ata_msense_rw_recovery(u8 *buf, bool changeable)
 {
-	memcpy(buf, def_rw_recovery_mpage, sizeof(def_rw_recovery_mpage));
+	modecpy(buf, def_rw_recovery_mpage, sizeof(def_rw_recovery_mpage),
+		changeable);
 	return sizeof(def_rw_recovery_mpage);
 }
 
@@ -2316,11 +2343,11 @@ static unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf)
 	page_control = scsicmd[2] >> 6;
 	switch (page_control) {
 	case 0: /* current */
+	case 1: /* changeable */
+	case 2: /* defaults */
 		break;  /* supported */
 	case 3: /* saved */
 		goto saving_not_supp;
-	case 1: /* changeable */
-	case 2: /* defaults */
 	default:
 		goto invalid_fld;
 	}
@@ -2341,21 +2368,21 @@ static unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf)
 
 	switch(pg) {
 	case RW_RECOVERY_MPAGE:
-		p += ata_msense_rw_recovery(p);
+		p += ata_msense_rw_recovery(p, page_control == 1);
 		break;
 
 	case CACHE_MPAGE:
-		p += ata_msense_caching(args->id, p);
+		p += ata_msense_caching(args->id, p, page_control == 1);
 		break;
 
 	case CONTROL_MPAGE:
-		p += ata_msense_ctl_mode(p);
+		p += ata_msense_ctl_mode(p, page_control == 1);
 		break;
 
 	case ALL_MPAGES:
-		p += ata_msense_rw_recovery(p);
-		p += ata_msense_caching(args->id, p);
-		p += ata_msense_ctl_mode(p);
+		p += ata_msense_rw_recovery(p, page_control == 1);
+		p += ata_msense_caching(args->id, p, page_control == 1);
+		p += ata_msense_ctl_mode(p, page_control == 1);
 		break;
 
 	default:		/* invalid page code */
@@ -3080,6 +3107,188 @@ static unsigned int ata_scsi_write_same_xlat(struct ata_queued_cmd *qc)
 }
 
 /**
+ *	ata_mselect_caching - Simulate MODE SELECT for caching info page
+ *	@qc: Storage for translated ATA taskfile
+ *	@buf: input buffer
+ *	@len: number of valid bytes in the input buffer
+ *
+ *	Prepare a taskfile to modify caching information for the device.
+ *
+ *	LOCKING:
+ *	None.
+ */
+static int ata_mselect_caching(struct ata_queued_cmd *qc,
+			       const u8 *buf, int len)
+{
+	struct ata_taskfile *tf = &qc->tf;
+	struct ata_device *dev = qc->dev;
+	char mpage[CACHE_MPAGE_LEN];
+	u8 wce;
+
+	/*
+	 * The first two bytes of def_cache_mpage are a header, so offsets
+	 * in mpage are off by 2 compared to buf.  Same for len.
+	 */
+
+	if (len != CACHE_MPAGE_LEN - 2)
+		return -EINVAL;
+
+	wce = buf[0] & (1 << 2);
+
+	/*
+	 * Check that read-only bits are not modified.
+	 */
+	ata_msense_caching(dev->id, mpage, false);
+	mpage[2] &= ~(1 << 2);
+	mpage[2] |= wce;
+	if (memcmp(mpage + 2, buf, CACHE_MPAGE_LEN - 2) != 0)
+		return -EINVAL;
+
+	tf->flags |= ATA_TFLAG_DEVICE | ATA_TFLAG_ISADDR;
+	tf->protocol = ATA_PROT_NODATA;
+	tf->nsect = 0;
+	tf->command = ATA_CMD_SET_FEATURES;
+	tf->feature = wce ? SETFEATURES_WC_ON : SETFEATURES_WC_OFF;
+	return 0;
+}
+
+/**
+ *	ata_scsiop_mode_select - Simulate MODE SELECT 6, 10 commands
+ *	@qc: Storage for translated ATA taskfile
+ *
+ *	Converts a MODE SELECT command to an ATA SET FEATURES taskfile.
+ *	Assume this is invoked for direct access devices (e.g. disks) only.
+ *	There should be no block descriptor for other device types.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host lock)
+ */
+static unsigned int ata_scsi_mode_select_xlat(struct ata_queued_cmd *qc)
+{
+	struct scsi_cmnd *scmd = qc->scsicmd;
+	const u8 *cdb = scmd->cmnd;
+	const u8 *p;
+	u8 pg, spg;
+	unsigned six_byte, pg_len, hdr_len, bd_len;
+	int len;
+
+	VPRINTK("ENTER\n");
+
+	six_byte = (cdb[0] == MODE_SELECT);
+	if (six_byte) {
+		if (scmd->cmd_len < 5)
+			goto invalid_fld;
+
+		len = cdb[4];
+		hdr_len = 4;
+	} else {
+		if (scmd->cmd_len < 9)
+			goto invalid_fld;
+
+		len = (cdb[7] << 8) + cdb[8];
+		hdr_len = 8;
+	}
+
+	/* We only support PF=1, SP=0.  */
+	if ((cdb[1] & 0x11) != 0x10)
+		goto invalid_fld;
+
+	/* Test early for possible overrun.  */
+	if (!scsi_sg_count(scmd) || scsi_sglist(scmd)->length < len)
+		goto invalid_param_len;
+
+	p = page_address(sg_page(scsi_sglist(scmd)));
+
+	/* Move past header and block descriptors.  */
+	if (len < hdr_len)
+		goto invalid_param_len;
+
+	if (six_byte)
+		bd_len = p[3];
+	else
+		bd_len = (p[6] << 8) + p[7];
+
+	len -= hdr_len;
+	p += hdr_len;
+	if (len < bd_len)
+		goto invalid_param_len;
+	if (bd_len != 0 && bd_len != 8)
+		goto invalid_param;
+
+	len -= bd_len;
+	p += bd_len;
+	if (len == 0)
+		goto skip;
+
+	/* Parse both possible formats for the mode page headers.  */
+	pg = p[0] & 0x3f;
+	if (p[0] & 0x40) {
+		if (len < 4)
+			goto invalid_param_len;
+
+		spg = p[1];
+		pg_len = (p[2] << 8) | p[3];
+		p += 4;
+		len -= 4;
+	} else {
+		if (len < 2)
+			goto invalid_param_len;
+
+		spg = 0;
+		pg_len = p[1];
+		p += 2;
+		len -= 2;
+	}
+
+	/*
+	 * No mode subpages supported (yet) but asking for _all_
+	 * subpages may be valid
+	 */
+	if (spg && (spg != ALL_SUB_MPAGES))
+		goto invalid_param;
+	if (pg_len > len)
+		goto invalid_param_len;
+
+	switch (pg) {
+	case CACHE_MPAGE:
+		if (ata_mselect_caching(qc, p, pg_len) < 0)
+			goto invalid_param;
+		break;
+
+	default:		/* invalid page code */
+		goto invalid_param;
+	}
+
+	/*
+	 * Only one page has changeable data, so we only support setting one
+	 * page at a time.
+	 */
+	if (len > pg_len)
+		goto invalid_param;
+
+	return 0;
+
+ invalid_fld:
+	/* "Invalid field in CDB" */
+	ata_scsi_set_sense(scmd, ILLEGAL_REQUEST, 0x24, 0x0);
+	return 1;
+
+ invalid_param:
+	/* "Invalid field in parameter list" */
+	ata_scsi_set_sense(scmd, ILLEGAL_REQUEST, 0x26, 0x0);
+	return 1;
+
+ invalid_param_len:
+	/* "Parameter list length error" */
+	ata_scsi_set_sense(scmd, ILLEGAL_REQUEST, 0x1a, 0x0);
+	return 1;
+
+ skip:
+	scmd->result = SAM_STAT_GOOD;
+	return 1;
+}
+
+/**
  *	ata_get_xlat_func - check if SCSI to ATA translation is possible
  *	@dev: ATA device
  *	@cmd: SCSI command opcode to consider
@@ -3119,6 +3328,11 @@ static inline ata_xlat_func_t ata_get_xlat_func(struct ata_device *dev, u8 cmd)
 	case ATA_16:
 		return ata_scsi_pass_thru;
 
+	case MODE_SELECT:
+	case MODE_SELECT_10:
+		return ata_scsi_mode_select_xlat;
+		break;
+
 	case START_STOP:
 		return ata_scsi_start_stop_xlat;
 	}
@@ -3311,11 +3525,6 @@ void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd)
 		ata_scsi_rbuf_fill(&args, ata_scsiop_mode_sense);
 		break;
 
-	case MODE_SELECT:	/* unconditionally return */
-	case MODE_SELECT_10:	/* bad-field-in-cdb */
-		ata_scsi_invalid_field(cmd);
-		break;
-
 	case READ_CAPACITY:
 		ata_scsi_rbuf_fill(&args, ata_scsiop_read_cap);
 		break;
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
index 50e4dff..7148a58 100644
--- a/drivers/ata/libata.h
+++ b/drivers/ata/libata.h
@@ -165,6 +165,8 @@ extern void ata_eh_about_to_do(struct ata_link *link, struct ata_device *dev,
 			       unsigned int action);
 extern void ata_eh_done(struct ata_link *link, struct ata_device *dev,
 			unsigned int action);
+extern unsigned int ata_read_log_page(struct ata_device *dev, u8 log,
+				      u8 page, void *buf, unsigned int sectors);
 extern void ata_eh_autopsy(struct ata_port *ap);
 const char *ata_get_cmd_descript(u8 command);
 extern void ata_eh_report(struct ata_port *ap);
diff --git a/drivers/ata/pata_arasan_cf.c b/drivers/ata/pata_arasan_cf.c
index bfaa5cb..26201eb 100644
--- a/drivers/ata/pata_arasan_cf.c
+++ b/drivers/ata/pata_arasan_cf.c
@@ -31,6 +31,7 @@
 #include <linux/kernel.h>
 #include <linux/libata.h>
 #include <linux/module.h>
+#include <linux/of.h>
 #include <linux/pata_arasan_cf_data.h>
 #include <linux/platform_device.h>
 #include <linux/pm.h>
@@ -310,7 +311,7 @@ static int cf_init(struct arasan_cf_dev *acdev)
 	unsigned long flags;
 	int ret = 0;
 
-	ret = clk_enable(acdev->clk);
+	ret = clk_prepare_enable(acdev->clk);
 	if (ret) {
 		dev_dbg(acdev->host->dev, "clock enable failed");
 		return ret;
@@ -340,7 +341,7 @@ static void cf_exit(struct arasan_cf_dev *acdev)
 	writel(readl(acdev->vbase + OP_MODE) & ~CFHOST_ENB,
 			acdev->vbase + OP_MODE);
 	spin_unlock_irqrestore(&acdev->host->lock, flags);
-	clk_disable(acdev->clk);
+	clk_disable_unprepare(acdev->clk);
 }
 
 static void dma_callback(void *dev)
@@ -935,6 +936,14 @@ static int arasan_cf_resume(struct device *dev)
 
 static SIMPLE_DEV_PM_OPS(arasan_cf_pm_ops, arasan_cf_suspend, arasan_cf_resume);
 
+#ifdef CONFIG_OF
+static const struct of_device_id arasan_cf_id_table[] = {
+	{ .compatible = "arasan,cf-spear1340" },
+	{}
+};
+MODULE_DEVICE_TABLE(of, arasan_cf_id_table);
+#endif
+
 static struct platform_driver arasan_cf_driver = {
 	.probe		= arasan_cf_probe,
 	.remove		= __devexit_p(arasan_cf_remove),
@@ -942,6 +951,7 @@ static struct platform_driver arasan_cf_driver = {
 		.name	= DRIVER_NAME,
 		.owner	= THIS_MODULE,
 		.pm	= &arasan_cf_pm_ops,
+		.of_match_table = of_match_ptr(arasan_cf_id_table),
 	},
 };
 
diff --git a/drivers/ata/pata_ep93xx.c b/drivers/ata/pata_ep93xx.c
index 6ef2e37..e056406 100644
--- a/drivers/ata/pata_ep93xx.c
+++ b/drivers/ata/pata_ep93xx.c
@@ -43,7 +43,7 @@
 #include <linux/dmaengine.h>
 #include <linux/ktime.h>
 
-#include <mach/dma.h>
+#include <linux/platform_data/dma-ep93xx.h>
 #include <mach/platform.h>
 
 #define DRV_NAME	"ep93xx-ide"
diff --git a/drivers/ata/pata_pxa.c b/drivers/ata/pata_pxa.c
index 0bb0fb7..4b8ba55 100644
--- a/drivers/ata/pata_pxa.c
+++ b/drivers/ata/pata_pxa.c
@@ -32,7 +32,7 @@
 #include <scsi/scsi_host.h>
 
 #include <mach/pxa2xx-regs.h>
-#include <mach/pata_pxa.h>
+#include <linux/platform_data/ata-pxa.h>
 #include <mach/dma.h>
 
 #define DRV_NAME	"pata_pxa"
diff --git a/drivers/ata/pata_samsung_cf.c b/drivers/ata/pata_samsung_cf.c
index 1b372c2..63ffb00 100644
--- a/drivers/ata/pata_samsung_cf.c
+++ b/drivers/ata/pata_samsung_cf.c
@@ -23,7 +23,7 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 
-#include <plat/ata.h>
+#include <linux/platform_data/ata-samsung_cf.h>
 #include <plat/regs-ata.h>
 
 #define DRV_NAME "pata_samsung_cf"
diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c
index d6577b9..124b2c1 100644
--- a/drivers/ata/sata_fsl.c
+++ b/drivers/ata/sata_fsl.c
@@ -123,6 +123,7 @@ enum {
 	ONLINE = (1 << 31),
 	GOING_OFFLINE = (1 << 30),
 	BIST_ERR = (1 << 29),
+	CLEAR_ERROR = (1 << 27),
 
 	FATAL_ERR_HC_MASTER_ERR = (1 << 18),
 	FATAL_ERR_PARITY_ERR_TX = (1 << 17),
@@ -143,6 +144,7 @@ enum {
 	    FATAL_ERR_CRC_ERR_RX |
 	    FATAL_ERR_FIFO_OVRFL_TX | FATAL_ERR_FIFO_OVRFL_RX,
 
+	INT_ON_DATA_LENGTH_MISMATCH = (1 << 12),
 	INT_ON_FATAL_ERR = (1 << 5),
 	INT_ON_PHYRDY_CHG = (1 << 4),
 
@@ -1181,25 +1183,54 @@ static void sata_fsl_host_intr(struct ata_port *ap)
 	u32 hstatus, done_mask = 0;
 	struct ata_queued_cmd *qc;
 	u32 SError;
+	u32 tag;
+	u32 status_mask = INT_ON_ERROR;
 
 	hstatus = ioread32(hcr_base + HSTATUS);
 
 	sata_fsl_scr_read(&ap->link, SCR_ERROR, &SError);
 
+	/* Read command completed register */
+	done_mask = ioread32(hcr_base + CC);
+
+	/* Workaround for data length mismatch errata */
+	if (unlikely(hstatus & INT_ON_DATA_LENGTH_MISMATCH)) {
+		for (tag = 0; tag < ATA_MAX_QUEUE; tag++) {
+			qc = ata_qc_from_tag(ap, tag);
+			if (qc && ata_is_atapi(qc->tf.protocol)) {
+				u32 hcontrol;
+				/* Set HControl[27] to clear error registers */
+				hcontrol = ioread32(hcr_base + HCONTROL);
+				iowrite32(hcontrol | CLEAR_ERROR,
+						hcr_base + HCONTROL);
+
+				/* Clear HControl[27] */
+				iowrite32(hcontrol & ~CLEAR_ERROR,
+						hcr_base + HCONTROL);
+
+				/* Clear SError[E] bit */
+				sata_fsl_scr_write(&ap->link, SCR_ERROR,
+						SError);
+
+				/* Ignore fatal error and device error */
+				status_mask &= ~(INT_ON_SINGL_DEVICE_ERR
+						| INT_ON_FATAL_ERR);
+				break;
+			}
+		}
+	}
+
 	if (unlikely(SError & 0xFFFF0000)) {
 		DPRINTK("serror @host_intr : 0x%x\n", SError);
 		sata_fsl_error_intr(ap);
 	}
 
-	if (unlikely(hstatus & INT_ON_ERROR)) {
+	if (unlikely(hstatus & status_mask)) {
 		DPRINTK("error interrupt!!\n");
 		sata_fsl_error_intr(ap);
 		return;
 	}
 
-	/* Read command completed register */
-	done_mask = ioread32(hcr_base + CC);
-
 	VPRINTK("Status of all queues :\n");
 	VPRINTK("done_mask/CC = 0x%x, CA = 0x%x, CE=0x%x,CQ=0x%x,apqa=0x%x\n",
 		done_mask,
diff --git a/drivers/ata/sata_highbank.c b/drivers/ata/sata_highbank.c
new file mode 100644
index 0000000..0d7c4c2
--- /dev/null
+++ b/drivers/ata/sata_highbank.c
@@ -0,0 +1,450 @@
+/*
+ * Calxeda Highbank AHCI SATA platform driver
+ * Copyright 2012 Calxeda, Inc.
+ *
+ * based on the AHCI SATA platform driver by Jeff Garzik and Anton Vorontsov
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/kernel.h>
+#include <linux/gfp.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/spinlock.h>
+#include <linux/device.h>
+#include <linux/of_device.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/libata.h>
+#include <linux/ahci_platform.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/export.h>
+#include "ahci.h"
+
+#define CPHY_MAP(dev, addr) ((((dev) & 0x1f) << 7) | (((addr) >> 9) & 0x7f))
+#define CPHY_ADDR(addr) (((addr) & 0x1ff) << 2)
+#define SERDES_CR_CTL			0x80a0
+#define SERDES_CR_ADDR			0x80a1
+#define SERDES_CR_DATA			0x80a2
+#define CR_BUSY				0x0001
+#define CR_START			0x0001
+#define CR_WR_RDN			0x0002
+#define CPHY_RX_INPUT_STS		0x2002
+#define CPHY_SATA_OVERRIDE	 	0x4000
+#define CPHY_OVERRIDE			0x2005
+#define SPHY_LANE			0x100
+#define SPHY_HALF_RATE			0x0001
+#define CPHY_SATA_DPLL_MODE		0x0700
+#define CPHY_SATA_DPLL_SHIFT		8
+#define CPHY_SATA_DPLL_RESET		(1 << 11)
+#define CPHY_PHY_COUNT			6
+#define CPHY_LANE_COUNT			4
+#define CPHY_PORT_COUNT			(CPHY_PHY_COUNT * CPHY_LANE_COUNT)
+
+static DEFINE_SPINLOCK(cphy_lock);
+/* Each of the 6 phys can have up to 4 sata ports attached to i. Map 0-based
+ * sata ports to their phys and then to their lanes within the phys
+ */
+struct phy_lane_info {
+	void __iomem *phy_base;
+	u8 lane_mapping;
+	u8 phy_devs;
+};
+static struct phy_lane_info port_data[CPHY_PORT_COUNT];
+
+static u32 __combo_phy_reg_read(u8 sata_port, u32 addr)
+{
+	u32 data;
+	u8 dev = port_data[sata_port].phy_devs;
+	spin_lock(&cphy_lock);
+	writel(CPHY_MAP(dev, addr), port_data[sata_port].phy_base + 0x800);
+	data = readl(port_data[sata_port].phy_base + CPHY_ADDR(addr));
+	spin_unlock(&cphy_lock);
+	return data;
+}
+
+static void __combo_phy_reg_write(u8 sata_port, u32 addr, u32 data)
+{
+	u8 dev = port_data[sata_port].phy_devs;
+	spin_lock(&cphy_lock);
+	writel(CPHY_MAP(dev, addr), port_data[sata_port].phy_base + 0x800);
+	writel(data, port_data[sata_port].phy_base + CPHY_ADDR(addr));
+	spin_unlock(&cphy_lock);
+}
+
+static void combo_phy_wait_for_ready(u8 sata_port)
+{
+	while (__combo_phy_reg_read(sata_port, SERDES_CR_CTL) & CR_BUSY)
+		udelay(5);
+}
+
+static u32 combo_phy_read(u8 sata_port, u32 addr)
+{
+	combo_phy_wait_for_ready(sata_port);
+	__combo_phy_reg_write(sata_port, SERDES_CR_ADDR, addr);
+	__combo_phy_reg_write(sata_port, SERDES_CR_CTL, CR_START);
+	combo_phy_wait_for_ready(sata_port);
+	return __combo_phy_reg_read(sata_port, SERDES_CR_DATA);
+}
+
+static void combo_phy_write(u8 sata_port, u32 addr, u32 data)
+{
+	combo_phy_wait_for_ready(sata_port);
+	__combo_phy_reg_write(sata_port, SERDES_CR_ADDR, addr);
+	__combo_phy_reg_write(sata_port, SERDES_CR_DATA, data);
+	__combo_phy_reg_write(sata_port, SERDES_CR_CTL, CR_WR_RDN | CR_START);
+}
+
+static void highbank_cphy_disable_overrides(u8 sata_port)
+{
+	u8 lane = port_data[sata_port].lane_mapping;
+	u32 tmp;
+	if (unlikely(port_data[sata_port].phy_base == NULL))
+		return;
+	tmp = combo_phy_read(sata_port, CPHY_RX_INPUT_STS + lane * SPHY_LANE);
+	tmp &= ~CPHY_SATA_OVERRIDE;
+	combo_phy_write(sata_port, CPHY_OVERRIDE + lane * SPHY_LANE, tmp);
+}
+
+static void cphy_override_rx_mode(u8 sata_port, u32 val)
+{
+	u8 lane = port_data[sata_port].lane_mapping;
+	u32 tmp;
+	tmp = combo_phy_read(sata_port, CPHY_RX_INPUT_STS + lane * SPHY_LANE);
+	tmp &= ~CPHY_SATA_OVERRIDE;
+	combo_phy_write(sata_port, CPHY_OVERRIDE + lane * SPHY_LANE, tmp);
+
+	tmp |= CPHY_SATA_OVERRIDE;
+	combo_phy_write(sata_port, CPHY_OVERRIDE + lane * SPHY_LANE, tmp);
+
+	tmp &= ~CPHY_SATA_DPLL_MODE;
+	tmp |= val << CPHY_SATA_DPLL_SHIFT;
+	combo_phy_write(sata_port, CPHY_OVERRIDE + lane * SPHY_LANE, tmp);
+
+	tmp |= CPHY_SATA_DPLL_RESET;
+	combo_phy_write(sata_port, CPHY_OVERRIDE + lane * SPHY_LANE, tmp);
+
+	tmp &= ~CPHY_SATA_DPLL_RESET;
+	combo_phy_write(sata_port, CPHY_OVERRIDE + lane * SPHY_LANE, tmp);
+
+	msleep(15);
+}
+
+static void highbank_cphy_override_lane(u8 sata_port)
+{
+	u8 lane = port_data[sata_port].lane_mapping;
+	u32 tmp, k = 0;
+
+	if (unlikely(port_data[sata_port].phy_base == NULL))
+		return;
+	do {
+		tmp = combo_phy_read(sata_port, CPHY_RX_INPUT_STS +
+						lane * SPHY_LANE);
+	} while ((tmp & SPHY_HALF_RATE) && (k++ < 1000));
+	cphy_override_rx_mode(sata_port, 3);
+}
+
+static int highbank_initialize_phys(struct device *dev, void __iomem *addr)
+{
+	struct device_node *sata_node = dev->of_node;
+	int phy_count = 0, phy, port = 0;
+	void __iomem *cphy_base[CPHY_PHY_COUNT];
+	struct device_node *phy_nodes[CPHY_PHY_COUNT];
+	memset(port_data, 0, sizeof(struct phy_lane_info) * CPHY_PORT_COUNT);
+	memset(phy_nodes, 0, sizeof(struct device_node*) * CPHY_PHY_COUNT);
+
+	do {
+		u32 tmp;
+		struct of_phandle_args phy_data;
+		if (of_parse_phandle_with_args(sata_node,
+				"calxeda,port-phys", "#phy-cells",
+				port, &phy_data))
+			break;
+		for (phy = 0; phy < phy_count; phy++) {
+			if (phy_nodes[phy] == phy_data.np)
+				break;
+		}
+		if (phy_nodes[phy] == NULL) {
+			phy_nodes[phy] = phy_data.np;
+			cphy_base[phy] = of_iomap(phy_nodes[phy], 0);
+			if (cphy_base[phy] == NULL) {
+				return 0;
+			}
+			phy_count += 1;
+		}
+		port_data[port].lane_mapping = phy_data.args[0];
+		of_property_read_u32(phy_nodes[phy], "phydev", &tmp);
+		port_data[port].phy_devs = tmp;
+		port_data[port].phy_base = cphy_base[phy];
+		of_node_put(phy_data.np);
+		port += 1;
+	} while (port < CPHY_PORT_COUNT);
+	return 0;
+}
+
+static int ahci_highbank_hardreset(struct ata_link *link, unsigned int *class,
+				unsigned long deadline)
+{
+	const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context);
+	struct ata_port *ap = link->ap;
+	struct ahci_port_priv *pp = ap->private_data;
+	u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
+	struct ata_taskfile tf;
+	bool online;
+	u32 sstatus;
+	int rc;
+	int retry = 10;
+
+	ahci_stop_engine(ap);
+
+	/* clear D2H reception area to properly wait for D2H FIS */
+	ata_tf_init(link->device, &tf);
+	tf.command = 0x80;
+	ata_tf_to_fis(&tf, 0, 0, d2h_fis);
+
+	do {
+		highbank_cphy_disable_overrides(link->ap->port_no);
+		rc = sata_link_hardreset(link, timing, deadline, &online, NULL);
+		highbank_cphy_override_lane(link->ap->port_no);
+
+		/* If the status is 1, we are connected, but the link did not
+		 * come up. So retry resetting the link again.
+		 */
+		if (sata_scr_read(link, SCR_STATUS, &sstatus))
+			break;
+		if (!(sstatus & 0x3))
+			break;
+	} while (!online && retry--);
+
+	ahci_start_engine(ap);
+
+	if (online)
+		*class = ahci_dev_classify(ap);
+
+	return rc;
+}
+
+static struct ata_port_operations ahci_highbank_ops = {
+	.inherits		= &ahci_ops,
+	.hardreset		= ahci_highbank_hardreset,
+};
+
+static const struct ata_port_info ahci_highbank_port_info = {
+	.flags          = AHCI_FLAG_COMMON,
+	.pio_mask       = ATA_PIO4,
+	.udma_mask      = ATA_UDMA6,
+	.port_ops       = &ahci_highbank_ops,
+};
+
+static struct scsi_host_template ahci_highbank_platform_sht = {
+	AHCI_SHT("highbank-ahci"),
+};
+
+static const struct of_device_id ahci_of_match[] = {
+	{ .compatible = "calxeda,hb-ahci" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, ahci_of_match);
+
+static int __init ahci_highbank_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct ahci_host_priv *hpriv;
+	struct ata_host *host;
+	struct resource *mem;
+	int irq;
+	int n_ports;
+	int i;
+	int rc;
+	struct ata_port_info pi = ahci_highbank_port_info;
+	const struct ata_port_info *ppi[] = { &pi, NULL };
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem) {
+		dev_err(dev, "no mmio space\n");
+		return -EINVAL;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq <= 0) {
+		dev_err(dev, "no irq\n");
+		return -EINVAL;
+	}
+
+	hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
+	if (!hpriv) {
+		dev_err(dev, "can't alloc ahci_host_priv\n");
+		return -ENOMEM;
+	}
+
+	hpriv->flags |= (unsigned long)pi.private_data;
+
+	hpriv->mmio = devm_ioremap(dev, mem->start, resource_size(mem));
+	if (!hpriv->mmio) {
+		dev_err(dev, "can't map %pR\n", mem);
+		return -ENOMEM;
+	}
+
+	rc = highbank_initialize_phys(dev, hpriv->mmio);
+	if (rc)
+		return rc;
+
+
+	ahci_save_initial_config(dev, hpriv, 0, 0);
+
+	/* prepare host */
+	if (hpriv->cap & HOST_CAP_NCQ)
+		pi.flags |= ATA_FLAG_NCQ;
+
+	if (hpriv->cap & HOST_CAP_PMP)
+		pi.flags |= ATA_FLAG_PMP;
+
+	ahci_set_em_messages(hpriv, &pi);
+
+	/* CAP.NP sometimes indicate the index of the last enabled
+	 * port, at other times, that of the last possible port, so
+	 * determining the maximum port number requires looking at
+	 * both CAP.NP and port_map.
+	 */
+	n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map));
+
+	host = ata_host_alloc_pinfo(dev, ppi, n_ports);
+	if (!host) {
+		rc = -ENOMEM;
+		goto err0;
+	}
+
+	host->private_data = hpriv;
+
+	if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss)
+		host->flags |= ATA_HOST_PARALLEL_SCAN;
+
+	if (pi.flags & ATA_FLAG_EM)
+		ahci_reset_em(host);
+
+	for (i = 0; i < host->n_ports; i++) {
+		struct ata_port *ap = host->ports[i];
+
+		ata_port_desc(ap, "mmio %pR", mem);
+		ata_port_desc(ap, "port 0x%x", 0x100 + ap->port_no * 0x80);
+
+		/* set enclosure management message type */
+		if (ap->flags & ATA_FLAG_EM)
+			ap->em_message_type = hpriv->em_msg_type;
+
+		/* disabled/not-implemented port */
+		if (!(hpriv->port_map & (1 << i)))
+			ap->ops = &ata_dummy_port_ops;
+	}
+
+	rc = ahci_reset_controller(host);
+	if (rc)
+		goto err0;
+
+	ahci_init_controller(host);
+	ahci_print_info(host, "platform");
+
+	rc = ata_host_activate(host, irq, ahci_interrupt, 0,
+					&ahci_highbank_platform_sht);
+	if (rc)
+		goto err0;
+
+	return 0;
+err0:
+	return rc;
+}
+
+static int __devexit ahci_highbank_remove(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct ata_host *host = dev_get_drvdata(dev);
+
+	ata_host_detach(host);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int ahci_highbank_suspend(struct device *dev)
+{
+	struct ata_host *host = dev_get_drvdata(dev);
+	struct ahci_host_priv *hpriv = host->private_data;
+	void __iomem *mmio = hpriv->mmio;
+	u32 ctl;
+	int rc;
+
+	if (hpriv->flags & AHCI_HFLAG_NO_SUSPEND) {
+		dev_err(dev, "firmware update required for suspend/resume\n");
+		return -EIO;
+	}
+
+	/*
+	 * AHCI spec rev1.1 section 8.3.3:
+	 * Software must disable interrupts prior to requesting a
+	 * transition of the HBA to D3 state.
+	 */
+	ctl = readl(mmio + HOST_CTL);
+	ctl &= ~HOST_IRQ_EN;
+	writel(ctl, mmio + HOST_CTL);
+	readl(mmio + HOST_CTL); /* flush */
+
+	rc = ata_host_suspend(host, PMSG_SUSPEND);
+	if (rc)
+		return rc;
+
+	return 0;
+}
+
+static int ahci_highbank_resume(struct device *dev)
+{
+	struct ata_host *host = dev_get_drvdata(dev);
+	int rc;
+
+	if (dev->power.power_state.event == PM_EVENT_SUSPEND) {
+		rc = ahci_reset_controller(host);
+		if (rc)
+			return rc;
+
+		ahci_init_controller(host);
+	}
+
+	ata_host_resume(host);
+
+	return 0;
+}
+#endif
+
+SIMPLE_DEV_PM_OPS(ahci_highbank_pm_ops,
+		  ahci_highbank_suspend, ahci_highbank_resume);
+
+static struct platform_driver ahci_highbank_driver = {
+        .remove = __devexit_p(ahci_highbank_remove),
+        .driver = {
+                .name = "highbank-ahci",
+                .owner = THIS_MODULE,
+                .of_match_table = ahci_of_match,
+                .pm = &ahci_highbank_pm_ops,
+        },
+	.probe = ahci_highbank_probe,
+};
+
+module_platform_driver(ahci_highbank_driver);
+
+MODULE_DESCRIPTION("Calxeda Highbank AHCI SATA platform driver");
+MODULE_AUTHOR("Mark Langsdorf <mark.langsdorf@calxeda.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("sata:highbank");
diff --git a/drivers/atm/eni.c b/drivers/atm/eni.c
index 2059ee4..81e44f7 100644
--- a/drivers/atm/eni.c
+++ b/drivers/atm/eni.c
@@ -1567,7 +1567,7 @@ tx_complete++;
 /*--------------------------------- entries ---------------------------------*/
 
 
-static const char *media_name[] __devinitdata = {
+static char * const media_name[] __devinitconst = {
     "MMF", "SMF", "MMF", "03?", /*  0- 3 */
     "UTP", "05?", "06?", "07?", /*  4- 7 */
     "TAXI","09?", "10?", "11?", /*  8-11 */
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 5e6e00b..abea76c 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -184,6 +184,17 @@ static void device_release(struct kobject *kobj)
 	struct device *dev = kobj_to_dev(kobj);
 	struct device_private *p = dev->p;
 
+	/*
+	 * Some platform devices are driven without driver attached
+	 * and managed resources may have been acquired.  Make sure
+	 * all resources are released.
+	 *
+	 * Drivers still can add resources into device after device
+	 * is deleted but alive, so release devres here to avoid
+	 * possible memory leak.
+	 */
+	devres_release_all(dev);
+
 	if (dev->release)
 		dev->release(dev);
 	else if (dev->type && dev->type->release)
@@ -1196,13 +1207,6 @@ void device_del(struct device *dev)
 	bus_remove_device(dev);
 	driver_deferred_probe_del(dev);
 
-	/*
-	 * Some platform devices are driven without driver attached
-	 * and managed resources may have been acquired.  Make sure
-	 * all resources are released.
-	 */
-	devres_release_all(dev);
-
 	/* Notify the platform of the removal, in case they
 	 * need to do anything...
 	 */
@@ -1861,26 +1865,20 @@ void device_shutdown(void)
  */
 
 #ifdef CONFIG_PRINTK
-int __dev_printk(const char *level, const struct device *dev,
-		 struct va_format *vaf)
+static int
+create_syslog_header(const struct device *dev, char *hdr, size_t hdrlen)
 {
-	char dict[128];
-	const char *level_extra = "";
-	size_t dictlen = 0;
 	const char *subsys;
-
-	if (!dev)
-		return printk("%s(NULL device *): %pV", level, vaf);
+	size_t pos = 0;
 
 	if (dev->class)
 		subsys = dev->class->name;
 	else if (dev->bus)
 		subsys = dev->bus->name;
 	else
-		goto skip;
+		return 0;
 
-	dictlen += snprintf(dict + dictlen, sizeof(dict) - dictlen,
-			    "SUBSYSTEM=%s", subsys);
+	pos += snprintf(hdr + pos, hdrlen - pos, "SUBSYSTEM=%s", subsys);
 
 	/*
 	 * Add device identifier DEVICE=:
@@ -1896,32 +1894,63 @@ int __dev_printk(const char *level, const struct device *dev,
 			c = 'b';
 		else
 			c = 'c';
-		dictlen++;
-		dictlen += snprintf(dict + dictlen, sizeof(dict) - dictlen,
-				   "DEVICE=%c%u:%u",
-				   c, MAJOR(dev->devt), MINOR(dev->devt));
+		pos++;
+		pos += snprintf(hdr + pos, hdrlen - pos,
+				"DEVICE=%c%u:%u",
+				c, MAJOR(dev->devt), MINOR(dev->devt));
 	} else if (strcmp(subsys, "net") == 0) {
 		struct net_device *net = to_net_dev(dev);
 
-		dictlen++;
-		dictlen += snprintf(dict + dictlen, sizeof(dict) - dictlen,
-				    "DEVICE=n%u", net->ifindex);
+		pos++;
+		pos += snprintf(hdr + pos, hdrlen - pos,
+				"DEVICE=n%u", net->ifindex);
 	} else {
-		dictlen++;
-		dictlen += snprintf(dict + dictlen, sizeof(dict) - dictlen,
-				    "DEVICE=+%s:%s", subsys, dev_name(dev));
+		pos++;
+		pos += snprintf(hdr + pos, hdrlen - pos,
+				"DEVICE=+%s:%s", subsys, dev_name(dev));
 	}
-skip:
-	if (level[2])
-		level_extra = &level[2]; /* skip past KERN_SOH "L" */
 
-	return printk_emit(0, level[1] - '0',
-			   dictlen ? dict : NULL, dictlen,
-			   "%s %s: %s%pV",
-			   dev_driver_string(dev), dev_name(dev),
-			   level_extra, vaf);
+	return pos;
+}
+EXPORT_SYMBOL(create_syslog_header);
+
+int dev_vprintk_emit(int level, const struct device *dev,
+		     const char *fmt, va_list args)
+{
+	char hdr[128];
+	size_t hdrlen;
+
+	hdrlen = create_syslog_header(dev, hdr, sizeof(hdr));
+
+	return vprintk_emit(0, level, hdrlen ? hdr : NULL, hdrlen, fmt, args);
+}
+EXPORT_SYMBOL(dev_vprintk_emit);
+
+int dev_printk_emit(int level, const struct device *dev, const char *fmt, ...)
+{
+	va_list args;
+	int r;
+
+	va_start(args, fmt);
+
+	r = dev_vprintk_emit(level, dev, fmt, args);
+
+	va_end(args);
+
+	return r;
+}
+EXPORT_SYMBOL(dev_printk_emit);
+
+static int __dev_printk(const char *level, const struct device *dev,
+			struct va_format *vaf)
+{
+	if (!dev)
+		return printk("%s(NULL device *): %pV", level, vaf);
+
+	return dev_printk_emit(level[1] - '0', dev,
+			       "%s %s: %pV",
+			       dev_driver_string(dev), dev_name(dev), vaf);
 }
-EXPORT_SYMBOL(__dev_printk);
 
 int dev_printk(const char *level, const struct device *dev,
 	       const char *fmt, ...)
@@ -1936,6 +1965,7 @@ int dev_printk(const char *level, const struct device *dev,
 	vaf.va = &args;
 
 	r = __dev_printk(level, dev, &vaf);
+
 	va_end(args);
 
 	return r;
@@ -1955,6 +1985,7 @@ int func(const struct device *dev, const char *fmt, ...)	\
 	vaf.va = &args;						\
 								\
 	r = __dev_printk(kern_level, dev, &vaf);		\
+								\
 	va_end(args);						\
 								\
 	return r;						\
diff --git a/drivers/base/devres.c b/drivers/base/devres.c
index 2360adb..8731979 100644
--- a/drivers/base/devres.c
+++ b/drivers/base/devres.c
@@ -144,6 +144,48 @@ EXPORT_SYMBOL_GPL(devres_alloc);
 #endif
 
 /**
+ * devres_for_each_res - Resource iterator
+ * @dev: Device to iterate resource from
+ * @release: Look for resources associated with this release function
+ * @match: Match function (optional)
+ * @match_data: Data for the match function
+ * @fn: Function to be called for each matched resource.
+ * @data: Data for @fn, the 3rd parameter of @fn
+ *
+ * Call @fn for each devres of @dev which is associated with @release
+ * and for which @match returns 1.
+ *
+ * RETURNS:
+ * 	void
+ */
+void devres_for_each_res(struct device *dev, dr_release_t release,
+			dr_match_t match, void *match_data,
+			void (*fn)(struct device *, void *, void *),
+			void *data)
+{
+	struct devres_node *node;
+	struct devres_node *tmp;
+	unsigned long flags;
+
+	if (!fn)
+		return;
+
+	spin_lock_irqsave(&dev->devres_lock, flags);
+	list_for_each_entry_safe_reverse(node, tmp,
+			&dev->devres_head, entry) {
+		struct devres *dr = container_of(node, struct devres, node);
+
+		if (node->release != release)
+			continue;
+		if (match && !match(dev, dr->data, match_data))
+			continue;
+		fn(dev, dr->data, data);
+	}
+	spin_unlock_irqrestore(&dev->devres_lock, flags);
+}
+EXPORT_SYMBOL_GPL(devres_for_each_res);
+
+/**
  * devres_free - Free device resource data
  * @res: Pointer to devres data to free
  *
diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c
index deb4a45..147d1a4 100644
--- a/drivers/base/devtmpfs.c
+++ b/drivers/base/devtmpfs.c
@@ -309,8 +309,8 @@ static int handle_remove(const char *nodename, struct device *dev)
 			 * before unlinking this node, reset permissions
 			 * of possible references like hardlinks
 			 */
-			newattrs.ia_uid = 0;
-			newattrs.ia_gid = 0;
+			newattrs.ia_uid = GLOBAL_ROOT_UID;
+			newattrs.ia_gid = GLOBAL_ROOT_GID;
 			newattrs.ia_mode = stat.mode & ~0777;
 			newattrs.ia_valid =
 				ATTR_UID|ATTR_GID|ATTR_MODE;
diff --git a/drivers/base/dma-buf.c b/drivers/base/dma-buf.c
index c30f3e1..460e22d 100644
--- a/drivers/base/dma-buf.c
+++ b/drivers/base/dma-buf.c
@@ -460,8 +460,7 @@ int dma_buf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma,
 	if (vma->vm_file)
 		fput(vma->vm_file);
 
-	vma->vm_file = dmabuf->file;
-	get_file(vma->vm_file);
+	vma->vm_file = get_file(dmabuf->file);
 
 	vma->vm_pgoff = pgoff;
 
diff --git a/drivers/base/dma-contiguous.c b/drivers/base/dma-contiguous.c
index 34d94c7..9a14694 100644
--- a/drivers/base/dma-contiguous.c
+++ b/drivers/base/dma-contiguous.c
@@ -315,6 +315,7 @@ struct page *dma_alloc_from_contiguous(struct device *dev, int count,
 {
 	unsigned long mask, pfn, pageno, start = 0;
 	struct cma *cma = dev_get_cma_area(dev);
+	struct page *page = NULL;
 	int ret;
 
 	if (!cma || !cma->count)
@@ -336,18 +337,17 @@ struct page *dma_alloc_from_contiguous(struct device *dev, int count,
 	for (;;) {
 		pageno = bitmap_find_next_zero_area(cma->bitmap, cma->count,
 						    start, count, mask);
-		if (pageno >= cma->count) {
-			ret = -ENOMEM;
-			goto error;
-		}
+		if (pageno >= cma->count)
+			break;
 
 		pfn = cma->base_pfn + pageno;
 		ret = alloc_contig_range(pfn, pfn + count, MIGRATE_CMA);
 		if (ret == 0) {
 			bitmap_set(cma->bitmap, pageno, count);
+			page = pfn_to_page(pfn);
 			break;
 		} else if (ret != -EBUSY) {
-			goto error;
+			break;
 		}
 		pr_debug("%s(): memory range at %p is busy, retrying\n",
 			 __func__, pfn_to_page(pfn));
@@ -356,12 +356,8 @@ struct page *dma_alloc_from_contiguous(struct device *dev, int count,
 	}
 
 	mutex_unlock(&cma_mutex);
-
-	pr_debug("%s(): returned %p\n", __func__, pfn_to_page(pfn));
-	return pfn_to_page(pfn);
-error:
-	mutex_unlock(&cma_mutex);
-	return NULL;
+	pr_debug("%s(): returned %p\n", __func__, page);
+	return page;
 }
 
 /**
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 803cfc1..6e21080 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -21,6 +21,13 @@
 #include <linux/firmware.h>
 #include <linux/slab.h>
 #include <linux/sched.h>
+#include <linux/list.h>
+#include <linux/async.h>
+#include <linux/pm.h>
+#include <linux/suspend.h>
+#include <linux/syscore_ops.h>
+
+#include "base.h"
 
 MODULE_AUTHOR("Manuel Estrada Sainz");
 MODULE_DESCRIPTION("Multi purpose firmware loading support");
@@ -85,23 +92,168 @@ static inline long firmware_loading_timeout(void)
 	return loading_timeout > 0 ? loading_timeout * HZ : MAX_SCHEDULE_TIMEOUT;
 }
 
-/* fw_lock could be moved to 'struct firmware_priv' but since it is just
- * guarding for corner cases a global lock should be OK */
-static DEFINE_MUTEX(fw_lock);
+struct firmware_cache {
+	/* firmware_buf instance will be added into the below list */
+	spinlock_t lock;
+	struct list_head head;
+	int state;
+
+#ifdef CONFIG_PM_SLEEP
+	/*
+	 * Names of firmware images which have been cached successfully
+	 * will be added into the below list so that device uncache
+	 * helper can trace which firmware images have been cached
+	 * before.
+	 */
+	spinlock_t name_lock;
+	struct list_head fw_names;
+
+	wait_queue_head_t wait_queue;
+	int cnt;
+	struct delayed_work work;
+
+	struct notifier_block   pm_notify;
+#endif
+};
 
-struct firmware_priv {
+struct firmware_buf {
+	struct kref ref;
+	struct list_head list;
 	struct completion completion;
-	struct firmware *fw;
+	struct firmware_cache *fwc;
 	unsigned long status;
+	void *data;
+	size_t size;
 	struct page **pages;
 	int nr_pages;
 	int page_array_size;
+	char fw_id[];
+};
+
+struct fw_cache_entry {
+	struct list_head list;
+	char name[];
+};
+
+struct firmware_priv {
 	struct timer_list timeout;
-	struct device dev;
 	bool nowait;
-	char fw_id[];
+	struct device dev;
+	struct firmware_buf *buf;
+	struct firmware *fw;
+};
+
+struct fw_name_devm {
+	unsigned long magic;
+	char name[];
 };
 
+#define to_fwbuf(d) container_of(d, struct firmware_buf, ref)
+
+#define	FW_LOADER_NO_CACHE	0
+#define	FW_LOADER_START_CACHE	1
+
+static int fw_cache_piggyback_on_request(const char *name);
+
+/* fw_lock could be moved to 'struct firmware_priv' but since it is just
+ * guarding for corner cases a global lock should be OK */
+static DEFINE_MUTEX(fw_lock);
+
+static struct firmware_cache fw_cache;
+
+static struct firmware_buf *__allocate_fw_buf(const char *fw_name,
+					      struct firmware_cache *fwc)
+{
+	struct firmware_buf *buf;
+
+	buf = kzalloc(sizeof(*buf) + strlen(fw_name) + 1 , GFP_ATOMIC);
+
+	if (!buf)
+		return buf;
+
+	kref_init(&buf->ref);
+	strcpy(buf->fw_id, fw_name);
+	buf->fwc = fwc;
+	init_completion(&buf->completion);
+
+	pr_debug("%s: fw-%s buf=%p\n", __func__, fw_name, buf);
+
+	return buf;
+}
+
+static struct firmware_buf *__fw_lookup_buf(const char *fw_name)
+{
+	struct firmware_buf *tmp;
+	struct firmware_cache *fwc = &fw_cache;
+
+	list_for_each_entry(tmp, &fwc->head, list)
+		if (!strcmp(tmp->fw_id, fw_name))
+			return tmp;
+	return NULL;
+}
+
+static int fw_lookup_and_allocate_buf(const char *fw_name,
+				      struct firmware_cache *fwc,
+				      struct firmware_buf **buf)
+{
+	struct firmware_buf *tmp;
+
+	spin_lock(&fwc->lock);
+	tmp = __fw_lookup_buf(fw_name);
+	if (tmp) {
+		kref_get(&tmp->ref);
+		spin_unlock(&fwc->lock);
+		*buf = tmp;
+		return 1;
+	}
+	tmp = __allocate_fw_buf(fw_name, fwc);
+	if (tmp)
+		list_add(&tmp->list, &fwc->head);
+	spin_unlock(&fwc->lock);
+
+	*buf = tmp;
+
+	return tmp ? 0 : -ENOMEM;
+}
+
+static struct firmware_buf *fw_lookup_buf(const char *fw_name)
+{
+	struct firmware_buf *tmp;
+	struct firmware_cache *fwc = &fw_cache;
+
+	spin_lock(&fwc->lock);
+	tmp = __fw_lookup_buf(fw_name);
+	spin_unlock(&fwc->lock);
+
+	return tmp;
+}
+
+static void __fw_free_buf(struct kref *ref)
+{
+	struct firmware_buf *buf = to_fwbuf(ref);
+	struct firmware_cache *fwc = buf->fwc;
+	int i;
+
+	pr_debug("%s: fw-%s buf=%p data=%p size=%u\n",
+		 __func__, buf->fw_id, buf, buf->data,
+		 (unsigned int)buf->size);
+
+	spin_lock(&fwc->lock);
+	list_del(&buf->list);
+	spin_unlock(&fwc->lock);
+
+	vunmap(buf->data);
+	for (i = 0; i < buf->nr_pages; i++)
+		__free_page(buf->pages[i]);
+	kfree(buf->pages);
+	kfree(buf);
+}
+
+static void fw_free_buf(struct firmware_buf *buf)
+{
+	kref_put(&buf->ref, __fw_free_buf);
+}
+
 static struct firmware_priv *to_firmware_priv(struct device *dev)
 {
 	return container_of(dev, struct firmware_priv, dev);
@@ -109,9 +261,10 @@ static struct firmware_priv *to_firmware_priv(struct device *dev)
 
 static void fw_load_abort(struct firmware_priv *fw_priv)
 {
-	set_bit(FW_STATUS_ABORT, &fw_priv->status);
-	wmb();
-	complete(&fw_priv->completion);
+	struct firmware_buf *buf = fw_priv->buf;
+
+	set_bit(FW_STATUS_ABORT, &buf->status);
+	complete_all(&buf->completion);
 }
 
 static ssize_t firmware_timeout_show(struct class *class,
@@ -154,11 +307,7 @@ static struct class_attribute firmware_class_attrs[] = {
 static void fw_dev_release(struct device *dev)
 {
 	struct firmware_priv *fw_priv = to_firmware_priv(dev);
-	int i;
 
-	for (i = 0; i < fw_priv->nr_pages; i++)
-		__free_page(fw_priv->pages[i]);
-	kfree(fw_priv->pages);
 	kfree(fw_priv);
 
 	module_put(THIS_MODULE);
@@ -168,7 +317,7 @@ static int firmware_uevent(struct device *dev, struct kobj_uevent_env *env)
 {
 	struct firmware_priv *fw_priv = to_firmware_priv(dev);
 
-	if (add_uevent_var(env, "FIRMWARE=%s", fw_priv->fw_id))
+	if (add_uevent_var(env, "FIRMWARE=%s", fw_priv->buf->fw_id))
 		return -ENOMEM;
 	if (add_uevent_var(env, "TIMEOUT=%i", loading_timeout))
 		return -ENOMEM;
@@ -189,20 +338,16 @@ static ssize_t firmware_loading_show(struct device *dev,
 				     struct device_attribute *attr, char *buf)
 {
 	struct firmware_priv *fw_priv = to_firmware_priv(dev);
-	int loading = test_bit(FW_STATUS_LOADING, &fw_priv->status);
+	int loading = test_bit(FW_STATUS_LOADING, &fw_priv->buf->status);
 
 	return sprintf(buf, "%d\n", loading);
 }
 
+/* firmware holds the ownership of pages */
 static void firmware_free_data(const struct firmware *fw)
 {
-	int i;
-	vunmap(fw->data);
-	if (fw->pages) {
-		for (i = 0; i < PFN_UP(fw->size); i++)
-			__free_page(fw->pages[i]);
-		kfree(fw->pages);
-	}
+	WARN_ON(!fw->priv);
+	fw_free_buf(fw->priv);
 }
 
 /* Some architectures don't have PAGE_KERNEL_RO */
@@ -227,45 +372,33 @@ static ssize_t firmware_loading_store(struct device *dev,
 				      const char *buf, size_t count)
 {
 	struct firmware_priv *fw_priv = to_firmware_priv(dev);
+	struct firmware_buf *fw_buf = fw_priv->buf;
 	int loading = simple_strtol(buf, NULL, 10);
 	int i;
 
 	mutex_lock(&fw_lock);
 
-	if (!fw_priv->fw)
+	if (!fw_buf)
 		goto out;
 
 	switch (loading) {
 	case 1:
-		firmware_free_data(fw_priv->fw);
-		memset(fw_priv->fw, 0, sizeof(struct firmware));
-		/* If the pages are not owned by 'struct firmware' */
-		for (i = 0; i < fw_priv->nr_pages; i++)
-			__free_page(fw_priv->pages[i]);
-		kfree(fw_priv->pages);
-		fw_priv->pages = NULL;
-		fw_priv->page_array_size = 0;
-		fw_priv->nr_pages = 0;
-		set_bit(FW_STATUS_LOADING, &fw_priv->status);
+		/* discarding any previous partial load */
+		if (!test_bit(FW_STATUS_DONE, &fw_buf->status)) {
+			for (i = 0; i < fw_buf->nr_pages; i++)
+				__free_page(fw_buf->pages[i]);
+			kfree(fw_buf->pages);
+			fw_buf->pages = NULL;
+			fw_buf->page_array_size = 0;
+			fw_buf->nr_pages = 0;
+			set_bit(FW_STATUS_LOADING, &fw_buf->status);
+		}
 		break;
 	case 0:
-		if (test_bit(FW_STATUS_LOADING, &fw_priv->status)) {
-			vunmap(fw_priv->fw->data);
-			fw_priv->fw->data = vmap(fw_priv->pages,
-						 fw_priv->nr_pages,
-						 0, PAGE_KERNEL_RO);
-			if (!fw_priv->fw->data) {
-				dev_err(dev, "%s: vmap() failed\n", __func__);
-				goto err;
-			}
-			/* Pages are now owned by 'struct firmware' */
-			fw_priv->fw->pages = fw_priv->pages;
-			fw_priv->pages = NULL;
-
-			fw_priv->page_array_size = 0;
-			fw_priv->nr_pages = 0;
-			complete(&fw_priv->completion);
-			clear_bit(FW_STATUS_LOADING, &fw_priv->status);
+		if (test_bit(FW_STATUS_LOADING, &fw_buf->status)) {
+			set_bit(FW_STATUS_DONE, &fw_buf->status);
+			clear_bit(FW_STATUS_LOADING, &fw_buf->status);
+			complete_all(&fw_buf->completion);
 			break;
 		}
 		/* fallthrough */
@@ -273,7 +406,6 @@ static ssize_t firmware_loading_store(struct device *dev,
 		dev_err(dev, "%s: unexpected value (%d)\n", __func__, loading);
 		/* fallthrough */
 	case -1:
-	err:
 		fw_load_abort(fw_priv);
 		break;
 	}
@@ -290,21 +422,21 @@ static ssize_t firmware_data_read(struct file *filp, struct kobject *kobj,
 {
 	struct device *dev = kobj_to_dev(kobj);
 	struct firmware_priv *fw_priv = to_firmware_priv(dev);
-	struct firmware *fw;
+	struct firmware_buf *buf;
 	ssize_t ret_count;
 
 	mutex_lock(&fw_lock);
-	fw = fw_priv->fw;
-	if (!fw || test_bit(FW_STATUS_DONE, &fw_priv->status)) {
+	buf = fw_priv->buf;
+	if (!buf || test_bit(FW_STATUS_DONE, &buf->status)) {
 		ret_count = -ENODEV;
 		goto out;
 	}
-	if (offset > fw->size) {
+	if (offset > buf->size) {
 		ret_count = 0;
 		goto out;
 	}
-	if (count > fw->size - offset)
-		count = fw->size - offset;
+	if (count > buf->size - offset)
+		count = buf->size - offset;
 
 	ret_count = count;
 
@@ -314,11 +446,11 @@ static ssize_t firmware_data_read(struct file *filp, struct kobject *kobj,
 		int page_ofs = offset & (PAGE_SIZE-1);
 		int page_cnt = min_t(size_t, PAGE_SIZE - page_ofs, count);
 
-		page_data = kmap(fw_priv->pages[page_nr]);
+		page_data = kmap(buf->pages[page_nr]);
 
 		memcpy(buffer, page_data + page_ofs, page_cnt);
 
-		kunmap(fw_priv->pages[page_nr]);
+		kunmap(buf->pages[page_nr]);
 		buffer += page_cnt;
 		offset += page_cnt;
 		count -= page_cnt;
@@ -330,12 +462,13 @@ out:
 
 static int fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size)
 {
+	struct firmware_buf *buf = fw_priv->buf;
 	int pages_needed = ALIGN(min_size, PAGE_SIZE) >> PAGE_SHIFT;
 
 	/* If the array of pages is too small, grow it... */
-	if (fw_priv->page_array_size < pages_needed) {
+	if (buf->page_array_size < pages_needed) {
 		int new_array_size = max(pages_needed,
-					 fw_priv->page_array_size * 2);
+					 buf->page_array_size * 2);
 		struct page **new_pages;
 
 		new_pages = kmalloc(new_array_size * sizeof(void *),
@@ -344,24 +477,24 @@ static int fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size)
 			fw_load_abort(fw_priv);
 			return -ENOMEM;
 		}
-		memcpy(new_pages, fw_priv->pages,
-		       fw_priv->page_array_size * sizeof(void *));
-		memset(&new_pages[fw_priv->page_array_size], 0, sizeof(void *) *
-		       (new_array_size - fw_priv->page_array_size));
-		kfree(fw_priv->pages);
-		fw_priv->pages = new_pages;
-		fw_priv->page_array_size = new_array_size;
+		memcpy(new_pages, buf->pages,
+		       buf->page_array_size * sizeof(void *));
+		memset(&new_pages[buf->page_array_size], 0, sizeof(void *) *
+		       (new_array_size - buf->page_array_size));
+		kfree(buf->pages);
+		buf->pages = new_pages;
+		buf->page_array_size = new_array_size;
 	}
 
-	while (fw_priv->nr_pages < pages_needed) {
-		fw_priv->pages[fw_priv->nr_pages] =
+	while (buf->nr_pages < pages_needed) {
+		buf->pages[buf->nr_pages] =
 			alloc_page(GFP_KERNEL | __GFP_HIGHMEM);
 
-		if (!fw_priv->pages[fw_priv->nr_pages]) {
+		if (!buf->pages[buf->nr_pages]) {
 			fw_load_abort(fw_priv);
 			return -ENOMEM;
 		}
-		fw_priv->nr_pages++;
+		buf->nr_pages++;
 	}
 	return 0;
 }
@@ -384,18 +517,19 @@ static ssize_t firmware_data_write(struct file *filp, struct kobject *kobj,
 {
 	struct device *dev = kobj_to_dev(kobj);
 	struct firmware_priv *fw_priv = to_firmware_priv(dev);
-	struct firmware *fw;
+	struct firmware_buf *buf;
 	ssize_t retval;
 
 	if (!capable(CAP_SYS_RAWIO))
 		return -EPERM;
 
 	mutex_lock(&fw_lock);
-	fw = fw_priv->fw;
-	if (!fw || test_bit(FW_STATUS_DONE, &fw_priv->status)) {
+	buf = fw_priv->buf;
+	if (!buf || test_bit(FW_STATUS_DONE, &buf->status)) {
 		retval = -ENODEV;
 		goto out;
 	}
+
 	retval = fw_realloc_buffer(fw_priv, offset + count);
 	if (retval)
 		goto out;
@@ -408,17 +542,17 @@ static ssize_t firmware_data_write(struct file *filp, struct kobject *kobj,
 		int page_ofs = offset & (PAGE_SIZE - 1);
 		int page_cnt = min_t(size_t, PAGE_SIZE - page_ofs, count);
 
-		page_data = kmap(fw_priv->pages[page_nr]);
+		page_data = kmap(buf->pages[page_nr]);
 
 		memcpy(page_data + page_ofs, buffer, page_cnt);
 
-		kunmap(fw_priv->pages[page_nr]);
+		kunmap(buf->pages[page_nr]);
 		buffer += page_cnt;
 		offset += page_cnt;
 		count -= page_cnt;
 	}
 
-	fw->size = max_t(size_t, offset, fw->size);
+	buf->size = max_t(size_t, offset, buf->size);
 out:
 	mutex_unlock(&fw_lock);
 	return retval;
@@ -445,35 +579,120 @@ fw_create_instance(struct firmware *firmware, const char *fw_name,
 	struct firmware_priv *fw_priv;
 	struct device *f_dev;
 
-	fw_priv = kzalloc(sizeof(*fw_priv) + strlen(fw_name) + 1 , GFP_KERNEL);
+	fw_priv = kzalloc(sizeof(*fw_priv), GFP_KERNEL);
 	if (!fw_priv) {
 		dev_err(device, "%s: kmalloc failed\n", __func__);
-		return ERR_PTR(-ENOMEM);
+		fw_priv = ERR_PTR(-ENOMEM);
+		goto exit;
 	}
 
-	fw_priv->fw = firmware;
 	fw_priv->nowait = nowait;
-	strcpy(fw_priv->fw_id, fw_name);
-	init_completion(&fw_priv->completion);
+	fw_priv->fw = firmware;
 	setup_timer(&fw_priv->timeout,
 		    firmware_class_timeout, (u_long) fw_priv);
 
 	f_dev = &fw_priv->dev;
 
 	device_initialize(f_dev);
-	dev_set_name(f_dev, "%s", dev_name(device));
+	dev_set_name(f_dev, "%s", fw_name);
 	f_dev->parent = device;
 	f_dev->class = &firmware_class;
-
+exit:
 	return fw_priv;
 }
 
+/* one pages buffer is mapped/unmapped only once */
+static int fw_map_pages_buf(struct firmware_buf *buf)
+{
+	buf->data = vmap(buf->pages, buf->nr_pages, 0, PAGE_KERNEL_RO);
+	if (!buf->data)
+		return -ENOMEM;
+	return 0;
+}
+
+/* store the pages buffer info firmware from buf */
+static void fw_set_page_data(struct firmware_buf *buf, struct firmware *fw)
+{
+	fw->priv = buf;
+	fw->pages = buf->pages;
+	fw->size = buf->size;
+	fw->data = buf->data;
+
+	pr_debug("%s: fw-%s buf=%p data=%p size=%u\n",
+		 __func__, buf->fw_id, buf, buf->data,
+		 (unsigned int)buf->size);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static void fw_name_devm_release(struct device *dev, void *res)
+{
+	struct fw_name_devm *fwn = res;
+
+	if (fwn->magic == (unsigned long)&fw_cache)
+		pr_debug("%s: fw_name-%s devm-%p released\n",
+				__func__, fwn->name, res);
+}
+
+static int fw_devm_match(struct device *dev, void *res,
+		void *match_data)
+{
+	struct fw_name_devm *fwn = res;
+
+	return (fwn->magic == (unsigned long)&fw_cache) &&
+		!strcmp(fwn->name, match_data);
+}
+
+static struct fw_name_devm *fw_find_devm_name(struct device *dev,
+		const char *name)
+{
+	struct fw_name_devm *fwn;
+
+	fwn = devres_find(dev, fw_name_devm_release,
+			  fw_devm_match, (void *)name);
+	return fwn;
+}
+
+/* add firmware name into devres list */
+static int fw_add_devm_name(struct device *dev, const char *name)
+{
+	struct fw_name_devm *fwn;
+
+	fwn = fw_find_devm_name(dev, name);
+	if (fwn)
+		return 1;
+
+	fwn = devres_alloc(fw_name_devm_release, sizeof(struct fw_name_devm) +
+			   strlen(name) + 1, GFP_KERNEL);
+	if (!fwn)
+		return -ENOMEM;
+
+	fwn->magic = (unsigned long)&fw_cache;
+	strcpy(fwn->name, name);
+	devres_add(dev, fwn);
+
+	return 0;
+}
+#else
+static int fw_add_devm_name(struct device *dev, const char *name)
+{
+	return 0;
+}
+#endif
+
+static void _request_firmware_cleanup(const struct firmware **firmware_p)
+{
+	release_firmware(*firmware_p);
+	*firmware_p = NULL;
+}
+
 static struct firmware_priv *
 _request_firmware_prepare(const struct firmware **firmware_p, const char *name,
 			  struct device *device, bool uevent, bool nowait)
 {
 	struct firmware *firmware;
-	struct firmware_priv *fw_priv;
+	struct firmware_priv *fw_priv = NULL;
+	struct firmware_buf *buf;
+	int ret;
 
 	if (!firmware_p)
 		return ERR_PTR(-EINVAL);
@@ -490,18 +709,46 @@ _request_firmware_prepare(const struct firmware **firmware_p, const char *name,
 		return NULL;
 	}
 
-	fw_priv = fw_create_instance(firmware, name, device, uevent, nowait);
-	if (IS_ERR(fw_priv)) {
-		release_firmware(firmware);
+	ret = fw_lookup_and_allocate_buf(name, &fw_cache, &buf);
+	if (!ret)
+		fw_priv = fw_create_instance(firmware, name, device,
+				uevent, nowait);
+
+	if (IS_ERR(fw_priv) || ret < 0) {
+		kfree(firmware);
 		*firmware_p = NULL;
+		return ERR_PTR(-ENOMEM);
+	} else if (fw_priv) {
+		fw_priv->buf = buf;
+
+		/*
+		 * bind with 'buf' now to avoid warning in failure path
+		 * of requesting firmware.
+		 */
+		firmware->priv = buf;
+		return fw_priv;
 	}
-	return fw_priv;
-}
 
-static void _request_firmware_cleanup(const struct firmware **firmware_p)
-{
-	release_firmware(*firmware_p);
-	*firmware_p = NULL;
+	/* share the cached buf, which is inprogessing or completed */
+ check_status:
+	mutex_lock(&fw_lock);
+	if (test_bit(FW_STATUS_ABORT, &buf->status)) {
+		fw_priv = ERR_PTR(-ENOENT);
+		firmware->priv = buf;
+		_request_firmware_cleanup(firmware_p);
+		goto exit;
+	} else if (test_bit(FW_STATUS_DONE, &buf->status)) {
+		fw_priv = NULL;
+		fw_set_page_data(buf, firmware);
+		goto exit;
+	}
+	mutex_unlock(&fw_lock);
+	wait_for_completion(&buf->completion);
+	goto check_status;
+
+exit:
+	mutex_unlock(&fw_lock);
+	return fw_priv;
 }
 
 static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent,
@@ -509,6 +756,8 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent,
 {
 	int retval = 0;
 	struct device *f_dev = &fw_priv->dev;
+	struct firmware_buf *buf = fw_priv->buf;
+	struct firmware_cache *fwc = &fw_cache;
 
 	dev_set_uevent_suppress(f_dev, true);
 
@@ -535,7 +784,7 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent,
 
 	if (uevent) {
 		dev_set_uevent_suppress(f_dev, false);
-		dev_dbg(f_dev, "firmware: requesting %s\n", fw_priv->fw_id);
+		dev_dbg(f_dev, "firmware: requesting %s\n", buf->fw_id);
 		if (timeout != MAX_SCHEDULE_TIMEOUT)
 			mod_timer(&fw_priv->timeout,
 				  round_jiffies_up(jiffies + timeout));
@@ -543,15 +792,40 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent,
 		kobject_uevent(&fw_priv->dev.kobj, KOBJ_ADD);
 	}
 
-	wait_for_completion(&fw_priv->completion);
+	wait_for_completion(&buf->completion);
 
-	set_bit(FW_STATUS_DONE, &fw_priv->status);
 	del_timer_sync(&fw_priv->timeout);
 
 	mutex_lock(&fw_lock);
-	if (!fw_priv->fw->size || test_bit(FW_STATUS_ABORT, &fw_priv->status))
+	if (!buf->size || test_bit(FW_STATUS_ABORT, &buf->status))
 		retval = -ENOENT;
-	fw_priv->fw = NULL;
+
+	/*
+	 * add firmware name into devres list so that we can auto cache
+	 * and uncache firmware for device.
+	 *
+	 * f_dev->parent may has been deleted already, but the problem
+	 * should be fixed in devres or driver core.
+	 */
+	if (!retval && f_dev->parent)
+		fw_add_devm_name(f_dev->parent, buf->fw_id);
+
+	if (!retval)
+		retval = fw_map_pages_buf(buf);
+
+	/*
+	 * After caching firmware image is started, let it piggyback
+	 * on request firmware.
+	 */
+	if (!retval && fwc->state == FW_LOADER_START_CACHE) {
+		if (fw_cache_piggyback_on_request(buf->fw_id))
+			kref_get(&buf->ref);
+	}
+
+	/* pass the pages buffer to driver at the last minute */
+	fw_set_page_data(buf, fw_priv->fw);
+
+	fw_priv->buf = NULL;
 	mutex_unlock(&fw_lock);
 
 	device_remove_file(f_dev, &dev_attr_loading);
@@ -578,6 +852,8 @@ err_put_dev:
  *      @name will be used as $FIRMWARE in the uevent environment and
  *      should be distinctive enough not to be confused with any other
  *      firmware image for this or any other device.
+ *
+ *	Caller must hold the reference count of @device.
  **/
 int
 request_firmware(const struct firmware **firmware_p, const char *name,
@@ -659,6 +935,7 @@ static void request_firmware_work_func(struct work_struct *work)
 
  out:
 	fw_work->cont(fw, fw_work->context);
+	put_device(fw_work->device);
 
 	module_put(fw_work->module);
 	kfree(fw_work);
@@ -677,9 +954,15 @@ static void request_firmware_work_func(struct work_struct *work)
  * @cont: function will be called asynchronously when the firmware
  *	request is over.
  *
- *	Asynchronous variant of request_firmware() for user contexts where
- *	it is not possible to sleep for long time. It can't be called
- *	in atomic contexts.
+ *	Caller must hold the reference count of @device.
+ *
+ *	Asynchronous variant of request_firmware() for user contexts:
+ *		- sleep for as small periods as possible since it may
+ *		increase kernel boot time of built-in device drivers
+ *		requesting firmware in their ->probe() methods, if
+ *		@gfp is GFP_KERNEL.
+ *
+ *		- can't sleep at all if @gfp is GFP_ATOMIC.
  **/
 int
 request_firmware_nowait(
@@ -705,18 +988,363 @@ request_firmware_nowait(
 		return -EFAULT;
 	}
 
+	get_device(fw_work->device);
 	INIT_WORK(&fw_work->work, request_firmware_work_func);
 	schedule_work(&fw_work->work);
 	return 0;
 }
 
+/**
+ * cache_firmware - cache one firmware image in kernel memory space
+ * @fw_name: the firmware image name
+ *
+ * Cache firmware in kernel memory so that drivers can use it when
+ * system isn't ready for them to request firmware image from userspace.
+ * Once it returns successfully, driver can use request_firmware or its
+ * nowait version to get the cached firmware without any interacting
+ * with userspace
+ *
+ * Return 0 if the firmware image has been cached successfully
+ * Return !0 otherwise
+ *
+ */
+int cache_firmware(const char *fw_name)
+{
+	int ret;
+	const struct firmware *fw;
+
+	pr_debug("%s: %s\n", __func__, fw_name);
+
+	ret = request_firmware(&fw, fw_name, NULL);
+	if (!ret)
+		kfree(fw);
+
+	pr_debug("%s: %s ret=%d\n", __func__, fw_name, ret);
+
+	return ret;
+}
+
+/**
+ * uncache_firmware - remove one cached firmware image
+ * @fw_name: the firmware image name
+ *
+ * Uncache one firmware image which has been cached successfully
+ * before.
+ *
+ * Return 0 if the firmware cache has been removed successfully
+ * Return !0 otherwise
+ *
+ */
+int uncache_firmware(const char *fw_name)
+{
+	struct firmware_buf *buf;
+	struct firmware fw;
+
+	pr_debug("%s: %s\n", __func__, fw_name);
+
+	if (fw_get_builtin_firmware(&fw, fw_name))
+		return 0;
+
+	buf = fw_lookup_buf(fw_name);
+	if (buf) {
+		fw_free_buf(buf);
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static struct fw_cache_entry *alloc_fw_cache_entry(const char *name)
+{
+	struct fw_cache_entry *fce;
+
+	fce = kzalloc(sizeof(*fce) + strlen(name) + 1, GFP_ATOMIC);
+	if (!fce)
+		goto exit;
+
+	strcpy(fce->name, name);
+exit:
+	return fce;
+}
+
+static int fw_cache_piggyback_on_request(const char *name)
+{
+	struct firmware_cache *fwc = &fw_cache;
+	struct fw_cache_entry *fce;
+	int ret = 0;
+
+	spin_lock(&fwc->name_lock);
+	list_for_each_entry(fce, &fwc->fw_names, list) {
+		if (!strcmp(fce->name, name))
+			goto found;
+	}
+
+	fce = alloc_fw_cache_entry(name);
+	if (fce) {
+		ret = 1;
+		list_add(&fce->list, &fwc->fw_names);
+		pr_debug("%s: fw: %s\n", __func__, name);
+	}
+found:
+	spin_unlock(&fwc->name_lock);
+	return ret;
+}
+
+static void free_fw_cache_entry(struct fw_cache_entry *fce)
+{
+	kfree(fce);
+}
+
+static void __async_dev_cache_fw_image(void *fw_entry,
+				       async_cookie_t cookie)
+{
+	struct fw_cache_entry *fce = fw_entry;
+	struct firmware_cache *fwc = &fw_cache;
+	int ret;
+
+	ret = cache_firmware(fce->name);
+	if (ret) {
+		spin_lock(&fwc->name_lock);
+		list_del(&fce->list);
+		spin_unlock(&fwc->name_lock);
+
+		free_fw_cache_entry(fce);
+	}
+
+	spin_lock(&fwc->name_lock);
+	fwc->cnt--;
+	spin_unlock(&fwc->name_lock);
+
+	wake_up(&fwc->wait_queue);
+}
+
+/* called with dev->devres_lock held */
+static void dev_create_fw_entry(struct device *dev, void *res,
+				void *data)
+{
+	struct fw_name_devm *fwn = res;
+	const char *fw_name = fwn->name;
+	struct list_head *head = data;
+	struct fw_cache_entry *fce;
+
+	fce = alloc_fw_cache_entry(fw_name);
+	if (fce)
+		list_add(&fce->list, head);
+}
+
+static int devm_name_match(struct device *dev, void *res,
+			   void *match_data)
+{
+	struct fw_name_devm *fwn = res;
+	return (fwn->magic == (unsigned long)match_data);
+}
+
+static void dev_cache_fw_image(struct device *dev, void *data)
+{
+	LIST_HEAD(todo);
+	struct fw_cache_entry *fce;
+	struct fw_cache_entry *fce_next;
+	struct firmware_cache *fwc = &fw_cache;
+
+	devres_for_each_res(dev, fw_name_devm_release,
+			    devm_name_match, &fw_cache,
+			    dev_create_fw_entry, &todo);
+
+	list_for_each_entry_safe(fce, fce_next, &todo, list) {
+		list_del(&fce->list);
+
+		spin_lock(&fwc->name_lock);
+		fwc->cnt++;
+		list_add(&fce->list, &fwc->fw_names);
+		spin_unlock(&fwc->name_lock);
+
+		async_schedule(__async_dev_cache_fw_image, (void *)fce);
+	}
+}
+
+static void __device_uncache_fw_images(void)
+{
+	struct firmware_cache *fwc = &fw_cache;
+	struct fw_cache_entry *fce;
+
+	spin_lock(&fwc->name_lock);
+	while (!list_empty(&fwc->fw_names)) {
+		fce = list_entry(fwc->fw_names.next,
+				struct fw_cache_entry, list);
+		list_del(&fce->list);
+		spin_unlock(&fwc->name_lock);
+
+		uncache_firmware(fce->name);
+		free_fw_cache_entry(fce);
+
+		spin_lock(&fwc->name_lock);
+	}
+	spin_unlock(&fwc->name_lock);
+}
+
+/**
+ * device_cache_fw_images - cache devices' firmware
+ *
+ * If one device called request_firmware or its nowait version
+ * successfully before, the firmware names are recored into the
+ * device's devres link list, so device_cache_fw_images can call
+ * cache_firmware() to cache these firmwares for the device,
+ * then the device driver can load its firmwares easily at
+ * time when system is not ready to complete loading firmware.
+ */
+static void device_cache_fw_images(void)
+{
+	struct firmware_cache *fwc = &fw_cache;
+	int old_timeout;
+	DEFINE_WAIT(wait);
+
+	pr_debug("%s\n", __func__);
+
+	/*
+	 * use small loading timeout for caching devices' firmware
+	 * because all these firmware images have been loaded
+	 * successfully at lease once, also system is ready for
+	 * completing firmware loading now. The maximum size of
+	 * firmware in current distributions is about 2M bytes,
+	 * so 10 secs should be enough.
+	 */
+	old_timeout = loading_timeout;
+	loading_timeout = 10;
+
+	mutex_lock(&fw_lock);
+	fwc->state = FW_LOADER_START_CACHE;
+	dpm_for_each_dev(NULL, dev_cache_fw_image);
+	mutex_unlock(&fw_lock);
+
+	/* wait for completion of caching firmware for all devices */
+	spin_lock(&fwc->name_lock);
+	for (;;) {
+		prepare_to_wait(&fwc->wait_queue, &wait,
+				TASK_UNINTERRUPTIBLE);
+		if (!fwc->cnt)
+			break;
+
+		spin_unlock(&fwc->name_lock);
+
+		schedule();
+
+		spin_lock(&fwc->name_lock);
+	}
+	spin_unlock(&fwc->name_lock);
+	finish_wait(&fwc->wait_queue, &wait);
+
+	loading_timeout = old_timeout;
+}
+
+/**
+ * device_uncache_fw_images - uncache devices' firmware
+ *
+ * uncache all firmwares which have been cached successfully
+ * by device_uncache_fw_images earlier
+ */
+static void device_uncache_fw_images(void)
+{
+	pr_debug("%s\n", __func__);
+	__device_uncache_fw_images();
+}
+
+static void device_uncache_fw_images_work(struct work_struct *work)
+{
+	device_uncache_fw_images();
+}
+
+/**
+ * device_uncache_fw_images_delay - uncache devices firmwares
+ * @delay: number of milliseconds to delay uncache device firmwares
+ *
+ * uncache all devices's firmwares which has been cached successfully
+ * by device_cache_fw_images after @delay milliseconds.
+ */
+static void device_uncache_fw_images_delay(unsigned long delay)
+{
+	schedule_delayed_work(&fw_cache.work,
+			msecs_to_jiffies(delay));
+}
+
+static int fw_pm_notify(struct notifier_block *notify_block,
+			unsigned long mode, void *unused)
+{
+	switch (mode) {
+	case PM_HIBERNATION_PREPARE:
+	case PM_SUSPEND_PREPARE:
+		device_cache_fw_images();
+		break;
+
+	case PM_POST_SUSPEND:
+	case PM_POST_HIBERNATION:
+	case PM_POST_RESTORE:
+		/*
+		 * In case that system sleep failed and syscore_suspend is
+		 * not called.
+		 */
+		mutex_lock(&fw_lock);
+		fw_cache.state = FW_LOADER_NO_CACHE;
+		mutex_unlock(&fw_lock);
+
+		device_uncache_fw_images_delay(10 * MSEC_PER_SEC);
+		break;
+	}
+
+	return 0;
+}
+
+/* stop caching firmware once syscore_suspend is reached */
+static int fw_suspend(void)
+{
+	fw_cache.state = FW_LOADER_NO_CACHE;
+	return 0;
+}
+
+static struct syscore_ops fw_syscore_ops = {
+	.suspend = fw_suspend,
+};
+#else
+static int fw_cache_piggyback_on_request(const char *name)
+{
+	return 0;
+}
+#endif
+
+static void __init fw_cache_init(void)
+{
+	spin_lock_init(&fw_cache.lock);
+	INIT_LIST_HEAD(&fw_cache.head);
+	fw_cache.state = FW_LOADER_NO_CACHE;
+
+#ifdef CONFIG_PM_SLEEP
+	spin_lock_init(&fw_cache.name_lock);
+	INIT_LIST_HEAD(&fw_cache.fw_names);
+	fw_cache.cnt = 0;
+
+	init_waitqueue_head(&fw_cache.wait_queue);
+	INIT_DELAYED_WORK(&fw_cache.work,
+			  device_uncache_fw_images_work);
+
+	fw_cache.pm_notify.notifier_call = fw_pm_notify;
+	register_pm_notifier(&fw_cache.pm_notify);
+
+	register_syscore_ops(&fw_syscore_ops);
+#endif
+}
+
 static int __init firmware_class_init(void)
 {
+	fw_cache_init();
 	return class_register(&firmware_class);
 }
 
 static void __exit firmware_class_exit(void)
 {
+#ifdef CONFIG_PM_SLEEP
+	unregister_syscore_ops(&fw_syscore_ops);
+	unregister_pm_notifier(&fw_cache.pm_notify);
+#endif
 	class_unregister(&firmware_class);
 }
 
@@ -726,3 +1354,5 @@ module_exit(firmware_class_exit);
 EXPORT_SYMBOL(release_firmware);
 EXPORT_SYMBOL(request_firmware);
 EXPORT_SYMBOL(request_firmware_nowait);
+EXPORT_SYMBOL_GPL(cache_firmware);
+EXPORT_SYMBOL_GPL(uncache_firmware);
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index a1a7225..8727e9c 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -20,8 +20,13 @@
 #include <linux/err.h>
 #include <linux/slab.h>
 #include <linux/pm_runtime.h>
+#include <linux/idr.h>
 
 #include "base.h"
+#include "power/power.h"
+
+/* For automatically allocated device IDs */
+static DEFINE_IDA(platform_devid_ida);
 
 #define to_platform_driver(drv)	(container_of((drv), struct platform_driver, \
 				 driver))
@@ -99,6 +104,9 @@ struct resource *platform_get_resource_byname(struct platform_device *dev,
 	for (i = 0; i < dev->num_resources; i++) {
 		struct resource *r = &dev->resource[i];
 
+		if (unlikely(!r->name))
+			continue;
+
 		if (type == resource_type(r) && !strcmp(r->name, name))
 			return r;
 	}
@@ -263,7 +271,7 @@ EXPORT_SYMBOL_GPL(platform_device_add_data);
  */
 int platform_device_add(struct platform_device *pdev)
 {
-	int i, ret = 0;
+	int i, ret;
 
 	if (!pdev)
 		return -EINVAL;
@@ -273,10 +281,27 @@ int platform_device_add(struct platform_device *pdev)
 
 	pdev->dev.bus = &platform_bus_type;
 
-	if (pdev->id != -1)
+	switch (pdev->id) {
+	default:
 		dev_set_name(&pdev->dev, "%s.%d", pdev->name,  pdev->id);
-	else
+		break;
+	case PLATFORM_DEVID_NONE:
 		dev_set_name(&pdev->dev, "%s", pdev->name);
+		break;
+	case PLATFORM_DEVID_AUTO:
+		/*
+		 * Automatically allocated device ID. We mark it as such so
+		 * that we remember it must be freed, and we append a suffix
+		 * to avoid namespace collision with explicit IDs.
+		 */
+		ret = ida_simple_get(&platform_devid_ida, 0, 0, GFP_KERNEL);
+		if (ret < 0)
+			goto err_out;
+		pdev->id = ret;
+		pdev->id_auto = true;
+		dev_set_name(&pdev->dev, "%s.%d.auto", pdev->name, pdev->id);
+		break;
+	}
 
 	for (i = 0; i < pdev->num_resources; i++) {
 		struct resource *p, *r = &pdev->resource[i];
@@ -309,6 +334,11 @@ int platform_device_add(struct platform_device *pdev)
 		return ret;
 
  failed:
+	if (pdev->id_auto) {
+		ida_simple_remove(&platform_devid_ida, pdev->id);
+		pdev->id = PLATFORM_DEVID_AUTO;
+	}
+
 	while (--i >= 0) {
 		struct resource *r = &pdev->resource[i];
 		unsigned long type = resource_type(r);
@@ -317,6 +347,7 @@ int platform_device_add(struct platform_device *pdev)
 			release_resource(r);
 	}
 
+ err_out:
 	return ret;
 }
 EXPORT_SYMBOL_GPL(platform_device_add);
@@ -336,6 +367,11 @@ void platform_device_del(struct platform_device *pdev)
 	if (pdev) {
 		device_del(&pdev->dev);
 
+		if (pdev->id_auto) {
+			ida_simple_remove(&platform_devid_ida, pdev->id);
+			pdev->id = PLATFORM_DEVID_AUTO;
+		}
+
 		for (i = 0; i < pdev->num_resources; i++) {
 			struct resource *r = &pdev->resource[i];
 			unsigned long type = resource_type(r);
@@ -948,6 +984,7 @@ void __init early_platform_add_devices(struct platform_device **devs, int num)
 		dev = &devs[i]->dev;
 
 		if (!dev->devres_head.next) {
+			pm_runtime_early_init(dev);
 			INIT_LIST_HEAD(&dev->devres_head);
 			list_add_tail(&dev->devres_head,
 				      &early_platform_device_list);
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index ba3487c..c22b869 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -53,6 +53,24 @@
 static LIST_HEAD(gpd_list);
 static DEFINE_MUTEX(gpd_list_lock);
 
+static struct generic_pm_domain *pm_genpd_lookup_name(const char *domain_name)
+{
+	struct generic_pm_domain *genpd = NULL, *gpd;
+
+	if (IS_ERR_OR_NULL(domain_name))
+		return NULL;
+
+	mutex_lock(&gpd_list_lock);
+	list_for_each_entry(gpd, &gpd_list, gpd_list_node) {
+		if (!strcmp(gpd->name, domain_name)) {
+			genpd = gpd;
+			break;
+		}
+	}
+	mutex_unlock(&gpd_list_lock);
+	return genpd;
+}
+
 #ifdef CONFIG_PM
 
 struct generic_pm_domain *dev_to_genpd(struct device *dev)
@@ -256,10 +274,28 @@ int pm_genpd_poweron(struct generic_pm_domain *genpd)
 	return ret;
 }
 
+/**
+ * pm_genpd_name_poweron - Restore power to a given PM domain and its masters.
+ * @domain_name: Name of the PM domain to power up.
+ */
+int pm_genpd_name_poweron(const char *domain_name)
+{
+	struct generic_pm_domain *genpd;
+
+	genpd = pm_genpd_lookup_name(domain_name);
+	return genpd ? pm_genpd_poweron(genpd) : -EINVAL;
+}
+
 #endif /* CONFIG_PM */
 
 #ifdef CONFIG_PM_RUNTIME
 
+static int genpd_start_dev_no_timing(struct generic_pm_domain *genpd,
+				     struct device *dev)
+{
+	return GENPD_DEV_CALLBACK(genpd, int, start, dev);
+}
+
 static int genpd_save_dev(struct generic_pm_domain *genpd, struct device *dev)
 {
 	return GENPD_DEV_TIMED_CALLBACK(genpd, int, save_state, dev,
@@ -436,7 +472,7 @@ static int pm_genpd_poweroff(struct generic_pm_domain *genpd)
 	not_suspended = 0;
 	list_for_each_entry(pdd, &genpd->dev_list, list_node)
 		if (pdd->dev->driver && (!pm_runtime_suspended(pdd->dev)
-		    || pdd->dev->power.irq_safe || to_gpd_data(pdd)->always_on))
+		    || pdd->dev->power.irq_safe))
 			not_suspended++;
 
 	if (not_suspended > genpd->in_progress)
@@ -578,9 +614,6 @@ static int pm_genpd_runtime_suspend(struct device *dev)
 
 	might_sleep_if(!genpd->dev_irq_safe);
 
-	if (dev_gpd_data(dev)->always_on)
-		return -EBUSY;
-
 	stop_ok = genpd->gov ? genpd->gov->stop_ok : NULL;
 	if (stop_ok && !stop_ok(dev))
 		return -EBUSY;
@@ -629,7 +662,7 @@ static int pm_genpd_runtime_resume(struct device *dev)
 
 	/* If power.irq_safe, the PM domain is never powered off. */
 	if (dev->power.irq_safe)
-		return genpd_start_dev(genpd, dev);
+		return genpd_start_dev_no_timing(genpd, dev);
 
 	mutex_lock(&genpd->lock);
 	ret = __pm_genpd_poweron(genpd);
@@ -697,6 +730,24 @@ static inline void genpd_power_off_work_fn(struct work_struct *work) {}
 
 #ifdef CONFIG_PM_SLEEP
 
+/**
+ * pm_genpd_present - Check if the given PM domain has been initialized.
+ * @genpd: PM domain to check.
+ */
+static bool pm_genpd_present(struct generic_pm_domain *genpd)
+{
+	struct generic_pm_domain *gpd;
+
+	if (IS_ERR_OR_NULL(genpd))
+		return false;
+
+	list_for_each_entry(gpd, &gpd_list, gpd_list_node)
+		if (gpd == genpd)
+			return true;
+
+	return false;
+}
+
 static bool genpd_dev_active_wakeup(struct generic_pm_domain *genpd,
 				    struct device *dev)
 {
@@ -750,9 +801,10 @@ static int genpd_thaw_dev(struct generic_pm_domain *genpd, struct device *dev)
  * Check if the given PM domain can be powered off (during system suspend or
  * hibernation) and do that if so.  Also, in that case propagate to its masters.
  *
- * This function is only called in "noirq" stages of system power transitions,
- * so it need not acquire locks (all of the "noirq" callbacks are executed
- * sequentially, so it is guaranteed that it will never run twice in parallel).
+ * This function is only called in "noirq" and "syscore" stages of system power
+ * transitions, so it need not acquire locks (all of the "noirq" callbacks are
+ * executed sequentially, so it is guaranteed that it will never run twice in
+ * parallel).
  */
 static void pm_genpd_sync_poweroff(struct generic_pm_domain *genpd)
 {
@@ -777,6 +829,33 @@ static void pm_genpd_sync_poweroff(struct generic_pm_domain *genpd)
 }
 
 /**
+ * pm_genpd_sync_poweron - Synchronously power on a PM domain and its masters.
+ * @genpd: PM domain to power on.
+ *
+ * This function is only called in "noirq" and "syscore" stages of system power
+ * transitions, so it need not acquire locks (all of the "noirq" callbacks are
+ * executed sequentially, so it is guaranteed that it will never run twice in
+ * parallel).
+ */
+static void pm_genpd_sync_poweron(struct generic_pm_domain *genpd)
+{
+	struct gpd_link *link;
+
+	if (genpd->status != GPD_STATE_POWER_OFF)
+		return;
+
+	list_for_each_entry(link, &genpd->slave_links, slave_node) {
+		pm_genpd_sync_poweron(link->master);
+		genpd_sd_counter_inc(link->master);
+	}
+
+	if (genpd->power_on)
+		genpd->power_on(genpd);
+
+	genpd->status = GPD_STATE_ACTIVE;
+}
+
+/**
  * resume_needed - Check whether to resume a device before system suspend.
  * @dev: Device to check.
  * @genpd: PM domain the device belongs to.
@@ -937,7 +1016,7 @@ static int pm_genpd_suspend_noirq(struct device *dev)
 	if (IS_ERR(genpd))
 		return -EINVAL;
 
-	if (genpd->suspend_power_off || dev_gpd_data(dev)->always_on
+	if (genpd->suspend_power_off
 	    || (dev->power.wakeup_path && genpd_dev_active_wakeup(genpd, dev)))
 		return 0;
 
@@ -970,7 +1049,7 @@ static int pm_genpd_resume_noirq(struct device *dev)
 	if (IS_ERR(genpd))
 		return -EINVAL;
 
-	if (genpd->suspend_power_off || dev_gpd_data(dev)->always_on
+	if (genpd->suspend_power_off
 	    || (dev->power.wakeup_path && genpd_dev_active_wakeup(genpd, dev)))
 		return 0;
 
@@ -979,7 +1058,7 @@ static int pm_genpd_resume_noirq(struct device *dev)
 	 * guaranteed that this function will never run twice in parallel for
 	 * the same PM domain, so it is not necessary to use locking here.
 	 */
-	pm_genpd_poweron(genpd);
+	pm_genpd_sync_poweron(genpd);
 	genpd->suspended_count--;
 
 	return genpd_start_dev(genpd, dev);
@@ -1090,8 +1169,7 @@ static int pm_genpd_freeze_noirq(struct device *dev)
 	if (IS_ERR(genpd))
 		return -EINVAL;
 
-	return genpd->suspend_power_off || dev_gpd_data(dev)->always_on ?
-		0 : genpd_stop_dev(genpd, dev);
+	return genpd->suspend_power_off ? 0 : genpd_stop_dev(genpd, dev);
 }
 
 /**
@@ -1111,8 +1189,7 @@ static int pm_genpd_thaw_noirq(struct device *dev)
 	if (IS_ERR(genpd))
 		return -EINVAL;
 
-	return genpd->suspend_power_off || dev_gpd_data(dev)->always_on ?
-		0 : genpd_start_dev(genpd, dev);
+	return genpd->suspend_power_off ? 0 : genpd_start_dev(genpd, dev);
 }
 
 /**
@@ -1186,8 +1263,8 @@ static int pm_genpd_restore_noirq(struct device *dev)
 	if (genpd->suspended_count++ == 0) {
 		/*
 		 * The boot kernel might put the domain into arbitrary state,
-		 * so make it appear as powered off to pm_genpd_poweron(), so
-		 * that it tries to power it on in case it was really off.
+		 * so make it appear as powered off to pm_genpd_sync_poweron(),
+		 * so that it tries to power it on in case it was really off.
 		 */
 		genpd->status = GPD_STATE_POWER_OFF;
 		if (genpd->suspend_power_off) {
@@ -1205,9 +1282,9 @@ static int pm_genpd_restore_noirq(struct device *dev)
 	if (genpd->suspend_power_off)
 		return 0;
 
-	pm_genpd_poweron(genpd);
+	pm_genpd_sync_poweron(genpd);
 
-	return dev_gpd_data(dev)->always_on ? 0 : genpd_start_dev(genpd, dev);
+	return genpd_start_dev(genpd, dev);
 }
 
 /**
@@ -1246,6 +1323,31 @@ static void pm_genpd_complete(struct device *dev)
 	}
 }
 
+/**
+ * pm_genpd_syscore_switch - Switch power during system core suspend or resume.
+ * @dev: Device that normally is marked as "always on" to switch power for.
+ *
+ * This routine may only be called during the system core (syscore) suspend or
+ * resume phase for devices whose "always on" flags are set.
+ */
+void pm_genpd_syscore_switch(struct device *dev, bool suspend)
+{
+	struct generic_pm_domain *genpd;
+
+	genpd = dev_to_genpd(dev);
+	if (!pm_genpd_present(genpd))
+		return;
+
+	if (suspend) {
+		genpd->suspended_count++;
+		pm_genpd_sync_poweroff(genpd);
+	} else {
+		pm_genpd_sync_poweron(genpd);
+		genpd->suspended_count--;
+	}
+}
+EXPORT_SYMBOL_GPL(pm_genpd_syscore_switch);
+
 #else
 
 #define pm_genpd_prepare		NULL
@@ -1393,6 +1495,19 @@ int __pm_genpd_of_add_device(struct device_node *genpd_node, struct device *dev,
 	return __pm_genpd_add_device(genpd, dev, td);
 }
 
+
+/**
+ * __pm_genpd_name_add_device - Find I/O PM domain and add a device to it.
+ * @domain_name: Name of the PM domain to add the device to.
+ * @dev: Device to be added.
+ * @td: Set of PM QoS timing parameters to attach to the device.
+ */
+int __pm_genpd_name_add_device(const char *domain_name, struct device *dev,
+			       struct gpd_timing_data *td)
+{
+	return __pm_genpd_add_device(pm_genpd_lookup_name(domain_name), dev, td);
+}
+
 /**
  * pm_genpd_remove_device - Remove a device from an I/O PM domain.
  * @genpd: PM domain to remove the device from.
@@ -1455,26 +1570,6 @@ int pm_genpd_remove_device(struct generic_pm_domain *genpd,
 }
 
 /**
- * pm_genpd_dev_always_on - Set/unset the "always on" flag for a given device.
- * @dev: Device to set/unset the flag for.
- * @val: The new value of the device's "always on" flag.
- */
-void pm_genpd_dev_always_on(struct device *dev, bool val)
-{
-	struct pm_subsys_data *psd;
-	unsigned long flags;
-
-	spin_lock_irqsave(&dev->power.lock, flags);
-
-	psd = dev_to_psd(dev);
-	if (psd && psd->domain_data)
-		to_gpd_data(psd->domain_data)->always_on = val;
-
-	spin_unlock_irqrestore(&dev->power.lock, flags);
-}
-EXPORT_SYMBOL_GPL(pm_genpd_dev_always_on);
-
-/**
  * pm_genpd_dev_need_restore - Set/unset the device's "need restore" flag.
  * @dev: Device to set/unset the flag for.
  * @val: The new value of the device's "need restore" flag.
@@ -1505,7 +1600,8 @@ int pm_genpd_add_subdomain(struct generic_pm_domain *genpd,
 	struct gpd_link *link;
 	int ret = 0;
 
-	if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(subdomain))
+	if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(subdomain)
+	    || genpd == subdomain)
 		return -EINVAL;
 
  start:
@@ -1552,6 +1648,35 @@ int pm_genpd_add_subdomain(struct generic_pm_domain *genpd,
 }
 
 /**
+ * pm_genpd_add_subdomain_names - Add a subdomain to an I/O PM domain.
+ * @master_name: Name of the master PM domain to add the subdomain to.
+ * @subdomain_name: Name of the subdomain to be added.
+ */
+int pm_genpd_add_subdomain_names(const char *master_name,
+				 const char *subdomain_name)
+{
+	struct generic_pm_domain *master = NULL, *subdomain = NULL, *gpd;
+
+	if (IS_ERR_OR_NULL(master_name) || IS_ERR_OR_NULL(subdomain_name))
+		return -EINVAL;
+
+	mutex_lock(&gpd_list_lock);
+	list_for_each_entry(gpd, &gpd_list, gpd_list_node) {
+		if (!master && !strcmp(gpd->name, master_name))
+			master = gpd;
+
+		if (!subdomain && !strcmp(gpd->name, subdomain_name))
+			subdomain = gpd;
+
+		if (master && subdomain)
+			break;
+	}
+	mutex_unlock(&gpd_list_lock);
+
+	return pm_genpd_add_subdomain(master, subdomain);
+}
+
+/**
  * pm_genpd_remove_subdomain - Remove a subdomain from an I/O PM domain.
  * @genpd: Master PM domain to remove the subdomain from.
  * @subdomain: Subdomain to be removed.
@@ -1704,7 +1829,16 @@ int __pm_genpd_remove_callbacks(struct device *dev, bool clear_td)
 }
 EXPORT_SYMBOL_GPL(__pm_genpd_remove_callbacks);
 
-int genpd_attach_cpuidle(struct generic_pm_domain *genpd, int state)
+/**
+ * pm_genpd_attach_cpuidle - Connect the given PM domain with cpuidle.
+ * @genpd: PM domain to be connected with cpuidle.
+ * @state: cpuidle state this domain can disable/enable.
+ *
+ * Make a PM domain behave as though it contained a CPU core, that is, instead
+ * of calling its power down routine it will enable the given cpuidle state so
+ * that the cpuidle subsystem can power it down (if possible and desirable).
+ */
+int pm_genpd_attach_cpuidle(struct generic_pm_domain *genpd, int state)
 {
 	struct cpuidle_driver *cpuidle_drv;
 	struct gpd_cpu_data *cpu_data;
@@ -1753,7 +1887,24 @@ int genpd_attach_cpuidle(struct generic_pm_domain *genpd, int state)
 	goto out;
 }
 
-int genpd_detach_cpuidle(struct generic_pm_domain *genpd)
+/**
+ * pm_genpd_name_attach_cpuidle - Find PM domain and connect cpuidle to it.
+ * @name: Name of the domain to connect to cpuidle.
+ * @state: cpuidle state this domain can manipulate.
+ */
+int pm_genpd_name_attach_cpuidle(const char *name, int state)
+{
+	return pm_genpd_attach_cpuidle(pm_genpd_lookup_name(name), state);
+}
+
+/**
+ * pm_genpd_detach_cpuidle - Remove the cpuidle connection from a PM domain.
+ * @genpd: PM domain to remove the cpuidle connection from.
+ *
+ * Remove the cpuidle connection set up by pm_genpd_attach_cpuidle() from the
+ * given PM domain.
+ */
+int pm_genpd_detach_cpuidle(struct generic_pm_domain *genpd)
 {
 	struct gpd_cpu_data *cpu_data;
 	struct cpuidle_state *idle_state;
@@ -1784,6 +1935,15 @@ int genpd_detach_cpuidle(struct generic_pm_domain *genpd)
 	return ret;
 }
 
+/**
+ * pm_genpd_name_detach_cpuidle - Find PM domain and disconnect cpuidle from it.
+ * @name: Name of the domain to disconnect cpuidle from.
+ */
+int pm_genpd_name_detach_cpuidle(const char *name)
+{
+	return pm_genpd_detach_cpuidle(pm_genpd_lookup_name(name));
+}
+
 /* Default device callbacks for generic PM domains. */
 
 /**
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index 0113adc..a3c1404 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -57,20 +57,17 @@ static pm_message_t pm_transition;
 static int async_error;
 
 /**
- * device_pm_init - Initialize the PM-related part of a device object.
+ * device_pm_sleep_init - Initialize system suspend-related device fields.
  * @dev: Device object being initialized.
  */
-void device_pm_init(struct device *dev)
+void device_pm_sleep_init(struct device *dev)
 {
 	dev->power.is_prepared = false;
 	dev->power.is_suspended = false;
 	init_completion(&dev->power.completion);
 	complete_all(&dev->power.completion);
 	dev->power.wakeup = NULL;
-	spin_lock_init(&dev->power.lock);
-	pm_runtime_init(dev);
 	INIT_LIST_HEAD(&dev->power.entry);
-	dev->power.power_state = PMSG_INVALID;
 }
 
 /**
@@ -408,6 +405,9 @@ static int device_resume_noirq(struct device *dev, pm_message_t state)
 	TRACE_DEVICE(dev);
 	TRACE_RESUME(0);
 
+	if (dev->power.syscore)
+		goto Out;
+
 	if (dev->pm_domain) {
 		info = "noirq power domain ";
 		callback = pm_noirq_op(&dev->pm_domain->ops, state);
@@ -429,6 +429,7 @@ static int device_resume_noirq(struct device *dev, pm_message_t state)
 
 	error = dpm_run_callback(callback, dev, state, info);
 
+ Out:
 	TRACE_RESUME(error);
 	return error;
 }
@@ -486,6 +487,9 @@ static int device_resume_early(struct device *dev, pm_message_t state)
 	TRACE_DEVICE(dev);
 	TRACE_RESUME(0);
 
+	if (dev->power.syscore)
+		goto Out;
+
 	if (dev->pm_domain) {
 		info = "early power domain ";
 		callback = pm_late_early_op(&dev->pm_domain->ops, state);
@@ -507,6 +511,7 @@ static int device_resume_early(struct device *dev, pm_message_t state)
 
 	error = dpm_run_callback(callback, dev, state, info);
 
+ Out:
 	TRACE_RESUME(error);
 	return error;
 }
@@ -565,11 +570,13 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
 	pm_callback_t callback = NULL;
 	char *info = NULL;
 	int error = 0;
-	bool put = false;
 
 	TRACE_DEVICE(dev);
 	TRACE_RESUME(0);
 
+	if (dev->power.syscore)
+		goto Complete;
+
 	dpm_wait(dev->parent, async);
 	device_lock(dev);
 
@@ -583,7 +590,6 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
 		goto Unlock;
 
 	pm_runtime_enable(dev);
-	put = true;
 
 	if (dev->pm_domain) {
 		info = "power domain ";
@@ -632,13 +638,12 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
 
  Unlock:
 	device_unlock(dev);
+
+ Complete:
 	complete_all(&dev->power.completion);
 
 	TRACE_RESUME(error);
 
-	if (put)
-		pm_runtime_put_sync(dev);
-
 	return error;
 }
 
@@ -722,6 +727,9 @@ static void device_complete(struct device *dev, pm_message_t state)
 	void (*callback)(struct device *) = NULL;
 	char *info = NULL;
 
+	if (dev->power.syscore)
+		return;
+
 	device_lock(dev);
 
 	if (dev->pm_domain) {
@@ -749,6 +757,8 @@ static void device_complete(struct device *dev, pm_message_t state)
 	}
 
 	device_unlock(dev);
+
+	pm_runtime_put_sync(dev);
 }
 
 /**
@@ -834,6 +844,9 @@ static int device_suspend_noirq(struct device *dev, pm_message_t state)
 	pm_callback_t callback = NULL;
 	char *info = NULL;
 
+	if (dev->power.syscore)
+		return 0;
+
 	if (dev->pm_domain) {
 		info = "noirq power domain ";
 		callback = pm_noirq_op(&dev->pm_domain->ops, state);
@@ -917,6 +930,9 @@ static int device_suspend_late(struct device *dev, pm_message_t state)
 	pm_callback_t callback = NULL;
 	char *info = NULL;
 
+	if (dev->power.syscore)
+		return 0;
+
 	if (dev->pm_domain) {
 		info = "late power domain ";
 		callback = pm_late_early_op(&dev->pm_domain->ops, state);
@@ -996,7 +1012,7 @@ int dpm_suspend_end(pm_message_t state)
 
 	error = dpm_suspend_noirq(state);
 	if (error) {
-		dpm_resume_early(state);
+		dpm_resume_early(resume_event(state));
 		return error;
 	}
 
@@ -1043,16 +1059,23 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
 	if (async_error)
 		goto Complete;
 
-	pm_runtime_get_noresume(dev);
+	/*
+	 * If a device configured to wake up the system from sleep states
+	 * has been suspended at run time and there's a resume request pending
+	 * for it, this is equivalent to the device signaling wakeup, so the
+	 * system suspend operation should be aborted.
+	 */
 	if (pm_runtime_barrier(dev) && device_may_wakeup(dev))
 		pm_wakeup_event(dev, 0);
 
 	if (pm_wakeup_pending()) {
-		pm_runtime_put_sync(dev);
 		async_error = -EBUSY;
 		goto Complete;
 	}
 
+	if (dev->power.syscore)
+		goto Complete;
+
 	device_lock(dev);
 
 	if (dev->pm_domain) {
@@ -1111,12 +1134,10 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
  Complete:
 	complete_all(&dev->power.completion);
 
-	if (error) {
-		pm_runtime_put_sync(dev);
+	if (error)
 		async_error = error;
-	} else if (dev->power.is_suspended) {
+	else if (dev->power.is_suspended)
 		__pm_runtime_disable(dev, false);
-	}
 
 	return error;
 }
@@ -1209,6 +1230,17 @@ static int device_prepare(struct device *dev, pm_message_t state)
 	char *info = NULL;
 	int error = 0;
 
+	if (dev->power.syscore)
+		return 0;
+
+	/*
+	 * If a device's parent goes into runtime suspend at the wrong time,
+	 * it won't be possible to resume the device.  To prevent this we
+	 * block runtime suspend here, during the prepare phase, and allow
+	 * it again during the complete phase.
+	 */
+	pm_runtime_get_noresume(dev);
+
 	device_lock(dev);
 
 	dev->power.wakeup_path = device_may_wakeup(dev);
@@ -1324,3 +1356,25 @@ int device_pm_wait_for_dev(struct device *subordinate, struct device *dev)
 	return async_error;
 }
 EXPORT_SYMBOL_GPL(device_pm_wait_for_dev);
+
+/**
+ * dpm_for_each_dev - device iterator.
+ * @data: data for the callback.
+ * @fn: function to be called for each device.
+ *
+ * Iterate over devices in dpm_list, and call @fn for each device,
+ * passing it @data.
+ */
+void dpm_for_each_dev(void *data, void (*fn)(struct device *, void *))
+{
+	struct device *dev;
+
+	if (!fn)
+		return;
+
+	device_pm_lock();
+	list_for_each_entry(dev, &dpm_list, power.entry)
+		fn(dev, data);
+	device_pm_unlock();
+}
+EXPORT_SYMBOL_GPL(dpm_for_each_dev);
diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c
index ac993ea..d946864 100644
--- a/drivers/base/power/opp.c
+++ b/drivers/base/power/opp.c
@@ -22,6 +22,7 @@
 #include <linux/rculist.h>
 #include <linux/rcupdate.h>
 #include <linux/opp.h>
+#include <linux/of.h>
 
 /*
  * Internal data structure organization with the OPP layer library is as
@@ -674,3 +675,49 @@ struct srcu_notifier_head *opp_get_notifier(struct device *dev)
 
 	return &dev_opp->head;
 }
+
+#ifdef CONFIG_OF
+/**
+ * of_init_opp_table() - Initialize opp table from device tree
+ * @dev:	device pointer used to lookup device OPPs.
+ *
+ * Register the initial OPP table with the OPP library for given device.
+ */
+int of_init_opp_table(struct device *dev)
+{
+	const struct property *prop;
+	const __be32 *val;
+	int nr;
+
+	prop = of_find_property(dev->of_node, "operating-points", NULL);
+	if (!prop)
+		return -ENODEV;
+	if (!prop->value)
+		return -ENODATA;
+
+	/*
+	 * Each OPP is a set of tuples consisting of frequency and
+	 * voltage like <freq-kHz vol-uV>.
+	 */
+	nr = prop->length / sizeof(u32);
+	if (nr % 2) {
+		dev_err(dev, "%s: Invalid OPP list\n", __func__);
+		return -EINVAL;
+	}
+
+	val = prop->value;
+	while (nr) {
+		unsigned long freq = be32_to_cpup(val++) * 1000;
+		unsigned long volt = be32_to_cpup(val++);
+
+		if (opp_add(dev, freq, volt)) {
+			dev_warn(dev, "%s: Failed to add OPP %ld\n",
+				 __func__, freq);
+			continue;
+		}
+		nr -= 2;
+	}
+
+	return 0;
+}
+#endif
diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h
index eeb4bff..0dbfdf4 100644
--- a/drivers/base/power/power.h
+++ b/drivers/base/power/power.h
@@ -1,12 +1,32 @@
 #include <linux/pm_qos.h>
 
+static inline void device_pm_init_common(struct device *dev)
+{
+	if (!dev->power.early_init) {
+		spin_lock_init(&dev->power.lock);
+		dev->power.power_state = PMSG_INVALID;
+		dev->power.early_init = true;
+	}
+}
+
 #ifdef CONFIG_PM_RUNTIME
 
+static inline void pm_runtime_early_init(struct device *dev)
+{
+	dev->power.disable_depth = 1;
+	device_pm_init_common(dev);
+}
+
 extern void pm_runtime_init(struct device *dev);
 extern void pm_runtime_remove(struct device *dev);
 
 #else /* !CONFIG_PM_RUNTIME */
 
+static inline void pm_runtime_early_init(struct device *dev)
+{
+	device_pm_init_common(dev);
+}
+
 static inline void pm_runtime_init(struct device *dev) {}
 static inline void pm_runtime_remove(struct device *dev) {}
 
@@ -25,7 +45,7 @@ static inline struct device *to_device(struct list_head *entry)
 	return container_of(entry, struct device, power.entry);
 }
 
-extern void device_pm_init(struct device *dev);
+extern void device_pm_sleep_init(struct device *dev);
 extern void device_pm_add(struct device *);
 extern void device_pm_remove(struct device *);
 extern void device_pm_move_before(struct device *, struct device *);
@@ -34,12 +54,7 @@ extern void device_pm_move_last(struct device *);
 
 #else /* !CONFIG_PM_SLEEP */
 
-static inline void device_pm_init(struct device *dev)
-{
-	spin_lock_init(&dev->power.lock);
-	dev->power.power_state = PMSG_INVALID;
-	pm_runtime_init(dev);
-}
+static inline void device_pm_sleep_init(struct device *dev) {}
 
 static inline void device_pm_add(struct device *dev)
 {
@@ -60,6 +75,13 @@ static inline void device_pm_move_last(struct device *dev) {}
 
 #endif /* !CONFIG_PM_SLEEP */
 
+static inline void device_pm_init(struct device *dev)
+{
+	device_pm_init_common(dev);
+	device_pm_sleep_init(dev);
+	pm_runtime_init(dev);
+}
+
 #ifdef CONFIG_PM
 
 /*
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index 7d9c1cb..3148b10 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -509,6 +509,9 @@ static int rpm_resume(struct device *dev, int rpmflags)
  repeat:
 	if (dev->power.runtime_error)
 		retval = -EINVAL;
+	else if (dev->power.disable_depth == 1 && dev->power.is_suspended
+	    && dev->power.runtime_status == RPM_ACTIVE)
+		retval = 1;
 	else if (dev->power.disable_depth > 0)
 		retval = -EACCES;
 	if (retval)
diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c
index cbb463b..e6ee5e8 100644
--- a/drivers/base/power/wakeup.c
+++ b/drivers/base/power/wakeup.c
@@ -127,6 +127,8 @@ EXPORT_SYMBOL_GPL(wakeup_source_destroy);
  */
 void wakeup_source_add(struct wakeup_source *ws)
 {
+	unsigned long flags;
+
 	if (WARN_ON(!ws))
 		return;
 
@@ -135,9 +137,9 @@ void wakeup_source_add(struct wakeup_source *ws)
 	ws->active = false;
 	ws->last_time = ktime_get();
 
-	spin_lock_irq(&events_lock);
+	spin_lock_irqsave(&events_lock, flags);
 	list_add_rcu(&ws->entry, &wakeup_sources);
-	spin_unlock_irq(&events_lock);
+	spin_unlock_irqrestore(&events_lock, flags);
 }
 EXPORT_SYMBOL_GPL(wakeup_source_add);
 
@@ -147,12 +149,14 @@ EXPORT_SYMBOL_GPL(wakeup_source_add);
  */
 void wakeup_source_remove(struct wakeup_source *ws)
 {
+	unsigned long flags;
+
 	if (WARN_ON(!ws))
 		return;
 
-	spin_lock_irq(&events_lock);
+	spin_lock_irqsave(&events_lock, flags);
 	list_del_rcu(&ws->entry);
-	spin_unlock_irq(&events_lock);
+	spin_unlock_irqrestore(&events_lock, flags);
 	synchronize_rcu();
 }
 EXPORT_SYMBOL_GPL(wakeup_source_remove);
@@ -649,6 +653,31 @@ void pm_wakeup_event(struct device *dev, unsigned int msec)
 }
 EXPORT_SYMBOL_GPL(pm_wakeup_event);
 
+static void print_active_wakeup_sources(void)
+{
+	struct wakeup_source *ws;
+	int active = 0;
+	struct wakeup_source *last_activity_ws = NULL;
+
+	rcu_read_lock();
+	list_for_each_entry_rcu(ws, &wakeup_sources, entry) {
+		if (ws->active) {
+			pr_info("active wakeup source: %s\n", ws->name);
+			active = 1;
+		} else if (!active &&
+			   (!last_activity_ws ||
+			    ktime_to_ns(ws->last_time) >
+			    ktime_to_ns(last_activity_ws->last_time))) {
+			last_activity_ws = ws;
+		}
+	}
+
+	if (!active && last_activity_ws)
+		pr_info("last active wakeup source: %s\n",
+			last_activity_ws->name);
+	rcu_read_unlock();
+}
+
 /**
  * pm_wakeup_pending - Check if power transition in progress should be aborted.
  *
@@ -671,6 +700,10 @@ bool pm_wakeup_pending(void)
 		events_check_enabled = !ret;
 	}
 	spin_unlock_irqrestore(&events_lock, flags);
+
+	if (ret)
+		print_active_wakeup_sources();
+
 	return ret;
 }
 
@@ -723,15 +756,16 @@ bool pm_get_wakeup_count(unsigned int *count, bool block)
 bool pm_save_wakeup_count(unsigned int count)
 {
 	unsigned int cnt, inpr;
+	unsigned long flags;
 
 	events_check_enabled = false;
-	spin_lock_irq(&events_lock);
+	spin_lock_irqsave(&events_lock, flags);
 	split_counters(&cnt, &inpr);
 	if (cnt == count && inpr == 0) {
 		saved_count = count;
 		events_check_enabled = true;
 	}
-	spin_unlock_irq(&events_lock);
+	spin_unlock_irqrestore(&events_lock, flags);
 	return events_check_enabled;
 }
 
diff --git a/drivers/base/regmap/regmap-irq.c b/drivers/base/regmap/regmap-irq.c
index a897346..5b6b1d8 100644
--- a/drivers/base/regmap/regmap-irq.c
+++ b/drivers/base/regmap/regmap-irq.c
@@ -16,12 +16,14 @@
 #include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/irqdomain.h>
+#include <linux/pm_runtime.h>
 #include <linux/slab.h>
 
 #include "internal.h"
 
 struct regmap_irq_chip_data {
 	struct mutex lock;
+	struct irq_chip irq_chip;
 
 	struct regmap *map;
 	const struct regmap_irq_chip *chip;
@@ -59,6 +61,14 @@ static void regmap_irq_sync_unlock(struct irq_data *data)
 	struct regmap_irq_chip_data *d = irq_data_get_irq_chip_data(data);
 	struct regmap *map = d->map;
 	int i, ret;
+	u32 reg;
+
+	if (d->chip->runtime_pm) {
+		ret = pm_runtime_get_sync(map->dev);
+		if (ret < 0)
+			dev_err(map->dev, "IRQ sync failed to resume: %d\n",
+				ret);
+	}
 
 	/*
 	 * If there's been a change in the mask write it back to the
@@ -66,15 +76,22 @@ static void regmap_irq_sync_unlock(struct irq_data *data)
 	 * suppress pointless writes.
 	 */
 	for (i = 0; i < d->chip->num_regs; i++) {
-		ret = regmap_update_bits(d->map, d->chip->mask_base +
-						(i * map->reg_stride *
-						d->irq_reg_stride),
+		reg = d->chip->mask_base +
+			(i * map->reg_stride * d->irq_reg_stride);
+		if (d->chip->mask_invert)
+			ret = regmap_update_bits(d->map, reg,
+					 d->mask_buf_def[i], ~d->mask_buf[i]);
+		else
+			ret = regmap_update_bits(d->map, reg,
 					 d->mask_buf_def[i], d->mask_buf[i]);
 		if (ret != 0)
 			dev_err(d->map->dev, "Failed to sync masks in %x\n",
-				d->chip->mask_base + (i * map->reg_stride));
+				reg);
 	}
 
+	if (d->chip->runtime_pm)
+		pm_runtime_put(map->dev);
+
 	/* If we've changed our wakeup count propagate it to the parent */
 	if (d->wake_count < 0)
 		for (i = d->wake_count; i < 0; i++)
@@ -128,8 +145,7 @@ static int regmap_irq_set_wake(struct irq_data *data, unsigned int on)
 	return 0;
 }
 
-static struct irq_chip regmap_irq_chip = {
-	.name			= "regmap",
+static const struct irq_chip regmap_irq_chip = {
 	.irq_bus_lock		= regmap_irq_lock,
 	.irq_bus_sync_unlock	= regmap_irq_sync_unlock,
 	.irq_disable		= regmap_irq_disable,
@@ -144,6 +160,16 @@ static irqreturn_t regmap_irq_thread(int irq, void *d)
 	struct regmap *map = data->map;
 	int ret, i;
 	bool handled = false;
+	u32 reg;
+
+	if (chip->runtime_pm) {
+		ret = pm_runtime_get_sync(map->dev);
+		if (ret < 0) {
+			dev_err(map->dev, "IRQ thread failed to resume: %d\n",
+				ret);
+			return IRQ_NONE;
+		}
+	}
 
 	/*
 	 * Ignore masked IRQs and ack if we need to; we ack early so
@@ -160,20 +186,20 @@ static irqreturn_t regmap_irq_thread(int irq, void *d)
 		if (ret != 0) {
 			dev_err(map->dev, "Failed to read IRQ status: %d\n",
 					ret);
+			if (chip->runtime_pm)
+				pm_runtime_put(map->dev);
 			return IRQ_NONE;
 		}
 
 		data->status_buf[i] &= ~data->mask_buf[i];
 
 		if (data->status_buf[i] && chip->ack_base) {
-			ret = regmap_write(map, chip->ack_base +
-						(i * map->reg_stride *
-						data->irq_reg_stride),
-					   data->status_buf[i]);
+			reg = chip->ack_base +
+				(i * map->reg_stride * data->irq_reg_stride);
+			ret = regmap_write(map, reg, data->status_buf[i]);
 			if (ret != 0)
 				dev_err(map->dev, "Failed to ack 0x%x: %d\n",
-					chip->ack_base + (i * map->reg_stride),
-					ret);
+					reg, ret);
 		}
 	}
 
@@ -185,6 +211,9 @@ static irqreturn_t regmap_irq_thread(int irq, void *d)
 		}
 	}
 
+	if (chip->runtime_pm)
+		pm_runtime_put(map->dev);
+
 	if (handled)
 		return IRQ_HANDLED;
 	else
@@ -197,7 +226,7 @@ static int regmap_irq_map(struct irq_domain *h, unsigned int virq,
 	struct regmap_irq_chip_data *data = h->host_data;
 
 	irq_set_chip_data(virq, data);
-	irq_set_chip_and_handler(virq, &regmap_irq_chip, handle_edge_irq);
+	irq_set_chip(virq, &data->irq_chip);
 	irq_set_nested_thread(virq, 1);
 
 	/* ARM needs us to explicitly flag the IRQ as valid
@@ -238,6 +267,7 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
 	struct regmap_irq_chip_data *d;
 	int i;
 	int ret = -ENOMEM;
+	u32 reg;
 
 	for (i = 0; i < chip->num_irqs; i++) {
 		if (chip->irqs[i].reg_offset % map->reg_stride)
@@ -284,6 +314,13 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
 			goto err_alloc;
 	}
 
+	d->irq_chip = regmap_irq_chip;
+	d->irq_chip.name = chip->name;
+	if (!chip->wake_base) {
+		d->irq_chip.irq_set_wake = NULL;
+		d->irq_chip.flags |= IRQCHIP_MASK_ON_SUSPEND |
+				     IRQCHIP_SKIP_SET_WAKE;
+	}
 	d->irq = irq;
 	d->map = map;
 	d->chip = chip;
@@ -303,16 +340,37 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
 	/* Mask all the interrupts by default */
 	for (i = 0; i < chip->num_regs; i++) {
 		d->mask_buf[i] = d->mask_buf_def[i];
-		ret = regmap_write(map, chip->mask_base + (i * map->reg_stride
-				   * d->irq_reg_stride),
-				   d->mask_buf[i]);
+		reg = chip->mask_base +
+			(i * map->reg_stride * d->irq_reg_stride);
+		if (chip->mask_invert)
+			ret = regmap_update_bits(map, reg,
+					 d->mask_buf[i], ~d->mask_buf[i]);
+		else
+			ret = regmap_update_bits(map, reg,
+					 d->mask_buf[i], d->mask_buf[i]);
 		if (ret != 0) {
 			dev_err(map->dev, "Failed to set masks in 0x%x: %d\n",
-				chip->mask_base + (i * map->reg_stride), ret);
+				reg, ret);
 			goto err_alloc;
 		}
 	}
 
+	/* Wake is disabled by default */
+	if (d->wake_buf) {
+		for (i = 0; i < chip->num_regs; i++) {
+			d->wake_buf[i] = d->mask_buf_def[i];
+			reg = chip->wake_base +
+				(i * map->reg_stride * d->irq_reg_stride);
+			ret = regmap_update_bits(map, reg, d->wake_buf[i],
+						 d->wake_buf[i]);
+			if (ret != 0) {
+				dev_err(map->dev, "Failed to set masks in 0x%x: %d\n",
+					reg, ret);
+				goto err_alloc;
+			}
+		}
+	}
+
 	if (irq_base)
 		d->domain = irq_domain_add_legacy(map->dev->of_node,
 						  chip->num_irqs, irq_base, 0,
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index c241ae2..52069d2 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -659,13 +659,12 @@ EXPORT_SYMBOL_GPL(devm_regmap_init);
  * new cache.  This can be used to restore the cache to defaults or to
  * update the cache configuration to reflect runtime discovery of the
  * hardware.
+ *
+ * No explicit locking is done here, the user needs to ensure that
+ * this function will not race with other calls to regmap.
  */
 int regmap_reinit_cache(struct regmap *map, const struct regmap_config *config)
 {
-	int ret;
-
-	map->lock(map);
-
 	regcache_exit(map);
 	regmap_debugfs_exit(map);
 
@@ -681,11 +680,7 @@ int regmap_reinit_cache(struct regmap *map, const struct regmap_config *config)
 	map->cache_bypass = false;
 	map->cache_only = false;
 
-	ret = regcache_init(map, config);
-
-	map->unlock(map);
-
-	return ret;
+	return regcache_init(map, config);
 }
 EXPORT_SYMBOL_GPL(regmap_reinit_cache);
 
diff --git a/drivers/bcma/Kconfig b/drivers/bcma/Kconfig
index 06b3207..a533af2 100644
--- a/drivers/bcma/Kconfig
+++ b/drivers/bcma/Kconfig
@@ -48,12 +48,12 @@ config BCMA_DRIVER_MIPS
 
 config BCMA_SFLASH
 	bool
-	depends on BCMA_DRIVER_MIPS && BROKEN
+	depends on BCMA_DRIVER_MIPS
 	default y
 
 config BCMA_NFLASH
 	bool
-	depends on BCMA_DRIVER_MIPS && BROKEN
+	depends on BCMA_DRIVER_MIPS
 	default y
 
 config BCMA_DRIVER_GMAC_CMN
diff --git a/drivers/bcma/bcma_private.h b/drivers/bcma/bcma_private.h
index 3cf9cc9..169fc58 100644
--- a/drivers/bcma/bcma_private.h
+++ b/drivers/bcma/bcma_private.h
@@ -54,6 +54,7 @@ u32 bcma_pmu_get_clockcpu(struct bcma_drv_cc *cc);
 #ifdef CONFIG_BCMA_SFLASH
 /* driver_chipcommon_sflash.c */
 int bcma_sflash_init(struct bcma_drv_cc *cc);
+extern struct platform_device bcma_sflash_dev;
 #else
 static inline int bcma_sflash_init(struct bcma_drv_cc *cc)
 {
@@ -65,6 +66,7 @@ static inline int bcma_sflash_init(struct bcma_drv_cc *cc)
 #ifdef CONFIG_BCMA_NFLASH
 /* driver_chipcommon_nflash.c */
 int bcma_nflash_init(struct bcma_drv_cc *cc);
+extern struct platform_device bcma_nflash_dev;
 #else
 static inline int bcma_nflash_init(struct bcma_drv_cc *cc)
 {
diff --git a/drivers/bcma/driver_chipcommon_nflash.c b/drivers/bcma/driver_chipcommon_nflash.c
index 574d624..9042781 100644
--- a/drivers/bcma/driver_chipcommon_nflash.c
+++ b/drivers/bcma/driver_chipcommon_nflash.c
@@ -5,15 +5,37 @@
  * Licensed under the GNU/GPL. See COPYING for details.
  */
 
+#include <linux/platform_device.h>
 #include <linux/bcma/bcma.h>
-#include <linux/bcma/bcma_driver_chipcommon.h>
-#include <linux/delay.h>
 
 #include "bcma_private.h"
 
+struct platform_device bcma_nflash_dev = {
+	.name		= "bcma_nflash",
+	.num_resources	= 0,
+};
+
 /* Initialize NAND flash access */
 int bcma_nflash_init(struct bcma_drv_cc *cc)
 {
-	bcma_err(cc->core->bus, "NAND flash support is broken\n");
+	struct bcma_bus *bus = cc->core->bus;
+
+	if (bus->chipinfo.id != BCMA_CHIP_ID_BCM4706 &&
+	    cc->core->id.rev != 0x38) {
+		bcma_err(bus, "NAND flash on unsupported board!\n");
+		return -ENOTSUPP;
+	}
+
+	if (!(cc->capabilities & BCMA_CC_CAP_NFLASH)) {
+		bcma_err(bus, "NAND flash not present according to ChipCommon\n");
+		return -ENODEV;
+	}
+
+	cc->nflash.present = true;
+
+	/* Prepare platform device, but don't register it yet. It's too early,
+	 * malloc (required by device_private_init) is not available yet. */
+	bcma_nflash_dev.dev.platform_data = &cc->nflash;
+
 	return 0;
 }
diff --git a/drivers/bcma/driver_chipcommon_pmu.c b/drivers/bcma/driver_chipcommon_pmu.c
index c9a4f46..8b8f2f3 100644
--- a/drivers/bcma/driver_chipcommon_pmu.c
+++ b/drivers/bcma/driver_chipcommon_pmu.c
@@ -101,7 +101,7 @@ void bcma_chipco_bcm4331_ext_pa_lines_ctl(struct bcma_drv_cc *cc, bool enable)
 	bcma_cc_write32(cc, BCMA_CC_CHIPCTL, val);
 }
 
-void bcma_pmu_workarounds(struct bcma_drv_cc *cc)
+static void bcma_pmu_workarounds(struct bcma_drv_cc *cc)
 {
 	struct bcma_bus *bus = cc->core->bus;
 
@@ -257,7 +257,7 @@ static u32 bcma_pmu_clock_bcm4706(struct bcma_drv_cc *cc, u32 pll0, u32 m)
 }
 
 /* query bus clock frequency for PMU-enabled chipcommon */
-u32 bcma_pmu_get_clockcontrol(struct bcma_drv_cc *cc)
+static u32 bcma_pmu_get_clockcontrol(struct bcma_drv_cc *cc)
 {
 	struct bcma_bus *bus = cc->core->bus;
 
diff --git a/drivers/bcma/driver_chipcommon_sflash.c b/drivers/bcma/driver_chipcommon_sflash.c
index 6e157a5..2c4eec2 100644
--- a/drivers/bcma/driver_chipcommon_sflash.c
+++ b/drivers/bcma/driver_chipcommon_sflash.c
@@ -5,15 +5,132 @@
  * Licensed under the GNU/GPL. See COPYING for details.
  */
 
+#include <linux/platform_device.h>
 #include <linux/bcma/bcma.h>
-#include <linux/bcma/bcma_driver_chipcommon.h>
-#include <linux/delay.h>
 
 #include "bcma_private.h"
 
+static struct resource bcma_sflash_resource = {
+	.name	= "bcma_sflash",
+	.start	= BCMA_SFLASH,
+	.end	= 0,
+	.flags  = IORESOURCE_MEM | IORESOURCE_READONLY,
+};
+
+struct platform_device bcma_sflash_dev = {
+	.name		= "bcma_sflash",
+	.resource	= &bcma_sflash_resource,
+	.num_resources	= 1,
+};
+
+struct bcma_sflash_tbl_e {
+	char *name;
+	u32 id;
+	u32 blocksize;
+	u16 numblocks;
+};
+
+static struct bcma_sflash_tbl_e bcma_sflash_st_tbl[] = {
+	{ "", 0x14, 0x10000, 32, },
+	{ 0 },
+};
+
+static struct bcma_sflash_tbl_e bcma_sflash_sst_tbl[] = {
+	{ 0 },
+};
+
+static struct bcma_sflash_tbl_e bcma_sflash_at_tbl[] = {
+	{ 0 },
+};
+
+static void bcma_sflash_cmd(struct bcma_drv_cc *cc, u32 opcode)
+{
+	int i;
+	bcma_cc_write32(cc, BCMA_CC_FLASHCTL,
+			BCMA_CC_FLASHCTL_START | opcode);
+	for (i = 0; i < 1000; i++) {
+		if (!(bcma_cc_read32(cc, BCMA_CC_FLASHCTL) &
+		      BCMA_CC_FLASHCTL_BUSY))
+			return;
+		cpu_relax();
+	}
+	bcma_err(cc->core->bus, "SFLASH control command failed (timeout)!\n");
+}
+
 /* Initialize serial flash access */
 int bcma_sflash_init(struct bcma_drv_cc *cc)
 {
-	bcma_err(cc->core->bus, "Serial flash support is broken\n");
+	struct bcma_bus *bus = cc->core->bus;
+	struct bcma_sflash *sflash = &cc->sflash;
+	struct bcma_sflash_tbl_e *e;
+	u32 id, id2;
+
+	switch (cc->capabilities & BCMA_CC_CAP_FLASHT) {
+	case BCMA_CC_FLASHT_STSER:
+		bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_ST_DP);
+
+		bcma_cc_write32(cc, BCMA_CC_FLASHADDR, 0);
+		bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_ST_RES);
+		id = bcma_cc_read32(cc, BCMA_CC_FLASHDATA);
+
+		bcma_cc_write32(cc, BCMA_CC_FLASHADDR, 1);
+		bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_ST_RES);
+		id2 = bcma_cc_read32(cc, BCMA_CC_FLASHDATA);
+
+		switch (id) {
+		case 0xbf:
+			for (e = bcma_sflash_sst_tbl; e->name; e++) {
+				if (e->id == id2)
+					break;
+			}
+			break;
+		default:
+			for (e = bcma_sflash_st_tbl; e->name; e++) {
+				if (e->id == id)
+					break;
+			}
+			break;
+		}
+		if (!e->name) {
+			bcma_err(bus, "Unsupported ST serial flash (id: 0x%X, id2: 0x%X)\n", id, id2);
+			return -ENOTSUPP;
+		}
+
+		break;
+	case BCMA_CC_FLASHT_ATSER:
+		bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_AT_STATUS);
+		id = bcma_cc_read32(cc, BCMA_CC_FLASHDATA) & 0x3c;
+
+		for (e = bcma_sflash_at_tbl; e->name; e++) {
+			if (e->id == id)
+				break;
+		}
+		if (!e->name) {
+			bcma_err(bus, "Unsupported Atmel serial flash (id: 0x%X)\n", id);
+			return -ENOTSUPP;
+		}
+
+		break;
+	default:
+		bcma_err(bus, "Unsupported flash type\n");
+		return -ENOTSUPP;
+	}
+
+	sflash->window = BCMA_SFLASH;
+	sflash->blocksize = e->blocksize;
+	sflash->numblocks = e->numblocks;
+	sflash->size = sflash->blocksize * sflash->numblocks;
+	sflash->present = true;
+
+	bcma_info(bus, "Found %s serial flash (size: %dKiB, blocksize: 0x%X, blocks: %d)\n",
+		  e->name, sflash->size / 1024, sflash->blocksize,
+		  sflash->numblocks);
+
+	/* Prepare platform device, but don't register it yet. It's too early,
+	 * malloc (required by device_private_init) is not available yet. */
+	bcma_sflash_dev.resource[0].end = bcma_sflash_dev.resource[0].start +
+					  sflash->size;
+	bcma_sflash_dev.dev.platform_data = sflash;
+
 	return 0;
 }
diff --git a/drivers/bcma/host_pci.c b/drivers/bcma/host_pci.c
index a6e5672..b6b4b5e 100644
--- a/drivers/bcma/host_pci.c
+++ b/drivers/bcma/host_pci.c
@@ -77,8 +77,8 @@ static void bcma_host_pci_write32(struct bcma_device *core, u16 offset,
 }
 
 #ifdef CONFIG_BCMA_BLOCKIO
-void bcma_host_pci_block_read(struct bcma_device *core, void *buffer,
-			      size_t count, u16 offset, u8 reg_width)
+static void bcma_host_pci_block_read(struct bcma_device *core, void *buffer,
+				     size_t count, u16 offset, u8 reg_width)
 {
 	void __iomem *addr = core->bus->mmio + offset;
 	if (core->bus->mapped_core != core)
@@ -100,8 +100,9 @@ void bcma_host_pci_block_read(struct bcma_device *core, void *buffer,
 	}
 }
 
-void bcma_host_pci_block_write(struct bcma_device *core, const void *buffer,
-			       size_t count, u16 offset, u8 reg_width)
+static void bcma_host_pci_block_write(struct bcma_device *core,
+				      const void *buffer, size_t count,
+				      u16 offset, u8 reg_width)
 {
 	void __iomem *addr = core->bus->mmio + offset;
 	if (core->bus->mapped_core != core)
@@ -139,7 +140,7 @@ static void bcma_host_pci_awrite32(struct bcma_device *core, u16 offset,
 	iowrite32(value, core->bus->mmio + (1 * BCMA_CORE_SIZE) + offset);
 }
 
-const struct bcma_host_ops bcma_host_pci_ops = {
+static const struct bcma_host_ops bcma_host_pci_ops = {
 	.read8		= bcma_host_pci_read8,
 	.read16		= bcma_host_pci_read16,
 	.read32		= bcma_host_pci_read32,
@@ -272,6 +273,7 @@ static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4331) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4353) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4357) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4358) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4359) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) },
 	{ 0, },
diff --git a/drivers/bcma/host_soc.c b/drivers/bcma/host_soc.c
index 3c381fb..3475e60 100644
--- a/drivers/bcma/host_soc.c
+++ b/drivers/bcma/host_soc.c
@@ -143,7 +143,7 @@ static void bcma_host_soc_awrite32(struct bcma_device *core, u16 offset,
 	writel(value, core->io_wrap + offset);
 }
 
-const struct bcma_host_ops bcma_host_soc_ops = {
+static const struct bcma_host_ops bcma_host_soc_ops = {
 	.read8		= bcma_host_soc_read8,
 	.read16		= bcma_host_soc_read16,
 	.read32		= bcma_host_soc_read32,
diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c
index 758af9c..432aeee 100644
--- a/drivers/bcma/main.c
+++ b/drivers/bcma/main.c
@@ -7,6 +7,7 @@
 
 #include "bcma_private.h"
 #include <linux/module.h>
+#include <linux/platform_device.h>
 #include <linux/bcma/bcma.h>
 #include <linux/slab.h>
 
@@ -136,6 +137,22 @@ static int bcma_register_cores(struct bcma_bus *bus)
 		dev_id++;
 	}
 
+#ifdef CONFIG_BCMA_SFLASH
+	if (bus->drv_cc.sflash.present) {
+		err = platform_device_register(&bcma_sflash_dev);
+		if (err)
+			bcma_err(bus, "Error registering serial flash\n");
+	}
+#endif
+
+#ifdef CONFIG_BCMA_NFLASH
+	if (bus->drv_cc.nflash.present) {
+		err = platform_device_register(&bcma_nflash_dev);
+		if (err)
+			bcma_err(bus, "Error registering NAND flash\n");
+	}
+#endif
+
 	return 0;
 }
 
@@ -210,7 +227,17 @@ int __devinit bcma_bus_register(struct bcma_bus *bus)
 
 void bcma_bus_unregister(struct bcma_bus *bus)
 {
+	struct bcma_device *cores[3];
+
+	cores[0] = bcma_find_core(bus, BCMA_CORE_MIPS_74K);
+	cores[1] = bcma_find_core(bus, BCMA_CORE_PCIE);
+	cores[2] = bcma_find_core(bus, BCMA_CORE_4706_MAC_GBIT_COMMON);
+
 	bcma_unregister_cores(bus);
+
+	kfree(cores[2]);
+	kfree(cores[1]);
+	kfree(cores[0]);
 }
 
 int __init bcma_bus_early_register(struct bcma_bus *bus,
diff --git a/drivers/bcma/sprom.c b/drivers/bcma/sprom.c
index 9ea4627..0d546b6 100644
--- a/drivers/bcma/sprom.c
+++ b/drivers/bcma/sprom.c
@@ -507,7 +507,9 @@ static bool bcma_sprom_onchip_available(struct bcma_bus *bus)
 		/* for these chips OTP is always available */
 		present = true;
 		break;
+	case BCMA_CHIP_ID_BCM43227:
 	case BCMA_CHIP_ID_BCM43228:
+	case BCMA_CHIP_ID_BCM43428:
 		present = chip_status & BCMA_CC_CHIPST_43228_OTP_PRESENT;
 		break;
 	default:
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index a796407..f7de322 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -131,6 +131,7 @@ config BLK_CPQ_DA
 config BLK_CPQ_CISS_DA
 	tristate "Compaq Smart Array 5xxx support"
 	depends on PCI
+	select CHECK_SIGNATURE
 	help
 	  This is the driver for Compaq Smart Array 5xxx controllers.
 	  Everyone using these boards should say Y here.
@@ -353,18 +354,6 @@ config BLK_DEV_SX8
 
 	  Use devices /dev/sx8/$N and /dev/sx8/$Np$M.
 
-config BLK_DEV_UB
-	tristate "Low Performance USB Block driver (deprecated)"
-	depends on USB
-	help
-	  This driver supports certain USB attached storage devices
-	  such as flash keys.
-
-	  If you enable this driver, it is recommended to avoid conflicts
-	  with usb-storage by enabling USB_LIBUSUAL.
-
-	  If unsure, say N.
-
 config BLK_DEV_RAM
 	tristate "RAM block device support"
 	---help---
diff --git a/drivers/block/Makefile b/drivers/block/Makefile
index 5b79505..17e82df 100644
--- a/drivers/block/Makefile
+++ b/drivers/block/Makefile
@@ -33,7 +33,6 @@ obj-$(CONFIG_VIRTIO_BLK)	+= virtio_blk.o
 
 obj-$(CONFIG_VIODASD)		+= viodasd.o
 obj-$(CONFIG_BLK_DEV_SX8)	+= sx8.o
-obj-$(CONFIG_BLK_DEV_UB)	+= ub.o
 obj-$(CONFIG_BLK_DEV_HD)	+= hd.o
 
 obj-$(CONFIG_XEN_BLKDEV_FRONTEND)	+= xen-blkfront.o
diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h
index db195ab..27d0a21 100644
--- a/drivers/block/aoe/aoe.h
+++ b/drivers/block/aoe/aoe.h
@@ -1,5 +1,5 @@
-/* Copyright (c) 2007 Coraid, Inc.  See COPYING for GPL terms. */
-#define VERSION "47"
+/* Copyright (c) 2012 Coraid, Inc.  See COPYING for GPL terms. */
+#define VERSION "49"
 #define AOE_MAJOR 152
 #define DEVICE_NAME "aoe"
 
@@ -75,72 +75,68 @@ enum {
 	DEVFL_UP = 1,	/* device is installed in system and ready for AoE->ATA commands */
 	DEVFL_TKILL = (1<<1),	/* flag for timer to know when to kill self */
 	DEVFL_EXT = (1<<2),	/* device accepts lba48 commands */
-	DEVFL_CLOSEWAIT = (1<<3), /* device is waiting for all closes to revalidate */
-	DEVFL_GDALLOC = (1<<4),	/* need to alloc gendisk */
-	DEVFL_KICKME = (1<<5),	/* slow polling network card catch */
-	DEVFL_NEWSIZE = (1<<6),	/* need to update dev size in block layer */
-
-	BUFFL_FAIL = 1,
+	DEVFL_GDALLOC = (1<<3),	/* need to alloc gendisk */
+	DEVFL_KICKME = (1<<4),	/* slow polling network card catch */
+	DEVFL_NEWSIZE = (1<<5),	/* need to update dev size in block layer */
 };
 
 enum {
 	DEFAULTBCNT = 2 * 512,	/* 2 sectors */
 	NPERSHELF = 16,		/* number of slots per shelf address */
-	FREETAG = -1,
 	MIN_BUFS = 16,
 	NTARGETS = 8,
 	NAOEIFS = 8,
-	NSKBPOOLMAX = 128,
+	NSKBPOOLMAX = 256,
+	NFACTIVE = 61,
 
 	TIMERTICK = HZ / 10,
 	MINTIMER = HZ >> 2,
 	MAXTIMER = HZ << 1,
-	HELPWAIT = 20,
 };
 
 struct buf {
-	struct list_head bufs;
-	ulong stime;	/* for disk stats */
-	ulong flags;
 	ulong nframesout;
 	ulong resid;
 	ulong bv_resid;
-	ulong bv_off;
 	sector_t sector;
 	struct bio *bio;
 	struct bio_vec *bv;
+	struct request *rq;
 };
 
 struct frame {
-	int tag;
+	struct list_head head;
+	u32 tag;
 	ulong waited;
+	struct aoetgt *t;		/* parent target I belong to */
+	sector_t lba;
+	struct sk_buff *skb;		/* command skb freed on module exit */
+	struct sk_buff *r_skb;		/* response skb for async processing */
 	struct buf *buf;
-	char *bufaddr;
+	struct bio_vec *bv;
 	ulong bcnt;
-	sector_t lba;
-	struct sk_buff *skb;
+	ulong bv_off;
 };
 
 struct aoeif {
 	struct net_device *nd;
-	unsigned char lost;
-	unsigned char lostjumbo;
-	ushort maxbcnt;
+	ulong lost;
+	int bcnt;
 };
 
 struct aoetgt {
 	unsigned char addr[6];
 	ushort nframes;
-	struct frame *frames;
+	struct aoedev *d;			/* parent device I belong to */
+	struct list_head ffree;			/* list of free frames */
 	struct aoeif ifs[NAOEIFS];
 	struct aoeif *ifp;	/* current aoeif in use */
 	ushort nout;
 	ushort maxout;
-	u16 lasttag;		/* last tag sent */
-	u16 useme;
+	ulong falloc;
 	ulong lastwadj;		/* last window adjustment */
+	int minbcnt;
 	int wpkts, rpkts;
-	int dataref;
 };
 
 struct aoedev {
@@ -153,6 +149,9 @@ struct aoedev {
 	u16 rttavg;		/* round trip average of requests/responses */
 	u16 mintimer;
 	u16 fw_ver;		/* version of blade's firmware */
+	u16 lasttag;		/* last tag sent */
+	u16 useme;
+	ulong ref;
 	struct work_struct work;/* disk create work struct */
 	struct gendisk *gd;
 	struct request_queue *blkq;
@@ -160,16 +159,31 @@ struct aoedev {
 	sector_t ssize;
 	struct timer_list timer;
 	spinlock_t lock;
-	struct sk_buff_head sendq;
 	struct sk_buff_head skbpool;
 	mempool_t *bufpool;	/* for deadlock-free Buf allocation */
-	struct list_head bufq;	/* queue of bios to work on */
-	struct buf *inprocess;	/* the one we're currently working on */
+	struct {		/* pointers to work in progress */
+		struct buf *buf;
+		struct bio *nxbio;
+		struct request *rq;
+	} ip;
+	ulong maxbcnt;
+	struct list_head factive[NFACTIVE];	/* hash of active frames */
 	struct aoetgt *targets[NTARGETS];
 	struct aoetgt **tgt;	/* target in use when working */
-	struct aoetgt **htgt;	/* target needing rexmit assistance */
+	struct aoetgt *htgt;	/* target needing rexmit assistance */
+	ulong ntargets;
+	ulong kicked;
 };
 
+/* kthread tracking */
+struct ktstate {
+	struct completion rendez;
+	struct task_struct *task;
+	wait_queue_head_t *waitq;
+	int (*fn) (void);
+	char *name;
+	spinlock_t *lock;
+};
 
 int aoeblk_init(void);
 void aoeblk_exit(void);
@@ -182,11 +196,18 @@ void aoechr_error(char *);
 
 void aoecmd_work(struct aoedev *d);
 void aoecmd_cfg(ushort aoemajor, unsigned char aoeminor);
-void aoecmd_ata_rsp(struct sk_buff *);
+struct sk_buff *aoecmd_ata_rsp(struct sk_buff *);
 void aoecmd_cfg_rsp(struct sk_buff *);
 void aoecmd_sleepwork(struct work_struct *);
 void aoecmd_cleanslate(struct aoedev *);
+void aoecmd_exit(void);
+int aoecmd_init(void);
 struct sk_buff *aoecmd_ata_id(struct aoedev *);
+void aoe_freetframe(struct frame *);
+void aoe_flush_iocq(void);
+void aoe_end_request(struct aoedev *, struct request *, int);
+int aoe_ktstart(struct ktstate *k);
+void aoe_ktstop(struct ktstate *k);
 
 int aoedev_init(void);
 void aoedev_exit(void);
@@ -194,6 +215,8 @@ struct aoedev *aoedev_by_aoeaddr(int maj, int min);
 struct aoedev *aoedev_by_sysminor_m(ulong sysminor);
 void aoedev_downdev(struct aoedev *d);
 int aoedev_flush(const char __user *str, size_t size);
+void aoe_failbuf(struct aoedev *, struct buf *);
+void aoedev_put(struct aoedev *);
 
 int aoenet_init(void);
 void aoenet_exit(void);
diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c
index 321de7b..83160ab 100644
--- a/drivers/block/aoe/aoeblk.c
+++ b/drivers/block/aoe/aoeblk.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007 Coraid, Inc.  See COPYING for GPL terms. */
+/* Copyright (c) 2012 Coraid, Inc.  See COPYING for GPL terms. */
 /*
  * aoeblk.c
  * block device routines
@@ -161,68 +161,22 @@ aoeblk_release(struct gendisk *disk, fmode_t mode)
 }
 
 static void
-aoeblk_make_request(struct request_queue *q, struct bio *bio)
+aoeblk_request(struct request_queue *q)
 {
-	struct sk_buff_head queue;
 	struct aoedev *d;
-	struct buf *buf;
-	ulong flags;
-
-	blk_queue_bounce(q, &bio);
-
-	if (bio == NULL) {
-		printk(KERN_ERR "aoe: bio is NULL\n");
-		BUG();
-		return;
-	}
-	d = bio->bi_bdev->bd_disk->private_data;
-	if (d == NULL) {
-		printk(KERN_ERR "aoe: bd_disk->private_data is NULL\n");
-		BUG();
-		bio_endio(bio, -ENXIO);
-		return;
-	} else if (bio->bi_io_vec == NULL) {
-		printk(KERN_ERR "aoe: bi_io_vec is NULL\n");
-		BUG();
-		bio_endio(bio, -ENXIO);
-		return;
-	}
-	buf = mempool_alloc(d->bufpool, GFP_NOIO);
-	if (buf == NULL) {
-		printk(KERN_INFO "aoe: buf allocation failure\n");
-		bio_endio(bio, -ENOMEM);
-		return;
-	}
-	memset(buf, 0, sizeof(*buf));
-	INIT_LIST_HEAD(&buf->bufs);
-	buf->stime = jiffies;
-	buf->bio = bio;
-	buf->resid = bio->bi_size;
-	buf->sector = bio->bi_sector;
-	buf->bv = &bio->bi_io_vec[bio->bi_idx];
-	buf->bv_resid = buf->bv->bv_len;
-	WARN_ON(buf->bv_resid == 0);
-	buf->bv_off = buf->bv->bv_offset;
-
-	spin_lock_irqsave(&d->lock, flags);
+	struct request *rq;
 
+	d = q->queuedata;
 	if ((d->flags & DEVFL_UP) == 0) {
 		pr_info_ratelimited("aoe: device %ld.%d is not up\n",
 			d->aoemajor, d->aoeminor);
-		spin_unlock_irqrestore(&d->lock, flags);
-		mempool_free(buf, d->bufpool);
-		bio_endio(bio, -ENXIO);
+		while ((rq = blk_peek_request(q))) {
+			blk_start_request(rq);
+			aoe_end_request(d, rq, 1);
+		}
 		return;
 	}
-
-	list_add_tail(&buf->bufs, &d->bufq);
-
 	aoecmd_work(d);
-	__skb_queue_head_init(&queue);
-	skb_queue_splice_init(&d->sendq, &queue);
-
-	spin_unlock_irqrestore(&d->lock, flags);
-	aoenet_xmit(&queue);
 }
 
 static int
@@ -254,31 +208,46 @@ aoeblk_gdalloc(void *vp)
 {
 	struct aoedev *d = vp;
 	struct gendisk *gd;
+	mempool_t *mp;
+	struct request_queue *q;
+	enum { KB = 1024, MB = KB * KB, READ_AHEAD = 2 * MB, };
 	ulong flags;
 
 	gd = alloc_disk(AOE_PARTITIONS);
 	if (gd == NULL) {
-		printk(KERN_ERR
-			"aoe: cannot allocate disk structure for %ld.%d\n",
+		pr_err("aoe: cannot allocate disk structure for %ld.%d\n",
 			d->aoemajor, d->aoeminor);
 		goto err;
 	}
 
-	d->bufpool = mempool_create_slab_pool(MIN_BUFS, buf_pool_cache);
-	if (d->bufpool == NULL) {
+	mp = mempool_create(MIN_BUFS, mempool_alloc_slab, mempool_free_slab,
+		buf_pool_cache);
+	if (mp == NULL) {
 		printk(KERN_ERR "aoe: cannot allocate bufpool for %ld.%d\n",
 			d->aoemajor, d->aoeminor);
 		goto err_disk;
 	}
+	q = blk_init_queue(aoeblk_request, &d->lock);
+	if (q == NULL) {
+		pr_err("aoe: cannot allocate block queue for %ld.%d\n",
+			d->aoemajor, d->aoeminor);
+		mempool_destroy(mp);
+		goto err_disk;
+	}
 
 	d->blkq = blk_alloc_queue(GFP_KERNEL);
 	if (!d->blkq)
 		goto err_mempool;
-	blk_queue_make_request(d->blkq, aoeblk_make_request);
 	d->blkq->backing_dev_info.name = "aoe";
 	if (bdi_init(&d->blkq->backing_dev_info))
 		goto err_blkq;
 	spin_lock_irqsave(&d->lock, flags);
+	blk_queue_max_hw_sectors(d->blkq, BLK_DEF_MAX_SECTORS);
+	q->backing_dev_info.ra_pages = READ_AHEAD / PAGE_CACHE_SIZE;
+	d->bufpool = mp;
+	d->blkq = gd->queue = q;
+	q->queuedata = d;
+	d->gd = gd;
 	gd->major = AOE_MAJOR;
 	gd->first_minor = d->sysminor * AOE_PARTITIONS;
 	gd->fops = &aoe_bdops;
@@ -287,8 +256,6 @@ aoeblk_gdalloc(void *vp)
 	snprintf(gd->disk_name, sizeof gd->disk_name, "etherd/e%ld.%d",
 		d->aoemajor, d->aoeminor);
 
-	gd->queue = d->blkq;
-	d->gd = gd;
 	d->flags &= ~DEVFL_GDALLOC;
 	d->flags |= DEVFL_UP;
 
diff --git a/drivers/block/aoe/aoechr.c b/drivers/block/aoe/aoechr.c
index e86d206..deb30c1 100644
--- a/drivers/block/aoe/aoechr.c
+++ b/drivers/block/aoe/aoechr.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007 Coraid, Inc.  See COPYING for GPL terms. */
+/* Copyright (c) 2012 Coraid, Inc.  See COPYING for GPL terms. */
 /*
  * aoechr.c
  * AoE character device driver
@@ -86,10 +86,9 @@ revalidate(const char __user *str, size_t size)
 	if (copy_from_user(buf, str, size))
 		return -EFAULT;
 
-	/* should be e%d.%d format */
 	n = sscanf(buf, "e%d.%d", &major, &minor);
 	if (n != 2) {
-		printk(KERN_ERR "aoe: invalid device specification\n");
+		pr_err("aoe: invalid device specification %s\n", buf);
 		return -EINVAL;
 	}
 	d = aoedev_by_aoeaddr(major, minor);
@@ -97,23 +96,24 @@ revalidate(const char __user *str, size_t size)
 		return -EINVAL;
 	spin_lock_irqsave(&d->lock, flags);
 	aoecmd_cleanslate(d);
+	aoecmd_cfg(major, minor);
 loop:
 	skb = aoecmd_ata_id(d);
 	spin_unlock_irqrestore(&d->lock, flags);
 	/* try again if we are able to sleep a bit,
 	 * otherwise give up this revalidation
 	 */
-	if (!skb && !msleep_interruptible(200)) {
+	if (!skb && !msleep_interruptible(250)) {
 		spin_lock_irqsave(&d->lock, flags);
 		goto loop;
 	}
+	aoedev_put(d);
 	if (skb) {
 		struct sk_buff_head queue;
 		__skb_queue_head_init(&queue);
 		__skb_queue_tail(&queue, skb);
 		aoenet_xmit(&queue);
 	}
-	aoecmd_cfg(major, minor);
 	return 0;
 }
 
@@ -174,6 +174,7 @@ aoechr_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offp
 		break;
 	case MINOR_FLUSH:
 		ret = aoedev_flush(buf, cnt);
+		break;
 	}
 	if (ret == 0)
 		ret = cnt;
diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c
index 887f68f..39dacdb 100644
--- a/drivers/block/aoe/aoecmd.c
+++ b/drivers/block/aoe/aoecmd.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007 Coraid, Inc.  See COPYING for GPL terms. */
+/* Copyright (c) 2012 Coraid, Inc.  See COPYING for GPL terms. */
 /*
  * aoecmd.c
  * Filesystem request handling methods
@@ -12,10 +12,19 @@
 #include <linux/netdevice.h>
 #include <linux/genhd.h>
 #include <linux/moduleparam.h>
+#include <linux/workqueue.h>
+#include <linux/kthread.h>
 #include <net/net_namespace.h>
 #include <asm/unaligned.h>
+#include <linux/uio.h>
 #include "aoe.h"
 
+#define MAXIOC (8192)	/* default meant to avoid most soft lockups */
+
+static void ktcomplete(struct frame *, struct sk_buff *);
+
+static struct buf *nextbuf(struct aoedev *);
+
 static int aoe_deadsecs = 60 * 3;
 module_param(aoe_deadsecs, int, 0644);
 MODULE_PARM_DESC(aoe_deadsecs, "After aoe_deadsecs seconds, give up and fail dev.");
@@ -25,6 +34,15 @@ module_param(aoe_maxout, int, 0644);
 MODULE_PARM_DESC(aoe_maxout,
 	"Only aoe_maxout outstanding packets for every MAC on eX.Y.");
 
+static wait_queue_head_t ktiowq;
+static struct ktstate kts;
+
+/* io completion queue */
+static struct {
+	struct list_head head;
+	spinlock_t lock;
+} iocq;
+
 static struct sk_buff *
 new_skb(ulong len)
 {
@@ -41,15 +59,21 @@ new_skb(ulong len)
 }
 
 static struct frame *
-getframe(struct aoetgt *t, int tag)
+getframe(struct aoedev *d, u32 tag)
 {
-	struct frame *f, *e;
+	struct frame *f;
+	struct list_head *head, *pos, *nx;
+	u32 n;
 
-	f = t->frames;
-	e = f + t->nframes;
-	for (; f<e; f++)
-		if (f->tag == tag)
+	n = tag % NFACTIVE;
+	head = &d->factive[n];
+	list_for_each_safe(pos, nx, head) {
+		f = list_entry(pos, struct frame, head);
+		if (f->tag == tag) {
+			list_del(pos);
 			return f;
+		}
+	}
 	return NULL;
 }
 
@@ -59,18 +83,18 @@ getframe(struct aoetgt *t, int tag)
  * This driver reserves tag -1 to mean "unused frame."
  */
 static int
-newtag(struct aoetgt *t)
+newtag(struct aoedev *d)
 {
 	register ulong n;
 
 	n = jiffies & 0xffff;
-	return n |= (++t->lasttag & 0x7fff) << 16;
+	return n |= (++d->lasttag & 0x7fff) << 16;
 }
 
-static int
+static u32
 aoehdr_atainit(struct aoedev *d, struct aoetgt *t, struct aoe_hdr *h)
 {
-	u32 host_tag = newtag(t);
+	u32 host_tag = newtag(d);
 
 	memcpy(h->src, t->ifp->nd->dev_addr, sizeof h->src);
 	memcpy(h->dst, t->addr, sizeof h->dst);
@@ -95,16 +119,18 @@ put_lba(struct aoe_atahdr *ah, sector_t lba)
 	ah->lba5 = lba >>= 8;
 }
 
-static void
+static struct aoeif *
 ifrotate(struct aoetgt *t)
 {
-	t->ifp++;
-	if (t->ifp >= &t->ifs[NAOEIFS] || t->ifp->nd == NULL)
-		t->ifp = t->ifs;
-	if (t->ifp->nd == NULL) {
-		printk(KERN_INFO "aoe: no interface to rotate to\n");
-		BUG();
-	}
+	struct aoeif *ifp;
+
+	ifp = t->ifp;
+	ifp++;
+	if (ifp >= &t->ifs[NAOEIFS] || ifp->nd == NULL)
+		ifp = t->ifs;
+	if (ifp->nd == NULL)
+		return NULL;
+	return t->ifp = ifp;
 }
 
 static void
@@ -129,78 +155,128 @@ skb_pool_get(struct aoedev *d)
 	return NULL;
 }
 
-/* freeframe is where we do our load balancing so it's a little hairy. */
+void
+aoe_freetframe(struct frame *f)
+{
+	struct aoetgt *t;
+
+	t = f->t;
+	f->buf = NULL;
+	f->bv = NULL;
+	f->r_skb = NULL;
+	list_add(&f->head, &t->ffree);
+}
+
 static struct frame *
-freeframe(struct aoedev *d)
+newtframe(struct aoedev *d, struct aoetgt *t)
 {
-	struct frame *f, *e, *rf;
-	struct aoetgt **t;
+	struct frame *f;
 	struct sk_buff *skb;
+	struct list_head *pos;
+
+	if (list_empty(&t->ffree)) {
+		if (t->falloc >= NSKBPOOLMAX*2)
+			return NULL;
+		f = kcalloc(1, sizeof(*f), GFP_ATOMIC);
+		if (f == NULL)
+			return NULL;
+		t->falloc++;
+		f->t = t;
+	} else {
+		pos = t->ffree.next;
+		list_del(pos);
+		f = list_entry(pos, struct frame, head);
+	}
+
+	skb = f->skb;
+	if (skb == NULL) {
+		f->skb = skb = new_skb(ETH_ZLEN);
+		if (!skb) {
+bail:			aoe_freetframe(f);
+			return NULL;
+		}
+	}
+
+	if (atomic_read(&skb_shinfo(skb)->dataref) != 1) {
+		skb = skb_pool_get(d);
+		if (skb == NULL)
+			goto bail;
+		skb_pool_put(d, f->skb);
+		f->skb = skb;
+	}
+
+	skb->truesize -= skb->data_len;
+	skb_shinfo(skb)->nr_frags = skb->data_len = 0;
+	skb_trim(skb, 0);
+	return f;
+}
+
+static struct frame *
+newframe(struct aoedev *d)
+{
+	struct frame *f;
+	struct aoetgt *t, **tt;
+	int totout = 0;
 
 	if (d->targets[0] == NULL) {	/* shouldn't happen, but I'm paranoid */
 		printk(KERN_ERR "aoe: NULL TARGETS!\n");
 		return NULL;
 	}
-	t = d->tgt;
-	t++;
-	if (t >= &d->targets[NTARGETS] || !*t)
-		t = d->targets;
+	tt = d->tgt;	/* last used target */
 	for (;;) {
-		if ((*t)->nout < (*t)->maxout
+		tt++;
+		if (tt >= &d->targets[NTARGETS] || !*tt)
+			tt = d->targets;
+		t = *tt;
+		totout += t->nout;
+		if (t->nout < t->maxout
 		&& t != d->htgt
-		&& (*t)->ifp->nd) {
-			rf = NULL;
-			f = (*t)->frames;
-			e = f + (*t)->nframes;
-			for (; f < e; f++) {
-				if (f->tag != FREETAG)
-					continue;
-				skb = f->skb;
-				if (!skb
-				&& !(f->skb = skb = new_skb(ETH_ZLEN)))
-					continue;
-				if (atomic_read(&skb_shinfo(skb)->dataref)
-					!= 1) {
-					if (!rf)
-						rf = f;
-					continue;
-				}
-gotone:				skb_shinfo(skb)->nr_frags = skb->data_len = 0;
-				skb_trim(skb, 0);
-				d->tgt = t;
-				ifrotate(*t);
+		&& t->ifp->nd) {
+			f = newtframe(d, t);
+			if (f) {
+				ifrotate(t);
+				d->tgt = tt;
 				return f;
 			}
-			/* Work can be done, but the network layer is
-			   holding our precious packets.  Try to grab
-			   one from the pool. */
-			f = rf;
-			if (f == NULL) {	/* more paranoia */
-				printk(KERN_ERR
-					"aoe: freeframe: %s.\n",
-					"unexpected null rf");
-				d->flags |= DEVFL_KICKME;
-				return NULL;
-			}
-			skb = skb_pool_get(d);
-			if (skb) {
-				skb_pool_put(d, f->skb);
-				f->skb = skb;
-				goto gotone;
-			}
-			(*t)->dataref++;
-			if ((*t)->nout == 0)
-				d->flags |= DEVFL_KICKME;
 		}
-		if (t == d->tgt)	/* we've looped and found nada */
+		if (tt == d->tgt)	/* we've looped and found nada */
 			break;
-		t++;
-		if (t >= &d->targets[NTARGETS] || !*t)
-			t = d->targets;
+	}
+	if (totout == 0) {
+		d->kicked++;
+		d->flags |= DEVFL_KICKME;
 	}
 	return NULL;
 }
 
+static void
+skb_fillup(struct sk_buff *skb, struct bio_vec *bv, ulong off, ulong cnt)
+{
+	int frag = 0;
+	ulong fcnt;
+loop:
+	fcnt = bv->bv_len - (off - bv->bv_offset);
+	if (fcnt > cnt)
+		fcnt = cnt;
+	skb_fill_page_desc(skb, frag++, bv->bv_page, off, fcnt);
+	cnt -= fcnt;
+	if (cnt <= 0)
+		return;
+	bv++;
+	off = bv->bv_offset;
+	goto loop;
+}
+
+static void
+fhash(struct frame *f)
+{
+	struct aoedev *d = f->t->d;
+	u32 n;
+
+	n = f->tag % NFACTIVE;
+	list_add_tail(&f->head, &d->factive[n]);
+}
+
 static int
 aoecmd_ata_rw(struct aoedev *d)
 {
@@ -208,26 +284,47 @@ aoecmd_ata_rw(struct aoedev *d)
 	struct aoe_hdr *h;
 	struct aoe_atahdr *ah;
 	struct buf *buf;
-	struct bio_vec *bv;
 	struct aoetgt *t;
 	struct sk_buff *skb;
-	ulong bcnt;
+	struct sk_buff_head queue;
+	ulong bcnt, fbcnt;
 	char writebit, extbit;
 
 	writebit = 0x10;
 	extbit = 0x4;
 
-	f = freeframe(d);
+	buf = nextbuf(d);
+	if (buf == NULL)
+		return 0;
+	f = newframe(d);
 	if (f == NULL)
 		return 0;
 	t = *d->tgt;
-	buf = d->inprocess;
-	bv = buf->bv;
-	bcnt = t->ifp->maxbcnt;
+	bcnt = d->maxbcnt;
 	if (bcnt == 0)
 		bcnt = DEFAULTBCNT;
-	if (bcnt > buf->bv_resid)
-		bcnt = buf->bv_resid;
+	if (bcnt > buf->resid)
+		bcnt = buf->resid;
+	fbcnt = bcnt;
+	f->bv = buf->bv;
+	f->bv_off = f->bv->bv_offset + (f->bv->bv_len - buf->bv_resid);
+	do {
+		if (fbcnt < buf->bv_resid) {
+			buf->bv_resid -= fbcnt;
+			buf->resid -= fbcnt;
+			break;
+		}
+		fbcnt -= buf->bv_resid;
+		buf->resid -= buf->bv_resid;
+		if (buf->resid == 0) {
+			d->ip.buf = NULL;
+			break;
+		}
+		buf->bv++;
+		buf->bv_resid = buf->bv->bv_len;
+		WARN_ON(buf->bv_resid == 0);
+	} while (fbcnt);
+
 	/* initialize the headers & frame */
 	skb = f->skb;
 	h = (struct aoe_hdr *) skb_mac_header(skb);
@@ -235,10 +332,10 @@ aoecmd_ata_rw(struct aoedev *d)
 	skb_put(skb, sizeof *h + sizeof *ah);
 	memset(h, 0, skb->len);
 	f->tag = aoehdr_atainit(d, t, h);
+	fhash(f);
 	t->nout++;
 	f->waited = 0;
 	f->buf = buf;
-	f->bufaddr = page_address(bv->bv_page) + buf->bv_off;
 	f->bcnt = bcnt;
 	f->lba = buf->sector;
 
@@ -253,10 +350,11 @@ aoecmd_ata_rw(struct aoedev *d)
 		ah->lba3 |= 0xe0;	/* LBA bit + obsolete 0xa0 */
 	}
 	if (bio_data_dir(buf->bio) == WRITE) {
-		skb_fill_page_desc(skb, 0, bv->bv_page, buf->bv_off, bcnt);
+		skb_fillup(skb, f->bv, f->bv_off, bcnt);
 		ah->aflags |= AOEAFL_WRITE;
 		skb->len += bcnt;
 		skb->data_len = bcnt;
+		skb->truesize += bcnt;
 		t->wpkts++;
 	} else {
 		t->rpkts++;
@@ -267,23 +365,15 @@ aoecmd_ata_rw(struct aoedev *d)
 
 	/* mark all tracking fields and load out */
 	buf->nframesout += 1;
-	buf->bv_off += bcnt;
-	buf->bv_resid -= bcnt;
-	buf->resid -= bcnt;
 	buf->sector += bcnt >> 9;
-	if (buf->resid == 0) {
-		d->inprocess = NULL;
-	} else if (buf->bv_resid == 0) {
-		buf->bv = ++bv;
-		buf->bv_resid = bv->bv_len;
-		WARN_ON(buf->bv_resid == 0);
-		buf->bv_off = bv->bv_offset;
-	}
 
 	skb->dev = t->ifp->nd;
 	skb = skb_clone(skb, GFP_ATOMIC);
-	if (skb)
-		__skb_queue_tail(&d->sendq, skb);
+	if (skb) {
+		__skb_queue_head_init(&queue);
+		__skb_queue_tail(&queue, skb);
+		aoenet_xmit(&queue);
+	}
 	return 1;
 }
 
@@ -330,17 +420,25 @@ cont:
 }
 
 static void
-resend(struct aoedev *d, struct aoetgt *t, struct frame *f)
+resend(struct aoedev *d, struct frame *f)
 {
 	struct sk_buff *skb;
+	struct sk_buff_head queue;
 	struct aoe_hdr *h;
 	struct aoe_atahdr *ah;
+	struct aoetgt *t;
 	char buf[128];
 	u32 n;
 
-	ifrotate(t);
-	n = newtag(t);
+	t = f->t;
+	n = newtag(d);
 	skb = f->skb;
+	if (ifrotate(t) == NULL) {
+		/* probably can't happen, but set it up to fail anyway */
+		pr_info("aoe: resend: no interfaces to rotate to.\n");
+		ktcomplete(f, NULL);
+		return;
+	}
 	h = (struct aoe_hdr *) skb_mac_header(skb);
 	ah = (struct aoe_atahdr *) (h+1);
 
@@ -351,39 +449,22 @@ resend(struct aoedev *d, struct aoetgt *t, struct frame *f)
 	aoechr_error(buf);
 
 	f->tag = n;
+	fhash(f);
 	h->tag = cpu_to_be32(n);
 	memcpy(h->dst, t->addr, sizeof h->dst);
 	memcpy(h->src, t->ifp->nd->dev_addr, sizeof h->src);
 
-	switch (ah->cmdstat) {
-	default:
-		break;
-	case ATA_CMD_PIO_READ:
-	case ATA_CMD_PIO_READ_EXT:
-	case ATA_CMD_PIO_WRITE:
-	case ATA_CMD_PIO_WRITE_EXT:
-		put_lba(ah, f->lba);
-
-		n = f->bcnt;
-		if (n > DEFAULTBCNT)
-			n = DEFAULTBCNT;
-		ah->scnt = n >> 9;
-		if (ah->aflags & AOEAFL_WRITE) {
-			skb_fill_page_desc(skb, 0, virt_to_page(f->bufaddr),
-				offset_in_page(f->bufaddr), n);
-			skb->len = sizeof *h + sizeof *ah + n;
-			skb->data_len = n;
-		}
-	}
 	skb->dev = t->ifp->nd;
 	skb = skb_clone(skb, GFP_ATOMIC);
 	if (skb == NULL)
 		return;
-	__skb_queue_tail(&d->sendq, skb);
+	__skb_queue_head_init(&queue);
+	__skb_queue_tail(&queue, skb);
+	aoenet_xmit(&queue);
 }
 
 static int
-tsince(int tag)
+tsince(u32 tag)
 {
 	int n;
 
@@ -407,58 +488,65 @@ getif(struct aoetgt *t, struct net_device *nd)
 	return NULL;
 }
 
-static struct aoeif *
-addif(struct aoetgt *t, struct net_device *nd)
-{
-	struct aoeif *p;
-
-	p = getif(t, NULL);
-	if (!p)
-		return NULL;
-	p->nd = nd;
-	p->maxbcnt = DEFAULTBCNT;
-	p->lost = 0;
-	p->lostjumbo = 0;
-	return p;
-}
-
 static void
 ejectif(struct aoetgt *t, struct aoeif *ifp)
 {
 	struct aoeif *e;
+	struct net_device *nd;
 	ulong n;
 
+	nd = ifp->nd;
 	e = t->ifs + NAOEIFS - 1;
 	n = (e - ifp) * sizeof *ifp;
 	memmove(ifp, ifp+1, n);
 	e->nd = NULL;
+	dev_put(nd);
 }
 
 static int
 sthtith(struct aoedev *d)
 {
-	struct frame *f, *e, *nf;
+	struct frame *f, *nf;
+	struct list_head *nx, *pos, *head;
 	struct sk_buff *skb;
-	struct aoetgt *ht = *d->htgt;
-
-	f = ht->frames;
-	e = f + ht->nframes;
-	for (; f < e; f++) {
-		if (f->tag == FREETAG)
-			continue;
-		nf = freeframe(d);
-		if (!nf)
-			return 0;
-		skb = nf->skb;
-		*nf = *f;
-		f->skb = skb;
-		f->tag = FREETAG;
-		nf->waited = 0;
-		ht->nout--;
-		(*d->tgt)->nout++;
-		resend(d, *d->tgt, nf);
+	struct aoetgt *ht = d->htgt;
+	int i;
+
+	for (i = 0; i < NFACTIVE; i++) {
+		head = &d->factive[i];
+		list_for_each_safe(pos, nx, head) {
+			f = list_entry(pos, struct frame, head);
+			if (f->t != ht)
+				continue;
+
+			nf = newframe(d);
+			if (!nf)
+				return 0;
+
+			/* remove frame from active list */
+			list_del(pos);
+
+			/* reassign all pertinent bits to new outbound frame */
+			skb = nf->skb;
+			nf->skb = f->skb;
+			nf->buf = f->buf;
+			nf->bcnt = f->bcnt;
+			nf->lba = f->lba;
+			nf->bv = f->bv;
+			nf->bv_off = f->bv_off;
+			nf->waited = 0;
+			f->skb = skb;
+			aoe_freetframe(f);
+			ht->nout--;
+			nf->t->nout++;
+			resend(d, nf);
+		}
 	}
-	/* he's clean, he's useless.  take away his interfaces */
+	/* We've cleaned up the outstanding so take away his
+	 * interfaces so he won't be used.  We should remove him from
+	 * the target array here, but cleaning up a target is
+	 * involved.  PUNT!
+	 */
 	memset(ht->ifs, 0, sizeof ht->ifs);
 	d->htgt = NULL;
 	return 1;
@@ -477,13 +565,15 @@ ata_scnt(unsigned char *packet) {
 static void
 rexmit_timer(ulong vp)
 {
-	struct sk_buff_head queue;
 	struct aoedev *d;
 	struct aoetgt *t, **tt, **te;
 	struct aoeif *ifp;
-	struct frame *f, *e;
+	struct frame *f;
+	struct list_head *head, *pos, *nx;
+	LIST_HEAD(flist);
 	register long timeout;
 	ulong flags, n;
+	int i;
 
 	d = (struct aoedev *) vp;
 
@@ -497,58 +587,22 @@ rexmit_timer(ulong vp)
 		spin_unlock_irqrestore(&d->lock, flags);
 		return;
 	}
-	tt = d->targets;
-	te = tt + NTARGETS;
-	for (; tt < te && *tt; tt++) {
-		t = *tt;
-		f = t->frames;
-		e = f + t->nframes;
-		for (; f < e; f++) {
-			if (f->tag == FREETAG
-			|| tsince(f->tag) < timeout)
-				continue;
-			n = f->waited += timeout;
-			n /= HZ;
-			if (n > aoe_deadsecs) {
-				/* waited too long.  device failure. */
-				aoedev_downdev(d);
-				break;
-			}
-
-			if (n > HELPWAIT /* see if another target can help */
-			&& (tt != d->targets || d->targets[1]))
-				d->htgt = tt;
-
-			if (t->nout == t->maxout) {
-				if (t->maxout > 1)
-					t->maxout--;
-				t->lastwadj = jiffies;
-			}
-
-			ifp = getif(t, f->skb->dev);
-			if (ifp && ++ifp->lost > (t->nframes << 1)
-			&& (ifp != t->ifs || t->ifs[1].nd)) {
-				ejectif(t, ifp);
-				ifp = NULL;
-			}
 
-			if (ata_scnt(skb_mac_header(f->skb)) > DEFAULTBCNT / 512
-			&& ifp && ++ifp->lostjumbo > (t->nframes << 1)
-			&& ifp->maxbcnt != DEFAULTBCNT) {
-				printk(KERN_INFO
-					"aoe: e%ld.%d: "
-					"too many lost jumbo on "
-					"%s:%pm - "
-					"falling back to %d frames.\n",
-					d->aoemajor, d->aoeminor,
-					ifp->nd->name, t->addr,
-					DEFAULTBCNT);
-				ifp->maxbcnt = 0;
-			}
-			resend(d, t, f);
+	/* collect all frames to rexmit into flist */
+	for (i = 0; i < NFACTIVE; i++) {
+		head = &d->factive[i];
+		list_for_each_safe(pos, nx, head) {
+			f = list_entry(pos, struct frame, head);
+			if (tsince(f->tag) < timeout)
+				break;	/* end of expired frames */
+			/* move to flist for later processing */
+			list_move_tail(pos, &flist);
 		}
-
-		/* window check */
+	}
+	/* window check */
+	tt = d->targets;
+	te = tt + d->ntargets;
+	for (; tt < te && (t = *tt); tt++) {
 		if (t->nout == t->maxout
 		&& t->maxout < t->nframes
 		&& (jiffies - t->lastwadj)/HZ > 10) {
@@ -557,45 +611,173 @@ rexmit_timer(ulong vp)
 		}
 	}
 
-	if (!skb_queue_empty(&d->sendq)) {
+	if (!list_empty(&flist)) {	/* retransmissions necessary */
 		n = d->rttavg <<= 1;
 		if (n > MAXTIMER)
 			d->rttavg = MAXTIMER;
 	}
 
-	if (d->flags & DEVFL_KICKME || d->htgt) {
-		d->flags &= ~DEVFL_KICKME;
-		aoecmd_work(d);
+	/* process expired frames */
+	while (!list_empty(&flist)) {
+		pos = flist.next;
+		f = list_entry(pos, struct frame, head);
+		n = f->waited += timeout;
+		n /= HZ;
+		if (n > aoe_deadsecs) {
+			/* Waited too long.  Device failure.
+			 * Hang all frames on first hash bucket for downdev
+			 * to clean up.
+			 */
+			list_splice(&flist, &d->factive[0]);
+			aoedev_downdev(d);
+			break;
+		}
+		list_del(pos);
+
+		t = f->t;
+		if (n > aoe_deadsecs/2)
+			d->htgt = t; /* see if another target can help */
+
+		if (t->nout == t->maxout) {
+			if (t->maxout > 1)
+				t->maxout--;
+			t->lastwadj = jiffies;
+		}
+
+		ifp = getif(t, f->skb->dev);
+		if (ifp && ++ifp->lost > (t->nframes << 1)
+		&& (ifp != t->ifs || t->ifs[1].nd)) {
+			ejectif(t, ifp);
+			ifp = NULL;
+		}
+		resend(d, f);
 	}
 
-	__skb_queue_head_init(&queue);
-	skb_queue_splice_init(&d->sendq, &queue);
+	if ((d->flags & DEVFL_KICKME || d->htgt) && d->blkq) {
+		d->flags &= ~DEVFL_KICKME;
+		d->blkq->request_fn(d->blkq);
+	}
 
 	d->timer.expires = jiffies + TIMERTICK;
 	add_timer(&d->timer);
 
 	spin_unlock_irqrestore(&d->lock, flags);
+}
 
-	aoenet_xmit(&queue);
+static unsigned long
+rqbiocnt(struct request *r)
+{
+	struct bio *bio;
+	unsigned long n = 0;
+
+	__rq_for_each_bio(bio, r)
+		n++;
+	return n;
+}
+
+/* This can be removed if we are certain that no users of the block
+ * layer will ever use zero-count pages in bios.  Otherwise we have to
+ * protect against the put_page sometimes done by the network layer.
+ *
+ * See http://oss.sgi.com/archives/xfs/2007-01/msg00594.html for
+ * discussion.
+ *
+ * We cannot use get_page in the workaround, because it insists on a
+ * positive page count as a precondition.  So we use _count directly.
+ */
+static void
+bio_pageinc(struct bio *bio)
+{
+	struct bio_vec *bv;
+	struct page *page;
+	int i;
+
+	bio_for_each_segment(bv, bio, i) {
+		page = bv->bv_page;
+		/* Non-zero page count for non-head members of
+		 * compound pages is no longer allowed by the kernel,
+		 * but this has never been seen here.
+		 */
+		if (unlikely(PageCompound(page)))
+			if (compound_trans_head(page) != page) {
+				pr_crit("page tail used for block I/O\n");
+				BUG();
+			}
+		atomic_inc(&page->_count);
+	}
+}
+
+static void
+bio_pagedec(struct bio *bio)
+{
+	struct bio_vec *bv;
+	int i;
+
+	bio_for_each_segment(bv, bio, i)
+		atomic_dec(&bv->bv_page->_count);
+}
+
+static void
+bufinit(struct buf *buf, struct request *rq, struct bio *bio)
+{
+	struct bio_vec *bv;
+
+	memset(buf, 0, sizeof(*buf));
+	buf->rq = rq;
+	buf->bio = bio;
+	buf->resid = bio->bi_size;
+	buf->sector = bio->bi_sector;
+	bio_pageinc(bio);
+	buf->bv = bv = &bio->bi_io_vec[bio->bi_idx];
+	buf->bv_resid = bv->bv_len;
+	WARN_ON(buf->bv_resid == 0);
+}
+
+static struct buf *
+nextbuf(struct aoedev *d)
+{
+	struct request *rq;
+	struct request_queue *q;
+	struct buf *buf;
+	struct bio *bio;
+
+	q = d->blkq;
+	if (q == NULL)
+		return NULL;	/* initializing */
+	if (d->ip.buf)
+		return d->ip.buf;
+	rq = d->ip.rq;
+	if (rq == NULL) {
+		rq = blk_peek_request(q);
+		if (rq == NULL)
+			return NULL;
+		blk_start_request(rq);
+		d->ip.rq = rq;
+		d->ip.nxbio = rq->bio;
+		rq->special = (void *) rqbiocnt(rq);
+	}
+	buf = mempool_alloc(d->bufpool, GFP_ATOMIC);
+	if (buf == NULL) {
+		pr_err("aoe: nextbuf: unable to mempool_alloc!\n");
+		return NULL;
+	}
+	bio = d->ip.nxbio;
+	bufinit(buf, rq, bio);
+	bio = bio->bi_next;
+	d->ip.nxbio = bio;
+	if (bio == NULL)
+		d->ip.rq = NULL;
+	return d->ip.buf = buf;
 }
 
 /* enters with d->lock held */
 void
 aoecmd_work(struct aoedev *d)
 {
-	struct buf *buf;
-loop:
 	if (d->htgt && !sthtith(d))
 		return;
-	if (d->inprocess == NULL) {
-		if (list_empty(&d->bufq))
-			return;
-		buf = container_of(d->bufq.next, struct buf, bufs);
-		list_del(d->bufq.next);
-		d->inprocess = buf;
-	}
-	if (aoecmd_ata_rw(d))
-		goto loop;
+	while (aoecmd_ata_rw(d))
+		;
 }
 
 /* this function performs work that has been deferred until sleeping is OK
@@ -604,28 +786,25 @@ void
 aoecmd_sleepwork(struct work_struct *work)
 {
 	struct aoedev *d = container_of(work, struct aoedev, work);
+	struct block_device *bd;
+	u64 ssize;
 
 	if (d->flags & DEVFL_GDALLOC)
 		aoeblk_gdalloc(d);
 
 	if (d->flags & DEVFL_NEWSIZE) {
-		struct block_device *bd;
-		unsigned long flags;
-		u64 ssize;
-
 		ssize = get_capacity(d->gd);
 		bd = bdget_disk(d->gd, 0);
-
 		if (bd) {
 			mutex_lock(&bd->bd_inode->i_mutex);
 			i_size_write(bd->bd_inode, (loff_t)ssize<<9);
 			mutex_unlock(&bd->bd_inode->i_mutex);
 			bdput(bd);
 		}
-		spin_lock_irqsave(&d->lock, flags);
+		spin_lock_irq(&d->lock);
 		d->flags |= DEVFL_UP;
 		d->flags &= ~DEVFL_NEWSIZE;
-		spin_unlock_irqrestore(&d->lock, flags);
+		spin_unlock_irq(&d->lock);
 	}
 }
 
@@ -718,163 +897,299 @@ gettgt(struct aoedev *d, char *addr)
 	return NULL;
 }
 
-static inline void
-diskstats(struct gendisk *disk, struct bio *bio, ulong duration, sector_t sector)
+static void
+bvcpy(struct bio_vec *bv, ulong off, struct sk_buff *skb, long cnt)
+{
+	ulong fcnt;
+	char *p;
+	int soff = 0;
+loop:
+	fcnt = bv->bv_len - (off - bv->bv_offset);
+	if (fcnt > cnt)
+		fcnt = cnt;
+	p = page_address(bv->bv_page) + off;
+	skb_copy_bits(skb, soff, p, fcnt);
+	soff += fcnt;
+	cnt -= fcnt;
+	if (cnt <= 0)
+		return;
+	bv++;
+	off = bv->bv_offset;
+	goto loop;
+}
+
+void
+aoe_end_request(struct aoedev *d, struct request *rq, int fastfail)
+{
+	struct bio *bio;
+	int bok;
+	struct request_queue *q;
+
+	q = d->blkq;
+	if (rq == d->ip.rq)
+		d->ip.rq = NULL;
+	do {
+		bio = rq->bio;
+		bok = !fastfail && test_bit(BIO_UPTODATE, &bio->bi_flags);
+	} while (__blk_end_request(rq, bok ? 0 : -EIO, bio->bi_size));
+
+	/* cf. http://lkml.org/lkml/2006/10/31/28 */
+	if (!fastfail)
+		q->request_fn(q);
+}
+
+static void
+aoe_end_buf(struct aoedev *d, struct buf *buf)
+{
+	struct request *rq;
+	unsigned long n;
+
+	if (buf == d->ip.buf)
+		d->ip.buf = NULL;
+	rq = buf->rq;
+	bio_pagedec(buf->bio);
+	mempool_free(buf, d->bufpool);
+	n = (unsigned long) rq->special;
+	rq->special = (void *) --n;
+	if (n == 0)
+		aoe_end_request(d, rq, 0);
+}
+
+static void
+ktiocomplete(struct frame *f)
 {
-	unsigned long n_sect = bio->bi_size >> 9;
-	const int rw = bio_data_dir(bio);
-	struct hd_struct *part;
-	int cpu;
+	struct aoe_hdr *hin, *hout;
+	struct aoe_atahdr *ahin, *ahout;
+	struct buf *buf;
+	struct sk_buff *skb;
+	struct aoetgt *t;
+	struct aoeif *ifp;
+	struct aoedev *d;
+	long n;
+
+	if (f == NULL)
+		return;
+
+	t = f->t;
+	d = t->d;
+
+	hout = (struct aoe_hdr *) skb_mac_header(f->skb);
+	ahout = (struct aoe_atahdr *) (hout+1);
+	buf = f->buf;
+	skb = f->r_skb;
+	if (skb == NULL)
+		goto noskb;	/* just fail the buf. */
+
+	hin = (struct aoe_hdr *) skb->data;
+	skb_pull(skb, sizeof(*hin));
+	ahin = (struct aoe_atahdr *) skb->data;
+	skb_pull(skb, sizeof(*ahin));
+	if (ahin->cmdstat & 0xa9) {	/* these bits cleared on success */
+		pr_err("aoe: ata error cmd=%2.2Xh stat=%2.2Xh from e%ld.%d\n",
+			ahout->cmdstat, ahin->cmdstat,
+			d->aoemajor, d->aoeminor);
+noskb:	if (buf)
+			clear_bit(BIO_UPTODATE, &buf->bio->bi_flags);
+		goto badrsp;
+	}
+
+	n = ahout->scnt << 9;
+	switch (ahout->cmdstat) {
+	case ATA_CMD_PIO_READ:
+	case ATA_CMD_PIO_READ_EXT:
+		if (skb->len < n) {
+			pr_err("aoe: runt data size in read.  skb->len=%d need=%ld\n",
+				skb->len, n);
+			clear_bit(BIO_UPTODATE, &buf->bio->bi_flags);
+			break;
+		}
+		bvcpy(f->bv, f->bv_off, skb, n);
+	case ATA_CMD_PIO_WRITE:
+	case ATA_CMD_PIO_WRITE_EXT:
+		spin_lock_irq(&d->lock);
+		ifp = getif(t, skb->dev);
+		if (ifp)
+			ifp->lost = 0;
+		if (d->htgt == t) /* I'll help myself, thank you. */
+			d->htgt = NULL;
+		spin_unlock_irq(&d->lock);
+		break;
+	case ATA_CMD_ID_ATA:
+		if (skb->len < 512) {
+			pr_info("aoe: runt data size in ataid.  skb->len=%d\n",
+				skb->len);
+			break;
+		}
+		if (skb_linearize(skb))
+			break;
+		spin_lock_irq(&d->lock);
+		ataid_complete(d, t, skb->data);
+		spin_unlock_irq(&d->lock);
+		break;
+	default:
+		pr_info("aoe: unrecognized ata command %2.2Xh for %d.%d\n",
+			ahout->cmdstat,
+			be16_to_cpu(get_unaligned(&hin->major)),
+			hin->minor);
+	}
+badrsp:
+	spin_lock_irq(&d->lock);
+
+	aoe_freetframe(f);
+
+	if (buf && --buf->nframesout == 0 && buf->resid == 0)
+		aoe_end_buf(d, buf);
+
+	aoecmd_work(d);
+
+	spin_unlock_irq(&d->lock);
+	aoedev_put(d);
+	dev_kfree_skb(skb);
+}
 
-	cpu = part_stat_lock();
-	part = disk_map_sector_rcu(disk, sector);
+/* Enters with iocq.lock held.
+ * Returns true iff responses needing processing remain.
+ */
+static int
+ktio(void)
+{
+	struct frame *f;
+	struct list_head *pos;
+	int i;
 
-	part_stat_inc(cpu, part, ios[rw]);
-	part_stat_add(cpu, part, ticks[rw], duration);
-	part_stat_add(cpu, part, sectors[rw], n_sect);
-	part_stat_add(cpu, part, io_ticks, duration);
+	for (i = 0; ; ++i) {
+		if (i == MAXIOC)
+			return 1;
+		if (list_empty(&iocq.head))
+			return 0;
+		pos = iocq.head.next;
+		list_del(pos);
+		spin_unlock_irq(&iocq.lock);
+		f = list_entry(pos, struct frame, head);
+		ktiocomplete(f);
+		spin_lock_irq(&iocq.lock);
+	}
+}
 
-	part_stat_unlock();
+static int
+kthread(void *vp)
+{
+	struct ktstate *k;
+	DECLARE_WAITQUEUE(wait, current);
+	int more;
+
+	k = vp;
+	current->flags |= PF_NOFREEZE;
+	set_user_nice(current, -10);
+	complete(&k->rendez);	/* tell spawner we're running */
+	do {
+		spin_lock_irq(k->lock);
+		more = k->fn();
+		if (!more) {
+			add_wait_queue(k->waitq, &wait);
+			__set_current_state(TASK_INTERRUPTIBLE);
+		}
+		spin_unlock_irq(k->lock);
+		if (!more) {
+			schedule();
+			remove_wait_queue(k->waitq, &wait);
+		} else
+			cond_resched();
+	} while (!kthread_should_stop());
+	complete(&k->rendez);	/* tell spawner we're stopping */
+	return 0;
 }
 
 void
+aoe_ktstop(struct ktstate *k)
+{
+	kthread_stop(k->task);
+	wait_for_completion(&k->rendez);
+}
+
+int
+aoe_ktstart(struct ktstate *k)
+{
+	struct task_struct *task;
+
+	init_completion(&k->rendez);
+	task = kthread_run(kthread, k, k->name);
+	if (task == NULL || IS_ERR(task))
+		return -ENOMEM;
+	k->task = task;
+	wait_for_completion(&k->rendez); /* allow kthread to start */
+	init_completion(&k->rendez);	/* for waiting for exit later */
+	return 0;
+}
+
+/* pass it off to kthreads for processing */
+static void
+ktcomplete(struct frame *f, struct sk_buff *skb)
+{
+	ulong flags;
+
+	f->r_skb = skb;
+	spin_lock_irqsave(&iocq.lock, flags);
+	list_add_tail(&f->head, &iocq.head);
+	spin_unlock_irqrestore(&iocq.lock, flags);
+	wake_up(&ktiowq);
+}
+
+struct sk_buff *
 aoecmd_ata_rsp(struct sk_buff *skb)
 {
-	struct sk_buff_head queue;
 	struct aoedev *d;
-	struct aoe_hdr *hin, *hout;
-	struct aoe_atahdr *ahin, *ahout;
+	struct aoe_hdr *h;
 	struct frame *f;
-	struct buf *buf;
 	struct aoetgt *t;
-	struct aoeif *ifp;
-	register long n;
+	u32 n;
 	ulong flags;
 	char ebuf[128];
 	u16 aoemajor;
 
-	hin = (struct aoe_hdr *) skb_mac_header(skb);
-	aoemajor = get_unaligned_be16(&hin->major);
-	d = aoedev_by_aoeaddr(aoemajor, hin->minor);
+	h = (struct aoe_hdr *) skb->data;
+	aoemajor = be16_to_cpu(get_unaligned(&h->major));
+	d = aoedev_by_aoeaddr(aoemajor, h->minor);
 	if (d == NULL) {
 		snprintf(ebuf, sizeof ebuf, "aoecmd_ata_rsp: ata response "
 			"for unknown device %d.%d\n",
-			 aoemajor, hin->minor);
+			aoemajor, h->minor);
 		aoechr_error(ebuf);
-		return;
+		return skb;
 	}
 
 	spin_lock_irqsave(&d->lock, flags);
 
-	n = get_unaligned_be32(&hin->tag);
-	t = gettgt(d, hin->src);
-	if (t == NULL) {
-		printk(KERN_INFO "aoe: can't find target e%ld.%d:%pm\n",
-			d->aoemajor, d->aoeminor, hin->src);
-		spin_unlock_irqrestore(&d->lock, flags);
-		return;
-	}
-	f = getframe(t, n);
+	n = be32_to_cpu(get_unaligned(&h->tag));
+	f = getframe(d, n);
 	if (f == NULL) {
 		calc_rttavg(d, -tsince(n));
 		spin_unlock_irqrestore(&d->lock, flags);
+		aoedev_put(d);
 		snprintf(ebuf, sizeof ebuf,
 			"%15s e%d.%d    tag=%08x@%08lx\n",
 			"unexpected rsp",
-			get_unaligned_be16(&hin->major),
-			hin->minor,
-			get_unaligned_be32(&hin->tag),
+			get_unaligned_be16(&h->major),
+			h->minor,
+			get_unaligned_be32(&h->tag),
 			jiffies);
 		aoechr_error(ebuf);
-		return;
+		return skb;
 	}
-
+	t = f->t;
 	calc_rttavg(d, tsince(f->tag));
-
-	ahin = (struct aoe_atahdr *) (hin+1);
-	hout = (struct aoe_hdr *) skb_mac_header(f->skb);
-	ahout = (struct aoe_atahdr *) (hout+1);
-	buf = f->buf;
-
-	if (ahin->cmdstat & 0xa9) {	/* these bits cleared on success */
-		printk(KERN_ERR
-			"aoe: ata error cmd=%2.2Xh stat=%2.2Xh from e%ld.%d\n",
-			ahout->cmdstat, ahin->cmdstat,
-			d->aoemajor, d->aoeminor);
-		if (buf)
-			buf->flags |= BUFFL_FAIL;
-	} else {
-		if (d->htgt && t == *d->htgt) /* I'll help myself, thank you. */
-			d->htgt = NULL;
-		n = ahout->scnt << 9;
-		switch (ahout->cmdstat) {
-		case ATA_CMD_PIO_READ:
-		case ATA_CMD_PIO_READ_EXT:
-			if (skb->len - sizeof *hin - sizeof *ahin < n) {
-				printk(KERN_ERR
-					"aoe: %s.  skb->len=%d need=%ld\n",
-					"runt data size in read", skb->len, n);
-				/* fail frame f?  just returning will rexmit. */
-				spin_unlock_irqrestore(&d->lock, flags);
-				return;
-			}
-			memcpy(f->bufaddr, ahin+1, n);
-		case ATA_CMD_PIO_WRITE:
-		case ATA_CMD_PIO_WRITE_EXT:
-			ifp = getif(t, skb->dev);
-			if (ifp) {
-				ifp->lost = 0;
-				if (n > DEFAULTBCNT)
-					ifp->lostjumbo = 0;
-			}
-			if (f->bcnt -= n) {
-				f->lba += n >> 9;
-				f->bufaddr += n;
-				resend(d, t, f);
-				goto xmit;
-			}
-			break;
-		case ATA_CMD_ID_ATA:
-			if (skb->len - sizeof *hin - sizeof *ahin < 512) {
-				printk(KERN_INFO
-					"aoe: runt data size in ataid.  skb->len=%d\n",
-					skb->len);
-				spin_unlock_irqrestore(&d->lock, flags);
-				return;
-			}
-			ataid_complete(d, t, (char *) (ahin+1));
-			break;
-		default:
-			printk(KERN_INFO
-				"aoe: unrecognized ata command %2.2Xh for %d.%d\n",
-				ahout->cmdstat,
-				get_unaligned_be16(&hin->major),
-				hin->minor);
-		}
-	}
-
-	if (buf && --buf->nframesout == 0 && buf->resid == 0) {
-		diskstats(d->gd, buf->bio, jiffies - buf->stime, buf->sector);
-		if (buf->flags & BUFFL_FAIL)
-			bio_endio(buf->bio, -EIO);
-		else {
-			bio_flush_dcache_pages(buf->bio);
-			bio_endio(buf->bio, 0);
-		}
-		mempool_free(buf, d->bufpool);
-	}
-
-	f->buf = NULL;
-	f->tag = FREETAG;
 	t->nout--;
-
 	aoecmd_work(d);
-xmit:
-	__skb_queue_head_init(&queue);
-	skb_queue_splice_init(&d->sendq, &queue);
 
 	spin_unlock_irqrestore(&d->lock, flags);
-	aoenet_xmit(&queue);
+
+	ktcomplete(f, skb);
+
+	/*
+	 * Note here that we do not perform an aoedev_put, as we are
+	 * leaving this reference for the ktio to release.
+	 */
+	return NULL;
 }
 
 void
@@ -896,7 +1211,7 @@ aoecmd_ata_id(struct aoedev *d)
 	struct sk_buff *skb;
 	struct aoetgt *t;
 
-	f = freeframe(d);
+	f = newframe(d);
 	if (f == NULL)
 		return NULL;
 
@@ -909,6 +1224,7 @@ aoecmd_ata_id(struct aoedev *d)
 	skb_put(skb, sizeof *h + sizeof *ah);
 	memset(h, 0, skb->len);
 	f->tag = aoehdr_atainit(d, t, h);
+	fhash(f);
 	t->nout++;
 	f->waited = 0;
 
@@ -929,7 +1245,6 @@ static struct aoetgt *
 addtgt(struct aoedev *d, char *addr, ulong nframes)
 {
 	struct aoetgt *t, **tt, **te;
-	struct frame *f, *e;
 
 	tt = d->targets;
 	te = tt + NTARGETS;
@@ -941,26 +1256,73 @@ addtgt(struct aoedev *d, char *addr, ulong nframes)
 			"aoe: device addtgt failure; too many targets\n");
 		return NULL;
 	}
-	t = kcalloc(1, sizeof *t, GFP_ATOMIC);
-	f = kcalloc(nframes, sizeof *f, GFP_ATOMIC);
-	if (!t || !f) {
-		kfree(f);
-		kfree(t);
+	t = kzalloc(sizeof(*t), GFP_ATOMIC);
+	if (!t) {
 		printk(KERN_INFO "aoe: cannot allocate memory to add target\n");
 		return NULL;
 	}
 
+	d->ntargets++;
 	t->nframes = nframes;
-	t->frames = f;
-	e = f + nframes;
-	for (; f < e; f++)
-		f->tag = FREETAG;
+	t->d = d;
 	memcpy(t->addr, addr, sizeof t->addr);
 	t->ifp = t->ifs;
 	t->maxout = t->nframes;
+	INIT_LIST_HEAD(&t->ffree);
 	return *tt = t;
 }
 
+static void
+setdbcnt(struct aoedev *d)
+{
+	struct aoetgt **t, **e;
+	int bcnt = 0;
+
+	t = d->targets;
+	e = t + NTARGETS;
+	for (; t < e && *t; t++)
+		if (bcnt == 0 || bcnt > (*t)->minbcnt)
+			bcnt = (*t)->minbcnt;
+	if (bcnt != d->maxbcnt) {
+		d->maxbcnt = bcnt;
+		pr_info("aoe: e%ld.%d: setting %d byte data frames\n",
+			d->aoemajor, d->aoeminor, bcnt);
+	}
+}
+
+static void
+setifbcnt(struct aoetgt *t, struct net_device *nd, int bcnt)
+{
+	struct aoedev *d;
+	struct aoeif *p, *e;
+	int minbcnt;
+
+	d = t->d;
+	minbcnt = bcnt;
+	p = t->ifs;
+	e = p + NAOEIFS;
+	for (; p < e; p++) {
+		if (p->nd == NULL)
+			break;		/* end of the valid interfaces */
+		if (p->nd == nd) {
+			p->bcnt = bcnt;	/* we're updating */
+			nd = NULL;
+		} else if (minbcnt > p->bcnt)
+			minbcnt = p->bcnt; /* find the min interface */
+	}
+	if (nd) {
+		if (p == e) {
+			pr_err("aoe: device setifbcnt failure; too many interfaces.\n");
+			return;
+		}
+		dev_hold(nd);
+		p->nd = nd;
+		p->bcnt = bcnt;
+	}
+	t->minbcnt = minbcnt;
+	setdbcnt(d);
+}
+
 void
 aoecmd_cfg_rsp(struct sk_buff *skb)
 {
@@ -968,11 +1330,12 @@ aoecmd_cfg_rsp(struct sk_buff *skb)
 	struct aoe_hdr *h;
 	struct aoe_cfghdr *ch;
 	struct aoetgt *t;
-	struct aoeif *ifp;
 	ulong flags, sysminor, aoemajor;
 	struct sk_buff *sl;
+	struct sk_buff_head queue;
 	u16 n;
 
+	sl = NULL;
 	h = (struct aoe_hdr *) skb_mac_header(skb);
 	ch = (struct aoe_cfghdr *) (h+1);
 
@@ -986,6 +1349,13 @@ aoecmd_cfg_rsp(struct sk_buff *skb)
 			"Check shelf dip switches.\n");
 		return;
 	}
+	if (h->minor >= NPERSHELF) {
+		pr_err("aoe: e%ld.%d %s, %d\n",
+			aoemajor, h->minor,
+			"slot number larger than the maximum",
+			NPERSHELF-1);
+		return;
+	}
 
 	sysminor = SYSMINOR(aoemajor, h->minor);
 	if (sysminor * AOE_PARTITIONS + AOE_PARTITIONS > MINORMASK) {
@@ -1009,52 +1379,26 @@ aoecmd_cfg_rsp(struct sk_buff *skb)
 	t = gettgt(d, h->src);
 	if (!t) {
 		t = addtgt(d, h->src, n);
-		if (!t) {
-			spin_unlock_irqrestore(&d->lock, flags);
-			return;
-		}
-	}
-	ifp = getif(t, skb->dev);
-	if (!ifp) {
-		ifp = addif(t, skb->dev);
-		if (!ifp) {
-			printk(KERN_INFO
-				"aoe: device addif failure; "
-				"too many interfaces?\n");
-			spin_unlock_irqrestore(&d->lock, flags);
-			return;
-		}
-	}
-	if (ifp->maxbcnt) {
-		n = ifp->nd->mtu;
-		n -= sizeof (struct aoe_hdr) + sizeof (struct aoe_atahdr);
-		n /= 512;
-		if (n > ch->scnt)
-			n = ch->scnt;
-		n = n ? n * 512 : DEFAULTBCNT;
-		if (n != ifp->maxbcnt) {
-			printk(KERN_INFO
-				"aoe: e%ld.%d: setting %d%s%s:%pm\n",
-				d->aoemajor, d->aoeminor, n,
-				" byte data frames on ", ifp->nd->name,
-				t->addr);
-			ifp->maxbcnt = n;
-		}
+		if (!t)
+			goto bail;
 	}
+	n = skb->dev->mtu;
+	n -= sizeof(struct aoe_hdr) + sizeof(struct aoe_atahdr);
+	n /= 512;
+	if (n > ch->scnt)
+		n = ch->scnt;
+	n = n ? n * 512 : DEFAULTBCNT;
+	setifbcnt(t, skb->dev, n);
 
 	/* don't change users' perspective */
-	if (d->nopen) {
-		spin_unlock_irqrestore(&d->lock, flags);
-		return;
+	if (d->nopen == 0) {
+		d->fw_ver = be16_to_cpu(ch->fwver);
+		sl = aoecmd_ata_id(d);
 	}
-	d->fw_ver = be16_to_cpu(ch->fwver);
-
-	sl = aoecmd_ata_id(d);
-
+bail:
 	spin_unlock_irqrestore(&d->lock, flags);
-
+	aoedev_put(d);
 	if (sl) {
-		struct sk_buff_head queue;
 		__skb_queue_head_init(&queue);
 		__skb_queue_tail(&queue, sl);
 		aoenet_xmit(&queue);
@@ -1065,20 +1409,74 @@ void
 aoecmd_cleanslate(struct aoedev *d)
 {
 	struct aoetgt **t, **te;
-	struct aoeif *p, *e;
 
 	d->mintimer = MINTIMER;
+	d->maxbcnt = 0;
 
 	t = d->targets;
 	te = t + NTARGETS;
-	for (; t < te && *t; t++) {
+	for (; t < te && *t; t++)
 		(*t)->maxout = (*t)->nframes;
-		p = (*t)->ifs;
-		e = p + NAOEIFS;
-		for (; p < e; p++) {
-			p->lostjumbo = 0;
-			p->lost = 0;
-			p->maxbcnt = DEFAULTBCNT;
+}
+
+void
+aoe_failbuf(struct aoedev *d, struct buf *buf)
+{
+	if (buf == NULL)
+		return;
+	buf->resid = 0;
+	clear_bit(BIO_UPTODATE, &buf->bio->bi_flags);
+	if (buf->nframesout == 0)
+		aoe_end_buf(d, buf);
+}
+
+void
+aoe_flush_iocq(void)
+{
+	struct frame *f;
+	struct aoedev *d;
+	LIST_HEAD(flist);
+	struct list_head *pos;
+	struct sk_buff *skb;
+	ulong flags;
+
+	spin_lock_irqsave(&iocq.lock, flags);
+	list_splice_init(&iocq.head, &flist);
+	spin_unlock_irqrestore(&iocq.lock, flags);
+	while (!list_empty(&flist)) {
+		pos = flist.next;
+		list_del(pos);
+		f = list_entry(pos, struct frame, head);
+		d = f->t->d;
+		skb = f->r_skb;
+		spin_lock_irqsave(&d->lock, flags);
+		if (f->buf) {
+			f->buf->nframesout--;
+			aoe_failbuf(d, f->buf);
 		}
+		aoe_freetframe(f);
+		spin_unlock_irqrestore(&d->lock, flags);
+		dev_kfree_skb(skb);
+		aoedev_put(d);
 	}
 }
+
+int __init
+aoecmd_init(void)
+{
+	INIT_LIST_HEAD(&iocq.head);
+	spin_lock_init(&iocq.lock);
+	init_waitqueue_head(&ktiowq);
+	kts.name = "aoe_ktio";
+	kts.fn = ktio;
+	kts.waitq = &ktiowq;
+	kts.lock = &iocq.lock;
+	return aoe_ktstart(&kts);
+}
+
+void
+aoecmd_exit(void)
+{
+	aoe_ktstop(&kts);
+	aoe_flush_iocq();
+}
diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c
index 6b5110a..ccaecff 100644
--- a/drivers/block/aoe/aoedev.c
+++ b/drivers/block/aoe/aoedev.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007 Coraid, Inc.  See COPYING for GPL terms. */
+/* Copyright (c) 2012 Coraid, Inc.  See COPYING for GPL terms. */
 /*
  * aoedev.c
  * AoE device utility functions; maintains device list.
@@ -19,6 +19,17 @@ static void skbpoolfree(struct aoedev *d);
 static struct aoedev *devlist;
 static DEFINE_SPINLOCK(devlist_lock);
 
+/*
+ * Users who grab a pointer to the device with aoedev_by_aoeaddr or
+ * aoedev_by_sysminor_m automatically get a reference count and must
+ * be responsible for performing a aoedev_put.  With the addition of
+ * async kthread processing I'm no longer confident that we can
+ * guarantee consistency in the face of device flushes.
+ *
+ * For the time being, we only bother to add extra references for
+ * frames sitting on the iocq.  When the kthreads finish processing
+ * these frames, they will aoedev_put the device.
+ */
 struct aoedev *
 aoedev_by_aoeaddr(int maj, int min)
 {
@@ -28,13 +39,25 @@ aoedev_by_aoeaddr(int maj, int min)
 	spin_lock_irqsave(&devlist_lock, flags);
 
 	for (d=devlist; d; d=d->next)
-		if (d->aoemajor == maj && d->aoeminor == min)
+		if (d->aoemajor == maj && d->aoeminor == min) {
+			d->ref++;
 			break;
+		}
 
 	spin_unlock_irqrestore(&devlist_lock, flags);
 	return d;
 }
 
+void
+aoedev_put(struct aoedev *d)
+{
+	ulong flags;
+
+	spin_lock_irqsave(&devlist_lock, flags);
+	d->ref--;
+	spin_unlock_irqrestore(&devlist_lock, flags);
+}
+
 static void
 dummy_timer(ulong vp)
 {
@@ -47,54 +70,74 @@ dummy_timer(ulong vp)
 	add_timer(&d->timer);
 }
 
+static void
+aoe_failip(struct aoedev *d)
+{
+	struct request *rq;
+	struct bio *bio;
+	unsigned long n;
+
+	aoe_failbuf(d, d->ip.buf);
+
+	rq = d->ip.rq;
+	if (rq == NULL)
+		return;
+	while ((bio = d->ip.nxbio)) {
+		clear_bit(BIO_UPTODATE, &bio->bi_flags);
+		d->ip.nxbio = bio->bi_next;
+		n = (unsigned long) rq->special;
+		rq->special = (void *) --n;
+	}
+	if ((unsigned long) rq->special == 0)
+		aoe_end_request(d, rq, 0);
+}
+
 void
 aoedev_downdev(struct aoedev *d)
 {
-	struct aoetgt **t, **te;
-	struct frame *f, *e;
-	struct buf *buf;
-	struct bio *bio;
+	struct aoetgt *t, **tt, **te;
+	struct frame *f;
+	struct list_head *head, *pos, *nx;
+	struct request *rq;
+	int i;
 
-	t = d->targets;
-	te = t + NTARGETS;
-	for (; t < te && *t; t++) {
-		f = (*t)->frames;
-		e = f + (*t)->nframes;
-		for (; f < e; f->tag = FREETAG, f->buf = NULL, f++) {
-			if (f->tag == FREETAG || f->buf == NULL)
-				continue;
-			buf = f->buf;
-			bio = buf->bio;
-			if (--buf->nframesout == 0
-			&& buf != d->inprocess) {
-				mempool_free(buf, d->bufpool);
-				bio_endio(bio, -EIO);
+	d->flags &= ~DEVFL_UP;
+
+	/* clean out active buffers */
+	for (i = 0; i < NFACTIVE; i++) {
+		head = &d->factive[i];
+		list_for_each_safe(pos, nx, head) {
+			f = list_entry(pos, struct frame, head);
+			list_del(pos);
+			if (f->buf) {
+				f->buf->nframesout--;
+				aoe_failbuf(d, f->buf);
 			}
+			aoe_freetframe(f);
 		}
-		(*t)->maxout = (*t)->nframes;
-		(*t)->nout = 0;
 	}
-	buf = d->inprocess;
-	if (buf) {
-		bio = buf->bio;
-		mempool_free(buf, d->bufpool);
-		bio_endio(bio, -EIO);
+	/* reset window dressings */
+	tt = d->targets;
+	te = tt + NTARGETS;
+	for (; tt < te && (t = *tt); tt++) {
+		t->maxout = t->nframes;
+		t->nout = 0;
 	}
-	d->inprocess = NULL;
+
+	/* clean out the in-process request (if any) */
+	aoe_failip(d);
 	d->htgt = NULL;
 
-	while (!list_empty(&d->bufq)) {
-		buf = container_of(d->bufq.next, struct buf, bufs);
-		list_del(d->bufq.next);
-		bio = buf->bio;
-		mempool_free(buf, d->bufpool);
-		bio_endio(bio, -EIO);
+	/* fast fail all pending I/O */
+	if (d->blkq) {
+		while ((rq = blk_peek_request(d->blkq))) {
+			blk_start_request(rq);
+			aoe_end_request(d, rq, 1);
+		}
 	}
 
 	if (d->gd)
 		set_capacity(d->gd, 0);
-
-	d->flags &= ~DEVFL_UP;
 }
 
 static void
@@ -107,6 +150,7 @@ aoedev_freedev(struct aoedev *d)
 		aoedisk_rm_sysfs(d);
 		del_gendisk(d->gd);
 		put_disk(d->gd);
+		blk_cleanup_queue(d->blkq);
 	}
 	t = d->targets;
 	e = t + NTARGETS;
@@ -115,7 +159,6 @@ aoedev_freedev(struct aoedev *d)
 	if (d->bufpool)
 		mempool_destroy(d->bufpool);
 	skbpoolfree(d);
-	blk_cleanup_queue(d->blkq);
 	kfree(d);
 }
 
@@ -142,7 +185,8 @@ aoedev_flush(const char __user *str, size_t cnt)
 		spin_lock(&d->lock);
 		if ((!all && (d->flags & DEVFL_UP))
 		|| (d->flags & (DEVFL_GDALLOC|DEVFL_NEWSIZE))
-		|| d->nopen) {
+		|| d->nopen
+		|| d->ref) {
 			spin_unlock(&d->lock);
 			dd = &d->next;
 			continue;
@@ -163,12 +207,15 @@ aoedev_flush(const char __user *str, size_t cnt)
 	return 0;
 }
 
-/* I'm not really sure that this is a realistic problem, but if the
-network driver goes gonzo let's just leak memory after complaining. */
+/* This has been confirmed to occur once with Tms=3*1000 due to the
+ * driver changing link and not processing its transmit ring.  The
+ * problem is hard enough to solve by returning an error that I'm
+ * still punting on "solving" this.
+ */
 static void
 skbfree(struct sk_buff *skb)
 {
-	enum { Sms = 100, Tms = 3*1000};
+	enum { Sms = 250, Tms = 30 * 1000};
 	int i = Tms / Sms;
 
 	if (skb == NULL)
@@ -182,6 +229,7 @@ skbfree(struct sk_buff *skb)
 			"cannot free skb -- memory leaked.");
 		return;
 	}
+	skb->truesize -= skb->data_len;
 	skb_shinfo(skb)->nr_frags = skb->data_len = 0;
 	skb_trim(skb, 0);
 	dev_kfree_skb(skb);
@@ -203,13 +251,16 @@ struct aoedev *
 aoedev_by_sysminor_m(ulong sysminor)
 {
 	struct aoedev *d;
+	int i;
 	ulong flags;
 
 	spin_lock_irqsave(&devlist_lock, flags);
 
 	for (d=devlist; d; d=d->next)
-		if (d->sysminor == sysminor)
+		if (d->sysminor == sysminor) {
+			d->ref++;
 			break;
+		}
 	if (d)
 		goto out;
 	d = kcalloc(1, sizeof *d, GFP_ATOMIC);
@@ -217,7 +268,6 @@ aoedev_by_sysminor_m(ulong sysminor)
 		goto out;
 	INIT_WORK(&d->work, aoecmd_sleepwork);
 	spin_lock_init(&d->lock);
-	skb_queue_head_init(&d->sendq);
 	skb_queue_head_init(&d->skbpool);
 	init_timer(&d->timer);
 	d->timer.data = (ulong) d;
@@ -226,7 +276,9 @@ aoedev_by_sysminor_m(ulong sysminor)
 	add_timer(&d->timer);
 	d->bufpool = NULL;	/* defer to aoeblk_gdalloc */
 	d->tgt = d->targets;
-	INIT_LIST_HEAD(&d->bufq);
+	d->ref = 1;
+	for (i = 0; i < NFACTIVE; i++)
+		INIT_LIST_HEAD(&d->factive[i]);
 	d->sysminor = sysminor;
 	d->aoemajor = AOEMAJOR(sysminor);
 	d->aoeminor = AOEMINOR(sysminor);
@@ -241,13 +293,23 @@ aoedev_by_sysminor_m(ulong sysminor)
 static void
 freetgt(struct aoedev *d, struct aoetgt *t)
 {
-	struct frame *f, *e;
+	struct frame *f;
+	struct list_head *pos, *nx, *head;
+	struct aoeif *ifp;
 
-	f = t->frames;
-	e = f + t->nframes;
-	for (; f < e; f++)
+	for (ifp = t->ifs; ifp < &t->ifs[NAOEIFS]; ++ifp) {
+		if (!ifp->nd)
+			break;
+		dev_put(ifp->nd);
+	}
+
+	head = &t->ffree;
+	list_for_each_safe(pos, nx, head) {
+		list_del(pos);
+		f = list_entry(pos, struct frame, head);
 		skbfree(f->skb);
-	kfree(t->frames);
+		kfree(f);
+	}
 	kfree(t);
 }
 
@@ -257,6 +319,7 @@ aoedev_exit(void)
 	struct aoedev *d;
 	ulong flags;
 
+	aoe_flush_iocq();
 	while ((d = devlist)) {
 		devlist = d->next;
 
diff --git a/drivers/block/aoe/aoemain.c b/drivers/block/aoe/aoemain.c
index 7f83ad9..04793c2 100644
--- a/drivers/block/aoe/aoemain.c
+++ b/drivers/block/aoe/aoemain.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007 Coraid, Inc.  See COPYING for GPL terms. */
+/* Copyright (c) 2012 Coraid, Inc.  See COPYING for GPL terms. */
 /*
  * aoemain.c
  * Module initialization routines, discover timer
@@ -61,6 +61,7 @@ aoe_exit(void)
 
 	aoenet_exit();
 	unregister_blkdev(AOE_MAJOR, DEVICE_NAME);
+	aoecmd_exit();
 	aoechr_exit();
 	aoedev_exit();
 	aoeblk_exit();		/* free cache after de-allocating bufs */
@@ -83,17 +84,20 @@ aoe_init(void)
 	ret = aoenet_init();
 	if (ret)
 		goto net_fail;
+	ret = aoecmd_init();
+	if (ret)
+		goto cmd_fail;
 	ret = register_blkdev(AOE_MAJOR, DEVICE_NAME);
 	if (ret < 0) {
 		printk(KERN_ERR "aoe: can't register major\n");
 		goto blkreg_fail;
 	}
-
 	printk(KERN_INFO "aoe: AoE v%s initialised.\n", VERSION);
 	discover_timer(TINIT);
 	return 0;
-
  blkreg_fail:
+	aoecmd_exit();
+ cmd_fail:
 	aoenet_exit();
  net_fail:
 	aoeblk_exit();
diff --git a/drivers/block/aoe/aoenet.c b/drivers/block/aoe/aoenet.c
index 4d3bc0d..162c647 100644
--- a/drivers/block/aoe/aoenet.c
+++ b/drivers/block/aoe/aoenet.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2007 Coraid, Inc.  See COPYING for GPL terms. */
+/* Copyright (c) 2012 Coraid, Inc.  See COPYING for GPL terms. */
 /*
  * aoenet.c
  * Ethernet portion of AoE driver
@@ -33,6 +33,9 @@ static char aoe_iflist[IFLISTSZ];
 module_param_string(aoe_iflist, aoe_iflist, IFLISTSZ, 0600);
 MODULE_PARM_DESC(aoe_iflist, "aoe_iflist=\"dev1 [dev2 ...]\"");
 
+static wait_queue_head_t txwq;
+static struct ktstate kts;
+
 #ifndef MODULE
 static int __init aoe_iflist_setup(char *str)
 {
@@ -44,6 +47,23 @@ static int __init aoe_iflist_setup(char *str)
 __setup("aoe_iflist=", aoe_iflist_setup);
 #endif
 
+static spinlock_t txlock;
+static struct sk_buff_head skbtxq;
+
+/* enters with txlock held */
+static int
+tx(void)
+{
+	struct sk_buff *skb;
+
+	while ((skb = skb_dequeue(&skbtxq))) {
+		spin_unlock_irq(&txlock);
+		dev_queue_xmit(skb);
+		spin_lock_irq(&txlock);
+	}
+	return 0;
+}
+
 int
 is_aoe_netif(struct net_device *ifp)
 {
@@ -88,10 +108,14 @@ void
 aoenet_xmit(struct sk_buff_head *queue)
 {
 	struct sk_buff *skb, *tmp;
+	ulong flags;
 
 	skb_queue_walk_safe(queue, skb, tmp) {
 		__skb_unlink(skb, queue);
-		dev_queue_xmit(skb);
+		spin_lock_irqsave(&txlock, flags);
+		skb_queue_tail(&skbtxq, skb);
+		spin_unlock_irqrestore(&txlock, flags);
+		wake_up(&txwq);
 	}
 }
 
@@ -102,7 +126,9 @@ static int
 aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt, struct net_device *orig_dev)
 {
 	struct aoe_hdr *h;
+	struct aoe_atahdr *ah;
 	u32 n;
+	int sn;
 
 	if (dev_net(ifp) != &init_net)
 		goto exit;
@@ -110,13 +136,16 @@ aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt,
 	skb = skb_share_check(skb, GFP_ATOMIC);
 	if (skb == NULL)
 		return 0;
-	if (skb_linearize(skb))
-		goto exit;
 	if (!is_aoe_netif(ifp))
 		goto exit;
 	skb_push(skb, ETH_HLEN);	/* (1) */
-
-	h = (struct aoe_hdr *) skb_mac_header(skb);
+	sn = sizeof(*h) + sizeof(*ah);
+	if (skb->len >= sn) {
+		sn -= skb_headlen(skb);
+		if (sn > 0 && !__pskb_pull_tail(skb, sn))
+			goto exit;
+	}
+	h = (struct aoe_hdr *) skb->data;
 	n = get_unaligned_be32(&h->tag);
 	if ((h->verfl & AOEFL_RSP) == 0 || (n & 1<<31))
 		goto exit;
@@ -137,7 +166,8 @@ aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt,
 
 	switch (h->cmd) {
 	case AOECMD_ATA:
-		aoecmd_ata_rsp(skb);
+		/* ata_rsp may keep skb for later processing or give it back */
+		skb = aoecmd_ata_rsp(skb);
 		break;
 	case AOECMD_CFG:
 		aoecmd_cfg_rsp(skb);
@@ -145,8 +175,12 @@ aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt,
 	default:
 		if (h->cmd >= AOECMD_VEND_MIN)
 			break;	/* don't complain about vendor commands */
-		printk(KERN_INFO "aoe: unknown cmd %d\n", h->cmd);
+		pr_info("aoe: unknown AoE command type 0x%02x\n", h->cmd);
+		break;
 	}
+
+	if (!skb)
+		return 0;
 exit:
 	dev_kfree_skb(skb);
 	return 0;
@@ -160,6 +194,15 @@ static struct packet_type aoe_pt __read_mostly = {
 int __init
 aoenet_init(void)
 {
+	skb_queue_head_init(&skbtxq);
+	init_waitqueue_head(&txwq);
+	spin_lock_init(&txlock);
+	kts.lock = &txlock;
+	kts.fn = tx;
+	kts.waitq = &txwq;
+	kts.name = "aoe_tx";
+	if (aoe_ktstart(&kts))
+		return -EAGAIN;
 	dev_add_pack(&aoe_pt);
 	return 0;
 }
@@ -167,6 +210,8 @@ aoenet_init(void)
 void
 aoenet_exit(void)
 {
+	aoe_ktstop(&kts);
+	skb_queue_purge(&skbtxq);
 	dev_remove_pack(&aoe_pt);
 }
 
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index b0f553b..6526157 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -41,8 +41,9 @@
 #include <linux/spinlock.h>
 #include <linux/compat.h>
 #include <linux/mutex.h>
+#include <linux/bitmap.h>
+#include <linux/io.h>
 #include <asm/uaccess.h>
-#include <asm/io.h>
 
 #include <linux/dma-mapping.h>
 #include <linux/blkdev.h>
@@ -978,8 +979,7 @@ static CommandList_struct *cmd_alloc(ctlr_info_t *h)
 		i = find_first_zero_bit(h->cmd_pool_bits, h->nr_cmds);
 		if (i == h->nr_cmds)
 			return NULL;
-	} while (test_and_set_bit(i & (BITS_PER_LONG - 1),
-		  h->cmd_pool_bits + (i / BITS_PER_LONG)) != 0);
+	} while (test_and_set_bit(i, h->cmd_pool_bits) != 0);
 	c = h->cmd_pool + i;
 	memset(c, 0, sizeof(CommandList_struct));
 	cmd_dma_handle = h->cmd_pool_dhandle + i * sizeof(CommandList_struct);
@@ -1046,8 +1046,7 @@ static void cmd_free(ctlr_info_t *h, CommandList_struct *c)
 	int i;
 
 	i = c - h->cmd_pool;
-	clear_bit(i & (BITS_PER_LONG - 1),
-		  h->cmd_pool_bits + (i / BITS_PER_LONG));
+	clear_bit(i, h->cmd_pool_bits);
 	h->nr_frees++;
 }
 
@@ -4268,10 +4267,7 @@ static void __devinit cciss_find_board_params(ctlr_info_t *h)
 
 static inline bool CISS_signature_present(ctlr_info_t *h)
 {
-	if ((readb(&h->cfgtable->Signature[0]) != 'C') ||
-	    (readb(&h->cfgtable->Signature[1]) != 'I') ||
-	    (readb(&h->cfgtable->Signature[2]) != 'S') ||
-	    (readb(&h->cfgtable->Signature[3]) != 'S')) {
+	if (!check_signature(h->cfgtable->Signature, "CISS", 4)) {
 		dev_warn(&h->pdev->dev, "not a valid CISS config table\n");
 		return false;
 	}
@@ -4812,8 +4808,7 @@ static __devinit int cciss_init_reset_devices(struct pci_dev *pdev)
 
 static __devinit int cciss_allocate_cmd_pool(ctlr_info_t *h)
 {
-	h->cmd_pool_bits = kmalloc(
-		DIV_ROUND_UP(h->nr_cmds, BITS_PER_LONG) *
+	h->cmd_pool_bits = kmalloc(BITS_TO_LONGS(h->nr_cmds) *
 		sizeof(unsigned long), GFP_KERNEL);
 	h->cmd_pool = pci_alloc_consistent(h->pdev,
 		h->nr_cmds * sizeof(CommandList_struct),
@@ -5068,9 +5063,7 @@ reinit_after_soft_reset:
 	pci_set_drvdata(pdev, h);
 	/* command and error info recs zeroed out before
 	   they are used */
-	memset(h->cmd_pool_bits, 0,
-	       DIV_ROUND_UP(h->nr_cmds, BITS_PER_LONG)
-			* sizeof(unsigned long));
+	bitmap_zero(h->cmd_pool_bits, h->nr_cmds);
 
 	h->num_luns = 0;
 	h->highest_lun = -1;
@@ -5205,7 +5198,6 @@ static void cciss_shutdown(struct pci_dev *pdev)
 		return;
 	}
 	/* write all data in the battery backed cache to disk */
-	memset(flush_buf, 0, 4);
 	return_code = sendcmd_withirq(h, CCISS_CACHE_FLUSH, flush_buf,
 		4, 0, CTLR_LUNID, TYPE_CMD);
 	kfree(flush_buf);
diff --git a/drivers/block/drbd/drbd_bitmap.c b/drivers/block/drbd/drbd_bitmap.c
index d845664..628b31a 100644
--- a/drivers/block/drbd/drbd_bitmap.c
+++ b/drivers/block/drbd/drbd_bitmap.c
@@ -977,13 +977,8 @@ static void bm_page_io_async(struct bm_aio_ctx *ctx, int page_nr, int rw) __must
 	bm_set_page_unchanged(b->bm_pages[page_nr]);
 
 	if (ctx->flags & BM_AIO_COPY_PAGES) {
-		void *src, *dest;
 		page = mempool_alloc(drbd_md_io_page_pool, __GFP_HIGHMEM|__GFP_WAIT);
-		dest = kmap_atomic(page);
-		src = kmap_atomic(b->bm_pages[page_nr]);
-		memcpy(dest, src, PAGE_SIZE);
-		kunmap_atomic(src);
-		kunmap_atomic(dest);
+		copy_highpage(page, b->bm_pages[page_nr]);
 		bm_store_page_idx(page, page_nr);
 	} else
 		page = b->bm_pages[page_nr];
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c
index f93a032..f55683a 100644
--- a/drivers/block/drbd/drbd_main.c
+++ b/drivers/block/drbd/drbd_main.c
@@ -162,23 +162,12 @@ static const struct block_device_operations drbd_ops = {
 	.release = drbd_release,
 };
 
-static void bio_destructor_drbd(struct bio *bio)
-{
-	bio_free(bio, drbd_md_io_bio_set);
-}
-
 struct bio *bio_alloc_drbd(gfp_t gfp_mask)
 {
-	struct bio *bio;
-
 	if (!drbd_md_io_bio_set)
 		return bio_alloc(gfp_mask, 1);
 
-	bio = bio_alloc_bioset(gfp_mask, 1, drbd_md_io_bio_set);
-	if (!bio)
-		return NULL;
-	bio->bi_destructor = bio_destructor_drbd;
-	return bio;
+	return bio_alloc_bioset(gfp_mask, 1, drbd_md_io_bio_set);
 }
 
 #ifdef __CHECKER__
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index a7d6347..a6eebab1 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -672,7 +672,6 @@ static void __reschedule_timeout(int drive, const char *message)
 
 	if (drive == current_reqD)
 		drive = current_drive;
-	__cancel_delayed_work(&fd_timeout);
 
 	if (drive < 0 || drive >= N_DRIVE) {
 		delay = 20UL * HZ;
@@ -680,7 +679,7 @@ static void __reschedule_timeout(int drive, const char *message)
 	} else
 		delay = UDP->timeout;
 
-	queue_delayed_work(floppy_wq, &fd_timeout, delay);
+	mod_delayed_work(floppy_wq, &fd_timeout, delay);
 	if (UDP->flags & FD_DEBUG)
 		DPRINT("reschedule timeout %s\n", message);
 	timeout_message = message;
@@ -891,7 +890,7 @@ static void unlock_fdc(void)
 
 	raw_cmd = NULL;
 	command_status = FD_COMMAND_NONE;
-	__cancel_delayed_work(&fd_timeout);
+	cancel_delayed_work(&fd_timeout);
 	do_floppy = NULL;
 	cont = NULL;
 	clear_bit(0, &fdc_busy);
@@ -4110,12 +4109,19 @@ static struct platform_driver floppy_driver = {
 
 static struct platform_device floppy_device[N_DRIVE];
 
+static bool floppy_available(int drive)
+{
+	if (!(allowed_drive_mask & (1 << drive)))
+		return false;
+	if (fdc_state[FDC(drive)].version == FDC_NONE)
+		return false;
+	return true;
+}
+
 static struct kobject *floppy_find(dev_t dev, int *part, void *data)
 {
 	int drive = (*part & 3) | ((*part & 0x80) >> 5);
-	if (drive >= N_DRIVE ||
-	    !(allowed_drive_mask & (1 << drive)) ||
-	    fdc_state[FDC(drive)].version == FDC_NONE)
+	if (drive >= N_DRIVE || !floppy_available(drive))
 		return NULL;
 	if (((*part >> 2) & 0x1f) >= ARRAY_SIZE(floppy_type))
 		return NULL;
@@ -4125,8 +4131,7 @@ static struct kobject *floppy_find(dev_t dev, int *part, void *data)
 
 static int __init do_floppy_init(void)
 {
-	int i, unit, drive;
-	int err, dr;
+	int i, unit, drive, err;
 
 	set_debugt();
 	interruptjiffies = resultjiffies = jiffies;
@@ -4138,34 +4143,32 @@ static int __init do_floppy_init(void)
 
 	raw_cmd = NULL;
 
-	for (dr = 0; dr < N_DRIVE; dr++) {
-		disks[dr] = alloc_disk(1);
-		if (!disks[dr]) {
-			err = -ENOMEM;
-			goto out_put_disk;
-		}
+	floppy_wq = alloc_ordered_workqueue("floppy", 0);
+	if (!floppy_wq)
+		return -ENOMEM;
 
-		floppy_wq = alloc_ordered_workqueue("floppy", 0);
-		if (!floppy_wq) {
+	for (drive = 0; drive < N_DRIVE; drive++) {
+		disks[drive] = alloc_disk(1);
+		if (!disks[drive]) {
 			err = -ENOMEM;
 			goto out_put_disk;
 		}
 
-		disks[dr]->queue = blk_init_queue(do_fd_request, &floppy_lock);
-		if (!disks[dr]->queue) {
+		disks[drive]->queue = blk_init_queue(do_fd_request, &floppy_lock);
+		if (!disks[drive]->queue) {
 			err = -ENOMEM;
-			goto out_destroy_workq;
+			goto out_put_disk;
 		}
 
-		blk_queue_max_hw_sectors(disks[dr]->queue, 64);
-		disks[dr]->major = FLOPPY_MAJOR;
-		disks[dr]->first_minor = TOMINOR(dr);
-		disks[dr]->fops = &floppy_fops;
-		sprintf(disks[dr]->disk_name, "fd%d", dr);
+		blk_queue_max_hw_sectors(disks[drive]->queue, 64);
+		disks[drive]->major = FLOPPY_MAJOR;
+		disks[drive]->first_minor = TOMINOR(drive);
+		disks[drive]->fops = &floppy_fops;
+		sprintf(disks[drive]->disk_name, "fd%d", drive);
 
-		init_timer(&motor_off_timer[dr]);
-		motor_off_timer[dr].data = dr;
-		motor_off_timer[dr].function = motor_off_callback;
+		init_timer(&motor_off_timer[drive]);
+		motor_off_timer[drive].data = drive;
+		motor_off_timer[drive].function = motor_off_callback;
 	}
 
 	err = register_blkdev(FLOPPY_MAJOR, "fd");
@@ -4283,9 +4286,7 @@ static int __init do_floppy_init(void)
 	}
 
 	for (drive = 0; drive < N_DRIVE; drive++) {
-		if (!(allowed_drive_mask & (1 << drive)))
-			continue;
-		if (fdc_state[FDC(drive)].version == FDC_NONE)
+		if (!floppy_available(drive))
 			continue;
 
 		floppy_device[drive].name = floppy_device_name;
@@ -4294,7 +4295,7 @@ static int __init do_floppy_init(void)
 
 		err = platform_device_register(&floppy_device[drive]);
 		if (err)
-			goto out_release_dma;
+			goto out_remove_drives;
 
 		err = device_create_file(&floppy_device[drive].dev,
 					 &dev_attr_cmos);
@@ -4312,29 +4313,33 @@ static int __init do_floppy_init(void)
 
 out_unreg_platform_dev:
 	platform_device_unregister(&floppy_device[drive]);
+out_remove_drives:
+	while (drive--) {
+		if (floppy_available(drive)) {
+			del_gendisk(disks[drive]);
+			device_remove_file(&floppy_device[drive].dev, &dev_attr_cmos);
+			platform_device_unregister(&floppy_device[drive]);
+		}
+	}
 out_release_dma:
 	if (atomic_read(&usage_count))
 		floppy_release_irq_and_dma();
 out_unreg_region:
 	blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256);
 	platform_driver_unregister(&floppy_driver);
-out_destroy_workq:
-	destroy_workqueue(floppy_wq);
 out_unreg_blkdev:
 	unregister_blkdev(FLOPPY_MAJOR, "fd");
 out_put_disk:
-	while (dr--) {
-		del_timer_sync(&motor_off_timer[dr]);
-		if (disks[dr]->queue) {
-			blk_cleanup_queue(disks[dr]->queue);
-			/*
-			 * put_disk() is not paired with add_disk() and
-			 * will put queue reference one extra time. fix it.
-			 */
-			disks[dr]->queue = NULL;
+	for (drive = 0; drive < N_DRIVE; drive++) {
+		if (!disks[drive])
+			break;
+		if (disks[drive]->queue) {
+			del_timer_sync(&motor_off_timer[drive]);
+			blk_cleanup_queue(disks[drive]->queue);
 		}
-		put_disk(disks[dr]);
+		put_disk(disks[drive]);
 	}
+	destroy_workqueue(floppy_wq);
 	return err;
 }
 
@@ -4552,22 +4557,13 @@ static void __exit floppy_module_exit(void)
 	for (drive = 0; drive < N_DRIVE; drive++) {
 		del_timer_sync(&motor_off_timer[drive]);
 
-		if ((allowed_drive_mask & (1 << drive)) &&
-		    fdc_state[FDC(drive)].version != FDC_NONE) {
+		if (floppy_available(drive)) {
 			del_gendisk(disks[drive]);
 			device_remove_file(&floppy_device[drive].dev, &dev_attr_cmos);
 			platform_device_unregister(&floppy_device[drive]);
 		}
 		blk_cleanup_queue(disks[drive]->queue);
 
-		/*
-		 * These disks have not called add_disk().  Don't put down
-		 * queue reference in put_disk().
-		 */
-		if (!(allowed_drive_mask & (1 << drive)) ||
-		    fdc_state[FDC(drive)].version == FDC_NONE)
-			disks[drive]->queue = NULL;
-
 		put_disk(disks[drive]);
 	}
 
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 3bba655..e9d594f 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -1038,10 +1038,10 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
 {
 	int err;
 	struct loop_func_table *xfer;
-	uid_t uid = current_uid();
+	kuid_t uid = current_uid();
 
 	if (lo->lo_encrypt_key_size &&
-	    lo->lo_key_owner != uid &&
+	    !uid_eq(lo->lo_key_owner, uid) &&
 	    !capable(CAP_SYS_ADMIN))
 		return -EPERM;
 	if (lo->lo_state != Lo_bound)
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 0c03411..043ddcc 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -78,6 +78,8 @@ static const char *ioctl_cmd_to_ascii(int cmd)
 	case NBD_SET_SOCK: return "set-sock";
 	case NBD_SET_BLKSIZE: return "set-blksize";
 	case NBD_SET_SIZE: return "set-size";
+	case NBD_SET_TIMEOUT: return "set-timeout";
+	case NBD_SET_FLAGS: return "set-flags";
 	case NBD_DO_IT: return "do-it";
 	case NBD_CLEAR_SOCK: return "clear-sock";
 	case NBD_CLEAR_QUE: return "clear-que";
@@ -96,6 +98,7 @@ static const char *nbdcmd_to_ascii(int cmd)
 	case  NBD_CMD_READ: return "read";
 	case NBD_CMD_WRITE: return "write";
 	case  NBD_CMD_DISC: return "disconnect";
+	case  NBD_CMD_TRIM: return "trim/discard";
 	}
 	return "invalid";
 }
@@ -467,8 +470,12 @@ static void nbd_handle_req(struct nbd_device *nbd, struct request *req)
 
 	nbd_cmd(req) = NBD_CMD_READ;
 	if (rq_data_dir(req) == WRITE) {
-		nbd_cmd(req) = NBD_CMD_WRITE;
-		if (nbd->flags & NBD_READ_ONLY) {
+		if ((req->cmd_flags & REQ_DISCARD)) {
+			WARN_ON(!(nbd->flags & NBD_FLAG_SEND_TRIM));
+			nbd_cmd(req) = NBD_CMD_TRIM;
+		} else
+			nbd_cmd(req) = NBD_CMD_WRITE;
+		if (nbd->flags & NBD_FLAG_READ_ONLY) {
 			dev_err(disk_to_dev(nbd->disk),
 				"Write on read-only\n");
 			goto error_out;
@@ -651,6 +658,10 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
 		nbd->xmit_timeout = arg * HZ;
 		return 0;
 
+	case NBD_SET_FLAGS:
+		nbd->flags = arg;
+		return 0;
+
 	case NBD_SET_SIZE_BLOCKS:
 		nbd->bytesize = ((u64) arg) * nbd->blksize;
 		bdev->bd_inode->i_size = nbd->bytesize;
@@ -670,6 +681,10 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
 
 		mutex_unlock(&nbd->tx_lock);
 
+		if (nbd->flags & NBD_FLAG_SEND_TRIM)
+			queue_flag_set_unlocked(QUEUE_FLAG_DISCARD,
+				nbd->disk->queue);
+
 		thread = kthread_create(nbd_thread, nbd, nbd->disk->disk_name);
 		if (IS_ERR(thread)) {
 			mutex_lock(&nbd->tx_lock);
@@ -687,6 +702,7 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
 		nbd->file = NULL;
 		nbd_clear_que(nbd);
 		dev_warn(disk_to_dev(nbd->disk), "queue cleared\n");
+		queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, nbd->disk->queue);
 		if (file)
 			fput(file);
 		nbd->bytesize = 0;
@@ -805,6 +821,9 @@ static int __init nbd_init(void)
 		 * Tell the block layer that we are not a rotational device
 		 */
 		queue_flag_set_unlocked(QUEUE_FLAG_NONROT, disk->queue);
+		disk->queue->limits.discard_granularity = 512;
+		disk->queue->limits.max_discard_sectors = UINT_MAX;
+		disk->queue->limits.discard_zeroes_data = 0;
 	}
 
 	if (register_blkdev(NBD_MAJOR, "nbd")) {
diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c
index 38a2d06..c95ca0f 100644
--- a/drivers/block/nvme.c
+++ b/drivers/block/nvme.c
@@ -1675,7 +1675,7 @@ static void __devexit nvme_remove(struct pci_dev *pdev)
 #define nvme_suspend NULL
 #define nvme_resume NULL
 
-static struct pci_error_handlers nvme_err_handler = {
+static const struct pci_error_handlers nvme_err_handler = {
 	.error_detected	= nvme_error_detected,
 	.mmio_enabled	= nvme_dump_registers,
 	.link_reset	= nvme_link_reset,
diff --git a/drivers/block/osdblk.c b/drivers/block/osdblk.c
index 87311eb..1bbc681 100644
--- a/drivers/block/osdblk.c
+++ b/drivers/block/osdblk.c
@@ -266,11 +266,10 @@ static struct bio *bio_chain_clone(struct bio *old_chain, gfp_t gfpmask)
 	struct bio *tmp, *new_chain = NULL, *tail = NULL;
 
 	while (old_chain) {
-		tmp = bio_kmalloc(gfpmask, old_chain->bi_max_vecs);
+		tmp = bio_clone_kmalloc(old_chain, gfpmask);
 		if (!tmp)
 			goto err_out;
 
-		__bio_clone(tmp, old_chain);
 		tmp->bi_bdev = NULL;
 		gfpmask &= ~__GFP_WAIT;
 		tmp->bi_next = NULL;
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index ba66e44..2e7de7a 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -522,38 +522,6 @@ static void pkt_bio_finished(struct pktcdvd_device *pd)
 	}
 }
 
-static void pkt_bio_destructor(struct bio *bio)
-{
-	kfree(bio->bi_io_vec);
-	kfree(bio);
-}
-
-static struct bio *pkt_bio_alloc(int nr_iovecs)
-{
-	struct bio_vec *bvl = NULL;
-	struct bio *bio;
-
-	bio = kmalloc(sizeof(struct bio), GFP_KERNEL);
-	if (!bio)
-		goto no_bio;
-	bio_init(bio);
-
-	bvl = kcalloc(nr_iovecs, sizeof(struct bio_vec), GFP_KERNEL);
-	if (!bvl)
-		goto no_bvl;
-
-	bio->bi_max_vecs = nr_iovecs;
-	bio->bi_io_vec = bvl;
-	bio->bi_destructor = pkt_bio_destructor;
-
-	return bio;
-
- no_bvl:
-	kfree(bio);
- no_bio:
-	return NULL;
-}
-
 /*
  * Allocate a packet_data struct
  */
@@ -567,7 +535,7 @@ static struct packet_data *pkt_alloc_packet_data(int frames)
 		goto no_pkt;
 
 	pkt->frames = frames;
-	pkt->w_bio = pkt_bio_alloc(frames);
+	pkt->w_bio = bio_kmalloc(GFP_KERNEL, frames);
 	if (!pkt->w_bio)
 		goto no_bio;
 
@@ -581,9 +549,10 @@ static struct packet_data *pkt_alloc_packet_data(int frames)
 	bio_list_init(&pkt->orig_bios);
 
 	for (i = 0; i < frames; i++) {
-		struct bio *bio = pkt_bio_alloc(1);
+		struct bio *bio = bio_kmalloc(GFP_KERNEL, 1);
 		if (!bio)
 			goto no_rd_bio;
+
 		pkt->r_bios[i] = bio;
 	}
 
@@ -1111,21 +1080,17 @@ static void pkt_gather_data(struct pktcdvd_device *pd, struct packet_data *pkt)
 	 * Schedule reads for missing parts of the packet.
 	 */
 	for (f = 0; f < pkt->frames; f++) {
-		struct bio_vec *vec;
-
 		int p, offset;
+
 		if (written[f])
 			continue;
+
 		bio = pkt->r_bios[f];
-		vec = bio->bi_io_vec;
-		bio_init(bio);
-		bio->bi_max_vecs = 1;
+		bio_reset(bio);
 		bio->bi_sector = pkt->sector + f * (CD_FRAMESIZE >> 9);
 		bio->bi_bdev = pd->bdev;
 		bio->bi_end_io = pkt_end_io_read;
 		bio->bi_private = pkt;
-		bio->bi_io_vec = vec;
-		bio->bi_destructor = pkt_bio_destructor;
 
 		p = (f * CD_FRAMESIZE) / PAGE_SIZE;
 		offset = (f * CD_FRAMESIZE) % PAGE_SIZE;
@@ -1418,14 +1383,11 @@ static void pkt_start_write(struct pktcdvd_device *pd, struct packet_data *pkt)
 	}
 
 	/* Start the write request */
-	bio_init(pkt->w_bio);
-	pkt->w_bio->bi_max_vecs = PACKET_MAX_SIZE;
+	bio_reset(pkt->w_bio);
 	pkt->w_bio->bi_sector = pkt->sector;
 	pkt->w_bio->bi_bdev = pd->bdev;
 	pkt->w_bio->bi_end_io = pkt_end_io_packet_write;
 	pkt->w_bio->bi_private = pkt;
-	pkt->w_bio->bi_io_vec = bvec;
-	pkt->w_bio->bi_destructor = pkt_bio_destructor;
 	for (f = 0; f < pkt->frames; f++)
 		if (!bio_add_page(pkt->w_bio, bvec[f].bv_page, CD_FRAMESIZE, bvec[f].bv_offset))
 			BUG();
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index 9917943..54a55f0 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -246,13 +246,12 @@ static int rbd_open(struct block_device *bdev, fmode_t mode)
 {
 	struct rbd_device *rbd_dev = bdev->bd_disk->private_data;
 
-	rbd_get_dev(rbd_dev);
-
-	set_device_ro(bdev, rbd_dev->read_only);
-
 	if ((mode & FMODE_WRITE) && rbd_dev->read_only)
 		return -EROFS;
 
+	rbd_get_dev(rbd_dev);
+	set_device_ro(bdev, rbd_dev->read_only);
+
 	return 0;
 }
 
diff --git a/drivers/block/ub.c b/drivers/block/ub.c
deleted file mode 100644
index fcec022..0000000
--- a/drivers/block/ub.c
+++ /dev/null
@@ -1,2474 +0,0 @@
-/*
- * The low performance USB storage driver (ub).
- *
- * Copyright (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
- * Copyright (C) 2004 Pete Zaitcev (zaitcev@yahoo.com)
- *
- * This work is a part of Linux kernel, is derived from it,
- * and is not licensed separately. See file COPYING for details.
- *
- * TODO (sorted by decreasing priority)
- *  -- Return sense now that rq allows it (we always auto-sense anyway).
- *  -- set readonly flag for CDs, set removable flag for CF readers
- *  -- do inquiry and verify we got a disk and not a tape (for LUN mismatch)
- *  -- verify the 13 conditions and do bulk resets
- *  -- highmem
- *  -- move top_sense and work_bcs into separate allocations (if they survive)
- *     for cache purists and esoteric architectures.
- *  -- Allocate structure for LUN 0 before the first ub_sync_tur, avoid NULL. ?
- *  -- prune comments, they are too volumnous
- *  -- Resove XXX's
- *  -- CLEAR, CLR2STS, CLRRS seem to be ripe for refactoring.
- */
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/usb.h>
-#include <linux/usb_usual.h>
-#include <linux/blkdev.h>
-#include <linux/timer.h>
-#include <linux/scatterlist.h>
-#include <linux/slab.h>
-#include <linux/mutex.h>
-#include <scsi/scsi.h>
-
-#define DRV_NAME "ub"
-
-#define UB_MAJOR 180
-
-/*
- * The command state machine is the key model for understanding of this driver.
- *
- * The general rule is that all transitions are done towards the bottom
- * of the diagram, thus preventing any loops.
- *
- * An exception to that is how the STAT state is handled. A counter allows it
- * to be re-entered along the path marked with [C].
- *
- *       +--------+
- *       ! INIT   !
- *       +--------+
- *           !
- *        ub_scsi_cmd_start fails ->--------------------------------------\
- *           !                                                            !
- *           V                                                            !
- *       +--------+                                                       !
- *       ! CMD    !                                                       !
- *       +--------+                                                       !
- *           !                                            +--------+      !
- *         was -EPIPE -->-------------------------------->! CLEAR  !      !
- *           !                                            +--------+      !
- *           !                                                !           !
- *         was error -->------------------------------------- ! --------->\
- *           !                                                !           !
- *  /--<-- cmd->dir == NONE ?                                 !           !
- *  !        !                                                !           !
- *  !        V                                                !           !
- *  !    +--------+                                           !           !
- *  !    ! DATA   !                                           !           !
- *  !    +--------+                                           !           !
- *  !        !                           +---------+          !           !
- *  !      was -EPIPE -->--------------->! CLR2STS !          !           !
- *  !        !                           +---------+          !           !
- *  !        !                                !               !           !
- *  !        !                              was error -->---- ! --------->\
- *  !      was error -->--------------------- ! ------------- ! --------->\
- *  !        !                                !               !           !
- *  !        V                                !               !           !
- *  \--->+--------+                           !               !           !
- *       ! STAT   !<--------------------------/               !           !
- *  /--->+--------+                                           !           !
- *  !        !                                                !           !
- * [C]     was -EPIPE -->-----------\                         !           !
- *  !        !                      !                         !           !
- *  +<---- len == 0                 !                         !           !
- *  !        !                      !                         !           !
- *  !      was error -->--------------------------------------!---------->\
- *  !        !                      !                         !           !
- *  +<---- bad CSW                  !                         !           !
- *  +<---- bad tag                  !                         !           !
- *  !        !                      V                         !           !
- *  !        !                 +--------+                     !           !
- *  !        !                 ! CLRRS  !                     !           !
- *  !        !                 +--------+                     !           !
- *  !        !                      !                         !           !
- *  \------- ! --------------------[C]--------\               !           !
- *           !                                !               !           !
- *         cmd->error---\                +--------+           !           !
- *           !          +--------------->! SENSE  !<----------/           !
- *         STAT_FAIL----/                +--------+                       !
- *           !                                !                           V
- *           !                                V                      +--------+
- *           \--------------------------------\--------------------->! DONE   !
- *                                                                   +--------+
- */
-
-/*
- * This many LUNs per USB device.
- * Every one of them takes a host, see UB_MAX_HOSTS.
- */
-#define UB_MAX_LUNS   9
-
-/*
- */
-
-#define UB_PARTS_PER_LUN      8
-
-#define UB_MAX_CDB_SIZE      16		/* Corresponds to Bulk */
-
-#define UB_SENSE_SIZE  18
-
-/*
- */
-struct ub_dev;
-
-#define UB_MAX_REQ_SG	9	/* cdrecord requires 32KB and maybe a header */
-#define UB_MAX_SECTORS 64
-
-/*
- * A second is more than enough for a 32K transfer (UB_MAX_SECTORS)
- * even if a webcam hogs the bus, but some devices need time to spin up.
- */
-#define UB_URB_TIMEOUT	(HZ*2)
-#define UB_DATA_TIMEOUT	(HZ*5)	/* ZIP does spin-ups in the data phase */
-#define UB_STAT_TIMEOUT	(HZ*5)	/* Same spinups and eject for a dataless cmd. */
-#define UB_CTRL_TIMEOUT	(HZ/2)	/* 500ms ought to be enough to clear a stall */
-
-/*
- * An instance of a SCSI command in transit.
- */
-#define UB_DIR_NONE	0
-#define UB_DIR_READ	1
-#define UB_DIR_ILLEGAL2	2
-#define UB_DIR_WRITE	3
-
-#define UB_DIR_CHAR(c)  (((c)==UB_DIR_WRITE)? 'w': \
-			 (((c)==UB_DIR_READ)? 'r': 'n'))
-
-enum ub_scsi_cmd_state {
-	UB_CMDST_INIT,			/* Initial state */
-	UB_CMDST_CMD,			/* Command submitted */
-	UB_CMDST_DATA,			/* Data phase */
-	UB_CMDST_CLR2STS,		/* Clearing before requesting status */
-	UB_CMDST_STAT,			/* Status phase */
-	UB_CMDST_CLEAR,			/* Clearing a stall (halt, actually) */
-	UB_CMDST_CLRRS,			/* Clearing before retrying status */
-	UB_CMDST_SENSE,			/* Sending Request Sense */
-	UB_CMDST_DONE			/* Final state */
-};
-
-struct ub_scsi_cmd {
-	unsigned char cdb[UB_MAX_CDB_SIZE];
-	unsigned char cdb_len;
-
-	unsigned char dir;		/* 0 - none, 1 - read, 3 - write. */
-	enum ub_scsi_cmd_state state;
-	unsigned int tag;
-	struct ub_scsi_cmd *next;
-
-	int error;			/* Return code - valid upon done */
-	unsigned int act_len;		/* Return size */
-	unsigned char key, asc, ascq;	/* May be valid if error==-EIO */
-
-	int stat_count;			/* Retries getting status. */
-	unsigned int timeo;		/* jiffies until rq->timeout changes */
-
-	unsigned int len;		/* Requested length */
-	unsigned int current_sg;
-	unsigned int nsg;		/* sgv[nsg] */
-	struct scatterlist sgv[UB_MAX_REQ_SG];
-
-	struct ub_lun *lun;
-	void (*done)(struct ub_dev *, struct ub_scsi_cmd *);
-	void *back;
-};
-
-struct ub_request {
-	struct request *rq;
-	unsigned int current_try;
-	unsigned int nsg;		/* sgv[nsg] */
-	struct scatterlist sgv[UB_MAX_REQ_SG];
-};
-
-/*
- */
-struct ub_capacity {
-	unsigned long nsec;		/* Linux size - 512 byte sectors */
-	unsigned int bsize;		/* Linux hardsect_size */
-	unsigned int bshift;		/* Shift between 512 and hard sects */
-};
-
-/*
- * This is a direct take-off from linux/include/completion.h
- * The difference is that I do not wait on this thing, just poll.
- * When I want to wait (ub_probe), I just use the stock completion.
- *
- * Note that INIT_COMPLETION takes no lock. It is correct. But why
- * in the bloody hell that thing takes struct instead of pointer to struct
- * is quite beyond me. I just copied it from the stock completion.
- */
-struct ub_completion {
-	unsigned int done;
-	spinlock_t lock;
-};
-
-static DEFINE_MUTEX(ub_mutex);
-static inline void ub_init_completion(struct ub_completion *x)
-{
-	x->done = 0;
-	spin_lock_init(&x->lock);
-}
-
-#define UB_INIT_COMPLETION(x)	((x).done = 0)
-
-static void ub_complete(struct ub_completion *x)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&x->lock, flags);
-	x->done++;
-	spin_unlock_irqrestore(&x->lock, flags);
-}
-
-static int ub_is_completed(struct ub_completion *x)
-{
-	unsigned long flags;
-	int ret;
-
-	spin_lock_irqsave(&x->lock, flags);
-	ret = x->done;
-	spin_unlock_irqrestore(&x->lock, flags);
-	return ret;
-}
-
-/*
- */
-struct ub_scsi_cmd_queue {
-	int qlen, qmax;
-	struct ub_scsi_cmd *head, *tail;
-};
-
-/*
- * The block device instance (one per LUN).
- */
-struct ub_lun {
-	struct ub_dev *udev;
-	struct list_head link;
-	struct gendisk *disk;
-	int id;				/* Host index */
-	int num;			/* LUN number */
-	char name[16];
-
-	int changed;			/* Media was changed */
-	int removable;
-	int readonly;
-
-	struct ub_request urq;
-
-	/* Use Ingo's mempool if or when we have more than one command. */
-	/*
-	 * Currently we never need more than one command for the whole device.
-	 * However, giving every LUN a command is a cheap and automatic way
-	 * to enforce fairness between them.
-	 */
-	int cmda[1];
-	struct ub_scsi_cmd cmdv[1];
-
-	struct ub_capacity capacity; 
-};
-
-/*
- * The USB device instance.
- */
-struct ub_dev {
-	spinlock_t *lock;
-	atomic_t poison;		/* The USB device is disconnected */
-	int openc;			/* protected by ub_lock! */
-					/* kref is too implicit for our taste */
-	int reset;			/* Reset is running */
-	int bad_resid;
-	unsigned int tagcnt;
-	char name[12];
-	struct usb_device *dev;
-	struct usb_interface *intf;
-
-	struct list_head luns;
-
-	unsigned int send_bulk_pipe;	/* cached pipe values */
-	unsigned int recv_bulk_pipe;
-	unsigned int send_ctrl_pipe;
-	unsigned int recv_ctrl_pipe;
-
-	struct tasklet_struct tasklet;
-
-	struct ub_scsi_cmd_queue cmd_queue;
-	struct ub_scsi_cmd top_rqs_cmd;	/* REQUEST SENSE */
-	unsigned char top_sense[UB_SENSE_SIZE];
-
-	struct ub_completion work_done;
-	struct urb work_urb;
-	struct timer_list work_timer;
-	int last_pipe;			/* What might need clearing */
-	__le32 signature;		/* Learned signature */
-	struct bulk_cb_wrap work_bcb;
-	struct bulk_cs_wrap work_bcs;
-	struct usb_ctrlrequest work_cr;
-
-	struct work_struct reset_work;
-	wait_queue_head_t reset_wait;
-};
-
-/*
- */
-static void ub_cleanup(struct ub_dev *sc);
-static int ub_request_fn_1(struct ub_lun *lun, struct request *rq);
-static void ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun,
-    struct ub_scsi_cmd *cmd, struct ub_request *urq);
-static void ub_cmd_build_packet(struct ub_dev *sc, struct ub_lun *lun,
-    struct ub_scsi_cmd *cmd, struct ub_request *urq);
-static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
-static void ub_end_rq(struct request *rq, unsigned int status);
-static int ub_rw_cmd_retry(struct ub_dev *sc, struct ub_lun *lun,
-    struct ub_request *urq, struct ub_scsi_cmd *cmd);
-static int ub_submit_scsi(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
-static void ub_urb_complete(struct urb *urb);
-static void ub_scsi_action(unsigned long _dev);
-static void ub_scsi_dispatch(struct ub_dev *sc);
-static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
-static void ub_data_start(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
-static void ub_state_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd, int rc);
-static int __ub_state_stat(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
-static void ub_state_stat(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
-static void ub_state_stat_counted(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
-static void ub_state_sense(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
-static int ub_submit_clear_stall(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
-    int stalled_pipe);
-static void ub_top_sense_done(struct ub_dev *sc, struct ub_scsi_cmd *scmd);
-static void ub_reset_enter(struct ub_dev *sc, int try);
-static void ub_reset_task(struct work_struct *work);
-static int ub_sync_tur(struct ub_dev *sc, struct ub_lun *lun);
-static int ub_sync_read_cap(struct ub_dev *sc, struct ub_lun *lun,
-    struct ub_capacity *ret);
-static int ub_sync_reset(struct ub_dev *sc);
-static int ub_probe_clear_stall(struct ub_dev *sc, int stalled_pipe);
-static int ub_probe_lun(struct ub_dev *sc, int lnum);
-
-/*
- */
-#ifdef CONFIG_USB_LIBUSUAL
-
-#define ub_usb_ids  usb_storage_usb_ids
-#else
-
-static const struct usb_device_id ub_usb_ids[] = {
-	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, USB_SC_SCSI, USB_PR_BULK) },
-	{ }
-};
-
-MODULE_DEVICE_TABLE(usb, ub_usb_ids);
-#endif /* CONFIG_USB_LIBUSUAL */
-
-/*
- * Find me a way to identify "next free minor" for add_disk(),
- * and the array disappears the next day. However, the number of
- * hosts has something to do with the naming and /proc/partitions.
- * This has to be thought out in detail before changing.
- * If UB_MAX_HOST was 1000, we'd use a bitmap. Or a better data structure.
- */
-#define UB_MAX_HOSTS  26
-static char ub_hostv[UB_MAX_HOSTS];
-
-#define UB_QLOCK_NUM 5
-static spinlock_t ub_qlockv[UB_QLOCK_NUM];
-static int ub_qlock_next = 0;
-
-static DEFINE_SPINLOCK(ub_lock);	/* Locks globals and ->openc */
-
-/*
- * The id allocator.
- *
- * This also stores the host for indexing by minor, which is somewhat dirty.
- */
-static int ub_id_get(void)
-{
-	unsigned long flags;
-	int i;
-
-	spin_lock_irqsave(&ub_lock, flags);
-	for (i = 0; i < UB_MAX_HOSTS; i++) {
-		if (ub_hostv[i] == 0) {
-			ub_hostv[i] = 1;
-			spin_unlock_irqrestore(&ub_lock, flags);
-			return i;
-		}
-	}
-	spin_unlock_irqrestore(&ub_lock, flags);
-	return -1;
-}
-
-static void ub_id_put(int id)
-{
-	unsigned long flags;
-
-	if (id < 0 || id >= UB_MAX_HOSTS) {
-		printk(KERN_ERR DRV_NAME ": bad host ID %d\n", id);
-		return;
-	}
-
-	spin_lock_irqsave(&ub_lock, flags);
-	if (ub_hostv[id] == 0) {
-		spin_unlock_irqrestore(&ub_lock, flags);
-		printk(KERN_ERR DRV_NAME ": freeing free host ID %d\n", id);
-		return;
-	}
-	ub_hostv[id] = 0;
-	spin_unlock_irqrestore(&ub_lock, flags);
-}
-
-/*
- * This is necessitated by the fact that blk_cleanup_queue does not
- * necesserily destroy the queue. Instead, it may merely decrease q->refcnt.
- * Since our blk_init_queue() passes a spinlock common with ub_dev,
- * we have life time issues when ub_cleanup frees ub_dev.
- */
-static spinlock_t *ub_next_lock(void)
-{
-	unsigned long flags;
-	spinlock_t *ret;
-
-	spin_lock_irqsave(&ub_lock, flags);
-	ret = &ub_qlockv[ub_qlock_next];
-	ub_qlock_next = (ub_qlock_next + 1) % UB_QLOCK_NUM;
-	spin_unlock_irqrestore(&ub_lock, flags);
-	return ret;
-}
-
-/*
- * Downcount for deallocation. This rides on two assumptions:
- *  - once something is poisoned, its refcount cannot grow
- *  - opens cannot happen at this time (del_gendisk was done)
- * If the above is true, we can drop the lock, which we need for
- * blk_cleanup_queue(): the silly thing may attempt to sleep.
- * [Actually, it never needs to sleep for us, but it calls might_sleep()]
- */
-static void ub_put(struct ub_dev *sc)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&ub_lock, flags);
-	--sc->openc;
-	if (sc->openc == 0 && atomic_read(&sc->poison)) {
-		spin_unlock_irqrestore(&ub_lock, flags);
-		ub_cleanup(sc);
-	} else {
-		spin_unlock_irqrestore(&ub_lock, flags);
-	}
-}
-
-/*
- * Final cleanup and deallocation.
- */
-static void ub_cleanup(struct ub_dev *sc)
-{
-	struct list_head *p;
-	struct ub_lun *lun;
-	struct request_queue *q;
-
-	while (!list_empty(&sc->luns)) {
-		p = sc->luns.next;
-		lun = list_entry(p, struct ub_lun, link);
-		list_del(p);
-
-		/* I don't think queue can be NULL. But... Stolen from sx8.c */
-		if ((q = lun->disk->queue) != NULL)
-			blk_cleanup_queue(q);
-		/*
-		 * If we zero disk->private_data BEFORE put_disk, we have
-		 * to check for NULL all over the place in open, release,
-		 * check_media and revalidate, because the block level
-		 * semaphore is well inside the put_disk.
-		 * But we cannot zero after the call, because *disk is gone.
-		 * The sd.c is blatantly racy in this area.
-		 */
-		/* disk->private_data = NULL; */
-		put_disk(lun->disk);
-		lun->disk = NULL;
-
-		ub_id_put(lun->id);
-		kfree(lun);
-	}
-
-	usb_set_intfdata(sc->intf, NULL);
-	usb_put_intf(sc->intf);
-	usb_put_dev(sc->dev);
-	kfree(sc);
-}
-
-/*
- * The "command allocator".
- */
-static struct ub_scsi_cmd *ub_get_cmd(struct ub_lun *lun)
-{
-	struct ub_scsi_cmd *ret;
-
-	if (lun->cmda[0])
-		return NULL;
-	ret = &lun->cmdv[0];
-	lun->cmda[0] = 1;
-	return ret;
-}
-
-static void ub_put_cmd(struct ub_lun *lun, struct ub_scsi_cmd *cmd)
-{
-	if (cmd != &lun->cmdv[0]) {
-		printk(KERN_WARNING "%s: releasing a foreign cmd %p\n",
-		    lun->name, cmd);
-		return;
-	}
-	if (!lun->cmda[0]) {
-		printk(KERN_WARNING "%s: releasing a free cmd\n", lun->name);
-		return;
-	}
-	lun->cmda[0] = 0;
-}
-
-/*
- * The command queue.
- */
-static void ub_cmdq_add(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
-{
-	struct ub_scsi_cmd_queue *t = &sc->cmd_queue;
-
-	if (t->qlen++ == 0) {
-		t->head = cmd;
-		t->tail = cmd;
-	} else {
-		t->tail->next = cmd;
-		t->tail = cmd;
-	}
-
-	if (t->qlen > t->qmax)
-		t->qmax = t->qlen;
-}
-
-static void ub_cmdq_insert(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
-{
-	struct ub_scsi_cmd_queue *t = &sc->cmd_queue;
-
-	if (t->qlen++ == 0) {
-		t->head = cmd;
-		t->tail = cmd;
-	} else {
-		cmd->next = t->head;
-		t->head = cmd;
-	}
-
-	if (t->qlen > t->qmax)
-		t->qmax = t->qlen;
-}
-
-static struct ub_scsi_cmd *ub_cmdq_pop(struct ub_dev *sc)
-{
-	struct ub_scsi_cmd_queue *t = &sc->cmd_queue;
-	struct ub_scsi_cmd *cmd;
-
-	if (t->qlen == 0)
-		return NULL;
-	if (--t->qlen == 0)
-		t->tail = NULL;
-	cmd = t->head;
-	t->head = cmd->next;
-	cmd->next = NULL;
-	return cmd;
-}
-
-#define ub_cmdq_peek(sc)  ((sc)->cmd_queue.head)
-
-/*
- * The request function is our main entry point
- */
-
-static void ub_request_fn(struct request_queue *q)
-{
-	struct ub_lun *lun = q->queuedata;
-	struct request *rq;
-
-	while ((rq = blk_peek_request(q)) != NULL) {
-		if (ub_request_fn_1(lun, rq) != 0) {
-			blk_stop_queue(q);
-			break;
-		}
-	}
-}
-
-static int ub_request_fn_1(struct ub_lun *lun, struct request *rq)
-{
-	struct ub_dev *sc = lun->udev;
-	struct ub_scsi_cmd *cmd;
-	struct ub_request *urq;
-	int n_elem;
-
-	if (atomic_read(&sc->poison)) {
-		blk_start_request(rq);
-		ub_end_rq(rq, DID_NO_CONNECT << 16);
-		return 0;
-	}
-
-	if (lun->changed && rq->cmd_type != REQ_TYPE_BLOCK_PC) {
-		blk_start_request(rq);
-		ub_end_rq(rq, SAM_STAT_CHECK_CONDITION);
-		return 0;
-	}
-
-	if (lun->urq.rq != NULL)
-		return -1;
-	if ((cmd = ub_get_cmd(lun)) == NULL)
-		return -1;
-	memset(cmd, 0, sizeof(struct ub_scsi_cmd));
-
-	blk_start_request(rq);
-
-	urq = &lun->urq;
-	memset(urq, 0, sizeof(struct ub_request));
-	urq->rq = rq;
-
-	/*
-	 * get scatterlist from block layer
-	 */
-	sg_init_table(&urq->sgv[0], UB_MAX_REQ_SG);
-	n_elem = blk_rq_map_sg(lun->disk->queue, rq, &urq->sgv[0]);
-	if (n_elem < 0) {
-		/* Impossible, because blk_rq_map_sg should not hit ENOMEM. */
-		printk(KERN_INFO "%s: failed request map (%d)\n",
-		    lun->name, n_elem);
-		goto drop;
-	}
-	if (n_elem > UB_MAX_REQ_SG) {	/* Paranoia */
-		printk(KERN_WARNING "%s: request with %d segments\n",
-		    lun->name, n_elem);
-		goto drop;
-	}
-	urq->nsg = n_elem;
-
-	if (rq->cmd_type == REQ_TYPE_BLOCK_PC) {
-		ub_cmd_build_packet(sc, lun, cmd, urq);
-	} else {
-		ub_cmd_build_block(sc, lun, cmd, urq);
-	}
-	cmd->state = UB_CMDST_INIT;
-	cmd->lun = lun;
-	cmd->done = ub_rw_cmd_done;
-	cmd->back = urq;
-
-	cmd->tag = sc->tagcnt++;
-	if (ub_submit_scsi(sc, cmd) != 0)
-		goto drop;
-
-	return 0;
-
-drop:
-	ub_put_cmd(lun, cmd);
-	ub_end_rq(rq, DID_ERROR << 16);
-	return 0;
-}
-
-static void ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun,
-    struct ub_scsi_cmd *cmd, struct ub_request *urq)
-{
-	struct request *rq = urq->rq;
-	unsigned int block, nblks;
-
-	if (rq_data_dir(rq) == WRITE)
-		cmd->dir = UB_DIR_WRITE;
-	else
-		cmd->dir = UB_DIR_READ;
-
-	cmd->nsg = urq->nsg;
-	memcpy(cmd->sgv, urq->sgv, sizeof(struct scatterlist) * cmd->nsg);
-
-	/*
-	 * build the command
-	 *
-	 * The call to blk_queue_logical_block_size() guarantees that request
-	 * is aligned, but it is given in terms of 512 byte units, always.
-	 */
-	block = blk_rq_pos(rq) >> lun->capacity.bshift;
-	nblks = blk_rq_sectors(rq) >> lun->capacity.bshift;
-
-	cmd->cdb[0] = (cmd->dir == UB_DIR_READ)? READ_10: WRITE_10;
-	/* 10-byte uses 4 bytes of LBA: 2147483648KB, 2097152MB, 2048GB */
-	cmd->cdb[2] = block >> 24;
-	cmd->cdb[3] = block >> 16;
-	cmd->cdb[4] = block >> 8;
-	cmd->cdb[5] = block;
-	cmd->cdb[7] = nblks >> 8;
-	cmd->cdb[8] = nblks;
-	cmd->cdb_len = 10;
-
-	cmd->len = blk_rq_bytes(rq);
-}
-
-static void ub_cmd_build_packet(struct ub_dev *sc, struct ub_lun *lun,
-    struct ub_scsi_cmd *cmd, struct ub_request *urq)
-{
-	struct request *rq = urq->rq;
-
-	if (blk_rq_bytes(rq) == 0) {
-		cmd->dir = UB_DIR_NONE;
-	} else {
-		if (rq_data_dir(rq) == WRITE)
-			cmd->dir = UB_DIR_WRITE;
-		else
-			cmd->dir = UB_DIR_READ;
-	}
-
-	cmd->nsg = urq->nsg;
-	memcpy(cmd->sgv, urq->sgv, sizeof(struct scatterlist) * cmd->nsg);
-
-	memcpy(&cmd->cdb, rq->cmd, rq->cmd_len);
-	cmd->cdb_len = rq->cmd_len;
-
-	cmd->len = blk_rq_bytes(rq);
-
-	/*
-	 * To reapply this to every URB is not as incorrect as it looks.
-	 * In return, we avoid any complicated tracking calculations.
-	 */
-	cmd->timeo = rq->timeout;
-}
-
-static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
-{
-	struct ub_lun *lun = cmd->lun;
-	struct ub_request *urq = cmd->back;
-	struct request *rq;
-	unsigned int scsi_status;
-
-	rq = urq->rq;
-
-	if (cmd->error == 0) {
-		if (rq->cmd_type == REQ_TYPE_BLOCK_PC) {
-			if (cmd->act_len >= rq->resid_len)
-				rq->resid_len = 0;
-			else
-				rq->resid_len -= cmd->act_len;
-			scsi_status = 0;
-		} else {
-			if (cmd->act_len != cmd->len) {
-				scsi_status = SAM_STAT_CHECK_CONDITION;
-			} else {
-				scsi_status = 0;
-			}
-		}
-	} else {
-		if (rq->cmd_type == REQ_TYPE_BLOCK_PC) {
-			/* UB_SENSE_SIZE is smaller than SCSI_SENSE_BUFFERSIZE */
-			memcpy(rq->sense, sc->top_sense, UB_SENSE_SIZE);
-			rq->sense_len = UB_SENSE_SIZE;
-			if (sc->top_sense[0] != 0)
-				scsi_status = SAM_STAT_CHECK_CONDITION;
-			else
-				scsi_status = DID_ERROR << 16;
-		} else {
-			if (cmd->error == -EIO &&
-			    (cmd->key == 0 ||
-			     cmd->key == MEDIUM_ERROR ||
-			     cmd->key == UNIT_ATTENTION)) {
-				if (ub_rw_cmd_retry(sc, lun, urq, cmd) == 0)
-					return;
-			}
-			scsi_status = SAM_STAT_CHECK_CONDITION;
-		}
-	}
-
-	urq->rq = NULL;
-
-	ub_put_cmd(lun, cmd);
-	ub_end_rq(rq, scsi_status);
-	blk_start_queue(lun->disk->queue);
-}
-
-static void ub_end_rq(struct request *rq, unsigned int scsi_status)
-{
-	int error;
-
-	if (scsi_status == 0) {
-		error = 0;
-	} else {
-		error = -EIO;
-		rq->errors = scsi_status;
-	}
-	__blk_end_request_all(rq, error);
-}
-
-static int ub_rw_cmd_retry(struct ub_dev *sc, struct ub_lun *lun,
-    struct ub_request *urq, struct ub_scsi_cmd *cmd)
-{
-
-	if (atomic_read(&sc->poison))
-		return -ENXIO;
-
-	ub_reset_enter(sc, urq->current_try);
-
-	if (urq->current_try >= 3)
-		return -EIO;
-	urq->current_try++;
-
-	/* Remove this if anyone complains of flooding. */
-	printk(KERN_DEBUG "%s: dir %c len/act %d/%d "
-	    "[sense %x %02x %02x] retry %d\n",
-	    sc->name, UB_DIR_CHAR(cmd->dir), cmd->len, cmd->act_len,
-	    cmd->key, cmd->asc, cmd->ascq, urq->current_try);
-
-	memset(cmd, 0, sizeof(struct ub_scsi_cmd));
-	ub_cmd_build_block(sc, lun, cmd, urq);
-
-	cmd->state = UB_CMDST_INIT;
-	cmd->lun = lun;
-	cmd->done = ub_rw_cmd_done;
-	cmd->back = urq;
-
-	cmd->tag = sc->tagcnt++;
-
-#if 0 /* Wasteful */
-	return ub_submit_scsi(sc, cmd);
-#else
-	ub_cmdq_add(sc, cmd);
-	return 0;
-#endif
-}
-
-/*
- * Submit a regular SCSI operation (not an auto-sense).
- *
- * The Iron Law of Good Submit Routine is:
- * Zero return - callback is done, Nonzero return - callback is not done.
- * No exceptions.
- *
- * Host is assumed locked.
- */
-static int ub_submit_scsi(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
-{
-
-	if (cmd->state != UB_CMDST_INIT ||
-	    (cmd->dir != UB_DIR_NONE && cmd->len == 0)) {
-		return -EINVAL;
-	}
-
-	ub_cmdq_add(sc, cmd);
-	/*
-	 * We can call ub_scsi_dispatch(sc) right away here, but it's a little
-	 * safer to jump to a tasklet, in case upper layers do something silly.
-	 */
-	tasklet_schedule(&sc->tasklet);
-	return 0;
-}
-
-/*
- * Submit the first URB for the queued command.
- * This function does not deal with queueing in any way.
- */
-static int ub_scsi_cmd_start(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
-{
-	struct bulk_cb_wrap *bcb;
-	int rc;
-
-	bcb = &sc->work_bcb;
-
-	/*
-	 * ``If the allocation length is eighteen or greater, and a device
-	 * server returns less than eithteen bytes of data, the application
-	 * client should assume that the bytes not transferred would have been
-	 * zeroes had the device server returned those bytes.''
-	 *
-	 * We zero sense for all commands so that when a packet request
-	 * fails it does not return a stale sense.
-	 */
-	memset(&sc->top_sense, 0, UB_SENSE_SIZE);
-
-	/* set up the command wrapper */
-	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
-	bcb->Tag = cmd->tag;		/* Endianness is not important */
-	bcb->DataTransferLength = cpu_to_le32(cmd->len);
-	bcb->Flags = (cmd->dir == UB_DIR_READ) ? 0x80 : 0;
-	bcb->Lun = (cmd->lun != NULL) ? cmd->lun->num : 0;
-	bcb->Length = cmd->cdb_len;
-
-	/* copy the command payload */
-	memcpy(bcb->CDB, cmd->cdb, UB_MAX_CDB_SIZE);
-
-	UB_INIT_COMPLETION(sc->work_done);
-
-	sc->last_pipe = sc->send_bulk_pipe;
-	usb_fill_bulk_urb(&sc->work_urb, sc->dev, sc->send_bulk_pipe,
-	    bcb, US_BULK_CB_WRAP_LEN, ub_urb_complete, sc);
-
-	if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) {
-		/* XXX Clear stalls */
-		ub_complete(&sc->work_done);
-		return rc;
-	}
-
-	sc->work_timer.expires = jiffies + UB_URB_TIMEOUT;
-	add_timer(&sc->work_timer);
-
-	cmd->state = UB_CMDST_CMD;
-	return 0;
-}
-
-/*
- * Timeout handler.
- */
-static void ub_urb_timeout(unsigned long arg)
-{
-	struct ub_dev *sc = (struct ub_dev *) arg;
-	unsigned long flags;
-
-	spin_lock_irqsave(sc->lock, flags);
-	if (!ub_is_completed(&sc->work_done))
-		usb_unlink_urb(&sc->work_urb);
-	spin_unlock_irqrestore(sc->lock, flags);
-}
-
-/*
- * Completion routine for the work URB.
- *
- * This can be called directly from usb_submit_urb (while we have
- * the sc->lock taken) and from an interrupt (while we do NOT have
- * the sc->lock taken). Therefore, bounce this off to a tasklet.
- */
-static void ub_urb_complete(struct urb *urb)
-{
-	struct ub_dev *sc = urb->context;
-
-	ub_complete(&sc->work_done);
-	tasklet_schedule(&sc->tasklet);
-}
-
-static void ub_scsi_action(unsigned long _dev)
-{
-	struct ub_dev *sc = (struct ub_dev *) _dev;
-	unsigned long flags;
-
-	spin_lock_irqsave(sc->lock, flags);
-	ub_scsi_dispatch(sc);
-	spin_unlock_irqrestore(sc->lock, flags);
-}
-
-static void ub_scsi_dispatch(struct ub_dev *sc)
-{
-	struct ub_scsi_cmd *cmd;
-	int rc;
-
-	while (!sc->reset && (cmd = ub_cmdq_peek(sc)) != NULL) {
-		if (cmd->state == UB_CMDST_DONE) {
-			ub_cmdq_pop(sc);
-			(*cmd->done)(sc, cmd);
-		} else if (cmd->state == UB_CMDST_INIT) {
-			if ((rc = ub_scsi_cmd_start(sc, cmd)) == 0)
-				break;
-			cmd->error = rc;
-			cmd->state = UB_CMDST_DONE;
-		} else {
-			if (!ub_is_completed(&sc->work_done))
-				break;
-			del_timer(&sc->work_timer);
-			ub_scsi_urb_compl(sc, cmd);
-		}
-	}
-}
-
-static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
-{
-	struct urb *urb = &sc->work_urb;
-	struct bulk_cs_wrap *bcs;
-	int endp;
-	int len;
-	int rc;
-
-	if (atomic_read(&sc->poison)) {
-		ub_state_done(sc, cmd, -ENODEV);
-		return;
-	}
-
-	endp = usb_pipeendpoint(sc->last_pipe);
-	if (usb_pipein(sc->last_pipe))
-		endp |= USB_DIR_IN;
-
-	if (cmd->state == UB_CMDST_CLEAR) {
-		if (urb->status == -EPIPE) {
-			/*
-			 * STALL while clearning STALL.
-			 * The control pipe clears itself - nothing to do.
-			 */
-			printk(KERN_NOTICE "%s: stall on control pipe\n",
-			    sc->name);
-			goto Bad_End;
-		}
-
-		/*
-		 * We ignore the result for the halt clear.
-		 */
-
-		usb_reset_endpoint(sc->dev, endp);
-
-		ub_state_sense(sc, cmd);
-
-	} else if (cmd->state == UB_CMDST_CLR2STS) {
-		if (urb->status == -EPIPE) {
-			printk(KERN_NOTICE "%s: stall on control pipe\n",
-			    sc->name);
-			goto Bad_End;
-		}
-
-		/*
-		 * We ignore the result for the halt clear.
-		 */
-
-		usb_reset_endpoint(sc->dev, endp);
-
-		ub_state_stat(sc, cmd);
-
-	} else if (cmd->state == UB_CMDST_CLRRS) {
-		if (urb->status == -EPIPE) {
-			printk(KERN_NOTICE "%s: stall on control pipe\n",
-			    sc->name);
-			goto Bad_End;
-		}
-
-		/*
-		 * We ignore the result for the halt clear.
-		 */
-
-		usb_reset_endpoint(sc->dev, endp);
-
-		ub_state_stat_counted(sc, cmd);
-
-	} else if (cmd->state == UB_CMDST_CMD) {
-		switch (urb->status) {
-		case 0:
-			break;
-		case -EOVERFLOW:
-			goto Bad_End;
-		case -EPIPE:
-			rc = ub_submit_clear_stall(sc, cmd, sc->last_pipe);
-			if (rc != 0) {
-				printk(KERN_NOTICE "%s: "
-				    "unable to submit clear (%d)\n",
-				    sc->name, rc);
-				/*
-				 * This is typically ENOMEM or some other such shit.
-				 * Retrying is pointless. Just do Bad End on it...
-				 */
-				ub_state_done(sc, cmd, rc);
-				return;
-			}
-			cmd->state = UB_CMDST_CLEAR;
-			return;
-		case -ESHUTDOWN:	/* unplug */
-		case -EILSEQ:		/* unplug timeout on uhci */
-			ub_state_done(sc, cmd, -ENODEV);
-			return;
-		default:
-			goto Bad_End;
-		}
-		if (urb->actual_length != US_BULK_CB_WRAP_LEN) {
-			goto Bad_End;
-		}
-
-		if (cmd->dir == UB_DIR_NONE || cmd->nsg < 1) {
-			ub_state_stat(sc, cmd);
-			return;
-		}
-
-		// udelay(125);		// usb-storage has this
-		ub_data_start(sc, cmd);
-
-	} else if (cmd->state == UB_CMDST_DATA) {
-		if (urb->status == -EPIPE) {
-			rc = ub_submit_clear_stall(sc, cmd, sc->last_pipe);
-			if (rc != 0) {
-				printk(KERN_NOTICE "%s: "
-				    "unable to submit clear (%d)\n",
-				    sc->name, rc);
-				ub_state_done(sc, cmd, rc);
-				return;
-			}
-			cmd->state = UB_CMDST_CLR2STS;
-			return;
-		}
-		if (urb->status == -EOVERFLOW) {
-			/*
-			 * A babble? Failure, but we must transfer CSW now.
-			 */
-			cmd->error = -EOVERFLOW;	/* A cheap trick... */
-			ub_state_stat(sc, cmd);
-			return;
-		}
-
-		if (cmd->dir == UB_DIR_WRITE) {
-			/*
-			 * Do not continue writes in case of a failure.
-			 * Doing so would cause sectors to be mixed up,
-			 * which is worse than sectors lost.
-			 *
-			 * We must try to read the CSW, or many devices
-			 * get confused.
-			 */
-			len = urb->actual_length;
-			if (urb->status != 0 ||
-			    len != cmd->sgv[cmd->current_sg].length) {
-				cmd->act_len += len;
-
-				cmd->error = -EIO;
-				ub_state_stat(sc, cmd);
-				return;
-			}
-
-		} else {
-			/*
-			 * If an error occurs on read, we record it, and
-			 * continue to fetch data in order to avoid bubble.
-			 *
-			 * As a small shortcut, we stop if we detect that
-			 * a CSW mixed into data.
-			 */
-			if (urb->status != 0)
-				cmd->error = -EIO;
-
-			len = urb->actual_length;
-			if (urb->status != 0 ||
-			    len != cmd->sgv[cmd->current_sg].length) {
-				if ((len & 0x1FF) == US_BULK_CS_WRAP_LEN)
-					goto Bad_End;
-			}
-		}
-
-		cmd->act_len += urb->actual_length;
-
-		if (++cmd->current_sg < cmd->nsg) {
-			ub_data_start(sc, cmd);
-			return;
-		}
-		ub_state_stat(sc, cmd);
-
-	} else if (cmd->state == UB_CMDST_STAT) {
-		if (urb->status == -EPIPE) {
-			rc = ub_submit_clear_stall(sc, cmd, sc->last_pipe);
-			if (rc != 0) {
-				printk(KERN_NOTICE "%s: "
-				    "unable to submit clear (%d)\n",
-				    sc->name, rc);
-				ub_state_done(sc, cmd, rc);
-				return;
-			}
-
-			/*
-			 * Having a stall when getting CSW is an error, so
-			 * make sure uppper levels are not oblivious to it.
-			 */
-			cmd->error = -EIO;		/* A cheap trick... */
-
-			cmd->state = UB_CMDST_CLRRS;
-			return;
-		}
-
-		/* Catch everything, including -EOVERFLOW and other nasties. */
-		if (urb->status != 0)
-			goto Bad_End;
-
-		if (urb->actual_length == 0) {
-			ub_state_stat_counted(sc, cmd);
-			return;
-		}
-
-		/*
-		 * Check the returned Bulk protocol status.
-		 * The status block has to be validated first.
-		 */
-
-		bcs = &sc->work_bcs;
-
-		if (sc->signature == cpu_to_le32(0)) {
-			/*
-			 * This is the first reply, so do not perform the check.
-			 * Instead, remember the signature the device uses
-			 * for future checks. But do not allow a nul.
-			 */
-			sc->signature = bcs->Signature;
-			if (sc->signature == cpu_to_le32(0)) {
-				ub_state_stat_counted(sc, cmd);
-				return;
-			}
-		} else {
-			if (bcs->Signature != sc->signature) {
-				ub_state_stat_counted(sc, cmd);
-				return;
-			}
-		}
-
-		if (bcs->Tag != cmd->tag) {
-			/*
-			 * This usually happens when we disagree with the
-			 * device's microcode about something. For instance,
-			 * a few of them throw this after timeouts. They buffer
-			 * commands and reply at commands we timed out before.
-			 * Without flushing these replies we loop forever.
-			 */
-			ub_state_stat_counted(sc, cmd);
-			return;
-		}
-
-		if (!sc->bad_resid) {
-			len = le32_to_cpu(bcs->Residue);
-			if (len != cmd->len - cmd->act_len) {
-				/*
-				 * Only start ignoring if this cmd ended well.
-				 */
-				if (cmd->len == cmd->act_len) {
-					printk(KERN_NOTICE "%s: "
-					    "bad residual %d of %d, ignoring\n",
-					    sc->name, len, cmd->len);
-					sc->bad_resid = 1;
-				}
-			}
-		}
-
-		switch (bcs->Status) {
-		case US_BULK_STAT_OK:
-			break;
-		case US_BULK_STAT_FAIL:
-			ub_state_sense(sc, cmd);
-			return;
-		case US_BULK_STAT_PHASE:
-			goto Bad_End;
-		default:
-			printk(KERN_INFO "%s: unknown CSW status 0x%x\n",
-			    sc->name, bcs->Status);
-			ub_state_done(sc, cmd, -EINVAL);
-			return;
-		}
-
-		/* Not zeroing error to preserve a babble indicator */
-		if (cmd->error != 0) {
-			ub_state_sense(sc, cmd);
-			return;
-		}
-		cmd->state = UB_CMDST_DONE;
-		ub_cmdq_pop(sc);
-		(*cmd->done)(sc, cmd);
-
-	} else if (cmd->state == UB_CMDST_SENSE) {
-		ub_state_done(sc, cmd, -EIO);
-
-	} else {
-		printk(KERN_WARNING "%s: wrong command state %d\n",
-		    sc->name, cmd->state);
-		ub_state_done(sc, cmd, -EINVAL);
-		return;
-	}
-	return;
-
-Bad_End: /* Little Excel is dead */
-	ub_state_done(sc, cmd, -EIO);
-}
-
-/*
- * Factorization helper for the command state machine:
- * Initiate a data segment transfer.
- */
-static void ub_data_start(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
-{
-	struct scatterlist *sg = &cmd->sgv[cmd->current_sg];
-	int pipe;
-	int rc;
-
-	UB_INIT_COMPLETION(sc->work_done);
-
-	if (cmd->dir == UB_DIR_READ)
-		pipe = sc->recv_bulk_pipe;
-	else
-		pipe = sc->send_bulk_pipe;
-	sc->last_pipe = pipe;
-	usb_fill_bulk_urb(&sc->work_urb, sc->dev, pipe, sg_virt(sg),
-	    sg->length, ub_urb_complete, sc);
-
-	if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) {
-		/* XXX Clear stalls */
-		ub_complete(&sc->work_done);
-		ub_state_done(sc, cmd, rc);
-		return;
-	}
-
-	if (cmd->timeo)
-		sc->work_timer.expires = jiffies + cmd->timeo;
-	else
-		sc->work_timer.expires = jiffies + UB_DATA_TIMEOUT;
-	add_timer(&sc->work_timer);
-
-	cmd->state = UB_CMDST_DATA;
-}
-
-/*
- * Factorization helper for the command state machine:
- * Finish the command.
- */
-static void ub_state_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd, int rc)
-{
-
-	cmd->error = rc;
-	cmd->state = UB_CMDST_DONE;
-	ub_cmdq_pop(sc);
-	(*cmd->done)(sc, cmd);
-}
-
-/*
- * Factorization helper for the command state machine:
- * Submit a CSW read.
- */
-static int __ub_state_stat(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
-{
-	int rc;
-
-	UB_INIT_COMPLETION(sc->work_done);
-
-	sc->last_pipe = sc->recv_bulk_pipe;
-	usb_fill_bulk_urb(&sc->work_urb, sc->dev, sc->recv_bulk_pipe,
-	    &sc->work_bcs, US_BULK_CS_WRAP_LEN, ub_urb_complete, sc);
-
-	if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) {
-		/* XXX Clear stalls */
-		ub_complete(&sc->work_done);
-		ub_state_done(sc, cmd, rc);
-		return -1;
-	}
-
-	if (cmd->timeo)
-		sc->work_timer.expires = jiffies + cmd->timeo;
-	else
-		sc->work_timer.expires = jiffies + UB_STAT_TIMEOUT;
-	add_timer(&sc->work_timer);
-	return 0;
-}
-
-/*
- * Factorization helper for the command state machine:
- * Submit a CSW read and go to STAT state.
- */
-static void ub_state_stat(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
-{
-
-	if (__ub_state_stat(sc, cmd) != 0)
-		return;
-
-	cmd->stat_count = 0;
-	cmd->state = UB_CMDST_STAT;
-}
-
-/*
- * Factorization helper for the command state machine:
- * Submit a CSW read and go to STAT state with counter (along [C] path).
- */
-static void ub_state_stat_counted(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
-{
-
-	if (++cmd->stat_count >= 4) {
-		ub_state_sense(sc, cmd);
-		return;
-	}
-
-	if (__ub_state_stat(sc, cmd) != 0)
-		return;
-
-	cmd->state = UB_CMDST_STAT;
-}
-
-/*
- * Factorization helper for the command state machine:
- * Submit a REQUEST SENSE and go to SENSE state.
- */
-static void ub_state_sense(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
-{
-	struct ub_scsi_cmd *scmd;
-	struct scatterlist *sg;
-	int rc;
-
-	if (cmd->cdb[0] == REQUEST_SENSE) {
-		rc = -EPIPE;
-		goto error;
-	}
-
-	scmd = &sc->top_rqs_cmd;
-	memset(scmd, 0, sizeof(struct ub_scsi_cmd));
-	scmd->cdb[0] = REQUEST_SENSE;
-	scmd->cdb[4] = UB_SENSE_SIZE;
-	scmd->cdb_len = 6;
-	scmd->dir = UB_DIR_READ;
-	scmd->state = UB_CMDST_INIT;
-	scmd->nsg = 1;
-	sg = &scmd->sgv[0];
-	sg_init_table(sg, UB_MAX_REQ_SG);
-	sg_set_page(sg, virt_to_page(sc->top_sense), UB_SENSE_SIZE,
-			(unsigned long)sc->top_sense & (PAGE_SIZE-1));
-	scmd->len = UB_SENSE_SIZE;
-	scmd->lun = cmd->lun;
-	scmd->done = ub_top_sense_done;
-	scmd->back = cmd;
-
-	scmd->tag = sc->tagcnt++;
-
-	cmd->state = UB_CMDST_SENSE;
-
-	ub_cmdq_insert(sc, scmd);
-	return;
-
-error:
-	ub_state_done(sc, cmd, rc);
-}
-
-/*
- * A helper for the command's state machine:
- * Submit a stall clear.
- */
-static int ub_submit_clear_stall(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
-    int stalled_pipe)
-{
-	int endp;
-	struct usb_ctrlrequest *cr;
-	int rc;
-
-	endp = usb_pipeendpoint(stalled_pipe);
-	if (usb_pipein (stalled_pipe))
-		endp |= USB_DIR_IN;
-
-	cr = &sc->work_cr;
-	cr->bRequestType = USB_RECIP_ENDPOINT;
-	cr->bRequest = USB_REQ_CLEAR_FEATURE;
-	cr->wValue = cpu_to_le16(USB_ENDPOINT_HALT);
-	cr->wIndex = cpu_to_le16(endp);
-	cr->wLength = cpu_to_le16(0);
-
-	UB_INIT_COMPLETION(sc->work_done);
-
-	usb_fill_control_urb(&sc->work_urb, sc->dev, sc->send_ctrl_pipe,
-	    (unsigned char*) cr, NULL, 0, ub_urb_complete, sc);
-
-	if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) {
-		ub_complete(&sc->work_done);
-		return rc;
-	}
-
-	sc->work_timer.expires = jiffies + UB_CTRL_TIMEOUT;
-	add_timer(&sc->work_timer);
-	return 0;
-}
-
-/*
- */
-static void ub_top_sense_done(struct ub_dev *sc, struct ub_scsi_cmd *scmd)
-{
-	unsigned char *sense = sc->top_sense;
-	struct ub_scsi_cmd *cmd;
-
-	/*
-	 * Find the command which triggered the unit attention or a check,
-	 * save the sense into it, and advance its state machine.
-	 */
-	if ((cmd = ub_cmdq_peek(sc)) == NULL) {
-		printk(KERN_WARNING "%s: sense done while idle\n", sc->name);
-		return;
-	}
-	if (cmd != scmd->back) {
-		printk(KERN_WARNING "%s: "
-		    "sense done for wrong command 0x%x\n",
-		    sc->name, cmd->tag);
-		return;
-	}
-	if (cmd->state != UB_CMDST_SENSE) {
-		printk(KERN_WARNING "%s: sense done with bad cmd state %d\n",
-		    sc->name, cmd->state);
-		return;
-	}
-
-	/*
-	 * Ignoring scmd->act_len, because the buffer was pre-zeroed.
-	 */
-	cmd->key = sense[2] & 0x0F;
-	cmd->asc = sense[12];
-	cmd->ascq = sense[13];
-
-	ub_scsi_urb_compl(sc, cmd);
-}
-
-/*
- * Reset management
- */
-
-static void ub_reset_enter(struct ub_dev *sc, int try)
-{
-
-	if (sc->reset) {
-		/* This happens often on multi-LUN devices. */
-		return;
-	}
-	sc->reset = try + 1;
-
-#if 0 /* Not needed because the disconnect waits for us. */
-	unsigned long flags;
-	spin_lock_irqsave(&ub_lock, flags);
-	sc->openc++;
-	spin_unlock_irqrestore(&ub_lock, flags);
-#endif
-
-#if 0 /* We let them stop themselves. */
-	struct ub_lun *lun;
-	list_for_each_entry(lun, &sc->luns, link) {
-		blk_stop_queue(lun->disk->queue);
-	}
-#endif
-
-	schedule_work(&sc->reset_work);
-}
-
-static void ub_reset_task(struct work_struct *work)
-{
-	struct ub_dev *sc = container_of(work, struct ub_dev, reset_work);
-	unsigned long flags;
-	struct ub_lun *lun;
-	int rc;
-
-	if (!sc->reset) {
-		printk(KERN_WARNING "%s: Running reset unrequested\n",
-		    sc->name);
-		return;
-	}
-
-	if (atomic_read(&sc->poison)) {
-		;
-	} else if ((sc->reset & 1) == 0) {
-		ub_sync_reset(sc);
-		msleep(700);	/* usb-storage sleeps 6s (!) */
-		ub_probe_clear_stall(sc, sc->recv_bulk_pipe);
-		ub_probe_clear_stall(sc, sc->send_bulk_pipe);
-	} else if (sc->dev->actconfig->desc.bNumInterfaces != 1) {
-		;
-	} else {
-		rc = usb_lock_device_for_reset(sc->dev, sc->intf);
-		if (rc < 0) {
-			printk(KERN_NOTICE
-			    "%s: usb_lock_device_for_reset failed (%d)\n",
-			    sc->name, rc);
-		} else {
-			rc = usb_reset_device(sc->dev);
-			if (rc < 0) {
-				printk(KERN_NOTICE "%s: "
-				    "usb_lock_device_for_reset failed (%d)\n",
-				    sc->name, rc);
-			}
-			usb_unlock_device(sc->dev);
-		}
-	}
-
-	/*
-	 * In theory, no commands can be running while reset is active,
-	 * so nobody can ask for another reset, and so we do not need any
-	 * queues of resets or anything. We do need a spinlock though,
-	 * to interact with block layer.
-	 */
-	spin_lock_irqsave(sc->lock, flags);
-	sc->reset = 0;
-	tasklet_schedule(&sc->tasklet);
-	list_for_each_entry(lun, &sc->luns, link) {
-		blk_start_queue(lun->disk->queue);
-	}
-	wake_up(&sc->reset_wait);
-	spin_unlock_irqrestore(sc->lock, flags);
-}
-
-/*
- * XXX Reset brackets are too much hassle to implement, so just stub them
- * in order to prevent forced unbinding (which deadlocks solid when our
- * ->disconnect method waits for the reset to complete and this kills keventd).
- *
- * XXX Tell Alan to move usb_unlock_device inside of usb_reset_device,
- * or else the post_reset is invoked, and restats I/O on a locked device.
- */
-static int ub_pre_reset(struct usb_interface *iface) {
-	return 0;
-}
-
-static int ub_post_reset(struct usb_interface *iface) {
-	return 0;
-}
-
-/*
- * This is called from a process context.
- */
-static void ub_revalidate(struct ub_dev *sc, struct ub_lun *lun)
-{
-
-	lun->readonly = 0;	/* XXX Query this from the device */
-
-	lun->capacity.nsec = 0;
-	lun->capacity.bsize = 512;
-	lun->capacity.bshift = 0;
-
-	if (ub_sync_tur(sc, lun) != 0)
-		return;			/* Not ready */
-	lun->changed = 0;
-
-	if (ub_sync_read_cap(sc, lun, &lun->capacity) != 0) {
-		/*
-		 * The retry here means something is wrong, either with the
-		 * device, with the transport, or with our code.
-		 * We keep this because sd.c has retries for capacity.
-		 */
-		if (ub_sync_read_cap(sc, lun, &lun->capacity) != 0) {
-			lun->capacity.nsec = 0;
-			lun->capacity.bsize = 512;
-			lun->capacity.bshift = 0;
-		}
-	}
-}
-
-/*
- * The open funcion.
- * This is mostly needed to keep refcounting, but also to support
- * media checks on removable media drives.
- */
-static int ub_bd_open(struct block_device *bdev, fmode_t mode)
-{
-	struct ub_lun *lun = bdev->bd_disk->private_data;
-	struct ub_dev *sc = lun->udev;
-	unsigned long flags;
-	int rc;
-
-	spin_lock_irqsave(&ub_lock, flags);
-	if (atomic_read(&sc->poison)) {
-		spin_unlock_irqrestore(&ub_lock, flags);
-		return -ENXIO;
-	}
-	sc->openc++;
-	spin_unlock_irqrestore(&ub_lock, flags);
-
-	if (lun->removable || lun->readonly)
-		check_disk_change(bdev);
-
-	/*
-	 * The sd.c considers ->media_present and ->changed not equivalent,
-	 * under some pretty murky conditions (a failure of READ CAPACITY).
-	 * We may need it one day.
-	 */
-	if (lun->removable && lun->changed && !(mode & FMODE_NDELAY)) {
-		rc = -ENOMEDIUM;
-		goto err_open;
-	}
-
-	if (lun->readonly && (mode & FMODE_WRITE)) {
-		rc = -EROFS;
-		goto err_open;
-	}
-
-	return 0;
-
-err_open:
-	ub_put(sc);
-	return rc;
-}
-
-static int ub_bd_unlocked_open(struct block_device *bdev, fmode_t mode)
-{
-	int ret;
-
-	mutex_lock(&ub_mutex);
-	ret = ub_bd_open(bdev, mode);
-	mutex_unlock(&ub_mutex);
-
-	return ret;
-}
-
-
-/*
- */
-static int ub_bd_release(struct gendisk *disk, fmode_t mode)
-{
-	struct ub_lun *lun = disk->private_data;
-	struct ub_dev *sc = lun->udev;
-
-	mutex_lock(&ub_mutex);
-	ub_put(sc);
-	mutex_unlock(&ub_mutex);
-
-	return 0;
-}
-
-/*
- * The ioctl interface.
- */
-static int ub_bd_ioctl(struct block_device *bdev, fmode_t mode,
-    unsigned int cmd, unsigned long arg)
-{
-	void __user *usermem = (void __user *) arg;
-	int ret;
-
-	mutex_lock(&ub_mutex);
-	ret = scsi_cmd_blk_ioctl(bdev, mode, cmd, usermem);
-	mutex_unlock(&ub_mutex);
-
-	return ret;
-}
-
-/*
- * This is called by check_disk_change if we reported a media change.
- * The main onjective here is to discover the features of the media such as
- * the capacity, read-only status, etc. USB storage generally does not
- * need to be spun up, but if we needed it, this would be the place.
- *
- * This call can sleep.
- *
- * The return code is not used.
- */
-static int ub_bd_revalidate(struct gendisk *disk)
-{
-	struct ub_lun *lun = disk->private_data;
-
-	ub_revalidate(lun->udev, lun);
-
-	/* XXX Support sector size switching like in sr.c */
-	blk_queue_logical_block_size(disk->queue, lun->capacity.bsize);
-	set_capacity(disk, lun->capacity.nsec);
-	// set_disk_ro(sdkp->disk, lun->readonly);
-
-	return 0;
-}
-
-/*
- * The check is called by the block layer to verify if the media
- * is still available. It is supposed to be harmless, lightweight and
- * non-intrusive in case the media was not changed.
- *
- * This call can sleep.
- *
- * The return code is bool!
- */
-static unsigned int ub_bd_check_events(struct gendisk *disk,
-				       unsigned int clearing)
-{
-	struct ub_lun *lun = disk->private_data;
-
-	if (!lun->removable)
-		return 0;
-
-	/*
-	 * We clean checks always after every command, so this is not
-	 * as dangerous as it looks. If the TEST_UNIT_READY fails here,
-	 * the device is actually not ready with operator or software
-	 * intervention required. One dangerous item might be a drive which
-	 * spins itself down, and come the time to write dirty pages, this
-	 * will fail, then block layer discards the data. Since we never
-	 * spin drives up, such devices simply cannot be used with ub anyway.
-	 */
-	if (ub_sync_tur(lun->udev, lun) != 0) {
-		lun->changed = 1;
-		return DISK_EVENT_MEDIA_CHANGE;
-	}
-
-	return lun->changed ? DISK_EVENT_MEDIA_CHANGE : 0;
-}
-
-static const struct block_device_operations ub_bd_fops = {
-	.owner		= THIS_MODULE,
-	.open		= ub_bd_unlocked_open,
-	.release	= ub_bd_release,
-	.ioctl		= ub_bd_ioctl,
-	.check_events	= ub_bd_check_events,
-	.revalidate_disk = ub_bd_revalidate,
-};
-
-/*
- * Common ->done routine for commands executed synchronously.
- */
-static void ub_probe_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
-{
-	struct completion *cop = cmd->back;
-	complete(cop);
-}
-
-/*
- * Test if the device has a check condition on it, synchronously.
- */
-static int ub_sync_tur(struct ub_dev *sc, struct ub_lun *lun)
-{
-	struct ub_scsi_cmd *cmd;
-	enum { ALLOC_SIZE = sizeof(struct ub_scsi_cmd) };
-	unsigned long flags;
-	struct completion compl;
-	int rc;
-
-	init_completion(&compl);
-
-	rc = -ENOMEM;
-	if ((cmd = kzalloc(ALLOC_SIZE, GFP_KERNEL)) == NULL)
-		goto err_alloc;
-
-	cmd->cdb[0] = TEST_UNIT_READY;
-	cmd->cdb_len = 6;
-	cmd->dir = UB_DIR_NONE;
-	cmd->state = UB_CMDST_INIT;
-	cmd->lun = lun;			/* This may be NULL, but that's ok */
-	cmd->done = ub_probe_done;
-	cmd->back = &compl;
-
-	spin_lock_irqsave(sc->lock, flags);
-	cmd->tag = sc->tagcnt++;
-
-	rc = ub_submit_scsi(sc, cmd);
-	spin_unlock_irqrestore(sc->lock, flags);
-
-	if (rc != 0)
-		goto err_submit;
-
-	wait_for_completion(&compl);
-
-	rc = cmd->error;
-
-	if (rc == -EIO && cmd->key != 0)	/* Retries for benh's key */
-		rc = cmd->key;
-
-err_submit:
-	kfree(cmd);
-err_alloc:
-	return rc;
-}
-
-/*
- * Read the SCSI capacity synchronously (for probing).
- */
-static int ub_sync_read_cap(struct ub_dev *sc, struct ub_lun *lun,
-    struct ub_capacity *ret)
-{
-	struct ub_scsi_cmd *cmd;
-	struct scatterlist *sg;
-	char *p;
-	enum { ALLOC_SIZE = sizeof(struct ub_scsi_cmd) + 8 };
-	unsigned long flags;
-	unsigned int bsize, shift;
-	unsigned long nsec;
-	struct completion compl;
-	int rc;
-
-	init_completion(&compl);
-
-	rc = -ENOMEM;
-	if ((cmd = kzalloc(ALLOC_SIZE, GFP_KERNEL)) == NULL)
-		goto err_alloc;
-	p = (char *)cmd + sizeof(struct ub_scsi_cmd);
-
-	cmd->cdb[0] = 0x25;
-	cmd->cdb_len = 10;
-	cmd->dir = UB_DIR_READ;
-	cmd->state = UB_CMDST_INIT;
-	cmd->nsg = 1;
-	sg = &cmd->sgv[0];
-	sg_init_table(sg, UB_MAX_REQ_SG);
-	sg_set_page(sg, virt_to_page(p), 8, (unsigned long)p & (PAGE_SIZE-1));
-	cmd->len = 8;
-	cmd->lun = lun;
-	cmd->done = ub_probe_done;
-	cmd->back = &compl;
-
-	spin_lock_irqsave(sc->lock, flags);
-	cmd->tag = sc->tagcnt++;
-
-	rc = ub_submit_scsi(sc, cmd);
-	spin_unlock_irqrestore(sc->lock, flags);
-
-	if (rc != 0)
-		goto err_submit;
-
-	wait_for_completion(&compl);
-
-	if (cmd->error != 0) {
-		rc = -EIO;
-		goto err_read;
-	}
-	if (cmd->act_len != 8) {
-		rc = -EIO;
-		goto err_read;
-	}
-
-	/* sd.c special-cases sector size of 0 to mean 512. Needed? Safe? */
-	nsec = be32_to_cpu(*(__be32 *)p) + 1;
-	bsize = be32_to_cpu(*(__be32 *)(p + 4));
-	switch (bsize) {
-	case 512:	shift = 0;	break;
-	case 1024:	shift = 1;	break;
-	case 2048:	shift = 2;	break;
-	case 4096:	shift = 3;	break;
-	default:
-		rc = -EDOM;
-		goto err_inv_bsize;
-	}
-
-	ret->bsize = bsize;
-	ret->bshift = shift;
-	ret->nsec = nsec << shift;
-	rc = 0;
-
-err_inv_bsize:
-err_read:
-err_submit:
-	kfree(cmd);
-err_alloc:
-	return rc;
-}
-
-/*
- */
-static void ub_probe_urb_complete(struct urb *urb)
-{
-	struct completion *cop = urb->context;
-	complete(cop);
-}
-
-static void ub_probe_timeout(unsigned long arg)
-{
-	struct completion *cop = (struct completion *) arg;
-	complete(cop);
-}
-
-/*
- * Reset with a Bulk reset.
- */
-static int ub_sync_reset(struct ub_dev *sc)
-{
-	int ifnum = sc->intf->cur_altsetting->desc.bInterfaceNumber;
-	struct usb_ctrlrequest *cr;
-	struct completion compl;
-	struct timer_list timer;
-	int rc;
-
-	init_completion(&compl);
-
-	cr = &sc->work_cr;
-	cr->bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE;
-	cr->bRequest = US_BULK_RESET_REQUEST;
-	cr->wValue = cpu_to_le16(0);
-	cr->wIndex = cpu_to_le16(ifnum);
-	cr->wLength = cpu_to_le16(0);
-
-	usb_fill_control_urb(&sc->work_urb, sc->dev, sc->send_ctrl_pipe,
-	    (unsigned char*) cr, NULL, 0, ub_probe_urb_complete, &compl);
-
-	if ((rc = usb_submit_urb(&sc->work_urb, GFP_KERNEL)) != 0) {
-		printk(KERN_WARNING
-		     "%s: Unable to submit a bulk reset (%d)\n", sc->name, rc);
-		return rc;
-	}
-
-	init_timer(&timer);
-	timer.function = ub_probe_timeout;
-	timer.data = (unsigned long) &compl;
-	timer.expires = jiffies + UB_CTRL_TIMEOUT;
-	add_timer(&timer);
-
-	wait_for_completion(&compl);
-
-	del_timer_sync(&timer);
-	usb_kill_urb(&sc->work_urb);
-
-	return sc->work_urb.status;
-}
-
-/*
- * Get number of LUNs by the way of Bulk GetMaxLUN command.
- */
-static int ub_sync_getmaxlun(struct ub_dev *sc)
-{
-	int ifnum = sc->intf->cur_altsetting->desc.bInterfaceNumber;
-	unsigned char *p;
-	enum { ALLOC_SIZE = 1 };
-	struct usb_ctrlrequest *cr;
-	struct completion compl;
-	struct timer_list timer;
-	int nluns;
-	int rc;
-
-	init_completion(&compl);
-
-	rc = -ENOMEM;
-	if ((p = kmalloc(ALLOC_SIZE, GFP_KERNEL)) == NULL)
-		goto err_alloc;
-	*p = 55;
-
-	cr = &sc->work_cr;
-	cr->bRequestType = USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
-	cr->bRequest = US_BULK_GET_MAX_LUN;
-	cr->wValue = cpu_to_le16(0);
-	cr->wIndex = cpu_to_le16(ifnum);
-	cr->wLength = cpu_to_le16(1);
-
-	usb_fill_control_urb(&sc->work_urb, sc->dev, sc->recv_ctrl_pipe,
-	    (unsigned char*) cr, p, 1, ub_probe_urb_complete, &compl);
-
-	if ((rc = usb_submit_urb(&sc->work_urb, GFP_KERNEL)) != 0)
-		goto err_submit;
-
-	init_timer(&timer);
-	timer.function = ub_probe_timeout;
-	timer.data = (unsigned long) &compl;
-	timer.expires = jiffies + UB_CTRL_TIMEOUT;
-	add_timer(&timer);
-
-	wait_for_completion(&compl);
-
-	del_timer_sync(&timer);
-	usb_kill_urb(&sc->work_urb);
-
-	if ((rc = sc->work_urb.status) < 0)
-		goto err_io;
-
-	if (sc->work_urb.actual_length != 1) {
-		nluns = 0;
-	} else {
-		if ((nluns = *p) == 55) {
-			nluns = 0;
-		} else {
-  			/* GetMaxLUN returns the maximum LUN number */
-			nluns += 1;
-			if (nluns > UB_MAX_LUNS)
-				nluns = UB_MAX_LUNS;
-		}
-	}
-
-	kfree(p);
-	return nluns;
-
-err_io:
-err_submit:
-	kfree(p);
-err_alloc:
-	return rc;
-}
-
-/*
- * Clear initial stalls.
- */
-static int ub_probe_clear_stall(struct ub_dev *sc, int stalled_pipe)
-{
-	int endp;
-	struct usb_ctrlrequest *cr;
-	struct completion compl;
-	struct timer_list timer;
-	int rc;
-
-	init_completion(&compl);
-
-	endp = usb_pipeendpoint(stalled_pipe);
-	if (usb_pipein (stalled_pipe))
-		endp |= USB_DIR_IN;
-
-	cr = &sc->work_cr;
-	cr->bRequestType = USB_RECIP_ENDPOINT;
-	cr->bRequest = USB_REQ_CLEAR_FEATURE;
-	cr->wValue = cpu_to_le16(USB_ENDPOINT_HALT);
-	cr->wIndex = cpu_to_le16(endp);
-	cr->wLength = cpu_to_le16(0);
-
-	usb_fill_control_urb(&sc->work_urb, sc->dev, sc->send_ctrl_pipe,
-	    (unsigned char*) cr, NULL, 0, ub_probe_urb_complete, &compl);
-
-	if ((rc = usb_submit_urb(&sc->work_urb, GFP_KERNEL)) != 0) {
-		printk(KERN_WARNING
-		     "%s: Unable to submit a probe clear (%d)\n", sc->name, rc);
-		return rc;
-	}
-
-	init_timer(&timer);
-	timer.function = ub_probe_timeout;
-	timer.data = (unsigned long) &compl;
-	timer.expires = jiffies + UB_CTRL_TIMEOUT;
-	add_timer(&timer);
-
-	wait_for_completion(&compl);
-
-	del_timer_sync(&timer);
-	usb_kill_urb(&sc->work_urb);
-
-	usb_reset_endpoint(sc->dev, endp);
-
-	return 0;
-}
-
-/*
- * Get the pipe settings.
- */
-static int ub_get_pipes(struct ub_dev *sc, struct usb_device *dev,
-    struct usb_interface *intf)
-{
-	struct usb_host_interface *altsetting = intf->cur_altsetting;
-	struct usb_endpoint_descriptor *ep_in = NULL;
-	struct usb_endpoint_descriptor *ep_out = NULL;
-	struct usb_endpoint_descriptor *ep;
-	int i;
-
-	/*
-	 * Find the endpoints we need.
-	 * We are expecting a minimum of 2 endpoints - in and out (bulk).
-	 * We will ignore any others.
-	 */
-	for (i = 0; i < altsetting->desc.bNumEndpoints; i++) {
-		ep = &altsetting->endpoint[i].desc;
-
-		/* Is it a BULK endpoint? */
-		if (usb_endpoint_xfer_bulk(ep)) {
-			/* BULK in or out? */
-			if (usb_endpoint_dir_in(ep)) {
-				if (ep_in == NULL)
-					ep_in = ep;
-			} else {
-				if (ep_out == NULL)
-					ep_out = ep;
-			}
-		}
-	}
-
-	if (ep_in == NULL || ep_out == NULL) {
-		printk(KERN_NOTICE "%s: failed endpoint check\n", sc->name);
-		return -ENODEV;
-	}
-
-	/* Calculate and store the pipe values */
-	sc->send_ctrl_pipe = usb_sndctrlpipe(dev, 0);
-	sc->recv_ctrl_pipe = usb_rcvctrlpipe(dev, 0);
-	sc->send_bulk_pipe = usb_sndbulkpipe(dev,
-		usb_endpoint_num(ep_out));
-	sc->recv_bulk_pipe = usb_rcvbulkpipe(dev, 
-		usb_endpoint_num(ep_in));
-
-	return 0;
-}
-
-/*
- * Probing is done in the process context, which allows us to cheat
- * and not to build a state machine for the discovery.
- */
-static int ub_probe(struct usb_interface *intf,
-    const struct usb_device_id *dev_id)
-{
-	struct ub_dev *sc;
-	int nluns;
-	int rc;
-	int i;
-
-	if (usb_usual_check_type(dev_id, USB_US_TYPE_UB))
-		return -ENXIO;
-
-	rc = -ENOMEM;
-	if ((sc = kzalloc(sizeof(struct ub_dev), GFP_KERNEL)) == NULL)
-		goto err_core;
-	sc->lock = ub_next_lock();
-	INIT_LIST_HEAD(&sc->luns);
-	usb_init_urb(&sc->work_urb);
-	tasklet_init(&sc->tasklet, ub_scsi_action, (unsigned long)sc);
-	atomic_set(&sc->poison, 0);
-	INIT_WORK(&sc->reset_work, ub_reset_task);
-	init_waitqueue_head(&sc->reset_wait);
-
-	init_timer(&sc->work_timer);
-	sc->work_timer.data = (unsigned long) sc;
-	sc->work_timer.function = ub_urb_timeout;
-
-	ub_init_completion(&sc->work_done);
-	sc->work_done.done = 1;		/* A little yuk, but oh well... */
-
-	sc->dev = interface_to_usbdev(intf);
-	sc->intf = intf;
-	// sc->ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
-	usb_set_intfdata(intf, sc);
-	usb_get_dev(sc->dev);
-	/*
-	 * Since we give the interface struct to the block level through
-	 * disk->driverfs_dev, we have to pin it. Otherwise, block_uevent
-	 * oopses on close after a disconnect (kernels 2.6.16 and up).
-	 */
-	usb_get_intf(sc->intf);
-
-	snprintf(sc->name, 12, DRV_NAME "(%d.%d)",
-	    sc->dev->bus->busnum, sc->dev->devnum);
-
-	/* XXX Verify that we can handle the device (from descriptors) */
-
-	if (ub_get_pipes(sc, sc->dev, intf) != 0)
-		goto err_dev_desc;
-
-	/*
-	 * At this point, all USB initialization is done, do upper layer.
-	 * We really hate halfway initialized structures, so from the
-	 * invariants perspective, this ub_dev is fully constructed at
-	 * this point.
-	 */
-
-	/*
-	 * This is needed to clear toggles. It is a problem only if we do
-	 * `rmmod ub && modprobe ub` without disconnects, but we like that.
-	 */
-#if 0 /* iPod Mini fails if we do this (big white iPod works) */
-	ub_probe_clear_stall(sc, sc->recv_bulk_pipe);
-	ub_probe_clear_stall(sc, sc->send_bulk_pipe);
-#endif
-
-	/*
-	 * The way this is used by the startup code is a little specific.
-	 * A SCSI check causes a USB stall. Our common case code sees it
-	 * and clears the check, after which the device is ready for use.
-	 * But if a check was not present, any command other than
-	 * TEST_UNIT_READY ends with a lockup (including REQUEST_SENSE).
-	 *
-	 * If we neglect to clear the SCSI check, the first real command fails
-	 * (which is the capacity readout). We clear that and retry, but why
-	 * causing spurious retries for no reason.
-	 *
-	 * Revalidation may start with its own TEST_UNIT_READY, but that one
-	 * has to succeed, so we clear checks with an additional one here.
-	 * In any case it's not our business how revaliadation is implemented.
-	 */
-	for (i = 0; i < 3; i++) {  /* Retries for the schwag key from KS'04 */
-		if ((rc = ub_sync_tur(sc, NULL)) <= 0) break;
-		if (rc != 0x6) break;
-		msleep(10);
-	}
-
-	nluns = 1;
-	for (i = 0; i < 3; i++) {
-		if ((rc = ub_sync_getmaxlun(sc)) < 0)
-			break;
-		if (rc != 0) {
-			nluns = rc;
-			break;
-		}
-		msleep(100);
-	}
-
-	for (i = 0; i < nluns; i++) {
-		ub_probe_lun(sc, i);
-	}
-	return 0;
-
-err_dev_desc:
-	usb_set_intfdata(intf, NULL);
-	usb_put_intf(sc->intf);
-	usb_put_dev(sc->dev);
-	kfree(sc);
-err_core:
-	return rc;
-}
-
-static int ub_probe_lun(struct ub_dev *sc, int lnum)
-{
-	struct ub_lun *lun;
-	struct request_queue *q;
-	struct gendisk *disk;
-	int rc;
-
-	rc = -ENOMEM;
-	if ((lun = kzalloc(sizeof(struct ub_lun), GFP_KERNEL)) == NULL)
-		goto err_alloc;
-	lun->num = lnum;
-
-	rc = -ENOSR;
-	if ((lun->id = ub_id_get()) == -1)
-		goto err_id;
-
-	lun->udev = sc;
-
-	snprintf(lun->name, 16, DRV_NAME "%c(%d.%d.%d)",
-	    lun->id + 'a', sc->dev->bus->busnum, sc->dev->devnum, lun->num);
-
-	lun->removable = 1;		/* XXX Query this from the device */
-	lun->changed = 1;		/* ub_revalidate clears only */
-	ub_revalidate(sc, lun);
-
-	rc = -ENOMEM;
-	if ((disk = alloc_disk(UB_PARTS_PER_LUN)) == NULL)
-		goto err_diskalloc;
-
-	sprintf(disk->disk_name, DRV_NAME "%c", lun->id + 'a');
-	disk->major = UB_MAJOR;
-	disk->first_minor = lun->id * UB_PARTS_PER_LUN;
-	disk->fops = &ub_bd_fops;
-	disk->private_data = lun;
-	disk->driverfs_dev = &sc->intf->dev;
-
-	rc = -ENOMEM;
-	if ((q = blk_init_queue(ub_request_fn, sc->lock)) == NULL)
-		goto err_blkqinit;
-
-	disk->queue = q;
-
-	blk_queue_bounce_limit(q, BLK_BOUNCE_HIGH);
-	blk_queue_max_segments(q, UB_MAX_REQ_SG);
-	blk_queue_segment_boundary(q, 0xffffffff);	/* Dubious. */
-	blk_queue_max_hw_sectors(q, UB_MAX_SECTORS);
-	blk_queue_logical_block_size(q, lun->capacity.bsize);
-
-	lun->disk = disk;
-	q->queuedata = lun;
-	list_add(&lun->link, &sc->luns);
-
-	set_capacity(disk, lun->capacity.nsec);
-	if (lun->removable)
-		disk->flags |= GENHD_FL_REMOVABLE;
-
-	add_disk(disk);
-
-	return 0;
-
-err_blkqinit:
-	put_disk(disk);
-err_diskalloc:
-	ub_id_put(lun->id);
-err_id:
-	kfree(lun);
-err_alloc:
-	return rc;
-}
-
-static void ub_disconnect(struct usb_interface *intf)
-{
-	struct ub_dev *sc = usb_get_intfdata(intf);
-	struct ub_lun *lun;
-	unsigned long flags;
-
-	/*
-	 * Prevent ub_bd_release from pulling the rug from under us.
-	 * XXX This is starting to look like a kref.
-	 * XXX Why not to take this ref at probe time?
-	 */
-	spin_lock_irqsave(&ub_lock, flags);
-	sc->openc++;
-	spin_unlock_irqrestore(&ub_lock, flags);
-
-	/*
-	 * Fence stall clearings, operations triggered by unlinkings and so on.
-	 * We do not attempt to unlink any URBs, because we do not trust the
-	 * unlink paths in HC drivers. Also, we get -84 upon disconnect anyway.
-	 */
-	atomic_set(&sc->poison, 1);
-
-	/*
-	 * Wait for reset to end, if any.
-	 */
-	wait_event(sc->reset_wait, !sc->reset);
-
-	/*
-	 * Blow away queued commands.
-	 *
-	 * Actually, this never works, because before we get here
-	 * the HCD terminates outstanding URB(s). It causes our
-	 * SCSI command queue to advance, commands fail to submit,
-	 * and the whole queue drains. So, we just use this code to
-	 * print warnings.
-	 */
-	spin_lock_irqsave(sc->lock, flags);
-	{
-		struct ub_scsi_cmd *cmd;
-		int cnt = 0;
-		while ((cmd = ub_cmdq_peek(sc)) != NULL) {
-			cmd->error = -ENOTCONN;
-			cmd->state = UB_CMDST_DONE;
-			ub_cmdq_pop(sc);
-			(*cmd->done)(sc, cmd);
-			cnt++;
-		}
-		if (cnt != 0) {
-			printk(KERN_WARNING "%s: "
-			    "%d was queued after shutdown\n", sc->name, cnt);
-		}
-	}
-	spin_unlock_irqrestore(sc->lock, flags);
-
-	/*
-	 * Unregister the upper layer.
-	 */
-	list_for_each_entry(lun, &sc->luns, link) {
-		del_gendisk(lun->disk);
-		/*
-		 * I wish I could do:
-		 *    queue_flag_set(QUEUE_FLAG_DEAD, q);
-		 * As it is, we rely on our internal poisoning and let
-		 * the upper levels to spin furiously failing all the I/O.
-		 */
-	}
-
-	/*
-	 * Testing for -EINPROGRESS is always a bug, so we are bending
-	 * the rules a little.
-	 */
-	spin_lock_irqsave(sc->lock, flags);
-	if (sc->work_urb.status == -EINPROGRESS) {	/* janitors: ignore */
-		printk(KERN_WARNING "%s: "
-		    "URB is active after disconnect\n", sc->name);
-	}
-	spin_unlock_irqrestore(sc->lock, flags);
-
-	/*
-	 * There is virtually no chance that other CPU runs a timeout so long
-	 * after ub_urb_complete should have called del_timer, but only if HCD
-	 * didn't forget to deliver a callback on unlink.
-	 */
-	del_timer_sync(&sc->work_timer);
-
-	/*
-	 * At this point there must be no commands coming from anyone
-	 * and no URBs left in transit.
-	 */
-
-	ub_put(sc);
-}
-
-static struct usb_driver ub_driver = {
-	.name =		"ub",
-	.probe =	ub_probe,
-	.disconnect =	ub_disconnect,
-	.id_table =	ub_usb_ids,
-	.pre_reset =	ub_pre_reset,
-	.post_reset =	ub_post_reset,
-};
-
-static int __init ub_init(void)
-{
-	int rc;
-	int i;
-
-	pr_info("'Low Performance USB Block' driver is deprecated. "
-			"Please switch to usb-storage\n");
-	for (i = 0; i < UB_QLOCK_NUM; i++)
-		spin_lock_init(&ub_qlockv[i]);
-
-	if ((rc = register_blkdev(UB_MAJOR, DRV_NAME)) != 0)
-		goto err_regblkdev;
-
-	if ((rc = usb_register(&ub_driver)) != 0)
-		goto err_register;
-
-	usb_usual_set_present(USB_US_TYPE_UB);
-	return 0;
-
-err_register:
-	unregister_blkdev(UB_MAJOR, DRV_NAME);
-err_regblkdev:
-	return rc;
-}
-
-static void __exit ub_exit(void)
-{
-	usb_deregister(&ub_driver);
-
-	unregister_blkdev(UB_MAJOR, DRV_NAME);
-	usb_usual_clear_present(USB_US_TYPE_UB);
-}
-
-module_init(ub_init);
-module_exit(ub_exit);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
index c0bbeb4..53b81d5 100644
--- a/drivers/block/virtio_blk.c
+++ b/drivers/block/virtio_blk.c
@@ -14,6 +14,9 @@
 
 #define PART_BITS 4
 
+static bool use_bio;
+module_param(use_bio, bool, S_IRUGO);
+
 static int major;
 static DEFINE_IDA(vd_index_ida);
 
@@ -23,6 +26,7 @@ struct virtio_blk
 {
 	struct virtio_device *vdev;
 	struct virtqueue *vq;
+	wait_queue_head_t queue_wait;
 
 	/* The disk structure for the kernel. */
 	struct gendisk *disk;
@@ -51,53 +55,241 @@ struct virtio_blk
 struct virtblk_req
 {
 	struct request *req;
+	struct bio *bio;
 	struct virtio_blk_outhdr out_hdr;
 	struct virtio_scsi_inhdr in_hdr;
+	struct work_struct work;
+	struct virtio_blk *vblk;
+	int flags;
 	u8 status;
+	struct scatterlist sg[];
+};
+
+enum {
+	VBLK_IS_FLUSH		= 1,
+	VBLK_REQ_FLUSH		= 2,
+	VBLK_REQ_DATA		= 4,
+	VBLK_REQ_FUA		= 8,
 };
 
-static void blk_done(struct virtqueue *vq)
+static inline int virtblk_result(struct virtblk_req *vbr)
+{
+	switch (vbr->status) {
+	case VIRTIO_BLK_S_OK:
+		return 0;
+	case VIRTIO_BLK_S_UNSUPP:
+		return -ENOTTY;
+	default:
+		return -EIO;
+	}
+}
+
+static inline struct virtblk_req *virtblk_alloc_req(struct virtio_blk *vblk,
+						    gfp_t gfp_mask)
 {
-	struct virtio_blk *vblk = vq->vdev->priv;
 	struct virtblk_req *vbr;
-	unsigned int len;
-	unsigned long flags;
 
-	spin_lock_irqsave(vblk->disk->queue->queue_lock, flags);
-	while ((vbr = virtqueue_get_buf(vblk->vq, &len)) != NULL) {
-		int error;
+	vbr = mempool_alloc(vblk->pool, gfp_mask);
+	if (!vbr)
+		return NULL;
 
-		switch (vbr->status) {
-		case VIRTIO_BLK_S_OK:
-			error = 0;
-			break;
-		case VIRTIO_BLK_S_UNSUPP:
-			error = -ENOTTY;
-			break;
-		default:
-			error = -EIO;
+	vbr->vblk = vblk;
+	if (use_bio)
+		sg_init_table(vbr->sg, vblk->sg_elems);
+
+	return vbr;
+}
+
+static void virtblk_add_buf_wait(struct virtio_blk *vblk,
+				 struct virtblk_req *vbr,
+				 unsigned long out,
+				 unsigned long in)
+{
+	DEFINE_WAIT(wait);
+
+	for (;;) {
+		prepare_to_wait_exclusive(&vblk->queue_wait, &wait,
+					  TASK_UNINTERRUPTIBLE);
+
+		spin_lock_irq(vblk->disk->queue->queue_lock);
+		if (virtqueue_add_buf(vblk->vq, vbr->sg, out, in, vbr,
+				      GFP_ATOMIC) < 0) {
+			spin_unlock_irq(vblk->disk->queue->queue_lock);
+			io_schedule();
+		} else {
+			virtqueue_kick(vblk->vq);
+			spin_unlock_irq(vblk->disk->queue->queue_lock);
 			break;
 		}
 
-		switch (vbr->req->cmd_type) {
-		case REQ_TYPE_BLOCK_PC:
-			vbr->req->resid_len = vbr->in_hdr.residual;
-			vbr->req->sense_len = vbr->in_hdr.sense_len;
-			vbr->req->errors = vbr->in_hdr.errors;
-			break;
-		case REQ_TYPE_SPECIAL:
-			vbr->req->errors = (error != 0);
-			break;
-		default:
-			break;
+	}
+
+	finish_wait(&vblk->queue_wait, &wait);
+}
+
+static inline void virtblk_add_req(struct virtblk_req *vbr,
+				   unsigned int out, unsigned int in)
+{
+	struct virtio_blk *vblk = vbr->vblk;
+
+	spin_lock_irq(vblk->disk->queue->queue_lock);
+	if (unlikely(virtqueue_add_buf(vblk->vq, vbr->sg, out, in, vbr,
+					GFP_ATOMIC) < 0)) {
+		spin_unlock_irq(vblk->disk->queue->queue_lock);
+		virtblk_add_buf_wait(vblk, vbr, out, in);
+		return;
+	}
+	virtqueue_kick(vblk->vq);
+	spin_unlock_irq(vblk->disk->queue->queue_lock);
+}
+
+static int virtblk_bio_send_flush(struct virtblk_req *vbr)
+{
+	unsigned int out = 0, in = 0;
+
+	vbr->flags |= VBLK_IS_FLUSH;
+	vbr->out_hdr.type = VIRTIO_BLK_T_FLUSH;
+	vbr->out_hdr.sector = 0;
+	vbr->out_hdr.ioprio = 0;
+	sg_set_buf(&vbr->sg[out++], &vbr->out_hdr, sizeof(vbr->out_hdr));
+	sg_set_buf(&vbr->sg[out + in++], &vbr->status, sizeof(vbr->status));
+
+	virtblk_add_req(vbr, out, in);
+
+	return 0;
+}
+
+static int virtblk_bio_send_data(struct virtblk_req *vbr)
+{
+	struct virtio_blk *vblk = vbr->vblk;
+	unsigned int num, out = 0, in = 0;
+	struct bio *bio = vbr->bio;
+
+	vbr->flags &= ~VBLK_IS_FLUSH;
+	vbr->out_hdr.type = 0;
+	vbr->out_hdr.sector = bio->bi_sector;
+	vbr->out_hdr.ioprio = bio_prio(bio);
+
+	sg_set_buf(&vbr->sg[out++], &vbr->out_hdr, sizeof(vbr->out_hdr));
+
+	num = blk_bio_map_sg(vblk->disk->queue, bio, vbr->sg + out);
+
+	sg_set_buf(&vbr->sg[num + out + in++], &vbr->status,
+		   sizeof(vbr->status));
+
+	if (num) {
+		if (bio->bi_rw & REQ_WRITE) {
+			vbr->out_hdr.type |= VIRTIO_BLK_T_OUT;
+			out += num;
+		} else {
+			vbr->out_hdr.type |= VIRTIO_BLK_T_IN;
+			in += num;
 		}
+	}
+
+	virtblk_add_req(vbr, out, in);
+
+	return 0;
+}
+
+static void virtblk_bio_send_data_work(struct work_struct *work)
+{
+	struct virtblk_req *vbr;
+
+	vbr = container_of(work, struct virtblk_req, work);
+
+	virtblk_bio_send_data(vbr);
+}
+
+static void virtblk_bio_send_flush_work(struct work_struct *work)
+{
+	struct virtblk_req *vbr;
+
+	vbr = container_of(work, struct virtblk_req, work);
+
+	virtblk_bio_send_flush(vbr);
+}
 
-		__blk_end_request_all(vbr->req, error);
+static inline void virtblk_request_done(struct virtblk_req *vbr)
+{
+	struct virtio_blk *vblk = vbr->vblk;
+	struct request *req = vbr->req;
+	int error = virtblk_result(vbr);
+
+	if (req->cmd_type == REQ_TYPE_BLOCK_PC) {
+		req->resid_len = vbr->in_hdr.residual;
+		req->sense_len = vbr->in_hdr.sense_len;
+		req->errors = vbr->in_hdr.errors;
+	} else if (req->cmd_type == REQ_TYPE_SPECIAL) {
+		req->errors = (error != 0);
+	}
+
+	__blk_end_request_all(req, error);
+	mempool_free(vbr, vblk->pool);
+}
+
+static inline void virtblk_bio_flush_done(struct virtblk_req *vbr)
+{
+	struct virtio_blk *vblk = vbr->vblk;
+
+	if (vbr->flags & VBLK_REQ_DATA) {
+		/* Send out the actual write data */
+		INIT_WORK(&vbr->work, virtblk_bio_send_data_work);
+		queue_work(virtblk_wq, &vbr->work);
+	} else {
+		bio_endio(vbr->bio, virtblk_result(vbr));
 		mempool_free(vbr, vblk->pool);
 	}
+}
+
+static inline void virtblk_bio_data_done(struct virtblk_req *vbr)
+{
+	struct virtio_blk *vblk = vbr->vblk;
+
+	if (unlikely(vbr->flags & VBLK_REQ_FUA)) {
+		/* Send out a flush before end the bio */
+		vbr->flags &= ~VBLK_REQ_DATA;
+		INIT_WORK(&vbr->work, virtblk_bio_send_flush_work);
+		queue_work(virtblk_wq, &vbr->work);
+	} else {
+		bio_endio(vbr->bio, virtblk_result(vbr));
+		mempool_free(vbr, vblk->pool);
+	}
+}
+
+static inline void virtblk_bio_done(struct virtblk_req *vbr)
+{
+	if (unlikely(vbr->flags & VBLK_IS_FLUSH))
+		virtblk_bio_flush_done(vbr);
+	else
+		virtblk_bio_data_done(vbr);
+}
+
+static void virtblk_done(struct virtqueue *vq)
+{
+	struct virtio_blk *vblk = vq->vdev->priv;
+	bool bio_done = false, req_done = false;
+	struct virtblk_req *vbr;
+	unsigned long flags;
+	unsigned int len;
+
+	spin_lock_irqsave(vblk->disk->queue->queue_lock, flags);
+	while ((vbr = virtqueue_get_buf(vblk->vq, &len)) != NULL) {
+		if (vbr->bio) {
+			virtblk_bio_done(vbr);
+			bio_done = true;
+		} else {
+			virtblk_request_done(vbr);
+			req_done = true;
+		}
+	}
 	/* In case queue is stopped waiting for more buffers. */
-	blk_start_queue(vblk->disk->queue);
+	if (req_done)
+		blk_start_queue(vblk->disk->queue);
 	spin_unlock_irqrestore(vblk->disk->queue->queue_lock, flags);
+
+	if (bio_done)
+		wake_up(&vblk->queue_wait);
 }
 
 static bool do_req(struct request_queue *q, struct virtio_blk *vblk,
@@ -106,13 +298,13 @@ static bool do_req(struct request_queue *q, struct virtio_blk *vblk,
 	unsigned long num, out = 0, in = 0;
 	struct virtblk_req *vbr;
 
-	vbr = mempool_alloc(vblk->pool, GFP_ATOMIC);
+	vbr = virtblk_alloc_req(vblk, GFP_ATOMIC);
 	if (!vbr)
 		/* When another request finishes we'll try again. */
 		return false;
 
 	vbr->req = req;
-
+	vbr->bio = NULL;
 	if (req->cmd_flags & REQ_FLUSH) {
 		vbr->out_hdr.type = VIRTIO_BLK_T_FLUSH;
 		vbr->out_hdr.sector = 0;
@@ -172,7 +364,8 @@ static bool do_req(struct request_queue *q, struct virtio_blk *vblk,
 		}
 	}
 
-	if (virtqueue_add_buf(vblk->vq, vblk->sg, out, in, vbr, GFP_ATOMIC)<0) {
+	if (virtqueue_add_buf(vblk->vq, vblk->sg, out, in, vbr,
+			      GFP_ATOMIC) < 0) {
 		mempool_free(vbr, vblk->pool);
 		return false;
 	}
@@ -180,7 +373,7 @@ static bool do_req(struct request_queue *q, struct virtio_blk *vblk,
 	return true;
 }
 
-static void do_virtblk_request(struct request_queue *q)
+static void virtblk_request(struct request_queue *q)
 {
 	struct virtio_blk *vblk = q->queuedata;
 	struct request *req;
@@ -203,6 +396,34 @@ static void do_virtblk_request(struct request_queue *q)
 		virtqueue_kick(vblk->vq);
 }
 
+static void virtblk_make_request(struct request_queue *q, struct bio *bio)
+{
+	struct virtio_blk *vblk = q->queuedata;
+	struct virtblk_req *vbr;
+
+	BUG_ON(bio->bi_phys_segments + 2 > vblk->sg_elems);
+
+	vbr = virtblk_alloc_req(vblk, GFP_NOIO);
+	if (!vbr) {
+		bio_endio(bio, -ENOMEM);
+		return;
+	}
+
+	vbr->bio = bio;
+	vbr->flags = 0;
+	if (bio->bi_rw & REQ_FLUSH)
+		vbr->flags |= VBLK_REQ_FLUSH;
+	if (bio->bi_rw & REQ_FUA)
+		vbr->flags |= VBLK_REQ_FUA;
+	if (bio->bi_size)
+		vbr->flags |= VBLK_REQ_DATA;
+
+	if (unlikely(vbr->flags & VBLK_REQ_FLUSH))
+		virtblk_bio_send_flush(vbr);
+	else
+		virtblk_bio_send_data(vbr);
+}
+
 /* return id (s/n) string for *disk to *id_str
  */
 static int virtblk_get_id(struct gendisk *disk, char *id_str)
@@ -360,7 +581,7 @@ static int init_vq(struct virtio_blk *vblk)
 	int err = 0;
 
 	/* We expect one virtqueue, for output. */
-	vblk->vq = virtio_find_single_vq(vblk->vdev, blk_done, "requests");
+	vblk->vq = virtio_find_single_vq(vblk->vdev, virtblk_done, "requests");
 	if (IS_ERR(vblk->vq))
 		err = PTR_ERR(vblk->vq);
 
@@ -477,6 +698,8 @@ static int __devinit virtblk_probe(struct virtio_device *vdev)
 	struct virtio_blk *vblk;
 	struct request_queue *q;
 	int err, index;
+	int pool_size;
+
 	u64 cap;
 	u32 v, blk_size, sg_elems, opt_io_size;
 	u16 min_io_size;
@@ -506,10 +729,12 @@ static int __devinit virtblk_probe(struct virtio_device *vdev)
 		goto out_free_index;
 	}
 
+	init_waitqueue_head(&vblk->queue_wait);
 	vblk->vdev = vdev;
 	vblk->sg_elems = sg_elems;
 	sg_init_table(vblk->sg, vblk->sg_elems);
 	mutex_init(&vblk->config_lock);
+
 	INIT_WORK(&vblk->config_work, virtblk_config_changed_work);
 	vblk->config_enable = true;
 
@@ -517,7 +742,10 @@ static int __devinit virtblk_probe(struct virtio_device *vdev)
 	if (err)
 		goto out_free_vblk;
 
-	vblk->pool = mempool_create_kmalloc_pool(1,sizeof(struct virtblk_req));
+	pool_size = sizeof(struct virtblk_req);
+	if (use_bio)
+		pool_size += sizeof(struct scatterlist) * sg_elems;
+	vblk->pool = mempool_create_kmalloc_pool(1, pool_size);
 	if (!vblk->pool) {
 		err = -ENOMEM;
 		goto out_free_vq;
@@ -530,12 +758,14 @@ static int __devinit virtblk_probe(struct virtio_device *vdev)
 		goto out_mempool;
 	}
 
-	q = vblk->disk->queue = blk_init_queue(do_virtblk_request, NULL);
+	q = vblk->disk->queue = blk_init_queue(virtblk_request, NULL);
 	if (!q) {
 		err = -ENOMEM;
 		goto out_put_disk;
 	}
 
+	if (use_bio)
+		blk_queue_make_request(q, virtblk_make_request);
 	q->queuedata = vblk;
 
 	virtblk_name_format("vd", index, vblk->disk->disk_name, DISK_NAME_LEN);
@@ -620,7 +850,6 @@ static int __devinit virtblk_probe(struct virtio_device *vdev)
 	if (!err && opt_io_size)
 		blk_queue_io_opt(q, blk_size * opt_io_size);
 
-
 	add_disk(vblk->disk);
 	err = device_create_file(disk_to_dev(vblk->disk), &dev_attr_serial);
 	if (err)
diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c
index 4f66171..f58434c 100644
--- a/drivers/block/xen-blkback/xenbus.c
+++ b/drivers/block/xen-blkback/xenbus.c
@@ -105,11 +105,10 @@ static struct xen_blkif *xen_blkif_alloc(domid_t domid)
 {
 	struct xen_blkif *blkif;
 
-	blkif = kmem_cache_alloc(xen_blkif_cachep, GFP_KERNEL);
+	blkif = kmem_cache_zalloc(xen_blkif_cachep, GFP_KERNEL);
 	if (!blkif)
 		return ERR_PTR(-ENOMEM);
 
-	memset(blkif, 0, sizeof(*blkif));
 	blkif->domid = domid;
 	spin_lock_init(&blkif->blk_ring_lock);
 	atomic_set(&blkif->refcnt, 1);
@@ -196,7 +195,7 @@ static void xen_blkif_disconnect(struct xen_blkif *blkif)
 	}
 }
 
-void xen_blkif_free(struct xen_blkif *blkif)
+static void xen_blkif_free(struct xen_blkif *blkif)
 {
 	if (!atomic_dec_and_test(&blkif->refcnt))
 		BUG();
@@ -257,7 +256,7 @@ static struct attribute_group xen_vbdstat_group = {
 VBD_SHOW(physical_device, "%x:%x\n", be->major, be->minor);
 VBD_SHOW(mode, "%s\n", be->mode);
 
-int xenvbd_sysfs_addif(struct xenbus_device *dev)
+static int xenvbd_sysfs_addif(struct xenbus_device *dev)
 {
 	int error;
 
@@ -281,7 +280,7 @@ fail1:	device_remove_file(&dev->dev, &dev_attr_physical_device);
 	return error;
 }
 
-void xenvbd_sysfs_delif(struct xenbus_device *dev)
+static void xenvbd_sysfs_delif(struct xenbus_device *dev)
 {
 	sysfs_remove_group(&dev->dev.kobj, &xen_vbdstat_group);
 	device_remove_file(&dev->dev, &dev_attr_mode);
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
index 2c2d2e5..007db89 100644
--- a/drivers/block/xen-blkfront.c
+++ b/drivers/block/xen-blkfront.c
@@ -670,7 +670,7 @@ static void xlvbd_release_gendisk(struct blkfront_info *info)
 	spin_unlock_irqrestore(&info->io_lock, flags);
 
 	/* Flush gnttab callback work. Must be done with no locks held. */
-	flush_work_sync(&info->work);
+	flush_work(&info->work);
 
 	del_gendisk(info->gd);
 
@@ -719,7 +719,7 @@ static void blkif_free(struct blkfront_info *info, int suspend)
 	spin_unlock_irq(&info->io_lock);
 
 	/* Flush gnttab callback work. Must be done with no locks held. */
-	flush_work_sync(&info->work);
+	flush_work(&info->work);
 
 	/* Free resources associated with old device channel. */
 	if (info->ring_ref != GRANT_INVALID_REF) {
diff --git a/drivers/bluetooth/bcm203x.c b/drivers/bluetooth/bcm203x.c
index 37ae175..364f82b 100644
--- a/drivers/bluetooth/bcm203x.c
+++ b/drivers/bluetooth/bcm203x.c
@@ -177,7 +177,7 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id
 	if (intf->cur_altsetting->desc.bInterfaceNumber != 0)
 		return -ENODEV;
 
-	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	data = devm_kzalloc(&intf->dev, sizeof(*data), GFP_KERNEL);
 	if (!data) {
 		BT_ERR("Can't allocate memory for data structure");
 		return -ENOMEM;
@@ -189,14 +189,12 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id
 	data->urb = usb_alloc_urb(0, GFP_KERNEL);
 	if (!data->urb) {
 		BT_ERR("Can't allocate URB");
-		kfree(data);
 		return -ENOMEM;
 	}
 
 	if (request_firmware(&firmware, "BCM2033-MD.hex", &udev->dev) < 0) {
 		BT_ERR("Mini driver request failed");
 		usb_free_urb(data->urb);
-		kfree(data);
 		return -EIO;
 	}
 
@@ -209,7 +207,6 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id
 		BT_ERR("Can't allocate memory for mini driver");
 		release_firmware(firmware);
 		usb_free_urb(data->urb);
-		kfree(data);
 		return -ENOMEM;
 	}
 
@@ -224,7 +221,6 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id
 		BT_ERR("Firmware request failed");
 		usb_free_urb(data->urb);
 		kfree(data->buffer);
-		kfree(data);
 		return -EIO;
 	}
 
@@ -236,7 +232,6 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id
 		release_firmware(firmware);
 		usb_free_urb(data->urb);
 		kfree(data->buffer);
-		kfree(data);
 		return -ENOMEM;
 	}
 
@@ -271,7 +266,6 @@ static void bcm203x_disconnect(struct usb_interface *intf)
 	usb_free_urb(data->urb);
 	kfree(data->fw_data);
 	kfree(data->buffer);
-	kfree(data);
 }
 
 static struct usb_driver bcm203x_driver = {
diff --git a/drivers/bluetooth/bfusb.c b/drivers/bluetooth/bfusb.c
index 32e8251..995aee9 100644
--- a/drivers/bluetooth/bfusb.c
+++ b/drivers/bluetooth/bfusb.c
@@ -653,7 +653,7 @@ static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *i
 	}
 
 	/* Initialize control structure and load firmware */
-	data = kzalloc(sizeof(struct bfusb_data), GFP_KERNEL);
+	data = devm_kzalloc(&intf->dev, sizeof(struct bfusb_data), GFP_KERNEL);
 	if (!data) {
 		BT_ERR("Can't allocate memory for control structure");
 		goto done;
@@ -674,7 +674,7 @@ static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *i
 
 	if (request_firmware(&firmware, "bfubase.frm", &udev->dev) < 0) {
 		BT_ERR("Firmware request failed");
-		goto error;
+		goto done;
 	}
 
 	BT_DBG("firmware data %p size %zu", firmware->data, firmware->size);
@@ -690,7 +690,7 @@ static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *i
 	hdev = hci_alloc_dev();
 	if (!hdev) {
 		BT_ERR("Can't allocate HCI device");
-		goto error;
+		goto done;
 	}
 
 	data->hdev = hdev;
@@ -708,7 +708,7 @@ static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *i
 	if (hci_register_dev(hdev) < 0) {
 		BT_ERR("Can't register HCI device");
 		hci_free_dev(hdev);
-		goto error;
+		goto done;
 	}
 
 	usb_set_intfdata(intf, data);
@@ -718,9 +718,6 @@ static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *i
 release:
 	release_firmware(firmware);
 
-error:
-	kfree(data);
-
 done:
 	return -EIO;
 }
@@ -741,7 +738,6 @@ static void bfusb_disconnect(struct usb_interface *intf)
 
 	hci_unregister_dev(hdev);
 	hci_free_dev(hdev);
-	kfree(data);
 }
 
 static struct usb_driver bfusb_driver = {
diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c
index 66c3a67..0d26851 100644
--- a/drivers/bluetooth/bluecard_cs.c
+++ b/drivers/bluetooth/bluecard_cs.c
@@ -681,7 +681,7 @@ static int bluecard_hci_send_frame(struct sk_buff *skb)
 	case HCI_SCODATA_PKT:
 		hdev->stat.sco_tx++;
 		break;
-	};
+	}
 
 	/* Prepend skb with frame type */
 	memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
@@ -849,7 +849,7 @@ static int bluecard_probe(struct pcmcia_device *link)
 	bluecard_info_t *info;
 
 	/* Create new info device */
-	info = kzalloc(sizeof(*info), GFP_KERNEL);
+	info = devm_kzalloc(&link->dev, sizeof(*info), GFP_KERNEL);
 	if (!info)
 		return -ENOMEM;
 
@@ -864,10 +864,7 @@ static int bluecard_probe(struct pcmcia_device *link)
 
 static void bluecard_detach(struct pcmcia_device *link)
 {
-	bluecard_info_t *info = link->priv;
-
 	bluecard_release(link);
-	kfree(info);
 }
 
 
diff --git a/drivers/bluetooth/bpa10x.c b/drivers/bluetooth/bpa10x.c
index 29caaed..2fe4a80 100644
--- a/drivers/bluetooth/bpa10x.c
+++ b/drivers/bluetooth/bpa10x.c
@@ -443,7 +443,7 @@ static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id *
 	if (intf->cur_altsetting->desc.bInterfaceNumber != 0)
 		return -ENODEV;
 
-	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	data = devm_kzalloc(&intf->dev, sizeof(*data), GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
 
@@ -453,10 +453,8 @@ static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id *
 	init_usb_anchor(&data->rx_anchor);
 
 	hdev = hci_alloc_dev();
-	if (!hdev) {
-		kfree(data);
+	if (!hdev)
 		return -ENOMEM;
-	}
 
 	hdev->bus = HCI_USB;
 	hci_set_drvdata(hdev, data);
@@ -475,7 +473,6 @@ static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id *
 	err = hci_register_dev(hdev);
 	if (err < 0) {
 		hci_free_dev(hdev);
-		kfree(data);
 		return err;
 	}
 
@@ -500,7 +497,6 @@ static void bpa10x_disconnect(struct usb_interface *intf)
 	hci_free_dev(data->hdev);
 	kfree_skb(data->rx_skb[0]);
 	kfree_skb(data->rx_skb[1]);
-	kfree(data);
 }
 
 static struct usb_driver bpa10x_driver = {
diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c
index 8925b6d..7ffd3f4 100644
--- a/drivers/bluetooth/bt3c_cs.c
+++ b/drivers/bluetooth/bt3c_cs.c
@@ -638,7 +638,7 @@ static int bt3c_probe(struct pcmcia_device *link)
 	bt3c_info_t *info;
 
 	/* Create new info device */
-	info = kzalloc(sizeof(*info), GFP_KERNEL);
+	info = devm_kzalloc(&link->dev, sizeof(*info), GFP_KERNEL);
 	if (!info)
 		return -ENOMEM;
 
@@ -654,10 +654,7 @@ static int bt3c_probe(struct pcmcia_device *link)
 
 static void bt3c_detach(struct pcmcia_device *link)
 {
-	bt3c_info_t *info = link->priv;
-
 	bt3c_release(link);
-	kfree(info);
 }
 
 static int bt3c_check_config(struct pcmcia_device *p_dev, void *priv_data)
diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c
index 6a9e971..3f4bfc8 100644
--- a/drivers/bluetooth/btmrvl_sdio.c
+++ b/drivers/bluetooth/btmrvl_sdio.c
@@ -600,8 +600,7 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)
 exit:
 	if (ret) {
 		hdev->stat.err_rx++;
-		if (skb)
-			kfree_skb(skb);
+		kfree_skb(skb);
 	}
 
 	return ret;
@@ -956,11 +955,9 @@ static int btmrvl_sdio_probe(struct sdio_func *func,
 	BT_INFO("vendor=0x%x, device=0x%x, class=%d, fn=%d",
 			id->vendor, id->device, id->class, func->num);
 
-	card = kzalloc(sizeof(*card), GFP_KERNEL);
-	if (!card) {
-		ret = -ENOMEM;
-		goto done;
-	}
+	card = devm_kzalloc(&func->dev, sizeof(*card), GFP_KERNEL);
+	if (!card)
+		return -ENOMEM;
 
 	card->func = func;
 
@@ -974,8 +971,7 @@ static int btmrvl_sdio_probe(struct sdio_func *func,
 
 	if (btmrvl_sdio_register_dev(card) < 0) {
 		BT_ERR("Failed to register BT device!");
-		ret = -ENODEV;
-		goto free_card;
+		return -ENODEV;
 	}
 
 	/* Disable the interrupts on the card */
@@ -1023,9 +1019,6 @@ disable_host_int:
 	btmrvl_sdio_disable_host_int(card);
 unreg_dev:
 	btmrvl_sdio_unregister_dev(card);
-free_card:
-	kfree(card);
-done:
 	return ret;
 }
 
@@ -1047,7 +1040,6 @@ static void btmrvl_sdio_remove(struct sdio_func *func)
 			BT_DBG("unregester dev");
 			btmrvl_sdio_unregister_dev(card);
 			btmrvl_remove_card(card->priv);
-			kfree(card);
 		}
 	}
 }
diff --git a/drivers/bluetooth/btsdio.c b/drivers/bluetooth/btsdio.c
index e10ea03..4a99097 100644
--- a/drivers/bluetooth/btsdio.c
+++ b/drivers/bluetooth/btsdio.c
@@ -304,7 +304,7 @@ static int btsdio_probe(struct sdio_func *func,
 		tuple = tuple->next;
 	}
 
-	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	data = devm_kzalloc(&func->dev, sizeof(*data), GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
 
@@ -315,10 +315,8 @@ static int btsdio_probe(struct sdio_func *func,
 	skb_queue_head_init(&data->txq);
 
 	hdev = hci_alloc_dev();
-	if (!hdev) {
-		kfree(data);
+	if (!hdev)
 		return -ENOMEM;
-	}
 
 	hdev->bus = HCI_SDIO;
 	hci_set_drvdata(hdev, data);
@@ -340,7 +338,6 @@ static int btsdio_probe(struct sdio_func *func,
 	err = hci_register_dev(hdev);
 	if (err < 0) {
 		hci_free_dev(hdev);
-		kfree(data);
 		return err;
 	}
 
@@ -366,7 +363,6 @@ static void btsdio_remove(struct sdio_func *func)
 	hci_unregister_dev(hdev);
 
 	hci_free_dev(hdev);
-	kfree(data);
 }
 
 static struct sdio_driver btsdio_driver = {
diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c
index 21e803a..35a553a 100644
--- a/drivers/bluetooth/btuart_cs.c
+++ b/drivers/bluetooth/btuart_cs.c
@@ -446,7 +446,7 @@ static int btuart_hci_send_frame(struct sk_buff *skb)
 	case HCI_SCODATA_PKT:
 		hdev->stat.sco_tx++;
 		break;
-	};
+	}
 
 	/* Prepend skb with frame type */
 	memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
@@ -567,7 +567,7 @@ static int btuart_probe(struct pcmcia_device *link)
 	btuart_info_t *info;
 
 	/* Create new info device */
-	info = kzalloc(sizeof(*info), GFP_KERNEL);
+	info = devm_kzalloc(&link->dev, sizeof(*info), GFP_KERNEL);
 	if (!info)
 		return -ENOMEM;
 
@@ -583,10 +583,7 @@ static int btuart_probe(struct pcmcia_device *link)
 
 static void btuart_detach(struct pcmcia_device *link)
 {
-	btuart_info_t *info = link->priv;
-
 	btuart_release(link);
-	kfree(info);
 }
 
 static int btuart_check_config(struct pcmcia_device *p_dev, void *priv_data)
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 654e248..debda27 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -96,11 +96,12 @@ static struct usb_device_id btusb_table[] = {
 	{ USB_DEVICE(0x0c10, 0x0000) },
 
 	/* Broadcom BCM20702A0 */
+	{ USB_DEVICE(0x04ca, 0x2003) },
 	{ USB_DEVICE(0x0489, 0xe042) },
 	{ USB_DEVICE(0x413c, 0x8197) },
 
 	/* Foxconn - Hon Hai */
-	{ USB_DEVICE(0x0489, 0xe033) },
+	{ USB_VENDOR_AND_INTERFACE_INFO(0x0489, 0xff, 0x01, 0x01) },
 
 	/*Broadcom devices with vendor specific id */
 	{ USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01) },
@@ -956,7 +957,7 @@ static int btusb_probe(struct usb_interface *intf,
 			return -ENODEV;
 	}
 
-	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	data = devm_kzalloc(&intf->dev, sizeof(*data), GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
 
@@ -979,10 +980,8 @@ static int btusb_probe(struct usb_interface *intf,
 		}
 	}
 
-	if (!data->intr_ep || !data->bulk_tx_ep || !data->bulk_rx_ep) {
-		kfree(data);
+	if (!data->intr_ep || !data->bulk_tx_ep || !data->bulk_rx_ep)
 		return -ENODEV;
-	}
 
 	data->cmdreq_type = USB_TYPE_CLASS;
 
@@ -1002,10 +1001,8 @@ static int btusb_probe(struct usb_interface *intf,
 	init_usb_anchor(&data->deferred);
 
 	hdev = hci_alloc_dev();
-	if (!hdev) {
-		kfree(data);
+	if (!hdev)
 		return -ENOMEM;
-	}
 
 	hdev->bus = HCI_USB;
 	hci_set_drvdata(hdev, data);
@@ -1073,7 +1070,6 @@ static int btusb_probe(struct usb_interface *intf,
 							data->isoc, data);
 		if (err < 0) {
 			hci_free_dev(hdev);
-			kfree(data);
 			return err;
 		}
 	}
@@ -1081,7 +1077,6 @@ static int btusb_probe(struct usb_interface *intf,
 	err = hci_register_dev(hdev);
 	if (err < 0) {
 		hci_free_dev(hdev);
-		kfree(data);
 		return err;
 	}
 
@@ -1114,7 +1109,6 @@ static void btusb_disconnect(struct usb_interface *intf)
 		usb_driver_release_interface(&btusb_driver, data->isoc);
 
 	hci_free_dev(hdev);
-	kfree(data);
 }
 
 #ifdef CONFIG_PM
diff --git a/drivers/bluetooth/btwilink.c b/drivers/bluetooth/btwilink.c
index 8869469..60abf59 100644
--- a/drivers/bluetooth/btwilink.c
+++ b/drivers/bluetooth/btwilink.c
@@ -297,16 +297,14 @@ static int bt_ti_probe(struct platform_device *pdev)
 	struct hci_dev *hdev;
 	int err;
 
-	hst = kzalloc(sizeof(struct ti_st), GFP_KERNEL);
+	hst = devm_kzalloc(&pdev->dev, sizeof(struct ti_st), GFP_KERNEL);
 	if (!hst)
 		return -ENOMEM;
 
 	/* Expose "hciX" device to user space */
 	hdev = hci_alloc_dev();
-	if (!hdev) {
-		kfree(hst);
+	if (!hdev)
 		return -ENOMEM;
-	}
 
 	BT_DBG("hdev %p", hdev);
 
@@ -321,7 +319,6 @@ static int bt_ti_probe(struct platform_device *pdev)
 	err = hci_register_dev(hdev);
 	if (err < 0) {
 		BT_ERR("Can't register HCI device error %d", err);
-		kfree(hst);
 		hci_free_dev(hdev);
 		return err;
 	}
@@ -347,7 +344,6 @@ static int bt_ti_remove(struct platform_device *pdev)
 	hci_unregister_dev(hdev);
 
 	hci_free_dev(hdev);
-	kfree(hst);
 
 	dev_set_drvdata(&pdev->dev, NULL);
 	return 0;
@@ -362,21 +358,7 @@ static struct platform_driver btwilink_driver = {
 	},
 };
 
-/* ------- Module Init/Exit interfaces ------ */
-static int __init btwilink_init(void)
-{
-	BT_INFO("Bluetooth Driver for TI WiLink - Version %s", VERSION);
-
-	return platform_driver_register(&btwilink_driver);
-}
-
-static void __exit btwilink_exit(void)
-{
-	platform_driver_unregister(&btwilink_driver);
-}
-
-module_init(btwilink_init);
-module_exit(btwilink_exit);
+module_platform_driver(btwilink_driver);
 
 /* ------ Module Info ------ */
 
diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c
index 97a7784..036cb36 100644
--- a/drivers/bluetooth/dtl1_cs.c
+++ b/drivers/bluetooth/dtl1_cs.c
@@ -550,7 +550,7 @@ static int dtl1_probe(struct pcmcia_device *link)
 	dtl1_info_t *info;
 
 	/* Create new info device */
-	info = kzalloc(sizeof(*info), GFP_KERNEL);
+	info = devm_kzalloc(&link->dev, sizeof(*info), GFP_KERNEL);
 	if (!info)
 		return -ENOMEM;
 
@@ -569,7 +569,6 @@ static void dtl1_detach(struct pcmcia_device *link)
 
 	dtl1_close(info);
 	pcmcia_disable_device(link);
-	kfree(info);
 }
 
 static int dtl1_confcheck(struct pcmcia_device *p_dev, void *priv_data)
diff --git a/drivers/bluetooth/hci_ath.c b/drivers/bluetooth/hci_ath.c
index 12172a6..0bc8a6a 100644
--- a/drivers/bluetooth/hci_ath.c
+++ b/drivers/bluetooth/hci_ath.c
@@ -58,7 +58,7 @@ static int ath_wakeup_ar3k(struct tty_struct *tty)
 		return status;
 
 	/* Disable Automatic RTSCTS */
-	memcpy(&ktermios, tty->termios, sizeof(ktermios));
+	ktermios = tty->termios;
 	ktermios.c_cflag &= ~CRTSCTS;
 	tty_set_termios(tty, &ktermios);
 
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index 74e0966..c8abce3 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -531,7 +531,7 @@ static int hci_uart_tty_ioctl(struct tty_struct *tty, struct file * file,
 	default:
 		err = n_tty_ioctl_helper(tty, file, cmd, arg);
 		break;
-	};
+	}
 
 	return err;
 }
diff --git a/drivers/bluetooth/hci_ll.c b/drivers/bluetooth/hci_ll.c
index ff6d589..cfc7679 100644
--- a/drivers/bluetooth/hci_ll.c
+++ b/drivers/bluetooth/hci_ll.c
@@ -481,7 +481,7 @@ static int ll_recv(struct hci_uart *hu, void *data, int count)
 			hu->hdev->stat.err_rx++;
 			ptr++; count--;
 			continue;
-		};
+		}
 
 		ptr++; count--;
 
diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c
index 3f72595..d8b7aed 100644
--- a/drivers/bluetooth/hci_vhci.c
+++ b/drivers/bluetooth/hci_vhci.c
@@ -156,7 +156,7 @@ static inline ssize_t vhci_put_user(struct vhci_data *data,
 	case HCI_SCODATA_PKT:
 		data->hdev->stat.sco_tx++;
 		break;
-	};
+	}
 
 	return total;
 }
diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig
new file mode 100644
index 0000000..bbec35d
--- /dev/null
+++ b/drivers/bus/Kconfig
@@ -0,0 +1,21 @@
+#
+# Bus Devices
+#
+
+menu "Bus devices"
+
+config OMAP_OCP2SCP
+	tristate "OMAP OCP2SCP DRIVER"
+	help
+	  Driver to enable ocp2scp module which transforms ocp interface
+	  protocol to scp protocol. In OMAP4, USB PHY is connected via
+	  OCP2SCP and in OMAP5, both USB PHY and SATA PHY is connected via
+	  OCP2SCP.
+
+config OMAP_INTERCONNECT
+	tristate "OMAP INTERCONNECT DRIVER"
+	depends on ARCH_OMAP2PLUS
+
+	help
+	  Driver to enable OMAP interconnect error handling driver.
+endmenu
diff --git a/drivers/bus/Makefile b/drivers/bus/Makefile
new file mode 100644
index 0000000..45d997c
--- /dev/null
+++ b/drivers/bus/Makefile
@@ -0,0 +1,8 @@
+#
+# Makefile for the bus drivers.
+#
+
+obj-$(CONFIG_OMAP_OCP2SCP)	+= omap-ocp2scp.o
+
+# Interconnect bus driver for OMAP SoCs.
+obj-$(CONFIG_OMAP_INTERCONNECT)	+= omap_l3_smx.o omap_l3_noc.o
diff --git a/drivers/bus/omap-ocp2scp.c b/drivers/bus/omap-ocp2scp.c
new file mode 100644
index 0000000..ff63560
--- /dev/null
+++ b/drivers/bus/omap-ocp2scp.c
@@ -0,0 +1,88 @@
+/*
+ * omap-ocp2scp.c - transform ocp interface protocol to scp protocol
+ *
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Author: Kishon Vijay Abraham I <kishon@ti.com>
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/pm_runtime.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+
+static int ocp2scp_remove_devices(struct device *dev, void *c)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+
+	platform_device_unregister(pdev);
+
+	return 0;
+}
+
+static int __devinit omap_ocp2scp_probe(struct platform_device *pdev)
+{
+	int			ret;
+	struct device_node	*np = pdev->dev.of_node;
+
+	if (np) {
+		ret = of_platform_populate(np, NULL, NULL, &pdev->dev);
+		if (ret) {
+			dev_err(&pdev->dev, "failed to add resources for ocp2scp child\n");
+			goto err0;
+		}
+	}
+	pm_runtime_enable(&pdev->dev);
+
+	return 0;
+
+err0:
+	device_for_each_child(&pdev->dev, NULL, ocp2scp_remove_devices);
+
+	return ret;
+}
+
+static int __devexit omap_ocp2scp_remove(struct platform_device *pdev)
+{
+	pm_runtime_disable(&pdev->dev);
+	device_for_each_child(&pdev->dev, NULL, ocp2scp_remove_devices);
+
+	return 0;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id omap_ocp2scp_id_table[] = {
+	{ .compatible = "ti,omap-ocp2scp" },
+	{}
+};
+MODULE_DEVICE_TABLE(of, omap_ocp2scp_id_table);
+#endif
+
+static struct platform_driver omap_ocp2scp_driver = {
+	.probe		= omap_ocp2scp_probe,
+	.remove		= __devexit_p(omap_ocp2scp_remove),
+	.driver		= {
+		.name	= "omap-ocp2scp",
+		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(omap_ocp2scp_id_table),
+	},
+};
+
+module_platform_driver(omap_ocp2scp_driver);
+
+MODULE_ALIAS("platform: omap-ocp2scp");
+MODULE_AUTHOR("Texas Instruments Inc.");
+MODULE_DESCRIPTION("OMAP OCP2SCP driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/bus/omap_l3_noc.c b/drivers/bus/omap_l3_noc.c
new file mode 100644
index 0000000..ab911a3
--- /dev/null
+++ b/drivers/bus/omap_l3_noc.c
@@ -0,0 +1,266 @@
+/*
+ * OMAP4XXX L3 Interconnect error handling driver
+ *
+ * Copyright (C) 2011 Texas Corporation
+ *	Santosh Shilimkar <santosh.shilimkar@ti.com>
+ *	Sricharan <r.sricharan@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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+
+#include "omap_l3_noc.h"
+
+/*
+ * Interrupt Handler for L3 error detection.
+ *	1) Identify the L3 clockdomain partition to which the error belongs to.
+ *	2) Identify the slave where the error information is logged
+ *	3) Print the logged information.
+ *	4) Add dump stack to provide kernel trace.
+ *
+ * Two Types of errors :
+ *	1) Custom errors in L3 :
+ *		Target like DMM/FW/EMIF generates SRESP=ERR error
+ *	2) Standard L3 error:
+ *		- Unsupported CMD.
+ *			L3 tries to access target while it is idle
+ *		- OCP disconnect.
+ *		- Address hole error:
+ *			If DSS/ISS/FDIF/USBHOSTFS access a target where they
+ *			do not have connectivity, the error is logged in
+ *			their default target which is DMM2.
+ *
+ *	On High Secure devices, firewall errors are possible and those
+ *	can be trapped as well. But the trapping is implemented as part
+ *	secure software and hence need not be implemented here.
+ */
+static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
+{
+
+	struct omap4_l3 *l3 = _l3;
+	int inttype, i, k;
+	int err_src = 0;
+	u32 std_err_main, err_reg, clear, masterid;
+	void __iomem *base, *l3_targ_base;
+	char *target_name, *master_name = "UN IDENTIFIED";
+
+	/* Get the Type of interrupt */
+	inttype = irq == l3->app_irq ? L3_APPLICATION_ERROR : L3_DEBUG_ERROR;
+
+	for (i = 0; i < L3_MODULES; i++) {
+		/*
+		 * Read the regerr register of the clock domain
+		 * to determine the source
+		 */
+		base = l3->l3_base[i];
+		err_reg = __raw_readl(base + l3_flagmux[i] +
+					+ L3_FLAGMUX_REGERR0 + (inttype << 3));
+
+		/* Get the corresponding error and analyse */
+		if (err_reg) {
+			/* Identify the source from control status register */
+			err_src = __ffs(err_reg);
+
+			/* Read the stderrlog_main_source from clk domain */
+			l3_targ_base = base + *(l3_targ[i] + err_src);
+			std_err_main =  __raw_readl(l3_targ_base +
+					L3_TARG_STDERRLOG_MAIN);
+			masterid = __raw_readl(l3_targ_base +
+					L3_TARG_STDERRLOG_MSTADDR);
+
+			switch (std_err_main & CUSTOM_ERROR) {
+			case STANDARD_ERROR:
+				target_name =
+					l3_targ_inst_name[i][err_src];
+				WARN(true, "L3 standard error: TARGET:%s at address 0x%x\n",
+					target_name,
+					__raw_readl(l3_targ_base +
+						L3_TARG_STDERRLOG_SLVOFSLSB));
+				/* clear the std error log*/
+				clear = std_err_main | CLEAR_STDERR_LOG;
+				writel(clear, l3_targ_base +
+					L3_TARG_STDERRLOG_MAIN);
+				break;
+
+			case CUSTOM_ERROR:
+				target_name =
+					l3_targ_inst_name[i][err_src];
+				for (k = 0; k < NUM_OF_L3_MASTERS; k++) {
+					if (masterid == l3_masters[k].id)
+						master_name =
+							l3_masters[k].name;
+				}
+				WARN(true, "L3 custom error: MASTER:%s TARGET:%s\n",
+					master_name, target_name);
+				/* clear the std error log*/
+				clear = std_err_main | CLEAR_STDERR_LOG;
+				writel(clear, l3_targ_base +
+					L3_TARG_STDERRLOG_MAIN);
+				break;
+
+			default:
+				/* Nothing to be handled here as of now */
+				break;
+			}
+		/* Error found so break the for loop */
+		break;
+		}
+	}
+	return IRQ_HANDLED;
+}
+
+static int __devinit omap4_l3_probe(struct platform_device *pdev)
+{
+	static struct omap4_l3 *l3;
+	struct resource	*res;
+	int ret;
+
+	l3 = kzalloc(sizeof(*l3), GFP_KERNEL);
+	if (!l3)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, l3);
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "couldn't find resource 0\n");
+		ret = -ENODEV;
+		goto err0;
+	}
+
+	l3->l3_base[0] = ioremap(res->start, resource_size(res));
+	if (!l3->l3_base[0]) {
+		dev_err(&pdev->dev, "ioremap failed\n");
+		ret = -ENOMEM;
+		goto err0;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!res) {
+		dev_err(&pdev->dev, "couldn't find resource 1\n");
+		ret = -ENODEV;
+		goto err1;
+	}
+
+	l3->l3_base[1] = ioremap(res->start, resource_size(res));
+	if (!l3->l3_base[1]) {
+		dev_err(&pdev->dev, "ioremap failed\n");
+		ret = -ENOMEM;
+		goto err1;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
+	if (!res) {
+		dev_err(&pdev->dev, "couldn't find resource 2\n");
+		ret = -ENODEV;
+		goto err2;
+	}
+
+	l3->l3_base[2] = ioremap(res->start, resource_size(res));
+	if (!l3->l3_base[2]) {
+		dev_err(&pdev->dev, "ioremap failed\n");
+		ret = -ENOMEM;
+		goto err2;
+	}
+
+	/*
+	 * Setup interrupt Handlers
+	 */
+	l3->debug_irq = platform_get_irq(pdev, 0);
+	ret = request_irq(l3->debug_irq,
+			l3_interrupt_handler,
+			IRQF_DISABLED, "l3-dbg-irq", l3);
+	if (ret) {
+		pr_crit("L3: request_irq failed to register for 0x%x\n",
+						l3->debug_irq);
+		goto err3;
+	}
+
+	l3->app_irq = platform_get_irq(pdev, 1);
+	ret = request_irq(l3->app_irq,
+			l3_interrupt_handler,
+			IRQF_DISABLED, "l3-app-irq", l3);
+	if (ret) {
+		pr_crit("L3: request_irq failed to register for 0x%x\n",
+						l3->app_irq);
+		goto err4;
+	}
+
+	return 0;
+
+err4:
+	free_irq(l3->debug_irq, l3);
+err3:
+	iounmap(l3->l3_base[2]);
+err2:
+	iounmap(l3->l3_base[1]);
+err1:
+	iounmap(l3->l3_base[0]);
+err0:
+	kfree(l3);
+	return ret;
+}
+
+static int __devexit omap4_l3_remove(struct platform_device *pdev)
+{
+	struct omap4_l3 *l3 = platform_get_drvdata(pdev);
+
+	free_irq(l3->app_irq, l3);
+	free_irq(l3->debug_irq, l3);
+	iounmap(l3->l3_base[0]);
+	iounmap(l3->l3_base[1]);
+	iounmap(l3->l3_base[2]);
+	kfree(l3);
+
+	return 0;
+}
+
+#if defined(CONFIG_OF)
+static const struct of_device_id l3_noc_match[] = {
+	{.compatible = "ti,omap4-l3-noc", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, l3_noc_match);
+#else
+#define l3_noc_match NULL
+#endif
+
+static struct platform_driver omap4_l3_driver = {
+	.probe		= omap4_l3_probe,
+	.remove		= __devexit_p(omap4_l3_remove),
+	.driver		= {
+		.name		= "omap_l3_noc",
+		.owner		= THIS_MODULE,
+		.of_match_table = l3_noc_match,
+	},
+};
+
+static int __init omap4_l3_init(void)
+{
+	return platform_driver_register(&omap4_l3_driver);
+}
+postcore_initcall_sync(omap4_l3_init);
+
+static void __exit omap4_l3_exit(void)
+{
+	platform_driver_unregister(&omap4_l3_driver);
+}
+module_exit(omap4_l3_exit);
diff --git a/drivers/bus/omap_l3_noc.h b/drivers/bus/omap_l3_noc.h
new file mode 100644
index 0000000..a6ce34d
--- /dev/null
+++ b/drivers/bus/omap_l3_noc.h
@@ -0,0 +1,176 @@
+/*
+ * OMAP4XXX L3 Interconnect  error handling driver header
+ *
+ * Copyright (C) 2011 Texas Corporation
+ *	Santosh Shilimkar <santosh.shilimkar@ti.com>
+ *	sricharan <r.sricharan@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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 __ARCH_ARM_MACH_OMAP2_L3_INTERCONNECT_3XXX_H
+#define __ARCH_ARM_MACH_OMAP2_L3_INTERCONNECT_3XXX_H
+
+#define L3_MODULES			3
+#define CLEAR_STDERR_LOG		(1 << 31)
+#define CUSTOM_ERROR			0x2
+#define STANDARD_ERROR			0x0
+#define INBAND_ERROR			0x0
+#define L3_APPLICATION_ERROR		0x0
+#define L3_DEBUG_ERROR			0x1
+
+/* L3 TARG register offsets */
+#define L3_TARG_STDERRLOG_MAIN		0x48
+#define L3_TARG_STDERRLOG_SLVOFSLSB	0x5c
+#define L3_TARG_STDERRLOG_MSTADDR	0x68
+#define L3_FLAGMUX_REGERR0		0xc
+
+#define NUM_OF_L3_MASTERS	(sizeof(l3_masters)/sizeof(l3_masters[0]))
+
+static u32 l3_flagmux[L3_MODULES] = {
+	0x500,
+	0x1000,
+	0X0200
+};
+
+/* L3 Target standard Error register offsets */
+static u32 l3_targ_inst_clk1[] = {
+	0x100, /* DMM1 */
+	0x200, /* DMM2 */
+	0x300, /* ABE */
+	0x400, /* L4CFG */
+	0x600,  /* CLK2 PWR DISC */
+	0x0,	/* Host CLK1 */
+	0x900	/* L4 Wakeup */
+};
+
+static u32 l3_targ_inst_clk2[] = {
+	0x500, /* CORTEX M3 */
+	0x300, /* DSS */
+	0x100, /* GPMC */
+	0x400, /* ISS */
+	0x700, /* IVAHD */
+	0xD00, /* missing in TRM  corresponds to AES1*/
+	0x900, /* L4 PER0*/
+	0x200, /* OCMRAM */
+	0x100, /* missing in TRM corresponds to GPMC sERROR*/
+	0x600, /* SGX */
+	0x800, /* SL2 */
+	0x1600, /* C2C */
+	0x1100,	/* missing in TRM corresponds PWR DISC CLK1*/
+	0xF00, /* missing in TRM corrsponds to SHA1*/
+	0xE00, /* missing in TRM corresponds to AES2*/
+	0xC00, /* L4 PER3 */
+	0xA00, /* L4 PER1*/
+	0xB00, /* L4 PER2*/
+	0x0, /* HOST CLK2 */
+	0x1800, /* CAL */
+	0x1700 /* LLI */
+};
+
+static u32 l3_targ_inst_clk3[] = {
+	0x0100	/* EMUSS */,
+	0x0300, /* DEBUGSS_CT_TBR */
+	0x0 /* HOST CLK3 */
+};
+
+static struct l3_masters_data {
+	u32 id;
+	char name[10];
+} l3_masters[] = {
+	{ 0x0 , "MPU"},
+	{ 0x10, "CS_ADP"},
+	{ 0x14, "xxx"},
+	{ 0x20, "DSP"},
+	{ 0x30, "IVAHD"},
+	{ 0x40, "ISS"},
+	{ 0x44, "DucatiM3"},
+	{ 0x48, "FaceDetect"},
+	{ 0x50, "SDMA_Rd"},
+	{ 0x54, "SDMA_Wr"},
+	{ 0x58, "xxx"},
+	{ 0x5C, "xxx"},
+	{ 0x60, "SGX"},
+	{ 0x70, "DSS"},
+	{ 0x80, "C2C"},
+	{ 0x88, "xxx"},
+	{ 0x8C, "xxx"},
+	{ 0x90, "HSI"},
+	{ 0xA0, "MMC1"},
+	{ 0xA4, "MMC2"},
+	{ 0xA8, "MMC6"},
+	{ 0xB0, "UNIPRO1"},
+	{ 0xC0, "USBHOSTHS"},
+	{ 0xC4, "USBOTGHS"},
+	{ 0xC8, "USBHOSTFS"}
+};
+
+static char *l3_targ_inst_name[L3_MODULES][21] = {
+	{
+		"DMM1",
+		"DMM2",
+		"ABE",
+		"L4CFG",
+		"CLK2 PWR DISC",
+		"HOST CLK1",
+		"L4 WAKEUP"
+	},
+	{
+		"CORTEX M3" ,
+		"DSS ",
+		"GPMC ",
+		"ISS ",
+		"IVAHD ",
+		"AES1",
+		"L4 PER0",
+		"OCMRAM ",
+		"GPMC sERROR",
+		"SGX ",
+		"SL2 ",
+		"C2C ",
+		"PWR DISC CLK1",
+		"SHA1",
+		"AES2",
+		"L4 PER3",
+		"L4 PER1",
+		"L4 PER2",
+		"HOST CLK2",
+		"CAL",
+		"LLI"
+	},
+	{
+		"EMUSS",
+		"DEBUG SOURCE",
+		"HOST CLK3"
+	},
+};
+
+static u32 *l3_targ[L3_MODULES] = {
+	l3_targ_inst_clk1,
+	l3_targ_inst_clk2,
+	l3_targ_inst_clk3,
+};
+
+struct omap4_l3 {
+	struct device *dev;
+	struct clk *ick;
+
+	/* memory base */
+	void __iomem *l3_base[L3_MODULES];
+
+	int debug_irq;
+	int app_irq;
+};
+#endif
diff --git a/drivers/bus/omap_l3_smx.c b/drivers/bus/omap_l3_smx.c
new file mode 100644
index 0000000..acc2164
--- /dev/null
+++ b/drivers/bus/omap_l3_smx.c
@@ -0,0 +1,297 @@
+/*
+ * OMAP3XXX L3 Interconnect Driver
+ *
+ * Copyright (C) 2011 Texas Corporation
+ *	Felipe Balbi <balbi@ti.com>
+ *	Santosh Shilimkar <santosh.shilimkar@ti.com>
+ *	Sricharan <r.sricharan@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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include "omap_l3_smx.h"
+
+static inline u64 omap3_l3_readll(void __iomem *base, u16 reg)
+{
+	return __raw_readll(base + reg);
+}
+
+static inline void omap3_l3_writell(void __iomem *base, u16 reg, u64 value)
+{
+	__raw_writell(value, base + reg);
+}
+
+static inline enum omap3_l3_code omap3_l3_decode_error_code(u64 error)
+{
+	return (error & 0x0f000000) >> L3_ERROR_LOG_CODE;
+}
+
+static inline u32 omap3_l3_decode_addr(u64 error_addr)
+{
+	return error_addr & 0xffffffff;
+}
+
+static inline unsigned omap3_l3_decode_cmd(u64 error)
+{
+	return (error & 0x07) >> L3_ERROR_LOG_CMD;
+}
+
+static inline enum omap3_l3_initiator_id omap3_l3_decode_initid(u64 error)
+{
+	return (error & 0xff00) >> L3_ERROR_LOG_INITID;
+}
+
+static inline unsigned omap3_l3_decode_req_info(u64 error)
+{
+	return (error >> 32) & 0xffff;
+}
+
+static char *omap3_l3_code_string(u8 code)
+{
+	switch (code) {
+	case OMAP_L3_CODE_NOERROR:
+		return "No Error";
+	case OMAP_L3_CODE_UNSUP_CMD:
+		return "Unsupported Command";
+	case OMAP_L3_CODE_ADDR_HOLE:
+		return "Address Hole";
+	case OMAP_L3_CODE_PROTECT_VIOLATION:
+		return "Protection Violation";
+	case OMAP_L3_CODE_IN_BAND_ERR:
+		return "In-band Error";
+	case OMAP_L3_CODE_REQ_TOUT_NOT_ACCEPT:
+		return "Request Timeout Not Accepted";
+	case OMAP_L3_CODE_REQ_TOUT_NO_RESP:
+		return "Request Timeout, no response";
+	default:
+		return "UNKNOWN error";
+	}
+}
+
+static char *omap3_l3_initiator_string(u8 initid)
+{
+	switch (initid) {
+	case OMAP_L3_LCD:
+		return "LCD";
+	case OMAP_L3_SAD2D:
+		return "SAD2D";
+	case OMAP_L3_IA_MPU_SS_1:
+	case OMAP_L3_IA_MPU_SS_2:
+	case OMAP_L3_IA_MPU_SS_3:
+	case OMAP_L3_IA_MPU_SS_4:
+	case OMAP_L3_IA_MPU_SS_5:
+		return "MPU";
+	case OMAP_L3_IA_IVA_SS_1:
+	case OMAP_L3_IA_IVA_SS_2:
+	case OMAP_L3_IA_IVA_SS_3:
+		return "IVA_SS";
+	case OMAP_L3_IA_IVA_SS_DMA_1:
+	case OMAP_L3_IA_IVA_SS_DMA_2:
+	case OMAP_L3_IA_IVA_SS_DMA_3:
+	case OMAP_L3_IA_IVA_SS_DMA_4:
+	case OMAP_L3_IA_IVA_SS_DMA_5:
+	case OMAP_L3_IA_IVA_SS_DMA_6:
+		return "IVA_SS_DMA";
+	case OMAP_L3_IA_SGX:
+		return "SGX";
+	case OMAP_L3_IA_CAM_1:
+	case OMAP_L3_IA_CAM_2:
+	case OMAP_L3_IA_CAM_3:
+		return "CAM";
+	case OMAP_L3_IA_DAP:
+		return "DAP";
+	case OMAP_L3_SDMA_WR_1:
+	case OMAP_L3_SDMA_WR_2:
+		return "SDMA_WR";
+	case OMAP_L3_SDMA_RD_1:
+	case OMAP_L3_SDMA_RD_2:
+	case OMAP_L3_SDMA_RD_3:
+	case OMAP_L3_SDMA_RD_4:
+		return "SDMA_RD";
+	case OMAP_L3_USBOTG:
+		return "USB_OTG";
+	case OMAP_L3_USBHOST:
+		return "USB_HOST";
+	default:
+		return "UNKNOWN Initiator";
+	}
+}
+
+/*
+ * omap3_l3_block_irq - handles a register block's irq
+ * @l3: struct omap3_l3 *
+ * @base: register block base address
+ * @error: L3_ERROR_LOG register of our block
+ *
+ * Called in hard-irq context. Caller should take care of locking
+ *
+ * OMAP36xx TRM gives, on page 2001, Figure 9-10, the Typical Error
+ * Analysis Sequence, we are following that sequence here, please
+ * refer to that Figure for more information on the subject.
+ */
+static irqreturn_t omap3_l3_block_irq(struct omap3_l3 *l3,
+					u64 error, int error_addr)
+{
+	u8 code = omap3_l3_decode_error_code(error);
+	u8 initid = omap3_l3_decode_initid(error);
+	u8 multi = error & L3_ERROR_LOG_MULTI;
+	u32 address = omap3_l3_decode_addr(error_addr);
+
+	pr_err("%s seen by %s %s at address %x\n",
+			omap3_l3_code_string(code),
+			omap3_l3_initiator_string(initid),
+			multi ? "Multiple Errors" : "", address);
+	WARN_ON(1);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t omap3_l3_app_irq(int irq, void *_l3)
+{
+	struct omap3_l3 *l3 = _l3;
+	u64 status, clear;
+	u64 error;
+	u64 error_addr;
+	u64 err_source = 0;
+	void __iomem *base;
+	int int_type;
+	irqreturn_t ret = IRQ_NONE;
+
+	int_type = irq == l3->app_irq ? L3_APPLICATION_ERROR : L3_DEBUG_ERROR;
+	if (!int_type) {
+		status = omap3_l3_readll(l3->rt, L3_SI_FLAG_STATUS_0);
+		/*
+		 * if we have a timeout error, there's nothing we can
+		 * do besides rebooting the board. So let's BUG on any
+		 * of such errors and handle the others. timeout error
+		 * is severe and not expected to occur.
+		 */
+		BUG_ON(status & L3_STATUS_0_TIMEOUT_MASK);
+	} else {
+		status = omap3_l3_readll(l3->rt, L3_SI_FLAG_STATUS_1);
+		/* No timeout error for debug sources */
+	}
+
+	/* identify the error source */
+	err_source = __ffs(status);
+
+	base = l3->rt + omap3_l3_bases[int_type][err_source];
+	error = omap3_l3_readll(base, L3_ERROR_LOG);
+	if (error) {
+		error_addr = omap3_l3_readll(base, L3_ERROR_LOG_ADDR);
+		ret |= omap3_l3_block_irq(l3, error, error_addr);
+	}
+
+	/* Clear the status register */
+	clear = (L3_AGENT_STATUS_CLEAR_IA << int_type) |
+		L3_AGENT_STATUS_CLEAR_TA;
+	omap3_l3_writell(base, L3_AGENT_STATUS, clear);
+
+	/* clear the error log register */
+	omap3_l3_writell(base, L3_ERROR_LOG, error);
+
+	return ret;
+}
+
+static int __init omap3_l3_probe(struct platform_device *pdev)
+{
+	struct omap3_l3 *l3;
+	struct resource *res;
+	int ret;
+
+	l3 = kzalloc(sizeof(*l3), GFP_KERNEL);
+	if (!l3)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, l3);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "couldn't find resource\n");
+		ret = -ENODEV;
+		goto err0;
+	}
+	l3->rt = ioremap(res->start, resource_size(res));
+	if (!l3->rt) {
+		dev_err(&pdev->dev, "ioremap failed\n");
+		ret = -ENOMEM;
+		goto err0;
+	}
+
+	l3->debug_irq = platform_get_irq(pdev, 0);
+	ret = request_irq(l3->debug_irq, omap3_l3_app_irq,
+		IRQF_DISABLED | IRQF_TRIGGER_RISING,
+		"l3-debug-irq", l3);
+	if (ret) {
+		dev_err(&pdev->dev, "couldn't request debug irq\n");
+		goto err1;
+	}
+
+	l3->app_irq = platform_get_irq(pdev, 1);
+	ret = request_irq(l3->app_irq, omap3_l3_app_irq,
+		IRQF_DISABLED | IRQF_TRIGGER_RISING,
+		"l3-app-irq", l3);
+	if (ret) {
+		dev_err(&pdev->dev, "couldn't request app irq\n");
+		goto err2;
+	}
+
+	return 0;
+
+err2:
+	free_irq(l3->debug_irq, l3);
+err1:
+	iounmap(l3->rt);
+err0:
+	kfree(l3);
+	return ret;
+}
+
+static int __exit omap3_l3_remove(struct platform_device *pdev)
+{
+	struct omap3_l3         *l3 = platform_get_drvdata(pdev);
+
+	free_irq(l3->app_irq, l3);
+	free_irq(l3->debug_irq, l3);
+	iounmap(l3->rt);
+	kfree(l3);
+
+	return 0;
+}
+
+static struct platform_driver omap3_l3_driver = {
+	.remove         = __exit_p(omap3_l3_remove),
+	.driver         = {
+	.name   = "omap_l3_smx",
+	},
+};
+
+static int __init omap3_l3_init(void)
+{
+	return platform_driver_probe(&omap3_l3_driver, omap3_l3_probe);
+}
+postcore_initcall_sync(omap3_l3_init);
+
+static void __exit omap3_l3_exit(void)
+{
+	platform_driver_unregister(&omap3_l3_driver);
+}
+module_exit(omap3_l3_exit);
diff --git a/drivers/bus/omap_l3_smx.h b/drivers/bus/omap_l3_smx.h
new file mode 100644
index 0000000..4f3cebc
--- /dev/null
+++ b/drivers/bus/omap_l3_smx.h
@@ -0,0 +1,338 @@
+/*
+ * OMAP3XXX L3 Interconnect Driver header
+ *
+ * Copyright (C) 2011 Texas Corporation
+ *	Felipe Balbi <balbi@ti.com>
+ *	Santosh Shilimkar <santosh.shilimkar@ti.com>
+ *	sricharan <r.sricharan@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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 __ARCH_ARM_MACH_OMAP2_L3_INTERCONNECT_3XXX_H
+#define __ARCH_ARM_MACH_OMAP2_L3_INTERCONNECT_3XXX_H
+
+/* Register definitions. All 64-bit wide */
+#define L3_COMPONENT			0x000
+#define L3_CORE				0x018
+#define L3_AGENT_CONTROL		0x020
+#define L3_AGENT_STATUS			0x028
+#define L3_ERROR_LOG			0x058
+
+#define L3_ERROR_LOG_MULTI		(1 << 31)
+#define L3_ERROR_LOG_SECONDARY		(1 << 30)
+
+#define L3_ERROR_LOG_ADDR		0x060
+
+/* Register definitions for Sideband Interconnect */
+#define L3_SI_CONTROL			0x020
+#define L3_SI_FLAG_STATUS_0		0x510
+
+static const u64 shift = 1;
+
+#define L3_STATUS_0_MPUIA_BRST		(shift << 0)
+#define L3_STATUS_0_MPUIA_RSP		(shift << 1)
+#define L3_STATUS_0_MPUIA_INBAND	(shift << 2)
+#define L3_STATUS_0_IVAIA_BRST		(shift << 6)
+#define L3_STATUS_0_IVAIA_RSP		(shift << 7)
+#define L3_STATUS_0_IVAIA_INBAND	(shift << 8)
+#define L3_STATUS_0_SGXIA_BRST		(shift << 9)
+#define L3_STATUS_0_SGXIA_RSP		(shift << 10)
+#define L3_STATUS_0_SGXIA_MERROR	(shift << 11)
+#define L3_STATUS_0_CAMIA_BRST		(shift << 12)
+#define L3_STATUS_0_CAMIA_RSP		(shift << 13)
+#define L3_STATUS_0_CAMIA_INBAND	(shift << 14)
+#define L3_STATUS_0_DISPIA_BRST		(shift << 15)
+#define L3_STATUS_0_DISPIA_RSP		(shift << 16)
+#define L3_STATUS_0_DMARDIA_BRST	(shift << 18)
+#define L3_STATUS_0_DMARDIA_RSP		(shift << 19)
+#define L3_STATUS_0_DMAWRIA_BRST	(shift << 21)
+#define L3_STATUS_0_DMAWRIA_RSP		(shift << 22)
+#define L3_STATUS_0_USBOTGIA_BRST	(shift << 24)
+#define L3_STATUS_0_USBOTGIA_RSP	(shift << 25)
+#define L3_STATUS_0_USBOTGIA_INBAND	(shift << 26)
+#define L3_STATUS_0_USBHOSTIA_BRST	(shift << 27)
+#define L3_STATUS_0_USBHOSTIA_INBAND	(shift << 28)
+#define L3_STATUS_0_SMSTA_REQ		(shift << 48)
+#define L3_STATUS_0_GPMCTA_REQ		(shift << 49)
+#define L3_STATUS_0_OCMRAMTA_REQ	(shift << 50)
+#define L3_STATUS_0_OCMROMTA_REQ	(shift << 51)
+#define L3_STATUS_0_IVATA_REQ		(shift << 54)
+#define L3_STATUS_0_SGXTA_REQ		(shift << 55)
+#define L3_STATUS_0_SGXTA_SERROR	(shift << 56)
+#define L3_STATUS_0_GPMCTA_SERROR	(shift << 57)
+#define L3_STATUS_0_L4CORETA_REQ	(shift << 58)
+#define L3_STATUS_0_L4PERTA_REQ		(shift << 59)
+#define L3_STATUS_0_L4EMUTA_REQ		(shift << 60)
+#define L3_STATUS_0_MAD2DTA_REQ		(shift << 61)
+
+#define L3_STATUS_0_TIMEOUT_MASK	(L3_STATUS_0_MPUIA_BRST		\
+					| L3_STATUS_0_MPUIA_RSP		\
+					| L3_STATUS_0_IVAIA_BRST	\
+					| L3_STATUS_0_IVAIA_RSP		\
+					| L3_STATUS_0_SGXIA_BRST	\
+					| L3_STATUS_0_SGXIA_RSP		\
+					| L3_STATUS_0_CAMIA_BRST	\
+					| L3_STATUS_0_CAMIA_RSP		\
+					| L3_STATUS_0_DISPIA_BRST	\
+					| L3_STATUS_0_DISPIA_RSP	\
+					| L3_STATUS_0_DMARDIA_BRST	\
+					| L3_STATUS_0_DMARDIA_RSP	\
+					| L3_STATUS_0_DMAWRIA_BRST	\
+					| L3_STATUS_0_DMAWRIA_RSP	\
+					| L3_STATUS_0_USBOTGIA_BRST	\
+					| L3_STATUS_0_USBOTGIA_RSP	\
+					| L3_STATUS_0_USBHOSTIA_BRST	\
+					| L3_STATUS_0_SMSTA_REQ		\
+					| L3_STATUS_0_GPMCTA_REQ	\
+					| L3_STATUS_0_OCMRAMTA_REQ	\
+					| L3_STATUS_0_OCMROMTA_REQ	\
+					| L3_STATUS_0_IVATA_REQ		\
+					| L3_STATUS_0_SGXTA_REQ		\
+					| L3_STATUS_0_L4CORETA_REQ	\
+					| L3_STATUS_0_L4PERTA_REQ	\
+					| L3_STATUS_0_L4EMUTA_REQ	\
+					| L3_STATUS_0_MAD2DTA_REQ)
+
+#define L3_SI_FLAG_STATUS_1		0x530
+
+#define L3_STATUS_1_MPU_DATAIA		(1 << 0)
+#define L3_STATUS_1_DAPIA0		(1 << 3)
+#define L3_STATUS_1_DAPIA1		(1 << 4)
+#define L3_STATUS_1_IVAIA		(1 << 6)
+
+#define L3_PM_ERROR_LOG			0x020
+#define L3_PM_CONTROL			0x028
+#define L3_PM_ERROR_CLEAR_SINGLE	0x030
+#define L3_PM_ERROR_CLEAR_MULTI		0x038
+#define L3_PM_REQ_INFO_PERMISSION(n)	(0x048 + (0x020 * n))
+#define L3_PM_READ_PERMISSION(n)	(0x050 + (0x020 * n))
+#define L3_PM_WRITE_PERMISSION(n)	(0x058 + (0x020 * n))
+#define L3_PM_ADDR_MATCH(n)		(0x060 + (0x020 * n))
+
+/* L3 error log bit fields. Common for IA and TA */
+#define L3_ERROR_LOG_CODE		24
+#define L3_ERROR_LOG_INITID		8
+#define L3_ERROR_LOG_CMD		0
+
+/* L3 agent status bit fields. */
+#define L3_AGENT_STATUS_CLEAR_IA	0x10000000
+#define L3_AGENT_STATUS_CLEAR_TA	0x01000000
+
+#define OMAP34xx_IRQ_L3_APP		10
+#define L3_APPLICATION_ERROR		0x0
+#define L3_DEBUG_ERROR			0x1
+
+enum omap3_l3_initiator_id {
+	/* LCD has 1 ID */
+	OMAP_L3_LCD = 29,
+	/* SAD2D has 1 ID */
+	OMAP_L3_SAD2D = 28,
+	/* MPU has 5 IDs */
+	OMAP_L3_IA_MPU_SS_1 = 27,
+	OMAP_L3_IA_MPU_SS_2 = 26,
+	OMAP_L3_IA_MPU_SS_3 = 25,
+	OMAP_L3_IA_MPU_SS_4 = 24,
+	OMAP_L3_IA_MPU_SS_5 = 23,
+	/* IVA2.2 SS has 3 IDs*/
+	OMAP_L3_IA_IVA_SS_1 = 22,
+	OMAP_L3_IA_IVA_SS_2 = 21,
+	OMAP_L3_IA_IVA_SS_3 = 20,
+	/* IVA 2.2 SS DMA has 6 IDS */
+	OMAP_L3_IA_IVA_SS_DMA_1 = 19,
+	OMAP_L3_IA_IVA_SS_DMA_2 = 18,
+	OMAP_L3_IA_IVA_SS_DMA_3 = 17,
+	OMAP_L3_IA_IVA_SS_DMA_4 = 16,
+	OMAP_L3_IA_IVA_SS_DMA_5 = 15,
+	OMAP_L3_IA_IVA_SS_DMA_6 = 14,
+	/* SGX has 1 ID */
+	OMAP_L3_IA_SGX = 13,
+	/* CAM has 3 ID */
+	OMAP_L3_IA_CAM_1 = 12,
+	OMAP_L3_IA_CAM_2 = 11,
+	OMAP_L3_IA_CAM_3 = 10,
+	/* DAP has 1 ID */
+	OMAP_L3_IA_DAP = 9,
+	/* SDMA WR has 2 IDs */
+	OMAP_L3_SDMA_WR_1 = 8,
+	OMAP_L3_SDMA_WR_2 = 7,
+	/* SDMA RD has 4 IDs */
+	OMAP_L3_SDMA_RD_1 = 6,
+	OMAP_L3_SDMA_RD_2 = 5,
+	OMAP_L3_SDMA_RD_3 = 4,
+	OMAP_L3_SDMA_RD_4 = 3,
+	/* HSUSB OTG has 1 ID */
+	OMAP_L3_USBOTG = 2,
+	/* HSUSB HOST has 1 ID */
+	OMAP_L3_USBHOST = 1,
+};
+
+enum omap3_l3_code {
+	OMAP_L3_CODE_NOERROR = 0,
+	OMAP_L3_CODE_UNSUP_CMD = 1,
+	OMAP_L3_CODE_ADDR_HOLE = 2,
+	OMAP_L3_CODE_PROTECT_VIOLATION = 3,
+	OMAP_L3_CODE_IN_BAND_ERR = 4,
+	/* codes 5 and 6 are reserved */
+	OMAP_L3_CODE_REQ_TOUT_NOT_ACCEPT = 7,
+	OMAP_L3_CODE_REQ_TOUT_NO_RESP = 8,
+	/* codes 9 - 15 are also reserved */
+};
+
+struct omap3_l3 {
+	struct device *dev;
+	struct clk *ick;
+
+	/* memory base*/
+	void __iomem *rt;
+
+	int debug_irq;
+	int app_irq;
+
+	/* true when and inband functional error occurs */
+	unsigned inband:1;
+};
+
+/* offsets for l3 agents in order with the Flag status register */
+static unsigned int omap3_l3_app_bases[] = {
+	/* MPU IA */
+	0x1400,
+	0x1400,
+	0x1400,
+	/* RESERVED */
+	0,
+	0,
+	0,
+	/* IVA 2.2 IA */
+	0x1800,
+	0x1800,
+	0x1800,
+	/* SGX IA */
+	0x1c00,
+	0x1c00,
+	/* RESERVED */
+	0,
+	/* CAMERA IA */
+	0x5800,
+	0x5800,
+	0x5800,
+	/* DISPLAY IA */
+	0x5400,
+	0x5400,
+	/* RESERVED */
+	0,
+	/*SDMA RD IA */
+	0x4c00,
+	0x4c00,
+	/* RESERVED */
+	0,
+	/* SDMA WR IA */
+	0x5000,
+	0x5000,
+	/* RESERVED */
+	0,
+	/* USB OTG IA */
+	0x4400,
+	0x4400,
+	0x4400,
+	/* USB HOST IA */
+	0x4000,
+	0x4000,
+	/* RESERVED */
+	0,
+	0,
+	0,
+	0,
+	/* SAD2D IA */
+	0x3000,
+	0x3000,
+	0x3000,
+	/* RESERVED */
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+	/* SMA TA */
+	0x2000,
+	/* GPMC TA */
+	0x2400,
+	/* OCM RAM TA */
+	0x2800,
+	/* OCM ROM TA */
+	0x2C00,
+	/* L4 CORE TA */
+	0x6800,
+	/* L4 PER TA */
+	0x6c00,
+	/* IVA 2.2 TA */
+	0x6000,
+	/* SGX TA */
+	0x6400,
+	/* L4 EMU TA */
+	0x7000,
+	/* GPMC TA */
+	0x2400,
+	/* L4 CORE TA */
+	0x6800,
+	/* L4 PER TA */
+	0x6c00,
+	/* L4 EMU TA */
+	0x7000,
+	/* MAD2D TA */
+	0x3400,
+	/* RESERVED */
+	0,
+	0,
+};
+
+static unsigned int omap3_l3_debug_bases[] = {
+	/* MPU DATA IA */
+	0x1400,
+	/* RESERVED */
+	0,
+	0,
+	/* DAP IA */
+	0x5c00,
+	0x5c00,
+	/* RESERVED */
+	0,
+	/* IVA 2.2 IA */
+	0x1800,
+	/* REST RESERVED */
+};
+
+static u32 *omap3_l3_bases[] = {
+	omap3_l3_app_bases,
+	omap3_l3_debug_bases,
+};
+
+/*
+ * REVISIT define __raw_readll/__raw_writell here, but move them to
+ * <asm/io.h> at some point
+ */
+#define __raw_writell(v, a)	(__chk_io_ptr(a), \
+				*(volatile u64 __force *)(a) = (v))
+#define __raw_readll(a)		(__chk_io_ptr(a), \
+				*(volatile u64 __force *)(a))
+
+#endif
diff --git a/drivers/cdrom/gdrom.c b/drivers/cdrom/gdrom.c
index 3ceaf00..75d485a 100644
--- a/drivers/cdrom/gdrom.c
+++ b/drivers/cdrom/gdrom.c
@@ -840,7 +840,7 @@ probe_fail_no_mem:
 
 static int __devexit remove_gdrom(struct platform_device *devptr)
 {
-	flush_work_sync(&work);
+	flush_work(&work);
 	blk_cleanup_queue(gd.gdrom_rq);
 	free_irq(HW_EVENT_GDROM_CMD, &gd);
 	free_irq(HW_EVENT_GDROM_DMA, &gd);
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index ea6f632..72bedad 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -418,8 +418,8 @@ config APPLICOM
 	  If unsure, say N.
 
 config SONYPI
-	tristate "Sony Vaio Programmable I/O Control Device support (EXPERIMENTAL)"
-	depends on EXPERIMENTAL && X86 && PCI && INPUT && !64BIT
+	tristate "Sony Vaio Programmable I/O Control Device support"
+	depends on X86 && PCI && INPUT && !64BIT
 	---help---
 	  This driver enables access to the Sony Programmable I/O Control
 	  Device which can be found in many (all ?) Sony Vaio laptops.
@@ -566,7 +566,7 @@ source "drivers/char/tpm/Kconfig"
 
 config TELCLOCK
 	tristate "Telecom clock driver for ATCA SBC"
-	depends on EXPERIMENTAL && X86
+	depends on X86
 	default n
 	help
 	  The telecom clock device is specific to the MPCBL0010 and MPCBL0050
diff --git a/drivers/char/agp/sgi-agp.c b/drivers/char/agp/sgi-agp.c
index 1920003..3a5af2f 100644
--- a/drivers/char/agp/sgi-agp.c
+++ b/drivers/char/agp/sgi-agp.c
@@ -289,12 +289,11 @@ static int __devinit agp_sgi_init(void)
 
 	j = 0;
 	list_for_each_entry(info, &tioca_list, ca_list) {
-		struct list_head *tmp;
 		if (list_empty(info->ca_devices))
 			continue;
-		list_for_each(tmp, info->ca_devices) {
+		list_for_each_entry(pdev, info->ca_devices, bus_list) {
 			u8 cap_ptr;
-			pdev = pci_dev_b(tmp);
+
 			if (pdev->class != (PCI_CLASS_DISPLAY_VGA << 8))
 				continue;
 			cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig
index 7c0d391..c58ea9b 100644
--- a/drivers/char/hw_random/Kconfig
+++ b/drivers/char/hw_random/Kconfig
@@ -127,12 +127,12 @@ config HW_RANDOM_VIA
 	  If unsure, say Y.
 
 config HW_RANDOM_IXP4XX
-	tristate "Intel IXP4xx NPU HW Random Number Generator support"
+	tristate "Intel IXP4xx NPU HW Pseudo-Random Number Generator support"
 	depends on HW_RANDOM && ARCH_IXP4XX
 	default HW_RANDOM
 	---help---
-	  This driver provides kernel-side support for the Random
-	  Number Generator hardware found on the Intel IXP4xx NPU.
+	  This driver provides kernel-side support for the Pseudo-Random
+	  Number Generator hardware found on the Intel IXP45x/46x NPU.
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called ixp4xx-rng.
@@ -289,3 +289,16 @@ config HW_RANDOM_EXYNOS
 	  module will be called exynos-rng.
 
 	  If unsure, say Y.
+
+config HW_RANDOM_TPM
+	tristate "TPM HW Random Number Generator support"
+	depends on HW_RANDOM && TCG_TPM
+	default HW_RANDOM
+	---help---
+	  This driver provides kernel-side support for the Random Number
+	  Generator in the Trusted Platform Module
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called tpm-rng.
+
+	  If unsure, say Y.
diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile
index 39a757c..1fd7eec 100644
--- a/drivers/char/hw_random/Makefile
+++ b/drivers/char/hw_random/Makefile
@@ -25,3 +25,4 @@ obj-$(CONFIG_HW_RANDOM_PICOXCELL) += picoxcell-rng.o
 obj-$(CONFIG_HW_RANDOM_PPC4XX) += ppc4xx-rng.o
 obj-$(CONFIG_HW_RANDOM_PSERIES) += pseries-rng.o
 obj-$(CONFIG_HW_RANDOM_EXYNOS)	+= exynos-rng.o
+obj-$(CONFIG_HW_RANDOM_TPM) += tpm-rng.o
diff --git a/drivers/char/hw_random/ixp4xx-rng.c b/drivers/char/hw_random/ixp4xx-rng.c
index 263567f..beec162 100644
--- a/drivers/char/hw_random/ixp4xx-rng.c
+++ b/drivers/char/hw_random/ixp4xx-rng.c
@@ -45,6 +45,9 @@ static int __init ixp4xx_rng_init(void)
 	void __iomem * rng_base;
 	int err;
 
+	if (!cpu_is_ixp46x()) /* includes IXP455 */
+		return -ENOSYS;
+
 	rng_base = ioremap(0x70002100, 4);
 	if (!rng_base)
 		return -ENOMEM;
@@ -68,5 +71,5 @@ module_init(ixp4xx_rng_init);
 module_exit(ixp4xx_rng_exit);
 
 MODULE_AUTHOR("Deepak Saxena <dsaxena@plexity.net>");
-MODULE_DESCRIPTION("H/W Random Number Generator (RNG) driver for IXP4xx");
+MODULE_DESCRIPTION("H/W Pseudo-Random Number Generator (RNG) driver for IXP45x/46x");
 MODULE_LICENSE("GPL");
diff --git a/drivers/char/hw_random/mxc-rnga.c b/drivers/char/hw_random/mxc-rnga.c
index 85074de..f05d857 100644
--- a/drivers/char/hw_random/mxc-rnga.c
+++ b/drivers/char/hw_random/mxc-rnga.c
@@ -59,16 +59,21 @@
 #define RNGA_STATUS_LAST_READ_STATUS	0x00000002
 #define RNGA_STATUS_SECURITY_VIOLATION	0x00000001
 
-static struct platform_device *rng_dev;
+struct mxc_rng {
+	struct device *dev;
+	struct hwrng rng;
+	void __iomem *mem;
+	struct clk *clk;
+};
 
 static int mxc_rnga_data_present(struct hwrng *rng, int wait)
 {
-	void __iomem *rng_base = (void __iomem *)rng->priv;
 	int i;
+	struct mxc_rng *mxc_rng = container_of(rng, struct mxc_rng, rng);
 
 	for (i = 0; i < 20; i++) {
 		/* how many random numbers are in FIFO? [0-16] */
-		int level = (__raw_readl(rng_base + RNGA_STATUS) &
+		int level = (__raw_readl(mxc_rng->mem + RNGA_STATUS) &
 				RNGA_STATUS_LEVEL_MASK) >> 8;
 		if (level || !wait)
 			return !!level;
@@ -81,20 +86,20 @@ static int mxc_rnga_data_read(struct hwrng *rng, u32 * data)
 {
 	int err;
 	u32 ctrl;
-	void __iomem *rng_base = (void __iomem *)rng->priv;
+	struct mxc_rng *mxc_rng = container_of(rng, struct mxc_rng, rng);
 
 	/* retrieve a random number from FIFO */
-	*data = __raw_readl(rng_base + RNGA_OUTPUT_FIFO);
+	*data = __raw_readl(mxc_rng->mem + RNGA_OUTPUT_FIFO);
 
 	/* some error while reading this random number? */
-	err = __raw_readl(rng_base + RNGA_STATUS) & RNGA_STATUS_ERROR_INT;
+	err = __raw_readl(mxc_rng->mem + RNGA_STATUS) & RNGA_STATUS_ERROR_INT;
 
 	/* if error: clear error interrupt, but doesn't return random number */
 	if (err) {
-		dev_dbg(&rng_dev->dev, "Error while reading random number!\n");
-		ctrl = __raw_readl(rng_base + RNGA_CONTROL);
+		dev_dbg(mxc_rng->dev, "Error while reading random number!\n");
+		ctrl = __raw_readl(mxc_rng->mem + RNGA_CONTROL);
 		__raw_writel(ctrl | RNGA_CONTROL_CLEAR_INT,
-					rng_base + RNGA_CONTROL);
+					mxc_rng->mem + RNGA_CONTROL);
 		return 0;
 	} else
 		return 4;
@@ -103,22 +108,22 @@ static int mxc_rnga_data_read(struct hwrng *rng, u32 * data)
 static int mxc_rnga_init(struct hwrng *rng)
 {
 	u32 ctrl, osc;
-	void __iomem *rng_base = (void __iomem *)rng->priv;
+	struct mxc_rng *mxc_rng = container_of(rng, struct mxc_rng, rng);
 
 	/* wake up */
-	ctrl = __raw_readl(rng_base + RNGA_CONTROL);
-	__raw_writel(ctrl & ~RNGA_CONTROL_SLEEP, rng_base + RNGA_CONTROL);
+	ctrl = __raw_readl(mxc_rng->mem + RNGA_CONTROL);
+	__raw_writel(ctrl & ~RNGA_CONTROL_SLEEP, mxc_rng->mem + RNGA_CONTROL);
 
 	/* verify if oscillator is working */
-	osc = __raw_readl(rng_base + RNGA_STATUS);
+	osc = __raw_readl(mxc_rng->mem + RNGA_STATUS);
 	if (osc & RNGA_STATUS_OSC_DEAD) {
-		dev_err(&rng_dev->dev, "RNGA Oscillator is dead!\n");
+		dev_err(mxc_rng->dev, "RNGA Oscillator is dead!\n");
 		return -ENODEV;
 	}
 
 	/* go running */
-	ctrl = __raw_readl(rng_base + RNGA_CONTROL);
-	__raw_writel(ctrl | RNGA_CONTROL_GO, rng_base + RNGA_CONTROL);
+	ctrl = __raw_readl(mxc_rng->mem + RNGA_CONTROL);
+	__raw_writel(ctrl | RNGA_CONTROL_GO, mxc_rng->mem + RNGA_CONTROL);
 
 	return 0;
 }
@@ -126,40 +131,40 @@ static int mxc_rnga_init(struct hwrng *rng)
 static void mxc_rnga_cleanup(struct hwrng *rng)
 {
 	u32 ctrl;
-	void __iomem *rng_base = (void __iomem *)rng->priv;
+	struct mxc_rng *mxc_rng = container_of(rng, struct mxc_rng, rng);
 
-	ctrl = __raw_readl(rng_base + RNGA_CONTROL);
+	ctrl = __raw_readl(mxc_rng->mem + RNGA_CONTROL);
 
 	/* stop rnga */
-	__raw_writel(ctrl & ~RNGA_CONTROL_GO, rng_base + RNGA_CONTROL);
+	__raw_writel(ctrl & ~RNGA_CONTROL_GO, mxc_rng->mem + RNGA_CONTROL);
 }
 
-static struct hwrng mxc_rnga = {
-	.name = "mxc-rnga",
-	.init = mxc_rnga_init,
-	.cleanup = mxc_rnga_cleanup,
-	.data_present = mxc_rnga_data_present,
-	.data_read = mxc_rnga_data_read
-};
-
 static int __init mxc_rnga_probe(struct platform_device *pdev)
 {
 	int err = -ENODEV;
-	struct clk *clk;
 	struct resource *res, *mem;
-	void __iomem *rng_base = NULL;
-
-	if (rng_dev)
-		return -EBUSY;
-
-	clk = clk_get(&pdev->dev, "rng");
-	if (IS_ERR(clk)) {
+	struct mxc_rng *mxc_rng;
+
+	mxc_rng = devm_kzalloc(&pdev->dev, sizeof(struct mxc_rng),
+					GFP_KERNEL);
+	if (!mxc_rng)
+		return -ENOMEM;
+
+	mxc_rng->dev = &pdev->dev;
+	mxc_rng->rng.name = "mxc-rnga";
+	mxc_rng->rng.init = mxc_rnga_init;
+	mxc_rng->rng.cleanup = mxc_rnga_cleanup,
+	mxc_rng->rng.data_present = mxc_rnga_data_present,
+	mxc_rng->rng.data_read = mxc_rnga_data_read,
+
+	mxc_rng->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(mxc_rng->clk)) {
 		dev_err(&pdev->dev, "Could not get rng_clk!\n");
-		err = PTR_ERR(clk);
+		err = PTR_ERR(mxc_rng->clk);
 		goto out;
 	}
 
-	clk_enable(clk);
+	clk_prepare_enable(mxc_rng->clk);
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res) {
@@ -173,36 +178,27 @@ static int __init mxc_rnga_probe(struct platform_device *pdev)
 		goto err_region;
 	}
 
-	rng_base = ioremap(res->start, resource_size(res));
-	if (!rng_base) {
+	mxc_rng->mem = ioremap(res->start, resource_size(res));
+	if (!mxc_rng->mem) {
 		err = -ENOMEM;
 		goto err_ioremap;
 	}
 
-	mxc_rnga.priv = (unsigned long)rng_base;
-
-	err = hwrng_register(&mxc_rnga);
+	err = hwrng_register(&mxc_rng->rng);
 	if (err) {
 		dev_err(&pdev->dev, "MXC RNGA registering failed (%d)\n", err);
-		goto err_register;
+		goto err_ioremap;
 	}
 
-	rng_dev = pdev;
-
 	dev_info(&pdev->dev, "MXC RNGA Registered.\n");
 
 	return 0;
 
-err_register:
-	iounmap(rng_base);
-	rng_base = NULL;
-
 err_ioremap:
 	release_mem_region(res->start, resource_size(res));
 
 err_region:
-	clk_disable(clk);
-	clk_put(clk);
+	clk_disable_unprepare(mxc_rng->clk);
 
 out:
 	return err;
@@ -211,17 +207,15 @@ out:
 static int __exit mxc_rnga_remove(struct platform_device *pdev)
 {
 	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	void __iomem *rng_base = (void __iomem *)mxc_rnga.priv;
-	struct clk *clk = clk_get(&pdev->dev, "rng");
+	struct mxc_rng *mxc_rng = platform_get_drvdata(pdev);
 
-	hwrng_unregister(&mxc_rnga);
+	hwrng_unregister(&mxc_rng->rng);
 
-	iounmap(rng_base);
+	iounmap(mxc_rng->mem);
 
 	release_mem_region(res->start, resource_size(res));
 
-	clk_disable(clk);
-	clk_put(clk);
+	clk_disable_unprepare(mxc_rng->clk);
 
 	return 0;
 }
diff --git a/drivers/char/hw_random/octeon-rng.c b/drivers/char/hw_random/octeon-rng.c
index 0943edc..5c34c09 100644
--- a/drivers/char/hw_random/octeon-rng.c
+++ b/drivers/char/hw_random/octeon-rng.c
@@ -75,42 +75,35 @@ static int __devinit octeon_rng_probe(struct platform_device *pdev)
 
 	res_ports = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res_ports)
-		goto err_ports;
+		return -ENOENT;
 
 	res_result = platform_get_resource(pdev, IORESOURCE_MEM, 1);
 	if (!res_result)
-		goto err_ports;
+		return -ENOENT;
 
 
 	rng->control_status = devm_ioremap_nocache(&pdev->dev,
 						   res_ports->start,
 						   sizeof(u64));
 	if (!rng->control_status)
-		goto err_ports;
+		return -ENOENT;
 
 	rng->result = devm_ioremap_nocache(&pdev->dev,
 					   res_result->start,
 					   sizeof(u64));
 	if (!rng->result)
-		goto err_r;
+		return -ENOENT;
 
 	rng->ops = ops;
 
 	dev_set_drvdata(&pdev->dev, &rng->ops);
 	ret = hwrng_register(&rng->ops);
 	if (ret)
-		goto err;
+		return -ENOENT;
 
 	dev_info(&pdev->dev, "Octeon Random Number Generator\n");
 
 	return 0;
-err:
-	devm_iounmap(&pdev->dev, rng->control_status);
-err_r:
-	devm_iounmap(&pdev->dev, rng->result);
-err_ports:
-	devm_kfree(&pdev->dev, rng);
-	return -ENOENT;
 }
 
 static int __exit octeon_rng_remove(struct platform_device *pdev)
diff --git a/drivers/char/hw_random/tpm-rng.c b/drivers/char/hw_random/tpm-rng.c
new file mode 100644
index 0000000..d6d4482
--- /dev/null
+++ b/drivers/char/hw_random/tpm-rng.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2012 Kent Yoder IBM Corporation
+ *
+ * HWRNG interfaces to pull RNG data from a TPM
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#include <linux/module.h>
+#include <linux/hw_random.h>
+#include <linux/tpm.h>
+
+#define MODULE_NAME "tpm-rng"
+
+static int tpm_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)
+{
+	return tpm_get_random(TPM_ANY_NUM, data, max);
+}
+
+static struct hwrng tpm_rng = {
+	.name = MODULE_NAME,
+	.read = tpm_rng_read,
+};
+
+static int __init rng_init(void)
+{
+	return hwrng_register(&tpm_rng);
+}
+module_init(rng_init);
+
+static void __exit rng_exit(void)
+{
+	hwrng_unregister(&tpm_rng);
+}
+module_exit(rng_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Kent Yoder <key@linux.vnet.ibm.com>");
+MODULE_DESCRIPTION("RNG driver for TPM devices");
diff --git a/drivers/char/mbcs.c b/drivers/char/mbcs.c
index 47ff7e4..f74e892 100644
--- a/drivers/char/mbcs.c
+++ b/drivers/char/mbcs.c
@@ -507,7 +507,7 @@ static int mbcs_gscr_mmap(struct file *fp, struct vm_area_struct *vma)
 
 	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
 
-	/* Remap-pfn-range will mark the range VM_IO and VM_RESERVED */
+	/* Remap-pfn-range will mark the range VM_IO */
 	if (remap_pfn_range(vma,
 			    vma->vm_start,
 			    __pa(soft->gscr_addr) >> PAGE_SHIFT,
@@ -799,7 +799,7 @@ static int mbcs_remove(struct cx_dev *dev)
 	return 0;
 }
 
-static const struct cx_device_id __devinitdata mbcs_id_table[] = {
+static const struct cx_device_id __devinitconst mbcs_id_table[] = {
 	{
 	 .part_num = MBCS_PART_NUM,
 	 .mfg_num = MBCS_MFG_NUM,
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index e5eedfa..0537903 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -322,7 +322,7 @@ static int mmap_mem(struct file *file, struct vm_area_struct *vma)
 
 	vma->vm_ops = &mmap_mem_ops;
 
-	/* Remap-pfn-range will mark the range VM_IO and VM_RESERVED */
+	/* Remap-pfn-range will mark the range VM_IO */
 	if (remap_pfn_range(vma,
 			    vma->vm_start,
 			    vma->vm_pgoff,
diff --git a/drivers/char/mspec.c b/drivers/char/mspec.c
index 845f97f..e1f60f9 100644
--- a/drivers/char/mspec.c
+++ b/drivers/char/mspec.c
@@ -286,7 +286,7 @@ mspec_mmap(struct file *file, struct vm_area_struct *vma,
 	atomic_set(&vdata->refcnt, 1);
 	vma->vm_private_data = vdata;
 
-	vma->vm_flags |= (VM_IO | VM_RESERVED | VM_PFNMAP | VM_DONTEXPAND);
+	vma->vm_flags |= VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP;
 	if (vdata->type == MSPEC_FETCHOP || vdata->type == MSPEC_UNCACHED)
 		vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
 	vma->vm_ops = &mspec_vm_ops;
diff --git a/drivers/char/mwave/mwavedd.c b/drivers/char/mwave/mwavedd.c
index 1d82d58..164544a 100644
--- a/drivers/char/mwave/mwavedd.c
+++ b/drivers/char/mwave/mwavedd.c
@@ -430,7 +430,7 @@ static ssize_t mwave_write(struct file *file, const char __user *buf,
 
 static int register_serial_portandirq(unsigned int port, int irq)
 {
-	struct uart_port uart;
+	struct uart_8250_port uart;
 	
 	switch ( port ) {
 		case 0x3f8:
@@ -462,14 +462,14 @@ static int register_serial_portandirq(unsigned int port, int irq)
 	} /* switch */
 	/* irq is okay */
 
-	memset(&uart, 0, sizeof(struct uart_port));
+	memset(&uart, 0, sizeof(uart));
 	
-	uart.uartclk =  1843200;
-	uart.iobase = port;
-	uart.irq = irq;
-	uart.iotype = UPIO_PORT;
-	uart.flags =  UPF_SHARE_IRQ;
-	return serial8250_register_port(&uart);
+	uart.port.uartclk =  1843200;
+	uart.port.iobase = port;
+	uart.port.irq = irq;
+	uart.port.iotype = UPIO_PORT;
+	uart.port.flags =  UPF_SHARE_IRQ;
+	return serial8250_register_8250_port(&uart);
 }
 
 
diff --git a/drivers/char/nwflash.c b/drivers/char/nwflash.c
index d45c334..a0e2f7d 100644
--- a/drivers/char/nwflash.c
+++ b/drivers/char/nwflash.c
@@ -30,7 +30,6 @@
 
 #include <asm/hardware/dec21285.h>
 #include <asm/io.h>
-#include <asm/leds.h>
 #include <asm/mach-types.h>
 #include <asm/uaccess.h>
 
@@ -179,9 +178,6 @@ static ssize_t flash_write(struct file *file, const char __user *buf,
 
 	written = 0;
 
-	leds_event(led_claim);
-	leds_event(led_green_on);
-
 	nBlock = (int) p >> 16;	//block # of 64K bytes
 
 	/*
@@ -258,11 +254,6 @@ static ssize_t flash_write(struct file *file, const char __user *buf,
 			printk(KERN_DEBUG "flash_write: written 0x%X bytes OK.\n", written);
 	}
 
-	/*
-	 * restore reg on exit
-	 */
-	leds_event(led_release);
-
 	mutex_unlock(&nwflash_mutex);
 
 	return written;
@@ -334,11 +325,6 @@ static int erase_block(int nBlock)
 	int temp, temp1;
 
 	/*
-	 * orange LED == erase
-	 */
-	leds_event(led_amber_on);
-
-	/*
 	 * reset footbridge to the correct offset 0 (...0..3)
 	 */
 	*CSR_ROMWRITEREG = 0;
@@ -446,12 +432,6 @@ static int write_block(unsigned long p, const char __user *buf, int count)
 	unsigned long timeout;
 	unsigned long timeout1;
 
-	/*
-	 * red LED == write
-	 */
-	leds_event(led_amber_off);
-	leds_event(led_red_on);
-
 	pWritePtr = (unsigned char *) ((unsigned int) (FLASH_BASE + p));
 
 	/*
@@ -558,17 +538,9 @@ static int write_block(unsigned long p, const char __user *buf, int count)
 					       pWritePtr - FLASH_BASE);
 
 				/*
-				 * no LED == waiting
-				 */
-				leds_event(led_amber_off);
-				/*
 				 * wait couple ms
 				 */
 				msleep(10);
-				/*
-				 * red LED == write
-				 */
-				leds_event(led_red_on);
 
 				goto WriteRetry;
 			} else {
@@ -583,12 +555,6 @@ static int write_block(unsigned long p, const char __user *buf, int count)
 		}
 	}
 
-	/*
-	 * green LED == read/verify
-	 */
-	leds_event(led_amber_off);
-	leds_event(led_green_on);
-
 	msleep(10);
 
 	pWritePtr = (unsigned char *) ((unsigned int) (FLASH_BASE + p));
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index 0a484b4..3f57d5de 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -1050,7 +1050,7 @@ static void cts_change(MGSLPC_INFO *info, struct tty_struct *tty)
 	wake_up_interruptible(&info->status_event_wait_q);
 	wake_up_interruptible(&info->event_wait_q);
 
-	if (info->port.flags & ASYNC_CTS_FLOW) {
+	if (tty_port_cts_enabled(&info->port)) {
 		if (tty->hw_stopped) {
 			if (info->serial_signals & SerialSignal_CTS) {
 				if (debug_level >= DEBUG_LEVEL_ISR)
@@ -1344,7 +1344,7 @@ static void shutdown(MGSLPC_INFO * info, struct tty_struct *tty)
 	/* TODO:disable interrupts instead of reset to preserve signal states */
 	reset_device(info);
 
- 	if (!tty || tty->termios->c_cflag & HUPCL) {
+ 	if (!tty || tty->termios.c_cflag & HUPCL) {
  		info->serial_signals &= ~(SerialSignal_DTR + SerialSignal_RTS);
 		set_signals(info);
 	}
@@ -1385,7 +1385,7 @@ static void mgslpc_program_hw(MGSLPC_INFO *info, struct tty_struct *tty)
 	port_irq_enable(info, (unsigned char) PVR_DSR | PVR_RI);
 	get_signals(info);
 
-	if (info->netcount || (tty && (tty->termios->c_cflag & CREAD)))
+	if (info->netcount || (tty && (tty->termios.c_cflag & CREAD)))
 		rx_start(info);
 
 	spin_unlock_irqrestore(&info->lock,flags);
@@ -1398,14 +1398,14 @@ static void mgslpc_change_params(MGSLPC_INFO *info, struct tty_struct *tty)
 	unsigned cflag;
 	int bits_per_char;
 
-	if (!tty || !tty->termios)
+	if (!tty)
 		return;
 
 	if (debug_level >= DEBUG_LEVEL_INFO)
 		printk("%s(%d):mgslpc_change_params(%s)\n",
 			 __FILE__,__LINE__, info->device_name );
 
-	cflag = tty->termios->c_cflag;
+	cflag = tty->termios.c_cflag;
 
 	/* if B0 rate (hangup) specified then negate DTR and RTS */
 	/* otherwise assert DTR and RTS */
@@ -1728,7 +1728,7 @@ static void mgslpc_throttle(struct tty_struct * tty)
 	if (I_IXOFF(tty))
 		mgslpc_send_xchar(tty, STOP_CHAR(tty));
 
- 	if (tty->termios->c_cflag & CRTSCTS) {
+ 	if (tty->termios.c_cflag & CRTSCTS) {
 		spin_lock_irqsave(&info->lock,flags);
 		info->serial_signals &= ~SerialSignal_RTS;
 	 	set_signals(info);
@@ -1757,7 +1757,7 @@ static void mgslpc_unthrottle(struct tty_struct * tty)
 			mgslpc_send_xchar(tty, START_CHAR(tty));
 	}
 
- 	if (tty->termios->c_cflag & CRTSCTS) {
+ 	if (tty->termios.c_cflag & CRTSCTS) {
 		spin_lock_irqsave(&info->lock,flags);
 		info->serial_signals |= SerialSignal_RTS;
 	 	set_signals(info);
@@ -2293,8 +2293,8 @@ static void mgslpc_set_termios(struct tty_struct *tty, struct ktermios *old_term
 			tty->driver->name );
 
 	/* just return if nothing has changed */
-	if ((tty->termios->c_cflag == old_termios->c_cflag)
-	    && (RELEVANT_IFLAG(tty->termios->c_iflag)
+	if ((tty->termios.c_cflag == old_termios->c_cflag)
+	    && (RELEVANT_IFLAG(tty->termios.c_iflag)
 		== RELEVANT_IFLAG(old_termios->c_iflag)))
 	  return;
 
@@ -2302,7 +2302,7 @@ static void mgslpc_set_termios(struct tty_struct *tty, struct ktermios *old_term
 
 	/* Handle transition to B0 status */
 	if (old_termios->c_cflag & CBAUD &&
-	    !(tty->termios->c_cflag & CBAUD)) {
+	    !(tty->termios.c_cflag & CBAUD)) {
 		info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR);
 		spin_lock_irqsave(&info->lock,flags);
 	 	set_signals(info);
@@ -2311,9 +2311,9 @@ static void mgslpc_set_termios(struct tty_struct *tty, struct ktermios *old_term
 
 	/* Handle transition away from B0 status */
 	if (!(old_termios->c_cflag & CBAUD) &&
-	    tty->termios->c_cflag & CBAUD) {
+	    tty->termios.c_cflag & CBAUD) {
 		info->serial_signals |= SerialSignal_DTR;
- 		if (!(tty->termios->c_cflag & CRTSCTS) ||
+ 		if (!(tty->termios.c_cflag & CRTSCTS) ||
  		    !test_bit(TTY_THROTTLED, &tty->flags)) {
 			info->serial_signals |= SerialSignal_RTS;
  		}
@@ -2324,7 +2324,7 @@ static void mgslpc_set_termios(struct tty_struct *tty, struct ktermios *old_term
 
 	/* Handle turning off CRTSCTS */
 	if (old_termios->c_cflag & CRTSCTS &&
-	    !(tty->termios->c_cflag & CRTSCTS)) {
+	    !(tty->termios.c_cflag & CRTSCTS)) {
 		tty->hw_stopped = 0;
 		tx_release(tty);
 	}
@@ -2731,6 +2731,8 @@ static void mgslpc_add_device(MGSLPC_INFO *info)
 #if SYNCLINK_GENERIC_HDLC
 	hdlcdev_init(info);
 #endif
+	tty_port_register_device(&info->port, serial_driver, info->line,
+			&info->p_dev->dev);
 }
 
 static void mgslpc_remove_device(MGSLPC_INFO *remove_info)
@@ -2744,6 +2746,7 @@ static void mgslpc_remove_device(MGSLPC_INFO *remove_info)
 				last->next_device = info->next_device;
 			else
 				mgslpc_device_list = info->next_device;
+			tty_unregister_device(serial_driver, info->line);
 #if SYNCLINK_GENERIC_HDLC
 			hdlcdev_exit(info);
 #endif
@@ -2798,77 +2801,63 @@ static const struct tty_operations mgslpc_ops = {
 	.proc_fops = &mgslpc_proc_fops,
 };
 
-static void synclink_cs_cleanup(void)
+static int __init synclink_cs_init(void)
 {
 	int rc;
 
-	while(mgslpc_device_list)
-		mgslpc_remove_device(mgslpc_device_list);
-
-	if (serial_driver) {
-		if ((rc = tty_unregister_driver(serial_driver)))
-			printk("%s(%d) failed to unregister tty driver err=%d\n",
-			       __FILE__,__LINE__,rc);
-		put_tty_driver(serial_driver);
+	if (break_on_load) {
+		mgslpc_get_text_ptr();
+		BREAKPOINT();
 	}
 
-	pcmcia_unregister_driver(&mgslpc_driver);
-}
-
-static int __init synclink_cs_init(void)
-{
-    int rc;
-
-    if (break_on_load) {
-	    mgslpc_get_text_ptr();
-	    BREAKPOINT();
-    }
-
-    if ((rc = pcmcia_register_driver(&mgslpc_driver)) < 0)
-	    return rc;
-
-    serial_driver = alloc_tty_driver(MAX_DEVICE_COUNT);
-    if (!serial_driver) {
-	    rc = -ENOMEM;
-	    goto error;
-    }
+	serial_driver = tty_alloc_driver(MAX_DEVICE_COUNT,
+			TTY_DRIVER_REAL_RAW |
+			TTY_DRIVER_DYNAMIC_DEV);
+	if (IS_ERR(serial_driver)) {
+		rc = PTR_ERR(serial_driver);
+		goto err;
+	}
 
-    /* Initialize the tty_driver structure */
-
-    serial_driver->driver_name = "synclink_cs";
-    serial_driver->name = "ttySLP";
-    serial_driver->major = ttymajor;
-    serial_driver->minor_start = 64;
-    serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
-    serial_driver->subtype = SERIAL_TYPE_NORMAL;
-    serial_driver->init_termios = tty_std_termios;
-    serial_driver->init_termios.c_cflag =
-	    B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-    serial_driver->flags = TTY_DRIVER_REAL_RAW;
-    tty_set_operations(serial_driver, &mgslpc_ops);
-
-    if ((rc = tty_register_driver(serial_driver)) < 0) {
-	    printk("%s(%d):Couldn't register serial driver\n",
-		   __FILE__,__LINE__);
-	    put_tty_driver(serial_driver);
-	    serial_driver = NULL;
-	    goto error;
-    }
+	/* Initialize the tty_driver structure */
+	serial_driver->driver_name = "synclink_cs";
+	serial_driver->name = "ttySLP";
+	serial_driver->major = ttymajor;
+	serial_driver->minor_start = 64;
+	serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
+	serial_driver->subtype = SERIAL_TYPE_NORMAL;
+	serial_driver->init_termios = tty_std_termios;
+	serial_driver->init_termios.c_cflag =
+	B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+	tty_set_operations(serial_driver, &mgslpc_ops);
+
+	rc = tty_register_driver(serial_driver);
+	if (rc < 0) {
+		printk(KERN_ERR "%s(%d):Couldn't register serial driver\n",
+				__FILE__, __LINE__);
+		goto err_put_tty;
+	}
 
-    printk("%s %s, tty major#%d\n",
-	   driver_name, driver_version,
-	   serial_driver->major);
+	rc = pcmcia_register_driver(&mgslpc_driver);
+	if (rc < 0)
+		goto err_unreg_tty;
 
-    return 0;
+	printk(KERN_INFO "%s %s, tty major#%d\n", driver_name, driver_version,
+			serial_driver->major);
 
-error:
-    synclink_cs_cleanup();
-    return rc;
+	return 0;
+err_unreg_tty:
+	tty_unregister_driver(serial_driver);
+err_put_tty:
+	put_tty_driver(serial_driver);
+err:
+	return rc;
 }
 
 static void __exit synclink_cs_exit(void)
 {
-	synclink_cs_cleanup();
+	pcmcia_unregister_driver(&mgslpc_driver);
+	tty_unregister_driver(serial_driver);
+	put_tty_driver(serial_driver);
 }
 
 module_init(synclink_cs_init);
diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c
index 3fcf80f..d0d824e 100644
--- a/drivers/char/ppdev.c
+++ b/drivers/char/ppdev.c
@@ -783,7 +783,8 @@ static int __init ppdev_init (void)
 		err = PTR_ERR(ppdev_class);
 		goto out_chrdev;
 	}
-	if (parport_register_driver(&pp_driver)) {
+	err = parport_register_driver(&pp_driver);
+	if (err < 0) {
 		printk (KERN_WARNING CHRDEV ": unable to register with parport\n");
 		goto out_class;
 	}
diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c
index f877805..320debb 100644
--- a/drivers/char/sonypi.c
+++ b/drivers/char/sonypi.c
@@ -1433,7 +1433,7 @@ static int __devexit sonypi_remove(struct platform_device *dev)
 	sonypi_disable();
 
 	synchronize_irq(sonypi_device.irq);
-	flush_work_sync(&sonypi_device.input_work);
+	flush_work(&sonypi_device.input_work);
 
 	if (useinput) {
 		input_unregister_device(sonypi_device.input_key_dev);
diff --git a/drivers/char/tlclk.c b/drivers/char/tlclk.c
index ce29e7c..e95e0ab 100644
--- a/drivers/char/tlclk.c
+++ b/drivers/char/tlclk.c
@@ -784,8 +784,10 @@ static int __init tlclk_init(void)
 	}
 	tlclk_major = ret;
 	alarm_events = kzalloc( sizeof(struct tlclk_alarms), GFP_KERNEL);
-	if (!alarm_events)
+	if (!alarm_events) {
+		ret = -ENOMEM;
 		goto out1;
+	}
 
 	/* Read telecom clock IRQ number (Set by BIOS) */
 	if (!request_region(TLCLK_BASE, 8, "telco_clock")) {
diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig
index a048199..915875e 100644
--- a/drivers/char/tpm/Kconfig
+++ b/drivers/char/tpm/Kconfig
@@ -33,6 +33,17 @@ config TCG_TIS
 	  from within Linux.  To compile this driver as a module, choose
 	  M here; the module will be called tpm_tis.
 
+config TCG_TIS_I2C_INFINEON
+	tristate "TPM Interface Specification 1.2 Interface (I2C - Infineon)"
+	depends on I2C
+	---help---
+	  If you have a TPM security chip that is compliant with the
+	  TCG TIS 1.2 TPM specification and Infineon's I2C Protocol Stack
+	  Specification 0.20 say Yes and it will be accessible from within
+	  Linux.
+	  To compile this driver as a module, choose M here; the module
+	  will be called tpm_tis_i2c_infineon.
+
 config TCG_NSC
 	tristate "National Semiconductor TPM Interface"
 	depends on X86
@@ -62,4 +73,12 @@ config TCG_INFINEON
 	  Further information on this driver and the supported hardware
 	  can be found at http://www.trust.rub.de/projects/linux-device-driver-infineon-tpm/ 
 
+config TCG_IBMVTPM
+	tristate "IBM VTPM Interface"
+	depends on PPC64
+	---help---
+	  If you have IBM virtual TPM (VTPM) support say Yes and it
+	  will be accessible from within Linux.  To compile this driver
+	  as a module, choose M here; the module will be called tpm_ibmvtpm.
+
 endif # TCG_TPM
diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile
index ea3a1e0..5b3fc8b 100644
--- a/drivers/char/tpm/Makefile
+++ b/drivers/char/tpm/Makefile
@@ -4,8 +4,16 @@
 obj-$(CONFIG_TCG_TPM) += tpm.o
 ifdef CONFIG_ACPI
 	obj-$(CONFIG_TCG_TPM) += tpm_bios.o
+	tpm_bios-objs += tpm_eventlog.o tpm_acpi.o tpm_ppi.o
+else
+ifdef CONFIG_TCG_IBMVTPM
+	obj-$(CONFIG_TCG_TPM) += tpm_bios.o
+	tpm_bios-objs += tpm_eventlog.o tpm_of.o
+endif
 endif
 obj-$(CONFIG_TCG_TIS) += tpm_tis.o
+obj-$(CONFIG_TCG_TIS_I2C_INFINEON) += tpm_i2c_infineon.o
 obj-$(CONFIG_TCG_NSC) += tpm_nsc.o
 obj-$(CONFIG_TCG_ATMEL) += tpm_atmel.o
 obj-$(CONFIG_TCG_INFINEON) += tpm_infineon.o
+obj-$(CONFIG_TCG_IBMVTPM) += tpm_ibmvtpm.o
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
index 817f0ee..f26afdb 100644
--- a/drivers/char/tpm/tpm.c
+++ b/drivers/char/tpm/tpm.c
@@ -30,12 +30,7 @@
 #include <linux/freezer.h>
 
 #include "tpm.h"
-
-enum tpm_const {
-	TPM_MINOR = 224,	/* officially assigned */
-	TPM_BUFSIZE = 4096,
-	TPM_NUM_DEVICES = 256,
-};
+#include "tpm_eventlog.h"
 
 enum tpm_duration {
 	TPM_SHORT = 0,
@@ -482,6 +477,7 @@ static ssize_t transmit_cmd(struct tpm_chip *chip, struct tpm_cmd_t *cmd,
 #define TPM_INTERNAL_RESULT_SIZE 200
 #define TPM_TAG_RQU_COMMAND cpu_to_be16(193)
 #define TPM_ORD_GET_CAP cpu_to_be32(101)
+#define TPM_ORD_GET_RANDOM cpu_to_be32(70)
 
 static const struct tpm_input_header tpm_getcap_header = {
 	.tag = TPM_TAG_RQU_COMMAND,
@@ -919,7 +915,7 @@ EXPORT_SYMBOL_GPL(tpm_show_pcrs);
 
 #define  READ_PUBEK_RESULT_SIZE 314
 #define TPM_ORD_READPUBEK cpu_to_be32(124)
-struct tpm_input_header tpm_readpubek_header = {
+static struct tpm_input_header tpm_readpubek_header = {
 	.tag = TPM_TAG_RQU_COMMAND,
 	.length = cpu_to_be32(30),
 	.ordinal = TPM_ORD_READPUBEK
@@ -1172,10 +1168,10 @@ int tpm_release(struct inode *inode, struct file *file)
 	struct tpm_chip *chip = file->private_data;
 
 	del_singleshot_timer_sync(&chip->user_read_timer);
-	flush_work_sync(&chip->work);
+	flush_work(&chip->work);
 	file->private_data = NULL;
 	atomic_set(&chip->data_pending, 0);
-	kfree(chip->data_buffer);
+	kzfree(chip->data_buffer);
 	clear_bit(0, &chip->is_open);
 	put_device(chip->dev);
 	return 0;
@@ -1225,9 +1221,8 @@ ssize_t tpm_read(struct file *file, char __user *buf,
 	int rc;
 
 	del_singleshot_timer_sync(&chip->user_read_timer);
-	flush_work_sync(&chip->work);
+	flush_work(&chip->work);
 	ret_size = atomic_read(&chip->data_pending);
-	atomic_set(&chip->data_pending, 0);
 	if (ret_size > 0) {	/* relay data */
 		ssize_t orig_ret_size = ret_size;
 		if (size < ret_size)
@@ -1242,6 +1237,8 @@ ssize_t tpm_read(struct file *file, char __user *buf,
 		mutex_unlock(&chip->buffer_mutex);
 	}
 
+	atomic_set(&chip->data_pending, 0);
+
 	return ret_size;
 }
 EXPORT_SYMBOL_GPL(tpm_read);
@@ -1326,6 +1323,58 @@ int tpm_pm_resume(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(tpm_pm_resume);
 
+#define TPM_GETRANDOM_RESULT_SIZE	18
+static struct tpm_input_header tpm_getrandom_header = {
+	.tag = TPM_TAG_RQU_COMMAND,
+	.length = cpu_to_be32(14),
+	.ordinal = TPM_ORD_GET_RANDOM
+};
+
+/**
+ * tpm_get_random() - Get random bytes from the tpm's RNG
+ * @chip_num: A specific chip number for the request or TPM_ANY_NUM
+ * @out: destination buffer for the random bytes
+ * @max: the max number of bytes to write to @out
+ *
+ * Returns < 0 on error and the number of bytes read on success
+ */
+int tpm_get_random(u32 chip_num, u8 *out, size_t max)
+{
+	struct tpm_chip *chip;
+	struct tpm_cmd_t tpm_cmd;
+	u32 recd, num_bytes = min_t(u32, max, TPM_MAX_RNG_DATA);
+	int err, total = 0, retries = 5;
+	u8 *dest = out;
+
+	chip = tpm_chip_find_get(chip_num);
+	if (chip == NULL)
+		return -ENODEV;
+
+	if (!out || !num_bytes || max > TPM_MAX_RNG_DATA)
+		return -EINVAL;
+
+	do {
+		tpm_cmd.header.in = tpm_getrandom_header;
+		tpm_cmd.params.getrandom_in.num_bytes = cpu_to_be32(num_bytes);
+
+		err = transmit_cmd(chip, &tpm_cmd,
+				   TPM_GETRANDOM_RESULT_SIZE + num_bytes,
+				   "attempting get random");
+		if (err)
+			break;
+
+		recd = be32_to_cpu(tpm_cmd.params.getrandom_out.rng_data_len);
+		memcpy(dest, tpm_cmd.params.getrandom_out.rng_data, recd);
+
+		dest += recd;
+		total += recd;
+		num_bytes -= recd;
+	} while (retries-- && total < max);
+
+	return total ? total : -EIO;
+}
+EXPORT_SYMBOL_GPL(tpm_get_random);
+
 /* In case vendor provided release function, call it too.*/
 
 void tpm_dev_vendor_release(struct tpm_chip *chip)
@@ -1346,7 +1395,7 @@ EXPORT_SYMBOL_GPL(tpm_dev_vendor_release);
  * Once all references to platform device are down to 0,
  * release all allocated structures.
  */
-void tpm_dev_release(struct device *dev)
+static void tpm_dev_release(struct device *dev)
 {
 	struct tpm_chip *chip = dev_get_drvdata(dev);
 
@@ -1427,6 +1476,11 @@ struct tpm_chip *tpm_register_hardware(struct device *dev,
 		goto put_device;
 	}
 
+	if (sys_add_ppi(&dev->kobj)) {
+		misc_deregister(&chip->vendor.miscdev);
+		goto put_device;
+	}
+
 	chip->bios_dir = tpm_bios_log_setup(devname);
 
 	/* Make chip available */
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 917f727..02c266a 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -28,6 +28,12 @@
 #include <linux/io.h>
 #include <linux/tpm.h>
 
+enum tpm_const {
+	TPM_MINOR = 224,	/* officially assigned */
+	TPM_BUFSIZE = 4096,
+	TPM_NUM_DEVICES = 256,
+};
+
 enum tpm_timeout {
 	TPM_TIMEOUT = 5,	/* msecs */
 };
@@ -94,6 +100,7 @@ struct tpm_vendor_specific {
 	bool timeout_adjusted;
 	unsigned long duration[3]; /* jiffies */
 	bool duration_adjusted;
+	void *data;
 
 	wait_queue_head_t read_queue;
 	wait_queue_head_t int_queue;
@@ -269,6 +276,21 @@ struct tpm_pcrextend_in {
 	u8	hash[TPM_DIGEST_SIZE];
 }__attribute__((packed));
 
+/* 128 bytes is an arbitrary cap. This could be as large as TPM_BUFSIZE - 18
+ * bytes, but 128 is still a relatively large number of random bytes and
+ * anything much bigger causes users of struct tpm_cmd_t to start getting
+ * compiler warnings about stack frame size. */
+#define TPM_MAX_RNG_DATA	128
+
+struct tpm_getrandom_out {
+	__be32 rng_data_len;
+	u8     rng_data[TPM_MAX_RNG_DATA];
+}__attribute__((packed));
+
+struct tpm_getrandom_in {
+	__be32 num_bytes;
+}__attribute__((packed));
+
 typedef union {
 	struct	tpm_getcap_params_out getcap_out;
 	struct	tpm_readpubek_params_out readpubek_out;
@@ -277,6 +299,8 @@ typedef union {
 	struct	tpm_pcrread_in	pcrread_in;
 	struct	tpm_pcrread_out	pcrread_out;
 	struct	tpm_pcrextend_in pcrextend_in;
+	struct	tpm_getrandom_in getrandom_in;
+	struct	tpm_getrandom_out getrandom_out;
 } tpm_cmd_params;
 
 struct tpm_cmd_t {
@@ -303,15 +327,12 @@ extern int tpm_pm_suspend(struct device *);
 extern int tpm_pm_resume(struct device *);
 extern int wait_for_tpm_stat(struct tpm_chip *, u8, unsigned long,
 			     wait_queue_head_t *);
+
 #ifdef CONFIG_ACPI
-extern struct dentry ** tpm_bios_log_setup(char *);
-extern void tpm_bios_log_teardown(struct dentry **);
+extern ssize_t sys_add_ppi(struct kobject *parent);
 #else
-static inline struct dentry ** tpm_bios_log_setup(char *name)
-{
-	return NULL;
-}
-static inline void tpm_bios_log_teardown(struct dentry **dir)
+static inline ssize_t sys_add_ppi(struct kobject *parent)
 {
+	return 0;
 }
 #endif
diff --git a/drivers/char/tpm/tpm_acpi.c b/drivers/char/tpm/tpm_acpi.c
new file mode 100644
index 0000000..56051d0
--- /dev/null
+++ b/drivers/char/tpm/tpm_acpi.c
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2005 IBM Corporation
+ *
+ * Authors:
+ *	Seiji Munetoh <munetoh@jp.ibm.com>
+ *	Stefan Berger <stefanb@us.ibm.com>
+ *	Reiner Sailer <sailer@watson.ibm.com>
+ *	Kylene Hall <kjhall@us.ibm.com>
+ *
+ * Maintained by: <tpmdd-devel@lists.sourceforge.net>
+ *
+ * Access to the eventlog extended by the TCG BIOS of PC platform
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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/seq_file.h>
+#include <linux/fs.h>
+#include <linux/security.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <acpi/acpi.h>
+
+#include "tpm.h"
+#include "tpm_eventlog.h"
+
+struct acpi_tcpa {
+	struct acpi_table_header hdr;
+	u16 platform_class;
+	union {
+		struct client_hdr {
+			u32 log_max_len __attribute__ ((packed));
+			u64 log_start_addr __attribute__ ((packed));
+		} client;
+		struct server_hdr {
+			u16 reserved;
+			u64 log_max_len __attribute__ ((packed));
+			u64 log_start_addr __attribute__ ((packed));
+		} server;
+	};
+};
+
+/* read binary bios log */
+int read_log(struct tpm_bios_log *log)
+{
+	struct acpi_tcpa *buff;
+	acpi_status status;
+	void __iomem *virt;
+	u64 len, start;
+
+	if (log->bios_event_log != NULL) {
+		printk(KERN_ERR
+		       "%s: ERROR - Eventlog already initialized\n",
+		       __func__);
+		return -EFAULT;
+	}
+
+	/* Find TCPA entry in RSDT (ACPI_LOGICAL_ADDRESSING) */
+	status = acpi_get_table(ACPI_SIG_TCPA, 1,
+				(struct acpi_table_header **)&buff);
+
+	if (ACPI_FAILURE(status)) {
+		printk(KERN_ERR "%s: ERROR - Could not get TCPA table\n",
+		       __func__);
+		return -EIO;
+	}
+
+	switch(buff->platform_class) {
+	case BIOS_SERVER:
+		len = buff->server.log_max_len;
+		start = buff->server.log_start_addr;
+		break;
+	case BIOS_CLIENT:
+	default:
+		len = buff->client.log_max_len;
+		start = buff->client.log_start_addr;
+		break;
+	}
+	if (!len) {
+		printk(KERN_ERR "%s: ERROR - TCPA log area empty\n", __func__);
+		return -EIO;
+	}
+
+	/* malloc EventLog space */
+	log->bios_event_log = kmalloc(len, GFP_KERNEL);
+	if (!log->bios_event_log) {
+		printk("%s: ERROR - Not enough  Memory for BIOS measurements\n",
+			__func__);
+		return -ENOMEM;
+	}
+
+	log->bios_event_log_end = log->bios_event_log + len;
+
+	virt = acpi_os_map_memory(start, len);
+	if (!virt) {
+		kfree(log->bios_event_log);
+		printk("%s: ERROR - Unable to map memory\n", __func__);
+		return -EIO;
+	}
+
+	memcpy_fromio(log->bios_event_log, virt, len);
+
+	acpi_os_unmap_memory(virt, len);
+	return 0;
+}
diff --git a/drivers/char/tpm/tpm_bios.c b/drivers/char/tpm/tpm_bios.c
deleted file mode 100644
index 0636520..0000000
--- a/drivers/char/tpm/tpm_bios.c
+++ /dev/null
@@ -1,556 +0,0 @@
-/*
- * Copyright (C) 2005 IBM Corporation
- *
- * Authors:
- *	Seiji Munetoh <munetoh@jp.ibm.com>
- *	Stefan Berger <stefanb@us.ibm.com>
- *	Reiner Sailer <sailer@watson.ibm.com>
- *	Kylene Hall <kjhall@us.ibm.com>
- *
- * Maintained by: <tpmdd-devel@lists.sourceforge.net>
- *
- * Access to the eventlog extended by the TCG BIOS of PC platform
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the 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/seq_file.h>
-#include <linux/fs.h>
-#include <linux/security.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <acpi/acpi.h>
-#include "tpm.h"
-
-#define TCG_EVENT_NAME_LEN_MAX	255
-#define MAX_TEXT_EVENT		1000	/* Max event string length */
-#define ACPI_TCPA_SIG		"TCPA"	/* 0x41504354 /'TCPA' */
-
-enum bios_platform_class {
-	BIOS_CLIENT = 0x00,
-	BIOS_SERVER = 0x01,
-};
-
-struct tpm_bios_log {
-	void *bios_event_log;
-	void *bios_event_log_end;
-};
-
-struct acpi_tcpa {
-	struct acpi_table_header hdr;
-	u16 platform_class;
-	union {
-		struct client_hdr {
-			u32 log_max_len __attribute__ ((packed));
-			u64 log_start_addr __attribute__ ((packed));
-		} client;
-		struct server_hdr {
-			u16 reserved;
-			u64 log_max_len __attribute__ ((packed));
-			u64 log_start_addr __attribute__ ((packed));
-		} server;
-	};
-};
-
-struct tcpa_event {
-	u32 pcr_index;
-	u32 event_type;
-	u8 pcr_value[20];	/* SHA1 */
-	u32 event_size;
-	u8 event_data[0];
-};
-
-enum tcpa_event_types {
-	PREBOOT = 0,
-	POST_CODE,
-	UNUSED,
-	NO_ACTION,
-	SEPARATOR,
-	ACTION,
-	EVENT_TAG,
-	SCRTM_CONTENTS,
-	SCRTM_VERSION,
-	CPU_MICROCODE,
-	PLATFORM_CONFIG_FLAGS,
-	TABLE_OF_DEVICES,
-	COMPACT_HASH,
-	IPL,
-	IPL_PARTITION_DATA,
-	NONHOST_CODE,
-	NONHOST_CONFIG,
-	NONHOST_INFO,
-};
-
-static const char* tcpa_event_type_strings[] = {
-	"PREBOOT",
-	"POST CODE",
-	"",
-	"NO ACTION",
-	"SEPARATOR",
-	"ACTION",
-	"EVENT TAG",
-	"S-CRTM Contents",
-	"S-CRTM Version",
-	"CPU Microcode",
-	"Platform Config Flags",
-	"Table of Devices",
-	"Compact Hash",
-	"IPL",
-	"IPL Partition Data",
-	"Non-Host Code",
-	"Non-Host Config",
-	"Non-Host Info"
-};
-
-struct tcpa_pc_event {
-	u32 event_id;
-	u32 event_size;
-	u8 event_data[0];
-};
-
-enum tcpa_pc_event_ids {
-	SMBIOS = 1,
-	BIS_CERT,
-	POST_BIOS_ROM,
-	ESCD,
-	CMOS,
-	NVRAM,
-	OPTION_ROM_EXEC,
-	OPTION_ROM_CONFIG,
-	OPTION_ROM_MICROCODE = 10,
-	S_CRTM_VERSION,
-	S_CRTM_CONTENTS,
-	POST_CONTENTS,
-	HOST_TABLE_OF_DEVICES,
-};
-
-static const char* tcpa_pc_event_id_strings[] = {
-	"",
-	"SMBIOS",
-	"BIS Certificate",
-	"POST BIOS ",
-	"ESCD ",
-	"CMOS",
-	"NVRAM",
-	"Option ROM",
-	"Option ROM config",
-	"",
-	"Option ROM microcode ",
-	"S-CRTM Version",
-	"S-CRTM Contents ",
-	"POST Contents ",
-	"Table of Devices",
-};
-
-/* returns pointer to start of pos. entry of tcg log */
-static void *tpm_bios_measurements_start(struct seq_file *m, loff_t *pos)
-{
-	loff_t i;
-	struct tpm_bios_log *log = m->private;
-	void *addr = log->bios_event_log;
-	void *limit = log->bios_event_log_end;
-	struct tcpa_event *event;
-
-	/* read over *pos measurements */
-	for (i = 0; i < *pos; i++) {
-		event = addr;
-
-		if ((addr + sizeof(struct tcpa_event)) < limit) {
-			if (event->event_type == 0 && event->event_size == 0)
-				return NULL;
-			addr += sizeof(struct tcpa_event) + event->event_size;
-		}
-	}
-
-	/* now check if current entry is valid */
-	if ((addr + sizeof(struct tcpa_event)) >= limit)
-		return NULL;
-
-	event = addr;
-
-	if ((event->event_type == 0 && event->event_size == 0) ||
-	    ((addr + sizeof(struct tcpa_event) + event->event_size) >= limit))
-		return NULL;
-
-	return addr;
-}
-
-static void *tpm_bios_measurements_next(struct seq_file *m, void *v,
-					loff_t *pos)
-{
-	struct tcpa_event *event = v;
-	struct tpm_bios_log *log = m->private;
-	void *limit = log->bios_event_log_end;
-
-	v += sizeof(struct tcpa_event) + event->event_size;
-
-	/* now check if current entry is valid */
-	if ((v + sizeof(struct tcpa_event)) >= limit)
-		return NULL;
-
-	event = v;
-
-	if (event->event_type == 0 && event->event_size == 0)
-		return NULL;
-
-	if ((event->event_type == 0 && event->event_size == 0) ||
-	    ((v + sizeof(struct tcpa_event) + event->event_size) >= limit))
-		return NULL;
-
-	(*pos)++;
-	return v;
-}
-
-static void tpm_bios_measurements_stop(struct seq_file *m, void *v)
-{
-}
-
-static int get_event_name(char *dest, struct tcpa_event *event,
-			unsigned char * event_entry)
-{
-	const char *name = "";
-	/* 41 so there is room for 40 data and 1 nul */
-	char data[41] = "";
-	int i, n_len = 0, d_len = 0;
-	struct tcpa_pc_event *pc_event;
-
-	switch(event->event_type) {
-	case PREBOOT:
-	case POST_CODE:
-	case UNUSED:
-	case NO_ACTION:
-	case SCRTM_CONTENTS:
-	case SCRTM_VERSION:
-	case CPU_MICROCODE:
-	case PLATFORM_CONFIG_FLAGS:
-	case TABLE_OF_DEVICES:
-	case COMPACT_HASH:
-	case IPL:
-	case IPL_PARTITION_DATA:
-	case NONHOST_CODE:
-	case NONHOST_CONFIG:
-	case NONHOST_INFO:
-		name = tcpa_event_type_strings[event->event_type];
-		n_len = strlen(name);
-		break;
-	case SEPARATOR:
-	case ACTION:
-		if (MAX_TEXT_EVENT > event->event_size) {
-			name = event_entry;
-			n_len = event->event_size;
-		}
-		break;
-	case EVENT_TAG:
-		pc_event = (struct tcpa_pc_event *)event_entry;
-
-		/* ToDo Row data -> Base64 */
-
-		switch (pc_event->event_id) {
-		case SMBIOS:
-		case BIS_CERT:
-		case CMOS:
-		case NVRAM:
-		case OPTION_ROM_EXEC:
-		case OPTION_ROM_CONFIG:
-		case S_CRTM_VERSION:
-			name = tcpa_pc_event_id_strings[pc_event->event_id];
-			n_len = strlen(name);
-			break;
-		/* hash data */
-		case POST_BIOS_ROM:
-		case ESCD:
-		case OPTION_ROM_MICROCODE:
-		case S_CRTM_CONTENTS:
-		case POST_CONTENTS:
-			name = tcpa_pc_event_id_strings[pc_event->event_id];
-			n_len = strlen(name);
-			for (i = 0; i < 20; i++)
-				d_len += sprintf(&data[2*i], "%02x",
-						pc_event->event_data[i]);
-			break;
-		default:
-			break;
-		}
-	default:
-		break;
-	}
-
-	return snprintf(dest, MAX_TEXT_EVENT, "[%.*s%.*s]",
-			n_len, name, d_len, data);
-
-}
-
-static int tpm_binary_bios_measurements_show(struct seq_file *m, void *v)
-{
-	struct tcpa_event *event = v;
-	char *data = v;
-	int i;
-
-	for (i = 0; i < sizeof(struct tcpa_event) + event->event_size; i++)
-		seq_putc(m, data[i]);
-
-	return 0;
-}
-
-static int tpm_bios_measurements_release(struct inode *inode,
-					 struct file *file)
-{
-	struct seq_file *seq = file->private_data;
-	struct tpm_bios_log *log = seq->private;
-
-	if (log) {
-		kfree(log->bios_event_log);
-		kfree(log);
-	}
-
-	return seq_release(inode, file);
-}
-
-static int tpm_ascii_bios_measurements_show(struct seq_file *m, void *v)
-{
-	int len = 0;
-	int i;
-	char *eventname;
-	struct tcpa_event *event = v;
-	unsigned char *event_entry =
-	    (unsigned char *) (v + sizeof(struct tcpa_event));
-
-	eventname = kmalloc(MAX_TEXT_EVENT, GFP_KERNEL);
-	if (!eventname) {
-		printk(KERN_ERR "%s: ERROR - No Memory for event name\n ",
-		       __func__);
-		return -EFAULT;
-	}
-
-	seq_printf(m, "%2d ", event->pcr_index);
-
-	/* 2nd: SHA1 */
-	for (i = 0; i < 20; i++)
-		seq_printf(m, "%02x", event->pcr_value[i]);
-
-	/* 3rd: event type identifier */
-	seq_printf(m, " %02x", event->event_type);
-
-	len += get_event_name(eventname, event, event_entry);
-
-	/* 4th: eventname <= max + \'0' delimiter */
-	seq_printf(m, " %s\n", eventname);
-
-	kfree(eventname);
-	return 0;
-}
-
-static const struct seq_operations tpm_ascii_b_measurments_seqops = {
-	.start = tpm_bios_measurements_start,
-	.next = tpm_bios_measurements_next,
-	.stop = tpm_bios_measurements_stop,
-	.show = tpm_ascii_bios_measurements_show,
-};
-
-static const struct seq_operations tpm_binary_b_measurments_seqops = {
-	.start = tpm_bios_measurements_start,
-	.next = tpm_bios_measurements_next,
-	.stop = tpm_bios_measurements_stop,
-	.show = tpm_binary_bios_measurements_show,
-};
-
-/* read binary bios log */
-static int read_log(struct tpm_bios_log *log)
-{
-	struct acpi_tcpa *buff;
-	acpi_status status;
-	struct acpi_table_header *virt;
-	u64 len, start;
-
-	if (log->bios_event_log != NULL) {
-		printk(KERN_ERR
-		       "%s: ERROR - Eventlog already initialized\n",
-		       __func__);
-		return -EFAULT;
-	}
-
-	/* Find TCPA entry in RSDT (ACPI_LOGICAL_ADDRESSING) */
-	status = acpi_get_table(ACPI_SIG_TCPA, 1,
-				(struct acpi_table_header **)&buff);
-
-	if (ACPI_FAILURE(status)) {
-		printk(KERN_ERR "%s: ERROR - Could not get TCPA table\n",
-		       __func__);
-		return -EIO;
-	}
-
-	switch(buff->platform_class) {
-	case BIOS_SERVER:
-		len = buff->server.log_max_len;
-		start = buff->server.log_start_addr;
-		break;
-	case BIOS_CLIENT:
-	default:
-		len = buff->client.log_max_len;
-		start = buff->client.log_start_addr;
-		break;
-	}
-	if (!len) {
-		printk(KERN_ERR "%s: ERROR - TCPA log area empty\n", __func__);
-		return -EIO;
-	}
-
-	/* malloc EventLog space */
-	log->bios_event_log = kmalloc(len, GFP_KERNEL);
-	if (!log->bios_event_log) {
-		printk("%s: ERROR - Not enough  Memory for BIOS measurements\n",
-			__func__);
-		return -ENOMEM;
-	}
-
-	log->bios_event_log_end = log->bios_event_log + len;
-
-	virt = acpi_os_map_memory(start, len);
-
-	memcpy(log->bios_event_log, virt, len);
-
-	acpi_os_unmap_memory(virt, len);
-	return 0;
-}
-
-static int tpm_ascii_bios_measurements_open(struct inode *inode,
-					    struct file *file)
-{
-	int err;
-	struct tpm_bios_log *log;
-	struct seq_file *seq;
-
-	log = kzalloc(sizeof(struct tpm_bios_log), GFP_KERNEL);
-	if (!log)
-		return -ENOMEM;
-
-	if ((err = read_log(log)))
-		goto out_free;
-
-	/* now register seq file */
-	err = seq_open(file, &tpm_ascii_b_measurments_seqops);
-	if (!err) {
-		seq = file->private_data;
-		seq->private = log;
-	} else {
-		goto out_free;
-	}
-
-out:
-	return err;
-out_free:
-	kfree(log->bios_event_log);
-	kfree(log);
-	goto out;
-}
-
-static const struct file_operations tpm_ascii_bios_measurements_ops = {
-	.open = tpm_ascii_bios_measurements_open,
-	.read = seq_read,
-	.llseek = seq_lseek,
-	.release = tpm_bios_measurements_release,
-};
-
-static int tpm_binary_bios_measurements_open(struct inode *inode,
-					     struct file *file)
-{
-	int err;
-	struct tpm_bios_log *log;
-	struct seq_file *seq;
-
-	log = kzalloc(sizeof(struct tpm_bios_log), GFP_KERNEL);
-	if (!log)
-		return -ENOMEM;
-
-	if ((err = read_log(log)))
-		goto out_free;
-
-	/* now register seq file */
-	err = seq_open(file, &tpm_binary_b_measurments_seqops);
-	if (!err) {
-		seq = file->private_data;
-		seq->private = log;
-	} else {
-		goto out_free;
-	}
-
-out:
-	return err;
-out_free:
-	kfree(log->bios_event_log);
-	kfree(log);
-	goto out;
-}
-
-static const struct file_operations tpm_binary_bios_measurements_ops = {
-	.open = tpm_binary_bios_measurements_open,
-	.read = seq_read,
-	.llseek = seq_lseek,
-	.release = tpm_bios_measurements_release,
-};
-
-static int is_bad(void *p)
-{
-	if (!p)
-		return 1;
-	if (IS_ERR(p) && (PTR_ERR(p) != -ENODEV))
-		return 1;
-	return 0;
-}
-
-struct dentry **tpm_bios_log_setup(char *name)
-{
-	struct dentry **ret = NULL, *tpm_dir, *bin_file, *ascii_file;
-
-	tpm_dir = securityfs_create_dir(name, NULL);
-	if (is_bad(tpm_dir))
-		goto out;
-
-	bin_file =
-	    securityfs_create_file("binary_bios_measurements",
-				   S_IRUSR | S_IRGRP, tpm_dir, NULL,
-				   &tpm_binary_bios_measurements_ops);
-	if (is_bad(bin_file))
-		goto out_tpm;
-
-	ascii_file =
-	    securityfs_create_file("ascii_bios_measurements",
-				   S_IRUSR | S_IRGRP, tpm_dir, NULL,
-				   &tpm_ascii_bios_measurements_ops);
-	if (is_bad(ascii_file))
-		goto out_bin;
-
-	ret = kmalloc(3 * sizeof(struct dentry *), GFP_KERNEL);
-	if (!ret)
-		goto out_ascii;
-
-	ret[0] = ascii_file;
-	ret[1] = bin_file;
-	ret[2] = tpm_dir;
-
-	return ret;
-
-out_ascii:
-	securityfs_remove(ascii_file);
-out_bin:
-	securityfs_remove(bin_file);
-out_tpm:
-	securityfs_remove(tpm_dir);
-out:
-	return NULL;
-}
-EXPORT_SYMBOL_GPL(tpm_bios_log_setup);
-
-void tpm_bios_log_teardown(struct dentry **lst)
-{
-	int i;
-
-	for (i = 0; i < 3; i++)
-		securityfs_remove(lst[i]);
-}
-EXPORT_SYMBOL_GPL(tpm_bios_log_teardown);
-MODULE_LICENSE("GPL");
diff --git a/drivers/char/tpm/tpm_eventlog.c b/drivers/char/tpm/tpm_eventlog.c
new file mode 100644
index 0000000..84ddc55
--- /dev/null
+++ b/drivers/char/tpm/tpm_eventlog.c
@@ -0,0 +1,419 @@
+/*
+ * Copyright (C) 2005, 2012 IBM Corporation
+ *
+ * Authors:
+ *	Kent Yoder <key@linux.vnet.ibm.com>
+ *	Seiji Munetoh <munetoh@jp.ibm.com>
+ *	Stefan Berger <stefanb@us.ibm.com>
+ *	Reiner Sailer <sailer@watson.ibm.com>
+ *	Kylene Hall <kjhall@us.ibm.com>
+ *
+ * Maintained by: <tpmdd-devel@lists.sourceforge.net>
+ *
+ * Access to the eventlog created by a system's firmware / BIOS
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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/seq_file.h>
+#include <linux/fs.h>
+#include <linux/security.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include "tpm.h"
+#include "tpm_eventlog.h"
+
+
+static const char* tcpa_event_type_strings[] = {
+	"PREBOOT",
+	"POST CODE",
+	"",
+	"NO ACTION",
+	"SEPARATOR",
+	"ACTION",
+	"EVENT TAG",
+	"S-CRTM Contents",
+	"S-CRTM Version",
+	"CPU Microcode",
+	"Platform Config Flags",
+	"Table of Devices",
+	"Compact Hash",
+	"IPL",
+	"IPL Partition Data",
+	"Non-Host Code",
+	"Non-Host Config",
+	"Non-Host Info"
+};
+
+static const char* tcpa_pc_event_id_strings[] = {
+	"",
+	"SMBIOS",
+	"BIS Certificate",
+	"POST BIOS ",
+	"ESCD ",
+	"CMOS",
+	"NVRAM",
+	"Option ROM",
+	"Option ROM config",
+	"",
+	"Option ROM microcode ",
+	"S-CRTM Version",
+	"S-CRTM Contents ",
+	"POST Contents ",
+	"Table of Devices",
+};
+
+/* returns pointer to start of pos. entry of tcg log */
+static void *tpm_bios_measurements_start(struct seq_file *m, loff_t *pos)
+{
+	loff_t i;
+	struct tpm_bios_log *log = m->private;
+	void *addr = log->bios_event_log;
+	void *limit = log->bios_event_log_end;
+	struct tcpa_event *event;
+
+	/* read over *pos measurements */
+	for (i = 0; i < *pos; i++) {
+		event = addr;
+
+		if ((addr + sizeof(struct tcpa_event)) < limit) {
+			if (event->event_type == 0 && event->event_size == 0)
+				return NULL;
+			addr += sizeof(struct tcpa_event) + event->event_size;
+		}
+	}
+
+	/* now check if current entry is valid */
+	if ((addr + sizeof(struct tcpa_event)) >= limit)
+		return NULL;
+
+	event = addr;
+
+	if ((event->event_type == 0 && event->event_size == 0) ||
+	    ((addr + sizeof(struct tcpa_event) + event->event_size) >= limit))
+		return NULL;
+
+	return addr;
+}
+
+static void *tpm_bios_measurements_next(struct seq_file *m, void *v,
+					loff_t *pos)
+{
+	struct tcpa_event *event = v;
+	struct tpm_bios_log *log = m->private;
+	void *limit = log->bios_event_log_end;
+
+	v += sizeof(struct tcpa_event) + event->event_size;
+
+	/* now check if current entry is valid */
+	if ((v + sizeof(struct tcpa_event)) >= limit)
+		return NULL;
+
+	event = v;
+
+	if (event->event_type == 0 && event->event_size == 0)
+		return NULL;
+
+	if ((event->event_type == 0 && event->event_size == 0) ||
+	    ((v + sizeof(struct tcpa_event) + event->event_size) >= limit))
+		return NULL;
+
+	(*pos)++;
+	return v;
+}
+
+static void tpm_bios_measurements_stop(struct seq_file *m, void *v)
+{
+}
+
+static int get_event_name(char *dest, struct tcpa_event *event,
+			unsigned char * event_entry)
+{
+	const char *name = "";
+	/* 41 so there is room for 40 data and 1 nul */
+	char data[41] = "";
+	int i, n_len = 0, d_len = 0;
+	struct tcpa_pc_event *pc_event;
+
+	switch(event->event_type) {
+	case PREBOOT:
+	case POST_CODE:
+	case UNUSED:
+	case NO_ACTION:
+	case SCRTM_CONTENTS:
+	case SCRTM_VERSION:
+	case CPU_MICROCODE:
+	case PLATFORM_CONFIG_FLAGS:
+	case TABLE_OF_DEVICES:
+	case COMPACT_HASH:
+	case IPL:
+	case IPL_PARTITION_DATA:
+	case NONHOST_CODE:
+	case NONHOST_CONFIG:
+	case NONHOST_INFO:
+		name = tcpa_event_type_strings[event->event_type];
+		n_len = strlen(name);
+		break;
+	case SEPARATOR:
+	case ACTION:
+		if (MAX_TEXT_EVENT > event->event_size) {
+			name = event_entry;
+			n_len = event->event_size;
+		}
+		break;
+	case EVENT_TAG:
+		pc_event = (struct tcpa_pc_event *)event_entry;
+
+		/* ToDo Row data -> Base64 */
+
+		switch (pc_event->event_id) {
+		case SMBIOS:
+		case BIS_CERT:
+		case CMOS:
+		case NVRAM:
+		case OPTION_ROM_EXEC:
+		case OPTION_ROM_CONFIG:
+		case S_CRTM_VERSION:
+			name = tcpa_pc_event_id_strings[pc_event->event_id];
+			n_len = strlen(name);
+			break;
+		/* hash data */
+		case POST_BIOS_ROM:
+		case ESCD:
+		case OPTION_ROM_MICROCODE:
+		case S_CRTM_CONTENTS:
+		case POST_CONTENTS:
+			name = tcpa_pc_event_id_strings[pc_event->event_id];
+			n_len = strlen(name);
+			for (i = 0; i < 20; i++)
+				d_len += sprintf(&data[2*i], "%02x",
+						pc_event->event_data[i]);
+			break;
+		default:
+			break;
+		}
+	default:
+		break;
+	}
+
+	return snprintf(dest, MAX_TEXT_EVENT, "[%.*s%.*s]",
+			n_len, name, d_len, data);
+
+}
+
+static int tpm_binary_bios_measurements_show(struct seq_file *m, void *v)
+{
+	struct tcpa_event *event = v;
+	char *data = v;
+	int i;
+
+	for (i = 0; i < sizeof(struct tcpa_event) + event->event_size; i++)
+		seq_putc(m, data[i]);
+
+	return 0;
+}
+
+static int tpm_bios_measurements_release(struct inode *inode,
+					 struct file *file)
+{
+	struct seq_file *seq = file->private_data;
+	struct tpm_bios_log *log = seq->private;
+
+	if (log) {
+		kfree(log->bios_event_log);
+		kfree(log);
+	}
+
+	return seq_release(inode, file);
+}
+
+static int tpm_ascii_bios_measurements_show(struct seq_file *m, void *v)
+{
+	int len = 0;
+	int i;
+	char *eventname;
+	struct tcpa_event *event = v;
+	unsigned char *event_entry =
+	    (unsigned char *) (v + sizeof(struct tcpa_event));
+
+	eventname = kmalloc(MAX_TEXT_EVENT, GFP_KERNEL);
+	if (!eventname) {
+		printk(KERN_ERR "%s: ERROR - No Memory for event name\n ",
+		       __func__);
+		return -EFAULT;
+	}
+
+	seq_printf(m, "%2d ", event->pcr_index);
+
+	/* 2nd: SHA1 */
+	for (i = 0; i < 20; i++)
+		seq_printf(m, "%02x", event->pcr_value[i]);
+
+	/* 3rd: event type identifier */
+	seq_printf(m, " %02x", event->event_type);
+
+	len += get_event_name(eventname, event, event_entry);
+
+	/* 4th: eventname <= max + \'0' delimiter */
+	seq_printf(m, " %s\n", eventname);
+
+	kfree(eventname);
+	return 0;
+}
+
+static const struct seq_operations tpm_ascii_b_measurments_seqops = {
+	.start = tpm_bios_measurements_start,
+	.next = tpm_bios_measurements_next,
+	.stop = tpm_bios_measurements_stop,
+	.show = tpm_ascii_bios_measurements_show,
+};
+
+static const struct seq_operations tpm_binary_b_measurments_seqops = {
+	.start = tpm_bios_measurements_start,
+	.next = tpm_bios_measurements_next,
+	.stop = tpm_bios_measurements_stop,
+	.show = tpm_binary_bios_measurements_show,
+};
+
+static int tpm_ascii_bios_measurements_open(struct inode *inode,
+					    struct file *file)
+{
+	int err;
+	struct tpm_bios_log *log;
+	struct seq_file *seq;
+
+	log = kzalloc(sizeof(struct tpm_bios_log), GFP_KERNEL);
+	if (!log)
+		return -ENOMEM;
+
+	if ((err = read_log(log)))
+		goto out_free;
+
+	/* now register seq file */
+	err = seq_open(file, &tpm_ascii_b_measurments_seqops);
+	if (!err) {
+		seq = file->private_data;
+		seq->private = log;
+	} else {
+		goto out_free;
+	}
+
+out:
+	return err;
+out_free:
+	kfree(log->bios_event_log);
+	kfree(log);
+	goto out;
+}
+
+static const struct file_operations tpm_ascii_bios_measurements_ops = {
+	.open = tpm_ascii_bios_measurements_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = tpm_bios_measurements_release,
+};
+
+static int tpm_binary_bios_measurements_open(struct inode *inode,
+					     struct file *file)
+{
+	int err;
+	struct tpm_bios_log *log;
+	struct seq_file *seq;
+
+	log = kzalloc(sizeof(struct tpm_bios_log), GFP_KERNEL);
+	if (!log)
+		return -ENOMEM;
+
+	if ((err = read_log(log)))
+		goto out_free;
+
+	/* now register seq file */
+	err = seq_open(file, &tpm_binary_b_measurments_seqops);
+	if (!err) {
+		seq = file->private_data;
+		seq->private = log;
+	} else {
+		goto out_free;
+	}
+
+out:
+	return err;
+out_free:
+	kfree(log->bios_event_log);
+	kfree(log);
+	goto out;
+}
+
+static const struct file_operations tpm_binary_bios_measurements_ops = {
+	.open = tpm_binary_bios_measurements_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = tpm_bios_measurements_release,
+};
+
+static int is_bad(void *p)
+{
+	if (!p)
+		return 1;
+	if (IS_ERR(p) && (PTR_ERR(p) != -ENODEV))
+		return 1;
+	return 0;
+}
+
+struct dentry **tpm_bios_log_setup(char *name)
+{
+	struct dentry **ret = NULL, *tpm_dir, *bin_file, *ascii_file;
+
+	tpm_dir = securityfs_create_dir(name, NULL);
+	if (is_bad(tpm_dir))
+		goto out;
+
+	bin_file =
+	    securityfs_create_file("binary_bios_measurements",
+				   S_IRUSR | S_IRGRP, tpm_dir, NULL,
+				   &tpm_binary_bios_measurements_ops);
+	if (is_bad(bin_file))
+		goto out_tpm;
+
+	ascii_file =
+	    securityfs_create_file("ascii_bios_measurements",
+				   S_IRUSR | S_IRGRP, tpm_dir, NULL,
+				   &tpm_ascii_bios_measurements_ops);
+	if (is_bad(ascii_file))
+		goto out_bin;
+
+	ret = kmalloc(3 * sizeof(struct dentry *), GFP_KERNEL);
+	if (!ret)
+		goto out_ascii;
+
+	ret[0] = ascii_file;
+	ret[1] = bin_file;
+	ret[2] = tpm_dir;
+
+	return ret;
+
+out_ascii:
+	securityfs_remove(ascii_file);
+out_bin:
+	securityfs_remove(bin_file);
+out_tpm:
+	securityfs_remove(tpm_dir);
+out:
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(tpm_bios_log_setup);
+
+void tpm_bios_log_teardown(struct dentry **lst)
+{
+	int i;
+
+	for (i = 0; i < 3; i++)
+		securityfs_remove(lst[i]);
+}
+EXPORT_SYMBOL_GPL(tpm_bios_log_teardown);
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/tpm/tpm_eventlog.h b/drivers/char/tpm/tpm_eventlog.h
new file mode 100644
index 0000000..e7da086
--- /dev/null
+++ b/drivers/char/tpm/tpm_eventlog.h
@@ -0,0 +1,86 @@
+
+#ifndef __TPM_EVENTLOG_H__
+#define __TPM_EVENTLOG_H__
+
+#define TCG_EVENT_NAME_LEN_MAX	255
+#define MAX_TEXT_EVENT		1000	/* Max event string length */
+#define ACPI_TCPA_SIG		"TCPA"	/* 0x41504354 /'TCPA' */
+
+enum bios_platform_class {
+	BIOS_CLIENT = 0x00,
+	BIOS_SERVER = 0x01,
+};
+
+struct tpm_bios_log {
+	void *bios_event_log;
+	void *bios_event_log_end;
+};
+
+struct tcpa_event {
+	u32 pcr_index;
+	u32 event_type;
+	u8 pcr_value[20];	/* SHA1 */
+	u32 event_size;
+	u8 event_data[0];
+};
+
+enum tcpa_event_types {
+	PREBOOT = 0,
+	POST_CODE,
+	UNUSED,
+	NO_ACTION,
+	SEPARATOR,
+	ACTION,
+	EVENT_TAG,
+	SCRTM_CONTENTS,
+	SCRTM_VERSION,
+	CPU_MICROCODE,
+	PLATFORM_CONFIG_FLAGS,
+	TABLE_OF_DEVICES,
+	COMPACT_HASH,
+	IPL,
+	IPL_PARTITION_DATA,
+	NONHOST_CODE,
+	NONHOST_CONFIG,
+	NONHOST_INFO,
+};
+
+struct tcpa_pc_event {
+	u32 event_id;
+	u32 event_size;
+	u8 event_data[0];
+};
+
+enum tcpa_pc_event_ids {
+	SMBIOS = 1,
+	BIS_CERT,
+	POST_BIOS_ROM,
+	ESCD,
+	CMOS,
+	NVRAM,
+	OPTION_ROM_EXEC,
+	OPTION_ROM_CONFIG,
+	OPTION_ROM_MICROCODE = 10,
+	S_CRTM_VERSION,
+	S_CRTM_CONTENTS,
+	POST_CONTENTS,
+	HOST_TABLE_OF_DEVICES,
+};
+
+int read_log(struct tpm_bios_log *log);
+
+#if defined(CONFIG_TCG_IBMVTPM) || defined(CONFIG_TCG_IBMVTPM_MODULE) || \
+	defined(CONFIG_ACPI)
+extern struct dentry **tpm_bios_log_setup(char *);
+extern void tpm_bios_log_teardown(struct dentry **);
+#else
+static inline struct dentry **tpm_bios_log_setup(char *name)
+{
+	return NULL;
+}
+static inline void tpm_bios_log_teardown(struct dentry **dir)
+{
+}
+#endif
+
+#endif
diff --git a/drivers/char/tpm/tpm_i2c_infineon.c b/drivers/char/tpm/tpm_i2c_infineon.c
new file mode 100644
index 0000000..5a831ae
--- /dev/null
+++ b/drivers/char/tpm/tpm_i2c_infineon.c
@@ -0,0 +1,695 @@
+/*
+ * Copyright (C) 2012 Infineon Technologies
+ *
+ * Authors:
+ * Peter Huewe <peter.huewe@infineon.com>
+ *
+ * Device driver for TCG/TCPA TPM (trusted platform module).
+ * Specifications at www.trustedcomputinggroup.org
+ *
+ * This device driver implements the TPM interface as defined in
+ * the TCG TPM Interface Spec version 1.2, revision 1.0 and the
+ * Infineon I2C Protocol Stack Specification v0.20.
+ *
+ * It is based on the original tpm_tis device driver from Leendert van
+ * Dorn and Kyleen Hall.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ *
+ */
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/wait.h>
+#include "tpm.h"
+
+/* max. buffer size supported by our TPM */
+#define TPM_BUFSIZE 1260
+
+/* max. number of iterations after I2C NAK */
+#define MAX_COUNT 3
+
+#define SLEEP_DURATION_LOW 55
+#define SLEEP_DURATION_HI 65
+
+/* max. number of iterations after I2C NAK for 'long' commands
+ * we need this especially for sending TPM_READY, since the cleanup after the
+ * transtion to the ready state may take some time, but it is unpredictable
+ * how long it will take.
+ */
+#define MAX_COUNT_LONG 50
+
+#define SLEEP_DURATION_LONG_LOW 200
+#define SLEEP_DURATION_LONG_HI 220
+
+/* After sending TPM_READY to 'reset' the TPM we have to sleep even longer */
+#define SLEEP_DURATION_RESET_LOW 2400
+#define SLEEP_DURATION_RESET_HI 2600
+
+/* we want to use usleep_range instead of msleep for the 5ms TPM_TIMEOUT */
+#define TPM_TIMEOUT_US_LOW (TPM_TIMEOUT * 1000)
+#define TPM_TIMEOUT_US_HI  (TPM_TIMEOUT_US_LOW + 2000)
+
+/* expected value for DIDVID register */
+#define TPM_TIS_I2C_DID_VID 0x000b15d1L
+
+/* Structure to store I2C TPM specific stuff */
+struct tpm_inf_dev {
+	struct i2c_client *client;
+	u8 buf[TPM_BUFSIZE + sizeof(u8)]; /* max. buffer size + addr */
+	struct tpm_chip *chip;
+};
+
+static struct tpm_inf_dev tpm_dev;
+static struct i2c_driver tpm_tis_i2c_driver;
+
+/*
+ * iic_tpm_read() - read from TPM register
+ * @addr: register address to read from
+ * @buffer: provided by caller
+ * @len: number of bytes to read
+ *
+ * Read len bytes from TPM register and put them into
+ * buffer (little-endian format, i.e. first byte is put into buffer[0]).
+ *
+ * NOTE: TPM is big-endian for multi-byte values. Multi-byte
+ * values have to be swapped.
+ *
+ * NOTE: We can't unfortunately use the combined read/write functions
+ * provided by the i2c core as the TPM currently does not support the
+ * repeated start condition and due to it's special requirements.
+ * The i2c_smbus* functions do not work for this chip.
+ *
+ * Return -EIO on error, 0 on success.
+ */
+static int iic_tpm_read(u8 addr, u8 *buffer, size_t len)
+{
+
+	struct i2c_msg msg1 = { tpm_dev.client->addr, 0, 1, &addr };
+	struct i2c_msg msg2 = { tpm_dev.client->addr, I2C_M_RD, len, buffer };
+
+	int rc;
+	int count;
+
+	/* Lock the adapter for the duration of the whole sequence. */
+	if (!tpm_dev.client->adapter->algo->master_xfer)
+		return -EOPNOTSUPP;
+	i2c_lock_adapter(tpm_dev.client->adapter);
+
+	for (count = 0; count < MAX_COUNT; count++) {
+		rc = __i2c_transfer(tpm_dev.client->adapter, &msg1, 1);
+		if (rc > 0)
+			break;	/* break here to skip sleep */
+
+		usleep_range(SLEEP_DURATION_LOW, SLEEP_DURATION_HI);
+	}
+
+	if (rc <= 0)
+		goto out;
+
+	/* After the TPM has successfully received the register address it needs
+	 * some time, thus we're sleeping here again, before retrieving the data
+	 */
+	for (count = 0; count < MAX_COUNT; count++) {
+		usleep_range(SLEEP_DURATION_LOW, SLEEP_DURATION_HI);
+		rc = __i2c_transfer(tpm_dev.client->adapter, &msg2, 1);
+		if (rc > 0)
+			break;
+
+	}
+
+out:
+	i2c_unlock_adapter(tpm_dev.client->adapter);
+	if (rc <= 0)
+		return -EIO;
+
+	return 0;
+}
+
+static int iic_tpm_write_generic(u8 addr, u8 *buffer, size_t len,
+				 unsigned int sleep_low,
+				 unsigned int sleep_hi, u8 max_count)
+{
+	int rc = -EIO;
+	int count;
+
+	struct i2c_msg msg1 = { tpm_dev.client->addr, 0, len + 1, tpm_dev.buf };
+
+	if (len > TPM_BUFSIZE)
+		return -EINVAL;
+
+	if (!tpm_dev.client->adapter->algo->master_xfer)
+		return -EOPNOTSUPP;
+	i2c_lock_adapter(tpm_dev.client->adapter);
+
+	/* prepend the 'register address' to the buffer */
+	tpm_dev.buf[0] = addr;
+	memcpy(&(tpm_dev.buf[1]), buffer, len);
+
+	/*
+	 * NOTE: We have to use these special mechanisms here and unfortunately
+	 * cannot rely on the standard behavior of i2c_transfer.
+	 */
+	for (count = 0; count < max_count; count++) {
+		rc = __i2c_transfer(tpm_dev.client->adapter, &msg1, 1);
+		if (rc > 0)
+			break;
+
+		usleep_range(sleep_low, sleep_hi);
+	}
+
+	i2c_unlock_adapter(tpm_dev.client->adapter);
+	if (rc <= 0)
+		return -EIO;
+
+	return 0;
+}
+
+/*
+ * iic_tpm_write() - write to TPM register
+ * @addr: register address to write to
+ * @buffer: containing data to be written
+ * @len: number of bytes to write
+ *
+ * Write len bytes from provided buffer to TPM register (little
+ * endian format, i.e. buffer[0] is written as first byte).
+ *
+ * NOTE: TPM is big-endian for multi-byte values. Multi-byte
+ * values have to be swapped.
+ *
+ * NOTE: use this function instead of the iic_tpm_write_generic function.
+ *
+ * Return -EIO on error, 0 on success
+ */
+static int iic_tpm_write(u8 addr, u8 *buffer, size_t len)
+{
+	return iic_tpm_write_generic(addr, buffer, len, SLEEP_DURATION_LOW,
+				     SLEEP_DURATION_HI, MAX_COUNT);
+}
+
+/*
+ * This function is needed especially for the cleanup situation after
+ * sending TPM_READY
+ * */
+static int iic_tpm_write_long(u8 addr, u8 *buffer, size_t len)
+{
+	return iic_tpm_write_generic(addr, buffer, len, SLEEP_DURATION_LONG_LOW,
+				     SLEEP_DURATION_LONG_HI, MAX_COUNT_LONG);
+}
+
+enum tis_access {
+	TPM_ACCESS_VALID = 0x80,
+	TPM_ACCESS_ACTIVE_LOCALITY = 0x20,
+	TPM_ACCESS_REQUEST_PENDING = 0x04,
+	TPM_ACCESS_REQUEST_USE = 0x02,
+};
+
+enum tis_status {
+	TPM_STS_VALID = 0x80,
+	TPM_STS_COMMAND_READY = 0x40,
+	TPM_STS_GO = 0x20,
+	TPM_STS_DATA_AVAIL = 0x10,
+	TPM_STS_DATA_EXPECT = 0x08,
+};
+
+enum tis_defaults {
+	TIS_SHORT_TIMEOUT = 750,	/* ms */
+	TIS_LONG_TIMEOUT = 2000,	/* 2 sec */
+};
+
+#define	TPM_ACCESS(l)			(0x0000 | ((l) << 4))
+#define	TPM_STS(l)			(0x0001 | ((l) << 4))
+#define	TPM_DATA_FIFO(l)		(0x0005 | ((l) << 4))
+#define	TPM_DID_VID(l)			(0x0006 | ((l) << 4))
+
+static int check_locality(struct tpm_chip *chip, int loc)
+{
+	u8 buf;
+	int rc;
+
+	rc = iic_tpm_read(TPM_ACCESS(loc), &buf, 1);
+	if (rc < 0)
+		return rc;
+
+	if ((buf & (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) ==
+	    (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) {
+		chip->vendor.locality = loc;
+		return loc;
+	}
+
+	return -EIO;
+}
+
+/* implementation similar to tpm_tis */
+static void release_locality(struct tpm_chip *chip, int loc, int force)
+{
+	u8 buf;
+	if (iic_tpm_read(TPM_ACCESS(loc), &buf, 1) < 0)
+		return;
+
+	if (force || (buf & (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) ==
+	    (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) {
+		buf = TPM_ACCESS_ACTIVE_LOCALITY;
+		iic_tpm_write(TPM_ACCESS(loc), &buf, 1);
+	}
+}
+
+static int request_locality(struct tpm_chip *chip, int loc)
+{
+	unsigned long stop;
+	u8 buf = TPM_ACCESS_REQUEST_USE;
+
+	if (check_locality(chip, loc) >= 0)
+		return loc;
+
+	iic_tpm_write(TPM_ACCESS(loc), &buf, 1);
+
+	/* wait for burstcount */
+	stop = jiffies + chip->vendor.timeout_a;
+	do {
+		if (check_locality(chip, loc) >= 0)
+			return loc;
+		usleep_range(TPM_TIMEOUT_US_LOW, TPM_TIMEOUT_US_HI);
+	} while (time_before(jiffies, stop));
+
+	return -ETIME;
+}
+
+static u8 tpm_tis_i2c_status(struct tpm_chip *chip)
+{
+	/* NOTE: since I2C read may fail, return 0 in this case --> time-out */
+	u8 buf;
+	if (iic_tpm_read(TPM_STS(chip->vendor.locality), &buf, 1) < 0)
+		return 0;
+	else
+		return buf;
+}
+
+static void tpm_tis_i2c_ready(struct tpm_chip *chip)
+{
+	/* this causes the current command to be aborted */
+	u8 buf = TPM_STS_COMMAND_READY;
+	iic_tpm_write_long(TPM_STS(chip->vendor.locality), &buf, 1);
+}
+
+static ssize_t get_burstcount(struct tpm_chip *chip)
+{
+	unsigned long stop;
+	ssize_t burstcnt;
+	u8 buf[3];
+
+	/* wait for burstcount */
+	/* which timeout value, spec has 2 answers (c & d) */
+	stop = jiffies + chip->vendor.timeout_d;
+	do {
+		/* Note: STS is little endian */
+		if (iic_tpm_read(TPM_STS(chip->vendor.locality)+1, buf, 3) < 0)
+			burstcnt = 0;
+		else
+			burstcnt = (buf[2] << 16) + (buf[1] << 8) + buf[0];
+
+		if (burstcnt)
+			return burstcnt;
+
+		usleep_range(TPM_TIMEOUT_US_LOW, TPM_TIMEOUT_US_HI);
+	} while (time_before(jiffies, stop));
+	return -EBUSY;
+}
+
+static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout,
+			 int *status)
+{
+	unsigned long stop;
+
+	/* check current status */
+	*status = tpm_tis_i2c_status(chip);
+	if ((*status & mask) == mask)
+		return 0;
+
+	stop = jiffies + timeout;
+	do {
+		/* since we just checked the status, give the TPM some time */
+		usleep_range(TPM_TIMEOUT_US_LOW, TPM_TIMEOUT_US_HI);
+		*status = tpm_tis_i2c_status(chip);
+		if ((*status & mask) == mask)
+			return 0;
+
+	} while (time_before(jiffies, stop));
+
+	return -ETIME;
+}
+
+static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count)
+{
+	size_t size = 0;
+	ssize_t burstcnt;
+	u8 retries = 0;
+	int rc;
+
+	while (size < count) {
+		burstcnt = get_burstcount(chip);
+
+		/* burstcnt < 0 = TPM is busy */
+		if (burstcnt < 0)
+			return burstcnt;
+
+		/* limit received data to max. left */
+		if (burstcnt > (count - size))
+			burstcnt = count - size;
+
+		rc = iic_tpm_read(TPM_DATA_FIFO(chip->vendor.locality),
+				  &(buf[size]), burstcnt);
+		if (rc == 0)
+			size += burstcnt;
+		else if (rc < 0)
+			retries++;
+
+		/* avoid endless loop in case of broken HW */
+		if (retries > MAX_COUNT_LONG)
+			return -EIO;
+
+	}
+	return size;
+}
+
+static int tpm_tis_i2c_recv(struct tpm_chip *chip, u8 *buf, size_t count)
+{
+	int size = 0;
+	int expected, status;
+
+	if (count < TPM_HEADER_SIZE) {
+		size = -EIO;
+		goto out;
+	}
+
+	/* read first 10 bytes, including tag, paramsize, and result */
+	size = recv_data(chip, buf, TPM_HEADER_SIZE);
+	if (size < TPM_HEADER_SIZE) {
+		dev_err(chip->dev, "Unable to read header\n");
+		goto out;
+	}
+
+	expected = be32_to_cpu(*(__be32 *)(buf + 2));
+	if ((size_t) expected > count) {
+		size = -EIO;
+		goto out;
+	}
+
+	size += recv_data(chip, &buf[TPM_HEADER_SIZE],
+			  expected - TPM_HEADER_SIZE);
+	if (size < expected) {
+		dev_err(chip->dev, "Unable to read remainder of result\n");
+		size = -ETIME;
+		goto out;
+	}
+
+	wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, &status);
+	if (status & TPM_STS_DATA_AVAIL) {	/* retry? */
+		dev_err(chip->dev, "Error left over data\n");
+		size = -EIO;
+		goto out;
+	}
+
+out:
+	tpm_tis_i2c_ready(chip);
+	/* The TPM needs some time to clean up here,
+	 * so we sleep rather than keeping the bus busy
+	 */
+	usleep_range(SLEEP_DURATION_RESET_LOW, SLEEP_DURATION_RESET_HI);
+	release_locality(chip, chip->vendor.locality, 0);
+	return size;
+}
+
+static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len)
+{
+	int rc, status;
+	ssize_t burstcnt;
+	size_t count = 0;
+	u8 retries = 0;
+	u8 sts = TPM_STS_GO;
+
+	if (len > TPM_BUFSIZE)
+		return -E2BIG;	/* command is too long for our tpm, sorry */
+
+	if (request_locality(chip, 0) < 0)
+		return -EBUSY;
+
+	status = tpm_tis_i2c_status(chip);
+	if ((status & TPM_STS_COMMAND_READY) == 0) {
+		tpm_tis_i2c_ready(chip);
+		if (wait_for_stat
+		    (chip, TPM_STS_COMMAND_READY,
+		     chip->vendor.timeout_b, &status) < 0) {
+			rc = -ETIME;
+			goto out_err;
+		}
+	}
+
+	while (count < len - 1) {
+		burstcnt = get_burstcount(chip);
+
+		/* burstcnt < 0 = TPM is busy */
+		if (burstcnt < 0)
+			return burstcnt;
+
+		if (burstcnt > (len - 1 - count))
+			burstcnt = len - 1 - count;
+
+		rc = iic_tpm_write(TPM_DATA_FIFO(chip->vendor.locality),
+				   &(buf[count]), burstcnt);
+		if (rc == 0)
+			count += burstcnt;
+		else if (rc < 0)
+			retries++;
+
+		/* avoid endless loop in case of broken HW */
+		if (retries > MAX_COUNT_LONG) {
+			rc = -EIO;
+			goto out_err;
+		}
+
+		wait_for_stat(chip, TPM_STS_VALID,
+			      chip->vendor.timeout_c, &status);
+
+		if ((status & TPM_STS_DATA_EXPECT) == 0) {
+			rc = -EIO;
+			goto out_err;
+		}
+
+	}
+
+	/* write last byte */
+	iic_tpm_write(TPM_DATA_FIFO(chip->vendor.locality), &(buf[count]), 1);
+	wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, &status);
+	if ((status & TPM_STS_DATA_EXPECT) != 0) {
+		rc = -EIO;
+		goto out_err;
+	}
+
+	/* go and do it */
+	iic_tpm_write(TPM_STS(chip->vendor.locality), &sts, 1);
+
+	return len;
+out_err:
+	tpm_tis_i2c_ready(chip);
+	/* The TPM needs some time to clean up here,
+	 * so we sleep rather than keeping the bus busy
+	 */
+	usleep_range(SLEEP_DURATION_RESET_LOW, SLEEP_DURATION_RESET_HI);
+	release_locality(chip, chip->vendor.locality, 0);
+	return rc;
+}
+
+static const struct file_operations tis_ops = {
+	.owner = THIS_MODULE,
+	.llseek = no_llseek,
+	.open = tpm_open,
+	.read = tpm_read,
+	.write = tpm_write,
+	.release = tpm_release,
+};
+
+static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL);
+static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL);
+static DEVICE_ATTR(enabled, S_IRUGO, tpm_show_enabled, NULL);
+static DEVICE_ATTR(active, S_IRUGO, tpm_show_active, NULL);
+static DEVICE_ATTR(owned, S_IRUGO, tpm_show_owned, NULL);
+static DEVICE_ATTR(temp_deactivated, S_IRUGO, tpm_show_temp_deactivated, NULL);
+static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps_1_2, NULL);
+static DEVICE_ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tpm_store_cancel);
+static DEVICE_ATTR(durations, S_IRUGO, tpm_show_durations, NULL);
+static DEVICE_ATTR(timeouts, S_IRUGO, tpm_show_timeouts, NULL);
+
+static struct attribute *tis_attrs[] = {
+	&dev_attr_pubek.attr,
+	&dev_attr_pcrs.attr,
+	&dev_attr_enabled.attr,
+	&dev_attr_active.attr,
+	&dev_attr_owned.attr,
+	&dev_attr_temp_deactivated.attr,
+	&dev_attr_caps.attr,
+	&dev_attr_cancel.attr,
+	&dev_attr_durations.attr,
+	&dev_attr_timeouts.attr,
+	NULL,
+};
+
+static struct attribute_group tis_attr_grp = {
+	.attrs = tis_attrs
+};
+
+static struct tpm_vendor_specific tpm_tis_i2c = {
+	.status = tpm_tis_i2c_status,
+	.recv = tpm_tis_i2c_recv,
+	.send = tpm_tis_i2c_send,
+	.cancel = tpm_tis_i2c_ready,
+	.req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
+	.req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
+	.req_canceled = TPM_STS_COMMAND_READY,
+	.attr_group = &tis_attr_grp,
+	.miscdev.fops = &tis_ops,
+};
+
+static int __devinit tpm_tis_i2c_init(struct device *dev)
+{
+	u32 vendor;
+	int rc = 0;
+	struct tpm_chip *chip;
+
+	chip = tpm_register_hardware(dev, &tpm_tis_i2c);
+	if (!chip) {
+		rc = -ENODEV;
+		goto out_err;
+	}
+
+	/* Disable interrupts */
+	chip->vendor.irq = 0;
+
+	/* Default timeouts */
+	chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
+	chip->vendor.timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT);
+	chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
+	chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
+
+	if (request_locality(chip, 0) != 0) {
+		rc = -ENODEV;
+		goto out_vendor;
+	}
+
+	/* read four bytes from DID_VID register */
+	if (iic_tpm_read(TPM_DID_VID(0), (u8 *)&vendor, 4) < 0) {
+		rc = -EIO;
+		goto out_release;
+	}
+
+	/* create DID_VID register value, after swapping to little-endian */
+	vendor = be32_to_cpu((__be32) vendor);
+
+	if (vendor != TPM_TIS_I2C_DID_VID) {
+		rc = -ENODEV;
+		goto out_release;
+	}
+
+	dev_info(dev, "1.2 TPM (device-id 0x%X)\n", vendor >> 16);
+
+	INIT_LIST_HEAD(&chip->vendor.list);
+	tpm_dev.chip = chip;
+
+	tpm_get_timeouts(chip);
+	tpm_do_selftest(chip);
+
+	return 0;
+
+out_release:
+	release_locality(chip, chip->vendor.locality, 1);
+
+out_vendor:
+	/* close file handles */
+	tpm_dev_vendor_release(chip);
+
+	/* remove hardware */
+	tpm_remove_hardware(chip->dev);
+
+	/* reset these pointers, otherwise we oops */
+	chip->dev->release = NULL;
+	chip->release = NULL;
+	tpm_dev.client = NULL;
+	dev_set_drvdata(chip->dev, chip);
+out_err:
+	return rc;
+}
+
+static const struct i2c_device_id tpm_tis_i2c_table[] = {
+	{"tpm_i2c_infineon", 0},
+	{},
+};
+
+MODULE_DEVICE_TABLE(i2c, tpm_tis_i2c_table);
+static SIMPLE_DEV_PM_OPS(tpm_tis_i2c_ops, tpm_pm_suspend, tpm_pm_resume);
+
+static int __devinit tpm_tis_i2c_probe(struct i2c_client *client,
+			     const struct i2c_device_id *id)
+{
+	int rc;
+	if (tpm_dev.client != NULL)
+		return -EBUSY;	/* We only support one client */
+
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+		dev_err(&client->dev,
+			"no algorithms associated to the i2c bus\n");
+		return -ENODEV;
+	}
+
+	client->driver = &tpm_tis_i2c_driver;
+	tpm_dev.client = client;
+	rc = tpm_tis_i2c_init(&client->dev);
+	if (rc != 0) {
+		client->driver = NULL;
+		tpm_dev.client = NULL;
+		rc = -ENODEV;
+	}
+	return rc;
+}
+
+static int __devexit tpm_tis_i2c_remove(struct i2c_client *client)
+{
+	struct tpm_chip *chip = tpm_dev.chip;
+	release_locality(chip, chip->vendor.locality, 1);
+
+	/* close file handles */
+	tpm_dev_vendor_release(chip);
+
+	/* remove hardware */
+	tpm_remove_hardware(chip->dev);
+
+	/* reset these pointers, otherwise we oops */
+	chip->dev->release = NULL;
+	chip->release = NULL;
+	tpm_dev.client = NULL;
+	dev_set_drvdata(chip->dev, chip);
+
+	return 0;
+}
+
+static struct i2c_driver tpm_tis_i2c_driver = {
+
+	.id_table = tpm_tis_i2c_table,
+	.probe = tpm_tis_i2c_probe,
+	.remove = tpm_tis_i2c_remove,
+	.driver = {
+		   .name = "tpm_i2c_infineon",
+		   .owner = THIS_MODULE,
+		   .pm = &tpm_tis_i2c_ops,
+		   },
+};
+
+module_i2c_driver(tpm_tis_i2c_driver);
+MODULE_AUTHOR("Peter Huewe <peter.huewe@infineon.com>");
+MODULE_DESCRIPTION("TPM TIS I2C Infineon Driver");
+MODULE_VERSION("2.1.5");
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/tpm/tpm_ibmvtpm.c b/drivers/char/tpm/tpm_ibmvtpm.c
new file mode 100644
index 0000000..efc4ab3
--- /dev/null
+++ b/drivers/char/tpm/tpm_ibmvtpm.c
@@ -0,0 +1,749 @@
+/*
+ * Copyright (C) 2012 IBM Corporation
+ *
+ * Author: Ashley Lai <adlai@us.ibm.com>
+ *
+ * Maintained by: <tpmdd-devel@lists.sourceforge.net>
+ *
+ * Device driver for TCG/TCPA TPM (trusted platform module).
+ * Specifications at www.trustedcomputinggroup.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, version 2 of the
+ * License.
+ *
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/dmapool.h>
+#include <linux/slab.h>
+#include <asm/vio.h>
+#include <asm/irq.h>
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/wait.h>
+#include <asm/prom.h>
+
+#include "tpm.h"
+#include "tpm_ibmvtpm.h"
+
+static const char tpm_ibmvtpm_driver_name[] = "tpm_ibmvtpm";
+
+static struct vio_device_id tpm_ibmvtpm_device_table[] __devinitdata = {
+	{ "IBM,vtpm", "IBM,vtpm"},
+	{ "", "" }
+};
+MODULE_DEVICE_TABLE(vio, tpm_ibmvtpm_device_table);
+
+DECLARE_WAIT_QUEUE_HEAD(wq);
+
+/**
+ * ibmvtpm_send_crq - Send a CRQ request
+ * @vdev:	vio device struct
+ * @w1:		first word
+ * @w2:		second word
+ *
+ * Return value:
+ *	0 -Sucess
+ *	Non-zero - Failure
+ */
+static int ibmvtpm_send_crq(struct vio_dev *vdev, u64 w1, u64 w2)
+{
+	return plpar_hcall_norets(H_SEND_CRQ, vdev->unit_address, w1, w2);
+}
+
+/**
+ * ibmvtpm_get_data - Retrieve ibm vtpm data
+ * @dev:	device struct
+ *
+ * Return value:
+ *	vtpm device struct
+ */
+static struct ibmvtpm_dev *ibmvtpm_get_data(const struct device *dev)
+{
+	struct tpm_chip *chip = dev_get_drvdata(dev);
+	if (chip)
+		return (struct ibmvtpm_dev *)chip->vendor.data;
+	return NULL;
+}
+
+/**
+ * tpm_ibmvtpm_recv - Receive data after send
+ * @chip:	tpm chip struct
+ * @buf:	buffer to read
+ * count:	size of buffer
+ *
+ * Return value:
+ *	Number of bytes read
+ */
+static int tpm_ibmvtpm_recv(struct tpm_chip *chip, u8 *buf, size_t count)
+{
+	struct ibmvtpm_dev *ibmvtpm;
+	u16 len;
+
+	ibmvtpm = (struct ibmvtpm_dev *)chip->vendor.data;
+
+	if (!ibmvtpm->rtce_buf) {
+		dev_err(ibmvtpm->dev, "ibmvtpm device is not ready\n");
+		return 0;
+	}
+
+	wait_event_interruptible(wq, ibmvtpm->crq_res.len != 0);
+
+	if (count < ibmvtpm->crq_res.len) {
+		dev_err(ibmvtpm->dev,
+			"Invalid size in recv: count=%ld, crq_size=%d\n",
+			count, ibmvtpm->crq_res.len);
+		return -EIO;
+	}
+
+	spin_lock(&ibmvtpm->rtce_lock);
+	memcpy((void *)buf, (void *)ibmvtpm->rtce_buf, ibmvtpm->crq_res.len);
+	memset(ibmvtpm->rtce_buf, 0, ibmvtpm->crq_res.len);
+	ibmvtpm->crq_res.valid = 0;
+	ibmvtpm->crq_res.msg = 0;
+	len = ibmvtpm->crq_res.len;
+	ibmvtpm->crq_res.len = 0;
+	spin_unlock(&ibmvtpm->rtce_lock);
+	return len;
+}
+
+/**
+ * tpm_ibmvtpm_send - Send tpm request
+ * @chip:	tpm chip struct
+ * @buf:	buffer contains data to send
+ * count:	size of buffer
+ *
+ * Return value:
+ *	Number of bytes sent
+ */
+static int tpm_ibmvtpm_send(struct tpm_chip *chip, u8 *buf, size_t count)
+{
+	struct ibmvtpm_dev *ibmvtpm;
+	struct ibmvtpm_crq crq;
+	u64 *word = (u64 *) &crq;
+	int rc;
+
+	ibmvtpm = (struct ibmvtpm_dev *)chip->vendor.data;
+
+	if (!ibmvtpm->rtce_buf) {
+		dev_err(ibmvtpm->dev, "ibmvtpm device is not ready\n");
+		return 0;
+	}
+
+	if (count > ibmvtpm->rtce_size) {
+		dev_err(ibmvtpm->dev,
+			"Invalid size in send: count=%ld, rtce_size=%d\n",
+			count, ibmvtpm->rtce_size);
+		return -EIO;
+	}
+
+	spin_lock(&ibmvtpm->rtce_lock);
+	memcpy((void *)ibmvtpm->rtce_buf, (void *)buf, count);
+	crq.valid = (u8)IBMVTPM_VALID_CMD;
+	crq.msg = (u8)VTPM_TPM_COMMAND;
+	crq.len = (u16)count;
+	crq.data = ibmvtpm->rtce_dma_handle;
+
+	rc = ibmvtpm_send_crq(ibmvtpm->vdev, word[0], word[1]);
+	if (rc != H_SUCCESS) {
+		dev_err(ibmvtpm->dev, "tpm_ibmvtpm_send failed rc=%d\n", rc);
+		rc = 0;
+	} else
+		rc = count;
+
+	spin_unlock(&ibmvtpm->rtce_lock);
+	return rc;
+}
+
+static void tpm_ibmvtpm_cancel(struct tpm_chip *chip)
+{
+	return;
+}
+
+static u8 tpm_ibmvtpm_status(struct tpm_chip *chip)
+{
+	return 0;
+}
+
+/**
+ * ibmvtpm_crq_get_rtce_size - Send a CRQ request to get rtce size
+ * @ibmvtpm:	vtpm device struct
+ *
+ * Return value:
+ *	0 - Success
+ *	Non-zero - Failure
+ */
+static int ibmvtpm_crq_get_rtce_size(struct ibmvtpm_dev *ibmvtpm)
+{
+	struct ibmvtpm_crq crq;
+	u64 *buf = (u64 *) &crq;
+	int rc;
+
+	crq.valid = (u8)IBMVTPM_VALID_CMD;
+	crq.msg = (u8)VTPM_GET_RTCE_BUFFER_SIZE;
+
+	rc = ibmvtpm_send_crq(ibmvtpm->vdev, buf[0], buf[1]);
+	if (rc != H_SUCCESS)
+		dev_err(ibmvtpm->dev,
+			"ibmvtpm_crq_get_rtce_size failed rc=%d\n", rc);
+
+	return rc;
+}
+
+/**
+ * ibmvtpm_crq_get_version - Send a CRQ request to get vtpm version
+ *			   - Note that this is vtpm version and not tpm version
+ * @ibmvtpm:	vtpm device struct
+ *
+ * Return value:
+ *	0 - Success
+ *	Non-zero - Failure
+ */
+static int ibmvtpm_crq_get_version(struct ibmvtpm_dev *ibmvtpm)
+{
+	struct ibmvtpm_crq crq;
+	u64 *buf = (u64 *) &crq;
+	int rc;
+
+	crq.valid = (u8)IBMVTPM_VALID_CMD;
+	crq.msg = (u8)VTPM_GET_VERSION;
+
+	rc = ibmvtpm_send_crq(ibmvtpm->vdev, buf[0], buf[1]);
+	if (rc != H_SUCCESS)
+		dev_err(ibmvtpm->dev,
+			"ibmvtpm_crq_get_version failed rc=%d\n", rc);
+
+	return rc;
+}
+
+/**
+ * ibmvtpm_crq_send_init_complete - Send a CRQ initialize complete message
+ * @ibmvtpm:	vtpm device struct
+ *
+ * Return value:
+ *	0 - Success
+ *	Non-zero - Failure
+ */
+static int ibmvtpm_crq_send_init_complete(struct ibmvtpm_dev *ibmvtpm)
+{
+	int rc;
+
+	rc = ibmvtpm_send_crq(ibmvtpm->vdev, INIT_CRQ_COMP_CMD, 0);
+	if (rc != H_SUCCESS)
+		dev_err(ibmvtpm->dev,
+			"ibmvtpm_crq_send_init_complete failed rc=%d\n", rc);
+
+	return rc;
+}
+
+/**
+ * ibmvtpm_crq_send_init - Send a CRQ initialize message
+ * @ibmvtpm:	vtpm device struct
+ *
+ * Return value:
+ *	0 - Success
+ *	Non-zero - Failure
+ */
+static int ibmvtpm_crq_send_init(struct ibmvtpm_dev *ibmvtpm)
+{
+	int rc;
+
+	rc = ibmvtpm_send_crq(ibmvtpm->vdev, INIT_CRQ_CMD, 0);
+	if (rc != H_SUCCESS)
+		dev_err(ibmvtpm->dev,
+			"ibmvtpm_crq_send_init failed rc=%d\n", rc);
+
+	return rc;
+}
+
+/**
+ * tpm_ibmvtpm_remove - ibm vtpm remove entry point
+ * @vdev:	vio device struct
+ *
+ * Return value:
+ *	0
+ */
+static int __devexit tpm_ibmvtpm_remove(struct vio_dev *vdev)
+{
+	struct ibmvtpm_dev *ibmvtpm = ibmvtpm_get_data(&vdev->dev);
+	int rc = 0;
+
+	free_irq(vdev->irq, ibmvtpm);
+	tasklet_kill(&ibmvtpm->tasklet);
+
+	do {
+		if (rc)
+			msleep(100);
+		rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address);
+	} while (rc == H_BUSY || H_IS_LONG_BUSY(rc));
+
+	dma_unmap_single(ibmvtpm->dev, ibmvtpm->crq_dma_handle,
+			 CRQ_RES_BUF_SIZE, DMA_BIDIRECTIONAL);
+	free_page((unsigned long)ibmvtpm->crq_queue.crq_addr);
+
+	if (ibmvtpm->rtce_buf) {
+		dma_unmap_single(ibmvtpm->dev, ibmvtpm->rtce_dma_handle,
+				 ibmvtpm->rtce_size, DMA_BIDIRECTIONAL);
+		kfree(ibmvtpm->rtce_buf);
+	}
+
+	tpm_remove_hardware(ibmvtpm->dev);
+
+	kfree(ibmvtpm);
+
+	return 0;
+}
+
+/**
+ * tpm_ibmvtpm_get_desired_dma - Get DMA size needed by this driver
+ * @vdev:	vio device struct
+ *
+ * Return value:
+ *	Number of bytes the driver needs to DMA map
+ */
+static unsigned long tpm_ibmvtpm_get_desired_dma(struct vio_dev *vdev)
+{
+	struct ibmvtpm_dev *ibmvtpm = ibmvtpm_get_data(&vdev->dev);
+	return CRQ_RES_BUF_SIZE + ibmvtpm->rtce_size;
+}
+
+/**
+ * tpm_ibmvtpm_suspend - Suspend
+ * @dev:	device struct
+ *
+ * Return value:
+ *	0
+ */
+static int tpm_ibmvtpm_suspend(struct device *dev)
+{
+	struct ibmvtpm_dev *ibmvtpm = ibmvtpm_get_data(dev);
+	struct ibmvtpm_crq crq;
+	u64 *buf = (u64 *) &crq;
+	int rc = 0;
+
+	crq.valid = (u8)IBMVTPM_VALID_CMD;
+	crq.msg = (u8)VTPM_PREPARE_TO_SUSPEND;
+
+	rc = ibmvtpm_send_crq(ibmvtpm->vdev, buf[0], buf[1]);
+	if (rc != H_SUCCESS)
+		dev_err(ibmvtpm->dev,
+			"tpm_ibmvtpm_suspend failed rc=%d\n", rc);
+
+	return rc;
+}
+
+/**
+ * ibmvtpm_reset_crq - Reset CRQ
+ * @ibmvtpm:	ibm vtpm struct
+ *
+ * Return value:
+ *	0 - Success
+ *	Non-zero - Failure
+ */
+static int ibmvtpm_reset_crq(struct ibmvtpm_dev *ibmvtpm)
+{
+	int rc = 0;
+
+	do {
+		if (rc)
+			msleep(100);
+		rc = plpar_hcall_norets(H_FREE_CRQ,
+					ibmvtpm->vdev->unit_address);
+	} while (rc == H_BUSY || H_IS_LONG_BUSY(rc));
+
+	memset(ibmvtpm->crq_queue.crq_addr, 0, CRQ_RES_BUF_SIZE);
+	ibmvtpm->crq_queue.index = 0;
+
+	return plpar_hcall_norets(H_REG_CRQ, ibmvtpm->vdev->unit_address,
+				  ibmvtpm->crq_dma_handle, CRQ_RES_BUF_SIZE);
+}
+
+/**
+ * tpm_ibmvtpm_resume - Resume from suspend
+ * @dev:	device struct
+ *
+ * Return value:
+ *	0
+ */
+static int tpm_ibmvtpm_resume(struct device *dev)
+{
+	struct ibmvtpm_dev *ibmvtpm = ibmvtpm_get_data(dev);
+	unsigned long flags;
+	int rc = 0;
+
+	do {
+		if (rc)
+			msleep(100);
+		rc = plpar_hcall_norets(H_ENABLE_CRQ,
+					ibmvtpm->vdev->unit_address);
+	} while (rc == H_IN_PROGRESS || rc == H_BUSY || H_IS_LONG_BUSY(rc));
+
+	if (rc) {
+		dev_err(dev, "Error enabling ibmvtpm rc=%d\n", rc);
+		return rc;
+	}
+
+	spin_lock_irqsave(&ibmvtpm->lock, flags);
+	vio_disable_interrupts(ibmvtpm->vdev);
+	tasklet_schedule(&ibmvtpm->tasklet);
+	spin_unlock_irqrestore(&ibmvtpm->lock, flags);
+
+	rc = ibmvtpm_crq_send_init(ibmvtpm);
+	if (rc)
+		dev_err(dev, "Error send_init rc=%d\n", rc);
+
+	return rc;
+}
+
+static const struct file_operations ibmvtpm_ops = {
+	.owner = THIS_MODULE,
+	.llseek = no_llseek,
+	.open = tpm_open,
+	.read = tpm_read,
+	.write = tpm_write,
+	.release = tpm_release,
+};
+
+static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL);
+static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL);
+static DEVICE_ATTR(enabled, S_IRUGO, tpm_show_enabled, NULL);
+static DEVICE_ATTR(active, S_IRUGO, tpm_show_active, NULL);
+static DEVICE_ATTR(owned, S_IRUGO, tpm_show_owned, NULL);
+static DEVICE_ATTR(temp_deactivated, S_IRUGO, tpm_show_temp_deactivated,
+		   NULL);
+static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps_1_2, NULL);
+static DEVICE_ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tpm_store_cancel);
+static DEVICE_ATTR(durations, S_IRUGO, tpm_show_durations, NULL);
+static DEVICE_ATTR(timeouts, S_IRUGO, tpm_show_timeouts, NULL);
+
+static struct attribute *ibmvtpm_attrs[] = {
+	&dev_attr_pubek.attr,
+	&dev_attr_pcrs.attr,
+	&dev_attr_enabled.attr,
+	&dev_attr_active.attr,
+	&dev_attr_owned.attr,
+	&dev_attr_temp_deactivated.attr,
+	&dev_attr_caps.attr,
+	&dev_attr_cancel.attr,
+	&dev_attr_durations.attr,
+	&dev_attr_timeouts.attr, NULL,
+};
+
+static struct attribute_group ibmvtpm_attr_grp = { .attrs = ibmvtpm_attrs };
+
+static const struct tpm_vendor_specific tpm_ibmvtpm = {
+	.recv = tpm_ibmvtpm_recv,
+	.send = tpm_ibmvtpm_send,
+	.cancel = tpm_ibmvtpm_cancel,
+	.status = tpm_ibmvtpm_status,
+	.req_complete_mask = 0,
+	.req_complete_val = 0,
+	.req_canceled = 0,
+	.attr_group = &ibmvtpm_attr_grp,
+	.miscdev = { .fops = &ibmvtpm_ops, },
+};
+
+static const struct dev_pm_ops tpm_ibmvtpm_pm_ops = {
+	.suspend = tpm_ibmvtpm_suspend,
+	.resume = tpm_ibmvtpm_resume,
+};
+
+/**
+ * ibmvtpm_crq_get_next - Get next responded crq
+ * @ibmvtpm	vtpm device struct
+ *
+ * Return value:
+ *	vtpm crq pointer
+ */
+static struct ibmvtpm_crq *ibmvtpm_crq_get_next(struct ibmvtpm_dev *ibmvtpm)
+{
+	struct ibmvtpm_crq_queue *crq_q = &ibmvtpm->crq_queue;
+	struct ibmvtpm_crq *crq = &crq_q->crq_addr[crq_q->index];
+
+	if (crq->valid & VTPM_MSG_RES) {
+		if (++crq_q->index == crq_q->num_entry)
+			crq_q->index = 0;
+		rmb();
+	} else
+		crq = NULL;
+	return crq;
+}
+
+/**
+ * ibmvtpm_crq_process - Process responded crq
+ * @crq		crq to be processed
+ * @ibmvtpm	vtpm device struct
+ *
+ * Return value:
+ *	Nothing
+ */
+static void ibmvtpm_crq_process(struct ibmvtpm_crq *crq,
+				struct ibmvtpm_dev *ibmvtpm)
+{
+	int rc = 0;
+
+	switch (crq->valid) {
+	case VALID_INIT_CRQ:
+		switch (crq->msg) {
+		case INIT_CRQ_RES:
+			dev_info(ibmvtpm->dev, "CRQ initialized\n");
+			rc = ibmvtpm_crq_send_init_complete(ibmvtpm);
+			if (rc)
+				dev_err(ibmvtpm->dev, "Unable to send CRQ init complete rc=%d\n", rc);
+			return;
+		case INIT_CRQ_COMP_RES:
+			dev_info(ibmvtpm->dev,
+				 "CRQ initialization completed\n");
+			return;
+		default:
+			dev_err(ibmvtpm->dev, "Unknown crq message type: %d\n", crq->msg);
+			return;
+		}
+		return;
+	case IBMVTPM_VALID_CMD:
+		switch (crq->msg) {
+		case VTPM_GET_RTCE_BUFFER_SIZE_RES:
+			if (crq->len <= 0) {
+				dev_err(ibmvtpm->dev, "Invalid rtce size\n");
+				return;
+			}
+			ibmvtpm->rtce_size = crq->len;
+			ibmvtpm->rtce_buf = kmalloc(ibmvtpm->rtce_size,
+						    GFP_KERNEL);
+			if (!ibmvtpm->rtce_buf) {
+				dev_err(ibmvtpm->dev, "Failed to allocate memory for rtce buffer\n");
+				return;
+			}
+
+			ibmvtpm->rtce_dma_handle = dma_map_single(ibmvtpm->dev,
+				ibmvtpm->rtce_buf, ibmvtpm->rtce_size,
+				DMA_BIDIRECTIONAL);
+
+			if (dma_mapping_error(ibmvtpm->dev,
+					      ibmvtpm->rtce_dma_handle)) {
+				kfree(ibmvtpm->rtce_buf);
+				ibmvtpm->rtce_buf = NULL;
+				dev_err(ibmvtpm->dev, "Failed to dma map rtce buffer\n");
+			}
+
+			return;
+		case VTPM_GET_VERSION_RES:
+			ibmvtpm->vtpm_version = crq->data;
+			return;
+		case VTPM_TPM_COMMAND_RES:
+			ibmvtpm->crq_res.valid = crq->valid;
+			ibmvtpm->crq_res.msg = crq->msg;
+			ibmvtpm->crq_res.len = crq->len;
+			ibmvtpm->crq_res.data = crq->data;
+			wake_up_interruptible(&wq);
+			return;
+		default:
+			return;
+		}
+	}
+	return;
+}
+
+/**
+ * ibmvtpm_interrupt -	Interrupt handler
+ * @irq:		irq number to handle
+ * @vtpm_instance:	vtpm that received interrupt
+ *
+ * Returns:
+ *	IRQ_HANDLED
+ **/
+static irqreturn_t ibmvtpm_interrupt(int irq, void *vtpm_instance)
+{
+	struct ibmvtpm_dev *ibmvtpm = (struct ibmvtpm_dev *) vtpm_instance;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ibmvtpm->lock, flags);
+	vio_disable_interrupts(ibmvtpm->vdev);
+	tasklet_schedule(&ibmvtpm->tasklet);
+	spin_unlock_irqrestore(&ibmvtpm->lock, flags);
+
+	return IRQ_HANDLED;
+}
+
+/**
+ * ibmvtpm_tasklet - Interrupt handler tasklet
+ * @data:	ibm vtpm device struct
+ *
+ * Returns:
+ *	Nothing
+ **/
+static void ibmvtpm_tasklet(void *data)
+{
+	struct ibmvtpm_dev *ibmvtpm = data;
+	struct ibmvtpm_crq *crq;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ibmvtpm->lock, flags);
+	while ((crq = ibmvtpm_crq_get_next(ibmvtpm)) != NULL) {
+		ibmvtpm_crq_process(crq, ibmvtpm);
+		crq->valid = 0;
+		wmb();
+	}
+
+	vio_enable_interrupts(ibmvtpm->vdev);
+	spin_unlock_irqrestore(&ibmvtpm->lock, flags);
+}
+
+/**
+ * tpm_ibmvtpm_probe - ibm vtpm initialize entry point
+ * @vio_dev:	vio device struct
+ * @id:		vio device id struct
+ *
+ * Return value:
+ *	0 - Success
+ *	Non-zero - Failure
+ */
+static int __devinit tpm_ibmvtpm_probe(struct vio_dev *vio_dev,
+				   const struct vio_device_id *id)
+{
+	struct ibmvtpm_dev *ibmvtpm;
+	struct device *dev = &vio_dev->dev;
+	struct ibmvtpm_crq_queue *crq_q;
+	struct tpm_chip *chip;
+	int rc = -ENOMEM, rc1;
+
+	chip = tpm_register_hardware(dev, &tpm_ibmvtpm);
+	if (!chip) {
+		dev_err(dev, "tpm_register_hardware failed\n");
+		return -ENODEV;
+	}
+
+	ibmvtpm = kzalloc(sizeof(struct ibmvtpm_dev), GFP_KERNEL);
+	if (!ibmvtpm) {
+		dev_err(dev, "kzalloc for ibmvtpm failed\n");
+		goto cleanup;
+	}
+
+	crq_q = &ibmvtpm->crq_queue;
+	crq_q->crq_addr = (struct ibmvtpm_crq *)get_zeroed_page(GFP_KERNEL);
+	if (!crq_q->crq_addr) {
+		dev_err(dev, "Unable to allocate memory for crq_addr\n");
+		goto cleanup;
+	}
+
+	crq_q->num_entry = CRQ_RES_BUF_SIZE / sizeof(*crq_q->crq_addr);
+	ibmvtpm->crq_dma_handle = dma_map_single(dev, crq_q->crq_addr,
+						 CRQ_RES_BUF_SIZE,
+						 DMA_BIDIRECTIONAL);
+
+	if (dma_mapping_error(dev, ibmvtpm->crq_dma_handle)) {
+		dev_err(dev, "dma mapping failed\n");
+		goto cleanup;
+	}
+
+	rc = plpar_hcall_norets(H_REG_CRQ, vio_dev->unit_address,
+				ibmvtpm->crq_dma_handle, CRQ_RES_BUF_SIZE);
+	if (rc == H_RESOURCE)
+		rc = ibmvtpm_reset_crq(ibmvtpm);
+
+	if (rc) {
+		dev_err(dev, "Unable to register CRQ rc=%d\n", rc);
+		goto reg_crq_cleanup;
+	}
+
+	tasklet_init(&ibmvtpm->tasklet, (void *)ibmvtpm_tasklet,
+		     (unsigned long)ibmvtpm);
+
+	rc = request_irq(vio_dev->irq, ibmvtpm_interrupt, 0,
+			 tpm_ibmvtpm_driver_name, ibmvtpm);
+	if (rc) {
+		dev_err(dev, "Error %d register irq 0x%x\n", rc, vio_dev->irq);
+		goto init_irq_cleanup;
+	}
+
+	rc = vio_enable_interrupts(vio_dev);
+	if (rc) {
+		dev_err(dev, "Error %d enabling interrupts\n", rc);
+		goto init_irq_cleanup;
+	}
+
+	crq_q->index = 0;
+
+	ibmvtpm->dev = dev;
+	ibmvtpm->vdev = vio_dev;
+	chip->vendor.data = (void *)ibmvtpm;
+
+	spin_lock_init(&ibmvtpm->lock);
+	spin_lock_init(&ibmvtpm->rtce_lock);
+
+	rc = ibmvtpm_crq_send_init(ibmvtpm);
+	if (rc)
+		goto init_irq_cleanup;
+
+	rc = ibmvtpm_crq_get_version(ibmvtpm);
+	if (rc)
+		goto init_irq_cleanup;
+
+	rc = ibmvtpm_crq_get_rtce_size(ibmvtpm);
+	if (rc)
+		goto init_irq_cleanup;
+
+	return rc;
+init_irq_cleanup:
+	tasklet_kill(&ibmvtpm->tasklet);
+	do {
+		rc1 = plpar_hcall_norets(H_FREE_CRQ, vio_dev->unit_address);
+	} while (rc1 == H_BUSY || H_IS_LONG_BUSY(rc1));
+reg_crq_cleanup:
+	dma_unmap_single(dev, ibmvtpm->crq_dma_handle, CRQ_RES_BUF_SIZE,
+			 DMA_BIDIRECTIONAL);
+cleanup:
+	if (ibmvtpm) {
+		if (crq_q->crq_addr)
+			free_page((unsigned long)crq_q->crq_addr);
+		kfree(ibmvtpm);
+	}
+
+	tpm_remove_hardware(dev);
+
+	return rc;
+}
+
+static struct vio_driver ibmvtpm_driver = {
+	.id_table	 = tpm_ibmvtpm_device_table,
+	.probe		 = tpm_ibmvtpm_probe,
+	.remove		 = tpm_ibmvtpm_remove,
+	.get_desired_dma = tpm_ibmvtpm_get_desired_dma,
+	.name		 = tpm_ibmvtpm_driver_name,
+	.pm		 = &tpm_ibmvtpm_pm_ops,
+};
+
+/**
+ * ibmvtpm_module_init - Initialize ibm vtpm module
+ *
+ * Return value:
+ *	0 -Success
+ *	Non-zero - Failure
+ */
+static int __init ibmvtpm_module_init(void)
+{
+	return vio_register_driver(&ibmvtpm_driver);
+}
+
+/**
+ * ibmvtpm_module_exit - Teardown ibm vtpm module
+ *
+ * Return value:
+ *	Nothing
+ */
+static void __exit ibmvtpm_module_exit(void)
+{
+	vio_unregister_driver(&ibmvtpm_driver);
+}
+
+module_init(ibmvtpm_module_init);
+module_exit(ibmvtpm_module_exit);
+
+MODULE_AUTHOR("adlai@us.ibm.com");
+MODULE_DESCRIPTION("IBM vTPM Driver");
+MODULE_VERSION("1.0");
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/tpm/tpm_ibmvtpm.h b/drivers/char/tpm/tpm_ibmvtpm.h
new file mode 100644
index 0000000..4296eb4
--- /dev/null
+++ b/drivers/char/tpm/tpm_ibmvtpm.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2012 IBM Corporation
+ *
+ * Author: Ashley Lai <adlai@us.ibm.com>
+ *
+ * Maintained by: <tpmdd-devel@lists.sourceforge.net>
+ *
+ * Device driver for TCG/TCPA TPM (trusted platform module).
+ * Specifications at www.trustedcomputinggroup.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, version 2 of the
+ * License.
+ *
+ */
+
+#ifndef __TPM_IBMVTPM_H__
+#define __TPM_IBMVTPM_H__
+
+/* vTPM Message Format 1 */
+struct ibmvtpm_crq {
+	u8 valid;
+	u8 msg;
+	u16 len;
+	u32 data;
+	u64 reserved;
+} __attribute__((packed, aligned(8)));
+
+struct ibmvtpm_crq_queue {
+	struct ibmvtpm_crq *crq_addr;
+	u32 index;
+	u32 num_entry;
+};
+
+struct ibmvtpm_dev {
+	struct device *dev;
+	struct vio_dev *vdev;
+	struct ibmvtpm_crq_queue crq_queue;
+	dma_addr_t crq_dma_handle;
+	spinlock_t lock;
+	struct tasklet_struct tasklet;
+	u32 rtce_size;
+	void __iomem *rtce_buf;
+	dma_addr_t rtce_dma_handle;
+	spinlock_t rtce_lock;
+	struct ibmvtpm_crq crq_res;
+	u32 vtpm_version;
+};
+
+#define CRQ_RES_BUF_SIZE	PAGE_SIZE
+
+/* Initialize CRQ */
+#define INIT_CRQ_CMD		0xC001000000000000LL /* Init cmd */
+#define INIT_CRQ_COMP_CMD	0xC002000000000000LL /* Init complete cmd */
+#define INIT_CRQ_RES		0x01	/* Init respond */
+#define INIT_CRQ_COMP_RES	0x02	/* Init complete respond */
+#define VALID_INIT_CRQ		0xC0	/* Valid command for init crq */
+
+/* vTPM CRQ response is the message type | 0x80 */
+#define VTPM_MSG_RES		0x80
+#define IBMVTPM_VALID_CMD	0x80
+
+/* vTPM CRQ message types */
+#define VTPM_GET_VERSION			0x01
+#define VTPM_GET_VERSION_RES			(0x01 | VTPM_MSG_RES)
+
+#define VTPM_TPM_COMMAND			0x02
+#define VTPM_TPM_COMMAND_RES			(0x02 | VTPM_MSG_RES)
+
+#define VTPM_GET_RTCE_BUFFER_SIZE		0x03
+#define VTPM_GET_RTCE_BUFFER_SIZE_RES		(0x03 | VTPM_MSG_RES)
+
+#define VTPM_PREPARE_TO_SUSPEND			0x04
+#define VTPM_PREPARE_TO_SUSPEND_RES		(0x04 | VTPM_MSG_RES)
+
+#endif
diff --git a/drivers/char/tpm/tpm_of.c b/drivers/char/tpm/tpm_of.c
new file mode 100644
index 0000000..98ba2bd
--- /dev/null
+++ b/drivers/char/tpm/tpm_of.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2012 IBM Corporation
+ *
+ * Author: Ashley Lai <adlai@us.ibm.com>
+ *
+ * Maintained by: <tpmdd-devel@lists.sourceforge.net>
+ *
+ * Read the event log created by the firmware on PPC64
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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/slab.h>
+#include <linux/of.h>
+
+#include "tpm.h"
+#include "tpm_eventlog.h"
+
+int read_log(struct tpm_bios_log *log)
+{
+	struct device_node *np;
+	const u32 *sizep;
+	const __be64 *basep;
+
+	if (log->bios_event_log != NULL) {
+		pr_err("%s: ERROR - Eventlog already initialized\n", __func__);
+		return -EFAULT;
+	}
+
+	np = of_find_node_by_name(NULL, "ibm,vtpm");
+	if (!np) {
+		pr_err("%s: ERROR - IBMVTPM not supported\n", __func__);
+		return -ENODEV;
+	}
+
+	sizep = of_get_property(np, "linux,sml-size", NULL);
+	if (sizep == NULL) {
+		pr_err("%s: ERROR - SML size not found\n", __func__);
+		goto cleanup_eio;
+	}
+	if (*sizep == 0) {
+		pr_err("%s: ERROR - event log area empty\n", __func__);
+		goto cleanup_eio;
+	}
+
+	basep = of_get_property(np, "linux,sml-base", NULL);
+	if (basep == NULL) {
+		pr_err(KERN_ERR "%s: ERROR - SML not found\n", __func__);
+		goto cleanup_eio;
+	}
+
+	of_node_put(np);
+	log->bios_event_log = kmalloc(*sizep, GFP_KERNEL);
+	if (!log->bios_event_log) {
+		pr_err("%s: ERROR - Not enough memory for BIOS measurements\n",
+		       __func__);
+		return -ENOMEM;
+	}
+
+	log->bios_event_log_end = log->bios_event_log + *sizep;
+
+	memcpy(log->bios_event_log, __va(be64_to_cpup(basep)), *sizep);
+
+	return 0;
+
+cleanup_eio:
+	of_node_put(np);
+	return -EIO;
+}
diff --git a/drivers/char/tpm/tpm_ppi.c b/drivers/char/tpm/tpm_ppi.c
new file mode 100644
index 0000000..f27b58c
--- /dev/null
+++ b/drivers/char/tpm/tpm_ppi.c
@@ -0,0 +1,461 @@
+#include <linux/acpi.h>
+#include <acpi/acpi_drivers.h>
+#include "tpm.h"
+
+static const u8 tpm_ppi_uuid[] = {
+	0xA6, 0xFA, 0xDD, 0x3D,
+	0x1B, 0x36,
+	0xB4, 0x4E,
+	0xA4, 0x24,
+	0x8D, 0x10, 0x08, 0x9D, 0x16, 0x53
+};
+static char *tpm_device_name = "TPM";
+
+#define TPM_PPI_REVISION_ID	1
+#define TPM_PPI_FN_VERSION	1
+#define TPM_PPI_FN_SUBREQ	2
+#define TPM_PPI_FN_GETREQ	3
+#define TPM_PPI_FN_GETACT	4
+#define TPM_PPI_FN_GETRSP	5
+#define TPM_PPI_FN_SUBREQ2	7
+#define TPM_PPI_FN_GETOPR	8
+#define PPI_TPM_REQ_MAX		22
+#define PPI_VS_REQ_START	128
+#define PPI_VS_REQ_END		255
+#define PPI_VERSION_LEN		3
+
+static acpi_status ppi_callback(acpi_handle handle, u32 level, void *context,
+				void **return_value)
+{
+	acpi_status status;
+	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+	status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
+	if (strstr(buffer.pointer, context) != NULL) {
+		*return_value = handle;
+		kfree(buffer.pointer);
+		return AE_CTRL_TERMINATE;
+	}
+	return AE_OK;
+}
+
+static inline void ppi_assign_params(union acpi_object params[4],
+				     u64 function_num)
+{
+	params[0].type = ACPI_TYPE_BUFFER;
+	params[0].buffer.length = sizeof(tpm_ppi_uuid);
+	params[0].buffer.pointer = (char *)tpm_ppi_uuid;
+	params[1].type = ACPI_TYPE_INTEGER;
+	params[1].integer.value = TPM_PPI_REVISION_ID;
+	params[2].type = ACPI_TYPE_INTEGER;
+	params[2].integer.value = function_num;
+	params[3].type = ACPI_TYPE_PACKAGE;
+	params[3].package.count = 0;
+	params[3].package.elements = NULL;
+}
+
+static ssize_t tpm_show_ppi_version(struct device *dev,
+				    struct device_attribute *attr, char *buf)
+{
+	acpi_handle handle;
+	acpi_status status;
+	struct acpi_object_list input;
+	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
+	union acpi_object params[4];
+	union acpi_object *obj;
+
+	input.count = 4;
+	ppi_assign_params(params, TPM_PPI_FN_VERSION);
+	input.pointer = params;
+	status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
+				     ACPI_UINT32_MAX, ppi_callback, NULL,
+				     tpm_device_name, &handle);
+	if (ACPI_FAILURE(status))
+		return -ENXIO;
+
+	status = acpi_evaluate_object_typed(handle, "_DSM", &input, &output,
+					 ACPI_TYPE_STRING);
+	if (ACPI_FAILURE(status))
+		return -ENOMEM;
+	obj = (union acpi_object *)output.pointer;
+	status = scnprintf(buf, PAGE_SIZE, "%s\n", obj->string.pointer);
+	kfree(output.pointer);
+	return status;
+}
+
+static ssize_t tpm_show_ppi_request(struct device *dev,
+				    struct device_attribute *attr, char *buf)
+{
+	acpi_handle handle;
+	acpi_status status;
+	struct acpi_object_list input;
+	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
+	union acpi_object params[4];
+	union acpi_object *ret_obj;
+
+	input.count = 4;
+	ppi_assign_params(params, TPM_PPI_FN_GETREQ);
+	input.pointer = params;
+	status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
+				     ACPI_UINT32_MAX, ppi_callback, NULL,
+				     tpm_device_name, &handle);
+	if (ACPI_FAILURE(status))
+		return -ENXIO;
+
+	status = acpi_evaluate_object_typed(handle, "_DSM", &input, &output,
+					    ACPI_TYPE_PACKAGE);
+	if (ACPI_FAILURE(status))
+		return -ENOMEM;
+	/*
+	 * output.pointer should be of package type, including two integers.
+	 * The first is function return code, 0 means success and 1 means
+	 * error. The second is pending TPM operation requested by the OS, 0
+	 * means none and >0 means operation value.
+	 */
+	ret_obj = ((union acpi_object *)output.pointer)->package.elements;
+	if (ret_obj->type == ACPI_TYPE_INTEGER) {
+		if (ret_obj->integer.value) {
+			status = -EFAULT;
+			goto cleanup;
+		}
+		ret_obj++;
+		if (ret_obj->type == ACPI_TYPE_INTEGER)
+			status = scnprintf(buf, PAGE_SIZE, "%llu\n",
+					   ret_obj->integer.value);
+		else
+			status = -EINVAL;
+	} else {
+		status = -EINVAL;
+	}
+cleanup:
+	kfree(output.pointer);
+	return status;
+}
+
+static ssize_t tpm_store_ppi_request(struct device *dev,
+				     struct device_attribute *attr,
+				     const char *buf, size_t count)
+{
+	char version[PPI_VERSION_LEN + 1];
+	acpi_handle handle;
+	acpi_status status;
+	struct acpi_object_list input;
+	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
+	union acpi_object params[4];
+	union acpi_object obj;
+	u32 req;
+	u64 ret;
+
+	input.count = 4;
+	ppi_assign_params(params, TPM_PPI_FN_VERSION);
+	input.pointer = params;
+	status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
+				     ACPI_UINT32_MAX, ppi_callback, NULL,
+				     tpm_device_name, &handle);
+	if (ACPI_FAILURE(status))
+		return -ENXIO;
+
+	status = acpi_evaluate_object_typed(handle, "_DSM", &input, &output,
+					    ACPI_TYPE_STRING);
+	if (ACPI_FAILURE(status))
+		return -ENOMEM;
+	strncpy(version,
+		((union acpi_object *)output.pointer)->string.pointer,
+		PPI_VERSION_LEN);
+	kfree(output.pointer);
+	output.length = ACPI_ALLOCATE_BUFFER;
+	output.pointer = NULL;
+	/*
+	 * the function to submit TPM operation request to pre-os environment
+	 * is updated with function index from SUBREQ to SUBREQ2 since PPI
+	 * version 1.1
+	 */
+	if (strcmp(version, "1.1") == -1)
+		params[2].integer.value = TPM_PPI_FN_SUBREQ;
+	else
+		params[2].integer.value = TPM_PPI_FN_SUBREQ2;
+	/*
+	 * PPI spec defines params[3].type as ACPI_TYPE_PACKAGE. Some BIOS
+	 * accept buffer/string/integer type, but some BIOS accept buffer/
+	 * string/package type. For PPI version 1.0 and 1.1, use buffer type
+	 * for compatibility, and use package type since 1.2 according to spec.
+	 */
+	if (strcmp(version, "1.2") == -1) {
+		params[3].type = ACPI_TYPE_BUFFER;
+		params[3].buffer.length = sizeof(req);
+		sscanf(buf, "%d", &req);
+		params[3].buffer.pointer = (char *)&req;
+	} else {
+		params[3].package.count = 1;
+		obj.type = ACPI_TYPE_INTEGER;
+		sscanf(buf, "%llu", &obj.integer.value);
+		params[3].package.elements = &obj;
+	}
+
+	status = acpi_evaluate_object_typed(handle, "_DSM", &input, &output,
+					    ACPI_TYPE_INTEGER);
+	if (ACPI_FAILURE(status))
+		return -ENOMEM;
+	ret = ((union acpi_object *)output.pointer)->integer.value;
+	if (ret == 0)
+		status = (acpi_status)count;
+	else if (ret == 1)
+		status = -EPERM;
+	else
+		status = -EFAULT;
+	kfree(output.pointer);
+	return status;
+}
+
+static ssize_t tpm_show_ppi_transition_action(struct device *dev,
+					      struct device_attribute *attr,
+					      char *buf)
+{
+	char version[PPI_VERSION_LEN + 1];
+	acpi_handle handle;
+	acpi_status status;
+	struct acpi_object_list input;
+	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
+	union acpi_object params[4];
+	u32 ret;
+	char *info[] = {
+		"None",
+		"Shutdown",
+		"Reboot",
+		"OS Vendor-specific",
+		"Error",
+	};
+	input.count = 4;
+	ppi_assign_params(params, TPM_PPI_FN_VERSION);
+	input.pointer = params;
+	status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
+				     ACPI_UINT32_MAX, ppi_callback, NULL,
+				     tpm_device_name, &handle);
+	if (ACPI_FAILURE(status))
+		return -ENXIO;
+
+	status = acpi_evaluate_object_typed(handle, "_DSM", &input, &output,
+					    ACPI_TYPE_STRING);
+	if (ACPI_FAILURE(status))
+		return -ENOMEM;
+	strncpy(version,
+		((union acpi_object *)output.pointer)->string.pointer,
+		PPI_VERSION_LEN);
+	/*
+	 * PPI spec defines params[3].type as empty package, but some platforms
+	 * (e.g. Capella with PPI 1.0) need integer/string/buffer type, so for
+	 * compatibility, define params[3].type as buffer, if PPI version < 1.2
+	 */
+	if (strcmp(version, "1.2") == -1) {
+		params[3].type = ACPI_TYPE_BUFFER;
+		params[3].buffer.length =  0;
+		params[3].buffer.pointer = NULL;
+	}
+	params[2].integer.value = TPM_PPI_FN_GETACT;
+	kfree(output.pointer);
+	output.length = ACPI_ALLOCATE_BUFFER;
+	output.pointer = NULL;
+	status = acpi_evaluate_object_typed(handle, "_DSM", &input, &output,
+					    ACPI_TYPE_INTEGER);
+	if (ACPI_FAILURE(status))
+		return -ENOMEM;
+	ret = ((union acpi_object *)output.pointer)->integer.value;
+	if (ret < ARRAY_SIZE(info) - 1)
+		status = scnprintf(buf, PAGE_SIZE, "%d: %s\n", ret, info[ret]);
+	else
+		status = scnprintf(buf, PAGE_SIZE, "%d: %s\n", ret,
+				   info[ARRAY_SIZE(info)-1]);
+	kfree(output.pointer);
+	return status;
+}
+
+static ssize_t tpm_show_ppi_response(struct device *dev,
+				     struct device_attribute *attr,
+				     char *buf)
+{
+	acpi_handle handle;
+	acpi_status status;
+	struct acpi_object_list input;
+	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
+	union acpi_object params[4];
+	union acpi_object *ret_obj;
+	u64 req;
+
+	input.count = 4;
+	ppi_assign_params(params, TPM_PPI_FN_GETRSP);
+	input.pointer = params;
+	status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
+				     ACPI_UINT32_MAX, ppi_callback, NULL,
+				     tpm_device_name, &handle);
+	if (ACPI_FAILURE(status))
+		return -ENXIO;
+
+	status = acpi_evaluate_object_typed(handle, "_DSM", &input, &output,
+					    ACPI_TYPE_PACKAGE);
+	if (ACPI_FAILURE(status))
+		return -ENOMEM;
+	/*
+	 * parameter output.pointer should be of package type, including
+	 * 3 integers. The first means function return code, the second means
+	 * most recent TPM operation request, and the last means response to
+	 * the most recent TPM operation request. Only if the first is 0, and
+	 * the second integer is not 0, the response makes sense.
+	 */
+	ret_obj = ((union acpi_object *)output.pointer)->package.elements;
+	if (ret_obj->type != ACPI_TYPE_INTEGER) {
+		status = -EINVAL;
+		goto cleanup;
+	}
+	if (ret_obj->integer.value) {
+		status = -EFAULT;
+		goto cleanup;
+	}
+	ret_obj++;
+	if (ret_obj->type != ACPI_TYPE_INTEGER) {
+		status = -EINVAL;
+		goto cleanup;
+	}
+	if (ret_obj->integer.value) {
+		req = ret_obj->integer.value;
+		ret_obj++;
+		if (ret_obj->type != ACPI_TYPE_INTEGER) {
+			status = -EINVAL;
+			goto cleanup;
+		}
+		if (ret_obj->integer.value == 0)
+			status = scnprintf(buf, PAGE_SIZE, "%llu %s\n", req,
+					   "0: Success");
+		else if (ret_obj->integer.value == 0xFFFFFFF0)
+			status = scnprintf(buf, PAGE_SIZE, "%llu %s\n", req,
+					   "0xFFFFFFF0: User Abort");
+		else if (ret_obj->integer.value == 0xFFFFFFF1)
+			status = scnprintf(buf, PAGE_SIZE, "%llu %s\n", req,
+					   "0xFFFFFFF1: BIOS Failure");
+		else if (ret_obj->integer.value >= 1 &&
+			 ret_obj->integer.value <= 0x00000FFF)
+			status = scnprintf(buf, PAGE_SIZE, "%llu %llu: %s\n",
+					   req, ret_obj->integer.value,
+					   "Corresponding TPM error");
+		else
+			status = scnprintf(buf, PAGE_SIZE, "%llu %llu: %s\n",
+					   req, ret_obj->integer.value,
+					   "Error");
+	} else {
+		status = scnprintf(buf, PAGE_SIZE, "%llu: %s\n",
+				   ret_obj->integer.value, "No Recent Request");
+	}
+cleanup:
+	kfree(output.pointer);
+	return status;
+}
+
+static ssize_t show_ppi_operations(char *buf, u32 start, u32 end)
+{
+	char *str = buf;
+	char version[PPI_VERSION_LEN];
+	acpi_handle handle;
+	acpi_status status;
+	struct acpi_object_list input;
+	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
+	union acpi_object params[4];
+	union acpi_object obj;
+	int i;
+	u32 ret;
+	char *info[] = {
+		"Not implemented",
+		"BIOS only",
+		"Blocked for OS by BIOS",
+		"User required",
+		"User not required",
+	};
+	input.count = 4;
+	ppi_assign_params(params, TPM_PPI_FN_VERSION);
+	input.pointer = params;
+	status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
+				     ACPI_UINT32_MAX, ppi_callback, NULL,
+				     tpm_device_name, &handle);
+	if (ACPI_FAILURE(status))
+		return -ENXIO;
+
+	status = acpi_evaluate_object_typed(handle, "_DSM", &input, &output,
+					 ACPI_TYPE_STRING);
+	if (ACPI_FAILURE(status))
+		return -ENOMEM;
+
+	strncpy(version,
+		((union acpi_object *)output.pointer)->string.pointer,
+		PPI_VERSION_LEN);
+	kfree(output.pointer);
+	output.length = ACPI_ALLOCATE_BUFFER;
+	output.pointer = NULL;
+	if (strcmp(version, "1.2") == -1)
+		return -EPERM;
+
+	params[2].integer.value = TPM_PPI_FN_GETOPR;
+	params[3].package.count = 1;
+	obj.type = ACPI_TYPE_INTEGER;
+	params[3].package.elements = &obj;
+	for (i = start; i <= end; i++) {
+		obj.integer.value = i;
+		status = acpi_evaluate_object_typed(handle, "_DSM",
+			 &input, &output, ACPI_TYPE_INTEGER);
+		if (ACPI_FAILURE(status))
+			return -ENOMEM;
+
+		ret = ((union acpi_object *)output.pointer)->integer.value;
+		if (ret > 0 && ret < ARRAY_SIZE(info))
+			str += scnprintf(str, PAGE_SIZE, "%d %d: %s\n",
+					 i, ret, info[ret]);
+		kfree(output.pointer);
+		output.length = ACPI_ALLOCATE_BUFFER;
+		output.pointer = NULL;
+	}
+	return str - buf;
+}
+
+static ssize_t tpm_show_ppi_tcg_operations(struct device *dev,
+					   struct device_attribute *attr,
+					   char *buf)
+{
+	return show_ppi_operations(buf, 0, PPI_TPM_REQ_MAX);
+}
+
+static ssize_t tpm_show_ppi_vs_operations(struct device *dev,
+					  struct device_attribute *attr,
+					  char *buf)
+{
+	return show_ppi_operations(buf, PPI_VS_REQ_START, PPI_VS_REQ_END);
+}
+
+static DEVICE_ATTR(version, S_IRUGO, tpm_show_ppi_version, NULL);
+static DEVICE_ATTR(request, S_IRUGO | S_IWUSR | S_IWGRP,
+		   tpm_show_ppi_request, tpm_store_ppi_request);
+static DEVICE_ATTR(transition_action, S_IRUGO,
+		   tpm_show_ppi_transition_action, NULL);
+static DEVICE_ATTR(response, S_IRUGO, tpm_show_ppi_response, NULL);
+static DEVICE_ATTR(tcg_operations, S_IRUGO, tpm_show_ppi_tcg_operations, NULL);
+static DEVICE_ATTR(vs_operations, S_IRUGO, tpm_show_ppi_vs_operations, NULL);
+
+static struct attribute *ppi_attrs[] = {
+	&dev_attr_version.attr,
+	&dev_attr_request.attr,
+	&dev_attr_transition_action.attr,
+	&dev_attr_response.attr,
+	&dev_attr_tcg_operations.attr,
+	&dev_attr_vs_operations.attr, NULL,
+};
+static struct attribute_group ppi_attr_grp = {
+	.attrs = ppi_attrs
+};
+
+ssize_t sys_add_ppi(struct kobject *parent)
+{
+	struct kobject *ppi;
+	ppi = kobject_create_and_add("ppi", parent);
+	if (sysfs_create_group(ppi, &ppi_attr_grp))
+		return -EFAULT;
+	else
+		return 0;
+}
+EXPORT_SYMBOL_GPL(sys_add_ppi);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
index c4be351..6bdf267 100644
--- a/drivers/char/tpm/tpm_tis.c
+++ b/drivers/char/tpm/tpm_tis.c
@@ -705,6 +705,7 @@ out_err:
 	return rc;
 }
 
+#if defined(CONFIG_PNP) || defined(CONFIG_PM_SLEEP)
 static void tpm_tis_reenable_interrupts(struct tpm_chip *chip)
 {
 	u32 intmask;
@@ -725,7 +726,7 @@ static void tpm_tis_reenable_interrupts(struct tpm_chip *chip)
 	iowrite32(intmask,
 		  chip->vendor.iobase + TPM_INT_ENABLE(chip->vendor.locality));
 }
-
+#endif
 
 #ifdef CONFIG_PNP
 static int __devinit tpm_tis_pnp_init(struct pnp_dev *pnp_dev,
diff --git a/drivers/char/ttyprintk.c b/drivers/char/ttyprintk.c
index 46b77ed..af98f6d 100644
--- a/drivers/char/ttyprintk.c
+++ b/drivers/char/ttyprintk.c
@@ -67,7 +67,7 @@ static int tpk_printk(const unsigned char *buf, int count)
 				tmp[tpk_curr + 1] = '\0';
 				printk(KERN_INFO "%s%s", tpk_tag, tmp);
 				tpk_curr = 0;
-				if (buf[i + 1] == '\n')
+				if ((i + 1) < count && buf[i + 1] == '\n')
 					i++;
 				break;
 			case '\n':
@@ -178,11 +178,17 @@ static struct tty_driver *ttyprintk_driver;
 static int __init ttyprintk_init(void)
 {
 	int ret = -ENOMEM;
-	void *rp;
 
-	ttyprintk_driver = alloc_tty_driver(1);
-	if (!ttyprintk_driver)
-		return ret;
+	tty_port_init(&tpk_port.port);
+	tpk_port.port.ops = &null_ops;
+	mutex_init(&tpk_port.port_write_mutex);
+
+	ttyprintk_driver = tty_alloc_driver(1,
+			TTY_DRIVER_RESET_TERMIOS |
+			TTY_DRIVER_REAL_RAW |
+			TTY_DRIVER_UNNUMBERED_NODE);
+	if (IS_ERR(ttyprintk_driver))
+		return PTR_ERR(ttyprintk_driver);
 
 	ttyprintk_driver->driver_name = "ttyprintk";
 	ttyprintk_driver->name = "ttyprintk";
@@ -191,9 +197,8 @@ static int __init ttyprintk_init(void)
 	ttyprintk_driver->type = TTY_DRIVER_TYPE_CONSOLE;
 	ttyprintk_driver->init_termios = tty_std_termios;
 	ttyprintk_driver->init_termios.c_oflag = OPOST | OCRNL | ONOCR | ONLRET;
-	ttyprintk_driver->flags = TTY_DRIVER_RESET_TERMIOS |
-		TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
 	tty_set_operations(ttyprintk_driver, &ttyprintk_ops);
+	tty_port_link_device(&tpk_port.port, ttyprintk_driver, 0);
 
 	ret = tty_register_driver(ttyprintk_driver);
 	if (ret < 0) {
@@ -201,22 +206,10 @@ static int __init ttyprintk_init(void)
 		goto error;
 	}
 
-	/* create our unnumbered device */
-	rp = device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 3), NULL,
-				ttyprintk_driver->name);
-	if (IS_ERR(rp)) {
-		printk(KERN_ERR "Couldn't create ttyprintk device\n");
-		ret = PTR_ERR(rp);
-		goto error;
-	}
-
-	tty_port_init(&tpk_port.port);
-	tpk_port.port.ops = &null_ops;
-	mutex_init(&tpk_port.port_write_mutex);
-
 	return 0;
 
 error:
+	tty_unregister_driver(ttyprintk_driver);
 	put_tty_driver(ttyprintk_driver);
 	ttyprintk_driver = NULL;
 	return ret;
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index cdf2f54..8ab9c3d 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -24,6 +24,8 @@
 #include <linux/err.h>
 #include <linux/freezer.h>
 #include <linux/fs.h>
+#include <linux/splice.h>
+#include <linux/pagemap.h>
 #include <linux/init.h>
 #include <linux/list.h>
 #include <linux/poll.h>
@@ -474,26 +476,53 @@ static ssize_t send_control_msg(struct port *port, unsigned int event,
 	return 0;
 }
 
+struct buffer_token {
+	union {
+		void *buf;
+		struct scatterlist *sg;
+	} u;
+	/* If sgpages == 0 then buf is used, else sg is used */
+	unsigned int sgpages;
+};
+
+static void reclaim_sg_pages(struct scatterlist *sg, unsigned int nrpages)
+{
+	int i;
+	struct page *page;
+
+	for (i = 0; i < nrpages; i++) {
+		page = sg_page(&sg[i]);
+		if (!page)
+			break;
+		put_page(page);
+	}
+	kfree(sg);
+}
+
 /* Callers must take the port->outvq_lock */
 static void reclaim_consumed_buffers(struct port *port)
 {
-	void *buf;
+	struct buffer_token *tok;
 	unsigned int len;
 
 	if (!port->portdev) {
 		/* Device has been unplugged.  vqs are already gone. */
 		return;
 	}
-	while ((buf = virtqueue_get_buf(port->out_vq, &len))) {
-		kfree(buf);
+	while ((tok = virtqueue_get_buf(port->out_vq, &len))) {
+		if (tok->sgpages)
+			reclaim_sg_pages(tok->u.sg, tok->sgpages);
+		else
+			kfree(tok->u.buf);
+		kfree(tok);
 		port->outvq_full = false;
 	}
 }
 
-static ssize_t send_buf(struct port *port, void *in_buf, size_t in_count,
-			bool nonblock)
+static ssize_t __send_to_port(struct port *port, struct scatterlist *sg,
+			      int nents, size_t in_count,
+			      struct buffer_token *tok, bool nonblock)
 {
-	struct scatterlist sg[1];
 	struct virtqueue *out_vq;
 	ssize_t ret;
 	unsigned long flags;
@@ -505,8 +534,7 @@ static ssize_t send_buf(struct port *port, void *in_buf, size_t in_count,
 
 	reclaim_consumed_buffers(port);
 
-	sg_init_one(sg, in_buf, in_count);
-	ret = virtqueue_add_buf(out_vq, sg, 1, 0, in_buf, GFP_ATOMIC);
+	ret = virtqueue_add_buf(out_vq, sg, nents, 0, tok, GFP_ATOMIC);
 
 	/* Tell Host to go! */
 	virtqueue_kick(out_vq);
@@ -544,6 +572,37 @@ done:
 	return in_count;
 }
 
+static ssize_t send_buf(struct port *port, void *in_buf, size_t in_count,
+			bool nonblock)
+{
+	struct scatterlist sg[1];
+	struct buffer_token *tok;
+
+	tok = kmalloc(sizeof(*tok), GFP_ATOMIC);
+	if (!tok)
+		return -ENOMEM;
+	tok->sgpages = 0;
+	tok->u.buf = in_buf;
+
+	sg_init_one(sg, in_buf, in_count);
+
+	return __send_to_port(port, sg, 1, in_count, tok, nonblock);
+}
+
+static ssize_t send_pages(struct port *port, struct scatterlist *sg, int nents,
+			  size_t in_count, bool nonblock)
+{
+	struct buffer_token *tok;
+
+	tok = kmalloc(sizeof(*tok), GFP_ATOMIC);
+	if (!tok)
+		return -ENOMEM;
+	tok->sgpages = nents;
+	tok->u.sg = sg;
+
+	return __send_to_port(port, sg, nents, in_count, tok, nonblock);
+}
+
 /*
  * Give out the data that's requested from the buffer that we have
  * queued up.
@@ -665,6 +724,26 @@ static ssize_t port_fops_read(struct file *filp, char __user *ubuf,
 	return fill_readbuf(port, ubuf, count, true);
 }
 
+static int wait_port_writable(struct port *port, bool nonblock)
+{
+	int ret;
+
+	if (will_write_block(port)) {
+		if (nonblock)
+			return -EAGAIN;
+
+		ret = wait_event_freezable(port->waitqueue,
+					   !will_write_block(port));
+		if (ret < 0)
+			return ret;
+	}
+	/* Port got hot-unplugged. */
+	if (!port->guest_connected)
+		return -ENODEV;
+
+	return 0;
+}
+
 static ssize_t port_fops_write(struct file *filp, const char __user *ubuf,
 			       size_t count, loff_t *offp)
 {
@@ -681,18 +760,9 @@ static ssize_t port_fops_write(struct file *filp, const char __user *ubuf,
 
 	nonblock = filp->f_flags & O_NONBLOCK;
 
-	if (will_write_block(port)) {
-		if (nonblock)
-			return -EAGAIN;
-
-		ret = wait_event_freezable(port->waitqueue,
-					   !will_write_block(port));
-		if (ret < 0)
-			return ret;
-	}
-	/* Port got hot-unplugged. */
-	if (!port->guest_connected)
-		return -ENODEV;
+	ret = wait_port_writable(port, nonblock);
+	if (ret < 0)
+		return ret;
 
 	count = min((size_t)(32 * 1024), count);
 
@@ -725,6 +795,93 @@ out:
 	return ret;
 }
 
+struct sg_list {
+	unsigned int n;
+	unsigned int size;
+	size_t len;
+	struct scatterlist *sg;
+};
+
+static int pipe_to_sg(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
+			struct splice_desc *sd)
+{
+	struct sg_list *sgl = sd->u.data;
+	unsigned int offset, len;
+
+	if (sgl->n == sgl->size)
+		return 0;
+
+	/* Try lock this page */
+	if (buf->ops->steal(pipe, buf) == 0) {
+		/* Get reference and unlock page for moving */
+		get_page(buf->page);
+		unlock_page(buf->page);
+
+		len = min(buf->len, sd->len);
+		sg_set_page(&(sgl->sg[sgl->n]), buf->page, len, buf->offset);
+	} else {
+		/* Failback to copying a page */
+		struct page *page = alloc_page(GFP_KERNEL);
+		char *src = buf->ops->map(pipe, buf, 1);
+		char *dst;
+
+		if (!page)
+			return -ENOMEM;
+		dst = kmap(page);
+
+		offset = sd->pos & ~PAGE_MASK;
+
+		len = sd->len;
+		if (len + offset > PAGE_SIZE)
+			len = PAGE_SIZE - offset;
+
+		memcpy(dst + offset, src + buf->offset, len);
+
+		kunmap(page);
+		buf->ops->unmap(pipe, buf, src);
+
+		sg_set_page(&(sgl->sg[sgl->n]), page, len, offset);
+	}
+	sgl->n++;
+	sgl->len += len;
+
+	return len;
+}
+
+/* Faster zero-copy write by splicing */
+static ssize_t port_fops_splice_write(struct pipe_inode_info *pipe,
+				      struct file *filp, loff_t *ppos,
+				      size_t len, unsigned int flags)
+{
+	struct port *port = filp->private_data;
+	struct sg_list sgl;
+	ssize_t ret;
+	struct splice_desc sd = {
+		.total_len = len,
+		.flags = flags,
+		.pos = *ppos,
+		.u.data = &sgl,
+	};
+
+	ret = wait_port_writable(port, filp->f_flags & O_NONBLOCK);
+	if (ret < 0)
+		return ret;
+
+	sgl.n = 0;
+	sgl.len = 0;
+	sgl.size = pipe->nrbufs;
+	sgl.sg = kmalloc(sizeof(struct scatterlist) * sgl.size, GFP_KERNEL);
+	if (unlikely(!sgl.sg))
+		return -ENOMEM;
+
+	sg_init_table(sgl.sg, sgl.size);
+	ret = __splice_from_pipe(pipe, &sd, pipe_to_sg);
+	if (likely(ret > 0))
+		ret = send_pages(port, sgl.sg, sgl.n, sgl.len, true);
+
+	return ret;
+}
+
 static unsigned int port_fops_poll(struct file *filp, poll_table *wait)
 {
 	struct port *port;
@@ -856,6 +1013,7 @@ static const struct file_operations port_fops = {
 	.open  = port_fops_open,
 	.read  = port_fops_read,
 	.write = port_fops_write,
+	.splice_write = port_fops_splice_write,
 	.poll  = port_fops_poll,
 	.release = port_fops_release,
 	.fasync = port_fops_fasync,
@@ -1941,7 +2099,17 @@ static int __init init(void)
 	INIT_LIST_HEAD(&pdrvdata.consoles);
 	INIT_LIST_HEAD(&pdrvdata.portdevs);
 
-	return register_virtio_driver(&virtio_console);
+	err = register_virtio_driver(&virtio_console);
+	if (err < 0) {
+		pr_err("Error %d registering virtio driver\n", err);
+		goto free;
+	}
+	return 0;
+free:
+	if (pdrvdata.debugfs_dir)
+		debugfs_remove_recursive(pdrvdata.debugfs_dir);
+	class_destroy(pdrvdata.class);
+	return err;
 }
 
 static void __exit fini(void)
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 7f0b5ca..bace9e9 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -40,4 +40,17 @@ config COMMON_CLK_WM831X
           Supports the clocking subsystem of the WM831x/2x series of
 	  PMICs from Wolfson Microlectronics.
 
+config COMMON_CLK_VERSATILE
+	bool "Clock driver for ARM Reference designs"
+	depends on ARCH_INTEGRATOR || ARCH_REALVIEW
+	---help---
+          Supports clocking on ARM Reference designs Integrator/AP,
+	  Integrator/CP, RealView PB1176, EB, PB11MP and PBX.
+
+config COMMON_CLK_MAX77686
+	tristate "Clock driver for Maxim 77686 MFD"
+	depends on MFD_MAX77686
+	---help---
+	  This driver supports Maxim 77686 crystal oscillator clock. 
+
 endmenu
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 72ce247..71a25b9 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -4,13 +4,22 @@ obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
 obj-$(CONFIG_COMMON_CLK)	+= clk.o clk-fixed-rate.o clk-gate.o \
 				   clk-mux.o clk-divider.o clk-fixed-factor.o
 # SoCs specific
+obj-$(CONFIG_ARCH_BCM2835)	+= clk-bcm2835.o
 obj-$(CONFIG_ARCH_NOMADIK)	+= clk-nomadik.o
 obj-$(CONFIG_ARCH_HIGHBANK)	+= clk-highbank.o
 obj-$(CONFIG_ARCH_MXS)		+= mxs/
 obj-$(CONFIG_ARCH_SOCFPGA)	+= socfpga/
 obj-$(CONFIG_PLAT_SPEAR)	+= spear/
 obj-$(CONFIG_ARCH_U300)		+= clk-u300.o
-obj-$(CONFIG_ARCH_INTEGRATOR)	+= versatile/
+obj-$(CONFIG_COMMON_CLK_VERSATILE) += versatile/
+obj-$(CONFIG_ARCH_PRIMA2)	+= clk-prima2.o
+ifeq ($(CONFIG_COMMON_CLK), y)
+obj-$(CONFIG_ARCH_MMP)		+= mmp/
+endif
+obj-$(CONFIG_MACH_LOONGSON1)	+= clk-ls1x.o
+obj-$(CONFIG_ARCH_U8500)	+= ux500/
+obj-$(CONFIG_ARCH_VT8500)	+= clk-vt8500.o
 
 # Chip specific
 obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o
+obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o
diff --git a/drivers/clk/clk-bcm2835.c b/drivers/clk/clk-bcm2835.c
new file mode 100644
index 0000000..67ad16b
--- /dev/null
+++ b/drivers/clk/clk-bcm2835.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2010 Broadcom
+ * Copyright (C) 2012 Stephen Warren
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/clk/bcm2835.h>
+
+/*
+ * These are fixed clocks. They're probably not all root clocks and it may
+ * be possible to turn them on and off but until this is mapped out better
+ * it's the only way they can be used.
+ */
+void __init bcm2835_init_clocks(void)
+{
+	struct clk *clk;
+	int ret;
+
+	clk = clk_register_fixed_rate(NULL, "sys_pclk", NULL, CLK_IS_ROOT,
+					250000000);
+	if (!clk)
+		pr_err("sys_pclk not registered\n");
+
+	clk = clk_register_fixed_rate(NULL, "apb_pclk", NULL, CLK_IS_ROOT,
+					126000000);
+	if (!clk)
+		pr_err("apb_pclk not registered\n");
+
+	clk = clk_register_fixed_rate(NULL, "uart0_pclk", NULL, CLK_IS_ROOT,
+					3000000);
+	if (!clk)
+		pr_err("uart0_pclk not registered\n");
+	ret = clk_register_clkdev(clk, NULL, "20201000.uart");
+	if (ret)
+		pr_err("uart0_pclk alias not registered\n");
+
+	clk = clk_register_fixed_rate(NULL, "uart1_pclk", NULL, CLK_IS_ROOT,
+					125000000);
+	if (!clk)
+		pr_err("uart1_pclk not registered\n");
+	ret = clk_register_clkdev(clk, NULL, "20215000.uart");
+	if (ret)
+		pr_err("uart0_pclk alias not registered\n");
+}
diff --git a/drivers/clk/clk-ls1x.c b/drivers/clk/clk-ls1x.c
new file mode 100644
index 0000000..f20b750
--- /dev/null
+++ b/drivers/clk/clk-ls1x.c
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2012 Zhang, Keguang <keguang.zhang@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/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+
+#include <loongson1.h>
+
+#define OSC	33
+
+static DEFINE_SPINLOCK(_lock);
+
+static int ls1x_pll_clk_enable(struct clk_hw *hw)
+{
+	return 0;
+}
+
+static void ls1x_pll_clk_disable(struct clk_hw *hw)
+{
+}
+
+static unsigned long ls1x_pll_recalc_rate(struct clk_hw *hw,
+					     unsigned long parent_rate)
+{
+	u32 pll, rate;
+
+	pll = __raw_readl(LS1X_CLK_PLL_FREQ);
+	rate = ((12 + (pll & 0x3f)) * 1000000) +
+		((((pll >> 8) & 0x3ff) * 1000000) >> 10);
+	rate *= OSC;
+	rate >>= 1;
+
+	return rate;
+}
+
+static const struct clk_ops ls1x_pll_clk_ops = {
+	.enable = ls1x_pll_clk_enable,
+	.disable = ls1x_pll_clk_disable,
+	.recalc_rate = ls1x_pll_recalc_rate,
+};
+
+static struct clk * __init clk_register_pll(struct device *dev,
+	 const char *name, const char *parent_name, unsigned long flags)
+{
+	struct clk_hw *hw;
+	struct clk *clk;
+	struct clk_init_data init;
+
+	/* allocate the divider */
+	hw = kzalloc(sizeof(struct clk_hw), GFP_KERNEL);
+	if (!hw) {
+		pr_err("%s: could not allocate clk_hw\n", __func__);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	init.name = name;
+	init.ops = &ls1x_pll_clk_ops;
+	init.flags = flags | CLK_IS_BASIC;
+	init.parent_names = (parent_name ? &parent_name : NULL);
+	init.num_parents = (parent_name ? 1 : 0);
+	hw->init = &init;
+
+	/* register the clock */
+	clk = clk_register(dev, hw);
+
+	if (IS_ERR(clk))
+		kfree(hw);
+
+	return clk;
+}
+
+void __init ls1x_clk_init(void)
+{
+	struct clk *clk;
+
+	clk = clk_register_pll(NULL, "pll_clk", NULL, CLK_IS_ROOT);
+	clk_prepare_enable(clk);
+
+	clk = clk_register_divider(NULL, "cpu_clk", "pll_clk",
+			CLK_SET_RATE_PARENT, LS1X_CLK_PLL_DIV, DIV_CPU_SHIFT,
+			DIV_CPU_WIDTH, CLK_DIVIDER_ONE_BASED, &_lock);
+	clk_prepare_enable(clk);
+	clk_register_clkdev(clk, "cpu", NULL);
+
+	clk = clk_register_divider(NULL, "dc_clk", "pll_clk",
+			CLK_SET_RATE_PARENT, LS1X_CLK_PLL_DIV, DIV_DC_SHIFT,
+			DIV_DC_WIDTH, CLK_DIVIDER_ONE_BASED, &_lock);
+	clk_prepare_enable(clk);
+	clk_register_clkdev(clk, "dc", NULL);
+
+	clk = clk_register_divider(NULL, "ahb_clk", "pll_clk",
+			CLK_SET_RATE_PARENT, LS1X_CLK_PLL_DIV, DIV_DDR_SHIFT,
+			DIV_DDR_WIDTH, CLK_DIVIDER_ONE_BASED, &_lock);
+	clk_prepare_enable(clk);
+	clk_register_clkdev(clk, "ahb", NULL);
+	clk_register_clkdev(clk, "stmmaceth", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "apb_clk", "ahb_clk", 0, 1, 2);
+	clk_prepare_enable(clk);
+	clk_register_clkdev(clk, "apb", NULL);
+	clk_register_clkdev(clk, "serial8250", NULL);
+}
diff --git a/drivers/clk/clk-max77686.c b/drivers/clk/clk-max77686.c
new file mode 100644
index 0000000..ac5f543
--- /dev/null
+++ b/drivers/clk/clk-max77686.c
@@ -0,0 +1,244 @@
+/*
+ * clk-max77686.c - Clock driver for Maxim 77686
+ *
+ * Copyright (C) 2012 Samsung Electornics
+ * Jonghwa Lee <jonghwa3.lee@samsung.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License 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/kernel.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/max77686.h>
+#include <linux/mfd/max77686-private.h>
+#include <linux/clk-provider.h>
+#include <linux/mutex.h>
+#include <linux/clkdev.h>
+
+enum {
+	MAX77686_CLK_AP = 0,
+	MAX77686_CLK_CP,
+	MAX77686_CLK_PMIC,
+	MAX77686_CLKS_NUM,
+};
+
+struct max77686_clk {
+	struct max77686_dev *iodev;
+	u32 mask;
+	struct clk_hw hw;
+	struct clk_lookup *lookup;
+};
+
+static struct max77686_clk *get_max77686_clk(struct clk_hw *hw)
+{
+	return container_of(hw, struct max77686_clk, hw);
+}
+
+static int max77686_clk_prepare(struct clk_hw *hw)
+{
+	struct max77686_clk *max77686;
+	int ret;
+
+	max77686 = get_max77686_clk(hw);
+	if (!max77686)
+		return -ENOMEM;
+
+	ret = regmap_update_bits(max77686->iodev->regmap,
+		MAX77686_REG_32KHZ, max77686->mask, max77686->mask);
+
+	return ret;
+}
+
+static void max77686_clk_unprepare(struct clk_hw *hw)
+{
+	struct max77686_clk *max77686;
+
+	max77686 = get_max77686_clk(hw);
+	if (!max77686)
+		return;
+
+	regmap_update_bits(max77686->iodev->regmap,
+		MAX77686_REG_32KHZ, max77686->mask, ~max77686->mask);
+}
+
+static int max77686_clk_is_enabled(struct clk_hw *hw)
+{
+	struct max77686_clk *max77686;
+	int ret;
+	u32 val;
+
+	max77686 = get_max77686_clk(hw);
+	if (!max77686)
+		return -ENOMEM;
+
+	ret = regmap_read(max77686->iodev->regmap,
+				MAX77686_REG_32KHZ, &val);
+
+	if (ret < 0)
+		return -EINVAL;
+
+	return val & max77686->mask;
+}
+
+static struct clk_ops max77686_clk_ops = {
+	.prepare	= max77686_clk_prepare,
+	.unprepare	= max77686_clk_unprepare,
+	.is_enabled	= max77686_clk_is_enabled,
+};
+
+static struct clk_init_data max77686_clks_init[MAX77686_CLKS_NUM] = {
+	[MAX77686_CLK_AP] = {
+		.name = "32khz_ap",
+		.ops = &max77686_clk_ops,
+		.flags = CLK_IS_ROOT,
+	},
+	[MAX77686_CLK_CP] = {
+		.name = "32khz_cp",
+		.ops = &max77686_clk_ops,
+		.flags = CLK_IS_ROOT,
+	},
+	[MAX77686_CLK_PMIC] = {
+		.name = "32khz_pmic",
+		.ops = &max77686_clk_ops,
+		.flags = CLK_IS_ROOT,
+	},
+};
+
+static int max77686_clk_register(struct device *dev,
+				struct max77686_clk *max77686)
+{
+	struct clk *clk;
+	struct clk_hw *hw = &max77686->hw;
+
+	clk = clk_register(dev, hw);
+
+	if (IS_ERR(clk))
+		return -ENOMEM;
+
+	max77686->lookup = devm_kzalloc(dev, sizeof(struct clk_lookup),
+					GFP_KERNEL);
+	if (IS_ERR(max77686->lookup))
+		return -ENOMEM;
+
+	max77686->lookup->con_id = hw->init->name;
+	max77686->lookup->clk = clk;
+
+	clkdev_add(max77686->lookup);
+
+	return 0;
+}
+
+static __devinit int max77686_clk_probe(struct platform_device *pdev)
+{
+	struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent);
+	struct max77686_clk **max77686_clks;
+	int i, ret;
+
+	max77686_clks = devm_kzalloc(&pdev->dev, sizeof(struct max77686_clk *)
+					* MAX77686_CLKS_NUM, GFP_KERNEL);
+	if (IS_ERR(max77686_clks))
+		return -ENOMEM;
+
+	for (i = 0; i < MAX77686_CLKS_NUM; i++) {
+		max77686_clks[i] = devm_kzalloc(&pdev->dev,
+					sizeof(struct max77686_clk), GFP_KERNEL);
+		if (IS_ERR(max77686_clks[i]))
+			return -ENOMEM;
+	}
+
+	for (i = 0; i < MAX77686_CLKS_NUM; i++) {
+		max77686_clks[i]->iodev = iodev;
+		max77686_clks[i]->mask = 1 << i;
+		max77686_clks[i]->hw.init = &max77686_clks_init[i];
+
+		ret = max77686_clk_register(&pdev->dev, max77686_clks[i]);
+		if (ret) {
+			switch (i) {
+			case MAX77686_CLK_AP:
+				dev_err(&pdev->dev, "Fail to register CLK_AP\n");
+				goto err_clk_ap;
+				break;
+			case MAX77686_CLK_CP:
+				dev_err(&pdev->dev, "Fail to register CLK_CP\n");
+				goto err_clk_cp;
+				break;
+			case MAX77686_CLK_PMIC:
+				dev_err(&pdev->dev, "Fail to register CLK_PMIC\n");
+				goto err_clk_pmic;
+			}
+		}
+	}
+
+	platform_set_drvdata(pdev, max77686_clks);
+
+	goto out;
+
+err_clk_pmic:
+	clkdev_drop(max77686_clks[MAX77686_CLK_CP]->lookup);
+	kfree(max77686_clks[MAX77686_CLK_CP]->hw.clk);
+err_clk_cp:
+	clkdev_drop(max77686_clks[MAX77686_CLK_AP]->lookup);
+	kfree(max77686_clks[MAX77686_CLK_AP]->hw.clk);
+err_clk_ap:
+out:
+	return ret;
+}
+
+static int __devexit max77686_clk_remove(struct platform_device *pdev)
+{
+	struct max77686_clk **max77686_clks = platform_get_drvdata(pdev);
+	int i;
+
+	for (i = 0; i < MAX77686_CLKS_NUM; i++) {
+		clkdev_drop(max77686_clks[i]->lookup);
+		kfree(max77686_clks[i]->hw.clk);
+	}
+	return 0;
+}
+
+static const struct platform_device_id max77686_clk_id[] = {
+	{ "max77686-clk", 0},
+	{ },
+};
+MODULE_DEVICE_TABLE(platform, max77686_clk_id);
+
+static struct platform_driver max77686_clk_driver = {
+	.driver = {
+		.name  = "max77686-clk",
+		.owner = THIS_MODULE,
+	},
+	.probe = max77686_clk_probe,
+	.remove = __devexit_p(max77686_clk_remove),
+	.id_table = max77686_clk_id,
+};
+
+static int __init max77686_clk_init(void)
+{
+	return platform_driver_register(&max77686_clk_driver);
+}
+subsys_initcall(max77686_clk_init);
+
+static void __init max77686_clk_cleanup(void)
+{
+	platform_driver_unregister(&max77686_clk_driver);
+}
+module_exit(max77686_clk_cleanup);
+
+MODULE_DESCRIPTION("MAXIM 77686 Clock Driver");
+MODULE_AUTHOR("Jonghwa Lee <jonghwa3.lee@samsung.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/clk-prima2.c b/drivers/clk/clk-prima2.c
new file mode 100644
index 0000000..517874f
--- /dev/null
+++ b/drivers/clk/clk-prima2.c
@@ -0,0 +1,1171 @@
+/*
+ * Clock tree for CSR SiRFprimaII
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/module.h>
+#include <linux/bitops.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/of_address.h>
+#include <linux/syscore_ops.h>
+
+#define SIRFSOC_CLKC_CLK_EN0    0x0000
+#define SIRFSOC_CLKC_CLK_EN1    0x0004
+#define SIRFSOC_CLKC_REF_CFG    0x0014
+#define SIRFSOC_CLKC_CPU_CFG    0x0018
+#define SIRFSOC_CLKC_MEM_CFG    0x001c
+#define SIRFSOC_CLKC_SYS_CFG    0x0020
+#define SIRFSOC_CLKC_IO_CFG     0x0024
+#define SIRFSOC_CLKC_DSP_CFG    0x0028
+#define SIRFSOC_CLKC_GFX_CFG    0x002c
+#define SIRFSOC_CLKC_MM_CFG     0x0030
+#define SIRFSOC_CLKC_LCD_CFG     0x0034
+#define SIRFSOC_CLKC_MMC_CFG    0x0038
+#define SIRFSOC_CLKC_PLL1_CFG0  0x0040
+#define SIRFSOC_CLKC_PLL2_CFG0  0x0044
+#define SIRFSOC_CLKC_PLL3_CFG0  0x0048
+#define SIRFSOC_CLKC_PLL1_CFG1  0x004c
+#define SIRFSOC_CLKC_PLL2_CFG1  0x0050
+#define SIRFSOC_CLKC_PLL3_CFG1  0x0054
+#define SIRFSOC_CLKC_PLL1_CFG2  0x0058
+#define SIRFSOC_CLKC_PLL2_CFG2  0x005c
+#define SIRFSOC_CLKC_PLL3_CFG2  0x0060
+#define SIRFSOC_USBPHY_PLL_CTRL 0x0008
+#define SIRFSOC_USBPHY_PLL_POWERDOWN  BIT(1)
+#define SIRFSOC_USBPHY_PLL_BYPASS     BIT(2)
+#define SIRFSOC_USBPHY_PLL_LOCK       BIT(3)
+
+static void *sirfsoc_clk_vbase, *sirfsoc_rsc_vbase;
+
+#define KHZ     1000
+#define MHZ     (KHZ * KHZ)
+
+/*
+ * SiRFprimaII clock controller
+ * - 2 oscillators: osc-26MHz, rtc-32.768KHz
+ * - 3 standard configurable plls: pll1, pll2 & pll3
+ * - 2 exclusive plls: usb phy pll and sata phy pll
+ * - 8 clock domains: cpu/cpudiv, mem/memdiv, sys/io, dsp, graphic, multimedia,
+ *     display and sdphy.
+ *     Each clock domain can select its own clock source from five clock sources,
+ *     X_XIN, X_XINW, PLL1, PLL2 and PLL3. The domain clock is used as the source
+ *     clock of the group clock.
+ *     - dsp domain: gps, mf
+ *     - io domain: dmac, nand, audio, uart, i2c, spi, usp, pwm, pulse
+ *     - sys domain: security
+ */
+
+struct clk_pll {
+	struct clk_hw hw;
+	unsigned short regofs;  /* register offset */
+};
+
+#define to_pllclk(_hw) container_of(_hw, struct clk_pll, hw)
+
+struct clk_dmn {
+	struct clk_hw hw;
+	signed char enable_bit; /* enable bit: 0 ~ 63 */
+	unsigned short regofs;  /* register offset */
+};
+
+#define to_dmnclk(_hw) container_of(_hw, struct clk_dmn, hw)
+
+struct clk_std {
+	struct clk_hw hw;
+	signed char enable_bit; /* enable bit: 0 ~ 63 */
+};
+
+#define to_stdclk(_hw) container_of(_hw, struct clk_std, hw)
+
+static int std_clk_is_enabled(struct clk_hw *hw);
+static int std_clk_enable(struct clk_hw *hw);
+static void std_clk_disable(struct clk_hw *hw);
+
+static inline unsigned long clkc_readl(unsigned reg)
+{
+	return readl(sirfsoc_clk_vbase + reg);
+}
+
+static inline void clkc_writel(u32 val, unsigned reg)
+{
+	writel(val, sirfsoc_clk_vbase + reg);
+}
+
+/*
+ * std pll
+ */
+
+static unsigned long pll_clk_recalc_rate(struct clk_hw *hw,
+	unsigned long parent_rate)
+{
+	unsigned long fin = parent_rate;
+	struct clk_pll *clk = to_pllclk(hw);
+	u32 regcfg2 = clk->regofs + SIRFSOC_CLKC_PLL1_CFG2 -
+		SIRFSOC_CLKC_PLL1_CFG0;
+
+	if (clkc_readl(regcfg2) & BIT(2)) {
+		/* pll bypass mode */
+		return fin;
+	} else {
+		/* fout = fin * nf / nr / od */
+		u32 cfg0 = clkc_readl(clk->regofs);
+		u32 nf = (cfg0 & (BIT(13) - 1)) + 1;
+		u32 nr = ((cfg0 >> 13) & (BIT(6) - 1)) + 1;
+		u32 od = ((cfg0 >> 19) & (BIT(4) - 1)) + 1;
+		WARN_ON(fin % MHZ);
+		return fin / MHZ * nf / nr / od * MHZ;
+	}
+}
+
+static long pll_clk_round_rate(struct clk_hw *hw, unsigned long rate,
+	unsigned long *parent_rate)
+{
+	unsigned long fin, nf, nr, od;
+
+	/*
+	 * fout = fin * nf / (nr * od);
+	 * set od = 1, nr = fin/MHz, so fout = nf * MHz
+	 */
+	rate = rate - rate % MHZ;
+
+	nf = rate / MHZ;
+	if (nf > BIT(13))
+		nf = BIT(13);
+	if (nf < 1)
+		nf = 1;
+
+	fin = *parent_rate;
+
+	nr = fin / MHZ;
+	if (nr > BIT(6))
+		nr = BIT(6);
+	od = 1;
+
+	return fin * nf / (nr * od);
+}
+
+static int pll_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+	unsigned long parent_rate)
+{
+	struct clk_pll *clk = to_pllclk(hw);
+	unsigned long fin, nf, nr, od, reg;
+
+	/*
+	 * fout = fin * nf / (nr * od);
+	 * set od = 1, nr = fin/MHz, so fout = nf * MHz
+	 */
+
+	nf = rate / MHZ;
+	if (unlikely((rate % MHZ) || nf > BIT(13) || nf < 1))
+		return -EINVAL;
+
+	fin = parent_rate;
+	BUG_ON(fin < MHZ);
+
+	nr = fin / MHZ;
+	BUG_ON((fin % MHZ) || nr > BIT(6));
+
+	od = 1;
+
+	reg = (nf - 1) | ((nr - 1) << 13) | ((od - 1) << 19);
+	clkc_writel(reg, clk->regofs);
+
+	reg = clk->regofs + SIRFSOC_CLKC_PLL1_CFG1 - SIRFSOC_CLKC_PLL1_CFG0;
+	clkc_writel((nf >> 1) - 1, reg);
+
+	reg = clk->regofs + SIRFSOC_CLKC_PLL1_CFG2 - SIRFSOC_CLKC_PLL1_CFG0;
+	while (!(clkc_readl(reg) & BIT(6)))
+		cpu_relax();
+
+	return 0;
+}
+
+static struct clk_ops std_pll_ops = {
+	.recalc_rate = pll_clk_recalc_rate,
+	.round_rate = pll_clk_round_rate,
+	.set_rate = pll_clk_set_rate,
+};
+
+static const char *pll_clk_parents[] = {
+	"osc",
+};
+
+static struct clk_init_data clk_pll1_init = {
+	.name = "pll1",
+	.ops = &std_pll_ops,
+	.parent_names = pll_clk_parents,
+	.num_parents = ARRAY_SIZE(pll_clk_parents),
+};
+
+static struct clk_init_data clk_pll2_init = {
+	.name = "pll2",
+	.ops = &std_pll_ops,
+	.parent_names = pll_clk_parents,
+	.num_parents = ARRAY_SIZE(pll_clk_parents),
+};
+
+static struct clk_init_data clk_pll3_init = {
+	.name = "pll3",
+	.ops = &std_pll_ops,
+	.parent_names = pll_clk_parents,
+	.num_parents = ARRAY_SIZE(pll_clk_parents),
+};
+
+static struct clk_pll clk_pll1 = {
+	.regofs = SIRFSOC_CLKC_PLL1_CFG0,
+	.hw = {
+		.init = &clk_pll1_init,
+	},
+};
+
+static struct clk_pll clk_pll2 = {
+	.regofs = SIRFSOC_CLKC_PLL2_CFG0,
+	.hw = {
+		.init = &clk_pll2_init,
+	},
+};
+
+static struct clk_pll clk_pll3 = {
+	.regofs = SIRFSOC_CLKC_PLL3_CFG0,
+	.hw = {
+		.init = &clk_pll3_init,
+	},
+};
+
+/*
+ * usb uses specified pll
+ */
+
+static int usb_pll_clk_enable(struct clk_hw *hw)
+{
+	u32 reg = readl(sirfsoc_rsc_vbase + SIRFSOC_USBPHY_PLL_CTRL);
+	reg &= ~(SIRFSOC_USBPHY_PLL_POWERDOWN | SIRFSOC_USBPHY_PLL_BYPASS);
+	writel(reg, sirfsoc_rsc_vbase + SIRFSOC_USBPHY_PLL_CTRL);
+	while (!(readl(sirfsoc_rsc_vbase + SIRFSOC_USBPHY_PLL_CTRL) &
+			SIRFSOC_USBPHY_PLL_LOCK))
+		cpu_relax();
+
+	return 0;
+}
+
+static void usb_pll_clk_disable(struct clk_hw *clk)
+{
+	u32 reg = readl(sirfsoc_rsc_vbase + SIRFSOC_USBPHY_PLL_CTRL);
+	reg |= (SIRFSOC_USBPHY_PLL_POWERDOWN | SIRFSOC_USBPHY_PLL_BYPASS);
+	writel(reg, sirfsoc_rsc_vbase + SIRFSOC_USBPHY_PLL_CTRL);
+}
+
+static unsigned long usb_pll_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
+{
+	u32 reg = readl(sirfsoc_rsc_vbase + SIRFSOC_USBPHY_PLL_CTRL);
+	return (reg & SIRFSOC_USBPHY_PLL_BYPASS) ? parent_rate : 48*MHZ;
+}
+
+static struct clk_ops usb_pll_ops = {
+	.enable = usb_pll_clk_enable,
+	.disable = usb_pll_clk_disable,
+	.recalc_rate = usb_pll_clk_recalc_rate,
+};
+
+static struct clk_init_data clk_usb_pll_init = {
+	.name = "usb_pll",
+	.ops = &usb_pll_ops,
+	.parent_names = pll_clk_parents,
+	.num_parents = ARRAY_SIZE(pll_clk_parents),
+};
+
+static struct clk_hw usb_pll_clk_hw = {
+	.init = &clk_usb_pll_init,
+};
+
+/*
+ * clock domains - cpu, mem, sys/io, dsp, gfx
+ */
+
+static const char *dmn_clk_parents[] = {
+	"rtc",
+	"osc",
+	"pll1",
+	"pll2",
+	"pll3",
+};
+
+static u8 dmn_clk_get_parent(struct clk_hw *hw)
+{
+	struct clk_dmn *clk = to_dmnclk(hw);
+	u32 cfg = clkc_readl(clk->regofs);
+
+	/* parent of io domain can only be pll3 */
+	if (strcmp(hw->init->name, "io") == 0)
+		return 4;
+
+	WARN_ON((cfg & (BIT(3) - 1)) > 4);
+
+	return cfg & (BIT(3) - 1);
+}
+
+static int dmn_clk_set_parent(struct clk_hw *hw, u8 parent)
+{
+	struct clk_dmn *clk = to_dmnclk(hw);
+	u32 cfg = clkc_readl(clk->regofs);
+
+	/* parent of io domain can only be pll3 */
+	if (strcmp(hw->init->name, "io") == 0)
+		return -EINVAL;
+
+	cfg &= ~(BIT(3) - 1);
+	clkc_writel(cfg | parent, clk->regofs);
+	/* BIT(3) - switching status: 1 - busy, 0 - done */
+	while (clkc_readl(clk->regofs) & BIT(3))
+		cpu_relax();
+
+	return 0;
+}
+
+static unsigned long dmn_clk_recalc_rate(struct clk_hw *hw,
+	unsigned long parent_rate)
+
+{
+	unsigned long fin = parent_rate;
+	struct clk_dmn *clk = to_dmnclk(hw);
+
+	u32 cfg = clkc_readl(clk->regofs);
+
+	if (cfg & BIT(24)) {
+		/* fcd bypass mode */
+		return fin;
+	} else {
+		/*
+		 * wait count: bit[19:16], hold count: bit[23:20]
+		 */
+		u32 wait = (cfg >> 16) & (BIT(4) - 1);
+		u32 hold = (cfg >> 20) & (BIT(4) - 1);
+
+		return fin / (wait + hold + 2);
+	}
+}
+
+static long dmn_clk_round_rate(struct clk_hw *hw, unsigned long rate,
+	unsigned long *parent_rate)
+{
+	unsigned long fin;
+	unsigned ratio, wait, hold;
+	unsigned bits = (strcmp(hw->init->name, "mem") == 0) ? 3 : 4;
+
+	fin = *parent_rate;
+	ratio = fin / rate;
+
+	if (ratio < 2)
+		ratio = 2;
+	if (ratio > BIT(bits + 1))
+		ratio = BIT(bits + 1);
+
+	wait = (ratio >> 1) - 1;
+	hold = ratio - wait - 2;
+
+	return fin / (wait + hold + 2);
+}
+
+static int dmn_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+	unsigned long parent_rate)
+{
+	struct clk_dmn *clk = to_dmnclk(hw);
+	unsigned long fin;
+	unsigned ratio, wait, hold, reg;
+	unsigned bits = (strcmp(hw->init->name, "mem") == 0) ? 3 : 4;
+
+	fin = parent_rate;
+	ratio = fin / rate;
+
+	if (unlikely(ratio < 2 || ratio > BIT(bits + 1)))
+		return -EINVAL;
+
+	WARN_ON(fin % rate);
+
+	wait = (ratio >> 1) - 1;
+	hold = ratio - wait - 2;
+
+	reg = clkc_readl(clk->regofs);
+	reg &= ~(((BIT(bits) - 1) << 16) | ((BIT(bits) - 1) << 20));
+	reg |= (wait << 16) | (hold << 20) | BIT(25);
+	clkc_writel(reg, clk->regofs);
+
+	/* waiting FCD been effective */
+	while (clkc_readl(clk->regofs) & BIT(25))
+		cpu_relax();
+
+	return 0;
+}
+
+static struct clk_ops msi_ops = {
+	.set_rate = dmn_clk_set_rate,
+	.round_rate = dmn_clk_round_rate,
+	.recalc_rate = dmn_clk_recalc_rate,
+	.set_parent = dmn_clk_set_parent,
+	.get_parent = dmn_clk_get_parent,
+};
+
+static struct clk_init_data clk_mem_init = {
+	.name = "mem",
+	.ops = &msi_ops,
+	.parent_names = dmn_clk_parents,
+	.num_parents = ARRAY_SIZE(dmn_clk_parents),
+};
+
+static struct clk_dmn clk_mem = {
+	.regofs = SIRFSOC_CLKC_MEM_CFG,
+	.hw = {
+		.init = &clk_mem_init,
+	},
+};
+
+static struct clk_init_data clk_sys_init = {
+	.name = "sys",
+	.ops = &msi_ops,
+	.parent_names = dmn_clk_parents,
+	.num_parents = ARRAY_SIZE(dmn_clk_parents),
+	.flags = CLK_SET_RATE_GATE,
+};
+
+static struct clk_dmn clk_sys = {
+	.regofs = SIRFSOC_CLKC_SYS_CFG,
+	.hw = {
+		.init = &clk_sys_init,
+	},
+};
+
+static struct clk_init_data clk_io_init = {
+	.name = "io",
+	.ops = &msi_ops,
+	.parent_names = dmn_clk_parents,
+	.num_parents = ARRAY_SIZE(dmn_clk_parents),
+};
+
+static struct clk_dmn clk_io = {
+	.regofs = SIRFSOC_CLKC_IO_CFG,
+	.hw = {
+		.init = &clk_io_init,
+	},
+};
+
+static struct clk_ops cpu_ops = {
+	.set_parent = dmn_clk_set_parent,
+	.get_parent = dmn_clk_get_parent,
+};
+
+static struct clk_init_data clk_cpu_init = {
+	.name = "cpu",
+	.ops = &cpu_ops,
+	.parent_names = dmn_clk_parents,
+	.num_parents = ARRAY_SIZE(dmn_clk_parents),
+	.flags = CLK_SET_RATE_PARENT,
+};
+
+static struct clk_dmn clk_cpu = {
+	.regofs = SIRFSOC_CLKC_CPU_CFG,
+	.hw = {
+		.init = &clk_cpu_init,
+	},
+};
+
+static struct clk_ops dmn_ops = {
+	.is_enabled = std_clk_is_enabled,
+	.enable = std_clk_enable,
+	.disable = std_clk_disable,
+	.set_rate = dmn_clk_set_rate,
+	.round_rate = dmn_clk_round_rate,
+	.recalc_rate = dmn_clk_recalc_rate,
+	.set_parent = dmn_clk_set_parent,
+	.get_parent = dmn_clk_get_parent,
+};
+
+/* dsp, gfx, mm, lcd and vpp domain */
+
+static struct clk_init_data clk_dsp_init = {
+	.name = "dsp",
+	.ops = &dmn_ops,
+	.parent_names = dmn_clk_parents,
+	.num_parents = ARRAY_SIZE(dmn_clk_parents),
+};
+
+static struct clk_dmn clk_dsp = {
+	.regofs = SIRFSOC_CLKC_DSP_CFG,
+	.enable_bit = 0,
+	.hw = {
+		.init = &clk_dsp_init,
+	},
+};
+
+static struct clk_init_data clk_gfx_init = {
+	.name = "gfx",
+	.ops = &dmn_ops,
+	.parent_names = dmn_clk_parents,
+	.num_parents = ARRAY_SIZE(dmn_clk_parents),
+};
+
+static struct clk_dmn clk_gfx = {
+	.regofs = SIRFSOC_CLKC_GFX_CFG,
+	.enable_bit = 8,
+	.hw = {
+		.init = &clk_gfx_init,
+	},
+};
+
+static struct clk_init_data clk_mm_init = {
+	.name = "mm",
+	.ops = &dmn_ops,
+	.parent_names = dmn_clk_parents,
+	.num_parents = ARRAY_SIZE(dmn_clk_parents),
+};
+
+static struct clk_dmn clk_mm = {
+	.regofs = SIRFSOC_CLKC_MM_CFG,
+	.enable_bit = 9,
+	.hw = {
+		.init = &clk_mm_init,
+	},
+};
+
+static struct clk_init_data clk_lcd_init = {
+	.name = "lcd",
+	.ops = &dmn_ops,
+	.parent_names = dmn_clk_parents,
+	.num_parents = ARRAY_SIZE(dmn_clk_parents),
+};
+
+static struct clk_dmn clk_lcd = {
+	.regofs = SIRFSOC_CLKC_LCD_CFG,
+	.enable_bit = 10,
+	.hw = {
+		.init = &clk_lcd_init,
+	},
+};
+
+static struct clk_init_data clk_vpp_init = {
+	.name = "vpp",
+	.ops = &dmn_ops,
+	.parent_names = dmn_clk_parents,
+	.num_parents = ARRAY_SIZE(dmn_clk_parents),
+};
+
+static struct clk_dmn clk_vpp = {
+	.regofs = SIRFSOC_CLKC_LCD_CFG,
+	.enable_bit = 11,
+	.hw = {
+		.init = &clk_vpp_init,
+	},
+};
+
+static struct clk_init_data clk_mmc01_init = {
+	.name = "mmc01",
+	.ops = &dmn_ops,
+	.parent_names = dmn_clk_parents,
+	.num_parents = ARRAY_SIZE(dmn_clk_parents),
+};
+
+static struct clk_dmn clk_mmc01 = {
+	.regofs = SIRFSOC_CLKC_MMC_CFG,
+	.enable_bit = 59,
+	.hw = {
+		.init = &clk_mmc01_init,
+	},
+};
+
+static struct clk_init_data clk_mmc23_init = {
+	.name = "mmc23",
+	.ops = &dmn_ops,
+	.parent_names = dmn_clk_parents,
+	.num_parents = ARRAY_SIZE(dmn_clk_parents),
+};
+
+static struct clk_dmn clk_mmc23 = {
+	.regofs = SIRFSOC_CLKC_MMC_CFG,
+	.enable_bit = 60,
+	.hw = {
+		.init = &clk_mmc23_init,
+	},
+};
+
+static struct clk_init_data clk_mmc45_init = {
+	.name = "mmc45",
+	.ops = &dmn_ops,
+	.parent_names = dmn_clk_parents,
+	.num_parents = ARRAY_SIZE(dmn_clk_parents),
+};
+
+static struct clk_dmn clk_mmc45 = {
+	.regofs = SIRFSOC_CLKC_MMC_CFG,
+	.enable_bit = 61,
+	.hw = {
+		.init = &clk_mmc45_init,
+	},
+};
+
+/*
+ * peripheral controllers in io domain
+ */
+
+static int std_clk_is_enabled(struct clk_hw *hw)
+{
+	u32 reg;
+	int bit;
+	struct clk_std *clk = to_stdclk(hw);
+
+	bit = clk->enable_bit % 32;
+	reg = clk->enable_bit / 32;
+	reg = SIRFSOC_CLKC_CLK_EN0 + reg * sizeof(reg);
+
+	return !!(clkc_readl(reg) & BIT(bit));
+}
+
+static int std_clk_enable(struct clk_hw *hw)
+{
+	u32 val, reg;
+	int bit;
+	struct clk_std *clk = to_stdclk(hw);
+
+	BUG_ON(clk->enable_bit < 0 || clk->enable_bit > 63);
+
+	bit = clk->enable_bit % 32;
+	reg = clk->enable_bit / 32;
+	reg = SIRFSOC_CLKC_CLK_EN0 + reg * sizeof(reg);
+
+	val = clkc_readl(reg) | BIT(bit);
+	clkc_writel(val, reg);
+	return 0;
+}
+
+static void std_clk_disable(struct clk_hw *hw)
+{
+	u32 val, reg;
+	int bit;
+	struct clk_std *clk = to_stdclk(hw);
+
+	BUG_ON(clk->enable_bit < 0 || clk->enable_bit > 63);
+
+	bit = clk->enable_bit % 32;
+	reg = clk->enable_bit / 32;
+	reg = SIRFSOC_CLKC_CLK_EN0 + reg * sizeof(reg);
+
+	val = clkc_readl(reg) & ~BIT(bit);
+	clkc_writel(val, reg);
+}
+
+static const char *std_clk_io_parents[] = {
+	"io",
+};
+
+static struct clk_ops ios_ops = {
+	.is_enabled = std_clk_is_enabled,
+	.enable = std_clk_enable,
+	.disable = std_clk_disable,
+};
+
+static struct clk_init_data clk_dmac0_init = {
+	.name = "dmac0",
+	.ops = &ios_ops,
+	.parent_names = std_clk_io_parents,
+	.num_parents = ARRAY_SIZE(std_clk_io_parents),
+};
+
+static struct clk_std clk_dmac0 = {
+	.enable_bit = 32,
+	.hw = {
+		.init = &clk_dmac0_init,
+	},
+};
+
+static struct clk_init_data clk_dmac1_init = {
+	.name = "dmac1",
+	.ops = &ios_ops,
+	.parent_names = std_clk_io_parents,
+	.num_parents = ARRAY_SIZE(std_clk_io_parents),
+};
+
+static struct clk_std clk_dmac1 = {
+	.enable_bit = 33,
+	.hw = {
+		.init = &clk_dmac1_init,
+	},
+};
+
+static struct clk_init_data clk_nand_init = {
+	.name = "nand",
+	.ops = &ios_ops,
+	.parent_names = std_clk_io_parents,
+	.num_parents = ARRAY_SIZE(std_clk_io_parents),
+};
+
+static struct clk_std clk_nand = {
+	.enable_bit = 34,
+	.hw = {
+		.init = &clk_nand_init,
+	},
+};
+
+static struct clk_init_data clk_audio_init = {
+	.name = "audio",
+	.ops = &ios_ops,
+	.parent_names = std_clk_io_parents,
+	.num_parents = ARRAY_SIZE(std_clk_io_parents),
+};
+
+static struct clk_std clk_audio = {
+	.enable_bit = 35,
+	.hw = {
+		.init = &clk_audio_init,
+	},
+};
+
+static struct clk_init_data clk_uart0_init = {
+	.name = "uart0",
+	.ops = &ios_ops,
+	.parent_names = std_clk_io_parents,
+	.num_parents = ARRAY_SIZE(std_clk_io_parents),
+};
+
+static struct clk_std clk_uart0 = {
+	.enable_bit = 36,
+	.hw = {
+		.init = &clk_uart0_init,
+	},
+};
+
+static struct clk_init_data clk_uart1_init = {
+	.name = "uart1",
+	.ops = &ios_ops,
+	.parent_names = std_clk_io_parents,
+	.num_parents = ARRAY_SIZE(std_clk_io_parents),
+};
+
+static struct clk_std clk_uart1 = {
+	.enable_bit = 37,
+	.hw = {
+		.init = &clk_uart1_init,
+	},
+};
+
+static struct clk_init_data clk_uart2_init = {
+	.name = "uart2",
+	.ops = &ios_ops,
+	.parent_names = std_clk_io_parents,
+	.num_parents = ARRAY_SIZE(std_clk_io_parents),
+};
+
+static struct clk_std clk_uart2 = {
+	.enable_bit = 38,
+	.hw = {
+		.init = &clk_uart2_init,
+	},
+};
+
+static struct clk_init_data clk_usp0_init = {
+	.name = "usp0",
+	.ops = &ios_ops,
+	.parent_names = std_clk_io_parents,
+	.num_parents = ARRAY_SIZE(std_clk_io_parents),
+};
+
+static struct clk_std clk_usp0 = {
+	.enable_bit = 39,
+	.hw = {
+		.init = &clk_usp0_init,
+	},
+};
+
+static struct clk_init_data clk_usp1_init = {
+	.name = "usp1",
+	.ops = &ios_ops,
+	.parent_names = std_clk_io_parents,
+	.num_parents = ARRAY_SIZE(std_clk_io_parents),
+};
+
+static struct clk_std clk_usp1 = {
+	.enable_bit = 40,
+	.hw = {
+		.init = &clk_usp1_init,
+	},
+};
+
+static struct clk_init_data clk_usp2_init = {
+	.name = "usp2",
+	.ops = &ios_ops,
+	.parent_names = std_clk_io_parents,
+	.num_parents = ARRAY_SIZE(std_clk_io_parents),
+};
+
+static struct clk_std clk_usp2 = {
+	.enable_bit = 41,
+	.hw = {
+		.init = &clk_usp2_init,
+	},
+};
+
+static struct clk_init_data clk_vip_init = {
+	.name = "vip",
+	.ops = &ios_ops,
+	.parent_names = std_clk_io_parents,
+	.num_parents = ARRAY_SIZE(std_clk_io_parents),
+};
+
+static struct clk_std clk_vip = {
+	.enable_bit = 42,
+	.hw = {
+		.init = &clk_vip_init,
+	},
+};
+
+static struct clk_init_data clk_spi0_init = {
+	.name = "spi0",
+	.ops = &ios_ops,
+	.parent_names = std_clk_io_parents,
+	.num_parents = ARRAY_SIZE(std_clk_io_parents),
+};
+
+static struct clk_std clk_spi0 = {
+	.enable_bit = 43,
+	.hw = {
+		.init = &clk_spi0_init,
+	},
+};
+
+static struct clk_init_data clk_spi1_init = {
+	.name = "spi1",
+	.ops = &ios_ops,
+	.parent_names = std_clk_io_parents,
+	.num_parents = ARRAY_SIZE(std_clk_io_parents),
+};
+
+static struct clk_std clk_spi1 = {
+	.enable_bit = 44,
+	.hw = {
+		.init = &clk_spi1_init,
+	},
+};
+
+static struct clk_init_data clk_tsc_init = {
+	.name = "tsc",
+	.ops = &ios_ops,
+	.parent_names = std_clk_io_parents,
+	.num_parents = ARRAY_SIZE(std_clk_io_parents),
+};
+
+static struct clk_std clk_tsc = {
+	.enable_bit = 45,
+	.hw = {
+		.init = &clk_tsc_init,
+	},
+};
+
+static struct clk_init_data clk_i2c0_init = {
+	.name = "i2c0",
+	.ops = &ios_ops,
+	.parent_names = std_clk_io_parents,
+	.num_parents = ARRAY_SIZE(std_clk_io_parents),
+};
+
+static struct clk_std clk_i2c0 = {
+	.enable_bit = 46,
+	.hw = {
+		.init = &clk_i2c0_init,
+	},
+};
+
+static struct clk_init_data clk_i2c1_init = {
+	.name = "i2c1",
+	.ops = &ios_ops,
+	.parent_names = std_clk_io_parents,
+	.num_parents = ARRAY_SIZE(std_clk_io_parents),
+};
+
+static struct clk_std clk_i2c1 = {
+	.enable_bit = 47,
+	.hw = {
+		.init = &clk_i2c1_init,
+	},
+};
+
+static struct clk_init_data clk_pwmc_init = {
+	.name = "pwmc",
+	.ops = &ios_ops,
+	.parent_names = std_clk_io_parents,
+	.num_parents = ARRAY_SIZE(std_clk_io_parents),
+};
+
+static struct clk_std clk_pwmc = {
+	.enable_bit = 48,
+	.hw = {
+		.init = &clk_pwmc_init,
+	},
+};
+
+static struct clk_init_data clk_efuse_init = {
+	.name = "efuse",
+	.ops = &ios_ops,
+	.parent_names = std_clk_io_parents,
+	.num_parents = ARRAY_SIZE(std_clk_io_parents),
+};
+
+static struct clk_std clk_efuse = {
+	.enable_bit = 49,
+	.hw = {
+		.init = &clk_efuse_init,
+	},
+};
+
+static struct clk_init_data clk_pulse_init = {
+	.name = "pulse",
+	.ops = &ios_ops,
+	.parent_names = std_clk_io_parents,
+	.num_parents = ARRAY_SIZE(std_clk_io_parents),
+};
+
+static struct clk_std clk_pulse = {
+	.enable_bit = 50,
+	.hw = {
+		.init = &clk_pulse_init,
+	},
+};
+
+static const char *std_clk_dsp_parents[] = {
+	"dsp",
+};
+
+static struct clk_init_data clk_gps_init = {
+	.name = "gps",
+	.ops = &ios_ops,
+	.parent_names = std_clk_dsp_parents,
+	.num_parents = ARRAY_SIZE(std_clk_dsp_parents),
+};
+
+static struct clk_std clk_gps = {
+	.enable_bit = 1,
+	.hw = {
+		.init = &clk_gps_init,
+	},
+};
+
+static struct clk_init_data clk_mf_init = {
+	.name = "mf",
+	.ops = &ios_ops,
+	.parent_names = std_clk_io_parents,
+	.num_parents = ARRAY_SIZE(std_clk_io_parents),
+};
+
+static struct clk_std clk_mf = {
+	.enable_bit = 2,
+	.hw = {
+		.init = &clk_mf_init,
+	},
+};
+
+static const char *std_clk_sys_parents[] = {
+	"sys",
+};
+
+static struct clk_init_data clk_security_init = {
+	.name = "mf",
+	.ops = &ios_ops,
+	.parent_names = std_clk_sys_parents,
+	.num_parents = ARRAY_SIZE(std_clk_sys_parents),
+};
+
+static struct clk_std clk_security = {
+	.enable_bit = 19,
+	.hw = {
+		.init = &clk_security_init,
+	},
+};
+
+static const char *std_clk_usb_parents[] = {
+	"usb_pll",
+};
+
+static struct clk_init_data clk_usb0_init = {
+	.name = "usb0",
+	.ops = &ios_ops,
+	.parent_names = std_clk_usb_parents,
+	.num_parents = ARRAY_SIZE(std_clk_usb_parents),
+};
+
+static struct clk_std clk_usb0 = {
+	.enable_bit = 16,
+	.hw = {
+		.init = &clk_usb0_init,
+	},
+};
+
+static struct clk_init_data clk_usb1_init = {
+	.name = "usb1",
+	.ops = &ios_ops,
+	.parent_names = std_clk_usb_parents,
+	.num_parents = ARRAY_SIZE(std_clk_usb_parents),
+};
+
+static struct clk_std clk_usb1 = {
+	.enable_bit = 17,
+	.hw = {
+		.init = &clk_usb1_init,
+	},
+};
+
+static struct of_device_id clkc_ids[] = {
+	{ .compatible = "sirf,prima2-clkc" },
+	{},
+};
+
+static struct of_device_id rsc_ids[] = {
+	{ .compatible = "sirf,prima2-rsc" },
+	{},
+};
+
+void __init sirfsoc_of_clk_init(void)
+{
+	struct clk *clk;
+	struct device_node *np;
+
+	np = of_find_matching_node(NULL, clkc_ids);
+	if (!np)
+		panic("unable to find compatible clkc node in dtb\n");
+
+	sirfsoc_clk_vbase = of_iomap(np, 0);
+	if (!sirfsoc_clk_vbase)
+		panic("unable to map clkc registers\n");
+
+	of_node_put(np);
+
+	np = of_find_matching_node(NULL, rsc_ids);
+	if (!np)
+		panic("unable to find compatible rsc node in dtb\n");
+
+	sirfsoc_rsc_vbase = of_iomap(np, 0);
+	if (!sirfsoc_rsc_vbase)
+		panic("unable to map rsc registers\n");
+
+	of_node_put(np);
+
+
+	/* These are always available (RTC and 26MHz OSC)*/
+	clk = clk_register_fixed_rate(NULL, "rtc", NULL,
+		CLK_IS_ROOT, 32768);
+	BUG_ON(!clk);
+	clk = clk_register_fixed_rate(NULL, "osc", NULL,
+		CLK_IS_ROOT, 26000000);
+	BUG_ON(!clk);
+
+	clk = clk_register(NULL, &clk_pll1.hw);
+	BUG_ON(!clk);
+	clk = clk_register(NULL, &clk_pll2.hw);
+	BUG_ON(!clk);
+	clk = clk_register(NULL, &clk_pll3.hw);
+	BUG_ON(!clk);
+	clk = clk_register(NULL, &clk_mem.hw);
+	BUG_ON(!clk);
+	clk = clk_register(NULL, &clk_sys.hw);
+	BUG_ON(!clk);
+	clk = clk_register(NULL, &clk_security.hw);
+	BUG_ON(!clk);
+	clk_register_clkdev(clk, NULL, "b8030000.security");
+	clk = clk_register(NULL, &clk_dsp.hw);
+	BUG_ON(!clk);
+	clk = clk_register(NULL, &clk_gps.hw);
+	BUG_ON(!clk);
+	clk_register_clkdev(clk, NULL, "a8010000.gps");
+	clk = clk_register(NULL, &clk_mf.hw);
+	BUG_ON(!clk);
+	clk = clk_register(NULL, &clk_io.hw);
+	BUG_ON(!clk);
+	clk_register_clkdev(clk, NULL, "io");
+	clk = clk_register(NULL, &clk_cpu.hw);
+	BUG_ON(!clk);
+	clk_register_clkdev(clk, NULL, "cpu");
+	clk = clk_register(NULL, &clk_uart0.hw);
+	BUG_ON(!clk);
+	clk_register_clkdev(clk, NULL, "b0050000.uart");
+	clk = clk_register(NULL, &clk_uart1.hw);
+	BUG_ON(!clk);
+	clk_register_clkdev(clk, NULL, "b0060000.uart");
+	clk = clk_register(NULL, &clk_uart2.hw);
+	BUG_ON(!clk);
+	clk_register_clkdev(clk, NULL, "b0070000.uart");
+	clk = clk_register(NULL, &clk_tsc.hw);
+	BUG_ON(!clk);
+	clk_register_clkdev(clk, NULL, "b0110000.tsc");
+	clk = clk_register(NULL, &clk_i2c0.hw);
+	BUG_ON(!clk);
+	clk_register_clkdev(clk, NULL, "b00e0000.i2c");
+	clk = clk_register(NULL, &clk_i2c1.hw);
+	BUG_ON(!clk);
+	clk_register_clkdev(clk, NULL, "b00f0000.i2c");
+	clk = clk_register(NULL, &clk_spi0.hw);
+	BUG_ON(!clk);
+	clk_register_clkdev(clk, NULL, "b00d0000.spi");
+	clk = clk_register(NULL, &clk_spi1.hw);
+	BUG_ON(!clk);
+	clk_register_clkdev(clk, NULL, "b0170000.spi");
+	clk = clk_register(NULL, &clk_pwmc.hw);
+	BUG_ON(!clk);
+	clk_register_clkdev(clk, NULL, "b0130000.pwm");
+	clk = clk_register(NULL, &clk_efuse.hw);
+	BUG_ON(!clk);
+	clk_register_clkdev(clk, NULL, "b0140000.efusesys");
+	clk = clk_register(NULL, &clk_pulse.hw);
+	BUG_ON(!clk);
+	clk_register_clkdev(clk, NULL, "b0150000.pulsec");
+	clk = clk_register(NULL, &clk_dmac0.hw);
+	BUG_ON(!clk);
+	clk_register_clkdev(clk, NULL, "b00b0000.dma-controller");
+	clk = clk_register(NULL, &clk_dmac1.hw);
+	BUG_ON(!clk);
+	clk_register_clkdev(clk, NULL, "b0160000.dma-controller");
+	clk = clk_register(NULL, &clk_nand.hw);
+	BUG_ON(!clk);
+	clk_register_clkdev(clk, NULL, "b0030000.nand");
+	clk = clk_register(NULL, &clk_audio.hw);
+	BUG_ON(!clk);
+	clk_register_clkdev(clk, NULL, "b0040000.audio");
+	clk = clk_register(NULL, &clk_usp0.hw);
+	BUG_ON(!clk);
+	clk_register_clkdev(clk, NULL, "b0080000.usp");
+	clk = clk_register(NULL, &clk_usp1.hw);
+	BUG_ON(!clk);
+	clk_register_clkdev(clk, NULL, "b0090000.usp");
+	clk = clk_register(NULL, &clk_usp2.hw);
+	BUG_ON(!clk);
+	clk_register_clkdev(clk, NULL, "b00a0000.usp");
+	clk = clk_register(NULL, &clk_vip.hw);
+	BUG_ON(!clk);
+	clk_register_clkdev(clk, NULL, "b00c0000.vip");
+	clk = clk_register(NULL, &clk_gfx.hw);
+	BUG_ON(!clk);
+	clk_register_clkdev(clk, NULL, "98000000.graphics");
+	clk = clk_register(NULL, &clk_mm.hw);
+	BUG_ON(!clk);
+	clk_register_clkdev(clk, NULL, "a0000000.multimedia");
+	clk = clk_register(NULL, &clk_lcd.hw);
+	BUG_ON(!clk);
+	clk_register_clkdev(clk, NULL, "90010000.display");
+	clk = clk_register(NULL, &clk_vpp.hw);
+	BUG_ON(!clk);
+	clk_register_clkdev(clk, NULL, "90020000.vpp");
+	clk = clk_register(NULL, &clk_mmc01.hw);
+	BUG_ON(!clk);
+	clk = clk_register(NULL, &clk_mmc23.hw);
+	BUG_ON(!clk);
+	clk = clk_register(NULL, &clk_mmc45.hw);
+	BUG_ON(!clk);
+	clk = clk_register(NULL, &usb_pll_clk_hw);
+	BUG_ON(!clk);
+	clk = clk_register(NULL, &clk_usb0.hw);
+	BUG_ON(!clk);
+	clk_register_clkdev(clk, NULL, "b00e0000.usb");
+	clk = clk_register(NULL, &clk_usb1.hw);
+	BUG_ON(!clk);
+	clk_register_clkdev(clk, NULL, "b00f0000.usb");
+}
diff --git a/drivers/clk/clk-vt8500.c b/drivers/clk/clk-vt8500.c
new file mode 100644
index 0000000..a885600
--- /dev/null
+++ b/drivers/clk/clk-vt8500.c
@@ -0,0 +1,510 @@
+/*
+ * Clock implementation for VIA/Wondermedia SoC's
+ * Copyright (C) 2012 Tony Prisk <linux@prisktech.co.nz>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+#include <linux/bitops.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+
+/* All clocks share the same lock as none can be changed concurrently */
+static DEFINE_SPINLOCK(_lock);
+
+struct clk_device {
+	struct clk_hw	hw;
+	void __iomem	*div_reg;
+	unsigned int	div_mask;
+	void __iomem	*en_reg;
+	int		en_bit;
+	spinlock_t	*lock;
+};
+
+/*
+ * Add new PLL_TYPE_x definitions here as required. Use the first known model
+ * to support the new type as the name.
+ * Add case statements to vtwm_pll_recalc_rate(), vtwm_pll_round_round() and
+ * vtwm_pll_set_rate() to handle the new PLL_TYPE_x
+ */
+
+#define PLL_TYPE_VT8500		0
+#define PLL_TYPE_WM8650		1
+
+struct clk_pll {
+	struct clk_hw	hw;
+	void __iomem	*reg;
+	spinlock_t	*lock;
+	int		type;
+};
+
+static void __iomem *pmc_base;
+
+#define to_clk_device(_hw) container_of(_hw, struct clk_device, hw)
+
+#define VT8500_PMC_BUSY_MASK		0x18
+
+static void vt8500_pmc_wait_busy(void)
+{
+	while (readl(pmc_base) & VT8500_PMC_BUSY_MASK)
+		cpu_relax();
+}
+
+static int vt8500_dclk_enable(struct clk_hw *hw)
+{
+	struct clk_device *cdev = to_clk_device(hw);
+	u32 en_val;
+	unsigned long flags = 0;
+
+	spin_lock_irqsave(cdev->lock, flags);
+
+	en_val = readl(cdev->en_reg);
+	en_val |= BIT(cdev->en_bit);
+	writel(en_val, cdev->en_reg);
+
+	spin_unlock_irqrestore(cdev->lock, flags);
+	return 0;
+}
+
+static void vt8500_dclk_disable(struct clk_hw *hw)
+{
+	struct clk_device *cdev = to_clk_device(hw);
+	u32 en_val;
+	unsigned long flags = 0;
+
+	spin_lock_irqsave(cdev->lock, flags);
+
+	en_val = readl(cdev->en_reg);
+	en_val &= ~BIT(cdev->en_bit);
+	writel(en_val, cdev->en_reg);
+
+	spin_unlock_irqrestore(cdev->lock, flags);
+}
+
+static int vt8500_dclk_is_enabled(struct clk_hw *hw)
+{
+	struct clk_device *cdev = to_clk_device(hw);
+	u32 en_val = (readl(cdev->en_reg) & BIT(cdev->en_bit));
+
+	return en_val ? 1 : 0;
+}
+
+static unsigned long vt8500_dclk_recalc_rate(struct clk_hw *hw,
+				unsigned long parent_rate)
+{
+	struct clk_device *cdev = to_clk_device(hw);
+	u32 div = readl(cdev->div_reg) & cdev->div_mask;
+
+	/* Special case for SDMMC devices */
+	if ((cdev->div_mask == 0x3F) && (div & BIT(5)))
+		div = 64 * (div & 0x1f);
+
+	/* div == 0 is actually the highest divisor */
+	if (div == 0)
+		div = (cdev->div_mask + 1);
+
+	return parent_rate / div;
+}
+
+static long vt8500_dclk_round_rate(struct clk_hw *hw, unsigned long rate,
+				unsigned long *prate)
+{
+	u32 divisor = *prate / rate;
+
+	return *prate / divisor;
+}
+
+static int vt8500_dclk_set_rate(struct clk_hw *hw, unsigned long rate,
+				unsigned long parent_rate)
+{
+	struct clk_device *cdev = to_clk_device(hw);
+	u32 divisor = parent_rate / rate;
+	unsigned long flags = 0;
+
+	if (divisor == cdev->div_mask + 1)
+		divisor = 0;
+
+	if (divisor > cdev->div_mask) {
+		pr_err("%s: invalid divisor for clock\n", __func__);
+		return -EINVAL;
+	}
+
+	spin_lock_irqsave(cdev->lock, flags);
+
+	vt8500_pmc_wait_busy();
+	writel(divisor, cdev->div_reg);
+	vt8500_pmc_wait_busy();
+
+	spin_lock_irqsave(cdev->lock, flags);
+
+	return 0;
+}
+
+
+static const struct clk_ops vt8500_gated_clk_ops = {
+	.enable = vt8500_dclk_enable,
+	.disable = vt8500_dclk_disable,
+	.is_enabled = vt8500_dclk_is_enabled,
+};
+
+static const struct clk_ops vt8500_divisor_clk_ops = {
+	.round_rate = vt8500_dclk_round_rate,
+	.set_rate = vt8500_dclk_set_rate,
+	.recalc_rate = vt8500_dclk_recalc_rate,
+};
+
+static const struct clk_ops vt8500_gated_divisor_clk_ops = {
+	.enable = vt8500_dclk_enable,
+	.disable = vt8500_dclk_disable,
+	.is_enabled = vt8500_dclk_is_enabled,
+	.round_rate = vt8500_dclk_round_rate,
+	.set_rate = vt8500_dclk_set_rate,
+	.recalc_rate = vt8500_dclk_recalc_rate,
+};
+
+#define CLK_INIT_GATED			BIT(0)
+#define CLK_INIT_DIVISOR		BIT(1)
+#define CLK_INIT_GATED_DIVISOR		(CLK_INIT_DIVISOR | CLK_INIT_GATED)
+
+static __init void vtwm_device_clk_init(struct device_node *node)
+{
+	u32 en_reg, div_reg;
+	struct clk *clk;
+	struct clk_device *dev_clk;
+	const char *clk_name = node->name;
+	const char *parent_name;
+	struct clk_init_data init;
+	int rc;
+	int clk_init_flags = 0;
+
+	dev_clk = kzalloc(sizeof(*dev_clk), GFP_KERNEL);
+	if (WARN_ON(!dev_clk))
+		return;
+
+	dev_clk->lock = &_lock;
+
+	rc = of_property_read_u32(node, "enable-reg", &en_reg);
+	if (!rc) {
+		dev_clk->en_reg = pmc_base + en_reg;
+		rc = of_property_read_u32(node, "enable-bit", &dev_clk->en_bit);
+		if (rc) {
+			pr_err("%s: enable-bit property required for gated clock\n",
+								__func__);
+			return;
+		}
+		clk_init_flags |= CLK_INIT_GATED;
+	}
+
+	rc = of_property_read_u32(node, "divisor-reg", &div_reg);
+	if (!rc) {
+		dev_clk->div_reg = pmc_base + div_reg;
+		/*
+		 * use 0x1f as the default mask since it covers
+		 * almost all the clocks and reduces dts properties
+		 */
+		dev_clk->div_mask = 0x1f;
+
+		of_property_read_u32(node, "divisor-mask", &dev_clk->div_mask);
+		clk_init_flags |= CLK_INIT_DIVISOR;
+	}
+
+	of_property_read_string(node, "clock-output-names", &clk_name);
+
+	switch (clk_init_flags) {
+	case CLK_INIT_GATED:
+		init.ops = &vt8500_gated_clk_ops;
+		break;
+	case CLK_INIT_DIVISOR:
+		init.ops = &vt8500_divisor_clk_ops;
+		break;
+	case CLK_INIT_GATED_DIVISOR:
+		init.ops = &vt8500_gated_divisor_clk_ops;
+		break;
+	default:
+		pr_err("%s: Invalid clock description in device tree\n",
+								__func__);
+		kfree(dev_clk);
+		return;
+	}
+
+	init.name = clk_name;
+	init.flags = 0;
+	parent_name = of_clk_get_parent_name(node, 0);
+	init.parent_names = &parent_name;
+	init.num_parents = 1;
+
+	dev_clk->hw.init = &init;
+
+	clk = clk_register(NULL, &dev_clk->hw);
+	if (WARN_ON(IS_ERR(clk))) {
+		kfree(dev_clk);
+		return;
+	}
+	rc = of_clk_add_provider(node, of_clk_src_simple_get, clk);
+	clk_register_clkdev(clk, clk_name, NULL);
+}
+
+
+/* PLL clock related functions */
+
+#define to_clk_pll(_hw) container_of(_hw, struct clk_pll, hw)
+
+/* Helper macros for PLL_VT8500 */
+#define VT8500_PLL_MUL(x)	((x & 0x1F) << 1)
+#define VT8500_PLL_DIV(x)	((x & 0x100) ? 1 : 2)
+
+#define VT8500_BITS_TO_FREQ(r, m, d)					\
+				((r / d) * m)
+
+#define VT8500_BITS_TO_VAL(m, d)					\
+				((d == 2 ? 0 : 0x100) | ((m >> 1) & 0x1F))
+
+/* Helper macros for PLL_WM8650 */
+#define WM8650_PLL_MUL(x)	(x & 0x3FF)
+#define WM8650_PLL_DIV(x)	(((x >> 10) & 7) * (1 << ((x >> 13) & 3)))
+
+#define WM8650_BITS_TO_FREQ(r, m, d1, d2)				\
+				(r * m / (d1 * (1 << d2)))
+
+#define WM8650_BITS_TO_VAL(m, d1, d2)					\
+				((d2 << 13) | (d1 << 10) | (m & 0x3FF))
+
+
+static void vt8500_find_pll_bits(unsigned long rate, unsigned long parent_rate,
+				u32 *multiplier, u32 *prediv)
+{
+	unsigned long tclk;
+
+	/* sanity check */
+	if ((rate < parent_rate * 4) || (rate > parent_rate * 62)) {
+		pr_err("%s: requested rate out of range\n", __func__);
+		*multiplier = 0;
+		*prediv = 1;
+		return;
+	}
+	if (rate <= parent_rate * 31)
+		/* use the prediv to double the resolution */
+		*prediv = 2;
+	else
+		*prediv = 1;
+
+	*multiplier = rate / (parent_rate / *prediv);
+	tclk = (parent_rate / *prediv) * *multiplier;
+
+	if (tclk != rate)
+		pr_warn("%s: requested rate %lu, found rate %lu\n", __func__,
+								rate, tclk);
+}
+
+static void wm8650_find_pll_bits(unsigned long rate, unsigned long parent_rate,
+				u32 *multiplier, u32 *divisor1, u32 *divisor2)
+{
+	u32 mul, div1, div2;
+	u32 best_mul, best_div1, best_div2;
+	unsigned long tclk, rate_err, best_err;
+
+	best_err = (unsigned long)-1;
+
+	/* Find the closest match (lower or equal to requested) */
+	for (div1 = 5; div1 >= 3; div1--)
+		for (div2 = 3; div2 >= 0; div2--)
+			for (mul = 3; mul <= 1023; mul++) {
+				tclk = parent_rate * mul / (div1 * (1 << div2));
+				if (tclk > rate)
+					continue;
+				/* error will always be +ve */
+				rate_err = rate - tclk;
+				if (rate_err == 0) {
+					*multiplier = mul;
+					*divisor1 = div1;
+					*divisor2 = div2;
+					return;
+				}
+
+				if (rate_err < best_err) {
+					best_err = rate_err;
+					best_mul = mul;
+					best_div1 = div1;
+					best_div2 = div2;
+				}
+			}
+
+	/* if we got here, it wasn't an exact match */
+	pr_warn("%s: requested rate %lu, found rate %lu\n", __func__, rate,
+							rate - best_err);
+	*multiplier = mul;
+	*divisor1 = div1;
+	*divisor2 = div2;
+}
+
+static int vtwm_pll_set_rate(struct clk_hw *hw, unsigned long rate,
+				unsigned long parent_rate)
+{
+	struct clk_pll *pll = to_clk_pll(hw);
+	u32 mul, div1, div2;
+	u32 pll_val;
+	unsigned long flags = 0;
+
+	/* sanity check */
+
+	switch (pll->type) {
+	case PLL_TYPE_VT8500:
+		vt8500_find_pll_bits(rate, parent_rate, &mul, &div1);
+		pll_val = VT8500_BITS_TO_VAL(mul, div1);
+		break;
+	case PLL_TYPE_WM8650:
+		wm8650_find_pll_bits(rate, parent_rate, &mul, &div1, &div2);
+		pll_val = WM8650_BITS_TO_VAL(mul, div1, div2);
+		break;
+	default:
+		pr_err("%s: invalid pll type\n", __func__);
+		return 0;
+	}
+
+	spin_lock_irqsave(pll->lock, flags);
+
+	vt8500_pmc_wait_busy();
+	writel(pll_val, pll->reg);
+	vt8500_pmc_wait_busy();
+
+	spin_unlock_irqrestore(pll->lock, flags);
+
+	return 0;
+}
+
+static long vtwm_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+				unsigned long *prate)
+{
+	struct clk_pll *pll = to_clk_pll(hw);
+	u32 mul, div1, div2;
+	long round_rate;
+
+	switch (pll->type) {
+	case PLL_TYPE_VT8500:
+		vt8500_find_pll_bits(rate, *prate, &mul, &div1);
+		round_rate = VT8500_BITS_TO_FREQ(*prate, mul, div1);
+		break;
+	case PLL_TYPE_WM8650:
+		wm8650_find_pll_bits(rate, *prate, &mul, &div1, &div2);
+		round_rate = WM8650_BITS_TO_FREQ(*prate, mul, div1, div2);
+		break;
+	default:
+		round_rate = 0;
+	}
+
+	return round_rate;
+}
+
+static unsigned long vtwm_pll_recalc_rate(struct clk_hw *hw,
+				unsigned long parent_rate)
+{
+	struct clk_pll *pll = to_clk_pll(hw);
+	u32 pll_val = readl(pll->reg);
+	unsigned long pll_freq;
+
+	switch (pll->type) {
+	case PLL_TYPE_VT8500:
+		pll_freq = parent_rate * VT8500_PLL_MUL(pll_val);
+		pll_freq /= VT8500_PLL_DIV(pll_val);
+		break;
+	case PLL_TYPE_WM8650:
+		pll_freq = parent_rate * WM8650_PLL_MUL(pll_val);
+		pll_freq /= WM8650_PLL_DIV(pll_val);
+		break;
+	default:
+		pll_freq = 0;
+	}
+
+	return pll_freq;
+}
+
+const struct clk_ops vtwm_pll_ops = {
+	.round_rate = vtwm_pll_round_rate,
+	.set_rate = vtwm_pll_set_rate,
+	.recalc_rate = vtwm_pll_recalc_rate,
+};
+
+static __init void vtwm_pll_clk_init(struct device_node *node, int pll_type)
+{
+	u32 reg;
+	struct clk *clk;
+	struct clk_pll *pll_clk;
+	const char *clk_name = node->name;
+	const char *parent_name;
+	struct clk_init_data init;
+	int rc;
+
+	rc = of_property_read_u32(node, "reg", &reg);
+	if (WARN_ON(rc))
+		return;
+
+	pll_clk = kzalloc(sizeof(*pll_clk), GFP_KERNEL);
+	if (WARN_ON(!pll_clk))
+		return;
+
+	pll_clk->reg = pmc_base + reg;
+	pll_clk->lock = &_lock;
+	pll_clk->type = pll_type;
+
+	of_property_read_string(node, "clock-output-names", &clk_name);
+
+	init.name = clk_name;
+	init.ops = &vtwm_pll_ops;
+	init.flags = 0;
+	parent_name = of_clk_get_parent_name(node, 0);
+	init.parent_names = &parent_name;
+	init.num_parents = 1;
+
+	pll_clk->hw.init = &init;
+
+	clk = clk_register(NULL, &pll_clk->hw);
+	if (WARN_ON(IS_ERR(clk))) {
+		kfree(pll_clk);
+		return;
+	}
+	rc = of_clk_add_provider(node, of_clk_src_simple_get, clk);
+	clk_register_clkdev(clk, clk_name, NULL);
+}
+
+
+/* Wrappers for initialization functions */
+
+static void __init vt8500_pll_init(struct device_node *node)
+{
+	vtwm_pll_clk_init(node, PLL_TYPE_VT8500);
+}
+
+static void __init wm8650_pll_init(struct device_node *node)
+{
+	vtwm_pll_clk_init(node, PLL_TYPE_WM8650);
+}
+
+static const __initconst struct of_device_id clk_match[] = {
+	{ .compatible = "fixed-clock", .data = of_fixed_clk_setup, },
+	{ .compatible = "via,vt8500-pll-clock", .data = vt8500_pll_init, },
+	{ .compatible = "wm,wm8650-pll-clock", .data = wm8650_pll_init, },
+	{ .compatible = "via,vt8500-device-clock",
+					.data = vtwm_device_clk_init, },
+	{ /* sentinel */ }
+};
+
+void __init vtwm_clk_init(void __iomem *base)
+{
+	if (!base)
+		return;
+
+	pmc_base = base;
+
+	of_clk_init(clk_match);
+}
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index efdfd00..56e4495e 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -558,25 +558,6 @@ int clk_enable(struct clk *clk)
 EXPORT_SYMBOL_GPL(clk_enable);
 
 /**
- * clk_get_rate - return the rate of clk
- * @clk: the clk whose rate is being returned
- *
- * Simply returns the cached rate of the clk.  Does not query the hardware.  If
- * clk is NULL then returns 0.
- */
-unsigned long clk_get_rate(struct clk *clk)
-{
-	unsigned long rate;
-
-	mutex_lock(&prepare_lock);
-	rate = __clk_get_rate(clk);
-	mutex_unlock(&prepare_lock);
-
-	return rate;
-}
-EXPORT_SYMBOL_GPL(clk_get_rate);
-
-/**
  * __clk_round_rate - round the given rate for a clk
  * @clk: round the rate of this clock
  *
@@ -702,6 +683,30 @@ static void __clk_recalc_rates(struct clk *clk, unsigned long msg)
 }
 
 /**
+ * clk_get_rate - return the rate of clk
+ * @clk: the clk whose rate is being returned
+ *
+ * Simply returns the cached rate of the clk, unless CLK_GET_RATE_NOCACHE flag
+ * is set, which means a recalc_rate will be issued.
+ * If clk is NULL then returns 0.
+ */
+unsigned long clk_get_rate(struct clk *clk)
+{
+	unsigned long rate;
+
+	mutex_lock(&prepare_lock);
+
+	if (clk && (clk->flags & CLK_GET_RATE_NOCACHE))
+		__clk_recalc_rates(clk, 0);
+
+	rate = __clk_get_rate(clk);
+	mutex_unlock(&prepare_lock);
+
+	return rate;
+}
+EXPORT_SYMBOL_GPL(clk_get_rate);
+
+/**
  * __clk_speculate_rates
  * @clk: first clk in the subtree
  * @parent_rate: the "future" rate of clk's parent
@@ -1582,6 +1587,20 @@ struct clk *of_clk_src_simple_get(struct of_phandle_args *clkspec,
 }
 EXPORT_SYMBOL_GPL(of_clk_src_simple_get);
 
+struct clk *of_clk_src_onecell_get(struct of_phandle_args *clkspec, void *data)
+{
+	struct clk_onecell_data *clk_data = data;
+	unsigned int idx = clkspec->args[0];
+
+	if (idx >= clk_data->clk_num) {
+		pr_err("%s: invalid clock index %d\n", __func__, idx);
+		return ERR_PTR(-EINVAL);
+	}
+
+	return clk_data->clks[idx];
+}
+EXPORT_SYMBOL_GPL(of_clk_src_onecell_get);
+
 /**
  * of_clk_add_provider() - Register a clock provider for a node
  * @np: Device node pointer associated with clock provider
diff --git a/drivers/clk/mmp/Makefile b/drivers/clk/mmp/Makefile
new file mode 100644
index 0000000..392d780
--- /dev/null
+++ b/drivers/clk/mmp/Makefile
@@ -0,0 +1,9 @@
+#
+# Makefile for mmp specific clk
+#
+
+obj-y += clk-apbc.o clk-apmu.o clk-frac.o
+
+obj-$(CONFIG_CPU_PXA168) += clk-pxa168.o
+obj-$(CONFIG_CPU_PXA910) += clk-pxa910.o
+obj-$(CONFIG_CPU_MMP2) += clk-mmp2.o
diff --git a/drivers/clk/mmp/clk-apbc.c b/drivers/clk/mmp/clk-apbc.c
new file mode 100644
index 0000000..d14120e
--- /dev/null
+++ b/drivers/clk/mmp/clk-apbc.c
@@ -0,0 +1,152 @@
+/*
+ * mmp APB clock operation source file
+ *
+ * Copyright (C) 2012 Marvell
+ * Chao Xie <xiechao.mail@gmail.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+
+#include "clk.h"
+
+/* 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 */
+#define APBC_POWER	(1 << 7)  /* Reset Generation */
+
+#define to_clk_apbc(hw) container_of(hw, struct clk_apbc, hw)
+struct clk_apbc {
+	struct clk_hw		hw;
+	void __iomem		*base;
+	unsigned int		delay;
+	unsigned int		flags;
+	spinlock_t		*lock;
+};
+
+static int clk_apbc_prepare(struct clk_hw *hw)
+{
+	struct clk_apbc *apbc = to_clk_apbc(hw);
+	unsigned int data;
+	unsigned long flags = 0;
+
+	/*
+	 * It may share same register as MUX clock,
+	 * and it will impact FNCLK enable. Spinlock is needed
+	 */
+	if (apbc->lock)
+		spin_lock_irqsave(apbc->lock, flags);
+
+	data = readl_relaxed(apbc->base);
+	if (apbc->flags & APBC_POWER_CTRL)
+		data |= APBC_POWER;
+	data |= APBC_FNCLK;
+	writel_relaxed(data, apbc->base);
+
+	if (apbc->lock)
+		spin_unlock_irqrestore(apbc->lock, flags);
+
+	udelay(apbc->delay);
+
+	if (apbc->lock)
+		spin_lock_irqsave(apbc->lock, flags);
+
+	data = readl_relaxed(apbc->base);
+	data |= APBC_APBCLK;
+	writel_relaxed(data, apbc->base);
+
+	if (apbc->lock)
+		spin_unlock_irqrestore(apbc->lock, flags);
+
+	udelay(apbc->delay);
+
+	if (!(apbc->flags & APBC_NO_BUS_CTRL)) {
+		if (apbc->lock)
+			spin_lock_irqsave(apbc->lock, flags);
+
+		data = readl_relaxed(apbc->base);
+		data &= ~APBC_RST;
+		writel_relaxed(data, apbc->base);
+
+		if (apbc->lock)
+			spin_unlock_irqrestore(apbc->lock, flags);
+	}
+
+	return 0;
+}
+
+static void clk_apbc_unprepare(struct clk_hw *hw)
+{
+	struct clk_apbc *apbc = to_clk_apbc(hw);
+	unsigned long data;
+	unsigned long flags = 0;
+
+	if (apbc->lock)
+		spin_lock_irqsave(apbc->lock, flags);
+
+	data = readl_relaxed(apbc->base);
+	if (apbc->flags & APBC_POWER_CTRL)
+		data &= ~APBC_POWER;
+	data &= ~APBC_FNCLK;
+	writel_relaxed(data, apbc->base);
+
+	if (apbc->lock)
+		spin_unlock_irqrestore(apbc->lock, flags);
+
+	udelay(10);
+
+	if (apbc->lock)
+		spin_lock_irqsave(apbc->lock, flags);
+
+	data = readl_relaxed(apbc->base);
+	data &= ~APBC_APBCLK;
+	writel_relaxed(data, apbc->base);
+
+	if (apbc->lock)
+		spin_unlock_irqrestore(apbc->lock, flags);
+}
+
+struct clk_ops clk_apbc_ops = {
+	.prepare = clk_apbc_prepare,
+	.unprepare = clk_apbc_unprepare,
+};
+
+struct clk *mmp_clk_register_apbc(const char *name, const char *parent_name,
+		void __iomem *base, unsigned int delay,
+		unsigned int apbc_flags, spinlock_t *lock)
+{
+	struct clk_apbc *apbc;
+	struct clk *clk;
+	struct clk_init_data init;
+
+	apbc = kzalloc(sizeof(*apbc), GFP_KERNEL);
+	if (!apbc)
+		return NULL;
+
+	init.name = name;
+	init.ops = &clk_apbc_ops;
+	init.flags = CLK_SET_RATE_PARENT;
+	init.parent_names = (parent_name ? &parent_name : NULL);
+	init.num_parents = (parent_name ? 1 : 0);
+
+	apbc->base = base;
+	apbc->delay = delay;
+	apbc->flags = apbc_flags;
+	apbc->lock = lock;
+	apbc->hw.init = &init;
+
+	clk = clk_register(NULL, &apbc->hw);
+	if (IS_ERR(clk))
+		kfree(apbc);
+
+	return clk;
+}
diff --git a/drivers/clk/mmp/clk-apmu.c b/drivers/clk/mmp/clk-apmu.c
new file mode 100644
index 0000000..abe182b
--- /dev/null
+++ b/drivers/clk/mmp/clk-apmu.c
@@ -0,0 +1,97 @@
+/*
+ * mmp AXI peripharal clock operation source file
+ *
+ * Copyright (C) 2012 Marvell
+ * Chao Xie <xiechao.mail@gmail.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+
+#include "clk.h"
+
+#define to_clk_apmu(clk) (container_of(clk, struct clk_apmu, clk))
+struct clk_apmu {
+	struct clk_hw   hw;
+	void __iomem    *base;
+	u32		rst_mask;
+	u32		enable_mask;
+	spinlock_t	*lock;
+};
+
+static int clk_apmu_enable(struct clk_hw *hw)
+{
+	struct clk_apmu *apmu = to_clk_apmu(hw);
+	unsigned long data;
+	unsigned long flags = 0;
+
+	if (apmu->lock)
+		spin_lock_irqsave(apmu->lock, flags);
+
+	data = readl_relaxed(apmu->base) | apmu->enable_mask;
+	writel_relaxed(data, apmu->base);
+
+	if (apmu->lock)
+		spin_unlock_irqrestore(apmu->lock, flags);
+
+	return 0;
+}
+
+static void clk_apmu_disable(struct clk_hw *hw)
+{
+	struct clk_apmu *apmu = to_clk_apmu(hw);
+	unsigned long data;
+	unsigned long flags = 0;
+
+	if (apmu->lock)
+		spin_lock_irqsave(apmu->lock, flags);
+
+	data = readl_relaxed(apmu->base) & ~apmu->enable_mask;
+	writel_relaxed(data, apmu->base);
+
+	if (apmu->lock)
+		spin_unlock_irqrestore(apmu->lock, flags);
+}
+
+struct clk_ops clk_apmu_ops = {
+	.enable = clk_apmu_enable,
+	.disable = clk_apmu_disable,
+};
+
+struct clk *mmp_clk_register_apmu(const char *name, const char *parent_name,
+		void __iomem *base, u32 enable_mask, spinlock_t *lock)
+{
+	struct clk_apmu *apmu;
+	struct clk *clk;
+	struct clk_init_data init;
+
+	apmu = kzalloc(sizeof(*apmu), GFP_KERNEL);
+	if (!apmu)
+		return NULL;
+
+	init.name = name;
+	init.ops = &clk_apmu_ops;
+	init.flags = CLK_SET_RATE_PARENT;
+	init.parent_names = (parent_name ? &parent_name : NULL);
+	init.num_parents = (parent_name ? 1 : 0);
+
+	apmu->base = base;
+	apmu->enable_mask = enable_mask;
+	apmu->lock = lock;
+	apmu->hw.init = &init;
+
+	clk = clk_register(NULL, &apmu->hw);
+
+	if (IS_ERR(clk))
+		kfree(apmu);
+
+	return clk;
+}
diff --git a/drivers/clk/mmp/clk-frac.c b/drivers/clk/mmp/clk-frac.c
new file mode 100644
index 0000000..80c1dd1
--- /dev/null
+++ b/drivers/clk/mmp/clk-frac.c
@@ -0,0 +1,153 @@
+/*
+ * mmp factor clock operation source file
+ *
+ * Copyright (C) 2012 Marvell
+ * Chao Xie <xiechao.mail@gmail.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/err.h>
+
+#include "clk.h"
+/*
+ * It is M/N clock
+ *
+ * Fout from synthesizer can be given from two equations:
+ * numerator/denominator = Fin / (Fout * factor)
+ */
+
+#define to_clk_factor(hw) container_of(hw, struct clk_factor, hw)
+struct clk_factor {
+	struct clk_hw		hw;
+	void __iomem		*base;
+	struct clk_factor_masks	*masks;
+	struct clk_factor_tbl	*ftbl;
+	unsigned int		ftbl_cnt;
+};
+
+static long clk_factor_round_rate(struct clk_hw *hw, unsigned long drate,
+		unsigned long *prate)
+{
+	struct clk_factor *factor = to_clk_factor(hw);
+	unsigned long rate = 0, prev_rate;
+	int i;
+
+	for (i = 0; i < factor->ftbl_cnt; i++) {
+		prev_rate = rate;
+		rate = (((*prate / 10000) * factor->ftbl[i].num) /
+			(factor->ftbl[i].den * factor->masks->factor)) * 10000;
+		if (rate > drate)
+			break;
+	}
+	if (i == 0)
+		return rate;
+	else
+		return prev_rate;
+}
+
+static unsigned long clk_factor_recalc_rate(struct clk_hw *hw,
+		unsigned long parent_rate)
+{
+	struct clk_factor *factor = to_clk_factor(hw);
+	struct clk_factor_masks *masks = factor->masks;
+	unsigned int val, num, den;
+
+	val = readl_relaxed(factor->base);
+
+	/* calculate numerator */
+	num = (val >> masks->num_shift) & masks->num_mask;
+
+	/* calculate denominator */
+	den = (val >> masks->den_shift) & masks->num_mask;
+
+	if (!den)
+		return 0;
+
+	return (((parent_rate / 10000)  * den) /
+			(num * factor->masks->factor)) * 10000;
+}
+
+/* Configures new clock rate*/
+static int clk_factor_set_rate(struct clk_hw *hw, unsigned long drate,
+				unsigned long prate)
+{
+	struct clk_factor *factor = to_clk_factor(hw);
+	struct clk_factor_masks *masks = factor->masks;
+	int i;
+	unsigned long val;
+	unsigned long prev_rate, rate = 0;
+
+	for (i = 0; i < factor->ftbl_cnt; i++) {
+		prev_rate = rate;
+		rate = (((prate / 10000) * factor->ftbl[i].num) /
+			(factor->ftbl[i].den * factor->masks->factor)) * 10000;
+		if (rate > drate)
+			break;
+	}
+	if (i > 0)
+		i--;
+
+	val = readl_relaxed(factor->base);
+
+	val &= ~(masks->num_mask << masks->num_shift);
+	val |= (factor->ftbl[i].num & masks->num_mask) << masks->num_shift;
+
+	val &= ~(masks->den_mask << masks->den_shift);
+	val |= (factor->ftbl[i].den & masks->den_mask) << masks->den_shift;
+
+	writel_relaxed(val, factor->base);
+
+	return 0;
+}
+
+static struct clk_ops clk_factor_ops = {
+	.recalc_rate = clk_factor_recalc_rate,
+	.round_rate = clk_factor_round_rate,
+	.set_rate = clk_factor_set_rate,
+};
+
+struct clk *mmp_clk_register_factor(const char *name, const char *parent_name,
+		unsigned long flags, void __iomem *base,
+		struct clk_factor_masks *masks, struct clk_factor_tbl *ftbl,
+		unsigned int ftbl_cnt)
+{
+	struct clk_factor *factor;
+	struct clk_init_data init;
+	struct clk *clk;
+
+	if (!masks) {
+		pr_err("%s: must pass a clk_factor_mask\n", __func__);
+		return ERR_PTR(-EINVAL);
+	}
+
+	factor = kzalloc(sizeof(*factor), GFP_KERNEL);
+	if (!factor) {
+		pr_err("%s: could not allocate factor  clk\n", __func__);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	/* struct clk_aux assignments */
+	factor->base = base;
+	factor->masks = masks;
+	factor->ftbl = ftbl;
+	factor->ftbl_cnt = ftbl_cnt;
+	factor->hw.init = &init;
+
+	init.name = name;
+	init.ops = &clk_factor_ops;
+	init.flags = flags;
+	init.parent_names = &parent_name;
+	init.num_parents = 1;
+
+	clk = clk_register(NULL, &factor->hw);
+	if (IS_ERR_OR_NULL(clk))
+		kfree(factor);
+
+	return clk;
+}
diff --git a/drivers/clk/mmp/clk-mmp2.c b/drivers/clk/mmp/clk-mmp2.c
new file mode 100644
index 0000000..ade4358
--- /dev/null
+++ b/drivers/clk/mmp/clk-mmp2.c
@@ -0,0 +1,449 @@
+/*
+ * mmp2 clock framework source file
+ *
+ * Copyright (C) 2012 Marvell
+ * Chao Xie <xiechao.mail@gmail.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+
+#include <mach/addr-map.h>
+
+#include "clk.h"
+
+#define APBC_RTC	0x0
+#define APBC_TWSI0	0x4
+#define APBC_TWSI1	0x8
+#define APBC_TWSI2	0xc
+#define APBC_TWSI3	0x10
+#define APBC_TWSI4	0x7c
+#define APBC_TWSI5	0x80
+#define APBC_KPC	0x18
+#define APBC_UART0	0x2c
+#define APBC_UART1	0x30
+#define APBC_UART2	0x34
+#define APBC_UART3	0x88
+#define APBC_GPIO	0x38
+#define APBC_PWM0	0x3c
+#define APBC_PWM1	0x40
+#define APBC_PWM2	0x44
+#define APBC_PWM3	0x48
+#define APBC_SSP0	0x50
+#define APBC_SSP1	0x54
+#define APBC_SSP2	0x58
+#define APBC_SSP3	0x5c
+#define APMU_SDH0	0x54
+#define APMU_SDH1	0x58
+#define APMU_SDH2	0xe8
+#define APMU_SDH3	0xec
+#define APMU_USB	0x5c
+#define APMU_DISP0	0x4c
+#define APMU_DISP1	0x110
+#define APMU_CCIC0	0x50
+#define APMU_CCIC1	0xf4
+#define MPMU_UART_PLL	0x14
+
+static DEFINE_SPINLOCK(clk_lock);
+
+static struct clk_factor_masks uart_factor_masks = {
+	.factor = 2,
+	.num_mask = 0x1fff,
+	.den_mask = 0x1fff,
+	.num_shift = 16,
+	.den_shift = 0,
+};
+
+static struct clk_factor_tbl uart_factor_tbl[] = {
+	{.num = 14634, .den = 2165},	/*14.745MHZ */
+	{.num = 3521, .den = 689},	/*19.23MHZ */
+	{.num = 9679, .den = 5728},	/*58.9824MHZ */
+	{.num = 15850, .den = 9451},	/*59.429MHZ */
+};
+
+static const char *uart_parent[] = {"uart_pll", "vctcxo"};
+static const char *ssp_parent[] = {"vctcxo_4", "vctcxo_2", "vctcxo", "pll1_16"};
+static const char *sdh_parent[] = {"pll1_4", "pll2", "usb_pll", "pll1"};
+static const char *disp_parent[] = {"pll1", "pll1_16", "pll2", "vctcxo"};
+static const char *ccic_parent[] = {"pll1_2", "pll1_16", "vctcxo"};
+
+void __init mmp2_clk_init(void)
+{
+	struct clk *clk;
+	struct clk *vctcxo;
+	void __iomem *mpmu_base;
+	void __iomem *apmu_base;
+	void __iomem *apbc_base;
+
+	mpmu_base = ioremap(APB_PHYS_BASE + 0x50000, SZ_4K);
+	if (mpmu_base == NULL) {
+		pr_err("error to ioremap MPMU base\n");
+		return;
+	}
+
+	apmu_base = ioremap(AXI_PHYS_BASE + 0x82800, SZ_4K);
+	if (apmu_base == NULL) {
+		pr_err("error to ioremap APMU base\n");
+		return;
+	}
+
+	apbc_base = ioremap(APB_PHYS_BASE + 0x15000, SZ_4K);
+	if (apbc_base == NULL) {
+		pr_err("error to ioremap APBC base\n");
+		return;
+	}
+
+	clk = clk_register_fixed_rate(NULL, "clk32", NULL, CLK_IS_ROOT, 3200);
+	clk_register_clkdev(clk, "clk32", NULL);
+
+	vctcxo = clk_register_fixed_rate(NULL, "vctcxo", NULL, CLK_IS_ROOT,
+				26000000);
+	clk_register_clkdev(vctcxo, "vctcxo", NULL);
+
+	clk = clk_register_fixed_rate(NULL, "pll1", NULL, CLK_IS_ROOT,
+				800000000);
+	clk_register_clkdev(clk, "pll1", NULL);
+
+	clk = clk_register_fixed_rate(NULL, "usb_pll", NULL, CLK_IS_ROOT,
+				480000000);
+	clk_register_clkdev(clk, "usb_pll", NULL);
+
+	clk = clk_register_fixed_rate(NULL, "pll2", NULL, CLK_IS_ROOT,
+				960000000);
+	clk_register_clkdev(clk, "pll2", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "pll1_2", "pll1",
+				CLK_SET_RATE_PARENT, 1, 2);
+	clk_register_clkdev(clk, "pll1_2", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "pll1_4", "pll1_2",
+				CLK_SET_RATE_PARENT, 1, 2);
+	clk_register_clkdev(clk, "pll1_4", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "pll1_8", "pll1_4",
+				CLK_SET_RATE_PARENT, 1, 2);
+	clk_register_clkdev(clk, "pll1_8", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "pll1_16", "pll1_8",
+				CLK_SET_RATE_PARENT, 1, 2);
+	clk_register_clkdev(clk, "pll1_16", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "pll1_20", "pll1_4",
+				CLK_SET_RATE_PARENT, 1, 5);
+	clk_register_clkdev(clk, "pll1_20", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "pll1_3", "pll1",
+				CLK_SET_RATE_PARENT, 1, 3);
+	clk_register_clkdev(clk, "pll1_3", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "pll1_6", "pll1_3",
+				CLK_SET_RATE_PARENT, 1, 2);
+	clk_register_clkdev(clk, "pll1_6", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "pll1_12", "pll1_6",
+				CLK_SET_RATE_PARENT, 1, 2);
+	clk_register_clkdev(clk, "pll1_12", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "pll2_2", "pll2",
+				CLK_SET_RATE_PARENT, 1, 2);
+	clk_register_clkdev(clk, "pll2_2", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "pll2_4", "pll2_2",
+				CLK_SET_RATE_PARENT, 1, 2);
+	clk_register_clkdev(clk, "pll2_4", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "pll2_8", "pll2_4",
+				CLK_SET_RATE_PARENT, 1, 2);
+	clk_register_clkdev(clk, "pll2_8", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "pll2_16", "pll2_8",
+				CLK_SET_RATE_PARENT, 1, 2);
+	clk_register_clkdev(clk, "pll2_16", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "pll2_3", "pll2",
+				CLK_SET_RATE_PARENT, 1, 3);
+	clk_register_clkdev(clk, "pll2_3", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "pll2_6", "pll2_3",
+				CLK_SET_RATE_PARENT, 1, 2);
+	clk_register_clkdev(clk, "pll2_6", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "pll2_12", "pll2_6",
+				CLK_SET_RATE_PARENT, 1, 2);
+	clk_register_clkdev(clk, "pll2_12", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "vctcxo_2", "vctcxo",
+				CLK_SET_RATE_PARENT, 1, 2);
+	clk_register_clkdev(clk, "vctcxo_2", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "vctcxo_4", "vctcxo_2",
+				CLK_SET_RATE_PARENT, 1, 2);
+	clk_register_clkdev(clk, "vctcxo_4", NULL);
+
+	clk = mmp_clk_register_factor("uart_pll", "pll1_4", 0,
+				mpmu_base + MPMU_UART_PLL,
+				&uart_factor_masks, uart_factor_tbl,
+				ARRAY_SIZE(uart_factor_tbl));
+	clk_set_rate(clk, 14745600);
+	clk_register_clkdev(clk, "uart_pll", NULL);
+
+	clk = mmp_clk_register_apbc("twsi0", "vctcxo",
+				apbc_base + APBC_TWSI0, 10, 0, &clk_lock);
+	clk_register_clkdev(clk, NULL, "pxa2xx-i2c.0");
+
+	clk = mmp_clk_register_apbc("twsi1", "vctcxo",
+				apbc_base + APBC_TWSI1, 10, 0, &clk_lock);
+	clk_register_clkdev(clk, NULL, "pxa2xx-i2c.1");
+
+	clk = mmp_clk_register_apbc("twsi2", "vctcxo",
+				apbc_base + APBC_TWSI2, 10, 0, &clk_lock);
+	clk_register_clkdev(clk, NULL, "pxa2xx-i2c.2");
+
+	clk = mmp_clk_register_apbc("twsi3", "vctcxo",
+				apbc_base + APBC_TWSI3, 10, 0, &clk_lock);
+	clk_register_clkdev(clk, NULL, "pxa2xx-i2c.3");
+
+	clk = mmp_clk_register_apbc("twsi4", "vctcxo",
+				apbc_base + APBC_TWSI4, 10, 0, &clk_lock);
+	clk_register_clkdev(clk, NULL, "pxa2xx-i2c.4");
+
+	clk = mmp_clk_register_apbc("twsi5", "vctcxo",
+				apbc_base + APBC_TWSI5, 10, 0, &clk_lock);
+	clk_register_clkdev(clk, NULL, "pxa2xx-i2c.5");
+
+	clk = mmp_clk_register_apbc("gpio", "vctcxo",
+				apbc_base + APBC_GPIO, 10, 0, &clk_lock);
+	clk_register_clkdev(clk, NULL, "pxa-gpio");
+
+	clk = mmp_clk_register_apbc("kpc", "clk32",
+				apbc_base + APBC_KPC, 10, 0, &clk_lock);
+	clk_register_clkdev(clk, NULL, "pxa27x-keypad");
+
+	clk = mmp_clk_register_apbc("rtc", "clk32",
+				apbc_base + APBC_RTC, 10, 0, &clk_lock);
+	clk_register_clkdev(clk, NULL, "mmp-rtc");
+
+	clk = mmp_clk_register_apbc("pwm0", "vctcxo",
+				apbc_base + APBC_PWM0, 10, 0, &clk_lock);
+	clk_register_clkdev(clk, NULL, "mmp2-pwm.0");
+
+	clk = mmp_clk_register_apbc("pwm1", "vctcxo",
+				apbc_base + APBC_PWM1, 10, 0, &clk_lock);
+	clk_register_clkdev(clk, NULL, "mmp2-pwm.1");
+
+	clk = mmp_clk_register_apbc("pwm2", "vctcxo",
+				apbc_base + APBC_PWM2, 10, 0, &clk_lock);
+	clk_register_clkdev(clk, NULL, "mmp2-pwm.2");
+
+	clk = mmp_clk_register_apbc("pwm3", "vctcxo",
+				apbc_base + APBC_PWM3, 10, 0, &clk_lock);
+	clk_register_clkdev(clk, NULL, "mmp2-pwm.3");
+
+	clk = clk_register_mux(NULL, "uart0_mux", uart_parent,
+				ARRAY_SIZE(uart_parent), CLK_SET_RATE_PARENT,
+				apbc_base + APBC_UART0, 4, 3, 0, &clk_lock);
+	clk_set_parent(clk, vctcxo);
+	clk_register_clkdev(clk, "uart_mux.0", NULL);
+
+	clk = mmp_clk_register_apbc("uart0", "uart0_mux",
+				apbc_base + APBC_UART0, 10, 0, &clk_lock);
+	clk_register_clkdev(clk, NULL, "pxa2xx-uart.0");
+
+	clk = clk_register_mux(NULL, "uart1_mux", uart_parent,
+				ARRAY_SIZE(uart_parent), CLK_SET_RATE_PARENT,
+				apbc_base + APBC_UART1, 4, 3, 0, &clk_lock);
+	clk_set_parent(clk, vctcxo);
+	clk_register_clkdev(clk, "uart_mux.1", NULL);
+
+	clk = mmp_clk_register_apbc("uart1", "uart1_mux",
+				apbc_base + APBC_UART1, 10, 0, &clk_lock);
+	clk_register_clkdev(clk, NULL, "pxa2xx-uart.1");
+
+	clk = clk_register_mux(NULL, "uart2_mux", uart_parent,
+				ARRAY_SIZE(uart_parent), CLK_SET_RATE_PARENT,
+				apbc_base + APBC_UART2, 4, 3, 0, &clk_lock);
+	clk_set_parent(clk, vctcxo);
+	clk_register_clkdev(clk, "uart_mux.2", NULL);
+
+	clk = mmp_clk_register_apbc("uart2", "uart2_mux",
+				apbc_base + APBC_UART2, 10, 0, &clk_lock);
+	clk_register_clkdev(clk, NULL, "pxa2xx-uart.2");
+
+	clk = clk_register_mux(NULL, "uart3_mux", uart_parent,
+				ARRAY_SIZE(uart_parent), CLK_SET_RATE_PARENT,
+				apbc_base + APBC_UART3, 4, 3, 0, &clk_lock);
+	clk_set_parent(clk, vctcxo);
+	clk_register_clkdev(clk, "uart_mux.3", NULL);
+
+	clk = mmp_clk_register_apbc("uart3", "uart3_mux",
+				apbc_base + APBC_UART3, 10, 0, &clk_lock);
+	clk_register_clkdev(clk, NULL, "pxa2xx-uart.3");
+
+	clk = clk_register_mux(NULL, "ssp0_mux", ssp_parent,
+				ARRAY_SIZE(ssp_parent), CLK_SET_RATE_PARENT,
+				apbc_base + APBC_SSP0, 4, 3, 0, &clk_lock);
+	clk_register_clkdev(clk, "uart_mux.0", NULL);
+
+	clk = mmp_clk_register_apbc("ssp0", "ssp0_mux",
+				apbc_base + APBC_SSP0, 10, 0, &clk_lock);
+	clk_register_clkdev(clk, NULL, "mmp-ssp.0");
+
+	clk = clk_register_mux(NULL, "ssp1_mux", ssp_parent,
+				ARRAY_SIZE(ssp_parent), CLK_SET_RATE_PARENT,
+				apbc_base + APBC_SSP1, 4, 3, 0, &clk_lock);
+	clk_register_clkdev(clk, "ssp_mux.1", NULL);
+
+	clk = mmp_clk_register_apbc("ssp1", "ssp1_mux",
+				apbc_base + APBC_SSP1, 10, 0, &clk_lock);
+	clk_register_clkdev(clk, NULL, "mmp-ssp.1");
+
+	clk = clk_register_mux(NULL, "ssp2_mux", ssp_parent,
+				ARRAY_SIZE(ssp_parent), CLK_SET_RATE_PARENT,
+				apbc_base + APBC_SSP2, 4, 3, 0, &clk_lock);
+	clk_register_clkdev(clk, "ssp_mux.2", NULL);
+
+	clk = mmp_clk_register_apbc("ssp2", "ssp2_mux",
+				apbc_base + APBC_SSP2, 10, 0, &clk_lock);
+	clk_register_clkdev(clk, NULL, "mmp-ssp.2");
+
+	clk = clk_register_mux(NULL, "ssp3_mux", ssp_parent,
+				ARRAY_SIZE(ssp_parent), CLK_SET_RATE_PARENT,
+				apbc_base + APBC_SSP3, 4, 3, 0, &clk_lock);
+	clk_register_clkdev(clk, "ssp_mux.3", NULL);
+
+	clk = mmp_clk_register_apbc("ssp3", "ssp3_mux",
+				apbc_base + APBC_SSP3, 10, 0, &clk_lock);
+	clk_register_clkdev(clk, NULL, "mmp-ssp.3");
+
+	clk = clk_register_mux(NULL, "sdh_mux", sdh_parent,
+				ARRAY_SIZE(sdh_parent), CLK_SET_RATE_PARENT,
+				apmu_base + APMU_SDH0, 8, 2, 0, &clk_lock);
+	clk_register_clkdev(clk, "sdh_mux", NULL);
+
+	clk = clk_register_divider(NULL, "sdh_div", "sdh_mux",
+				CLK_SET_RATE_PARENT, apmu_base + APMU_SDH0,
+				10, 4, CLK_DIVIDER_ONE_BASED, &clk_lock);
+	clk_register_clkdev(clk, "sdh_div", NULL);
+
+	clk = mmp_clk_register_apmu("sdh0", "sdh_div", apmu_base + APMU_SDH0,
+				0x1b, &clk_lock);
+	clk_register_clkdev(clk, NULL, "sdhci-pxav3.0");
+
+	clk = mmp_clk_register_apmu("sdh1", "sdh_div", apmu_base + APMU_SDH1,
+				0x1b, &clk_lock);
+	clk_register_clkdev(clk, NULL, "sdhci-pxav3.1");
+
+	clk = mmp_clk_register_apmu("sdh2", "sdh_div", apmu_base + APMU_SDH2,
+				0x1b, &clk_lock);
+	clk_register_clkdev(clk, NULL, "sdhci-pxav3.2");
+
+	clk = mmp_clk_register_apmu("sdh3", "sdh_div", apmu_base + APMU_SDH3,
+				0x1b, &clk_lock);
+	clk_register_clkdev(clk, NULL, "sdhci-pxav3.3");
+
+	clk = mmp_clk_register_apmu("usb", "usb_pll", apmu_base + APMU_USB,
+				0x9, &clk_lock);
+	clk_register_clkdev(clk, "usb_clk", NULL);
+
+	clk = clk_register_mux(NULL, "disp0_mux", disp_parent,
+				ARRAY_SIZE(disp_parent), CLK_SET_RATE_PARENT,
+				apmu_base + APMU_DISP0, 6, 2, 0, &clk_lock);
+	clk_register_clkdev(clk, "disp_mux.0", NULL);
+
+	clk = clk_register_divider(NULL, "disp0_div", "disp0_mux",
+				CLK_SET_RATE_PARENT, apmu_base + APMU_DISP0,
+				8, 4, CLK_DIVIDER_ONE_BASED, &clk_lock);
+	clk_register_clkdev(clk, "disp_div.0", NULL);
+
+	clk = mmp_clk_register_apmu("disp0", "disp0_div",
+				apmu_base + APMU_DISP0, 0x1b, &clk_lock);
+	clk_register_clkdev(clk, NULL, "mmp-disp.0");
+
+	clk = clk_register_divider(NULL, "disp0_sphy_div", "disp0_mux", 0,
+				apmu_base + APMU_DISP0, 15, 5, 0, &clk_lock);
+	clk_register_clkdev(clk, "disp_sphy_div.0", NULL);
+
+	clk = mmp_clk_register_apmu("disp0_sphy", "disp0_sphy_div",
+				apmu_base + APMU_DISP0, 0x1024, &clk_lock);
+	clk_register_clkdev(clk, "disp_sphy.0", NULL);
+
+	clk = clk_register_mux(NULL, "disp1_mux", disp_parent,
+				ARRAY_SIZE(disp_parent), CLK_SET_RATE_PARENT,
+				apmu_base + APMU_DISP1, 6, 2, 0, &clk_lock);
+	clk_register_clkdev(clk, "disp_mux.1", NULL);
+
+	clk = clk_register_divider(NULL, "disp1_div", "disp1_mux",
+				CLK_SET_RATE_PARENT, apmu_base + APMU_DISP1,
+				8, 4, CLK_DIVIDER_ONE_BASED, &clk_lock);
+	clk_register_clkdev(clk, "disp_div.1", NULL);
+
+	clk = mmp_clk_register_apmu("disp1", "disp1_div",
+				apmu_base + APMU_DISP1, 0x1b, &clk_lock);
+	clk_register_clkdev(clk, NULL, "mmp-disp.1");
+
+	clk = mmp_clk_register_apmu("ccic_arbiter", "vctcxo",
+				apmu_base + APMU_CCIC0, 0x1800, &clk_lock);
+	clk_register_clkdev(clk, "ccic_arbiter", NULL);
+
+	clk = clk_register_mux(NULL, "ccic0_mux", ccic_parent,
+				ARRAY_SIZE(ccic_parent), CLK_SET_RATE_PARENT,
+				apmu_base + APMU_CCIC0, 6, 2, 0, &clk_lock);
+	clk_register_clkdev(clk, "ccic_mux.0", NULL);
+
+	clk = clk_register_divider(NULL, "ccic0_div", "ccic0_mux",
+				CLK_SET_RATE_PARENT, apmu_base + APMU_CCIC0,
+				17, 4, CLK_DIVIDER_ONE_BASED, &clk_lock);
+	clk_register_clkdev(clk, "ccic_div.0", NULL);
+
+	clk = mmp_clk_register_apmu("ccic0", "ccic0_div",
+				apmu_base + APMU_CCIC0, 0x1b, &clk_lock);
+	clk_register_clkdev(clk, "fnclk", "mmp-ccic.0");
+
+	clk = mmp_clk_register_apmu("ccic0_phy", "ccic0_div",
+				apmu_base + APMU_CCIC0, 0x24, &clk_lock);
+	clk_register_clkdev(clk, "phyclk", "mmp-ccic.0");
+
+	clk = clk_register_divider(NULL, "ccic0_sphy_div", "ccic0_div",
+				CLK_SET_RATE_PARENT, apmu_base + APMU_CCIC0,
+				10, 5, 0, &clk_lock);
+	clk_register_clkdev(clk, "sphyclk_div", "mmp-ccic.0");
+
+	clk = mmp_clk_register_apmu("ccic0_sphy", "ccic0_sphy_div",
+				apmu_base + APMU_CCIC0, 0x300, &clk_lock);
+	clk_register_clkdev(clk, "sphyclk", "mmp-ccic.0");
+
+	clk = clk_register_mux(NULL, "ccic1_mux", ccic_parent,
+				ARRAY_SIZE(ccic_parent), CLK_SET_RATE_PARENT,
+				apmu_base + APMU_CCIC1, 6, 2, 0, &clk_lock);
+	clk_register_clkdev(clk, "ccic_mux.1", NULL);
+
+	clk = clk_register_divider(NULL, "ccic1_div", "ccic1_mux",
+				CLK_SET_RATE_PARENT, apmu_base + APMU_CCIC1,
+				16, 4, CLK_DIVIDER_ONE_BASED, &clk_lock);
+	clk_register_clkdev(clk, "ccic_div.1", NULL);
+
+	clk = mmp_clk_register_apmu("ccic1", "ccic1_div",
+				apmu_base + APMU_CCIC1, 0x1b, &clk_lock);
+	clk_register_clkdev(clk, "fnclk", "mmp-ccic.1");
+
+	clk = mmp_clk_register_apmu("ccic1_phy", "ccic1_div",
+				apmu_base + APMU_CCIC1, 0x24, &clk_lock);
+	clk_register_clkdev(clk, "phyclk", "mmp-ccic.1");
+
+	clk = clk_register_divider(NULL, "ccic1_sphy_div", "ccic1_div",
+				CLK_SET_RATE_PARENT, apmu_base + APMU_CCIC1,
+				10, 5, 0, &clk_lock);
+	clk_register_clkdev(clk, "sphyclk_div", "mmp-ccic.1");
+
+	clk = mmp_clk_register_apmu("ccic1_sphy", "ccic1_sphy_div",
+				apmu_base + APMU_CCIC1, 0x300, &clk_lock);
+	clk_register_clkdev(clk, "sphyclk", "mmp-ccic.1");
+}
diff --git a/drivers/clk/mmp/clk-pxa168.c b/drivers/clk/mmp/clk-pxa168.c
new file mode 100644
index 0000000..e8d036c
--- /dev/null
+++ b/drivers/clk/mmp/clk-pxa168.c
@@ -0,0 +1,346 @@
+/*
+ * pxa168 clock framework source file
+ *
+ * Copyright (C) 2012 Marvell
+ * Chao Xie <xiechao.mail@gmail.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+
+#include <mach/addr-map.h>
+
+#include "clk.h"
+
+#define APBC_RTC	0x28
+#define APBC_TWSI0	0x2c
+#define APBC_KPC	0x30
+#define APBC_UART0	0x0
+#define APBC_UART1	0x4
+#define APBC_GPIO	0x8
+#define APBC_PWM0	0xc
+#define APBC_PWM1	0x10
+#define APBC_PWM2	0x14
+#define APBC_PWM3	0x18
+#define APBC_SSP0	0x81c
+#define APBC_SSP1	0x820
+#define APBC_SSP2	0x84c
+#define APBC_SSP3	0x858
+#define APBC_SSP4	0x85c
+#define APBC_TWSI1	0x6c
+#define APBC_UART2	0x70
+#define APMU_SDH0	0x54
+#define APMU_SDH1	0x58
+#define APMU_USB	0x5c
+#define APMU_DISP0	0x4c
+#define APMU_CCIC0	0x50
+#define APMU_DFC	0x60
+#define MPMU_UART_PLL	0x14
+
+static DEFINE_SPINLOCK(clk_lock);
+
+static struct clk_factor_masks uart_factor_masks = {
+	.factor = 2,
+	.num_mask = 0x1fff,
+	.den_mask = 0x1fff,
+	.num_shift = 16,
+	.den_shift = 0,
+};
+
+static struct clk_factor_tbl uart_factor_tbl[] = {
+	{.num = 8125, .den = 1536},	/*14.745MHZ */
+};
+
+static const char *uart_parent[] = {"pll1_3_16", "uart_pll"};
+static const char *ssp_parent[] = {"pll1_96", "pll1_48", "pll1_24", "pll1_12"};
+static const char *sdh_parent[] = {"pll1_12", "pll1_13"};
+static const char *disp_parent[] = {"pll1_2", "pll1_12"};
+static const char *ccic_parent[] = {"pll1_2", "pll1_12"};
+static const char *ccic_phy_parent[] = {"pll1_6", "pll1_12"};
+
+void __init pxa168_clk_init(void)
+{
+	struct clk *clk;
+	struct clk *uart_pll;
+	void __iomem *mpmu_base;
+	void __iomem *apmu_base;
+	void __iomem *apbc_base;
+
+	mpmu_base = ioremap(APB_PHYS_BASE + 0x50000, SZ_4K);
+	if (mpmu_base == NULL) {
+		pr_err("error to ioremap MPMU base\n");
+		return;
+	}
+
+	apmu_base = ioremap(AXI_PHYS_BASE + 0x82800, SZ_4K);
+	if (apmu_base == NULL) {
+		pr_err("error to ioremap APMU base\n");
+		return;
+	}
+
+	apbc_base = ioremap(APB_PHYS_BASE + 0x15000, SZ_4K);
+	if (apbc_base == NULL) {
+		pr_err("error to ioremap APBC base\n");
+		return;
+	}
+
+	clk = clk_register_fixed_rate(NULL, "clk32", NULL, CLK_IS_ROOT, 3200);
+	clk_register_clkdev(clk, "clk32", NULL);
+
+	clk = clk_register_fixed_rate(NULL, "vctcxo", NULL, CLK_IS_ROOT,
+				26000000);
+	clk_register_clkdev(clk, "vctcxo", NULL);
+
+	clk = clk_register_fixed_rate(NULL, "pll1", NULL, CLK_IS_ROOT,
+				624000000);
+	clk_register_clkdev(clk, "pll1", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "pll1_2", "pll1",
+				CLK_SET_RATE_PARENT, 1, 2);
+	clk_register_clkdev(clk, "pll1_2", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "pll1_4", "pll1_2",
+				CLK_SET_RATE_PARENT, 1, 2);
+	clk_register_clkdev(clk, "pll1_4", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "pll1_8", "pll1_4",
+				CLK_SET_RATE_PARENT, 1, 2);
+	clk_register_clkdev(clk, "pll1_8", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "pll1_16", "pll1_8",
+				CLK_SET_RATE_PARENT, 1, 2);
+	clk_register_clkdev(clk, "pll1_16", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "pll1_6", "pll1_2",
+				CLK_SET_RATE_PARENT, 1, 3);
+	clk_register_clkdev(clk, "pll1_6", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "pll1_12", "pll1_6",
+				CLK_SET_RATE_PARENT, 1, 2);
+	clk_register_clkdev(clk, "pll1_12", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "pll1_24", "pll1_12",
+				CLK_SET_RATE_PARENT, 1, 2);
+	clk_register_clkdev(clk, "pll1_24", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "pll1_48", "pll1_24",
+				CLK_SET_RATE_PARENT, 1, 2);
+	clk_register_clkdev(clk, "pll1_48", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "pll1_96", "pll1_48",
+				CLK_SET_RATE_PARENT, 1, 2);
+	clk_register_clkdev(clk, "pll1_96", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "pll1_13", "pll1",
+				CLK_SET_RATE_PARENT, 1, 13);
+	clk_register_clkdev(clk, "pll1_13", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "pll1_13_1_5", "pll1",
+				CLK_SET_RATE_PARENT, 2, 3);
+	clk_register_clkdev(clk, "pll1_13_1_5", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "pll1_2_1_5", "pll1",
+				CLK_SET_RATE_PARENT, 2, 3);
+	clk_register_clkdev(clk, "pll1_2_1_5", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "pll1_3_16", "pll1",
+				CLK_SET_RATE_PARENT, 3, 16);
+	clk_register_clkdev(clk, "pll1_3_16", NULL);
+
+	uart_pll = mmp_clk_register_factor("uart_pll", "pll1_4", 0,
+				mpmu_base + MPMU_UART_PLL,
+				&uart_factor_masks, uart_factor_tbl,
+				ARRAY_SIZE(uart_factor_tbl));
+	clk_set_rate(uart_pll, 14745600);
+	clk_register_clkdev(uart_pll, "uart_pll", NULL);
+
+	clk = mmp_clk_register_apbc("twsi0", "pll1_13_1_5",
+				apbc_base + APBC_TWSI0, 10, 0, &clk_lock);
+	clk_register_clkdev(clk, NULL, "pxa2xx-i2c.0");
+
+	clk = mmp_clk_register_apbc("twsi1", "pll1_13_1_5",
+				apbc_base + APBC_TWSI1, 10, 0, &clk_lock);
+	clk_register_clkdev(clk, NULL, "pxa2xx-i2c.1");
+
+	clk = mmp_clk_register_apbc("gpio", "vctcxo",
+				apbc_base + APBC_GPIO, 10, 0, &clk_lock);
+	clk_register_clkdev(clk, NULL, "pxa-gpio");
+
+	clk = mmp_clk_register_apbc("kpc", "clk32",
+				apbc_base + APBC_KPC, 10, 0, &clk_lock);
+	clk_register_clkdev(clk, NULL, "pxa27x-keypad");
+
+	clk = mmp_clk_register_apbc("rtc", "clk32",
+				apbc_base + APBC_RTC, 10, 0, &clk_lock);
+	clk_register_clkdev(clk, NULL, "sa1100-rtc");
+
+	clk = mmp_clk_register_apbc("pwm0", "pll1_48",
+				apbc_base + APBC_PWM0, 10, 0, &clk_lock);
+	clk_register_clkdev(clk, NULL, "pxa168-pwm.0");
+
+	clk = mmp_clk_register_apbc("pwm1", "pll1_48",
+				apbc_base + APBC_PWM1, 10, 0, &clk_lock);
+	clk_register_clkdev(clk, NULL, "pxa168-pwm.1");
+
+	clk = mmp_clk_register_apbc("pwm2", "pll1_48",
+				apbc_base + APBC_PWM2, 10, 0, &clk_lock);
+	clk_register_clkdev(clk, NULL, "pxa168-pwm.2");
+
+	clk = mmp_clk_register_apbc("pwm3", "pll1_48",
+				apbc_base + APBC_PWM3, 10, 0, &clk_lock);
+	clk_register_clkdev(clk, NULL, "pxa168-pwm.3");
+
+	clk = clk_register_mux(NULL, "uart0_mux", uart_parent,
+				ARRAY_SIZE(uart_parent), CLK_SET_RATE_PARENT,
+				apbc_base + APBC_UART0, 4, 3, 0, &clk_lock);
+	clk_set_parent(clk, uart_pll);
+	clk_register_clkdev(clk, "uart_mux.0", NULL);
+
+	clk = mmp_clk_register_apbc("uart0", "uart0_mux",
+				apbc_base + APBC_UART0, 10, 0, &clk_lock);
+	clk_register_clkdev(clk, NULL, "pxa2xx-uart.0");
+
+	clk = clk_register_mux(NULL, "uart1_mux", uart_parent,
+				ARRAY_SIZE(uart_parent), CLK_SET_RATE_PARENT,
+				apbc_base + APBC_UART1, 4, 3, 0, &clk_lock);
+	clk_set_parent(clk, uart_pll);
+	clk_register_clkdev(clk, "uart_mux.1", NULL);
+
+	clk = mmp_clk_register_apbc("uart1", "uart1_mux",
+				apbc_base + APBC_UART1,	10, 0, &clk_lock);
+	clk_register_clkdev(clk, NULL, "pxa2xx-uart.1");
+
+	clk = clk_register_mux(NULL, "uart2_mux", uart_parent,
+				ARRAY_SIZE(uart_parent), CLK_SET_RATE_PARENT,
+				apbc_base + APBC_UART2, 4, 3, 0, &clk_lock);
+	clk_set_parent(clk, uart_pll);
+	clk_register_clkdev(clk, "uart_mux.2", NULL);
+
+	clk = mmp_clk_register_apbc("uart2", "uart2_mux",
+				apbc_base + APBC_UART2,	10, 0, &clk_lock);
+	clk_register_clkdev(clk, NULL, "pxa2xx-uart.2");
+
+	clk = clk_register_mux(NULL, "ssp0_mux", ssp_parent,
+				ARRAY_SIZE(ssp_parent), CLK_SET_RATE_PARENT,
+				apbc_base + APBC_SSP0, 4, 3, 0, &clk_lock);
+	clk_register_clkdev(clk, "uart_mux.0", NULL);
+
+	clk = mmp_clk_register_apbc("ssp0", "ssp0_mux", apbc_base + APBC_SSP0,
+				10, 0, &clk_lock);
+	clk_register_clkdev(clk, NULL, "mmp-ssp.0");
+
+	clk = clk_register_mux(NULL, "ssp1_mux", ssp_parent,
+				ARRAY_SIZE(ssp_parent), CLK_SET_RATE_PARENT,
+				apbc_base + APBC_SSP1, 4, 3, 0, &clk_lock);
+	clk_register_clkdev(clk, "ssp_mux.1", NULL);
+
+	clk = mmp_clk_register_apbc("ssp1", "ssp1_mux", apbc_base + APBC_SSP1,
+				10, 0, &clk_lock);
+	clk_register_clkdev(clk, NULL, "mmp-ssp.1");
+
+	clk = clk_register_mux(NULL, "ssp2_mux", ssp_parent,
+				ARRAY_SIZE(ssp_parent), CLK_SET_RATE_PARENT,
+				apbc_base + APBC_SSP2, 4, 3, 0, &clk_lock);
+	clk_register_clkdev(clk, "ssp_mux.2", NULL);
+
+	clk = mmp_clk_register_apbc("ssp2", "ssp1_mux", apbc_base + APBC_SSP2,
+				10, 0, &clk_lock);
+	clk_register_clkdev(clk, NULL, "mmp-ssp.2");
+
+	clk = clk_register_mux(NULL, "ssp3_mux", ssp_parent,
+				ARRAY_SIZE(ssp_parent), CLK_SET_RATE_PARENT,
+				apbc_base + APBC_SSP3, 4, 3, 0, &clk_lock);
+	clk_register_clkdev(clk, "ssp_mux.3", NULL);
+
+	clk = mmp_clk_register_apbc("ssp3", "ssp1_mux", apbc_base + APBC_SSP3,
+				10, 0, &clk_lock);
+	clk_register_clkdev(clk, NULL, "mmp-ssp.3");
+
+	clk = clk_register_mux(NULL, "ssp4_mux", ssp_parent,
+				ARRAY_SIZE(ssp_parent), CLK_SET_RATE_PARENT,
+				apbc_base + APBC_SSP4, 4, 3, 0, &clk_lock);
+	clk_register_clkdev(clk, "ssp_mux.4", NULL);
+
+	clk = mmp_clk_register_apbc("ssp4", "ssp1_mux", apbc_base + APBC_SSP4,
+				10, 0, &clk_lock);
+	clk_register_clkdev(clk, NULL, "mmp-ssp.4");
+
+	clk = mmp_clk_register_apmu("dfc", "pll1_4", apmu_base + APMU_DFC,
+				0x19b, &clk_lock);
+	clk_register_clkdev(clk, NULL, "pxa3xx-nand.0");
+
+	clk = clk_register_mux(NULL, "sdh0_mux", sdh_parent,
+				ARRAY_SIZE(sdh_parent), CLK_SET_RATE_PARENT,
+				apmu_base + APMU_SDH0, 6, 1, 0, &clk_lock);
+	clk_register_clkdev(clk, "sdh0_mux", NULL);
+
+	clk = mmp_clk_register_apmu("sdh0", "sdh_mux", apmu_base + APMU_SDH0,
+				0x1b, &clk_lock);
+	clk_register_clkdev(clk, NULL, "sdhci-pxa.0");
+
+	clk = clk_register_mux(NULL, "sdh1_mux", sdh_parent,
+				ARRAY_SIZE(sdh_parent), CLK_SET_RATE_PARENT,
+				apmu_base + APMU_SDH1, 6, 1, 0, &clk_lock);
+	clk_register_clkdev(clk, "sdh1_mux", NULL);
+
+	clk = mmp_clk_register_apmu("sdh1", "sdh1_mux", apmu_base + APMU_SDH1,
+				0x1b, &clk_lock);
+	clk_register_clkdev(clk, NULL, "sdhci-pxa.1");
+
+	clk = mmp_clk_register_apmu("usb", "usb_pll", apmu_base + APMU_USB,
+				0x9, &clk_lock);
+	clk_register_clkdev(clk, "usb_clk", NULL);
+
+	clk = mmp_clk_register_apmu("sph", "usb_pll", apmu_base + APMU_USB,
+				0x12, &clk_lock);
+	clk_register_clkdev(clk, "sph_clk", NULL);
+
+	clk = clk_register_mux(NULL, "disp0_mux", disp_parent,
+				ARRAY_SIZE(disp_parent), CLK_SET_RATE_PARENT,
+				apmu_base + APMU_DISP0, 6, 1, 0, &clk_lock);
+	clk_register_clkdev(clk, "disp_mux.0", NULL);
+
+	clk = mmp_clk_register_apmu("disp0", "disp0_mux",
+				apmu_base + APMU_DISP0, 0x1b, &clk_lock);
+	clk_register_clkdev(clk, "fnclk", "mmp-disp.0");
+
+	clk = mmp_clk_register_apmu("disp0_hclk", "disp0_mux",
+				apmu_base + APMU_DISP0, 0x24, &clk_lock);
+	clk_register_clkdev(clk, "hclk", "mmp-disp.0");
+
+	clk = clk_register_mux(NULL, "ccic0_mux", ccic_parent,
+				ARRAY_SIZE(ccic_parent), CLK_SET_RATE_PARENT,
+				apmu_base + APMU_CCIC0, 6, 1, 0, &clk_lock);
+	clk_register_clkdev(clk, "ccic_mux.0", NULL);
+
+	clk = mmp_clk_register_apmu("ccic0", "ccic0_mux",
+				apmu_base + APMU_CCIC0, 0x1b, &clk_lock);
+	clk_register_clkdev(clk, "fnclk", "mmp-ccic.0");
+
+	clk = clk_register_mux(NULL, "ccic0_phy_mux", ccic_phy_parent,
+				ARRAY_SIZE(ccic_phy_parent),
+				CLK_SET_RATE_PARENT, apmu_base + APMU_CCIC0,
+				7, 1, 0, &clk_lock);
+	clk_register_clkdev(clk, "ccic_phy_mux.0", NULL);
+
+	clk = mmp_clk_register_apmu("ccic0_phy", "ccic0_phy_mux",
+				apmu_base + APMU_CCIC0, 0x24, &clk_lock);
+	clk_register_clkdev(clk, "phyclk", "mmp-ccic.0");
+
+	clk = clk_register_divider(NULL, "ccic0_sphy_div", "ccic0_mux",
+				CLK_SET_RATE_PARENT, apmu_base + APMU_CCIC0,
+				10, 5, 0, &clk_lock);
+	clk_register_clkdev(clk, "sphyclk_div", NULL);
+
+	clk = mmp_clk_register_apmu("ccic0_sphy", "ccic0_sphy_div",
+				apmu_base + APMU_CCIC0, 0x300, &clk_lock);
+	clk_register_clkdev(clk, "sphyclk", "mmp-ccic.0");
+}
diff --git a/drivers/clk/mmp/clk-pxa910.c b/drivers/clk/mmp/clk-pxa910.c
new file mode 100644
index 0000000..7048c31
--- /dev/null
+++ b/drivers/clk/mmp/clk-pxa910.c
@@ -0,0 +1,320 @@
+/*
+ * pxa910 clock framework source file
+ *
+ * Copyright (C) 2012 Marvell
+ * Chao Xie <xiechao.mail@gmail.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+
+#include <mach/addr-map.h>
+
+#include "clk.h"
+
+#define APBC_RTC	0x28
+#define APBC_TWSI0	0x2c
+#define APBC_KPC	0x18
+#define APBC_UART0	0x0
+#define APBC_UART1	0x4
+#define APBC_GPIO	0x8
+#define APBC_PWM0	0xc
+#define APBC_PWM1	0x10
+#define APBC_PWM2	0x14
+#define APBC_PWM3	0x18
+#define APBC_SSP0	0x1c
+#define APBC_SSP1	0x20
+#define APBC_SSP2	0x4c
+#define APBCP_TWSI1	0x28
+#define APBCP_UART2	0x1c
+#define APMU_SDH0	0x54
+#define APMU_SDH1	0x58
+#define APMU_USB	0x5c
+#define APMU_DISP0	0x4c
+#define APMU_CCIC0	0x50
+#define APMU_DFC	0x60
+#define MPMU_UART_PLL	0x14
+
+static DEFINE_SPINLOCK(clk_lock);
+
+static struct clk_factor_masks uart_factor_masks = {
+	.factor = 2,
+	.num_mask = 0x1fff,
+	.den_mask = 0x1fff,
+	.num_shift = 16,
+	.den_shift = 0,
+};
+
+static struct clk_factor_tbl uart_factor_tbl[] = {
+	{.num = 8125, .den = 1536},	/*14.745MHZ */
+};
+
+static const char *uart_parent[] = {"pll1_3_16", "uart_pll"};
+static const char *ssp_parent[] = {"pll1_96", "pll1_48", "pll1_24", "pll1_12"};
+static const char *sdh_parent[] = {"pll1_12", "pll1_13"};
+static const char *disp_parent[] = {"pll1_2", "pll1_12"};
+static const char *ccic_parent[] = {"pll1_2", "pll1_12"};
+static const char *ccic_phy_parent[] = {"pll1_6", "pll1_12"};
+
+void __init pxa910_clk_init(void)
+{
+	struct clk *clk;
+	struct clk *uart_pll;
+	void __iomem *mpmu_base;
+	void __iomem *apmu_base;
+	void __iomem *apbcp_base;
+	void __iomem *apbc_base;
+
+	mpmu_base = ioremap(APB_PHYS_BASE + 0x50000, SZ_4K);
+	if (mpmu_base == NULL) {
+		pr_err("error to ioremap MPMU base\n");
+		return;
+	}
+
+	apmu_base = ioremap(AXI_PHYS_BASE + 0x82800, SZ_4K);
+	if (apmu_base == NULL) {
+		pr_err("error to ioremap APMU base\n");
+		return;
+	}
+
+	apbcp_base = ioremap(APB_PHYS_BASE + 0x3b000, SZ_4K);
+	if (apbcp_base == NULL) {
+		pr_err("error to ioremap APBC extension base\n");
+		return;
+	}
+
+	apbc_base = ioremap(APB_PHYS_BASE + 0x15000, SZ_4K);
+	if (apbc_base == NULL) {
+		pr_err("error to ioremap APBC base\n");
+		return;
+	}
+
+	clk = clk_register_fixed_rate(NULL, "clk32", NULL, CLK_IS_ROOT, 3200);
+	clk_register_clkdev(clk, "clk32", NULL);
+
+	clk = clk_register_fixed_rate(NULL, "vctcxo", NULL, CLK_IS_ROOT,
+				26000000);
+	clk_register_clkdev(clk, "vctcxo", NULL);
+
+	clk = clk_register_fixed_rate(NULL, "pll1", NULL, CLK_IS_ROOT,
+				624000000);
+	clk_register_clkdev(clk, "pll1", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "pll1_2", "pll1",
+				CLK_SET_RATE_PARENT, 1, 2);
+	clk_register_clkdev(clk, "pll1_2", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "pll1_4", "pll1_2",
+				CLK_SET_RATE_PARENT, 1, 2);
+	clk_register_clkdev(clk, "pll1_4", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "pll1_8", "pll1_4",
+				CLK_SET_RATE_PARENT, 1, 2);
+	clk_register_clkdev(clk, "pll1_8", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "pll1_16", "pll1_8",
+				CLK_SET_RATE_PARENT, 1, 2);
+	clk_register_clkdev(clk, "pll1_16", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "pll1_6", "pll1_2",
+				CLK_SET_RATE_PARENT, 1, 3);
+	clk_register_clkdev(clk, "pll1_6", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "pll1_12", "pll1_6",
+				CLK_SET_RATE_PARENT, 1, 2);
+	clk_register_clkdev(clk, "pll1_12", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "pll1_24", "pll1_12",
+				CLK_SET_RATE_PARENT, 1, 2);
+	clk_register_clkdev(clk, "pll1_24", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "pll1_48", "pll1_24",
+				CLK_SET_RATE_PARENT, 1, 2);
+	clk_register_clkdev(clk, "pll1_48", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "pll1_96", "pll1_48",
+				CLK_SET_RATE_PARENT, 1, 2);
+	clk_register_clkdev(clk, "pll1_96", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "pll1_13", "pll1",
+				CLK_SET_RATE_PARENT, 1, 13);
+	clk_register_clkdev(clk, "pll1_13", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "pll1_13_1_5", "pll1",
+				CLK_SET_RATE_PARENT, 2, 3);
+	clk_register_clkdev(clk, "pll1_13_1_5", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "pll1_2_1_5", "pll1",
+				CLK_SET_RATE_PARENT, 2, 3);
+	clk_register_clkdev(clk, "pll1_2_1_5", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "pll1_3_16", "pll1",
+				CLK_SET_RATE_PARENT, 3, 16);
+	clk_register_clkdev(clk, "pll1_3_16", NULL);
+
+	uart_pll =  mmp_clk_register_factor("uart_pll", "pll1_4", 0,
+				mpmu_base + MPMU_UART_PLL,
+				&uart_factor_masks, uart_factor_tbl,
+				ARRAY_SIZE(uart_factor_tbl));
+	clk_set_rate(uart_pll, 14745600);
+	clk_register_clkdev(uart_pll, "uart_pll", NULL);
+
+	clk = mmp_clk_register_apbc("twsi0", "pll1_13_1_5",
+				apbc_base + APBC_TWSI0, 10, 0, &clk_lock);
+	clk_register_clkdev(clk, NULL, "pxa2xx-i2c.0");
+
+	clk = mmp_clk_register_apbc("twsi1", "pll1_13_1_5",
+				apbcp_base + APBCP_TWSI1, 10, 0, &clk_lock);
+	clk_register_clkdev(clk, NULL, "pxa2xx-i2c.1");
+
+	clk = mmp_clk_register_apbc("gpio", "vctcxo",
+				apbc_base + APBC_GPIO, 10, 0, &clk_lock);
+	clk_register_clkdev(clk, NULL, "pxa-gpio");
+
+	clk = mmp_clk_register_apbc("kpc", "clk32",
+				apbc_base + APBC_KPC, 10, 0, &clk_lock);
+	clk_register_clkdev(clk, NULL, "pxa27x-keypad");
+
+	clk = mmp_clk_register_apbc("rtc", "clk32",
+				apbc_base + APBC_RTC, 10, 0, &clk_lock);
+	clk_register_clkdev(clk, NULL, "sa1100-rtc");
+
+	clk = mmp_clk_register_apbc("pwm0", "pll1_48",
+				apbc_base + APBC_PWM0, 10, 0, &clk_lock);
+	clk_register_clkdev(clk, NULL, "pxa910-pwm.0");
+
+	clk = mmp_clk_register_apbc("pwm1", "pll1_48",
+				apbc_base + APBC_PWM1, 10, 0, &clk_lock);
+	clk_register_clkdev(clk, NULL, "pxa910-pwm.1");
+
+	clk = mmp_clk_register_apbc("pwm2", "pll1_48",
+				apbc_base + APBC_PWM2, 10, 0, &clk_lock);
+	clk_register_clkdev(clk, NULL, "pxa910-pwm.2");
+
+	clk = mmp_clk_register_apbc("pwm3", "pll1_48",
+				apbc_base + APBC_PWM3, 10, 0, &clk_lock);
+	clk_register_clkdev(clk, NULL, "pxa910-pwm.3");
+
+	clk = clk_register_mux(NULL, "uart0_mux", uart_parent,
+				ARRAY_SIZE(uart_parent), CLK_SET_RATE_PARENT,
+				apbc_base + APBC_UART0, 4, 3, 0, &clk_lock);
+	clk_set_parent(clk, uart_pll);
+	clk_register_clkdev(clk, "uart_mux.0", NULL);
+
+	clk = mmp_clk_register_apbc("uart0", "uart0_mux",
+				apbc_base + APBC_UART0, 10, 0, &clk_lock);
+	clk_register_clkdev(clk, NULL, "pxa2xx-uart.0");
+
+	clk = clk_register_mux(NULL, "uart1_mux", uart_parent,
+				ARRAY_SIZE(uart_parent), CLK_SET_RATE_PARENT,
+				apbc_base + APBC_UART1, 4, 3, 0, &clk_lock);
+	clk_set_parent(clk, uart_pll);
+	clk_register_clkdev(clk, "uart_mux.1", NULL);
+
+	clk = mmp_clk_register_apbc("uart1", "uart1_mux",
+				apbc_base + APBC_UART1, 10, 0, &clk_lock);
+	clk_register_clkdev(clk, NULL, "pxa2xx-uart.1");
+
+	clk = clk_register_mux(NULL, "uart2_mux", uart_parent,
+				ARRAY_SIZE(uart_parent), CLK_SET_RATE_PARENT,
+				apbcp_base + APBCP_UART2, 4, 3, 0, &clk_lock);
+	clk_set_parent(clk, uart_pll);
+	clk_register_clkdev(clk, "uart_mux.2", NULL);
+
+	clk = mmp_clk_register_apbc("uart2", "uart2_mux",
+				apbcp_base + APBCP_UART2, 10, 0, &clk_lock);
+	clk_register_clkdev(clk, NULL, "pxa2xx-uart.2");
+
+	clk = clk_register_mux(NULL, "ssp0_mux", ssp_parent,
+				ARRAY_SIZE(ssp_parent), CLK_SET_RATE_PARENT,
+				apbc_base + APBC_SSP0, 4, 3, 0, &clk_lock);
+	clk_register_clkdev(clk, "uart_mux.0", NULL);
+
+	clk = mmp_clk_register_apbc("ssp0", "ssp0_mux",
+				apbc_base + APBC_SSP0, 10, 0, &clk_lock);
+	clk_register_clkdev(clk, NULL, "mmp-ssp.0");
+
+	clk = clk_register_mux(NULL, "ssp1_mux", ssp_parent,
+				ARRAY_SIZE(ssp_parent), CLK_SET_RATE_PARENT,
+				apbc_base + APBC_SSP1, 4, 3, 0, &clk_lock);
+	clk_register_clkdev(clk, "ssp_mux.1", NULL);
+
+	clk = mmp_clk_register_apbc("ssp1", "ssp1_mux",
+				apbc_base + APBC_SSP1, 10, 0, &clk_lock);
+	clk_register_clkdev(clk, NULL, "mmp-ssp.1");
+
+	clk = mmp_clk_register_apmu("dfc", "pll1_4",
+				apmu_base + APMU_DFC, 0x19b, &clk_lock);
+	clk_register_clkdev(clk, NULL, "pxa3xx-nand.0");
+
+	clk = clk_register_mux(NULL, "sdh0_mux", sdh_parent,
+				ARRAY_SIZE(sdh_parent), CLK_SET_RATE_PARENT,
+				apmu_base + APMU_SDH0, 6, 1, 0, &clk_lock);
+	clk_register_clkdev(clk, "sdh0_mux", NULL);
+
+	clk = mmp_clk_register_apmu("sdh0", "sdh_mux",
+				apmu_base + APMU_SDH0, 0x1b, &clk_lock);
+	clk_register_clkdev(clk, NULL, "sdhci-pxa.0");
+
+	clk = clk_register_mux(NULL, "sdh1_mux", sdh_parent,
+				ARRAY_SIZE(sdh_parent), CLK_SET_RATE_PARENT,
+				apmu_base + APMU_SDH1, 6, 1, 0, &clk_lock);
+	clk_register_clkdev(clk, "sdh1_mux", NULL);
+
+	clk = mmp_clk_register_apmu("sdh1", "sdh1_mux",
+				apmu_base + APMU_SDH1, 0x1b, &clk_lock);
+	clk_register_clkdev(clk, NULL, "sdhci-pxa.1");
+
+	clk = mmp_clk_register_apmu("usb", "usb_pll",
+				apmu_base + APMU_USB, 0x9, &clk_lock);
+	clk_register_clkdev(clk, "usb_clk", NULL);
+
+	clk = mmp_clk_register_apmu("sph", "usb_pll",
+				apmu_base + APMU_USB, 0x12, &clk_lock);
+	clk_register_clkdev(clk, "sph_clk", NULL);
+
+	clk = clk_register_mux(NULL, "disp0_mux", disp_parent,
+				ARRAY_SIZE(disp_parent), CLK_SET_RATE_PARENT,
+				apmu_base + APMU_DISP0, 6, 1, 0, &clk_lock);
+	clk_register_clkdev(clk, "disp_mux.0", NULL);
+
+	clk = mmp_clk_register_apmu("disp0", "disp0_mux",
+				apmu_base + APMU_DISP0, 0x1b, &clk_lock);
+	clk_register_clkdev(clk, NULL, "mmp-disp.0");
+
+	clk = clk_register_mux(NULL, "ccic0_mux", ccic_parent,
+				ARRAY_SIZE(ccic_parent), CLK_SET_RATE_PARENT,
+				apmu_base + APMU_CCIC0, 6, 1, 0, &clk_lock);
+	clk_register_clkdev(clk, "ccic_mux.0", NULL);
+
+	clk = mmp_clk_register_apmu("ccic0", "ccic0_mux",
+				apmu_base + APMU_CCIC0, 0x1b, &clk_lock);
+	clk_register_clkdev(clk, "fnclk", "mmp-ccic.0");
+
+	clk = clk_register_mux(NULL, "ccic0_phy_mux", ccic_phy_parent,
+				ARRAY_SIZE(ccic_phy_parent),
+				CLK_SET_RATE_PARENT, apmu_base + APMU_CCIC0,
+				7, 1, 0, &clk_lock);
+	clk_register_clkdev(clk, "ccic_phy_mux.0", NULL);
+
+	clk = mmp_clk_register_apmu("ccic0_phy", "ccic0_phy_mux",
+				apmu_base + APMU_CCIC0, 0x24, &clk_lock);
+	clk_register_clkdev(clk, "phyclk", "mmp-ccic.0");
+
+	clk = clk_register_divider(NULL, "ccic0_sphy_div", "ccic0_mux",
+				CLK_SET_RATE_PARENT, apmu_base + APMU_CCIC0,
+				10, 5, 0, &clk_lock);
+	clk_register_clkdev(clk, "sphyclk_div", NULL);
+
+	clk = mmp_clk_register_apmu("ccic0_sphy", "ccic0_sphy_div",
+				apmu_base + APMU_CCIC0, 0x300, &clk_lock);
+	clk_register_clkdev(clk, "sphyclk", "mmp-ccic.0");
+}
diff --git a/drivers/clk/mmp/clk.h b/drivers/clk/mmp/clk.h
new file mode 100644
index 0000000..ab86dd4
--- /dev/null
+++ b/drivers/clk/mmp/clk.h
@@ -0,0 +1,35 @@
+#ifndef __MACH_MMP_CLK_H
+#define __MACH_MMP_CLK_H
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+
+#define APBC_NO_BUS_CTRL	BIT(0)
+#define APBC_POWER_CTRL		BIT(1)
+
+struct clk_factor_masks {
+	unsigned int	factor;
+	unsigned int	num_mask;
+	unsigned int	den_mask;
+	unsigned int	num_shift;
+	unsigned int	den_shift;
+};
+
+struct clk_factor_tbl {
+	unsigned int num;
+	unsigned int den;
+};
+
+extern struct clk *mmp_clk_register_pll2(const char *name,
+		const char *parent_name, unsigned long flags);
+extern struct clk *mmp_clk_register_apbc(const char *name,
+		const char *parent_name, void __iomem *base,
+		unsigned int delay, unsigned int apbc_flags, spinlock_t *lock);
+extern struct clk *mmp_clk_register_apmu(const char *name,
+		const char *parent_name, void __iomem *base, u32 enable_mask,
+		spinlock_t *lock);
+extern struct clk *mmp_clk_register_factor(const char *name,
+		const char *parent_name, unsigned long flags,
+		void __iomem *base, struct clk_factor_masks *masks,
+		struct clk_factor_tbl *ftbl, unsigned int ftbl_cnt);
+#endif
diff --git a/drivers/clk/mxs/Makefile b/drivers/clk/mxs/Makefile
index 7bedeec..a6a2223 100644
--- a/drivers/clk/mxs/Makefile
+++ b/drivers/clk/mxs/Makefile
@@ -2,7 +2,7 @@
 # Makefile for mxs specific clk
 #
 
-obj-y += clk.o clk-pll.o clk-ref.o clk-div.o clk-frac.o
+obj-y += clk.o clk-pll.o clk-ref.o clk-div.o clk-frac.o clk-ssp.o
 
 obj-$(CONFIG_SOC_IMX23) += clk-imx23.o
 obj-$(CONFIG_SOC_IMX28) += clk-imx28.o
diff --git a/drivers/clk/mxs/clk-imx23.c b/drivers/clk/mxs/clk-imx23.c
index 844043a..f00dffb 100644
--- a/drivers/clk/mxs/clk-imx23.c
+++ b/drivers/clk/mxs/clk-imx23.c
@@ -14,6 +14,7 @@
 #include <linux/err.h>
 #include <linux/init.h>
 #include <linux/io.h>
+#include <linux/of.h>
 #include <mach/common.h>
 #include <mach/mx23.h>
 #include "clk.h"
@@ -71,44 +72,6 @@ static void __init clk_misc_init(void)
 	__mxs_setl(30 << BP_FRAC_IOFRAC, FRAC);
 }
 
-static struct clk_lookup uart_lookups[] = {
-	{ .dev_id = "duart", },
-	{ .dev_id = "mxs-auart.0", },
-	{ .dev_id = "mxs-auart.1", },
-	{ .dev_id = "8006c000.serial", },
-	{ .dev_id = "8006e000.serial", },
-	{ .dev_id = "80070000.serial", },
-};
-
-static struct clk_lookup hbus_lookups[] = {
-	{ .dev_id = "imx23-dma-apbh", },
-	{ .dev_id = "80004000.dma-apbh", },
-};
-
-static struct clk_lookup xbus_lookups[] = {
-	{ .dev_id = "duart", .con_id = "apb_pclk"},
-	{ .dev_id = "80070000.serial", .con_id = "apb_pclk"},
-	{ .dev_id = "imx23-dma-apbx", },
-	{ .dev_id = "80024000.dma-apbx", },
-};
-
-static struct clk_lookup ssp_lookups[] = {
-	{ .dev_id = "imx23-mmc.0", },
-	{ .dev_id = "imx23-mmc.1", },
-	{ .dev_id = "80010000.ssp", },
-	{ .dev_id = "80034000.ssp", },
-};
-
-static struct clk_lookup lcdif_lookups[] = {
-	{ .dev_id = "imx23-fb", },
-	{ .dev_id = "80030000.lcdif", },
-};
-
-static struct clk_lookup gpmi_lookups[] = {
-	{ .dev_id = "imx23-gpmi-nand", },
-	{ .dev_id = "8000c000.gpmi-nand", },
-};
-
 static const char *sel_pll[]  __initconst = { "pll", "ref_xtal", };
 static const char *sel_cpu[]  __initconst = { "ref_cpu", "ref_xtal", };
 static const char *sel_pix[]  __initconst = { "ref_pix", "ref_xtal", };
@@ -127,6 +90,7 @@ enum imx23_clk {
 };
 
 static struct clk *clks[clk_max];
+static struct clk_onecell_data clk_data;
 
 static enum imx23_clk clks_init_on[] __initdata = {
 	cpu, hbus, xbus, emi, uart,
@@ -134,6 +98,7 @@ static enum imx23_clk clks_init_on[] __initdata = {
 
 int __init mx23_clocks_init(void)
 {
+	struct device_node *np;
 	int i;
 
 	clk_misc_init();
@@ -188,19 +153,19 @@ int __init mx23_clocks_init(void)
 			return PTR_ERR(clks[i]);
 		}
 
+	np = of_find_compatible_node(NULL, NULL, "fsl,imx23-clkctrl");
+	if (np) {
+		clk_data.clks = clks;
+		clk_data.clk_num = ARRAY_SIZE(clks);
+		of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+	}
+
 	clk_register_clkdev(clks[clk32k], NULL, "timrot");
-	clk_register_clkdev(clks[pwm], NULL, "80064000.pwm");
-	clk_register_clkdevs(clks[hbus], hbus_lookups, ARRAY_SIZE(hbus_lookups));
-	clk_register_clkdevs(clks[xbus], xbus_lookups, ARRAY_SIZE(xbus_lookups));
-	clk_register_clkdevs(clks[uart], uart_lookups, ARRAY_SIZE(uart_lookups));
-	clk_register_clkdevs(clks[ssp], ssp_lookups, ARRAY_SIZE(ssp_lookups));
-	clk_register_clkdevs(clks[gpmi], gpmi_lookups, ARRAY_SIZE(gpmi_lookups));
-	clk_register_clkdevs(clks[lcdif], lcdif_lookups, ARRAY_SIZE(lcdif_lookups));
 
 	for (i = 0; i < ARRAY_SIZE(clks_init_on); i++)
 		clk_prepare_enable(clks[clks_init_on[i]]);
 
-	mxs_timer_init(MX23_INT_TIMER0);
+	mxs_timer_init();
 
 	return 0;
 }
diff --git a/drivers/clk/mxs/clk-imx28.c b/drivers/clk/mxs/clk-imx28.c
index e3aab67..42978f1b 100644
--- a/drivers/clk/mxs/clk-imx28.c
+++ b/drivers/clk/mxs/clk-imx28.c
@@ -14,6 +14,7 @@
 #include <linux/err.h>
 #include <linux/init.h>
 #include <linux/io.h>
+#include <linux/of.h>
 #include <mach/common.h>
 #include <mach/mx28.h>
 #include "clk.h"
@@ -120,90 +121,6 @@ static void __init clk_misc_init(void)
 	writel_relaxed(val, FRAC0);
 }
 
-static struct clk_lookup uart_lookups[] = {
-	{ .dev_id = "duart", },
-	{ .dev_id = "mxs-auart.0", },
-	{ .dev_id = "mxs-auart.1", },
-	{ .dev_id = "mxs-auart.2", },
-	{ .dev_id = "mxs-auart.3", },
-	{ .dev_id = "mxs-auart.4", },
-	{ .dev_id = "8006a000.serial", },
-	{ .dev_id = "8006c000.serial", },
-	{ .dev_id = "8006e000.serial", },
-	{ .dev_id = "80070000.serial", },
-	{ .dev_id = "80072000.serial", },
-	{ .dev_id = "80074000.serial", },
-};
-
-static struct clk_lookup hbus_lookups[] = {
-	{ .dev_id = "imx28-dma-apbh", },
-	{ .dev_id = "80004000.dma-apbh", },
-};
-
-static struct clk_lookup xbus_lookups[] = {
-	{ .dev_id = "duart", .con_id = "apb_pclk"},
-	{ .dev_id = "80074000.serial", .con_id = "apb_pclk"},
-	{ .dev_id = "imx28-dma-apbx", },
-	{ .dev_id = "80024000.dma-apbx", },
-};
-
-static struct clk_lookup ssp0_lookups[] = {
-	{ .dev_id = "imx28-mmc.0", },
-	{ .dev_id = "80010000.ssp", },
-};
-
-static struct clk_lookup ssp1_lookups[] = {
-	{ .dev_id = "imx28-mmc.1", },
-	{ .dev_id = "80012000.ssp", },
-};
-
-static struct clk_lookup ssp2_lookups[] = {
-	{ .dev_id = "imx28-mmc.2", },
-	{ .dev_id = "80014000.ssp", },
-};
-
-static struct clk_lookup ssp3_lookups[] = {
-	{ .dev_id = "imx28-mmc.3", },
-	{ .dev_id = "80016000.ssp", },
-};
-
-static struct clk_lookup lcdif_lookups[] = {
-	{ .dev_id = "imx28-fb", },
-	{ .dev_id = "80030000.lcdif", },
-};
-
-static struct clk_lookup gpmi_lookups[] = {
-	{ .dev_id = "imx28-gpmi-nand", },
-	{ .dev_id = "8000c000.gpmi-nand", },
-};
-
-static struct clk_lookup fec_lookups[] = {
-	{ .dev_id = "imx28-fec.0", },
-	{ .dev_id = "imx28-fec.1", },
-	{ .dev_id = "800f0000.ethernet", },
-	{ .dev_id = "800f4000.ethernet", },
-};
-
-static struct clk_lookup can0_lookups[] = {
-	{ .dev_id = "flexcan.0", },
-	{ .dev_id = "80032000.can", },
-};
-
-static struct clk_lookup can1_lookups[] = {
-	{ .dev_id = "flexcan.1", },
-	{ .dev_id = "80034000.can", },
-};
-
-static struct clk_lookup saif0_lookups[] = {
-	{ .dev_id = "mxs-saif.0", },
-	{ .dev_id = "80042000.saif", },
-};
-
-static struct clk_lookup saif1_lookups[] = {
-	{ .dev_id = "mxs-saif.1", },
-	{ .dev_id = "80046000.saif", },
-};
-
 static const char *sel_cpu[]  __initconst = { "ref_cpu", "ref_xtal", };
 static const char *sel_io0[]  __initconst = { "ref_io0", "ref_xtal", };
 static const char *sel_io1[]  __initconst = { "ref_io1", "ref_xtal", };
@@ -228,6 +145,7 @@ enum imx28_clk {
 };
 
 static struct clk *clks[clk_max];
+static struct clk_onecell_data clk_data;
 
 static enum imx28_clk clks_init_on[] __initdata = {
 	cpu, hbus, xbus, emi, uart,
@@ -235,6 +153,7 @@ static enum imx28_clk clks_init_on[] __initdata = {
 
 int __init mx28_clocks_init(void)
 {
+	struct device_node *np;
 	int i;
 
 	clk_misc_init();
@@ -312,32 +231,20 @@ int __init mx28_clocks_init(void)
 			return PTR_ERR(clks[i]);
 		}
 
+	np = of_find_compatible_node(NULL, NULL, "fsl,imx28-clkctrl");
+	if (np) {
+		clk_data.clks = clks;
+		clk_data.clk_num = ARRAY_SIZE(clks);
+		of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+	}
+
 	clk_register_clkdev(clks[clk32k], NULL, "timrot");
 	clk_register_clkdev(clks[enet_out], NULL, "enet_out");
-	clk_register_clkdev(clks[pwm], NULL, "80064000.pwm");
-	clk_register_clkdevs(clks[hbus], hbus_lookups, ARRAY_SIZE(hbus_lookups));
-	clk_register_clkdevs(clks[xbus], xbus_lookups, ARRAY_SIZE(xbus_lookups));
-	clk_register_clkdevs(clks[uart], uart_lookups, ARRAY_SIZE(uart_lookups));
-	clk_register_clkdevs(clks[ssp0], ssp0_lookups, ARRAY_SIZE(ssp0_lookups));
-	clk_register_clkdevs(clks[ssp1], ssp1_lookups, ARRAY_SIZE(ssp1_lookups));
-	clk_register_clkdevs(clks[ssp2], ssp2_lookups, ARRAY_SIZE(ssp2_lookups));
-	clk_register_clkdevs(clks[ssp3], ssp3_lookups, ARRAY_SIZE(ssp3_lookups));
-	clk_register_clkdevs(clks[gpmi], gpmi_lookups, ARRAY_SIZE(gpmi_lookups));
-	clk_register_clkdevs(clks[saif0], saif0_lookups, ARRAY_SIZE(saif0_lookups));
-	clk_register_clkdevs(clks[saif1], saif1_lookups, ARRAY_SIZE(saif1_lookups));
-	clk_register_clkdevs(clks[lcdif], lcdif_lookups, ARRAY_SIZE(lcdif_lookups));
-	clk_register_clkdevs(clks[fec], fec_lookups, ARRAY_SIZE(fec_lookups));
-	clk_register_clkdevs(clks[can0], can0_lookups, ARRAY_SIZE(can0_lookups));
-	clk_register_clkdevs(clks[can1], can1_lookups, ARRAY_SIZE(can1_lookups));
-	clk_register_clkdev(clks[usb0_pwr], NULL, "8007c000.usbphy");
-	clk_register_clkdev(clks[usb1_pwr], NULL, "8007e000.usbphy");
-	clk_register_clkdev(clks[usb0], NULL, "80080000.usb");
-	clk_register_clkdev(clks[usb1], NULL, "80090000.usb");
 
 	for (i = 0; i < ARRAY_SIZE(clks_init_on); i++)
 		clk_prepare_enable(clks[clks_init_on[i]]);
 
-	mxs_timer_init(MX28_INT_TIMER0);
+	mxs_timer_init();
 
 	return 0;
 }
diff --git a/drivers/clk/mxs/clk-ssp.c b/drivers/clk/mxs/clk-ssp.c
new file mode 100644
index 0000000..af7bdbf
--- /dev/null
+++ b/drivers/clk/mxs/clk-ssp.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2012 DENX Software Engineering, GmbH
+ *
+ * Pulled from code:
+ * Portions copyright (C) 2003 Russell King, PXA MMCI Driver
+ * Portions copyright (C) 2004-2005 Pierre Ossman, W83L51xD SD/MMC driver
+ *
+ * Copyright 2008 Embedded Alley Solutions, Inc.
+ * Copyright 2009-2011 Freescale Semiconductor, Inc.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/spi/mxs-spi.h>
+
+void mxs_ssp_set_clk_rate(struct mxs_ssp *ssp, unsigned int rate)
+{
+	unsigned int ssp_clk, ssp_sck;
+	u32 clock_divide, clock_rate;
+	u32 val;
+
+	ssp_clk = clk_get_rate(ssp->clk);
+
+	for (clock_divide = 2; clock_divide <= 254; clock_divide += 2) {
+		clock_rate = DIV_ROUND_UP(ssp_clk, rate * clock_divide);
+		clock_rate = (clock_rate > 0) ? clock_rate - 1 : 0;
+		if (clock_rate <= 255)
+			break;
+	}
+
+	if (clock_divide > 254) {
+		dev_err(ssp->dev,
+			"%s: cannot set clock to %d\n", __func__, rate);
+		return;
+	}
+
+	ssp_sck = ssp_clk / clock_divide / (1 + clock_rate);
+
+	val = readl(ssp->base + HW_SSP_TIMING(ssp));
+	val &= ~(BM_SSP_TIMING_CLOCK_DIVIDE | BM_SSP_TIMING_CLOCK_RATE);
+	val |= BF_SSP(clock_divide, TIMING_CLOCK_DIVIDE);
+	val |= BF_SSP(clock_rate, TIMING_CLOCK_RATE);
+	writel(val, ssp->base + HW_SSP_TIMING(ssp));
+
+	ssp->clk_rate = ssp_sck;
+
+	dev_dbg(ssp->dev,
+		"%s: clock_divide %d, clock_rate %d, ssp_clk %d, rate_actual %d, rate_requested %d\n",
+		__func__, clock_divide, clock_rate, ssp_clk, ssp_sck, rate);
+}
+EXPORT_SYMBOL_GPL(mxs_ssp_set_clk_rate);
diff --git a/drivers/clk/ux500/Makefile b/drivers/clk/ux500/Makefile
new file mode 100644
index 0000000..858fbfe
--- /dev/null
+++ b/drivers/clk/ux500/Makefile
@@ -0,0 +1,12 @@
+#
+# Makefile for ux500 clocks
+#
+
+# Clock types
+obj-y += clk-prcc.o
+obj-y += clk-prcmu.o
+
+# Clock definitions
+obj-y += u8500_clk.o
+obj-y += u9540_clk.o
+obj-y += u8540_clk.o
diff --git a/drivers/clk/ux500/clk-prcc.c b/drivers/clk/ux500/clk-prcc.c
new file mode 100644
index 0000000..7eee7f7
--- /dev/null
+++ b/drivers/clk/ux500/clk-prcc.c
@@ -0,0 +1,164 @@
+/*
+ * PRCC clock implementation for ux500 platform.
+ *
+ * Copyright (C) 2012 ST-Ericsson SA
+ * Author: Ulf Hansson <ulf.hansson@linaro.org>
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clk-private.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/types.h>
+#include <mach/hardware.h>
+
+#include "clk.h"
+
+#define PRCC_PCKEN			0x000
+#define PRCC_PCKDIS			0x004
+#define PRCC_KCKEN			0x008
+#define PRCC_KCKDIS			0x00C
+#define PRCC_PCKSR			0x010
+#define PRCC_KCKSR			0x014
+
+#define to_clk_prcc(_hw) container_of(_hw, struct clk_prcc, hw)
+
+struct clk_prcc {
+	struct clk_hw hw;
+	void __iomem *base;
+	u32 cg_sel;
+	int is_enabled;
+};
+
+/* PRCC clock operations. */
+
+static int clk_prcc_pclk_enable(struct clk_hw *hw)
+{
+	struct clk_prcc *clk = to_clk_prcc(hw);
+
+	writel(clk->cg_sel, (clk->base + PRCC_PCKEN));
+	while (!(readl(clk->base + PRCC_PCKSR) & clk->cg_sel))
+		cpu_relax();
+
+	clk->is_enabled = 1;
+	return 0;
+}
+
+static void clk_prcc_pclk_disable(struct clk_hw *hw)
+{
+	struct clk_prcc *clk = to_clk_prcc(hw);
+
+	writel(clk->cg_sel, (clk->base + PRCC_PCKDIS));
+	clk->is_enabled = 0;
+}
+
+static int clk_prcc_kclk_enable(struct clk_hw *hw)
+{
+	struct clk_prcc *clk = to_clk_prcc(hw);
+
+	writel(clk->cg_sel, (clk->base + PRCC_KCKEN));
+	while (!(readl(clk->base + PRCC_KCKSR) & clk->cg_sel))
+		cpu_relax();
+
+	clk->is_enabled = 1;
+	return 0;
+}
+
+static void clk_prcc_kclk_disable(struct clk_hw *hw)
+{
+	struct clk_prcc *clk = to_clk_prcc(hw);
+
+	writel(clk->cg_sel, (clk->base + PRCC_KCKDIS));
+	clk->is_enabled = 0;
+}
+
+static int clk_prcc_is_enabled(struct clk_hw *hw)
+{
+	struct clk_prcc *clk = to_clk_prcc(hw);
+	return clk->is_enabled;
+}
+
+static struct clk_ops clk_prcc_pclk_ops = {
+	.enable = clk_prcc_pclk_enable,
+	.disable = clk_prcc_pclk_disable,
+	.is_enabled = clk_prcc_is_enabled,
+};
+
+static struct clk_ops clk_prcc_kclk_ops = {
+	.enable = clk_prcc_kclk_enable,
+	.disable = clk_prcc_kclk_disable,
+	.is_enabled = clk_prcc_is_enabled,
+};
+
+static struct clk *clk_reg_prcc(const char *name,
+				const char *parent_name,
+				resource_size_t phy_base,
+				u32 cg_sel,
+				unsigned long flags,
+				struct clk_ops *clk_prcc_ops)
+{
+	struct clk_prcc *clk;
+	struct clk_init_data clk_prcc_init;
+	struct clk *clk_reg;
+
+	if (!name) {
+		pr_err("clk_prcc: %s invalid arguments passed\n", __func__);
+		return ERR_PTR(-EINVAL);
+	}
+
+	clk = kzalloc(sizeof(struct clk_prcc), GFP_KERNEL);
+	if (!clk) {
+		pr_err("clk_prcc: %s could not allocate clk\n", __func__);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	clk->base = ioremap(phy_base, SZ_4K);
+	if (!clk->base)
+		goto free_clk;
+
+	clk->cg_sel = cg_sel;
+	clk->is_enabled = 1;
+
+	clk_prcc_init.name = name;
+	clk_prcc_init.ops = clk_prcc_ops;
+	clk_prcc_init.flags = flags;
+	clk_prcc_init.parent_names = (parent_name ? &parent_name : NULL);
+	clk_prcc_init.num_parents = (parent_name ? 1 : 0);
+	clk->hw.init = &clk_prcc_init;
+
+	clk_reg = clk_register(NULL, &clk->hw);
+	if (IS_ERR_OR_NULL(clk_reg))
+		goto unmap_clk;
+
+	return clk_reg;
+
+unmap_clk:
+	iounmap(clk->base);
+free_clk:
+	kfree(clk);
+	pr_err("clk_prcc: %s failed to register clk\n", __func__);
+	return ERR_PTR(-ENOMEM);
+}
+
+struct clk *clk_reg_prcc_pclk(const char *name,
+			      const char *parent_name,
+			      resource_size_t phy_base,
+			      u32 cg_sel,
+			      unsigned long flags)
+{
+	return clk_reg_prcc(name, parent_name, phy_base, cg_sel, flags,
+			&clk_prcc_pclk_ops);
+}
+
+struct clk *clk_reg_prcc_kclk(const char *name,
+			      const char *parent_name,
+			      resource_size_t phy_base,
+			      u32 cg_sel,
+			      unsigned long flags)
+{
+	return clk_reg_prcc(name, parent_name, phy_base, cg_sel, flags,
+			&clk_prcc_kclk_ops);
+}
diff --git a/drivers/clk/ux500/clk-prcmu.c b/drivers/clk/ux500/clk-prcmu.c
new file mode 100644
index 0000000..930cdfe
--- /dev/null
+++ b/drivers/clk/ux500/clk-prcmu.c
@@ -0,0 +1,252 @@
+/*
+ * PRCMU clock implementation for ux500 platform.
+ *
+ * Copyright (C) 2012 ST-Ericsson SA
+ * Author: Ulf Hansson <ulf.hansson@linaro.org>
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clk-private.h>
+#include <linux/mfd/dbx500-prcmu.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include "clk.h"
+
+#define to_clk_prcmu(_hw) container_of(_hw, struct clk_prcmu, hw)
+
+struct clk_prcmu {
+	struct clk_hw hw;
+	u8 cg_sel;
+	int is_enabled;
+};
+
+/* PRCMU clock operations. */
+
+static int clk_prcmu_prepare(struct clk_hw *hw)
+{
+	struct clk_prcmu *clk = to_clk_prcmu(hw);
+	return prcmu_request_clock(clk->cg_sel, true);
+}
+
+static void clk_prcmu_unprepare(struct clk_hw *hw)
+{
+	struct clk_prcmu *clk = to_clk_prcmu(hw);
+	if (prcmu_request_clock(clk->cg_sel, false))
+		pr_err("clk_prcmu: %s failed to disable %s.\n", __func__,
+			hw->init->name);
+}
+
+static int clk_prcmu_enable(struct clk_hw *hw)
+{
+	struct clk_prcmu *clk = to_clk_prcmu(hw);
+	clk->is_enabled = 1;
+	return 0;
+}
+
+static void clk_prcmu_disable(struct clk_hw *hw)
+{
+	struct clk_prcmu *clk = to_clk_prcmu(hw);
+	clk->is_enabled = 0;
+}
+
+static int clk_prcmu_is_enabled(struct clk_hw *hw)
+{
+	struct clk_prcmu *clk = to_clk_prcmu(hw);
+	return clk->is_enabled;
+}
+
+static unsigned long clk_prcmu_recalc_rate(struct clk_hw *hw,
+					   unsigned long parent_rate)
+{
+	struct clk_prcmu *clk = to_clk_prcmu(hw);
+	return prcmu_clock_rate(clk->cg_sel);
+}
+
+static long clk_prcmu_round_rate(struct clk_hw *hw, unsigned long rate,
+				 unsigned long *parent_rate)
+{
+	struct clk_prcmu *clk = to_clk_prcmu(hw);
+	return prcmu_round_clock_rate(clk->cg_sel, rate);
+}
+
+static int clk_prcmu_set_rate(struct clk_hw *hw, unsigned long rate,
+			      unsigned long parent_rate)
+{
+	struct clk_prcmu *clk = to_clk_prcmu(hw);
+	return prcmu_set_clock_rate(clk->cg_sel, rate);
+}
+
+static int request_ape_opp100(bool enable)
+{
+	static int reqs;
+	int err = 0;
+
+	if (enable) {
+		if (!reqs)
+			err = prcmu_qos_add_requirement(PRCMU_QOS_APE_OPP,
+							"clock", 100);
+		if (!err)
+			reqs++;
+	} else {
+		reqs--;
+		if (!reqs)
+			prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP,
+						"clock");
+	}
+	return err;
+}
+
+static int clk_prcmu_opp_prepare(struct clk_hw *hw)
+{
+	int err;
+	struct clk_prcmu *clk = to_clk_prcmu(hw);
+
+	err = request_ape_opp100(true);
+	if (err) {
+		pr_err("clk_prcmu: %s failed to request APE OPP100 for %s.\n",
+			__func__, hw->init->name);
+		return err;
+	}
+
+	err = prcmu_request_clock(clk->cg_sel, true);
+	if (err)
+		request_ape_opp100(false);
+
+	return err;
+}
+
+static void clk_prcmu_opp_unprepare(struct clk_hw *hw)
+{
+	struct clk_prcmu *clk = to_clk_prcmu(hw);
+
+	if (prcmu_request_clock(clk->cg_sel, false))
+		goto out_error;
+	if (request_ape_opp100(false))
+		goto out_error;
+	return;
+
+out_error:
+	pr_err("clk_prcmu: %s failed to disable %s.\n", __func__,
+		hw->init->name);
+}
+
+static struct clk_ops clk_prcmu_scalable_ops = {
+	.prepare = clk_prcmu_prepare,
+	.unprepare = clk_prcmu_unprepare,
+	.enable = clk_prcmu_enable,
+	.disable = clk_prcmu_disable,
+	.is_enabled = clk_prcmu_is_enabled,
+	.recalc_rate = clk_prcmu_recalc_rate,
+	.round_rate = clk_prcmu_round_rate,
+	.set_rate = clk_prcmu_set_rate,
+};
+
+static struct clk_ops clk_prcmu_gate_ops = {
+	.prepare = clk_prcmu_prepare,
+	.unprepare = clk_prcmu_unprepare,
+	.enable = clk_prcmu_enable,
+	.disable = clk_prcmu_disable,
+	.is_enabled = clk_prcmu_is_enabled,
+	.recalc_rate = clk_prcmu_recalc_rate,
+};
+
+static struct clk_ops clk_prcmu_rate_ops = {
+	.is_enabled = clk_prcmu_is_enabled,
+	.recalc_rate = clk_prcmu_recalc_rate,
+};
+
+static struct clk_ops clk_prcmu_opp_gate_ops = {
+	.prepare = clk_prcmu_opp_prepare,
+	.unprepare = clk_prcmu_opp_unprepare,
+	.enable = clk_prcmu_enable,
+	.disable = clk_prcmu_disable,
+	.is_enabled = clk_prcmu_is_enabled,
+	.recalc_rate = clk_prcmu_recalc_rate,
+};
+
+static struct clk *clk_reg_prcmu(const char *name,
+				 const char *parent_name,
+				 u8 cg_sel,
+				 unsigned long rate,
+				 unsigned long flags,
+				 struct clk_ops *clk_prcmu_ops)
+{
+	struct clk_prcmu *clk;
+	struct clk_init_data clk_prcmu_init;
+	struct clk *clk_reg;
+
+	if (!name) {
+		pr_err("clk_prcmu: %s invalid arguments passed\n", __func__);
+		return ERR_PTR(-EINVAL);
+	}
+
+	clk = kzalloc(sizeof(struct clk_prcmu), GFP_KERNEL);
+	if (!clk) {
+		pr_err("clk_prcmu: %s could not allocate clk\n", __func__);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	clk->cg_sel = cg_sel;
+	clk->is_enabled = 1;
+	/* "rate" can be used for changing the initial frequency */
+	if (rate)
+		prcmu_set_clock_rate(cg_sel, rate);
+
+	clk_prcmu_init.name = name;
+	clk_prcmu_init.ops = clk_prcmu_ops;
+	clk_prcmu_init.flags = flags;
+	clk_prcmu_init.parent_names = (parent_name ? &parent_name : NULL);
+	clk_prcmu_init.num_parents = (parent_name ? 1 : 0);
+	clk->hw.init = &clk_prcmu_init;
+
+	clk_reg = clk_register(NULL, &clk->hw);
+	if (IS_ERR_OR_NULL(clk_reg))
+		goto free_clk;
+
+	return clk_reg;
+
+free_clk:
+	kfree(clk);
+	pr_err("clk_prcmu: %s failed to register clk\n", __func__);
+	return ERR_PTR(-ENOMEM);
+}
+
+struct clk *clk_reg_prcmu_scalable(const char *name,
+				   const char *parent_name,
+				   u8 cg_sel,
+				   unsigned long rate,
+				   unsigned long flags)
+{
+	return clk_reg_prcmu(name, parent_name, cg_sel, rate, flags,
+			&clk_prcmu_scalable_ops);
+}
+
+struct clk *clk_reg_prcmu_gate(const char *name,
+			       const char *parent_name,
+			       u8 cg_sel,
+			       unsigned long flags)
+{
+	return clk_reg_prcmu(name, parent_name, cg_sel, 0, flags,
+			&clk_prcmu_gate_ops);
+}
+
+struct clk *clk_reg_prcmu_rate(const char *name,
+			       const char *parent_name,
+			       u8 cg_sel,
+			       unsigned long flags)
+{
+	return clk_reg_prcmu(name, parent_name, cg_sel, 0, flags,
+			&clk_prcmu_rate_ops);
+}
+
+struct clk *clk_reg_prcmu_opp_gate(const char *name,
+				   const char *parent_name,
+				   u8 cg_sel,
+				   unsigned long flags)
+{
+	return clk_reg_prcmu(name, parent_name, cg_sel, 0, flags,
+			&clk_prcmu_opp_gate_ops);
+}
diff --git a/drivers/clk/ux500/clk.h b/drivers/clk/ux500/clk.h
new file mode 100644
index 0000000..836d7d1
--- /dev/null
+++ b/drivers/clk/ux500/clk.h
@@ -0,0 +1,48 @@
+/*
+ * Clocks for ux500 platforms
+ *
+ * Copyright (C) 2012 ST-Ericsson SA
+ * Author: Ulf Hansson <ulf.hansson@linaro.org>
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#ifndef __UX500_CLK_H
+#define __UX500_CLK_H
+
+#include <linux/clk.h>
+
+struct clk *clk_reg_prcc_pclk(const char *name,
+			      const char *parent_name,
+			      unsigned int phy_base,
+			      u32 cg_sel,
+			      unsigned long flags);
+
+struct clk *clk_reg_prcc_kclk(const char *name,
+			      const char *parent_name,
+			      unsigned int phy_base,
+			      u32 cg_sel,
+			      unsigned long flags);
+
+struct clk *clk_reg_prcmu_scalable(const char *name,
+				   const char *parent_name,
+				   u8 cg_sel,
+				   unsigned long rate,
+				   unsigned long flags);
+
+struct clk *clk_reg_prcmu_gate(const char *name,
+			       const char *parent_name,
+			       u8 cg_sel,
+			       unsigned long flags);
+
+struct clk *clk_reg_prcmu_rate(const char *name,
+			       const char *parent_name,
+			       u8 cg_sel,
+			       unsigned long flags);
+
+struct clk *clk_reg_prcmu_opp_gate(const char *name,
+				   const char *parent_name,
+				   u8 cg_sel,
+				   unsigned long flags);
+
+#endif /* __UX500_CLK_H */
diff --git a/drivers/clk/ux500/u8500_clk.c b/drivers/clk/ux500/u8500_clk.c
new file mode 100644
index 0000000..ca4a25e
--- /dev/null
+++ b/drivers/clk/ux500/u8500_clk.c
@@ -0,0 +1,477 @@
+/*
+ * Clock definitions for u8500 platform.
+ *
+ * Copyright (C) 2012 ST-Ericsson SA
+ * Author: Ulf Hansson <ulf.hansson@linaro.org>
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/mfd/dbx500-prcmu.h>
+#include <linux/platform_data/clk-ux500.h>
+
+#include "clk.h"
+
+void u8500_clk_init(void)
+{
+	struct prcmu_fw_version *fw_version;
+	const char *sgaclk_parent = NULL;
+	struct clk *clk;
+
+	/* Clock sources */
+	clk = clk_reg_prcmu_gate("soc0_pll", NULL, PRCMU_PLLSOC0,
+				CLK_IS_ROOT|CLK_IGNORE_UNUSED);
+	clk_register_clkdev(clk, "soc0_pll", NULL);
+
+	clk = clk_reg_prcmu_gate("soc1_pll", NULL, PRCMU_PLLSOC1,
+				CLK_IS_ROOT|CLK_IGNORE_UNUSED);
+	clk_register_clkdev(clk, "soc1_pll", NULL);
+
+	clk = clk_reg_prcmu_gate("ddr_pll", NULL, PRCMU_PLLDDR,
+				CLK_IS_ROOT|CLK_IGNORE_UNUSED);
+	clk_register_clkdev(clk, "ddr_pll", NULL);
+
+	/* FIXME: Add sys, ulp and int clocks here. */
+
+	clk = clk_register_fixed_rate(NULL, "rtc32k", "NULL",
+				CLK_IS_ROOT|CLK_IGNORE_UNUSED,
+				32768);
+	clk_register_clkdev(clk, "clk32k", NULL);
+	clk_register_clkdev(clk, NULL, "rtc-pl031");
+
+	/* PRCMU clocks */
+	fw_version = prcmu_get_fw_version();
+	if (fw_version != NULL) {
+		switch (fw_version->project) {
+		case PRCMU_FW_PROJECT_U8500_C2:
+		case PRCMU_FW_PROJECT_U8520:
+		case PRCMU_FW_PROJECT_U8420:
+			sgaclk_parent = "soc0_pll";
+			break;
+		default:
+			break;
+		}
+	}
+
+	if (sgaclk_parent)
+		clk = clk_reg_prcmu_gate("sgclk", sgaclk_parent,
+					PRCMU_SGACLK, 0);
+	else
+		clk = clk_reg_prcmu_gate("sgclk", NULL,
+					PRCMU_SGACLK, CLK_IS_ROOT);
+	clk_register_clkdev(clk, NULL, "mali");
+
+	clk = clk_reg_prcmu_gate("uartclk", NULL, PRCMU_UARTCLK, CLK_IS_ROOT);
+	clk_register_clkdev(clk, NULL, "UART");
+
+	clk = clk_reg_prcmu_gate("msp02clk", NULL, PRCMU_MSP02CLK, CLK_IS_ROOT);
+	clk_register_clkdev(clk, NULL, "MSP02");
+
+	clk = clk_reg_prcmu_gate("msp1clk", NULL, PRCMU_MSP1CLK, CLK_IS_ROOT);
+	clk_register_clkdev(clk, NULL, "MSP1");
+
+	clk = clk_reg_prcmu_gate("i2cclk", NULL, PRCMU_I2CCLK, CLK_IS_ROOT);
+	clk_register_clkdev(clk, NULL, "I2C");
+
+	clk = clk_reg_prcmu_gate("slimclk", NULL, PRCMU_SLIMCLK, CLK_IS_ROOT);
+	clk_register_clkdev(clk, NULL, "slim");
+
+	clk = clk_reg_prcmu_gate("per1clk", NULL, PRCMU_PER1CLK, CLK_IS_ROOT);
+	clk_register_clkdev(clk, NULL, "PERIPH1");
+
+	clk = clk_reg_prcmu_gate("per2clk", NULL, PRCMU_PER2CLK, CLK_IS_ROOT);
+	clk_register_clkdev(clk, NULL, "PERIPH2");
+
+	clk = clk_reg_prcmu_gate("per3clk", NULL, PRCMU_PER3CLK, CLK_IS_ROOT);
+	clk_register_clkdev(clk, NULL, "PERIPH3");
+
+	clk = clk_reg_prcmu_gate("per5clk", NULL, PRCMU_PER5CLK, CLK_IS_ROOT);
+	clk_register_clkdev(clk, NULL, "PERIPH5");
+
+	clk = clk_reg_prcmu_gate("per6clk", NULL, PRCMU_PER6CLK, CLK_IS_ROOT);
+	clk_register_clkdev(clk, NULL, "PERIPH6");
+
+	clk = clk_reg_prcmu_gate("per7clk", NULL, PRCMU_PER7CLK, CLK_IS_ROOT);
+	clk_register_clkdev(clk, NULL, "PERIPH7");
+
+	clk = clk_reg_prcmu_scalable("lcdclk", NULL, PRCMU_LCDCLK, 0,
+				CLK_IS_ROOT|CLK_SET_RATE_GATE);
+	clk_register_clkdev(clk, NULL, "lcd");
+	clk_register_clkdev(clk, "lcd", "mcde");
+
+	clk = clk_reg_prcmu_opp_gate("bmlclk", NULL, PRCMU_BMLCLK, CLK_IS_ROOT);
+	clk_register_clkdev(clk, NULL, "bml");
+
+	clk = clk_reg_prcmu_scalable("hsitxclk", NULL, PRCMU_HSITXCLK, 0,
+				CLK_IS_ROOT|CLK_SET_RATE_GATE);
+
+	clk = clk_reg_prcmu_scalable("hsirxclk", NULL, PRCMU_HSIRXCLK, 0,
+				CLK_IS_ROOT|CLK_SET_RATE_GATE);
+
+	clk = clk_reg_prcmu_scalable("hdmiclk", NULL, PRCMU_HDMICLK, 0,
+				CLK_IS_ROOT|CLK_SET_RATE_GATE);
+	clk_register_clkdev(clk, NULL, "hdmi");
+	clk_register_clkdev(clk, "hdmi", "mcde");
+
+	clk = clk_reg_prcmu_gate("apeatclk", NULL, PRCMU_APEATCLK, CLK_IS_ROOT);
+	clk_register_clkdev(clk, NULL, "apeat");
+
+	clk = clk_reg_prcmu_gate("apetraceclk", NULL, PRCMU_APETRACECLK,
+				CLK_IS_ROOT);
+	clk_register_clkdev(clk, NULL, "apetrace");
+
+	clk = clk_reg_prcmu_gate("mcdeclk", NULL, PRCMU_MCDECLK, CLK_IS_ROOT);
+	clk_register_clkdev(clk, NULL, "mcde");
+	clk_register_clkdev(clk, "mcde", "mcde");
+	clk_register_clkdev(clk, "dsisys", "dsilink.0");
+	clk_register_clkdev(clk, "dsisys", "dsilink.1");
+	clk_register_clkdev(clk, "dsisys", "dsilink.2");
+
+	clk = clk_reg_prcmu_opp_gate("ipi2cclk", NULL, PRCMU_IPI2CCLK,
+				CLK_IS_ROOT);
+	clk_register_clkdev(clk, NULL, "ipi2");
+
+	clk = clk_reg_prcmu_gate("dsialtclk", NULL, PRCMU_DSIALTCLK,
+				CLK_IS_ROOT);
+	clk_register_clkdev(clk, NULL, "dsialt");
+
+	clk = clk_reg_prcmu_gate("dmaclk", NULL, PRCMU_DMACLK, CLK_IS_ROOT);
+	clk_register_clkdev(clk, NULL, "dma40.0");
+
+	clk = clk_reg_prcmu_gate("b2r2clk", NULL, PRCMU_B2R2CLK, CLK_IS_ROOT);
+	clk_register_clkdev(clk, NULL, "b2r2");
+	clk_register_clkdev(clk, NULL, "b2r2_core");
+	clk_register_clkdev(clk, NULL, "U8500-B2R2.0");
+
+	clk = clk_reg_prcmu_scalable("tvclk", NULL, PRCMU_TVCLK, 0,
+				CLK_IS_ROOT|CLK_SET_RATE_GATE);
+	clk_register_clkdev(clk, NULL, "tv");
+	clk_register_clkdev(clk, "tv", "mcde");
+
+	clk = clk_reg_prcmu_gate("sspclk", NULL, PRCMU_SSPCLK, CLK_IS_ROOT);
+	clk_register_clkdev(clk, NULL, "SSP");
+
+	clk = clk_reg_prcmu_gate("rngclk", NULL, PRCMU_RNGCLK, CLK_IS_ROOT);
+	clk_register_clkdev(clk, NULL, "rngclk");
+
+	clk = clk_reg_prcmu_gate("uiccclk", NULL, PRCMU_UICCCLK, CLK_IS_ROOT);
+	clk_register_clkdev(clk, NULL, "uicc");
+
+	/*
+	 * FIXME: The MTU clocks might need some kind of "parent muxed join"
+	 * and these have no K-clocks. For now, we ignore the missing
+	 * connection to the corresponding P-clocks, p6_mtu0_clk and
+	 * p6_mtu1_clk. Instead timclk is used which is the valid parent.
+	 */
+	clk = clk_reg_prcmu_gate("timclk", NULL, PRCMU_TIMCLK, CLK_IS_ROOT);
+	clk_register_clkdev(clk, NULL, "mtu0");
+	clk_register_clkdev(clk, NULL, "mtu1");
+
+	clk = clk_reg_prcmu_gate("sdmmcclk", NULL, PRCMU_SDMMCCLK, CLK_IS_ROOT);
+	clk_register_clkdev(clk, NULL, "sdmmc");
+
+
+	clk = clk_reg_prcmu_scalable("dsi_pll", "hdmiclk",
+				PRCMU_PLLDSI, 0, CLK_SET_RATE_GATE);
+	clk_register_clkdev(clk, "dsihs2", "mcde");
+	clk_register_clkdev(clk, "dsihs2", "dsilink.2");
+
+
+	clk = clk_reg_prcmu_scalable("dsi0clk", "dsi_pll",
+				PRCMU_DSI0CLK, 0, CLK_SET_RATE_GATE);
+	clk_register_clkdev(clk, "dsihs0", "mcde");
+	clk_register_clkdev(clk, "dsihs0", "dsilink.0");
+
+	clk = clk_reg_prcmu_scalable("dsi1clk", "dsi_pll",
+				PRCMU_DSI1CLK, 0, CLK_SET_RATE_GATE);
+	clk_register_clkdev(clk, "dsihs1", "mcde");
+	clk_register_clkdev(clk, "dsihs1", "dsilink.1");
+
+	clk = clk_reg_prcmu_scalable("dsi0escclk", "tvclk",
+				PRCMU_DSI0ESCCLK, 0, CLK_SET_RATE_GATE);
+	clk_register_clkdev(clk, "dsilp0", "dsilink.0");
+	clk_register_clkdev(clk, "dsilp0", "mcde");
+
+	clk = clk_reg_prcmu_scalable("dsi1escclk", "tvclk",
+				PRCMU_DSI1ESCCLK, 0, CLK_SET_RATE_GATE);
+	clk_register_clkdev(clk, "dsilp1", "dsilink.1");
+	clk_register_clkdev(clk, "dsilp1", "mcde");
+
+	clk = clk_reg_prcmu_scalable("dsi2escclk", "tvclk",
+				PRCMU_DSI2ESCCLK, 0, CLK_SET_RATE_GATE);
+	clk_register_clkdev(clk, "dsilp2", "dsilink.2");
+	clk_register_clkdev(clk, "dsilp2", "mcde");
+
+	clk = clk_reg_prcmu_rate("smp_twd", NULL, PRCMU_ARMSS,
+				CLK_IS_ROOT|CLK_GET_RATE_NOCACHE|
+				CLK_IGNORE_UNUSED);
+	clk_register_clkdev(clk, NULL, "smp_twd");
+
+	/*
+	 * FIXME: Add special handled PRCMU clocks here:
+	 * 1. clk_arm, use PRCMU_ARMCLK.
+	 * 2. clkout0yuv, use PRCMU as parent + need regulator + pinctrl.
+	 * 3. ab9540_clkout1yuv, see clkout0yuv
+	 */
+
+	/* PRCC P-clocks */
+	clk = clk_reg_prcc_pclk("p1_pclk0", "per1clk", U8500_CLKRST1_BASE,
+				BIT(0), 0);
+	clk_register_clkdev(clk, "apb_pclk", "uart0");
+
+	clk = clk_reg_prcc_pclk("p1_pclk1", "per1clk", U8500_CLKRST1_BASE,
+				BIT(1), 0);
+	clk_register_clkdev(clk, "apb_pclk", "uart1");
+
+	clk = clk_reg_prcc_pclk("p1_pclk2", "per1clk", U8500_CLKRST1_BASE,
+				BIT(2), 0);
+	clk = clk_reg_prcc_pclk("p1_pclk3", "per1clk", U8500_CLKRST1_BASE,
+				BIT(3), 0);
+	clk = clk_reg_prcc_pclk("p1_pclk4", "per1clk", U8500_CLKRST1_BASE,
+				BIT(4), 0);
+
+	clk = clk_reg_prcc_pclk("p1_pclk5", "per1clk", U8500_CLKRST1_BASE,
+				BIT(5), 0);
+	clk_register_clkdev(clk, "apb_pclk", "sdi0");
+
+	clk = clk_reg_prcc_pclk("p1_pclk6", "per1clk", U8500_CLKRST1_BASE,
+				BIT(6), 0);
+
+	clk = clk_reg_prcc_pclk("p1_pclk7", "per1clk", U8500_CLKRST1_BASE,
+				BIT(7), 0);
+	clk_register_clkdev(clk, NULL, "spi3");
+
+	clk = clk_reg_prcc_pclk("p1_pclk8", "per1clk", U8500_CLKRST1_BASE,
+				BIT(8), 0);
+
+	clk = clk_reg_prcc_pclk("p1_pclk9", "per1clk", U8500_CLKRST1_BASE,
+				BIT(9), 0);
+	clk_register_clkdev(clk, NULL, "gpio.0");
+	clk_register_clkdev(clk, NULL, "gpio.1");
+	clk_register_clkdev(clk, NULL, "gpioblock0");
+
+	clk = clk_reg_prcc_pclk("p1_pclk10", "per1clk", U8500_CLKRST1_BASE,
+				BIT(10), 0);
+	clk = clk_reg_prcc_pclk("p1_pclk11", "per1clk", U8500_CLKRST1_BASE,
+				BIT(11), 0);
+
+	clk = clk_reg_prcc_pclk("p2_pclk0", "per2clk", U8500_CLKRST2_BASE,
+				BIT(0), 0);
+
+	clk = clk_reg_prcc_pclk("p2_pclk1", "per2clk", U8500_CLKRST2_BASE,
+				BIT(1), 0);
+	clk_register_clkdev(clk, NULL, "spi2");
+
+	clk = clk_reg_prcc_pclk("p2_pclk2", "per2clk", U8500_CLKRST2_BASE,
+				BIT(2), 0);
+	clk_register_clkdev(clk, NULL, "spi1");
+
+	clk = clk_reg_prcc_pclk("p2_pclk3", "per2clk", U8500_CLKRST2_BASE,
+				BIT(3), 0);
+	clk_register_clkdev(clk, NULL, "pwl");
+
+	clk = clk_reg_prcc_pclk("p2_pclk4", "per2clk", U8500_CLKRST2_BASE,
+				BIT(4), 0);
+	clk_register_clkdev(clk, "apb_pclk", "sdi4");
+
+	clk = clk_reg_prcc_pclk("p2_pclk5", "per2clk", U8500_CLKRST2_BASE,
+				BIT(5), 0);
+
+	clk = clk_reg_prcc_pclk("p2_pclk6", "per2clk", U8500_CLKRST2_BASE,
+				BIT(6), 0);
+	clk_register_clkdev(clk, "apb_pclk", "sdi1");
+
+
+	clk = clk_reg_prcc_pclk("p2_pclk7", "per2clk", U8500_CLKRST2_BASE,
+				BIT(7), 0);
+	clk_register_clkdev(clk, "apb_pclk", "sdi3");
+
+	clk = clk_reg_prcc_pclk("p2_pclk8", "per2clk", U8500_CLKRST2_BASE,
+				BIT(8), 0);
+	clk_register_clkdev(clk, NULL, "spi0");
+
+	clk = clk_reg_prcc_pclk("p2_pclk9", "per2clk", U8500_CLKRST2_BASE,
+				BIT(9), 0);
+	clk_register_clkdev(clk, "hsir_hclk", "ste_hsi.0");
+
+	clk = clk_reg_prcc_pclk("p2_pclk10", "per2clk", U8500_CLKRST2_BASE,
+				BIT(10), 0);
+	clk_register_clkdev(clk, "hsit_hclk", "ste_hsi.0");
+
+	clk = clk_reg_prcc_pclk("p2_pclk11", "per2clk", U8500_CLKRST2_BASE,
+				BIT(11), 0);
+	clk_register_clkdev(clk, NULL, "gpio.6");
+	clk_register_clkdev(clk, NULL, "gpio.7");
+	clk_register_clkdev(clk, NULL, "gpioblock1");
+
+	clk = clk_reg_prcc_pclk("p2_pclk12", "per2clk", U8500_CLKRST2_BASE,
+				BIT(11), 0);
+
+	clk = clk_reg_prcc_pclk("p3_pclk0", "per3clk", U8500_CLKRST3_BASE,
+				BIT(0), 0);
+	clk_register_clkdev(clk, NULL, "fsmc");
+
+	clk = clk_reg_prcc_pclk("p3_pclk1", "per3clk", U8500_CLKRST3_BASE,
+				BIT(1), 0);
+	clk = clk_reg_prcc_pclk("p3_pclk2", "per3clk", U8500_CLKRST3_BASE,
+				BIT(2), 0);
+	clk = clk_reg_prcc_pclk("p3_pclk3", "per3clk", U8500_CLKRST3_BASE,
+				BIT(3), 0);
+
+	clk = clk_reg_prcc_pclk("p3_pclk4", "per3clk", U8500_CLKRST3_BASE,
+				BIT(4), 0);
+	clk_register_clkdev(clk, "apb_pclk", "sdi2");
+
+	clk = clk_reg_prcc_pclk("p3_pclk5", "per3clk", U8500_CLKRST3_BASE,
+				BIT(5), 0);
+
+	clk = clk_reg_prcc_pclk("p3_pclk6", "per3clk", U8500_CLKRST3_BASE,
+				BIT(6), 0);
+	clk_register_clkdev(clk, "apb_pclk", "uart2");
+
+	clk = clk_reg_prcc_pclk("p3_pclk7", "per3clk", U8500_CLKRST3_BASE,
+				BIT(7), 0);
+	clk_register_clkdev(clk, "apb_pclk", "sdi5");
+
+	clk = clk_reg_prcc_pclk("p3_pclk8", "per3clk", U8500_CLKRST3_BASE,
+				BIT(8), 0);
+	clk_register_clkdev(clk, NULL, "gpio.2");
+	clk_register_clkdev(clk, NULL, "gpio.3");
+	clk_register_clkdev(clk, NULL, "gpio.4");
+	clk_register_clkdev(clk, NULL, "gpio.5");
+	clk_register_clkdev(clk, NULL, "gpioblock2");
+
+	clk = clk_reg_prcc_pclk("p5_pclk0", "per5clk", U8500_CLKRST5_BASE,
+				BIT(0), 0);
+	clk_register_clkdev(clk, "usb", "musb-ux500.0");
+
+	clk = clk_reg_prcc_pclk("p5_pclk1", "per5clk", U8500_CLKRST5_BASE,
+				BIT(1), 0);
+	clk_register_clkdev(clk, NULL, "gpio.8");
+	clk_register_clkdev(clk, NULL, "gpioblock3");
+
+	clk = clk_reg_prcc_pclk("p6_pclk0", "per6clk", U8500_CLKRST6_BASE,
+				BIT(0), 0);
+
+	clk = clk_reg_prcc_pclk("p6_pclk1", "per6clk", U8500_CLKRST6_BASE,
+				BIT(1), 0);
+	clk_register_clkdev(clk, NULL, "cryp0");
+	clk_register_clkdev(clk, NULL, "cryp1");
+
+	clk = clk_reg_prcc_pclk("p6_pclk2", "per6clk", U8500_CLKRST6_BASE,
+				BIT(2), 0);
+	clk_register_clkdev(clk, NULL, "hash0");
+
+	clk = clk_reg_prcc_pclk("p6_pclk3", "per6clk", U8500_CLKRST6_BASE,
+				BIT(3), 0);
+	clk_register_clkdev(clk, NULL, "pka");
+
+	clk = clk_reg_prcc_pclk("p6_pclk4", "per6clk", U8500_CLKRST6_BASE,
+				BIT(4), 0);
+	clk_register_clkdev(clk, NULL, "hash1");
+
+	clk = clk_reg_prcc_pclk("p6_pclk5", "per6clk", U8500_CLKRST6_BASE,
+				BIT(5), 0);
+	clk_register_clkdev(clk, NULL, "cfgreg");
+
+	clk = clk_reg_prcc_pclk("p6_pclk6", "per6clk", U8500_CLKRST6_BASE,
+				BIT(6), 0);
+	clk = clk_reg_prcc_pclk("p6_pclk7", "per6clk", U8500_CLKRST6_BASE,
+				BIT(7), 0);
+
+	/* PRCC K-clocks
+	 *
+	 * FIXME: Some drivers requires PERPIH[n| to be automatically enabled
+	 * by enabling just the K-clock, even if it is not a valid parent to
+	 * the K-clock. Until drivers get fixed we might need some kind of
+	 * "parent muxed join".
+	 */
+
+	/* Periph1 */
+	clk = clk_reg_prcc_kclk("p1_uart0_kclk", "uartclk",
+			U8500_CLKRST1_BASE, BIT(0), CLK_SET_RATE_GATE);
+	clk_register_clkdev(clk, NULL, "uart0");
+
+	clk = clk_reg_prcc_kclk("p1_uart1_kclk", "uartclk",
+			U8500_CLKRST1_BASE, BIT(1), CLK_SET_RATE_GATE);
+	clk_register_clkdev(clk, NULL, "uart1");
+
+	clk = clk_reg_prcc_kclk("p1_i2c1_kclk", "i2cclk",
+			U8500_CLKRST1_BASE, BIT(2), CLK_SET_RATE_GATE);
+	clk = clk_reg_prcc_kclk("p1_msp0_kclk", "msp02clk",
+			U8500_CLKRST1_BASE, BIT(3), CLK_SET_RATE_GATE);
+	clk = clk_reg_prcc_kclk("p1_msp1_kclk", "msp1clk",
+			U8500_CLKRST1_BASE, BIT(4), CLK_SET_RATE_GATE);
+
+	clk = clk_reg_prcc_kclk("p1_sdi0_kclk", "sdmmcclk",
+			U8500_CLKRST1_BASE, BIT(5), CLK_SET_RATE_GATE);
+	clk_register_clkdev(clk, NULL, "sdi0");
+
+	clk = clk_reg_prcc_kclk("p1_i2c2_kclk", "i2cclk",
+			U8500_CLKRST1_BASE, BIT(6), CLK_SET_RATE_GATE);
+	clk = clk_reg_prcc_kclk("p1_slimbus0_kclk", "slimclk",
+			U8500_CLKRST1_BASE, BIT(3), CLK_SET_RATE_GATE);
+	/* FIXME: Redefinition of BIT(3). */
+	clk = clk_reg_prcc_kclk("p1_i2c4_kclk", "i2cclk",
+			U8500_CLKRST1_BASE, BIT(9), CLK_SET_RATE_GATE);
+	clk = clk_reg_prcc_kclk("p1_msp3_kclk", "msp1clk",
+			U8500_CLKRST1_BASE, BIT(10), CLK_SET_RATE_GATE);
+
+	/* Periph2 */
+	clk = clk_reg_prcc_kclk("p2_i2c3_kclk", "i2cclk",
+			U8500_CLKRST2_BASE, BIT(0), CLK_SET_RATE_GATE);
+
+	clk = clk_reg_prcc_kclk("p2_sdi4_kclk", "sdmmcclk",
+			U8500_CLKRST2_BASE, BIT(2), CLK_SET_RATE_GATE);
+	clk_register_clkdev(clk, NULL, "sdi4");
+
+	clk = clk_reg_prcc_kclk("p2_msp2_kclk", "msp02clk",
+			U8500_CLKRST2_BASE, BIT(3), CLK_SET_RATE_GATE);
+
+	clk = clk_reg_prcc_kclk("p2_sdi1_kclk", "sdmmcclk",
+			U8500_CLKRST2_BASE, BIT(4), CLK_SET_RATE_GATE);
+	clk_register_clkdev(clk, NULL, "sdi1");
+
+	clk = clk_reg_prcc_kclk("p2_sdi3_kclk", "sdmmcclk",
+			U8500_CLKRST2_BASE, BIT(5), CLK_SET_RATE_GATE);
+	clk_register_clkdev(clk, NULL, "sdi3");
+
+	/* Note that rate is received from parent. */
+	clk = clk_reg_prcc_kclk("p2_ssirx_kclk", "hsirxclk",
+			U8500_CLKRST2_BASE, BIT(6),
+			CLK_SET_RATE_GATE|CLK_SET_RATE_PARENT);
+	clk = clk_reg_prcc_kclk("p2_ssitx_kclk", "hsitxclk",
+			U8500_CLKRST2_BASE, BIT(7),
+			CLK_SET_RATE_GATE|CLK_SET_RATE_PARENT);
+
+	/* Periph3 */
+	clk = clk_reg_prcc_kclk("p3_ssp0_kclk", "sspclk",
+			U8500_CLKRST3_BASE, BIT(1), CLK_SET_RATE_GATE);
+	clk = clk_reg_prcc_kclk("p3_ssp1_kclk", "sspclk",
+			U8500_CLKRST3_BASE, BIT(2), CLK_SET_RATE_GATE);
+	clk = clk_reg_prcc_kclk("p3_i2c0_kclk", "i2cclk",
+			U8500_CLKRST3_BASE, BIT(3), CLK_SET_RATE_GATE);
+
+	clk = clk_reg_prcc_kclk("p3_sdi2_kclk", "sdmmcclk",
+			U8500_CLKRST3_BASE, BIT(4), CLK_SET_RATE_GATE);
+	clk_register_clkdev(clk, NULL, "sdi2");
+
+	clk = clk_reg_prcc_kclk("p3_ske_kclk", "rtc32k",
+			U8500_CLKRST3_BASE, BIT(5), CLK_SET_RATE_GATE);
+
+	clk = clk_reg_prcc_kclk("p3_uart2_kclk", "uartclk",
+			U8500_CLKRST3_BASE, BIT(6), CLK_SET_RATE_GATE);
+	clk_register_clkdev(clk, NULL, "uart2");
+
+	clk = clk_reg_prcc_kclk("p3_sdi5_kclk", "sdmmcclk",
+			U8500_CLKRST3_BASE, BIT(7), CLK_SET_RATE_GATE);
+	clk_register_clkdev(clk, NULL, "sdi5");
+
+	/* Periph6 */
+	clk = clk_reg_prcc_kclk("p3_rng_kclk", "rngclk",
+			U8500_CLKRST6_BASE, BIT(0), CLK_SET_RATE_GATE);
+
+}
diff --git a/drivers/clk/ux500/u8540_clk.c b/drivers/clk/ux500/u8540_clk.c
new file mode 100644
index 0000000..10adfd2
--- /dev/null
+++ b/drivers/clk/ux500/u8540_clk.c
@@ -0,0 +1,21 @@
+/*
+ * Clock definitions for u8540 platform.
+ *
+ * Copyright (C) 2012 ST-Ericsson SA
+ * Author: Ulf Hansson <ulf.hansson@linaro.org>
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/mfd/dbx500-prcmu.h>
+#include <linux/platform_data/clk-ux500.h>
+
+#include "clk.h"
+
+void u8540_clk_init(void)
+{
+	/* register clocks here */
+}
diff --git a/drivers/clk/ux500/u9540_clk.c b/drivers/clk/ux500/u9540_clk.c
new file mode 100644
index 0000000..dbc0191
--- /dev/null
+++ b/drivers/clk/ux500/u9540_clk.c
@@ -0,0 +1,21 @@
+/*
+ * Clock definitions for u9540 platform.
+ *
+ * Copyright (C) 2012 ST-Ericsson SA
+ * Author: Ulf Hansson <ulf.hansson@linaro.org>
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/mfd/dbx500-prcmu.h>
+#include <linux/platform_data/clk-ux500.h>
+
+#include "clk.h"
+
+void u9540_clk_init(void)
+{
+	/* register clocks here */
+}
diff --git a/drivers/clk/versatile/Makefile b/drivers/clk/versatile/Makefile
index 50cf6a2..c0a0f64 100644
--- a/drivers/clk/versatile/Makefile
+++ b/drivers/clk/versatile/Makefile
@@ -1,3 +1,4 @@
 # Makefile for Versatile-specific clocks
 obj-$(CONFIG_ICST)		+= clk-icst.o
 obj-$(CONFIG_ARCH_INTEGRATOR)	+= clk-integrator.o
+obj-$(CONFIG_ARCH_REALVIEW)	+= clk-realview.o
diff --git a/drivers/clk/versatile/clk-realview.c b/drivers/clk/versatile/clk-realview.c
new file mode 100644
index 0000000..e21a99c
--- /dev/null
+++ b/drivers/clk/versatile/clk-realview.c
@@ -0,0 +1,114 @@
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/clk-provider.h>
+
+#include <mach/hardware.h>
+#include <mach/platform.h>
+
+#include "clk-icst.h"
+
+/*
+ * Implementation of the ARM RealView clock trees.
+ */
+
+static void __iomem *sys_lock;
+static void __iomem *sys_vcoreg;
+
+/**
+ * realview_oscvco_get() - get ICST OSC settings for the RealView
+ */
+static struct icst_vco realview_oscvco_get(void)
+{
+	u32 val;
+	struct icst_vco vco;
+
+	val = readl(sys_vcoreg);
+	vco.v = val & 0x1ff;
+	vco.r = (val >> 9) & 0x7f;
+	vco.s = (val >> 16) & 03;
+	return vco;
+}
+
+static void realview_oscvco_set(struct icst_vco vco)
+{
+	u32 val;
+
+	val = readl(sys_vcoreg) & ~0x7ffff;
+	val |= vco.v | (vco.r << 9) | (vco.s << 16);
+
+	/* This magic unlocks the CM VCO so it can be controlled */
+	writel(0xa05f, sys_lock);
+	writel(val, sys_vcoreg);
+	/* This locks the CM again */
+	writel(0, sys_lock);
+}
+
+static const struct icst_params realview_oscvco_params = {
+	.ref		= 24000000,
+	.vco_max	= ICST307_VCO_MAX,
+	.vco_min	= ICST307_VCO_MIN,
+	.vd_min		= 4 + 8,
+	.vd_max		= 511 + 8,
+	.rd_min		= 1 + 2,
+	.rd_max		= 127 + 2,
+	.s2div		= icst307_s2div,
+	.idx2s		= icst307_idx2s,
+};
+
+static const struct clk_icst_desc __initdata realview_icst_desc = {
+	.params = &realview_oscvco_params,
+	.getvco = realview_oscvco_get,
+	.setvco = realview_oscvco_set,
+};
+
+/*
+ * realview_clk_init() - set up the RealView clock tree
+ */
+void __init realview_clk_init(void __iomem *sysbase, bool is_pb1176)
+{
+	struct clk *clk;
+
+	sys_lock = sysbase + REALVIEW_SYS_LOCK_OFFSET;
+	if (is_pb1176)
+		sys_vcoreg = sysbase + REALVIEW_SYS_OSC0_OFFSET;
+	else
+		sys_vcoreg = sysbase + REALVIEW_SYS_OSC4_OFFSET;
+
+
+	/* APB clock dummy */
+	clk = clk_register_fixed_rate(NULL, "apb_pclk", NULL, CLK_IS_ROOT, 0);
+	clk_register_clkdev(clk, "apb_pclk", NULL);
+
+	/* 24 MHz clock */
+	clk = clk_register_fixed_rate(NULL, "clk24mhz", NULL, CLK_IS_ROOT,
+				24000000);
+	clk_register_clkdev(clk, NULL, "dev:uart0");
+	clk_register_clkdev(clk, NULL, "dev:uart1");
+	clk_register_clkdev(clk, NULL, "dev:uart2");
+	clk_register_clkdev(clk, NULL, "fpga:kmi0");
+	clk_register_clkdev(clk, NULL, "fpga:kmi1");
+	clk_register_clkdev(clk, NULL, "fpga:mmc0");
+	clk_register_clkdev(clk, NULL, "dev:ssp0");
+	if (is_pb1176) {
+		/*
+		 * UART3 is on the dev chip in PB1176
+		 * UART4 only exists in PB1176
+		 */
+		clk_register_clkdev(clk, NULL, "dev:uart3");
+		clk_register_clkdev(clk, NULL, "dev:uart4");
+	} else
+		clk_register_clkdev(clk, NULL, "fpga:uart3");
+
+
+	/* 1 MHz clock */
+	clk = clk_register_fixed_rate(NULL, "clk1mhz", NULL, CLK_IS_ROOT,
+				      1000000);
+	clk_register_clkdev(clk, NULL, "sp804");
+
+	/* ICST VCO clock */
+	clk = icst_clk_register(NULL, &realview_icst_desc);
+	clk_register_clkdev(clk, NULL, "dev:clcd");
+	clk_register_clkdev(clk, NULL, "issp:clcd");
+}
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index d53cd0a..6a78073 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -35,3 +35,8 @@ config CLKSRC_DBX500_PRCMU_SCHED_CLOCK
 	default y
 	help
 	  Use the always on PRCMU Timer as sched_clock
+
+config CLKSRC_ARM_GENERIC
+	def_bool y if ARM64
+	help
+	  This option enables support for the ARM generic timer.
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index b65d0c5..cccde85 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -13,3 +13,5 @@ obj-$(CONFIG_DW_APB_TIMER)	+= dw_apb_timer.o
 obj-$(CONFIG_DW_APB_TIMER_OF)	+= dw_apb_timer_of.o
 obj-$(CONFIG_CLKSRC_DBX500_PRCMU)	+= clksrc-dbx500-prcmu.o
 obj-$(CONFIG_ARMADA_370_XP_TIMER)	+= time-armada-370-xp.o
+obj-$(CONFIG_CLKSRC_ARM_GENERIC)	+= arm_generic.o
+obj-$(CONFIG_ARCH_BCM2835)	+= bcm2835_timer.o
diff --git a/drivers/clocksource/arm_generic.c b/drivers/clocksource/arm_generic.c
new file mode 100644
index 0000000..c4d9f95
--- /dev/null
+++ b/drivers/clocksource/arm_generic.c
@@ -0,0 +1,232 @@
+/*
+ * Generic timers support
+ *
+ * Copyright (C) 2012 ARM Ltd.
+ * Author: Marc Zyngier <marc.zyngier@arm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/smp.h>
+#include <linux/cpu.h>
+#include <linux/jiffies.h>
+#include <linux/interrupt.h>
+#include <linux/clockchips.h>
+#include <linux/of_irq.h>
+#include <linux/io.h>
+
+#include <clocksource/arm_generic.h>
+
+#include <asm/arm_generic.h>
+
+static u32 arch_timer_rate;
+static u64 sched_clock_mult __read_mostly;
+static DEFINE_PER_CPU(struct clock_event_device, arch_timer_evt);
+static int arch_timer_ppi;
+
+static irqreturn_t arch_timer_handle_irq(int irq, void *dev_id)
+{
+	struct clock_event_device *evt = dev_id;
+	unsigned long ctrl;
+
+	ctrl = arch_timer_reg_read(ARCH_TIMER_REG_CTRL);
+	if (ctrl & ARCH_TIMER_CTRL_ISTATUS) {
+		ctrl |= ARCH_TIMER_CTRL_IMASK;
+		arch_timer_reg_write(ARCH_TIMER_REG_CTRL, ctrl);
+		evt->event_handler(evt);
+		return IRQ_HANDLED;
+	}
+
+	return IRQ_NONE;
+}
+
+static void arch_timer_stop(void)
+{
+	unsigned long ctrl;
+
+	ctrl = arch_timer_reg_read(ARCH_TIMER_REG_CTRL);
+	ctrl &= ~ARCH_TIMER_CTRL_ENABLE;
+	arch_timer_reg_write(ARCH_TIMER_REG_CTRL, ctrl);
+}
+
+static void arch_timer_set_mode(enum clock_event_mode mode,
+				struct clock_event_device *clk)
+{
+	switch (mode) {
+	case CLOCK_EVT_MODE_UNUSED:
+	case CLOCK_EVT_MODE_SHUTDOWN:
+		arch_timer_stop();
+		break;
+	default:
+		break;
+	}
+}
+
+static int arch_timer_set_next_event(unsigned long evt,
+				     struct clock_event_device *unused)
+{
+	unsigned long ctrl;
+
+	ctrl = arch_timer_reg_read(ARCH_TIMER_REG_CTRL);
+	ctrl |= ARCH_TIMER_CTRL_ENABLE;
+	ctrl &= ~ARCH_TIMER_CTRL_IMASK;
+
+	arch_timer_reg_write(ARCH_TIMER_REG_TVAL, evt);
+	arch_timer_reg_write(ARCH_TIMER_REG_CTRL, ctrl);
+
+	return 0;
+}
+
+static void __cpuinit arch_timer_setup(struct clock_event_device *clk)
+{
+	/* Let's make sure the timer is off before doing anything else */
+	arch_timer_stop();
+
+	clk->features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_C3STOP;
+	clk->name = "arch_sys_timer";
+	clk->rating = 400;
+	clk->set_mode = arch_timer_set_mode;
+	clk->set_next_event = arch_timer_set_next_event;
+	clk->irq = arch_timer_ppi;
+	clk->cpumask = cpumask_of(smp_processor_id());
+
+	clockevents_config_and_register(clk, arch_timer_rate,
+					0xf, 0x7fffffff);
+
+	enable_percpu_irq(clk->irq, 0);
+
+	/* Ensure the physical counter is visible to userspace for the vDSO. */
+	arch_counter_enable_user_access();
+}
+
+static void __init arch_timer_calibrate(void)
+{
+	if (arch_timer_rate == 0) {
+		arch_timer_reg_write(ARCH_TIMER_REG_CTRL, 0);
+		arch_timer_rate = arch_timer_reg_read(ARCH_TIMER_REG_FREQ);
+
+		/* Check the timer frequency. */
+		if (arch_timer_rate == 0)
+			panic("Architected timer frequency is set to zero.\n"
+			      "You must set this in your .dts file\n");
+	}
+
+	/* Cache the sched_clock multiplier to save a divide in the hot path. */
+
+	sched_clock_mult = NSEC_PER_SEC / arch_timer_rate;
+
+	pr_info("Architected local timer running at %u.%02uMHz.\n",
+		 arch_timer_rate / 1000000, (arch_timer_rate / 10000) % 100);
+}
+
+static cycle_t arch_counter_read(struct clocksource *cs)
+{
+	return arch_counter_get_cntpct();
+}
+
+static struct clocksource clocksource_counter = {
+	.name	= "arch_sys_counter",
+	.rating	= 400,
+	.read	= arch_counter_read,
+	.mask	= CLOCKSOURCE_MASK(56),
+	.flags	= (CLOCK_SOURCE_IS_CONTINUOUS | CLOCK_SOURCE_VALID_FOR_HRES),
+};
+
+int read_current_timer(unsigned long *timer_value)
+{
+	*timer_value = arch_counter_get_cntpct();
+	return 0;
+}
+
+unsigned long long notrace sched_clock(void)
+{
+	return arch_counter_get_cntvct() * sched_clock_mult;
+}
+
+static int __cpuinit arch_timer_cpu_notify(struct notifier_block *self,
+					   unsigned long action, void *hcpu)
+{
+	int cpu = (long)hcpu;
+	struct clock_event_device *clk = per_cpu_ptr(&arch_timer_evt, cpu);
+
+	switch(action) {
+	case CPU_STARTING:
+	case CPU_STARTING_FROZEN:
+		arch_timer_setup(clk);
+		break;
+
+	case CPU_DYING:
+	case CPU_DYING_FROZEN:
+		pr_debug("arch_timer_teardown disable IRQ%d cpu #%d\n",
+			 clk->irq, cpu);
+		disable_percpu_irq(clk->irq);
+		arch_timer_set_mode(CLOCK_EVT_MODE_UNUSED, clk);
+		break;
+	}
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block __cpuinitdata arch_timer_cpu_nb = {
+	.notifier_call = arch_timer_cpu_notify,
+};
+
+static const struct of_device_id arch_timer_of_match[] __initconst = {
+	{ .compatible = "arm,armv8-timer" },
+	{},
+};
+
+int __init arm_generic_timer_init(void)
+{
+	struct device_node *np;
+	int err;
+	u32 freq;
+
+	np = of_find_matching_node(NULL, arch_timer_of_match);
+	if (!np) {
+		pr_err("arch_timer: can't find DT node\n");
+		return -ENODEV;
+	}
+
+	/* Try to determine the frequency from the device tree or CNTFRQ */
+	if (!of_property_read_u32(np, "clock-frequency", &freq))
+		arch_timer_rate = freq;
+	arch_timer_calibrate();
+
+	arch_timer_ppi = irq_of_parse_and_map(np, 0);
+	pr_info("arch_timer: found %s irq %d\n", np->name, arch_timer_ppi);
+
+	err = request_percpu_irq(arch_timer_ppi, arch_timer_handle_irq,
+				 np->name, &arch_timer_evt);
+	if (err) {
+		pr_err("arch_timer: can't register interrupt %d (%d)\n",
+		       arch_timer_ppi, err);
+		return err;
+	}
+
+	clocksource_register_hz(&clocksource_counter, arch_timer_rate);
+
+	/* Calibrate the delay loop directly */
+	lpj_fine = arch_timer_rate / HZ;
+
+	/* Immediately configure the timer on the boot CPU */
+	arch_timer_setup(per_cpu_ptr(&arch_timer_evt, smp_processor_id()));
+
+	register_cpu_notifier(&arch_timer_cpu_nb);
+
+	return 0;
+}
diff --git a/drivers/clocksource/bcm2835_timer.c b/drivers/clocksource/bcm2835_timer.c
new file mode 100644
index 0000000..bc19f12
--- /dev/null
+++ b/drivers/clocksource/bcm2835_timer.c
@@ -0,0 +1,161 @@
+/*
+ * Copyright 2012 Simon Arlott
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/bcm2835_timer.h>
+#include <linux/bitops.h>
+#include <linux/clockchips.h>
+#include <linux/clocksource.h>
+#include <linux/interrupt.h>
+#include <linux/irqreturn.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+
+#include <asm/sched_clock.h>
+#include <asm/irq.h>
+
+#define REG_CONTROL	0x00
+#define REG_COUNTER_LO	0x04
+#define REG_COUNTER_HI	0x08
+#define REG_COMPARE(n)	(0x0c + (n) * 4)
+#define MAX_TIMER	3
+#define DEFAULT_TIMER	3
+
+struct bcm2835_timer {
+	void __iomem *control;
+	void __iomem *compare;
+	int match_mask;
+	struct clock_event_device evt;
+	struct irqaction act;
+};
+
+static void __iomem *system_clock __read_mostly;
+
+static u32 notrace bcm2835_sched_read(void)
+{
+	return readl_relaxed(system_clock);
+}
+
+static void bcm2835_time_set_mode(enum clock_event_mode mode,
+	struct clock_event_device *evt_dev)
+{
+	switch (mode) {
+	case CLOCK_EVT_MODE_ONESHOT:
+	case CLOCK_EVT_MODE_UNUSED:
+	case CLOCK_EVT_MODE_SHUTDOWN:
+	case CLOCK_EVT_MODE_RESUME:
+		break;
+	default:
+		WARN(1, "%s: unhandled event mode %d\n", __func__, mode);
+		break;
+	}
+}
+
+static int bcm2835_time_set_next_event(unsigned long event,
+	struct clock_event_device *evt_dev)
+{
+	struct bcm2835_timer *timer = container_of(evt_dev,
+		struct bcm2835_timer, evt);
+	writel_relaxed(readl_relaxed(system_clock) + event,
+		timer->compare);
+	return 0;
+}
+
+static irqreturn_t bcm2835_time_interrupt(int irq, void *dev_id)
+{
+	struct bcm2835_timer *timer = dev_id;
+	void (*event_handler)(struct clock_event_device *);
+	if (readl_relaxed(timer->control) & timer->match_mask) {
+		writel_relaxed(timer->match_mask, timer->control);
+
+		event_handler = ACCESS_ONCE(timer->evt.event_handler);
+		if (event_handler)
+			event_handler(&timer->evt);
+		return IRQ_HANDLED;
+	} else {
+		return IRQ_NONE;
+	}
+}
+
+static struct of_device_id bcm2835_time_match[] __initconst = {
+	{ .compatible = "brcm,bcm2835-system-timer" },
+	{}
+};
+
+static void __init bcm2835_time_init(void)
+{
+	struct device_node *node;
+	void __iomem *base;
+	u32 freq;
+	int irq;
+	struct bcm2835_timer *timer;
+
+	node = of_find_matching_node(NULL, bcm2835_time_match);
+	if (!node)
+		panic("No bcm2835 timer node");
+
+	base = of_iomap(node, 0);
+	if (!base)
+		panic("Can't remap registers");
+
+	if (of_property_read_u32(node, "clock-frequency", &freq))
+		panic("Can't read clock-frequency");
+
+	system_clock = base + REG_COUNTER_LO;
+	setup_sched_clock(bcm2835_sched_read, 32, freq);
+
+	clocksource_mmio_init(base + REG_COUNTER_LO, node->name,
+		freq, 300, 32, clocksource_mmio_readl_up);
+
+	irq = irq_of_parse_and_map(node, DEFAULT_TIMER);
+	if (irq <= 0)
+		panic("Can't parse IRQ");
+
+	timer = kzalloc(sizeof(*timer), GFP_KERNEL);
+	if (!timer)
+		panic("Can't allocate timer struct\n");
+
+	timer->control = base + REG_CONTROL;
+	timer->compare = base + REG_COMPARE(DEFAULT_TIMER);
+	timer->match_mask = BIT(DEFAULT_TIMER);
+	timer->evt.name = node->name;
+	timer->evt.rating = 300;
+	timer->evt.features = CLOCK_EVT_FEAT_ONESHOT;
+	timer->evt.set_mode = bcm2835_time_set_mode;
+	timer->evt.set_next_event = bcm2835_time_set_next_event;
+	timer->evt.cpumask = cpumask_of(0);
+	timer->act.name = node->name;
+	timer->act.flags = IRQF_TIMER | IRQF_SHARED;
+	timer->act.dev_id = timer;
+	timer->act.handler = bcm2835_time_interrupt;
+
+	if (setup_irq(irq, &timer->act))
+		panic("Can't set up timer IRQ\n");
+
+	clockevents_config_and_register(&timer->evt, freq, 0xf, 0xffffffff);
+
+	pr_info("bcm2835: system timer (irq = %d)\n", irq);
+}
+
+struct sys_timer bcm2835_timer = {
+	.init = bcm2835_time_init,
+};
diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
index 98b06ba..a5f7829 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.c
@@ -33,6 +33,7 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/pm_domain.h>
+#include <linux/pm_runtime.h>
 
 struct sh_cmt_priv {
 	void __iomem *mapbase;
@@ -52,6 +53,7 @@ struct sh_cmt_priv {
 	struct clock_event_device ced;
 	struct clocksource cs;
 	unsigned long total_cycles;
+	bool cs_enabled;
 };
 
 static DEFINE_RAW_SPINLOCK(sh_cmt_lock);
@@ -155,6 +157,9 @@ static int sh_cmt_enable(struct sh_cmt_priv *p, unsigned long *rate)
 {
 	int k, ret;
 
+	pm_runtime_get_sync(&p->pdev->dev);
+	dev_pm_syscore_device(&p->pdev->dev, true);
+
 	/* enable clock */
 	ret = clk_enable(p->clk);
 	if (ret) {
@@ -221,6 +226,9 @@ static void sh_cmt_disable(struct sh_cmt_priv *p)
 
 	/* stop clock */
 	clk_disable(p->clk);
+
+	dev_pm_syscore_device(&p->pdev->dev, false);
+	pm_runtime_put(&p->pdev->dev);
 }
 
 /* private flags */
@@ -451,22 +459,42 @@ static int sh_cmt_clocksource_enable(struct clocksource *cs)
 	int ret;
 	struct sh_cmt_priv *p = cs_to_sh_cmt(cs);
 
+	WARN_ON(p->cs_enabled);
+
 	p->total_cycles = 0;
 
 	ret = sh_cmt_start(p, FLAG_CLOCKSOURCE);
-	if (!ret)
+	if (!ret) {
 		__clocksource_updatefreq_hz(cs, p->rate);
+		p->cs_enabled = true;
+	}
 	return ret;
 }
 
 static void sh_cmt_clocksource_disable(struct clocksource *cs)
 {
-	sh_cmt_stop(cs_to_sh_cmt(cs), FLAG_CLOCKSOURCE);
+	struct sh_cmt_priv *p = cs_to_sh_cmt(cs);
+
+	WARN_ON(!p->cs_enabled);
+
+	sh_cmt_stop(p, FLAG_CLOCKSOURCE);
+	p->cs_enabled = false;
+}
+
+static void sh_cmt_clocksource_suspend(struct clocksource *cs)
+{
+	struct sh_cmt_priv *p = cs_to_sh_cmt(cs);
+
+	sh_cmt_stop(p, FLAG_CLOCKSOURCE);
+	pm_genpd_syscore_poweroff(&p->pdev->dev);
 }
 
 static void sh_cmt_clocksource_resume(struct clocksource *cs)
 {
-	sh_cmt_start(cs_to_sh_cmt(cs), FLAG_CLOCKSOURCE);
+	struct sh_cmt_priv *p = cs_to_sh_cmt(cs);
+
+	pm_genpd_syscore_poweron(&p->pdev->dev);
+	sh_cmt_start(p, FLAG_CLOCKSOURCE);
 }
 
 static int sh_cmt_register_clocksource(struct sh_cmt_priv *p,
@@ -479,7 +507,7 @@ static int sh_cmt_register_clocksource(struct sh_cmt_priv *p,
 	cs->read = sh_cmt_clocksource_read;
 	cs->enable = sh_cmt_clocksource_enable;
 	cs->disable = sh_cmt_clocksource_disable;
-	cs->suspend = sh_cmt_clocksource_disable;
+	cs->suspend = sh_cmt_clocksource_suspend;
 	cs->resume = sh_cmt_clocksource_resume;
 	cs->mask = CLOCKSOURCE_MASK(sizeof(unsigned long) * 8);
 	cs->flags = CLOCK_SOURCE_IS_CONTINUOUS;
@@ -562,6 +590,16 @@ static int sh_cmt_clock_event_next(unsigned long delta,
 	return 0;
 }
 
+static void sh_cmt_clock_event_suspend(struct clock_event_device *ced)
+{
+	pm_genpd_syscore_poweroff(&ced_to_sh_cmt(ced)->pdev->dev);
+}
+
+static void sh_cmt_clock_event_resume(struct clock_event_device *ced)
+{
+	pm_genpd_syscore_poweron(&ced_to_sh_cmt(ced)->pdev->dev);
+}
+
 static void sh_cmt_register_clockevent(struct sh_cmt_priv *p,
 				       char *name, unsigned long rating)
 {
@@ -576,6 +614,8 @@ static void sh_cmt_register_clockevent(struct sh_cmt_priv *p,
 	ced->cpumask = cpumask_of(0);
 	ced->set_next_event = sh_cmt_clock_event_next;
 	ced->set_mode = sh_cmt_clock_event_mode;
+	ced->suspend = sh_cmt_clock_event_suspend;
+	ced->resume = sh_cmt_clock_event_resume;
 
 	dev_info(&p->pdev->dev, "used for clock events\n");
 	clockevents_register_device(ced);
@@ -670,6 +710,7 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev)
 		dev_err(&p->pdev->dev, "registration failed\n");
 		goto err1;
 	}
+	p->cs_enabled = false;
 
 	ret = setup_irq(irq, &p->irqaction);
 	if (ret) {
@@ -688,14 +729,17 @@ err0:
 static int __devinit sh_cmt_probe(struct platform_device *pdev)
 {
 	struct sh_cmt_priv *p = platform_get_drvdata(pdev);
+	struct sh_timer_config *cfg = pdev->dev.platform_data;
 	int ret;
 
-	if (!is_early_platform_device(pdev))
-		pm_genpd_dev_always_on(&pdev->dev, true);
+	if (!is_early_platform_device(pdev)) {
+		pm_runtime_set_active(&pdev->dev);
+		pm_runtime_enable(&pdev->dev);
+	}
 
 	if (p) {
 		dev_info(&pdev->dev, "kept as earlytimer\n");
-		return 0;
+		goto out;
 	}
 
 	p = kmalloc(sizeof(*p), GFP_KERNEL);
@@ -708,8 +752,19 @@ static int __devinit sh_cmt_probe(struct platform_device *pdev)
 	if (ret) {
 		kfree(p);
 		platform_set_drvdata(pdev, NULL);
+		pm_runtime_idle(&pdev->dev);
+		return ret;
 	}
-	return ret;
+	if (is_early_platform_device(pdev))
+		return 0;
+
+ out:
+	if (cfg->clockevent_rating || cfg->clocksource_rating)
+		pm_runtime_irq_safe(&pdev->dev);
+	else
+		pm_runtime_idle(&pdev->dev);
+
+	return 0;
 }
 
 static int __devexit sh_cmt_remove(struct platform_device *pdev)
diff --git a/drivers/clocksource/sh_mtu2.c b/drivers/clocksource/sh_mtu2.c
index d9b76ca..c5eea85 100644
--- a/drivers/clocksource/sh_mtu2.c
+++ b/drivers/clocksource/sh_mtu2.c
@@ -32,6 +32,7 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/pm_domain.h>
+#include <linux/pm_runtime.h>
 
 struct sh_mtu2_priv {
 	void __iomem *mapbase;
@@ -123,6 +124,9 @@ static int sh_mtu2_enable(struct sh_mtu2_priv *p)
 {
 	int ret;
 
+	pm_runtime_get_sync(&p->pdev->dev);
+	dev_pm_syscore_device(&p->pdev->dev, true);
+
 	/* enable clock */
 	ret = clk_enable(p->clk);
 	if (ret) {
@@ -157,6 +161,9 @@ static void sh_mtu2_disable(struct sh_mtu2_priv *p)
 
 	/* stop clock */
 	clk_disable(p->clk);
+
+	dev_pm_syscore_device(&p->pdev->dev, false);
+	pm_runtime_put(&p->pdev->dev);
 }
 
 static irqreturn_t sh_mtu2_interrupt(int irq, void *dev_id)
@@ -208,6 +215,16 @@ static void sh_mtu2_clock_event_mode(enum clock_event_mode mode,
 	}
 }
 
+static void sh_mtu2_clock_event_suspend(struct clock_event_device *ced)
+{
+	pm_genpd_syscore_poweroff(&ced_to_sh_mtu2(ced)->pdev->dev);
+}
+
+static void sh_mtu2_clock_event_resume(struct clock_event_device *ced)
+{
+	pm_genpd_syscore_poweron(&ced_to_sh_mtu2(ced)->pdev->dev);
+}
+
 static void sh_mtu2_register_clockevent(struct sh_mtu2_priv *p,
 				       char *name, unsigned long rating)
 {
@@ -221,6 +238,8 @@ static void sh_mtu2_register_clockevent(struct sh_mtu2_priv *p,
 	ced->rating = rating;
 	ced->cpumask = cpumask_of(0);
 	ced->set_mode = sh_mtu2_clock_event_mode;
+	ced->suspend = sh_mtu2_clock_event_suspend;
+	ced->resume = sh_mtu2_clock_event_resume;
 
 	dev_info(&p->pdev->dev, "used for clock events\n");
 	clockevents_register_device(ced);
@@ -305,14 +324,17 @@ static int sh_mtu2_setup(struct sh_mtu2_priv *p, struct platform_device *pdev)
 static int __devinit sh_mtu2_probe(struct platform_device *pdev)
 {
 	struct sh_mtu2_priv *p = platform_get_drvdata(pdev);
+	struct sh_timer_config *cfg = pdev->dev.platform_data;
 	int ret;
 
-	if (!is_early_platform_device(pdev))
-		pm_genpd_dev_always_on(&pdev->dev, true);
+	if (!is_early_platform_device(pdev)) {
+		pm_runtime_set_active(&pdev->dev);
+		pm_runtime_enable(&pdev->dev);
+	}
 
 	if (p) {
 		dev_info(&pdev->dev, "kept as earlytimer\n");
-		return 0;
+		goto out;
 	}
 
 	p = kmalloc(sizeof(*p), GFP_KERNEL);
@@ -325,8 +347,19 @@ static int __devinit sh_mtu2_probe(struct platform_device *pdev)
 	if (ret) {
 		kfree(p);
 		platform_set_drvdata(pdev, NULL);
+		pm_runtime_idle(&pdev->dev);
+		return ret;
 	}
-	return ret;
+	if (is_early_platform_device(pdev))
+		return 0;
+
+ out:
+	if (cfg->clockevent_rating)
+		pm_runtime_irq_safe(&pdev->dev);
+	else
+		pm_runtime_idle(&pdev->dev);
+
+	return 0;
 }
 
 static int __devexit sh_mtu2_remove(struct platform_device *pdev)
diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c
index c1b51d4..0cc4add 100644
--- a/drivers/clocksource/sh_tmu.c
+++ b/drivers/clocksource/sh_tmu.c
@@ -33,6 +33,7 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/pm_domain.h>
+#include <linux/pm_runtime.h>
 
 struct sh_tmu_priv {
 	void __iomem *mapbase;
@@ -43,6 +44,8 @@ struct sh_tmu_priv {
 	unsigned long periodic;
 	struct clock_event_device ced;
 	struct clocksource cs;
+	bool cs_enabled;
+	unsigned int enable_count;
 };
 
 static DEFINE_RAW_SPINLOCK(sh_tmu_lock);
@@ -107,7 +110,7 @@ static void sh_tmu_start_stop_ch(struct sh_tmu_priv *p, int start)
 	raw_spin_unlock_irqrestore(&sh_tmu_lock, flags);
 }
 
-static int sh_tmu_enable(struct sh_tmu_priv *p)
+static int __sh_tmu_enable(struct sh_tmu_priv *p)
 {
 	int ret;
 
@@ -135,7 +138,18 @@ static int sh_tmu_enable(struct sh_tmu_priv *p)
 	return 0;
 }
 
-static void sh_tmu_disable(struct sh_tmu_priv *p)
+static int sh_tmu_enable(struct sh_tmu_priv *p)
+{
+	if (p->enable_count++ > 0)
+		return 0;
+
+	pm_runtime_get_sync(&p->pdev->dev);
+	dev_pm_syscore_device(&p->pdev->dev, true);
+
+	return __sh_tmu_enable(p);
+}
+
+static void __sh_tmu_disable(struct sh_tmu_priv *p)
 {
 	/* disable channel */
 	sh_tmu_start_stop_ch(p, 0);
@@ -147,6 +161,20 @@ static void sh_tmu_disable(struct sh_tmu_priv *p)
 	clk_disable(p->clk);
 }
 
+static void sh_tmu_disable(struct sh_tmu_priv *p)
+{
+	if (WARN_ON(p->enable_count == 0))
+		return;
+
+	if (--p->enable_count > 0)
+		return;
+
+	__sh_tmu_disable(p);
+
+	dev_pm_syscore_device(&p->pdev->dev, false);
+	pm_runtime_put(&p->pdev->dev);
+}
+
 static void sh_tmu_set_next(struct sh_tmu_priv *p, unsigned long delta,
 			    int periodic)
 {
@@ -203,15 +231,53 @@ static int sh_tmu_clocksource_enable(struct clocksource *cs)
 	struct sh_tmu_priv *p = cs_to_sh_tmu(cs);
 	int ret;
 
+	if (WARN_ON(p->cs_enabled))
+		return 0;
+
 	ret = sh_tmu_enable(p);
-	if (!ret)
+	if (!ret) {
 		__clocksource_updatefreq_hz(cs, p->rate);
+		p->cs_enabled = true;
+	}
+
 	return ret;
 }
 
 static void sh_tmu_clocksource_disable(struct clocksource *cs)
 {
-	sh_tmu_disable(cs_to_sh_tmu(cs));
+	struct sh_tmu_priv *p = cs_to_sh_tmu(cs);
+
+	if (WARN_ON(!p->cs_enabled))
+		return;
+
+	sh_tmu_disable(p);
+	p->cs_enabled = false;
+}
+
+static void sh_tmu_clocksource_suspend(struct clocksource *cs)
+{
+	struct sh_tmu_priv *p = cs_to_sh_tmu(cs);
+
+	if (!p->cs_enabled)
+		return;
+
+	if (--p->enable_count == 0) {
+		__sh_tmu_disable(p);
+		pm_genpd_syscore_poweroff(&p->pdev->dev);
+	}
+}
+
+static void sh_tmu_clocksource_resume(struct clocksource *cs)
+{
+	struct sh_tmu_priv *p = cs_to_sh_tmu(cs);
+
+	if (!p->cs_enabled)
+		return;
+
+	if (p->enable_count++ == 0) {
+		pm_genpd_syscore_poweron(&p->pdev->dev);
+		__sh_tmu_enable(p);
+	}
 }
 
 static int sh_tmu_register_clocksource(struct sh_tmu_priv *p,
@@ -224,6 +290,8 @@ static int sh_tmu_register_clocksource(struct sh_tmu_priv *p,
 	cs->read = sh_tmu_clocksource_read;
 	cs->enable = sh_tmu_clocksource_enable;
 	cs->disable = sh_tmu_clocksource_disable;
+	cs->suspend = sh_tmu_clocksource_suspend;
+	cs->resume = sh_tmu_clocksource_resume;
 	cs->mask = CLOCKSOURCE_MASK(32);
 	cs->flags = CLOCK_SOURCE_IS_CONTINUOUS;
 
@@ -301,6 +369,16 @@ static int sh_tmu_clock_event_next(unsigned long delta,
 	return 0;
 }
 
+static void sh_tmu_clock_event_suspend(struct clock_event_device *ced)
+{
+	pm_genpd_syscore_poweroff(&ced_to_sh_tmu(ced)->pdev->dev);
+}
+
+static void sh_tmu_clock_event_resume(struct clock_event_device *ced)
+{
+	pm_genpd_syscore_poweron(&ced_to_sh_tmu(ced)->pdev->dev);
+}
+
 static void sh_tmu_register_clockevent(struct sh_tmu_priv *p,
 				       char *name, unsigned long rating)
 {
@@ -316,6 +394,8 @@ static void sh_tmu_register_clockevent(struct sh_tmu_priv *p,
 	ced->cpumask = cpumask_of(0);
 	ced->set_next_event = sh_tmu_clock_event_next;
 	ced->set_mode = sh_tmu_clock_event_mode;
+	ced->suspend = sh_tmu_clock_event_suspend;
+	ced->resume = sh_tmu_clock_event_resume;
 
 	dev_info(&p->pdev->dev, "used for clock events\n");
 
@@ -392,6 +472,8 @@ static int sh_tmu_setup(struct sh_tmu_priv *p, struct platform_device *pdev)
 		ret = PTR_ERR(p->clk);
 		goto err1;
 	}
+	p->cs_enabled = false;
+	p->enable_count = 0;
 
 	return sh_tmu_register(p, (char *)dev_name(&p->pdev->dev),
 			       cfg->clockevent_rating,
@@ -405,14 +487,17 @@ static int sh_tmu_setup(struct sh_tmu_priv *p, struct platform_device *pdev)
 static int __devinit sh_tmu_probe(struct platform_device *pdev)
 {
 	struct sh_tmu_priv *p = platform_get_drvdata(pdev);
+	struct sh_timer_config *cfg = pdev->dev.platform_data;
 	int ret;
 
-	if (!is_early_platform_device(pdev))
-		pm_genpd_dev_always_on(&pdev->dev, true);
+	if (!is_early_platform_device(pdev)) {
+		pm_runtime_set_active(&pdev->dev);
+		pm_runtime_enable(&pdev->dev);
+	}
 
 	if (p) {
 		dev_info(&pdev->dev, "kept as earlytimer\n");
-		return 0;
+		goto out;
 	}
 
 	p = kmalloc(sizeof(*p), GFP_KERNEL);
@@ -425,8 +510,19 @@ static int __devinit sh_tmu_probe(struct platform_device *pdev)
 	if (ret) {
 		kfree(p);
 		platform_set_drvdata(pdev, NULL);
+		pm_runtime_idle(&pdev->dev);
+		return ret;
 	}
-	return ret;
+	if (is_early_platform_device(pdev))
+		return 0;
+
+ out:
+	if (cfg->clockevent_rating || cfg->clocksource_rating)
+		pm_runtime_irq_safe(&pdev->dev);
+	else
+		pm_runtime_idle(&pdev->dev);
+
+	return 0;
 }
 
 static int __devexit sh_tmu_remove(struct platform_device *pdev)
diff --git a/drivers/connector/cn_proc.c b/drivers/connector/cn_proc.c
index 3e92b7d..fce2000 100644
--- a/drivers/connector/cn_proc.c
+++ b/drivers/connector/cn_proc.c
@@ -30,6 +30,7 @@
 #include <linux/gfp.h>
 #include <linux/ptrace.h>
 #include <linux/atomic.h>
+#include <linux/pid_namespace.h>
 
 #include <asm/unaligned.h>
 
@@ -127,11 +128,11 @@ void proc_id_connector(struct task_struct *task, int which_id)
 	rcu_read_lock();
 	cred = __task_cred(task);
 	if (which_id == PROC_EVENT_UID) {
-		ev->event_data.id.r.ruid = cred->uid;
-		ev->event_data.id.e.euid = cred->euid;
+		ev->event_data.id.r.ruid = from_kuid_munged(&init_user_ns, cred->uid);
+		ev->event_data.id.e.euid = from_kuid_munged(&init_user_ns, cred->euid);
 	} else if (which_id == PROC_EVENT_GID) {
-		ev->event_data.id.r.rgid = cred->gid;
-		ev->event_data.id.e.egid = cred->egid;
+		ev->event_data.id.r.rgid = from_kgid_munged(&init_user_ns, cred->gid);
+		ev->event_data.id.e.egid = from_kgid_munged(&init_user_ns, cred->egid);
 	} else {
 		rcu_read_unlock();
 		return;
@@ -303,6 +304,15 @@ static void cn_proc_mcast_ctl(struct cn_msg *msg,
 	if (msg->len != sizeof(*mc_op))
 		return;
 
+	/* 
+	 * Events are reported with respect to the initial pid
+	 * and user namespaces so ignore requestors from
+	 * other namespaces.
+	 */
+	if ((current_user_ns() != &init_user_ns) ||
+	    (task_active_pid_ns(current) != &init_pid_ns))
+		return;
+
 	mc_op = (enum proc_cn_mcast_op *)msg->data;
 	switch (*mc_op) {
 	case PROC_CN_MCAST_LISTEN:
diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c
index 82fa4f0..965b781 100644
--- a/drivers/connector/connector.c
+++ b/drivers/connector/connector.c
@@ -264,8 +264,7 @@ static int __devinit cn_init(void)
 		.input	= dev->input,
 	};
 
-	dev->nls = netlink_kernel_create(&init_net, NETLINK_CONNECTOR,
-					 THIS_MODULE, &cfg);
+	dev->nls = netlink_kernel_create(&init_net, NETLINK_CONNECTOR, &cfg);
 	if (!dev->nls)
 		return -EIO;
 
diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig
index e24a2a1..ea512f4 100644
--- a/drivers/cpufreq/Kconfig
+++ b/drivers/cpufreq/Kconfig
@@ -179,6 +179,17 @@ config CPU_FREQ_GOV_CONSERVATIVE
 
 	  If in doubt, say N.
 
+config GENERIC_CPUFREQ_CPU0
+	bool "Generic CPU0 cpufreq driver"
+	depends on HAVE_CLK && REGULATOR && PM_OPP && OF
+	select CPU_FREQ_TABLE
+	help
+	  This adds a generic cpufreq driver for CPU0 frequency management.
+	  It supports both uniprocessor (UP) and symmetric multiprocessor (SMP)
+	  systems which share clock and voltage across all CPUs.
+
+	  If in doubt, say N.
+
 menu "x86 CPU frequency scaling drivers"
 depends on X86
 source "drivers/cpufreq/Kconfig.x86"
diff --git a/drivers/cpufreq/Kconfig.x86 b/drivers/cpufreq/Kconfig.x86
index 78ff7ee..934854a 100644
--- a/drivers/cpufreq/Kconfig.x86
+++ b/drivers/cpufreq/Kconfig.x86
@@ -23,7 +23,8 @@ config X86_ACPI_CPUFREQ
 	help
 	  This driver adds a CPUFreq driver which utilizes the ACPI
 	  Processor Performance States.
-	  This driver also supports Intel Enhanced Speedstep.
+	  This driver also supports Intel Enhanced Speedstep and newer
+	  AMD CPUs.
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called acpi-cpufreq.
@@ -32,6 +33,18 @@ config X86_ACPI_CPUFREQ
 
 	  If in doubt, say N.
 
+config X86_ACPI_CPUFREQ_CPB
+	default y
+	bool "Legacy cpb sysfs knob support for AMD CPUs"
+	depends on X86_ACPI_CPUFREQ && CPU_SUP_AMD
+	help
+	  The powernow-k8 driver used to provide a sysfs knob called "cpb"
+	  to disable the Core Performance Boosting feature of AMD CPUs. This
+	  file has now been superseeded by the more generic "boost" entry.
+
+	  By enabling this option the acpi_cpufreq driver provides the old
+	  entry in addition to the new boost ones, for compatibility reasons.
+
 config ELAN_CPUFREQ
 	tristate "AMD Elan SC400 and SC410"
 	select CPU_FREQ_TABLE
@@ -95,7 +108,8 @@ config X86_POWERNOW_K8
 	select CPU_FREQ_TABLE
 	depends on ACPI && ACPI_PROCESSOR
 	help
-	  This adds the CPUFreq driver for K8/K10 Opteron/Athlon64 processors.
+	  This adds the CPUFreq driver for K8/early Opteron/Athlon64 processors.
+	  Support for K10 and newer processors is now in acpi-cpufreq.
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called powernow-k8.
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index 9531fc2..1bc90e1 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -13,13 +13,15 @@ obj-$(CONFIG_CPU_FREQ_GOV_CONSERVATIVE)	+= cpufreq_conservative.o
 # CPUfreq cross-arch helpers
 obj-$(CONFIG_CPU_FREQ_TABLE)		+= freq_table.o
 
+obj-$(CONFIG_GENERIC_CPUFREQ_CPU0)	+= cpufreq-cpu0.o
+
 ##################################################################################
 # x86 drivers.
 # Link order matters. K8 is preferred to ACPI because of firmware bugs in early
 # K8 systems. ACPI is preferred to all other hardware-specific drivers.
 # speedstep-* is preferred over p4-clockmod.
 
-obj-$(CONFIG_X86_POWERNOW_K8)		+= powernow-k8.o mperf.o
+obj-$(CONFIG_X86_POWERNOW_K8)		+= powernow-k8.o
 obj-$(CONFIG_X86_ACPI_CPUFREQ)		+= acpi-cpufreq.o mperf.o
 obj-$(CONFIG_X86_PCC_CPUFREQ)		+= pcc-cpufreq.o
 obj-$(CONFIG_X86_POWERNOW_K6)		+= powernow-k6.o
diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c
index 56c6c6b..0d048f6 100644
--- a/drivers/cpufreq/acpi-cpufreq.c
+++ b/drivers/cpufreq/acpi-cpufreq.c
@@ -51,13 +51,19 @@ MODULE_AUTHOR("Paul Diefenbaugh, Dominik Brodowski");
 MODULE_DESCRIPTION("ACPI Processor P-States Driver");
 MODULE_LICENSE("GPL");
 
+#define PFX "acpi-cpufreq: "
+
 enum {
 	UNDEFINED_CAPABLE = 0,
 	SYSTEM_INTEL_MSR_CAPABLE,
+	SYSTEM_AMD_MSR_CAPABLE,
 	SYSTEM_IO_CAPABLE,
 };
 
 #define INTEL_MSR_RANGE		(0xffff)
+#define AMD_MSR_RANGE		(0x7)
+
+#define MSR_K7_HWCR_CPB_DIS	(1ULL << 25)
 
 struct acpi_cpufreq_data {
 	struct acpi_processor_performance *acpi_data;
@@ -74,6 +80,116 @@ static struct acpi_processor_performance __percpu *acpi_perf_data;
 static struct cpufreq_driver acpi_cpufreq_driver;
 
 static unsigned int acpi_pstate_strict;
+static bool boost_enabled, boost_supported;
+static struct msr __percpu *msrs;
+
+static bool boost_state(unsigned int cpu)
+{
+	u32 lo, hi;
+	u64 msr;
+
+	switch (boot_cpu_data.x86_vendor) {
+	case X86_VENDOR_INTEL:
+		rdmsr_on_cpu(cpu, MSR_IA32_MISC_ENABLE, &lo, &hi);
+		msr = lo | ((u64)hi << 32);
+		return !(msr & MSR_IA32_MISC_ENABLE_TURBO_DISABLE);
+	case X86_VENDOR_AMD:
+		rdmsr_on_cpu(cpu, MSR_K7_HWCR, &lo, &hi);
+		msr = lo | ((u64)hi << 32);
+		return !(msr & MSR_K7_HWCR_CPB_DIS);
+	}
+	return false;
+}
+
+static void boost_set_msrs(bool enable, const struct cpumask *cpumask)
+{
+	u32 cpu;
+	u32 msr_addr;
+	u64 msr_mask;
+
+	switch (boot_cpu_data.x86_vendor) {
+	case X86_VENDOR_INTEL:
+		msr_addr = MSR_IA32_MISC_ENABLE;
+		msr_mask = MSR_IA32_MISC_ENABLE_TURBO_DISABLE;
+		break;
+	case X86_VENDOR_AMD:
+		msr_addr = MSR_K7_HWCR;
+		msr_mask = MSR_K7_HWCR_CPB_DIS;
+		break;
+	default:
+		return;
+	}
+
+	rdmsr_on_cpus(cpumask, msr_addr, msrs);
+
+	for_each_cpu(cpu, cpumask) {
+		struct msr *reg = per_cpu_ptr(msrs, cpu);
+		if (enable)
+			reg->q &= ~msr_mask;
+		else
+			reg->q |= msr_mask;
+	}
+
+	wrmsr_on_cpus(cpumask, msr_addr, msrs);
+}
+
+static ssize_t _store_boost(const char *buf, size_t count)
+{
+	int ret;
+	unsigned long val = 0;
+
+	if (!boost_supported)
+		return -EINVAL;
+
+	ret = kstrtoul(buf, 10, &val);
+	if (ret || (val > 1))
+		return -EINVAL;
+
+	if ((val && boost_enabled) || (!val && !boost_enabled))
+		return count;
+
+	get_online_cpus();
+
+	boost_set_msrs(val, cpu_online_mask);
+
+	put_online_cpus();
+
+	boost_enabled = val;
+	pr_debug("Core Boosting %sabled.\n", val ? "en" : "dis");
+
+	return count;
+}
+
+static ssize_t store_global_boost(struct kobject *kobj, struct attribute *attr,
+				  const char *buf, size_t count)
+{
+	return _store_boost(buf, count);
+}
+
+static ssize_t show_global_boost(struct kobject *kobj,
+				 struct attribute *attr, char *buf)
+{
+	return sprintf(buf, "%u\n", boost_enabled);
+}
+
+static struct global_attr global_boost = __ATTR(boost, 0644,
+						show_global_boost,
+						store_global_boost);
+
+#ifdef CONFIG_X86_ACPI_CPUFREQ_CPB
+static ssize_t store_cpb(struct cpufreq_policy *policy, const char *buf,
+			 size_t count)
+{
+	return _store_boost(buf, count);
+}
+
+static ssize_t show_cpb(struct cpufreq_policy *policy, char *buf)
+{
+	return sprintf(buf, "%u\n", boost_enabled);
+}
+
+static struct freq_attr cpb = __ATTR(cpb, 0644, show_cpb, store_cpb);
+#endif
 
 static int check_est_cpu(unsigned int cpuid)
 {
@@ -82,6 +198,13 @@ static int check_est_cpu(unsigned int cpuid)
 	return cpu_has(cpu, X86_FEATURE_EST);
 }
 
+static int check_amd_hwpstate_cpu(unsigned int cpuid)
+{
+	struct cpuinfo_x86 *cpu = &cpu_data(cpuid);
+
+	return cpu_has(cpu, X86_FEATURE_HW_PSTATE);
+}
+
 static unsigned extract_io(u32 value, struct acpi_cpufreq_data *data)
 {
 	struct acpi_processor_performance *perf;
@@ -101,7 +224,11 @@ static unsigned extract_msr(u32 msr, struct acpi_cpufreq_data *data)
 	int i;
 	struct acpi_processor_performance *perf;
 
-	msr &= INTEL_MSR_RANGE;
+	if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD)
+		msr &= AMD_MSR_RANGE;
+	else
+		msr &= INTEL_MSR_RANGE;
+
 	perf = data->acpi_data;
 
 	for (i = 0; data->freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
@@ -115,6 +242,7 @@ static unsigned extract_freq(u32 val, struct acpi_cpufreq_data *data)
 {
 	switch (data->cpu_feature) {
 	case SYSTEM_INTEL_MSR_CAPABLE:
+	case SYSTEM_AMD_MSR_CAPABLE:
 		return extract_msr(val, data);
 	case SYSTEM_IO_CAPABLE:
 		return extract_io(val, data);
@@ -150,6 +278,7 @@ static void do_drv_read(void *_cmd)
 
 	switch (cmd->type) {
 	case SYSTEM_INTEL_MSR_CAPABLE:
+	case SYSTEM_AMD_MSR_CAPABLE:
 		rdmsr(cmd->addr.msr.reg, cmd->val, h);
 		break;
 	case SYSTEM_IO_CAPABLE:
@@ -174,6 +303,9 @@ static void do_drv_write(void *_cmd)
 		lo = (lo & ~INTEL_MSR_RANGE) | (cmd->val & INTEL_MSR_RANGE);
 		wrmsr(cmd->addr.msr.reg, lo, hi);
 		break;
+	case SYSTEM_AMD_MSR_CAPABLE:
+		wrmsr(cmd->addr.msr.reg, cmd->val, 0);
+		break;
 	case SYSTEM_IO_CAPABLE:
 		acpi_os_write_port((acpi_io_address)cmd->addr.io.port,
 				cmd->val,
@@ -217,6 +349,10 @@ static u32 get_cur_val(const struct cpumask *mask)
 		cmd.type = SYSTEM_INTEL_MSR_CAPABLE;
 		cmd.addr.msr.reg = MSR_IA32_PERF_STATUS;
 		break;
+	case SYSTEM_AMD_MSR_CAPABLE:
+		cmd.type = SYSTEM_AMD_MSR_CAPABLE;
+		cmd.addr.msr.reg = MSR_AMD_PERF_STATUS;
+		break;
 	case SYSTEM_IO_CAPABLE:
 		cmd.type = SYSTEM_IO_CAPABLE;
 		perf = per_cpu(acfreq_data, cpumask_first(mask))->acpi_data;
@@ -326,6 +462,11 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy,
 		cmd.addr.msr.reg = MSR_IA32_PERF_CTL;
 		cmd.val = (u32) perf->states[next_perf_state].control;
 		break;
+	case SYSTEM_AMD_MSR_CAPABLE:
+		cmd.type = SYSTEM_AMD_MSR_CAPABLE;
+		cmd.addr.msr.reg = MSR_AMD_PERF_CTL;
+		cmd.val = (u32) perf->states[next_perf_state].control;
+		break;
 	case SYSTEM_IO_CAPABLE:
 		cmd.type = SYSTEM_IO_CAPABLE;
 		cmd.addr.io.port = perf->control_register.address;
@@ -419,6 +560,44 @@ static void free_acpi_perf_data(void)
 	free_percpu(acpi_perf_data);
 }
 
+static int boost_notify(struct notifier_block *nb, unsigned long action,
+		      void *hcpu)
+{
+	unsigned cpu = (long)hcpu;
+	const struct cpumask *cpumask;
+
+	cpumask = get_cpu_mask(cpu);
+
+	/*
+	 * Clear the boost-disable bit on the CPU_DOWN path so that
+	 * this cpu cannot block the remaining ones from boosting. On
+	 * the CPU_UP path we simply keep the boost-disable flag in
+	 * sync with the current global state.
+	 */
+
+	switch (action) {
+	case CPU_UP_PREPARE:
+	case CPU_UP_PREPARE_FROZEN:
+		boost_set_msrs(boost_enabled, cpumask);
+		break;
+
+	case CPU_DOWN_PREPARE:
+	case CPU_DOWN_PREPARE_FROZEN:
+		boost_set_msrs(1, cpumask);
+		break;
+
+	default:
+		break;
+	}
+
+	return NOTIFY_OK;
+}
+
+
+static struct notifier_block boost_nb = {
+	.notifier_call          = boost_notify,
+};
+
 /*
  * acpi_cpufreq_early_init - initialize ACPI P-States library
  *
@@ -559,6 +738,14 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
 		policy->shared_type = CPUFREQ_SHARED_TYPE_ALL;
 		cpumask_copy(policy->cpus, cpu_core_mask(cpu));
 	}
+
+	if (check_amd_hwpstate_cpu(cpu) && !acpi_pstate_strict) {
+		cpumask_clear(policy->cpus);
+		cpumask_set_cpu(cpu, policy->cpus);
+		cpumask_copy(policy->related_cpus, cpu_sibling_mask(cpu));
+		policy->shared_type = CPUFREQ_SHARED_TYPE_HW;
+		pr_info_once(PFX "overriding BIOS provided _PSD data\n");
+	}
 #endif
 
 	/* capability check */
@@ -580,12 +767,16 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
 		break;
 	case ACPI_ADR_SPACE_FIXED_HARDWARE:
 		pr_debug("HARDWARE addr space\n");
-		if (!check_est_cpu(cpu)) {
-			result = -ENODEV;
-			goto err_unreg;
+		if (check_est_cpu(cpu)) {
+			data->cpu_feature = SYSTEM_INTEL_MSR_CAPABLE;
+			break;
 		}
-		data->cpu_feature = SYSTEM_INTEL_MSR_CAPABLE;
-		break;
+		if (check_amd_hwpstate_cpu(cpu)) {
+			data->cpu_feature = SYSTEM_AMD_MSR_CAPABLE;
+			break;
+		}
+		result = -ENODEV;
+		goto err_unreg;
 	default:
 		pr_debug("Unknown addr space %d\n",
 			(u32) (perf->control_register.space_id));
@@ -718,6 +909,7 @@ static int acpi_cpufreq_resume(struct cpufreq_policy *policy)
 
 static struct freq_attr *acpi_cpufreq_attr[] = {
 	&cpufreq_freq_attr_scaling_available_freqs,
+	NULL,	/* this is a placeholder for cpb, do not remove */
 	NULL,
 };
 
@@ -733,6 +925,49 @@ static struct cpufreq_driver acpi_cpufreq_driver = {
 	.attr		= acpi_cpufreq_attr,
 };
 
+static void __init acpi_cpufreq_boost_init(void)
+{
+	if (boot_cpu_has(X86_FEATURE_CPB) || boot_cpu_has(X86_FEATURE_IDA)) {
+		msrs = msrs_alloc();
+
+		if (!msrs)
+			return;
+
+		boost_supported = true;
+		boost_enabled = boost_state(0);
+
+		get_online_cpus();
+
+		/* Force all MSRs to the same value */
+		boost_set_msrs(boost_enabled, cpu_online_mask);
+
+		register_cpu_notifier(&boost_nb);
+
+		put_online_cpus();
+	} else
+		global_boost.attr.mode = 0444;
+
+	/* We create the boost file in any case, though for systems without
+	 * hardware support it will be read-only and hardwired to return 0.
+	 */
+	if (sysfs_create_file(cpufreq_global_kobject, &(global_boost.attr)))
+		pr_warn(PFX "could not register global boost sysfs file\n");
+	else
+		pr_debug("registered global boost sysfs file\n");
+}
+
+static void __exit acpi_cpufreq_boost_exit(void)
+{
+	sysfs_remove_file(cpufreq_global_kobject, &(global_boost.attr));
+
+	if (msrs) {
+		unregister_cpu_notifier(&boost_nb);
+
+		msrs_free(msrs);
+		msrs = NULL;
+	}
+}
+
 static int __init acpi_cpufreq_init(void)
 {
 	int ret;
@@ -746,9 +981,32 @@ static int __init acpi_cpufreq_init(void)
 	if (ret)
 		return ret;
 
+#ifdef CONFIG_X86_ACPI_CPUFREQ_CPB
+	/* this is a sysfs file with a strange name and an even stranger
+	 * semantic - per CPU instantiation, but system global effect.
+	 * Lets enable it only on AMD CPUs for compatibility reasons and
+	 * only if configured. This is considered legacy code, which
+	 * will probably be removed at some point in the future.
+	 */
+	if (check_amd_hwpstate_cpu(0)) {
+		struct freq_attr **iter;
+
+		pr_debug("adding sysfs entry for cpb\n");
+
+		for (iter = acpi_cpufreq_attr; *iter != NULL; iter++)
+			;
+
+		/* make sure there is a terminator behind it */
+		if (iter[1] == NULL)
+			*iter = &cpb;
+	}
+#endif
+
 	ret = cpufreq_register_driver(&acpi_cpufreq_driver);
 	if (ret)
 		free_acpi_perf_data();
+	else
+		acpi_cpufreq_boost_init();
 
 	return ret;
 }
@@ -757,6 +1015,8 @@ static void __exit acpi_cpufreq_exit(void)
 {
 	pr_debug("acpi_cpufreq_exit\n");
 
+	acpi_cpufreq_boost_exit();
+
 	cpufreq_unregister_driver(&acpi_cpufreq_driver);
 
 	free_acpi_perf_data();
diff --git a/drivers/cpufreq/cpufreq-cpu0.c b/drivers/cpufreq/cpufreq-cpu0.c
new file mode 100644
index 0000000..e915827
--- /dev/null
+++ b/drivers/cpufreq/cpufreq-cpu0.c
@@ -0,0 +1,269 @@
+/*
+ * Copyright (C) 2012 Freescale Semiconductor, Inc.
+ *
+ * The OPP code in function cpu0_set_target() is reused from
+ * drivers/cpufreq/omap-cpufreq.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.
+ */
+
+#define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
+
+#include <linux/clk.h>
+#include <linux/cpu.h>
+#include <linux/cpufreq.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/opp.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+
+static unsigned int transition_latency;
+static unsigned int voltage_tolerance; /* in percentage */
+
+static struct device *cpu_dev;
+static struct clk *cpu_clk;
+static struct regulator *cpu_reg;
+static struct cpufreq_frequency_table *freq_table;
+
+static int cpu0_verify_speed(struct cpufreq_policy *policy)
+{
+	return cpufreq_frequency_table_verify(policy, freq_table);
+}
+
+static unsigned int cpu0_get_speed(unsigned int cpu)
+{
+	return clk_get_rate(cpu_clk) / 1000;
+}
+
+static int cpu0_set_target(struct cpufreq_policy *policy,
+			   unsigned int target_freq, unsigned int relation)
+{
+	struct cpufreq_freqs freqs;
+	struct opp *opp;
+	unsigned long freq_Hz, volt = 0, volt_old = 0, tol = 0;
+	unsigned int index, cpu;
+	int ret;
+
+	ret = cpufreq_frequency_table_target(policy, freq_table, target_freq,
+					     relation, &index);
+	if (ret) {
+		pr_err("failed to match target freqency %d: %d\n",
+		       target_freq, ret);
+		return ret;
+	}
+
+	freq_Hz = clk_round_rate(cpu_clk, freq_table[index].frequency * 1000);
+	if (freq_Hz < 0)
+		freq_Hz = freq_table[index].frequency * 1000;
+	freqs.new = freq_Hz / 1000;
+	freqs.old = clk_get_rate(cpu_clk) / 1000;
+
+	if (freqs.old == freqs.new)
+		return 0;
+
+	for_each_online_cpu(cpu) {
+		freqs.cpu = cpu;
+		cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+	}
+
+	if (cpu_reg) {
+		opp = opp_find_freq_ceil(cpu_dev, &freq_Hz);
+		if (IS_ERR(opp)) {
+			pr_err("failed to find OPP for %ld\n", freq_Hz);
+			return PTR_ERR(opp);
+		}
+		volt = opp_get_voltage(opp);
+		tol = volt * voltage_tolerance / 100;
+		volt_old = regulator_get_voltage(cpu_reg);
+	}
+
+	pr_debug("%u MHz, %ld mV --> %u MHz, %ld mV\n",
+		 freqs.old / 1000, volt_old ? volt_old / 1000 : -1,
+		 freqs.new / 1000, volt ? volt / 1000 : -1);
+
+	/* scaling up?  scale voltage before frequency */
+	if (cpu_reg && freqs.new > freqs.old) {
+		ret = regulator_set_voltage_tol(cpu_reg, volt, tol);
+		if (ret) {
+			pr_err("failed to scale voltage up: %d\n", ret);
+			freqs.new = freqs.old;
+			return ret;
+		}
+	}
+
+	ret = clk_set_rate(cpu_clk, freqs.new * 1000);
+	if (ret) {
+		pr_err("failed to set clock rate: %d\n", ret);
+		if (cpu_reg)
+			regulator_set_voltage_tol(cpu_reg, volt_old, tol);
+		return ret;
+	}
+
+	/* scaling down?  scale voltage after frequency */
+	if (cpu_reg && freqs.new < freqs.old) {
+		ret = regulator_set_voltage_tol(cpu_reg, volt, tol);
+		if (ret) {
+			pr_err("failed to scale voltage down: %d\n", ret);
+			clk_set_rate(cpu_clk, freqs.old * 1000);
+			freqs.new = freqs.old;
+			return ret;
+		}
+	}
+
+	for_each_online_cpu(cpu) {
+		freqs.cpu = cpu;
+		cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+	}
+
+	return 0;
+}
+
+static int cpu0_cpufreq_init(struct cpufreq_policy *policy)
+{
+	int ret;
+
+	if (policy->cpu != 0)
+		return -EINVAL;
+
+	ret = cpufreq_frequency_table_cpuinfo(policy, freq_table);
+	if (ret) {
+		pr_err("invalid frequency table: %d\n", ret);
+		return ret;
+	}
+
+	policy->cpuinfo.transition_latency = transition_latency;
+	policy->cur = clk_get_rate(cpu_clk) / 1000;
+
+	/*
+	 * The driver only supports the SMP configuartion where all processors
+	 * share the clock and voltage and clock.  Use cpufreq affected_cpus
+	 * interface to have all CPUs scaled together.
+	 */
+	policy->shared_type = CPUFREQ_SHARED_TYPE_ANY;
+	cpumask_setall(policy->cpus);
+
+	cpufreq_frequency_table_get_attr(freq_table, policy->cpu);
+
+	return 0;
+}
+
+static int cpu0_cpufreq_exit(struct cpufreq_policy *policy)
+{
+	cpufreq_frequency_table_put_attr(policy->cpu);
+
+	return 0;
+}
+
+static struct freq_attr *cpu0_cpufreq_attr[] = {
+	&cpufreq_freq_attr_scaling_available_freqs,
+	NULL,
+};
+
+static struct cpufreq_driver cpu0_cpufreq_driver = {
+	.flags = CPUFREQ_STICKY,
+	.verify = cpu0_verify_speed,
+	.target = cpu0_set_target,
+	.get = cpu0_get_speed,
+	.init = cpu0_cpufreq_init,
+	.exit = cpu0_cpufreq_exit,
+	.name = "generic_cpu0",
+	.attr = cpu0_cpufreq_attr,
+};
+
+static int __devinit cpu0_cpufreq_driver_init(void)
+{
+	struct device_node *np;
+	int ret;
+
+	np = of_find_node_by_path("/cpus/cpu@0");
+	if (!np) {
+		pr_err("failed to find cpu0 node\n");
+		return -ENOENT;
+	}
+
+	cpu_dev = get_cpu_device(0);
+	if (!cpu_dev) {
+		pr_err("failed to get cpu0 device\n");
+		ret = -ENODEV;
+		goto out_put_node;
+	}
+
+	cpu_dev->of_node = np;
+
+	cpu_clk = clk_get(cpu_dev, NULL);
+	if (IS_ERR(cpu_clk)) {
+		ret = PTR_ERR(cpu_clk);
+		pr_err("failed to get cpu0 clock: %d\n", ret);
+		goto out_put_node;
+	}
+
+	cpu_reg = regulator_get(cpu_dev, "cpu0");
+	if (IS_ERR(cpu_reg)) {
+		pr_warn("failed to get cpu0 regulator\n");
+		cpu_reg = NULL;
+	}
+
+	ret = of_init_opp_table(cpu_dev);
+	if (ret) {
+		pr_err("failed to init OPP table: %d\n", ret);
+		goto out_put_node;
+	}
+
+	ret = opp_init_cpufreq_table(cpu_dev, &freq_table);
+	if (ret) {
+		pr_err("failed to init cpufreq table: %d\n", ret);
+		goto out_put_node;
+	}
+
+	of_property_read_u32(np, "voltage-tolerance", &voltage_tolerance);
+
+	if (of_property_read_u32(np, "clock-latency", &transition_latency))
+		transition_latency = CPUFREQ_ETERNAL;
+
+	if (cpu_reg) {
+		struct opp *opp;
+		unsigned long min_uV, max_uV;
+		int i;
+
+		/*
+		 * OPP is maintained in order of increasing frequency, and
+		 * freq_table initialised from OPP is therefore sorted in the
+		 * same order.
+		 */
+		for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++)
+			;
+		opp = opp_find_freq_exact(cpu_dev,
+				freq_table[0].frequency * 1000, true);
+		min_uV = opp_get_voltage(opp);
+		opp = opp_find_freq_exact(cpu_dev,
+				freq_table[i-1].frequency * 1000, true);
+		max_uV = opp_get_voltage(opp);
+		ret = regulator_set_voltage_time(cpu_reg, min_uV, max_uV);
+		if (ret > 0)
+			transition_latency += ret * 1000;
+	}
+
+	ret = cpufreq_register_driver(&cpu0_cpufreq_driver);
+	if (ret) {
+		pr_err("failed register driver: %d\n", ret);
+		goto out_free_table;
+	}
+
+	of_node_put(np);
+	return 0;
+
+out_free_table:
+	opp_free_cpufreq_table(cpu_dev, &freq_table);
+out_put_node:
+	of_node_put(np);
+	return ret;
+}
+late_initcall(cpu0_cpufreq_driver_init);
+
+MODULE_AUTHOR("Shawn Guo <shawn.guo@linaro.org>");
+MODULE_DESCRIPTION("Generic CPU0 cpufreq driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c
index 235a340..a152af7 100644
--- a/drivers/cpufreq/cpufreq_conservative.c
+++ b/drivers/cpufreq/cpufreq_conservative.c
@@ -466,7 +466,7 @@ static inline void dbs_timer_init(struct cpu_dbs_info_s *dbs_info)
 	delay -= jiffies % delay;
 
 	dbs_info->enable = 1;
-	INIT_DELAYED_WORK_DEFERRABLE(&dbs_info->work, do_dbs_timer);
+	INIT_DEFERRABLE_WORK(&dbs_info->work, do_dbs_timer);
 	schedule_delayed_work_on(dbs_info->cpu, &dbs_info->work, delay);
 }
 
@@ -504,6 +504,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
 				j_dbs_info->prev_cpu_nice =
 						kcpustat_cpu(j).cpustat[CPUTIME_NICE];
 		}
+		this_dbs_info->cpu = cpu;
 		this_dbs_info->down_skip = 0;
 		this_dbs_info->requested_freq = policy->cur;
 
@@ -583,6 +584,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
 			__cpufreq_driver_target(
 					this_dbs_info->cur_policy,
 					policy->min, CPUFREQ_RELATION_L);
+		dbs_check_cpu(this_dbs_info);
 		mutex_unlock(&this_dbs_info->timer_mutex);
 
 		break;
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index 836e9b0..396322f 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -644,7 +644,7 @@ static inline void dbs_timer_init(struct cpu_dbs_info_s *dbs_info)
 		delay -= jiffies % delay;
 
 	dbs_info->sample_type = DBS_NORMAL_SAMPLE;
-	INIT_DELAYED_WORK_DEFERRABLE(&dbs_info->work, do_dbs_timer);
+	INIT_DEFERRABLE_WORK(&dbs_info->work, do_dbs_timer);
 	schedule_delayed_work_on(dbs_info->cpu, &dbs_info->work, delay);
 }
 
@@ -761,6 +761,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
 		else if (policy->min > this_dbs_info->cur_policy->cur)
 			__cpufreq_driver_target(this_dbs_info->cur_policy,
 				policy->min, CPUFREQ_RELATION_L);
+		dbs_check_cpu(this_dbs_info);
 		mutex_unlock(&this_dbs_info->timer_mutex);
 		break;
 	}
diff --git a/drivers/cpufreq/longhaul.h b/drivers/cpufreq/longhaul.h
index cbf48fb..e2dc436 100644
--- a/drivers/cpufreq/longhaul.h
+++ b/drivers/cpufreq/longhaul.h
@@ -56,7 +56,7 @@ union msr_longhaul {
 /*
  * VIA C3 Samuel 1  & Samuel 2 (stepping 0)
  */
-static const int __cpuinitdata samuel1_mults[16] = {
+static const int __cpuinitconst samuel1_mults[16] = {
 	-1, /* 0000 -> RESERVED */
 	30, /* 0001 ->  3.0x */
 	40, /* 0010 ->  4.0x */
@@ -75,7 +75,7 @@ static const int __cpuinitdata samuel1_mults[16] = {
 	-1, /* 1111 -> RESERVED */
 };
 
-static const int __cpuinitdata samuel1_eblcr[16] = {
+static const int __cpuinitconst samuel1_eblcr[16] = {
 	50, /* 0000 -> RESERVED */
 	30, /* 0001 ->  3.0x */
 	40, /* 0010 ->  4.0x */
@@ -97,7 +97,7 @@ static const int __cpuinitdata samuel1_eblcr[16] = {
 /*
  * VIA C3 Samuel2 Stepping 1->15
  */
-static const int __cpuinitdata samuel2_eblcr[16] = {
+static const int __cpuinitconst samuel2_eblcr[16] = {
 	50,  /* 0000 ->  5.0x */
 	30,  /* 0001 ->  3.0x */
 	40,  /* 0010 ->  4.0x */
@@ -119,7 +119,7 @@ static const int __cpuinitdata samuel2_eblcr[16] = {
 /*
  * VIA C3 Ezra
  */
-static const int __cpuinitdata ezra_mults[16] = {
+static const int __cpuinitconst ezra_mults[16] = {
 	100, /* 0000 -> 10.0x */
 	30,  /* 0001 ->  3.0x */
 	40,  /* 0010 ->  4.0x */
@@ -138,7 +138,7 @@ static const int __cpuinitdata ezra_mults[16] = {
 	120, /* 1111 -> 12.0x */
 };
 
-static const int __cpuinitdata ezra_eblcr[16] = {
+static const int __cpuinitconst ezra_eblcr[16] = {
 	50,  /* 0000 ->  5.0x */
 	30,  /* 0001 ->  3.0x */
 	40,  /* 0010 ->  4.0x */
@@ -160,7 +160,7 @@ static const int __cpuinitdata ezra_eblcr[16] = {
 /*
  * VIA C3 (Ezra-T) [C5M].
  */
-static const int __cpuinitdata ezrat_mults[32] = {
+static const int __cpuinitconst ezrat_mults[32] = {
 	100, /* 0000 -> 10.0x */
 	30,  /* 0001 ->  3.0x */
 	40,  /* 0010 ->  4.0x */
@@ -196,7 +196,7 @@ static const int __cpuinitdata ezrat_mults[32] = {
 	-1,  /* 1111 -> RESERVED (12.0x) */
 };
 
-static const int __cpuinitdata ezrat_eblcr[32] = {
+static const int __cpuinitconst ezrat_eblcr[32] = {
 	50,  /* 0000 ->  5.0x */
 	30,  /* 0001 ->  3.0x */
 	40,  /* 0010 ->  4.0x */
@@ -235,7 +235,7 @@ static const int __cpuinitdata ezrat_eblcr[32] = {
 /*
  * VIA C3 Nehemiah */
 
-static const int __cpuinitdata nehemiah_mults[32] = {
+static const int __cpuinitconst nehemiah_mults[32] = {
 	100, /* 0000 -> 10.0x */
 	-1, /* 0001 -> 16.0x */
 	40,  /* 0010 ->  4.0x */
@@ -270,7 +270,7 @@ static const int __cpuinitdata nehemiah_mults[32] = {
 	-1, /* 1111 -> 12.0x */
 };
 
-static const int __cpuinitdata nehemiah_eblcr[32] = {
+static const int __cpuinitconst nehemiah_eblcr[32] = {
 	50,  /* 0000 ->  5.0x */
 	160, /* 0001 -> 16.0x */
 	40,  /* 0010 ->  4.0x */
@@ -315,7 +315,7 @@ struct mV_pos {
 	unsigned short pos;
 };
 
-static const struct mV_pos __cpuinitdata vrm85_mV[32] = {
+static const struct mV_pos __cpuinitconst vrm85_mV[32] = {
 	{1250, 8},	{1200, 6},	{1150, 4},	{1100, 2},
 	{1050, 0},	{1800, 30},	{1750, 28},	{1700, 26},
 	{1650, 24},	{1600, 22},	{1550, 20},	{1500, 18},
@@ -326,14 +326,14 @@ static const struct mV_pos __cpuinitdata vrm85_mV[32] = {
 	{1475, 17},	{1425, 15},	{1375, 13},	{1325, 11}
 };
 
-static const unsigned char __cpuinitdata mV_vrm85[32] = {
+static const unsigned char __cpuinitconst mV_vrm85[32] = {
 	0x04,	0x14,	0x03,	0x13,	0x02,	0x12,	0x01,	0x11,
 	0x00,	0x10,	0x0f,	0x1f,	0x0e,	0x1e,	0x0d,	0x1d,
 	0x0c,	0x1c,	0x0b,	0x1b,	0x0a,	0x1a,	0x09,	0x19,
 	0x08,	0x18,	0x07,	0x17,	0x06,	0x16,	0x05,	0x15
 };
 
-static const struct mV_pos __cpuinitdata mobilevrm_mV[32] = {
+static const struct mV_pos __cpuinitconst mobilevrm_mV[32] = {
 	{1750, 31},	{1700, 30},	{1650, 29},	{1600, 28},
 	{1550, 27},	{1500, 26},	{1450, 25},	{1400, 24},
 	{1350, 23},	{1300, 22},	{1250, 21},	{1200, 20},
@@ -344,7 +344,7 @@ static const struct mV_pos __cpuinitdata mobilevrm_mV[32] = {
 	{675, 3},	{650, 2},	{625, 1},	{600, 0}
 };
 
-static const unsigned char __cpuinitdata mV_mobilevrm[32] = {
+static const unsigned char __cpuinitconst mV_mobilevrm[32] = {
 	0x1f,	0x1e,	0x1d,	0x1c,	0x1b,	0x1a,	0x19,	0x18,
 	0x17,	0x16,	0x15,	0x14,	0x13,	0x12,	0x11,	0x10,
 	0x0f,	0x0e,	0x0d,	0x0c,	0x0b,	0x0a,	0x09,	0x08,
diff --git a/drivers/cpufreq/omap-cpufreq.c b/drivers/cpufreq/omap-cpufreq.c
index b47034e..65f8e9a 100644
--- a/drivers/cpufreq/omap-cpufreq.c
+++ b/drivers/cpufreq/omap-cpufreq.c
@@ -40,16 +40,6 @@
 /* OPP tolerance in percentage */
 #define	OPP_TOLERANCE	4
 
-#ifdef CONFIG_SMP
-struct lpj_info {
-	unsigned long	ref;
-	unsigned int	freq;
-};
-
-static DEFINE_PER_CPU(struct lpj_info, lpj_ref);
-static struct lpj_info global_lpj_ref;
-#endif
-
 static struct cpufreq_frequency_table *freq_table;
 static atomic_t freq_table_users = ATOMIC_INIT(0);
 static struct clk *mpu_clk;
@@ -161,31 +151,6 @@ static int omap_target(struct cpufreq_policy *policy,
 	}
 
 	freqs.new = omap_getspeed(policy->cpu);
-#ifdef CONFIG_SMP
-	/*
-	 * Note that loops_per_jiffy is not updated on SMP systems in
-	 * cpufreq driver. So, update the per-CPU loops_per_jiffy value
-	 * on frequency transition. We need to update all dependent CPUs.
-	 */
-	for_each_cpu(i, policy->cpus) {
-		struct lpj_info *lpj = &per_cpu(lpj_ref, i);
-		if (!lpj->freq) {
-			lpj->ref = per_cpu(cpu_data, i).loops_per_jiffy;
-			lpj->freq = freqs.old;
-		}
-
-		per_cpu(cpu_data, i).loops_per_jiffy =
-			cpufreq_scale(lpj->ref, lpj->freq, freqs.new);
-	}
-
-	/* And don't forget to adjust the global one */
-	if (!global_lpj_ref.freq) {
-		global_lpj_ref.ref = loops_per_jiffy;
-		global_lpj_ref.freq = freqs.old;
-	}
-	loops_per_jiffy = cpufreq_scale(global_lpj_ref.ref, global_lpj_ref.freq,
-					freqs.new);
-#endif
 
 done:
 	/* notifiers */
@@ -301,9 +266,9 @@ static int __init omap_cpufreq_init(void)
 	}
 
 	mpu_dev = omap_device_get_by_hwmod_name("mpu");
-	if (!mpu_dev) {
+	if (IS_ERR(mpu_dev)) {
 		pr_warning("%s: unable to get the mpu device\n", __func__);
-		return -EINVAL;
+		return PTR_ERR(mpu_dev);
 	}
 
 	mpu_reg = regulator_get(mpu_dev, "vcc");
diff --git a/drivers/cpufreq/powernow-k8.c b/drivers/cpufreq/powernow-k8.c
index 1a40935..129e80b 100644
--- a/drivers/cpufreq/powernow-k8.c
+++ b/drivers/cpufreq/powernow-k8.c
@@ -48,22 +48,12 @@
 #define PFX "powernow-k8: "
 #define VERSION "version 2.20.00"
 #include "powernow-k8.h"
-#include "mperf.h"
 
 /* serialize freq changes  */
 static DEFINE_MUTEX(fidvid_mutex);
 
 static DEFINE_PER_CPU(struct powernow_k8_data *, powernow_data);
 
-static int cpu_family = CPU_OPTERON;
-
-/* array to map SW pstate number to acpi state */
-static u32 ps_to_as[8];
-
-/* core performance boost */
-static bool cpb_capable, cpb_enabled;
-static struct msr __percpu *msrs;
-
 static struct cpufreq_driver cpufreq_amd64_driver;
 
 #ifndef CONFIG_SMP
@@ -85,12 +75,6 @@ static u32 find_khz_freq_from_fid(u32 fid)
 	return 1000 * find_freq_from_fid(fid);
 }
 
-static u32 find_khz_freq_from_pstate(struct cpufreq_frequency_table *data,
-				     u32 pstate)
-{
-	return data[ps_to_as[pstate]].frequency;
-}
-
 /* Return the vco fid for an input fid
  *
  * Each "low" fid has corresponding "high" fid, and you can get to "low" fids
@@ -113,9 +97,6 @@ static int pending_bit_stuck(void)
 {
 	u32 lo, hi;
 
-	if (cpu_family == CPU_HW_PSTATE)
-		return 0;
-
 	rdmsr(MSR_FIDVID_STATUS, lo, hi);
 	return lo & MSR_S_LO_CHANGE_PENDING ? 1 : 0;
 }
@@ -129,20 +110,6 @@ static int query_current_values_with_pending_wait(struct powernow_k8_data *data)
 	u32 lo, hi;
 	u32 i = 0;
 
-	if (cpu_family == CPU_HW_PSTATE) {
-		rdmsr(MSR_PSTATE_STATUS, lo, hi);
-		i = lo & HW_PSTATE_MASK;
-		data->currpstate = i;
-
-		/*
-		 * a workaround for family 11h erratum 311 might cause
-		 * an "out-of-range Pstate if the core is in Pstate-0
-		 */
-		if ((boot_cpu_data.x86 == 0x11) && (i >= data->numps))
-			data->currpstate = HW_PSTATE_0;
-
-		return 0;
-	}
 	do {
 		if (i++ > 10000) {
 			pr_debug("detected change pending stuck\n");
@@ -299,14 +266,6 @@ static int decrease_vid_code_by_step(struct powernow_k8_data *data,
 	return 0;
 }
 
-/* Change hardware pstate by single MSR write */
-static int transition_pstate(struct powernow_k8_data *data, u32 pstate)
-{
-	wrmsr(MSR_PSTATE_CTRL, pstate, 0);
-	data->currpstate = pstate;
-	return 0;
-}
-
 /* Change Opteron/Athlon64 fid and vid, by the 3 phases. */
 static int transition_fid_vid(struct powernow_k8_data *data,
 		u32 reqfid, u32 reqvid)
@@ -523,8 +482,6 @@ static int core_voltage_post_transition(struct powernow_k8_data *data,
 static const struct x86_cpu_id powernow_k8_ids[] = {
 	/* IO based frequency switching */
 	{ X86_VENDOR_AMD, 0xf },
-	/* MSR based frequency switching supported */
-	X86_FEATURE_MATCH(X86_FEATURE_HW_PSTATE),
 	{}
 };
 MODULE_DEVICE_TABLE(x86cpu, powernow_k8_ids);
@@ -560,15 +517,8 @@ static void check_supported_cpu(void *_rc)
 				"Power state transitions not supported\n");
 			return;
 		}
-	} else { /* must be a HW Pstate capable processor */
-		cpuid(CPUID_FREQ_VOLT_CAPABILITIES, &eax, &ebx, &ecx, &edx);
-		if ((edx & USE_HW_PSTATE) == USE_HW_PSTATE)
-			cpu_family = CPU_HW_PSTATE;
-		else
-			return;
+		*rc = 0;
 	}
-
-	*rc = 0;
 }
 
 static int check_pst_table(struct powernow_k8_data *data, struct pst_s *pst,
@@ -632,18 +582,11 @@ static void print_basics(struct powernow_k8_data *data)
 	for (j = 0; j < data->numps; j++) {
 		if (data->powernow_table[j].frequency !=
 				CPUFREQ_ENTRY_INVALID) {
-			if (cpu_family == CPU_HW_PSTATE) {
-				printk(KERN_INFO PFX
-					"   %d : pstate %d (%d MHz)\n", j,
-					data->powernow_table[j].index,
-					data->powernow_table[j].frequency/1000);
-			} else {
 				printk(KERN_INFO PFX
 					"fid 0x%x (%d MHz), vid 0x%x\n",
 					data->powernow_table[j].index & 0xff,
 					data->powernow_table[j].frequency/1000,
 					data->powernow_table[j].index >> 8);
-			}
 		}
 	}
 	if (data->batps)
@@ -651,20 +594,6 @@ static void print_basics(struct powernow_k8_data *data)
 				data->batps);
 }
 
-static u32 freq_from_fid_did(u32 fid, u32 did)
-{
-	u32 mhz = 0;
-
-	if (boot_cpu_data.x86 == 0x10)
-		mhz = (100 * (fid + 0x10)) >> did;
-	else if (boot_cpu_data.x86 == 0x11)
-		mhz = (100 * (fid + 8)) >> did;
-	else
-		BUG();
-
-	return mhz * 1000;
-}
-
 static int fill_powernow_table(struct powernow_k8_data *data,
 		struct pst_s *pst, u8 maxvid)
 {
@@ -824,7 +753,7 @@ static void powernow_k8_acpi_pst_values(struct powernow_k8_data *data,
 {
 	u64 control;
 
-	if (!data->acpi_data.state_count || (cpu_family == CPU_HW_PSTATE))
+	if (!data->acpi_data.state_count)
 		return;
 
 	control = data->acpi_data.states[index].control;
@@ -875,10 +804,7 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data)
 	data->numps = data->acpi_data.state_count;
 	powernow_k8_acpi_pst_values(data, 0);
 
-	if (cpu_family == CPU_HW_PSTATE)
-		ret_val = fill_powernow_table_pstate(data, powernow_table);
-	else
-		ret_val = fill_powernow_table_fidvid(data, powernow_table);
+	ret_val = fill_powernow_table_fidvid(data, powernow_table);
 	if (ret_val)
 		goto err_out_mem;
 
@@ -915,51 +841,6 @@ err_out:
 	return ret_val;
 }
 
-static int fill_powernow_table_pstate(struct powernow_k8_data *data,
-		struct cpufreq_frequency_table *powernow_table)
-{
-	int i;
-	u32 hi = 0, lo = 0;
-	rdmsr(MSR_PSTATE_CUR_LIMIT, lo, hi);
-	data->max_hw_pstate = (lo & HW_PSTATE_MAX_MASK) >> HW_PSTATE_MAX_SHIFT;
-
-	for (i = 0; i < data->acpi_data.state_count; i++) {
-		u32 index;
-
-		index = data->acpi_data.states[i].control & HW_PSTATE_MASK;
-		if (index > data->max_hw_pstate) {
-			printk(KERN_ERR PFX "invalid pstate %d - "
-					"bad value %d.\n", i, index);
-			printk(KERN_ERR PFX "Please report to BIOS "
-					"manufacturer\n");
-			invalidate_entry(powernow_table, i);
-			continue;
-		}
-
-		ps_to_as[index] = i;
-
-		/* Frequency may be rounded for these */
-		if ((boot_cpu_data.x86 == 0x10 && boot_cpu_data.x86_model < 10)
-				 || boot_cpu_data.x86 == 0x11) {
-
-			rdmsr(MSR_PSTATE_DEF_BASE + index, lo, hi);
-			if (!(hi & HW_PSTATE_VALID_MASK)) {
-				pr_debug("invalid pstate %d, ignoring\n", index);
-				invalidate_entry(powernow_table, i);
-				continue;
-			}
-
-			powernow_table[i].frequency =
-				freq_from_fid_did(lo & 0x3f, (lo >> 6) & 7);
-		} else
-			powernow_table[i].frequency =
-				data->acpi_data.states[i].core_frequency * 1000;
-
-		powernow_table[i].index = index;
-	}
-	return 0;
-}
-
 static int fill_powernow_table_fidvid(struct powernow_k8_data *data,
 		struct cpufreq_frequency_table *powernow_table)
 {
@@ -1036,15 +917,7 @@ static int get_transition_latency(struct powernow_k8_data *data)
 			max_latency = cur_latency;
 	}
 	if (max_latency == 0) {
-		/*
-		 * Fam 11h and later may return 0 as transition latency. This
-		 * is intended and means "very fast". While cpufreq core and
-		 * governors currently can handle that gracefully, better set it
-		 * to 1 to avoid problems in the future.
-		 */
-		if (boot_cpu_data.x86 < 0x11)
-			printk(KERN_ERR FW_WARN PFX "Invalid zero transition "
-				"latency\n");
+		pr_err(FW_WARN PFX "Invalid zero transition latency\n");
 		max_latency = 1;
 	}
 	/* value in usecs, needs to be in nanoseconds */
@@ -1104,40 +977,6 @@ static int transition_frequency_fidvid(struct powernow_k8_data *data,
 	return res;
 }
 
-/* Take a frequency, and issue the hardware pstate transition command */
-static int transition_frequency_pstate(struct powernow_k8_data *data,
-		unsigned int index)
-{
-	u32 pstate = 0;
-	int res, i;
-	struct cpufreq_freqs freqs;
-
-	pr_debug("cpu %d transition to index %u\n", smp_processor_id(), index);
-
-	/* get MSR index for hardware pstate transition */
-	pstate = index & HW_PSTATE_MASK;
-	if (pstate > data->max_hw_pstate)
-		return -EINVAL;
-
-	freqs.old = find_khz_freq_from_pstate(data->powernow_table,
-			data->currpstate);
-	freqs.new = find_khz_freq_from_pstate(data->powernow_table, pstate);
-
-	for_each_cpu(i, data->available_cores) {
-		freqs.cpu = i;
-		cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
-	}
-
-	res = transition_pstate(data, pstate);
-	freqs.new = find_khz_freq_from_pstate(data->powernow_table, pstate);
-
-	for_each_cpu(i, data->available_cores) {
-		freqs.cpu = i;
-		cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
-	}
-	return res;
-}
-
 struct powernowk8_target_arg {
 	struct cpufreq_policy		*pol;
 	unsigned			targfreq;
@@ -1173,18 +1012,15 @@ static long powernowk8_target_fn(void *arg)
 	if (query_current_values_with_pending_wait(data))
 		return -EIO;
 
-	if (cpu_family != CPU_HW_PSTATE) {
-		pr_debug("targ: curr fid 0x%x, vid 0x%x\n",
-		data->currfid, data->currvid);
+	pr_debug("targ: curr fid 0x%x, vid 0x%x\n",
+		 data->currfid, data->currvid);
 
-		if ((checkvid != data->currvid) ||
-		    (checkfid != data->currfid)) {
-			printk(KERN_INFO PFX
-				"error - out of sync, fix 0x%x 0x%x, "
-				"vid 0x%x 0x%x\n",
-				checkfid, data->currfid,
-				checkvid, data->currvid);
-		}
+	if ((checkvid != data->currvid) ||
+	    (checkfid != data->currfid)) {
+		pr_info(PFX
+		       "error - out of sync, fix 0x%x 0x%x, vid 0x%x 0x%x\n",
+		       checkfid, data->currfid,
+		       checkvid, data->currvid);
 	}
 
 	if (cpufreq_frequency_table_target(pol, data->powernow_table,
@@ -1195,11 +1031,8 @@ static long powernowk8_target_fn(void *arg)
 
 	powernow_k8_acpi_pst_values(data, newstate);
 
-	if (cpu_family == CPU_HW_PSTATE)
-		ret = transition_frequency_pstate(data,
-			data->powernow_table[newstate].index);
-	else
-		ret = transition_frequency_fidvid(data, newstate);
+	ret = transition_frequency_fidvid(data, newstate);
+
 	if (ret) {
 		printk(KERN_ERR PFX "transition frequency failed\n");
 		mutex_unlock(&fidvid_mutex);
@@ -1207,11 +1040,7 @@ static long powernowk8_target_fn(void *arg)
 	}
 	mutex_unlock(&fidvid_mutex);
 
-	if (cpu_family == CPU_HW_PSTATE)
-		pol->cur = find_khz_freq_from_pstate(data->powernow_table,
-				data->powernow_table[newstate].index);
-	else
-		pol->cur = find_khz_freq_from_fid(data->currfid);
+	pol->cur = find_khz_freq_from_fid(data->currfid);
 
 	return 0;
 }
@@ -1264,22 +1093,23 @@ static void __cpuinit powernowk8_cpu_init_on_cpu(void *_init_on_cpu)
 		return;
 	}
 
-	if (cpu_family == CPU_OPTERON)
-		fidvid_msr_init();
+	fidvid_msr_init();
 
 	init_on_cpu->rc = 0;
 }
 
+static const char missing_pss_msg[] =
+	KERN_ERR
+	FW_BUG PFX "No compatible ACPI _PSS objects found.\n"
+	FW_BUG PFX "First, make sure Cool'N'Quiet is enabled in the BIOS.\n"
+	FW_BUG PFX "If that doesn't help, try upgrading your BIOS.\n";
+
 /* per CPU init entry point to the driver */
 static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
 {
-	static const char ACPI_PSS_BIOS_BUG_MSG[] =
-		KERN_ERR FW_BUG PFX "No compatible ACPI _PSS objects found.\n"
-		FW_BUG PFX "Try again with latest BIOS.\n";
 	struct powernow_k8_data *data;
 	struct init_on_cpu init_on_cpu;
 	int rc;
-	struct cpuinfo_x86 *c = &cpu_data(pol->cpu);
 
 	if (!cpu_online(pol->cpu))
 		return -ENODEV;
@@ -1295,7 +1125,6 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
 	}
 
 	data->cpu = pol->cpu;
-	data->currpstate = HW_PSTATE_INVALID;
 
 	if (powernow_k8_cpu_init_acpi(data)) {
 		/*
@@ -1303,7 +1132,7 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
 		 * an UP version, and is deprecated by AMD.
 		 */
 		if (num_online_cpus() != 1) {
-			printk_once(ACPI_PSS_BIOS_BUG_MSG);
+			printk_once(missing_pss_msg);
 			goto err_out;
 		}
 		if (pol->cpu != 0) {
@@ -1332,17 +1161,10 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
 	if (rc != 0)
 		goto err_out_exit_acpi;
 
-	if (cpu_family == CPU_HW_PSTATE)
-		cpumask_copy(pol->cpus, cpumask_of(pol->cpu));
-	else
-		cpumask_copy(pol->cpus, cpu_core_mask(pol->cpu));
+	cpumask_copy(pol->cpus, cpu_core_mask(pol->cpu));
 	data->available_cores = pol->cpus;
 
-	if (cpu_family == CPU_HW_PSTATE)
-		pol->cur = find_khz_freq_from_pstate(data->powernow_table,
-				data->currpstate);
-	else
-		pol->cur = find_khz_freq_from_fid(data->currfid);
+	pol->cur = find_khz_freq_from_fid(data->currfid);
 	pr_debug("policy current frequency %d kHz\n", pol->cur);
 
 	/* min/max the cpu is capable of */
@@ -1354,18 +1176,10 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
 		return -EINVAL;
 	}
 
-	/* Check for APERF/MPERF support in hardware */
-	if (cpu_has(c, X86_FEATURE_APERFMPERF))
-		cpufreq_amd64_driver.getavg = cpufreq_get_measured_perf;
-
 	cpufreq_frequency_table_get_attr(data->powernow_table, pol->cpu);
 
-	if (cpu_family == CPU_HW_PSTATE)
-		pr_debug("cpu_init done, current pstate 0x%x\n",
-				data->currpstate);
-	else
-		pr_debug("cpu_init done, current fid 0x%x, vid 0x%x\n",
-			data->currfid, data->currvid);
+	pr_debug("cpu_init done, current fid 0x%x, vid 0x%x\n",
+		 data->currfid, data->currvid);
 
 	per_cpu(powernow_data, pol->cpu) = data;
 
@@ -1418,88 +1232,15 @@ static unsigned int powernowk8_get(unsigned int cpu)
 	if (err)
 		goto out;
 
-	if (cpu_family == CPU_HW_PSTATE)
-		khz = find_khz_freq_from_pstate(data->powernow_table,
-						data->currpstate);
-	else
-		khz = find_khz_freq_from_fid(data->currfid);
+	khz = find_khz_freq_from_fid(data->currfid);
 
 
 out:
 	return khz;
 }
 
-static void _cpb_toggle_msrs(bool t)
-{
-	int cpu;
-
-	get_online_cpus();
-
-	rdmsr_on_cpus(cpu_online_mask, MSR_K7_HWCR, msrs);
-
-	for_each_cpu(cpu, cpu_online_mask) {
-		struct msr *reg = per_cpu_ptr(msrs, cpu);
-		if (t)
-			reg->l &= ~BIT(25);
-		else
-			reg->l |= BIT(25);
-	}
-	wrmsr_on_cpus(cpu_online_mask, MSR_K7_HWCR, msrs);
-
-	put_online_cpus();
-}
-
-/*
- * Switch on/off core performance boosting.
- *
- * 0=disable
- * 1=enable.
- */
-static void cpb_toggle(bool t)
-{
-	if (!cpb_capable)
-		return;
-
-	if (t && !cpb_enabled) {
-		cpb_enabled = true;
-		_cpb_toggle_msrs(t);
-		printk(KERN_INFO PFX "Core Boosting enabled.\n");
-	} else if (!t && cpb_enabled) {
-		cpb_enabled = false;
-		_cpb_toggle_msrs(t);
-		printk(KERN_INFO PFX "Core Boosting disabled.\n");
-	}
-}
-
-static ssize_t store_cpb(struct cpufreq_policy *policy, const char *buf,
-				 size_t count)
-{
-	int ret = -EINVAL;
-	unsigned long val = 0;
-
-	ret = strict_strtoul(buf, 10, &val);
-	if (!ret && (val == 0 || val == 1) && cpb_capable)
-		cpb_toggle(val);
-	else
-		return -EINVAL;
-
-	return count;
-}
-
-static ssize_t show_cpb(struct cpufreq_policy *policy, char *buf)
-{
-	return sprintf(buf, "%u\n", cpb_enabled);
-}
-
-#define define_one_rw(_name) \
-static struct freq_attr _name = \
-__ATTR(_name, 0644, show_##_name, store_##_name)
-
-define_one_rw(cpb);
-
 static struct freq_attr *powernow_k8_attr[] = {
 	&cpufreq_freq_attr_scaling_available_freqs,
-	&cpb,
 	NULL,
 };
 
@@ -1515,53 +1256,18 @@ static struct cpufreq_driver cpufreq_amd64_driver = {
 	.attr		= powernow_k8_attr,
 };
 
-/*
- * Clear the boost-disable flag on the CPU_DOWN path so that this cpu
- * cannot block the remaining ones from boosting. On the CPU_UP path we
- * simply keep the boost-disable flag in sync with the current global
- * state.
- */
-static int cpb_notify(struct notifier_block *nb, unsigned long action,
-		      void *hcpu)
-{
-	unsigned cpu = (long)hcpu;
-	u32 lo, hi;
-
-	switch (action) {
-	case CPU_UP_PREPARE:
-	case CPU_UP_PREPARE_FROZEN:
-
-		if (!cpb_enabled) {
-			rdmsr_on_cpu(cpu, MSR_K7_HWCR, &lo, &hi);
-			lo |= BIT(25);
-			wrmsr_on_cpu(cpu, MSR_K7_HWCR, lo, hi);
-		}
-		break;
-
-	case CPU_DOWN_PREPARE:
-	case CPU_DOWN_PREPARE_FROZEN:
-		rdmsr_on_cpu(cpu, MSR_K7_HWCR, &lo, &hi);
-		lo &= ~BIT(25);
-		wrmsr_on_cpu(cpu, MSR_K7_HWCR, lo, hi);
-		break;
-
-	default:
-		break;
-	}
-
-	return NOTIFY_OK;
-}
-
-static struct notifier_block cpb_nb = {
-	.notifier_call		= cpb_notify,
-};
-
 /* driver entry point for init */
 static int __cpuinit powernowk8_init(void)
 {
-	unsigned int i, supported_cpus = 0, cpu;
+	unsigned int i, supported_cpus = 0;
 	int rv;
 
+	if (static_cpu_has(X86_FEATURE_HW_PSTATE)) {
+		pr_warn(PFX "this CPU is not supported anymore, using acpi-cpufreq instead.\n");
+		request_module("acpi-cpufreq");
+		return -ENODEV;
+	}
+
 	if (!x86_match_cpu(powernow_k8_ids))
 		return -ENODEV;
 
@@ -1575,38 +1281,13 @@ static int __cpuinit powernowk8_init(void)
 	if (supported_cpus != num_online_cpus())
 		return -ENODEV;
 
-	printk(KERN_INFO PFX "Found %d %s (%d cpu cores) (" VERSION ")\n",
-		num_online_nodes(), boot_cpu_data.x86_model_id, supported_cpus);
-
-	if (boot_cpu_has(X86_FEATURE_CPB)) {
-
-		cpb_capable = true;
-
-		msrs = msrs_alloc();
-		if (!msrs) {
-			printk(KERN_ERR "%s: Error allocating msrs!\n", __func__);
-			return -ENOMEM;
-		}
-
-		register_cpu_notifier(&cpb_nb);
-
-		rdmsr_on_cpus(cpu_online_mask, MSR_K7_HWCR, msrs);
+	rv = cpufreq_register_driver(&cpufreq_amd64_driver);
 
-		for_each_cpu(cpu, cpu_online_mask) {
-			struct msr *reg = per_cpu_ptr(msrs, cpu);
-			cpb_enabled |= !(!!(reg->l & BIT(25)));
-		}
+	if (!rv)
+		pr_info(PFX "Found %d %s (%d cpu cores) (" VERSION ")\n",
+			num_online_nodes(), boot_cpu_data.x86_model_id,
+			supported_cpus);
 
-		printk(KERN_INFO PFX "Core Performance Boosting: %s.\n",
-			(cpb_enabled ? "on" : "off"));
-	}
-
-	rv = cpufreq_register_driver(&cpufreq_amd64_driver);
-	if (rv < 0 && boot_cpu_has(X86_FEATURE_CPB)) {
-		unregister_cpu_notifier(&cpb_nb);
-		msrs_free(msrs);
-		msrs = NULL;
-	}
 	return rv;
 }
 
@@ -1615,13 +1296,6 @@ static void __exit powernowk8_exit(void)
 {
 	pr_debug("exit\n");
 
-	if (boot_cpu_has(X86_FEATURE_CPB)) {
-		msrs_free(msrs);
-		msrs = NULL;
-
-		unregister_cpu_notifier(&cpb_nb);
-	}
-
 	cpufreq_unregister_driver(&cpufreq_amd64_driver);
 }
 
diff --git a/drivers/cpufreq/powernow-k8.h b/drivers/cpufreq/powernow-k8.h
index 3744d26..79329d4 100644
--- a/drivers/cpufreq/powernow-k8.h
+++ b/drivers/cpufreq/powernow-k8.h
@@ -5,24 +5,11 @@
  *  http://www.gnu.org/licenses/gpl.html
  */
 
-enum pstate {
-	HW_PSTATE_INVALID = 0xff,
-	HW_PSTATE_0 = 0,
-	HW_PSTATE_1 = 1,
-	HW_PSTATE_2 = 2,
-	HW_PSTATE_3 = 3,
-	HW_PSTATE_4 = 4,
-	HW_PSTATE_5 = 5,
-	HW_PSTATE_6 = 6,
-	HW_PSTATE_7 = 7,
-};
-
 struct powernow_k8_data {
 	unsigned int cpu;
 
 	u32 numps;  /* number of p-states */
 	u32 batps;  /* number of p-states supported on battery */
-	u32 max_hw_pstate; /* maximum legal hardware pstate */
 
 	/* these values are constant when the PSB is used to determine
 	 * vid/fid pairings, but are modified during the ->target() call
@@ -37,7 +24,6 @@ struct powernow_k8_data {
 	/* keep track of the current fid / vid or pstate */
 	u32 currvid;
 	u32 currfid;
-	enum pstate currpstate;
 
 	/* the powernow_table includes all frequency and vid/fid pairings:
 	 * fid are the lower 8 bits of the index, vid are the upper 8 bits.
@@ -97,23 +83,6 @@ struct powernow_k8_data {
 #define MSR_S_HI_CURRENT_VID      0x0000003f
 #define MSR_C_HI_STP_GNT_BENIGN	  0x00000001
 
-
-/* Hardware Pstate _PSS and MSR definitions */
-#define USE_HW_PSTATE		0x00000080
-#define HW_PSTATE_MASK 		0x00000007
-#define HW_PSTATE_VALID_MASK 	0x80000000
-#define HW_PSTATE_MAX_MASK	0x000000f0
-#define HW_PSTATE_MAX_SHIFT	4
-#define MSR_PSTATE_DEF_BASE 	0xc0010064 /* base of Pstate MSRs */
-#define MSR_PSTATE_STATUS 	0xc0010063 /* Pstate Status MSR */
-#define MSR_PSTATE_CTRL 	0xc0010062 /* Pstate control MSR */
-#define MSR_PSTATE_CUR_LIMIT	0xc0010061 /* pstate current limit MSR */
-
-/* define the two driver architectures */
-#define CPU_OPTERON 0
-#define CPU_HW_PSTATE 1
-
-
 /*
  * There are restrictions frequencies have to follow:
  * - only 1 entry in the low fid table ( <=1.4GHz )
@@ -218,5 +187,4 @@ static int core_frequency_transition(struct powernow_k8_data *data, u32 reqfid);
 
 static void powernow_k8_acpi_pst_values(struct powernow_k8_data *data, unsigned int index);
 
-static int fill_powernow_table_pstate(struct powernow_k8_data *data, struct cpufreq_frequency_table *powernow_table);
 static int fill_powernow_table_fidvid(struct powernow_k8_data *data, struct cpufreq_frequency_table *powernow_table);
diff --git a/drivers/cpuidle/driver.c b/drivers/cpuidle/driver.c
index 58bf3b1..87db387 100644
--- a/drivers/cpuidle/driver.c
+++ b/drivers/cpuidle/driver.c
@@ -18,9 +18,10 @@ static struct cpuidle_driver *cpuidle_curr_driver;
 DEFINE_SPINLOCK(cpuidle_driver_lock);
 int cpuidle_driver_refcount;
 
-static void __cpuidle_register_driver(struct cpuidle_driver *drv)
+static void set_power_states(struct cpuidle_driver *drv)
 {
 	int i;
+
 	/*
 	 * cpuidle driver should set the drv->power_specified bit
 	 * before registering if the driver provides
@@ -35,13 +36,10 @@ static void __cpuidle_register_driver(struct cpuidle_driver *drv)
 	 * an power value of -1.  So we use -2, -3, etc, for other
 	 * c-states.
 	 */
-	if (!drv->power_specified) {
-		for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++)
-			drv->states[i].power_usage = -1 - i;
-	}
+	for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++)
+		drv->states[i].power_usage = -1 - i;
 }
 
-
 /**
  * cpuidle_register_driver - registers a driver
  * @drv: the driver
@@ -59,13 +57,16 @@ int cpuidle_register_driver(struct cpuidle_driver *drv)
 		spin_unlock(&cpuidle_driver_lock);
 		return -EBUSY;
 	}
-	__cpuidle_register_driver(drv);
+
+	if (!drv->power_specified)
+		set_power_states(drv);
+
 	cpuidle_curr_driver = drv;
+
 	spin_unlock(&cpuidle_driver_lock);
 
 	return 0;
 }
-
 EXPORT_SYMBOL_GPL(cpuidle_register_driver);
 
 /**
@@ -96,7 +97,6 @@ void cpuidle_unregister_driver(struct cpuidle_driver *drv)
 
 	spin_unlock(&cpuidle_driver_lock);
 }
-
 EXPORT_SYMBOL_GPL(cpuidle_unregister_driver);
 
 struct cpuidle_driver *cpuidle_driver_ref(void)
diff --git a/drivers/cpuidle/governors/ladder.c b/drivers/cpuidle/governors/ladder.c
index b6a09ea..9b78405 100644
--- a/drivers/cpuidle/governors/ladder.c
+++ b/drivers/cpuidle/governors/ladder.c
@@ -88,6 +88,8 @@ static int ladder_select_state(struct cpuidle_driver *drv,
 
 	/* consider promotion */
 	if (last_idx < drv->state_count - 1 &&
+	    !drv->states[last_idx + 1].disabled &&
+	    !dev->states_usage[last_idx + 1].disable &&
 	    last_residency > last_state->threshold.promotion_time &&
 	    drv->states[last_idx + 1].exit_latency <= latency_req) {
 		last_state->stats.promotion_count++;
@@ -100,7 +102,9 @@ static int ladder_select_state(struct cpuidle_driver *drv,
 
 	/* consider demotion */
 	if (last_idx > CPUIDLE_DRIVER_STATE_START &&
-	    drv->states[last_idx].exit_latency > latency_req) {
+	    (drv->states[last_idx].disabled ||
+	    dev->states_usage[last_idx].disable ||
+	    drv->states[last_idx].exit_latency > latency_req)) {
 		int i;
 
 		for (i = last_idx - 1; i > CPUIDLE_DRIVER_STATE_START; i--) {
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index 7d74d09..f6644f5 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -224,7 +224,7 @@ config CRYPTO_DEV_TALITOS
 
 config CRYPTO_DEV_IXP4XX
 	tristate "Driver for IXP4xx crypto hardware acceleration"
-	depends on ARCH_IXP4XX
+	depends on ARCH_IXP4XX && IXP4XX_QMGR && IXP4XX_NPE
 	select CRYPTO_DES
 	select CRYPTO_ALGAPI
 	select CRYPTO_AUTHENC
@@ -298,21 +298,15 @@ config CRYPTO_DEV_TEGRA_AES
 	  will be called tegra-aes.
 
 config CRYPTO_DEV_NX
-	tristate "Support for Power7+ in-Nest cryptographic acceleration"
+	bool "Support for IBM Power7+ in-Nest cryptographic acceleration"
 	depends on PPC64 && IBMVIO
-	select CRYPTO_AES
-	select CRYPTO_CBC
-	select CRYPTO_ECB
-	select CRYPTO_CCM
-	select CRYPTO_GCM
-	select CRYPTO_AUTHENC
-	select CRYPTO_XCBC
-	select CRYPTO_SHA256
-	select CRYPTO_SHA512
+	default n
 	help
-	  Support for Power7+ in-Nest cryptographic acceleration. This
-	  module supports acceleration for AES and SHA2 algorithms. If you
-	  choose 'M' here, this module will be called nx_crypto.
+	  Support for Power7+ in-Nest cryptographic acceleration.
+
+if CRYPTO_DEV_NX
+	source "drivers/crypto/nx/Kconfig"
+endif
 
 config CRYPTO_DEV_UX500
 	tristate "Driver for ST-Ericsson UX500 crypto hardware acceleration"
@@ -340,7 +334,7 @@ config CRYPTO_DEV_ATMEL_AES
 	select CRYPTO_AES
 	select CRYPTO_ALGAPI
 	select CRYPTO_BLKCIPHER
-	select CONFIG_AT_HDMAC
+	select AT_HDMAC
 	help
 	  Some Atmel processors have AES hw accelerator.
 	  Select this if you want to use the Atmel module for
diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c
index 6bb20ff..8061336 100644
--- a/drivers/crypto/atmel-aes.c
+++ b/drivers/crypto/atmel-aes.c
@@ -24,15 +24,10 @@
 #include <linux/platform_device.h>
 
 #include <linux/device.h>
-#include <linux/module.h>
 #include <linux/init.h>
 #include <linux/errno.h>
 #include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/clk.h>
 #include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
 #include <linux/scatterlist.h>
 #include <linux/dma-mapping.h>
 #include <linux/delay.h>
@@ -1017,7 +1012,6 @@ static int atmel_aes_register_algs(struct atmel_aes_dev *dd)
 	int err, i, j;
 
 	for (i = 0; i < ARRAY_SIZE(aes_algs); i++) {
-		INIT_LIST_HEAD(&aes_algs[i].cra_list);
 		err = crypto_register_alg(&aes_algs[i]);
 		if (err)
 			goto err_aes_algs;
@@ -1026,7 +1020,6 @@ static int atmel_aes_register_algs(struct atmel_aes_dev *dd)
 	atmel_aes_hw_version_init(dd);
 
 	if (dd->hw_version >= 0x130) {
-		INIT_LIST_HEAD(&aes_cfb64_alg[0].cra_list);
 		err = crypto_register_alg(&aes_cfb64_alg[0]);
 		if (err)
 			goto err_aes_cfb64_alg;
diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c
index f938b9d..bcdf55f 100644
--- a/drivers/crypto/atmel-sha.c
+++ b/drivers/crypto/atmel-sha.c
@@ -24,15 +24,10 @@
 #include <linux/platform_device.h>
 
 #include <linux/device.h>
-#include <linux/module.h>
 #include <linux/init.h>
 #include <linux/errno.h>
 #include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/clk.h>
 #include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
 #include <linux/scatterlist.h>
 #include <linux/dma-mapping.h>
 #include <linux/delay.h>
diff --git a/drivers/crypto/atmel-tdes.c b/drivers/crypto/atmel-tdes.c
index eb2b61e..7495f98 100644
--- a/drivers/crypto/atmel-tdes.c
+++ b/drivers/crypto/atmel-tdes.c
@@ -24,15 +24,10 @@
 #include <linux/platform_device.h>
 
 #include <linux/device.h>
-#include <linux/module.h>
 #include <linux/init.h>
 #include <linux/errno.h>
 #include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/clk.h>
 #include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
 #include <linux/scatterlist.h>
 #include <linux/dma-mapping.h>
 #include <linux/delay.h>
@@ -1044,7 +1039,6 @@ static int atmel_tdes_register_algs(struct atmel_tdes_dev *dd)
 	int err, i, j;
 
 	for (i = 0; i < ARRAY_SIZE(tdes_algs); i++) {
-		INIT_LIST_HEAD(&tdes_algs[i].cra_list);
 		err = crypto_register_alg(&tdes_algs[i]);
 		if (err)
 			goto err_tdes_algs;
diff --git a/drivers/crypto/caam/caamalg.c b/drivers/crypto/caam/caamalg.c
index 0c1ea84..b2a0a07 100644
--- a/drivers/crypto/caam/caamalg.c
+++ b/drivers/crypto/caam/caamalg.c
@@ -205,7 +205,7 @@ static void init_sh_desc_key_aead(u32 *desc, struct caam_ctx *ctx,
 {
 	u32 *key_jump_cmd;
 
-	init_sh_desc(desc, HDR_SHARE_WAIT);
+	init_sh_desc(desc, HDR_SHARE_SERIAL);
 
 	/* Skip if already shared */
 	key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
@@ -224,7 +224,7 @@ static int aead_set_sh_desc(struct crypto_aead *aead)
 	struct aead_tfm *tfm = &aead->base.crt_aead;
 	struct caam_ctx *ctx = crypto_aead_ctx(aead);
 	struct device *jrdev = ctx->jrdev;
-	bool keys_fit_inline = 0;
+	bool keys_fit_inline = false;
 	u32 *key_jump_cmd, *jump_cmd;
 	u32 geniv, moveiv;
 	u32 *desc;
@@ -239,7 +239,7 @@ static int aead_set_sh_desc(struct crypto_aead *aead)
 	if (DESC_AEAD_ENC_LEN + DESC_JOB_IO_LEN +
 	    ctx->split_key_pad_len + ctx->enckeylen <=
 	    CAAM_DESC_BYTES_MAX)
-		keys_fit_inline = 1;
+		keys_fit_inline = true;
 
 	/* aead_encrypt shared descriptor */
 	desc = ctx->sh_desc_enc;
@@ -297,12 +297,12 @@ static int aead_set_sh_desc(struct crypto_aead *aead)
 	if (DESC_AEAD_DEC_LEN + DESC_JOB_IO_LEN +
 	    ctx->split_key_pad_len + ctx->enckeylen <=
 	    CAAM_DESC_BYTES_MAX)
-		keys_fit_inline = 1;
+		keys_fit_inline = true;
 
 	desc = ctx->sh_desc_dec;
 
 	/* aead_decrypt shared descriptor */
-	init_sh_desc(desc, HDR_SHARE_WAIT);
+	init_sh_desc(desc, HDR_SHARE_SERIAL);
 
 	/* Skip if already shared */
 	key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
@@ -365,7 +365,7 @@ static int aead_set_sh_desc(struct crypto_aead *aead)
 	if (DESC_AEAD_GIVENC_LEN + DESC_JOB_IO_LEN +
 	    ctx->split_key_pad_len + ctx->enckeylen <=
 	    CAAM_DESC_BYTES_MAX)
-		keys_fit_inline = 1;
+		keys_fit_inline = true;
 
 	/* aead_givencrypt shared descriptor */
 	desc = ctx->sh_desc_givenc;
@@ -564,7 +564,7 @@ static int ablkcipher_setkey(struct crypto_ablkcipher *ablkcipher,
 
 	/* ablkcipher_encrypt shared descriptor */
 	desc = ctx->sh_desc_enc;
-	init_sh_desc(desc, HDR_SHARE_WAIT);
+	init_sh_desc(desc, HDR_SHARE_SERIAL);
 	/* Skip if already shared */
 	key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
 				   JUMP_COND_SHRD);
@@ -605,7 +605,7 @@ static int ablkcipher_setkey(struct crypto_ablkcipher *ablkcipher,
 	/* ablkcipher_decrypt shared descriptor */
 	desc = ctx->sh_desc_dec;
 
-	init_sh_desc(desc, HDR_SHARE_WAIT);
+	init_sh_desc(desc, HDR_SHARE_SERIAL);
 	/* Skip if already shared */
 	key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
 				   JUMP_COND_SHRD);
@@ -1354,10 +1354,10 @@ static struct aead_edesc *aead_giv_edesc_alloc(struct aead_givcrypt_request
 		contig &= ~GIV_SRC_CONTIG;
 	if (dst_nents || iv_dma + ivsize != sg_dma_address(req->dst))
 		contig &= ~GIV_DST_CONTIG;
-		if (unlikely(req->src != req->dst)) {
-			dst_nents = dst_nents ? : 1;
-			sec4_sg_len += 1;
-		}
+	if (unlikely(req->src != req->dst)) {
+		dst_nents = dst_nents ? : 1;
+		sec4_sg_len += 1;
+	}
 	if (!(contig & GIV_SRC_CONTIG)) {
 		assoc_nents = assoc_nents ? : 1;
 		src_nents = src_nents ? : 1;
@@ -1650,7 +1650,11 @@ struct caam_alg_template {
 };
 
 static struct caam_alg_template driver_algs[] = {
-	/* single-pass ipsec_esp descriptor */
+	/*
+	 * single-pass ipsec_esp descriptor
+	 * authencesn(*,*) is also registered, although not present
+	 * explicitly here.
+	 */
 	{
 		.name = "authenc(hmac(md5),cbc(aes))",
 		.driver_name = "authenc-hmac-md5-cbc-aes-caam",
@@ -2213,7 +2217,9 @@ static int __init caam_algapi_init(void)
 	for (i = 0; i < ARRAY_SIZE(driver_algs); i++) {
 		/* TODO: check if h/w supports alg */
 		struct caam_crypto_alg *t_alg;
+		bool done = false;
 
+authencesn:
 		t_alg = caam_alg_alloc(ctrldev, &driver_algs[i]);
 		if (IS_ERR(t_alg)) {
 			err = PTR_ERR(t_alg);
@@ -2227,8 +2233,25 @@ static int __init caam_algapi_init(void)
 			dev_warn(ctrldev, "%s alg registration failed\n",
 				t_alg->crypto_alg.cra_driver_name);
 			kfree(t_alg);
-		} else
+		} else {
 			list_add_tail(&t_alg->entry, &priv->alg_list);
+			if (driver_algs[i].type == CRYPTO_ALG_TYPE_AEAD &&
+			    !memcmp(driver_algs[i].name, "authenc", 7) &&
+			    !done) {
+				char *name;
+
+				name = driver_algs[i].name;
+				memmove(name + 10, name + 7, strlen(name) - 7);
+				memcpy(name + 7, "esn", 3);
+
+				name = driver_algs[i].driver_name;
+				memmove(name + 10, name + 7, strlen(name) - 7);
+				memcpy(name + 7, "esn", 3);
+
+				done = true;
+				goto authencesn;
+			}
+		}
 	}
 	if (!list_empty(&priv->alg_list))
 		dev_info(ctrldev, "%s algorithms registered in /proc/crypto\n",
diff --git a/drivers/crypto/caam/caamhash.c b/drivers/crypto/caam/caamhash.c
index 895aaf2..32aba7a 100644
--- a/drivers/crypto/caam/caamhash.c
+++ b/drivers/crypto/caam/caamhash.c
@@ -225,7 +225,7 @@ static inline void init_sh_desc_key_ahash(u32 *desc, struct caam_hash_ctx *ctx)
 {
 	u32 *key_jump_cmd;
 
-	init_sh_desc(desc, HDR_SHARE_WAIT);
+	init_sh_desc(desc, HDR_SHARE_SERIAL);
 
 	if (ctx->split_key_len) {
 		/* Skip if already shared */
@@ -311,7 +311,7 @@ static int ahash_set_sh_desc(struct crypto_ahash *ahash)
 	/* ahash_update shared descriptor */
 	desc = ctx->sh_desc_update;
 
-	init_sh_desc(desc, HDR_SHARE_WAIT);
+	init_sh_desc(desc, HDR_SHARE_SERIAL);
 
 	/* Import context from software */
 	append_cmd(desc, CMD_SEQ_LOAD | LDST_SRCDST_BYTE_CONTEXT |
@@ -430,6 +430,10 @@ static u32 hash_digest_key(struct caam_hash_ctx *ctx, const u8 *key_in,
 	int ret = 0;
 
 	desc = kmalloc(CAAM_CMD_SZ * 6 + CAAM_PTR_SZ * 2, GFP_KERNEL | GFP_DMA);
+	if (!desc) {
+		dev_err(jrdev, "unable to allocate key input memory\n");
+		return -ENOMEM;
+	}
 
 	init_job_desc(desc, 0);
 
@@ -1736,8 +1740,11 @@ static void __exit caam_algapi_hash_exit(void)
 	struct caam_hash_alg *t_alg, *n;
 
 	dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0");
-	if (!dev_node)
-		return;
+	if (!dev_node) {
+		dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0");
+		if (!dev_node)
+			return;
+	}
 
 	pdev = of_find_device_by_node(dev_node);
 	if (!pdev)
@@ -1812,8 +1819,11 @@ static int __init caam_algapi_hash_init(void)
 	int i = 0, err = 0;
 
 	dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0");
-	if (!dev_node)
-		return -ENODEV;
+	if (!dev_node) {
+		dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0");
+		if (!dev_node)
+			return -ENODEV;
+	}
 
 	pdev = of_find_device_by_node(dev_node);
 	if (!pdev)
diff --git a/drivers/crypto/caam/caamrng.c b/drivers/crypto/caam/caamrng.c
index e2bfe16..d1939a9 100644
--- a/drivers/crypto/caam/caamrng.c
+++ b/drivers/crypto/caam/caamrng.c
@@ -193,7 +193,7 @@ static inline void rng_create_sh_desc(struct caam_rng_ctx *ctx)
 	struct device *jrdev = ctx->jrdev;
 	u32 *desc = ctx->sh_desc;
 
-	init_sh_desc(desc, HDR_SHARE_WAIT);
+	init_sh_desc(desc, HDR_SHARE_SERIAL);
 
 	/* Propagate errors from shared to job descriptor */
 	append_cmd(desc, SET_OK_NO_PROP_ERRORS | CMD_LOAD);
@@ -284,8 +284,11 @@ static int __init caam_rng_init(void)
 	struct caam_drv_private *priv;
 
 	dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0");
-	if (!dev_node)
-		return -ENODEV;
+	if (!dev_node) {
+		dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0");
+		if (!dev_node)
+			return -ENODEV;
+	}
 
 	pdev = of_find_device_by_node(dev_node);
 	if (!pdev)
diff --git a/drivers/crypto/caam/compat.h b/drivers/crypto/caam/compat.h
index 762aeff..cf15e78 100644
--- a/drivers/crypto/caam/compat.h
+++ b/drivers/crypto/caam/compat.h
@@ -23,6 +23,7 @@
 #include <linux/types.h>
 #include <linux/debugfs.h>
 #include <linux/circ_buf.h>
+#include <linux/string.h>
 #include <net/xfrm.h>
 
 #include <crypto/algapi.h>
diff --git a/drivers/crypto/caam/key_gen.c b/drivers/crypto/caam/key_gen.c
index d216cd3..f6dba10 100644
--- a/drivers/crypto/caam/key_gen.c
+++ b/drivers/crypto/caam/key_gen.c
@@ -54,6 +54,10 @@ u32 gen_split_key(struct device *jrdev, u8 *key_out, int split_key_len,
 	int ret = 0;
 
 	desc = kmalloc(CAAM_CMD_SZ * 6 + CAAM_PTR_SZ * 2, GFP_KERNEL | GFP_DMA);
+	if (!desc) {
+		dev_err(jrdev, "unable to allocate key input memory\n");
+		return -ENOMEM;
+	}
 
 	init_job_desc(desc, 0);
 
diff --git a/drivers/crypto/geode-aes.c b/drivers/crypto/geode-aes.c
index f3e36c8..51f196d 100644
--- a/drivers/crypto/geode-aes.c
+++ b/drivers/crypto/geode-aes.c
@@ -289,7 +289,6 @@ static struct crypto_alg geode_alg = {
 	.cra_blocksize		=	AES_MIN_BLOCK_SIZE,
 	.cra_ctxsize		=	sizeof(struct geode_aes_op),
 	.cra_module			=	THIS_MODULE,
-	.cra_list			=	LIST_HEAD_INIT(geode_alg.cra_list),
 	.cra_u				=	{
 		.cipher	=	{
 			.cia_min_keysize	=	AES_MIN_KEY_SIZE,
@@ -402,7 +401,6 @@ static struct crypto_alg geode_cbc_alg = {
 	.cra_alignmask		=	15,
 	.cra_type			=	&crypto_blkcipher_type,
 	.cra_module			=	THIS_MODULE,
-	.cra_list			=	LIST_HEAD_INIT(geode_cbc_alg.cra_list),
 	.cra_u				=	{
 		.blkcipher	=	{
 			.min_keysize	=	AES_MIN_KEY_SIZE,
@@ -489,7 +487,6 @@ static struct crypto_alg geode_ecb_alg = {
 	.cra_alignmask		=	15,
 	.cra_type			=	&crypto_blkcipher_type,
 	.cra_module			=	THIS_MODULE,
-	.cra_list			=	LIST_HEAD_INIT(geode_ecb_alg.cra_list),
 	.cra_u				=	{
 		.blkcipher	=	{
 			.min_keysize	=	AES_MIN_KEY_SIZE,
@@ -588,21 +585,8 @@ static struct pci_driver geode_aes_driver = {
 	.remove = __devexit_p(geode_aes_remove)
 };
 
-static int __init
-geode_aes_init(void)
-{
-	return pci_register_driver(&geode_aes_driver);
-}
-
-static void __exit
-geode_aes_exit(void)
-{
-	pci_unregister_driver(&geode_aes_driver);
-}
+module_pci_driver(geode_aes_driver);
 
 MODULE_AUTHOR("Advanced Micro Devices, Inc.");
 MODULE_DESCRIPTION("Geode LX Hardware AES driver");
 MODULE_LICENSE("GPL");
-
-module_init(geode_aes_init);
-module_exit(geode_aes_exit);
diff --git a/drivers/crypto/ixp4xx_crypto.c b/drivers/crypto/ixp4xx_crypto.c
index 8f3f74c..21180d6 100644
--- a/drivers/crypto/ixp4xx_crypto.c
+++ b/drivers/crypto/ixp4xx_crypto.c
@@ -750,12 +750,12 @@ static int setup_cipher(struct crypto_tfm *tfm, int encrypt,
 	}
 	if (cipher_cfg & MOD_AES) {
 		switch (key_len) {
-			case 16: keylen_cfg = MOD_AES128 | KEYLEN_128; break;
-			case 24: keylen_cfg = MOD_AES192 | KEYLEN_192; break;
-			case 32: keylen_cfg = MOD_AES256 | KEYLEN_256; break;
-			default:
-				*flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
-				return -EINVAL;
+		case 16: keylen_cfg = MOD_AES128; break;
+		case 24: keylen_cfg = MOD_AES192; break;
+		case 32: keylen_cfg = MOD_AES256; break;
+		default:
+			*flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+			return -EINVAL;
 		}
 		cipher_cfg |= keylen_cfg;
 	} else if (cipher_cfg & MOD_3DES) {
diff --git a/drivers/crypto/mv_cesa.c b/drivers/crypto/mv_cesa.c
index 21c1a87..24ccae4 100644
--- a/drivers/crypto/mv_cesa.c
+++ b/drivers/crypto/mv_cesa.c
@@ -19,6 +19,9 @@
 #include <linux/clk.h>
 #include <crypto/internal/hash.h>
 #include <crypto/sha.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/of_irq.h>
 
 #include "mv_cesa.h"
 
@@ -1062,7 +1065,10 @@ static int mv_probe(struct platform_device *pdev)
 		goto err_unmap_reg;
 	}
 
-	irq = platform_get_irq(pdev, 0);
+	if (pdev->dev.of_node)
+		irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
+	else
+		irq = platform_get_irq(pdev, 0);
 	if (irq < 0 || irq == NO_IRQ) {
 		ret = irq;
 		goto err_unmap_sram;
@@ -1170,12 +1176,19 @@ static int mv_remove(struct platform_device *pdev)
 	return 0;
 }
 
+static const struct of_device_id mv_cesa_of_match_table[] = {
+	{ .compatible = "marvell,orion-crypto", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, mv_cesa_of_match_table);
+
 static struct platform_driver marvell_crypto = {
 	.probe		= mv_probe,
-	.remove		= mv_remove,
+	.remove		= __devexit_p(mv_remove),
 	.driver		= {
 		.owner	= THIS_MODULE,
 		.name	= "mv_crypto",
+		.of_match_table = of_match_ptr(mv_cesa_of_match_table),
 	},
 };
 MODULE_ALIAS("platform:mv_crypto");
diff --git a/drivers/crypto/n2_core.c b/drivers/crypto/n2_core.c
index a8bd031..aab2574 100644
--- a/drivers/crypto/n2_core.c
+++ b/drivers/crypto/n2_core.c
@@ -42,7 +42,7 @@ MODULE_DESCRIPTION("Niagara2 Crypto driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_MODULE_VERSION);
 
-#define N2_CRA_PRIORITY		300
+#define N2_CRA_PRIORITY		200
 
 static DEFINE_MUTEX(spu_lock);
 
diff --git a/drivers/crypto/nx/Kconfig b/drivers/crypto/nx/Kconfig
new file mode 100644
index 0000000..f826166
--- /dev/null
+++ b/drivers/crypto/nx/Kconfig
@@ -0,0 +1,26 @@
+config CRYPTO_DEV_NX_ENCRYPT
+	tristate "Encryption acceleration support"
+	depends on PPC64 && IBMVIO
+	default y
+	select CRYPTO_AES
+	select CRYPTO_CBC
+	select CRYPTO_ECB
+	select CRYPTO_CCM
+	select CRYPTO_GCM
+	select CRYPTO_AUTHENC
+	select CRYPTO_XCBC
+	select CRYPTO_SHA256
+	select CRYPTO_SHA512
+	help
+	  Support for Power7+ in-Nest encryption acceleration. This
+	  module supports acceleration for AES and SHA2 algorithms. If you
+	  choose 'M' here, this module will be called nx_crypto.
+
+config CRYPTO_DEV_NX_COMPRESS
+	tristate "Compression acceleration support"
+	depends on PPC64 && IBMVIO
+	default y
+	help
+	  Support for Power7+ in-Nest compression acceleration. This
+	  module supports acceleration for AES and SHA2 algorithms. If you
+	  choose 'M' here, this module will be called nx_compress.
diff --git a/drivers/crypto/nx/Makefile b/drivers/crypto/nx/Makefile
index 411ce59..bb770ea 100644
--- a/drivers/crypto/nx/Makefile
+++ b/drivers/crypto/nx/Makefile
@@ -1,4 +1,4 @@
-obj-$(CONFIG_CRYPTO_DEV_NX) += nx-crypto.o
+obj-$(CONFIG_CRYPTO_DEV_NX_ENCRYPT) += nx-crypto.o
 nx-crypto-objs := nx.o \
 		  nx_debugfs.o \
 		  nx-aes-cbc.o \
@@ -9,3 +9,6 @@ nx-crypto-objs := nx.o \
 		  nx-aes-xcbc.o \
 		  nx-sha256.o \
 		  nx-sha512.o
+
+obj-$(CONFIG_CRYPTO_DEV_NX_COMPRESS) += nx-compress.o
+nx-compress-objs := nx-842.o
diff --git a/drivers/crypto/nx/nx-842.c b/drivers/crypto/nx/nx-842.c
new file mode 100644
index 0000000..0ce6257
--- /dev/null
+++ b/drivers/crypto/nx/nx-842.c
@@ -0,0 +1,1617 @@
+/*
+ * Driver for IBM Power 842 compression accelerator
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ * Copyright (C) IBM Corporation, 2012
+ *
+ * Authors: Robert Jennings <rcj@linux.vnet.ibm.com>
+ *          Seth Jennings <sjenning@linux.vnet.ibm.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/nx842.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+
+#include <asm/page.h>
+#include <asm/pSeries_reconfig.h>
+#include <asm/vio.h>
+
+#include "nx_csbcpb.h" /* struct nx_csbcpb */
+
+#define MODULE_NAME "nx-compress"
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Robert Jennings <rcj@linux.vnet.ibm.com>");
+MODULE_DESCRIPTION("842 H/W Compression driver for IBM Power processors");
+
+#define SHIFT_4K 12
+#define SHIFT_64K 16
+#define SIZE_4K (1UL << SHIFT_4K)
+#define SIZE_64K (1UL << SHIFT_64K)
+
+/* IO buffer must be 128 byte aligned */
+#define IO_BUFFER_ALIGN 128
+
+struct nx842_header {
+	int blocks_nr; /* number of compressed blocks */
+	int offset; /* offset of the first block (from beginning of header) */
+	int sizes[0]; /* size of compressed blocks */
+};
+
+static inline int nx842_header_size(const struct nx842_header *hdr)
+{
+	return sizeof(struct nx842_header) +
+			hdr->blocks_nr * sizeof(hdr->sizes[0]);
+}
+
+/* Macros for fields within nx_csbcpb */
+/* Check the valid bit within the csbcpb valid field */
+#define NX842_CSBCBP_VALID_CHK(x) (x & BIT_MASK(7))
+
+/* CE macros operate on the completion_extension field bits in the csbcpb.
+ * CE0 0=full completion, 1=partial completion
+ * CE1 0=CE0 indicates completion, 1=termination (output may be modified)
+ * CE2 0=processed_bytes is source bytes, 1=processed_bytes is target bytes */
+#define NX842_CSBCPB_CE0(x)	(x & BIT_MASK(7))
+#define NX842_CSBCPB_CE1(x)	(x & BIT_MASK(6))
+#define NX842_CSBCPB_CE2(x)	(x & BIT_MASK(5))
+
+/* The NX unit accepts data only on 4K page boundaries */
+#define NX842_HW_PAGE_SHIFT	SHIFT_4K
+#define NX842_HW_PAGE_SIZE	(ASM_CONST(1) << NX842_HW_PAGE_SHIFT)
+#define NX842_HW_PAGE_MASK	(~(NX842_HW_PAGE_SIZE-1))
+
+enum nx842_status {
+	UNAVAILABLE,
+	AVAILABLE
+};
+
+struct ibm_nx842_counters {
+	atomic64_t comp_complete;
+	atomic64_t comp_failed;
+	atomic64_t decomp_complete;
+	atomic64_t decomp_failed;
+	atomic64_t swdecomp;
+	atomic64_t comp_times[32];
+	atomic64_t decomp_times[32];
+};
+
+static struct nx842_devdata {
+	struct vio_dev *vdev;
+	struct device *dev;
+	struct ibm_nx842_counters *counters;
+	unsigned int max_sg_len;
+	unsigned int max_sync_size;
+	unsigned int max_sync_sg;
+	enum nx842_status status;
+} __rcu *devdata;
+static DEFINE_SPINLOCK(devdata_mutex);
+
+#define NX842_COUNTER_INC(_x) \
+static inline void nx842_inc_##_x( \
+	const struct nx842_devdata *dev) { \
+	if (dev) \
+		atomic64_inc(&dev->counters->_x); \
+}
+NX842_COUNTER_INC(comp_complete);
+NX842_COUNTER_INC(comp_failed);
+NX842_COUNTER_INC(decomp_complete);
+NX842_COUNTER_INC(decomp_failed);
+NX842_COUNTER_INC(swdecomp);
+
+#define NX842_HIST_SLOTS 16
+
+static void ibm_nx842_incr_hist(atomic64_t *times, unsigned int time)
+{
+	int bucket = fls(time);
+
+	if (bucket)
+		bucket = min((NX842_HIST_SLOTS - 1), bucket - 1);
+
+	atomic64_inc(&times[bucket]);
+}
+
+/* NX unit operation flags */
+#define NX842_OP_COMPRESS	0x0
+#define NX842_OP_CRC		0x1
+#define NX842_OP_DECOMPRESS	0x2
+#define NX842_OP_COMPRESS_CRC   (NX842_OP_COMPRESS | NX842_OP_CRC)
+#define NX842_OP_DECOMPRESS_CRC (NX842_OP_DECOMPRESS | NX842_OP_CRC)
+#define NX842_OP_ASYNC		(1<<23)
+#define NX842_OP_NOTIFY		(1<<22)
+#define NX842_OP_NOTIFY_INT(x)	((x & 0xff)<<8)
+
+static unsigned long nx842_get_desired_dma(struct vio_dev *viodev)
+{
+	/* No use of DMA mappings within the driver. */
+	return 0;
+}
+
+struct nx842_slentry {
+	unsigned long ptr; /* Real address (use __pa()) */
+	unsigned long len;
+};
+
+/* pHyp scatterlist entry */
+struct nx842_scatterlist {
+	int entry_nr; /* number of slentries */
+	struct nx842_slentry *entries; /* ptr to array of slentries */
+};
+
+/* Does not include sizeof(entry_nr) in the size */
+static inline unsigned long nx842_get_scatterlist_size(
+				struct nx842_scatterlist *sl)
+{
+	return sl->entry_nr * sizeof(struct nx842_slentry);
+}
+
+static int nx842_build_scatterlist(unsigned long buf, int len,
+			struct nx842_scatterlist *sl)
+{
+	unsigned long nextpage;
+	struct nx842_slentry *entry;
+
+	sl->entry_nr = 0;
+
+	entry = sl->entries;
+	while (len) {
+		entry->ptr = __pa(buf);
+		nextpage = ALIGN(buf + 1, NX842_HW_PAGE_SIZE);
+		if (nextpage < buf + len) {
+			/* we aren't at the end yet */
+			if (IS_ALIGNED(buf, NX842_HW_PAGE_SIZE))
+				/* we are in the middle (or beginning) */
+				entry->len = NX842_HW_PAGE_SIZE;
+			else
+				/* we are at the beginning */
+				entry->len = nextpage - buf;
+		} else {
+			/* at the end */
+			entry->len = len;
+		}
+
+		len -= entry->len;
+		buf += entry->len;
+		sl->entry_nr++;
+		entry++;
+	}
+
+	return 0;
+}
+
+/*
+ * Working memory for software decompression
+ */
+struct sw842_fifo {
+	union {
+		char f8[256][8];
+		char f4[512][4];
+	};
+	char f2[256][2];
+	unsigned char f84_full;
+	unsigned char f2_full;
+	unsigned char f8_count;
+	unsigned char f2_count;
+	unsigned int f4_count;
+};
+
+/*
+ * Working memory for crypto API
+ */
+struct nx842_workmem {
+	char bounce[PAGE_SIZE]; /* bounce buffer for decompression input */
+	union {
+		/* hardware working memory */
+		struct {
+			/* scatterlist */
+			char slin[SIZE_4K];
+			char slout[SIZE_4K];
+			/* coprocessor status/parameter block */
+			struct nx_csbcpb csbcpb;
+		};
+		/* software working memory */
+		struct sw842_fifo swfifo; /* software decompression fifo */
+	};
+};
+
+int nx842_get_workmem_size(void)
+{
+	return sizeof(struct nx842_workmem) + NX842_HW_PAGE_SIZE;
+}
+EXPORT_SYMBOL_GPL(nx842_get_workmem_size);
+
+int nx842_get_workmem_size_aligned(void)
+{
+	return sizeof(struct nx842_workmem);
+}
+EXPORT_SYMBOL_GPL(nx842_get_workmem_size_aligned);
+
+static int nx842_validate_result(struct device *dev,
+	struct cop_status_block *csb)
+{
+	/* The csb must be valid after returning from vio_h_cop_sync */
+	if (!NX842_CSBCBP_VALID_CHK(csb->valid)) {
+		dev_err(dev, "%s: cspcbp not valid upon completion.\n",
+				__func__);
+		dev_dbg(dev, "valid:0x%02x cs:0x%02x cc:0x%02x ce:0x%02x\n",
+				csb->valid,
+				csb->crb_seq_number,
+				csb->completion_code,
+				csb->completion_extension);
+		dev_dbg(dev, "processed_bytes:%d address:0x%016lx\n",
+				csb->processed_byte_count,
+				(unsigned long)csb->address);
+		return -EIO;
+	}
+
+	/* Check return values from the hardware in the CSB */
+	switch (csb->completion_code) {
+	case 0:	/* Completed without error */
+		break;
+	case 64: /* Target bytes > Source bytes during compression */
+	case 13: /* Output buffer too small */
+		dev_dbg(dev, "%s: Compression output larger than input\n",
+					__func__);
+		return -ENOSPC;
+	case 66: /* Input data contains an illegal template field */
+	case 67: /* Template indicates data past the end of the input stream */
+		dev_dbg(dev, "%s: Bad data for decompression (code:%d)\n",
+					__func__, csb->completion_code);
+		return -EINVAL;
+	default:
+		dev_dbg(dev, "%s: Unspecified error (code:%d)\n",
+					__func__, csb->completion_code);
+		return -EIO;
+	}
+
+	/* Hardware sanity check */
+	if (!NX842_CSBCPB_CE2(csb->completion_extension)) {
+		dev_err(dev, "%s: No error returned by hardware, but "
+				"data returned is unusable, contact support.\n"
+				"(Additional info: csbcbp->processed bytes "
+				"does not specify processed bytes for the "
+				"target buffer.)\n", __func__);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+/**
+ * nx842_compress - Compress data using the 842 algorithm
+ *
+ * Compression provide by the NX842 coprocessor on IBM Power systems.
+ * The input buffer is compressed and the result is stored in the
+ * provided output buffer.
+ *
+ * Upon return from this function @outlen contains the length of the
+ * compressed data.  If there is an error then @outlen will be 0 and an
+ * error will be specified by the return code from this function.
+ *
+ * @in: Pointer to input buffer, must be page aligned
+ * @inlen: Length of input buffer, must be PAGE_SIZE
+ * @out: Pointer to output buffer
+ * @outlen: Length of output buffer
+ * @wrkmem: ptr to buffer for working memory, size determined by
+ *          nx842_get_workmem_size()
+ *
+ * Returns:
+ *   0		Success, output of length @outlen stored in the buffer at @out
+ *   -ENOMEM	Unable to allocate internal buffers
+ *   -ENOSPC	Output buffer is to small
+ *   -EMSGSIZE	XXX Difficult to describe this limitation
+ *   -EIO	Internal error
+ *   -ENODEV	Hardware unavailable
+ */
+int nx842_compress(const unsigned char *in, unsigned int inlen,
+		       unsigned char *out, unsigned int *outlen, void *wmem)
+{
+	struct nx842_header *hdr;
+	struct nx842_devdata *local_devdata;
+	struct device *dev = NULL;
+	struct nx842_workmem *workmem;
+	struct nx842_scatterlist slin, slout;
+	struct nx_csbcpb *csbcpb;
+	int ret = 0, max_sync_size, i, bytesleft, size, hdrsize;
+	unsigned long inbuf, outbuf, padding;
+	struct vio_pfo_op op = {
+		.done = NULL,
+		.handle = 0,
+		.timeout = 0,
+	};
+	unsigned long start_time = get_tb();
+
+	/*
+	 * Make sure input buffer is 64k page aligned.  This is assumed since
+	 * this driver is designed for page compression only (for now).  This
+	 * is very nice since we can now use direct DDE(s) for the input and
+	 * the alignment is guaranteed.
+	*/
+	inbuf = (unsigned long)in;
+	if (!IS_ALIGNED(inbuf, PAGE_SIZE) || inlen != PAGE_SIZE)
+		return -EINVAL;
+
+	rcu_read_lock();
+	local_devdata = rcu_dereference(devdata);
+	if (!local_devdata || !local_devdata->dev) {
+		rcu_read_unlock();
+		return -ENODEV;
+	}
+	max_sync_size = local_devdata->max_sync_size;
+	dev = local_devdata->dev;
+
+	/* Create the header */
+	hdr = (struct nx842_header *)out;
+	hdr->blocks_nr = PAGE_SIZE / max_sync_size;
+	hdrsize = nx842_header_size(hdr);
+	outbuf = (unsigned long)out + hdrsize;
+	bytesleft = *outlen - hdrsize;
+
+	/* Init scatterlist */
+	workmem = (struct nx842_workmem *)ALIGN((unsigned long)wmem,
+		NX842_HW_PAGE_SIZE);
+	slin.entries = (struct nx842_slentry *)workmem->slin;
+	slout.entries = (struct nx842_slentry *)workmem->slout;
+
+	/* Init operation */
+	op.flags = NX842_OP_COMPRESS;
+	csbcpb = &workmem->csbcpb;
+	memset(csbcpb, 0, sizeof(*csbcpb));
+	op.csbcpb = __pa(csbcpb);
+	op.out = __pa(slout.entries);
+
+	for (i = 0; i < hdr->blocks_nr; i++) {
+		/*
+		 * Aligning the output blocks to 128 bytes does waste space,
+		 * but it prevents the need for bounce buffers and memory
+		 * copies.  It also simplifies the code a lot.  In the worst
+		 * case (64k page, 4k max_sync_size), you lose up to
+		 * (128*16)/64k = ~3% the compression factor. For 64k
+		 * max_sync_size, the loss would be at most 128/64k = ~0.2%.
+		 */
+		padding = ALIGN(outbuf, IO_BUFFER_ALIGN) - outbuf;
+		outbuf += padding;
+		bytesleft -= padding;
+		if (i == 0)
+			/* save offset into first block in header */
+			hdr->offset = padding + hdrsize;
+
+		if (bytesleft <= 0) {
+			ret = -ENOSPC;
+			goto unlock;
+		}
+
+		/*
+		 * NOTE: If the default max_sync_size is changed from 4k
+		 * to 64k, remove the "likely" case below, since a
+		 * scatterlist will always be needed.
+		 */
+		if (likely(max_sync_size == NX842_HW_PAGE_SIZE)) {
+			/* Create direct DDE */
+			op.in = __pa(inbuf);
+			op.inlen = max_sync_size;
+
+		} else {
+			/* Create indirect DDE (scatterlist) */
+			nx842_build_scatterlist(inbuf, max_sync_size, &slin);
+			op.in = __pa(slin.entries);
+			op.inlen = -nx842_get_scatterlist_size(&slin);
+		}
+
+		/*
+		 * If max_sync_size != NX842_HW_PAGE_SIZE, an indirect
+		 * DDE is required for the outbuf.
+		 * If max_sync_size == NX842_HW_PAGE_SIZE, outbuf must
+		 * also be page aligned (1 in 128/4k=32 chance) in order
+		 * to use a direct DDE.
+		 * This is unlikely, just use an indirect DDE always.
+		 */
+		nx842_build_scatterlist(outbuf,
+			min(bytesleft, max_sync_size), &slout);
+		/* op.out set before loop */
+		op.outlen = -nx842_get_scatterlist_size(&slout);
+
+		/* Send request to pHyp */
+		ret = vio_h_cop_sync(local_devdata->vdev, &op);
+
+		/* Check for pHyp error */
+		if (ret) {
+			dev_dbg(dev, "%s: vio_h_cop_sync error (ret=%d, hret=%ld)\n",
+				__func__, ret, op.hcall_err);
+			ret = -EIO;
+			goto unlock;
+		}
+
+		/* Check for hardware error */
+		ret = nx842_validate_result(dev, &csbcpb->csb);
+		if (ret && ret != -ENOSPC)
+			goto unlock;
+
+		/* Handle incompressible data */
+		if (unlikely(ret == -ENOSPC)) {
+			if (bytesleft < max_sync_size) {
+				/*
+				 * Not enough space left in the output buffer
+				 * to store uncompressed block
+				 */
+				goto unlock;
+			} else {
+				/* Store incompressible block */
+				memcpy((void *)outbuf, (void *)inbuf,
+					max_sync_size);
+				hdr->sizes[i] = -max_sync_size;
+				outbuf += max_sync_size;
+				bytesleft -= max_sync_size;
+				/* Reset ret, incompressible data handled */
+				ret = 0;
+			}
+		} else {
+			/* Normal case, compression was successful */
+			size = csbcpb->csb.processed_byte_count;
+			dev_dbg(dev, "%s: processed_bytes=%d\n",
+				__func__, size);
+			hdr->sizes[i] = size;
+			outbuf += size;
+			bytesleft -= size;
+		}
+
+		inbuf += max_sync_size;
+	}
+
+	*outlen = (unsigned int)(outbuf - (unsigned long)out);
+
+unlock:
+	if (ret)
+		nx842_inc_comp_failed(local_devdata);
+	else {
+		nx842_inc_comp_complete(local_devdata);
+		ibm_nx842_incr_hist(local_devdata->counters->comp_times,
+			(get_tb() - start_time) / tb_ticks_per_usec);
+	}
+	rcu_read_unlock();
+	return ret;
+}
+EXPORT_SYMBOL_GPL(nx842_compress);
+
+static int sw842_decompress(const unsigned char *, int, unsigned char *, int *,
+			const void *);
+
+/**
+ * nx842_decompress - Decompress data using the 842 algorithm
+ *
+ * Decompression provide by the NX842 coprocessor on IBM Power systems.
+ * The input buffer is decompressed and the result is stored in the
+ * provided output buffer.  The size allocated to the output buffer is
+ * provided by the caller of this function in @outlen.  Upon return from
+ * this function @outlen contains the length of the decompressed data.
+ * If there is an error then @outlen will be 0 and an error will be
+ * specified by the return code from this function.
+ *
+ * @in: Pointer to input buffer, will use bounce buffer if not 128 byte
+ *      aligned
+ * @inlen: Length of input buffer
+ * @out: Pointer to output buffer, must be page aligned
+ * @outlen: Length of output buffer, must be PAGE_SIZE
+ * @wrkmem: ptr to buffer for working memory, size determined by
+ *          nx842_get_workmem_size()
+ *
+ * Returns:
+ *   0		Success, output of length @outlen stored in the buffer at @out
+ *   -ENODEV	Hardware decompression device is unavailable
+ *   -ENOMEM	Unable to allocate internal buffers
+ *   -ENOSPC	Output buffer is to small
+ *   -EINVAL	Bad input data encountered when attempting decompress
+ *   -EIO	Internal error
+ */
+int nx842_decompress(const unsigned char *in, unsigned int inlen,
+			 unsigned char *out, unsigned int *outlen, void *wmem)
+{
+	struct nx842_header *hdr;
+	struct nx842_devdata *local_devdata;
+	struct device *dev = NULL;
+	struct nx842_workmem *workmem;
+	struct nx842_scatterlist slin, slout;
+	struct nx_csbcpb *csbcpb;
+	int ret = 0, i, size, max_sync_size;
+	unsigned long inbuf, outbuf;
+	struct vio_pfo_op op = {
+		.done = NULL,
+		.handle = 0,
+		.timeout = 0,
+	};
+	unsigned long start_time = get_tb();
+
+	/* Ensure page alignment and size */
+	outbuf = (unsigned long)out;
+	if (!IS_ALIGNED(outbuf, PAGE_SIZE) || *outlen != PAGE_SIZE)
+		return -EINVAL;
+
+	rcu_read_lock();
+	local_devdata = rcu_dereference(devdata);
+	if (local_devdata)
+		dev = local_devdata->dev;
+
+	/* Get header */
+	hdr = (struct nx842_header *)in;
+
+	workmem = (struct nx842_workmem *)ALIGN((unsigned long)wmem,
+		NX842_HW_PAGE_SIZE);
+
+	inbuf = (unsigned long)in + hdr->offset;
+	if (likely(!IS_ALIGNED(inbuf, IO_BUFFER_ALIGN))) {
+		/* Copy block(s) into bounce buffer for alignment */
+		memcpy(workmem->bounce, in + hdr->offset, inlen - hdr->offset);
+		inbuf = (unsigned long)workmem->bounce;
+	}
+
+	/* Init scatterlist */
+	slin.entries = (struct nx842_slentry *)workmem->slin;
+	slout.entries = (struct nx842_slentry *)workmem->slout;
+
+	/* Init operation */
+	op.flags = NX842_OP_DECOMPRESS;
+	csbcpb = &workmem->csbcpb;
+	memset(csbcpb, 0, sizeof(*csbcpb));
+	op.csbcpb = __pa(csbcpb);
+
+	/*
+	 * max_sync_size may have changed since compression,
+	 * so we can't read it from the device info. We need
+	 * to derive it from hdr->blocks_nr.
+	 */
+	max_sync_size = PAGE_SIZE / hdr->blocks_nr;
+
+	for (i = 0; i < hdr->blocks_nr; i++) {
+		/* Skip padding */
+		inbuf = ALIGN(inbuf, IO_BUFFER_ALIGN);
+
+		if (hdr->sizes[i] < 0) {
+			/* Negative sizes indicate uncompressed data blocks */
+			size = abs(hdr->sizes[i]);
+			memcpy((void *)outbuf, (void *)inbuf, size);
+			outbuf += size;
+			inbuf += size;
+			continue;
+		}
+
+		if (!dev)
+			goto sw;
+
+		/*
+		 * The better the compression, the more likely the "likely"
+		 * case becomes.
+		 */
+		if (likely((inbuf & NX842_HW_PAGE_MASK) ==
+			((inbuf + hdr->sizes[i] - 1) & NX842_HW_PAGE_MASK))) {
+			/* Create direct DDE */
+			op.in = __pa(inbuf);
+			op.inlen = hdr->sizes[i];
+		} else {
+			/* Create indirect DDE (scatterlist) */
+			nx842_build_scatterlist(inbuf, hdr->sizes[i] , &slin);
+			op.in = __pa(slin.entries);
+			op.inlen = -nx842_get_scatterlist_size(&slin);
+		}
+
+		/*
+		 * NOTE: If the default max_sync_size is changed from 4k
+		 * to 64k, remove the "likely" case below, since a
+		 * scatterlist will always be needed.
+		 */
+		if (likely(max_sync_size == NX842_HW_PAGE_SIZE)) {
+			/* Create direct DDE */
+			op.out = __pa(outbuf);
+			op.outlen = max_sync_size;
+		} else {
+			/* Create indirect DDE (scatterlist) */
+			nx842_build_scatterlist(outbuf, max_sync_size, &slout);
+			op.out = __pa(slout.entries);
+			op.outlen = -nx842_get_scatterlist_size(&slout);
+		}
+
+		/* Send request to pHyp */
+		ret = vio_h_cop_sync(local_devdata->vdev, &op);
+
+		/* Check for pHyp error */
+		if (ret) {
+			dev_dbg(dev, "%s: vio_h_cop_sync error (ret=%d, hret=%ld)\n",
+				__func__, ret, op.hcall_err);
+			dev = NULL;
+			goto sw;
+		}
+
+		/* Check for hardware error */
+		ret = nx842_validate_result(dev, &csbcpb->csb);
+		if (ret) {
+			dev = NULL;
+			goto sw;
+		}
+
+		/* HW decompression success */
+		inbuf += hdr->sizes[i];
+		outbuf += csbcpb->csb.processed_byte_count;
+		continue;
+
+sw:
+		/* software decompression */
+		size = max_sync_size;
+		ret = sw842_decompress(
+			(unsigned char *)inbuf, hdr->sizes[i],
+			(unsigned char *)outbuf, &size, wmem);
+		if (ret)
+			pr_debug("%s: sw842_decompress failed with %d\n",
+				__func__, ret);
+
+		if (ret) {
+			if (ret != -ENOSPC && ret != -EINVAL &&
+					ret != -EMSGSIZE)
+				ret = -EIO;
+			goto unlock;
+		}
+
+		/* SW decompression success */
+		inbuf += hdr->sizes[i];
+		outbuf += size;
+	}
+
+	*outlen = (unsigned int)(outbuf - (unsigned long)out);
+
+unlock:
+	if (ret)
+		/* decompress fail */
+		nx842_inc_decomp_failed(local_devdata);
+	else {
+		if (!dev)
+			/* software decompress */
+			nx842_inc_swdecomp(local_devdata);
+		nx842_inc_decomp_complete(local_devdata);
+		ibm_nx842_incr_hist(local_devdata->counters->decomp_times,
+			(get_tb() - start_time) / tb_ticks_per_usec);
+	}
+
+	rcu_read_unlock();
+	return ret;
+}
+EXPORT_SYMBOL_GPL(nx842_decompress);
+
+/**
+ * nx842_OF_set_defaults -- Set default (disabled) values for devdata
+ *
+ * @devdata - struct nx842_devdata to update
+ *
+ * Returns:
+ *  0 on success
+ *  -ENOENT if @devdata ptr is NULL
+ */
+static int nx842_OF_set_defaults(struct nx842_devdata *devdata)
+{
+	if (devdata) {
+		devdata->max_sync_size = 0;
+		devdata->max_sync_sg = 0;
+		devdata->max_sg_len = 0;
+		devdata->status = UNAVAILABLE;
+		return 0;
+	} else
+		return -ENOENT;
+}
+
+/**
+ * nx842_OF_upd_status -- Update the device info from OF status prop
+ *
+ * The status property indicates if the accelerator is enabled.  If the
+ * device is in the OF tree it indicates that the hardware is present.
+ * The status field indicates if the device is enabled when the status
+ * is 'okay'.  Otherwise the device driver will be disabled.
+ *
+ * @devdata - struct nx842_devdata to update
+ * @prop - struct property point containing the maxsyncop for the update
+ *
+ * Returns:
+ *  0 - Device is available
+ *  -EINVAL - Device is not available
+ */
+static int nx842_OF_upd_status(struct nx842_devdata *devdata,
+					struct property *prop) {
+	int ret = 0;
+	const char *status = (const char *)prop->value;
+
+	if (!strncmp(status, "okay", (size_t)prop->length)) {
+		devdata->status = AVAILABLE;
+	} else {
+		dev_info(devdata->dev, "%s: status '%s' is not 'okay'\n",
+				__func__, status);
+		devdata->status = UNAVAILABLE;
+	}
+
+	return ret;
+}
+
+/**
+ * nx842_OF_upd_maxsglen -- Update the device info from OF maxsglen prop
+ *
+ * Definition of the 'ibm,max-sg-len' OF property:
+ *  This field indicates the maximum byte length of a scatter list
+ *  for the platform facility. It is a single cell encoded as with encode-int.
+ *
+ * Example:
+ *  # od -x ibm,max-sg-len
+ *  0000000 0000 0ff0
+ *
+ *  In this example, the maximum byte length of a scatter list is
+ *  0x0ff0 (4,080).
+ *
+ * @devdata - struct nx842_devdata to update
+ * @prop - struct property point containing the maxsyncop for the update
+ *
+ * Returns:
+ *  0 on success
+ *  -EINVAL on failure
+ */
+static int nx842_OF_upd_maxsglen(struct nx842_devdata *devdata,
+					struct property *prop) {
+	int ret = 0;
+	const int *maxsglen = prop->value;
+
+	if (prop->length != sizeof(*maxsglen)) {
+		dev_err(devdata->dev, "%s: unexpected format for ibm,max-sg-len property\n", __func__);
+		dev_dbg(devdata->dev, "%s: ibm,max-sg-len is %d bytes long, expected %lu bytes\n", __func__,
+				prop->length, sizeof(*maxsglen));
+		ret = -EINVAL;
+	} else {
+		devdata->max_sg_len = (unsigned int)min(*maxsglen,
+				(int)NX842_HW_PAGE_SIZE);
+	}
+
+	return ret;
+}
+
+/**
+ * nx842_OF_upd_maxsyncop -- Update the device info from OF maxsyncop prop
+ *
+ * Definition of the 'ibm,max-sync-cop' OF property:
+ *  Two series of cells.  The first series of cells represents the maximums
+ *  that can be synchronously compressed. The second series of cells
+ *  represents the maximums that can be synchronously decompressed.
+ *  1. The first cell in each series contains the count of the number of
+ *     data length, scatter list elements pairs that follow – each being
+ *     of the form
+ *    a. One cell data byte length
+ *    b. One cell total number of scatter list elements
+ *
+ * Example:
+ *  # od -x ibm,max-sync-cop
+ *  0000000 0000 0001 0000 1000 0000 01fe 0000 0001
+ *  0000020 0000 1000 0000 01fe
+ *
+ *  In this example, compression supports 0x1000 (4,096) data byte length
+ *  and 0x1fe (510) total scatter list elements.  Decompression supports
+ *  0x1000 (4,096) data byte length and 0x1f3 (510) total scatter list
+ *  elements.
+ *
+ * @devdata - struct nx842_devdata to update
+ * @prop - struct property point containing the maxsyncop for the update
+ *
+ * Returns:
+ *  0 on success
+ *  -EINVAL on failure
+ */
+static int nx842_OF_upd_maxsyncop(struct nx842_devdata *devdata,
+					struct property *prop) {
+	int ret = 0;
+	const struct maxsynccop_t {
+		int comp_elements;
+		int comp_data_limit;
+		int comp_sg_limit;
+		int decomp_elements;
+		int decomp_data_limit;
+		int decomp_sg_limit;
+	} *maxsynccop;
+
+	if (prop->length != sizeof(*maxsynccop)) {
+		dev_err(devdata->dev, "%s: unexpected format for ibm,max-sync-cop property\n", __func__);
+		dev_dbg(devdata->dev, "%s: ibm,max-sync-cop is %d bytes long, expected %lu bytes\n", __func__, prop->length,
+				sizeof(*maxsynccop));
+		ret = -EINVAL;
+		goto out;
+	}
+
+	maxsynccop = (const struct maxsynccop_t *)prop->value;
+
+	/* Use one limit rather than separate limits for compression and
+	 * decompression. Set a maximum for this so as not to exceed the
+	 * size that the header can support and round the value down to
+	 * the hardware page size (4K) */
+	devdata->max_sync_size =
+			(unsigned int)min(maxsynccop->comp_data_limit,
+					maxsynccop->decomp_data_limit);
+
+	devdata->max_sync_size = min_t(unsigned int, devdata->max_sync_size,
+					SIZE_64K);
+
+	if (devdata->max_sync_size < SIZE_4K) {
+		dev_err(devdata->dev, "%s: hardware max data size (%u) is "
+				"less than the driver minimum, unable to use "
+				"the hardware device\n",
+				__func__, devdata->max_sync_size);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	devdata->max_sync_sg = (unsigned int)min(maxsynccop->comp_sg_limit,
+						maxsynccop->decomp_sg_limit);
+	if (devdata->max_sync_sg < 1) {
+		dev_err(devdata->dev, "%s: hardware max sg size (%u) is "
+				"less than the driver minimum, unable to use "
+				"the hardware device\n",
+				__func__, devdata->max_sync_sg);
+		ret = -EINVAL;
+		goto out;
+	}
+
+out:
+	return ret;
+}
+
+/**
+ *
+ * nx842_OF_upd -- Handle OF properties updates for the device.
+ *
+ * Set all properties from the OF tree.  Optionally, a new property
+ * can be provided by the @new_prop pointer to overwrite an existing value.
+ * The device will remain disabled until all values are valid, this function
+ * will return an error for updates unless all values are valid.
+ *
+ * @new_prop: If not NULL, this property is being updated.  If NULL, update
+ *  all properties from the current values in the OF tree.
+ *
+ * Returns:
+ *  0 - Success
+ *  -ENOMEM - Could not allocate memory for new devdata structure
+ *  -EINVAL - property value not found, new_prop is not a recognized
+ *	property for the device or property value is not valid.
+ *  -ENODEV - Device is not available
+ */
+static int nx842_OF_upd(struct property *new_prop)
+{
+	struct nx842_devdata *old_devdata = NULL;
+	struct nx842_devdata *new_devdata = NULL;
+	struct device_node *of_node = NULL;
+	struct property *status = NULL;
+	struct property *maxsglen = NULL;
+	struct property *maxsyncop = NULL;
+	int ret = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&devdata_mutex, flags);
+	old_devdata = rcu_dereference_check(devdata,
+			lockdep_is_held(&devdata_mutex));
+	if (old_devdata)
+		of_node = old_devdata->dev->of_node;
+
+	if (!old_devdata || !of_node) {
+		pr_err("%s: device is not available\n", __func__);
+		spin_unlock_irqrestore(&devdata_mutex, flags);
+		return -ENODEV;
+	}
+
+	new_devdata = kzalloc(sizeof(*new_devdata), GFP_NOFS);
+	if (!new_devdata) {
+		dev_err(old_devdata->dev, "%s: Could not allocate memory for device data\n", __func__);
+		ret = -ENOMEM;
+		goto error_out;
+	}
+
+	memcpy(new_devdata, old_devdata, sizeof(*old_devdata));
+	new_devdata->counters = old_devdata->counters;
+
+	/* Set ptrs for existing properties */
+	status = of_find_property(of_node, "status", NULL);
+	maxsglen = of_find_property(of_node, "ibm,max-sg-len", NULL);
+	maxsyncop = of_find_property(of_node, "ibm,max-sync-cop", NULL);
+	if (!status || !maxsglen || !maxsyncop) {
+		dev_err(old_devdata->dev, "%s: Could not locate device properties\n", __func__);
+		ret = -EINVAL;
+		goto error_out;
+	}
+
+	/* Set ptr to new property if provided */
+	if (new_prop) {
+		/* Single property */
+		if (!strncmp(new_prop->name, "status", new_prop->length)) {
+			status = new_prop;
+
+		} else if (!strncmp(new_prop->name, "ibm,max-sg-len",
+					new_prop->length)) {
+			maxsglen = new_prop;
+
+		} else if (!strncmp(new_prop->name, "ibm,max-sync-cop",
+					new_prop->length)) {
+			maxsyncop = new_prop;
+
+		} else {
+			/*
+			 * Skip the update, the property being updated
+			 * has no impact.
+			 */
+			goto out;
+		}
+	}
+
+	/* Perform property updates */
+	ret = nx842_OF_upd_status(new_devdata, status);
+	if (ret)
+		goto error_out;
+
+	ret = nx842_OF_upd_maxsglen(new_devdata, maxsglen);
+	if (ret)
+		goto error_out;
+
+	ret = nx842_OF_upd_maxsyncop(new_devdata, maxsyncop);
+	if (ret)
+		goto error_out;
+
+out:
+	dev_info(old_devdata->dev, "%s: max_sync_size new:%u old:%u\n",
+			__func__, new_devdata->max_sync_size,
+			old_devdata->max_sync_size);
+	dev_info(old_devdata->dev, "%s: max_sync_sg new:%u old:%u\n",
+			__func__, new_devdata->max_sync_sg,
+			old_devdata->max_sync_sg);
+	dev_info(old_devdata->dev, "%s: max_sg_len new:%u old:%u\n",
+			__func__, new_devdata->max_sg_len,
+			old_devdata->max_sg_len);
+
+	rcu_assign_pointer(devdata, new_devdata);
+	spin_unlock_irqrestore(&devdata_mutex, flags);
+	synchronize_rcu();
+	dev_set_drvdata(new_devdata->dev, new_devdata);
+	kfree(old_devdata);
+	return 0;
+
+error_out:
+	if (new_devdata) {
+		dev_info(old_devdata->dev, "%s: device disabled\n", __func__);
+		nx842_OF_set_defaults(new_devdata);
+		rcu_assign_pointer(devdata, new_devdata);
+		spin_unlock_irqrestore(&devdata_mutex, flags);
+		synchronize_rcu();
+		dev_set_drvdata(new_devdata->dev, new_devdata);
+		kfree(old_devdata);
+	} else {
+		dev_err(old_devdata->dev, "%s: could not update driver from hardware\n", __func__);
+		spin_unlock_irqrestore(&devdata_mutex, flags);
+	}
+
+	if (!ret)
+		ret = -EINVAL;
+	return ret;
+}
+
+/**
+ * nx842_OF_notifier - Process updates to OF properties for the device
+ *
+ * @np: notifier block
+ * @action: notifier action
+ * @update: struct pSeries_reconfig_prop_update pointer if action is
+ *	PSERIES_UPDATE_PROPERTY
+ *
+ * Returns:
+ *	NOTIFY_OK on success
+ *	NOTIFY_BAD encoded with error number on failure, use
+ *		notifier_to_errno() to decode this value
+ */
+static int nx842_OF_notifier(struct notifier_block *np,
+					unsigned long action,
+					void *update)
+{
+	struct pSeries_reconfig_prop_update *upd;
+	struct nx842_devdata *local_devdata;
+	struct device_node *node = NULL;
+
+	upd = (struct pSeries_reconfig_prop_update *)update;
+
+	rcu_read_lock();
+	local_devdata = rcu_dereference(devdata);
+	if (local_devdata)
+		node = local_devdata->dev->of_node;
+
+	if (local_devdata &&
+			action == PSERIES_UPDATE_PROPERTY &&
+			!strcmp(upd->node->name, node->name)) {
+		rcu_read_unlock();
+		nx842_OF_upd(upd->property);
+	} else
+		rcu_read_unlock();
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block nx842_of_nb = {
+	.notifier_call = nx842_OF_notifier,
+};
+
+#define nx842_counter_read(_name)					\
+static ssize_t nx842_##_name##_show(struct device *dev,		\
+		struct device_attribute *attr,				\
+		char *buf) {						\
+	struct nx842_devdata *local_devdata;			\
+	int p = 0;							\
+	rcu_read_lock();						\
+	local_devdata = rcu_dereference(devdata);			\
+	if (local_devdata)						\
+		p = snprintf(buf, PAGE_SIZE, "%ld\n",			\
+		       atomic64_read(&local_devdata->counters->_name));	\
+	rcu_read_unlock();						\
+	return p;							\
+}
+
+#define NX842DEV_COUNTER_ATTR_RO(_name)					\
+	nx842_counter_read(_name);					\
+	static struct device_attribute dev_attr_##_name = __ATTR(_name,	\
+						0444,			\
+						nx842_##_name##_show,\
+						NULL);
+
+NX842DEV_COUNTER_ATTR_RO(comp_complete);
+NX842DEV_COUNTER_ATTR_RO(comp_failed);
+NX842DEV_COUNTER_ATTR_RO(decomp_complete);
+NX842DEV_COUNTER_ATTR_RO(decomp_failed);
+NX842DEV_COUNTER_ATTR_RO(swdecomp);
+
+static ssize_t nx842_timehist_show(struct device *,
+		struct device_attribute *, char *);
+
+static struct device_attribute dev_attr_comp_times = __ATTR(comp_times, 0444,
+		nx842_timehist_show, NULL);
+static struct device_attribute dev_attr_decomp_times = __ATTR(decomp_times,
+		0444, nx842_timehist_show, NULL);
+
+static ssize_t nx842_timehist_show(struct device *dev,
+		struct device_attribute *attr, char *buf) {
+	char *p = buf;
+	struct nx842_devdata *local_devdata;
+	atomic64_t *times;
+	int bytes_remain = PAGE_SIZE;
+	int bytes;
+	int i;
+
+	rcu_read_lock();
+	local_devdata = rcu_dereference(devdata);
+	if (!local_devdata) {
+		rcu_read_unlock();
+		return 0;
+	}
+
+	if (attr == &dev_attr_comp_times)
+		times = local_devdata->counters->comp_times;
+	else if (attr == &dev_attr_decomp_times)
+		times = local_devdata->counters->decomp_times;
+	else {
+		rcu_read_unlock();
+		return 0;
+	}
+
+	for (i = 0; i < (NX842_HIST_SLOTS - 2); i++) {
+		bytes = snprintf(p, bytes_remain, "%u-%uus:\t%ld\n",
+			       i ? (2<<(i-1)) : 0, (2<<i)-1,
+			       atomic64_read(&times[i]));
+		bytes_remain -= bytes;
+		p += bytes;
+	}
+	/* The last bucket holds everything over
+	 * 2<<(NX842_HIST_SLOTS - 2) us */
+	bytes = snprintf(p, bytes_remain, "%uus - :\t%ld\n",
+			2<<(NX842_HIST_SLOTS - 2),
+			atomic64_read(&times[(NX842_HIST_SLOTS - 1)]));
+	p += bytes;
+
+	rcu_read_unlock();
+	return p - buf;
+}
+
+static struct attribute *nx842_sysfs_entries[] = {
+	&dev_attr_comp_complete.attr,
+	&dev_attr_comp_failed.attr,
+	&dev_attr_decomp_complete.attr,
+	&dev_attr_decomp_failed.attr,
+	&dev_attr_swdecomp.attr,
+	&dev_attr_comp_times.attr,
+	&dev_attr_decomp_times.attr,
+	NULL,
+};
+
+static struct attribute_group nx842_attribute_group = {
+	.name = NULL,		/* put in device directory */
+	.attrs = nx842_sysfs_entries,
+};
+
+static int __init nx842_probe(struct vio_dev *viodev,
+				  const struct vio_device_id *id)
+{
+	struct nx842_devdata *old_devdata, *new_devdata = NULL;
+	unsigned long flags;
+	int ret = 0;
+
+	spin_lock_irqsave(&devdata_mutex, flags);
+	old_devdata = rcu_dereference_check(devdata,
+			lockdep_is_held(&devdata_mutex));
+
+	if (old_devdata && old_devdata->vdev != NULL) {
+		dev_err(&viodev->dev, "%s: Attempt to register more than one instance of the hardware\n", __func__);
+		ret = -1;
+		goto error_unlock;
+	}
+
+	dev_set_drvdata(&viodev->dev, NULL);
+
+	new_devdata = kzalloc(sizeof(*new_devdata), GFP_NOFS);
+	if (!new_devdata) {
+		dev_err(&viodev->dev, "%s: Could not allocate memory for device data\n", __func__);
+		ret = -ENOMEM;
+		goto error_unlock;
+	}
+
+	new_devdata->counters = kzalloc(sizeof(*new_devdata->counters),
+			GFP_NOFS);
+	if (!new_devdata->counters) {
+		dev_err(&viodev->dev, "%s: Could not allocate memory for performance counters\n", __func__);
+		ret = -ENOMEM;
+		goto error_unlock;
+	}
+
+	new_devdata->vdev = viodev;
+	new_devdata->dev = &viodev->dev;
+	nx842_OF_set_defaults(new_devdata);
+
+	rcu_assign_pointer(devdata, new_devdata);
+	spin_unlock_irqrestore(&devdata_mutex, flags);
+	synchronize_rcu();
+	kfree(old_devdata);
+
+	pSeries_reconfig_notifier_register(&nx842_of_nb);
+
+	ret = nx842_OF_upd(NULL);
+	if (ret && ret != -ENODEV) {
+		dev_err(&viodev->dev, "could not parse device tree. %d\n", ret);
+		ret = -1;
+		goto error;
+	}
+
+	rcu_read_lock();
+	if (dev_set_drvdata(&viodev->dev, rcu_dereference(devdata))) {
+		rcu_read_unlock();
+		dev_err(&viodev->dev, "failed to set driver data for device\n");
+		ret = -1;
+		goto error;
+	}
+	rcu_read_unlock();
+
+	if (sysfs_create_group(&viodev->dev.kobj, &nx842_attribute_group)) {
+		dev_err(&viodev->dev, "could not create sysfs device attributes\n");
+		ret = -1;
+		goto error;
+	}
+
+	return 0;
+
+error_unlock:
+	spin_unlock_irqrestore(&devdata_mutex, flags);
+	if (new_devdata)
+		kfree(new_devdata->counters);
+	kfree(new_devdata);
+error:
+	return ret;
+}
+
+static int __exit nx842_remove(struct vio_dev *viodev)
+{
+	struct nx842_devdata *old_devdata;
+	unsigned long flags;
+
+	pr_info("Removing IBM Power 842 compression device\n");
+	sysfs_remove_group(&viodev->dev.kobj, &nx842_attribute_group);
+
+	spin_lock_irqsave(&devdata_mutex, flags);
+	old_devdata = rcu_dereference_check(devdata,
+			lockdep_is_held(&devdata_mutex));
+	pSeries_reconfig_notifier_unregister(&nx842_of_nb);
+	rcu_assign_pointer(devdata, NULL);
+	spin_unlock_irqrestore(&devdata_mutex, flags);
+	synchronize_rcu();
+	dev_set_drvdata(&viodev->dev, NULL);
+	if (old_devdata)
+		kfree(old_devdata->counters);
+	kfree(old_devdata);
+	return 0;
+}
+
+static struct vio_device_id nx842_driver_ids[] = {
+	{"ibm,compression-v1", "ibm,compression"},
+	{"", ""},
+};
+
+static struct vio_driver nx842_driver = {
+	.name = MODULE_NAME,
+	.probe = nx842_probe,
+	.remove = nx842_remove,
+	.get_desired_dma = nx842_get_desired_dma,
+	.id_table = nx842_driver_ids,
+};
+
+static int __init nx842_init(void)
+{
+	struct nx842_devdata *new_devdata;
+	pr_info("Registering IBM Power 842 compression driver\n");
+
+	RCU_INIT_POINTER(devdata, NULL);
+	new_devdata = kzalloc(sizeof(*new_devdata), GFP_KERNEL);
+	if (!new_devdata) {
+		pr_err("Could not allocate memory for device data\n");
+		return -ENOMEM;
+	}
+	new_devdata->status = UNAVAILABLE;
+	RCU_INIT_POINTER(devdata, new_devdata);
+
+	return vio_register_driver(&nx842_driver);
+}
+
+module_init(nx842_init);
+
+static void __exit nx842_exit(void)
+{
+	struct nx842_devdata *old_devdata;
+	unsigned long flags;
+
+	pr_info("Exiting IBM Power 842 compression driver\n");
+	spin_lock_irqsave(&devdata_mutex, flags);
+	old_devdata = rcu_dereference_check(devdata,
+			lockdep_is_held(&devdata_mutex));
+	rcu_assign_pointer(devdata, NULL);
+	spin_unlock_irqrestore(&devdata_mutex, flags);
+	synchronize_rcu();
+	if (old_devdata)
+		dev_set_drvdata(old_devdata->dev, NULL);
+	kfree(old_devdata);
+	vio_unregister_driver(&nx842_driver);
+}
+
+module_exit(nx842_exit);
+
+/*********************************
+ * 842 software decompressor
+*********************************/
+typedef int (*sw842_template_op)(const char **, int *, unsigned char **,
+						struct sw842_fifo *);
+
+static int sw842_data8(const char **, int *, unsigned char **,
+						struct sw842_fifo *);
+static int sw842_data4(const char **, int *, unsigned char **,
+						struct sw842_fifo *);
+static int sw842_data2(const char **, int *, unsigned char **,
+						struct sw842_fifo *);
+static int sw842_ptr8(const char **, int *, unsigned char **,
+						struct sw842_fifo *);
+static int sw842_ptr4(const char **, int *, unsigned char **,
+						struct sw842_fifo *);
+static int sw842_ptr2(const char **, int *, unsigned char **,
+						struct sw842_fifo *);
+
+/* special templates */
+#define SW842_TMPL_REPEAT 0x1B
+#define SW842_TMPL_ZEROS 0x1C
+#define SW842_TMPL_EOF 0x1E
+
+static sw842_template_op sw842_tmpl_ops[26][4] = {
+	{ sw842_data8, NULL}, /* 0 (00000) */
+	{ sw842_data4, sw842_data2, sw842_ptr2,  NULL},
+	{ sw842_data4, sw842_ptr2,  sw842_data2, NULL},
+	{ sw842_data4, sw842_ptr2,  sw842_ptr2,  NULL},
+	{ sw842_data4, sw842_ptr4,  NULL},
+	{ sw842_data2, sw842_ptr2,  sw842_data4, NULL},
+	{ sw842_data2, sw842_ptr2,  sw842_data2, sw842_ptr2},
+	{ sw842_data2, sw842_ptr2,  sw842_ptr2,  sw842_data2},
+	{ sw842_data2, sw842_ptr2,  sw842_ptr2,  sw842_ptr2,},
+	{ sw842_data2, sw842_ptr2,  sw842_ptr4,  NULL},
+	{ sw842_ptr2,  sw842_data2, sw842_data4, NULL}, /* 10 (01010) */
+	{ sw842_ptr2,  sw842_data4, sw842_ptr2,  NULL},
+	{ sw842_ptr2,  sw842_data2, sw842_ptr2,  sw842_data2},
+	{ sw842_ptr2,  sw842_data2, sw842_ptr2,  sw842_ptr2},
+	{ sw842_ptr2,  sw842_data2, sw842_ptr4,  NULL},
+	{ sw842_ptr2,  sw842_ptr2,  sw842_data4, NULL},
+	{ sw842_ptr2,  sw842_ptr2,  sw842_data2, sw842_ptr2},
+	{ sw842_ptr2,  sw842_ptr2,  sw842_ptr2,  sw842_data2},
+	{ sw842_ptr2,  sw842_ptr2,  sw842_ptr2,  sw842_ptr2},
+	{ sw842_ptr2,  sw842_ptr2,  sw842_ptr4,  NULL},
+	{ sw842_ptr4,  sw842_data4, NULL}, /* 20 (10100) */
+	{ sw842_ptr4,  sw842_data2, sw842_ptr2,  NULL},
+	{ sw842_ptr4,  sw842_ptr2,  sw842_data2, NULL},
+	{ sw842_ptr4,  sw842_ptr2,  sw842_ptr2,  NULL},
+	{ sw842_ptr4,  sw842_ptr4,  NULL},
+	{ sw842_ptr8,  NULL}
+};
+
+/* Software decompress helpers */
+
+static uint8_t sw842_get_byte(const char *buf, int bit)
+{
+	uint8_t tmpl;
+	uint16_t tmp;
+	tmp = htons(*(uint16_t *)(buf));
+	tmp = (uint16_t)(tmp << bit);
+	tmp = ntohs(tmp);
+	memcpy(&tmpl, &tmp, 1);
+	return tmpl;
+}
+
+static uint8_t sw842_get_template(const char **buf, int *bit)
+{
+	uint8_t byte;
+	byte = sw842_get_byte(*buf, *bit);
+	byte = byte >> 3;
+	byte &= 0x1F;
+	*buf += (*bit + 5) / 8;
+	*bit = (*bit + 5) % 8;
+	return byte;
+}
+
+/* repeat_count happens to be 5-bit too (like the template) */
+static uint8_t sw842_get_repeat_count(const char **buf, int *bit)
+{
+	uint8_t byte;
+	byte = sw842_get_byte(*buf, *bit);
+	byte = byte >> 2;
+	byte &= 0x3F;
+	*buf += (*bit + 6) / 8;
+	*bit = (*bit + 6) % 8;
+	return byte;
+}
+
+static uint8_t sw842_get_ptr2(const char **buf, int *bit)
+{
+	uint8_t ptr;
+	ptr = sw842_get_byte(*buf, *bit);
+	(*buf)++;
+	return ptr;
+}
+
+static uint16_t sw842_get_ptr4(const char **buf, int *bit,
+		struct sw842_fifo *fifo)
+{
+	uint16_t ptr;
+	ptr = htons(*(uint16_t *)(*buf));
+	ptr = (uint16_t)(ptr << *bit);
+	ptr = ptr >> 7;
+	ptr &= 0x01FF;
+	*buf += (*bit + 9) / 8;
+	*bit = (*bit + 9) % 8;
+	return ptr;
+}
+
+static uint8_t sw842_get_ptr8(const char **buf, int *bit,
+		struct sw842_fifo *fifo)
+{
+	return sw842_get_ptr2(buf, bit);
+}
+
+/* Software decompress template ops */
+
+static int sw842_data8(const char **inbuf, int *inbit,
+		unsigned char **outbuf, struct sw842_fifo *fifo)
+{
+	int ret;
+
+	ret = sw842_data4(inbuf, inbit, outbuf, fifo);
+	if (ret)
+		return ret;
+	ret = sw842_data4(inbuf, inbit, outbuf, fifo);
+	return ret;
+}
+
+static int sw842_data4(const char **inbuf, int *inbit,
+		unsigned char **outbuf, struct sw842_fifo *fifo)
+{
+	int ret;
+
+	ret = sw842_data2(inbuf, inbit, outbuf, fifo);
+	if (ret)
+		return ret;
+	ret = sw842_data2(inbuf, inbit, outbuf, fifo);
+	return ret;
+}
+
+static int sw842_data2(const char **inbuf, int *inbit,
+		unsigned char **outbuf, struct sw842_fifo *fifo)
+{
+	**outbuf = sw842_get_byte(*inbuf, *inbit);
+	(*inbuf)++;
+	(*outbuf)++;
+	**outbuf = sw842_get_byte(*inbuf, *inbit);
+	(*inbuf)++;
+	(*outbuf)++;
+	return 0;
+}
+
+static int sw842_ptr8(const char **inbuf, int *inbit,
+		unsigned char **outbuf, struct sw842_fifo *fifo)
+{
+	uint8_t ptr;
+	ptr = sw842_get_ptr8(inbuf, inbit, fifo);
+	if (!fifo->f84_full && (ptr >= fifo->f8_count))
+		return 1;
+	memcpy(*outbuf, fifo->f8[ptr], 8);
+	*outbuf += 8;
+	return 0;
+}
+
+static int sw842_ptr4(const char **inbuf, int *inbit,
+		unsigned char **outbuf, struct sw842_fifo *fifo)
+{
+	uint16_t ptr;
+	ptr = sw842_get_ptr4(inbuf, inbit, fifo);
+	if (!fifo->f84_full && (ptr >= fifo->f4_count))
+		return 1;
+	memcpy(*outbuf, fifo->f4[ptr], 4);
+	*outbuf += 4;
+	return 0;
+}
+
+static int sw842_ptr2(const char **inbuf, int *inbit,
+		unsigned char **outbuf, struct sw842_fifo *fifo)
+{
+	uint8_t ptr;
+	ptr = sw842_get_ptr2(inbuf, inbit);
+	if (!fifo->f2_full && (ptr >= fifo->f2_count))
+		return 1;
+	memcpy(*outbuf, fifo->f2[ptr], 2);
+	*outbuf += 2;
+	return 0;
+}
+
+static void sw842_copy_to_fifo(const char *buf, struct sw842_fifo *fifo)
+{
+	unsigned char initial_f2count = fifo->f2_count;
+
+	memcpy(fifo->f8[fifo->f8_count], buf, 8);
+	fifo->f4_count += 2;
+	fifo->f8_count += 1;
+
+	if (!fifo->f84_full && fifo->f4_count >= 512) {
+		fifo->f84_full = 1;
+		fifo->f4_count /= 512;
+	}
+
+	memcpy(fifo->f2[fifo->f2_count++], buf, 2);
+	memcpy(fifo->f2[fifo->f2_count++], buf + 2, 2);
+	memcpy(fifo->f2[fifo->f2_count++], buf + 4, 2);
+	memcpy(fifo->f2[fifo->f2_count++], buf + 6, 2);
+	if (fifo->f2_count < initial_f2count)
+		fifo->f2_full = 1;
+}
+
+static int sw842_decompress(const unsigned char *src, int srclen,
+			unsigned char *dst, int *destlen,
+			const void *wrkmem)
+{
+	uint8_t tmpl;
+	const char *inbuf;
+	int inbit = 0;
+	unsigned char *outbuf, *outbuf_end, *origbuf, *prevbuf;
+	const char *inbuf_end;
+	sw842_template_op op;
+	int opindex;
+	int i, repeat_count;
+	struct sw842_fifo *fifo;
+	int ret = 0;
+
+	fifo = &((struct nx842_workmem *)(wrkmem))->swfifo;
+	memset(fifo, 0, sizeof(*fifo));
+
+	origbuf = NULL;
+	inbuf = src;
+	inbuf_end = src + srclen;
+	outbuf = dst;
+	outbuf_end = dst + *destlen;
+
+	while ((tmpl = sw842_get_template(&inbuf, &inbit)) != SW842_TMPL_EOF) {
+		if (inbuf >= inbuf_end) {
+			ret = -EINVAL;
+			goto out;
+		}
+
+		opindex = 0;
+		prevbuf = origbuf;
+		origbuf = outbuf;
+		switch (tmpl) {
+		case SW842_TMPL_REPEAT:
+			if (prevbuf == NULL) {
+				ret = -EINVAL;
+				goto out;
+			}
+
+			repeat_count = sw842_get_repeat_count(&inbuf,
+								&inbit) + 1;
+
+			/* Did the repeat count advance past the end of input */
+			if (inbuf > inbuf_end) {
+				ret = -EINVAL;
+				goto out;
+			}
+
+			for (i = 0; i < repeat_count; i++) {
+				/* Would this overflow the output buffer */
+				if ((outbuf + 8) > outbuf_end) {
+					ret = -ENOSPC;
+					goto out;
+				}
+
+				memcpy(outbuf, prevbuf, 8);
+				sw842_copy_to_fifo(outbuf, fifo);
+				outbuf += 8;
+			}
+			break;
+
+		case SW842_TMPL_ZEROS:
+			/* Would this overflow the output buffer */
+			if ((outbuf + 8) > outbuf_end) {
+				ret = -ENOSPC;
+				goto out;
+			}
+
+			memset(outbuf, 0, 8);
+			sw842_copy_to_fifo(outbuf, fifo);
+			outbuf += 8;
+			break;
+
+		default:
+			if (tmpl > 25) {
+				ret = -EINVAL;
+				goto out;
+			}
+
+			/* Does this go past the end of the input buffer */
+			if ((inbuf + 2) > inbuf_end) {
+				ret = -EINVAL;
+				goto out;
+			}
+
+			/* Would this overflow the output buffer */
+			if ((outbuf + 8) > outbuf_end) {
+				ret = -ENOSPC;
+				goto out;
+			}
+
+			while (opindex < 4 &&
+				(op = sw842_tmpl_ops[tmpl][opindex++])
+					!= NULL) {
+				ret = (*op)(&inbuf, &inbit, &outbuf, fifo);
+				if (ret) {
+					ret = -EINVAL;
+					goto out;
+				}
+				sw842_copy_to_fifo(origbuf, fifo);
+			}
+		}
+	}
+
+out:
+	if (!ret)
+		*destlen = (unsigned int)(outbuf - dst);
+	else
+		*destlen = 0;
+
+	return ret;
+}
diff --git a/drivers/crypto/nx/nx-aes-cbc.c b/drivers/crypto/nx/nx-aes-cbc.c
index 69ed796..a76d4c4 100644
--- a/drivers/crypto/nx/nx-aes-cbc.c
+++ b/drivers/crypto/nx/nx-aes-cbc.c
@@ -127,7 +127,6 @@ struct crypto_alg nx_cbc_aes_alg = {
 	.cra_ctxsize     = sizeof(struct nx_crypto_ctx),
 	.cra_type        = &crypto_blkcipher_type,
 	.cra_module      = THIS_MODULE,
-	.cra_list        = LIST_HEAD_INIT(nx_cbc_aes_alg.cra_list),
 	.cra_init        = nx_crypto_ctx_aes_cbc_init,
 	.cra_exit        = nx_crypto_ctx_exit,
 	.cra_blkcipher = {
diff --git a/drivers/crypto/nx/nx-aes-ccm.c b/drivers/crypto/nx/nx-aes-ccm.c
index 7aeac67..ef5eae6 100644
--- a/drivers/crypto/nx/nx-aes-ccm.c
+++ b/drivers/crypto/nx/nx-aes-ccm.c
@@ -430,7 +430,6 @@ struct crypto_alg nx_ccm_aes_alg = {
 	.cra_ctxsize     = sizeof(struct nx_crypto_ctx),
 	.cra_type        = &crypto_aead_type,
 	.cra_module      = THIS_MODULE,
-	.cra_list        = LIST_HEAD_INIT(nx_ccm_aes_alg.cra_list),
 	.cra_init        = nx_crypto_ctx_aes_ccm_init,
 	.cra_exit        = nx_crypto_ctx_exit,
 	.cra_aead = {
@@ -453,7 +452,6 @@ struct crypto_alg nx_ccm4309_aes_alg = {
 	.cra_ctxsize     = sizeof(struct nx_crypto_ctx),
 	.cra_type        = &crypto_nivaead_type,
 	.cra_module      = THIS_MODULE,
-	.cra_list        = LIST_HEAD_INIT(nx_ccm4309_aes_alg.cra_list),
 	.cra_init        = nx_crypto_ctx_aes_ccm_init,
 	.cra_exit        = nx_crypto_ctx_exit,
 	.cra_aead = {
diff --git a/drivers/crypto/nx/nx-aes-ctr.c b/drivers/crypto/nx/nx-aes-ctr.c
index 52d4eb0..b6286f1 100644
--- a/drivers/crypto/nx/nx-aes-ctr.c
+++ b/drivers/crypto/nx/nx-aes-ctr.c
@@ -141,7 +141,6 @@ struct crypto_alg nx_ctr_aes_alg = {
 	.cra_ctxsize     = sizeof(struct nx_crypto_ctx),
 	.cra_type        = &crypto_blkcipher_type,
 	.cra_module      = THIS_MODULE,
-	.cra_list        = LIST_HEAD_INIT(nx_ctr_aes_alg.cra_list),
 	.cra_init        = nx_crypto_ctx_aes_ctr_init,
 	.cra_exit        = nx_crypto_ctx_exit,
 	.cra_blkcipher = {
@@ -163,7 +162,6 @@ struct crypto_alg nx_ctr3686_aes_alg = {
 	.cra_ctxsize     = sizeof(struct nx_crypto_ctx),
 	.cra_type        = &crypto_blkcipher_type,
 	.cra_module      = THIS_MODULE,
-	.cra_list        = LIST_HEAD_INIT(nx_ctr3686_aes_alg.cra_list),
 	.cra_init        = nx_crypto_ctx_aes_ctr_init,
 	.cra_exit        = nx_crypto_ctx_exit,
 	.cra_blkcipher = {
diff --git a/drivers/crypto/nx/nx-aes-ecb.c b/drivers/crypto/nx/nx-aes-ecb.c
index 7b77bc2..ba5f161 100644
--- a/drivers/crypto/nx/nx-aes-ecb.c
+++ b/drivers/crypto/nx/nx-aes-ecb.c
@@ -126,7 +126,6 @@ struct crypto_alg nx_ecb_aes_alg = {
 	.cra_ctxsize     = sizeof(struct nx_crypto_ctx),
 	.cra_type        = &crypto_blkcipher_type,
 	.cra_module      = THIS_MODULE,
-	.cra_list        = LIST_HEAD_INIT(nx_ecb_aes_alg.cra_list),
 	.cra_init        = nx_crypto_ctx_aes_ecb_init,
 	.cra_exit        = nx_crypto_ctx_exit,
 	.cra_blkcipher = {
diff --git a/drivers/crypto/nx/nx-aes-gcm.c b/drivers/crypto/nx/nx-aes-gcm.c
index 9ab1c73..c8109ed 100644
--- a/drivers/crypto/nx/nx-aes-gcm.c
+++ b/drivers/crypto/nx/nx-aes-gcm.c
@@ -316,7 +316,6 @@ struct crypto_alg nx_gcm_aes_alg = {
 	.cra_ctxsize     = sizeof(struct nx_crypto_ctx),
 	.cra_type        = &crypto_aead_type,
 	.cra_module      = THIS_MODULE,
-	.cra_list        = LIST_HEAD_INIT(nx_gcm_aes_alg.cra_list),
 	.cra_init        = nx_crypto_ctx_aes_gcm_init,
 	.cra_exit        = nx_crypto_ctx_exit,
 	.cra_aead = {
@@ -338,7 +337,6 @@ struct crypto_alg nx_gcm4106_aes_alg = {
 	.cra_ctxsize     = sizeof(struct nx_crypto_ctx),
 	.cra_type        = &crypto_nivaead_type,
 	.cra_module      = THIS_MODULE,
-	.cra_list        = LIST_HEAD_INIT(nx_gcm4106_aes_alg.cra_list),
 	.cra_init        = nx_crypto_ctx_aes_gcm_init,
 	.cra_exit        = nx_crypto_ctx_exit,
 	.cra_aead = {
diff --git a/drivers/crypto/nx/nx.c b/drivers/crypto/nx/nx.c
index d7f179c..638110e 100644
--- a/drivers/crypto/nx/nx.c
+++ b/drivers/crypto/nx/nx.c
@@ -34,7 +34,6 @@
 #include <linux/device.h>
 #include <linux/of.h>
 #include <asm/pSeries_reconfig.h>
-#include <asm/abs_addr.h>
 #include <asm/hvcall.h>
 #include <asm/vio.h>
 
@@ -104,10 +103,10 @@ struct nx_sg *nx_build_sg_list(struct nx_sg *sg_head,
 	/* determine the start and end for this address range - slightly
 	 * different if this is in VMALLOC_REGION */
 	if (is_vmalloc_addr(start_addr))
-		sg_addr = phys_to_abs(page_to_phys(vmalloc_to_page(start_addr)))
+		sg_addr = page_to_phys(vmalloc_to_page(start_addr))
 			  + offset_in_page(sg_addr);
 	else
-		sg_addr = virt_to_abs(sg_addr);
+		sg_addr = __pa(sg_addr);
 
 	end_addr = sg_addr + len;
 
@@ -265,17 +264,17 @@ void nx_ctx_init(struct nx_crypto_ctx *nx_ctx, unsigned int function)
 	nx_ctx->csbcpb->csb.valid |= NX_CSB_VALID_BIT;
 
 	nx_ctx->op.flags = function;
-	nx_ctx->op.csbcpb = virt_to_abs(nx_ctx->csbcpb);
-	nx_ctx->op.in = virt_to_abs(nx_ctx->in_sg);
-	nx_ctx->op.out = virt_to_abs(nx_ctx->out_sg);
+	nx_ctx->op.csbcpb = __pa(nx_ctx->csbcpb);
+	nx_ctx->op.in = __pa(nx_ctx->in_sg);
+	nx_ctx->op.out = __pa(nx_ctx->out_sg);
 
 	if (nx_ctx->csbcpb_aead) {
 		nx_ctx->csbcpb_aead->csb.valid |= NX_CSB_VALID_BIT;
 
 		nx_ctx->op_aead.flags = function;
-		nx_ctx->op_aead.csbcpb = virt_to_abs(nx_ctx->csbcpb_aead);
-		nx_ctx->op_aead.in = virt_to_abs(nx_ctx->in_sg);
-		nx_ctx->op_aead.out = virt_to_abs(nx_ctx->out_sg);
+		nx_ctx->op_aead.csbcpb = __pa(nx_ctx->csbcpb_aead);
+		nx_ctx->op_aead.in = __pa(nx_ctx->in_sg);
+		nx_ctx->op_aead.out = __pa(nx_ctx->out_sg);
 	}
 }
 
diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c
index 63e57b5..093a8af 100644
--- a/drivers/crypto/omap-aes.c
+++ b/drivers/crypto/omap-aes.c
@@ -876,7 +876,6 @@ static int omap_aes_probe(struct platform_device *pdev)
 
 	for (i = 0; i < ARRAY_SIZE(algs); i++) {
 		pr_debug("i: %d\n", i);
-		INIT_LIST_HEAD(&algs[i].cra_list);
 		err = crypto_register_alg(&algs[i]);
 		if (err)
 			goto err_algs;
diff --git a/drivers/crypto/padlock-aes.c b/drivers/crypto/padlock-aes.c
index 37b2e94..633ba94 100644
--- a/drivers/crypto/padlock-aes.c
+++ b/drivers/crypto/padlock-aes.c
@@ -328,7 +328,6 @@ static struct crypto_alg aes_alg = {
 	.cra_ctxsize		=	sizeof(struct aes_ctx),
 	.cra_alignmask		=	PADLOCK_ALIGNMENT - 1,
 	.cra_module		=	THIS_MODULE,
-	.cra_list		=	LIST_HEAD_INIT(aes_alg.cra_list),
 	.cra_u			=	{
 		.cipher = {
 			.cia_min_keysize	=	AES_MIN_KEY_SIZE,
@@ -408,7 +407,6 @@ static struct crypto_alg ecb_aes_alg = {
 	.cra_alignmask		=	PADLOCK_ALIGNMENT - 1,
 	.cra_type		=	&crypto_blkcipher_type,
 	.cra_module		=	THIS_MODULE,
-	.cra_list		=	LIST_HEAD_INIT(ecb_aes_alg.cra_list),
 	.cra_u			=	{
 		.blkcipher = {
 			.min_keysize		=	AES_MIN_KEY_SIZE,
@@ -491,7 +489,6 @@ static struct crypto_alg cbc_aes_alg = {
 	.cra_alignmask		=	PADLOCK_ALIGNMENT - 1,
 	.cra_type		=	&crypto_blkcipher_type,
 	.cra_module		=	THIS_MODULE,
-	.cra_list		=	LIST_HEAD_INIT(cbc_aes_alg.cra_list),
 	.cra_u			=	{
 		.blkcipher = {
 			.min_keysize		=	AES_MIN_KEY_SIZE,
diff --git a/drivers/crypto/s5p-sss.c b/drivers/crypto/s5p-sss.c
index bc986f8..a227144 100644
--- a/drivers/crypto/s5p-sss.c
+++ b/drivers/crypto/s5p-sss.c
@@ -626,7 +626,6 @@ static int s5p_aes_probe(struct platform_device *pdev)
 	crypto_init_queue(&pdata->queue, CRYPTO_QUEUE_LEN);
 
 	for (i = 0; i < ARRAY_SIZE(algs); i++) {
-		INIT_LIST_HEAD(&algs[i].cra_list);
 		err = crypto_register_alg(&algs[i]);
 		if (err)
 			goto err_algs;
diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c
index efff788..da11127 100644
--- a/drivers/crypto/talitos.c
+++ b/drivers/crypto/talitos.c
@@ -38,6 +38,7 @@
 #include <linux/spinlock.h>
 #include <linux/rtnetlink.h>
 #include <linux/slab.h>
+#include <linux/string.h>
 
 #include <crypto/algapi.h>
 #include <crypto/aes.h>
@@ -714,8 +715,13 @@ badkey:
 
 /*
  * talitos_edesc - s/w-extended descriptor
+ * @assoc_nents: number of segments in associated data scatterlist
  * @src_nents: number of segments in input scatterlist
  * @dst_nents: number of segments in output scatterlist
+ * @assoc_chained: whether assoc is chained or not
+ * @src_chained: whether src is chained or not
+ * @dst_chained: whether dst is chained or not
+ * @iv_dma: dma address of iv for checking continuity and link table
  * @dma_len: length of dma mapped link_tbl space
  * @dma_link_tbl: bus physical address of link_tbl
  * @desc: h/w descriptor
@@ -726,10 +732,13 @@ badkey:
  * of link_tbl data
  */
 struct talitos_edesc {
+	int assoc_nents;
 	int src_nents;
 	int dst_nents;
-	int src_is_chained;
-	int dst_is_chained;
+	bool assoc_chained;
+	bool src_chained;
+	bool dst_chained;
+	dma_addr_t iv_dma;
 	int dma_len;
 	dma_addr_t dma_link_tbl;
 	struct talitos_desc desc;
@@ -738,7 +747,7 @@ struct talitos_edesc {
 
 static int talitos_map_sg(struct device *dev, struct scatterlist *sg,
 			  unsigned int nents, enum dma_data_direction dir,
-			  int chained)
+			  bool chained)
 {
 	if (unlikely(chained))
 		while (sg) {
@@ -768,13 +777,13 @@ static void talitos_sg_unmap(struct device *dev,
 	unsigned int dst_nents = edesc->dst_nents ? : 1;
 
 	if (src != dst) {
-		if (edesc->src_is_chained)
+		if (edesc->src_chained)
 			talitos_unmap_sg_chain(dev, src, DMA_TO_DEVICE);
 		else
 			dma_unmap_sg(dev, src, src_nents, DMA_TO_DEVICE);
 
 		if (dst) {
-			if (edesc->dst_is_chained)
+			if (edesc->dst_chained)
 				talitos_unmap_sg_chain(dev, dst,
 						       DMA_FROM_DEVICE);
 			else
@@ -782,7 +791,7 @@ static void talitos_sg_unmap(struct device *dev,
 					     DMA_FROM_DEVICE);
 		}
 	} else
-		if (edesc->src_is_chained)
+		if (edesc->src_chained)
 			talitos_unmap_sg_chain(dev, src, DMA_BIDIRECTIONAL);
 		else
 			dma_unmap_sg(dev, src, src_nents, DMA_BIDIRECTIONAL);
@@ -797,7 +806,13 @@ static void ipsec_esp_unmap(struct device *dev,
 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[2], DMA_TO_DEVICE);
 	unmap_single_talitos_ptr(dev, &edesc->desc.ptr[0], DMA_TO_DEVICE);
 
-	dma_unmap_sg(dev, areq->assoc, 1, DMA_TO_DEVICE);
+	if (edesc->assoc_chained)
+		talitos_unmap_sg_chain(dev, areq->assoc, DMA_TO_DEVICE);
+	else
+		/* assoc_nents counts also for IV in non-contiguous cases */
+		dma_unmap_sg(dev, areq->assoc,
+			     edesc->assoc_nents ? edesc->assoc_nents - 1 : 1,
+			     DMA_TO_DEVICE);
 
 	talitos_sg_unmap(dev, edesc, areq->src, areq->dst);
 
@@ -825,9 +840,10 @@ static void ipsec_esp_encrypt_done(struct device *dev,
 	ipsec_esp_unmap(dev, edesc, areq);
 
 	/* copy the generated ICV to dst */
-	if (edesc->dma_len) {
+	if (edesc->dst_nents) {
 		icvdata = &edesc->link_tbl[edesc->src_nents +
-					   edesc->dst_nents + 2];
+					   edesc->dst_nents + 2 +
+					   edesc->assoc_nents];
 		sg = sg_last(areq->dst, edesc->dst_nents);
 		memcpy((char *)sg_virt(sg) + sg->length - ctx->authsize,
 		       icvdata, ctx->authsize);
@@ -857,7 +873,8 @@ static void ipsec_esp_decrypt_swauth_done(struct device *dev,
 		/* auth check */
 		if (edesc->dma_len)
 			icvdata = &edesc->link_tbl[edesc->src_nents +
-						   edesc->dst_nents + 2];
+						   edesc->dst_nents + 2 +
+						   edesc->assoc_nents];
 		else
 			icvdata = &edesc->link_tbl[0];
 
@@ -932,10 +949,9 @@ static int sg_to_link_tbl(struct scatterlist *sg, int sg_count,
  * fill in and submit ipsec_esp descriptor
  */
 static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq,
-		     u8 *giv, u64 seq,
-		     void (*callback) (struct device *dev,
-				       struct talitos_desc *desc,
-				       void *context, int error))
+		     u64 seq, void (*callback) (struct device *dev,
+						struct talitos_desc *desc,
+						void *context, int error))
 {
 	struct crypto_aead *aead = crypto_aead_reqtfm(areq);
 	struct talitos_ctx *ctx = crypto_aead_ctx(aead);
@@ -950,12 +966,42 @@ static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq,
 	/* hmac key */
 	map_single_talitos_ptr(dev, &desc->ptr[0], ctx->authkeylen, &ctx->key,
 			       0, DMA_TO_DEVICE);
+
 	/* hmac data */
-	map_single_talitos_ptr(dev, &desc->ptr[1], areq->assoclen + ivsize,
-			       sg_virt(areq->assoc), 0, DMA_TO_DEVICE);
+	desc->ptr[1].len = cpu_to_be16(areq->assoclen + ivsize);
+	if (edesc->assoc_nents) {
+		int tbl_off = edesc->src_nents + edesc->dst_nents + 2;
+		struct talitos_ptr *tbl_ptr = &edesc->link_tbl[tbl_off];
+
+		to_talitos_ptr(&desc->ptr[1], edesc->dma_link_tbl + tbl_off *
+			       sizeof(struct talitos_ptr));
+		desc->ptr[1].j_extent = DESC_PTR_LNKTBL_JUMP;
+
+		/* assoc_nents - 1 entries for assoc, 1 for IV */
+		sg_count = sg_to_link_tbl(areq->assoc, edesc->assoc_nents - 1,
+					  areq->assoclen, tbl_ptr);
+
+		/* add IV to link table */
+		tbl_ptr += sg_count - 1;
+		tbl_ptr->j_extent = 0;
+		tbl_ptr++;
+		to_talitos_ptr(tbl_ptr, edesc->iv_dma);
+		tbl_ptr->len = cpu_to_be16(ivsize);
+		tbl_ptr->j_extent = DESC_PTR_LNKTBL_RETURN;
+
+		dma_sync_single_for_device(dev, edesc->dma_link_tbl,
+					   edesc->dma_len, DMA_BIDIRECTIONAL);
+	} else {
+		to_talitos_ptr(&desc->ptr[1], sg_dma_address(areq->assoc));
+		desc->ptr[1].j_extent = 0;
+	}
+
 	/* cipher iv */
-	map_single_talitos_ptr(dev, &desc->ptr[2], ivsize, giv ?: areq->iv, 0,
-			       DMA_TO_DEVICE);
+	to_talitos_ptr(&desc->ptr[2], edesc->iv_dma);
+	desc->ptr[2].len = cpu_to_be16(ivsize);
+	desc->ptr[2].j_extent = 0;
+	/* Sync needed for the aead_givencrypt case */
+	dma_sync_single_for_device(dev, edesc->iv_dma, ivsize, DMA_TO_DEVICE);
 
 	/* cipher key */
 	map_single_talitos_ptr(dev, &desc->ptr[3], ctx->enckeylen,
@@ -974,7 +1020,7 @@ static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq,
 	sg_count = talitos_map_sg(dev, areq->src, edesc->src_nents ? : 1,
 				  (areq->src == areq->dst) ? DMA_BIDIRECTIONAL
 							   : DMA_TO_DEVICE,
-				  edesc->src_is_chained);
+				  edesc->src_chained);
 
 	if (sg_count == 1) {
 		to_talitos_ptr(&desc->ptr[4], sg_dma_address(areq->src));
@@ -1006,32 +1052,30 @@ static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq,
 	if (areq->src != areq->dst)
 		sg_count = talitos_map_sg(dev, areq->dst,
 					  edesc->dst_nents ? : 1,
-					  DMA_FROM_DEVICE,
-					  edesc->dst_is_chained);
+					  DMA_FROM_DEVICE, edesc->dst_chained);
 
 	if (sg_count == 1) {
 		to_talitos_ptr(&desc->ptr[5], sg_dma_address(areq->dst));
 	} else {
-		struct talitos_ptr *link_tbl_ptr =
-			&edesc->link_tbl[edesc->src_nents + 1];
+		int tbl_off = edesc->src_nents + 1;
+		struct talitos_ptr *tbl_ptr = &edesc->link_tbl[tbl_off];
 
 		to_talitos_ptr(&desc->ptr[5], edesc->dma_link_tbl +
-			       (edesc->src_nents + 1) *
-			       sizeof(struct talitos_ptr));
+			       tbl_off * sizeof(struct talitos_ptr));
 		sg_count = sg_to_link_tbl(areq->dst, sg_count, cryptlen,
-					  link_tbl_ptr);
+					  tbl_ptr);
 
 		/* Add an entry to the link table for ICV data */
-		link_tbl_ptr += sg_count - 1;
-		link_tbl_ptr->j_extent = 0;
-		sg_count++;
-		link_tbl_ptr++;
-		link_tbl_ptr->j_extent = DESC_PTR_LNKTBL_RETURN;
-		link_tbl_ptr->len = cpu_to_be16(authsize);
+		tbl_ptr += sg_count - 1;
+		tbl_ptr->j_extent = 0;
+		tbl_ptr++;
+		tbl_ptr->j_extent = DESC_PTR_LNKTBL_RETURN;
+		tbl_ptr->len = cpu_to_be16(authsize);
 
 		/* icv data follows link tables */
-		to_talitos_ptr(link_tbl_ptr, edesc->dma_link_tbl +
-			       (edesc->src_nents + edesc->dst_nents + 2) *
+		to_talitos_ptr(tbl_ptr, edesc->dma_link_tbl +
+			       (tbl_off + edesc->dst_nents + 1 +
+				edesc->assoc_nents) *
 			       sizeof(struct talitos_ptr));
 		desc->ptr[5].j_extent |= DESC_PTR_LNKTBL_JUMP;
 		dma_sync_single_for_device(ctx->dev, edesc->dma_link_tbl,
@@ -1053,17 +1097,17 @@ static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq,
 /*
  * derive number of elements in scatterlist
  */
-static int sg_count(struct scatterlist *sg_list, int nbytes, int *chained)
+static int sg_count(struct scatterlist *sg_list, int nbytes, bool *chained)
 {
 	struct scatterlist *sg = sg_list;
 	int sg_nents = 0;
 
-	*chained = 0;
+	*chained = false;
 	while (nbytes > 0) {
 		sg_nents++;
 		nbytes -= sg->length;
 		if (!sg_is_last(sg) && (sg + 1)->length == 0)
-			*chained = 1;
+			*chained = true;
 		sg = scatterwalk_sg_next(sg);
 	}
 
@@ -1132,17 +1176,21 @@ static size_t sg_copy_end_to_buffer(struct scatterlist *sgl, unsigned int nents,
  * allocate and map the extended descriptor
  */
 static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
+						 struct scatterlist *assoc,
 						 struct scatterlist *src,
 						 struct scatterlist *dst,
-						 int hash_result,
+						 u8 *iv,
+						 unsigned int assoclen,
 						 unsigned int cryptlen,
 						 unsigned int authsize,
+						 unsigned int ivsize,
 						 int icv_stashing,
 						 u32 cryptoflags)
 {
 	struct talitos_edesc *edesc;
-	int src_nents, dst_nents, alloc_len, dma_len;
-	int src_chained, dst_chained = 0;
+	int assoc_nents = 0, src_nents, dst_nents, alloc_len, dma_len;
+	bool assoc_chained = false, src_chained = false, dst_chained = false;
+	dma_addr_t iv_dma = 0;
 	gfp_t flags = cryptoflags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL :
 		      GFP_ATOMIC;
 
@@ -1151,10 +1199,29 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
 		return ERR_PTR(-EINVAL);
 	}
 
+	if (iv)
+		iv_dma = dma_map_single(dev, iv, ivsize, DMA_TO_DEVICE);
+
+	if (assoc) {
+		/*
+		 * Currently it is assumed that iv is provided whenever assoc
+		 * is.
+		 */
+		BUG_ON(!iv);
+
+		assoc_nents = sg_count(assoc, assoclen, &assoc_chained);
+		talitos_map_sg(dev, assoc, assoc_nents, DMA_TO_DEVICE,
+			       assoc_chained);
+		assoc_nents = (assoc_nents == 1) ? 0 : assoc_nents;
+
+		if (assoc_nents || sg_dma_address(assoc) + assoclen != iv_dma)
+			assoc_nents = assoc_nents ? assoc_nents + 1 : 2;
+	}
+
 	src_nents = sg_count(src, cryptlen + authsize, &src_chained);
 	src_nents = (src_nents == 1) ? 0 : src_nents;
 
-	if (hash_result) {
+	if (!dst) {
 		dst_nents = 0;
 	} else {
 		if (dst == src) {
@@ -1172,9 +1239,9 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
 	 * and the ICV data itself
 	 */
 	alloc_len = sizeof(struct talitos_edesc);
-	if (src_nents || dst_nents) {
-		dma_len = (src_nents + dst_nents + 2) *
-				 sizeof(struct talitos_ptr) + authsize;
+	if (assoc_nents || src_nents || dst_nents) {
+		dma_len = (src_nents + dst_nents + 2 + assoc_nents) *
+			  sizeof(struct talitos_ptr) + authsize;
 		alloc_len += dma_len;
 	} else {
 		dma_len = 0;
@@ -1183,14 +1250,20 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
 
 	edesc = kmalloc(alloc_len, GFP_DMA | flags);
 	if (!edesc) {
+		talitos_unmap_sg_chain(dev, assoc, DMA_TO_DEVICE);
+		if (iv_dma)
+			dma_unmap_single(dev, iv_dma, ivsize, DMA_TO_DEVICE);
 		dev_err(dev, "could not allocate edescriptor\n");
 		return ERR_PTR(-ENOMEM);
 	}
 
+	edesc->assoc_nents = assoc_nents;
 	edesc->src_nents = src_nents;
 	edesc->dst_nents = dst_nents;
-	edesc->src_is_chained = src_chained;
-	edesc->dst_is_chained = dst_chained;
+	edesc->assoc_chained = assoc_chained;
+	edesc->src_chained = src_chained;
+	edesc->dst_chained = dst_chained;
+	edesc->iv_dma = iv_dma;
 	edesc->dma_len = dma_len;
 	if (dma_len)
 		edesc->dma_link_tbl = dma_map_single(dev, &edesc->link_tbl[0],
@@ -1200,14 +1273,16 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
 	return edesc;
 }
 
-static struct talitos_edesc *aead_edesc_alloc(struct aead_request *areq,
+static struct talitos_edesc *aead_edesc_alloc(struct aead_request *areq, u8 *iv,
 					      int icv_stashing)
 {
 	struct crypto_aead *authenc = crypto_aead_reqtfm(areq);
 	struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
+	unsigned int ivsize = crypto_aead_ivsize(authenc);
 
-	return talitos_edesc_alloc(ctx->dev, areq->src, areq->dst, 0,
-				   areq->cryptlen, ctx->authsize, icv_stashing,
+	return talitos_edesc_alloc(ctx->dev, areq->assoc, areq->src, areq->dst,
+				   iv, areq->assoclen, areq->cryptlen,
+				   ctx->authsize, ivsize, icv_stashing,
 				   areq->base.flags);
 }
 
@@ -1218,14 +1293,14 @@ static int aead_encrypt(struct aead_request *req)
 	struct talitos_edesc *edesc;
 
 	/* allocate extended descriptor */
-	edesc = aead_edesc_alloc(req, 0);
+	edesc = aead_edesc_alloc(req, req->iv, 0);
 	if (IS_ERR(edesc))
 		return PTR_ERR(edesc);
 
 	/* set encrypt */
 	edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_MODE0_ENCRYPT;
 
-	return ipsec_esp(edesc, req, NULL, 0, ipsec_esp_encrypt_done);
+	return ipsec_esp(edesc, req, 0, ipsec_esp_encrypt_done);
 }
 
 static int aead_decrypt(struct aead_request *req)
@@ -1241,7 +1316,7 @@ static int aead_decrypt(struct aead_request *req)
 	req->cryptlen -= authsize;
 
 	/* allocate extended descriptor */
-	edesc = aead_edesc_alloc(req, 1);
+	edesc = aead_edesc_alloc(req, req->iv, 1);
 	if (IS_ERR(edesc))
 		return PTR_ERR(edesc);
 
@@ -1257,9 +1332,7 @@ static int aead_decrypt(struct aead_request *req)
 		/* reset integrity check result bits */
 		edesc->desc.hdr_lo = 0;
 
-		return ipsec_esp(edesc, req, NULL, 0,
-				 ipsec_esp_decrypt_hwauth_done);
-
+		return ipsec_esp(edesc, req, 0, ipsec_esp_decrypt_hwauth_done);
 	}
 
 	/* Have to check the ICV with software */
@@ -1268,7 +1341,8 @@ static int aead_decrypt(struct aead_request *req)
 	/* stash incoming ICV for later cmp with ICV generated by the h/w */
 	if (edesc->dma_len)
 		icvdata = &edesc->link_tbl[edesc->src_nents +
-					   edesc->dst_nents + 2];
+					   edesc->dst_nents + 2 +
+					   edesc->assoc_nents];
 	else
 		icvdata = &edesc->link_tbl[0];
 
@@ -1277,7 +1351,7 @@ static int aead_decrypt(struct aead_request *req)
 	memcpy(icvdata, (char *)sg_virt(sg) + sg->length - ctx->authsize,
 	       ctx->authsize);
 
-	return ipsec_esp(edesc, req, NULL, 0, ipsec_esp_decrypt_swauth_done);
+	return ipsec_esp(edesc, req, 0, ipsec_esp_decrypt_swauth_done);
 }
 
 static int aead_givencrypt(struct aead_givcrypt_request *req)
@@ -1288,7 +1362,7 @@ static int aead_givencrypt(struct aead_givcrypt_request *req)
 	struct talitos_edesc *edesc;
 
 	/* allocate extended descriptor */
-	edesc = aead_edesc_alloc(areq, 0);
+	edesc = aead_edesc_alloc(areq, req->giv, 0);
 	if (IS_ERR(edesc))
 		return PTR_ERR(edesc);
 
@@ -1299,8 +1373,7 @@ static int aead_givencrypt(struct aead_givcrypt_request *req)
 	/* avoid consecutive packets going out with same IV */
 	*(__be64 *)req->giv ^= cpu_to_be64(req->seq);
 
-	return ipsec_esp(edesc, areq, req->giv, req->seq,
-			 ipsec_esp_encrypt_done);
+	return ipsec_esp(edesc, areq, req->seq, ipsec_esp_encrypt_done);
 }
 
 static int ablkcipher_setkey(struct crypto_ablkcipher *cipher,
@@ -1356,7 +1429,7 @@ static int common_nonsnoop(struct talitos_edesc *edesc,
 	struct device *dev = ctx->dev;
 	struct talitos_desc *desc = &edesc->desc;
 	unsigned int cryptlen = areq->nbytes;
-	unsigned int ivsize;
+	unsigned int ivsize = crypto_ablkcipher_ivsize(cipher);
 	int sg_count, ret;
 
 	/* first DWORD empty */
@@ -1365,9 +1438,9 @@ static int common_nonsnoop(struct talitos_edesc *edesc,
 	desc->ptr[0].j_extent = 0;
 
 	/* cipher iv */
-	ivsize = crypto_ablkcipher_ivsize(cipher);
-	map_single_talitos_ptr(dev, &desc->ptr[1], ivsize, areq->info, 0,
-			       DMA_TO_DEVICE);
+	to_talitos_ptr(&desc->ptr[1], edesc->iv_dma);
+	desc->ptr[1].len = cpu_to_be16(ivsize);
+	desc->ptr[1].j_extent = 0;
 
 	/* cipher key */
 	map_single_talitos_ptr(dev, &desc->ptr[2], ctx->keylen,
@@ -1382,7 +1455,7 @@ static int common_nonsnoop(struct talitos_edesc *edesc,
 	sg_count = talitos_map_sg(dev, areq->src, edesc->src_nents ? : 1,
 				  (areq->src == areq->dst) ? DMA_BIDIRECTIONAL
 							   : DMA_TO_DEVICE,
-				  edesc->src_is_chained);
+				  edesc->src_chained);
 
 	if (sg_count == 1) {
 		to_talitos_ptr(&desc->ptr[3], sg_dma_address(areq->src));
@@ -1409,8 +1482,7 @@ static int common_nonsnoop(struct talitos_edesc *edesc,
 	if (areq->src != areq->dst)
 		sg_count = talitos_map_sg(dev, areq->dst,
 					  edesc->dst_nents ? : 1,
-					  DMA_FROM_DEVICE,
-					  edesc->dst_is_chained);
+					  DMA_FROM_DEVICE, edesc->dst_chained);
 
 	if (sg_count == 1) {
 		to_talitos_ptr(&desc->ptr[4], sg_dma_address(areq->dst));
@@ -1450,9 +1522,11 @@ static struct talitos_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request *
 {
 	struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
 	struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
+	unsigned int ivsize = crypto_ablkcipher_ivsize(cipher);
 
-	return talitos_edesc_alloc(ctx->dev, areq->src, areq->dst, 0,
-				   areq->nbytes, 0, 0, areq->base.flags);
+	return talitos_edesc_alloc(ctx->dev, NULL, areq->src, areq->dst,
+				   areq->info, 0, areq->nbytes, 0, ivsize, 0,
+				   areq->base.flags);
 }
 
 static int ablkcipher_encrypt(struct ablkcipher_request *areq)
@@ -1578,8 +1652,7 @@ static int common_nonsnoop_hash(struct talitos_edesc *edesc,
 
 	sg_count = talitos_map_sg(dev, req_ctx->psrc,
 				  edesc->src_nents ? : 1,
-				  DMA_TO_DEVICE,
-				  edesc->src_is_chained);
+				  DMA_TO_DEVICE, edesc->src_chained);
 
 	if (sg_count == 1) {
 		to_talitos_ptr(&desc->ptr[3], sg_dma_address(req_ctx->psrc));
@@ -1631,8 +1704,8 @@ static struct talitos_edesc *ahash_edesc_alloc(struct ahash_request *areq,
 	struct talitos_ctx *ctx = crypto_ahash_ctx(tfm);
 	struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
 
-	return talitos_edesc_alloc(ctx->dev, req_ctx->psrc, NULL, 1,
-				   nbytes, 0, 0, areq->base.flags);
+	return talitos_edesc_alloc(ctx->dev, NULL, req_ctx->psrc, NULL, NULL, 0,
+				   nbytes, 0, 0, 0, areq->base.flags);
 }
 
 static int ahash_init(struct ahash_request *areq)
@@ -1690,7 +1763,7 @@ static int ahash_process_req(struct ahash_request *areq, unsigned int nbytes)
 	unsigned int nbytes_to_hash;
 	unsigned int to_hash_later;
 	unsigned int nsg;
-	int chained;
+	bool chained;
 
 	if (!req_ctx->last && (nbytes + req_ctx->nbuf <= blocksize)) {
 		/* Buffer up to one whole block */
@@ -1902,21 +1975,18 @@ struct talitos_alg_template {
 };
 
 static struct talitos_alg_template driver_algs[] = {
-	/* AEAD algorithms.  These use a single-pass ipsec_esp descriptor */
+	/*
+	 * AEAD algorithms. These use a single-pass ipsec_esp descriptor.
+	 * authencesn(*,*) is also registered, although not present
+	 * explicitly here.
+	 */
 	{	.type = CRYPTO_ALG_TYPE_AEAD,
 		.alg.crypto = {
 			.cra_name = "authenc(hmac(sha1),cbc(aes))",
 			.cra_driver_name = "authenc-hmac-sha1-cbc-aes-talitos",
 			.cra_blocksize = AES_BLOCK_SIZE,
 			.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
-			.cra_type = &crypto_aead_type,
 			.cra_aead = {
-				.setkey = aead_setkey,
-				.setauthsize = aead_setauthsize,
-				.encrypt = aead_encrypt,
-				.decrypt = aead_decrypt,
-				.givencrypt = aead_givencrypt,
-				.geniv = "<built-in>",
 				.ivsize = AES_BLOCK_SIZE,
 				.maxauthsize = SHA1_DIGEST_SIZE,
 			}
@@ -1935,14 +2005,7 @@ static struct talitos_alg_template driver_algs[] = {
 			.cra_driver_name = "authenc-hmac-sha1-cbc-3des-talitos",
 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
 			.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
-			.cra_type = &crypto_aead_type,
 			.cra_aead = {
-				.setkey = aead_setkey,
-				.setauthsize = aead_setauthsize,
-				.encrypt = aead_encrypt,
-				.decrypt = aead_decrypt,
-				.givencrypt = aead_givencrypt,
-				.geniv = "<built-in>",
 				.ivsize = DES3_EDE_BLOCK_SIZE,
 				.maxauthsize = SHA1_DIGEST_SIZE,
 			}
@@ -1962,14 +2025,7 @@ static struct talitos_alg_template driver_algs[] = {
 			.cra_driver_name = "authenc-hmac-sha224-cbc-aes-talitos",
 			.cra_blocksize = AES_BLOCK_SIZE,
 			.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
-			.cra_type = &crypto_aead_type,
 			.cra_aead = {
-				.setkey = aead_setkey,
-				.setauthsize = aead_setauthsize,
-				.encrypt = aead_encrypt,
-				.decrypt = aead_decrypt,
-				.givencrypt = aead_givencrypt,
-				.geniv = "<built-in>",
 				.ivsize = AES_BLOCK_SIZE,
 				.maxauthsize = SHA224_DIGEST_SIZE,
 			}
@@ -1988,14 +2044,7 @@ static struct talitos_alg_template driver_algs[] = {
 			.cra_driver_name = "authenc-hmac-sha224-cbc-3des-talitos",
 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
 			.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
-			.cra_type = &crypto_aead_type,
 			.cra_aead = {
-				.setkey = aead_setkey,
-				.setauthsize = aead_setauthsize,
-				.encrypt = aead_encrypt,
-				.decrypt = aead_decrypt,
-				.givencrypt = aead_givencrypt,
-				.geniv = "<built-in>",
 				.ivsize = DES3_EDE_BLOCK_SIZE,
 				.maxauthsize = SHA224_DIGEST_SIZE,
 			}
@@ -2015,14 +2064,7 @@ static struct talitos_alg_template driver_algs[] = {
 			.cra_driver_name = "authenc-hmac-sha256-cbc-aes-talitos",
 			.cra_blocksize = AES_BLOCK_SIZE,
 			.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
-			.cra_type = &crypto_aead_type,
 			.cra_aead = {
-				.setkey = aead_setkey,
-				.setauthsize = aead_setauthsize,
-				.encrypt = aead_encrypt,
-				.decrypt = aead_decrypt,
-				.givencrypt = aead_givencrypt,
-				.geniv = "<built-in>",
 				.ivsize = AES_BLOCK_SIZE,
 				.maxauthsize = SHA256_DIGEST_SIZE,
 			}
@@ -2041,14 +2083,7 @@ static struct talitos_alg_template driver_algs[] = {
 			.cra_driver_name = "authenc-hmac-sha256-cbc-3des-talitos",
 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
 			.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
-			.cra_type = &crypto_aead_type,
 			.cra_aead = {
-				.setkey = aead_setkey,
-				.setauthsize = aead_setauthsize,
-				.encrypt = aead_encrypt,
-				.decrypt = aead_decrypt,
-				.givencrypt = aead_givencrypt,
-				.geniv = "<built-in>",
 				.ivsize = DES3_EDE_BLOCK_SIZE,
 				.maxauthsize = SHA256_DIGEST_SIZE,
 			}
@@ -2068,14 +2103,7 @@ static struct talitos_alg_template driver_algs[] = {
 			.cra_driver_name = "authenc-hmac-sha384-cbc-aes-talitos",
 			.cra_blocksize = AES_BLOCK_SIZE,
 			.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
-			.cra_type = &crypto_aead_type,
 			.cra_aead = {
-				.setkey = aead_setkey,
-				.setauthsize = aead_setauthsize,
-				.encrypt = aead_encrypt,
-				.decrypt = aead_decrypt,
-				.givencrypt = aead_givencrypt,
-				.geniv = "<built-in>",
 				.ivsize = AES_BLOCK_SIZE,
 				.maxauthsize = SHA384_DIGEST_SIZE,
 			}
@@ -2094,14 +2122,7 @@ static struct talitos_alg_template driver_algs[] = {
 			.cra_driver_name = "authenc-hmac-sha384-cbc-3des-talitos",
 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
 			.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
-			.cra_type = &crypto_aead_type,
 			.cra_aead = {
-				.setkey = aead_setkey,
-				.setauthsize = aead_setauthsize,
-				.encrypt = aead_encrypt,
-				.decrypt = aead_decrypt,
-				.givencrypt = aead_givencrypt,
-				.geniv = "<built-in>",
 				.ivsize = DES3_EDE_BLOCK_SIZE,
 				.maxauthsize = SHA384_DIGEST_SIZE,
 			}
@@ -2121,14 +2142,7 @@ static struct talitos_alg_template driver_algs[] = {
 			.cra_driver_name = "authenc-hmac-sha512-cbc-aes-talitos",
 			.cra_blocksize = AES_BLOCK_SIZE,
 			.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
-			.cra_type = &crypto_aead_type,
 			.cra_aead = {
-				.setkey = aead_setkey,
-				.setauthsize = aead_setauthsize,
-				.encrypt = aead_encrypt,
-				.decrypt = aead_decrypt,
-				.givencrypt = aead_givencrypt,
-				.geniv = "<built-in>",
 				.ivsize = AES_BLOCK_SIZE,
 				.maxauthsize = SHA512_DIGEST_SIZE,
 			}
@@ -2147,14 +2161,7 @@ static struct talitos_alg_template driver_algs[] = {
 			.cra_driver_name = "authenc-hmac-sha512-cbc-3des-talitos",
 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
 			.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
-			.cra_type = &crypto_aead_type,
 			.cra_aead = {
-				.setkey = aead_setkey,
-				.setauthsize = aead_setauthsize,
-				.encrypt = aead_encrypt,
-				.decrypt = aead_decrypt,
-				.givencrypt = aead_givencrypt,
-				.geniv = "<built-in>",
 				.ivsize = DES3_EDE_BLOCK_SIZE,
 				.maxauthsize = SHA512_DIGEST_SIZE,
 			}
@@ -2174,14 +2181,7 @@ static struct talitos_alg_template driver_algs[] = {
 			.cra_driver_name = "authenc-hmac-md5-cbc-aes-talitos",
 			.cra_blocksize = AES_BLOCK_SIZE,
 			.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
-			.cra_type = &crypto_aead_type,
 			.cra_aead = {
-				.setkey = aead_setkey,
-				.setauthsize = aead_setauthsize,
-				.encrypt = aead_encrypt,
-				.decrypt = aead_decrypt,
-				.givencrypt = aead_givencrypt,
-				.geniv = "<built-in>",
 				.ivsize = AES_BLOCK_SIZE,
 				.maxauthsize = MD5_DIGEST_SIZE,
 			}
@@ -2200,14 +2200,7 @@ static struct talitos_alg_template driver_algs[] = {
 			.cra_driver_name = "authenc-hmac-md5-cbc-3des-talitos",
 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
 			.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
-			.cra_type = &crypto_aead_type,
 			.cra_aead = {
-				.setkey = aead_setkey,
-				.setauthsize = aead_setauthsize,
-				.encrypt = aead_encrypt,
-				.decrypt = aead_decrypt,
-				.givencrypt = aead_givencrypt,
-				.geniv = "<built-in>",
 				.ivsize = DES3_EDE_BLOCK_SIZE,
 				.maxauthsize = MD5_DIGEST_SIZE,
 			}
@@ -2229,12 +2222,7 @@ static struct talitos_alg_template driver_algs[] = {
 			.cra_blocksize = AES_BLOCK_SIZE,
 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
                                      CRYPTO_ALG_ASYNC,
-			.cra_type = &crypto_ablkcipher_type,
 			.cra_ablkcipher = {
-				.setkey = ablkcipher_setkey,
-				.encrypt = ablkcipher_encrypt,
-				.decrypt = ablkcipher_decrypt,
-				.geniv = "eseqiv",
 				.min_keysize = AES_MIN_KEY_SIZE,
 				.max_keysize = AES_MAX_KEY_SIZE,
 				.ivsize = AES_BLOCK_SIZE,
@@ -2251,12 +2239,7 @@ static struct talitos_alg_template driver_algs[] = {
 			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
 			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
                                      CRYPTO_ALG_ASYNC,
-			.cra_type = &crypto_ablkcipher_type,
 			.cra_ablkcipher = {
-				.setkey = ablkcipher_setkey,
-				.encrypt = ablkcipher_encrypt,
-				.decrypt = ablkcipher_decrypt,
-				.geniv = "eseqiv",
 				.min_keysize = DES3_EDE_KEY_SIZE,
 				.max_keysize = DES3_EDE_KEY_SIZE,
 				.ivsize = DES3_EDE_BLOCK_SIZE,
@@ -2270,11 +2253,6 @@ static struct talitos_alg_template driver_algs[] = {
 	/* AHASH algorithms. */
 	{	.type = CRYPTO_ALG_TYPE_AHASH,
 		.alg.hash = {
-			.init = ahash_init,
-			.update = ahash_update,
-			.final = ahash_final,
-			.finup = ahash_finup,
-			.digest = ahash_digest,
 			.halg.digestsize = MD5_DIGEST_SIZE,
 			.halg.base = {
 				.cra_name = "md5",
@@ -2282,7 +2260,6 @@ static struct talitos_alg_template driver_algs[] = {
 				.cra_blocksize = MD5_BLOCK_SIZE,
 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
 					     CRYPTO_ALG_ASYNC,
-				.cra_type = &crypto_ahash_type
 			}
 		},
 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
@@ -2291,11 +2268,6 @@ static struct talitos_alg_template driver_algs[] = {
 	},
 	{	.type = CRYPTO_ALG_TYPE_AHASH,
 		.alg.hash = {
-			.init = ahash_init,
-			.update = ahash_update,
-			.final = ahash_final,
-			.finup = ahash_finup,
-			.digest = ahash_digest,
 			.halg.digestsize = SHA1_DIGEST_SIZE,
 			.halg.base = {
 				.cra_name = "sha1",
@@ -2303,7 +2275,6 @@ static struct talitos_alg_template driver_algs[] = {
 				.cra_blocksize = SHA1_BLOCK_SIZE,
 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
 					     CRYPTO_ALG_ASYNC,
-				.cra_type = &crypto_ahash_type
 			}
 		},
 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
@@ -2312,11 +2283,6 @@ static struct talitos_alg_template driver_algs[] = {
 	},
 	{	.type = CRYPTO_ALG_TYPE_AHASH,
 		.alg.hash = {
-			.init = ahash_init,
-			.update = ahash_update,
-			.final = ahash_final,
-			.finup = ahash_finup,
-			.digest = ahash_digest,
 			.halg.digestsize = SHA224_DIGEST_SIZE,
 			.halg.base = {
 				.cra_name = "sha224",
@@ -2324,7 +2290,6 @@ static struct talitos_alg_template driver_algs[] = {
 				.cra_blocksize = SHA224_BLOCK_SIZE,
 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
 					     CRYPTO_ALG_ASYNC,
-				.cra_type = &crypto_ahash_type
 			}
 		},
 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
@@ -2333,11 +2298,6 @@ static struct talitos_alg_template driver_algs[] = {
 	},
 	{	.type = CRYPTO_ALG_TYPE_AHASH,
 		.alg.hash = {
-			.init = ahash_init,
-			.update = ahash_update,
-			.final = ahash_final,
-			.finup = ahash_finup,
-			.digest = ahash_digest,
 			.halg.digestsize = SHA256_DIGEST_SIZE,
 			.halg.base = {
 				.cra_name = "sha256",
@@ -2345,7 +2305,6 @@ static struct talitos_alg_template driver_algs[] = {
 				.cra_blocksize = SHA256_BLOCK_SIZE,
 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
 					     CRYPTO_ALG_ASYNC,
-				.cra_type = &crypto_ahash_type
 			}
 		},
 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
@@ -2354,11 +2313,6 @@ static struct talitos_alg_template driver_algs[] = {
 	},
 	{	.type = CRYPTO_ALG_TYPE_AHASH,
 		.alg.hash = {
-			.init = ahash_init,
-			.update = ahash_update,
-			.final = ahash_final,
-			.finup = ahash_finup,
-			.digest = ahash_digest,
 			.halg.digestsize = SHA384_DIGEST_SIZE,
 			.halg.base = {
 				.cra_name = "sha384",
@@ -2366,7 +2320,6 @@ static struct talitos_alg_template driver_algs[] = {
 				.cra_blocksize = SHA384_BLOCK_SIZE,
 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
 					     CRYPTO_ALG_ASYNC,
-				.cra_type = &crypto_ahash_type
 			}
 		},
 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
@@ -2375,11 +2328,6 @@ static struct talitos_alg_template driver_algs[] = {
 	},
 	{	.type = CRYPTO_ALG_TYPE_AHASH,
 		.alg.hash = {
-			.init = ahash_init,
-			.update = ahash_update,
-			.final = ahash_final,
-			.finup = ahash_finup,
-			.digest = ahash_digest,
 			.halg.digestsize = SHA512_DIGEST_SIZE,
 			.halg.base = {
 				.cra_name = "sha512",
@@ -2387,7 +2335,6 @@ static struct talitos_alg_template driver_algs[] = {
 				.cra_blocksize = SHA512_BLOCK_SIZE,
 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
 					     CRYPTO_ALG_ASYNC,
-				.cra_type = &crypto_ahash_type
 			}
 		},
 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
@@ -2396,12 +2343,6 @@ static struct talitos_alg_template driver_algs[] = {
 	},
 	{	.type = CRYPTO_ALG_TYPE_AHASH,
 		.alg.hash = {
-			.init = ahash_init,
-			.update = ahash_update,
-			.final = ahash_final,
-			.finup = ahash_finup,
-			.digest = ahash_digest,
-			.setkey = ahash_setkey,
 			.halg.digestsize = MD5_DIGEST_SIZE,
 			.halg.base = {
 				.cra_name = "hmac(md5)",
@@ -2409,7 +2350,6 @@ static struct talitos_alg_template driver_algs[] = {
 				.cra_blocksize = MD5_BLOCK_SIZE,
 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
 					     CRYPTO_ALG_ASYNC,
-				.cra_type = &crypto_ahash_type
 			}
 		},
 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
@@ -2418,12 +2358,6 @@ static struct talitos_alg_template driver_algs[] = {
 	},
 	{	.type = CRYPTO_ALG_TYPE_AHASH,
 		.alg.hash = {
-			.init = ahash_init,
-			.update = ahash_update,
-			.final = ahash_final,
-			.finup = ahash_finup,
-			.digest = ahash_digest,
-			.setkey = ahash_setkey,
 			.halg.digestsize = SHA1_DIGEST_SIZE,
 			.halg.base = {
 				.cra_name = "hmac(sha1)",
@@ -2431,7 +2365,6 @@ static struct talitos_alg_template driver_algs[] = {
 				.cra_blocksize = SHA1_BLOCK_SIZE,
 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
 					     CRYPTO_ALG_ASYNC,
-				.cra_type = &crypto_ahash_type
 			}
 		},
 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
@@ -2440,12 +2373,6 @@ static struct talitos_alg_template driver_algs[] = {
 	},
 	{	.type = CRYPTO_ALG_TYPE_AHASH,
 		.alg.hash = {
-			.init = ahash_init,
-			.update = ahash_update,
-			.final = ahash_final,
-			.finup = ahash_finup,
-			.digest = ahash_digest,
-			.setkey = ahash_setkey,
 			.halg.digestsize = SHA224_DIGEST_SIZE,
 			.halg.base = {
 				.cra_name = "hmac(sha224)",
@@ -2453,7 +2380,6 @@ static struct talitos_alg_template driver_algs[] = {
 				.cra_blocksize = SHA224_BLOCK_SIZE,
 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
 					     CRYPTO_ALG_ASYNC,
-				.cra_type = &crypto_ahash_type
 			}
 		},
 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
@@ -2462,12 +2388,6 @@ static struct talitos_alg_template driver_algs[] = {
 	},
 	{	.type = CRYPTO_ALG_TYPE_AHASH,
 		.alg.hash = {
-			.init = ahash_init,
-			.update = ahash_update,
-			.final = ahash_final,
-			.finup = ahash_finup,
-			.digest = ahash_digest,
-			.setkey = ahash_setkey,
 			.halg.digestsize = SHA256_DIGEST_SIZE,
 			.halg.base = {
 				.cra_name = "hmac(sha256)",
@@ -2475,7 +2395,6 @@ static struct talitos_alg_template driver_algs[] = {
 				.cra_blocksize = SHA256_BLOCK_SIZE,
 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
 					     CRYPTO_ALG_ASYNC,
-				.cra_type = &crypto_ahash_type
 			}
 		},
 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
@@ -2484,12 +2403,6 @@ static struct talitos_alg_template driver_algs[] = {
 	},
 	{	.type = CRYPTO_ALG_TYPE_AHASH,
 		.alg.hash = {
-			.init = ahash_init,
-			.update = ahash_update,
-			.final = ahash_final,
-			.finup = ahash_finup,
-			.digest = ahash_digest,
-			.setkey = ahash_setkey,
 			.halg.digestsize = SHA384_DIGEST_SIZE,
 			.halg.base = {
 				.cra_name = "hmac(sha384)",
@@ -2497,7 +2410,6 @@ static struct talitos_alg_template driver_algs[] = {
 				.cra_blocksize = SHA384_BLOCK_SIZE,
 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
 					     CRYPTO_ALG_ASYNC,
-				.cra_type = &crypto_ahash_type
 			}
 		},
 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
@@ -2506,12 +2418,6 @@ static struct talitos_alg_template driver_algs[] = {
 	},
 	{	.type = CRYPTO_ALG_TYPE_AHASH,
 		.alg.hash = {
-			.init = ahash_init,
-			.update = ahash_update,
-			.final = ahash_final,
-			.finup = ahash_finup,
-			.digest = ahash_digest,
-			.setkey = ahash_setkey,
 			.halg.digestsize = SHA512_DIGEST_SIZE,
 			.halg.base = {
 				.cra_name = "hmac(sha512)",
@@ -2519,7 +2425,6 @@ static struct talitos_alg_template driver_algs[] = {
 				.cra_blocksize = SHA512_BLOCK_SIZE,
 				.cra_flags = CRYPTO_ALG_TYPE_AHASH |
 					     CRYPTO_ALG_ASYNC,
-				.cra_type = &crypto_ahash_type
 			}
 		},
 		.desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
@@ -2677,14 +2582,34 @@ static struct talitos_crypto_alg *talitos_alg_alloc(struct device *dev,
 	case CRYPTO_ALG_TYPE_ABLKCIPHER:
 		alg = &t_alg->algt.alg.crypto;
 		alg->cra_init = talitos_cra_init;
+		alg->cra_type = &crypto_ablkcipher_type;
+		alg->cra_ablkcipher.setkey = ablkcipher_setkey;
+		alg->cra_ablkcipher.encrypt = ablkcipher_encrypt;
+		alg->cra_ablkcipher.decrypt = ablkcipher_decrypt;
+		alg->cra_ablkcipher.geniv = "eseqiv";
 		break;
 	case CRYPTO_ALG_TYPE_AEAD:
 		alg = &t_alg->algt.alg.crypto;
 		alg->cra_init = talitos_cra_init_aead;
+		alg->cra_type = &crypto_aead_type;
+		alg->cra_aead.setkey = aead_setkey;
+		alg->cra_aead.setauthsize = aead_setauthsize;
+		alg->cra_aead.encrypt = aead_encrypt;
+		alg->cra_aead.decrypt = aead_decrypt;
+		alg->cra_aead.givencrypt = aead_givencrypt;
+		alg->cra_aead.geniv = "<built-in>";
 		break;
 	case CRYPTO_ALG_TYPE_AHASH:
 		alg = &t_alg->algt.alg.hash.halg.base;
 		alg->cra_init = talitos_cra_init_ahash;
+		alg->cra_type = &crypto_ahash_type;
+		t_alg->algt.alg.hash.init = ahash_init;
+		t_alg->algt.alg.hash.update = ahash_update;
+		t_alg->algt.alg.hash.final = ahash_final;
+		t_alg->algt.alg.hash.finup = ahash_finup;
+		t_alg->algt.alg.hash.digest = ahash_digest;
+		t_alg->algt.alg.hash.setkey = ahash_setkey;
+
 		if (!(priv->features & TALITOS_FTR_HMAC_OK) &&
 		    !strncmp(alg->cra_name, "hmac", 4)) {
 			kfree(t_alg);
@@ -2896,7 +2821,9 @@ static int talitos_probe(struct platform_device *ofdev)
 		if (hw_supports(dev, driver_algs[i].desc_hdr_template)) {
 			struct talitos_crypto_alg *t_alg;
 			char *name = NULL;
+			bool authenc = false;
 
+authencesn:
 			t_alg = talitos_alg_alloc(dev, &driver_algs[i]);
 			if (IS_ERR(t_alg)) {
 				err = PTR_ERR(t_alg);
@@ -2911,6 +2838,8 @@ static int talitos_probe(struct platform_device *ofdev)
 				err = crypto_register_alg(
 						&t_alg->algt.alg.crypto);
 				name = t_alg->algt.alg.crypto.cra_driver_name;
+				authenc = authenc ? !authenc :
+					  !(bool)memcmp(name, "authenc", 7);
 				break;
 			case CRYPTO_ALG_TYPE_AHASH:
 				err = crypto_register_ahash(
@@ -2923,8 +2852,25 @@ static int talitos_probe(struct platform_device *ofdev)
 				dev_err(dev, "%s alg registration failed\n",
 					name);
 				kfree(t_alg);
-			} else
+			} else {
 				list_add_tail(&t_alg->entry, &priv->alg_list);
+				if (authenc) {
+					struct crypto_alg *alg =
+						&driver_algs[i].alg.crypto;
+
+					name = alg->cra_name;
+					memmove(name + 10, name + 7,
+						strlen(name) - 7);
+					memcpy(name + 7, "esn", 3);
+
+					name = alg->cra_driver_name;
+					memmove(name + 10, name + 7,
+						strlen(name) - 7);
+					memcpy(name + 7, "esn", 3);
+
+					goto authencesn;
+				}
+			}
 		}
 	}
 	if (!list_empty(&priv->alg_list))
diff --git a/drivers/crypto/tegra-aes.c b/drivers/crypto/tegra-aes.c
index ac236f6..631149e5 100644
--- a/drivers/crypto/tegra-aes.c
+++ b/drivers/crypto/tegra-aes.c
@@ -1004,8 +1004,6 @@ static int tegra_aes_probe(struct platform_device *pdev)
 
 	aes_dev = dd;
 	for (i = 0; i < ARRAY_SIZE(algs); i++) {
-		INIT_LIST_HEAD(&algs[i].cra_list);
-
 		algs[i].cra_priority = 300;
 		algs[i].cra_ctxsize = sizeof(struct tegra_aes_ctx);
 		algs[i].cra_module = THIS_MODULE;
diff --git a/drivers/crypto/ux500/cryp/cryp_core.c b/drivers/crypto/ux500/cryp/cryp_core.c
index 1c307e1..ef17e38 100644
--- a/drivers/crypto/ux500/cryp/cryp_core.c
+++ b/drivers/crypto/ux500/cryp/cryp_core.c
@@ -32,7 +32,7 @@
 
 #include <plat/ste_dma40.h>
 
-#include <mach/crypto-ux500.h>
+#include <linux/platform_data/crypto-ux500.h>
 #include <mach/hardware.h>
 
 #include "cryp_p.h"
diff --git a/drivers/crypto/ux500/hash/hash_core.c b/drivers/crypto/ux500/hash/hash_core.c
index 08d5032..632c333 100644
--- a/drivers/crypto/ux500/hash/hash_core.c
+++ b/drivers/crypto/ux500/hash/hash_core.c
@@ -31,7 +31,7 @@
 #include <crypto/scatterwalk.h>
 #include <crypto/algapi.h>
 
-#include <mach/crypto-ux500.h>
+#include <linux/platform_data/crypto-ux500.h>
 #include <mach/hardware.h>
 
 #include "hash_alg.h"
@@ -1991,7 +1991,6 @@ static int __init ux500_hash_mod_init(void)
 static void __exit ux500_hash_mod_fini(void)
 {
 	platform_driver_unregister(&hash_driver);
-	return;
 }
 
 module_init(ux500_hash_mod_init);
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index 70c31d4..b146d76 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -607,7 +607,7 @@ static int __init devfreq_start_polling(void)
 	mutex_lock(&devfreq_list_lock);
 	polling = false;
 	devfreq_wq = create_freezable_workqueue("devfreq_wq");
-	INIT_DELAYED_WORK_DEFERRABLE(&devfreq_work, devfreq_monitor);
+	INIT_DEFERRABLE_WORK(&devfreq_work, devfreq_monitor);
 	mutex_unlock(&devfreq_list_lock);
 
 	devfreq_monitor(&devfreq_work.work);
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index d06ea29..677cd6e 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -208,6 +208,16 @@ config SIRF_DMA
 	help
 	  Enable support for the CSR SiRFprimaII DMA engine.
 
+config TI_EDMA
+	tristate "TI EDMA support"
+	depends on ARCH_DAVINCI
+	select DMA_ENGINE
+	select DMA_VIRTUAL_CHANNELS
+	default n
+	help
+	  Enable support for the TI EDMA controller. This DMA
+	  engine is found on TI DaVinci and AM33xx parts.
+
 config ARCH_HAS_ASYNC_TX_FIND_CHANNEL
 	bool
 
@@ -292,6 +302,13 @@ config DMA_OMAP
 	select DMA_ENGINE
 	select DMA_VIRTUAL_CHANNELS
 
+config MMP_PDMA
+	bool "MMP PDMA support"
+	depends on (ARCH_MMP || ARCH_PXA)
+	select DMA_ENGINE
+	help
+	  Support the MMP PDMA engine for PXA and MMP platfrom.
+
 config DMA_ENGINE
 	bool
 
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index 4cf6b12..7428fea 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -23,6 +23,7 @@ obj-$(CONFIG_IMX_DMA) += imx-dma.o
 obj-$(CONFIG_MXS_DMA) += mxs-dma.o
 obj-$(CONFIG_TIMB_DMA) += timb_dma.o
 obj-$(CONFIG_SIRF_DMA) += sirf-dma.o
+obj-$(CONFIG_TI_EDMA) += edma.o
 obj-$(CONFIG_STE_DMA40) += ste_dma40.o ste_dma40_ll.o
 obj-$(CONFIG_TEGRA20_APB_DMA) += tegra20-apb-dma.o
 obj-$(CONFIG_PL330_DMA) += pl330.o
@@ -32,3 +33,4 @@ obj-$(CONFIG_EP93XX_DMA) += ep93xx_dma.o
 obj-$(CONFIG_DMA_SA11X0) += sa11x0-dma.o
 obj-$(CONFIG_MMP_TDMA) += mmp_tdma.o
 obj-$(CONFIG_DMA_OMAP) += omap-dma.o
+obj-$(CONFIG_MMP_PDMA) += mmp_pdma.o
diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c
index 6fbeebb..d1cc579 100644
--- a/drivers/dma/amba-pl08x.c
+++ b/drivers/dma/amba-pl08x.c
@@ -1892,6 +1892,7 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id)
 	pl08x->pd = dev_get_platdata(&adev->dev);
 	if (!pl08x->pd) {
 		dev_err(&adev->dev, "no platform data supplied\n");
+		ret = -EINVAL;
 		goto out_no_platdata;
 	}
 
@@ -1943,6 +1944,7 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id)
 		dev_err(&adev->dev, "%s failed to allocate "
 			"physical channel holders\n",
 			__func__);
+		ret = -ENOMEM;
 		goto out_no_phychans;
 	}
 
diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c
index 7ab6e26..13a02f4 100644
--- a/drivers/dma/at_hdmac.c
+++ b/drivers/dma/at_hdmac.c
@@ -168,9 +168,9 @@ static void atc_desc_put(struct at_dma_chan *atchan, struct at_desc *desc)
 }
 
 /**
- * atc_desc_chain - build chain adding a descripor
- * @first: address of first descripor of the chain
- * @prev: address of previous descripor of the chain
+ * atc_desc_chain - build chain adding a descriptor
+ * @first: address of first descriptor of the chain
+ * @prev: address of previous descriptor of the chain
  * @desc: descriptor to queue
  *
  * Called from prep_* functions
@@ -796,7 +796,7 @@ err_out:
 }
 
 /**
- * atc_dma_cyclic_fill_desc - Fill one period decriptor
+ * atc_dma_cyclic_fill_desc - Fill one period descriptor
  */
 static int
 atc_dma_cyclic_fill_desc(struct dma_chan *chan, struct at_desc *desc,
@@ -852,12 +852,13 @@ atc_dma_cyclic_fill_desc(struct dma_chan *chan, struct at_desc *desc,
  * @buf_len: total number of bytes for the entire buffer
  * @period_len: number of bytes for each period
  * @direction: transfer direction, to or from device
+ * @flags: tx descriptor status flags
  * @context: transfer context (ignored)
  */
 static struct dma_async_tx_descriptor *
 atc_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,
 		size_t period_len, enum dma_transfer_direction direction,
-		void *context)
+		unsigned long flags, void *context)
 {
 	struct at_dma_chan	*atchan = to_at_dma_chan(chan);
 	struct at_dma_slave	*atslave = chan->private;
diff --git a/drivers/dma/at_hdmac_regs.h b/drivers/dma/at_hdmac_regs.h
index 8a6c8e8..116e4ad 100644
--- a/drivers/dma/at_hdmac_regs.h
+++ b/drivers/dma/at_hdmac_regs.h
@@ -11,7 +11,7 @@
 #ifndef AT_HDMAC_REGS_H
 #define	AT_HDMAC_REGS_H
 
-#include <mach/at_hdmac.h>
+#include <linux/platform_data/dma-atmel.h>
 
 #define	AT_DMA_MAX_NR_CHANNELS	8
 
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
index 3491654..a815d44 100644
--- a/drivers/dma/dmaengine.c
+++ b/drivers/dma/dmaengine.c
@@ -582,7 +582,7 @@ void dmaengine_get(void)
 				list_del_rcu(&device->global_node);
 				break;
 			} else if (err)
-				pr_err("%s: failed to get %s: (%d)\n",
+				pr_debug("%s: failed to get %s: (%d)\n",
 				       __func__, dma_chan_name(chan), err);
 		}
 	}
diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c
index d3c5a5a..efbd16a 100644
--- a/drivers/dma/dw_dmac.c
+++ b/drivers/dma/dw_dmac.c
@@ -177,6 +177,11 @@ static void dwc_initialize(struct dw_dma_chan *dwc)
 
 		cfghi = dws->cfg_hi;
 		cfglo |= dws->cfg_lo & ~DWC_CFGL_CH_PRIOR_MASK;
+	} else {
+		if (dwc->dma_sconfig.direction == DMA_MEM_TO_DEV)
+			cfghi = DWC_CFGH_DST_PER(dwc->dma_sconfig.slave_id);
+		else if (dwc->dma_sconfig.direction == DMA_DEV_TO_MEM)
+			cfghi = DWC_CFGH_SRC_PER(dwc->dma_sconfig.slave_id);
 	}
 
 	channel_writel(dwc, CFG_LO, cfglo);
@@ -1392,26 +1397,17 @@ static int __devinit dw_probe(struct platform_device *pdev)
 
 	size = sizeof(struct dw_dma);
 	size += pdata->nr_channels * sizeof(struct dw_dma_chan);
-	dw = kzalloc(size, GFP_KERNEL);
+	dw = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
 	if (!dw)
 		return -ENOMEM;
 
-	if (!request_mem_region(io->start, DW_REGLEN, pdev->dev.driver->name)) {
-		err = -EBUSY;
-		goto err_kfree;
-	}
-
-	dw->regs = ioremap(io->start, DW_REGLEN);
-	if (!dw->regs) {
-		err = -ENOMEM;
-		goto err_release_r;
-	}
+	dw->regs = devm_request_and_ioremap(&pdev->dev, io);
+	if (!dw->regs)
+		return -EBUSY;
 
-	dw->clk = clk_get(&pdev->dev, "hclk");
-	if (IS_ERR(dw->clk)) {
-		err = PTR_ERR(dw->clk);
-		goto err_clk;
-	}
+	dw->clk = devm_clk_get(&pdev->dev, "hclk");
+	if (IS_ERR(dw->clk))
+		return PTR_ERR(dw->clk);
 	clk_prepare_enable(dw->clk);
 
 	/* Calculate all channel mask before DMA setup */
@@ -1423,9 +1419,10 @@ static int __devinit dw_probe(struct platform_device *pdev)
 	/* disable BLOCK interrupts as well */
 	channel_clear_bit(dw, MASK.BLOCK, dw->all_chan_mask);
 
-	err = request_irq(irq, dw_dma_interrupt, 0, "dw_dmac", dw);
+	err = devm_request_irq(&pdev->dev, irq, dw_dma_interrupt, 0,
+			       "dw_dmac", dw);
 	if (err)
-		goto err_irq;
+		return err;
 
 	platform_set_drvdata(pdev, dw);
 
@@ -1491,30 +1488,16 @@ static int __devinit dw_probe(struct platform_device *pdev)
 	dma_async_device_register(&dw->dma);
 
 	return 0;
-
-err_irq:
-	clk_disable_unprepare(dw->clk);
-	clk_put(dw->clk);
-err_clk:
-	iounmap(dw->regs);
-	dw->regs = NULL;
-err_release_r:
-	release_resource(io);
-err_kfree:
-	kfree(dw);
-	return err;
 }
 
 static int __devexit dw_remove(struct platform_device *pdev)
 {
 	struct dw_dma		*dw = platform_get_drvdata(pdev);
 	struct dw_dma_chan	*dwc, *_dwc;
-	struct resource		*io;
 
 	dw_dma_off(dw);
 	dma_async_device_unregister(&dw->dma);
 
-	free_irq(platform_get_irq(pdev, 0), dw);
 	tasklet_kill(&dw->tasklet);
 
 	list_for_each_entry_safe(dwc, _dwc, &dw->dma.channels,
@@ -1523,17 +1506,6 @@ static int __devexit dw_remove(struct platform_device *pdev)
 		channel_clear_bit(dw, CH_EN, dwc->mask);
 	}
 
-	clk_disable_unprepare(dw->clk);
-	clk_put(dw->clk);
-
-	iounmap(dw->regs);
-	dw->regs = NULL;
-
-	io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	release_mem_region(io->start, DW_REGLEN);
-
-	kfree(dw);
-
 	return 0;
 }
 
diff --git a/drivers/dma/dw_dmac_regs.h b/drivers/dma/dw_dmac_regs.h
index 50830be..f6d92d7 100644
--- a/drivers/dma/dw_dmac_regs.h
+++ b/drivers/dma/dw_dmac_regs.h
@@ -140,8 +140,6 @@ struct dw_dma_regs {
 /* Bitfields in CFG */
 #define DW_CFG_DMA_EN		(1 << 0)
 
-#define DW_REGLEN		0x400
-
 enum dw_dmac_flags {
 	DW_DMA_IS_CYCLIC = 0,
 };
diff --git a/drivers/dma/edma.c b/drivers/dma/edma.c
new file mode 100644
index 0000000..05aea3c
--- /dev/null
+++ b/drivers/dma/edma.c
@@ -0,0 +1,671 @@
+/*
+ * TI EDMA DMA engine driver
+ *
+ * Copyright 2012 Texas Instruments
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#include <mach/edma.h>
+
+#include "dmaengine.h"
+#include "virt-dma.h"
+
+/*
+ * This will go away when the private EDMA API is folded
+ * into this driver and the platform device(s) are
+ * instantiated in the arch code. We can only get away
+ * with this simplification because DA8XX may not be built
+ * in the same kernel image with other DaVinci parts. This
+ * avoids having to sprinkle dmaengine driver platform devices
+ * and data throughout all the existing board files.
+ */
+#ifdef CONFIG_ARCH_DAVINCI_DA8XX
+#define EDMA_CTLRS	2
+#define EDMA_CHANS	32
+#else
+#define EDMA_CTLRS	1
+#define EDMA_CHANS	64
+#endif /* CONFIG_ARCH_DAVINCI_DA8XX */
+
+/* Max of 16 segments per channel to conserve PaRAM slots */
+#define MAX_NR_SG		16
+#define EDMA_MAX_SLOTS		MAX_NR_SG
+#define EDMA_DESCRIPTORS	16
+
+struct edma_desc {
+	struct virt_dma_desc		vdesc;
+	struct list_head		node;
+	int				absync;
+	int				pset_nr;
+	struct edmacc_param		pset[0];
+};
+
+struct edma_cc;
+
+struct edma_chan {
+	struct virt_dma_chan		vchan;
+	struct list_head		node;
+	struct edma_desc		*edesc;
+	struct edma_cc			*ecc;
+	int				ch_num;
+	bool				alloced;
+	int				slot[EDMA_MAX_SLOTS];
+	dma_addr_t			addr;
+	int				addr_width;
+	int				maxburst;
+};
+
+struct edma_cc {
+	int				ctlr;
+	struct dma_device		dma_slave;
+	struct edma_chan		slave_chans[EDMA_CHANS];
+	int				num_slave_chans;
+	int				dummy_slot;
+};
+
+static inline struct edma_cc *to_edma_cc(struct dma_device *d)
+{
+	return container_of(d, struct edma_cc, dma_slave);
+}
+
+static inline struct edma_chan *to_edma_chan(struct dma_chan *c)
+{
+	return container_of(c, struct edma_chan, vchan.chan);
+}
+
+static inline struct edma_desc
+*to_edma_desc(struct dma_async_tx_descriptor *tx)
+{
+	return container_of(tx, struct edma_desc, vdesc.tx);
+}
+
+static void edma_desc_free(struct virt_dma_desc *vdesc)
+{
+	kfree(container_of(vdesc, struct edma_desc, vdesc));
+}
+
+/* Dispatch a queued descriptor to the controller (caller holds lock) */
+static void edma_execute(struct edma_chan *echan)
+{
+	struct virt_dma_desc *vdesc = vchan_next_desc(&echan->vchan);
+	struct edma_desc *edesc;
+	int i;
+
+	if (!vdesc) {
+		echan->edesc = NULL;
+		return;
+	}
+
+	list_del(&vdesc->node);
+
+	echan->edesc = edesc = to_edma_desc(&vdesc->tx);
+
+	/* Write descriptor PaRAM set(s) */
+	for (i = 0; i < edesc->pset_nr; i++) {
+		edma_write_slot(echan->slot[i], &edesc->pset[i]);
+		dev_dbg(echan->vchan.chan.device->dev,
+			"\n pset[%d]:\n"
+			"  chnum\t%d\n"
+			"  slot\t%d\n"
+			"  opt\t%08x\n"
+			"  src\t%08x\n"
+			"  dst\t%08x\n"
+			"  abcnt\t%08x\n"
+			"  ccnt\t%08x\n"
+			"  bidx\t%08x\n"
+			"  cidx\t%08x\n"
+			"  lkrld\t%08x\n",
+			i, echan->ch_num, echan->slot[i],
+			edesc->pset[i].opt,
+			edesc->pset[i].src,
+			edesc->pset[i].dst,
+			edesc->pset[i].a_b_cnt,
+			edesc->pset[i].ccnt,
+			edesc->pset[i].src_dst_bidx,
+			edesc->pset[i].src_dst_cidx,
+			edesc->pset[i].link_bcntrld);
+		/* Link to the previous slot if not the last set */
+		if (i != (edesc->pset_nr - 1))
+			edma_link(echan->slot[i], echan->slot[i+1]);
+		/* Final pset links to the dummy pset */
+		else
+			edma_link(echan->slot[i], echan->ecc->dummy_slot);
+	}
+
+	edma_start(echan->ch_num);
+}
+
+static int edma_terminate_all(struct edma_chan *echan)
+{
+	unsigned long flags;
+	LIST_HEAD(head);
+
+	spin_lock_irqsave(&echan->vchan.lock, flags);
+
+	/*
+	 * Stop DMA activity: we assume the callback will not be called
+	 * after edma_dma() returns (even if it does, it will see
+	 * echan->edesc is NULL and exit.)
+	 */
+	if (echan->edesc) {
+		echan->edesc = NULL;
+		edma_stop(echan->ch_num);
+	}
+
+	vchan_get_all_descriptors(&echan->vchan, &head);
+	spin_unlock_irqrestore(&echan->vchan.lock, flags);
+	vchan_dma_desc_free_list(&echan->vchan, &head);
+
+	return 0;
+}
+
+
+static int edma_slave_config(struct edma_chan *echan,
+	struct dma_slave_config *config)
+{
+	if ((config->src_addr_width > DMA_SLAVE_BUSWIDTH_4_BYTES) ||
+	    (config->dst_addr_width > DMA_SLAVE_BUSWIDTH_4_BYTES))
+		return -EINVAL;
+
+	if (config->direction == DMA_MEM_TO_DEV) {
+		if (config->dst_addr)
+			echan->addr = config->dst_addr;
+		if (config->dst_addr_width)
+			echan->addr_width = config->dst_addr_width;
+		if (config->dst_maxburst)
+			echan->maxburst = config->dst_maxburst;
+	} else if (config->direction == DMA_DEV_TO_MEM) {
+		if (config->src_addr)
+			echan->addr = config->src_addr;
+		if (config->src_addr_width)
+			echan->addr_width = config->src_addr_width;
+		if (config->src_maxburst)
+			echan->maxburst = config->src_maxburst;
+	}
+
+	return 0;
+}
+
+static int edma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
+			unsigned long arg)
+{
+	int ret = 0;
+	struct dma_slave_config *config;
+	struct edma_chan *echan = to_edma_chan(chan);
+
+	switch (cmd) {
+	case DMA_TERMINATE_ALL:
+		edma_terminate_all(echan);
+		break;
+	case DMA_SLAVE_CONFIG:
+		config = (struct dma_slave_config *)arg;
+		ret = edma_slave_config(echan, config);
+		break;
+	default:
+		ret = -ENOSYS;
+	}
+
+	return ret;
+}
+
+static struct dma_async_tx_descriptor *edma_prep_slave_sg(
+	struct dma_chan *chan, struct scatterlist *sgl,
+	unsigned int sg_len, enum dma_transfer_direction direction,
+	unsigned long tx_flags, void *context)
+{
+	struct edma_chan *echan = to_edma_chan(chan);
+	struct device *dev = chan->device->dev;
+	struct edma_desc *edesc;
+	struct scatterlist *sg;
+	int i;
+	int acnt, bcnt, ccnt, src, dst, cidx;
+	int src_bidx, dst_bidx, src_cidx, dst_cidx;
+
+	if (unlikely(!echan || !sgl || !sg_len))
+		return NULL;
+
+	if (echan->addr_width == DMA_SLAVE_BUSWIDTH_UNDEFINED) {
+		dev_err(dev, "Undefined slave buswidth\n");
+		return NULL;
+	}
+
+	if (sg_len > MAX_NR_SG) {
+		dev_err(dev, "Exceeded max SG segments %d > %d\n",
+			sg_len, MAX_NR_SG);
+		return NULL;
+	}
+
+	edesc = kzalloc(sizeof(*edesc) + sg_len *
+		sizeof(edesc->pset[0]), GFP_ATOMIC);
+	if (!edesc) {
+		dev_dbg(dev, "Failed to allocate a descriptor\n");
+		return NULL;
+	}
+
+	edesc->pset_nr = sg_len;
+
+	for_each_sg(sgl, sg, sg_len, i) {
+		/* Allocate a PaRAM slot, if needed */
+		if (echan->slot[i] < 0) {
+			echan->slot[i] =
+				edma_alloc_slot(EDMA_CTLR(echan->ch_num),
+						EDMA_SLOT_ANY);
+			if (echan->slot[i] < 0) {
+				dev_err(dev, "Failed to allocate slot\n");
+				return NULL;
+			}
+		}
+
+		acnt = echan->addr_width;
+
+		/*
+		 * If the maxburst is equal to the fifo width, use
+		 * A-synced transfers. This allows for large contiguous
+		 * buffer transfers using only one PaRAM set.
+		 */
+		if (echan->maxburst == 1) {
+			edesc->absync = false;
+			ccnt = sg_dma_len(sg) / acnt / (SZ_64K - 1);
+			bcnt = sg_dma_len(sg) / acnt - ccnt * (SZ_64K - 1);
+			if (bcnt)
+				ccnt++;
+			else
+				bcnt = SZ_64K - 1;
+			cidx = acnt;
+		/*
+		 * If maxburst is greater than the fifo address_width,
+		 * use AB-synced transfers where A count is the fifo
+		 * address_width and B count is the maxburst. In this
+		 * case, we are limited to transfers of C count frames
+		 * of (address_width * maxburst) where C count is limited
+		 * to SZ_64K-1. This places an upper bound on the length
+		 * of an SG segment that can be handled.
+		 */
+		} else {
+			edesc->absync = true;
+			bcnt = echan->maxburst;
+			ccnt = sg_dma_len(sg) / (acnt * bcnt);
+			if (ccnt > (SZ_64K - 1)) {
+				dev_err(dev, "Exceeded max SG segment size\n");
+				return NULL;
+			}
+			cidx = acnt * bcnt;
+		}
+
+		if (direction == DMA_MEM_TO_DEV) {
+			src = sg_dma_address(sg);
+			dst = echan->addr;
+			src_bidx = acnt;
+			src_cidx = cidx;
+			dst_bidx = 0;
+			dst_cidx = 0;
+		} else {
+			src = echan->addr;
+			dst = sg_dma_address(sg);
+			src_bidx = 0;
+			src_cidx = 0;
+			dst_bidx = acnt;
+			dst_cidx = cidx;
+		}
+
+		edesc->pset[i].opt = EDMA_TCC(EDMA_CHAN_SLOT(echan->ch_num));
+		/* Configure A or AB synchronized transfers */
+		if (edesc->absync)
+			edesc->pset[i].opt |= SYNCDIM;
+		/* If this is the last set, enable completion interrupt flag */
+		if (i == sg_len - 1)
+			edesc->pset[i].opt |= TCINTEN;
+
+		edesc->pset[i].src = src;
+		edesc->pset[i].dst = dst;
+
+		edesc->pset[i].src_dst_bidx = (dst_bidx << 16) | src_bidx;
+		edesc->pset[i].src_dst_cidx = (dst_cidx << 16) | src_cidx;
+
+		edesc->pset[i].a_b_cnt = bcnt << 16 | acnt;
+		edesc->pset[i].ccnt = ccnt;
+		edesc->pset[i].link_bcntrld = 0xffffffff;
+
+	}
+
+	return vchan_tx_prep(&echan->vchan, &edesc->vdesc, tx_flags);
+}
+
+static void edma_callback(unsigned ch_num, u16 ch_status, void *data)
+{
+	struct edma_chan *echan = data;
+	struct device *dev = echan->vchan.chan.device->dev;
+	struct edma_desc *edesc;
+	unsigned long flags;
+
+	/* Stop the channel */
+	edma_stop(echan->ch_num);
+
+	switch (ch_status) {
+	case DMA_COMPLETE:
+		dev_dbg(dev, "transfer complete on channel %d\n", ch_num);
+
+		spin_lock_irqsave(&echan->vchan.lock, flags);
+
+		edesc = echan->edesc;
+		if (edesc) {
+			edma_execute(echan);
+			vchan_cookie_complete(&edesc->vdesc);
+		}
+
+		spin_unlock_irqrestore(&echan->vchan.lock, flags);
+
+		break;
+	case DMA_CC_ERROR:
+		dev_dbg(dev, "transfer error on channel %d\n", ch_num);
+		break;
+	default:
+		break;
+	}
+}
+
+/* Alloc channel resources */
+static int edma_alloc_chan_resources(struct dma_chan *chan)
+{
+	struct edma_chan *echan = to_edma_chan(chan);
+	struct device *dev = chan->device->dev;
+	int ret;
+	int a_ch_num;
+	LIST_HEAD(descs);
+
+	a_ch_num = edma_alloc_channel(echan->ch_num, edma_callback,
+					chan, EVENTQ_DEFAULT);
+
+	if (a_ch_num < 0) {
+		ret = -ENODEV;
+		goto err_no_chan;
+	}
+
+	if (a_ch_num != echan->ch_num) {
+		dev_err(dev, "failed to allocate requested channel %u:%u\n",
+			EDMA_CTLR(echan->ch_num),
+			EDMA_CHAN_SLOT(echan->ch_num));
+		ret = -ENODEV;
+		goto err_wrong_chan;
+	}
+
+	echan->alloced = true;
+	echan->slot[0] = echan->ch_num;
+
+	dev_info(dev, "allocated channel for %u:%u\n",
+		 EDMA_CTLR(echan->ch_num), EDMA_CHAN_SLOT(echan->ch_num));
+
+	return 0;
+
+err_wrong_chan:
+	edma_free_channel(a_ch_num);
+err_no_chan:
+	return ret;
+}
+
+/* Free channel resources */
+static void edma_free_chan_resources(struct dma_chan *chan)
+{
+	struct edma_chan *echan = to_edma_chan(chan);
+	struct device *dev = chan->device->dev;
+	int i;
+
+	/* Terminate transfers */
+	edma_stop(echan->ch_num);
+
+	vchan_free_chan_resources(&echan->vchan);
+
+	/* Free EDMA PaRAM slots */
+	for (i = 1; i < EDMA_MAX_SLOTS; i++) {
+		if (echan->slot[i] >= 0) {
+			edma_free_slot(echan->slot[i]);
+			echan->slot[i] = -1;
+		}
+	}
+
+	/* Free EDMA channel */
+	if (echan->alloced) {
+		edma_free_channel(echan->ch_num);
+		echan->alloced = false;
+	}
+
+	dev_info(dev, "freeing channel for %u\n", echan->ch_num);
+}
+
+/* Send pending descriptor to hardware */
+static void edma_issue_pending(struct dma_chan *chan)
+{
+	struct edma_chan *echan = to_edma_chan(chan);
+	unsigned long flags;
+
+	spin_lock_irqsave(&echan->vchan.lock, flags);
+	if (vchan_issue_pending(&echan->vchan) && !echan->edesc)
+		edma_execute(echan);
+	spin_unlock_irqrestore(&echan->vchan.lock, flags);
+}
+
+static size_t edma_desc_size(struct edma_desc *edesc)
+{
+	int i;
+	size_t size;
+
+	if (edesc->absync)
+		for (size = i = 0; i < edesc->pset_nr; i++)
+			size += (edesc->pset[i].a_b_cnt & 0xffff) *
+				(edesc->pset[i].a_b_cnt >> 16) *
+				 edesc->pset[i].ccnt;
+	else
+		size = (edesc->pset[0].a_b_cnt & 0xffff) *
+			(edesc->pset[0].a_b_cnt >> 16) +
+			(edesc->pset[0].a_b_cnt & 0xffff) *
+			(SZ_64K - 1) * edesc->pset[0].ccnt;
+
+	return size;
+}
+
+/* Check request completion status */
+static enum dma_status edma_tx_status(struct dma_chan *chan,
+				      dma_cookie_t cookie,
+				      struct dma_tx_state *txstate)
+{
+	struct edma_chan *echan = to_edma_chan(chan);
+	struct virt_dma_desc *vdesc;
+	enum dma_status ret;
+	unsigned long flags;
+
+	ret = dma_cookie_status(chan, cookie, txstate);
+	if (ret == DMA_SUCCESS || !txstate)
+		return ret;
+
+	spin_lock_irqsave(&echan->vchan.lock, flags);
+	vdesc = vchan_find_desc(&echan->vchan, cookie);
+	if (vdesc) {
+		txstate->residue = edma_desc_size(to_edma_desc(&vdesc->tx));
+	} else if (echan->edesc && echan->edesc->vdesc.tx.cookie == cookie) {
+		struct edma_desc *edesc = echan->edesc;
+		txstate->residue = edma_desc_size(edesc);
+	} else {
+		txstate->residue = 0;
+	}
+	spin_unlock_irqrestore(&echan->vchan.lock, flags);
+
+	return ret;
+}
+
+static void __init edma_chan_init(struct edma_cc *ecc,
+				  struct dma_device *dma,
+				  struct edma_chan *echans)
+{
+	int i, j;
+
+	for (i = 0; i < EDMA_CHANS; i++) {
+		struct edma_chan *echan = &echans[i];
+		echan->ch_num = EDMA_CTLR_CHAN(ecc->ctlr, i);
+		echan->ecc = ecc;
+		echan->vchan.desc_free = edma_desc_free;
+
+		vchan_init(&echan->vchan, dma);
+
+		INIT_LIST_HEAD(&echan->node);
+		for (j = 0; j < EDMA_MAX_SLOTS; j++)
+			echan->slot[j] = -1;
+	}
+}
+
+static void edma_dma_init(struct edma_cc *ecc, struct dma_device *dma,
+			  struct device *dev)
+{
+	dma->device_prep_slave_sg = edma_prep_slave_sg;
+	dma->device_alloc_chan_resources = edma_alloc_chan_resources;
+	dma->device_free_chan_resources = edma_free_chan_resources;
+	dma->device_issue_pending = edma_issue_pending;
+	dma->device_tx_status = edma_tx_status;
+	dma->device_control = edma_control;
+	dma->dev = dev;
+
+	INIT_LIST_HEAD(&dma->channels);
+}
+
+static int __devinit edma_probe(struct platform_device *pdev)
+{
+	struct edma_cc *ecc;
+	int ret;
+
+	ecc = devm_kzalloc(&pdev->dev, sizeof(*ecc), GFP_KERNEL);
+	if (!ecc) {
+		dev_err(&pdev->dev, "Can't allocate controller\n");
+		return -ENOMEM;
+	}
+
+	ecc->ctlr = pdev->id;
+	ecc->dummy_slot = edma_alloc_slot(ecc->ctlr, EDMA_SLOT_ANY);
+	if (ecc->dummy_slot < 0) {
+		dev_err(&pdev->dev, "Can't allocate PaRAM dummy slot\n");
+		return -EIO;
+	}
+
+	dma_cap_zero(ecc->dma_slave.cap_mask);
+	dma_cap_set(DMA_SLAVE, ecc->dma_slave.cap_mask);
+
+	edma_dma_init(ecc, &ecc->dma_slave, &pdev->dev);
+
+	edma_chan_init(ecc, &ecc->dma_slave, ecc->slave_chans);
+
+	ret = dma_async_device_register(&ecc->dma_slave);
+	if (ret)
+		goto err_reg1;
+
+	platform_set_drvdata(pdev, ecc);
+
+	dev_info(&pdev->dev, "TI EDMA DMA engine driver\n");
+
+	return 0;
+
+err_reg1:
+	edma_free_slot(ecc->dummy_slot);
+	return ret;
+}
+
+static int __devexit edma_remove(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct edma_cc *ecc = dev_get_drvdata(dev);
+
+	dma_async_device_unregister(&ecc->dma_slave);
+	edma_free_slot(ecc->dummy_slot);
+
+	return 0;
+}
+
+static struct platform_driver edma_driver = {
+	.probe		= edma_probe,
+	.remove		= __devexit_p(edma_remove),
+	.driver = {
+		.name = "edma-dma-engine",
+		.owner = THIS_MODULE,
+	},
+};
+
+bool edma_filter_fn(struct dma_chan *chan, void *param)
+{
+	if (chan->device->dev->driver == &edma_driver.driver) {
+		struct edma_chan *echan = to_edma_chan(chan);
+		unsigned ch_req = *(unsigned *)param;
+		return ch_req == echan->ch_num;
+	}
+	return false;
+}
+EXPORT_SYMBOL(edma_filter_fn);
+
+static struct platform_device *pdev0, *pdev1;
+
+static const struct platform_device_info edma_dev_info0 = {
+	.name = "edma-dma-engine",
+	.id = 0,
+	.dma_mask = DMA_BIT_MASK(32),
+};
+
+static const struct platform_device_info edma_dev_info1 = {
+	.name = "edma-dma-engine",
+	.id = 1,
+	.dma_mask = DMA_BIT_MASK(32),
+};
+
+static int edma_init(void)
+{
+	int ret = platform_driver_register(&edma_driver);
+
+	if (ret == 0) {
+		pdev0 = platform_device_register_full(&edma_dev_info0);
+		if (IS_ERR(pdev0)) {
+			platform_driver_unregister(&edma_driver);
+			ret = PTR_ERR(pdev0);
+			goto out;
+		}
+	}
+
+	if (EDMA_CTLRS == 2) {
+		pdev1 = platform_device_register_full(&edma_dev_info1);
+		if (IS_ERR(pdev1)) {
+			platform_driver_unregister(&edma_driver);
+			platform_device_unregister(pdev0);
+			ret = PTR_ERR(pdev1);
+		}
+	}
+
+out:
+	return ret;
+}
+subsys_initcall(edma_init);
+
+static void __exit edma_exit(void)
+{
+	platform_device_unregister(pdev0);
+	if (pdev1)
+		platform_device_unregister(pdev1);
+	platform_driver_unregister(&edma_driver);
+}
+module_exit(edma_exit);
+
+MODULE_AUTHOR("Matt Porter <mporter@ti.com>");
+MODULE_DESCRIPTION("TI EDMA DMA engine driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/dma/ep93xx_dma.c b/drivers/dma/ep93xx_dma.c
index c64917e..bcfde40 100644
--- a/drivers/dma/ep93xx_dma.c
+++ b/drivers/dma/ep93xx_dma.c
@@ -26,7 +26,7 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 
-#include <mach/dma.h>
+#include <linux/platform_data/dma-ep93xx.h>
 
 #include "dmaengine.h"
 
@@ -1118,8 +1118,9 @@ fail:
  * @chan: channel
  * @dma_addr: DMA mapped address of the buffer
  * @buf_len: length of the buffer (in bytes)
- * @period_len: lenght of a single period
+ * @period_len: length of a single period
  * @dir: direction of the operation
+ * @flags: tx descriptor status flags
  * @context: operation context (ignored)
  *
  * Prepares a descriptor for cyclic DMA operation. This means that once the
@@ -1133,7 +1134,8 @@ fail:
 static struct dma_async_tx_descriptor *
 ep93xx_dma_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t dma_addr,
 			   size_t buf_len, size_t period_len,
-			   enum dma_transfer_direction dir, void *context)
+			   enum dma_transfer_direction dir, unsigned long flags,
+			   void *context)
 {
 	struct ep93xx_dma_chan *edmac = to_ep93xx_dma_chan(chan);
 	struct ep93xx_dma_desc *desc, *first;
diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
index 8f84761..094437b 100644
--- a/drivers/dma/fsldma.c
+++ b/drivers/dma/fsldma.c
@@ -1015,7 +1015,7 @@ static irqreturn_t fsldma_chan_irq(int irq, void *data)
 	/*
 	 * Programming Error
 	 * The DMA_INTERRUPT async_tx is a NULL transfer, which will
-	 * triger a PE interrupt.
+	 * trigger a PE interrupt.
 	 */
 	if (stat & FSL_DMA_SR_PE) {
 		chan_dbg(chan, "irq: Programming Error INT\n");
diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c
index 5084975..f11b5b2 100644
--- a/drivers/dma/imx-dma.c
+++ b/drivers/dma/imx-dma.c
@@ -28,7 +28,7 @@
 #include <linux/module.h>
 
 #include <asm/irq.h>
-#include <mach/dma.h>
+#include <linux/platform_data/dma-imx.h>
 #include <mach/hardware.h>
 
 #include "dmaengine.h"
@@ -572,8 +572,8 @@ static void imxdma_tasklet(unsigned long data)
 	if (desc->desc.callback)
 		desc->desc.callback(desc->desc.callback_param);
 
-	/* If we are dealing with a cyclic descriptor keep it on ld_active
-	 * and dont mark the descripor as complete.
+	/* If we are dealing with a cyclic descriptor, keep it on ld_active
+	 * and dont mark the descriptor as complete.
 	 * Only in non-cyclic cases it would be marked as complete
 	 */
 	if (imxdma_chan_is_doing_cyclic(imxdmac))
@@ -801,7 +801,7 @@ static struct dma_async_tx_descriptor *imxdma_prep_slave_sg(
 static struct dma_async_tx_descriptor *imxdma_prep_dma_cyclic(
 		struct dma_chan *chan, dma_addr_t dma_addr, size_t buf_len,
 		size_t period_len, enum dma_transfer_direction direction,
-		void *context)
+		unsigned long flags, void *context)
 {
 	struct imxdma_channel *imxdmac = to_imxdma_chan(chan);
 	struct imxdma_engine *imxdma = imxdmac->imxdma;
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index 1dc2a4a..c099ca0 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -38,8 +38,8 @@
 #include <linux/of_device.h>
 
 #include <asm/irq.h>
-#include <mach/sdma.h>
-#include <mach/dma.h>
+#include <linux/platform_data/dma-imx-sdma.h>
+#include <linux/platform_data/dma-imx.h>
 #include <mach/hardware.h>
 
 #include "dmaengine.h"
@@ -1012,7 +1012,7 @@ err_out:
 static struct dma_async_tx_descriptor *sdma_prep_dma_cyclic(
 		struct dma_chan *chan, dma_addr_t dma_addr, size_t buf_len,
 		size_t period_len, enum dma_transfer_direction direction,
-		void *context)
+		unsigned long flags, void *context)
 {
 	struct sdma_channel *sdmac = to_sdma_chan(chan);
 	struct sdma_engine *sdma = sdmac->sdma;
diff --git a/drivers/dma/intel_mid_dma.c b/drivers/dma/intel_mid_dma.c
index 222e907..02b21d7 100644
--- a/drivers/dma/intel_mid_dma.c
+++ b/drivers/dma/intel_mid_dma.c
@@ -427,7 +427,7 @@ DMA engine callback Functions*/
  * intel_mid_dma_tx_submit -	callback to submit DMA transaction
  * @tx: dma engine descriptor
  *
- * Submit the DMA trasaction for this descriptor, start if ch idle
+ * Submit the DMA transaction for this descriptor, start if ch idle
  */
 static dma_cookie_t intel_mid_dma_tx_submit(struct dma_async_tx_descriptor *tx)
 {
diff --git a/drivers/dma/intel_mid_dma_regs.h b/drivers/dma/intel_mid_dma_regs.h
index 1bfa926..17b4219 100644
--- a/drivers/dma/intel_mid_dma_regs.h
+++ b/drivers/dma/intel_mid_dma_regs.h
@@ -168,9 +168,9 @@ union intel_mid_dma_cfg_hi {
  * @active_list: current active descriptors
  * @queue: current queued up descriptors
  * @free_list: current free descriptors
- * @slave: dma slave struture
- * @descs_allocated: total number of decsiptors allocated
- * @dma: dma device struture pointer
+ * @slave: dma slave structure
+ * @descs_allocated: total number of descriptors allocated
+ * @dma: dma device structure pointer
  * @busy: bool representing if ch is busy (active txn) or not
  * @in_use: bool representing if ch is in use or not
  * @raw_tfr: raw trf interrupt received
diff --git a/drivers/dma/ioat/dma_v2.c b/drivers/dma/ioat/dma_v2.c
index 8689576..b9d6678 100644
--- a/drivers/dma/ioat/dma_v2.c
+++ b/drivers/dma/ioat/dma_v2.c
@@ -434,12 +434,11 @@ static struct ioat_ring_ent *ioat2_alloc_ring_ent(struct dma_chan *chan, gfp_t f
 		return NULL;
 	memset(hw, 0, sizeof(*hw));
 
-	desc = kmem_cache_alloc(ioat2_cache, flags);
+	desc = kmem_cache_zalloc(ioat2_cache, flags);
 	if (!desc) {
 		pci_pool_free(dma->dma_pool, hw, phys);
 		return NULL;
 	}
-	memset(desc, 0, sizeof(*desc));
 
 	dma_async_tx_descriptor_init(&desc->txd, chan);
 	desc->txd.tx_submit = ioat2_tx_submit_unlock;
diff --git a/drivers/dma/ioat/hw.h b/drivers/dma/ioat/hw.h
index 60e6754..d2ff3fd 100644
--- a/drivers/dma/ioat/hw.h
+++ b/drivers/dma/ioat/hw.h
@@ -22,7 +22,6 @@
 #define _IOAT_HW_H_
 
 /* PCI Configuration Space Values */
-#define IOAT_PCI_VID            0x8086
 #define IOAT_MMIO_BAR		0
 
 /* CB device ID's */
@@ -31,9 +30,6 @@
 #define IOAT_PCI_DID_SCNB       0x65FF
 #define IOAT_PCI_DID_SNB        0x402F
 
-#define IOAT_PCI_RID            0x00
-#define IOAT_PCI_SVID           0x8086
-#define IOAT_PCI_SID            0x8086
 #define IOAT_VER_1_2            0x12    /* Version 1.2 */
 #define IOAT_VER_2_0            0x20    /* Version 2.0 */
 #define IOAT_VER_3_0            0x30    /* Version 3.0 */
diff --git a/drivers/dma/ioat/pci.c b/drivers/dma/ioat/pci.c
index 5e3a40f..c057306 100644
--- a/drivers/dma/ioat/pci.c
+++ b/drivers/dma/ioat/pci.c
@@ -40,6 +40,17 @@ MODULE_VERSION(IOAT_DMA_VERSION);
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_AUTHOR("Intel Corporation");
 
+#define PCI_DEVICE_ID_INTEL_IOAT_IVB0	0x0e20
+#define PCI_DEVICE_ID_INTEL_IOAT_IVB1	0x0e21
+#define PCI_DEVICE_ID_INTEL_IOAT_IVB2	0x0e22
+#define PCI_DEVICE_ID_INTEL_IOAT_IVB3	0x0e23
+#define PCI_DEVICE_ID_INTEL_IOAT_IVB4	0x0e24
+#define PCI_DEVICE_ID_INTEL_IOAT_IVB5	0x0e25
+#define PCI_DEVICE_ID_INTEL_IOAT_IVB6	0x0e26
+#define PCI_DEVICE_ID_INTEL_IOAT_IVB7	0x0e27
+#define PCI_DEVICE_ID_INTEL_IOAT_IVB8	0x0e2e
+#define PCI_DEVICE_ID_INTEL_IOAT_IVB9	0x0e2f
+
 static struct pci_device_id ioat_pci_tbl[] = {
 	/* I/OAT v1 platforms */
 	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT) },
@@ -83,6 +94,17 @@ static struct pci_device_id ioat_pci_tbl[] = {
 	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB8) },
 	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB9) },
 
+	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_IVB0) },
+	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_IVB1) },
+	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_IVB2) },
+	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_IVB3) },
+	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_IVB4) },
+	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_IVB5) },
+	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_IVB6) },
+	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_IVB7) },
+	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_IVB8) },
+	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_IVB9) },
+
 	{ 0, }
 };
 MODULE_DEVICE_TABLE(pci, ioat_pci_tbl);
diff --git a/drivers/dma/mmp_pdma.c b/drivers/dma/mmp_pdma.c
new file mode 100644
index 0000000..14da1f4
--- /dev/null
+++ b/drivers/dma/mmp_pdma.c
@@ -0,0 +1,875 @@
+/*
+ * Copyright 2012 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/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <linux/dmaengine.h>
+#include <linux/platform_device.h>
+#include <linux/device.h>
+#include <linux/platform_data/mmp_dma.h>
+#include <linux/dmapool.h>
+#include <linux/of_device.h>
+#include <linux/of.h>
+
+#include "dmaengine.h"
+
+#define DCSR		0x0000
+#define DALGN		0x00a0
+#define DINT		0x00f0
+#define DDADR		0x0200
+#define DSADR		0x0204
+#define DTADR		0x0208
+#define DCMD		0x020c
+
+#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) */
+
+#define PDMA_ALIGNMENT		3
+#define PDMA_MAX_DESC_BYTES	0x1000
+
+struct mmp_pdma_desc_hw {
+	u32 ddadr;	/* Points to the next descriptor + flags */
+	u32 dsadr;	/* DSADR value for the current transfer */
+	u32 dtadr;	/* DTADR value for the current transfer */
+	u32 dcmd;	/* DCMD value for the current transfer */
+} __aligned(32);
+
+struct mmp_pdma_desc_sw {
+	struct mmp_pdma_desc_hw desc;
+	struct list_head node;
+	struct list_head tx_list;
+	struct dma_async_tx_descriptor async_tx;
+};
+
+struct mmp_pdma_phy;
+
+struct mmp_pdma_chan {
+	struct device *dev;
+	struct dma_chan chan;
+	struct dma_async_tx_descriptor desc;
+	struct mmp_pdma_phy *phy;
+	enum dma_transfer_direction dir;
+
+	/* channel's basic info */
+	struct tasklet_struct tasklet;
+	u32 dcmd;
+	u32 drcmr;
+	u32 dev_addr;
+
+	/* list for desc */
+	spinlock_t desc_lock;		/* Descriptor list lock */
+	struct list_head chain_pending;	/* Link descriptors queue for pending */
+	struct list_head chain_running;	/* Link descriptors queue for running */
+	bool idle;			/* channel statue machine */
+
+	struct dma_pool *desc_pool;	/* Descriptors pool */
+};
+
+struct mmp_pdma_phy {
+	int idx;
+	void __iomem *base;
+	struct mmp_pdma_chan *vchan;
+};
+
+struct mmp_pdma_device {
+	int				dma_channels;
+	void __iomem			*base;
+	struct device			*dev;
+	struct dma_device		device;
+	struct mmp_pdma_phy		*phy;
+};
+
+#define tx_to_mmp_pdma_desc(tx) container_of(tx, struct mmp_pdma_desc_sw, async_tx)
+#define to_mmp_pdma_desc(lh) container_of(lh, struct mmp_pdma_desc_sw, node)
+#define to_mmp_pdma_chan(dchan) container_of(dchan, struct mmp_pdma_chan, chan)
+#define to_mmp_pdma_dev(dmadev) container_of(dmadev, struct mmp_pdma_device, device)
+
+static void set_desc(struct mmp_pdma_phy *phy, dma_addr_t addr)
+{
+	u32 reg = (phy->idx << 4) + DDADR;
+
+	writel(addr, phy->base + reg);
+}
+
+static void enable_chan(struct mmp_pdma_phy *phy)
+{
+	u32 reg;
+
+	if (!phy->vchan)
+		return;
+
+	reg = phy->vchan->drcmr;
+	reg = (((reg) < 64) ? 0x0100 : 0x1100) + (((reg) & 0x3f) << 2);
+	writel(DRCMR_MAPVLD | phy->idx, phy->base + reg);
+
+	reg = (phy->idx << 2) + DCSR;
+	writel(readl(phy->base + reg) | DCSR_RUN,
+					phy->base + reg);
+}
+
+static void disable_chan(struct mmp_pdma_phy *phy)
+{
+	u32 reg;
+
+	if (phy) {
+		reg = (phy->idx << 2) + DCSR;
+		writel(readl(phy->base + reg) & ~DCSR_RUN,
+						phy->base + reg);
+	}
+}
+
+static int clear_chan_irq(struct mmp_pdma_phy *phy)
+{
+	u32 dcsr;
+	u32 dint = readl(phy->base + DINT);
+	u32 reg = (phy->idx << 2) + DCSR;
+
+	if (dint & BIT(phy->idx)) {
+		/* clear irq */
+		dcsr = readl(phy->base + reg);
+		writel(dcsr, phy->base + reg);
+		if ((dcsr & DCSR_BUSERR) && (phy->vchan))
+			dev_warn(phy->vchan->dev, "DCSR_BUSERR\n");
+		return 0;
+	}
+	return -EAGAIN;
+}
+
+static irqreturn_t mmp_pdma_chan_handler(int irq, void *dev_id)
+{
+	struct mmp_pdma_phy *phy = dev_id;
+
+	if (clear_chan_irq(phy) == 0) {
+		tasklet_schedule(&phy->vchan->tasklet);
+		return IRQ_HANDLED;
+	} else
+		return IRQ_NONE;
+}
+
+static irqreturn_t mmp_pdma_int_handler(int irq, void *dev_id)
+{
+	struct mmp_pdma_device *pdev = dev_id;
+	struct mmp_pdma_phy *phy;
+	u32 dint = readl(pdev->base + DINT);
+	int i, ret;
+	int irq_num = 0;
+
+	while (dint) {
+		i = __ffs(dint);
+		dint &= (dint - 1);
+		phy = &pdev->phy[i];
+		ret = mmp_pdma_chan_handler(irq, phy);
+		if (ret == IRQ_HANDLED)
+			irq_num++;
+	}
+
+	if (irq_num)
+		return IRQ_HANDLED;
+	else
+		return IRQ_NONE;
+}
+
+/* lookup free phy channel as descending priority */
+static struct mmp_pdma_phy *lookup_phy(struct mmp_pdma_chan *pchan)
+{
+	int prio, i;
+	struct mmp_pdma_device *pdev = to_mmp_pdma_dev(pchan->chan.device);
+	struct mmp_pdma_phy *phy;
+
+	/*
+	 * dma channel priorities
+	 * ch 0 - 3,  16 - 19  <--> (0)
+	 * ch 4 - 7,  20 - 23  <--> (1)
+	 * ch 8 - 11, 24 - 27  <--> (2)
+	 * ch 12 - 15, 28 - 31  <--> (3)
+	 */
+	for (prio = 0; prio <= (((pdev->dma_channels - 1) & 0xf) >> 2); prio++) {
+		for (i = 0; i < pdev->dma_channels; i++) {
+			if (prio != ((i & 0xf) >> 2))
+				continue;
+			phy = &pdev->phy[i];
+			if (!phy->vchan) {
+				phy->vchan = pchan;
+				return phy;
+			}
+		}
+	}
+
+	return NULL;
+}
+
+/* desc->tx_list ==> pending list */
+static void append_pending_queue(struct mmp_pdma_chan *chan,
+					struct mmp_pdma_desc_sw *desc)
+{
+	struct mmp_pdma_desc_sw *tail =
+				to_mmp_pdma_desc(chan->chain_pending.prev);
+
+	if (list_empty(&chan->chain_pending))
+		goto out_splice;
+
+	/* one irq per queue, even appended */
+	tail->desc.ddadr = desc->async_tx.phys;
+	tail->desc.dcmd &= ~DCMD_ENDIRQEN;
+
+	/* softly link to pending list */
+out_splice:
+	list_splice_tail_init(&desc->tx_list, &chan->chain_pending);
+}
+
+/**
+ * start_pending_queue - transfer any pending transactions
+ * pending list ==> running list
+ */
+static void start_pending_queue(struct mmp_pdma_chan *chan)
+{
+	struct mmp_pdma_desc_sw *desc;
+
+	/* still in running, irq will start the pending list */
+	if (!chan->idle) {
+		dev_dbg(chan->dev, "DMA controller still busy\n");
+		return;
+	}
+
+	if (list_empty(&chan->chain_pending)) {
+		/* chance to re-fetch phy channel with higher prio */
+		if (chan->phy) {
+			chan->phy->vchan = NULL;
+			chan->phy = NULL;
+		}
+		dev_dbg(chan->dev, "no pending list\n");
+		return;
+	}
+
+	if (!chan->phy) {
+		chan->phy = lookup_phy(chan);
+		if (!chan->phy) {
+			dev_dbg(chan->dev, "no free dma channel\n");
+			return;
+		}
+	}
+
+	/*
+	 * pending -> running
+	 * reintilize pending list
+	 */
+	desc = list_first_entry(&chan->chain_pending,
+				struct mmp_pdma_desc_sw, node);
+	list_splice_tail_init(&chan->chain_pending, &chan->chain_running);
+
+	/*
+	 * Program the descriptor's address into the DMA controller,
+	 * then start the DMA transaction
+	 */
+	set_desc(chan->phy, desc->async_tx.phys);
+	enable_chan(chan->phy);
+	chan->idle = false;
+}
+
+
+/* desc->tx_list ==> pending list */
+static dma_cookie_t mmp_pdma_tx_submit(struct dma_async_tx_descriptor *tx)
+{
+	struct mmp_pdma_chan *chan = to_mmp_pdma_chan(tx->chan);
+	struct mmp_pdma_desc_sw *desc = tx_to_mmp_pdma_desc(tx);
+	struct mmp_pdma_desc_sw *child;
+	unsigned long flags;
+	dma_cookie_t cookie = -EBUSY;
+
+	spin_lock_irqsave(&chan->desc_lock, flags);
+
+	list_for_each_entry(child, &desc->tx_list, node) {
+		cookie = dma_cookie_assign(&child->async_tx);
+	}
+
+	append_pending_queue(chan, desc);
+
+	spin_unlock_irqrestore(&chan->desc_lock, flags);
+
+	return cookie;
+}
+
+struct mmp_pdma_desc_sw *mmp_pdma_alloc_descriptor(struct mmp_pdma_chan *chan)
+{
+	struct mmp_pdma_desc_sw *desc;
+	dma_addr_t pdesc;
+
+	desc = dma_pool_alloc(chan->desc_pool, GFP_ATOMIC, &pdesc);
+	if (!desc) {
+		dev_err(chan->dev, "out of memory for link descriptor\n");
+		return NULL;
+	}
+
+	memset(desc, 0, sizeof(*desc));
+	INIT_LIST_HEAD(&desc->tx_list);
+	dma_async_tx_descriptor_init(&desc->async_tx, &chan->chan);
+	/* each desc has submit */
+	desc->async_tx.tx_submit = mmp_pdma_tx_submit;
+	desc->async_tx.phys = pdesc;
+
+	return desc;
+}
+
+/**
+ * mmp_pdma_alloc_chan_resources - Allocate resources for DMA channel.
+ *
+ * This function will create a dma pool for descriptor allocation.
+ * Request irq only when channel is requested
+ * Return - The number of allocated descriptors.
+ */
+
+static int mmp_pdma_alloc_chan_resources(struct dma_chan *dchan)
+{
+	struct mmp_pdma_chan *chan = to_mmp_pdma_chan(dchan);
+
+	if (chan->desc_pool)
+		return 1;
+
+	chan->desc_pool =
+		dma_pool_create(dev_name(&dchan->dev->device), chan->dev,
+				  sizeof(struct mmp_pdma_desc_sw),
+				  __alignof__(struct mmp_pdma_desc_sw), 0);
+	if (!chan->desc_pool) {
+		dev_err(chan->dev, "unable to allocate descriptor pool\n");
+		return -ENOMEM;
+	}
+	if (chan->phy) {
+		chan->phy->vchan = NULL;
+		chan->phy = NULL;
+	}
+	chan->idle = true;
+	chan->dev_addr = 0;
+	return 1;
+}
+
+static void mmp_pdma_free_desc_list(struct mmp_pdma_chan *chan,
+				  struct list_head *list)
+{
+	struct mmp_pdma_desc_sw *desc, *_desc;
+
+	list_for_each_entry_safe(desc, _desc, list, node) {
+		list_del(&desc->node);
+		dma_pool_free(chan->desc_pool, desc, desc->async_tx.phys);
+	}
+}
+
+static void mmp_pdma_free_chan_resources(struct dma_chan *dchan)
+{
+	struct mmp_pdma_chan *chan = to_mmp_pdma_chan(dchan);
+	unsigned long flags;
+
+	spin_lock_irqsave(&chan->desc_lock, flags);
+	mmp_pdma_free_desc_list(chan, &chan->chain_pending);
+	mmp_pdma_free_desc_list(chan, &chan->chain_running);
+	spin_unlock_irqrestore(&chan->desc_lock, flags);
+
+	dma_pool_destroy(chan->desc_pool);
+	chan->desc_pool = NULL;
+	chan->idle = true;
+	chan->dev_addr = 0;
+	if (chan->phy) {
+		chan->phy->vchan = NULL;
+		chan->phy = NULL;
+	}
+	return;
+}
+
+static struct dma_async_tx_descriptor *
+mmp_pdma_prep_memcpy(struct dma_chan *dchan,
+	dma_addr_t dma_dst, dma_addr_t dma_src,
+	size_t len, unsigned long flags)
+{
+	struct mmp_pdma_chan *chan;
+	struct mmp_pdma_desc_sw *first = NULL, *prev = NULL, *new;
+	size_t copy = 0;
+
+	if (!dchan)
+		return NULL;
+
+	if (!len)
+		return NULL;
+
+	chan = to_mmp_pdma_chan(dchan);
+
+	if (!chan->dir) {
+		chan->dir = DMA_MEM_TO_MEM;
+		chan->dcmd = DCMD_INCTRGADDR | DCMD_INCSRCADDR;
+		chan->dcmd |= DCMD_BURST32;
+	}
+
+	do {
+		/* Allocate the link descriptor from DMA pool */
+		new = mmp_pdma_alloc_descriptor(chan);
+		if (!new) {
+			dev_err(chan->dev, "no memory for desc\n");
+			goto fail;
+		}
+
+		copy = min_t(size_t, len, PDMA_MAX_DESC_BYTES);
+
+		new->desc.dcmd = chan->dcmd | (DCMD_LENGTH & copy);
+		new->desc.dsadr = dma_src;
+		new->desc.dtadr = dma_dst;
+
+		if (!first)
+			first = new;
+		else
+			prev->desc.ddadr = new->async_tx.phys;
+
+		new->async_tx.cookie = 0;
+		async_tx_ack(&new->async_tx);
+
+		prev = new;
+		len -= copy;
+
+		if (chan->dir == DMA_MEM_TO_DEV) {
+			dma_src += copy;
+		} else if (chan->dir == DMA_DEV_TO_MEM) {
+			dma_dst += copy;
+		} else if (chan->dir == DMA_MEM_TO_MEM) {
+			dma_src += copy;
+			dma_dst += copy;
+		}
+
+		/* Insert the link descriptor to the LD ring */
+		list_add_tail(&new->node, &first->tx_list);
+	} while (len);
+
+	first->async_tx.flags = flags; /* client is in control of this ack */
+	first->async_tx.cookie = -EBUSY;
+
+	/* last desc and fire IRQ */
+	new->desc.ddadr = DDADR_STOP;
+	new->desc.dcmd |= DCMD_ENDIRQEN;
+
+	return &first->async_tx;
+
+fail:
+	if (first)
+		mmp_pdma_free_desc_list(chan, &first->tx_list);
+	return NULL;
+}
+
+static struct dma_async_tx_descriptor *
+mmp_pdma_prep_slave_sg(struct dma_chan *dchan, struct scatterlist *sgl,
+			 unsigned int sg_len, enum dma_transfer_direction dir,
+			 unsigned long flags, void *context)
+{
+	struct mmp_pdma_chan *chan = to_mmp_pdma_chan(dchan);
+	struct mmp_pdma_desc_sw *first = NULL, *prev = NULL, *new = NULL;
+	size_t len, avail;
+	struct scatterlist *sg;
+	dma_addr_t addr;
+	int i;
+
+	if ((sgl == NULL) || (sg_len == 0))
+		return NULL;
+
+	for_each_sg(sgl, sg, sg_len, i) {
+		addr = sg_dma_address(sg);
+		avail = sg_dma_len(sgl);
+
+		do {
+			len = min_t(size_t, avail, PDMA_MAX_DESC_BYTES);
+
+			/* allocate and populate the descriptor */
+			new = mmp_pdma_alloc_descriptor(chan);
+			if (!new) {
+				dev_err(chan->dev, "no memory for desc\n");
+				goto fail;
+			}
+
+			new->desc.dcmd = chan->dcmd | (DCMD_LENGTH & len);
+			if (dir == DMA_MEM_TO_DEV) {
+				new->desc.dsadr = addr;
+				new->desc.dtadr = chan->dev_addr;
+			} else {
+				new->desc.dsadr = chan->dev_addr;
+				new->desc.dtadr = addr;
+			}
+
+			if (!first)
+				first = new;
+			else
+				prev->desc.ddadr = new->async_tx.phys;
+
+			new->async_tx.cookie = 0;
+			async_tx_ack(&new->async_tx);
+			prev = new;
+
+			/* Insert the link descriptor to the LD ring */
+			list_add_tail(&new->node, &first->tx_list);
+
+			/* update metadata */
+			addr += len;
+			avail -= len;
+		} while (avail);
+	}
+
+	first->async_tx.cookie = -EBUSY;
+	first->async_tx.flags = flags;
+
+	/* last desc and fire IRQ */
+	new->desc.ddadr = DDADR_STOP;
+	new->desc.dcmd |= DCMD_ENDIRQEN;
+
+	return &first->async_tx;
+
+fail:
+	if (first)
+		mmp_pdma_free_desc_list(chan, &first->tx_list);
+	return NULL;
+}
+
+static int mmp_pdma_control(struct dma_chan *dchan, enum dma_ctrl_cmd cmd,
+		unsigned long arg)
+{
+	struct mmp_pdma_chan *chan = to_mmp_pdma_chan(dchan);
+	struct dma_slave_config *cfg = (void *)arg;
+	unsigned long flags;
+	int ret = 0;
+	u32 maxburst = 0, addr = 0;
+	enum dma_slave_buswidth width = DMA_SLAVE_BUSWIDTH_UNDEFINED;
+
+	if (!dchan)
+		return -EINVAL;
+
+	switch (cmd) {
+	case DMA_TERMINATE_ALL:
+		disable_chan(chan->phy);
+		if (chan->phy) {
+			chan->phy->vchan = NULL;
+			chan->phy = NULL;
+		}
+		spin_lock_irqsave(&chan->desc_lock, flags);
+		mmp_pdma_free_desc_list(chan, &chan->chain_pending);
+		mmp_pdma_free_desc_list(chan, &chan->chain_running);
+		spin_unlock_irqrestore(&chan->desc_lock, flags);
+		chan->idle = true;
+		break;
+	case DMA_SLAVE_CONFIG:
+		if (cfg->direction == DMA_DEV_TO_MEM) {
+			chan->dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC;
+			maxburst = cfg->src_maxburst;
+			width = cfg->src_addr_width;
+			addr = cfg->src_addr;
+		} else if (cfg->direction == DMA_MEM_TO_DEV) {
+			chan->dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG;
+			maxburst = cfg->dst_maxburst;
+			width = cfg->dst_addr_width;
+			addr = cfg->dst_addr;
+		}
+
+		if (width == DMA_SLAVE_BUSWIDTH_1_BYTE)
+			chan->dcmd |= DCMD_WIDTH1;
+		else if (width == DMA_SLAVE_BUSWIDTH_2_BYTES)
+			chan->dcmd |= DCMD_WIDTH2;
+		else if (width == DMA_SLAVE_BUSWIDTH_4_BYTES)
+			chan->dcmd |= DCMD_WIDTH4;
+
+		if (maxburst == 8)
+			chan->dcmd |= DCMD_BURST8;
+		else if (maxburst == 16)
+			chan->dcmd |= DCMD_BURST16;
+		else if (maxburst == 32)
+			chan->dcmd |= DCMD_BURST32;
+
+		if (cfg) {
+			chan->dir = cfg->direction;
+			chan->drcmr = cfg->slave_id;
+		}
+		chan->dev_addr = addr;
+		break;
+	default:
+		return -ENOSYS;
+	}
+
+	return ret;
+}
+
+static enum dma_status mmp_pdma_tx_status(struct dma_chan *dchan,
+			dma_cookie_t cookie, struct dma_tx_state *txstate)
+{
+	struct mmp_pdma_chan *chan = to_mmp_pdma_chan(dchan);
+	enum dma_status ret;
+	unsigned long flags;
+
+	spin_lock_irqsave(&chan->desc_lock, flags);
+	ret = dma_cookie_status(dchan, cookie, txstate);
+	spin_unlock_irqrestore(&chan->desc_lock, flags);
+
+	return ret;
+}
+
+/**
+ * mmp_pdma_issue_pending - Issue the DMA start command
+ * pending list ==> running list
+ */
+static void mmp_pdma_issue_pending(struct dma_chan *dchan)
+{
+	struct mmp_pdma_chan *chan = to_mmp_pdma_chan(dchan);
+	unsigned long flags;
+
+	spin_lock_irqsave(&chan->desc_lock, flags);
+	start_pending_queue(chan);
+	spin_unlock_irqrestore(&chan->desc_lock, flags);
+}
+
+/*
+ * dma_do_tasklet
+ * Do call back
+ * Start pending list
+ */
+static void dma_do_tasklet(unsigned long data)
+{
+	struct mmp_pdma_chan *chan = (struct mmp_pdma_chan *)data;
+	struct mmp_pdma_desc_sw *desc, *_desc;
+	LIST_HEAD(chain_cleanup);
+	unsigned long flags;
+
+	/* submit pending list; callback for each desc; free desc */
+
+	spin_lock_irqsave(&chan->desc_lock, flags);
+
+	/* update the cookie if we have some descriptors to cleanup */
+	if (!list_empty(&chan->chain_running)) {
+		dma_cookie_t cookie;
+
+		desc = to_mmp_pdma_desc(chan->chain_running.prev);
+		cookie = desc->async_tx.cookie;
+		dma_cookie_complete(&desc->async_tx);
+
+		dev_dbg(chan->dev, "completed_cookie=%d\n", cookie);
+	}
+
+	/*
+	 * move the descriptors to a temporary list so we can drop the lock
+	 * during the entire cleanup operation
+	 */
+	list_splice_tail_init(&chan->chain_running, &chain_cleanup);
+
+	/* the hardware is now idle and ready for more */
+	chan->idle = true;
+
+	/* Start any pending transactions automatically */
+	start_pending_queue(chan);
+	spin_unlock_irqrestore(&chan->desc_lock, flags);
+
+	/* Run the callback for each descriptor, in order */
+	list_for_each_entry_safe(desc, _desc, &chain_cleanup, node) {
+		struct dma_async_tx_descriptor *txd = &desc->async_tx;
+
+		/* Remove from the list of transactions */
+		list_del(&desc->node);
+		/* Run the link descriptor callback function */
+		if (txd->callback)
+			txd->callback(txd->callback_param);
+
+		dma_pool_free(chan->desc_pool, desc, txd->phys);
+	}
+}
+
+static int __devexit mmp_pdma_remove(struct platform_device *op)
+{
+	struct mmp_pdma_device *pdev = platform_get_drvdata(op);
+
+	dma_async_device_unregister(&pdev->device);
+	return 0;
+}
+
+static int __devinit mmp_pdma_chan_init(struct mmp_pdma_device *pdev,
+							int idx, int irq)
+{
+	struct mmp_pdma_phy *phy  = &pdev->phy[idx];
+	struct mmp_pdma_chan *chan;
+	int ret;
+
+	chan = devm_kzalloc(pdev->dev,
+			sizeof(struct mmp_pdma_chan), GFP_KERNEL);
+	if (chan == NULL)
+		return -ENOMEM;
+
+	phy->idx = idx;
+	phy->base = pdev->base;
+
+	if (irq) {
+		ret = devm_request_irq(pdev->dev, irq,
+			mmp_pdma_chan_handler, IRQF_DISABLED, "pdma", phy);
+		if (ret) {
+			dev_err(pdev->dev, "channel request irq fail!\n");
+			return ret;
+		}
+	}
+
+	spin_lock_init(&chan->desc_lock);
+	chan->dev = pdev->dev;
+	chan->chan.device = &pdev->device;
+	tasklet_init(&chan->tasklet, dma_do_tasklet, (unsigned long)chan);
+	INIT_LIST_HEAD(&chan->chain_pending);
+	INIT_LIST_HEAD(&chan->chain_running);
+
+	/* register virt channel to dma engine */
+	list_add_tail(&chan->chan.device_node,
+			&pdev->device.channels);
+
+	return 0;
+}
+
+static struct of_device_id mmp_pdma_dt_ids[] = {
+	{ .compatible = "marvell,pdma-1.0", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, mmp_pdma_dt_ids);
+
+static int __devinit mmp_pdma_probe(struct platform_device *op)
+{
+	struct mmp_pdma_device *pdev;
+	const struct of_device_id *of_id;
+	struct mmp_dma_platdata *pdata = dev_get_platdata(&op->dev);
+	struct resource *iores;
+	int i, ret, irq = 0;
+	int dma_channels = 0, irq_num = 0;
+
+	pdev = devm_kzalloc(&op->dev, sizeof(*pdev), GFP_KERNEL);
+	if (!pdev)
+		return -ENOMEM;
+	pdev->dev = &op->dev;
+
+	iores = platform_get_resource(op, IORESOURCE_MEM, 0);
+	if (!iores)
+		return -EINVAL;
+
+	pdev->base = devm_request_and_ioremap(pdev->dev, iores);
+	if (!pdev->base)
+		return -EADDRNOTAVAIL;
+
+	of_id = of_match_device(mmp_pdma_dt_ids, pdev->dev);
+	if (of_id)
+		of_property_read_u32(pdev->dev->of_node,
+				"#dma-channels", &dma_channels);
+	else if (pdata && pdata->dma_channels)
+		dma_channels = pdata->dma_channels;
+	else
+		dma_channels = 32;	/* default 32 channel */
+	pdev->dma_channels = dma_channels;
+
+	for (i = 0; i < dma_channels; i++) {
+		if (platform_get_irq(op, i) > 0)
+			irq_num++;
+	}
+
+	pdev->phy = devm_kzalloc(pdev->dev,
+		dma_channels * sizeof(struct mmp_pdma_chan), GFP_KERNEL);
+	if (pdev->phy == NULL)
+		return -ENOMEM;
+
+	INIT_LIST_HEAD(&pdev->device.channels);
+
+	if (irq_num != dma_channels) {
+		/* all chan share one irq, demux inside */
+		irq = platform_get_irq(op, 0);
+		ret = devm_request_irq(pdev->dev, irq,
+			mmp_pdma_int_handler, IRQF_DISABLED, "pdma", pdev);
+		if (ret)
+			return ret;
+	}
+
+	for (i = 0; i < dma_channels; i++) {
+		irq = (irq_num != dma_channels) ? 0 : platform_get_irq(op, i);
+		ret = mmp_pdma_chan_init(pdev, i, irq);
+		if (ret)
+			return ret;
+	}
+
+	dma_cap_set(DMA_SLAVE, pdev->device.cap_mask);
+	dma_cap_set(DMA_MEMCPY, pdev->device.cap_mask);
+	dma_cap_set(DMA_SLAVE, pdev->device.cap_mask);
+	pdev->device.dev = &op->dev;
+	pdev->device.device_alloc_chan_resources = mmp_pdma_alloc_chan_resources;
+	pdev->device.device_free_chan_resources = mmp_pdma_free_chan_resources;
+	pdev->device.device_tx_status = mmp_pdma_tx_status;
+	pdev->device.device_prep_dma_memcpy = mmp_pdma_prep_memcpy;
+	pdev->device.device_prep_slave_sg = mmp_pdma_prep_slave_sg;
+	pdev->device.device_issue_pending = mmp_pdma_issue_pending;
+	pdev->device.device_control = mmp_pdma_control;
+	pdev->device.copy_align = PDMA_ALIGNMENT;
+
+	if (pdev->dev->coherent_dma_mask)
+		dma_set_mask(pdev->dev, pdev->dev->coherent_dma_mask);
+	else
+		dma_set_mask(pdev->dev, DMA_BIT_MASK(64));
+
+	ret = dma_async_device_register(&pdev->device);
+	if (ret) {
+		dev_err(pdev->device.dev, "unable to register\n");
+		return ret;
+	}
+
+	dev_info(pdev->device.dev, "initialized\n");
+	return 0;
+}
+
+static const struct platform_device_id mmp_pdma_id_table[] = {
+	{ "mmp-pdma", },
+	{ },
+};
+
+static struct platform_driver mmp_pdma_driver = {
+	.driver		= {
+		.name	= "mmp-pdma",
+		.owner  = THIS_MODULE,
+		.of_match_table = mmp_pdma_dt_ids,
+	},
+	.id_table	= mmp_pdma_id_table,
+	.probe		= mmp_pdma_probe,
+	.remove		= __devexit_p(mmp_pdma_remove),
+};
+
+module_platform_driver(mmp_pdma_driver);
+
+MODULE_DESCRIPTION("MARVELL MMP Periphera DMA Driver");
+MODULE_AUTHOR("Marvell International Ltd.");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/dma/mmp_tdma.c b/drivers/dma/mmp_tdma.c
index 8a15cf2..05ce16f 100644
--- a/drivers/dma/mmp_tdma.c
+++ b/drivers/dma/mmp_tdma.c
@@ -19,7 +19,8 @@
 #include <linux/platform_device.h>
 #include <linux/device.h>
 #include <mach/regs-icu.h>
-#include <mach/sram.h>
+#include <linux/of_device.h>
+#include <linux/platform_data/dma-mmp_tdma.h>
 
 #include "dmaengine.h"
 
@@ -127,7 +128,6 @@ struct mmp_tdma_device {
 	void __iomem			*base;
 	struct dma_device		device;
 	struct mmp_tdma_chan		*tdmac[TDMA_CHANNEL_NUM];
-	int				irq;
 };
 
 #define to_mmp_tdma_chan(dchan) container_of(dchan, struct mmp_tdma_chan, chan)
@@ -358,7 +358,7 @@ struct mmp_tdma_desc *mmp_tdma_alloc_descriptor(struct mmp_tdma_chan *tdmac)
 static struct dma_async_tx_descriptor *mmp_tdma_prep_dma_cyclic(
 		struct dma_chan *chan, dma_addr_t dma_addr, size_t buf_len,
 		size_t period_len, enum dma_transfer_direction direction,
-		void *context)
+		unsigned long flags, void *context)
 {
 	struct mmp_tdma_chan *tdmac = to_mmp_tdma_chan(chan);
 	struct mmp_tdma_desc *desc;
@@ -492,7 +492,7 @@ static int __devinit mmp_tdma_chan_init(struct mmp_tdma_device *tdev,
 		return -ENOMEM;
 	}
 	if (irq)
-		tdmac->irq = irq + idx;
+		tdmac->irq = irq;
 	tdmac->dev	   = tdev->dev;
 	tdmac->chan.device = &tdev->device;
 	tdmac->idx	   = idx;
@@ -505,34 +505,43 @@ static int __devinit mmp_tdma_chan_init(struct mmp_tdma_device *tdev,
 	/* add the channel to tdma_chan list */
 	list_add_tail(&tdmac->chan.device_node,
 			&tdev->device.channels);
-
 	return 0;
 }
 
+static struct of_device_id mmp_tdma_dt_ids[] = {
+	{ .compatible = "marvell,adma-1.0", .data = (void *)MMP_AUD_TDMA},
+	{ .compatible = "marvell,pxa910-squ", .data = (void *)PXA910_SQU},
+	{}
+};
+MODULE_DEVICE_TABLE(of, mmp_tdma_dt_ids);
+
 static int __devinit mmp_tdma_probe(struct platform_device *pdev)
 {
-	const struct platform_device_id *id = platform_get_device_id(pdev);
-	enum mmp_tdma_type type = id->driver_data;
+	enum mmp_tdma_type type;
+	const struct of_device_id *of_id;
 	struct mmp_tdma_device *tdev;
 	struct resource *iores;
 	int i, ret;
-	int irq = 0;
+	int irq = 0, irq_num = 0;
 	int chan_num = TDMA_CHANNEL_NUM;
 
+	of_id = of_match_device(mmp_tdma_dt_ids, &pdev->dev);
+	if (of_id)
+		type = (enum mmp_tdma_type) of_id->data;
+	else
+		type = platform_get_device_id(pdev)->driver_data;
+
 	/* always have couple channels */
 	tdev = devm_kzalloc(&pdev->dev, sizeof(*tdev), GFP_KERNEL);
 	if (!tdev)
 		return -ENOMEM;
 
 	tdev->dev = &pdev->dev;
-	iores = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	if (!iores)
-		return -EINVAL;
 
-	if (resource_size(iores) != chan_num)
-		tdev->irq = iores->start;
-	else
-		irq = iores->start;
+	for (i = 0; i < chan_num; i++) {
+		if (platform_get_irq(pdev, i) > 0)
+			irq_num++;
+	}
 
 	iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!iores)
@@ -542,25 +551,26 @@ static int __devinit mmp_tdma_probe(struct platform_device *pdev)
 	if (!tdev->base)
 		return -EADDRNOTAVAIL;
 
-	if (tdev->irq) {
-		ret = devm_request_irq(&pdev->dev, tdev->irq,
+	INIT_LIST_HEAD(&tdev->device.channels);
+
+	if (irq_num != chan_num) {
+		irq = platform_get_irq(pdev, 0);
+		ret = devm_request_irq(&pdev->dev, irq,
 			mmp_tdma_int_handler, IRQF_DISABLED, "tdma", tdev);
 		if (ret)
 			return ret;
 	}
 
-	dma_cap_set(DMA_SLAVE, tdev->device.cap_mask);
-	dma_cap_set(DMA_CYCLIC, tdev->device.cap_mask);
-
-	INIT_LIST_HEAD(&tdev->device.channels);
-
 	/* initialize channel parameters */
 	for (i = 0; i < chan_num; i++) {
+		irq = (irq_num != chan_num) ? 0 : platform_get_irq(pdev, i);
 		ret = mmp_tdma_chan_init(tdev, i, irq, type);
 		if (ret)
 			return ret;
 	}
 
+	dma_cap_set(DMA_SLAVE, tdev->device.cap_mask);
+	dma_cap_set(DMA_CYCLIC, tdev->device.cap_mask);
 	tdev->device.dev = &pdev->dev;
 	tdev->device.device_alloc_chan_resources =
 					mmp_tdma_alloc_chan_resources;
@@ -595,6 +605,7 @@ static struct platform_driver mmp_tdma_driver = {
 	.driver		= {
 		.name	= "mmp-tdma",
 		.owner  = THIS_MODULE,
+		.of_match_table = mmp_tdma_dt_ids,
 	},
 	.id_table	= mmp_tdma_id_table,
 	.probe		= mmp_tdma_probe,
diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c
index 0b12e68..e362e2b 100644
--- a/drivers/dma/mv_xor.c
+++ b/drivers/dma/mv_xor.c
@@ -26,7 +26,7 @@
 #include <linux/platform_device.h>
 #include <linux/memory.h>
 #include <linux/clk.h>
-#include <plat/mv_xor.h>
+#include <linux/platform_data/dma-mv_xor.h>
 
 #include "dmaengine.h"
 #include "mv_xor.h"
diff --git a/drivers/dma/mxs-dma.c b/drivers/dma/mxs-dma.c
index 7f41b25..9f02e79 100644
--- a/drivers/dma/mxs-dma.c
+++ b/drivers/dma/mxs-dma.c
@@ -101,7 +101,8 @@ struct mxs_dma_ccw {
 	u32		pio_words[MXS_PIO_WORDS];
 };
 
-#define NUM_CCW	(int)(PAGE_SIZE / sizeof(struct mxs_dma_ccw))
+#define CCW_BLOCK_SIZE	(4 * PAGE_SIZE)
+#define NUM_CCW	(int)(CCW_BLOCK_SIZE / sizeof(struct mxs_dma_ccw))
 
 struct mxs_dma_chan {
 	struct mxs_dma_engine		*mxs_dma;
@@ -354,14 +355,15 @@ static int mxs_dma_alloc_chan_resources(struct dma_chan *chan)
 
 	mxs_chan->chan_irq = data->chan_irq;
 
-	mxs_chan->ccw = dma_alloc_coherent(mxs_dma->dma_device.dev, PAGE_SIZE,
-				&mxs_chan->ccw_phys, GFP_KERNEL);
+	mxs_chan->ccw = dma_alloc_coherent(mxs_dma->dma_device.dev,
+				CCW_BLOCK_SIZE, &mxs_chan->ccw_phys,
+				GFP_KERNEL);
 	if (!mxs_chan->ccw) {
 		ret = -ENOMEM;
 		goto err_alloc;
 	}
 
-	memset(mxs_chan->ccw, 0, PAGE_SIZE);
+	memset(mxs_chan->ccw, 0, CCW_BLOCK_SIZE);
 
 	if (mxs_chan->chan_irq != NO_IRQ) {
 		ret = request_irq(mxs_chan->chan_irq, mxs_dma_int_handler,
@@ -387,7 +389,7 @@ static int mxs_dma_alloc_chan_resources(struct dma_chan *chan)
 err_clk:
 	free_irq(mxs_chan->chan_irq, mxs_dma);
 err_irq:
-	dma_free_coherent(mxs_dma->dma_device.dev, PAGE_SIZE,
+	dma_free_coherent(mxs_dma->dma_device.dev, CCW_BLOCK_SIZE,
 			mxs_chan->ccw, mxs_chan->ccw_phys);
 err_alloc:
 	return ret;
@@ -402,7 +404,7 @@ static void mxs_dma_free_chan_resources(struct dma_chan *chan)
 
 	free_irq(mxs_chan->chan_irq, mxs_dma);
 
-	dma_free_coherent(mxs_dma->dma_device.dev, PAGE_SIZE,
+	dma_free_coherent(mxs_dma->dma_device.dev, CCW_BLOCK_SIZE,
 			mxs_chan->ccw, mxs_chan->ccw_phys);
 
 	clk_disable_unprepare(mxs_dma->clk);
@@ -531,7 +533,7 @@ err_out:
 static struct dma_async_tx_descriptor *mxs_dma_prep_dma_cyclic(
 		struct dma_chan *chan, dma_addr_t dma_addr, size_t buf_len,
 		size_t period_len, enum dma_transfer_direction direction,
-		void *context)
+		unsigned long flags, void *context)
 {
 	struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(chan);
 	struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c
index ae05618..bb2d8e7 100644
--- a/drivers/dma/omap-dma.c
+++ b/drivers/dma/omap-dma.c
@@ -18,6 +18,8 @@
 #include <linux/spinlock.h>
 
 #include "virt-dma.h"
+
+#include <plat/cpu.h>
 #include <plat/dma.h>
 
 struct omap_dmadev {
@@ -34,6 +36,7 @@ struct omap_chan {
 	struct dma_slave_config	cfg;
 	unsigned dma_sig;
 	bool cyclic;
+	bool paused;
 
 	int dma_ch;
 	struct omap_desc *desc;
@@ -365,7 +368,8 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg(
 
 static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic(
 	struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,
-	size_t period_len, enum dma_transfer_direction dir, void *context)
+	size_t period_len, enum dma_transfer_direction dir, unsigned long flags,
+	void *context)
 {
 	struct omap_chan *c = to_omap_dma_chan(chan);
 	enum dma_slave_buswidth dev_width;
@@ -413,7 +417,10 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic(
 	d->dev_addr = dev_addr;
 	d->fi = burst;
 	d->es = es;
-	d->sync_mode = OMAP_DMA_SYNC_PACKET;
+	if (burst)
+		d->sync_mode = OMAP_DMA_SYNC_PACKET;
+	else
+		d->sync_mode = OMAP_DMA_SYNC_ELEMENT;
 	d->sync_type = sync_type;
 	d->periph_port = OMAP_DMA_PORT_MPUI;
 	d->sg[0].addr = buf_addr;
@@ -424,7 +431,10 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic(
 	if (!c->cyclic) {
 		c->cyclic = true;
 		omap_dma_link_lch(c->dma_ch, c->dma_ch);
-		omap_enable_dma_irq(c->dma_ch, OMAP_DMA_FRAME_IRQ);
+
+		if (flags & DMA_PREP_INTERRUPT)
+			omap_enable_dma_irq(c->dma_ch, OMAP_DMA_FRAME_IRQ);
+
 		omap_disable_dma_irq(c->dma_ch, OMAP_DMA_BLOCK_IRQ);
 	}
 
@@ -433,7 +443,7 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic(
 		omap_set_dma_dest_burst_mode(c->dma_ch, OMAP_DMA_DATA_BURST_16);
 	}
 
-	return vchan_tx_prep(&c->vc, &d->vd, DMA_CTRL_ACK | DMA_PREP_INTERRUPT);
+	return vchan_tx_prep(&c->vc, &d->vd, flags);
 }
 
 static int omap_dma_slave_config(struct omap_chan *c, struct dma_slave_config *cfg)
@@ -467,11 +477,14 @@ static int omap_dma_terminate_all(struct omap_chan *c)
 	 */
 	if (c->desc) {
 		c->desc = NULL;
-		omap_stop_dma(c->dma_ch);
+		/* Avoid stopping the dma twice */
+		if (!c->paused)
+			omap_stop_dma(c->dma_ch);
 	}
 
 	if (c->cyclic) {
 		c->cyclic = false;
+		c->paused = false;
 		omap_dma_unlink_lch(c->dma_ch, c->dma_ch);
 	}
 
@@ -484,14 +497,30 @@ static int omap_dma_terminate_all(struct omap_chan *c)
 
 static int omap_dma_pause(struct omap_chan *c)
 {
-	/* FIXME: not supported by platform private API */
-	return -EINVAL;
+	/* Pause/Resume only allowed with cyclic mode */
+	if (!c->cyclic)
+		return -EINVAL;
+
+	if (!c->paused) {
+		omap_stop_dma(c->dma_ch);
+		c->paused = true;
+	}
+
+	return 0;
 }
 
 static int omap_dma_resume(struct omap_chan *c)
 {
-	/* FIXME: not supported by platform private API */
-	return -EINVAL;
+	/* Pause/Resume only allowed with cyclic mode */
+	if (!c->cyclic)
+		return -EINVAL;
+
+	if (c->paused) {
+		omap_start_dma(c->dma_ch);
+		c->paused = false;
+	}
+
+	return 0;
 }
 
 static int omap_dma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index f5843bc..665668b 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -23,7 +23,6 @@
 #include <linux/dmaengine.h>
 #include <linux/amba/bus.h>
 #include <linux/amba/pl330.h>
-#include <linux/pm_runtime.h>
 #include <linux/scatterlist.h>
 #include <linux/of.h>
 
@@ -522,7 +521,7 @@ enum desc_status {
 	/* In the DMAC pool */
 	FREE,
 	/*
-	 * Allocted to some channel during prep_xxx
+	 * Allocated to some channel during prep_xxx
 	 * Also may be sitting on the work_list.
 	 */
 	PREP,
@@ -586,8 +585,6 @@ struct dma_pl330_dmac {
 
 	/* Peripheral channels connected to this DMAC */
 	struct dma_pl330_chan *peripherals; /* keep at end */
-
-	struct clk *clk;
 };
 
 struct dma_pl330_desc {
@@ -2395,7 +2392,7 @@ static int pl330_alloc_chan_resources(struct dma_chan *chan)
 	pch->pl330_chid = pl330_request_channel(&pdmac->pif);
 	if (!pch->pl330_chid) {
 		spin_unlock_irqrestore(&pch->lock, flags);
-		return 0;
+		return -ENOMEM;
 	}
 
 	tasklet_init(&pch->task, pl330_tasklet, (unsigned long) pch);
@@ -2685,7 +2682,7 @@ static inline int get_burst_len(struct dma_pl330_desc *desc, size_t len)
 static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic(
 		struct dma_chan *chan, dma_addr_t dma_addr, size_t len,
 		size_t period_len, enum dma_transfer_direction direction,
-		void *context)
+		unsigned long flags, void *context)
 {
 	struct dma_pl330_desc *desc;
 	struct dma_pl330_chan *pch = to_pchan(chan);
@@ -2889,29 +2886,17 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
 		goto probe_err1;
 	}
 
-	pdmac->clk = clk_get(&adev->dev, "dma");
-	if (IS_ERR(pdmac->clk)) {
-		dev_err(&adev->dev, "Cannot get operation clock.\n");
-		ret = -EINVAL;
-		goto probe_err2;
-	}
-
 	amba_set_drvdata(adev, pdmac);
 
-#ifndef CONFIG_PM_RUNTIME
-	/* enable dma clk */
-	clk_enable(pdmac->clk);
-#endif
-
 	irq = adev->irq[0];
 	ret = request_irq(irq, pl330_irq_handler, 0,
 			dev_name(&adev->dev), pi);
 	if (ret)
-		goto probe_err3;
+		goto probe_err2;
 
 	ret = pl330_add(pi);
 	if (ret)
-		goto probe_err4;
+		goto probe_err3;
 
 	INIT_LIST_HEAD(&pdmac->desc_pool);
 	spin_lock_init(&pdmac->pool_lock);
@@ -2933,7 +2918,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
 	if (!pdmac->peripherals) {
 		ret = -ENOMEM;
 		dev_err(&adev->dev, "unable to allocate pdmac->peripherals\n");
-		goto probe_err5;
+		goto probe_err4;
 	}
 
 	for (i = 0; i < num_chan; i++) {
@@ -2961,6 +2946,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
 		if (pi->pcfg.num_peri) {
 			dma_cap_set(DMA_SLAVE, pd->cap_mask);
 			dma_cap_set(DMA_CYCLIC, pd->cap_mask);
+			dma_cap_set(DMA_PRIVATE, pd->cap_mask);
 		}
 	}
 
@@ -2976,7 +2962,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
 	ret = dma_async_device_register(pd);
 	if (ret) {
 		dev_err(&adev->dev, "unable to register DMAC\n");
-		goto probe_err5;
+		goto probe_err4;
 	}
 
 	dev_info(&adev->dev,
@@ -2989,15 +2975,10 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
 
 	return 0;
 
-probe_err5:
-	pl330_del(pi);
 probe_err4:
-	free_irq(irq, pi);
+	pl330_del(pi);
 probe_err3:
-#ifndef CONFIG_PM_RUNTIME
-	clk_disable(pdmac->clk);
-#endif
-	clk_put(pdmac->clk);
+	free_irq(irq, pi);
 probe_err2:
 	iounmap(pi->base);
 probe_err1:
@@ -3044,10 +3025,6 @@ static int __devexit pl330_remove(struct amba_device *adev)
 	res = &adev->res;
 	release_mem_region(res->start, resource_size(res));
 
-#ifndef CONFIG_PM_RUNTIME
-	clk_disable(pdmac->clk);
-#endif
-
 	kfree(pdmac);
 
 	return 0;
@@ -3063,49 +3040,10 @@ static struct amba_id pl330_ids[] = {
 
 MODULE_DEVICE_TABLE(amba, pl330_ids);
 
-#ifdef CONFIG_PM_RUNTIME
-static int pl330_runtime_suspend(struct device *dev)
-{
-	struct dma_pl330_dmac *pdmac = dev_get_drvdata(dev);
-
-	if (!pdmac) {
-		dev_err(dev, "failed to get dmac\n");
-		return -ENODEV;
-	}
-
-	clk_disable(pdmac->clk);
-
-	return 0;
-}
-
-static int pl330_runtime_resume(struct device *dev)
-{
-	struct dma_pl330_dmac *pdmac = dev_get_drvdata(dev);
-
-	if (!pdmac) {
-		dev_err(dev, "failed to get dmac\n");
-		return -ENODEV;
-	}
-
-	clk_enable(pdmac->clk);
-
-	return 0;
-}
-#else
-#define pl330_runtime_suspend	NULL
-#define pl330_runtime_resume	NULL
-#endif /* CONFIG_PM_RUNTIME */
-
-static const struct dev_pm_ops pl330_pm_ops = {
-	.runtime_suspend = pl330_runtime_suspend,
-	.runtime_resume = pl330_runtime_resume,
-};
-
 static struct amba_driver pl330_driver = {
 	.drv = {
 		.owner = THIS_MODULE,
 		.name = "dma-pl330",
-		.pm = &pl330_pm_ops,
 	},
 	.id_table = pl330_ids,
 	.probe = pl330_probe,
diff --git a/drivers/dma/ppc4xx/adma.c b/drivers/dma/ppc4xx/adma.c
index ced9882..f72348d 100644
--- a/drivers/dma/ppc4xx/adma.c
+++ b/drivers/dma/ppc4xx/adma.c
@@ -4446,7 +4446,7 @@ static int __devinit ppc440spe_adma_probe(struct platform_device *ofdev)
 		ret = -ENOMEM;
 		goto err_dma_alloc;
 	}
-	dev_dbg(&ofdev->dev, "allocted descriptor pool virt 0x%p phys 0x%llx\n",
+	dev_dbg(&ofdev->dev, "allocated descriptor pool virt 0x%p phys 0x%llx\n",
 		adev->dma_desc_pool_virt, (u64)adev->dma_desc_pool);
 
 	regs = ioremap(res.start, resource_size(&res));
diff --git a/drivers/dma/sa11x0-dma.c b/drivers/dma/sa11x0-dma.c
index f5a7360..b893159 100644
--- a/drivers/dma/sa11x0-dma.c
+++ b/drivers/dma/sa11x0-dma.c
@@ -614,7 +614,7 @@ static struct dma_async_tx_descriptor *sa11x0_dma_prep_slave_sg(
 
 static struct dma_async_tx_descriptor *sa11x0_dma_prep_dma_cyclic(
 	struct dma_chan *chan, dma_addr_t addr, size_t size, size_t period,
-	enum dma_transfer_direction dir, void *context)
+	enum dma_transfer_direction dir, unsigned long flags, void *context)
 {
 	struct sa11x0_dma_chan *c = to_sa11x0_dma_chan(chan);
 	struct sa11x0_dma_desc *txd;
diff --git a/drivers/dma/sirf-dma.c b/drivers/dma/sirf-dma.c
index 434ad31..64385cd 100644
--- a/drivers/dma/sirf-dma.c
+++ b/drivers/dma/sirf-dma.c
@@ -489,7 +489,7 @@ err_dir:
 static struct dma_async_tx_descriptor *
 sirfsoc_dma_prep_cyclic(struct dma_chan *chan, dma_addr_t addr,
 	size_t buf_len, size_t period_len,
-	enum dma_transfer_direction direction, void *context)
+	enum dma_transfer_direction direction, unsigned long flags, void *context)
 {
 	struct sirfsoc_dma_chan *schan = dma_chan_to_sirfsoc_dma_chan(chan);
 	struct sirfsoc_dma_desc *sdesc = NULL;
@@ -570,21 +570,19 @@ static int __devinit sirfsoc_dma_probe(struct platform_device *op)
 
 	if (of_property_read_u32(dn, "cell-index", &id)) {
 		dev_err(dev, "Fail to get DMAC index\n");
-		ret = -ENODEV;
-		goto free_mem;
+		return -ENODEV;
 	}
 
 	sdma->irq = irq_of_parse_and_map(dn, 0);
 	if (sdma->irq == NO_IRQ) {
 		dev_err(dev, "Error mapping IRQ!\n");
-		ret = -EINVAL;
-		goto free_mem;
+		return -EINVAL;
 	}
 
 	ret = of_address_to_resource(dn, 0, &res);
 	if (ret) {
 		dev_err(dev, "Error parsing memory region!\n");
-		goto free_mem;
+		goto irq_dispose;
 	}
 
 	regs_start = res.start;
@@ -597,12 +595,11 @@ static int __devinit sirfsoc_dma_probe(struct platform_device *op)
 		goto irq_dispose;
 	}
 
-	ret = devm_request_irq(dev, sdma->irq, &sirfsoc_dma_irq, 0, DRV_NAME,
-		sdma);
+	ret = request_irq(sdma->irq, &sirfsoc_dma_irq, 0, DRV_NAME, sdma);
 	if (ret) {
 		dev_err(dev, "Error requesting IRQ!\n");
 		ret = -EINVAL;
-		goto unmap_mem;
+		goto irq_dispose;
 	}
 
 	dma = &sdma->dma;
@@ -652,13 +649,9 @@ static int __devinit sirfsoc_dma_probe(struct platform_device *op)
 	return 0;
 
 free_irq:
-	devm_free_irq(dev, sdma->irq, sdma);
+	free_irq(sdma->irq, sdma);
 irq_dispose:
 	irq_dispose_mapping(sdma->irq);
-unmap_mem:
-	iounmap(sdma->base);
-free_mem:
-	devm_kfree(dev, sdma);
 	return ret;
 }
 
@@ -668,10 +661,8 @@ static int __devexit sirfsoc_dma_remove(struct platform_device *op)
 	struct sirfsoc_dma *sdma = dev_get_drvdata(dev);
 
 	dma_async_device_unregister(&sdma->dma);
-	devm_free_irq(dev, sdma->irq, sdma);
+	free_irq(sdma->irq, sdma);
 	irq_dispose_mapping(sdma->irq);
-	iounmap(sdma->base);
-	devm_kfree(dev, sdma);
 	return 0;
 }
 
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index 000d309..ae55091 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -2347,7 +2347,8 @@ static struct dma_async_tx_descriptor *d40_prep_slave_sg(struct dma_chan *chan,
 static struct dma_async_tx_descriptor *
 dma40_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t dma_addr,
 		     size_t buf_len, size_t period_len,
-		     enum dma_transfer_direction direction, void *context)
+		     enum dma_transfer_direction direction, unsigned long flags,
+		     void *context)
 {
 	unsigned int periods = buf_len / period_len;
 	struct dma_async_tx_descriptor *txd;
@@ -2920,19 +2921,23 @@ static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev)
 	struct d40_base *base = NULL;
 	int num_log_chans = 0;
 	int num_phy_chans;
+	int clk_ret = -EINVAL;
 	int i;
 	u32 pid;
 	u32 cid;
 	u8 rev;
 
 	clk = clk_get(&pdev->dev, NULL);
-
 	if (IS_ERR(clk)) {
 		d40_err(&pdev->dev, "No matching clock found\n");
 		goto failure;
 	}
 
-	clk_enable(clk);
+	clk_ret = clk_prepare_enable(clk);
+	if (clk_ret) {
+		d40_err(&pdev->dev, "Failed to prepare/enable clock\n");
+		goto failure;
+	}
 
 	/* Get IO for DMAC base address */
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "base");
@@ -3062,10 +3067,10 @@ static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev)
 	return base;
 
 failure:
-	if (!IS_ERR(clk)) {
-		clk_disable(clk);
+	if (!clk_ret)
+		clk_disable_unprepare(clk);
+	if (!IS_ERR(clk))
 		clk_put(clk);
-	}
 	if (virtbase)
 		iounmap(virtbase);
 	if (res)
diff --git a/drivers/dma/ste_dma40_ll.h b/drivers/dma/ste_dma40_ll.h
index 51e8e53..6d47373 100644
--- a/drivers/dma/ste_dma40_ll.h
+++ b/drivers/dma/ste_dma40_ll.h
@@ -202,7 +202,7 @@
 /* LLI related structures */
 
 /**
- * struct d40_phy_lli - The basic configration register for each physical
+ * struct d40_phy_lli - The basic configuration register for each physical
  * channel.
  *
  * @reg_cfg: The configuration register.
diff --git a/drivers/dma/tegra20-apb-dma.c b/drivers/dma/tegra20-apb-dma.c
index 24acd71..24a6512 100644
--- a/drivers/dma/tegra20-apb-dma.c
+++ b/drivers/dma/tegra20-apb-dma.c
@@ -201,7 +201,7 @@ struct tegra_dma {
 	struct clk			*dma_clk;
 	spinlock_t			global_lock;
 	void __iomem			*base_addr;
-	struct tegra_dma_chip_data	*chip_data;
+	const struct tegra_dma_chip_data *chip_data;
 
 	/* Some register need to be cache before suspend */
 	u32				reg_gen;
@@ -475,8 +475,7 @@ static void tegra_dma_abort_all(struct tegra_dma_channel *tdc)
 	while (!list_empty(&tdc->pending_sg_req)) {
 		sgreq = list_first_entry(&tdc->pending_sg_req,
 						typeof(*sgreq), node);
-		list_del(&sgreq->node);
-		list_add_tail(&sgreq->node, &tdc->free_sg_req);
+		list_move_tail(&sgreq->node, &tdc->free_sg_req);
 		if (sgreq->last_sg) {
 			dma_desc = sgreq->dma_desc;
 			dma_desc->dma_status = DMA_ERROR;
@@ -570,8 +569,7 @@ static void handle_cont_sngl_cycle_dma_done(struct tegra_dma_channel *tdc,
 
 	/* If not last req then put at end of pending list */
 	if (!list_is_last(&sgreq->node, &tdc->pending_sg_req)) {
-		list_del(&sgreq->node);
-		list_add_tail(&sgreq->node, &tdc->pending_sg_req);
+		list_move_tail(&sgreq->node, &tdc->pending_sg_req);
 		sgreq->configured = false;
 		st = handle_continuous_head_request(tdc, sgreq, to_terminate);
 		if (!st)
@@ -990,7 +988,7 @@ static struct dma_async_tx_descriptor *tegra_dma_prep_slave_sg(
 struct dma_async_tx_descriptor *tegra_dma_prep_dma_cyclic(
 	struct dma_chan *dc, dma_addr_t buf_addr, size_t buf_len,
 	size_t period_len, enum dma_transfer_direction direction,
-	void *context)
+	unsigned long flags, void *context)
 {
 	struct tegra_dma_channel *tdc = to_tegra_dma_chan(dc);
 	struct tegra_dma_desc *dma_desc = NULL;
@@ -1173,14 +1171,14 @@ static void tegra_dma_free_chan_resources(struct dma_chan *dc)
 }
 
 /* Tegra20 specific DMA controller information */
-static struct tegra_dma_chip_data tegra20_dma_chip_data = {
+static const struct tegra_dma_chip_data tegra20_dma_chip_data = {
 	.nr_channels		= 16,
 	.max_dma_count		= 1024UL * 64,
 };
 
 #if defined(CONFIG_OF)
 /* Tegra30 specific DMA controller information */
-static struct tegra_dma_chip_data tegra30_dma_chip_data = {
+static const struct tegra_dma_chip_data tegra30_dma_chip_data = {
 	.nr_channels		= 32,
 	.max_dma_count		= 1024UL * 64,
 };
@@ -1204,7 +1202,7 @@ static int __devinit tegra_dma_probe(struct platform_device *pdev)
 	struct tegra_dma *tdma;
 	int ret;
 	int i;
-	struct tegra_dma_chip_data *cdata = NULL;
+	const struct tegra_dma_chip_data *cdata = NULL;
 
 	if (pdev->dev.of_node) {
 		const struct of_device_id *match;
diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c
index d5dc9da..59a9f8a 100644
--- a/drivers/edac/edac_mc.c
+++ b/drivers/edac/edac_mc.c
@@ -433,13 +433,6 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num,
 
 	mci->op_state = OP_ALLOC;
 
-	/* at this point, the root kobj is valid, and in order to
-	 * 'free' the object, then the function:
-	 *      edac_mc_unregister_sysfs_main_kobj() must be called
-	 * which will perform kobj unregistration and the actual free
-	 * will occur during the kobject callback operation
-	 */
-
 	return mci;
 
 error:
@@ -559,7 +552,7 @@ static void edac_mc_workq_setup(struct mem_ctl_info *mci, unsigned msec)
 		return;
 
 	INIT_DELAYED_WORK(&mci->work, edac_mc_workq_function);
-	queue_delayed_work(edac_workqueue, &mci->work, msecs_to_jiffies(msec));
+	mod_delayed_work(edac_workqueue, &mci->work, msecs_to_jiffies(msec));
 }
 
 /*
@@ -599,21 +592,6 @@ void edac_mc_reset_delay_period(int value)
 
 	mutex_lock(&mem_ctls_mutex);
 
-	/* scan the list and turn off all workq timers, doing so under lock
-	 */
-	list_for_each(item, &mc_devices) {
-		mci = list_entry(item, struct mem_ctl_info, link);
-
-		if (mci->op_state == OP_RUNNING_POLL)
-			cancel_delayed_work(&mci->work);
-	}
-
-	mutex_unlock(&mem_ctls_mutex);
-
-
-	/* re-walk the list, and reset the poll delay */
-	mutex_lock(&mem_ctls_mutex);
-
 	list_for_each(item, &mc_devices) {
 		mci = list_entry(item, struct mem_ctl_info, link);
 
diff --git a/drivers/edac/i3200_edac.c b/drivers/edac/i3200_edac.c
index 47180a0..b6653a6 100644
--- a/drivers/edac/i3200_edac.c
+++ b/drivers/edac/i3200_edac.c
@@ -391,7 +391,7 @@ static int i3200_probe1(struct pci_dev *pdev, int dev_idx)
 		for (j = 0; j < nr_channels; j++) {
 			struct dimm_info *dimm = csrow->channels[j]->dimm;
 
-			dimm->nr_pages = nr_pages / nr_channels;
+			dimm->nr_pages = nr_pages;
 			dimm->grain = nr_pages << PAGE_SHIFT;
 			dimm->mtype = MEM_DDR2;
 			dimm->dtype = DEV_UNKNOWN;
diff --git a/drivers/edac/i5000_edac.c b/drivers/edac/i5000_edac.c
index 39c6375..6a49dd0 100644
--- a/drivers/edac/i5000_edac.c
+++ b/drivers/edac/i5000_edac.c
@@ -1012,6 +1012,10 @@ static void handle_channel(struct i5000_pvt *pvt, int slot, int channel,
 			/* add the number of COLUMN bits */
 			addrBits += MTR_DIMM_COLS_ADDR_BITS(mtr);
 
+			/* Dual-rank memories have twice the size */
+			if (dinfo->dual_rank)
+				addrBits++;
+
 			addrBits += 6;	/* add 64 bits per DIMM */
 			addrBits -= 20;	/* divide by 2^^20 */
 			addrBits -= 3;	/* 8 bits per bytes */
diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c
index a1e791e..4fe66fa 100644
--- a/drivers/edac/mpc85xx_edac.c
+++ b/drivers/edac/mpc85xx_edac.c
@@ -212,7 +212,7 @@ static irqreturn_t mpc85xx_pci_isr(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
-static int __devinit mpc85xx_pci_err_probe(struct platform_device *op)
+int __devinit mpc85xx_pci_err_probe(struct platform_device *op)
 {
 	struct edac_pci_ctl_info *pci;
 	struct mpc85xx_pci_pdata *pdata;
@@ -226,6 +226,16 @@ static int __devinit mpc85xx_pci_err_probe(struct platform_device *op)
 	if (!pci)
 		return -ENOMEM;
 
+	/* make sure error reporting method is sane */
+	switch (edac_op_state) {
+	case EDAC_OPSTATE_POLL:
+	case EDAC_OPSTATE_INT:
+		break;
+	default:
+		edac_op_state = EDAC_OPSTATE_INT;
+		break;
+	}
+
 	pdata = pci->pvt_info;
 	pdata->name = "mpc85xx_pci_err";
 	pdata->irq = NO_IRQ;
@@ -315,6 +325,7 @@ err:
 	devres_release_group(&op->dev, mpc85xx_pci_err_probe);
 	return res;
 }
+EXPORT_SYMBOL(mpc85xx_pci_err_probe);
 
 static int mpc85xx_pci_err_remove(struct platform_device *op)
 {
@@ -338,27 +349,6 @@ static int mpc85xx_pci_err_remove(struct platform_device *op)
 	return 0;
 }
 
-static struct of_device_id mpc85xx_pci_err_of_match[] = {
-	{
-	 .compatible = "fsl,mpc8540-pcix",
-	 },
-	{
-	 .compatible = "fsl,mpc8540-pci",
-	},
-	{},
-};
-MODULE_DEVICE_TABLE(of, mpc85xx_pci_err_of_match);
-
-static struct platform_driver mpc85xx_pci_err_driver = {
-	.probe = mpc85xx_pci_err_probe,
-	.remove = __devexit_p(mpc85xx_pci_err_remove),
-	.driver = {
-		.name = "mpc85xx_pci_err",
-		.owner = THIS_MODULE,
-		.of_match_table = mpc85xx_pci_err_of_match,
-	},
-};
-
 #endif				/* CONFIG_PCI */
 
 /**************************** L2 Err device ***************************/
@@ -1210,12 +1200,6 @@ static int __init mpc85xx_mc_init(void)
 	if (res)
 		printk(KERN_WARNING EDAC_MOD_STR "L2 fails to register\n");
 
-#ifdef CONFIG_PCI
-	res = platform_driver_register(&mpc85xx_pci_err_driver);
-	if (res)
-		printk(KERN_WARNING EDAC_MOD_STR "PCI fails to register\n");
-#endif
-
 #ifdef CONFIG_FSL_SOC_BOOKE
 	pvr = mfspr(SPRN_PVR);
 
@@ -1252,9 +1236,6 @@ static void __exit mpc85xx_mc_exit(void)
 		on_each_cpu(mpc85xx_mc_restore_hid1, NULL, 0);
 	}
 #endif
-#ifdef CONFIG_PCI
-	platform_driver_unregister(&mpc85xx_pci_err_driver);
-#endif
 	platform_driver_unregister(&mpc85xx_l2_err_driver);
 	platform_driver_unregister(&mpc85xx_mc_err_driver);
 }
diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c
index f3b1f9f..5715b7c 100644
--- a/drivers/edac/sb_edac.c
+++ b/drivers/edac/sb_edac.c
@@ -513,7 +513,8 @@ static int get_dimm_config(struct mem_ctl_info *mci)
 {
 	struct sbridge_pvt *pvt = mci->pvt_info;
 	struct dimm_info *dimm;
-	int i, j, banks, ranks, rows, cols, size, npages;
+	unsigned i, j, banks, ranks, rows, cols, npages;
+	u64 size;
 	u32 reg;
 	enum edac_type mode;
 	enum mem_type mtype;
@@ -585,10 +586,10 @@ static int get_dimm_config(struct mem_ctl_info *mci)
 				cols = numcol(mtr);
 
 				/* DDR3 has 8 I/O banks */
-				size = (rows * cols * banks * ranks) >> (20 - 3);
+				size = ((u64)rows * cols * banks * ranks) >> (20 - 3);
 				npages = MiB_TO_PAGES(size);
 
-				edac_dbg(0, "mc#%d: channel %d, dimm %d, %d Mb (%d pages) bank: %d, rank: %d, row: %#x, col: %#x\n",
+				edac_dbg(0, "mc#%d: channel %d, dimm %d, %Ld Mb (%d pages) bank: %d, rank: %d, row: %#x, col: %#x\n",
 					 pvt->sbridge_dev->mc, i, j,
 					 size, npages,
 					 banks, ranks, rows, cols);
diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig
index e175c8e..07122a9 100644
--- a/drivers/extcon/Kconfig
+++ b/drivers/extcon/Kconfig
@@ -21,6 +21,12 @@ config EXTCON_GPIO
 	  Say Y here to enable GPIO based extcon support. Note that GPIO
 	  extcon supports single state per extcon instance.
 
+config EXTCON_ADC_JACK
+	tristate "ADC Jack extcon support"
+	depends on IIO
+	help
+	  Say Y here to enable extcon device driver based on ADC values.
+
 config EXTCON_MAX77693
 	tristate "MAX77693 EXTCON Support"
 	depends on MFD_MAX77693
@@ -41,7 +47,7 @@ config EXTCON_MAX8997
 
 config EXTCON_ARIZONA
 	tristate "Wolfson Arizona EXTCON support"
-	depends on MFD_ARIZONA
+	depends on MFD_ARIZONA && INPUT
 	help
 	  Say Y here to enable support for external accessory detection
 	  with Wolfson Arizona devices. These are audio CODECs with
diff --git a/drivers/extcon/Makefile b/drivers/extcon/Makefile
index 88961b3..f98a3c4 100644
--- a/drivers/extcon/Makefile
+++ b/drivers/extcon/Makefile
@@ -2,8 +2,9 @@
 # Makefile for external connector class (extcon) devices
 #
 
-obj-$(CONFIG_EXTCON)		+= extcon_class.o
-obj-$(CONFIG_EXTCON_GPIO)	+= extcon_gpio.o
+obj-$(CONFIG_EXTCON)		+= extcon-class.o
+obj-$(CONFIG_EXTCON_GPIO)	+= extcon-gpio.o
+obj-$(CONFIG_EXTCON_ADC_JACK)	+= extcon-adc-jack.o
 obj-$(CONFIG_EXTCON_MAX77693)	+= extcon-max77693.o
 obj-$(CONFIG_EXTCON_MAX8997)	+= extcon-max8997.o
 obj-$(CONFIG_EXTCON_ARIZONA)	+= extcon-arizona.o
diff --git a/drivers/extcon/extcon-adc-jack.c b/drivers/extcon/extcon-adc-jack.c
new file mode 100644
index 0000000..725eb5a
--- /dev/null
+++ b/drivers/extcon/extcon-adc-jack.c
@@ -0,0 +1,198 @@
+/*
+ * drivers/extcon/extcon-adc-jack.c
+ *
+ * Analog Jack extcon driver with ADC-based detection capability.
+ *
+ * Copyright (C) 2012 Samsung Electronics
+ * MyungJoo Ham <myungjoo.ham@samsung.com>
+ *
+ * Modified for calling to IIO to get adc by <anish.singh@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+#include <linux/iio/consumer.h>
+#include <linux/extcon/extcon-adc-jack.h>
+#include <linux/extcon.h>
+
+/**
+ * struct adc_jack_data - internal data for adc_jack device driver
+ * @edev        - extcon device.
+ * @cable_names - list of supported cables.
+ * @num_cables  - size of cable_names.
+ * @adc_conditions       - list of adc value conditions.
+ * @num_conditions       - size of adc_conditions.
+ * @irq         - irq number of attach/detach event (0 if not exist).
+ * @handling_delay      - interrupt handler will schedule extcon event
+ *                      handling at handling_delay jiffies.
+ * @handler     - extcon event handler called by interrupt handler.
+ * @chan       - iio channel being queried.
+ */
+struct adc_jack_data {
+	struct extcon_dev edev;
+
+	const char **cable_names;
+	int num_cables;
+	struct adc_jack_cond *adc_conditions;
+	int num_conditions;
+
+	int irq;
+	unsigned long handling_delay; /* in jiffies */
+	struct delayed_work handler;
+
+	struct iio_channel *chan;
+};
+
+static void adc_jack_handler(struct work_struct *work)
+{
+	struct adc_jack_data *data = container_of(to_delayed_work(work),
+			struct adc_jack_data,
+			handler);
+	u32 state = 0;
+	int ret, adc_val;
+	int i;
+
+	ret = iio_read_channel_raw(data->chan, &adc_val);
+	if (ret < 0) {
+		dev_err(data->edev.dev, "read channel() error: %d\n", ret);
+		return;
+	}
+
+	/* Get state from adc value with adc_conditions */
+	for (i = 0; i < data->num_conditions; i++) {
+		struct adc_jack_cond *def = &data->adc_conditions[i];
+		if (!def->state)
+			break;
+		if (def->min_adc <= adc_val && def->max_adc >= adc_val) {
+			state = def->state;
+			break;
+		}
+	}
+	/* if no def has met, it means state = 0 (no cables attached) */
+
+	extcon_set_state(&data->edev, state);
+}
+
+static irqreturn_t adc_jack_irq_thread(int irq, void *_data)
+{
+	struct adc_jack_data *data = _data;
+
+	schedule_delayed_work(&data->handler, data->handling_delay);
+	return IRQ_HANDLED;
+}
+
+static int __devinit adc_jack_probe(struct platform_device *pdev)
+{
+	struct adc_jack_data *data;
+	struct adc_jack_pdata *pdata = pdev->dev.platform_data;
+	int i, err = 0;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->edev.name = pdata->name;
+
+	if (!pdata->cable_names) {
+		err = -EINVAL;
+		dev_err(&pdev->dev, "error: cable_names not defined.\n");
+		goto out;
+	}
+
+	data->edev.supported_cable = pdata->cable_names;
+
+	/* Check the length of array and set num_cables */
+	for (i = 0; data->edev.supported_cable[i]; i++)
+		;
+	if (i == 0 || i > SUPPORTED_CABLE_MAX) {
+		err = -EINVAL;
+		dev_err(&pdev->dev, "error: pdata->cable_names size = %d\n",
+				i - 1);
+		goto out;
+	}
+	data->num_cables = i;
+
+	if (!pdata->adc_conditions ||
+			!pdata->adc_conditions[0].state) {
+		err = -EINVAL;
+		dev_err(&pdev->dev, "error: adc_conditions not defined.\n");
+		goto out;
+	}
+	data->adc_conditions = pdata->adc_conditions;
+
+	/* Check the length of array and set num_conditions */
+	for (i = 0; data->adc_conditions[i].state; i++)
+		;
+	data->num_conditions = i;
+
+	data->chan = iio_channel_get(dev_name(&pdev->dev),
+			pdata->consumer_channel);
+	if (IS_ERR(data->chan)) {
+		err = PTR_ERR(data->chan);
+		goto out;
+	}
+
+	data->handling_delay = msecs_to_jiffies(pdata->handling_delay_ms);
+
+	INIT_DEFERRABLE_WORK(&data->handler, adc_jack_handler);
+
+	platform_set_drvdata(pdev, data);
+
+	err = extcon_dev_register(&data->edev, &pdev->dev);
+	if (err)
+		goto out;
+
+	data->irq = platform_get_irq(pdev, 0);
+	if (!data->irq) {
+		dev_err(&pdev->dev, "platform_get_irq failed\n");
+		err = -ENODEV;
+		goto err_irq;
+	}
+
+	err = request_any_context_irq(data->irq, adc_jack_irq_thread,
+			pdata->irq_flags, pdata->name, data);
+
+	if (err) {
+		dev_err(&pdev->dev, "error: irq %d\n", data->irq);
+		err = -EINVAL;
+		goto err_irq;
+	}
+
+	goto out;
+
+err_irq:
+	extcon_dev_unregister(&data->edev);
+out:
+	return err;
+}
+
+static int __devexit adc_jack_remove(struct platform_device *pdev)
+{
+	struct adc_jack_data *data = platform_get_drvdata(pdev);
+
+	free_irq(data->irq, data);
+	cancel_work_sync(&data->handler.work);
+	extcon_dev_unregister(&data->edev);
+
+	return 0;
+}
+
+static struct platform_driver adc_jack_driver = {
+	.probe          = adc_jack_probe,
+	.remove         = __devexit_p(adc_jack_remove),
+	.driver         = {
+		.name   = "adc-jack",
+		.owner  = THIS_MODULE,
+	},
+};
+
+module_platform_driver(adc_jack_driver);
diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c
index 427a289..cdab9e5 100644
--- a/drivers/extcon/extcon-arizona.c
+++ b/drivers/extcon/extcon-arizona.c
@@ -21,6 +21,7 @@
 #include <linux/interrupt.h>
 #include <linux/err.h>
 #include <linux/gpio.h>
+#include <linux/input.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/regulator/consumer.h>
@@ -30,11 +31,14 @@
 #include <linux/mfd/arizona/pdata.h>
 #include <linux/mfd/arizona/registers.h>
 
+#define ARIZONA_NUM_BUTTONS 6
+
 struct arizona_extcon_info {
 	struct device *dev;
 	struct arizona *arizona;
 	struct mutex lock;
 	struct regulator *micvdd;
+	struct input_dev *input;
 
 	int micd_mode;
 	const struct arizona_micd_config *micd_modes;
@@ -54,6 +58,18 @@ static const struct arizona_micd_config micd_default_modes[] = {
 	{ 0,                  2 << ARIZONA_MICD_BIAS_SRC_SHIFT, 1 },
 };
 
+static struct {
+	u16 status;
+	int report;
+} arizona_lvl_to_key[ARIZONA_NUM_BUTTONS] = {
+	{  0x1, BTN_0 },
+	{  0x2, BTN_1 },
+	{  0x4, BTN_2 },
+	{  0x8, BTN_3 },
+	{ 0x10, BTN_4 },
+	{ 0x20, BTN_5 },
+};
+
 #define ARIZONA_CABLE_MECHANICAL 0
 #define ARIZONA_CABLE_MICROPHONE 1
 #define ARIZONA_CABLE_HEADPHONE  2
@@ -133,6 +149,7 @@ static void arizona_stop_mic(struct arizona_extcon_info *info)
 
 	if (change) {
 		regulator_disable(info->micvdd);
+		pm_runtime_mark_last_busy(info->dev);
 		pm_runtime_put_autosuspend(info->dev);
 	}
 }
@@ -141,8 +158,8 @@ static irqreturn_t arizona_micdet(int irq, void *data)
 {
 	struct arizona_extcon_info *info = data;
 	struct arizona *arizona = info->arizona;
-	unsigned int val;
-	int ret;
+	unsigned int val, lvl;
+	int ret, i;
 
 	mutex_lock(&info->lock);
 
@@ -219,13 +236,22 @@ static irqreturn_t arizona_micdet(int irq, void *data)
 
 	/*
 	 * If we're still detecting and we detect a short then we've
-	 * got a headphone.  Otherwise it's a button press, the
-	 * button reporting is stubbed out for now.
+	 * got a headphone.  Otherwise it's a button press.
 	 */
 	if (val & 0x3fc) {
 		if (info->mic) {
 			dev_dbg(arizona->dev, "Mic button detected\n");
 
+			lvl = val & ARIZONA_MICD_LVL_MASK;
+			lvl >>= ARIZONA_MICD_LVL_SHIFT;
+
+			for (i = 0; i < ARIZONA_NUM_BUTTONS; i++)
+				if (lvl & arizona_lvl_to_key[i].status)
+					input_report_key(info->input,
+							 arizona_lvl_to_key[i].report,
+							 1);
+			input_sync(info->input);
+
 		} else if (info->detecting) {
 			dev_dbg(arizona->dev, "Headphone detected\n");
 			info->detecting = false;
@@ -244,6 +270,10 @@ static irqreturn_t arizona_micdet(int irq, void *data)
 		}
 	} else {
 		dev_dbg(arizona->dev, "Mic button released\n");
+		for (i = 0; i < ARIZONA_NUM_BUTTONS; i++)
+			input_report_key(info->input,
+					 arizona_lvl_to_key[i].report, 0);
+		input_sync(info->input);
 	}
 
 handled:
@@ -258,7 +288,7 @@ static irqreturn_t arizona_jackdet(int irq, void *data)
 	struct arizona_extcon_info *info = data;
 	struct arizona *arizona = info->arizona;
 	unsigned int val;
-	int ret;
+	int ret, i;
 
 	pm_runtime_get_sync(info->dev);
 
@@ -288,6 +318,11 @@ static irqreturn_t arizona_jackdet(int irq, void *data)
 
 		arizona_stop_mic(info);
 
+		for (i = 0; i < ARIZONA_NUM_BUTTONS; i++)
+			input_report_key(info->input,
+					 arizona_lvl_to_key[i].report, 0);
+		input_sync(info->input);
+
 		ret = extcon_update_state(&info->edev, 0xffffffff, 0);
 		if (ret != 0)
 			dev_err(arizona->dev, "Removal report failed: %d\n",
@@ -307,13 +342,13 @@ static int __devinit arizona_extcon_probe(struct platform_device *pdev)
 	struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
 	struct arizona_pdata *pdata;
 	struct arizona_extcon_info *info;
-	int ret, mode;
+	int ret, mode, i;
 
 	pdata = dev_get_platdata(arizona->dev);
 
 	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
 	if (!info) {
-		dev_err(&pdev->dev, "failed to allocate memory\n");
+		dev_err(&pdev->dev, "Failed to allocate memory\n");
 		ret = -ENOMEM;
 		goto err;
 	}
@@ -350,7 +385,7 @@ static int __devinit arizona_extcon_probe(struct platform_device *pdev)
 
 	ret = extcon_dev_register(&info->edev, arizona->dev);
 	if (ret < 0) {
-		dev_err(arizona->dev, "extcon_dev_regster() failed: %d\n",
+		dev_err(arizona->dev, "extcon_dev_register() failed: %d\n",
 			ret);
 		goto err;
 	}
@@ -382,6 +417,20 @@ static int __devinit arizona_extcon_probe(struct platform_device *pdev)
 
 	arizona_extcon_set_mode(info, 0);
 
+	info->input = input_allocate_device();
+	if (!info->input) {
+		dev_err(arizona->dev, "Can't allocate input dev\n");
+		ret = -ENOMEM;
+		goto err_register;
+	}
+
+	for (i = 0; i < ARIZONA_NUM_BUTTONS; i++)
+		input_set_capability(info->input, EV_KEY,
+				     arizona_lvl_to_key[i].report);
+	info->input->name = "Headset";
+	info->input->phys = "arizona/extcon";
+	info->input->dev.parent = &pdev->dev;
+
 	pm_runtime_enable(&pdev->dev);
 	pm_runtime_idle(&pdev->dev);
 	pm_runtime_get_sync(&pdev->dev);
@@ -391,7 +440,7 @@ static int __devinit arizona_extcon_probe(struct platform_device *pdev)
 	if (ret != 0) {
 		dev_err(&pdev->dev, "Failed to get JACKDET rise IRQ: %d\n",
 			ret);
-		goto err_register;
+		goto err_input;
 	}
 
 	ret = arizona_set_irq_wake(arizona, ARIZONA_IRQ_JD_RISE, 1);
@@ -434,10 +483,23 @@ static int __devinit arizona_extcon_probe(struct platform_device *pdev)
 	regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE,
 			   ARIZONA_JD1_ENA, ARIZONA_JD1_ENA);
 
+	ret = regulator_allow_bypass(info->micvdd, true);
+	if (ret != 0)
+		dev_warn(arizona->dev, "Failed to set MICVDD to bypass: %d\n",
+			 ret);
+
 	pm_runtime_put(&pdev->dev);
 
+	ret = input_register_device(info->input);
+	if (ret) {
+		dev_err(&pdev->dev, "Can't register input device: %d\n", ret);
+		goto err_micdet;
+	}
+
 	return 0;
 
+err_micdet:
+	arizona_free_irq(arizona, ARIZONA_IRQ_MICDET, info);
 err_fall_wake:
 	arizona_set_irq_wake(arizona, ARIZONA_IRQ_JD_FALL, 0);
 err_fall:
@@ -446,6 +508,8 @@ err_rise_wake:
 	arizona_set_irq_wake(arizona, ARIZONA_IRQ_JD_RISE, 0);
 err_rise:
 	arizona_free_irq(arizona, ARIZONA_IRQ_JD_RISE, info);
+err_input:
+	input_free_device(info->input);
 err_register:
 	pm_runtime_disable(&pdev->dev);
 	extcon_dev_unregister(&info->edev);
@@ -468,6 +532,7 @@ static int __devexit arizona_extcon_remove(struct platform_device *pdev)
 	regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE,
 			   ARIZONA_JD1_ENA, 0);
 	arizona_clk32k_disable(arizona);
+	input_unregister_device(info->input);
 	extcon_dev_unregister(&info->edev);
 
 	return 0;
diff --git a/drivers/extcon/extcon-class.c b/drivers/extcon/extcon-class.c
new file mode 100644
index 0000000..946a318
--- /dev/null
+++ b/drivers/extcon/extcon-class.c
@@ -0,0 +1,836 @@
+/*
+ *  drivers/extcon/extcon_class.c
+ *
+ *  External connector (extcon) class driver
+ *
+ * Copyright (C) 2012 Samsung Electronics
+ * Author: Donggeun Kim <dg77.kim@samsung.com>
+ * Author: MyungJoo Ham <myungjoo.ham@samsung.com>
+ *
+ * based on android/drivers/switch/switch_class.c
+ * Copyright (C) 2008 Google, Inc.
+ * Author: Mike Lockwood <lockwood@android.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+*/
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/fs.h>
+#include <linux/err.h>
+#include <linux/extcon.h>
+#include <linux/slab.h>
+#include <linux/sysfs.h>
+
+/*
+ * extcon_cable_name suggests the standard cable names for commonly used
+ * cable types.
+ *
+ * However, please do not use extcon_cable_name directly for extcon_dev
+ * struct's supported_cable pointer unless your device really supports
+ * every single port-type of the following cable names. Please choose cable
+ * names that are actually used in your extcon device.
+ */
+const char *extcon_cable_name[] = {
+	[EXTCON_USB]		= "USB",
+	[EXTCON_USB_HOST]	= "USB-Host",
+	[EXTCON_TA]		= "TA",
+	[EXTCON_FAST_CHARGER]	= "Fast-charger",
+	[EXTCON_SLOW_CHARGER]	= "Slow-charger",
+	[EXTCON_CHARGE_DOWNSTREAM]	= "Charge-downstream",
+	[EXTCON_HDMI]		= "HDMI",
+	[EXTCON_MHL]		= "MHL",
+	[EXTCON_DVI]		= "DVI",
+	[EXTCON_VGA]		= "VGA",
+	[EXTCON_DOCK]		= "Dock",
+	[EXTCON_LINE_IN]	= "Line-in",
+	[EXTCON_LINE_OUT]	= "Line-out",
+	[EXTCON_MIC_IN]		= "Microphone",
+	[EXTCON_HEADPHONE_OUT]	= "Headphone",
+	[EXTCON_SPDIF_IN]	= "SPDIF-in",
+	[EXTCON_SPDIF_OUT]	= "SPDIF-out",
+	[EXTCON_VIDEO_IN]	= "Video-in",
+	[EXTCON_VIDEO_OUT]	= "Video-out",
+	[EXTCON_MECHANICAL]	= "Mechanical",
+
+	NULL,
+};
+
+static struct class *extcon_class;
+#if defined(CONFIG_ANDROID)
+static struct class_compat *switch_class;
+#endif /* CONFIG_ANDROID */
+
+static LIST_HEAD(extcon_dev_list);
+static DEFINE_MUTEX(extcon_dev_list_lock);
+
+/**
+ * check_mutually_exclusive - Check if new_state violates mutually_exclusive
+ *			    condition.
+ * @edev:	the extcon device
+ * @new_state:	new cable attach status for @edev
+ *
+ * Returns 0 if nothing violates. Returns the index + 1 for the first
+ * violated condition.
+ */
+static int check_mutually_exclusive(struct extcon_dev *edev, u32 new_state)
+{
+	int i = 0;
+
+	if (!edev->mutually_exclusive)
+		return 0;
+
+	for (i = 0; edev->mutually_exclusive[i]; i++) {
+		int count = 0, j;
+		u32 correspondants = new_state & edev->mutually_exclusive[i];
+		u32 exp = 1;
+
+		for (j = 0; j < 32; j++) {
+			if (exp & correspondants)
+				count++;
+			if (count > 1)
+				return i + 1;
+			exp <<= 1;
+		}
+	}
+
+	return 0;
+}
+
+static ssize_t state_show(struct device *dev, struct device_attribute *attr,
+			  char *buf)
+{
+	int i, count = 0;
+	struct extcon_dev *edev = (struct extcon_dev *) dev_get_drvdata(dev);
+
+	if (edev->print_state) {
+		int ret = edev->print_state(edev, buf);
+
+		if (ret >= 0)
+			return ret;
+		/* Use default if failed */
+	}
+
+	if (edev->max_supported == 0)
+		return sprintf(buf, "%u\n", edev->state);
+
+	for (i = 0; i < SUPPORTED_CABLE_MAX; i++) {
+		if (!edev->supported_cable[i])
+			break;
+		count += sprintf(buf + count, "%s=%d\n",
+				 edev->supported_cable[i],
+				 !!(edev->state & (1 << i)));
+	}
+
+	return count;
+}
+
+int extcon_set_state(struct extcon_dev *edev, u32 state);
+static ssize_t state_store(struct device *dev, struct device_attribute *attr,
+			   const char *buf, size_t count)
+{
+	u32 state;
+	ssize_t ret = 0;
+	struct extcon_dev *edev = (struct extcon_dev *) dev_get_drvdata(dev);
+
+	ret = sscanf(buf, "0x%x", &state);
+	if (ret == 0)
+		ret = -EINVAL;
+	else
+		ret = extcon_set_state(edev, state);
+
+	if (ret < 0)
+		return ret;
+
+	return count;
+}
+
+static ssize_t name_show(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	struct extcon_dev *edev = (struct extcon_dev *) dev_get_drvdata(dev);
+
+	/* Optional callback given by the user */
+	if (edev->print_name) {
+		int ret = edev->print_name(edev, buf);
+		if (ret >= 0)
+			return ret;
+	}
+
+	return sprintf(buf, "%s\n", dev_name(edev->dev));
+}
+
+static ssize_t cable_name_show(struct device *dev,
+			       struct device_attribute *attr, char *buf)
+{
+	struct extcon_cable *cable = container_of(attr, struct extcon_cable,
+						  attr_name);
+
+	return sprintf(buf, "%s\n",
+		       cable->edev->supported_cable[cable->cable_index]);
+}
+
+static ssize_t cable_state_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct extcon_cable *cable = container_of(attr, struct extcon_cable,
+						  attr_state);
+
+	return sprintf(buf, "%d\n",
+		       extcon_get_cable_state_(cable->edev,
+					       cable->cable_index));
+}
+
+static ssize_t cable_state_store(struct device *dev,
+				 struct device_attribute *attr, const char *buf,
+				 size_t count)
+{
+	struct extcon_cable *cable = container_of(attr, struct extcon_cable,
+						  attr_state);
+	int ret, state;
+
+	ret = sscanf(buf, "%d", &state);
+	if (ret == 0)
+		ret = -EINVAL;
+	else
+		ret = extcon_set_cable_state_(cable->edev, cable->cable_index,
+					      state);
+
+	if (ret < 0)
+		return ret;
+	return count;
+}
+
+/**
+ * extcon_update_state() - Update the cable attach states of the extcon device
+ *			only for the masked bits.
+ * @edev:	the extcon device
+ * @mask:	the bit mask to designate updated bits.
+ * @state:	new cable attach status for @edev
+ *
+ * Changing the state sends uevent with environment variable containing
+ * the name of extcon device (envp[0]) and the state output (envp[1]).
+ * Tizen uses this format for extcon device to get events from ports.
+ * Android uses this format as well.
+ *
+ * Note that the notifier provides which bits are changed in the state
+ * variable with the val parameter (second) to the callback.
+ */
+int extcon_update_state(struct extcon_dev *edev, u32 mask, u32 state)
+{
+	char name_buf[120];
+	char state_buf[120];
+	char *prop_buf;
+	char *envp[3];
+	int env_offset = 0;
+	int length;
+	unsigned long flags;
+
+	spin_lock_irqsave(&edev->lock, flags);
+
+	if (edev->state != ((edev->state & ~mask) | (state & mask))) {
+		u32 old_state = edev->state;
+
+		if (check_mutually_exclusive(edev, (edev->state & ~mask) |
+						   (state & mask))) {
+			spin_unlock_irqrestore(&edev->lock, flags);
+			return -EPERM;
+		}
+
+		edev->state &= ~mask;
+		edev->state |= state & mask;
+
+		raw_notifier_call_chain(&edev->nh, old_state, edev);
+
+		/* This could be in interrupt handler */
+		prop_buf = (char *)get_zeroed_page(GFP_ATOMIC);
+		if (prop_buf) {
+			length = name_show(edev->dev, NULL, prop_buf);
+			if (length > 0) {
+				if (prop_buf[length - 1] == '\n')
+					prop_buf[length - 1] = 0;
+				snprintf(name_buf, sizeof(name_buf),
+					"NAME=%s", prop_buf);
+				envp[env_offset++] = name_buf;
+			}
+			length = state_show(edev->dev, NULL, prop_buf);
+			if (length > 0) {
+				if (prop_buf[length - 1] == '\n')
+					prop_buf[length - 1] = 0;
+				snprintf(state_buf, sizeof(state_buf),
+					"STATE=%s", prop_buf);
+				envp[env_offset++] = state_buf;
+			}
+			envp[env_offset] = NULL;
+			/* Unlock early before uevent */
+			spin_unlock_irqrestore(&edev->lock, flags);
+
+			kobject_uevent_env(&edev->dev->kobj, KOBJ_CHANGE, envp);
+			free_page((unsigned long)prop_buf);
+		} else {
+			/* Unlock early before uevent */
+			spin_unlock_irqrestore(&edev->lock, flags);
+
+			dev_err(edev->dev, "out of memory in extcon_set_state\n");
+			kobject_uevent(&edev->dev->kobj, KOBJ_CHANGE);
+		}
+	} else {
+		/* No changes */
+		spin_unlock_irqrestore(&edev->lock, flags);
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(extcon_update_state);
+
+/**
+ * extcon_set_state() - Set the cable attach states of the extcon device.
+ * @edev:	the extcon device
+ * @state:	new cable attach status for @edev
+ *
+ * Note that notifier provides which bits are changed in the state
+ * variable with the val parameter (second) to the callback.
+ */
+int extcon_set_state(struct extcon_dev *edev, u32 state)
+{
+	return extcon_update_state(edev, 0xffffffff, state);
+}
+EXPORT_SYMBOL_GPL(extcon_set_state);
+
+/**
+ * extcon_find_cable_index() - Get the cable index based on the cable name.
+ * @edev:	the extcon device that has the cable.
+ * @cable_name:	cable name to be searched.
+ *
+ * Note that accessing a cable state based on cable_index is faster than
+ * cable_name because using cable_name induces a loop with strncmp().
+ * Thus, when get/set_cable_state is repeatedly used, using cable_index
+ * is recommended.
+ */
+int extcon_find_cable_index(struct extcon_dev *edev, const char *cable_name)
+{
+	int i;
+
+	if (edev->supported_cable) {
+		for (i = 0; edev->supported_cable[i]; i++) {
+			if (!strncmp(edev->supported_cable[i],
+				cable_name, CABLE_NAME_MAX))
+				return i;
+		}
+	}
+
+	return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(extcon_find_cable_index);
+
+/**
+ * extcon_get_cable_state_() - Get the status of a specific cable.
+ * @edev:	the extcon device that has the cable.
+ * @index:	cable index that can be retrieved by extcon_find_cable_index().
+ */
+int extcon_get_cable_state_(struct extcon_dev *edev, int index)
+{
+	if (index < 0 || (edev->max_supported && edev->max_supported <= index))
+		return -EINVAL;
+
+	return !!(edev->state & (1 << index));
+}
+EXPORT_SYMBOL_GPL(extcon_get_cable_state_);
+
+/**
+ * extcon_get_cable_state() - Get the status of a specific cable.
+ * @edev:	the extcon device that has the cable.
+ * @cable_name:	cable name.
+ *
+ * Note that this is slower than extcon_get_cable_state_.
+ */
+int extcon_get_cable_state(struct extcon_dev *edev, const char *cable_name)
+{
+	return extcon_get_cable_state_(edev, extcon_find_cable_index
+						(edev, cable_name));
+}
+EXPORT_SYMBOL_GPL(extcon_get_cable_state);
+
+/**
+ * extcon_get_cable_state_() - Set the status of a specific cable.
+ * @edev:	the extcon device that has the cable.
+ * @index:	cable index that can be retrieved by extcon_find_cable_index().
+ * @cable_state:	the new cable status. The default semantics is
+ *			true: attached / false: detached.
+ */
+int extcon_set_cable_state_(struct extcon_dev *edev,
+			int index, bool cable_state)
+{
+	u32 state;
+
+	if (index < 0 || (edev->max_supported && edev->max_supported <= index))
+		return -EINVAL;
+
+	state = cable_state ? (1 << index) : 0;
+	return extcon_update_state(edev, 1 << index, state);
+}
+EXPORT_SYMBOL_GPL(extcon_set_cable_state_);
+
+/**
+ * extcon_get_cable_state() - Set the status of a specific cable.
+ * @edev:	the extcon device that has the cable.
+ * @cable_name:	cable name.
+ * @cable_state:	the new cable status. The default semantics is
+ *			true: attached / false: detached.
+ *
+ * Note that this is slower than extcon_set_cable_state_.
+ */
+int extcon_set_cable_state(struct extcon_dev *edev,
+			const char *cable_name, bool cable_state)
+{
+	return extcon_set_cable_state_(edev, extcon_find_cable_index
+					(edev, cable_name), cable_state);
+}
+EXPORT_SYMBOL_GPL(extcon_set_cable_state);
+
+/**
+ * extcon_get_extcon_dev() - Get the extcon device instance from the name
+ * @extcon_name:	The extcon name provided with extcon_dev_register()
+ */
+struct extcon_dev *extcon_get_extcon_dev(const char *extcon_name)
+{
+	struct extcon_dev *sd;
+
+	mutex_lock(&extcon_dev_list_lock);
+	list_for_each_entry(sd, &extcon_dev_list, entry) {
+		if (!strcmp(sd->name, extcon_name))
+			goto out;
+	}
+	sd = NULL;
+out:
+	mutex_unlock(&extcon_dev_list_lock);
+	return sd;
+}
+EXPORT_SYMBOL_GPL(extcon_get_extcon_dev);
+
+static int _call_per_cable(struct notifier_block *nb, unsigned long val,
+			   void *ptr)
+{
+	struct extcon_specific_cable_nb *obj = container_of(nb,
+			struct extcon_specific_cable_nb, internal_nb);
+	struct extcon_dev *edev = ptr;
+
+	if ((val & (1 << obj->cable_index)) !=
+	    (edev->state & (1 << obj->cable_index))) {
+		bool cable_state = true;
+
+		obj->previous_value = val;
+
+		if (val & (1 << obj->cable_index))
+			cable_state = false;
+
+		return obj->user_nb->notifier_call(obj->user_nb,
+				cable_state, ptr);
+	}
+
+	return NOTIFY_OK;
+}
+
+/**
+ * extcon_register_interest() - Register a notifier for a state change of a
+ *			      specific cable, not an entier set of cables of a
+ *			      extcon device.
+ * @obj:	an empty extcon_specific_cable_nb object to be returned.
+ * @extcon_name:	the name of extcon device.
+ * @cable_name:		the target cable name.
+ * @nb:		the notifier block to get notified.
+ *
+ * Provide an empty extcon_specific_cable_nb. extcon_register_interest() sets
+ * the struct for you.
+ *
+ * extcon_register_interest is a helper function for those who want to get
+ * notification for a single specific cable's status change. If a user wants
+ * to get notification for any changes of all cables of a extcon device,
+ * he/she should use the general extcon_register_notifier().
+ *
+ * Note that the second parameter given to the callback of nb (val) is
+ * "old_state", not the current state. The current state can be retrieved
+ * by looking at the third pameter (edev pointer)'s state value.
+ */
+int extcon_register_interest(struct extcon_specific_cable_nb *obj,
+			     const char *extcon_name, const char *cable_name,
+			     struct notifier_block *nb)
+{
+	if (!obj || !extcon_name || !cable_name || !nb)
+		return -EINVAL;
+
+	obj->edev = extcon_get_extcon_dev(extcon_name);
+	if (!obj->edev)
+		return -ENODEV;
+
+	obj->cable_index = extcon_find_cable_index(obj->edev, cable_name);
+	if (obj->cable_index < 0)
+		return -ENODEV;
+
+	obj->user_nb = nb;
+
+	obj->internal_nb.notifier_call = _call_per_cable;
+
+	return raw_notifier_chain_register(&obj->edev->nh, &obj->internal_nb);
+}
+
+/**
+ * extcon_unregister_interest() - Unregister the notifier registered by
+ *				extcon_register_interest().
+ * @obj:	the extcon_specific_cable_nb object returned by
+ *		extcon_register_interest().
+ */
+int extcon_unregister_interest(struct extcon_specific_cable_nb *obj)
+{
+	if (!obj)
+		return -EINVAL;
+
+	return raw_notifier_chain_unregister(&obj->edev->nh, &obj->internal_nb);
+}
+
+/**
+ * extcon_register_notifier() - Register a notifiee to get notified by
+ *			      any attach status changes from the extcon.
+ * @edev:	the extcon device.
+ * @nb:		a notifier block to be registered.
+ *
+ * Note that the second parameter given to the callback of nb (val) is
+ * "old_state", not the current state. The current state can be retrieved
+ * by looking at the third pameter (edev pointer)'s state value.
+ */
+int extcon_register_notifier(struct extcon_dev *edev,
+			struct notifier_block *nb)
+{
+	return raw_notifier_chain_register(&edev->nh, nb);
+}
+EXPORT_SYMBOL_GPL(extcon_register_notifier);
+
+/**
+ * extcon_unregister_notifier() - Unregister a notifiee from the extcon device.
+ * @edev:	the extcon device.
+ * @nb:		a registered notifier block to be unregistered.
+ */
+int extcon_unregister_notifier(struct extcon_dev *edev,
+			struct notifier_block *nb)
+{
+	return raw_notifier_chain_unregister(&edev->nh, nb);
+}
+EXPORT_SYMBOL_GPL(extcon_unregister_notifier);
+
+static struct device_attribute extcon_attrs[] = {
+	__ATTR(state, S_IRUGO | S_IWUSR, state_show, state_store),
+	__ATTR_RO(name),
+	__ATTR_NULL,
+};
+
+static int create_extcon_class(void)
+{
+	if (!extcon_class) {
+		extcon_class = class_create(THIS_MODULE, "extcon");
+		if (IS_ERR(extcon_class))
+			return PTR_ERR(extcon_class);
+		extcon_class->dev_attrs = extcon_attrs;
+
+#if defined(CONFIG_ANDROID)
+		switch_class = class_compat_register("switch");
+		if (WARN(!switch_class, "cannot allocate"))
+			return -ENOMEM;
+#endif /* CONFIG_ANDROID */
+	}
+
+	return 0;
+}
+
+static void extcon_cleanup(struct extcon_dev *edev, bool skip)
+{
+	mutex_lock(&extcon_dev_list_lock);
+	list_del(&edev->entry);
+	mutex_unlock(&extcon_dev_list_lock);
+
+	if (!skip && get_device(edev->dev)) {
+		int index;
+
+		if (edev->mutually_exclusive && edev->max_supported) {
+			for (index = 0; edev->mutually_exclusive[index];
+			     index++)
+				kfree(edev->d_attrs_muex[index].attr.name);
+			kfree(edev->d_attrs_muex);
+			kfree(edev->attrs_muex);
+		}
+
+		for (index = 0; index < edev->max_supported; index++)
+			kfree(edev->cables[index].attr_g.name);
+
+		if (edev->max_supported) {
+			kfree(edev->extcon_dev_type.groups);
+			kfree(edev->cables);
+		}
+
+		device_unregister(edev->dev);
+		put_device(edev->dev);
+	}
+
+	kfree(edev->dev);
+}
+
+static void extcon_dev_release(struct device *dev)
+{
+	struct extcon_dev *edev = (struct extcon_dev *) dev_get_drvdata(dev);
+
+	extcon_cleanup(edev, true);
+}
+
+static const char *muex_name = "mutually_exclusive";
+static void dummy_sysfs_dev_release(struct device *dev)
+{
+}
+
+/**
+ * extcon_dev_register() - Register a new extcon device
+ * @edev	: the new extcon device (should be allocated before calling)
+ * @dev		: the parent device for this extcon device.
+ *
+ * Among the members of edev struct, please set the "user initializing data"
+ * in any case and set the "optional callbacks" if required. However, please
+ * do not set the values of "internal data", which are initialized by
+ * this function.
+ */
+int extcon_dev_register(struct extcon_dev *edev, struct device *dev)
+{
+	int ret, index = 0;
+
+	if (!extcon_class) {
+		ret = create_extcon_class();
+		if (ret < 0)
+			return ret;
+	}
+
+	if (edev->supported_cable) {
+		/* Get size of array */
+		for (index = 0; edev->supported_cable[index]; index++)
+			;
+		edev->max_supported = index;
+	} else {
+		edev->max_supported = 0;
+	}
+
+	if (index > SUPPORTED_CABLE_MAX) {
+		dev_err(edev->dev, "extcon: maximum number of supported cables exceeded.\n");
+		return -EINVAL;
+	}
+
+	edev->dev = kzalloc(sizeof(struct device), GFP_KERNEL);
+	if (!edev->dev)
+		return -ENOMEM;
+	edev->dev->parent = dev;
+	edev->dev->class = extcon_class;
+	edev->dev->release = extcon_dev_release;
+
+	dev_set_name(edev->dev, edev->name ? edev->name : dev_name(dev));
+
+	if (edev->max_supported) {
+		char buf[10];
+		char *str;
+		struct extcon_cable *cable;
+
+		edev->cables = kzalloc(sizeof(struct extcon_cable) *
+				       edev->max_supported, GFP_KERNEL);
+		if (!edev->cables) {
+			ret = -ENOMEM;
+			goto err_sysfs_alloc;
+		}
+		for (index = 0; index < edev->max_supported; index++) {
+			cable = &edev->cables[index];
+
+			snprintf(buf, 10, "cable.%d", index);
+			str = kzalloc(sizeof(char) * (strlen(buf) + 1),
+				      GFP_KERNEL);
+			if (!str) {
+				for (index--; index >= 0; index--) {
+					cable = &edev->cables[index];
+					kfree(cable->attr_g.name);
+				}
+				ret = -ENOMEM;
+
+				goto err_alloc_cables;
+			}
+			strcpy(str, buf);
+
+			cable->edev = edev;
+			cable->cable_index = index;
+			cable->attrs[0] = &cable->attr_name.attr;
+			cable->attrs[1] = &cable->attr_state.attr;
+			cable->attrs[2] = NULL;
+			cable->attr_g.name = str;
+			cable->attr_g.attrs = cable->attrs;
+
+			sysfs_attr_init(&cable->attr_name.attr);
+			cable->attr_name.attr.name = "name";
+			cable->attr_name.attr.mode = 0444;
+			cable->attr_name.show = cable_name_show;
+
+			sysfs_attr_init(&cable->attr_state.attr);
+			cable->attr_state.attr.name = "state";
+			cable->attr_state.attr.mode = 0644;
+			cable->attr_state.show = cable_state_show;
+			cable->attr_state.store = cable_state_store;
+		}
+	}
+
+	if (edev->max_supported && edev->mutually_exclusive) {
+		char buf[80];
+		char *name;
+
+		/* Count the size of mutually_exclusive array */
+		for (index = 0; edev->mutually_exclusive[index]; index++)
+			;
+
+		edev->attrs_muex = kzalloc(sizeof(struct attribute *) *
+					   (index + 1), GFP_KERNEL);
+		if (!edev->attrs_muex) {
+			ret = -ENOMEM;
+			goto err_muex;
+		}
+
+		edev->d_attrs_muex = kzalloc(sizeof(struct device_attribute) *
+					     index, GFP_KERNEL);
+		if (!edev->d_attrs_muex) {
+			ret = -ENOMEM;
+			kfree(edev->attrs_muex);
+			goto err_muex;
+		}
+
+		for (index = 0; edev->mutually_exclusive[index]; index++) {
+			sprintf(buf, "0x%x", edev->mutually_exclusive[index]);
+			name = kzalloc(sizeof(char) * (strlen(buf) + 1),
+				       GFP_KERNEL);
+			if (!name) {
+				for (index--; index >= 0; index--) {
+					kfree(edev->d_attrs_muex[index].attr.
+					      name);
+				}
+				kfree(edev->d_attrs_muex);
+				kfree(edev->attrs_muex);
+				ret = -ENOMEM;
+				goto err_muex;
+			}
+			strcpy(name, buf);
+			sysfs_attr_init(&edev->d_attrs_muex[index].attr);
+			edev->d_attrs_muex[index].attr.name = name;
+			edev->d_attrs_muex[index].attr.mode = 0000;
+			edev->attrs_muex[index] = &edev->d_attrs_muex[index]
+							.attr;
+		}
+		edev->attr_g_muex.name = muex_name;
+		edev->attr_g_muex.attrs = edev->attrs_muex;
+
+	}
+
+	if (edev->max_supported) {
+		edev->extcon_dev_type.groups =
+			kzalloc(sizeof(struct attribute_group *) *
+				(edev->max_supported + 2), GFP_KERNEL);
+		if (!edev->extcon_dev_type.groups) {
+			ret = -ENOMEM;
+			goto err_alloc_groups;
+		}
+
+		edev->extcon_dev_type.name = dev_name(edev->dev);
+		edev->extcon_dev_type.release = dummy_sysfs_dev_release;
+
+		for (index = 0; index < edev->max_supported; index++)
+			edev->extcon_dev_type.groups[index] =
+				&edev->cables[index].attr_g;
+		if (edev->mutually_exclusive)
+			edev->extcon_dev_type.groups[index] =
+				&edev->attr_g_muex;
+
+		edev->dev->type = &edev->extcon_dev_type;
+	}
+
+	ret = device_register(edev->dev);
+	if (ret) {
+		put_device(edev->dev);
+		goto err_dev;
+	}
+#if defined(CONFIG_ANDROID)
+	if (switch_class)
+		ret = class_compat_create_link(switch_class, edev->dev,
+					       NULL);
+#endif /* CONFIG_ANDROID */
+
+	spin_lock_init(&edev->lock);
+
+	RAW_INIT_NOTIFIER_HEAD(&edev->nh);
+
+	dev_set_drvdata(edev->dev, edev);
+	edev->state = 0;
+
+	mutex_lock(&extcon_dev_list_lock);
+	list_add(&edev->entry, &extcon_dev_list);
+	mutex_unlock(&extcon_dev_list_lock);
+
+	return 0;
+
+err_dev:
+	if (edev->max_supported)
+		kfree(edev->extcon_dev_type.groups);
+err_alloc_groups:
+	if (edev->max_supported && edev->mutually_exclusive) {
+		for (index = 0; edev->mutually_exclusive[index]; index++)
+			kfree(edev->d_attrs_muex[index].attr.name);
+		kfree(edev->d_attrs_muex);
+		kfree(edev->attrs_muex);
+	}
+err_muex:
+	for (index = 0; index < edev->max_supported; index++)
+		kfree(edev->cables[index].attr_g.name);
+err_alloc_cables:
+	if (edev->max_supported)
+		kfree(edev->cables);
+err_sysfs_alloc:
+	kfree(edev->dev);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(extcon_dev_register);
+
+/**
+ * extcon_dev_unregister() - Unregister the extcon device.
+ * @edev:	the extcon device instance to be unregistered.
+ *
+ * Note that this does not call kfree(edev) because edev was not allocated
+ * by this class.
+ */
+void extcon_dev_unregister(struct extcon_dev *edev)
+{
+	extcon_cleanup(edev, false);
+}
+EXPORT_SYMBOL_GPL(extcon_dev_unregister);
+
+static int __init extcon_class_init(void)
+{
+	return create_extcon_class();
+}
+module_init(extcon_class_init);
+
+static void __exit extcon_class_exit(void)
+{
+	class_destroy(extcon_class);
+}
+module_exit(extcon_class_exit);
+
+MODULE_AUTHOR("Mike Lockwood <lockwood@android.com>");
+MODULE_AUTHOR("Donggeun Kim <dg77.kim@samsung.com>");
+MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
+MODULE_DESCRIPTION("External connector (extcon) class driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/extcon/extcon-gpio.c b/drivers/extcon/extcon-gpio.c
new file mode 100644
index 0000000..3cc152e
--- /dev/null
+++ b/drivers/extcon/extcon-gpio.c
@@ -0,0 +1,165 @@
+/*
+ *  drivers/extcon/extcon_gpio.c
+ *
+ *  Single-state GPIO extcon driver based on extcon class
+ *
+ * Copyright (C) 2008 Google, Inc.
+ * Author: Mike Lockwood <lockwood@android.com>
+ *
+ * Modified by MyungJoo Ham <myungjoo.ham@samsung.com> to support extcon
+ * (originally switch class is supported)
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+*/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/extcon.h>
+#include <linux/workqueue.h>
+#include <linux/gpio.h>
+#include <linux/extcon.h>
+#include <linux/extcon/extcon_gpio.h>
+
+struct gpio_extcon_data {
+	struct extcon_dev edev;
+	unsigned gpio;
+	const char *state_on;
+	const char *state_off;
+	int irq;
+	struct delayed_work work;
+	unsigned long debounce_jiffies;
+};
+
+static void gpio_extcon_work(struct work_struct *work)
+{
+	int state;
+	struct gpio_extcon_data	*data =
+		container_of(to_delayed_work(work), struct gpio_extcon_data,
+			     work);
+
+	state = gpio_get_value(data->gpio);
+	extcon_set_state(&data->edev, state);
+}
+
+static irqreturn_t gpio_irq_handler(int irq, void *dev_id)
+{
+	struct gpio_extcon_data *extcon_data = dev_id;
+
+	schedule_delayed_work(&extcon_data->work,
+			      extcon_data->debounce_jiffies);
+	return IRQ_HANDLED;
+}
+
+static ssize_t extcon_gpio_print_state(struct extcon_dev *edev, char *buf)
+{
+	struct gpio_extcon_data	*extcon_data =
+		container_of(edev, struct gpio_extcon_data, edev);
+	const char *state;
+	if (extcon_get_state(edev))
+		state = extcon_data->state_on;
+	else
+		state = extcon_data->state_off;
+
+	if (state)
+		return sprintf(buf, "%s\n", state);
+	return -EINVAL;
+}
+
+static int __devinit gpio_extcon_probe(struct platform_device *pdev)
+{
+	struct gpio_extcon_platform_data *pdata = pdev->dev.platform_data;
+	struct gpio_extcon_data *extcon_data;
+	int ret = 0;
+
+	if (!pdata)
+		return -EBUSY;
+	if (!pdata->irq_flags) {
+		dev_err(&pdev->dev, "IRQ flag is not specified.\n");
+		return -EINVAL;
+	}
+
+	extcon_data = devm_kzalloc(&pdev->dev, sizeof(struct gpio_extcon_data),
+				   GFP_KERNEL);
+	if (!extcon_data)
+		return -ENOMEM;
+
+	extcon_data->edev.name = pdata->name;
+	extcon_data->gpio = pdata->gpio;
+	extcon_data->state_on = pdata->state_on;
+	extcon_data->state_off = pdata->state_off;
+	if (pdata->state_on && pdata->state_off)
+		extcon_data->edev.print_state = extcon_gpio_print_state;
+	extcon_data->debounce_jiffies = msecs_to_jiffies(pdata->debounce);
+
+	ret = extcon_dev_register(&extcon_data->edev, &pdev->dev);
+	if (ret < 0)
+		return ret;
+
+	ret = devm_gpio_request_one(&pdev->dev, extcon_data->gpio, GPIOF_DIR_IN,
+				    pdev->name);
+	if (ret < 0)
+		goto err;
+
+	INIT_DELAYED_WORK(&extcon_data->work, gpio_extcon_work);
+
+	extcon_data->irq = gpio_to_irq(extcon_data->gpio);
+	if (extcon_data->irq < 0) {
+		ret = extcon_data->irq;
+		goto err;
+	}
+
+	ret = request_any_context_irq(extcon_data->irq, gpio_irq_handler,
+				      pdata->irq_flags, pdev->name,
+				      extcon_data);
+	if (ret < 0)
+		goto err;
+
+	platform_set_drvdata(pdev, extcon_data);
+	/* Perform initial detection */
+	gpio_extcon_work(&extcon_data->work.work);
+
+	return 0;
+
+err:
+	extcon_dev_unregister(&extcon_data->edev);
+
+	return ret;
+}
+
+static int __devexit gpio_extcon_remove(struct platform_device *pdev)
+{
+	struct gpio_extcon_data *extcon_data = platform_get_drvdata(pdev);
+
+	cancel_delayed_work_sync(&extcon_data->work);
+	free_irq(extcon_data->irq, extcon_data);
+	extcon_dev_unregister(&extcon_data->edev);
+
+	return 0;
+}
+
+static struct platform_driver gpio_extcon_driver = {
+	.probe		= gpio_extcon_probe,
+	.remove		= __devexit_p(gpio_extcon_remove),
+	.driver		= {
+		.name	= "extcon-gpio",
+		.owner	= THIS_MODULE,
+	},
+};
+
+module_platform_driver(gpio_extcon_driver);
+
+MODULE_AUTHOR("Mike Lockwood <lockwood@android.com>");
+MODULE_DESCRIPTION("GPIO extcon driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/extcon/extcon-max77693.c b/drivers/extcon/extcon-max77693.c
index 38f9e52..e21387e 100644
--- a/drivers/extcon/extcon-max77693.c
+++ b/drivers/extcon/extcon-max77693.c
@@ -356,7 +356,7 @@ static int max77693_muic_adc_ground_handler(struct max77693_muic_info *info,
 		extcon_set_cable_state(info->edev, "MHL", attached);
 		break;
 	default:
-		dev_err(info->dev, "faild to detect %s accessory\n",
+		dev_err(info->dev, "failed to detect %s accessory\n",
 			attached ? "attached" : "detached");
 		dev_err(info->dev, "- adc:0x%x, adclow:0x%x, adc1k:0x%x\n",
 			adc, adclow, adc1k);
@@ -548,7 +548,7 @@ static void max77693_muic_irq_work(struct work_struct *work)
 		curr_adc = info->status[0] & STATUS1_ADC_MASK;
 		curr_adc >>= STATUS1_ADC_SHIFT;
 
-		/* Check accossory state which is either detached or attached */
+		/* Check accessory state which is either detached or attached */
 		if (curr_adc == MAX77693_MUIC_ADC_OPEN)
 			attached = false;
 
@@ -564,7 +564,7 @@ static void max77693_muic_irq_work(struct work_struct *work)
 		curr_chg_type = info->status[1] & STATUS2_CHGTYP_MASK;
 		curr_chg_type >>= STATUS2_CHGTYP_SHIFT;
 
-		/* Check charger accossory state which
+		/* Check charger accessory state which
 		   is either detached or attached */
 		if (curr_chg_type == MAX77693_CHARGER_TYPE_NONE)
 			attached = false;
@@ -699,7 +699,7 @@ static int __devinit max77693_muic_probe(struct platform_device *pdev)
 
 		ret = request_threaded_irq(virq, NULL,
 				max77693_muic_irq_handler,
-				0, muic_irq->name, info);
+				IRQF_ONESHOT, muic_irq->name, info);
 		if (ret) {
 			dev_err(&pdev->dev,
 				"failed: irq request (IRQ: %d,"
diff --git a/drivers/extcon/extcon_class.c b/drivers/extcon/extcon_class.c
deleted file mode 100644
index f6419f9..0000000
--- a/drivers/extcon/extcon_class.c
+++ /dev/null
@@ -1,832 +0,0 @@
-/*
- *  drivers/extcon/extcon_class.c
- *
- *  External connector (extcon) class driver
- *
- * Copyright (C) 2012 Samsung Electronics
- * Author: Donggeun Kim <dg77.kim@samsung.com>
- * Author: MyungJoo Ham <myungjoo.ham@samsung.com>
- *
- * based on android/drivers/switch/switch_class.c
- * Copyright (C) 2008 Google, Inc.
- * Author: Mike Lockwood <lockwood@android.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
-*/
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/device.h>
-#include <linux/fs.h>
-#include <linux/err.h>
-#include <linux/extcon.h>
-#include <linux/slab.h>
-
-/*
- * extcon_cable_name suggests the standard cable names for commonly used
- * cable types.
- *
- * However, please do not use extcon_cable_name directly for extcon_dev
- * struct's supported_cable pointer unless your device really supports
- * every single port-type of the following cable names. Please choose cable
- * names that are actually used in your extcon device.
- */
-const char *extcon_cable_name[] = {
-	[EXTCON_USB]		= "USB",
-	[EXTCON_USB_HOST]	= "USB-Host",
-	[EXTCON_TA]		= "TA",
-	[EXTCON_FAST_CHARGER]	= "Fast-charger",
-	[EXTCON_SLOW_CHARGER]	= "Slow-charger",
-	[EXTCON_CHARGE_DOWNSTREAM]	= "Charge-downstream",
-	[EXTCON_HDMI]		= "HDMI",
-	[EXTCON_MHL]		= "MHL",
-	[EXTCON_DVI]		= "DVI",
-	[EXTCON_VGA]		= "VGA",
-	[EXTCON_DOCK]		= "Dock",
-	[EXTCON_LINE_IN]	= "Line-in",
-	[EXTCON_LINE_OUT]	= "Line-out",
-	[EXTCON_MIC_IN]		= "Microphone",
-	[EXTCON_HEADPHONE_OUT]	= "Headphone",
-	[EXTCON_SPDIF_IN]	= "SPDIF-in",
-	[EXTCON_SPDIF_OUT]	= "SPDIF-out",
-	[EXTCON_VIDEO_IN]	= "Video-in",
-	[EXTCON_VIDEO_OUT]	= "Video-out",
-	[EXTCON_MECHANICAL]	= "Mechanical",
-
-	NULL,
-};
-
-static struct class *extcon_class;
-#if defined(CONFIG_ANDROID)
-static struct class_compat *switch_class;
-#endif /* CONFIG_ANDROID */
-
-static LIST_HEAD(extcon_dev_list);
-static DEFINE_MUTEX(extcon_dev_list_lock);
-
-/**
- * check_mutually_exclusive - Check if new_state violates mutually_exclusive
- *			    condition.
- * @edev:	the extcon device
- * @new_state:	new cable attach status for @edev
- *
- * Returns 0 if nothing violates. Returns the index + 1 for the first
- * violated condition.
- */
-static int check_mutually_exclusive(struct extcon_dev *edev, u32 new_state)
-{
-	int i = 0;
-
-	if (!edev->mutually_exclusive)
-		return 0;
-
-	for (i = 0; edev->mutually_exclusive[i]; i++) {
-		int count = 0, j;
-		u32 correspondants = new_state & edev->mutually_exclusive[i];
-		u32 exp = 1;
-
-		for (j = 0; j < 32; j++) {
-			if (exp & correspondants)
-				count++;
-			if (count > 1)
-				return i + 1;
-			exp <<= 1;
-		}
-	}
-
-	return 0;
-}
-
-static ssize_t state_show(struct device *dev, struct device_attribute *attr,
-			  char *buf)
-{
-	int i, count = 0;
-	struct extcon_dev *edev = (struct extcon_dev *) dev_get_drvdata(dev);
-
-	if (edev->print_state) {
-		int ret = edev->print_state(edev, buf);
-
-		if (ret >= 0)
-			return ret;
-		/* Use default if failed */
-	}
-
-	if (edev->max_supported == 0)
-		return sprintf(buf, "%u\n", edev->state);
-
-	for (i = 0; i < SUPPORTED_CABLE_MAX; i++) {
-		if (!edev->supported_cable[i])
-			break;
-		count += sprintf(buf + count, "%s=%d\n",
-				 edev->supported_cable[i],
-				 !!(edev->state & (1 << i)));
-	}
-
-	return count;
-}
-
-int extcon_set_state(struct extcon_dev *edev, u32 state);
-static ssize_t state_store(struct device *dev, struct device_attribute *attr,
-			   const char *buf, size_t count)
-{
-	u32 state;
-	ssize_t ret = 0;
-	struct extcon_dev *edev = (struct extcon_dev *) dev_get_drvdata(dev);
-
-	ret = sscanf(buf, "0x%x", &state);
-	if (ret == 0)
-		ret = -EINVAL;
-	else
-		ret = extcon_set_state(edev, state);
-
-	if (ret < 0)
-		return ret;
-
-	return count;
-}
-
-static ssize_t name_show(struct device *dev, struct device_attribute *attr,
-		char *buf)
-{
-	struct extcon_dev *edev = (struct extcon_dev *) dev_get_drvdata(dev);
-
-	/* Optional callback given by the user */
-	if (edev->print_name) {
-		int ret = edev->print_name(edev, buf);
-		if (ret >= 0)
-			return ret;
-	}
-
-	return sprintf(buf, "%s\n", dev_name(edev->dev));
-}
-
-static ssize_t cable_name_show(struct device *dev,
-			       struct device_attribute *attr, char *buf)
-{
-	struct extcon_cable *cable = container_of(attr, struct extcon_cable,
-						  attr_name);
-
-	return sprintf(buf, "%s\n",
-		       cable->edev->supported_cable[cable->cable_index]);
-}
-
-static ssize_t cable_state_show(struct device *dev,
-				struct device_attribute *attr, char *buf)
-{
-	struct extcon_cable *cable = container_of(attr, struct extcon_cable,
-						  attr_state);
-
-	return sprintf(buf, "%d\n",
-		       extcon_get_cable_state_(cable->edev,
-					       cable->cable_index));
-}
-
-static ssize_t cable_state_store(struct device *dev,
-				 struct device_attribute *attr, const char *buf,
-				 size_t count)
-{
-	struct extcon_cable *cable = container_of(attr, struct extcon_cable,
-						  attr_state);
-	int ret, state;
-
-	ret = sscanf(buf, "%d", &state);
-	if (ret == 0)
-		ret = -EINVAL;
-	else
-		ret = extcon_set_cable_state_(cable->edev, cable->cable_index,
-					      state);
-
-	if (ret < 0)
-		return ret;
-	return count;
-}
-
-/**
- * extcon_update_state() - Update the cable attach states of the extcon device
- *			only for the masked bits.
- * @edev:	the extcon device
- * @mask:	the bit mask to designate updated bits.
- * @state:	new cable attach status for @edev
- *
- * Changing the state sends uevent with environment variable containing
- * the name of extcon device (envp[0]) and the state output (envp[1]).
- * Tizen uses this format for extcon device to get events from ports.
- * Android uses this format as well.
- *
- * Note that the notifier provides which bits are changed in the state
- * variable with the val parameter (second) to the callback.
- */
-int extcon_update_state(struct extcon_dev *edev, u32 mask, u32 state)
-{
-	char name_buf[120];
-	char state_buf[120];
-	char *prop_buf;
-	char *envp[3];
-	int env_offset = 0;
-	int length;
-	unsigned long flags;
-
-	spin_lock_irqsave(&edev->lock, flags);
-
-	if (edev->state != ((edev->state & ~mask) | (state & mask))) {
-		u32 old_state = edev->state;
-
-		if (check_mutually_exclusive(edev, (edev->state & ~mask) |
-						   (state & mask))) {
-			spin_unlock_irqrestore(&edev->lock, flags);
-			return -EPERM;
-		}
-
-		edev->state &= ~mask;
-		edev->state |= state & mask;
-
-		raw_notifier_call_chain(&edev->nh, old_state, edev);
-
-		/* This could be in interrupt handler */
-		prop_buf = (char *)get_zeroed_page(GFP_ATOMIC);
-		if (prop_buf) {
-			length = name_show(edev->dev, NULL, prop_buf);
-			if (length > 0) {
-				if (prop_buf[length - 1] == '\n')
-					prop_buf[length - 1] = 0;
-				snprintf(name_buf, sizeof(name_buf),
-					"NAME=%s", prop_buf);
-				envp[env_offset++] = name_buf;
-			}
-			length = state_show(edev->dev, NULL, prop_buf);
-			if (length > 0) {
-				if (prop_buf[length - 1] == '\n')
-					prop_buf[length - 1] = 0;
-				snprintf(state_buf, sizeof(state_buf),
-					"STATE=%s", prop_buf);
-				envp[env_offset++] = state_buf;
-			}
-			envp[env_offset] = NULL;
-			/* Unlock early before uevent */
-			spin_unlock_irqrestore(&edev->lock, flags);
-
-			kobject_uevent_env(&edev->dev->kobj, KOBJ_CHANGE, envp);
-			free_page((unsigned long)prop_buf);
-		} else {
-			/* Unlock early before uevent */
-			spin_unlock_irqrestore(&edev->lock, flags);
-
-			dev_err(edev->dev, "out of memory in extcon_set_state\n");
-			kobject_uevent(&edev->dev->kobj, KOBJ_CHANGE);
-		}
-	} else {
-		/* No changes */
-		spin_unlock_irqrestore(&edev->lock, flags);
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(extcon_update_state);
-
-/**
- * extcon_set_state() - Set the cable attach states of the extcon device.
- * @edev:	the extcon device
- * @state:	new cable attach status for @edev
- *
- * Note that notifier provides which bits are changed in the state
- * variable with the val parameter (second) to the callback.
- */
-int extcon_set_state(struct extcon_dev *edev, u32 state)
-{
-	return extcon_update_state(edev, 0xffffffff, state);
-}
-EXPORT_SYMBOL_GPL(extcon_set_state);
-
-/**
- * extcon_find_cable_index() - Get the cable index based on the cable name.
- * @edev:	the extcon device that has the cable.
- * @cable_name:	cable name to be searched.
- *
- * Note that accessing a cable state based on cable_index is faster than
- * cable_name because using cable_name induces a loop with strncmp().
- * Thus, when get/set_cable_state is repeatedly used, using cable_index
- * is recommended.
- */
-int extcon_find_cable_index(struct extcon_dev *edev, const char *cable_name)
-{
-	int i;
-
-	if (edev->supported_cable) {
-		for (i = 0; edev->supported_cable[i]; i++) {
-			if (!strncmp(edev->supported_cable[i],
-				cable_name, CABLE_NAME_MAX))
-				return i;
-		}
-	}
-
-	return -EINVAL;
-}
-EXPORT_SYMBOL_GPL(extcon_find_cable_index);
-
-/**
- * extcon_get_cable_state_() - Get the status of a specific cable.
- * @edev:	the extcon device that has the cable.
- * @index:	cable index that can be retrieved by extcon_find_cable_index().
- */
-int extcon_get_cable_state_(struct extcon_dev *edev, int index)
-{
-	if (index < 0 || (edev->max_supported && edev->max_supported <= index))
-		return -EINVAL;
-
-	return !!(edev->state & (1 << index));
-}
-EXPORT_SYMBOL_GPL(extcon_get_cable_state_);
-
-/**
- * extcon_get_cable_state() - Get the status of a specific cable.
- * @edev:	the extcon device that has the cable.
- * @cable_name:	cable name.
- *
- * Note that this is slower than extcon_get_cable_state_.
- */
-int extcon_get_cable_state(struct extcon_dev *edev, const char *cable_name)
-{
-	return extcon_get_cable_state_(edev, extcon_find_cable_index
-						(edev, cable_name));
-}
-EXPORT_SYMBOL_GPL(extcon_get_cable_state);
-
-/**
- * extcon_get_cable_state_() - Set the status of a specific cable.
- * @edev:	the extcon device that has the cable.
- * @index:	cable index that can be retrieved by extcon_find_cable_index().
- * @cable_state:	the new cable status. The default semantics is
- *			true: attached / false: detached.
- */
-int extcon_set_cable_state_(struct extcon_dev *edev,
-			int index, bool cable_state)
-{
-	u32 state;
-
-	if (index < 0 || (edev->max_supported && edev->max_supported <= index))
-		return -EINVAL;
-
-	state = cable_state ? (1 << index) : 0;
-	return extcon_update_state(edev, 1 << index, state);
-}
-EXPORT_SYMBOL_GPL(extcon_set_cable_state_);
-
-/**
- * extcon_get_cable_state() - Set the status of a specific cable.
- * @edev:	the extcon device that has the cable.
- * @cable_name:	cable name.
- * @cable_state:	the new cable status. The default semantics is
- *			true: attached / false: detached.
- *
- * Note that this is slower than extcon_set_cable_state_.
- */
-int extcon_set_cable_state(struct extcon_dev *edev,
-			const char *cable_name, bool cable_state)
-{
-	return extcon_set_cable_state_(edev, extcon_find_cable_index
-					(edev, cable_name), cable_state);
-}
-EXPORT_SYMBOL_GPL(extcon_set_cable_state);
-
-/**
- * extcon_get_extcon_dev() - Get the extcon device instance from the name
- * @extcon_name:	The extcon name provided with extcon_dev_register()
- */
-struct extcon_dev *extcon_get_extcon_dev(const char *extcon_name)
-{
-	struct extcon_dev *sd;
-
-	mutex_lock(&extcon_dev_list_lock);
-	list_for_each_entry(sd, &extcon_dev_list, entry) {
-		if (!strcmp(sd->name, extcon_name))
-			goto out;
-	}
-	sd = NULL;
-out:
-	mutex_unlock(&extcon_dev_list_lock);
-	return sd;
-}
-EXPORT_SYMBOL_GPL(extcon_get_extcon_dev);
-
-static int _call_per_cable(struct notifier_block *nb, unsigned long val,
-			   void *ptr)
-{
-	struct extcon_specific_cable_nb *obj = container_of(nb,
-			struct extcon_specific_cable_nb, internal_nb);
-	struct extcon_dev *edev = ptr;
-
-	if ((val & (1 << obj->cable_index)) !=
-	    (edev->state & (1 << obj->cable_index))) {
-		bool cable_state = true;
-
-		obj->previous_value = val;
-
-		if (val & (1 << obj->cable_index))
-			cable_state = false;
-
-		return obj->user_nb->notifier_call(obj->user_nb,
-				cable_state, ptr);
-	}
-
-	return NOTIFY_OK;
-}
-
-/**
- * extcon_register_interest() - Register a notifier for a state change of a
- *			      specific cable, not a entier set of cables of a
- *			      extcon device.
- * @obj:	an empty extcon_specific_cable_nb object to be returned.
- * @extcon_name:	the name of extcon device.
- * @cable_name:		the target cable name.
- * @nb:		the notifier block to get notified.
- *
- * Provide an empty extcon_specific_cable_nb. extcon_register_interest() sets
- * the struct for you.
- *
- * extcon_register_interest is a helper function for those who want to get
- * notification for a single specific cable's status change. If a user wants
- * to get notification for any changes of all cables of a extcon device,
- * he/she should use the general extcon_register_notifier().
- *
- * Note that the second parameter given to the callback of nb (val) is
- * "old_state", not the current state. The current state can be retrieved
- * by looking at the third pameter (edev pointer)'s state value.
- */
-int extcon_register_interest(struct extcon_specific_cable_nb *obj,
-			     const char *extcon_name, const char *cable_name,
-			     struct notifier_block *nb)
-{
-	if (!obj || !extcon_name || !cable_name || !nb)
-		return -EINVAL;
-
-	obj->edev = extcon_get_extcon_dev(extcon_name);
-	if (!obj->edev)
-		return -ENODEV;
-
-	obj->cable_index = extcon_find_cable_index(obj->edev, cable_name);
-	if (obj->cable_index < 0)
-		return -ENODEV;
-
-	obj->user_nb = nb;
-
-	obj->internal_nb.notifier_call = _call_per_cable;
-
-	return raw_notifier_chain_register(&obj->edev->nh, &obj->internal_nb);
-}
-
-/**
- * extcon_unregister_interest() - Unregister the notifier registered by
- *				extcon_register_interest().
- * @obj:	the extcon_specific_cable_nb object returned by
- *		extcon_register_interest().
- */
-int extcon_unregister_interest(struct extcon_specific_cable_nb *obj)
-{
-	if (!obj)
-		return -EINVAL;
-
-	return raw_notifier_chain_unregister(&obj->edev->nh, &obj->internal_nb);
-}
-
-/**
- * extcon_register_notifier() - Register a notifee to get notified by
- *			      any attach status changes from the extcon.
- * @edev:	the extcon device.
- * @nb:		a notifier block to be registered.
- *
- * Note that the second parameter given to the callback of nb (val) is
- * "old_state", not the current state. The current state can be retrieved
- * by looking at the third pameter (edev pointer)'s state value.
- */
-int extcon_register_notifier(struct extcon_dev *edev,
-			struct notifier_block *nb)
-{
-	return raw_notifier_chain_register(&edev->nh, nb);
-}
-EXPORT_SYMBOL_GPL(extcon_register_notifier);
-
-/**
- * extcon_unregister_notifier() - Unregister a notifee from the extcon device.
- * @edev:	the extcon device.
- * @nb:		a registered notifier block to be unregistered.
- */
-int extcon_unregister_notifier(struct extcon_dev *edev,
-			struct notifier_block *nb)
-{
-	return raw_notifier_chain_unregister(&edev->nh, nb);
-}
-EXPORT_SYMBOL_GPL(extcon_unregister_notifier);
-
-static struct device_attribute extcon_attrs[] = {
-	__ATTR(state, S_IRUGO | S_IWUSR, state_show, state_store),
-	__ATTR_RO(name),
-	__ATTR_NULL,
-};
-
-static int create_extcon_class(void)
-{
-	if (!extcon_class) {
-		extcon_class = class_create(THIS_MODULE, "extcon");
-		if (IS_ERR(extcon_class))
-			return PTR_ERR(extcon_class);
-		extcon_class->dev_attrs = extcon_attrs;
-
-#if defined(CONFIG_ANDROID)
-		switch_class = class_compat_register("switch");
-		if (WARN(!switch_class, "cannot allocate"))
-			return -ENOMEM;
-#endif /* CONFIG_ANDROID */
-	}
-
-	return 0;
-}
-
-static void extcon_cleanup(struct extcon_dev *edev, bool skip)
-{
-	mutex_lock(&extcon_dev_list_lock);
-	list_del(&edev->entry);
-	mutex_unlock(&extcon_dev_list_lock);
-
-	if (!skip && get_device(edev->dev)) {
-		int index;
-
-		if (edev->mutually_exclusive && edev->max_supported) {
-			for (index = 0; edev->mutually_exclusive[index];
-			     index++)
-				kfree(edev->d_attrs_muex[index].attr.name);
-			kfree(edev->d_attrs_muex);
-			kfree(edev->attrs_muex);
-		}
-
-		for (index = 0; index < edev->max_supported; index++)
-			kfree(edev->cables[index].attr_g.name);
-
-		if (edev->max_supported) {
-			kfree(edev->extcon_dev_type.groups);
-			kfree(edev->cables);
-		}
-
-		device_unregister(edev->dev);
-		put_device(edev->dev);
-	}
-
-	kfree(edev->dev);
-}
-
-static void extcon_dev_release(struct device *dev)
-{
-	struct extcon_dev *edev = (struct extcon_dev *) dev_get_drvdata(dev);
-
-	extcon_cleanup(edev, true);
-}
-
-static const char *muex_name = "mutually_exclusive";
-static void dummy_sysfs_dev_release(struct device *dev)
-{
-}
-
-/**
- * extcon_dev_register() - Register a new extcon device
- * @edev	: the new extcon device (should be allocated before calling)
- * @dev		: the parent device for this extcon device.
- *
- * Among the members of edev struct, please set the "user initializing data"
- * in any case and set the "optional callbacks" if required. However, please
- * do not set the values of "internal data", which are initialized by
- * this function.
- */
-int extcon_dev_register(struct extcon_dev *edev, struct device *dev)
-{
-	int ret, index = 0;
-
-	if (!extcon_class) {
-		ret = create_extcon_class();
-		if (ret < 0)
-			return ret;
-	}
-
-	if (edev->supported_cable) {
-		/* Get size of array */
-		for (index = 0; edev->supported_cable[index]; index++)
-			;
-		edev->max_supported = index;
-	} else {
-		edev->max_supported = 0;
-	}
-
-	if (index > SUPPORTED_CABLE_MAX) {
-		dev_err(edev->dev, "extcon: maximum number of supported cables exceeded.\n");
-		return -EINVAL;
-	}
-
-	edev->dev = kzalloc(sizeof(struct device), GFP_KERNEL);
-	if (!edev->dev)
-		return -ENOMEM;
-	edev->dev->parent = dev;
-	edev->dev->class = extcon_class;
-	edev->dev->release = extcon_dev_release;
-
-	dev_set_name(edev->dev, edev->name ? edev->name : dev_name(dev));
-
-	if (edev->max_supported) {
-		char buf[10];
-		char *str;
-		struct extcon_cable *cable;
-
-		edev->cables = kzalloc(sizeof(struct extcon_cable) *
-				       edev->max_supported, GFP_KERNEL);
-		if (!edev->cables) {
-			ret = -ENOMEM;
-			goto err_sysfs_alloc;
-		}
-		for (index = 0; index < edev->max_supported; index++) {
-			cable = &edev->cables[index];
-
-			snprintf(buf, 10, "cable.%d", index);
-			str = kzalloc(sizeof(char) * (strlen(buf) + 1),
-				      GFP_KERNEL);
-			if (!str) {
-				for (index--; index >= 0; index--) {
-					cable = &edev->cables[index];
-					kfree(cable->attr_g.name);
-				}
-				ret = -ENOMEM;
-
-				goto err_alloc_cables;
-			}
-			strcpy(str, buf);
-
-			cable->edev = edev;
-			cable->cable_index = index;
-			cable->attrs[0] = &cable->attr_name.attr;
-			cable->attrs[1] = &cable->attr_state.attr;
-			cable->attrs[2] = NULL;
-			cable->attr_g.name = str;
-			cable->attr_g.attrs = cable->attrs;
-
-			cable->attr_name.attr.name = "name";
-			cable->attr_name.attr.mode = 0444;
-			cable->attr_name.show = cable_name_show;
-
-			cable->attr_state.attr.name = "state";
-			cable->attr_state.attr.mode = 0644;
-			cable->attr_state.show = cable_state_show;
-			cable->attr_state.store = cable_state_store;
-		}
-	}
-
-	if (edev->max_supported && edev->mutually_exclusive) {
-		char buf[80];
-		char *name;
-
-		/* Count the size of mutually_exclusive array */
-		for (index = 0; edev->mutually_exclusive[index]; index++)
-			;
-
-		edev->attrs_muex = kzalloc(sizeof(struct attribute *) *
-					   (index + 1), GFP_KERNEL);
-		if (!edev->attrs_muex) {
-			ret = -ENOMEM;
-			goto err_muex;
-		}
-
-		edev->d_attrs_muex = kzalloc(sizeof(struct device_attribute) *
-					     index, GFP_KERNEL);
-		if (!edev->d_attrs_muex) {
-			ret = -ENOMEM;
-			kfree(edev->attrs_muex);
-			goto err_muex;
-		}
-
-		for (index = 0; edev->mutually_exclusive[index]; index++) {
-			sprintf(buf, "0x%x", edev->mutually_exclusive[index]);
-			name = kzalloc(sizeof(char) * (strlen(buf) + 1),
-				       GFP_KERNEL);
-			if (!name) {
-				for (index--; index >= 0; index--) {
-					kfree(edev->d_attrs_muex[index].attr.
-					      name);
-				}
-				kfree(edev->d_attrs_muex);
-				kfree(edev->attrs_muex);
-				ret = -ENOMEM;
-				goto err_muex;
-			}
-			strcpy(name, buf);
-			edev->d_attrs_muex[index].attr.name = name;
-			edev->d_attrs_muex[index].attr.mode = 0000;
-			edev->attrs_muex[index] = &edev->d_attrs_muex[index]
-							.attr;
-		}
-		edev->attr_g_muex.name = muex_name;
-		edev->attr_g_muex.attrs = edev->attrs_muex;
-
-	}
-
-	if (edev->max_supported) {
-		edev->extcon_dev_type.groups =
-			kzalloc(sizeof(struct attribute_group *) *
-				(edev->max_supported + 2), GFP_KERNEL);
-		if (!edev->extcon_dev_type.groups) {
-			ret = -ENOMEM;
-			goto err_alloc_groups;
-		}
-
-		edev->extcon_dev_type.name = dev_name(edev->dev);
-		edev->extcon_dev_type.release = dummy_sysfs_dev_release;
-
-		for (index = 0; index < edev->max_supported; index++)
-			edev->extcon_dev_type.groups[index] =
-				&edev->cables[index].attr_g;
-		if (edev->mutually_exclusive)
-			edev->extcon_dev_type.groups[index] =
-				&edev->attr_g_muex;
-
-		edev->dev->type = &edev->extcon_dev_type;
-	}
-
-	ret = device_register(edev->dev);
-	if (ret) {
-		put_device(edev->dev);
-		goto err_dev;
-	}
-#if defined(CONFIG_ANDROID)
-	if (switch_class)
-		ret = class_compat_create_link(switch_class, edev->dev,
-					       NULL);
-#endif /* CONFIG_ANDROID */
-
-	spin_lock_init(&edev->lock);
-
-	RAW_INIT_NOTIFIER_HEAD(&edev->nh);
-
-	dev_set_drvdata(edev->dev, edev);
-	edev->state = 0;
-
-	mutex_lock(&extcon_dev_list_lock);
-	list_add(&edev->entry, &extcon_dev_list);
-	mutex_unlock(&extcon_dev_list_lock);
-
-	return 0;
-
-err_dev:
-	if (edev->max_supported)
-		kfree(edev->extcon_dev_type.groups);
-err_alloc_groups:
-	if (edev->max_supported && edev->mutually_exclusive) {
-		for (index = 0; edev->mutually_exclusive[index]; index++)
-			kfree(edev->d_attrs_muex[index].attr.name);
-		kfree(edev->d_attrs_muex);
-		kfree(edev->attrs_muex);
-	}
-err_muex:
-	for (index = 0; index < edev->max_supported; index++)
-		kfree(edev->cables[index].attr_g.name);
-err_alloc_cables:
-	if (edev->max_supported)
-		kfree(edev->cables);
-err_sysfs_alloc:
-	kfree(edev->dev);
-	return ret;
-}
-EXPORT_SYMBOL_GPL(extcon_dev_register);
-
-/**
- * extcon_dev_unregister() - Unregister the extcon device.
- * @edev:	the extcon device instance to be unregitered.
- *
- * Note that this does not call kfree(edev) because edev was not allocated
- * by this class.
- */
-void extcon_dev_unregister(struct extcon_dev *edev)
-{
-	extcon_cleanup(edev, false);
-}
-EXPORT_SYMBOL_GPL(extcon_dev_unregister);
-
-static int __init extcon_class_init(void)
-{
-	return create_extcon_class();
-}
-module_init(extcon_class_init);
-
-static void __exit extcon_class_exit(void)
-{
-	class_destroy(extcon_class);
-}
-module_exit(extcon_class_exit);
-
-MODULE_AUTHOR("Mike Lockwood <lockwood@android.com>");
-MODULE_AUTHOR("Donggeun Kim <dg77.kim@samsung.com>");
-MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
-MODULE_DESCRIPTION("External connector (extcon) class driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/extcon/extcon_gpio.c b/drivers/extcon/extcon_gpio.c
deleted file mode 100644
index 3cc152e..0000000
--- a/drivers/extcon/extcon_gpio.c
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- *  drivers/extcon/extcon_gpio.c
- *
- *  Single-state GPIO extcon driver based on extcon class
- *
- * Copyright (C) 2008 Google, Inc.
- * Author: Mike Lockwood <lockwood@android.com>
- *
- * Modified by MyungJoo Ham <myungjoo.ham@samsung.com> to support extcon
- * (originally switch class is supported)
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
-*/
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/extcon.h>
-#include <linux/workqueue.h>
-#include <linux/gpio.h>
-#include <linux/extcon.h>
-#include <linux/extcon/extcon_gpio.h>
-
-struct gpio_extcon_data {
-	struct extcon_dev edev;
-	unsigned gpio;
-	const char *state_on;
-	const char *state_off;
-	int irq;
-	struct delayed_work work;
-	unsigned long debounce_jiffies;
-};
-
-static void gpio_extcon_work(struct work_struct *work)
-{
-	int state;
-	struct gpio_extcon_data	*data =
-		container_of(to_delayed_work(work), struct gpio_extcon_data,
-			     work);
-
-	state = gpio_get_value(data->gpio);
-	extcon_set_state(&data->edev, state);
-}
-
-static irqreturn_t gpio_irq_handler(int irq, void *dev_id)
-{
-	struct gpio_extcon_data *extcon_data = dev_id;
-
-	schedule_delayed_work(&extcon_data->work,
-			      extcon_data->debounce_jiffies);
-	return IRQ_HANDLED;
-}
-
-static ssize_t extcon_gpio_print_state(struct extcon_dev *edev, char *buf)
-{
-	struct gpio_extcon_data	*extcon_data =
-		container_of(edev, struct gpio_extcon_data, edev);
-	const char *state;
-	if (extcon_get_state(edev))
-		state = extcon_data->state_on;
-	else
-		state = extcon_data->state_off;
-
-	if (state)
-		return sprintf(buf, "%s\n", state);
-	return -EINVAL;
-}
-
-static int __devinit gpio_extcon_probe(struct platform_device *pdev)
-{
-	struct gpio_extcon_platform_data *pdata = pdev->dev.platform_data;
-	struct gpio_extcon_data *extcon_data;
-	int ret = 0;
-
-	if (!pdata)
-		return -EBUSY;
-	if (!pdata->irq_flags) {
-		dev_err(&pdev->dev, "IRQ flag is not specified.\n");
-		return -EINVAL;
-	}
-
-	extcon_data = devm_kzalloc(&pdev->dev, sizeof(struct gpio_extcon_data),
-				   GFP_KERNEL);
-	if (!extcon_data)
-		return -ENOMEM;
-
-	extcon_data->edev.name = pdata->name;
-	extcon_data->gpio = pdata->gpio;
-	extcon_data->state_on = pdata->state_on;
-	extcon_data->state_off = pdata->state_off;
-	if (pdata->state_on && pdata->state_off)
-		extcon_data->edev.print_state = extcon_gpio_print_state;
-	extcon_data->debounce_jiffies = msecs_to_jiffies(pdata->debounce);
-
-	ret = extcon_dev_register(&extcon_data->edev, &pdev->dev);
-	if (ret < 0)
-		return ret;
-
-	ret = devm_gpio_request_one(&pdev->dev, extcon_data->gpio, GPIOF_DIR_IN,
-				    pdev->name);
-	if (ret < 0)
-		goto err;
-
-	INIT_DELAYED_WORK(&extcon_data->work, gpio_extcon_work);
-
-	extcon_data->irq = gpio_to_irq(extcon_data->gpio);
-	if (extcon_data->irq < 0) {
-		ret = extcon_data->irq;
-		goto err;
-	}
-
-	ret = request_any_context_irq(extcon_data->irq, gpio_irq_handler,
-				      pdata->irq_flags, pdev->name,
-				      extcon_data);
-	if (ret < 0)
-		goto err;
-
-	platform_set_drvdata(pdev, extcon_data);
-	/* Perform initial detection */
-	gpio_extcon_work(&extcon_data->work.work);
-
-	return 0;
-
-err:
-	extcon_dev_unregister(&extcon_data->edev);
-
-	return ret;
-}
-
-static int __devexit gpio_extcon_remove(struct platform_device *pdev)
-{
-	struct gpio_extcon_data *extcon_data = platform_get_drvdata(pdev);
-
-	cancel_delayed_work_sync(&extcon_data->work);
-	free_irq(extcon_data->irq, extcon_data);
-	extcon_dev_unregister(&extcon_data->edev);
-
-	return 0;
-}
-
-static struct platform_driver gpio_extcon_driver = {
-	.probe		= gpio_extcon_probe,
-	.remove		= __devexit_p(gpio_extcon_remove),
-	.driver		= {
-		.name	= "extcon-gpio",
-		.owner	= THIS_MODULE,
-	},
-};
-
-module_platform_driver(gpio_extcon_driver);
-
-MODULE_AUTHOR("Mike Lockwood <lockwood@android.com>");
-MODULE_DESCRIPTION("GPIO extcon driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/firewire/core-device.c b/drivers/firewire/core-device.c
index 7a05fd2..3873d53 100644
--- a/drivers/firewire/core-device.c
+++ b/drivers/firewire/core-device.c
@@ -32,6 +32,7 @@
 #include <linux/mod_devicetable.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
+#include <linux/random.h>
 #include <linux/rwsem.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
@@ -1066,6 +1067,8 @@ static void fw_device_init(struct work_struct *work)
 		device->config_rom_retries = 0;
 
 		set_broadcast_channel(device, device->generation);
+
+		add_device_randomness(&device->config_rom[3], 8);
 	}
 
 	/*
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index c788dbd..834e71d 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -1777,11 +1777,35 @@ static int get_self_id_pos(struct fw_ohci *ohci, u32 self_id,
 	return i;
 }
 
+static int initiated_reset(struct fw_ohci *ohci)
+{
+	int reg;
+	int ret = 0;
+
+	mutex_lock(&ohci->phy_reg_mutex);
+	reg = write_phy_reg(ohci, 7, 0xe0); /* Select page 7 */
+	if (reg >= 0) {
+		reg = read_phy_reg(ohci, 8);
+		reg |= 0x40;
+		reg = write_phy_reg(ohci, 8, reg); /* set PMODE bit */
+		if (reg >= 0) {
+			reg = read_phy_reg(ohci, 12); /* read register 12 */
+			if (reg >= 0) {
+				if ((reg & 0x08) == 0x08) {
+					/* bit 3 indicates "initiated reset" */
+					ret = 0x2;
+				}
+			}
+		}
+	}
+	mutex_unlock(&ohci->phy_reg_mutex);
+	return ret;
+}
+
 /*
  * TI TSB82AA2B and TSB12LV26 do not receive the selfID of a locally
  * attached TSB41BA3D phy; see http://www.ti.com/litv/pdf/sllz059.
  * Construct the selfID from phy register contents.
- * FIXME:  How to determine the selfID.i flag?
  */
 static int find_and_insert_self_id(struct fw_ohci *ohci, int self_id_count)
 {
@@ -1814,6 +1838,8 @@ static int find_and_insert_self_id(struct fw_ohci *ohci, int self_id_count)
 		self_id |= ((status & 0x3) << (6 - (i * 2)));
 	}
 
+	self_id |= initiated_reset(ohci);
+
 	pos = get_self_id_pos(ohci, self_id, self_id_count);
 	if (pos >= 0) {
 		memmove(&(ohci->self_id_buffer[pos+1]),
diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c
index b298158..fd3ae62 100644
--- a/drivers/firmware/dmi_scan.c
+++ b/drivers/firmware/dmi_scan.c
@@ -16,6 +16,7 @@
  */
 static char dmi_empty_string[] = "        ";
 
+static u16 __initdata dmi_ver;
 /*
  * Catch too early calls to dmi_check_system():
  */
@@ -118,12 +119,12 @@ static int __init dmi_walk_early(void (*decode)(const struct dmi_header *,
 	return 0;
 }
 
-static int __init dmi_checksum(const u8 *buf)
+static int __init dmi_checksum(const u8 *buf, u8 len)
 {
 	u8 sum = 0;
 	int a;
 
-	for (a = 0; a < 15; a++)
+	for (a = 0; a < len; a++)
 		sum += buf[a];
 
 	return sum == 0;
@@ -161,8 +162,10 @@ static void __init dmi_save_uuid(const struct dmi_header *dm, int slot, int inde
 		return;
 
 	for (i = 0; i < 16 && (is_ff || is_00); i++) {
-		if(d[i] != 0x00) is_ff = 0;
-		if(d[i] != 0xFF) is_00 = 0;
+		if (d[i] != 0x00)
+			is_00 = 0;
+		if (d[i] != 0xFF)
+			is_ff = 0;
 	}
 
 	if (is_ff || is_00)
@@ -172,7 +175,15 @@ static void __init dmi_save_uuid(const struct dmi_header *dm, int slot, int inde
 	if (!s)
 		return;
 
-	sprintf(s, "%pUB", d);
+	/*
+	 * As of version 2.6 of the SMBIOS specification, the first 3 fields of
+	 * the UUID are supposed to be little-endian encoded.  The specification
+	 * says that this is the defacto standard.
+	 */
+	if (dmi_ver >= 0x0206)
+		sprintf(s, "%pUL", d);
+	else
+		sprintf(s, "%pUB", d);
 
         dmi_ident[slot] = s;
 }
@@ -404,29 +415,57 @@ static int __init dmi_present(const char __iomem *p)
 	u8 buf[15];
 
 	memcpy_fromio(buf, p, 15);
-	if ((memcmp(buf, "_DMI_", 5) == 0) && dmi_checksum(buf)) {
+	if (dmi_checksum(buf, 15)) {
 		dmi_num = (buf[13] << 8) | buf[12];
 		dmi_len = (buf[7] << 8) | buf[6];
 		dmi_base = (buf[11] << 24) | (buf[10] << 16) |
 			(buf[9] << 8) | buf[8];
 
-		/*
-		 * DMI version 0.0 means that the real version is taken from
-		 * the SMBIOS version, which we don't know at this point.
-		 */
-		if (buf[14] != 0)
-			printk(KERN_INFO "DMI %d.%d present.\n",
-			       buf[14] >> 4, buf[14] & 0xF);
-		else
-			printk(KERN_INFO "DMI present.\n");
 		if (dmi_walk_early(dmi_decode) == 0) {
+			if (dmi_ver)
+				pr_info("SMBIOS %d.%d present.\n",
+				       dmi_ver >> 8, dmi_ver & 0xFF);
+			else {
+				dmi_ver = (buf[14] & 0xF0) << 4 |
+					   (buf[14] & 0x0F);
+				pr_info("Legacy DMI %d.%d present.\n",
+				       dmi_ver >> 8, dmi_ver & 0xFF);
+			}
 			dmi_dump_ids();
 			return 0;
 		}
 	}
+	dmi_ver = 0;
 	return 1;
 }
 
+static int __init smbios_present(const char __iomem *p)
+{
+	u8 buf[32];
+	int offset = 0;
+
+	memcpy_fromio(buf, p, 32);
+	if ((buf[5] < 32) && dmi_checksum(buf, buf[5])) {
+		dmi_ver = (buf[6] << 8) + buf[7];
+
+		/* Some BIOS report weird SMBIOS version, fix that up */
+		switch (dmi_ver) {
+		case 0x021F:
+		case 0x0221:
+			pr_debug("SMBIOS version fixup(2.%d->2.%d)\n",
+			       dmi_ver & 0xFF, 3);
+			dmi_ver = 0x0203;
+			break;
+		case 0x0233:
+			pr_debug("SMBIOS version fixup(2.%d->2.%d)\n", 51, 6);
+			dmi_ver = 0x0206;
+			break;
+		}
+		offset = 16;
+	}
+	return dmi_present(buf + offset);
+}
+
 void __init dmi_scan_machine(void)
 {
 	char __iomem *p, *q;
@@ -444,7 +483,7 @@ void __init dmi_scan_machine(void)
 		if (p == NULL)
 			goto error;
 
-		rc = dmi_present(p + 0x10); /* offset of _DMI_ string */
+		rc = smbios_present(p);
 		dmi_iounmap(p, 32);
 		if (!rc) {
 			dmi_available = 1;
@@ -462,7 +501,12 @@ void __init dmi_scan_machine(void)
 			goto error;
 
 		for (q = p; q < p + 0x10000; q += 16) {
-			rc = dmi_present(q);
+			if (memcmp(q, "_SM_", 4) == 0 && q - p <= 0xFFE0)
+				rc = smbios_present(q);
+			else if (memcmp(q, "_DMI_", 5) == 0)
+				rc = dmi_present(q);
+			else
+				continue;
 			if (!rc) {
 				dmi_available = 1;
 				dmi_iounmap(p, 0x10000);
diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
index 47408e8..d10c987 100644
--- a/drivers/firmware/efivars.c
+++ b/drivers/firmware/efivars.c
@@ -435,12 +435,23 @@ efivar_attr_read(struct efivar_entry *entry, char *buf)
 	if (status != EFI_SUCCESS)
 		return -EIO;
 
-	if (var->Attributes & 0x1)
+	if (var->Attributes & EFI_VARIABLE_NON_VOLATILE)
 		str += sprintf(str, "EFI_VARIABLE_NON_VOLATILE\n");
-	if (var->Attributes & 0x2)
+	if (var->Attributes & EFI_VARIABLE_BOOTSERVICE_ACCESS)
 		str += sprintf(str, "EFI_VARIABLE_BOOTSERVICE_ACCESS\n");
-	if (var->Attributes & 0x4)
+	if (var->Attributes & EFI_VARIABLE_RUNTIME_ACCESS)
 		str += sprintf(str, "EFI_VARIABLE_RUNTIME_ACCESS\n");
+	if (var->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD)
+		str += sprintf(str, "EFI_VARIABLE_HARDWARE_ERROR_RECORD\n");
+	if (var->Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS)
+		str += sprintf(str,
+			"EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS\n");
+	if (var->Attributes &
+			EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS)
+		str += sprintf(str,
+			"EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS\n");
+	if (var->Attributes & EFI_VARIABLE_APPEND_WRITE)
+		str += sprintf(str, "EFI_VARIABLE_APPEND_WRITE\n");
 	return str - buf;
 }
 
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index ba7926f5..0c05532 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -82,7 +82,7 @@ config GPIO_GENERIC
 
 config GPIO_DA9052
 	tristate "Dialog DA9052 GPIO"
-	depends on PMIC_DA9052 && BROKEN
+	depends on PMIC_DA9052
 	help
 	  Say yes here to enable the GPIO driver for the DA9052 chip.
 
@@ -150,6 +150,12 @@ config GPIO_MSM_V2
 	  Qualcomm MSM chips.  Most of the pins on the MSM can be
 	  selected for GPIO, and are controlled by this driver.
 
+config GPIO_MVEBU
+	def_bool y
+	depends on ARCH_MVEBU
+	select GPIO_GENERIC
+	select GENERIC_IRQ_CHIP
+
 config GPIO_MXC
 	def_bool y
 	depends on ARCH_MXC
@@ -183,6 +189,12 @@ config GPIO_STA2X11
 	  Say yes here to support the STA2x11/ConneXt GPIO device.
 	  The GPIO module has 128 GPIO pins with alternate functions.
 
+config GPIO_VT8500
+	bool "VIA/Wondermedia SoC GPIO Support"
+	depends on ARCH_VT8500
+	help
+	  Say yes here to support the VT8500/WM8505/WM8650 GPIO controller.
+
 config GPIO_XILINX
 	bool "Xilinx GPIO support"
 	depends on PPC_OF || MICROBLAZE
@@ -402,6 +414,13 @@ config GPIO_TWL4030
 	  Say yes here to access the GPIO signals of various multi-function
 	  power management chips from Texas Instruments.
 
+config GPIO_TWL6040
+	tristate "TWL6040 GPO"
+	depends on TWL6040_CORE
+	help
+	  Say yes here to access the GPO signals of twl6040
+	  audio chip from Texas Instruments.
+
 config GPIO_WM831X
 	tristate "WM831x GPIOs"
 	depends on MFD_WM831X
@@ -444,6 +463,17 @@ config GPIO_ADP5588_IRQ
 	  Say yes here to enable the adp5588 to be used as an interrupt
 	  controller. It requires the driver to be built in the kernel.
 
+config GPIO_ADNP
+	tristate "Avionic Design N-bit GPIO expander"
+	depends on I2C && OF
+	help
+	  This option enables support for N GPIOs found on Avionic Design
+	  I2C GPIO expanders. The register space will be extended by powers
+	  of two, so the controller will need to accomodate for that. For
+	  example: if a controller provides 48 pins, 6 registers will be
+	  enough to represent all pins, but the driver will assume a
+	  register layout for 64 pins (8 registers).
+
 comment "PCI GPIO expanders:"
 
 config GPIO_CS5535
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 153cace..9aeed67 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_GPIO_GENERIC)	+= gpio-generic.o
 
 obj-$(CONFIG_GPIO_74X164)	+= gpio-74x164.o
 obj-$(CONFIG_GPIO_AB8500)	+= gpio-ab8500.o
+obj-$(CONFIG_GPIO_ADNP)		+= gpio-adnp.o
 obj-$(CONFIG_GPIO_ADP5520)	+= gpio-adp5520.o
 obj-$(CONFIG_GPIO_ADP5588)	+= gpio-adp5588.o
 obj-$(CONFIG_GPIO_AMD8111)	+= gpio-amd8111.o
@@ -41,6 +42,7 @@ obj-$(CONFIG_GPIO_MPC8XXX)	+= gpio-mpc8xxx.o
 obj-$(CONFIG_GPIO_MSIC)		+= gpio-msic.o
 obj-$(CONFIG_GPIO_MSM_V1)	+= gpio-msm-v1.o
 obj-$(CONFIG_GPIO_MSM_V2)	+= gpio-msm-v2.o
+obj-$(CONFIG_GPIO_MVEBU)        += gpio-mvebu.o
 obj-$(CONFIG_GPIO_MXC)		+= gpio-mxc.o
 obj-$(CONFIG_GPIO_MXS)		+= gpio-mxs.o
 obj-$(CONFIG_ARCH_OMAP)		+= gpio-omap.o
@@ -67,8 +69,10 @@ obj-$(CONFIG_GPIO_TPS6586X)	+= gpio-tps6586x.o
 obj-$(CONFIG_GPIO_TPS65910)	+= gpio-tps65910.o
 obj-$(CONFIG_GPIO_TPS65912)	+= gpio-tps65912.o
 obj-$(CONFIG_GPIO_TWL4030)	+= gpio-twl4030.o
+obj-$(CONFIG_GPIO_TWL6040)	+= gpio-twl6040.o
 obj-$(CONFIG_GPIO_UCB1400)	+= gpio-ucb1400.o
 obj-$(CONFIG_GPIO_VR41XX)	+= gpio-vr41xx.o
+obj-$(CONFIG_GPIO_VT8500)	+= gpio-vt8500.o
 obj-$(CONFIG_GPIO_VX855)	+= gpio-vx855.o
 obj-$(CONFIG_GPIO_WM831X)	+= gpio-wm831x.o
 obj-$(CONFIG_GPIO_WM8350)	+= gpio-wm8350.o
diff --git a/drivers/gpio/gpio-74x164.c b/drivers/gpio/gpio-74x164.c
index a31ad6f..ed3e551 100644
--- a/drivers/gpio/gpio-74x164.c
+++ b/drivers/gpio/gpio-74x164.c
@@ -14,14 +14,18 @@
 #include <linux/spi/spi.h>
 #include <linux/spi/74x164.h>
 #include <linux/gpio.h>
+#include <linux/of_gpio.h>
 #include <linux/slab.h>
 #include <linux/module.h>
 
+#define GEN_74X164_NUMBER_GPIOS	8
+
 struct gen_74x164_chip {
 	struct spi_device	*spi;
+	u8			*buffer;
 	struct gpio_chip	gpio_chip;
 	struct mutex		lock;
-	u8			port_config;
+	u32			registers;
 };
 
 static struct gen_74x164_chip *gpio_to_74x164_chip(struct gpio_chip *gc)
@@ -31,17 +35,47 @@ static struct gen_74x164_chip *gpio_to_74x164_chip(struct gpio_chip *gc)
 
 static int __gen_74x164_write_config(struct gen_74x164_chip *chip)
 {
-	return spi_write(chip->spi,
-			 &chip->port_config, sizeof(chip->port_config));
+	struct spi_message message;
+	struct spi_transfer *msg_buf;
+	int i, ret = 0;
+
+	msg_buf = kzalloc(chip->registers * sizeof(struct spi_transfer),
+			GFP_KERNEL);
+	if (!msg_buf)
+		return -ENOMEM;
+
+	spi_message_init(&message);
+
+	/*
+	 * Since the registers are chained, every byte sent will make
+	 * the previous byte shift to the next register in the
+	 * chain. Thus, the first byte send will end up in the last
+	 * register at the end of the transfer. So, to have a logical
+	 * numbering, send the bytes in reverse order so that the last
+	 * byte of the buffer will end up in the last register.
+	 */
+	for (i = chip->registers - 1; i >= 0; i--) {
+		msg_buf[i].tx_buf = chip->buffer +i;
+		msg_buf[i].len = sizeof(u8);
+		spi_message_add_tail(msg_buf + i, &message);
+	}
+
+	ret = spi_sync(chip->spi, &message);
+
+	kfree(msg_buf);
+
+	return ret;
 }
 
 static int gen_74x164_get_value(struct gpio_chip *gc, unsigned offset)
 {
 	struct gen_74x164_chip *chip = gpio_to_74x164_chip(gc);
+	u8 bank = offset / 8;
+	u8 pin = offset % 8;
 	int ret;
 
 	mutex_lock(&chip->lock);
-	ret = (chip->port_config >> offset) & 0x1;
+	ret = (chip->buffer[bank] >> pin) & 0x1;
 	mutex_unlock(&chip->lock);
 
 	return ret;
@@ -51,12 +85,14 @@ static void gen_74x164_set_value(struct gpio_chip *gc,
 		unsigned offset, int val)
 {
 	struct gen_74x164_chip *chip = gpio_to_74x164_chip(gc);
+	u8 bank = offset / 8;
+	u8 pin = offset % 8;
 
 	mutex_lock(&chip->lock);
 	if (val)
-		chip->port_config |= (1 << offset);
+		chip->buffer[bank] |= (1 << pin);
 	else
-		chip->port_config &= ~(1 << offset);
+		chip->buffer[bank] &= ~(1 << pin);
 
 	__gen_74x164_write_config(chip);
 	mutex_unlock(&chip->lock);
@@ -75,9 +111,8 @@ static int __devinit gen_74x164_probe(struct spi_device *spi)
 	struct gen_74x164_chip_platform_data *pdata;
 	int ret;
 
-	pdata = spi->dev.platform_data;
-	if (!pdata || !pdata->base) {
-		dev_dbg(&spi->dev, "incorrect or missing platform data\n");
+	if (!spi->dev.of_node) {
+		dev_err(&spi->dev, "No device tree data available.\n");
 		return -EINVAL;
 	}
 
@@ -90,10 +125,16 @@ static int __devinit gen_74x164_probe(struct spi_device *spi)
 	if (ret < 0)
 		return ret;
 
-	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+	chip = devm_kzalloc(&spi->dev, sizeof(*chip), GFP_KERNEL);
 	if (!chip)
 		return -ENOMEM;
 
+	pdata = spi->dev.platform_data;
+	if (pdata && pdata->base)
+		chip->gpio_chip.base = pdata->base;
+	else
+		chip->gpio_chip.base = -1;
+
 	mutex_init(&chip->lock);
 
 	dev_set_drvdata(&spi->dev, chip);
@@ -104,8 +145,20 @@ static int __devinit gen_74x164_probe(struct spi_device *spi)
 	chip->gpio_chip.direction_output = gen_74x164_direction_output;
 	chip->gpio_chip.get = gen_74x164_get_value;
 	chip->gpio_chip.set = gen_74x164_set_value;
-	chip->gpio_chip.base = pdata->base;
-	chip->gpio_chip.ngpio = 8;
+
+	if (of_property_read_u32(spi->dev.of_node, "registers-number", &chip->registers)) {
+		dev_err(&spi->dev, "Missing registers-number property in the DT.\n");
+		ret = -EINVAL;
+		goto exit_destroy;
+	}
+
+	chip->gpio_chip.ngpio = GEN_74X164_NUMBER_GPIOS * chip->registers;
+	chip->buffer = devm_kzalloc(&spi->dev, chip->gpio_chip.ngpio, GFP_KERNEL);
+	if (!chip->buffer) {
+		ret = -ENOMEM;
+		goto exit_destroy;
+	}
+
 	chip->gpio_chip.can_sleep = 1;
 	chip->gpio_chip.dev = &spi->dev;
 	chip->gpio_chip.owner = THIS_MODULE;
@@ -125,7 +178,6 @@ static int __devinit gen_74x164_probe(struct spi_device *spi)
 exit_destroy:
 	dev_set_drvdata(&spi->dev, NULL);
 	mutex_destroy(&chip->lock);
-	kfree(chip);
 	return ret;
 }
 
@@ -141,36 +193,31 @@ static int __devexit gen_74x164_remove(struct spi_device *spi)
 	dev_set_drvdata(&spi->dev, NULL);
 
 	ret = gpiochip_remove(&chip->gpio_chip);
-	if (!ret) {
+	if (!ret)
 		mutex_destroy(&chip->lock);
-		kfree(chip);
-	} else
+	else
 		dev_err(&spi->dev, "Failed to remove the GPIO controller: %d\n",
 				ret);
 
 	return ret;
 }
 
+static const struct of_device_id gen_74x164_dt_ids[] = {
+	{ .compatible = "fairchild,74hc595" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, gen_74x164_dt_ids);
+
 static struct spi_driver gen_74x164_driver = {
 	.driver = {
 		.name		= "74x164",
 		.owner		= THIS_MODULE,
+		.of_match_table	= of_match_ptr(gen_74x164_dt_ids),
 	},
 	.probe		= gen_74x164_probe,
 	.remove		= __devexit_p(gen_74x164_remove),
 };
-
-static int __init gen_74x164_init(void)
-{
-	return spi_register_driver(&gen_74x164_driver);
-}
-subsys_initcall(gen_74x164_init);
-
-static void __exit gen_74x164_exit(void)
-{
-	spi_unregister_driver(&gen_74x164_driver);
-}
-module_exit(gen_74x164_exit);
+module_spi_driver(gen_74x164_driver);
 
 MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>");
 MODULE_AUTHOR("Miguel Gaio <miguel.gaio@efixo.com>");
diff --git a/drivers/gpio/gpio-adnp.c b/drivers/gpio/gpio-adnp.c
new file mode 100644
index 0000000..3df8833
--- /dev/null
+++ b/drivers/gpio/gpio-adnp.c
@@ -0,0 +1,611 @@
+/*
+ * Copyright (C) 2011-2012 Avionic Design GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/irqdomain.h>
+#include <linux/module.h>
+#include <linux/of_irq.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+
+#define GPIO_DDR(gpio) (0x00 << (gpio)->reg_shift)
+#define GPIO_PLR(gpio) (0x01 << (gpio)->reg_shift)
+#define GPIO_IER(gpio) (0x02 << (gpio)->reg_shift)
+#define GPIO_ISR(gpio) (0x03 << (gpio)->reg_shift)
+#define GPIO_PTR(gpio) (0x04 << (gpio)->reg_shift)
+
+struct adnp {
+	struct i2c_client *client;
+	struct gpio_chip gpio;
+	unsigned int reg_shift;
+
+	struct mutex i2c_lock;
+
+	struct irq_domain *domain;
+	struct mutex irq_lock;
+
+	u8 *irq_enable;
+	u8 *irq_level;
+	u8 *irq_rise;
+	u8 *irq_fall;
+	u8 *irq_high;
+	u8 *irq_low;
+};
+
+static inline struct adnp *to_adnp(struct gpio_chip *chip)
+{
+	return container_of(chip, struct adnp, gpio);
+}
+
+static int adnp_read(struct adnp *adnp, unsigned offset, uint8_t *value)
+{
+	int err;
+
+	err = i2c_smbus_read_byte_data(adnp->client, offset);
+	if (err < 0) {
+		dev_err(adnp->gpio.dev, "%s failed: %d\n",
+			"i2c_smbus_read_byte_data()", err);
+		return err;
+	}
+
+	*value = err;
+	return 0;
+}
+
+static int adnp_write(struct adnp *adnp, unsigned offset, uint8_t value)
+{
+	int err;
+
+	err = i2c_smbus_write_byte_data(adnp->client, offset, value);
+	if (err < 0) {
+		dev_err(adnp->gpio.dev, "%s failed: %d\n",
+			"i2c_smbus_write_byte_data()", err);
+		return err;
+	}
+
+	return 0;
+}
+
+static int adnp_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+	struct adnp *adnp = to_adnp(chip);
+	unsigned int reg = offset >> adnp->reg_shift;
+	unsigned int pos = offset & 7;
+	u8 value;
+	int err;
+
+	err = adnp_read(adnp, GPIO_PLR(adnp) + reg, &value);
+	if (err < 0)
+		return err;
+
+	return (value & BIT(pos)) ? 1 : 0;
+}
+
+static void __adnp_gpio_set(struct adnp *adnp, unsigned offset, int value)
+{
+	unsigned int reg = offset >> adnp->reg_shift;
+	unsigned int pos = offset & 7;
+	int err;
+	u8 val;
+
+	err = adnp_read(adnp, GPIO_PLR(adnp) + reg, &val);
+	if (err < 0)
+		return;
+
+	if (value)
+		val |= BIT(pos);
+	else
+		val &= ~BIT(pos);
+
+	adnp_write(adnp, GPIO_PLR(adnp) + reg, val);
+}
+
+static void adnp_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+	struct adnp *adnp = to_adnp(chip);
+
+	mutex_lock(&adnp->i2c_lock);
+	__adnp_gpio_set(adnp, offset, value);
+	mutex_unlock(&adnp->i2c_lock);
+}
+
+static int adnp_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	struct adnp *adnp = to_adnp(chip);
+	unsigned int reg = offset >> adnp->reg_shift;
+	unsigned int pos = offset & 7;
+	u8 value;
+	int err;
+
+	mutex_lock(&adnp->i2c_lock);
+
+	err = adnp_read(adnp, GPIO_DDR(adnp) + reg, &value);
+	if (err < 0)
+		goto out;
+
+	value &= ~BIT(pos);
+
+	err = adnp_write(adnp, GPIO_DDR(adnp) + reg, value);
+	if (err < 0)
+		goto out;
+
+	err = adnp_read(adnp, GPIO_DDR(adnp) + reg, &value);
+	if (err < 0)
+		goto out;
+
+	if (err & BIT(pos))
+		err = -EACCES;
+
+	err = 0;
+
+out:
+	mutex_unlock(&adnp->i2c_lock);
+	return err;
+}
+
+static int adnp_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
+				      int value)
+{
+	struct adnp *adnp = to_adnp(chip);
+	unsigned int reg = offset >> adnp->reg_shift;
+	unsigned int pos = offset & 7;
+	int err;
+	u8 val;
+
+	mutex_lock(&adnp->i2c_lock);
+
+	err = adnp_read(adnp, GPIO_DDR(adnp) + reg, &val);
+	if (err < 0)
+		goto out;
+
+	val |= BIT(pos);
+
+	err = adnp_write(adnp, GPIO_DDR(adnp) + reg, val);
+	if (err < 0)
+		goto out;
+
+	err = adnp_read(adnp, GPIO_DDR(adnp) + reg, &val);
+	if (err < 0)
+		goto out;
+
+	if (!(val & BIT(pos))) {
+		err = -EPERM;
+		goto out;
+	}
+
+	__adnp_gpio_set(adnp, offset, value);
+	err = 0;
+
+out:
+	mutex_unlock(&adnp->i2c_lock);
+	return err;
+}
+
+static void adnp_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
+{
+	struct adnp *adnp = to_adnp(chip);
+	unsigned int num_regs = 1 << adnp->reg_shift, i, j;
+	int err;
+
+	for (i = 0; i < num_regs; i++) {
+		u8 ddr, plr, ier, isr;
+
+		mutex_lock(&adnp->i2c_lock);
+
+		err = adnp_read(adnp, GPIO_DDR(adnp) + i, &ddr);
+		if (err < 0) {
+			mutex_unlock(&adnp->i2c_lock);
+			return;
+		}
+
+		err = adnp_read(adnp, GPIO_PLR(adnp) + i, &plr);
+		if (err < 0) {
+			mutex_unlock(&adnp->i2c_lock);
+			return;
+		}
+
+		err = adnp_read(adnp, GPIO_IER(adnp) + i, &ier);
+		if (err < 0) {
+			mutex_unlock(&adnp->i2c_lock);
+			return;
+		}
+
+		err = adnp_read(adnp, GPIO_ISR(adnp) + i, &isr);
+		if (err < 0) {
+			mutex_unlock(&adnp->i2c_lock);
+			return;
+		}
+
+		mutex_unlock(&adnp->i2c_lock);
+
+		for (j = 0; j < 8; j++) {
+			unsigned int bit = (i << adnp->reg_shift) + j;
+			const char *direction = "input ";
+			const char *level = "low ";
+			const char *interrupt = "disabled";
+			const char *pending = "";
+
+			if (ddr & BIT(j))
+				direction = "output";
+
+			if (plr & BIT(j))
+				level = "high";
+
+			if (ier & BIT(j))
+				interrupt = "enabled ";
+
+			if (isr & BIT(j))
+				pending = "pending";
+
+			seq_printf(s, "%2u: %s %s IRQ %s %s\n", bit,
+				   direction, level, interrupt, pending);
+		}
+	}
+}
+
+static int adnp_gpio_setup(struct adnp *adnp, unsigned int num_gpios)
+{
+	struct gpio_chip *chip = &adnp->gpio;
+
+	adnp->reg_shift = get_count_order(num_gpios) - 3;
+
+	chip->direction_input = adnp_gpio_direction_input;
+	chip->direction_output = adnp_gpio_direction_output;
+	chip->get = adnp_gpio_get;
+	chip->set = adnp_gpio_set;
+	chip->can_sleep = 1;
+
+	if (IS_ENABLED(CONFIG_DEBUG_FS))
+		chip->dbg_show = adnp_gpio_dbg_show;
+
+	chip->base = -1;
+	chip->ngpio = num_gpios;
+	chip->label = adnp->client->name;
+	chip->dev = &adnp->client->dev;
+	chip->of_node = chip->dev->of_node;
+	chip->owner = THIS_MODULE;
+
+	return 0;
+}
+
+static irqreturn_t adnp_irq(int irq, void *data)
+{
+	struct adnp *adnp = data;
+	unsigned int num_regs, i;
+
+	num_regs = 1 << adnp->reg_shift;
+
+	for (i = 0; i < num_regs; i++) {
+		unsigned int base = i << adnp->reg_shift, bit;
+		u8 changed, level, isr, ier;
+		unsigned long pending;
+		int err;
+
+		mutex_lock(&adnp->i2c_lock);
+
+		err = adnp_read(adnp, GPIO_PLR(adnp) + i, &level);
+		if (err < 0) {
+			mutex_unlock(&adnp->i2c_lock);
+			continue;
+		}
+
+		err = adnp_read(adnp, GPIO_ISR(adnp) + i, &isr);
+		if (err < 0) {
+			mutex_unlock(&adnp->i2c_lock);
+			continue;
+		}
+
+		err = adnp_read(adnp, GPIO_IER(adnp) + i, &ier);
+		if (err < 0) {
+			mutex_unlock(&adnp->i2c_lock);
+			continue;
+		}
+
+		mutex_unlock(&adnp->i2c_lock);
+
+		/* determine pins that changed levels */
+		changed = level ^ adnp->irq_level[i];
+
+		/* compute edge-triggered interrupts */
+		pending = changed & ((adnp->irq_fall[i] & ~level) |
+				     (adnp->irq_rise[i] & level));
+
+		/* add in level-triggered interrupts */
+		pending |= (adnp->irq_high[i] & level) |
+			   (adnp->irq_low[i] & ~level);
+
+		/* mask out non-pending and disabled interrupts */
+		pending &= isr & ier;
+
+		for_each_set_bit(bit, &pending, 8) {
+			unsigned int virq;
+			virq = irq_find_mapping(adnp->domain, base + bit);
+			handle_nested_irq(virq);
+		}
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int adnp_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+	struct adnp *adnp = to_adnp(chip);
+	return irq_create_mapping(adnp->domain, offset);
+}
+
+static void adnp_irq_mask(struct irq_data *data)
+{
+	struct adnp *adnp = irq_data_get_irq_chip_data(data);
+	unsigned int reg = data->hwirq >> adnp->reg_shift;
+	unsigned int pos = data->hwirq & 7;
+
+	adnp->irq_enable[reg] &= ~BIT(pos);
+}
+
+static void adnp_irq_unmask(struct irq_data *data)
+{
+	struct adnp *adnp = irq_data_get_irq_chip_data(data);
+	unsigned int reg = data->hwirq >> adnp->reg_shift;
+	unsigned int pos = data->hwirq & 7;
+
+	adnp->irq_enable[reg] |= BIT(pos);
+}
+
+static int adnp_irq_set_type(struct irq_data *data, unsigned int type)
+{
+	struct adnp *adnp = irq_data_get_irq_chip_data(data);
+	unsigned int reg = data->hwirq >> adnp->reg_shift;
+	unsigned int pos = data->hwirq & 7;
+
+	if (type & IRQ_TYPE_EDGE_RISING)
+		adnp->irq_rise[reg] |= BIT(pos);
+	else
+		adnp->irq_rise[reg] &= ~BIT(pos);
+
+	if (type & IRQ_TYPE_EDGE_FALLING)
+		adnp->irq_fall[reg] |= BIT(pos);
+	else
+		adnp->irq_fall[reg] &= ~BIT(pos);
+
+	if (type & IRQ_TYPE_LEVEL_HIGH)
+		adnp->irq_high[reg] |= BIT(pos);
+	else
+		adnp->irq_high[reg] &= ~BIT(pos);
+
+	if (type & IRQ_TYPE_LEVEL_LOW)
+		adnp->irq_low[reg] |= BIT(pos);
+	else
+		adnp->irq_low[reg] &= ~BIT(pos);
+
+	return 0;
+}
+
+static void adnp_irq_bus_lock(struct irq_data *data)
+{
+	struct adnp *adnp = irq_data_get_irq_chip_data(data);
+
+	mutex_lock(&adnp->irq_lock);
+}
+
+static void adnp_irq_bus_unlock(struct irq_data *data)
+{
+	struct adnp *adnp = irq_data_get_irq_chip_data(data);
+	unsigned int num_regs = 1 << adnp->reg_shift, i;
+
+	mutex_lock(&adnp->i2c_lock);
+
+	for (i = 0; i < num_regs; i++)
+		adnp_write(adnp, GPIO_IER(adnp) + i, adnp->irq_enable[i]);
+
+	mutex_unlock(&adnp->i2c_lock);
+	mutex_unlock(&adnp->irq_lock);
+}
+
+static struct irq_chip adnp_irq_chip = {
+	.name = "gpio-adnp",
+	.irq_mask = adnp_irq_mask,
+	.irq_unmask = adnp_irq_unmask,
+	.irq_set_type = adnp_irq_set_type,
+	.irq_bus_lock = adnp_irq_bus_lock,
+	.irq_bus_sync_unlock = adnp_irq_bus_unlock,
+};
+
+static int adnp_irq_map(struct irq_domain *domain, unsigned int irq,
+			irq_hw_number_t hwirq)
+{
+	irq_set_chip_data(irq, domain->host_data);
+	irq_set_chip(irq, &adnp_irq_chip);
+	irq_set_nested_thread(irq, true);
+
+#ifdef CONFIG_ARM
+	set_irq_flags(irq, IRQF_VALID);
+#else
+	irq_set_noprobe(irq);
+#endif
+
+	return 0;
+}
+
+static const struct irq_domain_ops adnp_irq_domain_ops = {
+	.map = adnp_irq_map,
+	.xlate = irq_domain_xlate_twocell,
+};
+
+static int adnp_irq_setup(struct adnp *adnp)
+{
+	unsigned int num_regs = 1 << adnp->reg_shift, i;
+	struct gpio_chip *chip = &adnp->gpio;
+	int err;
+
+	mutex_init(&adnp->irq_lock);
+
+	/*
+	 * Allocate memory to keep track of the current level and trigger
+	 * modes of the interrupts. To avoid multiple allocations, a single
+	 * large buffer is allocated and pointers are setup to point at the
+	 * corresponding offsets. For consistency, the layout of the buffer
+	 * is chosen to match the register layout of the hardware in that
+	 * each segment contains the corresponding bits for all interrupts.
+	 */
+	adnp->irq_enable = devm_kzalloc(chip->dev, num_regs * 6, GFP_KERNEL);
+	if (!adnp->irq_enable)
+		return -ENOMEM;
+
+	adnp->irq_level = adnp->irq_enable + (num_regs * 1);
+	adnp->irq_rise = adnp->irq_enable + (num_regs * 2);
+	adnp->irq_fall = adnp->irq_enable + (num_regs * 3);
+	adnp->irq_high = adnp->irq_enable + (num_regs * 4);
+	adnp->irq_low = adnp->irq_enable + (num_regs * 5);
+
+	for (i = 0; i < num_regs; i++) {
+		/*
+		 * Read the initial level of all pins to allow the emulation
+		 * of edge triggered interrupts.
+		 */
+		err = adnp_read(adnp, GPIO_PLR(adnp) + i, &adnp->irq_level[i]);
+		if (err < 0)
+			return err;
+
+		/* disable all interrupts */
+		err = adnp_write(adnp, GPIO_IER(adnp) + i, 0);
+		if (err < 0)
+			return err;
+
+		adnp->irq_enable[i] = 0x00;
+	}
+
+	adnp->domain = irq_domain_add_linear(chip->of_node, chip->ngpio,
+					     &adnp_irq_domain_ops, adnp);
+
+	err = request_threaded_irq(adnp->client->irq, NULL, adnp_irq,
+				   IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+				   dev_name(chip->dev), adnp);
+	if (err != 0) {
+		dev_err(chip->dev, "can't request IRQ#%d: %d\n",
+			adnp->client->irq, err);
+		goto error;
+	}
+
+	chip->to_irq = adnp_gpio_to_irq;
+	return 0;
+
+error:
+	irq_domain_remove(adnp->domain);
+	return err;
+}
+
+static void adnp_irq_teardown(struct adnp *adnp)
+{
+	unsigned int irq, i;
+
+	free_irq(adnp->client->irq, adnp);
+
+	for (i = 0; i < adnp->gpio.ngpio; i++) {
+		irq = irq_find_mapping(adnp->domain, i);
+		if (irq > 0)
+			irq_dispose_mapping(irq);
+	}
+
+	irq_domain_remove(adnp->domain);
+}
+
+static __devinit int adnp_i2c_probe(struct i2c_client *client,
+				    const struct i2c_device_id *id)
+{
+	struct device_node *np = client->dev.of_node;
+	struct adnp *adnp;
+	u32 num_gpios;
+	int err;
+
+	err = of_property_read_u32(np, "nr-gpios", &num_gpios);
+	if (err < 0)
+		return err;
+
+	client->irq = irq_of_parse_and_map(np, 0);
+	if (!client->irq)
+		return -EPROBE_DEFER;
+
+	adnp = devm_kzalloc(&client->dev, sizeof(*adnp), GFP_KERNEL);
+	if (!adnp)
+		return -ENOMEM;
+
+	mutex_init(&adnp->i2c_lock);
+	adnp->client = client;
+
+	err = adnp_gpio_setup(adnp, num_gpios);
+	if (err < 0)
+		return err;
+
+	if (of_find_property(np, "interrupt-controller", NULL)) {
+		err = adnp_irq_setup(adnp);
+		if (err < 0)
+			goto teardown;
+	}
+
+	err = gpiochip_add(&adnp->gpio);
+	if (err < 0)
+		goto teardown;
+
+	i2c_set_clientdata(client, adnp);
+	return 0;
+
+teardown:
+	if (of_find_property(np, "interrupt-controller", NULL))
+		adnp_irq_teardown(adnp);
+
+	return err;
+}
+
+static __devexit int adnp_i2c_remove(struct i2c_client *client)
+{
+	struct adnp *adnp = i2c_get_clientdata(client);
+	struct device_node *np = client->dev.of_node;
+	int err;
+
+	err = gpiochip_remove(&adnp->gpio);
+	if (err < 0) {
+		dev_err(&client->dev, "%s failed: %d\n", "gpiochip_remove()",
+			err);
+		return err;
+	}
+
+	if (of_find_property(np, "interrupt-controller", NULL))
+		adnp_irq_teardown(adnp);
+
+	return 0;
+}
+
+static const struct i2c_device_id adnp_i2c_id[] __devinitconst = {
+	{ "gpio-adnp" },
+	{ },
+};
+MODULE_DEVICE_TABLE(i2c, adnp_i2c_id);
+
+static const struct of_device_id adnp_of_match[] __devinitconst = {
+	{ .compatible = "ad,gpio-adnp", },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, adnp_of_match);
+
+static struct i2c_driver adnp_i2c_driver = {
+	.driver = {
+		.name = "gpio-adnp",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(adnp_of_match),
+	},
+	.probe = adnp_i2c_probe,
+	.remove = __devexit_p(adnp_i2c_remove),
+	.id_table = adnp_i2c_id,
+};
+module_i2c_driver(adnp_i2c_driver);
+
+MODULE_DESCRIPTION("Avionic Design N-bit GPIO expander");
+MODULE_AUTHOR("Thierry Reding <thierry.reding@avionic-design.de>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/gpio-adp5588.c b/drivers/gpio/gpio-adp5588.c
index ae5d7f1..eeedad4 100644
--- a/drivers/gpio/gpio-adp5588.c
+++ b/drivers/gpio/gpio-adp5588.c
@@ -483,19 +483,7 @@ static struct i2c_driver adp5588_gpio_driver = {
 	.id_table = adp5588_gpio_id,
 };
 
-static int __init adp5588_gpio_init(void)
-{
-	return i2c_add_driver(&adp5588_gpio_driver);
-}
-
-module_init(adp5588_gpio_init);
-
-static void __exit adp5588_gpio_exit(void)
-{
-	i2c_del_driver(&adp5588_gpio_driver);
-}
-
-module_exit(adp5588_gpio_exit);
+module_i2c_driver(adp5588_gpio_driver);
 
 MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
 MODULE_DESCRIPTION("GPIO ADP5588 Driver");
diff --git a/drivers/gpio/gpio-bt8xx.c b/drivers/gpio/gpio-bt8xx.c
index e4cc7eb..7d9d7cb 100644
--- a/drivers/gpio/gpio-bt8xx.c
+++ b/drivers/gpio/gpio-bt8xx.c
@@ -50,7 +50,7 @@
 #include <linux/slab.h>
 
 /* Steal the hardware definitions from the bttv driver. */
-#include "../media/video/bt8xx/bt848.h"
+#include "../media/pci/bt8xx/bt848.h"
 
 
 #define BT8XXGPIO_NR_GPIOS		24 /* We have 24 GPIO pins */
@@ -310,7 +310,7 @@ static int bt8xxgpio_resume(struct pci_dev *pdev)
 #define bt8xxgpio_resume NULL
 #endif /* CONFIG_PM */
 
-static struct pci_device_id bt8xxgpio_pci_tbl[] = {
+static DEFINE_PCI_DEVICE_TABLE(bt8xxgpio_pci_tbl) = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT848) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT849) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT878) },
diff --git a/drivers/gpio/gpio-da9052.c b/drivers/gpio/gpio-da9052.c
index 56dd047..24b8c29 100644
--- a/drivers/gpio/gpio-da9052.c
+++ b/drivers/gpio/gpio-da9052.c
@@ -207,7 +207,7 @@ static int __devinit da9052_gpio_probe(struct platform_device *pdev)
 	struct da9052_pdata *pdata;
 	int ret;
 
-	gpio = kzalloc(sizeof(*gpio), GFP_KERNEL);
+	gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
 	if (gpio == NULL)
 		return -ENOMEM;
 
@@ -221,28 +221,19 @@ static int __devinit da9052_gpio_probe(struct platform_device *pdev)
 	ret = gpiochip_add(&gpio->gp);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret);
-		goto err_mem;
+		return ret;
 	}
 
 	platform_set_drvdata(pdev, gpio);
 
 	return 0;
-
-err_mem:
-	kfree(gpio);
-	return ret;
 }
 
 static int __devexit da9052_gpio_remove(struct platform_device *pdev)
 {
 	struct da9052_gpio *gpio = platform_get_drvdata(pdev);
-	int ret;
-
-	ret = gpiochip_remove(&gpio->gp);
-	if (ret == 0)
-		kfree(gpio);
 
-	return ret;
+	return gpiochip_remove(&gpio->gp);
 }
 
 static struct platform_driver da9052_gpio_driver = {
diff --git a/drivers/gpio/gpio-davinci.c b/drivers/gpio/gpio-davinci.c
index 3d00016..17df6db 100644
--- a/drivers/gpio/gpio-davinci.c
+++ b/drivers/gpio/gpio-davinci.c
@@ -366,7 +366,7 @@ static int __init davinci_gpio_irq_setup(void)
 		       PTR_ERR(clk));
 		return PTR_ERR(clk);
 	}
-	clk_enable(clk);
+	clk_prepare_enable(clk);
 
 	/* Arrange gpio_to_irq() support, handling either direct IRQs or
 	 * banked IRQs.  Having GPIOs in the first GPIO bank use direct
diff --git a/drivers/gpio/gpio-em.c b/drivers/gpio/gpio-em.c
index ec48ed5..efb4c2d 100644
--- a/drivers/gpio/gpio-em.c
+++ b/drivers/gpio/gpio-em.c
@@ -85,22 +85,16 @@ static inline void em_gio_write(struct em_gio_priv *p, int offs,
 		iowrite32(value, p->base1 + (offs - GIO_IDT0));
 }
 
-static inline struct em_gio_priv *irq_to_priv(struct irq_data *d)
-{
-	struct irq_chip *chip = irq_data_get_irq_chip(d);
-	return container_of(chip, struct em_gio_priv, irq_chip);
-}
-
 static void em_gio_irq_disable(struct irq_data *d)
 {
-	struct em_gio_priv *p = irq_to_priv(d);
+	struct em_gio_priv *p = irq_data_get_irq_chip_data(d);
 
 	em_gio_write(p, GIO_IDS, BIT(irqd_to_hwirq(d)));
 }
 
 static void em_gio_irq_enable(struct irq_data *d)
 {
-	struct em_gio_priv *p = irq_to_priv(d);
+	struct em_gio_priv *p = irq_data_get_irq_chip_data(d);
 
 	em_gio_write(p, GIO_IEN, BIT(irqd_to_hwirq(d)));
 }
@@ -118,7 +112,7 @@ static unsigned char em_gio_sense_table[IRQ_TYPE_SENSE_MASK + 1] = {
 static int em_gio_irq_set_type(struct irq_data *d, unsigned int type)
 {
 	unsigned char value = em_gio_sense_table[type & IRQ_TYPE_SENSE_MASK];
-	struct em_gio_priv *p = irq_to_priv(d);
+	struct em_gio_priv *p = irq_data_get_irq_chip_data(d);
 	unsigned int reg, offset, shift;
 	unsigned long flags;
 	unsigned long tmp;
diff --git a/drivers/gpio/gpio-ich.c b/drivers/gpio/gpio-ich.c
index b7c0651..d4d6179 100644
--- a/drivers/gpio/gpio-ich.c
+++ b/drivers/gpio/gpio-ich.c
@@ -49,6 +49,10 @@ static const u8 ichx_regs[3][3] = {
 	{0x0c, 0x38, 0x48},	/* LVL[1-3] offsets */
 };
 
+static const u8 ichx_reglen[3] = {
+	0x30, 0x10, 0x10,
+};
+
 #define ICHX_WRITE(val, reg, base_res)	outl(val, (reg) + (base_res)->start)
 #define ICHX_READ(reg, base_res)	inl((reg) + (base_res)->start)
 
@@ -75,6 +79,7 @@ static struct {
 	struct resource *pm_base;	/* Power Mangagment IO base */
 	struct ichx_desc *desc;	/* Pointer to chipset-specific description */
 	u32 orig_gpio_ctrl;	/* Orig CTRL value, used to restore on exit */
+	u8 use_gpio;		/* Which GPIO groups are usable */
 } ichx_priv;
 
 static int modparam_gpiobase = -1;	/* dynamic */
@@ -123,8 +128,16 @@ static int ichx_read_bit(int reg, unsigned nr)
 	return data & (1 << bit) ? 1 : 0;
 }
 
+static int ichx_gpio_check_available(struct gpio_chip *gpio, unsigned nr)
+{
+	return (ichx_priv.use_gpio & (1 << (nr / 32))) ? 0 : -ENXIO;
+}
+
 static int ichx_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
 {
+	if (!ichx_gpio_check_available(gpio, nr))
+		return -ENXIO;
+
 	/*
 	 * Try setting pin as an input and verify it worked since many pins
 	 * are output-only.
@@ -138,6 +151,9 @@ static int ichx_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
 static int ichx_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,
 					int val)
 {
+	if (!ichx_gpio_check_available(gpio, nr))
+		return -ENXIO;
+
 	/* Set GPIO output value. */
 	ichx_write_bit(GPIO_LVL, nr, val, 0);
 
@@ -153,6 +169,9 @@ static int ichx_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,
 
 static int ichx_gpio_get(struct gpio_chip *chip, unsigned nr)
 {
+	if (!ichx_gpio_check_available(chip, nr))
+		return -ENXIO;
+
 	return ichx_read_bit(GPIO_LVL, nr);
 }
 
@@ -161,6 +180,9 @@ static int ich6_gpio_get(struct gpio_chip *chip, unsigned nr)
 	unsigned long flags;
 	u32 data;
 
+	if (!ichx_gpio_check_available(chip, nr))
+		return -ENXIO;
+
 	/*
 	 * GPI 0 - 15 need to be read from the power management registers on
 	 * a ICH6/3100 bridge.
@@ -291,6 +313,46 @@ static struct ichx_desc intel5_desc = {
 	.ngpio = 76,
 };
 
+static int __devinit ichx_gpio_request_regions(struct resource *res_base,
+						const char *name, u8 use_gpio)
+{
+	int i;
+
+	if (!res_base || !res_base->start || !res_base->end)
+		return -ENODEV;
+
+	for (i = 0; i < ARRAY_SIZE(ichx_regs[0]); i++) {
+		if (!(use_gpio & (1 << i)))
+			continue;
+		if (!request_region(res_base->start + ichx_regs[0][i],
+				    ichx_reglen[i], name))
+			goto request_err;
+	}
+	return 0;
+
+request_err:
+	/* Clean up: release already requested regions, if any */
+	for (i--; i >= 0; i--) {
+		if (!(use_gpio & (1 << i)))
+			continue;
+		release_region(res_base->start + ichx_regs[0][i],
+			       ichx_reglen[i]);
+	}
+	return -EBUSY;
+}
+
+static void ichx_gpio_release_regions(struct resource *res_base, u8 use_gpio)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(ichx_regs[0]); i++) {
+		if (!(use_gpio & (1 << i)))
+			continue;
+		release_region(res_base->start + ichx_regs[0][i],
+			       ichx_reglen[i]);
+	}
+}
+
 static int __devinit ichx_gpio_probe(struct platform_device *pdev)
 {
 	struct resource *res_base, *res_pm;
@@ -329,12 +391,11 @@ static int __devinit ichx_gpio_probe(struct platform_device *pdev)
 	}
 
 	res_base = platform_get_resource(pdev, IORESOURCE_IO, ICH_RES_GPIO);
-	if (!res_base || !res_base->start || !res_base->end)
-		return -ENODEV;
-
-	if (!request_region(res_base->start, resource_size(res_base),
-				pdev->name))
-		return -EBUSY;
+	ichx_priv.use_gpio = ich_info->use_gpio;
+	err = ichx_gpio_request_regions(res_base, pdev->name,
+					ichx_priv.use_gpio);
+	if (err)
+		return err;
 
 	ichx_priv.gpio_base = res_base;
 
@@ -374,8 +435,7 @@ init:
 	return 0;
 
 add_err:
-	release_region(ichx_priv.gpio_base->start,
-			resource_size(ichx_priv.gpio_base));
+	ichx_gpio_release_regions(ichx_priv.gpio_base, ichx_priv.use_gpio);
 	if (ichx_priv.pm_base)
 		release_region(ichx_priv.pm_base->start,
 				resource_size(ichx_priv.pm_base));
@@ -393,8 +453,7 @@ static int __devexit ichx_gpio_remove(struct platform_device *pdev)
 		return err;
 	}
 
-	release_region(ichx_priv.gpio_base->start,
-				resource_size(ichx_priv.gpio_base));
+	ichx_gpio_release_regions(ichx_priv.gpio_base, ichx_priv.use_gpio);
 	if (ichx_priv.pm_base)
 		release_region(ichx_priv.pm_base->start,
 				resource_size(ichx_priv.pm_base));
diff --git a/drivers/gpio/gpio-lpc32xx.c b/drivers/gpio/gpio-lpc32xx.c
index 8a420f1..ed94b4e 100644
--- a/drivers/gpio/gpio-lpc32xx.c
+++ b/drivers/gpio/gpio-lpc32xx.c
@@ -308,6 +308,7 @@ static int lpc32xx_gpio_dir_output_p012(struct gpio_chip *chip, unsigned pin,
 {
 	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
 
+	__set_gpio_level_p012(group, pin, value);
 	__set_gpio_dir_p012(group, pin, 0);
 
 	return 0;
@@ -318,6 +319,7 @@ static int lpc32xx_gpio_dir_output_p3(struct gpio_chip *chip, unsigned pin,
 {
 	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
 
+	__set_gpio_level_p3(group, pin, value);
 	__set_gpio_dir_p3(group, pin, 0);
 
 	return 0;
@@ -326,6 +328,9 @@ static int lpc32xx_gpio_dir_output_p3(struct gpio_chip *chip, unsigned pin,
 static int lpc32xx_gpio_dir_out_always(struct gpio_chip *chip, unsigned pin,
 	int value)
 {
+	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
+
+	__set_gpo_level_p3(group, pin, value);
 	return 0;
 }
 
diff --git a/drivers/gpio/gpio-mc9s08dz60.c b/drivers/gpio/gpio-mc9s08dz60.c
index 2738cc4..0ab7000 100644
--- a/drivers/gpio/gpio-mc9s08dz60.c
+++ b/drivers/gpio/gpio-mc9s08dz60.c
@@ -91,10 +91,9 @@ static int mc9s08dz60_direction_output(struct gpio_chip *gc,
 static int mc9s08dz60_probe(struct i2c_client *client,
 			    const struct i2c_device_id *id)
 {
-	int ret = 0;
 	struct mc9s08dz60 *mc9s;
 
-	mc9s = kzalloc(sizeof(*mc9s), GFP_KERNEL);
+	mc9s = devm_kzalloc(&client->dev, sizeof(*mc9s), GFP_KERNEL);
 	if (!mc9s)
 		return -ENOMEM;
 
@@ -110,30 +109,16 @@ static int mc9s08dz60_probe(struct i2c_client *client,
 	mc9s->client = client;
 	i2c_set_clientdata(client, mc9s);
 
-	ret = gpiochip_add(&mc9s->chip);
-	if (ret)
-		goto error;
-
-	return 0;
-
- error:
-	kfree(mc9s);
-	return ret;
+	return gpiochip_add(&mc9s->chip);
 }
 
 static int mc9s08dz60_remove(struct i2c_client *client)
 {
 	struct mc9s08dz60 *mc9s;
-	int ret;
 
 	mc9s = i2c_get_clientdata(client);
 
-	ret = gpiochip_remove(&mc9s->chip);
-	if (!ret)
-		kfree(mc9s);
-
-	return ret;
-
+	return gpiochip_remove(&mc9s->chip);
 }
 
 static const struct i2c_device_id mc9s08dz60_id[] = {
diff --git a/drivers/gpio/gpio-ml-ioh.c b/drivers/gpio/gpio-ml-ioh.c
index db01f15..6a29ee1 100644
--- a/drivers/gpio/gpio-ml-ioh.c
+++ b/drivers/gpio/gpio-ml-ioh.c
@@ -87,8 +87,7 @@ struct ioh_gpio_reg_data {
  * @gpio_use_sel:		Save GPIO_USE_SEL1~4 register for PM
  * @ch:				Indicate GPIO channel
  * @irq_base:		Save base of IRQ number for interrupt
- * @spinlock:		Used for register access protection in
- *				interrupt context ioh_irq_type and PM;
+ * @spinlock:		Used for register access protection
  */
 struct ioh_gpio {
 	void __iomem *base;
@@ -97,7 +96,6 @@ struct ioh_gpio {
 	struct gpio_chip gpio;
 	struct ioh_gpio_reg_data ioh_gpio_reg;
 	u32 gpio_use_sel;
-	struct mutex lock;
 	int ch;
 	int irq_base;
 	spinlock_t spinlock;
@@ -109,8 +107,9 @@ static void ioh_gpio_set(struct gpio_chip *gpio, unsigned nr, int val)
 {
 	u32 reg_val;
 	struct ioh_gpio *chip =	container_of(gpio, struct ioh_gpio, gpio);
+	unsigned long flags;
 
-	mutex_lock(&chip->lock);
+	spin_lock_irqsave(&chip->spinlock, flags);
 	reg_val = ioread32(&chip->reg->regs[chip->ch].po);
 	if (val)
 		reg_val |= (1 << nr);
@@ -118,7 +117,7 @@ static void ioh_gpio_set(struct gpio_chip *gpio, unsigned nr, int val)
 		reg_val &= ~(1 << nr);
 
 	iowrite32(reg_val, &chip->reg->regs[chip->ch].po);
-	mutex_unlock(&chip->lock);
+	spin_unlock_irqrestore(&chip->spinlock, flags);
 }
 
 static int ioh_gpio_get(struct gpio_chip *gpio, unsigned nr)
@@ -134,8 +133,9 @@ static int ioh_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,
 	struct ioh_gpio *chip =	container_of(gpio, struct ioh_gpio, gpio);
 	u32 pm;
 	u32 reg_val;
+	unsigned long flags;
 
-	mutex_lock(&chip->lock);
+	spin_lock_irqsave(&chip->spinlock, flags);
 	pm = ioread32(&chip->reg->regs[chip->ch].pm) &
 					((1 << num_ports[chip->ch]) - 1);
 	pm |= (1 << nr);
@@ -148,7 +148,7 @@ static int ioh_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,
 		reg_val &= ~(1 << nr);
 	iowrite32(reg_val, &chip->reg->regs[chip->ch].po);
 
-	mutex_unlock(&chip->lock);
+	spin_unlock_irqrestore(&chip->spinlock, flags);
 
 	return 0;
 }
@@ -157,13 +157,14 @@ static int ioh_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
 {
 	struct ioh_gpio *chip =	container_of(gpio, struct ioh_gpio, gpio);
 	u32 pm;
+	unsigned long flags;
 
-	mutex_lock(&chip->lock);
+	spin_lock_irqsave(&chip->spinlock, flags);
 	pm = ioread32(&chip->reg->regs[chip->ch].pm) &
 				((1 << num_ports[chip->ch]) - 1);
 	pm &= ~(1 << nr);
 	iowrite32(pm, &chip->reg->regs[chip->ch].pm);
-	mutex_unlock(&chip->lock);
+	spin_unlock_irqrestore(&chip->spinlock, flags);
 
 	return 0;
 }
@@ -447,7 +448,6 @@ static int __devinit ioh_gpio_probe(struct pci_dev *pdev,
 		chip->base = base;
 		chip->reg = chip->base;
 		chip->ch = i;
-		mutex_init(&chip->lock);
 		spin_lock_init(&chip->spinlock);
 		ioh_gpio_setup(chip, num_ports[i]);
 		ret = gpiochip_add(&chip->gpio);
diff --git a/drivers/gpio/gpio-mpc8xxx.c b/drivers/gpio/gpio-mpc8xxx.c
index 5a1817e..9ae29cc 100644
--- a/drivers/gpio/gpio-mpc8xxx.c
+++ b/drivers/gpio/gpio-mpc8xxx.c
@@ -38,7 +38,7 @@ struct mpc8xxx_gpio_chip {
 	 */
 	u32 data;
 	struct irq_domain *irq;
-	void *of_dev_id_data;
+	const void *of_dev_id_data;
 };
 
 static inline u32 mpc8xxx_gpio2mask(unsigned int gpio)
diff --git a/drivers/gpio/gpio-msm-v2.c b/drivers/gpio/gpio-msm-v2.c
index 5cb1227..38305be 100644
--- a/drivers/gpio/gpio-msm-v2.c
+++ b/drivers/gpio/gpio-msm-v2.c
@@ -317,9 +317,7 @@ static void msm_summary_irq_handler(unsigned int irq, struct irq_desc *desc)
 
 	chained_irq_enter(chip, desc);
 
-	for (i = find_first_bit(msm_gpio.enabled_irqs, NR_GPIO_IRQS);
-	     i < NR_GPIO_IRQS;
-	     i = find_next_bit(msm_gpio.enabled_irqs, NR_GPIO_IRQS, i + 1)) {
+	for_each_set_bit(i, msm_gpio.enabled_irqs, NR_GPIO_IRQS) {
 		if (readl(GPIO_INTR_STATUS(i)) & BIT(INTR_STATUS))
 			generic_handle_irq(msm_gpio_to_irq(&msm_gpio.gpio_chip,
 							   i));
diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c
new file mode 100644
index 0000000..902af43
--- /dev/null
+++ b/drivers/gpio/gpio-mvebu.c
@@ -0,0 +1,679 @@
+/*
+ * GPIO driver for Marvell SoCs
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ * Andrew Lunn <andrew@lunn.ch>
+ * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ *
+ * This driver is a fairly straightforward GPIO driver for the
+ * complete family of Marvell EBU SoC platforms (Orion, Dove,
+ * Kirkwood, Discovery, Armada 370/XP). The only complexity of this
+ * driver is the different register layout that exists between the
+ * non-SMP platforms (Orion, Dove, Kirkwood, Armada 370) and the SMP
+ * platforms (MV78200 from the Discovery family and the Armada
+ * XP). Therefore, this driver handles three variants of the GPIO
+ * block:
+ * - the basic variant, called "orion-gpio", with the simplest
+ *   register set. Used on Orion, Dove, Kirkwoord, Armada 370 and
+ *   non-SMP Discovery systems
+ * - the mv78200 variant for MV78200 Discovery systems. This variant
+ *   turns the edge mask and level mask registers into CPU0 edge
+ *   mask/level mask registers, and adds CPU1 edge mask/level mask
+ *   registers.
+ * - the armadaxp variant for Armada XP systems. This variant keeps
+ *   the normal cause/edge mask/level mask registers when the global
+ *   interrupts are used, but adds per-CPU cause/edge mask/level mask
+ *   registers n a separate memory area for the per-CPU GPIO
+ *   interrupts.
+ */
+
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/irq.h>
+#include <linux/slab.h>
+#include <linux/irqdomain.h>
+#include <linux/io.h>
+#include <linux/of_irq.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pinctrl/consumer.h>
+
+/*
+ * GPIO unit register offsets.
+ */
+#define GPIO_OUT_OFF		0x0000
+#define GPIO_IO_CONF_OFF	0x0004
+#define GPIO_BLINK_EN_OFF	0x0008
+#define GPIO_IN_POL_OFF		0x000c
+#define GPIO_DATA_IN_OFF	0x0010
+#define GPIO_EDGE_CAUSE_OFF	0x0014
+#define GPIO_EDGE_MASK_OFF	0x0018
+#define GPIO_LEVEL_MASK_OFF	0x001c
+
+/* The MV78200 has per-CPU registers for edge mask and level mask */
+#define GPIO_EDGE_MASK_MV78200_OFF(cpu)   ((cpu) ? 0x30 : 0x18)
+#define GPIO_LEVEL_MASK_MV78200_OFF(cpu)  ((cpu) ? 0x34 : 0x1C)
+
+/* The Armada XP has per-CPU registers for interrupt cause, interrupt
+ * mask and interrupt level mask. Those are relative to the
+ * percpu_membase. */
+#define GPIO_EDGE_CAUSE_ARMADAXP_OFF(cpu) ((cpu) * 0x4)
+#define GPIO_EDGE_MASK_ARMADAXP_OFF(cpu)  (0x10 + (cpu) * 0x4)
+#define GPIO_LEVEL_MASK_ARMADAXP_OFF(cpu) (0x20 + (cpu) * 0x4)
+
+#define MVEBU_GPIO_SOC_VARIANT_ORION    0x1
+#define MVEBU_GPIO_SOC_VARIANT_MV78200  0x2
+#define MVEBU_GPIO_SOC_VARIANT_ARMADAXP 0x3
+
+#define MVEBU_MAX_GPIO_PER_BANK         32
+
+struct mvebu_gpio_chip {
+	struct gpio_chip   chip;
+	spinlock_t	   lock;
+	void __iomem	  *membase;
+	void __iomem	  *percpu_membase;
+	unsigned int       irqbase;
+	struct irq_domain *domain;
+	int                soc_variant;
+};
+
+/*
+ * Functions returning addresses of individual registers for a given
+ * GPIO controller.
+ */
+static inline void __iomem *mvebu_gpioreg_out(struct mvebu_gpio_chip *mvchip)
+{
+	return mvchip->membase + GPIO_OUT_OFF;
+}
+
+static inline void __iomem *mvebu_gpioreg_io_conf(struct mvebu_gpio_chip *mvchip)
+{
+	return mvchip->membase + GPIO_IO_CONF_OFF;
+}
+
+static inline void __iomem *mvebu_gpioreg_in_pol(struct mvebu_gpio_chip *mvchip)
+{
+	return mvchip->membase + GPIO_IN_POL_OFF;
+}
+
+static inline void __iomem *mvebu_gpioreg_data_in(struct mvebu_gpio_chip *mvchip)
+{
+	return mvchip->membase + GPIO_DATA_IN_OFF;
+}
+
+static inline void __iomem *mvebu_gpioreg_edge_cause(struct mvebu_gpio_chip *mvchip)
+{
+	int cpu;
+
+	switch(mvchip->soc_variant) {
+	case MVEBU_GPIO_SOC_VARIANT_ORION:
+	case MVEBU_GPIO_SOC_VARIANT_MV78200:
+		return mvchip->membase + GPIO_EDGE_CAUSE_OFF;
+	case MVEBU_GPIO_SOC_VARIANT_ARMADAXP:
+		cpu = smp_processor_id();
+		return mvchip->percpu_membase + GPIO_EDGE_CAUSE_ARMADAXP_OFF(cpu);
+	default:
+		BUG();
+	}
+}
+
+static inline void __iomem *mvebu_gpioreg_edge_mask(struct mvebu_gpio_chip *mvchip)
+{
+	int cpu;
+
+	switch(mvchip->soc_variant) {
+	case MVEBU_GPIO_SOC_VARIANT_ORION:
+		return mvchip->membase + GPIO_EDGE_MASK_OFF;
+	case MVEBU_GPIO_SOC_VARIANT_MV78200:
+		cpu = smp_processor_id();
+		return mvchip->membase + GPIO_EDGE_MASK_MV78200_OFF(cpu);
+	case MVEBU_GPIO_SOC_VARIANT_ARMADAXP:
+		cpu = smp_processor_id();
+		return mvchip->percpu_membase + GPIO_EDGE_MASK_ARMADAXP_OFF(cpu);
+	default:
+		BUG();
+	}
+}
+
+static void __iomem *mvebu_gpioreg_level_mask(struct mvebu_gpio_chip *mvchip)
+{
+	int cpu;
+
+	switch(mvchip->soc_variant) {
+	case MVEBU_GPIO_SOC_VARIANT_ORION:
+		return mvchip->membase + GPIO_LEVEL_MASK_OFF;
+	case MVEBU_GPIO_SOC_VARIANT_MV78200:
+		cpu = smp_processor_id();
+		return mvchip->membase + GPIO_LEVEL_MASK_MV78200_OFF(cpu);
+	case MVEBU_GPIO_SOC_VARIANT_ARMADAXP:
+		cpu = smp_processor_id();
+		return mvchip->percpu_membase + GPIO_LEVEL_MASK_ARMADAXP_OFF(cpu);
+	default:
+		BUG();
+	}
+}
+
+/*
+ * Functions implementing the gpio_chip methods
+ */
+
+int mvebu_gpio_request(struct gpio_chip *chip, unsigned pin)
+{
+	return pinctrl_request_gpio(chip->base + pin);
+}
+
+void mvebu_gpio_free(struct gpio_chip *chip, unsigned pin)
+{
+	pinctrl_free_gpio(chip->base + pin);
+}
+
+static void mvebu_gpio_set(struct gpio_chip *chip, unsigned pin, int value)
+{
+	struct mvebu_gpio_chip *mvchip =
+		container_of(chip, struct mvebu_gpio_chip, chip);
+	unsigned long flags;
+	u32 u;
+
+	spin_lock_irqsave(&mvchip->lock, flags);
+	u = readl_relaxed(mvebu_gpioreg_out(mvchip));
+	if (value)
+		u |= 1 << pin;
+	else
+		u &= ~(1 << pin);
+	writel_relaxed(u, mvebu_gpioreg_out(mvchip));
+	spin_unlock_irqrestore(&mvchip->lock, flags);
+}
+
+static int mvebu_gpio_get(struct gpio_chip *chip, unsigned pin)
+{
+	struct mvebu_gpio_chip *mvchip =
+		container_of(chip, struct mvebu_gpio_chip, chip);
+	u32 u;
+
+	if (readl_relaxed(mvebu_gpioreg_io_conf(mvchip)) & (1 << pin)) {
+		u = readl_relaxed(mvebu_gpioreg_data_in(mvchip)) ^
+			readl_relaxed(mvebu_gpioreg_in_pol(mvchip));
+	} else {
+		u = readl_relaxed(mvebu_gpioreg_out(mvchip));
+	}
+
+	return (u >> pin) & 1;
+}
+
+static int mvebu_gpio_direction_input(struct gpio_chip *chip, unsigned pin)
+{
+	struct mvebu_gpio_chip *mvchip =
+		container_of(chip, struct mvebu_gpio_chip, chip);
+	unsigned long flags;
+	int ret;
+	u32 u;
+
+	/* Check with the pinctrl driver whether this pin is usable as
+	 * an input GPIO */
+	ret = pinctrl_gpio_direction_input(chip->base + pin);
+	if (ret)
+		return ret;
+
+	spin_lock_irqsave(&mvchip->lock, flags);
+	u = readl_relaxed(mvebu_gpioreg_io_conf(mvchip));
+	u |= 1 << pin;
+	writel_relaxed(u, mvebu_gpioreg_io_conf(mvchip));
+	spin_unlock_irqrestore(&mvchip->lock, flags);
+
+	return 0;
+}
+
+static int mvebu_gpio_direction_output(struct gpio_chip *chip, unsigned pin,
+				       int value)
+{
+	struct mvebu_gpio_chip *mvchip =
+		container_of(chip, struct mvebu_gpio_chip, chip);
+	unsigned long flags;
+	int ret;
+	u32 u;
+
+	/* Check with the pinctrl driver whether this pin is usable as
+	 * an output GPIO */
+	ret = pinctrl_gpio_direction_output(chip->base + pin);
+	if (ret)
+		return ret;
+
+	spin_lock_irqsave(&mvchip->lock, flags);
+	u = readl_relaxed(mvebu_gpioreg_io_conf(mvchip));
+	u &= ~(1 << pin);
+	writel_relaxed(u, mvebu_gpioreg_io_conf(mvchip));
+	spin_unlock_irqrestore(&mvchip->lock, flags);
+
+	return 0;
+}
+
+static int mvebu_gpio_to_irq(struct gpio_chip *chip, unsigned pin)
+{
+	struct mvebu_gpio_chip *mvchip =
+		container_of(chip, struct mvebu_gpio_chip, chip);
+	return irq_create_mapping(mvchip->domain, pin);
+}
+
+/*
+ * Functions implementing the irq_chip methods
+ */
+static void mvebu_gpio_irq_ack(struct irq_data *d)
+{
+	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+	struct mvebu_gpio_chip *mvchip = gc->private;
+	u32 mask = ~(1 << (d->irq - gc->irq_base));
+
+	irq_gc_lock(gc);
+	writel_relaxed(mask, mvebu_gpioreg_edge_cause(mvchip));
+	irq_gc_unlock(gc);
+}
+
+static void mvebu_gpio_edge_irq_mask(struct irq_data *d)
+{
+	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+	struct mvebu_gpio_chip *mvchip = gc->private;
+	u32 mask = 1 << (d->irq - gc->irq_base);
+
+	irq_gc_lock(gc);
+	gc->mask_cache &= ~mask;
+	writel_relaxed(gc->mask_cache, mvebu_gpioreg_edge_mask(mvchip));
+	irq_gc_unlock(gc);
+}
+
+static void mvebu_gpio_edge_irq_unmask(struct irq_data *d)
+{
+	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+	struct mvebu_gpio_chip *mvchip = gc->private;
+	u32 mask = 1 << (d->irq - gc->irq_base);
+
+	irq_gc_lock(gc);
+	gc->mask_cache |= mask;
+	writel_relaxed(gc->mask_cache, mvebu_gpioreg_edge_mask(mvchip));
+	irq_gc_unlock(gc);
+}
+
+static void mvebu_gpio_level_irq_mask(struct irq_data *d)
+{
+	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+	struct mvebu_gpio_chip *mvchip = gc->private;
+	u32 mask = 1 << (d->irq - gc->irq_base);
+
+	irq_gc_lock(gc);
+	gc->mask_cache &= ~mask;
+	writel_relaxed(gc->mask_cache, mvebu_gpioreg_level_mask(mvchip));
+	irq_gc_unlock(gc);
+}
+
+static void mvebu_gpio_level_irq_unmask(struct irq_data *d)
+{
+	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+	struct mvebu_gpio_chip *mvchip = gc->private;
+	u32 mask = 1 << (d->irq - gc->irq_base);
+
+	irq_gc_lock(gc);
+	gc->mask_cache |= mask;
+	writel_relaxed(gc->mask_cache, mvebu_gpioreg_level_mask(mvchip));
+	irq_gc_unlock(gc);
+}
+
+/*****************************************************************************
+ * MVEBU GPIO IRQ
+ *
+ * GPIO_IN_POL register controls whether GPIO_DATA_IN will hold the same
+ * value of the line or the opposite value.
+ *
+ * Level IRQ handlers: DATA_IN is used directly as cause register.
+ *                     Interrupt are masked by LEVEL_MASK registers.
+ * Edge IRQ handlers:  Change in DATA_IN are latched in EDGE_CAUSE.
+ *                     Interrupt are masked by EDGE_MASK registers.
+ * Both-edge handlers: Similar to regular Edge handlers, but also swaps
+ *                     the polarity to catch the next line transaction.
+ *                     This is a race condition that might not perfectly
+ *                     work on some use cases.
+ *
+ * Every eight GPIO lines are grouped (OR'ed) before going up to main
+ * cause register.
+ *
+ *                    EDGE  cause    mask
+ *        data-in   /--------| |-----| |----\
+ *     -----| |-----                         ---- to main cause reg
+ *           X      \----------------| |----/
+ *        polarity    LEVEL          mask
+ *
+ ****************************************************************************/
+
+static int mvebu_gpio_irq_set_type(struct irq_data *d, unsigned int type)
+{
+	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+	struct irq_chip_type *ct = irq_data_get_chip_type(d);
+	struct mvebu_gpio_chip *mvchip = gc->private;
+	int pin;
+	u32 u;
+
+	pin = d->hwirq;
+
+	u = readl_relaxed(mvebu_gpioreg_io_conf(mvchip)) & (1 << pin);
+	if (!u) {
+		return -EINVAL;
+	}
+
+	type &= IRQ_TYPE_SENSE_MASK;
+	if (type == IRQ_TYPE_NONE)
+		return -EINVAL;
+
+	/* Check if we need to change chip and handler */
+	if (!(ct->type & type))
+		if (irq_setup_alt_chip(d, type))
+			return -EINVAL;
+
+	/*
+	 * Configure interrupt polarity.
+	 */
+	switch(type) {
+	case IRQ_TYPE_EDGE_RISING:
+	case IRQ_TYPE_LEVEL_HIGH:
+		u = readl_relaxed(mvebu_gpioreg_in_pol(mvchip));
+		u &= ~(1 << pin);
+		writel_relaxed(u, mvebu_gpioreg_in_pol(mvchip));
+	case IRQ_TYPE_EDGE_FALLING:
+	case IRQ_TYPE_LEVEL_LOW:
+		u = readl_relaxed(mvebu_gpioreg_in_pol(mvchip));
+		u |= 1 << pin;
+		writel_relaxed(u, mvebu_gpioreg_in_pol(mvchip));
+	case IRQ_TYPE_EDGE_BOTH: {
+		u32 v;
+
+		v = readl_relaxed(mvebu_gpioreg_in_pol(mvchip)) ^
+			readl_relaxed(mvebu_gpioreg_data_in(mvchip));
+
+		/*
+		 * set initial polarity based on current input level
+		 */
+		u = readl_relaxed(mvebu_gpioreg_in_pol(mvchip));
+		if (v & (1 << pin))
+			u |= 1 << pin;		/* falling */
+		else
+			u &= ~(1 << pin);	/* rising */
+		writel_relaxed(u, mvebu_gpioreg_in_pol(mvchip));
+	}
+	}
+	return 0;
+}
+
+static void mvebu_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+	struct mvebu_gpio_chip *mvchip = irq_get_handler_data(irq);
+	u32 cause, type;
+	int i;
+
+	if (mvchip == NULL)
+		return;
+
+	cause = readl_relaxed(mvebu_gpioreg_data_in(mvchip)) &
+		readl_relaxed(mvebu_gpioreg_level_mask(mvchip));
+	cause |= readl_relaxed(mvebu_gpioreg_edge_cause(mvchip)) &
+		readl_relaxed(mvebu_gpioreg_edge_mask(mvchip));
+
+	for (i = 0; i < mvchip->chip.ngpio; i++) {
+		int irq;
+
+		irq = mvchip->irqbase + i;
+
+		if (!(cause & (1 << i)))
+			continue;
+
+		type = irqd_get_trigger_type(irq_get_irq_data(irq));
+		if ((type & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) {
+			/* Swap polarity (race with GPIO line) */
+			u32 polarity;
+
+			polarity = readl_relaxed(mvebu_gpioreg_in_pol(mvchip));
+			polarity ^= 1 << i;
+			writel_relaxed(polarity, mvebu_gpioreg_in_pol(mvchip));
+		}
+		generic_handle_irq(irq);
+	}
+}
+
+static struct platform_device_id mvebu_gpio_ids[] = {
+	{
+		.name = "orion-gpio",
+	}, {
+		.name = "mv78200-gpio",
+	}, {
+		.name = "armadaxp-gpio",
+	}, {
+		/* sentinel */
+	},
+};
+MODULE_DEVICE_TABLE(platform, mvebu_gpio_ids);
+
+static struct of_device_id mvebu_gpio_of_match[] __devinitdata = {
+	{
+		.compatible = "marvell,orion-gpio",
+		.data       = (void*) MVEBU_GPIO_SOC_VARIANT_ORION,
+	},
+	{
+		.compatible = "marvell,mv78200-gpio",
+		.data       = (void*) MVEBU_GPIO_SOC_VARIANT_MV78200,
+	},
+	{
+		.compatible = "marvell,armadaxp-gpio",
+		.data       = (void*) MVEBU_GPIO_SOC_VARIANT_ARMADAXP,
+	},
+	{
+		/* sentinel */
+	},
+};
+MODULE_DEVICE_TABLE(of, mvebu_gpio_of_match);
+
+static int __devinit mvebu_gpio_probe(struct platform_device *pdev)
+{
+	struct mvebu_gpio_chip *mvchip;
+	const struct of_device_id *match;
+	struct device_node *np = pdev->dev.of_node;
+	struct resource *res;
+	struct irq_chip_generic *gc;
+	struct irq_chip_type *ct;
+	unsigned int ngpios;
+	int soc_variant;
+	int i, cpu, id;
+
+	match = of_match_device(mvebu_gpio_of_match, &pdev->dev);
+	if (match)
+		soc_variant = (int) match->data;
+	else
+		soc_variant = MVEBU_GPIO_SOC_VARIANT_ORION;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (! res) {
+		dev_err(&pdev->dev, "Cannot get memory resource\n");
+		return -ENODEV;
+	}
+
+	mvchip = devm_kzalloc(&pdev->dev, sizeof(struct mvebu_gpio_chip), GFP_KERNEL);
+	if (! mvchip){
+		dev_err(&pdev->dev, "Cannot allocate memory\n");
+		return -ENOMEM;
+	}
+
+	if (of_property_read_u32(pdev->dev.of_node, "ngpios", &ngpios)) {
+		dev_err(&pdev->dev, "Missing ngpios OF property\n");
+		return -ENODEV;
+	}
+
+	id = of_alias_get_id(pdev->dev.of_node, "gpio");
+	if (id < 0) {
+		dev_err(&pdev->dev, "Couldn't get OF id\n");
+		return id;
+	}
+
+	mvchip->soc_variant = soc_variant;
+	mvchip->chip.label = dev_name(&pdev->dev);
+	mvchip->chip.dev = &pdev->dev;
+	mvchip->chip.request = mvebu_gpio_request;
+	mvchip->chip.direction_input = mvebu_gpio_direction_input;
+	mvchip->chip.get = mvebu_gpio_get;
+	mvchip->chip.direction_output = mvebu_gpio_direction_output;
+	mvchip->chip.set = mvebu_gpio_set;
+	mvchip->chip.to_irq = mvebu_gpio_to_irq;
+	mvchip->chip.base = id * MVEBU_MAX_GPIO_PER_BANK;
+	mvchip->chip.ngpio = ngpios;
+	mvchip->chip.can_sleep = 0;
+#ifdef CONFIG_OF
+	mvchip->chip.of_node = np;
+#endif
+
+	spin_lock_init(&mvchip->lock);
+	mvchip->membase = devm_request_and_ioremap(&pdev->dev, res);
+	if (! mvchip->membase) {
+		dev_err(&pdev->dev, "Cannot ioremap\n");
+		kfree(mvchip->chip.label);
+		return -ENOMEM;
+	}
+
+	/* The Armada XP has a second range of registers for the
+	 * per-CPU registers */
+	if (soc_variant == MVEBU_GPIO_SOC_VARIANT_ARMADAXP) {
+		res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+		if (! res) {
+			dev_err(&pdev->dev, "Cannot get memory resource\n");
+			kfree(mvchip->chip.label);
+			return -ENODEV;
+		}
+
+		mvchip->percpu_membase = devm_request_and_ioremap(&pdev->dev, res);
+		if (! mvchip->percpu_membase) {
+			dev_err(&pdev->dev, "Cannot ioremap\n");
+			kfree(mvchip->chip.label);
+			return -ENOMEM;
+		}
+	}
+
+	/*
+	 * Mask and clear GPIO interrupts.
+	 */
+	switch(soc_variant) {
+	case MVEBU_GPIO_SOC_VARIANT_ORION:
+		writel_relaxed(0, mvchip->membase + GPIO_EDGE_CAUSE_OFF);
+		writel_relaxed(0, mvchip->membase + GPIO_EDGE_MASK_OFF);
+		writel_relaxed(0, mvchip->membase + GPIO_LEVEL_MASK_OFF);
+		break;
+	case MVEBU_GPIO_SOC_VARIANT_MV78200:
+		writel_relaxed(0, mvchip->membase + GPIO_EDGE_CAUSE_OFF);
+		for (cpu = 0; cpu < 2; cpu++) {
+			writel_relaxed(0, mvchip->membase +
+				       GPIO_EDGE_MASK_MV78200_OFF(cpu));
+			writel_relaxed(0, mvchip->membase +
+				       GPIO_LEVEL_MASK_MV78200_OFF(cpu));
+		}
+		break;
+	case MVEBU_GPIO_SOC_VARIANT_ARMADAXP:
+		writel_relaxed(0, mvchip->membase + GPIO_EDGE_CAUSE_OFF);
+		writel_relaxed(0, mvchip->membase + GPIO_EDGE_MASK_OFF);
+		writel_relaxed(0, mvchip->membase + GPIO_LEVEL_MASK_OFF);
+		for (cpu = 0; cpu < 4; cpu++) {
+			writel_relaxed(0, mvchip->percpu_membase +
+				       GPIO_EDGE_CAUSE_ARMADAXP_OFF(cpu));
+			writel_relaxed(0, mvchip->percpu_membase +
+				       GPIO_EDGE_MASK_ARMADAXP_OFF(cpu));
+			writel_relaxed(0, mvchip->percpu_membase +
+				       GPIO_LEVEL_MASK_ARMADAXP_OFF(cpu));
+		}
+		break;
+	default:
+		BUG();
+	}
+
+	gpiochip_add(&mvchip->chip);
+
+	/* Some gpio controllers do not provide irq support */
+	if (!of_irq_count(np))
+		return 0;
+
+	/* Setup the interrupt handlers. Each chip can have up to 4
+	 * interrupt handlers, with each handler dealing with 8 GPIO
+	 * pins. */
+	for (i = 0; i < 4; i++) {
+		int irq;
+		irq = platform_get_irq(pdev, i);
+		if (irq < 0)
+			continue;
+		irq_set_handler_data(irq, mvchip);
+		irq_set_chained_handler(irq, mvebu_gpio_irq_handler);
+	}
+
+	mvchip->irqbase = irq_alloc_descs(-1, 0, ngpios, -1);
+	if (mvchip->irqbase < 0) {
+		dev_err(&pdev->dev, "no irqs\n");
+		kfree(mvchip->chip.label);
+		return -ENOMEM;
+	}
+
+	gc = irq_alloc_generic_chip("mvebu_gpio_irq", 2, mvchip->irqbase,
+				    mvchip->membase, handle_level_irq);
+	if (! gc) {
+		dev_err(&pdev->dev, "Cannot allocate generic irq_chip\n");
+		kfree(mvchip->chip.label);
+		return -ENOMEM;
+	}
+
+	gc->private = mvchip;
+	ct = &gc->chip_types[0];
+	ct->type = IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW;
+	ct->chip.irq_mask = mvebu_gpio_level_irq_mask;
+	ct->chip.irq_unmask = mvebu_gpio_level_irq_unmask;
+	ct->chip.irq_set_type = mvebu_gpio_irq_set_type;
+	ct->chip.name = mvchip->chip.label;
+
+	ct = &gc->chip_types[1];
+	ct->type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
+	ct->chip.irq_ack = mvebu_gpio_irq_ack;
+	ct->chip.irq_mask = mvebu_gpio_edge_irq_mask;
+	ct->chip.irq_unmask = mvebu_gpio_edge_irq_unmask;
+	ct->chip.irq_set_type = mvebu_gpio_irq_set_type;
+	ct->handler = handle_edge_irq;
+	ct->chip.name = mvchip->chip.label;
+
+	irq_setup_generic_chip(gc, IRQ_MSK(ngpios), IRQ_GC_INIT_MASK_CACHE,
+			       IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE);
+
+	/* Setup irq domain on top of the generic chip. */
+	mvchip->domain = irq_domain_add_legacy(np, mvchip->chip.ngpio,
+					       mvchip->irqbase, 0,
+					       &irq_domain_simple_ops,
+					       mvchip);
+	if (!mvchip->domain) {
+		dev_err(&pdev->dev, "couldn't allocate irq domain %s (DT).\n",
+			mvchip->chip.label);
+		irq_remove_generic_chip(gc, IRQ_MSK(ngpios), IRQ_NOREQUEST,
+					IRQ_LEVEL | IRQ_NOPROBE);
+		kfree(gc);
+		kfree(mvchip->chip.label);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static struct platform_driver mvebu_gpio_driver = {
+	.driver		= {
+		.name	        = "mvebu-gpio",
+		.owner	        = THIS_MODULE,
+		.of_match_table = mvebu_gpio_of_match,
+	},
+	.probe		= mvebu_gpio_probe,
+	.id_table	= mvebu_gpio_ids,
+};
+
+static int __init mvebu_gpio_init(void)
+{
+	return platform_driver_register(&mvebu_gpio_driver);
+}
+postcore_initcall(mvebu_gpio_init);
diff --git a/drivers/gpio/gpio-mxs.c b/drivers/gpio/gpio-mxs.c
index 39e4956..796fb13 100644
--- a/drivers/gpio/gpio-mxs.c
+++ b/drivers/gpio/gpio-mxs.c
@@ -24,6 +24,7 @@
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/irq.h>
+#include <linux/irqdomain.h>
 #include <linux/gpio.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
@@ -52,8 +53,6 @@
 #define GPIO_INT_LEV_MASK	(1 << 0)
 #define GPIO_INT_POL_MASK	(1 << 1)
 
-#define irq_to_gpio(irq)	((irq) - MXS_GPIO_IRQ_START)
-
 enum mxs_gpio_id {
 	IMX23_GPIO,
 	IMX28_GPIO,
@@ -63,7 +62,7 @@ struct mxs_gpio_port {
 	void __iomem *base;
 	int id;
 	int irq;
-	int virtual_irq_start;
+	struct irq_domain *domain;
 	struct bgpio_chip bgc;
 	enum mxs_gpio_id devid;
 };
@@ -82,8 +81,7 @@ static inline int is_imx28_gpio(struct mxs_gpio_port *port)
 
 static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type)
 {
-	u32 gpio = irq_to_gpio(d->irq);
-	u32 pin_mask = 1 << (gpio & 31);
+	u32 pin_mask = 1 << d->hwirq;
 	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
 	struct mxs_gpio_port *port = gc->private;
 	void __iomem *pin_addr;
@@ -120,7 +118,7 @@ static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type)
 	else
 		writel(pin_mask, pin_addr + MXS_CLR);
 
-	writel(1 << (gpio & 0x1f),
+	writel(pin_mask,
 	       port->base + PINCTRL_IRQSTAT(port) + MXS_CLR);
 
 	return 0;
@@ -131,7 +129,6 @@ static void mxs_gpio_irq_handler(u32 irq, struct irq_desc *desc)
 {
 	u32 irq_stat;
 	struct mxs_gpio_port *port = irq_get_handler_data(irq);
-	u32 gpio_irq_no_base = port->virtual_irq_start;
 
 	desc->irq_data.chip->irq_ack(&desc->irq_data);
 
@@ -140,7 +137,7 @@ static void mxs_gpio_irq_handler(u32 irq, struct irq_desc *desc)
 
 	while (irq_stat != 0) {
 		int irqoffset = fls(irq_stat) - 1;
-		generic_handle_irq(gpio_irq_no_base + irqoffset);
+		generic_handle_irq(irq_find_mapping(port->domain, irqoffset));
 		irq_stat &= ~(1 << irqoffset);
 	}
 }
@@ -167,12 +164,12 @@ static int mxs_gpio_set_wake_irq(struct irq_data *d, unsigned int enable)
 	return 0;
 }
 
-static void __init mxs_gpio_init_gc(struct mxs_gpio_port *port)
+static void __init mxs_gpio_init_gc(struct mxs_gpio_port *port, int irq_base)
 {
 	struct irq_chip_generic *gc;
 	struct irq_chip_type *ct;
 
-	gc = irq_alloc_generic_chip("gpio-mxs", 1, port->virtual_irq_start,
+	gc = irq_alloc_generic_chip("gpio-mxs", 1, irq_base,
 				    port->base, handle_level_irq);
 	gc->private = port;
 
@@ -194,7 +191,7 @@ static int mxs_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
 	struct mxs_gpio_port *port =
 		container_of(bgc, struct mxs_gpio_port, bgc);
 
-	return port->virtual_irq_start + offset;
+	return irq_find_mapping(port->domain, offset);
 }
 
 static struct platform_device_id mxs_gpio_ids[] = {
@@ -226,6 +223,7 @@ static int __devinit mxs_gpio_probe(struct platform_device *pdev)
 	static void __iomem *base;
 	struct mxs_gpio_port *port;
 	struct resource *iores = NULL;
+	int irq_base;
 	int err;
 
 	port = devm_kzalloc(&pdev->dev, sizeof(*port), GFP_KERNEL);
@@ -241,7 +239,6 @@ static int __devinit mxs_gpio_probe(struct platform_device *pdev)
 		port->id = pdev->id;
 		port->devid = pdev->id_entry->driver_data;
 	}
-	port->virtual_irq_start = MXS_GPIO_IRQ_START + port->id * 32;
 
 	port->irq = platform_get_irq(pdev, 0);
 	if (port->irq < 0)
@@ -275,8 +272,19 @@ static int __devinit mxs_gpio_probe(struct platform_device *pdev)
 	/* clear address has to be used to clear IRQSTAT bits */
 	writel(~0U, port->base + PINCTRL_IRQSTAT(port) + MXS_CLR);
 
+	irq_base = irq_alloc_descs(-1, 0, 32, numa_node_id());
+	if (irq_base < 0)
+		return irq_base;
+
+	port->domain = irq_domain_add_legacy(np, 32, irq_base, 0,
+					     &irq_domain_simple_ops, NULL);
+	if (!port->domain) {
+		err = -ENODEV;
+		goto out_irqdesc_free;
+	}
+
 	/* gpio-mxs can be a generic irq chip */
-	mxs_gpio_init_gc(port);
+	mxs_gpio_init_gc(port, irq_base);
 
 	/* setup one handler for each entry */
 	irq_set_chained_handler(port->irq, mxs_gpio_irq_handler);
@@ -287,18 +295,22 @@ static int __devinit mxs_gpio_probe(struct platform_device *pdev)
 			 port->base + PINCTRL_DOUT(port), NULL,
 			 port->base + PINCTRL_DOE(port), NULL, 0);
 	if (err)
-		return err;
+		goto out_irqdesc_free;
 
 	port->bgc.gc.to_irq = mxs_gpio_to_irq;
 	port->bgc.gc.base = port->id * 32;
 
 	err = gpiochip_add(&port->bgc.gc);
-	if (err) {
-		bgpio_remove(&port->bgc);
-		return err;
-	}
+	if (err)
+		goto out_bgpio_remove;
 
 	return 0;
+
+out_bgpio_remove:
+	bgpio_remove(&port->bgc);
+out_irqdesc_free:
+	irq_free_descs(irq_base, 32);
+	return err;
 }
 
 static struct platform_driver mxs_gpio_driver = {
diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c
index e6efd77..94cbc84 100644
--- a/drivers/gpio/gpio-omap.c
+++ b/drivers/gpio/gpio-omap.c
@@ -25,11 +25,9 @@
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/irqdomain.h>
+#include <linux/gpio.h>
+#include <linux/platform_data/gpio-omap.h>
 
-#include <mach/hardware.h>
-#include <asm/irq.h>
-#include <mach/irqs.h>
-#include <asm/gpio.h>
 #include <asm/mach/irq.h>
 
 #define OFF_MODE	1
@@ -385,13 +383,16 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio,
 static int gpio_irq_type(struct irq_data *d, unsigned type)
 {
 	struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
-	unsigned gpio;
+	unsigned gpio = 0;
 	int retval;
 	unsigned long flags;
 
-	if (!cpu_class_is_omap2() && d->irq > IH_MPUIO_BASE)
+#ifdef CONFIG_ARCH_OMAP1
+	if (d->irq > IH_MPUIO_BASE)
 		gpio = OMAP_MPUIO(d->irq - IH_MPUIO_BASE);
-	else
+#endif
+
+	if (!gpio)
 		gpio = irq_to_gpio(bank, d->irq);
 
 	if (type & ~IRQ_TYPE_SENSE_MASK)
@@ -1058,7 +1059,7 @@ static int __devinit omap_gpio_probe(struct platform_device *pdev)
 	struct device *dev = &pdev->dev;
 	struct device_node *node = dev->of_node;
 	const struct of_device_id *match;
-	struct omap_gpio_platform_data *pdata;
+	const struct omap_gpio_platform_data *pdata;
 	struct resource *res;
 	struct gpio_bank *bank;
 	int ret = 0;
@@ -1440,19 +1441,19 @@ static struct omap_gpio_reg_offs omap4_gpio_regs = {
 	.fallingdetect =	OMAP4_GPIO_FALLINGDETECT,
 };
 
-static struct omap_gpio_platform_data omap2_pdata = {
+const static struct omap_gpio_platform_data omap2_pdata = {
 	.regs = &omap2_gpio_regs,
 	.bank_width = 32,
 	.dbck_flag = false,
 };
 
-static struct omap_gpio_platform_data omap3_pdata = {
+const static struct omap_gpio_platform_data omap3_pdata = {
 	.regs = &omap2_gpio_regs,
 	.bank_width = 32,
 	.dbck_flag = true,
 };
 
-static struct omap_gpio_platform_data omap4_pdata = {
+const static struct omap_gpio_platform_data omap4_pdata = {
 	.regs = &omap4_gpio_regs,
 	.bank_width = 32,
 	.dbck_flag = true,
diff --git a/drivers/gpio/gpio-pcf857x.c b/drivers/gpio/gpio-pcf857x.c
index 076e236..16af35c 100644
--- a/drivers/gpio/gpio-pcf857x.c
+++ b/drivers/gpio/gpio-pcf857x.c
@@ -23,7 +23,12 @@
 #include <linux/gpio.h>
 #include <linux/i2c.h>
 #include <linux/i2c/pcf857x.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
 #include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
 
 
 static const struct i2c_device_id pcf857x_id[] = {
@@ -60,7 +65,12 @@ struct pcf857x {
 	struct gpio_chip	chip;
 	struct i2c_client	*client;
 	struct mutex		lock;		/* protect 'out' */
+	struct work_struct	work;		/* irq demux work */
+	struct irq_domain	*irq_domain;	/* for irq demux  */
+	spinlock_t		slock;		/* protect irq demux */
 	unsigned		out;		/* software latch */
+	unsigned		status;		/* current status */
+	int			irq;		/* real irq number */
 
 	int (*write)(struct i2c_client *client, unsigned data);
 	int (*read)(struct i2c_client *client);
@@ -150,6 +160,100 @@ static void pcf857x_set(struct gpio_chip *chip, unsigned offset, int value)
 
 /*-------------------------------------------------------------------------*/
 
+static int pcf857x_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+	struct pcf857x *gpio = container_of(chip, struct pcf857x, chip);
+
+	return irq_create_mapping(gpio->irq_domain, offset);
+}
+
+static void pcf857x_irq_demux_work(struct work_struct *work)
+{
+	struct pcf857x *gpio = container_of(work,
+					       struct pcf857x,
+					       work);
+	unsigned long change, i, status, flags;
+
+	status = gpio->read(gpio->client);
+
+	spin_lock_irqsave(&gpio->slock, flags);
+
+	change = gpio->status ^ status;
+	for_each_set_bit(i, &change, gpio->chip.ngpio)
+		generic_handle_irq(irq_find_mapping(gpio->irq_domain, i));
+	gpio->status = status;
+
+	spin_unlock_irqrestore(&gpio->slock, flags);
+}
+
+static irqreturn_t pcf857x_irq_demux(int irq, void *data)
+{
+	struct pcf857x	*gpio = data;
+
+	/*
+	 * pcf857x can't read/write data here,
+	 * since i2c data access might go to sleep.
+	 */
+	schedule_work(&gpio->work);
+
+	return IRQ_HANDLED;
+}
+
+static int pcf857x_irq_domain_map(struct irq_domain *domain, unsigned int virq,
+				 irq_hw_number_t hw)
+{
+	irq_set_chip_and_handler(virq,
+				 &dummy_irq_chip,
+				 handle_level_irq);
+	return 0;
+}
+
+static struct irq_domain_ops pcf857x_irq_domain_ops = {
+	.map	= pcf857x_irq_domain_map,
+};
+
+static void pcf857x_irq_domain_cleanup(struct pcf857x *gpio)
+{
+	if (gpio->irq_domain)
+		irq_domain_remove(gpio->irq_domain);
+
+	if (gpio->irq)
+		free_irq(gpio->irq, gpio);
+}
+
+static int pcf857x_irq_domain_init(struct pcf857x *gpio,
+				   struct pcf857x_platform_data *pdata,
+				   struct device *dev)
+{
+	int status;
+
+	gpio->irq_domain = irq_domain_add_linear(dev->of_node,
+						 gpio->chip.ngpio,
+						 &pcf857x_irq_domain_ops,
+						 NULL);
+	if (!gpio->irq_domain)
+		goto fail;
+
+	/* enable real irq */
+	status = request_irq(pdata->irq, pcf857x_irq_demux, 0,
+			     dev_name(dev), gpio);
+	if (status)
+		goto fail;
+
+	/* enable gpio_to_irq() */
+	INIT_WORK(&gpio->work, pcf857x_irq_demux_work);
+	gpio->chip.to_irq	= pcf857x_to_irq;
+	gpio->irq		= pdata->irq;
+
+	return 0;
+
+fail:
+	pcf857x_irq_domain_cleanup(gpio);
+	return -EINVAL;
+}
+
+/*-------------------------------------------------------------------------*/
+
 static int pcf857x_probe(struct i2c_client *client,
 			 const struct i2c_device_id *id)
 {
@@ -168,6 +272,7 @@ static int pcf857x_probe(struct i2c_client *client,
 		return -ENOMEM;
 
 	mutex_init(&gpio->lock);
+	spin_lock_init(&gpio->slock);
 
 	gpio->chip.base			= pdata ? pdata->gpio_base : -1;
 	gpio->chip.can_sleep		= 1;
@@ -179,6 +284,15 @@ static int pcf857x_probe(struct i2c_client *client,
 	gpio->chip.direction_output	= pcf857x_output;
 	gpio->chip.ngpio		= id->driver_data;
 
+	/* enable gpio_to_irq() if platform has settings */
+	if (pdata && pdata->irq) {
+		status = pcf857x_irq_domain_init(gpio, pdata, &client->dev);
+		if (status < 0) {
+			dev_err(&client->dev, "irq_domain init failed\n");
+			goto fail;
+		}
+	}
+
 	/* NOTE:  the OnSemi jlc1562b is also largely compatible with
 	 * these parts, notably for output.  It has a low-resolution
 	 * DAC instead of pin change IRQs; and its inputs can be the
@@ -248,6 +362,7 @@ static int pcf857x_probe(struct i2c_client *client,
 	 * all-ones reset state.  Otherwise it flags pins to be driven low.
 	 */
 	gpio->out = pdata ? ~pdata->n_latch : ~0;
+	gpio->status = gpio->out;
 
 	status = gpiochip_add(&gpio->chip);
 	if (status < 0)
@@ -278,6 +393,10 @@ static int pcf857x_probe(struct i2c_client *client,
 fail:
 	dev_dbg(&client->dev, "probe error %d for '%s'\n",
 			status, client->name);
+
+	if (pdata && pdata->irq)
+		pcf857x_irq_domain_cleanup(gpio);
+
 	kfree(gpio);
 	return status;
 }
@@ -299,6 +418,9 @@ static int pcf857x_remove(struct i2c_client *client)
 		}
 	}
 
+	if (pdata && pdata->irq)
+		pcf857x_irq_domain_cleanup(gpio);
+
 	status = gpiochip_remove(&gpio->chip);
 	if (status == 0)
 		kfree(gpio);
diff --git a/drivers/gpio/gpio-pch.c b/drivers/gpio/gpio-pch.c
index 139ad3e..4ad0c4f 100644
--- a/drivers/gpio/gpio-pch.c
+++ b/drivers/gpio/gpio-pch.c
@@ -92,9 +92,7 @@ struct pch_gpio_reg_data {
  * @lock:			Used for register access protection
  * @irq_base:		Save base of IRQ number for interrupt
  * @ioh:		IOH ID
- * @spinlock:		Used for register access protection in
- *				interrupt context pch_irq_mask,
- *				pch_irq_unmask and pch_irq_type;
+ * @spinlock:		Used for register access protection
  */
 struct pch_gpio {
 	void __iomem *base;
@@ -102,7 +100,6 @@ struct pch_gpio {
 	struct device *dev;
 	struct gpio_chip gpio;
 	struct pch_gpio_reg_data pch_gpio_reg;
-	struct mutex lock;
 	int irq_base;
 	enum pch_type_t ioh;
 	spinlock_t spinlock;
@@ -112,8 +109,9 @@ static void pch_gpio_set(struct gpio_chip *gpio, unsigned nr, int val)
 {
 	u32 reg_val;
 	struct pch_gpio *chip =	container_of(gpio, struct pch_gpio, gpio);
+	unsigned long flags;
 
-	mutex_lock(&chip->lock);
+	spin_lock_irqsave(&chip->spinlock, flags);
 	reg_val = ioread32(&chip->reg->po);
 	if (val)
 		reg_val |= (1 << nr);
@@ -121,7 +119,7 @@ static void pch_gpio_set(struct gpio_chip *gpio, unsigned nr, int val)
 		reg_val &= ~(1 << nr);
 
 	iowrite32(reg_val, &chip->reg->po);
-	mutex_unlock(&chip->lock);
+	spin_unlock_irqrestore(&chip->spinlock, flags);
 }
 
 static int pch_gpio_get(struct gpio_chip *gpio, unsigned nr)
@@ -137,8 +135,9 @@ static int pch_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,
 	struct pch_gpio *chip =	container_of(gpio, struct pch_gpio, gpio);
 	u32 pm;
 	u32 reg_val;
+	unsigned long flags;
 
-	mutex_lock(&chip->lock);
+	spin_lock_irqsave(&chip->spinlock, flags);
 	pm = ioread32(&chip->reg->pm) & ((1 << gpio_pins[chip->ioh]) - 1);
 	pm |= (1 << nr);
 	iowrite32(pm, &chip->reg->pm);
@@ -149,8 +148,7 @@ static int pch_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,
 	else
 		reg_val &= ~(1 << nr);
 	iowrite32(reg_val, &chip->reg->po);
-
-	mutex_unlock(&chip->lock);
+	spin_unlock_irqrestore(&chip->spinlock, flags);
 
 	return 0;
 }
@@ -159,12 +157,13 @@ static int pch_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
 {
 	struct pch_gpio *chip =	container_of(gpio, struct pch_gpio, gpio);
 	u32 pm;
+	unsigned long flags;
 
-	mutex_lock(&chip->lock);
+	spin_lock_irqsave(&chip->spinlock, flags);
 	pm = ioread32(&chip->reg->pm) & ((1 << gpio_pins[chip->ioh]) - 1);
 	pm &= ~(1 << nr);
 	iowrite32(pm, &chip->reg->pm);
-	mutex_unlock(&chip->lock);
+	spin_unlock_irqrestore(&chip->spinlock, flags);
 
 	return 0;
 }
@@ -387,7 +386,6 @@ static int __devinit pch_gpio_probe(struct pci_dev *pdev,
 
 	chip->reg = chip->base;
 	pci_set_drvdata(pdev, chip);
-	mutex_init(&chip->lock);
 	spin_lock_init(&chip->spinlock);
 	pch_gpio_setup(chip);
 	ret = gpiochip_add(&chip->gpio);
diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c
index 9cac88a..98d52cb 100644
--- a/drivers/gpio/gpio-pxa.c
+++ b/drivers/gpio/gpio-pxa.c
@@ -26,6 +26,8 @@
 #include <linux/syscore_ops.h>
 #include <linux/slab.h>
 
+#include <asm/mach/irq.h>
+
 #include <mach/irqs.h>
 
 /*
@@ -59,6 +61,7 @@
 #define BANK_OFF(n)	(((n) < 3) ? (n) << 2 : 0x100 + (((n) - 3) << 2))
 
 int pxa_last_gpio;
+static int irq_base;
 
 #ifdef CONFIG_OF
 static struct irq_domain *domain;
@@ -167,63 +170,14 @@ static inline int __gpio_is_occupied(unsigned gpio)
 	return ret;
 }
 
-#ifdef CONFIG_ARCH_PXA
-static inline int __pxa_gpio_to_irq(int gpio)
-{
-	if (gpio_is_pxa_type(gpio_type))
-		return PXA_GPIO_TO_IRQ(gpio);
-	return -1;
-}
-
-static inline int __pxa_irq_to_gpio(int irq)
-{
-	if (gpio_is_pxa_type(gpio_type))
-		return irq - PXA_GPIO_TO_IRQ(0);
-	return -1;
-}
-#else
-static inline int __pxa_gpio_to_irq(int gpio) { return -1; }
-static inline int __pxa_irq_to_gpio(int irq) { return -1; }
-#endif
-
-#ifdef CONFIG_ARCH_MMP
-static inline int __mmp_gpio_to_irq(int gpio)
-{
-	if (gpio_is_mmp_type(gpio_type))
-		return MMP_GPIO_TO_IRQ(gpio);
-	return -1;
-}
-
-static inline int __mmp_irq_to_gpio(int irq)
-{
-	if (gpio_is_mmp_type(gpio_type))
-		return irq - MMP_GPIO_TO_IRQ(0);
-	return -1;
-}
-#else
-static inline int __mmp_gpio_to_irq(int gpio) { return -1; }
-static inline int __mmp_irq_to_gpio(int irq) { return -1; }
-#endif
-
 static int pxa_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
 {
-	int gpio, ret;
-
-	gpio = chip->base + offset;
-	ret = __pxa_gpio_to_irq(gpio);
-	if (ret >= 0)
-		return ret;
-	return __mmp_gpio_to_irq(gpio);
+	return chip->base + offset + irq_base;
 }
 
 int pxa_irq_to_gpio(int irq)
 {
-	int ret;
-
-	ret = __pxa_irq_to_gpio(irq);
-	if (ret >= 0)
-		return ret;
-	return __mmp_irq_to_gpio(irq);
+	return irq - irq_base;
 }
 
 static int pxa_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
@@ -403,6 +357,9 @@ 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;
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+
+	chained_irq_enter(chip, desc);
 
 	do {
 		loop = 0;
@@ -413,15 +370,15 @@ static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc)
 			gedr = gedr & c->irq_mask;
 			writel_relaxed(gedr, c->regbase + GEDR_OFFSET);
 
-			n = find_first_bit(&gedr, BITS_PER_LONG);
-			while (n < BITS_PER_LONG) {
+			for_each_set_bit(n, &gedr, 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);
+
+	chained_irq_exit(chip, desc);
 }
 
 static void pxa_ack_muxed_gpio(struct irq_data *d)
@@ -535,7 +492,7 @@ const struct irq_domain_ops pxa_irq_domain_ops = {
 
 static int __devinit pxa_gpio_probe_dt(struct platform_device *pdev)
 {
-	int ret, nr_banks, nr_gpios, irq_base;
+	int ret, nr_banks, nr_gpios;
 	struct device_node *prev, *next, *np = pdev->dev.of_node;
 	const struct of_device_id *of_id =
 				of_match_device(pxa_gpio_dt_ids, &pdev->dev);
@@ -590,10 +547,20 @@ static int __devinit pxa_gpio_probe(struct platform_device *pdev)
 	int irq0 = 0, irq1 = 0, irq_mux, gpio_offset = 0;
 
 	ret = pxa_gpio_probe_dt(pdev);
-	if (ret < 0)
+	if (ret < 0) {
 		pxa_last_gpio = pxa_gpio_nums();
-	else
+#ifdef CONFIG_ARCH_PXA
+		if (gpio_is_pxa_type(gpio_type))
+			irq_base = PXA_GPIO_TO_IRQ(0);
+#endif
+#ifdef CONFIG_ARCH_MMP
+		if (gpio_is_mmp_type(gpio_type))
+			irq_base = MMP_GPIO_TO_IRQ(0);
+#endif
+	} else {
 		use_of = 1;
+	}
+
 	if (!pxa_last_gpio)
 		return -EINVAL;
 
@@ -620,15 +587,8 @@ static int __devinit pxa_gpio_probe(struct platform_device *pdev)
 		iounmap(gpio_reg_base);
 		return PTR_ERR(clk);
 	}
-	ret = clk_prepare(clk);
-	if (ret) {
-		clk_put(clk);
-		iounmap(gpio_reg_base);
-		return ret;
-	}
-	ret = clk_enable(clk);
+	ret = clk_prepare_enable(clk);
 	if (ret) {
-		clk_unprepare(clk);
 		clk_put(clk);
 		iounmap(gpio_reg_base);
 		return ret;
diff --git a/drivers/gpio/gpio-samsung.c b/drivers/gpio/gpio-samsung.c
index ba126cc..a006f0d 100644
--- a/drivers/gpio/gpio-samsung.c
+++ b/drivers/gpio/gpio-samsung.c
@@ -938,6 +938,67 @@ static void __init samsung_gpiolib_add(struct samsung_gpio_chip *chip)
 		s3c_gpiolib_track(chip);
 }
 
+#if defined(CONFIG_PLAT_S3C24XX) && defined(CONFIG_OF)
+static int s3c24xx_gpio_xlate(struct gpio_chip *gc,
+			const struct of_phandle_args *gpiospec, u32 *flags)
+{
+	unsigned int pin;
+
+	if (WARN_ON(gc->of_gpio_n_cells < 3))
+		return -EINVAL;
+
+	if (WARN_ON(gpiospec->args_count < gc->of_gpio_n_cells))
+		return -EINVAL;
+
+	if (gpiospec->args[0] > gc->ngpio)
+		return -EINVAL;
+
+	pin = gc->base + gpiospec->args[0];
+
+	if (s3c_gpio_cfgpin(pin, S3C_GPIO_SFN(gpiospec->args[1])))
+		pr_warn("gpio_xlate: failed to set pin function\n");
+	if (s3c_gpio_setpull(pin, gpiospec->args[2] & 0xffff))
+		pr_warn("gpio_xlate: failed to set pin pull up/down\n");
+
+	if (flags)
+		*flags = gpiospec->args[2] >> 16;
+
+	return gpiospec->args[0];
+}
+
+static const struct of_device_id s3c24xx_gpio_dt_match[] __initdata = {
+	{ .compatible = "samsung,s3c24xx-gpio", },
+	{}
+};
+
+static __init void s3c24xx_gpiolib_attach_ofnode(struct samsung_gpio_chip *chip,
+						 u64 base, u64 offset)
+{
+	struct gpio_chip *gc =  &chip->chip;
+	u64 address;
+
+	if (!of_have_populated_dt())
+		return;
+
+	address = chip->base ? base + ((u32)chip->base & 0xfff) : base + offset;
+	gc->of_node = of_find_matching_node_by_address(NULL,
+			s3c24xx_gpio_dt_match, address);
+	if (!gc->of_node) {
+		pr_info("gpio: device tree node not found for gpio controller"
+			" with base address %08llx\n", address);
+		return;
+	}
+	gc->of_gpio_n_cells = 3;
+	gc->of_xlate = s3c24xx_gpio_xlate;
+}
+#else
+static __init void s3c24xx_gpiolib_attach_ofnode(struct samsung_gpio_chip *chip,
+						 u64 base, u64 offset)
+{
+	return;
+}
+#endif /* defined(CONFIG_PLAT_S3C24XX) && defined(CONFIG_OF) */
+
 static void __init s3c24xx_gpiolib_add_chips(struct samsung_gpio_chip *chip,
 					     int nr_chips, void __iomem *base)
 {
@@ -962,6 +1023,8 @@ static void __init s3c24xx_gpiolib_add_chips(struct samsung_gpio_chip *chip,
 			gc->direction_output = samsung_gpiolib_2bit_output;
 
 		samsung_gpiolib_add(chip);
+
+		s3c24xx_gpiolib_attach_ofnode(chip, S3C24XX_PA_GPIO, i * 0x10);
 	}
 }
 
@@ -2734,6 +2797,27 @@ static __init void exynos4_gpiolib_init(void)
 	int group = 0;
 	void __iomem *gpx_base;
 
+#ifdef CONFIG_PINCTRL_SAMSUNG
+		/*
+		 * This gpio driver includes support for device tree support and
+		 * there are platforms using it. In order to maintain
+		 * compatibility with those platforms, and to allow non-dt
+		 * Exynos4210 platforms to use this gpiolib support, a check
+		 * is added to find out if there is a active pin-controller
+		 * driver support available. If it is available, this gpiolib
+		 * support is ignored and the gpiolib support available in
+		 * pin-controller driver is used. This is a temporary check and
+		 * will go away when all of the Exynos4210 platforms have
+		 * switched to using device tree and the pin-ctrl driver.
+		 */
+		struct device_node *pctrl_np;
+		const char *pctrl_compat = "samsung,pinctrl-exynos4210";
+		pctrl_np = of_find_compatible_node(NULL, NULL, pctrl_compat);
+		if (pctrl_np)
+			if (of_device_is_available(pctrl_np))
+				return;
+#endif
+
 	/* gpio part1 */
 	gpio_base1 = ioremap(EXYNOS4_PA_GPIO1, SZ_4K);
 	if (gpio_base1 == NULL) {
@@ -3131,46 +3215,6 @@ samsung_gpio_pull_t s3c_gpio_getpull(unsigned int pin)
 }
 EXPORT_SYMBOL(s3c_gpio_getpull);
 
-/* gpiolib wrappers until these are totally eliminated */
-
-void s3c2410_gpio_pullup(unsigned int pin, unsigned int to)
-{
-	int ret;
-
-	WARN_ON(to);	/* should be none of these left */
-
-	if (!to) {
-		/* if pull is enabled, try first with up, and if that
-		 * fails, try using down */
-
-		ret = s3c_gpio_setpull(pin, S3C_GPIO_PULL_UP);
-		if (ret)
-			s3c_gpio_setpull(pin, S3C_GPIO_PULL_DOWN);
-	} else {
-		s3c_gpio_setpull(pin, S3C_GPIO_PULL_NONE);
-	}
-}
-EXPORT_SYMBOL(s3c2410_gpio_pullup);
-
-void s3c2410_gpio_setpin(unsigned int pin, unsigned int to)
-{
-	/* do this via gpiolib until all users removed */
-
-	gpio_request(pin, "temporary");
-	gpio_set_value(pin, to);
-	gpio_free(pin);
-}
-EXPORT_SYMBOL(s3c2410_gpio_setpin);
-
-unsigned int s3c2410_gpio_getpin(unsigned int pin)
-{
-	struct samsung_gpio_chip *chip = samsung_gpiolib_getchip(pin);
-	unsigned long offs = pin - chip->chip.base;
-
-	return __raw_readl(chip->base + 0x04) & (1 << offs);
-}
-EXPORT_SYMBOL(s3c2410_gpio_getpin);
-
 #ifdef CONFIG_S5P_GPIO_DRVSTR
 s5p_gpio_drvstr_t s5p_gpio_get_drvstr(unsigned int pin)
 {
diff --git a/drivers/gpio/gpio-sodaville.c b/drivers/gpio/gpio-sodaville.c
index 9d9891f..e25f731 100644
--- a/drivers/gpio/gpio-sodaville.c
+++ b/drivers/gpio/gpio-sodaville.c
@@ -270,7 +270,7 @@ static void sdv_gpio_remove(struct pci_dev *pdev)
 	kfree(sd);
 }
 
-static struct pci_device_id sdv_gpio_pci_ids[] __devinitdata = {
+static DEFINE_PCI_DEVICE_TABLE(sdv_gpio_pci_ids) = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_SDV_GPIO) },
 	{ 0, },
 };
diff --git a/drivers/gpio/gpio-sx150x.c b/drivers/gpio/gpio-sx150x.c
index a4f7353..eb3e215 100644
--- a/drivers/gpio/gpio-sx150x.c
+++ b/drivers/gpio/gpio-sx150x.c
@@ -311,11 +311,9 @@ static int sx150x_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
 
 static void sx150x_irq_mask(struct irq_data *d)
 {
-	struct irq_chip *ic = irq_data_get_irq_chip(d);
-	struct sx150x_chip *chip;
+	struct sx150x_chip *chip = irq_data_get_irq_chip_data(d);
 	unsigned n;
 
-	chip = container_of(ic, struct sx150x_chip, irq_chip);
 	n = d->irq - chip->irq_base;
 	chip->irq_masked |= (1 << n);
 	chip->irq_update = n;
@@ -323,27 +321,22 @@ static void sx150x_irq_mask(struct irq_data *d)
 
 static void sx150x_irq_unmask(struct irq_data *d)
 {
-	struct irq_chip *ic = irq_data_get_irq_chip(d);
-	struct sx150x_chip *chip;
+	struct sx150x_chip *chip = irq_data_get_irq_chip_data(d);
 	unsigned n;
 
-	chip = container_of(ic, struct sx150x_chip, irq_chip);
 	n = d->irq - chip->irq_base;
-
 	chip->irq_masked &= ~(1 << n);
 	chip->irq_update = n;
 }
 
 static int sx150x_irq_set_type(struct irq_data *d, unsigned int flow_type)
 {
-	struct irq_chip *ic = irq_data_get_irq_chip(d);
-	struct sx150x_chip *chip;
+	struct sx150x_chip *chip = irq_data_get_irq_chip_data(d);
 	unsigned n, val = 0;
 
 	if (flow_type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW))
 		return -EINVAL;
 
-	chip = container_of(ic, struct sx150x_chip, irq_chip);
 	n = d->irq - chip->irq_base;
 
 	if (flow_type & IRQ_TYPE_EDGE_RISING)
@@ -391,22 +384,16 @@ static irqreturn_t sx150x_irq_thread_fn(int irq, void *dev_id)
 
 static void sx150x_irq_bus_lock(struct irq_data *d)
 {
-	struct irq_chip *ic = irq_data_get_irq_chip(d);
-	struct sx150x_chip *chip;
-
-	chip = container_of(ic, struct sx150x_chip, irq_chip);
+	struct sx150x_chip *chip = irq_data_get_irq_chip_data(d);
 
 	mutex_lock(&chip->lock);
 }
 
 static void sx150x_irq_bus_sync_unlock(struct irq_data *d)
 {
-	struct irq_chip *ic = irq_data_get_irq_chip(d);
-	struct sx150x_chip *chip;
+	struct sx150x_chip *chip = irq_data_get_irq_chip_data(d);
 	unsigned n;
 
-	chip = container_of(ic, struct sx150x_chip, irq_chip);
-
 	if (chip->irq_update == NO_UPDATE_PENDING)
 		goto out;
 
@@ -551,6 +538,7 @@ static int sx150x_install_irq_chip(struct sx150x_chip *chip,
 
 	for (n = 0; n < chip->dev_cfg->ngpios; ++n) {
 		irq = irq_base + n;
+		irq_set_chip_data(irq, chip);
 		irq_set_chip_and_handler(irq, &chip->irq_chip, handle_edge_irq);
 		irq_set_nested_thread(irq, 1);
 #ifdef CONFIG_ARM
diff --git a/drivers/gpio/gpio-tc3589x.c b/drivers/gpio/gpio-tc3589x.c
index 2a82e89..1e48317 100644
--- a/drivers/gpio/gpio-tc3589x.c
+++ b/drivers/gpio/gpio-tc3589x.c
@@ -11,7 +11,9 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/gpio.h>
+#include <linux/of.h>
 #include <linux/irq.h>
+#include <linux/irqdomain.h>
 #include <linux/interrupt.h>
 #include <linux/mfd/tc3589x.h>
 
@@ -29,6 +31,7 @@ struct tc3589x_gpio {
 	struct tc3589x *tc3589x;
 	struct device *dev;
 	struct mutex irq_lock;
+	struct irq_domain *domain;
 
 	int irq_base;
 
@@ -92,11 +95,28 @@ static int tc3589x_gpio_direction_input(struct gpio_chip *chip,
 	return tc3589x_set_bits(tc3589x, reg, 1 << pos, 0);
 }
 
+/**
+ * tc3589x_gpio_irq_get_virq(): Map an interrupt on a chip to a virtual IRQ
+ *
+ * @tc3589x_gpio: tc3589x_gpio_irq controller to operate on.
+ * @irq: index of the interrupt requested in the chip IRQs
+ *
+ * Useful for drivers to request their own IRQs.
+ */
+static int tc3589x_gpio_irq_get_virq(struct tc3589x_gpio *tc3589x_gpio,
+				     int irq)
+{
+	if (!tc3589x_gpio)
+		return -EINVAL;
+
+	return irq_create_mapping(tc3589x_gpio->domain, irq);
+}
+
 static int tc3589x_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
 {
 	struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip);
 
-	return tc3589x_gpio->irq_base + offset;
+	return tc3589x_gpio_irq_get_virq(tc3589x_gpio, offset);
 }
 
 static struct gpio_chip template_chip = {
@@ -113,7 +133,7 @@ static struct gpio_chip template_chip = {
 static int tc3589x_gpio_irq_set_type(struct irq_data *d, unsigned int type)
 {
 	struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d);
-	int offset = d->irq - tc3589x_gpio->irq_base;
+	int offset = d->hwirq;
 	int regoffset = offset / 8;
 	int mask = 1 << (offset % 8);
 
@@ -175,7 +195,7 @@ static void tc3589x_gpio_irq_sync_unlock(struct irq_data *d)
 static void tc3589x_gpio_irq_mask(struct irq_data *d)
 {
 	struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d);
-	int offset = d->irq - tc3589x_gpio->irq_base;
+	int offset = d->hwirq;
 	int regoffset = offset / 8;
 	int mask = 1 << (offset % 8);
 
@@ -185,7 +205,7 @@ static void tc3589x_gpio_irq_mask(struct irq_data *d)
 static void tc3589x_gpio_irq_unmask(struct irq_data *d)
 {
 	struct tc3589x_gpio *tc3589x_gpio = irq_data_get_irq_chip_data(d);
-	int offset = d->irq - tc3589x_gpio->irq_base;
+	int offset = d->hwirq;
 	int regoffset = offset / 8;
 	int mask = 1 << (offset % 8);
 
@@ -222,8 +242,9 @@ static irqreturn_t tc3589x_gpio_irq(int irq, void *dev)
 		while (stat) {
 			int bit = __ffs(stat);
 			int line = i * 8 + bit;
+			int virq = tc3589x_gpio_irq_get_virq(tc3589x_gpio, line);
 
-			handle_nested_irq(tc3589x_gpio->irq_base + line);
+			handle_nested_irq(virq);
 			stat &= ~(1 << bit);
 		}
 
@@ -233,51 +254,78 @@ static irqreturn_t tc3589x_gpio_irq(int irq, void *dev)
 	return IRQ_HANDLED;
 }
 
-static int tc3589x_gpio_irq_init(struct tc3589x_gpio *tc3589x_gpio)
+static int tc3589x_gpio_irq_map(struct irq_domain *d, unsigned int virq,
+				irq_hw_number_t hwirq)
 {
-	int base = tc3589x_gpio->irq_base;
-	int irq;
+	struct tc3589x *tc3589x_gpio = d->host_data;
 
-	for (irq = base; irq < base + tc3589x_gpio->chip.ngpio; irq++) {
-		irq_set_chip_data(irq, tc3589x_gpio);
-		irq_set_chip_and_handler(irq, &tc3589x_gpio_irq_chip,
-					 handle_simple_irq);
-		irq_set_nested_thread(irq, 1);
+	irq_set_chip_data(virq, tc3589x_gpio);
+	irq_set_chip_and_handler(virq, &tc3589x_gpio_irq_chip,
+				handle_simple_irq);
+	irq_set_nested_thread(virq, 1);
 #ifdef CONFIG_ARM
-		set_irq_flags(irq, IRQF_VALID);
+	set_irq_flags(virq, IRQF_VALID);
 #else
-		irq_set_noprobe(irq);
+	irq_set_noprobe(virq);
 #endif
-	}
 
 	return 0;
 }
 
-static void tc3589x_gpio_irq_remove(struct tc3589x_gpio *tc3589x_gpio)
+static void tc3589x_gpio_irq_unmap(struct irq_domain *d, unsigned int virq)
 {
-	int base = tc3589x_gpio->irq_base;
-	int irq;
-
-	for (irq = base; irq < base + tc3589x_gpio->chip.ngpio; irq++) {
 #ifdef CONFIG_ARM
-		set_irq_flags(irq, 0);
+	set_irq_flags(virq, 0);
 #endif
-		irq_set_chip_and_handler(irq, NULL, NULL);
-		irq_set_chip_data(irq, NULL);
+	irq_set_chip_and_handler(virq, NULL, NULL);
+	irq_set_chip_data(virq, NULL);
+}
+
+static struct irq_domain_ops tc3589x_irq_ops = {
+        .map    = tc3589x_gpio_irq_map,
+        .unmap  = tc3589x_gpio_irq_unmap,
+        .xlate  = irq_domain_xlate_twocell,
+};
+
+static int tc3589x_gpio_irq_init(struct tc3589x_gpio *tc3589x_gpio,
+				struct device_node *np)
+{
+	int base = tc3589x_gpio->irq_base;
+
+	if (base) {
+		tc3589x_gpio->domain = irq_domain_add_legacy(
+			NULL, tc3589x_gpio->chip.ngpio, base,
+			0, &tc3589x_irq_ops, tc3589x_gpio);
+	}
+	else {
+		tc3589x_gpio->domain = irq_domain_add_linear(
+			np, tc3589x_gpio->chip.ngpio,
+			&tc3589x_irq_ops, tc3589x_gpio);
+	}
+
+	if (!tc3589x_gpio->domain) {
+		dev_err(tc3589x_gpio->dev, "Failed to create irqdomain\n");
+		return -ENOSYS;
 	}
+
+	return 0;
 }
 
 static int __devinit tc3589x_gpio_probe(struct platform_device *pdev)
 {
 	struct tc3589x *tc3589x = dev_get_drvdata(pdev->dev.parent);
 	struct tc3589x_gpio_platform_data *pdata;
+	struct device_node *np = pdev->dev.of_node;
 	struct tc3589x_gpio *tc3589x_gpio;
 	int ret;
 	int irq;
 
 	pdata = tc3589x->pdata->gpio;
-	if (!pdata)
-		return -ENODEV;
+
+	if (!(pdata || np)) {
+		dev_err(&pdev->dev, "No platform data or Device Tree found\n");
+		return -EINVAL;
+	}
 
 	irq = platform_get_irq(pdev, 0);
 	if (irq < 0)
@@ -295,9 +343,14 @@ static int __devinit tc3589x_gpio_probe(struct platform_device *pdev)
 	tc3589x_gpio->chip = template_chip;
 	tc3589x_gpio->chip.ngpio = tc3589x->num_gpio;
 	tc3589x_gpio->chip.dev = &pdev->dev;
-	tc3589x_gpio->chip.base = pdata->gpio_base;
+	tc3589x_gpio->chip.base = (pdata) ? pdata->gpio_base : -1;
 
-	tc3589x_gpio->irq_base = tc3589x->irq_base + TC3589x_INT_GPIO(0);
+#ifdef CONFIG_OF_GPIO
+        tc3589x_gpio->chip.of_node = np;
+#endif
+
+	tc3589x_gpio->irq_base = tc3589x->irq_base ?
+		tc3589x->irq_base + TC3589x_INT_GPIO(0) : 0;
 
 	/* Bring the GPIO module out of reset */
 	ret = tc3589x_set_bits(tc3589x, TC3589x_RSTCTRL,
@@ -305,7 +358,7 @@ static int __devinit tc3589x_gpio_probe(struct platform_device *pdev)
 	if (ret < 0)
 		goto out_free;
 
-	ret = tc3589x_gpio_irq_init(tc3589x_gpio);
+	ret = tc3589x_gpio_irq_init(tc3589x_gpio, np);
 	if (ret)
 		goto out_free;
 
@@ -313,7 +366,7 @@ static int __devinit tc3589x_gpio_probe(struct platform_device *pdev)
 				   "tc3589x-gpio", tc3589x_gpio);
 	if (ret) {
 		dev_err(&pdev->dev, "unable to get irq: %d\n", ret);
-		goto out_removeirq;
+		goto out_free;
 	}
 
 	ret = gpiochip_add(&tc3589x_gpio->chip);
@@ -322,7 +375,7 @@ static int __devinit tc3589x_gpio_probe(struct platform_device *pdev)
 		goto out_freeirq;
 	}
 
-	if (pdata->setup)
+	if (pdata && pdata->setup)
 		pdata->setup(tc3589x, tc3589x_gpio->chip.base);
 
 	platform_set_drvdata(pdev, tc3589x_gpio);
@@ -331,8 +384,6 @@ static int __devinit tc3589x_gpio_probe(struct platform_device *pdev)
 
 out_freeirq:
 	free_irq(irq, tc3589x_gpio);
-out_removeirq:
-	tc3589x_gpio_irq_remove(tc3589x_gpio);
 out_free:
 	kfree(tc3589x_gpio);
 	return ret;
@@ -346,7 +397,7 @@ static int __devexit tc3589x_gpio_remove(struct platform_device *pdev)
 	int irq = platform_get_irq(pdev, 0);
 	int ret;
 
-	if (pdata->remove)
+	if (pdata && pdata->remove)
 		pdata->remove(tc3589x, tc3589x_gpio->chip.base);
 
 	ret = gpiochip_remove(&tc3589x_gpio->chip);
@@ -357,7 +408,6 @@ static int __devexit tc3589x_gpio_remove(struct platform_device *pdev)
 	}
 
 	free_irq(irq, tc3589x_gpio);
-	tc3589x_gpio_irq_remove(tc3589x_gpio);
 
 	platform_set_drvdata(pdev, NULL);
 	kfree(tc3589x_gpio);
diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c
index dc5184d..d982593 100644
--- a/drivers/gpio/gpio-tegra.c
+++ b/drivers/gpio/gpio-tegra.c
@@ -30,9 +30,6 @@
 
 #include <asm/mach/irq.h>
 
-#include <mach/iomap.h>
-#include <mach/suspend.h>
-
 #define GPIO_BANK(x)		((x) >> 5)
 #define GPIO_PORT(x)		(((x) >> 3) & 0x3)
 #define GPIO_BIT(x)		((x) & 0x7)
diff --git a/drivers/gpio/gpio-tps65912.c b/drivers/gpio/gpio-tps65912.c
index 79e66c0..99106d1 100644
--- a/drivers/gpio/gpio-tps65912.c
+++ b/drivers/gpio/gpio-tps65912.c
@@ -70,7 +70,6 @@ static int tps65912_gpio_input(struct gpio_chip *gc, unsigned offset)
 
 	return tps65912_clear_bits(tps65912, TPS65912_GPIO1 + offset,
 								GPIO_CFG_MASK);
-
 }
 
 static struct gpio_chip template_chip = {
@@ -92,7 +91,8 @@ static int __devinit tps65912_gpio_probe(struct platform_device *pdev)
 	struct tps65912_gpio_data *tps65912_gpio;
 	int ret;
 
-	tps65912_gpio = kzalloc(sizeof(*tps65912_gpio), GFP_KERNEL);
+	tps65912_gpio = devm_kzalloc(&pdev->dev, sizeof(*tps65912_gpio),
+				     GFP_KERNEL);
 	if (tps65912_gpio == NULL)
 		return -ENOMEM;
 
@@ -105,28 +105,19 @@ static int __devinit tps65912_gpio_probe(struct platform_device *pdev)
 	ret = gpiochip_add(&tps65912_gpio->gpio_chip);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "Failed to register gpiochip, %d\n", ret);
-		goto err;
+		return ret;
 	}
 
 	platform_set_drvdata(pdev, tps65912_gpio);
 
 	return ret;
-
-err:
-	kfree(tps65912_gpio);
-	return ret;
 }
 
 static int __devexit tps65912_gpio_remove(struct platform_device *pdev)
 {
 	struct tps65912_gpio_data  *tps65912_gpio = platform_get_drvdata(pdev);
-	int ret;
-
-	ret = gpiochip_remove(&tps65912_gpio->gpio_chip);
-	if (ret == 0)
-		kfree(tps65912_gpio);
 
-	return ret;
+	return gpiochip_remove(&tps65912_gpio->gpio_chip);
 }
 
 static struct platform_driver tps65912_gpio_driver = {
diff --git a/drivers/gpio/gpio-twl4030.c b/drivers/gpio/gpio-twl4030.c
index 94256fe..c5f8ca2 100644
--- a/drivers/gpio/gpio-twl4030.c
+++ b/drivers/gpio/gpio-twl4030.c
@@ -51,6 +51,7 @@
 
 
 static struct gpio_chip twl_gpiochip;
+static int twl4030_gpio_base;
 static int twl4030_gpio_irq_base;
 
 /* genirq interfaces are not available to modules */
@@ -395,6 +396,29 @@ static int __devinit gpio_twl4030_debounce(u32 debounce, u8 mmc_cd)
 
 static int gpio_twl4030_remove(struct platform_device *pdev);
 
+static struct twl4030_gpio_platform_data *of_gpio_twl4030(struct device *dev)
+{
+	struct twl4030_gpio_platform_data *omap_twl_info;
+
+	omap_twl_info = devm_kzalloc(dev, sizeof(*omap_twl_info), GFP_KERNEL);
+	if (!omap_twl_info)
+		return NULL;
+
+	omap_twl_info->use_leds = of_property_read_bool(dev->of_node,
+			"ti,use-leds");
+
+	of_property_read_u32(dev->of_node, "ti,debounce",
+			     &omap_twl_info->debounce);
+	of_property_read_u32(dev->of_node, "ti,mmc-cd",
+			     (u32 *)&omap_twl_info->mmc_cd);
+	of_property_read_u32(dev->of_node, "ti,pullups",
+			     &omap_twl_info->pullups);
+	of_property_read_u32(dev->of_node, "ti,pulldowns",
+			     &omap_twl_info->pulldowns);
+
+	return omap_twl_info;
+}
+
 static int __devinit gpio_twl4030_probe(struct platform_device *pdev)
 {
 	struct twl4030_gpio_platform_data *pdata = pdev->dev.platform_data;
@@ -427,49 +451,57 @@ no_irqs:
 	twl_gpiochip.ngpio = TWL4030_GPIO_MAX;
 	twl_gpiochip.dev = &pdev->dev;
 
-	if (pdata) {
-		twl_gpiochip.base = pdata->gpio_base;
+	if (node)
+		pdata = of_gpio_twl4030(&pdev->dev);
 
-		/*
-		 * NOTE:  boards may waste power if they don't set pullups
-		 * and pulldowns correctly ... default for non-ULPI pins is
-		 * pulldown, and some other pins may have external pullups
-		 * or pulldowns.  Careful!
-		 */
-		ret = gpio_twl4030_pulls(pdata->pullups, pdata->pulldowns);
-		if (ret)
-			dev_dbg(&pdev->dev, "pullups %.05x %.05x --> %d\n",
-					pdata->pullups, pdata->pulldowns,
-					ret);
-
-		ret = gpio_twl4030_debounce(pdata->debounce, pdata->mmc_cd);
-		if (ret)
-			dev_dbg(&pdev->dev, "debounce %.03x %.01x --> %d\n",
-					pdata->debounce, pdata->mmc_cd,
-					ret);
-
-		/*
-		 * NOTE: we assume VIBRA_CTL.VIBRA_EN, in MODULE_AUDIO_VOICE,
-		 * is (still) clear if use_leds is set.
-		 */
-		if (pdata->use_leds)
-			twl_gpiochip.ngpio += 2;
+	if (pdata == NULL) {
+		dev_err(&pdev->dev, "Platform data is missing\n");
+		return -ENXIO;
 	}
 
+	/*
+	 * NOTE:  boards may waste power if they don't set pullups
+	 * and pulldowns correctly ... default for non-ULPI pins is
+	 * pulldown, and some other pins may have external pullups
+	 * or pulldowns.  Careful!
+	 */
+	ret = gpio_twl4030_pulls(pdata->pullups, pdata->pulldowns);
+	if (ret)
+		dev_dbg(&pdev->dev, "pullups %.05x %.05x --> %d\n",
+			pdata->pullups, pdata->pulldowns, ret);
+
+	ret = gpio_twl4030_debounce(pdata->debounce, pdata->mmc_cd);
+	if (ret)
+		dev_dbg(&pdev->dev, "debounce %.03x %.01x --> %d\n",
+			pdata->debounce, pdata->mmc_cd, ret);
+
+	/*
+	 * NOTE: we assume VIBRA_CTL.VIBRA_EN, in MODULE_AUDIO_VOICE,
+	 * is (still) clear if use_leds is set.
+	 */
+	if (pdata->use_leds)
+		twl_gpiochip.ngpio += 2;
+
 	ret = gpiochip_add(&twl_gpiochip);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "could not register gpiochip, %d\n", ret);
 		twl_gpiochip.ngpio = 0;
 		gpio_twl4030_remove(pdev);
-	} else if (pdata && pdata->setup) {
+		goto out;
+	}
+
+	twl4030_gpio_base = twl_gpiochip.base;
+
+	if (pdata && pdata->setup) {
 		int status;
 
 		status = pdata->setup(&pdev->dev,
-				pdata->gpio_base, TWL4030_GPIO_MAX);
+				twl4030_gpio_base, TWL4030_GPIO_MAX);
 		if (status)
 			dev_dbg(&pdev->dev, "setup --> %d\n", status);
 	}
 
+out:
 	return ret;
 }
 
@@ -481,7 +513,7 @@ static int gpio_twl4030_remove(struct platform_device *pdev)
 
 	if (pdata && pdata->teardown) {
 		status = pdata->teardown(&pdev->dev,
-				pdata->gpio_base, TWL4030_GPIO_MAX);
+				twl4030_gpio_base, TWL4030_GPIO_MAX);
 		if (status) {
 			dev_dbg(&pdev->dev, "teardown --> %d\n", status);
 			return status;
diff --git a/drivers/gpio/gpio-twl6040.c b/drivers/gpio/gpio-twl6040.c
new file mode 100644
index 0000000..dd58e8b
--- /dev/null
+++ b/drivers/gpio/gpio-twl6040.c
@@ -0,0 +1,137 @@
+/*
+ * Access to GPOs on TWL6040 chip
+ *
+ * Copyright (C) 2012 Texas Instruments, Inc.
+ *
+ * Authors:
+ *	Sergio Aguirre <saaguirre@ti.com>
+ *	Peter Ujfalusi <peter.ujfalusi@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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kthread.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+
+#include <linux/mfd/twl6040.h>
+
+static struct gpio_chip twl6040gpo_chip;
+
+static int twl6040gpo_get(struct gpio_chip *chip, unsigned offset)
+{
+	struct twl6040 *twl6040 = dev_get_drvdata(chip->dev->parent);
+	int ret = 0;
+
+	ret = twl6040_reg_read(twl6040, TWL6040_REG_GPOCTL);
+	if (ret < 0)
+		return ret;
+
+	return (ret >> offset) & 1;
+}
+
+static int twl6040gpo_direction_out(struct gpio_chip *chip, unsigned offset,
+				    int value)
+{
+	/* This only drives GPOs, and can't change direction */
+	return 0;
+}
+
+static void twl6040gpo_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+	struct twl6040 *twl6040 = dev_get_drvdata(chip->dev->parent);
+	int ret;
+	u8 gpoctl;
+
+	ret = twl6040_reg_read(twl6040, TWL6040_REG_GPOCTL);
+	if (ret < 0)
+		return;
+
+	if (value)
+		gpoctl = ret | (1 << offset);
+	else
+		gpoctl = ret & ~(1 << offset);
+
+	twl6040_reg_write(twl6040, TWL6040_REG_GPOCTL, gpoctl);
+}
+
+static struct gpio_chip twl6040gpo_chip = {
+	.label			= "twl6040",
+	.owner			= THIS_MODULE,
+	.get			= twl6040gpo_get,
+	.direction_output	= twl6040gpo_direction_out,
+	.set			= twl6040gpo_set,
+	.can_sleep		= 1,
+};
+
+/*----------------------------------------------------------------------*/
+
+static int __devinit gpo_twl6040_probe(struct platform_device *pdev)
+{
+	struct twl6040_gpo_data *pdata = pdev->dev.platform_data;
+	struct device *twl6040_core_dev = pdev->dev.parent;
+	struct twl6040 *twl6040 = dev_get_drvdata(twl6040_core_dev);
+	int ret;
+
+	if (pdata)
+		twl6040gpo_chip.base = pdata->gpio_base;
+	else
+		twl6040gpo_chip.base = -1;
+
+	if (twl6040_get_revid(twl6040) < TWL6041_REV_ES2_0)
+		twl6040gpo_chip.ngpio = 3; /* twl6040 have 3 GPO */
+	else
+		twl6040gpo_chip.ngpio = 1; /* twl6041 have 1 GPO */
+
+	twl6040gpo_chip.dev = &pdev->dev;
+#ifdef CONFIG_OF_GPIO
+	twl6040gpo_chip.of_node = twl6040_core_dev->of_node;
+#endif
+
+	ret = gpiochip_add(&twl6040gpo_chip);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "could not register gpiochip, %d\n", ret);
+		twl6040gpo_chip.ngpio = 0;
+	}
+
+	return ret;
+}
+
+static int __devexit gpo_twl6040_remove(struct platform_device *pdev)
+{
+	return gpiochip_remove(&twl6040gpo_chip);
+}
+
+/* Note:  this hardware lives inside an I2C-based multi-function device. */
+MODULE_ALIAS("platform:twl6040-gpo");
+
+static struct platform_driver gpo_twl6040_driver = {
+	.driver = {
+		.name	= "twl6040-gpo",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= gpo_twl6040_probe,
+	.remove		= gpo_twl6040_remove,
+};
+
+module_platform_driver(gpo_twl6040_driver);
+
+MODULE_AUTHOR("Texas Instruments, Inc.");
+MODULE_DESCRIPTION("GPO interface for TWL6040");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/gpio-vt8500.c b/drivers/gpio/gpio-vt8500.c
new file mode 100644
index 0000000..bcd8e4a
--- /dev/null
+++ b/drivers/gpio/gpio-vt8500.c
@@ -0,0 +1,316 @@
+/* drivers/gpio/gpio-vt8500.c
+ *
+ * Copyright (C) 2012 Tony Prisk <linux@prisktech.co.nz>
+ * Based on arch/arm/mach-vt8500/gpio.c:
+ * - Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/platform_device.h>
+#include <linux/bitops.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_device.h>
+
+/*
+	We handle GPIOs by bank, each bank containing up to 32 GPIOs covered
+	by one set of registers (although not all may be valid).
+
+	Because different SoC's have different register offsets, we pass the
+	register offsets as data in vt8500_gpio_dt_ids[].
+
+	A value of NO_REG is used to indicate that this register is not
+	supported. Only used for ->en at the moment.
+*/
+
+#define NO_REG	0xFFFF
+
+/*
+ * struct vt8500_gpio_bank_regoffsets
+ * @en: offset to enable register of the bank
+ * @dir: offset to direction register of the bank
+ * @data_out: offset to the data out register of the bank
+ * @data_in: offset to the data in register of the bank
+ * @ngpio: highest valid pin in this bank
+ */
+
+struct vt8500_gpio_bank_regoffsets {
+	unsigned int	en;
+	unsigned int	dir;
+	unsigned int	data_out;
+	unsigned int	data_in;
+	unsigned char	ngpio;
+};
+
+struct vt8500_gpio_data {
+	unsigned int				num_banks;
+	struct vt8500_gpio_bank_regoffsets	banks[];
+};
+
+#define VT8500_BANK(__en, __dir, __out, __in, __ngpio)		\
+{								\
+	.en = __en,						\
+	.dir = __dir,						\
+	.data_out = __out,					\
+	.data_in = __in,					\
+	.ngpio = __ngpio,					\
+}
+
+static struct vt8500_gpio_data vt8500_data = {
+	.num_banks	= 7,
+	.banks	= {
+		VT8500_BANK(0x00, 0x20, 0x40, 0x60, 26),
+		VT8500_BANK(0x04, 0x24, 0x44, 0x64, 28),
+		VT8500_BANK(0x08, 0x28, 0x48, 0x68, 31),
+		VT8500_BANK(0x0C, 0x2C, 0x4C, 0x6C, 19),
+		VT8500_BANK(0x10, 0x30, 0x50, 0x70, 19),
+		VT8500_BANK(0x14, 0x34, 0x54, 0x74, 23),
+		VT8500_BANK(NO_REG, 0x3C, 0x5C, 0x7C, 9),
+	},
+};
+
+static struct vt8500_gpio_data wm8505_data = {
+	.num_banks	= 10,
+	.banks	= {
+		VT8500_BANK(0x40, 0x68, 0x90, 0xB8, 8),
+		VT8500_BANK(0x44, 0x6C, 0x94, 0xBC, 32),
+		VT8500_BANK(0x48, 0x70, 0x98, 0xC0, 6),
+		VT8500_BANK(0x4C, 0x74, 0x9C, 0xC4, 16),
+		VT8500_BANK(0x50, 0x78, 0xA0, 0xC8, 25),
+		VT8500_BANK(0x54, 0x7C, 0xA4, 0xCC, 5),
+		VT8500_BANK(0x58, 0x80, 0xA8, 0xD0, 5),
+		VT8500_BANK(0x5C, 0x84, 0xAC, 0xD4, 12),
+		VT8500_BANK(0x60, 0x88, 0xB0, 0xD8, 16),
+		VT8500_BANK(0x64, 0x8C, 0xB4, 0xDC, 22),
+	},
+};
+
+/*
+ * No information about which bits are valid so we just make
+ * them all available until its figured out.
+ */
+static struct vt8500_gpio_data wm8650_data = {
+	.num_banks	= 9,
+	.banks	= {
+		VT8500_BANK(0x40, 0x80, 0xC0, 0x00, 32),
+		VT8500_BANK(0x44, 0x84, 0xC4, 0x04, 32),
+		VT8500_BANK(0x48, 0x88, 0xC8, 0x08, 32),
+		VT8500_BANK(0x4C, 0x8C, 0xCC, 0x0C, 32),
+		VT8500_BANK(0x50, 0x90, 0xD0, 0x10, 32),
+		VT8500_BANK(0x54, 0x94, 0xD4, 0x14, 32),
+		VT8500_BANK(0x58, 0x98, 0xD8, 0x18, 32),
+		VT8500_BANK(0x5C, 0x9C, 0xDC, 0x1C, 32),
+		VT8500_BANK(0x7C, 0xBC, 0xFC, 0x3C, 32),
+	},
+};
+
+struct vt8500_gpio_chip {
+	struct gpio_chip		chip;
+
+	const struct vt8500_gpio_bank_regoffsets *regs;
+	void __iomem	*base;
+};
+
+
+#define to_vt8500(__chip) container_of(__chip, struct vt8500_gpio_chip, chip)
+
+static int vt8500_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+	u32 val;
+	struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
+
+	if (vt8500_chip->regs->en == NO_REG)
+		return 0;
+
+	val = readl_relaxed(vt8500_chip->base + vt8500_chip->regs->en);
+	val |= BIT(offset);
+	writel_relaxed(val, vt8500_chip->base + vt8500_chip->regs->en);
+
+	return 0;
+}
+
+static void vt8500_gpio_free(struct gpio_chip *chip, unsigned offset)
+{
+	struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
+	u32 val;
+
+	if (vt8500_chip->regs->en == NO_REG)
+		return;
+
+	val = readl_relaxed(vt8500_chip->base + vt8500_chip->regs->en);
+	val &= ~BIT(offset);
+	writel_relaxed(val, vt8500_chip->base + vt8500_chip->regs->en);
+}
+
+static int vt8500_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
+
+	u32 val = readl_relaxed(vt8500_chip->base + vt8500_chip->regs->dir);
+	val &= ~BIT(offset);
+	writel_relaxed(val, vt8500_chip->base + vt8500_chip->regs->dir);
+
+	return 0;
+}
+
+static int vt8500_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
+								int value)
+{
+	struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
+
+	u32 val = readl_relaxed(vt8500_chip->base + vt8500_chip->regs->dir);
+	val |= BIT(offset);
+	writel_relaxed(val, vt8500_chip->base + vt8500_chip->regs->dir);
+
+	if (value) {
+		val = readl_relaxed(vt8500_chip->base +
+						vt8500_chip->regs->data_out);
+		val |= BIT(offset);
+		writel_relaxed(val, vt8500_chip->base +
+						vt8500_chip->regs->data_out);
+	}
+	return 0;
+}
+
+static int vt8500_gpio_get_value(struct gpio_chip *chip, unsigned offset)
+{
+	struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
+
+	return (readl_relaxed(vt8500_chip->base + vt8500_chip->regs->data_in) >>
+								offset) & 1;
+}
+
+static void vt8500_gpio_set_value(struct gpio_chip *chip, unsigned offset,
+								int value)
+{
+	struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
+
+	u32 val = readl_relaxed(vt8500_chip->base +
+						vt8500_chip->regs->data_out);
+	if (value)
+		val |= BIT(offset);
+	else
+		val &= ~BIT(offset);
+
+	writel_relaxed(val, vt8500_chip->base + vt8500_chip->regs->data_out);
+}
+
+static int vt8500_of_xlate(struct gpio_chip *gc,
+			    const struct of_phandle_args *gpiospec, u32 *flags)
+{
+	/* bank if specificed in gpiospec->args[0] */
+	if (flags)
+		*flags = gpiospec->args[2];
+
+	return gpiospec->args[1];
+}
+
+static int vt8500_add_chips(struct platform_device *pdev, void __iomem *base,
+				const struct vt8500_gpio_data *data)
+{
+	struct vt8500_gpio_chip *vtchip;
+	struct gpio_chip *chip;
+	int i;
+	int pin_cnt = 0;
+
+	vtchip = devm_kzalloc(&pdev->dev,
+			sizeof(struct vt8500_gpio_chip) * data->num_banks,
+			GFP_KERNEL);
+	if (!vtchip) {
+		pr_err("%s: failed to allocate chip memory\n", __func__);
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < data->num_banks; i++) {
+		vtchip[i].base = base;
+		vtchip[i].regs = &data->banks[i];
+
+		chip = &vtchip[i].chip;
+
+		chip->of_xlate = vt8500_of_xlate;
+		chip->of_gpio_n_cells = 3;
+		chip->of_node = pdev->dev.of_node;
+
+		chip->request = vt8500_gpio_request;
+		chip->free = vt8500_gpio_free;
+		chip->direction_input = vt8500_gpio_direction_input;
+		chip->direction_output = vt8500_gpio_direction_output;
+		chip->get = vt8500_gpio_get_value;
+		chip->set = vt8500_gpio_set_value;
+		chip->can_sleep = 0;
+		chip->base = pin_cnt;
+		chip->ngpio = data->banks[i].ngpio;
+
+		pin_cnt += data->banks[i].ngpio;
+
+		gpiochip_add(chip);
+	}
+	return 0;
+}
+
+static struct of_device_id vt8500_gpio_dt_ids[] = {
+	{ .compatible = "via,vt8500-gpio", .data = &vt8500_data, },
+	{ .compatible = "wm,wm8505-gpio", .data = &wm8505_data, },
+	{ .compatible = "wm,wm8650-gpio", .data = &wm8650_data, },
+	{ /* Sentinel */ },
+};
+
+static int __devinit vt8500_gpio_probe(struct platform_device *pdev)
+{
+	void __iomem *gpio_base;
+	struct device_node *np;
+	const struct of_device_id *of_id =
+				of_match_device(vt8500_gpio_dt_ids, &pdev->dev);
+
+	if (!of_id) {
+		dev_err(&pdev->dev, "Failed to find gpio controller\n");
+		return -ENODEV;
+	}
+
+	np = pdev->dev.of_node;
+	if (!np) {
+		dev_err(&pdev->dev, "Missing GPIO description in devicetree\n");
+		return -EFAULT;
+	}
+
+	gpio_base = of_iomap(np, 0);
+	if (!gpio_base) {
+		dev_err(&pdev->dev, "Unable to map GPIO registers\n");
+		of_node_put(np);
+		return -ENOMEM;
+	}
+
+	vt8500_add_chips(pdev, gpio_base, of_id->data);
+
+	return 0;
+}
+
+static struct platform_driver vt8500_gpio_driver = {
+	.probe		= vt8500_gpio_probe,
+	.driver		= {
+		.name	= "vt8500-gpio",
+		.owner	= THIS_MODULE,
+		.of_match_table = vt8500_gpio_dt_ids,
+	},
+};
+
+module_platform_driver(vt8500_gpio_driver);
+
+MODULE_DESCRIPTION("VT8500 GPIO Driver");
+MODULE_AUTHOR("Tony Prisk <linux@prisktech.co.nz>");
+MODULE_LICENSE("GPL v2");
+MODULE_DEVICE_TABLE(of, vt8500_gpio_dt_ids);
diff --git a/drivers/gpio/gpio-wm831x.c b/drivers/gpio/gpio-wm831x.c
index e56a216..b6eda35 100644
--- a/drivers/gpio/gpio-wm831x.c
+++ b/drivers/gpio/gpio-wm831x.c
@@ -250,7 +250,8 @@ static int __devinit wm831x_gpio_probe(struct platform_device *pdev)
 	struct wm831x_gpio *wm831x_gpio;
 	int ret;
 
-	wm831x_gpio = kzalloc(sizeof(*wm831x_gpio), GFP_KERNEL);
+	wm831x_gpio = devm_kzalloc(&pdev->dev, sizeof(*wm831x_gpio),
+				   GFP_KERNEL);
 	if (wm831x_gpio == NULL)
 		return -ENOMEM;
 
@@ -265,30 +266,20 @@ static int __devinit wm831x_gpio_probe(struct platform_device *pdev)
 
 	ret = gpiochip_add(&wm831x_gpio->gpio_chip);
 	if (ret < 0) {
-		dev_err(&pdev->dev, "Could not register gpiochip, %d\n",
-			ret);
-		goto err;
+		dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret);
+		return ret;
 	}
 
 	platform_set_drvdata(pdev, wm831x_gpio);
 
 	return ret;
-
-err:
-	kfree(wm831x_gpio);
-	return ret;
 }
 
 static int __devexit wm831x_gpio_remove(struct platform_device *pdev)
 {
 	struct wm831x_gpio *wm831x_gpio = platform_get_drvdata(pdev);
-	int ret;
-
-	ret = gpiochip_remove(&wm831x_gpio->gpio_chip);
-	if (ret == 0)
-		kfree(wm831x_gpio);
 
-	return ret;
+	return  gpiochip_remove(&wm831x_gpio->gpio_chip);
 }
 
 static struct platform_driver wm831x_gpio_driver = {
diff --git a/drivers/gpio/gpio-wm8350.c b/drivers/gpio/gpio-wm8350.c
index a06af51..fb42938 100644
--- a/drivers/gpio/gpio-wm8350.c
+++ b/drivers/gpio/gpio-wm8350.c
@@ -116,7 +116,8 @@ static int __devinit wm8350_gpio_probe(struct platform_device *pdev)
 	struct wm8350_gpio_data *wm8350_gpio;
 	int ret;
 
-	wm8350_gpio = kzalloc(sizeof(*wm8350_gpio), GFP_KERNEL);
+	wm8350_gpio = devm_kzalloc(&pdev->dev, sizeof(*wm8350_gpio),
+				   GFP_KERNEL);
 	if (wm8350_gpio == NULL)
 		return -ENOMEM;
 
@@ -131,30 +132,20 @@ static int __devinit wm8350_gpio_probe(struct platform_device *pdev)
 
 	ret = gpiochip_add(&wm8350_gpio->gpio_chip);
 	if (ret < 0) {
-		dev_err(&pdev->dev, "Could not register gpiochip, %d\n",
-			ret);
-		goto err;
+		dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret);
+		return ret;
 	}
 
 	platform_set_drvdata(pdev, wm8350_gpio);
 
 	return ret;
-
-err:
-	kfree(wm8350_gpio);
-	return ret;
 }
 
 static int __devexit wm8350_gpio_remove(struct platform_device *pdev)
 {
 	struct wm8350_gpio_data *wm8350_gpio = platform_get_drvdata(pdev);
-	int ret;
-
-	ret = gpiochip_remove(&wm8350_gpio->gpio_chip);
-	if (ret == 0)
-		kfree(wm8350_gpio);
 
-	return ret;
+	return gpiochip_remove(&wm8350_gpio->gpio_chip);
 }
 
 static struct platform_driver wm8350_gpio_driver = {
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index de0213c..5d6c71e 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -1773,56 +1773,102 @@ static void gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip)
 	}
 }
 
-static int gpiolib_show(struct seq_file *s, void *unused)
+static void *gpiolib_seq_start(struct seq_file *s, loff_t *pos)
 {
-	struct gpio_chip	*chip = NULL;
-	unsigned		gpio;
-	int			started = 0;
+	struct gpio_chip *chip = NULL;
+	unsigned int gpio;
+	void *ret = NULL;
+	loff_t index = 0;
 
 	/* REVISIT this isn't locked against gpio_chip removal ... */
 
 	for (gpio = 0; gpio_is_valid(gpio); gpio++) {
-		struct device *dev;
-
-		if (chip == gpio_desc[gpio].chip)
+		if (gpio_desc[gpio].chip == chip)
 			continue;
+
 		chip = gpio_desc[gpio].chip;
 		if (!chip)
 			continue;
 
-		seq_printf(s, "%sGPIOs %d-%d",
-				started ? "\n" : "",
-				chip->base, chip->base + chip->ngpio - 1);
-		dev = chip->dev;
-		if (dev)
-			seq_printf(s, ", %s/%s",
-				dev->bus ? dev->bus->name : "no-bus",
-				dev_name(dev));
-		if (chip->label)
-			seq_printf(s, ", %s", chip->label);
-		if (chip->can_sleep)
-			seq_printf(s, ", can sleep");
-		seq_printf(s, ":\n");
-
-		started = 1;
-		if (chip->dbg_show)
-			chip->dbg_show(s, chip);
-		else
-			gpiolib_dbg_show(s, chip);
+		if (index++ >= *pos) {
+			ret = chip;
+			break;
+		}
 	}
+
+	s->private = "";
+
+	return ret;
+}
+
+static void *gpiolib_seq_next(struct seq_file *s, void *v, loff_t *pos)
+{
+	struct gpio_chip *chip = v;
+	unsigned int gpio;
+	void *ret = NULL;
+
+	/* skip GPIOs provided by the current chip */
+	for (gpio = chip->base + chip->ngpio; gpio_is_valid(gpio); gpio++) {
+		chip = gpio_desc[gpio].chip;
+		if (chip) {
+			ret = chip;
+			break;
+		}
+	}
+
+	s->private = "\n";
+	++*pos;
+
+	return ret;
+}
+
+static void gpiolib_seq_stop(struct seq_file *s, void *v)
+{
+}
+
+static int gpiolib_seq_show(struct seq_file *s, void *v)
+{
+	struct gpio_chip *chip = v;
+	struct device *dev;
+
+	seq_printf(s, "%sGPIOs %d-%d", (char *)s->private,
+			chip->base, chip->base + chip->ngpio - 1);
+	dev = chip->dev;
+	if (dev)
+		seq_printf(s, ", %s/%s", dev->bus ? dev->bus->name : "no-bus",
+			dev_name(dev));
+	if (chip->label)
+		seq_printf(s, ", %s", chip->label);
+	if (chip->can_sleep)
+		seq_printf(s, ", can sleep");
+	seq_printf(s, ":\n");
+
+	if (chip->dbg_show)
+		chip->dbg_show(s, chip);
+	else
+		gpiolib_dbg_show(s, chip);
+
 	return 0;
 }
 
+static const struct seq_operations gpiolib_seq_ops = {
+	.start = gpiolib_seq_start,
+	.next = gpiolib_seq_next,
+	.stop = gpiolib_seq_stop,
+	.show = gpiolib_seq_show,
+};
+
 static int gpiolib_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, gpiolib_show, NULL);
+	return seq_open(file, &gpiolib_seq_ops);
 }
 
 static const struct file_operations gpiolib_operations = {
+	.owner		= THIS_MODULE,
 	.open		= gpiolib_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
-	.release	= single_release,
+	.release	= seq_release,
 };
 
 static int __init gpiolib_debugfs_init(void)
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 90e2808..18321b68b 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -22,7 +22,7 @@ menuconfig DRM
 config DRM_USB
 	tristate
 	depends on DRM
-	depends on USB_ARCH_HAS_HCD
+	depends on USB_SUPPORT && USB_ARCH_HAS_HCD
 	select USB
 
 config DRM_KMS_HELPER
@@ -54,6 +54,21 @@ config DRM_TTM
 	  GPU memory types. Will be enabled automatically if a device driver
 	  uses it.
 
+config DRM_GEM_CMA_HELPER
+	bool
+	depends on DRM
+	help
+	  Choose this if you need the GEM CMA helper functions
+
+config DRM_KMS_CMA_HELPER
+	bool
+	select DRM_GEM_CMA_HELPER
+	select FB_SYS_FILLRECT
+	select FB_SYS_COPYAREA
+	select FB_SYS_IMAGEBLIT
+	help
+	  Choose this if you need the KMS CMA helper functions
+
 config DRM_TDFX
 	tristate "3dfx Banshee/Voodoo3+"
 	depends on DRM && PCI
@@ -193,3 +208,5 @@ source "drivers/gpu/drm/ast/Kconfig"
 source "drivers/gpu/drm/mgag200/Kconfig"
 
 source "drivers/gpu/drm/cirrus/Kconfig"
+
+source "drivers/gpu/drm/shmobile/Kconfig"
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index f65f65e..2ff5cef 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -15,11 +15,13 @@ drm-y       :=	drm_auth.o drm_buffer.o drm_bufs.o drm_cache.o \
 		drm_trace_points.o drm_global.o drm_prime.o
 
 drm-$(CONFIG_COMPAT) += drm_ioc32.o
+drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o
 
 drm-usb-y   := drm_usb.o
 
 drm_kms_helper-y := drm_fb_helper.o drm_crtc_helper.o drm_dp_i2c_helper.o
 drm_kms_helper-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o
+drm_kms_helper-$(CONFIG_DRM_KMS_CMA_HELPER) += drm_fb_cma_helper.o
 
 obj-$(CONFIG_DRM_KMS_HELPER) += drm_kms_helper.o
 
@@ -45,4 +47,5 @@ obj-$(CONFIG_DRM_EXYNOS) +=exynos/
 obj-$(CONFIG_DRM_GMA500) += gma500/
 obj-$(CONFIG_DRM_UDL) += udl/
 obj-$(CONFIG_DRM_AST) += ast/
+obj-$(CONFIG_DRM_SHMOBILE) +=shmobile/
 obj-y			+= i2c/
diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h
index d4af9ed..20a437f 100644
--- a/drivers/gpu/drm/ast/ast_drv.h
+++ b/drivers/gpu/drm/ast/ast_drv.h
@@ -94,7 +94,6 @@ struct ast_private {
 		struct drm_global_reference mem_global_ref;
 		struct ttm_bo_global_ref bo_global_ref;
 		struct ttm_bo_device bdev;
-		atomic_t validate_sequence;
 	} ttm;
 
 	struct drm_gem_object *cursor_cache;
diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c
index a712caf..f3b2a7c 100644
--- a/drivers/gpu/drm/ast/ast_mode.c
+++ b/drivers/gpu/drm/ast/ast_mode.c
@@ -737,6 +737,7 @@ static int ast_get_modes(struct drm_connector *connector)
 	if (edid) {
 		drm_mode_connector_update_edid_property(&ast_connector->base, edid);
 		ret = drm_add_edid_modes(connector, edid);
+		kfree(edid);
 		return ret;
 	} else
 		drm_mode_connector_update_edid_property(&ast_connector->base, NULL);
diff --git a/drivers/gpu/drm/cirrus/cirrus_drv.h b/drivers/gpu/drm/cirrus/cirrus_drv.h
index 64ea597..5d04564 100644
--- a/drivers/gpu/drm/cirrus/cirrus_drv.h
+++ b/drivers/gpu/drm/cirrus/cirrus_drv.h
@@ -143,7 +143,6 @@ struct cirrus_device {
 		struct drm_global_reference mem_global_ref;
 		struct ttm_bo_global_ref bo_global_ref;
 		struct ttm_bo_device bdev;
-		atomic_t validate_sequence;
 	} ttm;
 	bool mm_inited;
 };
diff --git a/drivers/gpu/drm/drm_cache.c b/drivers/gpu/drm/drm_cache.c
index 08758e0..3dbc7f1 100644
--- a/drivers/gpu/drm/drm_cache.c
+++ b/drivers/gpu/drm/drm_cache.c
@@ -37,12 +37,13 @@ drm_clflush_page(struct page *page)
 {
 	uint8_t *page_virtual;
 	unsigned int i;
+	const int size = boot_cpu_data.x86_clflush_size;
 
 	if (unlikely(page == NULL))
 		return;
 
 	page_virtual = kmap_atomic(page);
-	for (i = 0; i < PAGE_SIZE; i += boot_cpu_data.x86_clflush_size)
+	for (i = 0; i < PAGE_SIZE; i += size)
 		clflush(page_virtual + i);
 	kunmap_atomic(page_virtual);
 }
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 6fbfc24..c317f72 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -2169,6 +2169,8 @@ static int format_check(const struct drm_mode_fb_cmd2 *r)
 	case DRM_FORMAT_NV21:
 	case DRM_FORMAT_NV16:
 	case DRM_FORMAT_NV61:
+	case DRM_FORMAT_NV24:
+	case DRM_FORMAT_NV42:
 	case DRM_FORMAT_YUV410:
 	case DRM_FORMAT_YVU410:
 	case DRM_FORMAT_YUV411:
@@ -3718,6 +3720,8 @@ int drm_format_num_planes(uint32_t format)
 	case DRM_FORMAT_NV21:
 	case DRM_FORMAT_NV16:
 	case DRM_FORMAT_NV61:
+	case DRM_FORMAT_NV24:
+	case DRM_FORMAT_NV42:
 		return 2;
 	default:
 		return 1;
@@ -3751,6 +3755,8 @@ int drm_format_plane_cpp(uint32_t format, int plane)
 	case DRM_FORMAT_NV21:
 	case DRM_FORMAT_NV16:
 	case DRM_FORMAT_NV61:
+	case DRM_FORMAT_NV24:
+	case DRM_FORMAT_NV42:
 		return plane ? 2 : 1;
 	case DRM_FORMAT_YUV410:
 	case DRM_FORMAT_YVU410:
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index 3252e70..8fa9d52 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -968,7 +968,7 @@ static void output_poll_execute(struct work_struct *work)
 	}
 
 	if (repoll)
-		queue_delayed_work(system_nrt_wq, delayed_work, DRM_OUTPUT_POLL_PERIOD);
+		schedule_delayed_work(delayed_work, DRM_OUTPUT_POLL_PERIOD);
 }
 
 void drm_kms_helper_poll_disable(struct drm_device *dev)
@@ -993,7 +993,7 @@ void drm_kms_helper_poll_enable(struct drm_device *dev)
 	}
 
 	if (poll)
-		queue_delayed_work(system_nrt_wq, &dev->mode_config.output_poll_work, DRM_OUTPUT_POLL_PERIOD);
+		schedule_delayed_work(&dev->mode_config.output_poll_work, DRM_OUTPUT_POLL_PERIOD);
 }
 EXPORT_SYMBOL(drm_kms_helper_poll_enable);
 
@@ -1020,6 +1020,6 @@ void drm_helper_hpd_irq_event(struct drm_device *dev)
 	/* kill timer and schedule immediate execution, this doesn't block */
 	cancel_delayed_work(&dev->mode_config.output_poll_work);
 	if (drm_kms_helper_poll)
-		queue_delayed_work(system_nrt_wq, &dev->mode_config.output_poll_work, 0);
+		schedule_delayed_work(&dev->mode_config.output_poll_work, 0);
 }
 EXPORT_SYMBOL(drm_helper_hpd_irq_event);
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 9238de4..1490e76 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -156,14 +156,14 @@ static struct drm_ioctl_desc drm_ioctls[] = {
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPROPERTY, drm_mode_connector_property_set_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPBLOB, drm_mode_getblob_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB2, drm_mode_addfb2, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB2, drm_mode_addfb2, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_PAGE_FLIP, drm_mode_page_flip_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATE_DUMB, drm_mode_create_dumb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_MAP_DUMB, drm_mode_mmap_dumb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_DESTROY_DUMB, drm_mode_destroy_dumb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATE_DUMB, drm_mode_create_dumb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_MAP_DUMB, drm_mode_mmap_dumb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_DESTROY_DUMB, drm_mode_destroy_dumb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_GETPROPERTIES, drm_mode_obj_get_properties_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_SETPROPERTY, drm_mode_obj_set_property_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 };
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index b7ee230..289c9b1 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -161,7 +161,7 @@ MODULE_PARM_DESC(edid_fixup,
  * Sanity check the EDID block (base or extension).  Return 0 if the block
  * doesn't check out, or 1 if it's valid.
  */
-bool drm_edid_block_valid(u8 *raw_edid, int block)
+bool drm_edid_block_valid(u8 *raw_edid, int block, bool print_bad_edid)
 {
 	int i;
 	u8 csum = 0;
@@ -184,7 +184,9 @@ bool drm_edid_block_valid(u8 *raw_edid, int block)
 	for (i = 0; i < EDID_LENGTH; i++)
 		csum += raw_edid[i];
 	if (csum) {
-		DRM_ERROR("EDID checksum is invalid, remainder is %d\n", csum);
+		if (print_bad_edid) {
+			DRM_ERROR("EDID checksum is invalid, remainder is %d\n", csum);
+		}
 
 		/* allow CEA to slide through, switches mangle this */
 		if (raw_edid[0] != 0x02)
@@ -210,7 +212,7 @@ bool drm_edid_block_valid(u8 *raw_edid, int block)
 	return 1;
 
 bad:
-	if (raw_edid) {
+	if (raw_edid && print_bad_edid) {
 		printk(KERN_ERR "Raw EDID:\n");
 		print_hex_dump(KERN_ERR, " \t", DUMP_PREFIX_NONE, 16, 1,
 			       raw_edid, EDID_LENGTH, false);
@@ -234,7 +236,7 @@ bool drm_edid_is_valid(struct edid *edid)
 		return false;
 
 	for (i = 0; i <= edid->extensions; i++)
-		if (!drm_edid_block_valid(raw + i * EDID_LENGTH, i))
+		if (!drm_edid_block_valid(raw + i * EDID_LENGTH, i, true))
 			return false;
 
 	return true;
@@ -257,6 +259,8 @@ drm_do_probe_ddc_edid(struct i2c_adapter *adapter, unsigned char *buf,
 		      int block, int len)
 {
 	unsigned char start = block * EDID_LENGTH;
+	unsigned char segment = block >> 1;
+	unsigned char xfers = segment ? 3 : 2;
 	int ret, retries = 5;
 
 	/* The core i2c driver will automatically retry the transfer if the
@@ -268,6 +272,11 @@ drm_do_probe_ddc_edid(struct i2c_adapter *adapter, unsigned char *buf,
 	do {
 		struct i2c_msg msgs[] = {
 			{
+				.addr	= DDC_SEGMENT_ADDR,
+				.flags	= 0,
+				.len	= 1,
+				.buf	= &segment,
+			}, {
 				.addr	= DDC_ADDR,
 				.flags	= 0,
 				.len	= 1,
@@ -279,15 +288,21 @@ drm_do_probe_ddc_edid(struct i2c_adapter *adapter, unsigned char *buf,
 				.buf	= buf,
 			}
 		};
-		ret = i2c_transfer(adapter, msgs, 2);
+
+	/*
+	 * Avoid sending the segment addr to not upset non-compliant ddc
+	 * monitors.
+	 */
+		ret = i2c_transfer(adapter, &msgs[3 - xfers], xfers);
+
 		if (ret == -ENXIO) {
 			DRM_DEBUG_KMS("drm: skipping non-existent adapter %s\n",
 					adapter->name);
 			break;
 		}
-	} while (ret != 2 && --retries);
+	} while (ret != xfers && --retries);
 
-	return ret == 2 ? 0 : -1;
+	return ret == xfers ? 0 : -1;
 }
 
 static bool drm_edid_is_zero(u8 *in_edid, int length)
@@ -306,6 +321,7 @@ drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter)
 {
 	int i, j = 0, valid_extensions = 0;
 	u8 *block, *new;
+	bool print_bad_edid = !connector->bad_edid_counter || (drm_debug & DRM_UT_KMS);
 
 	if ((block = kmalloc(EDID_LENGTH, GFP_KERNEL)) == NULL)
 		return NULL;
@@ -314,7 +330,7 @@ drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter)
 	for (i = 0; i < 4; i++) {
 		if (drm_do_probe_ddc_edid(adapter, block, 0, EDID_LENGTH))
 			goto out;
-		if (drm_edid_block_valid(block, 0))
+		if (drm_edid_block_valid(block, 0, print_bad_edid))
 			break;
 		if (i == 0 && drm_edid_is_zero(block, EDID_LENGTH)) {
 			connector->null_edid_counter++;
@@ -339,7 +355,7 @@ drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter)
 				  block + (valid_extensions + 1) * EDID_LENGTH,
 				  j, EDID_LENGTH))
 				goto out;
-			if (drm_edid_block_valid(block + (valid_extensions + 1) * EDID_LENGTH, j)) {
+			if (drm_edid_block_valid(block + (valid_extensions + 1) * EDID_LENGTH, j, print_bad_edid)) {
 				valid_extensions++;
 				break;
 			}
@@ -362,8 +378,11 @@ drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter)
 	return block;
 
 carp:
-	dev_warn(connector->dev->dev, "%s: EDID block %d invalid.\n",
-		 drm_get_connector_name(connector), j);
+	if (print_bad_edid) {
+		dev_warn(connector->dev->dev, "%s: EDID block %d invalid.\n",
+			 drm_get_connector_name(connector), j);
+	}
+	connector->bad_edid_counter++;
 
 out:
 	kfree(block);
@@ -402,10 +421,7 @@ struct edid *drm_get_edid(struct drm_connector *connector,
 	if (drm_probe_ddc(adapter))
 		edid = (struct edid *)drm_do_get_edid(connector, adapter);
 
-	connector->display_info.raw_edid = (char *)edid;
-
 	return edid;
-
 }
 EXPORT_SYMBOL(drm_get_edid);
 
@@ -1523,16 +1539,57 @@ do_cea_modes (struct drm_connector *connector, u8 *db, u8 len)
 }
 
 static int
+cea_db_payload_len(const u8 *db)
+{
+	return db[0] & 0x1f;
+}
+
+static int
+cea_db_tag(const u8 *db)
+{
+	return db[0] >> 5;
+}
+
+static int
+cea_revision(const u8 *cea)
+{
+	return cea[1];
+}
+
+static int
+cea_db_offsets(const u8 *cea, int *start, int *end)
+{
+	/* Data block offset in CEA extension block */
+	*start = 4;
+	*end = cea[2];
+	if (*end == 0)
+		*end = 127;
+	if (*end < 4 || *end > 127)
+		return -ERANGE;
+	return 0;
+}
+
+#define for_each_cea_db(cea, i, start, end) \
+	for ((i) = (start); (i) < (end) && (i) + cea_db_payload_len(&(cea)[(i)]) < (end); (i) += cea_db_payload_len(&(cea)[(i)]) + 1)
+
+static int
 add_cea_modes(struct drm_connector *connector, struct edid *edid)
 {
 	u8 * cea = drm_find_cea_extension(edid);
 	u8 * db, dbl;
 	int modes = 0;
 
-	if (cea && cea[1] >= 3) {
-		for (db = cea + 4; db < cea + cea[2]; db += dbl + 1) {
-			dbl = db[0] & 0x1f;
-			if (((db[0] & 0xe0) >> 5) == VIDEO_BLOCK)
+	if (cea && cea_revision(cea) >= 3) {
+		int i, start, end;
+
+		if (cea_db_offsets(cea, &start, &end))
+			return 0;
+
+		for_each_cea_db(cea, i, start, end) {
+			db = &cea[i];
+			dbl = cea_db_payload_len(db);
+
+			if (cea_db_tag(db) == VIDEO_BLOCK)
 				modes += do_cea_modes (connector, db+1, dbl);
 		}
 	}
@@ -1541,19 +1598,28 @@ add_cea_modes(struct drm_connector *connector, struct edid *edid)
 }
 
 static void
-parse_hdmi_vsdb(struct drm_connector *connector, uint8_t *db)
+parse_hdmi_vsdb(struct drm_connector *connector, const u8 *db)
 {
-	connector->eld[5] |= (db[6] >> 7) << 1;  /* Supports_AI */
-
-	connector->dvi_dual = db[6] & 1;
-	connector->max_tmds_clock = db[7] * 5;
+	u8 len = cea_db_payload_len(db);
 
-	connector->latency_present[0] = db[8] >> 7;
-	connector->latency_present[1] = (db[8] >> 6) & 1;
-	connector->video_latency[0] = db[9];
-	connector->audio_latency[0] = db[10];
-	connector->video_latency[1] = db[11];
-	connector->audio_latency[1] = db[12];
+	if (len >= 6) {
+		connector->eld[5] |= (db[6] >> 7) << 1;  /* Supports_AI */
+		connector->dvi_dual = db[6] & 1;
+	}
+	if (len >= 7)
+		connector->max_tmds_clock = db[7] * 5;
+	if (len >= 8) {
+		connector->latency_present[0] = db[8] >> 7;
+		connector->latency_present[1] = (db[8] >> 6) & 1;
+	}
+	if (len >= 9)
+		connector->video_latency[0] = db[9];
+	if (len >= 10)
+		connector->audio_latency[0] = db[10];
+	if (len >= 11)
+		connector->video_latency[1] = db[11];
+	if (len >= 12)
+		connector->audio_latency[1] = db[12];
 
 	DRM_LOG_KMS("HDMI: DVI dual %d, "
 		    "max TMDS clock %d, "
@@ -1577,6 +1643,21 @@ monitor_name(struct detailed_timing *t, void *data)
 		*(u8 **)data = t->data.other_data.data.str.str;
 }
 
+static bool cea_db_is_hdmi_vsdb(const u8 *db)
+{
+	int hdmi_id;
+
+	if (cea_db_tag(db) != VENDOR_BLOCK)
+		return false;
+
+	if (cea_db_payload_len(db) < 5)
+		return false;
+
+	hdmi_id = db[1] | (db[2] << 8) | (db[3] << 16);
+
+	return hdmi_id == HDMI_IDENTIFIER;
+}
+
 /**
  * drm_edid_to_eld - build ELD from EDID
  * @connector: connector corresponding to the HDMI/DP sink
@@ -1623,29 +1704,40 @@ void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid)
 	eld[18] = edid->prod_code[0];
 	eld[19] = edid->prod_code[1];
 
-	if (cea[1] >= 3)
-		for (db = cea + 4; db < cea + cea[2]; db += dbl + 1) {
-			dbl = db[0] & 0x1f;
-			
-			switch ((db[0] & 0xe0) >> 5) {
+	if (cea_revision(cea) >= 3) {
+		int i, start, end;
+
+		if (cea_db_offsets(cea, &start, &end)) {
+			start = 0;
+			end = 0;
+		}
+
+		for_each_cea_db(cea, i, start, end) {
+			db = &cea[i];
+			dbl = cea_db_payload_len(db);
+
+			switch (cea_db_tag(db)) {
 			case AUDIO_BLOCK:
 				/* Audio Data Block, contains SADs */
 				sad_count = dbl / 3;
-				memcpy(eld + 20 + mnl, &db[1], dbl);
+				if (dbl >= 1)
+					memcpy(eld + 20 + mnl, &db[1], dbl);
 				break;
 			case SPEAKER_BLOCK:
-                                /* Speaker Allocation Data Block */
-				eld[7] = db[1];
+				/* Speaker Allocation Data Block */
+				if (dbl >= 1)
+					eld[7] = db[1];
 				break;
 			case VENDOR_BLOCK:
 				/* HDMI Vendor-Specific Data Block */
-				if (db[1] == 0x03 && db[2] == 0x0c && db[3] == 0)
+				if (cea_db_is_hdmi_vsdb(db))
 					parse_hdmi_vsdb(connector, db);
 				break;
 			default:
 				break;
 			}
 		}
+	}
 	eld[5] |= sad_count << 4;
 	eld[2] = (20 + mnl + sad_count * 3 + 3) / 4;
 
@@ -1723,38 +1815,26 @@ EXPORT_SYMBOL(drm_select_eld);
 bool drm_detect_hdmi_monitor(struct edid *edid)
 {
 	u8 *edid_ext;
-	int i, hdmi_id;
+	int i;
 	int start_offset, end_offset;
-	bool is_hdmi = false;
 
 	edid_ext = drm_find_cea_extension(edid);
 	if (!edid_ext)
-		goto end;
+		return false;
 
-	/* Data block offset in CEA extension block */
-	start_offset = 4;
-	end_offset = edid_ext[2];
+	if (cea_db_offsets(edid_ext, &start_offset, &end_offset))
+		return false;
 
 	/*
 	 * Because HDMI identifier is in Vendor Specific Block,
 	 * search it from all data blocks of CEA extension.
 	 */
-	for (i = start_offset; i < end_offset;
-		/* Increased by data block len */
-		i += ((edid_ext[i] & 0x1f) + 1)) {
-		/* Find vendor specific block */
-		if ((edid_ext[i] >> 5) == VENDOR_BLOCK) {
-			hdmi_id = edid_ext[i + 1] | (edid_ext[i + 2] << 8) |
-				  edid_ext[i + 3] << 16;
-			/* Find HDMI identifier */
-			if (hdmi_id == HDMI_IDENTIFIER)
-				is_hdmi = true;
-			break;
-		}
+	for_each_cea_db(edid_ext, i, start_offset, end_offset) {
+		if (cea_db_is_hdmi_vsdb(&edid_ext[i]))
+			return true;
 	}
 
-end:
-	return is_hdmi;
+	return false;
 }
 EXPORT_SYMBOL(drm_detect_hdmi_monitor);
 
@@ -1786,15 +1866,13 @@ bool drm_detect_monitor_audio(struct edid *edid)
 		goto end;
 	}
 
-	/* Data block offset in CEA extension block */
-	start_offset = 4;
-	end_offset = edid_ext[2];
+	if (cea_db_offsets(edid_ext, &start_offset, &end_offset))
+		goto end;
 
-	for (i = start_offset; i < end_offset;
-			i += ((edid_ext[i] & 0x1f) + 1)) {
-		if ((edid_ext[i] >> 5) == AUDIO_BLOCK) {
+	for_each_cea_db(edid_ext, i, start_offset, end_offset) {
+		if (cea_db_tag(&edid_ext[i]) == AUDIO_BLOCK) {
 			has_audio = true;
-			for (j = 1; j < (edid_ext[i] & 0x1f); j += 3)
+			for (j = 1; j < cea_db_payload_len(&edid_ext[i]) + 1; j += 3)
 				DRM_DEBUG_KMS("CEA audio format %d\n",
 					      (edid_ext[i + j] >> 3) & 0xf);
 			goto end;
diff --git a/drivers/gpu/drm/drm_edid_load.c b/drivers/gpu/drm/drm_edid_load.c
index 0303935..ea9cdab 100644
--- a/drivers/gpu/drm/drm_edid_load.c
+++ b/drivers/gpu/drm/drm_edid_load.c
@@ -114,8 +114,8 @@ static u8 generic_edid[GENERIC_EDIDS][128] = {
 	},
 };
 
-static int edid_load(struct drm_connector *connector, char *name,
-		     char *connector_name)
+static u8 *edid_load(struct drm_connector *connector, char *name,
+			char *connector_name)
 {
 	const struct firmware *fw;
 	struct platform_device *pdev;
@@ -123,6 +123,7 @@ static int edid_load(struct drm_connector *connector, char *name,
 	int fwsize, expected;
 	int builtin = 0, err = 0;
 	int i, valid_extensions = 0;
+	bool print_bad_edid = !connector->bad_edid_counter || (drm_debug & DRM_UT_KMS);
 
 	pdev = platform_device_register_simple(connector_name, -1, NULL, 0);
 	if (IS_ERR(pdev)) {
@@ -173,7 +174,8 @@ static int edid_load(struct drm_connector *connector, char *name,
 	}
 	memcpy(edid, fwdata, fwsize);
 
-	if (!drm_edid_block_valid(edid, 0)) {
+	if (!drm_edid_block_valid(edid, 0, print_bad_edid)) {
+		connector->bad_edid_counter++;
 		DRM_ERROR("Base block of EDID firmware \"%s\" is invalid ",
 		    name);
 		kfree(edid);
@@ -185,7 +187,7 @@ static int edid_load(struct drm_connector *connector, char *name,
 		if (i != valid_extensions + 1)
 			memcpy(edid + (valid_extensions + 1) * EDID_LENGTH,
 			    edid + i * EDID_LENGTH, EDID_LENGTH);
-		if (drm_edid_block_valid(edid + i * EDID_LENGTH, i))
+		if (drm_edid_block_valid(edid + i * EDID_LENGTH, i, print_bad_edid))
 			valid_extensions++;
 	}
 
@@ -205,7 +207,6 @@ static int edid_load(struct drm_connector *connector, char *name,
 		edid = new_edid;
 	}
 
-	connector->display_info.raw_edid = edid;
 	DRM_INFO("Got %s EDID base block and %d extension%s from "
 	    "\"%s\" for connector \"%s\"\n", builtin ? "built-in" :
 	    "external", valid_extensions, valid_extensions == 1 ? "" : "s",
@@ -215,7 +216,10 @@ relfw_out:
 	release_firmware(fw);
 
 out:
-	return err;
+	if (err)
+		return ERR_PTR(err);
+
+	return edid;
 }
 
 int drm_load_edid_firmware(struct drm_connector *connector)
@@ -223,6 +227,7 @@ int drm_load_edid_firmware(struct drm_connector *connector)
 	char *connector_name = drm_get_connector_name(connector);
 	char *edidname = edid_firmware, *last, *colon;
 	int ret;
+	struct edid *edid;
 
 	if (*edidname == '\0')
 		return 0;
@@ -240,13 +245,13 @@ int drm_load_edid_firmware(struct drm_connector *connector)
 	if (*last == '\n')
 		*last = '\0';
 
-	ret = edid_load(connector, edidname, connector_name);
-	if (ret)
+	edid = (struct edid *) edid_load(connector, edidname, connector_name);
+	if (IS_ERR_OR_NULL(edid))
 		return 0;
 
-	drm_mode_connector_update_edid_property(connector,
-	    (struct edid *) connector->display_info.raw_edid);
+	drm_mode_connector_update_edid_property(connector, edid);
+	ret = drm_add_edid_modes(connector, edid);
+	kfree(edid);
 
-	return drm_add_edid_modes(connector, (struct edid *)
-	    connector->display_info.raw_edid);
+	return ret;
 }
diff --git a/drivers/gpu/drm/drm_edid_modes.h b/drivers/gpu/drm/drm_edid_modes.h
index ff98a7e..57459b3 100644
--- a/drivers/gpu/drm/drm_edid_modes.h
+++ b/drivers/gpu/drm/drm_edid_modes.h
@@ -89,7 +89,7 @@ static const struct drm_display_mode drm_dmt_modes[] = {
 		   976, 1088, 0, 480, 486, 494, 517, 0,
 		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
 	/* 1024x768@43Hz, interlace */
-	{ DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 44900, 1024, 1032,
+	{ DRM_MODE("1024x768i", DRM_MODE_TYPE_DRIVER, 44900, 1024, 1032,
 		   1208, 1264, 0, 768, 768, 772, 817, 0,
 		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
 			DRM_MODE_FLAG_INTERLACE) },
@@ -395,7 +395,7 @@ static const struct drm_display_mode edid_est_modes[] = {
 	{ DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 65000, 1024, 1048,
 		   1184, 1344, 0,  768, 771, 777, 806, 0,
 		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 1024x768@60Hz */
-	{ DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER,44900, 1024, 1032,
+	{ DRM_MODE("1024x768i", DRM_MODE_TYPE_DRIVER,44900, 1024, 1032,
 		   1208, 1264, 0, 768, 768, 776, 817, 0,
 		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC | DRM_MODE_FLAG_INTERLACE) }, /* 1024x768@43Hz */
 	{ DRM_MODE("832x624", DRM_MODE_TYPE_DRIVER, 57284, 832, 864,
@@ -506,17 +506,17 @@ static const struct drm_display_mode edid_cea_modes[] = {
 		   1430, 1650, 0, 720, 725, 730, 750, 0,
 		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
 	/* 5 - 1920x1080i@60Hz */
-	{ DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2008,
+	{ DRM_MODE("1920x1080i", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2008,
 		   2052, 2200, 0, 1080, 1084, 1094, 1125, 0,
 		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
 			DRM_MODE_FLAG_INTERLACE) },
 	/* 6 - 1440x480i@60Hz */
-	{ DRM_MODE("1440x480", DRM_MODE_TYPE_DRIVER, 27000, 1440, 1478,
+	{ DRM_MODE("1440x480i", DRM_MODE_TYPE_DRIVER, 27000, 1440, 1478,
 		   1602, 1716, 0, 480, 488, 494, 525, 0,
 		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
 			DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK) },
 	/* 7 - 1440x480i@60Hz */
-	{ DRM_MODE("1440x480", DRM_MODE_TYPE_DRIVER, 27000, 1440, 1478,
+	{ DRM_MODE("1440x480i", DRM_MODE_TYPE_DRIVER, 27000, 1440, 1478,
 		   1602, 1716, 0, 480, 488, 494, 525, 0,
 		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
 			DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK) },
@@ -531,12 +531,12 @@ static const struct drm_display_mode edid_cea_modes[] = {
 		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
 			DRM_MODE_FLAG_DBLCLK) },
 	/* 10 - 2880x480i@60Hz */
-	{ DRM_MODE("2880x480", DRM_MODE_TYPE_DRIVER, 54000, 2880, 2956,
+	{ DRM_MODE("2880x480i", DRM_MODE_TYPE_DRIVER, 54000, 2880, 2956,
 		   3204, 3432, 0, 480, 488, 494, 525, 0,
 		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
 			DRM_MODE_FLAG_INTERLACE) },
 	/* 11 - 2880x480i@60Hz */
-	{ DRM_MODE("2880x480", DRM_MODE_TYPE_DRIVER, 54000, 2880, 2956,
+	{ DRM_MODE("2880x480i", DRM_MODE_TYPE_DRIVER, 54000, 2880, 2956,
 		   3204, 3432, 0, 480, 488, 494, 525, 0,
 		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
 			DRM_MODE_FLAG_INTERLACE) },
@@ -573,17 +573,17 @@ static const struct drm_display_mode edid_cea_modes[] = {
 		   1760, 1980, 0, 720, 725, 730, 750, 0,
 		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
 	/* 20 - 1920x1080i@50Hz */
-	{ DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2448,
+	{ DRM_MODE("1920x1080i", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2448,
 		   2492, 2640, 0, 1080, 1084, 1094, 1125, 0,
 		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
 			DRM_MODE_FLAG_INTERLACE) },
 	/* 21 - 1440x576i@50Hz */
-	{ DRM_MODE("1440x576", DRM_MODE_TYPE_DRIVER, 27000, 1440, 1464,
+	{ DRM_MODE("1440x576i", DRM_MODE_TYPE_DRIVER, 27000, 1440, 1464,
 		   1590, 1728, 0, 576, 580, 586, 625, 0,
 		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
 			DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK) },
 	/* 22 - 1440x576i@50Hz */
-	{ DRM_MODE("1440x576", DRM_MODE_TYPE_DRIVER, 27000, 1440, 1464,
+	{ DRM_MODE("1440x576i", DRM_MODE_TYPE_DRIVER, 27000, 1440, 1464,
 		   1590, 1728, 0, 576, 580, 586, 625, 0,
 		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
 			DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK) },
@@ -598,12 +598,12 @@ static const struct drm_display_mode edid_cea_modes[] = {
 		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
 			DRM_MODE_FLAG_DBLCLK) },
 	/* 25 - 2880x576i@50Hz */
-	{ DRM_MODE("2880x576", DRM_MODE_TYPE_DRIVER, 54000, 2880, 2928,
+	{ DRM_MODE("2880x576i", DRM_MODE_TYPE_DRIVER, 54000, 2880, 2928,
 		   3180, 3456, 0, 576, 580, 586, 625, 0,
 		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
 			DRM_MODE_FLAG_INTERLACE) },
 	/* 26 - 2880x576i@50Hz */
-	{ DRM_MODE("2880x576", DRM_MODE_TYPE_DRIVER, 54000, 2880, 2928,
+	{ DRM_MODE("2880x576i", DRM_MODE_TYPE_DRIVER, 54000, 2880, 2928,
 		   3180, 3456, 0, 576, 580, 586, 625, 0,
 		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
 			DRM_MODE_FLAG_INTERLACE) },
@@ -656,12 +656,12 @@ static const struct drm_display_mode edid_cea_modes[] = {
 		   3184, 3456, 0, 576, 581, 586, 625, 0,
 		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
 	/* 39 - 1920x1080i@50Hz */
-	{ DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 72000, 1920, 1952,
+	{ DRM_MODE("1920x1080i", DRM_MODE_TYPE_DRIVER, 72000, 1920, 1952,
 		   2120, 2304, 0, 1080, 1126, 1136, 1250, 0,
 		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC |
 			DRM_MODE_FLAG_INTERLACE) },
 	/* 40 - 1920x1080i@100Hz */
-	{ DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2448,
+	{ DRM_MODE("1920x1080i", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2448,
 		   2492, 2640, 0, 1080, 1084, 1094, 1125, 0,
 		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
 			DRM_MODE_FLAG_INTERLACE) },
@@ -688,7 +688,7 @@ static const struct drm_display_mode edid_cea_modes[] = {
 		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
 			DRM_MODE_FLAG_DBLCLK) },
 	/* 46 - 1920x1080i@120Hz */
-	{ DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2008,
+	{ DRM_MODE("1920x1080i", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2008,
 		   2052, 2200, 0, 1080, 1084, 1094, 1125, 0,
 		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
 			DRM_MODE_FLAG_INTERLACE) },
@@ -705,12 +705,12 @@ static const struct drm_display_mode edid_cea_modes[] = {
 		   798, 858, 0, 480, 489, 495, 525, 0,
 		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
 	/* 50 - 1440x480i@120Hz */
-	{ DRM_MODE("1440x480", DRM_MODE_TYPE_DRIVER, 54000, 1440, 1478,
+	{ DRM_MODE("1440x480i", DRM_MODE_TYPE_DRIVER, 54000, 1440, 1478,
 		   1602, 1716, 0, 480, 488, 494, 525, 0,
 		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
 			DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK) },
 	/* 51 - 1440x480i@120Hz */
-	{ DRM_MODE("1440x480", DRM_MODE_TYPE_DRIVER, 54000, 1440, 1478,
+	{ DRM_MODE("1440x480i", DRM_MODE_TYPE_DRIVER, 54000, 1440, 1478,
 		   1602, 1716, 0, 480, 488, 494, 525, 0,
 		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
 			DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK) },
@@ -723,12 +723,12 @@ static const struct drm_display_mode edid_cea_modes[] = {
 		   796, 864, 0, 576, 581, 586, 625, 0,
 		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
 	/* 54 - 1440x576i@200Hz */
-	{ DRM_MODE("1440x576", DRM_MODE_TYPE_DRIVER, 108000, 1440, 1464,
+	{ DRM_MODE("1440x576i", DRM_MODE_TYPE_DRIVER, 108000, 1440, 1464,
 		   1590, 1728, 0, 576, 580, 586, 625, 0,
 		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
 			DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK) },
 	/* 55 - 1440x576i@200Hz */
-	{ DRM_MODE("1440x576", DRM_MODE_TYPE_DRIVER, 108000, 1440, 1464,
+	{ DRM_MODE("1440x576i", DRM_MODE_TYPE_DRIVER, 108000, 1440, 1464,
 		   1590, 1728, 0, 576, 580, 586, 625, 0,
 		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
 			DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK) },
@@ -741,12 +741,12 @@ static const struct drm_display_mode edid_cea_modes[] = {
 		   798, 858, 0, 480, 489, 495, 525, 0,
 		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) },
 	/* 58 - 1440x480i@240 */
-	{ DRM_MODE("1440x480", DRM_MODE_TYPE_DRIVER, 108000, 1440, 1478,
+	{ DRM_MODE("1440x480i", DRM_MODE_TYPE_DRIVER, 108000, 1440, 1478,
 		   1602, 1716, 0, 480, 488, 494, 525, 0,
 		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
 			DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK) },
 	/* 59 - 1440x480i@240 */
-	{ DRM_MODE("1440x480", DRM_MODE_TYPE_DRIVER, 108000, 1440, 1478,
+	{ DRM_MODE("1440x480i", DRM_MODE_TYPE_DRIVER, 108000, 1440, 1478,
 		   1602, 1716, 0, 480, 488, 494, 525, 0,
 		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
 			DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK) },
diff --git a/drivers/gpu/drm/drm_fb_cma_helper.c b/drivers/gpu/drm/drm_fb_cma_helper.c
new file mode 100644
index 0000000..09e11a5
--- /dev/null
+++ b/drivers/gpu/drm/drm_fb_cma_helper.c
@@ -0,0 +1,406 @@
+/*
+ * drm kms/fb cma (contiguous memory allocator) helper functions
+ *
+ * Copyright (C) 2012 Analog Device Inc.
+ *   Author: Lars-Peter Clausen <lars@metafoo.de>
+ *
+ * Based on udl_fbdev.c
+ *  Copyright (C) 2012 Red Hat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <linux/module.h>
+
+struct drm_fb_cma {
+	struct drm_framebuffer		fb;
+	struct drm_gem_cma_object	*obj[4];
+};
+
+struct drm_fbdev_cma {
+	struct drm_fb_helper	fb_helper;
+	struct drm_fb_cma	*fb;
+};
+
+static inline struct drm_fbdev_cma *to_fbdev_cma(struct drm_fb_helper *helper)
+{
+	return container_of(helper, struct drm_fbdev_cma, fb_helper);
+}
+
+static inline struct drm_fb_cma *to_fb_cma(struct drm_framebuffer *fb)
+{
+	return container_of(fb, struct drm_fb_cma, fb);
+}
+
+static void drm_fb_cma_destroy(struct drm_framebuffer *fb)
+{
+	struct drm_fb_cma *fb_cma = to_fb_cma(fb);
+	int i;
+
+	for (i = 0; i < 4; i++) {
+		if (fb_cma->obj[i])
+			drm_gem_object_unreference_unlocked(&fb_cma->obj[i]->base);
+	}
+
+	drm_framebuffer_cleanup(fb);
+	kfree(fb_cma);
+}
+
+static int drm_fb_cma_create_handle(struct drm_framebuffer *fb,
+	struct drm_file *file_priv, unsigned int *handle)
+{
+	struct drm_fb_cma *fb_cma = to_fb_cma(fb);
+
+	return drm_gem_handle_create(file_priv,
+			&fb_cma->obj[0]->base, handle);
+}
+
+static struct drm_framebuffer_funcs drm_fb_cma_funcs = {
+	.destroy	= drm_fb_cma_destroy,
+	.create_handle	= drm_fb_cma_create_handle,
+};
+
+static struct drm_fb_cma *drm_fb_cma_alloc(struct drm_device *dev,
+	struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_cma_object **obj,
+	unsigned int num_planes)
+{
+	struct drm_fb_cma *fb_cma;
+	int ret;
+	int i;
+
+	fb_cma = kzalloc(sizeof(*fb_cma), GFP_KERNEL);
+	if (!fb_cma)
+		return ERR_PTR(-ENOMEM);
+
+	ret = drm_framebuffer_init(dev, &fb_cma->fb, &drm_fb_cma_funcs);
+	if (ret) {
+		dev_err(dev->dev, "Failed to initalize framebuffer: %d\n", ret);
+		kfree(fb_cma);
+		return ERR_PTR(ret);
+	}
+
+	drm_helper_mode_fill_fb_struct(&fb_cma->fb, mode_cmd);
+
+	for (i = 0; i < num_planes; i++)
+		fb_cma->obj[i] = obj[i];
+
+	return fb_cma;
+}
+
+/**
+ * drm_fb_cma_create() - (struct drm_mode_config_funcs *)->fb_create callback function
+ *
+ * If your hardware has special alignment or pitch requirements these should be
+ * checked before calling this function.
+ */
+struct drm_framebuffer *drm_fb_cma_create(struct drm_device *dev,
+	struct drm_file *file_priv, struct drm_mode_fb_cmd2 *mode_cmd)
+{
+	struct drm_fb_cma *fb_cma;
+	struct drm_gem_cma_object *objs[4];
+	struct drm_gem_object *obj;
+	unsigned int hsub;
+	unsigned int vsub;
+	int ret;
+	int i;
+
+	hsub = drm_format_horz_chroma_subsampling(mode_cmd->pixel_format);
+	vsub = drm_format_vert_chroma_subsampling(mode_cmd->pixel_format);
+
+	for (i = 0; i < drm_format_num_planes(mode_cmd->pixel_format); i++) {
+		unsigned int width = mode_cmd->width / (i ? hsub : 1);
+		unsigned int height = mode_cmd->height / (i ? vsub : 1);
+		unsigned int min_size;
+
+		obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[i]);
+		if (!obj) {
+			dev_err(dev->dev, "Failed to lookup GEM object\n");
+			ret = -ENXIO;
+			goto err_gem_object_unreference;
+		}
+
+		min_size = (height - 1) * mode_cmd->pitches[i]
+			 + width * drm_format_plane_cpp(mode_cmd->pixel_format, i)
+			 + mode_cmd->offsets[i];
+
+		if (obj->size < min_size) {
+			drm_gem_object_unreference_unlocked(obj);
+			ret = -EINVAL;
+			goto err_gem_object_unreference;
+		}
+		objs[i] = to_drm_gem_cma_obj(obj);
+	}
+
+	fb_cma = drm_fb_cma_alloc(dev, mode_cmd, objs, i);
+	if (IS_ERR(fb_cma)) {
+		ret = PTR_ERR(fb_cma);
+		goto err_gem_object_unreference;
+	}
+
+	return &fb_cma->fb;
+
+err_gem_object_unreference:
+	for (i--; i >= 0; i--)
+		drm_gem_object_unreference_unlocked(&objs[i]->base);
+	return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(drm_fb_cma_create);
+
+/**
+ * drm_fb_cma_get_gem_obj() - Get CMA GEM object for framebuffer
+ * @fb: The framebuffer
+ * @plane: Which plane
+ *
+ * Return the CMA GEM object for given framebuffer.
+ *
+ * This function will usually be called from the CRTC callback functions.
+ */
+struct drm_gem_cma_object *drm_fb_cma_get_gem_obj(struct drm_framebuffer *fb,
+	unsigned int plane)
+{
+	struct drm_fb_cma *fb_cma = to_fb_cma(fb);
+
+	if (plane >= 4)
+		return NULL;
+
+	return fb_cma->obj[plane];
+}
+EXPORT_SYMBOL_GPL(drm_fb_cma_get_gem_obj);
+
+static struct fb_ops drm_fbdev_cma_ops = {
+	.owner		= THIS_MODULE,
+	.fb_fillrect	= sys_fillrect,
+	.fb_copyarea	= sys_copyarea,
+	.fb_imageblit	= sys_imageblit,
+	.fb_check_var	= drm_fb_helper_check_var,
+	.fb_set_par	= drm_fb_helper_set_par,
+	.fb_blank	= drm_fb_helper_blank,
+	.fb_pan_display	= drm_fb_helper_pan_display,
+	.fb_setcmap	= drm_fb_helper_setcmap,
+};
+
+static int drm_fbdev_cma_create(struct drm_fb_helper *helper,
+	struct drm_fb_helper_surface_size *sizes)
+{
+	struct drm_fbdev_cma *fbdev_cma = to_fbdev_cma(helper);
+	struct drm_mode_fb_cmd2 mode_cmd = { 0 };
+	struct drm_device *dev = helper->dev;
+	struct drm_gem_cma_object *obj;
+	struct drm_framebuffer *fb;
+	unsigned int bytes_per_pixel;
+	unsigned long offset;
+	struct fb_info *fbi;
+	size_t size;
+	int ret;
+
+	DRM_DEBUG_KMS("surface width(%d), height(%d) and bpp(%d\n",
+			sizes->surface_width, sizes->surface_height,
+			sizes->surface_bpp);
+
+	bytes_per_pixel = DIV_ROUND_UP(sizes->surface_bpp, 8);
+
+	mode_cmd.width = sizes->surface_width;
+	mode_cmd.height = sizes->surface_height;
+	mode_cmd.pitches[0] = sizes->surface_width * bytes_per_pixel;
+	mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
+		sizes->surface_depth);
+
+	size = mode_cmd.pitches[0] * mode_cmd.height;
+	obj = drm_gem_cma_create(dev, size);
+	if (!obj)
+		return -ENOMEM;
+
+	fbi = framebuffer_alloc(0, dev->dev);
+	if (!fbi) {
+		dev_err(dev->dev, "Failed to allocate framebuffer info.\n");
+		ret = -ENOMEM;
+		goto err_drm_gem_cma_free_object;
+	}
+
+	fbdev_cma->fb = drm_fb_cma_alloc(dev, &mode_cmd, &obj, 1);
+	if (IS_ERR(fbdev_cma->fb)) {
+		dev_err(dev->dev, "Failed to allocate DRM framebuffer.\n");
+		ret = PTR_ERR(fbdev_cma->fb);
+		goto err_framebuffer_release;
+	}
+
+	fb = &fbdev_cma->fb->fb;
+	helper->fb = fb;
+	helper->fbdev = fbi;
+
+	fbi->par = helper;
+	fbi->flags = FBINFO_FLAG_DEFAULT;
+	fbi->fbops = &drm_fbdev_cma_ops;
+
+	ret = fb_alloc_cmap(&fbi->cmap, 256, 0);
+	if (ret) {
+		dev_err(dev->dev, "Failed to allocate color map.\n");
+		goto err_drm_fb_cma_destroy;
+	}
+
+	drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth);
+	drm_fb_helper_fill_var(fbi, helper, fb->width, fb->height);
+
+	offset = fbi->var.xoffset * bytes_per_pixel;
+	offset += fbi->var.yoffset * fb->pitches[0];
+
+	dev->mode_config.fb_base = (resource_size_t)obj->paddr;
+	fbi->screen_base = obj->vaddr + offset;
+	fbi->fix.smem_start = (unsigned long)(obj->paddr + offset);
+	fbi->screen_size = size;
+	fbi->fix.smem_len = size;
+
+	return 0;
+
+err_drm_fb_cma_destroy:
+	drm_fb_cma_destroy(fb);
+err_framebuffer_release:
+	framebuffer_release(fbi);
+err_drm_gem_cma_free_object:
+	drm_gem_cma_free_object(&obj->base);
+	return ret;
+}
+
+static int drm_fbdev_cma_probe(struct drm_fb_helper *helper,
+	struct drm_fb_helper_surface_size *sizes)
+{
+	int ret = 0;
+
+	if (!helper->fb) {
+		ret = drm_fbdev_cma_create(helper, sizes);
+		if (ret < 0)
+			return ret;
+		ret = 1;
+	}
+
+	return ret;
+}
+
+static struct drm_fb_helper_funcs drm_fb_cma_helper_funcs = {
+	.fb_probe = drm_fbdev_cma_probe,
+};
+
+/**
+ * drm_fbdev_cma_init() - Allocate and initializes a drm_fbdev_cma struct
+ * @dev: DRM device
+ * @preferred_bpp: Preferred bits per pixel for the device
+ * @num_crtc: Number of CRTCs
+ * @max_conn_count: Maximum number of connectors
+ *
+ * Returns a newly allocated drm_fbdev_cma struct or a ERR_PTR.
+ */
+struct drm_fbdev_cma *drm_fbdev_cma_init(struct drm_device *dev,
+	unsigned int preferred_bpp, unsigned int num_crtc,
+	unsigned int max_conn_count)
+{
+	struct drm_fbdev_cma *fbdev_cma;
+	struct drm_fb_helper *helper;
+	int ret;
+
+	fbdev_cma = kzalloc(sizeof(*fbdev_cma), GFP_KERNEL);
+	if (!fbdev_cma) {
+		dev_err(dev->dev, "Failed to allocate drm fbdev.\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	fbdev_cma->fb_helper.funcs = &drm_fb_cma_helper_funcs;
+	helper = &fbdev_cma->fb_helper;
+
+	ret = drm_fb_helper_init(dev, helper, num_crtc, max_conn_count);
+	if (ret < 0) {
+		dev_err(dev->dev, "Failed to initialize drm fb helper.\n");
+		goto err_free;
+	}
+
+	ret = drm_fb_helper_single_add_all_connectors(helper);
+	if (ret < 0) {
+		dev_err(dev->dev, "Failed to add connectors.\n");
+		goto err_drm_fb_helper_fini;
+
+	}
+
+	ret = drm_fb_helper_initial_config(helper, preferred_bpp);
+	if (ret < 0) {
+		dev_err(dev->dev, "Failed to set inital hw configuration.\n");
+		goto err_drm_fb_helper_fini;
+	}
+
+	return fbdev_cma;
+
+err_drm_fb_helper_fini:
+	drm_fb_helper_fini(helper);
+err_free:
+	kfree(fbdev_cma);
+
+	return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(drm_fbdev_cma_init);
+
+/**
+ * drm_fbdev_cma_fini() - Free drm_fbdev_cma struct
+ * @fbdev_cma: The drm_fbdev_cma struct
+ */
+void drm_fbdev_cma_fini(struct drm_fbdev_cma *fbdev_cma)
+{
+	if (fbdev_cma->fb_helper.fbdev) {
+		struct fb_info *info;
+		int ret;
+
+		info = fbdev_cma->fb_helper.fbdev;
+		ret = unregister_framebuffer(info);
+		if (ret < 0)
+			DRM_DEBUG_KMS("failed unregister_framebuffer()\n");
+
+		if (info->cmap.len)
+			fb_dealloc_cmap(&info->cmap);
+
+		framebuffer_release(info);
+	}
+
+	if (fbdev_cma->fb)
+		drm_fb_cma_destroy(&fbdev_cma->fb->fb);
+
+	drm_fb_helper_fini(&fbdev_cma->fb_helper);
+	kfree(fbdev_cma);
+}
+EXPORT_SYMBOL_GPL(drm_fbdev_cma_fini);
+
+/**
+ * drm_fbdev_cma_restore_mode() - Restores initial framebuffer mode
+ * @fbdev_cma: The drm_fbdev_cma struct, may be NULL
+ *
+ * This function is usually called from the DRM drivers lastclose callback.
+ */
+void drm_fbdev_cma_restore_mode(struct drm_fbdev_cma *fbdev_cma)
+{
+	if (fbdev_cma)
+		drm_fb_helper_restore_fbdev_mode(&fbdev_cma->fb_helper);
+}
+EXPORT_SYMBOL_GPL(drm_fbdev_cma_restore_mode);
+
+/**
+ * drm_fbdev_cma_hotplug_event() - Poll for hotpulug events
+ * @fbdev_cma: The drm_fbdev_cma struct, may be NULL
+ *
+ * This function is usually called from the DRM drivers output_poll_changed
+ * callback.
+ */
+void drm_fbdev_cma_hotplug_event(struct drm_fbdev_cma *fbdev_cma)
+{
+	if (fbdev_cma)
+		drm_fb_helper_hotplug_event(&fbdev_cma->fb_helper);
+}
+EXPORT_SYMBOL_GPL(drm_fbdev_cma_hotplug_event);
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index f546d1e..b5d05f5 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -236,7 +236,7 @@ bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper)
 }
 EXPORT_SYMBOL(drm_fb_helper_restore_fbdev_mode);
 
-bool drm_fb_helper_force_kernel_mode(void)
+static bool drm_fb_helper_force_kernel_mode(void)
 {
 	bool ret, error = false;
 	struct drm_fb_helper *helper;
@@ -330,7 +330,7 @@ static void drm_fb_helper_dpms(struct fb_info *info, int dpms_mode)
 		/* Walk the connectors & encoders on this fb turning them on/off */
 		for (j = 0; j < fb_helper->connector_count; j++) {
 			connector = fb_helper->connector_info[j]->connector;
-			drm_helper_connector_dpms(connector, dpms_mode);
+			connector->funcs->dpms(connector, dpms_mode);
 			drm_connector_property_set_value(connector,
 				dev->mode_config.dpms_property, dpms_mode);
 		}
@@ -1230,7 +1230,6 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper)
 	struct drm_device *dev = fb_helper->dev;
 	struct drm_fb_helper_crtc **crtcs;
 	struct drm_display_mode **modes;
-	struct drm_encoder *encoder;
 	struct drm_mode_set *modeset;
 	bool *enabled;
 	int width, height;
@@ -1241,11 +1240,6 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper)
 	width = dev->mode_config.max_width;
 	height = dev->mode_config.max_height;
 
-	/* clean out all the encoder/crtc combos */
-	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
-		encoder->crtc = NULL;
-	}
-
 	crtcs = kcalloc(dev->mode_config.num_connector,
 			sizeof(struct drm_fb_helper_crtc *), GFP_KERNEL);
 	modes = kcalloc(dev->mode_config.num_connector,
diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
index 5062eec..433d2fa 100644
--- a/drivers/gpu/drm/drm_fops.c
+++ b/drivers/gpu/drm/drm_fops.c
@@ -251,7 +251,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
 	filp->private_data = priv;
 	priv->filp = filp;
 	priv->uid = current_euid();
-	priv->pid = task_pid_nr(current);
+	priv->pid = get_pid(task_pid(current));
 	priv->minor = idr_find(&drm_minors_idr, minor_id);
 	priv->ioctl_count = 0;
 	/* for compatibility root is always authenticated */
@@ -524,6 +524,7 @@ int drm_release(struct inode *inode, struct file *filp)
 	if (drm_core_check_feature(dev, DRIVER_PRIME))
 		drm_prime_destroy_file_private(&file_priv->prime);
 
+	put_pid(file_priv->pid);
 	kfree(file_priv);
 
 	/* ========================================================
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
index fbe0842..611c99d 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -706,7 +706,7 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
 		goto out_unlock;
 	}
 
-	vma->vm_flags |= VM_RESERVED | VM_IO | VM_PFNMAP | VM_DONTEXPAND;
+	vma->vm_flags |= VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP;
 	vma->vm_ops = obj->dev->driver->gem_vm_ops;
 	vma->vm_private_data = map->handle;
 	vma->vm_page_prot =  pgprot_writecombine(vm_get_page_prot(vma->vm_flags));
diff --git a/drivers/gpu/drm/drm_gem_cma_helper.c b/drivers/gpu/drm/drm_gem_cma_helper.c
new file mode 100644
index 0000000..1aa8fee
--- /dev/null
+++ b/drivers/gpu/drm/drm_gem_cma_helper.c
@@ -0,0 +1,251 @@
+/*
+ * drm gem CMA (contiguous memory allocator) helper functions
+ *
+ * Copyright (C) 2012 Sascha Hauer, Pengutronix
+ *
+ * Based on Samsung Exynos code
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/mutex.h>
+#include <linux/export.h>
+#include <linux/dma-mapping.h>
+
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include <drm/drm_gem_cma_helper.h>
+
+static unsigned int get_gem_mmap_offset(struct drm_gem_object *obj)
+{
+	return (unsigned int)obj->map_list.hash.key << PAGE_SHIFT;
+}
+
+static void drm_gem_cma_buf_destroy(struct drm_device *drm,
+		struct drm_gem_cma_object *cma_obj)
+{
+	dma_free_writecombine(drm->dev, cma_obj->base.size, cma_obj->vaddr,
+			cma_obj->paddr);
+}
+
+/*
+ * drm_gem_cma_create - allocate an object with the given size
+ *
+ * returns a struct drm_gem_cma_object* on success or ERR_PTR values
+ * on failure.
+ */
+struct drm_gem_cma_object *drm_gem_cma_create(struct drm_device *drm,
+		unsigned int size)
+{
+	struct drm_gem_cma_object *cma_obj;
+	struct drm_gem_object *gem_obj;
+	int ret;
+
+	size = round_up(size, PAGE_SIZE);
+
+	cma_obj = kzalloc(sizeof(*cma_obj), GFP_KERNEL);
+	if (!cma_obj)
+		return ERR_PTR(-ENOMEM);
+
+	cma_obj->vaddr = dma_alloc_writecombine(drm->dev, size,
+			&cma_obj->paddr, GFP_KERNEL | __GFP_NOWARN);
+	if (!cma_obj->vaddr) {
+		dev_err(drm->dev, "failed to allocate buffer with size %d\n", size);
+		ret = -ENOMEM;
+		goto err_dma_alloc;
+	}
+
+	gem_obj = &cma_obj->base;
+
+	ret = drm_gem_object_init(drm, gem_obj, size);
+	if (ret)
+		goto err_obj_init;
+
+	ret = drm_gem_create_mmap_offset(gem_obj);
+	if (ret)
+		goto err_create_mmap_offset;
+
+	return cma_obj;
+
+err_create_mmap_offset:
+	drm_gem_object_release(gem_obj);
+
+err_obj_init:
+	drm_gem_cma_buf_destroy(drm, cma_obj);
+
+err_dma_alloc:
+	kfree(cma_obj);
+
+	return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(drm_gem_cma_create);
+
+/*
+ * drm_gem_cma_create_with_handle - allocate an object with the given
+ * size and create a gem handle on it
+ *
+ * returns a struct drm_gem_cma_object* on success or ERR_PTR values
+ * on failure.
+ */
+static struct drm_gem_cma_object *drm_gem_cma_create_with_handle(
+		struct drm_file *file_priv,
+		struct drm_device *drm, unsigned int size,
+		unsigned int *handle)
+{
+	struct drm_gem_cma_object *cma_obj;
+	struct drm_gem_object *gem_obj;
+	int ret;
+
+	cma_obj = drm_gem_cma_create(drm, size);
+	if (IS_ERR(cma_obj))
+		return cma_obj;
+
+	gem_obj = &cma_obj->base;
+
+	/*
+	 * allocate a id of idr table where the obj is registered
+	 * and handle has the id what user can see.
+	 */
+	ret = drm_gem_handle_create(file_priv, gem_obj, handle);
+	if (ret)
+		goto err_handle_create;
+
+	/* drop reference from allocate - handle holds it now. */
+	drm_gem_object_unreference_unlocked(gem_obj);
+
+	return cma_obj;
+
+err_handle_create:
+	drm_gem_cma_free_object(gem_obj);
+
+	return ERR_PTR(ret);
+}
+
+/*
+ * drm_gem_cma_free_object - (struct drm_driver)->gem_free_object callback
+ * function
+ */
+void drm_gem_cma_free_object(struct drm_gem_object *gem_obj)
+{
+	struct drm_gem_cma_object *cma_obj;
+
+	if (gem_obj->map_list.map)
+		drm_gem_free_mmap_offset(gem_obj);
+
+	drm_gem_object_release(gem_obj);
+
+	cma_obj = to_drm_gem_cma_obj(gem_obj);
+
+	drm_gem_cma_buf_destroy(gem_obj->dev, cma_obj);
+
+	kfree(cma_obj);
+}
+EXPORT_SYMBOL_GPL(drm_gem_cma_free_object);
+
+/*
+ * drm_gem_cma_dumb_create - (struct drm_driver)->dumb_create callback
+ * function
+ *
+ * This aligns the pitch and size arguments to the minimum required. wrap
+ * this into your own function if you need bigger alignment.
+ */
+int drm_gem_cma_dumb_create(struct drm_file *file_priv,
+		struct drm_device *dev, struct drm_mode_create_dumb *args)
+{
+	struct drm_gem_cma_object *cma_obj;
+	int min_pitch = DIV_ROUND_UP(args->width * args->bpp, 8);
+
+	if (args->pitch < min_pitch)
+		args->pitch = min_pitch;
+
+	if (args->size < args->pitch * args->height)
+		args->size = args->pitch * args->height;
+
+	cma_obj = drm_gem_cma_create_with_handle(file_priv, dev,
+			args->size, &args->handle);
+	if (IS_ERR(cma_obj))
+		return PTR_ERR(cma_obj);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(drm_gem_cma_dumb_create);
+
+/*
+ * drm_gem_cma_dumb_map_offset - (struct drm_driver)->dumb_map_offset callback
+ * function
+ */
+int drm_gem_cma_dumb_map_offset(struct drm_file *file_priv,
+		struct drm_device *drm, uint32_t handle, uint64_t *offset)
+{
+	struct drm_gem_object *gem_obj;
+
+	mutex_lock(&drm->struct_mutex);
+
+	gem_obj = drm_gem_object_lookup(drm, file_priv, handle);
+	if (!gem_obj) {
+		dev_err(drm->dev, "failed to lookup gem object\n");
+		mutex_unlock(&drm->struct_mutex);
+		return -EINVAL;
+	}
+
+	*offset = get_gem_mmap_offset(gem_obj);
+
+	drm_gem_object_unreference(gem_obj);
+
+	mutex_unlock(&drm->struct_mutex);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(drm_gem_cma_dumb_map_offset);
+
+const struct vm_operations_struct drm_gem_cma_vm_ops = {
+	.open = drm_gem_vm_open,
+	.close = drm_gem_vm_close,
+};
+EXPORT_SYMBOL_GPL(drm_gem_cma_vm_ops);
+
+/*
+ * drm_gem_cma_mmap - (struct file_operation)->mmap callback function
+ */
+int drm_gem_cma_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+	struct drm_gem_object *gem_obj;
+	struct drm_gem_cma_object *cma_obj;
+	int ret;
+
+	ret = drm_gem_mmap(filp, vma);
+	if (ret)
+		return ret;
+
+	gem_obj = vma->vm_private_data;
+	cma_obj = to_drm_gem_cma_obj(gem_obj);
+
+	ret = remap_pfn_range(vma, vma->vm_start, cma_obj->paddr >> PAGE_SHIFT,
+			vma->vm_end - vma->vm_start, vma->vm_page_prot);
+	if (ret)
+		drm_gem_vm_close(vma);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(drm_gem_cma_mmap);
+
+/*
+ * drm_gem_cma_dumb_destroy - (struct drm_driver)->dumb_destroy callback function
+ */
+int drm_gem_cma_dumb_destroy(struct drm_file *file_priv,
+		struct drm_device *drm, unsigned int handle)
+{
+	return drm_gem_handle_delete(file_priv, handle);
+}
+EXPORT_SYMBOL_GPL(drm_gem_cma_dumb_destroy);
diff --git a/drivers/gpu/drm/drm_info.c b/drivers/gpu/drm/drm_info.c
index 8928edb..eb0af39 100644
--- a/drivers/gpu/drm/drm_info.c
+++ b/drivers/gpu/drm/drm_info.c
@@ -191,8 +191,9 @@ int drm_clients_info(struct seq_file *m, void *data)
 		seq_printf(m, "%c %3d %5d %5d %10u %10lu\n",
 			   priv->authenticated ? 'y' : 'n',
 			   priv->minor->index,
-			   priv->pid,
-			   priv->uid, priv->magic, priv->ioctl_count);
+			   pid_vnr(priv->pid),
+			   from_kuid_munged(seq_user_ns(m), priv->uid),
+			   priv->magic, priv->ioctl_count);
 	}
 	mutex_unlock(&dev->struct_mutex);
 	return 0;
diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
index 64a62c6..39a4383 100644
--- a/drivers/gpu/drm/drm_ioctl.c
+++ b/drivers/gpu/drm/drm_ioctl.c
@@ -215,8 +215,8 @@ int drm_getclient(struct drm_device *dev, void *data,
 	list_for_each_entry(pt, &dev->filelist, lhead) {
 		if (i++ >= idx) {
 			client->auth = pt->authenticated;
-			client->pid = pt->pid;
-			client->uid = pt->uid;
+			client->pid = pid_vnr(pt->pid);
+			client->uid = from_kuid_munged(current_user_ns(), pt->uid);
 			client->magic = pt->magic;
 			client->iocs = pt->ioctl_count;
 			mutex_unlock(&dev->struct_mutex);
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c
index 03f16f3..076c4a8 100644
--- a/drivers/gpu/drm/drm_irq.c
+++ b/drivers/gpu/drm/drm_irq.c
@@ -1236,7 +1236,7 @@ done:
 	return ret;
 }
 
-void drm_handle_vblank_events(struct drm_device *dev, int crtc)
+static void drm_handle_vblank_events(struct drm_device *dev, int crtc)
 {
 	struct drm_pending_vblank_event *e, *t;
 	struct timeval now;
diff --git a/drivers/gpu/drm/drm_vm.c b/drivers/gpu/drm/drm_vm.c
index 961ee08..19c512d70 100644
--- a/drivers/gpu/drm/drm_vm.c
+++ b/drivers/gpu/drm/drm_vm.c
@@ -62,7 +62,7 @@ static pgprot_t drm_io_prot(uint32_t map_type, struct vm_area_struct *vma)
 		tmp = pgprot_writecombine(tmp);
 	else
 		tmp = pgprot_noncached(tmp);
-#elif defined(__sparc__) || defined(__arm__)
+#elif defined(__sparc__) || defined(__arm__) || defined(__mips__)
 	tmp = pgprot_noncached(tmp);
 #endif
 	return tmp;
@@ -514,8 +514,7 @@ static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma)
 
 	vma->vm_ops = &drm_vm_dma_ops;
 
-	vma->vm_flags |= VM_RESERVED;	/* Don't swap */
-	vma->vm_flags |= VM_DONTEXPAND;
+	vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
 
 	drm_vm_open_locked(dev, vma);
 	return 0;
@@ -619,20 +618,11 @@ int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma)
 		offset = drm_core_get_reg_ofs(dev);
 		vma->vm_flags |= VM_IO;	/* not in core dump */
 		vma->vm_page_prot = drm_io_prot(map->type, vma);
-#if !defined(__arm__)
 		if (io_remap_pfn_range(vma, vma->vm_start,
 				       (map->offset + offset) >> PAGE_SHIFT,
 				       vma->vm_end - vma->vm_start,
 				       vma->vm_page_prot))
 			return -EAGAIN;
-#else
-		if (remap_pfn_range(vma, vma->vm_start,
-					(map->offset + offset) >> PAGE_SHIFT,
-					vma->vm_end - vma->vm_start,
-					vma->vm_page_prot))
-			return -EAGAIN;
-#endif
-
 		DRM_DEBUG("   Type = %d; start = 0x%lx, end = 0x%lx,"
 			  " offset = 0x%llx\n",
 			  map->type,
@@ -652,21 +642,16 @@ int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma)
 	case _DRM_SHM:
 		vma->vm_ops = &drm_vm_shm_ops;
 		vma->vm_private_data = (void *)map;
-		/* Don't let this area swap.  Change when
-		   DRM_KERNEL advisory is supported. */
-		vma->vm_flags |= VM_RESERVED;
 		break;
 	case _DRM_SCATTER_GATHER:
 		vma->vm_ops = &drm_vm_sg_ops;
 		vma->vm_private_data = (void *)map;
-		vma->vm_flags |= VM_RESERVED;
 		vma->vm_page_prot = drm_dma_prot(map->type, vma);
 		break;
 	default:
 		return -EINVAL;	/* This should never happen. */
 	}
-	vma->vm_flags |= VM_RESERVED;	/* Don't swap */
-	vma->vm_flags |= VM_DONTEXPAND;
+	vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
 
 	drm_vm_open_locked(dev, vma);
 	return 0;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_connector.c b/drivers/gpu/drm/exynos/exynos_drm_connector.c
index d956819..9dce3b9 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_connector.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_connector.c
@@ -147,9 +147,7 @@ static int exynos_drm_connector_get_modes(struct drm_connector *connector)
 
 		drm_mode_connector_update_edid_property(connector, edid);
 		count = drm_add_edid_modes(connector, edid);
-
-		kfree(connector->display_info.raw_edid);
-		connector->display_info.raw_edid = edid;
+		kfree(edid);
 	} else {
 		struct drm_display_mode *mode = drm_mode_create(connector->dev);
 		struct exynos_drm_panel_info *panel;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
index b19cd93..d96db5e 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -19,8 +19,8 @@
 #include <linux/clk.h>
 #include <linux/pm_runtime.h>
 
+#include <video/samsung_fimd.h>
 #include <drm/exynos_drm.h>
-#include <plat/regs-fb-v4.h>
 
 #include "exynos_drm_drv.h"
 #include "exynos_drm_fbdev.h"
diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
index 1065e90..2526e82 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
@@ -878,7 +878,7 @@ static int g2d_suspend(struct device *dev)
 		/* FIXME: good range? */
 		usleep_range(500, 1000);
 
-	flush_work_sync(&g2d->runqueue_work);
+	flush_work(&g2d->runqueue_work);
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c b/drivers/gpu/drm/exynos/exynos_drm_gem.c
index a38051c..9787b2d 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_gem.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c
@@ -501,7 +501,7 @@ static int exynos_drm_gem_mmap_buffer(struct file *filp,
 
 	DRM_DEBUG_KMS("%s\n", __FILE__);
 
-	vma->vm_flags |= (VM_IO | VM_RESERVED);
+	vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP;
 
 	update_vm_cache_attr(exynos_gem_obj, vma);
 
diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
index 537027a..e364165 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
@@ -102,7 +102,6 @@ static int vidi_get_edid(struct device *dev, struct drm_connector *connector,
 				u8 *edid, int len)
 {
 	struct vidi_context *ctx = get_vidi_context(dev);
-	struct edid *raw_edid;
 
 	DRM_DEBUG_KMS("%s\n", __FILE__);
 
@@ -115,18 +114,6 @@ static int vidi_get_edid(struct device *dev, struct drm_connector *connector,
 		return -EFAULT;
 	}
 
-	raw_edid = kzalloc(len, GFP_KERNEL);
-	if (!raw_edid) {
-		DRM_DEBUG_KMS("failed to allocate raw_edid.\n");
-		return -ENOMEM;
-	}
-
-	memcpy(raw_edid, ctx->raw_edid, min((1 + ctx->raw_edid->extensions)
-						* EDID_LENGTH, len));
-
-	/* attach the edid data to connector. */
-	connector->display_info.raw_edid = (char *)raw_edid;
-
 	memcpy(edid, ctx->raw_edid, min((1 + ctx->raw_edid->extensions)
 					* EDID_LENGTH, len));
 
diff --git a/drivers/gpu/drm/gma500/Makefile b/drivers/gpu/drm/gma500/Makefile
index abfa2a93..7a2d40a 100644
--- a/drivers/gpu/drm/gma500/Makefile
+++ b/drivers/gpu/drm/gma500/Makefile
@@ -3,7 +3,7 @@
 #
 ccflags-y += -I$(srctree)/include/drm
 
-gma500_gfx-y += gem_glue.o \
+gma500_gfx-y += \
 	  accel_2d.o \
 	  backlight.o \
 	  framebuffer.o \
@@ -30,7 +30,8 @@ gma500_gfx-$(CONFIG_DRM_GMA3600) +=  cdv_device.o \
 	  cdv_intel_crt.o \
 	  cdv_intel_display.o \
 	  cdv_intel_hdmi.o \
-	  cdv_intel_lvds.o
+	  cdv_intel_lvds.o \
+	  cdv_intel_dp.o
 
 gma500_gfx-$(CONFIG_DRM_GMA600) += oaktrail_device.o \
 	  oaktrail_crtc.o \
diff --git a/drivers/gpu/drm/gma500/backlight.c b/drivers/gpu/drm/gma500/backlight.c
index 2079395..143eba3 100644
--- a/drivers/gpu/drm/gma500/backlight.c
+++ b/drivers/gpu/drm/gma500/backlight.c
@@ -26,10 +26,55 @@
 #include "intel_bios.h"
 #include "power.h"
 
+static void do_gma_backlight_set(struct drm_device *dev)
+{
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	backlight_update_status(dev_priv->backlight_device);
+#endif	
+}
+
+void gma_backlight_enable(struct drm_device *dev)
+{
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	dev_priv->backlight_enabled = true;
+	if (dev_priv->backlight_device) {
+		dev_priv->backlight_device->props.brightness = dev_priv->backlight_level;
+		do_gma_backlight_set(dev);
+	}
+#endif	
+}
+
+void gma_backlight_disable(struct drm_device *dev)
+{
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	dev_priv->backlight_enabled = false;
+	if (dev_priv->backlight_device) {
+		dev_priv->backlight_device->props.brightness = 0;
+		do_gma_backlight_set(dev);
+	}
+#endif	
+}
+
+void gma_backlight_set(struct drm_device *dev, int v)
+{
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	dev_priv->backlight_level = v;
+	if (dev_priv->backlight_device && dev_priv->backlight_enabled) {
+		dev_priv->backlight_device->props.brightness = v;
+		do_gma_backlight_set(dev);
+	}
+#endif	
+}
+
 int gma_backlight_init(struct drm_device *dev)
 {
 #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
 	struct drm_psb_private *dev_priv = dev->dev_private;
+	dev_priv->backlight_enabled = true;
 	return dev_priv->ops->backlight_init(dev);
 #else
 	return 0;
diff --git a/drivers/gpu/drm/gma500/cdv_device.c b/drivers/gpu/drm/gma500/cdv_device.c
index b7e7b49..bfc2f39 100644
--- a/drivers/gpu/drm/gma500/cdv_device.c
+++ b/drivers/gpu/drm/gma500/cdv_device.c
@@ -58,10 +58,17 @@ static int cdv_output_init(struct drm_device *dev)
 	cdv_intel_lvds_init(dev, &dev_priv->mode_dev);
 
 	/* These bits indicate HDMI not SDVO on CDV */
-	if (REG_READ(SDVOB) & SDVO_DETECTED)
+	if (REG_READ(SDVOB) & SDVO_DETECTED) {
 		cdv_hdmi_init(dev, &dev_priv->mode_dev, SDVOB);
-	if (REG_READ(SDVOC) & SDVO_DETECTED)
+		if (REG_READ(DP_B) & DP_DETECTED)
+			cdv_intel_dp_init(dev, &dev_priv->mode_dev, DP_B);
+	}
+
+	if (REG_READ(SDVOC) & SDVO_DETECTED) {
 		cdv_hdmi_init(dev, &dev_priv->mode_dev, SDVOC);
+		if (REG_READ(DP_C) & DP_DETECTED)
+			cdv_intel_dp_init(dev, &dev_priv->mode_dev, DP_C);
+	}
 	return 0;
 }
 
@@ -163,6 +170,7 @@ static int cdv_backlight_init(struct drm_device *dev)
 			cdv_get_brightness(cdv_backlight_device);
 	backlight_update_status(cdv_backlight_device);
 	dev_priv->backlight_device = cdv_backlight_device;
+	dev_priv->backlight_enabled = true;
 	return 0;
 }
 
@@ -449,6 +457,7 @@ static void cdv_get_core_freq(struct drm_device *dev)
 	case 6:
 	case 7:
 		dev_priv->core_freq = 266;
+		break;
 	default:
 		dev_priv->core_freq = 0;
 	}
@@ -488,6 +497,65 @@ static void cdv_hotplug_enable(struct drm_device *dev, bool on)
 	}	
 }
 
+static const char *force_audio_names[] = {
+	"off",
+	"auto",
+	"on",
+};
+
+void cdv_intel_attach_force_audio_property(struct drm_connector *connector)
+{
+	struct drm_device *dev = connector->dev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct drm_property *prop;
+	int i;
+
+	prop = dev_priv->force_audio_property;
+	if (prop == NULL) {
+		prop = drm_property_create(dev, DRM_MODE_PROP_ENUM,
+					   "audio",
+					   ARRAY_SIZE(force_audio_names));
+		if (prop == NULL)
+			return;
+
+		for (i = 0; i < ARRAY_SIZE(force_audio_names); i++)
+			drm_property_add_enum(prop, i, i-1, force_audio_names[i]);
+
+		dev_priv->force_audio_property = prop;
+	}
+	drm_connector_attach_property(connector, prop, 0);
+}
+
+
+static const char *broadcast_rgb_names[] = {
+	"Full",
+	"Limited 16:235",
+};
+
+void cdv_intel_attach_broadcast_rgb_property(struct drm_connector *connector)
+{
+	struct drm_device *dev = connector->dev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct drm_property *prop;
+	int i;
+
+	prop = dev_priv->broadcast_rgb_property;
+	if (prop == NULL) {
+		prop = drm_property_create(dev, DRM_MODE_PROP_ENUM,
+					   "Broadcast RGB",
+					   ARRAY_SIZE(broadcast_rgb_names));
+		if (prop == NULL)
+			return;
+
+		for (i = 0; i < ARRAY_SIZE(broadcast_rgb_names); i++)
+			drm_property_add_enum(prop, i, i, broadcast_rgb_names[i]);
+
+		dev_priv->broadcast_rgb_property = prop;
+	}
+
+	drm_connector_attach_property(connector, prop, 0);
+}
+
 /* Cedarview */
 static const struct psb_offset cdv_regmap[2] = {
 	{
diff --git a/drivers/gpu/drm/gma500/cdv_intel_display.c b/drivers/gpu/drm/gma500/cdv_intel_display.c
index a68509b..3cfd093 100644
--- a/drivers/gpu/drm/gma500/cdv_intel_display.c
+++ b/drivers/gpu/drm/gma500/cdv_intel_display.c
@@ -57,15 +57,26 @@ struct cdv_intel_clock_t {
 struct cdv_intel_limit_t {
 	struct cdv_intel_range_t dot, vco, n, m, m1, m2, p, p1;
 	struct cdv_intel_p2_t p2;
+	bool (*find_pll)(const struct cdv_intel_limit_t *, struct drm_crtc *,
+			int, int, struct cdv_intel_clock_t *);
 };
 
+static bool cdv_intel_find_best_PLL(const struct cdv_intel_limit_t *limit,
+	struct drm_crtc *crtc, int target, int refclk,
+	struct cdv_intel_clock_t *best_clock);
+static bool cdv_intel_find_dp_pll(const struct cdv_intel_limit_t *limit, struct drm_crtc *crtc, int target,
+				int refclk,
+				struct cdv_intel_clock_t *best_clock);
+
 #define CDV_LIMIT_SINGLE_LVDS_96	0
 #define CDV_LIMIT_SINGLE_LVDS_100	1
 #define CDV_LIMIT_DAC_HDMI_27		2
 #define CDV_LIMIT_DAC_HDMI_96		3
+#define CDV_LIMIT_DP_27			4
+#define CDV_LIMIT_DP_100		5
 
 static const struct cdv_intel_limit_t cdv_intel_limits[] = {
-	{			/* CDV_SIGNLE_LVDS_96MHz */
+	{			/* CDV_SINGLE_LVDS_96MHz */
 	 .dot = {.min = 20000, .max = 115500},
 	 .vco = {.min = 1800000, .max = 3600000},
 	 .n = {.min = 2, .max = 6},
@@ -76,6 +87,7 @@ static const struct cdv_intel_limit_t cdv_intel_limits[] = {
 	 .p1 = {.min = 2, .max = 10},
 	 .p2 = {.dot_limit = 200000,
 		.p2_slow = 14, .p2_fast = 14},
+		.find_pll = cdv_intel_find_best_PLL,
 	 },
 	{			/* CDV_SINGLE_LVDS_100MHz */
 	 .dot = {.min = 20000, .max = 115500},
@@ -90,6 +102,7 @@ static const struct cdv_intel_limit_t cdv_intel_limits[] = {
 	  * is 80-224Mhz.  Prefer single channel as much as possible.
 	  */
 	 .p2 = {.dot_limit = 200000, .p2_slow = 14, .p2_fast = 14},
+	.find_pll = cdv_intel_find_best_PLL,
 	 },
 	{			/* CDV_DAC_HDMI_27MHz */
 	 .dot = {.min = 20000, .max = 400000},
@@ -101,6 +114,7 @@ static const struct cdv_intel_limit_t cdv_intel_limits[] = {
 	 .p = {.min = 5, .max = 90},
 	 .p1 = {.min = 1, .max = 9},
 	 .p2 = {.dot_limit = 225000, .p2_slow = 10, .p2_fast = 5},
+	.find_pll = cdv_intel_find_best_PLL,
 	 },
 	{			/* CDV_DAC_HDMI_96MHz */
 	 .dot = {.min = 20000, .max = 400000},
@@ -112,7 +126,32 @@ static const struct cdv_intel_limit_t cdv_intel_limits[] = {
 	 .p = {.min = 5, .max = 100},
 	 .p1 = {.min = 1, .max = 10},
 	 .p2 = {.dot_limit = 225000, .p2_slow = 10, .p2_fast = 5},
+	.find_pll = cdv_intel_find_best_PLL,
+	 },
+	{			/* CDV_DP_27MHz */
+	 .dot = {.min = 160000, .max = 272000},
+	 .vco = {.min = 1809000, .max = 3564000},
+	 .n = {.min = 1, .max = 1},
+	 .m = {.min = 67, .max = 132},
+	 .m1 = {.min = 0, .max = 0},
+	 .m2 = {.min = 65, .max = 130},
+	 .p = {.min = 5, .max = 90},
+	 .p1 = {.min = 1, .max = 9},
+	 .p2 = {.dot_limit = 225000, .p2_slow = 10, .p2_fast = 10},
+	 .find_pll = cdv_intel_find_dp_pll,
 	 },
+	{			/* CDV_DP_100MHz */
+	 .dot = {.min = 160000, .max = 272000},
+	 .vco = {.min = 1800000, .max = 3600000},
+	 .n = {.min = 2, .max = 6},
+	 .m = {.min = 60, .max = 164},
+	 .m1 = {.min = 0, .max = 0},
+	 .m2 = {.min = 58, .max = 162},
+	 .p = {.min = 5, .max = 100},
+	 .p1 = {.min = 1, .max = 10},
+	 .p2 = {.dot_limit = 225000, .p2_slow = 10, .p2_fast = 10},
+	 .find_pll = cdv_intel_find_dp_pll,
+	 }	
 };
 
 #define _wait_for(COND, MS, W) ({ \
@@ -132,7 +171,7 @@ static const struct cdv_intel_limit_t cdv_intel_limits[] = {
 #define wait_for(COND, MS) _wait_for(COND, MS, 1)
 
 
-static int cdv_sb_read(struct drm_device *dev, u32 reg, u32 *val)
+int cdv_sb_read(struct drm_device *dev, u32 reg, u32 *val)
 {
 	int ret;
 
@@ -159,7 +198,7 @@ static int cdv_sb_read(struct drm_device *dev, u32 reg, u32 *val)
 	return 0;
 }
 
-static int cdv_sb_write(struct drm_device *dev, u32 reg, u32 val)
+int cdv_sb_write(struct drm_device *dev, u32 reg, u32 val)
 {
 	int ret;
 	static bool dpio_debug = true;
@@ -201,7 +240,7 @@ static int cdv_sb_write(struct drm_device *dev, u32 reg, u32 val)
 /* Reset the DPIO configuration register.  The BIOS does this at every
  * mode set.
  */
-static void cdv_sb_reset(struct drm_device *dev)
+void cdv_sb_reset(struct drm_device *dev)
 {
 
 	REG_WRITE(DPIO_CFG, 0);
@@ -216,7 +255,7 @@ static void cdv_sb_reset(struct drm_device *dev)
  */
 static int
 cdv_dpll_set_clock_cdv(struct drm_device *dev, struct drm_crtc *crtc,
-			       struct cdv_intel_clock_t *clock, bool is_lvds)
+			       struct cdv_intel_clock_t *clock, bool is_lvds, u32 ddi_select)
 {
 	struct psb_intel_crtc *psb_crtc = to_psb_intel_crtc(crtc);
 	int pipe = psb_crtc->pipe;
@@ -259,7 +298,7 @@ cdv_dpll_set_clock_cdv(struct drm_device *dev, struct drm_crtc *crtc,
 	ref_value &= ~(REF_CLK_MASK);
 
 	/* use DPLL_A for pipeB on CRT/HDMI */
-	if (pipe == 1 && !is_lvds) {
+	if (pipe == 1 && !is_lvds && !(ddi_select & DP_MASK)) {
 		DRM_DEBUG_KMS("use DPLLA for pipe B\n");
 		ref_value |= REF_CLK_DPLLA;
 	} else {
@@ -336,30 +375,33 @@ cdv_dpll_set_clock_cdv(struct drm_device *dev, struct drm_crtc *crtc,
 	if (ret)
 		return ret;
 
-	lane_reg = PSB_LANE0;
-	cdv_sb_read(dev, lane_reg, &lane_value);
-	lane_value &= ~(LANE_PLL_MASK);
-	lane_value |= LANE_PLL_ENABLE | LANE_PLL_PIPE(pipe);
-	cdv_sb_write(dev, lane_reg, lane_value);
-
-	lane_reg = PSB_LANE1;
-	cdv_sb_read(dev, lane_reg, &lane_value);
-	lane_value &= ~(LANE_PLL_MASK);
-	lane_value |= LANE_PLL_ENABLE | LANE_PLL_PIPE(pipe);
-	cdv_sb_write(dev, lane_reg, lane_value);
-
-	lane_reg = PSB_LANE2;
-	cdv_sb_read(dev, lane_reg, &lane_value);
-	lane_value &= ~(LANE_PLL_MASK);
-	lane_value |= LANE_PLL_ENABLE | LANE_PLL_PIPE(pipe);
-	cdv_sb_write(dev, lane_reg, lane_value);
-
-	lane_reg = PSB_LANE3;
-	cdv_sb_read(dev, lane_reg, &lane_value);
-	lane_value &= ~(LANE_PLL_MASK);
-	lane_value |= LANE_PLL_ENABLE | LANE_PLL_PIPE(pipe);
-	cdv_sb_write(dev, lane_reg, lane_value);
-
+	if (ddi_select) {
+		if ((ddi_select & DDI_MASK) == DDI0_SELECT) {
+			lane_reg = PSB_LANE0;
+			cdv_sb_read(dev, lane_reg, &lane_value);
+			lane_value &= ~(LANE_PLL_MASK);
+			lane_value |= LANE_PLL_ENABLE | LANE_PLL_PIPE(pipe);
+			cdv_sb_write(dev, lane_reg, lane_value);
+
+			lane_reg = PSB_LANE1;
+			cdv_sb_read(dev, lane_reg, &lane_value);
+			lane_value &= ~(LANE_PLL_MASK);
+			lane_value |= LANE_PLL_ENABLE | LANE_PLL_PIPE(pipe);
+			cdv_sb_write(dev, lane_reg, lane_value);
+		} else {
+			lane_reg = PSB_LANE2;
+			cdv_sb_read(dev, lane_reg, &lane_value);
+			lane_value &= ~(LANE_PLL_MASK);
+			lane_value |= LANE_PLL_ENABLE | LANE_PLL_PIPE(pipe);
+			cdv_sb_write(dev, lane_reg, lane_value);
+
+			lane_reg = PSB_LANE3;
+			cdv_sb_read(dev, lane_reg, &lane_value);
+			lane_value &= ~(LANE_PLL_MASK);
+			lane_value |= LANE_PLL_ENABLE | LANE_PLL_PIPE(pipe);
+			cdv_sb_write(dev, lane_reg, lane_value);
+		}
+	}
 	return 0;
 }
 
@@ -396,6 +438,12 @@ static const struct cdv_intel_limit_t *cdv_intel_limit(struct drm_crtc *crtc,
 			limit = &cdv_intel_limits[CDV_LIMIT_SINGLE_LVDS_96];
 		else
 			limit = &cdv_intel_limits[CDV_LIMIT_SINGLE_LVDS_100];
+	} else if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT) ||
+			psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP)) {
+		if (refclk == 27000)
+			limit = &cdv_intel_limits[CDV_LIMIT_DP_27];
+		else
+			limit = &cdv_intel_limits[CDV_LIMIT_DP_100];
 	} else {
 		if (refclk == 27000)
 			limit = &cdv_intel_limits[CDV_LIMIT_DAC_HDMI_27];
@@ -438,13 +486,12 @@ static bool cdv_intel_PLL_is_valid(struct drm_crtc *crtc,
 	return true;
 }
 
-static bool cdv_intel_find_best_PLL(struct drm_crtc *crtc, int target,
-				int refclk,
-				struct cdv_intel_clock_t *best_clock)
+static bool cdv_intel_find_best_PLL(const struct cdv_intel_limit_t *limit,
+	struct drm_crtc *crtc, int target, int refclk,
+	struct cdv_intel_clock_t *best_clock)
 {
 	struct drm_device *dev = crtc->dev;
 	struct cdv_intel_clock_t clock;
-	const struct cdv_intel_limit_t *limit = cdv_intel_limit(crtc, refclk);
 	int err = target;
 
 
@@ -498,6 +545,49 @@ static bool cdv_intel_find_best_PLL(struct drm_crtc *crtc, int target,
 	return err != target;
 }
 
+static bool cdv_intel_find_dp_pll(const struct cdv_intel_limit_t *limit, struct drm_crtc *crtc, int target,
+				int refclk,
+				struct cdv_intel_clock_t *best_clock)
+{
+	struct cdv_intel_clock_t clock;
+	if (refclk == 27000) {
+		if (target < 200000) {
+			clock.p1 = 2;
+			clock.p2 = 10;
+			clock.n = 1;
+			clock.m1 = 0;
+			clock.m2 = 118;
+		} else {
+			clock.p1 = 1;
+			clock.p2 = 10;
+			clock.n = 1;
+			clock.m1 = 0;
+			clock.m2 = 98;
+		}
+	} else if (refclk == 100000) {
+		if (target < 200000) {
+			clock.p1 = 2;
+			clock.p2 = 10;
+			clock.n = 5;
+			clock.m1 = 0;
+			clock.m2 = 160;
+		} else {
+			clock.p1 = 1;
+			clock.p2 = 10;
+			clock.n = 5;
+			clock.m1 = 0;
+			clock.m2 = 133;
+		}
+	} else
+		return false;
+	clock.m = clock.m2 + 2;
+	clock.p = clock.p1 * clock.p2;
+	clock.vco = (refclk * clock.m) / clock.n;
+	clock.dot = clock.vco / clock.p;
+	memcpy(best_clock, &clock, sizeof(struct cdv_intel_clock_t));
+	return true;
+}
+
 static int cdv_intel_pipe_set_base(struct drm_crtc *crtc,
 			    int x, int y, struct drm_framebuffer *old_fb)
 {
@@ -791,7 +881,7 @@ static void cdv_intel_crtc_dpms(struct drm_crtc *crtc, int mode)
 	case DRM_MODE_DPMS_STANDBY:
 	case DRM_MODE_DPMS_SUSPEND:
 		if (psb_intel_crtc->active)
-			return;
+			break;
 
 		psb_intel_crtc->active = true;
 
@@ -835,17 +925,15 @@ static void cdv_intel_crtc_dpms(struct drm_crtc *crtc, int mode)
 		REG_WRITE(map->status, temp);
 		REG_READ(map->status);
 
-		cdv_intel_update_watermark(dev, crtc);
 		cdv_intel_crtc_load_lut(crtc);
 
 		/* Give the overlay scaler a chance to enable
 		 * if it's on this pipe */
 		/* psb_intel_crtc_dpms_video(crtc, true); TODO */
-		psb_intel_crtc->crtc_enable = true;
 		break;
 	case DRM_MODE_DPMS_OFF:
 		if (!psb_intel_crtc->active)
-			return;
+			break;
 
 		psb_intel_crtc->active = false;
 
@@ -892,10 +980,9 @@ static void cdv_intel_crtc_dpms(struct drm_crtc *crtc, int mode)
 
 		/* Wait for the clocks to turn off. */
 		udelay(150);
-		cdv_intel_update_watermark(dev, crtc);
-		psb_intel_crtc->crtc_enable = false;
 		break;
 	}
+	cdv_intel_update_watermark(dev, crtc);
 	/*Set FIFO Watermarks*/
 	REG_WRITE(DSPARB, 0x3F3E);
 }
@@ -952,9 +1039,12 @@ static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc,
 	u32 dpll = 0, dspcntr, pipeconf;
 	bool ok;
 	bool is_crt = false, is_lvds = false, is_tv = false;
-	bool is_hdmi = false;
+	bool is_hdmi = false, is_dp = false;
 	struct drm_mode_config *mode_config = &dev->mode_config;
 	struct drm_connector *connector;
+	const struct cdv_intel_limit_t *limit;
+	u32 ddi_select = 0;
+	bool is_edp = false;
 
 	list_for_each_entry(connector, &mode_config->connector_list, head) {
 		struct psb_intel_encoder *psb_intel_encoder =
@@ -964,6 +1054,7 @@ static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc,
 		    || connector->encoder->crtc != crtc)
 			continue;
 
+		ddi_select = psb_intel_encoder->ddi_select;
 		switch (psb_intel_encoder->type) {
 		case INTEL_OUTPUT_LVDS:
 			is_lvds = true;
@@ -977,6 +1068,15 @@ static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc,
 		case INTEL_OUTPUT_HDMI:
 			is_hdmi = true;
 			break;
+		case INTEL_OUTPUT_DISPLAYPORT:
+			is_dp = true;
+			break;
+		case INTEL_OUTPUT_EDP:
+			is_edp = true;
+			break;
+		default:
+			DRM_ERROR("invalid output type.\n");
+			return 0;
 		}
 	}
 
@@ -986,6 +1086,20 @@ static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc,
 	else
 		/* high-end sku, 27/100 mhz */
 		refclk = 27000;
+	if (is_dp || is_edp) {
+		/*
+		 * Based on the spec the low-end SKU has only CRT/LVDS. So it is
+		 * unnecessary to consider it for DP/eDP.
+		 * On the high-end SKU, it will use the 27/100M reference clk
+		 * for DP/eDP. When using SSC clock, the ref clk is 100MHz.Otherwise
+		 * it will be 27MHz. From the VBIOS code it seems that the pipe A choose
+		 * 27MHz for DP/eDP while the Pipe B chooses the 100MHz.
+		 */ 
+		if (pipe == 0)
+			refclk = 27000;
+		else
+			refclk = 100000;
+	}
 
 	if (is_lvds && dev_priv->lvds_use_ssc) {
 		refclk = dev_priv->lvds_ssc_freq * 1000;
@@ -993,8 +1107,10 @@ static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc,
 	}
 
 	drm_mode_debug_printmodeline(adjusted_mode);
+	
+	limit = cdv_intel_limit(crtc, refclk);
 
-	ok = cdv_intel_find_best_PLL(crtc, adjusted_mode->clock, refclk,
+	ok = limit->find_pll(limit, crtc, adjusted_mode->clock, refclk,
 				 &clock);
 	if (!ok) {
 		dev_err(dev->dev, "Couldn't find PLL settings for mode!\n");
@@ -1009,6 +1125,15 @@ static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc,
 	}
 /*		dpll |= PLL_REF_INPUT_DREFCLK; */
 
+	if (is_dp || is_edp) {
+		cdv_intel_dp_set_m_n(crtc, mode, adjusted_mode);
+	} else {
+		REG_WRITE(PIPE_GMCH_DATA_M(pipe), 0);
+		REG_WRITE(PIPE_GMCH_DATA_N(pipe), 0);
+		REG_WRITE(PIPE_DP_LINK_M(pipe), 0);
+		REG_WRITE(PIPE_DP_LINK_N(pipe), 0);
+	}
+
 	dpll |= DPLL_SYNCLOCK_ENABLE;
 /*	if (is_lvds)
 		dpll |= DPLLB_MODE_LVDS;
@@ -1019,6 +1144,31 @@ static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc,
 	/* setup pipeconf */
 	pipeconf = REG_READ(map->conf);
 
+	pipeconf &= ~(PIPE_BPC_MASK);
+	if (is_edp) {
+		switch (dev_priv->edp.bpp) {
+		case 24:
+			pipeconf |= PIPE_8BPC;
+			break;
+		case 18:
+			pipeconf |= PIPE_6BPC;
+			break;
+		case 30:
+			pipeconf |= PIPE_10BPC;
+			break;
+		default:
+			pipeconf |= PIPE_8BPC;
+			break;
+		}
+	} else if (is_lvds) {
+		/* the BPC will be 6 if it is 18-bit LVDS panel */
+		if ((REG_READ(LVDS) & LVDS_A3_POWER_MASK) == LVDS_A3_POWER_UP)
+			pipeconf |= PIPE_8BPC;
+		else
+			pipeconf |= PIPE_6BPC;
+	} else
+		pipeconf |= PIPE_8BPC;
+			
 	/* Set up the display plane register */
 	dspcntr = DISPPLANE_GAMMA_ENABLE;
 
@@ -1033,7 +1183,7 @@ static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc,
 	REG_WRITE(map->dpll, dpll | DPLL_VGA_MODE_DIS | DPLL_SYNCLOCK_ENABLE);
 	REG_READ(map->dpll);
 
-	cdv_dpll_set_clock_cdv(dev, crtc, &clock, is_lvds);
+	cdv_dpll_set_clock_cdv(dev, crtc, &clock, is_lvds, ddi_select);
 
 	udelay(150);
 
diff --git a/drivers/gpu/drm/gma500/cdv_intel_dp.c b/drivers/gpu/drm/gma500/cdv_intel_dp.c
new file mode 100644
index 0000000..c9abc06
--- /dev/null
+++ b/drivers/gpu/drm/gma500/cdv_intel_dp.c
@@ -0,0 +1,1951 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Keith Packard <keithp@keithp.com>
+ *
+ */
+
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include "drmP.h"
+#include "drm.h"
+#include "drm_crtc.h"
+#include "drm_crtc_helper.h"
+#include "psb_drv.h"
+#include "psb_intel_drv.h"
+#include "psb_intel_reg.h"
+#include "drm_dp_helper.h"
+
+#define _wait_for(COND, MS, W) ({ \
+        unsigned long timeout__ = jiffies + msecs_to_jiffies(MS);       \
+        int ret__ = 0;                                                  \
+        while (! (COND)) {                                              \
+                if (time_after(jiffies, timeout__)) {                   \
+                        ret__ = -ETIMEDOUT;                             \
+                        break;                                          \
+                }                                                       \
+                if (W && !in_dbg_master()) msleep(W);                   \
+        }                                                               \
+        ret__;                                                          \
+})      
+
+#define wait_for(COND, MS) _wait_for(COND, MS, 1)
+
+#define DP_LINK_STATUS_SIZE	6
+#define DP_LINK_CHECK_TIMEOUT	(10 * 1000)
+
+#define DP_LINK_CONFIGURATION_SIZE	9
+
+#define CDV_FAST_LINK_TRAIN	1
+
+struct cdv_intel_dp {
+	uint32_t output_reg;
+	uint32_t DP;
+	uint8_t  link_configuration[DP_LINK_CONFIGURATION_SIZE];
+	bool has_audio;
+	int force_audio;
+	uint32_t color_range;
+	uint8_t link_bw;
+	uint8_t lane_count;
+	uint8_t dpcd[4];
+	struct psb_intel_encoder *encoder;
+	struct i2c_adapter adapter;
+	struct i2c_algo_dp_aux_data algo;
+	uint8_t	train_set[4];
+	uint8_t link_status[DP_LINK_STATUS_SIZE];
+	int panel_power_up_delay;
+	int panel_power_down_delay;
+	int panel_power_cycle_delay;
+	int backlight_on_delay;
+	int backlight_off_delay;
+	struct drm_display_mode *panel_fixed_mode;  /* for eDP */
+	bool panel_on;
+};
+
+struct ddi_regoff {
+	uint32_t	PreEmph1;
+	uint32_t	PreEmph2;
+	uint32_t	VSwing1;
+	uint32_t	VSwing2;
+	uint32_t	VSwing3;
+	uint32_t	VSwing4;
+	uint32_t	VSwing5;
+};
+
+static struct ddi_regoff ddi_DP_train_table[] = {
+	{.PreEmph1 = 0x812c, .PreEmph2 = 0x8124, .VSwing1 = 0x8154,
+	.VSwing2 = 0x8148, .VSwing3 = 0x814C, .VSwing4 = 0x8150,
+	.VSwing5 = 0x8158,},
+	{.PreEmph1 = 0x822c, .PreEmph2 = 0x8224, .VSwing1 = 0x8254,
+	.VSwing2 = 0x8248, .VSwing3 = 0x824C, .VSwing4 = 0x8250,
+	.VSwing5 = 0x8258,},
+};
+
+static uint32_t dp_vswing_premph_table[] = {
+        0x55338954,	0x4000,
+        0x554d8954,	0x2000,
+        0x55668954,	0,
+        0x559ac0d4,	0x6000,
+};
+/**
+ * is_edp - is the given port attached to an eDP panel (either CPU or PCH)
+ * @intel_dp: DP struct
+ *
+ * If a CPU or PCH DP output is attached to an eDP panel, this function
+ * will return true, and false otherwise.
+ */
+static bool is_edp(struct psb_intel_encoder *encoder)
+{
+	return encoder->type == INTEL_OUTPUT_EDP;
+}
+
+
+static void cdv_intel_dp_start_link_train(struct psb_intel_encoder *encoder);
+static void cdv_intel_dp_complete_link_train(struct psb_intel_encoder *encoder);
+static void cdv_intel_dp_link_down(struct psb_intel_encoder *encoder);
+
+static int
+cdv_intel_dp_max_lane_count(struct psb_intel_encoder *encoder)
+{
+	struct cdv_intel_dp *intel_dp = encoder->dev_priv;
+	int max_lane_count = 4;
+
+	if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11) {
+		max_lane_count = intel_dp->dpcd[DP_MAX_LANE_COUNT] & 0x1f;
+		switch (max_lane_count) {
+		case 1: case 2: case 4:
+			break;
+		default:
+			max_lane_count = 4;
+		}
+	}
+	return max_lane_count;
+}
+
+static int
+cdv_intel_dp_max_link_bw(struct psb_intel_encoder *encoder)
+{
+	struct cdv_intel_dp *intel_dp = encoder->dev_priv;
+	int max_link_bw = intel_dp->dpcd[DP_MAX_LINK_RATE];
+
+	switch (max_link_bw) {
+	case DP_LINK_BW_1_62:
+	case DP_LINK_BW_2_7:
+		break;
+	default:
+		max_link_bw = DP_LINK_BW_1_62;
+		break;
+	}
+	return max_link_bw;
+}
+
+static int
+cdv_intel_dp_link_clock(uint8_t link_bw)
+{
+	if (link_bw == DP_LINK_BW_2_7)
+		return 270000;
+	else
+		return 162000;
+}
+
+static int
+cdv_intel_dp_link_required(int pixel_clock, int bpp)
+{
+	return (pixel_clock * bpp + 7) / 8;
+}
+
+static int
+cdv_intel_dp_max_data_rate(int max_link_clock, int max_lanes)
+{
+	return (max_link_clock * max_lanes * 19) / 20;
+}
+
+static void cdv_intel_edp_panel_vdd_on(struct psb_intel_encoder *intel_encoder)
+{
+	struct drm_device *dev = intel_encoder->base.dev;
+	struct cdv_intel_dp *intel_dp = intel_encoder->dev_priv;
+	u32 pp;
+
+	if (intel_dp->panel_on) {
+		DRM_DEBUG_KMS("Skip VDD on because of panel on\n");
+		return;
+	}	
+	DRM_DEBUG_KMS("\n");
+
+	pp = REG_READ(PP_CONTROL);
+
+	pp |= EDP_FORCE_VDD;
+	REG_WRITE(PP_CONTROL, pp);
+	REG_READ(PP_CONTROL);
+	msleep(intel_dp->panel_power_up_delay);
+}
+
+static void cdv_intel_edp_panel_vdd_off(struct psb_intel_encoder *intel_encoder)
+{
+	struct drm_device *dev = intel_encoder->base.dev;
+	u32 pp;
+
+	DRM_DEBUG_KMS("\n");
+	pp = REG_READ(PP_CONTROL);
+
+	pp &= ~EDP_FORCE_VDD;
+	REG_WRITE(PP_CONTROL, pp);
+	REG_READ(PP_CONTROL);
+
+}
+
+/* Returns true if the panel was already on when called */
+static bool cdv_intel_edp_panel_on(struct psb_intel_encoder *intel_encoder)
+{
+	struct drm_device *dev = intel_encoder->base.dev;
+	struct cdv_intel_dp *intel_dp = intel_encoder->dev_priv;
+	u32 pp, idle_on_mask = PP_ON | PP_SEQUENCE_NONE;
+
+	if (intel_dp->panel_on)
+		return true;
+
+	DRM_DEBUG_KMS("\n");
+	pp = REG_READ(PP_CONTROL);
+	pp &= ~PANEL_UNLOCK_MASK;
+
+	pp |= (PANEL_UNLOCK_REGS | POWER_TARGET_ON);
+	REG_WRITE(PP_CONTROL, pp);
+	REG_READ(PP_CONTROL);
+
+	if (wait_for(((REG_READ(PP_STATUS) & idle_on_mask) == idle_on_mask), 1000)) {
+		DRM_DEBUG_KMS("Error in Powering up eDP panel, status %x\n", REG_READ(PP_STATUS));
+		intel_dp->panel_on = false;
+	} else
+		intel_dp->panel_on = true;	
+	msleep(intel_dp->panel_power_up_delay);
+
+	return false;
+}
+
+static void cdv_intel_edp_panel_off (struct psb_intel_encoder *intel_encoder)
+{
+	struct drm_device *dev = intel_encoder->base.dev;
+	u32 pp, idle_off_mask = PP_ON ;
+	struct cdv_intel_dp *intel_dp = intel_encoder->dev_priv;
+
+	DRM_DEBUG_KMS("\n");
+
+	pp = REG_READ(PP_CONTROL);
+
+	if ((pp & POWER_TARGET_ON) == 0) 
+		return;
+
+	intel_dp->panel_on = false;
+	pp &= ~PANEL_UNLOCK_MASK;
+	/* ILK workaround: disable reset around power sequence */
+
+	pp &= ~POWER_TARGET_ON;
+	pp &= ~EDP_FORCE_VDD;
+	pp &= ~EDP_BLC_ENABLE;
+	REG_WRITE(PP_CONTROL, pp);
+	REG_READ(PP_CONTROL);
+	DRM_DEBUG_KMS("PP_STATUS %x\n", REG_READ(PP_STATUS));
+
+	if (wait_for((REG_READ(PP_STATUS) & idle_off_mask) == 0, 1000)) {
+		DRM_DEBUG_KMS("Error in turning off Panel\n");	
+	}
+
+	msleep(intel_dp->panel_power_cycle_delay);
+	DRM_DEBUG_KMS("Over\n");
+}
+
+static void cdv_intel_edp_backlight_on (struct psb_intel_encoder *intel_encoder)
+{
+	struct drm_device *dev = intel_encoder->base.dev;
+	u32 pp;
+
+	DRM_DEBUG_KMS("\n");
+	/*
+	 * If we enable the backlight right away following a panel power
+	 * on, we may see slight flicker as the panel syncs with the eDP
+	 * link.  So delay a bit to make sure the image is solid before
+	 * allowing it to appear.
+	 */
+	msleep(300);
+	pp = REG_READ(PP_CONTROL);
+
+	pp |= EDP_BLC_ENABLE;
+	REG_WRITE(PP_CONTROL, pp);
+	gma_backlight_enable(dev);
+}
+
+static void cdv_intel_edp_backlight_off (struct psb_intel_encoder *intel_encoder)
+{
+	struct drm_device *dev = intel_encoder->base.dev;
+	struct cdv_intel_dp *intel_dp = intel_encoder->dev_priv;
+	u32 pp;
+
+	DRM_DEBUG_KMS("\n");
+	gma_backlight_disable(dev);
+	msleep(10);
+	pp = REG_READ(PP_CONTROL);
+
+	pp &= ~EDP_BLC_ENABLE;
+	REG_WRITE(PP_CONTROL, pp);
+	msleep(intel_dp->backlight_off_delay);
+}
+
+static int
+cdv_intel_dp_mode_valid(struct drm_connector *connector,
+		    struct drm_display_mode *mode)
+{
+	struct psb_intel_encoder *encoder = psb_intel_attached_encoder(connector);
+	struct cdv_intel_dp *intel_dp = encoder->dev_priv;
+	int max_link_clock = cdv_intel_dp_link_clock(cdv_intel_dp_max_link_bw(encoder));
+	int max_lanes = cdv_intel_dp_max_lane_count(encoder);
+	struct drm_psb_private *dev_priv = connector->dev->dev_private;
+
+	if (is_edp(encoder) && intel_dp->panel_fixed_mode) {
+		if (mode->hdisplay > intel_dp->panel_fixed_mode->hdisplay)
+			return MODE_PANEL;
+		if (mode->vdisplay > intel_dp->panel_fixed_mode->vdisplay)
+			return MODE_PANEL;
+	}
+
+	/* only refuse the mode on non eDP since we have seen some weird eDP panels
+	   which are outside spec tolerances but somehow work by magic */
+	if (!is_edp(encoder) &&
+	    (cdv_intel_dp_link_required(mode->clock, dev_priv->edp.bpp)
+	     > cdv_intel_dp_max_data_rate(max_link_clock, max_lanes)))
+		return MODE_CLOCK_HIGH;
+
+	if (is_edp(encoder)) {
+	    if (cdv_intel_dp_link_required(mode->clock, 24)
+	     	> cdv_intel_dp_max_data_rate(max_link_clock, max_lanes))
+		return MODE_CLOCK_HIGH;
+		
+	}
+	if (mode->clock < 10000)
+		return MODE_CLOCK_LOW;
+
+	return MODE_OK;
+}
+
+static uint32_t
+pack_aux(uint8_t *src, int src_bytes)
+{
+	int	i;
+	uint32_t v = 0;
+
+	if (src_bytes > 4)
+		src_bytes = 4;
+	for (i = 0; i < src_bytes; i++)
+		v |= ((uint32_t) src[i]) << ((3-i) * 8);
+	return v;
+}
+
+static void
+unpack_aux(uint32_t src, uint8_t *dst, int dst_bytes)
+{
+	int i;
+	if (dst_bytes > 4)
+		dst_bytes = 4;
+	for (i = 0; i < dst_bytes; i++)
+		dst[i] = src >> ((3-i) * 8);
+}
+
+static int
+cdv_intel_dp_aux_ch(struct psb_intel_encoder *encoder,
+		uint8_t *send, int send_bytes,
+		uint8_t *recv, int recv_size)
+{
+	struct cdv_intel_dp *intel_dp = encoder->dev_priv;
+	uint32_t output_reg = intel_dp->output_reg;
+	struct drm_device *dev = encoder->base.dev;
+	uint32_t ch_ctl = output_reg + 0x10;
+	uint32_t ch_data = ch_ctl + 4;
+	int i;
+	int recv_bytes;
+	uint32_t status;
+	uint32_t aux_clock_divider;
+	int try, precharge;
+
+	/* The clock divider is based off the hrawclk,
+	 * and would like to run at 2MHz. So, take the
+	 * hrawclk value and divide by 2 and use that
+	 * On CDV platform it uses 200MHz as hrawclk.
+	 *
+	 */
+	aux_clock_divider = 200 / 2;
+
+	precharge = 4;
+	if (is_edp(encoder))
+		precharge = 10;
+
+	if (REG_READ(ch_ctl) & DP_AUX_CH_CTL_SEND_BUSY) {
+		DRM_ERROR("dp_aux_ch not started status 0x%08x\n",
+			  REG_READ(ch_ctl));
+		return -EBUSY;
+	}
+
+	/* Must try at least 3 times according to DP spec */
+	for (try = 0; try < 5; try++) {
+		/* Load the send data into the aux channel data registers */
+		for (i = 0; i < send_bytes; i += 4)
+			REG_WRITE(ch_data + i,
+				   pack_aux(send + i, send_bytes - i));
+	
+		/* Send the command and wait for it to complete */
+		REG_WRITE(ch_ctl,
+			   DP_AUX_CH_CTL_SEND_BUSY |
+			   DP_AUX_CH_CTL_TIME_OUT_400us |
+			   (send_bytes << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) |
+			   (precharge << DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT) |
+			   (aux_clock_divider << DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT) |
+			   DP_AUX_CH_CTL_DONE |
+			   DP_AUX_CH_CTL_TIME_OUT_ERROR |
+			   DP_AUX_CH_CTL_RECEIVE_ERROR);
+		for (;;) {
+			status = REG_READ(ch_ctl);
+			if ((status & DP_AUX_CH_CTL_SEND_BUSY) == 0)
+				break;
+			udelay(100);
+		}
+	
+		/* Clear done status and any errors */
+		REG_WRITE(ch_ctl,
+			   status |
+			   DP_AUX_CH_CTL_DONE |
+			   DP_AUX_CH_CTL_TIME_OUT_ERROR |
+			   DP_AUX_CH_CTL_RECEIVE_ERROR);
+		if (status & DP_AUX_CH_CTL_DONE)
+			break;
+	}
+
+	if ((status & DP_AUX_CH_CTL_DONE) == 0) {
+		DRM_ERROR("dp_aux_ch not done status 0x%08x\n", status);
+		return -EBUSY;
+	}
+
+	/* Check for timeout or receive error.
+	 * Timeouts occur when the sink is not connected
+	 */
+	if (status & DP_AUX_CH_CTL_RECEIVE_ERROR) {
+		DRM_ERROR("dp_aux_ch receive error status 0x%08x\n", status);
+		return -EIO;
+	}
+
+	/* Timeouts occur when the device isn't connected, so they're
+	 * "normal" -- don't fill the kernel log with these */
+	if (status & DP_AUX_CH_CTL_TIME_OUT_ERROR) {
+		DRM_DEBUG_KMS("dp_aux_ch timeout status 0x%08x\n", status);
+		return -ETIMEDOUT;
+	}
+
+	/* Unload any bytes sent back from the other side */
+	recv_bytes = ((status & DP_AUX_CH_CTL_MESSAGE_SIZE_MASK) >>
+		      DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT);
+	if (recv_bytes > recv_size)
+		recv_bytes = recv_size;
+	
+	for (i = 0; i < recv_bytes; i += 4)
+		unpack_aux(REG_READ(ch_data + i),
+			   recv + i, recv_bytes - i);
+
+	return recv_bytes;
+}
+
+/* Write data to the aux channel in native mode */
+static int
+cdv_intel_dp_aux_native_write(struct psb_intel_encoder *encoder,
+			  uint16_t address, uint8_t *send, int send_bytes)
+{
+	int ret;
+	uint8_t	msg[20];
+	int msg_bytes;
+	uint8_t	ack;
+
+	if (send_bytes > 16)
+		return -1;
+	msg[0] = AUX_NATIVE_WRITE << 4;
+	msg[1] = address >> 8;
+	msg[2] = address & 0xff;
+	msg[3] = send_bytes - 1;
+	memcpy(&msg[4], send, send_bytes);
+	msg_bytes = send_bytes + 4;
+	for (;;) {
+		ret = cdv_intel_dp_aux_ch(encoder, msg, msg_bytes, &ack, 1);
+		if (ret < 0)
+			return ret;
+		if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK)
+			break;
+		else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER)
+			udelay(100);
+		else
+			return -EIO;
+	}
+	return send_bytes;
+}
+
+/* Write a single byte to the aux channel in native mode */
+static int
+cdv_intel_dp_aux_native_write_1(struct psb_intel_encoder *encoder,
+			    uint16_t address, uint8_t byte)
+{
+	return cdv_intel_dp_aux_native_write(encoder, address, &byte, 1);
+}
+
+/* read bytes from a native aux channel */
+static int
+cdv_intel_dp_aux_native_read(struct psb_intel_encoder *encoder,
+			 uint16_t address, uint8_t *recv, int recv_bytes)
+{
+	uint8_t msg[4];
+	int msg_bytes;
+	uint8_t reply[20];
+	int reply_bytes;
+	uint8_t ack;
+	int ret;
+
+	msg[0] = AUX_NATIVE_READ << 4;
+	msg[1] = address >> 8;
+	msg[2] = address & 0xff;
+	msg[3] = recv_bytes - 1;
+
+	msg_bytes = 4;
+	reply_bytes = recv_bytes + 1;
+
+	for (;;) {
+		ret = cdv_intel_dp_aux_ch(encoder, msg, msg_bytes,
+				      reply, reply_bytes);
+		if (ret == 0)
+			return -EPROTO;
+		if (ret < 0)
+			return ret;
+		ack = reply[0];
+		if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK) {
+			memcpy(recv, reply + 1, ret - 1);
+			return ret - 1;
+		}
+		else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER)
+			udelay(100);
+		else
+			return -EIO;
+	}
+}
+
+static int
+cdv_intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
+		    uint8_t write_byte, uint8_t *read_byte)
+{
+	struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
+	struct cdv_intel_dp *intel_dp = container_of(adapter,
+						struct cdv_intel_dp,
+						adapter);
+	struct psb_intel_encoder *encoder = intel_dp->encoder;
+	uint16_t address = algo_data->address;
+	uint8_t msg[5];
+	uint8_t reply[2];
+	unsigned retry;
+	int msg_bytes;
+	int reply_bytes;
+	int ret;
+
+	/* Set up the command byte */
+	if (mode & MODE_I2C_READ)
+		msg[0] = AUX_I2C_READ << 4;
+	else
+		msg[0] = AUX_I2C_WRITE << 4;
+
+	if (!(mode & MODE_I2C_STOP))
+		msg[0] |= AUX_I2C_MOT << 4;
+
+	msg[1] = address >> 8;
+	msg[2] = address;
+
+	switch (mode) {
+	case MODE_I2C_WRITE:
+		msg[3] = 0;
+		msg[4] = write_byte;
+		msg_bytes = 5;
+		reply_bytes = 1;
+		break;
+	case MODE_I2C_READ:
+		msg[3] = 0;
+		msg_bytes = 4;
+		reply_bytes = 2;
+		break;
+	default:
+		msg_bytes = 3;
+		reply_bytes = 1;
+		break;
+	}
+
+	for (retry = 0; retry < 5; retry++) {
+		ret = cdv_intel_dp_aux_ch(encoder,
+				      msg, msg_bytes,
+				      reply, reply_bytes);
+		if (ret < 0) {
+			DRM_DEBUG_KMS("aux_ch failed %d\n", ret);
+			return ret;
+		}
+
+		switch (reply[0] & AUX_NATIVE_REPLY_MASK) {
+		case AUX_NATIVE_REPLY_ACK:
+			/* I2C-over-AUX Reply field is only valid
+			 * when paired with AUX ACK.
+			 */
+			break;
+		case AUX_NATIVE_REPLY_NACK:
+			DRM_DEBUG_KMS("aux_ch native nack\n");
+			return -EREMOTEIO;
+		case AUX_NATIVE_REPLY_DEFER:
+			udelay(100);
+			continue;
+		default:
+			DRM_ERROR("aux_ch invalid native reply 0x%02x\n",
+				  reply[0]);
+			return -EREMOTEIO;
+		}
+
+		switch (reply[0] & AUX_I2C_REPLY_MASK) {
+		case AUX_I2C_REPLY_ACK:
+			if (mode == MODE_I2C_READ) {
+				*read_byte = reply[1];
+			}
+			return reply_bytes - 1;
+		case AUX_I2C_REPLY_NACK:
+			DRM_DEBUG_KMS("aux_i2c nack\n");
+			return -EREMOTEIO;
+		case AUX_I2C_REPLY_DEFER:
+			DRM_DEBUG_KMS("aux_i2c defer\n");
+			udelay(100);
+			break;
+		default:
+			DRM_ERROR("aux_i2c invalid reply 0x%02x\n", reply[0]);
+			return -EREMOTEIO;
+		}
+	}
+
+	DRM_ERROR("too many retries, giving up\n");
+	return -EREMOTEIO;
+}
+
+static int
+cdv_intel_dp_i2c_init(struct psb_intel_connector *connector, struct psb_intel_encoder *encoder, const char *name)
+{
+	struct cdv_intel_dp *intel_dp = encoder->dev_priv;
+	int ret;
+
+	DRM_DEBUG_KMS("i2c_init %s\n", name);
+
+	intel_dp->algo.running = false;
+	intel_dp->algo.address = 0;
+	intel_dp->algo.aux_ch = cdv_intel_dp_i2c_aux_ch;
+
+	memset(&intel_dp->adapter, '\0', sizeof (intel_dp->adapter));
+	intel_dp->adapter.owner = THIS_MODULE;
+	intel_dp->adapter.class = I2C_CLASS_DDC;
+	strncpy (intel_dp->adapter.name, name, sizeof(intel_dp->adapter.name) - 1);
+	intel_dp->adapter.name[sizeof(intel_dp->adapter.name) - 1] = '\0';
+	intel_dp->adapter.algo_data = &intel_dp->algo;
+	intel_dp->adapter.dev.parent = &connector->base.kdev;
+
+	if (is_edp(encoder))
+		cdv_intel_edp_panel_vdd_on(encoder);
+	ret = i2c_dp_aux_add_bus(&intel_dp->adapter);
+	if (is_edp(encoder))
+		cdv_intel_edp_panel_vdd_off(encoder);
+	
+	return ret;
+}
+
+void cdv_intel_fixed_panel_mode(struct drm_display_mode *fixed_mode,
+	struct drm_display_mode *adjusted_mode)
+{
+	adjusted_mode->hdisplay = fixed_mode->hdisplay;
+	adjusted_mode->hsync_start = fixed_mode->hsync_start;
+	adjusted_mode->hsync_end = fixed_mode->hsync_end;
+	adjusted_mode->htotal = fixed_mode->htotal;
+
+	adjusted_mode->vdisplay = fixed_mode->vdisplay;
+	adjusted_mode->vsync_start = fixed_mode->vsync_start;
+	adjusted_mode->vsync_end = fixed_mode->vsync_end;
+	adjusted_mode->vtotal = fixed_mode->vtotal;
+
+	adjusted_mode->clock = fixed_mode->clock;
+
+	drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
+}
+
+static bool
+cdv_intel_dp_mode_fixup(struct drm_encoder *encoder, const struct drm_display_mode *mode,
+		    struct drm_display_mode *adjusted_mode)
+{
+	struct drm_psb_private *dev_priv = encoder->dev->dev_private;
+	struct psb_intel_encoder *intel_encoder = to_psb_intel_encoder(encoder);
+	struct cdv_intel_dp *intel_dp = intel_encoder->dev_priv;
+	int lane_count, clock;
+	int max_lane_count = cdv_intel_dp_max_lane_count(intel_encoder);
+	int max_clock = cdv_intel_dp_max_link_bw(intel_encoder) == DP_LINK_BW_2_7 ? 1 : 0;
+	static int bws[2] = { DP_LINK_BW_1_62, DP_LINK_BW_2_7 };
+	int refclock = mode->clock;
+	int bpp = 24;
+
+	if (is_edp(intel_encoder) && intel_dp->panel_fixed_mode) {
+		cdv_intel_fixed_panel_mode(intel_dp->panel_fixed_mode, adjusted_mode);
+		refclock = intel_dp->panel_fixed_mode->clock;
+		bpp = dev_priv->edp.bpp;
+	}
+
+	for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) {
+		for (clock = max_clock; clock >= 0; clock--) {
+			int link_avail = cdv_intel_dp_max_data_rate(cdv_intel_dp_link_clock(bws[clock]), lane_count);
+
+			if (cdv_intel_dp_link_required(refclock, bpp) <= link_avail) {
+				intel_dp->link_bw = bws[clock];
+				intel_dp->lane_count = lane_count;
+				adjusted_mode->clock = cdv_intel_dp_link_clock(intel_dp->link_bw);
+				DRM_DEBUG_KMS("Display port link bw %02x lane "
+						"count %d clock %d\n",
+				       intel_dp->link_bw, intel_dp->lane_count,
+				       adjusted_mode->clock);
+				return true;
+			}
+		}
+	}
+	if (is_edp(intel_encoder)) {
+		/* okay we failed just pick the highest */
+		intel_dp->lane_count = max_lane_count;
+		intel_dp->link_bw = bws[max_clock];
+		adjusted_mode->clock = cdv_intel_dp_link_clock(intel_dp->link_bw);
+		DRM_DEBUG_KMS("Force picking display port link bw %02x lane "
+			      "count %d clock %d\n",
+			      intel_dp->link_bw, intel_dp->lane_count,
+			      adjusted_mode->clock);
+
+		return true;
+	}
+	return false;
+}
+
+struct cdv_intel_dp_m_n {
+	uint32_t	tu;
+	uint32_t	gmch_m;
+	uint32_t	gmch_n;
+	uint32_t	link_m;
+	uint32_t	link_n;
+};
+
+static void
+cdv_intel_reduce_ratio(uint32_t *num, uint32_t *den)
+{
+	/*
+	while (*num > 0xffffff || *den > 0xffffff) {
+		*num >>= 1;
+		*den >>= 1;
+	}*/
+	uint64_t value, m;
+	m = *num;
+	value = m * (0x800000);
+	m = do_div(value, *den);
+	*num = value;
+	*den = 0x800000;
+}
+
+static void
+cdv_intel_dp_compute_m_n(int bpp,
+		     int nlanes,
+		     int pixel_clock,
+		     int link_clock,
+		     struct cdv_intel_dp_m_n *m_n)
+{
+	m_n->tu = 64;
+	m_n->gmch_m = (pixel_clock * bpp + 7) >> 3;
+	m_n->gmch_n = link_clock * nlanes;
+	cdv_intel_reduce_ratio(&m_n->gmch_m, &m_n->gmch_n);
+	m_n->link_m = pixel_clock;
+	m_n->link_n = link_clock;
+	cdv_intel_reduce_ratio(&m_n->link_m, &m_n->link_n);
+}
+
+void
+cdv_intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
+		 struct drm_display_mode *adjusted_mode)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct drm_mode_config *mode_config = &dev->mode_config;
+	struct drm_encoder *encoder;
+	struct psb_intel_crtc *intel_crtc = to_psb_intel_crtc(crtc);
+	int lane_count = 4, bpp = 24;
+	struct cdv_intel_dp_m_n m_n;
+	int pipe = intel_crtc->pipe;
+
+	/*
+	 * Find the lane count in the intel_encoder private
+	 */
+	list_for_each_entry(encoder, &mode_config->encoder_list, head) {
+		struct psb_intel_encoder *intel_encoder;
+		struct cdv_intel_dp *intel_dp;
+
+		if (encoder->crtc != crtc)
+			continue;
+
+		intel_encoder = to_psb_intel_encoder(encoder);
+		intel_dp = intel_encoder->dev_priv;
+		if (intel_encoder->type == INTEL_OUTPUT_DISPLAYPORT) {
+			lane_count = intel_dp->lane_count;
+			break;
+		} else if (is_edp(intel_encoder)) {
+			lane_count = intel_dp->lane_count;
+			bpp = dev_priv->edp.bpp;
+			break;
+		}
+	}
+
+	/*
+	 * Compute the GMCH and Link ratios. The '3' here is
+	 * the number of bytes_per_pixel post-LUT, which we always
+	 * set up for 8-bits of R/G/B, or 3 bytes total.
+	 */
+	cdv_intel_dp_compute_m_n(bpp, lane_count,
+			     mode->clock, adjusted_mode->clock, &m_n);
+
+	{
+		REG_WRITE(PIPE_GMCH_DATA_M(pipe),
+			   ((m_n.tu - 1) << PIPE_GMCH_DATA_M_TU_SIZE_SHIFT) |
+			   m_n.gmch_m);
+		REG_WRITE(PIPE_GMCH_DATA_N(pipe), m_n.gmch_n);
+		REG_WRITE(PIPE_DP_LINK_M(pipe), m_n.link_m);
+		REG_WRITE(PIPE_DP_LINK_N(pipe), m_n.link_n);
+	}
+}
+
+static void
+cdv_intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
+		  struct drm_display_mode *adjusted_mode)
+{
+	struct psb_intel_encoder *intel_encoder = to_psb_intel_encoder(encoder);
+	struct drm_crtc *crtc = encoder->crtc;
+	struct psb_intel_crtc *intel_crtc = to_psb_intel_crtc(crtc);
+	struct cdv_intel_dp *intel_dp = intel_encoder->dev_priv;
+	struct drm_device *dev = encoder->dev;
+
+	intel_dp->DP = DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0;
+	intel_dp->DP |= intel_dp->color_range;
+
+	if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
+		intel_dp->DP |= DP_SYNC_HS_HIGH;
+	if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
+		intel_dp->DP |= DP_SYNC_VS_HIGH;
+
+	intel_dp->DP |= DP_LINK_TRAIN_OFF;
+
+	switch (intel_dp->lane_count) {
+	case 1:
+		intel_dp->DP |= DP_PORT_WIDTH_1;
+		break;
+	case 2:
+		intel_dp->DP |= DP_PORT_WIDTH_2;
+		break;
+	case 4:
+		intel_dp->DP |= DP_PORT_WIDTH_4;
+		break;
+	}
+	if (intel_dp->has_audio)
+		intel_dp->DP |= DP_AUDIO_OUTPUT_ENABLE;
+
+	memset(intel_dp->link_configuration, 0, DP_LINK_CONFIGURATION_SIZE);
+	intel_dp->link_configuration[0] = intel_dp->link_bw;
+	intel_dp->link_configuration[1] = intel_dp->lane_count;
+
+	/*
+	 * Check for DPCD version > 1.1 and enhanced framing support
+	 */
+	if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11 &&
+	    (intel_dp->dpcd[DP_MAX_LANE_COUNT] & DP_ENHANCED_FRAME_CAP)) {
+		intel_dp->link_configuration[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
+		intel_dp->DP |= DP_ENHANCED_FRAMING;
+	}
+
+	/* CPT DP's pipe select is decided in TRANS_DP_CTL */
+	if (intel_crtc->pipe == 1)
+		intel_dp->DP |= DP_PIPEB_SELECT;
+
+	REG_WRITE(intel_dp->output_reg, (intel_dp->DP | DP_PORT_EN));
+	DRM_DEBUG_KMS("DP expected reg is %x\n", intel_dp->DP);
+	if (is_edp(intel_encoder)) {
+		uint32_t pfit_control;
+		cdv_intel_edp_panel_on(intel_encoder);
+
+		if (mode->hdisplay != adjusted_mode->hdisplay ||
+			    mode->vdisplay != adjusted_mode->vdisplay)
+			pfit_control = PFIT_ENABLE;
+		else
+			pfit_control = 0;
+
+		pfit_control |= intel_crtc->pipe << PFIT_PIPE_SHIFT;
+
+		REG_WRITE(PFIT_CONTROL, pfit_control);
+	}
+}
+
+
+/* If the sink supports it, try to set the power state appropriately */
+static void cdv_intel_dp_sink_dpms(struct psb_intel_encoder *encoder, int mode)
+{
+	struct cdv_intel_dp *intel_dp = encoder->dev_priv;
+	int ret, i;
+
+	/* Should have a valid DPCD by this point */
+	if (intel_dp->dpcd[DP_DPCD_REV] < 0x11)
+		return;
+
+	if (mode != DRM_MODE_DPMS_ON) {
+		ret = cdv_intel_dp_aux_native_write_1(encoder, DP_SET_POWER,
+						  DP_SET_POWER_D3);
+		if (ret != 1)
+			DRM_DEBUG_DRIVER("failed to write sink power state\n");
+	} else {
+		/*
+		 * When turning on, we need to retry for 1ms to give the sink
+		 * time to wake up.
+		 */
+		for (i = 0; i < 3; i++) {
+			ret = cdv_intel_dp_aux_native_write_1(encoder,
+							  DP_SET_POWER,
+							  DP_SET_POWER_D0);
+			if (ret == 1)
+				break;
+			udelay(1000);
+		}
+	}
+}
+
+static void cdv_intel_dp_prepare(struct drm_encoder *encoder)
+{
+	struct psb_intel_encoder *intel_encoder = to_psb_intel_encoder(encoder);
+	int edp = is_edp(intel_encoder);
+
+	if (edp) {
+		cdv_intel_edp_backlight_off(intel_encoder);
+		cdv_intel_edp_panel_off(intel_encoder);
+		cdv_intel_edp_panel_vdd_on(intel_encoder);
+        }
+	/* Wake up the sink first */
+	cdv_intel_dp_sink_dpms(intel_encoder, DRM_MODE_DPMS_ON);
+	cdv_intel_dp_link_down(intel_encoder);
+	if (edp)
+		cdv_intel_edp_panel_vdd_off(intel_encoder);
+}
+
+static void cdv_intel_dp_commit(struct drm_encoder *encoder)
+{
+	struct psb_intel_encoder *intel_encoder = to_psb_intel_encoder(encoder);
+	int edp = is_edp(intel_encoder);
+
+	if (edp)
+		cdv_intel_edp_panel_on(intel_encoder);
+	cdv_intel_dp_start_link_train(intel_encoder);
+	cdv_intel_dp_complete_link_train(intel_encoder);
+	if (edp)
+		cdv_intel_edp_backlight_on(intel_encoder);
+}
+
+static void
+cdv_intel_dp_dpms(struct drm_encoder *encoder, int mode)
+{
+	struct psb_intel_encoder *intel_encoder = to_psb_intel_encoder(encoder);
+	struct cdv_intel_dp *intel_dp = intel_encoder->dev_priv;
+	struct drm_device *dev = encoder->dev;
+	uint32_t dp_reg = REG_READ(intel_dp->output_reg);
+	int edp = is_edp(intel_encoder);
+
+	if (mode != DRM_MODE_DPMS_ON) {
+		if (edp) {
+			cdv_intel_edp_backlight_off(intel_encoder);
+			cdv_intel_edp_panel_vdd_on(intel_encoder);
+		}
+		cdv_intel_dp_sink_dpms(intel_encoder, mode);
+		cdv_intel_dp_link_down(intel_encoder);
+		if (edp) {
+			cdv_intel_edp_panel_vdd_off(intel_encoder);
+			cdv_intel_edp_panel_off(intel_encoder);
+		}
+	} else {
+        	if (edp)
+			cdv_intel_edp_panel_on(intel_encoder);
+		cdv_intel_dp_sink_dpms(intel_encoder, mode);
+		if (!(dp_reg & DP_PORT_EN)) {
+			cdv_intel_dp_start_link_train(intel_encoder);
+			cdv_intel_dp_complete_link_train(intel_encoder);
+		}
+		if (edp)
+        		cdv_intel_edp_backlight_on(intel_encoder);
+	}
+}
+
+/*
+ * Native read with retry for link status and receiver capability reads for
+ * cases where the sink may still be asleep.
+ */
+static bool
+cdv_intel_dp_aux_native_read_retry(struct psb_intel_encoder *encoder, uint16_t address,
+			       uint8_t *recv, int recv_bytes)
+{
+	int ret, i;
+
+	/*
+	 * Sinks are *supposed* to come up within 1ms from an off state,
+	 * but we're also supposed to retry 3 times per the spec.
+	 */
+	for (i = 0; i < 3; i++) {
+		ret = cdv_intel_dp_aux_native_read(encoder, address, recv,
+					       recv_bytes);
+		if (ret == recv_bytes)
+			return true;
+		udelay(1000);
+	}
+
+	return false;
+}
+
+/*
+ * Fetch AUX CH registers 0x202 - 0x207 which contain
+ * link status information
+ */
+static bool
+cdv_intel_dp_get_link_status(struct psb_intel_encoder *encoder)
+{
+	struct cdv_intel_dp *intel_dp = encoder->dev_priv;
+	return cdv_intel_dp_aux_native_read_retry(encoder,
+					      DP_LANE0_1_STATUS,
+					      intel_dp->link_status,
+					      DP_LINK_STATUS_SIZE);
+}
+
+static uint8_t
+cdv_intel_dp_link_status(uint8_t link_status[DP_LINK_STATUS_SIZE],
+		     int r)
+{
+	return link_status[r - DP_LANE0_1_STATUS];
+}
+
+static uint8_t
+cdv_intel_get_adjust_request_voltage(uint8_t link_status[DP_LINK_STATUS_SIZE],
+				 int lane)
+{
+	int	    i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1);
+	int	    s = ((lane & 1) ?
+			 DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT :
+			 DP_ADJUST_VOLTAGE_SWING_LANE0_SHIFT);
+	uint8_t l = cdv_intel_dp_link_status(link_status, i);
+
+	return ((l >> s) & 3) << DP_TRAIN_VOLTAGE_SWING_SHIFT;
+}
+
+static uint8_t
+cdv_intel_get_adjust_request_pre_emphasis(uint8_t link_status[DP_LINK_STATUS_SIZE],
+				      int lane)
+{
+	int	    i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1);
+	int	    s = ((lane & 1) ?
+			 DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT :
+			 DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT);
+	uint8_t l = cdv_intel_dp_link_status(link_status, i);
+
+	return ((l >> s) & 3) << DP_TRAIN_PRE_EMPHASIS_SHIFT;
+}
+
+
+#if 0
+static char	*voltage_names[] = {
+	"0.4V", "0.6V", "0.8V", "1.2V"
+};
+static char	*pre_emph_names[] = {
+	"0dB", "3.5dB", "6dB", "9.5dB"
+};
+static char	*link_train_names[] = {
+	"pattern 1", "pattern 2", "idle", "off"
+};
+#endif
+
+#define CDV_DP_VOLTAGE_MAX	    DP_TRAIN_VOLTAGE_SWING_1200
+/*
+static uint8_t
+cdv_intel_dp_pre_emphasis_max(uint8_t voltage_swing)
+{
+	switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) {
+	case DP_TRAIN_VOLTAGE_SWING_400:
+		return DP_TRAIN_PRE_EMPHASIS_6;
+	case DP_TRAIN_VOLTAGE_SWING_600:
+		return DP_TRAIN_PRE_EMPHASIS_6;
+	case DP_TRAIN_VOLTAGE_SWING_800:
+		return DP_TRAIN_PRE_EMPHASIS_3_5;
+	case DP_TRAIN_VOLTAGE_SWING_1200:
+	default:
+		return DP_TRAIN_PRE_EMPHASIS_0;
+	}
+}
+*/
+static void
+cdv_intel_get_adjust_train(struct psb_intel_encoder *encoder)
+{
+	struct cdv_intel_dp *intel_dp = encoder->dev_priv;
+	uint8_t v = 0;
+	uint8_t p = 0;
+	int lane;
+
+	for (lane = 0; lane < intel_dp->lane_count; lane++) {
+		uint8_t this_v = cdv_intel_get_adjust_request_voltage(intel_dp->link_status, lane);
+		uint8_t this_p = cdv_intel_get_adjust_request_pre_emphasis(intel_dp->link_status, lane);
+
+		if (this_v > v)
+			v = this_v;
+		if (this_p > p)
+			p = this_p;
+	}
+	
+	if (v >= CDV_DP_VOLTAGE_MAX)
+		v = CDV_DP_VOLTAGE_MAX | DP_TRAIN_MAX_SWING_REACHED;
+
+	if (p == DP_TRAIN_PRE_EMPHASIS_MASK)
+		p |= DP_TRAIN_MAX_PRE_EMPHASIS_REACHED;
+		
+	for (lane = 0; lane < 4; lane++)
+		intel_dp->train_set[lane] = v | p;
+}
+
+
+static uint8_t
+cdv_intel_get_lane_status(uint8_t link_status[DP_LINK_STATUS_SIZE],
+		      int lane)
+{
+	int i = DP_LANE0_1_STATUS + (lane >> 1);
+	int s = (lane & 1) * 4;
+	uint8_t l = cdv_intel_dp_link_status(link_status, i);
+
+	return (l >> s) & 0xf;
+}
+
+/* Check for clock recovery is done on all channels */
+static bool
+cdv_intel_clock_recovery_ok(uint8_t link_status[DP_LINK_STATUS_SIZE], int lane_count)
+{
+	int lane;
+	uint8_t lane_status;
+
+	for (lane = 0; lane < lane_count; lane++) {
+		lane_status = cdv_intel_get_lane_status(link_status, lane);
+		if ((lane_status & DP_LANE_CR_DONE) == 0)
+			return false;
+	}
+	return true;
+}
+
+/* Check to see if channel eq is done on all channels */
+#define CHANNEL_EQ_BITS (DP_LANE_CR_DONE|\
+			 DP_LANE_CHANNEL_EQ_DONE|\
+			 DP_LANE_SYMBOL_LOCKED)
+static bool
+cdv_intel_channel_eq_ok(struct psb_intel_encoder *encoder)
+{
+	struct cdv_intel_dp *intel_dp = encoder->dev_priv;
+	uint8_t lane_align;
+	uint8_t lane_status;
+	int lane;
+
+	lane_align = cdv_intel_dp_link_status(intel_dp->link_status,
+					  DP_LANE_ALIGN_STATUS_UPDATED);
+	if ((lane_align & DP_INTERLANE_ALIGN_DONE) == 0)
+		return false;
+	for (lane = 0; lane < intel_dp->lane_count; lane++) {
+		lane_status = cdv_intel_get_lane_status(intel_dp->link_status, lane);
+		if ((lane_status & CHANNEL_EQ_BITS) != CHANNEL_EQ_BITS)
+			return false;
+	}
+	return true;
+}
+
+static bool
+cdv_intel_dp_set_link_train(struct psb_intel_encoder *encoder,
+			uint32_t dp_reg_value,
+			uint8_t dp_train_pat)
+{
+	
+	struct drm_device *dev = encoder->base.dev;
+	int ret;
+	struct cdv_intel_dp *intel_dp = encoder->dev_priv;
+
+	REG_WRITE(intel_dp->output_reg, dp_reg_value);
+	REG_READ(intel_dp->output_reg);
+
+	ret = cdv_intel_dp_aux_native_write_1(encoder,
+				    DP_TRAINING_PATTERN_SET,
+				    dp_train_pat);
+
+	if (ret != 1) {
+		DRM_DEBUG_KMS("Failure in setting link pattern %x\n",
+				dp_train_pat);
+		return false;
+	}
+
+	return true;
+}
+
+
+static bool
+cdv_intel_dplink_set_level(struct psb_intel_encoder *encoder,
+			uint8_t dp_train_pat)
+{
+	
+	int ret;
+	struct cdv_intel_dp *intel_dp = encoder->dev_priv;
+
+	ret = cdv_intel_dp_aux_native_write(encoder,
+					DP_TRAINING_LANE0_SET,
+					intel_dp->train_set,
+					intel_dp->lane_count);
+
+	if (ret != intel_dp->lane_count) {
+		DRM_DEBUG_KMS("Failure in setting level %d, lane_cnt= %d\n",
+				intel_dp->train_set[0], intel_dp->lane_count);
+		return false;
+	}
+	return true;
+}
+
+static void
+cdv_intel_dp_set_vswing_premph(struct psb_intel_encoder *encoder, uint8_t signal_level)
+{
+	struct drm_device *dev = encoder->base.dev;
+	struct cdv_intel_dp *intel_dp = encoder->dev_priv;
+	struct ddi_regoff *ddi_reg;
+	int vswing, premph, index;
+
+	if (intel_dp->output_reg == DP_B)
+		ddi_reg = &ddi_DP_train_table[0];
+	else
+		ddi_reg = &ddi_DP_train_table[1];
+
+	vswing = (signal_level & DP_TRAIN_VOLTAGE_SWING_MASK);
+	premph = ((signal_level & DP_TRAIN_PRE_EMPHASIS_MASK)) >>
+				DP_TRAIN_PRE_EMPHASIS_SHIFT;
+
+	if (vswing + premph > 3)
+		return;
+#ifdef CDV_FAST_LINK_TRAIN
+	return;
+#endif
+	DRM_DEBUG_KMS("Test2\n");
+	//return ;
+	cdv_sb_reset(dev);
+	/* ;Swing voltage programming
+        ;gfx_dpio_set_reg(0xc058, 0x0505313A) */
+	cdv_sb_write(dev, ddi_reg->VSwing5, 0x0505313A);
+
+	/* ;gfx_dpio_set_reg(0x8154, 0x43406055) */
+	cdv_sb_write(dev, ddi_reg->VSwing1, 0x43406055);
+
+	/* ;gfx_dpio_set_reg(0x8148, 0x55338954)
+	 * The VSwing_PreEmph table is also considered based on the vswing/premp
+	 */
+	index = (vswing + premph) * 2;
+	if (premph == 1 && vswing == 1) {
+		cdv_sb_write(dev, ddi_reg->VSwing2, 0x055738954);
+	} else
+		cdv_sb_write(dev, ddi_reg->VSwing2, dp_vswing_premph_table[index]);
+
+	/* ;gfx_dpio_set_reg(0x814c, 0x40802040) */
+	if ((vswing + premph) == DP_TRAIN_VOLTAGE_SWING_1200)
+		cdv_sb_write(dev, ddi_reg->VSwing3, 0x70802040);
+	else
+		cdv_sb_write(dev, ddi_reg->VSwing3, 0x40802040);
+
+	/* ;gfx_dpio_set_reg(0x8150, 0x2b405555) */
+	/* cdv_sb_write(dev, ddi_reg->VSwing4, 0x2b405555); */
+
+	/* ;gfx_dpio_set_reg(0x8154, 0xc3406055) */
+	cdv_sb_write(dev, ddi_reg->VSwing1, 0xc3406055);
+
+	/* ;Pre emphasis programming
+	 * ;gfx_dpio_set_reg(0xc02c, 0x1f030040)
+	 */
+	cdv_sb_write(dev, ddi_reg->PreEmph1, 0x1f030040);
+
+	/* ;gfx_dpio_set_reg(0x8124, 0x00004000) */
+	index = 2 * premph + 1;
+	cdv_sb_write(dev, ddi_reg->PreEmph2, dp_vswing_premph_table[index]);
+	return;	
+}
+
+
+/* Enable corresponding port and start training pattern 1 */
+static void
+cdv_intel_dp_start_link_train(struct psb_intel_encoder *encoder)
+{
+	struct drm_device *dev = encoder->base.dev;
+	struct cdv_intel_dp *intel_dp = encoder->dev_priv;
+	int i;
+	uint8_t voltage;
+	bool clock_recovery = false;
+	int tries;
+	u32 reg;
+	uint32_t DP = intel_dp->DP;
+
+	DP |= DP_PORT_EN;
+	DP &= ~DP_LINK_TRAIN_MASK;
+		
+	reg = DP;	
+	reg |= DP_LINK_TRAIN_PAT_1;
+	/* Enable output, wait for it to become active */
+	REG_WRITE(intel_dp->output_reg, reg);
+	REG_READ(intel_dp->output_reg);
+	psb_intel_wait_for_vblank(dev);
+
+	DRM_DEBUG_KMS("Link config\n");
+	/* Write the link configuration data */
+	cdv_intel_dp_aux_native_write(encoder, DP_LINK_BW_SET,
+				  intel_dp->link_configuration,
+				  2);
+
+	memset(intel_dp->train_set, 0, 4);
+	voltage = 0;
+	tries = 0;
+	clock_recovery = false;
+
+	DRM_DEBUG_KMS("Start train\n");
+		reg = DP | DP_LINK_TRAIN_PAT_1;
+
+
+	for (;;) {
+		/* Use intel_dp->train_set[0] to set the voltage and pre emphasis values */
+		DRM_DEBUG_KMS("DP Link Train Set %x, Link_config %x, %x\n",
+				intel_dp->train_set[0],
+				intel_dp->link_configuration[0],
+				intel_dp->link_configuration[1]);
+
+		if (!cdv_intel_dp_set_link_train(encoder, reg, DP_TRAINING_PATTERN_1)) {
+			DRM_DEBUG_KMS("Failure in aux-transfer setting pattern 1\n");
+		}
+		cdv_intel_dp_set_vswing_premph(encoder, intel_dp->train_set[0]);
+		/* Set training pattern 1 */
+
+		cdv_intel_dplink_set_level(encoder, DP_TRAINING_PATTERN_1);
+
+		udelay(200);
+		if (!cdv_intel_dp_get_link_status(encoder))
+			break;
+
+		DRM_DEBUG_KMS("DP Link status %x, %x, %x, %x, %x, %x\n",
+				intel_dp->link_status[0], intel_dp->link_status[1], intel_dp->link_status[2],
+				intel_dp->link_status[3], intel_dp->link_status[4], intel_dp->link_status[5]);
+
+		if (cdv_intel_clock_recovery_ok(intel_dp->link_status, intel_dp->lane_count)) {
+			DRM_DEBUG_KMS("PT1 train is done\n");
+			clock_recovery = true;
+			break;
+		}
+
+		/* Check to see if we've tried the max voltage */
+		for (i = 0; i < intel_dp->lane_count; i++)
+			if ((intel_dp->train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0)
+				break;
+		if (i == intel_dp->lane_count)
+			break;
+
+		/* Check to see if we've tried the same voltage 5 times */
+		if ((intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) {
+			++tries;
+			if (tries == 5)
+				break;
+		} else
+			tries = 0;
+		voltage = intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK;
+
+		/* Compute new intel_dp->train_set as requested by target */
+		cdv_intel_get_adjust_train(encoder);
+
+	}
+
+	if (!clock_recovery) {
+		DRM_DEBUG_KMS("failure in DP patter 1 training, train set %x\n", intel_dp->train_set[0]);
+	}
+	
+	intel_dp->DP = DP;
+}
+
+static void
+cdv_intel_dp_complete_link_train(struct psb_intel_encoder *encoder)
+{
+	struct drm_device *dev = encoder->base.dev;
+	struct cdv_intel_dp *intel_dp = encoder->dev_priv;
+	bool channel_eq = false;
+	int tries, cr_tries;
+	u32 reg;
+	uint32_t DP = intel_dp->DP;
+
+	/* channel equalization */
+	tries = 0;
+	cr_tries = 0;
+	channel_eq = false;
+
+	DRM_DEBUG_KMS("\n");
+		reg = DP | DP_LINK_TRAIN_PAT_2;
+
+	for (;;) {
+
+		DRM_DEBUG_KMS("DP Link Train Set %x, Link_config %x, %x\n",
+				intel_dp->train_set[0],
+				intel_dp->link_configuration[0],
+				intel_dp->link_configuration[1]);
+        	/* channel eq pattern */
+
+		if (!cdv_intel_dp_set_link_train(encoder, reg,
+					     DP_TRAINING_PATTERN_2)) {
+			DRM_DEBUG_KMS("Failure in aux-transfer setting pattern 2\n");
+		}
+		/* Use intel_dp->train_set[0] to set the voltage and pre emphasis values */
+
+		if (cr_tries > 5) {
+			DRM_ERROR("failed to train DP, aborting\n");
+			cdv_intel_dp_link_down(encoder);
+			break;
+		}
+
+		cdv_intel_dp_set_vswing_premph(encoder, intel_dp->train_set[0]);
+
+		cdv_intel_dplink_set_level(encoder, DP_TRAINING_PATTERN_2);
+
+		udelay(1000);
+		if (!cdv_intel_dp_get_link_status(encoder))
+			break;
+
+		DRM_DEBUG_KMS("DP Link status %x, %x, %x, %x, %x, %x\n",
+				intel_dp->link_status[0], intel_dp->link_status[1], intel_dp->link_status[2],
+				intel_dp->link_status[3], intel_dp->link_status[4], intel_dp->link_status[5]);
+
+		/* Make sure clock is still ok */
+		if (!cdv_intel_clock_recovery_ok(intel_dp->link_status, intel_dp->lane_count)) {
+			cdv_intel_dp_start_link_train(encoder);
+			cr_tries++;
+			continue;
+		}
+
+		if (cdv_intel_channel_eq_ok(encoder)) {
+			DRM_DEBUG_KMS("PT2 train is done\n");
+			channel_eq = true;
+			break;
+		}
+
+		/* Try 5 times, then try clock recovery if that fails */
+		if (tries > 5) {
+			cdv_intel_dp_link_down(encoder);
+			cdv_intel_dp_start_link_train(encoder);
+			tries = 0;
+			cr_tries++;
+			continue;
+		}
+
+		/* Compute new intel_dp->train_set as requested by target */
+		cdv_intel_get_adjust_train(encoder);
+		++tries;
+
+	}
+
+	reg = DP | DP_LINK_TRAIN_OFF;
+
+	REG_WRITE(intel_dp->output_reg, reg);
+	REG_READ(intel_dp->output_reg);
+	cdv_intel_dp_aux_native_write_1(encoder,
+				    DP_TRAINING_PATTERN_SET, DP_TRAINING_PATTERN_DISABLE);
+}
+
+static void
+cdv_intel_dp_link_down(struct psb_intel_encoder *encoder)
+{
+	struct drm_device *dev = encoder->base.dev;
+	struct cdv_intel_dp *intel_dp = encoder->dev_priv;
+	uint32_t DP = intel_dp->DP;
+
+	if ((REG_READ(intel_dp->output_reg) & DP_PORT_EN) == 0)
+		return;
+
+	DRM_DEBUG_KMS("\n");
+
+
+	{
+		DP &= ~DP_LINK_TRAIN_MASK;
+		REG_WRITE(intel_dp->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE);
+	}
+	REG_READ(intel_dp->output_reg);
+
+	msleep(17);
+
+	REG_WRITE(intel_dp->output_reg, DP & ~DP_PORT_EN);
+	REG_READ(intel_dp->output_reg);
+}
+
+static enum drm_connector_status
+cdv_dp_detect(struct psb_intel_encoder *encoder)
+{
+	struct cdv_intel_dp *intel_dp = encoder->dev_priv;
+	enum drm_connector_status status;
+
+	status = connector_status_disconnected;
+	if (cdv_intel_dp_aux_native_read(encoder, 0x000, intel_dp->dpcd,
+				     sizeof (intel_dp->dpcd)) == sizeof (intel_dp->dpcd))
+	{
+		if (intel_dp->dpcd[DP_DPCD_REV] != 0)
+			status = connector_status_connected;
+	}
+	if (status == connector_status_connected)
+		DRM_DEBUG_KMS("DPCD: Rev=%x LN_Rate=%x LN_CNT=%x LN_DOWNSP=%x\n",
+			intel_dp->dpcd[0], intel_dp->dpcd[1],
+			intel_dp->dpcd[2], intel_dp->dpcd[3]);
+	return status;
+}
+
+/**
+ * Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect DP connection.
+ *
+ * \return true if DP port is connected.
+ * \return false if DP port is disconnected.
+ */
+static enum drm_connector_status
+cdv_intel_dp_detect(struct drm_connector *connector, bool force)
+{
+	struct psb_intel_encoder *encoder = psb_intel_attached_encoder(connector);
+	struct cdv_intel_dp *intel_dp = encoder->dev_priv;
+	enum drm_connector_status status;
+	struct edid *edid = NULL;
+	int edp = is_edp(encoder);
+
+	intel_dp->has_audio = false;
+
+	if (edp)
+		cdv_intel_edp_panel_vdd_on(encoder);
+	status = cdv_dp_detect(encoder);
+	if (status != connector_status_connected) {
+		if (edp)
+			cdv_intel_edp_panel_vdd_off(encoder);
+		return status;
+        }
+
+	if (intel_dp->force_audio) {
+		intel_dp->has_audio = intel_dp->force_audio > 0;
+	} else {
+		edid = drm_get_edid(connector, &intel_dp->adapter);
+		if (edid) {
+			intel_dp->has_audio = drm_detect_monitor_audio(edid);
+			kfree(edid);
+		}
+	}
+	if (edp)
+		cdv_intel_edp_panel_vdd_off(encoder);
+
+	return connector_status_connected;
+}
+
+static int cdv_intel_dp_get_modes(struct drm_connector *connector)
+{
+	struct psb_intel_encoder *intel_encoder = psb_intel_attached_encoder(connector);
+	struct cdv_intel_dp *intel_dp = intel_encoder->dev_priv;
+	struct edid *edid = NULL;
+	int ret = 0;
+	int edp = is_edp(intel_encoder);
+
+
+	edid = drm_get_edid(connector, &intel_dp->adapter);
+	if (edid) {
+		drm_mode_connector_update_edid_property(connector, edid);
+		ret = drm_add_edid_modes(connector, edid);
+		kfree(edid);
+	}
+
+	if (is_edp(intel_encoder)) {
+		struct drm_device *dev = connector->dev;
+		struct drm_psb_private *dev_priv = dev->dev_private;
+		
+		cdv_intel_edp_panel_vdd_off(intel_encoder);
+		if (ret) {
+			if (edp && !intel_dp->panel_fixed_mode) {
+				struct drm_display_mode *newmode;
+				list_for_each_entry(newmode, &connector->probed_modes,
+					    head) {
+					if (newmode->type & DRM_MODE_TYPE_PREFERRED) {
+						intel_dp->panel_fixed_mode =
+							drm_mode_duplicate(dev, newmode);
+						break;
+					}
+				}
+			}
+
+			return ret;
+		}
+		if (!intel_dp->panel_fixed_mode && dev_priv->lfp_lvds_vbt_mode) {
+			intel_dp->panel_fixed_mode =
+				drm_mode_duplicate(dev, dev_priv->lfp_lvds_vbt_mode);
+			if (intel_dp->panel_fixed_mode) {
+				intel_dp->panel_fixed_mode->type |=
+					DRM_MODE_TYPE_PREFERRED;
+			}
+		}
+		if (intel_dp->panel_fixed_mode != NULL) {
+			struct drm_display_mode *mode;
+			mode = drm_mode_duplicate(dev, intel_dp->panel_fixed_mode);
+			drm_mode_probed_add(connector, mode);
+			return 1;
+		}
+	}
+
+	return ret;
+}
+
+static bool
+cdv_intel_dp_detect_audio(struct drm_connector *connector)
+{
+	struct psb_intel_encoder *encoder = psb_intel_attached_encoder(connector);
+	struct cdv_intel_dp *intel_dp = encoder->dev_priv;
+	struct edid *edid;
+	bool has_audio = false;
+	int edp = is_edp(encoder);
+
+	if (edp)
+		cdv_intel_edp_panel_vdd_on(encoder);
+
+	edid = drm_get_edid(connector, &intel_dp->adapter);
+	if (edid) {
+		has_audio = drm_detect_monitor_audio(edid);
+		kfree(edid);
+	}
+	if (edp)
+		cdv_intel_edp_panel_vdd_off(encoder);
+
+	return has_audio;
+}
+
+static int
+cdv_intel_dp_set_property(struct drm_connector *connector,
+		      struct drm_property *property,
+		      uint64_t val)
+{
+	struct drm_psb_private *dev_priv = connector->dev->dev_private;
+	struct psb_intel_encoder *encoder = psb_intel_attached_encoder(connector);
+	struct cdv_intel_dp *intel_dp = encoder->dev_priv;
+	int ret;
+
+	ret = drm_connector_property_set_value(connector, property, val);
+	if (ret)
+		return ret;
+
+	if (property == dev_priv->force_audio_property) {
+		int i = val;
+		bool has_audio;
+
+		if (i == intel_dp->force_audio)
+			return 0;
+
+		intel_dp->force_audio = i;
+
+		if (i == 0)
+			has_audio = cdv_intel_dp_detect_audio(connector);
+		else
+			has_audio = i > 0;
+
+		if (has_audio == intel_dp->has_audio)
+			return 0;
+
+		intel_dp->has_audio = has_audio;
+		goto done;
+	}
+
+	if (property == dev_priv->broadcast_rgb_property) {
+		if (val == !!intel_dp->color_range)
+			return 0;
+
+		intel_dp->color_range = val ? DP_COLOR_RANGE_16_235 : 0;
+		goto done;
+	}
+
+	return -EINVAL;
+
+done:
+	if (encoder->base.crtc) {
+		struct drm_crtc *crtc = encoder->base.crtc;
+		drm_crtc_helper_set_mode(crtc, &crtc->mode,
+					 crtc->x, crtc->y,
+					 crtc->fb);
+	}
+
+	return 0;
+}
+
+static void
+cdv_intel_dp_destroy(struct drm_connector *connector)
+{
+	struct psb_intel_encoder *psb_intel_encoder =
+					psb_intel_attached_encoder(connector);
+	struct cdv_intel_dp *intel_dp = psb_intel_encoder->dev_priv;
+
+	if (is_edp(psb_intel_encoder)) {
+	/*	cdv_intel_panel_destroy_backlight(connector->dev); */
+		if (intel_dp->panel_fixed_mode) {
+			kfree(intel_dp->panel_fixed_mode);
+			intel_dp->panel_fixed_mode = NULL;
+		}
+	}
+	i2c_del_adapter(&intel_dp->adapter);
+	drm_sysfs_connector_remove(connector);
+	drm_connector_cleanup(connector);
+	kfree(connector);
+}
+
+static void cdv_intel_dp_encoder_destroy(struct drm_encoder *encoder)
+{
+	drm_encoder_cleanup(encoder);
+}
+
+static const struct drm_encoder_helper_funcs cdv_intel_dp_helper_funcs = {
+	.dpms = cdv_intel_dp_dpms,
+	.mode_fixup = cdv_intel_dp_mode_fixup,
+	.prepare = cdv_intel_dp_prepare,
+	.mode_set = cdv_intel_dp_mode_set,
+	.commit = cdv_intel_dp_commit,
+};
+
+static const struct drm_connector_funcs cdv_intel_dp_connector_funcs = {
+	.dpms = drm_helper_connector_dpms,
+	.detect = cdv_intel_dp_detect,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.set_property = cdv_intel_dp_set_property,
+	.destroy = cdv_intel_dp_destroy,
+};
+
+static const struct drm_connector_helper_funcs cdv_intel_dp_connector_helper_funcs = {
+	.get_modes = cdv_intel_dp_get_modes,
+	.mode_valid = cdv_intel_dp_mode_valid,
+	.best_encoder = psb_intel_best_encoder,
+};
+
+static const struct drm_encoder_funcs cdv_intel_dp_enc_funcs = {
+	.destroy = cdv_intel_dp_encoder_destroy,
+};
+
+
+static void cdv_intel_dp_add_properties(struct drm_connector *connector)
+{
+	cdv_intel_attach_force_audio_property(connector);
+	cdv_intel_attach_broadcast_rgb_property(connector);
+}
+
+/* check the VBT to see whether the eDP is on DP-D port */
+static bool cdv_intel_dpc_is_edp(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct child_device_config *p_child;
+	int i;
+
+	if (!dev_priv->child_dev_num)
+		return false;
+
+	for (i = 0; i < dev_priv->child_dev_num; i++) {
+		p_child = dev_priv->child_dev + i;
+
+		if (p_child->dvo_port == PORT_IDPC &&
+		    p_child->device_type == DEVICE_TYPE_eDP)
+			return true;
+	}
+	return false;
+}
+
+/* Cedarview display clock gating
+
+   We need this disable dot get correct behaviour while enabling
+   DP/eDP. TODO - investigate if we can turn it back to normality
+   after enabling */
+static void cdv_disable_intel_clock_gating(struct drm_device *dev)
+{
+	u32 reg_value;
+	reg_value = REG_READ(DSPCLK_GATE_D);
+
+	reg_value |= (DPUNIT_PIPEB_GATE_DISABLE |
+			DPUNIT_PIPEA_GATE_DISABLE |
+			DPCUNIT_CLOCK_GATE_DISABLE |
+			DPLSUNIT_CLOCK_GATE_DISABLE |
+			DPOUNIT_CLOCK_GATE_DISABLE |
+		 	DPIOUNIT_CLOCK_GATE_DISABLE);	
+
+	REG_WRITE(DSPCLK_GATE_D, reg_value);
+
+	udelay(500);		
+}
+
+void
+cdv_intel_dp_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev, int output_reg)
+{
+	struct psb_intel_encoder *psb_intel_encoder;
+	struct psb_intel_connector *psb_intel_connector;
+	struct drm_connector *connector;
+	struct drm_encoder *encoder;
+	struct cdv_intel_dp *intel_dp;
+	const char *name = NULL;
+	int type = DRM_MODE_CONNECTOR_DisplayPort;
+
+	psb_intel_encoder = kzalloc(sizeof(struct psb_intel_encoder), GFP_KERNEL);
+	if (!psb_intel_encoder)
+		return;
+        psb_intel_connector = kzalloc(sizeof(struct psb_intel_connector), GFP_KERNEL);
+        if (!psb_intel_connector)
+                goto err_connector;
+	intel_dp = kzalloc(sizeof(struct cdv_intel_dp), GFP_KERNEL);
+	if (!intel_dp)
+	        goto err_priv;
+
+	if ((output_reg == DP_C) && cdv_intel_dpc_is_edp(dev))
+		type = DRM_MODE_CONNECTOR_eDP;
+
+	connector = &psb_intel_connector->base;
+	encoder = &psb_intel_encoder->base;
+
+	drm_connector_init(dev, connector, &cdv_intel_dp_connector_funcs, type);
+	drm_encoder_init(dev, encoder, &cdv_intel_dp_enc_funcs, DRM_MODE_ENCODER_TMDS);
+
+	psb_intel_connector_attach_encoder(psb_intel_connector, psb_intel_encoder);
+
+	if (type == DRM_MODE_CONNECTOR_DisplayPort)
+        	psb_intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
+        else
+		psb_intel_encoder->type = INTEL_OUTPUT_EDP;
+
+
+	psb_intel_encoder->dev_priv=intel_dp;
+	intel_dp->encoder = psb_intel_encoder;
+	intel_dp->output_reg = output_reg;
+	
+	drm_encoder_helper_add(encoder, &cdv_intel_dp_helper_funcs);
+	drm_connector_helper_add(connector, &cdv_intel_dp_connector_helper_funcs);
+
+	connector->polled = DRM_CONNECTOR_POLL_HPD;
+	connector->interlace_allowed = false;
+	connector->doublescan_allowed = false;
+
+	drm_sysfs_connector_add(connector);
+
+	/* Set up the DDC bus. */
+	switch (output_reg) {
+		case DP_B:
+			name = "DPDDC-B";
+			psb_intel_encoder->ddi_select = (DP_MASK | DDI0_SELECT);
+			break;
+		case DP_C:
+			name = "DPDDC-C";
+			psb_intel_encoder->ddi_select = (DP_MASK | DDI1_SELECT);
+			break;
+	}
+
+	cdv_disable_intel_clock_gating(dev);
+
+	cdv_intel_dp_i2c_init(psb_intel_connector, psb_intel_encoder, name);
+        /* FIXME:fail check */
+	cdv_intel_dp_add_properties(connector);
+
+	if (is_edp(psb_intel_encoder)) {
+		int ret;
+		struct edp_power_seq cur;
+                u32 pp_on, pp_off, pp_div;
+		u32 pwm_ctrl;
+
+		pp_on = REG_READ(PP_CONTROL);
+		pp_on &= ~PANEL_UNLOCK_MASK;
+	        pp_on |= PANEL_UNLOCK_REGS;
+		
+		REG_WRITE(PP_CONTROL, pp_on);
+
+		pwm_ctrl = REG_READ(BLC_PWM_CTL2);
+		pwm_ctrl |= PWM_PIPE_B;
+		REG_WRITE(BLC_PWM_CTL2, pwm_ctrl);
+
+                pp_on = REG_READ(PP_ON_DELAYS);
+                pp_off = REG_READ(PP_OFF_DELAYS);
+                pp_div = REG_READ(PP_DIVISOR);
+	
+		/* Pull timing values out of registers */
+                cur.t1_t3 = (pp_on & PANEL_POWER_UP_DELAY_MASK) >>
+                        PANEL_POWER_UP_DELAY_SHIFT;
+
+                cur.t8 = (pp_on & PANEL_LIGHT_ON_DELAY_MASK) >>
+                        PANEL_LIGHT_ON_DELAY_SHIFT;
+
+                cur.t9 = (pp_off & PANEL_LIGHT_OFF_DELAY_MASK) >>
+                        PANEL_LIGHT_OFF_DELAY_SHIFT;
+
+                cur.t10 = (pp_off & PANEL_POWER_DOWN_DELAY_MASK) >>
+                        PANEL_POWER_DOWN_DELAY_SHIFT;
+
+                cur.t11_t12 = ((pp_div & PANEL_POWER_CYCLE_DELAY_MASK) >>
+                               PANEL_POWER_CYCLE_DELAY_SHIFT);
+
+                DRM_DEBUG_KMS("cur t1_t3 %d t8 %d t9 %d t10 %d t11_t12 %d\n",
+                              cur.t1_t3, cur.t8, cur.t9, cur.t10, cur.t11_t12);
+
+
+		intel_dp->panel_power_up_delay = cur.t1_t3 / 10;
+                intel_dp->backlight_on_delay = cur.t8 / 10;
+                intel_dp->backlight_off_delay = cur.t9 / 10;
+                intel_dp->panel_power_down_delay = cur.t10 / 10;
+                intel_dp->panel_power_cycle_delay = (cur.t11_t12 - 1) * 100;
+
+                DRM_DEBUG_KMS("panel power up delay %d, power down delay %d, power cycle delay %d\n",
+                              intel_dp->panel_power_up_delay, intel_dp->panel_power_down_delay,
+                              intel_dp->panel_power_cycle_delay);
+
+                DRM_DEBUG_KMS("backlight on delay %d, off delay %d\n",
+                              intel_dp->backlight_on_delay, intel_dp->backlight_off_delay);
+
+
+		cdv_intel_edp_panel_vdd_on(psb_intel_encoder);
+		ret = cdv_intel_dp_aux_native_read(psb_intel_encoder, DP_DPCD_REV,
+					       intel_dp->dpcd,
+					       sizeof(intel_dp->dpcd));
+		cdv_intel_edp_panel_vdd_off(psb_intel_encoder);
+		if (ret == 0) {
+			/* if this fails, presume the device is a ghost */
+			DRM_INFO("failed to retrieve link info, disabling eDP\n");
+			cdv_intel_dp_encoder_destroy(encoder);
+			cdv_intel_dp_destroy(connector);
+			goto err_priv;
+		} else {
+        		DRM_DEBUG_KMS("DPCD: Rev=%x LN_Rate=%x LN_CNT=%x LN_DOWNSP=%x\n",
+				intel_dp->dpcd[0], intel_dp->dpcd[1], 
+				intel_dp->dpcd[2], intel_dp->dpcd[3]);
+			
+		}
+		/* The CDV reference driver moves pnale backlight setup into the displays that
+		   have a backlight: this is a good idea and one we should probably adopt, however
+		   we need to migrate all the drivers before we can do that */
+                /*cdv_intel_panel_setup_backlight(dev); */
+	}
+	return;
+
+err_priv:
+	kfree(psb_intel_connector);
+err_connector:
+	kfree(psb_intel_encoder);
+}
diff --git a/drivers/gpu/drm/gma500/cdv_intel_hdmi.c b/drivers/gpu/drm/gma500/cdv_intel_hdmi.c
index a86f87b..7272a46 100644
--- a/drivers/gpu/drm/gma500/cdv_intel_hdmi.c
+++ b/drivers/gpu/drm/gma500/cdv_intel_hdmi.c
@@ -139,8 +139,6 @@ static enum drm_connector_status cdv_hdmi_detect(
 {
 	struct psb_intel_encoder *psb_intel_encoder =
 					psb_intel_attached_encoder(connector);
-	struct psb_intel_connector *psb_intel_connector =
-					to_psb_intel_connector(connector);
 	struct mid_intel_hdmi_priv *hdmi_priv = psb_intel_encoder->dev_priv;
 	struct edid *edid = NULL;
 	enum drm_connector_status status = connector_status_disconnected;
@@ -157,8 +155,6 @@ static enum drm_connector_status cdv_hdmi_detect(
 			hdmi_priv->has_hdmi_audio =
 						drm_detect_monitor_audio(edid);
 		}
-
-		psb_intel_connector->base.display_info.raw_edid = NULL;
 		kfree(edid);
 	}
 	return status;
@@ -352,9 +348,11 @@ void cdv_hdmi_init(struct drm_device *dev,
 	switch (reg) {
 	case SDVOB:
 		ddc_bus = GPIOE;
+		psb_intel_encoder->ddi_select = DDI0_SELECT;
 		break;
 	case SDVOC:
 		ddc_bus = GPIOD;
+		psb_intel_encoder->ddi_select = DDI1_SELECT;
 		break;
 	default:
 		DRM_ERROR("unknown reg 0x%x for HDMI\n", reg);
diff --git a/drivers/gpu/drm/gma500/cdv_intel_lvds.c b/drivers/gpu/drm/gma500/cdv_intel_lvds.c
index c7f9468..b362dd3 100644
--- a/drivers/gpu/drm/gma500/cdv_intel_lvds.c
+++ b/drivers/gpu/drm/gma500/cdv_intel_lvds.c
@@ -506,16 +506,8 @@ static int cdv_intel_lvds_set_property(struct drm_connector *connector,
 							property,
 							value))
 			return -1;
-		else {
-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
-			struct drm_psb_private *dev_priv =
-						encoder->dev->dev_private;
-			struct backlight_device *bd =
-						dev_priv->backlight_device;
-			bd->props.brightness = value;
-			backlight_update_status(bd);
-#endif
-		}
+		else
+                        gma_backlight_set(encoder->dev, value);
 	} else if (!strcmp(property->name, "DPMS") && encoder) {
 		struct drm_encoder_helper_funcs *helpers =
 					encoder->helper_private;
diff --git a/drivers/gpu/drm/gma500/framebuffer.c b/drivers/gpu/drm/gma500/framebuffer.c
index 5732b57..afded54 100644
--- a/drivers/gpu/drm/gma500/framebuffer.c
+++ b/drivers/gpu/drm/gma500/framebuffer.c
@@ -178,8 +178,7 @@ static int psbfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
 	 */
 	vma->vm_ops = &psbfb_vm_ops;
 	vma->vm_private_data = (void *)psbfb;
-	vma->vm_flags |= VM_RESERVED | VM_IO |
-					VM_MIXEDMAP | VM_DONTEXPAND;
+	vma->vm_flags |= VM_IO | VM_MIXEDMAP | VM_DONTEXPAND | VM_DONTDUMP;
 	return 0;
 }
 
@@ -764,6 +763,13 @@ static void psb_setup_outputs(struct drm_device *dev)
 		        crtc_mask = dev_priv->ops->hdmi_mask;
 			clone_mask = (1 << INTEL_OUTPUT_HDMI);
 			break;
+		case INTEL_OUTPUT_DISPLAYPORT:
+			crtc_mask = (1 << 0) | (1 << 1);
+			clone_mask = (1 << INTEL_OUTPUT_DISPLAYPORT);
+			break;
+		case INTEL_OUTPUT_EDP:
+			crtc_mask = (1 << 1);
+			clone_mask = (1 << INTEL_OUTPUT_EDP);
 		}
 		encoder->possible_crtcs = crtc_mask;
 		encoder->possible_clones =
diff --git a/drivers/gpu/drm/gma500/gem.c b/drivers/gpu/drm/gma500/gem.c
index fc7d144..df20546 100644
--- a/drivers/gpu/drm/gma500/gem.c
+++ b/drivers/gpu/drm/gma500/gem.c
@@ -36,7 +36,12 @@ int psb_gem_init_object(struct drm_gem_object *obj)
 void psb_gem_free_object(struct drm_gem_object *obj)
 {
 	struct gtt_range *gtt = container_of(obj, struct gtt_range, gem);
-	drm_gem_object_release_wrap(obj);
+
+	/* Remove the list map if one is present */
+	if (obj->map_list.map)
+		drm_gem_free_mmap_offset(obj);
+	drm_gem_object_release(obj);
+
 	/* This must occur last as it frees up the memory of the GEM object */
 	psb_gtt_free_range(obj->dev, gtt);
 }
@@ -77,7 +82,7 @@ int psb_gem_dumb_map_gtt(struct drm_file *file, struct drm_device *dev,
 
 	/* Make it mmapable */
 	if (!obj->map_list.map) {
-		ret = gem_create_mmap_offset(obj);
+		ret = drm_gem_create_mmap_offset(obj);
 		if (ret)
 			goto out;
 	}
diff --git a/drivers/gpu/drm/gma500/gem_glue.c b/drivers/gpu/drm/gma500/gem_glue.c
deleted file mode 100644
index 3c17634..0000000
--- a/drivers/gpu/drm/gma500/gem_glue.c
+++ /dev/null
@@ -1,90 +0,0 @@
-/**************************************************************************
- * Copyright (c) 2011, Intel Corporation.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- **************************************************************************/
-
-#include <drm/drmP.h>
-#include <drm/drm.h>
-#include "gem_glue.h"
-
-void drm_gem_object_release_wrap(struct drm_gem_object *obj)
-{
-	/* Remove the list map if one is present */
-	if (obj->map_list.map) {
-		struct drm_gem_mm *mm = obj->dev->mm_private;
-		struct drm_map_list *list = &obj->map_list;
-		drm_ht_remove_item(&mm->offset_hash, &list->hash);
-		drm_mm_put_block(list->file_offset_node);
-		kfree(list->map);
-		list->map = NULL;
-	}
-	drm_gem_object_release(obj);
-}
-
-/**
- *	gem_create_mmap_offset		-	invent an mmap offset
- *	@obj: our object
- *
- *	Standard implementation of offset generation for mmap as is
- *	duplicated in several drivers. This belongs in GEM.
- */
-int gem_create_mmap_offset(struct drm_gem_object *obj)
-{
-	struct drm_device *dev = obj->dev;
-	struct drm_gem_mm *mm = dev->mm_private;
-	struct drm_map_list *list;
-	struct drm_local_map *map;
-	int ret;
-
-	list = &obj->map_list;
-	list->map = kzalloc(sizeof(struct drm_map_list), GFP_KERNEL);
-	if (list->map == NULL)
-		return -ENOMEM;
-	map = list->map;
-	map->type = _DRM_GEM;
-	map->size = obj->size;
-	map->handle = obj;
-
-	list->file_offset_node = drm_mm_search_free(&mm->offset_manager,
-					obj->size / PAGE_SIZE, 0, 0);
-	if (!list->file_offset_node) {
-		dev_err(dev->dev, "failed to allocate offset for bo %d\n",
-								obj->name);
-		ret = -ENOSPC;
-		goto free_it;
-	}
-	list->file_offset_node = drm_mm_get_block(list->file_offset_node,
-					obj->size / PAGE_SIZE, 0);
-	if (!list->file_offset_node) {
-		ret = -ENOMEM;
-		goto free_it;
-	}
-	list->hash.key = list->file_offset_node->start;
-	ret = drm_ht_insert_item(&mm->offset_hash, &list->hash);
-	if (ret) {
-		dev_err(dev->dev, "failed to add to map hash\n");
-		goto free_mm;
-	}
-	return 0;
-
-free_mm:
-	drm_mm_put_block(list->file_offset_node);
-free_it:
-	kfree(list->map);
-	list->map = NULL;
-	return ret;
-}
diff --git a/drivers/gpu/drm/gma500/gem_glue.h b/drivers/gpu/drm/gma500/gem_glue.h
deleted file mode 100644
index ce5ce30..0000000
--- a/drivers/gpu/drm/gma500/gem_glue.h
+++ /dev/null
@@ -1,2 +0,0 @@
-extern void drm_gem_object_release_wrap(struct drm_gem_object *obj);
-extern int gem_create_mmap_offset(struct drm_gem_object *obj);
diff --git a/drivers/gpu/drm/gma500/intel_bios.c b/drivers/gpu/drm/gma500/intel_bios.c
index 8d7caf0..4fb79cf 100644
--- a/drivers/gpu/drm/gma500/intel_bios.c
+++ b/drivers/gpu/drm/gma500/intel_bios.c
@@ -54,6 +54,98 @@ static void *find_section(struct bdb_header *bdb, int section_id)
 	return NULL;
 }
 
+static void
+parse_edp(struct drm_psb_private *dev_priv, struct bdb_header *bdb)
+{
+	struct bdb_edp *edp;
+	struct edp_power_seq *edp_pps;
+	struct edp_link_params *edp_link_params;
+	uint8_t	panel_type;
+
+	edp = find_section(bdb, BDB_EDP);
+	
+	dev_priv->edp.bpp = 18;
+	if (!edp) {
+		if (dev_priv->edp.support) {
+			DRM_DEBUG_KMS("No eDP BDB found but eDP panel supported, assume %dbpp panel color depth.\n",
+				      dev_priv->edp.bpp);
+		}
+		return;
+	}
+
+	panel_type = dev_priv->panel_type;
+	switch ((edp->color_depth >> (panel_type * 2)) & 3) {
+	case EDP_18BPP:
+		dev_priv->edp.bpp = 18;
+		break;
+	case EDP_24BPP:
+		dev_priv->edp.bpp = 24;
+		break;
+	case EDP_30BPP:
+		dev_priv->edp.bpp = 30;
+		break;
+	}
+
+	/* Get the eDP sequencing and link info */
+	edp_pps = &edp->power_seqs[panel_type];
+	edp_link_params = &edp->link_params[panel_type];
+
+	dev_priv->edp.pps = *edp_pps;
+
+	DRM_DEBUG_KMS("EDP timing in vbt t1_t3 %d t8 %d t9 %d t10 %d t11_t12 %d\n",
+				dev_priv->edp.pps.t1_t3, dev_priv->edp.pps.t8, 
+				dev_priv->edp.pps.t9, dev_priv->edp.pps.t10,
+				dev_priv->edp.pps.t11_t12);
+
+	dev_priv->edp.rate = edp_link_params->rate ? DP_LINK_BW_2_7 :
+		DP_LINK_BW_1_62;
+	switch (edp_link_params->lanes) {
+	case 0:
+		dev_priv->edp.lanes = 1;
+		break;
+	case 1:
+		dev_priv->edp.lanes = 2;
+		break;
+	case 3:
+	default:
+		dev_priv->edp.lanes = 4;
+		break;
+	}
+	DRM_DEBUG_KMS("VBT reports EDP: Lane_count %d, Lane_rate %d, Bpp %d\n",
+			dev_priv->edp.lanes, dev_priv->edp.rate, dev_priv->edp.bpp);
+
+	switch (edp_link_params->preemphasis) {
+	case 0:
+		dev_priv->edp.preemphasis = DP_TRAIN_PRE_EMPHASIS_0;
+		break;
+	case 1:
+		dev_priv->edp.preemphasis = DP_TRAIN_PRE_EMPHASIS_3_5;
+		break;
+	case 2:
+		dev_priv->edp.preemphasis = DP_TRAIN_PRE_EMPHASIS_6;
+		break;
+	case 3:
+		dev_priv->edp.preemphasis = DP_TRAIN_PRE_EMPHASIS_9_5;
+		break;
+	}
+	switch (edp_link_params->vswing) {
+	case 0:
+		dev_priv->edp.vswing = DP_TRAIN_VOLTAGE_SWING_400;
+		break;
+	case 1:
+		dev_priv->edp.vswing = DP_TRAIN_VOLTAGE_SWING_600;
+		break;
+	case 2:
+		dev_priv->edp.vswing = DP_TRAIN_VOLTAGE_SWING_800;
+		break;
+	case 3:
+		dev_priv->edp.vswing = DP_TRAIN_VOLTAGE_SWING_1200;
+		break;
+	}
+	DRM_DEBUG_KMS("VBT reports EDP: VSwing  %d, Preemph %d\n",
+			dev_priv->edp.vswing, dev_priv->edp.preemphasis);
+}
+
 static u16
 get_blocksize(void *p)
 {
@@ -154,6 +246,8 @@ static void parse_lfp_panel_data(struct drm_psb_private *dev_priv,
 		return;
 
 	dev_priv->lvds_dither = lvds_options->pixel_dither;
+	dev_priv->panel_type = lvds_options->panel_type;
+
 	if (lvds_options->panel_type == 0xff)
 		return;
 
@@ -340,6 +434,9 @@ parse_driver_features(struct drm_psb_private *dev_priv,
 	if (!driver)
 		return;
 
+	if (driver->lvds_config == BDB_DRIVER_FEATURE_EDP)
+		dev_priv->edp.support = 1;
+
 	/* This bit means to use 96Mhz for DPLL_A or not */
 	if (driver->primary_lfp_id)
 		dev_priv->dplla_96mhz = true;
@@ -437,6 +534,9 @@ int psb_intel_init_bios(struct drm_device *dev)
 	size_t size;
 	int i;
 
+
+	dev_priv->panel_type = 0xff;
+
 	/* XXX Should this validation be moved to intel_opregion.c? */
 	if (dev_priv->opregion.vbt) {
 		struct vbt_header *vbt = dev_priv->opregion.vbt;
@@ -477,6 +577,7 @@ int psb_intel_init_bios(struct drm_device *dev)
 	parse_sdvo_device_mapping(dev_priv, bdb);
 	parse_device_mapping(dev_priv, bdb);
 	parse_backlight_data(dev_priv, bdb);
+	parse_edp(dev_priv, bdb);
 
 	if (bios)
 		pci_unmap_rom(pdev, bios);
diff --git a/drivers/gpu/drm/gma500/intel_bios.h b/drivers/gpu/drm/gma500/intel_bios.h
index 2e95523..c6267c9 100644
--- a/drivers/gpu/drm/gma500/intel_bios.h
+++ b/drivers/gpu/drm/gma500/intel_bios.h
@@ -23,6 +23,7 @@
 #define _I830_BIOS_H_
 
 #include <drm/drmP.h>
+#include <drm/drm_dp_helper.h>
 
 struct vbt_header {
 	u8 signature[20];		/**< Always starts with 'VBT$' */
@@ -93,6 +94,7 @@ struct vbios_data {
 #define BDB_SDVO_LVDS_PNP_IDS	 24
 #define BDB_SDVO_LVDS_POWER_SEQ	 25
 #define BDB_TV_OPTIONS		 26
+#define BDB_EDP			 27
 #define BDB_LVDS_OPTIONS	 40
 #define BDB_LVDS_LFP_DATA_PTRS	 41
 #define BDB_LVDS_LFP_DATA	 42
@@ -391,6 +393,11 @@ struct bdb_sdvo_lvds_options {
 	u8 panel_misc_bits_4;
 } __attribute__((packed));
 
+#define BDB_DRIVER_FEATURE_NO_LVDS		0
+#define BDB_DRIVER_FEATURE_INT_LVDS		1
+#define BDB_DRIVER_FEATURE_SDVO_LVDS		2
+#define BDB_DRIVER_FEATURE_EDP			3
+
 struct bdb_driver_features {
 	u8 boot_dev_algorithm:1;
 	u8 block_display_switch:1;
@@ -431,6 +438,45 @@ struct bdb_driver_features {
 	u8 custom_vbt_version;
 } __attribute__((packed));
 
+#define EDP_18BPP	0
+#define EDP_24BPP	1
+#define EDP_30BPP	2
+#define EDP_RATE_1_62	0
+#define EDP_RATE_2_7	1
+#define EDP_LANE_1	0
+#define EDP_LANE_2	1
+#define EDP_LANE_4	3
+#define EDP_PREEMPHASIS_NONE	0
+#define EDP_PREEMPHASIS_3_5dB	1
+#define EDP_PREEMPHASIS_6dB	2
+#define EDP_PREEMPHASIS_9_5dB	3
+#define EDP_VSWING_0_4V		0
+#define EDP_VSWING_0_6V		1
+#define EDP_VSWING_0_8V		2
+#define EDP_VSWING_1_2V		3
+
+struct edp_power_seq {
+	u16 t1_t3;
+	u16 t8;
+	u16 t9;
+	u16 t10;
+	u16 t11_t12;
+} __attribute__ ((packed));
+
+struct edp_link_params {
+	u8 rate:4;
+	u8 lanes:4;
+	u8 preemphasis:4;
+	u8 vswing:4;
+} __attribute__ ((packed));
+
+struct bdb_edp {
+	struct edp_power_seq power_seqs[16];
+	u32 color_depth;
+	u32 sdrrs_msa_timing_delay;
+	struct edp_link_params link_params[16];
+} __attribute__ ((packed));
+
 extern int psb_intel_init_bios(struct drm_device *dev);
 extern void psb_intel_destroy_bios(struct drm_device *dev);
 
diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_output.c b/drivers/gpu/drm/gma500/mdfld_dsi_output.c
index 5675d93..32dba2a 100644
--- a/drivers/gpu/drm/gma500/mdfld_dsi_output.c
+++ b/drivers/gpu/drm/gma500/mdfld_dsi_output.c
@@ -299,17 +299,8 @@ static int mdfld_dsi_connector_set_property(struct drm_connector *connector,
 		if (drm_connector_property_set_value(connector, property,
 									value))
 			goto set_prop_error;
-		else {
-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
-			struct backlight_device *psb_bd;
-
-			psb_bd = mdfld_get_backlight_device();
-			if (psb_bd) {
-				psb_bd->props.brightness = value;
-				mdfld_set_brightness(psb_bd);
-			}
-#endif
-		}
+		else
+			gma_backlight_set(encoder->dev, value);
 	}
 set_prop_done:
 	return 0;
diff --git a/drivers/gpu/drm/gma500/mid_bios.c b/drivers/gpu/drm/gma500/mid_bios.c
index b2a790b..850cd3f 100644
--- a/drivers/gpu/drm/gma500/mid_bios.c
+++ b/drivers/gpu/drm/gma500/mid_bios.c
@@ -118,20 +118,20 @@ static void mid_get_pci_revID(struct drm_psb_private *dev_priv)
 					dev_priv->platform_rev_id);
 }
 
-struct vbt_header {
+struct mid_vbt_header {
 	u32 signature;
 	u8 revision;
 } __packed;
 
 /* The same for r0 and r1 */
 struct vbt_r0 {
-	struct vbt_header vbt_header;
+	struct mid_vbt_header vbt_header;
 	u8 size;
 	u8 checksum;
 } __packed;
 
 struct vbt_r10 {
-	struct vbt_header vbt_header;
+	struct mid_vbt_header vbt_header;
 	u8 checksum;
 	u16 size;
 	u8 panel_count;
@@ -281,7 +281,7 @@ static void mid_get_vbt_data(struct drm_psb_private *dev_priv)
 	struct drm_device *dev = dev_priv->dev;
 	u32 addr;
 	u8 __iomem *vbt_virtual;
-	struct vbt_header vbt_header;
+	struct mid_vbt_header vbt_header;
 	struct pci_dev *pci_gfx_root = pci_get_bus_and_slot(0, PCI_DEVFN(2, 0));
 	int ret = -1;
 
diff --git a/drivers/gpu/drm/gma500/oaktrail_hdmi.c b/drivers/gpu/drm/gma500/oaktrail_hdmi.c
index 2eb3dc4..69e51e9 100644
--- a/drivers/gpu/drm/gma500/oaktrail_hdmi.c
+++ b/drivers/gpu/drm/gma500/oaktrail_hdmi.c
@@ -252,7 +252,6 @@ static int oaktrail_hdmi_get_modes(struct drm_connector *connector)
 	if (edid) {
 		drm_mode_connector_update_edid_property(connector, edid);
 		ret = drm_add_edid_modes(connector, edid);
-		connector->display_info.raw_edid = NULL;
 	}
 
 	/*
diff --git a/drivers/gpu/drm/gma500/opregion.c b/drivers/gpu/drm/gma500/opregion.c
index c430bd4..ad0d6de 100644
--- a/drivers/gpu/drm/gma500/opregion.c
+++ b/drivers/gpu/drm/gma500/opregion.c
@@ -166,8 +166,7 @@ static u32 asle_set_backlight(struct drm_device *dev, u32 bclp)
 
 	if (config_enabled(CONFIG_BACKLIGHT_CLASS_DEVICE)) {
 		int max = bd->props.max_brightness;
-		bd->props.brightness = bclp * max / 255;
-		backlight_update_status(bd);
+		gma_backlight_set(dev, bclp * max / 255);
 	}
 
 	asle->cblv = (bclp * 0x64) / 0xff | ASLE_CBLV_VALID;
diff --git a/drivers/gpu/drm/gma500/psb_device.c b/drivers/gpu/drm/gma500/psb_device.c
index 5971bc8..f1432f0 100644
--- a/drivers/gpu/drm/gma500/psb_device.c
+++ b/drivers/gpu/drm/gma500/psb_device.c
@@ -290,6 +290,7 @@ static void psb_get_core_freq(struct drm_device *dev)
 	case 6:
 	case 7:
 		dev_priv->core_freq = 266;
+		break;
 	default:
 		dev_priv->core_freq = 0;
 	}
diff --git a/drivers/gpu/drm/gma500/psb_drv.h b/drivers/gpu/drm/gma500/psb_drv.h
index 1bd115e..223ff5b 100644
--- a/drivers/gpu/drm/gma500/psb_drv.h
+++ b/drivers/gpu/drm/gma500/psb_drv.h
@@ -24,10 +24,10 @@
 
 #include <drm/drmP.h>
 #include "drm_global.h"
-#include "gem_glue.h"
 #include "gma_drm.h"
 #include "psb_reg.h"
 #include "psb_intel_drv.h"
+#include "intel_bios.h"
 #include "gtt.h"
 #include "power.h"
 #include "opregion.h"
@@ -613,6 +613,8 @@ struct drm_psb_private {
 	 */
 	struct backlight_device *backlight_device;
 	struct drm_property *backlight_property;
+	bool backlight_enabled;
+	int backlight_level;
 	uint32_t blc_adj1;
 	uint32_t blc_adj2;
 
@@ -640,6 +642,19 @@ struct drm_psb_private {
 	int mdfld_panel_id;
 
 	bool dplla_96mhz;	/* DPLL data from the VBT */
+
+	struct {
+		int rate;
+		int lanes;
+		int preemphasis;
+		int vswing;
+
+		bool initialized;
+		bool support;
+		int bpp;
+		struct edp_power_seq pps;
+	} edp;
+	uint8_t panel_type;
 };
 
 
@@ -796,6 +811,9 @@ extern int psb_fbdev_init(struct drm_device *dev);
 /* backlight.c */
 int gma_backlight_init(struct drm_device *dev);
 void gma_backlight_exit(struct drm_device *dev);
+void gma_backlight_disable(struct drm_device *dev);
+void gma_backlight_enable(struct drm_device *dev);
+void gma_backlight_set(struct drm_device *dev, int v);
 
 /* oaktrail_crtc.c */
 extern const struct drm_crtc_helper_funcs oaktrail_helper_funcs;
diff --git a/drivers/gpu/drm/gma500/psb_intel_drv.h b/drivers/gpu/drm/gma500/psb_intel_drv.h
index ebe1a28..90f2d11 100644
--- a/drivers/gpu/drm/gma500/psb_intel_drv.h
+++ b/drivers/gpu/drm/gma500/psb_intel_drv.h
@@ -29,10 +29,6 @@
  * Display related stuff
  */
 
-/* store information about an Ixxx DVO */
-/* The i830->i865 use multiple DVOs with multiple i2cs */
-/* the i915, i945 have a single sDVO i2c bus - which is different */
-#define MAX_OUTPUTS 6
 /* maximum connectors per crtcs in the mode set */
 #define INTELFB_CONN_LIMIT 4
 
@@ -69,6 +65,8 @@
 #define INTEL_OUTPUT_HDMI 6
 #define INTEL_OUTPUT_MIPI 7
 #define INTEL_OUTPUT_MIPI2 8
+#define INTEL_OUTPUT_DISPLAYPORT 9
+#define INTEL_OUTPUT_EDP 10
 
 #define INTEL_DVO_CHIP_NONE 0
 #define INTEL_DVO_CHIP_LVDS 1
@@ -133,6 +131,11 @@ struct psb_intel_encoder {
 	void (*hot_plug)(struct psb_intel_encoder *);
 	int crtc_mask;
 	int clone_mask;
+	u32 ddi_select;	/* Channel info */
+#define DDI0_SELECT	0x01
+#define DDI1_SELECT	0x02
+#define DP_MASK		0x8000
+#define DDI_MASK	0x03
 	void *dev_priv; /* For sdvo_priv, lvds_priv, etc... */
 
 	/* FIXME: Either make SDVO and LVDS store it's i2c here or give CDV it's
@@ -190,7 +193,6 @@ struct psb_intel_crtc {
 	u32 mode_flags;
 
 	bool active;
-	bool crtc_enable;
 
 	/* Saved Crtc HW states */
 	struct psb_intel_crtc_state *crtc_state;
@@ -285,4 +287,20 @@ extern void gma_intel_gmbus_set_speed(struct i2c_adapter *adapter, int speed);
 extern void gma_intel_gmbus_force_bit(struct i2c_adapter *adapter, bool force_bit);
 extern void gma_intel_teardown_gmbus(struct drm_device *dev);
 
+/* DP support */
+extern void cdv_intel_dp_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev, int output_reg);
+extern void cdv_intel_dp_set_m_n(struct drm_crtc *crtc,
+					struct drm_display_mode *mode,
+					struct drm_display_mode *adjusted_mode);
+
+extern void psb_intel_attach_force_audio_property(struct drm_connector *connector);
+extern void psb_intel_attach_broadcast_rgb_property(struct drm_connector *connector);
+
+extern int cdv_sb_read(struct drm_device *dev, u32 reg, u32 *val);
+extern int cdv_sb_write(struct drm_device *dev, u32 reg, u32 val);
+extern void cdv_sb_reset(struct drm_device *dev);
+
+extern void cdv_intel_attach_force_audio_property(struct drm_connector *connector);
+extern void cdv_intel_attach_broadcast_rgb_property(struct drm_connector *connector);
+
 #endif				/* __INTEL_DRV_H__ */
diff --git a/drivers/gpu/drm/gma500/psb_intel_lvds.c b/drivers/gpu/drm/gma500/psb_intel_lvds.c
index 37adc9e..2a4c3a9 100644
--- a/drivers/gpu/drm/gma500/psb_intel_lvds.c
+++ b/drivers/gpu/drm/gma500/psb_intel_lvds.c
@@ -630,17 +630,8 @@ int psb_intel_lvds_set_property(struct drm_connector *connector,
 							property,
 							value))
 			goto set_prop_error;
-		else {
-#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
-			struct drm_psb_private *devp =
-						encoder->dev->dev_private;
-			struct backlight_device *bd = devp->backlight_device;
-			if (bd) {
-				bd->props.brightness = value;
-				backlight_update_status(bd);
-			}
-#endif
-		}
+		else
+                        gma_backlight_set(encoder->dev, value);
 	} else if (!strcmp(property->name, "DPMS")) {
 		struct drm_encoder_helper_funcs *hfuncs
 						= encoder->helper_private;
diff --git a/drivers/gpu/drm/gma500/psb_intel_reg.h b/drivers/gpu/drm/gma500/psb_intel_reg.h
index 8e8c8ef..d914719 100644
--- a/drivers/gpu/drm/gma500/psb_intel_reg.h
+++ b/drivers/gpu/drm/gma500/psb_intel_reg.h
@@ -173,15 +173,46 @@
 #define PP_SEQUENCE_ON			(1 << 28)
 #define PP_SEQUENCE_OFF			(2 << 28)
 #define PP_SEQUENCE_MASK		0x30000000
+#define	PP_CYCLE_DELAY_ACTIVE		(1 << 27)
+#define	PP_SEQUENCE_STATE_ON_IDLE	(1 << 3)
+#define	PP_SEQUENCE_STATE_MASK		0x0000000f
+
 #define PP_CONTROL		0x61204
 #define POWER_TARGET_ON			(1 << 0)
-
+#define	PANEL_UNLOCK_REGS		(0xabcd << 16)
+#define	PANEL_UNLOCK_MASK		(0xffff << 16)
+#define	EDP_FORCE_VDD			(1 << 3)
+#define	EDP_BLC_ENABLE			(1 << 2)
+#define	PANEL_POWER_RESET		(1 << 1)
+#define	PANEL_POWER_OFF			(0 << 0)
+#define	PANEL_POWER_ON			(1 << 0)
+
+/* Poulsbo/Oaktrail */
 #define LVDSPP_ON		0x61208
 #define LVDSPP_OFF		0x6120c
 #define PP_CYCLE		0x61210
 
+/* Cedartrail */
 #define PP_ON_DELAYS		0x61208		/* Cedartrail */
+#define PANEL_PORT_SELECT_MASK 		(3 << 30)
+#define PANEL_PORT_SELECT_LVDS 		(0 << 30)
+#define PANEL_PORT_SELECT_EDP		(1 << 30)
+#define PANEL_POWER_UP_DELAY_MASK	(0x1fff0000)
+#define PANEL_POWER_UP_DELAY_SHIFT	16
+#define PANEL_LIGHT_ON_DELAY_MASK	(0x1fff)
+#define PANEL_LIGHT_ON_DELAY_SHIFT	0
+
 #define PP_OFF_DELAYS		0x6120c		/* Cedartrail */
+#define PANEL_POWER_DOWN_DELAY_MASK	(0x1fff0000)
+#define PANEL_POWER_DOWN_DELAY_SHIFT	16
+#define PANEL_LIGHT_OFF_DELAY_MASK	(0x1fff)
+#define PANEL_LIGHT_OFF_DELAY_SHIFT	0
+
+#define PP_DIVISOR		0x61210		/* Cedartrail */
+#define  PP_REFERENCE_DIVIDER_MASK	(0xffffff00)
+#define  PP_REFERENCE_DIVIDER_SHIFT	8
+#define  PANEL_POWER_CYCLE_DELAY_MASK	(0x1f)
+#define  PANEL_POWER_CYCLE_DELAY_SHIFT	0
 
 #define PFIT_CONTROL		0x61230
 #define PFIT_ENABLE			(1 << 31)
@@ -1282,6 +1313,10 @@ No status bits are changed.
 # define VRHUNIT_CLOCK_GATE_DISABLE		(1 << 28) /* Fixed value on CDV */
 # define DPOUNIT_CLOCK_GATE_DISABLE		(1 << 11)
 # define DPIOUNIT_CLOCK_GATE_DISABLE		(1 << 6)
+# define DPUNIT_PIPEB_GATE_DISABLE		(1 << 30)
+# define DPUNIT_PIPEA_GATE_DISABLE		(1 << 25)
+# define DPCUNIT_CLOCK_GATE_DISABLE		(1 << 24)
+# define DPLSUNIT_CLOCK_GATE_DISABLE		(1 << 13)
 
 #define RAMCLK_GATE_D		0x6210
 
@@ -1347,5 +1382,165 @@ No status bits are changed.
 #define LANE_PLL_ENABLE		(0x3 << 20)
 #define LANE_PLL_PIPE(p)	(((p) == 0) ? (1 << 21) : (0 << 21))
 
+#define DP_B				0x64100
+#define DP_C				0x64200
+
+#define   DP_PORT_EN			(1 << 31)
+#define   DP_PIPEB_SELECT		(1 << 30)
+#define   DP_PIPE_MASK			(1 << 30)
+
+/* Link training mode - select a suitable mode for each stage */
+#define   DP_LINK_TRAIN_PAT_1		(0 << 28)
+#define   DP_LINK_TRAIN_PAT_2		(1 << 28)
+#define   DP_LINK_TRAIN_PAT_IDLE	(2 << 28)
+#define   DP_LINK_TRAIN_OFF		(3 << 28)
+#define   DP_LINK_TRAIN_MASK		(3 << 28)
+#define   DP_LINK_TRAIN_SHIFT		28
+
+/* Signal voltages. These are mostly controlled by the other end */
+#define   DP_VOLTAGE_0_4		(0 << 25)
+#define   DP_VOLTAGE_0_6		(1 << 25)
+#define   DP_VOLTAGE_0_8		(2 << 25)
+#define   DP_VOLTAGE_1_2		(3 << 25)
+#define   DP_VOLTAGE_MASK		(7 << 25)
+#define   DP_VOLTAGE_SHIFT		25
+
+/* Signal pre-emphasis levels, like voltages, the other end tells us what
+ * they want
+ */
+#define   DP_PRE_EMPHASIS_0		(0 << 22)
+#define   DP_PRE_EMPHASIS_3_5		(1 << 22)
+#define   DP_PRE_EMPHASIS_6		(2 << 22)
+#define   DP_PRE_EMPHASIS_9_5		(3 << 22)
+#define   DP_PRE_EMPHASIS_MASK		(7 << 22)
+#define   DP_PRE_EMPHASIS_SHIFT		22
+
+/* How many wires to use. I guess 3 was too hard */
+#define   DP_PORT_WIDTH_1		(0 << 19)
+#define   DP_PORT_WIDTH_2		(1 << 19)
+#define   DP_PORT_WIDTH_4		(3 << 19)
+#define   DP_PORT_WIDTH_MASK		(7 << 19)
+
+/* Mystic DPCD version 1.1 special mode */
+#define   DP_ENHANCED_FRAMING		(1 << 18)
+
+/** locked once port is enabled */
+#define   DP_PORT_REVERSAL		(1 << 15)
+
+/** sends the clock on lane 15 of the PEG for debug */
+#define   DP_CLOCK_OUTPUT_ENABLE	(1 << 13)
+
+#define   DP_SCRAMBLING_DISABLE		(1 << 12)
+#define   DP_SCRAMBLING_DISABLE_IRONLAKE	(1 << 7)
+
+/** limit RGB values to avoid confusing TVs */
+#define   DP_COLOR_RANGE_16_235		(1 << 8)
+
+/** Turn on the audio link */
+#define   DP_AUDIO_OUTPUT_ENABLE	(1 << 6)
+
+/** vs and hs sync polarity */
+#define   DP_SYNC_VS_HIGH		(1 << 4)
+#define   DP_SYNC_HS_HIGH		(1 << 3)
+
+/** A fantasy */
+#define   DP_DETECTED			(1 << 2)
+
+/** The aux channel provides a way to talk to the
+ * signal sink for DDC etc. Max packet size supported
+ * is 20 bytes in each direction, hence the 5 fixed
+ * data registers
+ */
+#define DPB_AUX_CH_CTL			0x64110
+#define DPB_AUX_CH_DATA1		0x64114
+#define DPB_AUX_CH_DATA2		0x64118
+#define DPB_AUX_CH_DATA3		0x6411c
+#define DPB_AUX_CH_DATA4		0x64120
+#define DPB_AUX_CH_DATA5		0x64124
+
+#define DPC_AUX_CH_CTL			0x64210
+#define DPC_AUX_CH_DATA1		0x64214
+#define DPC_AUX_CH_DATA2		0x64218
+#define DPC_AUX_CH_DATA3		0x6421c
+#define DPC_AUX_CH_DATA4		0x64220
+#define DPC_AUX_CH_DATA5		0x64224
+
+#define   DP_AUX_CH_CTL_SEND_BUSY	    (1 << 31)
+#define   DP_AUX_CH_CTL_DONE		    (1 << 30)
+#define   DP_AUX_CH_CTL_INTERRUPT	    (1 << 29)
+#define   DP_AUX_CH_CTL_TIME_OUT_ERROR	    (1 << 28)
+#define   DP_AUX_CH_CTL_TIME_OUT_400us	    (0 << 26)
+#define   DP_AUX_CH_CTL_TIME_OUT_600us	    (1 << 26)
+#define   DP_AUX_CH_CTL_TIME_OUT_800us	    (2 << 26)
+#define   DP_AUX_CH_CTL_TIME_OUT_1600us	    (3 << 26)
+#define   DP_AUX_CH_CTL_TIME_OUT_MASK	    (3 << 26)
+#define   DP_AUX_CH_CTL_RECEIVE_ERROR	    (1 << 25)
+#define   DP_AUX_CH_CTL_MESSAGE_SIZE_MASK    (0x1f << 20)
+#define   DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT   20
+#define   DP_AUX_CH_CTL_PRECHARGE_2US_MASK   (0xf << 16)
+#define   DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT  16
+#define   DP_AUX_CH_CTL_AUX_AKSV_SELECT	    (1 << 15)
+#define   DP_AUX_CH_CTL_MANCHESTER_TEST	    (1 << 14)
+#define   DP_AUX_CH_CTL_SYNC_TEST	    (1 << 13)
+#define   DP_AUX_CH_CTL_DEGLITCH_TEST	    (1 << 12)
+#define   DP_AUX_CH_CTL_PRECHARGE_TEST	    (1 << 11)
+#define   DP_AUX_CH_CTL_BIT_CLOCK_2X_MASK    (0x7ff)
+#define   DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT   0
+
+/*
+ * Computing GMCH M and N values for the Display Port link
+ *
+ * GMCH M/N = dot clock * bytes per pixel / ls_clk * # of lanes
+ *
+ * ls_clk (we assume) is the DP link clock (1.62 or 2.7 GHz)
+ *
+ * The GMCH value is used internally
+ *
+ * bytes_per_pixel is the number of bytes coming out of the plane,
+ * which is after the LUTs, so we want the bytes for our color format.
+ * For our current usage, this is always 3, one byte for R, G and B.
+ */
+
+#define _PIPEA_GMCH_DATA_M			0x70050
+#define _PIPEB_GMCH_DATA_M			0x71050
+
+/* Transfer unit size for display port - 1, default is 0x3f (for TU size 64) */
+#define   PIPE_GMCH_DATA_M_TU_SIZE_MASK		(0x3f << 25)
+#define   PIPE_GMCH_DATA_M_TU_SIZE_SHIFT	25
+
+#define   PIPE_GMCH_DATA_M_MASK			(0xffffff)
+
+#define _PIPEA_GMCH_DATA_N			0x70054
+#define _PIPEB_GMCH_DATA_N			0x71054
+#define   PIPE_GMCH_DATA_N_MASK			(0xffffff)
+
+/*
+ * Computing Link M and N values for the Display Port link
+ *
+ * Link M / N = pixel_clock / ls_clk
+ *
+ * (the DP spec calls pixel_clock the 'strm_clk')
+ *
+ * The Link value is transmitted in the Main Stream
+ * Attributes and VB-ID.
+ */
+
+#define _PIPEA_DP_LINK_M				0x70060
+#define _PIPEB_DP_LINK_M				0x71060
+#define   PIPEA_DP_LINK_M_MASK			(0xffffff)
+
+#define _PIPEA_DP_LINK_N				0x70064
+#define _PIPEB_DP_LINK_N				0x71064
+#define   PIPEA_DP_LINK_N_MASK			(0xffffff)
+
+#define PIPE_GMCH_DATA_M(pipe) _PIPE(pipe, _PIPEA_GMCH_DATA_M, _PIPEB_GMCH_DATA_M)
+#define PIPE_GMCH_DATA_N(pipe) _PIPE(pipe, _PIPEA_GMCH_DATA_N, _PIPEB_GMCH_DATA_N)
+#define PIPE_DP_LINK_M(pipe) _PIPE(pipe, _PIPEA_DP_LINK_M, _PIPEB_DP_LINK_M)
+#define PIPE_DP_LINK_N(pipe) _PIPE(pipe, _PIPEA_DP_LINK_N, _PIPEB_DP_LINK_N)
+
+#define   PIPE_BPC_MASK				(7 << 5)
+#define   PIPE_8BPC				(0 << 5)
+#define   PIPE_10BPC				(1 << 5)
+#define   PIPE_6BPC				(2 << 5)
 
 #endif
diff --git a/drivers/gpu/drm/gma500/psb_intel_sdvo.c b/drivers/gpu/drm/gma500/psb_intel_sdvo.c
index 0466c7b..d35f93b 100644
--- a/drivers/gpu/drm/gma500/psb_intel_sdvo.c
+++ b/drivers/gpu/drm/gma500/psb_intel_sdvo.c
@@ -1292,7 +1292,6 @@ psb_intel_sdvo_get_analog_edid(struct drm_connector *connector)
 
 	return drm_get_edid(connector,
 			    &dev_priv->gmbus[dev_priv->crt_ddc_pin].adapter);
-	return NULL;
 }
 
 static enum drm_connector_status
@@ -1343,7 +1342,6 @@ psb_intel_sdvo_hdmi_sink_detect(struct drm_connector *connector)
 			}
 		} else
 			status = connector_status_disconnected;
-		connector->display_info.raw_edid = NULL;
 		kfree(edid);
 	}
 
@@ -1404,7 +1402,6 @@ psb_intel_sdvo_detect(struct drm_connector *connector, bool force)
 				ret = connector_status_disconnected;
 			else
 				ret = connector_status_connected;
-			connector->display_info.raw_edid = NULL;
 			kfree(edid);
 		} else
 			ret = connector_status_connected;
@@ -1453,7 +1450,6 @@ static void psb_intel_sdvo_get_ddc_modes(struct drm_connector *connector)
 			drm_add_edid_modes(connector, edid);
 		}
 
-		connector->display_info.raw_edid = NULL;
 		kfree(edid);
 	}
 }
diff --git a/drivers/gpu/drm/i2c/ch7006_drv.c b/drivers/gpu/drm/i2c/ch7006_drv.c
index 36d9522..599099f 100644
--- a/drivers/gpu/drm/i2c/ch7006_drv.c
+++ b/drivers/gpu/drm/i2c/ch7006_drv.c
@@ -427,15 +427,10 @@ static int ch7006_remove(struct i2c_client *client)
 	return 0;
 }
 
-static int ch7006_suspend(struct i2c_client *client, pm_message_t mesg)
+static int ch7006_resume(struct device *dev)
 {
-	ch7006_dbg(client, "\n");
-
-	return 0;
-}
+	struct i2c_client *client = to_i2c_client(dev);
 
-static int ch7006_resume(struct i2c_client *client)
-{
 	ch7006_dbg(client, "\n");
 
 	ch7006_write(client, 0x3d, 0x0);
@@ -499,15 +494,18 @@ static struct i2c_device_id ch7006_ids[] = {
 };
 MODULE_DEVICE_TABLE(i2c, ch7006_ids);
 
+static const struct dev_pm_ops ch7006_pm_ops = {
+	.resume = ch7006_resume,
+};
+
 static struct drm_i2c_encoder_driver ch7006_driver = {
 	.i2c_driver = {
 		.probe = ch7006_probe,
 		.remove = ch7006_remove,
-		.suspend = ch7006_suspend,
-		.resume = ch7006_resume,
 
 		.driver = {
 			.name = "ch7006",
+			.pm = &ch7006_pm_ops,
 		},
 
 		.id_table = ch7006_ids,
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index b0bacdb..0f2c549 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -40,6 +40,7 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o \
 	  dvo_ivch.o \
 	  dvo_tfp410.o \
 	  dvo_sil164.o \
+	  dvo_ns2501.o \
 	  i915_gem_dmabuf.o
 
 i915-$(CONFIG_COMPAT)   += i915_ioc32.o
diff --git a/drivers/gpu/drm/i915/dvo.h b/drivers/gpu/drm/i915/dvo.h
index 5891469..74b5efc 100644
--- a/drivers/gpu/drm/i915/dvo.h
+++ b/drivers/gpu/drm/i915/dvo.h
@@ -58,13 +58,12 @@ struct intel_dvo_dev_ops {
 	void (*create_resources)(struct intel_dvo_device *dvo);
 
 	/*
-	 * Turn on/off output or set intermediate power levels if available.
+	 * Turn on/off output.
 	 *
-	 * Unsupported intermediate modes drop to the lower power setting.
-	 * If the  mode is DPMSModeOff, the output must be disabled,
-	 * as the DPLL may be disabled afterwards.
+	 * Because none of our dvo drivers support an intermediate power levels,
+	 * we don't expose this in the interfac.
 	 */
-	void (*dpms)(struct intel_dvo_device *dvo, int mode);
+	void (*dpms)(struct intel_dvo_device *dvo, bool enable);
 
 	/*
 	 * Callback for testing a video mode for a given output.
@@ -115,6 +114,12 @@ struct intel_dvo_dev_ops {
 	 */
 	enum drm_connector_status (*detect)(struct intel_dvo_device *dvo);
 
+	/*
+	 * Probe the current hw status, returning true if the connected output
+	 * is active.
+	 */
+	bool (*get_hw_state)(struct intel_dvo_device *dev);
+
 	/**
 	 * Query the device for the modes it provides.
 	 *
@@ -140,5 +145,6 @@ extern struct intel_dvo_dev_ops ch7xxx_ops;
 extern struct intel_dvo_dev_ops ivch_ops;
 extern struct intel_dvo_dev_ops tfp410_ops;
 extern struct intel_dvo_dev_ops ch7017_ops;
+extern struct intel_dvo_dev_ops ns2501_ops;
 
 #endif /* _INTEL_DVO_H */
diff --git a/drivers/gpu/drm/i915/dvo_ch7017.c b/drivers/gpu/drm/i915/dvo_ch7017.c
index 1ca799a..86b27d1 100644
--- a/drivers/gpu/drm/i915/dvo_ch7017.c
+++ b/drivers/gpu/drm/i915/dvo_ch7017.c
@@ -163,7 +163,7 @@ struct ch7017_priv {
 };
 
 static void ch7017_dump_regs(struct intel_dvo_device *dvo);
-static void ch7017_dpms(struct intel_dvo_device *dvo, int mode);
+static void ch7017_dpms(struct intel_dvo_device *dvo, bool enable);
 
 static bool ch7017_read(struct intel_dvo_device *dvo, u8 addr, u8 *val)
 {
@@ -309,7 +309,7 @@ static void ch7017_mode_set(struct intel_dvo_device *dvo,
 	lvds_power_down = CH7017_LVDS_POWER_DOWN_DEFAULT_RESERVED |
 			  (mode->hdisplay & 0x0700) >> 8;
 
-	ch7017_dpms(dvo, DRM_MODE_DPMS_OFF);
+	ch7017_dpms(dvo, false);
 	ch7017_write(dvo, CH7017_HORIZONTAL_ACTIVE_PIXEL_INPUT,
 			horizontal_active_pixel_input);
 	ch7017_write(dvo, CH7017_HORIZONTAL_ACTIVE_PIXEL_OUTPUT,
@@ -331,7 +331,7 @@ static void ch7017_mode_set(struct intel_dvo_device *dvo,
 }
 
 /* set the CH7017 power state */
-static void ch7017_dpms(struct intel_dvo_device *dvo, int mode)
+static void ch7017_dpms(struct intel_dvo_device *dvo, bool enable)
 {
 	uint8_t val;
 
@@ -345,7 +345,7 @@ static void ch7017_dpms(struct intel_dvo_device *dvo, int mode)
 			CH7017_DAC3_POWER_DOWN |
 			CH7017_TV_POWER_DOWN_EN);
 
-	if (mode == DRM_MODE_DPMS_ON) {
+	if (enable) {
 		/* Turn on the LVDS */
 		ch7017_write(dvo, CH7017_LVDS_POWER_DOWN,
 			     val & ~CH7017_LVDS_POWER_DOWN_EN);
@@ -359,6 +359,18 @@ static void ch7017_dpms(struct intel_dvo_device *dvo, int mode)
 	msleep(20);
 }
 
+static bool ch7017_get_hw_state(struct intel_dvo_device *dvo)
+{
+	uint8_t val;
+
+	ch7017_read(dvo, CH7017_LVDS_POWER_DOWN, &val);
+
+	if (val & CH7017_LVDS_POWER_DOWN_EN)
+		return false;
+	else
+		return true;
+}
+
 static void ch7017_dump_regs(struct intel_dvo_device *dvo)
 {
 	uint8_t val;
@@ -396,6 +408,7 @@ struct intel_dvo_dev_ops ch7017_ops = {
 	.mode_valid = ch7017_mode_valid,
 	.mode_set = ch7017_mode_set,
 	.dpms = ch7017_dpms,
+	.get_hw_state = ch7017_get_hw_state,
 	.dump_regs = ch7017_dump_regs,
 	.destroy = ch7017_destroy,
 };
diff --git a/drivers/gpu/drm/i915/dvo_ch7xxx.c b/drivers/gpu/drm/i915/dvo_ch7xxx.c
index 4a03660..38f3a6c 100644
--- a/drivers/gpu/drm/i915/dvo_ch7xxx.c
+++ b/drivers/gpu/drm/i915/dvo_ch7xxx.c
@@ -289,14 +289,26 @@ static void ch7xxx_mode_set(struct intel_dvo_device *dvo,
 }
 
 /* set the CH7xxx power state */
-static void ch7xxx_dpms(struct intel_dvo_device *dvo, int mode)
+static void ch7xxx_dpms(struct intel_dvo_device *dvo, bool enable)
 {
-	if (mode == DRM_MODE_DPMS_ON)
+	if (enable)
 		ch7xxx_writeb(dvo, CH7xxx_PM, CH7xxx_PM_DVIL | CH7xxx_PM_DVIP);
 	else
 		ch7xxx_writeb(dvo, CH7xxx_PM, CH7xxx_PM_FPD);
 }
 
+static bool ch7xxx_get_hw_state(struct intel_dvo_device *dvo)
+{
+	u8 val;
+
+	ch7xxx_readb(dvo, CH7xxx_PM, &val);
+
+	if (val & CH7xxx_PM_FPD)
+		return false;
+	else
+		return true;
+}
+
 static void ch7xxx_dump_regs(struct intel_dvo_device *dvo)
 {
 	int i;
@@ -326,6 +338,7 @@ struct intel_dvo_dev_ops ch7xxx_ops = {
 	.mode_valid = ch7xxx_mode_valid,
 	.mode_set = ch7xxx_mode_set,
 	.dpms = ch7xxx_dpms,
+	.get_hw_state = ch7xxx_get_hw_state,
 	.dump_regs = ch7xxx_dump_regs,
 	.destroy = ch7xxx_destroy,
 };
diff --git a/drivers/gpu/drm/i915/dvo_ivch.c b/drivers/gpu/drm/i915/dvo_ivch.c
index 04f2893..baaf65b 100644
--- a/drivers/gpu/drm/i915/dvo_ivch.c
+++ b/drivers/gpu/drm/i915/dvo_ivch.c
@@ -288,7 +288,7 @@ static enum drm_mode_status ivch_mode_valid(struct intel_dvo_device *dvo,
 }
 
 /** Sets the power state of the panel connected to the ivch */
-static void ivch_dpms(struct intel_dvo_device *dvo, int mode)
+static void ivch_dpms(struct intel_dvo_device *dvo, bool enable)
 {
 	int i;
 	uint16_t vr01, vr30, backlight;
@@ -297,13 +297,13 @@ static void ivch_dpms(struct intel_dvo_device *dvo, int mode)
 	if (!ivch_read(dvo, VR01, &vr01))
 		return;
 
-	if (mode == DRM_MODE_DPMS_ON)
+	if (enable)
 		backlight = 1;
 	else
 		backlight = 0;
 	ivch_write(dvo, VR80, backlight);
 
-	if (mode == DRM_MODE_DPMS_ON)
+	if (enable)
 		vr01 |= VR01_LCD_ENABLE | VR01_DVO_ENABLE;
 	else
 		vr01 &= ~(VR01_LCD_ENABLE | VR01_DVO_ENABLE);
@@ -315,7 +315,7 @@ static void ivch_dpms(struct intel_dvo_device *dvo, int mode)
 		if (!ivch_read(dvo, VR30, &vr30))
 			break;
 
-		if (((vr30 & VR30_PANEL_ON) != 0) == (mode == DRM_MODE_DPMS_ON))
+		if (((vr30 & VR30_PANEL_ON) != 0) == enable)
 			break;
 		udelay(1000);
 	}
@@ -323,6 +323,20 @@ static void ivch_dpms(struct intel_dvo_device *dvo, int mode)
 	udelay(16 * 1000);
 }
 
+static bool ivch_get_hw_state(struct intel_dvo_device *dvo)
+{
+	uint16_t vr01;
+
+	/* Set the new power state of the panel. */
+	if (!ivch_read(dvo, VR01, &vr01))
+		return false;
+
+	if (vr01 & VR01_LCD_ENABLE)
+		return true;
+	else
+		return false;
+}
+
 static void ivch_mode_set(struct intel_dvo_device *dvo,
 			  struct drm_display_mode *mode,
 			  struct drm_display_mode *adjusted_mode)
@@ -413,6 +427,7 @@ static void ivch_destroy(struct intel_dvo_device *dvo)
 struct intel_dvo_dev_ops ivch_ops = {
 	.init = ivch_init,
 	.dpms = ivch_dpms,
+	.get_hw_state = ivch_get_hw_state,
 	.mode_valid = ivch_mode_valid,
 	.mode_set = ivch_mode_set,
 	.detect = ivch_detect,
diff --git a/drivers/gpu/drm/i915/dvo_ns2501.c b/drivers/gpu/drm/i915/dvo_ns2501.c
new file mode 100644
index 0000000..c4a255b
--- /dev/null
+++ b/drivers/gpu/drm/i915/dvo_ns2501.c
@@ -0,0 +1,588 @@
+/*
+ *
+ * Copyright (c) 2012 Gilles Dartiguelongue, Thomas Richter
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "dvo.h"
+#include "i915_reg.h"
+#include "i915_drv.h"
+
+#define NS2501_VID 0x1305
+#define NS2501_DID 0x6726
+
+#define NS2501_VID_LO 0x00
+#define NS2501_VID_HI 0x01
+#define NS2501_DID_LO 0x02
+#define NS2501_DID_HI 0x03
+#define NS2501_REV 0x04
+#define NS2501_RSVD 0x05
+#define NS2501_FREQ_LO 0x06
+#define NS2501_FREQ_HI 0x07
+
+#define NS2501_REG8 0x08
+#define NS2501_8_VEN (1<<5)
+#define NS2501_8_HEN (1<<4)
+#define NS2501_8_DSEL (1<<3)
+#define NS2501_8_BPAS (1<<2)
+#define NS2501_8_RSVD (1<<1)
+#define NS2501_8_PD (1<<0)
+
+#define NS2501_REG9 0x09
+#define NS2501_9_VLOW (1<<7)
+#define NS2501_9_MSEL_MASK (0x7<<4)
+#define NS2501_9_TSEL (1<<3)
+#define NS2501_9_RSEN (1<<2)
+#define NS2501_9_RSVD (1<<1)
+#define NS2501_9_MDI (1<<0)
+
+#define NS2501_REGC 0x0c
+
+struct ns2501_priv {
+	//I2CDevRec d;
+	bool quiet;
+	int reg_8_shadow;
+	int reg_8_set;
+	// Shadow registers for i915
+	int dvoc;
+	int pll_a;
+	int srcdim;
+	int fw_blc;
+};
+
+#define NSPTR(d) ((NS2501Ptr)(d->DriverPrivate.ptr))
+
+/*
+ * For reasons unclear to me, the ns2501 at least on the Fujitsu/Siemens
+ * laptops does not react on the i2c bus unless
+ * both the PLL is running and the display is configured in its native
+ * resolution.
+ * This function forces the DVO on, and stores the registers it touches.
+ * Afterwards, registers are restored to regular values.
+ *
+ * This is pretty much a hack, though it works.
+ * Without that, ns2501_readb and ns2501_writeb fail
+ * when switching the resolution.
+ */
+
+static void enable_dvo(struct intel_dvo_device *dvo)
+{
+	struct ns2501_priv *ns = (struct ns2501_priv *)(dvo->dev_priv);
+	struct i2c_adapter *adapter = dvo->i2c_bus;
+	struct intel_gmbus *bus = container_of(adapter,
+					       struct intel_gmbus,
+					       adapter);
+	struct drm_i915_private *dev_priv = bus->dev_priv;
+
+	DRM_DEBUG_KMS("%s: Trying to re-enable the DVO\n", __FUNCTION__);
+
+	ns->dvoc = I915_READ(DVO_C);
+	ns->pll_a = I915_READ(_DPLL_A);
+	ns->srcdim = I915_READ(DVOC_SRCDIM);
+	ns->fw_blc = I915_READ(FW_BLC);
+
+	I915_WRITE(DVOC, 0x10004084);
+	I915_WRITE(_DPLL_A, 0xd0820000);
+	I915_WRITE(DVOC_SRCDIM, 0x400300);	// 1024x768
+	I915_WRITE(FW_BLC, 0x1080304);
+
+	I915_WRITE(DVOC, 0x90004084);
+}
+
+/*
+ * Restore the I915 registers modified by the above
+ * trigger function.
+ */
+static void restore_dvo(struct intel_dvo_device *dvo)
+{
+	struct i2c_adapter *adapter = dvo->i2c_bus;
+	struct intel_gmbus *bus = container_of(adapter,
+					       struct intel_gmbus,
+					       adapter);
+	struct drm_i915_private *dev_priv = bus->dev_priv;
+	struct ns2501_priv *ns = (struct ns2501_priv *)(dvo->dev_priv);
+
+	I915_WRITE(DVOC, ns->dvoc);
+	I915_WRITE(_DPLL_A, ns->pll_a);
+	I915_WRITE(DVOC_SRCDIM, ns->srcdim);
+	I915_WRITE(FW_BLC, ns->fw_blc);
+}
+
+/*
+** Read a register from the ns2501.
+** Returns true if successful, false otherwise.
+** If it returns false, it might be wise to enable the
+** DVO with the above function.
+*/
+static bool ns2501_readb(struct intel_dvo_device *dvo, int addr, uint8_t * ch)
+{
+	struct ns2501_priv *ns = dvo->dev_priv;
+	struct i2c_adapter *adapter = dvo->i2c_bus;
+	u8 out_buf[2];
+	u8 in_buf[2];
+
+	struct i2c_msg msgs[] = {
+		{
+		 .addr = dvo->slave_addr,
+		 .flags = 0,
+		 .len = 1,
+		 .buf = out_buf,
+		 },
+		{
+		 .addr = dvo->slave_addr,
+		 .flags = I2C_M_RD,
+		 .len = 1,
+		 .buf = in_buf,
+		 }
+	};
+
+	out_buf[0] = addr;
+	out_buf[1] = 0;
+
+	if (i2c_transfer(adapter, msgs, 2) == 2) {
+		*ch = in_buf[0];
+		return true;
+	};
+
+	if (!ns->quiet) {
+		DRM_DEBUG_KMS
+		    ("Unable to read register 0x%02x from %s:0x%02x.\n", addr,
+		     adapter->name, dvo->slave_addr);
+	}
+
+	return false;
+}
+
+/*
+** Write a register to the ns2501.
+** Returns true if successful, false otherwise.
+** If it returns false, it might be wise to enable the
+** DVO with the above function.
+*/
+static bool ns2501_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch)
+{
+	struct ns2501_priv *ns = dvo->dev_priv;
+	struct i2c_adapter *adapter = dvo->i2c_bus;
+	uint8_t out_buf[2];
+
+	struct i2c_msg msg = {
+		.addr = dvo->slave_addr,
+		.flags = 0,
+		.len = 2,
+		.buf = out_buf,
+	};
+
+	out_buf[0] = addr;
+	out_buf[1] = ch;
+
+	if (i2c_transfer(adapter, &msg, 1) == 1) {
+		return true;
+	}
+
+	if (!ns->quiet) {
+		DRM_DEBUG_KMS("Unable to write register 0x%02x to %s:%d\n",
+			      addr, adapter->name, dvo->slave_addr);
+	}
+
+	return false;
+}
+
+/* National Semiconductor 2501 driver for chip on i2c bus
+ * scan for the chip on the bus.
+ * Hope the VBIOS initialized the PLL correctly so we can
+ * talk to it. If not, it will not be seen and not detected.
+ * Bummer!
+ */
+static bool ns2501_init(struct intel_dvo_device *dvo,
+			struct i2c_adapter *adapter)
+{
+	/* this will detect the NS2501 chip on the specified i2c bus */
+	struct ns2501_priv *ns;
+	unsigned char ch;
+
+	ns = kzalloc(sizeof(struct ns2501_priv), GFP_KERNEL);
+	if (ns == NULL)
+		return false;
+
+	dvo->i2c_bus = adapter;
+	dvo->dev_priv = ns;
+	ns->quiet = true;
+
+	if (!ns2501_readb(dvo, NS2501_VID_LO, &ch))
+		goto out;
+
+	if (ch != (NS2501_VID & 0xff)) {
+		DRM_DEBUG_KMS("ns2501 not detected got %d: from %s Slave %d.\n",
+			      ch, adapter->name, dvo->slave_addr);
+		goto out;
+	}
+
+	if (!ns2501_readb(dvo, NS2501_DID_LO, &ch))
+		goto out;
+
+	if (ch != (NS2501_DID & 0xff)) {
+		DRM_DEBUG_KMS("ns2501 not detected got %d: from %s Slave %d.\n",
+			      ch, adapter->name, dvo->slave_addr);
+		goto out;
+	}
+	ns->quiet = false;
+	ns->reg_8_set = 0;
+	ns->reg_8_shadow =
+	    NS2501_8_PD | NS2501_8_BPAS | NS2501_8_VEN | NS2501_8_HEN;
+
+	DRM_DEBUG_KMS("init ns2501 dvo controller successfully!\n");
+	return true;
+
+out:
+	kfree(ns);
+	return false;
+}
+
+static enum drm_connector_status ns2501_detect(struct intel_dvo_device *dvo)
+{
+	/*
+	 * This is a Laptop display, it doesn't have hotplugging.
+	 * Even if not, the detection bit of the 2501 is unreliable as
+	 * it only works for some display types.
+	 * It is even more unreliable as the PLL must be active for
+	 * allowing reading from the chiop.
+	 */
+	return connector_status_connected;
+}
+
+static enum drm_mode_status ns2501_mode_valid(struct intel_dvo_device *dvo,
+					      struct drm_display_mode *mode)
+{
+	DRM_DEBUG_KMS
+	    ("%s: is mode valid (hdisplay=%d,htotal=%d,vdisplay=%d,vtotal=%d)\n",
+	     __FUNCTION__, mode->hdisplay, mode->htotal, mode->vdisplay,
+	     mode->vtotal);
+
+	/*
+	 * Currently, these are all the modes I have data from.
+	 * More might exist. Unclear how to find the native resolution
+	 * of the panel in here so we could always accept it
+	 * by disabling the scaler.
+	 */
+	if ((mode->hdisplay == 800 && mode->vdisplay == 600) ||
+	    (mode->hdisplay == 640 && mode->vdisplay == 480) ||
+	    (mode->hdisplay == 1024 && mode->vdisplay == 768)) {
+		return MODE_OK;
+	} else {
+		return MODE_ONE_SIZE;	/* Is this a reasonable error? */
+	}
+}
+
+static void ns2501_mode_set(struct intel_dvo_device *dvo,
+			    struct drm_display_mode *mode,
+			    struct drm_display_mode *adjusted_mode)
+{
+	bool ok;
+	bool restore = false;
+	struct ns2501_priv *ns = (struct ns2501_priv *)(dvo->dev_priv);
+
+	DRM_DEBUG_KMS
+	    ("%s: set mode (hdisplay=%d,htotal=%d,vdisplay=%d,vtotal=%d).\n",
+	     __FUNCTION__, mode->hdisplay, mode->htotal, mode->vdisplay,
+	     mode->vtotal);
+
+	/*
+	 * Where do I find the native resolution for which scaling is not required???
+	 *
+	 * First trigger the DVO on as otherwise the chip does not appear on the i2c
+	 * bus.
+	 */
+	do {
+		ok = true;
+
+		if (mode->hdisplay == 800 && mode->vdisplay == 600) {
+			/* mode 277 */
+			ns->reg_8_shadow &= ~NS2501_8_BPAS;
+			DRM_DEBUG_KMS("%s: switching to 800x600\n",
+				      __FUNCTION__);
+
+			/*
+			 * No, I do not know where this data comes from.
+			 * It is just what the video bios left in the DVO, so
+			 * I'm just copying it here over.
+			 * This also means that I cannot support any other modes
+			 * except the ones supported by the bios.
+			 */
+			ok &= ns2501_writeb(dvo, 0x11, 0xc8);	// 0xc7 also works.
+			ok &= ns2501_writeb(dvo, 0x1b, 0x19);
+			ok &= ns2501_writeb(dvo, 0x1c, 0x62);	// VBIOS left 0x64 here, but 0x62 works nicer
+			ok &= ns2501_writeb(dvo, 0x1d, 0x02);
+
+			ok &= ns2501_writeb(dvo, 0x34, 0x03);
+			ok &= ns2501_writeb(dvo, 0x35, 0xff);
+
+			ok &= ns2501_writeb(dvo, 0x80, 0x27);
+			ok &= ns2501_writeb(dvo, 0x81, 0x03);
+			ok &= ns2501_writeb(dvo, 0x82, 0x41);
+			ok &= ns2501_writeb(dvo, 0x83, 0x05);
+
+			ok &= ns2501_writeb(dvo, 0x8d, 0x02);
+			ok &= ns2501_writeb(dvo, 0x8e, 0x04);
+			ok &= ns2501_writeb(dvo, 0x8f, 0x00);
+
+			ok &= ns2501_writeb(dvo, 0x90, 0xfe);	/* vertical. VBIOS left 0xff here, but 0xfe works better */
+			ok &= ns2501_writeb(dvo, 0x91, 0x07);
+			ok &= ns2501_writeb(dvo, 0x94, 0x00);
+			ok &= ns2501_writeb(dvo, 0x95, 0x00);
+
+			ok &= ns2501_writeb(dvo, 0x96, 0x00);
+
+			ok &= ns2501_writeb(dvo, 0x99, 0x00);
+			ok &= ns2501_writeb(dvo, 0x9a, 0x88);
+
+			ok &= ns2501_writeb(dvo, 0x9c, 0x23);	/* Looks like first and last line of the image. */
+			ok &= ns2501_writeb(dvo, 0x9d, 0x00);
+			ok &= ns2501_writeb(dvo, 0x9e, 0x25);
+			ok &= ns2501_writeb(dvo, 0x9f, 0x03);
+
+			ok &= ns2501_writeb(dvo, 0xa4, 0x80);
+
+			ok &= ns2501_writeb(dvo, 0xb6, 0x00);
+
+			ok &= ns2501_writeb(dvo, 0xb9, 0xc8);	/* horizontal? */
+			ok &= ns2501_writeb(dvo, 0xba, 0x00);	/* horizontal? */
+
+			ok &= ns2501_writeb(dvo, 0xc0, 0x05);	/* horizontal? */
+			ok &= ns2501_writeb(dvo, 0xc1, 0xd7);
+
+			ok &= ns2501_writeb(dvo, 0xc2, 0x00);
+			ok &= ns2501_writeb(dvo, 0xc3, 0xf8);
+
+			ok &= ns2501_writeb(dvo, 0xc4, 0x03);
+			ok &= ns2501_writeb(dvo, 0xc5, 0x1a);
+
+			ok &= ns2501_writeb(dvo, 0xc6, 0x00);
+			ok &= ns2501_writeb(dvo, 0xc7, 0x73);
+			ok &= ns2501_writeb(dvo, 0xc8, 0x02);
+
+		} else if (mode->hdisplay == 640 && mode->vdisplay == 480) {
+			/* mode 274 */
+			DRM_DEBUG_KMS("%s: switching to 640x480\n",
+				      __FUNCTION__);
+			/*
+			 * No, I do not know where this data comes from.
+			 * It is just what the video bios left in the DVO, so
+			 * I'm just copying it here over.
+			 * This also means that I cannot support any other modes
+			 * except the ones supported by the bios.
+			 */
+			ns->reg_8_shadow &= ~NS2501_8_BPAS;
+
+			ok &= ns2501_writeb(dvo, 0x11, 0xa0);
+			ok &= ns2501_writeb(dvo, 0x1b, 0x11);
+			ok &= ns2501_writeb(dvo, 0x1c, 0x54);
+			ok &= ns2501_writeb(dvo, 0x1d, 0x03);
+
+			ok &= ns2501_writeb(dvo, 0x34, 0x03);
+			ok &= ns2501_writeb(dvo, 0x35, 0xff);
+
+			ok &= ns2501_writeb(dvo, 0x80, 0xff);
+			ok &= ns2501_writeb(dvo, 0x81, 0x07);
+			ok &= ns2501_writeb(dvo, 0x82, 0x3d);
+			ok &= ns2501_writeb(dvo, 0x83, 0x05);
+
+			ok &= ns2501_writeb(dvo, 0x8d, 0x02);
+			ok &= ns2501_writeb(dvo, 0x8e, 0x10);
+			ok &= ns2501_writeb(dvo, 0x8f, 0x00);
+
+			ok &= ns2501_writeb(dvo, 0x90, 0xff);	/* vertical */
+			ok &= ns2501_writeb(dvo, 0x91, 0x07);
+			ok &= ns2501_writeb(dvo, 0x94, 0x00);
+			ok &= ns2501_writeb(dvo, 0x95, 0x00);
+
+			ok &= ns2501_writeb(dvo, 0x96, 0x05);
+
+			ok &= ns2501_writeb(dvo, 0x99, 0x00);
+			ok &= ns2501_writeb(dvo, 0x9a, 0x88);
+
+			ok &= ns2501_writeb(dvo, 0x9c, 0x24);
+			ok &= ns2501_writeb(dvo, 0x9d, 0x00);
+			ok &= ns2501_writeb(dvo, 0x9e, 0x25);
+			ok &= ns2501_writeb(dvo, 0x9f, 0x03);
+
+			ok &= ns2501_writeb(dvo, 0xa4, 0x84);
+
+			ok &= ns2501_writeb(dvo, 0xb6, 0x09);
+
+			ok &= ns2501_writeb(dvo, 0xb9, 0xa0);	/* horizontal? */
+			ok &= ns2501_writeb(dvo, 0xba, 0x00);	/* horizontal? */
+
+			ok &= ns2501_writeb(dvo, 0xc0, 0x05);	/* horizontal? */
+			ok &= ns2501_writeb(dvo, 0xc1, 0x90);
+
+			ok &= ns2501_writeb(dvo, 0xc2, 0x00);
+			ok &= ns2501_writeb(dvo, 0xc3, 0x0f);
+
+			ok &= ns2501_writeb(dvo, 0xc4, 0x03);
+			ok &= ns2501_writeb(dvo, 0xc5, 0x16);
+
+			ok &= ns2501_writeb(dvo, 0xc6, 0x00);
+			ok &= ns2501_writeb(dvo, 0xc7, 0x02);
+			ok &= ns2501_writeb(dvo, 0xc8, 0x02);
+
+		} else if (mode->hdisplay == 1024 && mode->vdisplay == 768) {
+			/* mode 280 */
+			DRM_DEBUG_KMS("%s: switching to 1024x768\n",
+				      __FUNCTION__);
+			/*
+			 * This might or might not work, actually. I'm silently
+			 * assuming here that the native panel resolution is
+			 * 1024x768. If not, then this leaves the scaler disabled
+			 * generating a picture that is likely not the expected.
+			 *
+			 * Problem is that I do not know where to take the panel
+			 * dimensions from.
+			 *
+			 * Enable the bypass, scaling not required.
+			 *
+			 * The scaler registers are irrelevant here....
+			 *
+			 */
+			ns->reg_8_shadow |= NS2501_8_BPAS;
+			ok &= ns2501_writeb(dvo, 0x37, 0x44);
+		} else {
+			/*
+			 * Data not known. Bummer!
+			 * Hopefully, the code should not go here
+			 * as mode_OK delivered no other modes.
+			 */
+			ns->reg_8_shadow |= NS2501_8_BPAS;
+		}
+		ok &= ns2501_writeb(dvo, NS2501_REG8, ns->reg_8_shadow);
+
+		if (!ok) {
+			if (restore)
+				restore_dvo(dvo);
+			enable_dvo(dvo);
+			restore = true;
+		}
+	} while (!ok);
+	/*
+	 * Restore the old i915 registers before
+	 * forcing the ns2501 on.
+	 */
+	if (restore)
+		restore_dvo(dvo);
+}
+
+/* set the NS2501 power state */
+static bool ns2501_get_hw_state(struct intel_dvo_device *dvo)
+{
+	unsigned char ch;
+
+	if (!ns2501_readb(dvo, NS2501_REG8, &ch))
+		return false;
+
+	if (ch & NS2501_8_PD)
+		return true;
+	else
+		return false;
+}
+
+/* set the NS2501 power state */
+static void ns2501_dpms(struct intel_dvo_device *dvo, bool enable)
+{
+	bool ok;
+	bool restore = false;
+	struct ns2501_priv *ns = (struct ns2501_priv *)(dvo->dev_priv);
+	unsigned char ch;
+
+	DRM_DEBUG_KMS("%s: Trying set the dpms of the DVO to %i\n",
+		      __FUNCTION__, enable);
+
+	ch = ns->reg_8_shadow;
+
+	if (enable)
+		ch |= NS2501_8_PD;
+	else
+		ch &= ~NS2501_8_PD;
+
+	if (ns->reg_8_set == 0 || ns->reg_8_shadow != ch) {
+		ns->reg_8_set = 1;
+		ns->reg_8_shadow = ch;
+
+		do {
+			ok = true;
+			ok &= ns2501_writeb(dvo, NS2501_REG8, ch);
+			ok &=
+			    ns2501_writeb(dvo, 0x34,
+					  enable ? 0x03 : 0x00);
+			ok &=
+			    ns2501_writeb(dvo, 0x35,
+					  enable ? 0xff : 0x00);
+			if (!ok) {
+				if (restore)
+					restore_dvo(dvo);
+				enable_dvo(dvo);
+				restore = true;
+			}
+		} while (!ok);
+
+		if (restore)
+			restore_dvo(dvo);
+	}
+}
+
+static void ns2501_dump_regs(struct intel_dvo_device *dvo)
+{
+	uint8_t val;
+
+	ns2501_readb(dvo, NS2501_FREQ_LO, &val);
+	DRM_LOG_KMS("NS2501_FREQ_LO: 0x%02x\n", val);
+	ns2501_readb(dvo, NS2501_FREQ_HI, &val);
+	DRM_LOG_KMS("NS2501_FREQ_HI: 0x%02x\n", val);
+	ns2501_readb(dvo, NS2501_REG8, &val);
+	DRM_LOG_KMS("NS2501_REG8: 0x%02x\n", val);
+	ns2501_readb(dvo, NS2501_REG9, &val);
+	DRM_LOG_KMS("NS2501_REG9: 0x%02x\n", val);
+	ns2501_readb(dvo, NS2501_REGC, &val);
+	DRM_LOG_KMS("NS2501_REGC: 0x%02x\n", val);
+}
+
+static void ns2501_destroy(struct intel_dvo_device *dvo)
+{
+	struct ns2501_priv *ns = dvo->dev_priv;
+
+	if (ns) {
+		kfree(ns);
+		dvo->dev_priv = NULL;
+	}
+}
+
+struct intel_dvo_dev_ops ns2501_ops = {
+	.init = ns2501_init,
+	.detect = ns2501_detect,
+	.mode_valid = ns2501_mode_valid,
+	.mode_set = ns2501_mode_set,
+	.dpms = ns2501_dpms,
+	.get_hw_state = ns2501_get_hw_state,
+	.dump_regs = ns2501_dump_regs,
+	.destroy = ns2501_destroy,
+};
diff --git a/drivers/gpu/drm/i915/dvo_sil164.c b/drivers/gpu/drm/i915/dvo_sil164.c
index a0b13a6..4debd32 100644
--- a/drivers/gpu/drm/i915/dvo_sil164.c
+++ b/drivers/gpu/drm/i915/dvo_sil164.c
@@ -208,7 +208,7 @@ static void sil164_mode_set(struct intel_dvo_device *dvo,
 }
 
 /* set the SIL164 power state */
-static void sil164_dpms(struct intel_dvo_device *dvo, int mode)
+static void sil164_dpms(struct intel_dvo_device *dvo, bool enable)
 {
 	int ret;
 	unsigned char ch;
@@ -217,7 +217,7 @@ static void sil164_dpms(struct intel_dvo_device *dvo, int mode)
 	if (ret == false)
 		return;
 
-	if (mode == DRM_MODE_DPMS_ON)
+	if (enable)
 		ch |= SIL164_8_PD;
 	else
 		ch &= ~SIL164_8_PD;
@@ -226,6 +226,21 @@ static void sil164_dpms(struct intel_dvo_device *dvo, int mode)
 	return;
 }
 
+static bool sil164_get_hw_state(struct intel_dvo_device *dvo)
+{
+	int ret;
+	unsigned char ch;
+
+	ret = sil164_readb(dvo, SIL164_REG8, &ch);
+	if (ret == false)
+		return false;
+
+	if (ch & SIL164_8_PD)
+		return true;
+	else
+		return false;
+}
+
 static void sil164_dump_regs(struct intel_dvo_device *dvo)
 {
 	uint8_t val;
@@ -258,6 +273,7 @@ struct intel_dvo_dev_ops sil164_ops = {
 	.mode_valid = sil164_mode_valid,
 	.mode_set = sil164_mode_set,
 	.dpms = sil164_dpms,
+	.get_hw_state = sil164_get_hw_state,
 	.dump_regs = sil164_dump_regs,
 	.destroy = sil164_destroy,
 };
diff --git a/drivers/gpu/drm/i915/dvo_tfp410.c b/drivers/gpu/drm/i915/dvo_tfp410.c
index aa2cd3e..e17f1b0 100644
--- a/drivers/gpu/drm/i915/dvo_tfp410.c
+++ b/drivers/gpu/drm/i915/dvo_tfp410.c
@@ -234,14 +234,14 @@ static void tfp410_mode_set(struct intel_dvo_device *dvo,
 }
 
 /* set the tfp410 power state */
-static void tfp410_dpms(struct intel_dvo_device *dvo, int mode)
+static void tfp410_dpms(struct intel_dvo_device *dvo, bool enable)
 {
 	uint8_t ctl1;
 
 	if (!tfp410_readb(dvo, TFP410_CTL_1, &ctl1))
 		return;
 
-	if (mode == DRM_MODE_DPMS_ON)
+	if (enable)
 		ctl1 |= TFP410_CTL_1_PD;
 	else
 		ctl1 &= ~TFP410_CTL_1_PD;
@@ -249,6 +249,19 @@ static void tfp410_dpms(struct intel_dvo_device *dvo, int mode)
 	tfp410_writeb(dvo, TFP410_CTL_1, ctl1);
 }
 
+static bool tfp410_get_hw_state(struct intel_dvo_device *dvo)
+{
+	uint8_t ctl1;
+
+	if (!tfp410_readb(dvo, TFP410_CTL_1, &ctl1))
+		return false;
+
+	if (ctl1 & TFP410_CTL_1_PD)
+		return true;
+	else
+		return false;
+}
+
 static void tfp410_dump_regs(struct intel_dvo_device *dvo)
 {
 	uint8_t val, val2;
@@ -299,6 +312,7 @@ struct intel_dvo_dev_ops tfp410_ops = {
 	.mode_valid = tfp410_mode_valid,
 	.mode_set = tfp410_mode_set,
 	.dpms = tfp410_dpms,
+	.get_hw_state = tfp410_get_hw_state,
 	.dump_regs = tfp410_dump_regs,
 	.destroy = tfp410_destroy,
 };
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 359f6e8..274a328 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -44,7 +44,6 @@
 
 enum {
 	ACTIVE_LIST,
-	FLUSHING_LIST,
 	INACTIVE_LIST,
 	PINNED_LIST,
 };
@@ -62,28 +61,11 @@ static int i915_capabilities(struct seq_file *m, void *data)
 
 	seq_printf(m, "gen: %d\n", info->gen);
 	seq_printf(m, "pch: %d\n", INTEL_PCH_TYPE(dev));
-#define B(x) seq_printf(m, #x ": %s\n", yesno(info->x))
-	B(is_mobile);
-	B(is_i85x);
-	B(is_i915g);
-	B(is_i945gm);
-	B(is_g33);
-	B(need_gfx_hws);
-	B(is_g4x);
-	B(is_pineview);
-	B(is_broadwater);
-	B(is_crestline);
-	B(has_fbc);
-	B(has_pipe_cxsr);
-	B(has_hotplug);
-	B(cursor_needs_physical);
-	B(has_overlay);
-	B(overlay_needs_physical);
-	B(supports_tv);
-	B(has_bsd_ring);
-	B(has_blt_ring);
-	B(has_llc);
-#undef B
+#define DEV_INFO_FLAG(x) seq_printf(m, #x ": %s\n", yesno(info->x))
+#define DEV_INFO_SEP ;
+	DEV_INFO_FLAGS;
+#undef DEV_INFO_FLAG
+#undef DEV_INFO_SEP
 
 	return 0;
 }
@@ -121,20 +103,23 @@ static const char *cache_level_str(int type)
 static void
 describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
 {
-	seq_printf(m, "%p: %s%s %8zdKiB %04x %04x %d %d%s%s%s",
+	seq_printf(m, "%p: %s%s %8zdKiB %04x %04x %d %d %d%s%s%s",
 		   &obj->base,
 		   get_pin_flag(obj),
 		   get_tiling_flag(obj),
 		   obj->base.size / 1024,
 		   obj->base.read_domains,
 		   obj->base.write_domain,
-		   obj->last_rendering_seqno,
+		   obj->last_read_seqno,
+		   obj->last_write_seqno,
 		   obj->last_fenced_seqno,
 		   cache_level_str(obj->cache_level),
 		   obj->dirty ? " dirty" : "",
 		   obj->madv == I915_MADV_DONTNEED ? " purgeable" : "");
 	if (obj->base.name)
 		seq_printf(m, " (name: %d)", obj->base.name);
+	if (obj->pin_count)
+		seq_printf(m, " (pinned x %d)", obj->pin_count);
 	if (obj->fence_reg != I915_FENCE_REG_NONE)
 		seq_printf(m, " (fence: %d)", obj->fence_reg);
 	if (obj->gtt_space != NULL)
@@ -177,10 +162,6 @@ static int i915_gem_object_list_info(struct seq_file *m, void *data)
 		seq_printf(m, "Inactive:\n");
 		head = &dev_priv->mm.inactive_list;
 		break;
-	case FLUSHING_LIST:
-		seq_printf(m, "Flushing:\n");
-		head = &dev_priv->mm.flushing_list;
-		break;
 	default:
 		mutex_unlock(&dev->struct_mutex);
 		return -EINVAL;
@@ -218,8 +199,8 @@ static int i915_gem_object_info(struct seq_file *m, void* data)
 	struct drm_info_node *node = (struct drm_info_node *) m->private;
 	struct drm_device *dev = node->minor->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	u32 count, mappable_count;
-	size_t size, mappable_size;
+	u32 count, mappable_count, purgeable_count;
+	size_t size, mappable_size, purgeable_size;
 	struct drm_i915_gem_object *obj;
 	int ret;
 
@@ -232,13 +213,12 @@ static int i915_gem_object_info(struct seq_file *m, void* data)
 		   dev_priv->mm.object_memory);
 
 	size = count = mappable_size = mappable_count = 0;
-	count_objects(&dev_priv->mm.gtt_list, gtt_list);
+	count_objects(&dev_priv->mm.bound_list, gtt_list);
 	seq_printf(m, "%u [%u] objects, %zu [%zu] bytes in gtt\n",
 		   count, mappable_count, size, mappable_size);
 
 	size = count = mappable_size = mappable_count = 0;
 	count_objects(&dev_priv->mm.active_list, mm_list);
-	count_objects(&dev_priv->mm.flushing_list, mm_list);
 	seq_printf(m, "  %u [%u] active objects, %zu [%zu] bytes\n",
 		   count, mappable_count, size, mappable_size);
 
@@ -247,8 +227,16 @@ static int i915_gem_object_info(struct seq_file *m, void* data)
 	seq_printf(m, "  %u [%u] inactive objects, %zu [%zu] bytes\n",
 		   count, mappable_count, size, mappable_size);
 
+	size = count = purgeable_size = purgeable_count = 0;
+	list_for_each_entry(obj, &dev_priv->mm.unbound_list, gtt_list) {
+		size += obj->base.size, ++count;
+		if (obj->madv == I915_MADV_DONTNEED)
+			purgeable_size += obj->base.size, ++purgeable_count;
+	}
+	seq_printf(m, "%u unbound objects, %zu bytes\n", count, size);
+
 	size = count = mappable_size = mappable_count = 0;
-	list_for_each_entry(obj, &dev_priv->mm.gtt_list, gtt_list) {
+	list_for_each_entry(obj, &dev_priv->mm.bound_list, gtt_list) {
 		if (obj->fault_mappable) {
 			size += obj->gtt_space->size;
 			++count;
@@ -257,7 +245,13 @@ static int i915_gem_object_info(struct seq_file *m, void* data)
 			mappable_size += obj->gtt_space->size;
 			++mappable_count;
 		}
+		if (obj->madv == I915_MADV_DONTNEED) {
+			purgeable_size += obj->base.size;
+			++purgeable_count;
+		}
 	}
+	seq_printf(m, "%u purgeable objects, %zu bytes\n",
+		   purgeable_count, purgeable_size);
 	seq_printf(m, "%u pinned mappable objects, %zu bytes\n",
 		   mappable_count, mappable_size);
 	seq_printf(m, "%u fault mappable objects, %zu bytes\n",
@@ -286,7 +280,7 @@ static int i915_gem_gtt_info(struct seq_file *m, void* data)
 		return ret;
 
 	total_obj_size = total_gtt_size = count = 0;
-	list_for_each_entry(obj, &dev_priv->mm.gtt_list, gtt_list) {
+	list_for_each_entry(obj, &dev_priv->mm.bound_list, gtt_list) {
 		if (list == PINNED_LIST && obj->pin_count == 0)
 			continue;
 
@@ -359,40 +353,22 @@ static int i915_gem_request_info(struct seq_file *m, void *data)
 	struct drm_info_node *node = (struct drm_info_node *) m->private;
 	struct drm_device *dev = node->minor->dev;
 	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct intel_ring_buffer *ring;
 	struct drm_i915_gem_request *gem_request;
-	int ret, count;
+	int ret, count, i;
 
 	ret = mutex_lock_interruptible(&dev->struct_mutex);
 	if (ret)
 		return ret;
 
 	count = 0;
-	if (!list_empty(&dev_priv->ring[RCS].request_list)) {
-		seq_printf(m, "Render requests:\n");
-		list_for_each_entry(gem_request,
-				    &dev_priv->ring[RCS].request_list,
-				    list) {
-			seq_printf(m, "    %d @ %d\n",
-				   gem_request->seqno,
-				   (int) (jiffies - gem_request->emitted_jiffies));
-		}
-		count++;
-	}
-	if (!list_empty(&dev_priv->ring[VCS].request_list)) {
-		seq_printf(m, "BSD requests:\n");
-		list_for_each_entry(gem_request,
-				    &dev_priv->ring[VCS].request_list,
-				    list) {
-			seq_printf(m, "    %d @ %d\n",
-				   gem_request->seqno,
-				   (int) (jiffies - gem_request->emitted_jiffies));
-		}
-		count++;
-	}
-	if (!list_empty(&dev_priv->ring[BCS].request_list)) {
-		seq_printf(m, "BLT requests:\n");
+	for_each_ring(ring, dev_priv, i) {
+		if (list_empty(&ring->request_list))
+			continue;
+
+		seq_printf(m, "%s requests:\n", ring->name);
 		list_for_each_entry(gem_request,
-				    &dev_priv->ring[BCS].request_list,
+				    &ring->request_list,
 				    list) {
 			seq_printf(m, "    %d @ %d\n",
 				   gem_request->seqno,
@@ -413,7 +389,7 @@ static void i915_ring_seqno_info(struct seq_file *m,
 {
 	if (ring->get_seqno) {
 		seq_printf(m, "Current sequence (%s): %d\n",
-			   ring->name, ring->get_seqno(ring));
+			   ring->name, ring->get_seqno(ring, false));
 	}
 }
 
@@ -422,14 +398,15 @@ static int i915_gem_seqno_info(struct seq_file *m, void *data)
 	struct drm_info_node *node = (struct drm_info_node *) m->private;
 	struct drm_device *dev = node->minor->dev;
 	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct intel_ring_buffer *ring;
 	int ret, i;
 
 	ret = mutex_lock_interruptible(&dev->struct_mutex);
 	if (ret)
 		return ret;
 
-	for (i = 0; i < I915_NUM_RINGS; i++)
-		i915_ring_seqno_info(m, &dev_priv->ring[i]);
+	for_each_ring(ring, dev_priv, i)
+		i915_ring_seqno_info(m, ring);
 
 	mutex_unlock(&dev->struct_mutex);
 
@@ -442,6 +419,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
 	struct drm_info_node *node = (struct drm_info_node *) m->private;
 	struct drm_device *dev = node->minor->dev;
 	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct intel_ring_buffer *ring;
 	int ret, i, pipe;
 
 	ret = mutex_lock_interruptible(&dev->struct_mutex);
@@ -519,13 +497,13 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
 	}
 	seq_printf(m, "Interrupts received: %d\n",
 		   atomic_read(&dev_priv->irq_received));
-	for (i = 0; i < I915_NUM_RINGS; i++) {
+	for_each_ring(ring, dev_priv, i) {
 		if (IS_GEN6(dev) || IS_GEN7(dev)) {
-			seq_printf(m, "Graphics Interrupt mask (%s):	%08x\n",
-				   dev_priv->ring[i].name,
-				   I915_READ_IMR(&dev_priv->ring[i]));
+			seq_printf(m,
+				   "Graphics Interrupt mask (%s):	%08x\n",
+				   ring->name, I915_READ_IMR(ring));
 		}
-		i915_ring_seqno_info(m, &dev_priv->ring[i]);
+		i915_ring_seqno_info(m, ring);
 	}
 	mutex_unlock(&dev->struct_mutex);
 
@@ -548,7 +526,8 @@ static int i915_gem_fence_regs_info(struct seq_file *m, void *data)
 	for (i = 0; i < dev_priv->num_fence_regs; i++) {
 		struct drm_i915_gem_object *obj = dev_priv->fence_regs[i].obj;
 
-		seq_printf(m, "Fenced object[%2d] = ", i);
+		seq_printf(m, "Fence %d, pin count = %d, object = ",
+			   i, dev_priv->fence_regs[i].pin_count);
 		if (obj == NULL)
 			seq_printf(m, "unused");
 		else
@@ -630,12 +609,12 @@ static void print_error_buffers(struct seq_file *m,
 	seq_printf(m, "%s [%d]:\n", name, count);
 
 	while (count--) {
-		seq_printf(m, "  %08x %8u %04x %04x %08x%s%s%s%s%s%s%s",
+		seq_printf(m, "  %08x %8u %04x %04x %x %x%s%s%s%s%s%s%s",
 			   err->gtt_offset,
 			   err->size,
 			   err->read_domains,
 			   err->write_domain,
-			   err->seqno,
+			   err->rseqno, err->wseqno,
 			   pin_flag(err->pinned),
 			   tiling_flag(err->tiling),
 			   dirty_flag(err->dirty),
@@ -667,10 +646,9 @@ static void i915_ring_error_state(struct seq_file *m,
 	seq_printf(m, "  IPEIR: 0x%08x\n", error->ipeir[ring]);
 	seq_printf(m, "  IPEHR: 0x%08x\n", error->ipehr[ring]);
 	seq_printf(m, "  INSTDONE: 0x%08x\n", error->instdone[ring]);
-	if (ring == RCS && INTEL_INFO(dev)->gen >= 4) {
-		seq_printf(m, "  INSTDONE1: 0x%08x\n", error->instdone1);
+	if (ring == RCS && INTEL_INFO(dev)->gen >= 4)
 		seq_printf(m, "  BBADDR: 0x%08llx\n", error->bbaddr);
-	}
+
 	if (INTEL_INFO(dev)->gen >= 4)
 		seq_printf(m, "  INSTPS: 0x%08x\n", error->instps[ring]);
 	seq_printf(m, "  INSTPM: 0x%08x\n", error->instpm[ring]);
@@ -719,11 +697,17 @@ static int i915_error_state(struct seq_file *m, void *unused)
 	for (i = 0; i < dev_priv->num_fence_regs; i++)
 		seq_printf(m, "  fence[%d] = %08llx\n", i, error->fence[i]);
 
+	for (i = 0; i < ARRAY_SIZE(error->extra_instdone); i++)
+		seq_printf(m, "  INSTDONE_%d: 0x%08x\n", i, error->extra_instdone[i]);
+
 	if (INTEL_INFO(dev)->gen >= 6) {
 		seq_printf(m, "ERROR: 0x%08x\n", error->error);
 		seq_printf(m, "DONE_REG: 0x%08x\n", error->done_reg);
 	}
 
+	if (INTEL_INFO(dev)->gen == 7)
+		seq_printf(m, "ERR_INT: 0x%08x\n", error->err_int);
+
 	for_each_ring(ring, dev_priv, i)
 		i915_ring_error_state(m, dev, error, i);
 
@@ -799,10 +783,14 @@ i915_error_state_write(struct file *filp,
 	struct seq_file *m = filp->private_data;
 	struct i915_error_state_file_priv *error_priv = m->private;
 	struct drm_device *dev = error_priv->dev;
+	int ret;
 
 	DRM_DEBUG_DRIVER("Resetting error state\n");
 
-	mutex_lock(&dev->struct_mutex);
+	ret = mutex_lock_interruptible(&dev->struct_mutex);
+	if (ret)
+		return ret;
+
 	i915_destroy_error_state(dev);
 	mutex_unlock(&dev->struct_mutex);
 
@@ -1292,7 +1280,8 @@ static int i915_ring_freq_table(struct seq_file *m, void *unused)
 
 	seq_printf(m, "GPU freq (MHz)\tEffective CPU freq (MHz)\n");
 
-	for (gpu_freq = dev_priv->min_delay; gpu_freq <= dev_priv->max_delay;
+	for (gpu_freq = dev_priv->rps.min_delay;
+	     gpu_freq <= dev_priv->rps.max_delay;
 	     gpu_freq++) {
 		I915_WRITE(GEN6_PCODE_DATA, gpu_freq);
 		I915_WRITE(GEN6_PCODE_MAILBOX, GEN6_PCODE_READY |
@@ -1472,8 +1461,12 @@ static int i915_swizzle_info(struct seq_file *m, void *data)
 	struct drm_info_node *node = (struct drm_info_node *) m->private;
 	struct drm_device *dev = node->minor->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	int ret;
+
+	ret = mutex_lock_interruptible(&dev->struct_mutex);
+	if (ret)
+		return ret;
 
-	mutex_lock(&dev->struct_mutex);
 	seq_printf(m, "bit6 swizzle for X-tiling = %s\n",
 		   swizzle_string(dev_priv->mm.bit_6_swizzle_x));
 	seq_printf(m, "bit6 swizzle for Y-tiling = %s\n",
@@ -1520,9 +1513,7 @@ static int i915_ppgtt_info(struct seq_file *m, void *data)
 	if (INTEL_INFO(dev)->gen == 6)
 		seq_printf(m, "GFX_MODE: 0x%08x\n", I915_READ(GFX_MODE));
 
-	for (i = 0; i < I915_NUM_RINGS; i++) {
-		ring = &dev_priv->ring[i];
-
+	for_each_ring(ring, dev_priv, i) {
 		seq_printf(m, "%s\n", ring->name);
 		if (INTEL_INFO(dev)->gen == 7)
 			seq_printf(m, "GFX_MODE: 0x%08x\n", I915_READ(RING_MODE_GEN7(ring)));
@@ -1674,7 +1665,7 @@ i915_ring_stop_write(struct file *filp,
 	struct drm_device *dev = filp->private_data;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	char buf[20];
-	int val = 0;
+	int val = 0, ret;
 
 	if (cnt > 0) {
 		if (cnt > sizeof(buf) - 1)
@@ -1689,7 +1680,10 @@ i915_ring_stop_write(struct file *filp,
 
 	DRM_DEBUG_DRIVER("Stopping rings 0x%08x\n", val);
 
-	mutex_lock(&dev->struct_mutex);
+	ret = mutex_lock_interruptible(&dev->struct_mutex);
+	if (ret)
+		return ret;
+
 	dev_priv->stop_rings = val;
 	mutex_unlock(&dev->struct_mutex);
 
@@ -1713,10 +1707,18 @@ i915_max_freq_read(struct file *filp,
 	struct drm_device *dev = filp->private_data;
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	char buf[80];
-	int len;
+	int len, ret;
+
+	if (!(IS_GEN6(dev) || IS_GEN7(dev)))
+		return -ENODEV;
+
+	ret = mutex_lock_interruptible(&dev->struct_mutex);
+	if (ret)
+		return ret;
 
 	len = snprintf(buf, sizeof(buf),
-		       "max freq: %d\n", dev_priv->max_delay * 50);
+		       "max freq: %d\n", dev_priv->rps.max_delay * 50);
+	mutex_unlock(&dev->struct_mutex);
 
 	if (len > sizeof(buf))
 		len = sizeof(buf);
@@ -1733,7 +1735,10 @@ i915_max_freq_write(struct file *filp,
 	struct drm_device *dev = filp->private_data;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	char buf[20];
-	int val = 1;
+	int val = 1, ret;
+
+	if (!(IS_GEN6(dev) || IS_GEN7(dev)))
+		return -ENODEV;
 
 	if (cnt > 0) {
 		if (cnt > sizeof(buf) - 1)
@@ -1748,12 +1753,17 @@ i915_max_freq_write(struct file *filp,
 
 	DRM_DEBUG_DRIVER("Manually setting max freq to %d\n", val);
 
+	ret = mutex_lock_interruptible(&dev->struct_mutex);
+	if (ret)
+		return ret;
+
 	/*
 	 * Turbo will still be enabled, but won't go above the set value.
 	 */
-	dev_priv->max_delay = val / 50;
+	dev_priv->rps.max_delay = val / 50;
 
 	gen6_set_rps(dev, val / 50);
+	mutex_unlock(&dev->struct_mutex);
 
 	return cnt;
 }
@@ -1773,10 +1783,18 @@ i915_min_freq_read(struct file *filp, char __user *ubuf, size_t max,
 	struct drm_device *dev = filp->private_data;
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	char buf[80];
-	int len;
+	int len, ret;
+
+	if (!(IS_GEN6(dev) || IS_GEN7(dev)))
+		return -ENODEV;
+
+	ret = mutex_lock_interruptible(&dev->struct_mutex);
+	if (ret)
+		return ret;
 
 	len = snprintf(buf, sizeof(buf),
-		       "min freq: %d\n", dev_priv->min_delay * 50);
+		       "min freq: %d\n", dev_priv->rps.min_delay * 50);
+	mutex_unlock(&dev->struct_mutex);
 
 	if (len > sizeof(buf))
 		len = sizeof(buf);
@@ -1791,7 +1809,10 @@ i915_min_freq_write(struct file *filp, const char __user *ubuf, size_t cnt,
 	struct drm_device *dev = filp->private_data;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	char buf[20];
-	int val = 1;
+	int val = 1, ret;
+
+	if (!(IS_GEN6(dev) || IS_GEN7(dev)))
+		return -ENODEV;
 
 	if (cnt > 0) {
 		if (cnt > sizeof(buf) - 1)
@@ -1806,12 +1827,17 @@ i915_min_freq_write(struct file *filp, const char __user *ubuf, size_t cnt,
 
 	DRM_DEBUG_DRIVER("Manually setting min freq to %d\n", val);
 
+	ret = mutex_lock_interruptible(&dev->struct_mutex);
+	if (ret)
+		return ret;
+
 	/*
 	 * Turbo will still be enabled, but won't go below the set value.
 	 */
-	dev_priv->min_delay = val / 50;
+	dev_priv->rps.min_delay = val / 50;
 
 	gen6_set_rps(dev, val / 50);
+	mutex_unlock(&dev->struct_mutex);
 
 	return cnt;
 }
@@ -1834,9 +1860,15 @@ i915_cache_sharing_read(struct file *filp,
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	char buf[80];
 	u32 snpcr;
-	int len;
+	int len, ret;
+
+	if (!(IS_GEN6(dev) || IS_GEN7(dev)))
+		return -ENODEV;
+
+	ret = mutex_lock_interruptible(&dev->struct_mutex);
+	if (ret)
+		return ret;
 
-	mutex_lock(&dev_priv->dev->struct_mutex);
 	snpcr = I915_READ(GEN6_MBCUNIT_SNPCR);
 	mutex_unlock(&dev_priv->dev->struct_mutex);
 
@@ -1862,6 +1894,9 @@ i915_cache_sharing_write(struct file *filp,
 	u32 snpcr;
 	int val = 1;
 
+	if (!(IS_GEN6(dev) || IS_GEN7(dev)))
+		return -ENODEV;
+
 	if (cnt > 0) {
 		if (cnt > sizeof(buf) - 1)
 			return -EINVAL;
@@ -1925,16 +1960,11 @@ static int i915_forcewake_open(struct inode *inode, struct file *file)
 {
 	struct drm_device *dev = inode->i_private;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	int ret;
 
 	if (INTEL_INFO(dev)->gen < 6)
 		return 0;
 
-	ret = mutex_lock_interruptible(&dev->struct_mutex);
-	if (ret)
-		return ret;
 	gen6_gt_force_wake_get(dev_priv);
-	mutex_unlock(&dev->struct_mutex);
 
 	return 0;
 }
@@ -1947,16 +1977,7 @@ static int i915_forcewake_release(struct inode *inode, struct file *file)
 	if (INTEL_INFO(dev)->gen < 6)
 		return 0;
 
-	/*
-	 * It's bad that we can potentially hang userspace if struct_mutex gets
-	 * forever stuck.  However, if we cannot acquire this lock it means that
-	 * almost certainly the driver has hung, is not unload-able. Therefore
-	 * hanging here is probably a minor inconvenience not to be seen my
-	 * almost every user.
-	 */
-	mutex_lock(&dev->struct_mutex);
 	gen6_gt_force_wake_put(dev_priv);
-	mutex_unlock(&dev->struct_mutex);
 
 	return 0;
 }
@@ -2006,7 +2027,6 @@ static struct drm_info_list i915_debugfs_list[] = {
 	{"i915_gem_gtt", i915_gem_gtt_info, 0},
 	{"i915_gem_pinned", i915_gem_gtt_info, 0, (void *) PINNED_LIST},
 	{"i915_gem_active", i915_gem_object_list_info, 0, (void *) ACTIVE_LIST},
-	{"i915_gem_flushing", i915_gem_object_list_info, 0, (void *) FLUSHING_LIST},
 	{"i915_gem_inactive", i915_gem_object_list_info, 0, (void *) INACTIVE_LIST},
 	{"i915_gem_pageflip", i915_gem_pageflip_info, 0},
 	{"i915_gem_request", i915_gem_request_info, 0},
@@ -2067,6 +2087,7 @@ int i915_debugfs_init(struct drm_minor *minor)
 				  &i915_cache_sharing_fops);
 	if (ret)
 		return ret;
+
 	ret = i915_debugfs_create(minor->debugfs_root, minor,
 				  "i915_ring_stop",
 				  &i915_ring_stop_fops);
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 914c0df..8bd7c9a 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -235,10 +235,10 @@ static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init)
 		}
 	}
 
-	dev_priv->cpp = init->cpp;
-	dev_priv->back_offset = init->back_offset;
-	dev_priv->front_offset = init->front_offset;
-	dev_priv->current_page = 0;
+	dev_priv->dri1.cpp = init->cpp;
+	dev_priv->dri1.back_offset = init->back_offset;
+	dev_priv->dri1.front_offset = init->front_offset;
+	dev_priv->dri1.current_page = 0;
 	if (master_priv->sarea_priv)
 		master_priv->sarea_priv->pf_current_page = 0;
 
@@ -575,7 +575,7 @@ static int i915_dispatch_flip(struct drm_device * dev)
 
 	DRM_DEBUG_DRIVER("%s: page=%d pfCurrentPage=%d\n",
 			  __func__,
-			 dev_priv->current_page,
+			 dev_priv->dri1.current_page,
 			 master_priv->sarea_priv->pf_current_page);
 
 	i915_kernel_lost_context(dev);
@@ -589,12 +589,12 @@ static int i915_dispatch_flip(struct drm_device * dev)
 
 	OUT_RING(CMD_OP_DISPLAYBUFFER_INFO | ASYNC_FLIP);
 	OUT_RING(0);
-	if (dev_priv->current_page == 0) {
-		OUT_RING(dev_priv->back_offset);
-		dev_priv->current_page = 1;
+	if (dev_priv->dri1.current_page == 0) {
+		OUT_RING(dev_priv->dri1.back_offset);
+		dev_priv->dri1.current_page = 1;
 	} else {
-		OUT_RING(dev_priv->front_offset);
-		dev_priv->current_page = 0;
+		OUT_RING(dev_priv->dri1.front_offset);
+		dev_priv->dri1.current_page = 0;
 	}
 	OUT_RING(0);
 
@@ -613,7 +613,7 @@ static int i915_dispatch_flip(struct drm_device * dev)
 		ADVANCE_LP_RING();
 	}
 
-	master_priv->sarea_priv->pf_current_page = dev_priv->current_page;
+	master_priv->sarea_priv->pf_current_page = dev_priv->dri1.current_page;
 	return 0;
 }
 
@@ -1009,6 +1009,12 @@ static int i915_getparam(struct drm_device *dev, void *data,
 	case I915_PARAM_HAS_WAIT_TIMEOUT:
 		value = 1;
 		break;
+	case I915_PARAM_HAS_SEMAPHORES:
+		value = i915_semaphore_is_enabled(dev);
+		break;
+	case I915_PARAM_HAS_PRIME_VMAP_FLUSH:
+		value = 1;
+		break;
 	default:
 		DRM_DEBUG_DRIVER("Unknown parameter %d\n",
 				 param->param);
@@ -1425,6 +1431,21 @@ static void i915_kick_out_firmware_fb(struct drm_i915_private *dev_priv)
 	kfree(ap);
 }
 
+static void i915_dump_device_info(struct drm_i915_private *dev_priv)
+{
+	const struct intel_device_info *info = dev_priv->info;
+
+#define DEV_INFO_FLAG(name) info->name ? #name "," : ""
+#define DEV_INFO_SEP ,
+	DRM_DEBUG_DRIVER("i915 device info: gen=%i, pciid=0x%04x flags="
+			 "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
+			 info->gen,
+			 dev_priv->dev->pdev->device,
+			 DEV_INFO_FLAGS);
+#undef DEV_INFO_FLAG
+#undef DEV_INFO_SEP
+}
+
 /**
  * i915_driver_load - setup chip and create an initial config
  * @dev: DRM device
@@ -1449,7 +1470,6 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 	if (info->gen >= 6 && !drm_core_check_feature(dev, DRIVER_MODESET))
 		return -ENODEV;
 
-
 	/* i915 has 4 more counters */
 	dev->counters += 4;
 	dev->types[6] = _DRM_STAT_IRQ;
@@ -1465,6 +1485,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 	dev_priv->dev = dev;
 	dev_priv->info = info;
 
+	i915_dump_device_info(dev_priv);
+
 	if (i915_get_bridge_dev(dev)) {
 		ret = -EIO;
 		goto free_priv;
@@ -1536,11 +1558,9 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 	 *
 	 * All tasks on the workqueue are expected to acquire the dev mutex
 	 * so there is no point in running more than one instance of the
-	 * workqueue at any time: max_active = 1 and NON_REENTRANT.
+	 * workqueue at any time.  Use an ordered one.
 	 */
-	dev_priv->wq = alloc_workqueue("i915",
-				       WQ_UNBOUND | WQ_NON_REENTRANT,
-				       1);
+	dev_priv->wq = alloc_ordered_workqueue("i915", 0);
 	if (dev_priv->wq == NULL) {
 		DRM_ERROR("Failed to create our workqueue.\n");
 		ret = -ENOMEM;
@@ -1586,7 +1606,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 
 	spin_lock_init(&dev_priv->irq_lock);
 	spin_lock_init(&dev_priv->error_lock);
-	spin_lock_init(&dev_priv->rps_lock);
+	spin_lock_init(&dev_priv->rps.lock);
 	spin_lock_init(&dev_priv->dpio_lock);
 
 	if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev))
@@ -1836,6 +1856,8 @@ struct drm_ioctl_desc i915_ioctls[] = {
 	DRM_IOCTL_DEF_DRV(I915_GEM_PIN, i915_gem_pin_ioctl, DRM_AUTH|DRM_ROOT_ONLY|DRM_UNLOCKED),
 	DRM_IOCTL_DEF_DRV(I915_GEM_UNPIN, i915_gem_unpin_ioctl, DRM_AUTH|DRM_ROOT_ONLY|DRM_UNLOCKED),
 	DRM_IOCTL_DEF_DRV(I915_GEM_BUSY, i915_gem_busy_ioctl, DRM_AUTH|DRM_UNLOCKED),
+	DRM_IOCTL_DEF_DRV(I915_GEM_SET_CACHEING, i915_gem_set_cacheing_ioctl, DRM_UNLOCKED),
+	DRM_IOCTL_DEF_DRV(I915_GEM_GET_CACHEING, i915_gem_get_cacheing_ioctl, DRM_UNLOCKED),
 	DRM_IOCTL_DEF_DRV(I915_GEM_THROTTLE, i915_gem_throttle_ioctl, DRM_AUTH|DRM_UNLOCKED),
 	DRM_IOCTL_DEF_DRV(I915_GEM_ENTERVT, i915_gem_entervt_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED),
 	DRM_IOCTL_DEF_DRV(I915_GEM_LEAVEVT, i915_gem_leavevt_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED),
@@ -1858,6 +1880,7 @@ struct drm_ioctl_desc i915_ioctls[] = {
 	DRM_IOCTL_DEF_DRV(I915_GEM_WAIT, i915_gem_wait_ioctl, DRM_AUTH|DRM_UNLOCKED),
 	DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_CREATE, i915_gem_context_create_ioctl, DRM_UNLOCKED),
 	DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_DESTROY, i915_gem_context_destroy_ioctl, DRM_UNLOCKED),
+	DRM_IOCTL_DEF_DRV(I915_REG_READ, i915_reg_read_ioctl, DRM_UNLOCKED),
 };
 
 int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index a24ffbe..a7837e5 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -470,6 +470,9 @@ static int i915_drm_freeze(struct drm_device *dev)
 				"GEM idle failed, resume might fail\n");
 			return error;
 		}
+
+		intel_modeset_disable(dev);
+
 		drm_irq_uninstall(dev);
 	}
 
@@ -543,13 +546,9 @@ static int i915_drm_thaw(struct drm_device *dev)
 		mutex_unlock(&dev->struct_mutex);
 
 		intel_modeset_init_hw(dev);
+		intel_modeset_setup_hw_state(dev);
 		drm_mode_config_reset(dev);
 		drm_irq_install(dev);
-
-		/* Resume the modeset for every activated CRTC */
-		mutex_lock(&dev->mode_config.mutex);
-		drm_helper_resume_force_mode(dev);
-		mutex_unlock(&dev->mode_config.mutex);
 	}
 
 	intel_opregion_init(dev);
@@ -1060,7 +1059,7 @@ static bool IS_DISPLAYREG(u32 reg)
 	 * This should make it easier to transition modules over to the
 	 * new register block scheme, since we can do it incrementally.
 	 */
-	if (reg >= 0x180000)
+	if (reg >= VLV_DISPLAY_BASE)
 		return false;
 
 	if (reg >= RENDER_RING_BASE &&
@@ -1174,9 +1173,59 @@ void i915_write##x(struct drm_i915_private *dev_priv, u32 reg, u##x val) { \
 	if (unlikely(__fifo_ret)) { \
 		gen6_gt_check_fifodbg(dev_priv); \
 	} \
+	if (IS_HASWELL(dev_priv->dev) && (I915_READ_NOTRACE(GEN7_ERR_INT) & ERR_INT_MMIO_UNCLAIMED)) { \
+		DRM_ERROR("Unclaimed write to %x\n", reg); \
+		writel(ERR_INT_MMIO_UNCLAIMED, dev_priv->regs + GEN7_ERR_INT);	\
+	} \
 }
 __i915_write(8, b)
 __i915_write(16, w)
 __i915_write(32, l)
 __i915_write(64, q)
 #undef __i915_write
+
+static const struct register_whitelist {
+	uint64_t offset;
+	uint32_t size;
+	uint32_t gen_bitmask; /* support gens, 0x10 for 4, 0x30 for 4 and 5, etc. */
+} whitelist[] = {
+	{ RING_TIMESTAMP(RENDER_RING_BASE), 8, 0xF0 },
+};
+
+int i915_reg_read_ioctl(struct drm_device *dev,
+			void *data, struct drm_file *file)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_reg_read *reg = data;
+	struct register_whitelist const *entry = whitelist;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(whitelist); i++, entry++) {
+		if (entry->offset == reg->offset &&
+		    (1 << INTEL_INFO(dev)->gen & entry->gen_bitmask))
+			break;
+	}
+
+	if (i == ARRAY_SIZE(whitelist))
+		return -EINVAL;
+
+	switch (entry->size) {
+	case 8:
+		reg->val = I915_READ64(reg->offset);
+		break;
+	case 4:
+		reg->val = I915_READ(reg->offset);
+		break;
+	case 2:
+		reg->val = I915_READ16(reg->offset);
+		break;
+	case 1:
+		reg->val = I915_READ8(reg->offset);
+		break;
+	default:
+		WARN_ON(1);
+		return -EINVAL;
+	}
+
+	return 0;
+}
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 627fe35..26c6959 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -109,6 +109,7 @@ struct intel_pch_pll {
 
 #define WATCH_COHERENCY	0
 #define WATCH_LISTS	0
+#define WATCH_GTT	0
 
 #define I915_GEM_PHYS_CURSOR_0 1
 #define I915_GEM_PHYS_CURSOR_1 2
@@ -195,9 +196,10 @@ struct drm_i915_error_state {
 	u32 cpu_ring_head[I915_NUM_RINGS];
 	u32 cpu_ring_tail[I915_NUM_RINGS];
 	u32 error; /* gen6+ */
+	u32 err_int; /* gen7 */
 	u32 instpm[I915_NUM_RINGS];
 	u32 instps[I915_NUM_RINGS];
-	u32 instdone1;
+	u32 extra_instdone[I915_NUM_INSTDONE_REG];
 	u32 seqno[I915_NUM_RINGS];
 	u64 bbaddr;
 	u32 fault_reg[I915_NUM_RINGS];
@@ -221,7 +223,7 @@ struct drm_i915_error_state {
 	struct drm_i915_error_buffer {
 		u32 size;
 		u32 name;
-		u32 seqno;
+		u32 rseqno, wseqno;
 		u32 gtt_offset;
 		u32 read_domains;
 		u32 write_domain;
@@ -239,7 +241,6 @@ struct drm_i915_error_state {
 };
 
 struct drm_i915_display_funcs {
-	void (*dpms)(struct drm_crtc *crtc, int mode);
 	bool (*fbc_enabled)(struct drm_device *dev);
 	void (*enable_fbc)(struct drm_crtc *crtc, unsigned long interval);
 	void (*disable_fbc)(struct drm_device *dev);
@@ -248,7 +249,6 @@ struct drm_i915_display_funcs {
 	void (*update_wm)(struct drm_device *dev);
 	void (*update_sprite_wm)(struct drm_device *dev, int pipe,
 				 uint32_t sprite_width, int pixel_size);
-	void (*sanitize_pm)(struct drm_device *dev);
 	void (*update_linetime_wm)(struct drm_device *dev, int pipe,
 				 struct drm_display_mode *mode);
 	int (*crtc_mode_set)(struct drm_crtc *crtc,
@@ -256,6 +256,8 @@ struct drm_i915_display_funcs {
 			     struct drm_display_mode *adjusted_mode,
 			     int x, int y,
 			     struct drm_framebuffer *old_fb);
+	void (*crtc_enable)(struct drm_crtc *crtc);
+	void (*crtc_disable)(struct drm_crtc *crtc);
 	void (*off)(struct drm_crtc *crtc);
 	void (*write_eld)(struct drm_connector *connector,
 			  struct drm_crtc *crtc);
@@ -279,6 +281,32 @@ struct drm_i915_gt_funcs {
 	void (*force_wake_put)(struct drm_i915_private *dev_priv);
 };
 
+#define DEV_INFO_FLAGS \
+	DEV_INFO_FLAG(is_mobile) DEV_INFO_SEP \
+	DEV_INFO_FLAG(is_i85x) DEV_INFO_SEP \
+	DEV_INFO_FLAG(is_i915g) DEV_INFO_SEP \
+	DEV_INFO_FLAG(is_i945gm) DEV_INFO_SEP \
+	DEV_INFO_FLAG(is_g33) DEV_INFO_SEP \
+	DEV_INFO_FLAG(need_gfx_hws) DEV_INFO_SEP \
+	DEV_INFO_FLAG(is_g4x) DEV_INFO_SEP \
+	DEV_INFO_FLAG(is_pineview) DEV_INFO_SEP \
+	DEV_INFO_FLAG(is_broadwater) DEV_INFO_SEP \
+	DEV_INFO_FLAG(is_crestline) DEV_INFO_SEP \
+	DEV_INFO_FLAG(is_ivybridge) DEV_INFO_SEP \
+	DEV_INFO_FLAG(is_valleyview) DEV_INFO_SEP \
+	DEV_INFO_FLAG(is_haswell) DEV_INFO_SEP \
+	DEV_INFO_FLAG(has_force_wake) DEV_INFO_SEP \
+	DEV_INFO_FLAG(has_fbc) DEV_INFO_SEP \
+	DEV_INFO_FLAG(has_pipe_cxsr) DEV_INFO_SEP \
+	DEV_INFO_FLAG(has_hotplug) DEV_INFO_SEP \
+	DEV_INFO_FLAG(cursor_needs_physical) DEV_INFO_SEP \
+	DEV_INFO_FLAG(has_overlay) DEV_INFO_SEP \
+	DEV_INFO_FLAG(overlay_needs_physical) DEV_INFO_SEP \
+	DEV_INFO_FLAG(supports_tv) DEV_INFO_SEP \
+	DEV_INFO_FLAG(has_bsd_ring) DEV_INFO_SEP \
+	DEV_INFO_FLAG(has_blt_ring) DEV_INFO_SEP \
+	DEV_INFO_FLAG(has_llc)
+
 struct intel_device_info {
 	u8 gen;
 	u8 is_mobile:1;
@@ -402,12 +430,6 @@ typedef struct drm_i915_private {
 
 	struct resource mch_res;
 
-	unsigned int cpp;
-	int back_offset;
-	int front_offset;
-	int current_page;
-	int page_flipping;
-
 	atomic_t irq_received;
 
 	/* protects the irq masks */
@@ -425,7 +447,6 @@ typedef struct drm_i915_private {
 	u32 hotplug_supported_mask;
 	struct work_struct hotplug_work;
 
-	unsigned int sr01, adpa, ppcr, dvob, dvoc, lvds;
 	int num_pipe;
 	int num_pch_pll;
 
@@ -434,8 +455,7 @@ typedef struct drm_i915_private {
 	struct timer_list hangcheck_timer;
 	int hangcheck_count;
 	uint32_t last_acthd[I915_NUM_RINGS];
-	uint32_t last_instdone;
-	uint32_t last_instdone1;
+	uint32_t prev_instdone[I915_NUM_INSTDONE_REG];
 
 	unsigned int stop_rings;
 
@@ -666,7 +686,13 @@ typedef struct drm_i915_private {
 		struct drm_mm gtt_space;
 		/** List of all objects in gtt_space. Used to restore gtt
 		 * mappings on resume */
-		struct list_head gtt_list;
+		struct list_head bound_list;
+		/**
+		 * List of objects which are not bound to the GTT (thus
+		 * are idle and not used by the GPU) but still have
+		 * (presumably uncached) pages still attached.
+		 */
+		struct list_head unbound_list;
 
 		/** Usable portion of the GTT for GEM */
 		unsigned long gtt_start;
@@ -696,17 +722,6 @@ typedef struct drm_i915_private {
 		struct list_head active_list;
 
 		/**
-		 * List of objects which are not in the ringbuffer but which
-		 * still have a write_domain which needs to be flushed before
-		 * unbinding.
-		 *
-		 * last_rendering_seqno is 0 while an object is in this list.
-		 *
-		 * A reference is held on the buffer while on this list.
-		 */
-		struct list_head flushing_list;
-
-		/**
 		 * LRU list of objects which are not in the ringbuffer and
 		 * are ready to unbind, but are still in the GTT.
 		 *
@@ -775,6 +790,12 @@ typedef struct drm_i915_private {
 	struct {
 		unsigned allow_batchbuffer : 1;
 		u32 __iomem *gfx_hws_cpu_addr;
+
+		unsigned int cpp;
+		int back_offset;
+		int front_offset;
+		int current_page;
+		int page_flipping;
 	} dri1;
 
 	/* Kernel Modesetting */
@@ -796,9 +817,6 @@ typedef struct drm_i915_private {
 	bool lvds_downclock_avail;
 	/* indicates the reduced downclock for LVDS*/
 	int lvds_downclock;
-	struct work_struct idle_work;
-	struct timer_list idle_timer;
-	bool busy;
 	u16 orig_clock;
 	int child_dev_num;
 	struct child_device_config *child_dev;
@@ -807,26 +825,41 @@ typedef struct drm_i915_private {
 
 	bool mchbar_need_disable;
 
-	struct work_struct rps_work;
-	spinlock_t rps_lock;
-	u32 pm_iir;
-
-	u8 cur_delay;
-	u8 min_delay;
-	u8 max_delay;
-	u8 fmax;
-	u8 fstart;
-
-	u64 last_count1;
-	unsigned long last_time1;
-	unsigned long chipset_power;
-	u64 last_count2;
-	struct timespec last_time2;
-	unsigned long gfx_power;
-	int c_m;
-	int r_t;
-	u8 corr;
-	spinlock_t *mchdev_lock;
+	/* gen6+ rps state */
+	struct {
+		struct work_struct work;
+		u32 pm_iir;
+		/* lock - irqsave spinlock that protectects the work_struct and
+		 * pm_iir. */
+		spinlock_t lock;
+
+		/* The below variables an all the rps hw state are protected by
+		 * dev->struct mutext. */
+		u8 cur_delay;
+		u8 min_delay;
+		u8 max_delay;
+	} rps;
+
+	/* ilk-only ips/rps state. Everything in here is protected by the global
+	 * mchdev_lock in intel_pm.c */
+	struct {
+		u8 cur_delay;
+		u8 min_delay;
+		u8 max_delay;
+		u8 fmax;
+		u8 fstart;
+
+		u64 last_count1;
+		unsigned long last_time1;
+		unsigned long chipset_power;
+		u64 last_count2;
+		struct timespec last_time2;
+		unsigned long gfx_power;
+		u8 corr;
+
+		int c_m;
+		int r_t;
+	} ips;
 
 	enum no_fbc_reason no_fbc_reason;
 
@@ -861,9 +894,9 @@ enum hdmi_force_audio {
 };
 
 enum i915_cache_level {
-	I915_CACHE_NONE,
+	I915_CACHE_NONE = 0,
 	I915_CACHE_LLC,
-	I915_CACHE_LLC_MLC, /* gen6+ */
+	I915_CACHE_LLC_MLC, /* gen6+, in docs at least! */
 };
 
 struct drm_i915_gem_object {
@@ -873,18 +906,16 @@ struct drm_i915_gem_object {
 	struct drm_mm_node *gtt_space;
 	struct list_head gtt_list;
 
-	/** This object's place on the active/flushing/inactive lists */
+	/** This object's place on the active/inactive lists */
 	struct list_head ring_list;
 	struct list_head mm_list;
-	/** This object's place on GPU write list */
-	struct list_head gpu_write_list;
 	/** This object's place in the batchbuffer or on the eviction list */
 	struct list_head exec_list;
 
 	/**
-	 * This is set if the object is on the active or flushing lists
-	 * (has pending rendering), and is not set if it's on inactive (ready
-	 * to be unbound).
+	 * This is set if the object is on the active lists (has pending
+	 * rendering and so a non-zero seqno), and is not set if it i s on
+	 * inactive (ready to be unbound) list.
 	 */
 	unsigned int active:1;
 
@@ -895,12 +926,6 @@ struct drm_i915_gem_object {
 	unsigned int dirty:1;
 
 	/**
-	 * This is set if the object has been written to since the last
-	 * GPU flush.
-	 */
-	unsigned int pending_gpu_write:1;
-
-	/**
 	 * Fence register bits (if any) for this object.  Will be set
 	 * as needed when mapped into the GTT.
 	 * Protected by dev->struct_mutex.
@@ -992,7 +1017,8 @@ struct drm_i915_gem_object {
 	struct intel_ring_buffer *ring;
 
 	/** Breadcrumb of last rendering to the buffer. */
-	uint32_t last_rendering_seqno;
+	uint32_t last_read_seqno;
+	uint32_t last_write_seqno;
 	/** Breadcrumb of last fenced GPU access to the buffer. */
 	uint32_t last_fenced_seqno;
 
@@ -1135,6 +1161,8 @@ struct drm_i915_file_private {
 
 #define HAS_FORCE_WAKE(dev) (INTEL_INFO(dev)->has_force_wake)
 
+#define HAS_L3_GPU_CACHE(dev) (IS_IVYBRIDGE(dev) || IS_HASWELL(dev))
+
 #include "i915_trace.h"
 
 /**
@@ -1256,6 +1284,10 @@ int i915_gem_unpin_ioctl(struct drm_device *dev, void *data,
 			 struct drm_file *file_priv);
 int i915_gem_busy_ioctl(struct drm_device *dev, void *data,
 			struct drm_file *file_priv);
+int i915_gem_get_cacheing_ioctl(struct drm_device *dev, void *data,
+				struct drm_file *file);
+int i915_gem_set_cacheing_ioctl(struct drm_device *dev, void *data,
+				struct drm_file *file);
 int i915_gem_throttle_ioctl(struct drm_device *dev, void *data,
 			    struct drm_file *file_priv);
 int i915_gem_madvise_ioctl(struct drm_device *dev, void *data,
@@ -1274,24 +1306,21 @@ int i915_gem_wait_ioctl(struct drm_device *dev, void *data,
 			struct drm_file *file_priv);
 void i915_gem_load(struct drm_device *dev);
 int i915_gem_init_object(struct drm_gem_object *obj);
-int __must_check i915_gem_flush_ring(struct intel_ring_buffer *ring,
-				     uint32_t invalidate_domains,
-				     uint32_t flush_domains);
+void i915_gem_object_init(struct drm_i915_gem_object *obj);
 struct drm_i915_gem_object *i915_gem_alloc_object(struct drm_device *dev,
 						  size_t size);
 void i915_gem_free_object(struct drm_gem_object *obj);
 int __must_check i915_gem_object_pin(struct drm_i915_gem_object *obj,
 				     uint32_t alignment,
-				     bool map_and_fenceable);
+				     bool map_and_fenceable,
+				     bool nonblocking);
 void i915_gem_object_unpin(struct drm_i915_gem_object *obj);
 int __must_check i915_gem_object_unbind(struct drm_i915_gem_object *obj);
 void i915_gem_release_mmap(struct drm_i915_gem_object *obj);
 void i915_gem_lastclose(struct drm_device *dev);
 
-int i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj,
-				  gfp_t gfpmask);
+int __must_check i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj);
 int __must_check i915_mutex_lock_interruptible(struct drm_device *dev);
-int __must_check i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj);
 int i915_gem_object_sync(struct drm_i915_gem_object *obj,
 			 struct intel_ring_buffer *to);
 void i915_gem_object_move_to_active(struct drm_i915_gem_object *obj,
@@ -1358,9 +1387,9 @@ void i915_gem_init_ppgtt(struct drm_device *dev);
 void i915_gem_cleanup_ringbuffer(struct drm_device *dev);
 int __must_check i915_gpu_idle(struct drm_device *dev);
 int __must_check i915_gem_idle(struct drm_device *dev);
-int __must_check i915_add_request(struct intel_ring_buffer *ring,
-				  struct drm_file *file,
-				  struct drm_i915_gem_request *request);
+int i915_add_request(struct intel_ring_buffer *ring,
+		     struct drm_file *file,
+		     struct drm_i915_gem_request *request);
 int __must_check i915_wait_seqno(struct intel_ring_buffer *ring,
 				 uint32_t seqno);
 int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
@@ -1429,8 +1458,11 @@ void i915_gem_init_global_gtt(struct drm_device *dev,
 
 /* i915_gem_evict.c */
 int __must_check i915_gem_evict_something(struct drm_device *dev, int min_size,
-					  unsigned alignment, bool mappable);
-int i915_gem_evict_everything(struct drm_device *dev, bool purgeable_only);
+					  unsigned alignment,
+					  unsigned cache_level,
+					  bool mappable,
+					  bool nonblock);
+int i915_gem_evict_everything(struct drm_device *dev);
 
 /* i915_gem_stolen.c */
 int i915_gem_init_stolen(struct drm_device *dev);
@@ -1519,6 +1551,7 @@ extern void intel_modeset_init(struct drm_device *dev);
 extern void intel_modeset_gem_init(struct drm_device *dev);
 extern void intel_modeset_cleanup(struct drm_device *dev);
 extern int intel_modeset_vga_set_state(struct drm_device *dev, bool state);
+extern void intel_modeset_setup_hw_state(struct drm_device *dev);
 extern bool intel_fbc_enabled(struct drm_device *dev);
 extern void intel_disable_fbc(struct drm_device *dev);
 extern bool ironlake_set_drps(struct drm_device *dev, u8 val);
@@ -1529,6 +1562,8 @@ extern int intel_trans_dp_port_sel(struct drm_crtc *crtc);
 extern int intel_enable_rc6(const struct drm_device *dev);
 
 extern bool i915_semaphore_is_enabled(struct drm_device *dev);
+int i915_reg_read_ioctl(struct drm_device *dev, void *data,
+			struct drm_file *file);
 
 /* overlay */
 #ifdef CONFIG_DEBUG_FS
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 274d25d..53c2a11 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -37,12 +37,12 @@
 #include <linux/pci.h>
 #include <linux/dma-buf.h>
 
-static __must_check int i915_gem_object_flush_gpu_write_domain(struct drm_i915_gem_object *obj);
 static void i915_gem_object_flush_gtt_write_domain(struct drm_i915_gem_object *obj);
 static void i915_gem_object_flush_cpu_write_domain(struct drm_i915_gem_object *obj);
 static __must_check int i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj,
 						    unsigned alignment,
-						    bool map_and_fenceable);
+						    bool map_and_fenceable,
+						    bool nonblocking);
 static int i915_gem_phys_pwrite(struct drm_device *dev,
 				struct drm_i915_gem_object *obj,
 				struct drm_i915_gem_pwrite *args,
@@ -56,6 +56,8 @@ static void i915_gem_object_update_fence(struct drm_i915_gem_object *obj,
 
 static int i915_gem_inactive_shrink(struct shrinker *shrinker,
 				    struct shrink_control *sc);
+static long i915_gem_purge(struct drm_i915_private *dev_priv, long target);
+static void i915_gem_shrink_all(struct drm_i915_private *dev_priv);
 static void i915_gem_object_truncate(struct drm_i915_gem_object *obj);
 
 static inline void i915_gem_object_fence_lost(struct drm_i915_gem_object *obj)
@@ -141,7 +143,7 @@ int i915_mutex_lock_interruptible(struct drm_device *dev)
 static inline bool
 i915_gem_object_is_inactive(struct drm_i915_gem_object *obj)
 {
-	return !obj->active;
+	return obj->gtt_space && !obj->active;
 }
 
 int
@@ -180,7 +182,7 @@ i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data,
 
 	pinned = 0;
 	mutex_lock(&dev->struct_mutex);
-	list_for_each_entry(obj, &dev_priv->mm.gtt_list, gtt_list)
+	list_for_each_entry(obj, &dev_priv->mm.bound_list, gtt_list)
 		if (obj->pin_count)
 			pinned += obj->gtt_space->size;
 	mutex_unlock(&dev->struct_mutex);
@@ -424,9 +426,11 @@ i915_gem_shmem_pread(struct drm_device *dev,
 		 * anyway again before the next pread happens. */
 		if (obj->cache_level == I915_CACHE_NONE)
 			needs_clflush = 1;
-		ret = i915_gem_object_set_to_gtt_domain(obj, false);
-		if (ret)
-			return ret;
+		if (obj->gtt_space) {
+			ret = i915_gem_object_set_to_gtt_domain(obj, false);
+			if (ret)
+				return ret;
+		}
 	}
 
 	offset = args->offset;
@@ -606,7 +610,7 @@ i915_gem_gtt_pwrite_fast(struct drm_device *dev,
 	char __user *user_data;
 	int page_offset, page_length, ret;
 
-	ret = i915_gem_object_pin(obj, 0, true);
+	ret = i915_gem_object_pin(obj, 0, true, true);
 	if (ret)
 		goto out;
 
@@ -752,9 +756,11 @@ i915_gem_shmem_pwrite(struct drm_device *dev,
 		 * right away and we therefore have to clflush anyway. */
 		if (obj->cache_level == I915_CACHE_NONE)
 			needs_clflush_after = 1;
-		ret = i915_gem_object_set_to_gtt_domain(obj, true);
-		if (ret)
-			return ret;
+		if (obj->gtt_space) {
+			ret = i915_gem_object_set_to_gtt_domain(obj, true);
+			if (ret)
+				return ret;
+		}
 	}
 	/* Same trick applies for invalidate partially written cachelines before
 	 * writing.  */
@@ -920,10 +926,8 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
 		goto out;
 	}
 
-	if (obj->gtt_space &&
-	    obj->cache_level == I915_CACHE_NONE &&
+	if (obj->cache_level == I915_CACHE_NONE &&
 	    obj->tiling_mode == I915_TILING_NONE &&
-	    obj->map_and_fenceable &&
 	    obj->base.write_domain != I915_GEM_DOMAIN_CPU) {
 		ret = i915_gem_gtt_pwrite_fast(dev, obj, args, file);
 		/* Note that the gtt paths might fail with non-page-backed user
@@ -931,7 +935,7 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
 		 * textures). Fallback to the shmem path in that case. */
 	}
 
-	if (ret == -EFAULT)
+	if (ret == -EFAULT || ret == -ENOSPC)
 		ret = i915_gem_shmem_pwrite(dev, obj, args, file);
 
 out:
@@ -941,6 +945,240 @@ unlock:
 	return ret;
 }
 
+int
+i915_gem_check_wedge(struct drm_i915_private *dev_priv,
+		     bool interruptible)
+{
+	if (atomic_read(&dev_priv->mm.wedged)) {
+		struct completion *x = &dev_priv->error_completion;
+		bool recovery_complete;
+		unsigned long flags;
+
+		/* Give the error handler a chance to run. */
+		spin_lock_irqsave(&x->wait.lock, flags);
+		recovery_complete = x->done > 0;
+		spin_unlock_irqrestore(&x->wait.lock, flags);
+
+		/* Non-interruptible callers can't handle -EAGAIN, hence return
+		 * -EIO unconditionally for these. */
+		if (!interruptible)
+			return -EIO;
+
+		/* Recovery complete, but still wedged means reset failure. */
+		if (recovery_complete)
+			return -EIO;
+
+		return -EAGAIN;
+	}
+
+	return 0;
+}
+
+/*
+ * Compare seqno against outstanding lazy request. Emit a request if they are
+ * equal.
+ */
+static int
+i915_gem_check_olr(struct intel_ring_buffer *ring, u32 seqno)
+{
+	int ret;
+
+	BUG_ON(!mutex_is_locked(&ring->dev->struct_mutex));
+
+	ret = 0;
+	if (seqno == ring->outstanding_lazy_request)
+		ret = i915_add_request(ring, NULL, NULL);
+
+	return ret;
+}
+
+/**
+ * __wait_seqno - wait until execution of seqno has finished
+ * @ring: the ring expected to report seqno
+ * @seqno: duh!
+ * @interruptible: do an interruptible wait (normally yes)
+ * @timeout: in - how long to wait (NULL forever); out - how much time remaining
+ *
+ * Returns 0 if the seqno was found within the alloted time. Else returns the
+ * errno with remaining time filled in timeout argument.
+ */
+static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno,
+			bool interruptible, struct timespec *timeout)
+{
+	drm_i915_private_t *dev_priv = ring->dev->dev_private;
+	struct timespec before, now, wait_time={1,0};
+	unsigned long timeout_jiffies;
+	long end;
+	bool wait_forever = true;
+	int ret;
+
+	if (i915_seqno_passed(ring->get_seqno(ring, true), seqno))
+		return 0;
+
+	trace_i915_gem_request_wait_begin(ring, seqno);
+
+	if (timeout != NULL) {
+		wait_time = *timeout;
+		wait_forever = false;
+	}
+
+	timeout_jiffies = timespec_to_jiffies(&wait_time);
+
+	if (WARN_ON(!ring->irq_get(ring)))
+		return -ENODEV;
+
+	/* Record current time in case interrupted by signal, or wedged * */
+	getrawmonotonic(&before);
+
+#define EXIT_COND \
+	(i915_seqno_passed(ring->get_seqno(ring, false), seqno) || \
+	atomic_read(&dev_priv->mm.wedged))
+	do {
+		if (interruptible)
+			end = wait_event_interruptible_timeout(ring->irq_queue,
+							       EXIT_COND,
+							       timeout_jiffies);
+		else
+			end = wait_event_timeout(ring->irq_queue, EXIT_COND,
+						 timeout_jiffies);
+
+		ret = i915_gem_check_wedge(dev_priv, interruptible);
+		if (ret)
+			end = ret;
+	} while (end == 0 && wait_forever);
+
+	getrawmonotonic(&now);
+
+	ring->irq_put(ring);
+	trace_i915_gem_request_wait_end(ring, seqno);
+#undef EXIT_COND
+
+	if (timeout) {
+		struct timespec sleep_time = timespec_sub(now, before);
+		*timeout = timespec_sub(*timeout, sleep_time);
+	}
+
+	switch (end) {
+	case -EIO:
+	case -EAGAIN: /* Wedged */
+	case -ERESTARTSYS: /* Signal */
+		return (int)end;
+	case 0: /* Timeout */
+		if (timeout)
+			set_normalized_timespec(timeout, 0, 0);
+		return -ETIME;
+	default: /* Completed */
+		WARN_ON(end < 0); /* We're not aware of other errors */
+		return 0;
+	}
+}
+
+/**
+ * Waits for a sequence number to be signaled, and cleans up the
+ * request and object lists appropriately for that event.
+ */
+int
+i915_wait_seqno(struct intel_ring_buffer *ring, uint32_t seqno)
+{
+	struct drm_device *dev = ring->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	bool interruptible = dev_priv->mm.interruptible;
+	int ret;
+
+	BUG_ON(!mutex_is_locked(&dev->struct_mutex));
+	BUG_ON(seqno == 0);
+
+	ret = i915_gem_check_wedge(dev_priv, interruptible);
+	if (ret)
+		return ret;
+
+	ret = i915_gem_check_olr(ring, seqno);
+	if (ret)
+		return ret;
+
+	return __wait_seqno(ring, seqno, interruptible, NULL);
+}
+
+/**
+ * Ensures that all rendering to the object has completed and the object is
+ * safe to unbind from the GTT or access from the CPU.
+ */
+static __must_check int
+i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj,
+			       bool readonly)
+{
+	struct intel_ring_buffer *ring = obj->ring;
+	u32 seqno;
+	int ret;
+
+	seqno = readonly ? obj->last_write_seqno : obj->last_read_seqno;
+	if (seqno == 0)
+		return 0;
+
+	ret = i915_wait_seqno(ring, seqno);
+	if (ret)
+		return ret;
+
+	i915_gem_retire_requests_ring(ring);
+
+	/* Manually manage the write flush as we may have not yet
+	 * retired the buffer.
+	 */
+	if (obj->last_write_seqno &&
+	    i915_seqno_passed(seqno, obj->last_write_seqno)) {
+		obj->last_write_seqno = 0;
+		obj->base.write_domain &= ~I915_GEM_GPU_DOMAINS;
+	}
+
+	return 0;
+}
+
+/* A nonblocking variant of the above wait. This is a highly dangerous routine
+ * as the object state may change during this call.
+ */
+static __must_check int
+i915_gem_object_wait_rendering__nonblocking(struct drm_i915_gem_object *obj,
+					    bool readonly)
+{
+	struct drm_device *dev = obj->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_ring_buffer *ring = obj->ring;
+	u32 seqno;
+	int ret;
+
+	BUG_ON(!mutex_is_locked(&dev->struct_mutex));
+	BUG_ON(!dev_priv->mm.interruptible);
+
+	seqno = readonly ? obj->last_write_seqno : obj->last_read_seqno;
+	if (seqno == 0)
+		return 0;
+
+	ret = i915_gem_check_wedge(dev_priv, true);
+	if (ret)
+		return ret;
+
+	ret = i915_gem_check_olr(ring, seqno);
+	if (ret)
+		return ret;
+
+	mutex_unlock(&dev->struct_mutex);
+	ret = __wait_seqno(ring, seqno, true, NULL);
+	mutex_lock(&dev->struct_mutex);
+
+	i915_gem_retire_requests_ring(ring);
+
+	/* Manually manage the write flush as we may have not yet
+	 * retired the buffer.
+	 */
+	if (obj->last_write_seqno &&
+	    i915_seqno_passed(seqno, obj->last_write_seqno)) {
+		obj->last_write_seqno = 0;
+		obj->base.write_domain &= ~I915_GEM_GPU_DOMAINS;
+	}
+
+	return ret;
+}
+
 /**
  * Called when user space prepares to use an object with the CPU, either
  * through the mmap ioctl's mapping or a GTT mapping.
@@ -978,6 +1216,14 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
 		goto unlock;
 	}
 
+	/* Try to flush the object off the GPU without holding the lock.
+	 * We will repeat the flush holding the lock in the normal manner
+	 * to catch cases where we are gazumped.
+	 */
+	ret = i915_gem_object_wait_rendering__nonblocking(obj, !write_domain);
+	if (ret)
+		goto unref;
+
 	if (read_domains & I915_GEM_DOMAIN_GTT) {
 		ret = i915_gem_object_set_to_gtt_domain(obj, write_domain != 0);
 
@@ -991,6 +1237,7 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
 		ret = i915_gem_object_set_to_cpu_domain(obj, write_domain != 0);
 	}
 
+unref:
 	drm_gem_object_unreference(&obj->base);
 unlock:
 	mutex_unlock(&dev->struct_mutex);
@@ -1110,7 +1357,7 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 			goto unlock;
 	}
 	if (!obj->gtt_space) {
-		ret = i915_gem_object_bind_to_gtt(obj, 0, true);
+		ret = i915_gem_object_bind_to_gtt(obj, 0, true, false);
 		if (ret)
 			goto unlock;
 
@@ -1271,6 +1518,42 @@ i915_gem_get_unfenced_gtt_alignment(struct drm_device *dev,
 	return i915_gem_get_gtt_size(dev, size, tiling_mode);
 }
 
+static int i915_gem_object_create_mmap_offset(struct drm_i915_gem_object *obj)
+{
+	struct drm_i915_private *dev_priv = obj->base.dev->dev_private;
+	int ret;
+
+	if (obj->base.map_list.map)
+		return 0;
+
+	ret = drm_gem_create_mmap_offset(&obj->base);
+	if (ret != -ENOSPC)
+		return ret;
+
+	/* Badly fragmented mmap space? The only way we can recover
+	 * space is by destroying unwanted objects. We can't randomly release
+	 * mmap_offsets as userspace expects them to be persistent for the
+	 * lifetime of the objects. The closest we can is to release the
+	 * offsets on purgeable objects by truncating it and marking it purged,
+	 * which prevents userspace from ever using that object again.
+	 */
+	i915_gem_purge(dev_priv, obj->base.size >> PAGE_SHIFT);
+	ret = drm_gem_create_mmap_offset(&obj->base);
+	if (ret != -ENOSPC)
+		return ret;
+
+	i915_gem_shrink_all(dev_priv);
+	return drm_gem_create_mmap_offset(&obj->base);
+}
+
+static void i915_gem_object_free_mmap_offset(struct drm_i915_gem_object *obj)
+{
+	if (!obj->base.map_list.map)
+		return;
+
+	drm_gem_free_mmap_offset(&obj->base);
+}
+
 int
 i915_gem_mmap_gtt(struct drm_file *file,
 		  struct drm_device *dev,
@@ -1302,11 +1585,9 @@ i915_gem_mmap_gtt(struct drm_file *file,
 		goto out;
 	}
 
-	if (!obj->base.map_list.map) {
-		ret = drm_gem_create_mmap_offset(&obj->base);
-		if (ret)
-			goto out;
-	}
+	ret = i915_gem_object_create_mmap_offset(obj);
+	if (ret)
+		goto out;
 
 	*offset = (u64)obj->base.map_list.hash.key << PAGE_SHIFT;
 
@@ -1341,64 +1622,58 @@ i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data,
 	return i915_gem_mmap_gtt(file, dev, args->handle, &args->offset);
 }
 
-int
-i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj,
-			      gfp_t gfpmask)
+/* Immediately discard the backing storage */
+static void
+i915_gem_object_truncate(struct drm_i915_gem_object *obj)
 {
-	int page_count, i;
-	struct address_space *mapping;
 	struct inode *inode;
-	struct page *page;
 
-	if (obj->pages || obj->sg_table)
-		return 0;
+	i915_gem_object_free_mmap_offset(obj);
 
-	/* Get the list of pages out of our struct file.  They'll be pinned
-	 * at this point until we release them.
-	 */
-	page_count = obj->base.size / PAGE_SIZE;
-	BUG_ON(obj->pages != NULL);
-	obj->pages = drm_malloc_ab(page_count, sizeof(struct page *));
-	if (obj->pages == NULL)
-		return -ENOMEM;
+	if (obj->base.filp == NULL)
+		return;
 
+	/* Our goal here is to return as much of the memory as
+	 * is possible back to the system as we are called from OOM.
+	 * To do this we must instruct the shmfs to drop all of its
+	 * backing pages, *now*.
+	 */
 	inode = obj->base.filp->f_path.dentry->d_inode;
-	mapping = inode->i_mapping;
-	gfpmask |= mapping_gfp_mask(mapping);
+	shmem_truncate_range(inode, 0, (loff_t)-1);
 
-	for (i = 0; i < page_count; i++) {
-		page = shmem_read_mapping_page_gfp(mapping, i, gfpmask);
-		if (IS_ERR(page))
-			goto err_pages;
-
-		obj->pages[i] = page;
-	}
-
-	if (i915_gem_object_needs_bit17_swizzle(obj))
-		i915_gem_object_do_bit_17_swizzle(obj);
-
-	return 0;
-
-err_pages:
-	while (i--)
-		page_cache_release(obj->pages[i]);
+	obj->madv = __I915_MADV_PURGED;
+}
 
-	drm_free_large(obj->pages);
-	obj->pages = NULL;
-	return PTR_ERR(page);
+static inline int
+i915_gem_object_is_purgeable(struct drm_i915_gem_object *obj)
+{
+	return obj->madv == I915_MADV_DONTNEED;
 }
 
-static void
+static int
 i915_gem_object_put_pages_gtt(struct drm_i915_gem_object *obj)
 {
 	int page_count = obj->base.size / PAGE_SIZE;
-	int i;
+	int ret, i;
 
-	if (!obj->pages)
-		return;
+	BUG_ON(obj->gtt_space);
+
+	if (obj->pages == NULL)
+		return 0;
 
+	BUG_ON(obj->gtt_space);
 	BUG_ON(obj->madv == __I915_MADV_PURGED);
 
+	ret = i915_gem_object_set_to_cpu_domain(obj, true);
+	if (ret) {
+		/* In the event of a disaster, abandon all caches and
+		 * hope for the best.
+		 */
+		WARN_ON(ret != -EIO);
+		i915_gem_clflush_object(obj);
+		obj->base.read_domains = obj->base.write_domain = I915_GEM_DOMAIN_CPU;
+	}
+
 	if (i915_gem_object_needs_bit17_swizzle(obj))
 		i915_gem_object_save_bit_17_swizzle(obj);
 
@@ -1418,6 +1693,129 @@ i915_gem_object_put_pages_gtt(struct drm_i915_gem_object *obj)
 
 	drm_free_large(obj->pages);
 	obj->pages = NULL;
+
+	list_del(&obj->gtt_list);
+
+	if (i915_gem_object_is_purgeable(obj))
+		i915_gem_object_truncate(obj);
+
+	return 0;
+}
+
+static long
+i915_gem_purge(struct drm_i915_private *dev_priv, long target)
+{
+	struct drm_i915_gem_object *obj, *next;
+	long count = 0;
+
+	list_for_each_entry_safe(obj, next,
+				 &dev_priv->mm.unbound_list,
+				 gtt_list) {
+		if (i915_gem_object_is_purgeable(obj) &&
+		    i915_gem_object_put_pages_gtt(obj) == 0) {
+			count += obj->base.size >> PAGE_SHIFT;
+			if (count >= target)
+				return count;
+		}
+	}
+
+	list_for_each_entry_safe(obj, next,
+				 &dev_priv->mm.inactive_list,
+				 mm_list) {
+		if (i915_gem_object_is_purgeable(obj) &&
+		    i915_gem_object_unbind(obj) == 0 &&
+		    i915_gem_object_put_pages_gtt(obj) == 0) {
+			count += obj->base.size >> PAGE_SHIFT;
+			if (count >= target)
+				return count;
+		}
+	}
+
+	return count;
+}
+
+static void
+i915_gem_shrink_all(struct drm_i915_private *dev_priv)
+{
+	struct drm_i915_gem_object *obj, *next;
+
+	i915_gem_evict_everything(dev_priv->dev);
+
+	list_for_each_entry_safe(obj, next, &dev_priv->mm.unbound_list, gtt_list)
+		i915_gem_object_put_pages_gtt(obj);
+}
+
+int
+i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)
+{
+	struct drm_i915_private *dev_priv = obj->base.dev->dev_private;
+	int page_count, i;
+	struct address_space *mapping;
+	struct page *page;
+	gfp_t gfp;
+
+	if (obj->pages || obj->sg_table)
+		return 0;
+
+	/* Assert that the object is not currently in any GPU domain. As it
+	 * wasn't in the GTT, there shouldn't be any way it could have been in
+	 * a GPU cache
+	 */
+	BUG_ON(obj->base.read_domains & I915_GEM_GPU_DOMAINS);
+	BUG_ON(obj->base.write_domain & I915_GEM_GPU_DOMAINS);
+
+	/* Get the list of pages out of our struct file.  They'll be pinned
+	 * at this point until we release them.
+	 */
+	page_count = obj->base.size / PAGE_SIZE;
+	obj->pages = drm_malloc_ab(page_count, sizeof(struct page *));
+	if (obj->pages == NULL)
+		return -ENOMEM;
+
+	/* Fail silently without starting the shrinker */
+	mapping = obj->base.filp->f_path.dentry->d_inode->i_mapping;
+	gfp = mapping_gfp_mask(mapping);
+	gfp |= __GFP_NORETRY | __GFP_NOWARN;
+	gfp &= ~(__GFP_IO | __GFP_WAIT);
+	for (i = 0; i < page_count; i++) {
+		page = shmem_read_mapping_page_gfp(mapping, i, gfp);
+		if (IS_ERR(page)) {
+			i915_gem_purge(dev_priv, page_count);
+			page = shmem_read_mapping_page_gfp(mapping, i, gfp);
+		}
+		if (IS_ERR(page)) {
+			/* We've tried hard to allocate the memory by reaping
+			 * our own buffer, now let the real VM do its job and
+			 * go down in flames if truly OOM.
+			 */
+			gfp &= ~(__GFP_NORETRY | __GFP_NOWARN);
+			gfp |= __GFP_IO | __GFP_WAIT;
+
+			i915_gem_shrink_all(dev_priv);
+			page = shmem_read_mapping_page_gfp(mapping, i, gfp);
+			if (IS_ERR(page))
+				goto err_pages;
+
+			gfp |= __GFP_NORETRY | __GFP_NOWARN;
+			gfp &= ~(__GFP_IO | __GFP_WAIT);
+		}
+
+		obj->pages[i] = page;
+	}
+
+	if (i915_gem_object_needs_bit17_swizzle(obj))
+		i915_gem_object_do_bit_17_swizzle(obj);
+
+	list_add_tail(&obj->gtt_list, &dev_priv->mm.unbound_list);
+	return 0;
+
+err_pages:
+	while (i--)
+		page_cache_release(obj->pages[i]);
+
+	drm_free_large(obj->pages);
+	obj->pages = NULL;
+	return PTR_ERR(page);
 }
 
 void
@@ -1441,7 +1839,7 @@ i915_gem_object_move_to_active(struct drm_i915_gem_object *obj,
 	list_move_tail(&obj->mm_list, &dev_priv->mm.active_list);
 	list_move_tail(&obj->ring_list, &ring->active_list);
 
-	obj->last_rendering_seqno = seqno;
+	obj->last_read_seqno = seqno;
 
 	if (obj->fenced_gpu_access) {
 		obj->last_fenced_seqno = seqno;
@@ -1458,97 +1856,35 @@ i915_gem_object_move_to_active(struct drm_i915_gem_object *obj,
 }
 
 static void
-i915_gem_object_move_off_active(struct drm_i915_gem_object *obj)
-{
-	list_del_init(&obj->ring_list);
-	obj->last_rendering_seqno = 0;
-	obj->last_fenced_seqno = 0;
-}
-
-static void
-i915_gem_object_move_to_flushing(struct drm_i915_gem_object *obj)
+i915_gem_object_move_to_inactive(struct drm_i915_gem_object *obj)
 {
 	struct drm_device *dev = obj->base.dev;
-	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct drm_i915_private *dev_priv = dev->dev_private;
 
+	BUG_ON(obj->base.write_domain & ~I915_GEM_GPU_DOMAINS);
 	BUG_ON(!obj->active);
-	list_move_tail(&obj->mm_list, &dev_priv->mm.flushing_list);
-
-	i915_gem_object_move_off_active(obj);
-}
 
-static void
-i915_gem_object_move_to_inactive(struct drm_i915_gem_object *obj)
-{
-	struct drm_device *dev = obj->base.dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
+	if (obj->pin_count) /* are we a framebuffer? */
+		intel_mark_fb_idle(obj);
 
 	list_move_tail(&obj->mm_list, &dev_priv->mm.inactive_list);
 
-	BUG_ON(!list_empty(&obj->gpu_write_list));
-	BUG_ON(!obj->active);
+	list_del_init(&obj->ring_list);
 	obj->ring = NULL;
 
-	i915_gem_object_move_off_active(obj);
+	obj->last_read_seqno = 0;
+	obj->last_write_seqno = 0;
+	obj->base.write_domain = 0;
+
+	obj->last_fenced_seqno = 0;
 	obj->fenced_gpu_access = false;
 
 	obj->active = 0;
-	obj->pending_gpu_write = false;
 	drm_gem_object_unreference(&obj->base);
 
 	WARN_ON(i915_verify_lists(dev));
 }
 
-/* Immediately discard the backing storage */
-static void
-i915_gem_object_truncate(struct drm_i915_gem_object *obj)
-{
-	struct inode *inode;
-
-	/* Our goal here is to return as much of the memory as
-	 * is possible back to the system as we are called from OOM.
-	 * To do this we must instruct the shmfs to drop all of its
-	 * backing pages, *now*.
-	 */
-	inode = obj->base.filp->f_path.dentry->d_inode;
-	shmem_truncate_range(inode, 0, (loff_t)-1);
-
-	if (obj->base.map_list.map)
-		drm_gem_free_mmap_offset(&obj->base);
-
-	obj->madv = __I915_MADV_PURGED;
-}
-
-static inline int
-i915_gem_object_is_purgeable(struct drm_i915_gem_object *obj)
-{
-	return obj->madv == I915_MADV_DONTNEED;
-}
-
-static void
-i915_gem_process_flushing_list(struct intel_ring_buffer *ring,
-			       uint32_t flush_domains)
-{
-	struct drm_i915_gem_object *obj, *next;
-
-	list_for_each_entry_safe(obj, next,
-				 &ring->gpu_write_list,
-				 gpu_write_list) {
-		if (obj->base.write_domain & flush_domains) {
-			uint32_t old_write_domain = obj->base.write_domain;
-
-			obj->base.write_domain = 0;
-			list_del_init(&obj->gpu_write_list);
-			i915_gem_object_move_to_active(obj, ring,
-						       i915_gem_next_request_seqno(ring));
-
-			trace_i915_gem_object_change_domain(obj,
-							    obj->base.read_domains,
-							    old_write_domain);
-		}
-	}
-}
-
 static u32
 i915_gem_get_seqno(struct drm_device *dev)
 {
@@ -1589,15 +1925,16 @@ i915_add_request(struct intel_ring_buffer *ring,
 	 * is that the flush _must_ happen before the next request, no matter
 	 * what.
 	 */
-	if (ring->gpu_caches_dirty) {
-		ret = i915_gem_flush_ring(ring, 0, I915_GEM_GPU_DOMAINS);
-		if (ret)
-			return ret;
+	ret = intel_ring_flush_all_caches(ring);
+	if (ret)
+		return ret;
 
-		ring->gpu_caches_dirty = false;
+	if (request == NULL) {
+		request = kmalloc(sizeof(*request), GFP_KERNEL);
+		if (request == NULL)
+			return -ENOMEM;
 	}
 
-	BUG_ON(request == NULL);
 	seqno = i915_gem_next_request_seqno(ring);
 
 	/* Record the position of the start of the request so that
@@ -1608,8 +1945,10 @@ i915_add_request(struct intel_ring_buffer *ring,
 	request_ring_position = intel_ring_get_tail(ring);
 
 	ret = ring->add_request(ring, &seqno);
-	if (ret)
-	    return ret;
+	if (ret) {
+		kfree(request);
+		return ret;
+	}
 
 	trace_i915_gem_request_add(ring, seqno);
 
@@ -1619,6 +1958,7 @@ i915_add_request(struct intel_ring_buffer *ring,
 	request->emitted_jiffies = jiffies;
 	was_empty = list_empty(&ring->request_list);
 	list_add_tail(&request->list, &ring->request_list);
+	request->file_priv = NULL;
 
 	if (file) {
 		struct drm_i915_file_private *file_priv = file->driver_priv;
@@ -1638,13 +1978,13 @@ i915_add_request(struct intel_ring_buffer *ring,
 				  jiffies +
 				  msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD));
 		}
-		if (was_empty)
+		if (was_empty) {
 			queue_delayed_work(dev_priv->wq,
 					   &dev_priv->mm.retire_work, HZ);
+			intel_mark_busy(dev_priv->dev);
+		}
 	}
 
-	WARN_ON(!list_empty(&ring->gpu_write_list));
-
 	return 0;
 }
 
@@ -1686,8 +2026,6 @@ static void i915_gem_reset_ring_lists(struct drm_i915_private *dev_priv,
 				       struct drm_i915_gem_object,
 				       ring_list);
 
-		obj->base.write_domain = 0;
-		list_del_init(&obj->gpu_write_list);
 		i915_gem_object_move_to_inactive(obj);
 	}
 }
@@ -1723,20 +2061,6 @@ void i915_gem_reset(struct drm_device *dev)
 	for_each_ring(ring, dev_priv, i)
 		i915_gem_reset_ring_lists(dev_priv, ring);
 
-	/* Remove anything from the flushing lists. The GPU cache is likely
-	 * to be lost on reset along with the data, so simply move the
-	 * lost bo to the inactive list.
-	 */
-	while (!list_empty(&dev_priv->mm.flushing_list)) {
-		obj = list_first_entry(&dev_priv->mm.flushing_list,
-				      struct drm_i915_gem_object,
-				      mm_list);
-
-		obj->base.write_domain = 0;
-		list_del_init(&obj->gpu_write_list);
-		i915_gem_object_move_to_inactive(obj);
-	}
-
 	/* Move everything out of the GPU domains to ensure we do any
 	 * necessary invalidation upon reuse.
 	 */
@@ -1747,6 +2071,7 @@ void i915_gem_reset(struct drm_device *dev)
 		obj->base.read_domains &= ~I915_GEM_GPU_DOMAINS;
 	}
 
+
 	/* The fence registers are invalidated so clear them out */
 	i915_gem_reset_fences(dev);
 }
@@ -1765,7 +2090,7 @@ i915_gem_retire_requests_ring(struct intel_ring_buffer *ring)
 
 	WARN_ON(i915_verify_lists(ring->dev));
 
-	seqno = ring->get_seqno(ring);
+	seqno = ring->get_seqno(ring, true);
 
 	for (i = 0; i < ARRAY_SIZE(ring->sync_seqno); i++)
 		if (seqno >= ring->sync_seqno[i])
@@ -1804,13 +2129,10 @@ i915_gem_retire_requests_ring(struct intel_ring_buffer *ring)
 				      struct drm_i915_gem_object,
 				      ring_list);
 
-		if (!i915_seqno_passed(seqno, obj->last_rendering_seqno))
+		if (!i915_seqno_passed(seqno, obj->last_read_seqno))
 			break;
 
-		if (obj->base.write_domain != 0)
-			i915_gem_object_move_to_flushing(obj);
-		else
-			i915_gem_object_move_to_inactive(obj);
+		i915_gem_object_move_to_inactive(obj);
 	}
 
 	if (unlikely(ring->trace_irq_seqno &&
@@ -1848,225 +2170,29 @@ i915_gem_retire_work_handler(struct work_struct *work)
 
 	/* Come back later if the device is busy... */
 	if (!mutex_trylock(&dev->struct_mutex)) {
-		queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, HZ);
-		return;
-	}
-
-	i915_gem_retire_requests(dev);
-
-	/* Send a periodic flush down the ring so we don't hold onto GEM
-	 * objects indefinitely.
-	 */
-	idle = true;
-	for_each_ring(ring, dev_priv, i) {
-		if (ring->gpu_caches_dirty) {
-			struct drm_i915_gem_request *request;
-
-			request = kzalloc(sizeof(*request), GFP_KERNEL);
-			if (request == NULL ||
-			    i915_add_request(ring, NULL, request))
-			    kfree(request);
-		}
-
-		idle &= list_empty(&ring->request_list);
-	}
-
-	if (!dev_priv->mm.suspended && !idle)
-		queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, HZ);
-
-	mutex_unlock(&dev->struct_mutex);
-}
-
-int
-i915_gem_check_wedge(struct drm_i915_private *dev_priv,
-		     bool interruptible)
-{
-	if (atomic_read(&dev_priv->mm.wedged)) {
-		struct completion *x = &dev_priv->error_completion;
-		bool recovery_complete;
-		unsigned long flags;
-
-		/* Give the error handler a chance to run. */
-		spin_lock_irqsave(&x->wait.lock, flags);
-		recovery_complete = x->done > 0;
-		spin_unlock_irqrestore(&x->wait.lock, flags);
-
-		/* Non-interruptible callers can't handle -EAGAIN, hence return
-		 * -EIO unconditionally for these. */
-		if (!interruptible)
-			return -EIO;
-
-		/* Recovery complete, but still wedged means reset failure. */
-		if (recovery_complete)
-			return -EIO;
-
-		return -EAGAIN;
-	}
-
-	return 0;
-}
-
-/*
- * Compare seqno against outstanding lazy request. Emit a request if they are
- * equal.
- */
-static int
-i915_gem_check_olr(struct intel_ring_buffer *ring, u32 seqno)
-{
-	int ret = 0;
-
-	BUG_ON(!mutex_is_locked(&ring->dev->struct_mutex));
-
-	if (seqno == ring->outstanding_lazy_request) {
-		struct drm_i915_gem_request *request;
-
-		request = kzalloc(sizeof(*request), GFP_KERNEL);
-		if (request == NULL)
-			return -ENOMEM;
-
-		ret = i915_add_request(ring, NULL, request);
-		if (ret) {
-			kfree(request);
-			return ret;
-		}
-
-		BUG_ON(seqno != request->seqno);
-	}
-
-	return ret;
-}
-
-/**
- * __wait_seqno - wait until execution of seqno has finished
- * @ring: the ring expected to report seqno
- * @seqno: duh!
- * @interruptible: do an interruptible wait (normally yes)
- * @timeout: in - how long to wait (NULL forever); out - how much time remaining
- *
- * Returns 0 if the seqno was found within the alloted time. Else returns the
- * errno with remaining time filled in timeout argument.
- */
-static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno,
-			bool interruptible, struct timespec *timeout)
-{
-	drm_i915_private_t *dev_priv = ring->dev->dev_private;
-	struct timespec before, now, wait_time={1,0};
-	unsigned long timeout_jiffies;
-	long end;
-	bool wait_forever = true;
-	int ret;
-
-	if (i915_seqno_passed(ring->get_seqno(ring), seqno))
-		return 0;
-
-	trace_i915_gem_request_wait_begin(ring, seqno);
-
-	if (timeout != NULL) {
-		wait_time = *timeout;
-		wait_forever = false;
-	}
-
-	timeout_jiffies = timespec_to_jiffies(&wait_time);
-
-	if (WARN_ON(!ring->irq_get(ring)))
-		return -ENODEV;
-
-	/* Record current time in case interrupted by signal, or wedged * */
-	getrawmonotonic(&before);
-
-#define EXIT_COND \
-	(i915_seqno_passed(ring->get_seqno(ring), seqno) || \
-	atomic_read(&dev_priv->mm.wedged))
-	do {
-		if (interruptible)
-			end = wait_event_interruptible_timeout(ring->irq_queue,
-							       EXIT_COND,
-							       timeout_jiffies);
-		else
-			end = wait_event_timeout(ring->irq_queue, EXIT_COND,
-						 timeout_jiffies);
-
-		ret = i915_gem_check_wedge(dev_priv, interruptible);
-		if (ret)
-			end = ret;
-	} while (end == 0 && wait_forever);
-
-	getrawmonotonic(&now);
-
-	ring->irq_put(ring);
-	trace_i915_gem_request_wait_end(ring, seqno);
-#undef EXIT_COND
-
-	if (timeout) {
-		struct timespec sleep_time = timespec_sub(now, before);
-		*timeout = timespec_sub(*timeout, sleep_time);
-	}
-
-	switch (end) {
-	case -EIO:
-	case -EAGAIN: /* Wedged */
-	case -ERESTARTSYS: /* Signal */
-		return (int)end;
-	case 0: /* Timeout */
-		if (timeout)
-			set_normalized_timespec(timeout, 0, 0);
-		return -ETIME;
-	default: /* Completed */
-		WARN_ON(end < 0); /* We're not aware of other errors */
-		return 0;
-	}
-}
-
-/**
- * Waits for a sequence number to be signaled, and cleans up the
- * request and object lists appropriately for that event.
- */
-int
-i915_wait_seqno(struct intel_ring_buffer *ring, uint32_t seqno)
-{
-	drm_i915_private_t *dev_priv = ring->dev->dev_private;
-	int ret = 0;
-
-	BUG_ON(seqno == 0);
-
-	ret = i915_gem_check_wedge(dev_priv, dev_priv->mm.interruptible);
-	if (ret)
-		return ret;
-
-	ret = i915_gem_check_olr(ring, seqno);
-	if (ret)
-		return ret;
-
-	ret = __wait_seqno(ring, seqno, dev_priv->mm.interruptible, NULL);
-
-	return ret;
-}
-
-/**
- * Ensures that all rendering to the object has completed and the object is
- * safe to unbind from the GTT or access from the CPU.
- */
-int
-i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj)
-{
-	int ret;
+		queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, HZ);
+		return;
+	}
 
-	/* This function only exists to support waiting for existing rendering,
-	 * not for emitting required flushes.
-	 */
-	BUG_ON((obj->base.write_domain & I915_GEM_GPU_DOMAINS) != 0);
+	i915_gem_retire_requests(dev);
 
-	/* If there is rendering queued on the buffer being evicted, wait for
-	 * it.
+	/* Send a periodic flush down the ring so we don't hold onto GEM
+	 * objects indefinitely.
 	 */
-	if (obj->active) {
-		ret = i915_wait_seqno(obj->ring, obj->last_rendering_seqno);
-		if (ret)
-			return ret;
-		i915_gem_retire_requests_ring(obj->ring);
+	idle = true;
+	for_each_ring(ring, dev_priv, i) {
+		if (ring->gpu_caches_dirty)
+			i915_add_request(ring, NULL, NULL);
+
+		idle &= list_empty(&ring->request_list);
 	}
 
-	return 0;
+	if (!dev_priv->mm.suspended && !idle)
+		queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, HZ);
+	if (idle)
+		intel_mark_idle(dev);
+
+	mutex_unlock(&dev->struct_mutex);
 }
 
 /**
@@ -2080,14 +2206,10 @@ i915_gem_object_flush_active(struct drm_i915_gem_object *obj)
 	int ret;
 
 	if (obj->active) {
-		ret = i915_gem_object_flush_gpu_write_domain(obj);
+		ret = i915_gem_check_olr(obj->ring, obj->last_read_seqno);
 		if (ret)
 			return ret;
 
-		ret = i915_gem_check_olr(obj->ring,
-					 obj->last_rendering_seqno);
-		if (ret)
-			return ret;
 		i915_gem_retire_requests_ring(obj->ring);
 	}
 
@@ -2147,7 +2269,7 @@ i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
 		goto out;
 
 	if (obj->active) {
-		seqno = obj->last_rendering_seqno;
+		seqno = obj->last_read_seqno;
 		ring = obj->ring;
 	}
 
@@ -2202,11 +2324,11 @@ i915_gem_object_sync(struct drm_i915_gem_object *obj,
 		return 0;
 
 	if (to == NULL || !i915_semaphore_is_enabled(obj->base.dev))
-		return i915_gem_object_wait_rendering(obj);
+		return i915_gem_object_wait_rendering(obj, false);
 
 	idx = intel_ring_sync_index(from, to);
 
-	seqno = obj->last_rendering_seqno;
+	seqno = obj->last_read_seqno;
 	if (seqno <= from->sync_seqno[idx])
 		return 0;
 
@@ -2260,6 +2382,8 @@ i915_gem_object_unbind(struct drm_i915_gem_object *obj)
 	if (obj->pin_count)
 		return -EBUSY;
 
+	BUG_ON(obj->pages == NULL);
+
 	ret = i915_gem_object_finish_gpu(obj);
 	if (ret)
 		return ret;
@@ -2270,22 +2394,6 @@ i915_gem_object_unbind(struct drm_i915_gem_object *obj)
 
 	i915_gem_object_finish_gtt(obj);
 
-	/* Move the object to the CPU domain to ensure that
-	 * any possible CPU writes while it's not in the GTT
-	 * are flushed when we go to remap it.
-	 */
-	if (ret == 0)
-		ret = i915_gem_object_set_to_cpu_domain(obj, 1);
-	if (ret == -ERESTARTSYS)
-		return ret;
-	if (ret) {
-		/* In the event of a disaster, abandon all caches and
-		 * hope for the best.
-		 */
-		i915_gem_clflush_object(obj);
-		obj->base.read_domains = obj->base.write_domain = I915_GEM_DOMAIN_CPU;
-	}
-
 	/* release the fence reg _after_ flushing */
 	ret = i915_gem_object_put_fence(obj);
 	if (ret)
@@ -2301,10 +2409,8 @@ i915_gem_object_unbind(struct drm_i915_gem_object *obj)
 	}
 	i915_gem_gtt_finish_object(obj);
 
-	i915_gem_object_put_pages_gtt(obj);
-
-	list_del_init(&obj->gtt_list);
-	list_del_init(&obj->mm_list);
+	list_del(&obj->mm_list);
+	list_move_tail(&obj->gtt_list, &dev_priv->mm.unbound_list);
 	/* Avoid an unnecessary call to unbind on rebind. */
 	obj->map_and_fenceable = true;
 
@@ -2312,48 +2418,14 @@ i915_gem_object_unbind(struct drm_i915_gem_object *obj)
 	obj->gtt_space = NULL;
 	obj->gtt_offset = 0;
 
-	if (i915_gem_object_is_purgeable(obj))
-		i915_gem_object_truncate(obj);
-
-	return ret;
-}
-
-int
-i915_gem_flush_ring(struct intel_ring_buffer *ring,
-		    uint32_t invalidate_domains,
-		    uint32_t flush_domains)
-{
-	int ret;
-
-	if (((invalidate_domains | flush_domains) & I915_GEM_GPU_DOMAINS) == 0)
-		return 0;
-
-	trace_i915_gem_ring_flush(ring, invalidate_domains, flush_domains);
-
-	ret = ring->flush(ring, invalidate_domains, flush_domains);
-	if (ret)
-		return ret;
-
-	if (flush_domains & I915_GEM_GPU_DOMAINS)
-		i915_gem_process_flushing_list(ring, flush_domains);
-
 	return 0;
 }
 
 static int i915_ring_idle(struct intel_ring_buffer *ring)
 {
-	int ret;
-
-	if (list_empty(&ring->gpu_write_list) && list_empty(&ring->active_list))
+	if (list_empty(&ring->active_list))
 		return 0;
 
-	if (!list_empty(&ring->gpu_write_list)) {
-		ret = i915_gem_flush_ring(ring,
-				    I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS);
-		if (ret)
-			return ret;
-	}
-
 	return i915_wait_seqno(ring, i915_gem_next_request_seqno(ring));
 }
 
@@ -2372,10 +2444,6 @@ int i915_gpu_idle(struct drm_device *dev)
 		ret = i915_ring_idle(ring);
 		if (ret)
 			return ret;
-
-		/* Is the device fubar? */
-		if (WARN_ON(!list_empty(&ring->gpu_write_list)))
-			return -EBUSY;
 	}
 
 	return 0;
@@ -2548,21 +2616,8 @@ static void i915_gem_object_update_fence(struct drm_i915_gem_object *obj,
 static int
 i915_gem_object_flush_fence(struct drm_i915_gem_object *obj)
 {
-	int ret;
-
-	if (obj->fenced_gpu_access) {
-		if (obj->base.write_domain & I915_GEM_GPU_DOMAINS) {
-			ret = i915_gem_flush_ring(obj->ring,
-						  0, obj->base.write_domain);
-			if (ret)
-				return ret;
-		}
-
-		obj->fenced_gpu_access = false;
-	}
-
 	if (obj->last_fenced_seqno) {
-		ret = i915_wait_seqno(obj->ring, obj->last_fenced_seqno);
+		int ret = i915_wait_seqno(obj->ring, obj->last_fenced_seqno);
 		if (ret)
 			return ret;
 
@@ -2575,6 +2630,7 @@ i915_gem_object_flush_fence(struct drm_i915_gem_object *obj)
 	if (obj->base.read_domains & I915_GEM_DOMAIN_GTT)
 		mb();
 
+	obj->fenced_gpu_access = false;
 	return 0;
 }
 
@@ -2694,18 +2750,88 @@ i915_gem_object_get_fence(struct drm_i915_gem_object *obj)
 	return 0;
 }
 
+static bool i915_gem_valid_gtt_space(struct drm_device *dev,
+				     struct drm_mm_node *gtt_space,
+				     unsigned long cache_level)
+{
+	struct drm_mm_node *other;
+
+	/* On non-LLC machines we have to be careful when putting differing
+	 * types of snoopable memory together to avoid the prefetcher
+	 * crossing memory domains and dieing.
+	 */
+	if (HAS_LLC(dev))
+		return true;
+
+	if (gtt_space == NULL)
+		return true;
+
+	if (list_empty(&gtt_space->node_list))
+		return true;
+
+	other = list_entry(gtt_space->node_list.prev, struct drm_mm_node, node_list);
+	if (other->allocated && !other->hole_follows && other->color != cache_level)
+		return false;
+
+	other = list_entry(gtt_space->node_list.next, struct drm_mm_node, node_list);
+	if (other->allocated && !gtt_space->hole_follows && other->color != cache_level)
+		return false;
+
+	return true;
+}
+
+static void i915_gem_verify_gtt(struct drm_device *dev)
+{
+#if WATCH_GTT
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_i915_gem_object *obj;
+	int err = 0;
+
+	list_for_each_entry(obj, &dev_priv->mm.gtt_list, gtt_list) {
+		if (obj->gtt_space == NULL) {
+			printk(KERN_ERR "object found on GTT list with no space reserved\n");
+			err++;
+			continue;
+		}
+
+		if (obj->cache_level != obj->gtt_space->color) {
+			printk(KERN_ERR "object reserved space [%08lx, %08lx] with wrong color, cache_level=%x, color=%lx\n",
+			       obj->gtt_space->start,
+			       obj->gtt_space->start + obj->gtt_space->size,
+			       obj->cache_level,
+			       obj->gtt_space->color);
+			err++;
+			continue;
+		}
+
+		if (!i915_gem_valid_gtt_space(dev,
+					      obj->gtt_space,
+					      obj->cache_level)) {
+			printk(KERN_ERR "invalid GTT space found at [%08lx, %08lx] - color=%x\n",
+			       obj->gtt_space->start,
+			       obj->gtt_space->start + obj->gtt_space->size,
+			       obj->cache_level);
+			err++;
+			continue;
+		}
+	}
+
+	WARN_ON(err);
+#endif
+}
+
 /**
  * Finds free space in the GTT aperture and binds the object there.
  */
 static int
 i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj,
 			    unsigned alignment,
-			    bool map_and_fenceable)
+			    bool map_and_fenceable,
+			    bool nonblocking)
 {
 	struct drm_device *dev = obj->base.dev;
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct drm_mm_node *free_space;
-	gfp_t gfpmask = __GFP_NORETRY | __GFP_NOWARN;
 	u32 size, fence_size, fence_alignment, unfenced_alignment;
 	bool mappable, fenceable;
 	int ret;
@@ -2745,89 +2871,67 @@ i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj,
 		return -E2BIG;
 	}
 
+	ret = i915_gem_object_get_pages_gtt(obj);
+	if (ret)
+		return ret;
+
  search_free:
 	if (map_and_fenceable)
 		free_space =
-			drm_mm_search_free_in_range(&dev_priv->mm.gtt_space,
-						    size, alignment,
-						    0, dev_priv->mm.gtt_mappable_end,
-						    0);
+			drm_mm_search_free_in_range_color(&dev_priv->mm.gtt_space,
+							  size, alignment, obj->cache_level,
+							  0, dev_priv->mm.gtt_mappable_end,
+							  false);
 	else
-		free_space = drm_mm_search_free(&dev_priv->mm.gtt_space,
-						size, alignment, 0);
+		free_space = drm_mm_search_free_color(&dev_priv->mm.gtt_space,
+						      size, alignment, obj->cache_level,
+						      false);
 
 	if (free_space != NULL) {
 		if (map_and_fenceable)
 			obj->gtt_space =
 				drm_mm_get_block_range_generic(free_space,
-							       size, alignment, 0,
+							       size, alignment, obj->cache_level,
 							       0, dev_priv->mm.gtt_mappable_end,
-							       0);
+							       false);
 		else
 			obj->gtt_space =
-				drm_mm_get_block(free_space, size, alignment);
+				drm_mm_get_block_generic(free_space,
+							 size, alignment, obj->cache_level,
+							 false);
 	}
 	if (obj->gtt_space == NULL) {
-		/* If the gtt is empty and we're still having trouble
-		 * fitting our object in, we're out of memory.
-		 */
 		ret = i915_gem_evict_something(dev, size, alignment,
-					       map_and_fenceable);
+					       obj->cache_level,
+					       map_and_fenceable,
+					       nonblocking);
 		if (ret)
 			return ret;
 
 		goto search_free;
 	}
-
-	ret = i915_gem_object_get_pages_gtt(obj, gfpmask);
-	if (ret) {
+	if (WARN_ON(!i915_gem_valid_gtt_space(dev,
+					      obj->gtt_space,
+					      obj->cache_level))) {
 		drm_mm_put_block(obj->gtt_space);
 		obj->gtt_space = NULL;
-
-		if (ret == -ENOMEM) {
-			/* first try to reclaim some memory by clearing the GTT */
-			ret = i915_gem_evict_everything(dev, false);
-			if (ret) {
-				/* now try to shrink everyone else */
-				if (gfpmask) {
-					gfpmask = 0;
-					goto search_free;
-				}
-
-				return -ENOMEM;
-			}
-
-			goto search_free;
-		}
-
-		return ret;
+		return -EINVAL;
 	}
 
+
 	ret = i915_gem_gtt_prepare_object(obj);
 	if (ret) {
-		i915_gem_object_put_pages_gtt(obj);
 		drm_mm_put_block(obj->gtt_space);
 		obj->gtt_space = NULL;
-
-		if (i915_gem_evict_everything(dev, false))
-			return ret;
-
-		goto search_free;
+		return ret;
 	}
 
 	if (!dev_priv->mm.aliasing_ppgtt)
 		i915_gem_gtt_bind_object(obj, obj->cache_level);
 
-	list_add_tail(&obj->gtt_list, &dev_priv->mm.gtt_list);
+	list_move_tail(&obj->gtt_list, &dev_priv->mm.bound_list);
 	list_add_tail(&obj->mm_list, &dev_priv->mm.inactive_list);
 
-	/* Assert that the object is not currently in any GPU domain. As it
-	 * wasn't in the GTT, there shouldn't be any way it could have been in
-	 * a GPU cache
-	 */
-	BUG_ON(obj->base.read_domains & I915_GEM_GPU_DOMAINS);
-	BUG_ON(obj->base.write_domain & I915_GEM_GPU_DOMAINS);
-
 	obj->gtt_offset = obj->gtt_space->start;
 
 	fenceable =
@@ -2840,6 +2944,7 @@ i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj,
 	obj->map_and_fenceable = mappable && fenceable;
 
 	trace_i915_gem_object_bind(obj, map_and_fenceable);
+	i915_gem_verify_gtt(dev);
 	return 0;
 }
 
@@ -2869,17 +2974,6 @@ i915_gem_clflush_object(struct drm_i915_gem_object *obj)
 	drm_clflush_pages(obj->pages, obj->base.size / PAGE_SIZE);
 }
 
-/** Flushes any GPU write domain for the object if it's dirty. */
-static int
-i915_gem_object_flush_gpu_write_domain(struct drm_i915_gem_object *obj)
-{
-	if ((obj->base.write_domain & I915_GEM_GPU_DOMAINS) == 0)
-		return 0;
-
-	/* Queue the GPU write cache flushing we need. */
-	return i915_gem_flush_ring(obj->ring, 0, obj->base.write_domain);
-}
-
 /** Flushes the GTT write domain for the object if it's dirty. */
 static void
 i915_gem_object_flush_gtt_write_domain(struct drm_i915_gem_object *obj)
@@ -2946,16 +3040,10 @@ i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write)
 	if (obj->base.write_domain == I915_GEM_DOMAIN_GTT)
 		return 0;
 
-	ret = i915_gem_object_flush_gpu_write_domain(obj);
+	ret = i915_gem_object_wait_rendering(obj, !write);
 	if (ret)
 		return ret;
 
-	if (obj->pending_gpu_write || write) {
-		ret = i915_gem_object_wait_rendering(obj);
-		if (ret)
-			return ret;
-	}
-
 	i915_gem_object_flush_cpu_write_domain(obj);
 
 	old_write_domain = obj->base.write_domain;
@@ -2998,6 +3086,12 @@ int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj,
 		return -EBUSY;
 	}
 
+	if (!i915_gem_valid_gtt_space(dev, obj->gtt_space, cache_level)) {
+		ret = i915_gem_object_unbind(obj);
+		if (ret)
+			return ret;
+	}
+
 	if (obj->gtt_space) {
 		ret = i915_gem_object_finish_gpu(obj);
 		if (ret)
@@ -3009,7 +3103,7 @@ int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj,
 		 * registers with snooped memory, so relinquish any fences
 		 * currently pointing to our region in the aperture.
 		 */
-		if (INTEL_INFO(obj->base.dev)->gen < 6) {
+		if (INTEL_INFO(dev)->gen < 6) {
 			ret = i915_gem_object_put_fence(obj);
 			if (ret)
 				return ret;
@@ -3020,6 +3114,8 @@ int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj,
 		if (obj->has_aliasing_ppgtt_mapping)
 			i915_ppgtt_bind_object(dev_priv->mm.aliasing_ppgtt,
 					       obj, cache_level);
+
+		obj->gtt_space->color = cache_level;
 	}
 
 	if (cache_level == I915_CACHE_NONE) {
@@ -3046,9 +3142,72 @@ int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj,
 	}
 
 	obj->cache_level = cache_level;
+	i915_gem_verify_gtt(dev);
 	return 0;
 }
 
+int i915_gem_get_cacheing_ioctl(struct drm_device *dev, void *data,
+				struct drm_file *file)
+{
+	struct drm_i915_gem_cacheing *args = data;
+	struct drm_i915_gem_object *obj;
+	int ret;
+
+	ret = i915_mutex_lock_interruptible(dev);
+	if (ret)
+		return ret;
+
+	obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle));
+	if (&obj->base == NULL) {
+		ret = -ENOENT;
+		goto unlock;
+	}
+
+	args->cacheing = obj->cache_level != I915_CACHE_NONE;
+
+	drm_gem_object_unreference(&obj->base);
+unlock:
+	mutex_unlock(&dev->struct_mutex);
+	return ret;
+}
+
+int i915_gem_set_cacheing_ioctl(struct drm_device *dev, void *data,
+				struct drm_file *file)
+{
+	struct drm_i915_gem_cacheing *args = data;
+	struct drm_i915_gem_object *obj;
+	enum i915_cache_level level;
+	int ret;
+
+	ret = i915_mutex_lock_interruptible(dev);
+	if (ret)
+		return ret;
+
+	switch (args->cacheing) {
+	case I915_CACHEING_NONE:
+		level = I915_CACHE_NONE;
+		break;
+	case I915_CACHEING_CACHED:
+		level = I915_CACHE_LLC;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle));
+	if (&obj->base == NULL) {
+		ret = -ENOENT;
+		goto unlock;
+	}
+
+	ret = i915_gem_object_set_cache_level(obj, level);
+
+	drm_gem_object_unreference(&obj->base);
+unlock:
+	mutex_unlock(&dev->struct_mutex);
+	return ret;
+}
+
 /*
  * Prepare buffer for display plane (scanout, cursors, etc).
  * Can be called from an uninterruptible phase (modesetting) and allows
@@ -3062,10 +3221,6 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj,
 	u32 old_read_domains, old_write_domain;
 	int ret;
 
-	ret = i915_gem_object_flush_gpu_write_domain(obj);
-	if (ret)
-		return ret;
-
 	if (pipelined != obj->ring) {
 		ret = i915_gem_object_sync(obj, pipelined);
 		if (ret)
@@ -3089,7 +3244,7 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj,
 	 * (e.g. libkms for the bootup splash), we have to ensure that we
 	 * always use map_and_fenceable for all scanout buffers.
 	 */
-	ret = i915_gem_object_pin(obj, alignment, true);
+	ret = i915_gem_object_pin(obj, alignment, true, false);
 	if (ret)
 		return ret;
 
@@ -3101,7 +3256,7 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj,
 	/* It should now be out of any other write domains, and we can update
 	 * the domain values for our changes.
 	 */
-	BUG_ON((obj->base.write_domain & ~I915_GEM_DOMAIN_GTT) != 0);
+	obj->base.write_domain = 0;
 	obj->base.read_domains |= I915_GEM_DOMAIN_GTT;
 
 	trace_i915_gem_object_change_domain(obj,
@@ -3119,13 +3274,7 @@ i915_gem_object_finish_gpu(struct drm_i915_gem_object *obj)
 	if ((obj->base.read_domains & I915_GEM_GPU_DOMAINS) == 0)
 		return 0;
 
-	if (obj->base.write_domain & I915_GEM_GPU_DOMAINS) {
-		ret = i915_gem_flush_ring(obj->ring, 0, obj->base.write_domain);
-		if (ret)
-			return ret;
-	}
-
-	ret = i915_gem_object_wait_rendering(obj);
+	ret = i915_gem_object_wait_rendering(obj, false);
 	if (ret)
 		return ret;
 
@@ -3149,16 +3298,10 @@ i915_gem_object_set_to_cpu_domain(struct drm_i915_gem_object *obj, bool write)
 	if (obj->base.write_domain == I915_GEM_DOMAIN_CPU)
 		return 0;
 
-	ret = i915_gem_object_flush_gpu_write_domain(obj);
+	ret = i915_gem_object_wait_rendering(obj, !write);
 	if (ret)
 		return ret;
 
-	if (write || obj->pending_gpu_write) {
-		ret = i915_gem_object_wait_rendering(obj);
-		if (ret)
-			return ret;
-	}
-
 	i915_gem_object_flush_gtt_write_domain(obj);
 
 	old_write_domain = obj->base.write_domain;
@@ -3238,7 +3381,8 @@ i915_gem_ring_throttle(struct drm_device *dev, struct drm_file *file)
 int
 i915_gem_object_pin(struct drm_i915_gem_object *obj,
 		    uint32_t alignment,
-		    bool map_and_fenceable)
+		    bool map_and_fenceable,
+		    bool nonblocking)
 {
 	int ret;
 
@@ -3263,7 +3407,8 @@ i915_gem_object_pin(struct drm_i915_gem_object *obj,
 
 	if (obj->gtt_space == NULL) {
 		ret = i915_gem_object_bind_to_gtt(obj, alignment,
-						  map_and_fenceable);
+						  map_and_fenceable,
+						  nonblocking);
 		if (ret)
 			return ret;
 	}
@@ -3321,7 +3466,7 @@ i915_gem_pin_ioctl(struct drm_device *dev, void *data,
 	obj->user_pin_count++;
 	obj->pin_filp = file;
 	if (obj->user_pin_count == 1) {
-		ret = i915_gem_object_pin(obj, args->alignment, true);
+		ret = i915_gem_object_pin(obj, args->alignment, true, false);
 		if (ret)
 			goto out;
 	}
@@ -3401,6 +3546,10 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data,
 	ret = i915_gem_object_flush_active(obj);
 
 	args->busy = obj->active;
+	if (obj->ring) {
+		BUILD_BUG_ON(I915_NUM_RINGS > 16);
+		args->busy |= intel_ring_flag(obj->ring) << 16;
+	}
 
 	drm_gem_object_unreference(&obj->base);
 unlock:
@@ -3449,9 +3598,8 @@ i915_gem_madvise_ioctl(struct drm_device *dev, void *data,
 	if (obj->madv != __I915_MADV_PURGED)
 		obj->madv = args->madv;
 
-	/* if the object is no longer bound, discard its backing storage */
-	if (i915_gem_object_is_purgeable(obj) &&
-	    obj->gtt_space == NULL)
+	/* if the object is no longer attached, discard its backing storage */
+	if (i915_gem_object_is_purgeable(obj) && obj->pages == NULL)
 		i915_gem_object_truncate(obj);
 
 	args->retained = obj->madv != __I915_MADV_PURGED;
@@ -3463,10 +3611,26 @@ unlock:
 	return ret;
 }
 
+void i915_gem_object_init(struct drm_i915_gem_object *obj)
+{
+	obj->base.driver_private = NULL;
+
+	INIT_LIST_HEAD(&obj->mm_list);
+	INIT_LIST_HEAD(&obj->gtt_list);
+	INIT_LIST_HEAD(&obj->ring_list);
+	INIT_LIST_HEAD(&obj->exec_list);
+
+	obj->fence_reg = I915_FENCE_REG_NONE;
+	obj->madv = I915_MADV_WILLNEED;
+	/* Avoid an unnecessary call to unbind on the first bind. */
+	obj->map_and_fenceable = true;
+
+	i915_gem_info_add_obj(obj->base.dev->dev_private, obj->base.size);
+}
+
 struct drm_i915_gem_object *i915_gem_alloc_object(struct drm_device *dev,
 						  size_t size)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_i915_gem_object *obj;
 	struct address_space *mapping;
 	u32 mask;
@@ -3490,7 +3654,7 @@ struct drm_i915_gem_object *i915_gem_alloc_object(struct drm_device *dev,
 	mapping = obj->base.filp->f_path.dentry->d_inode->i_mapping;
 	mapping_set_gfp_mask(mapping, mask);
 
-	i915_gem_info_add_obj(dev_priv, size);
+	i915_gem_object_init(obj);
 
 	obj->base.write_domain = I915_GEM_DOMAIN_CPU;
 	obj->base.read_domains = I915_GEM_DOMAIN_CPU;
@@ -3512,17 +3676,6 @@ struct drm_i915_gem_object *i915_gem_alloc_object(struct drm_device *dev,
 	} else
 		obj->cache_level = I915_CACHE_NONE;
 
-	obj->base.driver_private = NULL;
-	obj->fence_reg = I915_FENCE_REG_NONE;
-	INIT_LIST_HEAD(&obj->mm_list);
-	INIT_LIST_HEAD(&obj->gtt_list);
-	INIT_LIST_HEAD(&obj->ring_list);
-	INIT_LIST_HEAD(&obj->exec_list);
-	INIT_LIST_HEAD(&obj->gpu_write_list);
-	obj->madv = I915_MADV_WILLNEED;
-	/* Avoid an unnecessary call to unbind on the first bind. */
-	obj->map_and_fenceable = true;
-
 	return obj;
 }
 
@@ -3559,8 +3712,8 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj)
 		dev_priv->mm.interruptible = was_interruptible;
 	}
 
-	if (obj->base.map_list.map)
-		drm_gem_free_mmap_offset(&obj->base);
+	i915_gem_object_put_pages_gtt(obj);
+	i915_gem_object_free_mmap_offset(obj);
 
 	drm_gem_object_release(&obj->base);
 	i915_gem_info_remove_obj(dev_priv, obj->base.size);
@@ -3591,7 +3744,7 @@ i915_gem_idle(struct drm_device *dev)
 
 	/* Under UMS, be paranoid and evict. */
 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
-		i915_gem_evict_everything(dev, false);
+		i915_gem_evict_everything(dev);
 
 	i915_gem_reset_fences(dev);
 
@@ -3892,7 +4045,6 @@ i915_gem_entervt_ioctl(struct drm_device *dev, void *data,
 	}
 
 	BUG_ON(!list_empty(&dev_priv->mm.active_list));
-	BUG_ON(!list_empty(&dev_priv->mm.flushing_list));
 	BUG_ON(!list_empty(&dev_priv->mm.inactive_list));
 	mutex_unlock(&dev->struct_mutex);
 
@@ -3940,7 +4092,6 @@ init_ring_lists(struct intel_ring_buffer *ring)
 {
 	INIT_LIST_HEAD(&ring->active_list);
 	INIT_LIST_HEAD(&ring->request_list);
-	INIT_LIST_HEAD(&ring->gpu_write_list);
 }
 
 void
@@ -3950,10 +4101,10 @@ i915_gem_load(struct drm_device *dev)
 	drm_i915_private_t *dev_priv = dev->dev_private;
 
 	INIT_LIST_HEAD(&dev_priv->mm.active_list);
-	INIT_LIST_HEAD(&dev_priv->mm.flushing_list);
 	INIT_LIST_HEAD(&dev_priv->mm.inactive_list);
+	INIT_LIST_HEAD(&dev_priv->mm.unbound_list);
+	INIT_LIST_HEAD(&dev_priv->mm.bound_list);
 	INIT_LIST_HEAD(&dev_priv->mm.fence_list);
-	INIT_LIST_HEAD(&dev_priv->mm.gtt_list);
 	for (i = 0; i < I915_NUM_RINGS; i++)
 		init_ring_lists(&dev_priv->ring[i]);
 	for (i = 0; i < I915_MAX_NUM_FENCES; i++)
@@ -4198,18 +4349,6 @@ void i915_gem_release(struct drm_device *dev, struct drm_file *file)
 }
 
 static int
-i915_gpu_is_active(struct drm_device *dev)
-{
-	drm_i915_private_t *dev_priv = dev->dev_private;
-	int lists_empty;
-
-	lists_empty = list_empty(&dev_priv->mm.flushing_list) &&
-		      list_empty(&dev_priv->mm.active_list);
-
-	return !lists_empty;
-}
-
-static int
 i915_gem_inactive_shrink(struct shrinker *shrinker, struct shrink_control *sc)
 {
 	struct drm_i915_private *dev_priv =
@@ -4217,60 +4356,26 @@ i915_gem_inactive_shrink(struct shrinker *shrinker, struct shrink_control *sc)
 			     struct drm_i915_private,
 			     mm.inactive_shrinker);
 	struct drm_device *dev = dev_priv->dev;
-	struct drm_i915_gem_object *obj, *next;
+	struct drm_i915_gem_object *obj;
 	int nr_to_scan = sc->nr_to_scan;
 	int cnt;
 
 	if (!mutex_trylock(&dev->struct_mutex))
 		return 0;
 
-	/* "fast-path" to count number of available objects */
-	if (nr_to_scan == 0) {
-		cnt = 0;
-		list_for_each_entry(obj,
-				    &dev_priv->mm.inactive_list,
-				    mm_list)
-			cnt++;
-		mutex_unlock(&dev->struct_mutex);
-		return cnt / 100 * sysctl_vfs_cache_pressure;
-	}
-
-rescan:
-	/* first scan for clean buffers */
-	i915_gem_retire_requests(dev);
-
-	list_for_each_entry_safe(obj, next,
-				 &dev_priv->mm.inactive_list,
-				 mm_list) {
-		if (i915_gem_object_is_purgeable(obj)) {
-			if (i915_gem_object_unbind(obj) == 0 &&
-			    --nr_to_scan == 0)
-				break;
-		}
+	if (nr_to_scan) {
+		nr_to_scan -= i915_gem_purge(dev_priv, nr_to_scan);
+		if (nr_to_scan > 0)
+			i915_gem_shrink_all(dev_priv);
 	}
 
-	/* second pass, evict/count anything still on the inactive list */
 	cnt = 0;
-	list_for_each_entry_safe(obj, next,
-				 &dev_priv->mm.inactive_list,
-				 mm_list) {
-		if (nr_to_scan &&
-		    i915_gem_object_unbind(obj) == 0)
-			nr_to_scan--;
-		else
-			cnt++;
-	}
+	list_for_each_entry(obj, &dev_priv->mm.unbound_list, gtt_list)
+		cnt += obj->base.size >> PAGE_SHIFT;
+	list_for_each_entry(obj, &dev_priv->mm.bound_list, gtt_list)
+		if (obj->pin_count == 0)
+			cnt += obj->base.size >> PAGE_SHIFT;
 
-	if (nr_to_scan && i915_gpu_is_active(dev)) {
-		/*
-		 * We are desperate for pages, so as a last resort, wait
-		 * for the GPU to finish and discard whatever we can.
-		 * This has a dramatic impact to reduce the number of
-		 * OOM-killer events whilst running the GPU aggressively.
-		 */
-		if (i915_gpu_idle(dev) == 0)
-			goto rescan;
-	}
 	mutex_unlock(&dev->struct_mutex);
-	return cnt / 100 * sysctl_vfs_cache_pressure;
+	return cnt;
 }
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c
index a9d58d7..4aa7ecf 100644
--- a/drivers/gpu/drm/i915/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/i915_gem_context.c
@@ -97,8 +97,7 @@
 
 static struct i915_hw_context *
 i915_gem_context_get(struct drm_i915_file_private *file_priv, u32 id);
-static int do_switch(struct drm_i915_gem_object *from_obj,
-		     struct i915_hw_context *to, u32 seqno);
+static int do_switch(struct i915_hw_context *to);
 
 static int get_context_size(struct drm_device *dev)
 {
@@ -113,7 +112,10 @@ static int get_context_size(struct drm_device *dev)
 		break;
 	case 7:
 		reg = I915_READ(GEN7_CXT_SIZE);
-		ret = GEN7_CXT_TOTAL_SIZE(reg) * 64;
+		if (IS_HASWELL(dev))
+			ret = HSW_CXT_TOTAL_SIZE(reg) * 64;
+		else
+			ret = GEN7_CXT_TOTAL_SIZE(reg) * 64;
 		break;
 	default:
 		BUG();
@@ -219,20 +221,21 @@ static int create_default_context(struct drm_i915_private *dev_priv)
 	 * default context.
 	 */
 	dev_priv->ring[RCS].default_context = ctx;
-	ret = i915_gem_object_pin(ctx->obj, CONTEXT_ALIGN, false);
-	if (ret) {
-		do_destroy(ctx);
-		return ret;
-	}
+	ret = i915_gem_object_pin(ctx->obj, CONTEXT_ALIGN, false, false);
+	if (ret)
+		goto err_destroy;
 
-	ret = do_switch(NULL, ctx, 0);
-	if (ret) {
-		i915_gem_object_unpin(ctx->obj);
-		do_destroy(ctx);
-	} else {
-		DRM_DEBUG_DRIVER("Default HW context loaded\n");
-	}
+	ret = do_switch(ctx);
+	if (ret)
+		goto err_unpin;
 
+	DRM_DEBUG_DRIVER("Default HW context loaded\n");
+	return 0;
+
+err_unpin:
+	i915_gem_object_unpin(ctx->obj);
+err_destroy:
+	do_destroy(ctx);
 	return ret;
 }
 
@@ -359,18 +362,19 @@ mi_set_context(struct intel_ring_buffer *ring,
 	return ret;
 }
 
-static int do_switch(struct drm_i915_gem_object *from_obj,
-		     struct i915_hw_context *to,
-		     u32 seqno)
+static int do_switch(struct i915_hw_context *to)
 {
-	struct intel_ring_buffer *ring = NULL;
+	struct intel_ring_buffer *ring = to->ring;
+	struct drm_i915_gem_object *from_obj = ring->last_context_obj;
 	u32 hw_flags = 0;
 	int ret;
 
-	BUG_ON(to == NULL);
 	BUG_ON(from_obj != NULL && from_obj->pin_count == 0);
 
-	ret = i915_gem_object_pin(to->obj, CONTEXT_ALIGN, false);
+	if (from_obj == to->obj)
+		return 0;
+
+	ret = i915_gem_object_pin(to->obj, CONTEXT_ALIGN, false, false);
 	if (ret)
 		return ret;
 
@@ -393,7 +397,6 @@ static int do_switch(struct drm_i915_gem_object *from_obj,
 	else if (WARN_ON_ONCE(from_obj == to->obj)) /* not yet expected */
 		hw_flags |= MI_FORCE_RESTORE;
 
-	ring = to->ring;
 	ret = mi_set_context(ring, to, hw_flags);
 	if (ret) {
 		i915_gem_object_unpin(to->obj);
@@ -407,6 +410,7 @@ static int do_switch(struct drm_i915_gem_object *from_obj,
 	 * MI_SET_CONTEXT instead of when the next seqno has completed.
 	 */
 	if (from_obj != NULL) {
+		u32 seqno = i915_gem_next_request_seqno(ring);
 		from_obj->base.read_domains = I915_GEM_DOMAIN_INSTRUCTION;
 		i915_gem_object_move_to_active(from_obj, ring, seqno);
 		/* As long as MI_SET_CONTEXT is serializing, ie. it flushes the
@@ -417,7 +421,7 @@ static int do_switch(struct drm_i915_gem_object *from_obj,
 		 * swapped, but there is no way to do that yet.
 		 */
 		from_obj->dirty = 1;
-		BUG_ON(from_obj->ring != to->ring);
+		BUG_ON(from_obj->ring != ring);
 		i915_gem_object_unpin(from_obj);
 
 		drm_gem_object_unreference(&from_obj->base);
@@ -448,9 +452,7 @@ int i915_switch_context(struct intel_ring_buffer *ring,
 			int to_id)
 {
 	struct drm_i915_private *dev_priv = ring->dev->dev_private;
-	struct drm_i915_file_private *file_priv = NULL;
 	struct i915_hw_context *to;
-	struct drm_i915_gem_object *from_obj = ring->last_context_obj;
 
 	if (dev_priv->hw_contexts_disabled)
 		return 0;
@@ -458,21 +460,18 @@ int i915_switch_context(struct intel_ring_buffer *ring,
 	if (ring != &dev_priv->ring[RCS])
 		return 0;
 
-	if (file)
-		file_priv = file->driver_priv;
-
 	if (to_id == DEFAULT_CONTEXT_ID) {
 		to = ring->default_context;
 	} else {
-		to = i915_gem_context_get(file_priv, to_id);
+		if (file == NULL)
+			return -EINVAL;
+
+		to = i915_gem_context_get(file->driver_priv, to_id);
 		if (to == NULL)
 			return -ENOENT;
 	}
 
-	if (from_obj == to->obj)
-		return 0;
-
-	return do_switch(from_obj, to, i915_gem_next_request_seqno(to->ring));
+	return do_switch(to);
 }
 
 int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
diff --git a/drivers/gpu/drm/i915/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/i915_gem_dmabuf.c
index aa308e1..43c9530 100644
--- a/drivers/gpu/drm/i915/i915_gem_dmabuf.c
+++ b/drivers/gpu/drm/i915/i915_gem_dmabuf.c
@@ -33,7 +33,7 @@ static struct sg_table *i915_gem_map_dma_buf(struct dma_buf_attachment *attachme
 	struct drm_i915_gem_object *obj = attachment->dmabuf->priv;
 	struct drm_device *dev = obj->base.dev;
 	int npages = obj->base.size / PAGE_SIZE;
-	struct sg_table *sg = NULL;
+	struct sg_table *sg;
 	int ret;
 	int nents;
 
@@ -41,10 +41,10 @@ static struct sg_table *i915_gem_map_dma_buf(struct dma_buf_attachment *attachme
 	if (ret)
 		return ERR_PTR(ret);
 
-	if (!obj->pages) {
-		ret = i915_gem_object_get_pages_gtt(obj, __GFP_NORETRY | __GFP_NOWARN);
-		if (ret)
-			goto out;
+	ret = i915_gem_object_get_pages_gtt(obj);
+	if (ret) {
+		sg = ERR_PTR(ret);
+		goto out;
 	}
 
 	/* link the pages into an SG then map the sg */
@@ -89,12 +89,10 @@ static void *i915_gem_dmabuf_vmap(struct dma_buf *dma_buf)
 		goto out_unlock;
 	}
 
-	if (!obj->pages) {
-		ret = i915_gem_object_get_pages_gtt(obj, __GFP_NORETRY | __GFP_NOWARN);
-		if (ret) {
-			mutex_unlock(&dev->struct_mutex);
-			return ERR_PTR(ret);
-		}
+	ret = i915_gem_object_get_pages_gtt(obj);
+	if (ret) {
+		mutex_unlock(&dev->struct_mutex);
+		return ERR_PTR(ret);
 	}
 
 	obj->dma_buf_vmapping = vmap(obj->pages, obj->base.size / PAGE_SIZE, 0, PAGE_KERNEL);
@@ -151,6 +149,22 @@ static int i915_gem_dmabuf_mmap(struct dma_buf *dma_buf, struct vm_area_struct *
 	return -EINVAL;
 }
 
+static int i915_gem_begin_cpu_access(struct dma_buf *dma_buf, size_t start, size_t length, enum dma_data_direction direction)
+{
+	struct drm_i915_gem_object *obj = dma_buf->priv;
+	struct drm_device *dev = obj->base.dev;
+	int ret;
+	bool write = (direction == DMA_BIDIRECTIONAL || direction == DMA_TO_DEVICE);
+
+	ret = i915_mutex_lock_interruptible(dev);
+	if (ret)
+		return ret;
+
+	ret = i915_gem_object_set_to_cpu_domain(obj, write);
+	mutex_unlock(&dev->struct_mutex);
+	return ret;
+}
+
 static const struct dma_buf_ops i915_dmabuf_ops =  {
 	.map_dma_buf = i915_gem_map_dma_buf,
 	.unmap_dma_buf = i915_gem_unmap_dma_buf,
@@ -162,6 +176,7 @@ static const struct dma_buf_ops i915_dmabuf_ops =  {
 	.mmap = i915_gem_dmabuf_mmap,
 	.vmap = i915_gem_dmabuf_vmap,
 	.vunmap = i915_gem_dmabuf_vunmap,
+	.begin_cpu_access = i915_gem_begin_cpu_access,
 };
 
 struct dma_buf *i915_gem_prime_export(struct drm_device *dev,
diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c
index eba0308..a2d8acd 100644
--- a/drivers/gpu/drm/i915/i915_gem_evict.c
+++ b/drivers/gpu/drm/i915/i915_gem_evict.c
@@ -44,7 +44,8 @@ mark_free(struct drm_i915_gem_object *obj, struct list_head *unwind)
 
 int
 i915_gem_evict_something(struct drm_device *dev, int min_size,
-			 unsigned alignment, bool mappable)
+			 unsigned alignment, unsigned cache_level,
+			 bool mappable, bool nonblocking)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct list_head eviction_list, unwind_list;
@@ -79,11 +80,11 @@ i915_gem_evict_something(struct drm_device *dev, int min_size,
 	INIT_LIST_HEAD(&unwind_list);
 	if (mappable)
 		drm_mm_init_scan_with_range(&dev_priv->mm.gtt_space,
-					    min_size, alignment, 0,
+					    min_size, alignment, cache_level,
 					    0, dev_priv->mm.gtt_mappable_end);
 	else
 		drm_mm_init_scan(&dev_priv->mm.gtt_space,
-				 min_size, alignment, 0);
+				 min_size, alignment, cache_level);
 
 	/* First see if there is a large enough contiguous idle region... */
 	list_for_each_entry(obj, &dev_priv->mm.inactive_list, mm_list) {
@@ -91,29 +92,16 @@ i915_gem_evict_something(struct drm_device *dev, int min_size,
 			goto found;
 	}
 
-	/* Now merge in the soon-to-be-expired objects... */
-	list_for_each_entry(obj, &dev_priv->mm.active_list, mm_list) {
-		/* Does the object require an outstanding flush? */
-		if (obj->base.write_domain)
-			continue;
-
-		if (mark_free(obj, &unwind_list))
-			goto found;
-	}
+	if (nonblocking)
+		goto none;
 
-	/* Finally add anything with a pending flush (in order of retirement) */
-	list_for_each_entry(obj, &dev_priv->mm.flushing_list, mm_list) {
-		if (mark_free(obj, &unwind_list))
-			goto found;
-	}
+	/* Now merge in the soon-to-be-expired objects... */
 	list_for_each_entry(obj, &dev_priv->mm.active_list, mm_list) {
-		if (!obj->base.write_domain)
-			continue;
-
 		if (mark_free(obj, &unwind_list))
 			goto found;
 	}
 
+none:
 	/* Nothing found, clean up and bail out! */
 	while (!list_empty(&unwind_list)) {
 		obj = list_first_entry(&unwind_list,
@@ -164,7 +152,7 @@ found:
 }
 
 int
-i915_gem_evict_everything(struct drm_device *dev, bool purgeable_only)
+i915_gem_evict_everything(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct drm_i915_gem_object *obj, *next;
@@ -172,12 +160,11 @@ i915_gem_evict_everything(struct drm_device *dev, bool purgeable_only)
 	int ret;
 
 	lists_empty = (list_empty(&dev_priv->mm.inactive_list) &&
-		       list_empty(&dev_priv->mm.flushing_list) &&
 		       list_empty(&dev_priv->mm.active_list));
 	if (lists_empty)
 		return -ENOSPC;
 
-	trace_i915_gem_evict_everything(dev, purgeable_only);
+	trace_i915_gem_evict_everything(dev);
 
 	/* The gpu_idle will flush everything in the write domain to the
 	 * active list. Then we must move everything off the active list
@@ -189,16 +176,11 @@ i915_gem_evict_everything(struct drm_device *dev, bool purgeable_only)
 
 	i915_gem_retire_requests(dev);
 
-	BUG_ON(!list_empty(&dev_priv->mm.flushing_list));
-
 	/* Having flushed everything, unbind() should never raise an error */
 	list_for_each_entry_safe(obj, next,
-				 &dev_priv->mm.inactive_list, mm_list) {
-		if (!purgeable_only || obj->madv != I915_MADV_WILLNEED) {
-			if (obj->pin_count == 0)
-				WARN_ON(i915_gem_object_unbind(obj));
-		}
-	}
+				 &dev_priv->mm.inactive_list, mm_list)
+		if (obj->pin_count == 0)
+			WARN_ON(i915_gem_object_unbind(obj));
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index ff2819e..e6b2205 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -34,180 +34,6 @@
 #include "intel_drv.h"
 #include <linux/dma_remapping.h>
 
-struct change_domains {
-	uint32_t invalidate_domains;
-	uint32_t flush_domains;
-	uint32_t flush_rings;
-	uint32_t flips;
-};
-
-/*
- * Set the next domain for the specified object. This
- * may not actually perform the necessary flushing/invaliding though,
- * as that may want to be batched with other set_domain operations
- *
- * This is (we hope) the only really tricky part of gem. The goal
- * is fairly simple -- track which caches hold bits of the object
- * and make sure they remain coherent. A few concrete examples may
- * help to explain how it works. For shorthand, we use the notation
- * (read_domains, write_domain), e.g. (CPU, CPU) to indicate the
- * a pair of read and write domain masks.
- *
- * Case 1: the batch buffer
- *
- *	1. Allocated
- *	2. Written by CPU
- *	3. Mapped to GTT
- *	4. Read by GPU
- *	5. Unmapped from GTT
- *	6. Freed
- *
- *	Let's take these a step at a time
- *
- *	1. Allocated
- *		Pages allocated from the kernel may still have
- *		cache contents, so we set them to (CPU, CPU) always.
- *	2. Written by CPU (using pwrite)
- *		The pwrite function calls set_domain (CPU, CPU) and
- *		this function does nothing (as nothing changes)
- *	3. Mapped by GTT
- *		This function asserts that the object is not
- *		currently in any GPU-based read or write domains
- *	4. Read by GPU
- *		i915_gem_execbuffer calls set_domain (COMMAND, 0).
- *		As write_domain is zero, this function adds in the
- *		current read domains (CPU+COMMAND, 0).
- *		flush_domains is set to CPU.
- *		invalidate_domains is set to COMMAND
- *		clflush is run to get data out of the CPU caches
- *		then i915_dev_set_domain calls i915_gem_flush to
- *		emit an MI_FLUSH and drm_agp_chipset_flush
- *	5. Unmapped from GTT
- *		i915_gem_object_unbind calls set_domain (CPU, CPU)
- *		flush_domains and invalidate_domains end up both zero
- *		so no flushing/invalidating happens
- *	6. Freed
- *		yay, done
- *
- * Case 2: The shared render buffer
- *
- *	1. Allocated
- *	2. Mapped to GTT
- *	3. Read/written by GPU
- *	4. set_domain to (CPU,CPU)
- *	5. Read/written by CPU
- *	6. Read/written by GPU
- *
- *	1. Allocated
- *		Same as last example, (CPU, CPU)
- *	2. Mapped to GTT
- *		Nothing changes (assertions find that it is not in the GPU)
- *	3. Read/written by GPU
- *		execbuffer calls set_domain (RENDER, RENDER)
- *		flush_domains gets CPU
- *		invalidate_domains gets GPU
- *		clflush (obj)
- *		MI_FLUSH and drm_agp_chipset_flush
- *	4. set_domain (CPU, CPU)
- *		flush_domains gets GPU
- *		invalidate_domains gets CPU
- *		wait_rendering (obj) to make sure all drawing is complete.
- *		This will include an MI_FLUSH to get the data from GPU
- *		to memory
- *		clflush (obj) to invalidate the CPU cache
- *		Another MI_FLUSH in i915_gem_flush (eliminate this somehow?)
- *	5. Read/written by CPU
- *		cache lines are loaded and dirtied
- *	6. Read written by GPU
- *		Same as last GPU access
- *
- * Case 3: The constant buffer
- *
- *	1. Allocated
- *	2. Written by CPU
- *	3. Read by GPU
- *	4. Updated (written) by CPU again
- *	5. Read by GPU
- *
- *	1. Allocated
- *		(CPU, CPU)
- *	2. Written by CPU
- *		(CPU, CPU)
- *	3. Read by GPU
- *		(CPU+RENDER, 0)
- *		flush_domains = CPU
- *		invalidate_domains = RENDER
- *		clflush (obj)
- *		MI_FLUSH
- *		drm_agp_chipset_flush
- *	4. Updated (written) by CPU again
- *		(CPU, CPU)
- *		flush_domains = 0 (no previous write domain)
- *		invalidate_domains = 0 (no new read domains)
- *	5. Read by GPU
- *		(CPU+RENDER, 0)
- *		flush_domains = CPU
- *		invalidate_domains = RENDER
- *		clflush (obj)
- *		MI_FLUSH
- *		drm_agp_chipset_flush
- */
-static void
-i915_gem_object_set_to_gpu_domain(struct drm_i915_gem_object *obj,
-				  struct intel_ring_buffer *ring,
-				  struct change_domains *cd)
-{
-	uint32_t invalidate_domains = 0, flush_domains = 0;
-
-	/*
-	 * If the object isn't moving to a new write domain,
-	 * let the object stay in multiple read domains
-	 */
-	if (obj->base.pending_write_domain == 0)
-		obj->base.pending_read_domains |= obj->base.read_domains;
-
-	/*
-	 * Flush the current write domain if
-	 * the new read domains don't match. Invalidate
-	 * any read domains which differ from the old
-	 * write domain
-	 */
-	if (obj->base.write_domain &&
-	    (((obj->base.write_domain != obj->base.pending_read_domains ||
-	       obj->ring != ring)) ||
-	     (obj->fenced_gpu_access && !obj->pending_fenced_gpu_access))) {
-		flush_domains |= obj->base.write_domain;
-		invalidate_domains |=
-			obj->base.pending_read_domains & ~obj->base.write_domain;
-	}
-	/*
-	 * Invalidate any read caches which may have
-	 * stale data. That is, any new read domains.
-	 */
-	invalidate_domains |= obj->base.pending_read_domains & ~obj->base.read_domains;
-	if ((flush_domains | invalidate_domains) & I915_GEM_DOMAIN_CPU)
-		i915_gem_clflush_object(obj);
-
-	if (obj->base.pending_write_domain)
-		cd->flips |= atomic_read(&obj->pending_flip);
-
-	/* The actual obj->write_domain will be updated with
-	 * pending_write_domain after we emit the accumulated flush for all
-	 * of our domain changes in execbuffers (which clears objects'
-	 * write_domains).  So if we have a current write domain that we
-	 * aren't changing, set pending_write_domain to that.
-	 */
-	if (flush_domains == 0 && obj->base.pending_write_domain == 0)
-		obj->base.pending_write_domain = obj->base.write_domain;
-
-	cd->invalidate_domains |= invalidate_domains;
-	cd->flush_domains |= flush_domains;
-	if (flush_domains & I915_GEM_GPU_DOMAINS)
-		cd->flush_rings |= intel_ring_flag(obj->ring);
-	if (invalidate_domains & I915_GEM_GPU_DOMAINS)
-		cd->flush_rings |= intel_ring_flag(ring);
-}
-
 struct eb_objects {
 	int and;
 	struct hlist_head buckets[0];
@@ -269,6 +95,7 @@ eb_destroy(struct eb_objects *eb)
 static inline int use_cpu_reloc(struct drm_i915_gem_object *obj)
 {
 	return (obj->base.write_domain == I915_GEM_DOMAIN_CPU ||
+		!obj->map_and_fenceable ||
 		obj->cache_level != I915_CACHE_NONE);
 }
 
@@ -504,7 +331,8 @@ i915_gem_execbuffer_relocate(struct drm_device *dev,
 	return ret;
 }
 
-#define  __EXEC_OBJECT_HAS_FENCE (1<<31)
+#define  __EXEC_OBJECT_HAS_PIN (1<<31)
+#define  __EXEC_OBJECT_HAS_FENCE (1<<30)
 
 static int
 need_reloc_mappable(struct drm_i915_gem_object *obj)
@@ -514,9 +342,10 @@ need_reloc_mappable(struct drm_i915_gem_object *obj)
 }
 
 static int
-pin_and_fence_object(struct drm_i915_gem_object *obj,
-		     struct intel_ring_buffer *ring)
+i915_gem_execbuffer_reserve_object(struct drm_i915_gem_object *obj,
+				   struct intel_ring_buffer *ring)
 {
+	struct drm_i915_private *dev_priv = obj->base.dev->dev_private;
 	struct drm_i915_gem_exec_object2 *entry = obj->exec_entry;
 	bool has_fenced_gpu_access = INTEL_INFO(ring->dev)->gen < 4;
 	bool need_fence, need_mappable;
@@ -528,15 +357,17 @@ pin_and_fence_object(struct drm_i915_gem_object *obj,
 		obj->tiling_mode != I915_TILING_NONE;
 	need_mappable = need_fence || need_reloc_mappable(obj);
 
-	ret = i915_gem_object_pin(obj, entry->alignment, need_mappable);
+	ret = i915_gem_object_pin(obj, entry->alignment, need_mappable, false);
 	if (ret)
 		return ret;
 
+	entry->flags |= __EXEC_OBJECT_HAS_PIN;
+
 	if (has_fenced_gpu_access) {
 		if (entry->flags & EXEC_OBJECT_NEEDS_FENCE) {
 			ret = i915_gem_object_get_fence(obj);
 			if (ret)
-				goto err_unpin;
+				return ret;
 
 			if (i915_gem_object_pin_fence(obj))
 				entry->flags |= __EXEC_OBJECT_HAS_FENCE;
@@ -545,12 +376,35 @@ pin_and_fence_object(struct drm_i915_gem_object *obj,
 		}
 	}
 
+	/* Ensure ppgtt mapping exists if needed */
+	if (dev_priv->mm.aliasing_ppgtt && !obj->has_aliasing_ppgtt_mapping) {
+		i915_ppgtt_bind_object(dev_priv->mm.aliasing_ppgtt,
+				       obj, obj->cache_level);
+
+		obj->has_aliasing_ppgtt_mapping = 1;
+	}
+
 	entry->offset = obj->gtt_offset;
 	return 0;
+}
 
-err_unpin:
-	i915_gem_object_unpin(obj);
-	return ret;
+static void
+i915_gem_execbuffer_unreserve_object(struct drm_i915_gem_object *obj)
+{
+	struct drm_i915_gem_exec_object2 *entry;
+
+	if (!obj->gtt_space)
+		return;
+
+	entry = obj->exec_entry;
+
+	if (entry->flags & __EXEC_OBJECT_HAS_FENCE)
+		i915_gem_object_unpin_fence(obj);
+
+	if (entry->flags & __EXEC_OBJECT_HAS_PIN)
+		i915_gem_object_unpin(obj);
+
+	entry->flags &= ~(__EXEC_OBJECT_HAS_FENCE | __EXEC_OBJECT_HAS_PIN);
 }
 
 static int
@@ -558,11 +412,10 @@ i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring,
 			    struct drm_file *file,
 			    struct list_head *objects)
 {
-	drm_i915_private_t *dev_priv = ring->dev->dev_private;
 	struct drm_i915_gem_object *obj;
-	int ret, retry;
-	bool has_fenced_gpu_access = INTEL_INFO(ring->dev)->gen < 4;
 	struct list_head ordered_objects;
+	bool has_fenced_gpu_access = INTEL_INFO(ring->dev)->gen < 4;
+	int retry;
 
 	INIT_LIST_HEAD(&ordered_objects);
 	while (!list_empty(objects)) {
@@ -587,6 +440,7 @@ i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring,
 
 		obj->base.pending_read_domains = 0;
 		obj->base.pending_write_domain = 0;
+		obj->pending_fenced_gpu_access = false;
 	}
 	list_splice(&ordered_objects, objects);
 
@@ -599,12 +453,12 @@ i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring,
 	 * 2.  Bind new objects.
 	 * 3.  Decrement pin count.
 	 *
-	 * This avoid unnecessary unbinding of later objects in order to makr
+	 * This avoid unnecessary unbinding of later objects in order to make
 	 * room for the earlier objects *unless* we need to defragment.
 	 */
 	retry = 0;
 	do {
-		ret = 0;
+		int ret = 0;
 
 		/* Unbind any ill-fitting objects or pin. */
 		list_for_each_entry(obj, objects, exec_list) {
@@ -624,7 +478,7 @@ i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring,
 			    (need_mappable && !obj->map_and_fenceable))
 				ret = i915_gem_object_unbind(obj);
 			else
-				ret = pin_and_fence_object(obj, ring);
+				ret = i915_gem_execbuffer_reserve_object(obj, ring);
 			if (ret)
 				goto err;
 		}
@@ -634,77 +488,22 @@ i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring,
 			if (obj->gtt_space)
 				continue;
 
-			ret = pin_and_fence_object(obj, ring);
-			if (ret) {
-				int ret_ignore;
-
-				/* This can potentially raise a harmless
-				 * -EINVAL if we failed to bind in the above
-				 * call. It cannot raise -EINTR since we know
-				 * that the bo is freshly bound and so will
-				 * not need to be flushed or waited upon.
-				 */
-				ret_ignore = i915_gem_object_unbind(obj);
-				(void)ret_ignore;
-				WARN_ON(obj->gtt_space);
-				break;
-			}
+			ret = i915_gem_execbuffer_reserve_object(obj, ring);
+			if (ret)
+				goto err;
 		}
 
-		/* Decrement pin count for bound objects */
-		list_for_each_entry(obj, objects, exec_list) {
-			struct drm_i915_gem_exec_object2 *entry;
-
-			if (!obj->gtt_space)
-				continue;
-
-			entry = obj->exec_entry;
-			if (entry->flags & __EXEC_OBJECT_HAS_FENCE) {
-				i915_gem_object_unpin_fence(obj);
-				entry->flags &= ~__EXEC_OBJECT_HAS_FENCE;
-			}
-
-			i915_gem_object_unpin(obj);
+err:		/* Decrement pin count for bound objects */
+		list_for_each_entry(obj, objects, exec_list)
+			i915_gem_execbuffer_unreserve_object(obj);
 
-			/* ... and ensure ppgtt mapping exist if needed. */
-			if (dev_priv->mm.aliasing_ppgtt && !obj->has_aliasing_ppgtt_mapping) {
-				i915_ppgtt_bind_object(dev_priv->mm.aliasing_ppgtt,
-						       obj, obj->cache_level);
-
-				obj->has_aliasing_ppgtt_mapping = 1;
-			}
-		}
-
-		if (ret != -ENOSPC || retry > 1)
+		if (ret != -ENOSPC || retry++)
 			return ret;
 
-		/* First attempt, just clear anything that is purgeable.
-		 * Second attempt, clear the entire GTT.
-		 */
-		ret = i915_gem_evict_everything(ring->dev, retry == 0);
+		ret = i915_gem_evict_everything(ring->dev);
 		if (ret)
 			return ret;
-
-		retry++;
 	} while (1);
-
-err:
-	list_for_each_entry_continue_reverse(obj, objects, exec_list) {
-		struct drm_i915_gem_exec_object2 *entry;
-
-		if (!obj->gtt_space)
-			continue;
-
-		entry = obj->exec_entry;
-		if (entry->flags & __EXEC_OBJECT_HAS_FENCE) {
-			i915_gem_object_unpin_fence(obj);
-			entry->flags &= ~__EXEC_OBJECT_HAS_FENCE;
-		}
-
-		i915_gem_object_unpin(obj);
-	}
-
-	return ret;
 }
 
 static int
@@ -810,18 +609,6 @@ err:
 	return ret;
 }
 
-static void
-i915_gem_execbuffer_flush(struct drm_device *dev,
-			  uint32_t invalidate_domains,
-			  uint32_t flush_domains)
-{
-	if (flush_domains & I915_GEM_DOMAIN_CPU)
-		intel_gtt_chipset_flush();
-
-	if (flush_domains & I915_GEM_DOMAIN_GTT)
-		wmb();
-}
-
 static int
 i915_gem_execbuffer_wait_for_flips(struct intel_ring_buffer *ring, u32 flips)
 {
@@ -854,48 +641,45 @@ i915_gem_execbuffer_wait_for_flips(struct intel_ring_buffer *ring, u32 flips)
 	return 0;
 }
 
-
 static int
 i915_gem_execbuffer_move_to_gpu(struct intel_ring_buffer *ring,
 				struct list_head *objects)
 {
 	struct drm_i915_gem_object *obj;
-	struct change_domains cd;
+	uint32_t flush_domains = 0;
+	uint32_t flips = 0;
 	int ret;
 
-	memset(&cd, 0, sizeof(cd));
-	list_for_each_entry(obj, objects, exec_list)
-		i915_gem_object_set_to_gpu_domain(obj, ring, &cd);
-
-	if (cd.invalidate_domains | cd.flush_domains) {
-		i915_gem_execbuffer_flush(ring->dev,
-					  cd.invalidate_domains,
-					  cd.flush_domains);
-	}
-
-	if (cd.flips) {
-		ret = i915_gem_execbuffer_wait_for_flips(ring, cd.flips);
+	list_for_each_entry(obj, objects, exec_list) {
+		ret = i915_gem_object_sync(obj, ring);
 		if (ret)
 			return ret;
+
+		if (obj->base.write_domain & I915_GEM_DOMAIN_CPU)
+			i915_gem_clflush_object(obj);
+
+		if (obj->base.pending_write_domain)
+			flips |= atomic_read(&obj->pending_flip);
+
+		flush_domains |= obj->base.write_domain;
 	}
 
-	list_for_each_entry(obj, objects, exec_list) {
-		ret = i915_gem_object_sync(obj, ring);
+	if (flips) {
+		ret = i915_gem_execbuffer_wait_for_flips(ring, flips);
 		if (ret)
 			return ret;
 	}
 
+	if (flush_domains & I915_GEM_DOMAIN_CPU)
+		intel_gtt_chipset_flush();
+
+	if (flush_domains & I915_GEM_DOMAIN_GTT)
+		wmb();
+
 	/* Unconditionally invalidate gpu caches and ensure that we do flush
 	 * any residual writes from the previous batch.
 	 */
-	ret = i915_gem_flush_ring(ring,
-				  I915_GEM_GPU_DOMAINS,
-				  ring->gpu_caches_dirty ? I915_GEM_GPU_DOMAINS : 0);
-	if (ret)
-		return ret;
-
-	ring->gpu_caches_dirty = false;
-	return 0;
+	return intel_ring_invalidate_all_caches(ring);
 }
 
 static bool
@@ -943,9 +727,8 @@ i915_gem_execbuffer_move_to_active(struct list_head *objects,
 	struct drm_i915_gem_object *obj;
 
 	list_for_each_entry(obj, objects, exec_list) {
-		  u32 old_read = obj->base.read_domains;
-		  u32 old_write = obj->base.write_domain;
-
+		u32 old_read = obj->base.read_domains;
+		u32 old_write = obj->base.write_domain;
 
 		obj->base.read_domains = obj->base.pending_read_domains;
 		obj->base.write_domain = obj->base.pending_write_domain;
@@ -954,17 +737,13 @@ i915_gem_execbuffer_move_to_active(struct list_head *objects,
 		i915_gem_object_move_to_active(obj, ring, seqno);
 		if (obj->base.write_domain) {
 			obj->dirty = 1;
-			obj->pending_gpu_write = true;
-			list_move_tail(&obj->gpu_write_list,
-				       &ring->gpu_write_list);
+			obj->last_write_seqno = seqno;
 			if (obj->pin_count) /* check for potential scanout */
-				intel_mark_busy(ring->dev, obj);
+				intel_mark_fb_busy(obj);
 		}
 
 		trace_i915_gem_object_change_domain(obj, old_read, old_write);
 	}
-
-	intel_mark_busy(ring->dev, NULL);
 }
 
 static void
@@ -972,16 +751,11 @@ i915_gem_execbuffer_retire_commands(struct drm_device *dev,
 				    struct drm_file *file,
 				    struct intel_ring_buffer *ring)
 {
-	struct drm_i915_gem_request *request;
-
 	/* Unconditionally force add_request to emit a full flush. */
 	ring->gpu_caches_dirty = true;
 
 	/* Add a breadcrumb for the completion of the batch buffer */
-	request = kzalloc(sizeof(*request), GFP_KERNEL);
-	if (request == NULL || i915_add_request(ring, file, request)) {
-		kfree(request);
-	}
+	(void)i915_add_request(ring, file, NULL);
 }
 
 static int
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index 60815b8..1f7516a 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -351,7 +351,7 @@ void i915_gem_restore_gtt_mappings(struct drm_device *dev)
 	intel_gtt_clear_range(dev_priv->mm.gtt_start / PAGE_SIZE,
 			      (dev_priv->mm.gtt_end - dev_priv->mm.gtt_start) / PAGE_SIZE);
 
-	list_for_each_entry(obj, &dev_priv->mm.gtt_list, gtt_list) {
+	list_for_each_entry(obj, &dev_priv->mm.bound_list, gtt_list) {
 		i915_gem_clflush_object(obj);
 		i915_gem_gtt_bind_object(obj, obj->cache_level);
 	}
@@ -426,6 +426,23 @@ void i915_gem_gtt_finish_object(struct drm_i915_gem_object *obj)
 	undo_idling(dev_priv, interruptible);
 }
 
+static void i915_gtt_color_adjust(struct drm_mm_node *node,
+				  unsigned long color,
+				  unsigned long *start,
+				  unsigned long *end)
+{
+	if (node->color != color)
+		*start += 4096;
+
+	if (!list_empty(&node->node_list)) {
+		node = list_entry(node->node_list.next,
+				  struct drm_mm_node,
+				  node_list);
+		if (node->allocated && node->color != color)
+			*end -= 4096;
+	}
+}
+
 void i915_gem_init_global_gtt(struct drm_device *dev,
 			      unsigned long start,
 			      unsigned long mappable_end,
@@ -435,6 +452,8 @@ void i915_gem_init_global_gtt(struct drm_device *dev,
 
 	/* Substract the guard page ... */
 	drm_mm_init(&dev_priv->mm.gtt_space, start, end - start - PAGE_SIZE);
+	if (!HAS_LLC(dev))
+		dev_priv->mm.gtt_space.color_adjust = i915_gtt_color_adjust;
 
 	dev_priv->mm.gtt_start = start;
 	dev_priv->mm.gtt_mappable_end = mappable_end;
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 5249640..9192936 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -296,11 +296,21 @@ static void i915_hotplug_work_func(struct work_struct *work)
 	drm_helper_hpd_irq_event(dev);
 }
 
-static void i915_handle_rps_change(struct drm_device *dev)
+/* defined intel_pm.c */
+extern spinlock_t mchdev_lock;
+
+static void ironlake_handle_rps_change(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	u32 busy_up, busy_down, max_avg, min_avg;
-	u8 new_delay = dev_priv->cur_delay;
+	u8 new_delay;
+	unsigned long flags;
+
+	spin_lock_irqsave(&mchdev_lock, flags);
+
+	I915_WRITE16(MEMINTRSTS, I915_READ(MEMINTRSTS));
+
+	new_delay = dev_priv->ips.cur_delay;
 
 	I915_WRITE16(MEMINTRSTS, MEMINT_EVAL_CHG);
 	busy_up = I915_READ(RCPREVBSYTUPAVG);
@@ -310,19 +320,21 @@ static void i915_handle_rps_change(struct drm_device *dev)
 
 	/* Handle RCS change request from hw */
 	if (busy_up > max_avg) {
-		if (dev_priv->cur_delay != dev_priv->max_delay)
-			new_delay = dev_priv->cur_delay - 1;
-		if (new_delay < dev_priv->max_delay)
-			new_delay = dev_priv->max_delay;
+		if (dev_priv->ips.cur_delay != dev_priv->ips.max_delay)
+			new_delay = dev_priv->ips.cur_delay - 1;
+		if (new_delay < dev_priv->ips.max_delay)
+			new_delay = dev_priv->ips.max_delay;
 	} else if (busy_down < min_avg) {
-		if (dev_priv->cur_delay != dev_priv->min_delay)
-			new_delay = dev_priv->cur_delay + 1;
-		if (new_delay > dev_priv->min_delay)
-			new_delay = dev_priv->min_delay;
+		if (dev_priv->ips.cur_delay != dev_priv->ips.min_delay)
+			new_delay = dev_priv->ips.cur_delay + 1;
+		if (new_delay > dev_priv->ips.min_delay)
+			new_delay = dev_priv->ips.min_delay;
 	}
 
 	if (ironlake_set_drps(dev, new_delay))
-		dev_priv->cur_delay = new_delay;
+		dev_priv->ips.cur_delay = new_delay;
+
+	spin_unlock_irqrestore(&mchdev_lock, flags);
 
 	return;
 }
@@ -335,7 +347,7 @@ static void notify_ring(struct drm_device *dev,
 	if (ring->obj == NULL)
 		return;
 
-	trace_i915_gem_request_complete(ring, ring->get_seqno(ring));
+	trace_i915_gem_request_complete(ring, ring->get_seqno(ring, false));
 
 	wake_up_all(&ring->irq_queue);
 	if (i915_enable_hangcheck) {
@@ -349,16 +361,16 @@ static void notify_ring(struct drm_device *dev,
 static void gen6_pm_rps_work(struct work_struct *work)
 {
 	drm_i915_private_t *dev_priv = container_of(work, drm_i915_private_t,
-						    rps_work);
+						    rps.work);
 	u32 pm_iir, pm_imr;
 	u8 new_delay;
 
-	spin_lock_irq(&dev_priv->rps_lock);
-	pm_iir = dev_priv->pm_iir;
-	dev_priv->pm_iir = 0;
+	spin_lock_irq(&dev_priv->rps.lock);
+	pm_iir = dev_priv->rps.pm_iir;
+	dev_priv->rps.pm_iir = 0;
 	pm_imr = I915_READ(GEN6_PMIMR);
 	I915_WRITE(GEN6_PMIMR, 0);
-	spin_unlock_irq(&dev_priv->rps_lock);
+	spin_unlock_irq(&dev_priv->rps.lock);
 
 	if ((pm_iir & GEN6_PM_DEFERRED_EVENTS) == 0)
 		return;
@@ -366,9 +378,9 @@ static void gen6_pm_rps_work(struct work_struct *work)
 	mutex_lock(&dev_priv->dev->struct_mutex);
 
 	if (pm_iir & GEN6_PM_RP_UP_THRESHOLD)
-		new_delay = dev_priv->cur_delay + 1;
+		new_delay = dev_priv->rps.cur_delay + 1;
 	else
-		new_delay = dev_priv->cur_delay - 1;
+		new_delay = dev_priv->rps.cur_delay - 1;
 
 	gen6_set_rps(dev_priv->dev, new_delay);
 
@@ -444,7 +456,7 @@ static void ivybridge_handle_parity_error(struct drm_device *dev)
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 	unsigned long flags;
 
-	if (!IS_IVYBRIDGE(dev))
+	if (!HAS_L3_GPU_CACHE(dev))
 		return;
 
 	spin_lock_irqsave(&dev_priv->irq_lock, flags);
@@ -488,19 +500,19 @@ static void gen6_queue_rps_work(struct drm_i915_private *dev_priv,
 	 * IIR bits should never already be set because IMR should
 	 * prevent an interrupt from being shown in IIR. The warning
 	 * displays a case where we've unsafely cleared
-	 * dev_priv->pm_iir. Although missing an interrupt of the same
+	 * dev_priv->rps.pm_iir. Although missing an interrupt of the same
 	 * type is not a problem, it displays a problem in the logic.
 	 *
-	 * The mask bit in IMR is cleared by rps_work.
+	 * The mask bit in IMR is cleared by dev_priv->rps.work.
 	 */
 
-	spin_lock_irqsave(&dev_priv->rps_lock, flags);
-	dev_priv->pm_iir |= pm_iir;
-	I915_WRITE(GEN6_PMIMR, dev_priv->pm_iir);
+	spin_lock_irqsave(&dev_priv->rps.lock, flags);
+	dev_priv->rps.pm_iir |= pm_iir;
+	I915_WRITE(GEN6_PMIMR, dev_priv->rps.pm_iir);
 	POSTING_READ(GEN6_PMIMR);
-	spin_unlock_irqrestore(&dev_priv->rps_lock, flags);
+	spin_unlock_irqrestore(&dev_priv->rps.lock, flags);
 
-	queue_work(dev_priv->wq, &dev_priv->rps_work);
+	queue_work(dev_priv->wq, &dev_priv->rps.work);
 }
 
 static irqreturn_t valleyview_irq_handler(DRM_IRQ_ARGS)
@@ -793,10 +805,8 @@ static irqreturn_t ironlake_irq_handler(DRM_IRQ_ARGS)
 			ibx_irq_handler(dev, pch_iir);
 	}
 
-	if (de_iir & DE_PCU_EVENT) {
-		I915_WRITE16(MEMINTRSTS, I915_READ(MEMINTRSTS));
-		i915_handle_rps_change(dev);
-	}
+	if (IS_GEN5(dev) &&  de_iir & DE_PCU_EVENT)
+		ironlake_handle_rps_change(dev);
 
 	if (IS_GEN6(dev) && pm_iir & GEN6_PM_DEFERRED_EVENTS)
 		gen6_queue_rps_work(dev_priv, pm_iir);
@@ -843,6 +853,35 @@ static void i915_error_work_func(struct work_struct *work)
 	}
 }
 
+/* NB: please notice the memset */
+static void i915_get_extra_instdone(struct drm_device *dev,
+				    uint32_t *instdone)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	memset(instdone, 0, sizeof(*instdone) * I915_NUM_INSTDONE_REG);
+
+	switch(INTEL_INFO(dev)->gen) {
+	case 2:
+	case 3:
+		instdone[0] = I915_READ(INSTDONE);
+		break;
+	case 4:
+	case 5:
+	case 6:
+		instdone[0] = I915_READ(INSTDONE_I965);
+		instdone[1] = I915_READ(INSTDONE1);
+		break;
+	default:
+		WARN_ONCE(1, "Unsupported platform\n");
+	case 7:
+		instdone[0] = I915_READ(GEN7_INSTDONE_1);
+		instdone[1] = I915_READ(GEN7_SC_INSTDONE);
+		instdone[2] = I915_READ(GEN7_SAMPLER_INSTDONE);
+		instdone[3] = I915_READ(GEN7_ROW_INSTDONE);
+		break;
+	}
+}
+
 #ifdef CONFIG_DEBUG_FS
 static struct drm_i915_error_object *
 i915_error_object_create(struct drm_i915_private *dev_priv,
@@ -949,7 +988,8 @@ static void capture_bo(struct drm_i915_error_buffer *err,
 {
 	err->size = obj->base.size;
 	err->name = obj->base.name;
-	err->seqno = obj->last_rendering_seqno;
+	err->rseqno = obj->last_read_seqno;
+	err->wseqno = obj->last_write_seqno;
 	err->gtt_offset = obj->gtt_offset;
 	err->read_domains = obj->base.read_domains;
 	err->write_domain = obj->base.write_domain;
@@ -1039,12 +1079,12 @@ i915_error_first_batchbuffer(struct drm_i915_private *dev_priv,
 	if (!ring->get_seqno)
 		return NULL;
 
-	seqno = ring->get_seqno(ring);
+	seqno = ring->get_seqno(ring, false);
 	list_for_each_entry(obj, &dev_priv->mm.active_list, mm_list) {
 		if (obj->ring != ring)
 			continue;
 
-		if (i915_seqno_passed(seqno, obj->last_rendering_seqno))
+		if (i915_seqno_passed(seqno, obj->last_read_seqno))
 			continue;
 
 		if ((obj->base.read_domains & I915_GEM_DOMAIN_COMMAND) == 0)
@@ -1080,10 +1120,8 @@ static void i915_record_ring_state(struct drm_device *dev,
 		error->ipehr[ring->id] = I915_READ(RING_IPEHR(ring->mmio_base));
 		error->instdone[ring->id] = I915_READ(RING_INSTDONE(ring->mmio_base));
 		error->instps[ring->id] = I915_READ(RING_INSTPS(ring->mmio_base));
-		if (ring->id == RCS) {
-			error->instdone1 = I915_READ(INSTDONE1);
+		if (ring->id == RCS)
 			error->bbaddr = I915_READ64(BB_ADDR);
-		}
 	} else {
 		error->faddr[ring->id] = I915_READ(DMA_FADD_I8XX);
 		error->ipeir[ring->id] = I915_READ(IPEIR);
@@ -1093,7 +1131,7 @@ static void i915_record_ring_state(struct drm_device *dev,
 
 	error->waiting[ring->id] = waitqueue_active(&ring->irq_queue);
 	error->instpm[ring->id] = I915_READ(RING_INSTPM(ring->mmio_base));
-	error->seqno[ring->id] = ring->get_seqno(ring);
+	error->seqno[ring->id] = ring->get_seqno(ring, false);
 	error->acthd[ring->id] = intel_ring_get_active_head(ring);
 	error->head[ring->id] = I915_READ_HEAD(ring);
 	error->tail[ring->id] = I915_READ_TAIL(ring);
@@ -1199,6 +1237,11 @@ static void i915_capture_error_state(struct drm_device *dev)
 		error->done_reg = I915_READ(DONE_REG);
 	}
 
+	if (INTEL_INFO(dev)->gen == 7)
+		error->err_int = I915_READ(GEN7_ERR_INT);
+
+	i915_get_extra_instdone(dev, error->extra_instdone);
+
 	i915_gem_record_fences(dev, error);
 	i915_gem_record_rings(dev, error);
 
@@ -1210,7 +1253,7 @@ static void i915_capture_error_state(struct drm_device *dev)
 	list_for_each_entry(obj, &dev_priv->mm.active_list, mm_list)
 		i++;
 	error->active_bo_count = i;
-	list_for_each_entry(obj, &dev_priv->mm.gtt_list, gtt_list)
+	list_for_each_entry(obj, &dev_priv->mm.bound_list, gtt_list)
 		if (obj->pin_count)
 			i++;
 	error->pinned_bo_count = i - error->active_bo_count;
@@ -1235,7 +1278,7 @@ static void i915_capture_error_state(struct drm_device *dev)
 		error->pinned_bo_count =
 			capture_pinned_bo(error->pinned_bo,
 					  error->pinned_bo_count,
-					  &dev_priv->mm.gtt_list);
+					  &dev_priv->mm.bound_list);
 
 	do_gettimeofday(&error->time);
 
@@ -1274,24 +1317,26 @@ void i915_destroy_error_state(struct drm_device *dev)
 static void i915_report_and_clear_eir(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	uint32_t instdone[I915_NUM_INSTDONE_REG];
 	u32 eir = I915_READ(EIR);
-	int pipe;
+	int pipe, i;
 
 	if (!eir)
 		return;
 
 	pr_err("render error detected, EIR: 0x%08x\n", eir);
 
+	i915_get_extra_instdone(dev, instdone);
+
 	if (IS_G4X(dev)) {
 		if (eir & (GM45_ERROR_MEM_PRIV | GM45_ERROR_CP_PRIV)) {
 			u32 ipeir = I915_READ(IPEIR_I965);
 
 			pr_err("  IPEIR: 0x%08x\n", I915_READ(IPEIR_I965));
 			pr_err("  IPEHR: 0x%08x\n", I915_READ(IPEHR_I965));
-			pr_err("  INSTDONE: 0x%08x\n",
-			       I915_READ(INSTDONE_I965));
+			for (i = 0; i < ARRAY_SIZE(instdone); i++)
+				pr_err("  INSTDONE_%d: 0x%08x\n", i, instdone[i]);
 			pr_err("  INSTPS: 0x%08x\n", I915_READ(INSTPS));
-			pr_err("  INSTDONE1: 0x%08x\n", I915_READ(INSTDONE1));
 			pr_err("  ACTHD: 0x%08x\n", I915_READ(ACTHD_I965));
 			I915_WRITE(IPEIR_I965, ipeir);
 			POSTING_READ(IPEIR_I965);
@@ -1325,12 +1370,13 @@ static void i915_report_and_clear_eir(struct drm_device *dev)
 	if (eir & I915_ERROR_INSTRUCTION) {
 		pr_err("instruction error\n");
 		pr_err("  INSTPM: 0x%08x\n", I915_READ(INSTPM));
+		for (i = 0; i < ARRAY_SIZE(instdone); i++)
+			pr_err("  INSTDONE_%d: 0x%08x\n", i, instdone[i]);
 		if (INTEL_INFO(dev)->gen < 4) {
 			u32 ipeir = I915_READ(IPEIR);
 
 			pr_err("  IPEIR: 0x%08x\n", I915_READ(IPEIR));
 			pr_err("  IPEHR: 0x%08x\n", I915_READ(IPEHR));
-			pr_err("  INSTDONE: 0x%08x\n", I915_READ(INSTDONE));
 			pr_err("  ACTHD: 0x%08x\n", I915_READ(ACTHD));
 			I915_WRITE(IPEIR, ipeir);
 			POSTING_READ(IPEIR);
@@ -1339,10 +1385,7 @@ static void i915_report_and_clear_eir(struct drm_device *dev)
 
 			pr_err("  IPEIR: 0x%08x\n", I915_READ(IPEIR_I965));
 			pr_err("  IPEHR: 0x%08x\n", I915_READ(IPEHR_I965));
-			pr_err("  INSTDONE: 0x%08x\n",
-			       I915_READ(INSTDONE_I965));
 			pr_err("  INSTPS: 0x%08x\n", I915_READ(INSTPS));
-			pr_err("  INSTDONE1: 0x%08x\n", I915_READ(INSTDONE1));
 			pr_err("  ACTHD: 0x%08x\n", I915_READ(ACTHD_I965));
 			I915_WRITE(IPEIR_I965, ipeir);
 			POSTING_READ(IPEIR_I965);
@@ -1590,7 +1633,8 @@ ring_last_seqno(struct intel_ring_buffer *ring)
 static bool i915_hangcheck_ring_idle(struct intel_ring_buffer *ring, bool *err)
 {
 	if (list_empty(&ring->request_list) ||
-	    i915_seqno_passed(ring->get_seqno(ring), ring_last_seqno(ring))) {
+	    i915_seqno_passed(ring->get_seqno(ring, false),
+			      ring_last_seqno(ring))) {
 		/* Issue a wake-up to catch stuck h/w. */
 		if (waitqueue_active(&ring->irq_queue)) {
 			DRM_ERROR("Hangcheck timer elapsed... %s idle\n",
@@ -1656,7 +1700,7 @@ void i915_hangcheck_elapsed(unsigned long data)
 {
 	struct drm_device *dev = (struct drm_device *)data;
 	drm_i915_private_t *dev_priv = dev->dev_private;
-	uint32_t acthd[I915_NUM_RINGS], instdone, instdone1;
+	uint32_t acthd[I915_NUM_RINGS], instdone[I915_NUM_INSTDONE_REG];
 	struct intel_ring_buffer *ring;
 	bool err = false, idle;
 	int i;
@@ -1684,25 +1728,16 @@ void i915_hangcheck_elapsed(unsigned long data)
 		return;
 	}
 
-	if (INTEL_INFO(dev)->gen < 4) {
-		instdone = I915_READ(INSTDONE);
-		instdone1 = 0;
-	} else {
-		instdone = I915_READ(INSTDONE_I965);
-		instdone1 = I915_READ(INSTDONE1);
-	}
-
+	i915_get_extra_instdone(dev, instdone);
 	if (memcmp(dev_priv->last_acthd, acthd, sizeof(acthd)) == 0 &&
-	    dev_priv->last_instdone == instdone &&
-	    dev_priv->last_instdone1 == instdone1) {
+	    memcmp(dev_priv->prev_instdone, instdone, sizeof(instdone)) == 0) {
 		if (i915_hangcheck_hung(dev))
 			return;
 	} else {
 		dev_priv->hangcheck_count = 0;
 
 		memcpy(dev_priv->last_acthd, acthd, sizeof(acthd));
-		dev_priv->last_instdone = instdone;
-		dev_priv->last_instdone1 = instdone1;
+		memcpy(dev_priv->prev_instdone, instdone, sizeof(instdone));
 	}
 
 repeat:
@@ -2647,7 +2682,7 @@ void intel_irq_init(struct drm_device *dev)
 
 	INIT_WORK(&dev_priv->hotplug_work, i915_hotplug_work_func);
 	INIT_WORK(&dev_priv->error_work, i915_error_work_func);
-	INIT_WORK(&dev_priv->rps_work, gen6_pm_rps_work);
+	INIT_WORK(&dev_priv->rps.work, gen6_pm_rps_work);
 	INIT_WORK(&dev_priv->parity_error_work, ivybridge_parity_work);
 
 	dev->driver->get_vblank_counter = i915_get_vblank_counter;
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 28725ce..a828e90 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -450,6 +450,7 @@
 #define RING_ACTHD(base)	((base)+0x74)
 #define RING_NOPID(base)	((base)+0x94)
 #define RING_IMR(base)		((base)+0xa8)
+#define RING_TIMESTAMP(base)	((base)+0x358)
 #define   TAIL_ADDR		0x001FFFF8
 #define   HEAD_WRAP_COUNT	0xFFE00000
 #define   HEAD_WRAP_ONE		0x00200000
@@ -478,6 +479,11 @@
 #define IPEIR_I965	0x02064
 #define IPEHR_I965	0x02068
 #define INSTDONE_I965	0x0206c
+#define GEN7_INSTDONE_1		0x0206c
+#define GEN7_SC_INSTDONE	0x07100
+#define GEN7_SAMPLER_INSTDONE	0x0e160
+#define GEN7_ROW_INSTDONE	0x0e164
+#define I915_NUM_INSTDONE_REG	4
 #define RING_IPEIR(base)	((base)+0x64)
 #define RING_IPEHR(base)	((base)+0x68)
 #define RING_INSTDONE(base)	((base)+0x6c)
@@ -500,6 +506,8 @@
 #define DMA_FADD_I8XX	0x020d0
 
 #define ERROR_GEN6	0x040a0
+#define GEN7_ERR_INT	0x44040
+#define   ERR_INT_MMIO_UNCLAIMED (1<<13)
 
 /* GM45+ chicken bits -- debug workaround bits that may be required
  * for various sorts of correct behavior.  The top 16 bits of each are
@@ -529,6 +537,8 @@
 #define   GFX_PSMI_GRANULARITY		(1<<10)
 #define   GFX_PPGTT_ENABLE		(1<<9)
 
+#define VLV_DISPLAY_BASE 0x180000
+
 #define SCPD0		0x0209c /* 915+ only */
 #define IER		0x020a0
 #define IIR		0x020a4
@@ -1496,6 +1506,14 @@
 					 GEN7_CXT_EXTENDED_SIZE(ctx_reg) + \
 					 GEN7_CXT_GT1_SIZE(ctx_reg) + \
 					 GEN7_CXT_VFSTATE_SIZE(ctx_reg))
+#define HSW_CXT_POWER_SIZE(ctx_reg)	((ctx_reg >> 26) & 0x3f)
+#define HSW_CXT_RING_SIZE(ctx_reg)	((ctx_reg >> 23) & 0x7)
+#define HSW_CXT_RENDER_SIZE(ctx_reg)	((ctx_reg >> 15) & 0xff)
+#define HSW_CXT_TOTAL_SIZE(ctx_reg)	(HSW_CXT_POWER_SIZE(ctx_reg) + \
+					 HSW_CXT_RING_SIZE(ctx_reg) + \
+					 HSW_CXT_RENDER_SIZE(ctx_reg) + \
+					 GEN7_CXT_VFSTATE_SIZE(ctx_reg))
+
 
 /*
  * Overlay regs
@@ -1549,12 +1567,35 @@
 
 /* VGA port control */
 #define ADPA			0x61100
+#define PCH_ADPA                0xe1100
+#define VLV_ADPA		(VLV_DISPLAY_BASE + ADPA)
+
 #define   ADPA_DAC_ENABLE	(1<<31)
 #define   ADPA_DAC_DISABLE	0
 #define   ADPA_PIPE_SELECT_MASK	(1<<30)
 #define   ADPA_PIPE_A_SELECT	0
 #define   ADPA_PIPE_B_SELECT	(1<<30)
 #define   ADPA_PIPE_SELECT(pipe) ((pipe) << 30)
+/* CPT uses bits 29:30 for pch transcoder select */
+#define   ADPA_CRT_HOTPLUG_MASK  0x03ff0000 /* bit 25-16 */
+#define   ADPA_CRT_HOTPLUG_MONITOR_NONE  (0<<24)
+#define   ADPA_CRT_HOTPLUG_MONITOR_MASK  (3<<24)
+#define   ADPA_CRT_HOTPLUG_MONITOR_COLOR (3<<24)
+#define   ADPA_CRT_HOTPLUG_MONITOR_MONO  (2<<24)
+#define   ADPA_CRT_HOTPLUG_ENABLE        (1<<23)
+#define   ADPA_CRT_HOTPLUG_PERIOD_64     (0<<22)
+#define   ADPA_CRT_HOTPLUG_PERIOD_128    (1<<22)
+#define   ADPA_CRT_HOTPLUG_WARMUP_5MS    (0<<21)
+#define   ADPA_CRT_HOTPLUG_WARMUP_10MS   (1<<21)
+#define   ADPA_CRT_HOTPLUG_SAMPLE_2S     (0<<20)
+#define   ADPA_CRT_HOTPLUG_SAMPLE_4S     (1<<20)
+#define   ADPA_CRT_HOTPLUG_VOLTAGE_40    (0<<18)
+#define   ADPA_CRT_HOTPLUG_VOLTAGE_50    (1<<18)
+#define   ADPA_CRT_HOTPLUG_VOLTAGE_60    (2<<18)
+#define   ADPA_CRT_HOTPLUG_VOLTAGE_70    (3<<18)
+#define   ADPA_CRT_HOTPLUG_VOLREF_325MV  (0<<17)
+#define   ADPA_CRT_HOTPLUG_VOLREF_475MV  (1<<17)
+#define   ADPA_CRT_HOTPLUG_FORCE_TRIGGER (1<<16)
 #define   ADPA_USE_VGA_HVPOLARITY (1<<15)
 #define   ADPA_SETS_HVPOLARITY	0
 #define   ADPA_VSYNC_CNTL_DISABLE (1<<11)
@@ -3889,31 +3930,6 @@
 #define FDI_PLL_CTL_1           0xfe000
 #define FDI_PLL_CTL_2           0xfe004
 
-/* CRT */
-#define PCH_ADPA                0xe1100
-#define  ADPA_TRANS_SELECT_MASK (1<<30)
-#define  ADPA_TRANS_A_SELECT    0
-#define  ADPA_TRANS_B_SELECT    (1<<30)
-#define  ADPA_CRT_HOTPLUG_MASK  0x03ff0000 /* bit 25-16 */
-#define  ADPA_CRT_HOTPLUG_MONITOR_NONE  (0<<24)
-#define  ADPA_CRT_HOTPLUG_MONITOR_MASK  (3<<24)
-#define  ADPA_CRT_HOTPLUG_MONITOR_COLOR (3<<24)
-#define  ADPA_CRT_HOTPLUG_MONITOR_MONO  (2<<24)
-#define  ADPA_CRT_HOTPLUG_ENABLE        (1<<23)
-#define  ADPA_CRT_HOTPLUG_PERIOD_64     (0<<22)
-#define  ADPA_CRT_HOTPLUG_PERIOD_128    (1<<22)
-#define  ADPA_CRT_HOTPLUG_WARMUP_5MS    (0<<21)
-#define  ADPA_CRT_HOTPLUG_WARMUP_10MS   (1<<21)
-#define  ADPA_CRT_HOTPLUG_SAMPLE_2S     (0<<20)
-#define  ADPA_CRT_HOTPLUG_SAMPLE_4S     (1<<20)
-#define  ADPA_CRT_HOTPLUG_VOLTAGE_40    (0<<18)
-#define  ADPA_CRT_HOTPLUG_VOLTAGE_50    (1<<18)
-#define  ADPA_CRT_HOTPLUG_VOLTAGE_60    (2<<18)
-#define  ADPA_CRT_HOTPLUG_VOLTAGE_70    (3<<18)
-#define  ADPA_CRT_HOTPLUG_VOLREF_325MV  (0<<17)
-#define  ADPA_CRT_HOTPLUG_VOLREF_475MV  (1<<17)
-#define  ADPA_CRT_HOTPLUG_FORCE_TRIGGER (1<<16)
-
 /* or SDVOB */
 #define HDMIB   0xe1140
 #define  PORT_ENABLE    (1 << 31)
@@ -4021,6 +4037,8 @@
 #define  PORT_TRANS_C_SEL_CPT	(2<<29)
 #define  PORT_TRANS_SEL_MASK	(3<<29)
 #define  PORT_TRANS_SEL_CPT(pipe)	((pipe) << 29)
+#define  PORT_TO_PIPE(val)	(((val) & (1<<30)) >> 30)
+#define  PORT_TO_PIPE_CPT(val)	(((val) & PORT_TRANS_SEL_MASK) >> 29)
 
 #define TRANS_DP_CTL_A		0xe0300
 #define TRANS_DP_CTL_B		0xe1300
@@ -4239,7 +4257,15 @@
 #define G4X_HDMIW_HDMIEDID		0x6210C
 
 #define IBX_HDMIW_HDMIEDID_A		0xE2050
+#define IBX_HDMIW_HDMIEDID_B		0xE2150
+#define IBX_HDMIW_HDMIEDID(pipe) _PIPE(pipe, \
+					IBX_HDMIW_HDMIEDID_A, \
+					IBX_HDMIW_HDMIEDID_B)
 #define IBX_AUD_CNTL_ST_A		0xE20B4
+#define IBX_AUD_CNTL_ST_B		0xE21B4
+#define IBX_AUD_CNTL_ST(pipe) _PIPE(pipe, \
+					IBX_AUD_CNTL_ST_A, \
+					IBX_AUD_CNTL_ST_B)
 #define IBX_ELD_BUFFER_SIZE		(0x1f << 10)
 #define IBX_ELD_ADDRESS			(0x1f << 5)
 #define IBX_ELD_ACK			(1 << 4)
@@ -4248,7 +4274,15 @@
 #define IBX_CP_READYB			(1 << 1)
 
 #define CPT_HDMIW_HDMIEDID_A		0xE5050
+#define CPT_HDMIW_HDMIEDID_B		0xE5150
+#define CPT_HDMIW_HDMIEDID(pipe) _PIPE(pipe, \
+					CPT_HDMIW_HDMIEDID_A, \
+					CPT_HDMIW_HDMIEDID_B)
 #define CPT_AUD_CNTL_ST_A		0xE50B4
+#define CPT_AUD_CNTL_ST_B		0xE51B4
+#define CPT_AUD_CNTL_ST(pipe) _PIPE(pipe, \
+					CPT_AUD_CNTL_ST_A, \
+					CPT_AUD_CNTL_ST_B)
 #define CPT_AUD_CNTRL_ST2		0xE50C0
 
 /* These are the 4 32-bit write offset registers for each stream
@@ -4258,7 +4292,15 @@
 #define GEN7_SO_WRITE_OFFSET(n)		(0x5280 + (n) * 4)
 
 #define IBX_AUD_CONFIG_A			0xe2000
+#define IBX_AUD_CONFIG_B			0xe2100
+#define IBX_AUD_CFG(pipe) _PIPE(pipe, \
+					IBX_AUD_CONFIG_A, \
+					IBX_AUD_CONFIG_B)
 #define CPT_AUD_CONFIG_A			0xe5000
+#define CPT_AUD_CONFIG_B			0xe5100
+#define CPT_AUD_CFG(pipe) _PIPE(pipe, \
+					CPT_AUD_CONFIG_A, \
+					CPT_AUD_CONFIG_B)
 #define   AUD_CONFIG_N_VALUE_INDEX		(1 << 29)
 #define   AUD_CONFIG_N_PROG_ENABLE		(1 << 28)
 #define   AUD_CONFIG_UPPER_N_SHIFT		20
@@ -4269,195 +4311,233 @@
 #define   AUD_CONFIG_PIXEL_CLOCK_HDMI		(0xf << 16)
 #define   AUD_CONFIG_DISABLE_NCTS		(1 << 3)
 
+/* HSW Audio */
+#define   HSW_AUD_CONFIG_A		0x65000 /* Audio Configuration Transcoder A */
+#define   HSW_AUD_CONFIG_B		0x65100 /* Audio Configuration Transcoder B */
+#define   HSW_AUD_CFG(pipe) _PIPE(pipe, \
+					HSW_AUD_CONFIG_A, \
+					HSW_AUD_CONFIG_B)
+
+#define   HSW_AUD_MISC_CTRL_A		0x65010 /* Audio Misc Control Convert 1 */
+#define   HSW_AUD_MISC_CTRL_B		0x65110 /* Audio Misc Control Convert 2 */
+#define   HSW_AUD_MISC_CTRL(pipe) _PIPE(pipe, \
+					HSW_AUD_MISC_CTRL_A, \
+					HSW_AUD_MISC_CTRL_B)
+
+#define   HSW_AUD_DIP_ELD_CTRL_ST_A	0x650b4 /* Audio DIP and ELD Control State Transcoder A */
+#define   HSW_AUD_DIP_ELD_CTRL_ST_B	0x651b4 /* Audio DIP and ELD Control State Transcoder B */
+#define   HSW_AUD_DIP_ELD_CTRL(pipe) _PIPE(pipe, \
+					HSW_AUD_DIP_ELD_CTRL_ST_A, \
+					HSW_AUD_DIP_ELD_CTRL_ST_B)
+
+/* Audio Digital Converter */
+#define   HSW_AUD_DIG_CNVT_1		0x65080 /* Audio Converter 1 */
+#define   HSW_AUD_DIG_CNVT_2		0x65180 /* Audio Converter 1 */
+#define   AUD_DIG_CNVT(pipe) _PIPE(pipe, \
+					HSW_AUD_DIG_CNVT_1, \
+					HSW_AUD_DIG_CNVT_2)
+#define   DIP_PORT_SEL_MASK		0x3
+
+#define   HSW_AUD_EDID_DATA_A		0x65050
+#define   HSW_AUD_EDID_DATA_B		0x65150
+#define   HSW_AUD_EDID_DATA(pipe) _PIPE(pipe, \
+					HSW_AUD_EDID_DATA_A, \
+					HSW_AUD_EDID_DATA_B)
+
+#define   HSW_AUD_PIPE_CONV_CFG		0x6507c /* Audio pipe and converter configs */
+#define   HSW_AUD_PIN_ELD_CP_VLD	0x650c0 /* Audio ELD and CP Ready Status */
+#define   AUDIO_INACTIVE_C		(1<<11)
+#define   AUDIO_INACTIVE_B		(1<<7)
+#define   AUDIO_INACTIVE_A		(1<<3)
+#define   AUDIO_OUTPUT_ENABLE_A		(1<<2)
+#define   AUDIO_OUTPUT_ENABLE_B		(1<<6)
+#define   AUDIO_OUTPUT_ENABLE_C		(1<<10)
+#define   AUDIO_ELD_VALID_A		(1<<0)
+#define   AUDIO_ELD_VALID_B		(1<<4)
+#define   AUDIO_ELD_VALID_C		(1<<8)
+#define   AUDIO_CP_READY_A		(1<<1)
+#define   AUDIO_CP_READY_B		(1<<5)
+#define   AUDIO_CP_READY_C		(1<<9)
+
 /* HSW Power Wells */
-#define HSW_PWR_WELL_CTL1		0x45400		/* BIOS */
-#define HSW_PWR_WELL_CTL2		0x45404		/* Driver */
-#define HSW_PWR_WELL_CTL3		0x45408		/* KVMR */
-#define HSW_PWR_WELL_CTL4		0x4540C		/* Debug */
-#define   HSW_PWR_WELL_ENABLE				(1<<31)
-#define   HSW_PWR_WELL_STATE				(1<<30)
-#define HSW_PWR_WELL_CTL5		0x45410
+#define HSW_PWR_WELL_CTL1			0x45400 /* BIOS */
+#define HSW_PWR_WELL_CTL2			0x45404 /* Driver */
+#define HSW_PWR_WELL_CTL3			0x45408 /* KVMR */
+#define HSW_PWR_WELL_CTL4			0x4540C /* Debug */
+#define   HSW_PWR_WELL_ENABLE			(1<<31)
+#define   HSW_PWR_WELL_STATE			(1<<30)
+#define HSW_PWR_WELL_CTL5			0x45410
 #define   HSW_PWR_WELL_ENABLE_SINGLE_STEP	(1<<31)
 #define   HSW_PWR_WELL_PWR_GATE_OVERRIDE	(1<<20)
-#define   HSW_PWR_WELL_FORCE_ON				(1<<19)
-#define HSW_PWR_WELL_CTL6		0x45414
+#define   HSW_PWR_WELL_FORCE_ON			(1<<19)
+#define HSW_PWR_WELL_CTL6			0x45414
 
 /* Per-pipe DDI Function Control */
-#define PIPE_DDI_FUNC_CTL_A			0x60400
-#define PIPE_DDI_FUNC_CTL_B			0x61400
-#define PIPE_DDI_FUNC_CTL_C			0x62400
+#define PIPE_DDI_FUNC_CTL_A		0x60400
+#define PIPE_DDI_FUNC_CTL_B		0x61400
+#define PIPE_DDI_FUNC_CTL_C		0x62400
 #define PIPE_DDI_FUNC_CTL_EDP		0x6F400
-#define DDI_FUNC_CTL(pipe) _PIPE(pipe, \
-					PIPE_DDI_FUNC_CTL_A, \
-					PIPE_DDI_FUNC_CTL_B)
+#define DDI_FUNC_CTL(pipe) _PIPE(pipe, PIPE_DDI_FUNC_CTL_A, \
+				       PIPE_DDI_FUNC_CTL_B)
 #define  PIPE_DDI_FUNC_ENABLE		(1<<31)
 /* Those bits are ignored by pipe EDP since it can only connect to DDI A */
-#define  PIPE_DDI_PORT_MASK			(7<<28)
-#define  PIPE_DDI_SELECT_PORT(x)		((x)<<28)
-#define  PIPE_DDI_MODE_SELECT_HDMI		(0<<24)
-#define  PIPE_DDI_MODE_SELECT_DVI		(1<<24)
+#define  PIPE_DDI_PORT_MASK		(7<<28)
+#define  PIPE_DDI_SELECT_PORT(x)	((x)<<28)
+#define  PIPE_DDI_MODE_SELECT_MASK	(7<<24)
+#define  PIPE_DDI_MODE_SELECT_HDMI	(0<<24)
+#define  PIPE_DDI_MODE_SELECT_DVI	(1<<24)
 #define  PIPE_DDI_MODE_SELECT_DP_SST	(2<<24)
 #define  PIPE_DDI_MODE_SELECT_DP_MST	(3<<24)
-#define  PIPE_DDI_MODE_SELECT_FDI		(4<<24)
-#define  PIPE_DDI_BPC_8					(0<<20)
-#define  PIPE_DDI_BPC_10				(1<<20)
-#define  PIPE_DDI_BPC_6					(2<<20)
-#define  PIPE_DDI_BPC_12				(3<<20)
-#define  PIPE_DDI_BFI_ENABLE			(1<<4)
-#define  PIPE_DDI_PORT_WIDTH_X1			(0<<1)
-#define  PIPE_DDI_PORT_WIDTH_X2			(1<<1)
-#define  PIPE_DDI_PORT_WIDTH_X4			(3<<1)
+#define  PIPE_DDI_MODE_SELECT_FDI	(4<<24)
+#define  PIPE_DDI_BPC_MASK		(7<<20)
+#define  PIPE_DDI_BPC_8			(0<<20)
+#define  PIPE_DDI_BPC_10		(1<<20)
+#define  PIPE_DDI_BPC_6			(2<<20)
+#define  PIPE_DDI_BPC_12		(3<<20)
+#define  PIPE_DDI_PVSYNC		(1<<17)
+#define  PIPE_DDI_PHSYNC		(1<<16)
+#define  PIPE_DDI_BFI_ENABLE		(1<<4)
+#define  PIPE_DDI_PORT_WIDTH_X1		(0<<1)
+#define  PIPE_DDI_PORT_WIDTH_X2		(1<<1)
+#define  PIPE_DDI_PORT_WIDTH_X4		(3<<1)
 
 /* DisplayPort Transport Control */
 #define DP_TP_CTL_A			0x64040
 #define DP_TP_CTL_B			0x64140
-#define DP_TP_CTL(port) _PORT(port, \
-					DP_TP_CTL_A, \
-					DP_TP_CTL_B)
-#define  DP_TP_CTL_ENABLE		(1<<31)
-#define  DP_TP_CTL_MODE_SST	(0<<27)
-#define  DP_TP_CTL_MODE_MST	(1<<27)
+#define DP_TP_CTL(port) _PORT(port, DP_TP_CTL_A, DP_TP_CTL_B)
+#define  DP_TP_CTL_ENABLE			(1<<31)
+#define  DP_TP_CTL_MODE_SST			(0<<27)
+#define  DP_TP_CTL_MODE_MST			(1<<27)
 #define  DP_TP_CTL_ENHANCED_FRAME_ENABLE	(1<<18)
-#define  DP_TP_CTL_FDI_AUTOTRAIN	(1<<15)
+#define  DP_TP_CTL_FDI_AUTOTRAIN		(1<<15)
 #define  DP_TP_CTL_LINK_TRAIN_MASK		(7<<8)
 #define  DP_TP_CTL_LINK_TRAIN_PAT1		(0<<8)
 #define  DP_TP_CTL_LINK_TRAIN_PAT2		(1<<8)
-#define  DP_TP_CTL_LINK_TRAIN_NORMAL	(3<<8)
+#define  DP_TP_CTL_LINK_TRAIN_NORMAL		(3<<8)
 
 /* DisplayPort Transport Status */
 #define DP_TP_STATUS_A			0x64044
 #define DP_TP_STATUS_B			0x64144
-#define DP_TP_STATUS(port) _PORT(port, \
-					DP_TP_STATUS_A, \
-					DP_TP_STATUS_B)
+#define DP_TP_STATUS(port) _PORT(port, DP_TP_STATUS_A, DP_TP_STATUS_B)
 #define  DP_TP_STATUS_AUTOTRAIN_DONE	(1<<12)
 
 /* DDI Buffer Control */
 #define DDI_BUF_CTL_A				0x64000
 #define DDI_BUF_CTL_B				0x64100
-#define DDI_BUF_CTL(port) _PORT(port, \
-					DDI_BUF_CTL_A, \
-					DDI_BUF_CTL_B)
-#define  DDI_BUF_CTL_ENABLE				(1<<31)
+#define DDI_BUF_CTL(port) _PORT(port, DDI_BUF_CTL_A, DDI_BUF_CTL_B)
+#define  DDI_BUF_CTL_ENABLE			(1<<31)
 #define  DDI_BUF_EMP_400MV_0DB_HSW		(0<<24)   /* Sel0 */
-#define  DDI_BUF_EMP_400MV_3_5DB_HSW	(1<<24)   /* Sel1 */
+#define  DDI_BUF_EMP_400MV_3_5DB_HSW		(1<<24)   /* Sel1 */
 #define  DDI_BUF_EMP_400MV_6DB_HSW		(2<<24)   /* Sel2 */
-#define  DDI_BUF_EMP_400MV_9_5DB_HSW	(3<<24)   /* Sel3 */
+#define  DDI_BUF_EMP_400MV_9_5DB_HSW		(3<<24)   /* Sel3 */
 #define  DDI_BUF_EMP_600MV_0DB_HSW		(4<<24)   /* Sel4 */
-#define  DDI_BUF_EMP_600MV_3_5DB_HSW	(5<<24)   /* Sel5 */
+#define  DDI_BUF_EMP_600MV_3_5DB_HSW		(5<<24)   /* Sel5 */
 #define  DDI_BUF_EMP_600MV_6DB_HSW		(6<<24)   /* Sel6 */
 #define  DDI_BUF_EMP_800MV_0DB_HSW		(7<<24)   /* Sel7 */
-#define  DDI_BUF_EMP_800MV_3_5DB_HSW	(8<<24)   /* Sel8 */
-#define  DDI_BUF_EMP_MASK				(0xf<<24)
-#define  DDI_BUF_IS_IDLE				(1<<7)
-#define  DDI_PORT_WIDTH_X1				(0<<1)
-#define  DDI_PORT_WIDTH_X2				(1<<1)
-#define  DDI_PORT_WIDTH_X4				(3<<1)
+#define  DDI_BUF_EMP_800MV_3_5DB_HSW		(8<<24)   /* Sel8 */
+#define  DDI_BUF_EMP_MASK			(0xf<<24)
+#define  DDI_BUF_IS_IDLE			(1<<7)
+#define  DDI_PORT_WIDTH_X1			(0<<1)
+#define  DDI_PORT_WIDTH_X2			(1<<1)
+#define  DDI_PORT_WIDTH_X4			(3<<1)
 #define  DDI_INIT_DISPLAY_DETECTED		(1<<0)
 
 /* DDI Buffer Translations */
 #define DDI_BUF_TRANS_A				0x64E00
 #define DDI_BUF_TRANS_B				0x64E60
-#define DDI_BUF_TRANS(port) _PORT(port, \
-					DDI_BUF_TRANS_A, \
-					DDI_BUF_TRANS_B)
+#define DDI_BUF_TRANS(port) _PORT(port, DDI_BUF_TRANS_A, DDI_BUF_TRANS_B)
 
 /* Sideband Interface (SBI) is programmed indirectly, via
  * SBI_ADDR, which contains the register offset; and SBI_DATA,
  * which contains the payload */
-#define SBI_ADDR				0xC6000
-#define SBI_DATA				0xC6004
+#define SBI_ADDR			0xC6000
+#define SBI_DATA			0xC6004
 #define SBI_CTL_STAT			0xC6008
 #define  SBI_CTL_OP_CRRD		(0x6<<8)
 #define  SBI_CTL_OP_CRWR		(0x7<<8)
 #define  SBI_RESPONSE_FAIL		(0x1<<1)
-#define  SBI_RESPONSE_SUCCESS	(0x0<<1)
-#define  SBI_BUSY				(0x1<<0)
-#define  SBI_READY				(0x0<<0)
+#define  SBI_RESPONSE_SUCCESS		(0x0<<1)
+#define  SBI_BUSY			(0x1<<0)
+#define  SBI_READY			(0x0<<0)
 
 /* SBI offsets */
-#define  SBI_SSCDIVINTPHASE6		0x0600
+#define  SBI_SSCDIVINTPHASE6			0x0600
 #define   SBI_SSCDIVINTPHASE_DIVSEL_MASK	((0x7f)<<1)
 #define   SBI_SSCDIVINTPHASE_DIVSEL(x)		((x)<<1)
 #define   SBI_SSCDIVINTPHASE_INCVAL_MASK	((0x7f)<<8)
 #define   SBI_SSCDIVINTPHASE_INCVAL(x)		((x)<<8)
-#define   SBI_SSCDIVINTPHASE_DIR(x)			((x)<<15)
+#define   SBI_SSCDIVINTPHASE_DIR(x)		((x)<<15)
 #define   SBI_SSCDIVINTPHASE_PROPAGATE		(1<<0)
-#define  SBI_SSCCTL					0x020c
+#define  SBI_SSCCTL				0x020c
 #define  SBI_SSCCTL6				0x060C
-#define   SBI_SSCCTL_DISABLE		(1<<0)
+#define   SBI_SSCCTL_DISABLE			(1<<0)
 #define  SBI_SSCAUXDIV6				0x0610
 #define   SBI_SSCAUXDIV_FINALDIV2SEL(x)		((x)<<4)
-#define  SBI_DBUFF0					0x2a00
+#define  SBI_DBUFF0				0x2a00
 
 /* LPT PIXCLK_GATE */
-#define PIXCLK_GATE				0xC6020
-#define  PIXCLK_GATE_UNGATE		1<<0
-#define  PIXCLK_GATE_GATE		0<<0
+#define PIXCLK_GATE			0xC6020
+#define  PIXCLK_GATE_UNGATE		(1<<0)
+#define  PIXCLK_GATE_GATE		(0<<0)
 
 /* SPLL */
-#define SPLL_CTL				0x46020
+#define SPLL_CTL			0x46020
 #define  SPLL_PLL_ENABLE		(1<<31)
 #define  SPLL_PLL_SCC			(1<<28)
 #define  SPLL_PLL_NON_SCC		(2<<28)
-#define  SPLL_PLL_FREQ_810MHz	(0<<26)
-#define  SPLL_PLL_FREQ_1350MHz	(1<<26)
+#define  SPLL_PLL_FREQ_810MHz		(0<<26)
+#define  SPLL_PLL_FREQ_1350MHz		(1<<26)
 
 /* WRPLL */
-#define WRPLL_CTL1				0x46040
-#define WRPLL_CTL2				0x46060
-#define  WRPLL_PLL_ENABLE				(1<<31)
-#define  WRPLL_PLL_SELECT_SSC			(0x01<<28)
-#define  WRPLL_PLL_SELECT_NON_SCC		(0x02<<28)
+#define WRPLL_CTL1			0x46040
+#define WRPLL_CTL2			0x46060
+#define  WRPLL_PLL_ENABLE		(1<<31)
+#define  WRPLL_PLL_SELECT_SSC		(0x01<<28)
+#define  WRPLL_PLL_SELECT_NON_SCC	(0x02<<28)
 #define  WRPLL_PLL_SELECT_LCPLL_2700	(0x03<<28)
 /* WRPLL divider programming */
-#define  WRPLL_DIVIDER_REFERENCE(x)		((x)<<0)
-#define  WRPLL_DIVIDER_POST(x)			((x)<<8)
-#define  WRPLL_DIVIDER_FEEDBACK(x)		((x)<<16)
+#define  WRPLL_DIVIDER_REFERENCE(x)	((x)<<0)
+#define  WRPLL_DIVIDER_POST(x)		((x)<<8)
+#define  WRPLL_DIVIDER_FEEDBACK(x)	((x)<<16)
 
 /* Port clock selection */
 #define PORT_CLK_SEL_A			0x46100
 #define PORT_CLK_SEL_B			0x46104
-#define PORT_CLK_SEL(port) _PORT(port, \
-					PORT_CLK_SEL_A, \
-					PORT_CLK_SEL_B)
+#define PORT_CLK_SEL(port) _PORT(port, PORT_CLK_SEL_A, PORT_CLK_SEL_B)
 #define  PORT_CLK_SEL_LCPLL_2700	(0<<29)
 #define  PORT_CLK_SEL_LCPLL_1350	(1<<29)
 #define  PORT_CLK_SEL_LCPLL_810		(2<<29)
-#define  PORT_CLK_SEL_SPLL			(3<<29)
+#define  PORT_CLK_SEL_SPLL		(3<<29)
 #define  PORT_CLK_SEL_WRPLL1		(4<<29)
 #define  PORT_CLK_SEL_WRPLL2		(5<<29)
 
 /* Pipe clock selection */
 #define PIPE_CLK_SEL_A			0x46140
 #define PIPE_CLK_SEL_B			0x46144
-#define PIPE_CLK_SEL(pipe) _PIPE(pipe, \
-					PIPE_CLK_SEL_A, \
-					PIPE_CLK_SEL_B)
+#define PIPE_CLK_SEL(pipe) _PIPE(pipe, PIPE_CLK_SEL_A, PIPE_CLK_SEL_B)
 /* For each pipe, we need to select the corresponding port clock */
-#define  PIPE_CLK_SEL_DISABLED	(0x0<<29)
-#define  PIPE_CLK_SEL_PORT(x)	((x+1)<<29)
+#define  PIPE_CLK_SEL_DISABLED		(0x0<<29)
+#define  PIPE_CLK_SEL_PORT(x)		((x+1)<<29)
 
 /* LCPLL Control */
-#define LCPLL_CTL				0x130040
+#define LCPLL_CTL			0x130040
 #define  LCPLL_PLL_DISABLE		(1<<31)
 #define  LCPLL_PLL_LOCK			(1<<30)
-#define  LCPLL_CD_CLOCK_DISABLE	(1<<25)
+#define  LCPLL_CD_CLOCK_DISABLE		(1<<25)
 #define  LCPLL_CD2X_CLOCK_DISABLE	(1<<23)
 
 /* Pipe WM_LINETIME - watermark line time */
 #define PIPE_WM_LINETIME_A		0x45270
 #define PIPE_WM_LINETIME_B		0x45274
-#define PIPE_WM_LINETIME(pipe) _PIPE(pipe, \
-					PIPE_WM_LINETIME_A, \
-					PIPE_WM_LINETIME_B)
-#define   PIPE_WM_LINETIME_MASK		(0x1ff)
-#define   PIPE_WM_LINETIME_TIME(x)			((x))
+#define PIPE_WM_LINETIME(pipe) _PIPE(pipe, PIPE_WM_LINETIME_A, \
+					   PIPE_WM_LINETIME_B)
+#define   PIPE_WM_LINETIME_MASK			(0x1ff)
+#define   PIPE_WM_LINETIME_TIME(x)		((x))
 #define   PIPE_WM_LINETIME_IPS_LINETIME_MASK	(0x1ff<<16)
-#define   PIPE_WM_LINETIME_IPS_LINETIME(x)		((x)<<16)
+#define   PIPE_WM_LINETIME_IPS_LINETIME(x)	((x)<<16)
 
 /* SFUSE_STRAP */
-#define SFUSE_STRAP				0xc2014
+#define SFUSE_STRAP			0xc2014
 #define  SFUSE_STRAP_DDIB_DETECTED	(1<<2)
 #define  SFUSE_STRAP_DDIC_DETECTED	(1<<1)
 #define  SFUSE_STRAP_DDID_DETECTED	(1<<0)
diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c
index 7631807..da733a3 100644
--- a/drivers/gpu/drm/i915/i915_sysfs.c
+++ b/drivers/gpu/drm/i915/i915_sysfs.c
@@ -93,6 +93,7 @@ static struct attribute_group rc6_attr_group = {
 	.name = power_group_name,
 	.attrs =  rc6_attrs
 };
+#endif
 
 static int l3_access_valid(struct drm_device *dev, loff_t offset)
 {
@@ -206,14 +207,15 @@ void i915_setup_sysfs(struct drm_device *dev)
 {
 	int ret;
 
+#ifdef CONFIG_PM
 	if (INTEL_INFO(dev)->gen >= 6) {
 		ret = sysfs_merge_group(&dev->primary->kdev.kobj,
 					&rc6_attr_group);
 		if (ret)
 			DRM_ERROR("RC6 residency sysfs setup failed\n");
 	}
-
-	if (IS_IVYBRIDGE(dev)) {
+#endif
+	if (HAS_L3_GPU_CACHE(dev)) {
 		ret = device_create_bin_file(&dev->primary->kdev, &dpf_attrs);
 		if (ret)
 			DRM_ERROR("l3 parity sysfs setup failed\n");
@@ -225,14 +227,3 @@ void i915_teardown_sysfs(struct drm_device *dev)
 	device_remove_bin_file(&dev->primary->kdev,  &dpf_attrs);
 	sysfs_unmerge_group(&dev->primary->kdev.kobj, &rc6_attr_group);
 }
-#else
-void i915_setup_sysfs(struct drm_device *dev)
-{
-	return;
-}
-
-void i915_teardown_sysfs(struct drm_device *dev)
-{
-	return;
-}
-#endif /* CONFIG_PM */
diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h
index fe90b3a..8134421 100644
--- a/drivers/gpu/drm/i915/i915_trace.h
+++ b/drivers/gpu/drm/i915/i915_trace.h
@@ -214,22 +214,18 @@ TRACE_EVENT(i915_gem_evict,
 );
 
 TRACE_EVENT(i915_gem_evict_everything,
-	    TP_PROTO(struct drm_device *dev, bool purgeable),
-	    TP_ARGS(dev, purgeable),
+	    TP_PROTO(struct drm_device *dev),
+	    TP_ARGS(dev),
 
 	    TP_STRUCT__entry(
 			     __field(u32, dev)
-			     __field(bool, purgeable)
 			    ),
 
 	    TP_fast_assign(
 			   __entry->dev = dev->primary->index;
-			   __entry->purgeable = purgeable;
 			  ),
 
-	    TP_printk("dev=%d%s",
-		      __entry->dev,
-		      __entry->purgeable ? ", purgeable only" : "")
+	    TP_printk("dev=%d", __entry->dev)
 );
 
 TRACE_EVENT(i915_gem_ring_dispatch,
@@ -434,6 +430,21 @@ TRACE_EVENT(i915_reg_rw,
 		(u32)(__entry->val >> 32))
 );
 
+TRACE_EVENT(intel_gpu_freq_change,
+	    TP_PROTO(u32 freq),
+	    TP_ARGS(freq),
+
+	    TP_STRUCT__entry(
+			     __field(u32, freq)
+			     ),
+
+	    TP_fast_assign(
+			   __entry->freq = freq;
+			   ),
+
+	    TP_printk("new_freq=%u", __entry->freq)
+);
+
 #endif /* _I915_TRACE_H_ */
 
 /* This part must be outside protection */
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index 23bdc8c..c42b980 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -47,6 +47,7 @@
 struct intel_crt {
 	struct intel_encoder base;
 	bool force_hotplug_required;
+	u32 adpa_reg;
 };
 
 static struct intel_crt *intel_attached_crt(struct drm_connector *connector)
@@ -55,42 +56,68 @@ static struct intel_crt *intel_attached_crt(struct drm_connector *connector)
 			    struct intel_crt, base);
 }
 
-static void pch_crt_dpms(struct drm_encoder *encoder, int mode)
+static struct intel_crt *intel_encoder_to_crt(struct intel_encoder *encoder)
 {
-	struct drm_device *dev = encoder->dev;
+	return container_of(encoder, struct intel_crt, base);
+}
+
+static bool intel_crt_get_hw_state(struct intel_encoder *encoder,
+				   enum pipe *pipe)
+{
+	struct drm_device *dev = encoder->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crt *crt = intel_encoder_to_crt(encoder);
+	u32 tmp;
+
+	tmp = I915_READ(crt->adpa_reg);
+
+	if (!(tmp & ADPA_DAC_ENABLE))
+		return false;
+
+	if (HAS_PCH_CPT(dev))
+		*pipe = PORT_TO_PIPE_CPT(tmp);
+	else
+		*pipe = PORT_TO_PIPE(tmp);
+
+	return true;
+}
+
+static void intel_disable_crt(struct intel_encoder *encoder)
+{
+	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
+	struct intel_crt *crt = intel_encoder_to_crt(encoder);
 	u32 temp;
 
-	temp = I915_READ(PCH_ADPA);
+	temp = I915_READ(crt->adpa_reg);
+	temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE);
 	temp &= ~ADPA_DAC_ENABLE;
+	I915_WRITE(crt->adpa_reg, temp);
+}
 
-	switch (mode) {
-	case DRM_MODE_DPMS_ON:
-		temp |= ADPA_DAC_ENABLE;
-		break;
-	case DRM_MODE_DPMS_STANDBY:
-	case DRM_MODE_DPMS_SUSPEND:
-	case DRM_MODE_DPMS_OFF:
-		/* Just leave port enable cleared */
-		break;
-	}
+static void intel_enable_crt(struct intel_encoder *encoder)
+{
+	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
+	struct intel_crt *crt = intel_encoder_to_crt(encoder);
+	u32 temp;
 
-	I915_WRITE(PCH_ADPA, temp);
+	temp = I915_READ(crt->adpa_reg);
+	temp |= ADPA_DAC_ENABLE;
+	I915_WRITE(crt->adpa_reg, temp);
 }
 
-static void gmch_crt_dpms(struct drm_encoder *encoder, int mode)
+/* Note: The caller is required to filter out dpms modes not supported by the
+ * platform. */
+static void intel_crt_set_dpms(struct intel_encoder *encoder, int mode)
 {
-	struct drm_device *dev = encoder->dev;
+	struct drm_device *dev = encoder->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crt *crt = intel_encoder_to_crt(encoder);
 	u32 temp;
 
-	temp = I915_READ(ADPA);
+	temp = I915_READ(crt->adpa_reg);
 	temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE);
 	temp &= ~ADPA_DAC_ENABLE;
 
-	if (IS_VALLEYVIEW(dev) && mode != DRM_MODE_DPMS_ON)
-		mode = DRM_MODE_DPMS_OFF;
-
 	switch (mode) {
 	case DRM_MODE_DPMS_ON:
 		temp |= ADPA_DAC_ENABLE;
@@ -106,7 +133,51 @@ static void gmch_crt_dpms(struct drm_encoder *encoder, int mode)
 		break;
 	}
 
-	I915_WRITE(ADPA, temp);
+	I915_WRITE(crt->adpa_reg, temp);
+}
+
+static void intel_crt_dpms(struct drm_connector *connector, int mode)
+{
+	struct drm_device *dev = connector->dev;
+	struct intel_encoder *encoder = intel_attached_encoder(connector);
+	struct drm_crtc *crtc;
+	int old_dpms;
+
+	/* PCH platforms and VLV only support on/off. */
+	if (INTEL_INFO(dev)->gen < 5 && mode != DRM_MODE_DPMS_ON)
+		mode = DRM_MODE_DPMS_OFF;
+
+	if (mode == connector->dpms)
+		return;
+
+	old_dpms = connector->dpms;
+	connector->dpms = mode;
+
+	/* Only need to change hw state when actually enabled */
+	crtc = encoder->base.crtc;
+	if (!crtc) {
+		encoder->connectors_active = false;
+		return;
+	}
+
+	/* We need the pipe to run for anything but OFF. */
+	if (mode == DRM_MODE_DPMS_OFF)
+		encoder->connectors_active = false;
+	else
+		encoder->connectors_active = true;
+
+	if (mode < old_dpms) {
+		/* From off to on, enable the pipe first. */
+		intel_crtc_update_dpms(crtc);
+
+		intel_crt_set_dpms(encoder, mode);
+	} else {
+		intel_crt_set_dpms(encoder, mode);
+
+		intel_crtc_update_dpms(crtc);
+	}
+
+	intel_modeset_check_state(connector->dev);
 }
 
 static int intel_crt_mode_valid(struct drm_connector *connector,
@@ -145,19 +216,15 @@ static void intel_crt_mode_set(struct drm_encoder *encoder,
 
 	struct drm_device *dev = encoder->dev;
 	struct drm_crtc *crtc = encoder->crtc;
+	struct intel_crt *crt =
+		intel_encoder_to_crt(to_intel_encoder(encoder));
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int dpll_md_reg;
 	u32 adpa, dpll_md;
-	u32 adpa_reg;
 
 	dpll_md_reg = DPLL_MD(intel_crtc->pipe);
 
-	if (HAS_PCH_SPLIT(dev))
-		adpa_reg = PCH_ADPA;
-	else
-		adpa_reg = ADPA;
-
 	/*
 	 * Disable separate mode multiplier used when cloning SDVO to CRT
 	 * XXX this needs to be adjusted when we really are cloning
@@ -185,7 +252,7 @@ static void intel_crt_mode_set(struct drm_encoder *encoder,
 	if (!HAS_PCH_SPLIT(dev))
 		I915_WRITE(BCLRPAT(intel_crtc->pipe), 0);
 
-	I915_WRITE(adpa_reg, adpa);
+	I915_WRITE(crt->adpa_reg, adpa);
 }
 
 static bool intel_ironlake_crt_detect_hotplug(struct drm_connector *connector)
@@ -545,14 +612,12 @@ intel_crt_detect(struct drm_connector *connector, bool force)
 		return connector->status;
 
 	/* for pre-945g platforms use load detect */
-	if (intel_get_load_detect_pipe(&crt->base, connector, NULL,
-				       &tmp)) {
+	if (intel_get_load_detect_pipe(connector, NULL, &tmp)) {
 		if (intel_crt_detect_ddc(connector))
 			status = connector_status_connected;
 		else
 			status = intel_crt_load_detect(crt);
-		intel_release_load_detect_pipe(&crt->base, connector,
-					       &tmp);
+		intel_release_load_detect_pipe(connector, &tmp);
 	} else
 		status = connector_status_unknown;
 
@@ -603,25 +668,15 @@ static void intel_crt_reset(struct drm_connector *connector)
  * Routines for controlling stuff on the analog port
  */
 
-static const struct drm_encoder_helper_funcs pch_encoder_funcs = {
+static const struct drm_encoder_helper_funcs crt_encoder_funcs = {
 	.mode_fixup = intel_crt_mode_fixup,
-	.prepare = intel_encoder_prepare,
-	.commit = intel_encoder_commit,
 	.mode_set = intel_crt_mode_set,
-	.dpms = pch_crt_dpms,
-};
-
-static const struct drm_encoder_helper_funcs gmch_encoder_funcs = {
-	.mode_fixup = intel_crt_mode_fixup,
-	.prepare = intel_encoder_prepare,
-	.commit = intel_encoder_commit,
-	.mode_set = intel_crt_mode_set,
-	.dpms = gmch_crt_dpms,
+	.disable = intel_encoder_noop,
 };
 
 static const struct drm_connector_funcs intel_crt_connector_funcs = {
 	.reset = intel_crt_reset,
-	.dpms = drm_helper_connector_dpms,
+	.dpms = intel_crt_dpms,
 	.detect = intel_crt_detect,
 	.fill_modes = drm_helper_probe_single_connector_modes,
 	.destroy = intel_crt_destroy,
@@ -662,7 +717,6 @@ void intel_crt_init(struct drm_device *dev)
 	struct intel_crt *crt;
 	struct intel_connector *intel_connector;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	const struct drm_encoder_helper_funcs *encoder_helper_funcs;
 
 	/* Skip machines without VGA that falsely report hotplug events */
 	if (dmi_check_system(intel_no_crt))
@@ -688,13 +742,11 @@ void intel_crt_init(struct drm_device *dev)
 	intel_connector_attach_encoder(intel_connector, &crt->base);
 
 	crt->base.type = INTEL_OUTPUT_ANALOG;
-	crt->base.clone_mask = (1 << INTEL_SDVO_NON_TV_CLONE_BIT |
-				1 << INTEL_ANALOG_CLONE_BIT |
-				1 << INTEL_SDVO_LVDS_CLONE_BIT);
+	crt->base.cloneable = true;
 	if (IS_HASWELL(dev))
 		crt->base.crtc_mask = (1 << 0);
 	else
-		crt->base.crtc_mask = (1 << 0) | (1 << 1);
+		crt->base.crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
 
 	if (IS_GEN2(dev))
 		connector->interlace_allowed = 0;
@@ -703,11 +755,18 @@ void intel_crt_init(struct drm_device *dev)
 	connector->doublescan_allowed = 0;
 
 	if (HAS_PCH_SPLIT(dev))
-		encoder_helper_funcs = &pch_encoder_funcs;
+		crt->adpa_reg = PCH_ADPA;
+	else if (IS_VALLEYVIEW(dev))
+		crt->adpa_reg = VLV_ADPA;
 	else
-		encoder_helper_funcs = &gmch_encoder_funcs;
+		crt->adpa_reg = ADPA;
+
+	crt->base.disable = intel_disable_crt;
+	crt->base.enable = intel_enable_crt;
+	crt->base.get_hw_state = intel_crt_get_hw_state;
+	intel_connector->get_hw_state = intel_connector_get_hw_state;
 
-	drm_encoder_helper_add(&crt->base.base, encoder_helper_funcs);
+	drm_encoder_helper_add(&crt->base.base, &crt_encoder_funcs);
 	drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs);
 
 	drm_sysfs_connector_add(connector);
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 933c748..bfe3754 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -250,7 +250,7 @@ void intel_ddi_init(struct drm_device *dev, enum port port)
 	case PORT_B:
 	case PORT_C:
 	case PORT_D:
-		intel_hdmi_init(dev, DDI_BUF_CTL(port));
+		intel_hdmi_init(dev, DDI_BUF_CTL(port), port);
 		break;
 	default:
 		DRM_DEBUG_DRIVER("No handlers defined for port %d, skipping DDI initialization\n",
@@ -267,7 +267,8 @@ struct wrpll_tmds_clock {
 	u16 r2;		/* Reference divider */
 };
 
-/* Table of matching values for WRPLL clocks programming for each frequency */
+/* Table of matching values for WRPLL clocks programming for each frequency.
+ * The code assumes this table is sorted. */
 static const struct wrpll_tmds_clock wrpll_tmds_clock_table[] = {
 	{19750,	38,	25,	18},
 	{20000,	48,	32,	18},
@@ -277,7 +278,6 @@ static const struct wrpll_tmds_clock wrpll_tmds_clock_table[] = {
 	{23000,	36,	23,	15},
 	{23500,	40,	40,	23},
 	{23750,	26,	16,	14},
-	{23750,	26,	16,	14},
 	{24000,	36,	24,	15},
 	{25000,	36,	25,	15},
 	{25175,	26,	40,	33},
@@ -437,7 +437,6 @@ static const struct wrpll_tmds_clock wrpll_tmds_clock_table[] = {
 	{108000,	8,	24,	15},
 	{108108,	8,	173,	108},
 	{109000,	6,	23,	19},
-	{109000,	6,	23,	19},
 	{110000,	6,	22,	18},
 	{110013,	6,	22,	18},
 	{110250,	8,	49,	30},
@@ -614,7 +613,6 @@ static const struct wrpll_tmds_clock wrpll_tmds_clock_table[] = {
 	{218250,	4,	42,	26},
 	{218750,	4,	34,	21},
 	{219000,	4,	47,	29},
-	{219000,	4,	47,	29},
 	{220000,	4,	44,	27},
 	{220640,	4,	49,	30},
 	{220750,	4,	36,	22},
@@ -658,7 +656,7 @@ void intel_ddi_mode_set(struct drm_encoder *encoder,
 	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
 	int port = intel_hdmi->ddi_port;
 	int pipe = intel_crtc->pipe;
-	int p, n2, r2, valid=0;
+	int p, n2, r2;
 	u32 temp, i;
 
 	/* On Haswell, we need to enable the clocks and prepare DDI function to
@@ -666,26 +664,23 @@ void intel_ddi_mode_set(struct drm_encoder *encoder,
 	 */
 	DRM_DEBUG_KMS("Preparing HDMI DDI mode for Haswell on port %c, pipe %c\n", port_name(port), pipe_name(pipe));
 
-	for (i=0; i < ARRAY_SIZE(wrpll_tmds_clock_table); i++) {
-		if (crtc->mode.clock == wrpll_tmds_clock_table[i].clock) {
-			p = wrpll_tmds_clock_table[i].p;
-			n2 = wrpll_tmds_clock_table[i].n2;
-			r2 = wrpll_tmds_clock_table[i].r2;
+	for (i = 0; i < ARRAY_SIZE(wrpll_tmds_clock_table); i++)
+		if (crtc->mode.clock <= wrpll_tmds_clock_table[i].clock)
+			break;
 
-			DRM_DEBUG_KMS("WR PLL clock: found settings for %dKHz refresh rate: p=%d, n2=%d, r2=%d\n",
-					crtc->mode.clock,
-					p, n2, r2);
+	if (i == ARRAY_SIZE(wrpll_tmds_clock_table))
+		i--;
 
-			valid = 1;
-			break;
-		}
-	}
+	p = wrpll_tmds_clock_table[i].p;
+	n2 = wrpll_tmds_clock_table[i].n2;
+	r2 = wrpll_tmds_clock_table[i].r2;
 
-	if (!valid) {
-		DRM_ERROR("Unable to find WR PLL clock settings for %dKHz refresh rate\n",
-				crtc->mode.clock);
-		return;
-	}
+	if (wrpll_tmds_clock_table[i].clock != crtc->mode.clock)
+		DRM_INFO("WR PLL: using settings for %dKHz on %dKHz mode\n",
+			 wrpll_tmds_clock_table[i].clock, crtc->mode.clock);
+
+	DRM_DEBUG_KMS("WR PLL: %dKHz refresh rate with p=%d, n2=%d r2=%d\n",
+		      crtc->mode.clock, p, n2, r2);
 
 	/* Enable LCPLL if disabled */
 	temp = I915_READ(LCPLL_CTL);
@@ -718,46 +713,107 @@ void intel_ddi_mode_set(struct drm_encoder *encoder,
 		/* Proper support for digital audio needs a new logic and a new set
 		 * of registers, so we leave it for future patch bombing.
 		 */
-		DRM_DEBUG_DRIVER("HDMI audio on pipe %c not yet supported on DDI\n",
+		DRM_DEBUG_DRIVER("HDMI audio on pipe %c on DDI\n",
 				 pipe_name(intel_crtc->pipe));
+
+		/* write eld */
+		DRM_DEBUG_DRIVER("HDMI audio: write eld information\n");
+		intel_write_eld(encoder, adjusted_mode);
 	}
 
 	/* Enable PIPE_DDI_FUNC_CTL for the pipe to work in HDMI mode */
-	temp = I915_READ(DDI_FUNC_CTL(pipe));
-	temp &= ~PIPE_DDI_PORT_MASK;
-	temp &= ~PIPE_DDI_BPC_12;
-	temp |= PIPE_DDI_SELECT_PORT(port) |
-			PIPE_DDI_MODE_SELECT_HDMI |
-			((intel_crtc->bpp > 24) ?
-				PIPE_DDI_BPC_12 :
-				PIPE_DDI_BPC_8) |
-			PIPE_DDI_FUNC_ENABLE;
+	temp = PIPE_DDI_FUNC_ENABLE | PIPE_DDI_SELECT_PORT(port);
+
+	switch (intel_crtc->bpp) {
+	case 18:
+		temp |= PIPE_DDI_BPC_6;
+		break;
+	case 24:
+		temp |= PIPE_DDI_BPC_8;
+		break;
+	case 30:
+		temp |= PIPE_DDI_BPC_10;
+		break;
+	case 36:
+		temp |= PIPE_DDI_BPC_12;
+		break;
+	default:
+		WARN(1, "%d bpp unsupported by pipe DDI function\n",
+		     intel_crtc->bpp);
+	}
+
+	if (intel_hdmi->has_hdmi_sink)
+		temp |= PIPE_DDI_MODE_SELECT_HDMI;
+	else
+		temp |= PIPE_DDI_MODE_SELECT_DVI;
+
+	if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
+		temp |= PIPE_DDI_PVSYNC;
+	if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
+		temp |= PIPE_DDI_PHSYNC;
 
 	I915_WRITE(DDI_FUNC_CTL(pipe), temp);
 
 	intel_hdmi->set_infoframes(encoder, adjusted_mode);
 }
 
-void intel_ddi_dpms(struct drm_encoder *encoder, int mode)
+bool intel_ddi_get_hw_state(struct intel_encoder *encoder,
+			    enum pipe *pipe)
 {
-	struct drm_device *dev = encoder->dev;
+	struct drm_device *dev = encoder->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
+	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
+	u32 tmp;
+	int i;
+
+	tmp = I915_READ(DDI_BUF_CTL(intel_hdmi->ddi_port));
+
+	if (!(tmp & DDI_BUF_CTL_ENABLE))
+		return false;
+
+	for_each_pipe(i) {
+		tmp = I915_READ(DDI_FUNC_CTL(i));
+
+		if ((tmp & PIPE_DDI_PORT_MASK)
+		    == PIPE_DDI_SELECT_PORT(intel_hdmi->ddi_port)) {
+			*pipe = i;
+			return true;
+		}
+	}
+
+	DRM_DEBUG_KMS("No pipe for ddi port %i found\n", intel_hdmi->ddi_port);
+
+	return true;
+}
+
+void intel_enable_ddi(struct intel_encoder *encoder)
+{
+	struct drm_device *dev = encoder->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
 	int port = intel_hdmi->ddi_port;
 	u32 temp;
 
 	temp = I915_READ(DDI_BUF_CTL(port));
-
-	if (mode != DRM_MODE_DPMS_ON) {
-		temp &= ~DDI_BUF_CTL_ENABLE;
-	} else {
-		temp |= DDI_BUF_CTL_ENABLE;
-	}
+	temp |= DDI_BUF_CTL_ENABLE;
 
 	/* Enable DDI_BUF_CTL. In HDMI/DVI mode, the port width,
 	 * and swing/emphasis values are ignored so nothing special needs
 	 * to be done besides enabling the port.
 	 */
-	I915_WRITE(DDI_BUF_CTL(port),
-			temp);
+	I915_WRITE(DDI_BUF_CTL(port), temp);
+}
+
+void intel_disable_ddi(struct intel_encoder *encoder)
+{
+	struct drm_device *dev = encoder->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
+	int port = intel_hdmi->ddi_port;
+	u32 temp;
+
+	temp = I915_READ(DDI_BUF_CTL(port));
+	temp &= ~DDI_BUF_CTL_ENABLE;
+
+	I915_WRITE(DDI_BUF_CTL(port), temp);
 }
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index c040aee..069ae98 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1006,7 +1006,7 @@ void intel_wait_for_pipe_off(struct drm_device *dev, int pipe)
 		/* Wait for the Pipe State to go off */
 		if (wait_for((I915_READ(reg) & I965_PIPECONF_ACTIVE) == 0,
 			     100))
-			DRM_DEBUG_KMS("pipe_off wait timed out\n");
+			WARN(1, "pipe_off wait timed out\n");
 	} else {
 		u32 last_line, line_mask;
 		int reg = PIPEDSL(pipe);
@@ -1024,7 +1024,7 @@ void intel_wait_for_pipe_off(struct drm_device *dev, int pipe)
 		} while (((I915_READ(reg) & line_mask) != last_line) &&
 			 time_after(timeout, jiffies));
 		if (time_after(jiffies, timeout))
-			DRM_DEBUG_KMS("pipe_off wait timed out\n");
+			WARN(1, "pipe_off wait timed out\n");
 	}
 }
 
@@ -1431,6 +1431,8 @@ static void assert_pch_ports_disabled(struct drm_i915_private *dev_priv,
  * protect mechanism may be enabled.
  *
  * Note!  This is for pre-ILK only.
+ *
+ * Unfortunately needed by dvo_ns2501 since the dvo depends on it running.
  */
 static void intel_enable_pll(struct drm_i915_private *dev_priv, enum pipe pipe)
 {
@@ -2201,16 +2203,17 @@ intel_finish_fb(struct drm_framebuffer *old_fb)
 
 static int
 intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
-		    struct drm_framebuffer *old_fb)
+		    struct drm_framebuffer *fb)
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_i915_master_private *master_priv;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct drm_framebuffer *old_fb;
 	int ret;
 
 	/* no fb bound */
-	if (!crtc->fb) {
+	if (!fb) {
 		DRM_ERROR("No FB bound\n");
 		return 0;
 	}
@@ -2224,7 +2227,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
 
 	mutex_lock(&dev->struct_mutex);
 	ret = intel_pin_and_fence_fb_obj(dev,
-					 to_intel_framebuffer(crtc->fb)->obj,
+					 to_intel_framebuffer(fb)->obj,
 					 NULL);
 	if (ret != 0) {
 		mutex_unlock(&dev->struct_mutex);
@@ -2232,17 +2235,22 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
 		return ret;
 	}
 
-	if (old_fb)
-		intel_finish_fb(old_fb);
+	if (crtc->fb)
+		intel_finish_fb(crtc->fb);
 
-	ret = dev_priv->display.update_plane(crtc, crtc->fb, x, y);
+	ret = dev_priv->display.update_plane(crtc, fb, x, y);
 	if (ret) {
-		intel_unpin_fb_obj(to_intel_framebuffer(crtc->fb)->obj);
+		intel_unpin_fb_obj(to_intel_framebuffer(fb)->obj);
 		mutex_unlock(&dev->struct_mutex);
 		DRM_ERROR("failed to update base address\n");
 		return ret;
 	}
 
+	old_fb = crtc->fb;
+	crtc->fb = fb;
+	crtc->x = x;
+	crtc->y = y;
+
 	if (old_fb) {
 		intel_wait_for_vblank(dev, intel_crtc->pipe);
 		intel_unpin_fb_obj(to_intel_framebuffer(old_fb)->obj);
@@ -2709,11 +2717,10 @@ static void ivb_manual_fdi_link_train(struct drm_crtc *crtc)
 	DRM_DEBUG_KMS("FDI train done.\n");
 }
 
-static void ironlake_fdi_pll_enable(struct drm_crtc *crtc)
+static void ironlake_fdi_pll_enable(struct intel_crtc *intel_crtc)
 {
-	struct drm_device *dev = crtc->dev;
+	struct drm_device *dev = intel_crtc->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	int pipe = intel_crtc->pipe;
 	u32 reg, temp;
 
@@ -2754,6 +2761,35 @@ static void ironlake_fdi_pll_enable(struct drm_crtc *crtc)
 	}
 }
 
+static void ironlake_fdi_pll_disable(struct intel_crtc *intel_crtc)
+{
+	struct drm_device *dev = intel_crtc->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	int pipe = intel_crtc->pipe;
+	u32 reg, temp;
+
+	/* Switch from PCDclk to Rawclk */
+	reg = FDI_RX_CTL(pipe);
+	temp = I915_READ(reg);
+	I915_WRITE(reg, temp & ~FDI_PCDCLK);
+
+	/* Disable CPU FDI TX PLL */
+	reg = FDI_TX_CTL(pipe);
+	temp = I915_READ(reg);
+	I915_WRITE(reg, temp & ~FDI_TX_PLL_ENABLE);
+
+	POSTING_READ(reg);
+	udelay(100);
+
+	reg = FDI_RX_CTL(pipe);
+	temp = I915_READ(reg);
+	I915_WRITE(reg, temp & ~FDI_RX_PLL_ENABLE);
+
+	/* Wait for the clocks to turn off. */
+	POSTING_READ(reg);
+	udelay(100);
+}
+
 static void cpt_phase_pointer_disable(struct drm_device *dev, int pipe)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -2838,13 +2874,13 @@ static void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc)
 static bool intel_crtc_driving_pch(struct drm_crtc *crtc)
 {
 	struct drm_device *dev = crtc->dev;
-	struct intel_encoder *encoder;
+	struct intel_encoder *intel_encoder;
 
 	/*
 	 * If there's a non-PCH eDP on this crtc, it must be DP_A, and that
 	 * must be driven by its own crtc; no sharing is possible.
 	 */
-	for_each_encoder_on_crtc(dev, crtc, encoder) {
+	for_each_encoder_on_crtc(dev, crtc, intel_encoder) {
 
 		/* On Haswell, LPT PCH handles the VGA connection via FDI, and Haswell
 		 * CPU handles all others */
@@ -2852,19 +2888,19 @@ static bool intel_crtc_driving_pch(struct drm_crtc *crtc)
 			/* It is still unclear how this will work on PPT, so throw up a warning */
 			WARN_ON(!HAS_PCH_LPT(dev));
 
-			if (encoder->type == DRM_MODE_ENCODER_DAC) {
+			if (intel_encoder->type == INTEL_OUTPUT_ANALOG) {
 				DRM_DEBUG_KMS("Haswell detected DAC encoder, assuming is PCH\n");
 				return true;
 			} else {
 				DRM_DEBUG_KMS("Haswell detected encoder %d, assuming is CPU\n",
-						encoder->type);
+					      intel_encoder->type);
 				return false;
 			}
 		}
 
-		switch (encoder->type) {
+		switch (intel_encoder->type) {
 		case INTEL_OUTPUT_EDP:
-			if (!intel_encoder_is_pch_edp(&encoder->base))
+			if (!intel_encoder_is_pch_edp(&intel_encoder->base))
 				return false;
 			continue;
 		}
@@ -3181,11 +3217,14 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct intel_encoder *encoder;
 	int pipe = intel_crtc->pipe;
 	int plane = intel_crtc->plane;
 	u32 temp;
 	bool is_pch_port;
 
+	WARN_ON(!crtc->enabled);
+
 	if (intel_crtc->active)
 		return;
 
@@ -3201,7 +3240,7 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
 	is_pch_port = intel_crtc_driving_pch(crtc);
 
 	if (is_pch_port)
-		ironlake_fdi_pll_enable(crtc);
+		ironlake_fdi_pll_enable(intel_crtc);
 	else
 		ironlake_fdi_disable(crtc);
 
@@ -3234,6 +3273,12 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
 	mutex_unlock(&dev->struct_mutex);
 
 	intel_crtc_update_cursor(crtc, true);
+
+	for_each_encoder_on_crtc(dev, crtc, encoder)
+		encoder->enable(encoder);
+
+	if (HAS_PCH_CPT(dev))
+		intel_cpt_verify_modeset(dev, intel_crtc->pipe);
 }
 
 static void ironlake_crtc_disable(struct drm_crtc *crtc)
@@ -3241,13 +3286,18 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct intel_encoder *encoder;
 	int pipe = intel_crtc->pipe;
 	int plane = intel_crtc->plane;
 	u32 reg, temp;
 
+
 	if (!intel_crtc->active)
 		return;
 
+	for_each_encoder_on_crtc(dev, crtc, encoder)
+		encoder->disable(encoder);
+
 	intel_crtc_wait_for_pending_flips(crtc);
 	drm_vblank_off(dev, pipe);
 	intel_crtc_update_cursor(crtc, false);
@@ -3304,26 +3354,7 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
 	/* disable PCH DPLL */
 	intel_disable_pch_pll(intel_crtc);
 
-	/* Switch from PCDclk to Rawclk */
-	reg = FDI_RX_CTL(pipe);
-	temp = I915_READ(reg);
-	I915_WRITE(reg, temp & ~FDI_PCDCLK);
-
-	/* Disable CPU FDI TX PLL */
-	reg = FDI_TX_CTL(pipe);
-	temp = I915_READ(reg);
-	I915_WRITE(reg, temp & ~FDI_TX_PLL_ENABLE);
-
-	POSTING_READ(reg);
-	udelay(100);
-
-	reg = FDI_RX_CTL(pipe);
-	temp = I915_READ(reg);
-	I915_WRITE(reg, temp & ~FDI_RX_PLL_ENABLE);
-
-	/* Wait for the clocks to turn off. */
-	POSTING_READ(reg);
-	udelay(100);
+	ironlake_fdi_pll_disable(intel_crtc);
 
 	intel_crtc->active = false;
 	intel_update_watermarks(dev);
@@ -3333,30 +3364,6 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
 	mutex_unlock(&dev->struct_mutex);
 }
 
-static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode)
-{
-	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	int pipe = intel_crtc->pipe;
-	int plane = intel_crtc->plane;
-
-	/* XXX: When our outputs are all unaware of DPMS modes other than off
-	 * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC.
-	 */
-	switch (mode) {
-	case DRM_MODE_DPMS_ON:
-	case DRM_MODE_DPMS_STANDBY:
-	case DRM_MODE_DPMS_SUSPEND:
-		DRM_DEBUG_KMS("crtc %d/%d dpms on\n", pipe, plane);
-		ironlake_crtc_enable(crtc);
-		break;
-
-	case DRM_MODE_DPMS_OFF:
-		DRM_DEBUG_KMS("crtc %d/%d dpms off\n", pipe, plane);
-		ironlake_crtc_disable(crtc);
-		break;
-	}
-}
-
 static void ironlake_crtc_off(struct drm_crtc *crtc)
 {
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
@@ -3386,9 +3393,12 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct intel_encoder *encoder;
 	int pipe = intel_crtc->pipe;
 	int plane = intel_crtc->plane;
 
+	WARN_ON(!crtc->enabled);
+
 	if (intel_crtc->active)
 		return;
 
@@ -3405,6 +3415,9 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
 	/* Give the overlay scaler a chance to enable if it's on this pipe */
 	intel_crtc_dpms_overlay(intel_crtc, true);
 	intel_crtc_update_cursor(crtc, true);
+
+	for_each_encoder_on_crtc(dev, crtc, encoder)
+		encoder->enable(encoder);
 }
 
 static void i9xx_crtc_disable(struct drm_crtc *crtc)
@@ -3412,12 +3425,17 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct intel_encoder *encoder;
 	int pipe = intel_crtc->pipe;
 	int plane = intel_crtc->plane;
 
+
 	if (!intel_crtc->active)
 		return;
 
+	for_each_encoder_on_crtc(dev, crtc, encoder)
+		encoder->disable(encoder);
+
 	/* Give the overlay scaler a chance to disable if it's on this pipe */
 	intel_crtc_wait_for_pending_flips(crtc);
 	drm_vblank_off(dev, pipe);
@@ -3436,45 +3454,17 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
 	intel_update_watermarks(dev);
 }
 
-static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode)
-{
-	/* XXX: When our outputs are all unaware of DPMS modes other than off
-	 * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC.
-	 */
-	switch (mode) {
-	case DRM_MODE_DPMS_ON:
-	case DRM_MODE_DPMS_STANDBY:
-	case DRM_MODE_DPMS_SUSPEND:
-		i9xx_crtc_enable(crtc);
-		break;
-	case DRM_MODE_DPMS_OFF:
-		i9xx_crtc_disable(crtc);
-		break;
-	}
-}
-
 static void i9xx_crtc_off(struct drm_crtc *crtc)
 {
 }
 
-/**
- * Sets the power management mode of the pipe and plane.
- */
-static void intel_crtc_dpms(struct drm_crtc *crtc, int mode)
+static void intel_crtc_update_sarea(struct drm_crtc *crtc,
+				    bool enabled)
 {
 	struct drm_device *dev = crtc->dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_i915_master_private *master_priv;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	int pipe = intel_crtc->pipe;
-	bool enabled;
-
-	if (intel_crtc->dpms_mode == mode)
-		return;
-
-	intel_crtc->dpms_mode = mode;
-
-	dev_priv->display.dpms(crtc, mode);
 
 	if (!dev->primary->master)
 		return;
@@ -3483,8 +3473,6 @@ static void intel_crtc_dpms(struct drm_crtc *crtc, int mode)
 	if (!master_priv->sarea_priv)
 		return;
 
-	enabled = crtc->enabled && mode != DRM_MODE_DPMS_OFF;
-
 	switch (pipe) {
 	case 0:
 		master_priv->sarea_priv->pipeA_w = enabled ? crtc->mode.hdisplay : 0;
@@ -3500,13 +3488,42 @@ static void intel_crtc_dpms(struct drm_crtc *crtc, int mode)
 	}
 }
 
+/**
+ * Sets the power management mode of the pipe and plane.
+ */
+void intel_crtc_update_dpms(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_encoder *intel_encoder;
+	bool enable = false;
+
+	for_each_encoder_on_crtc(dev, crtc, intel_encoder)
+		enable |= intel_encoder->connectors_active;
+
+	if (enable)
+		dev_priv->display.crtc_enable(crtc);
+	else
+		dev_priv->display.crtc_disable(crtc);
+
+	intel_crtc_update_sarea(crtc, enable);
+}
+
+static void intel_crtc_noop(struct drm_crtc *crtc)
+{
+}
+
 static void intel_crtc_disable(struct drm_crtc *crtc)
 {
-	struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
 	struct drm_device *dev = crtc->dev;
+	struct drm_connector *connector;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
+	/* crtc should still be enabled when we disable it. */
+	WARN_ON(!crtc->enabled);
+
+	dev_priv->display.crtc_disable(crtc);
+	intel_crtc_update_sarea(crtc, false);
 	dev_priv->display.off(crtc);
 
 	assert_plane_disabled(dev->dev_private, to_intel_crtc(crtc)->plane);
@@ -3516,63 +3533,128 @@ static void intel_crtc_disable(struct drm_crtc *crtc)
 		mutex_lock(&dev->struct_mutex);
 		intel_unpin_fb_obj(to_intel_framebuffer(crtc->fb)->obj);
 		mutex_unlock(&dev->struct_mutex);
+		crtc->fb = NULL;
+	}
+
+	/* Update computed state. */
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		if (!connector->encoder || !connector->encoder->crtc)
+			continue;
+
+		if (connector->encoder->crtc != crtc)
+			continue;
+
+		connector->dpms = DRM_MODE_DPMS_OFF;
+		to_intel_encoder(connector->encoder)->connectors_active = false;
 	}
 }
 
-/* Prepare for a mode set.
- *
- * Note we could be a lot smarter here.  We need to figure out which outputs
- * will be enabled, which disabled (in short, how the config will changes)
- * and perform the minimum necessary steps to accomplish that, e.g. updating
- * watermarks, FBC configuration, making sure PLLs are programmed correctly,
- * panel fitting is in the proper state, etc.
- */
-static void i9xx_crtc_prepare(struct drm_crtc *crtc)
+void intel_modeset_disable(struct drm_device *dev)
 {
-	i9xx_crtc_disable(crtc);
+	struct drm_crtc *crtc;
+
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		if (crtc->enabled)
+			intel_crtc_disable(crtc);
+	}
 }
 
-static void i9xx_crtc_commit(struct drm_crtc *crtc)
+void intel_encoder_noop(struct drm_encoder *encoder)
 {
-	i9xx_crtc_enable(crtc);
 }
 
-static void ironlake_crtc_prepare(struct drm_crtc *crtc)
+void intel_encoder_destroy(struct drm_encoder *encoder)
 {
-	ironlake_crtc_disable(crtc);
+	struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
+
+	drm_encoder_cleanup(encoder);
+	kfree(intel_encoder);
 }
 
-static void ironlake_crtc_commit(struct drm_crtc *crtc)
+/* Simple dpms helper for encodres with just one connector, no cloning and only
+ * one kind of off state. It clamps all !ON modes to fully OFF and changes the
+ * state of the entire output pipe. */
+void intel_encoder_dpms(struct intel_encoder *encoder, int mode)
 {
-	ironlake_crtc_enable(crtc);
+	if (mode == DRM_MODE_DPMS_ON) {
+		encoder->connectors_active = true;
+
+		intel_crtc_update_dpms(encoder->base.crtc);
+	} else {
+		encoder->connectors_active = false;
+
+		intel_crtc_update_dpms(encoder->base.crtc);
+	}
 }
 
-void intel_encoder_prepare(struct drm_encoder *encoder)
+/* Cross check the actual hw state with our own modeset state tracking (and it's
+ * internal consistency). */
+static void intel_connector_check_state(struct intel_connector *connector)
 {
-	struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
-	/* lvds has its own version of prepare see intel_lvds_prepare */
-	encoder_funcs->dpms(encoder, DRM_MODE_DPMS_OFF);
+	if (connector->get_hw_state(connector)) {
+		struct intel_encoder *encoder = connector->encoder;
+		struct drm_crtc *crtc;
+		bool encoder_enabled;
+		enum pipe pipe;
+
+		DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
+			      connector->base.base.id,
+			      drm_get_connector_name(&connector->base));
+
+		WARN(connector->base.dpms == DRM_MODE_DPMS_OFF,
+		     "wrong connector dpms state\n");
+		WARN(connector->base.encoder != &encoder->base,
+		     "active connector not linked to encoder\n");
+		WARN(!encoder->connectors_active,
+		     "encoder->connectors_active not set\n");
+
+		encoder_enabled = encoder->get_hw_state(encoder, &pipe);
+		WARN(!encoder_enabled, "encoder not enabled\n");
+		if (WARN_ON(!encoder->base.crtc))
+			return;
+
+		crtc = encoder->base.crtc;
+
+		WARN(!crtc->enabled, "crtc not enabled\n");
+		WARN(!to_intel_crtc(crtc)->active, "crtc not active\n");
+		WARN(pipe != to_intel_crtc(crtc)->pipe,
+		     "encoder active on the wrong pipe\n");
+	}
 }
 
-void intel_encoder_commit(struct drm_encoder *encoder)
+/* Even simpler default implementation, if there's really no special case to
+ * consider. */
+void intel_connector_dpms(struct drm_connector *connector, int mode)
 {
-	struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
-	struct drm_device *dev = encoder->dev;
-	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
+	struct intel_encoder *encoder = intel_attached_encoder(connector);
 
-	/* lvds has its own version of commit see intel_lvds_commit */
-	encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
+	/* All the simple cases only support two dpms states. */
+	if (mode != DRM_MODE_DPMS_ON)
+		mode = DRM_MODE_DPMS_OFF;
 
-	if (HAS_PCH_CPT(dev))
-		intel_cpt_verify_modeset(dev, intel_crtc->pipe);
+	if (mode == connector->dpms)
+		return;
+
+	connector->dpms = mode;
+
+	/* Only need to change hw state when actually enabled */
+	if (encoder->base.crtc)
+		intel_encoder_dpms(encoder, mode);
+	else
+		WARN_ON(encoder->connectors_active != false);
+
+	intel_modeset_check_state(connector->dev);
 }
 
-void intel_encoder_destroy(struct drm_encoder *encoder)
+/* Simple connector->get_hw_state implementation for encoders that support only
+ * one connector and no cloning and hence the encoder state determines the state
+ * of the connector. */
+bool intel_connector_get_hw_state(struct intel_connector *connector)
 {
-	struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
+	enum pipe pipe = 0;
+	struct intel_encoder *encoder = connector->encoder;
 
-	drm_encoder_cleanup(encoder);
-	kfree(intel_encoder);
+	return encoder->get_hw_state(encoder, &pipe);
 }
 
 static bool intel_crtc_mode_fixup(struct drm_crtc *crtc,
@@ -3593,6 +3675,13 @@ static bool intel_crtc_mode_fixup(struct drm_crtc *crtc,
 	if (!(adjusted_mode->private_flags & INTEL_MODE_CRTC_TIMINGS_SET))
 		drm_mode_set_crtcinfo(adjusted_mode, 0);
 
+	/* WaPruneModeWithIncorrectHsyncOffset: Cantiga+ cannot handle modes
+	 * with a hsync front porch of 0.
+	 */
+	if ((INTEL_INFO(dev)->gen > 4 || IS_G4X(dev)) &&
+		adjusted_mode->hsync_start == adjusted_mode->hdisplay)
+		return false;
+
 	return true;
 }
 
@@ -3728,6 +3817,7 @@ static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv)
  * true if they don't match).
  */
 static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc,
+					 struct drm_framebuffer *fb,
 					 unsigned int *pipe_bpp,
 					 struct drm_display_mode *mode)
 {
@@ -3797,7 +3887,7 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc,
 	 * also stays within the max display bpc discovered above.
 	 */
 
-	switch (crtc->fb->depth) {
+	switch (fb->depth) {
 	case 8:
 		bpc = 8; /* since we go through a colormap */
 		break;
@@ -4216,7 +4306,7 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
 			      struct drm_display_mode *mode,
 			      struct drm_display_mode *adjusted_mode,
 			      int x, int y,
-			      struct drm_framebuffer *old_fb)
+			      struct drm_framebuffer *fb)
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -4406,7 +4496,7 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
 	I915_WRITE(DSPCNTR(plane), dspcntr);
 	POSTING_READ(DSPCNTR(plane));
 
-	ret = intel_pipe_set_base(crtc, x, y, old_fb);
+	ret = intel_pipe_set_base(crtc, x, y, fb);
 
 	intel_update_watermarks(dev);
 
@@ -4564,7 +4654,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
 				  struct drm_display_mode *mode,
 				  struct drm_display_mode *adjusted_mode,
 				  int x, int y,
-				  struct drm_framebuffer *old_fb)
+				  struct drm_framebuffer *fb)
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -4684,7 +4774,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
 	/* determine panel color depth */
 	temp = I915_READ(PIPECONF(pipe));
 	temp &= ~PIPE_BPC_MASK;
-	dither = intel_choose_pipe_bpp_dither(crtc, &pipe_bpp, mode);
+	dither = intel_choose_pipe_bpp_dither(crtc, fb, &pipe_bpp, mode);
 	switch (pipe_bpp) {
 	case 18:
 		temp |= PIPE_6BPC;
@@ -4953,7 +5043,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
 	I915_WRITE(DSPCNTR(plane), dspcntr);
 	POSTING_READ(DSPCNTR(plane));
 
-	ret = intel_pipe_set_base(crtc, x, y, old_fb);
+	ret = intel_pipe_set_base(crtc, x, y, fb);
 
 	intel_update_watermarks(dev);
 
@@ -4966,7 +5056,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
 			       struct drm_display_mode *mode,
 			       struct drm_display_mode *adjusted_mode,
 			       int x, int y,
-			       struct drm_framebuffer *old_fb)
+			       struct drm_framebuffer *fb)
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -4977,14 +5067,9 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
 	drm_vblank_pre_modeset(dev, pipe);
 
 	ret = dev_priv->display.crtc_mode_set(crtc, mode, adjusted_mode,
-					      x, y, old_fb);
+					      x, y, fb);
 	drm_vblank_post_modeset(dev, pipe);
 
-	if (ret)
-		intel_crtc->dpms_mode = DRM_MODE_DPMS_OFF;
-	else
-		intel_crtc->dpms_mode = DRM_MODE_DPMS_ON;
-
 	return ret;
 }
 
@@ -5057,6 +5142,91 @@ static void g4x_write_eld(struct drm_connector *connector,
 	I915_WRITE(G4X_AUD_CNTL_ST, i);
 }
 
+static void haswell_write_eld(struct drm_connector *connector,
+				     struct drm_crtc *crtc)
+{
+	struct drm_i915_private *dev_priv = connector->dev->dev_private;
+	uint8_t *eld = connector->eld;
+	struct drm_device *dev = crtc->dev;
+	uint32_t eldv;
+	uint32_t i;
+	int len;
+	int pipe = to_intel_crtc(crtc)->pipe;
+	int tmp;
+
+	int hdmiw_hdmiedid = HSW_AUD_EDID_DATA(pipe);
+	int aud_cntl_st = HSW_AUD_DIP_ELD_CTRL(pipe);
+	int aud_config = HSW_AUD_CFG(pipe);
+	int aud_cntrl_st2 = HSW_AUD_PIN_ELD_CP_VLD;
+
+
+	DRM_DEBUG_DRIVER("HDMI: Haswell Audio initialize....\n");
+
+	/* Audio output enable */
+	DRM_DEBUG_DRIVER("HDMI audio: enable codec\n");
+	tmp = I915_READ(aud_cntrl_st2);
+	tmp |= (AUDIO_OUTPUT_ENABLE_A << (pipe * 4));
+	I915_WRITE(aud_cntrl_st2, tmp);
+
+	/* Wait for 1 vertical blank */
+	intel_wait_for_vblank(dev, pipe);
+
+	/* Set ELD valid state */
+	tmp = I915_READ(aud_cntrl_st2);
+	DRM_DEBUG_DRIVER("HDMI audio: pin eld vld status=0x%8x\n", tmp);
+	tmp |= (AUDIO_ELD_VALID_A << (pipe * 4));
+	I915_WRITE(aud_cntrl_st2, tmp);
+	tmp = I915_READ(aud_cntrl_st2);
+	DRM_DEBUG_DRIVER("HDMI audio: eld vld status=0x%8x\n", tmp);
+
+	/* Enable HDMI mode */
+	tmp = I915_READ(aud_config);
+	DRM_DEBUG_DRIVER("HDMI audio: audio conf: 0x%8x\n", tmp);
+	/* clear N_programing_enable and N_value_index */
+	tmp &= ~(AUD_CONFIG_N_VALUE_INDEX | AUD_CONFIG_N_PROG_ENABLE);
+	I915_WRITE(aud_config, tmp);
+
+	DRM_DEBUG_DRIVER("ELD on pipe %c\n", pipe_name(pipe));
+
+	eldv = AUDIO_ELD_VALID_A << (pipe * 4);
+
+	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) {
+		DRM_DEBUG_DRIVER("ELD: DisplayPort detected\n");
+		eld[5] |= (1 << 2);	/* Conn_Type, 0x1 = DisplayPort */
+		I915_WRITE(aud_config, AUD_CONFIG_N_VALUE_INDEX); /* 0x1 = DP */
+	} else
+		I915_WRITE(aud_config, 0);
+
+	if (intel_eld_uptodate(connector,
+			       aud_cntrl_st2, eldv,
+			       aud_cntl_st, IBX_ELD_ADDRESS,
+			       hdmiw_hdmiedid))
+		return;
+
+	i = I915_READ(aud_cntrl_st2);
+	i &= ~eldv;
+	I915_WRITE(aud_cntrl_st2, i);
+
+	if (!eld[0])
+		return;
+
+	i = I915_READ(aud_cntl_st);
+	i &= ~IBX_ELD_ADDRESS;
+	I915_WRITE(aud_cntl_st, i);
+	i = (i >> 29) & DIP_PORT_SEL_MASK;		/* DIP_Port_Select, 0x1 = PortB */
+	DRM_DEBUG_DRIVER("port num:%d\n", i);
+
+	len = min_t(uint8_t, eld[2], 21);	/* 84 bytes of hw ELD buffer */
+	DRM_DEBUG_DRIVER("ELD size %d\n", len);
+	for (i = 0; i < len; i++)
+		I915_WRITE(hdmiw_hdmiedid, *((uint32_t *)eld + i));
+
+	i = I915_READ(aud_cntrl_st2);
+	i |= eldv;
+	I915_WRITE(aud_cntrl_st2, i);
+
+}
+
 static void ironlake_write_eld(struct drm_connector *connector,
 				     struct drm_crtc *crtc)
 {
@@ -5069,28 +5239,24 @@ static void ironlake_write_eld(struct drm_connector *connector,
 	int aud_config;
 	int aud_cntl_st;
 	int aud_cntrl_st2;
+	int pipe = to_intel_crtc(crtc)->pipe;
 
 	if (HAS_PCH_IBX(connector->dev)) {
-		hdmiw_hdmiedid = IBX_HDMIW_HDMIEDID_A;
-		aud_config = IBX_AUD_CONFIG_A;
-		aud_cntl_st = IBX_AUD_CNTL_ST_A;
+		hdmiw_hdmiedid = IBX_HDMIW_HDMIEDID(pipe);
+		aud_config = IBX_AUD_CFG(pipe);
+		aud_cntl_st = IBX_AUD_CNTL_ST(pipe);
 		aud_cntrl_st2 = IBX_AUD_CNTL_ST2;
 	} else {
-		hdmiw_hdmiedid = CPT_HDMIW_HDMIEDID_A;
-		aud_config = CPT_AUD_CONFIG_A;
-		aud_cntl_st = CPT_AUD_CNTL_ST_A;
+		hdmiw_hdmiedid = CPT_HDMIW_HDMIEDID(pipe);
+		aud_config = CPT_AUD_CFG(pipe);
+		aud_cntl_st = CPT_AUD_CNTL_ST(pipe);
 		aud_cntrl_st2 = CPT_AUD_CNTRL_ST2;
 	}
 
-	i = to_intel_crtc(crtc)->pipe;
-	hdmiw_hdmiedid += i * 0x100;
-	aud_cntl_st += i * 0x100;
-	aud_config += i * 0x100;
-
-	DRM_DEBUG_DRIVER("ELD on pipe %c\n", pipe_name(i));
+	DRM_DEBUG_DRIVER("ELD on pipe %c\n", pipe_name(pipe));
 
 	i = I915_READ(aud_cntl_st);
-	i = (i >> 29) & 0x3;		/* DIP_Port_Select, 0x1 = PortB */
+	i = (i >> 29) & DIP_PORT_SEL_MASK;		/* DIP_Port_Select, 0x1 = PortB */
 	if (!i) {
 		DRM_DEBUG_DRIVER("Audio directed to unknown port\n");
 		/* operate blindly on all ports */
@@ -5337,8 +5503,6 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
 	uint32_t addr;
 	int ret;
 
-	DRM_DEBUG_KMS("\n");
-
 	/* if we want to turn off the cursor ignore width and height */
 	if (!handle) {
 		DRM_DEBUG_KMS("cursor off\n");
@@ -5584,17 +5748,18 @@ mode_fits_in_fbdev(struct drm_device *dev,
 	return fb;
 }
 
-bool intel_get_load_detect_pipe(struct intel_encoder *intel_encoder,
-				struct drm_connector *connector,
+bool intel_get_load_detect_pipe(struct drm_connector *connector,
 				struct drm_display_mode *mode,
 				struct intel_load_detect_pipe *old)
 {
 	struct intel_crtc *intel_crtc;
+	struct intel_encoder *intel_encoder =
+		intel_attached_encoder(connector);
 	struct drm_crtc *possible_crtc;
 	struct drm_encoder *encoder = &intel_encoder->base;
 	struct drm_crtc *crtc = NULL;
 	struct drm_device *dev = encoder->dev;
-	struct drm_framebuffer *old_fb;
+	struct drm_framebuffer *fb;
 	int i = -1;
 
 	DRM_DEBUG_KMS("[CONNECTOR:%d:%s], [ENCODER:%d:%s]\n",
@@ -5615,21 +5780,12 @@ bool intel_get_load_detect_pipe(struct intel_encoder *intel_encoder,
 	if (encoder->crtc) {
 		crtc = encoder->crtc;
 
-		intel_crtc = to_intel_crtc(crtc);
-		old->dpms_mode = intel_crtc->dpms_mode;
+		old->dpms_mode = connector->dpms;
 		old->load_detect_temp = false;
 
 		/* Make sure the crtc and connector are running */
-		if (intel_crtc->dpms_mode != DRM_MODE_DPMS_ON) {
-			struct drm_encoder_helper_funcs *encoder_funcs;
-			struct drm_crtc_helper_funcs *crtc_funcs;
-
-			crtc_funcs = crtc->helper_private;
-			crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
-
-			encoder_funcs = encoder->helper_private;
-			encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
-		}
+		if (connector->dpms != DRM_MODE_DPMS_ON)
+			connector->funcs->dpms(connector, DRM_MODE_DPMS_ON);
 
 		return true;
 	}
@@ -5653,19 +5809,17 @@ bool intel_get_load_detect_pipe(struct intel_encoder *intel_encoder,
 		return false;
 	}
 
-	encoder->crtc = crtc;
-	connector->encoder = encoder;
+	intel_encoder->new_crtc = to_intel_crtc(crtc);
+	to_intel_connector(connector)->new_encoder = intel_encoder;
 
 	intel_crtc = to_intel_crtc(crtc);
-	old->dpms_mode = intel_crtc->dpms_mode;
+	old->dpms_mode = connector->dpms;
 	old->load_detect_temp = true;
 	old->release_fb = NULL;
 
 	if (!mode)
 		mode = &load_detect_mode;
 
-	old_fb = crtc->fb;
-
 	/* We need a framebuffer large enough to accommodate all accesses
 	 * that the plane may generate whilst we perform load detection.
 	 * We can not rely on the fbcon either being present (we get called
@@ -5673,50 +5827,52 @@ bool intel_get_load_detect_pipe(struct intel_encoder *intel_encoder,
 	 * not even exist) or that it is large enough to satisfy the
 	 * requested mode.
 	 */
-	crtc->fb = mode_fits_in_fbdev(dev, mode);
-	if (crtc->fb == NULL) {
+	fb = mode_fits_in_fbdev(dev, mode);
+	if (fb == NULL) {
 		DRM_DEBUG_KMS("creating tmp fb for load-detection\n");
-		crtc->fb = intel_framebuffer_create_for_mode(dev, mode, 24, 32);
-		old->release_fb = crtc->fb;
+		fb = intel_framebuffer_create_for_mode(dev, mode, 24, 32);
+		old->release_fb = fb;
 	} else
 		DRM_DEBUG_KMS("reusing fbdev for load-detection framebuffer\n");
-	if (IS_ERR(crtc->fb)) {
+	if (IS_ERR(fb)) {
 		DRM_DEBUG_KMS("failed to allocate framebuffer for load-detection\n");
-		crtc->fb = old_fb;
-		return false;
+		goto fail;
 	}
 
-	if (!drm_crtc_helper_set_mode(crtc, mode, 0, 0, old_fb)) {
+	if (!intel_set_mode(crtc, mode, 0, 0, fb)) {
 		DRM_DEBUG_KMS("failed to set mode on load-detect pipe\n");
 		if (old->release_fb)
 			old->release_fb->funcs->destroy(old->release_fb);
-		crtc->fb = old_fb;
-		return false;
+		goto fail;
 	}
 
 	/* let the connector get through one full cycle before testing */
 	intel_wait_for_vblank(dev, intel_crtc->pipe);
 
 	return true;
+fail:
+	connector->encoder = NULL;
+	encoder->crtc = NULL;
+	return false;
 }
 
-void intel_release_load_detect_pipe(struct intel_encoder *intel_encoder,
-				    struct drm_connector *connector,
+void intel_release_load_detect_pipe(struct drm_connector *connector,
 				    struct intel_load_detect_pipe *old)
 {
+	struct intel_encoder *intel_encoder =
+		intel_attached_encoder(connector);
 	struct drm_encoder *encoder = &intel_encoder->base;
-	struct drm_device *dev = encoder->dev;
-	struct drm_crtc *crtc = encoder->crtc;
-	struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
-	struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
 
 	DRM_DEBUG_KMS("[CONNECTOR:%d:%s], [ENCODER:%d:%s]\n",
 		      connector->base.id, drm_get_connector_name(connector),
 		      encoder->base.id, drm_get_encoder_name(encoder));
 
 	if (old->load_detect_temp) {
-		connector->encoder = NULL;
-		drm_helper_disable_unused_functions(dev);
+		struct drm_crtc *crtc = encoder->crtc;
+
+		to_intel_connector(connector)->new_encoder = NULL;
+		intel_encoder->new_crtc = NULL;
+		intel_set_mode(crtc, NULL, 0, 0, NULL);
 
 		if (old->release_fb)
 			old->release_fb->funcs->destroy(old->release_fb);
@@ -5725,10 +5881,8 @@ void intel_release_load_detect_pipe(struct intel_encoder *intel_encoder,
 	}
 
 	/* Switch crtc and encoder back off if necessary */
-	if (old->dpms_mode != DRM_MODE_DPMS_ON) {
-		encoder_funcs->dpms(encoder, old->dpms_mode);
-		crtc_funcs->dpms(crtc, old->dpms_mode);
-	}
+	if (old->dpms_mode != DRM_MODE_DPMS_ON)
+		connector->funcs->dpms(connector, old->dpms_mode);
 }
 
 /* Returns the clock of the currently programmed mode of the given pipe. */
@@ -5850,56 +6004,16 @@ struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev,
 	return mode;
 }
 
-#define GPU_IDLE_TIMEOUT 500 /* ms */
-
-/* When this timer fires, we've been idle for awhile */
-static void intel_gpu_idle_timer(unsigned long arg)
+static void intel_increase_pllclock(struct drm_crtc *crtc)
 {
-	struct drm_device *dev = (struct drm_device *)arg;
+	struct drm_device *dev = crtc->dev;
 	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	int pipe = intel_crtc->pipe;
+	int dpll_reg = DPLL(pipe);
+	int dpll;
 
-	if (!list_empty(&dev_priv->mm.active_list)) {
-		/* Still processing requests, so just re-arm the timer. */
-		mod_timer(&dev_priv->idle_timer, jiffies +
-			  msecs_to_jiffies(GPU_IDLE_TIMEOUT));
-		return;
-	}
-
-	dev_priv->busy = false;
-	queue_work(dev_priv->wq, &dev_priv->idle_work);
-}
-
-#define CRTC_IDLE_TIMEOUT 1000 /* ms */
-
-static void intel_crtc_idle_timer(unsigned long arg)
-{
-	struct intel_crtc *intel_crtc = (struct intel_crtc *)arg;
-	struct drm_crtc *crtc = &intel_crtc->base;
-	drm_i915_private_t *dev_priv = crtc->dev->dev_private;
-	struct intel_framebuffer *intel_fb;
-
-	intel_fb = to_intel_framebuffer(crtc->fb);
-	if (intel_fb && intel_fb->obj->active) {
-		/* The framebuffer is still being accessed by the GPU. */
-		mod_timer(&intel_crtc->idle_timer, jiffies +
-			  msecs_to_jiffies(CRTC_IDLE_TIMEOUT));
-		return;
-	}
-
-	intel_crtc->busy = false;
-	queue_work(dev_priv->wq, &dev_priv->idle_work);
-}
-
-static void intel_increase_pllclock(struct drm_crtc *crtc)
-{
-	struct drm_device *dev = crtc->dev;
-	drm_i915_private_t *dev_priv = dev->dev_private;
-	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	int pipe = intel_crtc->pipe;
-	int dpll_reg = DPLL(pipe);
-	int dpll;
-
-	if (HAS_PCH_SPLIT(dev))
+	if (HAS_PCH_SPLIT(dev))
 		return;
 
 	if (!dev_priv->lvds_downclock_avail)
@@ -5919,10 +6033,6 @@ static void intel_increase_pllclock(struct drm_crtc *crtc)
 		if (dpll & DISPLAY_RATE_SELECT_FPA1)
 			DRM_DEBUG_DRIVER("failed to upclock LVDS!\n");
 	}
-
-	/* Schedule downclock */
-	mod_timer(&intel_crtc->idle_timer, jiffies +
-		  msecs_to_jiffies(CRTC_IDLE_TIMEOUT));
 }
 
 static void intel_decrease_pllclock(struct drm_crtc *crtc)
@@ -5961,89 +6071,46 @@ static void intel_decrease_pllclock(struct drm_crtc *crtc)
 
 }
 
-/**
- * intel_idle_update - adjust clocks for idleness
- * @work: work struct
- *
- * Either the GPU or display (or both) went idle.  Check the busy status
- * here and adjust the CRTC and GPU clocks as necessary.
- */
-static void intel_idle_update(struct work_struct *work)
+void intel_mark_busy(struct drm_device *dev)
+{
+	i915_update_gfx_val(dev->dev_private);
+}
+
+void intel_mark_idle(struct drm_device *dev)
 {
-	drm_i915_private_t *dev_priv = container_of(work, drm_i915_private_t,
-						    idle_work);
-	struct drm_device *dev = dev_priv->dev;
+}
+
+void intel_mark_fb_busy(struct drm_i915_gem_object *obj)
+{
+	struct drm_device *dev = obj->base.dev;
 	struct drm_crtc *crtc;
-	struct intel_crtc *intel_crtc;
 
 	if (!i915_powersave)
 		return;
 
-	mutex_lock(&dev->struct_mutex);
-
-	i915_update_gfx_val(dev_priv);
-
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-		/* Skip inactive CRTCs */
 		if (!crtc->fb)
 			continue;
 
-		intel_crtc = to_intel_crtc(crtc);
-		if (!intel_crtc->busy)
-			intel_decrease_pllclock(crtc);
+		if (to_intel_framebuffer(crtc->fb)->obj == obj)
+			intel_increase_pllclock(crtc);
 	}
-
-
-	mutex_unlock(&dev->struct_mutex);
 }
 
-/**
- * intel_mark_busy - mark the GPU and possibly the display busy
- * @dev: drm device
- * @obj: object we're operating on
- *
- * Callers can use this function to indicate that the GPU is busy processing
- * commands.  If @obj matches one of the CRTC objects (i.e. it's a scanout
- * buffer), we'll also mark the display as busy, so we know to increase its
- * clock frequency.
- */
-void intel_mark_busy(struct drm_device *dev, struct drm_i915_gem_object *obj)
+void intel_mark_fb_idle(struct drm_i915_gem_object *obj)
 {
-	drm_i915_private_t *dev_priv = dev->dev_private;
-	struct drm_crtc *crtc = NULL;
-	struct intel_framebuffer *intel_fb;
-	struct intel_crtc *intel_crtc;
-
-	if (!drm_core_check_feature(dev, DRIVER_MODESET))
-		return;
-
-	if (!dev_priv->busy) {
-		intel_sanitize_pm(dev);
-		dev_priv->busy = true;
-	} else
-		mod_timer(&dev_priv->idle_timer, jiffies +
-			  msecs_to_jiffies(GPU_IDLE_TIMEOUT));
+	struct drm_device *dev = obj->base.dev;
+	struct drm_crtc *crtc;
 
-	if (obj == NULL)
+	if (!i915_powersave)
 		return;
 
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
 		if (!crtc->fb)
 			continue;
 
-		intel_crtc = to_intel_crtc(crtc);
-		intel_fb = to_intel_framebuffer(crtc->fb);
-		if (intel_fb->obj == obj) {
-			if (!intel_crtc->busy) {
-				/* Non-busy -> busy, upclock */
-				intel_increase_pllclock(crtc);
-				intel_crtc->busy = true;
-			} else {
-				/* Busy -> busy, put off timer */
-				mod_timer(&intel_crtc->idle_timer, jiffies +
-					  msecs_to_jiffies(CRTC_IDLE_TIMEOUT));
-			}
-		}
+		if (to_intel_framebuffer(crtc->fb)->obj == obj)
+			intel_decrease_pllclock(crtc);
 	}
 }
 
@@ -6394,7 +6461,7 @@ static int intel_gen7_queue_flip(struct drm_device *dev,
 	default:
 		WARN_ONCE(1, "unknown plane in flip command\n");
 		ret = -ENODEV;
-		goto err;
+		goto err_unpin;
 	}
 
 	ret = intel_ring_begin(ring, 4);
@@ -6502,7 +6569,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
 		goto cleanup_pending;
 
 	intel_disable_fbc(dev);
-	intel_mark_busy(dev, obj);
+	intel_mark_fb_busy(obj);
 	mutex_unlock(&dev->struct_mutex);
 
 	trace_i915_flip_request(intel_crtc->plane, obj);
@@ -6527,81 +6594,811 @@ free_work:
 	return ret;
 }
 
-static void intel_sanitize_modesetting(struct drm_device *dev,
-				       int pipe, int plane)
+static struct drm_crtc_helper_funcs intel_helper_funcs = {
+	.mode_set_base_atomic = intel_pipe_set_base_atomic,
+	.load_lut = intel_crtc_load_lut,
+	.disable = intel_crtc_noop,
+};
+
+bool intel_encoder_check_is_cloned(struct intel_encoder *encoder)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	u32 reg, val;
-	int i;
+	struct intel_encoder *other_encoder;
+	struct drm_crtc *crtc = &encoder->new_crtc->base;
 
-	/* Clear any frame start delays used for debugging left by the BIOS */
-	for_each_pipe(i) {
-		reg = PIPECONF(i);
-		I915_WRITE(reg, I915_READ(reg) & ~PIPECONF_FRAME_START_DELAY_MASK);
+	if (WARN_ON(!crtc))
+		return false;
+
+	list_for_each_entry(other_encoder,
+			    &crtc->dev->mode_config.encoder_list,
+			    base.head) {
+
+		if (&other_encoder->new_crtc->base != crtc ||
+		    encoder == other_encoder)
+			continue;
+		else
+			return true;
 	}
 
-	if (HAS_PCH_SPLIT(dev))
-		return;
+	return false;
+}
 
-	/* Who knows what state these registers were left in by the BIOS or
-	 * grub?
-	 *
-	 * If we leave the registers in a conflicting state (e.g. with the
-	 * display plane reading from the other pipe than the one we intend
-	 * to use) then when we attempt to teardown the active mode, we will
-	 * not disable the pipes and planes in the correct order -- leaving
-	 * a plane reading from a disabled pipe and possibly leading to
-	 * undefined behaviour.
+static bool intel_encoder_crtc_ok(struct drm_encoder *encoder,
+				  struct drm_crtc *crtc)
+{
+	struct drm_device *dev;
+	struct drm_crtc *tmp;
+	int crtc_mask = 1;
+
+	WARN(!crtc, "checking null crtc?\n");
+
+	dev = crtc->dev;
+
+	list_for_each_entry(tmp, &dev->mode_config.crtc_list, head) {
+		if (tmp == crtc)
+			break;
+		crtc_mask <<= 1;
+	}
+
+	if (encoder->possible_crtcs & crtc_mask)
+		return true;
+	return false;
+}
+
+/**
+ * intel_modeset_update_staged_output_state
+ *
+ * Updates the staged output configuration state, e.g. after we've read out the
+ * current hw state.
+ */
+static void intel_modeset_update_staged_output_state(struct drm_device *dev)
+{
+	struct intel_encoder *encoder;
+	struct intel_connector *connector;
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list,
+			    base.head) {
+		connector->new_encoder =
+			to_intel_encoder(connector->base.encoder);
+	}
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list,
+			    base.head) {
+		encoder->new_crtc =
+			to_intel_crtc(encoder->base.crtc);
+	}
+}
+
+/**
+ * intel_modeset_commit_output_state
+ *
+ * This function copies the stage display pipe configuration to the real one.
+ */
+static void intel_modeset_commit_output_state(struct drm_device *dev)
+{
+	struct intel_encoder *encoder;
+	struct intel_connector *connector;
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list,
+			    base.head) {
+		connector->base.encoder = &connector->new_encoder->base;
+	}
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list,
+			    base.head) {
+		encoder->base.crtc = &encoder->new_crtc->base;
+	}
+}
+
+static struct drm_display_mode *
+intel_modeset_adjusted_mode(struct drm_crtc *crtc,
+			    struct drm_display_mode *mode)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_display_mode *adjusted_mode;
+	struct drm_encoder_helper_funcs *encoder_funcs;
+	struct intel_encoder *encoder;
+
+	adjusted_mode = drm_mode_duplicate(dev, mode);
+	if (!adjusted_mode)
+		return ERR_PTR(-ENOMEM);
+
+	/* Pass our mode to the connectors and the CRTC to give them a chance to
+	 * adjust it according to limitations or connector properties, and also
+	 * a chance to reject the mode entirely.
 	 */
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list,
+			    base.head) {
 
-	reg = DSPCNTR(plane);
-	val = I915_READ(reg);
+		if (&encoder->new_crtc->base != crtc)
+			continue;
+		encoder_funcs = encoder->base.helper_private;
+		if (!(encoder_funcs->mode_fixup(&encoder->base, mode,
+						adjusted_mode))) {
+			DRM_DEBUG_KMS("Encoder fixup failed\n");
+			goto fail;
+		}
+	}
 
-	if ((val & DISPLAY_PLANE_ENABLE) == 0)
-		return;
-	if (!!(val & DISPPLANE_SEL_PIPE_MASK) == pipe)
-		return;
+	if (!(intel_crtc_mode_fixup(crtc, mode, adjusted_mode))) {
+		DRM_DEBUG_KMS("CRTC fixup failed\n");
+		goto fail;
+	}
+	DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id);
 
-	/* This display plane is active and attached to the other CPU pipe. */
-	pipe = !pipe;
+	return adjusted_mode;
+fail:
+	drm_mode_destroy(dev, adjusted_mode);
+	return ERR_PTR(-EINVAL);
+}
 
-	/* Disable the plane and wait for it to stop reading from the pipe. */
-	intel_disable_plane(dev_priv, plane, pipe);
-	intel_disable_pipe(dev_priv, pipe);
+/* Computes which crtcs are affected and sets the relevant bits in the mask. For
+ * simplicity we use the crtc's pipe number (because it's easier to obtain). */
+static void
+intel_modeset_affected_pipes(struct drm_crtc *crtc, unsigned *modeset_pipes,
+			     unsigned *prepare_pipes, unsigned *disable_pipes)
+{
+	struct intel_crtc *intel_crtc;
+	struct drm_device *dev = crtc->dev;
+	struct intel_encoder *encoder;
+	struct intel_connector *connector;
+	struct drm_crtc *tmp_crtc;
+
+	*disable_pipes = *modeset_pipes = *prepare_pipes = 0;
+
+	/* Check which crtcs have changed outputs connected to them, these need
+	 * to be part of the prepare_pipes mask. We don't (yet) support global
+	 * modeset across multiple crtcs, so modeset_pipes will only have one
+	 * bit set at most. */
+	list_for_each_entry(connector, &dev->mode_config.connector_list,
+			    base.head) {
+		if (connector->base.encoder == &connector->new_encoder->base)
+			continue;
+
+		if (connector->base.encoder) {
+			tmp_crtc = connector->base.encoder->crtc;
+
+			*prepare_pipes |= 1 << to_intel_crtc(tmp_crtc)->pipe;
+		}
+
+		if (connector->new_encoder)
+			*prepare_pipes |=
+				1 << connector->new_encoder->new_crtc->pipe;
+	}
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list,
+			    base.head) {
+		if (encoder->base.crtc == &encoder->new_crtc->base)
+			continue;
+
+		if (encoder->base.crtc) {
+			tmp_crtc = encoder->base.crtc;
+
+			*prepare_pipes |= 1 << to_intel_crtc(tmp_crtc)->pipe;
+		}
+
+		if (encoder->new_crtc)
+			*prepare_pipes |= 1 << encoder->new_crtc->pipe;
+	}
+
+	/* Check for any pipes that will be fully disabled ... */
+	list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list,
+			    base.head) {
+		bool used = false;
+
+		/* Don't try to disable disabled crtcs. */
+		if (!intel_crtc->base.enabled)
+			continue;
+
+		list_for_each_entry(encoder, &dev->mode_config.encoder_list,
+				    base.head) {
+			if (encoder->new_crtc == intel_crtc)
+				used = true;
+		}
+
+		if (!used)
+			*disable_pipes |= 1 << intel_crtc->pipe;
+	}
+
+
+	/* set_mode is also used to update properties on life display pipes. */
+	intel_crtc = to_intel_crtc(crtc);
+	if (crtc->enabled)
+		*prepare_pipes |= 1 << intel_crtc->pipe;
+
+	/* We only support modeset on one single crtc, hence we need to do that
+	 * only for the passed in crtc iff we change anything else than just
+	 * disable crtcs.
+	 *
+	 * This is actually not true, to be fully compatible with the old crtc
+	 * helper we automatically disable _any_ output (i.e. doesn't need to be
+	 * connected to the crtc we're modesetting on) if it's disconnected.
+	 * Which is a rather nutty api (since changed the output configuration
+	 * without userspace's explicit request can lead to confusion), but
+	 * alas. Hence we currently need to modeset on all pipes we prepare. */
+	if (*prepare_pipes)
+		*modeset_pipes = *prepare_pipes;
+
+	/* ... and mask these out. */
+	*modeset_pipes &= ~(*disable_pipes);
+	*prepare_pipes &= ~(*disable_pipes);
 }
 
-static void intel_crtc_reset(struct drm_crtc *crtc)
+static bool intel_crtc_in_use(struct drm_crtc *crtc)
 {
+	struct drm_encoder *encoder;
 	struct drm_device *dev = crtc->dev;
-	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 
-	/* Reset flags back to the 'unknown' status so that they
-	 * will be correctly set on the initial modeset.
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
+		if (encoder->crtc == crtc)
+			return true;
+
+	return false;
+}
+
+static void
+intel_modeset_update_state(struct drm_device *dev, unsigned prepare_pipes)
+{
+	struct intel_encoder *intel_encoder;
+	struct intel_crtc *intel_crtc;
+	struct drm_connector *connector;
+
+	list_for_each_entry(intel_encoder, &dev->mode_config.encoder_list,
+			    base.head) {
+		if (!intel_encoder->base.crtc)
+			continue;
+
+		intel_crtc = to_intel_crtc(intel_encoder->base.crtc);
+
+		if (prepare_pipes & (1 << intel_crtc->pipe))
+			intel_encoder->connectors_active = false;
+	}
+
+	intel_modeset_commit_output_state(dev);
+
+	/* Update computed state. */
+	list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list,
+			    base.head) {
+		intel_crtc->base.enabled = intel_crtc_in_use(&intel_crtc->base);
+	}
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		if (!connector->encoder || !connector->encoder->crtc)
+			continue;
+
+		intel_crtc = to_intel_crtc(connector->encoder->crtc);
+
+		if (prepare_pipes & (1 << intel_crtc->pipe)) {
+			connector->dpms = DRM_MODE_DPMS_ON;
+
+			intel_encoder = to_intel_encoder(connector->encoder);
+			intel_encoder->connectors_active = true;
+		}
+	}
+
+}
+
+#define for_each_intel_crtc_masked(dev, mask, intel_crtc) \
+	list_for_each_entry((intel_crtc), \
+			    &(dev)->mode_config.crtc_list, \
+			    base.head) \
+		if (mask & (1 <<(intel_crtc)->pipe)) \
+
+void
+intel_modeset_check_state(struct drm_device *dev)
+{
+	struct intel_crtc *crtc;
+	struct intel_encoder *encoder;
+	struct intel_connector *connector;
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list,
+			    base.head) {
+		/* This also checks the encoder/connector hw state with the
+		 * ->get_hw_state callbacks. */
+		intel_connector_check_state(connector);
+
+		WARN(&connector->new_encoder->base != connector->base.encoder,
+		     "connector's staged encoder doesn't match current encoder\n");
+	}
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list,
+			    base.head) {
+		bool enabled = false;
+		bool active = false;
+		enum pipe pipe, tracked_pipe;
+
+		DRM_DEBUG_KMS("[ENCODER:%d:%s]\n",
+			      encoder->base.base.id,
+			      drm_get_encoder_name(&encoder->base));
+
+		WARN(&encoder->new_crtc->base != encoder->base.crtc,
+		     "encoder's stage crtc doesn't match current crtc\n");
+		WARN(encoder->connectors_active && !encoder->base.crtc,
+		     "encoder's active_connectors set, but no crtc\n");
+
+		list_for_each_entry(connector, &dev->mode_config.connector_list,
+				    base.head) {
+			if (connector->base.encoder != &encoder->base)
+				continue;
+			enabled = true;
+			if (connector->base.dpms != DRM_MODE_DPMS_OFF)
+				active = true;
+		}
+		WARN(!!encoder->base.crtc != enabled,
+		     "encoder's enabled state mismatch "
+		     "(expected %i, found %i)\n",
+		     !!encoder->base.crtc, enabled);
+		WARN(active && !encoder->base.crtc,
+		     "active encoder with no crtc\n");
+
+		WARN(encoder->connectors_active != active,
+		     "encoder's computed active state doesn't match tracked active state "
+		     "(expected %i, found %i)\n", active, encoder->connectors_active);
+
+		active = encoder->get_hw_state(encoder, &pipe);
+		WARN(active != encoder->connectors_active,
+		     "encoder's hw state doesn't match sw tracking "
+		     "(expected %i, found %i)\n",
+		     encoder->connectors_active, active);
+
+		if (!encoder->base.crtc)
+			continue;
+
+		tracked_pipe = to_intel_crtc(encoder->base.crtc)->pipe;
+		WARN(active && pipe != tracked_pipe,
+		     "active encoder's pipe doesn't match"
+		     "(expected %i, found %i)\n",
+		     tracked_pipe, pipe);
+
+	}
+
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list,
+			    base.head) {
+		bool enabled = false;
+		bool active = false;
+
+		DRM_DEBUG_KMS("[CRTC:%d]\n",
+			      crtc->base.base.id);
+
+		WARN(crtc->active && !crtc->base.enabled,
+		     "active crtc, but not enabled in sw tracking\n");
+
+		list_for_each_entry(encoder, &dev->mode_config.encoder_list,
+				    base.head) {
+			if (encoder->base.crtc != &crtc->base)
+				continue;
+			enabled = true;
+			if (encoder->connectors_active)
+				active = true;
+		}
+		WARN(active != crtc->active,
+		     "crtc's computed active state doesn't match tracked active state "
+		     "(expected %i, found %i)\n", active, crtc->active);
+		WARN(enabled != crtc->base.enabled,
+		     "crtc's computed enabled state doesn't match tracked enabled state "
+		     "(expected %i, found %i)\n", enabled, crtc->base.enabled);
+
+		assert_pipe(dev->dev_private, crtc->pipe, crtc->active);
+	}
+}
+
+bool intel_set_mode(struct drm_crtc *crtc,
+		    struct drm_display_mode *mode,
+		    int x, int y, struct drm_framebuffer *fb)
+{
+	struct drm_device *dev = crtc->dev;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct drm_display_mode *adjusted_mode, saved_mode, saved_hwmode;
+	struct drm_encoder_helper_funcs *encoder_funcs;
+	struct drm_encoder *encoder;
+	struct intel_crtc *intel_crtc;
+	unsigned disable_pipes, prepare_pipes, modeset_pipes;
+	bool ret = true;
+
+	intel_modeset_affected_pipes(crtc, &modeset_pipes,
+				     &prepare_pipes, &disable_pipes);
+
+	DRM_DEBUG_KMS("set mode pipe masks: modeset: %x, prepare: %x, disable: %x\n",
+		      modeset_pipes, prepare_pipes, disable_pipes);
+
+	for_each_intel_crtc_masked(dev, disable_pipes, intel_crtc)
+		intel_crtc_disable(&intel_crtc->base);
+
+	saved_hwmode = crtc->hwmode;
+	saved_mode = crtc->mode;
+
+	/* Hack: Because we don't (yet) support global modeset on multiple
+	 * crtcs, we don't keep track of the new mode for more than one crtc.
+	 * Hence simply check whether any bit is set in modeset_pipes in all the
+	 * pieces of code that are not yet converted to deal with mutliple crtcs
+	 * changing their mode at the same time. */
+	adjusted_mode = NULL;
+	if (modeset_pipes) {
+		adjusted_mode = intel_modeset_adjusted_mode(crtc, mode);
+		if (IS_ERR(adjusted_mode)) {
+			return false;
+		}
+	}
+
+	for_each_intel_crtc_masked(dev, prepare_pipes, intel_crtc) {
+		if (intel_crtc->base.enabled)
+			dev_priv->display.crtc_disable(&intel_crtc->base);
+	}
+
+	/* crtc->mode is already used by the ->mode_set callbacks, hence we need
+	 * to set it here already despite that we pass it down the callchain.
 	 */
-	intel_crtc->dpms_mode = -1;
+	if (modeset_pipes)
+		crtc->mode = *mode;
 
-	/* We need to fix up any BIOS configuration that conflicts with
-	 * our expectations.
+	/* Only after disabling all output pipelines that will be changed can we
+	 * update the the output configuration. */
+	intel_modeset_update_state(dev, prepare_pipes);
+
+	/* Set up the DPLL and any encoders state that needs to adjust or depend
+	 * on the DPLL.
 	 */
-	intel_sanitize_modesetting(dev, intel_crtc->pipe, intel_crtc->plane);
+	for_each_intel_crtc_masked(dev, modeset_pipes, intel_crtc) {
+		ret = !intel_crtc_mode_set(&intel_crtc->base,
+					   mode, adjusted_mode,
+					   x, y, fb);
+		if (!ret)
+		    goto done;
+
+		list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+
+			if (encoder->crtc != &intel_crtc->base)
+				continue;
+
+			DRM_DEBUG_KMS("[ENCODER:%d:%s] set [MODE:%d:%s]\n",
+				encoder->base.id, drm_get_encoder_name(encoder),
+				mode->base.id, mode->name);
+			encoder_funcs = encoder->helper_private;
+			encoder_funcs->mode_set(encoder, mode, adjusted_mode);
+		}
+	}
+
+	/* Now enable the clocks, plane, pipe, and connectors that we set up. */
+	for_each_intel_crtc_masked(dev, prepare_pipes, intel_crtc)
+		dev_priv->display.crtc_enable(&intel_crtc->base);
+
+	if (modeset_pipes) {
+		/* Store real post-adjustment hardware mode. */
+		crtc->hwmode = *adjusted_mode;
+
+		/* Calculate and store various constants which
+		 * are later needed by vblank and swap-completion
+		 * timestamping. They are derived from true hwmode.
+		 */
+		drm_calc_timestamping_constants(crtc);
+	}
+
+	/* FIXME: add subpixel order */
+done:
+	drm_mode_destroy(dev, adjusted_mode);
+	if (!ret && crtc->enabled) {
+		crtc->hwmode = saved_hwmode;
+		crtc->mode = saved_mode;
+	} else {
+		intel_modeset_check_state(dev);
+	}
+
+	return ret;
 }
 
-static struct drm_crtc_helper_funcs intel_helper_funcs = {
-	.dpms = intel_crtc_dpms,
-	.mode_fixup = intel_crtc_mode_fixup,
-	.mode_set = intel_crtc_mode_set,
-	.mode_set_base = intel_pipe_set_base,
-	.mode_set_base_atomic = intel_pipe_set_base_atomic,
-	.load_lut = intel_crtc_load_lut,
-	.disable = intel_crtc_disable,
-};
+#undef for_each_intel_crtc_masked
+
+static void intel_set_config_free(struct intel_set_config *config)
+{
+	if (!config)
+		return;
+
+	kfree(config->save_connector_encoders);
+	kfree(config->save_encoder_crtcs);
+	kfree(config);
+}
+
+static int intel_set_config_save_state(struct drm_device *dev,
+				       struct intel_set_config *config)
+{
+	struct drm_encoder *encoder;
+	struct drm_connector *connector;
+	int count;
+
+	config->save_encoder_crtcs =
+		kcalloc(dev->mode_config.num_encoder,
+			sizeof(struct drm_crtc *), GFP_KERNEL);
+	if (!config->save_encoder_crtcs)
+		return -ENOMEM;
+
+	config->save_connector_encoders =
+		kcalloc(dev->mode_config.num_connector,
+			sizeof(struct drm_encoder *), GFP_KERNEL);
+	if (!config->save_connector_encoders)
+		return -ENOMEM;
+
+	/* Copy data. Note that driver private data is not affected.
+	 * Should anything bad happen only the expected state is
+	 * restored, not the drivers personal bookkeeping.
+	 */
+	count = 0;
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+		config->save_encoder_crtcs[count++] = encoder->crtc;
+	}
+
+	count = 0;
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		config->save_connector_encoders[count++] = connector->encoder;
+	}
+
+	return 0;
+}
+
+static void intel_set_config_restore_state(struct drm_device *dev,
+					   struct intel_set_config *config)
+{
+	struct intel_encoder *encoder;
+	struct intel_connector *connector;
+	int count;
+
+	count = 0;
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) {
+		encoder->new_crtc =
+			to_intel_crtc(config->save_encoder_crtcs[count++]);
+	}
+
+	count = 0;
+	list_for_each_entry(connector, &dev->mode_config.connector_list, base.head) {
+		connector->new_encoder =
+			to_intel_encoder(config->save_connector_encoders[count++]);
+	}
+}
+
+static void
+intel_set_config_compute_mode_changes(struct drm_mode_set *set,
+				      struct intel_set_config *config)
+{
+
+	/* We should be able to check here if the fb has the same properties
+	 * and then just flip_or_move it */
+	if (set->crtc->fb != set->fb) {
+		/* If we have no fb then treat it as a full mode set */
+		if (set->crtc->fb == NULL) {
+			DRM_DEBUG_KMS("crtc has no fb, full mode set\n");
+			config->mode_changed = true;
+		} else if (set->fb == NULL) {
+			config->mode_changed = true;
+		} else if (set->fb->depth != set->crtc->fb->depth) {
+			config->mode_changed = true;
+		} else if (set->fb->bits_per_pixel !=
+			   set->crtc->fb->bits_per_pixel) {
+			config->mode_changed = true;
+		} else
+			config->fb_changed = true;
+	}
+
+	if (set->fb && (set->x != set->crtc->x || set->y != set->crtc->y))
+		config->fb_changed = true;
+
+	if (set->mode && !drm_mode_equal(set->mode, &set->crtc->mode)) {
+		DRM_DEBUG_KMS("modes are different, full mode set\n");
+		drm_mode_debug_printmodeline(&set->crtc->mode);
+		drm_mode_debug_printmodeline(set->mode);
+		config->mode_changed = true;
+	}
+}
+
+static int
+intel_modeset_stage_output_state(struct drm_device *dev,
+				 struct drm_mode_set *set,
+				 struct intel_set_config *config)
+{
+	struct drm_crtc *new_crtc;
+	struct intel_connector *connector;
+	struct intel_encoder *encoder;
+	int count, ro;
+
+	/* The upper layers ensure that we either disabl a crtc or have a list
+	 * of connectors. For paranoia, double-check this. */
+	WARN_ON(!set->fb && (set->num_connectors != 0));
+	WARN_ON(set->fb && (set->num_connectors == 0));
+
+	count = 0;
+	list_for_each_entry(connector, &dev->mode_config.connector_list,
+			    base.head) {
+		/* Otherwise traverse passed in connector list and get encoders
+		 * for them. */
+		for (ro = 0; ro < set->num_connectors; ro++) {
+			if (set->connectors[ro] == &connector->base) {
+				connector->new_encoder = connector->encoder;
+				break;
+			}
+		}
+
+		/* If we disable the crtc, disable all its connectors. Also, if
+		 * the connector is on the changing crtc but not on the new
+		 * connector list, disable it. */
+		if ((!set->fb || ro == set->num_connectors) &&
+		    connector->base.encoder &&
+		    connector->base.encoder->crtc == set->crtc) {
+			connector->new_encoder = NULL;
+
+			DRM_DEBUG_KMS("[CONNECTOR:%d:%s] to [NOCRTC]\n",
+				connector->base.base.id,
+				drm_get_connector_name(&connector->base));
+		}
+
+
+		if (&connector->new_encoder->base != connector->base.encoder) {
+			DRM_DEBUG_KMS("encoder changed, full mode switch\n");
+			config->mode_changed = true;
+		}
+
+		/* Disable all disconnected encoders. */
+		if (connector->base.status == connector_status_disconnected)
+			connector->new_encoder = NULL;
+	}
+	/* connector->new_encoder is now updated for all connectors. */
+
+	/* Update crtc of enabled connectors. */
+	count = 0;
+	list_for_each_entry(connector, &dev->mode_config.connector_list,
+			    base.head) {
+		if (!connector->new_encoder)
+			continue;
+
+		new_crtc = connector->new_encoder->base.crtc;
+
+		for (ro = 0; ro < set->num_connectors; ro++) {
+			if (set->connectors[ro] == &connector->base)
+				new_crtc = set->crtc;
+		}
+
+		/* Make sure the new CRTC will work with the encoder */
+		if (!intel_encoder_crtc_ok(&connector->new_encoder->base,
+					   new_crtc)) {
+			return -EINVAL;
+		}
+		connector->encoder->new_crtc = to_intel_crtc(new_crtc);
+
+		DRM_DEBUG_KMS("[CONNECTOR:%d:%s] to [CRTC:%d]\n",
+			connector->base.base.id,
+			drm_get_connector_name(&connector->base),
+			new_crtc->base.id);
+	}
+
+	/* Check for any encoders that needs to be disabled. */
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list,
+			    base.head) {
+		list_for_each_entry(connector,
+				    &dev->mode_config.connector_list,
+				    base.head) {
+			if (connector->new_encoder == encoder) {
+				WARN_ON(!connector->new_encoder->new_crtc);
+
+				goto next_encoder;
+			}
+		}
+		encoder->new_crtc = NULL;
+next_encoder:
+		/* Only now check for crtc changes so we don't miss encoders
+		 * that will be disabled. */
+		if (&encoder->new_crtc->base != encoder->base.crtc) {
+			DRM_DEBUG_KMS("crtc changed, full mode switch\n");
+			config->mode_changed = true;
+		}
+	}
+	/* Now we've also updated encoder->new_crtc for all encoders. */
+
+	return 0;
+}
+
+static int intel_crtc_set_config(struct drm_mode_set *set)
+{
+	struct drm_device *dev;
+	struct drm_mode_set save_set;
+	struct intel_set_config *config;
+	int ret;
+	int i;
+
+	BUG_ON(!set);
+	BUG_ON(!set->crtc);
+	BUG_ON(!set->crtc->helper_private);
+
+	if (!set->mode)
+		set->fb = NULL;
+
+	/* The fb helper likes to play gross jokes with ->mode_set_config.
+	 * Unfortunately the crtc helper doesn't do much at all for this case,
+	 * so we have to cope with this madness until the fb helper is fixed up. */
+	if (set->fb && set->num_connectors == 0)
+		return 0;
+
+	if (set->fb) {
+		DRM_DEBUG_KMS("[CRTC:%d] [FB:%d] #connectors=%d (x y) (%i %i)\n",
+				set->crtc->base.id, set->fb->base.id,
+				(int)set->num_connectors, set->x, set->y);
+	} else {
+		DRM_DEBUG_KMS("[CRTC:%d] [NOFB]\n", set->crtc->base.id);
+	}
+
+	dev = set->crtc->dev;
+
+	ret = -ENOMEM;
+	config = kzalloc(sizeof(*config), GFP_KERNEL);
+	if (!config)
+		goto out_config;
+
+	ret = intel_set_config_save_state(dev, config);
+	if (ret)
+		goto out_config;
+
+	save_set.crtc = set->crtc;
+	save_set.mode = &set->crtc->mode;
+	save_set.x = set->crtc->x;
+	save_set.y = set->crtc->y;
+	save_set.fb = set->crtc->fb;
+
+	/* Compute whether we need a full modeset, only an fb base update or no
+	 * change at all. In the future we might also check whether only the
+	 * mode changed, e.g. for LVDS where we only change the panel fitter in
+	 * such cases. */
+	intel_set_config_compute_mode_changes(set, config);
+
+	ret = intel_modeset_stage_output_state(dev, set, config);
+	if (ret)
+		goto fail;
+
+	if (config->mode_changed) {
+		if (set->mode) {
+			DRM_DEBUG_KMS("attempting to set mode from"
+					" userspace\n");
+			drm_mode_debug_printmodeline(set->mode);
+		}
+
+		if (!intel_set_mode(set->crtc, set->mode,
+				    set->x, set->y, set->fb)) {
+			DRM_ERROR("failed to set mode on [CRTC:%d]\n",
+				  set->crtc->base.id);
+			ret = -EINVAL;
+			goto fail;
+		}
+
+		if (set->crtc->enabled) {
+			DRM_DEBUG_KMS("Setting connector DPMS state to on\n");
+			for (i = 0; i < set->num_connectors; i++) {
+				DRM_DEBUG_KMS("\t[CONNECTOR:%d:%s] set DPMS on\n", set->connectors[i]->base.id,
+					      drm_get_connector_name(set->connectors[i]));
+				set->connectors[i]->funcs->dpms(set->connectors[i], DRM_MODE_DPMS_ON);
+			}
+		}
+	} else if (config->fb_changed) {
+		ret = intel_pipe_set_base(set->crtc,
+					  set->x, set->y, set->fb);
+	}
+
+	intel_set_config_free(config);
+
+	return 0;
+
+fail:
+	intel_set_config_restore_state(dev, config);
+
+	/* Try to restore the config */
+	if (config->mode_changed &&
+	    !intel_set_mode(save_set.crtc, save_set.mode,
+			    save_set.x, save_set.y, save_set.fb))
+		DRM_ERROR("failed to restore config after modeset failure\n");
+
+out_config:
+	intel_set_config_free(config);
+	return ret;
+}
 
 static const struct drm_crtc_funcs intel_crtc_funcs = {
-	.reset = intel_crtc_reset,
 	.cursor_set = intel_crtc_cursor_set,
 	.cursor_move = intel_crtc_cursor_move,
 	.gamma_set = intel_crtc_gamma_set,
-	.set_config = drm_crtc_helper_set_config,
+	.set_config = intel_crtc_set_config,
 	.destroy = intel_crtc_destroy,
 	.page_flip = intel_crtc_page_flip,
 };
@@ -6655,24 +7452,9 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
 	dev_priv->plane_to_crtc_mapping[intel_crtc->plane] = &intel_crtc->base;
 	dev_priv->pipe_to_crtc_mapping[intel_crtc->pipe] = &intel_crtc->base;
 
-	intel_crtc_reset(&intel_crtc->base);
-	intel_crtc->active = true; /* force the pipe off on setup_init_config */
 	intel_crtc->bpp = 24; /* default for pre-Ironlake */
 
-	if (HAS_PCH_SPLIT(dev)) {
-		intel_helper_funcs.prepare = ironlake_crtc_prepare;
-		intel_helper_funcs.commit = ironlake_crtc_commit;
-	} else {
-		intel_helper_funcs.prepare = i9xx_crtc_prepare;
-		intel_helper_funcs.commit = i9xx_crtc_commit;
-	}
-
 	drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs);
-
-	intel_crtc->busy = false;
-
-	setup_timer(&intel_crtc->idle_timer, intel_crtc_idle_timer,
-		    (unsigned long)intel_crtc);
 }
 
 int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
@@ -6699,15 +7481,23 @@ int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
 	return 0;
 }
 
-static int intel_encoder_clones(struct drm_device *dev, int type_mask)
+static int intel_encoder_clones(struct intel_encoder *encoder)
 {
-	struct intel_encoder *encoder;
+	struct drm_device *dev = encoder->base.dev;
+	struct intel_encoder *source_encoder;
 	int index_mask = 0;
 	int entry = 0;
 
-	list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) {
-		if (type_mask & encoder->clone_mask)
+	list_for_each_entry(source_encoder,
+			    &dev->mode_config.encoder_list, base.head) {
+
+		if (encoder == source_encoder)
+			index_mask |= (1 << entry);
+
+		/* Intel hw has only one MUX where enocoders could be cloned. */
+		if (encoder->cloneable && source_encoder->cloneable)
 			index_mask |= (1 << entry);
+
 		entry++;
 	}
 
@@ -6748,10 +7538,10 @@ static void intel_setup_outputs(struct drm_device *dev)
 		dpd_is_edp = intel_dpd_is_edp(dev);
 
 		if (has_edp_a(dev))
-			intel_dp_init(dev, DP_A);
+			intel_dp_init(dev, DP_A, PORT_A);
 
 		if (dpd_is_edp && (I915_READ(PCH_DP_D) & DP_DETECTED))
-			intel_dp_init(dev, PCH_DP_D);
+			intel_dp_init(dev, PCH_DP_D, PORT_D);
 	}
 
 	intel_crt_init(dev);
@@ -6782,22 +7572,22 @@ static void intel_setup_outputs(struct drm_device *dev)
 			/* PCH SDVOB multiplex with HDMIB */
 			found = intel_sdvo_init(dev, PCH_SDVOB, true);
 			if (!found)
-				intel_hdmi_init(dev, HDMIB);
+				intel_hdmi_init(dev, HDMIB, PORT_B);
 			if (!found && (I915_READ(PCH_DP_B) & DP_DETECTED))
-				intel_dp_init(dev, PCH_DP_B);
+				intel_dp_init(dev, PCH_DP_B, PORT_B);
 		}
 
 		if (I915_READ(HDMIC) & PORT_DETECTED)
-			intel_hdmi_init(dev, HDMIC);
+			intel_hdmi_init(dev, HDMIC, PORT_C);
 
 		if (!dpd_is_edp && I915_READ(HDMID) & PORT_DETECTED)
-			intel_hdmi_init(dev, HDMID);
+			intel_hdmi_init(dev, HDMID, PORT_D);
 
 		if (I915_READ(PCH_DP_C) & DP_DETECTED)
-			intel_dp_init(dev, PCH_DP_C);
+			intel_dp_init(dev, PCH_DP_C, PORT_C);
 
 		if (!dpd_is_edp && (I915_READ(PCH_DP_D) & DP_DETECTED))
-			intel_dp_init(dev, PCH_DP_D);
+			intel_dp_init(dev, PCH_DP_D, PORT_D);
 	} else if (IS_VALLEYVIEW(dev)) {
 		int found;
 
@@ -6805,17 +7595,17 @@ static void intel_setup_outputs(struct drm_device *dev)
 			/* SDVOB multiplex with HDMIB */
 			found = intel_sdvo_init(dev, SDVOB, true);
 			if (!found)
-				intel_hdmi_init(dev, SDVOB);
+				intel_hdmi_init(dev, SDVOB, PORT_B);
 			if (!found && (I915_READ(DP_B) & DP_DETECTED))
-				intel_dp_init(dev, DP_B);
+				intel_dp_init(dev, DP_B, PORT_B);
 		}
 
 		if (I915_READ(SDVOC) & PORT_DETECTED)
-			intel_hdmi_init(dev, SDVOC);
+			intel_hdmi_init(dev, SDVOC, PORT_C);
 
 		/* Shares lanes with HDMI on SDVOC */
 		if (I915_READ(DP_C) & DP_DETECTED)
-			intel_dp_init(dev, DP_C);
+			intel_dp_init(dev, DP_C, PORT_C);
 	} else if (SUPPORTS_DIGITAL_OUTPUTS(dev)) {
 		bool found = false;
 
@@ -6824,12 +7614,12 @@ static void intel_setup_outputs(struct drm_device *dev)
 			found = intel_sdvo_init(dev, SDVOB, true);
 			if (!found && SUPPORTS_INTEGRATED_HDMI(dev)) {
 				DRM_DEBUG_KMS("probing HDMI on SDVOB\n");
-				intel_hdmi_init(dev, SDVOB);
+				intel_hdmi_init(dev, SDVOB, PORT_B);
 			}
 
 			if (!found && SUPPORTS_INTEGRATED_DP(dev)) {
 				DRM_DEBUG_KMS("probing DP_B\n");
-				intel_dp_init(dev, DP_B);
+				intel_dp_init(dev, DP_B, PORT_B);
 			}
 		}
 
@@ -6844,18 +7634,18 @@ static void intel_setup_outputs(struct drm_device *dev)
 
 			if (SUPPORTS_INTEGRATED_HDMI(dev)) {
 				DRM_DEBUG_KMS("probing HDMI on SDVOC\n");
-				intel_hdmi_init(dev, SDVOC);
+				intel_hdmi_init(dev, SDVOC, PORT_C);
 			}
 			if (SUPPORTS_INTEGRATED_DP(dev)) {
 				DRM_DEBUG_KMS("probing DP_C\n");
-				intel_dp_init(dev, DP_C);
+				intel_dp_init(dev, DP_C, PORT_C);
 			}
 		}
 
 		if (SUPPORTS_INTEGRATED_DP(dev) &&
 		    (I915_READ(DP_D) & DP_DETECTED)) {
 			DRM_DEBUG_KMS("probing DP_D\n");
-			intel_dp_init(dev, DP_D);
+			intel_dp_init(dev, DP_D, PORT_D);
 		}
 	} else if (IS_GEN2(dev))
 		intel_dvo_init(dev);
@@ -6866,12 +7656,9 @@ static void intel_setup_outputs(struct drm_device *dev)
 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) {
 		encoder->base.possible_crtcs = encoder->crtc_mask;
 		encoder->base.possible_clones =
-			intel_encoder_clones(dev, encoder->clone_mask);
+			intel_encoder_clones(encoder);
 	}
 
-	/* disable all the possible outputs/crtcs before entering KMS mode */
-	drm_helper_disable_unused_functions(dev);
-
 	if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev))
 		ironlake_init_pch_refclk(dev);
 }
@@ -6973,13 +7760,15 @@ static void intel_init_display(struct drm_device *dev)
 
 	/* We always want a DPMS function */
 	if (HAS_PCH_SPLIT(dev)) {
-		dev_priv->display.dpms = ironlake_crtc_dpms;
 		dev_priv->display.crtc_mode_set = ironlake_crtc_mode_set;
+		dev_priv->display.crtc_enable = ironlake_crtc_enable;
+		dev_priv->display.crtc_disable = ironlake_crtc_disable;
 		dev_priv->display.off = ironlake_crtc_off;
 		dev_priv->display.update_plane = ironlake_update_plane;
 	} else {
-		dev_priv->display.dpms = i9xx_crtc_dpms;
 		dev_priv->display.crtc_mode_set = i9xx_crtc_mode_set;
+		dev_priv->display.crtc_enable = i9xx_crtc_enable;
+		dev_priv->display.crtc_disable = i9xx_crtc_disable;
 		dev_priv->display.off = i9xx_crtc_off;
 		dev_priv->display.update_plane = i9xx_update_plane;
 	}
@@ -7023,7 +7812,7 @@ static void intel_init_display(struct drm_device *dev)
 			dev_priv->display.write_eld = ironlake_write_eld;
 		} else if (IS_HASWELL(dev)) {
 			dev_priv->display.fdi_link_train = hsw_fdi_link_train;
-			dev_priv->display.write_eld = ironlake_write_eld;
+			dev_priv->display.write_eld = haswell_write_eld;
 		} else
 			dev_priv->display.update_wm = NULL;
 	} else if (IS_G4X(dev)) {
@@ -7101,21 +7890,16 @@ static struct intel_quirk intel_quirks[] = {
 	/* HP Mini needs pipe A force quirk (LP: #322104) */
 	{ 0x27ae, 0x103c, 0x361a, quirk_pipea_force },
 
-	/* Thinkpad R31 needs pipe A force quirk */
-	{ 0x3577, 0x1014, 0x0505, quirk_pipea_force },
 	/* Toshiba Protege R-205, S-209 needs pipe A force quirk */
 	{ 0x2592, 0x1179, 0x0001, quirk_pipea_force },
 
-	/* ThinkPad X30 needs pipe A force quirk (LP: #304614) */
-	{ 0x3577,  0x1014, 0x0513, quirk_pipea_force },
-	/* ThinkPad X40 needs pipe A force quirk */
-
 	/* ThinkPad T60 needs pipe A force quirk (bug #16494) */
 	{ 0x2782, 0x17aa, 0x201a, quirk_pipea_force },
 
 	/* 855 & before need to leave pipe A & dpll A up */
 	{ 0x3582, PCI_ANY_ID, PCI_ANY_ID, quirk_pipea_force },
 	{ 0x2562, PCI_ANY_ID, PCI_ANY_ID, quirk_pipea_force },
+	{ 0x3577, PCI_ANY_ID, PCI_ANY_ID, quirk_pipea_force },
 
 	/* Lenovo U160 cannot use SSC on LVDS */
 	{ 0x0046, 0x17aa, 0x3920, quirk_ssc_force_disable },
@@ -7231,10 +8015,251 @@ void intel_modeset_init(struct drm_device *dev)
 	/* Just disable it once at startup */
 	i915_disable_vga(dev);
 	intel_setup_outputs(dev);
+}
+
+static void
+intel_connector_break_all_links(struct intel_connector *connector)
+{
+	connector->base.dpms = DRM_MODE_DPMS_OFF;
+	connector->base.encoder = NULL;
+	connector->encoder->connectors_active = false;
+	connector->encoder->base.crtc = NULL;
+}
+
+static void intel_enable_pipe_a(struct drm_device *dev)
+{
+	struct intel_connector *connector;
+	struct drm_connector *crt = NULL;
+	struct intel_load_detect_pipe load_detect_temp;
+
+	/* We can't just switch on the pipe A, we need to set things up with a
+	 * proper mode and output configuration. As a gross hack, enable pipe A
+	 * by enabling the load detect pipe once. */
+	list_for_each_entry(connector,
+			    &dev->mode_config.connector_list,
+			    base.head) {
+		if (connector->encoder->type == INTEL_OUTPUT_ANALOG) {
+			crt = &connector->base;
+			break;
+		}
+	}
+
+	if (!crt)
+		return;
+
+	if (intel_get_load_detect_pipe(crt, NULL, &load_detect_temp))
+		intel_release_load_detect_pipe(crt, &load_detect_temp);
+
+
+}
+
+static void intel_sanitize_crtc(struct intel_crtc *crtc)
+{
+	struct drm_device *dev = crtc->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 reg, val;
+
+	/* Clear any frame start delays used for debugging left by the BIOS */
+	reg = PIPECONF(crtc->pipe);
+	I915_WRITE(reg, I915_READ(reg) & ~PIPECONF_FRAME_START_DELAY_MASK);
+
+	/* We need to sanitize the plane -> pipe mapping first because this will
+	 * disable the crtc (and hence change the state) if it is wrong. */
+	if (!HAS_PCH_SPLIT(dev)) {
+		struct intel_connector *connector;
+		bool plane;
+
+		reg = DSPCNTR(crtc->plane);
+		val = I915_READ(reg);
+
+		if ((val & DISPLAY_PLANE_ENABLE) == 0 &&
+		    (!!(val & DISPPLANE_SEL_PIPE_MASK) == crtc->pipe))
+			goto ok;
+
+		DRM_DEBUG_KMS("[CRTC:%d] wrong plane connection detected!\n",
+			      crtc->base.base.id);
+
+		/* Pipe has the wrong plane attached and the plane is active.
+		 * Temporarily change the plane mapping and disable everything
+		 * ...  */
+		plane = crtc->plane;
+		crtc->plane = !plane;
+		dev_priv->display.crtc_disable(&crtc->base);
+		crtc->plane = plane;
+
+		/* ... and break all links. */
+		list_for_each_entry(connector, &dev->mode_config.connector_list,
+				    base.head) {
+			if (connector->encoder->base.crtc != &crtc->base)
+				continue;
+
+			intel_connector_break_all_links(connector);
+		}
+
+		WARN_ON(crtc->active);
+		crtc->base.enabled = false;
+	}
+ok:
+
+	if (dev_priv->quirks & QUIRK_PIPEA_FORCE &&
+	    crtc->pipe == PIPE_A && !crtc->active) {
+		/* BIOS forgot to enable pipe A, this mostly happens after
+		 * resume. Force-enable the pipe to fix this, the update_dpms
+		 * call below we restore the pipe to the right state, but leave
+		 * the required bits on. */
+		intel_enable_pipe_a(dev);
+	}
+
+	/* Adjust the state of the output pipe according to whether we
+	 * have active connectors/encoders. */
+	intel_crtc_update_dpms(&crtc->base);
+
+	if (crtc->active != crtc->base.enabled) {
+		struct intel_encoder *encoder;
+
+		/* This can happen either due to bugs in the get_hw_state
+		 * functions or because the pipe is force-enabled due to the
+		 * pipe A quirk. */
+		DRM_DEBUG_KMS("[CRTC:%d] hw state adjusted, was %s, now %s\n",
+			      crtc->base.base.id,
+			      crtc->base.enabled ? "enabled" : "disabled",
+			      crtc->active ? "enabled" : "disabled");
+
+		crtc->base.enabled = crtc->active;
+
+		/* Because we only establish the connector -> encoder ->
+		 * crtc links if something is active, this means the
+		 * crtc is now deactivated. Break the links. connector
+		 * -> encoder links are only establish when things are
+		 *  actually up, hence no need to break them. */
+		WARN_ON(crtc->active);
+
+		for_each_encoder_on_crtc(dev, &crtc->base, encoder) {
+			WARN_ON(encoder->connectors_active);
+			encoder->base.crtc = NULL;
+		}
+	}
+}
+
+static void intel_sanitize_encoder(struct intel_encoder *encoder)
+{
+	struct intel_connector *connector;
+	struct drm_device *dev = encoder->base.dev;
+
+	/* We need to check both for a crtc link (meaning that the
+	 * encoder is active and trying to read from a pipe) and the
+	 * pipe itself being active. */
+	bool has_active_crtc = encoder->base.crtc &&
+		to_intel_crtc(encoder->base.crtc)->active;
+
+	if (encoder->connectors_active && !has_active_crtc) {
+		DRM_DEBUG_KMS("[ENCODER:%d:%s] has active connectors but no active pipe!\n",
+			      encoder->base.base.id,
+			      drm_get_encoder_name(&encoder->base));
 
-	INIT_WORK(&dev_priv->idle_work, intel_idle_update);
-	setup_timer(&dev_priv->idle_timer, intel_gpu_idle_timer,
-		    (unsigned long)dev);
+		/* Connector is active, but has no active pipe. This is
+		 * fallout from our resume register restoring. Disable
+		 * the encoder manually again. */
+		if (encoder->base.crtc) {
+			DRM_DEBUG_KMS("[ENCODER:%d:%s] manually disabled\n",
+				      encoder->base.base.id,
+				      drm_get_encoder_name(&encoder->base));
+			encoder->disable(encoder);
+		}
+
+		/* Inconsistent output/port/pipe state happens presumably due to
+		 * a bug in one of the get_hw_state functions. Or someplace else
+		 * in our code, like the register restore mess on resume. Clamp
+		 * things to off as a safer default. */
+		list_for_each_entry(connector,
+				    &dev->mode_config.connector_list,
+				    base.head) {
+			if (connector->encoder != encoder)
+				continue;
+
+			intel_connector_break_all_links(connector);
+		}
+	}
+	/* Enabled encoders without active connectors will be fixed in
+	 * the crtc fixup. */
+}
+
+/* Scan out the current hw modeset state, sanitizes it and maps it into the drm
+ * and i915 state tracking structures. */
+void intel_modeset_setup_hw_state(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	enum pipe pipe;
+	u32 tmp;
+	struct intel_crtc *crtc;
+	struct intel_encoder *encoder;
+	struct intel_connector *connector;
+
+	for_each_pipe(pipe) {
+		crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
+
+		tmp = I915_READ(PIPECONF(pipe));
+		if (tmp & PIPECONF_ENABLE)
+			crtc->active = true;
+		else
+			crtc->active = false;
+
+		crtc->base.enabled = crtc->active;
+
+		DRM_DEBUG_KMS("[CRTC:%d] hw state readout: %s\n",
+			      crtc->base.base.id,
+			      crtc->active ? "enabled" : "disabled");
+	}
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list,
+			    base.head) {
+		pipe = 0;
+
+		if (encoder->get_hw_state(encoder, &pipe)) {
+			encoder->base.crtc =
+				dev_priv->pipe_to_crtc_mapping[pipe];
+		} else {
+			encoder->base.crtc = NULL;
+		}
+
+		encoder->connectors_active = false;
+		DRM_DEBUG_KMS("[ENCODER:%d:%s] hw state readout: %s, pipe=%i\n",
+			      encoder->base.base.id,
+			      drm_get_encoder_name(&encoder->base),
+			      encoder->base.crtc ? "enabled" : "disabled",
+			      pipe);
+	}
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list,
+			    base.head) {
+		if (connector->get_hw_state(connector)) {
+			connector->base.dpms = DRM_MODE_DPMS_ON;
+			connector->encoder->connectors_active = true;
+			connector->base.encoder = &connector->encoder->base;
+		} else {
+			connector->base.dpms = DRM_MODE_DPMS_OFF;
+			connector->base.encoder = NULL;
+		}
+		DRM_DEBUG_KMS("[CONNECTOR:%d:%s] hw state readout: %s\n",
+			      connector->base.base.id,
+			      drm_get_connector_name(&connector->base),
+			      connector->base.encoder ? "enabled" : "disabled");
+	}
+
+	/* HW state is read out, now we need to sanitize this mess. */
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list,
+			    base.head) {
+		intel_sanitize_encoder(encoder);
+	}
+
+	for_each_pipe(pipe) {
+		crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
+		intel_sanitize_crtc(crtc);
+	}
+
+	intel_modeset_update_staged_output_state(dev);
+
+	intel_modeset_check_state(dev);
 }
 
 void intel_modeset_gem_init(struct drm_device *dev)
@@ -7242,6 +8267,8 @@ void intel_modeset_gem_init(struct drm_device *dev)
 	intel_modeset_init_hw(dev);
 
 	intel_setup_overlay(dev);
+
+	intel_modeset_setup_hw_state(dev);
 }
 
 void intel_modeset_cleanup(struct drm_device *dev)
@@ -7280,19 +8307,11 @@ void intel_modeset_cleanup(struct drm_device *dev)
 	 * enqueue unpin/hotplug work. */
 	drm_irq_uninstall(dev);
 	cancel_work_sync(&dev_priv->hotplug_work);
-	cancel_work_sync(&dev_priv->rps_work);
+	cancel_work_sync(&dev_priv->rps.work);
 
 	/* flush any delayed tasks or pending work */
 	flush_scheduled_work();
 
-	/* Shut off idle work before the crtcs get freed. */
-	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-		intel_crtc = to_intel_crtc(crtc);
-		del_timer_sync(&intel_crtc->idle_timer);
-	}
-	del_timer_sync(&dev_priv->idle_timer);
-	cancel_work_sync(&dev_priv->idle_work);
-
 	drm_mode_config_cleanup(dev);
 }
 
@@ -7338,7 +8357,7 @@ struct intel_display_error_state {
 		u32 position;
 		u32 base;
 		u32 size;
-	} cursor[2];
+	} cursor[I915_MAX_PIPES];
 
 	struct intel_pipe_error_state {
 		u32 conf;
@@ -7350,7 +8369,7 @@ struct intel_display_error_state {
 		u32 vtotal;
 		u32 vblank;
 		u32 vsync;
-	} pipe[2];
+	} pipe[I915_MAX_PIPES];
 
 	struct intel_plane_error_state {
 		u32 control;
@@ -7360,7 +8379,7 @@ struct intel_display_error_state {
 		u32 addr;
 		u32 surface;
 		u32 tile_offset;
-	} plane[2];
+	} plane[I915_MAX_PIPES];
 };
 
 struct intel_display_error_state *
@@ -7374,7 +8393,7 @@ intel_display_capture_error_state(struct drm_device *dev)
 	if (error == NULL)
 		return NULL;
 
-	for (i = 0; i < 2; i++) {
+	for_each_pipe(i) {
 		error->cursor[i].control = I915_READ(CURCNTR(i));
 		error->cursor[i].position = I915_READ(CURPOS(i));
 		error->cursor[i].base = I915_READ(CURBASE(i));
@@ -7407,9 +8426,11 @@ intel_display_print_error_state(struct seq_file *m,
 				struct drm_device *dev,
 				struct intel_display_error_state *error)
 {
+	drm_i915_private_t *dev_priv = dev->dev_private;
 	int i;
 
-	for (i = 0; i < 2; i++) {
+	seq_printf(m, "Num Pipes: %d\n", dev_priv->num_pipe);
+	for_each_pipe(i) {
 		seq_printf(m, "Pipe [%d]:\n", i);
 		seq_printf(m, "  CONF: %08x\n", error->pipe[i].conf);
 		seq_printf(m, "  SRC: %08x\n", error->pipe[i].source);
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index ace757a..1f8b25b 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -36,42 +36,10 @@
 #include "intel_drv.h"
 #include "i915_drm.h"
 #include "i915_drv.h"
-#include "drm_dp_helper.h"
 
-#define DP_RECEIVER_CAP_SIZE	0xf
 #define DP_LINK_STATUS_SIZE	6
 #define DP_LINK_CHECK_TIMEOUT	(10 * 1000)
 
-#define DP_LINK_CONFIGURATION_SIZE	9
-
-struct intel_dp {
-	struct intel_encoder base;
-	uint32_t output_reg;
-	uint32_t DP;
-	uint8_t  link_configuration[DP_LINK_CONFIGURATION_SIZE];
-	bool has_audio;
-	enum hdmi_force_audio force_audio;
-	uint32_t color_range;
-	int dpms_mode;
-	uint8_t link_bw;
-	uint8_t lane_count;
-	uint8_t dpcd[DP_RECEIVER_CAP_SIZE];
-	struct i2c_adapter adapter;
-	struct i2c_algo_dp_aux_data algo;
-	bool is_pch_edp;
-	uint8_t	train_set[4];
-	int panel_power_up_delay;
-	int panel_power_down_delay;
-	int panel_power_cycle_delay;
-	int backlight_on_delay;
-	int backlight_off_delay;
-	struct drm_display_mode *panel_fixed_mode;  /* for eDP */
-	struct delayed_work panel_vdd_work;
-	bool want_panel_vdd;
-	struct edid *edid; /* cached EDID for eDP */
-	int edid_mode_count;
-};
-
 /**
  * is_edp - is the given port attached to an eDP panel (either CPU or PCH)
  * @intel_dp: DP struct
@@ -882,10 +850,8 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
 	 * supposed to be read-only.
 	 */
 	intel_dp->DP = I915_READ(intel_dp->output_reg) & DP_DETECTED;
-	intel_dp->DP |=  DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0;
 
 	/* Handle DP bits in common between all three register formats */
-
 	intel_dp->DP |= DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0;
 
 	switch (intel_dp->lane_count) {
@@ -1282,10 +1248,57 @@ static void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode)
 	}
 }
 
-static void intel_dp_prepare(struct drm_encoder *encoder)
+static bool intel_dp_get_hw_state(struct intel_encoder *encoder,
+				  enum pipe *pipe)
 {
-	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
+	struct drm_device *dev = encoder->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 tmp = I915_READ(intel_dp->output_reg);
+
+	if (!(tmp & DP_PORT_EN))
+		return false;
 
+	if (is_cpu_edp(intel_dp) && IS_GEN7(dev)) {
+		*pipe = PORT_TO_PIPE_CPT(tmp);
+	} else if (!HAS_PCH_CPT(dev) || is_cpu_edp(intel_dp)) {
+		*pipe = PORT_TO_PIPE(tmp);
+	} else {
+		u32 trans_sel;
+		u32 trans_dp;
+		int i;
+
+		switch (intel_dp->output_reg) {
+		case PCH_DP_B:
+			trans_sel = TRANS_DP_PORT_SEL_B;
+			break;
+		case PCH_DP_C:
+			trans_sel = TRANS_DP_PORT_SEL_C;
+			break;
+		case PCH_DP_D:
+			trans_sel = TRANS_DP_PORT_SEL_D;
+			break;
+		default:
+			return true;
+		}
+
+		for_each_pipe(i) {
+			trans_dp = I915_READ(TRANS_DP_CTL(i));
+			if ((trans_dp & TRANS_DP_PORT_SEL_MASK) == trans_sel) {
+				*pipe = i;
+				return true;
+			}
+		}
+	}
+
+	DRM_DEBUG_KMS("No pipe for dp port 0x%x found\n", intel_dp->output_reg);
+
+	return true;
+}
+
+static void intel_disable_dp(struct intel_encoder *encoder)
+{
+	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
 
 	/* Make sure the panel is off before trying to change the mode. But also
 	 * ensure that we have vdd while we switch off the panel. */
@@ -1296,60 +1309,58 @@ static void intel_dp_prepare(struct drm_encoder *encoder)
 	intel_dp_link_down(intel_dp);
 }
 
-static void intel_dp_commit(struct drm_encoder *encoder)
+static void intel_enable_dp(struct intel_encoder *encoder)
 {
-	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
-	struct drm_device *dev = encoder->dev;
-	struct intel_crtc *intel_crtc = to_intel_crtc(intel_dp->base.base.crtc);
+	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
+	struct drm_device *dev = encoder->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	uint32_t dp_reg = I915_READ(intel_dp->output_reg);
 
 	ironlake_edp_panel_vdd_on(intel_dp);
 	intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
-	intel_dp_start_link_train(intel_dp);
-	ironlake_edp_panel_on(intel_dp);
-	ironlake_edp_panel_vdd_off(intel_dp, true);
-	intel_dp_complete_link_train(intel_dp);
+	if (!(dp_reg & DP_PORT_EN)) {
+		intel_dp_start_link_train(intel_dp);
+		ironlake_edp_panel_on(intel_dp);
+		ironlake_edp_panel_vdd_off(intel_dp, true);
+		intel_dp_complete_link_train(intel_dp);
+	} else
+		ironlake_edp_panel_vdd_off(intel_dp, false);
 	ironlake_edp_backlight_on(intel_dp);
-
-	intel_dp->dpms_mode = DRM_MODE_DPMS_ON;
-
-	if (HAS_PCH_CPT(dev))
-		intel_cpt_verify_modeset(dev, intel_crtc->pipe);
 }
 
 static void
-intel_dp_dpms(struct drm_encoder *encoder, int mode)
+intel_dp_dpms(struct drm_connector *connector, int mode)
 {
-	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
-	struct drm_device *dev = encoder->dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	uint32_t dp_reg = I915_READ(intel_dp->output_reg);
+	struct intel_dp *intel_dp = intel_attached_dp(connector);
+
+	/* DP supports only 2 dpms states. */
+	if (mode != DRM_MODE_DPMS_ON)
+		mode = DRM_MODE_DPMS_OFF;
+
+	if (mode == connector->dpms)
+		return;
+
+	connector->dpms = mode;
+
+	/* Only need to change hw state when actually enabled */
+	if (!intel_dp->base.base.crtc) {
+		intel_dp->base.connectors_active = false;
+		return;
+	}
 
 	if (mode != DRM_MODE_DPMS_ON) {
-		/* Switching the panel off requires vdd. */
-		ironlake_edp_panel_vdd_on(intel_dp);
-		ironlake_edp_backlight_off(intel_dp);
-		intel_dp_sink_dpms(intel_dp, mode);
-		ironlake_edp_panel_off(intel_dp);
-		intel_dp_link_down(intel_dp);
+		intel_encoder_dpms(&intel_dp->base, mode);
 
 		if (is_cpu_edp(intel_dp))
-			ironlake_edp_pll_off(encoder);
+			ironlake_edp_pll_off(&intel_dp->base.base);
 	} else {
 		if (is_cpu_edp(intel_dp))
-			ironlake_edp_pll_on(encoder);
+			ironlake_edp_pll_on(&intel_dp->base.base);
 
-		ironlake_edp_panel_vdd_on(intel_dp);
-		intel_dp_sink_dpms(intel_dp, mode);
-		if (!(dp_reg & DP_PORT_EN)) {
-			intel_dp_start_link_train(intel_dp);
-			ironlake_edp_panel_on(intel_dp);
-			ironlake_edp_panel_vdd_off(intel_dp, true);
-			intel_dp_complete_link_train(intel_dp);
-		} else
-			ironlake_edp_panel_vdd_off(intel_dp, false);
-		ironlake_edp_backlight_on(intel_dp);
+		intel_encoder_dpms(&intel_dp->base, mode);
 	}
-	intel_dp->dpms_mode = mode;
+
+	intel_modeset_check_state(connector->dev);
 }
 
 /*
@@ -1668,6 +1679,45 @@ intel_dp_set_link_train(struct intel_dp *intel_dp,
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int ret;
 
+	if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || !is_cpu_edp(intel_dp))) {
+		dp_reg_value &= ~DP_LINK_TRAIN_MASK_CPT;
+
+		switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) {
+		case DP_TRAINING_PATTERN_DISABLE:
+			dp_reg_value |= DP_LINK_TRAIN_OFF_CPT;
+			break;
+		case DP_TRAINING_PATTERN_1:
+			dp_reg_value |= DP_LINK_TRAIN_PAT_1_CPT;
+			break;
+		case DP_TRAINING_PATTERN_2:
+			dp_reg_value |= DP_LINK_TRAIN_PAT_2_CPT;
+			break;
+		case DP_TRAINING_PATTERN_3:
+			DRM_ERROR("DP training pattern 3 not supported\n");
+			dp_reg_value |= DP_LINK_TRAIN_PAT_2_CPT;
+			break;
+		}
+
+	} else {
+		dp_reg_value &= ~DP_LINK_TRAIN_MASK;
+
+		switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) {
+		case DP_TRAINING_PATTERN_DISABLE:
+			dp_reg_value |= DP_LINK_TRAIN_OFF;
+			break;
+		case DP_TRAINING_PATTERN_1:
+			dp_reg_value |= DP_LINK_TRAIN_PAT_1;
+			break;
+		case DP_TRAINING_PATTERN_2:
+			dp_reg_value |= DP_LINK_TRAIN_PAT_2;
+			break;
+		case DP_TRAINING_PATTERN_3:
+			DRM_ERROR("DP training pattern 3 not supported\n");
+			dp_reg_value |= DP_LINK_TRAIN_PAT_2;
+			break;
+		}
+	}
+
 	I915_WRITE(intel_dp->output_reg, dp_reg_value);
 	POSTING_READ(intel_dp->output_reg);
 
@@ -1675,12 +1725,15 @@ intel_dp_set_link_train(struct intel_dp *intel_dp,
 				    DP_TRAINING_PATTERN_SET,
 				    dp_train_pat);
 
-	ret = intel_dp_aux_native_write(intel_dp,
-					DP_TRAINING_LANE0_SET,
-					intel_dp->train_set,
-					intel_dp->lane_count);
-	if (ret != intel_dp->lane_count)
-		return false;
+	if ((dp_train_pat & DP_TRAINING_PATTERN_MASK) !=
+	    DP_TRAINING_PATTERN_DISABLE) {
+		ret = intel_dp_aux_native_write(intel_dp,
+						DP_TRAINING_LANE0_SET,
+						intel_dp->train_set,
+						intel_dp->lane_count);
+		if (ret != intel_dp->lane_count)
+			return false;
+	}
 
 	return true;
 }
@@ -1696,7 +1749,6 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)
 	uint8_t voltage;
 	bool clock_recovery = false;
 	int voltage_tries, loop_tries;
-	u32 reg;
 	uint32_t DP = intel_dp->DP;
 
 	/*
@@ -1717,10 +1769,6 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)
 
 	DP |= DP_PORT_EN;
 
-	if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || !is_cpu_edp(intel_dp)))
-		DP &= ~DP_LINK_TRAIN_MASK_CPT;
-	else
-		DP &= ~DP_LINK_TRAIN_MASK;
 	memset(intel_dp->train_set, 0, 4);
 	voltage = 0xff;
 	voltage_tries = 0;
@@ -1744,12 +1792,7 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)
 			DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels;
 		}
 
-		if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || !is_cpu_edp(intel_dp)))
-			reg = DP | DP_LINK_TRAIN_PAT_1_CPT;
-		else
-			reg = DP | DP_LINK_TRAIN_PAT_1;
-
-		if (!intel_dp_set_link_train(intel_dp, reg,
+		if (!intel_dp_set_link_train(intel_dp, DP,
 					     DP_TRAINING_PATTERN_1 |
 					     DP_LINK_SCRAMBLING_DISABLE))
 			break;
@@ -1804,10 +1847,8 @@ static void
 intel_dp_complete_link_train(struct intel_dp *intel_dp)
 {
 	struct drm_device *dev = intel_dp->base.base.dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
 	bool channel_eq = false;
 	int tries, cr_tries;
-	u32 reg;
 	uint32_t DP = intel_dp->DP;
 
 	/* channel equalization */
@@ -1836,13 +1877,8 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)
 			DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels;
 		}
 
-		if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || !is_cpu_edp(intel_dp)))
-			reg = DP | DP_LINK_TRAIN_PAT_2_CPT;
-		else
-			reg = DP | DP_LINK_TRAIN_PAT_2;
-
 		/* channel eq pattern */
-		if (!intel_dp_set_link_train(intel_dp, reg,
+		if (!intel_dp_set_link_train(intel_dp, DP,
 					     DP_TRAINING_PATTERN_2 |
 					     DP_LINK_SCRAMBLING_DISABLE))
 			break;
@@ -1877,15 +1913,7 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)
 		++tries;
 	}
 
-	if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || !is_cpu_edp(intel_dp)))
-		reg = DP | DP_LINK_TRAIN_OFF_CPT;
-	else
-		reg = DP | DP_LINK_TRAIN_OFF;
-
-	I915_WRITE(intel_dp->output_reg, reg);
-	POSTING_READ(intel_dp->output_reg);
-	intel_dp_aux_native_write_1(intel_dp,
-				    DP_TRAINING_PATTERN_SET, DP_TRAINING_PATTERN_DISABLE);
+	intel_dp_set_link_train(intel_dp, DP, DP_TRAINING_PATTERN_DISABLE);
 }
 
 static void
@@ -2033,10 +2061,10 @@ intel_dp_check_link_status(struct intel_dp *intel_dp)
 	u8 sink_irq_vector;
 	u8 link_status[DP_LINK_STATUS_SIZE];
 
-	if (intel_dp->dpms_mode != DRM_MODE_DPMS_ON)
+	if (!intel_dp->base.connectors_active)
 		return;
 
-	if (!intel_dp->base.base.crtc)
+	if (WARN_ON(!intel_dp->base.base.crtc))
 		return;
 
 	/* Try to read receiver status if the link appears to be up */
@@ -2160,7 +2188,6 @@ intel_dp_get_edid_modes(struct drm_connector *connector, struct i2c_adapter *ada
 		ret = drm_add_edid_modes(connector, intel_dp->edid);
 		drm_edid_to_eld(connector,
 				intel_dp->edid);
-		connector->display_info.raw_edid = NULL;
 		return intel_dp->edid_mode_count;
 	}
 
@@ -2206,7 +2233,6 @@ intel_dp_detect(struct drm_connector *connector, bool force)
 		edid = intel_dp_get_edid(connector, &intel_dp->adapter);
 		if (edid) {
 			intel_dp->has_audio = drm_detect_monitor_audio(edid);
-			connector->display_info.raw_edid = NULL;
 			kfree(edid);
 		}
 	}
@@ -2271,8 +2297,6 @@ intel_dp_detect_audio(struct drm_connector *connector)
 	edid = intel_dp_get_edid(connector, &intel_dp->adapter);
 	if (edid) {
 		has_audio = drm_detect_monitor_audio(edid);
-
-		connector->display_info.raw_edid = NULL;
 		kfree(edid);
 	}
 
@@ -2326,9 +2350,8 @@ intel_dp_set_property(struct drm_connector *connector,
 done:
 	if (intel_dp->base.base.crtc) {
 		struct drm_crtc *crtc = intel_dp->base.base.crtc;
-		drm_crtc_helper_set_mode(crtc, &crtc->mode,
-					 crtc->x, crtc->y,
-					 crtc->fb);
+		intel_set_mode(crtc, &crtc->mode,
+			       crtc->x, crtc->y, crtc->fb);
 	}
 
 	return 0;
@@ -2362,15 +2385,13 @@ static void intel_dp_encoder_destroy(struct drm_encoder *encoder)
 }
 
 static const struct drm_encoder_helper_funcs intel_dp_helper_funcs = {
-	.dpms = intel_dp_dpms,
 	.mode_fixup = intel_dp_mode_fixup,
-	.prepare = intel_dp_prepare,
 	.mode_set = intel_dp_mode_set,
-	.commit = intel_dp_commit,
+	.disable = intel_encoder_noop,
 };
 
 static const struct drm_connector_funcs intel_dp_connector_funcs = {
-	.dpms = drm_helper_connector_dpms,
+	.dpms = intel_dp_dpms,
 	.detect = intel_dp_detect,
 	.fill_modes = drm_helper_probe_single_connector_modes,
 	.set_property = intel_dp_set_property,
@@ -2441,7 +2462,7 @@ intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connect
 }
 
 void
-intel_dp_init(struct drm_device *dev, int output_reg)
+intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_connector *connector;
@@ -2456,7 +2477,7 @@ intel_dp_init(struct drm_device *dev, int output_reg)
 		return;
 
 	intel_dp->output_reg = output_reg;
-	intel_dp->dpms_mode = -1;
+	intel_dp->port = port;
 
 	intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL);
 	if (!intel_connector) {
@@ -2483,18 +2504,10 @@ intel_dp_init(struct drm_device *dev, int output_reg)
 
 	connector->polled = DRM_CONNECTOR_POLL_HPD;
 
-	if (output_reg == DP_B || output_reg == PCH_DP_B)
-		intel_encoder->clone_mask = (1 << INTEL_DP_B_CLONE_BIT);
-	else if (output_reg == DP_C || output_reg == PCH_DP_C)
-		intel_encoder->clone_mask = (1 << INTEL_DP_C_CLONE_BIT);
-	else if (output_reg == DP_D || output_reg == PCH_DP_D)
-		intel_encoder->clone_mask = (1 << INTEL_DP_D_CLONE_BIT);
+	intel_encoder->cloneable = false;
 
-	if (is_edp(intel_dp)) {
-		intel_encoder->clone_mask = (1 << INTEL_EDP_CLONE_BIT);
-		INIT_DELAYED_WORK(&intel_dp->panel_vdd_work,
-				  ironlake_panel_vdd_work);
-	}
+	INIT_DELAYED_WORK(&intel_dp->panel_vdd_work,
+			  ironlake_panel_vdd_work);
 
 	intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
 
@@ -2508,29 +2521,31 @@ intel_dp_init(struct drm_device *dev, int output_reg)
 	intel_connector_attach_encoder(intel_connector, intel_encoder);
 	drm_sysfs_connector_add(connector);
 
+	intel_encoder->enable = intel_enable_dp;
+	intel_encoder->disable = intel_disable_dp;
+	intel_encoder->get_hw_state = intel_dp_get_hw_state;
+	intel_connector->get_hw_state = intel_connector_get_hw_state;
+
 	/* Set up the DDC bus. */
-	switch (output_reg) {
-		case DP_A:
-			name = "DPDDC-A";
-			break;
-		case DP_B:
-		case PCH_DP_B:
-			dev_priv->hotplug_supported_mask |=
-				DPB_HOTPLUG_INT_STATUS;
-			name = "DPDDC-B";
-			break;
-		case DP_C:
-		case PCH_DP_C:
-			dev_priv->hotplug_supported_mask |=
-				DPC_HOTPLUG_INT_STATUS;
-			name = "DPDDC-C";
-			break;
-		case DP_D:
-		case PCH_DP_D:
-			dev_priv->hotplug_supported_mask |=
-				DPD_HOTPLUG_INT_STATUS;
-			name = "DPDDC-D";
-			break;
+	switch (port) {
+	case PORT_A:
+		name = "DPDDC-A";
+		break;
+	case PORT_B:
+		dev_priv->hotplug_supported_mask |= DPB_HOTPLUG_INT_STATUS;
+		name = "DPDDC-B";
+		break;
+	case PORT_C:
+		dev_priv->hotplug_supported_mask |= DPC_HOTPLUG_INT_STATUS;
+		name = "DPDDC-C";
+		break;
+	case PORT_D:
+		dev_priv->hotplug_supported_mask |= DPD_HOTPLUG_INT_STATUS;
+		name = "DPDDC-D";
+		break;
+	default:
+		WARN(1, "Invalid port %c\n", port_name(port));
+		break;
 	}
 
 	/* Cache some DPCD data in the eDP case */
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index cd54cf8..4f2b2d6 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -31,6 +31,7 @@
 #include "drm_crtc.h"
 #include "drm_crtc_helper.h"
 #include "drm_fb_helper.h"
+#include "drm_dp_helper.h"
 
 #define _wait_for(COND, MS, W) ({ \
 	unsigned long timeout__ = jiffies + msecs_to_jiffies(MS);	\
@@ -40,7 +41,11 @@
 			ret__ = -ETIMEDOUT;				\
 			break;						\
 		}							\
-		if (W && drm_can_sleep()) msleep(W);	\
+		if (W && drm_can_sleep())  {				\
+			msleep(W);					\
+		} else {						\
+			cpu_relax();					\
+		}							\
 	}								\
 	ret__;								\
 })
@@ -90,25 +95,6 @@
 #define INTEL_OUTPUT_DISPLAYPORT 7
 #define INTEL_OUTPUT_EDP 8
 
-/* Intel Pipe Clone Bit */
-#define INTEL_HDMIB_CLONE_BIT 1
-#define INTEL_HDMIC_CLONE_BIT 2
-#define INTEL_HDMID_CLONE_BIT 3
-#define INTEL_HDMIE_CLONE_BIT 4
-#define INTEL_HDMIF_CLONE_BIT 5
-#define INTEL_SDVO_NON_TV_CLONE_BIT 6
-#define INTEL_SDVO_TV_CLONE_BIT 7
-#define INTEL_SDVO_LVDS_CLONE_BIT 8
-#define INTEL_ANALOG_CLONE_BIT 9
-#define INTEL_TV_CLONE_BIT 10
-#define INTEL_DP_B_CLONE_BIT 11
-#define INTEL_DP_C_CLONE_BIT 12
-#define INTEL_DP_D_CLONE_BIT 13
-#define INTEL_LVDS_CLONE_BIT 14
-#define INTEL_DVO_TMDS_CLONE_BIT 15
-#define INTEL_DVO_LVDS_CLONE_BIT 16
-#define INTEL_EDP_CLONE_BIT 17
-
 #define INTEL_DVO_CHIP_NONE 0
 #define INTEL_DVO_CHIP_LVDS 1
 #define INTEL_DVO_CHIP_TMDS 2
@@ -151,16 +137,46 @@ struct intel_fbdev {
 
 struct intel_encoder {
 	struct drm_encoder base;
+	/*
+	 * The new crtc this encoder will be driven from. Only differs from
+	 * base->crtc while a modeset is in progress.
+	 */
+	struct intel_crtc *new_crtc;
+
 	int type;
 	bool needs_tv_clock;
+	/*
+	 * Intel hw has only one MUX where encoders could be clone, hence a
+	 * simple flag is enough to compute the possible_clones mask.
+	 */
+	bool cloneable;
+	bool connectors_active;
 	void (*hot_plug)(struct intel_encoder *);
+	void (*enable)(struct intel_encoder *);
+	void (*disable)(struct intel_encoder *);
+	/* Read out the current hw state of this connector, returning true if
+	 * the encoder is active. If the encoder is enabled it also set the pipe
+	 * it is connected to in the pipe parameter. */
+	bool (*get_hw_state)(struct intel_encoder *, enum pipe *pipe);
 	int crtc_mask;
-	int clone_mask;
 };
 
 struct intel_connector {
 	struct drm_connector base;
+	/*
+	 * The fixed encoder this connector is connected to.
+	 */
 	struct intel_encoder *encoder;
+
+	/*
+	 * The new encoder this connector will be driven. Only differs from
+	 * encoder while a modeset is in progress.
+	 */
+	struct intel_encoder *new_encoder;
+
+	/* Reads out the current hw, returning true if the connector is enabled
+	 * and active (i.e. dpms ON state). */
+	bool (*get_hw_state)(struct intel_connector *);
 };
 
 struct intel_crtc {
@@ -168,11 +184,13 @@ struct intel_crtc {
 	enum pipe pipe;
 	enum plane plane;
 	u8 lut_r[256], lut_g[256], lut_b[256];
-	int dpms_mode;
-	bool active; /* is the crtc on? independent of the dpms mode */
+	/*
+	 * Whether the crtc and the connected output pipeline is active. Implies
+	 * that crtc->enabled is set, i.e. the current mode configuration has
+	 * some outputs connected to this crtc.
+	 */
+	bool active;
 	bool primary_disabled; /* is the crtc obscured by a plane? */
-	bool busy; /* is scanout buffer being updated frequently? */
-	struct timer_list idle_timer;
 	bool lowfreq_avail;
 	struct intel_overlay *overlay;
 	struct intel_unpin_work *unpin_work;
@@ -311,6 +329,37 @@ struct intel_hdmi {
 			       struct drm_display_mode *adjusted_mode);
 };
 
+#define DP_RECEIVER_CAP_SIZE		0xf
+#define DP_LINK_CONFIGURATION_SIZE	9
+
+struct intel_dp {
+	struct intel_encoder base;
+	uint32_t output_reg;
+	uint32_t DP;
+	uint8_t  link_configuration[DP_LINK_CONFIGURATION_SIZE];
+	bool has_audio;
+	enum hdmi_force_audio force_audio;
+	enum port port;
+	uint32_t color_range;
+	uint8_t link_bw;
+	uint8_t lane_count;
+	uint8_t dpcd[DP_RECEIVER_CAP_SIZE];
+	struct i2c_adapter adapter;
+	struct i2c_algo_dp_aux_data algo;
+	bool is_pch_edp;
+	uint8_t train_set[4];
+	int panel_power_up_delay;
+	int panel_power_down_delay;
+	int panel_power_cycle_delay;
+	int backlight_on_delay;
+	int backlight_off_delay;
+	struct drm_display_mode *panel_fixed_mode;  /* for eDP */
+	struct delayed_work panel_vdd_work;
+	bool want_panel_vdd;
+	struct edid *edid; /* cached EDID for eDP */
+	int edid_mode_count;
+};
+
 static inline struct drm_crtc *
 intel_get_crtc_for_pipe(struct drm_device *dev, int pipe)
 {
@@ -350,17 +399,21 @@ extern void intel_attach_force_audio_property(struct drm_connector *connector);
 extern void intel_attach_broadcast_rgb_property(struct drm_connector *connector);
 
 extern void intel_crt_init(struct drm_device *dev);
-extern void intel_hdmi_init(struct drm_device *dev, int sdvox_reg);
+extern void intel_hdmi_init(struct drm_device *dev,
+			    int sdvox_reg, enum port port);
 extern struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder);
 extern void intel_dip_infoframe_csum(struct dip_infoframe *avi_if);
 extern bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg,
 			    bool is_sdvob);
 extern void intel_dvo_init(struct drm_device *dev);
 extern void intel_tv_init(struct drm_device *dev);
-extern void intel_mark_busy(struct drm_device *dev,
-			    struct drm_i915_gem_object *obj);
+extern void intel_mark_busy(struct drm_device *dev);
+extern void intel_mark_idle(struct drm_device *dev);
+extern void intel_mark_fb_busy(struct drm_i915_gem_object *obj);
+extern void intel_mark_fb_idle(struct drm_i915_gem_object *obj);
 extern bool intel_lvds_init(struct drm_device *dev);
-extern void intel_dp_init(struct drm_device *dev, int dp_reg);
+extern void intel_dp_init(struct drm_device *dev, int output_reg,
+			  enum port port);
 void
 intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
 		 struct drm_display_mode *adjusted_mode);
@@ -373,8 +426,6 @@ extern int intel_plane_init(struct drm_device *dev, enum pipe pipe);
 extern void intel_flush_display_plane(struct drm_i915_private *dev_priv,
 				      enum plane plane);
 
-void intel_sanitize_pm(struct drm_device *dev);
-
 /* intel_panel.c */
 extern void intel_fixed_panel_mode(struct drm_display_mode *fixed_mode,
 				   struct drm_display_mode *adjusted_mode);
@@ -391,10 +442,27 @@ extern void intel_panel_disable_backlight(struct drm_device *dev);
 extern void intel_panel_destroy_backlight(struct drm_device *dev);
 extern enum drm_connector_status intel_panel_detect(struct drm_device *dev);
 
+struct intel_set_config {
+	struct drm_encoder **save_connector_encoders;
+	struct drm_crtc **save_encoder_crtcs;
+
+	bool fb_changed;
+	bool mode_changed;
+};
+
+extern bool intel_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode,
+			   int x, int y, struct drm_framebuffer *old_fb);
+extern void intel_modeset_disable(struct drm_device *dev);
 extern void intel_crtc_load_lut(struct drm_crtc *crtc);
-extern void intel_encoder_prepare(struct drm_encoder *encoder);
-extern void intel_encoder_commit(struct drm_encoder *encoder);
+extern void intel_crtc_update_dpms(struct drm_crtc *crtc);
+extern void intel_encoder_noop(struct drm_encoder *encoder);
 extern void intel_encoder_destroy(struct drm_encoder *encoder);
+extern void intel_encoder_dpms(struct intel_encoder *encoder, int mode);
+extern bool intel_encoder_check_is_cloned(struct intel_encoder *encoder);
+extern void intel_connector_dpms(struct drm_connector *, int mode);
+extern bool intel_connector_get_hw_state(struct intel_connector *connector);
+extern void intel_modeset_check_state(struct drm_device *dev);
+
 
 static inline struct intel_encoder *intel_attached_encoder(struct drm_connector *connector)
 {
@@ -417,12 +485,10 @@ struct intel_load_detect_pipe {
 	bool load_detect_temp;
 	int dpms_mode;
 };
-extern bool intel_get_load_detect_pipe(struct intel_encoder *intel_encoder,
-				       struct drm_connector *connector,
+extern bool intel_get_load_detect_pipe(struct drm_connector *connector,
 				       struct drm_display_mode *mode,
 				       struct intel_load_detect_pipe *old);
-extern void intel_release_load_detect_pipe(struct intel_encoder *intel_encoder,
-					   struct drm_connector *connector,
+extern void intel_release_load_detect_pipe(struct drm_connector *connector,
 					   struct intel_load_detect_pipe *old);
 
 extern void intelfb_restore(void);
@@ -503,7 +569,10 @@ extern void intel_disable_gt_powersave(struct drm_device *dev);
 extern void gen6_gt_check_fifodbg(struct drm_i915_private *dev_priv);
 extern void ironlake_teardown_rc6(struct drm_device *dev);
 
-extern void intel_ddi_dpms(struct drm_encoder *encoder, int mode);
+extern void intel_enable_ddi(struct intel_encoder *encoder);
+extern void intel_disable_ddi(struct intel_encoder *encoder);
+extern bool intel_ddi_get_hw_state(struct intel_encoder *encoder,
+				   enum pipe *pipe);
 extern void intel_ddi_mode_set(struct drm_encoder *encoder,
 				struct drm_display_mode *mode,
 				struct drm_display_mode *adjusted_mode);
diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c
index 36c542e..4f1fdcc 100644
--- a/drivers/gpu/drm/i915/intel_dvo.c
+++ b/drivers/gpu/drm/i915/intel_dvo.c
@@ -37,6 +37,7 @@
 #define SIL164_ADDR	0x38
 #define CH7xxx_ADDR	0x76
 #define TFP410_ADDR	0x38
+#define NS2501_ADDR     0x38
 
 static const struct intel_dvo_device intel_dvo_devices[] = {
 	{
@@ -74,7 +75,14 @@ static const struct intel_dvo_device intel_dvo_devices[] = {
 		.slave_addr = 0x75,
 		.gpio = GMBUS_PORT_DPB,
 		.dev_ops = &ch7017_ops,
-	}
+	},
+	{
+	        .type = INTEL_DVO_CHIP_TMDS,
+		.name = "ns2501",
+		.dvo_reg = DVOC,
+		.slave_addr = NS2501_ADDR,
+		.dev_ops = &ns2501_ops,
+       }
 };
 
 struct intel_dvo {
@@ -97,22 +105,91 @@ static struct intel_dvo *intel_attached_dvo(struct drm_connector *connector)
 			    struct intel_dvo, base);
 }
 
-static void intel_dvo_dpms(struct drm_encoder *encoder, int mode)
+static bool intel_dvo_connector_get_hw_state(struct intel_connector *connector)
 {
-	struct drm_i915_private *dev_priv = encoder->dev->dev_private;
-	struct intel_dvo *intel_dvo = enc_to_intel_dvo(encoder);
+	struct intel_dvo *intel_dvo = intel_attached_dvo(&connector->base);
+
+	return intel_dvo->dev.dev_ops->get_hw_state(&intel_dvo->dev);
+}
+
+static bool intel_dvo_get_hw_state(struct intel_encoder *encoder,
+				   enum pipe *pipe)
+{
+	struct drm_device *dev = encoder->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_dvo *intel_dvo = enc_to_intel_dvo(&encoder->base);
+	u32 tmp;
+
+	tmp = I915_READ(intel_dvo->dev.dvo_reg);
+
+	if (!(tmp & DVO_ENABLE))
+		return false;
+
+	*pipe = PORT_TO_PIPE(tmp);
+
+	return true;
+}
+
+static void intel_disable_dvo(struct intel_encoder *encoder)
+{
+	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
+	struct intel_dvo *intel_dvo = enc_to_intel_dvo(&encoder->base);
+	u32 dvo_reg = intel_dvo->dev.dvo_reg;
+	u32 temp = I915_READ(dvo_reg);
+
+	intel_dvo->dev.dev_ops->dpms(&intel_dvo->dev, false);
+	I915_WRITE(dvo_reg, temp & ~DVO_ENABLE);
+	I915_READ(dvo_reg);
+}
+
+static void intel_enable_dvo(struct intel_encoder *encoder)
+{
+	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
+	struct intel_dvo *intel_dvo = enc_to_intel_dvo(&encoder->base);
 	u32 dvo_reg = intel_dvo->dev.dvo_reg;
 	u32 temp = I915_READ(dvo_reg);
 
+	I915_WRITE(dvo_reg, temp | DVO_ENABLE);
+	I915_READ(dvo_reg);
+	intel_dvo->dev.dev_ops->dpms(&intel_dvo->dev, true);
+}
+
+static void intel_dvo_dpms(struct drm_connector *connector, int mode)
+{
+	struct intel_dvo *intel_dvo = intel_attached_dvo(connector);
+	struct drm_crtc *crtc;
+
+	/* dvo supports only 2 dpms states. */
+	if (mode != DRM_MODE_DPMS_ON)
+		mode = DRM_MODE_DPMS_OFF;
+
+	if (mode == connector->dpms)
+		return;
+
+	connector->dpms = mode;
+
+	/* Only need to change hw state when actually enabled */
+	crtc = intel_dvo->base.base.crtc;
+	if (!crtc) {
+		intel_dvo->base.connectors_active = false;
+		return;
+	}
+
 	if (mode == DRM_MODE_DPMS_ON) {
-		I915_WRITE(dvo_reg, temp | DVO_ENABLE);
-		I915_READ(dvo_reg);
-		intel_dvo->dev.dev_ops->dpms(&intel_dvo->dev, mode);
+		intel_dvo->base.connectors_active = true;
+
+		intel_crtc_update_dpms(crtc);
+
+		intel_dvo->dev.dev_ops->dpms(&intel_dvo->dev, true);
 	} else {
-		intel_dvo->dev.dev_ops->dpms(&intel_dvo->dev, mode);
-		I915_WRITE(dvo_reg, temp & ~DVO_ENABLE);
-		I915_READ(dvo_reg);
+		intel_dvo->dev.dev_ops->dpms(&intel_dvo->dev, false);
+
+		intel_dvo->base.connectors_active = false;
+
+		intel_crtc_update_dpms(crtc);
 	}
+
+	intel_modeset_check_state(connector->dev);
 }
 
 static int intel_dvo_mode_valid(struct drm_connector *connector,
@@ -267,15 +344,13 @@ static void intel_dvo_destroy(struct drm_connector *connector)
 }
 
 static const struct drm_encoder_helper_funcs intel_dvo_helper_funcs = {
-	.dpms = intel_dvo_dpms,
 	.mode_fixup = intel_dvo_mode_fixup,
-	.prepare = intel_encoder_prepare,
 	.mode_set = intel_dvo_mode_set,
-	.commit = intel_encoder_commit,
+	.disable = intel_encoder_noop,
 };
 
 static const struct drm_connector_funcs intel_dvo_connector_funcs = {
-	.dpms = drm_helper_connector_dpms,
+	.dpms = intel_dvo_dpms,
 	.detect = intel_dvo_detect,
 	.destroy = intel_dvo_destroy,
 	.fill_modes = drm_helper_probe_single_connector_modes,
@@ -364,6 +439,11 @@ void intel_dvo_init(struct drm_device *dev)
 	drm_encoder_init(dev, &intel_encoder->base,
 			 &intel_dvo_enc_funcs, encoder_type);
 
+	intel_encoder->disable = intel_disable_dvo;
+	intel_encoder->enable = intel_enable_dvo;
+	intel_encoder->get_hw_state = intel_dvo_get_hw_state;
+	intel_connector->get_hw_state = intel_dvo_connector_get_hw_state;
+
 	/* Now, try to find a controller */
 	for (i = 0; i < ARRAY_SIZE(intel_dvo_devices); i++) {
 		struct drm_connector *connector = &intel_connector->base;
@@ -396,17 +476,14 @@ void intel_dvo_init(struct drm_device *dev)
 		intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
 		switch (dvo->type) {
 		case INTEL_DVO_CHIP_TMDS:
-			intel_encoder->clone_mask =
-				(1 << INTEL_DVO_TMDS_CLONE_BIT) |
-				(1 << INTEL_ANALOG_CLONE_BIT);
+			intel_encoder->cloneable = true;
 			drm_connector_init(dev, connector,
 					   &intel_dvo_connector_funcs,
 					   DRM_MODE_CONNECTOR_DVII);
 			encoder_type = DRM_MODE_ENCODER_TMDS;
 			break;
 		case INTEL_DVO_CHIP_LVDS:
-			intel_encoder->clone_mask =
-				(1 << INTEL_DVO_LVDS_CLONE_BIT);
+			intel_encoder->cloneable = false;
 			drm_connector_init(dev, connector,
 					   &intel_dvo_connector_funcs,
 					   DRM_MODE_CONNECTOR_LVDS);
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index 12dc330..d39ed58 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -601,15 +601,36 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder,
 	intel_hdmi->set_infoframes(encoder, adjusted_mode);
 }
 
-static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode)
+static bool intel_hdmi_get_hw_state(struct intel_encoder *encoder,
+				    enum pipe *pipe)
 {
-	struct drm_device *dev = encoder->dev;
+	struct drm_device *dev = encoder->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
+	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
+	u32 tmp;
+
+	tmp = I915_READ(intel_hdmi->sdvox_reg);
+
+	if (!(tmp & SDVO_ENABLE))
+		return false;
+
+	if (HAS_PCH_CPT(dev))
+		*pipe = PORT_TO_PIPE_CPT(tmp);
+	else
+		*pipe = PORT_TO_PIPE(tmp);
+
+	return true;
+}
+
+static void intel_enable_hdmi(struct intel_encoder *encoder)
+{
+	struct drm_device *dev = encoder->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
 	u32 temp;
 	u32 enable_bits = SDVO_ENABLE;
 
-	if (intel_hdmi->has_audio || mode != DRM_MODE_DPMS_ON)
+	if (intel_hdmi->has_audio)
 		enable_bits |= SDVO_AUDIO_ENABLE;
 
 	temp = I915_READ(intel_hdmi->sdvox_reg);
@@ -617,31 +638,12 @@ static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode)
 	/* HW workaround for IBX, we need to move the port to transcoder A
 	 * before disabling it. */
 	if (HAS_PCH_IBX(dev)) {
-		struct drm_crtc *crtc = encoder->crtc;
+		struct drm_crtc *crtc = encoder->base.crtc;
 		int pipe = crtc ? to_intel_crtc(crtc)->pipe : -1;
 
-		if (mode != DRM_MODE_DPMS_ON) {
-			if (temp & SDVO_PIPE_B_SELECT) {
-				temp &= ~SDVO_PIPE_B_SELECT;
-				I915_WRITE(intel_hdmi->sdvox_reg, temp);
-				POSTING_READ(intel_hdmi->sdvox_reg);
-
-				/* Again we need to write this twice. */
-				I915_WRITE(intel_hdmi->sdvox_reg, temp);
-				POSTING_READ(intel_hdmi->sdvox_reg);
-
-				/* Transcoder selection bits only update
-				 * effectively on vblank. */
-				if (crtc)
-					intel_wait_for_vblank(dev, pipe);
-				else
-					msleep(50);
-			}
-		} else {
-			/* Restore the transcoder select bit. */
-			if (pipe == PIPE_B)
-				enable_bits |= SDVO_PIPE_B_SELECT;
-		}
+		/* Restore the transcoder select bit. */
+		if (pipe == PIPE_B)
+			enable_bits |= SDVO_PIPE_B_SELECT;
 	}
 
 	/* HW workaround, need to toggle enable bit off and on for 12bpc, but
@@ -652,12 +654,66 @@ static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode)
 		POSTING_READ(intel_hdmi->sdvox_reg);
 	}
 
-	if (mode != DRM_MODE_DPMS_ON) {
-		temp &= ~enable_bits;
-	} else {
-		temp |= enable_bits;
+	temp |= enable_bits;
+
+	I915_WRITE(intel_hdmi->sdvox_reg, temp);
+	POSTING_READ(intel_hdmi->sdvox_reg);
+
+	/* HW workaround, need to write this twice for issue that may result
+	 * in first write getting masked.
+	 */
+	if (HAS_PCH_SPLIT(dev)) {
+		I915_WRITE(intel_hdmi->sdvox_reg, temp);
+		POSTING_READ(intel_hdmi->sdvox_reg);
+	}
+}
+
+static void intel_disable_hdmi(struct intel_encoder *encoder)
+{
+	struct drm_device *dev = encoder->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
+	u32 temp;
+	u32 enable_bits = SDVO_ENABLE;
+
+	enable_bits |= SDVO_AUDIO_ENABLE;
+
+	temp = I915_READ(intel_hdmi->sdvox_reg);
+
+	/* HW workaround for IBX, we need to move the port to transcoder A
+	 * before disabling it. */
+	if (HAS_PCH_IBX(dev)) {
+		struct drm_crtc *crtc = encoder->base.crtc;
+		int pipe = crtc ? to_intel_crtc(crtc)->pipe : -1;
+
+		if (temp & SDVO_PIPE_B_SELECT) {
+			temp &= ~SDVO_PIPE_B_SELECT;
+			I915_WRITE(intel_hdmi->sdvox_reg, temp);
+			POSTING_READ(intel_hdmi->sdvox_reg);
+
+			/* Again we need to write this twice. */
+			I915_WRITE(intel_hdmi->sdvox_reg, temp);
+			POSTING_READ(intel_hdmi->sdvox_reg);
+
+			/* Transcoder selection bits only update
+			 * effectively on vblank. */
+			if (crtc)
+				intel_wait_for_vblank(dev, pipe);
+			else
+				msleep(50);
+		}
+	}
+
+	/* HW workaround, need to toggle enable bit off and on for 12bpc, but
+	 * we do this anyway which shows more stable in testing.
+	 */
+	if (HAS_PCH_SPLIT(dev)) {
+		I915_WRITE(intel_hdmi->sdvox_reg, temp & ~SDVO_ENABLE);
+		POSTING_READ(intel_hdmi->sdvox_reg);
 	}
 
+	temp &= ~enable_bits;
+
 	I915_WRITE(intel_hdmi->sdvox_reg, temp);
 	POSTING_READ(intel_hdmi->sdvox_reg);
 
@@ -737,7 +793,6 @@ intel_hdmi_detect(struct drm_connector *connector, bool force)
 						drm_detect_hdmi_monitor(edid);
 			intel_hdmi->has_audio = drm_detect_monitor_audio(edid);
 		}
-		connector->display_info.raw_edid = NULL;
 		kfree(edid);
 	}
 
@@ -778,8 +833,6 @@ intel_hdmi_detect_audio(struct drm_connector *connector)
 	if (edid) {
 		if (edid->input & DRM_EDID_INPUT_DIGITAL)
 			has_audio = drm_detect_monitor_audio(edid);
-
-		connector->display_info.raw_edid = NULL;
 		kfree(edid);
 	}
 
@@ -833,9 +886,8 @@ intel_hdmi_set_property(struct drm_connector *connector,
 done:
 	if (intel_hdmi->base.base.crtc) {
 		struct drm_crtc *crtc = intel_hdmi->base.base.crtc;
-		drm_crtc_helper_set_mode(crtc, &crtc->mode,
-					 crtc->x, crtc->y,
-					 crtc->fb);
+		intel_set_mode(crtc, &crtc->mode,
+			       crtc->x, crtc->y, crtc->fb);
 	}
 
 	return 0;
@@ -849,23 +901,19 @@ static void intel_hdmi_destroy(struct drm_connector *connector)
 }
 
 static const struct drm_encoder_helper_funcs intel_hdmi_helper_funcs_hsw = {
-	.dpms = intel_ddi_dpms,
 	.mode_fixup = intel_hdmi_mode_fixup,
-	.prepare = intel_encoder_prepare,
 	.mode_set = intel_ddi_mode_set,
-	.commit = intel_encoder_commit,
+	.disable = intel_encoder_noop,
 };
 
 static const struct drm_encoder_helper_funcs intel_hdmi_helper_funcs = {
-	.dpms = intel_hdmi_dpms,
 	.mode_fixup = intel_hdmi_mode_fixup,
-	.prepare = intel_encoder_prepare,
 	.mode_set = intel_hdmi_mode_set,
-	.commit = intel_encoder_commit,
+	.disable = intel_encoder_noop,
 };
 
 static const struct drm_connector_funcs intel_hdmi_connector_funcs = {
-	.dpms = drm_helper_connector_dpms,
+	.dpms = intel_connector_dpms,
 	.detect = intel_hdmi_detect,
 	.fill_modes = drm_helper_probe_single_connector_modes,
 	.set_property = intel_hdmi_set_property,
@@ -889,7 +937,7 @@ intel_hdmi_add_properties(struct intel_hdmi *intel_hdmi, struct drm_connector *c
 	intel_attach_broadcast_rgb_property(connector);
 }
 
-void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
+void intel_hdmi_init(struct drm_device *dev, int sdvox_reg, enum port port)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_connector *connector;
@@ -923,48 +971,25 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
 	connector->doublescan_allowed = 0;
 	intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
 
-	/* Set up the DDC bus. */
-	if (sdvox_reg == SDVOB) {
-		intel_encoder->clone_mask = (1 << INTEL_HDMIB_CLONE_BIT);
-		intel_hdmi->ddc_bus = GMBUS_PORT_DPB;
-		dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS;
-	} else if (sdvox_reg == SDVOC) {
-		intel_encoder->clone_mask = (1 << INTEL_HDMIC_CLONE_BIT);
-		intel_hdmi->ddc_bus = GMBUS_PORT_DPC;
-		dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS;
-	} else if (sdvox_reg == HDMIB) {
-		intel_encoder->clone_mask = (1 << INTEL_HDMID_CLONE_BIT);
-		intel_hdmi->ddc_bus = GMBUS_PORT_DPB;
-		dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS;
-	} else if (sdvox_reg == HDMIC) {
-		intel_encoder->clone_mask = (1 << INTEL_HDMIE_CLONE_BIT);
-		intel_hdmi->ddc_bus = GMBUS_PORT_DPC;
-		dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS;
-	} else if (sdvox_reg == HDMID) {
-		intel_encoder->clone_mask = (1 << INTEL_HDMIF_CLONE_BIT);
-		intel_hdmi->ddc_bus = GMBUS_PORT_DPD;
-		dev_priv->hotplug_supported_mask |= HDMID_HOTPLUG_INT_STATUS;
-	} else if (sdvox_reg == DDI_BUF_CTL(PORT_B)) {
-		DRM_DEBUG_DRIVER("LPT: detected output on DDI B\n");
-		intel_encoder->clone_mask = (1 << INTEL_HDMIB_CLONE_BIT);
+	intel_encoder->cloneable = false;
+
+	intel_hdmi->ddi_port = port;
+	switch (port) {
+	case PORT_B:
 		intel_hdmi->ddc_bus = GMBUS_PORT_DPB;
-		intel_hdmi->ddi_port = PORT_B;
 		dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS;
-	} else if (sdvox_reg == DDI_BUF_CTL(PORT_C)) {
-		DRM_DEBUG_DRIVER("LPT: detected output on DDI C\n");
-		intel_encoder->clone_mask = (1 << INTEL_HDMIC_CLONE_BIT);
+		break;
+	case PORT_C:
 		intel_hdmi->ddc_bus = GMBUS_PORT_DPC;
-		intel_hdmi->ddi_port = PORT_C;
 		dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS;
-	} else if (sdvox_reg == DDI_BUF_CTL(PORT_D)) {
-		DRM_DEBUG_DRIVER("LPT: detected output on DDI D\n");
-		intel_encoder->clone_mask = (1 << INTEL_HDMID_CLONE_BIT);
+		break;
+	case PORT_D:
 		intel_hdmi->ddc_bus = GMBUS_PORT_DPD;
-		intel_hdmi->ddi_port = PORT_D;
 		dev_priv->hotplug_supported_mask |= HDMID_HOTPLUG_INT_STATUS;
-	} else {
-		/* If we got an unknown sdvox_reg, things are pretty much broken
-		 * in a way that we should let the kernel know about it */
+		break;
+	case PORT_A:
+		/* Internal port only for eDP. */
+	default:
 		BUG();
 	}
 
@@ -987,10 +1012,21 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
 		intel_hdmi->set_infoframes = cpt_set_infoframes;
 	}
 
-	if (IS_HASWELL(dev))
-		drm_encoder_helper_add(&intel_encoder->base, &intel_hdmi_helper_funcs_hsw);
-	else
-		drm_encoder_helper_add(&intel_encoder->base, &intel_hdmi_helper_funcs);
+	if (IS_HASWELL(dev)) {
+		intel_encoder->enable = intel_enable_ddi;
+		intel_encoder->disable = intel_disable_ddi;
+		intel_encoder->get_hw_state = intel_ddi_get_hw_state;
+		drm_encoder_helper_add(&intel_encoder->base,
+				       &intel_hdmi_helper_funcs_hsw);
+	} else {
+		intel_encoder->enable = intel_enable_hdmi;
+		intel_encoder->disable = intel_disable_hdmi;
+		intel_encoder->get_hw_state = intel_hdmi_get_hw_state;
+		drm_encoder_helper_add(&intel_encoder->base,
+				       &intel_hdmi_helper_funcs);
+	}
+	intel_connector->get_hw_state = intel_connector_get_hw_state;
+
 
 	intel_hdmi_add_properties(intel_hdmi, connector);
 
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index e9a6f6a..40d72bd 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -65,13 +65,40 @@ static struct intel_lvds *intel_attached_lvds(struct drm_connector *connector)
 			    struct intel_lvds, base);
 }
 
+static bool intel_lvds_get_hw_state(struct intel_encoder *encoder,
+				    enum pipe *pipe)
+{
+	struct drm_device *dev = encoder->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 lvds_reg, tmp;
+
+	if (HAS_PCH_SPLIT(dev)) {
+		lvds_reg = PCH_LVDS;
+	} else {
+		lvds_reg = LVDS;
+	}
+
+	tmp = I915_READ(lvds_reg);
+
+	if (!(tmp & LVDS_PORT_EN))
+		return false;
+
+	if (HAS_PCH_CPT(dev))
+		*pipe = PORT_TO_PIPE_CPT(tmp);
+	else
+		*pipe = PORT_TO_PIPE(tmp);
+
+	return true;
+}
+
 /**
  * Sets the power state for the panel.
  */
-static void intel_lvds_enable(struct intel_lvds *intel_lvds)
+static void intel_enable_lvds(struct intel_encoder *encoder)
 {
-	struct drm_device *dev = intel_lvds->base.base.dev;
-	struct intel_crtc *intel_crtc = to_intel_crtc(intel_lvds->base.base.crtc);
+	struct drm_device *dev = encoder->base.dev;
+	struct intel_lvds *intel_lvds = to_intel_lvds(&encoder->base);
+	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 ctl_reg, lvds_reg, stat_reg;
 
@@ -111,9 +138,10 @@ static void intel_lvds_enable(struct intel_lvds *intel_lvds)
 	intel_panel_enable_backlight(dev, intel_crtc->pipe);
 }
 
-static void intel_lvds_disable(struct intel_lvds *intel_lvds)
+static void intel_disable_lvds(struct intel_encoder *encoder)
 {
-	struct drm_device *dev = intel_lvds->base.base.dev;
+	struct drm_device *dev = encoder->base.dev;
+	struct intel_lvds *intel_lvds = to_intel_lvds(&encoder->base);
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 ctl_reg, lvds_reg, stat_reg;
 
@@ -142,18 +170,6 @@ static void intel_lvds_disable(struct intel_lvds *intel_lvds)
 	POSTING_READ(lvds_reg);
 }
 
-static void intel_lvds_dpms(struct drm_encoder *encoder, int mode)
-{
-	struct intel_lvds *intel_lvds = to_intel_lvds(encoder);
-
-	if (mode == DRM_MODE_DPMS_ON)
-		intel_lvds_enable(intel_lvds);
-	else
-		intel_lvds_disable(intel_lvds);
-
-	/* XXX: We never power down the LVDS pairs. */
-}
-
 static int intel_lvds_mode_valid(struct drm_connector *connector,
 				 struct drm_display_mode *mode)
 {
@@ -234,9 +250,8 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
 {
 	struct drm_device *dev = encoder->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
 	struct intel_lvds *intel_lvds = to_intel_lvds(encoder);
-	struct intel_encoder *tmp_encoder;
+	struct intel_crtc *intel_crtc = intel_lvds->base.new_crtc;
 	u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0;
 	int pipe;
 
@@ -246,14 +261,8 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
 		return false;
 	}
 
-	/* Should never happen!! */
-	for_each_encoder_on_crtc(dev, encoder->crtc, tmp_encoder) {
-		if (&tmp_encoder->base != encoder) {
-			DRM_ERROR("Can't enable LVDS and another "
-			       "encoder on the same pipe\n");
-			return false;
-		}
-	}
+	if (intel_encoder_check_is_cloned(&intel_lvds->base))
+		return false;
 
 	/*
 	 * We have timings from the BIOS for the panel, put them in
@@ -405,23 +414,6 @@ out:
 	return true;
 }
 
-static void intel_lvds_prepare(struct drm_encoder *encoder)
-{
-	struct intel_lvds *intel_lvds = to_intel_lvds(encoder);
-
-	intel_lvds_disable(intel_lvds);
-}
-
-static void intel_lvds_commit(struct drm_encoder *encoder)
-{
-	struct intel_lvds *intel_lvds = to_intel_lvds(encoder);
-
-	/* Always do a full power on as we do not know what state
-	 * we were left in.
-	 */
-	intel_lvds_enable(intel_lvds);
-}
-
 static void intel_lvds_mode_set(struct drm_encoder *encoder,
 				struct drm_display_mode *mode,
 				struct drm_display_mode *adjusted_mode)
@@ -535,7 +527,7 @@ static int intel_lid_notify(struct notifier_block *nb, unsigned long val,
 	dev_priv->modeset_on_lid = 0;
 
 	mutex_lock(&dev->mode_config.mutex);
-	drm_helper_resume_force_mode(dev);
+	intel_modeset_check_state(dev);
 	mutex_unlock(&dev->mode_config.mutex);
 
 	return NOTIFY_OK;
@@ -587,8 +579,8 @@ static int intel_lvds_set_property(struct drm_connector *connector,
 			 * If the CRTC is enabled, the display will be changed
 			 * according to the new panel fitting mode.
 			 */
-			drm_crtc_helper_set_mode(crtc, &crtc->mode,
-				crtc->x, crtc->y, crtc->fb);
+			intel_set_mode(crtc, &crtc->mode,
+				       crtc->x, crtc->y, crtc->fb);
 		}
 	}
 
@@ -596,11 +588,9 @@ static int intel_lvds_set_property(struct drm_connector *connector,
 }
 
 static const struct drm_encoder_helper_funcs intel_lvds_helper_funcs = {
-	.dpms = intel_lvds_dpms,
 	.mode_fixup = intel_lvds_mode_fixup,
-	.prepare = intel_lvds_prepare,
 	.mode_set = intel_lvds_mode_set,
-	.commit = intel_lvds_commit,
+	.disable = intel_encoder_noop,
 };
 
 static const struct drm_connector_helper_funcs intel_lvds_connector_helper_funcs = {
@@ -610,7 +600,7 @@ static const struct drm_connector_helper_funcs intel_lvds_connector_helper_funcs
 };
 
 static const struct drm_connector_funcs intel_lvds_connector_funcs = {
-	.dpms = drm_helper_connector_dpms,
+	.dpms = intel_connector_dpms,
 	.detect = intel_lvds_detect,
 	.fill_modes = drm_helper_probe_single_connector_modes,
 	.set_property = intel_lvds_set_property,
@@ -972,10 +962,15 @@ bool intel_lvds_init(struct drm_device *dev)
 	drm_encoder_init(dev, &intel_encoder->base, &intel_lvds_enc_funcs,
 			 DRM_MODE_ENCODER_LVDS);
 
+	intel_encoder->enable = intel_enable_lvds;
+	intel_encoder->disable = intel_disable_lvds;
+	intel_encoder->get_hw_state = intel_lvds_get_hw_state;
+	intel_connector->get_hw_state = intel_connector_get_hw_state;
+
 	intel_connector_attach_encoder(intel_connector, intel_encoder);
 	intel_encoder->type = INTEL_OUTPUT_LVDS;
 
-	intel_encoder->clone_mask = (1 << INTEL_LVDS_CLONE_BIT);
+	intel_encoder->cloneable = false;
 	if (HAS_PCH_SPLIT(dev))
 		intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
 	else if (IS_GEN4(dev))
diff --git a/drivers/gpu/drm/i915/intel_modes.c b/drivers/gpu/drm/i915/intel_modes.c
index 29b7259..4bc1c0f 100644
--- a/drivers/gpu/drm/i915/intel_modes.c
+++ b/drivers/gpu/drm/i915/intel_modes.c
@@ -45,7 +45,6 @@ int intel_connector_update_modes(struct drm_connector *connector,
 	drm_mode_connector_update_edid_property(connector, edid);
 	ret = drm_add_edid_modes(connector, edid);
 	drm_edid_to_eld(connector, edid);
-	connector->display_info.raw_edid = NULL;
 	kfree(edid);
 
 	return ret;
diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c
index 830d0dd..afd0f30 100644
--- a/drivers/gpu/drm/i915/intel_overlay.c
+++ b/drivers/gpu/drm/i915/intel_overlay.c
@@ -235,54 +235,6 @@ static int intel_overlay_do_wait_request(struct intel_overlay *overlay,
 	return 0;
 }
 
-/* Workaround for i830 bug where pipe a must be enable to change control regs */
-static int
-i830_activate_pipe_a(struct drm_device *dev)
-{
-	drm_i915_private_t *dev_priv = dev->dev_private;
-	struct intel_crtc *crtc;
-	struct drm_crtc_helper_funcs *crtc_funcs;
-	struct drm_display_mode vesa_640x480 = {
-		DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25175, 640, 656,
-			 752, 800, 0, 480, 489, 492, 525, 0,
-			 DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC)
-	}, *mode;
-
-	crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[0]);
-	if (crtc->dpms_mode == DRM_MODE_DPMS_ON)
-		return 0;
-
-	/* most i8xx have pipe a forced on, so don't trust dpms mode */
-	if (I915_READ(_PIPEACONF) & PIPECONF_ENABLE)
-		return 0;
-
-	crtc_funcs = crtc->base.helper_private;
-	if (crtc_funcs->dpms == NULL)
-		return 0;
-
-	DRM_DEBUG_DRIVER("Enabling pipe A in order to enable overlay\n");
-
-	mode = drm_mode_duplicate(dev, &vesa_640x480);
-
-	if (!drm_crtc_helper_set_mode(&crtc->base, mode,
-				       crtc->base.x, crtc->base.y,
-				       crtc->base.fb))
-		return 0;
-
-	crtc_funcs->dpms(&crtc->base, DRM_MODE_DPMS_ON);
-	return 1;
-}
-
-static void
-i830_deactivate_pipe_a(struct drm_device *dev)
-{
-	drm_i915_private_t *dev_priv = dev->dev_private;
-	struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[0];
-	struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
-
-	crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
-}
-
 /* overlay needs to be disable in OCMD reg */
 static int intel_overlay_on(struct intel_overlay *overlay)
 {
@@ -290,17 +242,12 @@ static int intel_overlay_on(struct intel_overlay *overlay)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_ring_buffer *ring = &dev_priv->ring[RCS];
 	struct drm_i915_gem_request *request;
-	int pipe_a_quirk = 0;
 	int ret;
 
 	BUG_ON(overlay->active);
 	overlay->active = 1;
 
-	if (IS_I830(dev)) {
-		pipe_a_quirk = i830_activate_pipe_a(dev);
-		if (pipe_a_quirk < 0)
-			return pipe_a_quirk;
-	}
+	WARN_ON(IS_I830(dev) && !(dev_priv->quirks & QUIRK_PIPEA_FORCE));
 
 	request = kzalloc(sizeof(*request), GFP_KERNEL);
 	if (request == NULL) {
@@ -322,9 +269,6 @@ static int intel_overlay_on(struct intel_overlay *overlay)
 
 	ret = intel_overlay_do_wait_request(overlay, request, NULL);
 out:
-	if (pipe_a_quirk)
-		i830_deactivate_pipe_a(dev);
-
 	return ret;
 }
 
@@ -1439,7 +1383,7 @@ void intel_setup_overlay(struct drm_device *dev)
 		}
 		overlay->flip_addr = reg_bo->phys_obj->handle->busaddr;
 	} else {
-		ret = i915_gem_object_pin(reg_bo, PAGE_SIZE, true);
+		ret = i915_gem_object_pin(reg_bo, PAGE_SIZE, true, false);
 		if (ret) {
 			DRM_ERROR("failed to pin overlay register bo\n");
 			goto out_free_bo;
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index ba8a27b..94dda33 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -31,6 +31,8 @@
 #include "../../../platform/x86/intel_ips.h"
 #include <linux/module.h>
 
+#define FORCEWAKE_ACK_TIMEOUT_MS 2
+
 /* FBC, or Frame Buffer Compression, is a technique employed to compress the
  * framebuffer contents in-memory, aiming at reducing the required bandwidth
  * during in-memory transfers and, therefore, reduce the power packet.
@@ -593,7 +595,7 @@ static void i915_ironlake_get_mem_freq(struct drm_device *dev)
 		break;
 	}
 
-	dev_priv->r_t = dev_priv->mem_freq;
+	dev_priv->ips.r_t = dev_priv->mem_freq;
 
 	switch (csipll & 0x3ff) {
 	case 0x00c:
@@ -625,11 +627,11 @@ static void i915_ironlake_get_mem_freq(struct drm_device *dev)
 	}
 
 	if (dev_priv->fsb_freq == 3200) {
-		dev_priv->c_m = 0;
+		dev_priv->ips.c_m = 0;
 	} else if (dev_priv->fsb_freq > 3200 && dev_priv->fsb_freq <= 4800) {
-		dev_priv->c_m = 1;
+		dev_priv->ips.c_m = 1;
 	} else {
-		dev_priv->c_m = 2;
+		dev_priv->ips.c_m = 2;
 	}
 }
 
@@ -2138,7 +2140,7 @@ intel_alloc_context_page(struct drm_device *dev)
 		return NULL;
 	}
 
-	ret = i915_gem_object_pin(ctx, 4096, true);
+	ret = i915_gem_object_pin(ctx, 4096, true, false);
 	if (ret) {
 		DRM_ERROR("failed to pin power context: %d\n", ret);
 		goto err_unref;
@@ -2160,11 +2162,22 @@ err_unref:
 	return NULL;
 }
 
+/**
+ * Lock protecting IPS related data structures
+ */
+DEFINE_SPINLOCK(mchdev_lock);
+
+/* Global for IPS driver to get at the current i915 device. Protected by
+ * mchdev_lock. */
+static struct drm_i915_private *i915_mch_dev;
+
 bool ironlake_set_drps(struct drm_device *dev, u8 val)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u16 rgvswctl;
 
+	assert_spin_locked(&mchdev_lock);
+
 	rgvswctl = I915_READ16(MEMSWCTL);
 	if (rgvswctl & MEMCTL_CMD_STS) {
 		DRM_DEBUG("gpu busy, RCS change rejected\n");
@@ -2188,6 +2201,8 @@ static void ironlake_enable_drps(struct drm_device *dev)
 	u32 rgvmodectl = I915_READ(MEMMODECTL);
 	u8 fmax, fmin, fstart, vstart;
 
+	spin_lock_irq(&mchdev_lock);
+
 	/* Enable temp reporting */
 	I915_WRITE16(PMMISC, I915_READ(PMMISC) | MCPPCE_EN);
 	I915_WRITE16(TSC1, I915_READ(TSC1) | TSE);
@@ -2211,12 +2226,12 @@ static void ironlake_enable_drps(struct drm_device *dev)
 	vstart = (I915_READ(PXVFREQ_BASE + (fstart * 4)) & PXVFREQ_PX_MASK) >>
 		PXVFREQ_PX_SHIFT;
 
-	dev_priv->fmax = fmax; /* IPS callback will increase this */
-	dev_priv->fstart = fstart;
+	dev_priv->ips.fmax = fmax; /* IPS callback will increase this */
+	dev_priv->ips.fstart = fstart;
 
-	dev_priv->max_delay = fstart;
-	dev_priv->min_delay = fmin;
-	dev_priv->cur_delay = fstart;
+	dev_priv->ips.max_delay = fstart;
+	dev_priv->ips.min_delay = fmin;
+	dev_priv->ips.cur_delay = fstart;
 
 	DRM_DEBUG_DRIVER("fmax: %d, fmin: %d, fstart: %d\n",
 			 fmax, fmin, fstart);
@@ -2233,23 +2248,29 @@ static void ironlake_enable_drps(struct drm_device *dev)
 	rgvmodectl |= MEMMODE_SWMODE_EN;
 	I915_WRITE(MEMMODECTL, rgvmodectl);
 
-	if (wait_for((I915_READ(MEMSWCTL) & MEMCTL_CMD_STS) == 0, 10))
+	if (wait_for_atomic((I915_READ(MEMSWCTL) & MEMCTL_CMD_STS) == 0, 10))
 		DRM_ERROR("stuck trying to change perf mode\n");
-	msleep(1);
+	mdelay(1);
 
 	ironlake_set_drps(dev, fstart);
 
-	dev_priv->last_count1 = I915_READ(0x112e4) + I915_READ(0x112e8) +
+	dev_priv->ips.last_count1 = I915_READ(0x112e4) + I915_READ(0x112e8) +
 		I915_READ(0x112e0);
-	dev_priv->last_time1 = jiffies_to_msecs(jiffies);
-	dev_priv->last_count2 = I915_READ(0x112f4);
-	getrawmonotonic(&dev_priv->last_time2);
+	dev_priv->ips.last_time1 = jiffies_to_msecs(jiffies);
+	dev_priv->ips.last_count2 = I915_READ(0x112f4);
+	getrawmonotonic(&dev_priv->ips.last_time2);
+
+	spin_unlock_irq(&mchdev_lock);
 }
 
 static void ironlake_disable_drps(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	u16 rgvswctl = I915_READ16(MEMSWCTL);
+	u16 rgvswctl;
+
+	spin_lock_irq(&mchdev_lock);
+
+	rgvswctl = I915_READ16(MEMSWCTL);
 
 	/* Ack interrupts, disable EFC interrupt */
 	I915_WRITE(MEMINTREN, I915_READ(MEMINTREN) & ~MEMINT_EVAL_CHG_EN);
@@ -2259,31 +2280,52 @@ static void ironlake_disable_drps(struct drm_device *dev)
 	I915_WRITE(DEIMR, I915_READ(DEIMR) | DE_PCU_EVENT);
 
 	/* Go back to the starting frequency */
-	ironlake_set_drps(dev, dev_priv->fstart);
-	msleep(1);
+	ironlake_set_drps(dev, dev_priv->ips.fstart);
+	mdelay(1);
 	rgvswctl |= MEMCTL_CMD_STS;
 	I915_WRITE(MEMSWCTL, rgvswctl);
-	msleep(1);
+	mdelay(1);
 
+	spin_unlock_irq(&mchdev_lock);
 }
 
-void gen6_set_rps(struct drm_device *dev, u8 val)
+/* There's a funny hw issue where the hw returns all 0 when reading from
+ * GEN6_RP_INTERRUPT_LIMITS. Hence we always need to compute the desired value
+ * ourselves, instead of doing a rmw cycle (which might result in us clearing
+ * all limits and the gpu stuck at whatever frequency it is at atm).
+ */
+static u32 gen6_rps_limits(struct drm_i915_private *dev_priv, u8 *val)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 limits;
 
 	limits = 0;
-	if (val >= dev_priv->max_delay)
-		val = dev_priv->max_delay;
-	else
-		limits |= dev_priv->max_delay << 24;
 
-	if (val <= dev_priv->min_delay)
-		val = dev_priv->min_delay;
-	else
-		limits |= dev_priv->min_delay << 16;
+	if (*val >= dev_priv->rps.max_delay)
+		*val = dev_priv->rps.max_delay;
+	limits |= dev_priv->rps.max_delay << 24;
+
+	/* Only set the down limit when we've reached the lowest level to avoid
+	 * getting more interrupts, otherwise leave this clear. This prevents a
+	 * race in the hw when coming out of rc6: There's a tiny window where
+	 * the hw runs at the minimal clock before selecting the desired
+	 * frequency, if the down threshold expires in that window we will not
+	 * receive a down interrupt. */
+	if (*val <= dev_priv->rps.min_delay) {
+		*val = dev_priv->rps.min_delay;
+		limits |= dev_priv->rps.min_delay << 16;
+	}
+
+	return limits;
+}
+
+void gen6_set_rps(struct drm_device *dev, u8 val)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 limits = gen6_rps_limits(dev_priv, &val);
 
-	if (val == dev_priv->cur_delay)
+	WARN_ON(!mutex_is_locked(&dev->struct_mutex));
+
+	if (val == dev_priv->rps.cur_delay)
 		return;
 
 	I915_WRITE(GEN6_RPNSWREQ,
@@ -2296,7 +2338,9 @@ void gen6_set_rps(struct drm_device *dev, u8 val)
 	 */
 	I915_WRITE(GEN6_RP_INTERRUPT_LIMITS, limits);
 
-	dev_priv->cur_delay = val;
+	dev_priv->rps.cur_delay = val;
+
+	trace_intel_gpu_freq_change(val * 50);
 }
 
 static void gen6_disable_rps(struct drm_device *dev)
@@ -2312,40 +2356,40 @@ static void gen6_disable_rps(struct drm_device *dev)
 	 * register (PMIMR) to mask PM interrupts. The only risk is in leaving
 	 * stale bits in PMIIR and PMIMR which gen6_enable_rps will clean up. */
 
-	spin_lock_irq(&dev_priv->rps_lock);
-	dev_priv->pm_iir = 0;
-	spin_unlock_irq(&dev_priv->rps_lock);
+	spin_lock_irq(&dev_priv->rps.lock);
+	dev_priv->rps.pm_iir = 0;
+	spin_unlock_irq(&dev_priv->rps.lock);
 
 	I915_WRITE(GEN6_PMIIR, I915_READ(GEN6_PMIIR));
 }
 
 int intel_enable_rc6(const struct drm_device *dev)
 {
-	/*
-	 * Respect the kernel parameter if it is set
-	 */
+	/* Respect the kernel parameter if it is set */
 	if (i915_enable_rc6 >= 0)
 		return i915_enable_rc6;
 
-	/*
-	 * Disable RC6 on Ironlake
-	 */
-	if (INTEL_INFO(dev)->gen == 5)
-		return 0;
+	if (INTEL_INFO(dev)->gen == 5) {
+#ifdef CONFIG_INTEL_IOMMU
+		/* Disable rc6 on ilk if VT-d is on. */
+		if (intel_iommu_gfx_mapped)
+			return false;
+#endif
+		DRM_DEBUG_DRIVER("Ironlake: only RC6 available\n");
+		return INTEL_RC6_ENABLE;
+	}
 
-	/* On Haswell, only RC6 is available. So let's enable it by default to
-	 * provide better testing and coverage since the beginning.
-	 */
-	if (IS_HASWELL(dev))
+	if (IS_HASWELL(dev)) {
+		DRM_DEBUG_DRIVER("Haswell: only RC6 available\n");
 		return INTEL_RC6_ENABLE;
+	}
 
-	/*
-	 * Disable rc6 on Sandybridge
-	 */
+	/* snb/ivb have more than one rc6 state. */
 	if (INTEL_INFO(dev)->gen == 6) {
 		DRM_DEBUG_DRIVER("Sandybridge: deep RC6 disabled\n");
 		return INTEL_RC6_ENABLE;
 	}
+
 	DRM_DEBUG_DRIVER("RC6 and deep RC6 enabled\n");
 	return (INTEL_RC6_ENABLE | INTEL_RC6p_ENABLE);
 }
@@ -2383,9 +2427,9 @@ static void gen6_enable_rps(struct drm_device *dev)
 	gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS);
 
 	/* In units of 100MHz */
-	dev_priv->max_delay = rp_state_cap & 0xff;
-	dev_priv->min_delay = (rp_state_cap & 0xff0000) >> 16;
-	dev_priv->cur_delay = 0;
+	dev_priv->rps.max_delay = rp_state_cap & 0xff;
+	dev_priv->rps.min_delay = (rp_state_cap & 0xff0000) >> 16;
+	dev_priv->rps.cur_delay = 0;
 
 	/* disable the counters and set deterministic thresholds */
 	I915_WRITE(GEN6_RC_CONTROL, 0);
@@ -2438,8 +2482,8 @@ static void gen6_enable_rps(struct drm_device *dev)
 
 	I915_WRITE(GEN6_RP_DOWN_TIMEOUT, 1000000);
 	I915_WRITE(GEN6_RP_INTERRUPT_LIMITS,
-		   dev_priv->max_delay << 24 |
-		   dev_priv->min_delay << 16);
+		   dev_priv->rps.max_delay << 24 |
+		   dev_priv->rps.min_delay << 16);
 
 	I915_WRITE(GEN6_RP_UP_THRESHOLD, 59400);
 	I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 245000);
@@ -2477,7 +2521,7 @@ static void gen6_enable_rps(struct drm_device *dev)
 		     500))
 		DRM_ERROR("timeout waiting for pcode mailbox to finish\n");
 	if (pcu_mbox & (1<<31)) { /* OC supported */
-		dev_priv->max_delay = pcu_mbox & 0xff;
+		dev_priv->rps.max_delay = pcu_mbox & 0xff;
 		DRM_DEBUG_DRIVER("overclocking supported, adjusting frequency max to %dMHz\n", pcu_mbox * 50);
 	}
 
@@ -2485,10 +2529,10 @@ static void gen6_enable_rps(struct drm_device *dev)
 
 	/* requires MSI enabled */
 	I915_WRITE(GEN6_PMIER, GEN6_PM_DEFERRED_EVENTS);
-	spin_lock_irq(&dev_priv->rps_lock);
-	WARN_ON(dev_priv->pm_iir != 0);
+	spin_lock_irq(&dev_priv->rps.lock);
+	WARN_ON(dev_priv->rps.pm_iir != 0);
 	I915_WRITE(GEN6_PMIMR, 0);
-	spin_unlock_irq(&dev_priv->rps_lock);
+	spin_unlock_irq(&dev_priv->rps.lock);
 	/* enable all PM interrupts */
 	I915_WRITE(GEN6_PMINTRMSK, 0);
 
@@ -2499,7 +2543,8 @@ static void gen6_update_ring_freq(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int min_freq = 15;
-	int gpu_freq, ia_freq, max_ia_freq;
+	int gpu_freq;
+	unsigned int ia_freq, max_ia_freq;
 	int scaling_factor = 180;
 
 	WARN_ON(!mutex_is_locked(&dev->struct_mutex));
@@ -2520,9 +2565,9 @@ static void gen6_update_ring_freq(struct drm_device *dev)
 	 * to use for memory access.  We do this by specifying the IA frequency
 	 * the PCU should use as a reference to determine the ring frequency.
 	 */
-	for (gpu_freq = dev_priv->max_delay; gpu_freq >= dev_priv->min_delay;
+	for (gpu_freq = dev_priv->rps.max_delay; gpu_freq >= dev_priv->rps.min_delay;
 	     gpu_freq--) {
-		int diff = dev_priv->max_delay - gpu_freq;
+		int diff = dev_priv->rps.max_delay - gpu_freq;
 
 		/*
 		 * For GPU frequencies less than 750MHz, just use the lowest
@@ -2693,7 +2738,9 @@ unsigned long i915_chipset_val(struct drm_i915_private *dev_priv)
 	unsigned long now = jiffies_to_msecs(jiffies), diff1;
 	int i;
 
-	diff1 = now - dev_priv->last_time1;
+	assert_spin_locked(&mchdev_lock);
+
+	diff1 = now - dev_priv->ips.last_time1;
 
 	/* Prevent division-by-zero if we are asking too fast.
 	 * Also, we don't get interesting results if we are polling
@@ -2701,7 +2748,7 @@ unsigned long i915_chipset_val(struct drm_i915_private *dev_priv)
 	 * in such cases.
 	 */
 	if (diff1 <= 10)
-		return dev_priv->chipset_power;
+		return dev_priv->ips.chipset_power;
 
 	count1 = I915_READ(DMIEC);
 	count2 = I915_READ(DDREC);
@@ -2710,16 +2757,16 @@ unsigned long i915_chipset_val(struct drm_i915_private *dev_priv)
 	total_count = count1 + count2 + count3;
 
 	/* FIXME: handle per-counter overflow */
-	if (total_count < dev_priv->last_count1) {
-		diff = ~0UL - dev_priv->last_count1;
+	if (total_count < dev_priv->ips.last_count1) {
+		diff = ~0UL - dev_priv->ips.last_count1;
 		diff += total_count;
 	} else {
-		diff = total_count - dev_priv->last_count1;
+		diff = total_count - dev_priv->ips.last_count1;
 	}
 
 	for (i = 0; i < ARRAY_SIZE(cparams); i++) {
-		if (cparams[i].i == dev_priv->c_m &&
-		    cparams[i].t == dev_priv->r_t) {
+		if (cparams[i].i == dev_priv->ips.c_m &&
+		    cparams[i].t == dev_priv->ips.r_t) {
 			m = cparams[i].m;
 			c = cparams[i].c;
 			break;
@@ -2730,10 +2777,10 @@ unsigned long i915_chipset_val(struct drm_i915_private *dev_priv)
 	ret = ((m * diff) + c);
 	ret = div_u64(ret, 10);
 
-	dev_priv->last_count1 = total_count;
-	dev_priv->last_time1 = now;
+	dev_priv->ips.last_count1 = total_count;
+	dev_priv->ips.last_time1 = now;
 
-	dev_priv->chipset_power = ret;
+	dev_priv->ips.chipset_power = ret;
 
 	return ret;
 }
@@ -2894,18 +2941,17 @@ static u16 pvid_to_extvid(struct drm_i915_private *dev_priv, u8 pxvid)
 		return v_table[pxvid].vd;
 }
 
-void i915_update_gfx_val(struct drm_i915_private *dev_priv)
+static void __i915_update_gfx_val(struct drm_i915_private *dev_priv)
 {
 	struct timespec now, diff1;
 	u64 diff;
 	unsigned long diffms;
 	u32 count;
 
-	if (dev_priv->info->gen != 5)
-		return;
+	assert_spin_locked(&mchdev_lock);
 
 	getrawmonotonic(&now);
-	diff1 = timespec_sub(now, dev_priv->last_time2);
+	diff1 = timespec_sub(now, dev_priv->ips.last_time2);
 
 	/* Don't divide by 0 */
 	diffms = diff1.tv_sec * 1000 + diff1.tv_nsec / 1000000;
@@ -2914,20 +2960,32 @@ void i915_update_gfx_val(struct drm_i915_private *dev_priv)
 
 	count = I915_READ(GFXEC);
 
-	if (count < dev_priv->last_count2) {
-		diff = ~0UL - dev_priv->last_count2;
+	if (count < dev_priv->ips.last_count2) {
+		diff = ~0UL - dev_priv->ips.last_count2;
 		diff += count;
 	} else {
-		diff = count - dev_priv->last_count2;
+		diff = count - dev_priv->ips.last_count2;
 	}
 
-	dev_priv->last_count2 = count;
-	dev_priv->last_time2 = now;
+	dev_priv->ips.last_count2 = count;
+	dev_priv->ips.last_time2 = now;
 
 	/* More magic constants... */
 	diff = diff * 1181;
 	diff = div_u64(diff, diffms * 10);
-	dev_priv->gfx_power = diff;
+	dev_priv->ips.gfx_power = diff;
+}
+
+void i915_update_gfx_val(struct drm_i915_private *dev_priv)
+{
+	if (dev_priv->info->gen != 5)
+		return;
+
+	spin_lock_irq(&mchdev_lock);
+
+	__i915_update_gfx_val(dev_priv);
+
+	spin_unlock_irq(&mchdev_lock);
 }
 
 unsigned long i915_gfx_val(struct drm_i915_private *dev_priv)
@@ -2935,7 +2993,9 @@ unsigned long i915_gfx_val(struct drm_i915_private *dev_priv)
 	unsigned long t, corr, state1, corr2, state2;
 	u32 pxvid, ext_v;
 
-	pxvid = I915_READ(PXVFREQ_BASE + (dev_priv->cur_delay * 4));
+	assert_spin_locked(&mchdev_lock);
+
+	pxvid = I915_READ(PXVFREQ_BASE + (dev_priv->rps.cur_delay * 4));
 	pxvid = (pxvid >> 24) & 0x7f;
 	ext_v = pvid_to_extvid(dev_priv, pxvid);
 
@@ -2955,28 +3015,16 @@ unsigned long i915_gfx_val(struct drm_i915_private *dev_priv)
 
 	corr = corr * ((150142 * state1) / 10000 - 78642);
 	corr /= 100000;
-	corr2 = (corr * dev_priv->corr);
+	corr2 = (corr * dev_priv->ips.corr);
 
 	state2 = (corr2 * state1) / 10000;
 	state2 /= 100; /* convert to mW */
 
-	i915_update_gfx_val(dev_priv);
+	__i915_update_gfx_val(dev_priv);
 
-	return dev_priv->gfx_power + state2;
+	return dev_priv->ips.gfx_power + state2;
 }
 
-/* Global for IPS driver to get at the current i915 device */
-static struct drm_i915_private *i915_mch_dev;
-/*
- * Lock protecting IPS related data structures
- *   - i915_mch_dev
- *   - dev_priv->max_delay
- *   - dev_priv->min_delay
- *   - dev_priv->fmax
- *   - dev_priv->gpu_busy
- */
-static DEFINE_SPINLOCK(mchdev_lock);
-
 /**
  * i915_read_mch_val - return value for IPS use
  *
@@ -2988,7 +3036,7 @@ unsigned long i915_read_mch_val(void)
 	struct drm_i915_private *dev_priv;
 	unsigned long chipset_val, graphics_val, ret = 0;
 
-	spin_lock(&mchdev_lock);
+	spin_lock_irq(&mchdev_lock);
 	if (!i915_mch_dev)
 		goto out_unlock;
 	dev_priv = i915_mch_dev;
@@ -2999,7 +3047,7 @@ unsigned long i915_read_mch_val(void)
 	ret = chipset_val + graphics_val;
 
 out_unlock:
-	spin_unlock(&mchdev_lock);
+	spin_unlock_irq(&mchdev_lock);
 
 	return ret;
 }
@@ -3015,18 +3063,18 @@ bool i915_gpu_raise(void)
 	struct drm_i915_private *dev_priv;
 	bool ret = true;
 
-	spin_lock(&mchdev_lock);
+	spin_lock_irq(&mchdev_lock);
 	if (!i915_mch_dev) {
 		ret = false;
 		goto out_unlock;
 	}
 	dev_priv = i915_mch_dev;
 
-	if (dev_priv->max_delay > dev_priv->fmax)
-		dev_priv->max_delay--;
+	if (dev_priv->ips.max_delay > dev_priv->ips.fmax)
+		dev_priv->ips.max_delay--;
 
 out_unlock:
-	spin_unlock(&mchdev_lock);
+	spin_unlock_irq(&mchdev_lock);
 
 	return ret;
 }
@@ -3043,18 +3091,18 @@ bool i915_gpu_lower(void)
 	struct drm_i915_private *dev_priv;
 	bool ret = true;
 
-	spin_lock(&mchdev_lock);
+	spin_lock_irq(&mchdev_lock);
 	if (!i915_mch_dev) {
 		ret = false;
 		goto out_unlock;
 	}
 	dev_priv = i915_mch_dev;
 
-	if (dev_priv->max_delay < dev_priv->min_delay)
-		dev_priv->max_delay++;
+	if (dev_priv->ips.max_delay < dev_priv->ips.min_delay)
+		dev_priv->ips.max_delay++;
 
 out_unlock:
-	spin_unlock(&mchdev_lock);
+	spin_unlock_irq(&mchdev_lock);
 
 	return ret;
 }
@@ -3068,17 +3116,20 @@ EXPORT_SYMBOL_GPL(i915_gpu_lower);
 bool i915_gpu_busy(void)
 {
 	struct drm_i915_private *dev_priv;
+	struct intel_ring_buffer *ring;
 	bool ret = false;
+	int i;
 
-	spin_lock(&mchdev_lock);
+	spin_lock_irq(&mchdev_lock);
 	if (!i915_mch_dev)
 		goto out_unlock;
 	dev_priv = i915_mch_dev;
 
-	ret = dev_priv->busy;
+	for_each_ring(ring, dev_priv, i)
+		ret |= !list_empty(&ring->request_list);
 
 out_unlock:
-	spin_unlock(&mchdev_lock);
+	spin_unlock_irq(&mchdev_lock);
 
 	return ret;
 }
@@ -3095,20 +3146,20 @@ bool i915_gpu_turbo_disable(void)
 	struct drm_i915_private *dev_priv;
 	bool ret = true;
 
-	spin_lock(&mchdev_lock);
+	spin_lock_irq(&mchdev_lock);
 	if (!i915_mch_dev) {
 		ret = false;
 		goto out_unlock;
 	}
 	dev_priv = i915_mch_dev;
 
-	dev_priv->max_delay = dev_priv->fstart;
+	dev_priv->ips.max_delay = dev_priv->ips.fstart;
 
-	if (!ironlake_set_drps(dev_priv->dev, dev_priv->fstart))
+	if (!ironlake_set_drps(dev_priv->dev, dev_priv->ips.fstart))
 		ret = false;
 
 out_unlock:
-	spin_unlock(&mchdev_lock);
+	spin_unlock_irq(&mchdev_lock);
 
 	return ret;
 }
@@ -3136,19 +3187,20 @@ ips_ping_for_i915_load(void)
 
 void intel_gpu_ips_init(struct drm_i915_private *dev_priv)
 {
-	spin_lock(&mchdev_lock);
+	/* We only register the i915 ips part with intel-ips once everything is
+	 * set up, to avoid intel-ips sneaking in and reading bogus values. */
+	spin_lock_irq(&mchdev_lock);
 	i915_mch_dev = dev_priv;
-	dev_priv->mchdev_lock = &mchdev_lock;
-	spin_unlock(&mchdev_lock);
+	spin_unlock_irq(&mchdev_lock);
 
 	ips_ping_for_i915_load();
 }
 
 void intel_gpu_ips_teardown(void)
 {
-	spin_lock(&mchdev_lock);
+	spin_lock_irq(&mchdev_lock);
 	i915_mch_dev = NULL;
-	spin_unlock(&mchdev_lock);
+	spin_unlock_irq(&mchdev_lock);
 }
 static void intel_init_emon(struct drm_device *dev)
 {
@@ -3218,7 +3270,7 @@ static void intel_init_emon(struct drm_device *dev)
 
 	lcfuse = I915_READ(LCFUSE02);
 
-	dev_priv->corr = (lcfuse & LCFUSE_HIV_MASK);
+	dev_priv->ips.corr = (lcfuse & LCFUSE_HIV_MASK);
 }
 
 void intel_disable_gt_powersave(struct drm_device *dev)
@@ -3731,42 +3783,6 @@ void intel_init_clock_gating(struct drm_device *dev)
 		dev_priv->display.init_pch_clock_gating(dev);
 }
 
-static void gen6_sanitize_pm(struct drm_device *dev)
-{
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	u32 limits, delay, old;
-
-	gen6_gt_force_wake_get(dev_priv);
-
-	old = limits = I915_READ(GEN6_RP_INTERRUPT_LIMITS);
-	/* Make sure we continue to get interrupts
-	 * until we hit the minimum or maximum frequencies.
-	 */
-	limits &= ~(0x3f << 16 | 0x3f << 24);
-	delay = dev_priv->cur_delay;
-	if (delay < dev_priv->max_delay)
-		limits |= (dev_priv->max_delay & 0x3f) << 24;
-	if (delay > dev_priv->min_delay)
-		limits |= (dev_priv->min_delay & 0x3f) << 16;
-
-	if (old != limits) {
-		/* Note that the known failure case is to read back 0. */
-		DRM_DEBUG_DRIVER("Power management discrepancy: GEN6_RP_INTERRUPT_LIMITS "
-				 "expected %08x, was %08x\n", limits, old);
-		I915_WRITE(GEN6_RP_INTERRUPT_LIMITS, limits);
-	}
-
-	gen6_gt_force_wake_put(dev_priv);
-}
-
-void intel_sanitize_pm(struct drm_device *dev)
-{
-	struct drm_i915_private *dev_priv = dev->dev_private;
-
-	if (dev_priv->display.sanitize_pm)
-		dev_priv->display.sanitize_pm(dev);
-}
-
 /* Starting with Haswell, we have different power wells for
  * different parts of the GPU. This attempts to enable them all.
  */
@@ -3852,7 +3868,6 @@ void intel_init_pm(struct drm_device *dev)
 				dev_priv->display.update_wm = NULL;
 			}
 			dev_priv->display.init_clock_gating = gen6_init_clock_gating;
-			dev_priv->display.sanitize_pm = gen6_sanitize_pm;
 		} else if (IS_IVYBRIDGE(dev)) {
 			/* FIXME: detect B0+ stepping and use auto training */
 			if (SNB_READ_WM0_LATENCY()) {
@@ -3864,7 +3879,6 @@ void intel_init_pm(struct drm_device *dev)
 				dev_priv->display.update_wm = NULL;
 			}
 			dev_priv->display.init_clock_gating = ivybridge_init_clock_gating;
-			dev_priv->display.sanitize_pm = gen6_sanitize_pm;
 		} else if (IS_HASWELL(dev)) {
 			if (SNB_READ_WM0_LATENCY()) {
 				dev_priv->display.update_wm = sandybridge_update_wm;
@@ -3876,7 +3890,6 @@ void intel_init_pm(struct drm_device *dev)
 				dev_priv->display.update_wm = NULL;
 			}
 			dev_priv->display.init_clock_gating = haswell_init_clock_gating;
-			dev_priv->display.sanitize_pm = gen6_sanitize_pm;
 		} else
 			dev_priv->display.update_wm = NULL;
 	} else if (IS_VALLEYVIEW(dev)) {
@@ -3955,14 +3968,16 @@ static void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv)
 	else
 		forcewake_ack = FORCEWAKE_ACK;
 
-	if (wait_for_atomic_us((I915_READ_NOTRACE(forcewake_ack) & 1) == 0, 500))
-		DRM_ERROR("Force wake wait timed out\n");
+	if (wait_for_atomic((I915_READ_NOTRACE(forcewake_ack) & 1) == 0,
+			    FORCEWAKE_ACK_TIMEOUT_MS))
+		DRM_ERROR("Timed out waiting for forcewake old ack to clear.\n");
 
 	I915_WRITE_NOTRACE(FORCEWAKE, 1);
-	POSTING_READ(FORCEWAKE);
+	POSTING_READ(ECOBUS); /* something from same cacheline, but !FORCEWAKE */
 
-	if (wait_for_atomic_us((I915_READ_NOTRACE(forcewake_ack) & 1), 500))
-		DRM_ERROR("Force wake wait timed out\n");
+	if (wait_for_atomic((I915_READ_NOTRACE(forcewake_ack) & 1),
+			    FORCEWAKE_ACK_TIMEOUT_MS))
+		DRM_ERROR("Timed out waiting for forcewake to ack request.\n");
 
 	__gen6_gt_wait_for_thread_c0(dev_priv);
 }
@@ -3976,14 +3991,16 @@ static void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv)
 	else
 		forcewake_ack = FORCEWAKE_MT_ACK;
 
-	if (wait_for_atomic_us((I915_READ_NOTRACE(forcewake_ack) & 1) == 0, 500))
-		DRM_ERROR("Force wake wait timed out\n");
+	if (wait_for_atomic((I915_READ_NOTRACE(forcewake_ack) & 1) == 0,
+			    FORCEWAKE_ACK_TIMEOUT_MS))
+		DRM_ERROR("Timed out waiting for forcewake old ack to clear.\n");
 
 	I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_ENABLE(1));
-	POSTING_READ(FORCEWAKE_MT);
+	POSTING_READ(ECOBUS); /* something from same cacheline, but !FORCEWAKE */
 
-	if (wait_for_atomic_us((I915_READ_NOTRACE(forcewake_ack) & 1), 500))
-		DRM_ERROR("Force wake wait timed out\n");
+	if (wait_for_atomic((I915_READ_NOTRACE(forcewake_ack) & 1),
+			    FORCEWAKE_ACK_TIMEOUT_MS))
+		DRM_ERROR("Timed out waiting for forcewake to ack request.\n");
 
 	__gen6_gt_wait_for_thread_c0(dev_priv);
 }
@@ -4016,14 +4033,14 @@ void gen6_gt_check_fifodbg(struct drm_i915_private *dev_priv)
 static void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
 {
 	I915_WRITE_NOTRACE(FORCEWAKE, 0);
-	POSTING_READ(FORCEWAKE);
+	/* gen6_gt_check_fifodbg doubles as the POSTING_READ */
 	gen6_gt_check_fifodbg(dev_priv);
 }
 
 static void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv)
 {
 	I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_DISABLE(1));
-	POSTING_READ(FORCEWAKE_MT);
+	/* gen6_gt_check_fifodbg doubles as the POSTING_READ */
 	gen6_gt_check_fifodbg(dev_priv);
 }
 
@@ -4062,24 +4079,24 @@ int __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv)
 
 static void vlv_force_wake_get(struct drm_i915_private *dev_priv)
 {
-	/* Already awake? */
-	if ((I915_READ(0x130094) & 0xa1) == 0xa1)
-		return;
+	if (wait_for_atomic((I915_READ_NOTRACE(FORCEWAKE_ACK_VLV) & 1) == 0,
+			    FORCEWAKE_ACK_TIMEOUT_MS))
+		DRM_ERROR("Timed out waiting for forcewake old ack to clear.\n");
 
-	I915_WRITE_NOTRACE(FORCEWAKE_VLV, 0xffffffff);
-	POSTING_READ(FORCEWAKE_VLV);
+	I915_WRITE_NOTRACE(FORCEWAKE_VLV, _MASKED_BIT_ENABLE(1));
 
-	if (wait_for_atomic_us((I915_READ_NOTRACE(FORCEWAKE_ACK_VLV) & 1), 500))
-		DRM_ERROR("Force wake wait timed out\n");
+	if (wait_for_atomic((I915_READ_NOTRACE(FORCEWAKE_ACK_VLV) & 1),
+			    FORCEWAKE_ACK_TIMEOUT_MS))
+		DRM_ERROR("Timed out waiting for forcewake to ack request.\n");
 
 	__gen6_gt_wait_for_thread_c0(dev_priv);
 }
 
 static void vlv_force_wake_put(struct drm_i915_private *dev_priv)
 {
-	I915_WRITE_NOTRACE(FORCEWAKE_VLV, 0xffff0000);
-	/* FIXME: confirm VLV behavior with Punit folks */
-	POSTING_READ(FORCEWAKE_VLV);
+	I915_WRITE_NOTRACE(FORCEWAKE_VLV, _MASKED_BIT_DISABLE(1));
+	/* The below doubles as a POSTING_READ */
+	gen6_gt_check_fifodbg(dev_priv);
 }
 
 void intel_gt_init(struct drm_device *dev)
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index e2a73b3..55cdb4d 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -262,6 +262,83 @@ gen6_render_ring_flush(struct intel_ring_buffer *ring,
 	return 0;
 }
 
+static int
+gen7_render_ring_cs_stall_wa(struct intel_ring_buffer *ring)
+{
+	int ret;
+
+	ret = intel_ring_begin(ring, 4);
+	if (ret)
+		return ret;
+
+	intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4));
+	intel_ring_emit(ring, PIPE_CONTROL_CS_STALL |
+			      PIPE_CONTROL_STALL_AT_SCOREBOARD);
+	intel_ring_emit(ring, 0);
+	intel_ring_emit(ring, 0);
+	intel_ring_advance(ring);
+
+	return 0;
+}
+
+static int
+gen7_render_ring_flush(struct intel_ring_buffer *ring,
+		       u32 invalidate_domains, u32 flush_domains)
+{
+	u32 flags = 0;
+	struct pipe_control *pc = ring->private;
+	u32 scratch_addr = pc->gtt_offset + 128;
+	int ret;
+
+	/*
+	 * Ensure that any following seqno writes only happen when the render
+	 * cache is indeed flushed.
+	 *
+	 * Workaround: 4th PIPE_CONTROL command (except the ones with only
+	 * read-cache invalidate bits set) must have the CS_STALL bit set. We
+	 * don't try to be clever and just set it unconditionally.
+	 */
+	flags |= PIPE_CONTROL_CS_STALL;
+
+	/* Just flush everything.  Experiments have shown that reducing the
+	 * number of bits based on the write domains has little performance
+	 * impact.
+	 */
+	if (flush_domains) {
+		flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH;
+		flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH;
+	}
+	if (invalidate_domains) {
+		flags |= PIPE_CONTROL_TLB_INVALIDATE;
+		flags |= PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE;
+		flags |= PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE;
+		flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE;
+		flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE;
+		flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE;
+		/*
+		 * TLB invalidate requires a post-sync write.
+		 */
+		flags |= PIPE_CONTROL_QW_WRITE;
+
+		/* Workaround: we must issue a pipe_control with CS-stall bit
+		 * set before a pipe_control command that has the state cache
+		 * invalidate bit set. */
+		gen7_render_ring_cs_stall_wa(ring);
+	}
+
+	ret = intel_ring_begin(ring, 4);
+	if (ret)
+		return ret;
+
+	intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(4));
+	intel_ring_emit(ring, flags);
+	intel_ring_emit(ring, scratch_addr | PIPE_CONTROL_GLOBAL_GTT);
+	intel_ring_emit(ring, 0);
+	intel_ring_advance(ring);
+
+	return 0;
+}
+
 static void ring_write_tail(struct intel_ring_buffer *ring,
 			    u32 value)
 {
@@ -382,7 +459,7 @@ init_pipe_control(struct intel_ring_buffer *ring)
 
 	i915_gem_object_set_cache_level(obj, I915_CACHE_LLC);
 
-	ret = i915_gem_object_pin(obj, 4096, true);
+	ret = i915_gem_object_pin(obj, 4096, true, false);
 	if (ret)
 		goto err_unref;
 
@@ -462,7 +539,7 @@ static int init_render_ring(struct intel_ring_buffer *ring)
 	if (INTEL_INFO(dev)->gen >= 6)
 		I915_WRITE(INSTPM, _MASKED_BIT_ENABLE(INSTPM_FORCE_ORDERING));
 
-	if (IS_IVYBRIDGE(dev))
+	if (HAS_L3_GPU_CACHE(dev))
 		I915_WRITE_IMR(ring, ~GEN6_RENDER_L3_PARITY_ERROR);
 
 	return ret;
@@ -628,26 +705,24 @@ pc_render_add_request(struct intel_ring_buffer *ring,
 }
 
 static u32
-gen6_ring_get_seqno(struct intel_ring_buffer *ring)
+gen6_ring_get_seqno(struct intel_ring_buffer *ring, bool lazy_coherency)
 {
-	struct drm_device *dev = ring->dev;
-
 	/* Workaround to force correct ordering between irq and seqno writes on
 	 * ivb (and maybe also on snb) by reading from a CS register (like
 	 * ACTHD) before reading the status page. */
-	if (IS_GEN6(dev) || IS_GEN7(dev))
+	if (!lazy_coherency)
 		intel_ring_get_active_head(ring);
 	return intel_read_status_page(ring, I915_GEM_HWS_INDEX);
 }
 
 static u32
-ring_get_seqno(struct intel_ring_buffer *ring)
+ring_get_seqno(struct intel_ring_buffer *ring, bool lazy_coherency)
 {
 	return intel_read_status_page(ring, I915_GEM_HWS_INDEX);
 }
 
 static u32
-pc_render_get_seqno(struct intel_ring_buffer *ring)
+pc_render_get_seqno(struct intel_ring_buffer *ring, bool lazy_coherency)
 {
 	struct pipe_control *pc = ring->private;
 	return pc->cpu_page[0];
@@ -852,7 +927,7 @@ gen6_ring_get_irq(struct intel_ring_buffer *ring)
 
 	spin_lock_irqsave(&dev_priv->irq_lock, flags);
 	if (ring->irq_refcount++ == 0) {
-		if (IS_IVYBRIDGE(dev) && ring->id == RCS)
+		if (HAS_L3_GPU_CACHE(dev) && ring->id == RCS)
 			I915_WRITE_IMR(ring, ~(ring->irq_enable_mask |
 						GEN6_RENDER_L3_PARITY_ERROR));
 		else
@@ -875,7 +950,7 @@ gen6_ring_put_irq(struct intel_ring_buffer *ring)
 
 	spin_lock_irqsave(&dev_priv->irq_lock, flags);
 	if (--ring->irq_refcount == 0) {
-		if (IS_IVYBRIDGE(dev) && ring->id == RCS)
+		if (HAS_L3_GPU_CACHE(dev) && ring->id == RCS)
 			I915_WRITE_IMR(ring, ~GEN6_RENDER_L3_PARITY_ERROR);
 		else
 			I915_WRITE_IMR(ring, ~0);
@@ -972,7 +1047,7 @@ static int init_status_page(struct intel_ring_buffer *ring)
 
 	i915_gem_object_set_cache_level(obj, I915_CACHE_LLC);
 
-	ret = i915_gem_object_pin(obj, 4096, true);
+	ret = i915_gem_object_pin(obj, 4096, true, false);
 	if (ret != 0) {
 		goto err_unref;
 	}
@@ -1010,7 +1085,6 @@ static int intel_init_ring_buffer(struct drm_device *dev,
 	ring->dev = dev;
 	INIT_LIST_HEAD(&ring->active_list);
 	INIT_LIST_HEAD(&ring->request_list);
-	INIT_LIST_HEAD(&ring->gpu_write_list);
 	ring->size = 32 * PAGE_SIZE;
 
 	init_waitqueue_head(&ring->irq_queue);
@@ -1030,7 +1104,7 @@ static int intel_init_ring_buffer(struct drm_device *dev,
 
 	ring->obj = obj;
 
-	ret = i915_gem_object_pin(obj, PAGE_SIZE, true);
+	ret = i915_gem_object_pin(obj, PAGE_SIZE, true, false);
 	if (ret)
 		goto err_unref;
 
@@ -1379,7 +1453,9 @@ int intel_init_render_ring_buffer(struct drm_device *dev)
 
 	if (INTEL_INFO(dev)->gen >= 6) {
 		ring->add_request = gen6_add_request;
-		ring->flush = gen6_render_ring_flush;
+		ring->flush = gen7_render_ring_flush;
+		if (INTEL_INFO(dev)->gen == 6)
+			ring->flush = gen6_render_ring_flush;
 		ring->irq_get = gen6_ring_get_irq;
 		ring->irq_put = gen6_ring_put_irq;
 		ring->irq_enable_mask = GT_USER_INTERRUPT;
@@ -1481,7 +1557,6 @@ int intel_render_ring_init_dri(struct drm_device *dev, u64 start, u32 size)
 	ring->dev = dev;
 	INIT_LIST_HEAD(&ring->active_list);
 	INIT_LIST_HEAD(&ring->request_list);
-	INIT_LIST_HEAD(&ring->gpu_write_list);
 
 	ring->size = size;
 	ring->effective_size = ring->size;
@@ -1574,3 +1649,41 @@ int intel_init_blt_ring_buffer(struct drm_device *dev)
 
 	return intel_init_ring_buffer(dev, ring);
 }
+
+int
+intel_ring_flush_all_caches(struct intel_ring_buffer *ring)
+{
+	int ret;
+
+	if (!ring->gpu_caches_dirty)
+		return 0;
+
+	ret = ring->flush(ring, 0, I915_GEM_GPU_DOMAINS);
+	if (ret)
+		return ret;
+
+	trace_i915_gem_ring_flush(ring, 0, I915_GEM_GPU_DOMAINS);
+
+	ring->gpu_caches_dirty = false;
+	return 0;
+}
+
+int
+intel_ring_invalidate_all_caches(struct intel_ring_buffer *ring)
+{
+	uint32_t flush_domains;
+	int ret;
+
+	flush_domains = 0;
+	if (ring->gpu_caches_dirty)
+		flush_domains = I915_GEM_GPU_DOMAINS;
+
+	ret = ring->flush(ring, I915_GEM_GPU_DOMAINS, flush_domains);
+	if (ret)
+		return ret;
+
+	trace_i915_gem_ring_flush(ring, I915_GEM_GPU_DOMAINS, flush_domains);
+
+	ring->gpu_caches_dirty = false;
+	return 0;
+}
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index 1d3c81f..2ea7a31 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -72,7 +72,14 @@ struct  intel_ring_buffer {
 				  u32	flush_domains);
 	int		(*add_request)(struct intel_ring_buffer *ring,
 				       u32 *seqno);
-	u32		(*get_seqno)(struct intel_ring_buffer *ring);
+	/* Some chipsets are not quite as coherent as advertised and need
+	 * an expensive kick to force a true read of the up-to-date seqno.
+	 * However, the up-to-date seqno is not always required and the last
+	 * seen value is good enough. Note that the seqno will always be
+	 * monotonic, even if not coherent.
+	 */
+	u32		(*get_seqno)(struct intel_ring_buffer *ring,
+				     bool lazy_coherency);
 	int		(*dispatch_execbuffer)(struct intel_ring_buffer *ring,
 					       u32 offset, u32 length);
 	void		(*cleanup)(struct intel_ring_buffer *ring);
@@ -101,15 +108,6 @@ struct  intel_ring_buffer {
 	struct list_head request_list;
 
 	/**
-	 * List of objects currently pending a GPU write flush.
-	 *
-	 * All elements on this list will belong to either the
-	 * active_list or flushing_list, last_rendering_seqno can
-	 * be used to differentiate between the two elements.
-	 */
-	struct list_head gpu_write_list;
-
-	/**
 	 * Do we have some not yet emitted requests outstanding?
 	 */
 	u32 outstanding_lazy_request;
@@ -204,6 +202,8 @@ static inline void intel_ring_emit(struct intel_ring_buffer *ring,
 void intel_ring_advance(struct intel_ring_buffer *ring);
 
 u32 intel_ring_get_seqno(struct intel_ring_buffer *ring);
+int intel_ring_flush_all_caches(struct intel_ring_buffer *ring);
+int intel_ring_invalidate_all_caches(struct intel_ring_buffer *ring);
 
 int intel_init_render_ring_buffer(struct drm_device *dev);
 int intel_init_bsd_ring_buffer(struct drm_device *dev);
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index 123afd3..39c3198 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -97,7 +97,7 @@ struct intel_sdvo {
 	/*
 	 * Hotplug activation bits for this device
 	 */
-	uint8_t hotplug_active[2];
+	uint16_t hotplug_active;
 
 	/**
 	 * This is used to select the color range of RBG outputs in HDMI mode.
@@ -628,6 +628,14 @@ static bool intel_sdvo_set_active_outputs(struct intel_sdvo *intel_sdvo,
 				    &outputs, sizeof(outputs));
 }
 
+static bool intel_sdvo_get_active_outputs(struct intel_sdvo *intel_sdvo,
+					  u16 *outputs)
+{
+	return intel_sdvo_get_value(intel_sdvo,
+				    SDVO_CMD_GET_ACTIVE_OUTPUTS,
+				    outputs, sizeof(*outputs));
+}
+
 static bool intel_sdvo_set_encoder_power_state(struct intel_sdvo *intel_sdvo,
 					       int mode)
 {
@@ -1142,51 +1150,132 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,
 	intel_sdvo_write_sdvox(intel_sdvo, sdvox);
 }
 
-static void intel_sdvo_dpms(struct drm_encoder *encoder, int mode)
+static bool intel_sdvo_connector_get_hw_state(struct intel_connector *connector)
 {
-	struct drm_device *dev = encoder->dev;
+	struct intel_sdvo_connector *intel_sdvo_connector =
+		to_intel_sdvo_connector(&connector->base);
+	struct intel_sdvo *intel_sdvo = intel_attached_sdvo(&connector->base);
+	u16 active_outputs;
+
+	intel_sdvo_get_active_outputs(intel_sdvo, &active_outputs);
+
+	if (active_outputs & intel_sdvo_connector->output_flag)
+		return true;
+	else
+		return false;
+}
+
+static bool intel_sdvo_get_hw_state(struct intel_encoder *encoder,
+				    enum pipe *pipe)
+{
+	struct drm_device *dev = encoder->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_sdvo *intel_sdvo = to_intel_sdvo(encoder);
-	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
+	struct intel_sdvo *intel_sdvo = to_intel_sdvo(&encoder->base);
+	u32 tmp;
+
+	tmp = I915_READ(intel_sdvo->sdvo_reg);
+
+	if (!(tmp & SDVO_ENABLE))
+		return false;
+
+	if (HAS_PCH_CPT(dev))
+		*pipe = PORT_TO_PIPE_CPT(tmp);
+	else
+		*pipe = PORT_TO_PIPE(tmp);
+
+	return true;
+}
+
+static void intel_disable_sdvo(struct intel_encoder *encoder)
+{
+	struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
+	struct intel_sdvo *intel_sdvo = to_intel_sdvo(&encoder->base);
+	u32 temp;
+
+	intel_sdvo_set_active_outputs(intel_sdvo, 0);
+	if (0)
+		intel_sdvo_set_encoder_power_state(intel_sdvo,
+						   DRM_MODE_DPMS_OFF);
+
+	temp = I915_READ(intel_sdvo->sdvo_reg);
+	if ((temp & SDVO_ENABLE) != 0) {
+		intel_sdvo_write_sdvox(intel_sdvo, temp & ~SDVO_ENABLE);
+	}
+}
+
+static void intel_enable_sdvo(struct intel_encoder *encoder)
+{
+	struct drm_device *dev = encoder->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_sdvo *intel_sdvo = to_intel_sdvo(&encoder->base);
+	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
 	u32 temp;
+	bool input1, input2;
+	int i;
+	u8 status;
+
+	temp = I915_READ(intel_sdvo->sdvo_reg);
+	if ((temp & SDVO_ENABLE) == 0)
+		intel_sdvo_write_sdvox(intel_sdvo, temp | SDVO_ENABLE);
+	for (i = 0; i < 2; i++)
+		intel_wait_for_vblank(dev, intel_crtc->pipe);
+
+	status = intel_sdvo_get_trained_inputs(intel_sdvo, &input1, &input2);
+	/* Warn if the device reported failure to sync.
+	 * A lot of SDVO devices fail to notify of sync, but it's
+	 * a given it the status is a success, we succeeded.
+	 */
+	if (status == SDVO_CMD_STATUS_SUCCESS && !input1) {
+		DRM_DEBUG_KMS("First %s output reported failure to "
+				"sync\n", SDVO_NAME(intel_sdvo));
+	}
+
+	if (0)
+		intel_sdvo_set_encoder_power_state(intel_sdvo,
+						   DRM_MODE_DPMS_ON);
+	intel_sdvo_set_active_outputs(intel_sdvo, intel_sdvo->attached_output);
+}
+
+static void intel_sdvo_dpms(struct drm_connector *connector, int mode)
+{
+	struct drm_crtc *crtc;
+	struct intel_sdvo *intel_sdvo = intel_attached_sdvo(connector);
+
+	/* dvo supports only 2 dpms states. */
+	if (mode != DRM_MODE_DPMS_ON)
+		mode = DRM_MODE_DPMS_OFF;
+
+	if (mode == connector->dpms)
+		return;
+
+	connector->dpms = mode;
+
+	/* Only need to change hw state when actually enabled */
+	crtc = intel_sdvo->base.base.crtc;
+	if (!crtc) {
+		intel_sdvo->base.connectors_active = false;
+		return;
+	}
 
 	if (mode != DRM_MODE_DPMS_ON) {
 		intel_sdvo_set_active_outputs(intel_sdvo, 0);
 		if (0)
 			intel_sdvo_set_encoder_power_state(intel_sdvo, mode);
 
-		if (mode == DRM_MODE_DPMS_OFF) {
-			temp = I915_READ(intel_sdvo->sdvo_reg);
-			if ((temp & SDVO_ENABLE) != 0) {
-				intel_sdvo_write_sdvox(intel_sdvo, temp & ~SDVO_ENABLE);
-			}
-		}
+		intel_sdvo->base.connectors_active = false;
+
+		intel_crtc_update_dpms(crtc);
 	} else {
-		bool input1, input2;
-		int i;
-		u8 status;
-
-		temp = I915_READ(intel_sdvo->sdvo_reg);
-		if ((temp & SDVO_ENABLE) == 0)
-			intel_sdvo_write_sdvox(intel_sdvo, temp | SDVO_ENABLE);
-		for (i = 0; i < 2; i++)
-			intel_wait_for_vblank(dev, intel_crtc->pipe);
-
-		status = intel_sdvo_get_trained_inputs(intel_sdvo, &input1, &input2);
-		/* Warn if the device reported failure to sync.
-		 * A lot of SDVO devices fail to notify of sync, but it's
-		 * a given it the status is a success, we succeeded.
-		 */
-		if (status == SDVO_CMD_STATUS_SUCCESS && !input1) {
-			DRM_DEBUG_KMS("First %s output reported failure to "
-					"sync\n", SDVO_NAME(intel_sdvo));
-		}
+		intel_sdvo->base.connectors_active = true;
+
+		intel_crtc_update_dpms(crtc);
 
 		if (0)
 			intel_sdvo_set_encoder_power_state(intel_sdvo, mode);
 		intel_sdvo_set_active_outputs(intel_sdvo, intel_sdvo->attached_output);
 	}
-	return;
+
+	intel_modeset_check_state(connector->dev);
 }
 
 static int intel_sdvo_mode_valid(struct drm_connector *connector,
@@ -1251,25 +1340,29 @@ static bool intel_sdvo_get_capabilities(struct intel_sdvo *intel_sdvo, struct in
 	return true;
 }
 
-static int intel_sdvo_supports_hotplug(struct intel_sdvo *intel_sdvo)
+static uint16_t intel_sdvo_get_hotplug_support(struct intel_sdvo *intel_sdvo)
 {
 	struct drm_device *dev = intel_sdvo->base.base.dev;
-	u8 response[2];
+	uint16_t hotplug;
 
 	/* HW Erratum: SDVO Hotplug is broken on all i945G chips, there's noise
 	 * on the line. */
 	if (IS_I945G(dev) || IS_I945GM(dev))
-		return false;
+		return 0;
 
-	return intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_HOT_PLUG_SUPPORT,
-				    &response, 2) && response[0];
+	if (!intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_HOT_PLUG_SUPPORT,
+					&hotplug, sizeof(hotplug)))
+		return 0;
+
+	return hotplug;
 }
 
 static void intel_sdvo_enable_hotplug(struct intel_encoder *encoder)
 {
 	struct intel_sdvo *intel_sdvo = to_intel_sdvo(&encoder->base);
 
-	intel_sdvo_write_cmd(intel_sdvo, SDVO_CMD_SET_ACTIVE_HOT_PLUG, &intel_sdvo->hotplug_active, 2);
+	intel_sdvo_write_cmd(intel_sdvo, SDVO_CMD_SET_ACTIVE_HOT_PLUG,
+			&intel_sdvo->hotplug_active, 2);
 }
 
 static bool
@@ -1345,7 +1438,6 @@ intel_sdvo_tmds_sink_detect(struct drm_connector *connector)
 			}
 		} else
 			status = connector_status_disconnected;
-		connector->display_info.raw_edid = NULL;
 		kfree(edid);
 	}
 
@@ -1419,7 +1511,6 @@ intel_sdvo_detect(struct drm_connector *connector, bool force)
 			else
 				ret = connector_status_disconnected;
 
-			connector->display_info.raw_edid = NULL;
 			kfree(edid);
 		} else
 			ret = connector_status_connected;
@@ -1465,7 +1556,6 @@ static void intel_sdvo_get_ddc_modes(struct drm_connector *connector)
 			drm_add_edid_modes(connector, edid);
 		}
 
-		connector->display_info.raw_edid = NULL;
 		kfree(edid);
 	}
 }
@@ -1837,8 +1927,8 @@ set_value:
 done:
 	if (intel_sdvo->base.base.crtc) {
 		struct drm_crtc *crtc = intel_sdvo->base.base.crtc;
-		drm_crtc_helper_set_mode(crtc, &crtc->mode, crtc->x,
-					 crtc->y, crtc->fb);
+		intel_set_mode(crtc, &crtc->mode,
+			       crtc->x, crtc->y, crtc->fb);
 	}
 
 	return 0;
@@ -1846,15 +1936,13 @@ done:
 }
 
 static const struct drm_encoder_helper_funcs intel_sdvo_helper_funcs = {
-	.dpms = intel_sdvo_dpms,
 	.mode_fixup = intel_sdvo_mode_fixup,
-	.prepare = intel_encoder_prepare,
 	.mode_set = intel_sdvo_mode_set,
-	.commit = intel_encoder_commit,
+	.disable = intel_encoder_noop,
 };
 
 static const struct drm_connector_funcs intel_sdvo_connector_funcs = {
-	.dpms = drm_helper_connector_dpms,
+	.dpms = intel_sdvo_dpms,
 	.detect = intel_sdvo_detect,
 	.fill_modes = drm_helper_probe_single_connector_modes,
 	.set_property = intel_sdvo_set_property,
@@ -2026,6 +2114,7 @@ intel_sdvo_connector_init(struct intel_sdvo_connector *connector,
 	connector->base.base.interlace_allowed = 1;
 	connector->base.base.doublescan_allowed = 0;
 	connector->base.base.display_info.subpixel_order = SubPixelHorizontalRGB;
+	connector->base.get_hw_state = intel_sdvo_connector_get_hw_state;
 
 	intel_connector_attach_encoder(&connector->base, &encoder->base);
 	drm_sysfs_connector_add(&connector->base.base);
@@ -2064,17 +2153,18 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device)
 
 	intel_connector = &intel_sdvo_connector->base;
 	connector = &intel_connector->base;
-	if (intel_sdvo_supports_hotplug(intel_sdvo) & (1 << device)) {
+	if (intel_sdvo_get_hotplug_support(intel_sdvo) &
+		intel_sdvo_connector->output_flag) {
 		connector->polled = DRM_CONNECTOR_POLL_HPD;
-		intel_sdvo->hotplug_active[0] |= 1 << device;
+		intel_sdvo->hotplug_active |= intel_sdvo_connector->output_flag;
 		/* Some SDVO devices have one-shot hotplug interrupts.
 		 * Ensure that they get re-enabled when an interrupt happens.
 		 */
 		intel_encoder->hot_plug = intel_sdvo_enable_hotplug;
 		intel_sdvo_enable_hotplug(intel_encoder);
-	}
-	else
+	} else {
 		connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT;
+	}
 	encoder->encoder_type = DRM_MODE_ENCODER_TMDS;
 	connector->connector_type = DRM_MODE_CONNECTOR_DVID;
 
@@ -2082,8 +2172,7 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device)
 		connector->connector_type = DRM_MODE_CONNECTOR_HDMIA;
 		intel_sdvo->is_hdmi = true;
 	}
-	intel_sdvo->base.clone_mask = ((1 << INTEL_SDVO_NON_TV_CLONE_BIT) |
-				       (1 << INTEL_ANALOG_CLONE_BIT));
+	intel_sdvo->base.cloneable = true;
 
 	intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo);
 	if (intel_sdvo->is_hdmi)
@@ -2114,7 +2203,7 @@ intel_sdvo_tv_init(struct intel_sdvo *intel_sdvo, int type)
 
 	intel_sdvo->is_tv = true;
 	intel_sdvo->base.needs_tv_clock = true;
-	intel_sdvo->base.clone_mask = 1 << INTEL_SDVO_TV_CLONE_BIT;
+	intel_sdvo->base.cloneable = false;
 
 	intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo);
 
@@ -2157,8 +2246,7 @@ intel_sdvo_analog_init(struct intel_sdvo *intel_sdvo, int device)
 		intel_sdvo_connector->output_flag = SDVO_OUTPUT_RGB1;
 	}
 
-	intel_sdvo->base.clone_mask = ((1 << INTEL_SDVO_NON_TV_CLONE_BIT) |
-				       (1 << INTEL_ANALOG_CLONE_BIT));
+	intel_sdvo->base.cloneable = true;
 
 	intel_sdvo_connector_init(intel_sdvo_connector,
 				  intel_sdvo);
@@ -2190,8 +2278,10 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device)
 		intel_sdvo_connector->output_flag = SDVO_OUTPUT_LVDS1;
 	}
 
-	intel_sdvo->base.clone_mask = ((1 << INTEL_ANALOG_CLONE_BIT) |
-				       (1 << INTEL_SDVO_LVDS_CLONE_BIT));
+	/* SDVO LVDS is cloneable because the SDVO encoder does the upscaling,
+	 * as opposed to native LVDS, where we upscale with the panel-fitter
+	 * (and hence only the native LVDS resolution could be cloned). */
+	intel_sdvo->base.cloneable = true;
 
 	intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo);
 	if (!intel_sdvo_create_enhance_property(intel_sdvo, intel_sdvo_connector))
@@ -2576,6 +2666,10 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob)
 
 	drm_encoder_helper_add(&intel_encoder->base, &intel_sdvo_helper_funcs);
 
+	intel_encoder->disable = intel_disable_sdvo;
+	intel_encoder->enable = intel_enable_sdvo;
+	intel_encoder->get_hw_state = intel_sdvo_get_hw_state;
+
 	/* In default case sdvo lvds is false */
 	if (!intel_sdvo_get_capabilities(intel_sdvo, &intel_sdvo->caps))
 		goto err;
@@ -2590,7 +2684,7 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob)
 	/* Only enable the hotplug irq if we need it, to work around noisy
 	 * hotplug lines.
 	 */
-	if (intel_sdvo->hotplug_active[0])
+	if (intel_sdvo->hotplug_active)
 		dev_priv->hotplug_supported_mask |= hotplug_mask;
 
 	intel_sdvo_select_ddc_bus(dev_priv, intel_sdvo, sdvo_reg);
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c
index befce6c..d2c5c8f 100644
--- a/drivers/gpu/drm/i915/intel_tv.c
+++ b/drivers/gpu/drm/i915/intel_tv.c
@@ -836,22 +836,37 @@ static struct intel_tv *intel_attached_tv(struct drm_connector *connector)
 			    base);
 }
 
+static bool
+intel_tv_get_hw_state(struct intel_encoder *encoder, enum pipe *pipe)
+{
+	struct drm_device *dev = encoder->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 tmp = I915_READ(TV_CTL);
+
+	if (!(tmp & TV_ENC_ENABLE))
+		return false;
+
+	*pipe = PORT_TO_PIPE(tmp);
+
+	return true;
+}
+
 static void
-intel_tv_dpms(struct drm_encoder *encoder, int mode)
+intel_enable_tv(struct intel_encoder *encoder)
 {
-	struct drm_device *dev = encoder->dev;
+	struct drm_device *dev = encoder->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	switch (mode) {
-	case DRM_MODE_DPMS_ON:
-		I915_WRITE(TV_CTL, I915_READ(TV_CTL) | TV_ENC_ENABLE);
-		break;
-	case DRM_MODE_DPMS_STANDBY:
-	case DRM_MODE_DPMS_SUSPEND:
-	case DRM_MODE_DPMS_OFF:
-		I915_WRITE(TV_CTL, I915_READ(TV_CTL) & ~TV_ENC_ENABLE);
-		break;
-	}
+	I915_WRITE(TV_CTL, I915_READ(TV_CTL) | TV_ENC_ENABLE);
+}
+
+static void
+intel_disable_tv(struct intel_encoder *encoder)
+{
+	struct drm_device *dev = encoder->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	I915_WRITE(TV_CTL, I915_READ(TV_CTL) & ~TV_ENC_ENABLE);
 }
 
 static const struct tv_mode *
@@ -895,17 +910,14 @@ intel_tv_mode_fixup(struct drm_encoder *encoder,
 		    const struct drm_display_mode *mode,
 		    struct drm_display_mode *adjusted_mode)
 {
-	struct drm_device *dev = encoder->dev;
 	struct intel_tv *intel_tv = enc_to_intel_tv(encoder);
 	const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv);
-	struct intel_encoder *other_encoder;
 
 	if (!tv_mode)
 		return false;
 
-	for_each_encoder_on_crtc(dev, encoder->crtc, other_encoder)
-		if (&other_encoder->base != encoder)
-			return false;
+	if (intel_encoder_check_is_cloned(&intel_tv->base))
+		return false;
 
 	adjusted_mode->clock = tv_mode->clock;
 	return true;
@@ -1303,12 +1315,9 @@ intel_tv_detect(struct drm_connector *connector, bool force)
 	if (force) {
 		struct intel_load_detect_pipe tmp;
 
-		if (intel_get_load_detect_pipe(&intel_tv->base, connector,
-					       &mode, &tmp)) {
+		if (intel_get_load_detect_pipe(connector, &mode, &tmp)) {
 			type = intel_tv_detect_type(intel_tv, connector);
-			intel_release_load_detect_pipe(&intel_tv->base,
-						       connector,
-						       &tmp);
+			intel_release_load_detect_pipe(connector, &tmp);
 		} else
 			return connector_status_unknown;
 	} else
@@ -1474,22 +1483,20 @@ intel_tv_set_property(struct drm_connector *connector, struct drm_property *prop
 	}
 
 	if (changed && crtc)
-		drm_crtc_helper_set_mode(crtc, &crtc->mode, crtc->x,
-				crtc->y, crtc->fb);
+		intel_set_mode(crtc, &crtc->mode,
+			       crtc->x, crtc->y, crtc->fb);
 out:
 	return ret;
 }
 
 static const struct drm_encoder_helper_funcs intel_tv_helper_funcs = {
-	.dpms = intel_tv_dpms,
 	.mode_fixup = intel_tv_mode_fixup,
-	.prepare = intel_encoder_prepare,
 	.mode_set = intel_tv_mode_set,
-	.commit = intel_encoder_commit,
+	.disable = intel_encoder_noop,
 };
 
 static const struct drm_connector_funcs intel_tv_connector_funcs = {
-	.dpms = drm_helper_connector_dpms,
+	.dpms = intel_connector_dpms,
 	.detect = intel_tv_detect,
 	.destroy = intel_tv_destroy,
 	.set_property = intel_tv_set_property,
@@ -1619,10 +1626,15 @@ intel_tv_init(struct drm_device *dev)
 	drm_encoder_init(dev, &intel_encoder->base, &intel_tv_enc_funcs,
 			 DRM_MODE_ENCODER_TVDAC);
 
+	intel_encoder->enable = intel_enable_tv;
+	intel_encoder->disable = intel_disable_tv;
+	intel_encoder->get_hw_state = intel_tv_get_hw_state;
+	intel_connector->get_hw_state = intel_connector_get_hw_state;
+
 	intel_connector_attach_encoder(intel_connector, intel_encoder);
 	intel_encoder->type = INTEL_OUTPUT_TVOUT;
 	intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
-	intel_encoder->clone_mask = (1 << INTEL_TV_CLONE_BIT);
+	intel_encoder->cloneable = false;
 	intel_encoder->base.possible_crtcs = ((1 << 0) | (1 << 1));
 	intel_encoder->base.possible_clones = (1 << INTEL_OUTPUT_TVOUT);
 	intel_tv->type = DRM_MODE_CONNECTOR_Unknown;
diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h
index 6f13b35..d22cbbf 100644
--- a/drivers/gpu/drm/mgag200/mgag200_drv.h
+++ b/drivers/gpu/drm/mgag200/mgag200_drv.h
@@ -195,7 +195,6 @@ struct mga_device {
 		struct drm_global_reference mem_global_ref;
 		struct ttm_bo_global_ref bo_global_ref;
 		struct ttm_bo_device bdev;
-		atomic_t validate_sequence;
 	} ttm;
 
 	u32 reg_1e24; /* SE model number */
diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c
index b69642d..c7420e8 100644
--- a/drivers/gpu/drm/mgag200/mgag200_mode.c
+++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
@@ -1399,7 +1399,6 @@ static int mga_vga_get_modes(struct drm_connector *connector)
 	if (edid) {
 		drm_mode_connector_update_edid_property(connector, edid);
 		ret = drm_add_edid_modes(connector, edid);
-		connector->display_info.raw_edid = NULL;
 		kfree(edid);
 	}
 	return ret;
diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c
index 7e289d2..e754aa3 100644
--- a/drivers/gpu/drm/nouveau/nouveau_dp.c
+++ b/drivers/gpu/drm/nouveau/nouveau_dp.c
@@ -289,9 +289,7 @@ dp_link_train_update(struct drm_device *dev, struct dp_state *dp, u32 delay)
 	if (ret)
 		return ret;
 
-	NV_DEBUG_KMS(dev, "status %02x %02x %02x %02x %02x %02x\n",
-		     dp->stat[0], dp->stat[1], dp->stat[2], dp->stat[3],
-		     dp->stat[4], dp->stat[5]);
+	NV_DEBUG_KMS(dev, "status %*ph\n", 6, dp->stat);
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/nouveau/nouveau_gpio.c b/drivers/gpu/drm/nouveau/nouveau_gpio.c
index 82c19e8..0fe4e17 100644
--- a/drivers/gpu/drm/nouveau/nouveau_gpio.c
+++ b/drivers/gpu/drm/nouveau/nouveau_gpio.c
@@ -302,7 +302,7 @@ nouveau_gpio_isr_del(struct drm_device *dev, int idx, u8 tag, u8 line,
 		spin_unlock_irqrestore(&pgpio->lock, flags);
 
 		list_for_each_entry_safe(isr, tmp, &tofree, head) {
-			flush_work_sync(&isr->work);
+			flush_work(&isr->work);
 			kfree(isr);
 		}
 	}
diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c
index 3623b98..d48224b 100644
--- a/drivers/gpu/drm/radeon/atombios_dp.c
+++ b/drivers/gpu/drm/radeon/atombios_dp.c
@@ -653,9 +653,7 @@ static bool radeon_dp_get_link_status(struct radeon_connector *radeon_connector,
 		return false;
 	}
 
-	DRM_DEBUG_KMS("link status %02x %02x %02x %02x %02x %02x\n",
-		  link_status[0], link_status[1], link_status[2],
-		  link_status[3], link_status[4], link_status[5]);
+	DRM_DEBUG_KMS("link status %*ph\n", 6, link_status);
 	return true;
 }
 
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
index e93b80a..ed3340a 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -77,13 +77,9 @@ void evergreen_tiling_fields(unsigned tiling_flags, unsigned *bankw,
 void evergreen_fix_pci_max_read_req_size(struct radeon_device *rdev)
 {
 	u16 ctl, v;
-	int cap, err;
+	int err;
 
-	cap = pci_pcie_cap(rdev->pdev);
-	if (!cap)
-		return;
-
-	err = pci_read_config_word(rdev->pdev, cap + PCI_EXP_DEVCTL, &ctl);
+	err = pcie_capability_read_word(rdev->pdev, PCI_EXP_DEVCTL, &ctl);
 	if (err)
 		return;
 
@@ -95,7 +91,7 @@ void evergreen_fix_pci_max_read_req_size(struct radeon_device *rdev)
 	if ((v == 0) || (v == 6) || (v == 7)) {
 		ctl &= ~PCI_EXP_DEVCTL_READRQ;
 		ctl |= (2 << 12);
-		pci_write_config_word(rdev->pdev, cap + PCI_EXP_DEVCTL, ctl);
+		pcie_capability_write_word(rdev->pdev, PCI_EXP_DEVCTL, ctl);
 	}
 }
 
diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c b/drivers/gpu/drm/radeon/radeon_irq_kms.c
index afaa172..50b596e 100644
--- a/drivers/gpu/drm/radeon/radeon_irq_kms.c
+++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c
@@ -277,7 +277,7 @@ void radeon_irq_kms_fini(struct radeon_device *rdev)
 		if (rdev->msi_enabled)
 			pci_disable_msi(rdev->pdev);
 	}
-	flush_work_sync(&rdev->hotplug_work);
+	flush_work(&rdev->hotplug_work);
 }
 
 /**
diff --git a/drivers/gpu/drm/shmobile/Kconfig b/drivers/gpu/drm/shmobile/Kconfig
new file mode 100644
index 0000000..7e7d52b
--- /dev/null
+++ b/drivers/gpu/drm/shmobile/Kconfig
@@ -0,0 +1,10 @@
+config DRM_SHMOBILE
+	tristate "DRM Support for SH Mobile"
+	depends on DRM && (SUPERH || ARCH_SHMOBILE)
+	select DRM_KMS_HELPER
+	select DRM_KMS_CMA_HELPER
+	select DRM_GEM_CMA_HELPER
+	help
+	  Choose this option if you have an SH Mobile chipset.
+	  If M is selected the module will be called shmob-drm.
+
diff --git a/drivers/gpu/drm/shmobile/Makefile b/drivers/gpu/drm/shmobile/Makefile
new file mode 100644
index 0000000..4c3eeb3
--- /dev/null
+++ b/drivers/gpu/drm/shmobile/Makefile
@@ -0,0 +1,7 @@
+shmob-drm-y := shmob_drm_backlight.o \
+	       shmob_drm_crtc.o \
+	       shmob_drm_drv.o \
+	       shmob_drm_kms.o \
+	       shmob_drm_plane.o
+
+obj-$(CONFIG_DRM_SHMOBILE)	+= shmob-drm.o
diff --git a/drivers/gpu/drm/shmobile/shmob_drm_backlight.c b/drivers/gpu/drm/shmobile/shmob_drm_backlight.c
new file mode 100644
index 0000000..463aee1
--- /dev/null
+++ b/drivers/gpu/drm/shmobile/shmob_drm_backlight.c
@@ -0,0 +1,90 @@
+/*
+ * shmob_drm_backlight.c  --  SH Mobile DRM Backlight
+ *
+ * Copyright (C) 2012 Renesas Corporation
+ *
+ * Laurent Pinchart (laurent.pinchart@ideasonboard.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/backlight.h>
+
+#include "shmob_drm_backlight.h"
+#include "shmob_drm_crtc.h"
+#include "shmob_drm_drv.h"
+
+static int shmob_drm_backlight_update(struct backlight_device *bdev)
+{
+	struct shmob_drm_connector *scon = bl_get_data(bdev);
+	struct shmob_drm_device *sdev = scon->connector.dev->dev_private;
+	const struct shmob_drm_backlight_data *bdata = &sdev->pdata->backlight;
+	int brightness = bdev->props.brightness;
+
+	if (bdev->props.power != FB_BLANK_UNBLANK ||
+	    bdev->props.state & BL_CORE_SUSPENDED)
+		brightness = 0;
+
+	return bdata->set_brightness(brightness);
+}
+
+static int shmob_drm_backlight_get_brightness(struct backlight_device *bdev)
+{
+	struct shmob_drm_connector *scon = bl_get_data(bdev);
+	struct shmob_drm_device *sdev = scon->connector.dev->dev_private;
+	const struct shmob_drm_backlight_data *bdata = &sdev->pdata->backlight;
+
+	return bdata->get_brightness();
+}
+
+static const struct backlight_ops shmob_drm_backlight_ops = {
+	.options	= BL_CORE_SUSPENDRESUME,
+	.update_status	= shmob_drm_backlight_update,
+	.get_brightness	= shmob_drm_backlight_get_brightness,
+};
+
+void shmob_drm_backlight_dpms(struct shmob_drm_connector *scon, int mode)
+{
+	if (scon->backlight == NULL)
+		return;
+
+	scon->backlight->props.power = mode == DRM_MODE_DPMS_ON
+				     ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
+	backlight_update_status(scon->backlight);
+}
+
+int shmob_drm_backlight_init(struct shmob_drm_connector *scon)
+{
+	struct shmob_drm_device *sdev = scon->connector.dev->dev_private;
+	const struct shmob_drm_backlight_data *bdata = &sdev->pdata->backlight;
+	struct drm_connector *connector = &scon->connector;
+	struct drm_device *dev = connector->dev;
+	struct backlight_device *backlight;
+
+	if (!bdata->max_brightness)
+		return 0;
+
+	backlight = backlight_device_register(bdata->name, dev->dev, scon,
+					      &shmob_drm_backlight_ops, NULL);
+	if (IS_ERR(backlight)) {
+		dev_err(dev->dev, "unable to register backlight device: %ld\n",
+			PTR_ERR(backlight));
+		return PTR_ERR(backlight);
+	}
+
+	backlight->props.max_brightness = bdata->max_brightness;
+	backlight->props.brightness = bdata->max_brightness;
+	backlight->props.power = FB_BLANK_POWERDOWN;
+	backlight_update_status(backlight);
+
+	scon->backlight = backlight;
+	return 0;
+}
+
+void shmob_drm_backlight_exit(struct shmob_drm_connector *scon)
+{
+	backlight_device_unregister(scon->backlight);
+}
diff --git a/drivers/gpu/drm/shmobile/shmob_drm_backlight.h b/drivers/gpu/drm/shmobile/shmob_drm_backlight.h
new file mode 100644
index 0000000..9477595
--- /dev/null
+++ b/drivers/gpu/drm/shmobile/shmob_drm_backlight.h
@@ -0,0 +1,23 @@
+/*
+ * shmob_drm_backlight.h  --  SH Mobile DRM Backlight
+ *
+ * Copyright (C) 2012 Renesas Corporation
+ *
+ * Laurent Pinchart (laurent.pinchart@ideasonboard.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __SHMOB_DRM_BACKLIGHT_H__
+#define __SHMOB_DRM_BACKLIGHT_H__
+
+struct shmob_drm_connector;
+
+void shmob_drm_backlight_dpms(struct shmob_drm_connector *scon, int mode);
+int shmob_drm_backlight_init(struct shmob_drm_connector *scon);
+void shmob_drm_backlight_exit(struct shmob_drm_connector *scon);
+
+#endif /* __SHMOB_DRM_BACKLIGHT_H__ */
diff --git a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c
new file mode 100644
index 0000000..0e7a930
--- /dev/null
+++ b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c
@@ -0,0 +1,763 @@
+/*
+ * shmob_drm_crtc.c  --  SH Mobile DRM CRTCs
+ *
+ * Copyright (C) 2012 Renesas Corporation
+ *
+ * Laurent Pinchart (laurent.pinchart@ideasonboard.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/backlight.h>
+#include <linux/clk.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+
+#include <video/sh_mobile_meram.h>
+
+#include "shmob_drm_backlight.h"
+#include "shmob_drm_crtc.h"
+#include "shmob_drm_drv.h"
+#include "shmob_drm_kms.h"
+#include "shmob_drm_plane.h"
+#include "shmob_drm_regs.h"
+
+/*
+ * TODO: panel support
+ */
+
+/* -----------------------------------------------------------------------------
+ * Clock management
+ */
+
+static void shmob_drm_clk_on(struct shmob_drm_device *sdev)
+{
+	if (sdev->clock)
+		clk_enable(sdev->clock);
+#if 0
+	if (sdev->meram_dev && sdev->meram_dev->pdev)
+		pm_runtime_get_sync(&sdev->meram_dev->pdev->dev);
+#endif
+}
+
+static void shmob_drm_clk_off(struct shmob_drm_device *sdev)
+{
+#if 0
+	if (sdev->meram_dev && sdev->meram_dev->pdev)
+		pm_runtime_put_sync(&sdev->meram_dev->pdev->dev);
+#endif
+	if (sdev->clock)
+		clk_disable(sdev->clock);
+}
+
+/* -----------------------------------------------------------------------------
+ * CRTC
+ */
+
+static void shmob_drm_crtc_setup_geometry(struct shmob_drm_crtc *scrtc)
+{
+	struct drm_crtc *crtc = &scrtc->crtc;
+	struct shmob_drm_device *sdev = crtc->dev->dev_private;
+	const struct shmob_drm_interface_data *idata = &sdev->pdata->iface;
+	const struct drm_display_mode *mode = &crtc->mode;
+	u32 value;
+
+	value = sdev->ldmt1r
+	      | ((mode->flags & DRM_MODE_FLAG_PVSYNC) ? 0 : LDMT1R_VPOL)
+	      | ((mode->flags & DRM_MODE_FLAG_PHSYNC) ? 0 : LDMT1R_HPOL)
+	      | ((idata->flags & SHMOB_DRM_IFACE_FL_DWPOL) ? LDMT1R_DWPOL : 0)
+	      | ((idata->flags & SHMOB_DRM_IFACE_FL_DIPOL) ? LDMT1R_DIPOL : 0)
+	      | ((idata->flags & SHMOB_DRM_IFACE_FL_DAPOL) ? LDMT1R_DAPOL : 0)
+	      | ((idata->flags & SHMOB_DRM_IFACE_FL_HSCNT) ? LDMT1R_HSCNT : 0)
+	      | ((idata->flags & SHMOB_DRM_IFACE_FL_DWCNT) ? LDMT1R_DWCNT : 0);
+	lcdc_write(sdev, LDMT1R, value);
+
+	if (idata->interface >= SHMOB_DRM_IFACE_SYS8A &&
+	    idata->interface <= SHMOB_DRM_IFACE_SYS24) {
+		/* Setup SYS bus. */
+		value = (idata->sys.cs_setup << LDMT2R_CSUP_SHIFT)
+		      | (idata->sys.vsync_active_high ? LDMT2R_RSV : 0)
+		      | (idata->sys.vsync_dir_input ? LDMT2R_VSEL : 0)
+		      | (idata->sys.write_setup << LDMT2R_WCSC_SHIFT)
+		      | (idata->sys.write_cycle << LDMT2R_WCEC_SHIFT)
+		      | (idata->sys.write_strobe << LDMT2R_WCLW_SHIFT);
+		lcdc_write(sdev, LDMT2R, value);
+
+		value = (idata->sys.read_latch << LDMT3R_RDLC_SHIFT)
+		      | (idata->sys.read_setup << LDMT3R_RCSC_SHIFT)
+		      | (idata->sys.read_cycle << LDMT3R_RCEC_SHIFT)
+		      | (idata->sys.read_strobe << LDMT3R_RCLW_SHIFT);
+		lcdc_write(sdev, LDMT3R, value);
+	}
+
+	value = ((mode->hdisplay / 8) << 16)			/* HDCN */
+	      | (mode->htotal / 8);				/* HTCN */
+	lcdc_write(sdev, LDHCNR, value);
+
+	value = (((mode->hsync_end - mode->hsync_start) / 8) << 16) /* HSYNW */
+	      | (mode->hsync_start / 8);			/* HSYNP */
+	lcdc_write(sdev, LDHSYNR, value);
+
+	value = ((mode->hdisplay & 7) << 24) | ((mode->htotal & 7) << 16)
+	      | (((mode->hsync_end - mode->hsync_start) & 7) << 8)
+	      | (mode->hsync_start & 7);
+	lcdc_write(sdev, LDHAJR, value);
+
+	value = ((mode->vdisplay) << 16)			/* VDLN */
+	      | mode->vtotal;					/* VTLN */
+	lcdc_write(sdev, LDVLNR, value);
+
+	value = ((mode->vsync_end - mode->vsync_start) << 16)	/* VSYNW */
+	      | mode->vsync_start;				/* VSYNP */
+	lcdc_write(sdev, LDVSYNR, value);
+}
+
+static void shmob_drm_crtc_start_stop(struct shmob_drm_crtc *scrtc, bool start)
+{
+	struct shmob_drm_device *sdev = scrtc->crtc.dev->dev_private;
+	u32 value;
+
+	value = lcdc_read(sdev, LDCNT2R);
+	if (start)
+		lcdc_write(sdev, LDCNT2R, value | LDCNT2R_DO);
+	else
+		lcdc_write(sdev, LDCNT2R, value & ~LDCNT2R_DO);
+
+	/* Wait until power is applied/stopped. */
+	while (1) {
+		value = lcdc_read(sdev, LDPMR) & LDPMR_LPS;
+		if ((start && value) || (!start && !value))
+			break;
+
+		cpu_relax();
+	}
+
+	if (!start) {
+		/* Stop the dot clock. */
+		lcdc_write(sdev, LDDCKSTPR, LDDCKSTPR_DCKSTP);
+	}
+}
+
+/*
+ * shmob_drm_crtc_start - Configure and start the LCDC
+ * @scrtc: the SH Mobile CRTC
+ *
+ * Configure and start the LCDC device. External devices (clocks, MERAM, panels,
+ * ...) are not touched by this function.
+ */
+static void shmob_drm_crtc_start(struct shmob_drm_crtc *scrtc)
+{
+	struct drm_crtc *crtc = &scrtc->crtc;
+	struct shmob_drm_device *sdev = crtc->dev->dev_private;
+	const struct shmob_drm_interface_data *idata = &sdev->pdata->iface;
+	const struct shmob_drm_format_info *format;
+	struct drm_device *dev = sdev->ddev;
+	struct drm_plane *plane;
+	u32 value;
+
+	if (scrtc->started)
+		return;
+
+	format = shmob_drm_format_info(crtc->fb->pixel_format);
+	if (WARN_ON(format == NULL))
+		return;
+
+	/* Enable clocks before accessing the hardware. */
+	shmob_drm_clk_on(sdev);
+
+	/* Reset and enable the LCDC. */
+	lcdc_write(sdev, LDCNT2R, lcdc_read(sdev, LDCNT2R) | LDCNT2R_BR);
+	lcdc_wait_bit(sdev, LDCNT2R, LDCNT2R_BR, 0);
+	lcdc_write(sdev, LDCNT2R, LDCNT2R_ME);
+
+	/* Stop the LCDC first and disable all interrupts. */
+	shmob_drm_crtc_start_stop(scrtc, false);
+	lcdc_write(sdev, LDINTR, 0);
+
+	/* Configure power supply, dot clocks and start them. */
+	lcdc_write(sdev, LDPMR, 0);
+
+	value = sdev->lddckr;
+	if (idata->clk_div) {
+		/* FIXME: sh7724 can only use 42, 48, 54 and 60 for the divider
+		 * denominator.
+		 */
+		lcdc_write(sdev, LDDCKPAT1R, 0);
+		lcdc_write(sdev, LDDCKPAT2R, (1 << (idata->clk_div / 2)) - 1);
+
+		if (idata->clk_div == 1)
+			value |= LDDCKR_MOSEL;
+		else
+			value |= idata->clk_div;
+	}
+
+	lcdc_write(sdev, LDDCKR, value);
+	lcdc_write(sdev, LDDCKSTPR, 0);
+	lcdc_wait_bit(sdev, LDDCKSTPR, ~0, 0);
+
+	/* TODO: Setup SYS panel */
+
+	/* Setup geometry, format, frame buffer memory and operation mode. */
+	shmob_drm_crtc_setup_geometry(scrtc);
+
+	/* TODO: Handle YUV colorspaces. Hardcode REC709 for now. */
+	lcdc_write(sdev, LDDFR, format->lddfr | LDDFR_CF1);
+	lcdc_write(sdev, LDMLSR, scrtc->line_size);
+	lcdc_write(sdev, LDSA1R, scrtc->dma[0]);
+	if (format->yuv)
+		lcdc_write(sdev, LDSA2R, scrtc->dma[1]);
+	lcdc_write(sdev, LDSM1R, 0);
+
+	/* Word and long word swap. */
+	switch (format->fourcc) {
+	case DRM_FORMAT_RGB565:
+	case DRM_FORMAT_NV21:
+	case DRM_FORMAT_NV61:
+	case DRM_FORMAT_NV42:
+		value = LDDDSR_LS | LDDDSR_WS;
+		break;
+	case DRM_FORMAT_RGB888:
+	case DRM_FORMAT_NV12:
+	case DRM_FORMAT_NV16:
+	case DRM_FORMAT_NV24:
+		value = LDDDSR_LS | LDDDSR_WS | LDDDSR_BS;
+		break;
+	case DRM_FORMAT_ARGB8888:
+	default:
+		value = LDDDSR_LS;
+		break;
+	}
+	lcdc_write(sdev, LDDDSR, value);
+
+	/* Setup planes. */
+	list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
+		if (plane->crtc == crtc)
+			shmob_drm_plane_setup(plane);
+	}
+
+	/* Enable the display output. */
+	lcdc_write(sdev, LDCNT1R, LDCNT1R_DE);
+
+	shmob_drm_crtc_start_stop(scrtc, true);
+
+	scrtc->started = true;
+}
+
+static void shmob_drm_crtc_stop(struct shmob_drm_crtc *scrtc)
+{
+	struct drm_crtc *crtc = &scrtc->crtc;
+	struct shmob_drm_device *sdev = crtc->dev->dev_private;
+
+	if (!scrtc->started)
+		return;
+
+	/* Disable the MERAM cache. */
+	if (scrtc->cache) {
+		sh_mobile_meram_cache_free(sdev->meram, scrtc->cache);
+		scrtc->cache = NULL;
+	}
+
+	/* Stop the LCDC. */
+	shmob_drm_crtc_start_stop(scrtc, false);
+
+	/* Disable the display output. */
+	lcdc_write(sdev, LDCNT1R, 0);
+
+	/* Stop clocks. */
+	shmob_drm_clk_off(sdev);
+
+	scrtc->started = false;
+}
+
+void shmob_drm_crtc_suspend(struct shmob_drm_crtc *scrtc)
+{
+	shmob_drm_crtc_stop(scrtc);
+}
+
+void shmob_drm_crtc_resume(struct shmob_drm_crtc *scrtc)
+{
+	if (scrtc->dpms != DRM_MODE_DPMS_ON)
+		return;
+
+	shmob_drm_crtc_start(scrtc);
+}
+
+static void shmob_drm_crtc_compute_base(struct shmob_drm_crtc *scrtc,
+					int x, int y)
+{
+	struct drm_crtc *crtc = &scrtc->crtc;
+	struct drm_framebuffer *fb = crtc->fb;
+	struct shmob_drm_device *sdev = crtc->dev->dev_private;
+	struct drm_gem_cma_object *gem;
+	unsigned int bpp;
+
+	bpp = scrtc->format->yuv ? 8 : scrtc->format->bpp;
+	gem = drm_fb_cma_get_gem_obj(fb, 0);
+	scrtc->dma[0] = gem->paddr + fb->offsets[0]
+		      + y * fb->pitches[0] + x * bpp / 8;
+
+	if (scrtc->format->yuv) {
+		bpp = scrtc->format->bpp - 8;
+		gem = drm_fb_cma_get_gem_obj(fb, 1);
+		scrtc->dma[1] = gem->paddr + fb->offsets[1]
+			      + y / (bpp == 4 ? 2 : 1) * fb->pitches[1]
+			      + x * (bpp == 16 ? 2 : 1);
+	}
+
+	if (scrtc->cache)
+		sh_mobile_meram_cache_update(sdev->meram, scrtc->cache,
+					     scrtc->dma[0], scrtc->dma[1],
+					     &scrtc->dma[0], &scrtc->dma[1]);
+}
+
+static void shmob_drm_crtc_update_base(struct shmob_drm_crtc *scrtc)
+{
+	struct drm_crtc *crtc = &scrtc->crtc;
+	struct shmob_drm_device *sdev = crtc->dev->dev_private;
+
+	shmob_drm_crtc_compute_base(scrtc, crtc->x, crtc->y);
+
+	lcdc_write_mirror(sdev, LDSA1R, scrtc->dma[0]);
+	if (scrtc->format->yuv)
+		lcdc_write_mirror(sdev, LDSA2R, scrtc->dma[1]);
+
+	lcdc_write(sdev, LDRCNTR, lcdc_read(sdev, LDRCNTR) ^ LDRCNTR_MRS);
+}
+
+#define to_shmob_crtc(c)	container_of(c, struct shmob_drm_crtc, crtc)
+
+static void shmob_drm_crtc_dpms(struct drm_crtc *crtc, int mode)
+{
+	struct shmob_drm_crtc *scrtc = to_shmob_crtc(crtc);
+
+	if (scrtc->dpms == mode)
+		return;
+
+	if (mode == DRM_MODE_DPMS_ON)
+		shmob_drm_crtc_start(scrtc);
+	else
+		shmob_drm_crtc_stop(scrtc);
+
+	scrtc->dpms = mode;
+}
+
+static bool shmob_drm_crtc_mode_fixup(struct drm_crtc *crtc,
+				      const struct drm_display_mode *mode,
+				      struct drm_display_mode *adjusted_mode)
+{
+	return true;
+}
+
+static void shmob_drm_crtc_mode_prepare(struct drm_crtc *crtc)
+{
+	shmob_drm_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
+}
+
+static int shmob_drm_crtc_mode_set(struct drm_crtc *crtc,
+				   struct drm_display_mode *mode,
+				   struct drm_display_mode *adjusted_mode,
+				   int x, int y,
+				   struct drm_framebuffer *old_fb)
+{
+	struct shmob_drm_crtc *scrtc = to_shmob_crtc(crtc);
+	struct shmob_drm_device *sdev = crtc->dev->dev_private;
+	const struct sh_mobile_meram_cfg *mdata = sdev->pdata->meram;
+	const struct shmob_drm_format_info *format;
+	void *cache;
+
+	format = shmob_drm_format_info(crtc->fb->pixel_format);
+	if (format == NULL) {
+		dev_dbg(sdev->dev, "mode_set: unsupported format %08x\n",
+			crtc->fb->pixel_format);
+		return -EINVAL;
+	}
+
+	scrtc->format = format;
+	scrtc->line_size = crtc->fb->pitches[0];
+
+	if (sdev->meram) {
+		/* Enable MERAM cache if configured. We need to de-init
+		 * configured ICBs before we can re-initialize them.
+		 */
+		if (scrtc->cache) {
+			sh_mobile_meram_cache_free(sdev->meram, scrtc->cache);
+			scrtc->cache = NULL;
+		}
+
+		cache = sh_mobile_meram_cache_alloc(sdev->meram, mdata,
+						    crtc->fb->pitches[0],
+						    adjusted_mode->vdisplay,
+						    format->meram,
+						    &scrtc->line_size);
+		if (!IS_ERR(cache))
+			scrtc->cache = cache;
+	}
+
+	shmob_drm_crtc_compute_base(scrtc, x, y);
+
+	return 0;
+}
+
+static void shmob_drm_crtc_mode_commit(struct drm_crtc *crtc)
+{
+	shmob_drm_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
+}
+
+static int shmob_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
+					struct drm_framebuffer *old_fb)
+{
+	shmob_drm_crtc_update_base(to_shmob_crtc(crtc));
+
+	return 0;
+}
+
+static const struct drm_crtc_helper_funcs crtc_helper_funcs = {
+	.dpms = shmob_drm_crtc_dpms,
+	.mode_fixup = shmob_drm_crtc_mode_fixup,
+	.prepare = shmob_drm_crtc_mode_prepare,
+	.commit = shmob_drm_crtc_mode_commit,
+	.mode_set = shmob_drm_crtc_mode_set,
+	.mode_set_base = shmob_drm_crtc_mode_set_base,
+};
+
+void shmob_drm_crtc_cancel_page_flip(struct shmob_drm_crtc *scrtc,
+				     struct drm_file *file)
+{
+	struct drm_pending_vblank_event *event;
+	struct drm_device *dev = scrtc->crtc.dev;
+	unsigned long flags;
+
+	/* Destroy the pending vertical blanking event associated with the
+	 * pending page flip, if any, and disable vertical blanking interrupts.
+	 */
+	spin_lock_irqsave(&dev->event_lock, flags);
+	event = scrtc->event;
+	if (event && event->base.file_priv == file) {
+		scrtc->event = NULL;
+		event->base.destroy(&event->base);
+		drm_vblank_put(dev, 0);
+	}
+	spin_unlock_irqrestore(&dev->event_lock, flags);
+}
+
+void shmob_drm_crtc_finish_page_flip(struct shmob_drm_crtc *scrtc)
+{
+	struct drm_pending_vblank_event *event;
+	struct drm_device *dev = scrtc->crtc.dev;
+	struct timeval vblanktime;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->event_lock, flags);
+	event = scrtc->event;
+	scrtc->event = NULL;
+	spin_unlock_irqrestore(&dev->event_lock, flags);
+
+	if (event == NULL)
+		return;
+
+	event->event.sequence = drm_vblank_count_and_time(dev, 0, &vblanktime);
+	event->event.tv_sec = vblanktime.tv_sec;
+	event->event.tv_usec = vblanktime.tv_usec;
+
+	spin_lock_irqsave(&dev->event_lock, flags);
+	list_add_tail(&event->base.link, &event->base.file_priv->event_list);
+	wake_up_interruptible(&event->base.file_priv->event_wait);
+	spin_unlock_irqrestore(&dev->event_lock, flags);
+
+	drm_vblank_put(dev, 0);
+}
+
+static int shmob_drm_crtc_page_flip(struct drm_crtc *crtc,
+				    struct drm_framebuffer *fb,
+				    struct drm_pending_vblank_event *event)
+{
+	struct shmob_drm_crtc *scrtc = to_shmob_crtc(crtc);
+	struct drm_device *dev = scrtc->crtc.dev;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->event_lock, flags);
+	if (scrtc->event != NULL) {
+		spin_unlock_irqrestore(&dev->event_lock, flags);
+		return -EBUSY;
+	}
+	spin_unlock_irqrestore(&dev->event_lock, flags);
+
+	crtc->fb = fb;
+	shmob_drm_crtc_update_base(scrtc);
+
+	if (event) {
+		event->pipe = 0;
+		spin_lock_irqsave(&dev->event_lock, flags);
+		scrtc->event = event;
+		spin_unlock_irqrestore(&dev->event_lock, flags);
+		drm_vblank_get(dev, 0);
+	}
+
+	return 0;
+}
+
+static const struct drm_crtc_funcs crtc_funcs = {
+	.destroy = drm_crtc_cleanup,
+	.set_config = drm_crtc_helper_set_config,
+	.page_flip = shmob_drm_crtc_page_flip,
+};
+
+int shmob_drm_crtc_create(struct shmob_drm_device *sdev)
+{
+	struct drm_crtc *crtc = &sdev->crtc.crtc;
+	int ret;
+
+	sdev->crtc.dpms = DRM_MODE_DPMS_OFF;
+
+	ret = drm_crtc_init(sdev->ddev, crtc, &crtc_funcs);
+	if (ret < 0)
+		return ret;
+
+	drm_crtc_helper_add(crtc, &crtc_helper_funcs);
+
+	return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Encoder
+ */
+
+#define to_shmob_encoder(e) \
+	container_of(e, struct shmob_drm_encoder, encoder)
+
+static void shmob_drm_encoder_dpms(struct drm_encoder *encoder, int mode)
+{
+	struct shmob_drm_encoder *senc = to_shmob_encoder(encoder);
+	struct shmob_drm_device *sdev = encoder->dev->dev_private;
+	struct shmob_drm_connector *scon = &sdev->connector;
+
+	if (senc->dpms == mode)
+		return;
+
+	shmob_drm_backlight_dpms(scon, mode);
+
+	senc->dpms = mode;
+}
+
+static bool shmob_drm_encoder_mode_fixup(struct drm_encoder *encoder,
+					 const struct drm_display_mode *mode,
+					 struct drm_display_mode *adjusted_mode)
+{
+	struct drm_device *dev = encoder->dev;
+	struct shmob_drm_device *sdev = dev->dev_private;
+	struct drm_connector *connector = &sdev->connector.connector;
+	const struct drm_display_mode *panel_mode;
+
+	if (list_empty(&connector->modes)) {
+		dev_dbg(dev->dev, "mode_fixup: empty modes list\n");
+		return false;
+	}
+
+	/* The flat panel mode is fixed, just copy it to the adjusted mode. */
+	panel_mode = list_first_entry(&connector->modes,
+				      struct drm_display_mode, head);
+	drm_mode_copy(adjusted_mode, panel_mode);
+
+	return true;
+}
+
+static void shmob_drm_encoder_mode_prepare(struct drm_encoder *encoder)
+{
+	/* No-op, everything is handled in the CRTC code. */
+}
+
+static void shmob_drm_encoder_mode_set(struct drm_encoder *encoder,
+				       struct drm_display_mode *mode,
+				       struct drm_display_mode *adjusted_mode)
+{
+	/* No-op, everything is handled in the CRTC code. */
+}
+
+static void shmob_drm_encoder_mode_commit(struct drm_encoder *encoder)
+{
+	/* No-op, everything is handled in the CRTC code. */
+}
+
+static const struct drm_encoder_helper_funcs encoder_helper_funcs = {
+	.dpms = shmob_drm_encoder_dpms,
+	.mode_fixup = shmob_drm_encoder_mode_fixup,
+	.prepare = shmob_drm_encoder_mode_prepare,
+	.commit = shmob_drm_encoder_mode_commit,
+	.mode_set = shmob_drm_encoder_mode_set,
+};
+
+static void shmob_drm_encoder_destroy(struct drm_encoder *encoder)
+{
+	drm_encoder_cleanup(encoder);
+}
+
+static const struct drm_encoder_funcs encoder_funcs = {
+	.destroy = shmob_drm_encoder_destroy,
+};
+
+int shmob_drm_encoder_create(struct shmob_drm_device *sdev)
+{
+	struct drm_encoder *encoder = &sdev->encoder.encoder;
+	int ret;
+
+	sdev->encoder.dpms = DRM_MODE_DPMS_OFF;
+
+	encoder->possible_crtcs = 1;
+
+	ret = drm_encoder_init(sdev->ddev, encoder, &encoder_funcs,
+			       DRM_MODE_ENCODER_LVDS);
+	if (ret < 0)
+		return ret;
+
+	drm_encoder_helper_add(encoder, &encoder_helper_funcs);
+
+	return 0;
+}
+
+void shmob_drm_crtc_enable_vblank(struct shmob_drm_device *sdev, bool enable)
+{
+	unsigned long flags;
+	u32 ldintr;
+
+	/* Be careful not to acknowledge any pending interrupt. */
+	spin_lock_irqsave(&sdev->irq_lock, flags);
+	ldintr = lcdc_read(sdev, LDINTR) | LDINTR_STATUS_MASK;
+	if (enable)
+		ldintr |= LDINTR_VEE;
+	else
+		ldintr &= ~LDINTR_VEE;
+	lcdc_write(sdev, LDINTR, ldintr);
+	spin_unlock_irqrestore(&sdev->irq_lock, flags);
+}
+
+/* -----------------------------------------------------------------------------
+ * Connector
+ */
+
+#define to_shmob_connector(c) \
+	container_of(c, struct shmob_drm_connector, connector)
+
+static int shmob_drm_connector_get_modes(struct drm_connector *connector)
+{
+	struct shmob_drm_device *sdev = connector->dev->dev_private;
+	struct drm_display_mode *mode;
+
+	mode = drm_mode_create(connector->dev);
+	if (mode == NULL)
+		return 0;
+
+	mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER;
+	mode->clock = sdev->pdata->panel.mode.clock;
+	mode->hdisplay = sdev->pdata->panel.mode.hdisplay;
+	mode->hsync_start = sdev->pdata->panel.mode.hsync_start;
+	mode->hsync_end = sdev->pdata->panel.mode.hsync_end;
+	mode->htotal = sdev->pdata->panel.mode.htotal;
+	mode->vdisplay = sdev->pdata->panel.mode.vdisplay;
+	mode->vsync_start = sdev->pdata->panel.mode.vsync_start;
+	mode->vsync_end = sdev->pdata->panel.mode.vsync_end;
+	mode->vtotal = sdev->pdata->panel.mode.vtotal;
+	mode->flags = sdev->pdata->panel.mode.flags;
+
+	drm_mode_set_name(mode);
+	drm_mode_probed_add(connector, mode);
+
+	connector->display_info.width_mm = sdev->pdata->panel.width_mm;
+	connector->display_info.height_mm = sdev->pdata->panel.height_mm;
+
+	return 1;
+}
+
+static int shmob_drm_connector_mode_valid(struct drm_connector *connector,
+					  struct drm_display_mode *mode)
+{
+	return MODE_OK;
+}
+
+static struct drm_encoder *
+shmob_drm_connector_best_encoder(struct drm_connector *connector)
+{
+	struct shmob_drm_connector *scon = to_shmob_connector(connector);
+
+	return scon->encoder;
+}
+
+static const struct drm_connector_helper_funcs connector_helper_funcs = {
+	.get_modes = shmob_drm_connector_get_modes,
+	.mode_valid = shmob_drm_connector_mode_valid,
+	.best_encoder = shmob_drm_connector_best_encoder,
+};
+
+static void shmob_drm_connector_destroy(struct drm_connector *connector)
+{
+	struct shmob_drm_connector *scon = to_shmob_connector(connector);
+
+	shmob_drm_backlight_exit(scon);
+	drm_sysfs_connector_remove(connector);
+	drm_connector_cleanup(connector);
+}
+
+static enum drm_connector_status
+shmob_drm_connector_detect(struct drm_connector *connector, bool force)
+{
+	return connector_status_connected;
+}
+
+static const struct drm_connector_funcs connector_funcs = {
+	.dpms = drm_helper_connector_dpms,
+	.detect = shmob_drm_connector_detect,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.destroy = shmob_drm_connector_destroy,
+};
+
+int shmob_drm_connector_create(struct shmob_drm_device *sdev,
+			       struct drm_encoder *encoder)
+{
+	struct drm_connector *connector = &sdev->connector.connector;
+	int ret;
+
+	sdev->connector.encoder = encoder;
+
+	connector->display_info.width_mm = sdev->pdata->panel.width_mm;
+	connector->display_info.height_mm = sdev->pdata->panel.height_mm;
+
+	ret = drm_connector_init(sdev->ddev, connector, &connector_funcs,
+				 DRM_MODE_CONNECTOR_LVDS);
+	if (ret < 0)
+		return ret;
+
+	drm_connector_helper_add(connector, &connector_helper_funcs);
+	ret = drm_sysfs_connector_add(connector);
+	if (ret < 0)
+		goto err_cleanup;
+
+	ret = shmob_drm_backlight_init(&sdev->connector);
+	if (ret < 0)
+		goto err_sysfs;
+
+	ret = drm_mode_connector_attach_encoder(connector, encoder);
+	if (ret < 0)
+		goto err_backlight;
+
+	connector->encoder = encoder;
+
+	drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
+	drm_connector_property_set_value(connector,
+		sdev->ddev->mode_config.dpms_property, DRM_MODE_DPMS_OFF);
+
+	return 0;
+
+err_backlight:
+	shmob_drm_backlight_exit(&sdev->connector);
+err_sysfs:
+	drm_sysfs_connector_remove(connector);
+err_cleanup:
+	drm_connector_cleanup(connector);
+	return ret;
+}
diff --git a/drivers/gpu/drm/shmobile/shmob_drm_crtc.h b/drivers/gpu/drm/shmobile/shmob_drm_crtc.h
new file mode 100644
index 0000000..e5bd109
--- /dev/null
+++ b/drivers/gpu/drm/shmobile/shmob_drm_crtc.h
@@ -0,0 +1,60 @@
+/*
+ * shmob_drm_crtc.h  --  SH Mobile DRM CRTCs
+ *
+ * Copyright (C) 2012 Renesas Corporation
+ *
+ * Laurent Pinchart (laurent.pinchart@ideasonboard.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __SHMOB_DRM_CRTC_H__
+#define __SHMOB_DRM_CRTC_H__
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc.h>
+
+struct backlight_device;
+struct shmob_drm_device;
+
+struct shmob_drm_crtc {
+	struct drm_crtc crtc;
+
+	struct drm_pending_vblank_event *event;
+	int dpms;
+
+	const struct shmob_drm_format_info *format;
+	void *cache;
+	unsigned long dma[2];
+	unsigned int line_size;
+	bool started;
+};
+
+struct shmob_drm_encoder {
+	struct drm_encoder encoder;
+	int dpms;
+};
+
+struct shmob_drm_connector {
+	struct drm_connector connector;
+	struct drm_encoder *encoder;
+
+	struct backlight_device *backlight;
+};
+
+int shmob_drm_crtc_create(struct shmob_drm_device *sdev);
+void shmob_drm_crtc_enable_vblank(struct shmob_drm_device *sdev, bool enable);
+void shmob_drm_crtc_cancel_page_flip(struct shmob_drm_crtc *scrtc,
+				     struct drm_file *file);
+void shmob_drm_crtc_finish_page_flip(struct shmob_drm_crtc *scrtc);
+void shmob_drm_crtc_suspend(struct shmob_drm_crtc *scrtc);
+void shmob_drm_crtc_resume(struct shmob_drm_crtc *scrtc);
+
+int shmob_drm_encoder_create(struct shmob_drm_device *sdev);
+int shmob_drm_connector_create(struct shmob_drm_device *sdev,
+			       struct drm_encoder *encoder);
+
+#endif /* __SHMOB_DRM_CRTC_H__ */
diff --git a/drivers/gpu/drm/shmobile/shmob_drm_drv.c b/drivers/gpu/drm/shmobile/shmob_drm_drv.c
new file mode 100644
index 0000000..c71d493
--- /dev/null
+++ b/drivers/gpu/drm/shmobile/shmob_drm_drv.c
@@ -0,0 +1,361 @@
+/*
+ * shmob_drm_drv.c  --  SH Mobile DRM driver
+ *
+ * Copyright (C) 2012 Renesas Corporation
+ *
+ * Laurent Pinchart (laurent.pinchart@ideasonboard.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/slab.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+
+#include "shmob_drm_crtc.h"
+#include "shmob_drm_drv.h"
+#include "shmob_drm_kms.h"
+#include "shmob_drm_plane.h"
+#include "shmob_drm_regs.h"
+
+/* -----------------------------------------------------------------------------
+ * Hardware initialization
+ */
+
+static int __devinit shmob_drm_init_interface(struct shmob_drm_device *sdev)
+{
+	static const u32 ldmt1r[] = {
+		[SHMOB_DRM_IFACE_RGB8] = LDMT1R_MIFTYP_RGB8,
+		[SHMOB_DRM_IFACE_RGB9] = LDMT1R_MIFTYP_RGB9,
+		[SHMOB_DRM_IFACE_RGB12A] = LDMT1R_MIFTYP_RGB12A,
+		[SHMOB_DRM_IFACE_RGB12B] = LDMT1R_MIFTYP_RGB12B,
+		[SHMOB_DRM_IFACE_RGB16] = LDMT1R_MIFTYP_RGB16,
+		[SHMOB_DRM_IFACE_RGB18] = LDMT1R_MIFTYP_RGB18,
+		[SHMOB_DRM_IFACE_RGB24] = LDMT1R_MIFTYP_RGB24,
+		[SHMOB_DRM_IFACE_YUV422] = LDMT1R_MIFTYP_YCBCR,
+		[SHMOB_DRM_IFACE_SYS8A] = LDMT1R_IFM | LDMT1R_MIFTYP_SYS8A,
+		[SHMOB_DRM_IFACE_SYS8B] = LDMT1R_IFM | LDMT1R_MIFTYP_SYS8B,
+		[SHMOB_DRM_IFACE_SYS8C] = LDMT1R_IFM | LDMT1R_MIFTYP_SYS8C,
+		[SHMOB_DRM_IFACE_SYS8D] = LDMT1R_IFM | LDMT1R_MIFTYP_SYS8D,
+		[SHMOB_DRM_IFACE_SYS9] = LDMT1R_IFM | LDMT1R_MIFTYP_SYS9,
+		[SHMOB_DRM_IFACE_SYS12] = LDMT1R_IFM | LDMT1R_MIFTYP_SYS12,
+		[SHMOB_DRM_IFACE_SYS16A] = LDMT1R_IFM | LDMT1R_MIFTYP_SYS16A,
+		[SHMOB_DRM_IFACE_SYS16B] = LDMT1R_IFM | LDMT1R_MIFTYP_SYS16B,
+		[SHMOB_DRM_IFACE_SYS16C] = LDMT1R_IFM | LDMT1R_MIFTYP_SYS16C,
+		[SHMOB_DRM_IFACE_SYS18] = LDMT1R_IFM | LDMT1R_MIFTYP_SYS18,
+		[SHMOB_DRM_IFACE_SYS24] = LDMT1R_IFM | LDMT1R_MIFTYP_SYS24,
+	};
+
+	if (sdev->pdata->iface.interface >= ARRAY_SIZE(ldmt1r)) {
+		dev_err(sdev->dev, "invalid interface type %u\n",
+			sdev->pdata->iface.interface);
+		return -EINVAL;
+	}
+
+	sdev->ldmt1r = ldmt1r[sdev->pdata->iface.interface];
+	return 0;
+}
+
+static int __devinit shmob_drm_setup_clocks(struct shmob_drm_device *sdev,
+					    enum shmob_drm_clk_source clksrc)
+{
+	struct clk *clk;
+	char *clkname;
+
+	switch (clksrc) {
+	case SHMOB_DRM_CLK_BUS:
+		clkname = "bus_clk";
+		sdev->lddckr = LDDCKR_ICKSEL_BUS;
+		break;
+	case SHMOB_DRM_CLK_PERIPHERAL:
+		clkname = "peripheral_clk";
+		sdev->lddckr = LDDCKR_ICKSEL_MIPI;
+		break;
+	case SHMOB_DRM_CLK_EXTERNAL:
+		clkname = NULL;
+		sdev->lddckr = LDDCKR_ICKSEL_HDMI;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	clk = clk_get(sdev->dev, clkname);
+	if (IS_ERR(clk)) {
+		dev_err(sdev->dev, "cannot get dot clock %s\n", clkname);
+		return PTR_ERR(clk);
+	}
+
+	sdev->clock = clk;
+	return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * DRM operations
+ */
+
+static int shmob_drm_unload(struct drm_device *dev)
+{
+	struct shmob_drm_device *sdev = dev->dev_private;
+
+	drm_kms_helper_poll_fini(dev);
+	drm_mode_config_cleanup(dev);
+	drm_vblank_cleanup(dev);
+	drm_irq_uninstall(dev);
+
+	if (sdev->clock)
+		clk_put(sdev->clock);
+
+	if (sdev->mmio)
+		iounmap(sdev->mmio);
+
+	dev->dev_private = NULL;
+	kfree(sdev);
+
+	return 0;
+}
+
+static int shmob_drm_load(struct drm_device *dev, unsigned long flags)
+{
+	struct shmob_drm_platform_data *pdata = dev->dev->platform_data;
+	struct platform_device *pdev = dev->platformdev;
+	struct shmob_drm_device *sdev;
+	struct resource *res;
+	unsigned int i;
+	int ret;
+
+	if (pdata == NULL) {
+		dev_err(dev->dev, "no platform data\n");
+		return -EINVAL;
+	}
+
+	sdev = kzalloc(sizeof(*sdev), GFP_KERNEL);
+	if (sdev == NULL) {
+		dev_err(dev->dev, "failed to allocate private data\n");
+		return -ENOMEM;
+	}
+
+	sdev->dev = &pdev->dev;
+	sdev->pdata = pdata;
+	spin_lock_init(&sdev->irq_lock);
+
+	sdev->ddev = dev;
+	dev->dev_private = sdev;
+
+	/* I/O resources and clocks */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res == NULL) {
+		dev_err(&pdev->dev, "failed to get memory resource\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	sdev->mmio = ioremap_nocache(res->start, resource_size(res));
+	if (sdev->mmio == NULL) {
+		dev_err(&pdev->dev, "failed to remap memory resource\n");
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	ret = shmob_drm_setup_clocks(sdev, pdata->clk_source);
+	if (ret < 0)
+		goto done;
+
+	ret = shmob_drm_init_interface(sdev);
+	if (ret < 0)
+		goto done;
+
+	ret = shmob_drm_modeset_init(sdev);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed to initialize mode setting\n");
+		goto done;
+	}
+
+	for (i = 0; i < 4; ++i) {
+		ret = shmob_drm_plane_create(sdev, i);
+		if (ret < 0) {
+			dev_err(&pdev->dev, "failed to create plane %u\n", i);
+			goto done;
+		}
+	}
+
+	ret = drm_vblank_init(dev, 1);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed to initialize vblank\n");
+		goto done;
+	}
+
+	ret = drm_irq_install(dev);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed to install IRQ handler\n");
+		goto done;
+	}
+
+done:
+	if (ret)
+		shmob_drm_unload(dev);
+
+	return ret;
+}
+
+static void shmob_drm_preclose(struct drm_device *dev, struct drm_file *file)
+{
+	struct shmob_drm_device *sdev = dev->dev_private;
+
+	shmob_drm_crtc_cancel_page_flip(&sdev->crtc, file);
+}
+
+static irqreturn_t shmob_drm_irq(int irq, void *arg)
+{
+	struct drm_device *dev = arg;
+	struct shmob_drm_device *sdev = dev->dev_private;
+	unsigned long flags;
+	u32 status;
+
+	/* Acknowledge interrupts. Putting interrupt enable and interrupt flag
+	 * bits in the same register is really brain-dead design and requires
+	 * taking a spinlock.
+	 */
+	spin_lock_irqsave(&sdev->irq_lock, flags);
+	status = lcdc_read(sdev, LDINTR);
+	lcdc_write(sdev, LDINTR, status ^ LDINTR_STATUS_MASK);
+	spin_unlock_irqrestore(&sdev->irq_lock, flags);
+
+	if (status & LDINTR_VES) {
+		drm_handle_vblank(dev, 0);
+		shmob_drm_crtc_finish_page_flip(&sdev->crtc);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int shmob_drm_enable_vblank(struct drm_device *dev, int crtc)
+{
+	struct shmob_drm_device *sdev = dev->dev_private;
+
+	shmob_drm_crtc_enable_vblank(sdev, true);
+
+	return 0;
+}
+
+static void shmob_drm_disable_vblank(struct drm_device *dev, int crtc)
+{
+	struct shmob_drm_device *sdev = dev->dev_private;
+
+	shmob_drm_crtc_enable_vblank(sdev, false);
+}
+
+static const struct file_operations shmob_drm_fops = {
+	.owner		= THIS_MODULE,
+	.open		= drm_open,
+	.release	= drm_release,
+	.unlocked_ioctl	= drm_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl	= drm_compat_ioctl,
+#endif
+	.poll		= drm_poll,
+	.read		= drm_read,
+	.fasync		= drm_fasync,
+	.llseek		= no_llseek,
+	.mmap		= drm_gem_cma_mmap,
+};
+
+static struct drm_driver shmob_drm_driver = {
+	.driver_features	= DRIVER_HAVE_IRQ | DRIVER_GEM | DRIVER_MODESET,
+	.load			= shmob_drm_load,
+	.unload			= shmob_drm_unload,
+	.preclose		= shmob_drm_preclose,
+	.irq_handler		= shmob_drm_irq,
+	.get_vblank_counter	= drm_vblank_count,
+	.enable_vblank		= shmob_drm_enable_vblank,
+	.disable_vblank		= shmob_drm_disable_vblank,
+	.gem_free_object	= drm_gem_cma_free_object,
+	.gem_vm_ops		= &drm_gem_cma_vm_ops,
+	.dumb_create		= drm_gem_cma_dumb_create,
+	.dumb_map_offset	= drm_gem_cma_dumb_map_offset,
+	.dumb_destroy		= drm_gem_cma_dumb_destroy,
+	.fops			= &shmob_drm_fops,
+	.name			= "shmob-drm",
+	.desc			= "Renesas SH Mobile DRM",
+	.date			= "20120424",
+	.major			= 1,
+	.minor			= 0,
+};
+
+/* -----------------------------------------------------------------------------
+ * Power management
+ */
+
+#if CONFIG_PM_SLEEP
+static int shmob_drm_pm_suspend(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct drm_device *ddev = platform_get_drvdata(pdev);
+	struct shmob_drm_device *sdev = ddev->dev_private;
+
+	drm_kms_helper_poll_disable(ddev);
+	shmob_drm_crtc_suspend(&sdev->crtc);
+
+	return 0;
+}
+
+static int shmob_drm_pm_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct drm_device *ddev = platform_get_drvdata(pdev);
+	struct shmob_drm_device *sdev = ddev->dev_private;
+
+	mutex_lock(&sdev->ddev->mode_config.mutex);
+	shmob_drm_crtc_resume(&sdev->crtc);
+	mutex_unlock(&sdev->ddev->mode_config.mutex);
+
+	drm_kms_helper_poll_enable(sdev->ddev);
+	return 0;
+}
+#endif
+
+static const struct dev_pm_ops shmob_drm_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(shmob_drm_pm_suspend, shmob_drm_pm_resume)
+};
+
+/* -----------------------------------------------------------------------------
+ * Platform driver
+ */
+
+static int __devinit shmob_drm_probe(struct platform_device *pdev)
+{
+	return drm_platform_init(&shmob_drm_driver, pdev);
+}
+
+static int __devexit shmob_drm_remove(struct platform_device *pdev)
+{
+	drm_platform_exit(&shmob_drm_driver, pdev);
+
+	return 0;
+}
+
+static struct platform_driver shmob_drm_platform_driver = {
+	.probe		= shmob_drm_probe,
+	.remove		= __devexit_p(shmob_drm_remove),
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= "shmob-drm",
+		.pm	= &shmob_drm_pm_ops,
+	},
+};
+
+module_platform_driver(shmob_drm_platform_driver);
+
+MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
+MODULE_DESCRIPTION("Renesas SH Mobile DRM Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/shmobile/shmob_drm_drv.h b/drivers/gpu/drm/shmobile/shmob_drm_drv.h
new file mode 100644
index 0000000..4d46b81
--- /dev/null
+++ b/drivers/gpu/drm/shmobile/shmob_drm_drv.h
@@ -0,0 +1,47 @@
+/*
+ * shmob_drm.h  --  SH Mobile DRM driver
+ *
+ * Copyright (C) 2012 Renesas Corporation
+ *
+ * Laurent Pinchart (laurent.pinchart@ideasonboard.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __SHMOB_DRM_DRV_H__
+#define __SHMOB_DRM_DRV_H__
+
+#include <linux/kernel.h>
+#include <linux/platform_data/shmob_drm.h>
+#include <linux/spinlock.h>
+
+#include "shmob_drm_crtc.h"
+
+struct clk;
+struct device;
+struct drm_device;
+struct sh_mobile_meram_info;
+
+struct shmob_drm_device {
+	struct device *dev;
+	const struct shmob_drm_platform_data *pdata;
+
+	void __iomem *mmio;
+	struct clk *clock;
+	struct sh_mobile_meram_info *meram;
+	u32 lddckr;
+	u32 ldmt1r;
+
+	spinlock_t irq_lock;		/* Protects hardware LDINTR register */
+
+	struct drm_device *ddev;
+
+	struct shmob_drm_crtc crtc;
+	struct shmob_drm_encoder encoder;
+	struct shmob_drm_connector connector;
+};
+
+#endif /* __SHMOB_DRM_DRV_H__ */
diff --git a/drivers/gpu/drm/shmobile/shmob_drm_kms.c b/drivers/gpu/drm/shmobile/shmob_drm_kms.c
new file mode 100644
index 0000000..c291ee3
--- /dev/null
+++ b/drivers/gpu/drm/shmobile/shmob_drm_kms.c
@@ -0,0 +1,160 @@
+/*
+ * shmob_drm_kms.c  --  SH Mobile DRM Mode Setting
+ *
+ * Copyright (C) 2012 Renesas Corporation
+ *
+ * Laurent Pinchart (laurent.pinchart@ideasonboard.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 <drm/drmP.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+
+#include <video/sh_mobile_meram.h>
+
+#include "shmob_drm_crtc.h"
+#include "shmob_drm_drv.h"
+#include "shmob_drm_kms.h"
+#include "shmob_drm_regs.h"
+
+/* -----------------------------------------------------------------------------
+ * Format helpers
+ */
+
+static const struct shmob_drm_format_info shmob_drm_format_infos[] = {
+	{
+		.fourcc = DRM_FORMAT_RGB565,
+		.bpp = 16,
+		.yuv = false,
+		.lddfr = LDDFR_PKF_RGB16,
+		.meram = SH_MOBILE_MERAM_PF_RGB,
+	}, {
+		.fourcc = DRM_FORMAT_RGB888,
+		.bpp = 24,
+		.yuv = false,
+		.lddfr = LDDFR_PKF_RGB24,
+		.meram = SH_MOBILE_MERAM_PF_RGB,
+	}, {
+		.fourcc = DRM_FORMAT_ARGB8888,
+		.bpp = 32,
+		.yuv = false,
+		.lddfr = LDDFR_PKF_ARGB32,
+		.meram = SH_MOBILE_MERAM_PF_RGB,
+	}, {
+		.fourcc = DRM_FORMAT_NV12,
+		.bpp = 12,
+		.yuv = true,
+		.lddfr = LDDFR_CC | LDDFR_YF_420,
+		.meram = SH_MOBILE_MERAM_PF_NV,
+	}, {
+		.fourcc = DRM_FORMAT_NV21,
+		.bpp = 12,
+		.yuv = true,
+		.lddfr = LDDFR_CC | LDDFR_YF_420,
+		.meram = SH_MOBILE_MERAM_PF_NV,
+	}, {
+		.fourcc = DRM_FORMAT_NV16,
+		.bpp = 16,
+		.yuv = true,
+		.lddfr = LDDFR_CC | LDDFR_YF_422,
+		.meram = SH_MOBILE_MERAM_PF_NV,
+	}, {
+		.fourcc = DRM_FORMAT_NV61,
+		.bpp = 16,
+		.yuv = true,
+		.lddfr = LDDFR_CC | LDDFR_YF_422,
+		.meram = SH_MOBILE_MERAM_PF_NV,
+	}, {
+		.fourcc = DRM_FORMAT_NV24,
+		.bpp = 24,
+		.yuv = true,
+		.lddfr = LDDFR_CC | LDDFR_YF_444,
+		.meram = SH_MOBILE_MERAM_PF_NV24,
+	}, {
+		.fourcc = DRM_FORMAT_NV42,
+		.bpp = 24,
+		.yuv = true,
+		.lddfr = LDDFR_CC | LDDFR_YF_444,
+		.meram = SH_MOBILE_MERAM_PF_NV24,
+	},
+};
+
+const struct shmob_drm_format_info *shmob_drm_format_info(u32 fourcc)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(shmob_drm_format_infos); ++i) {
+		if (shmob_drm_format_infos[i].fourcc == fourcc)
+			return &shmob_drm_format_infos[i];
+	}
+
+	return NULL;
+}
+
+/* -----------------------------------------------------------------------------
+ * Frame buffer
+ */
+
+static struct drm_framebuffer *
+shmob_drm_fb_create(struct drm_device *dev, struct drm_file *file_priv,
+		    struct drm_mode_fb_cmd2 *mode_cmd)
+{
+	const struct shmob_drm_format_info *format;
+
+	format = shmob_drm_format_info(mode_cmd->pixel_format);
+	if (format == NULL) {
+		dev_dbg(dev->dev, "unsupported pixel format %08x\n",
+			mode_cmd->pixel_format);
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (mode_cmd->pitches[0] & 7 || mode_cmd->pitches[0] >= 65536) {
+		dev_dbg(dev->dev, "valid pitch value %u\n",
+			mode_cmd->pitches[0]);
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (format->yuv) {
+		unsigned int chroma_cpp = format->bpp == 24 ? 2 : 1;
+
+		if (mode_cmd->pitches[1] != mode_cmd->pitches[0] * chroma_cpp) {
+			dev_dbg(dev->dev,
+				"luma and chroma pitches do not match\n");
+			return ERR_PTR(-EINVAL);
+		}
+	}
+
+	return drm_fb_cma_create(dev, file_priv, mode_cmd);
+}
+
+static const struct drm_mode_config_funcs shmob_drm_mode_config_funcs = {
+	.fb_create = shmob_drm_fb_create,
+};
+
+int shmob_drm_modeset_init(struct shmob_drm_device *sdev)
+{
+	drm_mode_config_init(sdev->ddev);
+
+	shmob_drm_crtc_create(sdev);
+	shmob_drm_encoder_create(sdev);
+	shmob_drm_connector_create(sdev, &sdev->encoder.encoder);
+
+	drm_kms_helper_poll_init(sdev->ddev);
+
+	sdev->ddev->mode_config.min_width = 0;
+	sdev->ddev->mode_config.min_height = 0;
+	sdev->ddev->mode_config.max_width = 4095;
+	sdev->ddev->mode_config.max_height = 4095;
+	sdev->ddev->mode_config.funcs = &shmob_drm_mode_config_funcs;
+
+	drm_helper_disable_unused_functions(sdev->ddev);
+
+	return 0;
+}
diff --git a/drivers/gpu/drm/shmobile/shmob_drm_kms.h b/drivers/gpu/drm/shmobile/shmob_drm_kms.h
new file mode 100644
index 0000000..9495c91
--- /dev/null
+++ b/drivers/gpu/drm/shmobile/shmob_drm_kms.h
@@ -0,0 +1,34 @@
+/*
+ * shmob_drm_kms.h  --  SH Mobile DRM Mode Setting
+ *
+ * Copyright (C) 2012 Renesas Corporation
+ *
+ * Laurent Pinchart (laurent.pinchart@ideasonboard.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __SHMOB_DRM_KMS_H__
+#define __SHMOB_DRM_KMS_H__
+
+#include <linux/types.h>
+
+struct drm_gem_cma_object;
+struct shmob_drm_device;
+
+struct shmob_drm_format_info {
+	u32 fourcc;
+	unsigned int bpp;
+	bool yuv;
+	u32 lddfr;
+	unsigned int meram;
+};
+
+const struct shmob_drm_format_info *shmob_drm_format_info(u32 fourcc);
+
+int shmob_drm_modeset_init(struct shmob_drm_device *sdev);
+
+#endif /* __SHMOB_DRM_KMS_H__ */
diff --git a/drivers/gpu/drm/shmobile/shmob_drm_plane.c b/drivers/gpu/drm/shmobile/shmob_drm_plane.c
new file mode 100644
index 0000000..e1eb899
--- /dev/null
+++ b/drivers/gpu/drm/shmobile/shmob_drm_plane.c
@@ -0,0 +1,268 @@
+/*
+ * shmob_drm_plane.c  --  SH Mobile DRM Planes
+ *
+ * Copyright (C) 2012 Renesas Corporation
+ *
+ * Laurent Pinchart (laurent.pinchart@ideasonboard.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 <drm/drmP.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+
+#include <video/sh_mobile_meram.h>
+
+#include "shmob_drm_drv.h"
+#include "shmob_drm_kms.h"
+#include "shmob_drm_plane.h"
+#include "shmob_drm_regs.h"
+
+struct shmob_drm_plane {
+	struct drm_plane plane;
+	unsigned int index;
+	unsigned int alpha;
+
+	const struct shmob_drm_format_info *format;
+	unsigned long dma[2];
+
+	unsigned int src_x;
+	unsigned int src_y;
+	unsigned int crtc_x;
+	unsigned int crtc_y;
+	unsigned int crtc_w;
+	unsigned int crtc_h;
+};
+
+#define to_shmob_plane(p)	container_of(p, struct shmob_drm_plane, plane)
+
+static void shmob_drm_plane_compute_base(struct shmob_drm_plane *splane,
+					 struct drm_framebuffer *fb,
+					 int x, int y)
+{
+	struct drm_gem_cma_object *gem;
+	unsigned int bpp;
+
+	bpp = splane->format->yuv ? 8 : splane->format->bpp;
+	gem = drm_fb_cma_get_gem_obj(fb, 0);
+	splane->dma[0] = gem->paddr + fb->offsets[0]
+		       + y * fb->pitches[0] + x * bpp / 8;
+
+	if (splane->format->yuv) {
+		bpp = splane->format->bpp - 8;
+		gem = drm_fb_cma_get_gem_obj(fb, 1);
+		splane->dma[1] = gem->paddr + fb->offsets[1]
+			       + y / (bpp == 4 ? 2 : 1) * fb->pitches[1]
+			       + x * (bpp == 16 ? 2 : 1);
+	}
+}
+
+static void __shmob_drm_plane_setup(struct shmob_drm_plane *splane,
+				    struct drm_framebuffer *fb)
+{
+	struct shmob_drm_device *sdev = splane->plane.dev->dev_private;
+	u32 format;
+
+	/* TODO: Support ROP3 mode */
+	format = LDBBSIFR_EN | (splane->alpha << LDBBSIFR_LAY_SHIFT);
+
+	switch (splane->format->fourcc) {
+	case DRM_FORMAT_RGB565:
+	case DRM_FORMAT_NV21:
+	case DRM_FORMAT_NV61:
+	case DRM_FORMAT_NV42:
+		format |= LDBBSIFR_SWPL | LDBBSIFR_SWPW;
+		break;
+	case DRM_FORMAT_RGB888:
+	case DRM_FORMAT_NV12:
+	case DRM_FORMAT_NV16:
+	case DRM_FORMAT_NV24:
+		format |= LDBBSIFR_SWPL | LDBBSIFR_SWPW | LDBBSIFR_SWPB;
+		break;
+	case DRM_FORMAT_ARGB8888:
+	default:
+		format |= LDBBSIFR_SWPL;
+		break;
+	}
+
+	switch (splane->format->fourcc) {
+	case DRM_FORMAT_RGB565:
+		format |= LDBBSIFR_AL_1 | LDBBSIFR_RY | LDBBSIFR_RPKF_RGB16;
+		break;
+	case DRM_FORMAT_RGB888:
+		format |= LDBBSIFR_AL_1 | LDBBSIFR_RY | LDBBSIFR_RPKF_RGB24;
+		break;
+	case DRM_FORMAT_ARGB8888:
+		format |= LDBBSIFR_AL_PK | LDBBSIFR_RY | LDDFR_PKF_ARGB32;
+		break;
+	case DRM_FORMAT_NV12:
+	case DRM_FORMAT_NV21:
+		format |= LDBBSIFR_AL_1 | LDBBSIFR_CHRR_420;
+		break;
+	case DRM_FORMAT_NV16:
+	case DRM_FORMAT_NV61:
+		format |= LDBBSIFR_AL_1 | LDBBSIFR_CHRR_422;
+		break;
+	case DRM_FORMAT_NV24:
+	case DRM_FORMAT_NV42:
+		format |= LDBBSIFR_AL_1 | LDBBSIFR_CHRR_444;
+		break;
+	}
+
+#define plane_reg_dump(sdev, splane, reg) \
+	dev_dbg(sdev->ddev->dev, "%s(%u): %s 0x%08x 0x%08x\n", __func__, \
+		splane->index, #reg, \
+		lcdc_read(sdev, reg(splane->index)), \
+		lcdc_read(sdev, reg(splane->index) + LCDC_SIDE_B_OFFSET))
+
+	plane_reg_dump(sdev, splane, LDBnBSIFR);
+	plane_reg_dump(sdev, splane, LDBnBSSZR);
+	plane_reg_dump(sdev, splane, LDBnBLOCR);
+	plane_reg_dump(sdev, splane, LDBnBSMWR);
+	plane_reg_dump(sdev, splane, LDBnBSAYR);
+	plane_reg_dump(sdev, splane, LDBnBSACR);
+
+	lcdc_write(sdev, LDBCR, LDBCR_UPC(splane->index));
+	dev_dbg(sdev->ddev->dev, "%s(%u): %s 0x%08x\n", __func__, splane->index,
+		"LDBCR", lcdc_read(sdev, LDBCR));
+
+	lcdc_write(sdev, LDBnBSIFR(splane->index), format);
+
+	lcdc_write(sdev, LDBnBSSZR(splane->index),
+		   (splane->crtc_h << LDBBSSZR_BVSS_SHIFT) |
+		   (splane->crtc_w << LDBBSSZR_BHSS_SHIFT));
+	lcdc_write(sdev, LDBnBLOCR(splane->index),
+		   (splane->crtc_y << LDBBLOCR_CVLC_SHIFT) |
+		   (splane->crtc_x << LDBBLOCR_CHLC_SHIFT));
+	lcdc_write(sdev, LDBnBSMWR(splane->index),
+		   fb->pitches[0] << LDBBSMWR_BSMW_SHIFT);
+
+	shmob_drm_plane_compute_base(splane, fb, splane->src_x, splane->src_y);
+
+	lcdc_write(sdev, LDBnBSAYR(splane->index), splane->dma[0]);
+	if (splane->format->yuv)
+		lcdc_write(sdev, LDBnBSACR(splane->index), splane->dma[1]);
+
+	lcdc_write(sdev, LDBCR,
+		   LDBCR_UPF(splane->index) | LDBCR_UPD(splane->index));
+	dev_dbg(sdev->ddev->dev, "%s(%u): %s 0x%08x\n", __func__, splane->index,
+		"LDBCR", lcdc_read(sdev, LDBCR));
+
+	plane_reg_dump(sdev, splane, LDBnBSIFR);
+	plane_reg_dump(sdev, splane, LDBnBSSZR);
+	plane_reg_dump(sdev, splane, LDBnBLOCR);
+	plane_reg_dump(sdev, splane, LDBnBSMWR);
+	plane_reg_dump(sdev, splane, LDBnBSAYR);
+	plane_reg_dump(sdev, splane, LDBnBSACR);
+}
+
+void shmob_drm_plane_setup(struct drm_plane *plane)
+{
+	struct shmob_drm_plane *splane = to_shmob_plane(plane);
+
+	if (plane->fb == NULL || !plane->enabled)
+		return;
+
+	__shmob_drm_plane_setup(splane, plane->fb);
+}
+
+static int
+shmob_drm_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
+		       struct drm_framebuffer *fb, int crtc_x, int crtc_y,
+		       unsigned int crtc_w, unsigned int crtc_h,
+		       uint32_t src_x, uint32_t src_y,
+		       uint32_t src_w, uint32_t src_h)
+{
+	struct shmob_drm_plane *splane = to_shmob_plane(plane);
+	struct shmob_drm_device *sdev = plane->dev->dev_private;
+	const struct shmob_drm_format_info *format;
+
+	format = shmob_drm_format_info(fb->pixel_format);
+	if (format == NULL) {
+		dev_dbg(sdev->dev, "update_plane: unsupported format %08x\n",
+			fb->pixel_format);
+		return -EINVAL;
+	}
+
+	if (src_w >> 16 != crtc_w || src_h >> 16 != crtc_h) {
+		dev_dbg(sdev->dev, "%s: scaling not supported\n", __func__);
+		return -EINVAL;
+	}
+
+	splane->format = format;
+
+	splane->src_x = src_x >> 16;
+	splane->src_y = src_y >> 16;
+	splane->crtc_x = crtc_x;
+	splane->crtc_y = crtc_y;
+	splane->crtc_w = crtc_w;
+	splane->crtc_h = crtc_h;
+
+	__shmob_drm_plane_setup(splane, fb);
+	return 0;
+}
+
+static int shmob_drm_plane_disable(struct drm_plane *plane)
+{
+	struct shmob_drm_plane *splane = to_shmob_plane(plane);
+	struct shmob_drm_device *sdev = plane->dev->dev_private;
+
+	splane->format = NULL;
+
+	lcdc_write(sdev, LDBnBSIFR(splane->index), 0);
+	return 0;
+}
+
+static void shmob_drm_plane_destroy(struct drm_plane *plane)
+{
+	struct shmob_drm_plane *splane = to_shmob_plane(plane);
+
+	shmob_drm_plane_disable(plane);
+	drm_plane_cleanup(plane);
+	kfree(splane);
+}
+
+static const struct drm_plane_funcs shmob_drm_plane_funcs = {
+	.update_plane = shmob_drm_plane_update,
+	.disable_plane = shmob_drm_plane_disable,
+	.destroy = shmob_drm_plane_destroy,
+};
+
+static const uint32_t formats[] = {
+	DRM_FORMAT_RGB565,
+	DRM_FORMAT_RGB888,
+	DRM_FORMAT_ARGB8888,
+	DRM_FORMAT_NV12,
+	DRM_FORMAT_NV21,
+	DRM_FORMAT_NV16,
+	DRM_FORMAT_NV61,
+	DRM_FORMAT_NV24,
+	DRM_FORMAT_NV42,
+};
+
+int shmob_drm_plane_create(struct shmob_drm_device *sdev, unsigned int index)
+{
+	struct shmob_drm_plane *splane;
+	int ret;
+
+	splane = kzalloc(sizeof(*splane), GFP_KERNEL);
+	if (splane == NULL)
+		return -ENOMEM;
+
+	splane->index = index;
+	splane->alpha = 255;
+
+	ret = drm_plane_init(sdev->ddev, &splane->plane, 1,
+			     &shmob_drm_plane_funcs, formats,
+			     ARRAY_SIZE(formats), false);
+	if (ret < 0)
+		kfree(splane);
+
+	return ret;
+}
diff --git a/drivers/gpu/drm/shmobile/shmob_drm_plane.h b/drivers/gpu/drm/shmobile/shmob_drm_plane.h
new file mode 100644
index 0000000..99623d0
--- /dev/null
+++ b/drivers/gpu/drm/shmobile/shmob_drm_plane.h
@@ -0,0 +1,22 @@
+/*
+ * shmob_drm_plane.h  --  SH Mobile DRM Planes
+ *
+ * Copyright (C) 2012 Renesas Corporation
+ *
+ * Laurent Pinchart (laurent.pinchart@ideasonboard.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __SHMOB_DRM_PLANE_H__
+#define __SHMOB_DRM_PLANE_H__
+
+struct shmob_drm_device;
+
+int shmob_drm_plane_create(struct shmob_drm_device *sdev, unsigned int index);
+void shmob_drm_plane_setup(struct drm_plane *plane);
+
+#endif /* __SHMOB_DRM_PLANE_H__ */
diff --git a/drivers/gpu/drm/shmobile/shmob_drm_regs.h b/drivers/gpu/drm/shmobile/shmob_drm_regs.h
new file mode 100644
index 0000000..7923cdd
--- /dev/null
+++ b/drivers/gpu/drm/shmobile/shmob_drm_regs.h
@@ -0,0 +1,311 @@
+/*
+ * shmob_drm_regs.h  --  SH Mobile DRM registers
+ *
+ * Copyright (C) 2012 Renesas Corporation
+ *
+ * Laurent Pinchart (laurent.pinchart@ideasonboard.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __SHMOB_DRM_REGS_H__
+#define __SHMOB_DRM_REGS_H__
+
+#include <linux/io.h>
+
+/* Register definitions */
+#define LDDCKPAT1R		0x400
+#define LDDCKPAT2R		0x404
+#define LDDCKR			0x410
+#define LDDCKR_ICKSEL_BUS	(0 << 16)
+#define LDDCKR_ICKSEL_MIPI	(1 << 16)
+#define LDDCKR_ICKSEL_HDMI	(2 << 16)
+#define LDDCKR_ICKSEL_EXT	(3 << 16)
+#define LDDCKR_ICKSEL_MASK	(7 << 16)
+#define LDDCKR_MOSEL		(1 << 6)
+#define LDDCKSTPR		0x414
+#define LDDCKSTPR_DCKSTS	(1 << 16)
+#define LDDCKSTPR_DCKSTP	(1 << 0)
+#define LDMT1R			0x418
+#define LDMT1R_VPOL		(1 << 28)
+#define LDMT1R_HPOL		(1 << 27)
+#define LDMT1R_DWPOL		(1 << 26)
+#define LDMT1R_DIPOL		(1 << 25)
+#define LDMT1R_DAPOL		(1 << 24)
+#define LDMT1R_HSCNT		(1 << 17)
+#define LDMT1R_DWCNT		(1 << 16)
+#define LDMT1R_IFM		(1 << 12)
+#define LDMT1R_MIFTYP_RGB8	(0x0 << 0)
+#define LDMT1R_MIFTYP_RGB9	(0x4 << 0)
+#define LDMT1R_MIFTYP_RGB12A	(0x5 << 0)
+#define LDMT1R_MIFTYP_RGB12B	(0x6 << 0)
+#define LDMT1R_MIFTYP_RGB16	(0x7 << 0)
+#define LDMT1R_MIFTYP_RGB18	(0xa << 0)
+#define LDMT1R_MIFTYP_RGB24	(0xb << 0)
+#define LDMT1R_MIFTYP_YCBCR	(0xf << 0)
+#define LDMT1R_MIFTYP_SYS8A	(0x0 << 0)
+#define LDMT1R_MIFTYP_SYS8B	(0x1 << 0)
+#define LDMT1R_MIFTYP_SYS8C	(0x2 << 0)
+#define LDMT1R_MIFTYP_SYS8D	(0x3 << 0)
+#define LDMT1R_MIFTYP_SYS9	(0x4 << 0)
+#define LDMT1R_MIFTYP_SYS12	(0x5 << 0)
+#define LDMT1R_MIFTYP_SYS16A	(0x7 << 0)
+#define LDMT1R_MIFTYP_SYS16B	(0x8 << 0)
+#define LDMT1R_MIFTYP_SYS16C	(0x9 << 0)
+#define LDMT1R_MIFTYP_SYS18	(0xa << 0)
+#define LDMT1R_MIFTYP_SYS24	(0xb << 0)
+#define LDMT1R_MIFTYP_MASK	(0xf << 0)
+#define LDMT2R			0x41c
+#define LDMT2R_CSUP_MASK	(7 << 26)
+#define LDMT2R_CSUP_SHIFT	26
+#define LDMT2R_RSV		(1 << 25)
+#define LDMT2R_VSEL		(1 << 24)
+#define LDMT2R_WCSC_MASK	(0xff << 16)
+#define LDMT2R_WCSC_SHIFT	16
+#define LDMT2R_WCEC_MASK	(0xff << 8)
+#define LDMT2R_WCEC_SHIFT	8
+#define LDMT2R_WCLW_MASK	(0xff << 0)
+#define LDMT2R_WCLW_SHIFT	0
+#define LDMT3R			0x420
+#define LDMT3R_RDLC_MASK	(0x3f << 24)
+#define LDMT3R_RDLC_SHIFT	24
+#define LDMT3R_RCSC_MASK	(0xff << 16)
+#define LDMT3R_RCSC_SHIFT	16
+#define LDMT3R_RCEC_MASK	(0xff << 8)
+#define LDMT3R_RCEC_SHIFT	8
+#define LDMT3R_RCLW_MASK	(0xff << 0)
+#define LDMT3R_RCLW_SHIFT	0
+#define LDDFR			0x424
+#define LDDFR_CF1		(1 << 18)
+#define LDDFR_CF0		(1 << 17)
+#define LDDFR_CC		(1 << 16)
+#define LDDFR_YF_420		(0 << 8)
+#define LDDFR_YF_422		(1 << 8)
+#define LDDFR_YF_444		(2 << 8)
+#define LDDFR_YF_MASK		(3 << 8)
+#define LDDFR_PKF_ARGB32	(0x00 << 0)
+#define LDDFR_PKF_RGB16		(0x03 << 0)
+#define LDDFR_PKF_RGB24		(0x0b << 0)
+#define LDDFR_PKF_MASK		(0x1f << 0)
+#define LDSM1R			0x428
+#define LDSM1R_OS		(1 << 0)
+#define LDSM2R			0x42c
+#define LDSM2R_OSTRG		(1 << 0)
+#define LDSA1R			0x430
+#define LDSA2R			0x434
+#define LDMLSR			0x438
+#define LDWBFR			0x43c
+#define LDWBCNTR		0x440
+#define LDWBAR			0x444
+#define LDHCNR			0x448
+#define LDHSYNR			0x44c
+#define LDVLNR			0x450
+#define LDVSYNR			0x454
+#define LDHPDR			0x458
+#define LDVPDR			0x45c
+#define LDPMR			0x460
+#define LDPMR_LPS		(3 << 0)
+#define LDINTR			0x468
+#define LDINTR_FE		(1 << 10)
+#define LDINTR_VSE		(1 << 9)
+#define LDINTR_VEE		(1 << 8)
+#define LDINTR_FS		(1 << 2)
+#define LDINTR_VSS		(1 << 1)
+#define LDINTR_VES		(1 << 0)
+#define LDINTR_STATUS_MASK	(0xff << 0)
+#define LDSR			0x46c
+#define LDSR_MSS		(1 << 10)
+#define LDSR_MRS		(1 << 8)
+#define LDSR_AS			(1 << 1)
+#define LDCNT1R			0x470
+#define LDCNT1R_DE		(1 << 0)
+#define LDCNT2R			0x474
+#define LDCNT2R_BR		(1 << 8)
+#define LDCNT2R_MD		(1 << 3)
+#define LDCNT2R_SE		(1 << 2)
+#define LDCNT2R_ME		(1 << 1)
+#define LDCNT2R_DO		(1 << 0)
+#define LDRCNTR			0x478
+#define LDRCNTR_SRS		(1 << 17)
+#define LDRCNTR_SRC		(1 << 16)
+#define LDRCNTR_MRS		(1 << 1)
+#define LDRCNTR_MRC		(1 << 0)
+#define LDDDSR			0x47c
+#define LDDDSR_LS		(1 << 2)
+#define LDDDSR_WS		(1 << 1)
+#define LDDDSR_BS		(1 << 0)
+#define LDHAJR			0x4a0
+
+#define LDDWD0R			0x800
+#define LDDWDxR_WDACT		(1 << 28)
+#define LDDWDxR_RSW		(1 << 24)
+#define LDDRDR			0x840
+#define LDDRDR_RSR		(1 << 24)
+#define LDDRDR_DRD_MASK		(0x3ffff << 0)
+#define LDDWAR			0x900
+#define LDDWAR_WA		(1 << 0)
+#define LDDRAR			0x904
+#define LDDRAR_RA		(1 << 0)
+
+#define LDBCR			0xb00
+#define LDBCR_UPC(n)		(1 << ((n) + 16))
+#define LDBCR_UPF(n)		(1 << ((n) + 8))
+#define LDBCR_UPD(n)		(1 << ((n) + 0))
+#define LDBnBSIFR(n)		(0xb20 + (n) * 0x20 + 0x00)
+#define LDBBSIFR_EN		(1 << 31)
+#define LDBBSIFR_VS		(1 << 29)
+#define LDBBSIFR_BRSEL		(1 << 28)
+#define LDBBSIFR_MX		(1 << 27)
+#define LDBBSIFR_MY		(1 << 26)
+#define LDBBSIFR_CV3		(3 << 24)
+#define LDBBSIFR_CV2		(2 << 24)
+#define LDBBSIFR_CV1		(1 << 24)
+#define LDBBSIFR_CV0		(0 << 24)
+#define LDBBSIFR_CV_MASK	(3 << 24)
+#define LDBBSIFR_LAY_MASK	(0xff << 16)
+#define LDBBSIFR_LAY_SHIFT	16
+#define LDBBSIFR_ROP3_MASK	(0xff << 16)
+#define LDBBSIFR_ROP3_SHIFT	16
+#define LDBBSIFR_AL_PL8		(3 << 14)
+#define LDBBSIFR_AL_PL1		(2 << 14)
+#define LDBBSIFR_AL_PK		(1 << 14)
+#define LDBBSIFR_AL_1		(0 << 14)
+#define LDBBSIFR_AL_MASK	(3 << 14)
+#define LDBBSIFR_SWPL		(1 << 10)
+#define LDBBSIFR_SWPW		(1 << 9)
+#define LDBBSIFR_SWPB		(1 << 8)
+#define LDBBSIFR_RY		(1 << 7)
+#define LDBBSIFR_CHRR_420	(2 << 0)
+#define LDBBSIFR_CHRR_422	(1 << 0)
+#define LDBBSIFR_CHRR_444	(0 << 0)
+#define LDBBSIFR_RPKF_ARGB32	(0x00 << 0)
+#define LDBBSIFR_RPKF_RGB16	(0x03 << 0)
+#define LDBBSIFR_RPKF_RGB24	(0x0b << 0)
+#define LDBBSIFR_RPKF_MASK	(0x1f << 0)
+#define LDBnBSSZR(n)		(0xb20 + (n) * 0x20 + 0x04)
+#define LDBBSSZR_BVSS_MASK	(0xfff << 16)
+#define LDBBSSZR_BVSS_SHIFT	16
+#define LDBBSSZR_BHSS_MASK	(0xfff << 0)
+#define LDBBSSZR_BHSS_SHIFT	0
+#define LDBnBLOCR(n)		(0xb20 + (n) * 0x20 + 0x08)
+#define LDBBLOCR_CVLC_MASK	(0xfff << 16)
+#define LDBBLOCR_CVLC_SHIFT	16
+#define LDBBLOCR_CHLC_MASK	(0xfff << 0)
+#define LDBBLOCR_CHLC_SHIFT	0
+#define LDBnBSMWR(n)		(0xb20 + (n) * 0x20 + 0x0c)
+#define LDBBSMWR_BSMWA_MASK	(0xffff << 16)
+#define LDBBSMWR_BSMWA_SHIFT	16
+#define LDBBSMWR_BSMW_MASK	(0xffff << 0)
+#define LDBBSMWR_BSMW_SHIFT	0
+#define LDBnBSAYR(n)		(0xb20 + (n) * 0x20 + 0x10)
+#define LDBBSAYR_FG1A_MASK	(0xff << 24)
+#define LDBBSAYR_FG1A_SHIFT	24
+#define LDBBSAYR_FG1R_MASK	(0xff << 16)
+#define LDBBSAYR_FG1R_SHIFT	16
+#define LDBBSAYR_FG1G_MASK	(0xff << 8)
+#define LDBBSAYR_FG1G_SHIFT	8
+#define LDBBSAYR_FG1B_MASK	(0xff << 0)
+#define LDBBSAYR_FG1B_SHIFT	0
+#define LDBnBSACR(n)		(0xb20 + (n) * 0x20 + 0x14)
+#define LDBBSACR_FG2A_MASK	(0xff << 24)
+#define LDBBSACR_FG2A_SHIFT	24
+#define LDBBSACR_FG2R_MASK	(0xff << 16)
+#define LDBBSACR_FG2R_SHIFT	16
+#define LDBBSACR_FG2G_MASK	(0xff << 8)
+#define LDBBSACR_FG2G_SHIFT	8
+#define LDBBSACR_FG2B_MASK	(0xff << 0)
+#define LDBBSACR_FG2B_SHIFT	0
+#define LDBnBSAAR(n)		(0xb20 + (n) * 0x20 + 0x18)
+#define LDBBSAAR_AP_MASK	(0xff << 24)
+#define LDBBSAAR_AP_SHIFT	24
+#define LDBBSAAR_R_MASK		(0xff << 16)
+#define LDBBSAAR_R_SHIFT	16
+#define LDBBSAAR_GY_MASK	(0xff << 8)
+#define LDBBSAAR_GY_SHIFT	8
+#define LDBBSAAR_B_MASK		(0xff << 0)
+#define LDBBSAAR_B_SHIFT	0
+#define LDBnBPPCR(n)		(0xb20 + (n) * 0x20 + 0x1c)
+#define LDBBPPCR_AP_MASK	(0xff << 24)
+#define LDBBPPCR_AP_SHIFT	24
+#define LDBBPPCR_R_MASK		(0xff << 16)
+#define LDBBPPCR_R_SHIFT	16
+#define LDBBPPCR_GY_MASK	(0xff << 8)
+#define LDBBPPCR_GY_SHIFT	8
+#define LDBBPPCR_B_MASK		(0xff << 0)
+#define LDBBPPCR_B_SHIFT	0
+#define LDBnBBGCL(n)		(0xb10 + (n) * 0x04)
+#define LDBBBGCL_BGA_MASK	(0xff << 24)
+#define LDBBBGCL_BGA_SHIFT	24
+#define LDBBBGCL_BGR_MASK	(0xff << 16)
+#define LDBBBGCL_BGR_SHIFT	16
+#define LDBBBGCL_BGG_MASK	(0xff << 8)
+#define LDBBBGCL_BGG_SHIFT	8
+#define LDBBBGCL_BGB_MASK	(0xff << 0)
+#define LDBBBGCL_BGB_SHIFT	0
+
+#define LCDC_SIDE_B_OFFSET	0x1000
+#define LCDC_MIRROR_OFFSET	0x2000
+
+static inline bool lcdc_is_banked(u32 reg)
+{
+	switch (reg) {
+	case LDMT1R:
+	case LDMT2R:
+	case LDMT3R:
+	case LDDFR:
+	case LDSM1R:
+	case LDSA1R:
+	case LDSA2R:
+	case LDMLSR:
+	case LDWBFR:
+	case LDWBCNTR:
+	case LDWBAR:
+	case LDHCNR:
+	case LDHSYNR:
+	case LDVLNR:
+	case LDVSYNR:
+	case LDHPDR:
+	case LDVPDR:
+	case LDHAJR:
+		return true;
+	default:
+		return reg >= LDBnBBGCL(0) && reg <= LDBnBPPCR(3);
+	}
+}
+
+static inline void lcdc_write_mirror(struct shmob_drm_device *sdev, u32 reg,
+				     u32 data)
+{
+	iowrite32(data, sdev->mmio + reg + LCDC_MIRROR_OFFSET);
+}
+
+static inline void lcdc_write(struct shmob_drm_device *sdev, u32 reg, u32 data)
+{
+	iowrite32(data, sdev->mmio + reg);
+	if (lcdc_is_banked(reg))
+		iowrite32(data, sdev->mmio + reg + LCDC_SIDE_B_OFFSET);
+}
+
+static inline u32 lcdc_read(struct shmob_drm_device *sdev, u32 reg)
+{
+	return ioread32(sdev->mmio + reg);
+}
+
+static inline int lcdc_wait_bit(struct shmob_drm_device *sdev, u32 reg,
+				u32 mask, u32 until)
+{
+	unsigned long timeout = jiffies + msecs_to_jiffies(5);
+
+	while ((lcdc_read(sdev, reg) & mask) != until) {
+		if (time_after(jiffies, timeout))
+			return -ETIMEDOUT;
+		cpu_relax();
+	}
+
+	return 0;
+}
+
+#endif /* __SHMOB_DRM_REGS_H__ */
diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c
index f8187ea..0df71ea 100644
--- a/drivers/gpu/drm/ttm/ttm_bo_util.c
+++ b/drivers/gpu/drm/ttm/ttm_bo_util.c
@@ -472,7 +472,7 @@ pgprot_t ttm_io_prot(uint32_t caching_flags, pgprot_t tmp)
 	else
 		tmp = pgprot_noncached(tmp);
 #endif
-#if defined(__sparc__)
+#if defined(__sparc__) || defined(__mips__)
 	if (!(caching_flags & TTM_PL_FLAG_CACHED))
 		tmp = pgprot_noncached(tmp);
 #endif
diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_vm.c
index a877813..3ba72db 100644
--- a/drivers/gpu/drm/ttm/ttm_bo_vm.c
+++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c
@@ -285,7 +285,7 @@ int ttm_bo_mmap(struct file *filp, struct vm_area_struct *vma,
 	 */
 
 	vma->vm_private_data = bo;
-	vma->vm_flags |= VM_RESERVED | VM_IO | VM_MIXEDMAP | VM_DONTEXPAND;
+	vma->vm_flags |= VM_IO | VM_MIXEDMAP | VM_DONTEXPAND | VM_DONTDUMP;
 	return 0;
 out_unref:
 	ttm_bo_unref(&bo);
@@ -300,7 +300,7 @@ int ttm_fbdev_mmap(struct vm_area_struct *vma, struct ttm_buffer_object *bo)
 
 	vma->vm_ops = &ttm_bo_vm_ops;
 	vma->vm_private_data = ttm_bo_reference(bo);
-	vma->vm_flags |= VM_RESERVED | VM_IO | VM_MIXEDMAP | VM_DONTEXPAND;
+	vma->vm_flags |= VM_IO | VM_MIXEDMAP | VM_DONTEXPAND;
 	return 0;
 }
 EXPORT_SYMBOL(ttm_fbdev_mmap);
diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c
index fa09daf..11c9369 100644
--- a/drivers/gpu/drm/ttm/ttm_tt.c
+++ b/drivers/gpu/drm/ttm/ttm_tt.c
@@ -290,8 +290,6 @@ int ttm_tt_swapin(struct ttm_tt *ttm)
 	struct file *swap_storage;
 	struct page *from_page;
 	struct page *to_page;
-	void *from_virtual;
-	void *to_virtual;
 	int i;
 	int ret = -ENOMEM;
 
@@ -311,11 +309,7 @@ int ttm_tt_swapin(struct ttm_tt *ttm)
 			goto out_err;
 
 		preempt_disable();
-		from_virtual = kmap_atomic(from_page);
-		to_virtual = kmap_atomic(to_page);
-		memcpy(to_virtual, from_virtual, PAGE_SIZE);
-		kunmap_atomic(to_virtual);
-		kunmap_atomic(from_virtual);
+		copy_highpage(to_page, from_page);
 		preempt_enable();
 		page_cache_release(from_page);
 	}
@@ -336,8 +330,6 @@ int ttm_tt_swapout(struct ttm_tt *ttm, struct file *persistent_swap_storage)
 	struct file *swap_storage;
 	struct page *from_page;
 	struct page *to_page;
-	void *from_virtual;
-	void *to_virtual;
 	int i;
 	int ret = -ENOMEM;
 
@@ -367,11 +359,7 @@ int ttm_tt_swapout(struct ttm_tt *ttm, struct file *persistent_swap_storage)
 			goto out_err;
 		}
 		preempt_disable();
-		from_virtual = kmap_atomic(from_page);
-		to_virtual = kmap_atomic(to_page);
-		memcpy(to_virtual, from_virtual, PAGE_SIZE);
-		kunmap_atomic(to_virtual);
-		kunmap_atomic(from_virtual);
+		copy_highpage(to_page, from_page);
 		preempt_enable();
 		set_page_dirty(to_page);
 		mark_page_accessed(to_page);
diff --git a/drivers/gpu/drm/udl/udl_connector.c b/drivers/gpu/drm/udl/udl_connector.c
index ba055e9..2d98ff9 100644
--- a/drivers/gpu/drm/udl/udl_connector.c
+++ b/drivers/gpu/drm/udl/udl_connector.c
@@ -57,11 +57,8 @@ static int udl_get_modes(struct drm_connector *connector)
 
 	edid = (struct edid *)udl_get_edid(udl);
 
-	connector->display_info.raw_edid = (char *)edid;
-
 	drm_mode_connector_update_edid_property(connector, edid);
 	ret = drm_add_edid_modes(connector, edid);
-	connector->display_info.raw_edid = NULL;
 	kfree(edid);
 	return ret;
 }
diff --git a/drivers/gpu/drm/udl/udl_fb.c b/drivers/gpu/drm/udl/udl_fb.c
index ce9a611..8f9d0bd 100644
--- a/drivers/gpu/drm/udl/udl_fb.c
+++ b/drivers/gpu/drm/udl/udl_fb.c
@@ -13,6 +13,7 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/fb.h>
+#include <linux/dma-buf.h>
 
 #include "drmP.h"
 #include "drm.h"
@@ -243,7 +244,7 @@ static int udl_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
 			size = 0;
 	}
 
-	vma->vm_flags |= VM_RESERVED;	/* avoid to swap out this VMA */
+	/* VM_IO | VM_DONTEXPAND | VM_DONTDUMP are set by remap_pfn_range() */
 	return 0;
 }
 
@@ -377,16 +378,33 @@ static int udl_user_framebuffer_dirty(struct drm_framebuffer *fb,
 {
 	struct udl_framebuffer *ufb = to_udl_fb(fb);
 	int i;
+	int ret = 0;
 
 	if (!ufb->active_16)
 		return 0;
 
+	if (ufb->obj->base.import_attach) {
+		ret = dma_buf_begin_cpu_access(ufb->obj->base.import_attach->dmabuf,
+					       0, ufb->obj->base.size,
+					       DMA_FROM_DEVICE);
+		if (ret)
+			return ret;
+	}
+
 	for (i = 0; i < num_clips; i++) {
-		udl_handle_damage(ufb, clips[i].x1, clips[i].y1,
+		ret = udl_handle_damage(ufb, clips[i].x1, clips[i].y1,
 				  clips[i].x2 - clips[i].x1,
 				  clips[i].y2 - clips[i].y1);
+		if (ret)
+			break;
 	}
-	return 0;
+
+	if (ufb->obj->base.import_attach) {
+		dma_buf_end_cpu_access(ufb->obj->base.import_attach->dmabuf,
+				       0, ufb->obj->base.size,
+				       DMA_FROM_DEVICE);
+	}
+	return ret;
 }
 
 static void udl_user_framebuffer_destroy(struct drm_framebuffer *fb)
diff --git a/drivers/gpu/drm/udl/udl_gem.c b/drivers/gpu/drm/udl/udl_gem.c
index 291ecc1..47b2563 100644
--- a/drivers/gpu/drm/udl/udl_gem.c
+++ b/drivers/gpu/drm/udl/udl_gem.c
@@ -181,11 +181,6 @@ int udl_gem_vmap(struct udl_gem_object *obj)
 	int ret;
 
 	if (obj->base.import_attach) {
-		ret = dma_buf_begin_cpu_access(obj->base.import_attach->dmabuf,
-					       0, obj->base.size, DMA_BIDIRECTIONAL);
-		if (ret)
-			return -EINVAL;
-
 		obj->vmapping = dma_buf_vmap(obj->base.import_attach->dmabuf);
 		if (!obj->vmapping)
 			return -ENOMEM;
@@ -206,8 +201,6 @@ void udl_gem_vunmap(struct udl_gem_object *obj)
 {
 	if (obj->base.import_attach) {
 		dma_buf_vunmap(obj->base.import_attach->dmabuf, obj->vmapping);
-		dma_buf_end_cpu_access(obj->base.import_attach->dmabuf, 0,
-				       obj->base.size, DMA_BIDIRECTIONAL);
 		return;
 	}
 
diff --git a/drivers/gpu/drm/udl/udl_main.c b/drivers/gpu/drm/udl/udl_main.c
index 4c2d836..40bf468 100644
--- a/drivers/gpu/drm/udl/udl_main.c
+++ b/drivers/gpu/drm/udl/udl_main.c
@@ -41,11 +41,8 @@ static int udl_parse_vendor_descriptor(struct drm_device *dev,
 	total_len = usb_get_descriptor(usbdev, 0x5f, /* vendor specific */
 				    0, desc, MAX_VENDOR_DESCRIPTOR_SIZE);
 	if (total_len > 5) {
-		DRM_INFO("vendor descriptor length:%x data:%02x %02x %02x %02x" \
-			"%02x %02x %02x %02x %02x %02x %02x\n",
-			total_len, desc[0],
-			desc[1], desc[2], desc[3], desc[4], desc[5], desc[6],
-			desc[7], desc[8], desc[9], desc[10]);
+		DRM_INFO("vendor descriptor length:%x data:%*ph\n",
+			total_len, 11, desc);
 
 		if ((desc[0] != total_len) || /* descriptor length */
 		    (desc[1] != 0x5f) ||   /* vendor descriptor type */
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index ba2c35d..09f44c5 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -438,7 +438,6 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
 		DRM_ERROR("Failed allocating a device private struct.\n");
 		return -ENOMEM;
 	}
-	memset(dev_priv, 0, sizeof(*dev_priv));
 
 	pci_set_master(dev->pdev);
 
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
index 3c447bf..a32f2e9 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
@@ -594,7 +594,7 @@ int vmw_fb_off(struct vmw_private *vmw_priv)
 	par->dirty.active = false;
 	spin_unlock_irqrestore(&par->dirty.lock, flags);
 
-	flush_delayed_work_sync(&info->deferred_work);
+	flush_delayed_work(&info->deferred_work);
 
 	par->bo_ptr = NULL;
 	ttm_bo_kunmap(&par->map);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index c50724b..5474394 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -483,7 +483,6 @@ static int do_surface_dirty_sou(struct vmw_private *dev_priv,
 	}
 
 	/* only need to do this once */
-	memset(cmd, 0, fifo_size);
 	cmd->header.id = cpu_to_le32(SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN);
 	cmd->header.size = cpu_to_le32(fifo_size - sizeof(cmd->header));
 
diff --git a/drivers/gpu/vga/vgaarb.c b/drivers/gpu/vga/vgaarb.c
index 3df8fc0..e893f6e 100644
--- a/drivers/gpu/vga/vgaarb.c
+++ b/drivers/gpu/vga/vgaarb.c
@@ -141,7 +141,11 @@ EXPORT_SYMBOL_GPL(vga_default_device);
 
 void vga_set_default_device(struct pci_dev *pdev)
 {
-	vga_default = pdev;
+	if (vga_default == pdev)
+		return;
+
+	pci_dev_put(vga_default);
+	vga_default = pci_dev_get(pdev);
 }
 #endif
 
@@ -577,7 +581,7 @@ static bool vga_arbiter_add_pci_device(struct pci_dev *pdev)
 #ifndef __ARCH_HAS_VGA_DEFAULT_DEVICE
 	if (vga_default == NULL &&
 	    ((vgadev->owns & VGA_RSRC_LEGACY_MASK) == VGA_RSRC_LEGACY_MASK))
-		vga_default = pci_dev_get(pdev);
+		vga_set_default_device(pdev);
 #endif
 
 	vga_arbiter_check_bridge_sharing(vgadev);
@@ -613,10 +617,8 @@ static bool vga_arbiter_del_pci_device(struct pci_dev *pdev)
 	}
 
 #ifndef __ARCH_HAS_VGA_DEFAULT_DEVICE
-	if (vga_default == pdev) {
-		pci_dev_put(vga_default);
-		vga_default = NULL;
-	}
+	if (vga_default == pdev)
+		vga_set_default_device(NULL);
 #endif
 
 	if (vgadev->decodes & (VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM))
@@ -1066,7 +1068,6 @@ static ssize_t vga_arb_write(struct file *file, const char __user * buf,
 		}
 
 	} else if (strncmp(curr_pos, "target ", 7) == 0) {
-		struct pci_bus *pbus;
 		unsigned int domain, bus, devfn;
 		struct vga_device *vgadev;
 
@@ -1085,19 +1086,11 @@ static ssize_t vga_arb_write(struct file *file, const char __user * buf,
 			pr_debug("vgaarb: %s ==> %x:%x:%x.%x\n", curr_pos,
 				domain, bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
 
-			pbus = pci_find_bus(domain, bus);
-			pr_debug("vgaarb: pbus %p\n", pbus);
-			if (pbus == NULL) {
-				pr_err("vgaarb: invalid PCI domain and/or bus address %x:%x\n",
-					domain, bus);
-				ret_val = -ENODEV;
-				goto done;
-			}
-			pdev = pci_get_slot(pbus, devfn);
+			pdev = pci_get_domain_bus_and_slot(domain, bus, devfn);
 			pr_debug("vgaarb: pdev %p\n", pdev);
 			if (!pdev) {
-				pr_err("vgaarb: invalid PCI address %x:%x\n",
-					bus, devfn);
+				pr_err("vgaarb: invalid PCI address %x:%x:%x\n",
+					domain, bus, devfn);
 				ret_val = -ENODEV;
 				goto done;
 			}
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index fbf4950..7003737 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -307,7 +307,6 @@ config HID_LOGITECH
 config HID_LOGITECH_DJ
 	tristate "Logitech Unifying receivers full support"
 	depends on HID_LOGITECH
-	default m
 	---help---
 	Say Y if you want support for Logitech Unifying receivers and devices.
 	Unifying receivers are capable of pairing up to 6 Logitech compliant
@@ -527,6 +526,14 @@ config HID_PICOLCD_LEDS
 	---help---
 	  Provide access to PicoLCD's GPO pins via leds class.
 
+config HID_PICOLCD_CIR
+	bool "CIR via RC class" if EXPERT
+	default !EXPERT
+	depends on HID_PICOLCD
+	depends on HID_PICOLCD=RC_CORE || RC_CORE=y
+	---help---
+	  Provide access to PicoLCD's CIR interface via remote control (LIRC).
+
 config HID_PRIMAX
 	tristate "Primax non-fully HID-compliant devices"
 	depends on USB_HID
@@ -690,6 +697,20 @@ config HID_ZYDACRON
 	---help---
 	Support for Zydacron remote control.
 
+config HID_SENSOR_HUB
+	tristate "HID Sensors framework support"
+	depends on USB_HID
+	select MFD_CORE
+	default n
+	-- help---
+	  Support for HID Sensor framework. This creates a MFD instance
+	  for a sensor hub and identifies all the sensors connected to it.
+	  Each sensor is registered as a MFD cell, so that sensor specific
+	  processing can be done in a separate driver. Each sensor
+	  drivers can use the service provided by this driver to register
+	  for events and handle data streams. Each sensor driver can format
+	  data and present to user mode using input or IIO interface.
+
 endmenu
 
 endif # HID
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index f975485..547e0ae 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -69,6 +69,26 @@ obj-$(CONFIG_HID_PRODIKEYS)	+= hid-prodikeys.o
 obj-$(CONFIG_HID_PANTHERLORD)	+= hid-pl.o
 obj-$(CONFIG_HID_PETALYNX)	+= hid-petalynx.o
 obj-$(CONFIG_HID_PICOLCD)	+= hid-picolcd.o
+hid-picolcd-y			+= hid-picolcd_core.o
+ifdef CONFIG_HID_PICOLCD_FB
+hid-picolcd-y			+= hid-picolcd_fb.o
+endif
+ifdef CONFIG_HID_PICOLCD_BACKLIGHT
+hid-picolcd-y			+= hid-picolcd_backlight.o
+endif
+ifdef CONFIG_HID_PICOLCD_LCD
+hid-picolcd-y			+= hid-picolcd_lcd.o
+endif
+ifdef CONFIG_HID_PICOLCD_LEDS
+hid-picolcd-y			+= hid-picolcd_leds.o
+endif
+ifdef CONFIG_HID_PICOLCD_CIR
+hid-picolcd-y			+= hid-picolcd_cir.o
+endif
+ifdef CONFIG_DEBUG_FS
+hid-picolcd-y			+= hid-picolcd_debugfs.o
+endif
+
 obj-$(CONFIG_HID_PRIMAX)	+= hid-primax.o
 obj-$(CONFIG_HID_ROCCAT)	+= hid-roccat.o hid-roccat-common.o \
 	hid-roccat-arvo.o hid-roccat-isku.o hid-roccat-kone.o \
@@ -91,6 +111,7 @@ obj-$(CONFIG_HID_ZYDACRON)	+= hid-zydacron.o
 obj-$(CONFIG_HID_WACOM)		+= hid-wacom.o
 obj-$(CONFIG_HID_WALTOP)	+= hid-waltop.o
 obj-$(CONFIG_HID_WIIMOTE)	+= hid-wiimote.o
+obj-$(CONFIG_HID_SENSOR_HUB)	+= hid-sensor-hub.o
 
 obj-$(CONFIG_USB_HID)		+= usbhid/
 obj-$(CONFIG_USB_MOUSE)		+= usbhid/
diff --git a/drivers/hid/hid-a4tech.c b/drivers/hid/hid-a4tech.c
index 902d1df..0a23988 100644
--- a/drivers/hid/hid-a4tech.c
+++ b/drivers/hid/hid-a4tech.c
@@ -5,7 +5,6 @@
  *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
  *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
  *  Copyright (c) 2006-2007 Jiri Kosina
- *  Copyright (c) 2007 Paul Walmsley
  *  Copyright (c) 2008 Jiri Slaby
  */
 
diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c
index 585344b..06ebdbb 100644
--- a/drivers/hid/hid-apple.c
+++ b/drivers/hid/hid-apple.c
@@ -5,7 +5,6 @@
  *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
  *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
  *  Copyright (c) 2006-2007 Jiri Kosina
- *  Copyright (c) 2007 Paul Walmsley
  *  Copyright (c) 2008 Jiri Slaby <jirislaby@gmail.com>
  */
 
diff --git a/drivers/hid/hid-aureal.c b/drivers/hid/hid-aureal.c
index ba64b04..7968187 100644
--- a/drivers/hid/hid-aureal.c
+++ b/drivers/hid/hid-aureal.c
@@ -9,7 +9,6 @@
  *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
  *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
  *  Copyright (c) 2006-2007 Jiri Kosina
- *  Copyright (c) 2007 Paul Walmsley
  *  Copyright (c) 2008 Jiri Slaby
  */
 #include <linux/device.h>
diff --git a/drivers/hid/hid-belkin.c b/drivers/hid/hid-belkin.c
index a1a765a..a1a5a12 100644
--- a/drivers/hid/hid-belkin.c
+++ b/drivers/hid/hid-belkin.c
@@ -5,7 +5,6 @@
  *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
  *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
  *  Copyright (c) 2006-2007 Jiri Kosina
- *  Copyright (c) 2007 Paul Walmsley
  *  Copyright (c) 2008 Jiri Slaby
  */
 
diff --git a/drivers/hid/hid-cherry.c b/drivers/hid/hid-cherry.c
index 888ece6..af034d3 100644
--- a/drivers/hid/hid-cherry.c
+++ b/drivers/hid/hid-cherry.c
@@ -5,7 +5,6 @@
  *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
  *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
  *  Copyright (c) 2006-2007 Jiri Kosina
- *  Copyright (c) 2007 Paul Walmsley
  *  Copyright (c) 2008 Jiri Slaby
  */
 
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 8bcd168..a9bb940 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -126,7 +126,7 @@ static int open_collection(struct hid_parser *parser, unsigned type)
 
 	if (parser->collection_stack_ptr == HID_COLLECTION_STACK_SIZE) {
 		hid_err(parser->device, "collection stack overflow\n");
-		return -1;
+		return -EINVAL;
 	}
 
 	if (parser->device->maxcollection == parser->device->collection_size) {
@@ -134,7 +134,7 @@ static int open_collection(struct hid_parser *parser, unsigned type)
 				parser->device->collection_size * 2, GFP_KERNEL);
 		if (collection == NULL) {
 			hid_err(parser->device, "failed to reallocate collection array\n");
-			return -1;
+			return -ENOMEM;
 		}
 		memcpy(collection, parser->device->collection,
 			sizeof(struct hid_collection) *
@@ -170,7 +170,7 @@ static int close_collection(struct hid_parser *parser)
 {
 	if (!parser->collection_stack_ptr) {
 		hid_err(parser->device, "collection stack underflow\n");
-		return -1;
+		return -EINVAL;
 	}
 	parser->collection_stack_ptr--;
 	return 0;
@@ -374,7 +374,7 @@ static int hid_parser_global(struct hid_parser *parser, struct hid_item *item)
 
 	case HID_GLOBAL_ITEM_TAG_REPORT_SIZE:
 		parser->global.report_size = item_udata(item);
-		if (parser->global.report_size > 96) {
+		if (parser->global.report_size > 128) {
 			hid_err(parser->device, "invalid report_size %d\n",
 					parser->global.report_size);
 			return -1;
@@ -1448,7 +1448,14 @@ void hid_disconnect(struct hid_device *hdev)
 }
 EXPORT_SYMBOL_GPL(hid_disconnect);
 
-/* a list of devices for which there is a specialized driver on HID bus */
+/*
+ * A list of devices for which there is a specialized driver on HID bus.
+ *
+ * Please note that for multitouch devices (driven by hid-multitouch driver),
+ * there is a proper autodetection and autoloading in place (based on presence
+ * of HID_DG_CONTACTID), so those devices don't need to be added to this list,
+ * as we are doing the right thing in hid_scan_usage().
+ */
 static const struct hid_device_id hid_have_special_driver[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D) },
@@ -1551,6 +1558,10 @@ static const struct hid_device_id hid_have_special_driver[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_3) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK, USB_DEVICE_ID_HOLTEK_ON_LINE_GRIP) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_INTEL_8086, USB_DEVICE_ID_SENSOR_HUB_1020) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_INTEL_8086, USB_DEVICE_ID_SENSOR_HUB_09FA) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_INTEL_8087, USB_DEVICE_ID_SENSOR_HUB_1020) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_INTEL_8087, USB_DEVICE_ID_SENSOR_HUB_09FA) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_KEYTOUCH, USB_DEVICE_ID_KEYTOUCH_IEC) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) },
@@ -1627,6 +1638,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_KEYBOARD) },
+#if IS_ENABLED(CONFIG_HID_ROCCAT)
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONE) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ARVO) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ISKU) },
@@ -1635,6 +1647,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRED) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRELESS) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_SAVU) },
+#endif
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_PS1000) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE) },
@@ -1644,6 +1657,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_STANTUM_STM, USB_DEVICE_ID_SENSOR_HUB_7014) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb300) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb304) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb323) },
@@ -1663,6 +1677,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP1062) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_TWHA60) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SMARTJOY_PLUS) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SUPER_JOY_BOX_3) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD) },
diff --git a/drivers/hid/hid-cypress.c b/drivers/hid/hid-cypress.c
index 9e43aac..3e159a5 100644
--- a/drivers/hid/hid-cypress.c
+++ b/drivers/hid/hid-cypress.c
@@ -5,7 +5,6 @@
  *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
  *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
  *  Copyright (c) 2006-2007 Jiri Kosina
- *  Copyright (c) 2007 Paul Walmsley
  *  Copyright (c) 2008 Jiri Slaby
  */
 
diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c
index 01dd9a7..933fff0 100644
--- a/drivers/hid/hid-debug.c
+++ b/drivers/hid/hid-debug.c
@@ -911,15 +911,21 @@ static void hid_dump_input_mapping(struct hid_device *hid, struct seq_file *f)
 
 }
 
-
 static int hid_debug_rdesc_show(struct seq_file *f, void *p)
 {
 	struct hid_device *hdev = f->private;
+	const __u8 *rdesc = hdev->rdesc;
+	unsigned rsize = hdev->rsize;
 	int i;
 
+	if (!rdesc) {
+		rdesc = hdev->dev_rdesc;
+		rsize = hdev->dev_rsize;
+	}
+
 	/* dump HID report descriptor */
-	for (i = 0; i < hdev->rsize; i++)
-		seq_printf(f, "%02x ", hdev->rdesc[i]);
+	for (i = 0; i < rsize; i++)
+		seq_printf(f, "%02x ", rdesc[i]);
 	seq_printf(f, "\n\n");
 
 	/* dump parsed data and input mappings */
diff --git a/drivers/hid/hid-ezkey.c b/drivers/hid/hid-ezkey.c
index ca1163e..6540af2 100644
--- a/drivers/hid/hid-ezkey.c
+++ b/drivers/hid/hid-ezkey.c
@@ -5,7 +5,6 @@
  *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
  *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
  *  Copyright (c) 2006-2007 Jiri Kosina
- *  Copyright (c) 2007 Paul Walmsley
  *  Copyright (c) 2008 Jiri Slaby
  */
 
diff --git a/drivers/hid/hid-gyration.c b/drivers/hid/hid-gyration.c
index e88b951..4442c30 100644
--- a/drivers/hid/hid-gyration.c
+++ b/drivers/hid/hid-gyration.c
@@ -4,7 +4,6 @@
  *  Copyright (c) 1999 Andreas Gal
  *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
  *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
- *  Copyright (c) 2007 Paul Walmsley
  *  Copyright (c) 2008 Jiri Slaby
  *  Copyright (c) 2006-2008 Jiri Kosina
  */
diff --git a/drivers/hid/hid-holtekff.c b/drivers/hid/hid-holtekff.c
index 4e75421..ff295e6 100644
--- a/drivers/hid/hid-holtekff.c
+++ b/drivers/hid/hid-holtekff.c
@@ -100,8 +100,7 @@ static void holtekff_send(struct holtekff_device *holtekff,
 		holtekff->field->value[i] = data[i];
 	}
 
-	dbg_hid("sending %02x %02x %02x %02x %02x %02x %02x\n", data[0],
-		data[1], data[2], data[3], data[4], data[5], data[6]);
+	dbg_hid("sending %*ph\n", 7, data);
 
 	usbhid_submit_report(hid, holtekff->field->report, USB_DIR_OUT);
 }
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 1dcb76f..d08a4cf 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -5,7 +5,6 @@
  *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
  *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
  *  Copyright (c) 2006-2007 Jiri Kosina
- *  Copyright (c) 2007 Paul Walmsley
  */
 
 /*
@@ -269,7 +268,11 @@
 #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72FA	0x72fa
 #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7302	0x7302
 #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7349	0x7349
+#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_73F7	0x73f7
 #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001	0xa001
+#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7224      0x7224
+#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72D0      0x72d0
+#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72C4      0x72c4
 
 #define USB_VENDOR_ID_ELECOM		0x056e
 #define USB_DEVICE_ID_ELECOM_BM084	0x0061
@@ -283,6 +286,9 @@
 #define USB_VENDOR_ID_EMS		0x2006
 #define USB_DEVICE_ID_EMS_TRIO_LINKER_PLUS_II 0x0118
 
+#define USB_VENDOR_ID_FLATFROG		0x25b5
+#define USB_DEVICE_ID_MULTITOUCH_3200	0x0002
+
 #define USB_VENDOR_ID_ESSENTIAL_REALITY	0x0d7f
 #define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100
 
@@ -296,6 +302,9 @@
 #define USB_VENDOR_ID_EZKEY		0x0518
 #define USB_DEVICE_ID_BTC_8193		0x0002
 
+#define USB_VENDOR_ID_FREESCALE		0x15A2
+#define USB_DEVICE_ID_FREESCALE_MX28	0x004F
+
 #define USB_VENDOR_ID_FRUCTEL	0x25B6
 #define USB_DEVICE_ID_GAMETEL_MT_MODE	0x0002
 
@@ -419,6 +428,11 @@
 #define USB_VENDOR_ID_IMATION		0x0718
 #define USB_DEVICE_ID_DISC_STAKKA	0xd000
 
+#define USB_VENDOR_ID_INTEL_8086	0x8086
+#define USB_VENDOR_ID_INTEL_8087	0x8087
+#define USB_DEVICE_ID_SENSOR_HUB_1020	0x1020
+#define USB_DEVICE_ID_SENSOR_HUB_09FA	0x09FA
+
 #define USB_VENDOR_ID_IRTOUCHSYSTEMS	0x6615
 #define USB_DEVICE_ID_IRTOUCH_INFRARED_USB	0x0070
 
@@ -652,7 +666,6 @@
 #define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH		0x3000
 #define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001		0x3001
 #define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008		0x3008
-#define USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN	0x3001
 
 #define USB_VENDOR_ID_ROCCAT		0x1e7d
 #define USB_DEVICE_ID_ROCCAT_ARVO	0x30d4
@@ -695,6 +708,7 @@
 
 #define USB_VENDOR_ID_STANTUM_STM		0x0483
 #define USB_DEVICE_ID_MTP_STM		0x3261
+#define USB_DEVICE_ID_SENSOR_HUB_7014	0x7014
 
 #define USB_VENDOR_ID_STANTUM_SITRONIX		0x1403
 #define USB_DEVICE_ID_MTP_SITRONIX		0x5001
@@ -758,6 +772,7 @@
 #define USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U	0x0005
 #define USB_DEVICE_ID_UCLOGIC_TABLET_WP1062	0x0064
 #define USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850	0x0522
+#define USB_DEVICE_ID_UCLOGIC_TABLET_TWHA60	0x0781
 
 #define USB_VENDOR_ID_UNITEC	0x227d
 #define USB_DEVICE_ID_UNITEC_USB_TOUCH_0709	0x0709
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 811bfad..d917c0d 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -1154,6 +1154,7 @@ static void report_features(struct hid_device *hid)
 
 int hidinput_connect(struct hid_device *hid, unsigned int force)
 {
+	struct hid_driver *drv = hid->driver;
 	struct hid_report *report;
 	struct hid_input *hidinput = NULL;
 	struct input_dev *input_dev;
@@ -1228,6 +1229,8 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
 				 * UGCI) cram a lot of unrelated inputs into the
 				 * same interface. */
 				hidinput->report = report;
+				if (drv->input_configured)
+					drv->input_configured(hid, hidinput);
 				if (input_register_device(hidinput->input))
 					goto out_cleanup;
 				hidinput = NULL;
@@ -1235,8 +1238,12 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
 		}
 	}
 
-	if (hidinput && input_register_device(hidinput->input))
-		goto out_cleanup;
+	if (hidinput) {
+		if (drv->input_configured)
+			drv->input_configured(hid, hidinput);
+		if (input_register_device(hidinput->input))
+			goto out_cleanup;
+	}
 
 	return 0;
 
diff --git a/drivers/hid/hid-lcpower.c b/drivers/hid/hid-lcpower.c
index c4fe9bd0..22bc14a 100644
--- a/drivers/hid/hid-lcpower.c
+++ b/drivers/hid/hid-lcpower.c
@@ -24,7 +24,7 @@ static int ts_input_mapping(struct hid_device *hdev, struct hid_input *hi,
 		struct hid_field *field, struct hid_usage *usage,
 		unsigned long **bit, int *max)
 {
-	if ((usage->hid & HID_USAGE_PAGE) != 0x0ffbc0000)
+	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR)
 		return 0;
 
 	switch (usage->hid & HID_USAGE) {
diff --git a/drivers/hid/hid-lenovo-tpkbd.c b/drivers/hid/hid-lenovo-tpkbd.c
index 60c4e1e..cea016e 100644
--- a/drivers/hid/hid-lenovo-tpkbd.c
+++ b/drivers/hid/hid-lenovo-tpkbd.c
@@ -56,9 +56,8 @@ static int tpkbd_input_mapping(struct hid_device *hdev,
 static int tpkbd_features_set(struct hid_device *hdev)
 {
 	struct hid_report *report;
-	struct tpkbd_data_pointer *data_pointer;
+	struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
 
-	data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev);
 	report = hdev->report_enum[HID_FEATURE_REPORT].report_id_hash[4];
 
 	report->field[0]->value[0]  = data_pointer->press_to_select   ? 0x01 : 0x02;
@@ -77,14 +76,8 @@ static ssize_t pointer_press_to_select_show(struct device *dev,
 		struct device_attribute *attr,
 		char *buf)
 {
-	struct hid_device *hdev;
-	struct tpkbd_data_pointer *data_pointer;
-
-	hdev = container_of(dev, struct hid_device, dev);
-	if (hdev == NULL)
-		return -ENODEV;
-
-	data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev);
+	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+	struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
 
 	return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->press_to_select);
 }
@@ -94,16 +87,10 @@ static ssize_t pointer_press_to_select_store(struct device *dev,
 		const char *buf,
 		size_t count)
 {
-	struct hid_device *hdev;
-	struct tpkbd_data_pointer *data_pointer;
+	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+	struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
 	int value;
 
-	hdev = container_of(dev, struct hid_device, dev);
-	if (hdev == NULL)
-		return -ENODEV;
-
-	data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev);
-
 	if (kstrtoint(buf, 10, &value))
 		return -EINVAL;
 	if (value < 0 || value > 1)
@@ -119,14 +106,8 @@ static ssize_t pointer_dragging_show(struct device *dev,
 		struct device_attribute *attr,
 		char *buf)
 {
-	struct hid_device *hdev;
-	struct tpkbd_data_pointer *data_pointer;
-
-	hdev = container_of(dev, struct hid_device, dev);
-	if (hdev == NULL)
-		return -ENODEV;
-
-	data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev);
+	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+	struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
 
 	return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->dragging);
 }
@@ -136,16 +117,10 @@ static ssize_t pointer_dragging_store(struct device *dev,
 		const char *buf,
 		size_t count)
 {
-	struct hid_device *hdev;
-	struct tpkbd_data_pointer *data_pointer;
+	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+	struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
 	int value;
 
-	hdev = container_of(dev, struct hid_device, dev);
-	if (hdev == NULL)
-		return -ENODEV;
-
-	data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev);
-
 	if (kstrtoint(buf, 10, &value))
 		return -EINVAL;
 	if (value < 0 || value > 1)
@@ -161,14 +136,8 @@ static ssize_t pointer_release_to_select_show(struct device *dev,
 		struct device_attribute *attr,
 		char *buf)
 {
-	struct hid_device *hdev;
-	struct tpkbd_data_pointer *data_pointer;
-
-	hdev = container_of(dev, struct hid_device, dev);
-	if (hdev == NULL)
-		return -ENODEV;
-
-	data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev);
+	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+	struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
 
 	return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->release_to_select);
 }
@@ -178,16 +147,10 @@ static ssize_t pointer_release_to_select_store(struct device *dev,
 		const char *buf,
 		size_t count)
 {
-	struct hid_device *hdev;
-	struct tpkbd_data_pointer *data_pointer;
+	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+	struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
 	int value;
 
-	hdev = container_of(dev, struct hid_device, dev);
-	if (hdev == NULL)
-		return -ENODEV;
-
-	data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev);
-
 	if (kstrtoint(buf, 10, &value))
 		return -EINVAL;
 	if (value < 0 || value > 1)
@@ -203,14 +166,8 @@ static ssize_t pointer_select_right_show(struct device *dev,
 		struct device_attribute *attr,
 		char *buf)
 {
-	struct hid_device *hdev;
-	struct tpkbd_data_pointer *data_pointer;
-
-	hdev = container_of(dev, struct hid_device, dev);
-	if (hdev == NULL)
-		return -ENODEV;
-
-	data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev);
+	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+	struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
 
 	return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->select_right);
 }
@@ -220,16 +177,10 @@ static ssize_t pointer_select_right_store(struct device *dev,
 		const char *buf,
 		size_t count)
 {
-	struct hid_device *hdev;
-	struct tpkbd_data_pointer *data_pointer;
+	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+	struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
 	int value;
 
-	hdev = container_of(dev, struct hid_device, dev);
-	if (hdev == NULL)
-		return -ENODEV;
-
-	data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev);
-
 	if (kstrtoint(buf, 10, &value))
 		return -EINVAL;
 	if (value < 0 || value > 1)
@@ -245,14 +196,8 @@ static ssize_t pointer_sensitivity_show(struct device *dev,
 		struct device_attribute *attr,
 		char *buf)
 {
-	struct hid_device *hdev;
-	struct tpkbd_data_pointer *data_pointer;
-
-	hdev = container_of(dev, struct hid_device, dev);
-	if (hdev == NULL)
-		return -ENODEV;
-
-	data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev);
+	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+	struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
 
 	return snprintf(buf, PAGE_SIZE, "%u\n",
 		data_pointer->sensitivity);
@@ -263,16 +208,10 @@ static ssize_t pointer_sensitivity_store(struct device *dev,
 		const char *buf,
 		size_t count)
 {
-	struct hid_device *hdev;
-	struct tpkbd_data_pointer *data_pointer;
+	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+	struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
 	int value;
 
-	hdev = container_of(dev, struct hid_device, dev);
-	if (hdev == NULL)
-		return -ENODEV;
-
-	data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev);
-
 	if (kstrtoint(buf, 10, &value) || value < 1 || value > 255)
 		return -EINVAL;
 
@@ -286,14 +225,10 @@ static ssize_t pointer_press_speed_show(struct device *dev,
 		struct device_attribute *attr,
 		char *buf)
 {
-	struct hid_device *hdev;
-	struct tpkbd_data_pointer *data_pointer;
+	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+	struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
 
-	hdev = container_of(dev, struct hid_device, dev);
-	if (hdev == NULL)
-		return -ENODEV;
-
-	data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev);
+	data_pointer = hid_get_drvdata(hdev);
 
 	return snprintf(buf, PAGE_SIZE, "%u\n",
 		data_pointer->press_speed);
@@ -304,16 +239,10 @@ static ssize_t pointer_press_speed_store(struct device *dev,
 		const char *buf,
 		size_t count)
 {
-	struct hid_device *hdev;
-	struct tpkbd_data_pointer *data_pointer;
+	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+	struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
 	int value;
 
-	hdev = container_of(dev, struct hid_device, dev);
-	if (hdev == NULL)
-		return -ENODEV;
-
-	data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev);
-
 	if (kstrtoint(buf, 10, &value) || value < 1 || value > 255)
 		return -EINVAL;
 
@@ -370,15 +299,11 @@ static const struct attribute_group tpkbd_attr_group_pointer = {
 static enum led_brightness tpkbd_led_brightness_get(
 			struct led_classdev *led_cdev)
 {
-	struct device *dev;
-	struct hid_device *hdev;
-	struct tpkbd_data_pointer *data_pointer;
+	struct device *dev = led_cdev->dev->parent;
+	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+	struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
 	int led_nr = 0;
 
-	dev = led_cdev->dev->parent;
-	hdev = container_of(dev, struct hid_device, dev);
-	data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev);
-
 	if (led_cdev == &data_pointer->led_micmute)
 		led_nr = 1;
 
@@ -390,16 +315,12 @@ static enum led_brightness tpkbd_led_brightness_get(
 static void tpkbd_led_brightness_set(struct led_classdev *led_cdev,
 			enum led_brightness value)
 {
-	struct device *dev;
-	struct hid_device *hdev;
+	struct device *dev = led_cdev->dev->parent;
+	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+	struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
 	struct hid_report *report;
-	struct tpkbd_data_pointer *data_pointer;
 	int led_nr = 0;
 
-	dev = led_cdev->dev->parent;
-	hdev = container_of(dev, struct hid_device, dev);
-	data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev);
-
 	if (led_cdev == &data_pointer->led_micmute)
 		led_nr = 1;
 
@@ -508,13 +429,11 @@ err_free:
 
 static void tpkbd_remove_tp(struct hid_device *hdev)
 {
-	struct tpkbd_data_pointer *data_pointer;
+	struct tpkbd_data_pointer *data_pointer = hid_get_drvdata(hdev);
 
 	sysfs_remove_group(&hdev->dev.kobj,
 			&tpkbd_attr_group_pointer);
 
-	data_pointer = (struct tpkbd_data_pointer *) hid_get_drvdata(hdev);
-
 	led_classdev_unregister(&data_pointer->led_micmute);
 	led_classdev_unregister(&data_pointer->led_mute);
 
diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c
index fc37ed6..a2f8e88 100644
--- a/drivers/hid/hid-lg.c
+++ b/drivers/hid/hid-lg.c
@@ -5,7 +5,6 @@
  *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
  *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
  *  Copyright (c) 2006-2007 Jiri Kosina
- *  Copyright (c) 2007 Paul Walmsley
  *  Copyright (c) 2008 Jiri Slaby
  *  Copyright (c) 2010 Hendrik Iben
  */
@@ -109,7 +108,7 @@ static __u8 dfp_rdesc_fixed[] = {
 static __u8 *lg_report_fixup(struct hid_device *hdev, __u8 *rdesc,
 		unsigned int *rsize)
 {
-	struct lg_drv_data *drv_data = (struct lg_drv_data *)hid_get_drvdata(hdev);
+	struct lg_drv_data *drv_data = hid_get_drvdata(hdev);
 
 	if ((drv_data->quirks & LG_RDESC) && *rsize >= 90 && rdesc[83] == 0x26 &&
 			rdesc[84] == 0x8c && rdesc[85] == 0x02) {
@@ -278,7 +277,7 @@ static int lg_input_mapping(struct hid_device *hdev, struct hid_input *hi,
 		  0,  0,  0,  0,  0,183,184,185,186,187,
 		188,189,190,191,192,193,194,  0,  0,  0
 	};
-	struct lg_drv_data *drv_data = (struct lg_drv_data *)hid_get_drvdata(hdev);
+	struct lg_drv_data *drv_data = hid_get_drvdata(hdev);
 	unsigned int hid = usage->hid;
 
 	if (hdev->product == USB_DEVICE_ID_LOGITECH_RECEIVER &&
@@ -319,7 +318,7 @@ static int lg_input_mapped(struct hid_device *hdev, struct hid_input *hi,
 		struct hid_field *field, struct hid_usage *usage,
 		unsigned long **bit, int *max)
 {
-	struct lg_drv_data *drv_data = (struct lg_drv_data *)hid_get_drvdata(hdev);
+	struct lg_drv_data *drv_data = hid_get_drvdata(hdev);
 
 	if ((drv_data->quirks & LG_BAD_RELATIVE_KEYS) && usage->type == EV_KEY &&
 			(field->flags & HID_MAIN_ITEM_RELATIVE))
@@ -335,13 +334,16 @@ static int lg_input_mapped(struct hid_device *hdev, struct hid_input *hi,
 static int lg_event(struct hid_device *hdev, struct hid_field *field,
 		struct hid_usage *usage, __s32 value)
 {
-	struct lg_drv_data *drv_data = (struct lg_drv_data *)hid_get_drvdata(hdev);
+	struct lg_drv_data *drv_data = hid_get_drvdata(hdev);
 
 	if ((drv_data->quirks & LG_INVERT_HWHEEL) && usage->code == REL_HWHEEL) {
 		input_event(field->hidinput->input, usage->type, usage->code,
 				-value);
 		return 1;
 	}
+	if (drv_data->quirks & LG_FF4) {
+		return lg4ff_adjust_input_event(hdev, field, usage, value, drv_data);
+	}
 
 	return 0;
 }
@@ -358,7 +360,7 @@ static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id)
 		return -ENOMEM;
 	}
 	drv_data->quirks = id->driver_data;
-	
+
 	hid_set_drvdata(hdev, (void *)drv_data);
 
 	if (drv_data->quirks & LG_NOGET)
@@ -380,7 +382,7 @@ static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id)
 	}
 
 	/* Setup wireless link with Logitech Wii wheel */
-	if(hdev->product == USB_DEVICE_ID_LOGITECH_WII_WHEEL) {
+	if (hdev->product == USB_DEVICE_ID_LOGITECH_WII_WHEEL) {
 		unsigned char buf[] = { 0x00, 0xAF,  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
 
 		ret = hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT);
@@ -416,7 +418,7 @@ err_free:
 
 static void lg_remove(struct hid_device *hdev)
 {
-	struct lg_drv_data *drv_data = (struct lg_drv_data *)hid_get_drvdata(hdev);
+	struct lg_drv_data *drv_data = hid_get_drvdata(hdev);
 	if (drv_data->quirks & LG_FF4)
 		lg4ff_deinit(hdev);
 
@@ -476,7 +478,7 @@ static const struct hid_device_id lg_devices[] = {
 		.driver_data = LG_NOGET | LG_FF4 },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WII_WHEEL),
 		.driver_data = LG_FF4 },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_FFG ),
+	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_FFG),
 		.driver_data = LG_FF },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2),
 		.driver_data = LG_FF2 },
diff --git a/drivers/hid/hid-lg.h b/drivers/hid/hid-lg.h
index d64cf8d..142ce3f 100644
--- a/drivers/hid/hid-lg.h
+++ b/drivers/hid/hid-lg.h
@@ -25,9 +25,13 @@ static inline int lg3ff_init(struct hid_device *hdev) { return -1; }
 #endif
 
 #ifdef CONFIG_LOGIWHEELS_FF
+int lg4ff_adjust_input_event(struct hid_device *hid, struct hid_field *field,
+			     struct hid_usage *usage, __s32 value, struct lg_drv_data *drv_data);
 int lg4ff_init(struct hid_device *hdev);
 int lg4ff_deinit(struct hid_device *hdev);
 #else
+static inline int lg4ff_adjust_input_event(struct hid_device *hid, struct hid_field *field,
+					   struct hid_usage *usage, __s32 value, struct lg_drv_data *drv_data) { return 0; }
 static inline int lg4ff_init(struct hid_device *hdev) { return -1; }
 static inline int lg4ff_deinit(struct hid_device *hdev) { return -1; }
 #endif
diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c
index f3390ee..d7947c7 100644
--- a/drivers/hid/hid-lg4ff.c
+++ b/drivers/hid/hid-lg4ff.c
@@ -43,6 +43,11 @@
 #define G27_REV_MAJ 0x12
 #define G27_REV_MIN 0x38
 
+#define DFP_X_MIN 0
+#define DFP_X_MAX 16383
+#define DFP_PEDAL_MIN 0
+#define DFP_PEDAL_MAX 255
+
 #define to_hid_device(pdev) container_of(pdev, struct hid_device, dev)
 
 static void hid_lg4ff_set_range_dfp(struct hid_device *hid, u16 range);
@@ -53,6 +58,7 @@ static ssize_t lg4ff_range_store(struct device *dev, struct device_attribute *at
 static DEVICE_ATTR(range, S_IRWXU | S_IRWXG | S_IRWXO, lg4ff_range_show, lg4ff_range_store);
 
 struct lg4ff_device_entry {
+	__u32 product_id;
 	__u16 range;
 	__u16 min_range;
 	__u16 max_range;
@@ -129,26 +135,77 @@ static const struct lg4ff_usb_revision lg4ff_revs[] = {
 	{G27_REV_MAJ,  G27_REV_MIN,  &native_g27},	/* G27 */
 };
 
+/* Recalculates X axis value accordingly to currently selected range */
+static __s32 lg4ff_adjust_dfp_x_axis(__s32 value, __u16 range)
+{
+	__u16 max_range;
+	__s32 new_value;
+
+	if (range == 900)
+		return value;
+	else if (range == 200)
+		return value;
+	else if (range < 200)
+		max_range = 200;
+	else
+		max_range = 900;
+
+	new_value = 8192 + mult_frac(value - 8192, max_range, range);
+	if (new_value < 0)
+		return 0;
+	else if (new_value > 16383)
+		return 16383;
+	else
+		return new_value;
+}
+
+int lg4ff_adjust_input_event(struct hid_device *hid, struct hid_field *field,
+			     struct hid_usage *usage, __s32 value, struct lg_drv_data *drv_data)
+{
+	struct lg4ff_device_entry *entry = drv_data->device_props;
+	__s32 new_value = 0;
+
+	if (!entry) {
+		hid_err(hid, "Device properties not found");
+		return 0;
+	}
+
+	switch (entry->product_id) {
+	case USB_DEVICE_ID_LOGITECH_DFP_WHEEL:
+		switch (usage->code) {
+		case ABS_X:
+			new_value = lg4ff_adjust_dfp_x_axis(value, entry->range);
+			input_event(field->hidinput->input, usage->type, usage->code, new_value);
+			return 1;
+		default:
+			return 0;
+		}
+	default:
+		return 0;
+	}
+}
+
 static int hid_lg4ff_play(struct input_dev *dev, void *data, struct ff_effect *effect)
 {
 	struct hid_device *hid = input_get_drvdata(dev);
 	struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
 	struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
+	__s32 *value = report->field[0]->value;
 	int x;
 
-#define CLAMP(x) if (x < 0) x = 0; if (x > 0xff) x = 0xff
+#define CLAMP(x) do { if (x < 0) x = 0; else if (x > 0xff) x = 0xff; } while (0)
 
 	switch (effect->type) {
 	case FF_CONSTANT:
 		x = effect->u.ramp.start_level + 0x80;	/* 0x80 is no force */
 		CLAMP(x);
-		report->field[0]->value[0] = 0x11;	/* Slot 1 */
-		report->field[0]->value[1] = 0x08;
-		report->field[0]->value[2] = x;
-		report->field[0]->value[3] = 0x80;
-		report->field[0]->value[4] = 0x00;
-		report->field[0]->value[5] = 0x00;
-		report->field[0]->value[6] = 0x00;
+		value[0] = 0x11;	/* Slot 1 */
+		value[1] = 0x08;
+		value[2] = x;
+		value[3] = 0x80;
+		value[4] = 0x00;
+		value[5] = 0x00;
+		value[6] = 0x00;
 
 		usbhid_submit_report(hid, report, USB_DIR_OUT);
 		break;
@@ -163,14 +220,15 @@ static void hid_lg4ff_set_autocenter_default(struct input_dev *dev, u16 magnitud
 	struct hid_device *hid = input_get_drvdata(dev);
 	struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
 	struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
+	__s32 *value = report->field[0]->value;
 
-	report->field[0]->value[0] = 0xfe;
-	report->field[0]->value[1] = 0x0d;
-	report->field[0]->value[2] = magnitude >> 13;
-	report->field[0]->value[3] = magnitude >> 13;
-	report->field[0]->value[4] = magnitude >> 8;
-	report->field[0]->value[5] = 0x00;
-	report->field[0]->value[6] = 0x00;
+	value[0] = 0xfe;
+	value[1] = 0x0d;
+	value[2] = magnitude >> 13;
+	value[3] = magnitude >> 13;
+	value[4] = magnitude >> 8;
+	value[5] = 0x00;
+	value[6] = 0x00;
 
 	usbhid_submit_report(hid, report, USB_DIR_OUT);
 }
@@ -181,16 +239,16 @@ static void hid_lg4ff_set_autocenter_ffex(struct input_dev *dev, u16 magnitude)
 	struct hid_device *hid = input_get_drvdata(dev);
 	struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
 	struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
+	__s32 *value = report->field[0]->value;
 	magnitude = magnitude * 90 / 65535;
-	
 
-	report->field[0]->value[0] = 0xfe;
-	report->field[0]->value[1] = 0x03;
-	report->field[0]->value[2] = magnitude >> 14;
-	report->field[0]->value[3] = magnitude >> 14;
-	report->field[0]->value[4] = magnitude;
-	report->field[0]->value[5] = 0x00;
-	report->field[0]->value[6] = 0x00;
+	value[0] = 0xfe;
+	value[1] = 0x03;
+	value[2] = magnitude >> 14;
+	value[3] = magnitude >> 14;
+	value[4] = magnitude;
+	value[5] = 0x00;
+	value[6] = 0x00;
 
 	usbhid_submit_report(hid, report, USB_DIR_OUT);
 }
@@ -200,15 +258,17 @@ static void hid_lg4ff_set_range_g25(struct hid_device *hid, u16 range)
 {
 	struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
 	struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
+	__s32 *value = report->field[0]->value;
+
 	dbg_hid("G25/G27/DFGT: setting range to %u\n", range);
 
-	report->field[0]->value[0] = 0xf8;
-	report->field[0]->value[1] = 0x81;
-	report->field[0]->value[2] = range & 0x00ff;
-	report->field[0]->value[3] = (range & 0xff00) >> 8;
-	report->field[0]->value[4] = 0x00;
-	report->field[0]->value[5] = 0x00;
-	report->field[0]->value[6] = 0x00;
+	value[0] = 0xf8;
+	value[1] = 0x81;
+	value[2] = range & 0x00ff;
+	value[3] = (range & 0xff00) >> 8;
+	value[4] = 0x00;
+	value[5] = 0x00;
+	value[6] = 0x00;
 
 	usbhid_submit_report(hid, report, USB_DIR_OUT);
 }
@@ -219,16 +279,18 @@ static void hid_lg4ff_set_range_dfp(struct hid_device *hid, __u16 range)
 	struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
 	struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
 	int start_left, start_right, full_range;
+	__s32 *value = report->field[0]->value;
+
 	dbg_hid("Driving Force Pro: setting range to %u\n", range);
 
 	/* Prepare "coarse" limit command */
-	report->field[0]->value[0] = 0xf8;
-	report->field[0]->value[1] = 0x00; 	/* Set later */
-	report->field[0]->value[2] = 0x00;
-	report->field[0]->value[3] = 0x00;
-	report->field[0]->value[4] = 0x00;
-	report->field[0]->value[5] = 0x00;
-	report->field[0]->value[6] = 0x00;
+	value[0] = 0xf8;
+	value[1] = 0x00;	/* Set later */
+	value[2] = 0x00;
+	value[3] = 0x00;
+	value[4] = 0x00;
+	value[5] = 0x00;
+	value[6] = 0x00;
 
 	if (range > 200) {
 		report->field[0]->value[1] = 0x03;
@@ -240,13 +302,13 @@ static void hid_lg4ff_set_range_dfp(struct hid_device *hid, __u16 range)
 	usbhid_submit_report(hid, report, USB_DIR_OUT);
 
 	/* Prepare "fine" limit command */
-	report->field[0]->value[0] = 0x81;
-	report->field[0]->value[1] = 0x0b;
-	report->field[0]->value[2] = 0x00;
-	report->field[0]->value[3] = 0x00;
-	report->field[0]->value[4] = 0x00;
-	report->field[0]->value[5] = 0x00;
-	report->field[0]->value[6] = 0x00;
+	value[0] = 0x81;
+	value[1] = 0x0b;
+	value[2] = 0x00;
+	value[3] = 0x00;
+	value[4] = 0x00;
+	value[5] = 0x00;
+	value[6] = 0x00;
 
 	if (range == 200 || range == 900) {	/* Do not apply any fine limit */
 		usbhid_submit_report(hid, report, USB_DIR_OUT);
@@ -257,11 +319,11 @@ static void hid_lg4ff_set_range_dfp(struct hid_device *hid, __u16 range)
 	start_left = (((full_range - range + 1) * 2047) / full_range);
 	start_right = 0xfff - start_left;
 
-	report->field[0]->value[2] = start_left >> 4;
-	report->field[0]->value[3] = start_right >> 4;
-	report->field[0]->value[4] = 0xff;
-	report->field[0]->value[5] = (start_right & 0xe) << 4 | (start_left & 0xe);
-	report->field[0]->value[6] = 0xff;
+	value[2] = start_left >> 4;
+	value[3] = start_right >> 4;
+	value[4] = 0xff;
+	value[5] = (start_right & 0xe) << 4 | (start_left & 0xe);
+	value[6] = 0xff;
 
 	usbhid_submit_report(hid, report, USB_DIR_OUT);
 }
@@ -344,14 +406,15 @@ static void lg4ff_set_leds(struct hid_device *hid, __u8 leds)
 {
 	struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
 	struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
-
-	report->field[0]->value[0] = 0xf8;
-	report->field[0]->value[1] = 0x12;
-	report->field[0]->value[2] = leds;
-	report->field[0]->value[3] = 0x00;
-	report->field[0]->value[4] = 0x00;
-	report->field[0]->value[5] = 0x00;
-	report->field[0]->value[6] = 0x00;
+	__s32 *value = report->field[0]->value;
+
+	value[0] = 0xf8;
+	value[1] = 0x12;
+	value[2] = leds;
+	value[3] = 0x00;
+	value[4] = 0x00;
+	value[5] = 0x00;
+	value[6] = 0x00;
 	usbhid_submit_report(hid, report, USB_DIR_OUT);
 }
 
@@ -360,7 +423,7 @@ static void lg4ff_led_set_brightness(struct led_classdev *led_cdev,
 {
 	struct device *dev = led_cdev->dev->parent;
 	struct hid_device *hid = container_of(dev, struct hid_device, dev);
-	struct lg_drv_data *drv_data = (struct lg_drv_data *)hid_get_drvdata(hid);
+	struct lg_drv_data *drv_data = hid_get_drvdata(hid);
 	struct lg4ff_device_entry *entry;
 	int i, state = 0;
 
@@ -395,7 +458,7 @@ static enum led_brightness lg4ff_led_get_brightness(struct led_classdev *led_cde
 {
 	struct device *dev = led_cdev->dev->parent;
 	struct hid_device *hid = container_of(dev, struct hid_device, dev);
-	struct lg_drv_data *drv_data = (struct lg_drv_data *)hid_get_drvdata(hid);
+	struct lg_drv_data *drv_data = hid_get_drvdata(hid);
 	struct lg4ff_device_entry *entry;
 	int i, value = 0;
 
@@ -501,7 +564,7 @@ int lg4ff_init(struct hid_device *hid)
 	/* Check if autocentering is available and
 	 * set the centering force to zero by default */
 	if (test_bit(FF_AUTOCENTER, dev->ffbit)) {
-		if(rev_maj == FFEX_REV_MAJ && rev_min == FFEX_REV_MIN)	/* Formula Force EX expects different autocentering command */
+		if (rev_maj == FFEX_REV_MAJ && rev_min == FFEX_REV_MIN)	/* Formula Force EX expects different autocentering command */
 			dev->ff->set_autocenter = hid_lg4ff_set_autocenter_ffex;
 		else
 			dev->ff->set_autocenter = hid_lg4ff_set_autocenter_default;
@@ -524,6 +587,7 @@ int lg4ff_init(struct hid_device *hid)
 	}
 	drv_data->device_props = entry;
 
+	entry->product_id = lg4ff_devices[i].product_id;
 	entry->min_range = lg4ff_devices[i].min_range;
 	entry->max_range = lg4ff_devices[i].max_range;
 	entry->set_range = lg4ff_devices[i].set_range;
@@ -534,6 +598,18 @@ int lg4ff_init(struct hid_device *hid)
 		return error;
 	dbg_hid("sysfs interface created\n");
 
+	/* Set default axes parameters */
+	switch (lg4ff_devices[i].product_id) {
+	case USB_DEVICE_ID_LOGITECH_DFP_WHEEL:
+		dbg_hid("Setting axes parameters for Driving Force Pro\n");
+		input_set_abs_params(dev, ABS_X, DFP_X_MIN, DFP_X_MAX, 0, 0);
+		input_set_abs_params(dev, ABS_Y, DFP_PEDAL_MIN, DFP_PEDAL_MAX, 0, 0);
+		input_set_abs_params(dev, ABS_RZ, DFP_PEDAL_MIN, DFP_PEDAL_MAX, 0, 0);
+		break;
+	default:
+		break;
+	}
+
 	/* Set the maximum range to start with */
 	entry->range = entry->max_range;
 	if (entry->set_range != NULL)
@@ -594,6 +670,8 @@ out:
 	return 0;
 }
 
+
+
 int lg4ff_deinit(struct hid_device *hid)
 {
 	struct lg4ff_device_entry *entry;
diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c
index 7364726..25ddf3e 100644
--- a/drivers/hid/hid-magicmouse.c
+++ b/drivers/hid/hid-magicmouse.c
@@ -392,7 +392,7 @@ static int magicmouse_setup_input(struct input_dev *input, struct hid_device *hd
 
 	__set_bit(EV_ABS, input->evbit);
 
-	error = input_mt_init_slots(input, 16);
+	error = input_mt_init_slots(input, 16, 0);
 	if (error)
 		return error;
 	input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, 255 << 2,
diff --git a/drivers/hid/hid-microsoft.c b/drivers/hid/hid-microsoft.c
index e5c699b..3acdcfc 100644
--- a/drivers/hid/hid-microsoft.c
+++ b/drivers/hid/hid-microsoft.c
@@ -5,7 +5,6 @@
  *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
  *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
  *  Copyright (c) 2006-2007 Jiri Kosina
- *  Copyright (c) 2007 Paul Walmsley
  *  Copyright (c) 2008 Jiri Slaby
  */
 
diff --git a/drivers/hid/hid-monterey.c b/drivers/hid/hid-monterey.c
index dedf757..cd3643e 100644
--- a/drivers/hid/hid-monterey.c
+++ b/drivers/hid/hid-monterey.c
@@ -5,7 +5,6 @@
  *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
  *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
  *  Copyright (c) 2006-2007 Jiri Kosina
- *  Copyright (c) 2007 Paul Walmsley
  *  Copyright (c) 2008 Jiri Slaby
  */
 
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index 59c8b5c..e99117f 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -51,12 +51,12 @@ MODULE_LICENSE("GPL");
 #define MT_QUIRK_VALID_IS_INRANGE	(1 << 5)
 #define MT_QUIRK_VALID_IS_CONFIDENCE	(1 << 6)
 #define MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE	(1 << 8)
+#define MT_QUIRK_NO_AREA		(1 << 9)
 
 struct mt_slot {
 	__s32 x, y, p, w, h;
 	__s32 contactid;	/* the device ContactID assigned to this slot */
 	bool touch_state;	/* is the touch valid? */
-	bool seen_in_this_frame;/* has this slot been updated */
 };
 
 struct mt_class {
@@ -92,8 +92,9 @@ struct mt_device {
 	__u8 touches_by_report;	/* how many touches are present in one report:
 				* 1 means we should use a serial protocol
 				* > 1 means hybrid (multitouch) protocol */
+	bool serial_maybe;	/* need to check for serial protocol */
 	bool curvalid;		/* is the current contact valid? */
-	struct mt_slot *slots;
+	unsigned mt_flags;	/* flags to pass to input-mt */
 };
 
 /* classes of device behavior */
@@ -115,6 +116,7 @@ struct mt_device {
 #define MT_CLS_EGALAX_SERIAL			0x0104
 #define MT_CLS_TOPSEED				0x0105
 #define MT_CLS_PANASONIC			0x0106
+#define MT_CLS_FLATFROG				0x0107
 
 #define MT_DEFAULT_MAXCONTACT	10
 
@@ -134,25 +136,6 @@ static int cypress_compute_slot(struct mt_device *td)
 		return -1;
 }
 
-static int find_slot_from_contactid(struct mt_device *td)
-{
-	int i;
-	for (i = 0; i < td->maxcontacts; ++i) {
-		if (td->slots[i].contactid == td->curdata.contactid &&
-			td->slots[i].touch_state)
-			return i;
-	}
-	for (i = 0; i < td->maxcontacts; ++i) {
-		if (!td->slots[i].seen_in_this_frame &&
-			!td->slots[i].touch_state)
-			return i;
-	}
-	/* should not occurs. If this happens that means
-	 * that the device sent more touches that it says
-	 * in the report descriptor. It is ignored then. */
-	return -1;
-}
-
 static struct mt_class mt_classes[] = {
 	{ .name = MT_CLS_DEFAULT,
 		.quirks = MT_QUIRK_NOT_SEEN_MEANS_UP },
@@ -190,7 +173,9 @@ static struct mt_class mt_classes[] = {
 			MT_QUIRK_SLOT_IS_CONTACTID,
 		.sn_move = 2048,
 		.sn_width = 128,
-		.sn_height = 128 },
+		.sn_height = 128,
+		.maxcontacts = 60,
+	},
 	{ .name = MT_CLS_CYPRESS,
 		.quirks = MT_QUIRK_NOT_SEEN_MEANS_UP |
 			MT_QUIRK_CYPRESS,
@@ -216,6 +201,12 @@ static struct mt_class mt_classes[] = {
 		.quirks = MT_QUIRK_NOT_SEEN_MEANS_UP,
 		.maxcontacts = 4 },
 
+	{ .name = MT_CLS_FLATFROG,
+		.quirks = MT_QUIRK_NOT_SEEN_MEANS_UP |
+			MT_QUIRK_NO_AREA,
+		.sn_move = 2048,
+		.maxcontacts = 40,
+	},
 	{ }
 };
 
@@ -319,24 +310,16 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
 	* We need to ignore fields that belong to other collections
 	* such as Mouse that might have the same GenericDesktop usages. */
 	if (field->application == HID_DG_TOUCHSCREEN)
-		set_bit(INPUT_PROP_DIRECT, hi->input->propbit);
+		td->mt_flags |= INPUT_MT_DIRECT;
 	else if (field->application != HID_DG_TOUCHPAD)
 		return 0;
 
-	/* In case of an indirect device (touchpad), we need to add
-	 * specific BTN_TOOL_* to be handled by the synaptics xorg
-	 * driver.
-	 * We also consider that touchscreens providing buttons are touchpads.
+	/*
+	 * Model touchscreens providing buttons as touchpads.
 	 */
 	if (field->application == HID_DG_TOUCHPAD ||
-	    (usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON ||
-	    cls->is_indirect) {
-		set_bit(INPUT_PROP_POINTER, hi->input->propbit);
-		set_bit(BTN_TOOL_FINGER, hi->input->keybit);
-		set_bit(BTN_TOOL_DOUBLETAP, hi->input->keybit);
-		set_bit(BTN_TOOL_TRIPLETAP, hi->input->keybit);
-		set_bit(BTN_TOOL_QUADTAP, hi->input->keybit);
-	}
+	    (usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON)
+		td->mt_flags |= INPUT_MT_POINTER;
 
 	/* eGalax devices provide a Digitizer.Stylus input which overrides
 	 * the correct Digitizers.Finger X/Y ranges.
@@ -353,8 +336,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
 					EV_ABS, ABS_MT_POSITION_X);
 			set_abs(hi->input, ABS_MT_POSITION_X, field,
 				cls->sn_move);
-			/* touchscreen emulation */
-			set_abs(hi->input, ABS_X, field, cls->sn_move);
 			mt_store_field(usage, td, hi);
 			td->last_field_index = field->index;
 			return 1;
@@ -363,8 +344,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
 					EV_ABS, ABS_MT_POSITION_Y);
 			set_abs(hi->input, ABS_MT_POSITION_Y, field,
 				cls->sn_move);
-			/* touchscreen emulation */
-			set_abs(hi->input, ABS_Y, field, cls->sn_move);
 			mt_store_field(usage, td, hi);
 			td->last_field_index = field->index;
 			return 1;
@@ -388,9 +367,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
 			td->last_field_index = field->index;
 			return 1;
 		case HID_DG_CONTACTID:
-			if (!td->maxcontacts)
-				td->maxcontacts = MT_DEFAULT_MAXCONTACT;
-			input_mt_init_slots(hi->input, td->maxcontacts);
 			mt_store_field(usage, td, hi);
 			td->last_field_index = field->index;
 			td->touches_by_report++;
@@ -398,18 +374,21 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
 		case HID_DG_WIDTH:
 			hid_map_usage(hi, usage, bit, max,
 					EV_ABS, ABS_MT_TOUCH_MAJOR);
-			set_abs(hi->input, ABS_MT_TOUCH_MAJOR, field,
-				cls->sn_width);
+			if (!(cls->quirks & MT_QUIRK_NO_AREA))
+				set_abs(hi->input, ABS_MT_TOUCH_MAJOR, field,
+					cls->sn_width);
 			mt_store_field(usage, td, hi);
 			td->last_field_index = field->index;
 			return 1;
 		case HID_DG_HEIGHT:
 			hid_map_usage(hi, usage, bit, max,
 					EV_ABS, ABS_MT_TOUCH_MINOR);
-			set_abs(hi->input, ABS_MT_TOUCH_MINOR, field,
-				cls->sn_height);
-			input_set_abs_params(hi->input,
+			if (!(cls->quirks & MT_QUIRK_NO_AREA)) {
+				set_abs(hi->input, ABS_MT_TOUCH_MINOR, field,
+					cls->sn_height);
+				input_set_abs_params(hi->input,
 					ABS_MT_ORIENTATION, 0, 1, 0, 0);
+			}
 			mt_store_field(usage, td, hi);
 			td->last_field_index = field->index;
 			return 1;
@@ -418,9 +397,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
 					EV_ABS, ABS_MT_PRESSURE);
 			set_abs(hi->input, ABS_MT_PRESSURE, field,
 				cls->sn_pressure);
-			/* touchscreen emulation */
-			set_abs(hi->input, ABS_PRESSURE, field,
-				cls->sn_pressure);
 			mt_store_field(usage, td, hi);
 			td->last_field_index = field->index;
 			return 1;
@@ -464,7 +440,7 @@ static int mt_input_mapped(struct hid_device *hdev, struct hid_input *hi,
 	return -1;
 }
 
-static int mt_compute_slot(struct mt_device *td)
+static int mt_compute_slot(struct mt_device *td, struct input_dev *input)
 {
 	__s32 quirks = td->mtclass.quirks;
 
@@ -480,42 +456,23 @@ static int mt_compute_slot(struct mt_device *td)
 	if (quirks & MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE)
 		return td->curdata.contactid - 1;
 
-	return find_slot_from_contactid(td);
+	return input_mt_get_slot_by_key(input, td->curdata.contactid);
 }
 
 /*
  * this function is called when a whole contact has been processed,
  * so that it can assign it to a slot and store the data there
  */
-static void mt_complete_slot(struct mt_device *td)
+static void mt_complete_slot(struct mt_device *td, struct input_dev *input)
 {
-	td->curdata.seen_in_this_frame = true;
 	if (td->curvalid) {
-		int slotnum = mt_compute_slot(td);
-
-		if (slotnum >= 0 && slotnum < td->maxcontacts)
-			td->slots[slotnum] = td->curdata;
-	}
-	td->num_received++;
-}
+		int slotnum = mt_compute_slot(td, input);
+		struct mt_slot *s = &td->curdata;
 
+		if (slotnum < 0 || slotnum >= td->maxcontacts)
+			return;
 
-/*
- * this function is called when a whole packet has been received and processed,
- * so that it can decide what to send to the input layer.
- */
-static void mt_emit_event(struct mt_device *td, struct input_dev *input)
-{
-	int i;
-
-	for (i = 0; i < td->maxcontacts; ++i) {
-		struct mt_slot *s = &(td->slots[i]);
-		if ((td->mtclass.quirks & MT_QUIRK_NOT_SEEN_MEANS_UP) &&
-			!s->seen_in_this_frame) {
-			s->touch_state = false;
-		}
-
-		input_mt_slot(input, i);
+		input_mt_slot(input, slotnum);
 		input_mt_report_slot_state(input, MT_TOOL_FINGER,
 			s->touch_state);
 		if (s->touch_state) {
@@ -532,24 +489,29 @@ static void mt_emit_event(struct mt_device *td, struct input_dev *input)
 			input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, major);
 			input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, minor);
 		}
-		s->seen_in_this_frame = false;
-
 	}
 
-	input_mt_report_pointer_emulation(input, true);
+	td->num_received++;
+}
+
+/*
+ * this function is called when a whole packet has been received and processed,
+ * so that it can decide what to send to the input layer.
+ */
+static void mt_sync_frame(struct mt_device *td, struct input_dev *input)
+{
+	input_mt_sync_frame(input);
 	input_sync(input);
 	td->num_received = 0;
 }
 
-
-
 static int mt_event(struct hid_device *hid, struct hid_field *field,
 				struct hid_usage *usage, __s32 value)
 {
 	struct mt_device *td = hid_get_drvdata(hid);
 	__s32 quirks = td->mtclass.quirks;
 
-	if (hid->claimed & HID_CLAIMED_INPUT && td->slots) {
+	if (hid->claimed & HID_CLAIMED_INPUT) {
 		switch (usage->hid) {
 		case HID_DG_INRANGE:
 			if (quirks & MT_QUIRK_ALWAYS_VALID)
@@ -602,11 +564,11 @@ static int mt_event(struct hid_device *hid, struct hid_field *field,
 		}
 
 		if (usage->hid == td->last_slot_field)
-			mt_complete_slot(td);
+			mt_complete_slot(td, field->hidinput->input);
 
 		if (field->index == td->last_field_index
 			&& td->num_received >= td->num_expected)
-			mt_emit_event(td, field->hidinput->input);
+			mt_sync_frame(td, field->hidinput->input);
 
 	}
 
@@ -685,18 +647,45 @@ static void mt_post_parse(struct mt_device *td)
 	}
 }
 
+static void mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
+
+{
+	struct mt_device *td = hid_get_drvdata(hdev);
+	struct mt_class *cls = &td->mtclass;
+	struct input_dev *input = hi->input;
+
+	/* Only initialize slots for MT input devices */
+	if (!test_bit(ABS_MT_POSITION_X, input->absbit))
+		return;
+
+	if (!td->maxcontacts)
+		td->maxcontacts = MT_DEFAULT_MAXCONTACT;
+
+	mt_post_parse(td);
+	if (td->serial_maybe)
+		mt_post_parse_default_settings(td);
+
+	if (cls->is_indirect)
+		td->mt_flags |= INPUT_MT_POINTER;
+
+	if (cls->quirks & MT_QUIRK_NOT_SEEN_MEANS_UP)
+		td->mt_flags |= INPUT_MT_DROP_UNUSED;
+
+	input_mt_init_slots(input, td->maxcontacts, td->mt_flags);
+
+	td->mt_flags = 0;
+}
+
 static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
 {
 	int ret, i;
 	struct mt_device *td;
 	struct mt_class *mtclass = mt_classes; /* MT_CLS_DEFAULT */
 
-	if (id) {
-		for (i = 0; mt_classes[i].name ; i++) {
-			if (id->driver_data == mt_classes[i].name) {
-				mtclass = &(mt_classes[i]);
-				break;
-			}
+	for (i = 0; mt_classes[i].name ; i++) {
+		if (id->driver_data == mt_classes[i].name) {
+			mtclass = &(mt_classes[i]);
+			break;
 		}
 	}
 
@@ -722,6 +711,9 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
 		goto fail;
 	}
 
+	if (id->vendor == HID_ANY_ID && id->product == HID_ANY_ID)
+		td->serial_maybe = true;
+
 	ret = hid_parse(hdev);
 	if (ret != 0)
 		goto fail;
@@ -730,20 +722,6 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
 	if (ret)
 		goto fail;
 
-	mt_post_parse(td);
-
-	if (id->vendor == HID_ANY_ID && id->product == HID_ANY_ID)
-		mt_post_parse_default_settings(td);
-
-	td->slots = kzalloc(td->maxcontacts * sizeof(struct mt_slot),
-				GFP_KERNEL);
-	if (!td->slots) {
-		dev_err(&hdev->dev, "cannot allocate multitouch slots\n");
-		hid_hw_stop(hdev);
-		ret = -ENOMEM;
-		goto fail;
-	}
-
 	ret = sysfs_create_group(&hdev->dev.kobj, &mt_attribute_group);
 
 	mt_set_maxcontacts(hdev);
@@ -767,6 +745,32 @@ static int mt_reset_resume(struct hid_device *hdev)
 	mt_set_input_mode(hdev);
 	return 0;
 }
+
+static int mt_resume(struct hid_device *hdev)
+{
+	struct usb_interface *intf;
+	struct usb_host_interface *interface;
+	struct usb_device *dev;
+
+	if (hdev->bus != BUS_USB)
+		return 0;
+
+	intf = to_usb_interface(hdev->dev.parent);
+	interface = intf->cur_altsetting;
+	dev = hid_to_usb_dev(hdev);
+
+	/* Some Elan legacy devices require SET_IDLE to be set on resume.
+	 * It should be safe to send it to other devices too.
+	 * Tested on 3M, Stantum, Cypress, Zytronic, eGalax, and Elan panels. */
+
+	usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+			HID_REQ_SET_IDLE,
+			USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+			0, interface->desc.bInterfaceNumber,
+			NULL, 0, USB_CTRL_SET_TIMEOUT);
+
+	return 0;
+}
 #endif
 
 static void mt_remove(struct hid_device *hdev)
@@ -774,7 +778,6 @@ static void mt_remove(struct hid_device *hdev)
 	struct mt_device *td = hid_get_drvdata(hdev);
 	sysfs_remove_group(&hdev->dev.kobj, &mt_attribute_group);
 	hid_hw_stop(hdev);
-	kfree(td->slots);
 	kfree(td);
 	hid_set_drvdata(hdev, NULL);
 }
@@ -885,13 +888,30 @@ static const struct hid_device_id mt_devices[] = {
 			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7349) },
 	{ .driver_data = MT_CLS_EGALAX_SERIAL,
 		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
+			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_73F7) },
+	{ .driver_data = MT_CLS_EGALAX_SERIAL,
+		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
 			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001) },
+	{ .driver_data = MT_CLS_EGALAX,
+		HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
+			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7224) },
+	{ .driver_data = MT_CLS_EGALAX,
+		HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
+			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72D0) },
+	{ .driver_data = MT_CLS_EGALAX,
+		HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
+			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72C4) },
 
 	/* Elo TouchSystems IntelliTouch Plus panel */
 	{ .driver_data = MT_CLS_DUAL_NSMU_CONTACTID,
 		MT_USB_DEVICE(USB_VENDOR_ID_ELO,
 			USB_DEVICE_ID_ELO_TS2515) },
 
+	/* Flatfrog Panels */
+	{ .driver_data = MT_CLS_FLATFROG,
+		MT_USB_DEVICE(USB_VENDOR_ID_FLATFROG,
+			USB_DEVICE_ID_MULTITOUCH_3200) },
+
 	/* GeneralTouch panel */
 	{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER,
 		MT_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH,
@@ -1087,11 +1107,13 @@ static struct hid_driver mt_driver = {
 	.remove = mt_remove,
 	.input_mapping = mt_input_mapping,
 	.input_mapped = mt_input_mapped,
+	.input_configured = mt_input_configured,
 	.feature_mapping = mt_feature_mapping,
 	.usage_table = mt_grabbed_usages,
 	.event = mt_event,
 #ifdef CONFIG_PM
 	.reset_resume = mt_reset_resume,
+	.resume = mt_resume,
 #endif
 };
 
diff --git a/drivers/hid/hid-ntrig.c b/drivers/hid/hid-ntrig.c
index 9fae2eb..86a969f 100644
--- a/drivers/hid/hid-ntrig.c
+++ b/drivers/hid/hid-ntrig.c
@@ -882,10 +882,10 @@ static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id)
 	nd->activate_slack = activate_slack;
 	nd->act_state = activate_slack;
 	nd->deactivate_slack = -deactivate_slack;
-	nd->sensor_logical_width = 0;
-	nd->sensor_logical_height = 0;
-	nd->sensor_physical_width = 0;
-	nd->sensor_physical_height = 0;
+	nd->sensor_logical_width = 1;
+	nd->sensor_logical_height = 1;
+	nd->sensor_physical_width = 1;
+	nd->sensor_physical_height = 1;
 
 	hid_set_drvdata(hdev, nd);
 
diff --git a/drivers/hid/hid-petalynx.c b/drivers/hid/hid-petalynx.c
index f1ea3ff..4c521de 100644
--- a/drivers/hid/hid-petalynx.c
+++ b/drivers/hid/hid-petalynx.c
@@ -5,7 +5,6 @@
  *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
  *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
  *  Copyright (c) 2006-2007 Jiri Kosina
- *  Copyright (c) 2007 Paul Walmsley
  *  Copyright (c) 2008 Jiri Slaby
  */
 
diff --git a/drivers/hid/hid-picolcd.c b/drivers/hid/hid-picolcd.c
deleted file mode 100644
index 27c8ebd..0000000
--- a/drivers/hid/hid-picolcd.c
+++ /dev/null
@@ -1,2748 +0,0 @@
-/***************************************************************************
- *   Copyright (C) 2010 by Bruno Prémont <bonbons@linux-vserver.org>       *
- *                                                                         *
- *   Based on Logitech G13 driver (v0.4)                                   *
- *     Copyright (C) 2009 by Rick L. Vinyard, Jr. <rvinyard@cs.nmsu.edu>   *
- *                                                                         *
- *   This program is free software: you can redistribute it and/or modify  *
- *   it under the terms of the GNU General Public License as published by  *
- *   the Free Software Foundation, version 2 of the License.               *
- *                                                                         *
- *   This driver is distributed in the hope that it will be useful, but    *
- *   WITHOUT ANY WARRANTY; without even the implied warranty of            *
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      *
- *   General Public License for more details.                              *
- *                                                                         *
- *   You should have received a copy of the GNU General Public License     *
- *   along with this software. If not see <http://www.gnu.org/licenses/>.  *
- ***************************************************************************/
-
-#include <linux/hid.h>
-#include <linux/hid-debug.h>
-#include <linux/input.h>
-#include "hid-ids.h"
-#include "usbhid/usbhid.h"
-#include <linux/usb.h>
-
-#include <linux/fb.h>
-#include <linux/vmalloc.h>
-#include <linux/backlight.h>
-#include <linux/lcd.h>
-
-#include <linux/leds.h>
-
-#include <linux/seq_file.h>
-#include <linux/debugfs.h>
-
-#include <linux/completion.h>
-#include <linux/uaccess.h>
-#include <linux/module.h>
-
-#define PICOLCD_NAME "PicoLCD (graphic)"
-
-/* Report numbers */
-#define REPORT_ERROR_CODE      0x10 /* LCD: IN[16]  */
-#define   ERR_SUCCESS            0x00
-#define   ERR_PARAMETER_MISSING  0x01
-#define   ERR_DATA_MISSING       0x02
-#define   ERR_BLOCK_READ_ONLY    0x03
-#define   ERR_BLOCK_NOT_ERASABLE 0x04
-#define   ERR_BLOCK_TOO_BIG      0x05
-#define   ERR_SECTION_OVERFLOW   0x06
-#define   ERR_INVALID_CMD_LEN    0x07
-#define   ERR_INVALID_DATA_LEN   0x08
-#define REPORT_KEY_STATE       0x11 /* LCD: IN[2]   */
-#define REPORT_IR_DATA         0x21 /* LCD: IN[63]  */
-#define REPORT_EE_DATA         0x32 /* LCD: IN[63]  */
-#define REPORT_MEMORY          0x41 /* LCD: IN[63]  */
-#define REPORT_LED_STATE       0x81 /* LCD: OUT[1]  */
-#define REPORT_BRIGHTNESS      0x91 /* LCD: OUT[1]  */
-#define REPORT_CONTRAST        0x92 /* LCD: OUT[1]  */
-#define REPORT_RESET           0x93 /* LCD: OUT[2]  */
-#define REPORT_LCD_CMD         0x94 /* LCD: OUT[63] */
-#define REPORT_LCD_DATA        0x95 /* LCD: OUT[63] */
-#define REPORT_LCD_CMD_DATA    0x96 /* LCD: OUT[63] */
-#define	REPORT_EE_READ         0xa3 /* LCD: OUT[63] */
-#define REPORT_EE_WRITE        0xa4 /* LCD: OUT[63] */
-#define REPORT_ERASE_MEMORY    0xb2 /* LCD: OUT[2]  */
-#define REPORT_READ_MEMORY     0xb3 /* LCD: OUT[3]  */
-#define REPORT_WRITE_MEMORY    0xb4 /* LCD: OUT[63] */
-#define REPORT_SPLASH_RESTART  0xc1 /* LCD: OUT[1]  */
-#define REPORT_EXIT_KEYBOARD   0xef /* LCD: OUT[2]  */
-#define REPORT_VERSION         0xf1 /* LCD: IN[2],OUT[1]    Bootloader: IN[2],OUT[1]   */
-#define REPORT_BL_ERASE_MEMORY 0xf2 /*                      Bootloader: IN[36],OUT[4]  */
-#define REPORT_BL_READ_MEMORY  0xf3 /*                      Bootloader: IN[36],OUT[4]  */
-#define REPORT_BL_WRITE_MEMORY 0xf4 /*                      Bootloader: IN[36],OUT[36] */
-#define REPORT_DEVID           0xf5 /* LCD: IN[5], OUT[1]   Bootloader: IN[5],OUT[1]   */
-#define REPORT_SPLASH_SIZE     0xf6 /* LCD: IN[4], OUT[1]   */
-#define REPORT_HOOK_VERSION    0xf7 /* LCD: IN[2], OUT[1]   */
-#define REPORT_EXIT_FLASHER    0xff /*                      Bootloader: OUT[2]         */
-
-#ifdef CONFIG_HID_PICOLCD_FB
-/* Framebuffer
- *
- * The PicoLCD use a Topway LCD module of 256x64 pixel
- * This display area is tiled over 4 controllers with 8 tiles
- * each. Each tile has 8x64 pixel, each data byte representing
- * a 1-bit wide vertical line of the tile.
- *
- * The display can be updated at a tile granularity.
- *
- *       Chip 1           Chip 2           Chip 3           Chip 4
- * +----------------+----------------+----------------+----------------+
- * |     Tile 1     |     Tile 1     |     Tile 1     |     Tile 1     |
- * +----------------+----------------+----------------+----------------+
- * |     Tile 2     |     Tile 2     |     Tile 2     |     Tile 2     |
- * +----------------+----------------+----------------+----------------+
- *                                  ...
- * +----------------+----------------+----------------+----------------+
- * |     Tile 8     |     Tile 8     |     Tile 8     |     Tile 8     |
- * +----------------+----------------+----------------+----------------+
- */
-#define PICOLCDFB_NAME "picolcdfb"
-#define PICOLCDFB_WIDTH (256)
-#define PICOLCDFB_HEIGHT (64)
-#define PICOLCDFB_SIZE (PICOLCDFB_WIDTH * PICOLCDFB_HEIGHT / 8)
-
-#define PICOLCDFB_UPDATE_RATE_LIMIT   10
-#define PICOLCDFB_UPDATE_RATE_DEFAULT  2
-
-/* Framebuffer visual structures */
-static const struct fb_fix_screeninfo picolcdfb_fix = {
-	.id          = PICOLCDFB_NAME,
-	.type        = FB_TYPE_PACKED_PIXELS,
-	.visual      = FB_VISUAL_MONO01,
-	.xpanstep    = 0,
-	.ypanstep    = 0,
-	.ywrapstep   = 0,
-	.line_length = PICOLCDFB_WIDTH / 8,
-	.accel       = FB_ACCEL_NONE,
-};
-
-static const struct fb_var_screeninfo picolcdfb_var = {
-	.xres           = PICOLCDFB_WIDTH,
-	.yres           = PICOLCDFB_HEIGHT,
-	.xres_virtual   = PICOLCDFB_WIDTH,
-	.yres_virtual   = PICOLCDFB_HEIGHT,
-	.width          = 103,
-	.height         = 26,
-	.bits_per_pixel = 1,
-	.grayscale      = 1,
-	.red            = {
-		.offset = 0,
-		.length = 1,
-		.msb_right = 0,
-	},
-	.green          = {
-		.offset = 0,
-		.length = 1,
-		.msb_right = 0,
-	},
-	.blue           = {
-		.offset = 0,
-		.length = 1,
-		.msb_right = 0,
-	},
-	.transp         = {
-		.offset = 0,
-		.length = 0,
-		.msb_right = 0,
-	},
-};
-#endif /* CONFIG_HID_PICOLCD_FB */
-
-/* Input device
- *
- * The PicoLCD has an IR receiver header, a built-in keypad with 5 keys
- * and header for 4x4 key matrix. The built-in keys are part of the matrix.
- */
-static const unsigned short def_keymap[] = {
-	KEY_RESERVED,	/* none */
-	KEY_BACK,	/* col 4 + row 1 */
-	KEY_HOMEPAGE,	/* col 3 + row 1 */
-	KEY_RESERVED,	/* col 2 + row 1 */
-	KEY_RESERVED,	/* col 1 + row 1 */
-	KEY_SCROLLUP,	/* col 4 + row 2 */
-	KEY_OK,		/* col 3 + row 2 */
-	KEY_SCROLLDOWN,	/* col 2 + row 2 */
-	KEY_RESERVED,	/* col 1 + row 2 */
-	KEY_RESERVED,	/* col 4 + row 3 */
-	KEY_RESERVED,	/* col 3 + row 3 */
-	KEY_RESERVED,	/* col 2 + row 3 */
-	KEY_RESERVED,	/* col 1 + row 3 */
-	KEY_RESERVED,	/* col 4 + row 4 */
-	KEY_RESERVED,	/* col 3 + row 4 */
-	KEY_RESERVED,	/* col 2 + row 4 */
-	KEY_RESERVED,	/* col 1 + row 4 */
-};
-#define PICOLCD_KEYS ARRAY_SIZE(def_keymap)
-
-/* Description of in-progress IO operation, used for operations
- * that trigger response from device */
-struct picolcd_pending {
-	struct hid_report *out_report;
-	struct hid_report *in_report;
-	struct completion ready;
-	int raw_size;
-	u8 raw_data[64];
-};
-
-/* Per device data structure */
-struct picolcd_data {
-	struct hid_device *hdev;
-#ifdef CONFIG_DEBUG_FS
-	struct dentry *debug_reset;
-	struct dentry *debug_eeprom;
-	struct dentry *debug_flash;
-	struct mutex mutex_flash;
-	int addr_sz;
-#endif
-	u8 version[2];
-	unsigned short opmode_delay;
-	/* input stuff */
-	u8 pressed_keys[2];
-	struct input_dev *input_keys;
-	struct input_dev *input_cir;
-	unsigned short keycode[PICOLCD_KEYS];
-
-#ifdef CONFIG_HID_PICOLCD_FB
-	/* Framebuffer stuff */
-	u8 fb_update_rate;
-	u8 fb_bpp;
-	u8 fb_force;
-	u8 *fb_vbitmap;		/* local copy of what was sent to PicoLCD */
-	u8 *fb_bitmap;		/* framebuffer */
-	struct fb_info *fb_info;
-	struct fb_deferred_io fb_defio;
-#endif /* CONFIG_HID_PICOLCD_FB */
-#ifdef CONFIG_HID_PICOLCD_LCD
-	struct lcd_device *lcd;
-	u8 lcd_contrast;
-#endif /* CONFIG_HID_PICOLCD_LCD */
-#ifdef CONFIG_HID_PICOLCD_BACKLIGHT
-	struct backlight_device *backlight;
-	u8 lcd_brightness;
-	u8 lcd_power;
-#endif /* CONFIG_HID_PICOLCD_BACKLIGHT */
-#ifdef CONFIG_HID_PICOLCD_LEDS
-	/* LED stuff */
-	u8 led_state;
-	struct led_classdev *led[8];
-#endif /* CONFIG_HID_PICOLCD_LEDS */
-
-	/* Housekeeping stuff */
-	spinlock_t lock;
-	struct mutex mutex;
-	struct picolcd_pending *pending;
-	int status;
-#define PICOLCD_BOOTLOADER 1
-#define PICOLCD_FAILED 2
-#define PICOLCD_READY_FB 4
-};
-
-
-/* Find a given report */
-#define picolcd_in_report(id, dev) picolcd_report(id, dev, HID_INPUT_REPORT)
-#define picolcd_out_report(id, dev) picolcd_report(id, dev, HID_OUTPUT_REPORT)
-
-static struct hid_report *picolcd_report(int id, struct hid_device *hdev, int dir)
-{
-	struct list_head *feature_report_list = &hdev->report_enum[dir].report_list;
-	struct hid_report *report = NULL;
-
-	list_for_each_entry(report, feature_report_list, list) {
-		if (report->id == id)
-			return report;
-	}
-	hid_warn(hdev, "No report with id 0x%x found\n", id);
-	return NULL;
-}
-
-#ifdef CONFIG_DEBUG_FS
-static void picolcd_debug_out_report(struct picolcd_data *data,
-		struct hid_device *hdev, struct hid_report *report);
-#define usbhid_submit_report(a, b, c) \
-	do { \
-		picolcd_debug_out_report(hid_get_drvdata(a), a, b); \
-		usbhid_submit_report(a, b, c); \
-	} while (0)
-#endif
-
-/* Submit a report and wait for a reply from device - if device fades away
- * or does not respond in time, return NULL */
-static struct picolcd_pending *picolcd_send_and_wait(struct hid_device *hdev,
-		int report_id, const u8 *raw_data, int size)
-{
-	struct picolcd_data *data = hid_get_drvdata(hdev);
-	struct picolcd_pending *work;
-	struct hid_report *report = picolcd_out_report(report_id, hdev);
-	unsigned long flags;
-	int i, j, k;
-
-	if (!report || !data)
-		return NULL;
-	if (data->status & PICOLCD_FAILED)
-		return NULL;
-	work = kzalloc(sizeof(*work), GFP_KERNEL);
-	if (!work)
-		return NULL;
-
-	init_completion(&work->ready);
-	work->out_report = report;
-	work->in_report  = NULL;
-	work->raw_size   = 0;
-
-	mutex_lock(&data->mutex);
-	spin_lock_irqsave(&data->lock, flags);
-	for (i = k = 0; i < report->maxfield; i++)
-		for (j = 0; j < report->field[i]->report_count; j++) {
-			hid_set_field(report->field[i], j, k < size ? raw_data[k] : 0);
-			k++;
-		}
-	data->pending = work;
-	usbhid_submit_report(data->hdev, report, USB_DIR_OUT);
-	spin_unlock_irqrestore(&data->lock, flags);
-	wait_for_completion_interruptible_timeout(&work->ready, HZ*2);
-	spin_lock_irqsave(&data->lock, flags);
-	data->pending = NULL;
-	spin_unlock_irqrestore(&data->lock, flags);
-	mutex_unlock(&data->mutex);
-	return work;
-}
-
-#ifdef CONFIG_HID_PICOLCD_FB
-/* Send a given tile to PicoLCD */
-static int picolcd_fb_send_tile(struct hid_device *hdev, int chip, int tile)
-{
-	struct picolcd_data *data = hid_get_drvdata(hdev);
-	struct hid_report *report1 = picolcd_out_report(REPORT_LCD_CMD_DATA, hdev);
-	struct hid_report *report2 = picolcd_out_report(REPORT_LCD_DATA, hdev);
-	unsigned long flags;
-	u8 *tdata;
-	int i;
-
-	if (!report1 || report1->maxfield != 1 || !report2 || report2->maxfield != 1)
-		return -ENODEV;
-
-	spin_lock_irqsave(&data->lock, flags);
-	hid_set_field(report1->field[0],  0, chip << 2);
-	hid_set_field(report1->field[0],  1, 0x02);
-	hid_set_field(report1->field[0],  2, 0x00);
-	hid_set_field(report1->field[0],  3, 0x00);
-	hid_set_field(report1->field[0],  4, 0xb8 | tile);
-	hid_set_field(report1->field[0],  5, 0x00);
-	hid_set_field(report1->field[0],  6, 0x00);
-	hid_set_field(report1->field[0],  7, 0x40);
-	hid_set_field(report1->field[0],  8, 0x00);
-	hid_set_field(report1->field[0],  9, 0x00);
-	hid_set_field(report1->field[0], 10,   32);
-
-	hid_set_field(report2->field[0],  0, (chip << 2) | 0x01);
-	hid_set_field(report2->field[0],  1, 0x00);
-	hid_set_field(report2->field[0],  2, 0x00);
-	hid_set_field(report2->field[0],  3,   32);
-
-	tdata = data->fb_vbitmap + (tile * 4 + chip) * 64;
-	for (i = 0; i < 64; i++)
-		if (i < 32)
-			hid_set_field(report1->field[0], 11 + i, tdata[i]);
-		else
-			hid_set_field(report2->field[0], 4 + i - 32, tdata[i]);
-
-	usbhid_submit_report(data->hdev, report1, USB_DIR_OUT);
-	usbhid_submit_report(data->hdev, report2, USB_DIR_OUT);
-	spin_unlock_irqrestore(&data->lock, flags);
-	return 0;
-}
-
-/* Translate a single tile*/
-static int picolcd_fb_update_tile(u8 *vbitmap, const u8 *bitmap, int bpp,
-		int chip, int tile)
-{
-	int i, b, changed = 0;
-	u8 tdata[64];
-	u8 *vdata = vbitmap + (tile * 4 + chip) * 64;
-
-	if (bpp == 1) {
-		for (b = 7; b >= 0; b--) {
-			const u8 *bdata = bitmap + tile * 256 + chip * 8 + b * 32;
-			for (i = 0; i < 64; i++) {
-				tdata[i] <<= 1;
-				tdata[i] |= (bdata[i/8] >> (i % 8)) & 0x01;
-			}
-		}
-	} else if (bpp == 8) {
-		for (b = 7; b >= 0; b--) {
-			const u8 *bdata = bitmap + (tile * 256 + chip * 8 + b * 32) * 8;
-			for (i = 0; i < 64; i++) {
-				tdata[i] <<= 1;
-				tdata[i] |= (bdata[i] & 0x80) ? 0x01 : 0x00;
-			}
-		}
-	} else {
-		/* Oops, we should never get here! */
-		WARN_ON(1);
-		return 0;
-	}
-
-	for (i = 0; i < 64; i++)
-		if (tdata[i] != vdata[i]) {
-			changed = 1;
-			vdata[i] = tdata[i];
-		}
-	return changed;
-}
-
-/* Reconfigure LCD display */
-static int picolcd_fb_reset(struct picolcd_data *data, int clear)
-{
-	struct hid_report *report = picolcd_out_report(REPORT_LCD_CMD, data->hdev);
-	int i, j;
-	unsigned long flags;
-	static const u8 mapcmd[8] = { 0x00, 0x02, 0x00, 0x64, 0x3f, 0x00, 0x64, 0xc0 };
-
-	if (!report || report->maxfield != 1)
-		return -ENODEV;
-
-	spin_lock_irqsave(&data->lock, flags);
-	for (i = 0; i < 4; i++) {
-		for (j = 0; j < report->field[0]->maxusage; j++)
-			if (j == 0)
-				hid_set_field(report->field[0], j, i << 2);
-			else if (j < sizeof(mapcmd))
-				hid_set_field(report->field[0], j, mapcmd[j]);
-			else
-				hid_set_field(report->field[0], j, 0);
-		usbhid_submit_report(data->hdev, report, USB_DIR_OUT);
-	}
-
-	data->status |= PICOLCD_READY_FB;
-	spin_unlock_irqrestore(&data->lock, flags);
-
-	if (data->fb_bitmap) {
-		if (clear) {
-			memset(data->fb_vbitmap, 0, PICOLCDFB_SIZE);
-			memset(data->fb_bitmap, 0, PICOLCDFB_SIZE*data->fb_bpp);
-		}
-		data->fb_force = 1;
-	}
-
-	/* schedule first output of framebuffer */
-	if (data->fb_info)
-		schedule_delayed_work(&data->fb_info->deferred_work, 0);
-
-	return 0;
-}
-
-/* Update fb_vbitmap from the screen_base and send changed tiles to device */
-static void picolcd_fb_update(struct picolcd_data *data)
-{
-	int chip, tile, n;
-	unsigned long flags;
-
-	if (!data)
-		return;
-
-	spin_lock_irqsave(&data->lock, flags);
-	if (!(data->status & PICOLCD_READY_FB)) {
-		spin_unlock_irqrestore(&data->lock, flags);
-		picolcd_fb_reset(data, 0);
-	} else {
-		spin_unlock_irqrestore(&data->lock, flags);
-	}
-
-	/*
-	 * Translate the framebuffer into the format needed by the PicoLCD.
-	 * See display layout above.
-	 * Do this one tile after the other and push those tiles that changed.
-	 *
-	 * Wait for our IO to complete as otherwise we might flood the queue!
-	 */
-	n = 0;
-	for (chip = 0; chip < 4; chip++)
-		for (tile = 0; tile < 8; tile++)
-			if (picolcd_fb_update_tile(data->fb_vbitmap,
-					data->fb_bitmap, data->fb_bpp, chip, tile) ||
-				data->fb_force) {
-				n += 2;
-				if (!data->fb_info->par)
-					return; /* device lost! */
-				if (n >= HID_OUTPUT_FIFO_SIZE / 2) {
-					usbhid_wait_io(data->hdev);
-					n = 0;
-				}
-				picolcd_fb_send_tile(data->hdev, chip, tile);
-			}
-	data->fb_force = false;
-	if (n)
-		usbhid_wait_io(data->hdev);
-}
-
-/* Stub to call the system default and update the image on the picoLCD */
-static void picolcd_fb_fillrect(struct fb_info *info,
-		const struct fb_fillrect *rect)
-{
-	if (!info->par)
-		return;
-	sys_fillrect(info, rect);
-
-	schedule_delayed_work(&info->deferred_work, 0);
-}
-
-/* Stub to call the system default and update the image on the picoLCD */
-static void picolcd_fb_copyarea(struct fb_info *info,
-		const struct fb_copyarea *area)
-{
-	if (!info->par)
-		return;
-	sys_copyarea(info, area);
-
-	schedule_delayed_work(&info->deferred_work, 0);
-}
-
-/* Stub to call the system default and update the image on the picoLCD */
-static void picolcd_fb_imageblit(struct fb_info *info, const struct fb_image *image)
-{
-	if (!info->par)
-		return;
-	sys_imageblit(info, image);
-
-	schedule_delayed_work(&info->deferred_work, 0);
-}
-
-/*
- * 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 picolcd_fb_write(struct fb_info *info, const char __user *buf,
-		size_t count, loff_t *ppos)
-{
-	ssize_t ret;
-	if (!info->par)
-		return -ENODEV;
-	ret = fb_sys_write(info, buf, count, ppos);
-	if (ret >= 0)
-		schedule_delayed_work(&info->deferred_work, 0);
-	return ret;
-}
-
-static int picolcd_fb_blank(int blank, struct fb_info *info)
-{
-	if (!info->par)
-		return -ENODEV;
-	/* We let fb notification do this for us via lcd/backlight device */
-	return 0;
-}
-
-static void picolcd_fb_destroy(struct fb_info *info)
-{
-	struct picolcd_data *data = info->par;
-	u32 *ref_cnt = info->pseudo_palette;
-	int may_release;
-
-	info->par = NULL;
-	if (data)
-		data->fb_info = NULL;
-	fb_deferred_io_cleanup(info);
-
-	ref_cnt--;
-	mutex_lock(&info->lock);
-	(*ref_cnt)--;
-	may_release = !*ref_cnt;
-	mutex_unlock(&info->lock);
-	if (may_release) {
-		vfree((u8 *)info->fix.smem_start);
-		framebuffer_release(info);
-	}
-}
-
-static int picolcd_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
-{
-	__u32 bpp      = var->bits_per_pixel;
-	__u32 activate = var->activate;
-
-	/* only allow 1/8 bit depth (8-bit is grayscale) */
-	*var = picolcdfb_var;
-	var->activate = activate;
-	if (bpp >= 8) {
-		var->bits_per_pixel = 8;
-		var->red.length     = 8;
-		var->green.length   = 8;
-		var->blue.length    = 8;
-	} else {
-		var->bits_per_pixel = 1;
-		var->red.length     = 1;
-		var->green.length   = 1;
-		var->blue.length    = 1;
-	}
-	return 0;
-}
-
-static int picolcd_set_par(struct fb_info *info)
-{
-	struct picolcd_data *data = info->par;
-	u8 *tmp_fb, *o_fb;
-	if (!data)
-		return -ENODEV;
-	if (info->var.bits_per_pixel == data->fb_bpp)
-		return 0;
-	/* switch between 1/8 bit depths */
-	if (info->var.bits_per_pixel != 1 && info->var.bits_per_pixel != 8)
-		return -EINVAL;
-
-	o_fb   = data->fb_bitmap;
-	tmp_fb = kmalloc(PICOLCDFB_SIZE*info->var.bits_per_pixel, GFP_KERNEL);
-	if (!tmp_fb)
-		return -ENOMEM;
-
-	/* translate FB content to new bits-per-pixel */
-	if (info->var.bits_per_pixel == 1) {
-		int i, b;
-		for (i = 0; i < PICOLCDFB_SIZE; i++) {
-			u8 p = 0;
-			for (b = 0; b < 8; b++) {
-				p <<= 1;
-				p |= o_fb[i*8+b] ? 0x01 : 0x00;
-			}
-			tmp_fb[i] = p;
-		}
-		memcpy(o_fb, tmp_fb, PICOLCDFB_SIZE);
-		info->fix.visual = FB_VISUAL_MONO01;
-		info->fix.line_length = PICOLCDFB_WIDTH / 8;
-	} else {
-		int i;
-		memcpy(tmp_fb, o_fb, PICOLCDFB_SIZE);
-		for (i = 0; i < PICOLCDFB_SIZE * 8; i++)
-			o_fb[i] = tmp_fb[i/8] & (0x01 << (7 - i % 8)) ? 0xff : 0x00;
-		info->fix.visual = FB_VISUAL_DIRECTCOLOR;
-		info->fix.line_length = PICOLCDFB_WIDTH;
-	}
-
-	kfree(tmp_fb);
-	data->fb_bpp      = info->var.bits_per_pixel;
-	return 0;
-}
-
-/* Do refcounting on our FB and cleanup per worker if FB is
- * closed after unplug of our device
- * (fb_release holds info->lock and still touches info after
- *  we return so we can't release it immediately.
- */
-struct picolcd_fb_cleanup_item {
-	struct fb_info *info;
-	struct picolcd_fb_cleanup_item *next;
-};
-static struct picolcd_fb_cleanup_item *fb_pending;
-static DEFINE_SPINLOCK(fb_pending_lock);
-
-static void picolcd_fb_do_cleanup(struct work_struct *data)
-{
-	struct picolcd_fb_cleanup_item *item;
-	unsigned long flags;
-
-	do {
-		spin_lock_irqsave(&fb_pending_lock, flags);
-		item = fb_pending;
-		fb_pending = item ? item->next : NULL;
-		spin_unlock_irqrestore(&fb_pending_lock, flags);
-
-		if (item) {
-			u8 *fb = (u8 *)item->info->fix.smem_start;
-			/* make sure we do not race against fb core when
-			 * releasing */
-			mutex_lock(&item->info->lock);
-			mutex_unlock(&item->info->lock);
-			framebuffer_release(item->info);
-			vfree(fb);
-		}
-	} while (item);
-}
-
-static DECLARE_WORK(picolcd_fb_cleanup, picolcd_fb_do_cleanup);
-
-static int picolcd_fb_open(struct fb_info *info, int u)
-{
-	u32 *ref_cnt = info->pseudo_palette;
-	ref_cnt--;
-
-	(*ref_cnt)++;
-	return 0;
-}
-
-static int picolcd_fb_release(struct fb_info *info, int u)
-{
-	u32 *ref_cnt = info->pseudo_palette;
-	ref_cnt--;
-
-	(*ref_cnt)++;
-	if (!*ref_cnt) {
-		unsigned long flags;
-		struct picolcd_fb_cleanup_item *item = (struct picolcd_fb_cleanup_item *)ref_cnt;
-		item--;
-		spin_lock_irqsave(&fb_pending_lock, flags);
-		item->next = fb_pending;
-		fb_pending = item;
-		spin_unlock_irqrestore(&fb_pending_lock, flags);
-		schedule_work(&picolcd_fb_cleanup);
-	}
-	return 0;
-}
-
-/* Note this can't be const because of struct fb_info definition */
-static struct fb_ops picolcdfb_ops = {
-	.owner        = THIS_MODULE,
-	.fb_destroy   = picolcd_fb_destroy,
-	.fb_open      = picolcd_fb_open,
-	.fb_release   = picolcd_fb_release,
-	.fb_read      = fb_sys_read,
-	.fb_write     = picolcd_fb_write,
-	.fb_blank     = picolcd_fb_blank,
-	.fb_fillrect  = picolcd_fb_fillrect,
-	.fb_copyarea  = picolcd_fb_copyarea,
-	.fb_imageblit = picolcd_fb_imageblit,
-	.fb_check_var = picolcd_fb_check_var,
-	.fb_set_par   = picolcd_set_par,
-};
-
-
-/* Callback from deferred IO workqueue */
-static void picolcd_fb_deferred_io(struct fb_info *info, struct list_head *pagelist)
-{
-	picolcd_fb_update(info->par);
-}
-
-static const struct fb_deferred_io picolcd_fb_defio = {
-	.delay = HZ / PICOLCDFB_UPDATE_RATE_DEFAULT,
-	.deferred_io = picolcd_fb_deferred_io,
-};
-
-
-/*
- * The "fb_update_rate" sysfs attribute
- */
-static ssize_t picolcd_fb_update_rate_show(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct picolcd_data *data = dev_get_drvdata(dev);
-	unsigned i, fb_update_rate = data->fb_update_rate;
-	size_t ret = 0;
-
-	for (i = 1; i <= PICOLCDFB_UPDATE_RATE_LIMIT; i++)
-		if (ret >= PAGE_SIZE)
-			break;
-		else if (i == fb_update_rate)
-			ret += snprintf(buf+ret, PAGE_SIZE-ret, "[%u] ", i);
-		else
-			ret += snprintf(buf+ret, PAGE_SIZE-ret, "%u ", i);
-	if (ret > 0)
-		buf[min(ret, (size_t)PAGE_SIZE)-1] = '\n';
-	return ret;
-}
-
-static ssize_t picolcd_fb_update_rate_store(struct device *dev,
-		struct device_attribute *attr, const char *buf, size_t count)
-{
-	struct picolcd_data *data = dev_get_drvdata(dev);
-	int i;
-	unsigned u;
-
-	if (count < 1 || count > 10)
-		return -EINVAL;
-
-	i = sscanf(buf, "%u", &u);
-	if (i != 1)
-		return -EINVAL;
-
-	if (u > PICOLCDFB_UPDATE_RATE_LIMIT)
-		return -ERANGE;
-	else if (u == 0)
-		u = PICOLCDFB_UPDATE_RATE_DEFAULT;
-
-	data->fb_update_rate = u;
-	data->fb_defio.delay = HZ / data->fb_update_rate;
-	return count;
-}
-
-static DEVICE_ATTR(fb_update_rate, 0666, picolcd_fb_update_rate_show,
-		picolcd_fb_update_rate_store);
-
-/* initialize Framebuffer device */
-static int picolcd_init_framebuffer(struct picolcd_data *data)
-{
-	struct device *dev = &data->hdev->dev;
-	struct fb_info *info = NULL;
-	int i, error = -ENOMEM;
-	u8 *fb_vbitmap = NULL;
-	u8 *fb_bitmap  = NULL;
-	u32 *palette;
-
-	fb_bitmap = vmalloc(PICOLCDFB_SIZE*8);
-	if (fb_bitmap == NULL) {
-		dev_err(dev, "can't get a free page for framebuffer\n");
-		goto err_nomem;
-	}
-
-	fb_vbitmap = kmalloc(PICOLCDFB_SIZE, GFP_KERNEL);
-	if (fb_vbitmap == NULL) {
-		dev_err(dev, "can't alloc vbitmap image buffer\n");
-		goto err_nomem;
-	}
-
-	data->fb_update_rate = PICOLCDFB_UPDATE_RATE_DEFAULT;
-	data->fb_defio = picolcd_fb_defio;
-	/* The extra memory is:
-	 * - struct picolcd_fb_cleanup_item
-	 * - u32 for ref_count
-	 * - 256*u32 for pseudo_palette
-	 */
-	info = framebuffer_alloc(257 * sizeof(u32) + sizeof(struct picolcd_fb_cleanup_item), dev);
-	if (info == NULL) {
-		dev_err(dev, "failed to allocate a framebuffer\n");
-		goto err_nomem;
-	}
-
-	palette  = info->par + sizeof(struct picolcd_fb_cleanup_item);
-	*palette = 1;
-	palette++;
-	for (i = 0; i < 256; i++)
-		palette[i] = i > 0 && i < 16 ? 0xff : 0;
-	info->pseudo_palette = palette;
-	info->fbdefio = &data->fb_defio;
-	info->screen_base = (char __force __iomem *)fb_bitmap;
-	info->fbops = &picolcdfb_ops;
-	info->var = picolcdfb_var;
-	info->fix = picolcdfb_fix;
-	info->fix.smem_len   = PICOLCDFB_SIZE*8;
-	info->fix.smem_start = (unsigned long)fb_bitmap;
-	info->par = data;
-	info->flags = FBINFO_FLAG_DEFAULT;
-
-	data->fb_vbitmap = fb_vbitmap;
-	data->fb_bitmap  = fb_bitmap;
-	data->fb_bpp     = picolcdfb_var.bits_per_pixel;
-	error = picolcd_fb_reset(data, 1);
-	if (error) {
-		dev_err(dev, "failed to configure display\n");
-		goto err_cleanup;
-	}
-	error = device_create_file(dev, &dev_attr_fb_update_rate);
-	if (error) {
-		dev_err(dev, "failed to create sysfs attributes\n");
-		goto err_cleanup;
-	}
-	fb_deferred_io_init(info);
-	data->fb_info    = info;
-	error = register_framebuffer(info);
-	if (error) {
-		dev_err(dev, "failed to register framebuffer\n");
-		goto err_sysfs;
-	}
-	/* schedule first output of framebuffer */
-	data->fb_force = 1;
-	schedule_delayed_work(&info->deferred_work, 0);
-	return 0;
-
-err_sysfs:
-	fb_deferred_io_cleanup(info);
-	device_remove_file(dev, &dev_attr_fb_update_rate);
-err_cleanup:
-	data->fb_vbitmap = NULL;
-	data->fb_bitmap  = NULL;
-	data->fb_bpp     = 0;
-	data->fb_info    = NULL;
-
-err_nomem:
-	framebuffer_release(info);
-	vfree(fb_bitmap);
-	kfree(fb_vbitmap);
-	return error;
-}
-
-static void picolcd_exit_framebuffer(struct picolcd_data *data)
-{
-	struct fb_info *info = data->fb_info;
-	u8 *fb_vbitmap = data->fb_vbitmap;
-
-	if (!info)
-		return;
-
-	info->par = NULL;
-	device_remove_file(&data->hdev->dev, &dev_attr_fb_update_rate);
-	unregister_framebuffer(info);
-	data->fb_vbitmap = NULL;
-	data->fb_bitmap  = NULL;
-	data->fb_bpp     = 0;
-	data->fb_info    = NULL;
-	kfree(fb_vbitmap);
-}
-
-#define picolcd_fbinfo(d) ((d)->fb_info)
-#else
-static inline int picolcd_fb_reset(struct picolcd_data *data, int clear)
-{
-	return 0;
-}
-static inline int picolcd_init_framebuffer(struct picolcd_data *data)
-{
-	return 0;
-}
-static inline void picolcd_exit_framebuffer(struct picolcd_data *data)
-{
-}
-#define picolcd_fbinfo(d) NULL
-#endif /* CONFIG_HID_PICOLCD_FB */
-
-#ifdef CONFIG_HID_PICOLCD_BACKLIGHT
-/*
- * backlight class device
- */
-static int picolcd_get_brightness(struct backlight_device *bdev)
-{
-	struct picolcd_data *data = bl_get_data(bdev);
-	return data->lcd_brightness;
-}
-
-static int picolcd_set_brightness(struct backlight_device *bdev)
-{
-	struct picolcd_data *data = bl_get_data(bdev);
-	struct hid_report *report = picolcd_out_report(REPORT_BRIGHTNESS, data->hdev);
-	unsigned long flags;
-
-	if (!report || report->maxfield != 1 || report->field[0]->report_count != 1)
-		return -ENODEV;
-
-	data->lcd_brightness = bdev->props.brightness & 0x0ff;
-	data->lcd_power      = bdev->props.power;
-	spin_lock_irqsave(&data->lock, flags);
-	hid_set_field(report->field[0], 0, data->lcd_power == FB_BLANK_UNBLANK ? data->lcd_brightness : 0);
-	usbhid_submit_report(data->hdev, report, USB_DIR_OUT);
-	spin_unlock_irqrestore(&data->lock, flags);
-	return 0;
-}
-
-static int picolcd_check_bl_fb(struct backlight_device *bdev, struct fb_info *fb)
-{
-	return fb && fb == picolcd_fbinfo((struct picolcd_data *)bl_get_data(bdev));
-}
-
-static const struct backlight_ops picolcd_blops = {
-	.update_status  = picolcd_set_brightness,
-	.get_brightness = picolcd_get_brightness,
-	.check_fb       = picolcd_check_bl_fb,
-};
-
-static int picolcd_init_backlight(struct picolcd_data *data, struct hid_report *report)
-{
-	struct device *dev = &data->hdev->dev;
-	struct backlight_device *bdev;
-	struct backlight_properties props;
-	if (!report)
-		return -ENODEV;
-	if (report->maxfield != 1 || report->field[0]->report_count != 1 ||
-			report->field[0]->report_size != 8) {
-		dev_err(dev, "unsupported BRIGHTNESS report");
-		return -EINVAL;
-	}
-
-	memset(&props, 0, sizeof(props));
-	props.type = BACKLIGHT_RAW;
-	props.max_brightness = 0xff;
-	bdev = backlight_device_register(dev_name(dev), dev, data,
-			&picolcd_blops, &props);
-	if (IS_ERR(bdev)) {
-		dev_err(dev, "failed to register backlight\n");
-		return PTR_ERR(bdev);
-	}
-	bdev->props.brightness     = 0xff;
-	data->lcd_brightness       = 0xff;
-	data->backlight            = bdev;
-	picolcd_set_brightness(bdev);
-	return 0;
-}
-
-static void picolcd_exit_backlight(struct picolcd_data *data)
-{
-	struct backlight_device *bdev = data->backlight;
-
-	data->backlight = NULL;
-	if (bdev)
-		backlight_device_unregister(bdev);
-}
-
-static inline int picolcd_resume_backlight(struct picolcd_data *data)
-{
-	if (!data->backlight)
-		return 0;
-	return picolcd_set_brightness(data->backlight);
-}
-
-#ifdef CONFIG_PM
-static void picolcd_suspend_backlight(struct picolcd_data *data)
-{
-	int bl_power = data->lcd_power;
-	if (!data->backlight)
-		return;
-
-	data->backlight->props.power = FB_BLANK_POWERDOWN;
-	picolcd_set_brightness(data->backlight);
-	data->lcd_power = data->backlight->props.power = bl_power;
-}
-#endif /* CONFIG_PM */
-#else
-static inline int picolcd_init_backlight(struct picolcd_data *data,
-		struct hid_report *report)
-{
-	return 0;
-}
-static inline void picolcd_exit_backlight(struct picolcd_data *data)
-{
-}
-static inline int picolcd_resume_backlight(struct picolcd_data *data)
-{
-	return 0;
-}
-static inline void picolcd_suspend_backlight(struct picolcd_data *data)
-{
-}
-#endif /* CONFIG_HID_PICOLCD_BACKLIGHT */
-
-#ifdef CONFIG_HID_PICOLCD_LCD
-/*
- * lcd class device
- */
-static int picolcd_get_contrast(struct lcd_device *ldev)
-{
-	struct picolcd_data *data = lcd_get_data(ldev);
-	return data->lcd_contrast;
-}
-
-static int picolcd_set_contrast(struct lcd_device *ldev, int contrast)
-{
-	struct picolcd_data *data = lcd_get_data(ldev);
-	struct hid_report *report = picolcd_out_report(REPORT_CONTRAST, data->hdev);
-	unsigned long flags;
-
-	if (!report || report->maxfield != 1 || report->field[0]->report_count != 1)
-		return -ENODEV;
-
-	data->lcd_contrast = contrast & 0x0ff;
-	spin_lock_irqsave(&data->lock, flags);
-	hid_set_field(report->field[0], 0, data->lcd_contrast);
-	usbhid_submit_report(data->hdev, report, USB_DIR_OUT);
-	spin_unlock_irqrestore(&data->lock, flags);
-	return 0;
-}
-
-static int picolcd_check_lcd_fb(struct lcd_device *ldev, struct fb_info *fb)
-{
-	return fb && fb == picolcd_fbinfo((struct picolcd_data *)lcd_get_data(ldev));
-}
-
-static struct lcd_ops picolcd_lcdops = {
-	.get_contrast   = picolcd_get_contrast,
-	.set_contrast   = picolcd_set_contrast,
-	.check_fb       = picolcd_check_lcd_fb,
-};
-
-static int picolcd_init_lcd(struct picolcd_data *data, struct hid_report *report)
-{
-	struct device *dev = &data->hdev->dev;
-	struct lcd_device *ldev;
-
-	if (!report)
-		return -ENODEV;
-	if (report->maxfield != 1 || report->field[0]->report_count != 1 ||
-			report->field[0]->report_size != 8) {
-		dev_err(dev, "unsupported CONTRAST report");
-		return -EINVAL;
-	}
-
-	ldev = lcd_device_register(dev_name(dev), dev, data, &picolcd_lcdops);
-	if (IS_ERR(ldev)) {
-		dev_err(dev, "failed to register LCD\n");
-		return PTR_ERR(ldev);
-	}
-	ldev->props.max_contrast = 0x0ff;
-	data->lcd_contrast = 0xe5;
-	data->lcd = ldev;
-	picolcd_set_contrast(ldev, 0xe5);
-	return 0;
-}
-
-static void picolcd_exit_lcd(struct picolcd_data *data)
-{
-	struct lcd_device *ldev = data->lcd;
-
-	data->lcd = NULL;
-	if (ldev)
-		lcd_device_unregister(ldev);
-}
-
-static inline int picolcd_resume_lcd(struct picolcd_data *data)
-{
-	if (!data->lcd)
-		return 0;
-	return picolcd_set_contrast(data->lcd, data->lcd_contrast);
-}
-#else
-static inline int picolcd_init_lcd(struct picolcd_data *data,
-		struct hid_report *report)
-{
-	return 0;
-}
-static inline void picolcd_exit_lcd(struct picolcd_data *data)
-{
-}
-static inline int picolcd_resume_lcd(struct picolcd_data *data)
-{
-	return 0;
-}
-#endif /* CONFIG_HID_PICOLCD_LCD */
-
-#ifdef CONFIG_HID_PICOLCD_LEDS
-/**
- * LED class device
- */
-static void picolcd_leds_set(struct picolcd_data *data)
-{
-	struct hid_report *report;
-	unsigned long flags;
-
-	if (!data->led[0])
-		return;
-	report = picolcd_out_report(REPORT_LED_STATE, data->hdev);
-	if (!report || report->maxfield != 1 || report->field[0]->report_count != 1)
-		return;
-
-	spin_lock_irqsave(&data->lock, flags);
-	hid_set_field(report->field[0], 0, data->led_state);
-	usbhid_submit_report(data->hdev, report, USB_DIR_OUT);
-	spin_unlock_irqrestore(&data->lock, flags);
-}
-
-static void picolcd_led_set_brightness(struct led_classdev *led_cdev,
-			enum led_brightness value)
-{
-	struct device *dev;
-	struct hid_device *hdev;
-	struct picolcd_data *data;
-	int i, state = 0;
-
-	dev  = led_cdev->dev->parent;
-	hdev = container_of(dev, struct hid_device, dev);
-	data = hid_get_drvdata(hdev);
-	for (i = 0; i < 8; i++) {
-		if (led_cdev != data->led[i])
-			continue;
-		state = (data->led_state >> i) & 1;
-		if (value == LED_OFF && state) {
-			data->led_state &= ~(1 << i);
-			picolcd_leds_set(data);
-		} else if (value != LED_OFF && !state) {
-			data->led_state |= 1 << i;
-			picolcd_leds_set(data);
-		}
-		break;
-	}
-}
-
-static enum led_brightness picolcd_led_get_brightness(struct led_classdev *led_cdev)
-{
-	struct device *dev;
-	struct hid_device *hdev;
-	struct picolcd_data *data;
-	int i, value = 0;
-
-	dev  = led_cdev->dev->parent;
-	hdev = container_of(dev, struct hid_device, dev);
-	data = hid_get_drvdata(hdev);
-	for (i = 0; i < 8; i++)
-		if (led_cdev == data->led[i]) {
-			value = (data->led_state >> i) & 1;
-			break;
-		}
-	return value ? LED_FULL : LED_OFF;
-}
-
-static int picolcd_init_leds(struct picolcd_data *data, struct hid_report *report)
-{
-	struct device *dev = &data->hdev->dev;
-	struct led_classdev *led;
-	size_t name_sz = strlen(dev_name(dev)) + 8;
-	char *name;
-	int i, ret = 0;
-
-	if (!report)
-		return -ENODEV;
-	if (report->maxfield != 1 || report->field[0]->report_count != 1 ||
-			report->field[0]->report_size != 8) {
-		dev_err(dev, "unsupported LED_STATE report");
-		return -EINVAL;
-	}
-
-	for (i = 0; i < 8; i++) {
-		led = kzalloc(sizeof(struct led_classdev)+name_sz, GFP_KERNEL);
-		if (!led) {
-			dev_err(dev, "can't allocate memory for LED %d\n", i);
-			ret = -ENOMEM;
-			goto err;
-		}
-		name = (void *)(&led[1]);
-		snprintf(name, name_sz, "%s::GPO%d", dev_name(dev), i);
-		led->name = name;
-		led->brightness = 0;
-		led->max_brightness = 1;
-		led->brightness_get = picolcd_led_get_brightness;
-		led->brightness_set = picolcd_led_set_brightness;
-
-		data->led[i] = led;
-		ret = led_classdev_register(dev, data->led[i]);
-		if (ret) {
-			data->led[i] = NULL;
-			kfree(led);
-			dev_err(dev, "can't register LED %d\n", i);
-			goto err;
-		}
-	}
-	return 0;
-err:
-	for (i = 0; i < 8; i++)
-		if (data->led[i]) {
-			led = data->led[i];
-			data->led[i] = NULL;
-			led_classdev_unregister(led);
-			kfree(led);
-		}
-	return ret;
-}
-
-static void picolcd_exit_leds(struct picolcd_data *data)
-{
-	struct led_classdev *led;
-	int i;
-
-	for (i = 0; i < 8; i++) {
-		led = data->led[i];
-		data->led[i] = NULL;
-		if (!led)
-			continue;
-		led_classdev_unregister(led);
-		kfree(led);
-	}
-}
-
-#else
-static inline int picolcd_init_leds(struct picolcd_data *data,
-		struct hid_report *report)
-{
-	return 0;
-}
-static inline void picolcd_exit_leds(struct picolcd_data *data)
-{
-}
-static inline int picolcd_leds_set(struct picolcd_data *data)
-{
-	return 0;
-}
-#endif /* CONFIG_HID_PICOLCD_LEDS */
-
-/*
- * input class device
- */
-static int picolcd_raw_keypad(struct picolcd_data *data,
-		struct hid_report *report, u8 *raw_data, int size)
-{
-	/*
-	 * Keypad event
-	 * First and second data bytes list currently pressed keys,
-	 * 0x00 means no key and at most 2 keys may be pressed at same time
-	 */
-	int i, j;
-
-	/* determine newly pressed keys */
-	for (i = 0; i < size; i++) {
-		unsigned int key_code;
-		if (raw_data[i] == 0)
-			continue;
-		for (j = 0; j < sizeof(data->pressed_keys); j++)
-			if (data->pressed_keys[j] == raw_data[i])
-				goto key_already_down;
-		for (j = 0; j < sizeof(data->pressed_keys); j++)
-			if (data->pressed_keys[j] == 0) {
-				data->pressed_keys[j] = raw_data[i];
-				break;
-			}
-		input_event(data->input_keys, EV_MSC, MSC_SCAN, raw_data[i]);
-		if (raw_data[i] < PICOLCD_KEYS)
-			key_code = data->keycode[raw_data[i]];
-		else
-			key_code = KEY_UNKNOWN;
-		if (key_code != KEY_UNKNOWN) {
-			dbg_hid(PICOLCD_NAME " got key press for %u:%d",
-					raw_data[i], key_code);
-			input_report_key(data->input_keys, key_code, 1);
-		}
-		input_sync(data->input_keys);
-key_already_down:
-		continue;
-	}
-
-	/* determine newly released keys */
-	for (j = 0; j < sizeof(data->pressed_keys); j++) {
-		unsigned int key_code;
-		if (data->pressed_keys[j] == 0)
-			continue;
-		for (i = 0; i < size; i++)
-			if (data->pressed_keys[j] == raw_data[i])
-				goto key_still_down;
-		input_event(data->input_keys, EV_MSC, MSC_SCAN, data->pressed_keys[j]);
-		if (data->pressed_keys[j] < PICOLCD_KEYS)
-			key_code = data->keycode[data->pressed_keys[j]];
-		else
-			key_code = KEY_UNKNOWN;
-		if (key_code != KEY_UNKNOWN) {
-			dbg_hid(PICOLCD_NAME " got key release for %u:%d",
-					data->pressed_keys[j], key_code);
-			input_report_key(data->input_keys, key_code, 0);
-		}
-		input_sync(data->input_keys);
-		data->pressed_keys[j] = 0;
-key_still_down:
-		continue;
-	}
-	return 1;
-}
-
-static int picolcd_raw_cir(struct picolcd_data *data,
-		struct hid_report *report, u8 *raw_data, int size)
-{
-	/* Need understanding of CIR data format to implement ... */
-	return 1;
-}
-
-static int picolcd_check_version(struct hid_device *hdev)
-{
-	struct picolcd_data *data = hid_get_drvdata(hdev);
-	struct picolcd_pending *verinfo;
-	int ret = 0;
-
-	if (!data)
-		return -ENODEV;
-
-	verinfo = picolcd_send_and_wait(hdev, REPORT_VERSION, NULL, 0);
-	if (!verinfo) {
-		hid_err(hdev, "no version response from PicoLCD\n");
-		return -ENODEV;
-	}
-
-	if (verinfo->raw_size == 2) {
-		data->version[0] = verinfo->raw_data[1];
-		data->version[1] = verinfo->raw_data[0];
-		if (data->status & PICOLCD_BOOTLOADER) {
-			hid_info(hdev, "PicoLCD, bootloader version %d.%d\n",
-				 verinfo->raw_data[1], verinfo->raw_data[0]);
-		} else {
-			hid_info(hdev, "PicoLCD, firmware version %d.%d\n",
-				 verinfo->raw_data[1], verinfo->raw_data[0]);
-		}
-	} else {
-		hid_err(hdev, "confused, got unexpected version response from PicoLCD\n");
-		ret = -EINVAL;
-	}
-	kfree(verinfo);
-	return ret;
-}
-
-/*
- * Reset our device and wait for answer to VERSION request
- */
-static int picolcd_reset(struct hid_device *hdev)
-{
-	struct picolcd_data *data = hid_get_drvdata(hdev);
-	struct hid_report *report = picolcd_out_report(REPORT_RESET, hdev);
-	unsigned long flags;
-	int error;
-
-	if (!data || !report || report->maxfield != 1)
-		return -ENODEV;
-
-	spin_lock_irqsave(&data->lock, flags);
-	if (hdev->product == USB_DEVICE_ID_PICOLCD_BOOTLOADER)
-		data->status |= PICOLCD_BOOTLOADER;
-
-	/* perform the reset */
-	hid_set_field(report->field[0], 0, 1);
-	usbhid_submit_report(hdev, report, USB_DIR_OUT);
-	spin_unlock_irqrestore(&data->lock, flags);
-
-	error = picolcd_check_version(hdev);
-	if (error)
-		return error;
-
-	picolcd_resume_lcd(data);
-	picolcd_resume_backlight(data);
-#ifdef CONFIG_HID_PICOLCD_FB
-	if (data->fb_info)
-		schedule_delayed_work(&data->fb_info->deferred_work, 0);
-#endif /* CONFIG_HID_PICOLCD_FB */
-
-	picolcd_leds_set(data);
-	return 0;
-}
-
-/*
- * The "operation_mode" sysfs attribute
- */
-static ssize_t picolcd_operation_mode_show(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct picolcd_data *data = dev_get_drvdata(dev);
-
-	if (data->status & PICOLCD_BOOTLOADER)
-		return snprintf(buf, PAGE_SIZE, "[bootloader] lcd\n");
-	else
-		return snprintf(buf, PAGE_SIZE, "bootloader [lcd]\n");
-}
-
-static ssize_t picolcd_operation_mode_store(struct device *dev,
-		struct device_attribute *attr, const char *buf, size_t count)
-{
-	struct picolcd_data *data = dev_get_drvdata(dev);
-	struct hid_report *report = NULL;
-	size_t cnt = count;
-	int timeout = data->opmode_delay;
-	unsigned long flags;
-
-	if (cnt >= 3 && strncmp("lcd", buf, 3) == 0) {
-		if (data->status & PICOLCD_BOOTLOADER)
-			report = picolcd_out_report(REPORT_EXIT_FLASHER, data->hdev);
-		buf += 3;
-		cnt -= 3;
-	} else if (cnt >= 10 && strncmp("bootloader", buf, 10) == 0) {
-		if (!(data->status & PICOLCD_BOOTLOADER))
-			report = picolcd_out_report(REPORT_EXIT_KEYBOARD, data->hdev);
-		buf += 10;
-		cnt -= 10;
-	}
-	if (!report)
-		return -EINVAL;
-
-	while (cnt > 0 && (buf[cnt-1] == '\n' || buf[cnt-1] == '\r'))
-		cnt--;
-	if (cnt != 0)
-		return -EINVAL;
-
-	spin_lock_irqsave(&data->lock, flags);
-	hid_set_field(report->field[0], 0, timeout & 0xff);
-	hid_set_field(report->field[0], 1, (timeout >> 8) & 0xff);
-	usbhid_submit_report(data->hdev, report, USB_DIR_OUT);
-	spin_unlock_irqrestore(&data->lock, flags);
-	return count;
-}
-
-static DEVICE_ATTR(operation_mode, 0644, picolcd_operation_mode_show,
-		picolcd_operation_mode_store);
-
-/*
- * The "operation_mode_delay" sysfs attribute
- */
-static ssize_t picolcd_operation_mode_delay_show(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct picolcd_data *data = dev_get_drvdata(dev);
-
-	return snprintf(buf, PAGE_SIZE, "%hu\n", data->opmode_delay);
-}
-
-static ssize_t picolcd_operation_mode_delay_store(struct device *dev,
-		struct device_attribute *attr, const char *buf, size_t count)
-{
-	struct picolcd_data *data = dev_get_drvdata(dev);
-	unsigned u;
-	if (sscanf(buf, "%u", &u) != 1)
-		return -EINVAL;
-	if (u > 30000)
-		return -EINVAL;
-	else
-		data->opmode_delay = u;
-	return count;
-}
-
-static DEVICE_ATTR(operation_mode_delay, 0644, picolcd_operation_mode_delay_show,
-		picolcd_operation_mode_delay_store);
-
-
-#ifdef CONFIG_DEBUG_FS
-/*
- * The "reset" file
- */
-static int picolcd_debug_reset_show(struct seq_file *f, void *p)
-{
-	if (picolcd_fbinfo((struct picolcd_data *)f->private))
-		seq_printf(f, "all fb\n");
-	else
-		seq_printf(f, "all\n");
-	return 0;
-}
-
-static int picolcd_debug_reset_open(struct inode *inode, struct file *f)
-{
-	return single_open(f, picolcd_debug_reset_show, inode->i_private);
-}
-
-static ssize_t picolcd_debug_reset_write(struct file *f, const char __user *user_buf,
-		size_t count, loff_t *ppos)
-{
-	struct picolcd_data *data = ((struct seq_file *)f->private_data)->private;
-	char buf[32];
-	size_t cnt = min(count, sizeof(buf)-1);
-	if (copy_from_user(buf, user_buf, cnt))
-		return -EFAULT;
-
-	while (cnt > 0 && (buf[cnt-1] == ' ' || buf[cnt-1] == '\n'))
-		cnt--;
-	buf[cnt] = '\0';
-	if (strcmp(buf, "all") == 0) {
-		picolcd_reset(data->hdev);
-		picolcd_fb_reset(data, 1);
-	} else if (strcmp(buf, "fb") == 0) {
-		picolcd_fb_reset(data, 1);
-	} else {
-		return -EINVAL;
-	}
-	return count;
-}
-
-static const struct file_operations picolcd_debug_reset_fops = {
-	.owner    = THIS_MODULE,
-	.open     = picolcd_debug_reset_open,
-	.read     = seq_read,
-	.llseek   = seq_lseek,
-	.write    = picolcd_debug_reset_write,
-	.release  = single_release,
-};
-
-/*
- * The "eeprom" file
- */
-static ssize_t picolcd_debug_eeprom_read(struct file *f, char __user *u,
-		size_t s, loff_t *off)
-{
-	struct picolcd_data *data = f->private_data;
-	struct picolcd_pending *resp;
-	u8 raw_data[3];
-	ssize_t ret = -EIO;
-
-	if (s == 0)
-		return -EINVAL;
-	if (*off > 0x0ff)
-		return 0;
-
-	/* prepare buffer with info about what we want to read (addr & len) */
-	raw_data[0] = *off & 0xff;
-	raw_data[1] = (*off >> 8) & 0xff;
-	raw_data[2] = s < 20 ? s : 20;
-	if (*off + raw_data[2] > 0xff)
-		raw_data[2] = 0x100 - *off;
-	resp = picolcd_send_and_wait(data->hdev, REPORT_EE_READ, raw_data,
-			sizeof(raw_data));
-	if (!resp)
-		return -EIO;
-
-	if (resp->in_report && resp->in_report->id == REPORT_EE_DATA) {
-		/* successful read :) */
-		ret = resp->raw_data[2];
-		if (ret > s)
-			ret = s;
-		if (copy_to_user(u, resp->raw_data+3, ret))
-			ret = -EFAULT;
-		else
-			*off += ret;
-	} /* anything else is some kind of IO error */
-
-	kfree(resp);
-	return ret;
-}
-
-static ssize_t picolcd_debug_eeprom_write(struct file *f, const char __user *u,
-		size_t s, loff_t *off)
-{
-	struct picolcd_data *data = f->private_data;
-	struct picolcd_pending *resp;
-	ssize_t ret = -EIO;
-	u8 raw_data[23];
-
-	if (s == 0)
-		return -EINVAL;
-	if (*off > 0x0ff)
-		return -ENOSPC;
-
-	memset(raw_data, 0, sizeof(raw_data));
-	raw_data[0] = *off & 0xff;
-	raw_data[1] = (*off >> 8) & 0xff;
-	raw_data[2] = min((size_t)20, s);
-	if (*off + raw_data[2] > 0xff)
-		raw_data[2] = 0x100 - *off;
-
-	if (copy_from_user(raw_data+3, u, min((u8)20, raw_data[2])))
-		return -EFAULT;
-	resp = picolcd_send_and_wait(data->hdev, REPORT_EE_WRITE, raw_data,
-			sizeof(raw_data));
-
-	if (!resp)
-		return -EIO;
-
-	if (resp->in_report && resp->in_report->id == REPORT_EE_DATA) {
-		/* check if written data matches */
-		if (memcmp(raw_data, resp->raw_data, 3+raw_data[2]) == 0) {
-			*off += raw_data[2];
-			ret = raw_data[2];
-		}
-	}
-	kfree(resp);
-	return ret;
-}
-
-/*
- * Notes:
- * - read/write happens in chunks of at most 20 bytes, it's up to userspace
- *   to loop in order to get more data.
- * - on write errors on otherwise correct write request the bytes
- *   that should have been written are in undefined state.
- */
-static const struct file_operations picolcd_debug_eeprom_fops = {
-	.owner    = THIS_MODULE,
-	.open     = simple_open,
-	.read     = picolcd_debug_eeprom_read,
-	.write    = picolcd_debug_eeprom_write,
-	.llseek   = generic_file_llseek,
-};
-
-/*
- * The "flash" file
- */
-/* record a flash address to buf (bounds check to be done by caller) */
-static int _picolcd_flash_setaddr(struct picolcd_data *data, u8 *buf, long off)
-{
-	buf[0] = off & 0xff;
-	buf[1] = (off >> 8) & 0xff;
-	if (data->addr_sz == 3)
-		buf[2] = (off >> 16) & 0xff;
-	return data->addr_sz == 2 ? 2 : 3;
-}
-
-/* read a given size of data (bounds check to be done by caller) */
-static ssize_t _picolcd_flash_read(struct picolcd_data *data, int report_id,
-		char __user *u, size_t s, loff_t *off)
-{
-	struct picolcd_pending *resp;
-	u8 raw_data[4];
-	ssize_t ret = 0;
-	int len_off, err = -EIO;
-
-	while (s > 0) {
-		err = -EIO;
-		len_off = _picolcd_flash_setaddr(data, raw_data, *off);
-		raw_data[len_off] = s > 32 ? 32 : s;
-		resp = picolcd_send_and_wait(data->hdev, report_id, raw_data, len_off+1);
-		if (!resp || !resp->in_report)
-			goto skip;
-		if (resp->in_report->id == REPORT_MEMORY ||
-			resp->in_report->id == REPORT_BL_READ_MEMORY) {
-			if (memcmp(raw_data, resp->raw_data, len_off+1) != 0)
-				goto skip;
-			if (copy_to_user(u+ret, resp->raw_data+len_off+1, raw_data[len_off])) {
-				err = -EFAULT;
-				goto skip;
-			}
-			*off += raw_data[len_off];
-			s    -= raw_data[len_off];
-			ret  += raw_data[len_off];
-			err   = 0;
-		}
-skip:
-		kfree(resp);
-		if (err)
-			return ret > 0 ? ret : err;
-	}
-	return ret;
-}
-
-static ssize_t picolcd_debug_flash_read(struct file *f, char __user *u,
-		size_t s, loff_t *off)
-{
-	struct picolcd_data *data = f->private_data;
-
-	if (s == 0)
-		return -EINVAL;
-	if (*off > 0x05fff)
-		return 0;
-	if (*off + s > 0x05fff)
-		s = 0x06000 - *off;
-
-	if (data->status & PICOLCD_BOOTLOADER)
-		return _picolcd_flash_read(data, REPORT_BL_READ_MEMORY, u, s, off);
-	else
-		return _picolcd_flash_read(data, REPORT_READ_MEMORY, u, s, off);
-}
-
-/* erase block aligned to 64bytes boundary */
-static ssize_t _picolcd_flash_erase64(struct picolcd_data *data, int report_id,
-		loff_t *off)
-{
-	struct picolcd_pending *resp;
-	u8 raw_data[3];
-	int len_off;
-	ssize_t ret = -EIO;
-
-	if (*off & 0x3f)
-		return -EINVAL;
-
-	len_off = _picolcd_flash_setaddr(data, raw_data, *off);
-	resp = picolcd_send_and_wait(data->hdev, report_id, raw_data, len_off);
-	if (!resp || !resp->in_report)
-		goto skip;
-	if (resp->in_report->id == REPORT_MEMORY ||
-		resp->in_report->id == REPORT_BL_ERASE_MEMORY) {
-		if (memcmp(raw_data, resp->raw_data, len_off) != 0)
-			goto skip;
-		ret = 0;
-	}
-skip:
-	kfree(resp);
-	return ret;
-}
-
-/* write a given size of data (bounds check to be done by caller) */
-static ssize_t _picolcd_flash_write(struct picolcd_data *data, int report_id,
-		const char __user *u, size_t s, loff_t *off)
-{
-	struct picolcd_pending *resp;
-	u8 raw_data[36];
-	ssize_t ret = 0;
-	int len_off, err = -EIO;
-
-	while (s > 0) {
-		err = -EIO;
-		len_off = _picolcd_flash_setaddr(data, raw_data, *off);
-		raw_data[len_off] = s > 32 ? 32 : s;
-		if (copy_from_user(raw_data+len_off+1, u, raw_data[len_off])) {
-			err = -EFAULT;
-			break;
-		}
-		resp = picolcd_send_and_wait(data->hdev, report_id, raw_data,
-				len_off+1+raw_data[len_off]);
-		if (!resp || !resp->in_report)
-			goto skip;
-		if (resp->in_report->id == REPORT_MEMORY ||
-			resp->in_report->id == REPORT_BL_WRITE_MEMORY) {
-			if (memcmp(raw_data, resp->raw_data, len_off+1+raw_data[len_off]) != 0)
-				goto skip;
-			*off += raw_data[len_off];
-			s    -= raw_data[len_off];
-			ret  += raw_data[len_off];
-			err   = 0;
-		}
-skip:
-		kfree(resp);
-		if (err)
-			break;
-	}
-	return ret > 0 ? ret : err;
-}
-
-static ssize_t picolcd_debug_flash_write(struct file *f, const char __user *u,
-		size_t s, loff_t *off)
-{
-	struct picolcd_data *data = f->private_data;
-	ssize_t err, ret = 0;
-	int report_erase, report_write;
-
-	if (s == 0)
-		return -EINVAL;
-	if (*off > 0x5fff)
-		return -ENOSPC;
-	if (s & 0x3f)
-		return -EINVAL;
-	if (*off & 0x3f)
-		return -EINVAL;
-
-	if (data->status & PICOLCD_BOOTLOADER) {
-		report_erase = REPORT_BL_ERASE_MEMORY;
-		report_write = REPORT_BL_WRITE_MEMORY;
-	} else {
-		report_erase = REPORT_ERASE_MEMORY;
-		report_write = REPORT_WRITE_MEMORY;
-	}
-	mutex_lock(&data->mutex_flash);
-	while (s > 0) {
-		err = _picolcd_flash_erase64(data, report_erase, off);
-		if (err)
-			break;
-		err = _picolcd_flash_write(data, report_write, u, 64, off);
-		if (err < 0)
-			break;
-		ret += err;
-		*off += err;
-		s -= err;
-		if (err != 64)
-			break;
-	}
-	mutex_unlock(&data->mutex_flash);
-	return ret > 0 ? ret : err;
-}
-
-/*
- * Notes:
- * - concurrent writing is prevented by mutex and all writes must be
- *   n*64 bytes and 64-byte aligned, each write being preceded by an
- *   ERASE which erases a 64byte block.
- *   If less than requested was written or an error is returned for an
- *   otherwise correct write request the next 64-byte block which should
- *   have been written is in undefined state (mostly: original, erased,
- *   (half-)written with write error)
- * - reading can happen without special restriction
- */
-static const struct file_operations picolcd_debug_flash_fops = {
-	.owner    = THIS_MODULE,
-	.open     = simple_open,
-	.read     = picolcd_debug_flash_read,
-	.write    = picolcd_debug_flash_write,
-	.llseek   = generic_file_llseek,
-};
-
-
-/*
- * Helper code for HID report level dumping/debugging
- */
-static const char *error_codes[] = {
-	"success", "parameter missing", "data_missing", "block readonly",
-	"block not erasable", "block too big", "section overflow",
-	"invalid command length", "invalid data length",
-};
-
-static void dump_buff_as_hex(char *dst, size_t dst_sz, const u8 *data,
-		const size_t data_len)
-{
-	int i, j;
-	for (i = j = 0; i < data_len && j + 3 < dst_sz; i++) {
-		dst[j++] = hex_asc[(data[i] >> 4) & 0x0f];
-		dst[j++] = hex_asc[data[i] & 0x0f];
-		dst[j++] = ' ';
-	}
-	if (j < dst_sz) {
-		dst[j--] = '\0';
-		dst[j] = '\n';
-	} else
-		dst[j] = '\0';
-}
-
-static void picolcd_debug_out_report(struct picolcd_data *data,
-		struct hid_device *hdev, struct hid_report *report)
-{
-	u8 raw_data[70];
-	int raw_size = (report->size >> 3) + 1;
-	char *buff;
-#define BUFF_SZ 256
-
-	/* Avoid unnecessary overhead if debugfs is disabled */
-	if (list_empty(&hdev->debug_list))
-		return;
-
-	buff = kmalloc(BUFF_SZ, GFP_ATOMIC);
-	if (!buff)
-		return;
-
-	snprintf(buff, BUFF_SZ, "\nout report %d (size %d) =  ",
-			report->id, raw_size);
-	hid_debug_event(hdev, buff);
-	if (raw_size + 5 > sizeof(raw_data)) {
-		kfree(buff);
-		hid_debug_event(hdev, " TOO BIG\n");
-		return;
-	} else {
-		raw_data[0] = report->id;
-		hid_output_report(report, raw_data);
-		dump_buff_as_hex(buff, BUFF_SZ, raw_data, raw_size);
-		hid_debug_event(hdev, buff);
-	}
-
-	switch (report->id) {
-	case REPORT_LED_STATE:
-		/* 1 data byte with GPO state */
-		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
-			"REPORT_LED_STATE", report->id, raw_size-1);
-		hid_debug_event(hdev, buff);
-		snprintf(buff, BUFF_SZ, "\tGPO state: 0x%02x\n", raw_data[1]);
-		hid_debug_event(hdev, buff);
-		break;
-	case REPORT_BRIGHTNESS:
-		/* 1 data byte with brightness */
-		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
-			"REPORT_BRIGHTNESS", report->id, raw_size-1);
-		hid_debug_event(hdev, buff);
-		snprintf(buff, BUFF_SZ, "\tBrightness: 0x%02x\n", raw_data[1]);
-		hid_debug_event(hdev, buff);
-		break;
-	case REPORT_CONTRAST:
-		/* 1 data byte with contrast */
-		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
-			"REPORT_CONTRAST", report->id, raw_size-1);
-		hid_debug_event(hdev, buff);
-		snprintf(buff, BUFF_SZ, "\tContrast: 0x%02x\n", raw_data[1]);
-		hid_debug_event(hdev, buff);
-		break;
-	case REPORT_RESET:
-		/* 2 data bytes with reset duration in ms */
-		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
-			"REPORT_RESET", report->id, raw_size-1);
-		hid_debug_event(hdev, buff);
-		snprintf(buff, BUFF_SZ, "\tDuration: 0x%02x%02x (%dms)\n",
-				raw_data[2], raw_data[1], raw_data[2] << 8 | raw_data[1]);
-		hid_debug_event(hdev, buff);
-		break;
-	case REPORT_LCD_CMD:
-		/* 63 data bytes with LCD commands */
-		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
-			"REPORT_LCD_CMD", report->id, raw_size-1);
-		hid_debug_event(hdev, buff);
-		/* TODO: format decoding */
-		break;
-	case REPORT_LCD_DATA:
-		/* 63 data bytes with LCD data */
-		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
-			"REPORT_LCD_CMD", report->id, raw_size-1);
-		/* TODO: format decoding */
-		hid_debug_event(hdev, buff);
-		break;
-	case REPORT_LCD_CMD_DATA:
-		/* 63 data bytes with LCD commands and data */
-		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
-			"REPORT_LCD_CMD", report->id, raw_size-1);
-		/* TODO: format decoding */
-		hid_debug_event(hdev, buff);
-		break;
-	case REPORT_EE_READ:
-		/* 3 data bytes with read area description */
-		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
-			"REPORT_EE_READ", report->id, raw_size-1);
-		hid_debug_event(hdev, buff);
-		snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x\n",
-				raw_data[2], raw_data[1]);
-		hid_debug_event(hdev, buff);
-		snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[3]);
-		hid_debug_event(hdev, buff);
-		break;
-	case REPORT_EE_WRITE:
-		/* 3+1..20 data bytes with write area description */
-		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
-			"REPORT_EE_WRITE", report->id, raw_size-1);
-		hid_debug_event(hdev, buff);
-		snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x\n",
-				raw_data[2], raw_data[1]);
-		hid_debug_event(hdev, buff);
-		snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[3]);
-		hid_debug_event(hdev, buff);
-		if (raw_data[3] == 0) {
-			snprintf(buff, BUFF_SZ, "\tNo data\n");
-		} else if (raw_data[3] + 4 <= raw_size) {
-			snprintf(buff, BUFF_SZ, "\tData: ");
-			hid_debug_event(hdev, buff);
-			dump_buff_as_hex(buff, BUFF_SZ, raw_data+4, raw_data[3]);
-		} else {
-			snprintf(buff, BUFF_SZ, "\tData overflowed\n");
-		}
-		hid_debug_event(hdev, buff);
-		break;
-	case REPORT_ERASE_MEMORY:
-	case REPORT_BL_ERASE_MEMORY:
-		/* 3 data bytes with pointer inside erase block */
-		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
-			"REPORT_ERASE_MEMORY", report->id, raw_size-1);
-		hid_debug_event(hdev, buff);
-		switch (data->addr_sz) {
-		case 2:
-			snprintf(buff, BUFF_SZ, "\tAddress inside 64 byte block: 0x%02x%02x\n",
-					raw_data[2], raw_data[1]);
-			break;
-		case 3:
-			snprintf(buff, BUFF_SZ, "\tAddress inside 64 byte block: 0x%02x%02x%02x\n",
-					raw_data[3], raw_data[2], raw_data[1]);
-			break;
-		default:
-			snprintf(buff, BUFF_SZ, "\tNot supported\n");
-		}
-		hid_debug_event(hdev, buff);
-		break;
-	case REPORT_READ_MEMORY:
-	case REPORT_BL_READ_MEMORY:
-		/* 4 data bytes with read area description */
-		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
-			"REPORT_READ_MEMORY", report->id, raw_size-1);
-		hid_debug_event(hdev, buff);
-		switch (data->addr_sz) {
-		case 2:
-			snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x\n",
-					raw_data[2], raw_data[1]);
-			hid_debug_event(hdev, buff);
-			snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[3]);
-			break;
-		case 3:
-			snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x%02x\n",
-					raw_data[3], raw_data[2], raw_data[1]);
-			hid_debug_event(hdev, buff);
-			snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[4]);
-			break;
-		default:
-			snprintf(buff, BUFF_SZ, "\tNot supported\n");
-		}
-		hid_debug_event(hdev, buff);
-		break;
-	case REPORT_WRITE_MEMORY:
-	case REPORT_BL_WRITE_MEMORY:
-		/* 4+1..32 data bytes with write adrea description */
-		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
-			"REPORT_WRITE_MEMORY", report->id, raw_size-1);
-		hid_debug_event(hdev, buff);
-		switch (data->addr_sz) {
-		case 2:
-			snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x\n",
-					raw_data[2], raw_data[1]);
-			hid_debug_event(hdev, buff);
-			snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[3]);
-			hid_debug_event(hdev, buff);
-			if (raw_data[3] == 0) {
-				snprintf(buff, BUFF_SZ, "\tNo data\n");
-			} else if (raw_data[3] + 4 <= raw_size) {
-				snprintf(buff, BUFF_SZ, "\tData: ");
-				hid_debug_event(hdev, buff);
-				dump_buff_as_hex(buff, BUFF_SZ, raw_data+4, raw_data[3]);
-			} else {
-				snprintf(buff, BUFF_SZ, "\tData overflowed\n");
-			}
-			break;
-		case 3:
-			snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x%02x\n",
-					raw_data[3], raw_data[2], raw_data[1]);
-			hid_debug_event(hdev, buff);
-			snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[4]);
-			hid_debug_event(hdev, buff);
-			if (raw_data[4] == 0) {
-				snprintf(buff, BUFF_SZ, "\tNo data\n");
-			} else if (raw_data[4] + 5 <= raw_size) {
-				snprintf(buff, BUFF_SZ, "\tData: ");
-				hid_debug_event(hdev, buff);
-				dump_buff_as_hex(buff, BUFF_SZ, raw_data+5, raw_data[4]);
-			} else {
-				snprintf(buff, BUFF_SZ, "\tData overflowed\n");
-			}
-			break;
-		default:
-			snprintf(buff, BUFF_SZ, "\tNot supported\n");
-		}
-		hid_debug_event(hdev, buff);
-		break;
-	case REPORT_SPLASH_RESTART:
-		/* TODO */
-		break;
-	case REPORT_EXIT_KEYBOARD:
-		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
-			"REPORT_EXIT_KEYBOARD", report->id, raw_size-1);
-		hid_debug_event(hdev, buff);
-		snprintf(buff, BUFF_SZ, "\tRestart delay: %dms (0x%02x%02x)\n",
-				raw_data[1] | (raw_data[2] << 8),
-				raw_data[2], raw_data[1]);
-		hid_debug_event(hdev, buff);
-		break;
-	case REPORT_VERSION:
-		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
-			"REPORT_VERSION", report->id, raw_size-1);
-		hid_debug_event(hdev, buff);
-		break;
-	case REPORT_DEVID:
-		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
-			"REPORT_DEVID", report->id, raw_size-1);
-		hid_debug_event(hdev, buff);
-		break;
-	case REPORT_SPLASH_SIZE:
-		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
-			"REPORT_SPLASH_SIZE", report->id, raw_size-1);
-		hid_debug_event(hdev, buff);
-		break;
-	case REPORT_HOOK_VERSION:
-		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
-			"REPORT_HOOK_VERSION", report->id, raw_size-1);
-		hid_debug_event(hdev, buff);
-		break;
-	case REPORT_EXIT_FLASHER:
-		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
-			"REPORT_VERSION", report->id, raw_size-1);
-		hid_debug_event(hdev, buff);
-		snprintf(buff, BUFF_SZ, "\tRestart delay: %dms (0x%02x%02x)\n",
-				raw_data[1] | (raw_data[2] << 8),
-				raw_data[2], raw_data[1]);
-		hid_debug_event(hdev, buff);
-		break;
-	default:
-		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
-			"<unknown>", report->id, raw_size-1);
-		hid_debug_event(hdev, buff);
-		break;
-	}
-	wake_up_interruptible(&hdev->debug_wait);
-	kfree(buff);
-}
-
-static void picolcd_debug_raw_event(struct picolcd_data *data,
-		struct hid_device *hdev, struct hid_report *report,
-		u8 *raw_data, int size)
-{
-	char *buff;
-
-#define BUFF_SZ 256
-	/* Avoid unnecessary overhead if debugfs is disabled */
-	if (!hdev->debug_events)
-		return;
-
-	buff = kmalloc(BUFF_SZ, GFP_ATOMIC);
-	if (!buff)
-		return;
-
-	switch (report->id) {
-	case REPORT_ERROR_CODE:
-		/* 2 data bytes with affected report and error code */
-		snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
-			"REPORT_ERROR_CODE", report->id, size-1);
-		hid_debug_event(hdev, buff);
-		if (raw_data[2] < ARRAY_SIZE(error_codes))
-			snprintf(buff, BUFF_SZ, "\tError code 0x%02x (%s) in reply to report 0x%02x\n",
-					raw_data[2], error_codes[raw_data[2]], raw_data[1]);
-		else
-			snprintf(buff, BUFF_SZ, "\tError code 0x%02x in reply to report 0x%02x\n",
-					raw_data[2], raw_data[1]);
-		hid_debug_event(hdev, buff);
-		break;
-	case REPORT_KEY_STATE:
-		/* 2 data bytes with key state */
-		snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
-			"REPORT_KEY_STATE", report->id, size-1);
-		hid_debug_event(hdev, buff);
-		if (raw_data[1] == 0)
-			snprintf(buff, BUFF_SZ, "\tNo key pressed\n");
-		else if (raw_data[2] == 0)
-			snprintf(buff, BUFF_SZ, "\tOne key pressed: 0x%02x (%d)\n",
-					raw_data[1], raw_data[1]);
-		else
-			snprintf(buff, BUFF_SZ, "\tTwo keys pressed: 0x%02x (%d), 0x%02x (%d)\n",
-					raw_data[1], raw_data[1], raw_data[2], raw_data[2]);
-		hid_debug_event(hdev, buff);
-		break;
-	case REPORT_IR_DATA:
-		/* Up to 20 byes of IR scancode data */
-		snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
-			"REPORT_IR_DATA", report->id, size-1);
-		hid_debug_event(hdev, buff);
-		if (raw_data[1] == 0) {
-			snprintf(buff, BUFF_SZ, "\tUnexpectedly 0 data length\n");
-			hid_debug_event(hdev, buff);
-		} else if (raw_data[1] + 1 <= size) {
-			snprintf(buff, BUFF_SZ, "\tData length: %d\n\tIR Data: ",
-					raw_data[1]-1);
-			hid_debug_event(hdev, buff);
-			dump_buff_as_hex(buff, BUFF_SZ, raw_data+2, raw_data[1]-1);
-			hid_debug_event(hdev, buff);
-		} else {
-			snprintf(buff, BUFF_SZ, "\tOverflowing data length: %d\n",
-					raw_data[1]-1);
-			hid_debug_event(hdev, buff);
-		}
-		break;
-	case REPORT_EE_DATA:
-		/* Data buffer in response to REPORT_EE_READ or REPORT_EE_WRITE */
-		snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
-			"REPORT_EE_DATA", report->id, size-1);
-		hid_debug_event(hdev, buff);
-		snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x\n",
-				raw_data[2], raw_data[1]);
-		hid_debug_event(hdev, buff);
-		snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[3]);
-		hid_debug_event(hdev, buff);
-		if (raw_data[3] == 0) {
-			snprintf(buff, BUFF_SZ, "\tNo data\n");
-			hid_debug_event(hdev, buff);
-		} else if (raw_data[3] + 4 <= size) {
-			snprintf(buff, BUFF_SZ, "\tData: ");
-			hid_debug_event(hdev, buff);
-			dump_buff_as_hex(buff, BUFF_SZ, raw_data+4, raw_data[3]);
-			hid_debug_event(hdev, buff);
-		} else {
-			snprintf(buff, BUFF_SZ, "\tData overflowed\n");
-			hid_debug_event(hdev, buff);
-		}
-		break;
-	case REPORT_MEMORY:
-		/* Data buffer in response to REPORT_READ_MEMORY or REPORT_WRTIE_MEMORY */
-		snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
-			"REPORT_MEMORY", report->id, size-1);
-		hid_debug_event(hdev, buff);
-		switch (data->addr_sz) {
-		case 2:
-			snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x\n",
-					raw_data[2], raw_data[1]);
-			hid_debug_event(hdev, buff);
-			snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[3]);
-			hid_debug_event(hdev, buff);
-			if (raw_data[3] == 0) {
-				snprintf(buff, BUFF_SZ, "\tNo data\n");
-			} else if (raw_data[3] + 4 <= size) {
-				snprintf(buff, BUFF_SZ, "\tData: ");
-				hid_debug_event(hdev, buff);
-				dump_buff_as_hex(buff, BUFF_SZ, raw_data+4, raw_data[3]);
-			} else {
-				snprintf(buff, BUFF_SZ, "\tData overflowed\n");
-			}
-			break;
-		case 3:
-			snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x%02x\n",
-					raw_data[3], raw_data[2], raw_data[1]);
-			hid_debug_event(hdev, buff);
-			snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[4]);
-			hid_debug_event(hdev, buff);
-			if (raw_data[4] == 0) {
-				snprintf(buff, BUFF_SZ, "\tNo data\n");
-			} else if (raw_data[4] + 5 <= size) {
-				snprintf(buff, BUFF_SZ, "\tData: ");
-				hid_debug_event(hdev, buff);
-				dump_buff_as_hex(buff, BUFF_SZ, raw_data+5, raw_data[4]);
-			} else {
-				snprintf(buff, BUFF_SZ, "\tData overflowed\n");
-			}
-			break;
-		default:
-			snprintf(buff, BUFF_SZ, "\tNot supported\n");
-		}
-		hid_debug_event(hdev, buff);
-		break;
-	case REPORT_VERSION:
-		snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
-			"REPORT_VERSION", report->id, size-1);
-		hid_debug_event(hdev, buff);
-		snprintf(buff, BUFF_SZ, "\tFirmware version: %d.%d\n",
-				raw_data[2], raw_data[1]);
-		hid_debug_event(hdev, buff);
-		break;
-	case REPORT_BL_ERASE_MEMORY:
-		snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
-			"REPORT_BL_ERASE_MEMORY", report->id, size-1);
-		hid_debug_event(hdev, buff);
-		/* TODO */
-		break;
-	case REPORT_BL_READ_MEMORY:
-		snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
-			"REPORT_BL_READ_MEMORY", report->id, size-1);
-		hid_debug_event(hdev, buff);
-		/* TODO */
-		break;
-	case REPORT_BL_WRITE_MEMORY:
-		snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
-			"REPORT_BL_WRITE_MEMORY", report->id, size-1);
-		hid_debug_event(hdev, buff);
-		/* TODO */
-		break;
-	case REPORT_DEVID:
-		snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
-			"REPORT_DEVID", report->id, size-1);
-		hid_debug_event(hdev, buff);
-		snprintf(buff, BUFF_SZ, "\tSerial: 0x%02x%02x%02x%02x\n",
-				raw_data[1], raw_data[2], raw_data[3], raw_data[4]);
-		hid_debug_event(hdev, buff);
-		snprintf(buff, BUFF_SZ, "\tType: 0x%02x\n",
-				raw_data[5]);
-		hid_debug_event(hdev, buff);
-		break;
-	case REPORT_SPLASH_SIZE:
-		snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
-			"REPORT_SPLASH_SIZE", report->id, size-1);
-		hid_debug_event(hdev, buff);
-		snprintf(buff, BUFF_SZ, "\tTotal splash space: %d\n",
-				(raw_data[2] << 8) | raw_data[1]);
-		hid_debug_event(hdev, buff);
-		snprintf(buff, BUFF_SZ, "\tUsed splash space: %d\n",
-				(raw_data[4] << 8) | raw_data[3]);
-		hid_debug_event(hdev, buff);
-		break;
-	case REPORT_HOOK_VERSION:
-		snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
-			"REPORT_HOOK_VERSION", report->id, size-1);
-		hid_debug_event(hdev, buff);
-		snprintf(buff, BUFF_SZ, "\tFirmware version: %d.%d\n",
-				raw_data[1], raw_data[2]);
-		hid_debug_event(hdev, buff);
-		break;
-	default:
-		snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
-			"<unknown>", report->id, size-1);
-		hid_debug_event(hdev, buff);
-		break;
-	}
-	wake_up_interruptible(&hdev->debug_wait);
-	kfree(buff);
-}
-
-static void picolcd_init_devfs(struct picolcd_data *data,
-		struct hid_report *eeprom_r, struct hid_report *eeprom_w,
-		struct hid_report *flash_r, struct hid_report *flash_w,
-		struct hid_report *reset)
-{
-	struct hid_device *hdev = data->hdev;
-
-	mutex_init(&data->mutex_flash);
-
-	/* reset */
-	if (reset)
-		data->debug_reset = debugfs_create_file("reset", 0600,
-				hdev->debug_dir, data, &picolcd_debug_reset_fops);
-
-	/* eeprom */
-	if (eeprom_r || eeprom_w)
-		data->debug_eeprom = debugfs_create_file("eeprom",
-			(eeprom_w ? S_IWUSR : 0) | (eeprom_r ? S_IRUSR : 0),
-			hdev->debug_dir, data, &picolcd_debug_eeprom_fops);
-
-	/* flash */
-	if (flash_r && flash_r->maxfield == 1 && flash_r->field[0]->report_size == 8)
-		data->addr_sz = flash_r->field[0]->report_count - 1;
-	else
-		data->addr_sz = -1;
-	if (data->addr_sz == 2 || data->addr_sz == 3) {
-		data->debug_flash = debugfs_create_file("flash",
-			(flash_w ? S_IWUSR : 0) | (flash_r ? S_IRUSR : 0),
-			hdev->debug_dir, data, &picolcd_debug_flash_fops);
-	} else if (flash_r || flash_w)
-		hid_warn(hdev, "Unexpected FLASH access reports, please submit rdesc for review\n");
-}
-
-static void picolcd_exit_devfs(struct picolcd_data *data)
-{
-	struct dentry *dent;
-
-	dent = data->debug_reset;
-	data->debug_reset = NULL;
-	if (dent)
-		debugfs_remove(dent);
-	dent = data->debug_eeprom;
-	data->debug_eeprom = NULL;
-	if (dent)
-		debugfs_remove(dent);
-	dent = data->debug_flash;
-	data->debug_flash = NULL;
-	if (dent)
-		debugfs_remove(dent);
-	mutex_destroy(&data->mutex_flash);
-}
-#else
-static inline void picolcd_debug_raw_event(struct picolcd_data *data,
-		struct hid_device *hdev, struct hid_report *report,
-		u8 *raw_data, int size)
-{
-}
-static inline void picolcd_init_devfs(struct picolcd_data *data,
-		struct hid_report *eeprom_r, struct hid_report *eeprom_w,
-		struct hid_report *flash_r, struct hid_report *flash_w,
-		struct hid_report *reset)
-{
-}
-static inline void picolcd_exit_devfs(struct picolcd_data *data)
-{
-}
-#endif /* CONFIG_DEBUG_FS */
-
-/*
- * Handle raw report as sent by device
- */
-static int picolcd_raw_event(struct hid_device *hdev,
-		struct hid_report *report, u8 *raw_data, int size)
-{
-	struct picolcd_data *data = hid_get_drvdata(hdev);
-	unsigned long flags;
-	int ret = 0;
-
-	if (!data)
-		return 1;
-
-	if (report->id == REPORT_KEY_STATE) {
-		if (data->input_keys)
-			ret = picolcd_raw_keypad(data, report, raw_data+1, size-1);
-	} else if (report->id == REPORT_IR_DATA) {
-		if (data->input_cir)
-			ret = picolcd_raw_cir(data, report, raw_data+1, size-1);
-	} else {
-		spin_lock_irqsave(&data->lock, flags);
-		/*
-		 * We let the caller of picolcd_send_and_wait() check if the
-		 * report we got is one of the expected ones or not.
-		 */
-		if (data->pending) {
-			memcpy(data->pending->raw_data, raw_data+1, size-1);
-			data->pending->raw_size  = size-1;
-			data->pending->in_report = report;
-			complete(&data->pending->ready);
-		}
-		spin_unlock_irqrestore(&data->lock, flags);
-	}
-
-	picolcd_debug_raw_event(data, hdev, report, raw_data, size);
-	return 1;
-}
-
-#ifdef CONFIG_PM
-static int picolcd_suspend(struct hid_device *hdev, pm_message_t message)
-{
-	if (PMSG_IS_AUTO(message))
-		return 0;
-
-	picolcd_suspend_backlight(hid_get_drvdata(hdev));
-	dbg_hid(PICOLCD_NAME " device ready for suspend\n");
-	return 0;
-}
-
-static int picolcd_resume(struct hid_device *hdev)
-{
-	int ret;
-	ret = picolcd_resume_backlight(hid_get_drvdata(hdev));
-	if (ret)
-		dbg_hid(PICOLCD_NAME " restoring backlight failed: %d\n", ret);
-	return 0;
-}
-
-static int picolcd_reset_resume(struct hid_device *hdev)
-{
-	int ret;
-	ret = picolcd_reset(hdev);
-	if (ret)
-		dbg_hid(PICOLCD_NAME " resetting our device failed: %d\n", ret);
-	ret = picolcd_fb_reset(hid_get_drvdata(hdev), 0);
-	if (ret)
-		dbg_hid(PICOLCD_NAME " restoring framebuffer content failed: %d\n", ret);
-	ret = picolcd_resume_lcd(hid_get_drvdata(hdev));
-	if (ret)
-		dbg_hid(PICOLCD_NAME " restoring lcd failed: %d\n", ret);
-	ret = picolcd_resume_backlight(hid_get_drvdata(hdev));
-	if (ret)
-		dbg_hid(PICOLCD_NAME " restoring backlight failed: %d\n", ret);
-	picolcd_leds_set(hid_get_drvdata(hdev));
-	return 0;
-}
-#endif
-
-/* initialize keypad input device */
-static int picolcd_init_keys(struct picolcd_data *data,
-		struct hid_report *report)
-{
-	struct hid_device *hdev = data->hdev;
-	struct input_dev *idev;
-	int error, i;
-
-	if (!report)
-		return -ENODEV;
-	if (report->maxfield != 1 || report->field[0]->report_count != 2 ||
-			report->field[0]->report_size != 8) {
-		hid_err(hdev, "unsupported KEY_STATE report\n");
-		return -EINVAL;
-	}
-
-	idev = input_allocate_device();
-	if (idev == NULL) {
-		hid_err(hdev, "failed to allocate input device\n");
-		return -ENOMEM;
-	}
-	input_set_drvdata(idev, hdev);
-	memcpy(data->keycode, def_keymap, sizeof(def_keymap));
-	idev->name = hdev->name;
-	idev->phys = hdev->phys;
-	idev->uniq = hdev->uniq;
-	idev->id.bustype = hdev->bus;
-	idev->id.vendor  = hdev->vendor;
-	idev->id.product = hdev->product;
-	idev->id.version = hdev->version;
-	idev->dev.parent = hdev->dev.parent;
-	idev->keycode     = &data->keycode;
-	idev->keycodemax  = PICOLCD_KEYS;
-	idev->keycodesize = sizeof(data->keycode[0]);
-	input_set_capability(idev, EV_MSC, MSC_SCAN);
-	set_bit(EV_REP, idev->evbit);
-	for (i = 0; i < PICOLCD_KEYS; i++)
-		input_set_capability(idev, EV_KEY, data->keycode[i]);
-	error = input_register_device(idev);
-	if (error) {
-		hid_err(hdev, "error registering the input device\n");
-		input_free_device(idev);
-		return error;
-	}
-	data->input_keys = idev;
-	return 0;
-}
-
-static void picolcd_exit_keys(struct picolcd_data *data)
-{
-	struct input_dev *idev = data->input_keys;
-
-	data->input_keys = NULL;
-	if (idev)
-		input_unregister_device(idev);
-}
-
-/* initialize CIR input device */
-static inline int picolcd_init_cir(struct picolcd_data *data, struct hid_report *report)
-{
-	/* support not implemented yet */
-	return 0;
-}
-
-static inline void picolcd_exit_cir(struct picolcd_data *data)
-{
-}
-
-static int picolcd_probe_lcd(struct hid_device *hdev, struct picolcd_data *data)
-{
-	int error;
-
-	error = picolcd_check_version(hdev);
-	if (error)
-		return error;
-
-	if (data->version[0] != 0 && data->version[1] != 3)
-		hid_info(hdev, "Device with untested firmware revision, please submit /sys/kernel/debug/hid/%s/rdesc for this device.\n",
-			 dev_name(&hdev->dev));
-
-	/* Setup keypad input device */
-	error = picolcd_init_keys(data, picolcd_in_report(REPORT_KEY_STATE, hdev));
-	if (error)
-		goto err;
-
-	/* Setup CIR input device */
-	error = picolcd_init_cir(data, picolcd_in_report(REPORT_IR_DATA, hdev));
-	if (error)
-		goto err;
-
-	/* Set up the framebuffer device */
-	error = picolcd_init_framebuffer(data);
-	if (error)
-		goto err;
-
-	/* Setup lcd class device */
-	error = picolcd_init_lcd(data, picolcd_out_report(REPORT_CONTRAST, hdev));
-	if (error)
-		goto err;
-
-	/* Setup backlight class device */
-	error = picolcd_init_backlight(data, picolcd_out_report(REPORT_BRIGHTNESS, hdev));
-	if (error)
-		goto err;
-
-	/* Setup the LED class devices */
-	error = picolcd_init_leds(data, picolcd_out_report(REPORT_LED_STATE, hdev));
-	if (error)
-		goto err;
-
-	picolcd_init_devfs(data, picolcd_out_report(REPORT_EE_READ, hdev),
-			picolcd_out_report(REPORT_EE_WRITE, hdev),
-			picolcd_out_report(REPORT_READ_MEMORY, hdev),
-			picolcd_out_report(REPORT_WRITE_MEMORY, hdev),
-			picolcd_out_report(REPORT_RESET, hdev));
-	return 0;
-err:
-	picolcd_exit_leds(data);
-	picolcd_exit_backlight(data);
-	picolcd_exit_lcd(data);
-	picolcd_exit_framebuffer(data);
-	picolcd_exit_cir(data);
-	picolcd_exit_keys(data);
-	return error;
-}
-
-static int picolcd_probe_bootloader(struct hid_device *hdev, struct picolcd_data *data)
-{
-	int error;
-
-	error = picolcd_check_version(hdev);
-	if (error)
-		return error;
-
-	if (data->version[0] != 1 && data->version[1] != 0)
-		hid_info(hdev, "Device with untested bootloader revision, please submit /sys/kernel/debug/hid/%s/rdesc for this device.\n",
-			 dev_name(&hdev->dev));
-
-	picolcd_init_devfs(data, NULL, NULL,
-			picolcd_out_report(REPORT_BL_READ_MEMORY, hdev),
-			picolcd_out_report(REPORT_BL_WRITE_MEMORY, hdev), NULL);
-	return 0;
-}
-
-static int picolcd_probe(struct hid_device *hdev,
-		     const struct hid_device_id *id)
-{
-	struct picolcd_data *data;
-	int error = -ENOMEM;
-
-	dbg_hid(PICOLCD_NAME " hardware probe...\n");
-
-	/*
-	 * Let's allocate the picolcd data structure, set some reasonable
-	 * defaults, and associate it with the device
-	 */
-	data = kzalloc(sizeof(struct picolcd_data), GFP_KERNEL);
-	if (data == NULL) {
-		hid_err(hdev, "can't allocate space for Minibox PicoLCD device data\n");
-		error = -ENOMEM;
-		goto err_no_cleanup;
-	}
-
-	spin_lock_init(&data->lock);
-	mutex_init(&data->mutex);
-	data->hdev = hdev;
-	data->opmode_delay = 5000;
-	if (hdev->product == USB_DEVICE_ID_PICOLCD_BOOTLOADER)
-		data->status |= PICOLCD_BOOTLOADER;
-	hid_set_drvdata(hdev, data);
-
-	/* Parse the device reports and start it up */
-	error = hid_parse(hdev);
-	if (error) {
-		hid_err(hdev, "device report parse failed\n");
-		goto err_cleanup_data;
-	}
-
-	error = hid_hw_start(hdev, 0);
-	if (error) {
-		hid_err(hdev, "hardware start failed\n");
-		goto err_cleanup_data;
-	}
-
-	error = hid_hw_open(hdev);
-	if (error) {
-		hid_err(hdev, "failed to open input interrupt pipe for key and IR events\n");
-		goto err_cleanup_hid_hw;
-	}
-
-	error = device_create_file(&hdev->dev, &dev_attr_operation_mode_delay);
-	if (error) {
-		hid_err(hdev, "failed to create sysfs attributes\n");
-		goto err_cleanup_hid_ll;
-	}
-
-	error = device_create_file(&hdev->dev, &dev_attr_operation_mode);
-	if (error) {
-		hid_err(hdev, "failed to create sysfs attributes\n");
-		goto err_cleanup_sysfs1;
-	}
-
-	if (data->status & PICOLCD_BOOTLOADER)
-		error = picolcd_probe_bootloader(hdev, data);
-	else
-		error = picolcd_probe_lcd(hdev, data);
-	if (error)
-		goto err_cleanup_sysfs2;
-
-	dbg_hid(PICOLCD_NAME " activated and initialized\n");
-	return 0;
-
-err_cleanup_sysfs2:
-	device_remove_file(&hdev->dev, &dev_attr_operation_mode);
-err_cleanup_sysfs1:
-	device_remove_file(&hdev->dev, &dev_attr_operation_mode_delay);
-err_cleanup_hid_ll:
-	hid_hw_close(hdev);
-err_cleanup_hid_hw:
-	hid_hw_stop(hdev);
-err_cleanup_data:
-	kfree(data);
-err_no_cleanup:
-	hid_set_drvdata(hdev, NULL);
-
-	return error;
-}
-
-static void picolcd_remove(struct hid_device *hdev)
-{
-	struct picolcd_data *data = hid_get_drvdata(hdev);
-	unsigned long flags;
-
-	dbg_hid(PICOLCD_NAME " hardware remove...\n");
-	spin_lock_irqsave(&data->lock, flags);
-	data->status |= PICOLCD_FAILED;
-	spin_unlock_irqrestore(&data->lock, flags);
-#ifdef CONFIG_HID_PICOLCD_FB
-	/* short-circuit FB as early as possible in order to
-	 * avoid long delays if we host console.
-	 */
-	if (data->fb_info)
-		data->fb_info->par = NULL;
-#endif
-
-	picolcd_exit_devfs(data);
-	device_remove_file(&hdev->dev, &dev_attr_operation_mode);
-	device_remove_file(&hdev->dev, &dev_attr_operation_mode_delay);
-	hid_hw_close(hdev);
-	hid_hw_stop(hdev);
-	hid_set_drvdata(hdev, NULL);
-
-	/* Shortcut potential pending reply that will never arrive */
-	spin_lock_irqsave(&data->lock, flags);
-	if (data->pending)
-		complete(&data->pending->ready);
-	spin_unlock_irqrestore(&data->lock, flags);
-
-	/* Cleanup LED */
-	picolcd_exit_leds(data);
-	/* Clean up the framebuffer */
-	picolcd_exit_backlight(data);
-	picolcd_exit_lcd(data);
-	picolcd_exit_framebuffer(data);
-	/* Cleanup input */
-	picolcd_exit_cir(data);
-	picolcd_exit_keys(data);
-
-	mutex_destroy(&data->mutex);
-	/* Finally, clean up the picolcd data itself */
-	kfree(data);
-}
-
-static const struct hid_device_id picolcd_devices[] = {
-	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD) },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD_BOOTLOADER) },
-	{ }
-};
-MODULE_DEVICE_TABLE(hid, picolcd_devices);
-
-static struct hid_driver picolcd_driver = {
-	.name =          "hid-picolcd",
-	.id_table =      picolcd_devices,
-	.probe =         picolcd_probe,
-	.remove =        picolcd_remove,
-	.raw_event =     picolcd_raw_event,
-#ifdef CONFIG_PM
-	.suspend =       picolcd_suspend,
-	.resume =        picolcd_resume,
-	.reset_resume =  picolcd_reset_resume,
-#endif
-};
-
-static int __init picolcd_init(void)
-{
-	return hid_register_driver(&picolcd_driver);
-}
-
-static void __exit picolcd_exit(void)
-{
-	hid_unregister_driver(&picolcd_driver);
-#ifdef CONFIG_HID_PICOLCD_FB
-	flush_work_sync(&picolcd_fb_cleanup);
-	WARN_ON(fb_pending);
-#endif
-}
-
-module_init(picolcd_init);
-module_exit(picolcd_exit);
-MODULE_DESCRIPTION("Minibox graphics PicoLCD Driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/hid/hid-picolcd.h b/drivers/hid/hid-picolcd.h
new file mode 100644
index 0000000..020cef6
--- /dev/null
+++ b/drivers/hid/hid-picolcd.h
@@ -0,0 +1,309 @@
+/***************************************************************************
+ *   Copyright (C) 2010-2012 by Bruno Prémont <bonbons@linux-vserver.org>  *
+ *                                                                         *
+ *   Based on Logitech G13 driver (v0.4)                                   *
+ *     Copyright (C) 2009 by Rick L. Vinyard, Jr. <rvinyard@cs.nmsu.edu>   *
+ *                                                                         *
+ *   This program is free software: you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation, version 2 of the License.               *
+ *                                                                         *
+ *   This driver is distributed in the hope that it will be useful, but    *
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of            *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      *
+ *   General Public License for more details.                              *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this software. If not see <http://www.gnu.org/licenses/>.  *
+ ***************************************************************************/
+
+#define PICOLCD_NAME "PicoLCD (graphic)"
+
+/* Report numbers */
+#define REPORT_ERROR_CODE      0x10 /* LCD: IN[16]  */
+#define   ERR_SUCCESS            0x00
+#define   ERR_PARAMETER_MISSING  0x01
+#define   ERR_DATA_MISSING       0x02
+#define   ERR_BLOCK_READ_ONLY    0x03
+#define   ERR_BLOCK_NOT_ERASABLE 0x04
+#define   ERR_BLOCK_TOO_BIG      0x05
+#define   ERR_SECTION_OVERFLOW   0x06
+#define   ERR_INVALID_CMD_LEN    0x07
+#define   ERR_INVALID_DATA_LEN   0x08
+#define REPORT_KEY_STATE       0x11 /* LCD: IN[2]   */
+#define REPORT_IR_DATA         0x21 /* LCD: IN[63]  */
+#define REPORT_EE_DATA         0x32 /* LCD: IN[63]  */
+#define REPORT_MEMORY          0x41 /* LCD: IN[63]  */
+#define REPORT_LED_STATE       0x81 /* LCD: OUT[1]  */
+#define REPORT_BRIGHTNESS      0x91 /* LCD: OUT[1]  */
+#define REPORT_CONTRAST        0x92 /* LCD: OUT[1]  */
+#define REPORT_RESET           0x93 /* LCD: OUT[2]  */
+#define REPORT_LCD_CMD         0x94 /* LCD: OUT[63] */
+#define REPORT_LCD_DATA        0x95 /* LCD: OUT[63] */
+#define REPORT_LCD_CMD_DATA    0x96 /* LCD: OUT[63] */
+#define	REPORT_EE_READ         0xa3 /* LCD: OUT[63] */
+#define REPORT_EE_WRITE        0xa4 /* LCD: OUT[63] */
+#define REPORT_ERASE_MEMORY    0xb2 /* LCD: OUT[2]  */
+#define REPORT_READ_MEMORY     0xb3 /* LCD: OUT[3]  */
+#define REPORT_WRITE_MEMORY    0xb4 /* LCD: OUT[63] */
+#define REPORT_SPLASH_RESTART  0xc1 /* LCD: OUT[1]  */
+#define REPORT_EXIT_KEYBOARD   0xef /* LCD: OUT[2]  */
+#define REPORT_VERSION         0xf1 /* LCD: IN[2],OUT[1]    Bootloader: IN[2],OUT[1]   */
+#define REPORT_BL_ERASE_MEMORY 0xf2 /*                      Bootloader: IN[36],OUT[4]  */
+#define REPORT_BL_READ_MEMORY  0xf3 /*                      Bootloader: IN[36],OUT[4]  */
+#define REPORT_BL_WRITE_MEMORY 0xf4 /*                      Bootloader: IN[36],OUT[36] */
+#define REPORT_DEVID           0xf5 /* LCD: IN[5], OUT[1]   Bootloader: IN[5],OUT[1]   */
+#define REPORT_SPLASH_SIZE     0xf6 /* LCD: IN[4], OUT[1]   */
+#define REPORT_HOOK_VERSION    0xf7 /* LCD: IN[2], OUT[1]   */
+#define REPORT_EXIT_FLASHER    0xff /*                      Bootloader: OUT[2]         */
+
+/* Description of in-progress IO operation, used for operations
+ * that trigger response from device */
+struct picolcd_pending {
+	struct hid_report *out_report;
+	struct hid_report *in_report;
+	struct completion ready;
+	int raw_size;
+	u8 raw_data[64];
+};
+
+
+#define PICOLCD_KEYS 17
+
+/* Per device data structure */
+struct picolcd_data {
+	struct hid_device *hdev;
+#ifdef CONFIG_DEBUG_FS
+	struct dentry *debug_reset;
+	struct dentry *debug_eeprom;
+	struct dentry *debug_flash;
+	struct mutex mutex_flash;
+	int addr_sz;
+#endif
+	u8 version[2];
+	unsigned short opmode_delay;
+	/* input stuff */
+	u8 pressed_keys[2];
+	struct input_dev *input_keys;
+#ifdef CONFIG_HID_PICOLCD_CIR
+	struct rc_dev *rc_dev;
+#endif
+	unsigned short keycode[PICOLCD_KEYS];
+
+#ifdef CONFIG_HID_PICOLCD_FB
+	/* Framebuffer stuff */
+	struct fb_info *fb_info;
+#endif /* CONFIG_HID_PICOLCD_FB */
+#ifdef CONFIG_HID_PICOLCD_LCD
+	struct lcd_device *lcd;
+	u8 lcd_contrast;
+#endif /* CONFIG_HID_PICOLCD_LCD */
+#ifdef CONFIG_HID_PICOLCD_BACKLIGHT
+	struct backlight_device *backlight;
+	u8 lcd_brightness;
+	u8 lcd_power;
+#endif /* CONFIG_HID_PICOLCD_BACKLIGHT */
+#ifdef CONFIG_HID_PICOLCD_LEDS
+	/* LED stuff */
+	u8 led_state;
+	struct led_classdev *led[8];
+#endif /* CONFIG_HID_PICOLCD_LEDS */
+
+	/* Housekeeping stuff */
+	spinlock_t lock;
+	struct mutex mutex;
+	struct picolcd_pending *pending;
+	int status;
+#define PICOLCD_BOOTLOADER 1
+#define PICOLCD_FAILED 2
+#define PICOLCD_CIR_SHUN 4
+};
+
+#ifdef CONFIG_HID_PICOLCD_FB
+struct picolcd_fb_data {
+	/* Framebuffer stuff */
+	spinlock_t lock;
+	struct picolcd_data *picolcd;
+	u8 update_rate;
+	u8 bpp;
+	u8 force;
+	u8 ready;
+	u8 *vbitmap;		/* local copy of what was sent to PicoLCD */
+	u8 *bitmap;		/* framebuffer */
+};
+#endif /* CONFIG_HID_PICOLCD_FB */
+
+/* Find a given report */
+#define picolcd_in_report(id, dev) picolcd_report(id, dev, HID_INPUT_REPORT)
+#define picolcd_out_report(id, dev) picolcd_report(id, dev, HID_OUTPUT_REPORT)
+
+struct hid_report *picolcd_report(int id, struct hid_device *hdev, int dir);
+
+#ifdef CONFIG_DEBUG_FS
+void picolcd_debug_out_report(struct picolcd_data *data,
+		struct hid_device *hdev, struct hid_report *report);
+#define usbhid_submit_report(a, b, c) \
+	do { \
+		picolcd_debug_out_report(hid_get_drvdata(a), a, b); \
+		usbhid_submit_report(a, b, c); \
+	} while (0)
+
+void picolcd_debug_raw_event(struct picolcd_data *data,
+		struct hid_device *hdev, struct hid_report *report,
+		u8 *raw_data, int size);
+
+void picolcd_init_devfs(struct picolcd_data *data,
+		struct hid_report *eeprom_r, struct hid_report *eeprom_w,
+		struct hid_report *flash_r, struct hid_report *flash_w,
+		struct hid_report *reset);
+
+void picolcd_exit_devfs(struct picolcd_data *data);
+#else
+static inline void picolcd_debug_out_report(struct picolcd_data *data,
+		struct hid_device *hdev, struct hid_report *report)
+{
+}
+static inline void picolcd_debug_raw_event(struct picolcd_data *data,
+		struct hid_device *hdev, struct hid_report *report,
+		u8 *raw_data, int size)
+{
+}
+static inline void picolcd_init_devfs(struct picolcd_data *data,
+		struct hid_report *eeprom_r, struct hid_report *eeprom_w,
+		struct hid_report *flash_r, struct hid_report *flash_w,
+		struct hid_report *reset)
+{
+}
+static inline void picolcd_exit_devfs(struct picolcd_data *data)
+{
+}
+#endif /* CONFIG_DEBUG_FS */
+
+
+#ifdef CONFIG_HID_PICOLCD_FB
+int picolcd_fb_reset(struct picolcd_data *data, int clear);
+
+int picolcd_init_framebuffer(struct picolcd_data *data);
+
+void picolcd_exit_framebuffer(struct picolcd_data *data);
+
+void picolcd_fb_refresh(struct picolcd_data *data);
+#define picolcd_fbinfo(d) ((d)->fb_info)
+#else
+static inline int picolcd_fb_reset(struct picolcd_data *data, int clear)
+{
+	return 0;
+}
+static inline int picolcd_init_framebuffer(struct picolcd_data *data)
+{
+	return 0;
+}
+static inline void picolcd_exit_framebuffer(struct picolcd_data *data)
+{
+}
+static inline void picolcd_fb_refresh(struct picolcd_data *data)
+{
+}
+#define picolcd_fbinfo(d) NULL
+#endif /* CONFIG_HID_PICOLCD_FB */
+
+
+#ifdef CONFIG_HID_PICOLCD_BACKLIGHT
+int picolcd_init_backlight(struct picolcd_data *data,
+		struct hid_report *report);
+
+void picolcd_exit_backlight(struct picolcd_data *data);
+
+int picolcd_resume_backlight(struct picolcd_data *data);
+
+void picolcd_suspend_backlight(struct picolcd_data *data);
+#else
+static inline int picolcd_init_backlight(struct picolcd_data *data,
+		struct hid_report *report)
+{
+	return 0;
+}
+static inline void picolcd_exit_backlight(struct picolcd_data *data)
+{
+}
+static inline int picolcd_resume_backlight(struct picolcd_data *data)
+{
+	return 0;
+}
+static inline void picolcd_suspend_backlight(struct picolcd_data *data)
+{
+}
+
+#endif /* CONFIG_HID_PICOLCD_BACKLIGHT */
+
+
+#ifdef CONFIG_HID_PICOLCD_LCD
+int picolcd_init_lcd(struct picolcd_data *data,
+		struct hid_report *report);
+
+void picolcd_exit_lcd(struct picolcd_data *data);
+
+int picolcd_resume_lcd(struct picolcd_data *data);
+#else
+static inline int picolcd_init_lcd(struct picolcd_data *data,
+		struct hid_report *report)
+{
+	return 0;
+}
+static inline void picolcd_exit_lcd(struct picolcd_data *data)
+{
+}
+static inline int picolcd_resume_lcd(struct picolcd_data *data)
+{
+	return 0;
+}
+#endif /* CONFIG_HID_PICOLCD_LCD */
+
+
+#ifdef CONFIG_HID_PICOLCD_LEDS
+int picolcd_init_leds(struct picolcd_data *data,
+		struct hid_report *report);
+
+void picolcd_exit_leds(struct picolcd_data *data);
+
+void picolcd_leds_set(struct picolcd_data *data);
+#else
+static inline int picolcd_init_leds(struct picolcd_data *data,
+		struct hid_report *report)
+{
+	return 0;
+}
+static inline void picolcd_exit_leds(struct picolcd_data *data)
+{
+}
+static inline void picolcd_leds_set(struct picolcd_data *data)
+{
+}
+#endif /* CONFIG_HID_PICOLCD_LEDS */
+
+
+#ifdef CONFIG_HID_PICOLCD_CIR
+int picolcd_raw_cir(struct picolcd_data *data,
+		struct hid_report *report, u8 *raw_data, int size);
+
+int picolcd_init_cir(struct picolcd_data *data, struct hid_report *report);
+
+void picolcd_exit_cir(struct picolcd_data *data);
+#else
+static inline int picolcd_raw_cir(struct picolcd_data *data,
+		struct hid_report *report, u8 *raw_data, int size)
+{
+	return 1;
+}
+static inline int picolcd_init_cir(struct picolcd_data *data, struct hid_report *report)
+{
+	return 0;
+}
+static inline void picolcd_exit_cir(struct picolcd_data *data)
+{
+}
+#endif /* CONFIG_HID_PICOLCD_LIRC */
+
+int picolcd_reset(struct hid_device *hdev);
+struct picolcd_pending *picolcd_send_and_wait(struct hid_device *hdev,
+			int report_id, const u8 *raw_data, int size);
diff --git a/drivers/hid/hid-picolcd_backlight.c b/drivers/hid/hid-picolcd_backlight.c
new file mode 100644
index 0000000..b91f309
--- /dev/null
+++ b/drivers/hid/hid-picolcd_backlight.c
@@ -0,0 +1,122 @@
+/***************************************************************************
+ *   Copyright (C) 2010-2012 by Bruno Prémont <bonbons@linux-vserver.org>  *
+ *                                                                         *
+ *   Based on Logitech G13 driver (v0.4)                                   *
+ *     Copyright (C) 2009 by Rick L. Vinyard, Jr. <rvinyard@cs.nmsu.edu>   *
+ *                                                                         *
+ *   This program is free software: you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation, version 2 of the License.               *
+ *                                                                         *
+ *   This driver is distributed in the hope that it will be useful, but    *
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of            *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      *
+ *   General Public License for more details.                              *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this software. If not see <http://www.gnu.org/licenses/>.  *
+ ***************************************************************************/
+
+#include <linux/hid.h>
+#include "usbhid/usbhid.h"
+#include <linux/usb.h>
+
+#include <linux/fb.h>
+#include <linux/backlight.h>
+
+#include "hid-picolcd.h"
+
+static int picolcd_get_brightness(struct backlight_device *bdev)
+{
+	struct picolcd_data *data = bl_get_data(bdev);
+	return data->lcd_brightness;
+}
+
+static int picolcd_set_brightness(struct backlight_device *bdev)
+{
+	struct picolcd_data *data = bl_get_data(bdev);
+	struct hid_report *report = picolcd_out_report(REPORT_BRIGHTNESS, data->hdev);
+	unsigned long flags;
+
+	if (!report || report->maxfield != 1 || report->field[0]->report_count != 1)
+		return -ENODEV;
+
+	data->lcd_brightness = bdev->props.brightness & 0x0ff;
+	data->lcd_power      = bdev->props.power;
+	spin_lock_irqsave(&data->lock, flags);
+	hid_set_field(report->field[0], 0, data->lcd_power == FB_BLANK_UNBLANK ? data->lcd_brightness : 0);
+	if (!(data->status & PICOLCD_FAILED))
+		usbhid_submit_report(data->hdev, report, USB_DIR_OUT);
+	spin_unlock_irqrestore(&data->lock, flags);
+	return 0;
+}
+
+static int picolcd_check_bl_fb(struct backlight_device *bdev, struct fb_info *fb)
+{
+	return fb && fb == picolcd_fbinfo((struct picolcd_data *)bl_get_data(bdev));
+}
+
+static const struct backlight_ops picolcd_blops = {
+	.update_status  = picolcd_set_brightness,
+	.get_brightness = picolcd_get_brightness,
+	.check_fb       = picolcd_check_bl_fb,
+};
+
+int picolcd_init_backlight(struct picolcd_data *data, struct hid_report *report)
+{
+	struct device *dev = &data->hdev->dev;
+	struct backlight_device *bdev;
+	struct backlight_properties props;
+	if (!report)
+		return -ENODEV;
+	if (report->maxfield != 1 || report->field[0]->report_count != 1 ||
+			report->field[0]->report_size != 8) {
+		dev_err(dev, "unsupported BRIGHTNESS report");
+		return -EINVAL;
+	}
+
+	memset(&props, 0, sizeof(props));
+	props.type = BACKLIGHT_RAW;
+	props.max_brightness = 0xff;
+	bdev = backlight_device_register(dev_name(dev), dev, data,
+			&picolcd_blops, &props);
+	if (IS_ERR(bdev)) {
+		dev_err(dev, "failed to register backlight\n");
+		return PTR_ERR(bdev);
+	}
+	bdev->props.brightness     = 0xff;
+	data->lcd_brightness       = 0xff;
+	data->backlight            = bdev;
+	picolcd_set_brightness(bdev);
+	return 0;
+}
+
+void picolcd_exit_backlight(struct picolcd_data *data)
+{
+	struct backlight_device *bdev = data->backlight;
+
+	data->backlight = NULL;
+	if (bdev)
+		backlight_device_unregister(bdev);
+}
+
+int picolcd_resume_backlight(struct picolcd_data *data)
+{
+	if (!data->backlight)
+		return 0;
+	return picolcd_set_brightness(data->backlight);
+}
+
+#ifdef CONFIG_PM
+void picolcd_suspend_backlight(struct picolcd_data *data)
+{
+	int bl_power = data->lcd_power;
+	if (!data->backlight)
+		return;
+
+	data->backlight->props.power = FB_BLANK_POWERDOWN;
+	picolcd_set_brightness(data->backlight);
+	data->lcd_power = data->backlight->props.power = bl_power;
+}
+#endif /* CONFIG_PM */
+
diff --git a/drivers/hid/hid-picolcd_cir.c b/drivers/hid/hid-picolcd_cir.c
new file mode 100644
index 0000000..13ca919
--- /dev/null
+++ b/drivers/hid/hid-picolcd_cir.c
@@ -0,0 +1,152 @@
+/***************************************************************************
+ *   Copyright (C) 2010-2012 by Bruno Prémont <bonbons@linux-vserver.org>  *
+ *                                                                         *
+ *   Based on Logitech G13 driver (v0.4)                                   *
+ *     Copyright (C) 2009 by Rick L. Vinyard, Jr. <rvinyard@cs.nmsu.edu>   *
+ *                                                                         *
+ *   This program is free software: you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation, version 2 of the License.               *
+ *                                                                         *
+ *   This driver is distributed in the hope that it will be useful, but    *
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of            *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      *
+ *   General Public License for more details.                              *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this software. If not see <http://www.gnu.org/licenses/>.  *
+ ***************************************************************************/
+
+#include <linux/hid.h>
+#include <linux/hid-debug.h>
+#include <linux/input.h>
+#include "hid-ids.h"
+#include "usbhid/usbhid.h"
+#include <linux/usb.h>
+
+#include <linux/fb.h>
+#include <linux/vmalloc.h>
+#include <linux/backlight.h>
+#include <linux/lcd.h>
+
+#include <linux/leds.h>
+
+#include <linux/seq_file.h>
+#include <linux/debugfs.h>
+
+#include <linux/completion.h>
+#include <linux/uaccess.h>
+#include <linux/module.h>
+#include <media/rc-core.h>
+
+#include "hid-picolcd.h"
+
+
+int picolcd_raw_cir(struct picolcd_data *data,
+		struct hid_report *report, u8 *raw_data, int size)
+{
+	unsigned long flags;
+	int i, w, sz;
+	DEFINE_IR_RAW_EVENT(rawir);
+
+	/* ignore if rc_dev is NULL or status is shunned */
+	spin_lock_irqsave(&data->lock, flags);
+	if (!data->rc_dev || (data->status & PICOLCD_CIR_SHUN)) {
+		spin_unlock_irqrestore(&data->lock, flags);
+		return 1;
+	}
+	spin_unlock_irqrestore(&data->lock, flags);
+
+	/* PicoLCD USB packets contain 16-bit intervals in network order,
+	 * with value negated for pulse. Intervals are in microseconds.
+	 *
+	 * Note: some userspace LIRC code for PicoLCD says negated values
+	 * for space - is it a matter of IR chip? (pulse for my TSOP2236)
+	 *
+	 * In addition, the first interval seems to be around 15000 + base
+	 * interval for non-first report of IR data - thus the quirk below
+	 * to get RC_CODE to understand Sony and JVC remotes I have at hand
+	 */
+	sz = size > 0 ? min((int)raw_data[0], size-1) : 0;
+	for (i = 0; i+1 < sz; i += 2) {
+		init_ir_raw_event(&rawir);
+		w = (raw_data[i] << 8) | (raw_data[i+1]);
+		rawir.pulse = !!(w & 0x8000);
+		rawir.duration = US_TO_NS(rawir.pulse ? (65536 - w) : w);
+		/* Quirk!! - see above */
+		if (i == 0 && rawir.duration > 15000000)
+			rawir.duration -= 15000000;
+		ir_raw_event_store(data->rc_dev, &rawir);
+	}
+	ir_raw_event_handle(data->rc_dev);
+
+	return 1;
+}
+
+static int picolcd_cir_open(struct rc_dev *dev)
+{
+	struct picolcd_data *data = dev->priv;
+	unsigned long flags;
+
+	spin_lock_irqsave(&data->lock, flags);
+	data->status &= ~PICOLCD_CIR_SHUN;
+	spin_unlock_irqrestore(&data->lock, flags);
+	return 0;
+}
+
+static void picolcd_cir_close(struct rc_dev *dev)
+{
+	struct picolcd_data *data = dev->priv;
+	unsigned long flags;
+
+	spin_lock_irqsave(&data->lock, flags);
+	data->status |= PICOLCD_CIR_SHUN;
+	spin_unlock_irqrestore(&data->lock, flags);
+}
+
+/* initialize CIR input device */
+int picolcd_init_cir(struct picolcd_data *data, struct hid_report *report)
+{
+	struct rc_dev *rdev;
+	int ret = 0;
+
+	rdev = rc_allocate_device();
+	if (!rdev)
+		return -ENOMEM;
+
+	rdev->priv             = data;
+	rdev->driver_type      = RC_DRIVER_IR_RAW;
+	rdev->allowed_protos   = RC_TYPE_ALL;
+	rdev->open             = picolcd_cir_open;
+	rdev->close            = picolcd_cir_close;
+	rdev->input_name       = data->hdev->name;
+	rdev->input_phys       = data->hdev->phys;
+	rdev->input_id.bustype = data->hdev->bus;
+	rdev->input_id.vendor  = data->hdev->vendor;
+	rdev->input_id.product = data->hdev->product;
+	rdev->input_id.version = data->hdev->version;
+	rdev->dev.parent       = &data->hdev->dev;
+	rdev->driver_name      = PICOLCD_NAME;
+	rdev->map_name         = RC_MAP_RC6_MCE;
+	rdev->timeout          = MS_TO_NS(100);
+	rdev->rx_resolution    = US_TO_NS(1);
+
+	ret = rc_register_device(rdev);
+	if (ret)
+		goto err;
+	data->rc_dev = rdev;
+	return 0;
+
+err:
+	rc_free_device(rdev);
+	return ret;
+}
+
+void picolcd_exit_cir(struct picolcd_data *data)
+{
+	struct rc_dev *rdev = data->rc_dev;
+
+	data->rc_dev = NULL;
+	rc_unregister_device(rdev);
+}
+
diff --git a/drivers/hid/hid-picolcd_core.c b/drivers/hid/hid-picolcd_core.c
new file mode 100644
index 0000000..86df26e
--- /dev/null
+++ b/drivers/hid/hid-picolcd_core.c
@@ -0,0 +1,689 @@
+/***************************************************************************
+ *   Copyright (C) 2010-2012 by Bruno Prémont <bonbons@linux-vserver.org>  *
+ *                                                                         *
+ *   Based on Logitech G13 driver (v0.4)                                   *
+ *     Copyright (C) 2009 by Rick L. Vinyard, Jr. <rvinyard@cs.nmsu.edu>   *
+ *                                                                         *
+ *   This program is free software: you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation, version 2 of the License.               *
+ *                                                                         *
+ *   This driver is distributed in the hope that it will be useful, but    *
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of            *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      *
+ *   General Public License for more details.                              *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this software. If not see <http://www.gnu.org/licenses/>.  *
+ ***************************************************************************/
+
+#include <linux/hid.h>
+#include <linux/hid-debug.h>
+#include <linux/input.h>
+#include "hid-ids.h"
+#include "usbhid/usbhid.h"
+#include <linux/usb.h>
+
+#include <linux/fb.h>
+#include <linux/vmalloc.h>
+
+#include <linux/completion.h>
+#include <linux/uaccess.h>
+#include <linux/module.h>
+
+#include "hid-picolcd.h"
+
+
+/* Input device
+ *
+ * The PicoLCD has an IR receiver header, a built-in keypad with 5 keys
+ * and header for 4x4 key matrix. The built-in keys are part of the matrix.
+ */
+static const unsigned short def_keymap[PICOLCD_KEYS] = {
+	KEY_RESERVED,	/* none */
+	KEY_BACK,	/* col 4 + row 1 */
+	KEY_HOMEPAGE,	/* col 3 + row 1 */
+	KEY_RESERVED,	/* col 2 + row 1 */
+	KEY_RESERVED,	/* col 1 + row 1 */
+	KEY_SCROLLUP,	/* col 4 + row 2 */
+	KEY_OK,		/* col 3 + row 2 */
+	KEY_SCROLLDOWN,	/* col 2 + row 2 */
+	KEY_RESERVED,	/* col 1 + row 2 */
+	KEY_RESERVED,	/* col 4 + row 3 */
+	KEY_RESERVED,	/* col 3 + row 3 */
+	KEY_RESERVED,	/* col 2 + row 3 */
+	KEY_RESERVED,	/* col 1 + row 3 */
+	KEY_RESERVED,	/* col 4 + row 4 */
+	KEY_RESERVED,	/* col 3 + row 4 */
+	KEY_RESERVED,	/* col 2 + row 4 */
+	KEY_RESERVED,	/* col 1 + row 4 */
+};
+
+
+/* Find a given report */
+struct hid_report *picolcd_report(int id, struct hid_device *hdev, int dir)
+{
+	struct list_head *feature_report_list = &hdev->report_enum[dir].report_list;
+	struct hid_report *report = NULL;
+
+	list_for_each_entry(report, feature_report_list, list) {
+		if (report->id == id)
+			return report;
+	}
+	hid_warn(hdev, "No report with id 0x%x found\n", id);
+	return NULL;
+}
+
+/* Submit a report and wait for a reply from device - if device fades away
+ * or does not respond in time, return NULL */
+struct picolcd_pending *picolcd_send_and_wait(struct hid_device *hdev,
+		int report_id, const u8 *raw_data, int size)
+{
+	struct picolcd_data *data = hid_get_drvdata(hdev);
+	struct picolcd_pending *work;
+	struct hid_report *report = picolcd_out_report(report_id, hdev);
+	unsigned long flags;
+	int i, j, k;
+
+	if (!report || !data)
+		return NULL;
+	if (data->status & PICOLCD_FAILED)
+		return NULL;
+	work = kzalloc(sizeof(*work), GFP_KERNEL);
+	if (!work)
+		return NULL;
+
+	init_completion(&work->ready);
+	work->out_report = report;
+	work->in_report  = NULL;
+	work->raw_size   = 0;
+
+	mutex_lock(&data->mutex);
+	spin_lock_irqsave(&data->lock, flags);
+	for (i = k = 0; i < report->maxfield; i++)
+		for (j = 0; j < report->field[i]->report_count; j++) {
+			hid_set_field(report->field[i], j, k < size ? raw_data[k] : 0);
+			k++;
+		}
+	if (data->status & PICOLCD_FAILED) {
+		kfree(work);
+		work = NULL;
+	} else {
+		data->pending = work;
+		usbhid_submit_report(data->hdev, report, USB_DIR_OUT);
+		spin_unlock_irqrestore(&data->lock, flags);
+		wait_for_completion_interruptible_timeout(&work->ready, HZ*2);
+		spin_lock_irqsave(&data->lock, flags);
+		data->pending = NULL;
+	}
+	spin_unlock_irqrestore(&data->lock, flags);
+	mutex_unlock(&data->mutex);
+	return work;
+}
+
+/*
+ * input class device
+ */
+static int picolcd_raw_keypad(struct picolcd_data *data,
+		struct hid_report *report, u8 *raw_data, int size)
+{
+	/*
+	 * Keypad event
+	 * First and second data bytes list currently pressed keys,
+	 * 0x00 means no key and at most 2 keys may be pressed at same time
+	 */
+	int i, j;
+
+	/* determine newly pressed keys */
+	for (i = 0; i < size; i++) {
+		unsigned int key_code;
+		if (raw_data[i] == 0)
+			continue;
+		for (j = 0; j < sizeof(data->pressed_keys); j++)
+			if (data->pressed_keys[j] == raw_data[i])
+				goto key_already_down;
+		for (j = 0; j < sizeof(data->pressed_keys); j++)
+			if (data->pressed_keys[j] == 0) {
+				data->pressed_keys[j] = raw_data[i];
+				break;
+			}
+		input_event(data->input_keys, EV_MSC, MSC_SCAN, raw_data[i]);
+		if (raw_data[i] < PICOLCD_KEYS)
+			key_code = data->keycode[raw_data[i]];
+		else
+			key_code = KEY_UNKNOWN;
+		if (key_code != KEY_UNKNOWN) {
+			dbg_hid(PICOLCD_NAME " got key press for %u:%d",
+					raw_data[i], key_code);
+			input_report_key(data->input_keys, key_code, 1);
+		}
+		input_sync(data->input_keys);
+key_already_down:
+		continue;
+	}
+
+	/* determine newly released keys */
+	for (j = 0; j < sizeof(data->pressed_keys); j++) {
+		unsigned int key_code;
+		if (data->pressed_keys[j] == 0)
+			continue;
+		for (i = 0; i < size; i++)
+			if (data->pressed_keys[j] == raw_data[i])
+				goto key_still_down;
+		input_event(data->input_keys, EV_MSC, MSC_SCAN, data->pressed_keys[j]);
+		if (data->pressed_keys[j] < PICOLCD_KEYS)
+			key_code = data->keycode[data->pressed_keys[j]];
+		else
+			key_code = KEY_UNKNOWN;
+		if (key_code != KEY_UNKNOWN) {
+			dbg_hid(PICOLCD_NAME " got key release for %u:%d",
+					data->pressed_keys[j], key_code);
+			input_report_key(data->input_keys, key_code, 0);
+		}
+		input_sync(data->input_keys);
+		data->pressed_keys[j] = 0;
+key_still_down:
+		continue;
+	}
+	return 1;
+}
+
+static int picolcd_check_version(struct hid_device *hdev)
+{
+	struct picolcd_data *data = hid_get_drvdata(hdev);
+	struct picolcd_pending *verinfo;
+	int ret = 0;
+
+	if (!data)
+		return -ENODEV;
+
+	verinfo = picolcd_send_and_wait(hdev, REPORT_VERSION, NULL, 0);
+	if (!verinfo) {
+		hid_err(hdev, "no version response from PicoLCD\n");
+		return -ENODEV;
+	}
+
+	if (verinfo->raw_size == 2) {
+		data->version[0] = verinfo->raw_data[1];
+		data->version[1] = verinfo->raw_data[0];
+		if (data->status & PICOLCD_BOOTLOADER) {
+			hid_info(hdev, "PicoLCD, bootloader version %d.%d\n",
+				 verinfo->raw_data[1], verinfo->raw_data[0]);
+		} else {
+			hid_info(hdev, "PicoLCD, firmware version %d.%d\n",
+				 verinfo->raw_data[1], verinfo->raw_data[0]);
+		}
+	} else {
+		hid_err(hdev, "confused, got unexpected version response from PicoLCD\n");
+		ret = -EINVAL;
+	}
+	kfree(verinfo);
+	return ret;
+}
+
+/*
+ * Reset our device and wait for answer to VERSION request
+ */
+int picolcd_reset(struct hid_device *hdev)
+{
+	struct picolcd_data *data = hid_get_drvdata(hdev);
+	struct hid_report *report = picolcd_out_report(REPORT_RESET, hdev);
+	unsigned long flags;
+	int error;
+
+	if (!data || !report || report->maxfield != 1)
+		return -ENODEV;
+
+	spin_lock_irqsave(&data->lock, flags);
+	if (hdev->product == USB_DEVICE_ID_PICOLCD_BOOTLOADER)
+		data->status |= PICOLCD_BOOTLOADER;
+
+	/* perform the reset */
+	hid_set_field(report->field[0], 0, 1);
+	if (data->status & PICOLCD_FAILED) {
+		spin_unlock_irqrestore(&data->lock, flags);
+		return -ENODEV;
+	}
+	usbhid_submit_report(hdev, report, USB_DIR_OUT);
+	spin_unlock_irqrestore(&data->lock, flags);
+
+	error = picolcd_check_version(hdev);
+	if (error)
+		return error;
+
+	picolcd_resume_lcd(data);
+	picolcd_resume_backlight(data);
+	picolcd_fb_refresh(data);
+	picolcd_leds_set(data);
+	return 0;
+}
+
+/*
+ * The "operation_mode" sysfs attribute
+ */
+static ssize_t picolcd_operation_mode_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct picolcd_data *data = dev_get_drvdata(dev);
+
+	if (data->status & PICOLCD_BOOTLOADER)
+		return snprintf(buf, PAGE_SIZE, "[bootloader] lcd\n");
+	else
+		return snprintf(buf, PAGE_SIZE, "bootloader [lcd]\n");
+}
+
+static ssize_t picolcd_operation_mode_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct picolcd_data *data = dev_get_drvdata(dev);
+	struct hid_report *report = NULL;
+	size_t cnt = count;
+	int timeout = data->opmode_delay;
+	unsigned long flags;
+
+	if (cnt >= 3 && strncmp("lcd", buf, 3) == 0) {
+		if (data->status & PICOLCD_BOOTLOADER)
+			report = picolcd_out_report(REPORT_EXIT_FLASHER, data->hdev);
+		buf += 3;
+		cnt -= 3;
+	} else if (cnt >= 10 && strncmp("bootloader", buf, 10) == 0) {
+		if (!(data->status & PICOLCD_BOOTLOADER))
+			report = picolcd_out_report(REPORT_EXIT_KEYBOARD, data->hdev);
+		buf += 10;
+		cnt -= 10;
+	}
+	if (!report)
+		return -EINVAL;
+
+	while (cnt > 0 && (buf[cnt-1] == '\n' || buf[cnt-1] == '\r'))
+		cnt--;
+	if (cnt != 0)
+		return -EINVAL;
+
+	spin_lock_irqsave(&data->lock, flags);
+	hid_set_field(report->field[0], 0, timeout & 0xff);
+	hid_set_field(report->field[0], 1, (timeout >> 8) & 0xff);
+	usbhid_submit_report(data->hdev, report, USB_DIR_OUT);
+	spin_unlock_irqrestore(&data->lock, flags);
+	return count;
+}
+
+static DEVICE_ATTR(operation_mode, 0644, picolcd_operation_mode_show,
+		picolcd_operation_mode_store);
+
+/*
+ * The "operation_mode_delay" sysfs attribute
+ */
+static ssize_t picolcd_operation_mode_delay_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct picolcd_data *data = dev_get_drvdata(dev);
+
+	return snprintf(buf, PAGE_SIZE, "%hu\n", data->opmode_delay);
+}
+
+static ssize_t picolcd_operation_mode_delay_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct picolcd_data *data = dev_get_drvdata(dev);
+	unsigned u;
+	if (sscanf(buf, "%u", &u) != 1)
+		return -EINVAL;
+	if (u > 30000)
+		return -EINVAL;
+	else
+		data->opmode_delay = u;
+	return count;
+}
+
+static DEVICE_ATTR(operation_mode_delay, 0644, picolcd_operation_mode_delay_show,
+		picolcd_operation_mode_delay_store);
+
+/*
+ * Handle raw report as sent by device
+ */
+static int picolcd_raw_event(struct hid_device *hdev,
+		struct hid_report *report, u8 *raw_data, int size)
+{
+	struct picolcd_data *data = hid_get_drvdata(hdev);
+	unsigned long flags;
+	int ret = 0;
+
+	if (!data)
+		return 1;
+
+	if (report->id == REPORT_KEY_STATE) {
+		if (data->input_keys)
+			ret = picolcd_raw_keypad(data, report, raw_data+1, size-1);
+	} else if (report->id == REPORT_IR_DATA) {
+		ret = picolcd_raw_cir(data, report, raw_data+1, size-1);
+	} else {
+		spin_lock_irqsave(&data->lock, flags);
+		/*
+		 * We let the caller of picolcd_send_and_wait() check if the
+		 * report we got is one of the expected ones or not.
+		 */
+		if (data->pending) {
+			memcpy(data->pending->raw_data, raw_data+1, size-1);
+			data->pending->raw_size  = size-1;
+			data->pending->in_report = report;
+			complete(&data->pending->ready);
+		}
+		spin_unlock_irqrestore(&data->lock, flags);
+	}
+
+	picolcd_debug_raw_event(data, hdev, report, raw_data, size);
+	return 1;
+}
+
+#ifdef CONFIG_PM
+static int picolcd_suspend(struct hid_device *hdev, pm_message_t message)
+{
+	if (PMSG_IS_AUTO(message))
+		return 0;
+
+	picolcd_suspend_backlight(hid_get_drvdata(hdev));
+	dbg_hid(PICOLCD_NAME " device ready for suspend\n");
+	return 0;
+}
+
+static int picolcd_resume(struct hid_device *hdev)
+{
+	int ret;
+	ret = picolcd_resume_backlight(hid_get_drvdata(hdev));
+	if (ret)
+		dbg_hid(PICOLCD_NAME " restoring backlight failed: %d\n", ret);
+	return 0;
+}
+
+static int picolcd_reset_resume(struct hid_device *hdev)
+{
+	int ret;
+	ret = picolcd_reset(hdev);
+	if (ret)
+		dbg_hid(PICOLCD_NAME " resetting our device failed: %d\n", ret);
+	ret = picolcd_fb_reset(hid_get_drvdata(hdev), 0);
+	if (ret)
+		dbg_hid(PICOLCD_NAME " restoring framebuffer content failed: %d\n", ret);
+	ret = picolcd_resume_lcd(hid_get_drvdata(hdev));
+	if (ret)
+		dbg_hid(PICOLCD_NAME " restoring lcd failed: %d\n", ret);
+	ret = picolcd_resume_backlight(hid_get_drvdata(hdev));
+	if (ret)
+		dbg_hid(PICOLCD_NAME " restoring backlight failed: %d\n", ret);
+	picolcd_leds_set(hid_get_drvdata(hdev));
+	return 0;
+}
+#endif
+
+/* initialize keypad input device */
+static int picolcd_init_keys(struct picolcd_data *data,
+		struct hid_report *report)
+{
+	struct hid_device *hdev = data->hdev;
+	struct input_dev *idev;
+	int error, i;
+
+	if (!report)
+		return -ENODEV;
+	if (report->maxfield != 1 || report->field[0]->report_count != 2 ||
+			report->field[0]->report_size != 8) {
+		hid_err(hdev, "unsupported KEY_STATE report\n");
+		return -EINVAL;
+	}
+
+	idev = input_allocate_device();
+	if (idev == NULL) {
+		hid_err(hdev, "failed to allocate input device\n");
+		return -ENOMEM;
+	}
+	input_set_drvdata(idev, hdev);
+	memcpy(data->keycode, def_keymap, sizeof(def_keymap));
+	idev->name = hdev->name;
+	idev->phys = hdev->phys;
+	idev->uniq = hdev->uniq;
+	idev->id.bustype = hdev->bus;
+	idev->id.vendor  = hdev->vendor;
+	idev->id.product = hdev->product;
+	idev->id.version = hdev->version;
+	idev->dev.parent = &hdev->dev;
+	idev->keycode     = &data->keycode;
+	idev->keycodemax  = PICOLCD_KEYS;
+	idev->keycodesize = sizeof(data->keycode[0]);
+	input_set_capability(idev, EV_MSC, MSC_SCAN);
+	set_bit(EV_REP, idev->evbit);
+	for (i = 0; i < PICOLCD_KEYS; i++)
+		input_set_capability(idev, EV_KEY, data->keycode[i]);
+	error = input_register_device(idev);
+	if (error) {
+		hid_err(hdev, "error registering the input device\n");
+		input_free_device(idev);
+		return error;
+	}
+	data->input_keys = idev;
+	return 0;
+}
+
+static void picolcd_exit_keys(struct picolcd_data *data)
+{
+	struct input_dev *idev = data->input_keys;
+
+	data->input_keys = NULL;
+	if (idev)
+		input_unregister_device(idev);
+}
+
+static int picolcd_probe_lcd(struct hid_device *hdev, struct picolcd_data *data)
+{
+	int error;
+
+	/* Setup keypad input device */
+	error = picolcd_init_keys(data, picolcd_in_report(REPORT_KEY_STATE, hdev));
+	if (error)
+		goto err;
+
+	/* Setup CIR input device */
+	error = picolcd_init_cir(data, picolcd_in_report(REPORT_IR_DATA, hdev));
+	if (error)
+		goto err;
+
+	/* Set up the framebuffer device */
+	error = picolcd_init_framebuffer(data);
+	if (error)
+		goto err;
+
+	/* Setup lcd class device */
+	error = picolcd_init_lcd(data, picolcd_out_report(REPORT_CONTRAST, hdev));
+	if (error)
+		goto err;
+
+	/* Setup backlight class device */
+	error = picolcd_init_backlight(data, picolcd_out_report(REPORT_BRIGHTNESS, hdev));
+	if (error)
+		goto err;
+
+	/* Setup the LED class devices */
+	error = picolcd_init_leds(data, picolcd_out_report(REPORT_LED_STATE, hdev));
+	if (error)
+		goto err;
+
+	picolcd_init_devfs(data, picolcd_out_report(REPORT_EE_READ, hdev),
+			picolcd_out_report(REPORT_EE_WRITE, hdev),
+			picolcd_out_report(REPORT_READ_MEMORY, hdev),
+			picolcd_out_report(REPORT_WRITE_MEMORY, hdev),
+			picolcd_out_report(REPORT_RESET, hdev));
+	return 0;
+err:
+	picolcd_exit_leds(data);
+	picolcd_exit_backlight(data);
+	picolcd_exit_lcd(data);
+	picolcd_exit_framebuffer(data);
+	picolcd_exit_cir(data);
+	picolcd_exit_keys(data);
+	return error;
+}
+
+static int picolcd_probe_bootloader(struct hid_device *hdev, struct picolcd_data *data)
+{
+	picolcd_init_devfs(data, NULL, NULL,
+			picolcd_out_report(REPORT_BL_READ_MEMORY, hdev),
+			picolcd_out_report(REPORT_BL_WRITE_MEMORY, hdev), NULL);
+	return 0;
+}
+
+static int picolcd_probe(struct hid_device *hdev,
+		     const struct hid_device_id *id)
+{
+	struct picolcd_data *data;
+	int error = -ENOMEM;
+
+	dbg_hid(PICOLCD_NAME " hardware probe...\n");
+
+	/*
+	 * Let's allocate the picolcd data structure, set some reasonable
+	 * defaults, and associate it with the device
+	 */
+	data = kzalloc(sizeof(struct picolcd_data), GFP_KERNEL);
+	if (data == NULL) {
+		hid_err(hdev, "can't allocate space for Minibox PicoLCD device data\n");
+		error = -ENOMEM;
+		goto err_no_cleanup;
+	}
+
+	spin_lock_init(&data->lock);
+	mutex_init(&data->mutex);
+	data->hdev = hdev;
+	data->opmode_delay = 5000;
+	if (hdev->product == USB_DEVICE_ID_PICOLCD_BOOTLOADER)
+		data->status |= PICOLCD_BOOTLOADER;
+	hid_set_drvdata(hdev, data);
+
+	/* Parse the device reports and start it up */
+	error = hid_parse(hdev);
+	if (error) {
+		hid_err(hdev, "device report parse failed\n");
+		goto err_cleanup_data;
+	}
+
+	error = hid_hw_start(hdev, 0);
+	if (error) {
+		hid_err(hdev, "hardware start failed\n");
+		goto err_cleanup_data;
+	}
+
+	error = hid_hw_open(hdev);
+	if (error) {
+		hid_err(hdev, "failed to open input interrupt pipe for key and IR events\n");
+		goto err_cleanup_hid_hw;
+	}
+
+	error = device_create_file(&hdev->dev, &dev_attr_operation_mode_delay);
+	if (error) {
+		hid_err(hdev, "failed to create sysfs attributes\n");
+		goto err_cleanup_hid_ll;
+	}
+
+	error = device_create_file(&hdev->dev, &dev_attr_operation_mode);
+	if (error) {
+		hid_err(hdev, "failed to create sysfs attributes\n");
+		goto err_cleanup_sysfs1;
+	}
+
+	if (data->status & PICOLCD_BOOTLOADER)
+		error = picolcd_probe_bootloader(hdev, data);
+	else
+		error = picolcd_probe_lcd(hdev, data);
+	if (error)
+		goto err_cleanup_sysfs2;
+
+	dbg_hid(PICOLCD_NAME " activated and initialized\n");
+	return 0;
+
+err_cleanup_sysfs2:
+	device_remove_file(&hdev->dev, &dev_attr_operation_mode);
+err_cleanup_sysfs1:
+	device_remove_file(&hdev->dev, &dev_attr_operation_mode_delay);
+err_cleanup_hid_ll:
+	hid_hw_close(hdev);
+err_cleanup_hid_hw:
+	hid_hw_stop(hdev);
+err_cleanup_data:
+	kfree(data);
+err_no_cleanup:
+	hid_set_drvdata(hdev, NULL);
+
+	return error;
+}
+
+static void picolcd_remove(struct hid_device *hdev)
+{
+	struct picolcd_data *data = hid_get_drvdata(hdev);
+	unsigned long flags;
+
+	dbg_hid(PICOLCD_NAME " hardware remove...\n");
+	spin_lock_irqsave(&data->lock, flags);
+	data->status |= PICOLCD_FAILED;
+	spin_unlock_irqrestore(&data->lock, flags);
+
+	picolcd_exit_devfs(data);
+	device_remove_file(&hdev->dev, &dev_attr_operation_mode);
+	device_remove_file(&hdev->dev, &dev_attr_operation_mode_delay);
+	hid_hw_close(hdev);
+	hid_hw_stop(hdev);
+
+	/* Shortcut potential pending reply that will never arrive */
+	spin_lock_irqsave(&data->lock, flags);
+	if (data->pending)
+		complete(&data->pending->ready);
+	spin_unlock_irqrestore(&data->lock, flags);
+
+	/* Cleanup LED */
+	picolcd_exit_leds(data);
+	/* Clean up the framebuffer */
+	picolcd_exit_backlight(data);
+	picolcd_exit_lcd(data);
+	picolcd_exit_framebuffer(data);
+	/* Cleanup input */
+	picolcd_exit_cir(data);
+	picolcd_exit_keys(data);
+
+	hid_set_drvdata(hdev, NULL);
+	mutex_destroy(&data->mutex);
+	/* Finally, clean up the picolcd data itself */
+	kfree(data);
+}
+
+static const struct hid_device_id picolcd_devices[] = {
+	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD_BOOTLOADER) },
+	{ }
+};
+MODULE_DEVICE_TABLE(hid, picolcd_devices);
+
+static struct hid_driver picolcd_driver = {
+	.name =          "hid-picolcd",
+	.id_table =      picolcd_devices,
+	.probe =         picolcd_probe,
+	.remove =        picolcd_remove,
+	.raw_event =     picolcd_raw_event,
+#ifdef CONFIG_PM
+	.suspend =       picolcd_suspend,
+	.resume =        picolcd_resume,
+	.reset_resume =  picolcd_reset_resume,
+#endif
+};
+
+static int __init picolcd_init(void)
+{
+	return hid_register_driver(&picolcd_driver);
+}
+
+static void __exit picolcd_exit(void)
+{
+	hid_unregister_driver(&picolcd_driver);
+}
+
+module_init(picolcd_init);
+module_exit(picolcd_exit);
+MODULE_DESCRIPTION("Minibox graphics PicoLCD Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/hid/hid-picolcd_debugfs.c b/drivers/hid/hid-picolcd_debugfs.c
new file mode 100644
index 0000000..6ef03be
--- /dev/null
+++ b/drivers/hid/hid-picolcd_debugfs.c
@@ -0,0 +1,899 @@
+/***************************************************************************
+ *   Copyright (C) 2010-2012 by Bruno Prémont <bonbons@linux-vserver.org>  *
+ *                                                                         *
+ *   Based on Logitech G13 driver (v0.4)                                   *
+ *     Copyright (C) 2009 by Rick L. Vinyard, Jr. <rvinyard@cs.nmsu.edu>   *
+ *                                                                         *
+ *   This program is free software: you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation, version 2 of the License.               *
+ *                                                                         *
+ *   This driver is distributed in the hope that it will be useful, but    *
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of            *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      *
+ *   General Public License for more details.                              *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this software. If not see <http://www.gnu.org/licenses/>.  *
+ ***************************************************************************/
+
+#include <linux/hid.h>
+#include <linux/hid-debug.h>
+#include "usbhid/usbhid.h"
+#include <linux/usb.h>
+
+#include <linux/fb.h>
+#include <linux/seq_file.h>
+#include <linux/debugfs.h>
+
+#include <linux/module.h>
+#include <linux/uaccess.h>
+
+#include "hid-picolcd.h"
+
+
+static int picolcd_debug_reset_show(struct seq_file *f, void *p)
+{
+	if (picolcd_fbinfo((struct picolcd_data *)f->private))
+		seq_printf(f, "all fb\n");
+	else
+		seq_printf(f, "all\n");
+	return 0;
+}
+
+static int picolcd_debug_reset_open(struct inode *inode, struct file *f)
+{
+	return single_open(f, picolcd_debug_reset_show, inode->i_private);
+}
+
+static ssize_t picolcd_debug_reset_write(struct file *f, const char __user *user_buf,
+		size_t count, loff_t *ppos)
+{
+	struct picolcd_data *data = ((struct seq_file *)f->private_data)->private;
+	char buf[32];
+	size_t cnt = min(count, sizeof(buf)-1);
+	if (copy_from_user(buf, user_buf, cnt))
+		return -EFAULT;
+
+	while (cnt > 0 && (buf[cnt-1] == ' ' || buf[cnt-1] == '\n'))
+		cnt--;
+	buf[cnt] = '\0';
+	if (strcmp(buf, "all") == 0) {
+		picolcd_reset(data->hdev);
+		picolcd_fb_reset(data, 1);
+	} else if (strcmp(buf, "fb") == 0) {
+		picolcd_fb_reset(data, 1);
+	} else {
+		return -EINVAL;
+	}
+	return count;
+}
+
+static const struct file_operations picolcd_debug_reset_fops = {
+	.owner    = THIS_MODULE,
+	.open     = picolcd_debug_reset_open,
+	.read     = seq_read,
+	.llseek   = seq_lseek,
+	.write    = picolcd_debug_reset_write,
+	.release  = single_release,
+};
+
+/*
+ * The "eeprom" file
+ */
+static ssize_t picolcd_debug_eeprom_read(struct file *f, char __user *u,
+		size_t s, loff_t *off)
+{
+	struct picolcd_data *data = f->private_data;
+	struct picolcd_pending *resp;
+	u8 raw_data[3];
+	ssize_t ret = -EIO;
+
+	if (s == 0)
+		return -EINVAL;
+	if (*off > 0x0ff)
+		return 0;
+
+	/* prepare buffer with info about what we want to read (addr & len) */
+	raw_data[0] = *off & 0xff;
+	raw_data[1] = (*off >> 8) & 0xff;
+	raw_data[2] = s < 20 ? s : 20;
+	if (*off + raw_data[2] > 0xff)
+		raw_data[2] = 0x100 - *off;
+	resp = picolcd_send_and_wait(data->hdev, REPORT_EE_READ, raw_data,
+			sizeof(raw_data));
+	if (!resp)
+		return -EIO;
+
+	if (resp->in_report && resp->in_report->id == REPORT_EE_DATA) {
+		/* successful read :) */
+		ret = resp->raw_data[2];
+		if (ret > s)
+			ret = s;
+		if (copy_to_user(u, resp->raw_data+3, ret))
+			ret = -EFAULT;
+		else
+			*off += ret;
+	} /* anything else is some kind of IO error */
+
+	kfree(resp);
+	return ret;
+}
+
+static ssize_t picolcd_debug_eeprom_write(struct file *f, const char __user *u,
+		size_t s, loff_t *off)
+{
+	struct picolcd_data *data = f->private_data;
+	struct picolcd_pending *resp;
+	ssize_t ret = -EIO;
+	u8 raw_data[23];
+
+	if (s == 0)
+		return -EINVAL;
+	if (*off > 0x0ff)
+		return -ENOSPC;
+
+	memset(raw_data, 0, sizeof(raw_data));
+	raw_data[0] = *off & 0xff;
+	raw_data[1] = (*off >> 8) & 0xff;
+	raw_data[2] = min_t(size_t, 20, s);
+	if (*off + raw_data[2] > 0xff)
+		raw_data[2] = 0x100 - *off;
+
+	if (copy_from_user(raw_data+3, u, min((u8)20, raw_data[2])))
+		return -EFAULT;
+	resp = picolcd_send_and_wait(data->hdev, REPORT_EE_WRITE, raw_data,
+			sizeof(raw_data));
+
+	if (!resp)
+		return -EIO;
+
+	if (resp->in_report && resp->in_report->id == REPORT_EE_DATA) {
+		/* check if written data matches */
+		if (memcmp(raw_data, resp->raw_data, 3+raw_data[2]) == 0) {
+			*off += raw_data[2];
+			ret = raw_data[2];
+		}
+	}
+	kfree(resp);
+	return ret;
+}
+
+/*
+ * Notes:
+ * - read/write happens in chunks of at most 20 bytes, it's up to userspace
+ *   to loop in order to get more data.
+ * - on write errors on otherwise correct write request the bytes
+ *   that should have been written are in undefined state.
+ */
+static const struct file_operations picolcd_debug_eeprom_fops = {
+	.owner    = THIS_MODULE,
+	.open     = simple_open,
+	.read     = picolcd_debug_eeprom_read,
+	.write    = picolcd_debug_eeprom_write,
+	.llseek   = generic_file_llseek,
+};
+
+/*
+ * The "flash" file
+ */
+/* record a flash address to buf (bounds check to be done by caller) */
+static int _picolcd_flash_setaddr(struct picolcd_data *data, u8 *buf, long off)
+{
+	buf[0] = off & 0xff;
+	buf[1] = (off >> 8) & 0xff;
+	if (data->addr_sz == 3)
+		buf[2] = (off >> 16) & 0xff;
+	return data->addr_sz == 2 ? 2 : 3;
+}
+
+/* read a given size of data (bounds check to be done by caller) */
+static ssize_t _picolcd_flash_read(struct picolcd_data *data, int report_id,
+		char __user *u, size_t s, loff_t *off)
+{
+	struct picolcd_pending *resp;
+	u8 raw_data[4];
+	ssize_t ret = 0;
+	int len_off, err = -EIO;
+
+	while (s > 0) {
+		err = -EIO;
+		len_off = _picolcd_flash_setaddr(data, raw_data, *off);
+		raw_data[len_off] = s > 32 ? 32 : s;
+		resp = picolcd_send_and_wait(data->hdev, report_id, raw_data, len_off+1);
+		if (!resp || !resp->in_report)
+			goto skip;
+		if (resp->in_report->id == REPORT_MEMORY ||
+			resp->in_report->id == REPORT_BL_READ_MEMORY) {
+			if (memcmp(raw_data, resp->raw_data, len_off+1) != 0)
+				goto skip;
+			if (copy_to_user(u+ret, resp->raw_data+len_off+1, raw_data[len_off])) {
+				err = -EFAULT;
+				goto skip;
+			}
+			*off += raw_data[len_off];
+			s    -= raw_data[len_off];
+			ret  += raw_data[len_off];
+			err   = 0;
+		}
+skip:
+		kfree(resp);
+		if (err)
+			return ret > 0 ? ret : err;
+	}
+	return ret;
+}
+
+static ssize_t picolcd_debug_flash_read(struct file *f, char __user *u,
+		size_t s, loff_t *off)
+{
+	struct picolcd_data *data = f->private_data;
+
+	if (s == 0)
+		return -EINVAL;
+	if (*off > 0x05fff)
+		return 0;
+	if (*off + s > 0x05fff)
+		s = 0x06000 - *off;
+
+	if (data->status & PICOLCD_BOOTLOADER)
+		return _picolcd_flash_read(data, REPORT_BL_READ_MEMORY, u, s, off);
+	else
+		return _picolcd_flash_read(data, REPORT_READ_MEMORY, u, s, off);
+}
+
+/* erase block aligned to 64bytes boundary */
+static ssize_t _picolcd_flash_erase64(struct picolcd_data *data, int report_id,
+		loff_t *off)
+{
+	struct picolcd_pending *resp;
+	u8 raw_data[3];
+	int len_off;
+	ssize_t ret = -EIO;
+
+	if (*off & 0x3f)
+		return -EINVAL;
+
+	len_off = _picolcd_flash_setaddr(data, raw_data, *off);
+	resp = picolcd_send_and_wait(data->hdev, report_id, raw_data, len_off);
+	if (!resp || !resp->in_report)
+		goto skip;
+	if (resp->in_report->id == REPORT_MEMORY ||
+		resp->in_report->id == REPORT_BL_ERASE_MEMORY) {
+		if (memcmp(raw_data, resp->raw_data, len_off) != 0)
+			goto skip;
+		ret = 0;
+	}
+skip:
+	kfree(resp);
+	return ret;
+}
+
+/* write a given size of data (bounds check to be done by caller) */
+static ssize_t _picolcd_flash_write(struct picolcd_data *data, int report_id,
+		const char __user *u, size_t s, loff_t *off)
+{
+	struct picolcd_pending *resp;
+	u8 raw_data[36];
+	ssize_t ret = 0;
+	int len_off, err = -EIO;
+
+	while (s > 0) {
+		err = -EIO;
+		len_off = _picolcd_flash_setaddr(data, raw_data, *off);
+		raw_data[len_off] = s > 32 ? 32 : s;
+		if (copy_from_user(raw_data+len_off+1, u, raw_data[len_off])) {
+			err = -EFAULT;
+			break;
+		}
+		resp = picolcd_send_and_wait(data->hdev, report_id, raw_data,
+				len_off+1+raw_data[len_off]);
+		if (!resp || !resp->in_report)
+			goto skip;
+		if (resp->in_report->id == REPORT_MEMORY ||
+			resp->in_report->id == REPORT_BL_WRITE_MEMORY) {
+			if (memcmp(raw_data, resp->raw_data, len_off+1+raw_data[len_off]) != 0)
+				goto skip;
+			*off += raw_data[len_off];
+			s    -= raw_data[len_off];
+			ret  += raw_data[len_off];
+			err   = 0;
+		}
+skip:
+		kfree(resp);
+		if (err)
+			break;
+	}
+	return ret > 0 ? ret : err;
+}
+
+static ssize_t picolcd_debug_flash_write(struct file *f, const char __user *u,
+		size_t s, loff_t *off)
+{
+	struct picolcd_data *data = f->private_data;
+	ssize_t err, ret = 0;
+	int report_erase, report_write;
+
+	if (s == 0)
+		return -EINVAL;
+	if (*off > 0x5fff)
+		return -ENOSPC;
+	if (s & 0x3f)
+		return -EINVAL;
+	if (*off & 0x3f)
+		return -EINVAL;
+
+	if (data->status & PICOLCD_BOOTLOADER) {
+		report_erase = REPORT_BL_ERASE_MEMORY;
+		report_write = REPORT_BL_WRITE_MEMORY;
+	} else {
+		report_erase = REPORT_ERASE_MEMORY;
+		report_write = REPORT_WRITE_MEMORY;
+	}
+	mutex_lock(&data->mutex_flash);
+	while (s > 0) {
+		err = _picolcd_flash_erase64(data, report_erase, off);
+		if (err)
+			break;
+		err = _picolcd_flash_write(data, report_write, u, 64, off);
+		if (err < 0)
+			break;
+		ret += err;
+		*off += err;
+		s -= err;
+		if (err != 64)
+			break;
+	}
+	mutex_unlock(&data->mutex_flash);
+	return ret > 0 ? ret : err;
+}
+
+/*
+ * Notes:
+ * - concurrent writing is prevented by mutex and all writes must be
+ *   n*64 bytes and 64-byte aligned, each write being preceded by an
+ *   ERASE which erases a 64byte block.
+ *   If less than requested was written or an error is returned for an
+ *   otherwise correct write request the next 64-byte block which should
+ *   have been written is in undefined state (mostly: original, erased,
+ *   (half-)written with write error)
+ * - reading can happen without special restriction
+ */
+static const struct file_operations picolcd_debug_flash_fops = {
+	.owner    = THIS_MODULE,
+	.open     = simple_open,
+	.read     = picolcd_debug_flash_read,
+	.write    = picolcd_debug_flash_write,
+	.llseek   = generic_file_llseek,
+};
+
+
+/*
+ * Helper code for HID report level dumping/debugging
+ */
+static const char * const error_codes[] = {
+	"success", "parameter missing", "data_missing", "block readonly",
+	"block not erasable", "block too big", "section overflow",
+	"invalid command length", "invalid data length",
+};
+
+static void dump_buff_as_hex(char *dst, size_t dst_sz, const u8 *data,
+		const size_t data_len)
+{
+	int i, j;
+	for (i = j = 0; i < data_len && j + 4 < dst_sz; i++) {
+		dst[j++] = hex_asc[(data[i] >> 4) & 0x0f];
+		dst[j++] = hex_asc[data[i] & 0x0f];
+		dst[j++] = ' ';
+	}
+	dst[j]   = '\0';
+	if (j > 0)
+		dst[j-1] = '\n';
+	if (i < data_len && j > 2)
+		dst[j-2] = dst[j-3] = '.';
+}
+
+void picolcd_debug_out_report(struct picolcd_data *data,
+		struct hid_device *hdev, struct hid_report *report)
+{
+	u8 raw_data[70];
+	int raw_size = (report->size >> 3) + 1;
+	char *buff;
+#define BUFF_SZ 256
+
+	/* Avoid unnecessary overhead if debugfs is disabled */
+	if (!hdev->debug_events)
+		return;
+
+	buff = kmalloc(BUFF_SZ, GFP_ATOMIC);
+	if (!buff)
+		return;
+
+	snprintf(buff, BUFF_SZ, "\nout report %d (size %d) =  ",
+			report->id, raw_size);
+	hid_debug_event(hdev, buff);
+	if (raw_size + 5 > sizeof(raw_data)) {
+		kfree(buff);
+		hid_debug_event(hdev, " TOO BIG\n");
+		return;
+	} else {
+		raw_data[0] = report->id;
+		hid_output_report(report, raw_data);
+		dump_buff_as_hex(buff, BUFF_SZ, raw_data, raw_size);
+		hid_debug_event(hdev, buff);
+	}
+
+	switch (report->id) {
+	case REPORT_LED_STATE:
+		/* 1 data byte with GPO state */
+		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
+			"REPORT_LED_STATE", report->id, raw_size-1);
+		hid_debug_event(hdev, buff);
+		snprintf(buff, BUFF_SZ, "\tGPO state: 0x%02x\n", raw_data[1]);
+		hid_debug_event(hdev, buff);
+		break;
+	case REPORT_BRIGHTNESS:
+		/* 1 data byte with brightness */
+		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
+			"REPORT_BRIGHTNESS", report->id, raw_size-1);
+		hid_debug_event(hdev, buff);
+		snprintf(buff, BUFF_SZ, "\tBrightness: 0x%02x\n", raw_data[1]);
+		hid_debug_event(hdev, buff);
+		break;
+	case REPORT_CONTRAST:
+		/* 1 data byte with contrast */
+		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
+			"REPORT_CONTRAST", report->id, raw_size-1);
+		hid_debug_event(hdev, buff);
+		snprintf(buff, BUFF_SZ, "\tContrast: 0x%02x\n", raw_data[1]);
+		hid_debug_event(hdev, buff);
+		break;
+	case REPORT_RESET:
+		/* 2 data bytes with reset duration in ms */
+		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
+			"REPORT_RESET", report->id, raw_size-1);
+		hid_debug_event(hdev, buff);
+		snprintf(buff, BUFF_SZ, "\tDuration: 0x%02x%02x (%dms)\n",
+				raw_data[2], raw_data[1], raw_data[2] << 8 | raw_data[1]);
+		hid_debug_event(hdev, buff);
+		break;
+	case REPORT_LCD_CMD:
+		/* 63 data bytes with LCD commands */
+		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
+			"REPORT_LCD_CMD", report->id, raw_size-1);
+		hid_debug_event(hdev, buff);
+		/* TODO: format decoding */
+		break;
+	case REPORT_LCD_DATA:
+		/* 63 data bytes with LCD data */
+		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
+			"REPORT_LCD_CMD", report->id, raw_size-1);
+		/* TODO: format decoding */
+		hid_debug_event(hdev, buff);
+		break;
+	case REPORT_LCD_CMD_DATA:
+		/* 63 data bytes with LCD commands and data */
+		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
+			"REPORT_LCD_CMD", report->id, raw_size-1);
+		/* TODO: format decoding */
+		hid_debug_event(hdev, buff);
+		break;
+	case REPORT_EE_READ:
+		/* 3 data bytes with read area description */
+		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
+			"REPORT_EE_READ", report->id, raw_size-1);
+		hid_debug_event(hdev, buff);
+		snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x\n",
+				raw_data[2], raw_data[1]);
+		hid_debug_event(hdev, buff);
+		snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[3]);
+		hid_debug_event(hdev, buff);
+		break;
+	case REPORT_EE_WRITE:
+		/* 3+1..20 data bytes with write area description */
+		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
+			"REPORT_EE_WRITE", report->id, raw_size-1);
+		hid_debug_event(hdev, buff);
+		snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x\n",
+				raw_data[2], raw_data[1]);
+		hid_debug_event(hdev, buff);
+		snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[3]);
+		hid_debug_event(hdev, buff);
+		if (raw_data[3] == 0) {
+			snprintf(buff, BUFF_SZ, "\tNo data\n");
+		} else if (raw_data[3] + 4 <= raw_size) {
+			snprintf(buff, BUFF_SZ, "\tData: ");
+			hid_debug_event(hdev, buff);
+			dump_buff_as_hex(buff, BUFF_SZ, raw_data+4, raw_data[3]);
+		} else {
+			snprintf(buff, BUFF_SZ, "\tData overflowed\n");
+		}
+		hid_debug_event(hdev, buff);
+		break;
+	case REPORT_ERASE_MEMORY:
+	case REPORT_BL_ERASE_MEMORY:
+		/* 3 data bytes with pointer inside erase block */
+		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
+			"REPORT_ERASE_MEMORY", report->id, raw_size-1);
+		hid_debug_event(hdev, buff);
+		switch (data->addr_sz) {
+		case 2:
+			snprintf(buff, BUFF_SZ, "\tAddress inside 64 byte block: 0x%02x%02x\n",
+					raw_data[2], raw_data[1]);
+			break;
+		case 3:
+			snprintf(buff, BUFF_SZ, "\tAddress inside 64 byte block: 0x%02x%02x%02x\n",
+					raw_data[3], raw_data[2], raw_data[1]);
+			break;
+		default:
+			snprintf(buff, BUFF_SZ, "\tNot supported\n");
+		}
+		hid_debug_event(hdev, buff);
+		break;
+	case REPORT_READ_MEMORY:
+	case REPORT_BL_READ_MEMORY:
+		/* 4 data bytes with read area description */
+		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
+			"REPORT_READ_MEMORY", report->id, raw_size-1);
+		hid_debug_event(hdev, buff);
+		switch (data->addr_sz) {
+		case 2:
+			snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x\n",
+					raw_data[2], raw_data[1]);
+			hid_debug_event(hdev, buff);
+			snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[3]);
+			break;
+		case 3:
+			snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x%02x\n",
+					raw_data[3], raw_data[2], raw_data[1]);
+			hid_debug_event(hdev, buff);
+			snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[4]);
+			break;
+		default:
+			snprintf(buff, BUFF_SZ, "\tNot supported\n");
+		}
+		hid_debug_event(hdev, buff);
+		break;
+	case REPORT_WRITE_MEMORY:
+	case REPORT_BL_WRITE_MEMORY:
+		/* 4+1..32 data bytes with write adrea description */
+		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
+			"REPORT_WRITE_MEMORY", report->id, raw_size-1);
+		hid_debug_event(hdev, buff);
+		switch (data->addr_sz) {
+		case 2:
+			snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x\n",
+					raw_data[2], raw_data[1]);
+			hid_debug_event(hdev, buff);
+			snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[3]);
+			hid_debug_event(hdev, buff);
+			if (raw_data[3] == 0) {
+				snprintf(buff, BUFF_SZ, "\tNo data\n");
+			} else if (raw_data[3] + 4 <= raw_size) {
+				snprintf(buff, BUFF_SZ, "\tData: ");
+				hid_debug_event(hdev, buff);
+				dump_buff_as_hex(buff, BUFF_SZ, raw_data+4, raw_data[3]);
+			} else {
+				snprintf(buff, BUFF_SZ, "\tData overflowed\n");
+			}
+			break;
+		case 3:
+			snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x%02x\n",
+					raw_data[3], raw_data[2], raw_data[1]);
+			hid_debug_event(hdev, buff);
+			snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[4]);
+			hid_debug_event(hdev, buff);
+			if (raw_data[4] == 0) {
+				snprintf(buff, BUFF_SZ, "\tNo data\n");
+			} else if (raw_data[4] + 5 <= raw_size) {
+				snprintf(buff, BUFF_SZ, "\tData: ");
+				hid_debug_event(hdev, buff);
+				dump_buff_as_hex(buff, BUFF_SZ, raw_data+5, raw_data[4]);
+			} else {
+				snprintf(buff, BUFF_SZ, "\tData overflowed\n");
+			}
+			break;
+		default:
+			snprintf(buff, BUFF_SZ, "\tNot supported\n");
+		}
+		hid_debug_event(hdev, buff);
+		break;
+	case REPORT_SPLASH_RESTART:
+		/* TODO */
+		break;
+	case REPORT_EXIT_KEYBOARD:
+		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
+			"REPORT_EXIT_KEYBOARD", report->id, raw_size-1);
+		hid_debug_event(hdev, buff);
+		snprintf(buff, BUFF_SZ, "\tRestart delay: %dms (0x%02x%02x)\n",
+				raw_data[1] | (raw_data[2] << 8),
+				raw_data[2], raw_data[1]);
+		hid_debug_event(hdev, buff);
+		break;
+	case REPORT_VERSION:
+		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
+			"REPORT_VERSION", report->id, raw_size-1);
+		hid_debug_event(hdev, buff);
+		break;
+	case REPORT_DEVID:
+		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
+			"REPORT_DEVID", report->id, raw_size-1);
+		hid_debug_event(hdev, buff);
+		break;
+	case REPORT_SPLASH_SIZE:
+		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
+			"REPORT_SPLASH_SIZE", report->id, raw_size-1);
+		hid_debug_event(hdev, buff);
+		break;
+	case REPORT_HOOK_VERSION:
+		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
+			"REPORT_HOOK_VERSION", report->id, raw_size-1);
+		hid_debug_event(hdev, buff);
+		break;
+	case REPORT_EXIT_FLASHER:
+		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
+			"REPORT_VERSION", report->id, raw_size-1);
+		hid_debug_event(hdev, buff);
+		snprintf(buff, BUFF_SZ, "\tRestart delay: %dms (0x%02x%02x)\n",
+				raw_data[1] | (raw_data[2] << 8),
+				raw_data[2], raw_data[1]);
+		hid_debug_event(hdev, buff);
+		break;
+	default:
+		snprintf(buff, BUFF_SZ, "out report %s (%d, size=%d)\n",
+			"<unknown>", report->id, raw_size-1);
+		hid_debug_event(hdev, buff);
+		break;
+	}
+	wake_up_interruptible(&hdev->debug_wait);
+	kfree(buff);
+}
+
+void picolcd_debug_raw_event(struct picolcd_data *data,
+		struct hid_device *hdev, struct hid_report *report,
+		u8 *raw_data, int size)
+{
+	char *buff;
+
+#define BUFF_SZ 256
+	/* Avoid unnecessary overhead if debugfs is disabled */
+	if (list_empty(&hdev->debug_list))
+		return;
+
+	buff = kmalloc(BUFF_SZ, GFP_ATOMIC);
+	if (!buff)
+		return;
+
+	switch (report->id) {
+	case REPORT_ERROR_CODE:
+		/* 2 data bytes with affected report and error code */
+		snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
+			"REPORT_ERROR_CODE", report->id, size-1);
+		hid_debug_event(hdev, buff);
+		if (raw_data[2] < ARRAY_SIZE(error_codes))
+			snprintf(buff, BUFF_SZ, "\tError code 0x%02x (%s) in reply to report 0x%02x\n",
+					raw_data[2], error_codes[raw_data[2]], raw_data[1]);
+		else
+			snprintf(buff, BUFF_SZ, "\tError code 0x%02x in reply to report 0x%02x\n",
+					raw_data[2], raw_data[1]);
+		hid_debug_event(hdev, buff);
+		break;
+	case REPORT_KEY_STATE:
+		/* 2 data bytes with key state */
+		snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
+			"REPORT_KEY_STATE", report->id, size-1);
+		hid_debug_event(hdev, buff);
+		if (raw_data[1] == 0)
+			snprintf(buff, BUFF_SZ, "\tNo key pressed\n");
+		else if (raw_data[2] == 0)
+			snprintf(buff, BUFF_SZ, "\tOne key pressed: 0x%02x (%d)\n",
+					raw_data[1], raw_data[1]);
+		else
+			snprintf(buff, BUFF_SZ, "\tTwo keys pressed: 0x%02x (%d), 0x%02x (%d)\n",
+					raw_data[1], raw_data[1], raw_data[2], raw_data[2]);
+		hid_debug_event(hdev, buff);
+		break;
+	case REPORT_IR_DATA:
+		/* Up to 20 byes of IR scancode data */
+		snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
+			"REPORT_IR_DATA", report->id, size-1);
+		hid_debug_event(hdev, buff);
+		if (raw_data[1] == 0) {
+			snprintf(buff, BUFF_SZ, "\tUnexpectedly 0 data length\n");
+			hid_debug_event(hdev, buff);
+		} else if (raw_data[1] + 1 <= size) {
+			snprintf(buff, BUFF_SZ, "\tData length: %d\n\tIR Data: ",
+					raw_data[1]);
+			hid_debug_event(hdev, buff);
+			dump_buff_as_hex(buff, BUFF_SZ, raw_data+2, raw_data[1]);
+			hid_debug_event(hdev, buff);
+		} else {
+			snprintf(buff, BUFF_SZ, "\tOverflowing data length: %d\n",
+					raw_data[1]-1);
+			hid_debug_event(hdev, buff);
+		}
+		break;
+	case REPORT_EE_DATA:
+		/* Data buffer in response to REPORT_EE_READ or REPORT_EE_WRITE */
+		snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
+			"REPORT_EE_DATA", report->id, size-1);
+		hid_debug_event(hdev, buff);
+		snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x\n",
+				raw_data[2], raw_data[1]);
+		hid_debug_event(hdev, buff);
+		snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[3]);
+		hid_debug_event(hdev, buff);
+		if (raw_data[3] == 0) {
+			snprintf(buff, BUFF_SZ, "\tNo data\n");
+			hid_debug_event(hdev, buff);
+		} else if (raw_data[3] + 4 <= size) {
+			snprintf(buff, BUFF_SZ, "\tData: ");
+			hid_debug_event(hdev, buff);
+			dump_buff_as_hex(buff, BUFF_SZ, raw_data+4, raw_data[3]);
+			hid_debug_event(hdev, buff);
+		} else {
+			snprintf(buff, BUFF_SZ, "\tData overflowed\n");
+			hid_debug_event(hdev, buff);
+		}
+		break;
+	case REPORT_MEMORY:
+		/* Data buffer in response to REPORT_READ_MEMORY or REPORT_WRTIE_MEMORY */
+		snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
+			"REPORT_MEMORY", report->id, size-1);
+		hid_debug_event(hdev, buff);
+		switch (data->addr_sz) {
+		case 2:
+			snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x\n",
+					raw_data[2], raw_data[1]);
+			hid_debug_event(hdev, buff);
+			snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[3]);
+			hid_debug_event(hdev, buff);
+			if (raw_data[3] == 0) {
+				snprintf(buff, BUFF_SZ, "\tNo data\n");
+			} else if (raw_data[3] + 4 <= size) {
+				snprintf(buff, BUFF_SZ, "\tData: ");
+				hid_debug_event(hdev, buff);
+				dump_buff_as_hex(buff, BUFF_SZ, raw_data+4, raw_data[3]);
+			} else {
+				snprintf(buff, BUFF_SZ, "\tData overflowed\n");
+			}
+			break;
+		case 3:
+			snprintf(buff, BUFF_SZ, "\tData address: 0x%02x%02x%02x\n",
+					raw_data[3], raw_data[2], raw_data[1]);
+			hid_debug_event(hdev, buff);
+			snprintf(buff, BUFF_SZ, "\tData length: %d\n", raw_data[4]);
+			hid_debug_event(hdev, buff);
+			if (raw_data[4] == 0) {
+				snprintf(buff, BUFF_SZ, "\tNo data\n");
+			} else if (raw_data[4] + 5 <= size) {
+				snprintf(buff, BUFF_SZ, "\tData: ");
+				hid_debug_event(hdev, buff);
+				dump_buff_as_hex(buff, BUFF_SZ, raw_data+5, raw_data[4]);
+			} else {
+				snprintf(buff, BUFF_SZ, "\tData overflowed\n");
+			}
+			break;
+		default:
+			snprintf(buff, BUFF_SZ, "\tNot supported\n");
+		}
+		hid_debug_event(hdev, buff);
+		break;
+	case REPORT_VERSION:
+		snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
+			"REPORT_VERSION", report->id, size-1);
+		hid_debug_event(hdev, buff);
+		snprintf(buff, BUFF_SZ, "\tFirmware version: %d.%d\n",
+				raw_data[2], raw_data[1]);
+		hid_debug_event(hdev, buff);
+		break;
+	case REPORT_BL_ERASE_MEMORY:
+		snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
+			"REPORT_BL_ERASE_MEMORY", report->id, size-1);
+		hid_debug_event(hdev, buff);
+		/* TODO */
+		break;
+	case REPORT_BL_READ_MEMORY:
+		snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
+			"REPORT_BL_READ_MEMORY", report->id, size-1);
+		hid_debug_event(hdev, buff);
+		/* TODO */
+		break;
+	case REPORT_BL_WRITE_MEMORY:
+		snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
+			"REPORT_BL_WRITE_MEMORY", report->id, size-1);
+		hid_debug_event(hdev, buff);
+		/* TODO */
+		break;
+	case REPORT_DEVID:
+		snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
+			"REPORT_DEVID", report->id, size-1);
+		hid_debug_event(hdev, buff);
+		snprintf(buff, BUFF_SZ, "\tSerial: 0x%02x%02x%02x%02x\n",
+				raw_data[1], raw_data[2], raw_data[3], raw_data[4]);
+		hid_debug_event(hdev, buff);
+		snprintf(buff, BUFF_SZ, "\tType: 0x%02x\n",
+				raw_data[5]);
+		hid_debug_event(hdev, buff);
+		break;
+	case REPORT_SPLASH_SIZE:
+		snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
+			"REPORT_SPLASH_SIZE", report->id, size-1);
+		hid_debug_event(hdev, buff);
+		snprintf(buff, BUFF_SZ, "\tTotal splash space: %d\n",
+				(raw_data[2] << 8) | raw_data[1]);
+		hid_debug_event(hdev, buff);
+		snprintf(buff, BUFF_SZ, "\tUsed splash space: %d\n",
+				(raw_data[4] << 8) | raw_data[3]);
+		hid_debug_event(hdev, buff);
+		break;
+	case REPORT_HOOK_VERSION:
+		snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
+			"REPORT_HOOK_VERSION", report->id, size-1);
+		hid_debug_event(hdev, buff);
+		snprintf(buff, BUFF_SZ, "\tFirmware version: %d.%d\n",
+				raw_data[1], raw_data[2]);
+		hid_debug_event(hdev, buff);
+		break;
+	default:
+		snprintf(buff, BUFF_SZ, "report %s (%d, size=%d)\n",
+			"<unknown>", report->id, size-1);
+		hid_debug_event(hdev, buff);
+		break;
+	}
+	wake_up_interruptible(&hdev->debug_wait);
+	kfree(buff);
+}
+
+void picolcd_init_devfs(struct picolcd_data *data,
+		struct hid_report *eeprom_r, struct hid_report *eeprom_w,
+		struct hid_report *flash_r, struct hid_report *flash_w,
+		struct hid_report *reset)
+{
+	struct hid_device *hdev = data->hdev;
+
+	mutex_init(&data->mutex_flash);
+
+	/* reset */
+	if (reset)
+		data->debug_reset = debugfs_create_file("reset", 0600,
+				hdev->debug_dir, data, &picolcd_debug_reset_fops);
+
+	/* eeprom */
+	if (eeprom_r || eeprom_w)
+		data->debug_eeprom = debugfs_create_file("eeprom",
+			(eeprom_w ? S_IWUSR : 0) | (eeprom_r ? S_IRUSR : 0),
+			hdev->debug_dir, data, &picolcd_debug_eeprom_fops);
+
+	/* flash */
+	if (flash_r && flash_r->maxfield == 1 && flash_r->field[0]->report_size == 8)
+		data->addr_sz = flash_r->field[0]->report_count - 1;
+	else
+		data->addr_sz = -1;
+	if (data->addr_sz == 2 || data->addr_sz == 3) {
+		data->debug_flash = debugfs_create_file("flash",
+			(flash_w ? S_IWUSR : 0) | (flash_r ? S_IRUSR : 0),
+			hdev->debug_dir, data, &picolcd_debug_flash_fops);
+	} else if (flash_r || flash_w)
+		hid_warn(hdev, "Unexpected FLASH access reports, please submit rdesc for review\n");
+}
+
+void picolcd_exit_devfs(struct picolcd_data *data)
+{
+	struct dentry *dent;
+
+	dent = data->debug_reset;
+	data->debug_reset = NULL;
+	if (dent)
+		debugfs_remove(dent);
+	dent = data->debug_eeprom;
+	data->debug_eeprom = NULL;
+	if (dent)
+		debugfs_remove(dent);
+	dent = data->debug_flash;
+	data->debug_flash = NULL;
+	if (dent)
+		debugfs_remove(dent);
+	mutex_destroy(&data->mutex_flash);
+}
+
diff --git a/drivers/hid/hid-picolcd_fb.c b/drivers/hid/hid-picolcd_fb.c
new file mode 100644
index 0000000..0008a51
--- /dev/null
+++ b/drivers/hid/hid-picolcd_fb.c
@@ -0,0 +1,615 @@
+/***************************************************************************
+ *   Copyright (C) 2010-2012 by Bruno Prémont <bonbons@linux-vserver.org>  *
+ *                                                                         *
+ *   Based on Logitech G13 driver (v0.4)                                   *
+ *     Copyright (C) 2009 by Rick L. Vinyard, Jr. <rvinyard@cs.nmsu.edu>   *
+ *                                                                         *
+ *   This program is free software: you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation, version 2 of the License.               *
+ *                                                                         *
+ *   This driver is distributed in the hope that it will be useful, but    *
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of            *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      *
+ *   General Public License for more details.                              *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this software. If not see <http://www.gnu.org/licenses/>.  *
+ ***************************************************************************/
+
+#include <linux/hid.h>
+#include <linux/vmalloc.h>
+#include "usbhid/usbhid.h"
+#include <linux/usb.h>
+
+#include <linux/fb.h>
+#include <linux/module.h>
+
+#include "hid-picolcd.h"
+
+/* Framebuffer
+ *
+ * The PicoLCD use a Topway LCD module of 256x64 pixel
+ * This display area is tiled over 4 controllers with 8 tiles
+ * each. Each tile has 8x64 pixel, each data byte representing
+ * a 1-bit wide vertical line of the tile.
+ *
+ * The display can be updated at a tile granularity.
+ *
+ *       Chip 1           Chip 2           Chip 3           Chip 4
+ * +----------------+----------------+----------------+----------------+
+ * |     Tile 1     |     Tile 1     |     Tile 1     |     Tile 1     |
+ * +----------------+----------------+----------------+----------------+
+ * |     Tile 2     |     Tile 2     |     Tile 2     |     Tile 2     |
+ * +----------------+----------------+----------------+----------------+
+ *                                  ...
+ * +----------------+----------------+----------------+----------------+
+ * |     Tile 8     |     Tile 8     |     Tile 8     |     Tile 8     |
+ * +----------------+----------------+----------------+----------------+
+ */
+#define PICOLCDFB_NAME "picolcdfb"
+#define PICOLCDFB_WIDTH (256)
+#define PICOLCDFB_HEIGHT (64)
+#define PICOLCDFB_SIZE (PICOLCDFB_WIDTH * PICOLCDFB_HEIGHT / 8)
+
+#define PICOLCDFB_UPDATE_RATE_LIMIT   10
+#define PICOLCDFB_UPDATE_RATE_DEFAULT  2
+
+/* Framebuffer visual structures */
+static const struct fb_fix_screeninfo picolcdfb_fix = {
+	.id          = PICOLCDFB_NAME,
+	.type        = FB_TYPE_PACKED_PIXELS,
+	.visual      = FB_VISUAL_MONO01,
+	.xpanstep    = 0,
+	.ypanstep    = 0,
+	.ywrapstep   = 0,
+	.line_length = PICOLCDFB_WIDTH / 8,
+	.accel       = FB_ACCEL_NONE,
+};
+
+static const struct fb_var_screeninfo picolcdfb_var = {
+	.xres           = PICOLCDFB_WIDTH,
+	.yres           = PICOLCDFB_HEIGHT,
+	.xres_virtual   = PICOLCDFB_WIDTH,
+	.yres_virtual   = PICOLCDFB_HEIGHT,
+	.width          = 103,
+	.height         = 26,
+	.bits_per_pixel = 1,
+	.grayscale      = 1,
+	.red            = {
+		.offset = 0,
+		.length = 1,
+		.msb_right = 0,
+	},
+	.green          = {
+		.offset = 0,
+		.length = 1,
+		.msb_right = 0,
+	},
+	.blue           = {
+		.offset = 0,
+		.length = 1,
+		.msb_right = 0,
+	},
+	.transp         = {
+		.offset = 0,
+		.length = 0,
+		.msb_right = 0,
+	},
+};
+
+/* Send a given tile to PicoLCD */
+static int picolcd_fb_send_tile(struct picolcd_data *data, u8 *vbitmap,
+		int chip, int tile)
+{
+	struct hid_report *report1, *report2;
+	unsigned long flags;
+	u8 *tdata;
+	int i;
+
+	report1 = picolcd_out_report(REPORT_LCD_CMD_DATA, data->hdev);
+	if (!report1 || report1->maxfield != 1)
+		return -ENODEV;
+	report2 = picolcd_out_report(REPORT_LCD_DATA, data->hdev);
+	if (!report2 || report2->maxfield != 1)
+		return -ENODEV;
+
+	spin_lock_irqsave(&data->lock, flags);
+	if ((data->status & PICOLCD_FAILED)) {
+		spin_unlock_irqrestore(&data->lock, flags);
+		return -ENODEV;
+	}
+	hid_set_field(report1->field[0],  0, chip << 2);
+	hid_set_field(report1->field[0],  1, 0x02);
+	hid_set_field(report1->field[0],  2, 0x00);
+	hid_set_field(report1->field[0],  3, 0x00);
+	hid_set_field(report1->field[0],  4, 0xb8 | tile);
+	hid_set_field(report1->field[0],  5, 0x00);
+	hid_set_field(report1->field[0],  6, 0x00);
+	hid_set_field(report1->field[0],  7, 0x40);
+	hid_set_field(report1->field[0],  8, 0x00);
+	hid_set_field(report1->field[0],  9, 0x00);
+	hid_set_field(report1->field[0], 10,   32);
+
+	hid_set_field(report2->field[0],  0, (chip << 2) | 0x01);
+	hid_set_field(report2->field[0],  1, 0x00);
+	hid_set_field(report2->field[0],  2, 0x00);
+	hid_set_field(report2->field[0],  3,   32);
+
+	tdata = vbitmap + (tile * 4 + chip) * 64;
+	for (i = 0; i < 64; i++)
+		if (i < 32)
+			hid_set_field(report1->field[0], 11 + i, tdata[i]);
+		else
+			hid_set_field(report2->field[0], 4 + i - 32, tdata[i]);
+
+	usbhid_submit_report(data->hdev, report1, USB_DIR_OUT);
+	usbhid_submit_report(data->hdev, report2, USB_DIR_OUT);
+	spin_unlock_irqrestore(&data->lock, flags);
+	return 0;
+}
+
+/* Translate a single tile*/
+static int picolcd_fb_update_tile(u8 *vbitmap, const u8 *bitmap, int bpp,
+		int chip, int tile)
+{
+	int i, b, changed = 0;
+	u8 tdata[64];
+	u8 *vdata = vbitmap + (tile * 4 + chip) * 64;
+
+	if (bpp == 1) {
+		for (b = 7; b >= 0; b--) {
+			const u8 *bdata = bitmap + tile * 256 + chip * 8 + b * 32;
+			for (i = 0; i < 64; i++) {
+				tdata[i] <<= 1;
+				tdata[i] |= (bdata[i/8] >> (i % 8)) & 0x01;
+			}
+		}
+	} else if (bpp == 8) {
+		for (b = 7; b >= 0; b--) {
+			const u8 *bdata = bitmap + (tile * 256 + chip * 8 + b * 32) * 8;
+			for (i = 0; i < 64; i++) {
+				tdata[i] <<= 1;
+				tdata[i] |= (bdata[i] & 0x80) ? 0x01 : 0x00;
+			}
+		}
+	} else {
+		/* Oops, we should never get here! */
+		WARN_ON(1);
+		return 0;
+	}
+
+	for (i = 0; i < 64; i++)
+		if (tdata[i] != vdata[i]) {
+			changed = 1;
+			vdata[i] = tdata[i];
+		}
+	return changed;
+}
+
+void picolcd_fb_refresh(struct picolcd_data *data)
+{
+	if (data->fb_info)
+		schedule_delayed_work(&data->fb_info->deferred_work, 0);
+}
+
+/* Reconfigure LCD display */
+int picolcd_fb_reset(struct picolcd_data *data, int clear)
+{
+	struct hid_report *report = picolcd_out_report(REPORT_LCD_CMD, data->hdev);
+	struct picolcd_fb_data *fbdata = data->fb_info->par;
+	int i, j;
+	unsigned long flags;
+	static const u8 mapcmd[8] = { 0x00, 0x02, 0x00, 0x64, 0x3f, 0x00, 0x64, 0xc0 };
+
+	if (!report || report->maxfield != 1)
+		return -ENODEV;
+
+	spin_lock_irqsave(&data->lock, flags);
+	for (i = 0; i < 4; i++) {
+		for (j = 0; j < report->field[0]->maxusage; j++)
+			if (j == 0)
+				hid_set_field(report->field[0], j, i << 2);
+			else if (j < sizeof(mapcmd))
+				hid_set_field(report->field[0], j, mapcmd[j]);
+			else
+				hid_set_field(report->field[0], j, 0);
+		usbhid_submit_report(data->hdev, report, USB_DIR_OUT);
+	}
+	spin_unlock_irqrestore(&data->lock, flags);
+
+	if (clear) {
+		memset(fbdata->vbitmap, 0, PICOLCDFB_SIZE);
+		memset(fbdata->bitmap, 0, PICOLCDFB_SIZE*fbdata->bpp);
+	}
+	fbdata->force = 1;
+
+	/* schedule first output of framebuffer */
+	if (fbdata->ready)
+		schedule_delayed_work(&data->fb_info->deferred_work, 0);
+	else
+		fbdata->ready = 1;
+
+	return 0;
+}
+
+/* Update fb_vbitmap from the screen_base and send changed tiles to device */
+static void picolcd_fb_update(struct fb_info *info)
+{
+	int chip, tile, n;
+	unsigned long flags;
+	struct picolcd_fb_data *fbdata = info->par;
+	struct picolcd_data *data;
+
+	mutex_lock(&info->lock);
+
+	spin_lock_irqsave(&fbdata->lock, flags);
+	if (!fbdata->ready && fbdata->picolcd)
+		picolcd_fb_reset(fbdata->picolcd, 0);
+	spin_unlock_irqrestore(&fbdata->lock, flags);
+
+	/*
+	 * Translate the framebuffer into the format needed by the PicoLCD.
+	 * See display layout above.
+	 * Do this one tile after the other and push those tiles that changed.
+	 *
+	 * Wait for our IO to complete as otherwise we might flood the queue!
+	 */
+	n = 0;
+	for (chip = 0; chip < 4; chip++)
+		for (tile = 0; tile < 8; tile++) {
+			if (!fbdata->force && !picolcd_fb_update_tile(
+					fbdata->vbitmap, fbdata->bitmap,
+					fbdata->bpp, chip, tile))
+				continue;
+			n += 2;
+			if (n >= HID_OUTPUT_FIFO_SIZE / 2) {
+				spin_lock_irqsave(&fbdata->lock, flags);
+				data = fbdata->picolcd;
+				spin_unlock_irqrestore(&fbdata->lock, flags);
+				mutex_unlock(&info->lock);
+				if (!data)
+					return;
+				usbhid_wait_io(data->hdev);
+				mutex_lock(&info->lock);
+				n = 0;
+			}
+			spin_lock_irqsave(&fbdata->lock, flags);
+			data = fbdata->picolcd;
+			spin_unlock_irqrestore(&fbdata->lock, flags);
+			if (!data || picolcd_fb_send_tile(data,
+					fbdata->vbitmap, chip, tile))
+				goto out;
+		}
+	fbdata->force = false;
+	if (n) {
+		spin_lock_irqsave(&fbdata->lock, flags);
+		data = fbdata->picolcd;
+		spin_unlock_irqrestore(&fbdata->lock, flags);
+		mutex_unlock(&info->lock);
+		if (data)
+			usbhid_wait_io(data->hdev);
+		return;
+	}
+out:
+	mutex_unlock(&info->lock);
+}
+
+/* Stub to call the system default and update the image on the picoLCD */
+static void picolcd_fb_fillrect(struct fb_info *info,
+		const struct fb_fillrect *rect)
+{
+	if (!info->par)
+		return;
+	sys_fillrect(info, rect);
+
+	schedule_delayed_work(&info->deferred_work, 0);
+}
+
+/* Stub to call the system default and update the image on the picoLCD */
+static void picolcd_fb_copyarea(struct fb_info *info,
+		const struct fb_copyarea *area)
+{
+	if (!info->par)
+		return;
+	sys_copyarea(info, area);
+
+	schedule_delayed_work(&info->deferred_work, 0);
+}
+
+/* Stub to call the system default and update the image on the picoLCD */
+static void picolcd_fb_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+	if (!info->par)
+		return;
+	sys_imageblit(info, image);
+
+	schedule_delayed_work(&info->deferred_work, 0);
+}
+
+/*
+ * 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 picolcd_fb_write(struct fb_info *info, const char __user *buf,
+		size_t count, loff_t *ppos)
+{
+	ssize_t ret;
+	if (!info->par)
+		return -ENODEV;
+	ret = fb_sys_write(info, buf, count, ppos);
+	if (ret >= 0)
+		schedule_delayed_work(&info->deferred_work, 0);
+	return ret;
+}
+
+static int picolcd_fb_blank(int blank, struct fb_info *info)
+{
+	/* We let fb notification do this for us via lcd/backlight device */
+	return 0;
+}
+
+static void picolcd_fb_destroy(struct fb_info *info)
+{
+	struct picolcd_fb_data *fbdata = info->par;
+
+	/* make sure no work is deferred */
+	fb_deferred_io_cleanup(info);
+
+	/* No thridparty should ever unregister our framebuffer! */
+	WARN_ON(fbdata->picolcd != NULL);
+
+	vfree((u8 *)info->fix.smem_start);
+	framebuffer_release(info);
+}
+
+static int picolcd_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	__u32 bpp      = var->bits_per_pixel;
+	__u32 activate = var->activate;
+
+	/* only allow 1/8 bit depth (8-bit is grayscale) */
+	*var = picolcdfb_var;
+	var->activate = activate;
+	if (bpp >= 8) {
+		var->bits_per_pixel = 8;
+		var->red.length     = 8;
+		var->green.length   = 8;
+		var->blue.length    = 8;
+	} else {
+		var->bits_per_pixel = 1;
+		var->red.length     = 1;
+		var->green.length   = 1;
+		var->blue.length    = 1;
+	}
+	return 0;
+}
+
+static int picolcd_set_par(struct fb_info *info)
+{
+	struct picolcd_fb_data *fbdata = info->par;
+	u8 *tmp_fb, *o_fb;
+	if (info->var.bits_per_pixel == fbdata->bpp)
+		return 0;
+	/* switch between 1/8 bit depths */
+	if (info->var.bits_per_pixel != 1 && info->var.bits_per_pixel != 8)
+		return -EINVAL;
+
+	o_fb   = fbdata->bitmap;
+	tmp_fb = kmalloc(PICOLCDFB_SIZE*info->var.bits_per_pixel, GFP_KERNEL);
+	if (!tmp_fb)
+		return -ENOMEM;
+
+	/* translate FB content to new bits-per-pixel */
+	if (info->var.bits_per_pixel == 1) {
+		int i, b;
+		for (i = 0; i < PICOLCDFB_SIZE; i++) {
+			u8 p = 0;
+			for (b = 0; b < 8; b++) {
+				p <<= 1;
+				p |= o_fb[i*8+b] ? 0x01 : 0x00;
+			}
+			tmp_fb[i] = p;
+		}
+		memcpy(o_fb, tmp_fb, PICOLCDFB_SIZE);
+		info->fix.visual = FB_VISUAL_MONO01;
+		info->fix.line_length = PICOLCDFB_WIDTH / 8;
+	} else {
+		int i;
+		memcpy(tmp_fb, o_fb, PICOLCDFB_SIZE);
+		for (i = 0; i < PICOLCDFB_SIZE * 8; i++)
+			o_fb[i] = tmp_fb[i/8] & (0x01 << (7 - i % 8)) ? 0xff : 0x00;
+		info->fix.visual = FB_VISUAL_DIRECTCOLOR;
+		info->fix.line_length = PICOLCDFB_WIDTH;
+	}
+
+	kfree(tmp_fb);
+	fbdata->bpp = info->var.bits_per_pixel;
+	return 0;
+}
+
+/* Note this can't be const because of struct fb_info definition */
+static struct fb_ops picolcdfb_ops = {
+	.owner        = THIS_MODULE,
+	.fb_destroy   = picolcd_fb_destroy,
+	.fb_read      = fb_sys_read,
+	.fb_write     = picolcd_fb_write,
+	.fb_blank     = picolcd_fb_blank,
+	.fb_fillrect  = picolcd_fb_fillrect,
+	.fb_copyarea  = picolcd_fb_copyarea,
+	.fb_imageblit = picolcd_fb_imageblit,
+	.fb_check_var = picolcd_fb_check_var,
+	.fb_set_par   = picolcd_set_par,
+};
+
+
+/* Callback from deferred IO workqueue */
+static void picolcd_fb_deferred_io(struct fb_info *info, struct list_head *pagelist)
+{
+	picolcd_fb_update(info);
+}
+
+static const struct fb_deferred_io picolcd_fb_defio = {
+	.delay = HZ / PICOLCDFB_UPDATE_RATE_DEFAULT,
+	.deferred_io = picolcd_fb_deferred_io,
+};
+
+
+/*
+ * The "fb_update_rate" sysfs attribute
+ */
+static ssize_t picolcd_fb_update_rate_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct picolcd_data *data = dev_get_drvdata(dev);
+	struct picolcd_fb_data *fbdata = data->fb_info->par;
+	unsigned i, fb_update_rate = fbdata->update_rate;
+	size_t ret = 0;
+
+	for (i = 1; i <= PICOLCDFB_UPDATE_RATE_LIMIT; i++)
+		if (ret >= PAGE_SIZE)
+			break;
+		else if (i == fb_update_rate)
+			ret += snprintf(buf+ret, PAGE_SIZE-ret, "[%u] ", i);
+		else
+			ret += snprintf(buf+ret, PAGE_SIZE-ret, "%u ", i);
+	if (ret > 0)
+		buf[min(ret, (size_t)PAGE_SIZE)-1] = '\n';
+	return ret;
+}
+
+static ssize_t picolcd_fb_update_rate_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct picolcd_data *data = dev_get_drvdata(dev);
+	struct picolcd_fb_data *fbdata = data->fb_info->par;
+	int i;
+	unsigned u;
+
+	if (count < 1 || count > 10)
+		return -EINVAL;
+
+	i = sscanf(buf, "%u", &u);
+	if (i != 1)
+		return -EINVAL;
+
+	if (u > PICOLCDFB_UPDATE_RATE_LIMIT)
+		return -ERANGE;
+	else if (u == 0)
+		u = PICOLCDFB_UPDATE_RATE_DEFAULT;
+
+	fbdata->update_rate = u;
+	data->fb_info->fbdefio->delay = HZ / fbdata->update_rate;
+	return count;
+}
+
+static DEVICE_ATTR(fb_update_rate, 0666, picolcd_fb_update_rate_show,
+		picolcd_fb_update_rate_store);
+
+/* initialize Framebuffer device */
+int picolcd_init_framebuffer(struct picolcd_data *data)
+{
+	struct device *dev = &data->hdev->dev;
+	struct fb_info *info = NULL;
+	struct picolcd_fb_data *fbdata = NULL;
+	int i, error = -ENOMEM;
+	u32 *palette;
+
+	/* The extra memory is:
+	 * - 256*u32 for pseudo_palette
+	 * - struct fb_deferred_io
+	 */
+	info = framebuffer_alloc(256 * sizeof(u32) +
+			sizeof(struct fb_deferred_io) +
+			sizeof(struct picolcd_fb_data) +
+			PICOLCDFB_SIZE, dev);
+	if (info == NULL) {
+		dev_err(dev, "failed to allocate a framebuffer\n");
+		goto err_nomem;
+	}
+
+	info->fbdefio = info->par;
+	*info->fbdefio = picolcd_fb_defio;
+	info->par += sizeof(struct fb_deferred_io);
+	palette = info->par;
+	info->par += 256 * sizeof(u32);
+	for (i = 0; i < 256; i++)
+		palette[i] = i > 0 && i < 16 ? 0xff : 0;
+	info->pseudo_palette = palette;
+	info->fbops = &picolcdfb_ops;
+	info->var = picolcdfb_var;
+	info->fix = picolcdfb_fix;
+	info->fix.smem_len   = PICOLCDFB_SIZE*8;
+	info->flags = FBINFO_FLAG_DEFAULT;
+
+	fbdata = info->par;
+	spin_lock_init(&fbdata->lock);
+	fbdata->picolcd = data;
+	fbdata->update_rate = PICOLCDFB_UPDATE_RATE_DEFAULT;
+	fbdata->bpp     = picolcdfb_var.bits_per_pixel;
+	fbdata->force   = 1;
+	fbdata->vbitmap = info->par + sizeof(struct picolcd_fb_data);
+	fbdata->bitmap  = vmalloc(PICOLCDFB_SIZE*8);
+	if (fbdata->bitmap == NULL) {
+		dev_err(dev, "can't get a free page for framebuffer\n");
+		goto err_nomem;
+	}
+	info->screen_base = (char __force __iomem *)fbdata->bitmap;
+	info->fix.smem_start = (unsigned long)fbdata->bitmap;
+	memset(fbdata->vbitmap, 0xff, PICOLCDFB_SIZE);
+	data->fb_info = info;
+
+	error = picolcd_fb_reset(data, 1);
+	if (error) {
+		dev_err(dev, "failed to configure display\n");
+		goto err_cleanup;
+	}
+
+	error = device_create_file(dev, &dev_attr_fb_update_rate);
+	if (error) {
+		dev_err(dev, "failed to create sysfs attributes\n");
+		goto err_cleanup;
+	}
+
+	fb_deferred_io_init(info);
+	error = register_framebuffer(info);
+	if (error) {
+		dev_err(dev, "failed to register framebuffer\n");
+		goto err_sysfs;
+	}
+	return 0;
+
+err_sysfs:
+	device_remove_file(dev, &dev_attr_fb_update_rate);
+	fb_deferred_io_cleanup(info);
+err_cleanup:
+	data->fb_info    = NULL;
+
+err_nomem:
+	if (fbdata)
+		vfree(fbdata->bitmap);
+	framebuffer_release(info);
+	return error;
+}
+
+void picolcd_exit_framebuffer(struct picolcd_data *data)
+{
+	struct fb_info *info = data->fb_info;
+	struct picolcd_fb_data *fbdata = info->par;
+	unsigned long flags;
+
+	device_remove_file(&data->hdev->dev, &dev_attr_fb_update_rate);
+
+	/* disconnect framebuffer from HID dev */
+	spin_lock_irqsave(&fbdata->lock, flags);
+	fbdata->picolcd = NULL;
+	spin_unlock_irqrestore(&fbdata->lock, flags);
+
+	/* make sure there is no running update - thus that fbdata->picolcd
+	 * once obtained under lock is guaranteed not to get free() under
+	 * the feet of the deferred work */
+	flush_delayed_work_sync(&info->deferred_work);
+
+	data->fb_info = NULL;
+	unregister_framebuffer(info);
+}
diff --git a/drivers/hid/hid-picolcd_lcd.c b/drivers/hid/hid-picolcd_lcd.c
new file mode 100644
index 0000000..2d0ddc5
--- /dev/null
+++ b/drivers/hid/hid-picolcd_lcd.c
@@ -0,0 +1,107 @@
+/***************************************************************************
+ *   Copyright (C) 2010-2012 by Bruno Prémont <bonbons@linux-vserver.org>  *
+ *                                                                         *
+ *   Based on Logitech G13 driver (v0.4)                                   *
+ *     Copyright (C) 2009 by Rick L. Vinyard, Jr. <rvinyard@cs.nmsu.edu>   *
+ *                                                                         *
+ *   This program is free software: you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation, version 2 of the License.               *
+ *                                                                         *
+ *   This driver is distributed in the hope that it will be useful, but    *
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of            *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      *
+ *   General Public License for more details.                              *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this software. If not see <http://www.gnu.org/licenses/>.  *
+ ***************************************************************************/
+
+#include <linux/hid.h>
+#include "usbhid/usbhid.h"
+#include <linux/usb.h>
+
+#include <linux/fb.h>
+#include <linux/lcd.h>
+
+#include "hid-picolcd.h"
+
+/*
+ * lcd class device
+ */
+static int picolcd_get_contrast(struct lcd_device *ldev)
+{
+	struct picolcd_data *data = lcd_get_data(ldev);
+	return data->lcd_contrast;
+}
+
+static int picolcd_set_contrast(struct lcd_device *ldev, int contrast)
+{
+	struct picolcd_data *data = lcd_get_data(ldev);
+	struct hid_report *report = picolcd_out_report(REPORT_CONTRAST, data->hdev);
+	unsigned long flags;
+
+	if (!report || report->maxfield != 1 || report->field[0]->report_count != 1)
+		return -ENODEV;
+
+	data->lcd_contrast = contrast & 0x0ff;
+	spin_lock_irqsave(&data->lock, flags);
+	hid_set_field(report->field[0], 0, data->lcd_contrast);
+	if (!(data->status & PICOLCD_FAILED))
+		usbhid_submit_report(data->hdev, report, USB_DIR_OUT);
+	spin_unlock_irqrestore(&data->lock, flags);
+	return 0;
+}
+
+static int picolcd_check_lcd_fb(struct lcd_device *ldev, struct fb_info *fb)
+{
+	return fb && fb == picolcd_fbinfo((struct picolcd_data *)lcd_get_data(ldev));
+}
+
+static struct lcd_ops picolcd_lcdops = {
+	.get_contrast   = picolcd_get_contrast,
+	.set_contrast   = picolcd_set_contrast,
+	.check_fb       = picolcd_check_lcd_fb,
+};
+
+int picolcd_init_lcd(struct picolcd_data *data, struct hid_report *report)
+{
+	struct device *dev = &data->hdev->dev;
+	struct lcd_device *ldev;
+
+	if (!report)
+		return -ENODEV;
+	if (report->maxfield != 1 || report->field[0]->report_count != 1 ||
+			report->field[0]->report_size != 8) {
+		dev_err(dev, "unsupported CONTRAST report");
+		return -EINVAL;
+	}
+
+	ldev = lcd_device_register(dev_name(dev), dev, data, &picolcd_lcdops);
+	if (IS_ERR(ldev)) {
+		dev_err(dev, "failed to register LCD\n");
+		return PTR_ERR(ldev);
+	}
+	ldev->props.max_contrast = 0x0ff;
+	data->lcd_contrast = 0xe5;
+	data->lcd = ldev;
+	picolcd_set_contrast(ldev, 0xe5);
+	return 0;
+}
+
+void picolcd_exit_lcd(struct picolcd_data *data)
+{
+	struct lcd_device *ldev = data->lcd;
+
+	data->lcd = NULL;
+	if (ldev)
+		lcd_device_unregister(ldev);
+}
+
+int picolcd_resume_lcd(struct picolcd_data *data)
+{
+	if (!data->lcd)
+		return 0;
+	return picolcd_set_contrast(data->lcd, data->lcd_contrast);
+}
+
diff --git a/drivers/hid/hid-picolcd_leds.c b/drivers/hid/hid-picolcd_leds.c
new file mode 100644
index 0000000..28cb6a4
--- /dev/null
+++ b/drivers/hid/hid-picolcd_leds.c
@@ -0,0 +1,175 @@
+/***************************************************************************
+ *   Copyright (C) 2010-2012 by Bruno Prémont <bonbons@linux-vserver.org>  *
+ *                                                                         *
+ *   Based on Logitech G13 driver (v0.4)                                   *
+ *     Copyright (C) 2009 by Rick L. Vinyard, Jr. <rvinyard@cs.nmsu.edu>   *
+ *                                                                         *
+ *   This program is free software: you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation, version 2 of the License.               *
+ *                                                                         *
+ *   This driver is distributed in the hope that it will be useful, but    *
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of            *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      *
+ *   General Public License for more details.                              *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this software. If not see <http://www.gnu.org/licenses/>.  *
+ ***************************************************************************/
+
+#include <linux/hid.h>
+#include <linux/hid-debug.h>
+#include <linux/input.h>
+#include "hid-ids.h"
+#include "usbhid/usbhid.h"
+#include <linux/usb.h>
+
+#include <linux/fb.h>
+#include <linux/vmalloc.h>
+#include <linux/backlight.h>
+#include <linux/lcd.h>
+
+#include <linux/leds.h>
+
+#include <linux/seq_file.h>
+#include <linux/debugfs.h>
+
+#include <linux/completion.h>
+#include <linux/uaccess.h>
+#include <linux/module.h>
+
+#include "hid-picolcd.h"
+
+
+void picolcd_leds_set(struct picolcd_data *data)
+{
+	struct hid_report *report;
+	unsigned long flags;
+
+	if (!data->led[0])
+		return;
+	report = picolcd_out_report(REPORT_LED_STATE, data->hdev);
+	if (!report || report->maxfield != 1 || report->field[0]->report_count != 1)
+		return;
+
+	spin_lock_irqsave(&data->lock, flags);
+	hid_set_field(report->field[0], 0, data->led_state);
+	if (!(data->status & PICOLCD_FAILED))
+		usbhid_submit_report(data->hdev, report, USB_DIR_OUT);
+	spin_unlock_irqrestore(&data->lock, flags);
+}
+
+static void picolcd_led_set_brightness(struct led_classdev *led_cdev,
+			enum led_brightness value)
+{
+	struct device *dev;
+	struct hid_device *hdev;
+	struct picolcd_data *data;
+	int i, state = 0;
+
+	dev  = led_cdev->dev->parent;
+	hdev = container_of(dev, struct hid_device, dev);
+	data = hid_get_drvdata(hdev);
+	if (!data)
+		return;
+	for (i = 0; i < 8; i++) {
+		if (led_cdev != data->led[i])
+			continue;
+		state = (data->led_state >> i) & 1;
+		if (value == LED_OFF && state) {
+			data->led_state &= ~(1 << i);
+			picolcd_leds_set(data);
+		} else if (value != LED_OFF && !state) {
+			data->led_state |= 1 << i;
+			picolcd_leds_set(data);
+		}
+		break;
+	}
+}
+
+static enum led_brightness picolcd_led_get_brightness(struct led_classdev *led_cdev)
+{
+	struct device *dev;
+	struct hid_device *hdev;
+	struct picolcd_data *data;
+	int i, value = 0;
+
+	dev  = led_cdev->dev->parent;
+	hdev = container_of(dev, struct hid_device, dev);
+	data = hid_get_drvdata(hdev);
+	for (i = 0; i < 8; i++)
+		if (led_cdev == data->led[i]) {
+			value = (data->led_state >> i) & 1;
+			break;
+		}
+	return value ? LED_FULL : LED_OFF;
+}
+
+int picolcd_init_leds(struct picolcd_data *data, struct hid_report *report)
+{
+	struct device *dev = &data->hdev->dev;
+	struct led_classdev *led;
+	size_t name_sz = strlen(dev_name(dev)) + 8;
+	char *name;
+	int i, ret = 0;
+
+	if (!report)
+		return -ENODEV;
+	if (report->maxfield != 1 || report->field[0]->report_count != 1 ||
+			report->field[0]->report_size != 8) {
+		dev_err(dev, "unsupported LED_STATE report");
+		return -EINVAL;
+	}
+
+	for (i = 0; i < 8; i++) {
+		led = kzalloc(sizeof(struct led_classdev)+name_sz, GFP_KERNEL);
+		if (!led) {
+			dev_err(dev, "can't allocate memory for LED %d\n", i);
+			ret = -ENOMEM;
+			goto err;
+		}
+		name = (void *)(&led[1]);
+		snprintf(name, name_sz, "%s::GPO%d", dev_name(dev), i);
+		led->name = name;
+		led->brightness = 0;
+		led->max_brightness = 1;
+		led->brightness_get = picolcd_led_get_brightness;
+		led->brightness_set = picolcd_led_set_brightness;
+
+		data->led[i] = led;
+		ret = led_classdev_register(dev, data->led[i]);
+		if (ret) {
+			data->led[i] = NULL;
+			kfree(led);
+			dev_err(dev, "can't register LED %d\n", i);
+			goto err;
+		}
+	}
+	return 0;
+err:
+	for (i = 0; i < 8; i++)
+		if (data->led[i]) {
+			led = data->led[i];
+			data->led[i] = NULL;
+			led_classdev_unregister(led);
+			kfree(led);
+		}
+	return ret;
+}
+
+void picolcd_exit_leds(struct picolcd_data *data)
+{
+	struct led_classdev *led;
+	int i;
+
+	for (i = 0; i < 8; i++) {
+		led = data->led[i];
+		data->led[i] = NULL;
+		if (!led)
+			continue;
+		led_classdev_unregister(led);
+		kfree(led);
+	}
+}
+
+
diff --git a/drivers/hid/hid-primax.c b/drivers/hid/hid-primax.c
index 4d3c60d..c15adb0 100644
--- a/drivers/hid/hid-primax.c
+++ b/drivers/hid/hid-primax.c
@@ -64,29 +64,6 @@ static int px_raw_event(struct hid_device *hid, struct hid_report *report,
 	return 0;
 }
 
-static int px_probe(struct hid_device *hid, const struct hid_device_id *id)
-{
-	int ret;
-
-	ret = hid_parse(hid);
-	if (ret) {
-		hid_err(hid, "parse failed\n");
-		goto fail;
-	}
-
-	ret = hid_hw_start(hid, HID_CONNECT_DEFAULT);
-	if (ret)
-		hid_err(hid, "hw start failed\n");
-
-fail:
-	return ret;
-}
-
-static void px_remove(struct hid_device *hid)
-{
-	hid_hw_stop(hid);
-}
-
 static const struct hid_device_id px_devices[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_KEYBOARD) },
 	{ }
@@ -97,8 +74,6 @@ static struct hid_driver px_driver = {
 	.name = "primax",
 	.id_table = px_devices,
 	.raw_event = px_raw_event,
-	.probe = px_probe,
-	.remove = px_remove,
 };
 
 static int __init px_init(void)
diff --git a/drivers/hid/hid-prodikeys.c b/drivers/hid/hid-prodikeys.c
index b71b77a..ec8ca33 100644
--- a/drivers/hid/hid-prodikeys.c
+++ b/drivers/hid/hid-prodikeys.c
@@ -105,7 +105,7 @@ static ssize_t show_channel(struct device *dev,
 	struct device_attribute *attr, char *buf)
 {
 	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
-	struct pk_device *pk = (struct pk_device *)hid_get_drvdata(hdev);
+	struct pk_device *pk = hid_get_drvdata(hdev);
 
 	dbg_hid("pcmidi sysfs read channel=%u\n", pk->pm->midi_channel);
 
@@ -118,7 +118,7 @@ static ssize_t store_channel(struct device *dev,
 	struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
-	struct pk_device *pk = (struct pk_device *)hid_get_drvdata(hdev);
+	struct pk_device *pk = hid_get_drvdata(hdev);
 
 	unsigned channel = 0;
 
@@ -142,7 +142,7 @@ static ssize_t show_sustain(struct device *dev,
  struct device_attribute *attr, char *buf)
 {
 	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
-	struct pk_device *pk = (struct pk_device *)hid_get_drvdata(hdev);
+	struct pk_device *pk = hid_get_drvdata(hdev);
 
 	dbg_hid("pcmidi sysfs read sustain=%u\n", pk->pm->midi_sustain);
 
@@ -155,7 +155,7 @@ static ssize_t store_sustain(struct device *dev,
 	struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
-	struct pk_device *pk = (struct pk_device *)hid_get_drvdata(hdev);
+	struct pk_device *pk = hid_get_drvdata(hdev);
 
 	unsigned sustain = 0;
 
@@ -181,7 +181,7 @@ static ssize_t show_octave(struct device *dev,
 	struct device_attribute *attr, char *buf)
 {
 	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
-	struct pk_device *pk = (struct pk_device *)hid_get_drvdata(hdev);
+	struct pk_device *pk = hid_get_drvdata(hdev);
 
 	dbg_hid("pcmidi sysfs read octave=%d\n", pk->pm->midi_octave);
 
@@ -194,7 +194,7 @@ static ssize_t store_octave(struct device *dev,
 	struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
-	struct pk_device *pk = (struct pk_device *)hid_get_drvdata(hdev);
+	struct pk_device *pk = hid_get_drvdata(hdev);
 
 	int octave = 0;
 
@@ -759,7 +759,7 @@ static int pk_input_mapping(struct hid_device *hdev, struct hid_input *hi,
 		struct hid_field *field, struct hid_usage *usage,
 		unsigned long **bit, int *max)
 {
-	struct pk_device *pk = (struct pk_device *)hid_get_drvdata(hdev);
+	struct pk_device *pk = hid_get_drvdata(hdev);
 	struct pcmidi_snd *pm;
 
 	pm = pk->pm;
@@ -777,7 +777,7 @@ static int pk_input_mapping(struct hid_device *hdev, struct hid_input *hi,
 static int pk_raw_event(struct hid_device *hdev, struct hid_report *report,
 	u8 *data, int size)
 {
-	struct pk_device *pk = (struct pk_device *)hid_get_drvdata(hdev);
+	struct pk_device *pk = hid_get_drvdata(hdev);
 	int ret = 0;
 
 	if (1 == pk->pm->ifnum) {
@@ -858,7 +858,7 @@ err_free_pk:
 
 static void pk_remove(struct hid_device *hdev)
 {
-	struct pk_device *pk = (struct pk_device *)hid_get_drvdata(hdev);
+	struct pk_device *pk = hid_get_drvdata(hdev);
 	struct pcmidi_snd *pm;
 
 	pm = pk->pm;
diff --git a/drivers/hid/hid-samsung.c b/drivers/hid/hid-samsung.c
index 3c1fd8a..a5821d3 100644
--- a/drivers/hid/hid-samsung.c
+++ b/drivers/hid/hid-samsung.c
@@ -5,7 +5,6 @@
  *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
  *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
  *  Copyright (c) 2006-2007 Jiri Kosina
- *  Copyright (c) 2007 Paul Walmsley
  *  Copyright (c) 2008 Jiri Slaby
  *  Copyright (c) 2010 Don Prince <dhprince.devel@yahoo.co.uk>
  *
diff --git a/drivers/hid/hid-sensor-hub.c b/drivers/hid/hid-sensor-hub.c
new file mode 100644
index 0000000..4ac759c
--- /dev/null
+++ b/drivers/hid/hid-sensor-hub.c
@@ -0,0 +1,695 @@
+/*
+ * HID Sensors Driver
+ * Copyright (c) 2012, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+#include <linux/device.h>
+#include <linux/hid.h>
+#include <linux/usb.h>
+#include "usbhid/usbhid.h"
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/mfd/core.h>
+#include <linux/list.h>
+#include <linux/hid-sensor-ids.h>
+#include <linux/hid-sensor-hub.h>
+#include "hid-ids.h"
+
+/**
+ * struct sensor_hub_pending - Synchronous read pending information
+ * @status:		Pending status true/false.
+ * @ready:		Completion synchronization data.
+ * @usage_id:		Usage id for physical device, E.g. Gyro usage id.
+ * @attr_usage_id:	Usage Id of a field, E.g. X-AXIS for a gyro.
+ * @raw_size:		Response size for a read request.
+ * @raw_data:		Place holder for received response.
+ */
+struct sensor_hub_pending {
+	bool status;
+	struct completion ready;
+	u32 usage_id;
+	u32 attr_usage_id;
+	int raw_size;
+	u8  *raw_data;
+};
+
+/**
+ * struct sensor_hub_data - Hold a instance data for a HID hub device
+ * @hsdev:		Stored hid instance for current hub device.
+ * @mutex:		Mutex to serialize synchronous request.
+ * @lock:		Spin lock to protect pending request structure.
+ * @pending:		Holds information of pending sync read request.
+ * @dyn_callback_list:	Holds callback function
+ * @dyn_callback_lock:	spin lock to protect callback list
+ * @hid_sensor_hub_client_devs:	Stores all MFD cells for a hub instance.
+ * @hid_sensor_client_cnt: Number of MFD cells, (no of sensors attached).
+ */
+struct sensor_hub_data {
+	struct hid_sensor_hub_device *hsdev;
+	struct mutex mutex;
+	spinlock_t lock;
+	struct sensor_hub_pending pending;
+	struct list_head dyn_callback_list;
+	spinlock_t dyn_callback_lock;
+	struct mfd_cell *hid_sensor_hub_client_devs;
+	int hid_sensor_client_cnt;
+};
+
+/**
+ * struct hid_sensor_hub_callbacks_list - Stores callback list
+ * @list:		list head.
+ * @usage_id:		usage id for a physical device.
+ * @usage_callback:	Stores registered callback functions.
+ * @priv:		Private data for a physical device.
+ */
+struct hid_sensor_hub_callbacks_list {
+	struct list_head list;
+	u32 usage_id;
+	struct hid_sensor_hub_callbacks *usage_callback;
+	void *priv;
+};
+
+static int sensor_hub_check_for_sensor_page(struct hid_device *hdev)
+{
+	int i;
+	int ret = -EINVAL;
+
+	for (i = 0; i < hdev->maxcollection; i++) {
+		struct hid_collection *col = &hdev->collection[i];
+		if (col->type == HID_COLLECTION_PHYSICAL &&
+		   (col->usage & HID_USAGE_PAGE) == HID_UP_SENSOR) {
+			ret = 0;
+			break;
+		}
+	}
+
+	return ret;
+}
+
+static struct hid_report *sensor_hub_report(int id, struct hid_device *hdev,
+						int dir)
+{
+	struct hid_report *report;
+
+	list_for_each_entry(report, &hdev->report_enum[dir].report_list, list) {
+		if (report->id == id)
+			return report;
+	}
+	hid_warn(hdev, "No report with id 0x%x found\n", id);
+
+	return NULL;
+}
+
+static int sensor_hub_get_physical_device_count(
+				struct hid_report_enum *report_enum)
+{
+	struct hid_report *report;
+	struct hid_field *field;
+	int cnt = 0;
+
+	list_for_each_entry(report, &report_enum->report_list, list) {
+		field = report->field[0];
+		if (report->maxfield && field &&
+					field->physical)
+			cnt++;
+	}
+
+	return cnt;
+}
+
+static void sensor_hub_fill_attr_info(
+		struct hid_sensor_hub_attribute_info *info,
+		s32 index, s32 report_id, s32 units, s32 unit_expo, s32 size)
+{
+	info->index = index;
+	info->report_id = report_id;
+	info->units = units;
+	info->unit_expo = unit_expo;
+	info->size = size/8;
+}
+
+static struct hid_sensor_hub_callbacks *sensor_hub_get_callback(
+					struct hid_device *hdev,
+					u32 usage_id, void **priv)
+{
+	struct hid_sensor_hub_callbacks_list *callback;
+	struct sensor_hub_data *pdata = hid_get_drvdata(hdev);
+
+	spin_lock(&pdata->dyn_callback_lock);
+	list_for_each_entry(callback, &pdata->dyn_callback_list, list)
+		if (callback->usage_id == usage_id) {
+			*priv = callback->priv;
+			spin_unlock(&pdata->dyn_callback_lock);
+			return callback->usage_callback;
+		}
+	spin_unlock(&pdata->dyn_callback_lock);
+
+	return NULL;
+}
+
+int sensor_hub_register_callback(struct hid_sensor_hub_device *hsdev,
+			u32 usage_id,
+			struct hid_sensor_hub_callbacks *usage_callback)
+{
+	struct hid_sensor_hub_callbacks_list *callback;
+	struct sensor_hub_data *pdata = hid_get_drvdata(hsdev->hdev);
+
+	spin_lock(&pdata->dyn_callback_lock);
+	list_for_each_entry(callback, &pdata->dyn_callback_list, list)
+		if (callback->usage_id == usage_id) {
+			spin_unlock(&pdata->dyn_callback_lock);
+			return -EINVAL;
+		}
+	callback = kzalloc(sizeof(*callback), GFP_KERNEL);
+	if (!callback) {
+		spin_unlock(&pdata->dyn_callback_lock);
+		return -ENOMEM;
+	}
+	callback->usage_callback = usage_callback;
+	callback->usage_id = usage_id;
+	callback->priv = NULL;
+	list_add_tail(&callback->list, &pdata->dyn_callback_list);
+	spin_unlock(&pdata->dyn_callback_lock);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(sensor_hub_register_callback);
+
+int sensor_hub_remove_callback(struct hid_sensor_hub_device *hsdev,
+				u32 usage_id)
+{
+	struct hid_sensor_hub_callbacks_list *callback;
+	struct sensor_hub_data *pdata = hid_get_drvdata(hsdev->hdev);
+
+	spin_lock(&pdata->dyn_callback_lock);
+	list_for_each_entry(callback, &pdata->dyn_callback_list, list)
+		if (callback->usage_id == usage_id) {
+			list_del(&callback->list);
+			kfree(callback);
+			break;
+		}
+	spin_unlock(&pdata->dyn_callback_lock);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(sensor_hub_remove_callback);
+
+int sensor_hub_set_feature(struct hid_sensor_hub_device *hsdev, u32 report_id,
+				u32 field_index, s32 value)
+{
+	struct hid_report *report;
+	struct sensor_hub_data *data =  hid_get_drvdata(hsdev->hdev);
+	int ret = 0;
+
+	if (report_id < 0)
+		return -EINVAL;
+
+	mutex_lock(&data->mutex);
+	report = sensor_hub_report(report_id, hsdev->hdev, HID_FEATURE_REPORT);
+	if (!report || (field_index >=  report->maxfield)) {
+		ret = -EINVAL;
+		goto done_proc;
+	}
+	hid_set_field(report->field[field_index], 0, value);
+	usbhid_submit_report(hsdev->hdev, report, USB_DIR_OUT);
+	usbhid_wait_io(hsdev->hdev);
+
+done_proc:
+	mutex_unlock(&data->mutex);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(sensor_hub_set_feature);
+
+int sensor_hub_get_feature(struct hid_sensor_hub_device *hsdev, u32 report_id,
+				u32 field_index, s32 *value)
+{
+	struct hid_report *report;
+	struct sensor_hub_data *data =  hid_get_drvdata(hsdev->hdev);
+	int ret = 0;
+
+	if (report_id < 0)
+		return -EINVAL;
+
+	mutex_lock(&data->mutex);
+	report = sensor_hub_report(report_id, hsdev->hdev, HID_FEATURE_REPORT);
+	if (!report || (field_index >=  report->maxfield)) {
+		ret = -EINVAL;
+		goto done_proc;
+	}
+	usbhid_submit_report(hsdev->hdev, report, USB_DIR_IN);
+	usbhid_wait_io(hsdev->hdev);
+	*value = report->field[field_index]->value[0];
+
+done_proc:
+	mutex_unlock(&data->mutex);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(sensor_hub_get_feature);
+
+
+int sensor_hub_input_attr_get_raw_value(struct hid_sensor_hub_device *hsdev,
+					u32 usage_id,
+					u32 attr_usage_id, u32 report_id)
+{
+	struct sensor_hub_data *data =  hid_get_drvdata(hsdev->hdev);
+	unsigned long flags;
+	struct hid_report *report;
+	int ret_val = 0;
+
+	if (report_id < 0)
+		return -EINVAL;
+
+	mutex_lock(&data->mutex);
+	memset(&data->pending, 0, sizeof(data->pending));
+	init_completion(&data->pending.ready);
+	data->pending.usage_id = usage_id;
+	data->pending.attr_usage_id = attr_usage_id;
+	data->pending.raw_size = 0;
+
+	spin_lock_irqsave(&data->lock, flags);
+	data->pending.status = true;
+	report = sensor_hub_report(report_id, hsdev->hdev, HID_INPUT_REPORT);
+	if (!report) {
+		spin_unlock_irqrestore(&data->lock, flags);
+		goto err_free;
+	}
+	usbhid_submit_report(hsdev->hdev, report, USB_DIR_IN);
+	spin_unlock_irqrestore(&data->lock, flags);
+	wait_for_completion_interruptible_timeout(&data->pending.ready, HZ*5);
+	switch (data->pending.raw_size) {
+	case 1:
+		ret_val = *(u8 *)data->pending.raw_data;
+		break;
+	case 2:
+		ret_val = *(u16 *)data->pending.raw_data;
+		break;
+	case 4:
+		ret_val = *(u32 *)data->pending.raw_data;
+		break;
+	default:
+		ret_val = 0;
+	}
+	kfree(data->pending.raw_data);
+
+err_free:
+	data->pending.status = false;
+	mutex_unlock(&data->mutex);
+
+	return ret_val;
+}
+EXPORT_SYMBOL_GPL(sensor_hub_input_attr_get_raw_value);
+
+int sensor_hub_input_get_attribute_info(struct hid_sensor_hub_device *hsdev,
+				u8 type,
+				u32 usage_id,
+				u32 attr_usage_id,
+				struct hid_sensor_hub_attribute_info *info)
+{
+	int ret = -1;
+	int i, j;
+	int collection_index = -1;
+	struct hid_report *report;
+	struct hid_field *field;
+	struct hid_report_enum *report_enum;
+	struct hid_device *hdev = hsdev->hdev;
+
+	/* Initialize with defaults */
+	info->usage_id = usage_id;
+	info->attrib_id =  attr_usage_id;
+	info->report_id = -1;
+	info->index = -1;
+	info->units = -1;
+	info->unit_expo = -1;
+
+	for (i = 0; i < hdev->maxcollection; ++i) {
+		struct hid_collection *collection = &hdev->collection[i];
+		if (usage_id == collection->usage) {
+			collection_index = i;
+			break;
+		}
+	}
+	if (collection_index == -1)
+		goto err_ret;
+
+	report_enum = &hdev->report_enum[type];
+	list_for_each_entry(report, &report_enum->report_list, list) {
+		for (i = 0; i < report->maxfield; ++i) {
+			field = report->field[i];
+			if (field->physical == usage_id &&
+				field->logical == attr_usage_id) {
+				sensor_hub_fill_attr_info(info, i, report->id,
+					field->unit, field->unit_exponent,
+					field->report_size);
+				ret = 0;
+			} else {
+				for (j = 0; j < field->maxusage; ++j) {
+					if (field->usage[j].hid ==
+					attr_usage_id &&
+					field->usage[j].collection_index ==
+					collection_index)  {
+						sensor_hub_fill_attr_info(info,
+							i, report->id,
+							field->unit,
+							field->unit_exponent,
+							field->report_size);
+						ret = 0;
+						break;
+					}
+				}
+			}
+			if (ret == 0)
+				break;
+		}
+	}
+
+err_ret:
+	return ret;
+}
+EXPORT_SYMBOL_GPL(sensor_hub_input_get_attribute_info);
+
+#ifdef CONFIG_PM
+static int sensor_hub_suspend(struct hid_device *hdev, pm_message_t message)
+{
+	struct sensor_hub_data *pdata =  hid_get_drvdata(hdev);
+	struct hid_sensor_hub_callbacks_list *callback;
+
+	hid_dbg(hdev, " sensor_hub_suspend\n");
+	spin_lock(&pdata->dyn_callback_lock);
+	list_for_each_entry(callback, &pdata->dyn_callback_list, list) {
+		if (callback->usage_callback->suspend)
+			callback->usage_callback->suspend(
+					pdata->hsdev, callback->priv);
+	}
+	spin_unlock(&pdata->dyn_callback_lock);
+
+	return 0;
+}
+
+static int sensor_hub_resume(struct hid_device *hdev)
+{
+	struct sensor_hub_data *pdata =  hid_get_drvdata(hdev);
+	struct hid_sensor_hub_callbacks_list *callback;
+
+	hid_dbg(hdev, " sensor_hub_resume\n");
+	spin_lock(&pdata->dyn_callback_lock);
+	list_for_each_entry(callback, &pdata->dyn_callback_list, list) {
+		if (callback->usage_callback->resume)
+			callback->usage_callback->resume(
+					pdata->hsdev, callback->priv);
+	}
+	spin_unlock(&pdata->dyn_callback_lock);
+
+	return 0;
+}
+
+static int sensor_hub_reset_resume(struct hid_device *hdev)
+{
+	return 0;
+}
+#endif
+/*
+ * Handle raw report as sent by device
+ */
+static int sensor_hub_raw_event(struct hid_device *hdev,
+		struct hid_report *report, u8 *raw_data, int size)
+{
+	int i;
+	u8 *ptr;
+	int sz;
+	struct sensor_hub_data *pdata = hid_get_drvdata(hdev);
+	unsigned long flags;
+	struct hid_sensor_hub_callbacks *callback = NULL;
+	struct hid_collection *collection = NULL;
+	void *priv = NULL;
+
+	hid_dbg(hdev, "sensor_hub_raw_event report id:0x%x size:%d type:%d\n",
+			 report->id, size, report->type);
+	hid_dbg(hdev, "maxfield:%d\n", report->maxfield);
+	if (report->type != HID_INPUT_REPORT)
+		return 1;
+
+	ptr = raw_data;
+	ptr++; /*Skip report id*/
+
+	if (!report)
+		goto err_report;
+
+	spin_lock_irqsave(&pdata->lock, flags);
+
+	for (i = 0; i < report->maxfield; ++i) {
+
+		hid_dbg(hdev, "%d collection_index:%x hid:%x sz:%x\n",
+				i, report->field[i]->usage->collection_index,
+				report->field[i]->usage->hid,
+				report->field[i]->report_size/8);
+
+		sz = report->field[i]->report_size/8;
+		if (pdata->pending.status && pdata->pending.attr_usage_id ==
+				report->field[i]->usage->hid) {
+			hid_dbg(hdev, "data was pending ...\n");
+			pdata->pending.raw_data = kmalloc(sz, GFP_KERNEL);
+			if (pdata->pending.raw_data) {
+				memcpy(pdata->pending.raw_data, ptr, sz);
+				pdata->pending.raw_size  = sz;
+			} else
+				pdata->pending.raw_size = 0;
+			complete(&pdata->pending.ready);
+		}
+		collection = &hdev->collection[
+				report->field[i]->usage->collection_index];
+		hid_dbg(hdev, "collection->usage %x\n",
+					collection->usage);
+		callback = sensor_hub_get_callback(pdata->hsdev->hdev,
+						report->field[i]->physical,
+							&priv);
+		if (callback && callback->capture_sample) {
+			if (report->field[i]->logical)
+				callback->capture_sample(pdata->hsdev,
+					report->field[i]->logical, sz, ptr,
+					callback->pdev);
+			else
+				callback->capture_sample(pdata->hsdev,
+					report->field[i]->usage->hid, sz, ptr,
+					callback->pdev);
+		}
+		ptr += sz;
+	}
+	if (callback && collection && callback->send_event)
+		callback->send_event(pdata->hsdev, collection->usage,
+				callback->pdev);
+	spin_unlock_irqrestore(&pdata->lock, flags);
+
+err_report:
+	return 1;
+}
+
+static int sensor_hub_probe(struct hid_device *hdev,
+				const struct hid_device_id *id)
+{
+	int ret;
+	struct sensor_hub_data *sd;
+	int i;
+	char *name;
+	struct hid_report *report;
+	struct hid_report_enum *report_enum;
+	struct hid_field *field;
+	int dev_cnt;
+
+	sd = kzalloc(sizeof(struct sensor_hub_data), GFP_KERNEL);
+	if (!sd) {
+		hid_err(hdev, "cannot allocate Sensor data\n");
+		return -ENOMEM;
+	}
+	sd->hsdev = kzalloc(sizeof(struct hid_sensor_hub_device), GFP_KERNEL);
+	if (!sd->hsdev) {
+		hid_err(hdev, "cannot allocate hid_sensor_hub_device\n");
+		ret = -ENOMEM;
+		goto err_free_hub;
+	}
+	hid_set_drvdata(hdev, sd);
+	sd->hsdev->hdev = hdev;
+	sd->hsdev->vendor_id = hdev->vendor;
+	sd->hsdev->product_id = hdev->product;
+	spin_lock_init(&sd->lock);
+	spin_lock_init(&sd->dyn_callback_lock);
+	mutex_init(&sd->mutex);
+	ret = hid_parse(hdev);
+	if (ret) {
+		hid_err(hdev, "parse failed\n");
+		goto err_free;
+	}
+	if (sensor_hub_check_for_sensor_page(hdev) < 0) {
+		hid_err(hdev, "sensor page not found\n");
+		goto err_free;
+	}
+	INIT_LIST_HEAD(&hdev->inputs);
+
+	hdev->claimed = HID_CLAIMED_INPUT;
+	ret = hid_hw_start(hdev, 0);
+	if (ret) {
+		hid_err(hdev, "hw start failed\n");
+		goto err_free;
+	}
+	ret = hid_hw_open(hdev);
+	if (ret) {
+		hid_err(hdev, "failed to open input interrupt pipe\n");
+		goto err_stop_hw;
+	}
+
+	INIT_LIST_HEAD(&sd->dyn_callback_list);
+	sd->hid_sensor_client_cnt = 0;
+	report_enum = &hdev->report_enum[HID_INPUT_REPORT];
+
+	dev_cnt = sensor_hub_get_physical_device_count(report_enum);
+	if (dev_cnt > HID_MAX_PHY_DEVICES) {
+		hid_err(hdev, "Invalid Physical device count\n");
+		ret = -EINVAL;
+		goto err_close;
+	}
+	sd->hid_sensor_hub_client_devs = kzalloc(dev_cnt *
+						sizeof(struct mfd_cell),
+						GFP_KERNEL);
+	if (sd->hid_sensor_hub_client_devs == NULL) {
+		hid_err(hdev,
+			"Failed to allocate memory for mfd cells\n");
+			ret = -ENOMEM;
+			goto err_close;
+	}
+	list_for_each_entry(report, &report_enum->report_list, list) {
+		hid_dbg(hdev, "Report id:%x\n", report->id);
+		field = report->field[0];
+		if (report->maxfield && field &&
+					field->physical) {
+			name = kasprintf(GFP_KERNEL, "HID-SENSOR-%x",
+						field->physical);
+			if (name  == NULL) {
+				hid_err(hdev,
+					"Failed MFD device name\n");
+					ret = -ENOMEM;
+					goto err_free_cells;
+			}
+			sd->hid_sensor_hub_client_devs[
+				sd->hid_sensor_client_cnt].name = name;
+			sd->hid_sensor_hub_client_devs[
+				sd->hid_sensor_client_cnt].platform_data =
+						sd->hsdev;
+			sd->hid_sensor_hub_client_devs[
+				sd->hid_sensor_client_cnt].pdata_size =
+						sizeof(*sd->hsdev);
+			hid_dbg(hdev, "Adding %s:%p\n", name, sd);
+			sd->hid_sensor_client_cnt++;
+		}
+	}
+	ret = mfd_add_devices(&hdev->dev, 0, sd->hid_sensor_hub_client_devs,
+		sd->hid_sensor_client_cnt, NULL, 0, NULL);
+	if (ret < 0)
+		goto err_free_names;
+
+	return ret;
+
+err_free_names:
+	for (i = 0; i < sd->hid_sensor_client_cnt ; ++i)
+		kfree(sd->hid_sensor_hub_client_devs[i].name);
+err_free_cells:
+	kfree(sd->hid_sensor_hub_client_devs);
+err_close:
+	hid_hw_stop(hdev);
+	hid_hw_close(hdev);
+err_stop_hw:
+	hid_hw_stop(hdev);
+err_free:
+	kfree(sd->hsdev);
+err_free_hub:
+	kfree(sd);
+
+	return ret;
+}
+
+static void sensor_hub_remove(struct hid_device *hdev)
+{
+	struct sensor_hub_data *data = hid_get_drvdata(hdev);
+	unsigned long flags;
+	int i;
+
+	hid_dbg(hdev, " hardware removed\n");
+	hdev->claimed &= ~HID_CLAIMED_INPUT;
+	hid_hw_stop(hdev);
+	hid_hw_close(hdev);
+	spin_lock_irqsave(&data->lock, flags);
+	if (data->pending.status)
+		complete(&data->pending.ready);
+	spin_unlock_irqrestore(&data->lock, flags);
+	mfd_remove_devices(&hdev->dev);
+	for (i = 0; i < data->hid_sensor_client_cnt ; ++i)
+		kfree(data->hid_sensor_hub_client_devs[i].name);
+	kfree(data->hid_sensor_hub_client_devs);
+	hid_set_drvdata(hdev, NULL);
+	mutex_destroy(&data->mutex);
+	kfree(data->hsdev);
+	kfree(data);
+}
+
+static const struct hid_device_id sensor_hub_devices[] = {
+	{ HID_USB_DEVICE(USB_VENDOR_ID_INTEL_8086,
+			USB_DEVICE_ID_SENSOR_HUB_1020) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_INTEL_8087,
+			USB_DEVICE_ID_SENSOR_HUB_1020) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_INTEL_8086,
+			USB_DEVICE_ID_SENSOR_HUB_09FA) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_INTEL_8087,
+			USB_DEVICE_ID_SENSOR_HUB_09FA) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_STANTUM_STM,
+			USB_DEVICE_ID_SENSOR_HUB_7014) },
+	{ }
+};
+MODULE_DEVICE_TABLE(hid, sensor_hub_devices);
+
+static const struct hid_usage_id sensor_hub_grabbed_usages[] = {
+	{ HID_ANY_ID, HID_ANY_ID, HID_ANY_ID },
+	{ HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1 }
+};
+
+static struct hid_driver sensor_hub_driver = {
+	.name = "hid-sensor-hub",
+	.id_table = sensor_hub_devices,
+	.probe = sensor_hub_probe,
+	.remove = sensor_hub_remove,
+	.raw_event = sensor_hub_raw_event,
+#ifdef CONFIG_PM
+	.suspend = sensor_hub_suspend,
+	.resume =  sensor_hub_resume,
+	.reset_resume =  sensor_hub_reset_resume,
+#endif
+};
+
+static int __init sensor_hub_init(void)
+{
+	return hid_register_driver(&sensor_hub_driver);
+}
+
+static void __exit sensor_hub_exit(void)
+{
+	hid_unregister_driver(&sensor_hub_driver);
+}
+
+module_init(sensor_hub_init);
+module_exit(sensor_hub_exit);
+
+MODULE_DESCRIPTION("HID Sensor Hub driver");
+MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@intel.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c
index 5cd25bd..7f33ebf 100644
--- a/drivers/hid/hid-sony.c
+++ b/drivers/hid/hid-sony.c
@@ -4,7 +4,6 @@
  *  Copyright (c) 1999 Andreas Gal
  *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
  *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
- *  Copyright (c) 2007 Paul Walmsley
  *  Copyright (c) 2008 Jiri Slaby
  *  Copyright (c) 2006-2008 Jiri Kosina
  */
diff --git a/drivers/hid/hid-sunplus.c b/drivers/hid/hid-sunplus.c
index d484a00..45b4b06 100644
--- a/drivers/hid/hid-sunplus.c
+++ b/drivers/hid/hid-sunplus.c
@@ -5,7 +5,6 @@
  *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
  *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
  *  Copyright (c) 2006-2007 Jiri Kosina
- *  Copyright (c) 2007 Paul Walmsley
  *  Copyright (c) 2008 Jiri Slaby
  */
 
diff --git a/drivers/hid/hid-uclogic.c b/drivers/hid/hid-uclogic.c
index 3aba02b..2e56a1f 100644
--- a/drivers/hid/hid-uclogic.c
+++ b/drivers/hid/hid-uclogic.c
@@ -466,6 +466,86 @@ static __u8 twhl850_rdesc_fixed2[] = {
 	0xC0                /*  End Collection                      */
 };
 
+/*
+ * See TWHA60 description, device and HID report descriptors at
+ * http://sf.net/apps/mediawiki/digimend/?title=UC-Logic_Tablet_TWHA60
+ */
+
+/* Size of the original descriptors of TWHA60 tablet */
+#define TWHA60_RDESC_ORIG_SIZE0 254
+#define TWHA60_RDESC_ORIG_SIZE1 139
+
+/* Fixed TWHA60 report descriptor, interface 0 (stylus) */
+static __u8 twha60_rdesc_fixed0[] = {
+	0x05, 0x0D,         /*  Usage Page (Digitizer),             */
+	0x09, 0x02,         /*  Usage (Pen),                        */
+	0xA1, 0x01,         /*  Collection (Application),           */
+	0x85, 0x09,         /*      Report ID (9),                  */
+	0x09, 0x20,         /*      Usage (Stylus),                 */
+	0xA0,               /*      Collection (Physical),          */
+	0x75, 0x01,         /*          Report Size (1),            */
+	0x09, 0x42,         /*          Usage (Tip Switch),         */
+	0x09, 0x44,         /*          Usage (Barrel Switch),      */
+	0x09, 0x46,         /*          Usage (Tablet Pick),        */
+	0x14,               /*          Logical Minimum (0),        */
+	0x25, 0x01,         /*          Logical Maximum (1),        */
+	0x95, 0x03,         /*          Report Count (3),           */
+	0x81, 0x02,         /*          Input (Variable),           */
+	0x95, 0x04,         /*          Report Count (4),           */
+	0x81, 0x01,         /*          Input (Constant),           */
+	0x09, 0x32,         /*          Usage (In Range),           */
+	0x95, 0x01,         /*          Report Count (1),           */
+	0x81, 0x02,         /*          Input (Variable),           */
+	0x75, 0x10,         /*          Report Size (16),           */
+	0x95, 0x01,         /*          Report Count (1),           */
+	0x14,               /*          Logical Minimum (0),        */
+	0xA4,               /*          Push,                       */
+	0x05, 0x01,         /*          Usage Page (Desktop),       */
+	0x55, 0xFD,         /*          Unit Exponent (-3),         */
+	0x65, 0x13,         /*          Unit (Inch),                */
+	0x34,               /*          Physical Minimum (0),       */
+	0x09, 0x30,         /*          Usage (X),                  */
+	0x46, 0x10, 0x27,   /*          Physical Maximum (10000),   */
+	0x27, 0x3F, 0x9C,
+		0x00, 0x00, /*          Logical Maximum (39999),    */
+	0x81, 0x02,         /*          Input (Variable),           */
+	0x09, 0x31,         /*          Usage (Y),                  */
+	0x46, 0x6A, 0x18,   /*          Physical Maximum (6250),    */
+	0x26, 0xA7, 0x61,   /*          Logical Maximum (24999),    */
+	0x81, 0x02,         /*          Input (Variable),           */
+	0xB4,               /*          Pop,                        */
+	0x09, 0x30,         /*          Usage (Tip Pressure),       */
+	0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),     */
+	0x81, 0x02,         /*          Input (Variable),           */
+	0xC0,               /*      End Collection,                 */
+	0xC0                /*  End Collection                      */
+};
+
+/* Fixed TWHA60 report descriptor, interface 1 (frame buttons) */
+static __u8 twha60_rdesc_fixed1[] = {
+	0x05, 0x01, /*  Usage Page (Desktop),       */
+	0x09, 0x06, /*  Usage (Keyboard),           */
+	0xA1, 0x01, /*  Collection (Application),   */
+	0x85, 0x05, /*      Report ID (5),          */
+	0x05, 0x07, /*      Usage Page (Keyboard),  */
+	0x14,       /*      Logical Minimum (0),    */
+	0x25, 0x01, /*      Logical Maximum (1),    */
+	0x75, 0x01, /*      Report Size (1),        */
+	0x95, 0x08, /*      Report Count (8),       */
+	0x81, 0x01, /*      Input (Constant),       */
+	0x95, 0x0C, /*      Report Count (12),      */
+	0x19, 0x3A, /*      Usage Minimum (KB F1),  */
+	0x29, 0x45, /*      Usage Maximum (KB F12), */
+	0x81, 0x02, /*      Input (Variable),       */
+	0x95, 0x0C, /*      Report Count (12),      */
+	0x19, 0x68, /*      Usage Minimum (KB F13), */
+	0x29, 0x73, /*      Usage Maximum (KB F24), */
+	0x81, 0x02, /*      Input (Variable),       */
+	0x95, 0x08, /*      Report Count (8),       */
+	0x81, 0x01, /*      Input (Constant),       */
+	0xC0        /*  End Collection              */
+};
+
 static __u8 *uclogic_report_fixup(struct hid_device *hdev, __u8 *rdesc,
 					unsigned int *rsize)
 {
@@ -525,6 +605,22 @@ static __u8 *uclogic_report_fixup(struct hid_device *hdev, __u8 *rdesc,
 			break;
 		}
 		break;
+	case USB_DEVICE_ID_UCLOGIC_TABLET_TWHA60:
+		switch (iface_num) {
+		case 0:
+			if (*rsize == TWHA60_RDESC_ORIG_SIZE0) {
+				rdesc = twha60_rdesc_fixed0;
+				*rsize = sizeof(twha60_rdesc_fixed0);
+			}
+			break;
+		case 1:
+			if (*rsize == TWHA60_RDESC_ORIG_SIZE1) {
+				rdesc = twha60_rdesc_fixed1;
+				*rsize = sizeof(twha60_rdesc_fixed1);
+			}
+			break;
+		}
+		break;
 	}
 
 	return rdesc;
@@ -543,6 +639,8 @@ static const struct hid_device_id uclogic_devices[] = {
 				USB_DEVICE_ID_UCLOGIC_TABLET_WP1062) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC,
 				USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC,
+				USB_DEVICE_ID_UCLOGIC_TABLET_TWHA60) },
 	{ }
 };
 MODULE_DEVICE_TABLE(hid, uclogic_devices);
diff --git a/drivers/hid/hid-wacom.c b/drivers/hid/hid-wacom.c
index fe23a1e..2f60da9 100644
--- a/drivers/hid/hid-wacom.c
+++ b/drivers/hid/hid-wacom.c
@@ -5,7 +5,6 @@
  *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
  *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
  *  Copyright (c) 2006-2007 Jiri Kosina
- *  Copyright (c) 2007 Paul Walmsley
  *  Copyright (c) 2008 Jiri Slaby <jirislaby@gmail.com>
  *  Copyright (c) 2006 Andrew Zabolotny <zap@homelink.ru>
  *  Copyright (c) 2009 Bastien Nocera <hadess@hadess.net>
@@ -33,6 +32,8 @@
 #define PAD_DEVICE_ID	0x0F
 
 #define WAC_CMD_LED_CONTROL     0x20
+#define WAC_CMD_ICON_START_STOP     0x21
+#define WAC_CMD_ICON_TRANSFER       0x26
 
 struct wacom_data {
 	__u16 tool;
@@ -69,6 +70,91 @@ static enum power_supply_property wacom_ac_props[] = {
 	POWER_SUPPLY_PROP_SCOPE,
 };
 
+static void wacom_scramble(__u8 *image)
+{
+	__u16 mask;
+	__u16 s1;
+	__u16 s2;
+	__u16 r1 ;
+	__u16 r2 ;
+	__u16 r;
+	__u8 buf[256];
+	int i, w, x, y, z;
+
+	for (x = 0; x < 32; x++) {
+		for (y = 0; y < 8; y++)
+			buf[(8 * x) + (7 - y)] = image[(8 * x) + y];
+	}
+
+	/* Change 76543210 into GECA6420 as required by Intuos4 WL
+	 *        HGFEDCBA      HFDB7531
+	 */
+	for (x = 0; x < 4; x++) {
+		for (y = 0; y < 4; y++) {
+			for (z = 0; z < 8; z++) {
+				mask = 0x0001;
+				r1 = 0;
+				r2 = 0;
+				i = (x << 6) + (y << 4) + z;
+				s1 = buf[i];
+				s2 = buf[i+8];
+				for (w = 0; w < 8; w++) {
+					r1 |= (s1 & mask);
+					r2 |= (s2 & mask);
+					s1 <<= 1;
+					s2 <<= 1;
+					mask <<= 2;
+				}
+				r = r1 | (r2 << 1);
+				i = (x << 6) + (y << 4) + (z << 1);
+				image[i] = 0xFF & r;
+				image[i+1] = (0xFF00 & r) >> 8;
+			}
+		}
+	}
+}
+
+static void wacom_set_image(struct hid_device *hdev, const char *image,
+						__u8 icon_no)
+{
+	__u8 rep_data[68];
+	__u8 p[256];
+	int ret, i, j;
+
+	for (i = 0; i < 256; i++)
+		p[i] = image[i];
+
+	rep_data[0] = WAC_CMD_ICON_START_STOP;
+	rep_data[1] = 0;
+	ret = hdev->hid_output_raw_report(hdev, rep_data, 2,
+				HID_FEATURE_REPORT);
+	if (ret < 0)
+		goto err;
+
+	rep_data[0] = WAC_CMD_ICON_TRANSFER;
+	rep_data[1] = icon_no & 0x07;
+
+	wacom_scramble(p);
+
+	for (i = 0; i < 4; i++) {
+		for (j = 0; j < 64; j++)
+			rep_data[j + 3] = p[(i << 6) + j];
+
+		rep_data[2] = i;
+		ret = hdev->hid_output_raw_report(hdev, rep_data, 67,
+					HID_FEATURE_REPORT);
+	}
+
+	rep_data[0] = WAC_CMD_ICON_START_STOP;
+	rep_data[1] = 0;
+
+	ret = hdev->hid_output_raw_report(hdev, rep_data, 2,
+				HID_FEATURE_REPORT);
+
+err:
+	return;
+}
+
 static void wacom_leds_set_brightness(struct led_classdev *led_dev,
 						enum led_brightness value)
 {
@@ -91,7 +177,10 @@ static void wacom_leds_set_brightness(struct led_classdev *led_dev,
 	if (buf) {
 		buf[0] = WAC_CMD_LED_CONTROL;
 		buf[1] = led;
-		buf[2] = value;
+		buf[2] = value >> 2;
+		buf[3] = value;
+		/* use fixed brightness for OLEDs */
+		buf[4] = 0x08;
 		hdev->hid_output_raw_report(hdev, buf, 9, HID_FEATURE_REPORT);
 		kfree(buf);
 	}
@@ -317,6 +406,34 @@ static ssize_t wacom_store_speed(struct device *dev,
 static DEVICE_ATTR(speed, S_IRUGO | S_IWUSR | S_IWGRP,
 		wacom_show_speed, wacom_store_speed);
 
+#define WACOM_STORE(OLED_ID)						\
+static ssize_t wacom_oled##OLED_ID##_store(struct device *dev,		\
+				struct device_attribute *attr,		\
+				const char *buf, size_t count)		\
+{									\
+	struct hid_device *hdev = container_of(dev, struct hid_device,	\
+				dev);					\
+									\
+	if (count != 256)						\
+		return -EINVAL;						\
+									\
+	wacom_set_image(hdev, buf, OLED_ID);				\
+									\
+	return count;							\
+}									\
+									\
+static DEVICE_ATTR(oled##OLED_ID##_img, S_IWUSR | S_IWGRP, NULL,	\
+				wacom_oled##OLED_ID##_store)
+
+WACOM_STORE(0);
+WACOM_STORE(1);
+WACOM_STORE(2);
+WACOM_STORE(3);
+WACOM_STORE(4);
+WACOM_STORE(5);
+WACOM_STORE(6);
+WACOM_STORE(7);
+
 static int wacom_gr_parse_report(struct hid_device *hdev,
 			struct wacom_data *wdata,
 			struct input_dev *input, unsigned char *data)
@@ -717,17 +834,33 @@ static int wacom_probe(struct hid_device *hdev,
 		hid_warn(hdev,
 			 "can't create sysfs speed attribute err: %d\n", ret);
 
+#define OLED_INIT(OLED_ID)						\
+	do {								\
+		ret = device_create_file(&hdev->dev,			\
+				&dev_attr_oled##OLED_ID##_img);		\
+		if (ret)						\
+			hid_warn(hdev,					\
+			 "can't create sysfs oled attribute, err: %d\n", ret);\
+	} while (0)
+
+OLED_INIT(0);
+OLED_INIT(1);
+OLED_INIT(2);
+OLED_INIT(3);
+OLED_INIT(4);
+OLED_INIT(5);
+OLED_INIT(6);
+OLED_INIT(7);
+
 	wdata->features = 0;
 	wacom_set_features(hdev, 1);
 
 	if (hdev->product == USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH) {
 		sprintf(hdev->name, "%s", "Wacom Intuos4 WL");
 		ret = wacom_initialize_leds(hdev);
-		if (ret) {
+		if (ret)
 			hid_warn(hdev,
 				 "can't create led attribute, err: %d\n", ret);
-			goto destroy_leds;
-		}
 	}
 
 	wdata->battery.properties = wacom_battery_props;
@@ -740,8 +873,8 @@ static int wacom_probe(struct hid_device *hdev,
 
 	ret = power_supply_register(&hdev->dev, &wdata->battery);
 	if (ret) {
-		hid_warn(hdev, "can't create sysfs battery attribute, err: %d\n",
-			 ret);
+		hid_err(hdev, "can't create sysfs battery attribute, err: %d\n",
+			ret);
 		goto err_battery;
 	}
 
@@ -756,8 +889,8 @@ static int wacom_probe(struct hid_device *hdev,
 
 	ret = power_supply_register(&hdev->dev, &wdata->ac);
 	if (ret) {
-		hid_warn(hdev,
-			 "can't create ac battery attribute, err: %d\n", ret);
+		hid_err(hdev,
+			"can't create ac battery attribute, err: %d\n", ret);
 		goto err_ac;
 	}
 
@@ -767,10 +900,17 @@ static int wacom_probe(struct hid_device *hdev,
 err_ac:
 	power_supply_unregister(&wdata->battery);
 err_battery:
+	wacom_destroy_leds(hdev);
+	device_remove_file(&hdev->dev, &dev_attr_oled0_img);
+	device_remove_file(&hdev->dev, &dev_attr_oled1_img);
+	device_remove_file(&hdev->dev, &dev_attr_oled2_img);
+	device_remove_file(&hdev->dev, &dev_attr_oled3_img);
+	device_remove_file(&hdev->dev, &dev_attr_oled4_img);
+	device_remove_file(&hdev->dev, &dev_attr_oled5_img);
+	device_remove_file(&hdev->dev, &dev_attr_oled6_img);
+	device_remove_file(&hdev->dev, &dev_attr_oled7_img);
 	device_remove_file(&hdev->dev, &dev_attr_speed);
 	hid_hw_stop(hdev);
-destroy_leds:
-	wacom_destroy_leds(hdev);
 err_free:
 	kfree(wdata);
 	return ret;
@@ -781,6 +921,14 @@ static void wacom_remove(struct hid_device *hdev)
 	struct wacom_data *wdata = hid_get_drvdata(hdev);
 
 	wacom_destroy_leds(hdev);
+	device_remove_file(&hdev->dev, &dev_attr_oled0_img);
+	device_remove_file(&hdev->dev, &dev_attr_oled1_img);
+	device_remove_file(&hdev->dev, &dev_attr_oled2_img);
+	device_remove_file(&hdev->dev, &dev_attr_oled3_img);
+	device_remove_file(&hdev->dev, &dev_attr_oled4_img);
+	device_remove_file(&hdev->dev, &dev_attr_oled5_img);
+	device_remove_file(&hdev->dev, &dev_attr_oled6_img);
+	device_remove_file(&hdev->dev, &dev_attr_oled7_img);
 	device_remove_file(&hdev->dev, &dev_attr_speed);
 	hid_hw_stop(hdev);
 
diff --git a/drivers/hid/hid-waltop.c b/drivers/hid/hid-waltop.c
index 745e4e9..bb536ab 100644
--- a/drivers/hid/hid-waltop.c
+++ b/drivers/hid/hid-waltop.c
@@ -638,28 +638,6 @@ static __u8 sirius_battery_free_tablet_rdesc_fixed[] = {
 	0xC0                /*  End Collection                      */
 };
 
-static int waltop_probe(struct hid_device *hdev,
-			const struct hid_device_id *id)
-{
-	int ret;
-
-	ret = hid_parse(hdev);
-	if (ret) {
-		hid_err(hdev, "parse failed\n");
-		goto err;
-	}
-
-	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
-	if (ret) {
-		hid_err(hdev, "hw start failed\n");
-		goto err;
-	}
-
-	return 0;
-err:
-	return ret;
-}
-
 static __u8 *waltop_report_fixup(struct hid_device *hdev, __u8 *rdesc,
 		unsigned int *rsize)
 {
@@ -776,11 +754,6 @@ static int waltop_raw_event(struct hid_device *hdev, struct hid_report *report,
 	return 0;
 }
 
-static void waltop_remove(struct hid_device *hdev)
-{
-	hid_hw_stop(hdev);
-}
-
 static const struct hid_device_id waltop_devices[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP,
 				USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH) },
@@ -803,10 +776,8 @@ MODULE_DEVICE_TABLE(hid, waltop_devices);
 static struct hid_driver waltop_driver = {
 	.name = "waltop",
 	.id_table = waltop_devices,
-	.probe = waltop_probe,
 	.report_fixup = waltop_report_fixup,
 	.raw_event = waltop_raw_event,
-	.remove = waltop_remove,
 };
 
 static int __init waltop_init(void)
diff --git a/drivers/hid/hid-wiimote-ext.c b/drivers/hid/hid-wiimote-ext.c
index 0a1805c..36260ba 100644
--- a/drivers/hid/hid-wiimote-ext.c
+++ b/drivers/hid/hid-wiimote-ext.c
@@ -28,12 +28,14 @@ struct wiimote_ext {
 	bool mp_plugged;
 	bool motionp;
 	__u8 ext_type;
+	__u16 calib[4][3];
 };
 
 enum wiiext_type {
 	WIIEXT_NONE,		/* placeholder */
 	WIIEXT_CLASSIC,		/* Nintendo classic controller */
 	WIIEXT_NUNCHUCK,	/* Nintendo nunchuck controller */
+	WIIEXT_BALANCE_BOARD,	/* Nintendo balance board controller */
 };
 
 enum wiiext_keys {
@@ -126,6 +128,7 @@ error:
 static __u8 ext_read(struct wiimote_ext *ext)
 {
 	ssize_t ret;
+	__u8 buf[24], i, j, offs = 0;
 	__u8 rmem[2], wmem;
 	__u8 type = WIIEXT_NONE;
 
@@ -151,6 +154,28 @@ static __u8 ext_read(struct wiimote_ext *ext)
 			type = WIIEXT_NUNCHUCK;
 		else if (rmem[0] == 0x01 && rmem[1] == 0x01)
 			type = WIIEXT_CLASSIC;
+		else if (rmem[0] == 0x04 && rmem[1] == 0x02)
+			type = WIIEXT_BALANCE_BOARD;
+	}
+
+	/* get balance board calibration data */
+	if (type == WIIEXT_BALANCE_BOARD) {
+		ret = wiimote_cmd_read(ext->wdata, 0xa40024, buf, 12);
+		ret += wiimote_cmd_read(ext->wdata, 0xa40024 + 12,
+					buf + 12, 12);
+
+		if (ret != 24) {
+			type = WIIEXT_NONE;
+		} else {
+			for (i = 0; i < 3; i++) {
+				for (j = 0; j < 4; j++) {
+					ext->calib[j][i] = buf[offs];
+					ext->calib[j][i] <<= 8;
+					ext->calib[j][i] |= buf[offs + 1];
+					offs += 2;
+				}
+			}
+		}
 	}
 
 	wiimote_cmd_release(ext->wdata);
@@ -204,7 +229,7 @@ static void wiiext_worker(struct work_struct *work)
 /* schedule work only once, otherwise mark for reschedule */
 static void wiiext_schedule(struct wiimote_ext *ext)
 {
-	queue_work(system_nrt_wq, &ext->worker);
+	schedule_work(&ext->worker);
 }
 
 /*
@@ -509,6 +534,70 @@ static void handler_classic(struct wiimote_ext *ext, const __u8 *payload)
 	input_sync(ext->input);
 }
 
+static void handler_balance_board(struct wiimote_ext *ext, const __u8 *payload)
+{
+	__s32 val[4], tmp;
+	unsigned int i;
+
+	/*   Byte |  8  7  6  5  4  3  2  1  |
+	 *   -----+--------------------------+
+	 *    1   |    Top Right <15:8>      |
+	 *    2   |    Top Right  <7:0>      |
+	 *   -----+--------------------------+
+	 *    3   | Bottom Right <15:8>      |
+	 *    4   | Bottom Right  <7:0>      |
+	 *   -----+--------------------------+
+	 *    5   |     Top Left <15:8>      |
+	 *    6   |     Top Left  <7:0>      |
+	 *   -----+--------------------------+
+	 *    7   |  Bottom Left <15:8>      |
+	 *    8   |  Bottom Left  <7:0>      |
+	 *   -----+--------------------------+
+	 *
+	 * These values represent the weight-measurements of the Wii-balance
+	 * board with 16bit precision.
+	 *
+	 * The balance-board is never reported interleaved with motionp.
+	 */
+
+	val[0] = payload[0];
+	val[0] <<= 8;
+	val[0] |= payload[1];
+
+	val[1] = payload[2];
+	val[1] <<= 8;
+	val[1] |= payload[3];
+
+	val[2] = payload[4];
+	val[2] <<= 8;
+	val[2] |= payload[5];
+
+	val[3] = payload[6];
+	val[3] <<= 8;
+	val[3] |= payload[7];
+
+	/* apply calibration data */
+	for (i = 0; i < 4; i++) {
+		if (val[i] < ext->calib[i][1]) {
+			tmp = val[i] - ext->calib[i][0];
+			tmp *= 1700;
+			tmp /= ext->calib[i][1] - ext->calib[i][0];
+		} else {
+			tmp = val[i] - ext->calib[i][1];
+			tmp *= 1700;
+			tmp /= ext->calib[i][2] - ext->calib[i][1] + 1700;
+		}
+		val[i] = tmp;
+	}
+
+	input_report_abs(ext->input, ABS_HAT0X, val[0]);
+	input_report_abs(ext->input, ABS_HAT0Y, val[1]);
+	input_report_abs(ext->input, ABS_HAT1X, val[2]);
+	input_report_abs(ext->input, ABS_HAT1Y, val[3]);
+
+	input_sync(ext->input);
+}
+
 /* call this with state.lock spinlock held */
 void wiiext_handle(struct wiimote_data *wdata, const __u8 *payload)
 {
@@ -523,6 +612,8 @@ void wiiext_handle(struct wiimote_data *wdata, const __u8 *payload)
 		handler_nunchuck(ext, payload);
 	} else if (ext->ext_type == WIIEXT_CLASSIC) {
 		handler_classic(ext, payload);
+	} else if (ext->ext_type == WIIEXT_BALANCE_BOARD) {
+		handler_balance_board(ext, payload);
 	}
 }
 
@@ -551,6 +642,11 @@ static ssize_t wiiext_show(struct device *dev, struct device_attribute *attr,
 			return sprintf(buf, "motionp+classic\n");
 		else
 			return sprintf(buf, "classic\n");
+	} else if (type == WIIEXT_BALANCE_BOARD) {
+		if (motionp)
+			return sprintf(buf, "motionp+balanceboard\n");
+		else
+			return sprintf(buf, "balanceboard\n");
 	} else {
 		if (motionp)
 			return sprintf(buf, "motionp\n");
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c
index 3b6f7bf..7c47fc3 100644
--- a/drivers/hid/hidraw.c
+++ b/drivers/hid/hidraw.c
@@ -559,21 +559,28 @@ int __init hidraw_init(void)
 
 	if (result < 0) {
 		pr_warn("can't get major number\n");
-		result = 0;
 		goto out;
 	}
 
 	hidraw_class = class_create(THIS_MODULE, "hidraw");
 	if (IS_ERR(hidraw_class)) {
 		result = PTR_ERR(hidraw_class);
-		unregister_chrdev(hidraw_major, "hidraw");
-		goto out;
+		goto error_cdev;
 	}
 
         cdev_init(&hidraw_cdev, &hidraw_ops);
-        cdev_add(&hidraw_cdev, dev_id, HIDRAW_MAX_DEVICES);
+	result = cdev_add(&hidraw_cdev, dev_id, HIDRAW_MAX_DEVICES);
+	if (result < 0)
+		goto error_class;
+
 out:
 	return result;
+
+error_class:
+	class_destroy(hidraw_class);
+error_cdev:
+	unregister_chrdev_region(dev_id, HIDRAW_MAX_DEVICES);
+	goto out;
 }
 
 void hidraw_exit(void)
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
index 991e85c..11c7932 100644
--- a/drivers/hid/usbhid/hid-quirks.c
+++ b/drivers/hid/usbhid/hid-quirks.c
@@ -70,12 +70,13 @@ static const struct hid_blacklist {
 	{ USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_AXIS_295, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET },
+	{ USB_VENDOR_ID_FREESCALE, USB_DEVICE_ID_FREESCALE_MX28, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN, HID_QUIRK_NO_INIT_REPORTS },
 	{ USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN1, HID_QUIRK_NO_INIT_REPORTS },
 	{ USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN2, HID_QUIRK_NO_INIT_REPORTS },
 	{ USB_VENDOR_ID_PRODIGE, USB_DEVICE_ID_PRODIGE_CORDLESS, HID_QUIRK_NOGET },
-	{ USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN, HID_QUIRK_NOGET },
+	{ USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_SENNHEISER, USB_DEVICE_ID_SENNHEISER_BTD500USB, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET },
diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c
index 86f8885..3648f8f 100644
--- a/drivers/hv/hv.c
+++ b/drivers/hv/hv.c
@@ -26,6 +26,7 @@
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/hyperv.h>
+#include <linux/version.h>
 #include <asm/hyperv.h>
 #include "hyperv_vmbus.h"
 
@@ -38,28 +39,6 @@ struct hv_context hv_context = {
 };
 
 /*
- * query_hypervisor_presence
- * - Query the cpuid for presence of windows hypervisor
- */
-static int query_hypervisor_presence(void)
-{
-	unsigned int eax;
-	unsigned int ebx;
-	unsigned int ecx;
-	unsigned int edx;
-	unsigned int op;
-
-	eax = 0;
-	ebx = 0;
-	ecx = 0;
-	edx = 0;
-	op = HVCPUID_VERSION_FEATURES;
-	cpuid(op, &eax, &ebx, &ecx, &edx);
-
-	return ecx & HV_PRESENT_BIT;
-}
-
-/*
  * query_hypervisor_info - Get version info of the windows hypervisor
  */
 static int query_hypervisor_info(void)
@@ -159,14 +138,13 @@ int hv_init(void)
 	memset(hv_context.synic_message_page, 0,
 	       sizeof(void *) * NR_CPUS);
 
-	if (!query_hypervisor_presence())
-		goto cleanup;
-
 	max_leaf = query_hypervisor_info();
 
-	/* Write our OS info */
-	wrmsrl(HV_X64_MSR_GUEST_OS_ID, HV_LINUX_GUEST_ID);
-	hv_context.guestid = HV_LINUX_GUEST_ID;
+	/*
+	 * Write our OS ID.
+	 */
+	hv_context.guestid = generate_guest_id(0, LINUX_VERSION_CODE, 0);
+	wrmsrl(HV_X64_MSR_GUEST_OS_ID, hv_context.guestid);
 
 	/* See if the hypercall page is already set */
 	rdmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
diff --git a/drivers/hv/hv_kvp.c b/drivers/hv/hv_kvp.c
index 0012eed..ed50e9e 100644
--- a/drivers/hv/hv_kvp.c
+++ b/drivers/hv/hv_kvp.c
@@ -48,13 +48,24 @@ static struct {
 	void *kvp_context; /* for the channel callback */
 } kvp_transaction;
 
+/*
+ * Before we can accept KVP messages from the host, we need
+ * to handshake with the user level daemon. This state tracks
+ * if we are in the handshake phase.
+ */
+static bool in_hand_shake = true;
+
+/*
+ * This state maintains the version number registered by the daemon.
+ */
+static int dm_reg_value;
+
 static void kvp_send_key(struct work_struct *dummy);
 
-#define TIMEOUT_FIRED 1
 
-static void kvp_respond_to_host(char *key, char *value, int error);
+static void kvp_respond_to_host(struct hv_kvp_msg *msg, int error);
 static void kvp_work_func(struct work_struct *dummy);
-static void kvp_register(void);
+static void kvp_register(int);
 
 static DECLARE_DELAYED_WORK(kvp_work, kvp_work_func);
 static DECLARE_WORK(kvp_sendkey_work, kvp_send_key);
@@ -68,7 +79,7 @@ static u8 *recv_buffer;
  */
 
 static void
-kvp_register(void)
+kvp_register(int reg_value)
 {
 
 	struct cn_msg *msg;
@@ -83,7 +94,7 @@ kvp_register(void)
 		msg->id.idx =  CN_KVP_IDX;
 		msg->id.val = CN_KVP_VAL;
 
-		kvp_msg->kvp_hdr.operation = KVP_OP_REGISTER;
+		kvp_msg->kvp_hdr.operation = reg_value;
 		strcpy(version, HV_DRV_VERSION);
 		msg->len = sizeof(struct hv_kvp_msg);
 		cn_netlink_send(msg, 0, GFP_ATOMIC);
@@ -97,9 +108,43 @@ kvp_work_func(struct work_struct *dummy)
 	 * If the timer fires, the user-mode component has not responded;
 	 * process the pending transaction.
 	 */
-	kvp_respond_to_host("Unknown key", "Guest timed out", TIMEOUT_FIRED);
+	kvp_respond_to_host(NULL, HV_E_FAIL);
+}
+
+static int kvp_handle_handshake(struct hv_kvp_msg *msg)
+{
+	int ret = 1;
+
+	switch (msg->kvp_hdr.operation) {
+	case KVP_OP_REGISTER:
+		dm_reg_value = KVP_OP_REGISTER;
+		pr_info("KVP: IP injection functionality not available\n");
+		pr_info("KVP: Upgrade the KVP daemon\n");
+		break;
+	case KVP_OP_REGISTER1:
+		dm_reg_value = KVP_OP_REGISTER1;
+		break;
+	default:
+		pr_info("KVP: incompatible daemon\n");
+		pr_info("KVP: KVP version: %d, Daemon version: %d\n",
+			KVP_OP_REGISTER1, msg->kvp_hdr.operation);
+		ret = 0;
+	}
+
+	if (ret) {
+		/*
+		 * We have a compatible daemon; complete the handshake.
+		 */
+		pr_info("KVP: user-mode registering done.\n");
+		kvp_register(dm_reg_value);
+		kvp_transaction.active = false;
+		if (kvp_transaction.kvp_context)
+			hv_kvp_onchannelcallback(kvp_transaction.kvp_context);
+	}
+	return ret;
 }
 
+
 /*
  * Callback when data is received from user mode.
  */
@@ -109,29 +154,165 @@ kvp_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
 {
 	struct hv_kvp_msg *message;
 	struct hv_kvp_msg_enumerate *data;
+	int	error = 0;
 
 	message = (struct hv_kvp_msg *)msg->data;
-	switch (message->kvp_hdr.operation) {
+
+	/*
+	 * If we are negotiating the version information
+	 * with the daemon; handle that first.
+	 */
+
+	if (in_hand_shake) {
+		if (kvp_handle_handshake(message))
+			in_hand_shake = false;
+		return;
+	}
+
+	/*
+	 * Based on the version of the daemon, we propagate errors from the
+	 * daemon differently.
+	 */
+
+	data = &message->body.kvp_enum_data;
+
+	switch (dm_reg_value) {
 	case KVP_OP_REGISTER:
-		pr_info("KVP: user-mode registering done.\n");
-		kvp_register();
-		kvp_transaction.active = false;
-		hv_kvp_onchannelcallback(kvp_transaction.kvp_context);
+		/*
+		 * Null string is used to pass back error condition.
+		 */
+		if (data->data.key[0] == 0)
+			error = HV_S_CONT;
 		break;
 
-	default:
-		data = &message->body.kvp_enum_data;
+	case KVP_OP_REGISTER1:
 		/*
-		 * Complete the transaction by forwarding the key value
-		 * to the host. But first, cancel the timeout.
+		 * We use the message header information from
+		 * the user level daemon to transmit errors.
 		 */
-		if (cancel_delayed_work_sync(&kvp_work))
-			kvp_respond_to_host(data->data.key,
-					 data->data.value,
-					!strlen(data->data.key));
+		error = message->error;
+		break;
+	}
+
+	/*
+	 * Complete the transaction by forwarding the key value
+	 * to the host. But first, cancel the timeout.
+	 */
+	if (cancel_delayed_work_sync(&kvp_work))
+		kvp_respond_to_host(message, error);
+}
+
+
+static int process_ob_ipinfo(void *in_msg, void *out_msg, int op)
+{
+	struct hv_kvp_msg *in = in_msg;
+	struct hv_kvp_ip_msg *out = out_msg;
+	int len;
+
+	switch (op) {
+	case KVP_OP_GET_IP_INFO:
+		/*
+		 * Transform all parameters into utf16 encoding.
+		 */
+		len = utf8s_to_utf16s((char *)in->body.kvp_ip_val.ip_addr,
+				strlen((char *)in->body.kvp_ip_val.ip_addr),
+				UTF16_HOST_ENDIAN,
+				(wchar_t *)out->kvp_ip_val.ip_addr,
+				MAX_IP_ADDR_SIZE);
+		if (len < 0)
+			return len;
+
+		len = utf8s_to_utf16s((char *)in->body.kvp_ip_val.sub_net,
+				strlen((char *)in->body.kvp_ip_val.sub_net),
+				UTF16_HOST_ENDIAN,
+				(wchar_t *)out->kvp_ip_val.sub_net,
+				MAX_IP_ADDR_SIZE);
+		if (len < 0)
+			return len;
+
+		len = utf8s_to_utf16s((char *)in->body.kvp_ip_val.gate_way,
+				strlen((char *)in->body.kvp_ip_val.gate_way),
+				UTF16_HOST_ENDIAN,
+				(wchar_t *)out->kvp_ip_val.gate_way,
+				MAX_GATEWAY_SIZE);
+		if (len < 0)
+			return len;
+
+		len = utf8s_to_utf16s((char *)in->body.kvp_ip_val.dns_addr,
+				strlen((char *)in->body.kvp_ip_val.dns_addr),
+				UTF16_HOST_ENDIAN,
+				(wchar_t *)out->kvp_ip_val.dns_addr,
+				MAX_IP_ADDR_SIZE);
+		if (len < 0)
+			return len;
+
+		len = utf8s_to_utf16s((char *)in->body.kvp_ip_val.adapter_id,
+				strlen((char *)in->body.kvp_ip_val.adapter_id),
+				UTF16_HOST_ENDIAN,
+				(wchar_t *)out->kvp_ip_val.adapter_id,
+				MAX_IP_ADDR_SIZE);
+		if (len < 0)
+			return len;
+
+		out->kvp_ip_val.dhcp_enabled =
+			in->body.kvp_ip_val.dhcp_enabled;
+		out->kvp_ip_val.addr_family =
+			in->body.kvp_ip_val.addr_family;
+	}
+
+	return 0;
+}
+
+static void process_ib_ipinfo(void *in_msg, void *out_msg, int op)
+{
+	struct hv_kvp_ip_msg *in = in_msg;
+	struct hv_kvp_msg *out = out_msg;
+
+	switch (op) {
+	case KVP_OP_SET_IP_INFO:
+		/*
+		 * Transform all parameters into utf8 encoding.
+		 */
+		utf16s_to_utf8s((wchar_t *)in->kvp_ip_val.ip_addr,
+				MAX_IP_ADDR_SIZE,
+				UTF16_LITTLE_ENDIAN,
+				(__u8 *)out->body.kvp_ip_val.ip_addr,
+				MAX_IP_ADDR_SIZE);
+
+		utf16s_to_utf8s((wchar_t *)in->kvp_ip_val.sub_net,
+				MAX_IP_ADDR_SIZE,
+				UTF16_LITTLE_ENDIAN,
+				(__u8 *)out->body.kvp_ip_val.sub_net,
+				MAX_IP_ADDR_SIZE);
+
+		utf16s_to_utf8s((wchar_t *)in->kvp_ip_val.gate_way,
+				MAX_GATEWAY_SIZE,
+				UTF16_LITTLE_ENDIAN,
+				(__u8 *)out->body.kvp_ip_val.gate_way,
+				MAX_GATEWAY_SIZE);
+
+		utf16s_to_utf8s((wchar_t *)in->kvp_ip_val.dns_addr,
+				MAX_IP_ADDR_SIZE,
+				UTF16_LITTLE_ENDIAN,
+				(__u8 *)out->body.kvp_ip_val.dns_addr,
+				MAX_IP_ADDR_SIZE);
+
+		out->body.kvp_ip_val.dhcp_enabled = in->kvp_ip_val.dhcp_enabled;
+
+	default:
+		utf16s_to_utf8s((wchar_t *)in->kvp_ip_val.adapter_id,
+				MAX_ADAPTER_ID_SIZE,
+				UTF16_LITTLE_ENDIAN,
+				(__u8 *)out->body.kvp_ip_val.adapter_id,
+				MAX_ADAPTER_ID_SIZE);
+
+		out->body.kvp_ip_val.addr_family = in->kvp_ip_val.addr_family;
 	}
 }
 
+
+
+
 static void
 kvp_send_key(struct work_struct *dummy)
 {
@@ -167,6 +348,12 @@ kvp_send_key(struct work_struct *dummy)
 	 */
 
 	switch (message->kvp_hdr.operation) {
+	case KVP_OP_SET_IP_INFO:
+		process_ib_ipinfo(in_msg, message, KVP_OP_SET_IP_INFO);
+		break;
+	case KVP_OP_GET_IP_INFO:
+		process_ib_ipinfo(in_msg, message, KVP_OP_GET_IP_INFO);
+		break;
 	case KVP_OP_SET:
 		switch (in_msg->body.kvp_set.data.value_type) {
 		case REG_SZ:
@@ -243,17 +430,19 @@ kvp_send_key(struct work_struct *dummy)
  */
 
 static void
-kvp_respond_to_host(char *key, char *value, int error)
+kvp_respond_to_host(struct hv_kvp_msg *msg_to_host, int error)
 {
 	struct hv_kvp_msg  *kvp_msg;
 	struct hv_kvp_exchg_msg_value  *kvp_data;
 	char	*key_name;
+	char	*value;
 	struct icmsg_hdr *icmsghdrp;
 	int	keylen = 0;
 	int	valuelen = 0;
 	u32	buf_len;
 	struct vmbus_channel *channel;
 	u64	req_id;
+	int ret;
 
 	/*
 	 * If a transaction is not active; log and return.
@@ -287,6 +476,7 @@ kvp_respond_to_host(char *key, char *value, int error)
 		 */
 		return;
 
+	icmsghdrp->status = error;
 
 	/*
 	 * If the error parameter is set, terminate the host's enumeration
@@ -294,20 +484,27 @@ kvp_respond_to_host(char *key, char *value, int error)
 	 */
 	if (error) {
 		/*
-		 * Something failed or the we have timedout;
-		 * terminate the current  host-side iteration.
+		 * Something failed or we have timedout;
+		 * terminate the current host-side iteration.
 		 */
-		icmsghdrp->status = HV_S_CONT;
 		goto response_done;
 	}
 
-	icmsghdrp->status = HV_S_OK;
-
 	kvp_msg = (struct hv_kvp_msg *)
 			&recv_buffer[sizeof(struct vmbuspipe_hdr) +
 			sizeof(struct icmsg_hdr)];
 
 	switch (kvp_transaction.kvp_msg->kvp_hdr.operation) {
+	case KVP_OP_GET_IP_INFO:
+		ret = process_ob_ipinfo(msg_to_host,
+				 (struct hv_kvp_ip_msg *)kvp_msg,
+				 KVP_OP_GET_IP_INFO);
+		if (ret < 0)
+			icmsghdrp->status = HV_E_FAIL;
+
+		goto response_done;
+	case KVP_OP_SET_IP_INFO:
+		goto response_done;
 	case KVP_OP_GET:
 		kvp_data = &kvp_msg->body.kvp_get.data;
 		goto copy_value;
@@ -321,7 +518,7 @@ kvp_respond_to_host(char *key, char *value, int error)
 	}
 
 	kvp_data = &kvp_msg->body.kvp_enum_data.data;
-	key_name = key;
+	key_name = msg_to_host->body.kvp_enum_data.data.key;
 
 	/*
 	 * The windows host expects the key/value pair to be encoded
@@ -335,6 +532,7 @@ kvp_respond_to_host(char *key, char *value, int error)
 	kvp_data->key_size = 2*(keylen + 1); /* utf16 encoding */
 
 copy_value:
+	value = msg_to_host->body.kvp_enum_data.data.value;
 	valuelen = utf8s_to_utf16s(value, strlen(value), UTF16_HOST_ENDIAN,
 				(wchar_t *) kvp_data->value,
 				(HV_KVP_EXCHANGE_MAX_VALUE_SIZE / 2) - 2);
@@ -387,7 +585,8 @@ void hv_kvp_onchannelcallback(void *context)
 		return;
 	}
 
-	vmbus_recvpacket(channel, recv_buffer, PAGE_SIZE, &recvlen, &requestid);
+	vmbus_recvpacket(channel, recv_buffer, PAGE_SIZE * 2, &recvlen,
+			 &requestid);
 
 	if (recvlen > 0) {
 		icmsghdrp = (struct icmsg_hdr *)&recv_buffer[
diff --git a/drivers/hv/hv_util.c b/drivers/hv/hv_util.c
index d3ac6a4..a0667de 100644
--- a/drivers/hv/hv_util.c
+++ b/drivers/hv/hv_util.c
@@ -263,7 +263,7 @@ static int util_probe(struct hv_device *dev,
 		(struct hv_util_service *)dev_id->driver_data;
 	int ret;
 
-	srv->recv_buffer = kmalloc(PAGE_SIZE, GFP_KERNEL);
+	srv->recv_buffer = kmalloc(PAGE_SIZE * 2, GFP_KERNEL);
 	if (!srv->recv_buffer)
 		return -ENOMEM;
 	if (srv->util_init) {
@@ -274,7 +274,7 @@ static int util_probe(struct hv_device *dev,
 		}
 	}
 
-	ret = vmbus_open(dev->channel, 2 * PAGE_SIZE, 2 * PAGE_SIZE, NULL, 0,
+	ret = vmbus_open(dev->channel, 4 * PAGE_SIZE, 4 * PAGE_SIZE, NULL, 0,
 			srv->util_cb, dev->channel);
 	if (ret)
 		goto error;
diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h
index 0614ff3..d8d1fad 100644
--- a/drivers/hv/hyperv_vmbus.h
+++ b/drivers/hv/hyperv_vmbus.h
@@ -410,10 +410,49 @@ enum {
 
 #define HV_PRESENT_BIT			0x80000000
 
-#define HV_LINUX_GUEST_ID_LO		0x00000000
-#define HV_LINUX_GUEST_ID_HI		2976579765
-#define HV_LINUX_GUEST_ID		(((u64)HV_LINUX_GUEST_ID_HI << 32) | \
-					   HV_LINUX_GUEST_ID_LO)
+/*
+ * The guest OS needs to register the guest ID with the hypervisor.
+ * The guest ID is a 64 bit entity and the structure of this ID is
+ * specified in the Hyper-V specification:
+ *
+ * http://msdn.microsoft.com/en-us/library/windows/hardware/ff542653%28v=vs.85%29.aspx
+ *
+ * While the current guideline does not specify how Linux guest ID(s)
+ * need to be generated, our plan is to publish the guidelines for
+ * Linux and other guest operating systems that currently are hosted
+ * on Hyper-V. The implementation here conforms to this yet
+ * unpublished guidelines.
+ *
+ *
+ * Bit(s)
+ * 63 - Indicates if the OS is Open Source or not; 1 is Open Source
+ * 62:56 - Os Type; Linux is 0x100
+ * 55:48 - Distro specific identification
+ * 47:16 - Linux kernel version number
+ * 15:0  - Distro specific identification
+ *
+ *
+ */
+
+#define HV_LINUX_VENDOR_ID		0x8100
+
+/*
+ * Generate the guest ID based on the guideline described above.
+ */
+
+static inline  __u64 generate_guest_id(__u8 d_info1, __u32 kernel_version,
+					__u16 d_info2)
+{
+	__u64 guest_id = 0;
+
+	guest_id = (((__u64)HV_LINUX_VENDOR_ID) << 48);
+	guest_id |= (((__u64)(d_info1)) << 48);
+	guest_id |= (((__u64)(kernel_version)) << 16);
+	guest_id |= ((__u64)(d_info2));
+
+	return guest_id;
+}
+
 
 #define HV_CPU_POWER_MANAGEMENT		(1 << 0)
 #define HV_RECOMMENDATIONS_MAX		4
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
index 4748086..8e1a9ec 100644
--- a/drivers/hv/vmbus_drv.c
+++ b/drivers/hv/vmbus_drv.c
@@ -34,6 +34,7 @@
 #include <linux/completion.h>
 #include <linux/hyperv.h>
 #include <asm/hyperv.h>
+#include <asm/hypervisor.h>
 #include "hyperv_vmbus.h"
 
 
@@ -146,43 +147,9 @@ static ssize_t vmbus_show_device_attr(struct device *dev,
 	get_channel_info(hv_dev, device_info);
 
 	if (!strcmp(dev_attr->attr.name, "class_id")) {
-		ret = sprintf(buf, "{%02x%02x%02x%02x-%02x%02x-%02x%02x-"
-			       "%02x%02x%02x%02x%02x%02x%02x%02x}\n",
-			       device_info->chn_type.b[3],
-			       device_info->chn_type.b[2],
-			       device_info->chn_type.b[1],
-			       device_info->chn_type.b[0],
-			       device_info->chn_type.b[5],
-			       device_info->chn_type.b[4],
-			       device_info->chn_type.b[7],
-			       device_info->chn_type.b[6],
-			       device_info->chn_type.b[8],
-			       device_info->chn_type.b[9],
-			       device_info->chn_type.b[10],
-			       device_info->chn_type.b[11],
-			       device_info->chn_type.b[12],
-			       device_info->chn_type.b[13],
-			       device_info->chn_type.b[14],
-			       device_info->chn_type.b[15]);
+		ret = sprintf(buf, "{%pUl}\n", device_info->chn_type.b);
 	} else if (!strcmp(dev_attr->attr.name, "device_id")) {
-		ret = sprintf(buf, "{%02x%02x%02x%02x-%02x%02x-%02x%02x-"
-			       "%02x%02x%02x%02x%02x%02x%02x%02x}\n",
-			       device_info->chn_instance.b[3],
-			       device_info->chn_instance.b[2],
-			       device_info->chn_instance.b[1],
-			       device_info->chn_instance.b[0],
-			       device_info->chn_instance.b[5],
-			       device_info->chn_instance.b[4],
-			       device_info->chn_instance.b[7],
-			       device_info->chn_instance.b[6],
-			       device_info->chn_instance.b[8],
-			       device_info->chn_instance.b[9],
-			       device_info->chn_instance.b[10],
-			       device_info->chn_instance.b[11],
-			       device_info->chn_instance.b[12],
-			       device_info->chn_instance.b[13],
-			       device_info->chn_instance.b[14],
-			       device_info->chn_instance.b[15]);
+		ret = sprintf(buf, "{%pUl}\n", device_info->chn_instance.b);
 	} else if (!strcmp(dev_attr->attr.name, "modalias")) {
 		print_alias_name(hv_dev, alias_name);
 		ret = sprintf(buf, "vmbus:%s\n", alias_name);
@@ -757,6 +724,9 @@ static int __init hv_acpi_init(void)
 {
 	int ret, t;
 
+	if (x86_hyper != &x86_hyper_ms_hyperv)
+		return -ENODEV;
+
 	init_completion(&probe_event);
 
 	/*
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index b0a2e4c..c4633de 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -41,7 +41,7 @@ comment "Native drivers"
 
 config SENSORS_ABITUGURU
 	tristate "Abit uGuru (rev 1 & 2)"
-	depends on X86 && DMI && EXPERIMENTAL
+	depends on X86 && DMI
 	help
 	  If you say yes here you get support for the sensor part of the first
 	  and second revision of the Abit uGuru chip. The voltage and frequency
@@ -56,7 +56,7 @@ config SENSORS_ABITUGURU
 
 config SENSORS_ABITUGURU3
 	tristate "Abit uGuru (rev 3)"
-	depends on X86 && DMI && EXPERIMENTAL
+	depends on X86 && DMI
 	help
 	  If you say yes here you get support for the sensor part of the
 	  third revision of the Abit uGuru chip. Only reading the sensors
@@ -70,7 +70,7 @@ config SENSORS_ABITUGURU3
 
 config SENSORS_AD7314
 	tristate "Analog Devices AD7314 and compatibles"
-	depends on SPI && EXPERIMENTAL
+	depends on SPI
 	help
 	  If you say yes here you get support for the Analog Devices
 	  AD7314, ADT7301 and ADT7302 temperature sensors.
@@ -80,7 +80,7 @@ config SENSORS_AD7314
 
 config SENSORS_AD7414
 	tristate "Analog Devices AD7414"
-	depends on I2C && EXPERIMENTAL
+	depends on I2C
 	help
 	  If you say yes here you get support for the Analog Devices
 	  AD7414 temperature monitoring chip.
@@ -90,7 +90,7 @@ config SENSORS_AD7414
 
 config SENSORS_AD7418
 	tristate "Analog Devices AD7416, AD7417 and AD7418"
-	depends on I2C && EXPERIMENTAL
+	depends on I2C
 	help
 	  If you say yes here you get support for the Analog Devices
 	  AD7416, AD7417 and AD7418 temperature monitoring chips.
@@ -100,7 +100,7 @@ config SENSORS_AD7418
 
 config SENSORS_ADCXX
 	tristate "National Semiconductor ADCxxxSxxx"
-	depends on SPI_MASTER && EXPERIMENTAL
+	depends on SPI_MASTER
 	help
 	  If you say yes here you get support for the National Semiconductor
 	  ADC<bb><c>S<sss> chip family, where
@@ -179,9 +179,19 @@ config SENSORS_ADM9240
 	  This driver can also be built as a module.  If so, the module
 	  will be called adm9240.
 
+config SENSORS_ADT7410
+	tristate "Analog Devices ADT7410"
+	depends on I2C
+	help
+	  If you say yes here you get support for the Analog Devices
+	  ADT7410 temperature monitoring chip.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called adt7410.
+
 config SENSORS_ADT7411
 	tristate "Analog Devices ADT7411"
-	depends on I2C && EXPERIMENTAL
+	depends on I2C
 	help
 	  If you say yes here you get support for the Analog Devices
 	  ADT7411 voltage and temperature monitoring chip.
@@ -191,7 +201,7 @@ config SENSORS_ADT7411
 
 config SENSORS_ADT7462
 	tristate "Analog Devices ADT7462"
-	depends on I2C && EXPERIMENTAL
+	depends on I2C
 	help
 	  If you say yes here you get support for the Analog Devices
 	  ADT7462 temperature monitoring chips.
@@ -201,7 +211,7 @@ config SENSORS_ADT7462
 
 config SENSORS_ADT7470
 	tristate "Analog Devices ADT7470"
-	depends on I2C && EXPERIMENTAL
+	depends on I2C
 	help
 	  If you say yes here you get support for the Analog Devices
 	  ADT7470 temperature monitoring chips.
@@ -236,7 +246,7 @@ config SENSORS_ASC7621
 
 config SENSORS_K8TEMP
 	tristate "AMD Athlon64/FX or Opteron temperature sensor"
-	depends on X86 && PCI && EXPERIMENTAL
+	depends on X86 && PCI
 	help
 	  If you say yes here you get support for the temperature
 	  sensor(s) inside your CPU. Supported is whole AMD K8
@@ -271,7 +281,7 @@ config SENSORS_FAM15H_POWER
 
 config SENSORS_ASB100
 	tristate "Asus ASB100 Bach"
-	depends on X86 && I2C && EXPERIMENTAL
+	depends on X86 && I2C
 	select HWMON_VID
 	help
 	  If you say yes here you get support for the ASB100 Bach sensor
@@ -282,7 +292,7 @@ config SENSORS_ASB100
 
 config SENSORS_ATXP1
 	tristate "Attansic ATXP1 VID controller"
-	depends on I2C && EXPERIMENTAL
+	depends on I2C
 	select HWMON_VID
 	help
 	  If you say yes here you get support for the Attansic ATXP1 VID
@@ -324,19 +334,9 @@ config SENSORS_DA9052_ADC
 	  This driver can also be built as module. If so, the module
 	  will be called da9052-hwmon.
 
-config SENSORS_EXYNOS4_TMU
-	tristate "Temperature sensor on Samsung EXYNOS4"
-	depends on ARCH_EXYNOS4
-	help
-	  If you say yes here you get support for TMU (Thermal Management
-	  Unit) on SAMSUNG EXYNOS4 series of SoC.
-
-	  This driver can also be built as a module. If so, the module
-	  will be called exynos4-tmu.
-
 config SENSORS_I5K_AMB
 	tristate "FB-DIMM AMB temperature sensor on Intel 5000 series chipsets"
-	depends on PCI && EXPERIMENTAL
+	depends on PCI
 	help
 	  If you say yes here you get support for FB-DIMM AMB temperature
 	  monitoring chips on systems with the Intel 5000 series chipset.
@@ -445,7 +445,7 @@ config SENSORS_GPIO_FAN
 
 config SENSORS_HIH6130
 	tristate "Honeywell Humidicon HIH-6130 humidity/temperature sensor"
-	depends on I2C && EXPERIMENTAL
+	depends on I2C
 	help
 	  If you say yes here you get support for Honeywell Humidicon
 	  HIH-6130 and HIH-6131 Humidicon humidity sensors.
@@ -455,7 +455,7 @@ config SENSORS_HIH6130
 
 config SENSORS_CORETEMP
 	tristate "Intel Core/Core2/Atom temperature sensor"
-	depends on X86 && PCI && EXPERIMENTAL
+	depends on X86 && PCI
 	help
 	  If you say yes here you get support for the temperature
 	  sensor inside your CPU. Most of the family 6 CPUs
@@ -495,8 +495,8 @@ config SENSORS_IT87
 	select HWMON_VID
 	help
 	  If you say yes here you get support for ITE IT8705F, IT8712F,
-	  IT8716F, IT8718F, IT8720F, IT8721F, IT8726F, IT8728F and IT8758E
-	  sensor chips, and the SiS960 clone.
+	  IT8716F, IT8718F, IT8720F, IT8721F, IT8726F, IT8728F, IT8758E,
+	  IT8782F, and IT8783E/F sensor chips, and the SiS950 clone.
 
 	  This driver can also be built as a module.  If so, the module
 	  will be called it87.
@@ -527,7 +527,7 @@ config SENSORS_JC42
 
 config SENSORS_LINEAGE
 	tristate "Lineage Compact Power Line Power Entry Module"
-	depends on I2C && EXPERIMENTAL
+	depends on I2C
 	help
 	  If you say yes here you get support for the Lineage Compact Power Line
 	  series of DC/DC and AC/DC converters such as CP1800, CP2000AC,
@@ -550,12 +550,12 @@ config SENSORS_LM63
 	  will be called lm63.
 
 config SENSORS_LM70
-	tristate "National Semiconductor LM70 / Texas Instruments TMP121"
+	tristate "National Semiconductor LM70 and compatibles"
 	depends on SPI_MASTER
 	help
 	  If you say yes here you get support for the National Semiconductor
-	  LM70 and Texas Instruments TMP121/TMP123 digital temperature
-	  sensor chips.
+	  LM70, LM71, LM74 and Texas Instruments TMP121/TMP123 digital tempera-
+	  ture sensor chips.
 
 	  This driver can also be built as a module.  If so, the module
 	  will be called lm70.
@@ -709,7 +709,7 @@ config SENSORS_LTC4151
 
 config SENSORS_LTC4215
 	tristate "Linear Technology LTC4215"
-	depends on I2C && EXPERIMENTAL
+	depends on I2C
 	default n
 	help
 	  If you say yes here you get support for Linear Technology LTC4215
@@ -720,7 +720,7 @@ config SENSORS_LTC4215
 
 config SENSORS_LTC4245
 	tristate "Linear Technology LTC4245"
-	depends on I2C && EXPERIMENTAL
+	depends on I2C
 	default n
 	help
 	  If you say yes here you get support for Linear Technology LTC4245
@@ -731,7 +731,7 @@ config SENSORS_LTC4245
 
 config SENSORS_LTC4261
 	tristate "Linear Technology LTC4261"
-	depends on I2C && EXPERIMENTAL
+	depends on I2C
 	default n
 	help
 	  If you say yes here you get support for Linear Technology LTC4261
@@ -752,7 +752,7 @@ config SENSORS_LM95241
 
 config SENSORS_LM95245
 	tristate "National Semiconductor LM95245 sensor chip"
-	depends on I2C && EXPERIMENTAL
+	depends on I2C
 	help
 	  If you say yes here you get support for LM95245 sensor chip.
 
@@ -760,10 +760,11 @@ config SENSORS_LM95245
 	  will be called lm95245.
 
 config SENSORS_MAX1111
-	tristate "Maxim MAX1111 Multichannel, Serial 8-bit ADC chip"
+	tristate "Maxim MAX1111 Serial 8-bit ADC chip and compatibles"
 	depends on SPI_MASTER
 	help
-	  Say y here to support Maxim's MAX1111 ADC chips.
+	  Say y here to support Maxim's MAX1110, MAX1111, MAX1112, and MAX1113
+	  ADC chips.
 
 	  This driver can also be built as a module.  If so, the module
 	  will be called max1111.
@@ -795,7 +796,7 @@ config SENSORS_MAX1619
 
 config SENSORS_MAX1668
 	tristate "Maxim MAX1668 and compatibles"
-	depends on I2C && EXPERIMENTAL
+	depends on I2C
 	help
 	  If you say yes here you get support for MAX1668, MAX1989 and
 	  MAX1805 chips.
@@ -803,9 +804,18 @@ config SENSORS_MAX1668
 	  This driver can also be built as a module.  If so, the module
 	  will be called max1668.
 
+config SENSORS_MAX197
+	tristate "Maxim MAX197 and compatibles"
+	help
+	  Support for the Maxim MAX197 A/D converter.
+	  Support will include, but not be limited to, MAX197, and MAX199.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called max197.
+
 config SENSORS_MAX6639
 	tristate "Maxim MAX6639 sensor chip"
-	depends on I2C && EXPERIMENTAL
+	depends on I2C
 	help
 	  If you say yes here you get support for the MAX6639
 	  sensor chips.
@@ -815,7 +825,7 @@ config SENSORS_MAX6639
 
 config SENSORS_MAX6642
 	tristate "Maxim MAX6642 sensor chip"
-	depends on I2C && EXPERIMENTAL
+	depends on I2C
 	help
 	  If you say yes here you get support for MAX6642 sensor chip.
 	  MAX6642 is a SMBus-Compatible Remote/Local Temperature Sensor
@@ -826,7 +836,7 @@ config SENSORS_MAX6642
 
 config SENSORS_MAX6650
 	tristate "Maxim MAX6650 sensor chip"
-	depends on I2C && EXPERIMENTAL
+	depends on I2C
 	help
 	  If you say yes here you get support for the MAX6650 / MAX6651
 	  sensor chips.
@@ -835,18 +845,18 @@ config SENSORS_MAX6650
 	  will be called max6650.
 
 config SENSORS_MCP3021
-	tristate "Microchip MCP3021"
-	depends on I2C && EXPERIMENTAL
+	tristate "Microchip MCP3021 and compatibles"
+	depends on I2C
 	help
-	  If you say yes here you get support for the MCP3021 chip
-	  that is a A/D converter (ADC) with 10-bit resolution.
+	  If you say yes here you get support for MCP3021 and MCP3221.
+	  The MCP3021 is a A/D converter (ADC) with 10-bit and the MCP3221
+	  with 12-bit resolution.
 
 	  This driver can also be built as a module.  If so, the module
 	  will be called mcp3021.
 
 config SENSORS_NTC_THERMISTOR
 	tristate "NTC thermistor support"
-	depends on EXPERIMENTAL
 	help
 	  This driver supports NTC thermistors sensor reading and its
 	  interpretation. The driver can also monitor the temperature and
@@ -951,7 +961,7 @@ config SENSORS_SIS5595
 
 config SENSORS_SMM665
 	tristate "Summit Microelectronics SMM665"
-	depends on I2C && EXPERIMENTAL
+	depends on I2C
 	default n
 	help
 	  If you say yes here you get support for the hardware monitoring
@@ -966,7 +976,7 @@ config SENSORS_SMM665
 
 config SENSORS_DME1737
 	tristate "SMSC DME1737, SCH311x and compatibles"
-	depends on I2C && EXPERIMENTAL && !PPC
+	depends on I2C && !PPC
 	select HWMON_VID
 	help
 	  If you say yes here you get support for the hardware monitoring
@@ -1042,7 +1052,7 @@ config SENSORS_SMSC47M192
 
 config SENSORS_SMSC47B397
 	tristate "SMSC LPC47B397-NC"
-	depends on EXPERIMENTAL && !PPC
+	depends on !PPC
 	help
 	  If you say yes here you get support for the SMSC LPC47B397-NC
 	  sensor chip.
@@ -1116,7 +1126,7 @@ config SENSORS_ADS7871
 
 config SENSORS_AMC6821
 	tristate "Texas Instruments AMC6821"
-	depends on I2C  && EXPERIMENTAL
+	depends on I2C 
 	help
 	  If you say yes here you get support for the Texas Instruments
 	  AMC6821 hardware monitoring chips.
@@ -1125,11 +1135,11 @@ config SENSORS_AMC6821
 	  will be called amc6821.
 
 config SENSORS_INA2XX
-	tristate "Texas Instruments INA219, INA226"
-	depends on I2C && EXPERIMENTAL
+	tristate "Texas Instruments INA219 and compatibles"
+	depends on I2C
 	help
-	  If you say yes here you get support for INA219 and INA226 power
-	  monitor chips.
+	  If you say yes here you get support for INA219, INA220, INA226, and
+	  INA230 power monitor chips.
 
 	  The INA2xx driver is configured for the default configuration of
 	  the part as described in the datasheet.
@@ -1149,7 +1159,7 @@ config SENSORS_THMC50
 
 config SENSORS_TMP102
 	tristate "Texas Instruments TMP102"
-	depends on I2C && EXPERIMENTAL
+	depends on I2C
 	help
 	  If you say yes here you get support for Texas Instruments TMP102
 	  sensor chips.
@@ -1159,7 +1169,7 @@ config SENSORS_TMP102
 
 config SENSORS_TMP401
 	tristate "Texas Instruments TMP401 and compatibles"
-	depends on I2C && EXPERIMENTAL
+	depends on I2C
 	help
 	  If you say yes here you get support for Texas Instruments TMP401 and
 	  TMP411 temperature sensor chips.
@@ -1169,7 +1179,7 @@ config SENSORS_TMP401
 
 config SENSORS_TMP421
 	tristate "Texas Instruments TMP421 and compatible"
-	depends on I2C && EXPERIMENTAL
+	depends on I2C
 	help
 	  If you say yes here you get support for Texas Instruments TMP421,
 	  TMP422 and TMP423 temperature sensor chips.
@@ -1261,7 +1271,7 @@ config SENSORS_W83792D
 
 config SENSORS_W83793
 	tristate "Winbond W83793"
-	depends on I2C && EXPERIMENTAL
+	depends on I2C
 	select HWMON_VID
 	help
 	  If you say yes here you get support for the Winbond W83793
@@ -1273,7 +1283,7 @@ config SENSORS_W83793
 
 config SENSORS_W83795
 	tristate "Winbond/Nuvoton W83795G/ADG"
-	depends on I2C && EXPERIMENTAL
+	depends on I2C
 	help
 	  If you say yes here you get support for the Winbond W83795G and
 	  W83795ADG hardware monitoring chip, including manual fan speed
@@ -1284,7 +1294,7 @@ config SENSORS_W83795
 
 config SENSORS_W83795_FANCTRL
 	boolean "Include automatic fan control support (DANGEROUS)"
-	depends on SENSORS_W83795 && EXPERIMENTAL
+	depends on SENSORS_W83795
 	default n
 	help
 	  If you say yes here, support for automatic fan speed control
@@ -1301,7 +1311,7 @@ config SENSORS_W83795_FANCTRL
 
 config SENSORS_W83L785TS
 	tristate "Winbond W83L785TS-S"
-	depends on I2C && EXPERIMENTAL
+	depends on I2C
 	help
 	  If you say yes here you get support for the Winbond W83L785TS-S
 	  sensor chip, which is used on the Asus A7N8X, among other
@@ -1312,7 +1322,7 @@ config SENSORS_W83L785TS
 
 config SENSORS_W83L786NG
 	tristate "Winbond W83L786NG, W83L786NR"
-	depends on I2C && EXPERIMENTAL
+	depends on I2C
 	help
 	  If you say yes here you get support for the Winbond W83L786NG
 	  and W83L786NR sensor chips.
@@ -1427,7 +1437,7 @@ config SENSORS_ACPI_POWER
 
 config SENSORS_ATK0110
 	tristate "ASUS ATK0110"
-	depends on X86 && EXPERIMENTAL
+	depends on X86
 	help
 	  If you say yes here you get support for the ACPI hardware
 	  monitoring interface found in many ASUS motherboards. This
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 7aa9811..8d5fcb5 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -34,6 +34,7 @@ obj-$(CONFIG_SENSORS_ADM9240)	+= adm9240.o
 obj-$(CONFIG_SENSORS_ADS1015)	+= ads1015.o
 obj-$(CONFIG_SENSORS_ADS7828)	+= ads7828.o
 obj-$(CONFIG_SENSORS_ADS7871)	+= ads7871.o
+obj-$(CONFIG_SENSORS_ADT7410)	+= adt7410.o
 obj-$(CONFIG_SENSORS_ADT7411)	+= adt7411.o
 obj-$(CONFIG_SENSORS_ADT7462)	+= adt7462.o
 obj-$(CONFIG_SENSORS_ADT7470)	+= adt7470.o
@@ -49,7 +50,6 @@ obj-$(CONFIG_SENSORS_DS1621)	+= ds1621.o
 obj-$(CONFIG_SENSORS_EMC1403)	+= emc1403.o
 obj-$(CONFIG_SENSORS_EMC2103)	+= emc2103.o
 obj-$(CONFIG_SENSORS_EMC6W201)	+= emc6w201.o
-obj-$(CONFIG_SENSORS_EXYNOS4_TMU)	+= exynos4_tmu.o
 obj-$(CONFIG_SENSORS_F71805F)	+= f71805f.o
 obj-$(CONFIG_SENSORS_F71882FG)	+= f71882fg.o
 obj-$(CONFIG_SENSORS_F75375S)	+= f75375s.o
@@ -94,6 +94,7 @@ obj-$(CONFIG_SENSORS_MAX1111)	+= max1111.o
 obj-$(CONFIG_SENSORS_MAX16065)	+= max16065.o
 obj-$(CONFIG_SENSORS_MAX1619)	+= max1619.o
 obj-$(CONFIG_SENSORS_MAX1668)	+= max1668.o
+obj-$(CONFIG_SENSORS_MAX197)	+= max197.o
 obj-$(CONFIG_SENSORS_MAX6639)	+= max6639.o
 obj-$(CONFIG_SENSORS_MAX6642)	+= max6642.o
 obj-$(CONFIG_SENSORS_MAX6650)	+= max6650.o
diff --git a/drivers/hwmon/abituguru.c b/drivers/hwmon/abituguru.c
index d4419b4..78b8179 100644
--- a/drivers/hwmon/abituguru.c
+++ b/drivers/hwmon/abituguru.c
@@ -1278,7 +1278,8 @@ static int __devinit abituguru_probe(struct platform_device *pdev)
 		0x00, 0x01, 0x03, 0x04, 0x0A, 0x08, 0x0E, 0x02,
 		0x09, 0x06, 0x05, 0x0B, 0x0F, 0x0D, 0x07, 0x0C };
 
-	data = kzalloc(sizeof(struct abituguru_data), GFP_KERNEL);
+	data = devm_kzalloc(&pdev->dev, sizeof(struct abituguru_data),
+			    GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
 
@@ -1430,8 +1431,6 @@ abituguru_probe_error:
 	for (i = 0; i < ARRAY_SIZE(abituguru_sysfs_attr); i++)
 		device_remove_file(&pdev->dev,
 			&abituguru_sysfs_attr[i].dev_attr);
-	platform_set_drvdata(pdev, NULL);
-	kfree(data);
 	return res;
 }
 
@@ -1446,8 +1445,6 @@ static int __devexit abituguru_remove(struct platform_device *pdev)
 	for (i = 0; i < ARRAY_SIZE(abituguru_sysfs_attr); i++)
 		device_remove_file(&pdev->dev,
 			&abituguru_sysfs_attr[i].dev_attr);
-	platform_set_drvdata(pdev, NULL);
-	kfree(data);
 
 	return 0;
 }
diff --git a/drivers/hwmon/abituguru3.c b/drivers/hwmon/abituguru3.c
index 5d582ae..b174b8b 100644
--- a/drivers/hwmon/abituguru3.c
+++ b/drivers/hwmon/abituguru3.c
@@ -976,7 +976,8 @@ static int __devinit abituguru3_probe(struct platform_device *pdev)
 	u8 buf[2];
 	u16 id;
 
-	data = kzalloc(sizeof(struct abituguru3_data), GFP_KERNEL);
+	data = devm_kzalloc(&pdev->dev, sizeof(struct abituguru3_data),
+			    GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
 
@@ -1068,7 +1069,6 @@ abituguru3_probe_error:
 	for (i = 0; i < ARRAY_SIZE(abituguru3_sysfs_attr); i++)
 		device_remove_file(&pdev->dev,
 			&abituguru3_sysfs_attr[i].dev_attr);
-	kfree(data);
 	return res;
 }
 
@@ -1084,8 +1084,6 @@ static int __devexit abituguru3_remove(struct platform_device *pdev)
 	for (i = 0; i < ARRAY_SIZE(abituguru3_sysfs_attr); i++)
 		device_remove_file(&pdev->dev,
 			&abituguru3_sysfs_attr[i].dev_attr);
-	kfree(data);
-
 	return 0;
 }
 
diff --git a/drivers/hwmon/ad7314.c b/drivers/hwmon/ad7314.c
index f915eb1..37c01e7 100644
--- a/drivers/hwmon/ad7314.c
+++ b/drivers/hwmon/ad7314.c
@@ -112,16 +112,16 @@ static int __devinit ad7314_probe(struct spi_device *spi_dev)
 	int ret;
 	struct ad7314_data *chip;
 
-	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-	if (chip == NULL) {
-		ret = -ENOMEM;
-		goto error_ret;
-	}
+	chip = devm_kzalloc(&spi_dev->dev, sizeof(*chip), GFP_KERNEL);
+	if (chip == NULL)
+		return -ENOMEM;
+
 	dev_set_drvdata(&spi_dev->dev, chip);
 
 	ret = sysfs_create_group(&spi_dev->dev.kobj, &ad7314_group);
 	if (ret < 0)
-		goto error_free_chip;
+		return ret;
+
 	chip->hwmon_dev = hwmon_device_register(&spi_dev->dev);
 	if (IS_ERR(chip->hwmon_dev)) {
 		ret = PTR_ERR(chip->hwmon_dev);
@@ -132,9 +132,6 @@ static int __devinit ad7314_probe(struct spi_device *spi_dev)
 	return 0;
 error_remove_group:
 	sysfs_remove_group(&spi_dev->dev.kobj, &ad7314_group);
-error_free_chip:
-	kfree(chip);
-error_ret:
 	return ret;
 }
 
@@ -144,7 +141,6 @@ static int __devexit ad7314_remove(struct spi_device *spi_dev)
 
 	hwmon_device_unregister(chip->hwmon_dev);
 	sysfs_remove_group(&spi_dev->dev.kobj, &ad7314_group);
-	kfree(chip);
 
 	return 0;
 }
diff --git a/drivers/hwmon/ad7414.c b/drivers/hwmon/ad7414.c
index 06d2d60..b420fb3 100644
--- a/drivers/hwmon/ad7414.c
+++ b/drivers/hwmon/ad7414.c
@@ -185,16 +185,13 @@ static int ad7414_probe(struct i2c_client *client,
 	int err;
 
 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA |
-				     I2C_FUNC_SMBUS_READ_WORD_DATA)) {
-		err = -EOPNOTSUPP;
-		goto exit;
-	}
+				     I2C_FUNC_SMBUS_READ_WORD_DATA))
+		return -EOPNOTSUPP;
 
-	data = kzalloc(sizeof(struct ad7414_data), GFP_KERNEL);
-	if (!data) {
-		err = -ENOMEM;
-		goto exit;
-	}
+	data = devm_kzalloc(&client->dev, sizeof(struct ad7414_data),
+			    GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
 
 	i2c_set_clientdata(client, data);
 	mutex_init(&data->lock);
@@ -214,7 +211,7 @@ static int ad7414_probe(struct i2c_client *client,
 	/* Register sysfs hooks */
 	err = sysfs_create_group(&client->dev.kobj, &ad7414_group);
 	if (err)
-		goto exit_free;
+		return err;
 
 	data->hwmon_dev = hwmon_device_register(&client->dev);
 	if (IS_ERR(data->hwmon_dev)) {
@@ -226,9 +223,6 @@ static int ad7414_probe(struct i2c_client *client,
 
 exit_remove:
 	sysfs_remove_group(&client->dev.kobj, &ad7414_group);
-exit_free:
-	kfree(data);
-exit:
 	return err;
 }
 
@@ -238,7 +232,6 @@ static int __devexit ad7414_remove(struct i2c_client *client)
 
 	hwmon_device_unregister(data->hwmon_dev);
 	sysfs_remove_group(&client->dev.kobj, &ad7414_group);
-	kfree(data);
 	return 0;
 }
 
diff --git a/drivers/hwmon/ad7418.c b/drivers/hwmon/ad7418.c
index a50a6be..57d4a62 100644
--- a/drivers/hwmon/ad7418.c
+++ b/drivers/hwmon/ad7418.c
@@ -227,16 +227,13 @@ static int ad7418_probe(struct i2c_client *client,
 	int err;
 
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
-					I2C_FUNC_SMBUS_WORD_DATA)) {
-		err = -EOPNOTSUPP;
-		goto exit;
-	}
+					I2C_FUNC_SMBUS_WORD_DATA))
+		return -EOPNOTSUPP;
 
-	data = kzalloc(sizeof(struct ad7418_data), GFP_KERNEL);
-	if (!data) {
-		err = -ENOMEM;
-		goto exit;
-	}
+	data = devm_kzalloc(&client->dev, sizeof(struct ad7418_data),
+			    GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
 
 	i2c_set_clientdata(client, data);
 
@@ -268,7 +265,7 @@ static int ad7418_probe(struct i2c_client *client,
 	/* Register sysfs hooks */
 	err = sysfs_create_group(&client->dev.kobj, &data->attrs);
 	if (err)
-		goto exit_free;
+		return err;
 
 	data->hwmon_dev = hwmon_device_register(&client->dev);
 	if (IS_ERR(data->hwmon_dev)) {
@@ -280,9 +277,6 @@ static int ad7418_probe(struct i2c_client *client,
 
 exit_remove:
 	sysfs_remove_group(&client->dev.kobj, &data->attrs);
-exit_free:
-	kfree(data);
-exit:
 	return err;
 }
 
@@ -291,7 +285,6 @@ static int ad7418_remove(struct i2c_client *client)
 	struct ad7418_data *data = i2c_get_clientdata(client);
 	hwmon_device_unregister(data->hwmon_dev);
 	sysfs_remove_group(&client->dev.kobj, &data->attrs);
-	kfree(data);
 	return 0;
 }
 
diff --git a/drivers/hwmon/adcxx.c b/drivers/hwmon/adcxx.c
index a3d3183..f4c5867 100644
--- a/drivers/hwmon/adcxx.c
+++ b/drivers/hwmon/adcxx.c
@@ -141,10 +141,7 @@ static ssize_t adcxx_set_max(struct device *dev,
 static ssize_t adcxx_show_name(struct device *dev, struct device_attribute
 			      *devattr, char *buf)
 {
-	struct spi_device *spi = to_spi_device(dev);
-	struct adcxx *adc = spi_get_drvdata(spi);
-
-	return sprintf(buf, "adcxx%ds\n", adc->channels);
+	return sprintf(buf, "%s\n", to_spi_device(dev)->modalias);
 }
 
 static struct sensor_device_attribute ad_input[] = {
@@ -171,7 +168,7 @@ static int __devinit adcxx_probe(struct spi_device *spi)
 	int status;
 	int i;
 
-	adc = kzalloc(sizeof *adc, GFP_KERNEL);
+	adc = devm_kzalloc(&spi->dev, sizeof(*adc), GFP_KERNEL);
 	if (!adc)
 		return -ENOMEM;
 
@@ -208,7 +205,6 @@ out_err:
 
 	spi_set_drvdata(spi, NULL);
 	mutex_unlock(&adc->lock);
-	kfree(adc);
 	return status;
 }
 
@@ -224,7 +220,6 @@ static int __devexit adcxx_remove(struct spi_device *spi)
 
 	spi_set_drvdata(spi, NULL);
 	mutex_unlock(&adc->lock);
-	kfree(adc);
 
 	return 0;
 }
diff --git a/drivers/hwmon/adm1029.c b/drivers/hwmon/adm1029.c
index 80cc465..97f4718 100644
--- a/drivers/hwmon/adm1029.c
+++ b/drivers/hwmon/adm1029.c
@@ -342,11 +342,10 @@ static int adm1029_probe(struct i2c_client *client,
 	struct adm1029_data *data;
 	int err;
 
-	data = kzalloc(sizeof(struct adm1029_data), GFP_KERNEL);
-	if (!data) {
-		err = -ENOMEM;
-		goto exit;
-	}
+	data = devm_kzalloc(&client->dev, sizeof(struct adm1029_data),
+			    GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
 
 	i2c_set_clientdata(client, data);
 	mutex_init(&data->update_lock);
@@ -355,15 +354,13 @@ static int adm1029_probe(struct i2c_client *client,
 	 * Initialize the ADM1029 chip
 	 * Check config register
 	 */
-	if (adm1029_init_client(client) == 0) {
-		err = -ENODEV;
-		goto exit_free;
-	}
+	if (adm1029_init_client(client) == 0)
+		return -ENODEV;
 
 	/* Register sysfs hooks */
 	err = sysfs_create_group(&client->dev.kobj, &adm1029_group);
 	if (err)
-		goto exit_free;
+		return err;
 
 	data->hwmon_dev = hwmon_device_register(&client->dev);
 	if (IS_ERR(data->hwmon_dev)) {
@@ -375,9 +372,6 @@ static int adm1029_probe(struct i2c_client *client,
 
  exit_remove_files:
 	sysfs_remove_group(&client->dev.kobj, &adm1029_group);
- exit_free:
-	kfree(data);
- exit:
 	return err;
 }
 
@@ -405,7 +399,6 @@ static int adm1029_remove(struct i2c_client *client)
 	hwmon_device_unregister(data->hwmon_dev);
 	sysfs_remove_group(&client->dev.kobj, &adm1029_group);
 
-	kfree(data);
 	return 0;
 }
 
diff --git a/drivers/hwmon/adm9240.c b/drivers/hwmon/adm9240.c
index 5a78d10..8b24d1a 100644
--- a/drivers/hwmon/adm9240.c
+++ b/drivers/hwmon/adm9240.c
@@ -500,31 +500,6 @@ static ssize_t set_aout(struct device *dev,
 }
 static DEVICE_ATTR(aout_output, S_IRUGO | S_IWUSR, show_aout, set_aout);
 
-/* chassis_clear */
-static ssize_t chassis_clear_legacy(struct device *dev,
-		struct device_attribute *attr,
-		const char *buf, size_t count)
-{
-	struct i2c_client *client = to_i2c_client(dev);
-	long val;
-	int err;
-
-	err = kstrtol(buf, 10, &val);
-	if (err)
-		return err;
-
-	dev_warn(dev, "Attribute chassis_clear is deprecated, "
-		 "use intrusion0_alarm instead\n");
-
-	if (val == 1) {
-		i2c_smbus_write_byte_data(client,
-				ADM9240_REG_CHASSIS_CLEAR, 0x80);
-		dev_dbg(&client->dev, "chassis intrusion latch cleared\n");
-	}
-	return count;
-}
-static DEVICE_ATTR(chassis_clear, S_IWUSR, NULL, chassis_clear_legacy);
-
 static ssize_t chassis_clear(struct device *dev,
 		struct device_attribute *attr,
 		const char *buf, size_t count)
@@ -586,7 +561,6 @@ static struct attribute *adm9240_attributes[] = {
 	&sensor_dev_attr_fan2_alarm.dev_attr.attr,
 	&dev_attr_alarms.attr,
 	&dev_attr_aout_output.attr,
-	&dev_attr_chassis_clear.attr,
 	&sensor_dev_attr_intrusion0_alarm.dev_attr.attr,
 	&dev_attr_cpu0_vid.attr,
 	NULL
diff --git a/drivers/hwmon/ads1015.c b/drivers/hwmon/ads1015.c
index 1958f03..2798246 100644
--- a/drivers/hwmon/ads1015.c
+++ b/drivers/hwmon/ads1015.c
@@ -156,7 +156,6 @@ static int ads1015_remove(struct i2c_client *client)
 	hwmon_device_unregister(data->hwmon_dev);
 	for (k = 0; k < ADS1015_CHANNELS; ++k)
 		device_remove_file(&client->dev, &ads1015_in[k].dev_attr);
-	kfree(data);
 	return 0;
 }
 
@@ -254,11 +253,10 @@ static int ads1015_probe(struct i2c_client *client,
 	int err;
 	unsigned int k;
 
-	data = kzalloc(sizeof(struct ads1015_data), GFP_KERNEL);
-	if (!data) {
-		err = -ENOMEM;
-		goto exit;
-	}
+	data = devm_kzalloc(&client->dev, sizeof(struct ads1015_data),
+			    GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
 
 	i2c_set_clientdata(client, data);
 	mutex_init(&data->update_lock);
@@ -284,8 +282,6 @@ static int ads1015_probe(struct i2c_client *client,
 exit_remove:
 	for (k = 0; k < ADS1015_CHANNELS; ++k)
 		device_remove_file(&client->dev, &ads1015_in[k].dev_attr);
-	kfree(data);
-exit:
 	return err;
 }
 
diff --git a/drivers/hwmon/ads7828.c b/drivers/hwmon/ads7828.c
index bf3fdf4..1f9e8af 100644
--- a/drivers/hwmon/ads7828.c
+++ b/drivers/hwmon/ads7828.c
@@ -154,7 +154,6 @@ static int ads7828_remove(struct i2c_client *client)
 	struct ads7828_data *data = i2c_get_clientdata(client);
 	hwmon_device_unregister(data->hwmon_dev);
 	sysfs_remove_group(&client->dev.kobj, &ads7828_group);
-	kfree(i2c_get_clientdata(client));
 	return 0;
 }
 
@@ -217,11 +216,10 @@ static int ads7828_probe(struct i2c_client *client,
 	struct ads7828_data *data;
 	int err;
 
-	data = kzalloc(sizeof(struct ads7828_data), GFP_KERNEL);
-	if (!data) {
-		err = -ENOMEM;
-		goto exit;
-	}
+	data = devm_kzalloc(&client->dev, sizeof(struct ads7828_data),
+			    GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
 
 	i2c_set_clientdata(client, data);
 	mutex_init(&data->update_lock);
@@ -229,7 +227,7 @@ static int ads7828_probe(struct i2c_client *client,
 	/* Register sysfs hooks */
 	err = sysfs_create_group(&client->dev.kobj, &ads7828_group);
 	if (err)
-		goto exit_free;
+		return err;
 
 	data->hwmon_dev = hwmon_device_register(&client->dev);
 	if (IS_ERR(data->hwmon_dev)) {
@@ -241,9 +239,6 @@ static int ads7828_probe(struct i2c_client *client,
 
 exit_remove:
 	sysfs_remove_group(&client->dev.kobj, &ads7828_group);
-exit_free:
-	kfree(data);
-exit:
 	return err;
 }
 
diff --git a/drivers/hwmon/ads7871.c b/drivers/hwmon/ads7871.c
index 7bf4ce3..1b53aa4 100644
--- a/drivers/hwmon/ads7871.c
+++ b/drivers/hwmon/ads7871.c
@@ -198,20 +198,17 @@ static int __devinit ads7871_probe(struct spi_device *spi)
 	 * because there is no other error checking on an SPI bus
 	 * we need to make sure we really have a chip
 	 */
-	if (val != ret) {
-		err = -ENODEV;
-		goto exit;
-	}
+	if (val != ret)
+		return -ENODEV;
 
-	pdata = kzalloc(sizeof(struct ads7871_data), GFP_KERNEL);
-	if (!pdata) {
-		err = -ENOMEM;
-		goto exit;
-	}
+	pdata = devm_kzalloc(&spi->dev, sizeof(struct ads7871_data),
+			     GFP_KERNEL);
+	if (!pdata)
+		return -ENOMEM;
 
 	err = sysfs_create_group(&spi->dev.kobj, &ads7871_group);
 	if (err < 0)
-		goto error_free;
+		return err;
 
 	spi_set_drvdata(spi, pdata);
 
@@ -225,9 +222,6 @@ static int __devinit ads7871_probe(struct spi_device *spi)
 
 error_remove:
 	sysfs_remove_group(&spi->dev.kobj, &ads7871_group);
-error_free:
-	kfree(pdata);
-exit:
 	return err;
 }
 
@@ -237,7 +231,6 @@ static int __devexit ads7871_remove(struct spi_device *spi)
 
 	hwmon_device_unregister(pdata->hwmon_dev);
 	sysfs_remove_group(&spi->dev.kobj, &ads7871_group);
-	kfree(pdata);
 	return 0;
 }
 
diff --git a/drivers/hwmon/adt7410.c b/drivers/hwmon/adt7410.c
new file mode 100644
index 0000000..030c8d7
--- /dev/null
+++ b/drivers/hwmon/adt7410.c
@@ -0,0 +1,464 @@
+/*
+ * adt7410.c - Part of lm_sensors, Linux kernel modules for hardware
+ *	 monitoring
+ * This driver handles the ADT7410 and compatible digital temperature sensors.
+ * Hartmut Knaack <knaack.h@gmx.de> 2012-07-22
+ * based on lm75.c by Frodo Looijaard <frodol@dds.nl>
+ * and adt7410.c from iio-staging by Sonic Zhang <sonic.zhang@analog.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <linux/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+
+/*
+ * ADT7410 registers definition
+ */
+
+#define ADT7410_TEMPERATURE		0
+#define ADT7410_STATUS			2
+#define ADT7410_CONFIG			3
+#define ADT7410_T_ALARM_HIGH		4
+#define ADT7410_T_ALARM_LOW		6
+#define ADT7410_T_CRIT			8
+#define ADT7410_T_HYST			0xA
+
+/*
+ * ADT7410 status
+ */
+#define ADT7410_STAT_T_LOW		(1 << 4)
+#define ADT7410_STAT_T_HIGH		(1 << 5)
+#define ADT7410_STAT_T_CRIT		(1 << 6)
+#define ADT7410_STAT_NOT_RDY		(1 << 7)
+
+/*
+ * ADT7410 config
+ */
+#define ADT7410_FAULT_QUEUE_MASK	(1 << 0 | 1 << 1)
+#define ADT7410_CT_POLARITY		(1 << 2)
+#define ADT7410_INT_POLARITY		(1 << 3)
+#define ADT7410_EVENT_MODE		(1 << 4)
+#define ADT7410_MODE_MASK		(1 << 5 | 1 << 6)
+#define ADT7410_FULL			(0 << 5 | 0 << 6)
+#define ADT7410_PD			(1 << 5 | 1 << 6)
+#define ADT7410_RESOLUTION		(1 << 7)
+
+/*
+ * ADT7410 masks
+ */
+#define ADT7410_T13_VALUE_MASK			0xFFF8
+#define ADT7410_T_HYST_MASK			0xF
+
+/* straight from the datasheet */
+#define ADT7410_TEMP_MIN (-55000)
+#define ADT7410_TEMP_MAX 150000
+
+enum adt7410_type {		/* keep sorted in alphabetical order */
+	adt7410,
+};
+
+/* Addresses scanned */
+static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b,
+					I2C_CLIENT_END };
+
+static const u8 ADT7410_REG_TEMP[4] = {
+	ADT7410_TEMPERATURE,		/* input */
+	ADT7410_T_ALARM_HIGH,		/* high */
+	ADT7410_T_ALARM_LOW,		/* low */
+	ADT7410_T_CRIT,			/* critical */
+};
+
+/* Each client has this additional data */
+struct adt7410_data {
+	struct device		*hwmon_dev;
+	struct mutex		update_lock;
+	u8			config;
+	u8			oldconfig;
+	bool			valid;		/* true if registers valid */
+	unsigned long		last_updated;	/* In jiffies */
+	s16			temp[4];	/* Register values,
+						   0 = input
+						   1 = high
+						   2 = low
+						   3 = critical */
+	u8			hyst;		/* hysteresis offset */
+};
+
+/*
+ * adt7410 register access by I2C
+ */
+static int adt7410_temp_ready(struct i2c_client *client)
+{
+	int i, status;
+
+	for (i = 0; i < 6; i++) {
+		status = i2c_smbus_read_byte_data(client, ADT7410_STATUS);
+		if (status < 0)
+			return status;
+		if (!(status & ADT7410_STAT_NOT_RDY))
+			return 0;
+		msleep(60);
+	}
+	return -ETIMEDOUT;
+}
+
+static struct adt7410_data *adt7410_update_device(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct adt7410_data *data = i2c_get_clientdata(client);
+	struct adt7410_data *ret = data;
+	mutex_lock(&data->update_lock);
+
+	if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
+	    || !data->valid) {
+		int i, status;
+
+		dev_dbg(&client->dev, "Starting update\n");
+
+		status = adt7410_temp_ready(client); /* check for new value */
+		if (unlikely(status)) {
+			ret = ERR_PTR(status);
+			goto abort;
+		}
+		for (i = 0; i < ARRAY_SIZE(data->temp); i++) {
+			status = i2c_smbus_read_word_swapped(client,
+							ADT7410_REG_TEMP[i]);
+			if (unlikely(status < 0)) {
+				dev_dbg(dev,
+					"Failed to read value: reg %d, error %d\n",
+					ADT7410_REG_TEMP[i], status);
+				ret = ERR_PTR(status);
+				goto abort;
+			}
+			data->temp[i] = status;
+		}
+		status = i2c_smbus_read_byte_data(client, ADT7410_T_HYST);
+		if (unlikely(status < 0)) {
+			dev_dbg(dev,
+				"Failed to read value: reg %d, error %d\n",
+				ADT7410_T_HYST, status);
+			ret = ERR_PTR(status);
+			goto abort;
+		}
+		data->hyst = status;
+		data->last_updated = jiffies;
+		data->valid = true;
+	}
+
+abort:
+	mutex_unlock(&data->update_lock);
+	return ret;
+}
+
+static s16 ADT7410_TEMP_TO_REG(long temp)
+{
+	return DIV_ROUND_CLOSEST(SENSORS_LIMIT(temp, ADT7410_TEMP_MIN,
+					       ADT7410_TEMP_MAX) * 128, 1000);
+}
+
+static int ADT7410_REG_TO_TEMP(struct adt7410_data *data, s16 reg)
+{
+	/* in 13 bit mode, bits 0-2 are status flags - mask them out */
+	if (!(data->config & ADT7410_RESOLUTION))
+		reg &= ADT7410_T13_VALUE_MASK;
+	/*
+	 * temperature is stored in twos complement format, in steps of
+	 * 1/128°C
+	 */
+	return DIV_ROUND_CLOSEST(reg * 1000, 128);
+}
+
+/*-----------------------------------------------------------------------*/
+
+/* sysfs attributes for hwmon */
+
+static ssize_t adt7410_show_temp(struct device *dev,
+				 struct device_attribute *da, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	struct adt7410_data *data = adt7410_update_device(dev);
+
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+
+	return sprintf(buf, "%d\n", ADT7410_REG_TO_TEMP(data,
+		       data->temp[attr->index]));
+}
+
+static ssize_t adt7410_set_temp(struct device *dev,
+				struct device_attribute *da,
+				const char *buf, size_t count)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	struct i2c_client *client = to_i2c_client(dev);
+	struct adt7410_data *data = i2c_get_clientdata(client);
+	int nr = attr->index;
+	long temp;
+	int ret;
+
+	ret = kstrtol(buf, 10, &temp);
+	if (ret)
+		return ret;
+
+	mutex_lock(&data->update_lock);
+	data->temp[nr] = ADT7410_TEMP_TO_REG(temp);
+	ret = i2c_smbus_write_word_swapped(client, ADT7410_REG_TEMP[nr],
+					   data->temp[nr]);
+	if (ret)
+		count = ret;
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static ssize_t adt7410_show_t_hyst(struct device *dev,
+				   struct device_attribute *da,
+				   char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	struct adt7410_data *data;
+	int nr = attr->index;
+	int hyst;
+
+	data = adt7410_update_device(dev);
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+	hyst = (data->hyst & ADT7410_T_HYST_MASK) * 1000;
+
+	/*
+	 * hysteresis is stored as a 4 bit offset in the device, convert it
+	 * to an absolute value
+	 */
+	if (nr == 2)	/* min has positive offset, others have negative */
+		hyst = -hyst;
+	return sprintf(buf, "%d\n",
+		       ADT7410_REG_TO_TEMP(data, data->temp[nr]) - hyst);
+}
+
+static ssize_t adt7410_set_t_hyst(struct device *dev,
+				  struct device_attribute *da,
+				  const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct adt7410_data *data = i2c_get_clientdata(client);
+	int limit, ret;
+	long hyst;
+
+	ret = kstrtol(buf, 10, &hyst);
+	if (ret)
+		return ret;
+	/* convert absolute hysteresis value to a 4 bit delta value */
+	limit = ADT7410_REG_TO_TEMP(data, data->temp[1]);
+	hyst = SENSORS_LIMIT(hyst, ADT7410_TEMP_MIN, ADT7410_TEMP_MAX);
+	data->hyst = SENSORS_LIMIT(DIV_ROUND_CLOSEST(limit - hyst, 1000),
+				   0, ADT7410_T_HYST_MASK);
+	ret = i2c_smbus_write_byte_data(client, ADT7410_T_HYST, data->hyst);
+	if (ret)
+		return ret;
+
+	return count;
+}
+
+static ssize_t adt7410_show_alarm(struct device *dev,
+				  struct device_attribute *da,
+				  char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	int ret;
+
+	ret = i2c_smbus_read_byte_data(client, ADT7410_STATUS);
+	if (ret < 0)
+		return ret;
+
+	return sprintf(buf, "%d\n", !!(ret & attr->index));
+}
+
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, adt7410_show_temp, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO,
+			  adt7410_show_temp, adt7410_set_temp, 1);
+static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO,
+			  adt7410_show_temp, adt7410_set_temp, 2);
+static SENSOR_DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO,
+			  adt7410_show_temp, adt7410_set_temp, 3);
+static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO,
+			  adt7410_show_t_hyst, adt7410_set_t_hyst, 1);
+static SENSOR_DEVICE_ATTR(temp1_min_hyst, S_IRUGO,
+			  adt7410_show_t_hyst, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO,
+			  adt7410_show_t_hyst, NULL, 3);
+static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, adt7410_show_alarm,
+			  NULL, ADT7410_STAT_T_LOW);
+static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, adt7410_show_alarm,
+			  NULL, ADT7410_STAT_T_HIGH);
+static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, adt7410_show_alarm,
+			  NULL, ADT7410_STAT_T_CRIT);
+
+static struct attribute *adt7410_attributes[] = {
+	&sensor_dev_attr_temp1_input.dev_attr.attr,
+	&sensor_dev_attr_temp1_max.dev_attr.attr,
+	&sensor_dev_attr_temp1_min.dev_attr.attr,
+	&sensor_dev_attr_temp1_crit.dev_attr.attr,
+	&sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
+	&sensor_dev_attr_temp1_min_hyst.dev_attr.attr,
+	&sensor_dev_attr_temp1_crit_hyst.dev_attr.attr,
+	&sensor_dev_attr_temp1_min_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp1_crit_alarm.dev_attr.attr,
+	NULL
+};
+
+static const struct attribute_group adt7410_group = {
+	.attrs = adt7410_attributes,
+};
+
+/*-----------------------------------------------------------------------*/
+
+/* device probe and removal */
+
+static int adt7410_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
+{
+	struct adt7410_data *data;
+	int ret;
+
+	if (!i2c_check_functionality(client->adapter,
+			I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA))
+		return -ENODEV;
+
+	data = devm_kzalloc(&client->dev, sizeof(struct adt7410_data),
+			    GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	i2c_set_clientdata(client, data);
+	mutex_init(&data->update_lock);
+
+	/* configure as specified */
+	ret = i2c_smbus_read_byte_data(client, ADT7410_CONFIG);
+	if (ret < 0) {
+		dev_dbg(&client->dev, "Can't read config? %d\n", ret);
+		return ret;
+	}
+	data->oldconfig = ret;
+	/*
+	 * Set to 16 bit resolution, continous conversion and comparator mode.
+	 */
+	data->config = ret | ADT7410_FULL | ADT7410_RESOLUTION |
+			ADT7410_EVENT_MODE;
+	if (data->config != data->oldconfig) {
+		ret = i2c_smbus_write_byte_data(client, ADT7410_CONFIG,
+						data->config);
+		if (ret)
+			return ret;
+	}
+	dev_dbg(&client->dev, "Config %02x\n", data->config);
+
+	/* Register sysfs hooks */
+	ret = sysfs_create_group(&client->dev.kobj, &adt7410_group);
+	if (ret)
+		goto exit_restore;
+
+	data->hwmon_dev = hwmon_device_register(&client->dev);
+	if (IS_ERR(data->hwmon_dev)) {
+		ret = PTR_ERR(data->hwmon_dev);
+		goto exit_remove;
+	}
+
+	dev_info(&client->dev, "sensor '%s'\n", client->name);
+
+	return 0;
+
+exit_remove:
+	sysfs_remove_group(&client->dev.kobj, &adt7410_group);
+exit_restore:
+	i2c_smbus_write_byte_data(client, ADT7410_CONFIG, data->oldconfig);
+	return ret;
+}
+
+static int adt7410_remove(struct i2c_client *client)
+{
+	struct adt7410_data *data = i2c_get_clientdata(client);
+
+	hwmon_device_unregister(data->hwmon_dev);
+	sysfs_remove_group(&client->dev.kobj, &adt7410_group);
+	if (data->oldconfig != data->config)
+		i2c_smbus_write_byte_data(client, ADT7410_CONFIG,
+					  data->oldconfig);
+	return 0;
+}
+
+static const struct i2c_device_id adt7410_ids[] = {
+	{ "adt7410", adt7410, },
+	{ /* LIST END */ }
+};
+MODULE_DEVICE_TABLE(i2c, adt7410_ids);
+
+#ifdef CONFIG_PM
+static int adt7410_suspend(struct device *dev)
+{
+	int ret;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct adt7410_data *data = i2c_get_clientdata(client);
+
+	ret = i2c_smbus_write_byte_data(client, ADT7410_CONFIG,
+					data->config | ADT7410_PD);
+	return ret;
+}
+
+static int adt7410_resume(struct device *dev)
+{
+	int ret;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct adt7410_data *data = i2c_get_clientdata(client);
+
+	ret = i2c_smbus_write_byte_data(client, ADT7410_CONFIG, data->config);
+	return ret;
+}
+
+static const struct dev_pm_ops adt7410_dev_pm_ops = {
+	.suspend	= adt7410_suspend,
+	.resume		= adt7410_resume,
+};
+#define ADT7410_DEV_PM_OPS (&adt7410_dev_pm_ops)
+#else
+#define ADT7410_DEV_PM_OPS NULL
+#endif /* CONFIG_PM */
+
+static struct i2c_driver adt7410_driver = {
+	.class		= I2C_CLASS_HWMON,
+	.driver = {
+		.name	= "adt7410",
+		.pm	= ADT7410_DEV_PM_OPS,
+	},
+	.probe		= adt7410_probe,
+	.remove		= adt7410_remove,
+	.id_table	= adt7410_ids,
+	.address_list	= normal_i2c,
+};
+
+module_i2c_driver(adt7410_driver);
+
+MODULE_AUTHOR("Hartmut Knaack");
+MODULE_DESCRIPTION("ADT7410 driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/adt7411.c b/drivers/hwmon/adt7411.c
index 71bacc5..fe72c69 100644
--- a/drivers/hwmon/adt7411.c
+++ b/drivers/hwmon/adt7411.c
@@ -283,7 +283,7 @@ static int __devinit adt7411_probe(struct i2c_client *client,
 	struct adt7411_data *data;
 	int ret;
 
-	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
 
@@ -294,14 +294,14 @@ static int __devinit adt7411_probe(struct i2c_client *client,
 	ret = adt7411_modify_bit(client, ADT7411_REG_CFG1,
 				 ADT7411_CFG1_START_MONITOR, 1);
 	if (ret < 0)
-		goto exit_free;
+		return ret;
 
 	/* force update on first occasion */
 	data->next_update = jiffies;
 
 	ret = sysfs_create_group(&client->dev.kobj, &adt7411_attr_grp);
 	if (ret)
-		goto exit_free;
+		return ret;
 
 	data->hwmon_dev = hwmon_device_register(&client->dev);
 	if (IS_ERR(data->hwmon_dev)) {
@@ -315,8 +315,6 @@ static int __devinit adt7411_probe(struct i2c_client *client,
 
  exit_remove:
 	sysfs_remove_group(&client->dev.kobj, &adt7411_attr_grp);
- exit_free:
-	kfree(data);
 	return ret;
 }
 
@@ -326,7 +324,6 @@ static int __devexit adt7411_remove(struct i2c_client *client)
 
 	hwmon_device_unregister(data->hwmon_dev);
 	sysfs_remove_group(&client->dev.kobj, &adt7411_attr_grp);
-	kfree(data);
 	return 0;
 }
 
diff --git a/drivers/hwmon/adt7462.c b/drivers/hwmon/adt7462.c
index 339269f..baee482 100644
--- a/drivers/hwmon/adt7462.c
+++ b/drivers/hwmon/adt7462.c
@@ -1931,11 +1931,10 @@ static int adt7462_probe(struct i2c_client *client,
 	struct adt7462_data *data;
 	int err;
 
-	data = kzalloc(sizeof(struct adt7462_data), GFP_KERNEL);
-	if (!data) {
-		err = -ENOMEM;
-		goto exit;
-	}
+	data = devm_kzalloc(&client->dev, sizeof(struct adt7462_data),
+			    GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
 
 	i2c_set_clientdata(client, data);
 	mutex_init(&data->lock);
@@ -1946,7 +1945,7 @@ static int adt7462_probe(struct i2c_client *client,
 	data->attrs.attrs = adt7462_attr;
 	err = sysfs_create_group(&client->dev.kobj, &data->attrs);
 	if (err)
-		goto exit_free;
+		return err;
 
 	data->hwmon_dev = hwmon_device_register(&client->dev);
 	if (IS_ERR(data->hwmon_dev)) {
@@ -1958,9 +1957,6 @@ static int adt7462_probe(struct i2c_client *client,
 
 exit_remove:
 	sysfs_remove_group(&client->dev.kobj, &data->attrs);
-exit_free:
-	kfree(data);
-exit:
 	return err;
 }
 
@@ -1970,7 +1966,6 @@ static int adt7462_remove(struct i2c_client *client)
 
 	hwmon_device_unregister(data->hwmon_dev);
 	sysfs_remove_group(&client->dev.kobj, &data->attrs);
-	kfree(data);
 	return 0;
 }
 
diff --git a/drivers/hwmon/adt7470.c b/drivers/hwmon/adt7470.c
index 54ec890..39ecb1a 100644
--- a/drivers/hwmon/adt7470.c
+++ b/drivers/hwmon/adt7470.c
@@ -1256,11 +1256,10 @@ static int adt7470_probe(struct i2c_client *client,
 	struct adt7470_data *data;
 	int err;
 
-	data = kzalloc(sizeof(struct adt7470_data), GFP_KERNEL);
-	if (!data) {
-		err = -ENOMEM;
-		goto exit;
-	}
+	data = devm_kzalloc(&client->dev, sizeof(struct adt7470_data),
+			    GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
 
 	data->num_temp_sensors = -1;
 	data->auto_update_interval = AUTO_UPDATE_INTERVAL;
@@ -1277,7 +1276,7 @@ static int adt7470_probe(struct i2c_client *client,
 	data->attrs.attrs = adt7470_attr;
 	err = sysfs_create_group(&client->dev.kobj, &data->attrs);
 	if (err)
-		goto exit_free;
+		return err;
 
 	data->hwmon_dev = hwmon_device_register(&client->dev);
 	if (IS_ERR(data->hwmon_dev)) {
@@ -1299,9 +1298,6 @@ exit_unregister:
 	hwmon_device_unregister(data->hwmon_dev);
 exit_remove:
 	sysfs_remove_group(&client->dev.kobj, &data->attrs);
-exit_free:
-	kfree(data);
-exit:
 	return err;
 }
 
@@ -1313,7 +1309,6 @@ static int adt7470_remove(struct i2c_client *client)
 	wait_for_completion(&data->auto_update_stop);
 	hwmon_device_unregister(data->hwmon_dev);
 	sysfs_remove_group(&client->dev.kobj, &data->attrs);
-	kfree(data);
 	return 0;
 }
 
diff --git a/drivers/hwmon/amc6821.c b/drivers/hwmon/amc6821.c
index f600fa1..ae482e3 100644
--- a/drivers/hwmon/amc6821.c
+++ b/drivers/hwmon/amc6821.c
@@ -862,12 +862,10 @@ static int amc6821_probe(
 	struct amc6821_data *data;
 	int err;
 
-	data = kzalloc(sizeof(struct amc6821_data), GFP_KERNEL);
-	if (!data) {
-		dev_err(&client->dev, "out of memory.\n");
+	data = devm_kzalloc(&client->dev, sizeof(struct amc6821_data),
+			    GFP_KERNEL);
+	if (!data)
 		return -ENOMEM;
-	}
-
 
 	i2c_set_clientdata(client, data);
 	mutex_init(&data->update_lock);
@@ -877,11 +875,11 @@ static int amc6821_probe(
 	 */
 	err = amc6821_init_client(client);
 	if (err)
-		goto err_free;
+		return err;
 
 	err = sysfs_create_group(&client->dev.kobj, &amc6821_attr_grp);
 	if (err)
-		goto err_free;
+		return err;
 
 	data->hwmon_dev = hwmon_device_register(&client->dev);
 	if (!IS_ERR(data->hwmon_dev))
@@ -890,8 +888,6 @@ static int amc6821_probe(
 	err = PTR_ERR(data->hwmon_dev);
 	dev_err(&client->dev, "error registering hwmon device.\n");
 	sysfs_remove_group(&client->dev.kobj, &amc6821_attr_grp);
-err_free:
-	kfree(data);
 	return err;
 }
 
@@ -902,8 +898,6 @@ static int amc6821_remove(struct i2c_client *client)
 	hwmon_device_unregister(data->hwmon_dev);
 	sysfs_remove_group(&client->dev.kobj, &amc6821_attr_grp);
 
-	kfree(data);
-
 	return 0;
 }
 
diff --git a/drivers/hwmon/asb100.c b/drivers/hwmon/asb100.c
index 4b8814d..a227be4 100644
--- a/drivers/hwmon/asb100.c
+++ b/drivers/hwmon/asb100.c
@@ -787,12 +787,10 @@ static int asb100_probe(struct i2c_client *client,
 	int err;
 	struct asb100_data *data;
 
-	data = kzalloc(sizeof(struct asb100_data), GFP_KERNEL);
-	if (!data) {
-		pr_debug("probe failed, kzalloc failed!\n");
-		err = -ENOMEM;
-		goto ERROR0;
-	}
+	data = devm_kzalloc(&client->dev, sizeof(struct asb100_data),
+			    GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
 
 	i2c_set_clientdata(client, data);
 	mutex_init(&data->lock);
@@ -801,7 +799,7 @@ static int asb100_probe(struct i2c_client *client,
 	/* Attach secondary lm75 clients */
 	err = asb100_detect_subclients(client);
 	if (err)
-		goto ERROR1;
+		return err;
 
 	/* Initialize the chip */
 	asb100_init_client(client);
@@ -829,9 +827,6 @@ ERROR4:
 ERROR3:
 	i2c_unregister_device(data->lm75[1]);
 	i2c_unregister_device(data->lm75[0]);
-ERROR1:
-	kfree(data);
-ERROR0:
 	return err;
 }
 
@@ -845,8 +840,6 @@ static int asb100_remove(struct i2c_client *client)
 	i2c_unregister_device(data->lm75[1]);
 	i2c_unregister_device(data->lm75[0]);
 
-	kfree(data);
-
 	return 0;
 }
 
diff --git a/drivers/hwmon/asus_atk0110.c b/drivers/hwmon/asus_atk0110.c
index 4ee5789..cccb0e9 100644
--- a/drivers/hwmon/asus_atk0110.c
+++ b/drivers/hwmon/asus_atk0110.c
@@ -962,7 +962,6 @@ static int atk_add_sensor(struct atk_data *data, union acpi_object *obj)
 
 	return 1;
 out:
-	kfree(sensor->acpi_name);
 	kfree(sensor);
 	return err;
 }
diff --git a/drivers/hwmon/dme1737.c b/drivers/hwmon/dme1737.c
index e7c6a19..fe0eeec 100644
--- a/drivers/hwmon/dme1737.c
+++ b/drivers/hwmon/dme1737.c
@@ -2475,11 +2475,9 @@ static int dme1737_i2c_probe(struct i2c_client *client,
 	struct device *dev = &client->dev;
 	int err;
 
-	data = kzalloc(sizeof(struct dme1737_data), GFP_KERNEL);
-	if (!data) {
-		err = -ENOMEM;
-		goto exit;
-	}
+	data = devm_kzalloc(dev, sizeof(struct dme1737_data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
 
 	i2c_set_clientdata(client, data);
 	data->type = id->driver_data;
@@ -2491,14 +2489,14 @@ static int dme1737_i2c_probe(struct i2c_client *client,
 	err = dme1737_init_device(dev);
 	if (err) {
 		dev_err(dev, "Failed to initialize device.\n");
-		goto exit_kfree;
+		return err;
 	}
 
 	/* Create sysfs files */
 	err = dme1737_create_files(dev);
 	if (err) {
 		dev_err(dev, "Failed to create sysfs files.\n");
-		goto exit_kfree;
+		return err;
 	}
 
 	/* Register device */
@@ -2513,9 +2511,6 @@ static int dme1737_i2c_probe(struct i2c_client *client,
 
 exit_remove:
 	dme1737_remove_files(dev);
-exit_kfree:
-	kfree(data);
-exit:
 	return err;
 }
 
@@ -2526,7 +2521,6 @@ static int dme1737_i2c_remove(struct i2c_client *client)
 	hwmon_device_unregister(data->hwmon_dev);
 	dme1737_remove_files(&client->dev);
 
-	kfree(data);
 	return 0;
 }
 
@@ -2645,19 +2639,16 @@ static int __devinit dme1737_isa_probe(struct platform_device *pdev)
 	int err;
 
 	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
-	if (!request_region(res->start, DME1737_EXTENT, "dme1737")) {
+	if (!devm_request_region(dev, res->start, DME1737_EXTENT, "dme1737")) {
 		dev_err(dev, "Failed to request region 0x%04x-0x%04x.\n",
 			(unsigned short)res->start,
 			(unsigned short)res->start + DME1737_EXTENT - 1);
-		err = -EBUSY;
-		goto exit;
+		return -EBUSY;
 	}
 
-	data = kzalloc(sizeof(struct dme1737_data), GFP_KERNEL);
-	if (!data) {
-		err = -ENOMEM;
-		goto exit_release_region;
-	}
+	data = devm_kzalloc(dev, sizeof(struct dme1737_data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
 
 	data->addr = res->start;
 	platform_set_drvdata(pdev, data);
@@ -2683,8 +2674,7 @@ static int __devinit dme1737_isa_probe(struct platform_device *pdev)
 			   (device == SCH5127_DEVICE)) {
 			data->type = sch5127;
 		} else {
-			err = -ENODEV;
-			goto exit_kfree;
+			return -ENODEV;
 		}
 	}
 
@@ -2703,14 +2693,14 @@ static int __devinit dme1737_isa_probe(struct platform_device *pdev)
 	err = dme1737_init_device(dev);
 	if (err) {
 		dev_err(dev, "Failed to initialize device.\n");
-		goto exit_kfree;
+		return err;
 	}
 
 	/* Create sysfs files */
 	err = dme1737_create_files(dev);
 	if (err) {
 		dev_err(dev, "Failed to create sysfs files.\n");
-		goto exit_kfree;
+		return err;
 	}
 
 	/* Register device */
@@ -2725,12 +2715,6 @@ static int __devinit dme1737_isa_probe(struct platform_device *pdev)
 
 exit_remove_files:
 	dme1737_remove_files(dev);
-exit_kfree:
-	platform_set_drvdata(pdev, NULL);
-	kfree(data);
-exit_release_region:
-	release_region(res->start, DME1737_EXTENT);
-exit:
 	return err;
 }
 
@@ -2740,9 +2724,6 @@ static int __devexit dme1737_isa_remove(struct platform_device *pdev)
 
 	hwmon_device_unregister(data->hwmon_dev);
 	dme1737_remove_files(&pdev->dev);
-	release_region(data->addr, DME1737_EXTENT);
-	platform_set_drvdata(pdev, NULL);
-	kfree(data);
 
 	return 0;
 }
diff --git a/drivers/hwmon/ds620.c b/drivers/hwmon/ds620.c
index 50663ef..f1d6b42 100644
--- a/drivers/hwmon/ds620.c
+++ b/drivers/hwmon/ds620.c
@@ -232,11 +232,10 @@ static int ds620_probe(struct i2c_client *client,
 	struct ds620_data *data;
 	int err;
 
-	data = kzalloc(sizeof(struct ds620_data), GFP_KERNEL);
-	if (!data) {
-		err = -ENOMEM;
-		goto exit;
-	}
+	data = devm_kzalloc(&client->dev, sizeof(struct ds620_data),
+			    GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
 
 	i2c_set_clientdata(client, data);
 	mutex_init(&data->update_lock);
@@ -247,7 +246,7 @@ static int ds620_probe(struct i2c_client *client,
 	/* Register sysfs hooks */
 	err = sysfs_create_group(&client->dev.kobj, &ds620_group);
 	if (err)
-		goto exit_free;
+		return err;
 
 	data->hwmon_dev = hwmon_device_register(&client->dev);
 	if (IS_ERR(data->hwmon_dev)) {
@@ -261,9 +260,6 @@ static int ds620_probe(struct i2c_client *client,
 
 exit_remove_files:
 	sysfs_remove_group(&client->dev.kobj, &ds620_group);
-exit_free:
-	kfree(data);
-exit:
 	return err;
 }
 
@@ -274,8 +270,6 @@ static int ds620_remove(struct i2c_client *client)
 	hwmon_device_unregister(data->hwmon_dev);
 	sysfs_remove_group(&client->dev.kobj, &ds620_group);
 
-	kfree(data);
-
 	return 0;
 }
 
diff --git a/drivers/hwmon/emc1403.c b/drivers/hwmon/emc1403.c
index 149dcb0..68ab94b 100644
--- a/drivers/hwmon/emc1403.c
+++ b/drivers/hwmon/emc1403.c
@@ -306,11 +306,10 @@ static int emc1403_probe(struct i2c_client *client,
 	int res;
 	struct thermal_data *data;
 
-	data = kzalloc(sizeof(struct thermal_data), GFP_KERNEL);
-	if (data == NULL) {
-		dev_warn(&client->dev, "out of memory");
+	data = devm_kzalloc(&client->dev, sizeof(struct thermal_data),
+			    GFP_KERNEL);
+	if (data == NULL)
 		return -ENOMEM;
-	}
 
 	i2c_set_clientdata(client, data);
 	mutex_init(&data->mutex);
@@ -319,21 +318,19 @@ static int emc1403_probe(struct i2c_client *client,
 	res = sysfs_create_group(&client->dev.kobj, &m_thermal_gr);
 	if (res) {
 		dev_warn(&client->dev, "create group failed\n");
-		goto thermal_error1;
+		return res;
 	}
 	data->hwmon_dev = hwmon_device_register(&client->dev);
 	if (IS_ERR(data->hwmon_dev)) {
 		res = PTR_ERR(data->hwmon_dev);
 		dev_warn(&client->dev, "register hwmon dev failed\n");
-		goto thermal_error2;
+		goto thermal_error;
 	}
 	dev_info(&client->dev, "EMC1403 Thermal chip found\n");
-	return res;
+	return 0;
 
-thermal_error2:
+thermal_error:
 	sysfs_remove_group(&client->dev.kobj, &m_thermal_gr);
-thermal_error1:
-	kfree(data);
 	return res;
 }
 
@@ -343,7 +340,6 @@ static int emc1403_remove(struct i2c_client *client)
 
 	hwmon_device_unregister(data->hwmon_dev);
 	sysfs_remove_group(&client->dev.kobj, &m_thermal_gr);
-	kfree(data);
 	return 0;
 }
 
diff --git a/drivers/hwmon/emc2103.c b/drivers/hwmon/emc2103.c
index 7bb8e88..77f434c 100644
--- a/drivers/hwmon/emc2103.c
+++ b/drivers/hwmon/emc2103.c
@@ -590,7 +590,8 @@ emc2103_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 		return -EIO;
 
-	data = kzalloc(sizeof(struct emc2103_data), GFP_KERNEL);
+	data = devm_kzalloc(&client->dev, sizeof(struct emc2103_data),
+			    GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
 
@@ -608,7 +609,7 @@ emc2103_probe(struct i2c_client *client, const struct i2c_device_id *id)
 		if (status < 0) {
 			dev_dbg(&client->dev, "reg 0x%02x, err %d\n", REG_CONF1,
 				status);
-			goto exit_free;
+			return status;
 		}
 
 		/* detect current state of hardware */
@@ -631,7 +632,7 @@ emc2103_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	/* Register sysfs hooks */
 	status = sysfs_create_group(&client->dev.kobj, &emc2103_group);
 	if (status)
-		goto exit_free;
+		return status;
 
 	if (data->temp_count >= 3) {
 		status = sysfs_create_group(&client->dev.kobj,
@@ -666,8 +667,6 @@ exit_remove_temp3:
 		sysfs_remove_group(&client->dev.kobj, &emc2103_temp3_group);
 exit_remove:
 	sysfs_remove_group(&client->dev.kobj, &emc2103_group);
-exit_free:
-	kfree(data);
 	return status;
 }
 
@@ -685,7 +684,6 @@ static int emc2103_remove(struct i2c_client *client)
 
 	sysfs_remove_group(&client->dev.kobj, &emc2103_group);
 
-	kfree(data);
 	return 0;
 }
 
diff --git a/drivers/hwmon/exynos4_tmu.c b/drivers/hwmon/exynos4_tmu.c
deleted file mode 100644
index e912059..0000000
--- a/drivers/hwmon/exynos4_tmu.c
+++ /dev/null
@@ -1,518 +0,0 @@
-/*
- * exynos4_tmu.c - Samsung EXYNOS4 TMU (Thermal Management Unit)
- *
- *  Copyright (C) 2011 Samsung Electronics
- *  Donggeun Kim <dg77.kim@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 program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-#include <linux/module.h>
-#include <linux/err.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/clk.h>
-#include <linux/workqueue.h>
-#include <linux/sysfs.h>
-#include <linux/kobject.h>
-#include <linux/io.h>
-#include <linux/mutex.h>
-
-#include <linux/hwmon.h>
-#include <linux/hwmon-sysfs.h>
-
-#include <linux/platform_data/exynos4_tmu.h>
-
-#define EXYNOS4_TMU_REG_TRIMINFO	0x0
-#define EXYNOS4_TMU_REG_CONTROL		0x20
-#define EXYNOS4_TMU_REG_STATUS		0x28
-#define EXYNOS4_TMU_REG_CURRENT_TEMP	0x40
-#define EXYNOS4_TMU_REG_THRESHOLD_TEMP	0x44
-#define EXYNOS4_TMU_REG_TRIG_LEVEL0	0x50
-#define EXYNOS4_TMU_REG_TRIG_LEVEL1	0x54
-#define EXYNOS4_TMU_REG_TRIG_LEVEL2	0x58
-#define EXYNOS4_TMU_REG_TRIG_LEVEL3	0x5C
-#define EXYNOS4_TMU_REG_PAST_TEMP0	0x60
-#define EXYNOS4_TMU_REG_PAST_TEMP1	0x64
-#define EXYNOS4_TMU_REG_PAST_TEMP2	0x68
-#define EXYNOS4_TMU_REG_PAST_TEMP3	0x6C
-#define EXYNOS4_TMU_REG_INTEN		0x70
-#define EXYNOS4_TMU_REG_INTSTAT		0x74
-#define EXYNOS4_TMU_REG_INTCLEAR	0x78
-
-#define EXYNOS4_TMU_GAIN_SHIFT		8
-#define EXYNOS4_TMU_REF_VOLTAGE_SHIFT	24
-
-#define EXYNOS4_TMU_TRIM_TEMP_MASK	0xff
-#define EXYNOS4_TMU_CORE_ON	3
-#define EXYNOS4_TMU_CORE_OFF	2
-#define EXYNOS4_TMU_DEF_CODE_TO_TEMP_OFFSET	50
-#define EXYNOS4_TMU_TRIG_LEVEL0_MASK	0x1
-#define EXYNOS4_TMU_TRIG_LEVEL1_MASK	0x10
-#define EXYNOS4_TMU_TRIG_LEVEL2_MASK	0x100
-#define EXYNOS4_TMU_TRIG_LEVEL3_MASK	0x1000
-#define EXYNOS4_TMU_INTCLEAR_VAL	0x1111
-
-struct exynos4_tmu_data {
-	struct exynos4_tmu_platform_data *pdata;
-	struct device *hwmon_dev;
-	struct resource *mem;
-	void __iomem *base;
-	int irq;
-	struct work_struct irq_work;
-	struct mutex lock;
-	struct clk *clk;
-	u8 temp_error1, temp_error2;
-};
-
-/*
- * TMU treats temperature as a mapped temperature code.
- * The temperature is converted differently depending on the calibration type.
- */
-static int temp_to_code(struct exynos4_tmu_data *data, u8 temp)
-{
-	struct exynos4_tmu_platform_data *pdata = data->pdata;
-	int temp_code;
-
-	/* temp should range between 25 and 125 */
-	if (temp < 25 || temp > 125) {
-		temp_code = -EINVAL;
-		goto out;
-	}
-
-	switch (pdata->cal_type) {
-	case TYPE_TWO_POINT_TRIMMING:
-		temp_code = (temp - 25) *
-		    (data->temp_error2 - data->temp_error1) /
-		    (85 - 25) + data->temp_error1;
-		break;
-	case TYPE_ONE_POINT_TRIMMING:
-		temp_code = temp + data->temp_error1 - 25;
-		break;
-	default:
-		temp_code = temp + EXYNOS4_TMU_DEF_CODE_TO_TEMP_OFFSET;
-		break;
-	}
-out:
-	return temp_code;
-}
-
-/*
- * Calculate a temperature value from a temperature code.
- * The unit of the temperature is degree Celsius.
- */
-static int code_to_temp(struct exynos4_tmu_data *data, u8 temp_code)
-{
-	struct exynos4_tmu_platform_data *pdata = data->pdata;
-	int temp;
-
-	/* temp_code should range between 75 and 175 */
-	if (temp_code < 75 || temp_code > 175) {
-		temp = -ENODATA;
-		goto out;
-	}
-
-	switch (pdata->cal_type) {
-	case TYPE_TWO_POINT_TRIMMING:
-		temp = (temp_code - data->temp_error1) * (85 - 25) /
-		    (data->temp_error2 - data->temp_error1) + 25;
-		break;
-	case TYPE_ONE_POINT_TRIMMING:
-		temp = temp_code - data->temp_error1 + 25;
-		break;
-	default:
-		temp = temp_code - EXYNOS4_TMU_DEF_CODE_TO_TEMP_OFFSET;
-		break;
-	}
-out:
-	return temp;
-}
-
-static int exynos4_tmu_initialize(struct platform_device *pdev)
-{
-	struct exynos4_tmu_data *data = platform_get_drvdata(pdev);
-	struct exynos4_tmu_platform_data *pdata = data->pdata;
-	unsigned int status, trim_info;
-	int ret = 0, threshold_code;
-
-	mutex_lock(&data->lock);
-	clk_enable(data->clk);
-
-	status = readb(data->base + EXYNOS4_TMU_REG_STATUS);
-	if (!status) {
-		ret = -EBUSY;
-		goto out;
-	}
-
-	/* Save trimming info in order to perform calibration */
-	trim_info = readl(data->base + EXYNOS4_TMU_REG_TRIMINFO);
-	data->temp_error1 = trim_info & EXYNOS4_TMU_TRIM_TEMP_MASK;
-	data->temp_error2 = ((trim_info >> 8) & EXYNOS4_TMU_TRIM_TEMP_MASK);
-
-	/* Write temperature code for threshold */
-	threshold_code = temp_to_code(data, pdata->threshold);
-	if (threshold_code < 0) {
-		ret = threshold_code;
-		goto out;
-	}
-	writeb(threshold_code,
-		data->base + EXYNOS4_TMU_REG_THRESHOLD_TEMP);
-
-	writeb(pdata->trigger_levels[0],
-		data->base + EXYNOS4_TMU_REG_TRIG_LEVEL0);
-	writeb(pdata->trigger_levels[1],
-		data->base + EXYNOS4_TMU_REG_TRIG_LEVEL1);
-	writeb(pdata->trigger_levels[2],
-		data->base + EXYNOS4_TMU_REG_TRIG_LEVEL2);
-	writeb(pdata->trigger_levels[3],
-		data->base + EXYNOS4_TMU_REG_TRIG_LEVEL3);
-
-	writel(EXYNOS4_TMU_INTCLEAR_VAL,
-		data->base + EXYNOS4_TMU_REG_INTCLEAR);
-out:
-	clk_disable(data->clk);
-	mutex_unlock(&data->lock);
-
-	return ret;
-}
-
-static void exynos4_tmu_control(struct platform_device *pdev, bool on)
-{
-	struct exynos4_tmu_data *data = platform_get_drvdata(pdev);
-	struct exynos4_tmu_platform_data *pdata = data->pdata;
-	unsigned int con, interrupt_en;
-
-	mutex_lock(&data->lock);
-	clk_enable(data->clk);
-
-	con = pdata->reference_voltage << EXYNOS4_TMU_REF_VOLTAGE_SHIFT |
-		pdata->gain << EXYNOS4_TMU_GAIN_SHIFT;
-	if (on) {
-		con |= EXYNOS4_TMU_CORE_ON;
-		interrupt_en = pdata->trigger_level3_en << 12 |
-			pdata->trigger_level2_en << 8 |
-			pdata->trigger_level1_en << 4 |
-			pdata->trigger_level0_en;
-	} else {
-		con |= EXYNOS4_TMU_CORE_OFF;
-		interrupt_en = 0; /* Disable all interrupts */
-	}
-	writel(interrupt_en, data->base + EXYNOS4_TMU_REG_INTEN);
-	writel(con, data->base + EXYNOS4_TMU_REG_CONTROL);
-
-	clk_disable(data->clk);
-	mutex_unlock(&data->lock);
-}
-
-static int exynos4_tmu_read(struct exynos4_tmu_data *data)
-{
-	u8 temp_code;
-	int temp;
-
-	mutex_lock(&data->lock);
-	clk_enable(data->clk);
-
-	temp_code = readb(data->base + EXYNOS4_TMU_REG_CURRENT_TEMP);
-	temp = code_to_temp(data, temp_code);
-
-	clk_disable(data->clk);
-	mutex_unlock(&data->lock);
-
-	return temp;
-}
-
-static void exynos4_tmu_work(struct work_struct *work)
-{
-	struct exynos4_tmu_data *data = container_of(work,
-			struct exynos4_tmu_data, irq_work);
-
-	mutex_lock(&data->lock);
-	clk_enable(data->clk);
-
-	writel(EXYNOS4_TMU_INTCLEAR_VAL, data->base + EXYNOS4_TMU_REG_INTCLEAR);
-
-	kobject_uevent(&data->hwmon_dev->kobj, KOBJ_CHANGE);
-
-	enable_irq(data->irq);
-
-	clk_disable(data->clk);
-	mutex_unlock(&data->lock);
-}
-
-static irqreturn_t exynos4_tmu_irq(int irq, void *id)
-{
-	struct exynos4_tmu_data *data = id;
-
-	disable_irq_nosync(irq);
-	schedule_work(&data->irq_work);
-
-	return IRQ_HANDLED;
-}
-
-static ssize_t exynos4_tmu_show_name(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	return sprintf(buf, "exynos4-tmu\n");
-}
-
-static ssize_t exynos4_tmu_show_temp(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct exynos4_tmu_data *data = dev_get_drvdata(dev);
-	int ret;
-
-	ret = exynos4_tmu_read(data);
-	if (ret < 0)
-		return ret;
-
-	/* convert from degree Celsius to millidegree Celsius */
-	return sprintf(buf, "%d\n", ret * 1000);
-}
-
-static ssize_t exynos4_tmu_show_alarm(struct device *dev,
-		struct device_attribute *devattr, char *buf)
-{
-	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct exynos4_tmu_data *data = dev_get_drvdata(dev);
-	struct exynos4_tmu_platform_data *pdata = data->pdata;
-	int temp;
-	unsigned int trigger_level;
-
-	temp = exynos4_tmu_read(data);
-	if (temp < 0)
-		return temp;
-
-	trigger_level = pdata->threshold + pdata->trigger_levels[attr->index];
-
-	return sprintf(buf, "%d\n", !!(temp > trigger_level));
-}
-
-static ssize_t exynos4_tmu_show_level(struct device *dev,
-		struct device_attribute *devattr, char *buf)
-{
-	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct exynos4_tmu_data *data = dev_get_drvdata(dev);
-	struct exynos4_tmu_platform_data *pdata = data->pdata;
-	unsigned int temp = pdata->threshold +
-			pdata->trigger_levels[attr->index];
-
-	return sprintf(buf, "%u\n", temp * 1000);
-}
-
-static DEVICE_ATTR(name, S_IRUGO, exynos4_tmu_show_name, NULL);
-static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, exynos4_tmu_show_temp, NULL, 0);
-
-static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO,
-		exynos4_tmu_show_alarm, NULL, 1);
-static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO,
-		exynos4_tmu_show_alarm, NULL, 2);
-static SENSOR_DEVICE_ATTR(temp1_emergency_alarm, S_IRUGO,
-		exynos4_tmu_show_alarm, NULL, 3);
-
-static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, exynos4_tmu_show_level, NULL, 1);
-static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, exynos4_tmu_show_level, NULL, 2);
-static SENSOR_DEVICE_ATTR(temp1_emergency, S_IRUGO,
-		exynos4_tmu_show_level, NULL, 3);
-
-static struct attribute *exynos4_tmu_attributes[] = {
-	&dev_attr_name.attr,
-	&sensor_dev_attr_temp1_input.dev_attr.attr,
-	&sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
-	&sensor_dev_attr_temp1_crit_alarm.dev_attr.attr,
-	&sensor_dev_attr_temp1_emergency_alarm.dev_attr.attr,
-	&sensor_dev_attr_temp1_max.dev_attr.attr,
-	&sensor_dev_attr_temp1_crit.dev_attr.attr,
-	&sensor_dev_attr_temp1_emergency.dev_attr.attr,
-	NULL,
-};
-
-static const struct attribute_group exynos4_tmu_attr_group = {
-	.attrs = exynos4_tmu_attributes,
-};
-
-static int __devinit exynos4_tmu_probe(struct platform_device *pdev)
-{
-	struct exynos4_tmu_data *data;
-	struct exynos4_tmu_platform_data *pdata = pdev->dev.platform_data;
-	int ret;
-
-	if (!pdata) {
-		dev_err(&pdev->dev, "No platform init data supplied.\n");
-		return -ENODEV;
-	}
-
-	data = kzalloc(sizeof(struct exynos4_tmu_data), GFP_KERNEL);
-	if (!data) {
-		dev_err(&pdev->dev, "Failed to allocate driver structure\n");
-		return -ENOMEM;
-	}
-
-	data->irq = platform_get_irq(pdev, 0);
-	if (data->irq < 0) {
-		ret = data->irq;
-		dev_err(&pdev->dev, "Failed to get platform irq\n");
-		goto err_free;
-	}
-
-	INIT_WORK(&data->irq_work, exynos4_tmu_work);
-
-	data->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!data->mem) {
-		ret = -ENOENT;
-		dev_err(&pdev->dev, "Failed to get platform resource\n");
-		goto err_free;
-	}
-
-	data->mem = request_mem_region(data->mem->start,
-			resource_size(data->mem), pdev->name);
-	if (!data->mem) {
-		ret = -ENODEV;
-		dev_err(&pdev->dev, "Failed to request memory region\n");
-		goto err_free;
-	}
-
-	data->base = ioremap(data->mem->start, resource_size(data->mem));
-	if (!data->base) {
-		ret = -ENODEV;
-		dev_err(&pdev->dev, "Failed to ioremap memory\n");
-		goto err_mem_region;
-	}
-
-	ret = request_irq(data->irq, exynos4_tmu_irq,
-		IRQF_TRIGGER_RISING,
-		"exynos4-tmu", data);
-	if (ret) {
-		dev_err(&pdev->dev, "Failed to request irq: %d\n", data->irq);
-		goto err_io_remap;
-	}
-
-	data->clk = clk_get(NULL, "tmu_apbif");
-	if (IS_ERR(data->clk)) {
-		ret = PTR_ERR(data->clk);
-		dev_err(&pdev->dev, "Failed to get clock\n");
-		goto err_irq;
-	}
-
-	data->pdata = pdata;
-	platform_set_drvdata(pdev, data);
-	mutex_init(&data->lock);
-
-	ret = exynos4_tmu_initialize(pdev);
-	if (ret) {
-		dev_err(&pdev->dev, "Failed to initialize TMU\n");
-		goto err_clk;
-	}
-
-	ret = sysfs_create_group(&pdev->dev.kobj, &exynos4_tmu_attr_group);
-	if (ret) {
-		dev_err(&pdev->dev, "Failed to create sysfs group\n");
-		goto err_clk;
-	}
-
-	data->hwmon_dev = hwmon_device_register(&pdev->dev);
-	if (IS_ERR(data->hwmon_dev)) {
-		ret = PTR_ERR(data->hwmon_dev);
-		dev_err(&pdev->dev, "Failed to register hwmon device\n");
-		goto err_create_group;
-	}
-
-	exynos4_tmu_control(pdev, true);
-
-	return 0;
-
-err_create_group:
-	sysfs_remove_group(&pdev->dev.kobj, &exynos4_tmu_attr_group);
-err_clk:
-	platform_set_drvdata(pdev, NULL);
-	clk_put(data->clk);
-err_irq:
-	free_irq(data->irq, data);
-err_io_remap:
-	iounmap(data->base);
-err_mem_region:
-	release_mem_region(data->mem->start, resource_size(data->mem));
-err_free:
-	kfree(data);
-
-	return ret;
-}
-
-static int __devexit exynos4_tmu_remove(struct platform_device *pdev)
-{
-	struct exynos4_tmu_data *data = platform_get_drvdata(pdev);
-
-	exynos4_tmu_control(pdev, false);
-
-	hwmon_device_unregister(data->hwmon_dev);
-	sysfs_remove_group(&pdev->dev.kobj, &exynos4_tmu_attr_group);
-
-	clk_put(data->clk);
-
-	free_irq(data->irq, data);
-
-	iounmap(data->base);
-	release_mem_region(data->mem->start, resource_size(data->mem));
-
-	platform_set_drvdata(pdev, NULL);
-
-	kfree(data);
-
-	return 0;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int exynos4_tmu_suspend(struct device *dev)
-{
-	exynos4_tmu_control(to_platform_device(dev), false);
-
-	return 0;
-}
-
-static int exynos4_tmu_resume(struct device *dev)
-{
-	struct platform_device *pdev = to_platform_device(dev);
-
-	exynos4_tmu_initialize(pdev);
-	exynos4_tmu_control(pdev, true);
-
-	return 0;
-}
-
-static SIMPLE_DEV_PM_OPS(exynos4_tmu_pm,
-			 exynos4_tmu_suspend, exynos4_tmu_resume);
-#define EXYNOS4_TMU_PM	&exynos4_tmu_pm
-#else
-#define EXYNOS4_TMU_PM	NULL
-#endif
-
-static struct platform_driver exynos4_tmu_driver = {
-	.driver = {
-		.name   = "exynos4-tmu",
-		.owner  = THIS_MODULE,
-		.pm     = EXYNOS4_TMU_PM,
-	},
-	.probe = exynos4_tmu_probe,
-	.remove	= __devexit_p(exynos4_tmu_remove),
-};
-
-module_platform_driver(exynos4_tmu_driver);
-
-MODULE_DESCRIPTION("EXYNOS4 TMU Driver");
-MODULE_AUTHOR("Donggeun Kim <dg77.kim@samsung.com>");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:exynos4-tmu");
diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c
index 6d12263..50e4ce2 100644
--- a/drivers/hwmon/f71882fg.c
+++ b/drivers/hwmon/f71882fg.c
@@ -2274,7 +2274,8 @@ static int __devinit f71882fg_probe(struct platform_device *pdev)
 	int err, i;
 	u8 start_reg, reg;
 
-	data = kzalloc(sizeof(struct f71882fg_data), GFP_KERNEL);
+	data = devm_kzalloc(&pdev->dev, sizeof(struct f71882fg_data),
+			    GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
 
@@ -2288,13 +2289,11 @@ static int __devinit f71882fg_probe(struct platform_device *pdev)
 	start_reg = f71882fg_read8(data, F71882FG_REG_START);
 	if (start_reg & 0x04) {
 		dev_warn(&pdev->dev, "Hardware monitor is powered down\n");
-		err = -ENODEV;
-		goto exit_free;
+		return -ENODEV;
 	}
 	if (!(start_reg & 0x03)) {
 		dev_warn(&pdev->dev, "Hardware monitoring not activated\n");
-		err = -ENODEV;
-		goto exit_free;
+		return -ENODEV;
 	}
 
 	/* Register sysfs interface files */
@@ -2422,8 +2421,6 @@ static int __devinit f71882fg_probe(struct platform_device *pdev)
 exit_unregister_sysfs:
 	f71882fg_remove(pdev); /* Will unregister the sysfs files for us */
 	return err; /* f71882fg_remove() also frees our data */
-exit_free:
-	kfree(data);
 	return err;
 }
 
@@ -2525,17 +2522,13 @@ static int f71882fg_remove(struct platform_device *pdev)
 				ARRAY_SIZE(fxxxx_auto_pwm_attr[0]) * nr_fans);
 		}
 	}
-
-	platform_set_drvdata(pdev, NULL);
-	kfree(data);
-
 	return 0;
 }
 
-static int __init f71882fg_find(int sioaddr, unsigned short *address,
-	struct f71882fg_sio_data *sio_data)
+static int __init f71882fg_find(int sioaddr, struct f71882fg_sio_data *sio_data)
 {
 	u16 devid;
+	unsigned short address;
 	int err = superio_enter(sioaddr);
 	if (err)
 		return err;
@@ -2603,25 +2596,25 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address,
 		goto exit;
 	}
 
-	*address = superio_inw(sioaddr, SIO_REG_ADDR);
-	if (*address == 0) {
+	address = superio_inw(sioaddr, SIO_REG_ADDR);
+	if (address == 0) {
 		pr_warn("Base address not set\n");
 		err = -ENODEV;
 		goto exit;
 	}
-	*address &= ~(REGION_LENGTH - 1);	/* Ignore 3 LSB */
+	address &= ~(REGION_LENGTH - 1);	/* Ignore 3 LSB */
 
-	err = 0;
+	err = address;
 	pr_info("Found %s chip at %#x, revision %d\n",
-		f71882fg_names[sio_data->type],	(unsigned int)*address,
+		f71882fg_names[sio_data->type],	(unsigned int)address,
 		(int)superio_inb(sioaddr, SIO_REG_DEVREV));
 exit:
 	superio_exit(sioaddr);
 	return err;
 }
 
-static int __init f71882fg_device_add(unsigned short address,
-	const struct f71882fg_sio_data *sio_data)
+static int __init f71882fg_device_add(int address,
+				      const struct f71882fg_sio_data *sio_data)
 {
 	struct resource res = {
 		.start	= address,
@@ -2668,19 +2661,21 @@ exit_device_put:
 
 static int __init f71882fg_init(void)
 {
-	int err = -ENODEV;
-	unsigned short address;
+	int err;
+	int address;
 	struct f71882fg_sio_data sio_data;
 
 	memset(&sio_data, 0, sizeof(sio_data));
 
-	if (f71882fg_find(0x2e, &address, &sio_data) &&
-	    f71882fg_find(0x4e, &address, &sio_data))
-		goto exit;
+	address = f71882fg_find(0x2e, &sio_data);
+	if (address < 0)
+		address = f71882fg_find(0x4e, &sio_data);
+	if (address < 0)
+		return address;
 
 	err = platform_driver_register(&f71882fg_driver);
 	if (err)
-		goto exit;
+		return err;
 
 	err = f71882fg_device_add(address, &sio_data);
 	if (err)
@@ -2690,7 +2685,6 @@ static int __init f71882fg_init(void)
 
 exit_driver:
 	platform_driver_unregister(&f71882fg_driver);
-exit:
 	return err;
 }
 
diff --git a/drivers/hwmon/f75375s.c b/drivers/hwmon/f75375s.c
index ece4159..f7dba22 100644
--- a/drivers/hwmon/f75375s.c
+++ b/drivers/hwmon/f75375s.c
@@ -838,7 +838,8 @@ static int f75375_probe(struct i2c_client *client,
 	if (!i2c_check_functionality(client->adapter,
 				I2C_FUNC_SMBUS_BYTE_DATA))
 		return -EIO;
-	data = kzalloc(sizeof(struct f75375_data), GFP_KERNEL);
+	data = devm_kzalloc(&client->dev, sizeof(struct f75375_data),
+			    GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
 
@@ -848,7 +849,7 @@ static int f75375_probe(struct i2c_client *client,
 
 	err = sysfs_create_group(&client->dev.kobj, &f75375_group);
 	if (err)
-		goto exit_free;
+		return err;
 
 	if (data->kind != f75373) {
 		err = sysfs_chmod_file(&client->dev.kobj,
@@ -875,8 +876,6 @@ static int f75375_probe(struct i2c_client *client,
 
 exit_remove:
 	sysfs_remove_group(&client->dev.kobj, &f75375_group);
-exit_free:
-	kfree(data);
 	return err;
 }
 
@@ -885,7 +884,6 @@ static int f75375_remove(struct i2c_client *client)
 	struct f75375_data *data = i2c_get_clientdata(client);
 	hwmon_device_unregister(data->hwmon_dev);
 	sysfs_remove_group(&client->dev.kobj, &f75375_group);
-	kfree(data);
 	return 0;
 }
 
diff --git a/drivers/hwmon/fam15h_power.c b/drivers/hwmon/fam15h_power.c
index af69073..68ad7d2 100644
--- a/drivers/hwmon/fam15h_power.c
+++ b/drivers/hwmon/fam15h_power.c
@@ -198,7 +198,7 @@ static int __devinit fam15h_power_probe(struct pci_dev *pdev,
 					const struct pci_device_id *id)
 {
 	struct fam15h_power_data *data;
-	struct device *dev;
+	struct device *dev = &pdev->dev;
 	int err;
 
 	/*
@@ -208,23 +208,19 @@ static int __devinit fam15h_power_probe(struct pci_dev *pdev,
 	 */
 	tweak_runavg_range(pdev);
 
-	if (!fam15h_power_is_internal_node0(pdev)) {
-		err = -ENODEV;
-		goto exit;
-	}
+	if (!fam15h_power_is_internal_node0(pdev))
+		return -ENODEV;
+
+	data = devm_kzalloc(dev, sizeof(struct fam15h_power_data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
 
-	data = kzalloc(sizeof(struct fam15h_power_data), GFP_KERNEL);
-	if (!data) {
-		err = -ENOMEM;
-		goto exit;
-	}
 	fam15h_power_init_data(pdev, data);
-	dev = &pdev->dev;
 
 	dev_set_drvdata(dev, data);
 	err = sysfs_create_group(&dev->kobj, &fam15h_power_attr_group);
 	if (err)
-		goto exit_free_data;
+		return err;
 
 	data->hwmon_dev = hwmon_device_register(dev);
 	if (IS_ERR(data->hwmon_dev)) {
@@ -236,9 +232,6 @@ static int __devinit fam15h_power_probe(struct pci_dev *pdev,
 
 exit_remove_group:
 	sysfs_remove_group(&dev->kobj, &fam15h_power_attr_group);
-exit_free_data:
-	kfree(data);
-exit:
 	return err;
 }
 
@@ -251,8 +244,6 @@ static void __devexit fam15h_power_remove(struct pci_dev *pdev)
 	data = dev_get_drvdata(dev);
 	hwmon_device_unregister(data->hwmon_dev);
 	sysfs_remove_group(&dev->kobj, &fam15h_power_attr_group);
-	dev_set_drvdata(dev, NULL);
-	kfree(data);
 }
 
 static DEFINE_PCI_DEVICE_TABLE(fam15h_power_id_table) = {
diff --git a/drivers/hwmon/g760a.c b/drivers/hwmon/g760a.c
index ebcd269..8b2106f 100644
--- a/drivers/hwmon/g760a.c
+++ b/drivers/hwmon/g760a.c
@@ -207,7 +207,8 @@ static int g760a_probe(struct i2c_client *client,
 				     I2C_FUNC_SMBUS_BYTE_DATA))
 		return -EIO;
 
-	data = kzalloc(sizeof(struct g760a_data), GFP_KERNEL);
+	data = devm_kzalloc(&client->dev, sizeof(struct g760a_data),
+			    GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
 
@@ -223,7 +224,7 @@ static int g760a_probe(struct i2c_client *client,
 	/* Register sysfs hooks */
 	err = sysfs_create_group(&client->dev.kobj, &g760a_group);
 	if (err)
-		goto error_sysfs_create_group;
+		return err;
 
 	data->hwmon_dev = hwmon_device_register(&client->dev);
 	if (IS_ERR(data->hwmon_dev)) {
@@ -235,9 +236,6 @@ static int g760a_probe(struct i2c_client *client,
 
 error_hwmon_device_register:
 	sysfs_remove_group(&client->dev.kobj, &g760a_group);
-error_sysfs_create_group:
-	kfree(data);
-
 	return err;
 }
 
@@ -246,8 +244,6 @@ static int g760a_remove(struct i2c_client *client)
 	struct g760a_data *data = i2c_get_clientdata(client);
 	hwmon_device_unregister(data->hwmon_dev);
 	sysfs_remove_group(&client->dev.kobj, &g760a_group);
-	kfree(data);
-
 	return 0;
 }
 
diff --git a/drivers/hwmon/gpio-fan.c b/drivers/hwmon/gpio-fan.c
index 2f4b01b..36509ae 100644
--- a/drivers/hwmon/gpio-fan.c
+++ b/drivers/hwmon/gpio-fan.c
@@ -31,6 +31,8 @@
 #include <linux/hwmon.h>
 #include <linux/gpio.h>
 #include <linux/gpio-fan.h>
+#include <linux/of_platform.h>
+#include <linux/of_gpio.h>
 
 struct gpio_fan_data {
 	struct platform_device	*pdev;
@@ -400,14 +402,131 @@ static ssize_t show_name(struct device *dev,
 
 static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
 
+
+#ifdef CONFIG_OF_GPIO
+/*
+ * Translate OpenFirmware node properties into platform_data
+ */
+static int gpio_fan_get_of_pdata(struct device *dev,
+			    struct gpio_fan_platform_data *pdata)
+{
+	struct device_node *node;
+	struct gpio_fan_speed *speed;
+	unsigned *ctrl;
+	unsigned i;
+	u32 u;
+	struct property *prop;
+	const __be32 *p;
+
+	node = dev->of_node;
+
+	/* Fill GPIO pin array */
+	pdata->num_ctrl = of_gpio_count(node);
+	if (!pdata->num_ctrl) {
+		dev_err(dev, "gpios DT property empty / missing");
+		return -ENODEV;
+	}
+	ctrl = devm_kzalloc(dev, pdata->num_ctrl * sizeof(unsigned),
+				GFP_KERNEL);
+	if (!ctrl)
+		return -ENOMEM;
+	for (i = 0; i < pdata->num_ctrl; i++) {
+		int val;
+
+		val = of_get_gpio(node, i);
+		if (val < 0)
+			return val;
+		ctrl[i] = val;
+	}
+	pdata->ctrl = ctrl;
+
+	/* Get number of RPM/ctrl_val pairs in speed map */
+	prop = of_find_property(node, "gpio-fan,speed-map", &i);
+	if (!prop) {
+		dev_err(dev, "gpio-fan,speed-map DT property missing");
+		return -ENODEV;
+	}
+	i = i / sizeof(u32);
+	if (i == 0 || i & 1) {
+		dev_err(dev, "gpio-fan,speed-map contains zero/odd number of entries");
+		return -ENODEV;
+	}
+	pdata->num_speed = i / 2;
+
+	/*
+	 * Populate speed map
+	 * Speed map is in the form <RPM ctrl_val RPM ctrl_val ...>
+	 * this needs splitting into pairs to create gpio_fan_speed structs
+	 */
+	speed = devm_kzalloc(dev,
+			pdata->num_speed * sizeof(struct gpio_fan_speed),
+			GFP_KERNEL);
+	if (!speed)
+		return -ENOMEM;
+	p = NULL;
+	for (i = 0; i < pdata->num_speed; i++) {
+		p = of_prop_next_u32(prop, p, &u);
+		if (!p)
+			return -ENODEV;
+		speed[i].rpm = u;
+		p = of_prop_next_u32(prop, p, &u);
+		if (!p)
+			return -ENODEV;
+		speed[i].ctrl_val = u;
+	}
+	pdata->speed = speed;
+
+	/* Alarm GPIO if one exists */
+	if (of_gpio_named_count(node, "alarm-gpios")) {
+		struct gpio_fan_alarm *alarm;
+		int val;
+		enum of_gpio_flags flags;
+
+		alarm = devm_kzalloc(dev, sizeof(struct gpio_fan_alarm),
+					GFP_KERNEL);
+		if (!alarm)
+			return -ENOMEM;
+
+		val = of_get_named_gpio_flags(node, "alarm-gpios", 0, &flags);
+		if (val < 0)
+			return val;
+		alarm->gpio = val;
+		alarm->active_low = flags & OF_GPIO_ACTIVE_LOW;
+
+		pdata->alarm = alarm;
+	}
+
+	return 0;
+}
+
+static struct of_device_id of_gpio_fan_match[] __devinitdata = {
+	{ .compatible = "gpio-fan", },
+	{},
+};
+#endif /* CONFIG_OF_GPIO */
+
 static int __devinit gpio_fan_probe(struct platform_device *pdev)
 {
 	int err;
 	struct gpio_fan_data *fan_data;
 	struct gpio_fan_platform_data *pdata = pdev->dev.platform_data;
 
+#ifdef CONFIG_OF_GPIO
+	if (!pdata) {
+		pdata = devm_kzalloc(&pdev->dev,
+					sizeof(struct gpio_fan_platform_data),
+					GFP_KERNEL);
+		if (!pdata)
+			return -ENOMEM;
+
+		err = gpio_fan_get_of_pdata(&pdev->dev, pdata);
+		if (err)
+			return err;
+	}
+#else /* CONFIG_OF_GPIO */
 	if (!pdata)
 		return -EINVAL;
+#endif /* CONFIG_OF_GPIO */
 
 	fan_data = devm_kzalloc(&pdev->dev, sizeof(struct gpio_fan_data),
 				GFP_KERNEL);
@@ -511,6 +630,7 @@ static struct platform_driver gpio_fan_driver = {
 	.driver	= {
 		.name	= "gpio-fan",
 		.pm	= GPIO_FAN_PM,
+		.of_match_table = of_match_ptr(of_gpio_fan_match),
 	},
 };
 
diff --git a/drivers/hwmon/ina2xx.c b/drivers/hwmon/ina2xx.c
index 6021482..70717d4 100644
--- a/drivers/hwmon/ina2xx.c
+++ b/drivers/hwmon/ina2xx.c
@@ -5,10 +5,18 @@
  * Zero Drift Bi-Directional Current/Power Monitor with I2C Interface
  * Datasheet: http://www.ti.com/product/ina219
  *
+ * INA220:
+ * Bi-Directional Current/Power Monitor with I2C Interface
+ * Datasheet: http://www.ti.com/product/ina220
+ *
  * INA226:
  * Bi-Directional Current/Power Monitor with I2C Interface
  * Datasheet: http://www.ti.com/product/ina226
  *
+ * INA230:
+ * Bi-directional Current/Power Monitor with I2C Interface
+ * Datasheet: http://www.ti.com/product/ina230
+ *
  * Copyright (C) 2012 Lothar Felten <l-felten@ti.com>
  * Thanks to Jan Volkering
  *
@@ -57,18 +65,49 @@
 
 enum ina2xx_ids { ina219, ina226 };
 
+struct ina2xx_config {
+	u16 config_default;
+	int calibration_factor;
+	int registers;
+	int shunt_div;
+	int bus_voltage_shift;
+	int bus_voltage_lsb;	/* uV */
+	int power_lsb;		/* uW */
+};
+
 struct ina2xx_data {
 	struct device *hwmon_dev;
+	const struct ina2xx_config *config;
 
 	struct mutex update_lock;
 	bool valid;
 	unsigned long last_updated;
 
 	int kind;
-	int registers;
 	u16 regs[INA2XX_MAX_REGISTERS];
 };
 
+static const struct ina2xx_config ina2xx_config[] = {
+	[ina219] = {
+		.config_default = INA219_CONFIG_DEFAULT,
+		.calibration_factor = 40960000,
+		.registers = INA219_REGISTERS,
+		.shunt_div = 100,
+		.bus_voltage_shift = 3,
+		.bus_voltage_lsb = 4000,
+		.power_lsb = 20000,
+	},
+	[ina226] = {
+		.config_default = INA226_CONFIG_DEFAULT,
+		.calibration_factor = 5120000,
+		.registers = INA226_REGISTERS,
+		.shunt_div = 400,
+		.bus_voltage_shift = 0,
+		.bus_voltage_lsb = 1250,
+		.power_lsb = 25000,
+	},
+};
+
 static struct ina2xx_data *ina2xx_update_device(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
@@ -85,7 +124,7 @@ static struct ina2xx_data *ina2xx_update_device(struct device *dev)
 		dev_dbg(&client->dev, "Starting ina2xx update\n");
 
 		/* Read all registers */
-		for (i = 0; i < data->registers; i++) {
+		for (i = 0; i < data->config->registers; i++) {
 			int rv = i2c_smbus_read_word_swapped(client, i);
 			if (rv < 0) {
 				ret = ERR_PTR(rv);
@@ -101,73 +140,26 @@ abort:
 	return ret;
 }
 
-static int ina219_get_value(struct ina2xx_data *data, u8 reg)
+static int ina2xx_get_value(struct ina2xx_data *data, u8 reg)
 {
-	/*
-	 * calculate exact value for the given register
-	 * we assume default power-on reset settings:
-	 * bus voltage range 32V
-	 * gain = /8
-	 * adc 1 & 2 -> conversion time 532uS
-	 * mode is continuous shunt and bus
-	 * calibration value is INA219_CALIBRATION_VALUE
-	 */
-	int val = data->regs[reg];
+	int val;
 
 	switch (reg) {
 	case INA2XX_SHUNT_VOLTAGE:
-		/* LSB=10uV. Convert to mV. */
-		val = DIV_ROUND_CLOSEST(val, 100);
+		val = DIV_ROUND_CLOSEST(data->regs[reg],
+					data->config->shunt_div);
 		break;
 	case INA2XX_BUS_VOLTAGE:
-		/* LSB=4mV. Register is not right aligned, convert to mV. */
-		val = (val >> 3) * 4;
+		val = (data->regs[reg] >> data->config->bus_voltage_shift)
+		  * data->config->bus_voltage_lsb;
+		val = DIV_ROUND_CLOSEST(val, 1000);
 		break;
 	case INA2XX_POWER:
-		/* LSB=20mW. Convert to uW */
-		val = val * 20 * 1000;
-		break;
-	case INA2XX_CURRENT:
-		/* LSB=1mA (selected). Is in mA */
-		break;
-	default:
-		/* programmer goofed */
-		WARN_ON_ONCE(1);
-		val = 0;
-		break;
-	}
-
-	return val;
-}
-
-static int ina226_get_value(struct ina2xx_data *data, u8 reg)
-{
-	/*
-	 * calculate exact value for the given register
-	 * we assume default power-on reset settings:
-	 * bus voltage range 32V
-	 * gain = /8
-	 * adc 1 & 2 -> conversion time 532uS
-	 * mode is continuous shunt and bus
-	 * calibration value is INA226_CALIBRATION_VALUE
-	 */
-	int val = data->regs[reg];
-
-	switch (reg) {
-	case INA2XX_SHUNT_VOLTAGE:
-		/* LSB=2.5uV. Convert to mV. */
-		val = DIV_ROUND_CLOSEST(val, 400);
-		break;
-	case INA2XX_BUS_VOLTAGE:
-		/* LSB=1.25mV. Convert to mV. */
-		val = val + DIV_ROUND_CLOSEST(val, 4);
-		break;
-	case INA2XX_POWER:
-		/* LSB=25mW. Convert to uW */
-		val = val * 25 * 1000;
+		val = data->regs[reg] * data->config->power_lsb;
 		break;
 	case INA2XX_CURRENT:
 		/* LSB=1mA (selected). Is in mA */
+		val = data->regs[reg];
 		break;
 	default:
 		/* programmer goofed */
@@ -184,23 +176,12 @@ static ssize_t ina2xx_show_value(struct device *dev,
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
 	struct ina2xx_data *data = ina2xx_update_device(dev);
-	int value = 0;
 
 	if (IS_ERR(data))
 		return PTR_ERR(data);
 
-	switch (data->kind) {
-	case ina219:
-		value = ina219_get_value(data, attr->index);
-		break;
-	case ina226:
-		value = ina226_get_value(data, attr->index);
-		break;
-	default:
-		WARN_ON_ONCE(1);
-		break;
-	}
-	return snprintf(buf, PAGE_SIZE, "%d\n", value);
+	return snprintf(buf, PAGE_SIZE, "%d\n",
+			ina2xx_get_value(data, attr->index));
 }
 
 /* shunt voltage */
@@ -238,7 +219,7 @@ static int ina2xx_probe(struct i2c_client *client,
 	struct i2c_adapter *adapter = client->adapter;
 	struct ina2xx_data *data;
 	struct ina2xx_platform_data *pdata;
-	int ret = 0;
+	int ret;
 	long shunt = 10000; /* default shunt value 10mOhms */
 
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA))
@@ -259,38 +240,15 @@ static int ina2xx_probe(struct i2c_client *client,
 
 	/* set the device type */
 	data->kind = id->driver_data;
+	data->config = &ina2xx_config[data->kind];
 
-	switch (data->kind) {
-	case ina219:
-		/* device configuration */
-		i2c_smbus_write_word_swapped(client, INA2XX_CONFIG,
-					     INA219_CONFIG_DEFAULT);
-
-		/* set current LSB to 1mA, shunt is in uOhms */
-		/* (equation 13 in datasheet) */
-		i2c_smbus_write_word_swapped(client, INA2XX_CALIBRATION,
-					     40960000 / shunt);
-		dev_info(&client->dev,
-			 "power monitor INA219 (Rshunt = %li uOhm)\n", shunt);
-		data->registers = INA219_REGISTERS;
-		break;
-	case ina226:
-		/* device configuration */
-		i2c_smbus_write_word_swapped(client, INA2XX_CONFIG,
-					     INA226_CONFIG_DEFAULT);
-
-		/* set current LSB to 1mA, shunt is in uOhms */
-		/* (equation 1 in datasheet)*/
-		i2c_smbus_write_word_swapped(client, INA2XX_CALIBRATION,
-					     5120000 / shunt);
-		dev_info(&client->dev,
-			 "power monitor INA226 (Rshunt = %li uOhm)\n", shunt);
-		data->registers = INA226_REGISTERS;
-		break;
-	default:
-		/* unknown device id */
-		return -ENODEV;
-	}
+	/* device configuration */
+	i2c_smbus_write_word_swapped(client, INA2XX_CONFIG,
+				     data->config->config_default);
+	/* set current LSB to 1mA, shunt is in uOhms */
+	/* (equation 13 in datasheet) */
+	i2c_smbus_write_word_swapped(client, INA2XX_CALIBRATION,
+				     data->config->calibration_factor / shunt);
 
 	i2c_set_clientdata(client, data);
 	mutex_init(&data->update_lock);
@@ -305,6 +263,9 @@ static int ina2xx_probe(struct i2c_client *client,
 		goto out_err_hwmon;
 	}
 
+	dev_info(&client->dev, "power monitor %s (Rshunt = %li uOhm)\n",
+		 id->name, shunt);
+
 	return 0;
 
 out_err_hwmon:
@@ -324,7 +285,9 @@ static int ina2xx_remove(struct i2c_client *client)
 
 static const struct i2c_device_id ina2xx_id[] = {
 	{ "ina219", ina219 },
+	{ "ina220", ina219 },
 	{ "ina226", ina226 },
+	{ "ina230", ina226 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, ina2xx_id);
diff --git a/drivers/hwmon/jz4740-hwmon.c b/drivers/hwmon/jz4740-hwmon.c
index 5253d23..dee9eec 100644
--- a/drivers/hwmon/jz4740-hwmon.c
+++ b/drivers/hwmon/jz4740-hwmon.c
@@ -20,6 +20,7 @@
 #include <linux/mutex.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
+#include <linux/io.h>
 
 #include <linux/completion.h>
 #include <linux/mfd/core.h>
@@ -106,42 +107,37 @@ static int __devinit jz4740_hwmon_probe(struct platform_device *pdev)
 	int ret;
 	struct jz4740_hwmon *hwmon;
 
-	hwmon = kmalloc(sizeof(*hwmon), GFP_KERNEL);
-	if (!hwmon) {
-		dev_err(&pdev->dev, "Failed to allocate driver structure\n");
+	hwmon = devm_kzalloc(&pdev->dev, sizeof(*hwmon), GFP_KERNEL);
+	if (!hwmon)
 		return -ENOMEM;
-	}
 
 	hwmon->cell = mfd_get_cell(pdev);
 
 	hwmon->irq = platform_get_irq(pdev, 0);
 	if (hwmon->irq < 0) {
-		ret = hwmon->irq;
-		dev_err(&pdev->dev, "Failed to get platform irq: %d\n", ret);
-		goto err_free;
+		dev_err(&pdev->dev, "Failed to get platform irq: %d\n",
+			hwmon->irq);
+		return hwmon->irq;
 	}
 
 	hwmon->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!hwmon->mem) {
-		ret = -ENOENT;
 		dev_err(&pdev->dev, "Failed to get platform mmio resource\n");
-		goto err_free;
+		return -ENOENT;
 	}
 
-	hwmon->mem = request_mem_region(hwmon->mem->start,
+	hwmon->mem = devm_request_mem_region(&pdev->dev, hwmon->mem->start,
 			resource_size(hwmon->mem), pdev->name);
 	if (!hwmon->mem) {
-		ret = -EBUSY;
 		dev_err(&pdev->dev, "Failed to request mmio memory region\n");
-		goto err_free;
+		return -EBUSY;
 	}
 
-	hwmon->base = ioremap_nocache(hwmon->mem->start,
-			resource_size(hwmon->mem));
+	hwmon->base = devm_ioremap_nocache(&pdev->dev, hwmon->mem->start,
+					   resource_size(hwmon->mem));
 	if (!hwmon->base) {
-		ret = -EBUSY;
 		dev_err(&pdev->dev, "Failed to ioremap mmio memory\n");
-		goto err_release_mem_region;
+		return -EBUSY;
 	}
 
 	init_completion(&hwmon->read_completion);
@@ -149,17 +145,18 @@ static int __devinit jz4740_hwmon_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, hwmon);
 
-	ret = request_irq(hwmon->irq, jz4740_hwmon_irq, 0, pdev->name, hwmon);
+	ret = devm_request_irq(&pdev->dev, hwmon->irq, jz4740_hwmon_irq, 0,
+			       pdev->name, hwmon);
 	if (ret) {
 		dev_err(&pdev->dev, "Failed to request irq: %d\n", ret);
-		goto err_iounmap;
+		return ret;
 	}
 	disable_irq(hwmon->irq);
 
 	ret = sysfs_create_group(&pdev->dev.kobj, &jz4740_hwmon_attr_group);
 	if (ret) {
 		dev_err(&pdev->dev, "Failed to create sysfs group: %d\n", ret);
-		goto err_free_irq;
+		return ret;
 	}
 
 	hwmon->hwmon = hwmon_device_register(&pdev->dev);
@@ -172,16 +169,6 @@ static int __devinit jz4740_hwmon_probe(struct platform_device *pdev)
 
 err_remove_file:
 	sysfs_remove_group(&pdev->dev.kobj, &jz4740_hwmon_attr_group);
-err_free_irq:
-	free_irq(hwmon->irq, hwmon);
-err_iounmap:
-	platform_set_drvdata(pdev, NULL);
-	iounmap(hwmon->base);
-err_release_mem_region:
-	release_mem_region(hwmon->mem->start, resource_size(hwmon->mem));
-err_free:
-	kfree(hwmon);
-
 	return ret;
 }
 
@@ -192,14 +179,6 @@ static int __devexit jz4740_hwmon_remove(struct platform_device *pdev)
 	hwmon_device_unregister(hwmon->hwmon);
 	sysfs_remove_group(&pdev->dev.kobj, &jz4740_hwmon_attr_group);
 
-	free_irq(hwmon->irq, hwmon);
-
-	iounmap(hwmon->base);
-	release_mem_region(hwmon->mem->start, resource_size(hwmon->mem));
-
-	platform_set_drvdata(pdev, NULL);
-	kfree(hwmon);
-
 	return 0;
 }
 
diff --git a/drivers/hwmon/lm70.c b/drivers/hwmon/lm70.c
index 472f795..2d1777a 100644
--- a/drivers/hwmon/lm70.c
+++ b/drivers/hwmon/lm70.c
@@ -43,6 +43,8 @@
 
 #define LM70_CHIP_LM70		0	/* original NS LM70 */
 #define LM70_CHIP_TMP121	1	/* TI TMP121/TMP123 */
+#define LM70_CHIP_LM71		2	/* NS LM71 */
+#define LM70_CHIP_LM74		3	/* NS LM74 */
 
 struct lm70 {
 	struct device *hwmon_dev;
@@ -88,9 +90,13 @@ static ssize_t lm70_sense_temp(struct device *dev,
 	 * Celsius.
 	 * So it's equivalent to multiplying by 0.25 * 1000 = 250.
 	 *
-	 * TMP121/TMP123:
+	 * LM74 and TMP121/TMP123:
 	 * 13 bits of 2's complement data, discard LSB 3 bits,
 	 * resolution 0.0625 degrees celsius.
+	 *
+	 * LM71:
+	 * 14 bits of 2's complement data, discard LSB 2 bits,
+	 * resolution 0.0312 degrees celsius.
 	 */
 	switch (p_lm70->chip) {
 	case LM70_CHIP_LM70:
@@ -98,8 +104,13 @@ static ssize_t lm70_sense_temp(struct device *dev,
 		break;
 
 	case LM70_CHIP_TMP121:
+	case LM70_CHIP_LM74:
 		val = ((int)raw / 8) * 625 / 10;
 		break;
+
+	case LM70_CHIP_LM71:
+		val = ((int)raw / 4) * 3125 / 100;
+		break;
 	}
 
 	status = sprintf(buf, "%d\n", val); /* millidegrees Celsius */
@@ -113,20 +124,7 @@ static DEVICE_ATTR(temp1_input, S_IRUGO, lm70_sense_temp, NULL);
 static ssize_t lm70_show_name(struct device *dev, struct device_attribute
 			      *devattr, char *buf)
 {
-	struct lm70 *p_lm70 = dev_get_drvdata(dev);
-	int ret;
-
-	switch (p_lm70->chip) {
-	case LM70_CHIP_LM70:
-		ret = sprintf(buf, "lm70\n");
-		break;
-	case LM70_CHIP_TMP121:
-		ret = sprintf(buf, "tmp121\n");
-		break;
-	default:
-		ret = -EINVAL;
-	}
-	return ret;
+	return sprintf(buf, "%s\n", to_spi_device(dev)->modalias);
 }
 
 static DEVICE_ATTR(name, S_IRUGO, lm70_show_name, NULL);
@@ -139,17 +137,13 @@ static int __devinit lm70_probe(struct spi_device *spi)
 	struct lm70 *p_lm70;
 	int status;
 
-	/* signaling is SPI_MODE_0 for both LM70 and TMP121 */
+	/* signaling is SPI_MODE_0 */
 	if (spi->mode & (SPI_CPOL | SPI_CPHA))
 		return -EINVAL;
 
-	/* 3-wire link (shared SI/SO) for LM70 */
-	if (chip == LM70_CHIP_LM70 && !(spi->mode & SPI_3WIRE))
-		return -EINVAL;
-
 	/* NOTE:  we assume 8-bit words, and convert to 16 bits manually */
 
-	p_lm70 = kzalloc(sizeof *p_lm70, GFP_KERNEL);
+	p_lm70 = devm_kzalloc(&spi->dev, sizeof(*p_lm70), GFP_KERNEL);
 	if (!p_lm70)
 		return -ENOMEM;
 
@@ -181,7 +175,6 @@ out_dev_create_file_failed:
 	device_remove_file(&spi->dev, &dev_attr_temp1_input);
 out_dev_create_temp_file_failed:
 	spi_set_drvdata(spi, NULL);
-	kfree(p_lm70);
 	return status;
 }
 
@@ -193,7 +186,6 @@ static int __devexit lm70_remove(struct spi_device *spi)
 	device_remove_file(&spi->dev, &dev_attr_temp1_input);
 	device_remove_file(&spi->dev, &dev_attr_name);
 	spi_set_drvdata(spi, NULL);
-	kfree(p_lm70);
 
 	return 0;
 }
@@ -202,6 +194,8 @@ static int __devexit lm70_remove(struct spi_device *spi)
 static const struct spi_device_id lm70_ids[] = {
 	{ "lm70",   LM70_CHIP_LM70 },
 	{ "tmp121", LM70_CHIP_TMP121 },
+	{ "lm71",   LM70_CHIP_LM71 },
+	{ "lm74",   LM70_CHIP_LM74 },
 	{ },
 };
 MODULE_DEVICE_TABLE(spi, lm70_ids);
@@ -219,5 +213,5 @@ static struct spi_driver lm70_driver = {
 module_spi_driver(lm70_driver);
 
 MODULE_AUTHOR("Kaiwan N Billimoria");
-MODULE_DESCRIPTION("NS LM70 / TI TMP121/TMP123 Linux driver");
+MODULE_DESCRIPTION("NS LM70 and compatibles Linux driver");
 MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/lm93.c b/drivers/hwmon/lm93.c
index bf94618..c3d4255 100644
--- a/drivers/hwmon/lm93.c
+++ b/drivers/hwmon/lm93.c
@@ -1830,7 +1830,7 @@ static ssize_t store_fan_smart_tach(struct device *dev,
 
 	mutex_lock(&data->update_lock);
 	/* sanity test, ignore the write otherwise */
-	if (0 <= val && val <= 2) {
+	if (val <= 2) {
 		/* can't enable if pwm freq is 22.5KHz */
 		if (val) {
 			u8 ctl4 = lm93_read_byte(client,
diff --git a/drivers/hwmon/lm95241.c b/drivers/hwmon/lm95241.c
index bd8cdb7..4b68fb2 100644
--- a/drivers/hwmon/lm95241.c
+++ b/drivers/hwmon/lm95241.c
@@ -391,11 +391,10 @@ static int lm95241_probe(struct i2c_client *new_client,
 	struct lm95241_data *data;
 	int err;
 
-	data = kzalloc(sizeof(struct lm95241_data), GFP_KERNEL);
-	if (!data) {
-		err = -ENOMEM;
-		goto exit;
-	}
+	data = devm_kzalloc(&new_client->dev, sizeof(struct lm95241_data),
+			    GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
 
 	i2c_set_clientdata(new_client, data);
 	mutex_init(&data->update_lock);
@@ -406,7 +405,7 @@ static int lm95241_probe(struct i2c_client *new_client,
 	/* Register sysfs hooks */
 	err = sysfs_create_group(&new_client->dev.kobj, &lm95241_group);
 	if (err)
-		goto exit_free;
+		return err;
 
 	data->hwmon_dev = hwmon_device_register(&new_client->dev);
 	if (IS_ERR(data->hwmon_dev)) {
@@ -418,9 +417,6 @@ static int lm95241_probe(struct i2c_client *new_client,
 
 exit_remove_files:
 	sysfs_remove_group(&new_client->dev.kobj, &lm95241_group);
-exit_free:
-	kfree(data);
-exit:
 	return err;
 }
 
@@ -431,7 +427,6 @@ static int lm95241_remove(struct i2c_client *client)
 	hwmon_device_unregister(data->hwmon_dev);
 	sysfs_remove_group(&client->dev.kobj, &lm95241_group);
 
-	kfree(data);
 	return 0;
 }
 
diff --git a/drivers/hwmon/lm95245.c b/drivers/hwmon/lm95245.c
index 9a46c10..2915fd9 100644
--- a/drivers/hwmon/lm95245.c
+++ b/drivers/hwmon/lm95245.c
@@ -462,11 +462,10 @@ static int lm95245_probe(struct i2c_client *new_client,
 	struct lm95245_data *data;
 	int err;
 
-	data = kzalloc(sizeof(struct lm95245_data), GFP_KERNEL);
-	if (!data) {
-		err = -ENOMEM;
-		goto exit;
-	}
+	data = devm_kzalloc(&new_client->dev, sizeof(struct lm95245_data),
+			    GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
 
 	i2c_set_clientdata(new_client, data);
 	mutex_init(&data->update_lock);
@@ -477,7 +476,7 @@ static int lm95245_probe(struct i2c_client *new_client,
 	/* Register sysfs hooks */
 	err = sysfs_create_group(&new_client->dev.kobj, &lm95245_group);
 	if (err)
-		goto exit_free;
+		return err;
 
 	data->hwmon_dev = hwmon_device_register(&new_client->dev);
 	if (IS_ERR(data->hwmon_dev)) {
@@ -489,9 +488,6 @@ static int lm95245_probe(struct i2c_client *new_client,
 
 exit_remove_files:
 	sysfs_remove_group(&new_client->dev.kobj, &lm95245_group);
-exit_free:
-	kfree(data);
-exit:
 	return err;
 }
 
@@ -502,7 +498,6 @@ static int lm95245_remove(struct i2c_client *client)
 	hwmon_device_unregister(data->hwmon_dev);
 	sysfs_remove_group(&client->dev.kobj, &lm95245_group);
 
-	kfree(data);
 	return 0;
 }
 
diff --git a/drivers/hwmon/ltc4151.c b/drivers/hwmon/ltc4151.c
index 4d005b2..8496baa 100644
--- a/drivers/hwmon/ltc4151.c
+++ b/drivers/hwmon/ltc4151.c
@@ -181,11 +181,9 @@ static int ltc4151_probe(struct i2c_client *client,
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 		return -ENODEV;
 
-	data = kzalloc(sizeof(*data), GFP_KERNEL);
-	if (!data) {
-		ret = -ENOMEM;
-		goto out_kzalloc;
-	}
+	data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
 
 	i2c_set_clientdata(client, data);
 	mutex_init(&data->update_lock);
@@ -193,7 +191,7 @@ static int ltc4151_probe(struct i2c_client *client,
 	/* Register sysfs hooks */
 	ret = sysfs_create_group(&client->dev.kobj, &ltc4151_group);
 	if (ret)
-		goto out_sysfs_create_group;
+		return ret;
 
 	data->hwmon_dev = hwmon_device_register(&client->dev);
 	if (IS_ERR(data->hwmon_dev)) {
@@ -205,9 +203,6 @@ static int ltc4151_probe(struct i2c_client *client,
 
 out_hwmon_device_register:
 	sysfs_remove_group(&client->dev.kobj, &ltc4151_group);
-out_sysfs_create_group:
-	kfree(data);
-out_kzalloc:
 	return ret;
 }
 
@@ -218,8 +213,6 @@ static int ltc4151_remove(struct i2c_client *client)
 	hwmon_device_unregister(data->hwmon_dev);
 	sysfs_remove_group(&client->dev.kobj, &ltc4151_group);
 
-	kfree(data);
-
 	return 0;
 }
 
diff --git a/drivers/hwmon/ltc4215.c b/drivers/hwmon/ltc4215.c
index 429c5b2..98b3d04f 100644
--- a/drivers/hwmon/ltc4215.c
+++ b/drivers/hwmon/ltc4215.c
@@ -253,11 +253,9 @@ static int ltc4215_probe(struct i2c_client *client,
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 		return -ENODEV;
 
-	data = kzalloc(sizeof(*data), GFP_KERNEL);
-	if (!data) {
-		ret = -ENOMEM;
-		goto out_kzalloc;
-	}
+	data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
 
 	i2c_set_clientdata(client, data);
 	mutex_init(&data->update_lock);
@@ -268,7 +266,7 @@ static int ltc4215_probe(struct i2c_client *client,
 	/* Register sysfs hooks */
 	ret = sysfs_create_group(&client->dev.kobj, &ltc4215_group);
 	if (ret)
-		goto out_sysfs_create_group;
+		return ret;
 
 	data->hwmon_dev = hwmon_device_register(&client->dev);
 	if (IS_ERR(data->hwmon_dev)) {
@@ -280,9 +278,6 @@ static int ltc4215_probe(struct i2c_client *client,
 
 out_hwmon_device_register:
 	sysfs_remove_group(&client->dev.kobj, &ltc4215_group);
-out_sysfs_create_group:
-	kfree(data);
-out_kzalloc:
 	return ret;
 }
 
@@ -293,8 +288,6 @@ static int ltc4215_remove(struct i2c_client *client)
 	hwmon_device_unregister(data->hwmon_dev);
 	sysfs_remove_group(&client->dev.kobj, &ltc4215_group);
 
-	kfree(data);
-
 	return 0;
 }
 
diff --git a/drivers/hwmon/ltc4245.c b/drivers/hwmon/ltc4245.c
index b99b45b..5207591 100644
--- a/drivers/hwmon/ltc4245.c
+++ b/drivers/hwmon/ltc4245.c
@@ -519,11 +519,9 @@ static int ltc4245_probe(struct i2c_client *client,
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 		return -ENODEV;
 
-	data = kzalloc(sizeof(*data), GFP_KERNEL);
-	if (!data) {
-		ret = -ENOMEM;
-		goto out_kzalloc;
-	}
+	data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
 
 	i2c_set_clientdata(client, data);
 	mutex_init(&data->update_lock);
@@ -536,7 +534,7 @@ static int ltc4245_probe(struct i2c_client *client,
 	/* Register sysfs hooks */
 	ret = ltc4245_sysfs_create_groups(client);
 	if (ret)
-		goto out_sysfs_create_groups;
+		return ret;
 
 	data->hwmon_dev = hwmon_device_register(&client->dev);
 	if (IS_ERR(data->hwmon_dev)) {
@@ -548,9 +546,6 @@ static int ltc4245_probe(struct i2c_client *client,
 
 out_hwmon_device_register:
 	ltc4245_sysfs_remove_groups(client);
-out_sysfs_create_groups:
-	kfree(data);
-out_kzalloc:
 	return ret;
 }
 
@@ -560,7 +555,6 @@ static int ltc4245_remove(struct i2c_client *client)
 
 	hwmon_device_unregister(data->hwmon_dev);
 	ltc4245_sysfs_remove_groups(client);
-	kfree(data);
 
 	return 0;
 }
diff --git a/drivers/hwmon/max1111.c b/drivers/hwmon/max1111.c
index f3978a4..b4eb088 100644
--- a/drivers/hwmon/max1111.c
+++ b/drivers/hwmon/max1111.c
@@ -22,6 +22,8 @@
 #include <linux/spi/spi.h>
 #include <linux/slab.h>
 
+enum chips { max1110, max1111, max1112, max1113 };
+
 #define MAX1111_TX_BUF_SIZE	1
 #define MAX1111_RX_BUF_SIZE	2
 
@@ -30,6 +32,7 @@
 #define MAX1111_CTRL_PD1      (1u << 1)
 #define MAX1111_CTRL_SGL      (1u << 2)
 #define MAX1111_CTRL_UNI      (1u << 3)
+#define MAX1110_CTRL_SEL_SH   (4)
 #define MAX1111_CTRL_SEL_SH   (5)	/* NOTE: bit 4 is ignored */
 #define MAX1111_CTRL_STR      (1u << 7)
 
@@ -42,6 +45,8 @@ struct max1111_data {
 	uint8_t rx_buf[MAX1111_RX_BUF_SIZE];
 	struct mutex		drvdata_lock;
 	/* protect msg, xfer and buffers from multiple access */
+	int			sel_sh;
+	int			lsb;
 };
 
 static int max1111_read(struct device *dev, int channel)
@@ -53,7 +58,7 @@ static int max1111_read(struct device *dev, int channel)
 	/* writing to drvdata struct is not thread safe, wait on mutex */
 	mutex_lock(&data->drvdata_lock);
 
-	data->tx_buf[0] = (channel << MAX1111_CTRL_SEL_SH) |
+	data->tx_buf[0] = (channel << data->sel_sh) |
 		MAX1111_CTRL_PD0 | MAX1111_CTRL_PD1 |
 		MAX1111_CTRL_SGL | MAX1111_CTRL_UNI | MAX1111_CTRL_STR;
 
@@ -93,12 +98,13 @@ EXPORT_SYMBOL(max1111_read_channel);
 static ssize_t show_name(struct device *dev,
 			 struct device_attribute *attr, char *buf)
 {
-	return sprintf(buf, "max1111\n");
+	return sprintf(buf, "%s\n", to_spi_device(dev)->modalias);
 }
 
 static ssize_t show_adc(struct device *dev,
 			struct device_attribute *attr, char *buf)
 {
+	struct max1111_data *data = dev_get_drvdata(dev);
 	int channel = to_sensor_dev_attr(attr)->index;
 	int ret;
 
@@ -107,10 +113,10 @@ static ssize_t show_adc(struct device *dev,
 		return ret;
 
 	/*
-	 * assume the reference voltage to be 2.048V, with an 8-bit sample,
-	 * the LSB weight is 8mV
+	 * Assume the reference voltage to be 2.048V or 4.096V, with an 8-bit
+	 * sample. The LSB weight is 8mV or 16mV depending on the chip type.
 	 */
-	return sprintf(buf, "%d\n", ret * 8);
+	return sprintf(buf, "%d\n", ret * data->lsb);
 }
 
 #define MAX1111_ADC_ATTR(_id)		\
@@ -121,6 +127,10 @@ static MAX1111_ADC_ATTR(0);
 static MAX1111_ADC_ATTR(1);
 static MAX1111_ADC_ATTR(2);
 static MAX1111_ADC_ATTR(3);
+static MAX1111_ADC_ATTR(4);
+static MAX1111_ADC_ATTR(5);
+static MAX1111_ADC_ATTR(6);
+static MAX1111_ADC_ATTR(7);
 
 static struct attribute *max1111_attributes[] = {
 	&dev_attr_name.attr,
@@ -135,6 +145,18 @@ static const struct attribute_group max1111_attr_group = {
 	.attrs	= max1111_attributes,
 };
 
+static struct attribute *max1110_attributes[] = {
+	&sensor_dev_attr_in4_input.dev_attr.attr,
+	&sensor_dev_attr_in5_input.dev_attr.attr,
+	&sensor_dev_attr_in6_input.dev_attr.attr,
+	&sensor_dev_attr_in7_input.dev_attr.attr,
+	NULL,
+};
+
+static const struct attribute_group max1110_attr_group = {
+	.attrs	= max1110_attributes,
+};
+
 static int __devinit setup_transfer(struct max1111_data *data)
 {
 	struct spi_message *m;
@@ -159,6 +181,7 @@ static int __devinit setup_transfer(struct max1111_data *data)
 
 static int __devinit max1111_probe(struct spi_device *spi)
 {
+	enum chips chip = spi_get_device_id(spi)->driver_data;
 	struct max1111_data *data;
 	int err;
 
@@ -174,6 +197,24 @@ static int __devinit max1111_probe(struct spi_device *spi)
 		return -ENOMEM;
 	}
 
+	switch (chip) {
+	case max1110:
+		data->lsb = 8;
+		data->sel_sh = MAX1110_CTRL_SEL_SH;
+		break;
+	case max1111:
+		data->lsb = 8;
+		data->sel_sh = MAX1111_CTRL_SEL_SH;
+		break;
+	case max1112:
+		data->lsb = 16;
+		data->sel_sh = MAX1110_CTRL_SEL_SH;
+		break;
+	case max1113:
+		data->lsb = 16;
+		data->sel_sh = MAX1111_CTRL_SEL_SH;
+		break;
+	}
 	err = setup_transfer(data);
 	if (err)
 		return err;
@@ -188,6 +229,14 @@ static int __devinit max1111_probe(struct spi_device *spi)
 		dev_err(&spi->dev, "failed to create attribute group\n");
 		return err;
 	}
+	if (chip == max1110 || chip == max1112) {
+		err = sysfs_create_group(&spi->dev.kobj, &max1110_attr_group);
+		if (err) {
+			dev_err(&spi->dev,
+				"failed to create extended attribute group\n");
+			goto err_remove;
+		}
+	}
 
 	data->hwmon_dev = hwmon_device_register(&spi->dev);
 	if (IS_ERR(data->hwmon_dev)) {
@@ -202,6 +251,7 @@ static int __devinit max1111_probe(struct spi_device *spi)
 	return 0;
 
 err_remove:
+	sysfs_remove_group(&spi->dev.kobj, &max1110_attr_group);
 	sysfs_remove_group(&spi->dev.kobj, &max1111_attr_group);
 	return err;
 }
@@ -211,16 +261,27 @@ static int __devexit max1111_remove(struct spi_device *spi)
 	struct max1111_data *data = spi_get_drvdata(spi);
 
 	hwmon_device_unregister(data->hwmon_dev);
+	sysfs_remove_group(&spi->dev.kobj, &max1110_attr_group);
 	sysfs_remove_group(&spi->dev.kobj, &max1111_attr_group);
 	mutex_destroy(&data->drvdata_lock);
 	return 0;
 }
 
+static const struct spi_device_id max1111_ids[] = {
+	{ "max1110", max1110 },
+	{ "max1111", max1111 },
+	{ "max1112", max1112 },
+	{ "max1113", max1113 },
+	{ },
+};
+MODULE_DEVICE_TABLE(spi, max1111_ids);
+
 static struct spi_driver max1111_driver = {
 	.driver		= {
 		.name	= "max1111",
 		.owner	= THIS_MODULE,
 	},
+	.id_table	= max1111_ids,
 	.probe		= max1111_probe,
 	.remove		= __devexit_p(max1111_remove),
 };
@@ -228,6 +289,5 @@ static struct spi_driver max1111_driver = {
 module_spi_driver(max1111_driver);
 
 MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>");
-MODULE_DESCRIPTION("MAX1111 ADC Driver");
+MODULE_DESCRIPTION("MAX1110/MAX1111/MAX1112/MAX1113 ADC Driver");
 MODULE_LICENSE("GPL");
-MODULE_ALIAS("spi:max1111");
diff --git a/drivers/hwmon/max1619.c b/drivers/hwmon/max1619.c
index 6c11ec2..445e5d4 100644
--- a/drivers/hwmon/max1619.c
+++ b/drivers/hwmon/max1619.c
@@ -1,7 +1,7 @@
 /*
  * max1619.c - Part of lm_sensors, Linux kernel modules for hardware
  *             monitoring
- * Copyright (C) 2003-2004 Alexey Fisher <fishor@mail.ru>
+ * Copyright (C) 2003-2004 Oleksij Rempel <bug-track@fisher-privat.net>
  *                         Jean Delvare <khali@linux-fr.org>
  *
  * Based on the lm90 driver. The MAX1619 is a sensor chip made by Maxim.
@@ -357,7 +357,7 @@ static struct max1619_data *max1619_update_device(struct device *dev)
 
 module_i2c_driver(max1619_driver);
 
-MODULE_AUTHOR("Alexey Fisher <fishor@mail.ru> and "
+MODULE_AUTHOR("Oleksij Rempel <bug-track@fisher-privat.net> and "
 	"Jean Delvare <khali@linux-fr.org>");
 MODULE_DESCRIPTION("MAX1619 sensor driver");
 MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/max1668.c b/drivers/hwmon/max1668.c
index 335b183..666d9f6 100644
--- a/drivers/hwmon/max1668.c
+++ b/drivers/hwmon/max1668.c
@@ -411,7 +411,8 @@ static int max1668_probe(struct i2c_client *client,
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 		return -ENODEV;
 
-	data = kzalloc(sizeof(struct max1668_data), GFP_KERNEL);
+	data = devm_kzalloc(&client->dev, sizeof(struct max1668_data),
+			    GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
 
@@ -422,7 +423,7 @@ static int max1668_probe(struct i2c_client *client,
 	/* Register sysfs hooks */
 	err = sysfs_create_group(&client->dev.kobj, &max1668_group_common);
 	if (err)
-		goto error_free;
+		return err;
 
 	if (data->type == max1668 || data->type == max1989) {
 		err = sysfs_create_group(&client->dev.kobj,
@@ -444,8 +445,6 @@ error_sysrem1:
 		sysfs_remove_group(&client->dev.kobj, &max1668_group_unique);
 error_sysrem0:
 	sysfs_remove_group(&client->dev.kobj, &max1668_group_common);
-error_free:
-	kfree(data);
 	return err;
 }
 
@@ -459,7 +458,6 @@ static int max1668_remove(struct i2c_client *client)
 
 	sysfs_remove_group(&client->dev.kobj, &max1668_group_common);
 
-	kfree(data);
 	return 0;
 }
 
diff --git a/drivers/hwmon/max197.c b/drivers/hwmon/max197.c
new file mode 100644
index 0000000..6304f26
--- /dev/null
+++ b/drivers/hwmon/max197.c
@@ -0,0 +1,349 @@
+/*
+ * Maxim MAX197 A/D Converter driver
+ *
+ * Copyright (c) 2012 Savoir-faire Linux Inc.
+ *          Vivien Didelot <vivien.didelot@savoirfairelinux.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.
+ *
+ * For further information, see the Documentation/hwmon/max197 file.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/mutex.h>
+#include <linux/device.h>
+#include <linux/sysfs.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/platform_device.h>
+#include <linux/platform_data/max197.h>
+
+#define MAX199_LIMIT	4000		/* 4V */
+#define MAX197_LIMIT	10000		/* 10V */
+
+#define MAX197_NUM_CH	8		/* 8 Analog Input Channels */
+
+/* Control byte format */
+#define MAX197_BIP	(1 << 3)	/* Bipolarity */
+#define MAX197_RNG	(1 << 4)	/* Full range */
+
+#define MAX197_SCALE	12207		/* Scale coefficient for raw data */
+
+/* List of supported chips */
+enum max197_chips { max197, max199 };
+
+/**
+ * struct max197_data - device instance specific data
+ * @pdata:		Platform data.
+ * @hwmon_dev:		The hwmon device.
+ * @lock:		Read/Write mutex.
+ * @limit:		Max range value (10V for MAX197, 4V for MAX199).
+ * @scale:		Need to scale.
+ * @ctrl_bytes:		Channels control byte.
+ */
+struct max197_data {
+	struct max197_platform_data *pdata;
+	struct device *hwmon_dev;
+	struct mutex lock;
+	int limit;
+	bool scale;
+	u8 ctrl_bytes[MAX197_NUM_CH];
+};
+
+static inline void max197_set_unipolarity(struct max197_data *data, int channel)
+{
+	data->ctrl_bytes[channel] &= ~MAX197_BIP;
+}
+
+static inline void max197_set_bipolarity(struct max197_data *data, int channel)
+{
+	data->ctrl_bytes[channel] |= MAX197_BIP;
+}
+
+static inline void max197_set_half_range(struct max197_data *data, int channel)
+{
+	data->ctrl_bytes[channel] &= ~MAX197_RNG;
+}
+
+static inline void max197_set_full_range(struct max197_data *data, int channel)
+{
+	data->ctrl_bytes[channel] |= MAX197_RNG;
+}
+
+static inline bool max197_is_bipolar(struct max197_data *data, int channel)
+{
+	return data->ctrl_bytes[channel] & MAX197_BIP;
+}
+
+static inline bool max197_is_full_range(struct max197_data *data, int channel)
+{
+	return data->ctrl_bytes[channel] & MAX197_RNG;
+}
+
+/* Function called on read access on in{0,1,2,3,4,5,6,7}_{min,max} */
+static ssize_t max197_show_range(struct device *dev,
+				 struct device_attribute *devattr, char *buf)
+{
+	struct max197_data *data = dev_get_drvdata(dev);
+	struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
+	int channel = attr->index;
+	bool is_min = attr->nr;
+	int range;
+
+	if (mutex_lock_interruptible(&data->lock))
+		return -ERESTARTSYS;
+
+	range = max197_is_full_range(data, channel) ?
+		data->limit : data->limit / 2;
+	if (is_min) {
+		if (max197_is_bipolar(data, channel))
+			range = -range;
+		else
+			range = 0;
+	}
+
+	mutex_unlock(&data->lock);
+
+	return sprintf(buf, "%d\n", range);
+}
+
+/* Function called on write access on in{0,1,2,3,4,5,6,7}_{min,max} */
+static ssize_t max197_store_range(struct device *dev,
+				  struct device_attribute *devattr,
+				  const char *buf, size_t count)
+{
+	struct max197_data *data = dev_get_drvdata(dev);
+	struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
+	int channel = attr->index;
+	bool is_min = attr->nr;
+	long value;
+	int half = data->limit / 2;
+	int full = data->limit;
+
+	if (kstrtol(buf, 10, &value))
+		return -EINVAL;
+
+	if (is_min) {
+		if (value <= -full)
+			value = -full;
+		else if (value < 0)
+			value = -half;
+		else
+			value = 0;
+	} else {
+		if (value >= full)
+			value = full;
+		else
+			value = half;
+	}
+
+	if (mutex_lock_interruptible(&data->lock))
+		return -ERESTARTSYS;
+
+	if (value == 0) {
+		/* We can deduce only the polarity */
+		max197_set_unipolarity(data, channel);
+	} else if (value == -half) {
+		max197_set_bipolarity(data, channel);
+		max197_set_half_range(data, channel);
+	} else if (value == -full) {
+		max197_set_bipolarity(data, channel);
+		max197_set_full_range(data, channel);
+	} else if (value == half) {
+		/* We can deduce only the range */
+		max197_set_half_range(data, channel);
+	} else if (value == full) {
+		/* We can deduce only the range */
+		max197_set_full_range(data, channel);
+	}
+
+	mutex_unlock(&data->lock);
+
+	return count;
+}
+
+/* Function called on read access on in{0,1,2,3,4,5,6,7}_input */
+static ssize_t max197_show_input(struct device *dev,
+				 struct device_attribute *devattr,
+				 char *buf)
+{
+	struct max197_data *data = dev_get_drvdata(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	int channel = attr->index;
+	s32 value;
+	int ret;
+
+	if (mutex_lock_interruptible(&data->lock))
+		return -ERESTARTSYS;
+
+	ret = data->pdata->convert(data->ctrl_bytes[channel]);
+	if (ret < 0) {
+		dev_err(dev, "conversion failed\n");
+		goto unlock;
+	}
+	value = ret;
+
+	/*
+	 * Coefficient to apply on raw value.
+	 * See Table 1. Full Scale and Zero Scale in the MAX197 datasheet.
+	 */
+	if (data->scale) {
+		value *= MAX197_SCALE;
+		if (max197_is_full_range(data, channel))
+			value *= 2;
+		value /= 10000;
+	}
+
+	ret = sprintf(buf, "%d\n", value);
+
+unlock:
+	mutex_unlock(&data->lock);
+	return ret;
+}
+
+static ssize_t max197_show_name(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	return sprintf(buf, "%s\n", pdev->name);
+}
+
+#define MAX197_SENSOR_DEVICE_ATTR_CH(chan)				\
+	static SENSOR_DEVICE_ATTR(in##chan##_input, S_IRUGO,		\
+				  max197_show_input, NULL, chan);	\
+	static SENSOR_DEVICE_ATTR_2(in##chan##_min, S_IRUGO | S_IWUSR,	\
+				    max197_show_range,			\
+				    max197_store_range,			\
+				    true, chan);			\
+	static SENSOR_DEVICE_ATTR_2(in##chan##_max, S_IRUGO | S_IWUSR,	\
+				    max197_show_range,			\
+				    max197_store_range,			\
+				    false, chan)
+
+#define MAX197_SENSOR_DEV_ATTR_IN(chan)					\
+	&sensor_dev_attr_in##chan##_input.dev_attr.attr,		\
+	&sensor_dev_attr_in##chan##_max.dev_attr.attr,			\
+	&sensor_dev_attr_in##chan##_min.dev_attr.attr
+
+static DEVICE_ATTR(name, S_IRUGO, max197_show_name, NULL);
+
+MAX197_SENSOR_DEVICE_ATTR_CH(0);
+MAX197_SENSOR_DEVICE_ATTR_CH(1);
+MAX197_SENSOR_DEVICE_ATTR_CH(2);
+MAX197_SENSOR_DEVICE_ATTR_CH(3);
+MAX197_SENSOR_DEVICE_ATTR_CH(4);
+MAX197_SENSOR_DEVICE_ATTR_CH(5);
+MAX197_SENSOR_DEVICE_ATTR_CH(6);
+MAX197_SENSOR_DEVICE_ATTR_CH(7);
+
+static const struct attribute_group max197_sysfs_group = {
+	.attrs = (struct attribute *[]) {
+		&dev_attr_name.attr,
+		MAX197_SENSOR_DEV_ATTR_IN(0),
+		MAX197_SENSOR_DEV_ATTR_IN(1),
+		MAX197_SENSOR_DEV_ATTR_IN(2),
+		MAX197_SENSOR_DEV_ATTR_IN(3),
+		MAX197_SENSOR_DEV_ATTR_IN(4),
+		MAX197_SENSOR_DEV_ATTR_IN(5),
+		MAX197_SENSOR_DEV_ATTR_IN(6),
+		MAX197_SENSOR_DEV_ATTR_IN(7),
+		NULL
+	},
+};
+
+static int __devinit max197_probe(struct platform_device *pdev)
+{
+	int ch, ret;
+	struct max197_data *data;
+	struct max197_platform_data *pdata = pdev->dev.platform_data;
+	enum max197_chips chip = platform_get_device_id(pdev)->driver_data;
+
+	if (pdata == NULL) {
+		dev_err(&pdev->dev, "no platform data supplied\n");
+		return -EINVAL;
+	}
+
+	if (pdata->convert == NULL) {
+		dev_err(&pdev->dev, "no convert function supplied\n");
+		return -EINVAL;
+	}
+
+	data = devm_kzalloc(&pdev->dev, sizeof(struct max197_data), GFP_KERNEL);
+	if (!data) {
+		dev_err(&pdev->dev, "devm_kzalloc failed\n");
+		return -ENOMEM;
+	}
+
+	data->pdata = pdata;
+	mutex_init(&data->lock);
+
+	if (chip == max197) {
+		data->limit = MAX197_LIMIT;
+		data->scale = true;
+	} else {
+		data->limit = MAX199_LIMIT;
+		data->scale = false;
+	}
+
+	for (ch = 0; ch < MAX197_NUM_CH; ch++)
+		data->ctrl_bytes[ch] = (u8) ch;
+
+	platform_set_drvdata(pdev, data);
+
+	ret = sysfs_create_group(&pdev->dev.kobj, &max197_sysfs_group);
+	if (ret) {
+		dev_err(&pdev->dev, "sysfs create group failed\n");
+		return ret;
+	}
+
+	data->hwmon_dev = hwmon_device_register(&pdev->dev);
+	if (IS_ERR(data->hwmon_dev)) {
+		ret = PTR_ERR(data->hwmon_dev);
+		dev_err(&pdev->dev, "hwmon device register failed\n");
+		goto error;
+	}
+
+	return 0;
+
+error:
+	sysfs_remove_group(&pdev->dev.kobj, &max197_sysfs_group);
+	return ret;
+}
+
+static int __devexit max197_remove(struct platform_device *pdev)
+{
+	struct max197_data *data = platform_get_drvdata(pdev);
+
+	hwmon_device_unregister(data->hwmon_dev);
+	sysfs_remove_group(&pdev->dev.kobj, &max197_sysfs_group);
+
+	return 0;
+}
+
+static struct platform_device_id max197_device_ids[] = {
+	{ "max197", max197 },
+	{ "max199", max199 },
+	{ }
+};
+MODULE_DEVICE_TABLE(platform, max197_device_ids);
+
+static struct platform_driver max197_driver = {
+	.driver = {
+		.name = "max197",
+		.owner = THIS_MODULE,
+	},
+	.probe = max197_probe,
+	.remove = __devexit_p(max197_remove),
+	.id_table = max197_device_ids,
+};
+module_platform_driver(max197_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Savoir-faire Linux Inc. <kernel@savoirfairelinux.com>");
+MODULE_DESCRIPTION("Maxim MAX197 A/D Converter driver");
diff --git a/drivers/hwmon/max6642.c b/drivers/hwmon/max6642.c
index bf236c0..223461a 100644
--- a/drivers/hwmon/max6642.c
+++ b/drivers/hwmon/max6642.c
@@ -7,7 +7,7 @@
  * Derived from:
  *
  *  Based on the max1619 driver.
- *  Copyright (C) 2003-2004 Alexey Fisher <fishor@mail.ru>
+ *  Copyright (C) 2003-2004 Oleksij Rempel <bug-track@fisher-privat.net>
  *                          Jean Delvare <khali@linux-fr.org>
  *
  * The MAX6642 is a sensor chip made by Maxim.
diff --git a/drivers/hwmon/mcp3021.c b/drivers/hwmon/mcp3021.c
index d0afc0c..eedb322 100644
--- a/drivers/hwmon/mcp3021.c
+++ b/drivers/hwmon/mcp3021.c
@@ -1,8 +1,9 @@
 /*
- * mcp3021.c - driver for the Microchip MCP3021 chip
+ * mcp3021.c - driver for Microchip MCP3021 and MCP3221
  *
  * Copyright (C) 2008-2009, 2012 Freescale Semiconductor, Inc.
  * Author: Mingkai Hu <Mingkai.hu@freescale.com>
+ * Reworked by Sven Schuchmann <schuchmann@schleissheimer.de>
  *
  * This driver export the value of analog input voltage to sysfs, the
  * voltage unit is mV. Through the sysfs interface, lm-sensors tool
@@ -34,16 +35,31 @@
 #define MCP3021_OUTPUT_RES	10	/* 10-bit resolution */
 #define MCP3021_OUTPUT_SCALE	4
 
+#define MCP3221_SAR_SHIFT	0
+#define MCP3221_SAR_MASK	0xfff
+#define MCP3221_OUTPUT_RES	12	/* 12-bit resolution */
+#define MCP3221_OUTPUT_SCALE	1
+
+enum chips {
+	mcp3021,
+	mcp3221
+};
+
 /*
  * Client data (each client gets its own)
  */
 struct mcp3021_data {
 	struct device *hwmon_dev;
 	u32 vdd;	/* device power supply */
+	u16 sar_shift;
+	u16 sar_mask;
+	u8 output_res;
+	u8 output_scale;
 };
 
 static int mcp3021_read16(struct i2c_client *client)
 {
+	struct mcp3021_data *data = i2c_get_clientdata(client);
 	int ret;
 	u16 reg;
 	__be16 buf;
@@ -61,20 +77,20 @@ static int mcp3021_read16(struct i2c_client *client)
 	 * The ten-bit output code is composed of the lower 4-bit of the
 	 * first byte and the upper 6-bit of the second byte.
 	 */
-	reg = (reg >> MCP3021_SAR_SHIFT) & MCP3021_SAR_MASK;
+	reg = (reg >> data->sar_shift) & data->sar_mask;
 
 	return reg;
 }
 
-static inline u16 volts_from_reg(u16 vdd, u16 val)
+static inline u16 volts_from_reg(struct mcp3021_data *data, u16 val)
 {
 	if (val == 0)
 		return 0;
 
-	val = val * MCP3021_OUTPUT_SCALE - MCP3021_OUTPUT_SCALE / 2;
+	val = val * data->output_scale - data->output_scale / 2;
 
-	return val * DIV_ROUND_CLOSEST(vdd,
-			(1 << MCP3021_OUTPUT_RES) * MCP3021_OUTPUT_SCALE);
+	return val * DIV_ROUND_CLOSEST(data->vdd,
+			(1 << data->output_res) * data->output_scale);
 }
 
 static ssize_t show_in_input(struct device *dev, struct device_attribute *attr,
@@ -88,7 +104,8 @@ static ssize_t show_in_input(struct device *dev, struct device_attribute *attr,
 	if (reg < 0)
 		return reg;
 
-	in_input = volts_from_reg(data->vdd, reg);
+	in_input = volts_from_reg(data, reg);
+
 	return sprintf(buf, "%d\n", in_input);
 }
 
@@ -103,25 +120,39 @@ static int mcp3021_probe(struct i2c_client *client,
 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
 		return -ENODEV;
 
-	data = kzalloc(sizeof(struct mcp3021_data), GFP_KERNEL);
+	data = devm_kzalloc(&client->dev, sizeof(struct mcp3021_data),
+			    GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
 
 	i2c_set_clientdata(client, data);
 
+	switch (id->driver_data) {
+	case mcp3021:
+		data->sar_shift = MCP3021_SAR_SHIFT;
+		data->sar_mask = MCP3021_SAR_MASK;
+		data->output_res = MCP3021_OUTPUT_RES;
+		data->output_scale = MCP3021_OUTPUT_SCALE;
+		break;
+
+	case mcp3221:
+		data->sar_shift = MCP3221_SAR_SHIFT;
+		data->sar_mask = MCP3221_SAR_MASK;
+		data->output_res = MCP3221_OUTPUT_RES;
+		data->output_scale = MCP3221_OUTPUT_SCALE;
+		break;
+	}
+
 	if (client->dev.platform_data) {
 		data->vdd = *(u32 *)client->dev.platform_data;
-		if (data->vdd > MCP3021_VDD_MAX ||
-				data->vdd < MCP3021_VDD_MIN) {
-			err = -EINVAL;
-			goto exit_free;
-		}
+		if (data->vdd > MCP3021_VDD_MAX || data->vdd < MCP3021_VDD_MIN)
+			return -EINVAL;
 	} else
 		data->vdd = MCP3021_VDD_REF;
 
 	err = sysfs_create_file(&client->dev.kobj, &dev_attr_in0_input.attr);
 	if (err)
-		goto exit_free;
+		return err;
 
 	data->hwmon_dev = hwmon_device_register(&client->dev);
 	if (IS_ERR(data->hwmon_dev)) {
@@ -133,8 +164,6 @@ static int mcp3021_probe(struct i2c_client *client,
 
 exit_remove:
 	sysfs_remove_file(&client->dev.kobj, &dev_attr_in0_input.attr);
-exit_free:
-	kfree(data);
 	return err;
 }
 
@@ -144,13 +173,13 @@ static int mcp3021_remove(struct i2c_client *client)
 
 	hwmon_device_unregister(data->hwmon_dev);
 	sysfs_remove_file(&client->dev.kobj, &dev_attr_in0_input.attr);
-	kfree(data);
 
 	return 0;
 }
 
 static const struct i2c_device_id mcp3021_id[] = {
-	{ "mcp3021", 0 },
+	{ "mcp3021", mcp3021 },
+	{ "mcp3221", mcp3221 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, mcp3021_id);
@@ -167,5 +196,5 @@ static struct i2c_driver mcp3021_driver = {
 module_i2c_driver(mcp3021_driver);
 
 MODULE_AUTHOR("Mingkai Hu <Mingkai.hu@freescale.com>");
-MODULE_DESCRIPTION("Microchip MCP3021 driver");
+MODULE_DESCRIPTION("Microchip MCP3021/MCP3221 driver");
 MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/s3c-hwmon.c b/drivers/hwmon/s3c-hwmon.c
index b7975f8..fe11b95 100644
--- a/drivers/hwmon/s3c-hwmon.c
+++ b/drivers/hwmon/s3c-hwmon.c
@@ -34,7 +34,7 @@
 #include <linux/hwmon-sysfs.h>
 
 #include <plat/adc.h>
-#include <plat/hwmon.h>
+#include <linux/platform_data/hwmon-s3c.h>
 
 struct s3c_hwmon_attr {
 	struct sensor_device_attribute	in;
diff --git a/drivers/hwmon/sch5627.c b/drivers/hwmon/sch5627.c
index 8342275..49f6230 100644
--- a/drivers/hwmon/sch5627.c
+++ b/drivers/hwmon/sch5627.c
@@ -461,8 +461,6 @@ static int sch5627_remove(struct platform_device *pdev)
 		hwmon_device_unregister(data->hwmon_dev);
 
 	sysfs_remove_group(&pdev->dev.kobj, &sch5627_group);
-	platform_set_drvdata(pdev, NULL);
-	kfree(data);
 
 	return 0;
 }
@@ -472,7 +470,8 @@ static int __devinit sch5627_probe(struct platform_device *pdev)
 	struct sch5627_data *data;
 	int err, build_code, build_id, hwmon_rev, val;
 
-	data = kzalloc(sizeof(struct sch5627_data), GFP_KERNEL);
+	data = devm_kzalloc(&pdev->dev, sizeof(struct sch5627_data),
+			    GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
 
diff --git a/drivers/hwmon/sch5636.c b/drivers/hwmon/sch5636.c
index 96a7e68..5171180 100644
--- a/drivers/hwmon/sch5636.c
+++ b/drivers/hwmon/sch5636.c
@@ -402,9 +402,6 @@ static int sch5636_remove(struct platform_device *pdev)
 		device_remove_file(&pdev->dev,
 				   &sch5636_fan_attr[i].dev_attr);
 
-	platform_set_drvdata(pdev, NULL);
-	kfree(data);
-
 	return 0;
 }
 
@@ -414,7 +411,8 @@ static int __devinit sch5636_probe(struct platform_device *pdev)
 	int i, err, val, revision[2];
 	char id[4];
 
-	data = kzalloc(sizeof(struct sch5636_data), GFP_KERNEL);
+	data = devm_kzalloc(&pdev->dev, sizeof(struct sch5636_data),
+			    GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
 
diff --git a/drivers/hwmon/sch56xx-common.c b/drivers/hwmon/sch56xx-common.c
index 4380f5d..d00b30a 100644
--- a/drivers/hwmon/sch56xx-common.c
+++ b/drivers/hwmon/sch56xx-common.c
@@ -503,10 +503,10 @@ EXPORT_SYMBOL(sch56xx_watchdog_unregister);
  * platform dev find, add and remove functions
  */
 
-static int __init sch56xx_find(int sioaddr, unsigned short *address,
-			       const char **name)
+static int __init sch56xx_find(int sioaddr, const char **name)
 {
 	u8 devid;
+	unsigned short address;
 	int err;
 
 	err = superio_enter(sioaddr);
@@ -540,20 +540,21 @@ static int __init sch56xx_find(int sioaddr, unsigned short *address,
 	 * Warning the order of the low / high byte is the other way around
 	 * as on most other superio devices!!
 	 */
-	*address = superio_inb(sioaddr, SIO_REG_ADDR) |
+	address = superio_inb(sioaddr, SIO_REG_ADDR) |
 		   superio_inb(sioaddr, SIO_REG_ADDR + 1) << 8;
-	if (*address == 0) {
+	if (address == 0) {
 		pr_warn("Base address not set\n");
 		err = -ENODEV;
 		goto exit;
 	}
+	err = address;
 
 exit:
 	superio_exit(sioaddr);
 	return err;
 }
 
-static int __init sch56xx_device_add(unsigned short address, const char *name)
+static int __init sch56xx_device_add(int address, const char *name)
 {
 	struct resource res = {
 		.start	= address,
@@ -593,15 +594,14 @@ exit_device_put:
 
 static int __init sch56xx_init(void)
 {
-	int err;
-	unsigned short address;
-	const char *name;
-
-	err = sch56xx_find(0x4e, &address, &name);
-	if (err)
-		err = sch56xx_find(0x2e, &address, &name);
-	if (err)
-		return err;
+	int address;
+	const char *name = NULL;
+
+	address = sch56xx_find(0x4e, &name);
+	if (address < 0)
+		address = sch56xx_find(0x2e, &name);
+	if (address < 0)
+		return address;
 
 	return sch56xx_device_add(address, name);
 }
diff --git a/drivers/hwmon/sht15.c b/drivers/hwmon/sht15.c
index 8b011d0..07a0c1a 100644
--- a/drivers/hwmon/sht15.c
+++ b/drivers/hwmon/sht15.c
@@ -1,7 +1,7 @@
 /*
  * sht15.c - support for the SHT15 Temperature and Humidity Sensor
  *
- * Portions Copyright (c) 2010-2011 Savoir-faire Linux Inc.
+ * Portions Copyright (c) 2010-2012 Savoir-faire Linux Inc.
  *          Jerome Oufella <jerome.oufella@savoirfairelinux.com>
  *          Vivien Didelot <vivien.didelot@savoirfairelinux.com>
  *
@@ -24,12 +24,12 @@
 #include <linux/hwmon.h>
 #include <linux/hwmon-sysfs.h>
 #include <linux/mutex.h>
+#include <linux/platform_data/sht15.h>
 #include <linux/platform_device.h>
 #include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/jiffies.h>
 #include <linux/err.h>
-#include <linux/sht15.h>
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
 #include <linux/atomic.h>
@@ -53,6 +53,9 @@
 #define SHT15_STATUS_HEATER		0x04
 #define SHT15_STATUS_LOW_BATTERY	0x40
 
+/* List of supported chips */
+enum sht15_chips { sht10, sht11, sht15, sht71, sht75 };
+
 /* Actions the driver may be doing */
 enum sht15_state {
 	SHT15_READING_NOTHING,
@@ -884,14 +887,12 @@ static int sht15_invalidate_voltage(struct notifier_block *nb,
 static int __devinit sht15_probe(struct platform_device *pdev)
 {
 	int ret;
-	struct sht15_data *data = kzalloc(sizeof(*data), GFP_KERNEL);
+	struct sht15_data *data;
 	u8 status = 0;
 
-	if (!data) {
-		ret = -ENOMEM;
-		dev_err(&pdev->dev, "kzalloc failed\n");
-		goto error_ret;
-	}
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
 
 	INIT_WORK(&data->read_work, sht15_bh_read_data);
 	INIT_WORK(&data->update_supply_work, sht15_update_voltage);
@@ -901,9 +902,8 @@ static int __devinit sht15_probe(struct platform_device *pdev)
 	init_waitqueue_head(&data->wait_queue);
 
 	if (pdev->dev.platform_data == NULL) {
-		ret = -EINVAL;
 		dev_err(&pdev->dev, "no platform data supplied\n");
-		goto err_free_data;
+		return -EINVAL;
 	}
 	data->pdata = pdev->dev.platform_data;
 	data->supply_uV = data->pdata->supply_mv * 1000;
@@ -918,7 +918,7 @@ static int __devinit sht15_probe(struct platform_device *pdev)
 	 * If a regulator is available,
 	 * query what the supply voltage actually is!
 	 */
-	data->reg = regulator_get(data->dev, "vcc");
+	data->reg = devm_regulator_get(data->dev, "vcc");
 	if (!IS_ERR(data->reg)) {
 		int voltage;
 
@@ -937,51 +937,51 @@ static int __devinit sht15_probe(struct platform_device *pdev)
 			dev_err(&pdev->dev,
 				"regulator notifier request failed\n");
 			regulator_disable(data->reg);
-			regulator_put(data->reg);
-			goto err_free_data;
+			return ret;
 		}
 	}
 
 	/* Try requesting the GPIOs */
-	ret = gpio_request(data->pdata->gpio_sck, "SHT15 sck");
+	ret = devm_gpio_request(&pdev->dev, data->pdata->gpio_sck, "SHT15 sck");
 	if (ret) {
 		dev_err(&pdev->dev, "gpio request failed\n");
 		goto err_release_reg;
 	}
 	gpio_direction_output(data->pdata->gpio_sck, 0);
 
-	ret = gpio_request(data->pdata->gpio_data, "SHT15 data");
+	ret = devm_gpio_request(&pdev->dev, data->pdata->gpio_data,
+				"SHT15 data");
 	if (ret) {
 		dev_err(&pdev->dev, "gpio request failed\n");
-		goto err_release_gpio_sck;
+		goto err_release_reg;
 	}
 
-	ret = request_irq(gpio_to_irq(data->pdata->gpio_data),
-			  sht15_interrupt_fired,
-			  IRQF_TRIGGER_FALLING,
-			  "sht15 data",
-			  data);
+	ret = devm_request_irq(&pdev->dev, gpio_to_irq(data->pdata->gpio_data),
+			       sht15_interrupt_fired,
+			       IRQF_TRIGGER_FALLING,
+			       "sht15 data",
+			       data);
 	if (ret) {
 		dev_err(&pdev->dev, "failed to get irq for data line\n");
-		goto err_release_gpio_data;
+		goto err_release_reg;
 	}
 	disable_irq_nosync(gpio_to_irq(data->pdata->gpio_data));
 	sht15_connection_reset(data);
 	ret = sht15_soft_reset(data);
 	if (ret)
-		goto err_release_irq;
+		goto err_release_reg;
 
 	/* write status with platform data options */
 	if (status) {
 		ret = sht15_send_status(data, status);
 		if (ret)
-			goto err_release_irq;
+			goto err_release_reg;
 	}
 
 	ret = sysfs_create_group(&pdev->dev.kobj, &sht15_attr_group);
 	if (ret) {
 		dev_err(&pdev->dev, "sysfs create failed\n");
-		goto err_release_irq;
+		goto err_release_reg;
 	}
 
 	data->hwmon_dev = hwmon_device_register(data->dev);
@@ -994,21 +994,11 @@ static int __devinit sht15_probe(struct platform_device *pdev)
 
 err_release_sysfs_group:
 	sysfs_remove_group(&pdev->dev.kobj, &sht15_attr_group);
-err_release_irq:
-	free_irq(gpio_to_irq(data->pdata->gpio_data), data);
-err_release_gpio_data:
-	gpio_free(data->pdata->gpio_data);
-err_release_gpio_sck:
-	gpio_free(data->pdata->gpio_sck);
 err_release_reg:
 	if (!IS_ERR(data->reg)) {
 		regulator_unregister_notifier(data->reg, &data->nb);
 		regulator_disable(data->reg);
-		regulator_put(data->reg);
 	}
-err_free_data:
-	kfree(data);
-error_ret:
 	return ret;
 }
 
@@ -1030,89 +1020,33 @@ static int __devexit sht15_remove(struct platform_device *pdev)
 	if (!IS_ERR(data->reg)) {
 		regulator_unregister_notifier(data->reg, &data->nb);
 		regulator_disable(data->reg);
-		regulator_put(data->reg);
 	}
 
-	free_irq(gpio_to_irq(data->pdata->gpio_data), data);
-	gpio_free(data->pdata->gpio_data);
-	gpio_free(data->pdata->gpio_sck);
 	mutex_unlock(&data->read_lock);
-	kfree(data);
 
 	return 0;
 }
 
-/*
- * sht_drivers simultaneously refers to __devinit and __devexit function
- * which causes spurious section mismatch warning. So use __refdata to
- * get rid from this.
- */
-static struct platform_driver __refdata sht_drivers[] = {
-	{
-		.driver = {
-			.name = "sht10",
-			.owner = THIS_MODULE,
-		},
-		.probe = sht15_probe,
-		.remove = __devexit_p(sht15_remove),
-	}, {
-		.driver = {
-			.name = "sht11",
-			.owner = THIS_MODULE,
-		},
-		.probe = sht15_probe,
-		.remove = __devexit_p(sht15_remove),
-	}, {
-		.driver = {
-			.name = "sht15",
-			.owner = THIS_MODULE,
-		},
-		.probe = sht15_probe,
-		.remove = __devexit_p(sht15_remove),
-	}, {
-		.driver = {
-			.name = "sht71",
-			.owner = THIS_MODULE,
-		},
-		.probe = sht15_probe,
-		.remove = __devexit_p(sht15_remove),
-	}, {
-		.driver = {
-			.name = "sht75",
-			.owner = THIS_MODULE,
-		},
-		.probe = sht15_probe,
-		.remove = __devexit_p(sht15_remove),
-	},
+static struct platform_device_id sht15_device_ids[] = {
+	{ "sht10", sht10 },
+	{ "sht11", sht11 },
+	{ "sht15", sht15 },
+	{ "sht71", sht71 },
+	{ "sht75", sht75 },
+	{ }
 };
+MODULE_DEVICE_TABLE(platform, sht15_device_ids);
 
-static int __init sht15_init(void)
-{
-	int ret;
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(sht_drivers); i++) {
-		ret = platform_driver_register(&sht_drivers[i]);
-		if (ret)
-			goto error_unreg;
-	}
-
-	return 0;
-
-error_unreg:
-	while (--i >= 0)
-		platform_driver_unregister(&sht_drivers[i]);
-
-	return ret;
-}
-module_init(sht15_init);
-
-static void __exit sht15_exit(void)
-{
-	int i;
-	for (i = ARRAY_SIZE(sht_drivers) - 1; i >= 0; i--)
-		platform_driver_unregister(&sht_drivers[i]);
-}
-module_exit(sht15_exit);
+static struct platform_driver sht15_driver = {
+	.driver = {
+		.name = "sht15",
+		.owner = THIS_MODULE,
+	},
+	.probe = sht15_probe,
+	.remove = __devexit_p(sht15_remove),
+	.id_table = sht15_device_ids,
+};
+module_platform_driver(sht15_driver);
 
 MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Sensirion SHT15 temperature and humidity sensor driver");
diff --git a/drivers/hwmon/sht21.c b/drivers/hwmon/sht21.c
index 6c2dede..c2565d0 100644
--- a/drivers/hwmon/sht21.c
+++ b/drivers/hwmon/sht21.c
@@ -199,11 +199,10 @@ static int __devinit sht21_probe(struct i2c_client *client,
 		return -ENODEV;
 	}
 
-	sht21 = kzalloc(sizeof(*sht21), GFP_KERNEL);
-	if (!sht21) {
-		dev_dbg(&client->dev, "kzalloc failed\n");
+	sht21 = devm_kzalloc(&client->dev, sizeof(*sht21), GFP_KERNEL);
+	if (!sht21)
 		return -ENOMEM;
-	}
+
 	i2c_set_clientdata(client, sht21);
 
 	mutex_init(&sht21->lock);
@@ -211,7 +210,7 @@ static int __devinit sht21_probe(struct i2c_client *client,
 	err = sysfs_create_group(&client->dev.kobj, &sht21_attr_group);
 	if (err) {
 		dev_dbg(&client->dev, "could not create sysfs files\n");
-		goto fail_free;
+		return err;
 	}
 	sht21->hwmon_dev = hwmon_device_register(&client->dev);
 	if (IS_ERR(sht21->hwmon_dev)) {
@@ -226,9 +225,6 @@ static int __devinit sht21_probe(struct i2c_client *client,
 
 fail_remove_sysfs:
 	sysfs_remove_group(&client->dev.kobj, &sht21_attr_group);
-fail_free:
-	kfree(sht21);
-
 	return err;
 }
 
@@ -242,7 +238,6 @@ static int __devexit sht21_remove(struct i2c_client *client)
 
 	hwmon_device_unregister(sht21->hwmon_dev);
 	sysfs_remove_group(&client->dev.kobj, &sht21_attr_group);
-	kfree(sht21);
 
 	return 0;
 }
diff --git a/drivers/hwmon/via-cputemp.c b/drivers/hwmon/via-cputemp.c
index 2e56c6c..4cddee0 100644
--- a/drivers/hwmon/via-cputemp.c
+++ b/drivers/hwmon/via-cputemp.c
@@ -128,12 +128,10 @@ static int __devinit via_cputemp_probe(struct platform_device *pdev)
 	int err;
 	u32 eax, edx;
 
-	data = kzalloc(sizeof(struct via_cputemp_data), GFP_KERNEL);
-	if (!data) {
-		err = -ENOMEM;
-		dev_err(&pdev->dev, "Out of memory\n");
-		goto exit;
-	}
+	data = devm_kzalloc(&pdev->dev, sizeof(struct via_cputemp_data),
+			    GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
 
 	data->id = pdev->id;
 	data->name = "via_cputemp";
@@ -151,8 +149,7 @@ static int __devinit via_cputemp_probe(struct platform_device *pdev)
 		data->msr_temp = 0x1423;
 		break;
 	default:
-		err = -ENODEV;
-		goto exit_free;
+		return -ENODEV;
 	}
 
 	/* test if we can access the TEMPERATURE MSR */
@@ -160,14 +157,14 @@ static int __devinit via_cputemp_probe(struct platform_device *pdev)
 	if (err) {
 		dev_err(&pdev->dev,
 			"Unable to access TEMPERATURE MSR, giving up\n");
-		goto exit_free;
+		return err;
 	}
 
 	platform_set_drvdata(pdev, data);
 
 	err = sysfs_create_group(&pdev->dev.kobj, &via_cputemp_group);
 	if (err)
-		goto exit_free;
+		return err;
 
 	if (data->msr_vid)
 		data->vrm = vid_which_vrm();
@@ -192,10 +189,6 @@ exit_remove:
 	if (data->vrm)
 		device_remove_file(&pdev->dev, &dev_attr_cpu0_vid);
 	sysfs_remove_group(&pdev->dev.kobj, &via_cputemp_group);
-exit_free:
-	platform_set_drvdata(pdev, NULL);
-	kfree(data);
-exit:
 	return err;
 }
 
@@ -207,8 +200,6 @@ static int __devexit via_cputemp_remove(struct platform_device *pdev)
 	if (data->vrm)
 		device_remove_file(&pdev->dev, &dev_attr_cpu0_vid);
 	sysfs_remove_group(&pdev->dev.kobj, &via_cputemp_group);
-	platform_set_drvdata(pdev, NULL);
-	kfree(data);
 	return 0;
 }
 
diff --git a/drivers/hwmon/vt8231.c b/drivers/hwmon/vt8231.c
index 386a845..84e3dc5 100644
--- a/drivers/hwmon/vt8231.c
+++ b/drivers/hwmon/vt8231.c
@@ -789,18 +789,16 @@ static int vt8231_probe(struct platform_device *pdev)
 
 	/* Reserve the ISA region */
 	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
-	if (!request_region(res->start, VT8231_EXTENT,
-			    vt8231_driver.driver.name)) {
+	if (!devm_request_region(&pdev->dev, res->start, VT8231_EXTENT,
+				 vt8231_driver.driver.name)) {
 		dev_err(&pdev->dev, "Region 0x%lx-0x%lx already in use!\n",
 			(unsigned long)res->start, (unsigned long)res->end);
 		return -ENODEV;
 	}
 
-	data = kzalloc(sizeof(struct vt8231_data), GFP_KERNEL);
-	if (!data) {
-		err = -ENOMEM;
-		goto exit_release;
-	}
+	data = devm_kzalloc(&pdev->dev, sizeof(struct vt8231_data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
 
 	platform_set_drvdata(pdev, data);
 	data->addr = res->start;
@@ -812,7 +810,7 @@ static int vt8231_probe(struct platform_device *pdev)
 	/* Register sysfs hooks */
 	err = sysfs_create_group(&pdev->dev.kobj, &vt8231_group);
 	if (err)
-		goto exit_free;
+		return err;
 
 	/* Must update device information to find out the config field */
 	data->uch_config = vt8231_read_value(data, VT8231_REG_UCH_CONFIG);
@@ -850,13 +848,6 @@ exit_remove_files:
 		sysfs_remove_group(&pdev->dev.kobj, &vt8231_group_temps[i]);
 
 	sysfs_remove_group(&pdev->dev.kobj, &vt8231_group);
-
-exit_free:
-	platform_set_drvdata(pdev, NULL);
-	kfree(data);
-
-exit_release:
-	release_region(res->start, VT8231_EXTENT);
 	return err;
 }
 
@@ -875,9 +866,6 @@ static int __devexit vt8231_remove(struct platform_device *pdev)
 
 	sysfs_remove_group(&pdev->dev.kobj, &vt8231_group);
 
-	release_region(data->addr, VT8231_EXTENT);
-	platform_set_drvdata(pdev, NULL);
-	kfree(data);
 	return 0;
 }
 
diff --git a/drivers/hwmon/w83791d.c b/drivers/hwmon/w83791d.c
index 9ade4d4..93ea81a 100644
--- a/drivers/hwmon/w83791d.c
+++ b/drivers/hwmon/w83791d.c
@@ -259,8 +259,7 @@ static u8 fan_to_reg(long rpm, int div)
 					((val) + 500) / 1000)
 
 /* for thermal cruise temp tolerance, 4-bits, LSB = 1 degree Celsius */
-#define TOL_TEMP_TO_REG(val)		((val) < 0 ? 0 : \
-					(val) >= 15000 ? 15 : \
+#define TOL_TEMP_TO_REG(val)		((val) >= 15000 ? 15 : \
 					((val) + 500) / 1000)
 
 #define BEEP_MASK_TO_REG(val)		((val) & 0xffffff)
@@ -848,10 +847,10 @@ static ssize_t store_temp_target(struct device *dev,
 	struct i2c_client *client = to_i2c_client(dev);
 	struct w83791d_data *data = i2c_get_clientdata(client);
 	int nr = sensor_attr->index;
-	unsigned long val;
+	long val;
 	u8 target_mask;
 
-	if (kstrtoul(buf, 10, &val))
+	if (kstrtol(buf, 10, &val))
 		return -EINVAL;
 
 	mutex_lock(&data->update_lock);
diff --git a/drivers/hwmon/w83792d.c b/drivers/hwmon/w83792d.c
index 0ba5a2b..06d6f56 100644
--- a/drivers/hwmon/w83792d.c
+++ b/drivers/hwmon/w83792d.c
@@ -296,7 +296,6 @@ struct w83792d_data {
 	u8 pwmenable[3];
 	u32 alarms;		/* realtime status register encoding,combined */
 	u8 chassis;		/* Chassis status */
-	u8 chassis_clear;	/* CLR_CHS, clear chassis intrusion detection */
 	u8 thermal_cruise[3];	/* Smart FanI: Fan1,2,3 target value */
 	u8 tolerance[3];	/* Fan1,2,3 tolerance(Smart Fan I/II) */
 	u8 sf2_points[3][4];	/* Smart FanII: Fan1,2,3 temperature points */
@@ -739,7 +738,7 @@ store_pwm_mode(struct device *dev, struct device_attribute *attr,
 }
 
 static ssize_t
-show_chassis(struct device *dev, struct device_attribute *attr,
+show_chassis_clear(struct device *dev, struct device_attribute *attr,
 			char *buf)
 {
 	struct w83792d_data *data = w83792d_update_device(dev);
@@ -747,52 +746,6 @@ show_chassis(struct device *dev, struct device_attribute *attr,
 }
 
 static ssize_t
-show_regs_chassis(struct device *dev, struct device_attribute *attr,
-			char *buf)
-{
-	dev_warn(dev,
-		 "Attribute %s is deprecated, use intrusion0_alarm instead\n",
-		 "chassis");
-	return show_chassis(dev, attr, buf);
-}
-
-static ssize_t
-show_chassis_clear(struct device *dev, struct device_attribute *attr, char *buf)
-{
-	struct w83792d_data *data = w83792d_update_device(dev);
-	return sprintf(buf, "%d\n", data->chassis_clear);
-}
-
-static ssize_t
-store_chassis_clear_legacy(struct device *dev, struct device_attribute *attr,
-			const char *buf, size_t count)
-{
-	struct i2c_client *client = to_i2c_client(dev);
-	struct w83792d_data *data = i2c_get_clientdata(client);
-	unsigned long val;
-	int err;
-	u8 temp1 = 0, temp2 = 0;
-
-	dev_warn(dev,
-		 "Attribute %s is deprecated, use intrusion0_alarm instead\n",
-		 "chassis_clear");
-
-	err = kstrtoul(buf, 10, &val);
-	if (err)
-		return err;
-
-	mutex_lock(&data->update_lock);
-	data->chassis_clear = SENSORS_LIMIT(val, 0, 1);
-	temp1 = ((data->chassis_clear) << 7) & 0x80;
-	temp2 = w83792d_read_value(client,
-		W83792D_REG_CHASSIS_CLR) & 0x7f;
-	w83792d_write_value(client, W83792D_REG_CHASSIS_CLR, temp1 | temp2);
-	mutex_unlock(&data->update_lock);
-
-	return count;
-}
-
-static ssize_t
 store_chassis_clear(struct device *dev, struct device_attribute *attr,
 			const char *buf, size_t count)
 {
@@ -1116,11 +1069,8 @@ static SENSOR_DEVICE_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 20);
 static SENSOR_DEVICE_ATTR(fan4_alarm, S_IRUGO, show_alarm, NULL, 21);
 static SENSOR_DEVICE_ATTR(fan5_alarm, S_IRUGO, show_alarm, NULL, 22);
 static SENSOR_DEVICE_ATTR(fan6_alarm, S_IRUGO, show_alarm, NULL, 23);
-static DEVICE_ATTR(chassis, S_IRUGO, show_regs_chassis, NULL);
-static DEVICE_ATTR(chassis_clear, S_IRUGO | S_IWUSR,
-			show_chassis_clear, store_chassis_clear_legacy);
 static DEVICE_ATTR(intrusion0_alarm, S_IRUGO | S_IWUSR,
-			show_chassis, store_chassis_clear);
+			show_chassis_clear, store_chassis_clear);
 static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0);
 static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 1);
 static SENSOR_DEVICE_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 2);
@@ -1320,8 +1270,6 @@ static struct attribute *w83792d_attributes[] = {
 	&sensor_dev_attr_pwm3_mode.dev_attr.attr,
 	&sensor_dev_attr_pwm3_enable.dev_attr.attr,
 	&dev_attr_alarms.attr,
-	&dev_attr_chassis.attr,
-	&dev_attr_chassis_clear.attr,
 	&dev_attr_intrusion0_alarm.attr,
 	&sensor_dev_attr_tolerance1.dev_attr.attr,
 	&sensor_dev_attr_thermal_cruise1.dev_attr.attr,
@@ -1627,8 +1575,6 @@ static struct w83792d_data *w83792d_update_device(struct device *dev)
 		/* Update CaseOpen status and it's CLR_CHS. */
 		data->chassis = (w83792d_read_value(client,
 			W83792D_REG_CHASSIS) >> 5) & 0x01;
-		data->chassis_clear = (w83792d_read_value(client,
-			W83792D_REG_CHASSIS_CLR) >> 7) & 0x01;
 
 		/* Update Thermal Cruise/Smart Fan I target value */
 		for (i = 0; i < 3; i++) {
diff --git a/drivers/hwmon/w83793.c b/drivers/hwmon/w83793.c
index d6b0bdd..4fc47e0 100644
--- a/drivers/hwmon/w83793.c
+++ b/drivers/hwmon/w83793.c
@@ -442,27 +442,6 @@ store_beep_enable(struct device *dev, struct device_attribute *attr,
 	return count;
 }
 
-/* Write any value to clear chassis alarm */
-static ssize_t
-store_chassis_clear_legacy(struct device *dev,
-			   struct device_attribute *attr, const char *buf,
-			   size_t count)
-{
-	struct i2c_client *client = to_i2c_client(dev);
-	struct w83793_data *data = i2c_get_clientdata(client);
-	u8 val;
-
-	dev_warn(dev, "Attribute chassis is deprecated, "
-		 "use intrusion0_alarm instead\n");
-
-	mutex_lock(&data->update_lock);
-	val = w83793_read_value(client, W83793_REG_CLR_CHASSIS);
-	val |= 0x80;
-	w83793_write_value(client, W83793_REG_CLR_CHASSIS, val);
-	mutex_unlock(&data->update_lock);
-	return count;
-}
-
 /* Write 0 to clear chassis alarm */
 static ssize_t
 store_chassis_clear(struct device *dev,
@@ -1189,8 +1168,6 @@ static struct sensor_device_attribute_2 w83793_vid[] = {
 static DEVICE_ATTR(vrm, S_IWUSR | S_IRUGO, show_vrm, store_vrm);
 
 static struct sensor_device_attribute_2 sda_single_files[] = {
-	SENSOR_ATTR_2(chassis, S_IWUSR | S_IRUGO, show_alarm_beep,
-		      store_chassis_clear_legacy, ALARM_STATUS, 30),
 	SENSOR_ATTR_2(intrusion0_alarm, S_IWUSR | S_IRUGO, show_alarm_beep,
 		      store_chassis_clear, ALARM_STATUS, 30),
 	SENSOR_ATTR_2(beep_enable, S_IWUSR | S_IRUGO, show_beep_enable,
diff --git a/drivers/hwmon/w83l786ng.c b/drivers/hwmon/w83l786ng.c
index 5850b77..c99c8a0 100644
--- a/drivers/hwmon/w83l786ng.c
+++ b/drivers/hwmon/w83l786ng.c
@@ -668,11 +668,10 @@ w83l786ng_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	int i, err = 0;
 	u8 reg_tmp;
 
-	data = kzalloc(sizeof(struct w83l786ng_data), GFP_KERNEL);
-	if (!data) {
-		err = -ENOMEM;
-		goto exit;
-	}
+	data = devm_kzalloc(&client->dev, sizeof(struct w83l786ng_data),
+			    GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
 
 	i2c_set_clientdata(client, data);
 	mutex_init(&data->update_lock);
@@ -708,8 +707,6 @@ w83l786ng_probe(struct i2c_client *client, const struct i2c_device_id *id)
 
 exit_remove:
 	sysfs_remove_group(&client->dev.kobj, &w83l786ng_group);
-	kfree(data);
-exit:
 	return err;
 }
 
@@ -721,8 +718,6 @@ w83l786ng_remove(struct i2c_client *client)
 	hwmon_device_unregister(data->hwmon_dev);
 	sysfs_remove_group(&client->dev.kobj, &w83l786ng_group);
 
-	kfree(data);
-
 	return 0;
 }
 
diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig
index 5a3bb3d..17b35c1 100644
--- a/drivers/i2c/Kconfig
+++ b/drivers/i2c/Kconfig
@@ -4,7 +4,6 @@
 
 menuconfig I2C
 	tristate "I2C support"
-	depends on HAS_IOMEM
 	select RT_MUTEXES
 	---help---
 	  I2C (pronounce: I-squared-C) is a slow serial bus protocol used in
@@ -49,6 +48,7 @@ config I2C_CHARDEV
 
 config I2C_MUX
 	tristate "I2C bus multiplexing support"
+	depends on HAS_IOMEM
 	help
 	  Say Y here if you want the I2C core to support the ability to
 	  handle multiplexed I2C bus topologies, by presenting each
@@ -86,6 +86,19 @@ config I2C_SMBUS
 source drivers/i2c/algos/Kconfig
 source drivers/i2c/busses/Kconfig
 
+config I2C_STUB
+	tristate "I2C/SMBus Test Stub"
+	depends on EXPERIMENTAL && m
+	default 'n'
+	help
+	  This module may be useful to developers of SMBus client drivers,
+	  especially for certain kinds of sensor chips.
+
+	  If you do build this module, be sure to read the notes and warnings
+	  in <file:Documentation/i2c/i2c-stub>.
+
+	  If you don't know what to do here, definitely say N.
+
 config I2C_DEBUG_CORE
 	bool "I2C Core debugging messages"
 	help
@@ -103,6 +116,7 @@ config I2C_DEBUG_ALGO
 
 config I2C_DEBUG_BUS
 	bool "I2C Bus debugging messages"
+	depends on HAS_IOMEM
 	help
 	  Say Y here if you want the I2C bus drivers to produce a bunch of
 	  debug messages to the system log.  Select this if you are having
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 970a161..b8ed12c 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -3,6 +3,7 @@
 #
 
 menu "I2C Hardware Bus support"
+	depends on HAS_IOMEM
 
 comment "PC SMBus host controller drivers"
 	depends on PCI
@@ -80,6 +81,7 @@ config I2C_I801
 	tristate "Intel 82801 (ICH/PCH)"
 	depends on PCI
 	select CHECK_SIGNATURE if X86 && DMI
+	select GPIOLIB if I2C_MUX
 	help
 	  If you say yes to this option, support will be included for the Intel
 	  801 family of mainboard I2C interfaces.  Specifically, the following
@@ -291,18 +293,21 @@ comment "I2C system bus drivers (mostly embedded / system-on-chip)"
 
 config I2C_AT91
 	tristate "Atmel AT91 I2C Two-Wire interface (TWI)"
-	depends on ARCH_AT91 && EXPERIMENTAL && BROKEN
+	depends on ARCH_AT91 && EXPERIMENTAL
 	help
 	  This supports the use of the I2C interface on Atmel AT91
 	  processors.
 
-	  This driver is BROKEN because the controller which it uses
-	  will easily trigger RX overrun and TX underrun errors.  Using
-	  low I2C clock rates may partially work around those issues
-	  on some systems.  Another serious problem is that there is no
-	  documented way to issue repeated START conditions, as needed
+	  A serious problem is that there is no documented way to issue
+	  repeated START conditions for more than two messages, as needed
 	  to support combined I2C messages.  Use the i2c-gpio driver
-	  unless your system can cope with those limitations.
+	  unless your system can cope with this limitation.
+
+	  Caution! at91rm9200, at91sam9261, at91sam9260, at91sam9263 devices
+	  don't have clock stretching in transmission mode. For that reason,
+	  you can encounter underrun issues causing premature stop sendings if
+	  the latency to fill the transmission register is too long. If you
+	  are facing this situation, use the i2c-gpio driver.
 
 config I2C_AU1550
 	tristate "Au1550/Au1200/Au1300 SMBus interface"
@@ -551,7 +556,7 @@ config I2C_PMCMSP
 
 config I2C_PNX
 	tristate "I2C bus support for Philips PNX and NXP LPC targets"
-	depends on ARCH_PNX4008 || ARCH_LPC32XX
+	depends on ARCH_LPC32XX
 	help
 	  This driver supports the Philips IP3204 I2C IP block master and/or
 	  slave controller
@@ -849,19 +854,6 @@ config I2C_SIBYTE
 	help
 	  Supports the SiByte SOC on-chip I2C interfaces (2 channels).
 
-config I2C_STUB
-	tristate "I2C/SMBus Test Stub"
-	depends on EXPERIMENTAL && m
-	default 'n'
-	help
-	  This module may be useful to developers of SMBus client drivers,
-	  especially for certain kinds of sensor chips.
-
-	  If you do build this module, be sure to read the notes and warnings
-	  in <file:Documentation/i2c/i2c-stub>.
-
-	  If you don't know what to do here, definitely say N.
-
 config SCx200_I2C
 	tristate "NatSemi SCx200 I2C using GPIO pins (DEPRECATED)"
 	depends on SCx200_GPIO
diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c
index e24484b..aa59a25 100644
--- a/drivers/i2c/busses/i2c-at91.c
+++ b/drivers/i2c/busses/i2c-at91.c
@@ -1,315 +1,554 @@
 /*
-    i2c Support for Atmel's AT91 Two-Wire Interface (TWI)
-
-    Copyright (C) 2004 Rick Bronson
-    Converted to 2.6 by Andrew Victor <andrew@sanpeople.com>
-
-    Borrowed heavily from original work by:
-    Copyright (C) 2000 Philip Edelbrock <phil@stimpy.netroedge.com>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-*/
+ *  i2c Support for Atmel's AT91 Two-Wire Interface (TWI)
+ *
+ *  Copyright (C) 2011 Weinmann Medical GmbH
+ *  Author: Nikolaus Voss <n.voss@weinmann.de>
+ *
+ *  Evolved from original work by:
+ *  Copyright (C) 2004 Rick Bronson
+ *  Converted to 2.6 by Andrew Victor <andrew@sanpeople.com>
+ *
+ *  Borrowed heavily from original work by:
+ *  Copyright (C) 2000 Philip Edelbrock <phil@stimpy.netroedge.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ */
 
-#include <linux/module.h>
-#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/completion.h>
 #include <linux/err.h>
-#include <linux/slab.h>
-#include <linux/types.h>
-#include <linux/delay.h>
 #include <linux/i2c.h>
-#include <linux/init.h>
-#include <linux/clk.h>
-#include <linux/platform_device.h>
+#include <linux/interrupt.h>
 #include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_i2c.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#define TWI_CLK_HZ		100000			/* max 400 Kbits/s */
+#define AT91_I2C_TIMEOUT	msecs_to_jiffies(100)	/* transfer timeout */
+
+/* AT91 TWI register definitions */
+#define	AT91_TWI_CR		0x0000	/* Control Register */
+#define	AT91_TWI_START		0x0001	/* Send a Start Condition */
+#define	AT91_TWI_STOP		0x0002	/* Send a Stop Condition */
+#define	AT91_TWI_MSEN		0x0004	/* Master Transfer Enable */
+#define	AT91_TWI_SVDIS		0x0020	/* Slave Transfer Disable */
+#define	AT91_TWI_SWRST		0x0080	/* Software Reset */
+
+#define	AT91_TWI_MMR		0x0004	/* Master Mode Register */
+#define	AT91_TWI_IADRSZ_1	0x0100	/* Internal Device Address Size */
+#define	AT91_TWI_MREAD		0x1000	/* Master Read Direction */
+
+#define	AT91_TWI_IADR		0x000c	/* Internal Address Register */
+
+#define	AT91_TWI_CWGR		0x0010	/* Clock Waveform Generator Reg */
+
+#define	AT91_TWI_SR		0x0020	/* Status Register */
+#define	AT91_TWI_TXCOMP		0x0001	/* Transmission Complete */
+#define	AT91_TWI_RXRDY		0x0002	/* Receive Holding Register Ready */
+#define	AT91_TWI_TXRDY		0x0004	/* Transmit Holding Register Ready */
 
-#include <mach/at91_twi.h>
-#include <mach/board.h>
-#include <mach/cpu.h>
+#define	AT91_TWI_OVRE		0x0040	/* Overrun Error */
+#define	AT91_TWI_UNRE		0x0080	/* Underrun Error */
+#define	AT91_TWI_NACK		0x0100	/* Not Acknowledged */
 
-#define TWI_CLOCK		100000		/* Hz. max 400 Kbits/sec */
+#define	AT91_TWI_IER		0x0024	/* Interrupt Enable Register */
+#define	AT91_TWI_IDR		0x0028	/* Interrupt Disable Register */
+#define	AT91_TWI_IMR		0x002c	/* Interrupt Mask Register */
+#define	AT91_TWI_RHR		0x0030	/* Receive Holding Register */
+#define	AT91_TWI_THR		0x0034	/* Transmit Holding Register */
 
+struct at91_twi_pdata {
+	unsigned	clk_max_div;
+	unsigned	clk_offset;
+	bool		has_unre_flag;
+};
+
+struct at91_twi_dev {
+	struct device		*dev;
+	void __iomem		*base;
+	struct completion	cmd_complete;
+	struct clk		*clk;
+	u8			*buf;
+	size_t			buf_len;
+	struct i2c_msg		*msg;
+	int			irq;
+	unsigned		transfer_status;
+	struct i2c_adapter	adapter;
+	unsigned		twi_cwgr_reg;
+	struct at91_twi_pdata	*pdata;
+};
 
-static struct clk *twi_clk;
-static void __iomem *twi_base;
+static unsigned at91_twi_read(struct at91_twi_dev *dev, unsigned reg)
+{
+	return readl_relaxed(dev->base + reg);
+}
+
+static void at91_twi_write(struct at91_twi_dev *dev, unsigned reg, unsigned val)
+{
+	writel_relaxed(val, dev->base + reg);
+}
 
-#define at91_twi_read(reg)		__raw_readl(twi_base + (reg))
-#define at91_twi_write(reg, val)	__raw_writel((val), twi_base + (reg))
+static void at91_disable_twi_interrupts(struct at91_twi_dev *dev)
+{
+	at91_twi_write(dev, AT91_TWI_IDR,
+		       AT91_TWI_TXCOMP | AT91_TWI_RXRDY | AT91_TWI_TXRDY);
+}
 
+static void at91_init_twi_bus(struct at91_twi_dev *dev)
+{
+	at91_disable_twi_interrupts(dev);
+	at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_SWRST);
+	at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_MSEN);
+	at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_SVDIS);
+	at91_twi_write(dev, AT91_TWI_CWGR, dev->twi_cwgr_reg);
+}
 
 /*
- * Initialize the TWI hardware registers.
+ * Calculate symmetric clock as stated in datasheet:
+ * twi_clk = F_MAIN / (2 * (cdiv * (1 << ckdiv) + offset))
  */
-static void __devinit at91_twi_hwinit(void)
+static void __devinit at91_calc_twi_clock(struct at91_twi_dev *dev, int twi_clk)
 {
-	unsigned long cdiv, ckdiv;
-
-	at91_twi_write(AT91_TWI_IDR, 0xffffffff);	/* Disable all interrupts */
-	at91_twi_write(AT91_TWI_CR, AT91_TWI_SWRST);	/* Reset peripheral */
-	at91_twi_write(AT91_TWI_CR, AT91_TWI_MSEN);	/* Set Master mode */
-
-	/* Calcuate clock dividers */
-	cdiv = (clk_get_rate(twi_clk) / (2 * TWI_CLOCK)) - 3;
-	cdiv = cdiv + 1;	/* round up */
-	ckdiv = 0;
-	while (cdiv > 255) {
-		ckdiv++;
-		cdiv = cdiv >> 1;
+	int ckdiv, cdiv, div;
+	struct at91_twi_pdata *pdata = dev->pdata;
+	int offset = pdata->clk_offset;
+	int max_ckdiv = pdata->clk_max_div;
+
+	div = max(0, (int)DIV_ROUND_UP(clk_get_rate(dev->clk),
+				       2 * twi_clk) - offset);
+	ckdiv = fls(div >> 8);
+	cdiv = div >> ckdiv;
+
+	if (ckdiv > max_ckdiv) {
+		dev_warn(dev->dev, "%d exceeds ckdiv max value which is %d.\n",
+			 ckdiv, max_ckdiv);
+		ckdiv = max_ckdiv;
+		cdiv = 255;
 	}
 
-	if (cpu_is_at91rm9200()) {			/* AT91RM9200 Errata #22 */
-		if (ckdiv > 5) {
-			printk(KERN_ERR "AT91 I2C: Invalid TWI_CLOCK value!\n");
-			ckdiv = 5;
-		}
-	}
+	dev->twi_cwgr_reg = (ckdiv << 16) | (cdiv << 8) | cdiv;
+	dev_dbg(dev->dev, "cdiv %d ckdiv %d\n", cdiv, ckdiv);
+}
 
-	at91_twi_write(AT91_TWI_CWGR, (ckdiv << 16) | (cdiv << 8) | cdiv);
+static void at91_twi_write_next_byte(struct at91_twi_dev *dev)
+{
+	if (dev->buf_len <= 0)
+		return;
+
+	at91_twi_write(dev, AT91_TWI_THR, *dev->buf);
+
+	/* send stop when last byte has been written */
+	if (--dev->buf_len == 0)
+		at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_STOP);
+
+	dev_dbg(dev->dev, "wrote 0x%x, to go %d\n", *dev->buf, dev->buf_len);
+
+	++dev->buf;
 }
 
-/*
- * Poll the i2c status register until the specified bit is set.
- * Returns 0 if timed out (100 msec).
- */
-static short at91_poll_status(unsigned long bit)
+static void at91_twi_read_next_byte(struct at91_twi_dev *dev)
 {
-	int loop_cntr = 10000;
+	if (dev->buf_len <= 0)
+		return;
+
+	*dev->buf = at91_twi_read(dev, AT91_TWI_RHR) & 0xff;
+	--dev->buf_len;
+
+	/* handle I2C_SMBUS_BLOCK_DATA */
+	if (unlikely(dev->msg->flags & I2C_M_RECV_LEN)) {
+		dev->msg->flags &= ~I2C_M_RECV_LEN;
+		dev->buf_len += *dev->buf;
+		dev->msg->len = dev->buf_len + 1;
+		dev_dbg(dev->dev, "received block length %d\n", dev->buf_len);
+	}
+
+	/* send stop if second but last byte has been read */
+	if (dev->buf_len == 1)
+		at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_STOP);
 
-	do {
-		udelay(10);
-	} while (!(at91_twi_read(AT91_TWI_SR) & bit) && (--loop_cntr > 0));
+	dev_dbg(dev->dev, "read 0x%x, to go %d\n", *dev->buf, dev->buf_len);
 
-	return (loop_cntr > 0);
+	++dev->buf;
 }
 
-static int xfer_read(struct i2c_adapter *adap, unsigned char *buf, int length)
+static irqreturn_t atmel_twi_interrupt(int irq, void *dev_id)
 {
-	/* Send Start */
-	at91_twi_write(AT91_TWI_CR, AT91_TWI_START);
-
-	/* Read data */
-	while (length--) {
-		if (!length)	/* need to send Stop before reading last byte */
-			at91_twi_write(AT91_TWI_CR, AT91_TWI_STOP);
-		if (!at91_poll_status(AT91_TWI_RXRDY)) {
-			dev_dbg(&adap->dev, "RXRDY timeout\n");
-			return -ETIMEDOUT;
-		}
-		*buf++ = (at91_twi_read(AT91_TWI_RHR) & 0xff);
+	struct at91_twi_dev *dev = dev_id;
+	const unsigned status = at91_twi_read(dev, AT91_TWI_SR);
+	const unsigned irqstatus = status & at91_twi_read(dev, AT91_TWI_IMR);
+
+	if (!irqstatus)
+		return IRQ_NONE;
+	else if (irqstatus & AT91_TWI_RXRDY)
+		at91_twi_read_next_byte(dev);
+	else if (irqstatus & AT91_TWI_TXRDY)
+		at91_twi_write_next_byte(dev);
+
+	/* catch error flags */
+	dev->transfer_status |= status;
+
+	if (irqstatus & AT91_TWI_TXCOMP) {
+		at91_disable_twi_interrupts(dev);
+		complete(&dev->cmd_complete);
 	}
 
-	return 0;
+	return IRQ_HANDLED;
 }
 
-static int xfer_write(struct i2c_adapter *adap, unsigned char *buf, int length)
+static int at91_do_twi_transfer(struct at91_twi_dev *dev)
 {
-	/* Load first byte into transmitter */
-	at91_twi_write(AT91_TWI_THR, *buf++);
+	int ret;
+	bool has_unre_flag = dev->pdata->has_unre_flag;
 
-	/* Send Start */
-	at91_twi_write(AT91_TWI_CR, AT91_TWI_START);
+	dev_dbg(dev->dev, "transfer: %s %d bytes.\n",
+		(dev->msg->flags & I2C_M_RD) ? "read" : "write", dev->buf_len);
 
-	do {
-		if (!at91_poll_status(AT91_TWI_TXRDY)) {
-			dev_dbg(&adap->dev, "TXRDY timeout\n");
-			return -ETIMEDOUT;
-		}
+	INIT_COMPLETION(dev->cmd_complete);
+	dev->transfer_status = 0;
+	if (dev->msg->flags & I2C_M_RD) {
+		unsigned start_flags = AT91_TWI_START;
 
-		length--;	/* byte was transmitted */
+		if (at91_twi_read(dev, AT91_TWI_SR) & AT91_TWI_RXRDY) {
+			dev_err(dev->dev, "RXRDY still set!");
+			at91_twi_read(dev, AT91_TWI_RHR);
+		}
 
-		if (length > 0)		/* more data to send? */
-			at91_twi_write(AT91_TWI_THR, *buf++);
-	} while (length);
+		/* if only one byte is to be read, immediately stop transfer */
+		if (dev->buf_len <= 1 && !(dev->msg->flags & I2C_M_RECV_LEN))
+			start_flags |= AT91_TWI_STOP;
+		at91_twi_write(dev, AT91_TWI_CR, start_flags);
+		at91_twi_write(dev, AT91_TWI_IER,
+			       AT91_TWI_TXCOMP | AT91_TWI_RXRDY);
+	} else {
+		at91_twi_write_next_byte(dev);
+		at91_twi_write(dev, AT91_TWI_IER,
+			       AT91_TWI_TXCOMP | AT91_TWI_TXRDY);
+	}
 
-	/* Send Stop */
-	at91_twi_write(AT91_TWI_CR, AT91_TWI_STOP);
+	ret = wait_for_completion_interruptible_timeout(&dev->cmd_complete,
+							dev->adapter.timeout);
+	if (ret == 0) {
+		dev_err(dev->dev, "controller timed out\n");
+		at91_init_twi_bus(dev);
+		return -ETIMEDOUT;
+	}
+	if (dev->transfer_status & AT91_TWI_NACK) {
+		dev_dbg(dev->dev, "received nack\n");
+		return -EREMOTEIO;
+	}
+	if (dev->transfer_status & AT91_TWI_OVRE) {
+		dev_err(dev->dev, "overrun while reading\n");
+		return -EIO;
+	}
+	if (has_unre_flag && dev->transfer_status & AT91_TWI_UNRE) {
+		dev_err(dev->dev, "underrun while writing\n");
+		return -EIO;
+	}
+	dev_dbg(dev->dev, "transfer complete\n");
 
 	return 0;
 }
 
-/*
- * Generic i2c master transfer entrypoint.
- *
- * Note: We do not use Atmel's feature of storing the "internal device address".
- * Instead the "internal device address" has to be written using a separate
- * i2c message.
- * http://lists.arm.linux.org.uk/pipermail/linux-arm-kernel/2004-September/024411.html
- */
-static int at91_xfer(struct i2c_adapter *adap, struct i2c_msg *pmsg, int num)
+static int at91_twi_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, int num)
 {
-	int i, ret;
+	struct at91_twi_dev *dev = i2c_get_adapdata(adap);
+	int ret;
+	unsigned int_addr_flag = 0;
+	struct i2c_msg *m_start = msg;
 
 	dev_dbg(&adap->dev, "at91_xfer: processing %d messages:\n", num);
 
-	for (i = 0; i < num; i++) {
-		dev_dbg(&adap->dev, " #%d: %sing %d byte%s %s 0x%02x\n", i,
-			pmsg->flags & I2C_M_RD ? "read" : "writ",
-			pmsg->len, pmsg->len > 1 ? "s" : "",
-			pmsg->flags & I2C_M_RD ? "from" : "to",	pmsg->addr);
-
-		at91_twi_write(AT91_TWI_MMR, (pmsg->addr << 16)
-			| ((pmsg->flags & I2C_M_RD) ? AT91_TWI_MREAD : 0));
-
-		if (pmsg->len && pmsg->buf) {	/* sanity check */
-			if (pmsg->flags & I2C_M_RD)
-				ret = xfer_read(adap, pmsg->buf, pmsg->len);
-			else
-				ret = xfer_write(adap, pmsg->buf, pmsg->len);
-
-			if (ret)
-				return ret;
-
-			/* Wait until transfer is finished */
-			if (!at91_poll_status(AT91_TWI_TXCOMP)) {
-				dev_dbg(&adap->dev, "TXCOMP timeout\n");
-				return -ETIMEDOUT;
-			}
+	/*
+	 * The hardware can handle at most two messages concatenated by a
+	 * repeated start via it's internal address feature.
+	 */
+	if (num > 2) {
+		dev_err(dev->dev,
+			"cannot handle more than two concatenated messages.\n");
+		return 0;
+	} else if (num == 2) {
+		int internal_address = 0;
+		int i;
+
+		if (msg->flags & I2C_M_RD) {
+			dev_err(dev->dev, "first transfer must be write.\n");
+			return -EINVAL;
 		}
-		dev_dbg(&adap->dev, "transfer complete\n");
-		pmsg++;		/* next message */
+		if (msg->len > 3) {
+			dev_err(dev->dev, "first message size must be <= 3.\n");
+			return -EINVAL;
+		}
+
+		/* 1st msg is put into the internal address, start with 2nd */
+		m_start = &msg[1];
+		for (i = 0; i < msg->len; ++i) {
+			const unsigned addr = msg->buf[msg->len - 1 - i];
+
+			internal_address |= addr << (8 * i);
+			int_addr_flag += AT91_TWI_IADRSZ_1;
+		}
+		at91_twi_write(dev, AT91_TWI_IADR, internal_address);
 	}
-	return i;
+
+	at91_twi_write(dev, AT91_TWI_MMR, (m_start->addr << 16) | int_addr_flag
+		       | ((m_start->flags & I2C_M_RD) ? AT91_TWI_MREAD : 0));
+
+	dev->buf_len = m_start->len;
+	dev->buf = m_start->buf;
+	dev->msg = m_start;
+
+	ret = at91_do_twi_transfer(dev);
+
+	return (ret < 0) ? ret : num;
 }
 
-/*
- * Return list of supported functionality.
- */
-static u32 at91_func(struct i2c_adapter *adapter)
+static u32 at91_twi_func(struct i2c_adapter *adapter)
 {
-	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL
+		| I2C_FUNC_SMBUS_READ_BLOCK_DATA;
 }
 
-static struct i2c_algorithm at91_algorithm = {
-	.master_xfer	= at91_xfer,
-	.functionality	= at91_func,
+static struct i2c_algorithm at91_twi_algorithm = {
+	.master_xfer	= at91_twi_xfer,
+	.functionality	= at91_twi_func,
 };
 
-/*
- * Main initialization routine.
- */
-static int __devinit at91_i2c_probe(struct platform_device *pdev)
-{
-	struct i2c_adapter *adapter;
-	struct resource *res;
-	int rc;
+static struct at91_twi_pdata at91rm9200_config = {
+	.clk_max_div = 5,
+	.clk_offset = 3,
+	.has_unre_flag = true,
+};
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res)
-		return -ENXIO;
+static struct at91_twi_pdata at91sam9261_config = {
+	.clk_max_div = 5,
+	.clk_offset = 4,
+	.has_unre_flag = false,
+};
 
-	if (!request_mem_region(res->start, resource_size(res), "at91_i2c"))
-		return -EBUSY;
+static struct at91_twi_pdata at91sam9260_config = {
+	.clk_max_div = 7,
+	.clk_offset = 4,
+	.has_unre_flag = false,
+};
+
+static struct at91_twi_pdata at91sam9g20_config = {
+	.clk_max_div = 7,
+	.clk_offset = 4,
+	.has_unre_flag = false,
+};
+
+static struct at91_twi_pdata at91sam9g10_config = {
+	.clk_max_div = 7,
+	.clk_offset = 4,
+	.has_unre_flag = false,
+};
 
-	twi_base = ioremap(res->start, resource_size(res));
-	if (!twi_base) {
-		rc = -ENOMEM;
-		goto fail0;
+static struct at91_twi_pdata at91sam9x5_config = {
+	.clk_max_div = 7,
+	.clk_offset = 4,
+	.has_unre_flag = false,
+};
+
+static const struct platform_device_id at91_twi_devtypes[] = {
+	{
+		.name = "i2c-at91rm9200",
+		.driver_data = (unsigned long) &at91rm9200_config,
+	}, {
+		.name = "i2c-at91sam9261",
+		.driver_data = (unsigned long) &at91sam9261_config,
+	}, {
+		.name = "i2c-at91sam9260",
+		.driver_data = (unsigned long) &at91sam9260_config,
+	}, {
+		.name = "i2c-at91sam9g20",
+		.driver_data = (unsigned long) &at91sam9g20_config,
+	}, {
+		.name = "i2c-at91sam9g10",
+		.driver_data = (unsigned long) &at91sam9g10_config,
+	}, {
+		/* sentinel */
 	}
+};
 
-	twi_clk = clk_get(NULL, "twi_clk");
-	if (IS_ERR(twi_clk)) {
-		dev_err(&pdev->dev, "no clock defined\n");
-		rc = -ENODEV;
-		goto fail1;
+#if defined(CONFIG_OF)
+static const struct of_device_id atmel_twi_dt_ids[] = {
+	{
+		.compatible = "atmel,at91sam9260-i2c",
+		.data = &at91sam9260_config,
+	} , {
+		.compatible = "atmel,at91sam9g20-i2c",
+		.data = &at91sam9g20_config,
+	} , {
+		.compatible = "atmel,at91sam9g10-i2c",
+		.data = &at91sam9g10_config,
+	}, {
+		.compatible = "atmel,at91sam9x5-i2c",
+		.data = &at91sam9x5_config,
+	}, {
+		/* sentinel */
 	}
+};
+MODULE_DEVICE_TABLE(of, atmel_twi_dt_ids);
+#else
+#define atmel_twi_dt_ids NULL
+#endif
 
-	adapter = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL);
-	if (adapter == NULL) {
-		dev_err(&pdev->dev, "can't allocate inteface!\n");
-		rc = -ENOMEM;
-		goto fail2;
+static struct at91_twi_pdata * __devinit at91_twi_get_driver_data(
+					struct platform_device *pdev)
+{
+	if (pdev->dev.of_node) {
+		const struct of_device_id *match;
+		match = of_match_node(atmel_twi_dt_ids, pdev->dev.of_node);
+		if (!match)
+			return NULL;
+		return match->data;
 	}
-	snprintf(adapter->name, sizeof(adapter->name), "AT91");
-	adapter->algo = &at91_algorithm;
-	adapter->class = I2C_CLASS_HWMON;
-	adapter->dev.parent = &pdev->dev;
-	/* adapter->id == 0 ... only one TWI controller for now */
+	return (struct at91_twi_pdata *) platform_get_device_id(pdev)->driver_data;
+}
+
+static int __devinit at91_twi_probe(struct platform_device *pdev)
+{
+	struct at91_twi_dev *dev;
+	struct resource *mem;
+	int rc;
+
+	dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
+	if (!dev)
+		return -ENOMEM;
+	init_completion(&dev->cmd_complete);
+	dev->dev = &pdev->dev;
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem)
+		return -ENODEV;
+
+	dev->pdata = at91_twi_get_driver_data(pdev);
+	if (!dev->pdata)
+		return -ENODEV;
 
-	platform_set_drvdata(pdev, adapter);
+	dev->base = devm_request_and_ioremap(&pdev->dev, mem);
+	if (!dev->base)
+		return -EBUSY;
 
-	clk_enable(twi_clk);		/* enable peripheral clock */
-	at91_twi_hwinit();		/* initialize TWI controller */
+	dev->irq = platform_get_irq(pdev, 0);
+	if (dev->irq < 0)
+		return dev->irq;
 
-	rc = i2c_add_numbered_adapter(adapter);
+	rc = devm_request_irq(&pdev->dev, dev->irq, atmel_twi_interrupt, 0,
+			 dev_name(dev->dev), dev);
 	if (rc) {
-		dev_err(&pdev->dev, "Adapter %s registration failed\n",
-				adapter->name);
-		goto fail3;
+		dev_err(dev->dev, "Cannot get irq %d: %d\n", dev->irq, rc);
+		return rc;
 	}
 
-	dev_info(&pdev->dev, "AT91 i2c bus driver.\n");
-	return 0;
+	platform_set_drvdata(pdev, dev);
 
-fail3:
-	platform_set_drvdata(pdev, NULL);
-	kfree(adapter);
-	clk_disable(twi_clk);
-fail2:
-	clk_put(twi_clk);
-fail1:
-	iounmap(twi_base);
-fail0:
-	release_mem_region(res->start, resource_size(res));
+	dev->clk = devm_clk_get(dev->dev, NULL);
+	if (IS_ERR(dev->clk)) {
+		dev_err(dev->dev, "no clock defined\n");
+		return -ENODEV;
+	}
+	clk_prepare_enable(dev->clk);
+
+	at91_calc_twi_clock(dev, TWI_CLK_HZ);
+	at91_init_twi_bus(dev);
+
+	snprintf(dev->adapter.name, sizeof(dev->adapter.name), "AT91");
+	i2c_set_adapdata(&dev->adapter, dev);
+	dev->adapter.owner = THIS_MODULE;
+	dev->adapter.class = I2C_CLASS_HWMON;
+	dev->adapter.algo = &at91_twi_algorithm;
+	dev->adapter.dev.parent = dev->dev;
+	dev->adapter.nr = pdev->id;
+	dev->adapter.timeout = AT91_I2C_TIMEOUT;
+	dev->adapter.dev.of_node = pdev->dev.of_node;
+
+	rc = i2c_add_numbered_adapter(&dev->adapter);
+	if (rc) {
+		dev_err(dev->dev, "Adapter %s registration failed\n",
+			dev->adapter.name);
+		clk_disable_unprepare(dev->clk);
+		return rc;
+	}
 
-	return rc;
+	of_i2c_register_devices(&dev->adapter);
+
+	dev_info(dev->dev, "AT91 i2c bus driver.\n");
+	return 0;
 }
 
-static int __devexit at91_i2c_remove(struct platform_device *pdev)
+static int __devexit at91_twi_remove(struct platform_device *pdev)
 {
-	struct i2c_adapter *adapter = platform_get_drvdata(pdev);
-	struct resource *res;
+	struct at91_twi_dev *dev = platform_get_drvdata(pdev);
 	int rc;
 
-	rc = i2c_del_adapter(adapter);
-	platform_set_drvdata(pdev, NULL);
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	iounmap(twi_base);
-	release_mem_region(res->start, resource_size(res));
-
-	clk_disable(twi_clk);		/* disable peripheral clock */
-	clk_put(twi_clk);
+	rc = i2c_del_adapter(&dev->adapter);
+	clk_disable_unprepare(dev->clk);
 
 	return rc;
 }
 
 #ifdef CONFIG_PM
 
-/* NOTE: could save a few mA by keeping clock off outside of at91_xfer... */
-
-static int at91_i2c_suspend(struct device *dev)
+static int at91_twi_runtime_suspend(struct device *dev)
 {
-	clk_disable(twi_clk);
+	struct at91_twi_dev *twi_dev = dev_get_drvdata(dev);
+
+	clk_disable(twi_dev->clk);
+
 	return 0;
 }
 
-static int at91_i2c_resume(struct device *dev)
+static int at91_twi_runtime_resume(struct device *dev)
 {
-	return clk_enable(twi_clk);
+	struct at91_twi_dev *twi_dev = dev_get_drvdata(dev);
+
+	return clk_enable(twi_dev->clk);
 }
 
-static SIMPLE_DEV_PM_OPS(at91_i2c_pm, at91_i2c_suspend, at91_i2c_resume);
-#define AT91_I2C_PM	(&at91_i2c_pm)
+static const struct dev_pm_ops at91_twi_pm = {
+	.runtime_suspend	= at91_twi_runtime_suspend,
+	.runtime_resume		= at91_twi_runtime_resume,
+};
 
+#define at91_twi_pm_ops (&at91_twi_pm)
 #else
-#define AT91_I2C_PM	NULL
+#define at91_twi_pm_ops NULL
 #endif
 
-static struct platform_driver at91_i2c_driver = {
-	.probe		= at91_i2c_probe,
-	.remove		= __devexit_p(at91_i2c_remove),
+static struct platform_driver at91_twi_driver = {
+	.probe		= at91_twi_probe,
+	.remove		= __devexit_p(at91_twi_remove),
+	.id_table	= at91_twi_devtypes,
 	.driver		= {
 		.name	= "at91_i2c",
 		.owner	= THIS_MODULE,
-		.pm	= AT91_I2C_PM,
+		.of_match_table = atmel_twi_dt_ids,
+		.pm	= at91_twi_pm_ops,
 	},
 };
 
-module_platform_driver(at91_i2c_driver);
+static int __init at91_twi_init(void)
+{
+	return platform_driver_register(&at91_twi_driver);
+}
+
+static void __exit at91_twi_exit(void)
+{
+	platform_driver_unregister(&at91_twi_driver);
+}
+
+subsys_initcall(at91_twi_init);
+module_exit(at91_twi_exit);
 
-MODULE_AUTHOR("Rick Bronson");
+MODULE_AUTHOR("Nikolaus Voss <n.voss@weinmann.de>");
 MODULE_DESCRIPTION("I2C (TWI) driver for Atmel AT91");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:at91_i2c");
diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c
index 79b4bcb..6a0a553 100644
--- a/drivers/i2c/busses/i2c-davinci.c
+++ b/drivers/i2c/busses/i2c-davinci.c
@@ -38,9 +38,11 @@
 #include <linux/slab.h>
 #include <linux/cpufreq.h>
 #include <linux/gpio.h>
+#include <linux/of_i2c.h>
+#include <linux/of_device.h>
 
 #include <mach/hardware.h>
-#include <mach/i2c.h>
+#include <linux/platform_data/i2c-davinci.h>
 
 /* ----- global defines ----------------------------------------------- */
 
@@ -114,6 +116,7 @@ struct davinci_i2c_dev {
 	struct completion	xfr_complete;
 	struct notifier_block	freq_transition;
 #endif
+	struct davinci_i2c_platform_data *pdata;
 };
 
 /* default platform data to use if not supplied in the platform_device */
@@ -155,7 +158,7 @@ static void generic_i2c_clock_pulse(unsigned int scl_pin)
 static void i2c_recover_bus(struct davinci_i2c_dev *dev)
 {
 	u32 flag = 0;
-	struct davinci_i2c_platform_data *pdata = dev->dev->platform_data;
+	struct davinci_i2c_platform_data *pdata = dev->pdata;
 
 	dev_err(dev->dev, "initiating i2c bus recovery\n");
 	/* Send NACK to the slave */
@@ -163,8 +166,7 @@ static void i2c_recover_bus(struct davinci_i2c_dev *dev)
 	flag |=  DAVINCI_I2C_MDR_NACK;
 	/* write the data into mode register */
 	davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag);
-	if (pdata)
-		generic_i2c_clock_pulse(pdata->scl_pin);
+	generic_i2c_clock_pulse(pdata->scl_pin);
 	/* Send STOP */
 	flag = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG);
 	flag |= DAVINCI_I2C_MDR_STP;
@@ -187,7 +189,7 @@ static inline void davinci_i2c_reset_ctrl(struct davinci_i2c_dev *i2c_dev,
 
 static void i2c_davinci_calc_clk_dividers(struct davinci_i2c_dev *dev)
 {
-	struct davinci_i2c_platform_data *pdata = dev->dev->platform_data;
+	struct davinci_i2c_platform_data *pdata = dev->pdata;
 	u16 psc;
 	u32 clk;
 	u32 d;
@@ -235,10 +237,7 @@ static void i2c_davinci_calc_clk_dividers(struct davinci_i2c_dev *dev)
  */
 static int i2c_davinci_init(struct davinci_i2c_dev *dev)
 {
-	struct davinci_i2c_platform_data *pdata = dev->dev->platform_data;
-
-	if (!pdata)
-		pdata = &davinci_i2c_platform_data_default;
+	struct davinci_i2c_platform_data *pdata = dev->pdata;
 
 	/* put I2C into reset */
 	davinci_i2c_reset_ctrl(dev, 0);
@@ -260,6 +259,7 @@ static int i2c_davinci_init(struct davinci_i2c_dev *dev)
 	dev_dbg(dev->dev, "bus_freq = %dkHz, bus_delay = %d\n",
 		pdata->bus_freq, pdata->bus_delay);
 
+
 	/* Take the I2C module out of reset: */
 	davinci_i2c_reset_ctrl(dev, 1);
 
@@ -308,13 +308,11 @@ static int
 i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
 {
 	struct davinci_i2c_dev *dev = i2c_get_adapdata(adap);
-	struct davinci_i2c_platform_data *pdata = dev->dev->platform_data;
+	struct davinci_i2c_platform_data *pdata = dev->pdata;
 	u32 flag;
 	u16 w;
 	int r;
 
-	if (!pdata)
-		pdata = &davinci_i2c_platform_data_default;
 	/* Introduce a delay, required for some boards (e.g Davinci EVM) */
 	if (pdata->bus_delay)
 		udelay(pdata->bus_delay);
@@ -635,6 +633,12 @@ static struct i2c_algorithm i2c_davinci_algo = {
 	.functionality	= i2c_davinci_func,
 };
 
+static const struct of_device_id davinci_i2c_of_match[] = {
+	{.compatible = "ti,davinci-i2c", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, davinci_i2c_of_match);
+
 static int davinci_i2c_probe(struct platform_device *pdev)
 {
 	struct davinci_i2c_dev *dev;
@@ -674,14 +678,33 @@ static int davinci_i2c_probe(struct platform_device *pdev)
 #endif
 	dev->dev = get_device(&pdev->dev);
 	dev->irq = irq->start;
+	dev->pdata = dev->dev->platform_data;
 	platform_set_drvdata(pdev, dev);
 
+	if (!dev->pdata && pdev->dev.of_node) {
+		u32 prop;
+
+		dev->pdata = devm_kzalloc(&pdev->dev,
+			sizeof(struct davinci_i2c_platform_data), GFP_KERNEL);
+		if (!dev->pdata) {
+			r = -ENOMEM;
+			goto err_free_mem;
+		}
+		memcpy(dev->pdata, &davinci_i2c_platform_data_default,
+			sizeof(struct davinci_i2c_platform_data));
+		if (!of_property_read_u32(pdev->dev.of_node, "clock-frequency",
+			&prop))
+			dev->pdata->bus_freq = prop / 1000;
+	} else if (!dev->pdata) {
+		dev->pdata = &davinci_i2c_platform_data_default;
+	}
+
 	dev->clk = clk_get(&pdev->dev, NULL);
 	if (IS_ERR(dev->clk)) {
 		r = -ENODEV;
 		goto err_free_mem;
 	}
-	clk_enable(dev->clk);
+	clk_prepare_enable(dev->clk);
 
 	dev->base = ioremap(mem->start, resource_size(mem));
 	if (!dev->base) {
@@ -711,6 +734,7 @@ static int davinci_i2c_probe(struct platform_device *pdev)
 	adap->algo = &i2c_davinci_algo;
 	adap->dev.parent = &pdev->dev;
 	adap->timeout = DAVINCI_I2C_TIMEOUT;
+	adap->dev.of_node = pdev->dev.of_node;
 
 	adap->nr = pdev->id;
 	r = i2c_add_numbered_adapter(adap);
@@ -718,6 +742,7 @@ static int davinci_i2c_probe(struct platform_device *pdev)
 		dev_err(&pdev->dev, "failure adding adapter\n");
 		goto err_free_irq;
 	}
+	of_i2c_register_devices(adap);
 
 	return 0;
 
@@ -726,7 +751,7 @@ err_free_irq:
 err_unuse_clocks:
 	iounmap(dev->base);
 err_mem_ioremap:
-	clk_disable(dev->clk);
+	clk_disable_unprepare(dev->clk);
 	clk_put(dev->clk);
 	dev->clk = NULL;
 err_free_mem:
@@ -750,7 +775,7 @@ static int davinci_i2c_remove(struct platform_device *pdev)
 	i2c_del_adapter(&dev->adapter);
 	put_device(&pdev->dev);
 
-	clk_disable(dev->clk);
+	clk_disable_unprepare(dev->clk);
 	clk_put(dev->clk);
 	dev->clk = NULL;
 
@@ -772,7 +797,7 @@ static int davinci_i2c_suspend(struct device *dev)
 
 	/* put I2C into reset */
 	davinci_i2c_reset_ctrl(i2c_dev, 0);
-	clk_disable(i2c_dev->clk);
+	clk_disable_unprepare(i2c_dev->clk);
 
 	return 0;
 }
@@ -782,7 +807,7 @@ static int davinci_i2c_resume(struct device *dev)
 	struct platform_device *pdev = to_platform_device(dev);
 	struct davinci_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
 
-	clk_enable(i2c_dev->clk);
+	clk_prepare_enable(i2c_dev->clk);
 	/* take I2C out of reset */
 	davinci_i2c_reset_ctrl(i2c_dev, 1);
 
@@ -809,6 +834,7 @@ static struct platform_driver davinci_i2c_driver = {
 		.name	= "i2c_davinci",
 		.owner	= THIS_MODULE,
 		.pm	= davinci_i2c_pm_ops,
+		.of_match_table = of_match_ptr(davinci_i2c_of_match),
 	},
 };
 
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index 33e9b0c..bb1d729 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -80,6 +80,13 @@
 #include <linux/dmi.h>
 #include <linux/slab.h>
 #include <linux/wait.h>
+#include <linux/err.h>
+
+#if defined CONFIG_I2C_MUX || defined CONFIG_I2C_MUX_MODULE
+#include <linux/gpio.h>
+#include <linux/i2c-mux-gpio.h>
+#include <linux/platform_device.h>
+#endif
 
 /* I801 SMBus address offsets */
 #define SMBHSTSTS(p)	(0 + (p)->smba)
@@ -158,6 +165,15 @@
 #define PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS	0x8c22
 #define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_SMBUS	0x9c22
 
+struct i801_mux_config {
+	char *gpio_chip;
+	unsigned values[3];
+	int n_values;
+	unsigned classes[3];
+	unsigned gpios[2];		/* Relative to gpio_chip->base */
+	int n_gpios;
+};
+
 struct i801_priv {
 	struct i2c_adapter adapter;
 	unsigned long smba;
@@ -175,6 +191,12 @@ struct i801_priv {
 	int count;
 	int len;
 	u8 *data;
+
+#if defined CONFIG_I2C_MUX || defined CONFIG_I2C_MUX_MODULE
+	const struct i801_mux_config *mux_drvdata;
+	unsigned mux_priv[2];
+	struct platform_device *mux_pdev;
+#endif
 };
 
 static struct pci_driver i801_driver;
@@ -900,6 +922,193 @@ static void __init input_apanel_init(void) {}
 static void __devinit i801_probe_optional_slaves(struct i801_priv *priv) {}
 #endif	/* CONFIG_X86 && CONFIG_DMI */
 
+#if defined CONFIG_I2C_MUX || defined CONFIG_I2C_MUX_MODULE
+static struct i801_mux_config i801_mux_config_asus_z8_d12 = {
+	.gpio_chip = "gpio_ich",
+	.values = { 0x02, 0x03 },
+	.n_values = 2,
+	.classes = { I2C_CLASS_SPD, I2C_CLASS_SPD },
+	.gpios = { 52, 53 },
+	.n_gpios = 2,
+};
+
+static struct i801_mux_config i801_mux_config_asus_z8_d18 = {
+	.gpio_chip = "gpio_ich",
+	.values = { 0x02, 0x03, 0x01 },
+	.n_values = 3,
+	.classes = { I2C_CLASS_SPD, I2C_CLASS_SPD, I2C_CLASS_SPD },
+	.gpios = { 52, 53 },
+	.n_gpios = 2,
+};
+
+static struct dmi_system_id __devinitdata mux_dmi_table[] = {
+	{
+		.matches = {
+			DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
+			DMI_MATCH(DMI_BOARD_NAME, "Z8NA-D6(C)"),
+		},
+		.driver_data = &i801_mux_config_asus_z8_d12,
+	},
+	{
+		.matches = {
+			DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
+			DMI_MATCH(DMI_BOARD_NAME, "Z8P(N)E-D12(X)"),
+		},
+		.driver_data = &i801_mux_config_asus_z8_d12,
+	},
+	{
+		.matches = {
+			DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
+			DMI_MATCH(DMI_BOARD_NAME, "Z8NH-D12"),
+		},
+		.driver_data = &i801_mux_config_asus_z8_d12,
+	},
+	{
+		.matches = {
+			DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
+			DMI_MATCH(DMI_BOARD_NAME, "Z8PH-D12/IFB"),
+		},
+		.driver_data = &i801_mux_config_asus_z8_d12,
+	},
+	{
+		.matches = {
+			DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
+			DMI_MATCH(DMI_BOARD_NAME, "Z8NR-D12"),
+		},
+		.driver_data = &i801_mux_config_asus_z8_d12,
+	},
+	{
+		.matches = {
+			DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
+			DMI_MATCH(DMI_BOARD_NAME, "Z8P(N)H-D12"),
+		},
+		.driver_data = &i801_mux_config_asus_z8_d12,
+	},
+	{
+		.matches = {
+			DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
+			DMI_MATCH(DMI_BOARD_NAME, "Z8PG-D18"),
+		},
+		.driver_data = &i801_mux_config_asus_z8_d18,
+	},
+	{
+		.matches = {
+			DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
+			DMI_MATCH(DMI_BOARD_NAME, "Z8PE-D18"),
+		},
+		.driver_data = &i801_mux_config_asus_z8_d18,
+	},
+	{
+		.matches = {
+			DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
+			DMI_MATCH(DMI_BOARD_NAME, "Z8PS-D12"),
+		},
+		.driver_data = &i801_mux_config_asus_z8_d12,
+	},
+	{ }
+};
+
+static int __devinit match_gpio_chip_by_label(struct gpio_chip *chip,
+					      void *data)
+{
+	return !strcmp(chip->label, data);
+}
+
+/* Setup multiplexing if needed */
+static int __devinit i801_add_mux(struct i801_priv *priv)
+{
+	struct device *dev = &priv->adapter.dev;
+	const struct i801_mux_config *mux_config;
+	struct gpio_chip *gpio;
+	struct i2c_mux_gpio_platform_data gpio_data;
+	int i, err;
+
+	if (!priv->mux_drvdata)
+		return 0;
+	mux_config = priv->mux_drvdata;
+
+	/* Find GPIO chip */
+	gpio = gpiochip_find(mux_config->gpio_chip, match_gpio_chip_by_label);
+	if (gpio) {
+		dev_info(dev,
+			 "GPIO chip %s found, SMBus multiplexing enabled\n",
+			 mux_config->gpio_chip);
+	} else {
+		dev_err(dev,
+			"GPIO chip %s not found, SMBus multiplexing disabled\n",
+			mux_config->gpio_chip);
+		return -ENODEV;
+	}
+
+	/* Find absolute GPIO pin numbers */
+	if (ARRAY_SIZE(priv->mux_priv) < mux_config->n_gpios) {
+		dev_err(dev, "i801_priv.mux_priv too small (%zu, need %d)\n",
+			ARRAY_SIZE(priv->mux_priv), mux_config->n_gpios);
+		return -ENODEV;
+	}
+	for (i = 0; i < mux_config->n_gpios; i++)
+		priv->mux_priv[i] = gpio->base + mux_config->gpios[i];
+
+	/* Prepare the platform data */
+	memset(&gpio_data, 0, sizeof(struct i2c_mux_gpio_platform_data));
+	gpio_data.parent = priv->adapter.nr;
+	gpio_data.values = mux_config->values;
+	gpio_data.n_values = mux_config->n_values;
+	gpio_data.classes = mux_config->classes;
+	gpio_data.gpios = priv->mux_priv;
+	gpio_data.n_gpios = mux_config->n_gpios;
+	gpio_data.idle = I2C_MUX_GPIO_NO_IDLE;
+
+	/* Register the mux device */
+	priv->mux_pdev = platform_device_register_data(dev, "i2c-mux-gpio",
+				priv->mux_priv[0], &gpio_data,
+				sizeof(struct i2c_mux_gpio_platform_data));
+	if (IS_ERR(priv->mux_pdev)) {
+		err = PTR_ERR(priv->mux_pdev);
+		priv->mux_pdev = NULL;
+		dev_err(dev, "Failed to register i2c-mux-gpio device\n");
+		return err;
+	}
+
+	return 0;
+}
+
+static void __devexit i801_del_mux(struct i801_priv *priv)
+{
+	if (priv->mux_pdev)
+		platform_device_unregister(priv->mux_pdev);
+}
+
+static unsigned int __devinit i801_get_adapter_class(struct i801_priv *priv)
+{
+	const struct dmi_system_id *id;
+	const struct i801_mux_config *mux_config;
+	unsigned int class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
+	int i;
+
+	id = dmi_first_match(mux_dmi_table);
+	if (id) {
+		/* Remove from branch classes from trunk */
+		mux_config = id->driver_data;
+		for (i = 0; i < mux_config->n_values; i++)
+			class &= ~mux_config->classes[i];
+
+		/* Remember for later */
+		priv->mux_drvdata = mux_config;
+	}
+
+	return class;
+}
+#else
+static inline int i801_add_mux(struct i801_priv *priv) { return 0; }
+static inline void i801_del_mux(struct i801_priv *priv) { }
+
+static inline unsigned int i801_get_adapter_class(struct i801_priv *priv)
+{
+	return I2C_CLASS_HWMON | I2C_CLASS_SPD;
+}
+#endif
+
 static int __devinit i801_probe(struct pci_dev *dev,
 				const struct pci_device_id *id)
 {
@@ -913,7 +1122,7 @@ static int __devinit i801_probe(struct pci_dev *dev,
 
 	i2c_set_adapdata(&priv->adapter, priv);
 	priv->adapter.owner = THIS_MODULE;
-	priv->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
+	priv->adapter.class = i801_get_adapter_class(priv);
 	priv->adapter.algo = &smbus_algorithm;
 
 	priv->pci_dev = dev;
@@ -1033,6 +1242,8 @@ static int __devinit i801_probe(struct pci_dev *dev,
 	}
 
 	i801_probe_optional_slaves(priv);
+	/* We ignore errors - multiplexing is optional */
+	i801_add_mux(priv);
 
 	pci_set_drvdata(dev, priv);
 
@@ -1052,6 +1263,7 @@ static void __devexit i801_remove(struct pci_dev *dev)
 {
 	struct i801_priv *priv = pci_get_drvdata(dev);
 
+	i801_del_mux(priv);
 	i2c_del_adapter(&priv->adapter);
 	pci_write_config_byte(dev, SMBHSTCFG, priv->original_hstcfg);
 
diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index 0722f86..2ef162d 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -54,7 +54,7 @@
 #include <linux/pinctrl/consumer.h>
 
 #include <mach/hardware.h>
-#include <mach/i2c.h>
+#include <linux/platform_data/i2c-imx.h>
 
 /** Defines ********************************************************************
 *******************************************************************************/
@@ -272,9 +272,9 @@ static void __init i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx,
 
 	/* dev_dbg() can't be used, because adapter is not yet registered */
 #ifdef CONFIG_I2C_DEBUG_BUS
-	printk(KERN_DEBUG "I2C: <%s> I2C_CLK=%d, REQ DIV=%d\n",
+	dev_dbg(&i2c_imx->adapter.dev, "<%s> I2C_CLK=%d, REQ DIV=%d\n",
 		__func__, i2c_clk_rate, div);
-	printk(KERN_DEBUG "I2C: <%s> IFDR[IC]=0x%x, REAL DIV=%d\n",
+	dev_dbg(&i2c_imx->adapter.dev, "<%s> IFDR[IC]=0x%x, REAL DIV=%d\n",
 		__func__, i2c_clk_div[i][1], i2c_clk_div[i][0]);
 #endif
 }
@@ -564,7 +564,7 @@ static int __init i2c_imx_probe(struct platform_device *pdev)
 		resource_size(res), res->start);
 	dev_dbg(&i2c_imx->adapter.dev, "adapter name: \"%s\"\n",
 		i2c_imx->adapter.name);
-	dev_dbg(&i2c_imx->adapter.dev, "IMX I2C adapter registered\n");
+	dev_info(&i2c_imx->adapter.dev, "IMX I2C adapter registered\n");
 
 	return 0;   /* Return OK */
 }
diff --git a/drivers/i2c/busses/i2c-iop3xx.c b/drivers/i2c/busses/i2c-iop3xx.c
index 93f147a..2f99613 100644
--- a/drivers/i2c/busses/i2c-iop3xx.c
+++ b/drivers/i2c/busses/i2c-iop3xx.c
@@ -4,13 +4,13 @@
 /* Copyright (C) 2003 Peter Milne, D-TACQ Solutions Ltd
  *                    <Peter dot Milne at D hyphen TACQ dot com>
  *
- * With acknowledgements to i2c-algo-ibm_ocp.c by 
+ * With acknowledgements to i2c-algo-ibm_ocp.c by
  * Ian DaSilva, MontaVista Software, Inc. idasilva@mvista.com
  *
  * And i2c-algo-pcf.c, which was created by Simon G. Vogl and Hans Berglund:
  *
  * Copyright (C) 1995-1997 Simon G. Vogl, 1998-2000 Hans Berglund
- *  
+ *
  * And which acknowledged Kyösti Mälkki <kmalkki@cc.hut.fi>,
  * Frodo Looijaard <frodol@dds.nl>, Martin Bailey<mbailey@littlefeet-inc.com>
  *
@@ -39,14 +39,15 @@
 #include <linux/platform_device.h>
 #include <linux/i2c.h>
 #include <linux/io.h>
+#include <linux/gpio.h>
 
 #include "i2c-iop3xx.h"
 
 /* global unit counter */
 static int i2c_id;
 
-static inline unsigned char 
-iic_cook_addr(struct i2c_msg *msg) 
+static inline unsigned char
+iic_cook_addr(struct i2c_msg *msg)
 {
 	unsigned char addr;
 
@@ -55,38 +56,38 @@ iic_cook_addr(struct i2c_msg *msg)
 	if (msg->flags & I2C_M_RD)
 		addr |= 1;
 
-	return addr;   
+	return addr;
 }
 
-static void 
+static void
 iop3xx_i2c_reset(struct i2c_algo_iop3xx_data *iop3xx_adap)
 {
 	/* Follows devman 9.3 */
 	__raw_writel(IOP3XX_ICR_UNIT_RESET, iop3xx_adap->ioaddr + CR_OFFSET);
 	__raw_writel(IOP3XX_ISR_CLEARBITS, iop3xx_adap->ioaddr + SR_OFFSET);
 	__raw_writel(0, iop3xx_adap->ioaddr + CR_OFFSET);
-} 
+}
 
-static void 
+static void
 iop3xx_i2c_enable(struct i2c_algo_iop3xx_data *iop3xx_adap)
 {
 	u32 cr = IOP3XX_ICR_GCD | IOP3XX_ICR_SCLEN | IOP3XX_ICR_UE;
 
-	/* 
+	/*
 	 * Every time unit enable is asserted, GPOD needs to be cleared
 	 * on IOP3XX to avoid data corruption on the bus.
 	 */
 #if defined(CONFIG_ARCH_IOP32X) || defined(CONFIG_ARCH_IOP33X)
 	if (iop3xx_adap->id == 0) {
-		gpio_line_set(IOP3XX_GPIO_LINE(7), GPIO_LOW);
-		gpio_line_set(IOP3XX_GPIO_LINE(6), GPIO_LOW);
+		gpio_set_value(7, 0);
+		gpio_set_value(6, 0);
 	} else {
-		gpio_line_set(IOP3XX_GPIO_LINE(5), GPIO_LOW);
-		gpio_line_set(IOP3XX_GPIO_LINE(4), GPIO_LOW);
+		gpio_set_value(5, 0);
+		gpio_set_value(4, 0);
 	}
 #endif
 	/* NB SR bits not same position as CR IE bits :-( */
-	iop3xx_adap->SR_enabled = 
+	iop3xx_adap->SR_enabled =
 		IOP3XX_ISR_ALD | IOP3XX_ISR_BERRD |
 		IOP3XX_ISR_RXFULL | IOP3XX_ISR_TXEMPTY;
 
@@ -96,23 +97,23 @@ iop3xx_i2c_enable(struct i2c_algo_iop3xx_data *iop3xx_adap)
 	__raw_writel(cr, iop3xx_adap->ioaddr + CR_OFFSET);
 }
 
-static void 
+static void
 iop3xx_i2c_transaction_cleanup(struct i2c_algo_iop3xx_data *iop3xx_adap)
 {
 	unsigned long cr = __raw_readl(iop3xx_adap->ioaddr + CR_OFFSET);
-	
-	cr &= ~(IOP3XX_ICR_MSTART | IOP3XX_ICR_TBYTE | 
+
+	cr &= ~(IOP3XX_ICR_MSTART | IOP3XX_ICR_TBYTE |
 		IOP3XX_ICR_MSTOP | IOP3XX_ICR_SCLEN);
 
 	__raw_writel(cr, iop3xx_adap->ioaddr + CR_OFFSET);
 }
 
-/* 
- * NB: the handler has to clear the source of the interrupt! 
+/*
+ * NB: the handler has to clear the source of the interrupt!
  * Then it passes the SR flags of interest to BH via adap data
  */
-static irqreturn_t 
-iop3xx_i2c_irq_handler(int this_irq, void *dev_id) 
+static irqreturn_t
+iop3xx_i2c_irq_handler(int this_irq, void *dev_id)
 {
 	struct i2c_algo_iop3xx_data *iop3xx_adap = dev_id;
 	u32 sr = __raw_readl(iop3xx_adap->ioaddr + SR_OFFSET);
@@ -126,7 +127,7 @@ iop3xx_i2c_irq_handler(int this_irq, void *dev_id)
 }
 
 /* check all error conditions, clear them , report most important */
-static int 
+static int
 iop3xx_i2c_error(u32 sr)
 {
 	int rc = 0;
@@ -135,12 +136,12 @@ iop3xx_i2c_error(u32 sr)
 		if ( !rc ) rc = -I2C_ERR_BERR;
 	}
 	if ((sr & IOP3XX_ISR_ALD)) {
-		if ( !rc ) rc = -I2C_ERR_ALD;		
+		if ( !rc ) rc = -I2C_ERR_ALD;
 	}
-	return rc;	
+	return rc;
 }
 
-static inline u32 
+static inline u32
 iop3xx_i2c_get_srstat(struct i2c_algo_iop3xx_data *iop3xx_adap)
 {
 	unsigned long flags;
@@ -161,8 +162,8 @@ iop3xx_i2c_get_srstat(struct i2c_algo_iop3xx_data *iop3xx_adap)
 typedef int (* compare_func)(unsigned test, unsigned mask);
 /* returns 1 on correct comparison */
 
-static int 
-iop3xx_i2c_wait_event(struct i2c_algo_iop3xx_data *iop3xx_adap, 
+static int
+iop3xx_i2c_wait_event(struct i2c_algo_iop3xx_data *iop3xx_adap,
 			  unsigned flags, unsigned* status,
 			  compare_func compare)
 {
@@ -192,47 +193,47 @@ iop3xx_i2c_wait_event(struct i2c_algo_iop3xx_data *iop3xx_adap,
 }
 
 /*
- * Concrete compare_funcs 
+ * Concrete compare_funcs
  */
-static int 
+static int
 all_bits_clear(unsigned test, unsigned mask)
 {
 	return (test & mask) == 0;
 }
 
-static int 
+static int
 any_bits_set(unsigned test, unsigned mask)
 {
 	return (test & mask) != 0;
 }
 
-static int 
+static int
 iop3xx_i2c_wait_tx_done(struct i2c_algo_iop3xx_data *iop3xx_adap, int *status)
 {
-	return iop3xx_i2c_wait_event( 
-		iop3xx_adap, 
+	return iop3xx_i2c_wait_event(
+		iop3xx_adap,
 	        IOP3XX_ISR_TXEMPTY | IOP3XX_ISR_ALD | IOP3XX_ISR_BERRD,
 		status, any_bits_set);
 }
 
-static int 
+static int
 iop3xx_i2c_wait_rx_done(struct i2c_algo_iop3xx_data *iop3xx_adap, int *status)
 {
-	return iop3xx_i2c_wait_event( 
-		iop3xx_adap, 
+	return iop3xx_i2c_wait_event(
+		iop3xx_adap,
 		IOP3XX_ISR_RXFULL | IOP3XX_ISR_ALD | IOP3XX_ISR_BERRD,
 		status,	any_bits_set);
 }
 
-static int 
+static int
 iop3xx_i2c_wait_idle(struct i2c_algo_iop3xx_data *iop3xx_adap, int *status)
 {
-	return iop3xx_i2c_wait_event( 
+	return iop3xx_i2c_wait_event(
 		iop3xx_adap, IOP3XX_ISR_UNITBUSY, status, all_bits_clear);
 }
 
-static int 
-iop3xx_i2c_send_target_addr(struct i2c_algo_iop3xx_data *iop3xx_adap, 
+static int
+iop3xx_i2c_send_target_addr(struct i2c_algo_iop3xx_data *iop3xx_adap,
 				struct i2c_msg* msg)
 {
 	unsigned long cr = __raw_readl(iop3xx_adap->ioaddr + CR_OFFSET);
@@ -247,7 +248,7 @@ iop3xx_i2c_send_target_addr(struct i2c_algo_iop3xx_data *iop3xx_adap,
 	}
 
 	__raw_writel(iic_cook_addr(msg), iop3xx_adap->ioaddr + DBR_OFFSET);
-	
+
 	cr &= ~(IOP3XX_ICR_MSTOP | IOP3XX_ICR_NACK);
 	cr |= IOP3XX_ICR_MSTART | IOP3XX_ICR_TBYTE;
 
@@ -257,8 +258,8 @@ iop3xx_i2c_send_target_addr(struct i2c_algo_iop3xx_data *iop3xx_adap,
 	return rc;
 }
 
-static int 
-iop3xx_i2c_write_byte(struct i2c_algo_iop3xx_data *iop3xx_adap, char byte, 
+static int
+iop3xx_i2c_write_byte(struct i2c_algo_iop3xx_data *iop3xx_adap, char byte,
 				int stop)
 {
 	unsigned long cr = __raw_readl(iop3xx_adap->ioaddr + CR_OFFSET);
@@ -277,10 +278,10 @@ iop3xx_i2c_write_byte(struct i2c_algo_iop3xx_data *iop3xx_adap, char byte,
 	rc = iop3xx_i2c_wait_tx_done(iop3xx_adap, &status);
 
 	return rc;
-} 
+}
 
-static int 
-iop3xx_i2c_read_byte(struct i2c_algo_iop3xx_data *iop3xx_adap, char* byte, 
+static int
+iop3xx_i2c_read_byte(struct i2c_algo_iop3xx_data *iop3xx_adap, char* byte,
 				int stop)
 {
 	unsigned long cr = __raw_readl(iop3xx_adap->ioaddr + CR_OFFSET);
@@ -304,19 +305,19 @@ iop3xx_i2c_read_byte(struct i2c_algo_iop3xx_data *iop3xx_adap, char* byte,
 	return rc;
 }
 
-static int 
+static int
 iop3xx_i2c_writebytes(struct i2c_adapter *i2c_adap, const char *buf, int count)
 {
 	struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data;
 	int ii;
 	int rc = 0;
 
-	for (ii = 0; rc == 0 && ii != count; ++ii) 
+	for (ii = 0; rc == 0 && ii != count; ++ii)
 		rc = iop3xx_i2c_write_byte(iop3xx_adap, buf[ii], ii==count-1);
 	return rc;
 }
 
-static int 
+static int
 iop3xx_i2c_readbytes(struct i2c_adapter *i2c_adap, char *buf, int count)
 {
 	struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data;
@@ -325,7 +326,7 @@ iop3xx_i2c_readbytes(struct i2c_adapter *i2c_adap, char *buf, int count)
 
 	for (ii = 0; rc == 0 && ii != count; ++ii)
 		rc = iop3xx_i2c_read_byte(iop3xx_adap, &buf[ii], ii==count-1);
-	
+
 	return rc;
 }
 
@@ -336,8 +337,8 @@ iop3xx_i2c_readbytes(struct i2c_adapter *i2c_adap, char *buf, int count)
  * Each transfer (i.e. a read or a write) is separated by a repeated start
  * condition.
  */
-static int 
-iop3xx_i2c_handle_msg(struct i2c_adapter *i2c_adap, struct i2c_msg* pmsg) 
+static int
+iop3xx_i2c_handle_msg(struct i2c_adapter *i2c_adap, struct i2c_msg* pmsg)
 {
 	struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data;
 	int rc;
@@ -357,8 +358,8 @@ iop3xx_i2c_handle_msg(struct i2c_adapter *i2c_adap, struct i2c_msg* pmsg)
 /*
  * master_xfer() - main read/write entry
  */
-static int 
-iop3xx_i2c_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, 
+static int
+iop3xx_i2c_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,
 				int num)
 {
 	struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data;
@@ -375,14 +376,14 @@ iop3xx_i2c_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,
 	}
 
 	iop3xx_i2c_transaction_cleanup(iop3xx_adap);
-	
+
 	if(ret)
 		return ret;
 
-	return im;   
+	return im;
 }
 
-static u32 
+static u32
 iop3xx_i2c_func(struct i2c_adapter *adap)
 {
 	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
@@ -393,11 +394,11 @@ static const struct i2c_algorithm iop3xx_i2c_algo = {
 	.functionality	= iop3xx_i2c_func,
 };
 
-static int 
+static int
 iop3xx_i2c_remove(struct platform_device *pdev)
 {
 	struct i2c_adapter *padapter = platform_get_drvdata(pdev);
-	struct i2c_algo_iop3xx_data *adapter_data = 
+	struct i2c_algo_iop3xx_data *adapter_data =
 		(struct i2c_algo_iop3xx_data *)padapter->algo_data;
 	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	unsigned long cr = __raw_readl(adapter_data->ioaddr + CR_OFFSET);
@@ -419,7 +420,7 @@ iop3xx_i2c_remove(struct platform_device *pdev)
 	return 0;
 }
 
-static int 
+static int
 iop3xx_i2c_probe(struct platform_device *pdev)
 {
 	struct resource *res;
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index b76731e..57f7703 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -647,7 +647,7 @@ static int __devinit fsl_i2c_probe(struct platform_device *op)
 	}
 
 	if (match->data) {
-		struct mpc_i2c_data *data = match->data;
+		const struct mpc_i2c_data *data = match->data;
 		data->setup(op->dev.of_node, i2c, clock, data->prescaler);
 	} else {
 		/* Backwards compatibility */
@@ -730,24 +730,24 @@ static int mpc_i2c_resume(struct device *dev)
 SIMPLE_DEV_PM_OPS(mpc_i2c_pm_ops, mpc_i2c_suspend, mpc_i2c_resume);
 #endif
 
-static struct mpc_i2c_data mpc_i2c_data_512x __devinitdata = {
+static const struct mpc_i2c_data mpc_i2c_data_512x __devinitdata = {
 	.setup = mpc_i2c_setup_512x,
 };
 
-static struct mpc_i2c_data mpc_i2c_data_52xx __devinitdata = {
+static const struct mpc_i2c_data mpc_i2c_data_52xx __devinitdata = {
 	.setup = mpc_i2c_setup_52xx,
 };
 
-static struct mpc_i2c_data mpc_i2c_data_8313 __devinitdata = {
+static const struct mpc_i2c_data mpc_i2c_data_8313 __devinitdata = {
 	.setup = mpc_i2c_setup_8xxx,
 };
 
-static struct mpc_i2c_data mpc_i2c_data_8543 __devinitdata = {
+static const struct mpc_i2c_data mpc_i2c_data_8543 __devinitdata = {
 	.setup = mpc_i2c_setup_8xxx,
 	.prescaler = 2,
 };
 
-static struct mpc_i2c_data mpc_i2c_data_8544 __devinitdata = {
+static const struct mpc_i2c_data mpc_i2c_data_8544 __devinitdata = {
 	.setup = mpc_i2c_setup_8xxx,
 	.prescaler = 3,
 };
diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c
index 61b00ed..1b898b6 100644
--- a/drivers/i2c/busses/i2c-nomadik.c
+++ b/drivers/i2c/busses/i2c-nomadik.c
@@ -22,7 +22,6 @@
 #include <linux/err.h>
 #include <linux/clk.h>
 #include <linux/io.h>
-#include <linux/regulator/consumer.h>
 #include <linux/pm_runtime.h>
 #include <linux/platform_data/i2c-nomadik.h>
 
@@ -146,7 +145,6 @@ struct i2c_nmk_client {
  * @stop: stop condition.
  * @xfer_complete: acknowledge completion for a I2C message.
  * @result: controller propogated result.
- * @regulator: pointer to i2c regulator.
  * @busy: Busy doing transfer.
  */
 struct nmk_i2c_dev {
@@ -160,7 +158,6 @@ struct nmk_i2c_dev {
 	int				stop;
 	struct completion		xfer_complete;
 	int				result;
-	struct regulator		*regulator;
 	bool				busy;
 };
 
@@ -643,8 +640,6 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap,
 
 	dev->busy = true;
 
-	if (dev->regulator)
-		regulator_enable(dev->regulator);
 	pm_runtime_get_sync(&dev->adev->dev);
 
 	clk_enable(dev->clk);
@@ -676,8 +671,6 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap,
 out:
 	clk_disable(dev->clk);
 	pm_runtime_put_sync(&dev->adev->dev);
-	if (dev->regulator)
-		regulator_disable(dev->regulator);
 
 	dev->busy = false;
 
@@ -957,12 +950,6 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id)
 		goto err_irq;
 	}
 
-	dev->regulator = regulator_get(&adev->dev, "v-i2c");
-	if (IS_ERR(dev->regulator)) {
-		dev_warn(&adev->dev, "could not get i2c regulator\n");
-		dev->regulator = NULL;
-	}
-
 	pm_suspend_ignore_children(&adev->dev, true);
 
 	dev->clk = clk_get(&adev->dev, NULL);
@@ -1009,8 +996,6 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id)
  err_add_adap:
 	clk_put(dev->clk);
  err_no_clk:
-	if (dev->regulator)
-		regulator_put(dev->regulator);
 	free_irq(dev->irq, dev);
  err_irq:
 	iounmap(dev->virtbase);
@@ -1038,8 +1023,6 @@ static int nmk_i2c_remove(struct amba_device *adev)
 	if (res)
 		release_mem_region(res->start, resource_size(res));
 	clk_put(dev->clk);
-	if (dev->regulator)
-		regulator_put(dev->regulator);
 	pm_runtime_disable(&adev->dev);
 	amba_set_drvdata(adev, NULL);
 	kfree(dev);
diff --git a/drivers/i2c/busses/i2c-nuc900.c b/drivers/i2c/busses/i2c-nuc900.c
index a26dfb8..f41502e 100644
--- a/drivers/i2c/busses/i2c-nuc900.c
+++ b/drivers/i2c/busses/i2c-nuc900.c
@@ -29,7 +29,7 @@
 #include <linux/io.h>
 
 #include <mach/mfp.h>
-#include <mach/i2c.h>
+#include <linux/platform_data/i2c-nuc900.h>
 
 /* nuc900 i2c registers offset */
 
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index 5d19a49..0b02543 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -55,6 +55,9 @@
 /* timeout waiting for the controller to respond */
 #define OMAP_I2C_TIMEOUT (msecs_to_jiffies(1000))
 
+/* timeout for pm runtime autosuspend */
+#define OMAP_I2C_PM_TIMEOUT		1000	/* ms */
+
 /* For OMAP3 I2C_IV has changed to I2C_WE (wakeup enable) */
 enum {
 	OMAP_I2C_REV_REG = 0,
@@ -176,6 +179,7 @@ enum {
 #define I2C_OMAP_ERRATA_I462		(1 << 1)
 
 struct omap_i2c_dev {
+	spinlock_t		lock;		/* IRQ synchronization */
 	struct device		*dev;
 	void __iomem		*base;		/* virtual */
 	int			irq;
@@ -193,12 +197,14 @@ struct omap_i2c_dev {
 	u8			*regs;
 	size_t			buf_len;
 	struct i2c_adapter	adapter;
+	u8			threshold;
 	u8			fifo_size;	/* use as flag and value
 						 * fifo_size==0 implies no fifo
 						 * if set, should be trsh+1
 						 */
 	u8			rev;
 	unsigned		b_hw:1;		/* bad h/w fixes */
+	unsigned		receiver:1;	/* true when we're in receiver mode */
 	u16			iestate;	/* Saved interrupt register */
 	u16			pscstate;
 	u16			scllstate;
@@ -417,13 +423,6 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
 	omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG, scll);
 	omap_i2c_write_reg(dev, OMAP_I2C_SCLH_REG, sclh);
 
-	if (dev->fifo_size) {
-		/* Note: setup required fifo size - 1. RTRSH and XTRSH */
-		buf = (dev->fifo_size - 1) << 8 | OMAP_I2C_BUF_RXFIF_CLR |
-			(dev->fifo_size - 1) | OMAP_I2C_BUF_TXFIF_CLR;
-		omap_i2c_write_reg(dev, OMAP_I2C_BUF_REG, buf);
-	}
-
 	/* Take the I2C module out of reset: */
 	omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN);
 
@@ -461,6 +460,45 @@ static int omap_i2c_wait_for_bb(struct omap_i2c_dev *dev)
 	return 0;
 }
 
+static void omap_i2c_resize_fifo(struct omap_i2c_dev *dev, u8 size, bool is_rx)
+{
+	u16		buf;
+
+	if (dev->flags & OMAP_I2C_FLAG_NO_FIFO)
+		return;
+
+	/*
+	 * Set up notification threshold based on message size. We're doing
+	 * this to try and avoid draining feature as much as possible. Whenever
+	 * we have big messages to transfer (bigger than our total fifo size)
+	 * then we might use draining feature to transfer the remaining bytes.
+	 */
+
+	dev->threshold = clamp(size, (u8) 1, dev->fifo_size);
+
+	buf = omap_i2c_read_reg(dev, OMAP_I2C_BUF_REG);
+
+	if (is_rx) {
+		/* Clear RX Threshold */
+		buf &= ~(0x3f << 8);
+		buf |= ((dev->threshold - 1) << 8) | OMAP_I2C_BUF_RXFIF_CLR;
+	} else {
+		/* Clear TX Threshold */
+		buf &= ~0x3f;
+		buf |= (dev->threshold - 1) | OMAP_I2C_BUF_TXFIF_CLR;
+	}
+
+	omap_i2c_write_reg(dev, OMAP_I2C_BUF_REG, buf);
+
+	if (dev->rev < OMAP_I2C_REV_ON_3630_4430)
+		dev->b_hw = 1; /* Enable hardware fixes */
+
+	/* calculate wakeup latency constraint for MPU */
+	if (dev->set_mpu_wkup_lat != NULL)
+		dev->latency = (1000000 * dev->threshold) /
+			(1000 * dev->speed / 8);
+}
+
 /*
  * Low level master read/write transaction.
  */
@@ -477,6 +515,9 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap,
 	if (msg->len == 0)
 		return -EINVAL;
 
+	dev->receiver = !!(msg->flags & I2C_M_RD);
+	omap_i2c_resize_fifo(dev, msg->len, dev->receiver);
+
 	omap_i2c_write_reg(dev, OMAP_I2C_SA_REG, msg->addr);
 
 	/* REVISIT: Could the STB bit of I2C_CON be used with probing? */
@@ -607,7 +648,8 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
 
 	omap_i2c_wait_for_bb(dev);
 out:
-	pm_runtime_put(dev->dev);
+	pm_runtime_mark_last_busy(dev->dev);
+	pm_runtime_put_autosuspend(dev->dev);
 	return r;
 }
 
@@ -725,186 +767,252 @@ omap_i2c_omap1_isr(int this_irq, void *dev_id)
  * data to DATA_REG. Otherwise some data bytes can be lost while transferring
  * them from the memory to the I2C interface.
  */
-static int errata_omap3_i462(struct omap_i2c_dev *dev, u16 *stat, int *err)
+static int errata_omap3_i462(struct omap_i2c_dev *dev)
 {
 	unsigned long timeout = 10000;
+	u16 stat;
 
-	while (--timeout && !(*stat & OMAP_I2C_STAT_XUDF)) {
-		if (*stat & (OMAP_I2C_STAT_NACK | OMAP_I2C_STAT_AL)) {
-			omap_i2c_ack_stat(dev, *stat & (OMAP_I2C_STAT_XRDY |
+	do {
+		stat = omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG);
+		if (stat & OMAP_I2C_STAT_XUDF)
+			break;
+
+		if (stat & (OMAP_I2C_STAT_NACK | OMAP_I2C_STAT_AL)) {
+			omap_i2c_ack_stat(dev, (OMAP_I2C_STAT_XRDY |
 							OMAP_I2C_STAT_XDR));
-			return -ETIMEDOUT;
+			if (stat & OMAP_I2C_STAT_NACK) {
+				dev->cmd_err |= OMAP_I2C_STAT_NACK;
+				omap_i2c_ack_stat(dev, OMAP_I2C_STAT_NACK);
+			}
+
+			if (stat & OMAP_I2C_STAT_AL) {
+				dev_err(dev->dev, "Arbitration lost\n");
+				dev->cmd_err |= OMAP_I2C_STAT_AL;
+				omap_i2c_ack_stat(dev, OMAP_I2C_STAT_NACK);
+			}
+
+			return -EIO;
 		}
 
 		cpu_relax();
-		*stat = omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG);
-	}
+	} while (--timeout);
 
 	if (!timeout) {
 		dev_err(dev->dev, "timeout waiting on XUDF bit\n");
 		return 0;
 	}
 
-	*err |= OMAP_I2C_STAT_XUDF;
 	return 0;
 }
 
+static void omap_i2c_receive_data(struct omap_i2c_dev *dev, u8 num_bytes,
+		bool is_rdr)
+{
+	u16		w;
+
+	while (num_bytes--) {
+		w = omap_i2c_read_reg(dev, OMAP_I2C_DATA_REG);
+		*dev->buf++ = w;
+		dev->buf_len--;
+
+		/*
+		 * Data reg in 2430, omap3 and
+		 * omap4 is 8 bit wide
+		 */
+		if (dev->flags & OMAP_I2C_FLAG_16BIT_DATA_REG) {
+			*dev->buf++ = w >> 8;
+			dev->buf_len--;
+		}
+	}
+}
+
+static int omap_i2c_transmit_data(struct omap_i2c_dev *dev, u8 num_bytes,
+		bool is_xdr)
+{
+	u16		w;
+
+	while (num_bytes--) {
+		w = *dev->buf++;
+		dev->buf_len--;
+
+		/*
+		 * Data reg in 2430, omap3 and
+		 * omap4 is 8 bit wide
+		 */
+		if (dev->flags & OMAP_I2C_FLAG_16BIT_DATA_REG) {
+			w |= *dev->buf++ << 8;
+			dev->buf_len--;
+		}
+
+		if (dev->errata & I2C_OMAP_ERRATA_I462) {
+			int ret;
+
+			ret = errata_omap3_i462(dev);
+			if (ret < 0)
+				return ret;
+		}
+
+		omap_i2c_write_reg(dev, OMAP_I2C_DATA_REG, w);
+	}
+
+	return 0;
+}
+
+static irqreturn_t
+omap_i2c_isr(int irq, void *dev_id)
+{
+	struct omap_i2c_dev *dev = dev_id;
+	irqreturn_t ret = IRQ_HANDLED;
+	u16 mask;
+	u16 stat;
+
+	spin_lock(&dev->lock);
+	mask = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG);
+	stat = omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG);
+
+	if (stat & mask)
+		ret = IRQ_WAKE_THREAD;
+
+	spin_unlock(&dev->lock);
+
+	return ret;
+}
+
 static irqreturn_t
-omap_i2c_isr(int this_irq, void *dev_id)
+omap_i2c_isr_thread(int this_irq, void *dev_id)
 {
 	struct omap_i2c_dev *dev = dev_id;
+	unsigned long flags;
 	u16 bits;
-	u16 stat, w;
-	int err, count = 0;
+	u16 stat;
+	int err = 0, count = 0;
+
+	spin_lock_irqsave(&dev->lock, flags);
+	do {
+		bits = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG);
+		stat = omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG);
+		stat &= bits;
+
+		/* If we're in receiver mode, ignore XDR/XRDY */
+		if (dev->receiver)
+			stat &= ~(OMAP_I2C_STAT_XDR | OMAP_I2C_STAT_XRDY);
+		else
+			stat &= ~(OMAP_I2C_STAT_RDR | OMAP_I2C_STAT_RRDY);
 
-	if (pm_runtime_suspended(dev->dev))
-		return IRQ_NONE;
+		if (!stat) {
+			/* my work here is done */
+			goto out;
+		}
 
-	bits = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG);
-	while ((stat = (omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG))) & bits) {
 		dev_dbg(dev->dev, "IRQ (ISR = 0x%04x)\n", stat);
 		if (count++ == 100) {
 			dev_warn(dev->dev, "Too much work in one IRQ\n");
 			break;
 		}
 
-		err = 0;
-complete:
-		/*
-		 * Ack the stat in one go, but [R/X]DR and [R/X]RDY should be
-		 * acked after the data operation is complete.
-		 * Ref: TRM SWPU114Q Figure 18-31
-		 */
-		omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, stat &
-				~(OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR |
-				OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR));
-
-		if (stat & OMAP_I2C_STAT_NACK)
+		if (stat & OMAP_I2C_STAT_NACK) {
 			err |= OMAP_I2C_STAT_NACK;
+			omap_i2c_ack_stat(dev, OMAP_I2C_STAT_NACK);
+			break;
+		}
 
 		if (stat & OMAP_I2C_STAT_AL) {
 			dev_err(dev->dev, "Arbitration lost\n");
 			err |= OMAP_I2C_STAT_AL;
+			omap_i2c_ack_stat(dev, OMAP_I2C_STAT_AL);
+			break;
 		}
+
 		/*
 		 * ProDB0017052: Clear ARDY bit twice
 		 */
 		if (stat & (OMAP_I2C_STAT_ARDY | OMAP_I2C_STAT_NACK |
 					OMAP_I2C_STAT_AL)) {
-			omap_i2c_ack_stat(dev, stat &
-				(OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR |
-				OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR |
-				OMAP_I2C_STAT_ARDY));
-			omap_i2c_complete_cmd(dev, err);
-			return IRQ_HANDLED;
+			omap_i2c_ack_stat(dev, (OMAP_I2C_STAT_RRDY |
+						OMAP_I2C_STAT_RDR |
+						OMAP_I2C_STAT_XRDY |
+						OMAP_I2C_STAT_XDR |
+						OMAP_I2C_STAT_ARDY));
+			break;
 		}
-		if (stat & (OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR)) {
+
+		if (stat & OMAP_I2C_STAT_RDR) {
 			u8 num_bytes = 1;
 
+			if (dev->fifo_size)
+				num_bytes = dev->buf_len;
+
+			omap_i2c_receive_data(dev, num_bytes, true);
+
 			if (dev->errata & I2C_OMAP_ERRATA_I207)
 				i2c_omap_errata_i207(dev, stat);
 
-			if (dev->fifo_size) {
-				if (stat & OMAP_I2C_STAT_RRDY)
-					num_bytes = dev->fifo_size;
-				else    /* read RXSTAT on RDR interrupt */
-					num_bytes = (omap_i2c_read_reg(dev,
-							OMAP_I2C_BUFSTAT_REG)
-							>> 8) & 0x3F;
-			}
-			while (num_bytes) {
-				num_bytes--;
-				w = omap_i2c_read_reg(dev, OMAP_I2C_DATA_REG);
-				if (dev->buf_len) {
-					*dev->buf++ = w;
-					dev->buf_len--;
-					/*
-					 * Data reg in 2430, omap3 and
-					 * omap4 is 8 bit wide
-					 */
-					if (dev->flags &
-						 OMAP_I2C_FLAG_16BIT_DATA_REG) {
-						if (dev->buf_len) {
-							*dev->buf++ = w >> 8;
-							dev->buf_len--;
-						}
-					}
-				} else {
-					if (stat & OMAP_I2C_STAT_RRDY)
-						dev_err(dev->dev,
-							"RRDY IRQ while no data"
-								" requested\n");
-					if (stat & OMAP_I2C_STAT_RDR)
-						dev_err(dev->dev,
-							"RDR IRQ while no data"
-								" requested\n");
-					break;
-				}
-			}
-			omap_i2c_ack_stat(dev,
-				stat & (OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR));
+			omap_i2c_ack_stat(dev, OMAP_I2C_STAT_RDR);
+			break;
+		}
+
+		if (stat & OMAP_I2C_STAT_RRDY) {
+			u8 num_bytes = 1;
+
+			if (dev->threshold)
+				num_bytes = dev->threshold;
+
+			omap_i2c_receive_data(dev, num_bytes, false);
+			omap_i2c_ack_stat(dev, OMAP_I2C_STAT_RRDY);
 			continue;
 		}
-		if (stat & (OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR)) {
+
+		if (stat & OMAP_I2C_STAT_XDR) {
 			u8 num_bytes = 1;
-			if (dev->fifo_size) {
-				if (stat & OMAP_I2C_STAT_XRDY)
-					num_bytes = dev->fifo_size;
-				else    /* read TXSTAT on XDR interrupt */
-					num_bytes = omap_i2c_read_reg(dev,
-							OMAP_I2C_BUFSTAT_REG)
-							& 0x3F;
-			}
-			while (num_bytes) {
-				num_bytes--;
-				w = 0;
-				if (dev->buf_len) {
-					w = *dev->buf++;
-					dev->buf_len--;
-					/*
-					 * Data reg in 2430, omap3 and
-					 * omap4 is 8 bit wide
-					 */
-					if (dev->flags &
-						 OMAP_I2C_FLAG_16BIT_DATA_REG) {
-						if (dev->buf_len) {
-							w |= *dev->buf++ << 8;
-							dev->buf_len--;
-						}
-					}
-				} else {
-					if (stat & OMAP_I2C_STAT_XRDY)
-						dev_err(dev->dev,
-							"XRDY IRQ while no "
-							"data to send\n");
-					if (stat & OMAP_I2C_STAT_XDR)
-						dev_err(dev->dev,
-							"XDR IRQ while no "
-							"data to send\n");
-					break;
-				}
-
-				if ((dev->errata & I2C_OMAP_ERRATA_I462) &&
-				    errata_omap3_i462(dev, &stat, &err))
-					goto complete;
-
-				omap_i2c_write_reg(dev, OMAP_I2C_DATA_REG, w);
-			}
-			omap_i2c_ack_stat(dev,
-				stat & (OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR));
+			int ret;
+
+			if (dev->fifo_size)
+				num_bytes = dev->buf_len;
+
+			ret = omap_i2c_transmit_data(dev, num_bytes, true);
+			if (ret < 0)
+				break;
+
+			omap_i2c_ack_stat(dev, OMAP_I2C_STAT_XDR);
+			break;
+		}
+
+		if (stat & OMAP_I2C_STAT_XRDY) {
+			u8 num_bytes = 1;
+			int ret;
+
+			if (dev->threshold)
+				num_bytes = dev->threshold;
+
+			ret = omap_i2c_transmit_data(dev, num_bytes, false);
+			if (ret < 0)
+				break;
+
+			omap_i2c_ack_stat(dev, OMAP_I2C_STAT_XRDY);
 			continue;
 		}
+
 		if (stat & OMAP_I2C_STAT_ROVR) {
 			dev_err(dev->dev, "Receive overrun\n");
-			dev->cmd_err |= OMAP_I2C_STAT_ROVR;
+			err |= OMAP_I2C_STAT_ROVR;
+			omap_i2c_ack_stat(dev, OMAP_I2C_STAT_ROVR);
+			break;
 		}
+
 		if (stat & OMAP_I2C_STAT_XUDF) {
 			dev_err(dev->dev, "Transmit underflow\n");
-			dev->cmd_err |= OMAP_I2C_STAT_XUDF;
+			err |= OMAP_I2C_STAT_XUDF;
+			omap_i2c_ack_stat(dev, OMAP_I2C_STAT_XUDF);
+			break;
 		}
-	}
+	} while (stat);
+
+	omap_i2c_complete_cmd(dev, err);
+
+out:
+	spin_unlock_irqrestore(&dev->lock, flags);
 
-	return count ? IRQ_HANDLED : IRQ_NONE;
+	return IRQ_HANDLED;
 }
 
 static const struct i2c_algorithm omap_i2c_algo = {
@@ -943,11 +1051,12 @@ omap_i2c_probe(struct platform_device *pdev)
 {
 	struct omap_i2c_dev	*dev;
 	struct i2c_adapter	*adap;
-	struct resource		*mem, *irq, *ioarea;
-	struct omap_i2c_bus_platform_data *pdata = pdev->dev.platform_data;
+	struct resource		*mem;
+	const struct omap_i2c_bus_platform_data *pdata =
+		pdev->dev.platform_data;
 	struct device_node	*node = pdev->dev.of_node;
 	const struct of_device_id *match;
-	irq_handler_t isr;
+	int irq;
 	int r;
 
 	/* NOTE: driver uses the static register mapping */
@@ -956,23 +1065,23 @@ omap_i2c_probe(struct platform_device *pdev)
 		dev_err(&pdev->dev, "no mem resource?\n");
 		return -ENODEV;
 	}
-	irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	if (!irq) {
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
 		dev_err(&pdev->dev, "no irq resource?\n");
-		return -ENODEV;
+		return irq;
 	}
 
-	ioarea = request_mem_region(mem->start, resource_size(mem),
-			pdev->name);
-	if (!ioarea) {
-		dev_err(&pdev->dev, "I2C region already claimed\n");
-		return -EBUSY;
+	dev = devm_kzalloc(&pdev->dev, sizeof(struct omap_i2c_dev), GFP_KERNEL);
+	if (!dev) {
+		dev_err(&pdev->dev, "Menory allocation failed\n");
+		return -ENOMEM;
 	}
 
-	dev = kzalloc(sizeof(struct omap_i2c_dev), GFP_KERNEL);
-	if (!dev) {
-		r = -ENOMEM;
-		goto err_release_region;
+	dev->base = devm_request_and_ioremap(&pdev->dev, mem);
+	if (!dev->base) {
+		dev_err(&pdev->dev, "I2C region already claimed\n");
+		return -ENOMEM;
 	}
 
 	match = of_match_device(of_match_ptr(omap_i2c_of_match), &pdev->dev);
@@ -994,12 +1103,9 @@ omap_i2c_probe(struct platform_device *pdev)
 	}
 
 	dev->dev = &pdev->dev;
-	dev->irq = irq->start;
-	dev->base = ioremap(mem->start, resource_size(mem));
-	if (!dev->base) {
-		r = -ENOMEM;
-		goto err_free_mem;
-	}
+	dev->irq = irq;
+
+	spin_lock_init(&dev->lock);
 
 	platform_set_drvdata(pdev, dev);
 	init_completion(&dev->cmd_complete);
@@ -1012,6 +1118,9 @@ omap_i2c_probe(struct platform_device *pdev)
 		dev->regs = (u8 *)reg_map_ip_v1;
 
 	pm_runtime_enable(dev->dev);
+	pm_runtime_set_autosuspend_delay(dev->dev, OMAP_I2C_PM_TIMEOUT);
+	pm_runtime_use_autosuspend(dev->dev);
+
 	r = pm_runtime_get_sync(dev->dev);
 	if (IS_ERR_VALUE(r))
 		goto err_free_mem;
@@ -1041,9 +1150,7 @@ omap_i2c_probe(struct platform_device *pdev)
 
 		dev->fifo_size = (dev->fifo_size / 2);
 
-		if (dev->rev >= OMAP_I2C_REV_ON_3630_4430)
-			dev->b_hw = 0; /* Disable hardware fixes */
-		else
+		if (dev->rev < OMAP_I2C_REV_ON_3630_4430)
 			dev->b_hw = 1; /* Enable hardware fixes */
 
 		/* calculate wakeup latency constraint for MPU */
@@ -1055,18 +1162,20 @@ omap_i2c_probe(struct platform_device *pdev)
 	/* reset ASAP, clearing any IRQs */
 	omap_i2c_init(dev);
 
-	isr = (dev->rev < OMAP_I2C_OMAP1_REV_2) ? omap_i2c_omap1_isr :
-								   omap_i2c_isr;
-	r = request_irq(dev->irq, isr, IRQF_NO_SUSPEND, pdev->name, dev);
+	if (dev->rev < OMAP_I2C_OMAP1_REV_2)
+		r = devm_request_irq(&pdev->dev, dev->irq, omap_i2c_omap1_isr,
+				IRQF_NO_SUSPEND, pdev->name, dev);
+	else
+		r = devm_request_threaded_irq(&pdev->dev, dev->irq,
+				omap_i2c_isr, omap_i2c_isr_thread,
+				IRQF_NO_SUSPEND | IRQF_ONESHOT,
+				pdev->name, dev);
 
 	if (r) {
 		dev_err(dev->dev, "failure requesting irq %i\n", dev->irq);
 		goto err_unuse_clocks;
 	}
 
-	dev_info(dev->dev, "bus %d rev%d.%d.%d at %d kHz\n", pdev->id,
-		 dev->dtrev, dev->rev >> 4, dev->rev & 0xf, dev->speed);
-
 	adap = &dev->adapter;
 	i2c_set_adapdata(adap, dev);
 	adap->owner = THIS_MODULE;
@@ -1081,27 +1190,25 @@ omap_i2c_probe(struct platform_device *pdev)
 	r = i2c_add_numbered_adapter(adap);
 	if (r) {
 		dev_err(dev->dev, "failure adding adapter\n");
-		goto err_free_irq;
+		goto err_unuse_clocks;
 	}
 
+	dev_info(dev->dev, "bus %d rev%d.%d.%d at %d kHz\n", adap->nr,
+		 dev->dtrev, dev->rev >> 4, dev->rev & 0xf, dev->speed);
+
 	of_i2c_register_devices(adap);
 
-	pm_runtime_put(dev->dev);
+	pm_runtime_mark_last_busy(dev->dev);
+	pm_runtime_put_autosuspend(dev->dev);
 
 	return 0;
 
-err_free_irq:
-	free_irq(dev->irq, dev);
 err_unuse_clocks:
 	omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
 	pm_runtime_put(dev->dev);
-	iounmap(dev->base);
 	pm_runtime_disable(&pdev->dev);
 err_free_mem:
 	platform_set_drvdata(pdev, NULL);
-	kfree(dev);
-err_release_region:
-	release_mem_region(mem->start, resource_size(mem));
 
 	return r;
 }
@@ -1109,12 +1216,10 @@ err_release_region:
 static int __devexit omap_i2c_remove(struct platform_device *pdev)
 {
 	struct omap_i2c_dev	*dev = platform_get_drvdata(pdev);
-	struct resource		*mem;
 	int ret;
 
 	platform_set_drvdata(pdev, NULL);
 
-	free_irq(dev->irq, dev);
 	i2c_del_adapter(&dev->adapter);
 	ret = pm_runtime_get_sync(&pdev->dev);
 	if (IS_ERR_VALUE(ret))
@@ -1123,10 +1228,6 @@ static int __devexit omap_i2c_remove(struct platform_device *pdev)
 	omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
 	pm_runtime_put(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
-	iounmap(dev->base);
-	kfree(dev);
-	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	release_mem_region(mem->start, resource_size(mem));
 	return 0;
 }
 
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
index 5ae3b02..4d07dea 100644
--- a/drivers/i2c/busses/i2c-s3c2410.c
+++ b/drivers/i2c/busses/i2c-s3c2410.c
@@ -42,7 +42,7 @@
 #include <asm/irq.h>
 
 #include <plat/regs-iic.h>
-#include <plat/iic.h>
+#include <linux/platform_data/i2c-s3c2410.h>
 
 /* Treat S3C2410 as baseline hardware, anything else is supported via quirks */
 #define QUIRK_S3C2440		(1 << 0)
diff --git a/drivers/i2c/busses/i2c-scmi.c b/drivers/i2c/busses/i2c-scmi.c
index 388cbdc..6aafa3d 100644
--- a/drivers/i2c/busses/i2c-scmi.c
+++ b/drivers/i2c/busses/i2c-scmi.c
@@ -426,19 +426,7 @@ static struct acpi_driver acpi_smbus_cmi_driver = {
 		.remove = acpi_smbus_cmi_remove,
 	},
 };
-
-static int __init acpi_smbus_cmi_init(void)
-{
-	return acpi_bus_register_driver(&acpi_smbus_cmi_driver);
-}
-
-static void __exit acpi_smbus_cmi_exit(void)
-{
-	acpi_bus_unregister_driver(&acpi_smbus_cmi_driver);
-}
-
-module_init(acpi_smbus_cmi_init);
-module_exit(acpi_smbus_cmi_exit);
+module_acpi_driver(acpi_smbus_cmi_driver);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Crane Cai <crane.cai@amd.com>");
diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index 9a08c57..f981ac4 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -27,6 +27,7 @@
 #include <linux/slab.h>
 #include <linux/i2c-tegra.h>
 #include <linux/of_i2c.h>
+#include <linux/of_device.h>
 #include <linux/module.h>
 
 #include <asm/unaligned.h>
@@ -114,11 +115,21 @@ enum msg_end_type {
 };
 
 /**
+ * struct tegra_i2c_hw_feature : Different HW support on Tegra
+ * @has_continue_xfer_support: Continue transfer supports.
+ */
+
+struct tegra_i2c_hw_feature {
+	bool has_continue_xfer_support;
+};
+
+/**
  * struct tegra_i2c_dev	- per device i2c context
  * @dev: device reference for power management
+ * @hw: Tegra i2c hw feature.
  * @adapter: core i2c layer adapter information
- * @clk: clock reference for i2c controller
- * @i2c_clk: clock reference for i2c bus
+ * @div_clk: clock reference for div clock of i2c controller.
+ * @fast_clk: clock reference for fast clock of i2c controller.
  * @base: ioremapped registers cookie
  * @cont_id: i2c controller id, used for for packet header
  * @irq: irq number of transfer complete interrupt
@@ -133,9 +144,10 @@ enum msg_end_type {
  */
 struct tegra_i2c_dev {
 	struct device *dev;
+	const struct tegra_i2c_hw_feature *hw;
 	struct i2c_adapter adapter;
-	struct clk *clk;
-	struct clk *i2c_clk;
+	struct clk *div_clk;
+	struct clk *fast_clk;
 	void __iomem *base;
 	int cont_id;
 	int irq;
@@ -351,16 +363,40 @@ static void tegra_dvc_init(struct tegra_i2c_dev *i2c_dev)
 	dvc_writel(i2c_dev, val, DVC_CTRL_REG1);
 }
 
+static inline int tegra_i2c_clock_enable(struct tegra_i2c_dev *i2c_dev)
+{
+	int ret;
+	ret = clk_prepare_enable(i2c_dev->fast_clk);
+	if (ret < 0) {
+		dev_err(i2c_dev->dev,
+			"Enabling fast clk failed, err %d\n", ret);
+		return ret;
+	}
+	ret = clk_prepare_enable(i2c_dev->div_clk);
+	if (ret < 0) {
+		dev_err(i2c_dev->dev,
+			"Enabling div clk failed, err %d\n", ret);
+		clk_disable_unprepare(i2c_dev->fast_clk);
+	}
+	return ret;
+}
+
+static inline void tegra_i2c_clock_disable(struct tegra_i2c_dev *i2c_dev)
+{
+	clk_disable_unprepare(i2c_dev->div_clk);
+	clk_disable_unprepare(i2c_dev->fast_clk);
+}
+
 static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
 {
 	u32 val;
 	int err = 0;
 
-	clk_prepare_enable(i2c_dev->clk);
+	tegra_i2c_clock_enable(i2c_dev);
 
-	tegra_periph_reset_assert(i2c_dev->clk);
+	tegra_periph_reset_assert(i2c_dev->div_clk);
 	udelay(2);
-	tegra_periph_reset_deassert(i2c_dev->clk);
+	tegra_periph_reset_deassert(i2c_dev->div_clk);
 
 	if (i2c_dev->is_dvc)
 		tegra_dvc_init(i2c_dev);
@@ -369,7 +405,7 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
 		(0x2 << I2C_CNFG_DEBOUNCE_CNT_SHIFT);
 	i2c_writel(i2c_dev, val, I2C_CNFG);
 	i2c_writel(i2c_dev, 0, I2C_INT_MASK);
-	clk_set_rate(i2c_dev->clk, i2c_dev->bus_clk_rate * 8);
+	clk_set_rate(i2c_dev->div_clk, i2c_dev->bus_clk_rate * 8);
 
 	if (!i2c_dev->is_dvc) {
 		u32 sl_cfg = i2c_readl(i2c_dev, I2C_SL_CNFG);
@@ -387,7 +423,7 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
 	if (tegra_i2c_flush_fifos(i2c_dev))
 		err = -ETIMEDOUT;
 
-	clk_disable_unprepare(i2c_dev->clk);
+	tegra_i2c_clock_disable(i2c_dev);
 
 	if (i2c_dev->irq_disabled) {
 		i2c_dev->irq_disabled = 0;
@@ -563,7 +599,7 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
 	if (i2c_dev->is_suspended)
 		return -EBUSY;
 
-	clk_prepare_enable(i2c_dev->clk);
+	tegra_i2c_clock_enable(i2c_dev);
 	for (i = 0; i < num; i++) {
 		enum msg_end_type end_type = MSG_END_STOP;
 		if (i < (num - 1)) {
@@ -576,14 +612,19 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
 		if (ret)
 			break;
 	}
-	clk_disable_unprepare(i2c_dev->clk);
+	tegra_i2c_clock_disable(i2c_dev);
 	return ret ?: i;
 }
 
 static u32 tegra_i2c_func(struct i2c_adapter *adap)
 {
-	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR |
-		I2C_FUNC_PROTOCOL_MANGLING | I2C_FUNC_NOSTART;
+	struct tegra_i2c_dev *i2c_dev = i2c_get_adapdata(adap);
+	u32 ret = I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR |
+				I2C_FUNC_PROTOCOL_MANGLING;
+
+	if (i2c_dev->hw->has_continue_xfer_support)
+		ret |= I2C_FUNC_NOSTART;
+	return ret;
 }
 
 static const struct i2c_algorithm tegra_i2c_algo = {
@@ -591,13 +632,32 @@ static const struct i2c_algorithm tegra_i2c_algo = {
 	.functionality	= tegra_i2c_func,
 };
 
+static const struct tegra_i2c_hw_feature tegra20_i2c_hw = {
+	.has_continue_xfer_support = false,
+};
+
+static const struct tegra_i2c_hw_feature tegra30_i2c_hw = {
+	.has_continue_xfer_support = true,
+};
+
+#if defined(CONFIG_OF)
+/* Match table for of_platform binding */
+static const struct of_device_id tegra_i2c_of_match[] __devinitconst = {
+	{ .compatible = "nvidia,tegra30-i2c", .data = &tegra30_i2c_hw, },
+	{ .compatible = "nvidia,tegra20-i2c", .data = &tegra20_i2c_hw, },
+	{ .compatible = "nvidia,tegra20-i2c-dvc", .data = &tegra20_i2c_hw, },
+	{},
+};
+MODULE_DEVICE_TABLE(of, tegra_i2c_of_match);
+#endif
+
 static int __devinit tegra_i2c_probe(struct platform_device *pdev)
 {
 	struct tegra_i2c_dev *i2c_dev;
 	struct tegra_i2c_platform_data *pdata = pdev->dev.platform_data;
 	struct resource *res;
-	struct clk *clk;
-	struct clk *i2c_clk;
+	struct clk *div_clk;
+	struct clk *fast_clk;
 	const unsigned int *prop;
 	void __iomem *base;
 	int irq;
@@ -622,16 +682,16 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev)
 	}
 	irq = res->start;
 
-	clk = devm_clk_get(&pdev->dev, NULL);
-	if (IS_ERR(clk)) {
+	div_clk = devm_clk_get(&pdev->dev, "div-clk");
+	if (IS_ERR(div_clk)) {
 		dev_err(&pdev->dev, "missing controller clock");
-		return PTR_ERR(clk);
+		return PTR_ERR(div_clk);
 	}
 
-	i2c_clk = devm_clk_get(&pdev->dev, "i2c");
-	if (IS_ERR(i2c_clk)) {
+	fast_clk = devm_clk_get(&pdev->dev, "fast-clk");
+	if (IS_ERR(fast_clk)) {
 		dev_err(&pdev->dev, "missing bus clock");
-		return PTR_ERR(i2c_clk);
+		return PTR_ERR(fast_clk);
 	}
 
 	i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL);
@@ -641,8 +701,8 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev)
 	}
 
 	i2c_dev->base = base;
-	i2c_dev->clk = clk;
-	i2c_dev->i2c_clk = i2c_clk;
+	i2c_dev->div_clk = div_clk;
+	i2c_dev->fast_clk = fast_clk;
 	i2c_dev->adapter.algo = &tegra_i2c_algo;
 	i2c_dev->irq = irq;
 	i2c_dev->cont_id = pdev->id;
@@ -659,11 +719,18 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev)
 			i2c_dev->bus_clk_rate = be32_to_cpup(prop);
 	}
 
-	if (pdev->dev.of_node)
+	i2c_dev->hw = &tegra20_i2c_hw;
+
+	if (pdev->dev.of_node) {
+		const struct of_device_id *match;
+		match = of_match_device(of_match_ptr(tegra_i2c_of_match),
+						&pdev->dev);
+		i2c_dev->hw = match->data;
 		i2c_dev->is_dvc = of_device_is_compatible(pdev->dev.of_node,
 						"nvidia,tegra20-i2c-dvc");
-	else if (pdev->id == 3)
+	} else if (pdev->id == 3) {
 		i2c_dev->is_dvc = 1;
+	}
 	init_completion(&i2c_dev->msg_complete);
 
 	platform_set_drvdata(pdev, i2c_dev);
@@ -681,8 +748,6 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev)
 		return ret;
 	}
 
-	clk_prepare_enable(i2c_dev->i2c_clk);
-
 	i2c_set_adapdata(&i2c_dev->adapter, i2c_dev);
 	i2c_dev->adapter.owner = THIS_MODULE;
 	i2c_dev->adapter.class = I2C_CLASS_HWMON;
@@ -696,7 +761,6 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev)
 	ret = i2c_add_numbered_adapter(&i2c_dev->adapter);
 	if (ret) {
 		dev_err(&pdev->dev, "Failed to add I2C adapter\n");
-		clk_disable_unprepare(i2c_dev->i2c_clk);
 		return ret;
 	}
 
@@ -751,16 +815,6 @@ static SIMPLE_DEV_PM_OPS(tegra_i2c_pm, tegra_i2c_suspend, tegra_i2c_resume);
 #define TEGRA_I2C_PM	NULL
 #endif
 
-#if defined(CONFIG_OF)
-/* Match table for of_platform binding */
-static const struct of_device_id tegra_i2c_of_match[] __devinitconst = {
-	{ .compatible = "nvidia,tegra20-i2c", },
-	{ .compatible = "nvidia,tegra20-i2c-dvc", },
-	{},
-};
-MODULE_DEVICE_TABLE(of, tegra_i2c_of_match);
-#endif
-
 static struct platform_driver tegra_i2c_driver = {
 	.probe   = tegra_i2c_probe,
 	.remove  = __devexit_p(tegra_i2c_remove),
diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c
index 2eacb77..08aab57 100644
--- a/drivers/i2c/busses/scx200_acb.c
+++ b/drivers/i2c/busses/scx200_acb.c
@@ -23,6 +23,8 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
@@ -37,8 +39,6 @@
 
 #include <linux/scx200.h>
 
-#define NAME "scx200_acb"
-
 MODULE_AUTHOR("Christer Weinigel <wingel@nano-system.com>");
 MODULE_DESCRIPTION("NatSemi SCx200 ACCESS.bus Driver");
 MODULE_ALIAS("platform:cs5535-smb");
@@ -398,7 +398,7 @@ static __devinit int scx200_acb_probe(struct scx200_acb_iface *iface)
 	outb(0x70, ACBCTL2);
 
 	if (inb(ACBCTL2) != 0x70) {
-		pr_debug(NAME ": ACBCTL2 readback failed\n");
+		pr_debug("ACBCTL2 readback failed\n");
 		return -ENXIO;
 	}
 
@@ -406,8 +406,7 @@ static __devinit int scx200_acb_probe(struct scx200_acb_iface *iface)
 
 	val = inb(ACBCTL1);
 	if (val) {
-		pr_debug(NAME ": disabled, but ACBCTL1=0x%02x\n",
-			val);
+		pr_debug("disabled, but ACBCTL1=0x%02x\n", val);
 		return -ENXIO;
 	}
 
@@ -417,8 +416,8 @@ static __devinit int scx200_acb_probe(struct scx200_acb_iface *iface)
 
 	val = inb(ACBCTL1);
 	if ((val & ACBCTL1_NMINTE) != ACBCTL1_NMINTE) {
-		pr_debug(NAME ": enabled, but NMINTE won't be set, "
-			 "ACBCTL1=0x%02x\n", val);
+		pr_debug("enabled, but NMINTE won't be set, ACBCTL1=0x%02x\n",
+			 val);
 		return -ENXIO;
 	}
 
@@ -433,7 +432,7 @@ static __devinit struct scx200_acb_iface *scx200_create_iface(const char *text,
 
 	iface = kzalloc(sizeof(*iface), GFP_KERNEL);
 	if (!iface) {
-		printk(KERN_ERR NAME ": can't allocate memory\n");
+		pr_err("can't allocate memory\n");
 		return NULL;
 	}
 
@@ -459,14 +458,14 @@ static int __devinit scx200_acb_create(struct scx200_acb_iface *iface)
 
 	rc = scx200_acb_probe(iface);
 	if (rc) {
-		printk(KERN_WARNING NAME ": probe failed\n");
+		pr_warn("probe failed\n");
 		return rc;
 	}
 
 	scx200_acb_reset(iface);
 
 	if (i2c_add_adapter(adapter) < 0) {
-		printk(KERN_ERR NAME ": failed to register\n");
+		pr_err("failed to register\n");
 		return -ENODEV;
 	}
 
@@ -493,8 +492,7 @@ static struct scx200_acb_iface * __devinit scx200_create_dev(const char *text,
 		return NULL;
 
 	if (!request_region(base, 8, iface->adapter.name)) {
-		printk(KERN_ERR NAME ": can't allocate io 0x%lx-0x%lx\n",
-		       base, base + 8 - 1);
+		pr_err("can't allocate io 0x%lx-0x%lx\n", base, base + 8 - 1);
 		goto errout_free;
 	}
 
@@ -583,7 +581,7 @@ static __init void scx200_scan_isa(void)
 
 static int __init scx200_acb_init(void)
 {
-	pr_debug(NAME ": NatSemi SCx200 ACCESS.bus Driver\n");
+	pr_debug("NatSemi SCx200 ACCESS.bus Driver\n");
 
 	/* First scan for ISA-based devices */
 	scx200_scan_isa();	/* XXX: should we care about errors? */
diff --git a/drivers/i2c/busses/scx200_i2c.c b/drivers/i2c/busses/scx200_i2c.c
index 7ee0d50..ae1258b 100644
--- a/drivers/i2c/busses/scx200_i2c.c
+++ b/drivers/i2c/busses/scx200_i2c.c
@@ -21,6 +21,8 @@
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.		     
 */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
@@ -31,8 +33,6 @@
 
 #include <linux/scx200_gpio.h>
 
-#define NAME "scx200_i2c"
-
 MODULE_AUTHOR("Christer Weinigel <wingel@nano-system.com>");
 MODULE_DESCRIPTION("NatSemi SCx200 I2C Driver");
 MODULE_LICENSE("GPL");
@@ -88,17 +88,17 @@ static struct i2c_adapter scx200_i2c_ops = {
 
 static int scx200_i2c_init(void)
 {
-	pr_debug(NAME ": NatSemi SCx200 I2C Driver\n");
+	pr_debug("NatSemi SCx200 I2C Driver\n");
 
 	if (!scx200_gpio_present()) {
-		printk(KERN_ERR NAME ": no SCx200 gpio pins available\n");
+		pr_err("no SCx200 gpio pins available\n");
 		return -ENODEV;
 	}
 
-	pr_debug(NAME ": SCL=GPIO%02u, SDA=GPIO%02u\n", scl, sda);
+	pr_debug("SCL=GPIO%02u, SDA=GPIO%02u\n", scl, sda);
 
 	if (scl == -1 || sda == -1 || scl == sda) {
-		printk(KERN_ERR NAME ": scl and sda must be specified\n");
+		pr_err("scl and sda must be specified\n");
 		return -EINVAL;
 	}
 
@@ -107,8 +107,7 @@ static int scx200_i2c_init(void)
 	scx200_gpio_configure(sda, ~2, 5);
 
 	if (i2c_bit_add_bus(&scx200_i2c_ops) < 0) {
-		printk(KERN_ERR NAME ": adapter %s registration failed\n", 
-		       scx200_i2c_ops.name);
+		pr_err("adapter %s registration failed\n", scx200_i2c_ops.name);
 		return -ENODEV;
 	}
 	
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 2091ae8..a7edf98 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -982,7 +982,7 @@ int i2c_add_numbered_adapter(struct i2c_adapter *adap)
 
 	if (adap->nr == -1) /* -1 means dynamically assign bus id */
 		return i2c_add_adapter(adap);
-	if (adap->nr & ~MAX_ID_MASK)
+	if (adap->nr & ~MAX_IDR_MASK)
 		return -EINVAL;
 
 retry:
@@ -1989,12 +1989,22 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr,
 	unsigned char msgbuf0[I2C_SMBUS_BLOCK_MAX+3];
 	unsigned char msgbuf1[I2C_SMBUS_BLOCK_MAX+2];
 	int num = read_write == I2C_SMBUS_READ ? 2 : 1;
-	struct i2c_msg msg[2] = { { addr, flags, 1, msgbuf0 },
-	                          { addr, flags | I2C_M_RD, 0, msgbuf1 }
-	                        };
 	int i;
 	u8 partial_pec = 0;
 	int status;
+	struct i2c_msg msg[2] = {
+		{
+			.addr = addr,
+			.flags = flags,
+			.len = 1,
+			.buf = msgbuf0,
+		}, {
+			.addr = addr,
+			.flags = flags | I2C_M_RD,
+			.len = 0,
+			.buf = msgbuf1,
+		},
+	};
 
 	msgbuf0[0] = command;
 	switch (size) {
diff --git a/drivers/i2c/i2c-mux.c b/drivers/i2c/i2c-mux.c
index 1038c38..d94e0ce 100644
--- a/drivers/i2c/i2c-mux.c
+++ b/drivers/i2c/i2c-mux.c
@@ -88,9 +88,23 @@ static u32 i2c_mux_functionality(struct i2c_adapter *adap)
 	return parent->algo->functionality(parent);
 }
 
+/* Return all parent classes, merged */
+static unsigned int i2c_mux_parent_classes(struct i2c_adapter *parent)
+{
+	unsigned int class = 0;
+
+	do {
+		class |= parent->class;
+		parent = i2c_parent_is_i2c_adapter(parent);
+	} while (parent);
+
+	return class;
+}
+
 struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent,
 				struct device *mux_dev,
 				void *mux_priv, u32 force_nr, u32 chan_id,
+				unsigned int class,
 				int (*select) (struct i2c_adapter *,
 					       void *, u32),
 				int (*deselect) (struct i2c_adapter *,
@@ -127,6 +141,14 @@ struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent,
 	priv->adap.algo_data = priv;
 	priv->adap.dev.parent = &parent->dev;
 
+	/* Sanity check on class */
+	if (i2c_mux_parent_classes(parent) & class)
+		dev_err(&parent->dev,
+			"Segment %d behind mux can't share classes with ancestors\n",
+			chan_id);
+	else
+		priv->adap.class = class;
+
 	/*
 	 * Try to populate the mux adapter's of_node, expands to
 	 * nothing if !CONFIG_OF.
diff --git a/drivers/i2c/i2c-smbus.c b/drivers/i2c/i2c-smbus.c
index df3e0bf..92cdd23 100644
--- a/drivers/i2c/i2c-smbus.c
+++ b/drivers/i2c/i2c-smbus.c
@@ -142,7 +142,8 @@ static int smbalert_probe(struct i2c_client *ara,
 	struct i2c_adapter *adapter = ara->adapter;
 	int res;
 
-	alert = kzalloc(sizeof(struct i2c_smbus_alert), GFP_KERNEL);
+	alert = devm_kzalloc(&ara->dev, sizeof(struct i2c_smbus_alert),
+			     GFP_KERNEL);
 	if (!alert)
 		return -ENOMEM;
 
@@ -154,10 +155,8 @@ static int smbalert_probe(struct i2c_client *ara,
 	if (setup->irq > 0) {
 		res = devm_request_irq(&ara->dev, setup->irq, smbalert_irq,
 				       0, "smbus_alert", alert);
-		if (res) {
-			kfree(alert);
+		if (res)
 			return res;
-		}
 	}
 
 	i2c_set_clientdata(ara, alert);
@@ -167,14 +166,12 @@ static int smbalert_probe(struct i2c_client *ara,
 	return 0;
 }
 
-/* IRQ resource is managed so it is freed automatically */
+/* IRQ and memory resources are managed so they are freed automatically */
 static int smbalert_remove(struct i2c_client *ara)
 {
 	struct i2c_smbus_alert *alert = i2c_get_clientdata(ara);
 
 	cancel_work_sync(&alert->alert);
-
-	kfree(alert);
 	return 0;
 }
 
diff --git a/drivers/i2c/muxes/i2c-mux-gpio.c b/drivers/i2c/muxes/i2c-mux-gpio.c
index 68b1f8e..56889e0 100644
--- a/drivers/i2c/muxes/i2c-mux-gpio.c
+++ b/drivers/i2c/muxes/i2c-mux-gpio.c
@@ -104,8 +104,10 @@ static int __devinit i2c_mux_gpio_probe(struct platform_device *pdev)
 
 	for (i = 0; i < pdata->n_values; i++) {
 		u32 nr = pdata->base_nr ? (pdata->base_nr + i) : 0;
+		unsigned int class = pdata->classes ? pdata->classes[i] : 0;
 
-		mux->adap[i] = i2c_add_mux_adapter(parent, &pdev->dev, mux, nr, i,
+		mux->adap[i] = i2c_add_mux_adapter(parent, &pdev->dev, mux, nr,
+						   i, class,
 						   i2c_mux_gpio_select, deselect);
 		if (!mux->adap[i]) {
 			ret = -ENODEV;
diff --git a/drivers/i2c/muxes/i2c-mux-pca9541.c b/drivers/i2c/muxes/i2c-mux-pca9541.c
index f8f72f3..f3b8f9a 100644
--- a/drivers/i2c/muxes/i2c-mux-pca9541.c
+++ b/drivers/i2c/muxes/i2c-mux-pca9541.c
@@ -354,7 +354,7 @@ static int pca9541_probe(struct i2c_client *client,
 	if (pdata)
 		force = pdata->modes[0].adap_id;
 	data->mux_adap = i2c_add_mux_adapter(adap, &client->dev, client,
-					     force, 0,
+					     force, 0, 0,
 					     pca9541_select_chan,
 					     pca9541_release_chan);
 
diff --git a/drivers/i2c/muxes/i2c-mux-pca954x.c b/drivers/i2c/muxes/i2c-mux-pca954x.c
index f2dfe0d..8e43872 100644
--- a/drivers/i2c/muxes/i2c-mux-pca954x.c
+++ b/drivers/i2c/muxes/i2c-mux-pca954x.c
@@ -186,7 +186,7 @@ static int pca954x_probe(struct i2c_client *client,
 {
 	struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent);
 	struct pca954x_platform_data *pdata = client->dev.platform_data;
-	int num, force;
+	int num, force, class;
 	struct pca954x *data;
 	int ret = -ENODEV;
 
@@ -216,18 +216,20 @@ static int pca954x_probe(struct i2c_client *client,
 	/* Now create an adapter for each channel */
 	for (num = 0; num < chips[data->type].nchans; num++) {
 		force = 0;			  /* dynamic adap number */
+		class = 0;			  /* no class by default */
 		if (pdata) {
-			if (num < pdata->num_modes)
+			if (num < pdata->num_modes) {
 				/* force static number */
 				force = pdata->modes[num].adap_id;
-			else
+				class = pdata->modes[num].class;
+			} else
 				/* discard unconfigured channels */
 				break;
 		}
 
 		data->virt_adaps[num] =
 			i2c_add_mux_adapter(adap, &client->dev, client,
-				force, num, pca954x_select_chan,
+				force, num, class, pca954x_select_chan,
 				(pdata && pdata->modes[num].deselect_on_exit)
 					? pca954x_deselect_mux : NULL);
 
diff --git a/drivers/i2c/muxes/i2c-mux-pinctrl.c b/drivers/i2c/muxes/i2c-mux-pinctrl.c
index 46a6697..5f097f3 100644
--- a/drivers/i2c/muxes/i2c-mux-pinctrl.c
+++ b/drivers/i2c/muxes/i2c-mux-pinctrl.c
@@ -221,7 +221,7 @@ static int __devinit i2c_mux_pinctrl_probe(struct platform_device *pdev)
 				(mux->pdata->base_bus_num + i) : 0;
 
 		mux->busses[i] = i2c_add_mux_adapter(mux->parent, &pdev->dev,
-						     mux, bus, i,
+						     mux, bus, i, 0,
 						     i2c_mux_pinctrl_select,
 						     deselect);
 		if (!mux->busses[i]) {
diff --git a/drivers/ide/aec62xx.c b/drivers/ide/aec62xx.c
index 57d00ca..0145194 100644
--- a/drivers/ide/aec62xx.c
+++ b/drivers/ide/aec62xx.c
@@ -181,7 +181,7 @@ static const struct ide_port_ops atp86x_port_ops = {
 	.cable_detect		= atp86x_cable_detect,
 };
 
-static const struct ide_port_info aec62xx_chipsets[] __devinitdata = {
+static const struct ide_port_info aec62xx_chipsets[] __devinitconst = {
 	{	/* 0: AEC6210 */
 		.name		= DRV_NAME,
 		.init_chipset	= init_chipset_aec62xx,
diff --git a/drivers/ide/ali14xx.c b/drivers/ide/ali14xx.c
index d3be99f..8f3570e 100644
--- a/drivers/ide/ali14xx.c
+++ b/drivers/ide/ali14xx.c
@@ -52,13 +52,13 @@
 
 /* port addresses for auto-detection */
 #define ALI_NUM_PORTS 4
-static const int ports[ALI_NUM_PORTS] __initdata =
+static const int ports[ALI_NUM_PORTS] __initconst =
 	{ 0x074, 0x0f4, 0x034, 0x0e4 };
 
 /* register initialization data */
 typedef struct { u8 reg, data; } RegInitializer;
 
-static const RegInitializer initData[] __initdata = {
+static const RegInitializer initData[] __initconst = {
 	{0x01, 0x0f}, {0x02, 0x00}, {0x03, 0x00}, {0x04, 0x00},
 	{0x05, 0x00}, {0x06, 0x00}, {0x07, 0x2b}, {0x0a, 0x0f},
 	{0x25, 0x00}, {0x26, 0x00}, {0x27, 0x00}, {0x28, 0x00},
diff --git a/drivers/ide/alim15x3.c b/drivers/ide/alim15x3.c
index 2c8016a..911a27c 100644
--- a/drivers/ide/alim15x3.c
+++ b/drivers/ide/alim15x3.c
@@ -512,7 +512,7 @@ static const struct ide_dma_ops ali_dma_ops = {
 	.dma_sff_read_status	= ide_dma_sff_read_status,
 };
 
-static const struct ide_port_info ali15x3_chipset __devinitdata = {
+static const struct ide_port_info ali15x3_chipset __devinitconst = {
 	.name		= DRV_NAME,
 	.init_chipset	= init_chipset_ali15x3,
 	.init_hwif	= init_hwif_ali15x3,
diff --git a/drivers/ide/amd74xx.c b/drivers/ide/amd74xx.c
index 3747b25..56fc995 100644
--- a/drivers/ide/amd74xx.c
+++ b/drivers/ide/amd74xx.c
@@ -223,7 +223,7 @@ static const struct ide_port_ops amd_port_ops = {
 		.udma_mask	= udma,					\
 	}
 
-static const struct ide_port_info amd74xx_chipsets[] __devinitdata = {
+static const struct ide_port_info amd74xx_chipsets[] __devinitconst = {
 	/* 0: AMD7401 */	DECLARE_AMD_DEV(0x00, ATA_UDMA2),
 	/* 1: AMD7409 */	DECLARE_AMD_DEV(ATA_SWDMA2, ATA_UDMA4),
 	/* 2: AMD7411/7441 */	DECLARE_AMD_DEV(ATA_SWDMA2, ATA_UDMA5),
diff --git a/drivers/ide/atiixp.c b/drivers/ide/atiixp.c
index 15f0ead..cb43480 100644
--- a/drivers/ide/atiixp.c
+++ b/drivers/ide/atiixp.c
@@ -139,7 +139,7 @@ static const struct ide_port_ops atiixp_port_ops = {
 	.cable_detect		= atiixp_cable_detect,
 };
 
-static const struct ide_port_info atiixp_pci_info[] __devinitdata = {
+static const struct ide_port_info atiixp_pci_info[] __devinitconst = {
 	{	/* 0: IXP200/300/400/700 */
 		.name		= DRV_NAME,
 		.enablebits	= {{0x48,0x01,0x00}, {0x48,0x08,0x00}},
diff --git a/drivers/ide/cmd640.c b/drivers/ide/cmd640.c
index 1471730..70f0a27 100644
--- a/drivers/ide/cmd640.c
+++ b/drivers/ide/cmd640.c
@@ -685,7 +685,7 @@ static int pci_conf2(void)
 	return 0;
 }
 
-static const struct ide_port_info cmd640_port_info __initdata = {
+static const struct ide_port_info cmd640_port_info __initconst = {
 	.chipset		= ide_cmd640,
 	.host_flags		= IDE_HFLAG_SERIALIZE |
 				  IDE_HFLAG_NO_DMA |
diff --git a/drivers/ide/cmd64x.c b/drivers/ide/cmd64x.c
index 5f80312..d1fc438 100644
--- a/drivers/ide/cmd64x.c
+++ b/drivers/ide/cmd64x.c
@@ -327,7 +327,7 @@ static const struct ide_dma_ops cmd646_rev1_dma_ops = {
 	.dma_sff_read_status	= ide_dma_sff_read_status,
 };
 
-static const struct ide_port_info cmd64x_chipsets[] __devinitdata = {
+static const struct ide_port_info cmd64x_chipsets[] __devinitconst = {
 	{	/* 0: CMD643 */
 		.name		= DRV_NAME,
 		.init_chipset	= init_chipset_cmd64x,
diff --git a/drivers/ide/cs5520.c b/drivers/ide/cs5520.c
index 2c1e5f7..1444762 100644
--- a/drivers/ide/cs5520.c
+++ b/drivers/ide/cs5520.c
@@ -94,7 +94,7 @@ static const struct ide_port_ops cs5520_port_ops = {
 	.set_dma_mode		= cs5520_set_dma_mode,
 };
 
-static const struct ide_port_info cyrix_chipset __devinitdata = {
+static const struct ide_port_info cyrix_chipset __devinitconst = {
 	.name		= DRV_NAME,
 	.enablebits	= { { 0x60, 0x01, 0x01 }, { 0x60, 0x02, 0x02 } },
 	.port_ops	= &cs5520_port_ops,
diff --git a/drivers/ide/cs5530.c b/drivers/ide/cs5530.c
index 4dc4eb9..49b40ad 100644
--- a/drivers/ide/cs5530.c
+++ b/drivers/ide/cs5530.c
@@ -245,7 +245,7 @@ static const struct ide_port_ops cs5530_port_ops = {
 	.udma_filter		= cs5530_udma_filter,
 };
 
-static const struct ide_port_info cs5530_chipset __devinitdata = {
+static const struct ide_port_info cs5530_chipset __devinitconst = {
 	.name		= DRV_NAME,
 	.init_chipset	= init_chipset_cs5530,
 	.init_hwif	= init_hwif_cs5530,
diff --git a/drivers/ide/cs5535.c b/drivers/ide/cs5535.c
index 5059faf..18d4c85 100644
--- a/drivers/ide/cs5535.c
+++ b/drivers/ide/cs5535.c
@@ -170,7 +170,7 @@ static const struct ide_port_ops cs5535_port_ops = {
 	.cable_detect		= cs5535_cable_detect,
 };
 
-static const struct ide_port_info cs5535_chipset __devinitdata = {
+static const struct ide_port_info cs5535_chipset __devinitconst = {
 	.name		= DRV_NAME,
 	.port_ops	= &cs5535_port_ops,
 	.host_flags	= IDE_HFLAG_SINGLE | IDE_HFLAG_POST_SET_MODE,
diff --git a/drivers/ide/cy82c693.c b/drivers/ide/cy82c693.c
index 847553f..3ffb49d 100644
--- a/drivers/ide/cy82c693.c
+++ b/drivers/ide/cy82c693.c
@@ -163,7 +163,7 @@ static const struct ide_port_ops cy82c693_port_ops = {
 	.set_dma_mode		= cy82c693_set_dma_mode,
 };
 
-static const struct ide_port_info cy82c693_chipset __devinitdata = {
+static const struct ide_port_info cy82c693_chipset __devinitconst = {
 	.name		= DRV_NAME,
 	.init_iops	= init_iops_cy82c693,
 	.port_ops	= &cy82c693_port_ops,
diff --git a/drivers/ide/dtc2278.c b/drivers/ide/dtc2278.c
index 46af474..8722df3 100644
--- a/drivers/ide/dtc2278.c
+++ b/drivers/ide/dtc2278.c
@@ -91,7 +91,7 @@ static const struct ide_port_ops dtc2278_port_ops = {
 	.set_pio_mode		= dtc2278_set_pio_mode,
 };
 
-static const struct ide_port_info dtc2278_port_info __initdata = {
+static const struct ide_port_info dtc2278_port_info __initconst = {
 	.name			= DRV_NAME,
 	.chipset		= ide_dtc2278,
 	.port_ops		= &dtc2278_port_ops,
diff --git a/drivers/ide/hpt366.c b/drivers/ide/hpt366.c
index 58c51cd..4aec3b8 100644
--- a/drivers/ide/hpt366.c
+++ b/drivers/ide/hpt366.c
@@ -443,7 +443,7 @@ static struct hpt_timings hpt37x_timings = {
 	}
 };
 
-static const struct hpt_info hpt36x __devinitdata = {
+static const struct hpt_info hpt36x __devinitconst = {
 	.chip_name	= "HPT36x",
 	.chip_type	= HPT36x,
 	.udma_mask	= HPT366_ALLOW_ATA66_3 ? (HPT366_ALLOW_ATA66_4 ? ATA_UDMA4 : ATA_UDMA3) : ATA_UDMA2,
@@ -451,7 +451,7 @@ static const struct hpt_info hpt36x __devinitdata = {
 	.timings	= &hpt36x_timings
 };
 
-static const struct hpt_info hpt370 __devinitdata = {
+static const struct hpt_info hpt370 __devinitconst = {
 	.chip_name	= "HPT370",
 	.chip_type	= HPT370,
 	.udma_mask	= HPT370_ALLOW_ATA100_5 ? ATA_UDMA5 : ATA_UDMA4,
@@ -459,7 +459,7 @@ static const struct hpt_info hpt370 __devinitdata = {
 	.timings	= &hpt37x_timings
 };
 
-static const struct hpt_info hpt370a __devinitdata = {
+static const struct hpt_info hpt370a __devinitconst = {
 	.chip_name	= "HPT370A",
 	.chip_type	= HPT370A,
 	.udma_mask	= HPT370_ALLOW_ATA100_5 ? ATA_UDMA5 : ATA_UDMA4,
@@ -467,7 +467,7 @@ static const struct hpt_info hpt370a __devinitdata = {
 	.timings	= &hpt37x_timings
 };
 
-static const struct hpt_info hpt374 __devinitdata = {
+static const struct hpt_info hpt374 __devinitconst = {
 	.chip_name	= "HPT374",
 	.chip_type	= HPT374,
 	.udma_mask	= ATA_UDMA5,
@@ -475,7 +475,7 @@ static const struct hpt_info hpt374 __devinitdata = {
 	.timings	= &hpt37x_timings
 };
 
-static const struct hpt_info hpt372 __devinitdata = {
+static const struct hpt_info hpt372 __devinitconst = {
 	.chip_name	= "HPT372",
 	.chip_type	= HPT372,
 	.udma_mask	= HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
@@ -483,7 +483,7 @@ static const struct hpt_info hpt372 __devinitdata = {
 	.timings	= &hpt37x_timings
 };
 
-static const struct hpt_info hpt372a __devinitdata = {
+static const struct hpt_info hpt372a __devinitconst = {
 	.chip_name	= "HPT372A",
 	.chip_type	= HPT372A,
 	.udma_mask	= HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
@@ -491,7 +491,7 @@ static const struct hpt_info hpt372a __devinitdata = {
 	.timings	= &hpt37x_timings
 };
 
-static const struct hpt_info hpt302 __devinitdata = {
+static const struct hpt_info hpt302 __devinitconst = {
 	.chip_name	= "HPT302",
 	.chip_type	= HPT302,
 	.udma_mask	= HPT302_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
@@ -499,7 +499,7 @@ static const struct hpt_info hpt302 __devinitdata = {
 	.timings	= &hpt37x_timings
 };
 
-static const struct hpt_info hpt371 __devinitdata = {
+static const struct hpt_info hpt371 __devinitconst = {
 	.chip_name	= "HPT371",
 	.chip_type	= HPT371,
 	.udma_mask	= HPT371_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
@@ -507,7 +507,7 @@ static const struct hpt_info hpt371 __devinitdata = {
 	.timings	= &hpt37x_timings
 };
 
-static const struct hpt_info hpt372n __devinitdata = {
+static const struct hpt_info hpt372n __devinitconst = {
 	.chip_name	= "HPT372N",
 	.chip_type	= HPT372N,
 	.udma_mask	= HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
@@ -515,7 +515,7 @@ static const struct hpt_info hpt372n __devinitdata = {
 	.timings	= &hpt37x_timings
 };
 
-static const struct hpt_info hpt302n __devinitdata = {
+static const struct hpt_info hpt302n __devinitconst = {
 	.chip_name	= "HPT302N",
 	.chip_type	= HPT302N,
 	.udma_mask	= HPT302_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
@@ -523,7 +523,7 @@ static const struct hpt_info hpt302n __devinitdata = {
 	.timings	= &hpt37x_timings
 };
 
-static const struct hpt_info hpt371n __devinitdata = {
+static const struct hpt_info hpt371n __devinitconst = {
 	.chip_name	= "HPT371N",
 	.chip_type	= HPT371N,
 	.udma_mask	= HPT371_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
@@ -1361,7 +1361,7 @@ static const struct ide_dma_ops hpt36x_dma_ops = {
 	.dma_sff_read_status	= ide_dma_sff_read_status,
 };
 
-static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
+static const struct ide_port_info hpt366_chipsets[] __devinitconst = {
 	{	/* 0: HPT36x */
 		.name		= DRV_NAME,
 		.init_chipset	= init_chipset_hpt366,
diff --git a/drivers/ide/ht6560b.c b/drivers/ide/ht6560b.c
index 986f251..1e0fd3a 100644
--- a/drivers/ide/ht6560b.c
+++ b/drivers/ide/ht6560b.c
@@ -341,7 +341,7 @@ static const struct ide_port_ops ht6560b_port_ops = {
 	.set_pio_mode		= ht6560b_set_pio_mode,
 };
 
-static const struct ide_port_info ht6560b_port_info __initdata = {
+static const struct ide_port_info ht6560b_port_info __initconst = {
 	.name			= DRV_NAME,
 	.chipset		= ide_ht6560b,
 	.tp_ops 		= &ht6560b_tp_ops,
diff --git a/drivers/ide/icside.c b/drivers/ide/icside.c
index bcb507b..e640d0a 100644
--- a/drivers/ide/icside.c
+++ b/drivers/ide/icside.c
@@ -451,7 +451,7 @@ err_free:
 	return ret;
 }
 
-static const struct ide_port_info icside_v6_port_info __initdata = {
+static const struct ide_port_info icside_v6_port_info __initconst = {
 	.init_dma		= icside_dma_off_init,
 	.port_ops		= &icside_v6_no_dma_port_ops,
 	.host_flags		= IDE_HFLAG_SERIALIZE | IDE_HFLAG_MMIO,
diff --git a/drivers/ide/ide-pci-generic.c b/drivers/ide/ide-pci-generic.c
index 7f56b73..dab5b67 100644
--- a/drivers/ide/ide-pci-generic.c
+++ b/drivers/ide/ide-pci-generic.c
@@ -53,7 +53,7 @@ static const struct ide_port_ops netcell_port_ops = {
 		.udma_mask	= ATA_UDMA6, \
 	}
 
-static const struct ide_port_info generic_chipsets[] __devinitdata = {
+static const struct ide_port_info generic_chipsets[] __devinitconst = {
 	/*  0: Unknown */
 	DECLARE_GENERIC_PCI_DEV(0),
 
diff --git a/drivers/ide/it8172.c b/drivers/ide/it8172.c
index 560e66d..d5dd180 100644
--- a/drivers/ide/it8172.c
+++ b/drivers/ide/it8172.c
@@ -115,7 +115,7 @@ static const struct ide_port_ops it8172_port_ops = {
 	.set_dma_mode	= it8172_set_dma_mode,
 };
 
-static const struct ide_port_info it8172_port_info __devinitdata = {
+static const struct ide_port_info it8172_port_info __devinitconst = {
 	.name		= DRV_NAME,
 	.port_ops	= &it8172_port_ops,
 	.enablebits	= { {0x41, 0x80, 0x80}, {0x00, 0x00, 0x00} },
diff --git a/drivers/ide/it8213.c b/drivers/ide/it8213.c
index 46816ba..1847aeb 100644
--- a/drivers/ide/it8213.c
+++ b/drivers/ide/it8213.c
@@ -156,7 +156,7 @@ static const struct ide_port_ops it8213_port_ops = {
 	.cable_detect		= it8213_cable_detect,
 };
 
-static const struct ide_port_info it8213_chipset __devinitdata = {
+static const struct ide_port_info it8213_chipset __devinitconst = {
 	.name		= DRV_NAME,
 	.enablebits	= { {0x41, 0x80, 0x80} },
 	.port_ops	= &it8213_port_ops,
diff --git a/drivers/ide/it821x.c b/drivers/ide/it821x.c
index 2e3169f..c5611db 100644
--- a/drivers/ide/it821x.c
+++ b/drivers/ide/it821x.c
@@ -630,7 +630,7 @@ static const struct ide_port_ops it821x_port_ops = {
 	.cable_detect		= it821x_cable_detect,
 };
 
-static const struct ide_port_info it821x_chipset __devinitdata = {
+static const struct ide_port_info it821x_chipset __devinitconst = {
 	.name		= DRV_NAME,
 	.init_chipset	= init_chipset_it821x,
 	.init_hwif	= init_hwif_it821x,
diff --git a/drivers/ide/jmicron.c b/drivers/ide/jmicron.c
index 74c2c4a..efddd7d 100644
--- a/drivers/ide/jmicron.c
+++ b/drivers/ide/jmicron.c
@@ -102,7 +102,7 @@ static const struct ide_port_ops jmicron_port_ops = {
 	.cable_detect		= jmicron_cable_detect,
 };
 
-static const struct ide_port_info jmicron_chipset __devinitdata = {
+static const struct ide_port_info jmicron_chipset __devinitconst = {
 	.name		= DRV_NAME,
 	.enablebits	= { { 0x40, 0x01, 0x01 }, { 0x40, 0x10, 0x10 } },
 	.port_ops	= &jmicron_port_ops,
diff --git a/drivers/ide/ns87415.c b/drivers/ide/ns87415.c
index 95327a2..73f78d8 100644
--- a/drivers/ide/ns87415.c
+++ b/drivers/ide/ns87415.c
@@ -293,7 +293,7 @@ static const struct ide_dma_ops ns87415_dma_ops = {
 	.dma_sff_read_status	= superio_dma_sff_read_status,
 };
 
-static const struct ide_port_info ns87415_chipset __devinitdata = {
+static const struct ide_port_info ns87415_chipset __devinitconst = {
 	.name		= DRV_NAME,
 	.init_hwif	= init_hwif_ns87415,
 	.tp_ops 	= &ns87415_tp_ops,
diff --git a/drivers/ide/opti621.c b/drivers/ide/opti621.c
index 1a53a4c..39edc66 100644
--- a/drivers/ide/opti621.c
+++ b/drivers/ide/opti621.c
@@ -131,7 +131,7 @@ static const struct ide_port_ops opti621_port_ops = {
 	.set_pio_mode		= opti621_set_pio_mode,
 };
 
-static const struct ide_port_info opti621_chipset __devinitdata = {
+static const struct ide_port_info opti621_chipset __devinitconst = {
 	.name		= DRV_NAME,
 	.enablebits	= { {0x45, 0x80, 0x00}, {0x40, 0x08, 0x00} },
 	.port_ops	= &opti621_port_ops,
diff --git a/drivers/ide/pdc202xx_new.c b/drivers/ide/pdc202xx_new.c
index 9546fe2..2e5ceb6 100644
--- a/drivers/ide/pdc202xx_new.c
+++ b/drivers/ide/pdc202xx_new.c
@@ -465,7 +465,7 @@ static const struct ide_port_ops pdcnew_port_ops = {
 		.udma_mask	= udma, \
 	}
 
-static const struct ide_port_info pdcnew_chipsets[] __devinitdata = {
+static const struct ide_port_info pdcnew_chipsets[] __devinitconst = {
 	/* 0: PDC202{68,70} */		DECLARE_PDCNEW_DEV(ATA_UDMA5),
 	/* 1: PDC202{69,71,75,76,77} */	DECLARE_PDCNEW_DEV(ATA_UDMA6),
 };
diff --git a/drivers/ide/pdc202xx_old.c b/drivers/ide/pdc202xx_old.c
index 3a35ec6..5634510 100644
--- a/drivers/ide/pdc202xx_old.c
+++ b/drivers/ide/pdc202xx_old.c
@@ -270,7 +270,7 @@ static const struct ide_dma_ops pdc2026x_dma_ops = {
 		.max_sectors	= sectors, \
 	}
 
-static const struct ide_port_info pdc202xx_chipsets[] __devinitdata = {
+static const struct ide_port_info pdc202xx_chipsets[] __devinitconst = {
 	{	/* 0: PDC20246 */
 		.name		= DRV_NAME,
 		.init_chipset	= init_chipset_pdc202xx,
diff --git a/drivers/ide/piix.c b/drivers/ide/piix.c
index 1892e81..fe0fd60 100644
--- a/drivers/ide/piix.c
+++ b/drivers/ide/piix.c
@@ -344,7 +344,7 @@ static const struct ide_port_ops ich_port_ops = {
 		.udma_mask	= udma, \
 	}
 
-static const struct ide_port_info piix_pci_info[] __devinitdata = {
+static const struct ide_port_info piix_pci_info[] __devinitconst = {
 	/* 0: MPIIX */
 	{	/*
 		 * MPIIX actually has only a single IDE channel mapped to
diff --git a/drivers/ide/qd65xx.c b/drivers/ide/qd65xx.c
index e03f4f1..a6fb6a8 100644
--- a/drivers/ide/qd65xx.c
+++ b/drivers/ide/qd65xx.c
@@ -335,7 +335,7 @@ static const struct ide_port_ops qd6580_port_ops = {
 	.set_pio_mode		= qd6580_set_pio_mode,
 };
 
-static const struct ide_port_info qd65xx_port_info __initdata = {
+static const struct ide_port_info qd65xx_port_info __initconst = {
 	.name			= DRV_NAME,
 	.tp_ops 		= &qd65xx_tp_ops,
 	.chipset		= ide_qd65xx,
diff --git a/drivers/ide/rz1000.c b/drivers/ide/rz1000.c
index a6414a8..c04173e 100644
--- a/drivers/ide/rz1000.c
+++ b/drivers/ide/rz1000.c
@@ -38,7 +38,7 @@ static int __devinit rz1000_disable_readahead(struct pci_dev *dev)
 	}
 }
 
-static const struct ide_port_info rz1000_chipset __devinitdata = {
+static const struct ide_port_info rz1000_chipset __devinitconst = {
 	.name		= DRV_NAME,
 	.host_flags	= IDE_HFLAG_NO_DMA,
 };
diff --git a/drivers/ide/sc1200.c b/drivers/ide/sc1200.c
index 356b9b5..d4758eb 100644
--- a/drivers/ide/sc1200.c
+++ b/drivers/ide/sc1200.c
@@ -291,7 +291,7 @@ static const struct ide_dma_ops sc1200_dma_ops = {
 	.dma_sff_read_status	= ide_dma_sff_read_status,
 };
 
-static const struct ide_port_info sc1200_chipset __devinitdata = {
+static const struct ide_port_info sc1200_chipset __devinitconst = {
 	.name		= DRV_NAME,
 	.port_ops	= &sc1200_port_ops,
 	.dma_ops	= &sc1200_dma_ops,
diff --git a/drivers/ide/scc_pata.c b/drivers/ide/scc_pata.c
index b7f5b0c..9701038 100644
--- a/drivers/ide/scc_pata.c
+++ b/drivers/ide/scc_pata.c
@@ -811,7 +811,7 @@ static const struct ide_dma_ops scc_dma_ops = {
 	.dma_sff_read_status	= scc_dma_sff_read_status,
 };
 
-static const struct ide_port_info scc_chipset __devinitdata = {
+static const struct ide_port_info scc_chipset __devinitconst = {
 	.name		= "sccIDE",
 	.init_iops	= init_iops_scc,
 	.init_dma	= scc_init_dma,
diff --git a/drivers/ide/serverworks.c b/drivers/ide/serverworks.c
index 35fb8da..24d72ef 100644
--- a/drivers/ide/serverworks.c
+++ b/drivers/ide/serverworks.c
@@ -337,7 +337,7 @@ static const struct ide_port_ops svwks_port_ops = {
 	.cable_detect		= svwks_cable_detect,
 };
 
-static const struct ide_port_info serverworks_chipsets[] __devinitdata = {
+static const struct ide_port_info serverworks_chipsets[] __devinitconst = {
 	{	/* 0: OSB4 */
 		.name		= DRV_NAME,
 		.init_chipset	= init_chipset_svwks,
diff --git a/drivers/ide/siimage.c b/drivers/ide/siimage.c
index ddeda44..46f7e30 100644
--- a/drivers/ide/siimage.c
+++ b/drivers/ide/siimage.c
@@ -719,7 +719,7 @@ static const struct ide_dma_ops sil_dma_ops = {
 		.udma_mask	= ATA_UDMA6,		\
 	}
 
-static const struct ide_port_info siimage_chipsets[] __devinitdata = {
+static const struct ide_port_info siimage_chipsets[] __devinitconst = {
 	/* 0: SiI680 */  DECLARE_SII_DEV(&sil_pata_port_ops),
 	/* 1: SiI3112 */ DECLARE_SII_DEV(&sil_sata_port_ops)
 };
diff --git a/drivers/ide/sis5513.c b/drivers/ide/sis5513.c
index 4a00225..09e61b4 100644
--- a/drivers/ide/sis5513.c
+++ b/drivers/ide/sis5513.c
@@ -563,7 +563,7 @@ static const struct ide_port_ops sis_ata133_port_ops = {
 	.cable_detect		= sis_cable_detect,
 };
 
-static const struct ide_port_info sis5513_chipset __devinitdata = {
+static const struct ide_port_info sis5513_chipset __devinitconst = {
 	.name		= DRV_NAME,
 	.init_chipset	= init_chipset_sis5513,
 	.enablebits	= { {0x4a, 0x02, 0x02}, {0x4a, 0x04, 0x04} },
diff --git a/drivers/ide/sl82c105.c b/drivers/ide/sl82c105.c
index f21dc2a..d051cd2 100644
--- a/drivers/ide/sl82c105.c
+++ b/drivers/ide/sl82c105.c
@@ -299,7 +299,7 @@ static const struct ide_dma_ops sl82c105_dma_ops = {
 	.dma_sff_read_status	= ide_dma_sff_read_status,
 };
 
-static const struct ide_port_info sl82c105_chipset __devinitdata = {
+static const struct ide_port_info sl82c105_chipset __devinitconst = {
 	.name		= DRV_NAME,
 	.init_chipset	= init_chipset_sl82c105,
 	.enablebits	= {{0x40,0x01,0x01}, {0x40,0x10,0x10}},
diff --git a/drivers/ide/slc90e66.c b/drivers/ide/slc90e66.c
index 864ffe0..863a5e9 100644
--- a/drivers/ide/slc90e66.c
+++ b/drivers/ide/slc90e66.c
@@ -132,7 +132,7 @@ static const struct ide_port_ops slc90e66_port_ops = {
 	.cable_detect		= slc90e66_cable_detect,
 };
 
-static const struct ide_port_info slc90e66_chipset __devinitdata = {
+static const struct ide_port_info slc90e66_chipset __devinitconst = {
 	.name		= DRV_NAME,
 	.enablebits	= { {0x41, 0x80, 0x80}, {0x43, 0x80, 0x80} },
 	.port_ops	= &slc90e66_port_ops,
diff --git a/drivers/ide/tc86c001.c b/drivers/ide/tc86c001.c
index 4799d5c..1794678 100644
--- a/drivers/ide/tc86c001.c
+++ b/drivers/ide/tc86c001.c
@@ -192,7 +192,7 @@ static const struct ide_dma_ops tc86c001_dma_ops = {
 	.dma_sff_read_status	= ide_dma_sff_read_status,
 };
 
-static const struct ide_port_info tc86c001_chipset __devinitdata = {
+static const struct ide_port_info tc86c001_chipset __devinitconst = {
 	.name		= DRV_NAME,
 	.init_hwif	= init_hwif_tc86c001,
 	.port_ops	= &tc86c001_port_ops,
diff --git a/drivers/ide/triflex.c b/drivers/ide/triflex.c
index 281c914..55ce1b8 100644
--- a/drivers/ide/triflex.c
+++ b/drivers/ide/triflex.c
@@ -92,7 +92,7 @@ static const struct ide_port_ops triflex_port_ops = {
 	.set_dma_mode		= triflex_set_mode,
 };
 
-static const struct ide_port_info triflex_device __devinitdata = {
+static const struct ide_port_info triflex_device __devinitconst = {
 	.name		= DRV_NAME,
 	.enablebits	= {{0x80, 0x01, 0x01}, {0x80, 0x02, 0x02}},
 	.port_ops	= &triflex_port_ops,
diff --git a/drivers/ide/trm290.c b/drivers/ide/trm290.c
index 4b42ca0..e494a98 100644
--- a/drivers/ide/trm290.c
+++ b/drivers/ide/trm290.c
@@ -324,7 +324,7 @@ static struct ide_dma_ops trm290_dma_ops = {
 	.dma_check		= trm290_dma_check,
 };
 
-static const struct ide_port_info trm290_chipset __devinitdata = {
+static const struct ide_port_info trm290_chipset __devinitconst = {
 	.name		= DRV_NAME,
 	.init_hwif	= init_hwif_trm290,
 	.tp_ops 	= &trm290_tp_ops,
diff --git a/drivers/ide/tx4938ide.c b/drivers/ide/tx4938ide.c
index 7002765..91d49dd 100644
--- a/drivers/ide/tx4938ide.c
+++ b/drivers/ide/tx4938ide.c
@@ -117,7 +117,7 @@ static const struct ide_port_ops tx4938ide_port_ops = {
 	.set_pio_mode		= tx4938ide_set_pio_mode,
 };
 
-static const struct ide_port_info tx4938ide_port_info __initdata = {
+static const struct ide_port_info tx4938ide_port_info __initconst = {
 	.port_ops		= &tx4938ide_port_ops,
 #ifdef __BIG_ENDIAN
 	.tp_ops			= &tx4938ide_tp_ops,
diff --git a/drivers/ide/tx4939ide.c b/drivers/ide/tx4939ide.c
index 71c2319..c0ab800 100644
--- a/drivers/ide/tx4939ide.c
+++ b/drivers/ide/tx4939ide.c
@@ -522,7 +522,7 @@ static const struct ide_dma_ops tx4939ide_dma_ops = {
 	.dma_sff_read_status	= tx4939ide_dma_sff_read_status,
 };
 
-static const struct ide_port_info tx4939ide_port_info __initdata = {
+static const struct ide_port_info tx4939ide_port_info __initconst = {
 	.init_hwif		= tx4939ide_init_hwif,
 	.init_dma		= tx4939ide_init_dma,
 	.port_ops		= &tx4939ide_port_ops,
diff --git a/drivers/ide/umc8672.c b/drivers/ide/umc8672.c
index 5cfb781..3aa0fea 100644
--- a/drivers/ide/umc8672.c
+++ b/drivers/ide/umc8672.c
@@ -128,7 +128,7 @@ static const struct ide_port_ops umc8672_port_ops = {
 	.set_pio_mode		= umc_set_pio_mode,
 };
 
-static const struct ide_port_info umc8672_port_info __initdata = {
+static const struct ide_port_info umc8672_port_info __initconst = {
 	.name			= DRV_NAME,
 	.chipset		= ide_umc8672,
 	.port_ops		= &umc8672_port_ops,
diff --git a/drivers/ide/via82cxxx.c b/drivers/ide/via82cxxx.c
index f46f49c..eb77678 100644
--- a/drivers/ide/via82cxxx.c
+++ b/drivers/ide/via82cxxx.c
@@ -403,7 +403,7 @@ static const struct ide_port_ops via_port_ops = {
 	.cable_detect		= via82cxxx_cable_detect,
 };
 
-static const struct ide_port_info via82cxxx_chipset __devinitdata = {
+static const struct ide_port_info via82cxxx_chipset __devinitconst = {
 	.name		= DRV_NAME,
 	.init_chipset	= init_chipset_via82cxxx,
 	.enablebits	= { { 0x40, 0x02, 0x02 }, { 0x40, 0x01, 0x01 } },
diff --git a/drivers/ieee802154/Kconfig b/drivers/ieee802154/Kconfig
deleted file mode 100644
index 1fc4eef..0000000
--- a/drivers/ieee802154/Kconfig
+++ /dev/null
@@ -1,36 +0,0 @@
-menuconfig IEEE802154_DRIVERS
-	tristate "IEEE 802.15.4 drivers"
-	depends on NETDEVICES && IEEE802154
-	default y
-	---help---
-	  Say Y here to get to see options for IEEE 802.15.4 Low-Rate
-	  Wireless Personal Area Network device drivers. This option alone
-	  does not add any kernel code.
-
-	  If you say N, all options in this submenu will be skipped and
-	  disabled.
-
-config IEEE802154_FAKEHARD
-	tristate "Fake LR-WPAN driver with several interconnected devices"
-	depends on  IEEE802154_DRIVERS
-	---help---
-	  Say Y here to enable the fake driver that serves as an example
-          of HardMAC device driver.
-
-          This driver can also be built as a module. To do so say M here.
-	  The module will be called 'fakehard'.
-
-config IEEE802154_FAKELB
-	depends on IEEE802154_DRIVERS && MAC802154
-	tristate "IEEE 802.15.4 loopback driver"
-	---help---
-	  Say Y here to enable the fake driver that can emulate a net
-	  of several interconnected radio devices.
-
-	  This driver can also be built as a module. To do so say M here.
-	  The module will be called 'fakelb'.
-
-config IEEE802154_AT86RF230
-        depends on IEEE802154_DRIVERS && MAC802154
-        tristate "AT86RF230/231 transceiver driver"
-        depends on SPI
diff --git a/drivers/ieee802154/Makefile b/drivers/ieee802154/Makefile
deleted file mode 100644
index 4f4371d..0000000
--- a/drivers/ieee802154/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-obj-$(CONFIG_IEEE802154_FAKEHARD) += fakehard.o
-obj-$(CONFIG_IEEE802154_FAKELB) += fakelb.o
-obj-$(CONFIG_IEEE802154_AT86RF230) += at86rf230.o
diff --git a/drivers/ieee802154/at86rf230.c b/drivers/ieee802154/at86rf230.c
deleted file mode 100644
index 5d30940..0000000
--- a/drivers/ieee802154/at86rf230.c
+++ /dev/null
@@ -1,968 +0,0 @@
-/*
- * AT86RF230/RF231 driver
- *
- * Copyright (C) 2009-2012 Siemens AG
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You 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.
- *
- * Written by:
- * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
- * Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
- */
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/gpio.h>
-#include <linux/delay.h>
-#include <linux/mutex.h>
-#include <linux/workqueue.h>
-#include <linux/spinlock.h>
-#include <linux/spi/spi.h>
-#include <linux/spi/at86rf230.h>
-#include <linux/skbuff.h>
-
-#include <net/mac802154.h>
-#include <net/wpan-phy.h>
-
-struct at86rf230_local {
-	struct spi_device *spi;
-	int rstn, slp_tr, dig2;
-
-	u8 part;
-	u8 vers;
-
-	u8 buf[2];
-	struct mutex bmux;
-
-	struct work_struct irqwork;
-	struct completion tx_complete;
-
-	struct ieee802154_dev *dev;
-
-	spinlock_t lock;
-	bool irq_disabled;
-	bool is_tx;
-};
-
-#define	RG_TRX_STATUS	(0x01)
-#define	SR_TRX_STATUS		0x01, 0x1f, 0
-#define	SR_RESERVED_01_3	0x01, 0x20, 5
-#define	SR_CCA_STATUS		0x01, 0x40, 6
-#define	SR_CCA_DONE		0x01, 0x80, 7
-#define	RG_TRX_STATE	(0x02)
-#define	SR_TRX_CMD		0x02, 0x1f, 0
-#define	SR_TRAC_STATUS		0x02, 0xe0, 5
-#define	RG_TRX_CTRL_0	(0x03)
-#define	SR_CLKM_CTRL		0x03, 0x07, 0
-#define	SR_CLKM_SHA_SEL		0x03, 0x08, 3
-#define	SR_PAD_IO_CLKM		0x03, 0x30, 4
-#define	SR_PAD_IO		0x03, 0xc0, 6
-#define	RG_TRX_CTRL_1	(0x04)
-#define	SR_IRQ_POLARITY		0x04, 0x01, 0
-#define	SR_IRQ_MASK_MODE	0x04, 0x02, 1
-#define	SR_SPI_CMD_MODE		0x04, 0x0c, 2
-#define	SR_RX_BL_CTRL		0x04, 0x10, 4
-#define	SR_TX_AUTO_CRC_ON	0x04, 0x20, 5
-#define	SR_IRQ_2_EXT_EN		0x04, 0x40, 6
-#define	SR_PA_EXT_EN		0x04, 0x80, 7
-#define	RG_PHY_TX_PWR	(0x05)
-#define	SR_TX_PWR		0x05, 0x0f, 0
-#define	SR_PA_LT		0x05, 0x30, 4
-#define	SR_PA_BUF_LT		0x05, 0xc0, 6
-#define	RG_PHY_RSSI	(0x06)
-#define	SR_RSSI			0x06, 0x1f, 0
-#define	SR_RND_VALUE		0x06, 0x60, 5
-#define	SR_RX_CRC_VALID		0x06, 0x80, 7
-#define	RG_PHY_ED_LEVEL	(0x07)
-#define	SR_ED_LEVEL		0x07, 0xff, 0
-#define	RG_PHY_CC_CCA	(0x08)
-#define	SR_CHANNEL		0x08, 0x1f, 0
-#define	SR_CCA_MODE		0x08, 0x60, 5
-#define	SR_CCA_REQUEST		0x08, 0x80, 7
-#define	RG_CCA_THRES	(0x09)
-#define	SR_CCA_ED_THRES		0x09, 0x0f, 0
-#define	SR_RESERVED_09_1	0x09, 0xf0, 4
-#define	RG_RX_CTRL	(0x0a)
-#define	SR_PDT_THRES		0x0a, 0x0f, 0
-#define	SR_RESERVED_0a_1	0x0a, 0xf0, 4
-#define	RG_SFD_VALUE	(0x0b)
-#define	SR_SFD_VALUE		0x0b, 0xff, 0
-#define	RG_TRX_CTRL_2	(0x0c)
-#define	SR_OQPSK_DATA_RATE	0x0c, 0x03, 0
-#define	SR_RESERVED_0c_2	0x0c, 0x7c, 2
-#define	SR_RX_SAFE_MODE		0x0c, 0x80, 7
-#define	RG_ANT_DIV	(0x0d)
-#define	SR_ANT_CTRL		0x0d, 0x03, 0
-#define	SR_ANT_EXT_SW_EN	0x0d, 0x04, 2
-#define	SR_ANT_DIV_EN		0x0d, 0x08, 3
-#define	SR_RESERVED_0d_2	0x0d, 0x70, 4
-#define	SR_ANT_SEL		0x0d, 0x80, 7
-#define	RG_IRQ_MASK	(0x0e)
-#define	SR_IRQ_MASK		0x0e, 0xff, 0
-#define	RG_IRQ_STATUS	(0x0f)
-#define	SR_IRQ_0_PLL_LOCK	0x0f, 0x01, 0
-#define	SR_IRQ_1_PLL_UNLOCK	0x0f, 0x02, 1
-#define	SR_IRQ_2_RX_START	0x0f, 0x04, 2
-#define	SR_IRQ_3_TRX_END	0x0f, 0x08, 3
-#define	SR_IRQ_4_CCA_ED_DONE	0x0f, 0x10, 4
-#define	SR_IRQ_5_AMI		0x0f, 0x20, 5
-#define	SR_IRQ_6_TRX_UR		0x0f, 0x40, 6
-#define	SR_IRQ_7_BAT_LOW	0x0f, 0x80, 7
-#define	RG_VREG_CTRL	(0x10)
-#define	SR_RESERVED_10_6	0x10, 0x03, 0
-#define	SR_DVDD_OK		0x10, 0x04, 2
-#define	SR_DVREG_EXT		0x10, 0x08, 3
-#define	SR_RESERVED_10_3	0x10, 0x30, 4
-#define	SR_AVDD_OK		0x10, 0x40, 6
-#define	SR_AVREG_EXT		0x10, 0x80, 7
-#define	RG_BATMON	(0x11)
-#define	SR_BATMON_VTH		0x11, 0x0f, 0
-#define	SR_BATMON_HR		0x11, 0x10, 4
-#define	SR_BATMON_OK		0x11, 0x20, 5
-#define	SR_RESERVED_11_1	0x11, 0xc0, 6
-#define	RG_XOSC_CTRL	(0x12)
-#define	SR_XTAL_TRIM		0x12, 0x0f, 0
-#define	SR_XTAL_MODE		0x12, 0xf0, 4
-#define	RG_RX_SYN	(0x15)
-#define	SR_RX_PDT_LEVEL		0x15, 0x0f, 0
-#define	SR_RESERVED_15_2	0x15, 0x70, 4
-#define	SR_RX_PDT_DIS		0x15, 0x80, 7
-#define	RG_XAH_CTRL_1	(0x17)
-#define	SR_RESERVED_17_8	0x17, 0x01, 0
-#define	SR_AACK_PROM_MODE	0x17, 0x02, 1
-#define	SR_AACK_ACK_TIME	0x17, 0x04, 2
-#define	SR_RESERVED_17_5	0x17, 0x08, 3
-#define	SR_AACK_UPLD_RES_FT	0x17, 0x10, 4
-#define	SR_AACK_FLTR_RES_FT	0x17, 0x20, 5
-#define	SR_RESERVED_17_2	0x17, 0x40, 6
-#define	SR_RESERVED_17_1	0x17, 0x80, 7
-#define	RG_FTN_CTRL	(0x18)
-#define	SR_RESERVED_18_2	0x18, 0x7f, 0
-#define	SR_FTN_START		0x18, 0x80, 7
-#define	RG_PLL_CF	(0x1a)
-#define	SR_RESERVED_1a_2	0x1a, 0x7f, 0
-#define	SR_PLL_CF_START		0x1a, 0x80, 7
-#define	RG_PLL_DCU	(0x1b)
-#define	SR_RESERVED_1b_3	0x1b, 0x3f, 0
-#define	SR_RESERVED_1b_2	0x1b, 0x40, 6
-#define	SR_PLL_DCU_START	0x1b, 0x80, 7
-#define	RG_PART_NUM	(0x1c)
-#define	SR_PART_NUM		0x1c, 0xff, 0
-#define	RG_VERSION_NUM	(0x1d)
-#define	SR_VERSION_NUM		0x1d, 0xff, 0
-#define	RG_MAN_ID_0	(0x1e)
-#define	SR_MAN_ID_0		0x1e, 0xff, 0
-#define	RG_MAN_ID_1	(0x1f)
-#define	SR_MAN_ID_1		0x1f, 0xff, 0
-#define	RG_SHORT_ADDR_0	(0x20)
-#define	SR_SHORT_ADDR_0		0x20, 0xff, 0
-#define	RG_SHORT_ADDR_1	(0x21)
-#define	SR_SHORT_ADDR_1		0x21, 0xff, 0
-#define	RG_PAN_ID_0	(0x22)
-#define	SR_PAN_ID_0		0x22, 0xff, 0
-#define	RG_PAN_ID_1	(0x23)
-#define	SR_PAN_ID_1		0x23, 0xff, 0
-#define	RG_IEEE_ADDR_0	(0x24)
-#define	SR_IEEE_ADDR_0		0x24, 0xff, 0
-#define	RG_IEEE_ADDR_1	(0x25)
-#define	SR_IEEE_ADDR_1		0x25, 0xff, 0
-#define	RG_IEEE_ADDR_2	(0x26)
-#define	SR_IEEE_ADDR_2		0x26, 0xff, 0
-#define	RG_IEEE_ADDR_3	(0x27)
-#define	SR_IEEE_ADDR_3		0x27, 0xff, 0
-#define	RG_IEEE_ADDR_4	(0x28)
-#define	SR_IEEE_ADDR_4		0x28, 0xff, 0
-#define	RG_IEEE_ADDR_5	(0x29)
-#define	SR_IEEE_ADDR_5		0x29, 0xff, 0
-#define	RG_IEEE_ADDR_6	(0x2a)
-#define	SR_IEEE_ADDR_6		0x2a, 0xff, 0
-#define	RG_IEEE_ADDR_7	(0x2b)
-#define	SR_IEEE_ADDR_7		0x2b, 0xff, 0
-#define	RG_XAH_CTRL_0	(0x2c)
-#define	SR_SLOTTED_OPERATION	0x2c, 0x01, 0
-#define	SR_MAX_CSMA_RETRIES	0x2c, 0x0e, 1
-#define	SR_MAX_FRAME_RETRIES	0x2c, 0xf0, 4
-#define	RG_CSMA_SEED_0	(0x2d)
-#define	SR_CSMA_SEED_0		0x2d, 0xff, 0
-#define	RG_CSMA_SEED_1	(0x2e)
-#define	SR_CSMA_SEED_1		0x2e, 0x07, 0
-#define	SR_AACK_I_AM_COORD	0x2e, 0x08, 3
-#define	SR_AACK_DIS_ACK		0x2e, 0x10, 4
-#define	SR_AACK_SET_PD		0x2e, 0x20, 5
-#define	SR_AACK_FVN_MODE	0x2e, 0xc0, 6
-#define	RG_CSMA_BE	(0x2f)
-#define	SR_MIN_BE		0x2f, 0x0f, 0
-#define	SR_MAX_BE		0x2f, 0xf0, 4
-
-#define CMD_REG		0x80
-#define CMD_REG_MASK	0x3f
-#define CMD_WRITE	0x40
-#define CMD_FB		0x20
-
-#define IRQ_BAT_LOW	(1 << 7)
-#define IRQ_TRX_UR	(1 << 6)
-#define IRQ_AMI		(1 << 5)
-#define IRQ_CCA_ED	(1 << 4)
-#define IRQ_TRX_END	(1 << 3)
-#define IRQ_RX_START	(1 << 2)
-#define IRQ_PLL_UNL	(1 << 1)
-#define IRQ_PLL_LOCK	(1 << 0)
-
-#define STATE_P_ON		0x00	/* BUSY */
-#define STATE_BUSY_RX		0x01
-#define STATE_BUSY_TX		0x02
-#define STATE_FORCE_TRX_OFF	0x03
-#define STATE_FORCE_TX_ON	0x04	/* IDLE */
-/* 0x05 */				/* INVALID_PARAMETER */
-#define STATE_RX_ON		0x06
-/* 0x07 */				/* SUCCESS */
-#define STATE_TRX_OFF		0x08
-#define STATE_TX_ON		0x09
-/* 0x0a - 0x0e */			/* 0x0a - UNSUPPORTED_ATTRIBUTE */
-#define STATE_SLEEP		0x0F
-#define STATE_BUSY_RX_AACK	0x11
-#define STATE_BUSY_TX_ARET	0x12
-#define STATE_BUSY_RX_AACK_ON	0x16
-#define STATE_BUSY_TX_ARET_ON	0x19
-#define STATE_RX_ON_NOCLK	0x1C
-#define STATE_RX_AACK_ON_NOCLK	0x1D
-#define STATE_BUSY_RX_AACK_NOCLK 0x1E
-#define STATE_TRANSITION_IN_PROGRESS 0x1F
-
-static int
-__at86rf230_write(struct at86rf230_local *lp, u8 addr, u8 data)
-{
-	u8 *buf = lp->buf;
-	int status;
-	struct spi_message msg;
-	struct spi_transfer xfer = {
-		.len	= 2,
-		.tx_buf	= buf,
-	};
-
-	buf[0] = (addr & CMD_REG_MASK) | CMD_REG | CMD_WRITE;
-	buf[1] = data;
-	dev_vdbg(&lp->spi->dev, "buf[0] = %02x\n", buf[0]);
-	dev_vdbg(&lp->spi->dev, "buf[1] = %02x\n", buf[1]);
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfer, &msg);
-
-	status = spi_sync(lp->spi, &msg);
-	dev_vdbg(&lp->spi->dev, "status = %d\n", status);
-	if (msg.status)
-		status = msg.status;
-
-	dev_vdbg(&lp->spi->dev, "status = %d\n", status);
-	dev_vdbg(&lp->spi->dev, "buf[0] = %02x\n", buf[0]);
-	dev_vdbg(&lp->spi->dev, "buf[1] = %02x\n", buf[1]);
-
-	return status;
-}
-
-static int
-__at86rf230_read_subreg(struct at86rf230_local *lp,
-			u8 addr, u8 mask, int shift, u8 *data)
-{
-	u8 *buf = lp->buf;
-	int status;
-	struct spi_message msg;
-	struct spi_transfer xfer = {
-		.len	= 2,
-		.tx_buf	= buf,
-		.rx_buf	= buf,
-	};
-
-	buf[0] = (addr & CMD_REG_MASK) | CMD_REG;
-	buf[1] = 0xff;
-	dev_vdbg(&lp->spi->dev, "buf[0] = %02x\n", buf[0]);
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfer, &msg);
-
-	status = spi_sync(lp->spi, &msg);
-	dev_vdbg(&lp->spi->dev, "status = %d\n", status);
-	if (msg.status)
-		status = msg.status;
-
-	dev_vdbg(&lp->spi->dev, "status = %d\n", status);
-	dev_vdbg(&lp->spi->dev, "buf[0] = %02x\n", buf[0]);
-	dev_vdbg(&lp->spi->dev, "buf[1] = %02x\n", buf[1]);
-
-	if (status == 0)
-		*data = buf[1];
-
-	return status;
-}
-
-static int
-at86rf230_read_subreg(struct at86rf230_local *lp,
-		      u8 addr, u8 mask, int shift, u8 *data)
-{
-	int status;
-
-	mutex_lock(&lp->bmux);
-	status = __at86rf230_read_subreg(lp, addr, mask, shift, data);
-	mutex_unlock(&lp->bmux);
-
-	return status;
-}
-
-static int
-at86rf230_write_subreg(struct at86rf230_local *lp,
-		       u8 addr, u8 mask, int shift, u8 data)
-{
-	int status;
-	u8 val;
-
-	mutex_lock(&lp->bmux);
-	status = __at86rf230_read_subreg(lp, addr, 0xff, 0, &val);
-	if (status)
-		goto out;
-
-	val &= ~mask;
-	val |= (data << shift) & mask;
-
-	status = __at86rf230_write(lp, addr, val);
-out:
-	mutex_unlock(&lp->bmux);
-
-	return status;
-}
-
-static int
-at86rf230_write_fbuf(struct at86rf230_local *lp, u8 *data, u8 len)
-{
-	u8 *buf = lp->buf;
-	int status;
-	struct spi_message msg;
-	struct spi_transfer xfer_head = {
-		.len		= 2,
-		.tx_buf		= buf,
-
-	};
-	struct spi_transfer xfer_buf = {
-		.len		= len,
-		.tx_buf		= data,
-	};
-
-	mutex_lock(&lp->bmux);
-	buf[0] = CMD_WRITE | CMD_FB;
-	buf[1] = len + 2; /* 2 bytes for CRC that isn't written */
-
-	dev_vdbg(&lp->spi->dev, "buf[0] = %02x\n", buf[0]);
-	dev_vdbg(&lp->spi->dev, "buf[1] = %02x\n", buf[1]);
-
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfer_head, &msg);
-	spi_message_add_tail(&xfer_buf, &msg);
-
-	status = spi_sync(lp->spi, &msg);
-	dev_vdbg(&lp->spi->dev, "status = %d\n", status);
-	if (msg.status)
-		status = msg.status;
-
-	dev_vdbg(&lp->spi->dev, "status = %d\n", status);
-	dev_vdbg(&lp->spi->dev, "buf[0] = %02x\n", buf[0]);
-	dev_vdbg(&lp->spi->dev, "buf[1] = %02x\n", buf[1]);
-
-	mutex_unlock(&lp->bmux);
-	return status;
-}
-
-static int
-at86rf230_read_fbuf(struct at86rf230_local *lp, u8 *data, u8 *len, u8 *lqi)
-{
-	u8 *buf = lp->buf;
-	int status;
-	struct spi_message msg;
-	struct spi_transfer xfer_head = {
-		.len		= 2,
-		.tx_buf		= buf,
-		.rx_buf		= buf,
-	};
-	struct spi_transfer xfer_head1 = {
-		.len		= 2,
-		.tx_buf		= buf,
-		.rx_buf		= buf,
-	};
-	struct spi_transfer xfer_buf = {
-		.len		= 0,
-		.rx_buf		= data,
-	};
-
-	mutex_lock(&lp->bmux);
-
-	buf[0] = CMD_FB;
-	buf[1] = 0x00;
-
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfer_head, &msg);
-
-	status = spi_sync(lp->spi, &msg);
-	dev_vdbg(&lp->spi->dev, "status = %d\n", status);
-
-	xfer_buf.len = *(buf + 1) + 1;
-	*len = buf[1];
-
-	buf[0] = CMD_FB;
-	buf[1] = 0x00;
-
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfer_head1, &msg);
-	spi_message_add_tail(&xfer_buf, &msg);
-
-	status = spi_sync(lp->spi, &msg);
-
-	if (msg.status)
-		status = msg.status;
-
-	dev_vdbg(&lp->spi->dev, "status = %d\n", status);
-	dev_vdbg(&lp->spi->dev, "buf[0] = %02x\n", buf[0]);
-	dev_vdbg(&lp->spi->dev, "buf[1] = %02x\n", buf[1]);
-
-	if (status) {
-		if (lqi && (*len > lp->buf[1]))
-			*lqi = data[lp->buf[1]];
-	}
-	mutex_unlock(&lp->bmux);
-
-	return status;
-}
-
-static int
-at86rf230_ed(struct ieee802154_dev *dev, u8 *level)
-{
-	might_sleep();
-	BUG_ON(!level);
-	*level = 0xbe;
-	return 0;
-}
-
-static int
-at86rf230_state(struct ieee802154_dev *dev, int state)
-{
-	struct at86rf230_local *lp = dev->priv;
-	int rc;
-	u8 val;
-	u8 desired_status;
-
-	might_sleep();
-
-	if (state == STATE_FORCE_TX_ON)
-		desired_status = STATE_TX_ON;
-	else if (state == STATE_FORCE_TRX_OFF)
-		desired_status = STATE_TRX_OFF;
-	else
-		desired_status = state;
-
-	do {
-		rc = at86rf230_read_subreg(lp, SR_TRX_STATUS, &val);
-		if (rc)
-			goto err;
-	} while (val == STATE_TRANSITION_IN_PROGRESS);
-
-	if (val == desired_status)
-		return 0;
-
-	/* state is equal to phy states */
-	rc = at86rf230_write_subreg(lp, SR_TRX_CMD, state);
-	if (rc)
-		goto err;
-
-	do {
-		rc = at86rf230_read_subreg(lp, SR_TRX_STATUS, &val);
-		if (rc)
-			goto err;
-	} while (val == STATE_TRANSITION_IN_PROGRESS);
-
-
-	if (val == desired_status)
-		return 0;
-
-	pr_err("unexpected state change: %d, asked for %d\n", val, state);
-	return -EBUSY;
-
-err:
-	pr_err("error: %d\n", rc);
-	return rc;
-}
-
-static int
-at86rf230_start(struct ieee802154_dev *dev)
-{
-	struct at86rf230_local *lp = dev->priv;
-	u8 rc;
-
-	rc = at86rf230_write_subreg(lp, SR_RX_SAFE_MODE, 1);
-	if (rc)
-		return rc;
-
-	return at86rf230_state(dev, STATE_RX_ON);
-}
-
-static void
-at86rf230_stop(struct ieee802154_dev *dev)
-{
-	at86rf230_state(dev, STATE_FORCE_TRX_OFF);
-}
-
-static int
-at86rf230_channel(struct ieee802154_dev *dev, int page, int channel)
-{
-	struct at86rf230_local *lp = dev->priv;
-	int rc;
-
-	might_sleep();
-
-	if (page != 0 || channel < 11 || channel > 26) {
-		WARN_ON(1);
-		return -EINVAL;
-	}
-
-	rc = at86rf230_write_subreg(lp, SR_CHANNEL, channel);
-	msleep(1); /* Wait for PLL */
-	dev->phy->current_channel = channel;
-
-	return 0;
-}
-
-static int
-at86rf230_xmit(struct ieee802154_dev *dev, struct sk_buff *skb)
-{
-	struct at86rf230_local *lp = dev->priv;
-	int rc;
-	unsigned long flags;
-
-	spin_lock(&lp->lock);
-	if  (lp->irq_disabled) {
-		spin_unlock(&lp->lock);
-		return -EBUSY;
-	}
-	spin_unlock(&lp->lock);
-
-	might_sleep();
-
-	rc = at86rf230_state(dev, STATE_FORCE_TX_ON);
-	if (rc)
-		goto err;
-
-	spin_lock_irqsave(&lp->lock, flags);
-	lp->is_tx = 1;
-	INIT_COMPLETION(lp->tx_complete);
-	spin_unlock_irqrestore(&lp->lock, flags);
-
-	rc = at86rf230_write_fbuf(lp, skb->data, skb->len);
-	if (rc)
-		goto err_rx;
-
-	rc = at86rf230_write_subreg(lp, SR_TRX_CMD, STATE_BUSY_TX);
-	if (rc)
-		goto err_rx;
-
-	rc = wait_for_completion_interruptible(&lp->tx_complete);
-	if (rc < 0)
-		goto err_rx;
-
-	rc = at86rf230_start(dev);
-
-	return rc;
-
-err_rx:
-	at86rf230_start(dev);
-err:
-	pr_err("error: %d\n", rc);
-
-	spin_lock_irqsave(&lp->lock, flags);
-	lp->is_tx = 0;
-	spin_unlock_irqrestore(&lp->lock, flags);
-
-	return rc;
-}
-
-static int at86rf230_rx(struct at86rf230_local *lp)
-{
-	u8 len = 128, lqi = 0;
-	struct sk_buff *skb;
-
-	skb = alloc_skb(len, GFP_KERNEL);
-
-	if (!skb)
-		return -ENOMEM;
-
-	if (at86rf230_read_fbuf(lp, skb_put(skb, len), &len, &lqi))
-		goto err;
-
-	if (len < 2)
-		goto err;
-
-	skb_trim(skb, len - 2); /* We do not put CRC into the frame */
-
-	ieee802154_rx_irqsafe(lp->dev, skb, lqi);
-
-	dev_dbg(&lp->spi->dev, "READ_FBUF: %d %x\n", len, lqi);
-
-	return 0;
-err:
-	pr_debug("received frame is too small\n");
-
-	kfree_skb(skb);
-	return -EINVAL;
-}
-
-static struct ieee802154_ops at86rf230_ops = {
-	.owner = THIS_MODULE,
-	.xmit = at86rf230_xmit,
-	.ed = at86rf230_ed,
-	.set_channel = at86rf230_channel,
-	.start = at86rf230_start,
-	.stop = at86rf230_stop,
-};
-
-static void at86rf230_irqwork(struct work_struct *work)
-{
-	struct at86rf230_local *lp =
-		container_of(work, struct at86rf230_local, irqwork);
-	u8 status = 0, val;
-	int rc;
-	unsigned long flags;
-
-	rc = at86rf230_read_subreg(lp, RG_IRQ_STATUS, 0xff, 0, &val);
-	status |= val;
-
-	status &= ~IRQ_PLL_LOCK; /* ignore */
-	status &= ~IRQ_RX_START; /* ignore */
-	status &= ~IRQ_AMI; /* ignore */
-	status &= ~IRQ_TRX_UR; /* FIXME: possibly handle ???*/
-
-	if (status & IRQ_TRX_END) {
-		spin_lock_irqsave(&lp->lock, flags);
-		status &= ~IRQ_TRX_END;
-		if (lp->is_tx) {
-			lp->is_tx = 0;
-			spin_unlock_irqrestore(&lp->lock, flags);
-			complete(&lp->tx_complete);
-		} else {
-			spin_unlock_irqrestore(&lp->lock, flags);
-			at86rf230_rx(lp);
-		}
-	}
-
-	spin_lock_irqsave(&lp->lock, flags);
-	lp->irq_disabled = 0;
-	spin_unlock_irqrestore(&lp->lock, flags);
-
-	enable_irq(lp->spi->irq);
-}
-
-static irqreturn_t at86rf230_isr(int irq, void *data)
-{
-	struct at86rf230_local *lp = data;
-
-	disable_irq_nosync(irq);
-
-	spin_lock(&lp->lock);
-	lp->irq_disabled = 1;
-	spin_unlock(&lp->lock);
-
-	schedule_work(&lp->irqwork);
-
-	return IRQ_HANDLED;
-}
-
-
-static int at86rf230_hw_init(struct at86rf230_local *lp)
-{
-	u8 status;
-	int rc;
-
-	rc = at86rf230_read_subreg(lp, SR_TRX_STATUS, &status);
-	if (rc)
-		return rc;
-
-	dev_info(&lp->spi->dev, "Status: %02x\n", status);
-	if (status == STATE_P_ON) {
-		rc = at86rf230_write_subreg(lp, SR_TRX_CMD, STATE_TRX_OFF);
-		if (rc)
-			return rc;
-		msleep(1);
-		rc = at86rf230_read_subreg(lp, SR_TRX_STATUS, &status);
-		if (rc)
-			return rc;
-		dev_info(&lp->spi->dev, "Status: %02x\n", status);
-	}
-
-	rc = at86rf230_write_subreg(lp, SR_IRQ_MASK, 0xff); /* IRQ_TRX_UR |
-							     * IRQ_CCA_ED |
-							     * IRQ_TRX_END |
-							     * IRQ_PLL_UNL |
-							     * IRQ_PLL_LOCK
-							     */
-	if (rc)
-		return rc;
-
-	/* CLKM changes are applied immediately */
-	rc = at86rf230_write_subreg(lp, SR_CLKM_SHA_SEL, 0x00);
-	if (rc)
-		return rc;
-
-	/* Turn CLKM Off */
-	rc = at86rf230_write_subreg(lp, SR_CLKM_CTRL, 0x00);
-	if (rc)
-		return rc;
-	/* Wait the next SLEEP cycle */
-	msleep(100);
-
-	rc = at86rf230_write_subreg(lp, SR_TRX_CMD, STATE_TX_ON);
-	if (rc)
-		return rc;
-	msleep(1);
-
-	rc = at86rf230_read_subreg(lp, SR_TRX_STATUS, &status);
-	if (rc)
-		return rc;
-	dev_info(&lp->spi->dev, "Status: %02x\n", status);
-
-	rc = at86rf230_read_subreg(lp, SR_DVDD_OK, &status);
-	if (rc)
-		return rc;
-	if (!status) {
-		dev_err(&lp->spi->dev, "DVDD error\n");
-		return -EINVAL;
-	}
-
-	rc = at86rf230_read_subreg(lp, SR_AVDD_OK, &status);
-	if (rc)
-		return rc;
-	if (!status) {
-		dev_err(&lp->spi->dev, "AVDD error\n");
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int at86rf230_suspend(struct spi_device *spi, pm_message_t message)
-{
-	return 0;
-}
-
-static int at86rf230_resume(struct spi_device *spi)
-{
-	return 0;
-}
-
-static int at86rf230_fill_data(struct spi_device *spi)
-{
-	struct at86rf230_local *lp = spi_get_drvdata(spi);
-	struct at86rf230_platform_data *pdata = spi->dev.platform_data;
-
-	if (!pdata) {
-		dev_err(&spi->dev, "no platform_data\n");
-		return -EINVAL;
-	}
-
-	lp->rstn = pdata->rstn;
-	lp->slp_tr = pdata->slp_tr;
-	lp->dig2 = pdata->dig2;
-
-	return 0;
-}
-
-static int __devinit at86rf230_probe(struct spi_device *spi)
-{
-	struct ieee802154_dev *dev;
-	struct at86rf230_local *lp;
-	u8 man_id_0, man_id_1;
-	int rc;
-	const char *chip;
-	int supported = 0;
-
-	if (!spi->irq) {
-		dev_err(&spi->dev, "no IRQ specified\n");
-		return -EINVAL;
-	}
-
-	dev = ieee802154_alloc_device(sizeof(*lp), &at86rf230_ops);
-	if (!dev)
-		return -ENOMEM;
-
-	lp = dev->priv;
-	lp->dev = dev;
-
-	lp->spi = spi;
-
-	dev->priv = lp;
-	dev->parent = &spi->dev;
-	dev->extra_tx_headroom = 0;
-	/* We do support only 2.4 Ghz */
-	dev->phy->channels_supported[0] = 0x7FFF800;
-	dev->flags = IEEE802154_HW_OMIT_CKSUM;
-
-	mutex_init(&lp->bmux);
-	INIT_WORK(&lp->irqwork, at86rf230_irqwork);
-	spin_lock_init(&lp->lock);
-	init_completion(&lp->tx_complete);
-
-	spi_set_drvdata(spi, lp);
-
-	rc = at86rf230_fill_data(spi);
-	if (rc)
-		goto err_fill;
-
-	rc = gpio_request(lp->rstn, "rstn");
-	if (rc)
-		goto err_rstn;
-
-	if (gpio_is_valid(lp->slp_tr)) {
-		rc = gpio_request(lp->slp_tr, "slp_tr");
-		if (rc)
-			goto err_slp_tr;
-	}
-
-	rc = gpio_direction_output(lp->rstn, 1);
-	if (rc)
-		goto err_gpio_dir;
-
-	if (gpio_is_valid(lp->slp_tr)) {
-		rc = gpio_direction_output(lp->slp_tr, 0);
-		if (rc)
-			goto err_gpio_dir;
-	}
-
-	/* Reset */
-	msleep(1);
-	gpio_set_value(lp->rstn, 0);
-	msleep(1);
-	gpio_set_value(lp->rstn, 1);
-	msleep(1);
-
-	rc = at86rf230_read_subreg(lp, SR_MAN_ID_0, &man_id_0);
-	if (rc)
-		goto err_gpio_dir;
-	rc = at86rf230_read_subreg(lp, SR_MAN_ID_1, &man_id_1);
-	if (rc)
-		goto err_gpio_dir;
-
-	if (man_id_1 != 0x00 || man_id_0 != 0x1f) {
-		dev_err(&spi->dev, "Non-Atmel dev found (MAN_ID %02x %02x)\n",
-			man_id_1, man_id_0);
-		rc = -EINVAL;
-		goto err_gpio_dir;
-	}
-
-	rc = at86rf230_read_subreg(lp, SR_PART_NUM, &lp->part);
-	if (rc)
-		goto err_gpio_dir;
-
-	rc = at86rf230_read_subreg(lp, SR_VERSION_NUM, &lp->vers);
-	if (rc)
-		goto err_gpio_dir;
-
-	switch (lp->part) {
-	case 2:
-		chip = "at86rf230";
-		/* supported = 1;  FIXME: should be easy to support; */
-		break;
-	case 3:
-		chip = "at86rf231";
-		supported = 1;
-		break;
-	default:
-		chip = "UNKNOWN";
-		break;
-	}
-
-	dev_info(&spi->dev, "Detected %s chip version %d\n", chip, lp->vers);
-	if (!supported) {
-		rc = -ENOTSUPP;
-		goto err_gpio_dir;
-	}
-
-	rc = at86rf230_hw_init(lp);
-	if (rc)
-		goto err_gpio_dir;
-
-	rc = request_irq(spi->irq, at86rf230_isr, IRQF_SHARED,
-			 dev_name(&spi->dev), lp);
-	if (rc)
-		goto err_gpio_dir;
-
-	rc = ieee802154_register_device(lp->dev);
-	if (rc)
-		goto err_irq;
-
-	return rc;
-
-	ieee802154_unregister_device(lp->dev);
-err_irq:
-	free_irq(spi->irq, lp);
-	flush_work(&lp->irqwork);
-err_gpio_dir:
-	if (gpio_is_valid(lp->slp_tr))
-		gpio_free(lp->slp_tr);
-err_slp_tr:
-	gpio_free(lp->rstn);
-err_rstn:
-err_fill:
-	spi_set_drvdata(spi, NULL);
-	mutex_destroy(&lp->bmux);
-	ieee802154_free_device(lp->dev);
-	return rc;
-}
-
-static int __devexit at86rf230_remove(struct spi_device *spi)
-{
-	struct at86rf230_local *lp = spi_get_drvdata(spi);
-
-	ieee802154_unregister_device(lp->dev);
-
-	free_irq(spi->irq, lp);
-	flush_work(&lp->irqwork);
-
-	if (gpio_is_valid(lp->slp_tr))
-		gpio_free(lp->slp_tr);
-	gpio_free(lp->rstn);
-
-	spi_set_drvdata(spi, NULL);
-	mutex_destroy(&lp->bmux);
-	ieee802154_free_device(lp->dev);
-
-	dev_dbg(&spi->dev, "unregistered at86rf230\n");
-	return 0;
-}
-
-static struct spi_driver at86rf230_driver = {
-	.driver = {
-		.name	= "at86rf230",
-		.owner	= THIS_MODULE,
-	},
-	.probe      = at86rf230_probe,
-	.remove     = __devexit_p(at86rf230_remove),
-	.suspend    = at86rf230_suspend,
-	.resume     = at86rf230_resume,
-};
-
-static int __init at86rf230_init(void)
-{
-	return spi_register_driver(&at86rf230_driver);
-}
-module_init(at86rf230_init);
-
-static void __exit at86rf230_exit(void)
-{
-	spi_unregister_driver(&at86rf230_driver);
-}
-module_exit(at86rf230_exit);
-
-MODULE_DESCRIPTION("AT86RF230 Transceiver Driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/ieee802154/fakehard.c b/drivers/ieee802154/fakehard.c
deleted file mode 100644
index 73d4531..0000000
--- a/drivers/ieee802154/fakehard.c
+++ /dev/null
@@ -1,449 +0,0 @@
-/*
- * Sample driver for HardMAC IEEE 802.15.4 devices
- *
- * Copyright (C) 2009 Siemens AG
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You 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.
- *
- * Written by:
- * Dmitry Eremin-Solenikov <dmitry.baryshkov@siemens.com>
- */
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/netdevice.h>
-#include <linux/skbuff.h>
-#include <linux/if_arp.h>
-
-#include <net/af_ieee802154.h>
-#include <net/ieee802154_netdev.h>
-#include <net/ieee802154.h>
-#include <net/nl802154.h>
-#include <net/wpan-phy.h>
-
-struct fakehard_priv {
-	struct wpan_phy *phy;
-};
-
-static struct wpan_phy *fake_to_phy(const struct net_device *dev)
-{
-	struct fakehard_priv *priv = netdev_priv(dev);
-	return priv->phy;
-}
-
-/**
- * fake_get_phy - Return a phy corresponding to this device.
- * @dev: The network device for which to return the wan-phy object
- *
- * This function returns a wpan-phy object corresponding to the passed
- * network device. Reference counter for wpan-phy object is incremented,
- * so when the wpan-phy isn't necessary, you should drop the reference
- * via @wpan_phy_put() call.
- */
-static struct wpan_phy *fake_get_phy(const struct net_device *dev)
-{
-	struct wpan_phy *phy = fake_to_phy(dev);
-	return to_phy(get_device(&phy->dev));
-}
-
-/**
- * fake_get_pan_id - Retrieve the PAN ID of the device.
- * @dev: The network device to retrieve the PAN of.
- *
- * Return the ID of the PAN from the PIB.
- */
-static u16 fake_get_pan_id(const struct net_device *dev)
-{
-	BUG_ON(dev->type != ARPHRD_IEEE802154);
-
-	return 0xeba1;
-}
-
-/**
- * fake_get_short_addr - Retrieve the short address of the device.
- * @dev: The network device to retrieve the short address of.
- *
- * Returns the IEEE 802.15.4 short-form address cached for this
- * device. If the device has not yet had a short address assigned
- * then this should return 0xFFFF to indicate a lack of association.
- */
-static u16 fake_get_short_addr(const struct net_device *dev)
-{
-	BUG_ON(dev->type != ARPHRD_IEEE802154);
-
-	return 0x1;
-}
-
-/**
- * fake_get_dsn - Retrieve the DSN of the device.
- * @dev: The network device to retrieve the DSN for.
- *
- * Returns the IEEE 802.15.4 DSN for the network device.
- * The DSN is the sequence number which will be added to each
- * packet or MAC command frame by the MAC during transmission.
- *
- * DSN means 'Data Sequence Number'.
- *
- * Note: This is in section 7.2.1.2 of the IEEE 802.15.4-2006
- *       document.
- */
-static u8 fake_get_dsn(const struct net_device *dev)
-{
-	BUG_ON(dev->type != ARPHRD_IEEE802154);
-
-	return 0x00; /* DSN are implemented in HW, so return just 0 */
-}
-
-/**
- * fake_get_bsn - Retrieve the BSN of the device.
- * @dev: The network device to retrieve the BSN for.
- *
- * Returns the IEEE 802.15.4 BSN for the network device.
- * The BSN is the sequence number which will be added to each
- * beacon frame sent by the MAC.
- *
- * BSN means 'Beacon Sequence Number'.
- *
- * Note: This is in section 7.2.1.2 of the IEEE 802.15.4-2006
- *       document.
- */
-static u8 fake_get_bsn(const struct net_device *dev)
-{
-	BUG_ON(dev->type != ARPHRD_IEEE802154);
-
-	return 0x00; /* BSN are implemented in HW, so return just 0 */
-}
-
-/**
- * fake_assoc_req - Make an association request to the HW.
- * @dev: The network device which we are associating to a network.
- * @addr: The coordinator with which we wish to associate.
- * @channel: The channel on which to associate.
- * @cap: The capability information field to use in the association.
- *
- * Start an association with a coordinator. The coordinator's address
- * and PAN ID can be found in @addr.
- *
- * Note: This is in section 7.3.1 and 7.5.3.1 of the IEEE
- *       802.15.4-2006 document.
- */
-static int fake_assoc_req(struct net_device *dev,
-		struct ieee802154_addr *addr, u8 channel, u8 page, u8 cap)
-{
-	struct wpan_phy *phy = fake_to_phy(dev);
-
-	mutex_lock(&phy->pib_lock);
-	phy->current_channel = channel;
-	phy->current_page = page;
-	mutex_unlock(&phy->pib_lock);
-
-	/* We simply emulate it here */
-	return ieee802154_nl_assoc_confirm(dev, fake_get_short_addr(dev),
-			IEEE802154_SUCCESS);
-}
-
-/**
- * fake_assoc_resp - Send an association response to a device.
- * @dev: The network device on which to send the response.
- * @addr: The address of the device to respond to.
- * @short_addr: The assigned short address for the device (if any).
- * @status: The result of the association request.
- *
- * Queue the association response of the coordinator to another
- * device's attempt to associate with the network which we
- * coordinate. This is then added to the indirect-send queue to be
- * transmitted to the end device when it polls for data.
- *
- * Note: This is in section 7.3.2 and 7.5.3.1 of the IEEE
- *       802.15.4-2006 document.
- */
-static int fake_assoc_resp(struct net_device *dev,
-		struct ieee802154_addr *addr, u16 short_addr, u8 status)
-{
-	return 0;
-}
-
-/**
- * fake_disassoc_req - Disassociate a device from a network.
- * @dev: The network device on which we're disassociating a device.
- * @addr: The device to disassociate from the network.
- * @reason: The reason to give to the device for being disassociated.
- *
- * This sends a disassociation notification to the device being
- * disassociated from the network.
- *
- * Note: This is in section 7.5.3.2 of the IEEE 802.15.4-2006
- *       document, with the reason described in 7.3.3.2.
- */
-static int fake_disassoc_req(struct net_device *dev,
-		struct ieee802154_addr *addr, u8 reason)
-{
-	return ieee802154_nl_disassoc_confirm(dev, IEEE802154_SUCCESS);
-}
-
-/**
- * fake_start_req - Start an IEEE 802.15.4 PAN.
- * @dev: The network device on which to start the PAN.
- * @addr: The coordinator address to use when starting the PAN.
- * @channel: The channel on which to start the PAN.
- * @bcn_ord: Beacon order.
- * @sf_ord: Superframe order.
- * @pan_coord: Whether or not we are the PAN coordinator or just
- *             requesting a realignment perhaps?
- * @blx: Battery Life Extension feature bitfield.
- * @coord_realign: Something to realign something else.
- *
- * If pan_coord is non-zero then this starts a network with the
- * provided parameters, otherwise it attempts a coordinator
- * realignment of the stated network instead.
- *
- * Note: This is in section 7.5.2.3 of the IEEE 802.15.4-2006
- * document, with 7.3.8 describing coordinator realignment.
- */
-static int fake_start_req(struct net_device *dev, struct ieee802154_addr *addr,
-				u8 channel, u8 page,
-				u8 bcn_ord, u8 sf_ord, u8 pan_coord, u8 blx,
-				u8 coord_realign)
-{
-	struct wpan_phy *phy = fake_to_phy(dev);
-
-	mutex_lock(&phy->pib_lock);
-	phy->current_channel = channel;
-	phy->current_page = page;
-	mutex_unlock(&phy->pib_lock);
-
-	/* We don't emulate beacons here at all, so START should fail */
-	ieee802154_nl_start_confirm(dev, IEEE802154_INVALID_PARAMETER);
-	return 0;
-}
-
-/**
- * fake_scan_req - Start a channel scan.
- * @dev: The network device on which to perform a channel scan.
- * @type: The type of scan to perform.
- * @channels: The channel bitmask to scan.
- * @duration: How long to spend on each channel.
- *
- * This starts either a passive (energy) scan or an active (PAN) scan
- * on the channels indicated in the @channels bitmask. The duration of
- * the scan is measured in terms of superframe duration. Specifically,
- * the scan will spend aBaseSuperFrameDuration * ((2^n) + 1) on each
- * channel.
- *
- * Note: This is in section 7.5.2.1 of the IEEE 802.15.4-2006 document.
- */
-static int fake_scan_req(struct net_device *dev, u8 type, u32 channels,
-		u8 page, u8 duration)
-{
-	u8 edl[27] = {};
-	return ieee802154_nl_scan_confirm(dev, IEEE802154_SUCCESS, type,
-			channels, page,
-			type == IEEE802154_MAC_SCAN_ED ? edl : NULL);
-}
-
-static struct ieee802154_mlme_ops fake_mlme = {
-	.assoc_req = fake_assoc_req,
-	.assoc_resp = fake_assoc_resp,
-	.disassoc_req = fake_disassoc_req,
-	.start_req = fake_start_req,
-	.scan_req = fake_scan_req,
-
-	.get_phy = fake_get_phy,
-
-	.get_pan_id = fake_get_pan_id,
-	.get_short_addr = fake_get_short_addr,
-	.get_dsn = fake_get_dsn,
-	.get_bsn = fake_get_bsn,
-};
-
-static int ieee802154_fake_open(struct net_device *dev)
-{
-	netif_start_queue(dev);
-	return 0;
-}
-
-static int ieee802154_fake_close(struct net_device *dev)
-{
-	netif_stop_queue(dev);
-	return 0;
-}
-
-static netdev_tx_t ieee802154_fake_xmit(struct sk_buff *skb,
-					      struct net_device *dev)
-{
-	dev->stats.tx_packets++;
-	dev->stats.tx_bytes += skb->len;
-
-	/* FIXME: do hardware work here ... */
-
-	dev_kfree_skb(skb);
-	return NETDEV_TX_OK;
-}
-
-
-static int ieee802154_fake_ioctl(struct net_device *dev, struct ifreq *ifr,
-		int cmd)
-{
-	struct sockaddr_ieee802154 *sa =
-		(struct sockaddr_ieee802154 *)&ifr->ifr_addr;
-	u16 pan_id, short_addr;
-
-	switch (cmd) {
-	case SIOCGIFADDR:
-		/* FIXME: fixed here, get from device IRL */
-		pan_id = fake_get_pan_id(dev);
-		short_addr = fake_get_short_addr(dev);
-		if (pan_id == IEEE802154_PANID_BROADCAST ||
-		    short_addr == IEEE802154_ADDR_BROADCAST)
-			return -EADDRNOTAVAIL;
-
-		sa->family = AF_IEEE802154;
-		sa->addr.addr_type = IEEE802154_ADDR_SHORT;
-		sa->addr.pan_id = pan_id;
-		sa->addr.short_addr = short_addr;
-		return 0;
-	}
-	return -ENOIOCTLCMD;
-}
-
-static int ieee802154_fake_mac_addr(struct net_device *dev, void *p)
-{
-	return -EBUSY; /* HW address is built into the device */
-}
-
-static const struct net_device_ops fake_ops = {
-	.ndo_open		= ieee802154_fake_open,
-	.ndo_stop		= ieee802154_fake_close,
-	.ndo_start_xmit		= ieee802154_fake_xmit,
-	.ndo_do_ioctl		= ieee802154_fake_ioctl,
-	.ndo_set_mac_address	= ieee802154_fake_mac_addr,
-};
-
-static void ieee802154_fake_destruct(struct net_device *dev)
-{
-	struct wpan_phy *phy = fake_to_phy(dev);
-
-	wpan_phy_unregister(phy);
-	free_netdev(dev);
-	wpan_phy_free(phy);
-}
-
-static void ieee802154_fake_setup(struct net_device *dev)
-{
-	dev->addr_len		= IEEE802154_ADDR_LEN;
-	memset(dev->broadcast, 0xff, IEEE802154_ADDR_LEN);
-	dev->features		= NETIF_F_HW_CSUM;
-	dev->needed_tailroom	= 2; /* FCS */
-	dev->mtu		= 127;
-	dev->tx_queue_len	= 10;
-	dev->type		= ARPHRD_IEEE802154;
-	dev->flags		= IFF_NOARP | IFF_BROADCAST;
-	dev->watchdog_timeo	= 0;
-	dev->destructor		= ieee802154_fake_destruct;
-}
-
-
-static int __devinit ieee802154fake_probe(struct platform_device *pdev)
-{
-	struct net_device *dev;
-	struct fakehard_priv *priv;
-	struct wpan_phy *phy = wpan_phy_alloc(0);
-	int err;
-
-	if (!phy)
-		return -ENOMEM;
-
-	dev = alloc_netdev(sizeof(struct fakehard_priv), "hardwpan%d", ieee802154_fake_setup);
-	if (!dev) {
-		wpan_phy_free(phy);
-		return -ENOMEM;
-	}
-
-	memcpy(dev->dev_addr, "\xba\xbe\xca\xfe\xde\xad\xbe\xef",
-			dev->addr_len);
-	memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
-
-	/*
-	 * For now we'd like to emulate 2.4 GHz-only device,
-	 * both O-QPSK and CSS
-	 */
-	/* 2.4 GHz O-QPSK 802.15.4-2003 */
-	phy->channels_supported[0] |= 0x7FFF800;
-	/* 2.4 GHz CSS 802.15.4a-2007 */
-	phy->channels_supported[3] |= 0x3fff;
-
-	phy->transmit_power = 0xbf;
-
-	dev->netdev_ops = &fake_ops;
-	dev->ml_priv = &fake_mlme;
-
-	priv = netdev_priv(dev);
-	priv->phy = phy;
-
-	wpan_phy_set_dev(phy, &pdev->dev);
-	SET_NETDEV_DEV(dev, &phy->dev);
-
-	platform_set_drvdata(pdev, dev);
-
-	err = wpan_phy_register(phy);
-	if (err)
-		goto out;
-
-	err = register_netdev(dev);
-	if (err < 0)
-		goto out;
-
-	dev_info(&pdev->dev, "Added ieee802154 HardMAC hardware\n");
-	return 0;
-
-out:
-	unregister_netdev(dev);
-	return err;
-}
-
-static int __devexit ieee802154fake_remove(struct platform_device *pdev)
-{
-	struct net_device *dev = platform_get_drvdata(pdev);
-	unregister_netdev(dev);
-	return 0;
-}
-
-static struct platform_device *ieee802154fake_dev;
-
-static struct platform_driver ieee802154fake_driver = {
-	.probe = ieee802154fake_probe,
-	.remove = __devexit_p(ieee802154fake_remove),
-	.driver = {
-			.name = "ieee802154hardmac",
-			.owner = THIS_MODULE,
-	},
-};
-
-static __init int fake_init(void)
-{
-	ieee802154fake_dev = platform_device_register_simple(
-			"ieee802154hardmac", -1, NULL, 0);
-	return platform_driver_register(&ieee802154fake_driver);
-}
-
-static __exit void fake_exit(void)
-{
-	platform_driver_unregister(&ieee802154fake_driver);
-	platform_device_unregister(ieee802154fake_dev);
-}
-
-module_init(fake_init);
-module_exit(fake_exit);
-MODULE_LICENSE("GPL");
-
diff --git a/drivers/ieee802154/fakelb.c b/drivers/ieee802154/fakelb.c
deleted file mode 100644
index e7456fc..0000000
--- a/drivers/ieee802154/fakelb.c
+++ /dev/null
@@ -1,294 +0,0 @@
-/*
- * Loopback IEEE 802.15.4 interface
- *
- * Copyright 2007-2012 Siemens AG
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You 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.
- *
- * Written by:
- * Sergey Lapin <slapin@ossfans.org>
- * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
- * Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
- */
-
-#include <linux/module.h>
-#include <linux/timer.h>
-#include <linux/platform_device.h>
-#include <linux/netdevice.h>
-#include <linux/spinlock.h>
-#include <net/mac802154.h>
-#include <net/wpan-phy.h>
-
-static int numlbs = 1;
-
-struct fakelb_dev_priv {
-	struct ieee802154_dev *dev;
-
-	struct list_head list;
-	struct fakelb_priv *fake;
-
-	spinlock_t lock;
-	bool working;
-};
-
-struct fakelb_priv {
-	struct list_head list;
-	rwlock_t lock;
-};
-
-static int
-fakelb_hw_ed(struct ieee802154_dev *dev, u8 *level)
-{
-	might_sleep();
-	BUG_ON(!level);
-	*level = 0xbe;
-
-	return 0;
-}
-
-static int
-fakelb_hw_channel(struct ieee802154_dev *dev, int page, int channel)
-{
-	pr_debug("set channel to %d\n", channel);
-
-	might_sleep();
-	dev->phy->current_page = page;
-	dev->phy->current_channel = channel;
-
-	return 0;
-}
-
-static void
-fakelb_hw_deliver(struct fakelb_dev_priv *priv, struct sk_buff *skb)
-{
-	struct sk_buff *newskb;
-
-	spin_lock(&priv->lock);
-	if (priv->working) {
-		newskb = pskb_copy(skb, GFP_ATOMIC);
-		ieee802154_rx_irqsafe(priv->dev, newskb, 0xcc);
-	}
-	spin_unlock(&priv->lock);
-}
-
-static int
-fakelb_hw_xmit(struct ieee802154_dev *dev, struct sk_buff *skb)
-{
-	struct fakelb_dev_priv *priv = dev->priv;
-	struct fakelb_priv *fake = priv->fake;
-
-	might_sleep();
-
-	read_lock_bh(&fake->lock);
-	if (priv->list.next == priv->list.prev) {
-		/* we are the only one device */
-		fakelb_hw_deliver(priv, skb);
-	} else {
-		struct fakelb_dev_priv *dp;
-		list_for_each_entry(dp, &priv->fake->list, list) {
-			if (dp != priv &&
-			    (dp->dev->phy->current_channel ==
-			     priv->dev->phy->current_channel))
-				fakelb_hw_deliver(dp, skb);
-		}
-	}
-	read_unlock_bh(&fake->lock);
-
-	return 0;
-}
-
-static int
-fakelb_hw_start(struct ieee802154_dev *dev) {
-	struct fakelb_dev_priv *priv = dev->priv;
-	int ret = 0;
-
-	spin_lock(&priv->lock);
-	if (priv->working)
-		ret = -EBUSY;
-	else
-		priv->working = 1;
-	spin_unlock(&priv->lock);
-
-	return ret;
-}
-
-static void
-fakelb_hw_stop(struct ieee802154_dev *dev) {
-	struct fakelb_dev_priv *priv = dev->priv;
-
-	spin_lock(&priv->lock);
-	priv->working = 0;
-	spin_unlock(&priv->lock);
-}
-
-static struct ieee802154_ops fakelb_ops = {
-	.owner = THIS_MODULE,
-	.xmit = fakelb_hw_xmit,
-	.ed = fakelb_hw_ed,
-	.set_channel = fakelb_hw_channel,
-	.start = fakelb_hw_start,
-	.stop = fakelb_hw_stop,
-};
-
-/* Number of dummy devices to be set up by this module. */
-module_param(numlbs, int, 0);
-MODULE_PARM_DESC(numlbs, " number of pseudo devices");
-
-static int fakelb_add_one(struct device *dev, struct fakelb_priv *fake)
-{
-	struct fakelb_dev_priv *priv;
-	int err;
-	struct ieee802154_dev *ieee;
-
-	ieee = ieee802154_alloc_device(sizeof(*priv), &fakelb_ops);
-	if (!ieee)
-		return -ENOMEM;
-
-	priv = ieee->priv;
-	priv->dev = ieee;
-
-	/* 868 MHz BPSK	802.15.4-2003 */
-	ieee->phy->channels_supported[0] |= 1;
-	/* 915 MHz BPSK	802.15.4-2003 */
-	ieee->phy->channels_supported[0] |= 0x7fe;
-	/* 2.4 GHz O-QPSK 802.15.4-2003 */
-	ieee->phy->channels_supported[0] |= 0x7FFF800;
-	/* 868 MHz ASK 802.15.4-2006 */
-	ieee->phy->channels_supported[1] |= 1;
-	/* 915 MHz ASK 802.15.4-2006 */
-	ieee->phy->channels_supported[1] |= 0x7fe;
-	/* 868 MHz O-QPSK 802.15.4-2006 */
-	ieee->phy->channels_supported[2] |= 1;
-	/* 915 MHz O-QPSK 802.15.4-2006 */
-	ieee->phy->channels_supported[2] |= 0x7fe;
-	/* 2.4 GHz CSS 802.15.4a-2007 */
-	ieee->phy->channels_supported[3] |= 0x3fff;
-	/* UWB Sub-gigahertz 802.15.4a-2007 */
-	ieee->phy->channels_supported[4] |= 1;
-	/* UWB Low band 802.15.4a-2007 */
-	ieee->phy->channels_supported[4] |= 0x1e;
-	/* UWB High band 802.15.4a-2007 */
-	ieee->phy->channels_supported[4] |= 0xffe0;
-	/* 750 MHz O-QPSK 802.15.4c-2009 */
-	ieee->phy->channels_supported[5] |= 0xf;
-	/* 750 MHz MPSK 802.15.4c-2009 */
-	ieee->phy->channels_supported[5] |= 0xf0;
-	/* 950 MHz BPSK 802.15.4d-2009 */
-	ieee->phy->channels_supported[6] |= 0x3ff;
-	/* 950 MHz GFSK 802.15.4d-2009 */
-	ieee->phy->channels_supported[6] |= 0x3ffc00;
-
-	INIT_LIST_HEAD(&priv->list);
-	priv->fake = fake;
-
-	spin_lock_init(&priv->lock);
-
-	ieee->parent = dev;
-
-	err = ieee802154_register_device(ieee);
-	if (err)
-		goto err_reg;
-
-	write_lock_bh(&fake->lock);
-	list_add_tail(&priv->list, &fake->list);
-	write_unlock_bh(&fake->lock);
-
-	return 0;
-
-err_reg:
-	ieee802154_free_device(priv->dev);
-	return err;
-}
-
-static void fakelb_del(struct fakelb_dev_priv *priv)
-{
-	write_lock_bh(&priv->fake->lock);
-	list_del(&priv->list);
-	write_unlock_bh(&priv->fake->lock);
-
-	ieee802154_unregister_device(priv->dev);
-	ieee802154_free_device(priv->dev);
-}
-
-static int __devinit fakelb_probe(struct platform_device *pdev)
-{
-	struct fakelb_priv *priv;
-	struct fakelb_dev_priv *dp;
-	int err = -ENOMEM;
-	int i;
-
-	priv = kzalloc(sizeof(struct fakelb_priv), GFP_KERNEL);
-	if (!priv)
-		goto err_alloc;
-
-	INIT_LIST_HEAD(&priv->list);
-	rwlock_init(&priv->lock);
-
-	for (i = 0; i < numlbs; i++) {
-		err = fakelb_add_one(&pdev->dev, priv);
-		if (err < 0)
-			goto err_slave;
-	}
-
-	platform_set_drvdata(pdev, priv);
-	dev_info(&pdev->dev, "added ieee802154 hardware\n");
-	return 0;
-
-err_slave:
-	list_for_each_entry(dp, &priv->list, list)
-		fakelb_del(dp);
-	kfree(priv);
-err_alloc:
-	return err;
-}
-
-static int __devexit fakelb_remove(struct platform_device *pdev)
-{
-	struct fakelb_priv *priv = platform_get_drvdata(pdev);
-	struct fakelb_dev_priv *dp, *temp;
-
-	list_for_each_entry_safe(dp, temp, &priv->list, list)
-		fakelb_del(dp);
-	kfree(priv);
-
-	return 0;
-}
-
-static struct platform_device *ieee802154fake_dev;
-
-static struct platform_driver ieee802154fake_driver = {
-	.probe = fakelb_probe,
-	.remove = __devexit_p(fakelb_remove),
-	.driver = {
-			.name = "ieee802154fakelb",
-			.owner = THIS_MODULE,
-	},
-};
-
-static __init int fakelb_init_module(void)
-{
-	ieee802154fake_dev = platform_device_register_simple(
-			     "ieee802154fakelb", -1, NULL, 0);
-	return platform_driver_register(&ieee802154fake_driver);
-}
-
-static __exit void fake_remove_module(void)
-{
-	platform_driver_unregister(&ieee802154fake_driver);
-	platform_device_unregister(ieee802154fake_dev);
-}
-
-module_init(fakelb_init_module);
-module_exit(fake_remove_module);
-MODULE_LICENSE("GPL");
diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig
index d4984c8..6e3f143 100644
--- a/drivers/iio/Kconfig
+++ b/drivers/iio/Kconfig
@@ -1,5 +1,5 @@
 #
-# Industrial I/O subsytem configuration
+# Industrial I/O subsystem configuration
 #
 
 menuconfig IIO
@@ -54,10 +54,15 @@ config IIO_CONSUMERS_PER_TRIGGER
 	This value controls the maximum number of consumers that a
 	given trigger may handle. Default is 2.
 
+source "drivers/iio/accel/Kconfig"
 source "drivers/iio/adc/Kconfig"
 source "drivers/iio/amplifiers/Kconfig"
 source "drivers/iio/light/Kconfig"
 source "drivers/iio/frequency/Kconfig"
 source "drivers/iio/dac/Kconfig"
+source "drivers/iio/common/Kconfig"
+source "drivers/iio/gyro/Kconfig"
+source "drivers/iio/light/Kconfig"
+source "drivers/iio/magnetometer/Kconfig"
 
 endif # IIO
diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile
index 34309ab..f7fa3c0 100644
--- a/drivers/iio/Makefile
+++ b/drivers/iio/Makefile
@@ -10,8 +10,13 @@ industrialio-$(CONFIG_IIO_TRIGGER) += industrialio-trigger.o
 obj-$(CONFIG_IIO_TRIGGERED_BUFFER) += industrialio-triggered-buffer.o
 obj-$(CONFIG_IIO_KFIFO_BUF) += kfifo_buf.o
 
+obj-y += accel/
 obj-y += adc/
 obj-y += amplifiers/
 obj-y += light/
 obj-y += frequency/
 obj-y += dac/
+obj-y += common/
+obj-y += gyro/
+obj-y += light/
+obj-y += magnetometer/
diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig
new file mode 100644
index 0000000..b2510c4
--- /dev/null
+++ b/drivers/iio/accel/Kconfig
@@ -0,0 +1,16 @@
+#
+# Accelerometer drivers
+#
+menu "Accelerometers"
+
+config HID_SENSOR_ACCEL_3D
+	depends on HID_SENSOR_HUB
+	select IIO_BUFFER
+	select IIO_TRIGGERED_BUFFER
+	select HID_SENSOR_IIO_COMMON
+	tristate "HID Acelerometers 3D"
+	help
+	  Say yes here to build support for the HID SENSOR
+	  accelerometers 3D.
+
+endmenu
diff --git a/drivers/iio/accel/Makefile b/drivers/iio/accel/Makefile
new file mode 100644
index 0000000..5bc6855
--- /dev/null
+++ b/drivers/iio/accel/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for industrial I/O accelerometer drivers
+#
+
+obj-$(CONFIG_HID_SENSOR_ACCEL_3D) += hid-sensor-accel-3d.o
diff --git a/drivers/iio/accel/hid-sensor-accel-3d.c b/drivers/iio/accel/hid-sensor-accel-3d.c
new file mode 100644
index 0000000..314a405
--- /dev/null
+++ b/drivers/iio/accel/hid-sensor-accel-3d.c
@@ -0,0 +1,418 @@
+/*
+ * HID Sensors Driver
+ * Copyright (c) 2012, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/slab.h>
+#include <linux/hid-sensor-hub.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
+#include "../common/hid-sensors/hid-sensor-attributes.h"
+#include "../common/hid-sensors/hid-sensor-trigger.h"
+
+/*Format: HID-SENSOR-usage_id_in_hex*/
+/*Usage ID from spec for Accelerometer-3D: 0x200073*/
+#define DRIVER_NAME "HID-SENSOR-200073"
+
+enum accel_3d_channel {
+	CHANNEL_SCAN_INDEX_X,
+	CHANNEL_SCAN_INDEX_Y,
+	CHANNEL_SCAN_INDEX_Z,
+	ACCEL_3D_CHANNEL_MAX,
+};
+
+struct accel_3d_state {
+	struct hid_sensor_hub_callbacks callbacks;
+	struct hid_sensor_iio_common common_attributes;
+	struct hid_sensor_hub_attribute_info accel[ACCEL_3D_CHANNEL_MAX];
+	u32 accel_val[ACCEL_3D_CHANNEL_MAX];
+};
+
+static const u32 accel_3d_addresses[ACCEL_3D_CHANNEL_MAX] = {
+	HID_USAGE_SENSOR_ACCEL_X_AXIS,
+	HID_USAGE_SENSOR_ACCEL_Y_AXIS,
+	HID_USAGE_SENSOR_ACCEL_Z_AXIS
+};
+
+/* Channel definitions */
+static const struct iio_chan_spec accel_3d_channels[] = {
+	{
+		.type = IIO_ACCEL,
+		.modified = 1,
+		.channel2 = IIO_MOD_X,
+		.info_mask = IIO_CHAN_INFO_OFFSET_SHARED_BIT |
+		IIO_CHAN_INFO_SCALE_SHARED_BIT |
+		IIO_CHAN_INFO_SAMP_FREQ_SHARED_BIT |
+		IIO_CHAN_INFO_HYSTERESIS_SHARED_BIT,
+		.scan_index = CHANNEL_SCAN_INDEX_X,
+	}, {
+		.type = IIO_ACCEL,
+		.modified = 1,
+		.channel2 = IIO_MOD_Y,
+		.info_mask = IIO_CHAN_INFO_OFFSET_SHARED_BIT |
+		IIO_CHAN_INFO_SCALE_SHARED_BIT |
+		IIO_CHAN_INFO_SAMP_FREQ_SHARED_BIT |
+		IIO_CHAN_INFO_HYSTERESIS_SHARED_BIT,
+		.scan_index = CHANNEL_SCAN_INDEX_Y,
+	}, {
+		.type = IIO_ACCEL,
+		.modified = 1,
+		.channel2 = IIO_MOD_Z,
+		.info_mask = IIO_CHAN_INFO_OFFSET_SHARED_BIT |
+		IIO_CHAN_INFO_SCALE_SHARED_BIT |
+		IIO_CHAN_INFO_SAMP_FREQ_SHARED_BIT |
+		IIO_CHAN_INFO_HYSTERESIS_SHARED_BIT,
+		.scan_index = CHANNEL_SCAN_INDEX_Z,
+	}
+};
+
+/* Adjust channel real bits based on report descriptor */
+static void accel_3d_adjust_channel_bit_mask(struct iio_chan_spec *channels,
+						int channel, int size)
+{
+	channels[channel].scan_type.sign = 's';
+	/* Real storage bits will change based on the report desc. */
+	channels[channel].scan_type.realbits = size * 8;
+	/* Maximum size of a sample to capture is u32 */
+	channels[channel].scan_type.storagebits = sizeof(u32) * 8;
+}
+
+/* Channel read_raw handler */
+static int accel_3d_read_raw(struct iio_dev *indio_dev,
+			      struct iio_chan_spec const *chan,
+			      int *val, int *val2,
+			      long mask)
+{
+	struct accel_3d_state *accel_state = iio_priv(indio_dev);
+	int report_id = -1;
+	u32 address;
+	int ret;
+	int ret_type;
+
+	*val = 0;
+	*val2 = 0;
+	switch (mask) {
+	case 0:
+		report_id = accel_state->accel[chan->scan_index].report_id;
+		address = accel_3d_addresses[chan->scan_index];
+		if (report_id >= 0)
+			*val = sensor_hub_input_attr_get_raw_value(
+				accel_state->common_attributes.hsdev,
+				HID_USAGE_SENSOR_ACCEL_3D, address,
+				report_id);
+		else {
+			*val = 0;
+			return -EINVAL;
+		}
+		ret_type = IIO_VAL_INT;
+		break;
+	case IIO_CHAN_INFO_SCALE:
+		*val = accel_state->accel[CHANNEL_SCAN_INDEX_X].units;
+		ret_type = IIO_VAL_INT;
+		break;
+	case IIO_CHAN_INFO_OFFSET:
+		*val = hid_sensor_convert_exponent(
+			accel_state->accel[CHANNEL_SCAN_INDEX_X].unit_expo);
+		ret_type = IIO_VAL_INT;
+		break;
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		ret = hid_sensor_read_samp_freq_value(
+			&accel_state->common_attributes, val, val2);
+		ret_type = IIO_VAL_INT_PLUS_MICRO;
+		break;
+	case IIO_CHAN_INFO_HYSTERESIS:
+		ret = hid_sensor_read_raw_hyst_value(
+			&accel_state->common_attributes, val, val2);
+		ret_type = IIO_VAL_INT_PLUS_MICRO;
+		break;
+	default:
+		ret_type = -EINVAL;
+		break;
+	}
+
+	return ret_type;
+}
+
+/* Channel write_raw handler */
+static int accel_3d_write_raw(struct iio_dev *indio_dev,
+			       struct iio_chan_spec const *chan,
+			       int val,
+			       int val2,
+			       long mask)
+{
+	struct accel_3d_state *accel_state = iio_priv(indio_dev);
+	int ret = 0;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		ret = hid_sensor_write_samp_freq_value(
+				&accel_state->common_attributes, val, val2);
+		break;
+	case IIO_CHAN_INFO_HYSTERESIS:
+		ret = hid_sensor_write_raw_hyst_value(
+				&accel_state->common_attributes, val, val2);
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static int accel_3d_write_raw_get_fmt(struct iio_dev *indio_dev,
+			       struct iio_chan_spec const *chan,
+			       long mask)
+{
+	return IIO_VAL_INT_PLUS_MICRO;
+}
+
+static const struct iio_info accel_3d_info = {
+	.driver_module = THIS_MODULE,
+	.read_raw = &accel_3d_read_raw,
+	.write_raw = &accel_3d_write_raw,
+	.write_raw_get_fmt = &accel_3d_write_raw_get_fmt,
+};
+
+/* Function to push data to buffer */
+static void hid_sensor_push_data(struct iio_dev *indio_dev, u8 *data, int len)
+{
+	struct iio_buffer *buffer = indio_dev->buffer;
+	int datum_sz;
+
+	dev_dbg(&indio_dev->dev, "hid_sensor_push_data\n");
+	if (!buffer) {
+		dev_err(&indio_dev->dev, "Buffer == NULL\n");
+		return;
+	}
+	datum_sz = buffer->access->get_bytes_per_datum(buffer);
+	if (len > datum_sz) {
+		dev_err(&indio_dev->dev, "Datum size mismatch %d:%d\n", len,
+				datum_sz);
+		return;
+	}
+	iio_push_to_buffer(buffer, (u8 *)data);
+}
+
+/* Callback handler to send event after all samples are received and captured */
+static int accel_3d_proc_event(struct hid_sensor_hub_device *hsdev,
+				unsigned usage_id,
+				void *priv)
+{
+	struct iio_dev *indio_dev = platform_get_drvdata(priv);
+	struct accel_3d_state *accel_state = iio_priv(indio_dev);
+
+	dev_dbg(&indio_dev->dev, "accel_3d_proc_event [%d]\n",
+				accel_state->common_attributes.data_ready);
+	if (accel_state->common_attributes.data_ready)
+		hid_sensor_push_data(indio_dev,
+				(u8 *)accel_state->accel_val,
+				sizeof(accel_state->accel_val));
+
+	return 0;
+}
+
+/* Capture samples in local storage */
+static int accel_3d_capture_sample(struct hid_sensor_hub_device *hsdev,
+				unsigned usage_id,
+				size_t raw_len, char *raw_data,
+				void *priv)
+{
+	struct iio_dev *indio_dev = platform_get_drvdata(priv);
+	struct accel_3d_state *accel_state = iio_priv(indio_dev);
+	int offset;
+	int ret = -EINVAL;
+
+	switch (usage_id) {
+	case HID_USAGE_SENSOR_ACCEL_X_AXIS:
+	case HID_USAGE_SENSOR_ACCEL_Y_AXIS:
+	case HID_USAGE_SENSOR_ACCEL_Z_AXIS:
+		offset = usage_id - HID_USAGE_SENSOR_ACCEL_X_AXIS;
+		accel_state->accel_val[CHANNEL_SCAN_INDEX_X + offset] =
+						*(u32 *)raw_data;
+		ret = 0;
+	break;
+	default:
+		break;
+	}
+
+	return ret;
+}
+
+/* Parse report which is specific to an usage id*/
+static int accel_3d_parse_report(struct platform_device *pdev,
+				struct hid_sensor_hub_device *hsdev,
+				struct iio_chan_spec *channels,
+				unsigned usage_id,
+				struct accel_3d_state *st)
+{
+	int ret;
+	int i;
+
+	for (i = 0; i <= CHANNEL_SCAN_INDEX_Z; ++i) {
+		ret = sensor_hub_input_get_attribute_info(hsdev,
+				HID_INPUT_REPORT,
+				usage_id,
+				HID_USAGE_SENSOR_ACCEL_X_AXIS + i,
+				&st->accel[CHANNEL_SCAN_INDEX_X + i]);
+		if (ret < 0)
+			break;
+		accel_3d_adjust_channel_bit_mask(channels,
+				CHANNEL_SCAN_INDEX_X + i,
+				st->accel[CHANNEL_SCAN_INDEX_X + i].size);
+	}
+	dev_dbg(&pdev->dev, "accel_3d %x:%x, %x:%x, %x:%x\n",
+			st->accel[0].index,
+			st->accel[0].report_id,
+			st->accel[1].index, st->accel[1].report_id,
+			st->accel[2].index, st->accel[2].report_id);
+
+	return ret;
+}
+
+/* Function to initialize the processing for usage id */
+static int __devinit hid_accel_3d_probe(struct platform_device *pdev)
+{
+	int ret = 0;
+	static const char *name = "accel_3d";
+	struct iio_dev *indio_dev;
+	struct accel_3d_state *accel_state;
+	struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
+	struct iio_chan_spec *channels;
+
+	indio_dev = iio_device_alloc(sizeof(struct accel_3d_state));
+	if (indio_dev == NULL) {
+		ret = -ENOMEM;
+		goto error_ret;
+	}
+	platform_set_drvdata(pdev, indio_dev);
+
+	accel_state = iio_priv(indio_dev);
+	accel_state->common_attributes.hsdev = hsdev;
+	accel_state->common_attributes.pdev = pdev;
+
+	ret = hid_sensor_parse_common_attributes(hsdev,
+					HID_USAGE_SENSOR_ACCEL_3D,
+					&accel_state->common_attributes);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to setup common attributes\n");
+		goto error_free_dev;
+	}
+
+	channels = kmemdup(accel_3d_channels,
+					sizeof(accel_3d_channels),
+					GFP_KERNEL);
+	if (!channels) {
+		dev_err(&pdev->dev, "failed to duplicate channels\n");
+		goto error_free_dev;
+	}
+
+	ret = accel_3d_parse_report(pdev, hsdev, channels,
+					HID_USAGE_SENSOR_ACCEL_3D, accel_state);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to setup attributes\n");
+		goto error_free_dev_mem;
+	}
+
+	indio_dev->channels = channels;
+	indio_dev->num_channels = ARRAY_SIZE(accel_3d_channels);
+	indio_dev->dev.parent = &pdev->dev;
+	indio_dev->info = &accel_3d_info;
+	indio_dev->name = name;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+
+	ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
+		NULL, NULL);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to initialize trigger buffer\n");
+		goto error_free_dev_mem;
+	}
+	accel_state->common_attributes.data_ready = false;
+	ret = hid_sensor_setup_trigger(indio_dev, name,
+					&accel_state->common_attributes);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "trigger setup failed\n");
+		goto error_unreg_buffer_funcs;
+	}
+
+	ret = iio_device_register(indio_dev);
+	if (ret) {
+		dev_err(&pdev->dev, "device register failed\n");
+		goto error_remove_trigger;
+	}
+
+	accel_state->callbacks.send_event = accel_3d_proc_event;
+	accel_state->callbacks.capture_sample = accel_3d_capture_sample;
+	accel_state->callbacks.pdev = pdev;
+	ret = sensor_hub_register_callback(hsdev, HID_USAGE_SENSOR_ACCEL_3D,
+					&accel_state->callbacks);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "callback reg failed\n");
+		goto error_iio_unreg;
+	}
+
+	return ret;
+
+error_iio_unreg:
+	iio_device_unregister(indio_dev);
+error_remove_trigger:
+	hid_sensor_remove_trigger(indio_dev);
+error_unreg_buffer_funcs:
+	iio_triggered_buffer_cleanup(indio_dev);
+error_free_dev_mem:
+	kfree(indio_dev->channels);
+error_free_dev:
+	iio_device_free(indio_dev);
+error_ret:
+	return ret;
+}
+
+/* Function to deinitialize the processing for usage id */
+static int __devinit hid_accel_3d_remove(struct platform_device *pdev)
+{
+	struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
+	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
+
+	sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_ACCEL_3D);
+	iio_device_unregister(indio_dev);
+	hid_sensor_remove_trigger(indio_dev);
+	iio_triggered_buffer_cleanup(indio_dev);
+	kfree(indio_dev->channels);
+	iio_device_free(indio_dev);
+
+	return 0;
+}
+
+static struct platform_driver hid_accel_3d_platform_driver = {
+	.driver = {
+		.name	= DRIVER_NAME,
+		.owner	= THIS_MODULE,
+	},
+	.probe		= hid_accel_3d_probe,
+	.remove		= hid_accel_3d_remove,
+};
+module_platform_driver(hid_accel_3d_platform_driver);
+
+MODULE_DESCRIPTION("HID Sensor Accel 3D");
+MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@intel.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 8a78b4f..03791a6 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -3,6 +3,11 @@
 #
 menu "Analog to digital converters"
 
+config AD_SIGMA_DELTA
+	tristate
+	select IIO_BUFFER
+	select IIO_TRIGGERED_BUFFER
+
 config AD7266
 	tristate "Analog Devices AD7265/AD7266 ADC driver"
 	depends on SPI_MASTER
@@ -13,6 +18,33 @@ config AD7266
 	  Say yes here to build support for Analog Devices AD7265 and AD7266
 	  ADCs.
 
+config AD7791
+	tristate "Analog Devices AD7791 ADC driver"
+	depends on SPI
+	select AD_SIGMA_DELTA
+	help
+	  Say yes here to build support for Analog Devices AD7787, AD7788, AD7789,
+	  AD7790 and AD7791 SPI analog to digital converters (ADC). If unsure, say
+	  N (but it is safe to say "Y").
+
+	  To compile this driver as a module, choose M here: the module will be
+	  called ad7791.
+
+config AD7476
+	tristate "Analog Devices AD7476 and similar 1-channel ADCs driver"
+	depends on SPI
+	select IIO_BUFFER
+	select IIO_TRIGGERED_BUFFER
+	help
+	  Say yes here to build support for Analog Devices AD7273, AD7274, AD7276,
+	  AD7277, AD7278, AD7475, AD7476, AD7477, AD7478, AD7466, AD7467, AD7468,
+	  AD7495, AD7910, AD7920, AD7920 SPI analog to digital converters (ADC).
+
+	  If unsure, say N (but it's safe to say "Y").
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ad7476.
+
 config AT91_ADC
 	tristate "Atmel AT91 ADC"
 	depends on ARCH_AT91
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index 52eec25..9824a70 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -2,5 +2,8 @@
 # Makefile for IIO ADC drivers
 #
 
+obj-$(CONFIG_AD_SIGMA_DELTA) += ad_sigma_delta.o
 obj-$(CONFIG_AD7266) += ad7266.o
+obj-$(CONFIG_AD7476) += ad7476.o
+obj-$(CONFIG_AD7791) += ad7791.o
 obj-$(CONFIG_AT91_ADC) += at91_adc.o
diff --git a/drivers/iio/adc/ad7266.c b/drivers/iio/adc/ad7266.c
index 5c3f1ba..b11f214 100644
--- a/drivers/iio/adc/ad7266.c
+++ b/drivers/iio/adc/ad7266.c
@@ -99,7 +99,7 @@ static irqreturn_t ad7266_trigger_handler(int irq, void *p)
 	if (ret == 0) {
 		if (indio_dev->scan_timestamp)
 			((s64 *)st->data)[1] = pf->timestamp;
-		iio_push_to_buffer(buffer, (u8 *)st->data, pf->timestamp);
+		iio_push_to_buffer(buffer, (u8 *)st->data);
 	}
 
 	iio_trigger_notify_done(indio_dev->trig);
diff --git a/drivers/iio/adc/ad7476.c b/drivers/iio/adc/ad7476.c
new file mode 100644
index 0000000..7f2f45a
--- /dev/null
+++ b/drivers/iio/adc/ad7476.c
@@ -0,0 +1,332 @@
+/*
+ * AD7466/7/8 AD7476/5/7/8 (A) SPI ADC driver
+ *
+ * Copyright 2010 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/sysfs.h>
+#include <linux/spi/spi.h>
+#include <linux/regulator/consumer.h>
+#include <linux/err.h>
+#include <linux/module.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
+
+#define RES_MASK(bits)	((1 << (bits)) - 1)
+
+struct ad7476_state;
+
+struct ad7476_chip_info {
+	unsigned int			int_vref_uv;
+	struct iio_chan_spec		channel[2];
+	void (*reset)(struct ad7476_state *);
+};
+
+struct ad7476_state {
+	struct spi_device		*spi;
+	const struct ad7476_chip_info	*chip_info;
+	struct regulator		*reg;
+	struct spi_transfer		xfer;
+	struct spi_message		msg;
+	/*
+	 * DMA (thus cache coherency maintenance) requires the
+	 * transfer buffers to live in their own cache lines.
+	 * Make the buffer large enough for one 16 bit sample and one 64 bit
+	 * aligned 64 bit timestamp.
+	 */
+	unsigned char data[ALIGN(2, sizeof(s64)) + sizeof(s64)]
+			____cacheline_aligned;
+};
+
+enum ad7476_supported_device_ids {
+	ID_AD7091R,
+	ID_AD7276,
+	ID_AD7277,
+	ID_AD7278,
+	ID_AD7466,
+	ID_AD7467,
+	ID_AD7468,
+	ID_AD7495,
+	ID_AD7940,
+};
+
+static irqreturn_t ad7476_trigger_handler(int irq, void  *p)
+{
+	struct iio_poll_func *pf = p;
+	struct iio_dev *indio_dev = pf->indio_dev;
+	struct ad7476_state *st = iio_priv(indio_dev);
+	s64 time_ns;
+	int b_sent;
+
+	b_sent = spi_sync(st->spi, &st->msg);
+	if (b_sent < 0)
+		goto done;
+
+	time_ns = iio_get_time_ns();
+
+	if (indio_dev->scan_timestamp)
+		((s64 *)st->data)[1] = time_ns;
+
+	iio_push_to_buffer(indio_dev->buffer, st->data);
+done:
+	iio_trigger_notify_done(indio_dev->trig);
+
+	return IRQ_HANDLED;
+}
+
+static void ad7091_reset(struct ad7476_state *st)
+{
+	/* Any transfers with 8 scl cycles will reset the device */
+	spi_read(st->spi, st->data, 1);
+}
+
+static int ad7476_scan_direct(struct ad7476_state *st)
+{
+	int ret;
+
+	ret = spi_sync(st->spi, &st->msg);
+	if (ret)
+		return ret;
+
+	return be16_to_cpup((__be16 *)st->data);
+}
+
+static int ad7476_read_raw(struct iio_dev *indio_dev,
+			   struct iio_chan_spec const *chan,
+			   int *val,
+			   int *val2,
+			   long m)
+{
+	int ret;
+	struct ad7476_state *st = iio_priv(indio_dev);
+	int scale_uv;
+
+	switch (m) {
+	case IIO_CHAN_INFO_RAW:
+		mutex_lock(&indio_dev->mlock);
+		if (iio_buffer_enabled(indio_dev))
+			ret = -EBUSY;
+		else
+			ret = ad7476_scan_direct(st);
+		mutex_unlock(&indio_dev->mlock);
+
+		if (ret < 0)
+			return ret;
+		*val = (ret >> st->chip_info->channel[0].scan_type.shift) &
+			RES_MASK(st->chip_info->channel[0].scan_type.realbits);
+		return IIO_VAL_INT;
+	case IIO_CHAN_INFO_SCALE:
+		if (!st->chip_info->int_vref_uv) {
+			scale_uv = regulator_get_voltage(st->reg);
+			if (scale_uv < 0)
+				return scale_uv;
+		} else {
+			scale_uv = st->chip_info->int_vref_uv;
+		}
+		scale_uv >>= chan->scan_type.realbits;
+		*val =  scale_uv / 1000;
+		*val2 = (scale_uv % 1000) * 1000;
+		return IIO_VAL_INT_PLUS_MICRO;
+	}
+	return -EINVAL;
+}
+
+#define _AD7476_CHAN(bits, _shift, _info_mask)			\
+	{							\
+	.type = IIO_VOLTAGE,					\
+	.indexed = 1,						\
+	.info_mask = _info_mask |				\
+	IIO_CHAN_INFO_SCALE_SHARED_BIT,				\
+	.scan_type = {						\
+		.sign = 'u',					\
+		.realbits = (bits),				\
+		.storagebits = 16,				\
+		.shift = (_shift),				\
+		.endianness = IIO_BE,				\
+	},							\
+}
+
+#define AD7476_CHAN(bits) _AD7476_CHAN((bits), 13 - (bits), \
+		IIO_CHAN_INFO_RAW_SEPARATE_BIT)
+#define AD7940_CHAN(bits) _AD7476_CHAN((bits), 15 - (bits), \
+		IIO_CHAN_INFO_RAW_SEPARATE_BIT)
+#define AD7091R_CHAN(bits) _AD7476_CHAN((bits), 16 - (bits), 0)
+
+static const struct ad7476_chip_info ad7476_chip_info_tbl[] = {
+	[ID_AD7091R] = {
+		.channel[0] = AD7091R_CHAN(12),
+		.channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1),
+		.reset = ad7091_reset,
+	},
+	[ID_AD7276] = {
+		.channel[0] = AD7940_CHAN(12),
+		.channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1),
+	},
+	[ID_AD7277] = {
+		.channel[0] = AD7940_CHAN(10),
+		.channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1),
+	},
+	[ID_AD7278] = {
+		.channel[0] = AD7940_CHAN(8),
+		.channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1),
+	},
+	[ID_AD7466] = {
+		.channel[0] = AD7476_CHAN(12),
+		.channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1),
+	},
+	[ID_AD7467] = {
+		.channel[0] = AD7476_CHAN(10),
+		.channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1),
+	},
+	[ID_AD7468] = {
+		.channel[0] = AD7476_CHAN(8),
+		.channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1),
+	},
+	[ID_AD7495] = {
+		.channel[0] = AD7476_CHAN(12),
+		.channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1),
+		.int_vref_uv = 2500000,
+	},
+	[ID_AD7940] = {
+		.channel[0] = AD7940_CHAN(14),
+		.channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1),
+	},
+};
+
+static const struct iio_info ad7476_info = {
+	.driver_module = THIS_MODULE,
+	.read_raw = &ad7476_read_raw,
+};
+
+static int __devinit ad7476_probe(struct spi_device *spi)
+{
+	struct ad7476_state *st;
+	struct iio_dev *indio_dev;
+	int ret;
+
+	indio_dev = iio_device_alloc(sizeof(*st));
+	if (indio_dev == NULL) {
+		ret = -ENOMEM;
+		goto error_ret;
+	}
+	st = iio_priv(indio_dev);
+	st->chip_info =
+		&ad7476_chip_info_tbl[spi_get_device_id(spi)->driver_data];
+
+	st->reg = regulator_get(&spi->dev, "vcc");
+	if (IS_ERR(st->reg)) {
+		ret = PTR_ERR(st->reg);
+		goto error_free_dev;
+	}
+
+	ret = regulator_enable(st->reg);
+	if (ret)
+		goto error_put_reg;
+
+	spi_set_drvdata(spi, indio_dev);
+
+	st->spi = spi;
+
+	/* Establish that the iio_dev is a child of the spi device */
+	indio_dev->dev.parent = &spi->dev;
+	indio_dev->name = spi_get_device_id(spi)->name;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->channels = st->chip_info->channel;
+	indio_dev->num_channels = 2;
+	indio_dev->info = &ad7476_info;
+	/* Setup default message */
+
+	st->xfer.rx_buf = &st->data;
+	st->xfer.len = st->chip_info->channel[0].scan_type.storagebits / 8;
+
+	spi_message_init(&st->msg);
+	spi_message_add_tail(&st->xfer, &st->msg);
+
+	ret = iio_triggered_buffer_setup(indio_dev, NULL,
+			&ad7476_trigger_handler, NULL);
+	if (ret)
+		goto error_disable_reg;
+
+	if (st->chip_info->reset)
+		st->chip_info->reset(st);
+
+	ret = iio_device_register(indio_dev);
+	if (ret)
+		goto error_ring_unregister;
+	return 0;
+
+error_ring_unregister:
+	iio_triggered_buffer_cleanup(indio_dev);
+error_disable_reg:
+	regulator_disable(st->reg);
+error_put_reg:
+	regulator_put(st->reg);
+error_free_dev:
+	iio_device_free(indio_dev);
+
+error_ret:
+	return ret;
+}
+
+static int __devexit ad7476_remove(struct spi_device *spi)
+{
+	struct iio_dev *indio_dev = spi_get_drvdata(spi);
+	struct ad7476_state *st = iio_priv(indio_dev);
+
+	iio_device_unregister(indio_dev);
+	iio_triggered_buffer_cleanup(indio_dev);
+	regulator_disable(st->reg);
+	regulator_put(st->reg);
+	iio_device_free(indio_dev);
+
+	return 0;
+}
+
+static const struct spi_device_id ad7476_id[] = {
+	{"ad7091r", ID_AD7091R},
+	{"ad7273", ID_AD7277},
+	{"ad7274", ID_AD7276},
+	{"ad7276", ID_AD7276},
+	{"ad7277", ID_AD7277},
+	{"ad7278", ID_AD7278},
+	{"ad7466", ID_AD7466},
+	{"ad7467", ID_AD7467},
+	{"ad7468", ID_AD7468},
+	{"ad7475", ID_AD7466},
+	{"ad7476", ID_AD7466},
+	{"ad7476a", ID_AD7466},
+	{"ad7477", ID_AD7467},
+	{"ad7477a", ID_AD7467},
+	{"ad7478", ID_AD7468},
+	{"ad7478a", ID_AD7468},
+	{"ad7495", ID_AD7495},
+	{"ad7910", ID_AD7467},
+	{"ad7920", ID_AD7466},
+	{"ad7940", ID_AD7940},
+	{}
+};
+MODULE_DEVICE_TABLE(spi, ad7476_id);
+
+static struct spi_driver ad7476_driver = {
+	.driver = {
+		.name	= "ad7476",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= ad7476_probe,
+	.remove		= __devexit_p(ad7476_remove),
+	.id_table	= ad7476_id,
+};
+module_spi_driver(ad7476_driver);
+
+MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
+MODULE_DESCRIPTION("Analog Devices AD7476 and similar 1-channel ADCs");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/adc/ad7791.c b/drivers/iio/adc/ad7791.c
new file mode 100644
index 0000000..e937408
--- /dev/null
+++ b/drivers/iio/adc/ad7791.c
@@ -0,0 +1,460 @@
+/*
+ * AD7787/AD7788/AD7789/AD7790/AD7791 SPI ADC driver
+ *
+ * Copyright 2012 Analog Devices Inc.
+ *  Author: Lars-Peter Clausen <lars@metafoo.de>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/sysfs.h>
+#include <linux/spi/spi.h>
+#include <linux/regulator/consumer.h>
+#include <linux/err.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
+#include <linux/iio/adc/ad_sigma_delta.h>
+
+#include <linux/platform_data/ad7791.h>
+
+#define AD7791_REG_COMM			0x0 /* For writes */
+#define AD7791_REG_STATUS		0x0 /* For reads */
+#define AD7791_REG_MODE			0x1
+#define AD7791_REG_FILTER		0x2
+#define AD7791_REG_DATA			0x3
+
+#define AD7791_MODE_CONTINUOUS		0x00
+#define AD7791_MODE_SINGLE		0x02
+#define AD7791_MODE_POWERDOWN		0x03
+
+#define AD7791_CH_AIN1P_AIN1N		0x00
+#define AD7791_CH_AIN2			0x01
+#define AD7791_CH_AIN1N_AIN1N		0x02
+#define AD7791_CH_AVDD_MONITOR		0x03
+
+#define AD7791_FILTER_CLK_DIV_1		(0x0 << 4)
+#define AD7791_FILTER_CLK_DIV_2		(0x1 << 4)
+#define AD7791_FILTER_CLK_DIV_4		(0x2 << 4)
+#define AD7791_FILTER_CLK_DIV_8		(0x3 << 4)
+#define AD7791_FILTER_CLK_MASK		(0x3 << 4)
+#define AD7791_FILTER_RATE_120		0x0
+#define AD7791_FILTER_RATE_100		0x1
+#define AD7791_FILTER_RATE_33_3		0x2
+#define AD7791_FILTER_RATE_20		0x3
+#define AD7791_FILTER_RATE_16_6		0x4
+#define AD7791_FILTER_RATE_16_7		0x5
+#define AD7791_FILTER_RATE_13_3		0x6
+#define AD7791_FILTER_RATE_9_5		0x7
+#define AD7791_FILTER_RATE_MASK		0x7
+
+#define AD7791_MODE_BUFFER		BIT(1)
+#define AD7791_MODE_UNIPOLAR		BIT(2)
+#define AD7791_MODE_BURNOUT		BIT(3)
+#define AD7791_MODE_SEL_MASK		(0x3 << 6)
+#define AD7791_MODE_SEL(x)		((x) << 6)
+
+#define DECLARE_AD7787_CHANNELS(name, bits, storagebits) \
+const struct iio_chan_spec name[] = { \
+	AD_SD_DIFF_CHANNEL(0, 0, 0, AD7791_CH_AIN1P_AIN1N, \
+		(bits), (storagebits), 0), \
+	AD_SD_CHANNEL(1, 1, AD7791_CH_AIN2, (bits), (storagebits), 0), \
+	AD_SD_SHORTED_CHANNEL(2, 0, AD7791_CH_AIN1N_AIN1N, \
+		(bits), (storagebits), 0), \
+	AD_SD_SUPPLY_CHANNEL(3, 2, AD7791_CH_AVDD_MONITOR,  \
+		(bits), (storagebits), 0), \
+	IIO_CHAN_SOFT_TIMESTAMP(4), \
+}
+
+#define DECLARE_AD7791_CHANNELS(name, bits, storagebits) \
+const struct iio_chan_spec name[] = { \
+	AD_SD_DIFF_CHANNEL(0, 0, 0, AD7791_CH_AIN1P_AIN1N, \
+		(bits), (storagebits), 0), \
+	AD_SD_SHORTED_CHANNEL(1, 0, AD7791_CH_AIN1N_AIN1N, \
+		(bits), (storagebits), 0), \
+	AD_SD_SUPPLY_CHANNEL(2, 1, AD7791_CH_AVDD_MONITOR, \
+		(bits), (storagebits), 0), \
+	IIO_CHAN_SOFT_TIMESTAMP(3), \
+}
+
+static DECLARE_AD7787_CHANNELS(ad7787_channels, 24, 32);
+static DECLARE_AD7791_CHANNELS(ad7790_channels, 16, 16);
+static DECLARE_AD7791_CHANNELS(ad7791_channels, 24, 32);
+
+enum {
+	AD7787,
+	AD7788,
+	AD7789,
+	AD7790,
+	AD7791,
+};
+
+enum ad7791_chip_info_flags {
+	AD7791_FLAG_HAS_FILTER		= (1 << 0),
+	AD7791_FLAG_HAS_BUFFER		= (1 << 1),
+	AD7791_FLAG_HAS_UNIPOLAR	= (1 << 2),
+	AD7791_FLAG_HAS_BURNOUT		= (1 << 3),
+};
+
+struct ad7791_chip_info {
+	const struct iio_chan_spec *channels;
+	unsigned int num_channels;
+	enum ad7791_chip_info_flags flags;
+};
+
+static const struct ad7791_chip_info ad7791_chip_infos[] = {
+	[AD7787] = {
+		.channels = ad7787_channels,
+		.num_channels = ARRAY_SIZE(ad7787_channels),
+		.flags = AD7791_FLAG_HAS_FILTER | AD7791_FLAG_HAS_BUFFER |
+			AD7791_FLAG_HAS_UNIPOLAR | AD7791_FLAG_HAS_BURNOUT,
+	},
+	[AD7788] = {
+		.channels = ad7790_channels,
+		.num_channels = ARRAY_SIZE(ad7790_channels),
+		.flags = AD7791_FLAG_HAS_UNIPOLAR,
+	},
+	[AD7789] = {
+		.channels = ad7791_channels,
+		.num_channels = ARRAY_SIZE(ad7791_channels),
+		.flags = AD7791_FLAG_HAS_UNIPOLAR,
+	},
+	[AD7790] = {
+		.channels = ad7790_channels,
+		.num_channels = ARRAY_SIZE(ad7790_channels),
+		.flags = AD7791_FLAG_HAS_FILTER | AD7791_FLAG_HAS_BUFFER |
+			AD7791_FLAG_HAS_BURNOUT,
+	},
+	[AD7791] = {
+		.channels = ad7791_channels,
+		.num_channels = ARRAY_SIZE(ad7791_channels),
+		.flags = AD7791_FLAG_HAS_FILTER | AD7791_FLAG_HAS_BUFFER |
+			AD7791_FLAG_HAS_UNIPOLAR | AD7791_FLAG_HAS_BURNOUT,
+	},
+};
+
+struct ad7791_state {
+	struct ad_sigma_delta sd;
+	uint8_t mode;
+	uint8_t filter;
+
+	struct regulator *reg;
+	const struct ad7791_chip_info *info;
+};
+
+static struct ad7791_state *ad_sigma_delta_to_ad7791(struct ad_sigma_delta *sd)
+{
+	return container_of(sd, struct ad7791_state, sd);
+}
+
+static int ad7791_set_channel(struct ad_sigma_delta *sd, unsigned int channel)
+{
+	ad_sd_set_comm(sd, channel);
+
+	return 0;
+}
+
+static int ad7791_set_mode(struct ad_sigma_delta *sd,
+	enum ad_sigma_delta_mode mode)
+{
+	struct ad7791_state *st = ad_sigma_delta_to_ad7791(sd);
+
+	switch (mode) {
+	case AD_SD_MODE_CONTINUOUS:
+		mode = AD7791_MODE_CONTINUOUS;
+		break;
+	case AD_SD_MODE_SINGLE:
+		mode = AD7791_MODE_SINGLE;
+		break;
+	case AD_SD_MODE_IDLE:
+	case AD_SD_MODE_POWERDOWN:
+		mode = AD7791_MODE_POWERDOWN;
+		break;
+	}
+
+	st->mode &= ~AD7791_MODE_SEL_MASK;
+	st->mode |= AD7791_MODE_SEL(mode);
+
+	return ad_sd_write_reg(sd, AD7791_REG_MODE, sizeof(st->mode), st->mode);
+}
+
+static const struct ad_sigma_delta_info ad7791_sigma_delta_info = {
+	.set_channel = ad7791_set_channel,
+	.set_mode = ad7791_set_mode,
+	.has_registers = true,
+	.addr_shift = 4,
+	.read_mask = BIT(3),
+};
+
+static int ad7791_read_raw(struct iio_dev *indio_dev,
+	const struct iio_chan_spec *chan, int *val, int *val2, long info)
+{
+	struct ad7791_state *st = iio_priv(indio_dev);
+	bool unipolar = !!(st->mode & AD7791_MODE_UNIPOLAR);
+	unsigned long long scale_pv;
+
+	switch (info) {
+	case IIO_CHAN_INFO_RAW:
+		return ad_sigma_delta_single_conversion(indio_dev, chan, val);
+	case IIO_CHAN_INFO_OFFSET:
+		/**
+		 * Unipolar: 0 to VREF
+		 * Bipolar -VREF to VREF
+		 **/
+		if (unipolar)
+			*val = 0;
+		else
+			*val = -(1 << (chan->scan_type.realbits - 1));
+		return IIO_VAL_INT;
+	case IIO_CHAN_INFO_SCALE:
+		/* The monitor channel uses an internal reference. */
+		if (chan->address == AD7791_CH_AVDD_MONITOR) {
+			scale_pv = 5850000000000ULL;
+		} else {
+			int voltage_uv;
+
+			voltage_uv = regulator_get_voltage(st->reg);
+			if (voltage_uv < 0)
+				return voltage_uv;
+			scale_pv = (unsigned long long)voltage_uv * 1000000;
+		}
+		if (unipolar)
+			scale_pv >>= chan->scan_type.realbits;
+		else
+			scale_pv >>= chan->scan_type.realbits - 1;
+		*val2 = do_div(scale_pv, 1000000000);
+		*val = scale_pv;
+
+		return IIO_VAL_INT_PLUS_NANO;
+	}
+
+	return -EINVAL;
+}
+
+static const char * const ad7791_sample_freq_avail[] = {
+	[AD7791_FILTER_RATE_120] = "120",
+	[AD7791_FILTER_RATE_100] = "100",
+	[AD7791_FILTER_RATE_33_3] = "33.3",
+	[AD7791_FILTER_RATE_20] = "20",
+	[AD7791_FILTER_RATE_16_6] = "16.6",
+	[AD7791_FILTER_RATE_16_7] = "16.7",
+	[AD7791_FILTER_RATE_13_3] = "13.3",
+	[AD7791_FILTER_RATE_9_5] = "9.5",
+};
+
+static ssize_t ad7791_read_frequency(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+	struct ad7791_state *st = iio_priv(indio_dev);
+	unsigned int rate = st->filter & AD7791_FILTER_RATE_MASK;
+
+	return sprintf(buf, "%s\n", ad7791_sample_freq_avail[rate]);
+}
+
+static ssize_t ad7791_write_frequency(struct device *dev,
+	struct device_attribute *attr, const char *buf, size_t len)
+{
+	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+	struct ad7791_state *st = iio_priv(indio_dev);
+	int i, ret;
+
+	mutex_lock(&indio_dev->mlock);
+	if (iio_buffer_enabled(indio_dev)) {
+		mutex_unlock(&indio_dev->mlock);
+		return -EBUSY;
+	}
+	mutex_unlock(&indio_dev->mlock);
+
+	ret = -EINVAL;
+
+	for (i = 0; i < ARRAY_SIZE(ad7791_sample_freq_avail); i++) {
+		if (sysfs_streq(ad7791_sample_freq_avail[i], buf)) {
+
+			mutex_lock(&indio_dev->mlock);
+			st->filter &= ~AD7791_FILTER_RATE_MASK;
+			st->filter |= i;
+			ad_sd_write_reg(&st->sd, AD7791_REG_FILTER,
+					 sizeof(st->filter), st->filter);
+			mutex_unlock(&indio_dev->mlock);
+			ret = 0;
+			break;
+		}
+	}
+
+	return ret ? ret : len;
+}
+
+static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
+		ad7791_read_frequency,
+		ad7791_write_frequency);
+
+static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("120 100 33.3 20 16.7 16.6 13.3 9.5");
+
+static struct attribute *ad7791_attributes[] = {
+	&iio_dev_attr_sampling_frequency.dev_attr.attr,
+	&iio_const_attr_sampling_frequency_available.dev_attr.attr,
+	NULL
+};
+
+static const struct attribute_group ad7791_attribute_group = {
+	.attrs = ad7791_attributes,
+};
+
+static const struct iio_info ad7791_info = {
+	.read_raw = &ad7791_read_raw,
+	.attrs = &ad7791_attribute_group,
+	.validate_trigger = ad_sd_validate_trigger,
+	.driver_module = THIS_MODULE,
+};
+
+static const struct iio_info ad7791_no_filter_info = {
+	.read_raw = &ad7791_read_raw,
+	.validate_trigger = ad_sd_validate_trigger,
+	.driver_module = THIS_MODULE,
+};
+
+static int __devinit ad7791_setup(struct ad7791_state *st,
+	struct ad7791_platform_data *pdata)
+{
+	/* Set to poweron-reset default values */
+	st->mode = AD7791_MODE_BUFFER;
+	st->filter = AD7791_FILTER_RATE_16_6;
+
+	if (!pdata)
+		return 0;
+
+	if ((st->info->flags & AD7791_FLAG_HAS_BUFFER) && !pdata->buffered)
+		st->mode &= ~AD7791_MODE_BUFFER;
+
+	if ((st->info->flags & AD7791_FLAG_HAS_BURNOUT) &&
+		pdata->burnout_current)
+		st->mode |= AD7791_MODE_BURNOUT;
+
+	if ((st->info->flags & AD7791_FLAG_HAS_UNIPOLAR) && pdata->unipolar)
+		st->mode |= AD7791_MODE_UNIPOLAR;
+
+	return ad_sd_write_reg(&st->sd, AD7791_REG_MODE, sizeof(st->mode),
+		st->mode);
+}
+
+static int __devinit ad7791_probe(struct spi_device *spi)
+{
+	struct ad7791_platform_data *pdata = spi->dev.platform_data;
+	struct iio_dev *indio_dev;
+	struct ad7791_state *st;
+	int ret;
+
+	if (!spi->irq) {
+		dev_err(&spi->dev, "Missing IRQ.\n");
+		return -ENXIO;
+	}
+
+	indio_dev = iio_device_alloc(sizeof(*st));
+	if (!indio_dev)
+		return -ENOMEM;
+
+	st = iio_priv(indio_dev);
+
+	st->reg = regulator_get(&spi->dev, "refin");
+	if (IS_ERR(st->reg)) {
+		ret = PTR_ERR(st->reg);
+		goto err_iio_free;
+	}
+
+	ret = regulator_enable(st->reg);
+	if (ret)
+		goto error_put_reg;
+
+	st->info = &ad7791_chip_infos[spi_get_device_id(spi)->driver_data];
+	ad_sd_init(&st->sd, indio_dev, spi, &ad7791_sigma_delta_info);
+
+	spi_set_drvdata(spi, indio_dev);
+
+	indio_dev->dev.parent = &spi->dev;
+	indio_dev->name = spi_get_device_id(spi)->name;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->channels = st->info->channels;
+	indio_dev->num_channels = st->info->num_channels;
+	if (st->info->flags & AD7791_FLAG_HAS_FILTER)
+		indio_dev->info = &ad7791_info;
+	else
+		indio_dev->info = &ad7791_no_filter_info;
+
+	ret = ad_sd_setup_buffer_and_trigger(indio_dev);
+	if (ret)
+		goto error_disable_reg;
+
+	ret = ad7791_setup(st, pdata);
+	if (ret)
+		goto error_remove_trigger;
+
+	ret = iio_device_register(indio_dev);
+	if (ret)
+		goto error_remove_trigger;
+
+	return 0;
+
+error_remove_trigger:
+	ad_sd_cleanup_buffer_and_trigger(indio_dev);
+error_disable_reg:
+	regulator_disable(st->reg);
+error_put_reg:
+	regulator_put(st->reg);
+err_iio_free:
+	iio_device_free(indio_dev);
+
+	return ret;
+}
+
+static int __devexit ad7791_remove(struct spi_device *spi)
+{
+	struct iio_dev *indio_dev = spi_get_drvdata(spi);
+	struct ad7791_state *st = iio_priv(indio_dev);
+
+	iio_device_unregister(indio_dev);
+	ad_sd_cleanup_buffer_and_trigger(indio_dev);
+
+	regulator_disable(st->reg);
+	regulator_put(st->reg);
+
+	iio_device_free(indio_dev);
+
+	return 0;
+}
+
+static const struct spi_device_id ad7791_spi_ids[] = {
+	{ "ad7787", AD7787 },
+	{ "ad7788", AD7788 },
+	{ "ad7789", AD7789 },
+	{ "ad7790", AD7790 },
+	{ "ad7791", AD7791 },
+	{}
+};
+MODULE_DEVICE_TABLE(spi, ad7791_spi_ids);
+
+static struct spi_driver ad7791_driver = {
+	.driver = {
+		.name	= "ad7791",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= ad7791_probe,
+	.remove		= __devexit_p(ad7791_remove),
+	.id_table	= ad7791_spi_ids,
+};
+module_spi_driver(ad7791_driver);
+
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_DESCRIPTION("Analog Device AD7787/AD7788/AD7789/AD7790/AD7791 ADC driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/adc/ad_sigma_delta.c b/drivers/iio/adc/ad_sigma_delta.c
new file mode 100644
index 0000000..67baa13
--- /dev/null
+++ b/drivers/iio/adc/ad_sigma_delta.c
@@ -0,0 +1,558 @@
+/*
+ * Support code for Analog Devices Sigma-Delta ADCs
+ *
+ * Copyright 2012 Analog Devices Inc.
+ *  Author: Lars-Peter Clausen <lars@metafoo.de>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/spi/spi.h>
+#include <linux/err.h>
+#include <linux/module.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
+#include <linux/iio/adc/ad_sigma_delta.h>
+
+#include <asm/unaligned.h>
+
+
+#define AD_SD_COMM_CHAN_MASK	0x3
+
+#define AD_SD_REG_COMM		0x00
+#define AD_SD_REG_DATA		0x03
+
+/**
+ * ad_sd_set_comm() - Set communications register
+ *
+ * @sigma_delta: The sigma delta device
+ * @comm: New value for the communications register
+ */
+void ad_sd_set_comm(struct ad_sigma_delta *sigma_delta, uint8_t comm)
+{
+	/* Some variants use the lower two bits of the communications register
+	 * to select the channel */
+	sigma_delta->comm = comm & AD_SD_COMM_CHAN_MASK;
+}
+EXPORT_SYMBOL_GPL(ad_sd_set_comm);
+
+/**
+ * ad_sd_write_reg() - Write a register
+ *
+ * @sigma_delta: The sigma delta device
+ * @reg: Address of the register
+ * @size: Size of the register (0-3)
+ * @val: Value to write to the register
+ *
+ * Returns 0 on success, an error code otherwise.
+ **/
+int ad_sd_write_reg(struct ad_sigma_delta *sigma_delta, unsigned int reg,
+	unsigned int size, unsigned int val)
+{
+	uint8_t *data = sigma_delta->data;
+	struct spi_transfer t = {
+		.tx_buf		= data,
+		.len		= size + 1,
+		.cs_change	= sigma_delta->bus_locked,
+	};
+	struct spi_message m;
+	int ret;
+
+	data[0] = (reg << sigma_delta->info->addr_shift) | sigma_delta->comm;
+
+	switch (size) {
+	case 3:
+		data[1] = val >> 16;
+		data[2] = val >> 8;
+		data[3] = val;
+		break;
+	case 2:
+		put_unaligned_be16(val, &data[1]);
+		break;
+	case 1:
+		data[1] = val;
+		break;
+	case 0:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	spi_message_init(&m);
+	spi_message_add_tail(&t, &m);
+
+	if (sigma_delta->bus_locked)
+		ret = spi_sync_locked(sigma_delta->spi, &m);
+	else
+		ret = spi_sync(sigma_delta->spi, &m);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(ad_sd_write_reg);
+
+static int ad_sd_read_reg_raw(struct ad_sigma_delta *sigma_delta,
+	unsigned int reg, unsigned int size, uint8_t *val)
+{
+	uint8_t *data = sigma_delta->data;
+	int ret;
+	struct spi_transfer t[] = {
+		{
+			.tx_buf = data,
+			.len = 1,
+		}, {
+			.rx_buf = val,
+			.len = size,
+			.cs_change = sigma_delta->bus_locked,
+		},
+	};
+	struct spi_message m;
+
+	spi_message_init(&m);
+
+	if (sigma_delta->info->has_registers) {
+		data[0] = reg << sigma_delta->info->addr_shift;
+		data[0] |= sigma_delta->info->read_mask;
+		spi_message_add_tail(&t[0], &m);
+	}
+	spi_message_add_tail(&t[1], &m);
+
+	if (sigma_delta->bus_locked)
+		ret = spi_sync_locked(sigma_delta->spi, &m);
+	else
+		ret = spi_sync(sigma_delta->spi, &m);
+
+	return ret;
+}
+
+/**
+ * ad_sd_read_reg() - Read a register
+ *
+ * @sigma_delta: The sigma delta device
+ * @reg: Address of the register
+ * @size: Size of the register (1-4)
+ * @val: Read value
+ *
+ * Returns 0 on success, an error code otherwise.
+ **/
+int ad_sd_read_reg(struct ad_sigma_delta *sigma_delta,
+	unsigned int reg, unsigned int size, unsigned int *val)
+{
+	int ret;
+
+	ret = ad_sd_read_reg_raw(sigma_delta, reg, size, sigma_delta->data);
+	if (ret < 0)
+		goto out;
+
+	switch (size) {
+	case 4:
+		*val = get_unaligned_be32(sigma_delta->data);
+		break;
+	case 3:
+		*val = (sigma_delta->data[0] << 16) |
+			(sigma_delta->data[1] << 8) |
+			sigma_delta->data[2];
+		break;
+	case 2:
+		*val = get_unaligned_be16(sigma_delta->data);
+		break;
+	case 1:
+		*val = sigma_delta->data[0];
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+out:
+	return ret;
+}
+EXPORT_SYMBOL_GPL(ad_sd_read_reg);
+
+static int ad_sd_calibrate(struct ad_sigma_delta *sigma_delta,
+	unsigned int mode, unsigned int channel)
+{
+	int ret;
+
+	ret = ad_sigma_delta_set_channel(sigma_delta, channel);
+	if (ret)
+		return ret;
+
+	spi_bus_lock(sigma_delta->spi->master);
+	sigma_delta->bus_locked = true;
+	INIT_COMPLETION(sigma_delta->completion);
+
+	ret = ad_sigma_delta_set_mode(sigma_delta, mode);
+	if (ret < 0)
+		goto out;
+
+	sigma_delta->irq_dis = false;
+	enable_irq(sigma_delta->spi->irq);
+	ret = wait_for_completion_timeout(&sigma_delta->completion, 2*HZ);
+	if (ret == 0) {
+		sigma_delta->irq_dis = true;
+		disable_irq_nosync(sigma_delta->spi->irq);
+		ret = -EIO;
+	} else {
+		ret = 0;
+	}
+out:
+	sigma_delta->bus_locked = false;
+	spi_bus_unlock(sigma_delta->spi->master);
+	ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_IDLE);
+
+	return ret;
+}
+
+/**
+ * ad_sd_calibrate_all() - Performs channel calibration
+ * @sigma_delta: The sigma delta device
+ * @cb: Array of channels and calibration type to perform
+ * @n: Number of items in cb
+ *
+ * Returns 0 on success, an error code otherwise.
+ **/
+int ad_sd_calibrate_all(struct ad_sigma_delta *sigma_delta,
+	const struct ad_sd_calib_data *cb, unsigned int n)
+{
+	unsigned int i;
+	int ret;
+
+	for (i = 0; i < n; i++) {
+		ret = ad_sd_calibrate(sigma_delta, cb[i].mode, cb[i].channel);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ad_sd_calibrate_all);
+
+/**
+ * ad_sigma_delta_single_conversion() - Performs a single data conversion
+ * @indio_dev: The IIO device
+ * @chan: The conversion is done for this channel
+ * @val: Pointer to the location where to store the read value
+ *
+ * Returns: 0 on success, an error value otherwise.
+ */
+int ad_sigma_delta_single_conversion(struct iio_dev *indio_dev,
+	const struct iio_chan_spec *chan, int *val)
+{
+	struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev);
+	unsigned int sample, raw_sample;
+	int ret = 0;
+
+	if (iio_buffer_enabled(indio_dev))
+		return -EBUSY;
+
+	mutex_lock(&indio_dev->mlock);
+	ad_sigma_delta_set_channel(sigma_delta, chan->address);
+
+	spi_bus_lock(sigma_delta->spi->master);
+	sigma_delta->bus_locked = true;
+	INIT_COMPLETION(sigma_delta->completion);
+
+	ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_SINGLE);
+
+	sigma_delta->irq_dis = false;
+	enable_irq(sigma_delta->spi->irq);
+	ret = wait_for_completion_interruptible_timeout(
+			&sigma_delta->completion, HZ);
+
+	sigma_delta->bus_locked = false;
+	spi_bus_unlock(sigma_delta->spi->master);
+
+	if (ret == 0)
+		ret = -EIO;
+	if (ret < 0)
+		goto out;
+
+	ret = ad_sd_read_reg(sigma_delta, AD_SD_REG_DATA,
+		DIV_ROUND_UP(chan->scan_type.realbits + chan->scan_type.shift, 8),
+		&raw_sample);
+
+out:
+	if (!sigma_delta->irq_dis) {
+		disable_irq_nosync(sigma_delta->spi->irq);
+		sigma_delta->irq_dis = true;
+	}
+
+	ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_IDLE);
+	mutex_unlock(&indio_dev->mlock);
+
+	if (ret)
+		return ret;
+
+	sample = raw_sample >> chan->scan_type.shift;
+	sample &= (1 << chan->scan_type.realbits) - 1;
+	*val = sample;
+
+	ret = ad_sigma_delta_postprocess_sample(sigma_delta, raw_sample);
+	if (ret)
+		return ret;
+
+	return IIO_VAL_INT;
+}
+EXPORT_SYMBOL_GPL(ad_sigma_delta_single_conversion);
+
+static int ad_sd_buffer_postenable(struct iio_dev *indio_dev)
+{
+	struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev);
+	unsigned int channel;
+	int ret;
+
+	ret = iio_triggered_buffer_postenable(indio_dev);
+	if (ret < 0)
+		return ret;
+
+	channel = find_first_bit(indio_dev->active_scan_mask,
+				 indio_dev->masklength);
+	ret = ad_sigma_delta_set_channel(sigma_delta,
+		indio_dev->channels[channel].address);
+	if (ret)
+		goto err_predisable;
+
+	spi_bus_lock(sigma_delta->spi->master);
+	sigma_delta->bus_locked = true;
+	ret = ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_CONTINUOUS);
+	if (ret)
+		goto err_unlock;
+
+	sigma_delta->irq_dis = false;
+	enable_irq(sigma_delta->spi->irq);
+
+	return 0;
+
+err_unlock:
+	spi_bus_unlock(sigma_delta->spi->master);
+err_predisable:
+
+	return ret;
+}
+
+static int ad_sd_buffer_postdisable(struct iio_dev *indio_dev)
+{
+	struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev);
+
+	INIT_COMPLETION(sigma_delta->completion);
+	wait_for_completion_timeout(&sigma_delta->completion, HZ);
+
+	if (!sigma_delta->irq_dis) {
+		disable_irq_nosync(sigma_delta->spi->irq);
+		sigma_delta->irq_dis = true;
+	}
+
+	ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_IDLE);
+
+	sigma_delta->bus_locked = false;
+	return spi_bus_unlock(sigma_delta->spi->master);
+}
+
+static irqreturn_t ad_sd_trigger_handler(int irq, void *p)
+{
+	struct iio_poll_func *pf = p;
+	struct iio_dev *indio_dev = pf->indio_dev;
+	struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev);
+	unsigned int reg_size;
+	uint8_t data[16];
+	int ret;
+
+	memset(data, 0x00, 16);
+
+	/* Guaranteed to be aligned with 8 byte boundary */
+	if (indio_dev->scan_timestamp)
+		((s64 *)data)[1] = pf->timestamp;
+
+	reg_size = indio_dev->channels[0].scan_type.realbits +
+			indio_dev->channels[0].scan_type.shift;
+	reg_size = DIV_ROUND_UP(reg_size, 8);
+
+	switch (reg_size) {
+	case 4:
+	case 2:
+	case 1:
+		ret = ad_sd_read_reg_raw(sigma_delta, AD_SD_REG_DATA,
+			reg_size, &data[0]);
+		break;
+	case 3:
+		/* We store 24 bit samples in a 32 bit word. Keep the upper
+		 * byte set to zero. */
+		ret = ad_sd_read_reg_raw(sigma_delta, AD_SD_REG_DATA,
+			reg_size, &data[1]);
+		break;
+	}
+
+	iio_push_to_buffer(indio_dev->buffer, (uint8_t *)data);
+
+	iio_trigger_notify_done(indio_dev->trig);
+	sigma_delta->irq_dis = false;
+	enable_irq(sigma_delta->spi->irq);
+
+	return IRQ_HANDLED;
+}
+
+static const struct iio_buffer_setup_ops ad_sd_buffer_setup_ops = {
+	.preenable = &iio_sw_buffer_preenable,
+	.postenable = &ad_sd_buffer_postenable,
+	.predisable = &iio_triggered_buffer_predisable,
+	.postdisable = &ad_sd_buffer_postdisable,
+	.validate_scan_mask = &iio_validate_scan_mask_onehot,
+};
+
+static irqreturn_t ad_sd_data_rdy_trig_poll(int irq, void *private)
+{
+	struct ad_sigma_delta *sigma_delta = private;
+
+	complete(&sigma_delta->completion);
+	disable_irq_nosync(irq);
+	sigma_delta->irq_dis = true;
+	iio_trigger_poll(sigma_delta->trig, iio_get_time_ns());
+
+	return IRQ_HANDLED;
+}
+
+/**
+ * ad_sd_validate_trigger() - validate_trigger callback for ad_sigma_delta devices
+ * @indio_dev: The IIO device
+ * @trig: The new trigger
+ *
+ * Returns: 0 if the 'trig' matches the trigger registered by the ad_sigma_delta
+ * device, -EINVAL otherwise.
+ */
+int ad_sd_validate_trigger(struct iio_dev *indio_dev, struct iio_trigger *trig)
+{
+	struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev);
+
+	if (sigma_delta->trig != trig)
+		return -EINVAL;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ad_sd_validate_trigger);
+
+static const struct iio_trigger_ops ad_sd_trigger_ops = {
+	.owner = THIS_MODULE,
+};
+
+static int ad_sd_probe_trigger(struct iio_dev *indio_dev)
+{
+	struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev);
+	int ret;
+
+	sigma_delta->trig = iio_trigger_alloc("%s-dev%d", indio_dev->name,
+						indio_dev->id);
+	if (sigma_delta->trig == NULL) {
+		ret = -ENOMEM;
+		goto error_ret;
+	}
+	sigma_delta->trig->ops = &ad_sd_trigger_ops;
+	init_completion(&sigma_delta->completion);
+
+	ret = request_irq(sigma_delta->spi->irq,
+			  ad_sd_data_rdy_trig_poll,
+			  IRQF_TRIGGER_LOW,
+			  indio_dev->name,
+			  sigma_delta);
+	if (ret)
+		goto error_free_trig;
+
+	if (!sigma_delta->irq_dis) {
+		sigma_delta->irq_dis = true;
+		disable_irq_nosync(sigma_delta->spi->irq);
+	}
+	sigma_delta->trig->dev.parent = &sigma_delta->spi->dev;
+	sigma_delta->trig->private_data = sigma_delta;
+
+	ret = iio_trigger_register(sigma_delta->trig);
+	if (ret)
+		goto error_free_irq;
+
+	/* select default trigger */
+	indio_dev->trig = sigma_delta->trig;
+
+	return 0;
+
+error_free_irq:
+	free_irq(sigma_delta->spi->irq, sigma_delta);
+error_free_trig:
+	iio_trigger_free(sigma_delta->trig);
+error_ret:
+	return ret;
+}
+
+static void ad_sd_remove_trigger(struct iio_dev *indio_dev)
+{
+	struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev);
+
+	iio_trigger_unregister(sigma_delta->trig);
+	free_irq(sigma_delta->spi->irq, sigma_delta);
+	iio_trigger_free(sigma_delta->trig);
+}
+
+/**
+ * ad_sd_setup_buffer_and_trigger() -
+ * @indio_dev: The IIO device
+ */
+int ad_sd_setup_buffer_and_trigger(struct iio_dev *indio_dev)
+{
+	int ret;
+
+	ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
+			&ad_sd_trigger_handler, &ad_sd_buffer_setup_ops);
+	if (ret)
+		return ret;
+
+	ret = ad_sd_probe_trigger(indio_dev);
+	if (ret) {
+		iio_triggered_buffer_cleanup(indio_dev);
+		return ret;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ad_sd_setup_buffer_and_trigger);
+
+/**
+ * ad_sd_cleanup_buffer_and_trigger() -
+ * @indio_dev: The IIO device
+ */
+void ad_sd_cleanup_buffer_and_trigger(struct iio_dev *indio_dev)
+{
+	ad_sd_remove_trigger(indio_dev);
+	iio_triggered_buffer_cleanup(indio_dev);
+}
+EXPORT_SYMBOL_GPL(ad_sd_cleanup_buffer_and_trigger);
+
+/**
+ * ad_sd_init() - Initializes a ad_sigma_delta struct
+ * @sigma_delta: The ad_sigma_delta device
+ * @indio_dev: The IIO device which the Sigma Delta device is used for
+ * @spi: The SPI device for the ad_sigma_delta device
+ * @info: Device specific callbacks and options
+ *
+ * This function needs to be called before any other operations are performed on
+ * the ad_sigma_delta struct.
+ */
+int ad_sd_init(struct ad_sigma_delta *sigma_delta, struct iio_dev *indio_dev,
+	struct spi_device *spi, const struct ad_sigma_delta_info *info)
+{
+	sigma_delta->spi = spi;
+	sigma_delta->info = info;
+	iio_device_set_drvdata(indio_dev, sigma_delta);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ad_sd_init);
+
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_DESCRIPTION("Analog Devices Sigma-Delta ADCs");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c
index 3bd5540..3ed94bf 100644
--- a/drivers/iio/adc/at91_adc.c
+++ b/drivers/iio/adc/at91_adc.c
@@ -82,7 +82,7 @@ static irqreturn_t at91_adc_trigger_handler(int irq, void *p)
 		*timestamp = pf->timestamp;
 	}
 
-	buffer->access->store_to(buffer, (u8 *)st->buffer, pf->timestamp);
+	buffer->access->store_to(buffer, (u8 *)st->buffer);
 
 	iio_trigger_notify_done(idev->trig);
 	st->irq_enabled = true;
@@ -545,13 +545,6 @@ static int __devinit at91_adc_probe(struct platform_device *pdev)
 		goto error_free_device;
 	}
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_err(&pdev->dev, "No resource defined\n");
-		ret = -ENXIO;
-		goto error_ret;
-	}
-
 	platform_set_drvdata(pdev, idev);
 
 	idev->dev.parent = &pdev->dev;
@@ -566,18 +559,12 @@ static int __devinit at91_adc_probe(struct platform_device *pdev)
 		goto error_free_device;
 	}
 
-	if (!request_mem_region(res->start, resource_size(res),
-				"AT91 adc registers")) {
-		dev_err(&pdev->dev, "Resources are unavailable.\n");
-		ret = -EBUSY;
-		goto error_free_device;
-	}
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 
-	st->reg_base = ioremap(res->start, resource_size(res));
+	st->reg_base = devm_request_and_ioremap(&pdev->dev, res);
 	if (!st->reg_base) {
-		dev_err(&pdev->dev, "Failed to map registers.\n");
 		ret = -ENOMEM;
-		goto error_release_mem;
+		goto error_free_device;
 	}
 
 	/*
@@ -592,45 +579,35 @@ static int __devinit at91_adc_probe(struct platform_device *pdev)
 			  idev);
 	if (ret) {
 		dev_err(&pdev->dev, "Failed to allocate IRQ.\n");
-		goto error_unmap_reg;
+		goto error_free_device;
 	}
 
-	st->clk = clk_get(&pdev->dev, "adc_clk");
+	st->clk = devm_clk_get(&pdev->dev, "adc_clk");
 	if (IS_ERR(st->clk)) {
 		dev_err(&pdev->dev, "Failed to get the clock.\n");
 		ret = PTR_ERR(st->clk);
 		goto error_free_irq;
 	}
 
-	ret = clk_prepare(st->clk);
+	ret = clk_prepare_enable(st->clk);
 	if (ret) {
-		dev_err(&pdev->dev, "Could not prepare the clock.\n");
-		goto error_free_clk;
-	}
-
-	ret = clk_enable(st->clk);
-	if (ret) {
-		dev_err(&pdev->dev, "Could not enable the clock.\n");
-		goto error_unprepare_clk;
+		dev_err(&pdev->dev,
+			"Could not prepare or enable the clock.\n");
+		goto error_free_irq;
 	}
 
-	st->adc_clk = clk_get(&pdev->dev, "adc_op_clk");
+	st->adc_clk = devm_clk_get(&pdev->dev, "adc_op_clk");
 	if (IS_ERR(st->adc_clk)) {
 		dev_err(&pdev->dev, "Failed to get the ADC clock.\n");
 		ret = PTR_ERR(st->adc_clk);
 		goto error_disable_clk;
 	}
 
-	ret = clk_prepare(st->adc_clk);
+	ret = clk_prepare_enable(st->adc_clk);
 	if (ret) {
-		dev_err(&pdev->dev, "Could not prepare the ADC clock.\n");
-		goto error_free_adc_clk;
-	}
-
-	ret = clk_enable(st->adc_clk);
-	if (ret) {
-		dev_err(&pdev->dev, "Could not enable the ADC clock.\n");
-		goto error_unprepare_adc_clk;
+		dev_err(&pdev->dev,
+			"Could not prepare or enable the ADC clock.\n");
+		goto error_disable_clk;
 	}
 
 	/*
@@ -694,23 +671,11 @@ error_remove_triggers:
 error_unregister_buffer:
 	at91_adc_buffer_remove(idev);
 error_disable_adc_clk:
-	clk_disable(st->adc_clk);
-error_unprepare_adc_clk:
-	clk_unprepare(st->adc_clk);
-error_free_adc_clk:
-	clk_put(st->adc_clk);
+	clk_disable_unprepare(st->adc_clk);
 error_disable_clk:
-	clk_disable(st->clk);
-error_unprepare_clk:
-	clk_unprepare(st->clk);
-error_free_clk:
-	clk_put(st->clk);
+	clk_disable_unprepare(st->clk);
 error_free_irq:
 	free_irq(st->irq, idev);
-error_unmap_reg:
-	iounmap(st->reg_base);
-error_release_mem:
-	release_mem_region(res->start, resource_size(res));
 error_free_device:
 	iio_device_free(idev);
 error_ret:
@@ -720,20 +685,14 @@ error_ret:
 static int __devexit at91_adc_remove(struct platform_device *pdev)
 {
 	struct iio_dev *idev = platform_get_drvdata(pdev);
-	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	struct at91_adc_state *st = iio_priv(idev);
 
 	iio_device_unregister(idev);
 	at91_adc_trigger_remove(idev);
 	at91_adc_buffer_remove(idev);
 	clk_disable_unprepare(st->adc_clk);
-	clk_put(st->adc_clk);
-	clk_disable(st->clk);
-	clk_unprepare(st->clk);
-	clk_put(st->clk);
+	clk_disable_unprepare(st->clk);
 	free_irq(st->irq, idev);
-	iounmap(st->reg_base);
-	release_mem_region(res->start, resource_size(res));
 	iio_device_free(idev);
 
 	return 0;
diff --git a/drivers/iio/common/Kconfig b/drivers/iio/common/Kconfig
new file mode 100644
index 0000000..ed45ee5
--- /dev/null
+++ b/drivers/iio/common/Kconfig
@@ -0,0 +1,5 @@
+#
+# IIO common modules
+#
+
+source "drivers/iio/common/hid-sensors/Kconfig"
diff --git a/drivers/iio/common/Makefile b/drivers/iio/common/Makefile
new file mode 100644
index 0000000..8158400
--- /dev/null
+++ b/drivers/iio/common/Makefile
@@ -0,0 +1,9 @@
+#
+# Makefile for the IIO common modules.
+# Common modules contains modules, which can be shared among multiple
+# IIO modules. For example if the trigger processing is common for
+# multiple IIO modules then this can be moved to a common module
+# instead of duplicating in each module.
+#
+
+obj-y += hid-sensors/
diff --git a/drivers/iio/common/hid-sensors/Kconfig b/drivers/iio/common/hid-sensors/Kconfig
new file mode 100644
index 0000000..8e63d81
--- /dev/null
+++ b/drivers/iio/common/hid-sensors/Kconfig
@@ -0,0 +1,26 @@
+#
+# Hid Sensor common modules
+#
+menu "Hid Sensor IIO Common"
+
+config HID_SENSOR_IIO_COMMON
+	tristate "Common modules for all HID Sensor IIO drivers"
+	depends on HID_SENSOR_HUB
+	select IIO_TRIGGER if IIO_BUFFER
+	help
+	  Say yes here to build support for HID sensor to use
+	  HID sensor common processing for attributes and IIO triggers.
+	  There are many attributes which can be shared among multiple
+	  HID sensor drivers, this module contains processing for those
+	  attributes.
+
+config HID_SENSOR_ENUM_BASE_QUIRKS
+	tristate "ENUM base quirks for HID Sensor IIO drivers"
+	depends on HID_SENSOR_IIO_COMMON
+	help
+	  Say yes here to build support for sensor hub FW using
+	  enumeration, which is using 1 as base instead of 0.
+	  Since logical minimum is still set 0 instead of 1,
+	  there is no easy way to differentiate.
+
+endmenu
diff --git a/drivers/iio/common/hid-sensors/Makefile b/drivers/iio/common/hid-sensors/Makefile
new file mode 100644
index 0000000..1f463e0
--- /dev/null
+++ b/drivers/iio/common/hid-sensors/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the Hid sensor common modules.
+#
+
+obj-$(CONFIG_HID_SENSOR_IIO_COMMON) += hid-sensor-iio-common.o
+hid-sensor-iio-common-y := hid-sensor-attributes.o hid-sensor-trigger.o
diff --git a/drivers/iio/common/hid-sensors/hid-sensor-attributes.c b/drivers/iio/common/hid-sensors/hid-sensor-attributes.c
new file mode 100644
index 0000000..7537495
--- /dev/null
+++ b/drivers/iio/common/hid-sensors/hid-sensor-attributes.c
@@ -0,0 +1,250 @@
+/*
+ * HID Sensors Driver
+ * Copyright (c) 2012, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/slab.h>
+#include <linux/hid-sensor-hub.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include "hid-sensor-attributes.h"
+
+static int pow_10(unsigned power)
+{
+	int i;
+	int ret = 1;
+	for (i = 0; i < power; ++i)
+		ret = ret * 10;
+
+	return ret;
+}
+
+static void simple_div(int dividend, int divisor, int *whole,
+				int *micro_frac)
+{
+	int rem;
+	int exp = 0;
+
+	*micro_frac = 0;
+	if (divisor == 0) {
+		*whole = 0;
+		return;
+	}
+	*whole = dividend/divisor;
+	rem = dividend % divisor;
+	if (rem) {
+		while (rem <= divisor) {
+			rem *= 10;
+			exp++;
+		}
+		*micro_frac = (rem / divisor) * pow_10(6-exp);
+	}
+}
+
+static void split_micro_fraction(unsigned int no, int exp, int *val1, int *val2)
+{
+	*val1 = no/pow_10(exp);
+	*val2 = no%pow_10(exp) * pow_10(6-exp);
+}
+
+/*
+VTF format uses exponent and variable size format.
+For example if the size is 2 bytes
+0x0067 with VTF16E14 format -> +1.03
+To convert just change to 0x67 to decimal and use two decimal as E14 stands
+for 10^-2.
+Negative numbers are 2's complement
+*/
+static void convert_from_vtf_format(u32 value, int size, int exp,
+					int *val1, int *val2)
+{
+	int sign = 1;
+
+	if (value & BIT(size*8 - 1)) {
+		value =  ((1LL << (size * 8)) - value);
+		sign = -1;
+	}
+	exp = hid_sensor_convert_exponent(exp);
+	if (exp >= 0) {
+		*val1 = sign * value * pow_10(exp);
+		*val2 = 0;
+	} else {
+		split_micro_fraction(value, -exp, val1, val2);
+		if (*val1)
+			*val1 = sign * (*val1);
+		else
+			*val2 = sign * (*val2);
+	}
+}
+
+static u32 convert_to_vtf_format(int size, int exp, int val1, int val2)
+{
+	u32 value;
+	int sign = 1;
+
+	if (val1 < 0 || val2 < 0)
+		sign = -1;
+	exp = hid_sensor_convert_exponent(exp);
+	if (exp < 0) {
+		value = abs(val1) * pow_10(-exp);
+		value += abs(val2) / pow_10(6+exp);
+	} else
+		value = abs(val1) / pow_10(exp);
+	if (sign < 0)
+		value =  ((1LL << (size * 8)) - value);
+
+	return value;
+}
+
+int hid_sensor_read_samp_freq_value(struct hid_sensor_iio_common *st,
+				int *val1, int *val2)
+{
+	s32 value;
+	int ret;
+
+	ret = sensor_hub_get_feature(st->hsdev,
+		st->poll.report_id,
+		st->poll.index, &value);
+	if (ret < 0 || value < 0) {
+		*val1 = *val2 = 0;
+		return -EINVAL;
+	} else {
+		if (st->poll.units == HID_USAGE_SENSOR_UNITS_MILLISECOND)
+			simple_div(1000, value, val1, val2);
+		else if (st->poll.units == HID_USAGE_SENSOR_UNITS_SECOND)
+			simple_div(1, value, val1, val2);
+		else {
+			*val1 = *val2 = 0;
+			return -EINVAL;
+		}
+	}
+
+	return IIO_VAL_INT_PLUS_MICRO;
+}
+EXPORT_SYMBOL(hid_sensor_read_samp_freq_value);
+
+int hid_sensor_write_samp_freq_value(struct hid_sensor_iio_common *st,
+				int val1, int val2)
+{
+	s32 value;
+	int ret;
+
+	if (val1 < 0 || val2 < 0)
+		ret = -EINVAL;
+
+	value = val1 * pow_10(6) + val2;
+	if (value) {
+		if (st->poll.units == HID_USAGE_SENSOR_UNITS_MILLISECOND)
+			value = pow_10(9)/value;
+		else if (st->poll.units == HID_USAGE_SENSOR_UNITS_SECOND)
+			value = pow_10(6)/value;
+		else
+			value = 0;
+	}
+	ret = sensor_hub_set_feature(st->hsdev,
+		st->poll.report_id,
+		st->poll.index, value);
+	if (ret < 0 || value < 0)
+		ret = -EINVAL;
+
+	return ret;
+}
+EXPORT_SYMBOL(hid_sensor_write_samp_freq_value);
+
+int hid_sensor_read_raw_hyst_value(struct hid_sensor_iio_common *st,
+				int *val1, int *val2)
+{
+	s32 value;
+	int ret;
+
+	ret = sensor_hub_get_feature(st->hsdev,
+		st->sensitivity.report_id,
+		st->sensitivity.index, &value);
+	if (ret < 0 || value < 0) {
+		*val1 = *val2 = 0;
+		return -EINVAL;
+	} else {
+		convert_from_vtf_format(value, st->sensitivity.size,
+					st->sensitivity.unit_expo,
+					val1, val2);
+	}
+
+	return IIO_VAL_INT_PLUS_MICRO;
+}
+EXPORT_SYMBOL(hid_sensor_read_raw_hyst_value);
+
+int hid_sensor_write_raw_hyst_value(struct hid_sensor_iio_common *st,
+					int val1, int val2)
+{
+	s32 value;
+	int ret;
+
+	value = convert_to_vtf_format(st->sensitivity.size,
+				st->sensitivity.unit_expo,
+				val1, val2);
+	ret = sensor_hub_set_feature(st->hsdev,
+		st->sensitivity.report_id,
+		st->sensitivity.index, value);
+	if (ret < 0 || value < 0)
+		ret = -EINVAL;
+
+	return ret;
+}
+EXPORT_SYMBOL(hid_sensor_write_raw_hyst_value);
+
+int hid_sensor_parse_common_attributes(struct hid_sensor_hub_device *hsdev,
+					u32 usage_id,
+					struct hid_sensor_iio_common *st)
+{
+
+	sensor_hub_input_get_attribute_info(hsdev,
+					HID_FEATURE_REPORT, usage_id,
+					HID_USAGE_SENSOR_PROP_REPORT_INTERVAL,
+					&st->poll);
+
+	sensor_hub_input_get_attribute_info(hsdev,
+					HID_FEATURE_REPORT, usage_id,
+					HID_USAGE_SENSOR_PROP_REPORT_STATE,
+					&st->report_state);
+
+	sensor_hub_input_get_attribute_info(hsdev,
+					HID_FEATURE_REPORT, usage_id,
+					HID_USAGE_SENSOR_PROY_POWER_STATE,
+					&st->power_state);
+
+	sensor_hub_input_get_attribute_info(hsdev,
+			HID_FEATURE_REPORT, usage_id,
+			HID_USAGE_SENSOR_PROP_SENSITIVITY_ABS,
+			 &st->sensitivity);
+
+	hid_dbg(hsdev->hdev, "common attributes: %x:%x, %x:%x, %x:%x %x:%x\n",
+			st->poll.index, st->poll.report_id,
+			st->report_state.index, st->report_state.report_id,
+			st->power_state.index, st->power_state.report_id,
+			st->sensitivity.index, st->sensitivity.report_id);
+
+	return 0;
+}
+EXPORT_SYMBOL(hid_sensor_parse_common_attributes);
+
+MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@intel.com>");
+MODULE_DESCRIPTION("HID Sensor common attribute processing");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/common/hid-sensors/hid-sensor-attributes.h b/drivers/iio/common/hid-sensors/hid-sensor-attributes.h
new file mode 100644
index 0000000..a4676a0
--- /dev/null
+++ b/drivers/iio/common/hid-sensors/hid-sensor-attributes.h
@@ -0,0 +1,57 @@
+/*
+ * HID Sensors Driver
+ * Copyright (c) 2012, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+#ifndef _HID_SENSORS_ATTRIBUTES_H
+#define _HID_SENSORS_ATTRIBUTES_H
+
+/* Common hid sensor iio structure */
+struct hid_sensor_iio_common {
+	struct hid_sensor_hub_device *hsdev;
+	struct platform_device *pdev;
+	unsigned usage_id;
+	bool data_ready;
+	struct hid_sensor_hub_attribute_info poll;
+	struct hid_sensor_hub_attribute_info report_state;
+	struct hid_sensor_hub_attribute_info power_state;
+	struct hid_sensor_hub_attribute_info sensitivity;
+};
+
+/*Convert from hid unit expo to regular exponent*/
+static inline int hid_sensor_convert_exponent(int unit_expo)
+{
+	if (unit_expo < 0x08)
+		return unit_expo;
+	else if (unit_expo <= 0x0f)
+		return -(0x0f-unit_expo+1);
+	else
+		return 0;
+}
+
+int hid_sensor_parse_common_attributes(struct hid_sensor_hub_device *hsdev,
+					u32 usage_id,
+					struct hid_sensor_iio_common *st);
+int hid_sensor_write_raw_hyst_value(struct hid_sensor_iio_common *st,
+					int val1, int val2);
+int hid_sensor_read_raw_hyst_value(struct hid_sensor_iio_common *st,
+					int *val1, int *val2);
+int hid_sensor_write_samp_freq_value(struct hid_sensor_iio_common *st,
+					int val1, int val2);
+int hid_sensor_read_samp_freq_value(struct hid_sensor_iio_common *st,
+					int *val1, int *val2);
+
+#endif
diff --git a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
new file mode 100644
index 0000000..12277e8
--- /dev/null
+++ b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
@@ -0,0 +1,102 @@
+/*
+ * HID Sensors Driver
+ * Copyright (c) 2012, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/slab.h>
+#include <linux/hid-sensor-hub.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/sysfs.h>
+#include "hid-sensor-attributes.h"
+#include "hid-sensor-trigger.h"
+
+static int hid_sensor_data_rdy_trigger_set_state(struct iio_trigger *trig,
+						bool state)
+{
+	struct hid_sensor_iio_common *st = trig->private_data;
+	int state_val;
+
+	state_val = state ? 1 : 0;
+#if (defined CONFIG_HID_SENSOR_ENUM_BASE_QUIRKS) || \
+	(defined CONFIG_HID_SENSOR_ENUM_BASE_QUIRKS_MODULE)
+	++state_val;
+#endif
+	st->data_ready = state;
+	sensor_hub_set_feature(st->hsdev, st->power_state.report_id,
+					st->power_state.index,
+					(s32)state_val);
+
+	sensor_hub_set_feature(st->hsdev, st->report_state.report_id,
+					st->report_state.index,
+					(s32)state_val);
+
+	return 0;
+}
+
+void hid_sensor_remove_trigger(struct iio_dev *indio_dev)
+{
+	iio_trigger_unregister(indio_dev->trig);
+	iio_trigger_free(indio_dev->trig);
+}
+EXPORT_SYMBOL(hid_sensor_remove_trigger);
+
+static const struct iio_trigger_ops hid_sensor_trigger_ops = {
+	.owner = THIS_MODULE,
+	.set_trigger_state = &hid_sensor_data_rdy_trigger_set_state,
+};
+
+int hid_sensor_setup_trigger(struct iio_dev *indio_dev, const char *name,
+				struct hid_sensor_iio_common *attrb)
+{
+	int ret;
+	struct iio_trigger *trig;
+
+	trig = iio_trigger_alloc("%s-dev%d", name, indio_dev->id);
+	if (trig == NULL) {
+		dev_err(&indio_dev->dev, "Trigger Allocate Failed\n");
+		ret = -ENOMEM;
+		goto error_ret;
+	}
+
+	trig->dev.parent = indio_dev->dev.parent;
+	trig->private_data = attrb;
+	trig->ops = &hid_sensor_trigger_ops;
+	ret = iio_trigger_register(trig);
+
+	if (ret) {
+		dev_err(&indio_dev->dev, "Trigger Register Failed\n");
+		goto error_free_trig;
+	}
+	indio_dev->trig = trig;
+
+	return ret;
+
+error_free_trig:
+	iio_trigger_free(trig);
+error_ret:
+	return ret;
+}
+EXPORT_SYMBOL(hid_sensor_setup_trigger);
+
+MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@intel.com>");
+MODULE_DESCRIPTION("HID Sensor trigger processing");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/common/hid-sensors/hid-sensor-trigger.h b/drivers/iio/common/hid-sensors/hid-sensor-trigger.h
new file mode 100644
index 0000000..fd98297
--- /dev/null
+++ b/drivers/iio/common/hid-sensors/hid-sensor-trigger.h
@@ -0,0 +1,26 @@
+/*
+ * HID Sensors Driver
+ * Copyright (c) 2012, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+#ifndef _HID_SENSOR_TRIGGER_H
+#define _HID_SENSOR_TRIGGER_H
+
+int hid_sensor_setup_trigger(struct iio_dev *indio_dev, const char *name,
+				struct hid_sensor_iio_common *attrb);
+void hid_sensor_remove_trigger(struct iio_dev *indio_dev);
+
+#endif
diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig
index 1be15fa..b1c0ee5 100644
--- a/drivers/iio/dac/Kconfig
+++ b/drivers/iio/dac/Kconfig
@@ -57,11 +57,12 @@ config AD5624R_SPI
 
 config AD5446
 	tristate "Analog Devices AD5446 and similar single channel DACs driver"
-	depends on SPI
+	depends on (SPI_MASTER || I2C)
 	help
-	  Say yes here to build support for Analog Devices AD5444, AD5446, AD5450,
-	  AD5451, AD5452, AD5453, AD5512A, AD5541A, AD5542A, AD5543, AD5553, AD5601,
-	  AD5611, AD5620, AD5621, AD5640, AD5660, AD5662 DACs.
+	  Say yes here to build support for Analog Devices AD5300, AD5301, AD5310,
+	  AD5311, AD5320, AD5321, AD5444, AD5446, AD5450, AD5451, AD5452, AD5453,
+	  AD5512A, AD5541A, AD5542A, AD5543, AD5553, AD5601, AD5602, AD5611, AD5612,
+	  AD5620, AD5621, AD5622, AD5640, AD5660, AD5662 DACs.
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called ad5446.
@@ -76,6 +77,17 @@ config AD5504
 	  To compile this driver as a module, choose M here: the
 	  module will be called ad5504.
 
+config AD5755
+	tristate "Analog Devices AD5755/AD5755-1/AD5757/AD5735/AD5737 DAC driver"
+	depends on SPI_MASTER
+	help
+	  Say yes here to build support for Analog Devices AD5755, AD5755-1,
+	  AD5757, AD5735, AD5737 quad channel Digital to
+	  Analog Converter.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ad5755.
+
 config AD5764
 	tristate "Analog Devices AD5764/64R/44/44R DAC driver"
 	depends on SPI_MASTER
diff --git a/drivers/iio/dac/Makefile b/drivers/iio/dac/Makefile
index 9ea3cee..c0d333b 100644
--- a/drivers/iio/dac/Makefile
+++ b/drivers/iio/dac/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_AD5624R_SPI) += ad5624r_spi.o
 obj-$(CONFIG_AD5064) += ad5064.o
 obj-$(CONFIG_AD5504) += ad5504.o
 obj-$(CONFIG_AD5446) += ad5446.o
+obj-$(CONFIG_AD5755) += ad5755.o
 obj-$(CONFIG_AD5764) += ad5764.o
 obj-$(CONFIG_AD5791) += ad5791.o
 obj-$(CONFIG_AD5686) += ad5686.o
diff --git a/drivers/iio/dac/ad5446.c b/drivers/iio/dac/ad5446.c
index 2ca5059..3310cbb 100644
--- a/drivers/iio/dac/ad5446.c
+++ b/drivers/iio/dac/ad5446.c
@@ -14,6 +14,7 @@
 #include <linux/sysfs.h>
 #include <linux/list.h>
 #include <linux/spi/spi.h>
+#include <linux/i2c.h>
 #include <linux/regulator/consumer.h>
 #include <linux/err.h>
 #include <linux/module.h>
@@ -21,24 +22,40 @@
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
 
-#include "ad5446.h"
+#define MODE_PWRDWN_1k		0x1
+#define MODE_PWRDWN_100k	0x2
+#define MODE_PWRDWN_TRISTATE	0x3
 
-static int ad5446_write(struct ad5446_state *st, unsigned val)
-{
-	__be16 data = cpu_to_be16(val);
-	return spi_write(st->spi, &data, sizeof(data));
-}
+/**
+ * struct ad5446_state - driver instance specific data
+ * @spi:		spi_device
+ * @chip_info:		chip model specific constants, available modes etc
+ * @reg:		supply regulator
+ * @vref_mv:		actual reference voltage used
+ */
 
-static int ad5660_write(struct ad5446_state *st, unsigned val)
-{
-	uint8_t data[3];
+struct ad5446_state {
+	struct device		*dev;
+	const struct ad5446_chip_info	*chip_info;
+	struct regulator		*reg;
+	unsigned short			vref_mv;
+	unsigned			cached_val;
+	unsigned			pwr_down_mode;
+	unsigned			pwr_down;
+};
 
-	data[0] = (val >> 16) & 0xFF;
-	data[1] = (val >> 8) & 0xFF;
-	data[2] = val & 0xFF;
+/**
+ * struct ad5446_chip_info - chip specific information
+ * @channel:		channel spec for the DAC
+ * @int_vref_mv:	AD5620/40/60: the internal reference voltage
+ * @write:		chip specific helper function to write to the register
+ */
 
-	return spi_write(st->spi, data, sizeof(data));
-}
+struct ad5446_chip_info {
+	struct iio_chan_spec	channel;
+	u16			int_vref_mv;
+	int			(*write)(struct ad5446_state *st, unsigned val);
+};
 
 static const char * const ad5446_powerdown_modes[] = {
 	"1kohm_to_gnd", "100kohm_to_gnd", "three_state"
@@ -110,7 +127,7 @@ static ssize_t ad5446_write_dac_powerdown(struct iio_dev *indio_dev,
 	return ret ? ret : len;
 }
 
-static const struct iio_chan_spec_ext_info ad5064_ext_info_powerdown[] = {
+static const struct iio_chan_spec_ext_info ad5446_ext_info_powerdown[] = {
 	{
 		.name = "powerdown",
 		.read = ad5446_read_dac_powerdown,
@@ -136,84 +153,7 @@ static const struct iio_chan_spec_ext_info ad5064_ext_info_powerdown[] = {
 	_AD5446_CHANNEL(bits, storage, shift, NULL)
 
 #define AD5446_CHANNEL_POWERDOWN(bits, storage, shift) \
-	_AD5446_CHANNEL(bits, storage, shift, ad5064_ext_info_powerdown)
-
-static const struct ad5446_chip_info ad5446_chip_info_tbl[] = {
-	[ID_AD5444] = {
-		.channel = AD5446_CHANNEL(12, 16, 2),
-		.write = ad5446_write,
-	},
-	[ID_AD5446] = {
-		.channel = AD5446_CHANNEL(14, 16, 0),
-		.write = ad5446_write,
-	},
-	[ID_AD5450] = {
-		.channel = AD5446_CHANNEL(8, 16, 6),
-		.write = ad5446_write,
-	},
-	[ID_AD5451] = {
-		.channel = AD5446_CHANNEL(10, 16, 4),
-		.write = ad5446_write,
-	},
-	[ID_AD5541A] = {
-		.channel = AD5446_CHANNEL(16, 16, 0),
-		.write = ad5446_write,
-	},
-	[ID_AD5512A] = {
-		.channel = AD5446_CHANNEL(12, 16, 4),
-		.write = ad5446_write,
-	},
-	[ID_AD5553] = {
-		.channel = AD5446_CHANNEL(14, 16, 0),
-		.write = ad5446_write,
-	},
-	[ID_AD5601] = {
-		.channel = AD5446_CHANNEL_POWERDOWN(8, 16, 6),
-		.write = ad5446_write,
-	},
-	[ID_AD5611] = {
-		.channel = AD5446_CHANNEL_POWERDOWN(10, 16, 4),
-		.write = ad5446_write,
-	},
-	[ID_AD5621] = {
-		.channel = AD5446_CHANNEL_POWERDOWN(12, 16, 2),
-		.write = ad5446_write,
-	},
-	[ID_AD5620_2500] = {
-		.channel = AD5446_CHANNEL_POWERDOWN(12, 16, 2),
-		.int_vref_mv = 2500,
-		.write = ad5446_write,
-	},
-	[ID_AD5620_1250] = {
-		.channel = AD5446_CHANNEL_POWERDOWN(12, 16, 2),
-		.int_vref_mv = 1250,
-		.write = ad5446_write,
-	},
-	[ID_AD5640_2500] = {
-		.channel = AD5446_CHANNEL_POWERDOWN(14, 16, 0),
-		.int_vref_mv = 2500,
-		.write = ad5446_write,
-	},
-	[ID_AD5640_1250] = {
-		.channel = AD5446_CHANNEL_POWERDOWN(14, 16, 0),
-		.int_vref_mv = 1250,
-		.write = ad5446_write,
-	},
-	[ID_AD5660_2500] = {
-		.channel = AD5446_CHANNEL_POWERDOWN(16, 16, 0),
-		.int_vref_mv = 2500,
-		.write = ad5660_write,
-	},
-	[ID_AD5660_1250] = {
-		.channel = AD5446_CHANNEL_POWERDOWN(16, 16, 0),
-		.int_vref_mv = 1250,
-		.write = ad5660_write,
-	},
-	[ID_AD5662] = {
-		.channel = AD5446_CHANNEL_POWERDOWN(16, 16, 0),
-		.write = ad5660_write,
-	},
-};
+	_AD5446_CHANNEL(bits, storage, shift, ad5446_ext_info_powerdown)
 
 static int ad5446_read_raw(struct iio_dev *indio_dev,
 			   struct iio_chan_spec const *chan,
@@ -272,14 +212,15 @@ static const struct iio_info ad5446_info = {
 	.driver_module = THIS_MODULE,
 };
 
-static int __devinit ad5446_probe(struct spi_device *spi)
+static int __devinit ad5446_probe(struct device *dev, const char *name,
+	const struct ad5446_chip_info *chip_info)
 {
 	struct ad5446_state *st;
 	struct iio_dev *indio_dev;
 	struct regulator *reg;
 	int ret, voltage_uv = 0;
 
-	reg = regulator_get(&spi->dev, "vcc");
+	reg = regulator_get(dev, "vcc");
 	if (!IS_ERR(reg)) {
 		ret = regulator_enable(reg);
 		if (ret)
@@ -294,16 +235,15 @@ static int __devinit ad5446_probe(struct spi_device *spi)
 		goto error_disable_reg;
 	}
 	st = iio_priv(indio_dev);
-	st->chip_info =
-		&ad5446_chip_info_tbl[spi_get_device_id(spi)->driver_data];
+	st->chip_info = chip_info;
 
-	spi_set_drvdata(spi, indio_dev);
+	dev_set_drvdata(dev, indio_dev);
 	st->reg = reg;
-	st->spi = spi;
+	st->dev = dev;
 
-	/* Establish that the iio_dev is a child of the spi device */
-	indio_dev->dev.parent = &spi->dev;
-	indio_dev->name = spi_get_device_id(spi)->name;
+	/* Establish that the iio_dev is a child of the device */
+	indio_dev->dev.parent = dev;
+	indio_dev->name = name;
 	indio_dev->info = &ad5446_info;
 	indio_dev->modes = INDIO_DIRECT_MODE;
 	indio_dev->channels = &st->chip_info->channel;
@@ -316,7 +256,7 @@ static int __devinit ad5446_probe(struct spi_device *spi)
 	else if (voltage_uv)
 		st->vref_mv = voltage_uv / 1000;
 	else
-		dev_warn(&spi->dev, "reference voltage unspecified\n");
+		dev_warn(dev, "reference voltage unspecified\n");
 
 	ret = iio_device_register(indio_dev);
 	if (ret)
@@ -336,9 +276,9 @@ error_put_reg:
 	return ret;
 }
 
-static int ad5446_remove(struct spi_device *spi)
+static int ad5446_remove(struct device *dev)
 {
-	struct iio_dev *indio_dev = spi_get_drvdata(spi);
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
 	struct ad5446_state *st = iio_priv(indio_dev);
 
 	iio_device_unregister(indio_dev);
@@ -351,7 +291,151 @@ static int ad5446_remove(struct spi_device *spi)
 	return 0;
 }
 
-static const struct spi_device_id ad5446_id[] = {
+#if IS_ENABLED(CONFIG_SPI_MASTER)
+
+static int ad5446_write(struct ad5446_state *st, unsigned val)
+{
+	struct spi_device *spi = to_spi_device(st->dev);
+	__be16 data = cpu_to_be16(val);
+
+	return spi_write(spi, &data, sizeof(data));
+}
+
+static int ad5660_write(struct ad5446_state *st, unsigned val)
+{
+	struct spi_device *spi = to_spi_device(st->dev);
+	uint8_t data[3];
+
+	data[0] = (val >> 16) & 0xFF;
+	data[1] = (val >> 8) & 0xFF;
+	data[2] = val & 0xFF;
+
+	return spi_write(spi, data, sizeof(data));
+}
+
+/**
+ * ad5446_supported_spi_device_ids:
+ * The AD5620/40/60 parts are available in different fixed internal reference
+ * voltage options. The actual part numbers may look differently
+ * (and a bit cryptic), however this style is used to make clear which
+ * parts are supported here.
+ */
+enum ad5446_supported_spi_device_ids {
+	ID_AD5300,
+	ID_AD5310,
+	ID_AD5320,
+	ID_AD5444,
+	ID_AD5446,
+	ID_AD5450,
+	ID_AD5451,
+	ID_AD5541A,
+	ID_AD5512A,
+	ID_AD5553,
+	ID_AD5601,
+	ID_AD5611,
+	ID_AD5621,
+	ID_AD5620_2500,
+	ID_AD5620_1250,
+	ID_AD5640_2500,
+	ID_AD5640_1250,
+	ID_AD5660_2500,
+	ID_AD5660_1250,
+	ID_AD5662,
+};
+
+static const struct ad5446_chip_info ad5446_spi_chip_info[] = {
+	[ID_AD5300] = {
+		.channel = AD5446_CHANNEL_POWERDOWN(8, 16, 4),
+		.write = ad5446_write,
+	},
+	[ID_AD5310] = {
+		.channel = AD5446_CHANNEL_POWERDOWN(10, 16, 2),
+		.write = ad5446_write,
+	},
+	[ID_AD5320] = {
+		.channel = AD5446_CHANNEL_POWERDOWN(12, 16, 0),
+		.write = ad5446_write,
+	},
+	[ID_AD5444] = {
+		.channel = AD5446_CHANNEL(12, 16, 2),
+		.write = ad5446_write,
+	},
+	[ID_AD5446] = {
+		.channel = AD5446_CHANNEL(14, 16, 0),
+		.write = ad5446_write,
+	},
+	[ID_AD5450] = {
+		.channel = AD5446_CHANNEL(8, 16, 6),
+		.write = ad5446_write,
+	},
+	[ID_AD5451] = {
+		.channel = AD5446_CHANNEL(10, 16, 4),
+		.write = ad5446_write,
+	},
+	[ID_AD5541A] = {
+		.channel = AD5446_CHANNEL(16, 16, 0),
+		.write = ad5446_write,
+	},
+	[ID_AD5512A] = {
+		.channel = AD5446_CHANNEL(12, 16, 4),
+		.write = ad5446_write,
+	},
+	[ID_AD5553] = {
+		.channel = AD5446_CHANNEL(14, 16, 0),
+		.write = ad5446_write,
+	},
+	[ID_AD5601] = {
+		.channel = AD5446_CHANNEL_POWERDOWN(8, 16, 6),
+		.write = ad5446_write,
+	},
+	[ID_AD5611] = {
+		.channel = AD5446_CHANNEL_POWERDOWN(10, 16, 4),
+		.write = ad5446_write,
+	},
+	[ID_AD5621] = {
+		.channel = AD5446_CHANNEL_POWERDOWN(12, 16, 2),
+		.write = ad5446_write,
+	},
+	[ID_AD5620_2500] = {
+		.channel = AD5446_CHANNEL_POWERDOWN(12, 16, 2),
+		.int_vref_mv = 2500,
+		.write = ad5446_write,
+	},
+	[ID_AD5620_1250] = {
+		.channel = AD5446_CHANNEL_POWERDOWN(12, 16, 2),
+		.int_vref_mv = 1250,
+		.write = ad5446_write,
+	},
+	[ID_AD5640_2500] = {
+		.channel = AD5446_CHANNEL_POWERDOWN(14, 16, 0),
+		.int_vref_mv = 2500,
+		.write = ad5446_write,
+	},
+	[ID_AD5640_1250] = {
+		.channel = AD5446_CHANNEL_POWERDOWN(14, 16, 0),
+		.int_vref_mv = 1250,
+		.write = ad5446_write,
+	},
+	[ID_AD5660_2500] = {
+		.channel = AD5446_CHANNEL_POWERDOWN(16, 16, 0),
+		.int_vref_mv = 2500,
+		.write = ad5660_write,
+	},
+	[ID_AD5660_1250] = {
+		.channel = AD5446_CHANNEL_POWERDOWN(16, 16, 0),
+		.int_vref_mv = 1250,
+		.write = ad5660_write,
+	},
+	[ID_AD5662] = {
+		.channel = AD5446_CHANNEL_POWERDOWN(16, 16, 0),
+		.write = ad5660_write,
+	},
+};
+
+static const struct spi_device_id ad5446_spi_ids[] = {
+	{"ad5300", ID_AD5300},
+	{"ad5310", ID_AD5310},
+	{"ad5320", ID_AD5320},
 	{"ad5444", ID_AD5444},
 	{"ad5446", ID_AD5446},
 	{"ad5450", ID_AD5450},
@@ -375,18 +459,160 @@ static const struct spi_device_id ad5446_id[] = {
 	{"ad5662", ID_AD5662},
 	{}
 };
-MODULE_DEVICE_TABLE(spi, ad5446_id);
+MODULE_DEVICE_TABLE(spi, ad5446_spi_ids);
+
+static int __devinit ad5446_spi_probe(struct spi_device *spi)
+{
+	const struct spi_device_id *id = spi_get_device_id(spi);
 
-static struct spi_driver ad5446_driver = {
+	return ad5446_probe(&spi->dev, id->name,
+		&ad5446_spi_chip_info[id->driver_data]);
+}
+
+static int __devexit ad5446_spi_remove(struct spi_device *spi)
+{
+	return ad5446_remove(&spi->dev);
+}
+
+static struct spi_driver ad5446_spi_driver = {
 	.driver = {
 		.name	= "ad5446",
 		.owner	= THIS_MODULE,
 	},
-	.probe		= ad5446_probe,
-	.remove		= __devexit_p(ad5446_remove),
-	.id_table	= ad5446_id,
+	.probe		= ad5446_spi_probe,
+	.remove		= __devexit_p(ad5446_spi_remove),
+	.id_table	= ad5446_spi_ids,
 };
-module_spi_driver(ad5446_driver);
+
+static int __init ad5446_spi_register_driver(void)
+{
+	return spi_register_driver(&ad5446_spi_driver);
+}
+
+static void ad5446_spi_unregister_driver(void)
+{
+	spi_unregister_driver(&ad5446_spi_driver);
+}
+
+#else
+
+static inline int ad5446_spi_register_driver(void) { return 0; }
+static inline void ad5446_spi_unregister_driver(void) { }
+
+#endif
+
+#if IS_ENABLED(CONFIG_I2C)
+
+static int ad5622_write(struct ad5446_state *st, unsigned val)
+{
+	struct i2c_client *client = to_i2c_client(st->dev);
+	__be16 data = cpu_to_be16(val);
+
+	return i2c_master_send(client, (char *)&data, sizeof(data));
+}
+
+/**
+ * ad5446_supported_i2c_device_ids:
+ * The AD5620/40/60 parts are available in different fixed internal reference
+ * voltage options. The actual part numbers may look differently
+ * (and a bit cryptic), however this style is used to make clear which
+ * parts are supported here.
+ */
+enum ad5446_supported_i2c_device_ids {
+	ID_AD5602,
+	ID_AD5612,
+	ID_AD5622,
+};
+
+static const struct ad5446_chip_info ad5446_i2c_chip_info[] = {
+	[ID_AD5602] = {
+		.channel = AD5446_CHANNEL_POWERDOWN(8, 16, 4),
+		.write = ad5622_write,
+	},
+	[ID_AD5612] = {
+		.channel = AD5446_CHANNEL_POWERDOWN(10, 16, 2),
+		.write = ad5622_write,
+	},
+	[ID_AD5622] = {
+		.channel = AD5446_CHANNEL_POWERDOWN(12, 16, 0),
+		.write = ad5622_write,
+	},
+};
+
+static int __devinit ad5446_i2c_probe(struct i2c_client *i2c,
+	const struct i2c_device_id *id)
+{
+	return ad5446_probe(&i2c->dev, id->name,
+		&ad5446_i2c_chip_info[id->driver_data]);
+}
+
+static int __devexit ad5446_i2c_remove(struct i2c_client *i2c)
+{
+	return ad5446_remove(&i2c->dev);
+}
+
+static const struct i2c_device_id ad5446_i2c_ids[] = {
+	{"ad5301", ID_AD5602},
+	{"ad5311", ID_AD5612},
+	{"ad5321", ID_AD5622},
+	{"ad5602", ID_AD5602},
+	{"ad5612", ID_AD5612},
+	{"ad5622", ID_AD5622},
+	{}
+};
+MODULE_DEVICE_TABLE(i2c, ad5446_i2c_ids);
+
+static struct i2c_driver ad5446_i2c_driver = {
+	.driver = {
+		   .name = "ad5446",
+		   .owner = THIS_MODULE,
+	},
+	.probe = ad5446_i2c_probe,
+	.remove = __devexit_p(ad5446_i2c_remove),
+	.id_table = ad5446_i2c_ids,
+};
+
+static int __init ad5446_i2c_register_driver(void)
+{
+	return i2c_add_driver(&ad5446_i2c_driver);
+}
+
+static void __exit ad5446_i2c_unregister_driver(void)
+{
+	i2c_del_driver(&ad5446_i2c_driver);
+}
+
+#else
+
+static inline int ad5446_i2c_register_driver(void) { return 0; }
+static inline void ad5446_i2c_unregister_driver(void) { }
+
+#endif
+
+static int __init ad5446_init(void)
+{
+	int ret;
+
+	ret = ad5446_spi_register_driver();
+	if (ret)
+		return ret;
+
+	ret = ad5446_i2c_register_driver();
+	if (ret) {
+		ad5446_spi_unregister_driver();
+		return ret;
+	}
+
+	return 0;
+}
+module_init(ad5446_init);
+
+static void __exit ad5446_exit(void)
+{
+	ad5446_i2c_unregister_driver();
+	ad5446_spi_unregister_driver();
+}
+module_exit(ad5446_exit);
 
 MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
 MODULE_DESCRIPTION("Analog Devices AD5444/AD5446 DAC");
diff --git a/drivers/iio/dac/ad5446.h b/drivers/iio/dac/ad5446.h
deleted file mode 100644
index 2934269..0000000
--- a/drivers/iio/dac/ad5446.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * AD5446 SPI DAC driver
- *
- * Copyright 2010 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- */
-#ifndef IIO_DAC_AD5446_H_
-#define IIO_DAC_AD5446_H_
-
-/* DAC Control Bits */
-
-#define AD5446_LOAD		(0x0 << 14) /* Load and update */
-#define AD5446_SDO_DIS		(0x1 << 14) /* Disable SDO */
-#define AD5446_NOP		(0x2 << 14) /* No operation */
-#define AD5446_CLK_RISING	(0x3 << 14) /* Clock data on rising edge */
-
-#define AD5620_LOAD		(0x0 << 14) /* Load and update Norm Operation*/
-#define AD5620_PWRDWN_1k	(0x1 << 14) /* Power-down: 1kOhm to GND */
-#define AD5620_PWRDWN_100k	(0x2 << 14) /* Power-down: 100kOhm to GND */
-#define AD5620_PWRDWN_TRISTATE	(0x3 << 14) /* Power-down: Three-state */
-
-#define AD5660_LOAD		(0x0 << 16) /* Load and update Norm Operation*/
-#define AD5660_PWRDWN_1k	(0x1 << 16) /* Power-down: 1kOhm to GND */
-#define AD5660_PWRDWN_100k	(0x2 << 16) /* Power-down: 100kOhm to GND */
-#define AD5660_PWRDWN_TRISTATE	(0x3 << 16) /* Power-down: Three-state */
-
-#define MODE_PWRDWN_1k		0x1
-#define MODE_PWRDWN_100k	0x2
-#define MODE_PWRDWN_TRISTATE	0x3
-
-/**
- * struct ad5446_state - driver instance specific data
- * @spi:		spi_device
- * @chip_info:		chip model specific constants, available modes etc
- * @reg:		supply regulator
- * @vref_mv:		actual reference voltage used
- */
-
-struct ad5446_state {
-	struct spi_device		*spi;
-	const struct ad5446_chip_info	*chip_info;
-	struct regulator		*reg;
-	unsigned short			vref_mv;
-	unsigned			cached_val;
-	unsigned			pwr_down_mode;
-	unsigned			pwr_down;
-};
-
-/**
- * struct ad5446_chip_info - chip specific information
- * @channel:		channel spec for the DAC
- * @int_vref_mv:	AD5620/40/60: the internal reference voltage
- * @write:		chip specific helper function to write to the register
- */
-
-struct ad5446_chip_info {
-	struct iio_chan_spec	channel;
-	u16			int_vref_mv;
-	int			(*write)(struct ad5446_state *st, unsigned val);
-};
-
-/**
- * ad5446_supported_device_ids:
- * The AD5620/40/60 parts are available in different fixed internal reference
- * voltage options. The actual part numbers may look differently
- * (and a bit cryptic), however this style is used to make clear which
- * parts are supported here.
- */
-
-enum ad5446_supported_device_ids {
-	ID_AD5444,
-	ID_AD5446,
-	ID_AD5450,
-	ID_AD5451,
-	ID_AD5541A,
-	ID_AD5512A,
-	ID_AD5553,
-	ID_AD5601,
-	ID_AD5611,
-	ID_AD5621,
-	ID_AD5620_2500,
-	ID_AD5620_1250,
-	ID_AD5640_2500,
-	ID_AD5640_1250,
-	ID_AD5660_2500,
-	ID_AD5660_1250,
-	ID_AD5662,
-};
-
-#endif /* IIO_DAC_AD5446_H_ */
diff --git a/drivers/iio/dac/ad5755.c b/drivers/iio/dac/ad5755.c
new file mode 100644
index 0000000..e6dbe5f
--- /dev/null
+++ b/drivers/iio/dac/ad5755.c
@@ -0,0 +1,650 @@
+/*
+ * AD5755, AD5755-1, AD5757, AD5735, AD5737 Digital to analog converters driver
+ *
+ * Copyright 2012 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/spi/spi.h>
+#include <linux/slab.h>
+#include <linux/sysfs.h>
+#include <linux/delay.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/platform_data/ad5755.h>
+
+#define AD5755_NUM_CHANNELS 4
+
+#define AD5755_ADDR(x)			((x) << 16)
+
+#define AD5755_WRITE_REG_DATA(chan)	(chan)
+#define AD5755_WRITE_REG_GAIN(chan)	(0x08 | (chan))
+#define AD5755_WRITE_REG_OFFSET(chan)	(0x10 | (chan))
+#define AD5755_WRITE_REG_CTRL(chan)	(0x1c | (chan))
+
+#define AD5755_READ_REG_DATA(chan)	(chan)
+#define AD5755_READ_REG_CTRL(chan)	(0x4 | (chan))
+#define AD5755_READ_REG_GAIN(chan)	(0x8 | (chan))
+#define AD5755_READ_REG_OFFSET(chan)	(0xc | (chan))
+#define AD5755_READ_REG_CLEAR(chan)	(0x10 | (chan))
+#define AD5755_READ_REG_SLEW(chan)	(0x14 | (chan))
+#define AD5755_READ_REG_STATUS		0x18
+#define AD5755_READ_REG_MAIN		0x19
+#define AD5755_READ_REG_DC_DC		0x1a
+
+#define AD5755_CTRL_REG_SLEW	0x0
+#define AD5755_CTRL_REG_MAIN	0x1
+#define AD5755_CTRL_REG_DAC	0x2
+#define AD5755_CTRL_REG_DC_DC	0x3
+#define AD5755_CTRL_REG_SW	0x4
+
+#define AD5755_READ_FLAG 0x800000
+
+#define AD5755_NOOP 0x1CE000
+
+#define AD5755_DAC_INT_EN			BIT(8)
+#define AD5755_DAC_CLR_EN			BIT(7)
+#define AD5755_DAC_OUT_EN			BIT(6)
+#define AD5755_DAC_INT_CURRENT_SENSE_RESISTOR	BIT(5)
+#define AD5755_DAC_DC_DC_EN			BIT(4)
+#define AD5755_DAC_VOLTAGE_OVERRANGE_EN		BIT(3)
+
+#define AD5755_DC_DC_MAXV			0
+#define AD5755_DC_DC_FREQ_SHIFT			2
+#define AD5755_DC_DC_PHASE_SHIFT		4
+#define AD5755_EXT_DC_DC_COMP_RES		BIT(6)
+
+#define AD5755_SLEW_STEP_SIZE_SHIFT		0
+#define AD5755_SLEW_RATE_SHIFT			3
+#define AD5755_SLEW_ENABLE			BIT(12)
+
+/**
+ * struct ad5755_chip_info - chip specific information
+ * @channel_template:	channel specification
+ * @calib_shift:	shift for the calibration data registers
+ * @has_voltage_out:	whether the chip has voltage outputs
+ */
+struct ad5755_chip_info {
+	const struct iio_chan_spec channel_template;
+	unsigned int calib_shift;
+	bool has_voltage_out;
+};
+
+/**
+ * struct ad5755_state - driver instance specific data
+ * @spi:	spi device the driver is attached to
+ * @chip_info:	chip model specific constants, available modes etc
+ * @pwr_down:	bitmask which contains  hether a channel is powered down or not
+ * @ctrl:	software shadow of the channel ctrl registers
+ * @channels:	iio channel spec for the device
+ * @data:	spi transfer buffers
+ */
+struct ad5755_state {
+	struct spi_device		*spi;
+	const struct ad5755_chip_info	*chip_info;
+	unsigned int			pwr_down;
+	unsigned int			ctrl[AD5755_NUM_CHANNELS];
+	struct iio_chan_spec		channels[AD5755_NUM_CHANNELS];
+
+	/*
+	 * DMA (thus cache coherency maintenance) requires the
+	 * transfer buffers to live in their own cache lines.
+	 */
+
+	union {
+		u32 d32;
+		u8 d8[4];
+	} data[2] ____cacheline_aligned;
+};
+
+enum ad5755_type {
+	ID_AD5755,
+	ID_AD5757,
+	ID_AD5735,
+	ID_AD5737,
+};
+
+static int ad5755_write_unlocked(struct iio_dev *indio_dev,
+	unsigned int reg, unsigned int val)
+{
+	struct ad5755_state *st = iio_priv(indio_dev);
+
+	st->data[0].d32 = cpu_to_be32((reg << 16) | val);
+
+	return spi_write(st->spi, &st->data[0].d8[1], 3);
+}
+
+static int ad5755_write_ctrl_unlocked(struct iio_dev *indio_dev,
+	unsigned int channel, unsigned int reg, unsigned int val)
+{
+	return ad5755_write_unlocked(indio_dev,
+		AD5755_WRITE_REG_CTRL(channel), (reg << 13) | val);
+}
+
+static int ad5755_write(struct iio_dev *indio_dev, unsigned int reg,
+	unsigned int val)
+{
+	int ret;
+
+	mutex_lock(&indio_dev->mlock);
+	ret = ad5755_write_unlocked(indio_dev, reg, val);
+	mutex_unlock(&indio_dev->mlock);
+
+	return ret;
+}
+
+static int ad5755_write_ctrl(struct iio_dev *indio_dev, unsigned int channel,
+	unsigned int reg, unsigned int val)
+{
+	int ret;
+
+	mutex_lock(&indio_dev->mlock);
+	ret = ad5755_write_ctrl_unlocked(indio_dev, channel, reg, val);
+	mutex_unlock(&indio_dev->mlock);
+
+	return ret;
+}
+
+static int ad5755_read(struct iio_dev *indio_dev, unsigned int addr)
+{
+	struct ad5755_state *st = iio_priv(indio_dev);
+	struct spi_message m;
+	int ret;
+	struct spi_transfer t[] = {
+		{
+			.tx_buf = &st->data[0].d8[1],
+			.len = 3,
+			.cs_change = 1,
+		}, {
+			.tx_buf = &st->data[1].d8[1],
+			.rx_buf = &st->data[1].d8[1],
+			.len = 3,
+		},
+	};
+
+	spi_message_init(&m);
+	spi_message_add_tail(&t[0], &m);
+	spi_message_add_tail(&t[1], &m);
+
+	mutex_lock(&indio_dev->mlock);
+
+	st->data[0].d32 = cpu_to_be32(AD5755_READ_FLAG | (addr << 16));
+	st->data[1].d32 = cpu_to_be32(AD5755_NOOP);
+
+	ret = spi_sync(st->spi, &m);
+	if (ret >= 0)
+		ret = be32_to_cpu(st->data[1].d32) & 0xffff;
+
+	mutex_unlock(&indio_dev->mlock);
+
+	return ret;
+}
+
+static int ad5755_update_dac_ctrl(struct iio_dev *indio_dev,
+	unsigned int channel, unsigned int set, unsigned int clr)
+{
+	struct ad5755_state *st = iio_priv(indio_dev);
+	int ret;
+
+	st->ctrl[channel] |= set;
+	st->ctrl[channel] &= ~clr;
+
+	ret = ad5755_write_ctrl_unlocked(indio_dev, channel,
+		AD5755_CTRL_REG_DAC, st->ctrl[channel]);
+
+	return ret;
+}
+
+static int ad5755_set_channel_pwr_down(struct iio_dev *indio_dev,
+	unsigned int channel, bool pwr_down)
+{
+	struct ad5755_state *st = iio_priv(indio_dev);
+	unsigned int mask = BIT(channel);
+
+	mutex_lock(&indio_dev->mlock);
+
+	if ((bool)(st->pwr_down & mask) == pwr_down)
+		goto out_unlock;
+
+	if (!pwr_down) {
+		st->pwr_down &= ~mask;
+		ad5755_update_dac_ctrl(indio_dev, channel,
+			AD5755_DAC_INT_EN | AD5755_DAC_DC_DC_EN, 0);
+		udelay(200);
+		ad5755_update_dac_ctrl(indio_dev, channel,
+			AD5755_DAC_OUT_EN, 0);
+	} else {
+		st->pwr_down |= mask;
+		ad5755_update_dac_ctrl(indio_dev, channel,
+			0, AD5755_DAC_INT_EN | AD5755_DAC_OUT_EN |
+				AD5755_DAC_DC_DC_EN);
+	}
+
+out_unlock:
+	mutex_unlock(&indio_dev->mlock);
+
+	return 0;
+}
+
+static const int ad5755_min_max_table[][2] = {
+	[AD5755_MODE_VOLTAGE_0V_5V] = { 0, 5000 },
+	[AD5755_MODE_VOLTAGE_0V_10V] = { 0, 10000 },
+	[AD5755_MODE_VOLTAGE_PLUSMINUS_5V] = { -5000, 5000 },
+	[AD5755_MODE_VOLTAGE_PLUSMINUS_10V] = { -10000, 10000 },
+	[AD5755_MODE_CURRENT_4mA_20mA] = { 4, 20 },
+	[AD5755_MODE_CURRENT_0mA_20mA] = { 0, 20 },
+	[AD5755_MODE_CURRENT_0mA_24mA] = { 0, 24 },
+};
+
+static void ad5755_get_min_max(struct ad5755_state *st,
+	struct iio_chan_spec const *chan, int *min, int *max)
+{
+	enum ad5755_mode mode = st->ctrl[chan->channel] & 7;
+	*min = ad5755_min_max_table[mode][0];
+	*max = ad5755_min_max_table[mode][1];
+}
+
+static inline int ad5755_get_offset(struct ad5755_state *st,
+	struct iio_chan_spec const *chan)
+{
+	int min, max;
+
+	ad5755_get_min_max(st, chan, &min, &max);
+	return (min * (1 << chan->scan_type.realbits)) / (max - min);
+}
+
+static inline int ad5755_get_scale(struct ad5755_state *st,
+	struct iio_chan_spec const *chan)
+{
+	int min, max;
+
+	ad5755_get_min_max(st, chan, &min, &max);
+	return ((max - min) * 1000000000ULL) >> chan->scan_type.realbits;
+}
+
+static int ad5755_chan_reg_info(struct ad5755_state *st,
+	struct iio_chan_spec const *chan, long info, bool write,
+	unsigned int *reg, unsigned int *shift, unsigned int *offset)
+{
+	switch (info) {
+	case IIO_CHAN_INFO_RAW:
+		if (write)
+			*reg = AD5755_WRITE_REG_DATA(chan->address);
+		else
+			*reg = AD5755_READ_REG_DATA(chan->address);
+		*shift = chan->scan_type.shift;
+		*offset = 0;
+		break;
+	case IIO_CHAN_INFO_CALIBBIAS:
+		if (write)
+			*reg = AD5755_WRITE_REG_OFFSET(chan->address);
+		else
+			*reg = AD5755_READ_REG_OFFSET(chan->address);
+		*shift = st->chip_info->calib_shift;
+		*offset = 32768;
+		break;
+	case IIO_CHAN_INFO_CALIBSCALE:
+		if (write)
+			*reg =  AD5755_WRITE_REG_GAIN(chan->address);
+		else
+			*reg =  AD5755_READ_REG_GAIN(chan->address);
+		*shift = st->chip_info->calib_shift;
+		*offset = 0;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int ad5755_read_raw(struct iio_dev *indio_dev,
+	const struct iio_chan_spec *chan, int *val, int *val2, long info)
+{
+	struct ad5755_state *st = iio_priv(indio_dev);
+	unsigned int reg, shift, offset;
+	int ret;
+
+	switch (info) {
+	case IIO_CHAN_INFO_SCALE:
+		*val = 0;
+		*val2 = ad5755_get_scale(st, chan);
+		return IIO_VAL_INT_PLUS_NANO;
+	case IIO_CHAN_INFO_OFFSET:
+		*val = ad5755_get_offset(st, chan);
+		return IIO_VAL_INT;
+	default:
+		ret = ad5755_chan_reg_info(st, chan, info, false,
+						&reg, &shift, &offset);
+		if (ret)
+			return ret;
+
+		ret = ad5755_read(indio_dev, reg);
+		if (ret < 0)
+			return ret;
+
+		*val = (ret - offset) >> shift;
+
+		return IIO_VAL_INT;
+	}
+
+	return -EINVAL;
+}
+
+static int ad5755_write_raw(struct iio_dev *indio_dev,
+	const struct iio_chan_spec *chan, int val, int val2, long info)
+{
+	struct ad5755_state *st = iio_priv(indio_dev);
+	unsigned int shift, reg, offset;
+	int ret;
+
+	ret = ad5755_chan_reg_info(st, chan, info, true,
+					&reg, &shift, &offset);
+	if (ret)
+		return ret;
+
+	val <<= shift;
+	val += offset;
+
+	if (val < 0 || val > 0xffff)
+		return -EINVAL;
+
+	return ad5755_write(indio_dev, reg, val);
+}
+
+static ssize_t ad5755_read_powerdown(struct iio_dev *indio_dev, uintptr_t priv,
+	const struct iio_chan_spec *chan, char *buf)
+{
+	struct ad5755_state *st = iio_priv(indio_dev);
+
+	return sprintf(buf, "%d\n",
+		       (bool)(st->pwr_down & (1 << chan->channel)));
+}
+
+static ssize_t ad5755_write_powerdown(struct iio_dev *indio_dev, uintptr_t priv,
+	struct iio_chan_spec const *chan, const char *buf, size_t len)
+{
+	bool pwr_down;
+	int ret;
+
+	ret = strtobool(buf, &pwr_down);
+	if (ret)
+		return ret;
+
+	ret = ad5755_set_channel_pwr_down(indio_dev, chan->channel, pwr_down);
+	return ret ? ret : len;
+}
+
+static const struct iio_info ad5755_info = {
+	.read_raw = ad5755_read_raw,
+	.write_raw = ad5755_write_raw,
+	.driver_module = THIS_MODULE,
+};
+
+static const struct iio_chan_spec_ext_info ad5755_ext_info[] = {
+	{
+		.name = "powerdown",
+		.read = ad5755_read_powerdown,
+		.write = ad5755_write_powerdown,
+	},
+	{ },
+};
+
+#define AD5755_CHANNEL(_bits) {					\
+	.indexed = 1,						\
+	.output = 1,						\
+	.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |		\
+		IIO_CHAN_INFO_SCALE_SEPARATE_BIT |		\
+		IIO_CHAN_INFO_OFFSET_SEPARATE_BIT |		\
+		IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT |		\
+		IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT,		\
+	.scan_type = IIO_ST('u', (_bits), 16, 16 - (_bits)),	\
+	.ext_info = ad5755_ext_info,				\
+}
+
+static const struct ad5755_chip_info ad5755_chip_info_tbl[] = {
+	[ID_AD5735] = {
+		.channel_template = AD5755_CHANNEL(14),
+		.has_voltage_out = true,
+		.calib_shift = 4,
+	},
+	[ID_AD5737] = {
+		.channel_template = AD5755_CHANNEL(14),
+		.has_voltage_out = false,
+		.calib_shift = 4,
+	},
+	[ID_AD5755] = {
+		.channel_template = AD5755_CHANNEL(16),
+		.has_voltage_out = true,
+		.calib_shift = 0,
+	},
+	[ID_AD5757] = {
+		.channel_template = AD5755_CHANNEL(16),
+		.has_voltage_out = false,
+		.calib_shift = 0,
+	},
+};
+
+static bool ad5755_is_valid_mode(struct ad5755_state *st, enum ad5755_mode mode)
+{
+	switch (mode) {
+	case AD5755_MODE_VOLTAGE_0V_5V:
+	case AD5755_MODE_VOLTAGE_0V_10V:
+	case AD5755_MODE_VOLTAGE_PLUSMINUS_5V:
+	case AD5755_MODE_VOLTAGE_PLUSMINUS_10V:
+		return st->chip_info->has_voltage_out;
+	case AD5755_MODE_CURRENT_4mA_20mA:
+	case AD5755_MODE_CURRENT_0mA_20mA:
+	case AD5755_MODE_CURRENT_0mA_24mA:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static int __devinit ad5755_setup_pdata(struct iio_dev *indio_dev,
+	const struct ad5755_platform_data *pdata)
+{
+	struct ad5755_state *st = iio_priv(indio_dev);
+	unsigned int ret;
+	unsigned int val;
+	unsigned int i;
+
+	if (pdata->dc_dc_phase > AD5755_DC_DC_PHASE_90_DEGREE ||
+		pdata->dc_dc_freq > AD5755_DC_DC_FREQ_650kHZ ||
+		pdata->dc_dc_maxv > AD5755_DC_DC_MAXV_29V5)
+		return -EINVAL;
+
+	val = pdata->dc_dc_maxv << AD5755_DC_DC_MAXV;
+	val |= pdata->dc_dc_freq << AD5755_DC_DC_FREQ_SHIFT;
+	val |= pdata->dc_dc_phase << AD5755_DC_DC_PHASE_SHIFT;
+	if (pdata->ext_dc_dc_compenstation_resistor)
+		val |= AD5755_EXT_DC_DC_COMP_RES;
+
+	ret = ad5755_write_ctrl(indio_dev, 0, AD5755_CTRL_REG_DC_DC, val);
+	if (ret < 0)
+		return ret;
+
+	for (i = 0; i < ARRAY_SIZE(pdata->dac); ++i) {
+		val = pdata->dac[i].slew.step_size <<
+			AD5755_SLEW_STEP_SIZE_SHIFT;
+		val |= pdata->dac[i].slew.rate <<
+			AD5755_SLEW_RATE_SHIFT;
+		if (pdata->dac[i].slew.enable)
+			val |= AD5755_SLEW_ENABLE;
+
+		ret = ad5755_write_ctrl(indio_dev, i,
+					AD5755_CTRL_REG_SLEW, val);
+		if (ret < 0)
+			return ret;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(pdata->dac); ++i) {
+		if (!ad5755_is_valid_mode(st, pdata->dac[i].mode))
+			return -EINVAL;
+
+		val = 0;
+		if (!pdata->dac[i].ext_current_sense_resistor)
+			val |= AD5755_DAC_INT_CURRENT_SENSE_RESISTOR;
+		if (pdata->dac[i].enable_voltage_overrange)
+			val |= AD5755_DAC_VOLTAGE_OVERRANGE_EN;
+		val |= pdata->dac[i].mode;
+
+		ret = ad5755_update_dac_ctrl(indio_dev, i, val, 0);
+		if (ret < 0)
+			return ret;
+	}
+
+	return 0;
+}
+
+static bool __devinit ad5755_is_voltage_mode(enum ad5755_mode mode)
+{
+	switch (mode) {
+	case AD5755_MODE_VOLTAGE_0V_5V:
+	case AD5755_MODE_VOLTAGE_0V_10V:
+	case AD5755_MODE_VOLTAGE_PLUSMINUS_5V:
+	case AD5755_MODE_VOLTAGE_PLUSMINUS_10V:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static int __devinit ad5755_init_channels(struct iio_dev *indio_dev,
+	const struct ad5755_platform_data *pdata)
+{
+	struct ad5755_state *st = iio_priv(indio_dev);
+	struct iio_chan_spec *channels = st->channels;
+	unsigned int i;
+
+	for (i = 0; i < AD5755_NUM_CHANNELS; ++i) {
+		channels[i] = st->chip_info->channel_template;
+		channels[i].channel = i;
+		channels[i].address = i;
+		if (pdata && ad5755_is_voltage_mode(pdata->dac[i].mode))
+			channels[i].type = IIO_VOLTAGE;
+		else
+			channels[i].type = IIO_CURRENT;
+	}
+
+	indio_dev->channels = channels;
+
+	return 0;
+}
+
+#define AD5755_DEFAULT_DAC_PDATA { \
+		.mode = AD5755_MODE_CURRENT_4mA_20mA, \
+		.ext_current_sense_resistor = true, \
+		.enable_voltage_overrange = false, \
+		.slew = { \
+			.enable = false, \
+			.rate = AD5755_SLEW_RATE_64k, \
+			.step_size = AD5755_SLEW_STEP_SIZE_1, \
+		}, \
+	}
+
+static const struct ad5755_platform_data ad5755_default_pdata = {
+	.ext_dc_dc_compenstation_resistor = false,
+	.dc_dc_phase = AD5755_DC_DC_PHASE_ALL_SAME_EDGE,
+	.dc_dc_freq = AD5755_DC_DC_FREQ_410kHZ,
+	.dc_dc_maxv = AD5755_DC_DC_MAXV_23V,
+	.dac = {
+		[0] = AD5755_DEFAULT_DAC_PDATA,
+		[1] = AD5755_DEFAULT_DAC_PDATA,
+		[2] = AD5755_DEFAULT_DAC_PDATA,
+		[3] = AD5755_DEFAULT_DAC_PDATA,
+	},
+};
+
+static int __devinit ad5755_probe(struct spi_device *spi)
+{
+	enum ad5755_type type = spi_get_device_id(spi)->driver_data;
+	const struct ad5755_platform_data *pdata = dev_get_platdata(&spi->dev);
+	struct iio_dev *indio_dev;
+	struct ad5755_state *st;
+	int ret;
+
+	indio_dev = iio_device_alloc(sizeof(*st));
+	if (indio_dev == NULL) {
+		dev_err(&spi->dev, "Failed to allocate iio device\n");
+		return  -ENOMEM;
+	}
+
+	st = iio_priv(indio_dev);
+	spi_set_drvdata(spi, indio_dev);
+
+	st->chip_info = &ad5755_chip_info_tbl[type];
+	st->spi = spi;
+	st->pwr_down = 0xf;
+
+	indio_dev->dev.parent = &spi->dev;
+	indio_dev->name = spi_get_device_id(spi)->name;
+	indio_dev->info = &ad5755_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->num_channels = AD5755_NUM_CHANNELS;
+
+	if (!pdata)
+		pdata = &ad5755_default_pdata;
+
+	ret = ad5755_init_channels(indio_dev, pdata);
+	if (ret)
+		goto error_free;
+
+	ret = ad5755_setup_pdata(indio_dev, pdata);
+	if (ret)
+		goto error_free;
+
+	ret = iio_device_register(indio_dev);
+	if (ret) {
+		dev_err(&spi->dev, "Failed to register iio device: %d\n", ret);
+		goto error_free;
+	}
+
+	return 0;
+
+error_free:
+	iio_device_free(indio_dev);
+
+	return ret;
+}
+
+static int __devexit ad5755_remove(struct spi_device *spi)
+{
+	struct iio_dev *indio_dev = spi_get_drvdata(spi);
+
+	iio_device_unregister(indio_dev);
+	iio_device_free(indio_dev);
+
+	return 0;
+}
+
+static const struct spi_device_id ad5755_id[] = {
+	{ "ad5755", ID_AD5755 },
+	{ "ad5755-1", ID_AD5755 },
+	{ "ad5757", ID_AD5757 },
+	{ "ad5735", ID_AD5735 },
+	{ "ad5737", ID_AD5737 },
+	{}
+};
+MODULE_DEVICE_TABLE(spi, ad5755_id);
+
+static struct spi_driver ad5755_driver = {
+	.driver = {
+		.name = "ad5755",
+		.owner = THIS_MODULE,
+	},
+	.probe = ad5755_probe,
+	.remove = __devexit_p(ad5755_remove),
+	.id_table = ad5755_id,
+};
+module_spi_driver(ad5755_driver);
+
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_DESCRIPTION("Analog Devices AD5755/55-1/57/35/37 DAC");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/gyro/Kconfig b/drivers/iio/gyro/Kconfig
new file mode 100644
index 0000000..21e27e2
--- /dev/null
+++ b/drivers/iio/gyro/Kconfig
@@ -0,0 +1,16 @@
+#
+# IIO Digital Gyroscope Sensor drivers configuration
+#
+menu "Digital gyroscope sensors"
+
+config HID_SENSOR_GYRO_3D
+	depends on HID_SENSOR_HUB
+	select IIO_BUFFER
+	select IIO_TRIGGERED_BUFFER
+	select HID_SENSOR_IIO_COMMON
+	tristate "HID Gyroscope 3D"
+	help
+	  Say yes here to build support for the HID SENSOR
+	  Gyroscope 3D.
+
+endmenu
diff --git a/drivers/iio/gyro/Makefile b/drivers/iio/gyro/Makefile
new file mode 100644
index 0000000..8a895d9
--- /dev/null
+++ b/drivers/iio/gyro/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for industrial I/O gyroscope sensor drivers
+#
+
+obj-$(CONFIG_HID_SENSOR_GYRO_3D) += hid-sensor-gyro-3d.o
diff --git a/drivers/iio/gyro/hid-sensor-gyro-3d.c b/drivers/iio/gyro/hid-sensor-gyro-3d.c
new file mode 100644
index 0000000..4c56ada
--- /dev/null
+++ b/drivers/iio/gyro/hid-sensor-gyro-3d.c
@@ -0,0 +1,418 @@
+/*
+ * HID Sensors Driver
+ * Copyright (c) 2012, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/slab.h>
+#include <linux/hid-sensor-hub.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
+#include "../common/hid-sensors/hid-sensor-attributes.h"
+#include "../common/hid-sensors/hid-sensor-trigger.h"
+
+/*Format: HID-SENSOR-usage_id_in_hex*/
+/*Usage ID from spec for Gyro-3D: 0x200076*/
+#define DRIVER_NAME "HID-SENSOR-200076"
+
+enum gyro_3d_channel {
+	CHANNEL_SCAN_INDEX_X,
+	CHANNEL_SCAN_INDEX_Y,
+	CHANNEL_SCAN_INDEX_Z,
+	GYRO_3D_CHANNEL_MAX,
+};
+
+struct gyro_3d_state {
+	struct hid_sensor_hub_callbacks callbacks;
+	struct hid_sensor_iio_common common_attributes;
+	struct hid_sensor_hub_attribute_info gyro[GYRO_3D_CHANNEL_MAX];
+	u32 gyro_val[GYRO_3D_CHANNEL_MAX];
+};
+
+static const u32 gyro_3d_addresses[GYRO_3D_CHANNEL_MAX] = {
+	HID_USAGE_SENSOR_ANGL_VELOCITY_X_AXIS,
+	HID_USAGE_SENSOR_ANGL_VELOCITY_Y_AXIS,
+	HID_USAGE_SENSOR_ANGL_VELOCITY_Z_AXIS
+};
+
+/* Channel definitions */
+static const struct iio_chan_spec gyro_3d_channels[] = {
+	{
+		.type = IIO_ANGL_VEL,
+		.modified = 1,
+		.channel2 = IIO_MOD_X,
+		.info_mask = IIO_CHAN_INFO_OFFSET_SHARED_BIT |
+		IIO_CHAN_INFO_SCALE_SHARED_BIT |
+		IIO_CHAN_INFO_SAMP_FREQ_SHARED_BIT |
+		IIO_CHAN_INFO_HYSTERESIS_SHARED_BIT,
+		.scan_index = CHANNEL_SCAN_INDEX_X,
+	}, {
+		.type = IIO_ANGL_VEL,
+		.modified = 1,
+		.channel2 = IIO_MOD_Y,
+		.info_mask = IIO_CHAN_INFO_OFFSET_SHARED_BIT |
+		IIO_CHAN_INFO_SCALE_SHARED_BIT |
+		IIO_CHAN_INFO_SAMP_FREQ_SHARED_BIT |
+		IIO_CHAN_INFO_HYSTERESIS_SHARED_BIT,
+		.scan_index = CHANNEL_SCAN_INDEX_Y,
+	}, {
+		.type = IIO_ANGL_VEL,
+		.modified = 1,
+		.channel2 = IIO_MOD_Z,
+		.info_mask = IIO_CHAN_INFO_OFFSET_SHARED_BIT |
+		IIO_CHAN_INFO_SCALE_SHARED_BIT |
+		IIO_CHAN_INFO_SAMP_FREQ_SHARED_BIT |
+		IIO_CHAN_INFO_HYSTERESIS_SHARED_BIT,
+		.scan_index = CHANNEL_SCAN_INDEX_Z,
+	}
+};
+
+/* Adjust channel real bits based on report descriptor */
+static void gyro_3d_adjust_channel_bit_mask(struct iio_chan_spec *channels,
+						int channel, int size)
+{
+	channels[channel].scan_type.sign = 's';
+	/* Real storage bits will change based on the report desc. */
+	channels[channel].scan_type.realbits = size * 8;
+	/* Maximum size of a sample to capture is u32 */
+	channels[channel].scan_type.storagebits = sizeof(u32) * 8;
+}
+
+/* Channel read_raw handler */
+static int gyro_3d_read_raw(struct iio_dev *indio_dev,
+			      struct iio_chan_spec const *chan,
+			      int *val, int *val2,
+			      long mask)
+{
+	struct gyro_3d_state *gyro_state = iio_priv(indio_dev);
+	int report_id = -1;
+	u32 address;
+	int ret;
+	int ret_type;
+
+	*val = 0;
+	*val2 = 0;
+	switch (mask) {
+	case 0:
+		report_id = gyro_state->gyro[chan->scan_index].report_id;
+		address = gyro_3d_addresses[chan->scan_index];
+		if (report_id >= 0)
+			*val = sensor_hub_input_attr_get_raw_value(
+				gyro_state->common_attributes.hsdev,
+				HID_USAGE_SENSOR_GYRO_3D, address,
+				report_id);
+		else {
+			*val = 0;
+			return -EINVAL;
+		}
+		ret_type = IIO_VAL_INT;
+		break;
+	case IIO_CHAN_INFO_SCALE:
+		*val = gyro_state->gyro[CHANNEL_SCAN_INDEX_X].units;
+		ret_type = IIO_VAL_INT;
+		break;
+	case IIO_CHAN_INFO_OFFSET:
+		*val = hid_sensor_convert_exponent(
+			gyro_state->gyro[CHANNEL_SCAN_INDEX_X].unit_expo);
+		ret_type = IIO_VAL_INT;
+		break;
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		ret = hid_sensor_read_samp_freq_value(
+			&gyro_state->common_attributes, val, val2);
+			ret_type = IIO_VAL_INT_PLUS_MICRO;
+		break;
+	case IIO_CHAN_INFO_HYSTERESIS:
+		ret = hid_sensor_read_raw_hyst_value(
+			&gyro_state->common_attributes, val, val2);
+		ret_type = IIO_VAL_INT_PLUS_MICRO;
+		break;
+	default:
+		ret_type = -EINVAL;
+		break;
+	}
+
+	return ret_type;
+}
+
+/* Channel write_raw handler */
+static int gyro_3d_write_raw(struct iio_dev *indio_dev,
+			       struct iio_chan_spec const *chan,
+			       int val,
+			       int val2,
+			       long mask)
+{
+	struct gyro_3d_state *gyro_state = iio_priv(indio_dev);
+	int ret = 0;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		ret = hid_sensor_write_samp_freq_value(
+				&gyro_state->common_attributes, val, val2);
+		break;
+	case IIO_CHAN_INFO_HYSTERESIS:
+		ret = hid_sensor_write_raw_hyst_value(
+				&gyro_state->common_attributes, val, val2);
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static int gyro_3d_write_raw_get_fmt(struct iio_dev *indio_dev,
+			       struct iio_chan_spec const *chan,
+			       long mask)
+{
+	return IIO_VAL_INT_PLUS_MICRO;
+}
+
+static const struct iio_info gyro_3d_info = {
+	.driver_module = THIS_MODULE,
+	.read_raw = &gyro_3d_read_raw,
+	.write_raw = &gyro_3d_write_raw,
+	.write_raw_get_fmt = &gyro_3d_write_raw_get_fmt,
+};
+
+/* Function to push data to buffer */
+static void hid_sensor_push_data(struct iio_dev *indio_dev, u8 *data, int len)
+{
+	struct iio_buffer *buffer = indio_dev->buffer;
+	int datum_sz;
+
+	dev_dbg(&indio_dev->dev, "hid_sensor_push_data\n");
+	if (!buffer) {
+		dev_err(&indio_dev->dev, "Buffer == NULL\n");
+		return;
+	}
+	datum_sz = buffer->access->get_bytes_per_datum(buffer);
+	if (len > datum_sz) {
+		dev_err(&indio_dev->dev, "Datum size mismatch %d:%d\n", len,
+				datum_sz);
+		return;
+	}
+	iio_push_to_buffer(buffer, (u8 *)data);
+}
+
+/* Callback handler to send event after all samples are received and captured */
+static int gyro_3d_proc_event(struct hid_sensor_hub_device *hsdev,
+				unsigned usage_id,
+				void *priv)
+{
+	struct iio_dev *indio_dev = platform_get_drvdata(priv);
+	struct gyro_3d_state *gyro_state = iio_priv(indio_dev);
+
+	dev_dbg(&indio_dev->dev, "gyro_3d_proc_event [%d]\n",
+				gyro_state->common_attributes.data_ready);
+	if (gyro_state->common_attributes.data_ready)
+		hid_sensor_push_data(indio_dev,
+				(u8 *)gyro_state->gyro_val,
+				sizeof(gyro_state->gyro_val));
+
+	return 0;
+}
+
+/* Capture samples in local storage */
+static int gyro_3d_capture_sample(struct hid_sensor_hub_device *hsdev,
+				unsigned usage_id,
+				size_t raw_len, char *raw_data,
+				void *priv)
+{
+	struct iio_dev *indio_dev = platform_get_drvdata(priv);
+	struct gyro_3d_state *gyro_state = iio_priv(indio_dev);
+	int offset;
+	int ret = -EINVAL;
+
+	switch (usage_id) {
+	case HID_USAGE_SENSOR_ANGL_VELOCITY_X_AXIS:
+	case HID_USAGE_SENSOR_ANGL_VELOCITY_Y_AXIS:
+	case HID_USAGE_SENSOR_ANGL_VELOCITY_Z_AXIS:
+		offset = usage_id - HID_USAGE_SENSOR_ANGL_VELOCITY_X_AXIS;
+		gyro_state->gyro_val[CHANNEL_SCAN_INDEX_X + offset] =
+						*(u32 *)raw_data;
+		ret = 0;
+	break;
+	default:
+		break;
+	}
+
+	return ret;
+}
+
+/* Parse report which is specific to an usage id*/
+static int gyro_3d_parse_report(struct platform_device *pdev,
+				struct hid_sensor_hub_device *hsdev,
+				struct iio_chan_spec *channels,
+				unsigned usage_id,
+				struct gyro_3d_state *st)
+{
+	int ret;
+	int i;
+
+	for (i = 0; i <= CHANNEL_SCAN_INDEX_Z; ++i) {
+		ret = sensor_hub_input_get_attribute_info(hsdev,
+				HID_INPUT_REPORT,
+				usage_id,
+				HID_USAGE_SENSOR_ANGL_VELOCITY_X_AXIS + i,
+				&st->gyro[CHANNEL_SCAN_INDEX_X + i]);
+		if (ret < 0)
+			break;
+		gyro_3d_adjust_channel_bit_mask(channels,
+				CHANNEL_SCAN_INDEX_X + i,
+				st->gyro[CHANNEL_SCAN_INDEX_X + i].size);
+	}
+	dev_dbg(&pdev->dev, "gyro_3d %x:%x, %x:%x, %x:%x\n",
+			st->gyro[0].index,
+			st->gyro[0].report_id,
+			st->gyro[1].index, st->gyro[1].report_id,
+			st->gyro[2].index, st->gyro[2].report_id);
+
+	return ret;
+}
+
+/* Function to initialize the processing for usage id */
+static int __devinit hid_gyro_3d_probe(struct platform_device *pdev)
+{
+	int ret = 0;
+	static const char *name = "gyro_3d";
+	struct iio_dev *indio_dev;
+	struct gyro_3d_state *gyro_state;
+	struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
+	struct iio_chan_spec *channels;
+
+	indio_dev = iio_device_alloc(sizeof(struct gyro_3d_state));
+	if (indio_dev == NULL) {
+		ret = -ENOMEM;
+		goto error_ret;
+	}
+	platform_set_drvdata(pdev, indio_dev);
+
+	gyro_state = iio_priv(indio_dev);
+	gyro_state->common_attributes.hsdev = hsdev;
+	gyro_state->common_attributes.pdev = pdev;
+
+	ret = hid_sensor_parse_common_attributes(hsdev,
+						HID_USAGE_SENSOR_GYRO_3D,
+						&gyro_state->common_attributes);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to setup common attributes\n");
+		goto error_free_dev;
+	}
+
+	channels = kmemdup(gyro_3d_channels,
+					sizeof(gyro_3d_channels),
+					GFP_KERNEL);
+	if (!channels) {
+		dev_err(&pdev->dev, "failed to duplicate channels\n");
+		goto error_free_dev;
+	}
+
+	ret = gyro_3d_parse_report(pdev, hsdev, channels,
+					HID_USAGE_SENSOR_GYRO_3D, gyro_state);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to setup attributes\n");
+		goto error_free_dev_mem;
+	}
+
+	indio_dev->channels = channels;
+	indio_dev->num_channels = ARRAY_SIZE(gyro_3d_channels);
+	indio_dev->dev.parent = &pdev->dev;
+	indio_dev->info = &gyro_3d_info;
+	indio_dev->name = name;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+
+	ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
+		NULL, NULL);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to initialize trigger buffer\n");
+		goto error_free_dev_mem;
+	}
+	gyro_state->common_attributes.data_ready = false;
+	ret = hid_sensor_setup_trigger(indio_dev, name,
+					&gyro_state->common_attributes);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "trigger setup failed\n");
+		goto error_unreg_buffer_funcs;
+	}
+
+	ret = iio_device_register(indio_dev);
+	if (ret) {
+		dev_err(&pdev->dev, "device register failed\n");
+		goto error_remove_trigger;
+	}
+
+	gyro_state->callbacks.send_event = gyro_3d_proc_event;
+	gyro_state->callbacks.capture_sample = gyro_3d_capture_sample;
+	gyro_state->callbacks.pdev = pdev;
+	ret = sensor_hub_register_callback(hsdev, HID_USAGE_SENSOR_GYRO_3D,
+					&gyro_state->callbacks);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "callback reg failed\n");
+		goto error_iio_unreg;
+	}
+
+	return ret;
+
+error_iio_unreg:
+	iio_device_unregister(indio_dev);
+error_remove_trigger:
+	hid_sensor_remove_trigger(indio_dev);
+error_unreg_buffer_funcs:
+	iio_triggered_buffer_cleanup(indio_dev);
+error_free_dev_mem:
+	kfree(indio_dev->channels);
+error_free_dev:
+	iio_device_free(indio_dev);
+error_ret:
+	return ret;
+}
+
+/* Function to deinitialize the processing for usage id */
+static int __devinit hid_gyro_3d_remove(struct platform_device *pdev)
+{
+	struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
+	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
+
+	sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_GYRO_3D);
+	iio_device_unregister(indio_dev);
+	hid_sensor_remove_trigger(indio_dev);
+	iio_triggered_buffer_cleanup(indio_dev);
+	kfree(indio_dev->channels);
+	iio_device_free(indio_dev);
+
+	return 0;
+}
+
+static struct platform_driver hid_gyro_3d_platform_driver = {
+	.driver = {
+		.name	= DRIVER_NAME,
+		.owner	= THIS_MODULE,
+	},
+	.probe		= hid_gyro_3d_probe,
+	.remove		= hid_gyro_3d_remove,
+};
+module_platform_driver(hid_gyro_3d_platform_driver);
+
+MODULE_DESCRIPTION("HID Sensor Gyroscope 3D");
+MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@intel.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c
index 4add9bb..d4ad374 100644
--- a/drivers/iio/industrialio-buffer.c
+++ b/drivers/iio/industrialio-buffer.c
@@ -422,7 +422,7 @@ ssize_t iio_buffer_store_enable(struct device *dev,
 			ret = indio_dev->setup_ops->preenable(indio_dev);
 			if (ret) {
 				printk(KERN_ERR
-				       "Buffer not started:"
+				       "Buffer not started: "
 				       "buffer preenable failed\n");
 				goto error_ret;
 			}
@@ -431,12 +431,12 @@ ssize_t iio_buffer_store_enable(struct device *dev,
 			ret = buffer->access->request_update(buffer);
 			if (ret) {
 				printk(KERN_INFO
-				       "Buffer not started:"
+				       "Buffer not started: "
 				       "buffer parameter update failed\n");
 				goto error_ret;
 			}
 		}
-		/* Definitely possible for devices to support both of these.*/
+		/* Definitely possible for devices to support both of these. */
 		if (indio_dev->modes & INDIO_BUFFER_TRIGGERED) {
 			if (!indio_dev->trig) {
 				printk(KERN_INFO
@@ -456,7 +456,7 @@ ssize_t iio_buffer_store_enable(struct device *dev,
 			ret = indio_dev->setup_ops->postenable(indio_dev);
 			if (ret) {
 				printk(KERN_INFO
-				       "Buffer not started:"
+				       "Buffer not started: "
 				       "postenable failed\n");
 				indio_dev->currentmode = previous_mode;
 				if (indio_dev->setup_ops->postdisable)
@@ -657,7 +657,7 @@ EXPORT_SYMBOL_GPL(iio_scan_mask_query);
 /**
  * struct iio_demux_table() - table describing demux memcpy ops
  * @from:	index to copy from
- * @to:	index to copy to
+ * @to:		index to copy to
  * @length:	how many bytes to copy
  * @l:		list head used for management
  */
@@ -682,12 +682,11 @@ static unsigned char *iio_demux(struct iio_buffer *buffer,
 	return buffer->demux_bounce;
 }
 
-int iio_push_to_buffer(struct iio_buffer *buffer, unsigned char *data,
-		       s64 timestamp)
+int iio_push_to_buffer(struct iio_buffer *buffer, unsigned char *data)
 {
 	unsigned char *dataout = iio_demux(buffer, data);
 
-	return buffer->access->store_to(buffer, dataout, timestamp);
+	return buffer->access->store_to(buffer, dataout);
 }
 EXPORT_SYMBOL_GPL(iio_push_to_buffer);
 
diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
index 2ec266e..6eb24db 100644
--- a/drivers/iio/industrialio-core.c
+++ b/drivers/iio/industrialio-core.c
@@ -29,7 +29,7 @@
 #include <linux/iio/sysfs.h>
 #include <linux/iio/events.h>
 
-/* IDA to assign each registered device a unique id*/
+/* IDA to assign each registered device a unique id */
 static DEFINE_IDA(iio_ida);
 
 static dev_t iio_devt;
@@ -99,6 +99,7 @@ static const char * const iio_chan_info_postfix[] = {
 	[IIO_CHAN_INFO_FREQUENCY] = "frequency",
 	[IIO_CHAN_INFO_PHASE] = "phase",
 	[IIO_CHAN_INFO_HARDWAREGAIN] = "hardwaregain",
+	[IIO_CHAN_INFO_HYSTERESIS] = "hysteresis",
 };
 
 const struct iio_chan_spec
@@ -365,6 +366,7 @@ static ssize_t iio_read_channel_info(struct device *dev,
 {
 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
+	unsigned long long tmp;
 	int val, val2;
 	bool scale_db = false;
 	int ret = indio_dev->info->read_raw(indio_dev, this_attr->c,
@@ -390,6 +392,11 @@ static ssize_t iio_read_channel_info(struct device *dev,
 			return sprintf(buf, "-%d.%09u\n", val, -val2);
 		else
 			return sprintf(buf, "%d.%09u\n", val, val2);
+	case IIO_VAL_FRACTIONAL:
+		tmp = div_s64((s64)val * 1000000000LL, val2);
+		val2 = do_div(tmp, 1000000000LL);
+		val = tmp;
+		return sprintf(buf, "%d.%09u\n", val, val2);
 	default:
 		return 0;
 	}
@@ -729,7 +736,7 @@ static int iio_device_register_sysfs(struct iio_dev *indio_dev)
 	attrcount = attrcount_orig;
 	/*
 	 * New channel registration method - relies on the fact a group does
-	 * not need to be initialized if it is name is NULL.
+	 * not need to be initialized if its name is NULL.
 	 */
 	if (indio_dev->channels)
 		for (i = 0; i < indio_dev->num_channels; i++) {
@@ -980,6 +987,6 @@ EXPORT_SYMBOL(iio_device_unregister);
 subsys_initcall(iio_init);
 module_exit(iio_exit);
 
-MODULE_AUTHOR("Jonathan Cameron <jic23@cam.ac.uk>");
+MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>");
 MODULE_DESCRIPTION("Industrial I/O core");
 MODULE_LICENSE("GPL");
diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c
index b5afc2f..25b0076 100644
--- a/drivers/iio/inkern.c
+++ b/drivers/iio/inkern.c
@@ -130,18 +130,27 @@ struct iio_channel *iio_channel_get(const char *name, const char *channel_name)
 	if (c == NULL)
 		return ERR_PTR(-ENODEV);
 
-	channel = kmalloc(sizeof(*channel), GFP_KERNEL);
+	channel = kzalloc(sizeof(*channel), GFP_KERNEL);
 	if (channel == NULL)
 		return ERR_PTR(-ENOMEM);
 
 	channel->indio_dev = c->indio_dev;
 
-	if (c->map->adc_channel_label)
+	if (c->map->adc_channel_label) {
 		channel->channel =
 			iio_chan_spec_from_name(channel->indio_dev,
 						c->map->adc_channel_label);
 
+		if (channel->channel == NULL)
+			goto error_no_chan;
+	}
+
 	return channel;
+
+error_no_chan:
+	iio_device_put(c->indio_dev);
+	kfree(channel);
+	return ERR_PTR(-EINVAL);
 }
 EXPORT_SYMBOL_GPL(iio_channel_get);
 
@@ -229,9 +238,21 @@ void iio_channel_release_all(struct iio_channel *channels)
 }
 EXPORT_SYMBOL_GPL(iio_channel_release_all);
 
+static int iio_channel_read(struct iio_channel *chan, int *val, int *val2,
+	enum iio_chan_info_enum info)
+{
+	int unused;
+
+	if (val2 == NULL)
+		val2 = &unused;
+
+	return chan->indio_dev->info->read_raw(chan->indio_dev, chan->channel,
+						val, val2, info);
+}
+
 int iio_read_channel_raw(struct iio_channel *chan, int *val)
 {
-	int val2, ret;
+	int ret;
 
 	mutex_lock(&chan->indio_dev->info_exist_lock);
 	if (chan->indio_dev->info == NULL) {
@@ -239,8 +260,7 @@ int iio_read_channel_raw(struct iio_channel *chan, int *val)
 		goto err_unlock;
 	}
 
-	ret = chan->indio_dev->info->read_raw(chan->indio_dev, chan->channel,
-					      val, &val2, 0);
+	ret = iio_channel_read(chan, val, NULL, IIO_CHAN_INFO_RAW);
 err_unlock:
 	mutex_unlock(&chan->indio_dev->info_exist_lock);
 
@@ -248,6 +268,100 @@ err_unlock:
 }
 EXPORT_SYMBOL_GPL(iio_read_channel_raw);
 
+static int iio_convert_raw_to_processed_unlocked(struct iio_channel *chan,
+	int raw, int *processed, unsigned int scale)
+{
+	int scale_type, scale_val, scale_val2, offset;
+	s64 raw64 = raw;
+	int ret;
+
+	ret = iio_channel_read(chan, &offset, NULL, IIO_CHAN_INFO_SCALE);
+	if (ret == 0)
+		raw64 += offset;
+
+	scale_type = iio_channel_read(chan, &scale_val, &scale_val2,
+					IIO_CHAN_INFO_SCALE);
+	if (scale_type < 0)
+		return scale_type;
+
+	switch (scale_type) {
+	case IIO_VAL_INT:
+		*processed = raw64 * scale_val;
+		break;
+	case IIO_VAL_INT_PLUS_MICRO:
+		if (scale_val2 < 0)
+			*processed = -raw64 * scale_val;
+		else
+			*processed = raw64 * scale_val;
+		*processed += div_s64(raw64 * (s64)scale_val2 * scale,
+				      1000000LL);
+		break;
+	case IIO_VAL_INT_PLUS_NANO:
+		if (scale_val2 < 0)
+			*processed = -raw64 * scale_val;
+		else
+			*processed = raw64 * scale_val;
+		*processed += div_s64(raw64 * (s64)scale_val2 * scale,
+				      1000000000LL);
+		break;
+	case IIO_VAL_FRACTIONAL:
+		*processed = div_s64(raw64 * (s64)scale_val * scale,
+				     scale_val2);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+int iio_convert_raw_to_processed(struct iio_channel *chan, int raw,
+	int *processed, unsigned int scale)
+{
+	int ret;
+
+	mutex_lock(&chan->indio_dev->info_exist_lock);
+	if (chan->indio_dev->info == NULL) {
+		ret = -ENODEV;
+		goto err_unlock;
+	}
+
+	ret = iio_convert_raw_to_processed_unlocked(chan, raw, processed,
+							scale);
+err_unlock:
+	mutex_unlock(&chan->indio_dev->info_exist_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(iio_convert_raw_to_processed);
+
+int iio_read_channel_processed(struct iio_channel *chan, int *val)
+{
+	int ret;
+
+	mutex_lock(&chan->indio_dev->info_exist_lock);
+	if (chan->indio_dev->info == NULL) {
+		ret = -ENODEV;
+		goto err_unlock;
+	}
+
+	if (iio_channel_has_info(chan->channel, IIO_CHAN_INFO_PROCESSED)) {
+		ret = iio_channel_read(chan, val, NULL,
+				       IIO_CHAN_INFO_PROCESSED);
+	} else {
+		ret = iio_channel_read(chan, val, NULL, IIO_CHAN_INFO_RAW);
+		if (ret < 0)
+			goto err_unlock;
+		ret = iio_convert_raw_to_processed_unlocked(chan, *val, val, 1);
+	}
+
+err_unlock:
+	mutex_unlock(&chan->indio_dev->info_exist_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(iio_read_channel_processed);
+
 int iio_read_channel_scale(struct iio_channel *chan, int *val, int *val2)
 {
 	int ret;
@@ -258,10 +372,7 @@ int iio_read_channel_scale(struct iio_channel *chan, int *val, int *val2)
 		goto err_unlock;
 	}
 
-	ret = chan->indio_dev->info->read_raw(chan->indio_dev,
-					      chan->channel,
-					      val, val2,
-					      IIO_CHAN_INFO_SCALE);
+	ret = iio_channel_read(chan, val, val2, IIO_CHAN_INFO_SCALE);
 err_unlock:
 	mutex_unlock(&chan->indio_dev->info_exist_lock);
 
diff --git a/drivers/iio/kfifo_buf.c b/drivers/iio/kfifo_buf.c
index 6bf9d05..5bc5c86 100644
--- a/drivers/iio/kfifo_buf.c
+++ b/drivers/iio/kfifo_buf.c
@@ -6,6 +6,7 @@
 #include <linux/kfifo.h>
 #include <linux/mutex.h>
 #include <linux/iio/kfifo_buf.h>
+#include <linux/sched.h>
 
 struct iio_kfifo {
 	struct iio_buffer buffer;
@@ -22,7 +23,8 @@ static inline int __iio_allocate_kfifo(struct iio_kfifo *buf,
 		return -EINVAL;
 
 	__iio_update_buffer(&buf->buffer, bytes_per_datum, length);
-	return kfifo_alloc(&buf->kf, bytes_per_datum*length, GFP_KERNEL);
+	return __kfifo_alloc((struct __kfifo *)&buf->kf, length,
+			     bytes_per_datum, GFP_KERNEL);
 }
 
 static int iio_request_update_kfifo(struct iio_buffer *r)
@@ -35,6 +37,7 @@ static int iio_request_update_kfifo(struct iio_buffer *r)
 	kfifo_free(&buf->kf);
 	ret = __iio_allocate_kfifo(buf, buf->buffer.bytes_per_datum,
 				   buf->buffer.length);
+	r->stufftoread = false;
 error_ret:
 	return ret;
 }
@@ -81,6 +84,9 @@ static int iio_set_bytes_per_datum_kfifo(struct iio_buffer *r, size_t bpd)
 
 static int iio_set_length_kfifo(struct iio_buffer *r, int length)
 {
+	/* Avoid an invalid state */
+	if (length < 2)
+		length = 2;
 	if (r->length != length) {
 		r->length = length;
 		iio_mark_update_needed_kfifo(r);
@@ -89,14 +95,16 @@ static int iio_set_length_kfifo(struct iio_buffer *r, int length)
 }
 
 static int iio_store_to_kfifo(struct iio_buffer *r,
-			      u8 *data,
-			      s64 timestamp)
+			      u8 *data)
 {
 	int ret;
 	struct iio_kfifo *kf = iio_to_kfifo(r);
-	ret = kfifo_in(&kf->kf, data, r->bytes_per_datum);
-	if (ret != r->bytes_per_datum)
+	ret = kfifo_in(&kf->kf, data, 1);
+	if (ret != 1)
 		return -EBUSY;
+	r->stufftoread = true;
+	wake_up_interruptible(&r->pollq);
+
 	return 0;
 }
 
@@ -106,11 +114,18 @@ static int iio_read_first_n_kfifo(struct iio_buffer *r,
 	int ret, copied;
 	struct iio_kfifo *kf = iio_to_kfifo(r);
 
-	if (n < r->bytes_per_datum)
+	if (n < r->bytes_per_datum || r->bytes_per_datum == 0)
 		return -EINVAL;
 
-	n = rounddown(n, r->bytes_per_datum);
 	ret = kfifo_to_user(&kf->kf, buf, n, &copied);
+	if (ret < 0)
+		return ret;
+
+	if (kfifo_is_empty(&kf->kf))
+		r->stufftoread = false;
+	/* verify it is still empty to avoid race */
+	if (!kfifo_is_empty(&kf->kf))
+		r->stufftoread = true;
 
 	return copied;
 }
@@ -136,7 +151,7 @@ struct iio_buffer *iio_kfifo_allocate(struct iio_dev *indio_dev)
 	iio_buffer_init(&kf->buffer);
 	kf->buffer.attrs = &iio_kfifo_attribute_group;
 	kf->buffer.access = &kfifo_access_funcs;
-
+	kf->buffer.length = 2;
 	return &kf->buffer;
 }
 EXPORT_SYMBOL(iio_kfifo_allocate);
diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig
index 91d15d2..1763c9b 100644
--- a/drivers/iio/light/Kconfig
+++ b/drivers/iio/light/Kconfig
@@ -42,4 +42,14 @@ config VCNL4000
 	 To compile this driver as a module, choose M here: the
 	 module will be called vcnl4000.
 
+config HID_SENSOR_ALS
+	depends on HID_SENSOR_HUB
+	select IIO_BUFFER
+	select IIO_TRIGGERED_BUFFER
+	select HID_SENSOR_IIO_COMMON
+	tristate "HID ALS"
+	help
+	  Say yes here to build support for the HID SENSOR
+	  Ambient light sensor.
+
 endmenu
diff --git a/drivers/iio/light/Makefile b/drivers/iio/light/Makefile
index 13f8a78..21a8f0d 100644
--- a/drivers/iio/light/Makefile
+++ b/drivers/iio/light/Makefile
@@ -5,3 +5,4 @@
 obj-$(CONFIG_ADJD_S311)		+= adjd_s311.o
 obj-$(CONFIG_SENSORS_LM3533)	+= lm3533-als.o
 obj-$(CONFIG_VCNL4000)		+= vcnl4000.o
+obj-$(CONFIG_HID_SENSOR_ALS)	+= hid-sensor-als.o
diff --git a/drivers/iio/light/adjd_s311.c b/drivers/iio/light/adjd_s311.c
index 9a99f43..164b62b 100644
--- a/drivers/iio/light/adjd_s311.c
+++ b/drivers/iio/light/adjd_s311.c
@@ -187,7 +187,7 @@ static irqreturn_t adjd_s311_trigger_handler(int irq, void *p)
 	if (indio_dev->scan_timestamp)
 		*(s64 *)((u8 *)data->buffer + ALIGN(len, sizeof(s64)))
 			= time_ns;
-	iio_push_to_buffer(buffer, (u8 *)data->buffer, time_ns);
+	iio_push_to_buffer(buffer, (u8 *)data->buffer);
 
 done:
 	iio_trigger_notify_done(indio_dev->trig);
diff --git a/drivers/iio/light/hid-sensor-als.c b/drivers/iio/light/hid-sensor-als.c
new file mode 100644
index 0000000..96e3691
--- /dev/null
+++ b/drivers/iio/light/hid-sensor-als.c
@@ -0,0 +1,385 @@
+/*
+ * HID Sensors Driver
+ * Copyright (c) 2012, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/slab.h>
+#include <linux/hid-sensor-hub.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
+#include "../common/hid-sensors/hid-sensor-attributes.h"
+#include "../common/hid-sensors/hid-sensor-trigger.h"
+
+/*Format: HID-SENSOR-usage_id_in_hex*/
+/*Usage ID from spec for Accelerometer-3D: 0x200041*/
+#define DRIVER_NAME "HID-SENSOR-200041"
+
+#define CHANNEL_SCAN_INDEX_ILLUM 0
+
+struct als_state {
+	struct hid_sensor_hub_callbacks callbacks;
+	struct hid_sensor_iio_common common_attributes;
+	struct hid_sensor_hub_attribute_info als_illum;
+	u32 illum;
+};
+
+/* Channel definitions */
+static const struct iio_chan_spec als_channels[] = {
+	{
+		.type = IIO_INTENSITY,
+		.modified = 1,
+		.channel2 = IIO_MOD_LIGHT_BOTH,
+		.info_mask = IIO_CHAN_INFO_OFFSET_SHARED_BIT |
+		IIO_CHAN_INFO_SCALE_SHARED_BIT |
+		IIO_CHAN_INFO_SAMP_FREQ_SHARED_BIT |
+		IIO_CHAN_INFO_HYSTERESIS_SHARED_BIT,
+		.scan_index = CHANNEL_SCAN_INDEX_ILLUM,
+	}
+};
+
+/* Adjust channel real bits based on report descriptor */
+static void als_adjust_channel_bit_mask(struct iio_chan_spec *channels,
+					int channel, int size)
+{
+	channels[channel].scan_type.sign = 's';
+	/* Real storage bits will change based on the report desc. */
+	channels[channel].scan_type.realbits = size * 8;
+	/* Maximum size of a sample to capture is u32 */
+	channels[channel].scan_type.storagebits = sizeof(u32) * 8;
+}
+
+/* Channel read_raw handler */
+static int als_read_raw(struct iio_dev *indio_dev,
+			      struct iio_chan_spec const *chan,
+			      int *val, int *val2,
+			      long mask)
+{
+	struct als_state *als_state = iio_priv(indio_dev);
+	int report_id = -1;
+	u32 address;
+	int ret;
+	int ret_type;
+
+	*val = 0;
+	*val2 = 0;
+	switch (mask) {
+	case 0:
+		switch (chan->scan_index) {
+		case  CHANNEL_SCAN_INDEX_ILLUM:
+			report_id = als_state->als_illum.report_id;
+			address =
+			HID_USAGE_SENSOR_LIGHT_ILLUM;
+			break;
+		default:
+			report_id = -1;
+			break;
+		}
+		if (report_id >= 0)
+			*val = sensor_hub_input_attr_get_raw_value(
+				als_state->common_attributes.hsdev,
+				HID_USAGE_SENSOR_ALS, address,
+				report_id);
+		else {
+			*val = 0;
+			return -EINVAL;
+		}
+		ret_type = IIO_VAL_INT;
+		break;
+	case IIO_CHAN_INFO_SCALE:
+		*val = als_state->als_illum.units;
+		ret_type = IIO_VAL_INT;
+		break;
+	case IIO_CHAN_INFO_OFFSET:
+		*val = hid_sensor_convert_exponent(
+				als_state->als_illum.unit_expo);
+		ret_type = IIO_VAL_INT;
+		break;
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		ret = hid_sensor_read_samp_freq_value(
+				&als_state->common_attributes, val, val2);
+		ret_type = IIO_VAL_INT_PLUS_MICRO;
+		break;
+	case IIO_CHAN_INFO_HYSTERESIS:
+		ret = hid_sensor_read_raw_hyst_value(
+				&als_state->common_attributes, val, val2);
+		ret_type = IIO_VAL_INT_PLUS_MICRO;
+		break;
+	default:
+		ret_type = -EINVAL;
+		break;
+	}
+
+	return ret_type;
+}
+
+/* Channel write_raw handler */
+static int als_write_raw(struct iio_dev *indio_dev,
+			       struct iio_chan_spec const *chan,
+			       int val,
+			       int val2,
+			       long mask)
+{
+	struct als_state *als_state = iio_priv(indio_dev);
+	int ret = 0;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		ret = hid_sensor_write_samp_freq_value(
+				&als_state->common_attributes, val, val2);
+		break;
+	case IIO_CHAN_INFO_HYSTERESIS:
+		ret = hid_sensor_write_raw_hyst_value(
+				&als_state->common_attributes, val, val2);
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static int als_write_raw_get_fmt(struct iio_dev *indio_dev,
+			       struct iio_chan_spec const *chan,
+			       long mask)
+{
+	return IIO_VAL_INT_PLUS_MICRO;
+}
+
+static const struct iio_info als_info = {
+	.driver_module = THIS_MODULE,
+	.read_raw = &als_read_raw,
+	.write_raw = &als_write_raw,
+	.write_raw_get_fmt = &als_write_raw_get_fmt,
+};
+
+/* Function to push data to buffer */
+static void hid_sensor_push_data(struct iio_dev *indio_dev, u8 *data, int len)
+{
+	struct iio_buffer *buffer = indio_dev->buffer;
+	int datum_sz;
+
+	dev_dbg(&indio_dev->dev, "hid_sensor_push_data\n");
+	if (!buffer) {
+		dev_err(&indio_dev->dev, "Buffer == NULL\n");
+		return;
+	}
+	datum_sz = buffer->access->get_bytes_per_datum(buffer);
+	if (len > datum_sz) {
+		dev_err(&indio_dev->dev, "Datum size mismatch %d:%d\n", len,
+				datum_sz);
+		return;
+	}
+	iio_push_to_buffer(buffer, (u8 *)data);
+}
+
+/* Callback handler to send event after all samples are received and captured */
+static int als_proc_event(struct hid_sensor_hub_device *hsdev,
+				unsigned usage_id,
+				void *priv)
+{
+	struct iio_dev *indio_dev = platform_get_drvdata(priv);
+	struct als_state *als_state = iio_priv(indio_dev);
+
+	dev_dbg(&indio_dev->dev, "als_proc_event [%d]\n",
+				als_state->common_attributes.data_ready);
+	if (als_state->common_attributes.data_ready)
+		hid_sensor_push_data(indio_dev,
+				(u8 *)&als_state->illum,
+				sizeof(als_state->illum));
+
+	return 0;
+}
+
+/* Capture samples in local storage */
+static int als_capture_sample(struct hid_sensor_hub_device *hsdev,
+				unsigned usage_id,
+				size_t raw_len, char *raw_data,
+				void *priv)
+{
+	struct iio_dev *indio_dev = platform_get_drvdata(priv);
+	struct als_state *als_state = iio_priv(indio_dev);
+	int ret = -EINVAL;
+
+	switch (usage_id) {
+	case HID_USAGE_SENSOR_LIGHT_ILLUM:
+		als_state->illum = *(u32 *)raw_data;
+		ret = 0;
+		break;
+	default:
+		break;
+	}
+
+	return ret;
+}
+
+/* Parse report which is specific to an usage id*/
+static int als_parse_report(struct platform_device *pdev,
+				struct hid_sensor_hub_device *hsdev,
+				struct iio_chan_spec *channels,
+				unsigned usage_id,
+				struct als_state *st)
+{
+	int ret;
+
+	ret = sensor_hub_input_get_attribute_info(hsdev, HID_INPUT_REPORT,
+			usage_id,
+			HID_USAGE_SENSOR_LIGHT_ILLUM,
+			&st->als_illum);
+	if (ret < 0)
+		return ret;
+	als_adjust_channel_bit_mask(channels, CHANNEL_SCAN_INDEX_ILLUM,
+					st->als_illum.size);
+
+	dev_dbg(&pdev->dev, "als %x:%x\n", st->als_illum.index,
+			st->als_illum.report_id);
+
+	return ret;
+}
+
+/* Function to initialize the processing for usage id */
+static int __devinit hid_als_probe(struct platform_device *pdev)
+{
+	int ret = 0;
+	static const char *name = "als";
+	struct iio_dev *indio_dev;
+	struct als_state *als_state;
+	struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
+	struct iio_chan_spec *channels;
+
+	indio_dev = iio_device_alloc(sizeof(struct als_state));
+	if (indio_dev == NULL) {
+		ret = -ENOMEM;
+		goto error_ret;
+	}
+	platform_set_drvdata(pdev, indio_dev);
+
+	als_state = iio_priv(indio_dev);
+	als_state->common_attributes.hsdev = hsdev;
+	als_state->common_attributes.pdev = pdev;
+
+	ret = hid_sensor_parse_common_attributes(hsdev, HID_USAGE_SENSOR_ALS,
+					&als_state->common_attributes);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to setup common attributes\n");
+		goto error_free_dev;
+	}
+
+	channels = kmemdup(als_channels,
+					sizeof(als_channels),
+					GFP_KERNEL);
+	if (!channels) {
+		dev_err(&pdev->dev, "failed to duplicate channels\n");
+		goto error_free_dev;
+	}
+
+	ret = als_parse_report(pdev, hsdev, channels,
+				HID_USAGE_SENSOR_ALS, als_state);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to setup attributes\n");
+		goto error_free_dev_mem;
+	}
+
+	indio_dev->channels = channels;
+	indio_dev->num_channels =
+				ARRAY_SIZE(als_channels);
+	indio_dev->dev.parent = &pdev->dev;
+	indio_dev->info = &als_info;
+	indio_dev->name = name;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+
+	ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
+		NULL, NULL);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to initialize trigger buffer\n");
+		goto error_free_dev_mem;
+	}
+	als_state->common_attributes.data_ready = false;
+	ret = hid_sensor_setup_trigger(indio_dev, name,
+				&als_state->common_attributes);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "trigger setup failed\n");
+		goto error_unreg_buffer_funcs;
+	}
+
+	ret = iio_device_register(indio_dev);
+	if (ret) {
+		dev_err(&pdev->dev, "device register failed\n");
+		goto error_remove_trigger;
+	}
+
+	als_state->callbacks.send_event = als_proc_event;
+	als_state->callbacks.capture_sample = als_capture_sample;
+	als_state->callbacks.pdev = pdev;
+	ret = sensor_hub_register_callback(hsdev, HID_USAGE_SENSOR_ALS,
+					&als_state->callbacks);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "callback reg failed\n");
+		goto error_iio_unreg;
+	}
+
+	return ret;
+
+error_iio_unreg:
+	iio_device_unregister(indio_dev);
+error_remove_trigger:
+	hid_sensor_remove_trigger(indio_dev);
+error_unreg_buffer_funcs:
+	iio_triggered_buffer_cleanup(indio_dev);
+error_free_dev_mem:
+	kfree(indio_dev->channels);
+error_free_dev:
+	iio_device_free(indio_dev);
+error_ret:
+	return ret;
+}
+
+/* Function to deinitialize the processing for usage id */
+static int __devinit hid_als_remove(struct platform_device *pdev)
+{
+	struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
+	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
+
+	sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_ALS);
+	iio_device_unregister(indio_dev);
+	hid_sensor_remove_trigger(indio_dev);
+	iio_triggered_buffer_cleanup(indio_dev);
+	kfree(indio_dev->channels);
+	iio_device_free(indio_dev);
+
+	return 0;
+}
+
+static struct platform_driver hid_als_platform_driver = {
+	.driver = {
+		.name	= DRIVER_NAME,
+		.owner	= THIS_MODULE,
+	},
+	.probe		= hid_als_probe,
+	.remove		= hid_als_remove,
+};
+module_platform_driver(hid_als_platform_driver);
+
+MODULE_DESCRIPTION("HID Sensor ALS");
+MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@intel.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/magnetometer/Kconfig b/drivers/iio/magnetometer/Kconfig
new file mode 100644
index 0000000..c1f0cdd
--- /dev/null
+++ b/drivers/iio/magnetometer/Kconfig
@@ -0,0 +1,16 @@
+#
+# Magnetometer sensors
+#
+menu "Magnetometer sensors"
+
+config HID_SENSOR_MAGNETOMETER_3D
+	depends on HID_SENSOR_HUB
+	select IIO_BUFFER
+	select IIO_TRIGGERED_BUFFER
+	select HID_SENSOR_IIO_COMMON
+	tristate "HID Magenetometer 3D"
+	help
+	  Say yes here to build support for the HID SENSOR
+	  Magnetometer 3D.
+
+endmenu
diff --git a/drivers/iio/magnetometer/Makefile b/drivers/iio/magnetometer/Makefile
new file mode 100644
index 0000000..60dc4f2
--- /dev/null
+++ b/drivers/iio/magnetometer/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for industrial I/O Magnetometer sensor drivers
+#
+
+obj-$(CONFIG_HID_SENSOR_MAGNETOMETER_3D) += hid-sensor-magn-3d.o
diff --git a/drivers/iio/magnetometer/hid-sensor-magn-3d.c b/drivers/iio/magnetometer/hid-sensor-magn-3d.c
new file mode 100644
index 0000000..c4f0d27
--- /dev/null
+++ b/drivers/iio/magnetometer/hid-sensor-magn-3d.c
@@ -0,0 +1,419 @@
+/*
+ * HID Sensors Driver
+ * Copyright (c) 2012, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/slab.h>
+#include <linux/hid-sensor-hub.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
+#include "../common/hid-sensors/hid-sensor-attributes.h"
+#include "../common/hid-sensors/hid-sensor-trigger.h"
+
+/*Format: HID-SENSOR-usage_id_in_hex*/
+/*Usage ID from spec for Magnetometer-3D: 0x200083*/
+#define DRIVER_NAME "HID-SENSOR-200083"
+
+enum magn_3d_channel {
+	CHANNEL_SCAN_INDEX_X,
+	CHANNEL_SCAN_INDEX_Y,
+	CHANNEL_SCAN_INDEX_Z,
+	MAGN_3D_CHANNEL_MAX,
+};
+
+struct magn_3d_state {
+	struct hid_sensor_hub_callbacks callbacks;
+	struct hid_sensor_iio_common common_attributes;
+	struct hid_sensor_hub_attribute_info magn[MAGN_3D_CHANNEL_MAX];
+	u32 magn_val[MAGN_3D_CHANNEL_MAX];
+};
+
+static const u32 magn_3d_addresses[MAGN_3D_CHANNEL_MAX] = {
+	HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_X_AXIS,
+	HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_Y_AXIS,
+	HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_Z_AXIS
+};
+
+/* Channel definitions */
+static const struct iio_chan_spec magn_3d_channels[] = {
+	{
+		.type = IIO_MAGN,
+		.modified = 1,
+		.channel2 = IIO_MOD_X,
+		.info_mask = IIO_CHAN_INFO_OFFSET_SHARED_BIT |
+		IIO_CHAN_INFO_SCALE_SHARED_BIT |
+		IIO_CHAN_INFO_SAMP_FREQ_SHARED_BIT |
+		IIO_CHAN_INFO_HYSTERESIS_SHARED_BIT,
+		.scan_index = CHANNEL_SCAN_INDEX_X,
+	}, {
+		.type = IIO_MAGN,
+		.modified = 1,
+		.channel2 = IIO_MOD_Y,
+		.info_mask = IIO_CHAN_INFO_OFFSET_SHARED_BIT |
+		IIO_CHAN_INFO_SCALE_SHARED_BIT |
+		IIO_CHAN_INFO_SAMP_FREQ_SHARED_BIT |
+		IIO_CHAN_INFO_HYSTERESIS_SHARED_BIT,
+		.scan_index = CHANNEL_SCAN_INDEX_Y,
+	}, {
+		.type = IIO_MAGN,
+		.modified = 1,
+		.channel2 = IIO_MOD_Z,
+		.info_mask = IIO_CHAN_INFO_OFFSET_SHARED_BIT |
+		IIO_CHAN_INFO_SCALE_SHARED_BIT |
+		IIO_CHAN_INFO_SAMP_FREQ_SHARED_BIT |
+		IIO_CHAN_INFO_HYSTERESIS_SHARED_BIT,
+		.scan_index = CHANNEL_SCAN_INDEX_Z,
+	}
+};
+
+/* Adjust channel real bits based on report descriptor */
+static void magn_3d_adjust_channel_bit_mask(struct iio_chan_spec *channels,
+						int channel, int size)
+{
+	channels[channel].scan_type.sign = 's';
+	/* Real storage bits will change based on the report desc. */
+	channels[channel].scan_type.realbits = size * 8;
+	/* Maximum size of a sample to capture is u32 */
+	channels[channel].scan_type.storagebits = sizeof(u32) * 8;
+}
+
+/* Channel read_raw handler */
+static int magn_3d_read_raw(struct iio_dev *indio_dev,
+			      struct iio_chan_spec const *chan,
+			      int *val, int *val2,
+			      long mask)
+{
+	struct magn_3d_state *magn_state = iio_priv(indio_dev);
+	int report_id = -1;
+	u32 address;
+	int ret;
+	int ret_type;
+
+	*val = 0;
+	*val2 = 0;
+	switch (mask) {
+	case 0:
+		report_id =
+			magn_state->magn[chan->scan_index].report_id;
+		address = magn_3d_addresses[chan->scan_index];
+		if (report_id >= 0)
+			*val = sensor_hub_input_attr_get_raw_value(
+				magn_state->common_attributes.hsdev,
+				HID_USAGE_SENSOR_COMPASS_3D, address,
+				report_id);
+		else {
+			*val = 0;
+			return -EINVAL;
+		}
+		ret_type = IIO_VAL_INT;
+		break;
+	case IIO_CHAN_INFO_SCALE:
+		*val = magn_state->magn[CHANNEL_SCAN_INDEX_X].units;
+		ret_type = IIO_VAL_INT;
+		break;
+	case IIO_CHAN_INFO_OFFSET:
+		*val = hid_sensor_convert_exponent(
+			magn_state->magn[CHANNEL_SCAN_INDEX_X].unit_expo);
+		ret_type = IIO_VAL_INT;
+		break;
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		ret = hid_sensor_read_samp_freq_value(
+			&magn_state->common_attributes, val, val2);
+		ret_type = IIO_VAL_INT_PLUS_MICRO;
+		break;
+	case IIO_CHAN_INFO_HYSTERESIS:
+		ret = hid_sensor_read_raw_hyst_value(
+			&magn_state->common_attributes, val, val2);
+		ret_type = IIO_VAL_INT_PLUS_MICRO;
+		break;
+	default:
+		ret_type = -EINVAL;
+		break;
+	}
+
+	return ret_type;
+}
+
+/* Channel write_raw handler */
+static int magn_3d_write_raw(struct iio_dev *indio_dev,
+			       struct iio_chan_spec const *chan,
+			       int val,
+			       int val2,
+			       long mask)
+{
+	struct magn_3d_state *magn_state = iio_priv(indio_dev);
+	int ret = 0;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		ret = hid_sensor_write_samp_freq_value(
+				&magn_state->common_attributes, val, val2);
+		break;
+	case IIO_CHAN_INFO_HYSTERESIS:
+		ret = hid_sensor_write_raw_hyst_value(
+				&magn_state->common_attributes, val, val2);
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static int magn_3d_write_raw_get_fmt(struct iio_dev *indio_dev,
+			       struct iio_chan_spec const *chan,
+			       long mask)
+{
+	return IIO_VAL_INT_PLUS_MICRO;
+}
+
+static const struct iio_info magn_3d_info = {
+	.driver_module = THIS_MODULE,
+	.read_raw = &magn_3d_read_raw,
+	.write_raw = &magn_3d_write_raw,
+	.write_raw_get_fmt = &magn_3d_write_raw_get_fmt,
+};
+
+/* Function to push data to buffer */
+static void hid_sensor_push_data(struct iio_dev *indio_dev, u8 *data, int len)
+{
+	struct iio_buffer *buffer = indio_dev->buffer;
+	int datum_sz;
+
+	dev_dbg(&indio_dev->dev, "hid_sensor_push_data\n");
+	if (!buffer) {
+		dev_err(&indio_dev->dev, "Buffer == NULL\n");
+		return;
+	}
+	datum_sz = buffer->access->get_bytes_per_datum(buffer);
+	if (len > datum_sz) {
+		dev_err(&indio_dev->dev, "Datum size mismatch %d:%d\n", len,
+				datum_sz);
+		return;
+	}
+	iio_push_to_buffer(buffer, (u8 *)data);
+}
+
+/* Callback handler to send event after all samples are received and captured */
+static int magn_3d_proc_event(struct hid_sensor_hub_device *hsdev,
+				unsigned usage_id,
+				void *priv)
+{
+	struct iio_dev *indio_dev = platform_get_drvdata(priv);
+	struct magn_3d_state *magn_state = iio_priv(indio_dev);
+
+	dev_dbg(&indio_dev->dev, "magn_3d_proc_event [%d]\n",
+				magn_state->common_attributes.data_ready);
+	if (magn_state->common_attributes.data_ready)
+		hid_sensor_push_data(indio_dev,
+				(u8 *)magn_state->magn_val,
+				sizeof(magn_state->magn_val));
+
+	return 0;
+}
+
+/* Capture samples in local storage */
+static int magn_3d_capture_sample(struct hid_sensor_hub_device *hsdev,
+				unsigned usage_id,
+				size_t raw_len, char *raw_data,
+				void *priv)
+{
+	struct iio_dev *indio_dev = platform_get_drvdata(priv);
+	struct magn_3d_state *magn_state = iio_priv(indio_dev);
+	int offset;
+	int ret = -EINVAL;
+
+	switch (usage_id) {
+	case HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_X_AXIS:
+	case HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_Y_AXIS:
+	case HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_Z_AXIS:
+		offset = usage_id - HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_X_AXIS;
+		magn_state->magn_val[CHANNEL_SCAN_INDEX_X + offset] =
+						*(u32 *)raw_data;
+		ret = 0;
+	break;
+	default:
+		break;
+	}
+
+	return ret;
+}
+
+/* Parse report which is specific to an usage id*/
+static int magn_3d_parse_report(struct platform_device *pdev,
+				struct hid_sensor_hub_device *hsdev,
+				struct iio_chan_spec *channels,
+				unsigned usage_id,
+				struct magn_3d_state *st)
+{
+	int ret;
+	int i;
+
+	for (i = 0; i <= CHANNEL_SCAN_INDEX_Z; ++i) {
+		ret = sensor_hub_input_get_attribute_info(hsdev,
+				HID_INPUT_REPORT,
+				usage_id,
+				HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_X_AXIS + i,
+				&st->magn[CHANNEL_SCAN_INDEX_X + i]);
+		if (ret < 0)
+			break;
+		magn_3d_adjust_channel_bit_mask(channels,
+				CHANNEL_SCAN_INDEX_X + i,
+				st->magn[CHANNEL_SCAN_INDEX_X + i].size);
+	}
+	dev_dbg(&pdev->dev, "magn_3d %x:%x, %x:%x, %x:%x\n",
+			st->magn[0].index,
+			st->magn[0].report_id,
+			st->magn[1].index, st->magn[1].report_id,
+			st->magn[2].index, st->magn[2].report_id);
+
+	return ret;
+}
+
+/* Function to initialize the processing for usage id */
+static int __devinit hid_magn_3d_probe(struct platform_device *pdev)
+{
+	int ret = 0;
+	static char *name = "magn_3d";
+	struct iio_dev *indio_dev;
+	struct magn_3d_state *magn_state;
+	struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
+	struct iio_chan_spec *channels;
+
+	indio_dev = iio_device_alloc(sizeof(struct magn_3d_state));
+	if (indio_dev == NULL) {
+		ret = -ENOMEM;
+		goto error_ret;
+	}
+	platform_set_drvdata(pdev, indio_dev);
+
+	magn_state = iio_priv(indio_dev);
+	magn_state->common_attributes.hsdev = hsdev;
+	magn_state->common_attributes.pdev = pdev;
+
+	ret = hid_sensor_parse_common_attributes(hsdev,
+				HID_USAGE_SENSOR_COMPASS_3D,
+				&magn_state->common_attributes);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to setup common attributes\n");
+		goto error_free_dev;
+	}
+
+	channels = kmemdup(magn_3d_channels,
+					sizeof(magn_3d_channels),
+					GFP_KERNEL);
+	if (!channels) {
+		dev_err(&pdev->dev, "failed to duplicate channels\n");
+		goto error_free_dev;
+	}
+
+	ret = magn_3d_parse_report(pdev, hsdev, channels,
+				HID_USAGE_SENSOR_COMPASS_3D, magn_state);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to setup attributes\n");
+		goto error_free_dev_mem;
+	}
+
+	indio_dev->channels = channels;
+	indio_dev->num_channels = ARRAY_SIZE(magn_3d_channels);
+	indio_dev->dev.parent = &pdev->dev;
+	indio_dev->info = &magn_3d_info;
+	indio_dev->name = name;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+
+	ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
+		NULL, NULL);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to initialize trigger buffer\n");
+		goto error_free_dev_mem;
+	}
+	magn_state->common_attributes.data_ready = false;
+	ret = hid_sensor_setup_trigger(indio_dev, name,
+					&magn_state->common_attributes);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "trigger setup failed\n");
+		goto error_unreg_buffer_funcs;
+	}
+
+	ret = iio_device_register(indio_dev);
+	if (ret) {
+		dev_err(&pdev->dev, "device register failed\n");
+		goto error_remove_trigger;
+	}
+
+	magn_state->callbacks.send_event = magn_3d_proc_event;
+	magn_state->callbacks.capture_sample = magn_3d_capture_sample;
+	magn_state->callbacks.pdev = pdev;
+	ret = sensor_hub_register_callback(hsdev, HID_USAGE_SENSOR_COMPASS_3D,
+					&magn_state->callbacks);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "callback reg failed\n");
+		goto error_iio_unreg;
+	}
+
+	return ret;
+
+error_iio_unreg:
+	iio_device_unregister(indio_dev);
+error_remove_trigger:
+	hid_sensor_remove_trigger(indio_dev);
+error_unreg_buffer_funcs:
+	iio_triggered_buffer_cleanup(indio_dev);
+error_free_dev_mem:
+	kfree(indio_dev->channels);
+error_free_dev:
+	iio_device_free(indio_dev);
+error_ret:
+	return ret;
+}
+
+/* Function to deinitialize the processing for usage id */
+static int __devinit hid_magn_3d_remove(struct platform_device *pdev)
+{
+	struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
+	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
+
+	sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_COMPASS_3D);
+	iio_device_unregister(indio_dev);
+	hid_sensor_remove_trigger(indio_dev);
+	iio_triggered_buffer_cleanup(indio_dev);
+	kfree(indio_dev->channels);
+	iio_device_free(indio_dev);
+
+	return 0;
+}
+
+static struct platform_driver hid_magn_3d_platform_driver = {
+	.driver = {
+		.name	= DRIVER_NAME,
+		.owner	= THIS_MODULE,
+	},
+	.probe		= hid_magn_3d_probe,
+	.remove		= hid_magn_3d_remove,
+};
+module_platform_driver(hid_magn_3d_platform_driver);
+
+MODULE_DESCRIPTION("HID Sensor Magnetometer 3D");
+MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@intel.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c
index 28058ae..eaec8d7 100644
--- a/drivers/infiniband/core/addr.c
+++ b/drivers/infiniband/core/addr.c
@@ -152,13 +152,11 @@ static void set_timeout(unsigned long time)
 {
 	unsigned long delay;
 
-	cancel_delayed_work(&work);
-
 	delay = time - jiffies;
 	if ((long)delay <= 0)
 		delay = 1;
 
-	queue_delayed_work(addr_wq, &work, delay);
+	mod_delayed_work(addr_wq, &work, delay);
 }
 
 static void queue_req(struct addr_req *req)
diff --git a/drivers/infiniband/core/cache.c b/drivers/infiniband/core/cache.c
index 9353992..80f6cf2 100644
--- a/drivers/infiniband/core/cache.c
+++ b/drivers/infiniband/core/cache.c
@@ -167,6 +167,7 @@ int ib_find_cached_pkey(struct ib_device *device,
 	unsigned long flags;
 	int i;
 	int ret = -ENOENT;
+	int partial_ix = -1;
 
 	if (port_num < start_port(device) || port_num > end_port(device))
 		return -EINVAL;
@@ -179,6 +180,46 @@ int ib_find_cached_pkey(struct ib_device *device,
 
 	for (i = 0; i < cache->table_len; ++i)
 		if ((cache->table[i] & 0x7fff) == (pkey & 0x7fff)) {
+			if (cache->table[i] & 0x8000) {
+				*index = i;
+				ret = 0;
+				break;
+			} else
+				partial_ix = i;
+		}
+
+	if (ret && partial_ix >= 0) {
+		*index = partial_ix;
+		ret = 0;
+	}
+
+	read_unlock_irqrestore(&device->cache.lock, flags);
+
+	return ret;
+}
+EXPORT_SYMBOL(ib_find_cached_pkey);
+
+int ib_find_exact_cached_pkey(struct ib_device *device,
+			      u8                port_num,
+			      u16               pkey,
+			      u16              *index)
+{
+	struct ib_pkey_cache *cache;
+	unsigned long flags;
+	int i;
+	int ret = -ENOENT;
+
+	if (port_num < start_port(device) || port_num > end_port(device))
+		return -EINVAL;
+
+	read_lock_irqsave(&device->cache.lock, flags);
+
+	cache = device->cache.pkey_cache[port_num - start_port(device)];
+
+	*index = -1;
+
+	for (i = 0; i < cache->table_len; ++i)
+		if (cache->table[i] == pkey) {
 			*index = i;
 			ret = 0;
 			break;
@@ -188,7 +229,7 @@ int ib_find_cached_pkey(struct ib_device *device,
 
 	return ret;
 }
-EXPORT_SYMBOL(ib_find_cached_pkey);
+EXPORT_SYMBOL(ib_find_exact_cached_pkey);
 
 int ib_get_cached_lmc(struct ib_device *device,
 		      u8                port_num,
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
index d67999f..394fea2 100644
--- a/drivers/infiniband/core/cm.c
+++ b/drivers/infiniband/core/cm.c
@@ -390,7 +390,7 @@ static int cm_alloc_id(struct cm_id_private *cm_id_priv)
 		ret = idr_get_new_above(&cm.local_id_table, cm_id_priv,
 					next_id, &id);
 		if (!ret)
-			next_id = ((unsigned) id + 1) & MAX_ID_MASK;
+			next_id = ((unsigned) id + 1) & MAX_IDR_MASK;
 		spin_unlock_irqrestore(&cm.lock, flags);
 	} while( (ret == -EAGAIN) && idr_pre_get(&cm.local_id_table, GFP_KERNEL) );
 
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index 7172559..26b3760 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -3058,7 +3058,10 @@ static int cma_join_ib_multicast(struct rdma_id_private *id_priv,
 
 	if (id_priv->id.ps == RDMA_PS_IPOIB)
 		comp_mask |= IB_SA_MCMEMBER_REC_RATE |
-			     IB_SA_MCMEMBER_REC_RATE_SELECTOR;
+			     IB_SA_MCMEMBER_REC_RATE_SELECTOR |
+			     IB_SA_MCMEMBER_REC_MTU_SELECTOR |
+			     IB_SA_MCMEMBER_REC_MTU |
+			     IB_SA_MCMEMBER_REC_HOP_LIMIT;
 
 	mc->multicast.ib = ib_sa_join_multicast(&sa_client, id_priv->id.device,
 						id_priv->id.port_num, &rec,
diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
index e711de4..18c1ece 100644
--- a/drivers/infiniband/core/device.c
+++ b/drivers/infiniband/core/device.c
@@ -707,18 +707,28 @@ int ib_find_pkey(struct ib_device *device,
 {
 	int ret, i;
 	u16 tmp_pkey;
+	int partial_ix = -1;
 
 	for (i = 0; i < device->pkey_tbl_len[port_num - start_port(device)]; ++i) {
 		ret = ib_query_pkey(device, port_num, i, &tmp_pkey);
 		if (ret)
 			return ret;
-
 		if ((pkey & 0x7fff) == (tmp_pkey & 0x7fff)) {
-			*index = i;
-			return 0;
+			/* if there is full-member pkey take it.*/
+			if (tmp_pkey & 0x8000) {
+				*index = i;
+				return 0;
+			}
+			if (partial_ix < 0)
+				partial_ix = i;
 		}
 	}
 
+	/*no full-member, if exists take the limited*/
+	if (partial_ix >= 0) {
+		*index = partial_ix;
+		return 0;
+	}
 	return -ENOENT;
 }
 EXPORT_SYMBOL(ib_find_pkey);
diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c
index b0d0bc8..dc3fd1e 100644
--- a/drivers/infiniband/core/mad.c
+++ b/drivers/infiniband/core/mad.c
@@ -2004,7 +2004,7 @@ static void adjust_timeout(struct ib_mad_agent_private *mad_agent_priv)
 	unsigned long delay;
 
 	if (list_empty(&mad_agent_priv->wait_list)) {
-		__cancel_delayed_work(&mad_agent_priv->timed_work);
+		cancel_delayed_work(&mad_agent_priv->timed_work);
 	} else {
 		mad_send_wr = list_entry(mad_agent_priv->wait_list.next,
 					 struct ib_mad_send_wr_private,
@@ -2013,13 +2013,11 @@ static void adjust_timeout(struct ib_mad_agent_private *mad_agent_priv)
 		if (time_after(mad_agent_priv->timeout,
 			       mad_send_wr->timeout)) {
 			mad_agent_priv->timeout = mad_send_wr->timeout;
-			__cancel_delayed_work(&mad_agent_priv->timed_work);
 			delay = mad_send_wr->timeout - jiffies;
 			if ((long)delay <= 0)
 				delay = 1;
-			queue_delayed_work(mad_agent_priv->qp_info->
-					   port_priv->wq,
-					   &mad_agent_priv->timed_work, delay);
+			mod_delayed_work(mad_agent_priv->qp_info->port_priv->wq,
+					 &mad_agent_priv->timed_work, delay);
 		}
 	}
 }
@@ -2052,11 +2050,9 @@ static void wait_for_response(struct ib_mad_send_wr_private *mad_send_wr)
 	list_add(&mad_send_wr->agent_list, list_item);
 
 	/* Reschedule a work item if we have a shorter timeout */
-	if (mad_agent_priv->wait_list.next == &mad_send_wr->agent_list) {
-		__cancel_delayed_work(&mad_agent_priv->timed_work);
-		queue_delayed_work(mad_agent_priv->qp_info->port_priv->wq,
-				   &mad_agent_priv->timed_work, delay);
-	}
+	if (mad_agent_priv->wait_list.next == &mad_send_wr->agent_list)
+		mod_delayed_work(mad_agent_priv->qp_info->port_priv->wq,
+				 &mad_agent_priv->timed_work, delay);
 }
 
 void ib_reset_mad_timeout(struct ib_mad_send_wr_private *mad_send_wr,
diff --git a/drivers/infiniband/core/netlink.c b/drivers/infiniband/core/netlink.c
index 3ae2bfd..fe10a94 100644
--- a/drivers/infiniband/core/netlink.c
+++ b/drivers/infiniband/core/netlink.c
@@ -177,7 +177,7 @@ int __init ibnl_init(void)
 		.input	= ibnl_rcv,
 	};
 
-	nls = netlink_kernel_create(&init_net, NETLINK_RDMA, THIS_MODULE, &cfg);
+	nls = netlink_kernel_create(&init_net, NETLINK_RDMA, &cfg);
 	if (!nls) {
 		pr_warn("Failed to create netlink socket\n");
 		return -ENOMEM;
diff --git a/drivers/infiniband/core/ucm.c b/drivers/infiniband/core/ucm.c
index 06f0871..49b15ac 100644
--- a/drivers/infiniband/core/ucm.c
+++ b/drivers/infiniband/core/ucm.c
@@ -397,7 +397,6 @@ static ssize_t ib_ucm_event(struct ib_ucm_file *file,
 	struct ib_ucm_event_get cmd;
 	struct ib_ucm_event *uevent;
 	int result = 0;
-	DEFINE_WAIT(wait);
 
 	if (out_len < sizeof(struct ib_ucm_event_resp))
 		return -ENOSPC;
diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c
index 055ed59..2709ff5 100644
--- a/drivers/infiniband/core/ucma.c
+++ b/drivers/infiniband/core/ucma.c
@@ -310,7 +310,6 @@ static ssize_t ucma_get_event(struct ucma_file *file, const char __user *inbuf,
 	struct rdma_ucm_get_event cmd;
 	struct ucma_event *uevent;
 	int ret = 0;
-	DEFINE_WAIT(wait);
 
 	if (out_len < sizeof uevent->resp)
 		return -ENOSPC;
@@ -1184,7 +1183,7 @@ static ssize_t ucma_migrate_id(struct ucma_file *new_file,
 	struct rdma_ucm_migrate_id cmd;
 	struct rdma_ucm_migrate_resp resp;
 	struct ucma_context *ctx;
-	struct file *filp;
+	struct fd f;
 	struct ucma_file *cur_file;
 	int ret = 0;
 
@@ -1192,12 +1191,12 @@ static ssize_t ucma_migrate_id(struct ucma_file *new_file,
 		return -EFAULT;
 
 	/* Get current fd to protect against it being closed */
-	filp = fget(cmd.fd);
-	if (!filp)
+	f = fdget(cmd.fd);
+	if (!f.file)
 		return -ENOENT;
 
 	/* Validate current fd and prevent destruction of id. */
-	ctx = ucma_get_ctx(filp->private_data, cmd.id);
+	ctx = ucma_get_ctx(f.file->private_data, cmd.id);
 	if (IS_ERR(ctx)) {
 		ret = PTR_ERR(ctx);
 		goto file_put;
@@ -1231,7 +1230,7 @@ response:
 
 	ucma_put_ctx(ctx);
 file_put:
-	fput(filp);
+	fdput(f);
 	return ret;
 }
 
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index f9d0d7c..0cb0007 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -705,7 +705,7 @@ ssize_t ib_uverbs_open_xrcd(struct ib_uverbs_file *file,
 	struct ib_udata			udata;
 	struct ib_uxrcd_object         *obj;
 	struct ib_xrcd                 *xrcd = NULL;
-	struct file                    *f = NULL;
+	struct fd			f = {NULL, 0};
 	struct inode                   *inode = NULL;
 	int				ret = 0;
 	int				new_xrcd = 0;
@@ -724,18 +724,13 @@ ssize_t ib_uverbs_open_xrcd(struct ib_uverbs_file *file,
 
 	if (cmd.fd != -1) {
 		/* search for file descriptor */
-		f = fget(cmd.fd);
-		if (!f) {
-			ret = -EBADF;
-			goto err_tree_mutex_unlock;
-		}
-
-		inode = f->f_dentry->d_inode;
-		if (!inode) {
+		f = fdget(cmd.fd);
+		if (!f.file) {
 			ret = -EBADF;
 			goto err_tree_mutex_unlock;
 		}
 
+		inode = f.file->f_path.dentry->d_inode;
 		xrcd = find_xrcd(file->device, inode);
 		if (!xrcd && !(cmd.oflags & O_CREAT)) {
 			/* no file descriptor. Need CREATE flag */
@@ -800,8 +795,8 @@ ssize_t ib_uverbs_open_xrcd(struct ib_uverbs_file *file,
 		goto err_copy;
 	}
 
-	if (f)
-		fput(f);
+	if (f.file)
+		fdput(f);
 
 	mutex_lock(&file->mutex);
 	list_add_tail(&obj->uobject.list, &file->ucontext->xrcd_list);
@@ -830,8 +825,8 @@ err:
 	put_uobj_write(&obj->uobject);
 
 err_tree_mutex_unlock:
-	if (f)
-		fput(f);
+	if (f.file)
+		fdput(f);
 
 	mutex_unlock(&file->device->xrcd_tree_mutex);
 
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
index 604556d..6f2ce6f 100644
--- a/drivers/infiniband/core/uverbs_main.c
+++ b/drivers/infiniband/core/uverbs_main.c
@@ -541,16 +541,15 @@ struct file *ib_uverbs_alloc_event_file(struct ib_uverbs_file *uverbs_file,
 struct ib_uverbs_event_file *ib_uverbs_lookup_comp_file(int fd)
 {
 	struct ib_uverbs_event_file *ev_file = NULL;
-	struct file *filp;
+	struct fd f = fdget(fd);
 
-	filp = fget(fd);
-	if (!filp)
+	if (!f.file)
 		return NULL;
 
-	if (filp->f_op != &uverbs_event_fops)
+	if (f.file->f_op != &uverbs_event_fops)
 		goto out;
 
-	ev_file = filp->private_data;
+	ev_file = f.file->private_data;
 	if (ev_file->is_async) {
 		ev_file = NULL;
 		goto out;
@@ -559,7 +558,7 @@ struct ib_uverbs_event_file *ib_uverbs_lookup_comp_file(int fd)
 	kref_get(&ev_file->ref);
 
 out:
-	fput(filp);
+	fdput(f);
 	return ev_file;
 }
 
diff --git a/drivers/infiniband/hw/cxgb4/qp.c b/drivers/infiniband/hw/cxgb4/qp.c
index 45aedf1..05bfe53 100644
--- a/drivers/infiniband/hw/cxgb4/qp.c
+++ b/drivers/infiniband/hw/cxgb4/qp.c
@@ -137,19 +137,25 @@ static int create_qp(struct c4iw_rdev *rdev, struct t4_wq *wq,
 		return -ENOMEM;
 
 	wq->rq.qid = c4iw_get_qpid(rdev, uctx);
-	if (!wq->rq.qid)
-		goto err1;
+	if (!wq->rq.qid) {
+		ret = -ENOMEM;
+		goto free_sq_qid;
+	}
 
 	if (!user) {
 		wq->sq.sw_sq = kzalloc(wq->sq.size * sizeof *wq->sq.sw_sq,
 				 GFP_KERNEL);
-		if (!wq->sq.sw_sq)
-			goto err2;
+		if (!wq->sq.sw_sq) {
+			ret = -ENOMEM;
+			goto free_rq_qid;
+		}
 
 		wq->rq.sw_rq = kzalloc(wq->rq.size * sizeof *wq->rq.sw_rq,
 				 GFP_KERNEL);
-		if (!wq->rq.sw_rq)
-			goto err3;
+		if (!wq->rq.sw_rq) {
+			ret = -ENOMEM;
+			goto free_sw_sq;
+		}
 	}
 
 	/*
@@ -157,15 +163,23 @@ static int create_qp(struct c4iw_rdev *rdev, struct t4_wq *wq,
 	 */
 	wq->rq.rqt_size = roundup_pow_of_two(wq->rq.size);
 	wq->rq.rqt_hwaddr = c4iw_rqtpool_alloc(rdev, wq->rq.rqt_size);
-	if (!wq->rq.rqt_hwaddr)
-		goto err4;
+	if (!wq->rq.rqt_hwaddr) {
+		ret = -ENOMEM;
+		goto free_sw_rq;
+	}
 
 	if (user) {
-		if (alloc_oc_sq(rdev, &wq->sq) && alloc_host_sq(rdev, &wq->sq))
-			goto err5;
+		ret = alloc_oc_sq(rdev, &wq->sq);
+		if (ret)
+			goto free_hwaddr;
+
+		ret = alloc_host_sq(rdev, &wq->sq);
+		if (ret)
+			goto free_sq;
 	} else
-		if (alloc_host_sq(rdev, &wq->sq))
-			goto err5;
+		ret = alloc_host_sq(rdev, &wq->sq);
+		if (ret)
+			goto free_hwaddr;
 	memset(wq->sq.queue, 0, wq->sq.memsize);
 	dma_unmap_addr_set(&wq->sq, mapping, wq->sq.dma_addr);
 
@@ -173,7 +187,7 @@ static int create_qp(struct c4iw_rdev *rdev, struct t4_wq *wq,
 					  wq->rq.memsize, &(wq->rq.dma_addr),
 					  GFP_KERNEL);
 	if (!wq->rq.queue)
-		goto err6;
+		goto free_sq;
 	PDBG("%s sq base va 0x%p pa 0x%llx rq base va 0x%p pa 0x%llx\n",
 		__func__, wq->sq.queue,
 		(unsigned long long)virt_to_phys(wq->sq.queue),
@@ -201,7 +215,7 @@ static int create_qp(struct c4iw_rdev *rdev, struct t4_wq *wq,
 	skb = alloc_skb(wr_len, GFP_KERNEL);
 	if (!skb) {
 		ret = -ENOMEM;
-		goto err7;
+		goto free_dma;
 	}
 	set_wr_txq(skb, CPL_PRIORITY_CONTROL, 0);
 
@@ -266,33 +280,33 @@ static int create_qp(struct c4iw_rdev *rdev, struct t4_wq *wq,
 
 	ret = c4iw_ofld_send(rdev, skb);
 	if (ret)
-		goto err7;
+		goto free_dma;
 	ret = c4iw_wait_for_reply(rdev, &wr_wait, 0, wq->sq.qid, __func__);
 	if (ret)
-		goto err7;
+		goto free_dma;
 
 	PDBG("%s sqid 0x%x rqid 0x%x kdb 0x%p squdb 0x%llx rqudb 0x%llx\n",
 	     __func__, wq->sq.qid, wq->rq.qid, wq->db,
 	     (unsigned long long)wq->sq.udb, (unsigned long long)wq->rq.udb);
 
 	return 0;
-err7:
+free_dma:
 	dma_free_coherent(&(rdev->lldi.pdev->dev),
 			  wq->rq.memsize, wq->rq.queue,
 			  dma_unmap_addr(&wq->rq, mapping));
-err6:
+free_sq:
 	dealloc_sq(rdev, &wq->sq);
-err5:
+free_hwaddr:
 	c4iw_rqtpool_free(rdev, wq->rq.rqt_hwaddr, wq->rq.rqt_size);
-err4:
+free_sw_rq:
 	kfree(wq->rq.sw_rq);
-err3:
+free_sw_sq:
 	kfree(wq->sq.sw_sq);
-err2:
+free_rq_qid:
 	c4iw_put_qpid(rdev, wq->rq.qid, uctx);
-err1:
+free_sq_qid:
 	c4iw_put_qpid(rdev, wq->sq.qid, uctx);
-	return -ENOMEM;
+	return ret;
 }
 
 static int build_immd(struct t4_sq *sq, struct fw_ri_immd *immdp,
@@ -1155,7 +1169,7 @@ static int ring_kernel_db(struct c4iw_qp *qhp, u32 qid, u16 inc)
 		 */
 		if (cxgb4_dbfifo_count(qhp->rhp->rdev.lldi.ports[0], 1) <
 		    (qhp->rhp->rdev.lldi.dbfifo_int_thresh << 5)) {
-			writel(V_QID(qid) | V_PIDX(inc), qhp->wq.db);
+			writel(QID(qid) | PIDX(inc), qhp->wq.db);
 			break;
 		}
 		set_current_state(TASK_UNINTERRUPTIBLE);
diff --git a/drivers/infiniband/hw/ehca/ehca_cq.c b/drivers/infiniband/hw/ehca/ehca_cq.c
index d9b0ebc..8f52901 100644
--- a/drivers/infiniband/hw/ehca/ehca_cq.c
+++ b/drivers/infiniband/hw/ehca/ehca_cq.c
@@ -220,7 +220,7 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, int comp_vector,
 			cq = ERR_PTR(-EAGAIN);
 			goto create_cq_exit4;
 		}
-		rpage = virt_to_abs(vpage);
+		rpage = __pa(vpage);
 
 		h_ret = hipz_h_register_rpage_cq(adapter_handle,
 						 my_cq->ipz_cq_handle,
diff --git a/drivers/infiniband/hw/ehca/ehca_eq.c b/drivers/infiniband/hw/ehca/ehca_eq.c
index 818d721..90da674 100644
--- a/drivers/infiniband/hw/ehca/ehca_eq.c
+++ b/drivers/infiniband/hw/ehca/ehca_eq.c
@@ -101,7 +101,7 @@ int ehca_create_eq(struct ehca_shca *shca,
 		if (!vpage)
 			goto create_eq_exit2;
 
-		rpage = virt_to_abs(vpage);
+		rpage = __pa(vpage);
 		h_ret = hipz_h_register_rpage_eq(shca->ipz_hca_handle,
 						 eq->ipz_eq_handle,
 						 &eq->pf,
diff --git a/drivers/infiniband/hw/ehca/ehca_irq.c b/drivers/infiniband/hw/ehca/ehca_irq.c
index 5358900..8615d7c 100644
--- a/drivers/infiniband/hw/ehca/ehca_irq.c
+++ b/drivers/infiniband/hw/ehca/ehca_irq.c
@@ -42,6 +42,7 @@
  */
 
 #include <linux/slab.h>
+#include <linux/smpboot.h>
 
 #include "ehca_classes.h"
 #include "ehca_irq.h"
@@ -652,7 +653,7 @@ void ehca_tasklet_eq(unsigned long data)
 	ehca_process_eq((struct ehca_shca*)data, 1);
 }
 
-static inline int find_next_online_cpu(struct ehca_comp_pool *pool)
+static int find_next_online_cpu(struct ehca_comp_pool *pool)
 {
 	int cpu;
 	unsigned long flags;
@@ -662,17 +663,20 @@ static inline int find_next_online_cpu(struct ehca_comp_pool *pool)
 		ehca_dmp(cpu_online_mask, cpumask_size(), "");
 
 	spin_lock_irqsave(&pool->last_cpu_lock, flags);
-	cpu = cpumask_next(pool->last_cpu, cpu_online_mask);
-	if (cpu >= nr_cpu_ids)
-		cpu = cpumask_first(cpu_online_mask);
-	pool->last_cpu = cpu;
+	do {
+		cpu = cpumask_next(pool->last_cpu, cpu_online_mask);
+		if (cpu >= nr_cpu_ids)
+			cpu = cpumask_first(cpu_online_mask);
+		pool->last_cpu = cpu;
+	} while (!per_cpu_ptr(pool->cpu_comp_tasks, cpu)->active);
 	spin_unlock_irqrestore(&pool->last_cpu_lock, flags);
 
 	return cpu;
 }
 
 static void __queue_comp_task(struct ehca_cq *__cq,
-			      struct ehca_cpu_comp_task *cct)
+			      struct ehca_cpu_comp_task *cct,
+			      struct task_struct *thread)
 {
 	unsigned long flags;
 
@@ -683,7 +687,7 @@ static void __queue_comp_task(struct ehca_cq *__cq,
 		__cq->nr_callbacks++;
 		list_add_tail(&__cq->entry, &cct->cq_list);
 		cct->cq_jobs++;
-		wake_up(&cct->wait_queue);
+		wake_up_process(thread);
 	} else
 		__cq->nr_callbacks++;
 
@@ -695,6 +699,7 @@ static void queue_comp_task(struct ehca_cq *__cq)
 {
 	int cpu_id;
 	struct ehca_cpu_comp_task *cct;
+	struct task_struct *thread;
 	int cq_jobs;
 	unsigned long flags;
 
@@ -702,7 +707,8 @@ static void queue_comp_task(struct ehca_cq *__cq)
 	BUG_ON(!cpu_online(cpu_id));
 
 	cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu_id);
-	BUG_ON(!cct);
+	thread = *per_cpu_ptr(pool->cpu_comp_threads, cpu_id);
+	BUG_ON(!cct || !thread);
 
 	spin_lock_irqsave(&cct->task_lock, flags);
 	cq_jobs = cct->cq_jobs;
@@ -710,28 +716,25 @@ static void queue_comp_task(struct ehca_cq *__cq)
 	if (cq_jobs > 0) {
 		cpu_id = find_next_online_cpu(pool);
 		cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu_id);
-		BUG_ON(!cct);
+		thread = *per_cpu_ptr(pool->cpu_comp_threads, cpu_id);
+		BUG_ON(!cct || !thread);
 	}
-
-	__queue_comp_task(__cq, cct);
+	__queue_comp_task(__cq, cct, thread);
 }
 
 static void run_comp_task(struct ehca_cpu_comp_task *cct)
 {
 	struct ehca_cq *cq;
-	unsigned long flags;
-
-	spin_lock_irqsave(&cct->task_lock, flags);
 
 	while (!list_empty(&cct->cq_list)) {
 		cq = list_entry(cct->cq_list.next, struct ehca_cq, entry);
-		spin_unlock_irqrestore(&cct->task_lock, flags);
+		spin_unlock_irq(&cct->task_lock);
 
 		comp_event_callback(cq);
 		if (atomic_dec_and_test(&cq->nr_events))
 			wake_up(&cq->wait_completion);
 
-		spin_lock_irqsave(&cct->task_lock, flags);
+		spin_lock_irq(&cct->task_lock);
 		spin_lock(&cq->task_lock);
 		cq->nr_callbacks--;
 		if (!cq->nr_callbacks) {
@@ -740,159 +743,76 @@ static void run_comp_task(struct ehca_cpu_comp_task *cct)
 		}
 		spin_unlock(&cq->task_lock);
 	}
-
-	spin_unlock_irqrestore(&cct->task_lock, flags);
 }
 
-static int comp_task(void *__cct)
+static void comp_task_park(unsigned int cpu)
 {
-	struct ehca_cpu_comp_task *cct = __cct;
-	int cql_empty;
-	DECLARE_WAITQUEUE(wait, current);
-
-	set_current_state(TASK_INTERRUPTIBLE);
-	while (!kthread_should_stop()) {
-		add_wait_queue(&cct->wait_queue, &wait);
-
-		spin_lock_irq(&cct->task_lock);
-		cql_empty = list_empty(&cct->cq_list);
-		spin_unlock_irq(&cct->task_lock);
-		if (cql_empty)
-			schedule();
-		else
-			__set_current_state(TASK_RUNNING);
-
-		remove_wait_queue(&cct->wait_queue, &wait);
+	struct ehca_cpu_comp_task *cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu);
+	struct ehca_cpu_comp_task *target;
+	struct task_struct *thread;
+	struct ehca_cq *cq, *tmp;
+	LIST_HEAD(list);
 
-		spin_lock_irq(&cct->task_lock);
-		cql_empty = list_empty(&cct->cq_list);
-		spin_unlock_irq(&cct->task_lock);
-		if (!cql_empty)
-			run_comp_task(__cct);
+	spin_lock_irq(&cct->task_lock);
+	cct->cq_jobs = 0;
+	cct->active = 0;
+	list_splice_init(&cct->cq_list, &list);
+	spin_unlock_irq(&cct->task_lock);
 
-		set_current_state(TASK_INTERRUPTIBLE);
+	cpu = find_next_online_cpu(pool);
+	target = per_cpu_ptr(pool->cpu_comp_tasks, cpu);
+	thread = *per_cpu_ptr(pool->cpu_comp_threads, cpu);
+	spin_lock_irq(&target->task_lock);
+	list_for_each_entry_safe(cq, tmp, &list, entry) {
+		list_del(&cq->entry);
+		__queue_comp_task(cq, target, thread);
 	}
-	__set_current_state(TASK_RUNNING);
-
-	return 0;
-}
-
-static struct task_struct *create_comp_task(struct ehca_comp_pool *pool,
-					    int cpu)
-{
-	struct ehca_cpu_comp_task *cct;
-
-	cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu);
-	spin_lock_init(&cct->task_lock);
-	INIT_LIST_HEAD(&cct->cq_list);
-	init_waitqueue_head(&cct->wait_queue);
-	cct->task = kthread_create_on_node(comp_task, cct, cpu_to_node(cpu),
-					   "ehca_comp/%d", cpu);
-
-	return cct->task;
+	spin_unlock_irq(&target->task_lock);
 }
 
-static void destroy_comp_task(struct ehca_comp_pool *pool,
-			      int cpu)
+static void comp_task_stop(unsigned int cpu, bool online)
 {
-	struct ehca_cpu_comp_task *cct;
-	struct task_struct *task;
-	unsigned long flags_cct;
-
-	cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu);
-
-	spin_lock_irqsave(&cct->task_lock, flags_cct);
+	struct ehca_cpu_comp_task *cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu);
 
-	task = cct->task;
-	cct->task = NULL;
+	spin_lock_irq(&cct->task_lock);
 	cct->cq_jobs = 0;
-
-	spin_unlock_irqrestore(&cct->task_lock, flags_cct);
-
-	if (task)
-		kthread_stop(task);
+	cct->active = 0;
+	WARN_ON(!list_empty(&cct->cq_list));
+	spin_unlock_irq(&cct->task_lock);
 }
 
-static void __cpuinit take_over_work(struct ehca_comp_pool *pool, int cpu)
+static int comp_task_should_run(unsigned int cpu)
 {
 	struct ehca_cpu_comp_task *cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu);
-	LIST_HEAD(list);
-	struct ehca_cq *cq;
-	unsigned long flags_cct;
-
-	spin_lock_irqsave(&cct->task_lock, flags_cct);
-
-	list_splice_init(&cct->cq_list, &list);
-
-	while (!list_empty(&list)) {
-		cq = list_entry(cct->cq_list.next, struct ehca_cq, entry);
-
-		list_del(&cq->entry);
-		__queue_comp_task(cq, this_cpu_ptr(pool->cpu_comp_tasks));
-	}
-
-	spin_unlock_irqrestore(&cct->task_lock, flags_cct);
 
+	return cct->cq_jobs;
 }
 
-static int __cpuinit comp_pool_callback(struct notifier_block *nfb,
-					unsigned long action,
-					void *hcpu)
+static void comp_task(unsigned int cpu)
 {
-	unsigned int cpu = (unsigned long)hcpu;
-	struct ehca_cpu_comp_task *cct;
+	struct ehca_cpu_comp_task *cct = this_cpu_ptr(pool->cpu_comp_tasks);
+	int cql_empty;
 
-	switch (action) {
-	case CPU_UP_PREPARE:
-	case CPU_UP_PREPARE_FROZEN:
-		ehca_gen_dbg("CPU: %x (CPU_PREPARE)", cpu);
-		if (!create_comp_task(pool, cpu)) {
-			ehca_gen_err("Can't create comp_task for cpu: %x", cpu);
-			return notifier_from_errno(-ENOMEM);
-		}
-		break;
-	case CPU_UP_CANCELED:
-	case CPU_UP_CANCELED_FROZEN:
-		ehca_gen_dbg("CPU: %x (CPU_CANCELED)", cpu);
-		cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu);
-		kthread_bind(cct->task, cpumask_any(cpu_online_mask));
-		destroy_comp_task(pool, cpu);
-		break;
-	case CPU_ONLINE:
-	case CPU_ONLINE_FROZEN:
-		ehca_gen_dbg("CPU: %x (CPU_ONLINE)", cpu);
-		cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu);
-		kthread_bind(cct->task, cpu);
-		wake_up_process(cct->task);
-		break;
-	case CPU_DOWN_PREPARE:
-	case CPU_DOWN_PREPARE_FROZEN:
-		ehca_gen_dbg("CPU: %x (CPU_DOWN_PREPARE)", cpu);
-		break;
-	case CPU_DOWN_FAILED:
-	case CPU_DOWN_FAILED_FROZEN:
-		ehca_gen_dbg("CPU: %x (CPU_DOWN_FAILED)", cpu);
-		break;
-	case CPU_DEAD:
-	case CPU_DEAD_FROZEN:
-		ehca_gen_dbg("CPU: %x (CPU_DEAD)", cpu);
-		destroy_comp_task(pool, cpu);
-		take_over_work(pool, cpu);
-		break;
+	spin_lock_irq(&cct->task_lock);
+	cql_empty = list_empty(&cct->cq_list);
+	if (!cql_empty) {
+		__set_current_state(TASK_RUNNING);
+		run_comp_task(cct);
 	}
-
-	return NOTIFY_OK;
+	spin_unlock_irq(&cct->task_lock);
 }
 
-static struct notifier_block comp_pool_callback_nb __cpuinitdata = {
-	.notifier_call	= comp_pool_callback,
-	.priority	= 0,
+static struct smp_hotplug_thread comp_pool_threads = {
+	.thread_should_run	= comp_task_should_run,
+	.thread_fn		= comp_task,
+	.thread_comm		= "ehca_comp/%u",
+	.cleanup		= comp_task_stop,
+	.park			= comp_task_park,
 };
 
 int ehca_create_comp_pool(void)
 {
-	int cpu;
-	struct task_struct *task;
+	int cpu, ret = -ENOMEM;
 
 	if (!ehca_scaling_code)
 		return 0;
@@ -905,38 +825,46 @@ int ehca_create_comp_pool(void)
 	pool->last_cpu = cpumask_any(cpu_online_mask);
 
 	pool->cpu_comp_tasks = alloc_percpu(struct ehca_cpu_comp_task);
-	if (pool->cpu_comp_tasks == NULL) {
-		kfree(pool);
-		return -EINVAL;
-	}
+	if (!pool->cpu_comp_tasks)
+		goto out_pool;
 
-	for_each_online_cpu(cpu) {
-		task = create_comp_task(pool, cpu);
-		if (task) {
-			kthread_bind(task, cpu);
-			wake_up_process(task);
-		}
+	pool->cpu_comp_threads = alloc_percpu(struct task_struct *);
+	if (!pool->cpu_comp_threads)
+		goto out_tasks;
+
+	for_each_present_cpu(cpu) {
+		struct ehca_cpu_comp_task *cct;
+
+		cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu);
+		spin_lock_init(&cct->task_lock);
+		INIT_LIST_HEAD(&cct->cq_list);
 	}
 
-	register_hotcpu_notifier(&comp_pool_callback_nb);
+	comp_pool_threads.store = pool->cpu_comp_threads;
+	ret = smpboot_register_percpu_thread(&comp_pool_threads);
+	if (ret)
+		goto out_threads;
 
-	printk(KERN_INFO "eHCA scaling code enabled\n");
+	pr_info("eHCA scaling code enabled\n");
+	return ret;
 
-	return 0;
+out_threads:
+	free_percpu(pool->cpu_comp_threads);
+out_tasks:
+	free_percpu(pool->cpu_comp_tasks);
+out_pool:
+	kfree(pool);
+	return ret;
 }
 
 void ehca_destroy_comp_pool(void)
 {
-	int i;
-
 	if (!ehca_scaling_code)
 		return;
 
-	unregister_hotcpu_notifier(&comp_pool_callback_nb);
-
-	for_each_online_cpu(i)
-		destroy_comp_task(pool, i);
+	smpboot_unregister_percpu_thread(&comp_pool_threads);
 
+	free_percpu(pool->cpu_comp_threads);
 	free_percpu(pool->cpu_comp_tasks);
 	kfree(pool);
 }
diff --git a/drivers/infiniband/hw/ehca/ehca_irq.h b/drivers/infiniband/hw/ehca/ehca_irq.h
index 3346cb0..5370199 100644
--- a/drivers/infiniband/hw/ehca/ehca_irq.h
+++ b/drivers/infiniband/hw/ehca/ehca_irq.h
@@ -58,15 +58,15 @@ void ehca_tasklet_eq(unsigned long data);
 void ehca_process_eq(struct ehca_shca *shca, int is_irq);
 
 struct ehca_cpu_comp_task {
-	wait_queue_head_t wait_queue;
 	struct list_head cq_list;
-	struct task_struct *task;
 	spinlock_t task_lock;
 	int cq_jobs;
+	int active;
 };
 
 struct ehca_comp_pool {
-	struct ehca_cpu_comp_task *cpu_comp_tasks;
+	struct ehca_cpu_comp_task __percpu *cpu_comp_tasks;
+	struct task_struct * __percpu *cpu_comp_threads;
 	int last_cpu;
 	spinlock_t last_cpu_lock;
 };
diff --git a/drivers/infiniband/hw/ehca/ehca_mrmw.c b/drivers/infiniband/hw/ehca/ehca_mrmw.c
index b781b2c..8784486 100644
--- a/drivers/infiniband/hw/ehca/ehca_mrmw.c
+++ b/drivers/infiniband/hw/ehca/ehca_mrmw.c
@@ -1136,7 +1136,7 @@ int ehca_reg_mr_rpages(struct ehca_shca *shca,
 		}
 
 		if (rnum > 1) {
-			rpage = virt_to_abs(kpage);
+			rpage = __pa(kpage);
 			if (!rpage) {
 				ehca_err(&shca->ib_device, "kpage=%p i=%x",
 					 kpage, i);
@@ -1231,7 +1231,7 @@ inline int ehca_rereg_mr_rereg1(struct ehca_shca *shca,
 			 pginfo->num_kpages, pginfo->num_hwpages, kpage);
 		goto ehca_rereg_mr_rereg1_exit1;
 	}
-	rpage = virt_to_abs(kpage);
+	rpage = __pa(kpage);
 	if (!rpage) {
 		ehca_err(&shca->ib_device, "kpage=%p", kpage);
 		ret = -EFAULT;
@@ -1525,7 +1525,7 @@ static inline void *ehca_calc_sectbase(int top, int dir, int idx)
 	unsigned long ret = idx;
 	ret |= dir << EHCA_DIR_INDEX_SHIFT;
 	ret |= top << EHCA_TOP_INDEX_SHIFT;
-	return abs_to_virt(ret << SECTION_SIZE_BITS);
+	return __va(ret << SECTION_SIZE_BITS);
 }
 
 #define ehca_bmap_valid(entry) \
@@ -1537,7 +1537,7 @@ static u64 ehca_reg_mr_section(int top, int dir, int idx, u64 *kpage,
 {
 	u64 h_ret = 0;
 	unsigned long page = 0;
-	u64 rpage = virt_to_abs(kpage);
+	u64 rpage = __pa(kpage);
 	int page_count;
 
 	void *sectbase = ehca_calc_sectbase(top, dir, idx);
@@ -1553,7 +1553,7 @@ static u64 ehca_reg_mr_section(int top, int dir, int idx, u64 *kpage,
 		for (rnum = 0; (rnum < MAX_RPAGES) && (page < page_count);
 		     rnum++) {
 			void *pg = sectbase + ((page++) * pginfo->hwpage_size);
-			kpage[rnum] = virt_to_abs(pg);
+			kpage[rnum] = __pa(pg);
 		}
 
 		h_ret = hipz_h_register_rpage_mr(shca->ipz_hca_handle, mr,
@@ -1870,9 +1870,8 @@ static int ehca_set_pagebuf_user1(struct ehca_mr_pginfo *pginfo,
 		for (i = pginfo->u.usr.next_nmap; i < chunk->nmap; ) {
 			pgaddr = page_to_pfn(sg_page(&chunk->page_list[i]))
 				<< PAGE_SHIFT ;
-			*kpage = phys_to_abs(pgaddr +
-					     (pginfo->next_hwpage *
-					      pginfo->hwpage_size));
+			*kpage = pgaddr + (pginfo->next_hwpage *
+					   pginfo->hwpage_size);
 			if ( !(*kpage) ) {
 				ehca_gen_err("pgaddr=%llx "
 					     "chunk->page_list[i]=%llx "
@@ -1927,7 +1926,7 @@ static int ehca_check_kpages_per_ate(struct scatterlist *page_list,
 		u64 pgaddr = page_to_pfn(sg_page(&page_list[t])) << PAGE_SHIFT;
 		if (ehca_debug_level >= 3)
 			ehca_gen_dbg("chunk_page=%llx value=%016llx", pgaddr,
-				     *(u64 *)abs_to_virt(phys_to_abs(pgaddr)));
+				     *(u64 *)__va(pgaddr));
 		if (pgaddr - PAGE_SIZE != *prev_pgaddr) {
 			ehca_gen_err("uncontiguous page found pgaddr=%llx "
 				     "prev_pgaddr=%llx page_list_i=%x",
@@ -1962,7 +1961,7 @@ static int ehca_set_pagebuf_user2(struct ehca_mr_pginfo *pginfo,
 			if (nr_kpages == kpages_per_hwpage) {
 				pgaddr = ( page_to_pfn(sg_page(&chunk->page_list[i]))
 					   << PAGE_SHIFT );
-				*kpage = phys_to_abs(pgaddr);
+				*kpage = pgaddr;
 				if ( !(*kpage) ) {
 					ehca_gen_err("pgaddr=%llx i=%x",
 						     pgaddr, i);
@@ -1990,13 +1989,11 @@ static int ehca_set_pagebuf_user2(struct ehca_mr_pginfo *pginfo,
 						 (pginfo->hwpage_size - 1)) >>
 						PAGE_SHIFT;
 					nr_kpages -= pginfo->kpage_cnt;
-					*kpage = phys_to_abs(
-						pgaddr &
-						~(pginfo->hwpage_size - 1));
+					*kpage = pgaddr &
+						 ~(pginfo->hwpage_size - 1);
 				}
 				if (ehca_debug_level >= 3) {
-					u64 val = *(u64 *)abs_to_virt(
-						phys_to_abs(pgaddr));
+					u64 val = *(u64 *)__va(pgaddr);
 					ehca_gen_dbg("kpage=%llx chunk_page=%llx "
 						     "value=%016llx",
 						     *kpage, pgaddr, val);
@@ -2084,9 +2081,8 @@ static int ehca_set_pagebuf_phys(struct ehca_mr_pginfo *pginfo,
 					     pginfo->num_hwpages, i);
 				return -EFAULT;
 			}
-			*kpage = phys_to_abs(
-				(pbuf->addr & ~(pginfo->hwpage_size - 1)) +
-				(pginfo->next_hwpage * pginfo->hwpage_size));
+			*kpage = (pbuf->addr & ~(pginfo->hwpage_size - 1)) +
+				 (pginfo->next_hwpage * pginfo->hwpage_size);
 			if ( !(*kpage) && pbuf->addr ) {
 				ehca_gen_err("pbuf->addr=%llx pbuf->size=%llx "
 					     "next_hwpage=%llx", pbuf->addr,
@@ -2124,8 +2120,8 @@ static int ehca_set_pagebuf_fmr(struct ehca_mr_pginfo *pginfo,
 	/* loop over desired page_list entries */
 	fmrlist = pginfo->u.fmr.page_list + pginfo->u.fmr.next_listelem;
 	for (i = 0; i < number; i++) {
-		*kpage = phys_to_abs((*fmrlist & ~(pginfo->hwpage_size - 1)) +
-				     pginfo->next_hwpage * pginfo->hwpage_size);
+		*kpage = (*fmrlist & ~(pginfo->hwpage_size - 1)) +
+			   pginfo->next_hwpage * pginfo->hwpage_size;
 		if ( !(*kpage) ) {
 			ehca_gen_err("*fmrlist=%llx fmrlist=%p "
 				     "next_listelem=%llx next_hwpage=%llx",
@@ -2152,8 +2148,7 @@ static int ehca_set_pagebuf_fmr(struct ehca_mr_pginfo *pginfo,
 			u64 prev = *kpage;
 			/* check if adrs are contiguous */
 			for (j = 1; j < cnt_per_hwpage; j++) {
-				u64 p = phys_to_abs(fmrlist[j] &
-						    ~(pginfo->hwpage_size - 1));
+				u64 p = fmrlist[j] & ~(pginfo->hwpage_size - 1);
 				if (prev + pginfo->u.fmr.fmr_pgsize != p) {
 					ehca_gen_err("uncontiguous fmr pages "
 						     "found prev=%llx p=%llx "
@@ -2388,8 +2383,8 @@ static int ehca_update_busmap(unsigned long pfn, unsigned long nr_pages)
 		memset(ehca_bmap, 0xFF, EHCA_TOP_MAP_SIZE);
 	}
 
-	start_section = phys_to_abs(pfn * PAGE_SIZE) / EHCA_SECTSIZE;
-	end_section = phys_to_abs((pfn + nr_pages) * PAGE_SIZE) / EHCA_SECTSIZE;
+	start_section = (pfn * PAGE_SIZE) / EHCA_SECTSIZE;
+	end_section = ((pfn + nr_pages) * PAGE_SIZE) / EHCA_SECTSIZE;
 	for (i = start_section; i < end_section; i++) {
 		int ret;
 		top = ehca_calc_index(i, EHCA_TOP_INDEX_SHIFT);
@@ -2508,7 +2503,7 @@ static u64 ehca_map_vaddr(void *caddr)
 	if (!ehca_bmap)
 		return EHCA_INVAL_ADDR;
 
-	abs_addr = virt_to_abs(caddr);
+	abs_addr = __pa(caddr);
 	top = ehca_calc_index(abs_addr, EHCA_TOP_INDEX_SHIFT + EHCA_SECTSHIFT);
 	if (!ehca_bmap_valid(ehca_bmap->top[top]))
 		return EHCA_INVAL_ADDR;
diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c b/drivers/infiniband/hw/ehca/ehca_qp.c
index 964f855..1493939 100644
--- a/drivers/infiniband/hw/ehca/ehca_qp.c
+++ b/drivers/infiniband/hw/ehca/ehca_qp.c
@@ -321,7 +321,7 @@ static inline int init_qp_queue(struct ehca_shca *shca,
 			ret = -EINVAL;
 			goto init_qp_queue1;
 		}
-		rpage = virt_to_abs(vpage);
+		rpage = __pa(vpage);
 
 		h_ret = hipz_h_register_rpage_qp(ipz_hca_handle,
 						 my_qp->ipz_qp_handle,
@@ -1094,7 +1094,7 @@ static int prepare_sqe_rts(struct ehca_qp *my_qp, struct ehca_shca *shca,
 	ehca_dbg(&shca->ib_device, "qp_num=%x bad_send_wqe_p=%p",
 		 qp_num, bad_send_wqe_p);
 	/* convert wqe pointer to vadr */
-	bad_send_wqe_v = abs_to_virt((u64)bad_send_wqe_p);
+	bad_send_wqe_v = __va((u64)bad_send_wqe_p);
 	if (ehca_debug_level >= 2)
 		ehca_dmp(bad_send_wqe_v, 32, "qp_num=%x bad_wqe", qp_num);
 	squeue = &my_qp->ipz_squeue;
@@ -1138,7 +1138,7 @@ static int calc_left_cqes(u64 wqe_p, struct ipz_queue *ipz_queue,
 	/* convert real to abs address */
 	wqe_p = wqe_p & (~(1UL << 63));
 
-	wqe_v = abs_to_virt(wqe_p);
+	wqe_v = __va(wqe_p);
 
 	if (ipz_queue_abs_to_offset(ipz_queue, wqe_p, &q_ofs)) {
 		ehca_gen_err("Invalid offset for calculating left cqes "
diff --git a/drivers/infiniband/hw/ehca/ehca_reqs.c b/drivers/infiniband/hw/ehca/ehca_reqs.c
index fd05f48..47f9498 100644
--- a/drivers/infiniband/hw/ehca/ehca_reqs.c
+++ b/drivers/infiniband/hw/ehca/ehca_reqs.c
@@ -135,7 +135,7 @@ static void trace_send_wr_ud(const struct ib_send_wr *send_wr)
 				     mad_hdr->attr_mod);
 		}
 		for (j = 0; j < send_wr->num_sge; j++) {
-			u8 *data = (u8 *)abs_to_virt(sge->addr);
+			u8 *data = __va(sge->addr);
 			ehca_gen_dbg("send_wr#%x sge#%x addr=%p length=%x "
 				     "lkey=%x",
 				     idx, j, data, sge->length, sge->lkey);
diff --git a/drivers/infiniband/hw/ehca/ehca_tools.h b/drivers/infiniband/hw/ehca/ehca_tools.h
index 54c0d23..d280b12 100644
--- a/drivers/infiniband/hw/ehca/ehca_tools.h
+++ b/drivers/infiniband/hw/ehca/ehca_tools.h
@@ -59,7 +59,6 @@
 #include <linux/device.h>
 
 #include <linux/atomic.h>
-#include <asm/abs_addr.h>
 #include <asm/ibmebus.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
diff --git a/drivers/infiniband/hw/ehca/ehca_uverbs.c b/drivers/infiniband/hw/ehca/ehca_uverbs.c
index 45ee89b..1a1d5d9 100644
--- a/drivers/infiniband/hw/ehca/ehca_uverbs.c
+++ b/drivers/infiniband/hw/ehca/ehca_uverbs.c
@@ -117,7 +117,7 @@ static int ehca_mmap_fw(struct vm_area_struct *vma, struct h_galpas *galpas,
 	physical = galpas->user.fw_handle;
 	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
 	ehca_gen_dbg("vsize=%llx physical=%llx", vsize, physical);
-	/* VM_IO | VM_RESERVED are set by remap_pfn_range() */
+	/* VM_IO | VM_DONTEXPAND | VM_DONTDUMP are set by remap_pfn_range() */
 	ret = remap_4k_pfn(vma, vma->vm_start, physical >> EHCA_PAGESHIFT,
 			   vma->vm_page_prot);
 	if (unlikely(ret)) {
@@ -139,7 +139,7 @@ static int ehca_mmap_queue(struct vm_area_struct *vma, struct ipz_queue *queue,
 	u64 start, ofs;
 	struct page *page;
 
-	vma->vm_flags |= VM_RESERVED;
+	vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
 	start = vma->vm_start;
 	for (ofs = 0; ofs < queue->queue_length; ofs += PAGE_SIZE) {
 		u64 virt_addr = (u64)ipz_qeit_calc(queue, ofs);
diff --git a/drivers/infiniband/hw/ehca/hcp_if.c b/drivers/infiniband/hw/ehca/hcp_if.c
index e6f9cdd..2d41d04 100644
--- a/drivers/infiniband/hw/ehca/hcp_if.c
+++ b/drivers/infiniband/hw/ehca/hcp_if.c
@@ -396,7 +396,7 @@ u64 hipz_h_query_port(const struct ipz_adapter_handle adapter_handle,
 		      struct hipz_query_port *query_port_response_block)
 {
 	u64 ret;
-	u64 r_cb = virt_to_abs(query_port_response_block);
+	u64 r_cb = __pa(query_port_response_block);
 
 	if (r_cb & (EHCA_PAGESIZE-1)) {
 		ehca_gen_err("response block not page aligned");
@@ -438,7 +438,7 @@ u64 hipz_h_modify_port(const struct ipz_adapter_handle adapter_handle,
 u64 hipz_h_query_hca(const struct ipz_adapter_handle adapter_handle,
 		     struct hipz_query_hca *query_hca_rblock)
 {
-	u64 r_cb = virt_to_abs(query_hca_rblock);
+	u64 r_cb = __pa(query_hca_rblock);
 
 	if (r_cb & (EHCA_PAGESIZE-1)) {
 		ehca_gen_err("response_block=%p not page aligned",
@@ -577,7 +577,7 @@ u64 hipz_h_modify_qp(const struct ipz_adapter_handle adapter_handle,
 				adapter_handle.handle, /* r4 */
 				qp_handle.handle,      /* r5 */
 				update_mask,	       /* r6 */
-				virt_to_abs(mqpcb),    /* r7 */
+				__pa(mqpcb),	       /* r7 */
 				0, 0, 0, 0, 0);
 
 	if (ret == H_NOT_ENOUGH_RESOURCES)
@@ -595,7 +595,7 @@ u64 hipz_h_query_qp(const struct ipz_adapter_handle adapter_handle,
 	return ehca_plpar_hcall_norets(H_QUERY_QP,
 				       adapter_handle.handle, /* r4 */
 				       qp_handle.handle,      /* r5 */
-				       virt_to_abs(qqpcb),    /* r6 */
+				       __pa(qqpcb),	      /* r6 */
 				       0, 0, 0, 0);
 }
 
@@ -787,7 +787,7 @@ u64 hipz_h_register_rpage_mr(const struct ipz_adapter_handle adapter_handle,
 		if (count > 1) {
 			u64 *kpage;
 			int i;
-			kpage = (u64 *)abs_to_virt(logical_address_of_page);
+			kpage = __va(logical_address_of_page);
 			for (i = 0; i < count; i++)
 				ehca_gen_dbg("kpage[%d]=%p",
 					     i, (void *)kpage[i]);
@@ -944,7 +944,7 @@ u64 hipz_h_error_data(const struct ipz_adapter_handle adapter_handle,
 		      void *rblock,
 		      unsigned long *byte_count)
 {
-	u64 r_cb = virt_to_abs(rblock);
+	u64 r_cb = __pa(rblock);
 
 	if (r_cb & (EHCA_PAGESIZE-1)) {
 		ehca_gen_err("rblock not page aligned.");
diff --git a/drivers/infiniband/hw/ehca/ipz_pt_fn.c b/drivers/infiniband/hw/ehca/ipz_pt_fn.c
index 1898d6e..62c71fa 100644
--- a/drivers/infiniband/hw/ehca/ipz_pt_fn.c
+++ b/drivers/infiniband/hw/ehca/ipz_pt_fn.c
@@ -81,7 +81,7 @@ int ipz_queue_abs_to_offset(struct ipz_queue *queue, u64 addr, u64 *q_offset)
 {
 	int i;
 	for (i = 0; i < queue->queue_length / queue->pagesize; i++) {
-		u64 page = (u64)virt_to_abs(queue->queue_pages[i]);
+		u64 page = __pa(queue->queue_pages[i]);
 		if (addr >= page && addr < page + queue->pagesize) {
 			*q_offset = addr - page + i * queue->pagesize;
 			return 0;
diff --git a/drivers/infiniband/hw/ipath/ipath_file_ops.c b/drivers/infiniband/hw/ipath/ipath_file_ops.c
index 736d9ed..3eb7e45 100644
--- a/drivers/infiniband/hw/ipath/ipath_file_ops.c
+++ b/drivers/infiniband/hw/ipath/ipath_file_ops.c
@@ -1225,7 +1225,7 @@ static int mmap_kvaddr(struct vm_area_struct *vma, u64 pgaddr,
 
 	vma->vm_pgoff = (unsigned long) addr >> PAGE_SHIFT;
 	vma->vm_ops = &ipath_file_vm_ops;
-	vma->vm_flags |= VM_RESERVED | VM_DONTEXPAND;
+	vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
 	ret = 1;
 
 bail:
diff --git a/drivers/infiniband/hw/mlx4/Makefile b/drivers/infiniband/hw/mlx4/Makefile
index 70f09c7..f4213b3 100644
--- a/drivers/infiniband/hw/mlx4/Makefile
+++ b/drivers/infiniband/hw/mlx4/Makefile
@@ -1,3 +1,3 @@
 obj-$(CONFIG_MLX4_INFINIBAND)	+= mlx4_ib.o
 
-mlx4_ib-y :=	ah.o cq.o doorbell.o mad.o main.o mr.o qp.o srq.o
+mlx4_ib-y :=	ah.o cq.o doorbell.o mad.o main.o mr.o qp.o srq.o mcg.o cm.o alias_GUID.o sysfs.o
diff --git a/drivers/infiniband/hw/mlx4/alias_GUID.c b/drivers/infiniband/hw/mlx4/alias_GUID.c
new file mode 100644
index 0000000..0fcd5cd
--- /dev/null
+++ b/drivers/infiniband/hw/mlx4/alias_GUID.c
@@ -0,0 +1,688 @@
+/*
+ * Copyright (c) 2012 Mellanox Technologies. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+ /***********************************************************/
+/*This file support the handling of the Alias GUID feature. */
+/***********************************************************/
+#include <rdma/ib_mad.h>
+#include <rdma/ib_smi.h>
+#include <rdma/ib_cache.h>
+#include <rdma/ib_sa.h>
+#include <rdma/ib_pack.h>
+#include <linux/mlx4/cmd.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <rdma/ib_user_verbs.h>
+#include <linux/delay.h>
+#include "mlx4_ib.h"
+
+/*
+The driver keeps the current state of all guids, as they are in the HW.
+Whenever we receive an smp mad GUIDInfo record, the data will be cached.
+*/
+
+struct mlx4_alias_guid_work_context {
+	u8 port;
+	struct mlx4_ib_dev     *dev ;
+	struct ib_sa_query     *sa_query;
+	struct completion	done;
+	int			query_id;
+	struct list_head	list;
+	int			block_num;
+};
+
+struct mlx4_next_alias_guid_work {
+	u8 port;
+	u8 block_num;
+	struct mlx4_sriov_alias_guid_info_rec_det rec_det;
+};
+
+
+void mlx4_ib_update_cache_on_guid_change(struct mlx4_ib_dev *dev, int block_num,
+					 u8 port_num, u8 *p_data)
+{
+	int i;
+	u64 guid_indexes;
+	int slave_id;
+	int port_index = port_num - 1;
+
+	if (!mlx4_is_master(dev->dev))
+		return;
+
+	guid_indexes = be64_to_cpu((__force __be64) dev->sriov.alias_guid.
+				   ports_guid[port_num - 1].
+				   all_rec_per_port[block_num].guid_indexes);
+	pr_debug("port: %d, guid_indexes: 0x%llx\n", port_num, guid_indexes);
+
+	for (i = 0; i < NUM_ALIAS_GUID_IN_REC; i++) {
+		/* The location of the specific index starts from bit number 4
+		 * until bit num 11 */
+		if (test_bit(i + 4, (unsigned long *)&guid_indexes)) {
+			slave_id = (block_num * NUM_ALIAS_GUID_IN_REC) + i ;
+			if (slave_id >= dev->dev->num_slaves) {
+				pr_debug("The last slave: %d\n", slave_id);
+				return;
+			}
+
+			/* cache the guid: */
+			memcpy(&dev->sriov.demux[port_index].guid_cache[slave_id],
+			       &p_data[i * GUID_REC_SIZE],
+			       GUID_REC_SIZE);
+		} else
+			pr_debug("Guid number: %d in block: %d"
+				 " was not updated\n", i, block_num);
+	}
+}
+
+static __be64 get_cached_alias_guid(struct mlx4_ib_dev *dev, int port, int index)
+{
+	if (index >= NUM_ALIAS_GUID_PER_PORT) {
+		pr_err("%s: ERROR: asked for index:%d\n", __func__, index);
+		return  (__force __be64) ((u64) 0xFFFFFFFFFFFFFFFFUL);
+	}
+	return *(__be64 *)&dev->sriov.demux[port - 1].guid_cache[index];
+}
+
+
+ib_sa_comp_mask mlx4_ib_get_aguid_comp_mask_from_ix(int index)
+{
+	return IB_SA_COMP_MASK(4 + index);
+}
+
+/*
+ * Whenever new GUID is set/unset (guid table change) create event and
+ * notify the relevant slave (master also should be notified).
+ * If the GUID value is not as we have in the cache the slave will not be
+ * updated; in this case it waits for the smp_snoop or the port management
+ * event to call the function and to update the slave.
+ * block_number - the index of the block (16 blocks available)
+ * port_number - 1 or 2
+ */
+void mlx4_ib_notify_slaves_on_guid_change(struct mlx4_ib_dev *dev,
+					  int block_num, u8 port_num,
+					  u8 *p_data)
+{
+	int i;
+	u64 guid_indexes;
+	int slave_id;
+	enum slave_port_state new_state;
+	enum slave_port_state prev_state;
+	__be64 tmp_cur_ag, form_cache_ag;
+	enum slave_port_gen_event gen_event;
+
+	if (!mlx4_is_master(dev->dev))
+		return;
+
+	guid_indexes = be64_to_cpu((__force __be64) dev->sriov.alias_guid.
+				   ports_guid[port_num - 1].
+				   all_rec_per_port[block_num].guid_indexes);
+	pr_debug("port: %d, guid_indexes: 0x%llx\n", port_num, guid_indexes);
+
+	/*calculate the slaves and notify them*/
+	for (i = 0; i < NUM_ALIAS_GUID_IN_REC; i++) {
+		/* the location of the specific index runs from bits 4..11 */
+		if (!(test_bit(i + 4, (unsigned long *)&guid_indexes)))
+			continue;
+
+		slave_id = (block_num * NUM_ALIAS_GUID_IN_REC) + i ;
+		if (slave_id >= dev->dev->num_slaves)
+			return;
+		tmp_cur_ag = *(__be64 *)&p_data[i * GUID_REC_SIZE];
+		form_cache_ag = get_cached_alias_guid(dev, port_num,
+					(NUM_ALIAS_GUID_IN_REC * block_num) + i);
+		/*
+		 * Check if guid is not the same as in the cache,
+		 * If it is different, wait for the snoop_smp or the port mgmt
+		 * change event to update the slave on its port state change
+		 */
+		if (tmp_cur_ag != form_cache_ag)
+			continue;
+		mlx4_gen_guid_change_eqe(dev->dev, slave_id, port_num);
+
+		/*2 cases: Valid GUID, and Invalid Guid*/
+
+		if (tmp_cur_ag != MLX4_NOT_SET_GUID) { /*valid GUID*/
+			prev_state = mlx4_get_slave_port_state(dev->dev, slave_id, port_num);
+			new_state = set_and_calc_slave_port_state(dev->dev, slave_id, port_num,
+								  MLX4_PORT_STATE_IB_PORT_STATE_EVENT_GID_VALID,
+								  &gen_event);
+			pr_debug("slave: %d, port: %d prev_port_state: %d,"
+				 " new_port_state: %d, gen_event: %d\n",
+				 slave_id, port_num, prev_state, new_state, gen_event);
+			if (gen_event == SLAVE_PORT_GEN_EVENT_UP) {
+				pr_debug("sending PORT_UP event to slave: %d, port: %d\n",
+					 slave_id, port_num);
+				mlx4_gen_port_state_change_eqe(dev->dev, slave_id,
+							       port_num, MLX4_PORT_CHANGE_SUBTYPE_ACTIVE);
+			}
+		} else { /* request to invalidate GUID */
+			set_and_calc_slave_port_state(dev->dev, slave_id, port_num,
+						      MLX4_PORT_STATE_IB_EVENT_GID_INVALID,
+						      &gen_event);
+			pr_debug("sending PORT DOWN event to slave: %d, port: %d\n",
+				 slave_id, port_num);
+			mlx4_gen_port_state_change_eqe(dev->dev, slave_id, port_num,
+						       MLX4_PORT_CHANGE_SUBTYPE_DOWN);
+		}
+	}
+}
+
+static void aliasguid_query_handler(int status,
+				    struct ib_sa_guidinfo_rec *guid_rec,
+				    void *context)
+{
+	struct mlx4_ib_dev *dev;
+	struct mlx4_alias_guid_work_context *cb_ctx = context;
+	u8 port_index ;
+	int i;
+	struct mlx4_sriov_alias_guid_info_rec_det *rec;
+	unsigned long flags, flags1;
+
+	if (!context)
+		return;
+
+	dev = cb_ctx->dev;
+	port_index = cb_ctx->port - 1;
+	rec = &dev->sriov.alias_guid.ports_guid[port_index].
+		all_rec_per_port[cb_ctx->block_num];
+
+	if (status) {
+		rec->status = MLX4_GUID_INFO_STATUS_IDLE;
+		pr_debug("(port: %d) failed: status = %d\n",
+			 cb_ctx->port, status);
+		goto out;
+	}
+
+	if (guid_rec->block_num != cb_ctx->block_num) {
+		pr_err("block num mismatch: %d != %d\n",
+		       cb_ctx->block_num, guid_rec->block_num);
+		goto out;
+	}
+
+	pr_debug("lid/port: %d/%d, block_num: %d\n",
+		 be16_to_cpu(guid_rec->lid), cb_ctx->port,
+		 guid_rec->block_num);
+
+	rec = &dev->sriov.alias_guid.ports_guid[port_index].
+		all_rec_per_port[guid_rec->block_num];
+
+	rec->status = MLX4_GUID_INFO_STATUS_SET;
+	rec->method = MLX4_GUID_INFO_RECORD_SET;
+
+	for (i = 0 ; i < NUM_ALIAS_GUID_IN_REC; i++) {
+		__be64 tmp_cur_ag;
+		tmp_cur_ag = *(__be64 *)&guid_rec->guid_info_list[i * GUID_REC_SIZE];
+		/* check if the SM didn't assign one of the records.
+		 * if it didn't, if it was not sysadmin request:
+		 * ask the SM to give a new GUID, (instead of the driver request).
+		 */
+		if (tmp_cur_ag == MLX4_NOT_SET_GUID) {
+			mlx4_ib_warn(&dev->ib_dev, "%s:Record num %d in "
+				     "block_num: %d was declined by SM, "
+				     "ownership by %d (0 = driver, 1=sysAdmin,"
+				     " 2=None)\n", __func__, i,
+				     guid_rec->block_num, rec->ownership);
+			if (rec->ownership == MLX4_GUID_DRIVER_ASSIGN) {
+				/* if it is driver assign, asks for new GUID from SM*/
+				*(__be64 *)&rec->all_recs[i * GUID_REC_SIZE] =
+					MLX4_NOT_SET_GUID;
+
+				/* Mark the record as not assigned, and let it
+				 * be sent again in the next work sched.*/
+				rec->status = MLX4_GUID_INFO_STATUS_IDLE;
+				rec->guid_indexes |= mlx4_ib_get_aguid_comp_mask_from_ix(i);
+			}
+		} else {
+		       /* properly assigned record. */
+		       /* We save the GUID we just got from the SM in the
+			* admin_guid in order to be persistent, and in the
+			* request from the sm the process will ask for the same GUID */
+			if (rec->ownership == MLX4_GUID_SYSADMIN_ASSIGN &&
+			    tmp_cur_ag != *(__be64 *)&rec->all_recs[i * GUID_REC_SIZE]) {
+				/* the sysadmin assignment failed.*/
+				mlx4_ib_warn(&dev->ib_dev, "%s: Failed to set"
+					     " admin guid after SysAdmin "
+					     "configuration. "
+					     "Record num %d in block_num:%d "
+					     "was declined by SM, "
+					     "new val(0x%llx) was kept\n",
+					      __func__, i,
+					     guid_rec->block_num,
+					     be64_to_cpu(*(__be64 *) &
+							 rec->all_recs[i * GUID_REC_SIZE]));
+			} else {
+				memcpy(&rec->all_recs[i * GUID_REC_SIZE],
+				       &guid_rec->guid_info_list[i * GUID_REC_SIZE],
+				       GUID_REC_SIZE);
+			}
+		}
+	}
+	/*
+	The func is call here to close the cases when the
+	sm doesn't send smp, so in the sa response the driver
+	notifies the slave.
+	*/
+	mlx4_ib_notify_slaves_on_guid_change(dev, guid_rec->block_num,
+					     cb_ctx->port,
+					     guid_rec->guid_info_list);
+out:
+	spin_lock_irqsave(&dev->sriov.going_down_lock, flags);
+	spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags1);
+	if (!dev->sriov.is_going_down)
+		queue_delayed_work(dev->sriov.alias_guid.ports_guid[port_index].wq,
+				   &dev->sriov.alias_guid.ports_guid[port_index].
+				   alias_guid_work, 0);
+	if (cb_ctx->sa_query) {
+		list_del(&cb_ctx->list);
+		kfree(cb_ctx);
+	} else
+		complete(&cb_ctx->done);
+	spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags1);
+	spin_unlock_irqrestore(&dev->sriov.going_down_lock, flags);
+}
+
+static void invalidate_guid_record(struct mlx4_ib_dev *dev, u8 port, int index)
+{
+	int i;
+	u64 cur_admin_val;
+	ib_sa_comp_mask comp_mask = 0;
+
+	dev->sriov.alias_guid.ports_guid[port - 1].all_rec_per_port[index].status
+		= MLX4_GUID_INFO_STATUS_IDLE;
+	dev->sriov.alias_guid.ports_guid[port - 1].all_rec_per_port[index].method
+		= MLX4_GUID_INFO_RECORD_SET;
+
+	/* calculate the comp_mask for that record.*/
+	for (i = 0; i < NUM_ALIAS_GUID_IN_REC; i++) {
+		cur_admin_val =
+			*(u64 *)&dev->sriov.alias_guid.ports_guid[port - 1].
+			all_rec_per_port[index].all_recs[GUID_REC_SIZE * i];
+		/*
+		check the admin value: if it's for delete (~00LL) or
+		it is the first guid of the first record (hw guid) or
+		the records is not in ownership of the sysadmin and the sm doesn't
+		need to assign GUIDs, then don't put it up for assignment.
+		*/
+		if (MLX4_GUID_FOR_DELETE_VAL == cur_admin_val ||
+		    (!index && !i) ||
+		    MLX4_GUID_NONE_ASSIGN == dev->sriov.alias_guid.
+		    ports_guid[port - 1].all_rec_per_port[index].ownership)
+			continue;
+		comp_mask |= mlx4_ib_get_aguid_comp_mask_from_ix(i);
+	}
+	dev->sriov.alias_guid.ports_guid[port - 1].
+		all_rec_per_port[index].guid_indexes = comp_mask;
+}
+
+static int set_guid_rec(struct ib_device *ibdev,
+			u8 port, int index,
+			struct mlx4_sriov_alias_guid_info_rec_det *rec_det)
+{
+	int err;
+	struct mlx4_ib_dev *dev = to_mdev(ibdev);
+	struct ib_sa_guidinfo_rec guid_info_rec;
+	ib_sa_comp_mask comp_mask;
+	struct ib_port_attr attr;
+	struct mlx4_alias_guid_work_context *callback_context;
+	unsigned long resched_delay, flags, flags1;
+	struct list_head *head =
+		&dev->sriov.alias_guid.ports_guid[port - 1].cb_list;
+
+	err = __mlx4_ib_query_port(ibdev, port, &attr, 1);
+	if (err) {
+		pr_debug("mlx4_ib_query_port failed (err: %d), port: %d\n",
+			 err, port);
+		return err;
+	}
+	/*check the port was configured by the sm, otherwise no need to send */
+	if (attr.state != IB_PORT_ACTIVE) {
+		pr_debug("port %d not active...rescheduling\n", port);
+		resched_delay = 5 * HZ;
+		err = -EAGAIN;
+		goto new_schedule;
+	}
+
+	callback_context = kmalloc(sizeof *callback_context, GFP_KERNEL);
+	if (!callback_context) {
+		err = -ENOMEM;
+		resched_delay = HZ * 5;
+		goto new_schedule;
+	}
+	callback_context->port = port;
+	callback_context->dev = dev;
+	callback_context->block_num = index;
+
+	memset(&guid_info_rec, 0, sizeof (struct ib_sa_guidinfo_rec));
+
+	guid_info_rec.lid = cpu_to_be16(attr.lid);
+	guid_info_rec.block_num = index;
+
+	memcpy(guid_info_rec.guid_info_list, rec_det->all_recs,
+	       GUID_REC_SIZE * NUM_ALIAS_GUID_IN_REC);
+	comp_mask = IB_SA_GUIDINFO_REC_LID | IB_SA_GUIDINFO_REC_BLOCK_NUM |
+		rec_det->guid_indexes;
+
+	init_completion(&callback_context->done);
+	spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags1);
+	list_add_tail(&callback_context->list, head);
+	spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags1);
+
+	callback_context->query_id =
+		ib_sa_guid_info_rec_query(dev->sriov.alias_guid.sa_client,
+					  ibdev, port, &guid_info_rec,
+					  comp_mask, rec_det->method, 1000,
+					  GFP_KERNEL, aliasguid_query_handler,
+					  callback_context,
+					  &callback_context->sa_query);
+	if (callback_context->query_id < 0) {
+		pr_debug("ib_sa_guid_info_rec_query failed, query_id: "
+			 "%d. will reschedule to the next 1 sec.\n",
+			 callback_context->query_id);
+		spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags1);
+		list_del(&callback_context->list);
+		kfree(callback_context);
+		spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags1);
+		resched_delay = 1 * HZ;
+		err = -EAGAIN;
+		goto new_schedule;
+	}
+	err = 0;
+	goto out;
+
+new_schedule:
+	spin_lock_irqsave(&dev->sriov.going_down_lock, flags);
+	spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags1);
+	invalidate_guid_record(dev, port, index);
+	if (!dev->sriov.is_going_down) {
+		queue_delayed_work(dev->sriov.alias_guid.ports_guid[port - 1].wq,
+				   &dev->sriov.alias_guid.ports_guid[port - 1].alias_guid_work,
+				   resched_delay);
+	}
+	spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags1);
+	spin_unlock_irqrestore(&dev->sriov.going_down_lock, flags);
+
+out:
+	return err;
+}
+
+void mlx4_ib_invalidate_all_guid_record(struct mlx4_ib_dev *dev, int port)
+{
+	int i;
+	unsigned long flags, flags1;
+
+	pr_debug("port %d\n", port);
+
+	spin_lock_irqsave(&dev->sriov.going_down_lock, flags);
+	spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags1);
+	for (i = 0; i < NUM_ALIAS_GUID_REC_IN_PORT; i++)
+		invalidate_guid_record(dev, port, i);
+
+	if (mlx4_is_master(dev->dev) && !dev->sriov.is_going_down) {
+		/*
+		make sure no work waits in the queue, if the work is already
+		queued(not on the timer) the cancel will fail. That is not a problem
+		because we just want the work started.
+		*/
+		__cancel_delayed_work(&dev->sriov.alias_guid.
+				      ports_guid[port - 1].alias_guid_work);
+		queue_delayed_work(dev->sriov.alias_guid.ports_guid[port - 1].wq,
+				   &dev->sriov.alias_guid.ports_guid[port - 1].alias_guid_work,
+				   0);
+	}
+	spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags1);
+	spin_unlock_irqrestore(&dev->sriov.going_down_lock, flags);
+}
+
+/* The function returns the next record that was
+ * not configured (or failed to be configured) */
+static int get_next_record_to_update(struct mlx4_ib_dev *dev, u8 port,
+				     struct mlx4_next_alias_guid_work *rec)
+{
+	int j;
+	unsigned long flags;
+
+	for (j = 0; j < NUM_ALIAS_GUID_REC_IN_PORT; j++) {
+		spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags);
+		if (dev->sriov.alias_guid.ports_guid[port].all_rec_per_port[j].status ==
+		    MLX4_GUID_INFO_STATUS_IDLE) {
+			memcpy(&rec->rec_det,
+			       &dev->sriov.alias_guid.ports_guid[port].all_rec_per_port[j],
+			       sizeof (struct mlx4_sriov_alias_guid_info_rec_det));
+			rec->port = port;
+			rec->block_num = j;
+			dev->sriov.alias_guid.ports_guid[port].all_rec_per_port[j].status =
+				MLX4_GUID_INFO_STATUS_PENDING;
+			spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags);
+			return 0;
+		}
+		spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags);
+	}
+	return -ENOENT;
+}
+
+static void set_administratively_guid_record(struct mlx4_ib_dev *dev, int port,
+					     int rec_index,
+					     struct mlx4_sriov_alias_guid_info_rec_det *rec_det)
+{
+	dev->sriov.alias_guid.ports_guid[port].all_rec_per_port[rec_index].guid_indexes =
+		rec_det->guid_indexes;
+	memcpy(dev->sriov.alias_guid.ports_guid[port].all_rec_per_port[rec_index].all_recs,
+	       rec_det->all_recs, NUM_ALIAS_GUID_IN_REC * GUID_REC_SIZE);
+	dev->sriov.alias_guid.ports_guid[port].all_rec_per_port[rec_index].status =
+		rec_det->status;
+}
+
+static void set_all_slaves_guids(struct mlx4_ib_dev *dev, int port)
+{
+	int j;
+	struct mlx4_sriov_alias_guid_info_rec_det rec_det ;
+
+	for (j = 0 ; j < NUM_ALIAS_GUID_REC_IN_PORT ; j++) {
+		memset(rec_det.all_recs, 0, NUM_ALIAS_GUID_IN_REC * GUID_REC_SIZE);
+		rec_det.guid_indexes = (!j ? 0 : IB_SA_GUIDINFO_REC_GID0) |
+			IB_SA_GUIDINFO_REC_GID1 | IB_SA_GUIDINFO_REC_GID2 |
+			IB_SA_GUIDINFO_REC_GID3 | IB_SA_GUIDINFO_REC_GID4 |
+			IB_SA_GUIDINFO_REC_GID5 | IB_SA_GUIDINFO_REC_GID6 |
+			IB_SA_GUIDINFO_REC_GID7;
+		rec_det.status = MLX4_GUID_INFO_STATUS_IDLE;
+		set_administratively_guid_record(dev, port, j, &rec_det);
+	}
+}
+
+static void alias_guid_work(struct work_struct *work)
+{
+	struct delayed_work *delay = to_delayed_work(work);
+	int ret = 0;
+	struct mlx4_next_alias_guid_work *rec;
+	struct mlx4_sriov_alias_guid_port_rec_det *sriov_alias_port =
+		container_of(delay, struct mlx4_sriov_alias_guid_port_rec_det,
+			     alias_guid_work);
+	struct mlx4_sriov_alias_guid *sriov_alias_guid = sriov_alias_port->parent;
+	struct mlx4_ib_sriov *ib_sriov = container_of(sriov_alias_guid,
+						struct mlx4_ib_sriov,
+						alias_guid);
+	struct mlx4_ib_dev *dev = container_of(ib_sriov, struct mlx4_ib_dev, sriov);
+
+	rec = kzalloc(sizeof *rec, GFP_KERNEL);
+	if (!rec) {
+		pr_err("alias_guid_work: No Memory\n");
+		return;
+	}
+
+	pr_debug("starting [port: %d]...\n", sriov_alias_port->port + 1);
+	ret = get_next_record_to_update(dev, sriov_alias_port->port, rec);
+	if (ret) {
+		pr_debug("No more records to update.\n");
+		goto out;
+	}
+
+	set_guid_rec(&dev->ib_dev, rec->port + 1, rec->block_num,
+		     &rec->rec_det);
+
+out:
+	kfree(rec);
+}
+
+
+void mlx4_ib_init_alias_guid_work(struct mlx4_ib_dev *dev, int port)
+{
+	unsigned long flags, flags1;
+
+	if (!mlx4_is_master(dev->dev))
+		return;
+	spin_lock_irqsave(&dev->sriov.going_down_lock, flags);
+	spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags1);
+	if (!dev->sriov.is_going_down) {
+		queue_delayed_work(dev->sriov.alias_guid.ports_guid[port].wq,
+			   &dev->sriov.alias_guid.ports_guid[port].alias_guid_work, 0);
+	}
+	spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags1);
+	spin_unlock_irqrestore(&dev->sriov.going_down_lock, flags);
+}
+
+void mlx4_ib_destroy_alias_guid_service(struct mlx4_ib_dev *dev)
+{
+	int i;
+	struct mlx4_ib_sriov *sriov = &dev->sriov;
+	struct mlx4_alias_guid_work_context *cb_ctx;
+	struct mlx4_sriov_alias_guid_port_rec_det *det;
+	struct ib_sa_query *sa_query;
+	unsigned long flags;
+
+	for (i = 0 ; i < dev->num_ports; i++) {
+		cancel_delayed_work(&dev->sriov.alias_guid.ports_guid[i].alias_guid_work);
+		det = &sriov->alias_guid.ports_guid[i];
+		spin_lock_irqsave(&sriov->alias_guid.ag_work_lock, flags);
+		while (!list_empty(&det->cb_list)) {
+			cb_ctx = list_entry(det->cb_list.next,
+					    struct mlx4_alias_guid_work_context,
+					    list);
+			sa_query = cb_ctx->sa_query;
+			cb_ctx->sa_query = NULL;
+			list_del(&cb_ctx->list);
+			spin_unlock_irqrestore(&sriov->alias_guid.ag_work_lock, flags);
+			ib_sa_cancel_query(cb_ctx->query_id, sa_query);
+			wait_for_completion(&cb_ctx->done);
+			kfree(cb_ctx);
+			spin_lock_irqsave(&sriov->alias_guid.ag_work_lock, flags);
+		}
+		spin_unlock_irqrestore(&sriov->alias_guid.ag_work_lock, flags);
+	}
+	for (i = 0 ; i < dev->num_ports; i++) {
+		flush_workqueue(dev->sriov.alias_guid.ports_guid[i].wq);
+		destroy_workqueue(dev->sriov.alias_guid.ports_guid[i].wq);
+	}
+	ib_sa_unregister_client(dev->sriov.alias_guid.sa_client);
+	kfree(dev->sriov.alias_guid.sa_client);
+}
+
+int mlx4_ib_init_alias_guid_service(struct mlx4_ib_dev *dev)
+{
+	char alias_wq_name[15];
+	int ret = 0;
+	int i, j, k;
+	union ib_gid gid;
+
+	if (!mlx4_is_master(dev->dev))
+		return 0;
+	dev->sriov.alias_guid.sa_client =
+		kzalloc(sizeof *dev->sriov.alias_guid.sa_client, GFP_KERNEL);
+	if (!dev->sriov.alias_guid.sa_client)
+		return -ENOMEM;
+
+	ib_sa_register_client(dev->sriov.alias_guid.sa_client);
+
+	spin_lock_init(&dev->sriov.alias_guid.ag_work_lock);
+
+	for (i = 1; i <= dev->num_ports; ++i) {
+		if (dev->ib_dev.query_gid(&dev->ib_dev , i, 0, &gid)) {
+			ret = -EFAULT;
+			goto err_unregister;
+		}
+	}
+
+	for (i = 0 ; i < dev->num_ports; i++) {
+		memset(&dev->sriov.alias_guid.ports_guid[i], 0,
+		       sizeof (struct mlx4_sriov_alias_guid_port_rec_det));
+		/*Check if the SM doesn't need to assign the GUIDs*/
+		for (j = 0; j < NUM_ALIAS_GUID_REC_IN_PORT; j++) {
+			if (mlx4_ib_sm_guid_assign) {
+				dev->sriov.alias_guid.ports_guid[i].
+					all_rec_per_port[j].
+					ownership = MLX4_GUID_DRIVER_ASSIGN;
+				continue;
+			}
+			dev->sriov.alias_guid.ports_guid[i].all_rec_per_port[j].
+					ownership = MLX4_GUID_NONE_ASSIGN;
+			/*mark each val as it was deleted,
+			  till the sysAdmin will give it valid val*/
+			for (k = 0; k < NUM_ALIAS_GUID_IN_REC; k++) {
+				*(__be64 *)&dev->sriov.alias_guid.ports_guid[i].
+					all_rec_per_port[j].all_recs[GUID_REC_SIZE * k] =
+						cpu_to_be64(MLX4_GUID_FOR_DELETE_VAL);
+			}
+		}
+		INIT_LIST_HEAD(&dev->sriov.alias_guid.ports_guid[i].cb_list);
+		/*prepare the records, set them to be allocated by sm*/
+		for (j = 0 ; j < NUM_ALIAS_GUID_REC_IN_PORT; j++)
+			invalidate_guid_record(dev, i + 1, j);
+
+		dev->sriov.alias_guid.ports_guid[i].parent = &dev->sriov.alias_guid;
+		dev->sriov.alias_guid.ports_guid[i].port  = i;
+		if (mlx4_ib_sm_guid_assign)
+			set_all_slaves_guids(dev, i);
+
+		snprintf(alias_wq_name, sizeof alias_wq_name, "alias_guid%d", i);
+		dev->sriov.alias_guid.ports_guid[i].wq =
+			create_singlethread_workqueue(alias_wq_name);
+		if (!dev->sriov.alias_guid.ports_guid[i].wq) {
+			ret = -ENOMEM;
+			goto err_thread;
+		}
+		INIT_DELAYED_WORK(&dev->sriov.alias_guid.ports_guid[i].alias_guid_work,
+			  alias_guid_work);
+	}
+	return 0;
+
+err_thread:
+	for (--i; i >= 0; i--) {
+		destroy_workqueue(dev->sriov.alias_guid.ports_guid[i].wq);
+		dev->sriov.alias_guid.ports_guid[i].wq = NULL;
+	}
+
+err_unregister:
+	ib_sa_unregister_client(dev->sriov.alias_guid.sa_client);
+	kfree(dev->sriov.alias_guid.sa_client);
+	dev->sriov.alias_guid.sa_client = NULL;
+	pr_err("init_alias_guid_service: Failed. (ret:%d)\n", ret);
+	return ret;
+}
diff --git a/drivers/infiniband/hw/mlx4/cm.c b/drivers/infiniband/hw/mlx4/cm.c
new file mode 100644
index 0000000..80079e5
--- /dev/null
+++ b/drivers/infiniband/hw/mlx4/cm.c
@@ -0,0 +1,437 @@
+/*
+ * Copyright (c) 2012 Mellanox Technologies. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <rdma/ib_mad.h>
+
+#include <linux/mlx4/cmd.h>
+#include <linux/rbtree.h>
+#include <linux/idr.h>
+#include <rdma/ib_cm.h>
+
+#include "mlx4_ib.h"
+
+#define CM_CLEANUP_CACHE_TIMEOUT  (5 * HZ)
+
+struct id_map_entry {
+	struct rb_node node;
+
+	u32 sl_cm_id;
+	u32 pv_cm_id;
+	int slave_id;
+	int scheduled_delete;
+	struct mlx4_ib_dev *dev;
+
+	struct list_head list;
+	struct delayed_work timeout;
+};
+
+struct cm_generic_msg {
+	struct ib_mad_hdr hdr;
+
+	__be32 local_comm_id;
+	__be32 remote_comm_id;
+};
+
+struct cm_req_msg {
+	unsigned char unused[0x60];
+	union ib_gid primary_path_sgid;
+};
+
+
+static void set_local_comm_id(struct ib_mad *mad, u32 cm_id)
+{
+	struct cm_generic_msg *msg = (struct cm_generic_msg *)mad;
+	msg->local_comm_id = cpu_to_be32(cm_id);
+}
+
+static u32 get_local_comm_id(struct ib_mad *mad)
+{
+	struct cm_generic_msg *msg = (struct cm_generic_msg *)mad;
+
+	return be32_to_cpu(msg->local_comm_id);
+}
+
+static void set_remote_comm_id(struct ib_mad *mad, u32 cm_id)
+{
+	struct cm_generic_msg *msg = (struct cm_generic_msg *)mad;
+	msg->remote_comm_id = cpu_to_be32(cm_id);
+}
+
+static u32 get_remote_comm_id(struct ib_mad *mad)
+{
+	struct cm_generic_msg *msg = (struct cm_generic_msg *)mad;
+
+	return be32_to_cpu(msg->remote_comm_id);
+}
+
+static union ib_gid gid_from_req_msg(struct ib_device *ibdev, struct ib_mad *mad)
+{
+	struct cm_req_msg *msg = (struct cm_req_msg *)mad;
+
+	return msg->primary_path_sgid;
+}
+
+/* Lock should be taken before called */
+static struct id_map_entry *
+id_map_find_by_sl_id(struct ib_device *ibdev, u32 slave_id, u32 sl_cm_id)
+{
+	struct rb_root *sl_id_map = &to_mdev(ibdev)->sriov.sl_id_map;
+	struct rb_node *node = sl_id_map->rb_node;
+
+	while (node) {
+		struct id_map_entry *id_map_entry =
+			rb_entry(node, struct id_map_entry, node);
+
+		if (id_map_entry->sl_cm_id > sl_cm_id)
+			node = node->rb_left;
+		else if (id_map_entry->sl_cm_id < sl_cm_id)
+			node = node->rb_right;
+		else if (id_map_entry->slave_id > slave_id)
+			node = node->rb_left;
+		else if (id_map_entry->slave_id < slave_id)
+			node = node->rb_right;
+		else
+			return id_map_entry;
+	}
+	return NULL;
+}
+
+static void id_map_ent_timeout(struct work_struct *work)
+{
+	struct delayed_work *delay = to_delayed_work(work);
+	struct id_map_entry *ent = container_of(delay, struct id_map_entry, timeout);
+	struct id_map_entry *db_ent, *found_ent;
+	struct mlx4_ib_dev *dev = ent->dev;
+	struct mlx4_ib_sriov *sriov = &dev->sriov;
+	struct rb_root *sl_id_map = &sriov->sl_id_map;
+	int pv_id = (int) ent->pv_cm_id;
+
+	spin_lock(&sriov->id_map_lock);
+	db_ent = (struct id_map_entry *)idr_find(&sriov->pv_id_table, pv_id);
+	if (!db_ent)
+		goto out;
+	found_ent = id_map_find_by_sl_id(&dev->ib_dev, ent->slave_id, ent->sl_cm_id);
+	if (found_ent && found_ent == ent)
+		rb_erase(&found_ent->node, sl_id_map);
+	idr_remove(&sriov->pv_id_table, pv_id);
+
+out:
+	list_del(&ent->list);
+	spin_unlock(&sriov->id_map_lock);
+	kfree(ent);
+}
+
+static void id_map_find_del(struct ib_device *ibdev, int pv_cm_id)
+{
+	struct mlx4_ib_sriov *sriov = &to_mdev(ibdev)->sriov;
+	struct rb_root *sl_id_map = &sriov->sl_id_map;
+	struct id_map_entry *ent, *found_ent;
+
+	spin_lock(&sriov->id_map_lock);
+	ent = (struct id_map_entry *)idr_find(&sriov->pv_id_table, pv_cm_id);
+	if (!ent)
+		goto out;
+	found_ent = id_map_find_by_sl_id(ibdev, ent->slave_id, ent->sl_cm_id);
+	if (found_ent && found_ent == ent)
+		rb_erase(&found_ent->node, sl_id_map);
+	idr_remove(&sriov->pv_id_table, pv_cm_id);
+out:
+	spin_unlock(&sriov->id_map_lock);
+}
+
+static void sl_id_map_add(struct ib_device *ibdev, struct id_map_entry *new)
+{
+	struct rb_root *sl_id_map = &to_mdev(ibdev)->sriov.sl_id_map;
+	struct rb_node **link = &sl_id_map->rb_node, *parent = NULL;
+	struct id_map_entry *ent;
+	int slave_id = new->slave_id;
+	int sl_cm_id = new->sl_cm_id;
+
+	ent = id_map_find_by_sl_id(ibdev, slave_id, sl_cm_id);
+	if (ent) {
+		pr_debug("overriding existing sl_id_map entry (cm_id = %x)\n",
+			 sl_cm_id);
+
+		rb_replace_node(&ent->node, &new->node, sl_id_map);
+		return;
+	}
+
+	/* Go to the bottom of the tree */
+	while (*link) {
+		parent = *link;
+		ent = rb_entry(parent, struct id_map_entry, node);
+
+		if (ent->sl_cm_id > sl_cm_id || (ent->sl_cm_id == sl_cm_id && ent->slave_id > slave_id))
+			link = &(*link)->rb_left;
+		else
+			link = &(*link)->rb_right;
+	}
+
+	rb_link_node(&new->node, parent, link);
+	rb_insert_color(&new->node, sl_id_map);
+}
+
+static struct id_map_entry *
+id_map_alloc(struct ib_device *ibdev, int slave_id, u32 sl_cm_id)
+{
+	int ret, id;
+	static int next_id;
+	struct id_map_entry *ent;
+	struct mlx4_ib_sriov *sriov = &to_mdev(ibdev)->sriov;
+
+	ent = kmalloc(sizeof (struct id_map_entry), GFP_KERNEL);
+	if (!ent) {
+		mlx4_ib_warn(ibdev, "Couldn't allocate id cache entry - out of memory\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	ent->sl_cm_id = sl_cm_id;
+	ent->slave_id = slave_id;
+	ent->scheduled_delete = 0;
+	ent->dev = to_mdev(ibdev);
+	INIT_DELAYED_WORK(&ent->timeout, id_map_ent_timeout);
+
+	do {
+		spin_lock(&to_mdev(ibdev)->sriov.id_map_lock);
+		ret = idr_get_new_above(&sriov->pv_id_table, ent,
+					next_id, &id);
+		if (!ret) {
+			next_id = ((unsigned) id + 1) & MAX_IDR_MASK;
+			ent->pv_cm_id = (u32)id;
+			sl_id_map_add(ibdev, ent);
+		}
+
+		spin_unlock(&sriov->id_map_lock);
+	} while (ret == -EAGAIN && idr_pre_get(&sriov->pv_id_table, GFP_KERNEL));
+	/*the function idr_get_new_above can return -ENOSPC, so don't insert in that case.*/
+	if (!ret) {
+		spin_lock(&sriov->id_map_lock);
+		list_add_tail(&ent->list, &sriov->cm_list);
+		spin_unlock(&sriov->id_map_lock);
+		return ent;
+	}
+	/*error flow*/
+	kfree(ent);
+	mlx4_ib_warn(ibdev, "No more space in the idr (err:0x%x)\n", ret);
+	return ERR_PTR(-ENOMEM);
+}
+
+static struct id_map_entry *
+id_map_get(struct ib_device *ibdev, int *pv_cm_id, int sl_cm_id, int slave_id)
+{
+	struct id_map_entry *ent;
+	struct mlx4_ib_sriov *sriov = &to_mdev(ibdev)->sriov;
+
+	spin_lock(&sriov->id_map_lock);
+	if (*pv_cm_id == -1) {
+		ent = id_map_find_by_sl_id(ibdev, sl_cm_id, slave_id);
+		if (ent)
+			*pv_cm_id = (int) ent->pv_cm_id;
+	} else
+		ent = (struct id_map_entry *)idr_find(&sriov->pv_id_table, *pv_cm_id);
+	spin_unlock(&sriov->id_map_lock);
+
+	return ent;
+}
+
+static void schedule_delayed(struct ib_device *ibdev, struct id_map_entry *id)
+{
+	struct mlx4_ib_sriov *sriov = &to_mdev(ibdev)->sriov;
+	unsigned long flags;
+
+	spin_lock_irqsave(&sriov->going_down_lock, flags);
+	spin_lock(&sriov->id_map_lock);
+	/*make sure that there is no schedule inside the scheduled work.*/
+	if (!sriov->is_going_down) {
+		id->scheduled_delete = 1;
+		schedule_delayed_work(&id->timeout, CM_CLEANUP_CACHE_TIMEOUT);
+	}
+	spin_unlock(&sriov->id_map_lock);
+	spin_unlock_irqrestore(&sriov->going_down_lock, flags);
+}
+
+int mlx4_ib_multiplex_cm_handler(struct ib_device *ibdev, int port, int slave_id,
+		struct ib_mad *mad)
+{
+	struct id_map_entry *id;
+	u32 sl_cm_id;
+	int pv_cm_id = -1;
+
+	sl_cm_id = get_local_comm_id(mad);
+
+	if (mad->mad_hdr.attr_id == CM_REQ_ATTR_ID ||
+			mad->mad_hdr.attr_id == CM_REP_ATTR_ID) {
+		id = id_map_alloc(ibdev, slave_id, sl_cm_id);
+		if (IS_ERR(id)) {
+			mlx4_ib_warn(ibdev, "%s: id{slave: %d, sl_cm_id: 0x%x} Failed to id_map_alloc\n",
+				__func__, slave_id, sl_cm_id);
+			return PTR_ERR(id);
+		}
+	} else if (mad->mad_hdr.attr_id == CM_REJ_ATTR_ID) {
+		return 0;
+	} else {
+		id = id_map_get(ibdev, &pv_cm_id, slave_id, sl_cm_id);
+	}
+
+	if (!id) {
+		pr_debug("id{slave: %d, sl_cm_id: 0x%x} is NULL!\n",
+			 slave_id, sl_cm_id);
+		return -EINVAL;
+	}
+
+	set_local_comm_id(mad, id->pv_cm_id);
+
+	if (mad->mad_hdr.attr_id == CM_DREQ_ATTR_ID)
+		schedule_delayed(ibdev, id);
+	else if (mad->mad_hdr.attr_id == CM_DREP_ATTR_ID)
+		id_map_find_del(ibdev, pv_cm_id);
+
+	return 0;
+}
+
+int mlx4_ib_demux_cm_handler(struct ib_device *ibdev, int port, int *slave,
+							     struct ib_mad *mad)
+{
+	u32 pv_cm_id;
+	struct id_map_entry *id;
+
+	if (mad->mad_hdr.attr_id == CM_REQ_ATTR_ID) {
+		union ib_gid gid;
+
+		gid = gid_from_req_msg(ibdev, mad);
+		*slave = mlx4_ib_find_real_gid(ibdev, port, gid.global.interface_id);
+		if (*slave < 0) {
+			mlx4_ib_warn(ibdev, "failed matching slave_id by gid (0x%llx)\n",
+					gid.global.interface_id);
+			return -ENOENT;
+		}
+		return 0;
+	}
+
+	pv_cm_id = get_remote_comm_id(mad);
+	id = id_map_get(ibdev, (int *)&pv_cm_id, -1, -1);
+
+	if (!id) {
+		pr_debug("Couldn't find an entry for pv_cm_id 0x%x\n", pv_cm_id);
+		return -ENOENT;
+	}
+
+	*slave = id->slave_id;
+	set_remote_comm_id(mad, id->sl_cm_id);
+
+	if (mad->mad_hdr.attr_id == CM_DREQ_ATTR_ID)
+		schedule_delayed(ibdev, id);
+	else if (mad->mad_hdr.attr_id == CM_REJ_ATTR_ID ||
+			mad->mad_hdr.attr_id == CM_DREP_ATTR_ID) {
+		id_map_find_del(ibdev, (int) pv_cm_id);
+	}
+
+	return 0;
+}
+
+void mlx4_ib_cm_paravirt_init(struct mlx4_ib_dev *dev)
+{
+	spin_lock_init(&dev->sriov.id_map_lock);
+	INIT_LIST_HEAD(&dev->sriov.cm_list);
+	dev->sriov.sl_id_map = RB_ROOT;
+	idr_init(&dev->sriov.pv_id_table);
+	idr_pre_get(&dev->sriov.pv_id_table, GFP_KERNEL);
+}
+
+/* slave = -1 ==> all slaves */
+/* TBD -- call paravirt clean for single slave.  Need for slave RESET event */
+void mlx4_ib_cm_paravirt_clean(struct mlx4_ib_dev *dev, int slave)
+{
+	struct mlx4_ib_sriov *sriov = &dev->sriov;
+	struct rb_root *sl_id_map = &sriov->sl_id_map;
+	struct list_head lh;
+	struct rb_node *nd;
+	int need_flush = 1;
+	struct id_map_entry *map, *tmp_map;
+	/* cancel all delayed work queue entries */
+	INIT_LIST_HEAD(&lh);
+	spin_lock(&sriov->id_map_lock);
+	list_for_each_entry_safe(map, tmp_map, &dev->sriov.cm_list, list) {
+		if (slave < 0 || slave == map->slave_id) {
+			if (map->scheduled_delete)
+				need_flush &= !!cancel_delayed_work(&map->timeout);
+		}
+	}
+
+	spin_unlock(&sriov->id_map_lock);
+
+	if (!need_flush)
+		flush_scheduled_work(); /* make sure all timers were flushed */
+
+	/* now, remove all leftover entries from databases*/
+	spin_lock(&sriov->id_map_lock);
+	if (slave < 0) {
+		while (rb_first(sl_id_map)) {
+			struct id_map_entry *ent =
+				rb_entry(rb_first(sl_id_map),
+					 struct id_map_entry, node);
+
+			rb_erase(&ent->node, sl_id_map);
+			idr_remove(&sriov->pv_id_table, (int) ent->pv_cm_id);
+		}
+		list_splice_init(&dev->sriov.cm_list, &lh);
+	} else {
+		/* first, move nodes belonging to slave to db remove list */
+		nd = rb_first(sl_id_map);
+		while (nd) {
+			struct id_map_entry *ent =
+				rb_entry(nd, struct id_map_entry, node);
+			nd = rb_next(nd);
+			if (ent->slave_id == slave)
+				list_move_tail(&ent->list, &lh);
+		}
+		/* remove those nodes from databases */
+		list_for_each_entry_safe(map, tmp_map, &lh, list) {
+			rb_erase(&map->node, sl_id_map);
+			idr_remove(&sriov->pv_id_table, (int) map->pv_cm_id);
+		}
+
+		/* add remaining nodes from cm_list */
+		list_for_each_entry_safe(map, tmp_map, &dev->sriov.cm_list, list) {
+			if (slave == map->slave_id)
+				list_move_tail(&map->list, &lh);
+		}
+	}
+
+	spin_unlock(&sriov->id_map_lock);
+
+	/* free any map entries left behind due to cancel_delayed_work above */
+	list_for_each_entry_safe(map, tmp_map, &lh, list) {
+		list_del(&map->list);
+		kfree(map);
+	}
+}
diff --git a/drivers/infiniband/hw/mlx4/cq.c b/drivers/infiniband/hw/mlx4/cq.c
index 6d4ef71c..c9eb6a6 100644
--- a/drivers/infiniband/hw/mlx4/cq.c
+++ b/drivers/infiniband/hw/mlx4/cq.c
@@ -547,6 +547,26 @@ static int mlx4_ib_ipoib_csum_ok(__be16 status, __be16 checksum)
 		checksum == cpu_to_be16(0xffff);
 }
 
+static int use_tunnel_data(struct mlx4_ib_qp *qp, struct mlx4_ib_cq *cq, struct ib_wc *wc,
+			   unsigned tail, struct mlx4_cqe *cqe)
+{
+	struct mlx4_ib_proxy_sqp_hdr *hdr;
+
+	ib_dma_sync_single_for_cpu(qp->ibqp.device,
+				   qp->sqp_proxy_rcv[tail].map,
+				   sizeof (struct mlx4_ib_proxy_sqp_hdr),
+				   DMA_FROM_DEVICE);
+	hdr = (struct mlx4_ib_proxy_sqp_hdr *) (qp->sqp_proxy_rcv[tail].addr);
+	wc->pkey_index	= be16_to_cpu(hdr->tun.pkey_index);
+	wc->slid	= be16_to_cpu(hdr->tun.slid_mac_47_32);
+	wc->sl		= (u8) (be16_to_cpu(hdr->tun.sl_vid) >> 12);
+	wc->src_qp	= be32_to_cpu(hdr->tun.flags_src_qp) & 0xFFFFFF;
+	wc->wc_flags   |= (hdr->tun.g_ml_path & 0x80) ? (IB_WC_GRH) : 0;
+	wc->dlid_path_bits = 0;
+
+	return 0;
+}
+
 static int mlx4_ib_poll_one(struct mlx4_ib_cq *cq,
 			    struct mlx4_ib_qp **cur_qp,
 			    struct ib_wc *wc)
@@ -559,6 +579,7 @@ static int mlx4_ib_poll_one(struct mlx4_ib_cq *cq,
 	int is_error;
 	u32 g_mlpath_rqpn;
 	u16 wqe_ctr;
+	unsigned tail = 0;
 
 repoll:
 	cqe = next_cqe_sw(cq);
@@ -634,7 +655,8 @@ repoll:
 		mlx4_ib_free_srq_wqe(srq, wqe_ctr);
 	} else {
 		wq	  = &(*cur_qp)->rq;
-		wc->wr_id = wq->wrid[wq->tail & (wq->wqe_cnt - 1)];
+		tail	  = wq->tail & (wq->wqe_cnt - 1);
+		wc->wr_id = wq->wrid[tail];
 		++wq->tail;
 	}
 
@@ -717,6 +739,13 @@ repoll:
 			break;
 		}
 
+		if (mlx4_is_mfunc(to_mdev(cq->ibcq.device)->dev)) {
+			if ((*cur_qp)->mlx4_ib_qp_type &
+			    (MLX4_IB_QPT_PROXY_SMI_OWNER |
+			     MLX4_IB_QPT_PROXY_SMI | MLX4_IB_QPT_PROXY_GSI))
+				return use_tunnel_data(*cur_qp, cq, wc, tail, cqe);
+		}
+
 		wc->slid	   = be16_to_cpu(cqe->rlid);
 		g_mlpath_rqpn	   = be32_to_cpu(cqe->g_mlpath_rqpn);
 		wc->src_qp	   = g_mlpath_rqpn & 0xffffff;
diff --git a/drivers/infiniband/hw/mlx4/mad.c b/drivers/infiniband/hw/mlx4/mad.c
index 9c2ae7e..21a7941 100644
--- a/drivers/infiniband/hw/mlx4/mad.c
+++ b/drivers/infiniband/hw/mlx4/mad.c
@@ -32,7 +32,10 @@
 
 #include <rdma/ib_mad.h>
 #include <rdma/ib_smi.h>
+#include <rdma/ib_sa.h>
+#include <rdma/ib_cache.h>
 
+#include <linux/random.h>
 #include <linux/mlx4/cmd.h>
 #include <linux/gfp.h>
 #include <rdma/ib_pma.h>
@@ -44,7 +47,62 @@ enum {
 	MLX4_IB_VENDOR_CLASS2 = 0xa
 };
 
-int mlx4_MAD_IFC(struct mlx4_ib_dev *dev, int ignore_mkey, int ignore_bkey,
+#define MLX4_TUN_SEND_WRID_SHIFT 34
+#define MLX4_TUN_QPN_SHIFT 32
+#define MLX4_TUN_WRID_RECV (((u64) 1) << MLX4_TUN_SEND_WRID_SHIFT)
+#define MLX4_TUN_SET_WRID_QPN(a) (((u64) ((a) & 0x3)) << MLX4_TUN_QPN_SHIFT)
+
+#define MLX4_TUN_IS_RECV(a)  (((a) >>  MLX4_TUN_SEND_WRID_SHIFT) & 0x1)
+#define MLX4_TUN_WRID_QPN(a) (((a) >> MLX4_TUN_QPN_SHIFT) & 0x3)
+
+ /* Port mgmt change event handling */
+
+#define GET_BLK_PTR_FROM_EQE(eqe) be32_to_cpu(eqe->event.port_mgmt_change.params.tbl_change_info.block_ptr)
+#define GET_MASK_FROM_EQE(eqe) be32_to_cpu(eqe->event.port_mgmt_change.params.tbl_change_info.tbl_entries_mask)
+#define NUM_IDX_IN_PKEY_TBL_BLK 32
+#define GUID_TBL_ENTRY_SIZE 8	   /* size in bytes */
+#define GUID_TBL_BLK_NUM_ENTRIES 8
+#define GUID_TBL_BLK_SIZE (GUID_TBL_ENTRY_SIZE * GUID_TBL_BLK_NUM_ENTRIES)
+
+struct mlx4_mad_rcv_buf {
+	struct ib_grh grh;
+	u8 payload[256];
+} __packed;
+
+struct mlx4_mad_snd_buf {
+	u8 payload[256];
+} __packed;
+
+struct mlx4_tunnel_mad {
+	struct ib_grh grh;
+	struct mlx4_ib_tunnel_header hdr;
+	struct ib_mad mad;
+} __packed;
+
+struct mlx4_rcv_tunnel_mad {
+	struct mlx4_rcv_tunnel_hdr hdr;
+	struct ib_grh grh;
+	struct ib_mad mad;
+} __packed;
+
+static void handle_client_rereg_event(struct mlx4_ib_dev *dev, u8 port_num);
+static void handle_lid_change_event(struct mlx4_ib_dev *dev, u8 port_num);
+static void __propagate_pkey_ev(struct mlx4_ib_dev *dev, int port_num,
+				int block, u32 change_bitmap);
+
+__be64 mlx4_ib_gen_node_guid(void)
+{
+#define NODE_GUID_HI	((u64) (((u64)IB_OPENIB_OUI) << 40))
+	return cpu_to_be64(NODE_GUID_HI | random32());
+}
+
+__be64 mlx4_ib_get_new_demux_tid(struct mlx4_ib_demux_ctx *ctx)
+{
+	return cpu_to_be64(atomic_inc_return(&ctx->tid)) |
+		cpu_to_be64(0xff00000000000000LL);
+}
+
+int mlx4_MAD_IFC(struct mlx4_ib_dev *dev, int mad_ifc_flags,
 		 int port, struct ib_wc *in_wc, struct ib_grh *in_grh,
 		 void *in_mad, void *response_mad)
 {
@@ -71,10 +129,13 @@ int mlx4_MAD_IFC(struct mlx4_ib_dev *dev, int ignore_mkey, int ignore_bkey,
 	 * Key check traps can't be generated unless we have in_wc to
 	 * tell us where to send the trap.
 	 */
-	if (ignore_mkey || !in_wc)
+	if ((mad_ifc_flags & MLX4_MAD_IFC_IGNORE_MKEY) || !in_wc)
 		op_modifier |= 0x1;
-	if (ignore_bkey || !in_wc)
+	if ((mad_ifc_flags & MLX4_MAD_IFC_IGNORE_BKEY) || !in_wc)
 		op_modifier |= 0x2;
+	if (mlx4_is_mfunc(dev->dev) &&
+	    (mad_ifc_flags & MLX4_MAD_IFC_NET_VIEW || in_wc))
+		op_modifier |= 0x8;
 
 	if (in_wc) {
 		struct {
@@ -107,10 +168,10 @@ int mlx4_MAD_IFC(struct mlx4_ib_dev *dev, int ignore_mkey, int ignore_bkey,
 		in_modifier |= in_wc->slid << 16;
 	}
 
-	err = mlx4_cmd_box(dev->dev, inmailbox->dma, outmailbox->dma,
-			   in_modifier, op_modifier,
+	err = mlx4_cmd_box(dev->dev, inmailbox->dma, outmailbox->dma, in_modifier,
+			   mlx4_is_master(dev->dev) ? (op_modifier & ~0x8) : op_modifier,
 			   MLX4_CMD_MAD_IFC, MLX4_CMD_TIME_CLASS_C,
-			   MLX4_CMD_NATIVE);
+			   (op_modifier & 0x8) ? MLX4_CMD_NATIVE : MLX4_CMD_WRAPPED);
 
 	if (!err)
 		memcpy(response_mad, outmailbox->buf, 256);
@@ -156,6 +217,10 @@ static void smp_snoop(struct ib_device *ibdev, u8 port_num, struct ib_mad *mad,
 {
 	struct ib_port_info *pinfo;
 	u16 lid;
+	__be16 *base;
+	u32 bn, pkey_change_bitmap;
+	int i;
+
 
 	struct mlx4_ib_dev *dev = to_mdev(ibdev);
 	if ((mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_LID_ROUTED ||
@@ -171,17 +236,46 @@ static void smp_snoop(struct ib_device *ibdev, u8 port_num, struct ib_mad *mad,
 				     pinfo->neighbormtu_mastersmsl & 0xf);
 
 			if (pinfo->clientrereg_resv_subnetto & 0x80)
-				mlx4_ib_dispatch_event(dev, port_num,
-						       IB_EVENT_CLIENT_REREGISTER);
+				handle_client_rereg_event(dev, port_num);
 
 			if (prev_lid != lid)
-				mlx4_ib_dispatch_event(dev, port_num,
-						       IB_EVENT_LID_CHANGE);
+				handle_lid_change_event(dev, port_num);
 			break;
 
 		case IB_SMP_ATTR_PKEY_TABLE:
-			mlx4_ib_dispatch_event(dev, port_num,
-					       IB_EVENT_PKEY_CHANGE);
+			if (!mlx4_is_mfunc(dev->dev)) {
+				mlx4_ib_dispatch_event(dev, port_num,
+						       IB_EVENT_PKEY_CHANGE);
+				break;
+			}
+
+			/* at this point, we are running in the master.
+			 * Slaves do not receive SMPs.
+			 */
+			bn  = be32_to_cpu(((struct ib_smp *)mad)->attr_mod) & 0xFFFF;
+			base = (__be16 *) &(((struct ib_smp *)mad)->data[0]);
+			pkey_change_bitmap = 0;
+			for (i = 0; i < 32; i++) {
+				pr_debug("PKEY[%d] = x%x\n",
+					 i + bn*32, be16_to_cpu(base[i]));
+				if (be16_to_cpu(base[i]) !=
+				    dev->pkeys.phys_pkey_cache[port_num - 1][i + bn*32]) {
+					pkey_change_bitmap |= (1 << i);
+					dev->pkeys.phys_pkey_cache[port_num - 1][i + bn*32] =
+						be16_to_cpu(base[i]);
+				}
+			}
+			pr_debug("PKEY Change event: port=%d, "
+				 "block=0x%x, change_bitmap=0x%x\n",
+				 port_num, bn, pkey_change_bitmap);
+
+			if (pkey_change_bitmap) {
+				mlx4_ib_dispatch_event(dev, port_num,
+						       IB_EVENT_PKEY_CHANGE);
+				if (!dev->sriov.is_going_down)
+					__propagate_pkey_ev(dev, port_num, bn,
+							    pkey_change_bitmap);
+			}
 			break;
 
 		case IB_SMP_ATTR_GUID_INFO:
@@ -189,12 +283,56 @@ static void smp_snoop(struct ib_device *ibdev, u8 port_num, struct ib_mad *mad,
 			if (!mlx4_is_master(dev->dev))
 				mlx4_ib_dispatch_event(dev, port_num,
 						       IB_EVENT_GID_CHANGE);
+			/*if master, notify relevant slaves*/
+			if (mlx4_is_master(dev->dev) &&
+			    !dev->sriov.is_going_down) {
+				bn = be32_to_cpu(((struct ib_smp *)mad)->attr_mod);
+				mlx4_ib_update_cache_on_guid_change(dev, bn, port_num,
+								    (u8 *)(&((struct ib_smp *)mad)->data));
+				mlx4_ib_notify_slaves_on_guid_change(dev, bn, port_num,
+								     (u8 *)(&((struct ib_smp *)mad)->data));
+			}
 			break;
+
 		default:
 			break;
 		}
 }
 
+static void __propagate_pkey_ev(struct mlx4_ib_dev *dev, int port_num,
+				int block, u32 change_bitmap)
+{
+	int i, ix, slave, err;
+	int have_event = 0;
+
+	for (slave = 0; slave < dev->dev->caps.sqp_demux; slave++) {
+		if (slave == mlx4_master_func_num(dev->dev))
+			continue;
+		if (!mlx4_is_slave_active(dev->dev, slave))
+			continue;
+
+		have_event = 0;
+		for (i = 0; i < 32; i++) {
+			if (!(change_bitmap & (1 << i)))
+				continue;
+			for (ix = 0;
+			     ix < dev->dev->caps.pkey_table_len[port_num]; ix++) {
+				if (dev->pkeys.virt2phys_pkey[slave][port_num - 1]
+				    [ix] == i + 32 * block) {
+					err = mlx4_gen_pkey_eqe(dev->dev, slave, port_num);
+					pr_debug("propagate_pkey_ev: slave %d,"
+						 " port %d, ix %d (%d)\n",
+						 slave, port_num, ix, err);
+					have_event = 1;
+					break;
+				}
+			}
+			if (have_event)
+				break;
+		}
+	}
+}
+
 static void node_desc_override(struct ib_device *dev,
 			       struct ib_mad *mad)
 {
@@ -242,6 +380,268 @@ static void forward_trap(struct mlx4_ib_dev *dev, u8 port_num, struct ib_mad *ma
 	}
 }
 
+static int mlx4_ib_demux_sa_handler(struct ib_device *ibdev, int port, int slave,
+							     struct ib_sa_mad *sa_mad)
+{
+	int ret = 0;
+
+	/* dispatch to different sa handlers */
+	switch (be16_to_cpu(sa_mad->mad_hdr.attr_id)) {
+	case IB_SA_ATTR_MC_MEMBER_REC:
+		ret = mlx4_ib_mcg_demux_handler(ibdev, port, slave, sa_mad);
+		break;
+	default:
+		break;
+	}
+	return ret;
+}
+
+int mlx4_ib_find_real_gid(struct ib_device *ibdev, u8 port, __be64 guid)
+{
+	struct mlx4_ib_dev *dev = to_mdev(ibdev);
+	int i;
+
+	for (i = 0; i < dev->dev->caps.sqp_demux; i++) {
+		if (dev->sriov.demux[port - 1].guid_cache[i] == guid)
+			return i;
+	}
+	return -1;
+}
+
+
+static int get_pkey_phys_indices(struct mlx4_ib_dev *ibdev, u8 port, u8 ph_pkey_ix,
+				 u8 *full_pk_ix, u8 *partial_pk_ix,
+				 int *is_full_member)
+{
+	u16 search_pkey;
+	int fm;
+	int err = 0;
+	u16 pk;
+
+	err = ib_get_cached_pkey(&ibdev->ib_dev, port, ph_pkey_ix, &search_pkey);
+	if (err)
+		return err;
+
+	fm = (search_pkey & 0x8000) ? 1 : 0;
+	if (fm) {
+		*full_pk_ix = ph_pkey_ix;
+		search_pkey &= 0x7FFF;
+	} else {
+		*partial_pk_ix = ph_pkey_ix;
+		search_pkey |= 0x8000;
+	}
+
+	if (ib_find_exact_cached_pkey(&ibdev->ib_dev, port, search_pkey, &pk))
+		pk = 0xFFFF;
+
+	if (fm)
+		*partial_pk_ix = (pk & 0xFF);
+	else
+		*full_pk_ix = (pk & 0xFF);
+
+	*is_full_member = fm;
+	return err;
+}
+
+int mlx4_ib_send_to_slave(struct mlx4_ib_dev *dev, int slave, u8 port,
+			  enum ib_qp_type dest_qpt, struct ib_wc *wc,
+			  struct ib_grh *grh, struct ib_mad *mad)
+{
+	struct ib_sge list;
+	struct ib_send_wr wr, *bad_wr;
+	struct mlx4_ib_demux_pv_ctx *tun_ctx;
+	struct mlx4_ib_demux_pv_qp *tun_qp;
+	struct mlx4_rcv_tunnel_mad *tun_mad;
+	struct ib_ah_attr attr;
+	struct ib_ah *ah;
+	struct ib_qp *src_qp = NULL;
+	unsigned tun_tx_ix = 0;
+	int dqpn;
+	int ret = 0;
+	int i;
+	int is_full_member = 0;
+	u16 tun_pkey_ix;
+	u8 ph_pkey_ix, full_pk_ix = 0, partial_pk_ix = 0;
+
+	if (dest_qpt > IB_QPT_GSI)
+		return -EINVAL;
+
+	tun_ctx = dev->sriov.demux[port-1].tun[slave];
+
+	/* check if proxy qp created */
+	if (!tun_ctx || tun_ctx->state != DEMUX_PV_STATE_ACTIVE)
+		return -EAGAIN;
+
+	/* QP0 forwarding only for Dom0 */
+	if (!dest_qpt && (mlx4_master_func_num(dev->dev) != slave))
+		return -EINVAL;
+
+	if (!dest_qpt)
+		tun_qp = &tun_ctx->qp[0];
+	else
+		tun_qp = &tun_ctx->qp[1];
+
+	/* compute pkey index for slave */
+	/* get physical pkey -- virtualized Dom0 pkey to phys*/
+	if (dest_qpt) {
+		ph_pkey_ix =
+			dev->pkeys.virt2phys_pkey[mlx4_master_func_num(dev->dev)][port - 1][wc->pkey_index];
+
+		/* now, translate this to the slave pkey index */
+		ret = get_pkey_phys_indices(dev, port, ph_pkey_ix, &full_pk_ix,
+					    &partial_pk_ix, &is_full_member);
+		if (ret)
+			return -EINVAL;
+
+		for (i = 0; i < dev->dev->caps.pkey_table_len[port]; i++) {
+			if ((dev->pkeys.virt2phys_pkey[slave][port - 1][i] == full_pk_ix) ||
+			    (is_full_member &&
+			     (dev->pkeys.virt2phys_pkey[slave][port - 1][i] == partial_pk_ix)))
+				break;
+		}
+		if (i == dev->dev->caps.pkey_table_len[port])
+			return -EINVAL;
+		tun_pkey_ix = i;
+	} else
+		tun_pkey_ix = dev->pkeys.virt2phys_pkey[slave][port - 1][0];
+
+	dqpn = dev->dev->phys_caps.base_proxy_sqpn + 8 * slave + port + (dest_qpt * 2) - 1;
+
+	/* get tunnel tx data buf for slave */
+	src_qp = tun_qp->qp;
+
+	/* create ah. Just need an empty one with the port num for the post send.
+	 * The driver will set the force loopback bit in post_send */
+	memset(&attr, 0, sizeof attr);
+	attr.port_num = port;
+	ah = ib_create_ah(tun_ctx->pd, &attr);
+	if (IS_ERR(ah))
+		return -ENOMEM;
+
+	/* allocate tunnel tx buf after pass failure returns */
+	spin_lock(&tun_qp->tx_lock);
+	if (tun_qp->tx_ix_head - tun_qp->tx_ix_tail >=
+	    (MLX4_NUM_TUNNEL_BUFS - 1))
+		ret = -EAGAIN;
+	else
+		tun_tx_ix = (++tun_qp->tx_ix_head) & (MLX4_NUM_TUNNEL_BUFS - 1);
+	spin_unlock(&tun_qp->tx_lock);
+	if (ret)
+		goto out;
+
+	tun_mad = (struct mlx4_rcv_tunnel_mad *) (tun_qp->tx_ring[tun_tx_ix].buf.addr);
+	if (tun_qp->tx_ring[tun_tx_ix].ah)
+		ib_destroy_ah(tun_qp->tx_ring[tun_tx_ix].ah);
+	tun_qp->tx_ring[tun_tx_ix].ah = ah;
+	ib_dma_sync_single_for_cpu(&dev->ib_dev,
+				   tun_qp->tx_ring[tun_tx_ix].buf.map,
+				   sizeof (struct mlx4_rcv_tunnel_mad),
+				   DMA_TO_DEVICE);
+
+	/* copy over to tunnel buffer */
+	if (grh)
+		memcpy(&tun_mad->grh, grh, sizeof *grh);
+	memcpy(&tun_mad->mad, mad, sizeof *mad);
+
+	/* adjust tunnel data */
+	tun_mad->hdr.pkey_index = cpu_to_be16(tun_pkey_ix);
+	tun_mad->hdr.sl_vid = cpu_to_be16(((u16)(wc->sl)) << 12);
+	tun_mad->hdr.slid_mac_47_32 = cpu_to_be16(wc->slid);
+	tun_mad->hdr.flags_src_qp = cpu_to_be32(wc->src_qp & 0xFFFFFF);
+	tun_mad->hdr.g_ml_path = (grh && (wc->wc_flags & IB_WC_GRH)) ? 0x80 : 0;
+
+	ib_dma_sync_single_for_device(&dev->ib_dev,
+				      tun_qp->tx_ring[tun_tx_ix].buf.map,
+				      sizeof (struct mlx4_rcv_tunnel_mad),
+				      DMA_TO_DEVICE);
+
+	list.addr = tun_qp->tx_ring[tun_tx_ix].buf.map;
+	list.length = sizeof (struct mlx4_rcv_tunnel_mad);
+	list.lkey = tun_ctx->mr->lkey;
+
+	wr.wr.ud.ah = ah;
+	wr.wr.ud.port_num = port;
+	wr.wr.ud.remote_qkey = IB_QP_SET_QKEY;
+	wr.wr.ud.remote_qpn = dqpn;
+	wr.next = NULL;
+	wr.wr_id = ((u64) tun_tx_ix) | MLX4_TUN_SET_WRID_QPN(dest_qpt);
+	wr.sg_list = &list;
+	wr.num_sge = 1;
+	wr.opcode = IB_WR_SEND;
+	wr.send_flags = IB_SEND_SIGNALED;
+
+	ret = ib_post_send(src_qp, &wr, &bad_wr);
+out:
+	if (ret)
+		ib_destroy_ah(ah);
+	return ret;
+}
+
+static int mlx4_ib_demux_mad(struct ib_device *ibdev, u8 port,
+			struct ib_wc *wc, struct ib_grh *grh,
+			struct ib_mad *mad)
+{
+	struct mlx4_ib_dev *dev = to_mdev(ibdev);
+	int err;
+	int slave;
+	u8 *slave_id;
+
+	/* Initially assume that this mad is for us */
+	slave = mlx4_master_func_num(dev->dev);
+
+	/* See if the slave id is encoded in a response mad */
+	if (mad->mad_hdr.method & 0x80) {
+		slave_id = (u8 *) &mad->mad_hdr.tid;
+		slave = *slave_id;
+		if (slave != 255) /*255 indicates the dom0*/
+			*slave_id = 0; /* remap tid */
+	}
+
+	/* If a grh is present, we demux according to it */
+	if (wc->wc_flags & IB_WC_GRH) {
+		slave = mlx4_ib_find_real_gid(ibdev, port, grh->dgid.global.interface_id);
+		if (slave < 0) {
+			mlx4_ib_warn(ibdev, "failed matching grh\n");
+			return -ENOENT;
+		}
+	}
+	/* Class-specific handling */
+	switch (mad->mad_hdr.mgmt_class) {
+	case IB_MGMT_CLASS_SUBN_ADM:
+		if (mlx4_ib_demux_sa_handler(ibdev, port, slave,
+					     (struct ib_sa_mad *) mad))
+			return 0;
+		break;
+	case IB_MGMT_CLASS_CM:
+		if (mlx4_ib_demux_cm_handler(ibdev, port, &slave, mad))
+			return 0;
+		break;
+	case IB_MGMT_CLASS_DEVICE_MGMT:
+		if (mad->mad_hdr.method != IB_MGMT_METHOD_GET_RESP)
+			return 0;
+		break;
+	default:
+		/* Drop unsupported classes for slaves in tunnel mode */
+		if (slave != mlx4_master_func_num(dev->dev)) {
+			pr_debug("dropping unsupported ingress mad from class:%d "
+				 "for slave:%d\n", mad->mad_hdr.mgmt_class, slave);
+			return 0;
+		}
+	}
+	/*make sure that no slave==255 was not handled yet.*/
+	if (slave >= dev->dev->caps.sqp_demux) {
+		mlx4_ib_warn(ibdev, "slave id: %d is bigger than allowed:%d\n",
+			     slave, dev->dev->caps.sqp_demux);
+		return -ENOENT;
+	}
+
+	err = mlx4_ib_send_to_slave(dev, slave, port, wc->qp->qp_type, wc, grh, mad);
+	if (err)
+		pr_debug("failed sending to slave %d via tunnel qp (%d)\n",
+			 slave, err);
+	return 0;
+}
+
 static int ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
 			struct ib_wc *in_wc, struct ib_grh *in_grh,
 			struct ib_mad *in_mad, struct ib_mad *out_mad)
@@ -306,8 +706,9 @@ static int ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
 		prev_lid = pattr.lid;
 
 	err = mlx4_MAD_IFC(to_mdev(ibdev),
-			   mad_flags & IB_MAD_IGNORE_MKEY,
-			   mad_flags & IB_MAD_IGNORE_BKEY,
+			   (mad_flags & IB_MAD_IGNORE_MKEY ? MLX4_MAD_IFC_IGNORE_MKEY : 0) |
+			   (mad_flags & IB_MAD_IGNORE_BKEY ? MLX4_MAD_IFC_IGNORE_BKEY : 0) |
+			   MLX4_MAD_IFC_NET_VIEW,
 			   port_num, in_wc, in_grh, in_mad, out_mad);
 	if (err)
 		return IB_MAD_RESULT_FAILURE;
@@ -315,7 +716,9 @@ static int ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
 	if (!out_mad->mad_hdr.status) {
 		if (!(to_mdev(ibdev)->dev->caps.flags & MLX4_DEV_CAP_FLAG_PORT_MNG_CHG_EV))
 			smp_snoop(ibdev, port_num, in_mad, prev_lid);
-		node_desc_override(ibdev, out_mad);
+		/* slaves get node desc from FW */
+		if (!mlx4_is_slave(to_mdev(ibdev)->dev))
+			node_desc_override(ibdev, out_mad);
 	}
 
 	/* set return bit in status of directed route responses */
@@ -398,6 +801,8 @@ int mlx4_ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
 static void send_handler(struct ib_mad_agent *agent,
 			 struct ib_mad_send_wc *mad_send_wc)
 {
+	if (mad_send_wc->send_buf->context[0])
+		ib_destroy_ah(mad_send_wc->send_buf->context[0]);
 	ib_free_send_mad(mad_send_wc->send_buf);
 }
 
@@ -456,6 +861,90 @@ void mlx4_ib_mad_cleanup(struct mlx4_ib_dev *dev)
 	}
 }
 
+static void handle_lid_change_event(struct mlx4_ib_dev *dev, u8 port_num)
+{
+	mlx4_ib_dispatch_event(dev, port_num, IB_EVENT_LID_CHANGE);
+
+	if (mlx4_is_master(dev->dev) && !dev->sriov.is_going_down)
+		mlx4_gen_slaves_port_mgt_ev(dev->dev, port_num,
+					    MLX4_EQ_PORT_INFO_LID_CHANGE_MASK);
+}
+
+static void handle_client_rereg_event(struct mlx4_ib_dev *dev, u8 port_num)
+{
+	/* re-configure the alias-guid and mcg's */
+	if (mlx4_is_master(dev->dev)) {
+		mlx4_ib_invalidate_all_guid_record(dev, port_num);
+
+		if (!dev->sriov.is_going_down) {
+			mlx4_ib_mcg_port_cleanup(&dev->sriov.demux[port_num - 1], 0);
+			mlx4_gen_slaves_port_mgt_ev(dev->dev, port_num,
+						    MLX4_EQ_PORT_INFO_CLIENT_REREG_MASK);
+		}
+	}
+	mlx4_ib_dispatch_event(dev, port_num, IB_EVENT_CLIENT_REREGISTER);
+}
+
+static void propagate_pkey_ev(struct mlx4_ib_dev *dev, int port_num,
+			      struct mlx4_eqe *eqe)
+{
+	__propagate_pkey_ev(dev, port_num, GET_BLK_PTR_FROM_EQE(eqe),
+			    GET_MASK_FROM_EQE(eqe));
+}
+
+static void handle_slaves_guid_change(struct mlx4_ib_dev *dev, u8 port_num,
+				      u32 guid_tbl_blk_num, u32 change_bitmap)
+{
+	struct ib_smp *in_mad  = NULL;
+	struct ib_smp *out_mad  = NULL;
+	u16 i;
+
+	if (!mlx4_is_mfunc(dev->dev) || !mlx4_is_master(dev->dev))
+		return;
+
+	in_mad  = kmalloc(sizeof *in_mad, GFP_KERNEL);
+	out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL);
+	if (!in_mad || !out_mad) {
+		mlx4_ib_warn(&dev->ib_dev, "failed to allocate memory for guid info mads\n");
+		goto out;
+	}
+
+	guid_tbl_blk_num  *= 4;
+
+	for (i = 0; i < 4; i++) {
+		if (change_bitmap && (!((change_bitmap >> (8 * i)) & 0xff)))
+			continue;
+		memset(in_mad, 0, sizeof *in_mad);
+		memset(out_mad, 0, sizeof *out_mad);
+
+		in_mad->base_version  = 1;
+		in_mad->mgmt_class    = IB_MGMT_CLASS_SUBN_LID_ROUTED;
+		in_mad->class_version = 1;
+		in_mad->method        = IB_MGMT_METHOD_GET;
+		in_mad->attr_id       = IB_SMP_ATTR_GUID_INFO;
+		in_mad->attr_mod      = cpu_to_be32(guid_tbl_blk_num + i);
+
+		if (mlx4_MAD_IFC(dev,
+				 MLX4_MAD_IFC_IGNORE_KEYS | MLX4_MAD_IFC_NET_VIEW,
+				 port_num, NULL, NULL, in_mad, out_mad)) {
+			mlx4_ib_warn(&dev->ib_dev, "Failed in get GUID INFO MAD_IFC\n");
+			goto out;
+		}
+
+		mlx4_ib_update_cache_on_guid_change(dev, guid_tbl_blk_num + i,
+						    port_num,
+						    (u8 *)(&((struct ib_smp *)out_mad)->data));
+		mlx4_ib_notify_slaves_on_guid_change(dev, guid_tbl_blk_num + i,
+						     port_num,
+						     (u8 *)(&((struct ib_smp *)out_mad)->data));
+	}
+
+out:
+	kfree(in_mad);
+	kfree(out_mad);
+	return;
+}
+
 void handle_port_mgmt_change_event(struct work_struct *work)
 {
 	struct ib_event_work *ew = container_of(work, struct ib_event_work, work);
@@ -463,6 +952,8 @@ void handle_port_mgmt_change_event(struct work_struct *work)
 	struct mlx4_eqe *eqe = &(ew->ib_eqe);
 	u8 port = eqe->event.port_mgmt_change.port;
 	u32 changed_attr;
+	u32 tbl_block;
+	u32 change_bitmap;
 
 	switch (eqe->subtype) {
 	case MLX4_DEV_PMC_SUBTYPE_PORT_INFO:
@@ -478,24 +969,36 @@ void handle_port_mgmt_change_event(struct work_struct *work)
 
 		/* Check if it is a lid change event */
 		if (changed_attr & MLX4_EQ_PORT_INFO_LID_CHANGE_MASK)
-			mlx4_ib_dispatch_event(dev, port, IB_EVENT_LID_CHANGE);
+			handle_lid_change_event(dev, port);
 
 		/* Generate GUID changed event */
-		if (changed_attr & MLX4_EQ_PORT_INFO_GID_PFX_CHANGE_MASK)
+		if (changed_attr & MLX4_EQ_PORT_INFO_GID_PFX_CHANGE_MASK) {
 			mlx4_ib_dispatch_event(dev, port, IB_EVENT_GID_CHANGE);
+			/*if master, notify all slaves*/
+			if (mlx4_is_master(dev->dev))
+				mlx4_gen_slaves_port_mgt_ev(dev->dev, port,
+							    MLX4_EQ_PORT_INFO_GID_PFX_CHANGE_MASK);
+		}
 
 		if (changed_attr & MLX4_EQ_PORT_INFO_CLIENT_REREG_MASK)
-			mlx4_ib_dispatch_event(dev, port,
-					       IB_EVENT_CLIENT_REREGISTER);
+			handle_client_rereg_event(dev, port);
 		break;
 
 	case MLX4_DEV_PMC_SUBTYPE_PKEY_TABLE:
 		mlx4_ib_dispatch_event(dev, port, IB_EVENT_PKEY_CHANGE);
+		if (mlx4_is_master(dev->dev) && !dev->sriov.is_going_down)
+			propagate_pkey_ev(dev, port, eqe);
 		break;
 	case MLX4_DEV_PMC_SUBTYPE_GUID_INFO:
 		/* paravirtualized master's guid is guid 0 -- does not change */
 		if (!mlx4_is_master(dev->dev))
 			mlx4_ib_dispatch_event(dev, port, IB_EVENT_GID_CHANGE);
+		/*if master, notify relevant slaves*/
+		else if (!dev->sriov.is_going_down) {
+			tbl_block = GET_BLK_PTR_FROM_EQE(eqe);
+			change_bitmap = GET_MASK_FROM_EQE(eqe);
+			handle_slaves_guid_change(dev, port, tbl_block, change_bitmap);
+		}
 		break;
 	default:
 		pr_warn("Unsupported subtype 0x%x for "
@@ -516,3 +1019,1035 @@ void mlx4_ib_dispatch_event(struct mlx4_ib_dev *dev, u8 port_num,
 
 	ib_dispatch_event(&event);
 }
+
+static void mlx4_ib_tunnel_comp_handler(struct ib_cq *cq, void *arg)
+{
+	unsigned long flags;
+	struct mlx4_ib_demux_pv_ctx *ctx = cq->cq_context;
+	struct mlx4_ib_dev *dev = to_mdev(ctx->ib_dev);
+	spin_lock_irqsave(&dev->sriov.going_down_lock, flags);
+	if (!dev->sriov.is_going_down && ctx->state == DEMUX_PV_STATE_ACTIVE)
+		queue_work(ctx->wq, &ctx->work);
+	spin_unlock_irqrestore(&dev->sriov.going_down_lock, flags);
+}
+
+static int mlx4_ib_post_pv_qp_buf(struct mlx4_ib_demux_pv_ctx *ctx,
+				  struct mlx4_ib_demux_pv_qp *tun_qp,
+				  int index)
+{
+	struct ib_sge sg_list;
+	struct ib_recv_wr recv_wr, *bad_recv_wr;
+	int size;
+
+	size = (tun_qp->qp->qp_type == IB_QPT_UD) ?
+		sizeof (struct mlx4_tunnel_mad) : sizeof (struct mlx4_mad_rcv_buf);
+
+	sg_list.addr = tun_qp->ring[index].map;
+	sg_list.length = size;
+	sg_list.lkey = ctx->mr->lkey;
+
+	recv_wr.next = NULL;
+	recv_wr.sg_list = &sg_list;
+	recv_wr.num_sge = 1;
+	recv_wr.wr_id = (u64) index | MLX4_TUN_WRID_RECV |
+		MLX4_TUN_SET_WRID_QPN(tun_qp->proxy_qpt);
+	ib_dma_sync_single_for_device(ctx->ib_dev, tun_qp->ring[index].map,
+				      size, DMA_FROM_DEVICE);
+	return ib_post_recv(tun_qp->qp, &recv_wr, &bad_recv_wr);
+}
+
+static int mlx4_ib_multiplex_sa_handler(struct ib_device *ibdev, int port,
+		int slave, struct ib_sa_mad *sa_mad)
+{
+	int ret = 0;
+
+	/* dispatch to different sa handlers */
+	switch (be16_to_cpu(sa_mad->mad_hdr.attr_id)) {
+	case IB_SA_ATTR_MC_MEMBER_REC:
+		ret = mlx4_ib_mcg_multiplex_handler(ibdev, port, slave, sa_mad);
+		break;
+	default:
+		break;
+	}
+	return ret;
+}
+
+static int is_proxy_qp0(struct mlx4_ib_dev *dev, int qpn, int slave)
+{
+	int proxy_start = dev->dev->phys_caps.base_proxy_sqpn + 8 * slave;
+
+	return (qpn >= proxy_start && qpn <= proxy_start + 1);
+}
+
+
+int mlx4_ib_send_to_wire(struct mlx4_ib_dev *dev, int slave, u8 port,
+			 enum ib_qp_type dest_qpt, u16 pkey_index, u32 remote_qpn,
+			 u32 qkey, struct ib_ah_attr *attr, struct ib_mad *mad)
+{
+	struct ib_sge list;
+	struct ib_send_wr wr, *bad_wr;
+	struct mlx4_ib_demux_pv_ctx *sqp_ctx;
+	struct mlx4_ib_demux_pv_qp *sqp;
+	struct mlx4_mad_snd_buf *sqp_mad;
+	struct ib_ah *ah;
+	struct ib_qp *send_qp = NULL;
+	unsigned wire_tx_ix = 0;
+	int ret = 0;
+	u16 wire_pkey_ix;
+	int src_qpnum;
+	u8 sgid_index;
+
+
+	sqp_ctx = dev->sriov.sqps[port-1];
+
+	/* check if proxy qp created */
+	if (!sqp_ctx || sqp_ctx->state != DEMUX_PV_STATE_ACTIVE)
+		return -EAGAIN;
+
+	/* QP0 forwarding only for Dom0 */
+	if (dest_qpt == IB_QPT_SMI && (mlx4_master_func_num(dev->dev) != slave))
+		return -EINVAL;
+
+	if (dest_qpt == IB_QPT_SMI) {
+		src_qpnum = 0;
+		sqp = &sqp_ctx->qp[0];
+		wire_pkey_ix = dev->pkeys.virt2phys_pkey[slave][port - 1][0];
+	} else {
+		src_qpnum = 1;
+		sqp = &sqp_ctx->qp[1];
+		wire_pkey_ix = dev->pkeys.virt2phys_pkey[slave][port - 1][pkey_index];
+	}
+
+	send_qp = sqp->qp;
+
+	/* create ah */
+	sgid_index = attr->grh.sgid_index;
+	attr->grh.sgid_index = 0;
+	ah = ib_create_ah(sqp_ctx->pd, attr);
+	if (IS_ERR(ah))
+		return -ENOMEM;
+	attr->grh.sgid_index = sgid_index;
+	to_mah(ah)->av.ib.gid_index = sgid_index;
+	/* get rid of force-loopback bit */
+	to_mah(ah)->av.ib.port_pd &= cpu_to_be32(0x7FFFFFFF);
+	spin_lock(&sqp->tx_lock);
+	if (sqp->tx_ix_head - sqp->tx_ix_tail >=
+	    (MLX4_NUM_TUNNEL_BUFS - 1))
+		ret = -EAGAIN;
+	else
+		wire_tx_ix = (++sqp->tx_ix_head) & (MLX4_NUM_TUNNEL_BUFS - 1);
+	spin_unlock(&sqp->tx_lock);
+	if (ret)
+		goto out;
+
+	sqp_mad = (struct mlx4_mad_snd_buf *) (sqp->tx_ring[wire_tx_ix].buf.addr);
+	if (sqp->tx_ring[wire_tx_ix].ah)
+		ib_destroy_ah(sqp->tx_ring[wire_tx_ix].ah);
+	sqp->tx_ring[wire_tx_ix].ah = ah;
+	ib_dma_sync_single_for_cpu(&dev->ib_dev,
+				   sqp->tx_ring[wire_tx_ix].buf.map,
+				   sizeof (struct mlx4_mad_snd_buf),
+				   DMA_TO_DEVICE);
+
+	memcpy(&sqp_mad->payload, mad, sizeof *mad);
+
+	ib_dma_sync_single_for_device(&dev->ib_dev,
+				      sqp->tx_ring[wire_tx_ix].buf.map,
+				      sizeof (struct mlx4_mad_snd_buf),
+				      DMA_TO_DEVICE);
+
+	list.addr = sqp->tx_ring[wire_tx_ix].buf.map;
+	list.length = sizeof (struct mlx4_mad_snd_buf);
+	list.lkey = sqp_ctx->mr->lkey;
+
+	wr.wr.ud.ah = ah;
+	wr.wr.ud.port_num = port;
+	wr.wr.ud.pkey_index = wire_pkey_ix;
+	wr.wr.ud.remote_qkey = qkey;
+	wr.wr.ud.remote_qpn = remote_qpn;
+	wr.next = NULL;
+	wr.wr_id = ((u64) wire_tx_ix) | MLX4_TUN_SET_WRID_QPN(src_qpnum);
+	wr.sg_list = &list;
+	wr.num_sge = 1;
+	wr.opcode = IB_WR_SEND;
+	wr.send_flags = IB_SEND_SIGNALED;
+
+	ret = ib_post_send(send_qp, &wr, &bad_wr);
+out:
+	if (ret)
+		ib_destroy_ah(ah);
+	return ret;
+}
+
+static void mlx4_ib_multiplex_mad(struct mlx4_ib_demux_pv_ctx *ctx, struct ib_wc *wc)
+{
+	struct mlx4_ib_dev *dev = to_mdev(ctx->ib_dev);
+	struct mlx4_ib_demux_pv_qp *tun_qp = &ctx->qp[MLX4_TUN_WRID_QPN(wc->wr_id)];
+	int wr_ix = wc->wr_id & (MLX4_NUM_TUNNEL_BUFS - 1);
+	struct mlx4_tunnel_mad *tunnel = tun_qp->ring[wr_ix].addr;
+	struct mlx4_ib_ah ah;
+	struct ib_ah_attr ah_attr;
+	u8 *slave_id;
+	int slave;
+
+	/* Get slave that sent this packet */
+	if (wc->src_qp < dev->dev->phys_caps.base_proxy_sqpn ||
+	    wc->src_qp >= dev->dev->phys_caps.base_proxy_sqpn + 8 * MLX4_MFUNC_MAX ||
+	    (wc->src_qp & 0x1) != ctx->port - 1 ||
+	    wc->src_qp & 0x4) {
+		mlx4_ib_warn(ctx->ib_dev, "can't multiplex bad sqp:%d\n", wc->src_qp);
+		return;
+	}
+	slave = ((wc->src_qp & ~0x7) - dev->dev->phys_caps.base_proxy_sqpn) / 8;
+	if (slave != ctx->slave) {
+		mlx4_ib_warn(ctx->ib_dev, "can't multiplex bad sqp:%d: "
+			     "belongs to another slave\n", wc->src_qp);
+		return;
+	}
+	if (slave != mlx4_master_func_num(dev->dev) && !(wc->src_qp & 0x2)) {
+		mlx4_ib_warn(ctx->ib_dev, "can't multiplex bad sqp:%d: "
+			     "non-master trying to send QP0 packets\n", wc->src_qp);
+		return;
+	}
+
+	/* Map transaction ID */
+	ib_dma_sync_single_for_cpu(ctx->ib_dev, tun_qp->ring[wr_ix].map,
+				   sizeof (struct mlx4_tunnel_mad),
+				   DMA_FROM_DEVICE);
+	switch (tunnel->mad.mad_hdr.method) {
+	case IB_MGMT_METHOD_SET:
+	case IB_MGMT_METHOD_GET:
+	case IB_MGMT_METHOD_REPORT:
+	case IB_SA_METHOD_GET_TABLE:
+	case IB_SA_METHOD_DELETE:
+	case IB_SA_METHOD_GET_MULTI:
+	case IB_SA_METHOD_GET_TRACE_TBL:
+		slave_id = (u8 *) &tunnel->mad.mad_hdr.tid;
+		if (*slave_id) {
+			mlx4_ib_warn(ctx->ib_dev, "egress mad has non-null tid msb:%d "
+				     "class:%d slave:%d\n", *slave_id,
+				     tunnel->mad.mad_hdr.mgmt_class, slave);
+			return;
+		} else
+			*slave_id = slave;
+	default:
+		/* nothing */;
+	}
+
+	/* Class-specific handling */
+	switch (tunnel->mad.mad_hdr.mgmt_class) {
+	case IB_MGMT_CLASS_SUBN_ADM:
+		if (mlx4_ib_multiplex_sa_handler(ctx->ib_dev, ctx->port, slave,
+			      (struct ib_sa_mad *) &tunnel->mad))
+			return;
+		break;
+	case IB_MGMT_CLASS_CM:
+		if (mlx4_ib_multiplex_cm_handler(ctx->ib_dev, ctx->port, slave,
+			      (struct ib_mad *) &tunnel->mad))
+			return;
+		break;
+	case IB_MGMT_CLASS_DEVICE_MGMT:
+		if (tunnel->mad.mad_hdr.method != IB_MGMT_METHOD_GET &&
+		    tunnel->mad.mad_hdr.method != IB_MGMT_METHOD_SET)
+			return;
+		break;
+	default:
+		/* Drop unsupported classes for slaves in tunnel mode */
+		if (slave != mlx4_master_func_num(dev->dev)) {
+			mlx4_ib_warn(ctx->ib_dev, "dropping unsupported egress mad from class:%d "
+				     "for slave:%d\n", tunnel->mad.mad_hdr.mgmt_class, slave);
+			return;
+		}
+	}
+
+	/* We are using standard ib_core services to send the mad, so generate a
+	 * stadard address handle by decoding the tunnelled mlx4_ah fields */
+	memcpy(&ah.av, &tunnel->hdr.av, sizeof (struct mlx4_av));
+	ah.ibah.device = ctx->ib_dev;
+	mlx4_ib_query_ah(&ah.ibah, &ah_attr);
+	if ((ah_attr.ah_flags & IB_AH_GRH) &&
+	    (ah_attr.grh.sgid_index != slave)) {
+		mlx4_ib_warn(ctx->ib_dev, "slave:%d accessed invalid sgid_index:%d\n",
+			     slave, ah_attr.grh.sgid_index);
+		return;
+	}
+
+	mlx4_ib_send_to_wire(dev, slave, ctx->port,
+			     is_proxy_qp0(dev, wc->src_qp, slave) ?
+			     IB_QPT_SMI : IB_QPT_GSI,
+			     be16_to_cpu(tunnel->hdr.pkey_index),
+			     be32_to_cpu(tunnel->hdr.remote_qpn),
+			     be32_to_cpu(tunnel->hdr.qkey),
+			     &ah_attr, &tunnel->mad);
+}
+
+static int mlx4_ib_alloc_pv_bufs(struct mlx4_ib_demux_pv_ctx *ctx,
+				 enum ib_qp_type qp_type, int is_tun)
+{
+	int i;
+	struct mlx4_ib_demux_pv_qp *tun_qp;
+	int rx_buf_size, tx_buf_size;
+
+	if (qp_type > IB_QPT_GSI)
+		return -EINVAL;
+
+	tun_qp = &ctx->qp[qp_type];
+
+	tun_qp->ring = kzalloc(sizeof (struct mlx4_ib_buf) * MLX4_NUM_TUNNEL_BUFS,
+			       GFP_KERNEL);
+	if (!tun_qp->ring)
+		return -ENOMEM;
+
+	tun_qp->tx_ring = kcalloc(MLX4_NUM_TUNNEL_BUFS,
+				  sizeof (struct mlx4_ib_tun_tx_buf),
+				  GFP_KERNEL);
+	if (!tun_qp->tx_ring) {
+		kfree(tun_qp->ring);
+		tun_qp->ring = NULL;
+		return -ENOMEM;
+	}
+
+	if (is_tun) {
+		rx_buf_size = sizeof (struct mlx4_tunnel_mad);
+		tx_buf_size = sizeof (struct mlx4_rcv_tunnel_mad);
+	} else {
+		rx_buf_size = sizeof (struct mlx4_mad_rcv_buf);
+		tx_buf_size = sizeof (struct mlx4_mad_snd_buf);
+	}
+
+	for (i = 0; i < MLX4_NUM_TUNNEL_BUFS; i++) {
+		tun_qp->ring[i].addr = kmalloc(rx_buf_size, GFP_KERNEL);
+		if (!tun_qp->ring[i].addr)
+			goto err;
+		tun_qp->ring[i].map = ib_dma_map_single(ctx->ib_dev,
+							tun_qp->ring[i].addr,
+							rx_buf_size,
+							DMA_FROM_DEVICE);
+	}
+
+	for (i = 0; i < MLX4_NUM_TUNNEL_BUFS; i++) {
+		tun_qp->tx_ring[i].buf.addr =
+			kmalloc(tx_buf_size, GFP_KERNEL);
+		if (!tun_qp->tx_ring[i].buf.addr)
+			goto tx_err;
+		tun_qp->tx_ring[i].buf.map =
+			ib_dma_map_single(ctx->ib_dev,
+					  tun_qp->tx_ring[i].buf.addr,
+					  tx_buf_size,
+					  DMA_TO_DEVICE);
+		tun_qp->tx_ring[i].ah = NULL;
+	}
+	spin_lock_init(&tun_qp->tx_lock);
+	tun_qp->tx_ix_head = 0;
+	tun_qp->tx_ix_tail = 0;
+	tun_qp->proxy_qpt = qp_type;
+
+	return 0;
+
+tx_err:
+	while (i > 0) {
+		--i;
+		ib_dma_unmap_single(ctx->ib_dev, tun_qp->tx_ring[i].buf.map,
+				    tx_buf_size, DMA_TO_DEVICE);
+		kfree(tun_qp->tx_ring[i].buf.addr);
+	}
+	kfree(tun_qp->tx_ring);
+	tun_qp->tx_ring = NULL;
+	i = MLX4_NUM_TUNNEL_BUFS;
+err:
+	while (i > 0) {
+		--i;
+		ib_dma_unmap_single(ctx->ib_dev, tun_qp->ring[i].map,
+				    rx_buf_size, DMA_FROM_DEVICE);
+		kfree(tun_qp->ring[i].addr);
+	}
+	kfree(tun_qp->ring);
+	tun_qp->ring = NULL;
+	return -ENOMEM;
+}
+
+static void mlx4_ib_free_pv_qp_bufs(struct mlx4_ib_demux_pv_ctx *ctx,
+				     enum ib_qp_type qp_type, int is_tun)
+{
+	int i;
+	struct mlx4_ib_demux_pv_qp *tun_qp;
+	int rx_buf_size, tx_buf_size;
+
+	if (qp_type > IB_QPT_GSI)
+		return;
+
+	tun_qp = &ctx->qp[qp_type];
+	if (is_tun) {
+		rx_buf_size = sizeof (struct mlx4_tunnel_mad);
+		tx_buf_size = sizeof (struct mlx4_rcv_tunnel_mad);
+	} else {
+		rx_buf_size = sizeof (struct mlx4_mad_rcv_buf);
+		tx_buf_size = sizeof (struct mlx4_mad_snd_buf);
+	}
+
+
+	for (i = 0; i < MLX4_NUM_TUNNEL_BUFS; i++) {
+		ib_dma_unmap_single(ctx->ib_dev, tun_qp->ring[i].map,
+				    rx_buf_size, DMA_FROM_DEVICE);
+		kfree(tun_qp->ring[i].addr);
+	}
+
+	for (i = 0; i < MLX4_NUM_TUNNEL_BUFS; i++) {
+		ib_dma_unmap_single(ctx->ib_dev, tun_qp->tx_ring[i].buf.map,
+				    tx_buf_size, DMA_TO_DEVICE);
+		kfree(tun_qp->tx_ring[i].buf.addr);
+		if (tun_qp->tx_ring[i].ah)
+			ib_destroy_ah(tun_qp->tx_ring[i].ah);
+	}
+	kfree(tun_qp->tx_ring);
+	kfree(tun_qp->ring);
+}
+
+static void mlx4_ib_tunnel_comp_worker(struct work_struct *work)
+{
+	struct mlx4_ib_demux_pv_ctx *ctx;
+	struct mlx4_ib_demux_pv_qp *tun_qp;
+	struct ib_wc wc;
+	int ret;
+	ctx = container_of(work, struct mlx4_ib_demux_pv_ctx, work);
+	ib_req_notify_cq(ctx->cq, IB_CQ_NEXT_COMP);
+
+	while (ib_poll_cq(ctx->cq, 1, &wc) == 1) {
+		tun_qp = &ctx->qp[MLX4_TUN_WRID_QPN(wc.wr_id)];
+		if (wc.status == IB_WC_SUCCESS) {
+			switch (wc.opcode) {
+			case IB_WC_RECV:
+				mlx4_ib_multiplex_mad(ctx, &wc);
+				ret = mlx4_ib_post_pv_qp_buf(ctx, tun_qp,
+							     wc.wr_id &
+							     (MLX4_NUM_TUNNEL_BUFS - 1));
+				if (ret)
+					pr_err("Failed reposting tunnel "
+					       "buf:%lld\n", wc.wr_id);
+				break;
+			case IB_WC_SEND:
+				pr_debug("received tunnel send completion:"
+					 "wrid=0x%llx, status=0x%x\n",
+					 wc.wr_id, wc.status);
+				ib_destroy_ah(tun_qp->tx_ring[wc.wr_id &
+					      (MLX4_NUM_TUNNEL_BUFS - 1)].ah);
+				tun_qp->tx_ring[wc.wr_id & (MLX4_NUM_TUNNEL_BUFS - 1)].ah
+					= NULL;
+				spin_lock(&tun_qp->tx_lock);
+				tun_qp->tx_ix_tail++;
+				spin_unlock(&tun_qp->tx_lock);
+
+				break;
+			default:
+				break;
+			}
+		} else  {
+			pr_debug("mlx4_ib: completion error in tunnel: %d."
+				 " status = %d, wrid = 0x%llx\n",
+				 ctx->slave, wc.status, wc.wr_id);
+			if (!MLX4_TUN_IS_RECV(wc.wr_id)) {
+				ib_destroy_ah(tun_qp->tx_ring[wc.wr_id &
+					      (MLX4_NUM_TUNNEL_BUFS - 1)].ah);
+				tun_qp->tx_ring[wc.wr_id & (MLX4_NUM_TUNNEL_BUFS - 1)].ah
+					= NULL;
+				spin_lock(&tun_qp->tx_lock);
+				tun_qp->tx_ix_tail++;
+				spin_unlock(&tun_qp->tx_lock);
+			}
+		}
+	}
+}
+
+static void pv_qp_event_handler(struct ib_event *event, void *qp_context)
+{
+	struct mlx4_ib_demux_pv_ctx *sqp = qp_context;
+
+	/* It's worse than that! He's dead, Jim! */
+	pr_err("Fatal error (%d) on a MAD QP on port %d\n",
+	       event->event, sqp->port);
+}
+
+static int create_pv_sqp(struct mlx4_ib_demux_pv_ctx *ctx,
+			    enum ib_qp_type qp_type, int create_tun)
+{
+	int i, ret;
+	struct mlx4_ib_demux_pv_qp *tun_qp;
+	struct mlx4_ib_qp_tunnel_init_attr qp_init_attr;
+	struct ib_qp_attr attr;
+	int qp_attr_mask_INIT;
+
+	if (qp_type > IB_QPT_GSI)
+		return -EINVAL;
+
+	tun_qp = &ctx->qp[qp_type];
+
+	memset(&qp_init_attr, 0, sizeof qp_init_attr);
+	qp_init_attr.init_attr.send_cq = ctx->cq;
+	qp_init_attr.init_attr.recv_cq = ctx->cq;
+	qp_init_attr.init_attr.sq_sig_type = IB_SIGNAL_ALL_WR;
+	qp_init_attr.init_attr.cap.max_send_wr = MLX4_NUM_TUNNEL_BUFS;
+	qp_init_attr.init_attr.cap.max_recv_wr = MLX4_NUM_TUNNEL_BUFS;
+	qp_init_attr.init_attr.cap.max_send_sge = 1;
+	qp_init_attr.init_attr.cap.max_recv_sge = 1;
+	if (create_tun) {
+		qp_init_attr.init_attr.qp_type = IB_QPT_UD;
+		qp_init_attr.init_attr.create_flags = MLX4_IB_SRIOV_TUNNEL_QP;
+		qp_init_attr.port = ctx->port;
+		qp_init_attr.slave = ctx->slave;
+		qp_init_attr.proxy_qp_type = qp_type;
+		qp_attr_mask_INIT = IB_QP_STATE | IB_QP_PKEY_INDEX |
+			   IB_QP_QKEY | IB_QP_PORT;
+	} else {
+		qp_init_attr.init_attr.qp_type = qp_type;
+		qp_init_attr.init_attr.create_flags = MLX4_IB_SRIOV_SQP;
+		qp_attr_mask_INIT = IB_QP_STATE | IB_QP_PKEY_INDEX | IB_QP_QKEY;
+	}
+	qp_init_attr.init_attr.port_num = ctx->port;
+	qp_init_attr.init_attr.qp_context = ctx;
+	qp_init_attr.init_attr.event_handler = pv_qp_event_handler;
+	tun_qp->qp = ib_create_qp(ctx->pd, &qp_init_attr.init_attr);
+	if (IS_ERR(tun_qp->qp)) {
+		ret = PTR_ERR(tun_qp->qp);
+		tun_qp->qp = NULL;
+		pr_err("Couldn't create %s QP (%d)\n",
+		       create_tun ? "tunnel" : "special", ret);
+		return ret;
+	}
+
+	memset(&attr, 0, sizeof attr);
+	attr.qp_state = IB_QPS_INIT;
+	attr.pkey_index =
+		to_mdev(ctx->ib_dev)->pkeys.virt2phys_pkey[ctx->slave][ctx->port - 1][0];
+	attr.qkey = IB_QP1_QKEY;
+	attr.port_num = ctx->port;
+	ret = ib_modify_qp(tun_qp->qp, &attr, qp_attr_mask_INIT);
+	if (ret) {
+		pr_err("Couldn't change %s qp state to INIT (%d)\n",
+		       create_tun ? "tunnel" : "special", ret);
+		goto err_qp;
+	}
+	attr.qp_state = IB_QPS_RTR;
+	ret = ib_modify_qp(tun_qp->qp, &attr, IB_QP_STATE);
+	if (ret) {
+		pr_err("Couldn't change %s qp state to RTR (%d)\n",
+		       create_tun ? "tunnel" : "special", ret);
+		goto err_qp;
+	}
+	attr.qp_state = IB_QPS_RTS;
+	attr.sq_psn = 0;
+	ret = ib_modify_qp(tun_qp->qp, &attr, IB_QP_STATE | IB_QP_SQ_PSN);
+	if (ret) {
+		pr_err("Couldn't change %s qp state to RTS (%d)\n",
+		       create_tun ? "tunnel" : "special", ret);
+		goto err_qp;
+	}
+
+	for (i = 0; i < MLX4_NUM_TUNNEL_BUFS; i++) {
+		ret = mlx4_ib_post_pv_qp_buf(ctx, tun_qp, i);
+		if (ret) {
+			pr_err(" mlx4_ib_post_pv_buf error"
+			       " (err = %d, i = %d)\n", ret, i);
+			goto err_qp;
+		}
+	}
+	return 0;
+
+err_qp:
+	ib_destroy_qp(tun_qp->qp);
+	tun_qp->qp = NULL;
+	return ret;
+}
+
+/*
+ * IB MAD completion callback for real SQPs
+ */
+static void mlx4_ib_sqp_comp_worker(struct work_struct *work)
+{
+	struct mlx4_ib_demux_pv_ctx *ctx;
+	struct mlx4_ib_demux_pv_qp *sqp;
+	struct ib_wc wc;
+	struct ib_grh *grh;
+	struct ib_mad *mad;
+
+	ctx = container_of(work, struct mlx4_ib_demux_pv_ctx, work);
+	ib_req_notify_cq(ctx->cq, IB_CQ_NEXT_COMP);
+
+	while (mlx4_ib_poll_cq(ctx->cq, 1, &wc) == 1) {
+		sqp = &ctx->qp[MLX4_TUN_WRID_QPN(wc.wr_id)];
+		if (wc.status == IB_WC_SUCCESS) {
+			switch (wc.opcode) {
+			case IB_WC_SEND:
+				ib_destroy_ah(sqp->tx_ring[wc.wr_id &
+					      (MLX4_NUM_TUNNEL_BUFS - 1)].ah);
+				sqp->tx_ring[wc.wr_id & (MLX4_NUM_TUNNEL_BUFS - 1)].ah
+					= NULL;
+				spin_lock(&sqp->tx_lock);
+				sqp->tx_ix_tail++;
+				spin_unlock(&sqp->tx_lock);
+				break;
+			case IB_WC_RECV:
+				mad = (struct ib_mad *) &(((struct mlx4_mad_rcv_buf *)
+						(sqp->ring[wc.wr_id &
+						(MLX4_NUM_TUNNEL_BUFS - 1)].addr))->payload);
+				grh = &(((struct mlx4_mad_rcv_buf *)
+						(sqp->ring[wc.wr_id &
+						(MLX4_NUM_TUNNEL_BUFS - 1)].addr))->grh);
+				mlx4_ib_demux_mad(ctx->ib_dev, ctx->port, &wc, grh, mad);
+				if (mlx4_ib_post_pv_qp_buf(ctx, sqp, wc.wr_id &
+							   (MLX4_NUM_TUNNEL_BUFS - 1)))
+					pr_err("Failed reposting SQP "
+					       "buf:%lld\n", wc.wr_id);
+				break;
+			default:
+				BUG_ON(1);
+				break;
+			}
+		} else  {
+			pr_debug("mlx4_ib: completion error in tunnel: %d."
+				 " status = %d, wrid = 0x%llx\n",
+				 ctx->slave, wc.status, wc.wr_id);
+			if (!MLX4_TUN_IS_RECV(wc.wr_id)) {
+				ib_destroy_ah(sqp->tx_ring[wc.wr_id &
+					      (MLX4_NUM_TUNNEL_BUFS - 1)].ah);
+				sqp->tx_ring[wc.wr_id & (MLX4_NUM_TUNNEL_BUFS - 1)].ah
+					= NULL;
+				spin_lock(&sqp->tx_lock);
+				sqp->tx_ix_tail++;
+				spin_unlock(&sqp->tx_lock);
+			}
+		}
+	}
+}
+
+static int alloc_pv_object(struct mlx4_ib_dev *dev, int slave, int port,
+			       struct mlx4_ib_demux_pv_ctx **ret_ctx)
+{
+	struct mlx4_ib_demux_pv_ctx *ctx;
+
+	*ret_ctx = NULL;
+	ctx = kzalloc(sizeof (struct mlx4_ib_demux_pv_ctx), GFP_KERNEL);
+	if (!ctx) {
+		pr_err("failed allocating pv resource context "
+		       "for port %d, slave %d\n", port, slave);
+		return -ENOMEM;
+	}
+
+	ctx->ib_dev = &dev->ib_dev;
+	ctx->port = port;
+	ctx->slave = slave;
+	*ret_ctx = ctx;
+	return 0;
+}
+
+static void free_pv_object(struct mlx4_ib_dev *dev, int slave, int port)
+{
+	if (dev->sriov.demux[port - 1].tun[slave]) {
+		kfree(dev->sriov.demux[port - 1].tun[slave]);
+		dev->sriov.demux[port - 1].tun[slave] = NULL;
+	}
+}
+
+static int create_pv_resources(struct ib_device *ibdev, int slave, int port,
+			       int create_tun, struct mlx4_ib_demux_pv_ctx *ctx)
+{
+	int ret, cq_size;
+
+	if (ctx->state != DEMUX_PV_STATE_DOWN)
+		return -EEXIST;
+
+	ctx->state = DEMUX_PV_STATE_STARTING;
+	/* have QP0 only on port owner, and only if link layer is IB */
+	if (ctx->slave == mlx4_master_func_num(to_mdev(ctx->ib_dev)->dev) &&
+	    rdma_port_get_link_layer(ibdev, ctx->port) == IB_LINK_LAYER_INFINIBAND)
+		ctx->has_smi = 1;
+
+	if (ctx->has_smi) {
+		ret = mlx4_ib_alloc_pv_bufs(ctx, IB_QPT_SMI, create_tun);
+		if (ret) {
+			pr_err("Failed allocating qp0 tunnel bufs (%d)\n", ret);
+			goto err_out;
+		}
+	}
+
+	ret = mlx4_ib_alloc_pv_bufs(ctx, IB_QPT_GSI, create_tun);
+	if (ret) {
+		pr_err("Failed allocating qp1 tunnel bufs (%d)\n", ret);
+		goto err_out_qp0;
+	}
+
+	cq_size = 2 * MLX4_NUM_TUNNEL_BUFS;
+	if (ctx->has_smi)
+		cq_size *= 2;
+
+	ctx->cq = ib_create_cq(ctx->ib_dev, mlx4_ib_tunnel_comp_handler,
+			       NULL, ctx, cq_size, 0);
+	if (IS_ERR(ctx->cq)) {
+		ret = PTR_ERR(ctx->cq);
+		pr_err("Couldn't create tunnel CQ (%d)\n", ret);
+		goto err_buf;
+	}
+
+	ctx->pd = ib_alloc_pd(ctx->ib_dev);
+	if (IS_ERR(ctx->pd)) {
+		ret = PTR_ERR(ctx->pd);
+		pr_err("Couldn't create tunnel PD (%d)\n", ret);
+		goto err_cq;
+	}
+
+	ctx->mr = ib_get_dma_mr(ctx->pd, IB_ACCESS_LOCAL_WRITE);
+	if (IS_ERR(ctx->mr)) {
+		ret = PTR_ERR(ctx->mr);
+		pr_err("Couldn't get tunnel DMA MR (%d)\n", ret);
+		goto err_pd;
+	}
+
+	if (ctx->has_smi) {
+		ret = create_pv_sqp(ctx, IB_QPT_SMI, create_tun);
+		if (ret) {
+			pr_err("Couldn't create %s QP0 (%d)\n",
+			       create_tun ? "tunnel for" : "",  ret);
+			goto err_mr;
+		}
+	}
+
+	ret = create_pv_sqp(ctx, IB_QPT_GSI, create_tun);
+	if (ret) {
+		pr_err("Couldn't create %s QP1 (%d)\n",
+		       create_tun ? "tunnel for" : "",  ret);
+		goto err_qp0;
+	}
+
+	if (create_tun)
+		INIT_WORK(&ctx->work, mlx4_ib_tunnel_comp_worker);
+	else
+		INIT_WORK(&ctx->work, mlx4_ib_sqp_comp_worker);
+
+	ctx->wq = to_mdev(ibdev)->sriov.demux[port - 1].wq;
+
+	ret = ib_req_notify_cq(ctx->cq, IB_CQ_NEXT_COMP);
+	if (ret) {
+		pr_err("Couldn't arm tunnel cq (%d)\n", ret);
+		goto err_wq;
+	}
+	ctx->state = DEMUX_PV_STATE_ACTIVE;
+	return 0;
+
+err_wq:
+	ctx->wq = NULL;
+	ib_destroy_qp(ctx->qp[1].qp);
+	ctx->qp[1].qp = NULL;
+
+
+err_qp0:
+	if (ctx->has_smi)
+		ib_destroy_qp(ctx->qp[0].qp);
+	ctx->qp[0].qp = NULL;
+
+err_mr:
+	ib_dereg_mr(ctx->mr);
+	ctx->mr = NULL;
+
+err_pd:
+	ib_dealloc_pd(ctx->pd);
+	ctx->pd = NULL;
+
+err_cq:
+	ib_destroy_cq(ctx->cq);
+	ctx->cq = NULL;
+
+err_buf:
+	mlx4_ib_free_pv_qp_bufs(ctx, IB_QPT_GSI, create_tun);
+
+err_out_qp0:
+	if (ctx->has_smi)
+		mlx4_ib_free_pv_qp_bufs(ctx, IB_QPT_SMI, create_tun);
+err_out:
+	ctx->state = DEMUX_PV_STATE_DOWN;
+	return ret;
+}
+
+static void destroy_pv_resources(struct mlx4_ib_dev *dev, int slave, int port,
+				 struct mlx4_ib_demux_pv_ctx *ctx, int flush)
+{
+	if (!ctx)
+		return;
+	if (ctx->state > DEMUX_PV_STATE_DOWN) {
+		ctx->state = DEMUX_PV_STATE_DOWNING;
+		if (flush)
+			flush_workqueue(ctx->wq);
+		if (ctx->has_smi) {
+			ib_destroy_qp(ctx->qp[0].qp);
+			ctx->qp[0].qp = NULL;
+			mlx4_ib_free_pv_qp_bufs(ctx, IB_QPT_SMI, 1);
+		}
+		ib_destroy_qp(ctx->qp[1].qp);
+		ctx->qp[1].qp = NULL;
+		mlx4_ib_free_pv_qp_bufs(ctx, IB_QPT_GSI, 1);
+		ib_dereg_mr(ctx->mr);
+		ctx->mr = NULL;
+		ib_dealloc_pd(ctx->pd);
+		ctx->pd = NULL;
+		ib_destroy_cq(ctx->cq);
+		ctx->cq = NULL;
+		ctx->state = DEMUX_PV_STATE_DOWN;
+	}
+}
+
+static int mlx4_ib_tunnels_update(struct mlx4_ib_dev *dev, int slave,
+				  int port, int do_init)
+{
+	int ret = 0;
+
+	if (!do_init) {
+		clean_vf_mcast(&dev->sriov.demux[port - 1], slave);
+		/* for master, destroy real sqp resources */
+		if (slave == mlx4_master_func_num(dev->dev))
+			destroy_pv_resources(dev, slave, port,
+					     dev->sriov.sqps[port - 1], 1);
+		/* destroy the tunnel qp resources */
+		destroy_pv_resources(dev, slave, port,
+				     dev->sriov.demux[port - 1].tun[slave], 1);
+		return 0;
+	}
+
+	/* create the tunnel qp resources */
+	ret = create_pv_resources(&dev->ib_dev, slave, port, 1,
+				  dev->sriov.demux[port - 1].tun[slave]);
+
+	/* for master, create the real sqp resources */
+	if (!ret && slave == mlx4_master_func_num(dev->dev))
+		ret = create_pv_resources(&dev->ib_dev, slave, port, 0,
+					  dev->sriov.sqps[port - 1]);
+	return ret;
+}
+
+void mlx4_ib_tunnels_update_work(struct work_struct *work)
+{
+	struct mlx4_ib_demux_work *dmxw;
+
+	dmxw = container_of(work, struct mlx4_ib_demux_work, work);
+	mlx4_ib_tunnels_update(dmxw->dev, dmxw->slave, (int) dmxw->port,
+			       dmxw->do_init);
+	kfree(dmxw);
+	return;
+}
+
+static int mlx4_ib_alloc_demux_ctx(struct mlx4_ib_dev *dev,
+				       struct mlx4_ib_demux_ctx *ctx,
+				       int port)
+{
+	char name[12];
+	int ret = 0;
+	int i;
+
+	ctx->tun = kcalloc(dev->dev->caps.sqp_demux,
+			   sizeof (struct mlx4_ib_demux_pv_ctx *), GFP_KERNEL);
+	if (!ctx->tun)
+		return -ENOMEM;
+
+	ctx->dev = dev;
+	ctx->port = port;
+	ctx->ib_dev = &dev->ib_dev;
+
+	for (i = 0; i < dev->dev->caps.sqp_demux; i++) {
+		ret = alloc_pv_object(dev, i, port, &ctx->tun[i]);
+		if (ret) {
+			ret = -ENOMEM;
+			goto err_mcg;
+		}
+	}
+
+	ret = mlx4_ib_mcg_port_init(ctx);
+	if (ret) {
+		pr_err("Failed initializing mcg para-virt (%d)\n", ret);
+		goto err_mcg;
+	}
+
+	snprintf(name, sizeof name, "mlx4_ibt%d", port);
+	ctx->wq = create_singlethread_workqueue(name);
+	if (!ctx->wq) {
+		pr_err("Failed to create tunnelling WQ for port %d\n", port);
+		ret = -ENOMEM;
+		goto err_wq;
+	}
+
+	snprintf(name, sizeof name, "mlx4_ibud%d", port);
+	ctx->ud_wq = create_singlethread_workqueue(name);
+	if (!ctx->ud_wq) {
+		pr_err("Failed to create up/down WQ for port %d\n", port);
+		ret = -ENOMEM;
+		goto err_udwq;
+	}
+
+	return 0;
+
+err_udwq:
+	destroy_workqueue(ctx->wq);
+	ctx->wq = NULL;
+
+err_wq:
+	mlx4_ib_mcg_port_cleanup(ctx, 1);
+err_mcg:
+	for (i = 0; i < dev->dev->caps.sqp_demux; i++)
+		free_pv_object(dev, i, port);
+	kfree(ctx->tun);
+	ctx->tun = NULL;
+	return ret;
+}
+
+static void mlx4_ib_free_sqp_ctx(struct mlx4_ib_demux_pv_ctx *sqp_ctx)
+{
+	if (sqp_ctx->state > DEMUX_PV_STATE_DOWN) {
+		sqp_ctx->state = DEMUX_PV_STATE_DOWNING;
+		flush_workqueue(sqp_ctx->wq);
+		if (sqp_ctx->has_smi) {
+			ib_destroy_qp(sqp_ctx->qp[0].qp);
+			sqp_ctx->qp[0].qp = NULL;
+			mlx4_ib_free_pv_qp_bufs(sqp_ctx, IB_QPT_SMI, 0);
+		}
+		ib_destroy_qp(sqp_ctx->qp[1].qp);
+		sqp_ctx->qp[1].qp = NULL;
+		mlx4_ib_free_pv_qp_bufs(sqp_ctx, IB_QPT_GSI, 0);
+		ib_dereg_mr(sqp_ctx->mr);
+		sqp_ctx->mr = NULL;
+		ib_dealloc_pd(sqp_ctx->pd);
+		sqp_ctx->pd = NULL;
+		ib_destroy_cq(sqp_ctx->cq);
+		sqp_ctx->cq = NULL;
+		sqp_ctx->state = DEMUX_PV_STATE_DOWN;
+	}
+}
+
+static void mlx4_ib_free_demux_ctx(struct mlx4_ib_demux_ctx *ctx)
+{
+	int i;
+	if (ctx) {
+		struct mlx4_ib_dev *dev = to_mdev(ctx->ib_dev);
+		mlx4_ib_mcg_port_cleanup(ctx, 1);
+		for (i = 0; i < dev->dev->caps.sqp_demux; i++) {
+			if (!ctx->tun[i])
+				continue;
+			if (ctx->tun[i]->state > DEMUX_PV_STATE_DOWN)
+				ctx->tun[i]->state = DEMUX_PV_STATE_DOWNING;
+		}
+		flush_workqueue(ctx->wq);
+		for (i = 0; i < dev->dev->caps.sqp_demux; i++) {
+			destroy_pv_resources(dev, i, ctx->port, ctx->tun[i], 0);
+			free_pv_object(dev, i, ctx->port);
+		}
+		kfree(ctx->tun);
+		destroy_workqueue(ctx->ud_wq);
+		destroy_workqueue(ctx->wq);
+	}
+}
+
+static void mlx4_ib_master_tunnels(struct mlx4_ib_dev *dev, int do_init)
+{
+	int i;
+
+	if (!mlx4_is_master(dev->dev))
+		return;
+	/* initialize or tear down tunnel QPs for the master */
+	for (i = 0; i < dev->dev->caps.num_ports; i++)
+		mlx4_ib_tunnels_update(dev, mlx4_master_func_num(dev->dev), i + 1, do_init);
+	return;
+}
+
+int mlx4_ib_init_sriov(struct mlx4_ib_dev *dev)
+{
+	int i = 0;
+	int err;
+
+	if (!mlx4_is_mfunc(dev->dev))
+		return 0;
+
+	dev->sriov.is_going_down = 0;
+	spin_lock_init(&dev->sriov.going_down_lock);
+	mlx4_ib_cm_paravirt_init(dev);
+
+	mlx4_ib_warn(&dev->ib_dev, "multi-function enabled\n");
+
+	if (mlx4_is_slave(dev->dev)) {
+		mlx4_ib_warn(&dev->ib_dev, "operating in qp1 tunnel mode\n");
+		return 0;
+	}
+
+	for (i = 0; i < dev->dev->caps.sqp_demux; i++) {
+		if (i == mlx4_master_func_num(dev->dev))
+			mlx4_put_slave_node_guid(dev->dev, i, dev->ib_dev.node_guid);
+		else
+			mlx4_put_slave_node_guid(dev->dev, i, mlx4_ib_gen_node_guid());
+	}
+
+	err = mlx4_ib_init_alias_guid_service(dev);
+	if (err) {
+		mlx4_ib_warn(&dev->ib_dev, "Failed init alias guid process.\n");
+		goto paravirt_err;
+	}
+	err = mlx4_ib_device_register_sysfs(dev);
+	if (err) {
+		mlx4_ib_warn(&dev->ib_dev, "Failed to register sysfs\n");
+		goto sysfs_err;
+	}
+
+	mlx4_ib_warn(&dev->ib_dev, "initializing demux service for %d qp1 clients\n",
+		     dev->dev->caps.sqp_demux);
+	for (i = 0; i < dev->num_ports; i++) {
+		union ib_gid gid;
+		err = __mlx4_ib_query_gid(&dev->ib_dev, i + 1, 0, &gid, 1);
+		if (err)
+			goto demux_err;
+		dev->sriov.demux[i].guid_cache[0] = gid.global.interface_id;
+		err = alloc_pv_object(dev, mlx4_master_func_num(dev->dev), i + 1,
+				      &dev->sriov.sqps[i]);
+		if (err)
+			goto demux_err;
+		err = mlx4_ib_alloc_demux_ctx(dev, &dev->sriov.demux[i], i + 1);
+		if (err)
+			goto demux_err;
+	}
+	mlx4_ib_master_tunnels(dev, 1);
+	return 0;
+
+demux_err:
+	while (i > 0) {
+		free_pv_object(dev, mlx4_master_func_num(dev->dev), i + 1);
+		mlx4_ib_free_demux_ctx(&dev->sriov.demux[i]);
+		--i;
+	}
+	mlx4_ib_device_unregister_sysfs(dev);
+
+sysfs_err:
+	mlx4_ib_destroy_alias_guid_service(dev);
+
+paravirt_err:
+	mlx4_ib_cm_paravirt_clean(dev, -1);
+
+	return err;
+}
+
+void mlx4_ib_close_sriov(struct mlx4_ib_dev *dev)
+{
+	int i;
+	unsigned long flags;
+
+	if (!mlx4_is_mfunc(dev->dev))
+		return;
+
+	spin_lock_irqsave(&dev->sriov.going_down_lock, flags);
+	dev->sriov.is_going_down = 1;
+	spin_unlock_irqrestore(&dev->sriov.going_down_lock, flags);
+	if (mlx4_is_master(dev->dev)) {
+		for (i = 0; i < dev->num_ports; i++) {
+			flush_workqueue(dev->sriov.demux[i].ud_wq);
+			mlx4_ib_free_sqp_ctx(dev->sriov.sqps[i]);
+			kfree(dev->sriov.sqps[i]);
+			dev->sriov.sqps[i] = NULL;
+			mlx4_ib_free_demux_ctx(&dev->sriov.demux[i]);
+		}
+
+		mlx4_ib_cm_paravirt_clean(dev, -1);
+		mlx4_ib_destroy_alias_guid_service(dev);
+		mlx4_ib_device_unregister_sysfs(dev);
+	}
+}
diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c
index cc05579..718ec6b 100644
--- a/drivers/infiniband/hw/mlx4/main.c
+++ b/drivers/infiniband/hw/mlx4/main.c
@@ -59,6 +59,10 @@ MODULE_DESCRIPTION("Mellanox ConnectX HCA InfiniBand driver");
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_VERSION(DRV_VERSION);
 
+int mlx4_ib_sm_guid_assign = 1;
+module_param_named(sm_guid_assign, mlx4_ib_sm_guid_assign, int, 0444);
+MODULE_PARM_DESC(sm_guid_assign, "Enable SM alias_GUID assignment if sm_guid_assign > 0 (Default: 1)");
+
 static const char mlx4_ib_version[] =
 	DRV_NAME ": Mellanox ConnectX InfiniBand driver v"
 	DRV_VERSION " (" DRV_RELDATE ")\n";
@@ -70,6 +74,8 @@ struct update_gid_work {
 	int			port;
 };
 
+static void do_slave_init(struct mlx4_ib_dev *ibdev, int slave, int do_init);
+
 static struct workqueue_struct *wq;
 
 static void init_query_mad(struct ib_smp *mad)
@@ -98,7 +104,8 @@ static int mlx4_ib_query_device(struct ib_device *ibdev,
 	init_query_mad(in_mad);
 	in_mad->attr_id = IB_SMP_ATTR_NODE_INFO;
 
-	err = mlx4_MAD_IFC(to_mdev(ibdev), 1, 1, 1, NULL, NULL, in_mad, out_mad);
+	err = mlx4_MAD_IFC(to_mdev(ibdev), MLX4_MAD_IFC_IGNORE_KEYS,
+			   1, NULL, NULL, in_mad, out_mad);
 	if (err)
 		goto out;
 
@@ -133,7 +140,7 @@ static int mlx4_ib_query_device(struct ib_device *ibdev,
 
 	props->vendor_id	   = be32_to_cpup((__be32 *) (out_mad->data + 36)) &
 		0xffffff;
-	props->vendor_part_id	   = be16_to_cpup((__be16 *) (out_mad->data + 30));
+	props->vendor_part_id	   = dev->dev->pdev->device;
 	props->hw_ver		   = be32_to_cpup((__be32 *) (out_mad->data + 32));
 	memcpy(&props->sys_image_guid, out_mad->data +	4, 8);
 
@@ -182,11 +189,12 @@ mlx4_ib_port_link_layer(struct ib_device *device, u8 port_num)
 }
 
 static int ib_link_query_port(struct ib_device *ibdev, u8 port,
-			      struct ib_port_attr *props)
+			      struct ib_port_attr *props, int netw_view)
 {
 	struct ib_smp *in_mad  = NULL;
 	struct ib_smp *out_mad = NULL;
 	int ext_active_speed;
+	int mad_ifc_flags = MLX4_MAD_IFC_IGNORE_KEYS;
 	int err = -ENOMEM;
 
 	in_mad  = kzalloc(sizeof *in_mad, GFP_KERNEL);
@@ -198,7 +206,10 @@ static int ib_link_query_port(struct ib_device *ibdev, u8 port,
 	in_mad->attr_id  = IB_SMP_ATTR_PORT_INFO;
 	in_mad->attr_mod = cpu_to_be32(port);
 
-	err = mlx4_MAD_IFC(to_mdev(ibdev), 1, 1, port, NULL, NULL,
+	if (mlx4_is_mfunc(to_mdev(ibdev)->dev) && netw_view)
+		mad_ifc_flags |= MLX4_MAD_IFC_NET_VIEW;
+
+	err = mlx4_MAD_IFC(to_mdev(ibdev), mad_ifc_flags, port, NULL, NULL,
 				in_mad, out_mad);
 	if (err)
 		goto out;
@@ -211,7 +222,10 @@ static int ib_link_query_port(struct ib_device *ibdev, u8 port,
 	props->state		= out_mad->data[32] & 0xf;
 	props->phys_state	= out_mad->data[33] >> 4;
 	props->port_cap_flags	= be32_to_cpup((__be32 *) (out_mad->data + 20));
-	props->gid_tbl_len	= to_mdev(ibdev)->dev->caps.gid_table_len[port];
+	if (netw_view)
+		props->gid_tbl_len = out_mad->data[50];
+	else
+		props->gid_tbl_len = to_mdev(ibdev)->dev->caps.gid_table_len[port];
 	props->max_msg_sz	= to_mdev(ibdev)->dev->caps.max_msg_sz;
 	props->pkey_tbl_len	= to_mdev(ibdev)->dev->caps.pkey_table_len[port];
 	props->bad_pkey_cntr	= be16_to_cpup((__be16 *) (out_mad->data + 46));
@@ -244,7 +258,7 @@ static int ib_link_query_port(struct ib_device *ibdev, u8 port,
 		in_mad->attr_id = MLX4_ATTR_EXTENDED_PORT_INFO;
 		in_mad->attr_mod = cpu_to_be32(port);
 
-		err = mlx4_MAD_IFC(to_mdev(ibdev), 1, 1, port,
+		err = mlx4_MAD_IFC(to_mdev(ibdev), mad_ifc_flags, port,
 				   NULL, NULL, in_mad, out_mad);
 		if (err)
 			goto out;
@@ -270,7 +284,7 @@ static u8 state_to_phys_state(enum ib_port_state state)
 }
 
 static int eth_link_query_port(struct ib_device *ibdev, u8 port,
-			       struct ib_port_attr *props)
+			       struct ib_port_attr *props, int netw_view)
 {
 
 	struct mlx4_ib_dev *mdev = to_mdev(ibdev);
@@ -320,26 +334,36 @@ out:
 	return err;
 }
 
-static int mlx4_ib_query_port(struct ib_device *ibdev, u8 port,
-			      struct ib_port_attr *props)
+int __mlx4_ib_query_port(struct ib_device *ibdev, u8 port,
+			 struct ib_port_attr *props, int netw_view)
 {
 	int err;
 
 	memset(props, 0, sizeof *props);
 
 	err = mlx4_ib_port_link_layer(ibdev, port) == IB_LINK_LAYER_INFINIBAND ?
-		ib_link_query_port(ibdev, port, props) :
-				eth_link_query_port(ibdev, port, props);
+		ib_link_query_port(ibdev, port, props, netw_view) :
+				eth_link_query_port(ibdev, port, props, netw_view);
 
 	return err;
 }
 
-static int __mlx4_ib_query_gid(struct ib_device *ibdev, u8 port, int index,
-			       union ib_gid *gid)
+static int mlx4_ib_query_port(struct ib_device *ibdev, u8 port,
+			      struct ib_port_attr *props)
+{
+	/* returns host view */
+	return __mlx4_ib_query_port(ibdev, port, props, 0);
+}
+
+int __mlx4_ib_query_gid(struct ib_device *ibdev, u8 port, int index,
+			union ib_gid *gid, int netw_view)
 {
 	struct ib_smp *in_mad  = NULL;
 	struct ib_smp *out_mad = NULL;
 	int err = -ENOMEM;
+	struct mlx4_ib_dev *dev = to_mdev(ibdev);
+	int clear = 0;
+	int mad_ifc_flags = MLX4_MAD_IFC_IGNORE_KEYS;
 
 	in_mad  = kzalloc(sizeof *in_mad, GFP_KERNEL);
 	out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL);
@@ -350,23 +374,38 @@ static int __mlx4_ib_query_gid(struct ib_device *ibdev, u8 port, int index,
 	in_mad->attr_id  = IB_SMP_ATTR_PORT_INFO;
 	in_mad->attr_mod = cpu_to_be32(port);
 
-	err = mlx4_MAD_IFC(to_mdev(ibdev), 1, 1, port, NULL, NULL, in_mad, out_mad);
+	if (mlx4_is_mfunc(dev->dev) && netw_view)
+		mad_ifc_flags |= MLX4_MAD_IFC_NET_VIEW;
+
+	err = mlx4_MAD_IFC(dev, mad_ifc_flags, port, NULL, NULL, in_mad, out_mad);
 	if (err)
 		goto out;
 
 	memcpy(gid->raw, out_mad->data + 8, 8);
 
+	if (mlx4_is_mfunc(dev->dev) && !netw_view) {
+		if (index) {
+			/* For any index > 0, return the null guid */
+			err = 0;
+			clear = 1;
+			goto out;
+		}
+	}
+
 	init_query_mad(in_mad);
 	in_mad->attr_id  = IB_SMP_ATTR_GUID_INFO;
 	in_mad->attr_mod = cpu_to_be32(index / 8);
 
-	err = mlx4_MAD_IFC(to_mdev(ibdev), 1, 1, port, NULL, NULL, in_mad, out_mad);
+	err = mlx4_MAD_IFC(dev, mad_ifc_flags, port,
+			   NULL, NULL, in_mad, out_mad);
 	if (err)
 		goto out;
 
 	memcpy(gid->raw + 8, out_mad->data + (index % 8) * 8, 8);
 
 out:
+	if (clear)
+		memset(gid->raw + 8, 0, 8);
 	kfree(in_mad);
 	kfree(out_mad);
 	return err;
@@ -386,16 +425,17 @@ static int mlx4_ib_query_gid(struct ib_device *ibdev, u8 port, int index,
 			     union ib_gid *gid)
 {
 	if (rdma_port_get_link_layer(ibdev, port) == IB_LINK_LAYER_INFINIBAND)
-		return __mlx4_ib_query_gid(ibdev, port, index, gid);
+		return __mlx4_ib_query_gid(ibdev, port, index, gid, 0);
 	else
 		return iboe_query_gid(ibdev, port, index, gid);
 }
 
-static int mlx4_ib_query_pkey(struct ib_device *ibdev, u8 port, u16 index,
-			      u16 *pkey)
+int __mlx4_ib_query_pkey(struct ib_device *ibdev, u8 port, u16 index,
+			 u16 *pkey, int netw_view)
 {
 	struct ib_smp *in_mad  = NULL;
 	struct ib_smp *out_mad = NULL;
+	int mad_ifc_flags = MLX4_MAD_IFC_IGNORE_KEYS;
 	int err = -ENOMEM;
 
 	in_mad  = kzalloc(sizeof *in_mad, GFP_KERNEL);
@@ -407,7 +447,11 @@ static int mlx4_ib_query_pkey(struct ib_device *ibdev, u8 port, u16 index,
 	in_mad->attr_id  = IB_SMP_ATTR_PKEY_TABLE;
 	in_mad->attr_mod = cpu_to_be32(index / 32);
 
-	err = mlx4_MAD_IFC(to_mdev(ibdev), 1, 1, port, NULL, NULL, in_mad, out_mad);
+	if (mlx4_is_mfunc(to_mdev(ibdev)->dev) && netw_view)
+		mad_ifc_flags |= MLX4_MAD_IFC_NET_VIEW;
+
+	err = mlx4_MAD_IFC(to_mdev(ibdev), mad_ifc_flags, port, NULL, NULL,
+			   in_mad, out_mad);
 	if (err)
 		goto out;
 
@@ -419,6 +463,11 @@ out:
 	return err;
 }
 
+static int mlx4_ib_query_pkey(struct ib_device *ibdev, u8 port, u16 index, u16 *pkey)
+{
+	return __mlx4_ib_query_pkey(ibdev, port, index, pkey, 0);
+}
+
 static int mlx4_ib_modify_device(struct ib_device *ibdev, int mask,
 				 struct ib_device_modify *props)
 {
@@ -431,6 +480,9 @@ static int mlx4_ib_modify_device(struct ib_device *ibdev, int mask,
 	if (!(mask & IB_DEVICE_MODIFY_NODE_DESC))
 		return 0;
 
+	if (mlx4_is_slave(to_mdev(ibdev)->dev))
+		return -EOPNOTSUPP;
+
 	spin_lock_irqsave(&to_mdev(ibdev)->sm_lock, flags);
 	memcpy(ibdev->node_desc, props->node_desc, 64);
 	spin_unlock_irqrestore(&to_mdev(ibdev)->sm_lock, flags);
@@ -446,7 +498,7 @@ static int mlx4_ib_modify_device(struct ib_device *ibdev, int mask,
 	memset(mailbox->buf, 0, 256);
 	memcpy(mailbox->buf, props->node_desc, 64);
 	mlx4_cmd(to_mdev(ibdev)->dev, mailbox->dma, 1, 0,
-		 MLX4_CMD_SET_NODE, MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
+		 MLX4_CMD_SET_NODE, MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
 
 	mlx4_free_cmd_mailbox(to_mdev(ibdev)->dev, mailbox);
 
@@ -849,6 +901,7 @@ static int init_node_data(struct mlx4_ib_dev *dev)
 {
 	struct ib_smp *in_mad  = NULL;
 	struct ib_smp *out_mad = NULL;
+	int mad_ifc_flags = MLX4_MAD_IFC_IGNORE_KEYS;
 	int err = -ENOMEM;
 
 	in_mad  = kzalloc(sizeof *in_mad, GFP_KERNEL);
@@ -858,8 +911,10 @@ static int init_node_data(struct mlx4_ib_dev *dev)
 
 	init_query_mad(in_mad);
 	in_mad->attr_id = IB_SMP_ATTR_NODE_DESC;
+	if (mlx4_is_master(dev->dev))
+		mad_ifc_flags |= MLX4_MAD_IFC_NET_VIEW;
 
-	err = mlx4_MAD_IFC(dev, 1, 1, 1, NULL, NULL, in_mad, out_mad);
+	err = mlx4_MAD_IFC(dev, mad_ifc_flags, 1, NULL, NULL, in_mad, out_mad);
 	if (err)
 		goto out;
 
@@ -867,10 +922,11 @@ static int init_node_data(struct mlx4_ib_dev *dev)
 
 	in_mad->attr_id = IB_SMP_ATTR_NODE_INFO;
 
-	err = mlx4_MAD_IFC(dev, 1, 1, 1, NULL, NULL, in_mad, out_mad);
+	err = mlx4_MAD_IFC(dev, mad_ifc_flags, 1, NULL, NULL, in_mad, out_mad);
 	if (err)
 		goto out;
 
+	dev->dev->rev_id = be32_to_cpup((__be32 *) (out_mad->data + 32));
 	memcpy(&dev->ib_dev.node_guid, out_mad->data + 12, 8);
 
 out:
@@ -959,7 +1015,7 @@ static void update_gids_task(struct work_struct *work)
 
 	err = mlx4_cmd(dev, mailbox->dma, MLX4_SET_PORT_GID_TABLE << 8 | gw->port,
 		       1, MLX4_CMD_SET_PORT, MLX4_CMD_TIME_CLASS_B,
-		       MLX4_CMD_NATIVE);
+		       MLX4_CMD_WRAPPED);
 	if (err)
 		pr_warn("set port command failed\n");
 	else {
@@ -1121,6 +1177,38 @@ static int mlx4_ib_netdev_event(struct notifier_block *this, unsigned long event
 	return NOTIFY_DONE;
 }
 
+static void init_pkeys(struct mlx4_ib_dev *ibdev)
+{
+	int port;
+	int slave;
+	int i;
+
+	if (mlx4_is_master(ibdev->dev)) {
+		for (slave = 0; slave <= ibdev->dev->num_vfs; ++slave) {
+			for (port = 1; port <= ibdev->dev->caps.num_ports; ++port) {
+				for (i = 0;
+				     i < ibdev->dev->phys_caps.pkey_phys_table_len[port];
+				     ++i) {
+					ibdev->pkeys.virt2phys_pkey[slave][port - 1][i] =
+					/* master has the identity virt2phys pkey mapping */
+						(slave == mlx4_master_func_num(ibdev->dev) || !i) ? i :
+							ibdev->dev->phys_caps.pkey_phys_table_len[port] - 1;
+					mlx4_sync_pkey_table(ibdev->dev, slave, port, i,
+							     ibdev->pkeys.virt2phys_pkey[slave][port - 1][i]);
+				}
+			}
+		}
+		/* initialize pkey cache */
+		for (port = 1; port <= ibdev->dev->caps.num_ports; ++port) {
+			for (i = 0;
+			     i < ibdev->dev->phys_caps.pkey_phys_table_len[port];
+			     ++i)
+				ibdev->pkeys.phys_pkey_cache[port-1][i] =
+					(i) ? 0 : 0xFFFF;
+		}
+	}
+}
+
 static void mlx4_ib_alloc_eqs(struct mlx4_dev *dev, struct mlx4_ib_dev *ibdev)
 {
 	char name[32];
@@ -1207,11 +1295,15 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
 
 	pr_info_once("%s", mlx4_ib_version);
 
-	if (mlx4_is_mfunc(dev)) {
-		pr_warn("IB not yet supported in SRIOV\n");
+	mlx4_foreach_non_ib_transport_port(i, dev)
+		num_ports++;
+
+	if (mlx4_is_mfunc(dev) && num_ports) {
+		dev_err(&dev->pdev->dev, "RoCE is not supported over SRIOV as yet\n");
 		return NULL;
 	}
 
+	num_ports = 0;
 	mlx4_foreach_ib_transport_port(i, dev)
 		num_ports++;
 
@@ -1318,10 +1410,12 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
 	ibdev->ib_dev.detach_mcast	= mlx4_ib_mcg_detach;
 	ibdev->ib_dev.process_mad	= mlx4_ib_process_mad;
 
-	ibdev->ib_dev.alloc_fmr		= mlx4_ib_fmr_alloc;
-	ibdev->ib_dev.map_phys_fmr	= mlx4_ib_map_phys_fmr;
-	ibdev->ib_dev.unmap_fmr		= mlx4_ib_unmap_fmr;
-	ibdev->ib_dev.dealloc_fmr	= mlx4_ib_fmr_dealloc;
+	if (!mlx4_is_slave(ibdev->dev)) {
+		ibdev->ib_dev.alloc_fmr		= mlx4_ib_fmr_alloc;
+		ibdev->ib_dev.map_phys_fmr	= mlx4_ib_map_phys_fmr;
+		ibdev->ib_dev.unmap_fmr		= mlx4_ib_unmap_fmr;
+		ibdev->ib_dev.dealloc_fmr	= mlx4_ib_fmr_dealloc;
+	}
 
 	if (dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC) {
 		ibdev->ib_dev.alloc_xrcd = mlx4_ib_alloc_xrcd;
@@ -1357,11 +1451,14 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
 	if (mlx4_ib_mad_init(ibdev))
 		goto err_reg;
 
+	if (mlx4_ib_init_sriov(ibdev))
+		goto err_mad;
+
 	if (dev->caps.flags & MLX4_DEV_CAP_FLAG_IBOE && !iboe->nb.notifier_call) {
 		iboe->nb.notifier_call = mlx4_ib_netdev_event;
 		err = register_netdevice_notifier(&iboe->nb);
 		if (err)
-			goto err_reg;
+			goto err_sriov;
 	}
 
 	for (j = 0; j < ARRAY_SIZE(mlx4_class_attributes); ++j) {
@@ -1372,6 +1469,18 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
 
 	ibdev->ib_active = true;
 
+	if (mlx4_is_mfunc(ibdev->dev))
+		init_pkeys(ibdev);
+
+	/* create paravirt contexts for any VFs which are active */
+	if (mlx4_is_master(ibdev->dev)) {
+		for (j = 0; j < MLX4_MFUNC_MAX; j++) {
+			if (j == mlx4_master_func_num(ibdev->dev))
+				continue;
+			if (mlx4_is_slave_active(ibdev->dev, j))
+				do_slave_init(ibdev, j, 1);
+		}
+	}
 	return ibdev;
 
 err_notif:
@@ -1379,6 +1488,12 @@ err_notif:
 		pr_warn("failure unregistering notifier\n");
 	flush_workqueue(wq);
 
+err_sriov:
+	mlx4_ib_close_sriov(ibdev);
+
+err_mad:
+	mlx4_ib_mad_cleanup(ibdev);
+
 err_reg:
 	ib_unregister_device(&ibdev->ib_dev);
 
@@ -1407,6 +1522,7 @@ static void mlx4_ib_remove(struct mlx4_dev *dev, void *ibdev_ptr)
 	struct mlx4_ib_dev *ibdev = ibdev_ptr;
 	int p;
 
+	mlx4_ib_close_sriov(ibdev);
 	mlx4_ib_mad_cleanup(ibdev);
 	ib_unregister_device(&ibdev->ib_dev);
 	if (ibdev->iboe.nb.notifier_call) {
@@ -1428,6 +1544,51 @@ static void mlx4_ib_remove(struct mlx4_dev *dev, void *ibdev_ptr)
 	ib_dealloc_device(&ibdev->ib_dev);
 }
 
+static void do_slave_init(struct mlx4_ib_dev *ibdev, int slave, int do_init)
+{
+	struct mlx4_ib_demux_work **dm = NULL;
+	struct mlx4_dev *dev = ibdev->dev;
+	int i;
+	unsigned long flags;
+
+	if (!mlx4_is_master(dev))
+		return;
+
+	dm = kcalloc(dev->caps.num_ports, sizeof *dm, GFP_ATOMIC);
+	if (!dm) {
+		pr_err("failed to allocate memory for tunneling qp update\n");
+		goto out;
+	}
+
+	for (i = 0; i < dev->caps.num_ports; i++) {
+		dm[i] = kmalloc(sizeof (struct mlx4_ib_demux_work), GFP_ATOMIC);
+		if (!dm[i]) {
+			pr_err("failed to allocate memory for tunneling qp update work struct\n");
+			for (i = 0; i < dev->caps.num_ports; i++) {
+				if (dm[i])
+					kfree(dm[i]);
+			}
+			goto out;
+		}
+	}
+	/* initialize or tear down tunnel QPs for the slave */
+	for (i = 0; i < dev->caps.num_ports; i++) {
+		INIT_WORK(&dm[i]->work, mlx4_ib_tunnels_update_work);
+		dm[i]->port = i + 1;
+		dm[i]->slave = slave;
+		dm[i]->do_init = do_init;
+		dm[i]->dev = ibdev;
+		spin_lock_irqsave(&ibdev->sriov.going_down_lock, flags);
+		if (!ibdev->sriov.is_going_down)
+			queue_work(ibdev->sriov.demux[i].ud_wq, &dm[i]->work);
+		spin_unlock_irqrestore(&ibdev->sriov.going_down_lock, flags);
+	}
+out:
+	if (dm)
+		kfree(dm);
+	return;
+}
+
 static void mlx4_ib_event(struct mlx4_dev *dev, void *ibdev_ptr,
 			  enum mlx4_dev_event event, unsigned long param)
 {
@@ -1435,22 +1596,28 @@ static void mlx4_ib_event(struct mlx4_dev *dev, void *ibdev_ptr,
 	struct mlx4_ib_dev *ibdev = to_mdev((struct ib_device *) ibdev_ptr);
 	struct mlx4_eqe *eqe = NULL;
 	struct ib_event_work *ew;
-	int port = 0;
+	int p = 0;
 
 	if (event == MLX4_DEV_EVENT_PORT_MGMT_CHANGE)
 		eqe = (struct mlx4_eqe *)param;
 	else
-		port = (u8)param;
-
-	if (port > ibdev->num_ports)
-		return;
+		p = (int) param;
 
 	switch (event) {
 	case MLX4_DEV_EVENT_PORT_UP:
+		if (p > ibdev->num_ports)
+			return;
+		if (mlx4_is_master(dev) &&
+		    rdma_port_get_link_layer(&ibdev->ib_dev, p) ==
+			IB_LINK_LAYER_INFINIBAND) {
+			mlx4_ib_invalidate_all_guid_record(ibdev, p);
+		}
 		ibev.event = IB_EVENT_PORT_ACTIVE;
 		break;
 
 	case MLX4_DEV_EVENT_PORT_DOWN:
+		if (p > ibdev->num_ports)
+			return;
 		ibev.event = IB_EVENT_PORT_ERR;
 		break;
 
@@ -1469,7 +1636,21 @@ static void mlx4_ib_event(struct mlx4_dev *dev, void *ibdev_ptr,
 		INIT_WORK(&ew->work, handle_port_mgmt_change_event);
 		memcpy(&ew->ib_eqe, eqe, sizeof *eqe);
 		ew->ib_dev = ibdev;
-		handle_port_mgmt_change_event(&ew->work);
+		/* need to queue only for port owner, which uses GEN_EQE */
+		if (mlx4_is_master(dev))
+			queue_work(wq, &ew->work);
+		else
+			handle_port_mgmt_change_event(&ew->work);
+		return;
+
+	case MLX4_DEV_EVENT_SLAVE_INIT:
+		/* here, p is the slave id */
+		do_slave_init(ibdev, p, 1);
+		return;
+
+	case MLX4_DEV_EVENT_SLAVE_SHUTDOWN:
+		/* here, p is the slave id */
+		do_slave_init(ibdev, p, 0);
 		return;
 
 	default:
@@ -1477,7 +1658,7 @@ static void mlx4_ib_event(struct mlx4_dev *dev, void *ibdev_ptr,
 	}
 
 	ibev.device	      = ibdev_ptr;
-	ibev.element.port_num = port;
+	ibev.element.port_num = (u8) p;
 
 	ib_dispatch_event(&ibev);
 }
@@ -1497,18 +1678,28 @@ static int __init mlx4_ib_init(void)
 	if (!wq)
 		return -ENOMEM;
 
+	err = mlx4_ib_mcg_init();
+	if (err)
+		goto clean_wq;
+
 	err = mlx4_register_interface(&mlx4_ib_interface);
-	if (err) {
-		destroy_workqueue(wq);
-		return err;
-	}
+	if (err)
+		goto clean_mcg;
 
 	return 0;
+
+clean_mcg:
+	mlx4_ib_mcg_destroy();
+
+clean_wq:
+	destroy_workqueue(wq);
+	return err;
 }
 
 static void __exit mlx4_ib_cleanup(void)
 {
 	mlx4_unregister_interface(&mlx4_ib_interface);
+	mlx4_ib_mcg_destroy();
 	destroy_workqueue(wq);
 }
 
diff --git a/drivers/infiniband/hw/mlx4/mcg.c b/drivers/infiniband/hw/mlx4/mcg.c
new file mode 100644
index 0000000..3c3b54c
--- /dev/null
+++ b/drivers/infiniband/hw/mlx4/mcg.c
@@ -0,0 +1,1254 @@
+/*
+ * Copyright (c) 2012 Mellanox Technologies. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <rdma/ib_mad.h>
+#include <rdma/ib_smi.h>
+#include <rdma/ib_cache.h>
+#include <rdma/ib_sa.h>
+
+#include <linux/mlx4/cmd.h>
+#include <linux/rbtree.h>
+#include <linux/delay.h>
+
+#include "mlx4_ib.h"
+
+#define MAX_VFS		80
+#define MAX_PEND_REQS_PER_FUNC 4
+#define MAD_TIMEOUT_MS	2000
+
+#define mcg_warn(fmt, arg...)	pr_warn("MCG WARNING: " fmt, ##arg)
+#define mcg_error(fmt, arg...)	pr_err(fmt, ##arg)
+#define mcg_warn_group(group, format, arg...) \
+	pr_warn("%s-%d: %16s (port %d): WARNING: " format, __func__, __LINE__,\
+	(group)->name, group->demux->port, ## arg)
+
+#define mcg_error_group(group, format, arg...) \
+	pr_err("  %16s: " format, (group)->name, ## arg)
+
+
+static union ib_gid mgid0;
+
+static struct workqueue_struct *clean_wq;
+
+enum mcast_state {
+	MCAST_NOT_MEMBER = 0,
+	MCAST_MEMBER,
+};
+
+enum mcast_group_state {
+	MCAST_IDLE,
+	MCAST_JOIN_SENT,
+	MCAST_LEAVE_SENT,
+	MCAST_RESP_READY
+};
+
+struct mcast_member {
+	enum mcast_state state;
+	uint8_t			join_state;
+	int			num_pend_reqs;
+	struct list_head	pending;
+};
+
+struct ib_sa_mcmember_data {
+	union ib_gid	mgid;
+	union ib_gid	port_gid;
+	__be32		qkey;
+	__be16		mlid;
+	u8		mtusel_mtu;
+	u8		tclass;
+	__be16		pkey;
+	u8		ratesel_rate;
+	u8		lifetmsel_lifetm;
+	__be32		sl_flowlabel_hoplimit;
+	u8		scope_join_state;
+	u8		proxy_join;
+	u8		reserved[2];
+};
+
+struct mcast_group {
+	struct ib_sa_mcmember_data rec;
+	struct rb_node		node;
+	struct list_head	mgid0_list;
+	struct mlx4_ib_demux_ctx *demux;
+	struct mcast_member	func[MAX_VFS];
+	struct mutex		lock;
+	struct work_struct	work;
+	struct list_head	pending_list;
+	int			members[3];
+	enum mcast_group_state	state;
+	enum mcast_group_state	prev_state;
+	struct ib_sa_mad	response_sa_mad;
+	__be64			last_req_tid;
+
+	char			name[33]; /* MGID string */
+	struct device_attribute	dentry;
+
+	/* refcount is the reference count for the following:
+	   1. Each queued request
+	   2. Each invocation of the worker thread
+	   3. Membership of the port at the SA
+	*/
+	atomic_t		refcount;
+
+	/* delayed work to clean pending SM request */
+	struct delayed_work	timeout_work;
+	struct list_head	cleanup_list;
+};
+
+struct mcast_req {
+	int			func;
+	struct ib_sa_mad	sa_mad;
+	struct list_head	group_list;
+	struct list_head	func_list;
+	struct mcast_group	*group;
+	int			clean;
+};
+
+
+#define safe_atomic_dec(ref) \
+	do {\
+		if (atomic_dec_and_test(ref)) \
+			mcg_warn_group(group, "did not expect to reach zero\n"); \
+	} while (0)
+
+static const char *get_state_string(enum mcast_group_state state)
+{
+	switch (state) {
+	case MCAST_IDLE:
+		return "MCAST_IDLE";
+	case MCAST_JOIN_SENT:
+		return "MCAST_JOIN_SENT";
+	case MCAST_LEAVE_SENT:
+		return "MCAST_LEAVE_SENT";
+	case MCAST_RESP_READY:
+		return "MCAST_RESP_READY";
+	}
+	return "Invalid State";
+}
+
+static struct mcast_group *mcast_find(struct mlx4_ib_demux_ctx *ctx,
+				      union ib_gid *mgid)
+{
+	struct rb_node *node = ctx->mcg_table.rb_node;
+	struct mcast_group *group;
+	int ret;
+
+	while (node) {
+		group = rb_entry(node, struct mcast_group, node);
+		ret = memcmp(mgid->raw, group->rec.mgid.raw, sizeof *mgid);
+		if (!ret)
+			return group;
+
+		if (ret < 0)
+			node = node->rb_left;
+		else
+			node = node->rb_right;
+	}
+	return NULL;
+}
+
+static struct mcast_group *mcast_insert(struct mlx4_ib_demux_ctx *ctx,
+					struct mcast_group *group)
+{
+	struct rb_node **link = &ctx->mcg_table.rb_node;
+	struct rb_node *parent = NULL;
+	struct mcast_group *cur_group;
+	int ret;
+
+	while (*link) {
+		parent = *link;
+		cur_group = rb_entry(parent, struct mcast_group, node);
+
+		ret = memcmp(group->rec.mgid.raw, cur_group->rec.mgid.raw,
+			     sizeof group->rec.mgid);
+		if (ret < 0)
+			link = &(*link)->rb_left;
+		else if (ret > 0)
+			link = &(*link)->rb_right;
+		else
+			return cur_group;
+	}
+	rb_link_node(&group->node, parent, link);
+	rb_insert_color(&group->node, &ctx->mcg_table);
+	return NULL;
+}
+
+static int send_mad_to_wire(struct mlx4_ib_demux_ctx *ctx, struct ib_mad *mad)
+{
+	struct mlx4_ib_dev *dev = ctx->dev;
+	struct ib_ah_attr	ah_attr;
+
+	spin_lock(&dev->sm_lock);
+	if (!dev->sm_ah[ctx->port - 1]) {
+		/* port is not yet Active, sm_ah not ready */
+		spin_unlock(&dev->sm_lock);
+		return -EAGAIN;
+	}
+	mlx4_ib_query_ah(dev->sm_ah[ctx->port - 1], &ah_attr);
+	spin_unlock(&dev->sm_lock);
+	return mlx4_ib_send_to_wire(dev, mlx4_master_func_num(dev->dev), ctx->port,
+				    IB_QPT_GSI, 0, 1, IB_QP1_QKEY, &ah_attr, mad);
+}
+
+static int send_mad_to_slave(int slave, struct mlx4_ib_demux_ctx *ctx,
+			     struct ib_mad *mad)
+{
+	struct mlx4_ib_dev *dev = ctx->dev;
+	struct ib_mad_agent *agent = dev->send_agent[ctx->port - 1][1];
+	struct ib_wc wc;
+	struct ib_ah_attr ah_attr;
+
+	/* Our agent might not yet be registered when mads start to arrive */
+	if (!agent)
+		return -EAGAIN;
+
+	ib_query_ah(dev->sm_ah[ctx->port - 1], &ah_attr);
+
+	wc.pkey_index = 0;
+	wc.sl = 0;
+	wc.dlid_path_bits = 0;
+	wc.port_num = ctx->port;
+	wc.slid = ah_attr.dlid;  /* opensm lid */
+	wc.src_qp = 1;
+	return mlx4_ib_send_to_slave(dev, slave, ctx->port, IB_QPT_GSI, &wc, NULL, mad);
+}
+
+static int send_join_to_wire(struct mcast_group *group, struct ib_sa_mad *sa_mad)
+{
+	struct ib_sa_mad mad;
+	struct ib_sa_mcmember_data *sa_mad_data = (struct ib_sa_mcmember_data *)&mad.data;
+	int ret;
+
+	/* we rely on a mad request as arrived from a VF */
+	memcpy(&mad, sa_mad, sizeof mad);
+
+	/* fix port GID to be the real one (slave 0) */
+	sa_mad_data->port_gid.global.interface_id = group->demux->guid_cache[0];
+
+	/* assign our own TID */
+	mad.mad_hdr.tid = mlx4_ib_get_new_demux_tid(group->demux);
+	group->last_req_tid = mad.mad_hdr.tid; /* keep it for later validation */
+
+	ret = send_mad_to_wire(group->demux, (struct ib_mad *)&mad);
+	/* set timeout handler */
+	if (!ret) {
+		/* calls mlx4_ib_mcg_timeout_handler */
+		queue_delayed_work(group->demux->mcg_wq, &group->timeout_work,
+				msecs_to_jiffies(MAD_TIMEOUT_MS));
+	}
+
+	return ret;
+}
+
+static int send_leave_to_wire(struct mcast_group *group, u8 join_state)
+{
+	struct ib_sa_mad mad;
+	struct ib_sa_mcmember_data *sa_data = (struct ib_sa_mcmember_data *)&mad.data;
+	int ret;
+
+	memset(&mad, 0, sizeof mad);
+	mad.mad_hdr.base_version = 1;
+	mad.mad_hdr.mgmt_class = IB_MGMT_CLASS_SUBN_ADM;
+	mad.mad_hdr.class_version = 2;
+	mad.mad_hdr.method = IB_SA_METHOD_DELETE;
+	mad.mad_hdr.status = cpu_to_be16(0);
+	mad.mad_hdr.class_specific = cpu_to_be16(0);
+	mad.mad_hdr.tid = mlx4_ib_get_new_demux_tid(group->demux);
+	group->last_req_tid = mad.mad_hdr.tid; /* keep it for later validation */
+	mad.mad_hdr.attr_id = cpu_to_be16(IB_SA_ATTR_MC_MEMBER_REC);
+	mad.mad_hdr.attr_mod = cpu_to_be32(0);
+	mad.sa_hdr.sm_key = 0x0;
+	mad.sa_hdr.attr_offset = cpu_to_be16(7);
+	mad.sa_hdr.comp_mask = IB_SA_MCMEMBER_REC_MGID |
+		IB_SA_MCMEMBER_REC_PORT_GID | IB_SA_MCMEMBER_REC_JOIN_STATE;
+
+	*sa_data = group->rec;
+	sa_data->scope_join_state = join_state;
+
+	ret = send_mad_to_wire(group->demux, (struct ib_mad *)&mad);
+	if (ret)
+		group->state = MCAST_IDLE;
+
+	/* set timeout handler */
+	if (!ret) {
+		/* calls mlx4_ib_mcg_timeout_handler */
+		queue_delayed_work(group->demux->mcg_wq, &group->timeout_work,
+				msecs_to_jiffies(MAD_TIMEOUT_MS));
+	}
+
+	return ret;
+}
+
+static int send_reply_to_slave(int slave, struct mcast_group *group,
+		struct ib_sa_mad *req_sa_mad, u16 status)
+{
+	struct ib_sa_mad mad;
+	struct ib_sa_mcmember_data *sa_data = (struct ib_sa_mcmember_data *)&mad.data;
+	struct ib_sa_mcmember_data *req_sa_data = (struct ib_sa_mcmember_data *)&req_sa_mad->data;
+	int ret;
+
+	memset(&mad, 0, sizeof mad);
+	mad.mad_hdr.base_version = 1;
+	mad.mad_hdr.mgmt_class = IB_MGMT_CLASS_SUBN_ADM;
+	mad.mad_hdr.class_version = 2;
+	mad.mad_hdr.method = IB_MGMT_METHOD_GET_RESP;
+	mad.mad_hdr.status = cpu_to_be16(status);
+	mad.mad_hdr.class_specific = cpu_to_be16(0);
+	mad.mad_hdr.tid = req_sa_mad->mad_hdr.tid;
+	*(u8 *)&mad.mad_hdr.tid = 0; /* resetting tid to 0 */
+	mad.mad_hdr.attr_id = cpu_to_be16(IB_SA_ATTR_MC_MEMBER_REC);
+	mad.mad_hdr.attr_mod = cpu_to_be32(0);
+	mad.sa_hdr.sm_key = req_sa_mad->sa_hdr.sm_key;
+	mad.sa_hdr.attr_offset = cpu_to_be16(7);
+	mad.sa_hdr.comp_mask = 0; /* ignored on responses, see IBTA spec */
+
+	*sa_data = group->rec;
+
+	/* reconstruct VF's requested join_state and port_gid */
+	sa_data->scope_join_state &= 0xf0;
+	sa_data->scope_join_state |= (group->func[slave].join_state & 0x0f);
+	memcpy(&sa_data->port_gid, &req_sa_data->port_gid, sizeof req_sa_data->port_gid);
+
+	ret = send_mad_to_slave(slave, group->demux, (struct ib_mad *)&mad);
+	return ret;
+}
+
+static int check_selector(ib_sa_comp_mask comp_mask,
+			  ib_sa_comp_mask selector_mask,
+			  ib_sa_comp_mask value_mask,
+			  u8 src_value, u8 dst_value)
+{
+	int err;
+	u8 selector = dst_value >> 6;
+	dst_value &= 0x3f;
+	src_value &= 0x3f;
+
+	if (!(comp_mask & selector_mask) || !(comp_mask & value_mask))
+		return 0;
+
+	switch (selector) {
+	case IB_SA_GT:
+		err = (src_value <= dst_value);
+		break;
+	case IB_SA_LT:
+		err = (src_value >= dst_value);
+		break;
+	case IB_SA_EQ:
+		err = (src_value != dst_value);
+		break;
+	default:
+		err = 0;
+		break;
+	}
+
+	return err;
+}
+
+static u16 cmp_rec(struct ib_sa_mcmember_data *src,
+		   struct ib_sa_mcmember_data *dst, ib_sa_comp_mask comp_mask)
+{
+	/* src is group record, dst is request record */
+	/* MGID must already match */
+	/* Port_GID we always replace to our Port_GID, so it is a match */
+
+#define MAD_STATUS_REQ_INVALID 0x0200
+	if (comp_mask & IB_SA_MCMEMBER_REC_QKEY && src->qkey != dst->qkey)
+		return MAD_STATUS_REQ_INVALID;
+	if (comp_mask & IB_SA_MCMEMBER_REC_MLID && src->mlid != dst->mlid)
+		return MAD_STATUS_REQ_INVALID;
+	if (check_selector(comp_mask, IB_SA_MCMEMBER_REC_MTU_SELECTOR,
+				 IB_SA_MCMEMBER_REC_MTU,
+				 src->mtusel_mtu, dst->mtusel_mtu))
+		return MAD_STATUS_REQ_INVALID;
+	if (comp_mask & IB_SA_MCMEMBER_REC_TRAFFIC_CLASS &&
+	    src->tclass != dst->tclass)
+		return MAD_STATUS_REQ_INVALID;
+	if (comp_mask & IB_SA_MCMEMBER_REC_PKEY && src->pkey != dst->pkey)
+		return MAD_STATUS_REQ_INVALID;
+	if (check_selector(comp_mask, IB_SA_MCMEMBER_REC_RATE_SELECTOR,
+				 IB_SA_MCMEMBER_REC_RATE,
+				 src->ratesel_rate, dst->ratesel_rate))
+		return MAD_STATUS_REQ_INVALID;
+	if (check_selector(comp_mask,
+				 IB_SA_MCMEMBER_REC_PACKET_LIFE_TIME_SELECTOR,
+				 IB_SA_MCMEMBER_REC_PACKET_LIFE_TIME,
+				 src->lifetmsel_lifetm, dst->lifetmsel_lifetm))
+		return MAD_STATUS_REQ_INVALID;
+	if (comp_mask & IB_SA_MCMEMBER_REC_SL &&
+			(be32_to_cpu(src->sl_flowlabel_hoplimit) & 0xf0000000) !=
+			(be32_to_cpu(dst->sl_flowlabel_hoplimit) & 0xf0000000))
+		return MAD_STATUS_REQ_INVALID;
+	if (comp_mask & IB_SA_MCMEMBER_REC_FLOW_LABEL &&
+			(be32_to_cpu(src->sl_flowlabel_hoplimit) & 0x0fffff00) !=
+			(be32_to_cpu(dst->sl_flowlabel_hoplimit) & 0x0fffff00))
+		return MAD_STATUS_REQ_INVALID;
+	if (comp_mask & IB_SA_MCMEMBER_REC_HOP_LIMIT &&
+			(be32_to_cpu(src->sl_flowlabel_hoplimit) & 0x000000ff) !=
+			(be32_to_cpu(dst->sl_flowlabel_hoplimit) & 0x000000ff))
+		return MAD_STATUS_REQ_INVALID;
+	if (comp_mask & IB_SA_MCMEMBER_REC_SCOPE &&
+			(src->scope_join_state & 0xf0) !=
+			(dst->scope_join_state & 0xf0))
+		return MAD_STATUS_REQ_INVALID;
+
+	/* join_state checked separately, proxy_join ignored */
+
+	return 0;
+}
+
+/* release group, return 1 if this was last release and group is destroyed
+ * timout work is canceled sync */
+static int release_group(struct mcast_group *group, int from_timeout_handler)
+{
+	struct mlx4_ib_demux_ctx *ctx = group->demux;
+	int nzgroup;
+
+	mutex_lock(&ctx->mcg_table_lock);
+	mutex_lock(&group->lock);
+	if (atomic_dec_and_test(&group->refcount)) {
+		if (!from_timeout_handler) {
+			if (group->state != MCAST_IDLE &&
+			    !cancel_delayed_work(&group->timeout_work)) {
+				atomic_inc(&group->refcount);
+				mutex_unlock(&group->lock);
+				mutex_unlock(&ctx->mcg_table_lock);
+				return 0;
+			}
+		}
+
+		nzgroup = memcmp(&group->rec.mgid, &mgid0, sizeof mgid0);
+		if (nzgroup)
+			del_sysfs_port_mcg_attr(ctx->dev, ctx->port, &group->dentry.attr);
+		if (!list_empty(&group->pending_list))
+			mcg_warn_group(group, "releasing a group with non empty pending list\n");
+		if (nzgroup)
+			rb_erase(&group->node, &ctx->mcg_table);
+		list_del_init(&group->mgid0_list);
+		mutex_unlock(&group->lock);
+		mutex_unlock(&ctx->mcg_table_lock);
+		kfree(group);
+		return 1;
+	} else {
+		mutex_unlock(&group->lock);
+		mutex_unlock(&ctx->mcg_table_lock);
+	}
+	return 0;
+}
+
+static void adjust_membership(struct mcast_group *group, u8 join_state, int inc)
+{
+	int i;
+
+	for (i = 0; i < 3; i++, join_state >>= 1)
+		if (join_state & 0x1)
+			group->members[i] += inc;
+}
+
+static u8 get_leave_state(struct mcast_group *group)
+{
+	u8 leave_state = 0;
+	int i;
+
+	for (i = 0; i < 3; i++)
+		if (!group->members[i])
+			leave_state |= (1 << i);
+
+	return leave_state & (group->rec.scope_join_state & 7);
+}
+
+static int join_group(struct mcast_group *group, int slave, u8 join_mask)
+{
+	int ret = 0;
+	u8 join_state;
+
+	/* remove bits that slave is already member of, and adjust */
+	join_state = join_mask & (~group->func[slave].join_state);
+	adjust_membership(group, join_state, 1);
+	group->func[slave].join_state |= join_state;
+	if (group->func[slave].state != MCAST_MEMBER && join_state) {
+		group->func[slave].state = MCAST_MEMBER;
+		ret = 1;
+	}
+	return ret;
+}
+
+static int leave_group(struct mcast_group *group, int slave, u8 leave_state)
+{
+	int ret = 0;
+
+	adjust_membership(group, leave_state, -1);
+	group->func[slave].join_state &= ~leave_state;
+	if (!group->func[slave].join_state) {
+		group->func[slave].state = MCAST_NOT_MEMBER;
+		ret = 1;
+	}
+	return ret;
+}
+
+static int check_leave(struct mcast_group *group, int slave, u8 leave_mask)
+{
+	if (group->func[slave].state != MCAST_MEMBER)
+		return MAD_STATUS_REQ_INVALID;
+
+	/* make sure we're not deleting unset bits */
+	if (~group->func[slave].join_state & leave_mask)
+		return MAD_STATUS_REQ_INVALID;
+
+	if (!leave_mask)
+		return MAD_STATUS_REQ_INVALID;
+
+	return 0;
+}
+
+static void mlx4_ib_mcg_timeout_handler(struct work_struct *work)
+{
+	struct delayed_work *delay = to_delayed_work(work);
+	struct mcast_group *group;
+	struct mcast_req *req = NULL;
+
+	group = container_of(delay, typeof(*group), timeout_work);
+
+	mutex_lock(&group->lock);
+	if (group->state == MCAST_JOIN_SENT) {
+		if (!list_empty(&group->pending_list)) {
+			req = list_first_entry(&group->pending_list, struct mcast_req, group_list);
+			list_del(&req->group_list);
+			list_del(&req->func_list);
+			--group->func[req->func].num_pend_reqs;
+			mutex_unlock(&group->lock);
+			kfree(req);
+			if (memcmp(&group->rec.mgid, &mgid0, sizeof mgid0)) {
+				if (release_group(group, 1))
+					return;
+			} else {
+				kfree(group);
+				return;
+			}
+			mutex_lock(&group->lock);
+		} else
+			mcg_warn_group(group, "DRIVER BUG\n");
+	} else if (group->state == MCAST_LEAVE_SENT) {
+		if (group->rec.scope_join_state & 7)
+			group->rec.scope_join_state &= 0xf8;
+		group->state = MCAST_IDLE;
+		mutex_unlock(&group->lock);
+		if (release_group(group, 1))
+			return;
+		mutex_lock(&group->lock);
+	} else
+		mcg_warn_group(group, "invalid state %s\n", get_state_string(group->state));
+	group->state = MCAST_IDLE;
+	atomic_inc(&group->refcount);
+	if (!queue_work(group->demux->mcg_wq, &group->work))
+		safe_atomic_dec(&group->refcount);
+
+	mutex_unlock(&group->lock);
+}
+
+static int handle_leave_req(struct mcast_group *group, u8 leave_mask,
+			    struct mcast_req *req)
+{
+	u16 status;
+
+	if (req->clean)
+		leave_mask = group->func[req->func].join_state;
+
+	status = check_leave(group, req->func, leave_mask);
+	if (!status)
+		leave_group(group, req->func, leave_mask);
+
+	if (!req->clean)
+		send_reply_to_slave(req->func, group, &req->sa_mad, status);
+	--group->func[req->func].num_pend_reqs;
+	list_del(&req->group_list);
+	list_del(&req->func_list);
+	kfree(req);
+	return 1;
+}
+
+static int handle_join_req(struct mcast_group *group, u8 join_mask,
+			   struct mcast_req *req)
+{
+	u8 group_join_state = group->rec.scope_join_state & 7;
+	int ref = 0;
+	u16 status;
+	struct ib_sa_mcmember_data *sa_data = (struct ib_sa_mcmember_data *)req->sa_mad.data;
+
+	if (join_mask == (group_join_state & join_mask)) {
+		/* port's membership need not change */
+		status = cmp_rec(&group->rec, sa_data, req->sa_mad.sa_hdr.comp_mask);
+		if (!status)
+			join_group(group, req->func, join_mask);
+
+		--group->func[req->func].num_pend_reqs;
+		send_reply_to_slave(req->func, group, &req->sa_mad, status);
+		list_del(&req->group_list);
+		list_del(&req->func_list);
+		kfree(req);
+		++ref;
+	} else {
+		/* port's membership needs to be updated */
+		group->prev_state = group->state;
+		if (send_join_to_wire(group, &req->sa_mad)) {
+			--group->func[req->func].num_pend_reqs;
+			list_del(&req->group_list);
+			list_del(&req->func_list);
+			kfree(req);
+			ref = 1;
+			group->state = group->prev_state;
+		} else
+			group->state = MCAST_JOIN_SENT;
+	}
+
+	return ref;
+}
+
+static void mlx4_ib_mcg_work_handler(struct work_struct *work)
+{
+	struct mcast_group *group;
+	struct mcast_req *req = NULL;
+	struct ib_sa_mcmember_data *sa_data;
+	u8 req_join_state;
+	int rc = 1; /* release_count - this is for the scheduled work */
+	u16 status;
+	u8 method;
+
+	group = container_of(work, typeof(*group), work);
+
+	mutex_lock(&group->lock);
+
+	/* First, let's see if a response from SM is waiting regarding this group.
+	 * If so, we need to update the group's REC. If this is a bad response, we
+	 * may need to send a bad response to a VF waiting for it. If VF is waiting
+	 * and this is a good response, the VF will be answered later in this func. */
+	if (group->state == MCAST_RESP_READY) {
+		/* cancels mlx4_ib_mcg_timeout_handler */
+		cancel_delayed_work(&group->timeout_work);
+		status = be16_to_cpu(group->response_sa_mad.mad_hdr.status);
+		method = group->response_sa_mad.mad_hdr.method;
+		if (group->last_req_tid != group->response_sa_mad.mad_hdr.tid) {
+			mcg_warn_group(group, "Got MAD response to existing MGID but wrong TID, dropping. Resp TID=%llx, group TID=%llx\n",
+				be64_to_cpu(group->response_sa_mad.mad_hdr.tid),
+				be64_to_cpu(group->last_req_tid));
+			group->state = group->prev_state;
+			goto process_requests;
+		}
+		if (status) {
+			if (!list_empty(&group->pending_list))
+				req = list_first_entry(&group->pending_list,
+						struct mcast_req, group_list);
+			if ((method == IB_MGMT_METHOD_GET_RESP)) {
+					if (req) {
+						send_reply_to_slave(req->func, group, &req->sa_mad, status);
+						--group->func[req->func].num_pend_reqs;
+						list_del(&req->group_list);
+						list_del(&req->func_list);
+						kfree(req);
+						++rc;
+					} else
+						mcg_warn_group(group, "no request for failed join\n");
+			} else if (method == IB_SA_METHOD_DELETE_RESP && group->demux->flushing)
+				++rc;
+		} else {
+			u8 resp_join_state;
+			u8 cur_join_state;
+
+			resp_join_state = ((struct ib_sa_mcmember_data *)
+						group->response_sa_mad.data)->scope_join_state & 7;
+			cur_join_state = group->rec.scope_join_state & 7;
+
+			if (method == IB_MGMT_METHOD_GET_RESP) {
+				/* successfull join */
+				if (!cur_join_state && resp_join_state)
+					--rc;
+			} else if (!resp_join_state)
+					++rc;
+			memcpy(&group->rec, group->response_sa_mad.data, sizeof group->rec);
+		}
+		group->state = MCAST_IDLE;
+	}
+
+process_requests:
+	/* We should now go over pending join/leave requests, as long as we are idle. */
+	while (!list_empty(&group->pending_list) && group->state == MCAST_IDLE) {
+		req = list_first_entry(&group->pending_list, struct mcast_req,
+				       group_list);
+		sa_data = (struct ib_sa_mcmember_data *)req->sa_mad.data;
+		req_join_state = sa_data->scope_join_state & 0x7;
+
+		/* For a leave request, we will immediately answer the VF, and
+		 * update our internal counters. The actual leave will be sent
+		 * to SM later, if at all needed. We dequeue the request now. */
+		if (req->sa_mad.mad_hdr.method == IB_SA_METHOD_DELETE)
+			rc += handle_leave_req(group, req_join_state, req);
+		else
+			rc += handle_join_req(group, req_join_state, req);
+	}
+
+	/* Handle leaves */
+	if (group->state == MCAST_IDLE) {
+		req_join_state = get_leave_state(group);
+		if (req_join_state) {
+			group->rec.scope_join_state &= ~req_join_state;
+			group->prev_state = group->state;
+			if (send_leave_to_wire(group, req_join_state)) {
+				group->state = group->prev_state;
+				++rc;
+			} else
+				group->state = MCAST_LEAVE_SENT;
+		}
+	}
+
+	if (!list_empty(&group->pending_list) && group->state == MCAST_IDLE)
+		goto process_requests;
+	mutex_unlock(&group->lock);
+
+	while (rc--)
+		release_group(group, 0);
+}
+
+static struct mcast_group *search_relocate_mgid0_group(struct mlx4_ib_demux_ctx *ctx,
+						       __be64 tid,
+						       union ib_gid *new_mgid)
+{
+	struct mcast_group *group = NULL, *cur_group;
+	struct mcast_req *req;
+	struct list_head *pos;
+	struct list_head *n;
+
+	mutex_lock(&ctx->mcg_table_lock);
+	list_for_each_safe(pos, n, &ctx->mcg_mgid0_list) {
+		group = list_entry(pos, struct mcast_group, mgid0_list);
+		mutex_lock(&group->lock);
+		if (group->last_req_tid == tid) {
+			if (memcmp(new_mgid, &mgid0, sizeof mgid0)) {
+				group->rec.mgid = *new_mgid;
+				sprintf(group->name, "%016llx%016llx",
+						be64_to_cpu(group->rec.mgid.global.subnet_prefix),
+						be64_to_cpu(group->rec.mgid.global.interface_id));
+				list_del_init(&group->mgid0_list);
+				cur_group = mcast_insert(ctx, group);
+				if (cur_group) {
+					/* A race between our code and SM. Silently cleaning the new one */
+					req = list_first_entry(&group->pending_list,
+							       struct mcast_req, group_list);
+					--group->func[req->func].num_pend_reqs;
+					list_del(&req->group_list);
+					list_del(&req->func_list);
+					kfree(req);
+					mutex_unlock(&group->lock);
+					mutex_unlock(&ctx->mcg_table_lock);
+					release_group(group, 0);
+					return NULL;
+				}
+
+				atomic_inc(&group->refcount);
+				add_sysfs_port_mcg_attr(ctx->dev, ctx->port, &group->dentry.attr);
+				mutex_unlock(&group->lock);
+				mutex_unlock(&ctx->mcg_table_lock);
+				return group;
+			} else {
+				struct mcast_req *tmp1, *tmp2;
+
+				list_del(&group->mgid0_list);
+				if (!list_empty(&group->pending_list) && group->state != MCAST_IDLE)
+					cancel_delayed_work_sync(&group->timeout_work);
+
+				list_for_each_entry_safe(tmp1, tmp2, &group->pending_list, group_list) {
+					list_del(&tmp1->group_list);
+					kfree(tmp1);
+				}
+				mutex_unlock(&group->lock);
+				mutex_unlock(&ctx->mcg_table_lock);
+				kfree(group);
+				return NULL;
+			}
+		}
+		mutex_unlock(&group->lock);
+	}
+	mutex_unlock(&ctx->mcg_table_lock);
+
+	return NULL;
+}
+
+static ssize_t sysfs_show_group(struct device *dev,
+		struct device_attribute *attr, char *buf);
+
+static struct mcast_group *acquire_group(struct mlx4_ib_demux_ctx *ctx,
+					 union ib_gid *mgid, int create,
+					 gfp_t gfp_mask)
+{
+	struct mcast_group *group, *cur_group;
+	int is_mgid0;
+	int i;
+
+	is_mgid0 = !memcmp(&mgid0, mgid, sizeof mgid0);
+	if (!is_mgid0) {
+		group = mcast_find(ctx, mgid);
+		if (group)
+			goto found;
+	}
+
+	if (!create)
+		return ERR_PTR(-ENOENT);
+
+	group = kzalloc(sizeof *group, gfp_mask);
+	if (!group)
+		return ERR_PTR(-ENOMEM);
+
+	group->demux = ctx;
+	group->rec.mgid = *mgid;
+	INIT_LIST_HEAD(&group->pending_list);
+	INIT_LIST_HEAD(&group->mgid0_list);
+	for (i = 0; i < MAX_VFS; ++i)
+		INIT_LIST_HEAD(&group->func[i].pending);
+	INIT_WORK(&group->work, mlx4_ib_mcg_work_handler);
+	INIT_DELAYED_WORK(&group->timeout_work, mlx4_ib_mcg_timeout_handler);
+	mutex_init(&group->lock);
+	sprintf(group->name, "%016llx%016llx",
+			be64_to_cpu(group->rec.mgid.global.subnet_prefix),
+			be64_to_cpu(group->rec.mgid.global.interface_id));
+	sysfs_attr_init(&group->dentry.attr);
+	group->dentry.show = sysfs_show_group;
+	group->dentry.store = NULL;
+	group->dentry.attr.name = group->name;
+	group->dentry.attr.mode = 0400;
+	group->state = MCAST_IDLE;
+
+	if (is_mgid0) {
+		list_add(&group->mgid0_list, &ctx->mcg_mgid0_list);
+		goto found;
+	}
+
+	cur_group = mcast_insert(ctx, group);
+	if (cur_group) {
+		mcg_warn("group just showed up %s - confused\n", cur_group->name);
+		kfree(group);
+		return ERR_PTR(-EINVAL);
+	}
+
+	add_sysfs_port_mcg_attr(ctx->dev, ctx->port, &group->dentry.attr);
+
+found:
+	atomic_inc(&group->refcount);
+	return group;
+}
+
+static void queue_req(struct mcast_req *req)
+{
+	struct mcast_group *group = req->group;
+
+	atomic_inc(&group->refcount); /* for the request */
+	atomic_inc(&group->refcount); /* for scheduling the work */
+	list_add_tail(&req->group_list, &group->pending_list);
+	list_add_tail(&req->func_list, &group->func[req->func].pending);
+	/* calls mlx4_ib_mcg_work_handler */
+	if (!queue_work(group->demux->mcg_wq, &group->work))
+		safe_atomic_dec(&group->refcount);
+}
+
+int mlx4_ib_mcg_demux_handler(struct ib_device *ibdev, int port, int slave,
+			      struct ib_sa_mad *mad)
+{
+	struct mlx4_ib_dev *dev = to_mdev(ibdev);
+	struct ib_sa_mcmember_data *rec = (struct ib_sa_mcmember_data *)mad->data;
+	struct mlx4_ib_demux_ctx *ctx = &dev->sriov.demux[port - 1];
+	struct mcast_group *group;
+
+	switch (mad->mad_hdr.method) {
+	case IB_MGMT_METHOD_GET_RESP:
+	case IB_SA_METHOD_DELETE_RESP:
+		mutex_lock(&ctx->mcg_table_lock);
+		group = acquire_group(ctx, &rec->mgid, 0, GFP_KERNEL);
+		mutex_unlock(&ctx->mcg_table_lock);
+		if (IS_ERR(group)) {
+			if (mad->mad_hdr.method == IB_MGMT_METHOD_GET_RESP) {
+				__be64 tid = mad->mad_hdr.tid;
+				*(u8 *)(&tid) = (u8)slave; /* in group we kept the modified TID */
+				group = search_relocate_mgid0_group(ctx, tid, &rec->mgid);
+			} else
+				group = NULL;
+		}
+
+		if (!group)
+			return 1;
+
+		mutex_lock(&group->lock);
+		group->response_sa_mad = *mad;
+		group->prev_state = group->state;
+		group->state = MCAST_RESP_READY;
+		/* calls mlx4_ib_mcg_work_handler */
+		atomic_inc(&group->refcount);
+		if (!queue_work(ctx->mcg_wq, &group->work))
+			safe_atomic_dec(&group->refcount);
+		mutex_unlock(&group->lock);
+		release_group(group, 0);
+		return 1; /* consumed */
+	case IB_MGMT_METHOD_SET:
+	case IB_SA_METHOD_GET_TABLE:
+	case IB_SA_METHOD_GET_TABLE_RESP:
+	case IB_SA_METHOD_DELETE:
+		return 0; /* not consumed, pass-through to guest over tunnel */
+	default:
+		mcg_warn("In demux, port %d: unexpected MCMember method: 0x%x, dropping\n",
+			port, mad->mad_hdr.method);
+		return 1; /* consumed */
+	}
+}
+
+int mlx4_ib_mcg_multiplex_handler(struct ib_device *ibdev, int port,
+				  int slave, struct ib_sa_mad *sa_mad)
+{
+	struct mlx4_ib_dev *dev = to_mdev(ibdev);
+	struct ib_sa_mcmember_data *rec = (struct ib_sa_mcmember_data *)sa_mad->data;
+	struct mlx4_ib_demux_ctx *ctx = &dev->sriov.demux[port - 1];
+	struct mcast_group *group;
+	struct mcast_req *req;
+	int may_create = 0;
+
+	if (ctx->flushing)
+		return -EAGAIN;
+
+	switch (sa_mad->mad_hdr.method) {
+	case IB_MGMT_METHOD_SET:
+		may_create = 1;
+	case IB_SA_METHOD_DELETE:
+		req = kzalloc(sizeof *req, GFP_KERNEL);
+		if (!req)
+			return -ENOMEM;
+
+		req->func = slave;
+		req->sa_mad = *sa_mad;
+
+		mutex_lock(&ctx->mcg_table_lock);
+		group = acquire_group(ctx, &rec->mgid, may_create, GFP_KERNEL);
+		mutex_unlock(&ctx->mcg_table_lock);
+		if (IS_ERR(group)) {
+			kfree(req);
+			return PTR_ERR(group);
+		}
+		mutex_lock(&group->lock);
+		if (group->func[slave].num_pend_reqs > MAX_PEND_REQS_PER_FUNC) {
+			mutex_unlock(&group->lock);
+			mcg_warn_group(group, "Port %d, Func %d has too many pending requests (%d), dropping\n",
+				       port, slave, MAX_PEND_REQS_PER_FUNC);
+			release_group(group, 0);
+			kfree(req);
+			return -ENOMEM;
+		}
+		++group->func[slave].num_pend_reqs;
+		req->group = group;
+		queue_req(req);
+		mutex_unlock(&group->lock);
+		release_group(group, 0);
+		return 1; /* consumed */
+	case IB_SA_METHOD_GET_TABLE:
+	case IB_MGMT_METHOD_GET_RESP:
+	case IB_SA_METHOD_GET_TABLE_RESP:
+	case IB_SA_METHOD_DELETE_RESP:
+		return 0; /* not consumed, pass-through */
+	default:
+		mcg_warn("In multiplex, port %d, func %d: unexpected MCMember method: 0x%x, dropping\n",
+			port, slave, sa_mad->mad_hdr.method);
+		return 1; /* consumed */
+	}
+}
+
+static ssize_t sysfs_show_group(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct mcast_group *group =
+		container_of(attr, struct mcast_group, dentry);
+	struct mcast_req *req = NULL;
+	char pending_str[40];
+	char state_str[40];
+	ssize_t len = 0;
+	int f;
+
+	if (group->state == MCAST_IDLE)
+		sprintf(state_str, "%s", get_state_string(group->state));
+	else
+		sprintf(state_str, "%s(TID=0x%llx)",
+				get_state_string(group->state),
+				be64_to_cpu(group->last_req_tid));
+	if (list_empty(&group->pending_list)) {
+		sprintf(pending_str, "No");
+	} else {
+		req = list_first_entry(&group->pending_list, struct mcast_req, group_list);
+		sprintf(pending_str, "Yes(TID=0x%llx)",
+				be64_to_cpu(req->sa_mad.mad_hdr.tid));
+	}
+	len += sprintf(buf + len, "%1d [%02d,%02d,%02d] %4d %4s %5s     ",
+			group->rec.scope_join_state & 0xf,
+			group->members[2], group->members[1], group->members[0],
+			atomic_read(&group->refcount),
+			pending_str,
+			state_str);
+	for (f = 0; f < MAX_VFS; ++f)
+		if (group->func[f].state == MCAST_MEMBER)
+			len += sprintf(buf + len, "%d[%1x] ",
+					f, group->func[f].join_state);
+
+	len += sprintf(buf + len, "\t\t(%4hx %4x %2x %2x %2x %2x %2x "
+		"%4x %4x %2x %2x)\n",
+		be16_to_cpu(group->rec.pkey),
+		be32_to_cpu(group->rec.qkey),
+		(group->rec.mtusel_mtu & 0xc0) >> 6,
+		group->rec.mtusel_mtu & 0x3f,
+		group->rec.tclass,
+		(group->rec.ratesel_rate & 0xc0) >> 6,
+		group->rec.ratesel_rate & 0x3f,
+		(be32_to_cpu(group->rec.sl_flowlabel_hoplimit) & 0xf0000000) >> 28,
+		(be32_to_cpu(group->rec.sl_flowlabel_hoplimit) & 0x0fffff00) >> 8,
+		be32_to_cpu(group->rec.sl_flowlabel_hoplimit) & 0x000000ff,
+		group->rec.proxy_join);
+
+	return len;
+}
+
+int mlx4_ib_mcg_port_init(struct mlx4_ib_demux_ctx *ctx)
+{
+	char name[20];
+
+	atomic_set(&ctx->tid, 0);
+	sprintf(name, "mlx4_ib_mcg%d", ctx->port);
+	ctx->mcg_wq = create_singlethread_workqueue(name);
+	if (!ctx->mcg_wq)
+		return -ENOMEM;
+
+	mutex_init(&ctx->mcg_table_lock);
+	ctx->mcg_table = RB_ROOT;
+	INIT_LIST_HEAD(&ctx->mcg_mgid0_list);
+	ctx->flushing = 0;
+
+	return 0;
+}
+
+static void force_clean_group(struct mcast_group *group)
+{
+	struct mcast_req *req, *tmp
+		;
+	list_for_each_entry_safe(req, tmp, &group->pending_list, group_list) {
+		list_del(&req->group_list);
+		kfree(req);
+	}
+	del_sysfs_port_mcg_attr(group->demux->dev, group->demux->port, &group->dentry.attr);
+	rb_erase(&group->node, &group->demux->mcg_table);
+	kfree(group);
+}
+
+static void _mlx4_ib_mcg_port_cleanup(struct mlx4_ib_demux_ctx *ctx, int destroy_wq)
+{
+	int i;
+	struct rb_node *p;
+	struct mcast_group *group;
+	unsigned long end;
+	int count;
+
+	if (ctx->flushing)
+		return;
+
+	ctx->flushing = 1;
+	for (i = 0; i < MAX_VFS; ++i)
+		clean_vf_mcast(ctx, i);
+
+	end = jiffies + msecs_to_jiffies(MAD_TIMEOUT_MS + 3000);
+	do {
+		count = 0;
+		mutex_lock(&ctx->mcg_table_lock);
+		for (p = rb_first(&ctx->mcg_table); p; p = rb_next(p))
+			++count;
+		mutex_unlock(&ctx->mcg_table_lock);
+		if (!count)
+			break;
+
+		msleep(1);
+	} while (time_after(end, jiffies));
+
+	flush_workqueue(ctx->mcg_wq);
+	if (destroy_wq)
+		destroy_workqueue(ctx->mcg_wq);
+
+	mutex_lock(&ctx->mcg_table_lock);
+	while ((p = rb_first(&ctx->mcg_table)) != NULL) {
+		group = rb_entry(p, struct mcast_group, node);
+		if (atomic_read(&group->refcount))
+			mcg_warn_group(group, "group refcount %d!!! (pointer %p)\n", atomic_read(&group->refcount), group);
+
+		force_clean_group(group);
+	}
+	mutex_unlock(&ctx->mcg_table_lock);
+
+	if (!destroy_wq)
+		ctx->flushing = 0;
+}
+
+struct clean_work {
+	struct work_struct work;
+	struct mlx4_ib_demux_ctx *ctx;
+	int destroy_wq;
+};
+
+static void mcg_clean_task(struct work_struct *work)
+{
+	struct clean_work *cw = container_of(work, struct clean_work, work);
+
+	_mlx4_ib_mcg_port_cleanup(cw->ctx, cw->destroy_wq);
+	kfree(cw);
+}
+
+void mlx4_ib_mcg_port_cleanup(struct mlx4_ib_demux_ctx *ctx, int destroy_wq)
+{
+	struct clean_work *work;
+
+	if (destroy_wq) {
+		_mlx4_ib_mcg_port_cleanup(ctx, destroy_wq);
+		return;
+	}
+
+	work = kmalloc(sizeof *work, GFP_KERNEL);
+	if (!work) {
+		mcg_warn("failed allocating work for cleanup\n");
+		return;
+	}
+
+	work->ctx = ctx;
+	work->destroy_wq = destroy_wq;
+	INIT_WORK(&work->work, mcg_clean_task);
+	queue_work(clean_wq, &work->work);
+}
+
+static void build_leave_mad(struct mcast_req *req)
+{
+	struct ib_sa_mad *mad = &req->sa_mad;
+
+	mad->mad_hdr.method = IB_SA_METHOD_DELETE;
+}
+
+
+static void clear_pending_reqs(struct mcast_group *group, int vf)
+{
+	struct mcast_req *req, *tmp, *group_first = NULL;
+	int clear;
+	int pend = 0;
+
+	if (!list_empty(&group->pending_list))
+		group_first = list_first_entry(&group->pending_list, struct mcast_req, group_list);
+
+	list_for_each_entry_safe(req, tmp, &group->func[vf].pending, func_list) {
+		clear = 1;
+		if (group_first == req &&
+		    (group->state == MCAST_JOIN_SENT ||
+		     group->state == MCAST_LEAVE_SENT)) {
+			clear = cancel_delayed_work(&group->timeout_work);
+			pend = !clear;
+			group->state = MCAST_IDLE;
+		}
+		if (clear) {
+			--group->func[vf].num_pend_reqs;
+			list_del(&req->group_list);
+			list_del(&req->func_list);
+			kfree(req);
+			atomic_dec(&group->refcount);
+		}
+	}
+
+	if (!pend && (!list_empty(&group->func[vf].pending) || group->func[vf].num_pend_reqs)) {
+		mcg_warn_group(group, "DRIVER BUG: list_empty %d, num_pend_reqs %d\n",
+			       list_empty(&group->func[vf].pending), group->func[vf].num_pend_reqs);
+	}
+}
+
+static int push_deleteing_req(struct mcast_group *group, int slave)
+{
+	struct mcast_req *req;
+	struct mcast_req *pend_req;
+
+	if (!group->func[slave].join_state)
+		return 0;
+
+	req = kzalloc(sizeof *req, GFP_KERNEL);
+	if (!req) {
+		mcg_warn_group(group, "failed allocation - may leave stall groups\n");
+		return -ENOMEM;
+	}
+
+	if (!list_empty(&group->func[slave].pending)) {
+		pend_req = list_entry(group->func[slave].pending.prev, struct mcast_req, group_list);
+		if (pend_req->clean) {
+			kfree(req);
+			return 0;
+		}
+	}
+
+	req->clean = 1;
+	req->func = slave;
+	req->group = group;
+	++group->func[slave].num_pend_reqs;
+	build_leave_mad(req);
+	queue_req(req);
+	return 0;
+}
+
+void clean_vf_mcast(struct mlx4_ib_demux_ctx *ctx, int slave)
+{
+	struct mcast_group *group;
+	struct rb_node *p;
+
+	mutex_lock(&ctx->mcg_table_lock);
+	for (p = rb_first(&ctx->mcg_table); p; p = rb_next(p)) {
+		group = rb_entry(p, struct mcast_group, node);
+		mutex_lock(&group->lock);
+		if (atomic_read(&group->refcount)) {
+			/* clear pending requests of this VF */
+			clear_pending_reqs(group, slave);
+			push_deleteing_req(group, slave);
+		}
+		mutex_unlock(&group->lock);
+	}
+	mutex_unlock(&ctx->mcg_table_lock);
+}
+
+
+int mlx4_ib_mcg_init(void)
+{
+	clean_wq = create_singlethread_workqueue("mlx4_ib_mcg");
+	if (!clean_wq)
+		return -ENOMEM;
+
+	return 0;
+}
+
+void mlx4_ib_mcg_destroy(void)
+{
+	destroy_workqueue(clean_wq);
+}
diff --git a/drivers/infiniband/hw/mlx4/mlx4_ib.h b/drivers/infiniband/hw/mlx4/mlx4_ib.h
index c136bb6..e04cbc9 100644
--- a/drivers/infiniband/hw/mlx4/mlx4_ib.h
+++ b/drivers/infiniband/hw/mlx4/mlx4_ib.h
@@ -37,9 +37,12 @@
 #include <linux/compiler.h>
 #include <linux/list.h>
 #include <linux/mutex.h>
+#include <linux/idr.h>
 
 #include <rdma/ib_verbs.h>
 #include <rdma/ib_umem.h>
+#include <rdma/ib_mad.h>
+#include <rdma/ib_sa.h>
 
 #include <linux/mlx4/device.h>
 #include <linux/mlx4/doorbell.h>
@@ -62,6 +65,9 @@ enum {
 #define MLX4_IB_SQ_HEADROOM(shift)	((MLX4_IB_MAX_HEADROOM >> (shift)) + 1)
 #define MLX4_IB_SQ_MAX_SPARE		(MLX4_IB_SQ_HEADROOM(MLX4_IB_SQ_MIN_WQE_SHIFT))
 
+/*module param to indicate if SM assigns the alias_GUID*/
+extern int mlx4_ib_sm_guid_assign;
+
 struct mlx4_ib_ucontext {
 	struct ib_ucontext	ibucontext;
 	struct mlx4_uar		uar;
@@ -133,8 +139,10 @@ struct mlx4_ib_wq {
 };
 
 enum mlx4_ib_qp_flags {
-	MLX4_IB_QP_LSO				= 1 << 0,
-	MLX4_IB_QP_BLOCK_MULTICAST_LOOPBACK	= 1 << 1,
+	MLX4_IB_QP_LSO = IB_QP_CREATE_IPOIB_UD_LSO,
+	MLX4_IB_QP_BLOCK_MULTICAST_LOOPBACK = IB_QP_CREATE_BLOCK_MULTICAST_LOOPBACK,
+	MLX4_IB_SRIOV_TUNNEL_QP = 1 << 30,
+	MLX4_IB_SRIOV_SQP = 1 << 31,
 };
 
 struct mlx4_ib_gid_entry {
@@ -144,6 +152,80 @@ struct mlx4_ib_gid_entry {
 	u8			port;
 };
 
+enum mlx4_ib_qp_type {
+	/*
+	 * IB_QPT_SMI and IB_QPT_GSI have to be the first two entries
+	 * here (and in that order) since the MAD layer uses them as
+	 * indices into a 2-entry table.
+	 */
+	MLX4_IB_QPT_SMI = IB_QPT_SMI,
+	MLX4_IB_QPT_GSI = IB_QPT_GSI,
+
+	MLX4_IB_QPT_RC = IB_QPT_RC,
+	MLX4_IB_QPT_UC = IB_QPT_UC,
+	MLX4_IB_QPT_UD = IB_QPT_UD,
+	MLX4_IB_QPT_RAW_IPV6 = IB_QPT_RAW_IPV6,
+	MLX4_IB_QPT_RAW_ETHERTYPE = IB_QPT_RAW_ETHERTYPE,
+	MLX4_IB_QPT_RAW_PACKET = IB_QPT_RAW_PACKET,
+	MLX4_IB_QPT_XRC_INI = IB_QPT_XRC_INI,
+	MLX4_IB_QPT_XRC_TGT = IB_QPT_XRC_TGT,
+
+	MLX4_IB_QPT_PROXY_SMI_OWNER	= 1 << 16,
+	MLX4_IB_QPT_PROXY_SMI		= 1 << 17,
+	MLX4_IB_QPT_PROXY_GSI		= 1 << 18,
+	MLX4_IB_QPT_TUN_SMI_OWNER	= 1 << 19,
+	MLX4_IB_QPT_TUN_SMI		= 1 << 20,
+	MLX4_IB_QPT_TUN_GSI		= 1 << 21,
+};
+
+#define MLX4_IB_QPT_ANY_SRIOV	(MLX4_IB_QPT_PROXY_SMI_OWNER | \
+	MLX4_IB_QPT_PROXY_SMI | MLX4_IB_QPT_PROXY_GSI | MLX4_IB_QPT_TUN_SMI_OWNER | \
+	MLX4_IB_QPT_TUN_SMI | MLX4_IB_QPT_TUN_GSI)
+
+enum mlx4_ib_mad_ifc_flags {
+	MLX4_MAD_IFC_IGNORE_MKEY	= 1,
+	MLX4_MAD_IFC_IGNORE_BKEY	= 2,
+	MLX4_MAD_IFC_IGNORE_KEYS	= (MLX4_MAD_IFC_IGNORE_MKEY |
+					   MLX4_MAD_IFC_IGNORE_BKEY),
+	MLX4_MAD_IFC_NET_VIEW		= 4,
+};
+
+enum {
+	MLX4_NUM_TUNNEL_BUFS		= 256,
+};
+
+struct mlx4_ib_tunnel_header {
+	struct mlx4_av av;
+	__be32 remote_qpn;
+	__be32 qkey;
+	__be16 vlan;
+	u8 mac[6];
+	__be16 pkey_index;
+	u8 reserved[6];
+};
+
+struct mlx4_ib_buf {
+	void *addr;
+	dma_addr_t map;
+};
+
+struct mlx4_rcv_tunnel_hdr {
+	__be32 flags_src_qp; /* flags[6:5] is defined for VLANs:
+			      * 0x0 - no vlan was in the packet
+			      * 0x01 - C-VLAN was in the packet */
+	u8 g_ml_path; /* gid bit stands for ipv6/4 header in RoCE */
+	u8 reserved;
+	__be16 pkey_index;
+	__be16 sl_vid;
+	__be16 slid_mac_47_32;
+	__be32 mac_31_0;
+};
+
+struct mlx4_ib_proxy_sqp_hdr {
+	struct ib_grh grh;
+	struct mlx4_rcv_tunnel_hdr tun;
+}  __packed;
+
 struct mlx4_ib_qp {
 	struct ib_qp		ibqp;
 	struct mlx4_qp		mqp;
@@ -159,6 +241,7 @@ struct mlx4_ib_qp {
 	int			sq_spare_wqes;
 	struct mlx4_ib_wq	sq;
 
+	enum mlx4_ib_qp_type	mlx4_ib_qp_type;
 	struct ib_umem	       *umem;
 	struct mlx4_mtt		mtt;
 	int			buf_size;
@@ -174,6 +257,8 @@ struct mlx4_ib_qp {
 	int			mlx_type;
 	struct list_head	gid_list;
 	struct list_head	steering_rules;
+	struct mlx4_ib_buf	*sqp_proxy_rcv;
+
 };
 
 struct mlx4_ib_srq {
@@ -196,6 +281,138 @@ struct mlx4_ib_ah {
 	union mlx4_ext_av       av;
 };
 
+/****************************************/
+/* alias guid support */
+/****************************************/
+#define NUM_PORT_ALIAS_GUID		2
+#define NUM_ALIAS_GUID_IN_REC		8
+#define NUM_ALIAS_GUID_REC_IN_PORT	16
+#define GUID_REC_SIZE			8
+#define NUM_ALIAS_GUID_PER_PORT		128
+#define MLX4_NOT_SET_GUID		(0x00LL)
+#define MLX4_GUID_FOR_DELETE_VAL	(~(0x00LL))
+
+enum mlx4_guid_alias_rec_status {
+	MLX4_GUID_INFO_STATUS_IDLE,
+	MLX4_GUID_INFO_STATUS_SET,
+	MLX4_GUID_INFO_STATUS_PENDING,
+};
+
+enum mlx4_guid_alias_rec_ownership {
+	MLX4_GUID_DRIVER_ASSIGN,
+	MLX4_GUID_SYSADMIN_ASSIGN,
+	MLX4_GUID_NONE_ASSIGN, /*init state of each record*/
+};
+
+enum mlx4_guid_alias_rec_method {
+	MLX4_GUID_INFO_RECORD_SET	= IB_MGMT_METHOD_SET,
+	MLX4_GUID_INFO_RECORD_DELETE	= IB_SA_METHOD_DELETE,
+};
+
+struct mlx4_sriov_alias_guid_info_rec_det {
+	u8 all_recs[GUID_REC_SIZE * NUM_ALIAS_GUID_IN_REC];
+	ib_sa_comp_mask guid_indexes; /*indicates what from the 8 records are valid*/
+	enum mlx4_guid_alias_rec_status status; /*indicates the administraively status of the record.*/
+	u8 method; /*set or delete*/
+	enum mlx4_guid_alias_rec_ownership ownership; /*indicates who assign that alias_guid record*/
+};
+
+struct mlx4_sriov_alias_guid_port_rec_det {
+	struct mlx4_sriov_alias_guid_info_rec_det all_rec_per_port[NUM_ALIAS_GUID_REC_IN_PORT];
+	struct workqueue_struct *wq;
+	struct delayed_work alias_guid_work;
+	u8 port;
+	struct mlx4_sriov_alias_guid *parent;
+	struct list_head cb_list;
+};
+
+struct mlx4_sriov_alias_guid {
+	struct mlx4_sriov_alias_guid_port_rec_det ports_guid[MLX4_MAX_PORTS];
+	spinlock_t ag_work_lock;
+	struct ib_sa_client *sa_client;
+};
+
+struct mlx4_ib_demux_work {
+	struct work_struct	work;
+	struct mlx4_ib_dev     *dev;
+	int			slave;
+	int			do_init;
+	u8			port;
+
+};
+
+struct mlx4_ib_tun_tx_buf {
+	struct mlx4_ib_buf buf;
+	struct ib_ah *ah;
+};
+
+struct mlx4_ib_demux_pv_qp {
+	struct ib_qp *qp;
+	enum ib_qp_type proxy_qpt;
+	struct mlx4_ib_buf *ring;
+	struct mlx4_ib_tun_tx_buf *tx_ring;
+	spinlock_t tx_lock;
+	unsigned tx_ix_head;
+	unsigned tx_ix_tail;
+};
+
+enum mlx4_ib_demux_pv_state {
+	DEMUX_PV_STATE_DOWN,
+	DEMUX_PV_STATE_STARTING,
+	DEMUX_PV_STATE_ACTIVE,
+	DEMUX_PV_STATE_DOWNING,
+};
+
+struct mlx4_ib_demux_pv_ctx {
+	int port;
+	int slave;
+	enum mlx4_ib_demux_pv_state state;
+	int has_smi;
+	struct ib_device *ib_dev;
+	struct ib_cq *cq;
+	struct ib_pd *pd;
+	struct ib_mr *mr;
+	struct work_struct work;
+	struct workqueue_struct *wq;
+	struct mlx4_ib_demux_pv_qp qp[2];
+};
+
+struct mlx4_ib_demux_ctx {
+	struct ib_device *ib_dev;
+	int port;
+	struct workqueue_struct *wq;
+	struct workqueue_struct *ud_wq;
+	spinlock_t ud_lock;
+	__be64 subnet_prefix;
+	__be64 guid_cache[128];
+	struct mlx4_ib_dev *dev;
+	/* the following lock protects both mcg_table and mcg_mgid0_list */
+	struct mutex		mcg_table_lock;
+	struct rb_root		mcg_table;
+	struct list_head	mcg_mgid0_list;
+	struct workqueue_struct	*mcg_wq;
+	struct mlx4_ib_demux_pv_ctx **tun;
+	atomic_t tid;
+	int    flushing; /* flushing the work queue */
+};
+
+struct mlx4_ib_sriov {
+	struct mlx4_ib_demux_ctx demux[MLX4_MAX_PORTS];
+	struct mlx4_ib_demux_pv_ctx *sqps[MLX4_MAX_PORTS];
+	/* when using this spinlock you should use "irq" because
+	 * it may be called from interrupt context.*/
+	spinlock_t going_down_lock;
+	int is_going_down;
+
+	struct mlx4_sriov_alias_guid alias_guid;
+
+	/* CM paravirtualization fields */
+	struct list_head cm_list;
+	spinlock_t id_map_lock;
+	struct rb_root sl_id_map;
+	struct idr pv_id_table;
+};
+
 struct mlx4_ib_iboe {
 	spinlock_t		lock;
 	struct net_device      *netdevs[MLX4_MAX_PORTS];
@@ -203,6 +420,42 @@ struct mlx4_ib_iboe {
 	union ib_gid		gid_table[MLX4_MAX_PORTS][128];
 };
 
+struct pkey_mgt {
+	u8			virt2phys_pkey[MLX4_MFUNC_MAX][MLX4_MAX_PORTS][MLX4_MAX_PORT_PKEYS];
+	u16			phys_pkey_cache[MLX4_MAX_PORTS][MLX4_MAX_PORT_PKEYS];
+	struct list_head	pkey_port_list[MLX4_MFUNC_MAX];
+	struct kobject	       *device_parent[MLX4_MFUNC_MAX];
+};
+
+struct mlx4_ib_iov_sysfs_attr {
+	void *ctx;
+	struct kobject *kobj;
+	unsigned long data;
+	u32 entry_num;
+	char name[15];
+	struct device_attribute dentry;
+	struct device *dev;
+};
+
+struct mlx4_ib_iov_sysfs_attr_ar {
+	struct mlx4_ib_iov_sysfs_attr dentries[3 * NUM_ALIAS_GUID_PER_PORT + 1];
+};
+
+struct mlx4_ib_iov_port {
+	char name[100];
+	u8 num;
+	struct mlx4_ib_dev *dev;
+	struct list_head list;
+	struct mlx4_ib_iov_sysfs_attr_ar *dentr_ar;
+	struct ib_port_attr attr;
+	struct kobject	*cur_port;
+	struct kobject	*admin_alias_parent;
+	struct kobject	*gids_parent;
+	struct kobject	*pkeys_parent;
+	struct kobject	*mcgs_parent;
+	struct mlx4_ib_iov_sysfs_attr mcg_dentry;
+};
+
 struct mlx4_ib_dev {
 	struct ib_device	ib_dev;
 	struct mlx4_dev	       *dev;
@@ -216,6 +469,7 @@ struct mlx4_ib_dev {
 	struct ib_mad_agent    *send_agent[MLX4_MAX_PORTS][2];
 	struct ib_ah	       *sm_ah[MLX4_MAX_PORTS];
 	spinlock_t		sm_lock;
+	struct mlx4_ib_sriov	sriov;
 
 	struct mutex		cap_mask_mutex;
 	bool			ib_active;
@@ -223,6 +477,11 @@ struct mlx4_ib_dev {
 	int			counters[MLX4_MAX_PORTS];
 	int		       *eq_table;
 	int			eq_added;
+	struct kobject	       *iov_parent;
+	struct kobject	       *ports_parent;
+	struct kobject	       *dev_ports_parent[MLX4_MFUNC_MAX];
+	struct mlx4_ib_iov_port	iov_ports[MLX4_MAX_PORTS];
+	struct pkey_mgt		pkeys;
 };
 
 struct ib_event_work {
@@ -231,6 +490,13 @@ struct ib_event_work {
 	struct mlx4_eqe		ib_eqe;
 };
 
+struct mlx4_ib_qp_tunnel_init_attr {
+	struct ib_qp_init_attr init_attr;
+	int slave;
+	enum ib_qp_type proxy_qp_type;
+	u8 port;
+};
+
 static inline struct mlx4_ib_dev *to_mdev(struct ib_device *ibdev)
 {
 	return container_of(ibdev, struct mlx4_ib_dev, ib_dev);
@@ -300,6 +566,9 @@ static inline struct mlx4_ib_ah *to_mah(struct ib_ah *ibah)
 	return container_of(ibah, struct mlx4_ib_ah, ibah);
 }
 
+int mlx4_ib_init_sriov(struct mlx4_ib_dev *dev);
+void mlx4_ib_close_sriov(struct mlx4_ib_dev *dev);
+
 int mlx4_ib_db_map_user(struct mlx4_ib_ucontext *context, unsigned long virt,
 			struct mlx4_db *db);
 void mlx4_ib_db_unmap_user(struct mlx4_ib_ucontext *context, struct mlx4_db *db);
@@ -356,7 +625,7 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
 int mlx4_ib_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *wr,
 		      struct ib_recv_wr **bad_wr);
 
-int mlx4_MAD_IFC(struct mlx4_ib_dev *dev, int ignore_mkey, int ignore_bkey,
+int mlx4_MAD_IFC(struct mlx4_ib_dev *dev, int mad_ifc_flags,
 		 int port, struct ib_wc *in_wc, struct ib_grh *in_grh,
 		 void *in_mad, void *response_mad);
 int mlx4_ib_process_mad(struct ib_device *ibdev, int mad_flags,	u8 port_num,
@@ -371,6 +640,13 @@ int mlx4_ib_map_phys_fmr(struct ib_fmr *ibfmr, u64 *page_list, int npages,
 			 u64 iova);
 int mlx4_ib_unmap_fmr(struct list_head *fmr_list);
 int mlx4_ib_fmr_dealloc(struct ib_fmr *fmr);
+int __mlx4_ib_query_port(struct ib_device *ibdev, u8 port,
+			 struct ib_port_attr *props, int netw_view);
+int __mlx4_ib_query_pkey(struct ib_device *ibdev, u8 port, u16 index,
+			 u16 *pkey, int netw_view);
+
+int __mlx4_ib_query_gid(struct ib_device *ibdev, u8 port, int index,
+			union ib_gid *gid, int netw_view);
 
 int mlx4_ib_resolve_grh(struct mlx4_ib_dev *dev, const struct ib_ah_attr *ah_attr,
 			u8 *mac, int *is_mcast, u8 port);
@@ -385,10 +661,69 @@ static inline int mlx4_ib_ah_grh_present(struct mlx4_ib_ah *ah)
 	return !!(ah->av.ib.g_slid & 0x80);
 }
 
+int mlx4_ib_mcg_port_init(struct mlx4_ib_demux_ctx *ctx);
+void mlx4_ib_mcg_port_cleanup(struct mlx4_ib_demux_ctx *ctx, int destroy_wq);
+void clean_vf_mcast(struct mlx4_ib_demux_ctx *ctx, int slave);
+int mlx4_ib_mcg_init(void);
+void mlx4_ib_mcg_destroy(void);
+
+int mlx4_ib_find_real_gid(struct ib_device *ibdev, u8 port, __be64 guid);
+
+int mlx4_ib_mcg_multiplex_handler(struct ib_device *ibdev, int port, int slave,
+				  struct ib_sa_mad *sa_mad);
+int mlx4_ib_mcg_demux_handler(struct ib_device *ibdev, int port, int slave,
+			      struct ib_sa_mad *mad);
+
 int mlx4_ib_add_mc(struct mlx4_ib_dev *mdev, struct mlx4_ib_qp *mqp,
 		   union ib_gid *gid);
 
 void mlx4_ib_dispatch_event(struct mlx4_ib_dev *dev, u8 port_num,
 			    enum ib_event_type type);
 
+void mlx4_ib_tunnels_update_work(struct work_struct *work);
+
+int mlx4_ib_send_to_slave(struct mlx4_ib_dev *dev, int slave, u8 port,
+			  enum ib_qp_type qpt, struct ib_wc *wc,
+			  struct ib_grh *grh, struct ib_mad *mad);
+int mlx4_ib_send_to_wire(struct mlx4_ib_dev *dev, int slave, u8 port,
+			 enum ib_qp_type dest_qpt, u16 pkey_index, u32 remote_qpn,
+			 u32 qkey, struct ib_ah_attr *attr, struct ib_mad *mad);
+__be64 mlx4_ib_get_new_demux_tid(struct mlx4_ib_demux_ctx *ctx);
+
+int mlx4_ib_demux_cm_handler(struct ib_device *ibdev, int port, int *slave,
+		struct ib_mad *mad);
+
+int mlx4_ib_multiplex_cm_handler(struct ib_device *ibdev, int port, int slave_id,
+		struct ib_mad *mad);
+
+void mlx4_ib_cm_paravirt_init(struct mlx4_ib_dev *dev);
+void mlx4_ib_cm_paravirt_clean(struct mlx4_ib_dev *dev, int slave_id);
+
+/* alias guid support */
+void mlx4_ib_init_alias_guid_work(struct mlx4_ib_dev *dev, int port);
+int mlx4_ib_init_alias_guid_service(struct mlx4_ib_dev *dev);
+void mlx4_ib_destroy_alias_guid_service(struct mlx4_ib_dev *dev);
+void mlx4_ib_invalidate_all_guid_record(struct mlx4_ib_dev *dev, int port);
+
+void mlx4_ib_notify_slaves_on_guid_change(struct mlx4_ib_dev *dev,
+					  int block_num,
+					  u8 port_num, u8 *p_data);
+
+void mlx4_ib_update_cache_on_guid_change(struct mlx4_ib_dev *dev,
+					 int block_num, u8 port_num,
+					 u8 *p_data);
+
+int add_sysfs_port_mcg_attr(struct mlx4_ib_dev *device, int port_num,
+			    struct attribute *attr);
+void del_sysfs_port_mcg_attr(struct mlx4_ib_dev *device, int port_num,
+			     struct attribute *attr);
+ib_sa_comp_mask mlx4_ib_get_aguid_comp_mask_from_ix(int index);
+
+int mlx4_ib_device_register_sysfs(struct mlx4_ib_dev *device) ;
+
+void mlx4_ib_device_unregister_sysfs(struct mlx4_ib_dev *device);
+
+__be64 mlx4_ib_gen_node_guid(void);
+
+
 #endif /* MLX4_IB_H */
diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c
index f585edd..19e0637 100644
--- a/drivers/infiniband/hw/mlx4/qp.c
+++ b/drivers/infiniband/hw/mlx4/qp.c
@@ -38,6 +38,7 @@
 #include <rdma/ib_cache.h>
 #include <rdma/ib_pack.h>
 #include <rdma/ib_addr.h>
+#include <rdma/ib_mad.h>
 
 #include <linux/mlx4/qp.h>
 
@@ -110,16 +111,62 @@ static struct mlx4_ib_sqp *to_msqp(struct mlx4_ib_qp *mqp)
 	return container_of(mqp, struct mlx4_ib_sqp, qp);
 }
 
+static int is_tunnel_qp(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp)
+{
+	if (!mlx4_is_master(dev->dev))
+		return 0;
+
+	return qp->mqp.qpn >= dev->dev->phys_caps.base_tunnel_sqpn &&
+	       qp->mqp.qpn < dev->dev->phys_caps.base_tunnel_sqpn +
+		8 * MLX4_MFUNC_MAX;
+}
+
 static int is_sqp(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp)
 {
-	return qp->mqp.qpn >= dev->dev->caps.sqp_start &&
-		qp->mqp.qpn <= dev->dev->caps.sqp_start + 3;
+	int proxy_sqp = 0;
+	int real_sqp = 0;
+	int i;
+	/* PPF or Native -- real SQP */
+	real_sqp = ((mlx4_is_master(dev->dev) || !mlx4_is_mfunc(dev->dev)) &&
+		    qp->mqp.qpn >= dev->dev->phys_caps.base_sqpn &&
+		    qp->mqp.qpn <= dev->dev->phys_caps.base_sqpn + 3);
+	if (real_sqp)
+		return 1;
+	/* VF or PF -- proxy SQP */
+	if (mlx4_is_mfunc(dev->dev)) {
+		for (i = 0; i < dev->dev->caps.num_ports; i++) {
+			if (qp->mqp.qpn == dev->dev->caps.qp0_proxy[i] ||
+			    qp->mqp.qpn == dev->dev->caps.qp1_proxy[i]) {
+				proxy_sqp = 1;
+				break;
+			}
+		}
+	}
+	return proxy_sqp;
 }
 
+/* used for INIT/CLOSE port logic */
 static int is_qp0(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp)
 {
-	return qp->mqp.qpn >= dev->dev->caps.sqp_start &&
-		qp->mqp.qpn <= dev->dev->caps.sqp_start + 1;
+	int proxy_qp0 = 0;
+	int real_qp0 = 0;
+	int i;
+	/* PPF or Native -- real QP0 */
+	real_qp0 = ((mlx4_is_master(dev->dev) || !mlx4_is_mfunc(dev->dev)) &&
+		    qp->mqp.qpn >= dev->dev->phys_caps.base_sqpn &&
+		    qp->mqp.qpn <= dev->dev->phys_caps.base_sqpn + 1);
+	if (real_qp0)
+		return 1;
+	/* VF or PF -- proxy QP0 */
+	if (mlx4_is_mfunc(dev->dev)) {
+		for (i = 0; i < dev->dev->caps.num_ports; i++) {
+			if (qp->mqp.qpn == dev->dev->caps.qp0_proxy[i]) {
+				proxy_qp0 = 1;
+				break;
+			}
+		}
+	}
+	return proxy_qp0;
 }
 
 static void *get_wqe(struct mlx4_ib_qp *qp, int offset)
@@ -270,7 +317,7 @@ static void mlx4_ib_qp_event(struct mlx4_qp *qp, enum mlx4_event type)
 	}
 }
 
-static int send_wqe_overhead(enum ib_qp_type type, u32 flags)
+static int send_wqe_overhead(enum mlx4_ib_qp_type type, u32 flags)
 {
 	/*
 	 * UD WQEs must have a datagram segment.
@@ -279,19 +326,29 @@ static int send_wqe_overhead(enum ib_qp_type type, u32 flags)
 	 * header and space for the ICRC).
 	 */
 	switch (type) {
-	case IB_QPT_UD:
+	case MLX4_IB_QPT_UD:
 		return sizeof (struct mlx4_wqe_ctrl_seg) +
 			sizeof (struct mlx4_wqe_datagram_seg) +
 			((flags & MLX4_IB_QP_LSO) ? MLX4_IB_LSO_HEADER_SPARE : 0);
-	case IB_QPT_UC:
+	case MLX4_IB_QPT_PROXY_SMI_OWNER:
+	case MLX4_IB_QPT_PROXY_SMI:
+	case MLX4_IB_QPT_PROXY_GSI:
+		return sizeof (struct mlx4_wqe_ctrl_seg) +
+			sizeof (struct mlx4_wqe_datagram_seg) + 64;
+	case MLX4_IB_QPT_TUN_SMI_OWNER:
+	case MLX4_IB_QPT_TUN_GSI:
+		return sizeof (struct mlx4_wqe_ctrl_seg) +
+			sizeof (struct mlx4_wqe_datagram_seg);
+
+	case MLX4_IB_QPT_UC:
 		return sizeof (struct mlx4_wqe_ctrl_seg) +
 			sizeof (struct mlx4_wqe_raddr_seg);
-	case IB_QPT_RC:
+	case MLX4_IB_QPT_RC:
 		return sizeof (struct mlx4_wqe_ctrl_seg) +
 			sizeof (struct mlx4_wqe_atomic_seg) +
 			sizeof (struct mlx4_wqe_raddr_seg);
-	case IB_QPT_SMI:
-	case IB_QPT_GSI:
+	case MLX4_IB_QPT_SMI:
+	case MLX4_IB_QPT_GSI:
 		return sizeof (struct mlx4_wqe_ctrl_seg) +
 			ALIGN(MLX4_IB_UD_HEADER_SIZE +
 			      DIV_ROUND_UP(MLX4_IB_UD_HEADER_SIZE,
@@ -345,7 +402,7 @@ static int set_rq_size(struct mlx4_ib_dev *dev, struct ib_qp_cap *cap,
 }
 
 static int set_kernel_sq_size(struct mlx4_ib_dev *dev, struct ib_qp_cap *cap,
-			      enum ib_qp_type type, struct mlx4_ib_qp *qp)
+			      enum mlx4_ib_qp_type type, struct mlx4_ib_qp *qp)
 {
 	int s;
 
@@ -360,7 +417,8 @@ static int set_kernel_sq_size(struct mlx4_ib_dev *dev, struct ib_qp_cap *cap,
 	 * For MLX transport we need 2 extra S/G entries:
 	 * one for the header and one for the checksum at the end
 	 */
-	if ((type == IB_QPT_SMI || type == IB_QPT_GSI) &&
+	if ((type == MLX4_IB_QPT_SMI || type == MLX4_IB_QPT_GSI ||
+	     type & (MLX4_IB_QPT_PROXY_SMI_OWNER | MLX4_IB_QPT_TUN_SMI_OWNER)) &&
 	    cap->max_send_sge + 2 > dev->dev->caps.max_sq_sg)
 		return -EINVAL;
 
@@ -404,7 +462,9 @@ static int set_kernel_sq_size(struct mlx4_ib_dev *dev, struct ib_qp_cap *cap,
 	 */
 	if (dev->dev->caps.fw_ver >= MLX4_FW_VER_WQE_CTRL_NEC &&
 	    qp->sq_signal_bits && BITS_PER_LONG == 64 &&
-	    type != IB_QPT_SMI && type != IB_QPT_GSI)
+	    type != MLX4_IB_QPT_SMI && type != MLX4_IB_QPT_GSI &&
+	    !(type & (MLX4_IB_QPT_PROXY_SMI_OWNER | MLX4_IB_QPT_PROXY_SMI |
+		      MLX4_IB_QPT_PROXY_GSI | MLX4_IB_QPT_TUN_SMI_OWNER)))
 		qp->sq.wqe_shift = ilog2(64);
 	else
 		qp->sq.wqe_shift = ilog2(roundup_pow_of_two(s));
@@ -476,6 +536,54 @@ static int set_user_sq_size(struct mlx4_ib_dev *dev,
 	return 0;
 }
 
+static int alloc_proxy_bufs(struct ib_device *dev, struct mlx4_ib_qp *qp)
+{
+	int i;
+
+	qp->sqp_proxy_rcv =
+		kmalloc(sizeof (struct mlx4_ib_buf) * qp->rq.wqe_cnt,
+			GFP_KERNEL);
+	if (!qp->sqp_proxy_rcv)
+		return -ENOMEM;
+	for (i = 0; i < qp->rq.wqe_cnt; i++) {
+		qp->sqp_proxy_rcv[i].addr =
+			kmalloc(sizeof (struct mlx4_ib_proxy_sqp_hdr),
+				GFP_KERNEL);
+		if (!qp->sqp_proxy_rcv[i].addr)
+			goto err;
+		qp->sqp_proxy_rcv[i].map =
+			ib_dma_map_single(dev, qp->sqp_proxy_rcv[i].addr,
+					  sizeof (struct mlx4_ib_proxy_sqp_hdr),
+					  DMA_FROM_DEVICE);
+	}
+	return 0;
+
+err:
+	while (i > 0) {
+		--i;
+		ib_dma_unmap_single(dev, qp->sqp_proxy_rcv[i].map,
+				    sizeof (struct mlx4_ib_proxy_sqp_hdr),
+				    DMA_FROM_DEVICE);
+		kfree(qp->sqp_proxy_rcv[i].addr);
+	}
+	kfree(qp->sqp_proxy_rcv);
+	qp->sqp_proxy_rcv = NULL;
+	return -ENOMEM;
+}
+
+static void free_proxy_bufs(struct ib_device *dev, struct mlx4_ib_qp *qp)
+{
+	int i;
+
+	for (i = 0; i < qp->rq.wqe_cnt; i++) {
+		ib_dma_unmap_single(dev, qp->sqp_proxy_rcv[i].map,
+				    sizeof (struct mlx4_ib_proxy_sqp_hdr),
+				    DMA_FROM_DEVICE);
+		kfree(qp->sqp_proxy_rcv[i].addr);
+	}
+	kfree(qp->sqp_proxy_rcv);
+}
+
 static int qp_has_rq(struct ib_qp_init_attr *attr)
 {
 	if (attr->qp_type == IB_QPT_XRC_INI || attr->qp_type == IB_QPT_XRC_TGT)
@@ -486,10 +594,67 @@ static int qp_has_rq(struct ib_qp_init_attr *attr)
 
 static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
 			    struct ib_qp_init_attr *init_attr,
-			    struct ib_udata *udata, int sqpn, struct mlx4_ib_qp *qp)
+			    struct ib_udata *udata, int sqpn, struct mlx4_ib_qp **caller_qp)
 {
 	int qpn;
 	int err;
+	struct mlx4_ib_sqp *sqp;
+	struct mlx4_ib_qp *qp;
+	enum mlx4_ib_qp_type qp_type = (enum mlx4_ib_qp_type) init_attr->qp_type;
+
+	/* When tunneling special qps, we use a plain UD qp */
+	if (sqpn) {
+		if (mlx4_is_mfunc(dev->dev) &&
+		    (!mlx4_is_master(dev->dev) ||
+		     !(init_attr->create_flags & MLX4_IB_SRIOV_SQP))) {
+			if (init_attr->qp_type == IB_QPT_GSI)
+				qp_type = MLX4_IB_QPT_PROXY_GSI;
+			else if (mlx4_is_master(dev->dev))
+				qp_type = MLX4_IB_QPT_PROXY_SMI_OWNER;
+			else
+				qp_type = MLX4_IB_QPT_PROXY_SMI;
+		}
+		qpn = sqpn;
+		/* add extra sg entry for tunneling */
+		init_attr->cap.max_recv_sge++;
+	} else if (init_attr->create_flags & MLX4_IB_SRIOV_TUNNEL_QP) {
+		struct mlx4_ib_qp_tunnel_init_attr *tnl_init =
+			container_of(init_attr,
+				     struct mlx4_ib_qp_tunnel_init_attr, init_attr);
+		if ((tnl_init->proxy_qp_type != IB_QPT_SMI &&
+		     tnl_init->proxy_qp_type != IB_QPT_GSI)   ||
+		    !mlx4_is_master(dev->dev))
+			return -EINVAL;
+		if (tnl_init->proxy_qp_type == IB_QPT_GSI)
+			qp_type = MLX4_IB_QPT_TUN_GSI;
+		else if (tnl_init->slave == mlx4_master_func_num(dev->dev))
+			qp_type = MLX4_IB_QPT_TUN_SMI_OWNER;
+		else
+			qp_type = MLX4_IB_QPT_TUN_SMI;
+		/* we are definitely in the PPF here, since we are creating
+		 * tunnel QPs. base_tunnel_sqpn is therefore valid. */
+		qpn = dev->dev->phys_caps.base_tunnel_sqpn + 8 * tnl_init->slave
+			+ tnl_init->proxy_qp_type * 2 + tnl_init->port - 1;
+		sqpn = qpn;
+	}
+
+	if (!*caller_qp) {
+		if (qp_type == MLX4_IB_QPT_SMI || qp_type == MLX4_IB_QPT_GSI ||
+		    (qp_type & (MLX4_IB_QPT_PROXY_SMI | MLX4_IB_QPT_PROXY_SMI_OWNER |
+				MLX4_IB_QPT_PROXY_GSI | MLX4_IB_QPT_TUN_SMI_OWNER))) {
+			sqp = kzalloc(sizeof (struct mlx4_ib_sqp), GFP_KERNEL);
+			if (!sqp)
+				return -ENOMEM;
+			qp = &sqp->qp;
+		} else {
+			qp = kzalloc(sizeof (struct mlx4_ib_qp), GFP_KERNEL);
+			if (!qp)
+				return -ENOMEM;
+		}
+	} else
+		qp = *caller_qp;
+
+	qp->mlx4_ib_qp_type = qp_type;
 
 	mutex_init(&qp->mutex);
 	spin_lock_init(&qp->sq.lock);
@@ -550,7 +715,7 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
 		if (init_attr->create_flags & IB_QP_CREATE_IPOIB_UD_LSO)
 			qp->flags |= MLX4_IB_QP_LSO;
 
-		err = set_kernel_sq_size(dev, &init_attr->cap, init_attr->qp_type, qp);
+		err = set_kernel_sq_size(dev, &init_attr->cap, qp_type, qp);
 		if (err)
 			goto err;
 
@@ -586,7 +751,13 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
 	}
 
 	if (sqpn) {
-		qpn = sqpn;
+		if (qp->mlx4_ib_qp_type & (MLX4_IB_QPT_PROXY_SMI_OWNER |
+		    MLX4_IB_QPT_PROXY_SMI | MLX4_IB_QPT_PROXY_GSI)) {
+			if (alloc_proxy_bufs(pd->device, qp)) {
+				err = -ENOMEM;
+				goto err_wrid;
+			}
+		}
 	} else {
 		/* Raw packet QPNs must be aligned to 8 bits. If not, the WQE
 		 * BlueFlame setup flow wrongly causes VLAN insertion. */
@@ -595,7 +766,7 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
 		else
 			err = mlx4_qp_reserve_range(dev->dev, 1, 1, &qpn);
 		if (err)
-			goto err_wrid;
+			goto err_proxy;
 	}
 
 	err = mlx4_qp_alloc(dev->dev, qpn, &qp->mqp);
@@ -613,13 +784,16 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
 	qp->doorbell_qpn = swab32(qp->mqp.qpn << 8);
 
 	qp->mqp.event = mlx4_ib_qp_event;
-
+	if (!*caller_qp)
+		*caller_qp = qp;
 	return 0;
 
 err_qpn:
 	if (!sqpn)
 		mlx4_qp_release_range(dev->dev, qpn, 1);
-
+err_proxy:
+	if (qp->mlx4_ib_qp_type == MLX4_IB_QPT_PROXY_GSI)
+		free_proxy_bufs(pd->device, qp);
 err_wrid:
 	if (pd->uobject) {
 		if (qp_has_rq(init_attr))
@@ -643,6 +817,8 @@ err_db:
 		mlx4_db_free(dev->dev, &qp->db);
 
 err:
+	if (!*caller_qp)
+		kfree(qp);
 	return err;
 }
 
@@ -755,7 +931,7 @@ static void destroy_qp_common(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp,
 
 	mlx4_qp_free(dev->dev, &qp->mqp);
 
-	if (!is_sqp(dev, qp))
+	if (!is_sqp(dev, qp) && !is_tunnel_qp(dev, qp))
 		mlx4_qp_release_range(dev->dev, qp->mqp.qpn, 1);
 
 	mlx4_mtt_cleanup(dev->dev, &qp->mtt);
@@ -768,6 +944,9 @@ static void destroy_qp_common(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp,
 	} else {
 		kfree(qp->sq.wrid);
 		kfree(qp->rq.wrid);
+		if (qp->mlx4_ib_qp_type & (MLX4_IB_QPT_PROXY_SMI_OWNER |
+		    MLX4_IB_QPT_PROXY_SMI | MLX4_IB_QPT_PROXY_GSI))
+			free_proxy_bufs(&dev->ib_dev, qp);
 		mlx4_buf_free(dev->dev, qp->buf_size, &qp->buf);
 		if (qp->rq.wqe_cnt)
 			mlx4_db_free(dev->dev, &qp->db);
@@ -776,25 +955,46 @@ static void destroy_qp_common(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp,
 	del_gid_entries(qp);
 }
 
+static u32 get_sqp_num(struct mlx4_ib_dev *dev, struct ib_qp_init_attr *attr)
+{
+	/* Native or PPF */
+	if (!mlx4_is_mfunc(dev->dev) ||
+	    (mlx4_is_master(dev->dev) &&
+	     attr->create_flags & MLX4_IB_SRIOV_SQP)) {
+		return  dev->dev->phys_caps.base_sqpn +
+			(attr->qp_type == IB_QPT_SMI ? 0 : 2) +
+			attr->port_num - 1;
+	}
+	/* PF or VF -- creating proxies */
+	if (attr->qp_type == IB_QPT_SMI)
+		return dev->dev->caps.qp0_proxy[attr->port_num - 1];
+	else
+		return dev->dev->caps.qp1_proxy[attr->port_num - 1];
+}
+
 struct ib_qp *mlx4_ib_create_qp(struct ib_pd *pd,
 				struct ib_qp_init_attr *init_attr,
 				struct ib_udata *udata)
 {
-	struct mlx4_ib_sqp *sqp;
-	struct mlx4_ib_qp *qp;
+	struct mlx4_ib_qp *qp = NULL;
 	int err;
 	u16 xrcdn = 0;
 
 	/*
-	 * We only support LSO and multicast loopback blocking, and
-	 * only for kernel UD QPs.
+	 * We only support LSO, vendor flag1, and multicast loopback blocking,
+	 * and only for kernel UD QPs.
 	 */
-	if (init_attr->create_flags & ~(IB_QP_CREATE_IPOIB_UD_LSO |
-					IB_QP_CREATE_BLOCK_MULTICAST_LOOPBACK))
+	if (init_attr->create_flags & ~(MLX4_IB_QP_LSO |
+					MLX4_IB_QP_BLOCK_MULTICAST_LOOPBACK |
+					MLX4_IB_SRIOV_TUNNEL_QP | MLX4_IB_SRIOV_SQP))
 		return ERR_PTR(-EINVAL);
 
 	if (init_attr->create_flags &&
-	    (udata || init_attr->qp_type != IB_QPT_UD))
+	    (udata ||
+	     ((init_attr->create_flags & ~MLX4_IB_SRIOV_SQP) &&
+	      init_attr->qp_type != IB_QPT_UD) ||
+	     ((init_attr->create_flags & MLX4_IB_SRIOV_SQP) &&
+	      init_attr->qp_type > IB_QPT_GSI)))
 		return ERR_PTR(-EINVAL);
 
 	switch (init_attr->qp_type) {
@@ -810,18 +1010,17 @@ struct ib_qp *mlx4_ib_create_qp(struct ib_pd *pd,
 		/* fall through */
 	case IB_QPT_RC:
 	case IB_QPT_UC:
-	case IB_QPT_UD:
 	case IB_QPT_RAW_PACKET:
-	{
 		qp = kzalloc(sizeof *qp, GFP_KERNEL);
 		if (!qp)
 			return ERR_PTR(-ENOMEM);
-
-		err = create_qp_common(to_mdev(pd->device), pd, init_attr, udata, 0, qp);
-		if (err) {
-			kfree(qp);
+		/* fall through */
+	case IB_QPT_UD:
+	{
+		err = create_qp_common(to_mdev(pd->device), pd, init_attr,
+				       udata, 0, &qp);
+		if (err)
 			return ERR_PTR(err);
-		}
 
 		qp->ibqp.qp_num = qp->mqp.qpn;
 		qp->xrcdn = xrcdn;
@@ -835,21 +1034,11 @@ struct ib_qp *mlx4_ib_create_qp(struct ib_pd *pd,
 		if (udata)
 			return ERR_PTR(-EINVAL);
 
-		sqp = kzalloc(sizeof *sqp, GFP_KERNEL);
-		if (!sqp)
-			return ERR_PTR(-ENOMEM);
-
-		qp = &sqp->qp;
-
 		err = create_qp_common(to_mdev(pd->device), pd, init_attr, udata,
-				       to_mdev(pd->device)->dev->caps.sqp_start +
-				       (init_attr->qp_type == IB_QPT_SMI ? 0 : 2) +
-				       init_attr->port_num - 1,
-				       qp);
-		if (err) {
-			kfree(sqp);
+				       get_sqp_num(to_mdev(pd->device), init_attr),
+				       &qp);
+		if (err)
 			return ERR_PTR(err);
-		}
 
 		qp->port	= init_attr->port_num;
 		qp->ibqp.qp_num = init_attr->qp_type == IB_QPT_SMI ? 0 : 1;
@@ -884,18 +1073,27 @@ int mlx4_ib_destroy_qp(struct ib_qp *qp)
 	return 0;
 }
 
-static int to_mlx4_st(enum ib_qp_type type)
+static int to_mlx4_st(struct mlx4_ib_dev *dev, enum mlx4_ib_qp_type type)
 {
 	switch (type) {
-	case IB_QPT_RC:		return MLX4_QP_ST_RC;
-	case IB_QPT_UC:		return MLX4_QP_ST_UC;
-	case IB_QPT_UD:		return MLX4_QP_ST_UD;
-	case IB_QPT_XRC_INI:
-	case IB_QPT_XRC_TGT:	return MLX4_QP_ST_XRC;
-	case IB_QPT_SMI:
-	case IB_QPT_GSI:
-	case IB_QPT_RAW_PACKET:	return MLX4_QP_ST_MLX;
-	default:		return -1;
+	case MLX4_IB_QPT_RC:		return MLX4_QP_ST_RC;
+	case MLX4_IB_QPT_UC:		return MLX4_QP_ST_UC;
+	case MLX4_IB_QPT_UD:		return MLX4_QP_ST_UD;
+	case MLX4_IB_QPT_XRC_INI:
+	case MLX4_IB_QPT_XRC_TGT:	return MLX4_QP_ST_XRC;
+	case MLX4_IB_QPT_SMI:
+	case MLX4_IB_QPT_GSI:
+	case MLX4_IB_QPT_RAW_PACKET:	return MLX4_QP_ST_MLX;
+
+	case MLX4_IB_QPT_PROXY_SMI_OWNER:
+	case MLX4_IB_QPT_TUN_SMI_OWNER:	return (mlx4_is_mfunc(dev->dev) ?
+						MLX4_QP_ST_MLX : -1);
+	case MLX4_IB_QPT_PROXY_SMI:
+	case MLX4_IB_QPT_TUN_SMI:
+	case MLX4_IB_QPT_PROXY_GSI:
+	case MLX4_IB_QPT_TUN_GSI:	return (mlx4_is_mfunc(dev->dev) ?
+						MLX4_QP_ST_UD : -1);
+	default:			return -1;
 	}
 }
 
@@ -1043,7 +1241,7 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
 		return -ENOMEM;
 
 	context->flags = cpu_to_be32((to_mlx4_state(new_state) << 28) |
-				     (to_mlx4_st(ibqp->qp_type) << 16));
+				     (to_mlx4_st(dev, qp->mlx4_ib_qp_type) << 16));
 
 	if (!(attr_mask & IB_QP_PATH_MIG_STATE))
 		context->flags |= cpu_to_be32(MLX4_QP_PM_MIGRATED << 11);
@@ -1121,13 +1319,16 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
 	}
 
 	if (attr_mask & IB_QP_PKEY_INDEX) {
+		if (qp->mlx4_ib_qp_type & MLX4_IB_QPT_ANY_SRIOV)
+			context->pri_path.disable_pkey_check = 0x40;
 		context->pri_path.pkey_index = attr->pkey_index;
 		optpar |= MLX4_QP_OPTPAR_PKEY_INDEX;
 	}
 
 	if (attr_mask & IB_QP_AV) {
 		if (mlx4_set_path(dev, &attr->ah_attr, &context->pri_path,
-				  attr_mask & IB_QP_PORT ? attr->port_num : qp->port))
+				  attr_mask & IB_QP_PORT ?
+				  attr->port_num : qp->port))
 			goto out;
 
 		optpar |= (MLX4_QP_OPTPAR_PRIMARY_ADDR_PATH |
@@ -1210,8 +1411,24 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
 	if (attr_mask & IB_QP_RQ_PSN)
 		context->rnr_nextrecvpsn |= cpu_to_be32(attr->rq_psn);
 
+	/* proxy and tunnel qp qkeys will be changed in modify-qp wrappers */
 	if (attr_mask & IB_QP_QKEY) {
-		context->qkey = cpu_to_be32(attr->qkey);
+		if (qp->mlx4_ib_qp_type &
+		    (MLX4_IB_QPT_PROXY_SMI_OWNER | MLX4_IB_QPT_TUN_SMI_OWNER))
+			context->qkey = cpu_to_be32(IB_QP_SET_QKEY);
+		else {
+			if (mlx4_is_mfunc(dev->dev) &&
+			    !(qp->mlx4_ib_qp_type & MLX4_IB_QPT_ANY_SRIOV) &&
+			    (attr->qkey & MLX4_RESERVED_QKEY_MASK) ==
+			    MLX4_RESERVED_QKEY_BASE) {
+				pr_err("Cannot use reserved QKEY"
+				       " 0x%x (range 0xffff0000..0xffffffff"
+				       " is reserved)\n", attr->qkey);
+				err = -EINVAL;
+				goto out;
+			}
+			context->qkey = cpu_to_be32(attr->qkey);
+		}
 		optpar |= MLX4_QP_OPTPAR_Q_KEY;
 	}
 
@@ -1227,10 +1444,17 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
 	     ibqp->qp_type == IB_QPT_UD ||
 	     ibqp->qp_type == IB_QPT_RAW_PACKET)) {
 		context->pri_path.sched_queue = (qp->port - 1) << 6;
-		if (is_qp0(dev, qp))
+		if (qp->mlx4_ib_qp_type == MLX4_IB_QPT_SMI ||
+		    qp->mlx4_ib_qp_type &
+		    (MLX4_IB_QPT_PROXY_SMI_OWNER | MLX4_IB_QPT_TUN_SMI_OWNER)) {
 			context->pri_path.sched_queue |= MLX4_IB_DEFAULT_QP0_SCHED_QUEUE;
-		else
+			if (qp->mlx4_ib_qp_type != MLX4_IB_QPT_SMI)
+				context->pri_path.fl = 0x80;
+		} else {
+			if (qp->mlx4_ib_qp_type & MLX4_IB_QPT_ANY_SRIOV)
+				context->pri_path.fl = 0x80;
 			context->pri_path.sched_queue |= MLX4_IB_DEFAULT_SCHED_QUEUE;
+		}
 	}
 
 	if (cur_state == IB_QPS_RTS && new_state == IB_QPS_SQD	&&
@@ -1346,7 +1570,7 @@ int mlx4_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
 	}
 
 	if ((attr_mask & IB_QP_PORT) &&
-	    (attr->port_num == 0 || attr->port_num > dev->dev->caps.num_ports)) {
+	    (attr->port_num == 0 || attr->port_num > dev->num_ports)) {
 		pr_debug("qpn 0x%x: invalid port number (%d) specified "
 			 "for transition %d to %d. qp_type %d\n",
 			 ibqp->qp_num, attr->port_num, cur_state,
@@ -1400,6 +1624,114 @@ out:
 	return err;
 }
 
+static int build_sriov_qp0_header(struct mlx4_ib_sqp *sqp,
+				  struct ib_send_wr *wr,
+				  void *wqe, unsigned *mlx_seg_len)
+{
+	struct mlx4_ib_dev *mdev = to_mdev(sqp->qp.ibqp.device);
+	struct ib_device *ib_dev = &mdev->ib_dev;
+	struct mlx4_wqe_mlx_seg *mlx = wqe;
+	struct mlx4_wqe_inline_seg *inl = wqe + sizeof *mlx;
+	struct mlx4_ib_ah *ah = to_mah(wr->wr.ud.ah);
+	u16 pkey;
+	u32 qkey;
+	int send_size;
+	int header_size;
+	int spc;
+	int i;
+
+	if (wr->opcode != IB_WR_SEND)
+		return -EINVAL;
+
+	send_size = 0;
+
+	for (i = 0; i < wr->num_sge; ++i)
+		send_size += wr->sg_list[i].length;
+
+	/* for proxy-qp0 sends, need to add in size of tunnel header */
+	/* for tunnel-qp0 sends, tunnel header is already in s/g list */
+	if (sqp->qp.mlx4_ib_qp_type == MLX4_IB_QPT_PROXY_SMI_OWNER)
+		send_size += sizeof (struct mlx4_ib_tunnel_header);
+
+	ib_ud_header_init(send_size, 1, 0, 0, 0, 0, &sqp->ud_header);
+
+	if (sqp->qp.mlx4_ib_qp_type == MLX4_IB_QPT_PROXY_SMI_OWNER) {
+		sqp->ud_header.lrh.service_level =
+			be32_to_cpu(ah->av.ib.sl_tclass_flowlabel) >> 28;
+		sqp->ud_header.lrh.destination_lid =
+			cpu_to_be16(ah->av.ib.g_slid & 0x7f);
+		sqp->ud_header.lrh.source_lid =
+			cpu_to_be16(ah->av.ib.g_slid & 0x7f);
+	}
+
+	mlx->flags &= cpu_to_be32(MLX4_WQE_CTRL_CQ_UPDATE);
+
+	/* force loopback */
+	mlx->flags |= cpu_to_be32(MLX4_WQE_MLX_VL15 | 0x1 | MLX4_WQE_MLX_SLR);
+	mlx->rlid = sqp->ud_header.lrh.destination_lid;
+
+	sqp->ud_header.lrh.virtual_lane    = 0;
+	sqp->ud_header.bth.solicited_event = !!(wr->send_flags & IB_SEND_SOLICITED);
+	ib_get_cached_pkey(ib_dev, sqp->qp.port, 0, &pkey);
+	sqp->ud_header.bth.pkey = cpu_to_be16(pkey);
+	if (sqp->qp.mlx4_ib_qp_type == MLX4_IB_QPT_TUN_SMI_OWNER)
+		sqp->ud_header.bth.destination_qpn = cpu_to_be32(wr->wr.ud.remote_qpn);
+	else
+		sqp->ud_header.bth.destination_qpn =
+			cpu_to_be32(mdev->dev->caps.qp0_tunnel[sqp->qp.port - 1]);
+
+	sqp->ud_header.bth.psn = cpu_to_be32((sqp->send_psn++) & ((1 << 24) - 1));
+	if (mlx4_get_parav_qkey(mdev->dev, sqp->qp.mqp.qpn, &qkey))
+		return -EINVAL;
+	sqp->ud_header.deth.qkey = cpu_to_be32(qkey);
+	sqp->ud_header.deth.source_qpn = cpu_to_be32(sqp->qp.mqp.qpn);
+
+	sqp->ud_header.bth.opcode        = IB_OPCODE_UD_SEND_ONLY;
+	sqp->ud_header.immediate_present = 0;
+
+	header_size = ib_ud_header_pack(&sqp->ud_header, sqp->header_buf);
+
+	/*
+	 * Inline data segments may not cross a 64 byte boundary.  If
+	 * our UD header is bigger than the space available up to the
+	 * next 64 byte boundary in the WQE, use two inline data
+	 * segments to hold the UD header.
+	 */
+	spc = MLX4_INLINE_ALIGN -
+	      ((unsigned long) (inl + 1) & (MLX4_INLINE_ALIGN - 1));
+	if (header_size <= spc) {
+		inl->byte_count = cpu_to_be32(1 << 31 | header_size);
+		memcpy(inl + 1, sqp->header_buf, header_size);
+		i = 1;
+	} else {
+		inl->byte_count = cpu_to_be32(1 << 31 | spc);
+		memcpy(inl + 1, sqp->header_buf, spc);
+
+		inl = (void *) (inl + 1) + spc;
+		memcpy(inl + 1, sqp->header_buf + spc, header_size - spc);
+		/*
+		 * Need a barrier here to make sure all the data is
+		 * visible before the byte_count field is set.
+		 * Otherwise the HCA prefetcher could grab the 64-byte
+		 * chunk with this inline segment and get a valid (!=
+		 * 0xffffffff) byte count but stale data, and end up
+		 * generating a packet with bad headers.
+		 *
+		 * The first inline segment's byte_count field doesn't
+		 * need a barrier, because it comes after a
+		 * control/MLX segment and therefore is at an offset
+		 * of 16 mod 64.
+		 */
+		wmb();
+		inl->byte_count = cpu_to_be32(1 << 31 | (header_size - spc));
+		i = 2;
+	}
+
+	*mlx_seg_len =
+	ALIGN(i * sizeof (struct mlx4_wqe_inline_seg) + header_size, 16);
+	return 0;
+}
+
 static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_send_wr *wr,
 			    void *wqe, unsigned *mlx_seg_len)
 {
@@ -1418,6 +1750,7 @@ static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_send_wr *wr,
 	int is_vlan = 0;
 	int is_grh;
 	u16 vlan;
+	int err = 0;
 
 	send_size = 0;
 	for (i = 0; i < wr->num_sge; ++i)
@@ -1426,8 +1759,24 @@ static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_send_wr *wr,
 	is_eth = rdma_port_get_link_layer(sqp->qp.ibqp.device, sqp->qp.port) == IB_LINK_LAYER_ETHERNET;
 	is_grh = mlx4_ib_ah_grh_present(ah);
 	if (is_eth) {
-		ib_get_cached_gid(ib_dev, be32_to_cpu(ah->av.ib.port_pd) >> 24,
-				  ah->av.ib.gid_index, &sgid);
+		if (mlx4_is_mfunc(to_mdev(ib_dev)->dev)) {
+			/* When multi-function is enabled, the ib_core gid
+			 * indexes don't necessarily match the hw ones, so
+			 * we must use our own cache */
+			sgid.global.subnet_prefix =
+				to_mdev(ib_dev)->sriov.demux[sqp->qp.port - 1].
+				subnet_prefix;
+			sgid.global.interface_id =
+				to_mdev(ib_dev)->sriov.demux[sqp->qp.port - 1].
+				guid_cache[ah->av.ib.gid_index];
+		} else  {
+			err = ib_get_cached_gid(ib_dev,
+						be32_to_cpu(ah->av.ib.port_pd) >> 24,
+						ah->av.ib.gid_index, &sgid);
+			if (err)
+				return err;
+		}
+
 		vlan = rdma_get_vlan_id(&sgid);
 		is_vlan = vlan < 0x1000;
 	}
@@ -1446,8 +1795,21 @@ static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_send_wr *wr,
 		sqp->ud_header.grh.flow_label    =
 			ah->av.ib.sl_tclass_flowlabel & cpu_to_be32(0xfffff);
 		sqp->ud_header.grh.hop_limit     = ah->av.ib.hop_limit;
-		ib_get_cached_gid(ib_dev, be32_to_cpu(ah->av.ib.port_pd) >> 24,
-				  ah->av.ib.gid_index, &sqp->ud_header.grh.source_gid);
+		if (mlx4_is_mfunc(to_mdev(ib_dev)->dev)) {
+			/* When multi-function is enabled, the ib_core gid
+			 * indexes don't necessarily match the hw ones, so
+			 * we must use our own cache */
+			sqp->ud_header.grh.source_gid.global.subnet_prefix =
+				to_mdev(ib_dev)->sriov.demux[sqp->qp.port - 1].
+						       subnet_prefix;
+			sqp->ud_header.grh.source_gid.global.interface_id =
+				to_mdev(ib_dev)->sriov.demux[sqp->qp.port - 1].
+					       guid_cache[ah->av.ib.gid_index];
+		} else
+			ib_get_cached_gid(ib_dev,
+					  be32_to_cpu(ah->av.ib.port_pd) >> 24,
+					  ah->av.ib.gid_index,
+					  &sqp->ud_header.grh.source_gid);
 		memcpy(sqp->ud_header.grh.destination_gid.raw,
 		       ah->av.ib.dgid, 16);
 	}
@@ -1459,6 +1821,8 @@ static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_send_wr *wr,
 					  (sqp->ud_header.lrh.destination_lid ==
 					   IB_LID_PERMISSIVE ? MLX4_WQE_MLX_SLR : 0) |
 					  (sqp->ud_header.lrh.service_level << 8));
+		if (ah->av.ib.port_pd & cpu_to_be32(0x80000000))
+			mlx->flags |= cpu_to_be32(0x1); /* force loopback */
 		mlx->rlid = sqp->ud_header.lrh.destination_lid;
 	}
 
@@ -1667,6 +2031,63 @@ static void set_datagram_seg(struct mlx4_wqe_datagram_seg *dseg,
 	memcpy(dseg->mac, to_mah(wr->wr.ud.ah)->av.eth.mac, 6);
 }
 
+static void set_tunnel_datagram_seg(struct mlx4_ib_dev *dev,
+				    struct mlx4_wqe_datagram_seg *dseg,
+				    struct ib_send_wr *wr, enum ib_qp_type qpt)
+{
+	union mlx4_ext_av *av = &to_mah(wr->wr.ud.ah)->av;
+	struct mlx4_av sqp_av = {0};
+	int port = *((u8 *) &av->ib.port_pd) & 0x3;
+
+	/* force loopback */
+	sqp_av.port_pd = av->ib.port_pd | cpu_to_be32(0x80000000);
+	sqp_av.g_slid = av->ib.g_slid & 0x7f; /* no GRH */
+	sqp_av.sl_tclass_flowlabel = av->ib.sl_tclass_flowlabel &
+			cpu_to_be32(0xf0000000);
+
+	memcpy(dseg->av, &sqp_av, sizeof (struct mlx4_av));
+	/* This function used only for sending on QP1 proxies */
+	dseg->dqpn = cpu_to_be32(dev->dev->caps.qp1_tunnel[port - 1]);
+	/* Use QKEY from the QP context, which is set by master */
+	dseg->qkey = cpu_to_be32(IB_QP_SET_QKEY);
+}
+
+static void build_tunnel_header(struct ib_send_wr *wr, void *wqe, unsigned *mlx_seg_len)
+{
+	struct mlx4_wqe_inline_seg *inl = wqe;
+	struct mlx4_ib_tunnel_header hdr;
+	struct mlx4_ib_ah *ah = to_mah(wr->wr.ud.ah);
+	int spc;
+	int i;
+
+	memcpy(&hdr.av, &ah->av, sizeof hdr.av);
+	hdr.remote_qpn = cpu_to_be32(wr->wr.ud.remote_qpn);
+	hdr.pkey_index = cpu_to_be16(wr->wr.ud.pkey_index);
+	hdr.qkey = cpu_to_be32(wr->wr.ud.remote_qkey);
+
+	spc = MLX4_INLINE_ALIGN -
+		((unsigned long) (inl + 1) & (MLX4_INLINE_ALIGN - 1));
+	if (sizeof (hdr) <= spc) {
+		memcpy(inl + 1, &hdr, sizeof (hdr));
+		wmb();
+		inl->byte_count = cpu_to_be32(1 << 31 | sizeof (hdr));
+		i = 1;
+	} else {
+		memcpy(inl + 1, &hdr, spc);
+		wmb();
+		inl->byte_count = cpu_to_be32(1 << 31 | spc);
+
+		inl = (void *) (inl + 1) + spc;
+		memcpy(inl + 1, (void *) &hdr + spc, sizeof (hdr) - spc);
+		wmb();
+		inl->byte_count = cpu_to_be32(1 << 31 | (sizeof (hdr) - spc));
+		i = 2;
+	}
+
+	*mlx_seg_len =
+		ALIGN(i * sizeof (struct mlx4_wqe_inline_seg) + sizeof (hdr), 16);
+}
+
 static void set_mlx_icrc_seg(void *dseg)
 {
 	u32 *t = dseg;
@@ -1748,6 +2169,13 @@ static __be32 send_ieth(struct ib_send_wr *wr)
 	}
 }
 
+static void add_zero_len_inline(void *wqe)
+{
+	struct mlx4_wqe_inline_seg *inl = wqe;
+	memset(wqe, 0, 16);
+	inl->byte_count = cpu_to_be32(1 << 31);
+}
+
 int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
 		      struct ib_send_wr **bad_wr)
 {
@@ -1806,9 +2234,9 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
 		wqe += sizeof *ctrl;
 		size = sizeof *ctrl / 16;
 
-		switch (ibqp->qp_type) {
-		case IB_QPT_RC:
-		case IB_QPT_UC:
+		switch (qp->mlx4_ib_qp_type) {
+		case MLX4_IB_QPT_RC:
+		case MLX4_IB_QPT_UC:
 			switch (wr->opcode) {
 			case IB_WR_ATOMIC_CMP_AND_SWP:
 			case IB_WR_ATOMIC_FETCH_AND_ADD:
@@ -1869,7 +2297,25 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
 			}
 			break;
 
-		case IB_QPT_UD:
+		case MLX4_IB_QPT_TUN_SMI_OWNER:
+			err =  build_sriov_qp0_header(to_msqp(qp), wr, ctrl, &seglen);
+			if (unlikely(err)) {
+				*bad_wr = wr;
+				goto out;
+			}
+			wqe  += seglen;
+			size += seglen / 16;
+			break;
+		case MLX4_IB_QPT_TUN_SMI:
+		case MLX4_IB_QPT_TUN_GSI:
+			/* this is a UD qp used in MAD responses to slaves. */
+			set_datagram_seg(wqe, wr);
+			/* set the forced-loopback bit in the data seg av */
+			*(__be32 *) wqe |= cpu_to_be32(0x80000000);
+			wqe  += sizeof (struct mlx4_wqe_datagram_seg);
+			size += sizeof (struct mlx4_wqe_datagram_seg) / 16;
+			break;
+		case MLX4_IB_QPT_UD:
 			set_datagram_seg(wqe, wr);
 			wqe  += sizeof (struct mlx4_wqe_datagram_seg);
 			size += sizeof (struct mlx4_wqe_datagram_seg) / 16;
@@ -1886,8 +2332,47 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
 			}
 			break;
 
-		case IB_QPT_SMI:
-		case IB_QPT_GSI:
+		case MLX4_IB_QPT_PROXY_SMI_OWNER:
+			if (unlikely(!mlx4_is_master(to_mdev(ibqp->device)->dev))) {
+				err = -ENOSYS;
+				*bad_wr = wr;
+				goto out;
+			}
+			err = build_sriov_qp0_header(to_msqp(qp), wr, ctrl, &seglen);
+			if (unlikely(err)) {
+				*bad_wr = wr;
+				goto out;
+			}
+			wqe  += seglen;
+			size += seglen / 16;
+			/* to start tunnel header on a cache-line boundary */
+			add_zero_len_inline(wqe);
+			wqe += 16;
+			size++;
+			build_tunnel_header(wr, wqe, &seglen);
+			wqe  += seglen;
+			size += seglen / 16;
+			break;
+		case MLX4_IB_QPT_PROXY_SMI:
+			/* don't allow QP0 sends on guests */
+			err = -ENOSYS;
+			*bad_wr = wr;
+			goto out;
+		case MLX4_IB_QPT_PROXY_GSI:
+			/* If we are tunneling special qps, this is a UD qp.
+			 * In this case we first add a UD segment targeting
+			 * the tunnel qp, and then add a header with address
+			 * information */
+			set_tunnel_datagram_seg(to_mdev(ibqp->device), wqe, wr, ibqp->qp_type);
+			wqe  += sizeof (struct mlx4_wqe_datagram_seg);
+			size += sizeof (struct mlx4_wqe_datagram_seg) / 16;
+			build_tunnel_header(wr, wqe, &seglen);
+			wqe  += seglen;
+			size += seglen / 16;
+			break;
+
+		case MLX4_IB_QPT_SMI:
+		case MLX4_IB_QPT_GSI:
 			err = build_mlx_header(to_msqp(qp), wr, ctrl, &seglen);
 			if (unlikely(err)) {
 				*bad_wr = wr;
@@ -1913,8 +2398,10 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
 		size += wr->num_sge * (sizeof (struct mlx4_wqe_data_seg) / 16);
 
 		/* Add one more inline data segment for ICRC for MLX sends */
-		if (unlikely(qp->ibqp.qp_type == IB_QPT_SMI ||
-			     qp->ibqp.qp_type == IB_QPT_GSI)) {
+		if (unlikely(qp->mlx4_ib_qp_type == MLX4_IB_QPT_SMI ||
+			     qp->mlx4_ib_qp_type == MLX4_IB_QPT_GSI ||
+			     qp->mlx4_ib_qp_type &
+			     (MLX4_IB_QPT_PROXY_SMI_OWNER | MLX4_IB_QPT_TUN_SMI_OWNER))) {
 			set_mlx_icrc_seg(dseg + 1);
 			size += sizeof (struct mlx4_wqe_data_seg) / 16;
 		}
@@ -2006,8 +2493,10 @@ int mlx4_ib_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *wr,
 	int err = 0;
 	int nreq;
 	int ind;
+	int max_gs;
 	int i;
 
+	max_gs = qp->rq.max_gs;
 	spin_lock_irqsave(&qp->rq.lock, flags);
 
 	ind = qp->rq.head & (qp->rq.wqe_cnt - 1);
@@ -2027,10 +2516,25 @@ int mlx4_ib_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *wr,
 
 		scat = get_recv_wqe(qp, ind);
 
+		if (qp->mlx4_ib_qp_type & (MLX4_IB_QPT_PROXY_SMI_OWNER |
+		    MLX4_IB_QPT_PROXY_SMI | MLX4_IB_QPT_PROXY_GSI)) {
+			ib_dma_sync_single_for_device(ibqp->device,
+						      qp->sqp_proxy_rcv[ind].map,
+						      sizeof (struct mlx4_ib_proxy_sqp_hdr),
+						      DMA_FROM_DEVICE);
+			scat->byte_count =
+				cpu_to_be32(sizeof (struct mlx4_ib_proxy_sqp_hdr));
+			/* use dma lkey from upper layer entry */
+			scat->lkey = cpu_to_be32(wr->sg_list->lkey);
+			scat->addr = cpu_to_be64(qp->sqp_proxy_rcv[ind].map);
+			scat++;
+			max_gs--;
+		}
+
 		for (i = 0; i < wr->num_sge; ++i)
 			__set_data_seg(scat + i, wr->sg_list + i);
 
-		if (i < qp->rq.max_gs) {
+		if (i < max_gs) {
 			scat[i].byte_count = 0;
 			scat[i].lkey       = cpu_to_be32(MLX4_INVALID_LKEY);
 			scat[i].addr       = 0;
@@ -2225,6 +2729,10 @@ done:
 	if (qp->flags & MLX4_IB_QP_LSO)
 		qp_init_attr->create_flags |= IB_QP_CREATE_IPOIB_UD_LSO;
 
+	qp_init_attr->sq_sig_type =
+		qp->sq_signal_bits == cpu_to_be32(MLX4_WQE_CTRL_CQ_UPDATE) ?
+		IB_SIGNAL_ALL_WR : IB_SIGNAL_REQ_WR;
+
 out:
 	mutex_unlock(&qp->mutex);
 	return err;
diff --git a/drivers/infiniband/hw/mlx4/sysfs.c b/drivers/infiniband/hw/mlx4/sysfs.c
new file mode 100644
index 0000000..5b2a01d
--- /dev/null
+++ b/drivers/infiniband/hw/mlx4/sysfs.c
@@ -0,0 +1,794 @@
+/*
+ * Copyright (c) 2012 Mellanox Technologies.  All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/*#include "core_priv.h"*/
+#include "mlx4_ib.h"
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/stat.h>
+
+#include <rdma/ib_mad.h>
+/*show_admin_alias_guid returns the administratively assigned value of that GUID.
+ * Values returned in buf parameter string:
+ *	0			- requests opensm to assign a value.
+ *	ffffffffffffffff	- delete this entry.
+ *	other			- value assigned by administrator.
+ */
+static ssize_t show_admin_alias_guid(struct device *dev,
+			      struct device_attribute *attr, char *buf)
+{
+	int record_num;/*0-15*/
+	int guid_index_in_rec; /*0 - 7*/
+	struct mlx4_ib_iov_sysfs_attr *mlx4_ib_iov_dentry =
+		container_of(attr, struct mlx4_ib_iov_sysfs_attr, dentry);
+	struct mlx4_ib_iov_port *port = mlx4_ib_iov_dentry->ctx;
+	struct mlx4_ib_dev *mdev = port->dev;
+
+	record_num = mlx4_ib_iov_dentry->entry_num / 8 ;
+	guid_index_in_rec = mlx4_ib_iov_dentry->entry_num % 8 ;
+
+	return sprintf(buf, "%llx\n",
+		       be64_to_cpu(*(__be64 *)&mdev->sriov.alias_guid.
+				   ports_guid[port->num - 1].
+				   all_rec_per_port[record_num].
+				   all_recs[8 * guid_index_in_rec]));
+}
+
+/* store_admin_alias_guid stores the (new) administratively assigned value of that GUID.
+ * Values in buf parameter string:
+ *	0			- requests opensm to assign a value.
+ *	0xffffffffffffffff	- delete this entry.
+ *	other			- guid value assigned by the administrator.
+ */
+static ssize_t store_admin_alias_guid(struct device *dev,
+				      struct device_attribute *attr,
+				      const char *buf, size_t count)
+{
+	int record_num;/*0-15*/
+	int guid_index_in_rec; /*0 - 7*/
+	struct mlx4_ib_iov_sysfs_attr *mlx4_ib_iov_dentry =
+		container_of(attr, struct mlx4_ib_iov_sysfs_attr, dentry);
+	struct mlx4_ib_iov_port *port = mlx4_ib_iov_dentry->ctx;
+	struct mlx4_ib_dev *mdev = port->dev;
+	u64 sysadmin_ag_val;
+
+	record_num = mlx4_ib_iov_dentry->entry_num / 8;
+	guid_index_in_rec = mlx4_ib_iov_dentry->entry_num % 8;
+	if (0 == record_num && 0 == guid_index_in_rec) {
+		pr_err("GUID 0 block 0 is RO\n");
+		return count;
+	}
+	sscanf(buf, "%llx", &sysadmin_ag_val);
+	*(__be64 *)&mdev->sriov.alias_guid.ports_guid[port->num - 1].
+		all_rec_per_port[record_num].
+		all_recs[GUID_REC_SIZE * guid_index_in_rec] =
+			cpu_to_be64(sysadmin_ag_val);
+
+	/* Change the state to be pending for update */
+	mdev->sriov.alias_guid.ports_guid[port->num - 1].all_rec_per_port[record_num].status
+		= MLX4_GUID_INFO_STATUS_IDLE ;
+
+	mdev->sriov.alias_guid.ports_guid[port->num - 1].all_rec_per_port[record_num].method
+		= MLX4_GUID_INFO_RECORD_SET;
+
+	switch (sysadmin_ag_val) {
+	case MLX4_GUID_FOR_DELETE_VAL:
+		mdev->sriov.alias_guid.ports_guid[port->num - 1].all_rec_per_port[record_num].method
+			= MLX4_GUID_INFO_RECORD_DELETE;
+		mdev->sriov.alias_guid.ports_guid[port->num - 1].all_rec_per_port[record_num].ownership
+			= MLX4_GUID_SYSADMIN_ASSIGN;
+		break;
+	/* The sysadmin requests the SM to re-assign */
+	case MLX4_NOT_SET_GUID:
+		mdev->sriov.alias_guid.ports_guid[port->num - 1].all_rec_per_port[record_num].ownership
+			= MLX4_GUID_DRIVER_ASSIGN;
+		break;
+	/* The sysadmin requests a specific value.*/
+	default:
+		mdev->sriov.alias_guid.ports_guid[port->num - 1].all_rec_per_port[record_num].ownership
+			= MLX4_GUID_SYSADMIN_ASSIGN;
+		break;
+	}
+
+	/* set the record index */
+	mdev->sriov.alias_guid.ports_guid[port->num - 1].all_rec_per_port[record_num].guid_indexes
+		= mlx4_ib_get_aguid_comp_mask_from_ix(guid_index_in_rec);
+
+	mlx4_ib_init_alias_guid_work(mdev, port->num - 1);
+
+	return count;
+}
+
+static ssize_t show_port_gid(struct device *dev,
+			     struct device_attribute *attr,
+			     char *buf)
+{
+	struct mlx4_ib_iov_sysfs_attr *mlx4_ib_iov_dentry =
+		container_of(attr, struct mlx4_ib_iov_sysfs_attr, dentry);
+	struct mlx4_ib_iov_port *port = mlx4_ib_iov_dentry->ctx;
+	struct mlx4_ib_dev *mdev = port->dev;
+	union ib_gid gid;
+	ssize_t ret;
+
+	ret = __mlx4_ib_query_gid(&mdev->ib_dev, port->num,
+				  mlx4_ib_iov_dentry->entry_num, &gid, 1);
+	if (ret)
+		return ret;
+	ret = sprintf(buf, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
+		      be16_to_cpu(((__be16 *) gid.raw)[0]),
+		      be16_to_cpu(((__be16 *) gid.raw)[1]),
+		      be16_to_cpu(((__be16 *) gid.raw)[2]),
+		      be16_to_cpu(((__be16 *) gid.raw)[3]),
+		      be16_to_cpu(((__be16 *) gid.raw)[4]),
+		      be16_to_cpu(((__be16 *) gid.raw)[5]),
+		      be16_to_cpu(((__be16 *) gid.raw)[6]),
+		      be16_to_cpu(((__be16 *) gid.raw)[7]));
+	return ret;
+}
+
+static ssize_t show_phys_port_pkey(struct device *dev,
+				   struct device_attribute *attr,
+				   char *buf)
+{
+	struct mlx4_ib_iov_sysfs_attr *mlx4_ib_iov_dentry =
+		container_of(attr, struct mlx4_ib_iov_sysfs_attr, dentry);
+	struct mlx4_ib_iov_port *port = mlx4_ib_iov_dentry->ctx;
+	struct mlx4_ib_dev *mdev = port->dev;
+	u16 pkey;
+	ssize_t ret;
+
+	ret = __mlx4_ib_query_pkey(&mdev->ib_dev, port->num,
+				   mlx4_ib_iov_dentry->entry_num, &pkey, 1);
+	if (ret)
+		return ret;
+
+	return sprintf(buf, "0x%04x\n", pkey);
+}
+
+#define DENTRY_REMOVE(_dentry)						\
+do {									\
+	sysfs_remove_file((_dentry)->kobj, &(_dentry)->dentry.attr);	\
+} while (0);
+
+static int create_sysfs_entry(void *_ctx, struct mlx4_ib_iov_sysfs_attr *_dentry,
+			      char *_name, struct kobject *_kobj,
+			      ssize_t (*show)(struct device *dev,
+					      struct device_attribute *attr,
+					      char *buf),
+			      ssize_t (*store)(struct device *dev,
+					       struct device_attribute *attr,
+					       const char *buf, size_t count)
+			      )
+{
+	int ret = 0;
+	struct mlx4_ib_iov_sysfs_attr *vdentry = _dentry;
+
+	vdentry->ctx = _ctx;
+	vdentry->dentry.show = show;
+	vdentry->dentry.store = store;
+	sysfs_attr_init(&vdentry->dentry.attr);
+	vdentry->dentry.attr.name = vdentry->name;
+	vdentry->dentry.attr.mode = 0;
+	vdentry->kobj = _kobj;
+	snprintf(vdentry->name, 15, "%s", _name);
+
+	if (vdentry->dentry.store)
+		vdentry->dentry.attr.mode |= S_IWUSR;
+
+	if (vdentry->dentry.show)
+		vdentry->dentry.attr.mode |= S_IRUGO;
+
+	ret = sysfs_create_file(vdentry->kobj, &vdentry->dentry.attr);
+	if (ret) {
+		pr_err("failed to create %s\n", vdentry->dentry.attr.name);
+		vdentry->ctx = NULL;
+		return ret;
+	}
+
+	return ret;
+}
+
+int add_sysfs_port_mcg_attr(struct mlx4_ib_dev *device, int port_num,
+		struct attribute *attr)
+{
+	struct mlx4_ib_iov_port *port = &device->iov_ports[port_num - 1];
+	int ret;
+
+	ret = sysfs_create_file(port->mcgs_parent, attr);
+	if (ret)
+		pr_err("failed to create %s\n", attr->name);
+
+	return ret;
+}
+
+void del_sysfs_port_mcg_attr(struct mlx4_ib_dev *device, int port_num,
+		struct attribute *attr)
+{
+	struct mlx4_ib_iov_port *port = &device->iov_ports[port_num - 1];
+
+	sysfs_remove_file(port->mcgs_parent, attr);
+}
+
+static int add_port_entries(struct mlx4_ib_dev *device, int port_num)
+{
+	int i;
+	char buff[10];
+	struct mlx4_ib_iov_port *port = NULL;
+	int ret = 0 ;
+	struct ib_port_attr attr;
+
+	/* get the physical gid and pkey table sizes.*/
+	ret = __mlx4_ib_query_port(&device->ib_dev, port_num, &attr, 1);
+	if (ret)
+		goto err;
+
+	port = &device->iov_ports[port_num - 1];
+	port->dev = device;
+	port->num = port_num;
+	/* Directory structure:
+	 * iov -
+	 *   port num -
+	 *	admin_guids
+	 *	gids (operational)
+	 *	mcg_table
+	 */
+	port->dentr_ar = kzalloc(sizeof (struct mlx4_ib_iov_sysfs_attr_ar),
+				 GFP_KERNEL);
+	if (!port->dentr_ar) {
+		ret = -ENOMEM;
+		goto err;
+	}
+	sprintf(buff, "%d", port_num);
+	port->cur_port = kobject_create_and_add(buff,
+				 kobject_get(device->ports_parent));
+	if (!port->cur_port) {
+		ret = -ENOMEM;
+		goto kobj_create_err;
+	}
+	/* admin GUIDs */
+	port->admin_alias_parent = kobject_create_and_add("admin_guids",
+						  kobject_get(port->cur_port));
+	if (!port->admin_alias_parent) {
+		ret = -ENOMEM;
+		goto err_admin_guids;
+	}
+	for (i = 0 ; i < attr.gid_tbl_len; i++) {
+		sprintf(buff, "%d", i);
+		port->dentr_ar->dentries[i].entry_num = i;
+		ret = create_sysfs_entry(port, &port->dentr_ar->dentries[i],
+					  buff, port->admin_alias_parent,
+					  show_admin_alias_guid, store_admin_alias_guid);
+		if (ret)
+			goto err_admin_alias_parent;
+	}
+
+	/* gids subdirectory (operational gids) */
+	port->gids_parent = kobject_create_and_add("gids",
+						  kobject_get(port->cur_port));
+	if (!port->gids_parent) {
+		ret = -ENOMEM;
+		goto err_gids;
+	}
+
+	for (i = 0 ; i < attr.gid_tbl_len; i++) {
+		sprintf(buff, "%d", i);
+		port->dentr_ar->dentries[attr.gid_tbl_len + i].entry_num = i;
+		ret = create_sysfs_entry(port,
+					 &port->dentr_ar->dentries[attr.gid_tbl_len + i],
+					 buff,
+					 port->gids_parent, show_port_gid, NULL);
+		if (ret)
+			goto err_gids_parent;
+	}
+
+	/* physical port pkey table */
+	port->pkeys_parent =
+		kobject_create_and_add("pkeys", kobject_get(port->cur_port));
+	if (!port->pkeys_parent) {
+		ret = -ENOMEM;
+		goto err_pkeys;
+	}
+
+	for (i = 0 ; i < attr.pkey_tbl_len; i++) {
+		sprintf(buff, "%d", i);
+		port->dentr_ar->dentries[2 * attr.gid_tbl_len + i].entry_num = i;
+		ret = create_sysfs_entry(port,
+					 &port->dentr_ar->dentries[2 * attr.gid_tbl_len + i],
+					 buff, port->pkeys_parent,
+					 show_phys_port_pkey, NULL);
+		if (ret)
+			goto err_pkeys_parent;
+	}
+
+	/* MCGs table */
+	port->mcgs_parent =
+		kobject_create_and_add("mcgs", kobject_get(port->cur_port));
+	if (!port->mcgs_parent) {
+		ret = -ENOMEM;
+		goto err_mcgs;
+	}
+	return 0;
+
+err_mcgs:
+	kobject_put(port->cur_port);
+
+err_pkeys_parent:
+	kobject_put(port->pkeys_parent);
+
+err_pkeys:
+	kobject_put(port->cur_port);
+
+err_gids_parent:
+	kobject_put(port->gids_parent);
+
+err_gids:
+	kobject_put(port->cur_port);
+
+err_admin_alias_parent:
+	kobject_put(port->admin_alias_parent);
+
+err_admin_guids:
+	kobject_put(port->cur_port);
+	kobject_put(port->cur_port); /* once more for create_and_add buff */
+
+kobj_create_err:
+	kobject_put(device->ports_parent);
+	kfree(port->dentr_ar);
+
+err:
+	pr_err("add_port_entries FAILED: for port:%d, error: %d\n",
+	       port_num, ret);
+	return ret;
+}
+
+static void get_name(struct mlx4_ib_dev *dev, char *name, int i, int max)
+{
+	char base_name[9];
+
+	/* pci_name format is: bus:dev:func -> xxxx:yy:zz.n */
+	strlcpy(name, pci_name(dev->dev->pdev), max);
+	strncpy(base_name, name, 8); /*till xxxx:yy:*/
+	base_name[8] = '\0';
+	/* with no ARI only 3 last bits are used so when the fn is higher than 8
+	 * need to add it to the dev num, so count in the last number will be
+	 * modulo 8 */
+	sprintf(name, "%s%.2d.%d", base_name, (i/8), (i%8));
+}
+
+struct mlx4_port {
+	struct kobject         kobj;
+	struct mlx4_ib_dev    *dev;
+	struct attribute_group pkey_group;
+	struct attribute_group gid_group;
+	u8                     port_num;
+	int		       slave;
+};
+
+
+static void mlx4_port_release(struct kobject *kobj)
+{
+	struct mlx4_port *p = container_of(kobj, struct mlx4_port, kobj);
+	struct attribute *a;
+	int i;
+
+	for (i = 0; (a = p->pkey_group.attrs[i]); ++i)
+		kfree(a);
+	kfree(p->pkey_group.attrs);
+	for (i = 0; (a = p->gid_group.attrs[i]); ++i)
+		kfree(a);
+	kfree(p->gid_group.attrs);
+	kfree(p);
+}
+
+struct port_attribute {
+	struct attribute attr;
+	ssize_t (*show)(struct mlx4_port *, struct port_attribute *, char *buf);
+	ssize_t (*store)(struct mlx4_port *, struct port_attribute *,
+			 const char *buf, size_t count);
+};
+
+static ssize_t port_attr_show(struct kobject *kobj,
+			      struct attribute *attr, char *buf)
+{
+	struct port_attribute *port_attr =
+		container_of(attr, struct port_attribute, attr);
+	struct mlx4_port *p = container_of(kobj, struct mlx4_port, kobj);
+
+	if (!port_attr->show)
+		return -EIO;
+	return port_attr->show(p, port_attr, buf);
+}
+
+static ssize_t port_attr_store(struct kobject *kobj,
+			       struct attribute *attr,
+			       const char *buf, size_t size)
+{
+	struct port_attribute *port_attr =
+		container_of(attr, struct port_attribute, attr);
+	struct mlx4_port *p = container_of(kobj, struct mlx4_port, kobj);
+
+	if (!port_attr->store)
+		return -EIO;
+	return port_attr->store(p, port_attr, buf, size);
+}
+
+static const struct sysfs_ops port_sysfs_ops = {
+	.show = port_attr_show,
+	.store = port_attr_store,
+};
+
+static struct kobj_type port_type = {
+	.release    = mlx4_port_release,
+	.sysfs_ops  = &port_sysfs_ops,
+};
+
+struct port_table_attribute {
+	struct port_attribute	attr;
+	char			name[8];
+	int			index;
+};
+
+static ssize_t show_port_pkey(struct mlx4_port *p, struct port_attribute *attr,
+			      char *buf)
+{
+	struct port_table_attribute *tab_attr =
+		container_of(attr, struct port_table_attribute, attr);
+	ssize_t ret = -ENODEV;
+
+	if (p->dev->pkeys.virt2phys_pkey[p->slave][p->port_num - 1][tab_attr->index] >=
+	    (p->dev->dev->caps.pkey_table_len[p->port_num]))
+		ret = sprintf(buf, "none\n");
+	else
+		ret = sprintf(buf, "%d\n",
+			      p->dev->pkeys.virt2phys_pkey[p->slave]
+			      [p->port_num - 1][tab_attr->index]);
+	return ret;
+}
+
+static ssize_t store_port_pkey(struct mlx4_port *p, struct port_attribute *attr,
+			       const char *buf, size_t count)
+{
+	struct port_table_attribute *tab_attr =
+		container_of(attr, struct port_table_attribute, attr);
+	int idx;
+	int err;
+
+	/* do not allow remapping Dom0 virtual pkey table */
+	if (p->slave == mlx4_master_func_num(p->dev->dev))
+		return -EINVAL;
+
+	if (!strncasecmp(buf, "no", 2))
+		idx = p->dev->dev->phys_caps.pkey_phys_table_len[p->port_num] - 1;
+	else if (sscanf(buf, "%i", &idx) != 1 ||
+		 idx >= p->dev->dev->caps.pkey_table_len[p->port_num] ||
+		 idx < 0)
+		return -EINVAL;
+
+	p->dev->pkeys.virt2phys_pkey[p->slave][p->port_num - 1]
+				    [tab_attr->index] = idx;
+	mlx4_sync_pkey_table(p->dev->dev, p->slave, p->port_num,
+			     tab_attr->index, idx);
+	err = mlx4_gen_pkey_eqe(p->dev->dev, p->slave, p->port_num);
+	if (err) {
+		pr_err("mlx4_gen_pkey_eqe failed for slave %d,"
+		       " port %d, index %d\n", p->slave, p->port_num, idx);
+		return err;
+	}
+	return count;
+}
+
+static ssize_t show_port_gid_idx(struct mlx4_port *p,
+				 struct port_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%d\n", p->slave);
+}
+
+static struct attribute **
+alloc_group_attrs(ssize_t (*show)(struct mlx4_port *,
+				  struct port_attribute *, char *buf),
+		  ssize_t (*store)(struct mlx4_port *, struct port_attribute *,
+				   const char *buf, size_t count),
+		  int len)
+{
+	struct attribute **tab_attr;
+	struct port_table_attribute *element;
+	int i;
+
+	tab_attr = kcalloc(1 + len, sizeof (struct attribute *), GFP_KERNEL);
+	if (!tab_attr)
+		return NULL;
+
+	for (i = 0; i < len; i++) {
+		element = kzalloc(sizeof (struct port_table_attribute),
+				  GFP_KERNEL);
+		if (!element)
+			goto err;
+		if (snprintf(element->name, sizeof (element->name),
+			     "%d", i) >= sizeof (element->name)) {
+			kfree(element);
+			goto err;
+		}
+		sysfs_attr_init(&element->attr.attr);
+		element->attr.attr.name  = element->name;
+		if (store) {
+			element->attr.attr.mode  = S_IWUSR | S_IRUGO;
+			element->attr.store	 = store;
+		} else
+			element->attr.attr.mode  = S_IRUGO;
+
+		element->attr.show       = show;
+		element->index		 = i;
+		tab_attr[i] = &element->attr.attr;
+	}
+	return tab_attr;
+
+err:
+	while (--i >= 0)
+		kfree(tab_attr[i]);
+	kfree(tab_attr);
+	return NULL;
+}
+
+static int add_port(struct mlx4_ib_dev *dev, int port_num, int slave)
+{
+	struct mlx4_port *p;
+	int i;
+	int ret;
+
+	p = kzalloc(sizeof *p, GFP_KERNEL);
+	if (!p)
+		return -ENOMEM;
+
+	p->dev = dev;
+	p->port_num = port_num;
+	p->slave = slave;
+
+	ret = kobject_init_and_add(&p->kobj, &port_type,
+				   kobject_get(dev->dev_ports_parent[slave]),
+				   "%d", port_num);
+	if (ret)
+		goto err_alloc;
+
+	p->pkey_group.name  = "pkey_idx";
+	p->pkey_group.attrs =
+		alloc_group_attrs(show_port_pkey, store_port_pkey,
+				  dev->dev->caps.pkey_table_len[port_num]);
+	if (!p->pkey_group.attrs)
+		goto err_alloc;
+
+	ret = sysfs_create_group(&p->kobj, &p->pkey_group);
+	if (ret)
+		goto err_free_pkey;
+
+	p->gid_group.name  = "gid_idx";
+	p->gid_group.attrs = alloc_group_attrs(show_port_gid_idx, NULL, 1);
+	if (!p->gid_group.attrs)
+		goto err_free_pkey;
+
+	ret = sysfs_create_group(&p->kobj, &p->gid_group);
+	if (ret)
+		goto err_free_gid;
+
+	list_add_tail(&p->kobj.entry, &dev->pkeys.pkey_port_list[slave]);
+	return 0;
+
+err_free_gid:
+	kfree(p->gid_group.attrs[0]);
+	kfree(p->gid_group.attrs);
+
+err_free_pkey:
+	for (i = 0; i < dev->dev->caps.pkey_table_len[port_num]; ++i)
+		kfree(p->pkey_group.attrs[i]);
+	kfree(p->pkey_group.attrs);
+
+err_alloc:
+	kobject_put(dev->dev_ports_parent[slave]);
+	kfree(p);
+	return ret;
+}
+
+static int register_one_pkey_tree(struct mlx4_ib_dev *dev, int slave)
+{
+	char name[32];
+	int err;
+	int port;
+	struct kobject *p, *t;
+	struct mlx4_port *mport;
+
+	get_name(dev, name, slave, sizeof name);
+
+	dev->pkeys.device_parent[slave] =
+		kobject_create_and_add(name, kobject_get(dev->iov_parent));
+
+	if (!dev->pkeys.device_parent[slave]) {
+		err = -ENOMEM;
+		goto fail_dev;
+	}
+
+	INIT_LIST_HEAD(&dev->pkeys.pkey_port_list[slave]);
+
+	dev->dev_ports_parent[slave] =
+		kobject_create_and_add("ports",
+				       kobject_get(dev->pkeys.device_parent[slave]));
+
+	if (!dev->dev_ports_parent[slave]) {
+		err = -ENOMEM;
+		goto err_ports;
+	}
+
+	for (port = 1; port <= dev->dev->caps.num_ports; ++port) {
+		err = add_port(dev, port, slave);
+		if (err)
+			goto err_add;
+	}
+	return 0;
+
+err_add:
+	list_for_each_entry_safe(p, t,
+				 &dev->pkeys.pkey_port_list[slave],
+				 entry) {
+		list_del(&p->entry);
+		mport = container_of(p, struct mlx4_port, kobj);
+		sysfs_remove_group(p, &mport->pkey_group);
+		sysfs_remove_group(p, &mport->gid_group);
+		kobject_put(p);
+	}
+	kobject_put(dev->dev_ports_parent[slave]);
+
+err_ports:
+	kobject_put(dev->pkeys.device_parent[slave]);
+	/* extra put for the device_parent create_and_add */
+	kobject_put(dev->pkeys.device_parent[slave]);
+
+fail_dev:
+	kobject_put(dev->iov_parent);
+	return err;
+}
+
+static int register_pkey_tree(struct mlx4_ib_dev *device)
+{
+	int i;
+
+	if (!mlx4_is_master(device->dev))
+		return 0;
+
+	for (i = 0; i <= device->dev->num_vfs; ++i)
+		register_one_pkey_tree(device, i);
+
+	return 0;
+}
+
+static void unregister_pkey_tree(struct mlx4_ib_dev *device)
+{
+	int slave;
+	struct kobject *p, *t;
+	struct mlx4_port *port;
+
+	if (!mlx4_is_master(device->dev))
+		return;
+
+	for (slave = device->dev->num_vfs; slave >= 0; --slave) {
+		list_for_each_entry_safe(p, t,
+					 &device->pkeys.pkey_port_list[slave],
+					 entry) {
+			list_del(&p->entry);
+			port = container_of(p, struct mlx4_port, kobj);
+			sysfs_remove_group(p, &port->pkey_group);
+			sysfs_remove_group(p, &port->gid_group);
+			kobject_put(p);
+			kobject_put(device->dev_ports_parent[slave]);
+		}
+		kobject_put(device->dev_ports_parent[slave]);
+		kobject_put(device->pkeys.device_parent[slave]);
+		kobject_put(device->pkeys.device_parent[slave]);
+		kobject_put(device->iov_parent);
+	}
+}
+
+int mlx4_ib_device_register_sysfs(struct mlx4_ib_dev *dev)
+{
+	int i;
+	int ret = 0;
+
+	if (!mlx4_is_master(dev->dev))
+		return 0;
+
+	dev->iov_parent =
+		kobject_create_and_add("iov",
+				       kobject_get(dev->ib_dev.ports_parent->parent));
+	if (!dev->iov_parent) {
+		ret = -ENOMEM;
+		goto err;
+	}
+	dev->ports_parent =
+		kobject_create_and_add("ports",
+				       kobject_get(dev->iov_parent));
+	if (!dev->iov_parent) {
+		ret = -ENOMEM;
+		goto err_ports;
+	}
+
+	for (i = 1; i <= dev->ib_dev.phys_port_cnt; ++i) {
+		ret = add_port_entries(dev, i);
+		if (ret)
+			goto err_add_entries;
+	}
+
+	ret = register_pkey_tree(dev);
+	if (ret)
+		goto err_add_entries;
+	return 0;
+
+err_add_entries:
+	kobject_put(dev->ports_parent);
+
+err_ports:
+	kobject_put(dev->iov_parent);
+err:
+	kobject_put(dev->ib_dev.ports_parent->parent);
+	pr_err("mlx4_ib_device_register_sysfs error (%d)\n", ret);
+	return ret;
+}
+
+static void unregister_alias_guid_tree(struct mlx4_ib_dev *device)
+{
+	struct mlx4_ib_iov_port *p;
+	int i;
+
+	if (!mlx4_is_master(device->dev))
+		return;
+
+	for (i = 0; i < device->dev->caps.num_ports; i++) {
+		p = &device->iov_ports[i];
+		kobject_put(p->admin_alias_parent);
+		kobject_put(p->gids_parent);
+		kobject_put(p->pkeys_parent);
+		kobject_put(p->mcgs_parent);
+		kobject_put(p->cur_port);
+		kobject_put(p->cur_port);
+		kobject_put(p->cur_port);
+		kobject_put(p->cur_port);
+		kobject_put(p->cur_port);
+		kobject_put(p->dev->ports_parent);
+		kfree(p->dentr_ar);
+	}
+}
+
+void mlx4_ib_device_unregister_sysfs(struct mlx4_ib_dev *device)
+{
+	unregister_alias_guid_tree(device);
+	unregister_pkey_tree(device);
+	kobject_put(device->ports_parent);
+	kobject_put(device->iov_parent);
+	kobject_put(device->iov_parent);
+	kobject_put(device->ib_dev.ports_parent->parent);
+}
diff --git a/drivers/infiniband/hw/mthca/mthca_reset.c b/drivers/infiniband/hw/mthca/mthca_reset.c
index 4fa3534..74c6a94 100644
--- a/drivers/infiniband/hw/mthca/mthca_reset.c
+++ b/drivers/infiniband/hw/mthca/mthca_reset.c
@@ -241,16 +241,16 @@ good:
 
 	if (hca_pcie_cap) {
 		devctl = hca_header[(hca_pcie_cap + PCI_EXP_DEVCTL) / 4];
-		if (pci_write_config_word(mdev->pdev, hca_pcie_cap + PCI_EXP_DEVCTL,
-					   devctl)) {
+		if (pcie_capability_write_word(mdev->pdev, PCI_EXP_DEVCTL,
+					       devctl)) {
 			err = -ENODEV;
 			mthca_err(mdev, "Couldn't restore HCA PCI Express "
 				  "Device Control register, aborting.\n");
 			goto out;
 		}
 		linkctl = hca_header[(hca_pcie_cap + PCI_EXP_LNKCTL) / 4];
-		if (pci_write_config_word(mdev->pdev, hca_pcie_cap + PCI_EXP_LNKCTL,
-					   linkctl)) {
+		if (pcie_capability_write_word(mdev->pdev, PCI_EXP_LNKCTL,
+					       linkctl)) {
 			err = -ENODEV;
 			mthca_err(mdev, "Couldn't restore HCA PCI Express "
 				  "Link control register, aborting.\n");
diff --git a/drivers/infiniband/hw/nes/nes.h b/drivers/infiniband/hw/nes/nes.h
index c438e46..0da62b9 100644
--- a/drivers/infiniband/hw/nes/nes.h
+++ b/drivers/infiniband/hw/nes/nes.h
@@ -399,11 +399,20 @@ static inline void nes_write8(void __iomem *addr, u8 val)
 	writeb(val, addr);
 }
 
-
+enum nes_resource {
+	NES_RESOURCE_MW = 1,
+	NES_RESOURCE_FAST_MR,
+	NES_RESOURCE_PHYS_MR,
+	NES_RESOURCE_USER_MR,
+	NES_RESOURCE_PD,
+	NES_RESOURCE_QP,
+	NES_RESOURCE_CQ,
+	NES_RESOURCE_ARP
+};
 
 static inline int nes_alloc_resource(struct nes_adapter *nesadapter,
 		unsigned long *resource_array, u32 max_resources,
-		u32 *req_resource_num, u32 *next)
+		u32 *req_resource_num, u32 *next, enum nes_resource resource_type)
 {
 	unsigned long flags;
 	u32 resource_num;
@@ -414,7 +423,7 @@ static inline int nes_alloc_resource(struct nes_adapter *nesadapter,
 	if (resource_num >= max_resources) {
 		resource_num = find_first_zero_bit(resource_array, max_resources);
 		if (resource_num >= max_resources) {
-			printk(KERN_ERR PFX "%s: No available resourcess.\n", __func__);
+			printk(KERN_ERR PFX "%s: No available resources [type=%u].\n", __func__, resource_type);
 			spin_unlock_irqrestore(&nesadapter->resource_lock, flags);
 			return -EMFILE;
 		}
diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c
index 020e95c..cfaacaf 100644
--- a/drivers/infiniband/hw/nes/nes_cm.c
+++ b/drivers/infiniband/hw/nes/nes_cm.c
@@ -430,6 +430,8 @@ static void form_cm_frame(struct sk_buff *skb,
 	buf += sizeof(*tcph);
 
 	skb->ip_summed = CHECKSUM_PARTIAL;
+	if (!(cm_node->netdev->features & NETIF_F_IP_CSUM))
+		skb->ip_summed = CHECKSUM_NONE;
 	skb->protocol = htons(0x800);
 	skb->data_len = 0;
 	skb->mac_len = ETH_HLEN;
@@ -1356,7 +1358,7 @@ static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip, int arpi
 	else
 		netdev = nesvnic->netdev;
 
-	neigh = dst_neigh_lookup(&rt->dst, &dst_ip);
+	neigh = neigh_lookup(&arp_tbl, &rt->rt_gateway, netdev);
 
 	rcu_read_lock();
 	if (neigh) {
@@ -1465,12 +1467,8 @@ static struct nes_cm_node *make_cm_node(struct nes_cm_core *cm_core,
 	cm_node->loopbackpartner = NULL;
 
 	/* get the mac addr for the remote node */
-	if (ipv4_is_loopback(htonl(cm_node->rem_addr))) {
-		arpindex = nes_arp_table(nesdev, ntohl(nesvnic->local_ipaddr), NULL, NES_ARP_RESOLVE);
-	} else {
-		oldarpindex = nes_arp_table(nesdev, cm_node->rem_addr, NULL, NES_ARP_RESOLVE);
-		arpindex = nes_addr_resolve_neigh(nesvnic, cm_info->rem_addr, oldarpindex);
-	}
+	oldarpindex = nes_arp_table(nesdev, cm_node->rem_addr, NULL, NES_ARP_RESOLVE);
+	arpindex = nes_addr_resolve_neigh(nesvnic, cm_info->rem_addr, oldarpindex);
 	if (arpindex < 0) {
 		kfree(cm_node);
 		return NULL;
@@ -3153,11 +3151,7 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
 	nesqp->nesqp_context->tcpPorts[1] =
 		cpu_to_le16(ntohs(cm_id->remote_addr.sin_port));
 
-	if (ipv4_is_loopback(cm_id->remote_addr.sin_addr.s_addr))
-		nesqp->nesqp_context->ip0 =
-			cpu_to_le32(ntohl(nesvnic->local_ipaddr));
-	else
-		nesqp->nesqp_context->ip0 =
+	nesqp->nesqp_context->ip0 =
 			cpu_to_le32(ntohl(cm_id->remote_addr.sin_addr.s_addr));
 
 	nesqp->nesqp_context->misc2 |= cpu_to_le32(
@@ -3182,10 +3176,7 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
 	memset(&nes_quad, 0, sizeof(nes_quad));
 	nes_quad.DstIpAdrIndex =
 		cpu_to_le32((u32)PCI_FUNC(nesdev->pcidev->devfn) << 24);
-	if (ipv4_is_loopback(cm_id->remote_addr.sin_addr.s_addr))
-		nes_quad.SrcIpadr = nesvnic->local_ipaddr;
-	else
-		nes_quad.SrcIpadr = cm_id->remote_addr.sin_addr.s_addr;
+	nes_quad.SrcIpadr = cm_id->remote_addr.sin_addr.s_addr;
 	nes_quad.TcpPorts[0] = cm_id->remote_addr.sin_port;
 	nes_quad.TcpPorts[1] = cm_id->local_addr.sin_port;
 
@@ -3538,11 +3529,7 @@ static void cm_event_connected(struct nes_cm_event *event)
 		cpu_to_le16(ntohs(cm_id->local_addr.sin_port));
 	nesqp->nesqp_context->tcpPorts[1] =
 		cpu_to_le16(ntohs(cm_id->remote_addr.sin_port));
-	if (ipv4_is_loopback(cm_id->remote_addr.sin_addr.s_addr))
-		nesqp->nesqp_context->ip0 =
-			cpu_to_le32(ntohl(nesvnic->local_ipaddr));
-	else
-		nesqp->nesqp_context->ip0 =
+	nesqp->nesqp_context->ip0 =
 			cpu_to_le32(ntohl(cm_id->remote_addr.sin_addr.s_addr));
 
 	nesqp->nesqp_context->misc2 |= cpu_to_le32(
@@ -3571,10 +3558,7 @@ static void cm_event_connected(struct nes_cm_event *event)
 
 	nes_quad.DstIpAdrIndex =
 		cpu_to_le32((u32)PCI_FUNC(nesdev->pcidev->devfn) << 24);
-	if (ipv4_is_loopback(cm_id->remote_addr.sin_addr.s_addr))
-		nes_quad.SrcIpadr = nesvnic->local_ipaddr;
-	else
-		nes_quad.SrcIpadr = cm_id->remote_addr.sin_addr.s_addr;
+	nes_quad.SrcIpadr = cm_id->remote_addr.sin_addr.s_addr;
 	nes_quad.TcpPorts[0] = cm_id->remote_addr.sin_port;
 	nes_quad.TcpPorts[1] = cm_id->local_addr.sin_port;
 
diff --git a/drivers/infiniband/hw/nes/nes_hw.c b/drivers/infiniband/hw/nes/nes_hw.c
index d42c9f4..fe7965e 100644
--- a/drivers/infiniband/hw/nes/nes_hw.c
+++ b/drivers/infiniband/hw/nes/nes_hw.c
@@ -2679,11 +2679,9 @@ static void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number)
 			}
 		}
 		if (nesadapter->phy_type[mac_index] == NES_PHY_TYPE_SFP_D) {
-			if (nesdev->link_recheck)
-				cancel_delayed_work(&nesdev->work);
 			nesdev->link_recheck = 1;
-			schedule_delayed_work(&nesdev->work,
-					      NES_LINK_RECHECK_DELAY);
+			mod_delayed_work(system_wq, &nesdev->work,
+					 NES_LINK_RECHECK_DELAY);
 		}
 	}
 
@@ -3577,10 +3575,10 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev,
 	tcp_state = (aeq_info & NES_AEQE_TCP_STATE_MASK) >> NES_AEQE_TCP_STATE_SHIFT;
 	iwarp_state = (aeq_info & NES_AEQE_IWARP_STATE_MASK) >> NES_AEQE_IWARP_STATE_SHIFT;
 	nes_debug(NES_DBG_AEQ, "aeid = 0x%04X, qp-cq id = %d, aeqe = %p,"
-			" Tcp state = %s, iWARP state = %s\n",
+			" Tcp state = %d, iWARP state = %d\n",
 			async_event_id,
 			le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]), aeqe,
-			nes_tcp_state_str[tcp_state], nes_iwarp_state_str[iwarp_state]);
+			tcp_state, iwarp_state);
 
 	aeqe_cq_id = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]);
 	if (aeq_info & NES_AEQE_QP) {
diff --git a/drivers/infiniband/hw/nes/nes_nic.c b/drivers/infiniband/hw/nes/nes_nic.c
index f3a3ecf..0564be7 100644
--- a/drivers/infiniband/hw/nes/nes_nic.c
+++ b/drivers/infiniband/hw/nes/nes_nic.c
@@ -243,10 +243,9 @@ static int nes_netdev_open(struct net_device *netdev)
 
 	spin_lock_irqsave(&nesdev->nesadapter->phy_lock, flags);
 	if (nesdev->nesadapter->phy_type[nesdev->mac_index] == NES_PHY_TYPE_SFP_D) {
-		if (nesdev->link_recheck)
-			cancel_delayed_work(&nesdev->work);
 		nesdev->link_recheck = 1;
-		schedule_delayed_work(&nesdev->work, NES_LINK_RECHECK_DELAY);
+		mod_delayed_work(system_wq, &nesdev->work,
+				 NES_LINK_RECHECK_DELAY);
 	}
 	spin_unlock_irqrestore(&nesdev->nesadapter->phy_lock, flags);
 
@@ -385,24 +384,20 @@ static int nes_nic_send(struct sk_buff *skb, struct net_device *netdev)
 	/* bump past the vlan tag */
 	wqe_fragment_length++;
 	/*	wqe_fragment_address = (u64 *)&nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_LOW_IDX]; */
+	wqe_misc |= NES_NIC_SQ_WQE_COMPLETION;
 
 	if (skb->ip_summed == CHECKSUM_PARTIAL) {
-		tcph = tcp_hdr(skb);
-		if (1) {
-			if (skb_is_gso(skb)) {
-				/* nes_debug(NES_DBG_NIC_TX, "%s: TSO request... seg size = %u\n",
-						netdev->name, skb_is_gso(skb)); */
-				wqe_misc |= NES_NIC_SQ_WQE_LSO_ENABLE |
-						NES_NIC_SQ_WQE_COMPLETION | (u16)skb_is_gso(skb);
-				set_wqe_32bit_value(nic_sqe->wqe_words, NES_NIC_SQ_WQE_LSO_INFO_IDX,
-						((u32)tcph->doff) |
-						(((u32)(((unsigned char *)tcph) - skb->data)) << 4));
-			} else {
-				wqe_misc |= NES_NIC_SQ_WQE_COMPLETION;
-			}
+		if (skb_is_gso(skb)) {
+			tcph = tcp_hdr(skb);
+			/* nes_debug(NES_DBG_NIC_TX, "%s: TSO request... is_gso = %u seg size = %u\n",
+					netdev->name, skb_is_gso(skb), skb_shinfo(skb)->gso_size); */
+			wqe_misc |= NES_NIC_SQ_WQE_LSO_ENABLE | (u16)skb_shinfo(skb)->gso_size;
+			set_wqe_32bit_value(nic_sqe->wqe_words, NES_NIC_SQ_WQE_LSO_INFO_IDX,
+					((u32)tcph->doff) |
+					(((u32)(((unsigned char *)tcph) - skb->data)) << 4));
 		}
 	} else {	/* CHECKSUM_HW */
-		wqe_misc |= NES_NIC_SQ_WQE_DISABLE_CHKSUM | NES_NIC_SQ_WQE_COMPLETION;
+		wqe_misc |= NES_NIC_SQ_WQE_DISABLE_CHKSUM;
 	}
 
 	set_wqe_32bit_value(nic_sqe->wqe_words, NES_NIC_SQ_WQE_TOTAL_LENGTH_IDX,
@@ -597,10 +592,10 @@ tso_sq_no_longer_full:
 					nes_debug(NES_DBG_NIC_TX, "ERROR: SKB header too big, headlen=%u, FIRST_FRAG_SIZE=%u\n",
 							original_first_length, NES_FIRST_FRAG_SIZE);
 					nes_debug(NES_DBG_NIC_TX, "%s Request to tx NIC packet length %u, headlen %u,"
-							" (%u frags), tso_size=%u\n",
+							" (%u frags), is_gso = %u tso_size=%u\n",
 							netdev->name,
 							skb->len, skb_headlen(skb),
-							skb_shinfo(skb)->nr_frags, skb_is_gso(skb));
+							skb_shinfo(skb)->nr_frags, skb_is_gso(skb), skb_shinfo(skb)->gso_size);
 				}
 				memcpy(&nesnic->first_frag_vbase[nesnic->sq_head].buffer,
 						skb->data, min(((unsigned int)NES_FIRST_FRAG_SIZE),
@@ -652,8 +647,8 @@ tso_sq_no_longer_full:
 				} else {
 					nesnic->tx_skb[nesnic->sq_head] = NULL;
 				}
-				wqe_misc |= NES_NIC_SQ_WQE_COMPLETION | (u16)skb_is_gso(skb);
-				if ((tso_wqe_length + original_first_length) > skb_is_gso(skb)) {
+				wqe_misc |= NES_NIC_SQ_WQE_COMPLETION | (u16)skb_shinfo(skb)->gso_size;
+				if ((tso_wqe_length + original_first_length) > skb_shinfo(skb)->gso_size) {
 					wqe_misc |= NES_NIC_SQ_WQE_LSO_ENABLE;
 				} else {
 					iph->tot_len = htons(tso_wqe_length + original_first_length - nhoffset);
@@ -1679,12 +1674,10 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev,
 	netdev->hard_header_len = ETH_HLEN;
 	netdev->addr_len = ETH_ALEN;
 	netdev->type = ARPHRD_ETHER;
-	netdev->features = NETIF_F_HIGHDMA;
 	netdev->netdev_ops = &nes_netdev_ops;
 	netdev->ethtool_ops = &nes_ethtool_ops;
 	netif_napi_add(netdev, &nesvnic->napi, nes_netdev_poll, 128);
 	nes_debug(NES_DBG_INIT, "Enabling VLAN Insert/Delete.\n");
-	netdev->features |= NETIF_F_HW_VLAN_TX;
 
 	/* Fill in the port structure */
 	nesvnic->netdev = netdev;
@@ -1711,11 +1704,11 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev,
 	netdev->dev_addr[5] = (u8)u64temp;
 	memcpy(netdev->perm_addr, netdev->dev_addr, 6);
 
-	netdev->hw_features = NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_IP_CSUM |
-			      NETIF_F_HW_VLAN_RX;
+	netdev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_RXCSUM | NETIF_F_HW_VLAN_RX;
 	if ((nesvnic->logical_port < 2) || (nesdev->nesadapter->hw_rev != NE020_REV))
 		netdev->hw_features |= NETIF_F_TSO;
-	netdev->features |= netdev->hw_features;
+
+	netdev->features = netdev->hw_features | NETIF_F_HIGHDMA | NETIF_F_HW_VLAN_TX;
 	netdev->hw_features |= NETIF_F_LRO;
 
 	nes_debug(NES_DBG_INIT, "nesvnic = %p, reported features = 0x%lX, QPid = %d,"
diff --git a/drivers/infiniband/hw/nes/nes_utils.c b/drivers/infiniband/hw/nes/nes_utils.c
index e98f4fc..2042c0f 100644
--- a/drivers/infiniband/hw/nes/nes_utils.c
+++ b/drivers/infiniband/hw/nes/nes_utils.c
@@ -699,7 +699,7 @@ int nes_arp_table(struct nes_device *nesdev, u32 ip_addr, u8 *mac_addr, u32 acti
 
 		arp_index = 0;
 		err = nes_alloc_resource(nesadapter, nesadapter->allocated_arps,
-				nesadapter->arp_table_size, (u32 *)&arp_index, &nesadapter->next_arp_index);
+				nesadapter->arp_table_size, (u32 *)&arp_index, &nesadapter->next_arp_index, NES_RESOURCE_ARP);
 		if (err) {
 			nes_debug(NES_DBG_NETDEV, "nes_alloc_resource returned error = %u\n", err);
 			return err;
diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c
index 8b8812d..1dadcf3 100644
--- a/drivers/infiniband/hw/nes/nes_verbs.c
+++ b/drivers/infiniband/hw/nes/nes_verbs.c
@@ -80,7 +80,7 @@ static struct ib_mw *nes_alloc_mw(struct ib_pd *ibpd) {
 	next_stag_index %= nesadapter->max_mr;
 
 	ret = nes_alloc_resource(nesadapter, nesadapter->allocated_mrs,
-			nesadapter->max_mr, &stag_index, &next_stag_index);
+			nesadapter->max_mr, &stag_index, &next_stag_index, NES_RESOURCE_MW);
 	if (ret) {
 		return ERR_PTR(ret);
 	}
@@ -404,7 +404,7 @@ static struct ib_mr *nes_alloc_fast_reg_mr(struct ib_pd *ibpd, int max_page_list
 
 	err = nes_alloc_resource(nesadapter, nesadapter->allocated_mrs,
 				 nesadapter->max_mr, &stag_index,
-				 &next_stag_index);
+				 &next_stag_index, NES_RESOURCE_FAST_MR);
 	if (err)
 		return ERR_PTR(err);
 
@@ -780,7 +780,7 @@ static struct ib_pd *nes_alloc_pd(struct ib_device *ibdev,
 			netdev_refcnt_read(nesvnic->netdev));
 
 	err = nes_alloc_resource(nesadapter, nesadapter->allocated_pds,
-			nesadapter->max_pd, &pd_num, &nesadapter->next_pd);
+			nesadapter->max_pd, &pd_num, &nesadapter->next_pd, NES_RESOURCE_PD);
 	if (err) {
 		return ERR_PTR(err);
 	}
@@ -1157,7 +1157,7 @@ static struct ib_qp *nes_create_qp(struct ib_pd *ibpd,
 			nes_debug(NES_DBG_QP, "RQ size=%u, SQ Size=%u\n", rq_size, sq_size);
 
 			ret = nes_alloc_resource(nesadapter, nesadapter->allocated_qps,
-					nesadapter->max_qp, &qp_num, &nesadapter->next_qp);
+					nesadapter->max_qp, &qp_num, &nesadapter->next_qp, NES_RESOURCE_QP);
 			if (ret) {
 				return ERR_PTR(ret);
 			}
@@ -1546,7 +1546,7 @@ static struct ib_cq *nes_create_cq(struct ib_device *ibdev, int entries,
 		return ERR_PTR(-EINVAL);
 
 	err = nes_alloc_resource(nesadapter, nesadapter->allocated_cqs,
-			nesadapter->max_cq, &cq_num, &nesadapter->next_cq);
+			nesadapter->max_cq, &cq_num, &nesadapter->next_cq, NES_RESOURCE_CQ);
 	if (err) {
 		return ERR_PTR(err);
 	}
@@ -2129,7 +2129,7 @@ static struct ib_mr *nes_reg_phys_mr(struct ib_pd *ib_pd,
 		return ERR_PTR(-EINVAL);
 
 	err = nes_alloc_resource(nesadapter, nesadapter->allocated_mrs, nesadapter->max_mr,
-			&stag_index, &next_stag_index);
+			&stag_index, &next_stag_index, NES_RESOURCE_PHYS_MR);
 	if (err) {
 		return ERR_PTR(err);
 	}
@@ -2360,7 +2360,7 @@ static struct ib_mr *nes_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
 			next_stag_index %= nesadapter->max_mr;
 
 			err = nes_alloc_resource(nesadapter, nesadapter->allocated_mrs,
-					nesadapter->max_mr, &stag_index, &next_stag_index);
+					nesadapter->max_mr, &stag_index, &next_stag_index, NES_RESOURCE_USER_MR);
 			if (err) {
 				ib_umem_release(region);
 				return ERR_PTR(err);
diff --git a/drivers/infiniband/hw/qib/qib.h b/drivers/infiniband/hw/qib/qib.h
index 7b1b8669..4d11575 100644
--- a/drivers/infiniband/hw/qib/qib.h
+++ b/drivers/infiniband/hw/qib/qib.h
@@ -87,7 +87,7 @@ struct qlogic_ib_stats {
 };
 
 extern struct qlogic_ib_stats qib_stats;
-extern struct pci_error_handlers qib_pci_err_handler;
+extern const struct pci_error_handlers qib_pci_err_handler;
 extern struct pci_driver qib_driver;
 
 #define QIB_CHIP_SWVERSION QIB_CHIP_VERS_MAJ
diff --git a/drivers/infiniband/hw/qib/qib_common.h b/drivers/infiniband/hw/qib/qib_common.h
index 145da40..d39e018 100644
--- a/drivers/infiniband/hw/qib/qib_common.h
+++ b/drivers/infiniband/hw/qib/qib_common.h
@@ -285,7 +285,6 @@ struct qib_base_info {
 
 #ifndef QIB_KERN_TYPE
 #define QIB_KERN_TYPE 0
-#define QIB_IDSTR "QLogic kernel.org driver"
 #endif
 
 /*
@@ -302,6 +301,19 @@ struct qib_base_info {
 #define QIB_KERN_SWVERSION ((QIB_KERN_TYPE << 31) | QIB_USER_SWVERSION)
 
 /*
+ * Define the driver version number.  This is something that refers only
+ * to the driver itself, not the software interfaces it supports.
+ */
+#define QIB_DRIVER_VERSION_BASE "1.11"
+
+/* create the final driver version string */
+#ifdef QIB_IDSTR
+#define QIB_DRIVER_VERSION QIB_DRIVER_VERSION_BASE " " QIB_IDSTR
+#else
+#define QIB_DRIVER_VERSION QIB_DRIVER_VERSION_BASE
+#endif
+
+/*
  * If the unit is specified via open, HCA choice is fixed.  If port is
  * specified, it's also fixed.  Otherwise we try to spread contexts
  * across ports and HCAs, using different algorithims.  WITHIN is
diff --git a/drivers/infiniband/hw/qib/qib_driver.c b/drivers/infiniband/hw/qib/qib_driver.c
index e41e7f7..5423edc 100644
--- a/drivers/infiniband/hw/qib/qib_driver.c
+++ b/drivers/infiniband/hw/qib/qib_driver.c
@@ -46,7 +46,7 @@
  * The size has to be longer than this string, so we can append
  * board/chip information to it in the init code.
  */
-const char ib_qib_version[] = QIB_IDSTR "\n";
+const char ib_qib_version[] = QIB_DRIVER_VERSION "\n";
 
 DEFINE_SPINLOCK(qib_devs_lock);
 LIST_HEAD(qib_dev_list);
@@ -65,6 +65,7 @@ MODULE_PARM_DESC(compat_ddr_negotiate,
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_AUTHOR("QLogic <support@qlogic.com>");
 MODULE_DESCRIPTION("QLogic IB driver");
+MODULE_VERSION(QIB_DRIVER_VERSION);
 
 /*
  * QIB_PIO_MAXIBHDR is the max IB header size allowed for in our
diff --git a/drivers/infiniband/hw/qib/qib_file_ops.c b/drivers/infiniband/hw/qib/qib_file_ops.c
index faa44cb..959a5c4 100644
--- a/drivers/infiniband/hw/qib/qib_file_ops.c
+++ b/drivers/infiniband/hw/qib/qib_file_ops.c
@@ -971,7 +971,7 @@ static int mmap_kvaddr(struct vm_area_struct *vma, u64 pgaddr,
 
 	vma->vm_pgoff = (unsigned long) addr >> PAGE_SHIFT;
 	vma->vm_ops = &qib_file_vm_ops;
-	vma->vm_flags |= VM_RESERVED | VM_DONTEXPAND;
+	vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
 	ret = 1;
 
 bail:
diff --git a/drivers/infiniband/hw/qib/qib_fs.c b/drivers/infiniband/hw/qib/qib_fs.c
index cff8a6c..65a2a23 100644
--- a/drivers/infiniband/hw/qib/qib_fs.c
+++ b/drivers/infiniband/hw/qib/qib_fs.c
@@ -61,8 +61,8 @@ static int qibfs_mknod(struct inode *dir, struct dentry *dentry,
 
 	inode->i_ino = get_next_ino();
 	inode->i_mode = mode;
-	inode->i_uid = 0;
-	inode->i_gid = 0;
+	inode->i_uid = GLOBAL_ROOT_UID;
+	inode->i_gid = GLOBAL_ROOT_GID;
 	inode->i_blocks = 0;
 	inode->i_atime = CURRENT_TIME;
 	inode->i_mtime = inode->i_atime;
diff --git a/drivers/infiniband/hw/qib/qib_pcie.c b/drivers/infiniband/hw/qib/qib_pcie.c
index 062c301..c574ec7 100644
--- a/drivers/infiniband/hw/qib/qib_pcie.c
+++ b/drivers/infiniband/hw/qib/qib_pcie.c
@@ -273,10 +273,9 @@ int qib_pcie_params(struct qib_devdata *dd, u32 minw, u32 *nent,
 		    struct qib_msix_entry *entry)
 {
 	u16 linkstat, speed;
-	int pos = 0, pose, ret = 1;
+	int pos = 0, ret = 1;
 
-	pose = pci_pcie_cap(dd->pcidev);
-	if (!pose) {
+	if (!pci_is_pcie(dd->pcidev)) {
 		qib_dev_err(dd, "Can't find PCI Express capability!\n");
 		/* set up something... */
 		dd->lbus_width = 1;
@@ -298,7 +297,7 @@ int qib_pcie_params(struct qib_devdata *dd, u32 minw, u32 *nent,
 	if (!pos)
 		qib_enable_intx(dd->pcidev);
 
-	pci_read_config_word(dd->pcidev, pose + PCI_EXP_LNKSTA, &linkstat);
+	pcie_capability_read_word(dd->pcidev, PCI_EXP_LNKSTA, &linkstat);
 	/*
 	 * speed is bits 0-3, linkwidth is bits 4-8
 	 * no defines for them in headers
@@ -516,7 +515,6 @@ static int qib_tune_pcie_coalesce(struct qib_devdata *dd)
 {
 	int r;
 	struct pci_dev *parent;
-	int ppos;
 	u16 devid;
 	u32 mask, bits, val;
 
@@ -529,8 +527,7 @@ static int qib_tune_pcie_coalesce(struct qib_devdata *dd)
 		qib_devinfo(dd->pcidev, "Parent not root\n");
 		return 1;
 	}
-	ppos = pci_pcie_cap(parent);
-	if (!ppos)
+	if (!pci_is_pcie(parent))
 		return 1;
 	if (parent->vendor != 0x8086)
 		return 1;
@@ -587,7 +584,6 @@ static int qib_tune_pcie_caps(struct qib_devdata *dd)
 {
 	int ret = 1; /* Assume the worst */
 	struct pci_dev *parent;
-	int ppos, epos;
 	u16 pcaps, pctl, ecaps, ectl;
 	int rc_sup, ep_sup;
 	int rc_cur, ep_cur;
@@ -598,19 +594,15 @@ static int qib_tune_pcie_caps(struct qib_devdata *dd)
 		qib_devinfo(dd->pcidev, "Parent not root\n");
 		goto bail;
 	}
-	ppos = pci_pcie_cap(parent);
-	if (ppos) {
-		pci_read_config_word(parent, ppos + PCI_EXP_DEVCAP, &pcaps);
-		pci_read_config_word(parent, ppos + PCI_EXP_DEVCTL, &pctl);
-	} else
+
+	if (!pci_is_pcie(parent) || !pci_is_pcie(dd->pcidev))
 		goto bail;
+	pcie_capability_read_word(parent, PCI_EXP_DEVCAP, &pcaps);
+	pcie_capability_read_word(parent, PCI_EXP_DEVCTL, &pctl);
 	/* Find out supported and configured values for endpoint (us) */
-	epos = pci_pcie_cap(dd->pcidev);
-	if (epos) {
-		pci_read_config_word(dd->pcidev, epos + PCI_EXP_DEVCAP, &ecaps);
-		pci_read_config_word(dd->pcidev, epos + PCI_EXP_DEVCTL, &ectl);
-	} else
-		goto bail;
+	pcie_capability_read_word(dd->pcidev, PCI_EXP_DEVCAP, &ecaps);
+	pcie_capability_read_word(dd->pcidev, PCI_EXP_DEVCTL, &ectl);
+
 	ret = 0;
 	/* Find max payload supported by root, endpoint */
 	rc_sup = fld2val(pcaps, PCI_EXP_DEVCAP_PAYLOAD);
@@ -629,14 +621,14 @@ static int qib_tune_pcie_caps(struct qib_devdata *dd)
 		rc_cur = rc_sup;
 		pctl = (pctl & ~PCI_EXP_DEVCTL_PAYLOAD) |
 			val2fld(rc_cur, PCI_EXP_DEVCTL_PAYLOAD);
-		pci_write_config_word(parent, ppos + PCI_EXP_DEVCTL, pctl);
+		pcie_capability_write_word(parent, PCI_EXP_DEVCTL, pctl);
 	}
 	/* If less than (allowed, supported), bump endpoint payload */
 	if (rc_sup > ep_cur) {
 		ep_cur = rc_sup;
 		ectl = (ectl & ~PCI_EXP_DEVCTL_PAYLOAD) |
 			val2fld(ep_cur, PCI_EXP_DEVCTL_PAYLOAD);
-		pci_write_config_word(dd->pcidev, epos + PCI_EXP_DEVCTL, ectl);
+		pcie_capability_write_word(dd->pcidev, PCI_EXP_DEVCTL, ectl);
 	}
 
 	/*
@@ -654,13 +646,13 @@ static int qib_tune_pcie_caps(struct qib_devdata *dd)
 		rc_cur = rc_sup;
 		pctl = (pctl & ~PCI_EXP_DEVCTL_READRQ) |
 			val2fld(rc_cur, PCI_EXP_DEVCTL_READRQ);
-		pci_write_config_word(parent, ppos + PCI_EXP_DEVCTL, pctl);
+		pcie_capability_write_word(parent, PCI_EXP_DEVCTL, pctl);
 	}
 	if (rc_sup > ep_cur) {
 		ep_cur = rc_sup;
 		ectl = (ectl & ~PCI_EXP_DEVCTL_READRQ) |
 			val2fld(ep_cur, PCI_EXP_DEVCTL_READRQ);
-		pci_write_config_word(dd->pcidev, epos + PCI_EXP_DEVCTL, ectl);
+		pcie_capability_write_word(dd->pcidev, PCI_EXP_DEVCTL, ectl);
 	}
 bail:
 	return ret;
@@ -753,7 +745,7 @@ qib_pci_resume(struct pci_dev *pdev)
 	qib_init(dd, 1); /* same as re-init after reset */
 }
 
-struct pci_error_handlers qib_pci_err_handler = {
+const struct pci_error_handlers qib_pci_err_handler = {
 	.error_detected = qib_pci_error_detected,
 	.mmio_enabled = qib_pci_mmio_enabled,
 	.link_reset = qib_pci_link_reset,
diff --git a/drivers/infiniband/hw/qib/qib_verbs.c b/drivers/infiniband/hw/qib/qib_verbs.c
index fc9b205..ba51a47 100644
--- a/drivers/infiniband/hw/qib/qib_verbs.c
+++ b/drivers/infiniband/hw/qib/qib_verbs.c
@@ -2224,7 +2224,7 @@ int qib_register_ib_device(struct qib_devdata *dd)
 	ibdev->dma_ops = &qib_dma_mapping_ops;
 
 	snprintf(ibdev->node_desc, sizeof(ibdev->node_desc),
-		 QIB_IDSTR " %s", init_utsname()->nodename);
+		 "QLogic Infiniband HCA %s", init_utsname()->nodename);
 
 	ret = ib_register_device(ibdev, qib_create_port_files);
 	if (ret)
diff --git a/drivers/infiniband/ulp/ipoib/Makefile b/drivers/infiniband/ulp/ipoib/Makefile
index 3090100..e5430dd 100644
--- a/drivers/infiniband/ulp/ipoib/Makefile
+++ b/drivers/infiniband/ulp/ipoib/Makefile
@@ -5,7 +5,8 @@ ib_ipoib-y					:= ipoib_main.o \
 						   ipoib_multicast.o \
 						   ipoib_verbs.o \
 						   ipoib_vlan.o \
-						   ipoib_ethtool.o
+						   ipoib_ethtool.o \
+						   ipoib_netlink.o
 ib_ipoib-$(CONFIG_INFINIBAND_IPOIB_CM)		+= ipoib_cm.o
 ib_ipoib-$(CONFIG_INFINIBAND_IPOIB_DEBUG)	+= ipoib_fs.o
 
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h
index 0af216d..ac48f86 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib.h
+++ b/drivers/infiniband/ulp/ipoib/ipoib.h
@@ -104,6 +104,10 @@ enum {
 
 	MAX_SEND_CQE		  = 16,
 	IPOIB_CM_COPYBREAK	  = 256,
+
+	IPOIB_NON_CHILD		  = 0,
+	IPOIB_LEGACY_CHILD	  = 1,
+	IPOIB_RTNL_CHILD	  = 2,
 };
 
 #define	IPOIB_OP_RECV   (1ul << 31)
@@ -353,6 +357,7 @@ struct ipoib_dev_priv {
 	struct net_device *parent;
 	struct list_head child_intfs;
 	struct list_head list;
+	int    child_type;
 
 #ifdef CONFIG_INFINIBAND_IPOIB_CM
 	struct ipoib_cm_dev_priv cm;
@@ -512,6 +517,14 @@ void ipoib_event(struct ib_event_handler *handler,
 int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey);
 int ipoib_vlan_delete(struct net_device *pdev, unsigned short pkey);
 
+int __ipoib_vlan_add(struct ipoib_dev_priv *ppriv, struct ipoib_dev_priv *priv,
+		     u16 pkey, int child_type);
+
+int  __init ipoib_netlink_init(void);
+void __exit ipoib_netlink_fini(void);
+
+void ipoib_setup(struct net_device *dev);
+
 void ipoib_pkey_poll(struct work_struct *work);
 int ipoib_pkey_dev_delay_open(struct net_device *dev);
 void ipoib_drain_cq(struct net_device *dev);
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 1e19b5a..b229df1 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -150,7 +150,7 @@ static int ipoib_stop(struct net_device *dev)
 
 	netif_stop_queue(dev);
 
-	ipoib_ib_dev_down(dev, 0);
+	ipoib_ib_dev_down(dev, 1);
 	ipoib_ib_dev_stop(dev, 0);
 
 	if (!test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags)) {
@@ -173,6 +173,11 @@ static int ipoib_stop(struct net_device *dev)
 	return 0;
 }
 
+static void ipoib_uninit(struct net_device *dev)
+{
+	ipoib_dev_cleanup(dev);
+}
+
 static netdev_features_t ipoib_fix_features(struct net_device *dev, netdev_features_t features)
 {
 	struct ipoib_dev_priv *priv = netdev_priv(dev);
@@ -1257,6 +1262,9 @@ out:
 void ipoib_dev_cleanup(struct net_device *dev)
 {
 	struct ipoib_dev_priv *priv = netdev_priv(dev), *cpriv, *tcpriv;
+	LIST_HEAD(head);
+
+	ASSERT_RTNL();
 
 	ipoib_delete_debug_files(dev);
 
@@ -1265,10 +1273,9 @@ void ipoib_dev_cleanup(struct net_device *dev)
 		/* Stop GC on child */
 		set_bit(IPOIB_STOP_NEIGH_GC, &cpriv->flags);
 		cancel_delayed_work(&cpriv->neigh_reap_task);
-		unregister_netdev(cpriv->dev);
-		ipoib_dev_cleanup(cpriv->dev);
-		free_netdev(cpriv->dev);
+		unregister_netdevice_queue(cpriv->dev, &head);
 	}
+	unregister_netdevice_many(&head);
 
 	ipoib_ib_dev_cleanup(dev);
 
@@ -1286,6 +1293,7 @@ static const struct header_ops ipoib_header_ops = {
 };
 
 static const struct net_device_ops ipoib_netdev_ops = {
+	.ndo_uninit		 = ipoib_uninit,
 	.ndo_open		 = ipoib_open,
 	.ndo_stop		 = ipoib_stop,
 	.ndo_change_mtu		 = ipoib_change_mtu,
@@ -1295,7 +1303,7 @@ static const struct net_device_ops ipoib_netdev_ops = {
 	.ndo_set_rx_mode	 = ipoib_set_mcast_list,
 };
 
-static void ipoib_setup(struct net_device *dev)
+void ipoib_setup(struct net_device *dev)
 {
 	struct ipoib_dev_priv *priv = netdev_priv(dev);
 
@@ -1657,7 +1665,6 @@ static void ipoib_remove_one(struct ib_device *device)
 		flush_workqueue(ipoib_workqueue);
 
 		unregister_netdev(priv->dev);
-		ipoib_dev_cleanup(priv->dev);
 		free_netdev(priv->dev);
 	}
 
@@ -1709,8 +1716,15 @@ static int __init ipoib_init_module(void)
 	if (ret)
 		goto err_sa;
 
+	ret = ipoib_netlink_init();
+	if (ret)
+		goto err_client;
+
 	return 0;
 
+err_client:
+	ib_unregister_client(&ipoib_client);
+
 err_sa:
 	ib_sa_unregister_client(&ipoib_sa_client);
 	destroy_workqueue(ipoib_workqueue);
@@ -1723,6 +1737,7 @@ err_fs:
 
 static void __exit ipoib_cleanup_module(void)
 {
+	ipoib_netlink_fini();
 	ib_unregister_client(&ipoib_client);
 	ib_sa_unregister_client(&ipoib_sa_client);
 	ipoib_unregister_debugfs();
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
index 7536724..cecb98a 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
@@ -175,7 +175,9 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast,
 
 	mcast->mcmember = *mcmember;
 
-	/* Set the cached Q_Key before we attach if it's the broadcast group */
+	/* Set the multicast MTU and cached Q_Key before we attach if it's
+	 * the broadcast group.
+	 */
 	if (!memcmp(mcast->mcmember.mgid.raw, priv->dev->broadcast + 4,
 		    sizeof (union ib_gid))) {
 		spin_lock_irq(&priv->lock);
@@ -183,10 +185,17 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast,
 			spin_unlock_irq(&priv->lock);
 			return -EAGAIN;
 		}
+		priv->mcast_mtu = IPOIB_UD_MTU(ib_mtu_enum_to_int(priv->broadcast->mcmember.mtu));
 		priv->qkey = be32_to_cpu(priv->broadcast->mcmember.qkey);
 		spin_unlock_irq(&priv->lock);
 		priv->tx_wr.wr.ud.remote_qkey = priv->qkey;
 		set_qkey = 1;
+
+		if (!ipoib_cm_admin_enabled(dev)) {
+			rtnl_lock();
+			dev_set_mtu(dev, min(priv->mcast_mtu, priv->admin_mtu));
+			rtnl_unlock();
+		}
 	}
 
 	if (!test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags)) {
@@ -574,14 +583,6 @@ void ipoib_mcast_join_task(struct work_struct *work)
 		return;
 	}
 
-	priv->mcast_mtu = IPOIB_UD_MTU(ib_mtu_enum_to_int(priv->broadcast->mcmember.mtu));
-
-	if (!ipoib_cm_admin_enabled(dev)) {
-		rtnl_lock();
-		dev_set_mtu(dev, min(priv->mcast_mtu, priv->admin_mtu));
-		rtnl_unlock();
-	}
-
 	ipoib_dbg_mcast(priv, "successfully joined all multicast groups\n");
 
 	clear_bit(IPOIB_MCAST_RUN, &priv->flags);
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_netlink.c b/drivers/infiniband/ulp/ipoib/ipoib_netlink.c
new file mode 100644
index 0000000..a7dc5ea
--- /dev/null
+++ b/drivers/infiniband/ulp/ipoib/ipoib_netlink.c
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2012 Mellanox Technologies. -  All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <linux/netdevice.h>
+#include <linux/module.h>
+#include <net/rtnetlink.h>
+#include "ipoib.h"
+
+static const struct nla_policy ipoib_policy[IFLA_IPOIB_MAX + 1] = {
+	[IFLA_IPOIB_PKEY]	= { .type = NLA_U16 },
+};
+
+static int ipoib_new_child_link(struct net *src_net, struct net_device *dev,
+			       struct nlattr *tb[], struct nlattr *data[])
+{
+	struct net_device *pdev;
+	struct ipoib_dev_priv *ppriv;
+	u16 child_pkey;
+	int err;
+
+	if (!tb[IFLA_LINK])
+		return -EINVAL;
+
+	pdev = __dev_get_by_index(src_net, nla_get_u32(tb[IFLA_LINK]));
+	if (!pdev)
+		return -ENODEV;
+
+	ppriv = netdev_priv(pdev);
+
+	if (test_bit(IPOIB_FLAG_SUBINTERFACE, &ppriv->flags)) {
+		ipoib_warn(ppriv, "child creation disallowed for child devices\n");
+		return -EINVAL;
+	}
+
+	if (!data || !data[IFLA_IPOIB_PKEY]) {
+		ipoib_dbg(ppriv, "no pkey specified, using parent pkey\n");
+		child_pkey  = ppriv->pkey;
+	} else
+		child_pkey  = nla_get_u16(data[IFLA_IPOIB_PKEY]);
+
+	err = __ipoib_vlan_add(ppriv, netdev_priv(dev), child_pkey, IPOIB_RTNL_CHILD);
+
+	return err;
+}
+
+static void ipoib_unregister_child_dev(struct net_device *dev, struct list_head *head)
+{
+	struct ipoib_dev_priv *priv, *ppriv;
+
+	priv = netdev_priv(dev);
+	ppriv = netdev_priv(priv->parent);
+
+	mutex_lock(&ppriv->vlan_mutex);
+	unregister_netdevice_queue(dev, head);
+	list_del(&priv->list);
+	mutex_unlock(&ppriv->vlan_mutex);
+}
+
+static size_t ipoib_get_size(const struct net_device *dev)
+{
+	return nla_total_size(2);	/* IFLA_IPOIB_PKEY */
+}
+
+static struct rtnl_link_ops ipoib_link_ops __read_mostly = {
+	.kind		= "ipoib",
+	.maxtype	= IFLA_IPOIB_MAX,
+	.policy		= ipoib_policy,
+	.priv_size	= sizeof(struct ipoib_dev_priv),
+	.setup		= ipoib_setup,
+	.newlink	= ipoib_new_child_link,
+	.dellink	= ipoib_unregister_child_dev,
+	.get_size	= ipoib_get_size,
+};
+
+int __init ipoib_netlink_init(void)
+{
+	return rtnl_link_register(&ipoib_link_ops);
+}
+
+void __exit ipoib_netlink_fini(void)
+{
+	rtnl_link_unregister(&ipoib_link_ops);
+}
+
+MODULE_ALIAS_RTNL_LINK("ipoib");
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
index d7e9740..238bbf9 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
@@ -49,47 +49,11 @@ static ssize_t show_parent(struct device *d, struct device_attribute *attr,
 }
 static DEVICE_ATTR(parent, S_IRUGO, show_parent, NULL);
 
-int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey)
+int __ipoib_vlan_add(struct ipoib_dev_priv *ppriv, struct ipoib_dev_priv *priv,
+		     u16 pkey, int type)
 {
-	struct ipoib_dev_priv *ppriv, *priv;
-	char intf_name[IFNAMSIZ];
 	int result;
 
-	if (!capable(CAP_NET_ADMIN))
-		return -EPERM;
-
-	ppriv = netdev_priv(pdev);
-
-	if (!rtnl_trylock())
-		return restart_syscall();
-	mutex_lock(&ppriv->vlan_mutex);
-
-	/*
-	 * First ensure this isn't a duplicate. We check the parent device and
-	 * then all of the child interfaces to make sure the Pkey doesn't match.
-	 */
-	if (ppriv->pkey == pkey) {
-		result = -ENOTUNIQ;
-		priv = NULL;
-		goto err;
-	}
-
-	list_for_each_entry(priv, &ppriv->child_intfs, list) {
-		if (priv->pkey == pkey) {
-			result = -ENOTUNIQ;
-			priv = NULL;
-			goto err;
-		}
-	}
-
-	snprintf(intf_name, sizeof intf_name, "%s.%04x",
-		 ppriv->dev->name, pkey);
-	priv = ipoib_intf_alloc(intf_name);
-	if (!priv) {
-		result = -ENOMEM;
-		goto err;
-	}
-
 	priv->max_ib_mtu = ppriv->max_ib_mtu;
 	/* MTU will be reset when mcast join happens */
 	priv->dev->mtu   = IPOIB_UD_MTU(priv->max_ib_mtu);
@@ -134,14 +98,13 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey)
 	if (device_create_file(&priv->dev->dev, &dev_attr_parent))
 		goto sysfs_failed;
 
+	priv->child_type = type;
 	list_add_tail(&priv->list, &ppriv->child_intfs);
 
-	mutex_unlock(&ppriv->vlan_mutex);
-	rtnl_unlock();
-
 	return 0;
 
 sysfs_failed:
+	result = -ENOMEM;
 	ipoib_delete_debug_files(priv->dev);
 	unregister_netdevice(priv->dev);
 
@@ -149,11 +112,60 @@ register_failed:
 	ipoib_dev_cleanup(priv->dev);
 
 err:
+	return result;
+}
+
+int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey)
+{
+	struct ipoib_dev_priv *ppriv, *priv;
+	char intf_name[IFNAMSIZ];
+	struct ipoib_dev_priv *tpriv;
+	int result;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	ppriv = netdev_priv(pdev);
+
+	snprintf(intf_name, sizeof intf_name, "%s.%04x",
+		 ppriv->dev->name, pkey);
+	priv = ipoib_intf_alloc(intf_name);
+	if (!priv)
+		return -ENOMEM;
+
+	if (!rtnl_trylock())
+		return restart_syscall();
+
+	mutex_lock(&ppriv->vlan_mutex);
+
+	/*
+	 * First ensure this isn't a duplicate. We check the parent device and
+	 * then all of the legacy child interfaces to make sure the Pkey
+	 * doesn't match.
+	 */
+	if (ppriv->pkey == pkey) {
+		result = -ENOTUNIQ;
+		goto out;
+	}
+
+	list_for_each_entry(tpriv, &ppriv->child_intfs, list) {
+		if (tpriv->pkey == pkey &&
+		    tpriv->child_type == IPOIB_LEGACY_CHILD) {
+			result = -ENOTUNIQ;
+			goto out;
+		}
+	}
+
+	result = __ipoib_vlan_add(ppriv, priv, pkey, IPOIB_LEGACY_CHILD);
+
+out:
 	mutex_unlock(&ppriv->vlan_mutex);
-	rtnl_unlock();
-	if (priv)
+
+	if (result)
 		free_netdev(priv->dev);
 
+	rtnl_unlock();
+
 	return result;
 }
 
@@ -171,9 +183,9 @@ int ipoib_vlan_delete(struct net_device *pdev, unsigned short pkey)
 		return restart_syscall();
 	mutex_lock(&ppriv->vlan_mutex);
 	list_for_each_entry_safe(priv, tpriv, &ppriv->child_intfs, list) {
-		if (priv->pkey == pkey) {
+		if (priv->pkey == pkey &&
+		    priv->child_type == IPOIB_LEGACY_CHILD) {
 			unregister_netdevice(priv->dev);
-			ipoib_dev_cleanup(priv->dev);
 			list_del(&priv->list);
 			dev = priv->dev;
 			break;
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index 1b5b0c7..922d845 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -638,9 +638,9 @@ static void srp_reset_req(struct srp_target_port *target, struct srp_request *re
 	struct scsi_cmnd *scmnd = srp_claim_req(target, req, NULL);
 
 	if (scmnd) {
+		srp_free_req(target, req, scmnd, 0);
 		scmnd->result = DID_RESET << 16;
 		scmnd->scsi_done(scmnd);
-		srp_free_req(target, req, scmnd, 0);
 	}
 }
 
@@ -1687,6 +1687,7 @@ static int srp_abort(struct scsi_cmnd *scmnd)
 			  SRP_TSK_ABORT_TASK);
 	srp_free_req(target, req, scmnd, 0);
 	scmnd->result = DID_ABORT << 16;
+	scmnd->scsi_done(scmnd);
 
 	return SUCCESS;
 }
diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c
index 9e1449f..cf23c46 100644
--- a/drivers/infiniband/ulp/srpt/ib_srpt.c
+++ b/drivers/infiniband/ulp/srpt/ib_srpt.c
@@ -3564,16 +3564,6 @@ static int srpt_get_tcm_cmd_state(struct se_cmd *se_cmd)
 	return srpt_get_cmd_state(ioctx);
 }
 
-static u16 srpt_set_fabric_sense_len(struct se_cmd *cmd, u32 sense_length)
-{
-	return 0;
-}
-
-static u16 srpt_get_fabric_sense_len(void)
-{
-	return 0;
-}
-
 /**
  * srpt_parse_i_port_id() - Parse an initiator port ID.
  * @name: ASCII representation of a 128-bit initiator port ID.
@@ -3953,8 +3943,6 @@ static struct target_core_fabric_ops srpt_template = {
 	.queue_data_in			= srpt_queue_response,
 	.queue_status			= srpt_queue_status,
 	.queue_tm_rsp			= srpt_queue_response,
-	.get_fabric_sense_len		= srpt_get_fabric_sense_len,
-	.set_fabric_sense_len		= srpt_set_fabric_sense_len,
 	/*
 	 * Setup function pointers for generic logic in
 	 * target_core_fabric_configfs.c
diff --git a/drivers/input/apm-power.c b/drivers/input/apm-power.c
index e90ee3d..650177a 100644
--- a/drivers/input/apm-power.c
+++ b/drivers/input/apm-power.c
@@ -33,7 +33,7 @@ static void system_power_event(unsigned int keycode)
 }
 
 static void apmpower_event(struct input_handle *handle, unsigned int type,
-		        unsigned int code, int value)
+			   unsigned int code, int value)
 {
 	/* only react on key down events */
 	if (value != 1)
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index 6c58bff..118d030 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -54,16 +54,9 @@ struct evdev_client {
 static struct evdev *evdev_table[EVDEV_MINORS];
 static DEFINE_MUTEX(evdev_table_mutex);
 
-static void evdev_pass_event(struct evdev_client *client,
-			     struct input_event *event,
-			     ktime_t mono, ktime_t real)
+static void __pass_event(struct evdev_client *client,
+			 const struct input_event *event)
 {
-	event->time = ktime_to_timeval(client->clkid == CLOCK_MONOTONIC ?
-					mono : real);
-
-	/* Interrupts are disabled, just acquire the lock. */
-	spin_lock(&client->buffer_lock);
-
 	client->buffer[client->head++] = *event;
 	client->head &= client->bufsize - 1;
 
@@ -86,42 +79,74 @@ static void evdev_pass_event(struct evdev_client *client,
 		client->packet_head = client->head;
 		kill_fasync(&client->fasync, SIGIO, POLL_IN);
 	}
+}
+
+static void evdev_pass_values(struct evdev_client *client,
+			const struct input_value *vals, unsigned int count,
+			ktime_t mono, ktime_t real)
+{
+	struct evdev *evdev = client->evdev;
+	const struct input_value *v;
+	struct input_event event;
+	bool wakeup = false;
+
+	event.time = ktime_to_timeval(client->clkid == CLOCK_MONOTONIC ?
+				      mono : real);
+
+	/* Interrupts are disabled, just acquire the lock. */
+	spin_lock(&client->buffer_lock);
+
+	for (v = vals; v != vals + count; v++) {
+		event.type = v->type;
+		event.code = v->code;
+		event.value = v->value;
+		__pass_event(client, &event);
+		if (v->type == EV_SYN && v->code == SYN_REPORT)
+			wakeup = true;
+	}
 
 	spin_unlock(&client->buffer_lock);
+
+	if (wakeup)
+		wake_up_interruptible(&evdev->wait);
 }
 
 /*
- * Pass incoming event to all connected clients.
+ * Pass incoming events to all connected clients.
  */
-static void evdev_event(struct input_handle *handle,
-			unsigned int type, unsigned int code, int value)
+static void evdev_events(struct input_handle *handle,
+			 const struct input_value *vals, unsigned int count)
 {
 	struct evdev *evdev = handle->private;
 	struct evdev_client *client;
-	struct input_event event;
 	ktime_t time_mono, time_real;
 
 	time_mono = ktime_get();
 	time_real = ktime_sub(time_mono, ktime_get_monotonic_offset());
 
-	event.type = type;
-	event.code = code;
-	event.value = value;
-
 	rcu_read_lock();
 
 	client = rcu_dereference(evdev->grab);
 
 	if (client)
-		evdev_pass_event(client, &event, time_mono, time_real);
+		evdev_pass_values(client, vals, count, time_mono, time_real);
 	else
 		list_for_each_entry_rcu(client, &evdev->client_list, node)
-			evdev_pass_event(client, &event, time_mono, time_real);
+			evdev_pass_values(client, vals, count,
+					  time_mono, time_real);
 
 	rcu_read_unlock();
+}
 
-	if (type == EV_SYN && code == SYN_REPORT)
-		wake_up_interruptible(&evdev->wait);
+/*
+ * Pass incoming event to all connected clients.
+ */
+static void evdev_event(struct input_handle *handle,
+			unsigned int type, unsigned int code, int value)
+{
+	struct input_value vals[] = { { type, code, value } };
+
+	evdev_events(handle, vals, 1);
 }
 
 static int evdev_fasync(int fd, struct file *file, int on)
@@ -653,20 +678,22 @@ static int evdev_handle_mt_request(struct input_dev *dev,
 				   unsigned int size,
 				   int __user *ip)
 {
-	const struct input_mt_slot *mt = dev->mt;
+	const struct input_mt *mt = dev->mt;
 	unsigned int code;
 	int max_slots;
 	int i;
 
 	if (get_user(code, &ip[0]))
 		return -EFAULT;
-	if (!input_is_mt_value(code))
+	if (!mt || !input_is_mt_value(code))
 		return -EINVAL;
 
 	max_slots = (size - sizeof(__u32)) / sizeof(__s32);
-	for (i = 0; i < dev->mtsize && i < max_slots; i++)
-		if (put_user(input_mt_get_value(&mt[i], code), &ip[1 + i]))
+	for (i = 0; i < mt->num_slots && i < max_slots; i++) {
+		int value = input_mt_get_value(&mt->slots[i], code);
+		if (put_user(value, &ip[1 + i]))
 			return -EFAULT;
+	}
 
 	return 0;
 }
@@ -1048,6 +1075,7 @@ MODULE_DEVICE_TABLE(input, evdev_ids);
 
 static struct input_handler evdev_handler = {
 	.event		= evdev_event,
+	.events		= evdev_events,
 	.connect	= evdev_connect,
 	.disconnect	= evdev_disconnect,
 	.fops		= &evdev_fops,
diff --git a/drivers/input/ff-core.c b/drivers/input/ff-core.c
index 480eb9d..f50f6dd 100644
--- a/drivers/input/ff-core.c
+++ b/drivers/input/ff-core.c
@@ -138,8 +138,8 @@ int input_ff_upload(struct input_dev *dev, struct ff_effect *effect,
 
 	if (effect->id == -1) {
 		for (id = 0; id < ff->max_effects; id++)
-		     if (!ff->effect_owners[id])
-			break;
+			if (!ff->effect_owners[id])
+				break;
 
 		if (id >= ff->max_effects) {
 			ret = -ENOSPC;
diff --git a/drivers/input/ff-memless.c b/drivers/input/ff-memless.c
index b107922..74c0d8c 100644
--- a/drivers/input/ff-memless.c
+++ b/drivers/input/ff-memless.c
@@ -72,12 +72,14 @@ static const struct ff_envelope *get_envelope(const struct ff_effect *effect)
 	static const struct ff_envelope empty_envelope;
 
 	switch (effect->type) {
-		case FF_PERIODIC:
-			return &effect->u.periodic.envelope;
-		case FF_CONSTANT:
-			return &effect->u.constant.envelope;
-		default:
-			return &empty_envelope;
+	case FF_PERIODIC:
+		return &effect->u.periodic.envelope;
+
+	case FF_CONSTANT:
+		return &effect->u.constant.envelope;
+
+	default:
+		return &empty_envelope;
 	}
 }
 
diff --git a/drivers/input/input-mt.c b/drivers/input/input-mt.c
index 70a16c7..c0ec7d4 100644
--- a/drivers/input/input-mt.c
+++ b/drivers/input/input-mt.c
@@ -14,6 +14,14 @@
 
 #define TRKID_SGN	((TRKID_MAX + 1) >> 1)
 
+static void copy_abs(struct input_dev *dev, unsigned int dst, unsigned int src)
+{
+	if (dev->absinfo && test_bit(src, dev->absbit)) {
+		dev->absinfo[dst] = dev->absinfo[src];
+		dev->absbit[BIT_WORD(dst)] |= BIT_MASK(dst);
+	}
+}
+
 /**
  * input_mt_init_slots() - initialize MT input slots
  * @dev: input device supporting MT events and finger tracking
@@ -25,29 +33,63 @@
  * May be called repeatedly. Returns -EINVAL if attempting to
  * reinitialize with a different number of slots.
  */
-int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots)
+int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots,
+			unsigned int flags)
 {
+	struct input_mt *mt = dev->mt;
 	int i;
 
 	if (!num_slots)
 		return 0;
-	if (dev->mt)
-		return dev->mtsize != num_slots ? -EINVAL : 0;
+	if (mt)
+		return mt->num_slots != num_slots ? -EINVAL : 0;
 
-	dev->mt = kcalloc(num_slots, sizeof(struct input_mt_slot), GFP_KERNEL);
-	if (!dev->mt)
-		return -ENOMEM;
+	mt = kzalloc(sizeof(*mt) + num_slots * sizeof(*mt->slots), GFP_KERNEL);
+	if (!mt)
+		goto err_mem;
 
-	dev->mtsize = num_slots;
+	mt->num_slots = num_slots;
+	mt->flags = flags;
 	input_set_abs_params(dev, ABS_MT_SLOT, 0, num_slots - 1, 0, 0);
 	input_set_abs_params(dev, ABS_MT_TRACKING_ID, 0, TRKID_MAX, 0, 0);
-	input_set_events_per_packet(dev, 6 * num_slots);
+
+	if (flags & (INPUT_MT_POINTER | INPUT_MT_DIRECT)) {
+		__set_bit(EV_KEY, dev->evbit);
+		__set_bit(BTN_TOUCH, dev->keybit);
+
+		copy_abs(dev, ABS_X, ABS_MT_POSITION_X);
+		copy_abs(dev, ABS_Y, ABS_MT_POSITION_Y);
+		copy_abs(dev, ABS_PRESSURE, ABS_MT_PRESSURE);
+	}
+	if (flags & INPUT_MT_POINTER) {
+		__set_bit(BTN_TOOL_FINGER, dev->keybit);
+		__set_bit(BTN_TOOL_DOUBLETAP, dev->keybit);
+		if (num_slots >= 3)
+			__set_bit(BTN_TOOL_TRIPLETAP, dev->keybit);
+		if (num_slots >= 4)
+			__set_bit(BTN_TOOL_QUADTAP, dev->keybit);
+		if (num_slots >= 5)
+			__set_bit(BTN_TOOL_QUINTTAP, dev->keybit);
+		__set_bit(INPUT_PROP_POINTER, dev->propbit);
+	}
+	if (flags & INPUT_MT_DIRECT)
+		__set_bit(INPUT_PROP_DIRECT, dev->propbit);
+	if (flags & INPUT_MT_TRACK) {
+		unsigned int n2 = num_slots * num_slots;
+		mt->red = kcalloc(n2, sizeof(*mt->red), GFP_KERNEL);
+		if (!mt->red)
+			goto err_mem;
+	}
 
 	/* Mark slots as 'unused' */
 	for (i = 0; i < num_slots; i++)
-		input_mt_set_value(&dev->mt[i], ABS_MT_TRACKING_ID, -1);
+		input_mt_set_value(&mt->slots[i], ABS_MT_TRACKING_ID, -1);
 
+	dev->mt = mt;
 	return 0;
+err_mem:
+	kfree(mt);
+	return -ENOMEM;
 }
 EXPORT_SYMBOL(input_mt_init_slots);
 
@@ -60,11 +102,11 @@ EXPORT_SYMBOL(input_mt_init_slots);
  */
 void input_mt_destroy_slots(struct input_dev *dev)
 {
-	kfree(dev->mt);
+	if (dev->mt) {
+		kfree(dev->mt->red);
+		kfree(dev->mt);
+	}
 	dev->mt = NULL;
-	dev->mtsize = 0;
-	dev->slot = 0;
-	dev->trkid = 0;
 }
 EXPORT_SYMBOL(input_mt_destroy_slots);
 
@@ -83,18 +125,24 @@ EXPORT_SYMBOL(input_mt_destroy_slots);
 void input_mt_report_slot_state(struct input_dev *dev,
 				unsigned int tool_type, bool active)
 {
-	struct input_mt_slot *mt;
+	struct input_mt *mt = dev->mt;
+	struct input_mt_slot *slot;
 	int id;
 
-	if (!dev->mt || !active) {
+	if (!mt)
+		return;
+
+	slot = &mt->slots[mt->slot];
+	slot->frame = mt->frame;
+
+	if (!active) {
 		input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1);
 		return;
 	}
 
-	mt = &dev->mt[dev->slot];
-	id = input_mt_get_value(mt, ABS_MT_TRACKING_ID);
-	if (id < 0 || input_mt_get_value(mt, ABS_MT_TOOL_TYPE) != tool_type)
-		id = input_mt_new_trkid(dev);
+	id = input_mt_get_value(slot, ABS_MT_TRACKING_ID);
+	if (id < 0 || input_mt_get_value(slot, ABS_MT_TOOL_TYPE) != tool_type)
+		id = input_mt_new_trkid(mt);
 
 	input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, id);
 	input_event(dev, EV_ABS, ABS_MT_TOOL_TYPE, tool_type);
@@ -135,13 +183,19 @@ EXPORT_SYMBOL(input_mt_report_finger_count);
  */
 void input_mt_report_pointer_emulation(struct input_dev *dev, bool use_count)
 {
-	struct input_mt_slot *oldest = NULL;
-	int oldid = dev->trkid;
-	int count = 0;
-	int i;
+	struct input_mt *mt = dev->mt;
+	struct input_mt_slot *oldest;
+	int oldid, count, i;
+
+	if (!mt)
+		return;
+
+	oldest = 0;
+	oldid = mt->trkid;
+	count = 0;
 
-	for (i = 0; i < dev->mtsize; ++i) {
-		struct input_mt_slot *ps = &dev->mt[i];
+	for (i = 0; i < mt->num_slots; ++i) {
+		struct input_mt_slot *ps = &mt->slots[i];
 		int id = input_mt_get_value(ps, ABS_MT_TRACKING_ID);
 
 		if (id < 0)
@@ -160,13 +214,208 @@ void input_mt_report_pointer_emulation(struct input_dev *dev, bool use_count)
 	if (oldest) {
 		int x = input_mt_get_value(oldest, ABS_MT_POSITION_X);
 		int y = input_mt_get_value(oldest, ABS_MT_POSITION_Y);
-		int p = input_mt_get_value(oldest, ABS_MT_PRESSURE);
 
 		input_event(dev, EV_ABS, ABS_X, x);
 		input_event(dev, EV_ABS, ABS_Y, y);
-		input_event(dev, EV_ABS, ABS_PRESSURE, p);
+
+		if (test_bit(ABS_MT_PRESSURE, dev->absbit)) {
+			int p = input_mt_get_value(oldest, ABS_MT_PRESSURE);
+			input_event(dev, EV_ABS, ABS_PRESSURE, p);
+		}
 	} else {
-		input_event(dev, EV_ABS, ABS_PRESSURE, 0);
+		if (test_bit(ABS_MT_PRESSURE, dev->absbit))
+			input_event(dev, EV_ABS, ABS_PRESSURE, 0);
 	}
 }
 EXPORT_SYMBOL(input_mt_report_pointer_emulation);
+
+/**
+ * input_mt_sync_frame() - synchronize mt frame
+ * @dev: input device with allocated MT slots
+ *
+ * Close the frame and prepare the internal state for a new one.
+ * Depending on the flags, marks unused slots as inactive and performs
+ * pointer emulation.
+ */
+void input_mt_sync_frame(struct input_dev *dev)
+{
+	struct input_mt *mt = dev->mt;
+	struct input_mt_slot *s;
+
+	if (!mt)
+		return;
+
+	if (mt->flags & INPUT_MT_DROP_UNUSED) {
+		for (s = mt->slots; s != mt->slots + mt->num_slots; s++) {
+			if (s->frame == mt->frame)
+				continue;
+			input_mt_slot(dev, s - mt->slots);
+			input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1);
+		}
+	}
+
+	input_mt_report_pointer_emulation(dev, (mt->flags & INPUT_MT_POINTER));
+
+	mt->frame++;
+}
+EXPORT_SYMBOL(input_mt_sync_frame);
+
+static int adjust_dual(int *begin, int step, int *end, int eq)
+{
+	int f, *p, s, c;
+
+	if (begin == end)
+		return 0;
+
+	f = *begin;
+	p = begin + step;
+	s = p == end ? f + 1 : *p;
+
+	for (; p != end; p += step)
+		if (*p < f)
+			s = f, f = *p;
+		else if (*p < s)
+			s = *p;
+
+	c = (f + s + 1) / 2;
+	if (c == 0 || (c > 0 && !eq))
+		return 0;
+	if (s < 0)
+		c *= 2;
+
+	for (p = begin; p != end; p += step)
+		*p -= c;
+
+	return (c < s && s <= 0) || (f >= 0 && f < c);
+}
+
+static void find_reduced_matrix(int *w, int nr, int nc, int nrc)
+{
+	int i, k, sum;
+
+	for (k = 0; k < nrc; k++) {
+		for (i = 0; i < nr; i++)
+			adjust_dual(w + i, nr, w + i + nrc, nr <= nc);
+		sum = 0;
+		for (i = 0; i < nrc; i += nr)
+			sum += adjust_dual(w + i, 1, w + i + nr, nc <= nr);
+		if (!sum)
+			break;
+	}
+}
+
+static int input_mt_set_matrix(struct input_mt *mt,
+			       const struct input_mt_pos *pos, int num_pos)
+{
+	const struct input_mt_pos *p;
+	struct input_mt_slot *s;
+	int *w = mt->red;
+	int x, y;
+
+	for (s = mt->slots; s != mt->slots + mt->num_slots; s++) {
+		if (!input_mt_is_active(s))
+			continue;
+		x = input_mt_get_value(s, ABS_MT_POSITION_X);
+		y = input_mt_get_value(s, ABS_MT_POSITION_Y);
+		for (p = pos; p != pos + num_pos; p++) {
+			int dx = x - p->x, dy = y - p->y;
+			*w++ = dx * dx + dy * dy;
+		}
+	}
+
+	return w - mt->red;
+}
+
+static void input_mt_set_slots(struct input_mt *mt,
+			       int *slots, int num_pos)
+{
+	struct input_mt_slot *s;
+	int *w = mt->red, *p;
+
+	for (p = slots; p != slots + num_pos; p++)
+		*p = -1;
+
+	for (s = mt->slots; s != mt->slots + mt->num_slots; s++) {
+		if (!input_mt_is_active(s))
+			continue;
+		for (p = slots; p != slots + num_pos; p++)
+			if (*w++ < 0)
+				*p = s - mt->slots;
+	}
+
+	for (s = mt->slots; s != mt->slots + mt->num_slots; s++) {
+		if (input_mt_is_active(s))
+			continue;
+		for (p = slots; p != slots + num_pos; p++)
+			if (*p < 0) {
+				*p = s - mt->slots;
+				break;
+			}
+	}
+}
+
+/**
+ * input_mt_assign_slots() - perform a best-match assignment
+ * @dev: input device with allocated MT slots
+ * @slots: the slot assignment to be filled
+ * @pos: the position array to match
+ * @num_pos: number of positions
+ *
+ * Performs a best match against the current contacts and returns
+ * the slot assignment list. New contacts are assigned to unused
+ * slots.
+ *
+ * Returns zero on success, or negative error in case of failure.
+ */
+int input_mt_assign_slots(struct input_dev *dev, int *slots,
+			  const struct input_mt_pos *pos, int num_pos)
+{
+	struct input_mt *mt = dev->mt;
+	int nrc;
+
+	if (!mt || !mt->red)
+		return -ENXIO;
+	if (num_pos > mt->num_slots)
+		return -EINVAL;
+	if (num_pos < 1)
+		return 0;
+
+	nrc = input_mt_set_matrix(mt, pos, num_pos);
+	find_reduced_matrix(mt->red, num_pos, nrc / num_pos, nrc);
+	input_mt_set_slots(mt, slots, num_pos);
+
+	return 0;
+}
+EXPORT_SYMBOL(input_mt_assign_slots);
+
+/**
+ * input_mt_get_slot_by_key() - return slot matching key
+ * @dev: input device with allocated MT slots
+ * @key: the key of the sought slot
+ *
+ * Returns the slot of the given key, if it exists, otherwise
+ * set the key on the first unused slot and return.
+ *
+ * If no available slot can be found, -1 is returned.
+ */
+int input_mt_get_slot_by_key(struct input_dev *dev, int key)
+{
+	struct input_mt *mt = dev->mt;
+	struct input_mt_slot *s;
+
+	if (!mt)
+		return -1;
+
+	for (s = mt->slots; s != mt->slots + mt->num_slots; s++)
+		if (input_mt_is_active(s) && s->key == key)
+			return s - mt->slots;
+
+	for (s = mt->slots; s != mt->slots + mt->num_slots; s++)
+		if (!input_mt_is_active(s)) {
+			s->key = key;
+			return s - mt->slots;
+		}
+
+	return -1;
+}
+EXPORT_SYMBOL(input_mt_get_slot_by_key);
diff --git a/drivers/input/input.c b/drivers/input/input.c
index 8921c61..ace3f7c 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -47,6 +47,8 @@ static DEFINE_MUTEX(input_mutex);
 
 static struct input_handler *input_table[8];
 
+static const struct input_value input_value_sync = { EV_SYN, SYN_REPORT, 1 };
+
 static inline int is_event_supported(unsigned int code,
 				     unsigned long *bm, unsigned int max)
 {
@@ -69,42 +71,102 @@ static int input_defuzz_abs_event(int value, int old_val, int fuzz)
 	return value;
 }
 
+static void input_start_autorepeat(struct input_dev *dev, int code)
+{
+	if (test_bit(EV_REP, dev->evbit) &&
+	    dev->rep[REP_PERIOD] && dev->rep[REP_DELAY] &&
+	    dev->timer.data) {
+		dev->repeat_key = code;
+		mod_timer(&dev->timer,
+			  jiffies + msecs_to_jiffies(dev->rep[REP_DELAY]));
+	}
+}
+
+static void input_stop_autorepeat(struct input_dev *dev)
+{
+	del_timer(&dev->timer);
+}
+
 /*
  * Pass event first through all filters and then, if event has not been
  * filtered out, through all open handles. This function is called with
  * dev->event_lock held and interrupts disabled.
  */
-static void input_pass_event(struct input_dev *dev,
-			     unsigned int type, unsigned int code, int value)
+static unsigned int input_to_handler(struct input_handle *handle,
+			struct input_value *vals, unsigned int count)
+{
+	struct input_handler *handler = handle->handler;
+	struct input_value *end = vals;
+	struct input_value *v;
+
+	for (v = vals; v != vals + count; v++) {
+		if (handler->filter &&
+		    handler->filter(handle, v->type, v->code, v->value))
+			continue;
+		if (end != v)
+			*end = *v;
+		end++;
+	}
+
+	count = end - vals;
+	if (!count)
+		return 0;
+
+	if (handler->events)
+		handler->events(handle, vals, count);
+	else if (handler->event)
+		for (v = vals; v != end; v++)
+			handler->event(handle, v->type, v->code, v->value);
+
+	return count;
+}
+
+/*
+ * Pass values first through all filters and then, if event has not been
+ * filtered out, through all open handles. This function is called with
+ * dev->event_lock held and interrupts disabled.
+ */
+static void input_pass_values(struct input_dev *dev,
+			      struct input_value *vals, unsigned int count)
 {
-	struct input_handler *handler;
 	struct input_handle *handle;
+	struct input_value *v;
+
+	if (!count)
+		return;
 
 	rcu_read_lock();
 
 	handle = rcu_dereference(dev->grab);
-	if (handle)
-		handle->handler->event(handle, type, code, value);
-	else {
-		bool filtered = false;
-
-		list_for_each_entry_rcu(handle, &dev->h_list, d_node) {
-			if (!handle->open)
-				continue;
+	if (handle) {
+		count = input_to_handler(handle, vals, count);
+	} else {
+		list_for_each_entry_rcu(handle, &dev->h_list, d_node)
+			if (handle->open)
+				count = input_to_handler(handle, vals, count);
+	}
 
-			handler = handle->handler;
-			if (!handler->filter) {
-				if (filtered)
-					break;
+	rcu_read_unlock();
 
-				handler->event(handle, type, code, value);
+	add_input_randomness(vals->type, vals->code, vals->value);
 
-			} else if (handler->filter(handle, type, code, value))
-				filtered = true;
+	/* trigger auto repeat for key events */
+	for (v = vals; v != vals + count; v++) {
+		if (v->type == EV_KEY && v->value != 2) {
+			if (v->value)
+				input_start_autorepeat(dev, v->code);
+			else
+				input_stop_autorepeat(dev);
 		}
 	}
+}
 
-	rcu_read_unlock();
+static void input_pass_event(struct input_dev *dev,
+			     unsigned int type, unsigned int code, int value)
+{
+	struct input_value vals[] = { { type, code, value } };
+
+	input_pass_values(dev, vals, ARRAY_SIZE(vals));
 }
 
 /*
@@ -121,18 +183,12 @@ static void input_repeat_key(unsigned long data)
 
 	if (test_bit(dev->repeat_key, dev->key) &&
 	    is_event_supported(dev->repeat_key, dev->keybit, KEY_MAX)) {
+		struct input_value vals[] =  {
+			{ EV_KEY, dev->repeat_key, 2 },
+			input_value_sync
+		};
 
-		input_pass_event(dev, EV_KEY, dev->repeat_key, 2);
-
-		if (dev->sync) {
-			/*
-			 * Only send SYN_REPORT if we are not in a middle
-			 * of driver parsing a new hardware packet.
-			 * Otherwise assume that the driver will send
-			 * SYN_REPORT once it's done.
-			 */
-			input_pass_event(dev, EV_SYN, SYN_REPORT, 1);
-		}
+		input_pass_values(dev, vals, ARRAY_SIZE(vals));
 
 		if (dev->rep[REP_PERIOD])
 			mod_timer(&dev->timer, jiffies +
@@ -142,30 +198,17 @@ static void input_repeat_key(unsigned long data)
 	spin_unlock_irqrestore(&dev->event_lock, flags);
 }
 
-static void input_start_autorepeat(struct input_dev *dev, int code)
-{
-	if (test_bit(EV_REP, dev->evbit) &&
-	    dev->rep[REP_PERIOD] && dev->rep[REP_DELAY] &&
-	    dev->timer.data) {
-		dev->repeat_key = code;
-		mod_timer(&dev->timer,
-			  jiffies + msecs_to_jiffies(dev->rep[REP_DELAY]));
-	}
-}
-
-static void input_stop_autorepeat(struct input_dev *dev)
-{
-	del_timer(&dev->timer);
-}
-
 #define INPUT_IGNORE_EVENT	0
 #define INPUT_PASS_TO_HANDLERS	1
 #define INPUT_PASS_TO_DEVICE	2
+#define INPUT_SLOT		4
+#define INPUT_FLUSH		8
 #define INPUT_PASS_TO_ALL	(INPUT_PASS_TO_HANDLERS | INPUT_PASS_TO_DEVICE)
 
 static int input_handle_abs_event(struct input_dev *dev,
 				  unsigned int code, int *pval)
 {
+	struct input_mt *mt = dev->mt;
 	bool is_mt_event;
 	int *pold;
 
@@ -174,8 +217,8 @@ static int input_handle_abs_event(struct input_dev *dev,
 		 * "Stage" the event; we'll flush it later, when we
 		 * get actual touch data.
 		 */
-		if (*pval >= 0 && *pval < dev->mtsize)
-			dev->slot = *pval;
+		if (mt && *pval >= 0 && *pval < mt->num_slots)
+			mt->slot = *pval;
 
 		return INPUT_IGNORE_EVENT;
 	}
@@ -184,9 +227,8 @@ static int input_handle_abs_event(struct input_dev *dev,
 
 	if (!is_mt_event) {
 		pold = &dev->absinfo[code].value;
-	} else if (dev->mt) {
-		struct input_mt_slot *mtslot = &dev->mt[dev->slot];
-		pold = &mtslot->abs[code - ABS_MT_FIRST];
+	} else if (mt) {
+		pold = &mt->slots[mt->slot].abs[code - ABS_MT_FIRST];
 	} else {
 		/*
 		 * Bypass filtering for multi-touch events when
@@ -205,16 +247,16 @@ static int input_handle_abs_event(struct input_dev *dev,
 	}
 
 	/* Flush pending "slot" event */
-	if (is_mt_event && dev->slot != input_abs_get_val(dev, ABS_MT_SLOT)) {
-		input_abs_set_val(dev, ABS_MT_SLOT, dev->slot);
-		input_pass_event(dev, EV_ABS, ABS_MT_SLOT, dev->slot);
+	if (is_mt_event && mt && mt->slot != input_abs_get_val(dev, ABS_MT_SLOT)) {
+		input_abs_set_val(dev, ABS_MT_SLOT, mt->slot);
+		return INPUT_PASS_TO_HANDLERS | INPUT_SLOT;
 	}
 
 	return INPUT_PASS_TO_HANDLERS;
 }
 
-static void input_handle_event(struct input_dev *dev,
-			       unsigned int type, unsigned int code, int value)
+static int input_get_disposition(struct input_dev *dev,
+			  unsigned int type, unsigned int code, int value)
 {
 	int disposition = INPUT_IGNORE_EVENT;
 
@@ -227,37 +269,34 @@ static void input_handle_event(struct input_dev *dev,
 			break;
 
 		case SYN_REPORT:
-			if (!dev->sync) {
-				dev->sync = true;
-				disposition = INPUT_PASS_TO_HANDLERS;
-			}
+			disposition = INPUT_PASS_TO_HANDLERS | INPUT_FLUSH;
 			break;
 		case SYN_MT_REPORT:
-			dev->sync = false;
 			disposition = INPUT_PASS_TO_HANDLERS;
 			break;
 		}
 		break;
 
 	case EV_KEY:
-		if (is_event_supported(code, dev->keybit, KEY_MAX) &&
-		    !!test_bit(code, dev->key) != value) {
+		if (is_event_supported(code, dev->keybit, KEY_MAX)) {
 
-			if (value != 2) {
-				__change_bit(code, dev->key);
-				if (value)
-					input_start_autorepeat(dev, code);
-				else
-					input_stop_autorepeat(dev);
+			/* auto-repeat bypasses state updates */
+			if (value == 2) {
+				disposition = INPUT_PASS_TO_HANDLERS;
+				break;
 			}
 
-			disposition = INPUT_PASS_TO_HANDLERS;
+			if (!!test_bit(code, dev->key) != !!value) {
+
+				__change_bit(code, dev->key);
+				disposition = INPUT_PASS_TO_HANDLERS;
+			}
 		}
 		break;
 
 	case EV_SW:
 		if (is_event_supported(code, dev->swbit, SW_MAX) &&
-		    !!test_bit(code, dev->sw) != value) {
+		    !!test_bit(code, dev->sw) != !!value) {
 
 			__change_bit(code, dev->sw);
 			disposition = INPUT_PASS_TO_HANDLERS;
@@ -284,7 +323,7 @@ static void input_handle_event(struct input_dev *dev,
 
 	case EV_LED:
 		if (is_event_supported(code, dev->ledbit, LED_MAX) &&
-		    !!test_bit(code, dev->led) != value) {
+		    !!test_bit(code, dev->led) != !!value) {
 
 			__change_bit(code, dev->led);
 			disposition = INPUT_PASS_TO_ALL;
@@ -317,14 +356,48 @@ static void input_handle_event(struct input_dev *dev,
 		break;
 	}
 
-	if (disposition != INPUT_IGNORE_EVENT && type != EV_SYN)
-		dev->sync = false;
+	return disposition;
+}
+
+static void input_handle_event(struct input_dev *dev,
+			       unsigned int type, unsigned int code, int value)
+{
+	int disposition;
+
+	disposition = input_get_disposition(dev, type, code, value);
 
 	if ((disposition & INPUT_PASS_TO_DEVICE) && dev->event)
 		dev->event(dev, type, code, value);
 
-	if (disposition & INPUT_PASS_TO_HANDLERS)
-		input_pass_event(dev, type, code, value);
+	if (!dev->vals)
+		return;
+
+	if (disposition & INPUT_PASS_TO_HANDLERS) {
+		struct input_value *v;
+
+		if (disposition & INPUT_SLOT) {
+			v = &dev->vals[dev->num_vals++];
+			v->type = EV_ABS;
+			v->code = ABS_MT_SLOT;
+			v->value = dev->mt->slot;
+		}
+
+		v = &dev->vals[dev->num_vals++];
+		v->type = type;
+		v->code = code;
+		v->value = value;
+	}
+
+	if (disposition & INPUT_FLUSH) {
+		if (dev->num_vals >= 2)
+			input_pass_values(dev, dev->vals, dev->num_vals);
+		dev->num_vals = 0;
+	} else if (dev->num_vals >= dev->max_vals - 2) {
+		dev->vals[dev->num_vals++] = input_value_sync;
+		input_pass_values(dev, dev->vals, dev->num_vals);
+		dev->num_vals = 0;
+	}
+
 }
 
 /**
@@ -352,7 +425,6 @@ void input_event(struct input_dev *dev,
 	if (is_event_supported(type, dev->evbit, EV_MAX)) {
 
 		spin_lock_irqsave(&dev->event_lock, flags);
-		add_input_randomness(type, code, value);
 		input_handle_event(dev, type, code, value);
 		spin_unlock_irqrestore(&dev->event_lock, flags);
 	}
@@ -831,10 +903,12 @@ int input_set_keycode(struct input_dev *dev,
 	if (test_bit(EV_KEY, dev->evbit) &&
 	    !is_event_supported(old_keycode, dev->keybit, KEY_MAX) &&
 	    __test_and_clear_bit(old_keycode, dev->key)) {
+		struct input_value vals[] =  {
+			{ EV_KEY, old_keycode, 0 },
+			input_value_sync
+		};
 
-		input_pass_event(dev, EV_KEY, old_keycode, 0);
-		if (dev->sync)
-			input_pass_event(dev, EV_SYN, SYN_REPORT, 1);
+		input_pass_values(dev, vals, ARRAY_SIZE(vals));
 	}
 
  out:
@@ -844,18 +918,10 @@ int input_set_keycode(struct input_dev *dev,
 }
 EXPORT_SYMBOL(input_set_keycode);
 
-#define MATCH_BIT(bit, max) \
-		for (i = 0; i < BITS_TO_LONGS(max); i++) \
-			if ((id->bit[i] & dev->bit[i]) != id->bit[i]) \
-				break; \
-		if (i != BITS_TO_LONGS(max)) \
-			continue;
-
 static const struct input_device_id *input_match_device(struct input_handler *handler,
 							struct input_dev *dev)
 {
 	const struct input_device_id *id;
-	int i;
 
 	for (id = handler->id_table; id->flags || id->driver_info; id++) {
 
@@ -875,15 +941,32 @@ static const struct input_device_id *input_match_device(struct input_handler *ha
 			if (id->version != dev->id.version)
 				continue;
 
-		MATCH_BIT(evbit,  EV_MAX);
-		MATCH_BIT(keybit, KEY_MAX);
-		MATCH_BIT(relbit, REL_MAX);
-		MATCH_BIT(absbit, ABS_MAX);
-		MATCH_BIT(mscbit, MSC_MAX);
-		MATCH_BIT(ledbit, LED_MAX);
-		MATCH_BIT(sndbit, SND_MAX);
-		MATCH_BIT(ffbit,  FF_MAX);
-		MATCH_BIT(swbit,  SW_MAX);
+		if (!bitmap_subset(id->evbit, dev->evbit, EV_MAX))
+			continue;
+
+		if (!bitmap_subset(id->keybit, dev->keybit, KEY_MAX))
+			continue;
+
+		if (!bitmap_subset(id->relbit, dev->relbit, REL_MAX))
+			continue;
+
+		if (!bitmap_subset(id->absbit, dev->absbit, ABS_MAX))
+			continue;
+
+		if (!bitmap_subset(id->mscbit, dev->mscbit, MSC_MAX))
+			continue;
+
+		if (!bitmap_subset(id->ledbit, dev->ledbit, LED_MAX))
+			continue;
+
+		if (!bitmap_subset(id->sndbit, dev->sndbit, SND_MAX))
+			continue;
+
+		if (!bitmap_subset(id->ffbit, dev->ffbit, FF_MAX))
+			continue;
+
+		if (!bitmap_subset(id->swbit, dev->swbit, SW_MAX))
+			continue;
 
 		if (!handler->match || handler->match(handler, dev))
 			return id;
@@ -1416,6 +1499,7 @@ static void input_dev_release(struct device *device)
 	input_ff_destroy(dev);
 	input_mt_destroy_slots(dev);
 	kfree(dev->absinfo);
+	kfree(dev->vals);
 	kfree(dev);
 
 	module_put(THIS_MODULE);
@@ -1751,8 +1835,8 @@ static unsigned int input_estimate_events_per_packet(struct input_dev *dev)
 	int i;
 	unsigned int events;
 
-	if (dev->mtsize) {
-		mt_slots = dev->mtsize;
+	if (dev->mt) {
+		mt_slots = dev->mt->num_slots;
 	} else if (test_bit(ABS_MT_TRACKING_ID, dev->absbit)) {
 		mt_slots = dev->absinfo[ABS_MT_TRACKING_ID].maximum -
 			   dev->absinfo[ABS_MT_TRACKING_ID].minimum + 1,
@@ -1778,6 +1862,9 @@ static unsigned int input_estimate_events_per_packet(struct input_dev *dev)
 		if (test_bit(i, dev->relbit))
 			events++;
 
+	/* Make room for KEY and MSC events */
+	events += 7;
+
 	return events;
 }
 
@@ -1816,6 +1903,7 @@ int input_register_device(struct input_dev *dev)
 {
 	static atomic_t input_no = ATOMIC_INIT(0);
 	struct input_handler *handler;
+	unsigned int packet_size;
 	const char *path;
 	int error;
 
@@ -1828,9 +1916,14 @@ int input_register_device(struct input_dev *dev)
 	/* Make sure that bitmasks not mentioned in dev->evbit are clean. */
 	input_cleanse_bitmasks(dev);
 
-	if (!dev->hint_events_per_packet)
-		dev->hint_events_per_packet =
-				input_estimate_events_per_packet(dev);
+	packet_size = input_estimate_events_per_packet(dev);
+	if (dev->hint_events_per_packet < packet_size)
+		dev->hint_events_per_packet = packet_size;
+
+	dev->max_vals = max(dev->hint_events_per_packet, packet_size) + 2;
+	dev->vals = kcalloc(dev->max_vals, sizeof(*dev->vals), GFP_KERNEL);
+	if (!dev->vals)
+		return -ENOMEM;
 
 	/*
 	 * If delay and period are pre-set by the driver, then autorepeating
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c
index 26043cc..78f323e 100644
--- a/drivers/input/joydev.c
+++ b/drivers/input/joydev.c
@@ -711,7 +711,7 @@ static long joydev_ioctl(struct file *file,
 
 	case JS_SET_ALL:
 		retval = copy_from_user(&joydev->glue, argp,
-					sizeof(joydev->glue)) ? -EFAULT: 0;
+					sizeof(joydev->glue)) ? -EFAULT : 0;
 		break;
 
 	case JS_GET_ALL:
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index c50fa75..b4b65af 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -533,7 +533,7 @@ config KEYBOARD_DAVINCI
 
 config KEYBOARD_OMAP
 	tristate "TI OMAP keypad support"
-	depends on (ARCH_OMAP1 || ARCH_OMAP2)
+	depends on ARCH_OMAP1
 	select INPUT_MATRIXKMAP
 	help
 	  Say Y here if you want to use the OMAP keypad.
diff --git a/drivers/input/keyboard/davinci_keyscan.c b/drivers/input/keyboard/davinci_keyscan.c
index 9d82b3a..d5bacbb 100644
--- a/drivers/input/keyboard/davinci_keyscan.c
+++ b/drivers/input/keyboard/davinci_keyscan.c
@@ -36,7 +36,7 @@
 
 #include <mach/hardware.h>
 #include <mach/irqs.h>
-#include <mach/keyscan.h>
+#include <linux/platform_data/keyscan-davinci.h>
 
 /* Key scan registers */
 #define DAVINCI_KEYSCAN_KEYCTRL		0x0000
diff --git a/drivers/input/keyboard/ep93xx_keypad.c b/drivers/input/keyboard/ep93xx_keypad.c
index c46fc81..7363402 100644
--- a/drivers/input/keyboard/ep93xx_keypad.c
+++ b/drivers/input/keyboard/ep93xx_keypad.c
@@ -29,7 +29,7 @@
 #include <linux/slab.h>
 
 #include <mach/hardware.h>
-#include <mach/ep93xx_keypad.h>
+#include <linux/platform_data/keypad-ep93xx.h>
 
 /*
  * Keypad Interface Register offsets
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
index cbb1add..6a68041 100644
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -43,11 +43,9 @@ struct gpio_button_data {
 };
 
 struct gpio_keys_drvdata {
+	const struct gpio_keys_platform_data *pdata;
 	struct input_dev *input;
 	struct mutex disable_lock;
-	unsigned int n_buttons;
-	int (*enable)(struct device *dev);
-	void (*disable)(struct device *dev);
 	struct gpio_button_data data[0];
 };
 
@@ -171,7 +169,7 @@ static ssize_t gpio_keys_attr_show_helper(struct gpio_keys_drvdata *ddata,
 	if (!bits)
 		return -ENOMEM;
 
-	for (i = 0; i < ddata->n_buttons; i++) {
+	for (i = 0; i < ddata->pdata->nbuttons; i++) {
 		struct gpio_button_data *bdata = &ddata->data[i];
 
 		if (bdata->button->type != type)
@@ -219,7 +217,7 @@ static ssize_t gpio_keys_attr_store_helper(struct gpio_keys_drvdata *ddata,
 		goto out;
 
 	/* First validate */
-	for (i = 0; i < ddata->n_buttons; i++) {
+	for (i = 0; i < ddata->pdata->nbuttons; i++) {
 		struct gpio_button_data *bdata = &ddata->data[i];
 
 		if (bdata->button->type != type)
@@ -234,7 +232,7 @@ static ssize_t gpio_keys_attr_store_helper(struct gpio_keys_drvdata *ddata,
 
 	mutex_lock(&ddata->disable_lock);
 
-	for (i = 0; i < ddata->n_buttons; i++) {
+	for (i = 0; i < ddata->pdata->nbuttons; i++) {
 		struct gpio_button_data *bdata = &ddata->data[i];
 
 		if (bdata->button->type != type)
@@ -346,6 +344,9 @@ static void gpio_keys_gpio_work_func(struct work_struct *work)
 		container_of(work, struct gpio_button_data, work);
 
 	gpio_keys_gpio_report_event(bdata);
+
+	if (bdata->button->wakeup)
+		pm_relax(bdata->input->dev.parent);
 }
 
 static void gpio_keys_gpio_timer(unsigned long _data)
@@ -361,6 +362,8 @@ static irqreturn_t gpio_keys_gpio_isr(int irq, void *dev_id)
 
 	BUG_ON(irq != bdata->irq);
 
+	if (bdata->button->wakeup)
+		pm_stay_awake(bdata->input->dev.parent);
 	if (bdata->timer_debounce)
 		mod_timer(&bdata->timer,
 			jiffies + msecs_to_jiffies(bdata->timer_debounce));
@@ -397,6 +400,9 @@ static irqreturn_t gpio_keys_irq_isr(int irq, void *dev_id)
 	spin_lock_irqsave(&bdata->lock, flags);
 
 	if (!bdata->key_pressed) {
+		if (bdata->button->wakeup)
+			pm_wakeup_event(bdata->input->dev.parent, 0);
+
 		input_event(input, EV_KEY, button->code, 1);
 		input_sync(input);
 
@@ -523,56 +529,64 @@ fail:
 static int gpio_keys_open(struct input_dev *input)
 {
 	struct gpio_keys_drvdata *ddata = input_get_drvdata(input);
+	const struct gpio_keys_platform_data *pdata = ddata->pdata;
 
-	return ddata->enable ? ddata->enable(input->dev.parent) : 0;
+	return pdata->enable ? pdata->enable(input->dev.parent) : 0;
 }
 
 static void gpio_keys_close(struct input_dev *input)
 {
 	struct gpio_keys_drvdata *ddata = input_get_drvdata(input);
+	const struct gpio_keys_platform_data *pdata = ddata->pdata;
 
-	if (ddata->disable)
-		ddata->disable(input->dev.parent);
+	if (pdata->disable)
+		pdata->disable(input->dev.parent);
 }
 
 /*
  * Handlers for alternative sources of platform_data
  */
+
 #ifdef CONFIG_OF
 /*
  * Translate OpenFirmware node properties into platform_data
  */
-static int gpio_keys_get_devtree_pdata(struct device *dev,
-			    struct gpio_keys_platform_data *pdata)
+static struct gpio_keys_platform_data * __devinit
+gpio_keys_get_devtree_pdata(struct device *dev)
 {
 	struct device_node *node, *pp;
+	struct gpio_keys_platform_data *pdata;
+	struct gpio_keys_button *button;
+	int error;
+	int nbuttons;
 	int i;
-	struct gpio_keys_button *buttons;
-	u32 reg;
 
 	node = dev->of_node;
-	if (node == NULL)
-		return -ENODEV;
-
-	memset(pdata, 0, sizeof *pdata);
+	if (!node) {
+		error = -ENODEV;
+		goto err_out;
+	}
 
-	pdata->rep = !!of_get_property(node, "autorepeat", NULL);
+	nbuttons = of_get_child_count(node);
+	if (nbuttons == 0) {
+		error = -ENODEV;
+		goto err_out;
+	}
 
-	/* First count the subnodes */
-	pp = NULL;
-	while ((pp = of_get_next_child(node, pp)))
-		pdata->nbuttons++;
+	pdata = kzalloc(sizeof(*pdata) + nbuttons * (sizeof *button),
+			GFP_KERNEL);
+	if (!pdata) {
+		error = -ENOMEM;
+		goto err_out;
+	}
 
-	if (pdata->nbuttons == 0)
-		return -ENODEV;
+	pdata->buttons = (struct gpio_keys_button *)(pdata + 1);
+	pdata->nbuttons = nbuttons;
 
-	buttons = kzalloc(pdata->nbuttons * (sizeof *buttons), GFP_KERNEL);
-	if (!buttons)
-		return -ENOMEM;
+	pdata->rep = !!of_get_property(node, "autorepeat", NULL);
 
-	pp = NULL;
 	i = 0;
-	while ((pp = of_get_next_child(node, pp))) {
+	for_each_child_of_node(node, pp) {
 		enum of_gpio_flags flags;
 
 		if (!of_find_property(pp, "gpios", NULL)) {
@@ -580,39 +594,42 @@ static int gpio_keys_get_devtree_pdata(struct device *dev,
 			dev_warn(dev, "Found button without gpios\n");
 			continue;
 		}
-		buttons[i].gpio = of_get_gpio_flags(pp, 0, &flags);
-		buttons[i].active_low = flags & OF_GPIO_ACTIVE_LOW;
 
-		if (of_property_read_u32(pp, "linux,code", &reg)) {
-			dev_err(dev, "Button without keycode: 0x%x\n", buttons[i].gpio);
-			goto out_fail;
-		}
-		buttons[i].code = reg;
+		button = &pdata->buttons[i++];
 
-		buttons[i].desc = of_get_property(pp, "label", NULL);
+		button->gpio = of_get_gpio_flags(pp, 0, &flags);
+		button->active_low = flags & OF_GPIO_ACTIVE_LOW;
 
-		if (of_property_read_u32(pp, "linux,input-type", &reg) == 0)
-			buttons[i].type = reg;
-		else
-			buttons[i].type = EV_KEY;
+		if (of_property_read_u32(pp, "linux,code", &button->code)) {
+			dev_err(dev, "Button without keycode: 0x%x\n",
+				button->gpio);
+			error = -EINVAL;
+			goto err_free_pdata;
+		}
 
-		buttons[i].wakeup = !!of_get_property(pp, "gpio-key,wakeup", NULL);
+		button->desc = of_get_property(pp, "label", NULL);
 
-		if (of_property_read_u32(pp, "debounce-interval", &reg) == 0)
-			buttons[i].debounce_interval = reg;
-		else
-			buttons[i].debounce_interval = 5;
+		if (of_property_read_u32(pp, "linux,input-type", &button->type))
+			button->type = EV_KEY;
 
-		i++;
+		button->wakeup = !!of_get_property(pp, "gpio-key,wakeup", NULL);
+
+		if (of_property_read_u32(pp, "debounce-interval",
+					 &button->debounce_interval))
+			button->debounce_interval = 5;
 	}
 
-	pdata->buttons = buttons;
+	if (pdata->nbuttons == 0) {
+		error = -EINVAL;
+		goto err_free_pdata;
+	}
 
-	return 0;
+	return pdata;
 
-out_fail:
-	kfree(buttons);
-	return -ENODEV;
+err_free_pdata:
+	kfree(pdata);
+err_out:
+	return ERR_PTR(error);
 }
 
 static struct of_device_id gpio_keys_of_match[] = {
@@ -623,14 +640,12 @@ MODULE_DEVICE_TABLE(of, gpio_keys_of_match);
 
 #else
 
-static int gpio_keys_get_devtree_pdata(struct device *dev,
-			    struct gpio_keys_platform_data *altp)
+static inline struct gpio_keys_platform_data *
+gpio_keys_get_devtree_pdata(struct device *dev)
 {
-	return -ENODEV;
+	return ERR_PTR(-ENODEV);
 }
 
-#define gpio_keys_of_match NULL
-
 #endif
 
 static void gpio_remove_key(struct gpio_button_data *bdata)
@@ -645,19 +660,17 @@ static void gpio_remove_key(struct gpio_button_data *bdata)
 
 static int __devinit gpio_keys_probe(struct platform_device *pdev)
 {
-	const struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
-	struct gpio_keys_drvdata *ddata;
 	struct device *dev = &pdev->dev;
-	struct gpio_keys_platform_data alt_pdata;
+	const struct gpio_keys_platform_data *pdata = dev_get_platdata(dev);
+	struct gpio_keys_drvdata *ddata;
 	struct input_dev *input;
 	int i, error;
 	int wakeup = 0;
 
 	if (!pdata) {
-		error = gpio_keys_get_devtree_pdata(dev, &alt_pdata);
-		if (error)
-			return error;
-		pdata = &alt_pdata;
+		pdata = gpio_keys_get_devtree_pdata(dev);
+		if (IS_ERR(pdata))
+			return PTR_ERR(pdata);
 	}
 
 	ddata = kzalloc(sizeof(struct gpio_keys_drvdata) +
@@ -670,10 +683,8 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
 		goto fail1;
 	}
 
+	ddata->pdata = pdata;
 	ddata->input = input;
-	ddata->n_buttons = pdata->nbuttons;
-	ddata->enable = pdata->enable;
-	ddata->disable = pdata->disable;
 	mutex_init(&ddata->disable_lock);
 
 	platform_set_drvdata(pdev, ddata);
@@ -742,9 +753,9 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
  fail1:
 	input_free_device(input);
 	kfree(ddata);
-	/* If we have no platform_data, we allocated buttons dynamically. */
-	if (!pdev->dev.platform_data)
-		kfree(pdata->buttons);
+	/* If we have no platform data, we allocated pdata dynamically. */
+	if (!dev_get_platdata(&pdev->dev))
+		kfree(pdata);
 
 	return error;
 }
@@ -759,18 +770,14 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev)
 
 	device_init_wakeup(&pdev->dev, 0);
 
-	for (i = 0; i < ddata->n_buttons; i++)
+	for (i = 0; i < ddata->pdata->nbuttons; i++)
 		gpio_remove_key(&ddata->data[i]);
 
 	input_unregister_device(input);
 
-	/*
-	 * If we had no platform_data, we allocated buttons dynamically, and
-	 * must free them here. ddata->data[0].button is the pointer to the
-	 * beginning of the allocated array.
-	 */
-	if (!pdev->dev.platform_data)
-		kfree(ddata->data[0].button);
+	/* If we have no platform data, we allocated pdata dynamically. */
+	if (!dev_get_platdata(&pdev->dev))
+		kfree(ddata->pdata);
 
 	kfree(ddata);
 
@@ -784,7 +791,7 @@ static int gpio_keys_suspend(struct device *dev)
 	int i;
 
 	if (device_may_wakeup(dev)) {
-		for (i = 0; i < ddata->n_buttons; i++) {
+		for (i = 0; i < ddata->pdata->nbuttons; i++) {
 			struct gpio_button_data *bdata = &ddata->data[i];
 			if (bdata->button->wakeup)
 				enable_irq_wake(bdata->irq);
@@ -799,7 +806,7 @@ static int gpio_keys_resume(struct device *dev)
 	struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev);
 	int i;
 
-	for (i = 0; i < ddata->n_buttons; i++) {
+	for (i = 0; i < ddata->pdata->nbuttons; i++) {
 		struct gpio_button_data *bdata = &ddata->data[i];
 		if (bdata->button->wakeup && device_may_wakeup(dev))
 			disable_irq_wake(bdata->irq);
@@ -822,7 +829,7 @@ static struct platform_driver gpio_keys_device_driver = {
 		.name	= "gpio-keys",
 		.owner	= THIS_MODULE,
 		.pm	= &gpio_keys_pm_ops,
-		.of_match_table = gpio_keys_of_match,
+		.of_match_table = of_match_ptr(gpio_keys_of_match),
 	}
 };
 
diff --git a/drivers/input/keyboard/gpio_keys_polled.c b/drivers/input/keyboard/gpio_keys_polled.c
index 20c8ab1..f2142de 100644
--- a/drivers/input/keyboard/gpio_keys_polled.c
+++ b/drivers/input/keyboard/gpio_keys_polled.c
@@ -25,6 +25,8 @@
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
 #include <linux/gpio_keys.h>
+#include <linux/of_platform.h>
+#include <linux/of_gpio.h>
 
 #define DRV_NAME	"gpio-keys-polled"
 
@@ -38,7 +40,7 @@ struct gpio_keys_button_data {
 struct gpio_keys_polled_dev {
 	struct input_polled_dev *poll_dev;
 	struct device *dev;
-	struct gpio_keys_platform_data *pdata;
+	const struct gpio_keys_platform_data *pdata;
 	struct gpio_keys_button_data data[0];
 };
 
@@ -67,11 +69,11 @@ static void gpio_keys_polled_check_state(struct input_dev *input,
 static void gpio_keys_polled_poll(struct input_polled_dev *dev)
 {
 	struct gpio_keys_polled_dev *bdev = dev->private;
-	struct gpio_keys_platform_data *pdata = bdev->pdata;
+	const struct gpio_keys_platform_data *pdata = bdev->pdata;
 	struct input_dev *input = dev->input;
 	int i;
 
-	for (i = 0; i < bdev->pdata->nbuttons; i++) {
+	for (i = 0; i < pdata->nbuttons; i++) {
 		struct gpio_keys_button_data *bdata = &bdev->data[i];
 
 		if (bdata->count < bdata->threshold)
@@ -85,7 +87,7 @@ static void gpio_keys_polled_poll(struct input_polled_dev *dev)
 static void gpio_keys_polled_open(struct input_polled_dev *dev)
 {
 	struct gpio_keys_polled_dev *bdev = dev->private;
-	struct gpio_keys_platform_data *pdata = bdev->pdata;
+	const struct gpio_keys_platform_data *pdata = bdev->pdata;
 
 	if (pdata->enable)
 		pdata->enable(bdev->dev);
@@ -94,31 +96,139 @@ static void gpio_keys_polled_open(struct input_polled_dev *dev)
 static void gpio_keys_polled_close(struct input_polled_dev *dev)
 {
 	struct gpio_keys_polled_dev *bdev = dev->private;
-	struct gpio_keys_platform_data *pdata = bdev->pdata;
+	const struct gpio_keys_platform_data *pdata = bdev->pdata;
 
 	if (pdata->disable)
 		pdata->disable(bdev->dev);
 }
 
+#ifdef CONFIG_OF
+static struct gpio_keys_platform_data * __devinit
+gpio_keys_polled_get_devtree_pdata(struct device *dev)
+{
+	struct device_node *node, *pp;
+	struct gpio_keys_platform_data *pdata;
+	struct gpio_keys_button *button;
+	int error;
+	int nbuttons;
+	int i;
+
+	node = dev->of_node;
+	if (!node)
+		return NULL;
+
+	nbuttons = of_get_child_count(node);
+	if (nbuttons == 0)
+		return NULL;
+
+	pdata = kzalloc(sizeof(*pdata) + nbuttons * (sizeof *button),
+			GFP_KERNEL);
+	if (!pdata) {
+		error = -ENOMEM;
+		goto err_out;
+	}
+
+	pdata->buttons = (struct gpio_keys_button *)(pdata + 1);
+	pdata->nbuttons = nbuttons;
+
+	pdata->rep = !!of_get_property(node, "autorepeat", NULL);
+	of_property_read_u32(node, "poll-interval", &pdata->poll_interval);
+
+	i = 0;
+	for_each_child_of_node(node, pp) {
+		enum of_gpio_flags flags;
+
+		if (!of_find_property(pp, "gpios", NULL)) {
+			pdata->nbuttons--;
+			dev_warn(dev, "Found button without gpios\n");
+			continue;
+		}
+
+		button = &pdata->buttons[i++];
+
+		button->gpio = of_get_gpio_flags(pp, 0, &flags);
+		button->active_low = flags & OF_GPIO_ACTIVE_LOW;
+
+		if (of_property_read_u32(pp, "linux,code", &button->code)) {
+			dev_err(dev, "Button without keycode: 0x%x\n",
+				button->gpio);
+			error = -EINVAL;
+			goto err_free_pdata;
+		}
+
+		button->desc = of_get_property(pp, "label", NULL);
+
+		if (of_property_read_u32(pp, "linux,input-type", &button->type))
+			button->type = EV_KEY;
+
+		button->wakeup = !!of_get_property(pp, "gpio-key,wakeup", NULL);
+
+		if (of_property_read_u32(pp, "debounce-interval",
+					 &button->debounce_interval))
+			button->debounce_interval = 5;
+	}
+
+	if (pdata->nbuttons == 0) {
+		error = -EINVAL;
+		goto err_free_pdata;
+	}
+
+	return pdata;
+
+err_free_pdata:
+	kfree(pdata);
+err_out:
+	return ERR_PTR(error);
+}
+
+static struct of_device_id gpio_keys_polled_of_match[] = {
+	{ .compatible = "gpio-keys-polled", },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, gpio_keys_polled_of_match);
+
+#else
+
+static inline struct gpio_keys_platform_data *
+gpio_keys_polled_get_devtree_pdata(struct device *dev)
+{
+	return NULL;
+}
+#endif
+
 static int __devinit gpio_keys_polled_probe(struct platform_device *pdev)
 {
-	struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
 	struct device *dev = &pdev->dev;
+	const struct gpio_keys_platform_data *pdata = dev_get_platdata(dev);
 	struct gpio_keys_polled_dev *bdev;
 	struct input_polled_dev *poll_dev;
 	struct input_dev *input;
 	int error;
 	int i;
 
-	if (!pdata || !pdata->poll_interval)
-		return -EINVAL;
+	if (!pdata) {
+		pdata = gpio_keys_polled_get_devtree_pdata(dev);
+		if (IS_ERR(pdata))
+			return PTR_ERR(pdata);
+		if (!pdata) {
+			dev_err(dev, "missing platform data\n");
+			return -EINVAL;
+		}
+	}
+
+	if (!pdata->poll_interval) {
+		dev_err(dev, "missing poll_interval value\n");
+		error = -EINVAL;
+		goto err_free_pdata;
+	}
 
 	bdev = kzalloc(sizeof(struct gpio_keys_polled_dev) +
 		       pdata->nbuttons * sizeof(struct gpio_keys_button_data),
 		       GFP_KERNEL);
 	if (!bdev) {
 		dev_err(dev, "no memory for private data\n");
-		return -ENOMEM;
+		error = -ENOMEM;
+		goto err_free_pdata;
 	}
 
 	poll_dev = input_allocate_polled_device();
@@ -197,7 +307,7 @@ static int __devinit gpio_keys_polled_probe(struct platform_device *pdev)
 	/* report initial state of the buttons */
 	for (i = 0; i < pdata->nbuttons; i++)
 		gpio_keys_polled_check_state(input, &pdata->buttons[i],
-					 &bdev->data[i]);
+					     &bdev->data[i]);
 
 	return 0;
 
@@ -209,15 +319,20 @@ err_free_gpio:
 
 err_free_bdev:
 	kfree(bdev);
-
 	platform_set_drvdata(pdev, NULL);
+
+err_free_pdata:
+	/* If we have no platform_data, we allocated pdata dynamically.  */
+	if (!dev_get_platdata(&pdev->dev))
+		kfree(pdata);
+
 	return error;
 }
 
 static int __devexit gpio_keys_polled_remove(struct platform_device *pdev)
 {
 	struct gpio_keys_polled_dev *bdev = platform_get_drvdata(pdev);
-	struct gpio_keys_platform_data *pdata = bdev->pdata;
+	const struct gpio_keys_platform_data *pdata = bdev->pdata;
 	int i;
 
 	input_unregister_polled_device(bdev->poll_dev);
@@ -227,6 +342,13 @@ static int __devexit gpio_keys_polled_remove(struct platform_device *pdev)
 
 	input_free_polled_device(bdev->poll_dev);
 
+	/*
+	 * If we had no platform_data, we allocated pdata dynamically and
+	 * must free it here.
+	 */
+	if (!dev_get_platdata(&pdev->dev))
+		kfree(pdata);
+
 	kfree(bdev);
 	platform_set_drvdata(pdev, NULL);
 
@@ -239,6 +361,7 @@ static struct platform_driver gpio_keys_polled_driver = {
 	.driver	= {
 		.name	= DRV_NAME,
 		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(gpio_keys_polled_of_match),
 	},
 };
 module_platform_driver(gpio_keys_polled_driver);
diff --git a/drivers/input/keyboard/nomadik-ske-keypad.c b/drivers/input/keyboard/nomadik-ske-keypad.c
index a880e74..49f5fa6 100644
--- a/drivers/input/keyboard/nomadik-ske-keypad.c
+++ b/drivers/input/keyboard/nomadik-ske-keypad.c
@@ -20,7 +20,7 @@
 #include <linux/clk.h>
 #include <linux/module.h>
 
-#include <plat/ske.h>
+#include <linux/platform_data/keypad-nomadik-ske.h>
 
 /* SKE_CR bits */
 #define SKE_KPMLT	(0x1 << 6)
diff --git a/drivers/input/keyboard/omap-keypad.c b/drivers/input/keyboard/omap-keypad.c
index a0222db..4a5fcc8 100644
--- a/drivers/input/keyboard/omap-keypad.c
+++ b/drivers/input/keyboard/omap-keypad.c
@@ -35,13 +35,9 @@
 #include <linux/mutex.h>
 #include <linux/errno.h>
 #include <linux/slab.h>
-#include <asm/gpio.h>
-#include <plat/keypad.h>
-#include <plat/menelaus.h>
-#include <asm/irq.h>
-#include <mach/hardware.h>
-#include <asm/io.h>
-#include <plat/mux.h>
+#include <linux/gpio.h>
+#include <linux/platform_data/gpio-omap.h>
+#include <linux/platform_data/keypad-omap.h>
 
 #undef NEW_BOARD_LEARNING_MODE
 
@@ -96,28 +92,8 @@ static u8 get_row_gpio_val(struct omap_kp *omap_kp)
 
 static irqreturn_t omap_kp_interrupt(int irq, void *dev_id)
 {
-	struct omap_kp *omap_kp = dev_id;
-
 	/* disable keyboard interrupt and schedule for handling */
-	if (cpu_is_omap24xx()) {
-		int i;
-
-		for (i = 0; i < omap_kp->rows; i++) {
-			int gpio_irq = gpio_to_irq(row_gpios[i]);
-			/*
-			 * The interrupt which we're currently handling should
-			 * be disabled _nosync() to avoid deadlocks waiting
-			 * for this handler to complete.  All others should
-			 * be disabled the regular way for SMP safety.
-			 */
-			if (gpio_irq == irq)
-				disable_irq_nosync(gpio_irq);
-			else
-				disable_irq(gpio_irq);
-		}
-	} else
-		/* disable keyboard interrupt and schedule for handling */
-		omap_writew(1, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);
+	omap_writew(1, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);
 
 	tasklet_schedule(&kp_tasklet);
 
@@ -133,33 +109,22 @@ static void omap_kp_scan_keypad(struct omap_kp *omap_kp, unsigned char *state)
 {
 	int col = 0;
 
-	/* read the keypad status */
-	if (cpu_is_omap24xx()) {
-		/* read the keypad status */
-		for (col = 0; col < omap_kp->cols; col++) {
-			set_col_gpio_val(omap_kp, ~(1 << col));
-			state[col] = ~(get_row_gpio_val(omap_kp)) & 0xff;
-		}
-		set_col_gpio_val(omap_kp, 0);
-
-	} else {
-		/* disable keyboard interrupt and schedule for handling */
-		omap_writew(1, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);
+	/* disable keyboard interrupt and schedule for handling */
+	omap_writew(1, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);
 
-		/* read the keypad status */
-		omap_writew(0xff, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBC);
-		for (col = 0; col < omap_kp->cols; col++) {
-			omap_writew(~(1 << col) & 0xff,
-				    OMAP1_MPUIO_BASE + OMAP_MPUIO_KBC);
+	/* read the keypad status */
+	omap_writew(0xff, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBC);
+	for (col = 0; col < omap_kp->cols; col++) {
+		omap_writew(~(1 << col) & 0xff,
+			    OMAP1_MPUIO_BASE + OMAP_MPUIO_KBC);
 
-			udelay(omap_kp->delay);
+		udelay(omap_kp->delay);
 
-			state[col] = ~omap_readw(OMAP1_MPUIO_BASE +
-						 OMAP_MPUIO_KBR_LATCH) & 0xff;
-		}
-		omap_writew(0x00, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBC);
-		udelay(2);
+		state[col] = ~omap_readw(OMAP1_MPUIO_BASE +
+					 OMAP_MPUIO_KBR_LATCH) & 0xff;
 	}
+	omap_writew(0x00, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBC);
+	udelay(2);
 }
 
 static void omap_kp_tasklet(unsigned long data)
@@ -214,7 +179,7 @@ static void omap_kp_tasklet(unsigned long data)
 	memcpy(keypad_state, new_state, sizeof(keypad_state));
 
 	if (key_down) {
-                int delay = HZ / 20;
+		int delay = HZ / 20;
 		/* some key is pressed - keep irq disabled and use timer
 		 * to poll the keypad */
 		if (spurious)
@@ -222,14 +187,8 @@ static void omap_kp_tasklet(unsigned long data)
 		mod_timer(&omap_kp_data->timer, jiffies + delay);
 	} else {
 		/* enable interrupts */
-		if (cpu_is_omap24xx()) {
-			int i;
-			for (i = 0; i < omap_kp_data->rows; i++)
-				enable_irq(gpio_to_irq(row_gpios[i]));
-		} else {
-			omap_writew(0, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);
-			kp_cur_group = -1;
-		}
+		omap_writew(0, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);
+		kp_cur_group = -1;
 	}
 }
 
@@ -242,6 +201,7 @@ static ssize_t omap_kp_enable_show(struct device *dev,
 static ssize_t omap_kp_enable_store(struct device *dev, struct device_attribute *attr,
 				    const char *buf, size_t count)
 {
+	struct omap_kp *omap_kp = dev_get_drvdata(dev);
 	int state;
 
 	if (sscanf(buf, "%u", &state) != 1)
@@ -253,9 +213,9 @@ static ssize_t omap_kp_enable_store(struct device *dev, struct device_attribute
 	mutex_lock(&kp_enable_mutex);
 	if (state != kp_enable) {
 		if (state)
-			enable_irq(INT_KEYBOARD);
+			enable_irq(omap_kp->irq);
 		else
-			disable_irq(INT_KEYBOARD);
+			disable_irq(omap_kp->irq);
 		kp_enable = state;
 	}
 	mutex_unlock(&kp_enable_mutex);
@@ -289,7 +249,7 @@ static int __devinit omap_kp_probe(struct platform_device *pdev)
 	struct omap_kp *omap_kp;
 	struct input_dev *input_dev;
 	struct omap_kp_platform_data *pdata =  pdev->dev.platform_data;
-	int i, col_idx, row_idx, irq_idx, ret;
+	int i, col_idx, row_idx, ret;
 	unsigned int row_shift, keycodemax;
 
 	if (!pdata->rows || !pdata->cols || !pdata->keymap_data) {
@@ -314,8 +274,7 @@ static int __devinit omap_kp_probe(struct platform_device *pdev)
 	omap_kp->input = input_dev;
 
 	/* Disable the interrupt for the MPUIO keyboard */
-	if (!cpu_is_omap24xx())
-		omap_writew(1, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);
+	omap_writew(1, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);
 
 	if (pdata->delay)
 		omap_kp->delay = pdata->delay;
@@ -328,31 +287,8 @@ static int __devinit omap_kp_probe(struct platform_device *pdev)
 	omap_kp->rows = pdata->rows;
 	omap_kp->cols = pdata->cols;
 
-	if (cpu_is_omap24xx()) {
-		/* Cols: outputs */
-		for (col_idx = 0; col_idx < omap_kp->cols; col_idx++) {
-			if (gpio_request(col_gpios[col_idx], "omap_kp_col") < 0) {
-				printk(KERN_ERR "Failed to request"
-				       "GPIO%d for keypad\n",
-				       col_gpios[col_idx]);
-				goto err1;
-			}
-			gpio_direction_output(col_gpios[col_idx], 0);
-		}
-		/* Rows: inputs */
-		for (row_idx = 0; row_idx < omap_kp->rows; row_idx++) {
-			if (gpio_request(row_gpios[row_idx], "omap_kp_row") < 0) {
-				printk(KERN_ERR "Failed to request"
-				       "GPIO%d for keypad\n",
-				       row_gpios[row_idx]);
-				goto err2;
-			}
-			gpio_direction_input(row_gpios[row_idx]);
-		}
-	} else {
-		col_idx = 0;
-		row_idx = 0;
-	}
+	col_idx = 0;
+	row_idx = 0;
 
 	setup_timer(&omap_kp->timer, omap_kp_timer, (unsigned long)omap_kp);
 
@@ -394,37 +330,25 @@ static int __devinit omap_kp_probe(struct platform_device *pdev)
 
 	/* scan current status and enable interrupt */
 	omap_kp_scan_keypad(omap_kp, keypad_state);
-	if (!cpu_is_omap24xx()) {
-		omap_kp->irq = platform_get_irq(pdev, 0);
-		if (omap_kp->irq >= 0) {
-			if (request_irq(omap_kp->irq, omap_kp_interrupt, 0,
-					"omap-keypad", omap_kp) < 0)
-				goto err4;
-		}
-		omap_writew(0, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);
-	} else {
-		for (irq_idx = 0; irq_idx < omap_kp->rows; irq_idx++) {
-			if (request_irq(gpio_to_irq(row_gpios[irq_idx]),
-					omap_kp_interrupt,
-					IRQF_TRIGGER_FALLING,
-					"omap-keypad", omap_kp) < 0)
-				goto err5;
-		}
+	omap_kp->irq = platform_get_irq(pdev, 0);
+	if (omap_kp->irq >= 0) {
+		if (request_irq(omap_kp->irq, omap_kp_interrupt, 0,
+				"omap-keypad", omap_kp) < 0)
+			goto err4;
 	}
+	omap_writew(0, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);
+
 	return 0;
-err5:
-	for (i = irq_idx - 1; i >=0; i--)
-		free_irq(row_gpios[i], omap_kp);
+
 err4:
 	input_unregister_device(omap_kp->input);
 	input_dev = NULL;
 err3:
 	device_remove_file(&pdev->dev, &dev_attr_enable);
 err2:
-	for (i = row_idx - 1; i >=0; i--)
+	for (i = row_idx - 1; i >= 0; i--)
 		gpio_free(row_gpios[i]);
-err1:
-	for (i = col_idx - 1; i >=0; i--)
+	for (i = col_idx - 1; i >= 0; i--)
 		gpio_free(col_gpios[i]);
 
 	kfree(omap_kp);
@@ -439,18 +363,8 @@ static int __devexit omap_kp_remove(struct platform_device *pdev)
 
 	/* disable keypad interrupt handling */
 	tasklet_disable(&kp_tasklet);
-	if (cpu_is_omap24xx()) {
-		int i;
-		for (i = 0; i < omap_kp->cols; i++)
-			gpio_free(col_gpios[i]);
-		for (i = 0; i < omap_kp->rows; i++) {
-			gpio_free(row_gpios[i]);
-			free_irq(gpio_to_irq(row_gpios[i]), omap_kp);
-		}
-	} else {
-		omap_writew(1, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);
-		free_irq(omap_kp->irq, omap_kp);
-	}
+	omap_writew(1, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);
+	free_irq(omap_kp->irq, omap_kp);
 
 	del_timer_sync(&omap_kp->timer);
 	tasklet_kill(&kp_tasklet);
diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c
index 7f7b724..803ff6f 100644
--- a/drivers/input/keyboard/pxa27x_keypad.c
+++ b/drivers/input/keyboard/pxa27x_keypad.c
@@ -32,7 +32,7 @@
 #include <asm/mach/map.h>
 
 #include <mach/hardware.h>
-#include <plat/pxa27x_keypad.h>
+#include <linux/platform_data/keypad-pxa27x.h>
 /*
  * Keypad Controller registers
  */
diff --git a/drivers/input/keyboard/pxa930_rotary.c b/drivers/input/keyboard/pxa930_rotary.c
index d7f1134..41488f9 100644
--- a/drivers/input/keyboard/pxa930_rotary.c
+++ b/drivers/input/keyboard/pxa930_rotary.c
@@ -15,7 +15,7 @@
 #include <linux/io.h>
 #include <linux/slab.h>
 
-#include <mach/pxa930_rotary.h>
+#include <linux/platform_data/keyboard-pxa930_rotary.h>
 
 #define SBCR	(0x04)
 #define ERCR	(0x0c)
diff --git a/drivers/input/keyboard/qt2160.c b/drivers/input/keyboard/qt2160.c
index e7a5e36..76b7d43 100644
--- a/drivers/input/keyboard/qt2160.c
+++ b/drivers/input/keyboard/qt2160.c
@@ -156,8 +156,7 @@ static irqreturn_t qt2160_irq(int irq, void *_qt2160)
 
 	spin_lock_irqsave(&qt2160->lock, flags);
 
-	__cancel_delayed_work(&qt2160->dwork);
-	schedule_delayed_work(&qt2160->dwork, 0);
+	mod_delayed_work(system_wq, &qt2160->dwork, 0);
 
 	spin_unlock_irqrestore(&qt2160->lock, flags);
 
diff --git a/drivers/input/keyboard/samsung-keypad.c b/drivers/input/keyboard/samsung-keypad.c
index a061ba6..277e26d 100644
--- a/drivers/input/keyboard/samsung-keypad.c
+++ b/drivers/input/keyboard/samsung-keypad.c
@@ -256,7 +256,7 @@ static struct samsung_keypad_platdata *samsung_keypad_parse_dt(
 	struct matrix_keymap_data *keymap_data;
 	uint32_t *keymap, num_rows = 0, num_cols = 0;
 	struct device_node *np = dev->of_node, *key_np;
-	unsigned int key_count = 0;
+	unsigned int key_count;
 
 	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
 	if (!pdata) {
@@ -280,9 +280,7 @@ static struct samsung_keypad_platdata *samsung_keypad_parse_dt(
 	}
 	pdata->keymap_data = keymap_data;
 
-	for_each_child_of_node(np, key_np)
-		key_count++;
-
+	key_count = of_get_child_count(np);
 	keymap_data->keymap_size = key_count;
 	keymap = devm_kzalloc(dev, sizeof(uint32_t) * key_count, GFP_KERNEL);
 	if (!keymap) {
@@ -662,8 +660,6 @@ static const struct of_device_id samsung_keypad_dt_match[] = {
 	{},
 };
 MODULE_DEVICE_TABLE(of, samsung_keypad_dt_match);
-#else
-#define samsung_keypad_dt_match NULL
 #endif
 
 static struct platform_device_id samsung_keypad_driver_ids[] = {
@@ -684,7 +680,7 @@ static struct platform_driver samsung_keypad_driver = {
 	.driver		= {
 		.name	= "samsung-keypad",
 		.owner	= THIS_MODULE,
-		.of_match_table = samsung_keypad_dt_match,
+		.of_match_table = of_match_ptr(samsung_keypad_dt_match),
 		.pm	= &samsung_keypad_pm_ops,
 	},
 	.id_table	= samsung_keypad_driver_ids,
diff --git a/drivers/input/keyboard/spear-keyboard.c b/drivers/input/keyboard/spear-keyboard.c
index 72ef01b..c7ca97f 100644
--- a/drivers/input/keyboard/spear-keyboard.c
+++ b/drivers/input/keyboard/spear-keyboard.c
@@ -24,7 +24,7 @@
 #include <linux/pm_wakeup.h>
 #include <linux/slab.h>
 #include <linux/types.h>
-#include <plat/keyboard.h>
+#include <linux/platform_data/keyboard-spear.h>
 
 /* Keyboard Registers */
 #define MODE_CTL_REG	0x00
diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c
index 2c1c9ed..5faaf25 100644
--- a/drivers/input/keyboard/tegra-kbc.c
+++ b/drivers/input/keyboard/tegra-kbc.c
@@ -29,8 +29,8 @@
 #include <linux/of.h>
 #include <linux/clk.h>
 #include <linux/slab.h>
+#include <linux/input/tegra_kbc.h>
 #include <mach/clk.h>
-#include <mach/kbc.h>
 
 #define KBC_MAX_DEBOUNCE_CNT	0x3ffu
 
diff --git a/drivers/input/keyboard/w90p910_keypad.c b/drivers/input/keyboard/w90p910_keypad.c
index 085ede4..e0f6cd1 100644
--- a/drivers/input/keyboard/w90p910_keypad.c
+++ b/drivers/input/keyboard/w90p910_keypad.c
@@ -21,7 +21,7 @@
 #include <linux/io.h>
 #include <linux/slab.h>
 
-#include <mach/w90p910_keypad.h>
+#include <linux/platform_data/keypad-w90p910.h>
 
 /* Keypad Interface Control Registers */
 #define KPI_CONF		0x00
diff --git a/drivers/input/misc/atlas_btns.c b/drivers/input/misc/atlas_btns.c
index 601f737..26f1313 100644
--- a/drivers/input/misc/atlas_btns.c
+++ b/drivers/input/misc/atlas_btns.c
@@ -151,22 +151,7 @@ static struct acpi_driver atlas_acpi_driver = {
 		.remove	= atlas_acpi_button_remove,
 	},
 };
-
-static int __init atlas_acpi_init(void)
-{
-	if (acpi_disabled)
-		return -ENODEV;
-
-	return acpi_bus_register_driver(&atlas_acpi_driver);
-}
-
-static void __exit atlas_acpi_exit(void)
-{
-	acpi_bus_unregister_driver(&atlas_acpi_driver);
-}
-
-module_init(atlas_acpi_init);
-module_exit(atlas_acpi_exit);
+module_acpi_driver(atlas_acpi_driver);
 
 MODULE_AUTHOR("Jaya Kumar");
 MODULE_LICENSE("GPL");
diff --git a/drivers/input/misc/rotary_encoder.c b/drivers/input/misc/rotary_encoder.c
index f07f784..99a49e4 100644
--- a/drivers/input/misc/rotary_encoder.c
+++ b/drivers/input/misc/rotary_encoder.c
@@ -24,12 +24,14 @@
 #include <linux/gpio.h>
 #include <linux/rotary_encoder.h>
 #include <linux/slab.h>
+#include <linux/of_platform.h>
+#include <linux/of_gpio.h>
 
 #define DRV_NAME "rotary-encoder"
 
 struct rotary_encoder {
 	struct input_dev *input;
-	struct rotary_encoder_platform_data *pdata;
+	const struct rotary_encoder_platform_data *pdata;
 
 	unsigned int axis;
 	unsigned int pos;
@@ -43,7 +45,7 @@ struct rotary_encoder {
 	char last_stable;
 };
 
-static int rotary_encoder_get_state(struct rotary_encoder_platform_data *pdata)
+static int rotary_encoder_get_state(const struct rotary_encoder_platform_data *pdata)
 {
 	int a = !!gpio_get_value(pdata->gpio_a);
 	int b = !!gpio_get_value(pdata->gpio_b);
@@ -56,7 +58,7 @@ static int rotary_encoder_get_state(struct rotary_encoder_platform_data *pdata)
 
 static void rotary_encoder_report_event(struct rotary_encoder *encoder)
 {
-	struct rotary_encoder_platform_data *pdata = encoder->pdata;
+	const struct rotary_encoder_platform_data *pdata = encoder->pdata;
 
 	if (pdata->relative_axis) {
 		input_report_rel(encoder->input,
@@ -140,36 +142,89 @@ static irqreturn_t rotary_encoder_half_period_irq(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
+#ifdef CONFIG_OF
+static struct of_device_id rotary_encoder_of_match[] = {
+	{ .compatible = "rotary-encoder", },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, rotary_encoder_of_match);
+
+static struct rotary_encoder_platform_data * __devinit
+rotary_encoder_parse_dt(struct device *dev)
+{
+	const struct of_device_id *of_id =
+				of_match_device(rotary_encoder_of_match, dev);
+	struct device_node *np = dev->of_node;
+	struct rotary_encoder_platform_data *pdata;
+	enum of_gpio_flags flags;
+
+	if (!of_id || !np)
+		return NULL;
+
+	pdata = kzalloc(sizeof(struct rotary_encoder_platform_data),
+			GFP_KERNEL);
+	if (!pdata)
+		return ERR_PTR(-ENOMEM);
+
+	of_property_read_u32(np, "rotary-encoder,steps", &pdata->steps);
+	of_property_read_u32(np, "linux,axis", &pdata->axis);
+
+	pdata->gpio_a = of_get_gpio_flags(np, 0, &flags);
+	pdata->inverted_a = flags & OF_GPIO_ACTIVE_LOW;
+
+	pdata->gpio_b = of_get_gpio_flags(np, 1, &flags);
+	pdata->inverted_b = flags & OF_GPIO_ACTIVE_LOW;
+
+	pdata->relative_axis = !!of_get_property(np,
+					"rotary-encoder,relative-axis", NULL);
+	pdata->rollover = !!of_get_property(np,
+					"rotary-encoder,rollover", NULL);
+	pdata->half_period = !!of_get_property(np,
+					"rotary-encoder,half-period", NULL);
+
+	return pdata;
+}
+#else
+static inline struct rotary_encoder_platform_data *
+rotary_encoder_parse_dt(struct device *dev)
+{
+	return NULL;
+}
+#endif
+
 static int __devinit rotary_encoder_probe(struct platform_device *pdev)
 {
-	struct rotary_encoder_platform_data *pdata = pdev->dev.platform_data;
+	struct device *dev = &pdev->dev;
+	const struct rotary_encoder_platform_data *pdata = dev_get_platdata(dev);
 	struct rotary_encoder *encoder;
 	struct input_dev *input;
 	irq_handler_t handler;
 	int err;
 
 	if (!pdata) {
-		dev_err(&pdev->dev, "missing platform data\n");
-		return -ENOENT;
+		pdata = rotary_encoder_parse_dt(dev);
+		if (IS_ERR(pdata))
+			return PTR_ERR(pdata);
+
+		if (!pdata) {
+			dev_err(dev, "missing platform data\n");
+			return -EINVAL;
+		}
 	}
 
 	encoder = kzalloc(sizeof(struct rotary_encoder), GFP_KERNEL);
 	input = input_allocate_device();
 	if (!encoder || !input) {
-		dev_err(&pdev->dev, "failed to allocate memory for device\n");
 		err = -ENOMEM;
 		goto exit_free_mem;
 	}
 
 	encoder->input = input;
 	encoder->pdata = pdata;
-	encoder->irq_a = gpio_to_irq(pdata->gpio_a);
-	encoder->irq_b = gpio_to_irq(pdata->gpio_b);
 
-	/* create and register the input driver */
 	input->name = pdev->name;
 	input->id.bustype = BUS_HOST;
-	input->dev.parent = &pdev->dev;
+	input->dev.parent = dev;
 
 	if (pdata->relative_axis) {
 		input->evbit[0] = BIT_MASK(EV_REL);
@@ -180,40 +235,21 @@ static int __devinit rotary_encoder_probe(struct platform_device *pdev)
 				     pdata->axis, 0, pdata->steps, 0, 1);
 	}
 
-	err = input_register_device(input);
-	if (err) {
-		dev_err(&pdev->dev, "failed to register input device\n");
-		goto exit_free_mem;
-	}
-
 	/* request the GPIOs */
-	err = gpio_request(pdata->gpio_a, DRV_NAME);
-	if (err) {
-		dev_err(&pdev->dev, "unable to request GPIO %d\n",
-			pdata->gpio_a);
-		goto exit_unregister_input;
-	}
-
-	err = gpio_direction_input(pdata->gpio_a);
+	err = gpio_request_one(pdata->gpio_a, GPIOF_IN, dev_name(dev));
 	if (err) {
-		dev_err(&pdev->dev, "unable to set GPIO %d for input\n",
-			pdata->gpio_a);
-		goto exit_unregister_input;
+		dev_err(dev, "unable to request GPIO %d\n", pdata->gpio_a);
+		goto exit_free_mem;
 	}
 
-	err = gpio_request(pdata->gpio_b, DRV_NAME);
+	err = gpio_request_one(pdata->gpio_b, GPIOF_IN, dev_name(dev));
 	if (err) {
-		dev_err(&pdev->dev, "unable to request GPIO %d\n",
-			pdata->gpio_b);
+		dev_err(dev, "unable to request GPIO %d\n", pdata->gpio_b);
 		goto exit_free_gpio_a;
 	}
 
-	err = gpio_direction_input(pdata->gpio_b);
-	if (err) {
-		dev_err(&pdev->dev, "unable to set GPIO %d for input\n",
-			pdata->gpio_b);
-		goto exit_free_gpio_a;
-	}
+	encoder->irq_a = gpio_to_irq(pdata->gpio_a);
+	encoder->irq_b = gpio_to_irq(pdata->gpio_b);
 
 	/* request the IRQs */
 	if (pdata->half_period) {
@@ -227,8 +263,7 @@ static int __devinit rotary_encoder_probe(struct platform_device *pdev)
 			  IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
 			  DRV_NAME, encoder);
 	if (err) {
-		dev_err(&pdev->dev, "unable to request IRQ %d\n",
-			encoder->irq_a);
+		dev_err(dev, "unable to request IRQ %d\n", encoder->irq_a);
 		goto exit_free_gpio_b;
 	}
 
@@ -236,43 +271,55 @@ static int __devinit rotary_encoder_probe(struct platform_device *pdev)
 			  IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
 			  DRV_NAME, encoder);
 	if (err) {
-		dev_err(&pdev->dev, "unable to request IRQ %d\n",
-			encoder->irq_b);
+		dev_err(dev, "unable to request IRQ %d\n", encoder->irq_b);
 		goto exit_free_irq_a;
 	}
 
+	err = input_register_device(input);
+	if (err) {
+		dev_err(dev, "failed to register input device\n");
+		goto exit_free_irq_b;
+	}
+
 	platform_set_drvdata(pdev, encoder);
 
 	return 0;
 
+exit_free_irq_b:
+	free_irq(encoder->irq_b, encoder);
 exit_free_irq_a:
 	free_irq(encoder->irq_a, encoder);
 exit_free_gpio_b:
 	gpio_free(pdata->gpio_b);
 exit_free_gpio_a:
 	gpio_free(pdata->gpio_a);
-exit_unregister_input:
-	input_unregister_device(input);
-	input = NULL; /* so we don't try to free it */
 exit_free_mem:
 	input_free_device(input);
 	kfree(encoder);
+	if (!dev_get_platdata(&pdev->dev))
+		kfree(pdata);
+
 	return err;
 }
 
 static int __devexit rotary_encoder_remove(struct platform_device *pdev)
 {
 	struct rotary_encoder *encoder = platform_get_drvdata(pdev);
-	struct rotary_encoder_platform_data *pdata = pdev->dev.platform_data;
+	const struct rotary_encoder_platform_data *pdata = encoder->pdata;
 
 	free_irq(encoder->irq_a, encoder);
 	free_irq(encoder->irq_b, encoder);
 	gpio_free(pdata->gpio_a);
 	gpio_free(pdata->gpio_b);
+
 	input_unregister_device(encoder->input);
-	platform_set_drvdata(pdev, NULL);
 	kfree(encoder);
 
+	if (!dev_get_platdata(&pdev->dev))
+		kfree(pdata);
+
+	platform_set_drvdata(pdev, NULL);
+
 	return 0;
 }
 
@@ -282,6 +329,7 @@ static struct platform_driver rotary_encoder_driver = {
 	.driver		= {
 		.name	= DRV_NAME,
 		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(rotary_encoder_of_match),
 	}
 };
 module_platform_driver(rotary_encoder_driver);
diff --git a/drivers/input/misc/twl4030-pwrbutton.c b/drivers/input/misc/twl4030-pwrbutton.c
index 38e4b50..b3dd96d 100644
--- a/drivers/input/misc/twl4030-pwrbutton.c
+++ b/drivers/input/misc/twl4030-pwrbutton.c
@@ -42,6 +42,7 @@ static irqreturn_t powerbutton_irq(int irq, void *_pwr)
 	err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &value,
 				STS_HW_CONDITIONS);
 	if (!err)  {
+		pm_wakeup_event(pwr->dev.parent, 0);
 		input_report_key(pwr, KEY_POWER, value & PWR_PWRON_IRQ);
 		input_sync(pwr);
 	} else {
diff --git a/drivers/input/misc/twl4030-vibra.c b/drivers/input/misc/twl4030-vibra.c
index fc0ed9b..2194a3c 100644
--- a/drivers/input/misc/twl4030-vibra.c
+++ b/drivers/input/misc/twl4030-vibra.c
@@ -26,6 +26,7 @@
 #include <linux/module.h>
 #include <linux/jiffies.h>
 #include <linux/platform_device.h>
+#include <linux/of.h>
 #include <linux/workqueue.h>
 #include <linux/i2c/twl.h>
 #include <linux/mfd/twl4030-audio.h>
@@ -194,13 +195,26 @@ static int twl4030_vibra_resume(struct device *dev)
 static SIMPLE_DEV_PM_OPS(twl4030_vibra_pm_ops,
 			 twl4030_vibra_suspend, twl4030_vibra_resume);
 
+static bool twl4030_vibra_check_coexist(struct twl4030_vibra_data *pdata,
+			      struct device_node *node)
+{
+	if (pdata && pdata->coexist)
+		return true;
+
+	if (of_find_node_by_name(node, "codec"))
+		return true;
+
+	return false;
+}
+
 static int __devinit twl4030_vibra_probe(struct platform_device *pdev)
 {
 	struct twl4030_vibra_data *pdata = pdev->dev.platform_data;
+	struct device_node *twl4030_core_node = pdev->dev.parent->of_node;
 	struct vibra_info *info;
 	int ret;
 
-	if (!pdata) {
+	if (!pdata && !twl4030_core_node) {
 		dev_dbg(&pdev->dev, "platform_data not available\n");
 		return -EINVAL;
 	}
@@ -210,7 +224,7 @@ static int __devinit twl4030_vibra_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	info->dev = &pdev->dev;
-	info->coexist = pdata->coexist;
+	info->coexist = twl4030_vibra_check_coexist(pdata, twl4030_core_node);
 	INIT_WORK(&info->play_work, vibra_play_work);
 
 	info->input_dev = input_allocate_device();
diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c
index 7360568..a0a4bba 100644
--- a/drivers/input/misc/uinput.c
+++ b/drivers/input/misc/uinput.c
@@ -40,7 +40,8 @@
 #include <linux/input/mt.h>
 #include "../input-compat.h"
 
-static int uinput_dev_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
+static int uinput_dev_event(struct input_dev *dev,
+			    unsigned int type, unsigned int code, int value)
 {
 	struct uinput_device	*udev = input_get_drvdata(dev);
 
@@ -56,10 +57,11 @@ static int uinput_dev_event(struct input_dev *dev, unsigned int type, unsigned i
 }
 
 /* Atomically allocate an ID for the given request. Returns 0 on success. */
-static int uinput_request_alloc_id(struct uinput_device *udev, struct uinput_request *request)
+static bool uinput_request_alloc_id(struct uinput_device *udev,
+				    struct uinput_request *request)
 {
-	int id;
-	int err = -1;
+	unsigned int id;
+	bool reserved = false;
 
 	spin_lock(&udev->requests_lock);
 
@@ -67,32 +69,35 @@ static int uinput_request_alloc_id(struct uinput_device *udev, struct uinput_req
 		if (!udev->requests[id]) {
 			request->id = id;
 			udev->requests[id] = request;
-			err = 0;
+			reserved = true;
 			break;
 		}
 	}
 
 	spin_unlock(&udev->requests_lock);
-	return err;
+	return reserved;
 }
 
-static struct uinput_request *uinput_request_find(struct uinput_device *udev, int id)
+static struct uinput_request *uinput_request_find(struct uinput_device *udev,
+						  unsigned int id)
 {
 	/* Find an input request, by ID. Returns NULL if the ID isn't valid. */
-	if (id >= UINPUT_NUM_REQUESTS || id < 0)
+	if (id >= UINPUT_NUM_REQUESTS)
 		return NULL;
 
 	return udev->requests[id];
 }
 
-static inline int uinput_request_reserve_slot(struct uinput_device *udev, struct uinput_request *request)
+static int uinput_request_reserve_slot(struct uinput_device *udev,
+				       struct uinput_request *request)
 {
 	/* Allocate slot. If none are available right away, wait. */
 	return wait_event_interruptible(udev->requests_waitq,
-					!uinput_request_alloc_id(udev, request));
+					uinput_request_alloc_id(udev, request));
 }
 
-static void uinput_request_done(struct uinput_device *udev, struct uinput_request *request)
+static void uinput_request_done(struct uinput_device *udev,
+				struct uinput_request *request)
 {
 	/* Mark slot as available */
 	udev->requests[request->id] = NULL;
@@ -101,14 +106,11 @@ static void uinput_request_done(struct uinput_device *udev, struct uinput_reques
 	complete(&request->done);
 }
 
-static int uinput_request_submit(struct uinput_device *udev, struct uinput_request *request)
+static int uinput_request_send(struct uinput_device *udev,
+			       struct uinput_request *request)
 {
 	int retval;
 
-	retval = uinput_request_reserve_slot(udev, request);
-	if (retval)
-		return retval;
-
 	retval = mutex_lock_interruptible(&udev->mutex);
 	if (retval)
 		return retval;
@@ -118,7 +120,12 @@ static int uinput_request_submit(struct uinput_device *udev, struct uinput_reque
 		goto out;
 	}
 
-	/* Tell our userspace app about this new request by queueing an input event */
+	init_completion(&request->done);
+
+	/*
+	 * Tell our userspace application about this new request
+	 * by queueing an input event.
+	 */
 	uinput_dev_event(udev->dev, EV_UINPUT, request->code, request->id);
 
  out:
@@ -126,8 +133,27 @@ static int uinput_request_submit(struct uinput_device *udev, struct uinput_reque
 	return retval;
 }
 
+static int uinput_request_submit(struct uinput_device *udev,
+				 struct uinput_request *request)
+{
+	int error;
+
+	error = uinput_request_reserve_slot(udev, request);
+	if (error)
+		return error;
+
+	error = uinput_request_send(udev, request);
+	if (error) {
+		uinput_request_done(udev, request);
+		return error;
+	}
+
+	wait_for_completion(&request->done);
+	return request->retval;
+}
+
 /*
- * Fail all ouitstanding requests so handlers don't wait for the userspace
+ * Fail all outstanding requests so handlers don't wait for the userspace
  * to finish processing them.
  */
 static void uinput_flush_requests(struct uinput_device *udev)
@@ -163,11 +189,12 @@ static int uinput_dev_playback(struct input_dev *dev, int effect_id, int value)
 	return uinput_dev_event(dev, EV_FF, effect_id, value);
 }
 
-static int uinput_dev_upload_effect(struct input_dev *dev, struct ff_effect *effect, struct ff_effect *old)
+static int uinput_dev_upload_effect(struct input_dev *dev,
+				    struct ff_effect *effect,
+				    struct ff_effect *old)
 {
 	struct uinput_device *udev = input_get_drvdata(dev);
 	struct uinput_request request;
-	int retval;
 
 	/*
 	 * uinput driver does not currently support periodic effects with
@@ -180,42 +207,25 @@ static int uinput_dev_upload_effect(struct input_dev *dev, struct ff_effect *eff
 			effect->u.periodic.waveform == FF_CUSTOM)
 		return -EINVAL;
 
-	request.id = -1;
-	init_completion(&request.done);
 	request.code = UI_FF_UPLOAD;
 	request.u.upload.effect = effect;
 	request.u.upload.old = old;
 
-	retval = uinput_request_submit(udev, &request);
-	if (!retval) {
-		wait_for_completion(&request.done);
-		retval = request.retval;
-	}
-
-	return retval;
+	return uinput_request_submit(udev, &request);
 }
 
 static int uinput_dev_erase_effect(struct input_dev *dev, int effect_id)
 {
 	struct uinput_device *udev = input_get_drvdata(dev);
 	struct uinput_request request;
-	int retval;
 
 	if (!test_bit(EV_FF, dev->evbit))
 		return -ENOSYS;
 
-	request.id = -1;
-	init_completion(&request.done);
 	request.code = UI_FF_ERASE;
 	request.u.effect_id = effect_id;
 
-	retval = uinput_request_submit(udev, &request);
-	if (!retval) {
-		wait_for_completion(&request.done);
-		retval = request.retval;
-	}
-
-	return retval;
+	return uinput_request_submit(udev, &request);
 }
 
 static void uinput_destroy_device(struct uinput_device *udev)
@@ -347,7 +357,8 @@ static int uinput_allocate_device(struct uinput_device *udev)
 	return 0;
 }
 
-static int uinput_setup_device(struct uinput_device *udev, const char __user *buffer, size_t count)
+static int uinput_setup_device(struct uinput_device *udev,
+			       const char __user *buffer, size_t count)
 {
 	struct uinput_user_dev	*user_dev;
 	struct input_dev	*dev;
@@ -405,7 +416,7 @@ static int uinput_setup_device(struct uinput_device *udev, const char __user *bu
 			goto exit;
 		if (test_bit(ABS_MT_SLOT, dev->absbit)) {
 			int nslot = input_abs_get_max(dev, ABS_MT_SLOT) + 1;
-			input_mt_init_slots(dev, nslot);
+			input_mt_init_slots(dev, nslot, 0);
 		} else if (test_bit(ABS_MT_POSITION_X, dev->absbit)) {
 			input_set_events_per_packet(dev, 60);
 		}
@@ -419,7 +430,8 @@ static int uinput_setup_device(struct uinput_device *udev, const char __user *bu
 	return retval;
 }
 
-static inline ssize_t uinput_inject_event(struct uinput_device *udev, const char __user *buffer, size_t count)
+static ssize_t uinput_inject_event(struct uinput_device *udev,
+				   const char __user *buffer, size_t count)
 {
 	struct input_event ev;
 
@@ -434,11 +446,15 @@ static inline ssize_t uinput_inject_event(struct uinput_device *udev, const char
 	return input_event_size();
 }
 
-static ssize_t uinput_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
+static ssize_t uinput_write(struct file *file, const char __user *buffer,
+			    size_t count, loff_t *ppos)
 {
 	struct uinput_device *udev = file->private_data;
 	int retval;
 
+	if (count == 0)
+		return 0;
+
 	retval = mutex_lock_interruptible(&udev->mutex);
 	if (retval)
 		return retval;
@@ -452,42 +468,74 @@ static ssize_t uinput_write(struct file *file, const char __user *buffer, size_t
 	return retval;
 }
 
-static ssize_t uinput_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
+static bool uinput_fetch_next_event(struct uinput_device *udev,
+				    struct input_event *event)
 {
-	struct uinput_device *udev = file->private_data;
-	int retval = 0;
+	bool have_event;
 
-	if (udev->state != UIST_CREATED)
-		return -ENODEV;
+	spin_lock_irq(&udev->dev->event_lock);
 
-	if (udev->head == udev->tail && (file->f_flags & O_NONBLOCK))
-		return -EAGAIN;
+	have_event = udev->head != udev->tail;
+	if (have_event) {
+		*event = udev->buff[udev->tail];
+		udev->tail = (udev->tail + 1) % UINPUT_BUFFER_SIZE;
+	}
 
-	retval = wait_event_interruptible(udev->waitq,
-			udev->head != udev->tail || udev->state != UIST_CREATED);
-	if (retval)
-		return retval;
+	spin_unlock_irq(&udev->dev->event_lock);
 
-	retval = mutex_lock_interruptible(&udev->mutex);
-	if (retval)
-		return retval;
+	return have_event;
+}
 
-	if (udev->state != UIST_CREATED) {
-		retval = -ENODEV;
-		goto out;
-	}
+static ssize_t uinput_events_to_user(struct uinput_device *udev,
+				     char __user *buffer, size_t count)
+{
+	struct input_event event;
+	size_t read = 0;
 
-	while (udev->head != udev->tail && retval + input_event_size() <= count) {
-		if (input_event_to_user(buffer + retval, &udev->buff[udev->tail])) {
-			retval = -EFAULT;
-			goto out;
-		}
-		udev->tail = (udev->tail + 1) % UINPUT_BUFFER_SIZE;
-		retval += input_event_size();
+	while (read + input_event_size() <= count &&
+	       uinput_fetch_next_event(udev, &event)) {
+
+		if (input_event_to_user(buffer + read, &event))
+			return -EFAULT;
+
+		read += input_event_size();
 	}
 
- out:
-	mutex_unlock(&udev->mutex);
+	return read;
+}
+
+static ssize_t uinput_read(struct file *file, char __user *buffer,
+			   size_t count, loff_t *ppos)
+{
+	struct uinput_device *udev = file->private_data;
+	ssize_t retval;
+
+	if (count != 0 && count < input_event_size())
+		return -EINVAL;
+
+	do {
+		retval = mutex_lock_interruptible(&udev->mutex);
+		if (retval)
+			return retval;
+
+		if (udev->state != UIST_CREATED)
+			retval = -ENODEV;
+		else if (udev->head == udev->tail &&
+			 (file->f_flags & O_NONBLOCK))
+			retval = -EAGAIN;
+		else
+			retval = uinput_events_to_user(udev, buffer, count);
+
+		mutex_unlock(&udev->mutex);
+
+		if (retval || count == 0)
+			break;
+
+		if (!(file->f_flags & O_NONBLOCK))
+			retval = wait_event_interruptible(udev->waitq,
+						  udev->head != udev->tail ||
+						  udev->state != UIST_CREATED);
+	} while (retval == 0);
 
 	return retval;
 }
@@ -516,8 +564,8 @@ static int uinput_release(struct inode *inode, struct file *file)
 
 #ifdef CONFIG_COMPAT
 struct uinput_ff_upload_compat {
-	int			request_id;
-	int			retval;
+	__u32			request_id;
+	__s32			retval;
 	struct ff_effect_compat	effect;
 	struct ff_effect_compat	old;
 };
@@ -703,7 +751,8 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd,
 				break;
 
 			req = uinput_request_find(udev, ff_up.request_id);
-			if (!req || req->code != UI_FF_UPLOAD || !req->u.upload.effect) {
+			if (!req || req->code != UI_FF_UPLOAD ||
+			    !req->u.upload.effect) {
 				retval = -EINVAL;
 				break;
 			}
@@ -786,7 +835,8 @@ static long uinput_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 }
 
 #ifdef CONFIG_COMPAT
-static long uinput_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+static long uinput_compat_ioctl(struct file *file,
+				unsigned int cmd, unsigned long arg)
 {
 	return uinput_ioctl_handler(file, cmd, arg, compat_ptr(arg));
 }
@@ -831,4 +881,3 @@ MODULE_VERSION("0.3");
 
 module_init(uinput_init);
 module_exit(uinput_exit);
-
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index 4a1347e..cf5af1f 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -1620,7 +1620,7 @@ int alps_init(struct psmouse *psmouse)
 	case ALPS_PROTO_V3:
 	case ALPS_PROTO_V4:
 		set_bit(INPUT_PROP_SEMI_MT, dev1->propbit);
-		input_mt_init_slots(dev1, 2);
+		input_mt_init_slots(dev1, 2, 0);
 		input_set_abs_params(dev1, ABS_MT_POSITION_X, 0, ALPS_V3_X_MAX, 0, 0);
 		input_set_abs_params(dev1, ABS_MT_POSITION_Y, 0, ALPS_V3_Y_MAX, 0, 0);
 
diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c
index d528c23..3a78f23 100644
--- a/drivers/input/mouse/bcm5974.c
+++ b/drivers/input/mouse/bcm5974.c
@@ -40,6 +40,7 @@
 #include <linux/usb/input.h>
 #include <linux/hid.h>
 #include <linux/mutex.h>
+#include <linux/input/mt.h>
 
 #define USB_VENDOR_ID_APPLE		0x05ac
 
@@ -183,26 +184,26 @@ struct tp_finger {
 	__le16 abs_y;		/* absolute y coodinate */
 	__le16 rel_x;		/* relative x coodinate */
 	__le16 rel_y;		/* relative y coodinate */
-	__le16 size_major;	/* finger size, major axis? */
-	__le16 size_minor;	/* finger size, minor axis? */
+	__le16 tool_major;	/* tool area, major axis */
+	__le16 tool_minor;	/* tool area, minor axis */
 	__le16 orientation;	/* 16384 when point, else 15 bit angle */
-	__le16 force_major;	/* trackpad force, major axis? */
-	__le16 force_minor;	/* trackpad force, minor axis? */
+	__le16 touch_major;	/* touch area, major axis */
+	__le16 touch_minor;	/* touch area, minor axis */
 	__le16 unused[3];	/* zeros */
 	__le16 multi;		/* one finger: varies, more fingers: constant */
 } __attribute__((packed,aligned(2)));
 
 /* trackpad finger data size, empirically at least ten fingers */
+#define MAX_FINGERS		16
 #define SIZEOF_FINGER		sizeof(struct tp_finger)
-#define SIZEOF_ALL_FINGERS	(16 * SIZEOF_FINGER)
+#define SIZEOF_ALL_FINGERS	(MAX_FINGERS * SIZEOF_FINGER)
 #define MAX_FINGER_ORIENTATION	16384
 
 /* device-specific parameters */
 struct bcm5974_param {
-	int dim;		/* logical dimension */
-	int fuzz;		/* logical noise value */
-	int devmin;		/* device minimum reading */
-	int devmax;		/* device maximum reading */
+	int snratio;		/* signal-to-noise ratio */
+	int min;		/* device minimum reading */
+	int max;		/* device maximum reading */
 };
 
 /* device-specific configuration */
@@ -219,6 +220,7 @@ struct bcm5974_config {
 	struct bcm5974_param w;	/* finger width limits */
 	struct bcm5974_param x;	/* horizontal limits */
 	struct bcm5974_param y;	/* vertical limits */
+	struct bcm5974_param o;	/* orientation limits */
 };
 
 /* logical device structure */
@@ -234,23 +236,16 @@ struct bcm5974 {
 	struct bt_data *bt_data;	/* button transferred data */
 	struct urb *tp_urb;		/* trackpad usb request block */
 	u8 *tp_data;			/* trackpad transferred data */
-	int fingers;			/* number of fingers on trackpad */
+	const struct tp_finger *index[MAX_FINGERS];	/* finger index data */
+	struct input_mt_pos pos[MAX_FINGERS];		/* position array */
+	int slots[MAX_FINGERS];				/* slot assignments */
 };
 
-/* logical dimensions */
-#define DIM_PRESSURE	256		/* maximum finger pressure */
-#define DIM_WIDTH	16		/* maximum finger width */
-#define DIM_X		1280		/* maximum trackpad x value */
-#define DIM_Y		800		/* maximum trackpad y value */
-
 /* logical signal quality */
 #define SN_PRESSURE	45		/* pressure signal-to-noise ratio */
-#define SN_WIDTH	100		/* width signal-to-noise ratio */
+#define SN_WIDTH	25		/* width signal-to-noise ratio */
 #define SN_COORD	250		/* coordinate signal-to-noise ratio */
-
-/* pressure thresholds */
-#define PRESSURE_LOW	(2 * DIM_PRESSURE / SN_PRESSURE)
-#define PRESSURE_HIGH	(3 * PRESSURE_LOW)
+#define SN_ORIENT	10		/* orientation signal-to-noise ratio */
 
 /* device constants */
 static const struct bcm5974_config bcm5974_config_table[] = {
@@ -261,10 +256,11 @@ static const struct bcm5974_config bcm5974_config_table[] = {
 		0,
 		0x84, sizeof(struct bt_data),
 		0x81, TYPE1, FINGER_TYPE1, FINGER_TYPE1 + SIZEOF_ALL_FINGERS,
-		{ DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 256 },
-		{ DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 },
-		{ DIM_X, DIM_X / SN_COORD, -4824, 5342 },
-		{ DIM_Y, DIM_Y / SN_COORD, -172, 5820 }
+		{ SN_PRESSURE, 0, 256 },
+		{ SN_WIDTH, 0, 2048 },
+		{ SN_COORD, -4824, 5342 },
+		{ SN_COORD, -172, 5820 },
+		{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
 	},
 	{
 		USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI,
@@ -273,10 +269,11 @@ static const struct bcm5974_config bcm5974_config_table[] = {
 		0,
 		0x84, sizeof(struct bt_data),
 		0x81, TYPE1, FINGER_TYPE1, FINGER_TYPE1 + SIZEOF_ALL_FINGERS,
-		{ DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 256 },
-		{ DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 },
-		{ DIM_X, DIM_X / SN_COORD, -4824, 4824 },
-		{ DIM_Y, DIM_Y / SN_COORD, -172, 4290 }
+		{ SN_PRESSURE, 0, 256 },
+		{ SN_WIDTH, 0, 2048 },
+		{ SN_COORD, -4824, 4824 },
+		{ SN_COORD, -172, 4290 },
+		{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
 	},
 	{
 		USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI,
@@ -285,10 +282,11 @@ static const struct bcm5974_config bcm5974_config_table[] = {
 		HAS_INTEGRATED_BUTTON,
 		0x84, sizeof(struct bt_data),
 		0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
-		{ DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 },
-		{ DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 },
-		{ DIM_X, DIM_X / SN_COORD, -4460, 5166 },
-		{ DIM_Y, DIM_Y / SN_COORD, -75, 6700 }
+		{ SN_PRESSURE, 0, 300 },
+		{ SN_WIDTH, 0, 2048 },
+		{ SN_COORD, -4460, 5166 },
+		{ SN_COORD, -75, 6700 },
+		{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
 	},
 	{
 		USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI,
@@ -297,10 +295,11 @@ static const struct bcm5974_config bcm5974_config_table[] = {
 		HAS_INTEGRATED_BUTTON,
 		0x84, sizeof(struct bt_data),
 		0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
-		{ DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 },
-		{ DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 },
-		{ DIM_X, DIM_X / SN_COORD, -4620, 5140 },
-		{ DIM_Y, DIM_Y / SN_COORD, -150, 6600 }
+		{ SN_PRESSURE, 0, 300 },
+		{ SN_WIDTH, 0, 2048 },
+		{ SN_COORD, -4620, 5140 },
+		{ SN_COORD, -150, 6600 },
+		{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
 	},
 	{
 		USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI,
@@ -309,10 +308,11 @@ static const struct bcm5974_config bcm5974_config_table[] = {
 		HAS_INTEGRATED_BUTTON,
 		0x84, sizeof(struct bt_data),
 		0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
-		{ DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 },
-		{ DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 },
-		{ DIM_X, DIM_X / SN_COORD, -4616, 5112 },
-		{ DIM_Y, DIM_Y / SN_COORD, -142, 5234 }
+		{ SN_PRESSURE, 0, 300 },
+		{ SN_WIDTH, 0, 2048 },
+		{ SN_COORD, -4616, 5112 },
+		{ SN_COORD, -142, 5234 },
+		{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
 	},
 	{
 		USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI,
@@ -321,10 +321,11 @@ static const struct bcm5974_config bcm5974_config_table[] = {
 		HAS_INTEGRATED_BUTTON,
 		0x84, sizeof(struct bt_data),
 		0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
-		{ DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 },
-		{ DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 },
-		{ DIM_X, DIM_X / SN_COORD, -4415, 5050 },
-		{ DIM_Y, DIM_Y / SN_COORD, -55, 6680 }
+		{ SN_PRESSURE, 0, 300 },
+		{ SN_WIDTH, 0, 2048 },
+		{ SN_COORD, -4415, 5050 },
+		{ SN_COORD, -55, 6680 },
+		{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
 	},
 	{
 		USB_DEVICE_ID_APPLE_WELLSPRING6_ANSI,
@@ -333,10 +334,11 @@ static const struct bcm5974_config bcm5974_config_table[] = {
 		HAS_INTEGRATED_BUTTON,
 		0x84, sizeof(struct bt_data),
 		0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
-		{ DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 },
-		{ DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 },
-		{ DIM_X, DIM_X / SN_COORD, -4620, 5140 },
-		{ DIM_Y, DIM_Y / SN_COORD, -150, 6600 }
+		{ SN_PRESSURE, 0, 300 },
+		{ SN_WIDTH, 0, 2048 },
+		{ SN_COORD, -4620, 5140 },
+		{ SN_COORD, -150, 6600 },
+		{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
 	},
 	{
 		USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI,
@@ -345,10 +347,11 @@ static const struct bcm5974_config bcm5974_config_table[] = {
 		HAS_INTEGRATED_BUTTON,
 		0x84, sizeof(struct bt_data),
 		0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
-		{ DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 },
-		{ DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 },
-		{ DIM_X, DIM_X / SN_COORD, -4750, 5280 },
-		{ DIM_Y, DIM_Y / SN_COORD, -150, 6730 }
+		{ SN_PRESSURE, 0, 300 },
+		{ SN_WIDTH, 0, 2048 },
+		{ SN_COORD, -4750, 5280 },
+		{ SN_COORD, -150, 6730 },
+		{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
 	},
 	{
 		USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI,
@@ -357,10 +360,11 @@ static const struct bcm5974_config bcm5974_config_table[] = {
 		HAS_INTEGRATED_BUTTON,
 		0x84, sizeof(struct bt_data),
 		0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
-		{ DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 },
-		{ DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 },
-		{ DIM_X, DIM_X / SN_COORD, -4620, 5140 },
-		{ DIM_Y, DIM_Y / SN_COORD, -150, 6600 }
+		{ SN_PRESSURE, 0, 300 },
+		{ SN_WIDTH, 0, 2048 },
+		{ SN_COORD, -4620, 5140 },
+		{ SN_COORD, -150, 6600 },
+		{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
 	},
 	{
 		USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI,
@@ -369,10 +373,11 @@ static const struct bcm5974_config bcm5974_config_table[] = {
 		HAS_INTEGRATED_BUTTON,
 		0x84, sizeof(struct bt_data),
 		0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
-		{ DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 },
-		{ DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 },
-		{ DIM_X, DIM_X / SN_COORD, -4750, 5280 },
-		{ DIM_Y, DIM_Y / SN_COORD, -150, 6730 }
+		{ SN_PRESSURE, 0, 300 },
+		{ SN_WIDTH, 0, 2048 },
+		{ SN_COORD, -4750, 5280 },
+		{ SN_COORD, -150, 6730 },
+		{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
 	},
 	{}
 };
@@ -396,18 +401,11 @@ static inline int raw2int(__le16 x)
 	return (signed short)le16_to_cpu(x);
 }
 
-/* scale device data to logical dimensions (asserts devmin < devmax) */
-static inline int int2scale(const struct bcm5974_param *p, int x)
-{
-	return x * p->dim / (p->devmax - p->devmin);
-}
-
-/* all logical value ranges are [0,dim). */
-static inline int int2bound(const struct bcm5974_param *p, int x)
+static void set_abs(struct input_dev *input, unsigned int code,
+		    const struct bcm5974_param *p)
 {
-	int s = int2scale(p, x);
-
-	return clamp_val(s, 0, p->dim - 1);
+	int fuzz = p->snratio ? (p->max - p->min) / p->snratio : 0;
+	input_set_abs_params(input, code, p->min, p->max, fuzz, 0);
 }
 
 /* setup which logical events to report */
@@ -416,48 +414,30 @@ static void setup_events_to_report(struct input_dev *input_dev,
 {
 	__set_bit(EV_ABS, input_dev->evbit);
 
-	input_set_abs_params(input_dev, ABS_PRESSURE,
-				0, cfg->p.dim, cfg->p.fuzz, 0);
-	input_set_abs_params(input_dev, ABS_TOOL_WIDTH,
-				0, cfg->w.dim, cfg->w.fuzz, 0);
-	input_set_abs_params(input_dev, ABS_X,
-				0, cfg->x.dim, cfg->x.fuzz, 0);
-	input_set_abs_params(input_dev, ABS_Y,
-				0, cfg->y.dim, cfg->y.fuzz, 0);
+	/* for synaptics only */
+	input_set_abs_params(input_dev, ABS_PRESSURE, 0, 256, 5, 0);
+	input_set_abs_params(input_dev, ABS_TOOL_WIDTH, 0, 16, 0, 0);
 
 	/* finger touch area */
-	input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
-			     cfg->w.devmin, cfg->w.devmax, 0, 0);
-	input_set_abs_params(input_dev, ABS_MT_TOUCH_MINOR,
-			     cfg->w.devmin, cfg->w.devmax, 0, 0);
+	set_abs(input_dev, ABS_MT_TOUCH_MAJOR, &cfg->w);
+	set_abs(input_dev, ABS_MT_TOUCH_MINOR, &cfg->w);
 	/* finger approach area */
-	input_set_abs_params(input_dev, ABS_MT_WIDTH_MAJOR,
-			     cfg->w.devmin, cfg->w.devmax, 0, 0);
-	input_set_abs_params(input_dev, ABS_MT_WIDTH_MINOR,
-			     cfg->w.devmin, cfg->w.devmax, 0, 0);
+	set_abs(input_dev, ABS_MT_WIDTH_MAJOR, &cfg->w);
+	set_abs(input_dev, ABS_MT_WIDTH_MINOR, &cfg->w);
 	/* finger orientation */
-	input_set_abs_params(input_dev, ABS_MT_ORIENTATION,
-			     -MAX_FINGER_ORIENTATION,
-			     MAX_FINGER_ORIENTATION, 0, 0);
+	set_abs(input_dev, ABS_MT_ORIENTATION, &cfg->o);
 	/* finger position */
-	input_set_abs_params(input_dev, ABS_MT_POSITION_X,
-			     cfg->x.devmin, cfg->x.devmax, 0, 0);
-	input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
-			     cfg->y.devmin, cfg->y.devmax, 0, 0);
+	set_abs(input_dev, ABS_MT_POSITION_X, &cfg->x);
+	set_abs(input_dev, ABS_MT_POSITION_Y, &cfg->y);
 
 	__set_bit(EV_KEY, input_dev->evbit);
-	__set_bit(BTN_TOUCH, input_dev->keybit);
-	__set_bit(BTN_TOOL_FINGER, input_dev->keybit);
-	__set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit);
-	__set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit);
-	__set_bit(BTN_TOOL_QUADTAP, input_dev->keybit);
 	__set_bit(BTN_LEFT, input_dev->keybit);
 
-	__set_bit(INPUT_PROP_POINTER, input_dev->propbit);
 	if (cfg->caps & HAS_INTEGRATED_BUTTON)
 		__set_bit(INPUT_PROP_BUTTONPAD, input_dev->propbit);
 
-	input_set_events_per_packet(input_dev, 60);
+	input_mt_init_slots(input_dev, MAX_FINGERS,
+		INPUT_MT_POINTER | INPUT_MT_DROP_UNUSED | INPUT_MT_TRACK);
 }
 
 /* report button data as logical button state */
@@ -477,24 +457,44 @@ static int report_bt_state(struct bcm5974 *dev, int size)
 	return 0;
 }
 
-static void report_finger_data(struct input_dev *input,
-			       const struct bcm5974_config *cfg,
+static void report_finger_data(struct input_dev *input, int slot,
+			       const struct input_mt_pos *pos,
 			       const struct tp_finger *f)
 {
+	input_mt_slot(input, slot);
+	input_mt_report_slot_state(input, MT_TOOL_FINGER, true);
+
 	input_report_abs(input, ABS_MT_TOUCH_MAJOR,
-			 raw2int(f->force_major) << 1);
+			 raw2int(f->touch_major) << 1);
 	input_report_abs(input, ABS_MT_TOUCH_MINOR,
-			 raw2int(f->force_minor) << 1);
+			 raw2int(f->touch_minor) << 1);
 	input_report_abs(input, ABS_MT_WIDTH_MAJOR,
-			 raw2int(f->size_major) << 1);
+			 raw2int(f->tool_major) << 1);
 	input_report_abs(input, ABS_MT_WIDTH_MINOR,
-			 raw2int(f->size_minor) << 1);
+			 raw2int(f->tool_minor) << 1);
 	input_report_abs(input, ABS_MT_ORIENTATION,
 			 MAX_FINGER_ORIENTATION - raw2int(f->orientation));
-	input_report_abs(input, ABS_MT_POSITION_X, raw2int(f->abs_x));
-	input_report_abs(input, ABS_MT_POSITION_Y,
-			 cfg->y.devmin + cfg->y.devmax - raw2int(f->abs_y));
-	input_mt_sync(input);
+	input_report_abs(input, ABS_MT_POSITION_X, pos->x);
+	input_report_abs(input, ABS_MT_POSITION_Y, pos->y);
+}
+
+static void report_synaptics_data(struct input_dev *input,
+				  const struct bcm5974_config *cfg,
+				  const struct tp_finger *f, int raw_n)
+{
+	int abs_p = 0, abs_w = 0;
+
+	if (raw_n) {
+		int p = raw2int(f->touch_major);
+		int w = raw2int(f->tool_major);
+		if (p > 0 && raw2int(f->origin)) {
+			abs_p = clamp_val(256 * p / cfg->p.max, 0, 255);
+			abs_w = clamp_val(16 * w / cfg->w.max, 0, 15);
+		}
+	}
+
+	input_report_abs(input, ABS_PRESSURE, abs_p);
+	input_report_abs(input, ABS_TOOL_WIDTH, abs_w);
 }
 
 /* report trackpad data as logical trackpad state */
@@ -503,9 +503,7 @@ static int report_tp_state(struct bcm5974 *dev, int size)
 	const struct bcm5974_config *c = &dev->cfg;
 	const struct tp_finger *f;
 	struct input_dev *input = dev->input;
-	int raw_p, raw_w, raw_x, raw_y, raw_n, i;
-	int ptest, origin, ibt = 0, nmin = 0, nmax = 0;
-	int abs_p = 0, abs_w = 0, abs_x = 0, abs_y = 0;
+	int raw_n, i, n = 0;
 
 	if (size < c->tp_offset || (size - c->tp_offset) % SIZEOF_FINGER != 0)
 		return -EIO;
@@ -514,76 +512,29 @@ static int report_tp_state(struct bcm5974 *dev, int size)
 	f = (const struct tp_finger *)(dev->tp_data + c->tp_offset);
 	raw_n = (size - c->tp_offset) / SIZEOF_FINGER;
 
-	/* always track the first finger; when detached, start over */
-	if (raw_n) {
-
-		/* report raw trackpad data */
-		for (i = 0; i < raw_n; i++)
-			report_finger_data(input, c, &f[i]);
-
-		raw_p = raw2int(f->force_major);
-		raw_w = raw2int(f->size_major);
-		raw_x = raw2int(f->abs_x);
-		raw_y = raw2int(f->abs_y);
-
-		dprintk(9,
-			"bcm5974: "
-			"raw: p: %+05d w: %+05d x: %+05d y: %+05d n: %d\n",
-			raw_p, raw_w, raw_x, raw_y, raw_n);
-
-		ptest = int2bound(&c->p, raw_p);
-		origin = raw2int(f->origin);
-
-		/* while tracking finger still valid, count all fingers */
-		if (ptest > PRESSURE_LOW && origin) {
-			abs_p = ptest;
-			abs_w = int2bound(&c->w, raw_w);
-			abs_x = int2bound(&c->x, raw_x - c->x.devmin);
-			abs_y = int2bound(&c->y, c->y.devmax - raw_y);
-			while (raw_n--) {
-				ptest = int2bound(&c->p,
-						  raw2int(f->force_major));
-				if (ptest > PRESSURE_LOW)
-					nmax++;
-				if (ptest > PRESSURE_HIGH)
-					nmin++;
-				f++;
-			}
-		}
+	for (i = 0; i < raw_n; i++) {
+		if (raw2int(f[i].touch_major) == 0)
+			continue;
+		dev->pos[n].x = raw2int(f[i].abs_x);
+		dev->pos[n].y = c->y.min + c->y.max - raw2int(f[i].abs_y);
+		dev->index[n++] = &f[i];
 	}
 
-	/* set the integrated button if applicable */
-	if (c->tp_type == TYPE2)
-		ibt = raw2int(dev->tp_data[BUTTON_TYPE2]);
-
-	if (dev->fingers < nmin)
-		dev->fingers = nmin;
-	if (dev->fingers > nmax)
-		dev->fingers = nmax;
-
-	input_report_key(input, BTN_TOUCH, dev->fingers > 0);
-	input_report_key(input, BTN_TOOL_FINGER, dev->fingers == 1);
-	input_report_key(input, BTN_TOOL_DOUBLETAP, dev->fingers == 2);
-	input_report_key(input, BTN_TOOL_TRIPLETAP, dev->fingers == 3);
-	input_report_key(input, BTN_TOOL_QUADTAP, dev->fingers > 3);
-
-	input_report_abs(input, ABS_PRESSURE, abs_p);
-	input_report_abs(input, ABS_TOOL_WIDTH, abs_w);
+	input_mt_assign_slots(input, dev->slots, dev->pos, n);
 
-	if (abs_p) {
-		input_report_abs(input, ABS_X, abs_x);
-		input_report_abs(input, ABS_Y, abs_y);
+	for (i = 0; i < n; i++)
+		report_finger_data(input, dev->slots[i],
+				   &dev->pos[i], dev->index[i]);
 
-		dprintk(8,
-			"bcm5974: abs: p: %+05d w: %+05d x: %+05d y: %+05d "
-			"nmin: %d nmax: %d n: %d ibt: %d\n", abs_p, abs_w,
-			abs_x, abs_y, nmin, nmax, dev->fingers, ibt);
+	input_mt_sync_frame(input);
 
-	}
+	report_synaptics_data(input, c, f, raw_n);
 
 	/* type 2 reports button events via ibt only */
-	if (c->tp_type == TYPE2)
+	if (c->tp_type == TYPE2) {
+		int ibt = raw2int(dev->tp_data[BUTTON_TYPE2]);
 		input_report_key(input, BTN_LEFT, ibt);
+	}
 
 	input_sync(input);
 
@@ -742,9 +693,11 @@ static int bcm5974_start_traffic(struct bcm5974 *dev)
 		goto err_out;
 	}
 
-	error = usb_submit_urb(dev->bt_urb, GFP_KERNEL);
-	if (error)
-		goto err_reset_mode;
+	if (dev->bt_urb) {
+		error = usb_submit_urb(dev->bt_urb, GFP_KERNEL);
+		if (error)
+			goto err_reset_mode;
+	}
 
 	error = usb_submit_urb(dev->tp_urb, GFP_KERNEL);
 	if (error)
@@ -868,19 +821,23 @@ static int bcm5974_probe(struct usb_interface *iface,
 	mutex_init(&dev->pm_mutex);
 
 	/* setup urbs */
-	dev->bt_urb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!dev->bt_urb)
-		goto err_free_devs;
+	if (cfg->tp_type == TYPE1) {
+		dev->bt_urb = usb_alloc_urb(0, GFP_KERNEL);
+		if (!dev->bt_urb)
+			goto err_free_devs;
+	}
 
 	dev->tp_urb = usb_alloc_urb(0, GFP_KERNEL);
 	if (!dev->tp_urb)
 		goto err_free_bt_urb;
 
-	dev->bt_data = usb_alloc_coherent(dev->udev,
+	if (dev->bt_urb) {
+		dev->bt_data = usb_alloc_coherent(dev->udev,
 					  dev->cfg.bt_datalen, GFP_KERNEL,
 					  &dev->bt_urb->transfer_dma);
-	if (!dev->bt_data)
-		goto err_free_urb;
+		if (!dev->bt_data)
+			goto err_free_urb;
+	}
 
 	dev->tp_data = usb_alloc_coherent(dev->udev,
 					  dev->cfg.tp_datalen, GFP_KERNEL,
@@ -888,10 +845,11 @@ static int bcm5974_probe(struct usb_interface *iface,
 	if (!dev->tp_data)
 		goto err_free_bt_buffer;
 
-	usb_fill_int_urb(dev->bt_urb, udev,
-			 usb_rcvintpipe(udev, cfg->bt_ep),
-			 dev->bt_data, dev->cfg.bt_datalen,
-			 bcm5974_irq_button, dev, 1);
+	if (dev->bt_urb)
+		usb_fill_int_urb(dev->bt_urb, udev,
+				 usb_rcvintpipe(udev, cfg->bt_ep),
+				 dev->bt_data, dev->cfg.bt_datalen,
+				 bcm5974_irq_button, dev, 1);
 
 	usb_fill_int_urb(dev->tp_urb, udev,
 			 usb_rcvintpipe(udev, cfg->tp_ep),
@@ -929,8 +887,9 @@ err_free_buffer:
 	usb_free_coherent(dev->udev, dev->cfg.tp_datalen,
 		dev->tp_data, dev->tp_urb->transfer_dma);
 err_free_bt_buffer:
-	usb_free_coherent(dev->udev, dev->cfg.bt_datalen,
-		dev->bt_data, dev->bt_urb->transfer_dma);
+	if (dev->bt_urb)
+		usb_free_coherent(dev->udev, dev->cfg.bt_datalen,
+				  dev->bt_data, dev->bt_urb->transfer_dma);
 err_free_urb:
 	usb_free_urb(dev->tp_urb);
 err_free_bt_urb:
@@ -951,8 +910,9 @@ static void bcm5974_disconnect(struct usb_interface *iface)
 	input_unregister_device(dev->input);
 	usb_free_coherent(dev->udev, dev->cfg.tp_datalen,
 			  dev->tp_data, dev->tp_urb->transfer_dma);
-	usb_free_coherent(dev->udev, dev->cfg.bt_datalen,
-			  dev->bt_data, dev->bt_urb->transfer_dma);
+	if (dev->bt_urb)
+		usb_free_coherent(dev->udev, dev->cfg.bt_datalen,
+				  dev->bt_data, dev->bt_urb->transfer_dma);
 	usb_free_urb(dev->tp_urb);
 	usb_free_urb(dev->bt_urb);
 	kfree(dev);
diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index 4790110..1e8e42f 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -1004,7 +1004,7 @@ static int elantech_set_input_params(struct psmouse *psmouse)
 			input_set_abs_params(dev, ABS_TOOL_WIDTH, ETP_WMIN_V2,
 					     ETP_WMAX_V2, 0, 0);
 		}
-		input_mt_init_slots(dev, 2);
+		input_mt_init_slots(dev, 2, 0);
 		input_set_abs_params(dev, ABS_MT_POSITION_X, x_min, x_max, 0, 0);
 		input_set_abs_params(dev, ABS_MT_POSITION_Y, y_min, y_max, 0, 0);
 		break;
@@ -1035,7 +1035,7 @@ static int elantech_set_input_params(struct psmouse *psmouse)
 		input_set_abs_params(dev, ABS_TOOL_WIDTH, ETP_WMIN_V2,
 				     ETP_WMAX_V2, 0, 0);
 		/* Multitouch capable pad, up to 5 fingers. */
-		input_mt_init_slots(dev, ETP_MAX_FINGERS);
+		input_mt_init_slots(dev, ETP_MAX_FINGERS, 0);
 		input_set_abs_params(dev, ABS_MT_POSITION_X, x_min, x_max, 0, 0);
 		input_set_abs_params(dev, ABS_MT_POSITION_Y, y_min, y_max, 0, 0);
 		input_abs_set_res(dev, ABS_MT_POSITION_X, x_res);
diff --git a/drivers/input/mouse/hgpk.c b/drivers/input/mouse/hgpk.c
index 575f880..62be888 100644
--- a/drivers/input/mouse/hgpk.c
+++ b/drivers/input/mouse/hgpk.c
@@ -334,11 +334,8 @@ static bool hgpk_is_byte_valid(struct psmouse *psmouse, unsigned char *packet)
 
 	if (!valid)
 		psmouse_dbg(psmouse,
-			    "bad data, mode %d (%d) %02x %02x %02x %02x %02x %02x\n",
-			    priv->mode, pktcnt,
-			    psmouse->packet[0], psmouse->packet[1],
-			    psmouse->packet[2], psmouse->packet[3],
-			    psmouse->packet[4], psmouse->packet[5]);
+			    "bad data, mode %d (%d) %*ph\n",
+			    priv->mode, pktcnt, 6, psmouse->packet);
 
 	return valid;
 }
@@ -1030,7 +1027,7 @@ static enum hgpk_model_t hgpk_get_model(struct psmouse *psmouse)
 		return -EIO;
 	}
 
-	psmouse_dbg(psmouse, "ID: %02x %02x %02x\n", param[0], param[1], param[2]);
+	psmouse_dbg(psmouse, "ID: %*ph\n", 3, param);
 
 	/* HGPK signature: 0x67, 0x00, 0x<model> */
 	if (param[0] != 0x67 || param[1] != 0x00)
diff --git a/drivers/input/mouse/pxa930_trkball.c b/drivers/input/mouse/pxa930_trkball.c
index a9e4bfd..4fe055f 100644
--- a/drivers/input/mouse/pxa930_trkball.c
+++ b/drivers/input/mouse/pxa930_trkball.c
@@ -20,7 +20,7 @@
 #include <linux/slab.h>
 
 #include <mach/hardware.h>
-#include <mach/pxa930_trkball.h>
+#include <linux/platform_data/mouse-pxa930_trkball.h>
 
 /* Trackball Controller Register Definitions */
 #define TBCR		(0x000C)
diff --git a/drivers/input/mouse/rpcmouse.c b/drivers/input/mouse/rpcmouse.c
index 272dedd..21c60fe 100644
--- a/drivers/input/mouse/rpcmouse.c
+++ b/drivers/input/mouse/rpcmouse.c
@@ -42,7 +42,7 @@ static irqreturn_t rpcmouse_irq(int irq, void *dev_id)
 
 	x = (short) iomd_readl(IOMD_MOUSEX);
 	y = (short) iomd_readl(IOMD_MOUSEY);
-	b = (short) (__raw_readl(0xe0310000) ^ 0x70);
+	b = (short) (__raw_readl(IOMEM(0xe0310000)) ^ 0x70);
 
 	dx = x - rpcmouse_lastx;
 	dy = y - rpcmouse_lasty;
diff --git a/drivers/input/mouse/sentelic.c b/drivers/input/mouse/sentelic.c
index a261d85..e582922 100644
--- a/drivers/input/mouse/sentelic.c
+++ b/drivers/input/mouse/sentelic.c
@@ -971,7 +971,7 @@ static int fsp_set_input_params(struct psmouse *psmouse)
 
 		input_set_abs_params(dev, ABS_X, 0, abs_x, 0, 0);
 		input_set_abs_params(dev, ABS_Y, 0, abs_y, 0, 0);
-		input_mt_init_slots(dev, 2);
+		input_mt_init_slots(dev, 2, 0);
 		input_set_abs_params(dev, ABS_MT_POSITION_X, 0, abs_x, 0, 0);
 		input_set_abs_params(dev, ABS_MT_POSITION_Y, 0, abs_y, 0, 0);
 	}
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
index 14eaece..37033ad 100644
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -1232,7 +1232,7 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)
 	input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0);
 
 	if (SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) {
-		input_mt_init_slots(dev, 2);
+		input_mt_init_slots(dev, 2, 0);
 		set_abs_position_params(dev, priv, ABS_MT_POSITION_X,
 					ABS_MT_POSITION_Y);
 		/* Image sensors can report per-contact pressure */
@@ -1244,7 +1244,7 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)
 	} else if (SYN_CAP_ADV_GESTURE(priv->ext_cap_0c)) {
 		/* Non-image sensors with AGM use semi-mt */
 		__set_bit(INPUT_PROP_SEMI_MT, dev->propbit);
-		input_mt_init_slots(dev, 2);
+		input_mt_init_slots(dev, 2, 0);
 		set_abs_position_params(dev, priv, ABS_MT_POSITION_X,
 					ABS_MT_POSITION_Y);
 	}
diff --git a/drivers/input/mouse/synaptics_i2c.c b/drivers/input/mouse/synaptics_i2c.c
index f1467570..063a174 100644
--- a/drivers/input/mouse/synaptics_i2c.c
+++ b/drivers/input/mouse/synaptics_i2c.c
@@ -376,12 +376,7 @@ static void synaptics_i2c_reschedule_work(struct synaptics_i2c *touch,
 
 	spin_lock_irqsave(&touch->lock, flags);
 
-	/*
-	 * If work is already scheduled then subsequent schedules will not
-	 * change the scheduled time that's why we have to cancel it first.
-	 */
-	__cancel_delayed_work(&touch->dwork);
-	schedule_delayed_work(&touch->dwork, delay);
+	mod_delayed_work(system_wq, &touch->dwork, delay);
 
 	spin_unlock_irqrestore(&touch->lock, flags);
 }
diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c
index 0110b5a..964e43d 100644
--- a/drivers/input/mousedev.c
+++ b/drivers/input/mousedev.c
@@ -551,17 +551,16 @@ static int mousedev_open(struct inode *inode, struct file *file)
 		return -ENODEV;
 
 	error = mutex_lock_interruptible(&mousedev_table_mutex);
-	if (error) {
+	if (error)
 		return error;
-	}
+
 	mousedev = mousedev_table[i];
 	if (mousedev)
 		get_device(&mousedev->dev);
 	mutex_unlock(&mousedev_table_mutex);
 
-	if (!mousedev) {
+	if (!mousedev)
 		return -ENODEV;
-	}
 
 	client = kzalloc(sizeof(struct mousedev_client), GFP_KERNEL);
 	if (!client) {
@@ -1088,7 +1087,7 @@ static int __init mousedev_init(void)
 #ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
 	error = misc_register(&psaux_mouse);
 	if (error)
-		pr_warning("could not register psaux device, error: %d\n",
+		pr_warn("could not register psaux device, error: %d\n",
 			   error);
 	else
 		psaux_registered = 1;
diff --git a/drivers/input/serio/ams_delta_serio.c b/drivers/input/serio/ams_delta_serio.c
index f5fbdf9..45887e3 100644
--- a/drivers/input/serio/ams_delta_serio.c
+++ b/drivers/input/serio/ams_delta_serio.c
@@ -27,7 +27,7 @@
 #include <linux/module.h>
 
 #include <asm/mach-types.h>
-#include <plat/board-ams-delta.h>
+#include <mach/board-ams-delta.h>
 
 #include <mach/ams-delta-fiq.h>
 
diff --git a/drivers/input/sparse-keymap.c b/drivers/input/sparse-keymap.c
index 75fb040..a70aa55 100644
--- a/drivers/input/sparse-keymap.c
+++ b/drivers/input/sparse-keymap.c
@@ -180,11 +180,11 @@ int sparse_keymap_setup(struct input_dev *dev,
 	for (e = keymap; e->type != KE_END; e++)
 		map_size++;
 
-	map = kcalloc(map_size, sizeof (struct key_entry), GFP_KERNEL);
+	map = kcalloc(map_size, sizeof(struct key_entry), GFP_KERNEL);
 	if (!map)
 		return -ENOMEM;
 
-	memcpy(map, keymap, map_size * sizeof (struct key_entry));
+	memcpy(map, keymap, map_size * sizeof(struct key_entry));
 
 	for (i = 0; i < map_size; i++) {
 		entry = &map[i];
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
index 532d067..2a81ce3 100644
--- a/drivers/input/tablet/wacom_wac.c
+++ b/drivers/input/tablet/wacom_wac.c
@@ -1530,7 +1530,7 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,
 			__set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit);
 			__set_bit(BTN_TOOL_QUADTAP, input_dev->keybit);
 
-			input_mt_init_slots(input_dev, features->touch_max);
+			input_mt_init_slots(input_dev, features->touch_max, 0);
 
 			input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
 			                     0, 255, 0, 0);
@@ -1575,7 +1575,7 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,
 
 	case TABLETPC2FG:
 		if (features->device_type == BTN_TOOL_FINGER) {
-			input_mt_init_slots(input_dev, features->touch_max);
+			input_mt_init_slots(input_dev, features->touch_max, 0);
 			input_set_abs_params(input_dev, ABS_MT_TOOL_TYPE,
 					0, MT_TOOL_MAX, 0, 0);
 			input_set_abs_params(input_dev, ABS_MT_POSITION_X,
@@ -1631,7 +1631,7 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,
 
 			__set_bit(BTN_TOOL_FINGER, input_dev->keybit);
 			__set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit);
-			input_mt_init_slots(input_dev, features->touch_max);
+			input_mt_init_slots(input_dev, features->touch_max, 0);
 
 			if (features->pktlen == WACOM_PKGLEN_BBTOUCH3) {
 				__set_bit(BTN_TOOL_TRIPLETAP,
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index 4623cc6..e92615d 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -1152,7 +1152,7 @@ static int __devinit mxt_probe(struct i2c_client *client,
 
 	/* For multi touch */
 	num_mt_slots = data->T9_reportid_max - data->T9_reportid_min + 1;
-	error = input_mt_init_slots(input_dev, num_mt_slots);
+	error = input_mt_init_slots(input_dev, num_mt_slots, 0);
 	if (error)
 		goto err_free_object;
 	input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
diff --git a/drivers/input/touchscreen/cyttsp_core.c b/drivers/input/touchscreen/cyttsp_core.c
index f030d9e..8e60437 100644
--- a/drivers/input/touchscreen/cyttsp_core.c
+++ b/drivers/input/touchscreen/cyttsp_core.c
@@ -571,7 +571,7 @@ struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops,
 	input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
 			     0, CY_MAXZ, 0, 0);
 
-	input_mt_init_slots(input_dev, CY_MAX_ID);
+	input_mt_init_slots(input_dev, CY_MAX_ID, 0);
 
 	error = request_threaded_irq(ts->irq, NULL, cyttsp_irq,
 				     IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c
index 6495777..099d144 100644
--- a/drivers/input/touchscreen/edt-ft5x06.c
+++ b/drivers/input/touchscreen/edt-ft5x06.c
@@ -782,7 +782,7 @@ static int __devinit edt_ft5x06_ts_probe(struct i2c_client *client,
 			     0, tsdata->num_x * 64 - 1, 0, 0);
 	input_set_abs_params(input, ABS_MT_POSITION_Y,
 			     0, tsdata->num_y * 64 - 1, 0, 0);
-	error = input_mt_init_slots(input, MAX_SUPPORT_POINTS);
+	error = input_mt_init_slots(input, MAX_SUPPORT_POINTS, 0);
 	if (error) {
 		dev_err(&client->dev, "Unable to init MT slots.\n");
 		goto err_free_mem;
diff --git a/drivers/input/touchscreen/egalax_ts.c b/drivers/input/touchscreen/egalax_ts.c
index 70524dd..c1e3460 100644
--- a/drivers/input/touchscreen/egalax_ts.c
+++ b/drivers/input/touchscreen/egalax_ts.c
@@ -204,7 +204,7 @@ static int __devinit egalax_ts_probe(struct i2c_client *client,
 			     ABS_MT_POSITION_X, 0, EGALAX_MAX_X, 0, 0);
 	input_set_abs_params(input_dev,
 			     ABS_MT_POSITION_X, 0, EGALAX_MAX_Y, 0, 0);
-	input_mt_init_slots(input_dev, MAX_SUPPORT_POINTS);
+	input_mt_init_slots(input_dev, MAX_SUPPORT_POINTS, 0);
 
 	input_set_drvdata(input_dev, ts);
 
diff --git a/drivers/input/touchscreen/ili210x.c b/drivers/input/touchscreen/ili210x.c
index c004417..4ac6976 100644
--- a/drivers/input/touchscreen/ili210x.c
+++ b/drivers/input/touchscreen/ili210x.c
@@ -252,7 +252,7 @@ static int __devinit ili210x_i2c_probe(struct i2c_client *client,
 	input_set_abs_params(input, ABS_Y, 0, ymax, 0, 0);
 
 	/* Multi touch */
-	input_mt_init_slots(input, MAX_TOUCHES);
+	input_mt_init_slots(input, MAX_TOUCHES, 0);
 	input_set_abs_params(input, ABS_MT_POSITION_X, 0, xmax, 0, 0);
 	input_set_abs_params(input, ABS_MT_POSITION_Y, 0, ymax, 0, 0);
 
diff --git a/drivers/input/touchscreen/mms114.c b/drivers/input/touchscreen/mms114.c
index 49c44bb..560cf09 100644
--- a/drivers/input/touchscreen/mms114.c
+++ b/drivers/input/touchscreen/mms114.c
@@ -404,7 +404,7 @@ static int __devinit mms114_probe(struct i2c_client *client,
 	input_set_abs_params(input_dev, ABS_Y, 0, data->pdata->y_size, 0, 0);
 
 	/* For multi touch */
-	input_mt_init_slots(input_dev, MMS114_MAX_TOUCH);
+	input_mt_init_slots(input_dev, MMS114_MAX_TOUCH, 0);
 	input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
 			     0, MMS114_MAX_AREA, 0, 0);
 	input_set_abs_params(input_dev, ABS_MT_POSITION_X,
diff --git a/drivers/input/touchscreen/penmount.c b/drivers/input/touchscreen/penmount.c
index 4ccde45..b49f0b8 100644
--- a/drivers/input/touchscreen/penmount.c
+++ b/drivers/input/touchscreen/penmount.c
@@ -264,7 +264,7 @@ static int pm_connect(struct serio *serio, struct serio_driver *drv)
 	input_set_abs_params(pm->dev, ABS_Y, 0, max_y, 0, 0);
 
 	if (pm->maxcontacts > 1) {
-		input_mt_init_slots(pm->dev, pm->maxcontacts);
+		input_mt_init_slots(pm->dev, pm->maxcontacts, 0);
 		input_set_abs_params(pm->dev,
 				     ABS_MT_POSITION_X, 0, max_x, 0, 0);
 		input_set_abs_params(pm->dev,
diff --git a/drivers/input/touchscreen/s3c2410_ts.c b/drivers/input/touchscreen/s3c2410_ts.c
index bf1a064..549fa29 100644
--- a/drivers/input/touchscreen/s3c2410_ts.c
+++ b/drivers/input/touchscreen/s3c2410_ts.c
@@ -37,7 +37,7 @@
 
 #include <plat/adc.h>
 #include <plat/regs-adc.h>
-#include <plat/ts.h>
+#include <linux/platform_data/touchscreen-s3c2410.h>
 
 #define TSC_SLEEP  (S3C2410_ADCTSC_PULL_UP_DISABLE | S3C2410_ADCTSC_XY_PST(0))
 
@@ -406,7 +406,7 @@ static int s3c2410ts_resume(struct device *dev)
 	return 0;
 }
 
-static struct dev_pm_ops s3c_ts_pmops = {
+static const struct dev_pm_ops s3c_ts_pmops = {
 	.suspend	= s3c2410ts_suspend,
 	.resume		= s3c2410ts_resume,
 };
diff --git a/drivers/input/touchscreen/wacom_w8001.c b/drivers/input/touchscreen/wacom_w8001.c
index 8f9ad2f..9a83be6 100644
--- a/drivers/input/touchscreen/wacom_w8001.c
+++ b/drivers/input/touchscreen/wacom_w8001.c
@@ -471,7 +471,7 @@ static int w8001_setup(struct w8001 *w8001)
 		case 5:
 			w8001->pktlen = W8001_PKTLEN_TOUCH2FG;
 
-			input_mt_init_slots(dev, 2);
+			input_mt_init_slots(dev, 2, 0);
 			input_set_abs_params(dev, ABS_MT_POSITION_X,
 						0, touch.x, 0, 0);
 			input_set_abs_params(dev, ABS_MT_POSITION_Y,
diff --git a/drivers/input/touchscreen/wm831x-ts.c b/drivers/input/touchscreen/wm831x-ts.c
index e834107..52abb98 100644
--- a/drivers/input/touchscreen/wm831x-ts.c
+++ b/drivers/input/touchscreen/wm831x-ts.c
@@ -221,7 +221,7 @@ static void wm831x_ts_input_close(struct input_dev *idev)
 	synchronize_irq(wm831x_ts->pd_irq);
 
 	/* Make sure the IRQ completion work is quiesced */
-	flush_work_sync(&wm831x_ts->pd_data_work);
+	flush_work(&wm831x_ts->pd_data_work);
 
 	/* If we ended up with the pen down then make sure we revert back
 	 * to pen detection state for the next time we start up.
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index b64502d..450b258 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -684,7 +684,7 @@ static void iommu_poll_ppr_log(struct amd_iommu *iommu)
 
 		/*
 		 * Release iommu->lock because ppr-handling might need to
-		 * re-aquire it
+		 * re-acquire it
 		 */
 		spin_unlock_irqrestore(&iommu->lock, flags);
 
@@ -802,7 +802,7 @@ static void build_inv_iommu_pages(struct iommu_cmd *cmd, u64 address,
 	CMD_SET_TYPE(cmd, CMD_INV_IOMMU_PAGES);
 	if (s) /* size bit - we flush more than one 4kb page */
 		cmd->data[2] |= CMD_INV_IOMMU_PAGES_SIZE_MASK;
-	if (pde) /* PDE bit - we wan't flush everything not only the PTEs */
+	if (pde) /* PDE bit - we want to flush everything, not only the PTEs */
 		cmd->data[2] |= CMD_INV_IOMMU_PAGES_PDE_MASK;
 }
 
@@ -2153,7 +2153,7 @@ static bool pci_pri_tlp_required(struct pci_dev *pdev)
 }
 
 /*
- * If a device is not yet associated with a domain, this function does
+ * If a device is not yet associated with a domain, this function
  * assigns it visible for the hardware
  */
 static int attach_device(struct device *dev,
@@ -2403,7 +2403,7 @@ static struct protection_domain *get_domain(struct device *dev)
 	if (domain != NULL)
 		return domain;
 
-	/* Device not bount yet - bind it */
+	/* Device not bound yet - bind it */
 	dma_dom = find_protection_domain(devid);
 	if (!dma_dom)
 		dma_dom = amd_iommu_rlookup_table[devid]->default_dom;
@@ -2942,7 +2942,7 @@ static void __init prealloc_protection_domains(void)
 			alloc_passthrough_domain();
 			dev_data->passthrough = true;
 			attach_device(&dev->dev, pt_domain);
-			pr_info("AMD-Vi: Using passthough domain for device %s\n",
+			pr_info("AMD-Vi: Using passthrough domain for device %s\n",
 				dev_name(&dev->dev));
 		}
 
diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c
index 18a89b7..577669f 100644
--- a/drivers/iommu/amd_iommu_init.c
+++ b/drivers/iommu/amd_iommu_init.c
@@ -26,7 +26,6 @@
 #include <linux/msi.h>
 #include <linux/amd-iommu.h>
 #include <linux/export.h>
-#include <linux/acpi.h>
 #include <acpi/acpi.h>
 #include <asm/pci-direct.h>
 #include <asm/iommu.h>
@@ -178,7 +177,7 @@ u16 *amd_iommu_alias_table;
 struct amd_iommu **amd_iommu_rlookup_table;
 
 /*
- * AMD IOMMU allows up to 2^16 differend protection domains. This is a bitmap
+ * AMD IOMMU allows up to 2^16 different protection domains. This is a bitmap
  * to know which ones are already in use.
  */
 unsigned long *amd_iommu_pd_alloc_bitmap;
@@ -478,7 +477,7 @@ static int __init find_last_devid_acpi(struct acpi_table_header *table)
 
 /****************************************************************************
  *
- * The following functions belong the the code path which parses the ACPI table
+ * The following functions belong to the code path which parses the ACPI table
  * the second time. In this ACPI parsing iteration we allocate IOMMU specific
  * data structures, initialize the device/alias/rlookup table and also
  * basically initialize the hardware.
@@ -691,7 +690,7 @@ static void __init set_dev_entry_from_acpi(struct amd_iommu *iommu,
 }
 
 /*
- * Reads the device exclusion range from ACPI and initialize IOMMU with
+ * Reads the device exclusion range from ACPI and initializes the IOMMU with
  * it
  */
 static void __init set_device_exclusion_range(u16 devid, struct ivmd_header *m)
@@ -1141,7 +1140,7 @@ static int __init amd_iommu_init_pci(void)
 /****************************************************************************
  *
  * The following functions initialize the MSI interrupts for all IOMMUs
- * in the system. Its a bit challenging because there could be multiple
+ * in the system. It's a bit challenging because there could be multiple
  * IOMMUs per PCI BDF but we can call pci_enable_msi(x) only once per
  * pci_dev.
  *
@@ -1199,7 +1198,7 @@ enable_faults:
  *
  * The next functions belong to the third pass of parsing the ACPI
  * table. In this last pass the memory mapping requirements are
- * gathered (like exclusion and unity mapping reanges).
+ * gathered (like exclusion and unity mapping ranges).
  *
  ****************************************************************************/
 
diff --git a/drivers/iommu/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h
index d0dab86..d1390b8 100644
--- a/drivers/iommu/amd_iommu_types.h
+++ b/drivers/iommu/amd_iommu_types.h
@@ -255,7 +255,7 @@
 #define PAGE_SIZE_ALIGN(address, pagesize) \
 		((address) & ~((pagesize) - 1))
 /*
- * Creates an IOMMU PTE for an address an a given pagesize
+ * Creates an IOMMU PTE for an address and a given pagesize
  * The PTE has no permission bits set
  * Pagesize is expected to be a power-of-two larger than 4096
  */
@@ -404,7 +404,7 @@ struct iommu_dev_data {
 	struct list_head dev_data_list;	  /* For global dev_data_list */
 	struct iommu_dev_data *alias_data;/* The alias dev_data */
 	struct protection_domain *domain; /* Domain the device is bound to */
-	atomic_t bind;			  /* Domain attach reverent count */
+	atomic_t bind;			  /* Domain attach reference count */
 	u16 devid;			  /* PCI Device ID */
 	bool iommu_v2;			  /* Device can make use of IOMMUv2 */
 	bool passthrough;		  /* Default for device is pt_domain */
diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index 80bad32..7fe44f8 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -840,8 +840,7 @@ static void exynos_iommu_detach_device(struct iommu_domain *domain,
 	if (__exynos_sysmmu_disable(data)) {
 		dev_dbg(dev, "%s: Detached IOMMU with pgtable %#lx\n",
 					__func__, __pa(priv->pgtable));
-		list_del(&data->node);
-		INIT_LIST_HEAD(&data->node);
+		list_del_init(&data->node);
 
 	} else {
 		dev_dbg(dev, "%s: Detaching IOMMU with pgtable %#lx delayed",
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 2297ec1..d4a4cd4 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -589,7 +589,9 @@ static void domain_update_iommu_coherency(struct dmar_domain *domain)
 {
 	int i;
 
-	domain->iommu_coherency = 1;
+	i = find_first_bit(domain->iommu_bmp, g_num_of_iommus);
+
+	domain->iommu_coherency = i < g_num_of_iommus ? 1 : 0;
 
 	for_each_set_bit(i, domain->iommu_bmp, g_num_of_iommus) {
 		if (!ecap_coherent(g_iommus[i]->ecap)) {
@@ -2351,7 +2353,7 @@ static int iommu_should_identity_map(struct pci_dev *pdev, int startup)
 			return 0;
 		if (pdev->class >> 8 == PCI_CLASS_BRIDGE_PCI)
 			return 0;
-	} else if (pdev->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE)
+	} else if (pci_pcie_type(pdev) == PCI_EXP_TYPE_PCI_BRIDGE)
 		return 0;
 
 	/* 
@@ -3546,10 +3548,10 @@ found:
 		struct pci_dev *bridge = bus->self;
 
 		if (!bridge || !pci_is_pcie(bridge) ||
-		    bridge->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE)
+		    pci_pcie_type(bridge) == PCI_EXP_TYPE_PCI_BRIDGE)
 			return 0;
 
-		if (bridge->pcie_type == PCI_EXP_TYPE_ROOT_PORT) {
+		if (pci_pcie_type(bridge) == PCI_EXP_TYPE_ROOT_PORT) {
 			for (i = 0; i < atsru->devices_cnt; i++)
 				if (atsru->devices[i] == bridge)
 					return 1;
diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c
index 2a4bb36..0b4d62e 100644
--- a/drivers/iommu/tegra-smmu.c
+++ b/drivers/iommu/tegra-smmu.c
@@ -32,14 +32,55 @@
 #include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_iommu.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
 
 #include <asm/page.h>
 #include <asm/cacheflush.h>
 
 #include <mach/iomap.h>
-#include <mach/smmu.h>
 #include <mach/tegra-ahb.h>
 
+enum smmu_hwgrp {
+	HWGRP_AFI,
+	HWGRP_AVPC,
+	HWGRP_DC,
+	HWGRP_DCB,
+	HWGRP_EPP,
+	HWGRP_G2,
+	HWGRP_HC,
+	HWGRP_HDA,
+	HWGRP_ISP,
+	HWGRP_MPE,
+	HWGRP_NV,
+	HWGRP_NV2,
+	HWGRP_PPCS,
+	HWGRP_SATA,
+	HWGRP_VDE,
+	HWGRP_VI,
+
+	HWGRP_COUNT,
+
+	HWGRP_END = ~0,
+};
+
+#define HWG_AFI		(1 << HWGRP_AFI)
+#define HWG_AVPC	(1 << HWGRP_AVPC)
+#define HWG_DC		(1 << HWGRP_DC)
+#define HWG_DCB		(1 << HWGRP_DCB)
+#define HWG_EPP		(1 << HWGRP_EPP)
+#define HWG_G2		(1 << HWGRP_G2)
+#define HWG_HC		(1 << HWGRP_HC)
+#define HWG_HDA		(1 << HWGRP_HDA)
+#define HWG_ISP		(1 << HWGRP_ISP)
+#define HWG_MPE		(1 << HWGRP_MPE)
+#define HWG_NV		(1 << HWGRP_NV)
+#define HWG_NV2		(1 << HWGRP_NV2)
+#define HWG_PPCS	(1 << HWGRP_PPCS)
+#define HWG_SATA	(1 << HWGRP_SATA)
+#define HWG_VDE		(1 << HWGRP_VDE)
+#define HWG_VI		(1 << HWGRP_VI)
+
 /* bitmap of the page sizes currently supported */
 #define SMMU_IOMMU_PGSIZES	(SZ_4K)
 
@@ -47,16 +88,29 @@
 #define SMMU_CONFIG_DISABLE			0
 #define SMMU_CONFIG_ENABLE			1
 
-#define SMMU_TLB_CONFIG				0x14
-#define SMMU_TLB_CONFIG_STATS__MASK		(1 << 31)
-#define SMMU_TLB_CONFIG_STATS__ENABLE		(1 << 31)
+/* REVISIT: To support multiple MCs */
+enum {
+	_MC = 0,
+};
+
+enum {
+	_TLB = 0,
+	_PTC,
+};
+
+#define SMMU_CACHE_CONFIG_BASE			0x14
+#define __SMMU_CACHE_CONFIG(mc, cache)		(SMMU_CACHE_CONFIG_BASE + 4 * cache)
+#define SMMU_CACHE_CONFIG(cache)		__SMMU_CACHE_CONFIG(_MC, cache)
+
+#define SMMU_CACHE_CONFIG_STATS_SHIFT		31
+#define SMMU_CACHE_CONFIG_STATS_ENABLE		(1 << SMMU_CACHE_CONFIG_STATS_SHIFT)
+#define SMMU_CACHE_CONFIG_STATS_TEST_SHIFT	30
+#define SMMU_CACHE_CONFIG_STATS_TEST		(1 << SMMU_CACHE_CONFIG_STATS_TEST_SHIFT)
+
 #define SMMU_TLB_CONFIG_HIT_UNDER_MISS__ENABLE	(1 << 29)
 #define SMMU_TLB_CONFIG_ACTIVE_LINES__VALUE	0x10
 #define SMMU_TLB_CONFIG_RESET_VAL		0x20000010
 
-#define SMMU_PTC_CONFIG				0x18
-#define SMMU_PTC_CONFIG_STATS__MASK		(1 << 31)
-#define SMMU_PTC_CONFIG_STATS__ENABLE		(1 << 31)
 #define SMMU_PTC_CONFIG_CACHE__ENABLE		(1 << 29)
 #define SMMU_PTC_CONFIG_INDEX_MAP__PATTERN	0x3f
 #define SMMU_PTC_CONFIG_RESET_VAL		0x2000003f
@@ -86,10 +140,10 @@
 
 #define SMMU_ASID_SECURITY			0x38
 
-#define SMMU_STATS_TLB_HIT_COUNT		0x1f0
-#define SMMU_STATS_TLB_MISS_COUNT		0x1f4
-#define SMMU_STATS_PTC_HIT_COUNT		0x1f8
-#define SMMU_STATS_PTC_MISS_COUNT		0x1fc
+#define SMMU_STATS_CACHE_COUNT_BASE		0x1f0
+
+#define SMMU_STATS_CACHE_COUNT(mc, cache, hitmiss)		\
+	(SMMU_STATS_CACHE_COUNT_BASE + 8 * cache + 4 * hitmiss)
 
 #define SMMU_TRANSLATION_ENABLE_0		0x228
 #define SMMU_TRANSLATION_ENABLE_1		0x22c
@@ -231,6 +285,12 @@ struct smmu_as {
 	spinlock_t		client_lock; /* for client list */
 };
 
+struct smmu_debugfs_info {
+	struct smmu_device *smmu;
+	int mc;
+	int cache;
+};
+
 /*
  * Per SMMU device - IOMMU device
  */
@@ -251,6 +311,9 @@ struct smmu_device {
 	unsigned long translation_enable_2;
 	unsigned long asid_security;
 
+	struct dentry *debugfs_root;
+	struct smmu_debugfs_info *debugfs_info;
+
 	struct device_node *ahb;
 
 	int		num_as;
@@ -412,8 +475,8 @@ static int smmu_setup_regs(struct smmu_device *smmu)
 	smmu_write(smmu, smmu->translation_enable_1, SMMU_TRANSLATION_ENABLE_1);
 	smmu_write(smmu, smmu->translation_enable_2, SMMU_TRANSLATION_ENABLE_2);
 	smmu_write(smmu, smmu->asid_security, SMMU_ASID_SECURITY);
-	smmu_write(smmu, SMMU_TLB_CONFIG_RESET_VAL, SMMU_TLB_CONFIG);
-	smmu_write(smmu, SMMU_PTC_CONFIG_RESET_VAL, SMMU_PTC_CONFIG);
+	smmu_write(smmu, SMMU_TLB_CONFIG_RESET_VAL, SMMU_CACHE_CONFIG(_TLB));
+	smmu_write(smmu, SMMU_PTC_CONFIG_RESET_VAL, SMMU_CACHE_CONFIG(_PTC));
 
 	smmu_flush_regs(smmu, 1);
 
@@ -895,6 +958,175 @@ static struct iommu_ops smmu_iommu_ops = {
 	.pgsize_bitmap	= SMMU_IOMMU_PGSIZES,
 };
 
+/* Should be in the order of enum */
+static const char * const smmu_debugfs_mc[] = { "mc", };
+static const char * const smmu_debugfs_cache[] = {  "tlb", "ptc", };
+
+static ssize_t smmu_debugfs_stats_write(struct file *file,
+					const char __user *buffer,
+					size_t count, loff_t *pos)
+{
+	struct smmu_debugfs_info *info;
+	struct smmu_device *smmu;
+	struct dentry *dent;
+	int i;
+	enum {
+		_OFF = 0,
+		_ON,
+		_RESET,
+	};
+	const char * const command[] = {
+		[_OFF]		= "off",
+		[_ON]		= "on",
+		[_RESET]	= "reset",
+	};
+	char str[] = "reset";
+	u32 val;
+	size_t offs;
+
+	count = min_t(size_t, count, sizeof(str));
+	if (copy_from_user(str, buffer, count))
+		return -EINVAL;
+
+	for (i = 0; i < ARRAY_SIZE(command); i++)
+		if (strncmp(str, command[i],
+			    strlen(command[i])) == 0)
+			break;
+
+	if (i == ARRAY_SIZE(command))
+		return -EINVAL;
+
+	dent = file->f_dentry;
+	info = dent->d_inode->i_private;
+	smmu = info->smmu;
+
+	offs = SMMU_CACHE_CONFIG(info->cache);
+	val = smmu_read(smmu, offs);
+	switch (i) {
+	case _OFF:
+		val &= ~SMMU_CACHE_CONFIG_STATS_ENABLE;
+		val &= ~SMMU_CACHE_CONFIG_STATS_TEST;
+		smmu_write(smmu, val, offs);
+		break;
+	case _ON:
+		val |= SMMU_CACHE_CONFIG_STATS_ENABLE;
+		val &= ~SMMU_CACHE_CONFIG_STATS_TEST;
+		smmu_write(smmu, val, offs);
+		break;
+	case _RESET:
+		val |= SMMU_CACHE_CONFIG_STATS_TEST;
+		smmu_write(smmu, val, offs);
+		val &= ~SMMU_CACHE_CONFIG_STATS_TEST;
+		smmu_write(smmu, val, offs);
+		break;
+	default:
+		BUG();
+		break;
+	}
+
+	dev_dbg(smmu->dev, "%s() %08x, %08x @%08x\n", __func__,
+		val, smmu_read(smmu, offs), offs);
+
+	return count;
+}
+
+static int smmu_debugfs_stats_show(struct seq_file *s, void *v)
+{
+	struct smmu_debugfs_info *info;
+	struct smmu_device *smmu;
+	struct dentry *dent;
+	int i;
+	const char * const stats[] = { "hit", "miss", };
+
+	dent = d_find_alias(s->private);
+	info = dent->d_inode->i_private;
+	smmu = info->smmu;
+
+	for (i = 0; i < ARRAY_SIZE(stats); i++) {
+		u32 val;
+		size_t offs;
+
+		offs = SMMU_STATS_CACHE_COUNT(info->mc, info->cache, i);
+		val = smmu_read(smmu, offs);
+		seq_printf(s, "%s:%08x ", stats[i], val);
+
+		dev_dbg(smmu->dev, "%s() %s %08x @%08x\n", __func__,
+			stats[i], val, offs);
+	}
+	seq_printf(s, "\n");
+
+	return 0;
+}
+
+static int smmu_debugfs_stats_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, smmu_debugfs_stats_show, inode);
+}
+
+static const struct file_operations smmu_debugfs_stats_fops = {
+	.open		= smmu_debugfs_stats_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+	.write		= smmu_debugfs_stats_write,
+};
+
+static void smmu_debugfs_delete(struct smmu_device *smmu)
+{
+	debugfs_remove_recursive(smmu->debugfs_root);
+	kfree(smmu->debugfs_info);
+}
+
+static void smmu_debugfs_create(struct smmu_device *smmu)
+{
+	int i;
+	size_t bytes;
+	struct dentry *root;
+
+	bytes = ARRAY_SIZE(smmu_debugfs_mc) * ARRAY_SIZE(smmu_debugfs_cache) *
+		sizeof(*smmu->debugfs_info);
+	smmu->debugfs_info = kmalloc(bytes, GFP_KERNEL);
+	if (!smmu->debugfs_info)
+		return;
+
+	root = debugfs_create_dir(dev_name(smmu->dev), NULL);
+	if (!root)
+		goto err_out;
+	smmu->debugfs_root = root;
+
+	for (i = 0; i < ARRAY_SIZE(smmu_debugfs_mc); i++) {
+		int j;
+		struct dentry *mc;
+
+		mc = debugfs_create_dir(smmu_debugfs_mc[i], root);
+		if (!mc)
+			goto err_out;
+
+		for (j = 0; j < ARRAY_SIZE(smmu_debugfs_cache); j++) {
+			struct dentry *cache;
+			struct smmu_debugfs_info *info;
+
+			info = smmu->debugfs_info;
+			info += i * ARRAY_SIZE(smmu_debugfs_mc) + j;
+			info->smmu = smmu;
+			info->mc = i;
+			info->cache = j;
+
+			cache = debugfs_create_file(smmu_debugfs_cache[j],
+						    S_IWUGO | S_IRUGO, mc,
+						    (void *)info,
+						    &smmu_debugfs_stats_fops);
+			if (!cache)
+				goto err_out;
+		}
+	}
+
+	return;
+
+err_out:
+	smmu_debugfs_delete(smmu);
+}
+
 static int tegra_smmu_suspend(struct device *dev)
 {
 	struct smmu_device *smmu = dev_get_drvdata(dev);
@@ -999,6 +1231,7 @@ static int tegra_smmu_probe(struct platform_device *pdev)
 	if (!smmu->avp_vector_page)
 		return -ENOMEM;
 
+	smmu_debugfs_create(smmu);
 	smmu_handle = smmu;
 	return 0;
 }
@@ -1008,6 +1241,8 @@ static int tegra_smmu_remove(struct platform_device *pdev)
 	struct smmu_device *smmu = platform_get_drvdata(pdev);
 	int i;
 
+	smmu_debugfs_delete(smmu);
+
 	smmu_write(smmu, SMMU_CONFIG_DISABLE, SMMU_CONFIG);
 	for (i = 0; i < smmu->num_as; i++)
 		free_pdir(&smmu->as[i]);
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
new file mode 100644
index 0000000..1bb8bf6
--- /dev/null
+++ b/drivers/irqchip/Kconfig
@@ -0,0 +1 @@
+# empty
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
new file mode 100644
index 0000000..054321d
--- /dev/null
+++ b/drivers/irqchip/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2835.o
diff --git a/drivers/irqchip/irq-bcm2835.c b/drivers/irqchip/irq-bcm2835.c
new file mode 100644
index 0000000..dc670cc
--- /dev/null
+++ b/drivers/irqchip/irq-bcm2835.c
@@ -0,0 +1,223 @@
+/*
+ * Copyright 2010 Broadcom
+ * Copyright 2012 Simon Arlott, Chris Boot, Stephen Warren
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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.
+ *
+ * Quirk 1: Shortcut interrupts don't set the bank 1/2 register pending bits
+ *
+ * If an interrupt fires on bank 1 that isn't in the shortcuts list, bit 8
+ * on bank 0 is set to signify that an interrupt in bank 1 has fired, and
+ * to look in the bank 1 status register for more information.
+ *
+ * If an interrupt fires on bank 1 that _is_ in the shortcuts list, its
+ * shortcut bit in bank 0 is set as well as its interrupt bit in the bank 1
+ * status register, but bank 0 bit 8 is _not_ set.
+ *
+ * Quirk 2: You can't mask the register 1/2 pending interrupts
+ *
+ * In a proper cascaded interrupt controller, the interrupt lines with
+ * cascaded interrupt controllers on them are just normal interrupt lines.
+ * You can mask the interrupts and get on with things. With this controller
+ * you can't do that.
+ *
+ * Quirk 3: The shortcut interrupts can't be (un)masked in bank 0
+ *
+ * Those interrupts that have shortcuts can only be masked/unmasked in
+ * their respective banks' enable/disable registers. Doing so in the bank 0
+ * enable/disable registers has no effect.
+ *
+ * The FIQ control register:
+ *  Bits 0-6: IRQ (index in order of interrupts from banks 1, 2, then 0)
+ *  Bit    7: Enable FIQ generation
+ *  Bits  8+: Unused
+ *
+ * An interrupt must be disabled before configuring it for FIQ generation
+ * otherwise both handlers will fire at the same time!
+ */
+
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/irqdomain.h>
+#include <linux/irqchip/bcm2835.h>
+
+#include <asm/exception.h>
+
+/* Put the bank and irq (32 bits) into the hwirq */
+#define MAKE_HWIRQ(b, n)	((b << 5) | (n))
+#define HWIRQ_BANK(i)		(i >> 5)
+#define HWIRQ_BIT(i)		BIT(i & 0x1f)
+
+#define NR_IRQS_BANK0		8
+#define BANK0_HWIRQ_MASK	0xff
+/* Shortcuts can't be disabled so any unknown new ones need to be masked */
+#define SHORTCUT1_MASK		0x00007c00
+#define SHORTCUT2_MASK		0x001f8000
+#define SHORTCUT_SHIFT		10
+#define BANK1_HWIRQ		BIT(8)
+#define BANK2_HWIRQ		BIT(9)
+#define BANK0_VALID_MASK	(BANK0_HWIRQ_MASK | BANK1_HWIRQ | BANK2_HWIRQ \
+					| SHORTCUT1_MASK | SHORTCUT2_MASK)
+
+#define REG_FIQ_CONTROL		0x0c
+
+#define NR_BANKS		3
+#define IRQS_PER_BANK		32
+
+static int reg_pending[] __initconst = { 0x00, 0x04, 0x08 };
+static int reg_enable[] __initconst = { 0x18, 0x10, 0x14 };
+static int reg_disable[] __initconst = { 0x24, 0x1c, 0x20 };
+static int bank_irqs[] __initconst = { 8, 32, 32 };
+
+static const int shortcuts[] = {
+	7, 9, 10, 18, 19,		/* Bank 1 */
+	21, 22, 23, 24, 25, 30		/* Bank 2 */
+};
+
+struct armctrl_ic {
+	void __iomem *base;
+	void __iomem *pending[NR_BANKS];
+	void __iomem *enable[NR_BANKS];
+	void __iomem *disable[NR_BANKS];
+	struct irq_domain *domain;
+};
+
+static struct armctrl_ic intc __read_mostly;
+
+static void armctrl_mask_irq(struct irq_data *d)
+{
+	writel_relaxed(HWIRQ_BIT(d->hwirq), intc.disable[HWIRQ_BANK(d->hwirq)]);
+}
+
+static void armctrl_unmask_irq(struct irq_data *d)
+{
+	writel_relaxed(HWIRQ_BIT(d->hwirq), intc.enable[HWIRQ_BANK(d->hwirq)]);
+}
+
+static struct irq_chip armctrl_chip = {
+	.name = "ARMCTRL-level",
+	.irq_mask = armctrl_mask_irq,
+	.irq_unmask = armctrl_unmask_irq
+};
+
+static int armctrl_xlate(struct irq_domain *d, struct device_node *ctrlr,
+	const u32 *intspec, unsigned int intsize,
+	unsigned long *out_hwirq, unsigned int *out_type)
+{
+	if (WARN_ON(intsize != 2))
+		return -EINVAL;
+
+	if (WARN_ON(intspec[0] >= NR_BANKS))
+		return -EINVAL;
+
+	if (WARN_ON(intspec[1] >= IRQS_PER_BANK))
+		return -EINVAL;
+
+	if (WARN_ON(intspec[0] == 0 && intspec[1] >= NR_IRQS_BANK0))
+		return -EINVAL;
+
+	*out_hwirq = MAKE_HWIRQ(intspec[0], intspec[1]);
+	*out_type = IRQ_TYPE_NONE;
+	return 0;
+}
+
+static struct irq_domain_ops armctrl_ops = {
+	.xlate = armctrl_xlate
+};
+
+static int __init armctrl_of_init(struct device_node *node,
+	struct device_node *parent)
+{
+	void __iomem *base;
+	int irq, b, i;
+
+	base = of_iomap(node, 0);
+	if (!base)
+		panic("%s: unable to map IC registers\n",
+			node->full_name);
+
+	intc.domain = irq_domain_add_linear(node, MAKE_HWIRQ(NR_BANKS, 0),
+			&armctrl_ops, NULL);
+	if (!intc.domain)
+		panic("%s: unable to create IRQ domain\n", node->full_name);
+
+	for (b = 0; b < NR_BANKS; b++) {
+		intc.pending[b] = base + reg_pending[b];
+		intc.enable[b] = base + reg_enable[b];
+		intc.disable[b] = base + reg_disable[b];
+
+		for (i = 0; i < bank_irqs[b]; i++) {
+			irq = irq_create_mapping(intc.domain, MAKE_HWIRQ(b, i));
+			BUG_ON(irq <= 0);
+			irq_set_chip_and_handler(irq, &armctrl_chip,
+				handle_level_irq);
+			set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+		}
+	}
+	return 0;
+}
+
+static struct of_device_id irq_of_match[] __initconst = {
+	{ .compatible = "brcm,bcm2835-armctrl-ic", .data = armctrl_of_init }
+};
+
+void __init bcm2835_init_irq(void)
+{
+	of_irq_init(irq_of_match);
+}
+
+/*
+ * Handle each interrupt across the entire interrupt controller.  This reads the
+ * status register before handling each interrupt, which is necessary given that
+ * handle_IRQ may briefly re-enable interrupts for soft IRQ handling.
+ */
+
+static void armctrl_handle_bank(int bank, struct pt_regs *regs)
+{
+	u32 stat, irq;
+
+	while ((stat = readl_relaxed(intc.pending[bank]))) {
+		irq = MAKE_HWIRQ(bank, ffs(stat) - 1);
+		handle_IRQ(irq_linear_revmap(intc.domain, irq), regs);
+	}
+}
+
+static void armctrl_handle_shortcut(int bank, struct pt_regs *regs,
+	u32 stat)
+{
+	u32 irq = MAKE_HWIRQ(bank, shortcuts[ffs(stat >> SHORTCUT_SHIFT) - 1]);
+	handle_IRQ(irq_linear_revmap(intc.domain, irq), regs);
+}
+
+asmlinkage void __exception_irq_entry bcm2835_handle_irq(
+	struct pt_regs *regs)
+{
+	u32 stat, irq;
+
+	while ((stat = readl_relaxed(intc.pending[0]) & BANK0_VALID_MASK)) {
+		if (stat & BANK0_HWIRQ_MASK) {
+			irq = MAKE_HWIRQ(0, ffs(stat & BANK0_HWIRQ_MASK) - 1);
+			handle_IRQ(irq_linear_revmap(intc.domain, irq), regs);
+		} else if (stat & SHORTCUT1_MASK) {
+			armctrl_handle_shortcut(1, regs, stat & SHORTCUT1_MASK);
+		} else if (stat & SHORTCUT2_MASK) {
+			armctrl_handle_shortcut(2, regs, stat & SHORTCUT2_MASK);
+		} else if (stat & BANK1_HWIRQ) {
+			armctrl_handle_bank(1, regs);
+		} else if (stat & BANK2_HWIRQ) {
+			armctrl_handle_bank(2, regs);
+		} else {
+			BUG();
+		}
+	}
+}
diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c
index 38c4bd8..c679867 100644
--- a/drivers/isdn/capi/capi.c
+++ b/drivers/isdn/capi/capi.c
@@ -234,7 +234,8 @@ static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci)
 
 	mp->minor = minor;
 
-	dev = tty_register_device(capinc_tty_driver, minor, NULL);
+	dev = tty_port_register_device(&mp->port, capinc_tty_driver, minor,
+			NULL);
 	if (IS_ERR(dev))
 		goto err_out2;
 
diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c
index aa41485..30a6b17 100644
--- a/drivers/isdn/gigaset/common.c
+++ b/drivers/isdn/gigaset/common.c
@@ -1123,7 +1123,6 @@ struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors,
 	return drv;
 
 error:
-	kfree(drv->cs);
 	kfree(drv);
 	return NULL;
 }
diff --git a/drivers/isdn/gigaset/interface.c b/drivers/isdn/gigaset/interface.c
index a6d9fd2..67abf3f 100644
--- a/drivers/isdn/gigaset/interface.c
+++ b/drivers/isdn/gigaset/interface.c
@@ -446,8 +446,8 @@ static void if_set_termios(struct tty_struct *tty, struct ktermios *old)
 		goto out;
 	}
 
-	iflag = tty->termios->c_iflag;
-	cflag = tty->termios->c_cflag;
+	iflag = tty->termios.c_iflag;
+	cflag = tty->termios.c_cflag;
 	old_cflag = old ? old->c_cflag : cflag;
 	gig_dbg(DEBUG_IF, "%u: iflag %x cflag %x old %x",
 		cs->minor_index, iflag, cflag, old_cflag);
@@ -524,7 +524,8 @@ void gigaset_if_init(struct cardstate *cs)
 	tasklet_init(&cs->if_wake_tasklet, if_wake, (unsigned long) cs);
 
 	mutex_lock(&cs->mutex);
-	cs->tty_dev = tty_register_device(drv->tty, cs->minor_index, NULL);
+	cs->tty_dev = tty_port_register_device(&cs->port, drv->tty,
+			cs->minor_index, NULL);
 
 	if (!IS_ERR(cs->tty_dev))
 		dev_set_drvdata(cs->tty_dev, cs);
diff --git a/drivers/isdn/hisax/Kconfig b/drivers/isdn/hisax/Kconfig
index 452fde9..70ecd0c 100644
--- a/drivers/isdn/hisax/Kconfig
+++ b/drivers/isdn/hisax/Kconfig
@@ -109,7 +109,7 @@ config HISAX_16_3
 
 config HISAX_TELESPCI
 	bool "Teles PCI"
-	depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV))
+	depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV || (XTENSA && !CPU_LITTLE_ENDIAN)))
 	help
 	  This enables HiSax support for the Teles PCI.
 	  See <file:Documentation/isdn/README.HiSax> on how to configure it.
@@ -237,7 +237,7 @@ config HISAX_MIC
 
 config HISAX_NETJET
 	bool "NETjet card"
-	depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV))
+	depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV || (XTENSA && !CPU_LITTLE_ENDIAN)))
 	help
 	  This enables HiSax support for the NetJet from Traverse
 	  Technologies.
@@ -248,7 +248,7 @@ config HISAX_NETJET
 
 config HISAX_NETJET_U
 	bool "NETspider U card"
-	depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV))
+	depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV || (XTENSA && !CPU_LITTLE_ENDIAN)))
 	help
 	  This enables HiSax support for the Netspider U interface ISDN card
 	  from Traverse Technologies.
@@ -316,7 +316,7 @@ config HISAX_GAZEL
 
 config HISAX_HFC_PCI
 	bool "HFC PCI-Bus cards"
-	depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV))
+	depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV || (XTENSA && !CPU_LITTLE_ENDIAN)))
 	help
 	  This enables HiSax support for the HFC-S PCI 2BDS0 based cards.
 
@@ -341,7 +341,7 @@ config HISAX_HFC_SX
 
 config HISAX_ENTERNOW_PCI
 	bool "Formula-n enter:now PCI card"
-	depends on HISAX_NETJET && PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV))
+	depends on HISAX_NETJET && PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV || (XTENSA && !CPU_LITTLE_ENDIAN)))
 	help
 	  This enables HiSax support for the Formula-n enter:now PCI
 	  ISDN card.
diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c
index 7bc5067..b817809 100644
--- a/drivers/isdn/i4l/isdn_tty.c
+++ b/drivers/isdn/i4l/isdn_tty.c
@@ -1009,15 +1009,15 @@ isdn_tty_change_speed(modem_info *info)
 		quot;
 	int i;
 
-	if (!port->tty || !port->tty->termios)
+	if (!port->tty)
 		return;
-	cflag = port->tty->termios->c_cflag;
+	cflag = port->tty->termios.c_cflag;
 
 	quot = i = cflag & CBAUD;
 	if (i & CBAUDEX) {
 		i &= ~CBAUDEX;
 		if (i < 1 || i > 2)
-			port->tty->termios->c_cflag &= ~CBAUDEX;
+			port->tty->termios.c_cflag &= ~CBAUDEX;
 		else
 			i += 15;
 	}
@@ -1097,7 +1097,7 @@ isdn_tty_shutdown(modem_info *info)
 #endif
 	isdn_unlock_drivers();
 	info->msr &= ~UART_MSR_RI;
-	if (!info->port.tty || (info->port.tty->termios->c_cflag & HUPCL)) {
+	if (!info->port.tty || (info->port.tty->termios.c_cflag & HUPCL)) {
 		info->mcr &= ~(UART_MCR_DTR | UART_MCR_RTS);
 		if (info->emu.mdmreg[REG_DTRHUP] & BIT_DTRHUP) {
 			isdn_tty_modem_reset_regs(info, 0);
@@ -1469,13 +1469,13 @@ isdn_tty_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
 	if (!old_termios)
 		isdn_tty_change_speed(info);
 	else {
-		if (tty->termios->c_cflag == old_termios->c_cflag &&
-		    tty->termios->c_ispeed == old_termios->c_ispeed &&
-		    tty->termios->c_ospeed == old_termios->c_ospeed)
+		if (tty->termios.c_cflag == old_termios->c_cflag &&
+		    tty->termios.c_ispeed == old_termios->c_ispeed &&
+		    tty->termios.c_ospeed == old_termios->c_ospeed)
 			return;
 		isdn_tty_change_speed(info);
 		if ((old_termios->c_cflag & CRTSCTS) &&
-		    !(tty->termios->c_cflag & CRTSCTS))
+		    !(tty->termios.c_cflag & CRTSCTS))
 			tty->hw_stopped = 0;
 	}
 }
@@ -1486,6 +1486,18 @@ isdn_tty_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
  * ------------------------------------------------------------
  */
 
+static int isdn_tty_install(struct tty_driver *driver, struct tty_struct *tty)
+{
+	modem_info *info = &dev->mdm.info[tty->index];
+
+	if (isdn_tty_paranoia_check(info, tty->name, __func__))
+		return -ENODEV;
+
+	tty->driver_data = info;
+
+	return tty_port_install(&info->port, driver, tty);
+}
+
 /*
  * This routine is called whenever a serial port is opened.  It
  * enables interrupts for a serial port, linking in its async structure into
@@ -1495,22 +1507,16 @@ isdn_tty_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
 static int
 isdn_tty_open(struct tty_struct *tty, struct file *filp)
 {
-	struct tty_port *port;
-	modem_info *info;
+	modem_info *info = tty->driver_data;
+	struct tty_port *port = &info->port;
 	int retval;
 
-	info = &dev->mdm.info[tty->index];
-	if (isdn_tty_paranoia_check(info, tty->name, "isdn_tty_open"))
-		return -ENODEV;
-	port = &info->port;
 #ifdef ISDN_DEBUG_MODEM_OPEN
 	printk(KERN_DEBUG "isdn_tty_open %s, count = %d\n", tty->name,
 	       port->count);
 #endif
 	port->count++;
-	tty->driver_data = info;
 	port->tty = tty;
-	tty->port = port;
 	/*
 	 * Start up serial port
 	 */
@@ -1738,6 +1744,7 @@ modem_write_profile(atemu *m)
 }
 
 static const struct tty_operations modem_ops = {
+	.install = isdn_tty_install,
 	.open = isdn_tty_open,
 	.close = isdn_tty_close,
 	.write = isdn_tty_write,
@@ -1782,7 +1789,7 @@ isdn_tty_modem_init(void)
 	m->tty_modem->subtype = SERIAL_TYPE_NORMAL;
 	m->tty_modem->init_termios = tty_std_termios;
 	m->tty_modem->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	m->tty_modem->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
+	m->tty_modem->flags = TTY_DRIVER_REAL_RAW;
 	m->tty_modem->driver_name = "isdn_tty";
 	tty_set_operations(m->tty_modem, &modem_ops);
 	retval = tty_register_driver(m->tty_modem);
diff --git a/drivers/isdn/mISDN/hwchannel.c b/drivers/isdn/mISDN/hwchannel.c
index 2602be2..84b4b0f 100644
--- a/drivers/isdn/mISDN/hwchannel.c
+++ b/drivers/isdn/mISDN/hwchannel.c
@@ -116,7 +116,7 @@ mISDN_freedchannel(struct dchannel *ch)
 	}
 	skb_queue_purge(&ch->squeue);
 	skb_queue_purge(&ch->rqueue);
-	flush_work_sync(&ch->workq);
+	flush_work(&ch->workq);
 	return 0;
 }
 EXPORT_SYMBOL(mISDN_freedchannel);
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index c96bbaa..f508def 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -63,6 +63,17 @@ config LEDS_LM3533
 	  hardware-accelerated blinking with maximum on and off periods of 9.8
 	  and 77 seconds respectively.
 
+config LEDS_LM3642
+	tristate "LED support for LM3642 Chip"
+	depends on LEDS_CLASS && I2C
+	select REGMAP_I2C
+	help
+	  This option enables support for LEDs connected to LM3642.
+	  The LM3642 is a 4MHz fixed-frequency synchronous boost
+	  converter plus 1.5A constant current driver for a high-current
+	  white LED.
+
+
 config LEDS_LOCOMO
 	tristate "LED Support for Locomo device"
 	depends on LEDS_CLASS
@@ -192,11 +203,12 @@ config LEDS_LP5521
 	  programming the engines.
 
 config LEDS_LP5523
-	tristate "LED Support for N.S. LP5523 LED driver chip"
+	tristate "LED Support for TI/National LP5523/55231 LED driver chip"
 	depends on LEDS_CLASS && I2C
 	help
-	  If you say yes here you get support for the National Semiconductor
-	  LP5523 LED driver. It is 9 channel chip with programmable engines.
+	  If you say yes here you get support for TI/National Semiconductor
+	  LP5523/55231 LED driver.
+	  It is 9 channel chip with programmable engines.
 	  Driver provides direct control via LED class and interface for
 	  programming the engines.
 
@@ -422,13 +434,13 @@ config LEDS_MAX8997
 	  This option enables support for on-chip LED drivers on
 	  MAXIM MAX8997 PMIC.
 
-config LEDS_LM3556
-	tristate "LED support for LM3556 Chip"
+config LEDS_LM355x
+	tristate "LED support for LM355x Chips, LM3554 and LM3556"
 	depends on LEDS_CLASS && I2C
 	select REGMAP_I2C
 	help
-	  This option enables support for LEDs connected to LM3556.
-	  LM3556 includes Torch, Flash and Indicator functions.
+	  This option enables support for LEDs connected to LM355x.
+	  LM355x includes Torch, Flash and Indicator functions.
 
 config LEDS_OT200
 	tristate "LED support for the Bachmann OT200"
@@ -506,6 +518,16 @@ config LEDS_TRIGGER_BACKLIGHT
 
 	  If unsure, say N.
 
+config LEDS_TRIGGER_CPU
+	bool "LED CPU Trigger"
+	depends on LEDS_TRIGGERS
+	help
+	  This allows LEDs to be controlled by active CPUs. This shows
+	  the active CPUs across an array of LEDs so you can see which
+	  CPUs are active on the system at any given moment.
+
+	  If unsure, say N.
+
 config LEDS_TRIGGER_GPIO
 	tristate "LED GPIO Trigger"
 	depends on LEDS_TRIGGERS
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index a4429a9..3fb9641 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_LEDS_BD2802)		+= leds-bd2802.o
 obj-$(CONFIG_LEDS_LOCOMO)		+= leds-locomo.o
 obj-$(CONFIG_LEDS_LM3530)		+= leds-lm3530.o
 obj-$(CONFIG_LEDS_LM3533)		+= leds-lm3533.o
+obj-$(CONFIG_LEDS_LM3642)		+= leds-lm3642.o
 obj-$(CONFIG_LEDS_MIKROTIK_RB532)	+= leds-rb532.o
 obj-$(CONFIG_LEDS_S3C24XX)		+= leds-s3c24xx.o
 obj-$(CONFIG_LEDS_NET48XX)		+= leds-net48xx.o
@@ -48,7 +49,7 @@ obj-$(CONFIG_LEDS_NETXBIG)		+= leds-netxbig.o
 obj-$(CONFIG_LEDS_ASIC3)		+= leds-asic3.o
 obj-$(CONFIG_LEDS_RENESAS_TPU)		+= leds-renesas-tpu.o
 obj-$(CONFIG_LEDS_MAX8997)		+= leds-max8997.o
-obj-$(CONFIG_LEDS_LM3556)		+= leds-lm3556.o
+obj-$(CONFIG_LEDS_LM355x)		+= leds-lm355x.o
 obj-$(CONFIG_LEDS_BLINKM)		+= leds-blinkm.o
 
 # LED SPI Drivers
@@ -61,5 +62,6 @@ obj-$(CONFIG_LEDS_TRIGGER_IDE_DISK)	+= ledtrig-ide-disk.o
 obj-$(CONFIG_LEDS_TRIGGER_HEARTBEAT)	+= ledtrig-heartbeat.o
 obj-$(CONFIG_LEDS_TRIGGER_BACKLIGHT)	+= ledtrig-backlight.o
 obj-$(CONFIG_LEDS_TRIGGER_GPIO)		+= ledtrig-gpio.o
+obj-$(CONFIG_LEDS_TRIGGER_CPU)		+= ledtrig-cpu.o
 obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON)	+= ledtrig-default-on.o
 obj-$(CONFIG_LEDS_TRIGGER_TRANSIENT)	+= ledtrig-transient.o
diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c
index c599095..48cce18 100644
--- a/drivers/leds/led-class.c
+++ b/drivers/leds/led-class.c
@@ -124,6 +124,16 @@ static void led_timer_function(unsigned long data)
 	mod_timer(&led_cdev->blink_timer, jiffies + msecs_to_jiffies(delay));
 }
 
+static void set_brightness_delayed(struct work_struct *ws)
+{
+	struct led_classdev *led_cdev =
+		container_of(ws, struct led_classdev, set_brightness_work);
+
+	led_stop_software_blink(led_cdev);
+
+	__led_set_brightness(led_cdev, led_cdev->delayed_set_value);
+}
+
 /**
  * led_classdev_suspend - suspend an led_classdev.
  * @led_cdev: the led_classdev to suspend.
@@ -191,6 +201,8 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
 
 	led_update_brightness(led_cdev);
 
+	INIT_WORK(&led_cdev->set_brightness_work, set_brightness_delayed);
+
 	init_timer(&led_cdev->blink_timer);
 	led_cdev->blink_timer.function = led_timer_function;
 	led_cdev->blink_timer.data = (unsigned long)led_cdev;
@@ -221,7 +233,10 @@ void led_classdev_unregister(struct led_classdev *led_cdev)
 	up_write(&led_cdev->trigger_lock);
 #endif
 
+	cancel_work_sync(&led_cdev->set_brightness_work);
+
 	/* Stop blinking */
+	led_stop_software_blink(led_cdev);
 	led_set_brightness(led_cdev, LED_OFF);
 
 	device_unregister(led_cdev->dev);
diff --git a/drivers/leds/led-core.c b/drivers/leds/led-core.c
index 2ab05af..ce8921a 100644
--- a/drivers/leds/led-core.c
+++ b/drivers/leds/led-core.c
@@ -103,13 +103,23 @@ void led_blink_set_oneshot(struct led_classdev *led_cdev,
 }
 EXPORT_SYMBOL(led_blink_set_oneshot);
 
-void led_set_brightness(struct led_classdev *led_cdev,
-			enum led_brightness brightness)
+void led_stop_software_blink(struct led_classdev *led_cdev)
 {
-	/* stop and clear soft-blink timer */
 	del_timer_sync(&led_cdev->blink_timer);
 	led_cdev->blink_delay_on = 0;
 	led_cdev->blink_delay_off = 0;
+}
+EXPORT_SYMBOL_GPL(led_stop_software_blink);
+
+void led_set_brightness(struct led_classdev *led_cdev,
+			enum led_brightness brightness)
+{
+	/* delay brightness setting if need to stop soft-blink timer */
+	if (led_cdev->blink_delay_on || led_cdev->blink_delay_off) {
+		led_cdev->delayed_set_value = brightness;
+		schedule_work(&led_cdev->set_brightness_work);
+		return;
+	}
 
 	__led_set_brightness(led_cdev, brightness);
 }
diff --git a/drivers/leds/led-triggers.c b/drivers/leds/led-triggers.c
index 363975b..262eb41 100644
--- a/drivers/leds/led-triggers.c
+++ b/drivers/leds/led-triggers.c
@@ -102,6 +102,12 @@ EXPORT_SYMBOL_GPL(led_trigger_show);
 void led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trig)
 {
 	unsigned long flags;
+	char *event = NULL;
+	char *envp[2];
+	const char *name;
+
+	name = trig ? trig->name : "none";
+	event = kasprintf(GFP_KERNEL, "TRIGGER=%s", name);
 
 	/* Remove any existing trigger */
 	if (led_cdev->trigger) {
@@ -109,6 +115,8 @@ void led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trig)
 		list_del(&led_cdev->trig_list);
 		write_unlock_irqrestore(&led_cdev->trigger->leddev_list_lock,
 			flags);
+		cancel_work_sync(&led_cdev->set_brightness_work);
+		led_stop_software_blink(led_cdev);
 		if (led_cdev->trigger->deactivate)
 			led_cdev->trigger->deactivate(led_cdev);
 		led_cdev->trigger = NULL;
@@ -122,6 +130,13 @@ void led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trig)
 		if (trig->activate)
 			trig->activate(led_cdev);
 	}
+
+	if (event) {
+		envp[0] = event;
+		envp[1] = NULL;
+		kobject_uevent_env(&led_cdev->dev->kobj, KOBJ_CHANGE, envp);
+		kfree(event);
+	}
 }
 EXPORT_SYMBOL_GPL(led_trigger_set);
 
@@ -224,7 +239,7 @@ void led_trigger_event(struct led_trigger *trig,
 		struct led_classdev *led_cdev;
 
 		led_cdev = list_entry(entry, struct led_classdev, trig_list);
-		__led_set_brightness(led_cdev, brightness);
+		led_set_brightness(led_cdev, brightness);
 	}
 	read_unlock(&trig->leddev_list_lock);
 }
diff --git a/drivers/leds/leds-88pm860x.c b/drivers/leds/leds-88pm860x.c
index 61897cf..70232b1 100644
--- a/drivers/leds/leds-88pm860x.c
+++ b/drivers/leds/leds-88pm860x.c
@@ -20,18 +20,12 @@
 #include <linux/mfd/88pm860x.h>
 #include <linux/module.h>
 
-#define LED_PWM_SHIFT		(3)
 #define LED_PWM_MASK		(0x1F)
 #define LED_CURRENT_MASK	(0x07 << 5)
 
-#define LED_BLINK_ON_MASK	(0x07)
 #define LED_BLINK_MASK		(0x7F)
 
-#define LED_BLINK_ON(x)		((x & 0x7) * 66 + 66)
-#define LED_BLINK_ON_MIN	LED_BLINK_ON(0)
-#define LED_BLINK_ON_MAX	LED_BLINK_ON(0x7)
 #define LED_ON_CONTINUOUS	(0x0F << 3)
-#define LED_TO_ON(x)		((x - 66) / 66)
 
 #define LED1_BLINK_EN		(1 << 1)
 #define LED2_BLINK_EN		(1 << 2)
@@ -49,85 +43,25 @@ struct pm860x_led {
 	unsigned char brightness;
 	unsigned char current_brightness;
 
-	int blink_data;
-	int blink_time;
-	int blink_on;
-	int blink_off;
+	int reg_control;
+	int reg_blink;
+	int blink_mask;
 };
 
-/* return offset of color register */
-static inline int __led_off(int port)
-{
-	int ret = -EINVAL;
-
-	switch (port) {
-	case PM8606_LED1_RED:
-	case PM8606_LED1_GREEN:
-	case PM8606_LED1_BLUE:
-		ret = port - PM8606_LED1_RED + PM8606_RGB1B;
-		break;
-	case PM8606_LED2_RED:
-	case PM8606_LED2_GREEN:
-	case PM8606_LED2_BLUE:
-		ret = port - PM8606_LED2_RED + PM8606_RGB2B;
-		break;
-	}
-	return ret;
-}
-
-/* return offset of blink register */
-static inline int __blink_off(int port)
-{
-	int ret = -EINVAL;
-
-	switch (port) {
-	case PM8606_LED1_RED:
-	case PM8606_LED1_GREEN:
-	case PM8606_LED1_BLUE:
-		ret = PM8606_RGB1A;
-		break;
-	case PM8606_LED2_RED:
-	case PM8606_LED2_GREEN:
-	case PM8606_LED2_BLUE:
-		ret = PM8606_RGB2A;
-		break;
-	}
-	return ret;
-}
-
-static inline int __blink_ctl_mask(int port)
-{
-	int ret = -EINVAL;
-
-	switch (port) {
-	case PM8606_LED1_RED:
-	case PM8606_LED1_GREEN:
-	case PM8606_LED1_BLUE:
-		ret = LED1_BLINK_EN;
-		break;
-	case PM8606_LED2_RED:
-	case PM8606_LED2_GREEN:
-	case PM8606_LED2_BLUE:
-		ret = LED2_BLINK_EN;
-		break;
-	}
-	return ret;
-}
-
 static int led_power_set(struct pm860x_chip *chip, int port, int on)
 {
 	int ret = -EINVAL;
 
 	switch (port) {
-	case PM8606_LED1_RED:
-	case PM8606_LED1_GREEN:
-	case PM8606_LED1_BLUE:
+	case 0:
+	case 1:
+	case 2:
 		ret = on ? pm8606_osc_enable(chip, RGB1_ENABLE) :
 			pm8606_osc_disable(chip, RGB1_ENABLE);
 		break;
-	case PM8606_LED2_RED:
-	case PM8606_LED2_GREEN:
-	case PM8606_LED2_BLUE:
+	case 3:
+	case 4:
+	case 5:
 		ret = on ? pm8606_osc_enable(chip, RGB2_ENABLE) :
 			pm8606_osc_disable(chip, RGB2_ENABLE);
 		break;
@@ -141,7 +75,7 @@ static void pm860x_led_work(struct work_struct *work)
 	struct pm860x_led *led;
 	struct pm860x_chip *chip;
 	unsigned char buf[3];
-	int mask, ret;
+	int ret;
 
 	led = container_of(work, struct pm860x_led, work);
 	chip = led->chip;
@@ -149,34 +83,34 @@ static void pm860x_led_work(struct work_struct *work)
 	if ((led->current_brightness == 0) && led->brightness) {
 		led_power_set(chip, led->port, 1);
 		if (led->iset) {
-			pm860x_set_bits(led->i2c, __led_off(led->port),
+			pm860x_set_bits(led->i2c, led->reg_control,
 					LED_CURRENT_MASK, led->iset);
 		}
-		pm860x_set_bits(led->i2c, __blink_off(led->port),
+		pm860x_set_bits(led->i2c, led->reg_blink,
 				LED_BLINK_MASK, LED_ON_CONTINUOUS);
-		mask = __blink_ctl_mask(led->port);
-		pm860x_set_bits(led->i2c, PM8606_WLED3B, mask, mask);
+		pm860x_set_bits(led->i2c, PM8606_WLED3B, led->blink_mask,
+				led->blink_mask);
 	}
-	pm860x_set_bits(led->i2c, __led_off(led->port), LED_PWM_MASK,
+	pm860x_set_bits(led->i2c, led->reg_control, LED_PWM_MASK,
 			led->brightness);
 
 	if (led->brightness == 0) {
-		pm860x_bulk_read(led->i2c, __led_off(led->port), 3, buf);
+		pm860x_bulk_read(led->i2c, led->reg_control, 3, buf);
 		ret = buf[0] & LED_PWM_MASK;
 		ret |= buf[1] & LED_PWM_MASK;
 		ret |= buf[2] & LED_PWM_MASK;
 		if (ret == 0) {
 			/* unset current since no led is lighting */
-			pm860x_set_bits(led->i2c, __led_off(led->port),
+			pm860x_set_bits(led->i2c, led->reg_control,
 					LED_CURRENT_MASK, 0);
-			mask = __blink_ctl_mask(led->port);
-			pm860x_set_bits(led->i2c, PM8606_WLED3B, mask, 0);
+			pm860x_set_bits(led->i2c, PM8606_WLED3B,
+					led->blink_mask, 0);
 			led_power_set(chip, led->port, 0);
 		}
 	}
 	led->current_brightness = led->brightness;
 	dev_dbg(chip->dev, "Update LED. (reg:%d, brightness:%d)\n",
-		__led_off(led->port), led->brightness);
+		led->reg_control, led->brightness);
 	mutex_unlock(&led->lock);
 }
 
@@ -192,36 +126,61 @@ static void pm860x_led_set(struct led_classdev *cdev,
 static int pm860x_led_probe(struct platform_device *pdev)
 {
 	struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
-	struct pm860x_led_pdata *pdata;
+	struct pm860x_led_pdata *pdata = pdev->dev.platform_data;
 	struct pm860x_led *data;
 	struct resource *res;
-	int ret;
-
-	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
-	if (res == NULL) {
-		dev_err(&pdev->dev, "No I/O resource!\n");
-		return -EINVAL;
-	}
-
-	pdata = pdev->dev.platform_data;
-	if (pdata == NULL) {
-		dev_err(&pdev->dev, "No platform data!\n");
-		return -EINVAL;
-	}
+	int ret = 0;
 
 	data = devm_kzalloc(&pdev->dev, sizeof(struct pm860x_led), GFP_KERNEL);
 	if (data == NULL)
 		return -ENOMEM;
-	strncpy(data->name, res->name, MFD_NAME_SIZE - 1);
+	res = platform_get_resource_byname(pdev, IORESOURCE_REG, "control");
+	if (!res) {
+		dev_err(&pdev->dev, "No REG resource for control\n");
+		ret = -ENXIO;
+		goto out;
+	}
+	data->reg_control = res->start;
+	res = platform_get_resource_byname(pdev, IORESOURCE_REG, "blink");
+	if (!res) {
+		dev_err(&pdev->dev, "No REG resource for blink\n");
+		ret = -ENXIO;
+		goto out;
+	}
+	data->reg_blink = res->start;
+	memset(data->name, 0, MFD_NAME_SIZE);
+	switch (pdev->id) {
+	case 0:
+		data->blink_mask = LED1_BLINK_EN;
+		sprintf(data->name, "led0-red");
+		break;
+	case 1:
+		data->blink_mask = LED1_BLINK_EN;
+		sprintf(data->name, "led0-green");
+		break;
+	case 2:
+		data->blink_mask = LED1_BLINK_EN;
+		sprintf(data->name, "led0-blue");
+		break;
+	case 3:
+		data->blink_mask = LED2_BLINK_EN;
+		sprintf(data->name, "led1-red");
+		break;
+	case 4:
+		data->blink_mask = LED2_BLINK_EN;
+		sprintf(data->name, "led1-green");
+		break;
+	case 5:
+		data->blink_mask = LED2_BLINK_EN;
+		sprintf(data->name, "led1-blue");
+		break;
+	}
 	dev_set_drvdata(&pdev->dev, data);
 	data->chip = chip;
 	data->i2c = (chip->id == CHIP_PM8606) ? chip->client : chip->companion;
-	data->iset = pdata->iset;
-	data->port = pdata->flags;
-	if (data->port < 0) {
-		dev_err(&pdev->dev, "check device failed\n");
-		return -EINVAL;
-	}
+	data->port = pdev->id;
+	if (pdata && pdata->iset)
+		data->iset = pdata->iset;
 
 	data->current_brightness = 0;
 	data->cdev.name = data->name;
@@ -236,6 +195,9 @@ static int pm860x_led_probe(struct platform_device *pdev)
 	}
 	pm860x_led_set(&data->cdev, 0);
 	return 0;
+out:
+	devm_kfree(&pdev->dev, data);
+	return ret;
 }
 
 static int pm860x_led_remove(struct platform_device *pdev)
diff --git a/drivers/leds/leds-clevo-mail.c b/drivers/leds/leds-clevo-mail.c
index 1ed1677..e024b0b 100644
--- a/drivers/leds/leds-clevo-mail.c
+++ b/drivers/leds/leds-clevo-mail.c
@@ -31,7 +31,7 @@ static int __init clevo_mail_led_dmi_callback(const struct dmi_system_id *id)
 }
 
 /*
- * struct mail_led_whitelist - List of known good models
+ * struct clevo_mail_led_dmi_table - List of known good models
  *
  * Contains the known good models this driver is compatible with.
  * When adding a new model try to be as strict as possible. This
@@ -39,7 +39,7 @@ static int __init clevo_mail_led_dmi_callback(const struct dmi_system_id *id)
  * detected as working, but in reality it is not) as low as
  * possible.
  */
-static struct dmi_system_id __initdata mail_led_whitelist[] = {
+static struct dmi_system_id __initdata clevo_mail_led_dmi_table[] = {
 	{
 		.callback = clevo_mail_led_dmi_callback,
 		.ident = "Clevo D410J",
@@ -59,11 +59,10 @@ static struct dmi_system_id __initdata mail_led_whitelist[] = {
 	},
 	{
 		.callback = clevo_mail_led_dmi_callback,
-		.ident = "Positivo Mobile",
+		.ident = "Clevo M5x0V",
 		.matches = {
 			DMI_MATCH(DMI_BOARD_VENDOR, "CLEVO Co. "),
 			DMI_MATCH(DMI_BOARD_NAME, "M5X0V "),
-			DMI_MATCH(DMI_PRODUCT_NAME, "Positivo Mobile"),
 			DMI_MATCH(DMI_PRODUCT_VERSION, "VT6198")
 		}
 	},
@@ -89,6 +88,7 @@ static struct dmi_system_id __initdata mail_led_whitelist[] = {
 	},
 	{ }
 };
+MODULE_DEVICE_TABLE(dmi, clevo_mail_led_dmi_table);
 
 static void clevo_mail_led_set(struct led_classdev *led_cdev,
 				enum led_brightness value)
@@ -180,7 +180,7 @@ static int __init clevo_mail_led_init(void)
 
 	/* Check with the help of DMI if we are running on supported hardware */
 	if (!nodetect) {
-		count = dmi_check_system(mail_led_whitelist);
+		count = dmi_check_system(clevo_mail_led_dmi_table);
 	} else {
 		count = 1;
 		printk(KERN_ERR KBUILD_MODNAME ": Skipping DMI detection. "
diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c
index c032b21..087d1e6 100644
--- a/drivers/leds/leds-gpio.c
+++ b/drivers/leds/leds-gpio.c
@@ -20,6 +20,7 @@
 #include <linux/slab.h>
 #include <linux/workqueue.h>
 #include <linux/module.h>
+#include <linux/pinctrl/consumer.h>
 
 struct gpio_led_data {
 	struct led_classdev cdev;
@@ -170,11 +171,10 @@ static struct gpio_leds_priv * __devinit gpio_leds_create_of(struct platform_dev
 {
 	struct device_node *np = pdev->dev.of_node, *child;
 	struct gpio_leds_priv *priv;
-	int count = 0, ret;
+	int count, ret;
 
 	/* count LEDs in this device, so we know how much to allocate */
-	for_each_child_of_node(np, child)
-		count++;
+	count = of_get_child_count(np);
 	if (!count)
 		return NULL;
 
@@ -228,7 +228,6 @@ static struct gpio_leds_priv * __devinit gpio_leds_create_of(struct platform_dev
 {
 	return NULL;
 }
-#define of_gpio_leds_match NULL
 #endif /* CONFIG_OF_GPIO */
 
 
@@ -236,8 +235,14 @@ static int __devinit gpio_led_probe(struct platform_device *pdev)
 {
 	struct gpio_led_platform_data *pdata = pdev->dev.platform_data;
 	struct gpio_leds_priv *priv;
+	struct pinctrl *pinctrl;
 	int i, ret = 0;
 
+	pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+	if (IS_ERR(pinctrl))
+		dev_warn(&pdev->dev,
+			"pins are not configured from the driver\n");
+
 	if (pdata && pdata->num_leds) {
 		priv = devm_kzalloc(&pdev->dev,
 				sizeof_gpio_leds_priv(pdata->num_leds),
@@ -270,13 +275,13 @@ static int __devinit gpio_led_probe(struct platform_device *pdev)
 
 static int __devexit gpio_led_remove(struct platform_device *pdev)
 {
-	struct gpio_leds_priv *priv = dev_get_drvdata(&pdev->dev);
+	struct gpio_leds_priv *priv = platform_get_drvdata(pdev);
 	int i;
 
 	for (i = 0; i < priv->num_leds; i++)
 		delete_gpio_led(&priv->leds[i]);
 
-	dev_set_drvdata(&pdev->dev, NULL);
+	platform_set_drvdata(pdev, NULL);
 
 	return 0;
 }
@@ -287,7 +292,7 @@ static struct platform_driver gpio_led_driver = {
 	.driver		= {
 		.name	= "leds-gpio",
 		.owner	= THIS_MODULE,
-		.of_match_table = of_gpio_leds_match,
+		.of_match_table = of_match_ptr(of_gpio_leds_match),
 	},
 };
 
diff --git a/drivers/leds/leds-lm3530.c b/drivers/leds/leds-lm3530.c
index 23637bd..b26306f 100644
--- a/drivers/leds/leds-lm3530.c
+++ b/drivers/leds/leds-lm3530.c
@@ -150,7 +150,7 @@ static int lm3530_get_mode_from_str(const char *str)
 		if (sysfs_streq(str, mode_map[i].mode))
 			return mode_map[i].mode_val;
 
-	return -1;
+	return -EINVAL;
 }
 
 static void lm3530_als_configure(struct lm3530_platform_data *pdata,
@@ -358,7 +358,7 @@ static ssize_t lm3530_mode_set(struct device *dev, struct device_attribute
 	mode = lm3530_get_mode_from_str(buf);
 	if (mode < 0) {
 		dev_err(dev, "Invalid mode\n");
-		return -EINVAL;
+		return mode;
 	}
 
 	drvdata->mode = mode;
@@ -416,7 +416,7 @@ static int __devinit lm3530_probe(struct i2c_client *client,
 
 	i2c_set_clientdata(client, drvdata);
 
-	drvdata->regulator = regulator_get(&client->dev, "vin");
+	drvdata->regulator = devm_regulator_get(&client->dev, "vin");
 	if (IS_ERR(drvdata->regulator)) {
 		dev_err(&client->dev, "regulator get failed\n");
 		err = PTR_ERR(drvdata->regulator);
@@ -429,15 +429,13 @@ static int __devinit lm3530_probe(struct i2c_client *client,
 		if (err < 0) {
 			dev_err(&client->dev,
 				"Register Init failed: %d\n", err);
-			err = -ENODEV;
-			goto err_reg_init;
+			return err;
 		}
 	}
 	err = led_classdev_register(&client->dev, &drvdata->led_dev);
 	if (err < 0) {
 		dev_err(&client->dev, "Register led class failed: %d\n", err);
-		err = -ENODEV;
-		goto err_class_register;
+		return err;
 	}
 
 	err = device_create_file(drvdata->led_dev.dev, &dev_attr_mode);
@@ -451,9 +449,6 @@ static int __devinit lm3530_probe(struct i2c_client *client,
 
 err_create_file:
 	led_classdev_unregister(&drvdata->led_dev);
-err_class_register:
-err_reg_init:
-	regulator_put(drvdata->regulator);
 	return err;
 }
 
@@ -465,7 +460,6 @@ static int __devexit lm3530_remove(struct i2c_client *client)
 
 	if (drvdata->enable)
 		regulator_disable(drvdata->regulator);
-	regulator_put(drvdata->regulator);
 	led_classdev_unregister(&drvdata->led_dev);
 	return 0;
 }
diff --git a/drivers/leds/leds-lm3533.c b/drivers/leds/leds-lm3533.c
index f56b6e7..f6837b9 100644
--- a/drivers/leds/leds-lm3533.c
+++ b/drivers/leds/leds-lm3533.c
@@ -737,7 +737,7 @@ err_sysfs_remove:
 	sysfs_remove_group(&led->cdev.dev->kobj, &lm3533_led_attribute_group);
 err_unregister:
 	led_classdev_unregister(&led->cdev);
-	flush_work_sync(&led->work);
+	flush_work(&led->work);
 
 	return ret;
 }
@@ -751,7 +751,7 @@ static int __devexit lm3533_led_remove(struct platform_device *pdev)
 	lm3533_ctrlbank_disable(&led->cb);
 	sysfs_remove_group(&led->cdev.dev->kobj, &lm3533_led_attribute_group);
 	led_classdev_unregister(&led->cdev);
-	flush_work_sync(&led->work);
+	flush_work(&led->work);
 
 	return 0;
 }
@@ -765,7 +765,7 @@ static void lm3533_led_shutdown(struct platform_device *pdev)
 
 	lm3533_ctrlbank_disable(&led->cb);
 	lm3533_led_set(&led->cdev, LED_OFF);		/* disable blink */
-	flush_work_sync(&led->work);
+	flush_work(&led->work);
 }
 
 static struct platform_driver lm3533_led_driver = {
diff --git a/drivers/leds/leds-lm3556.c b/drivers/leds/leds-lm3556.c
deleted file mode 100644
index 3062abd..0000000
--- a/drivers/leds/leds-lm3556.c
+++ /dev/null
@@ -1,512 +0,0 @@
-/*
- * Simple driver for Texas Instruments LM3556 LED Flash driver chip (Rev0x03)
- * Copyright (C) 2012 Texas Instruments
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Please refer Documentation/leds/leds-lm3556.txt file.
- */
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/i2c.h>
-#include <linux/leds.h>
-#include <linux/slab.h>
-#include <linux/platform_device.h>
-#include <linux/fs.h>
-#include <linux/regmap.h>
-#include <linux/platform_data/leds-lm3556.h>
-
-#define REG_FILT_TIME			(0x0)
-#define REG_IVFM_MODE			(0x1)
-#define REG_NTC				(0x2)
-#define REG_INDIC_TIME			(0x3)
-#define REG_INDIC_BLINK			(0x4)
-#define REG_INDIC_PERIOD		(0x5)
-#define REG_TORCH_TIME			(0x6)
-#define REG_CONF			(0x7)
-#define REG_FLASH			(0x8)
-#define REG_I_CTRL			(0x9)
-#define REG_ENABLE			(0xA)
-#define REG_FLAG			(0xB)
-#define REG_MAX				(0xB)
-
-#define IVFM_FILTER_TIME_SHIFT		(3)
-#define UVLO_EN_SHIFT			(7)
-#define HYSTERSIS_SHIFT			(5)
-#define IVM_D_TH_SHIFT			(2)
-#define IVFM_ADJ_MODE_SHIFT		(0)
-#define NTC_EVENT_LVL_SHIFT		(5)
-#define NTC_TRIP_TH_SHIFT		(2)
-#define NTC_BIAS_I_LVL_SHIFT		(0)
-#define INDIC_RAMP_UP_TIME_SHIFT	(3)
-#define INDIC_RAMP_DN_TIME_SHIFT	(0)
-#define INDIC_N_BLANK_SHIFT		(4)
-#define INDIC_PULSE_TIME_SHIFT		(0)
-#define INDIC_N_PERIOD_SHIFT		(0)
-#define TORCH_RAMP_UP_TIME_SHIFT	(3)
-#define TORCH_RAMP_DN_TIME_SHIFT	(0)
-#define STROBE_USUAGE_SHIFT		(7)
-#define STROBE_PIN_POLARITY_SHIFT	(6)
-#define TORCH_PIN_POLARITY_SHIFT	(5)
-#define TX_PIN_POLARITY_SHIFT		(4)
-#define TX_EVENT_LVL_SHIFT		(3)
-#define IVFM_EN_SHIFT			(2)
-#define NTC_MODE_SHIFT			(1)
-#define INDIC_MODE_SHIFT		(0)
-#define INDUCTOR_I_LIMIT_SHIFT		(6)
-#define FLASH_RAMP_TIME_SHIFT		(3)
-#define FLASH_TOUT_TIME_SHIFT		(0)
-#define TORCH_I_SHIFT			(4)
-#define FLASH_I_SHIFT			(0)
-#define NTC_EN_SHIFT			(7)
-#define TX_PIN_EN_SHIFT			(6)
-#define STROBE_PIN_EN_SHIFT		(5)
-#define TORCH_PIN_EN_SHIFT		(4)
-#define PRECHG_MODE_EN_SHIFT		(3)
-#define PASS_MODE_ONLY_EN_SHIFT		(2)
-#define MODE_BITS_SHIFT			(0)
-
-#define IVFM_FILTER_TIME_MASK		(0x3)
-#define UVLO_EN_MASK			(0x1)
-#define HYSTERSIS_MASK			(0x3)
-#define IVM_D_TH_MASK			(0x7)
-#define IVFM_ADJ_MODE_MASK		(0x3)
-#define NTC_EVENT_LVL_MASK		(0x1)
-#define NTC_TRIP_TH_MASK		(0x7)
-#define NTC_BIAS_I_LVL_MASK		(0x3)
-#define INDIC_RAMP_UP_TIME_MASK		(0x7)
-#define INDIC_RAMP_DN_TIME_MASK		(0x7)
-#define INDIC_N_BLANK_MASK		(0x7)
-#define INDIC_PULSE_TIME_MASK		(0x7)
-#define INDIC_N_PERIOD_MASK		(0x7)
-#define TORCH_RAMP_UP_TIME_MASK		(0x7)
-#define TORCH_RAMP_DN_TIME_MASK		(0x7)
-#define STROBE_USUAGE_MASK		(0x1)
-#define STROBE_PIN_POLARITY_MASK	(0x1)
-#define TORCH_PIN_POLARITY_MASK		(0x1)
-#define TX_PIN_POLARITY_MASK		(0x1)
-#define TX_EVENT_LVL_MASK		(0x1)
-#define IVFM_EN_MASK			(0x1)
-#define NTC_MODE_MASK			(0x1)
-#define INDIC_MODE_MASK			(0x1)
-#define INDUCTOR_I_LIMIT_MASK		(0x3)
-#define FLASH_RAMP_TIME_MASK		(0x7)
-#define FLASH_TOUT_TIME_MASK		(0x7)
-#define TORCH_I_MASK			(0x7)
-#define FLASH_I_MASK			(0xF)
-#define NTC_EN_MASK			(0x1)
-#define TX_PIN_EN_MASK			(0x1)
-#define STROBE_PIN_EN_MASK		(0x1)
-#define TORCH_PIN_EN_MASK		(0x1)
-#define PRECHG_MODE_EN_MASK		(0x1)
-#define PASS_MODE_ONLY_EN_MASK		(0x1)
-#define MODE_BITS_MASK			(0x13)
-#define EX_PIN_CONTROL_MASK		(0xF1)
-#define EX_PIN_ENABLE_MASK		(0x70)
-
-enum lm3556_indic_pulse_time {
-	PULSE_TIME_0_MS = 0,
-	PULSE_TIME_32_MS,
-	PULSE_TIME_64_MS,
-	PULSE_TIME_92_MS,
-	PULSE_TIME_128_MS,
-	PULSE_TIME_160_MS,
-	PULSE_TIME_196_MS,
-	PULSE_TIME_224_MS,
-	PULSE_TIME_256_MS,
-	PULSE_TIME_288_MS,
-	PULSE_TIME_320_MS,
-	PULSE_TIME_352_MS,
-	PULSE_TIME_384_MS,
-	PULSE_TIME_416_MS,
-	PULSE_TIME_448_MS,
-	PULSE_TIME_480_MS,
-};
-
-enum lm3556_indic_n_blank {
-	INDIC_N_BLANK_0 = 0,
-	INDIC_N_BLANK_1,
-	INDIC_N_BLANK_2,
-	INDIC_N_BLANK_3,
-	INDIC_N_BLANK_4,
-	INDIC_N_BLANK_5,
-	INDIC_N_BLANK_6,
-	INDIC_N_BLANK_7,
-	INDIC_N_BLANK_8,
-	INDIC_N_BLANK_9,
-	INDIC_N_BLANK_10,
-	INDIC_N_BLANK_11,
-	INDIC_N_BLANK_12,
-	INDIC_N_BLANK_13,
-	INDIC_N_BLANK_14,
-	INDIC_N_BLANK_15,
-};
-
-enum lm3556_indic_period {
-	INDIC_PERIOD_0 = 0,
-	INDIC_PERIOD_1,
-	INDIC_PERIOD_2,
-	INDIC_PERIOD_3,
-	INDIC_PERIOD_4,
-	INDIC_PERIOD_5,
-	INDIC_PERIOD_6,
-	INDIC_PERIOD_7,
-};
-
-enum lm3556_mode {
-	MODES_STASNDBY = 0,
-	MODES_INDIC,
-	MODES_TORCH,
-	MODES_FLASH
-};
-
-#define INDIC_PATTERN_SIZE 4
-
-struct indicator {
-	u8 blinking;
-	u8 period_cnt;
-};
-
-struct lm3556_chip_data {
-	struct device *dev;
-
-	struct led_classdev cdev_flash;
-	struct led_classdev cdev_torch;
-	struct led_classdev cdev_indicator;
-
-	struct lm3556_platform_data *pdata;
-	struct regmap *regmap;
-	struct mutex lock;
-
-	unsigned int last_flag;
-};
-
-/* indicator pattern */
-static struct indicator indicator_pattern[INDIC_PATTERN_SIZE] = {
-	[0] = {(INDIC_N_BLANK_1 << INDIC_N_BLANK_SHIFT)
-	       | PULSE_TIME_32_MS, INDIC_PERIOD_1},
-	[1] = {(INDIC_N_BLANK_15 << INDIC_N_BLANK_SHIFT)
-	       | PULSE_TIME_32_MS, INDIC_PERIOD_2},
-	[2] = {(INDIC_N_BLANK_10 << INDIC_N_BLANK_SHIFT)
-	       | PULSE_TIME_32_MS, INDIC_PERIOD_4},
-	[3] = {(INDIC_N_BLANK_5 << INDIC_N_BLANK_SHIFT)
-	       | PULSE_TIME_32_MS, INDIC_PERIOD_7},
-};
-
-/* chip initialize */
-static int __devinit lm3556_chip_init(struct lm3556_chip_data *chip)
-{
-	unsigned int reg_val;
-	int ret;
-	struct lm3556_platform_data *pdata = chip->pdata;
-
-	/* set config register */
-	ret = regmap_read(chip->regmap, REG_CONF, &reg_val);
-	if (ret < 0) {
-		dev_err(chip->dev, "Failed to read REG_CONF Register\n");
-		goto out;
-	}
-
-	reg_val &= (~EX_PIN_CONTROL_MASK);
-	reg_val |= ((pdata->torch_pin_polarity & 0x01)
-		    << TORCH_PIN_POLARITY_SHIFT);
-	reg_val |= ((pdata->strobe_usuage & 0x01) << STROBE_USUAGE_SHIFT);
-	reg_val |= ((pdata->strobe_pin_polarity & 0x01)
-		    << STROBE_PIN_POLARITY_SHIFT);
-	reg_val |= ((pdata->tx_pin_polarity & 0x01) << TX_PIN_POLARITY_SHIFT);
-	reg_val |= ((pdata->indicator_mode & 0x01) << INDIC_MODE_SHIFT);
-
-	ret = regmap_write(chip->regmap, REG_CONF, reg_val);
-	if (ret < 0) {
-		dev_err(chip->dev, "Failed to write REG_CONF Regisgter\n");
-		goto out;
-	}
-
-	/* set enable register */
-	ret = regmap_read(chip->regmap, REG_ENABLE, &reg_val);
-	if (ret < 0) {
-		dev_err(chip->dev, "Failed to read REG_ENABLE Register\n");
-		goto out;
-	}
-
-	reg_val &= (~EX_PIN_ENABLE_MASK);
-	reg_val |= ((pdata->torch_pin_en & 0x01) << TORCH_PIN_EN_SHIFT);
-	reg_val |= ((pdata->strobe_pin_en & 0x01) << STROBE_PIN_EN_SHIFT);
-	reg_val |= ((pdata->tx_pin_en & 0x01) << TX_PIN_EN_SHIFT);
-
-	ret = regmap_write(chip->regmap, REG_ENABLE, reg_val);
-	if (ret < 0) {
-		dev_err(chip->dev, "Failed to write REG_ENABLE Regisgter\n");
-		goto out;
-	}
-
-out:
-	return ret;
-}
-
-/* chip control */
-static int lm3556_control(struct lm3556_chip_data *chip,
-			  u8 brightness, enum lm3556_mode opmode)
-{
-	int ret;
-	struct lm3556_platform_data *pdata = chip->pdata;
-
-	ret = regmap_read(chip->regmap, REG_FLAG, &chip->last_flag);
-	if (ret < 0) {
-		dev_err(chip->dev, "Failed to read REG_FLAG Register\n");
-		goto out;
-	}
-
-	if (chip->last_flag)
-		dev_info(chip->dev, "Last FLAG is 0x%x\n", chip->last_flag);
-
-	/* brightness 0 means off-state */
-	if (!brightness)
-		opmode = MODES_STASNDBY;
-
-	switch (opmode) {
-	case MODES_TORCH:
-		ret = regmap_update_bits(chip->regmap, REG_I_CTRL,
-					 TORCH_I_MASK << TORCH_I_SHIFT,
-					 (brightness - 1) << TORCH_I_SHIFT);
-
-		if (pdata->torch_pin_en)
-			opmode |= (TORCH_PIN_EN_MASK << TORCH_PIN_EN_SHIFT);
-		break;
-
-	case MODES_FLASH:
-		ret = regmap_update_bits(chip->regmap, REG_I_CTRL,
-					 FLASH_I_MASK << FLASH_I_SHIFT,
-					 (brightness - 1) << FLASH_I_SHIFT);
-		break;
-
-	case MODES_INDIC:
-		ret = regmap_update_bits(chip->regmap, REG_I_CTRL,
-					 TORCH_I_MASK << TORCH_I_SHIFT,
-					 (brightness - 1) << TORCH_I_SHIFT);
-		break;
-
-	case MODES_STASNDBY:
-		if (pdata->torch_pin_en)
-			opmode |= (TORCH_PIN_EN_MASK << TORCH_PIN_EN_SHIFT);
-		break;
-
-	default:
-		return ret;
-	}
-	if (ret < 0) {
-		dev_err(chip->dev, "Failed to write REG_I_CTRL Register\n");
-		goto out;
-	}
-	ret = regmap_update_bits(chip->regmap, REG_ENABLE,
-				 MODE_BITS_MASK << MODE_BITS_SHIFT,
-				 opmode << MODE_BITS_SHIFT);
-
-out:
-	return ret;
-}
-
-/* torch */
-static void lm3556_torch_brightness_set(struct led_classdev *cdev,
-					enum led_brightness brightness)
-{
-	struct lm3556_chip_data *chip =
-	    container_of(cdev, struct lm3556_chip_data, cdev_torch);
-
-	mutex_lock(&chip->lock);
-	lm3556_control(chip, brightness, MODES_TORCH);
-	mutex_unlock(&chip->lock);
-}
-
-/* flash */
-static void lm3556_strobe_brightness_set(struct led_classdev *cdev,
-					 enum led_brightness brightness)
-{
-	struct lm3556_chip_data *chip =
-	    container_of(cdev, struct lm3556_chip_data, cdev_flash);
-
-	mutex_lock(&chip->lock);
-	lm3556_control(chip, brightness, MODES_FLASH);
-	mutex_unlock(&chip->lock);
-}
-
-/* indicator */
-static void lm3556_indicator_brightness_set(struct led_classdev *cdev,
-					    enum led_brightness brightness)
-{
-	struct lm3556_chip_data *chip =
-	    container_of(cdev, struct lm3556_chip_data, cdev_indicator);
-
-	mutex_lock(&chip->lock);
-	lm3556_control(chip, brightness, MODES_INDIC);
-	mutex_unlock(&chip->lock);
-}
-
-/* indicator pattern */
-static ssize_t lm3556_indicator_pattern_store(struct device *dev,
-					      struct device_attribute *devAttr,
-					      const char *buf, size_t size)
-{
-	ssize_t ret;
-	struct led_classdev *led_cdev = dev_get_drvdata(dev);
-	struct lm3556_chip_data *chip =
-	    container_of(led_cdev, struct lm3556_chip_data, cdev_indicator);
-	unsigned int state;
-
-	ret = kstrtouint(buf, 10, &state);
-	if (ret)
-		goto out;
-	if (state > INDIC_PATTERN_SIZE - 1)
-		state = INDIC_PATTERN_SIZE - 1;
-
-	ret = regmap_write(chip->regmap, REG_INDIC_BLINK,
-			   indicator_pattern[state].blinking);
-	if (ret < 0) {
-		dev_err(chip->dev, "Failed to write REG_ENABLE Regisgter\n");
-		goto out;
-	}
-
-	ret = regmap_write(chip->regmap, REG_INDIC_PERIOD,
-			   indicator_pattern[state].period_cnt);
-	if (ret < 0) {
-		dev_err(chip->dev, "Failed to write REG_ENABLE Regisgter\n");
-		goto out;
-	}
-
-	return size;
-out:
-	dev_err(chip->dev, "Indicator pattern doesn't saved\n");
-	return size;
-}
-
-static DEVICE_ATTR(pattern, 0666, NULL, lm3556_indicator_pattern_store);
-
-static const struct regmap_config lm3556_regmap = {
-	.reg_bits = 8,
-	.val_bits = 8,
-	.max_register = REG_MAX,
-};
-
-/* module initialize */
-static int __devinit lm3556_probe(struct i2c_client *client,
-				  const struct i2c_device_id *id)
-{
-	struct lm3556_platform_data *pdata = client->dev.platform_data;
-	struct lm3556_chip_data *chip;
-
-	int err;
-
-	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
-		dev_err(&client->dev, "i2c functionality check fail.\n");
-		return -EOPNOTSUPP;
-	}
-
-	if (pdata == NULL) {
-		dev_err(&client->dev, "Needs Platform Data.\n");
-		return -ENODATA;
-	}
-
-	chip =
-	    devm_kzalloc(&client->dev, sizeof(struct lm3556_chip_data),
-			 GFP_KERNEL);
-	if (!chip)
-		return -ENOMEM;
-
-	chip->dev = &client->dev;
-	chip->pdata = pdata;
-
-	chip->regmap = devm_regmap_init_i2c(client, &lm3556_regmap);
-	if (IS_ERR(chip->regmap)) {
-		err = PTR_ERR(chip->regmap);
-		dev_err(&client->dev, "Failed to allocate register map: %d\n",
-			err);
-		return err;
-	}
-
-	mutex_init(&chip->lock);
-	i2c_set_clientdata(client, chip);
-
-	err = lm3556_chip_init(chip);
-	if (err < 0)
-		goto err_out;
-
-	/* flash */
-	chip->cdev_flash.name = "flash";
-	chip->cdev_flash.max_brightness = 16;
-	chip->cdev_flash.brightness_set = lm3556_strobe_brightness_set;
-	err = led_classdev_register((struct device *)
-				    &client->dev, &chip->cdev_flash);
-	if (err < 0)
-		goto err_out;
-	/* torch */
-	chip->cdev_torch.name = "torch";
-	chip->cdev_torch.max_brightness = 8;
-	chip->cdev_torch.brightness_set = lm3556_torch_brightness_set;
-	err = led_classdev_register((struct device *)
-				    &client->dev, &chip->cdev_torch);
-	if (err < 0)
-		goto err_create_torch_file;
-	/* indicator */
-	chip->cdev_indicator.name = "indicator";
-	chip->cdev_indicator.max_brightness = 8;
-	chip->cdev_indicator.brightness_set = lm3556_indicator_brightness_set;
-	err = led_classdev_register((struct device *)
-				    &client->dev, &chip->cdev_indicator);
-	if (err < 0)
-		goto err_create_indicator_file;
-
-	err = device_create_file(chip->cdev_indicator.dev, &dev_attr_pattern);
-	if (err < 0)
-		goto err_create_pattern_file;
-
-	dev_info(&client->dev, "LM3556 is initialized\n");
-	return 0;
-
-err_create_pattern_file:
-	led_classdev_unregister(&chip->cdev_indicator);
-err_create_indicator_file:
-	led_classdev_unregister(&chip->cdev_torch);
-err_create_torch_file:
-	led_classdev_unregister(&chip->cdev_flash);
-err_out:
-	return err;
-}
-
-static int __devexit lm3556_remove(struct i2c_client *client)
-{
-	struct lm3556_chip_data *chip = i2c_get_clientdata(client);
-
-	device_remove_file(chip->cdev_indicator.dev, &dev_attr_pattern);
-	led_classdev_unregister(&chip->cdev_indicator);
-	led_classdev_unregister(&chip->cdev_torch);
-	led_classdev_unregister(&chip->cdev_flash);
-	regmap_write(chip->regmap, REG_ENABLE, 0);
-	return 0;
-}
-
-static const struct i2c_device_id lm3556_id[] = {
-	{LM3556_NAME, 0},
-	{}
-};
-
-MODULE_DEVICE_TABLE(i2c, lm3556_id);
-
-static struct i2c_driver lm3556_i2c_driver = {
-	.driver = {
-		   .name = LM3556_NAME,
-		   .owner = THIS_MODULE,
-		   .pm = NULL,
-		   },
-	.probe = lm3556_probe,
-	.remove = __devexit_p(lm3556_remove),
-	.id_table = lm3556_id,
-};
-
-module_i2c_driver(lm3556_i2c_driver);
-
-MODULE_DESCRIPTION("Texas Instruments Flash Lighting driver for LM3556");
-MODULE_AUTHOR("Daniel Jeong <daniel.jeong@ti.com>");
-MODULE_AUTHOR("G.Shark Jeong <gshark.jeong@gmail.com>");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/leds/leds-lm355x.c b/drivers/leds/leds-lm355x.c
new file mode 100644
index 0000000..065ec01
--- /dev/null
+++ b/drivers/leds/leds-lm355x.c
@@ -0,0 +1,572 @@
+/*
+* Simple driver for Texas Instruments LM355x LED Flash driver chip
+* Copyright (C) 2012 Texas Instruments
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 as
+* published by the Free Software Foundation.
+*/
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/leds.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/fs.h>
+#include <linux/regmap.h>
+#include <linux/workqueue.h>
+#include <linux/platform_data/leds-lm355x.h>
+
+enum lm355x_type {
+	CHIP_LM3554 = 0,
+	CHIP_LM3556,
+};
+
+enum lm355x_regs {
+	REG_FLAG = 0,
+	REG_TORCH_CFG,
+	REG_TORCH_CTRL,
+	REG_STROBE_CFG,
+	REG_FLASH_CTRL,
+	REG_INDI_CFG,
+	REG_INDI_CTRL,
+	REG_OPMODE,
+	REG_MAX,
+};
+
+/* operation mode */
+enum lm355x_mode {
+	MODE_SHDN = 0,
+	MODE_INDIC,
+	MODE_TORCH,
+	MODE_FLASH
+};
+
+/* register map info. */
+struct lm355x_reg_data {
+	u8 regno;
+	u8 mask;
+	u8 shift;
+};
+
+struct lm355x_chip_data {
+	struct device *dev;
+	enum lm355x_type type;
+
+	struct led_classdev cdev_flash;
+	struct led_classdev cdev_torch;
+	struct led_classdev cdev_indicator;
+
+	struct work_struct work_flash;
+	struct work_struct work_torch;
+	struct work_struct work_indicator;
+
+	u8 br_flash;
+	u8 br_torch;
+	u8 br_indicator;
+
+	struct lm355x_platform_data *pdata;
+	struct regmap *regmap;
+	struct mutex lock;
+
+	unsigned int last_flag;
+	struct lm355x_reg_data *regs;
+};
+
+/* specific indicator function for lm3556 */
+enum lm3556_indic_pulse_time {
+	PULSE_TIME_0_MS = 0,
+	PULSE_TIME_32_MS,
+	PULSE_TIME_64_MS,
+	PULSE_TIME_92_MS,
+	PULSE_TIME_128_MS,
+	PULSE_TIME_160_MS,
+	PULSE_TIME_196_MS,
+	PULSE_TIME_224_MS,
+	PULSE_TIME_256_MS,
+	PULSE_TIME_288_MS,
+	PULSE_TIME_320_MS,
+	PULSE_TIME_352_MS,
+	PULSE_TIME_384_MS,
+	PULSE_TIME_416_MS,
+	PULSE_TIME_448_MS,
+	PULSE_TIME_480_MS,
+};
+
+enum lm3556_indic_n_blank {
+	INDIC_N_BLANK_0 = 0,
+	INDIC_N_BLANK_1,
+	INDIC_N_BLANK_2,
+	INDIC_N_BLANK_3,
+	INDIC_N_BLANK_4,
+	INDIC_N_BLANK_5,
+	INDIC_N_BLANK_6,
+	INDIC_N_BLANK_7,
+	INDIC_N_BLANK_8,
+	INDIC_N_BLANK_9,
+	INDIC_N_BLANK_10,
+	INDIC_N_BLANK_11,
+	INDIC_N_BLANK_12,
+	INDIC_N_BLANK_13,
+	INDIC_N_BLANK_14,
+	INDIC_N_BLANK_15,
+};
+
+enum lm3556_indic_period {
+	INDIC_PERIOD_0 = 0,
+	INDIC_PERIOD_1,
+	INDIC_PERIOD_2,
+	INDIC_PERIOD_3,
+	INDIC_PERIOD_4,
+	INDIC_PERIOD_5,
+	INDIC_PERIOD_6,
+	INDIC_PERIOD_7,
+};
+
+#define INDIC_PATTERN_SIZE 4
+
+struct indicator {
+	u8 blinking;
+	u8 period_cnt;
+};
+
+/* indicator pattern data only for lm3556 */
+static struct indicator indicator_pattern[INDIC_PATTERN_SIZE] = {
+	[0] = {(INDIC_N_BLANK_1 << 4) | PULSE_TIME_32_MS, INDIC_PERIOD_1},
+	[1] = {(INDIC_N_BLANK_15 << 4) | PULSE_TIME_32_MS, INDIC_PERIOD_2},
+	[2] = {(INDIC_N_BLANK_10 << 4) | PULSE_TIME_32_MS, INDIC_PERIOD_4},
+	[3] = {(INDIC_N_BLANK_5 << 4) | PULSE_TIME_32_MS, INDIC_PERIOD_7},
+};
+
+static struct lm355x_reg_data lm3554_regs[REG_MAX] = {
+	[REG_FLAG] = {0xD0, 0xBF, 0},
+	[REG_TORCH_CFG] = {0xE0, 0x80, 7},
+	[REG_TORCH_CTRL] = {0xA0, 0x38, 3},
+	[REG_STROBE_CFG] = {0xE0, 0x04, 2},
+	[REG_FLASH_CTRL] = {0xB0, 0x78, 3},
+	[REG_INDI_CFG] = {0xE0, 0x08, 3},
+	[REG_INDI_CTRL] = {0xA0, 0xC0, 6},
+	[REG_OPMODE] = {0xA0, 0x03, 0},
+};
+
+static struct lm355x_reg_data lm3556_regs[REG_MAX] = {
+	[REG_FLAG] = {0x0B, 0xFF, 0},
+	[REG_TORCH_CFG] = {0x0A, 0x10, 4},
+	[REG_TORCH_CTRL] = {0x09, 0x70, 4},
+	[REG_STROBE_CFG] = {0x0A, 0x20, 5},
+	[REG_FLASH_CTRL] = {0x09, 0x0F, 0},
+	[REG_INDI_CFG] = {0xFF, 0xFF, 0},
+	[REG_INDI_CTRL] = {0x09, 0x70, 4},
+	[REG_OPMODE] = {0x0A, 0x03, 0},
+};
+
+static char lm355x_name[][I2C_NAME_SIZE] = {
+	[CHIP_LM3554] = LM3554_NAME,
+	[CHIP_LM3556] = LM3556_NAME,
+};
+
+/* chip initialize */
+static int __devinit lm355x_chip_init(struct lm355x_chip_data *chip)
+{
+	int ret;
+	unsigned int reg_val;
+	struct lm355x_platform_data *pdata = chip->pdata;
+
+	/* input and output pins configuration */
+	switch (chip->type) {
+	case CHIP_LM3554:
+		reg_val = pdata->pin_tx2 | pdata->ntc_pin;
+		ret = regmap_update_bits(chip->regmap, 0xE0, 0x28, reg_val);
+		if (ret < 0)
+			goto out;
+		reg_val = pdata->pass_mode;
+		ret = regmap_update_bits(chip->regmap, 0xA0, 0x04, reg_val);
+		if (ret < 0)
+			goto out;
+		break;
+
+	case CHIP_LM3556:
+		reg_val = pdata->pin_tx2 | pdata->ntc_pin | pdata->pass_mode;
+		ret = regmap_update_bits(chip->regmap, 0x0A, 0xC4, reg_val);
+		if (ret < 0)
+			goto out;
+		break;
+	default:
+		return -ENODATA;
+	}
+
+	return ret;
+out:
+	dev_err(chip->dev, "%s:i2c access fail to register\n", __func__);
+	return ret;
+}
+
+/* chip control */
+static void lm355x_control(struct lm355x_chip_data *chip,
+			   u8 brightness, enum lm355x_mode opmode)
+{
+	int ret;
+	unsigned int reg_val;
+	struct lm355x_platform_data *pdata = chip->pdata;
+	struct lm355x_reg_data *preg = chip->regs;
+
+	ret = regmap_read(chip->regmap, preg[REG_FLAG].regno, &chip->last_flag);
+	if (ret < 0)
+		goto out;
+	if (chip->last_flag & preg[REG_FLAG].mask)
+		dev_info(chip->dev, "%s Last FLAG is 0x%x\n",
+			 lm355x_name[chip->type],
+			 chip->last_flag & preg[REG_FLAG].mask);
+	/* brightness 0 means shutdown */
+	if (!brightness)
+		opmode = MODE_SHDN;
+
+	switch (opmode) {
+	case MODE_TORCH:
+		ret =
+		    regmap_update_bits(chip->regmap, preg[REG_TORCH_CTRL].regno,
+				       preg[REG_TORCH_CTRL].mask,
+				       (brightness - 1)
+				       << preg[REG_TORCH_CTRL].shift);
+		if (ret < 0)
+			goto out;
+
+		if (pdata->pin_tx1 != LM355x_PIN_TORCH_DISABLE) {
+			ret =
+			    regmap_update_bits(chip->regmap,
+					       preg[REG_TORCH_CFG].regno,
+					       preg[REG_TORCH_CFG].mask,
+					       0x01 <<
+					       preg[REG_TORCH_CFG].shift);
+			if (ret < 0)
+				goto out;
+			opmode = MODE_SHDN;
+			dev_info(chip->dev,
+				 "torch brt is set - ext. torch pin mode\n");
+		}
+		break;
+
+	case MODE_FLASH:
+
+		ret =
+		    regmap_update_bits(chip->regmap, preg[REG_FLASH_CTRL].regno,
+				       preg[REG_FLASH_CTRL].mask,
+				       (brightness - 1)
+				       << preg[REG_FLASH_CTRL].shift);
+		if (ret < 0)
+			goto out;
+
+		if (pdata->pin_strobe != LM355x_PIN_STROBE_DISABLE) {
+			if (chip->type == CHIP_LM3554)
+				reg_val = 0x00;
+			else
+				reg_val = 0x01;
+			ret =
+			    regmap_update_bits(chip->regmap,
+					       preg[REG_STROBE_CFG].regno,
+					       preg[REG_STROBE_CFG].mask,
+					       reg_val <<
+					       preg[REG_STROBE_CFG].shift);
+			if (ret < 0)
+				goto out;
+			opmode = MODE_SHDN;
+			dev_info(chip->dev,
+				 "flash brt is set - ext. strobe pin mode\n");
+		}
+		break;
+
+	case MODE_INDIC:
+		ret =
+		    regmap_update_bits(chip->regmap, preg[REG_INDI_CTRL].regno,
+				       preg[REG_INDI_CTRL].mask,
+				       (brightness - 1)
+				       << preg[REG_INDI_CTRL].shift);
+		if (ret < 0)
+			goto out;
+
+		if (pdata->pin_tx2 != LM355x_PIN_TX_DISABLE) {
+			ret =
+			    regmap_update_bits(chip->regmap,
+					       preg[REG_INDI_CFG].regno,
+					       preg[REG_INDI_CFG].mask,
+					       0x01 <<
+					       preg[REG_INDI_CFG].shift);
+			if (ret < 0)
+				goto out;
+			opmode = MODE_SHDN;
+		}
+		break;
+	case MODE_SHDN:
+		break;
+	default:
+		return;
+	}
+	/* operation mode control */
+	ret = regmap_update_bits(chip->regmap, preg[REG_OPMODE].regno,
+				 preg[REG_OPMODE].mask,
+				 opmode << preg[REG_OPMODE].shift);
+	if (ret < 0)
+		goto out;
+	return;
+out:
+	dev_err(chip->dev, "%s:i2c access fail to register\n", __func__);
+	return;
+}
+
+/* torch */
+static void lm355x_deferred_torch_brightness_set(struct work_struct *work)
+{
+	struct lm355x_chip_data *chip =
+	    container_of(work, struct lm355x_chip_data, work_torch);
+
+	mutex_lock(&chip->lock);
+	lm355x_control(chip, chip->br_torch, MODE_TORCH);
+	mutex_unlock(&chip->lock);
+}
+
+static void lm355x_torch_brightness_set(struct led_classdev *cdev,
+					enum led_brightness brightness)
+{
+	struct lm355x_chip_data *chip =
+	    container_of(cdev, struct lm355x_chip_data, cdev_torch);
+
+	chip->br_torch = brightness;
+	schedule_work(&chip->work_torch);
+}
+
+/* flash */
+static void lm355x_deferred_strobe_brightness_set(struct work_struct *work)
+{
+	struct lm355x_chip_data *chip =
+	    container_of(work, struct lm355x_chip_data, work_flash);
+
+	mutex_lock(&chip->lock);
+	lm355x_control(chip, chip->br_flash, MODE_FLASH);
+	mutex_unlock(&chip->lock);
+}
+
+static void lm355x_strobe_brightness_set(struct led_classdev *cdev,
+					 enum led_brightness brightness)
+{
+	struct lm355x_chip_data *chip =
+	    container_of(cdev, struct lm355x_chip_data, cdev_flash);
+
+	chip->br_flash = brightness;
+	schedule_work(&chip->work_flash);
+}
+
+/* indicator */
+static void lm355x_deferred_indicator_brightness_set(struct work_struct *work)
+{
+	struct lm355x_chip_data *chip =
+	    container_of(work, struct lm355x_chip_data, work_indicator);
+
+	mutex_lock(&chip->lock);
+	lm355x_control(chip, chip->br_indicator, MODE_INDIC);
+	mutex_unlock(&chip->lock);
+}
+
+static void lm355x_indicator_brightness_set(struct led_classdev *cdev,
+					    enum led_brightness brightness)
+{
+	struct lm355x_chip_data *chip =
+	    container_of(cdev, struct lm355x_chip_data, cdev_indicator);
+
+	chip->br_indicator = brightness;
+	schedule_work(&chip->work_indicator);
+}
+
+/* indicator pattern only for lm3556*/
+static ssize_t lm3556_indicator_pattern_store(struct device *dev,
+					      struct device_attribute *devAttr,
+					      const char *buf, size_t size)
+{
+	ssize_t ret;
+	struct led_classdev *led_cdev = dev_get_drvdata(dev);
+	struct lm355x_chip_data *chip =
+	    container_of(led_cdev, struct lm355x_chip_data, cdev_indicator);
+	unsigned int state;
+
+	ret = kstrtouint(buf, 10, &state);
+	if (ret)
+		goto out;
+	if (state > INDIC_PATTERN_SIZE - 1)
+		state = INDIC_PATTERN_SIZE - 1;
+
+	ret = regmap_write(chip->regmap, 0x04,
+			   indicator_pattern[state].blinking);
+	if (ret < 0)
+		goto out;
+
+	ret = regmap_write(chip->regmap, 0x05,
+			   indicator_pattern[state].period_cnt);
+	if (ret < 0)
+		goto out;
+
+	return size;
+out:
+	dev_err(chip->dev, "%s:i2c access fail to register\n", __func__);
+	return size;
+}
+
+static DEVICE_ATTR(pattern, 0666, NULL, lm3556_indicator_pattern_store);
+
+static const struct regmap_config lm355x_regmap = {
+	.reg_bits = 8,
+	.val_bits = 8,
+	.max_register = 0xFF,
+};
+
+/* module initialize */
+static int __devinit lm355x_probe(struct i2c_client *client,
+				  const struct i2c_device_id *id)
+{
+	struct lm355x_platform_data *pdata = client->dev.platform_data;
+	struct lm355x_chip_data *chip;
+
+	int err;
+
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+		dev_err(&client->dev, "i2c functionality check fail.\n");
+		return -EOPNOTSUPP;
+	}
+
+	if (pdata == NULL) {
+		dev_err(&client->dev, "needs Platform Data.\n");
+		return -ENODATA;
+	}
+
+	chip = devm_kzalloc(&client->dev,
+			    sizeof(struct lm355x_chip_data), GFP_KERNEL);
+	if (!chip)
+		return -ENOMEM;
+
+	chip->dev = &client->dev;
+	chip->type = id->driver_data;
+	switch (id->driver_data) {
+	case CHIP_LM3554:
+		chip->regs = lm3554_regs;
+		break;
+	case CHIP_LM3556:
+		chip->regs = lm3556_regs;
+		break;
+	default:
+		return -ENOSYS;
+	}
+	chip->pdata = pdata;
+
+	chip->regmap = devm_regmap_init_i2c(client, &lm355x_regmap);
+	if (IS_ERR(chip->regmap)) {
+		err = PTR_ERR(chip->regmap);
+		dev_err(&client->dev,
+			"Failed to allocate register map: %d\n", err);
+		return err;
+	}
+
+	mutex_init(&chip->lock);
+	i2c_set_clientdata(client, chip);
+
+	err = lm355x_chip_init(chip);
+	if (err < 0)
+		goto err_out;
+
+	/* flash */
+	INIT_WORK(&chip->work_flash, lm355x_deferred_strobe_brightness_set);
+	chip->cdev_flash.name = "flash";
+	chip->cdev_flash.max_brightness = 16;
+	chip->cdev_flash.brightness_set = lm355x_strobe_brightness_set;
+	err = led_classdev_register((struct device *)
+				    &client->dev, &chip->cdev_flash);
+	if (err < 0)
+		goto err_out;
+	/* torch */
+	INIT_WORK(&chip->work_torch, lm355x_deferred_torch_brightness_set);
+	chip->cdev_torch.name = "torch";
+	chip->cdev_torch.max_brightness = 8;
+	chip->cdev_torch.brightness_set = lm355x_torch_brightness_set;
+	err = led_classdev_register((struct device *)
+				    &client->dev, &chip->cdev_torch);
+	if (err < 0)
+		goto err_create_torch_file;
+	/* indicator */
+	INIT_WORK(&chip->work_indicator,
+		  lm355x_deferred_indicator_brightness_set);
+	chip->cdev_indicator.name = "indicator";
+	if (id->driver_data == CHIP_LM3554)
+		chip->cdev_indicator.max_brightness = 4;
+	else
+		chip->cdev_indicator.max_brightness = 8;
+	chip->cdev_indicator.brightness_set = lm355x_indicator_brightness_set;
+	err = led_classdev_register((struct device *)
+				    &client->dev, &chip->cdev_indicator);
+	if (err < 0)
+		goto err_create_indicator_file;
+	/* indicator pattern control only for LM3554 */
+	if (id->driver_data == CHIP_LM3556) {
+		err =
+		    device_create_file(chip->cdev_indicator.dev,
+				       &dev_attr_pattern);
+		if (err < 0)
+			goto err_create_pattern_file;
+	}
+
+	dev_info(&client->dev, "%s is initialized\n",
+		 lm355x_name[id->driver_data]);
+	return 0;
+
+err_create_pattern_file:
+	led_classdev_unregister(&chip->cdev_indicator);
+err_create_indicator_file:
+	led_classdev_unregister(&chip->cdev_torch);
+err_create_torch_file:
+	led_classdev_unregister(&chip->cdev_flash);
+err_out:
+	return err;
+}
+
+static int __devexit lm355x_remove(struct i2c_client *client)
+{
+	struct lm355x_chip_data *chip = i2c_get_clientdata(client);
+	struct lm355x_reg_data *preg = chip->regs;
+
+	regmap_write(chip->regmap, preg[REG_OPMODE].regno, 0);
+	if (chip->type == CHIP_LM3556)
+		device_remove_file(chip->cdev_indicator.dev, &dev_attr_pattern);
+	led_classdev_unregister(&chip->cdev_indicator);
+	flush_work(&chip->work_indicator);
+	led_classdev_unregister(&chip->cdev_torch);
+	flush_work(&chip->work_torch);
+	led_classdev_unregister(&chip->cdev_flash);
+	flush_work(&chip->work_flash);
+	dev_info(&client->dev, "%s is removed\n", lm355x_name[chip->type]);
+
+	return 0;
+}
+
+static const struct i2c_device_id lm355x_id[] = {
+	{LM3554_NAME, CHIP_LM3554},
+	{LM3556_NAME, CHIP_LM3556},
+	{}
+};
+
+MODULE_DEVICE_TABLE(i2c, lm355x_id);
+
+static struct i2c_driver lm355x_i2c_driver = {
+	.driver = {
+		   .name = LM355x_NAME,
+		   .owner = THIS_MODULE,
+		   .pm = NULL,
+		   },
+	.probe = lm355x_probe,
+	.remove = __devexit_p(lm355x_remove),
+	.id_table = lm355x_id,
+};
+
+module_i2c_driver(lm355x_i2c_driver);
+
+MODULE_DESCRIPTION("Texas Instruments Flash Lighting driver for LM355x");
+MODULE_AUTHOR("Daniel Jeong <daniel.jeong@ti.com>");
+MODULE_AUTHOR("G.Shark Jeong <gshark.jeong@gmail.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/leds/leds-lm3642.c b/drivers/leds/leds-lm3642.c
new file mode 100644
index 0000000..3285006
--- /dev/null
+++ b/drivers/leds/leds-lm3642.c
@@ -0,0 +1,462 @@
+/*
+* Simple driver for Texas Instruments LM3642 LED Flash driver chip
+* Copyright (C) 2012 Texas Instruments
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 as
+* published by the Free Software Foundation.
+*
+*/
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/leds.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/fs.h>
+#include <linux/regmap.h>
+#include <linux/workqueue.h>
+#include <linux/platform_data/leds-lm3642.h>
+
+#define	REG_FILT_TIME			(0x0)
+#define	REG_IVFM_MODE			(0x1)
+#define	REG_TORCH_TIME			(0x6)
+#define	REG_FLASH			(0x8)
+#define	REG_I_CTRL			(0x9)
+#define	REG_ENABLE			(0xA)
+#define	REG_FLAG			(0xB)
+#define	REG_MAX				(0xB)
+
+#define	UVLO_EN_SHIFT			(7)
+#define	IVM_D_TH_SHIFT			(2)
+#define	TORCH_RAMP_UP_TIME_SHIFT	(3)
+#define	TORCH_RAMP_DN_TIME_SHIFT	(0)
+#define	INDUCTOR_I_LIMIT_SHIFT		(6)
+#define	FLASH_RAMP_TIME_SHIFT		(3)
+#define	FLASH_TOUT_TIME_SHIFT		(0)
+#define	TORCH_I_SHIFT			(4)
+#define	FLASH_I_SHIFT			(0)
+#define	IVFM_SHIFT			(7)
+#define	TX_PIN_EN_SHIFT			(6)
+#define	STROBE_PIN_EN_SHIFT		(5)
+#define	TORCH_PIN_EN_SHIFT		(4)
+#define	MODE_BITS_SHIFT			(0)
+
+#define	UVLO_EN_MASK			(0x1)
+#define	IVM_D_TH_MASK			(0x7)
+#define	TORCH_RAMP_UP_TIME_MASK		(0x7)
+#define	TORCH_RAMP_DN_TIME_MASK		(0x7)
+#define	INDUCTOR_I_LIMIT_MASK		(0x1)
+#define	FLASH_RAMP_TIME_MASK		(0x7)
+#define	FLASH_TOUT_TIME_MASK		(0x7)
+#define	TORCH_I_MASK			(0x7)
+#define	FLASH_I_MASK			(0xF)
+#define	IVFM_MASK			(0x1)
+#define	TX_PIN_EN_MASK			(0x1)
+#define	STROBE_PIN_EN_MASK		(0x1)
+#define	TORCH_PIN_EN_MASK		(0x1)
+#define	MODE_BITS_MASK			(0x73)
+#define EX_PIN_CONTROL_MASK		(0x71)
+#define EX_PIN_ENABLE_MASK		(0x70)
+
+enum lm3642_mode {
+	MODES_STASNDBY = 0,
+	MODES_INDIC,
+	MODES_TORCH,
+	MODES_FLASH
+};
+
+struct lm3642_chip_data {
+	struct device *dev;
+
+	struct led_classdev cdev_flash;
+	struct led_classdev cdev_torch;
+	struct led_classdev cdev_indicator;
+
+	struct work_struct work_flash;
+	struct work_struct work_torch;
+	struct work_struct work_indicator;
+
+	u8 br_flash;
+	u8 br_torch;
+	u8 br_indicator;
+
+	enum lm3642_torch_pin_enable torch_pin;
+	enum lm3642_strobe_pin_enable strobe_pin;
+	enum lm3642_tx_pin_enable tx_pin;
+
+	struct lm3642_platform_data *pdata;
+	struct regmap *regmap;
+	struct mutex lock;
+
+	unsigned int last_flag;
+};
+
+/* chip initialize */
+static int __devinit lm3642_chip_init(struct lm3642_chip_data *chip)
+{
+	int ret;
+	struct lm3642_platform_data *pdata = chip->pdata;
+
+	/* set enable register */
+	ret = regmap_update_bits(chip->regmap, REG_ENABLE, EX_PIN_ENABLE_MASK,
+				 pdata->tx_pin);
+	if (ret < 0)
+		dev_err(chip->dev, "Failed to update REG_ENABLE Register\n");
+	return ret;
+}
+
+/* chip control */
+static int lm3642_control(struct lm3642_chip_data *chip,
+			  u8 brightness, enum lm3642_mode opmode)
+{
+	int ret;
+
+	ret = regmap_read(chip->regmap, REG_FLAG, &chip->last_flag);
+	if (ret < 0) {
+		dev_err(chip->dev, "Failed to read REG_FLAG Register\n");
+		goto out;
+	}
+
+	if (chip->last_flag)
+		dev_info(chip->dev, "Last FLAG is 0x%x\n", chip->last_flag);
+
+	/* brightness 0 means off-state */
+	if (!brightness)
+		opmode = MODES_STASNDBY;
+
+	switch (opmode) {
+	case MODES_TORCH:
+		ret = regmap_update_bits(chip->regmap, REG_I_CTRL,
+					 TORCH_I_MASK << TORCH_I_SHIFT,
+					 (brightness - 1) << TORCH_I_SHIFT);
+
+		if (chip->torch_pin)
+			opmode |= (TORCH_PIN_EN_MASK << TORCH_PIN_EN_SHIFT);
+		break;
+
+	case MODES_FLASH:
+		ret = regmap_update_bits(chip->regmap, REG_I_CTRL,
+					 FLASH_I_MASK << FLASH_I_SHIFT,
+					 (brightness - 1) << FLASH_I_SHIFT);
+
+		if (chip->strobe_pin)
+			opmode |= (STROBE_PIN_EN_MASK << STROBE_PIN_EN_SHIFT);
+		break;
+
+	case MODES_INDIC:
+		ret = regmap_update_bits(chip->regmap, REG_I_CTRL,
+					 TORCH_I_MASK << TORCH_I_SHIFT,
+					 (brightness - 1) << TORCH_I_SHIFT);
+		break;
+
+	case MODES_STASNDBY:
+
+		break;
+
+	default:
+		return ret;
+	}
+	if (ret < 0) {
+		dev_err(chip->dev, "Failed to write REG_I_CTRL Register\n");
+		goto out;
+	}
+
+	if (chip->tx_pin)
+		opmode |= (TX_PIN_EN_MASK << TX_PIN_EN_SHIFT);
+
+	ret = regmap_update_bits(chip->regmap, REG_ENABLE,
+				 MODE_BITS_MASK << MODE_BITS_SHIFT,
+				 opmode << MODE_BITS_SHIFT);
+out:
+	return ret;
+}
+
+/* torch */
+
+/* torch pin config for lm3642*/
+static ssize_t lm3642_torch_pin_store(struct device *dev,
+				      struct device_attribute *devAttr,
+				      const char *buf, size_t size)
+{
+	ssize_t ret;
+	struct led_classdev *led_cdev = dev_get_drvdata(dev);
+	struct lm3642_chip_data *chip =
+	    container_of(led_cdev, struct lm3642_chip_data, cdev_indicator);
+	unsigned int state;
+
+	ret = kstrtouint(buf, 10, &state);
+	if (ret)
+		goto out_strtoint;
+	if (state != 0)
+		state = 0x01 << TORCH_PIN_EN_SHIFT;
+
+	chip->torch_pin = state;
+	ret = regmap_update_bits(chip->regmap, REG_ENABLE,
+				 TORCH_PIN_EN_MASK << TORCH_PIN_EN_SHIFT,
+				 state);
+	if (ret < 0)
+		goto out;
+
+	return size;
+out:
+	dev_err(chip->dev, "%s:i2c access fail to register\n", __func__);
+	return size;
+out_strtoint:
+	dev_err(chip->dev, "%s: fail to change str to int\n", __func__);
+	return size;
+}
+
+static DEVICE_ATTR(torch_pin, 0666, NULL, lm3642_torch_pin_store);
+
+static void lm3642_deferred_torch_brightness_set(struct work_struct *work)
+{
+	struct lm3642_chip_data *chip =
+	    container_of(work, struct lm3642_chip_data, work_torch);
+
+	mutex_lock(&chip->lock);
+	lm3642_control(chip, chip->br_torch, MODES_TORCH);
+	mutex_unlock(&chip->lock);
+}
+
+static void lm3642_torch_brightness_set(struct led_classdev *cdev,
+					enum led_brightness brightness)
+{
+	struct lm3642_chip_data *chip =
+	    container_of(cdev, struct lm3642_chip_data, cdev_torch);
+
+	chip->br_torch = brightness;
+	schedule_work(&chip->work_torch);
+}
+
+/* flash */
+
+/* strobe pin config for lm3642*/
+static ssize_t lm3642_strobe_pin_store(struct device *dev,
+				       struct device_attribute *devAttr,
+				       const char *buf, size_t size)
+{
+	ssize_t ret;
+	struct led_classdev *led_cdev = dev_get_drvdata(dev);
+	struct lm3642_chip_data *chip =
+	    container_of(led_cdev, struct lm3642_chip_data, cdev_indicator);
+	unsigned int state;
+
+	ret = kstrtouint(buf, 10, &state);
+	if (ret)
+		goto out_strtoint;
+	if (state != 0)
+		state = 0x01 << STROBE_PIN_EN_SHIFT;
+
+	chip->strobe_pin = state;
+	ret = regmap_update_bits(chip->regmap, REG_ENABLE,
+				 STROBE_PIN_EN_MASK << STROBE_PIN_EN_SHIFT,
+				 state);
+	if (ret < 0)
+		goto out;
+
+	return size;
+out:
+	dev_err(chip->dev, "%s:i2c access fail to register\n", __func__);
+	return size;
+out_strtoint:
+	dev_err(chip->dev, "%s: fail to change str to int\n", __func__);
+	return size;
+}
+
+static DEVICE_ATTR(strobe_pin, 0666, NULL, lm3642_strobe_pin_store);
+
+static void lm3642_deferred_strobe_brightness_set(struct work_struct *work)
+{
+	struct lm3642_chip_data *chip =
+	    container_of(work, struct lm3642_chip_data, work_flash);
+
+	mutex_lock(&chip->lock);
+	lm3642_control(chip, chip->br_flash, MODES_FLASH);
+	mutex_unlock(&chip->lock);
+}
+
+static void lm3642_strobe_brightness_set(struct led_classdev *cdev,
+					 enum led_brightness brightness)
+{
+	struct lm3642_chip_data *chip =
+	    container_of(cdev, struct lm3642_chip_data, cdev_flash);
+
+	chip->br_flash = brightness;
+	schedule_work(&chip->work_flash);
+}
+
+/* indicator */
+static void lm3642_deferred_indicator_brightness_set(struct work_struct *work)
+{
+	struct lm3642_chip_data *chip =
+	    container_of(work, struct lm3642_chip_data, work_indicator);
+
+	mutex_lock(&chip->lock);
+	lm3642_control(chip, chip->br_indicator, MODES_INDIC);
+	mutex_unlock(&chip->lock);
+}
+
+static void lm3642_indicator_brightness_set(struct led_classdev *cdev,
+					    enum led_brightness brightness)
+{
+	struct lm3642_chip_data *chip =
+	    container_of(cdev, struct lm3642_chip_data, cdev_indicator);
+
+	chip->br_indicator = brightness;
+	schedule_work(&chip->work_indicator);
+}
+
+static const struct regmap_config lm3642_regmap = {
+	.reg_bits = 8,
+	.val_bits = 8,
+	.max_register = REG_MAX,
+};
+
+static int __devinit lm3642_probe(struct i2c_client *client,
+				  const struct i2c_device_id *id)
+{
+	struct lm3642_platform_data *pdata = client->dev.platform_data;
+	struct lm3642_chip_data *chip;
+
+	int err;
+
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+		dev_err(&client->dev, "i2c functionality check fail.\n");
+		return -EOPNOTSUPP;
+	}
+
+	if (pdata == NULL) {
+		dev_err(&client->dev, "needs Platform Data.\n");
+		return -ENODATA;
+	}
+
+	chip = devm_kzalloc(&client->dev,
+			    sizeof(struct lm3642_chip_data), GFP_KERNEL);
+	if (!chip)
+		return -ENOMEM;
+
+	chip->dev = &client->dev;
+	chip->pdata = pdata;
+
+	chip->tx_pin = pdata->tx_pin;
+	chip->torch_pin = pdata->torch_pin;
+	chip->strobe_pin = pdata->strobe_pin;
+
+	chip->regmap = devm_regmap_init_i2c(client, &lm3642_regmap);
+	if (IS_ERR(chip->regmap)) {
+		err = PTR_ERR(chip->regmap);
+		dev_err(&client->dev, "Failed to allocate register map: %d\n",
+			err);
+		return err;
+	}
+
+	mutex_init(&chip->lock);
+	i2c_set_clientdata(client, chip);
+
+	err = lm3642_chip_init(chip);
+	if (err < 0)
+		goto err_out;
+
+	/* flash */
+	INIT_WORK(&chip->work_flash, lm3642_deferred_strobe_brightness_set);
+	chip->cdev_flash.name = "flash";
+	chip->cdev_flash.max_brightness = 16;
+	chip->cdev_flash.brightness_set = lm3642_strobe_brightness_set;
+	err = led_classdev_register((struct device *)
+				    &client->dev, &chip->cdev_flash);
+	if (err < 0) {
+		dev_err(chip->dev, "failed to register flash\n");
+		goto err_out;
+	}
+	err = device_create_file(chip->cdev_flash.dev, &dev_attr_strobe_pin);
+	if (err < 0) {
+		dev_err(chip->dev, "failed to create strobe-pin file\n");
+		goto err_create_flash_pin_file;
+	}
+
+	/* torch */
+	INIT_WORK(&chip->work_torch, lm3642_deferred_torch_brightness_set);
+	chip->cdev_torch.name = "torch";
+	chip->cdev_torch.max_brightness = 8;
+	chip->cdev_torch.brightness_set = lm3642_torch_brightness_set;
+	err = led_classdev_register((struct device *)
+				    &client->dev, &chip->cdev_torch);
+	if (err < 0) {
+		dev_err(chip->dev, "failed to register torch\n");
+		goto err_create_torch_file;
+	}
+	err = device_create_file(chip->cdev_torch.dev, &dev_attr_torch_pin);
+	if (err < 0) {
+		dev_err(chip->dev, "failed to create torch-pin file\n");
+		goto err_create_torch_pin_file;
+	}
+
+	/* indicator */
+	INIT_WORK(&chip->work_indicator,
+		  lm3642_deferred_indicator_brightness_set);
+	chip->cdev_indicator.name = "indicator";
+	chip->cdev_indicator.max_brightness = 8;
+	chip->cdev_indicator.brightness_set = lm3642_indicator_brightness_set;
+	err = led_classdev_register((struct device *)
+				    &client->dev, &chip->cdev_indicator);
+	if (err < 0) {
+		dev_err(chip->dev, "failed to register indicator\n");
+		goto err_create_indicator_file;
+	}
+
+	dev_info(&client->dev, "LM3642 is initialized\n");
+	return 0;
+
+err_create_indicator_file:
+	device_remove_file(chip->cdev_torch.dev, &dev_attr_torch_pin);
+err_create_torch_pin_file:
+	led_classdev_unregister(&chip->cdev_torch);
+err_create_torch_file:
+	device_remove_file(chip->cdev_flash.dev, &dev_attr_strobe_pin);
+err_create_flash_pin_file:
+	led_classdev_unregister(&chip->cdev_flash);
+err_out:
+	return err;
+}
+
+static int __devexit lm3642_remove(struct i2c_client *client)
+{
+	struct lm3642_chip_data *chip = i2c_get_clientdata(client);
+
+	led_classdev_unregister(&chip->cdev_indicator);
+	flush_work(&chip->work_indicator);
+	device_remove_file(chip->cdev_torch.dev, &dev_attr_torch_pin);
+	led_classdev_unregister(&chip->cdev_torch);
+	flush_work(&chip->work_torch);
+	device_remove_file(chip->cdev_flash.dev, &dev_attr_strobe_pin);
+	led_classdev_unregister(&chip->cdev_flash);
+	flush_work(&chip->work_flash);
+	regmap_write(chip->regmap, REG_ENABLE, 0);
+	return 0;
+}
+
+static const struct i2c_device_id lm3642_id[] = {
+	{LM3642_NAME, 0},
+	{}
+};
+
+MODULE_DEVICE_TABLE(i2c, lm3642_id);
+
+static struct i2c_driver lm3642_i2c_driver = {
+	.driver = {
+		   .name = LM3642_NAME,
+		   .owner = THIS_MODULE,
+		   .pm = NULL,
+		   },
+	.probe = lm3642_probe,
+	.remove = __devexit_p(lm3642_remove),
+	.id_table = lm3642_id,
+};
+
+module_i2c_driver(lm3642_i2c_driver);
+
+MODULE_DESCRIPTION("Texas Instruments Flash Lighting driver for LM3642");
+MODULE_AUTHOR("Daniel Jeong <daniel.jeong@ti.com>");
+MODULE_AUTHOR("G.Shark Jeong <gshark.jeong@gmail.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/leds/leds-lp5523.c b/drivers/leds/leds-lp5523.c
index fbc12ac..97994ff 100644
--- a/drivers/leds/leds-lp5523.c
+++ b/drivers/leds/leds-lp5523.c
@@ -104,6 +104,11 @@
 #define LED_ACTIVE(mux, led)		(!!(mux & (0x0001 << led)))
 #define SHIFT_MASK(id)			(((id) - 1) * 2)
 
+enum lp5523_chip_id {
+	LP5523,
+	LP55231,
+};
+
 struct lp5523_engine {
 	int		id;
 	u8		mode;
@@ -150,7 +155,7 @@ static inline struct lp5523_chip *led_to_lp5523(struct lp5523_led *led)
 			    leds[led->id]);
 }
 
-static int lp5523_set_mode(struct lp5523_engine *engine, u8 mode);
+static void lp5523_set_mode(struct lp5523_engine *engine, u8 mode);
 static int lp5523_set_engine_mode(struct lp5523_engine *engine, u8 mode);
 static int lp5523_load_program(struct lp5523_engine *engine, const u8 *pattern);
 
@@ -177,7 +182,7 @@ static int lp5523_detect(struct i2c_client *client)
 	int ret;
 	u8 buf;
 
-	ret = lp5523_write(client, LP5523_REG_ENABLE, 0x40);
+	ret = lp5523_write(client, LP5523_REG_ENABLE, LP5523_ENABLE);
 	if (ret)
 		return ret;
 	ret = lp5523_read(client, LP5523_REG_ENABLE, &buf);
@@ -338,7 +343,8 @@ static int lp5523_mux_parse(const char *buf, u16 *mux, size_t len)
 {
 	int i;
 	u16 tmp_mux = 0;
-	len = len < LP5523_LEDS ? len : LP5523_LEDS;
+
+	len = min_t(int, len, LP5523_LEDS);
 	for (i = 0; i < len; i++) {
 		switch (buf[i]) {
 		case '1':
@@ -546,6 +552,9 @@ static int lp5523_do_store_load(struct lp5523_engine *engine,
 	unsigned cmd;
 	u8 pattern[LP5523_PROGRAM_LENGTH] = {0};
 
+	if (engine->mode != LP5523_CMD_LOAD)
+		return -EINVAL;
+
 	while ((offset < len - 1) && (i < LP5523_PROGRAM_LENGTH)) {
 		/* separate sscanfs because length is working only for %s */
 		ret = sscanf(buf + offset, "%2s%n ", c, &nrchars);
@@ -563,12 +572,7 @@ static int lp5523_do_store_load(struct lp5523_engine *engine,
 		goto fail;
 
 	mutex_lock(&chip->lock);
-
-	if (engine->mode == LP5523_CMD_LOAD)
-		ret = lp5523_load_program(engine, pattern);
-	else
-		ret = -EINVAL;
-
+	ret = lp5523_load_program(engine, pattern);
 	mutex_unlock(&chip->lock);
 
 	if (ret) {
@@ -755,6 +759,7 @@ static struct attribute *lp5523_attributes[] = {
 	&dev_attr_engine2_leds.attr,
 	&dev_attr_engine3_load.attr,
 	&dev_attr_engine3_leds.attr,
+	NULL,
 };
 
 static const struct attribute_group lp5523_group = {
@@ -789,26 +794,28 @@ static void lp5523_unregister_sysfs(struct i2c_client *client)
 /*--------------------------------------------------------------*/
 /*			Set chip operating mode			*/
 /*--------------------------------------------------------------*/
-static int lp5523_set_mode(struct lp5523_engine *engine, u8 mode)
+static void lp5523_set_mode(struct lp5523_engine *engine, u8 mode)
 {
-	int ret = 0;
-
 	/* if in that mode already do nothing, except for run */
 	if (mode == engine->mode && mode != LP5523_CMD_RUN)
-		return 0;
+		return;
 
-	if (mode == LP5523_CMD_RUN) {
-		ret = lp5523_run_program(engine);
-	} else if (mode == LP5523_CMD_LOAD) {
+	switch (mode) {
+	case LP5523_CMD_RUN:
+		lp5523_run_program(engine);
+		break;
+	case LP5523_CMD_LOAD:
 		lp5523_set_engine_mode(engine, LP5523_CMD_DISABLED);
 		lp5523_set_engine_mode(engine, LP5523_CMD_LOAD);
-	} else if (mode == LP5523_CMD_DISABLED) {
+		break;
+	case LP5523_CMD_DISABLED:
 		lp5523_set_engine_mode(engine, LP5523_CMD_DISABLED);
+		break;
+	default:
+		return;
 	}
 
 	engine->mode = mode;
-
-	return ret;
 }
 
 /*--------------------------------------------------------------*/
@@ -827,7 +834,8 @@ static int __init lp5523_init_engine(struct lp5523_engine *engine, int id)
 }
 
 static int __devinit lp5523_init_led(struct lp5523_led *led, struct device *dev,
-			   int chan, struct lp5523_platform_data *pdata)
+			   int chan, struct lp5523_platform_data *pdata,
+			   const char *chip_name)
 {
 	char name[32];
 	int res;
@@ -846,10 +854,14 @@ static int __devinit lp5523_init_led(struct lp5523_led *led, struct device *dev,
 			return -EINVAL;
 		}
 
-		snprintf(name, sizeof(name), "%s:channel%d",
-			pdata->label ?: "lp5523", chan);
+		if (pdata->led_config[chan].name) {
+			led->cdev.name = pdata->led_config[chan].name;
+		} else {
+			snprintf(name, sizeof(name), "%s:channel%d",
+				pdata->label ? : chip_name, chan);
+			led->cdev.name = name;
+		}
 
-		led->cdev.name = name;
 		led->cdev.brightness_set = lp5523_set_brightness;
 		res = led_classdev_register(dev, &led->cdev);
 		if (res < 0) {
@@ -917,7 +929,7 @@ static int __devinit lp5523_probe(struct i2c_client *client,
 	if (ret)
 		goto fail1;
 
-	dev_info(&client->dev, "LP5523 Programmable led chip found\n");
+	dev_info(&client->dev, "%s Programmable led chip found\n", id->name);
 
 	/* Initialize engines */
 	for (i = 0; i < ARRAY_SIZE(chip->engines); i++) {
@@ -945,7 +957,8 @@ static int __devinit lp5523_probe(struct i2c_client *client,
 		INIT_WORK(&chip->leds[led].brightness_work,
 			lp5523_led_brightness_work);
 
-		ret = lp5523_init_led(&chip->leds[led], &client->dev, i, pdata);
+		ret = lp5523_init_led(&chip->leds[led], &client->dev, i, pdata,
+				id->name);
 		if (ret) {
 			dev_err(&client->dev, "error initializing leds\n");
 			goto fail2;
@@ -970,7 +983,7 @@ static int __devinit lp5523_probe(struct i2c_client *client,
 fail2:
 	for (i = 0; i < chip->num_leds; i++) {
 		led_classdev_unregister(&chip->leds[i].cdev);
-		cancel_work_sync(&chip->leds[i].brightness_work);
+		flush_work(&chip->leds[i].brightness_work);
 	}
 fail1:
 	if (pdata->enable)
@@ -985,11 +998,14 @@ static int lp5523_remove(struct i2c_client *client)
 	struct lp5523_chip *chip = i2c_get_clientdata(client);
 	int i;
 
+	/* Disable engine mode */
+	lp5523_write(client, LP5523_REG_OP_MODE, LP5523_CMD_DISABLED);
+
 	lp5523_unregister_sysfs(client);
 
 	for (i = 0; i < chip->num_leds; i++) {
 		led_classdev_unregister(&chip->leds[i].cdev);
-		cancel_work_sync(&chip->leds[i].brightness_work);
+		flush_work(&chip->leds[i].brightness_work);
 	}
 
 	if (chip->pdata->enable)
@@ -1000,7 +1016,8 @@ static int lp5523_remove(struct i2c_client *client)
 }
 
 static const struct i2c_device_id lp5523_id[] = {
-	{ "lp5523", 0 },
+	{ "lp5523",  LP5523 },
+	{ "lp55231", LP55231 },
 	{ }
 };
 
@@ -1008,7 +1025,7 @@ MODULE_DEVICE_TABLE(i2c, lp5523_id);
 
 static struct i2c_driver lp5523_driver = {
 	.driver = {
-		.name	= "lp5523",
+		.name	= "lp5523x",
 	},
 	.probe		= lp5523_probe,
 	.remove		= lp5523_remove,
diff --git a/drivers/leds/leds-lp8788.c b/drivers/leds/leds-lp8788.c
index 0ade6eb..64009a1 100644
--- a/drivers/leds/leds-lp8788.c
+++ b/drivers/leds/leds-lp8788.c
@@ -172,7 +172,7 @@ static int __devexit lp8788_led_remove(struct platform_device *pdev)
 	struct lp8788_led *led = platform_get_drvdata(pdev);
 
 	led_classdev_unregister(&led->led_dev);
-	flush_work_sync(&led->work);
+	flush_work(&led->work);
 
 	return 0;
 }
diff --git a/drivers/leds/leds-netxbig.c b/drivers/leds/leds-netxbig.c
index e37618e..461bbf9 100644
--- a/drivers/leds/leds-netxbig.c
+++ b/drivers/leds/leds-netxbig.c
@@ -28,7 +28,7 @@
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
 #include <linux/leds.h>
-#include <mach/leds-netxbig.h>
+#include <linux/platform_data/leds-kirkwood-netxbig.h>
 
 /*
  * GPIO extension bus.
diff --git a/drivers/leds/leds-ns2.c b/drivers/leds/leds-ns2.c
index 10528da..d176ec8 100644
--- a/drivers/leds/leds-ns2.c
+++ b/drivers/leds/leds-ns2.c
@@ -29,7 +29,7 @@
 #include <linux/gpio.h>
 #include <linux/leds.h>
 #include <linux/module.h>
-#include <mach/leds-ns2.h>
+#include <linux/platform_data/leds-kirkwood-ns2.h>
 
 /*
  * The Network Space v2 dual-GPIO LED is wired to a CPLD and can blink in
diff --git a/drivers/leds/leds-pca9633.c b/drivers/leds/leds-pca9633.c
index edcd706..2f2f9c4 100644
--- a/drivers/leds/leds-pca9633.c
+++ b/drivers/leds/leds-pca9633.c
@@ -22,6 +22,7 @@
 #include <linux/i2c.h>
 #include <linux/workqueue.h>
 #include <linux/slab.h>
+#include <linux/platform_data/leds-pca9633.h>
 
 /* LED select registers determine the source that drives LED outputs */
 #define PCA9633_LED_OFF		0x0	/* LED driver off */
@@ -96,13 +97,13 @@ static int __devinit pca9633_probe(struct i2c_client *client,
 					const struct i2c_device_id *id)
 {
 	struct pca9633_led *pca9633;
-	struct led_platform_data *pdata;
+	struct pca9633_platform_data *pdata;
 	int i, err;
 
 	pdata = client->dev.platform_data;
 
 	if (pdata) {
-		if (pdata->num_leds <= 0 || pdata->num_leds > 4) {
+		if (pdata->leds.num_leds <= 0 || pdata->leds.num_leds > 4) {
 			dev_err(&client->dev, "board info must claim at most 4 LEDs");
 			return -EINVAL;
 		}
@@ -119,14 +120,14 @@ static int __devinit pca9633_probe(struct i2c_client *client,
 		pca9633[i].led_num = i;
 
 		/* Platform data can specify LED names and default triggers */
-		if (pdata && i < pdata->num_leds) {
-			if (pdata->leds[i].name)
+		if (pdata && i < pdata->leds.num_leds) {
+			if (pdata->leds.leds[i].name)
 				snprintf(pca9633[i].name,
 					 sizeof(pca9633[i].name), "pca9633:%s",
-					 pdata->leds[i].name);
-			if (pdata->leds[i].default_trigger)
+					 pdata->leds.leds[i].name);
+			if (pdata->leds.leds[i].default_trigger)
 				pca9633[i].led_cdev.default_trigger =
-					pdata->leds[i].default_trigger;
+					pdata->leds.leds[i].default_trigger;
 		} else {
 			snprintf(pca9633[i].name, sizeof(pca9633[i].name),
 				 "pca9633:%d", i);
@@ -145,6 +146,10 @@ static int __devinit pca9633_probe(struct i2c_client *client,
 	/* Disable LED all-call address and set normal mode */
 	i2c_smbus_write_byte_data(client, PCA9633_MODE1, 0x00);
 
+	/* Configure output: open-drain or totem pole (push-pull) */
+	if (pdata && pdata->outdrv == PCA9633_OPEN_DRAIN)
+		i2c_smbus_write_byte_data(client, PCA9633_MODE2, 0x01);
+
 	/* Turn off LEDs */
 	i2c_smbus_write_byte_data(client, PCA9633_LEDOUT, 0x00);
 
diff --git a/drivers/leds/leds-s3c24xx.c b/drivers/leds/leds-s3c24xx.c
index 942f0ea..e1a0df6 100644
--- a/drivers/leds/leds-s3c24xx.c
+++ b/drivers/leds/leds-s3c24xx.c
@@ -21,7 +21,7 @@
 
 #include <mach/hardware.h>
 #include <mach/regs-gpio.h>
-#include <mach/leds-gpio.h>
+#include <linux/platform_data/leds-s3c24xx.h>
 
 /* our context */
 
diff --git a/drivers/leds/leds-wm8350.c b/drivers/leds/leds-wm8350.c
index 918d4ba..88f23f8 100644
--- a/drivers/leds/leds-wm8350.c
+++ b/drivers/leds/leds-wm8350.c
@@ -201,7 +201,7 @@ static int wm8350_led_probe(struct platform_device *pdev)
 	struct regulator *isink, *dcdc;
 	struct wm8350_led *led;
 	struct wm8350_led_platform_data *pdata = pdev->dev.platform_data;
-	int ret, i;
+	int i;
 
 	if (pdata == NULL) {
 		dev_err(&pdev->dev, "no platform data\n");
@@ -214,24 +214,21 @@ static int wm8350_led_probe(struct platform_device *pdev)
 		return -EINVAL;
 	}
 
-	isink = regulator_get(&pdev->dev, "led_isink");
+	isink = devm_regulator_get(&pdev->dev, "led_isink");
 	if (IS_ERR(isink)) {
 		printk(KERN_ERR "%s: can't get ISINK\n", __func__);
 		return PTR_ERR(isink);
 	}
 
-	dcdc = regulator_get(&pdev->dev, "led_vcc");
+	dcdc = devm_regulator_get(&pdev->dev, "led_vcc");
 	if (IS_ERR(dcdc)) {
 		printk(KERN_ERR "%s: can't get DCDC\n", __func__);
-		ret = PTR_ERR(dcdc);
-		goto err_isink;
+		return PTR_ERR(dcdc);
 	}
 
 	led = devm_kzalloc(&pdev->dev, sizeof(*led), GFP_KERNEL);
-	if (led == NULL) {
-		ret = -ENOMEM;
-		goto err_dcdc;
-	}
+	if (led == NULL)
+		return -ENOMEM;
 
 	led->cdev.brightness_set = wm8350_led_set;
 	led->cdev.default_trigger = pdata->default_trigger;
@@ -257,17 +254,7 @@ static int wm8350_led_probe(struct platform_device *pdev)
 	led->value = LED_OFF;
 	platform_set_drvdata(pdev, led);
 
-	ret = led_classdev_register(&pdev->dev, &led->cdev);
-	if (ret < 0)
-		goto err_dcdc;
-
-	return 0;
-
- err_dcdc:
-	regulator_put(dcdc);
- err_isink:
-	regulator_put(isink);
-	return ret;
+	return led_classdev_register(&pdev->dev, &led->cdev);
 }
 
 static int wm8350_led_remove(struct platform_device *pdev)
@@ -275,10 +262,8 @@ static int wm8350_led_remove(struct platform_device *pdev)
 	struct wm8350_led *led = platform_get_drvdata(pdev);
 
 	led_classdev_unregister(&led->cdev);
-	flush_work_sync(&led->work);
+	flush_work(&led->work);
 	wm8350_led_disable(led);
-	regulator_put(led->dcdc);
-	regulator_put(led->isink);
 	return 0;
 }
 
diff --git a/drivers/leds/leds.h b/drivers/leds/leds.h
index d02acd4..4c50365 100644
--- a/drivers/leds/leds.h
+++ b/drivers/leds/leds.h
@@ -32,6 +32,8 @@ static inline int led_get_brightness(struct led_classdev *led_cdev)
 	return led_cdev->brightness;
 }
 
+void led_stop_software_blink(struct led_classdev *led_cdev);
+
 extern struct rw_semaphore leds_list_lock;
 extern struct list_head leds_list;
 
diff --git a/drivers/leds/ledtrig-cpu.c b/drivers/leds/ledtrig-cpu.c
new file mode 100644
index 0000000..b312056
--- /dev/null
+++ b/drivers/leds/ledtrig-cpu.c
@@ -0,0 +1,163 @@
+/*
+ * ledtrig-cpu.c - LED trigger based on CPU activity
+ *
+ * This LED trigger will be registered for each possible CPU and named as
+ * cpu0, cpu1, cpu2, cpu3, etc.
+ *
+ * It can be bound to any LED just like other triggers using either a
+ * board file or via sysfs interface.
+ *
+ * An API named ledtrig_cpu is exported for any user, who want to add CPU
+ * activity indication in their code
+ *
+ * Copyright 2011 Linus Walleij <linus.walleij@linaro.org>
+ * Copyright 2011 - 2012 Bryan Wu <bryan.wu@canonical.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/percpu.h>
+#include <linux/syscore_ops.h>
+#include <linux/rwsem.h>
+#include "leds.h"
+
+#define MAX_NAME_LEN	8
+
+struct led_trigger_cpu {
+	char name[MAX_NAME_LEN];
+	struct led_trigger *_trig;
+	struct mutex lock;
+	int lock_is_inited;
+};
+
+static DEFINE_PER_CPU(struct led_trigger_cpu, cpu_trig);
+
+/**
+ * ledtrig_cpu - emit a CPU event as a trigger
+ * @evt: CPU event to be emitted
+ *
+ * Emit a CPU event on a CPU core, which will trigger a
+ * binded LED to turn on or turn off.
+ */
+void ledtrig_cpu(enum cpu_led_event ledevt)
+{
+	struct led_trigger_cpu *trig = &__get_cpu_var(cpu_trig);
+
+	/* mutex lock should be initialized before calling mutex_call() */
+	if (!trig->lock_is_inited)
+		return;
+
+	mutex_lock(&trig->lock);
+
+	/* Locate the correct CPU LED */
+	switch (ledevt) {
+	case CPU_LED_IDLE_END:
+	case CPU_LED_START:
+		/* Will turn the LED on, max brightness */
+		led_trigger_event(trig->_trig, LED_FULL);
+		break;
+
+	case CPU_LED_IDLE_START:
+	case CPU_LED_STOP:
+	case CPU_LED_HALTED:
+		/* Will turn the LED off */
+		led_trigger_event(trig->_trig, LED_OFF);
+		break;
+
+	default:
+		/* Will leave the LED as it is */
+		break;
+	}
+
+	mutex_unlock(&trig->lock);
+}
+EXPORT_SYMBOL(ledtrig_cpu);
+
+static int ledtrig_cpu_syscore_suspend(void)
+{
+	ledtrig_cpu(CPU_LED_STOP);
+	return 0;
+}
+
+static void ledtrig_cpu_syscore_resume(void)
+{
+	ledtrig_cpu(CPU_LED_START);
+}
+
+static void ledtrig_cpu_syscore_shutdown(void)
+{
+	ledtrig_cpu(CPU_LED_HALTED);
+}
+
+static struct syscore_ops ledtrig_cpu_syscore_ops = {
+	.shutdown	= ledtrig_cpu_syscore_shutdown,
+	.suspend	= ledtrig_cpu_syscore_suspend,
+	.resume		= ledtrig_cpu_syscore_resume,
+};
+
+static int __init ledtrig_cpu_init(void)
+{
+	int cpu;
+
+	/* Supports up to 9999 cpu cores */
+	BUILD_BUG_ON(CONFIG_NR_CPUS > 9999);
+
+	/*
+	 * Registering CPU led trigger for each CPU core here
+	 * ignores CPU hotplug, but after this CPU hotplug works
+	 * fine with this trigger.
+	 */
+	for_each_possible_cpu(cpu) {
+		struct led_trigger_cpu *trig = &per_cpu(cpu_trig, cpu);
+
+		mutex_init(&trig->lock);
+
+		snprintf(trig->name, MAX_NAME_LEN, "cpu%d", cpu);
+
+		mutex_lock(&trig->lock);
+		led_trigger_register_simple(trig->name, &trig->_trig);
+		trig->lock_is_inited = 1;
+		mutex_unlock(&trig->lock);
+	}
+
+	register_syscore_ops(&ledtrig_cpu_syscore_ops);
+
+	pr_info("ledtrig-cpu: registered to indicate activity on CPUs\n");
+
+	return 0;
+}
+module_init(ledtrig_cpu_init);
+
+static void __exit ledtrig_cpu_exit(void)
+{
+	int cpu;
+
+	for_each_possible_cpu(cpu) {
+		struct led_trigger_cpu *trig = &per_cpu(cpu_trig, cpu);
+
+		mutex_lock(&trig->lock);
+
+		led_trigger_unregister_simple(trig->_trig);
+		trig->_trig = NULL;
+		memset(trig->name, 0, MAX_NAME_LEN);
+		trig->lock_is_inited = 0;
+
+		mutex_unlock(&trig->lock);
+		mutex_destroy(&trig->lock);
+	}
+
+	unregister_syscore_ops(&ledtrig_cpu_syscore_ops);
+}
+module_exit(ledtrig_cpu_exit);
+
+MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
+MODULE_AUTHOR("Bryan Wu <bryan.wu@canonical.com>");
+MODULE_DESCRIPTION("CPU LED trigger");
+MODULE_LICENSE("GPL");
diff --git a/drivers/lguest/lguest_device.c b/drivers/lguest/lguest_device.c
index 9e8388e..fc92ccb 100644
--- a/drivers/lguest/lguest_device.c
+++ b/drivers/lguest/lguest_device.c
@@ -263,6 +263,9 @@ static struct virtqueue *lg_find_vq(struct virtio_device *vdev,
 	struct virtqueue *vq;
 	int err;
 
+	if (!name)
+		return NULL;
+
 	/* We must have this many virtqueues. */
 	if (index >= ldev->desc->num_vq)
 		return ERR_PTR(-ENOENT);
@@ -296,7 +299,7 @@ static struct virtqueue *lg_find_vq(struct virtio_device *vdev,
 	 * to 'true': the host just a(nother) SMP CPU, so we only need inter-cpu
 	 * barriers.
 	 */
-	vq = vring_new_virtqueue(lvq->config.num, LGUEST_VRING_ALIGN, vdev,
+	vq = vring_new_virtqueue(index, lvq->config.num, LGUEST_VRING_ALIGN, vdev,
 				 true, lvq->pages, lg_notify, callback, name);
 	if (!vq) {
 		err = -ENOMEM;
diff --git a/drivers/lguest/x86/core.c b/drivers/lguest/x86/core.c
index 39809035..4af12e1 100644
--- a/drivers/lguest/x86/core.c
+++ b/drivers/lguest/x86/core.c
@@ -203,8 +203,8 @@ void lguest_arch_run_guest(struct lg_cpu *cpu)
 	 * we set it now, so we can trap and pass that trap to the Guest if it
 	 * uses the FPU.
 	 */
-	if (cpu->ts)
-		unlazy_fpu(current);
+	if (cpu->ts && user_has_fpu())
+		stts();
 
 	/*
 	 * SYSENTER is an optimized way of doing system calls.  We can't allow
@@ -234,6 +234,10 @@ void lguest_arch_run_guest(struct lg_cpu *cpu)
 	 if (boot_cpu_has(X86_FEATURE_SEP))
 		wrmsr(MSR_IA32_SYSENTER_CS, __KERNEL_CS, 0);
 
+	/* Clear the host TS bit if it was set above. */
+	if (cpu->ts && user_has_fpu())
+		clts();
+
 	/*
 	 * If the Guest page faulted, then the cr2 register will tell us the
 	 * bad virtual address.  We have to grab this now, because once we
@@ -249,7 +253,7 @@ void lguest_arch_run_guest(struct lg_cpu *cpu)
 	 * a different CPU. So all the critical stuff should be done
 	 * before this.
 	 */
-	else if (cpu->regs->trapnum == 7)
+	else if (cpu->regs->trapnum == 7 && !user_has_fpu())
 		math_state_restore();
 }
 
diff --git a/drivers/macintosh/ams/ams-core.c b/drivers/macintosh/ams/ams-core.c
index 5c6a2d8..36a4fdd 100644
--- a/drivers/macintosh/ams/ams-core.c
+++ b/drivers/macintosh/ams/ams-core.c
@@ -226,7 +226,7 @@ void ams_sensor_detach(void)
 	 * We do this after ams_info.exit(), because an interrupt might
 	 * have arrived before disabling them.
 	 */
-	flush_work_sync(&ams_info.worker);
+	flush_work(&ams_info.worker);
 
 	/* Remove device */
 	of_device_unregister(ams_info.of_dev);
diff --git a/drivers/macintosh/macio_asic.c b/drivers/macintosh/macio_asic.c
index 20e5c2c..ef87310 100644
--- a/drivers/macintosh/macio_asic.c
+++ b/drivers/macintosh/macio_asic.c
@@ -748,7 +748,7 @@ static void __devexit macio_pci_remove(struct pci_dev* pdev)
  * MacIO is matched against any Apple ID, it's probe() function
  * will then decide wether it applies or not
  */
-static const struct pci_device_id __devinitdata pci_ids [] = { {
+static const struct pci_device_id __devinitconst pci_ids[] = { {
 	.vendor		= PCI_VENDOR_ID_APPLE,
 	.device		= PCI_ANY_ID,
 	.subvendor	= PCI_ANY_ID,
diff --git a/drivers/macintosh/mediabay.c b/drivers/macintosh/mediabay.c
index 831d751..3f8d032 100644
--- a/drivers/macintosh/mediabay.c
+++ b/drivers/macintosh/mediabay.c
@@ -63,7 +63,7 @@ struct media_bay_info {
 	int				value_count;
 	int				timer;
 	struct macio_dev		*mdev;
-	struct mb_ops*			ops;
+	const struct mb_ops*		ops;
 	int				index;
 	int				cached_gpio;
 	int				sleeping;
@@ -669,7 +669,7 @@ static int media_bay_resume(struct macio_dev *mdev)
 
 /* Definitions of "ops" structures.
  */
-static struct mb_ops ohare_mb_ops = {
+static const struct mb_ops ohare_mb_ops = {
 	.name		= "Ohare",
 	.content	= ohare_mb_content,
 	.power		= ohare_mb_power,
@@ -678,7 +678,7 @@ static struct mb_ops ohare_mb_ops = {
 	.un_reset_ide	= ohare_mb_un_reset_ide,
 };
 
-static struct mb_ops heathrow_mb_ops = {
+static const struct mb_ops heathrow_mb_ops = {
 	.name		= "Heathrow",
 	.content	= heathrow_mb_content,
 	.power		= heathrow_mb_power,
@@ -687,7 +687,7 @@ static struct mb_ops heathrow_mb_ops = {
 	.un_reset_ide	= heathrow_mb_un_reset_ide,
 };
 
-static struct mb_ops keylargo_mb_ops = {
+static const struct mb_ops keylargo_mb_ops = {
 	.name		= "KeyLargo",
 	.init		= keylargo_mb_init,
 	.content	= keylargo_mb_content,
diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c
index 54ac7ff..7d5a6b4 100644
--- a/drivers/macintosh/smu.c
+++ b/drivers/macintosh/smu.c
@@ -45,7 +45,6 @@
 #include <asm/pmac_feature.h>
 #include <asm/smu.h>
 #include <asm/sections.h>
-#include <asm/abs_addr.h>
 #include <asm/uaccess.h>
 
 #define VERSION "0.7"
@@ -502,7 +501,7 @@ int __init smu_init (void)
 	 * 32 bits value safely
 	 */
 	smu->cmd_buf_abs = (u32)smu_cmdbuf_abs;
-	smu->cmd_buf = (struct smu_cmd_buf *)abs_to_virt(smu_cmdbuf_abs);
+	smu->cmd_buf = __va(smu_cmdbuf_abs);
 
 	smu->db_node = of_find_node_by_name(NULL, "smu-doorbell");
 	if (smu->db_node == NULL) {
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
index 94e7f6b..7155945 100644
--- a/drivers/md/bitmap.c
+++ b/drivers/md/bitmap.c
@@ -163,20 +163,17 @@ static struct md_rdev *next_active_rdev(struct md_rdev *rdev, struct mddev *mdde
 	 * As devices are only added or removed when raid_disk is < 0 and
 	 * nr_pending is 0 and In_sync is clear, the entries we return will
 	 * still be in the same position on the list when we re-enter
-	 * list_for_each_continue_rcu.
+	 * list_for_each_entry_continue_rcu.
 	 */
-	struct list_head *pos;
 	rcu_read_lock();
 	if (rdev == NULL)
 		/* start at the beginning */
-		pos = &mddev->disks;
+		rdev = list_entry_rcu(&mddev->disks, struct md_rdev, same_set);
 	else {
 		/* release the previous rdev and start from there. */
 		rdev_dec_pending(rdev, mddev);
-		pos = &rdev->same_set;
 	}
-	list_for_each_continue_rcu(pos, &mddev->disks) {
-		rdev = list_entry(pos, struct md_rdev, same_set);
+	list_for_each_entry_continue_rcu(rdev, &mddev->disks, same_set) {
 		if (rdev->raid_disk >= 0 &&
 		    !test_bit(Faulty, &rdev->flags)) {
 			/* this is a usable devices */
@@ -473,14 +470,10 @@ static int bitmap_new_disk_sb(struct bitmap *bitmap)
 {
 	bitmap_super_t *sb;
 	unsigned long chunksize, daemon_sleep, write_behind;
-	int err = -EINVAL;
 
 	bitmap->storage.sb_page = alloc_page(GFP_KERNEL);
-	if (IS_ERR(bitmap->storage.sb_page)) {
-		err = PTR_ERR(bitmap->storage.sb_page);
-		bitmap->storage.sb_page = NULL;
-		return err;
-	}
+	if (bitmap->storage.sb_page == NULL)
+		return -ENOMEM;
 	bitmap->storage.sb_page->index = 0;
 
 	sb = kmap_atomic(bitmap->storage.sb_page);
diff --git a/drivers/md/dm-bufio.c b/drivers/md/dm-bufio.c
index cc06a1e..651ca79 100644
--- a/drivers/md/dm-bufio.c
+++ b/drivers/md/dm-bufio.c
@@ -280,9 +280,7 @@ static void __cache_size_refresh(void)
 	BUG_ON(!mutex_is_locked(&dm_bufio_clients_lock));
 	BUG_ON(dm_bufio_client_count < 0);
 
-	dm_bufio_cache_size_latch = dm_bufio_cache_size;
-
-	barrier();
+	dm_bufio_cache_size_latch = ACCESS_ONCE(dm_bufio_cache_size);
 
 	/*
 	 * Use default if set to 0 and report the actual cache size used.
@@ -441,8 +439,7 @@ static void __relink_lru(struct dm_buffer *b, int dirty)
 	c->n_buffers[b->list_mode]--;
 	c->n_buffers[dirty]++;
 	b->list_mode = dirty;
-	list_del(&b->lru_list);
-	list_add(&b->lru_list, &c->lru[dirty]);
+	list_move(&b->lru_list, &c->lru[dirty]);
 }
 
 /*----------------------------------------------------------------
@@ -813,7 +810,7 @@ static void __get_memory_limit(struct dm_bufio_client *c,
 {
 	unsigned long buffers;
 
-	if (dm_bufio_cache_size != dm_bufio_cache_size_latch) {
+	if (ACCESS_ONCE(dm_bufio_cache_size) != dm_bufio_cache_size_latch) {
 		mutex_lock(&dm_bufio_clients_lock);
 		__cache_size_refresh();
 		mutex_unlock(&dm_bufio_clients_lock);
@@ -1591,11 +1588,9 @@ EXPORT_SYMBOL_GPL(dm_bufio_client_destroy);
 
 static void cleanup_old_buffers(void)
 {
-	unsigned long max_age = dm_bufio_max_age;
+	unsigned long max_age = ACCESS_ONCE(dm_bufio_max_age);
 	struct dm_bufio_client *c;
 
-	barrier();
-
 	if (max_age > ULONG_MAX / HZ)
 		max_age = ULONG_MAX / HZ;
 
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index 664743d..bbf459b 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -798,14 +798,6 @@ static int crypt_convert(struct crypt_config *cc,
 	return 0;
 }
 
-static void dm_crypt_bio_destructor(struct bio *bio)
-{
-	struct dm_crypt_io *io = bio->bi_private;
-	struct crypt_config *cc = io->cc;
-
-	bio_free(bio, cc->bs);
-}
-
 /*
  * Generate a new unfragmented bio with the given size
  * This should never violate the device limitations
@@ -974,7 +966,6 @@ static void clone_init(struct dm_crypt_io *io, struct bio *clone)
 	clone->bi_end_io  = crypt_endio;
 	clone->bi_bdev    = cc->dev->bdev;
 	clone->bi_rw      = io->base_bio->bi_rw;
-	clone->bi_destructor = dm_crypt_bio_destructor;
 }
 
 static int kcryptd_io_read(struct dm_crypt_io *io, gfp_t gfp)
@@ -988,19 +979,14 @@ static int kcryptd_io_read(struct dm_crypt_io *io, gfp_t gfp)
 	 * copy the required bvecs because we need the original
 	 * one in order to decrypt the whole bio data *afterwards*.
 	 */
-	clone = bio_alloc_bioset(gfp, bio_segments(base_bio), cc->bs);
+	clone = bio_clone_bioset(base_bio, gfp, cc->bs);
 	if (!clone)
 		return 1;
 
 	crypt_inc_pending(io);
 
 	clone_init(io, clone);
-	clone->bi_idx = 0;
-	clone->bi_vcnt = bio_segments(base_bio);
-	clone->bi_size = base_bio->bi_size;
 	clone->bi_sector = cc->start + io->sector;
-	memcpy(clone->bi_io_vec, bio_iovec(base_bio),
-	       sizeof(struct bio_vec) * clone->bi_vcnt);
 
 	generic_make_request(clone);
 	return 0;
diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c
index ea5dd28..1c46f97 100644
--- a/drivers/md/dm-io.c
+++ b/drivers/md/dm-io.c
@@ -249,16 +249,6 @@ static void vm_dp_init(struct dpages *dp, void *data)
 	dp->context_ptr = data;
 }
 
-static void dm_bio_destructor(struct bio *bio)
-{
-	unsigned region;
-	struct io *io;
-
-	retrieve_io_and_region_from_bio(bio, &io, &region);
-
-	bio_free(bio, io->client->bios);
-}
-
 /*
  * Functions for getting the pages from kernel memory.
  */
@@ -317,7 +307,6 @@ static void do_region(int rw, unsigned region, struct dm_io_region *where,
 		bio->bi_sector = where->sector + (where->count - remaining);
 		bio->bi_bdev = where->bdev;
 		bio->bi_end_io = endio;
-		bio->bi_destructor = dm_bio_destructor;
 		store_io_and_region_in_bio(bio, io, region);
 
 		if (rw & REQ_DISCARD) {
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index d8abb90..573bd04 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -944,7 +944,7 @@ static void flush_multipath_work(struct multipath *m)
 	flush_workqueue(kmpath_handlerd);
 	multipath_wait_for_pg_init_completion(m);
 	flush_workqueue(kmultipathd);
-	flush_work_sync(&m->trigger_event);
+	flush_work(&m->trigger_event);
 }
 
 static void multipath_dtr(struct dm_target *ti)
@@ -1309,13 +1309,14 @@ static int multipath_end_io(struct dm_target *ti, struct request *clone,
 {
 	struct multipath *m = ti->private;
 	struct dm_mpath_io *mpio = map_context->ptr;
-	struct pgpath *pgpath = mpio->pgpath;
+	struct pgpath *pgpath;
 	struct path_selector *ps;
 	int r;
 
 	BUG_ON(!mpio);
 
 	r  = do_end_io(m, clone, error, mpio);
+	pgpath = mpio->pgpath;
 	if (pgpath) {
 		ps = &pgpath->pg->ps;
 		if (ps->type->end_io)
@@ -1555,6 +1556,7 @@ static int multipath_ioctl(struct dm_target *ti, unsigned int cmd,
 			   unsigned long arg)
 {
 	struct multipath *m = ti->private;
+	struct pgpath *pgpath;
 	struct block_device *bdev;
 	fmode_t mode;
 	unsigned long flags;
@@ -1570,12 +1572,14 @@ again:
 	if (!m->current_pgpath)
 		__choose_pgpath(m, 0);
 
-	if (m->current_pgpath) {
-		bdev = m->current_pgpath->path.dev->bdev;
-		mode = m->current_pgpath->path.dev->mode;
+	pgpath = m->current_pgpath;
+
+	if (pgpath) {
+		bdev = pgpath->path.dev->bdev;
+		mode = pgpath->path.dev->mode;
 	}
 
-	if (m->queue_io)
+	if ((pgpath && m->queue_io) || (!pgpath && m->queue_if_no_path))
 		r = -EAGAIN;
 	else if (!bdev)
 		r = -EIO;
diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c
index 982e3e3..45d94a7 100644
--- a/drivers/md/dm-raid.c
+++ b/drivers/md/dm-raid.c
@@ -338,6 +338,84 @@ static int validate_region_size(struct raid_set *rs, unsigned long region_size)
 }
 
 /*
+ * validate_rebuild_devices
+ * @rs
+ *
+ * Determine if the devices specified for rebuild can result in a valid
+ * usable array that is capable of rebuilding the given devices.
+ *
+ * Returns: 0 on success, -EINVAL on failure.
+ */
+static int validate_rebuild_devices(struct raid_set *rs)
+{
+	unsigned i, rebuild_cnt = 0;
+	unsigned rebuilds_per_group, copies, d;
+
+	if (!(rs->print_flags & DMPF_REBUILD))
+		return 0;
+
+	for (i = 0; i < rs->md.raid_disks; i++)
+		if (!test_bit(In_sync, &rs->dev[i].rdev.flags))
+			rebuild_cnt++;
+
+	switch (rs->raid_type->level) {
+	case 1:
+		if (rebuild_cnt >= rs->md.raid_disks)
+			goto too_many;
+		break;
+	case 4:
+	case 5:
+	case 6:
+		if (rebuild_cnt > rs->raid_type->parity_devs)
+			goto too_many;
+		break;
+	case 10:
+		copies = raid10_md_layout_to_copies(rs->md.layout);
+		if (rebuild_cnt < copies)
+			break;
+
+		/*
+		 * It is possible to have a higher rebuild count for RAID10,
+		 * as long as the failed devices occur in different mirror
+		 * groups (i.e. different stripes).
+		 *
+		 * Right now, we only allow for "near" copies.  When other
+		 * formats are added, we will have to check those too.
+		 *
+		 * When checking "near" format, make sure no adjacent devices
+		 * have failed beyond what can be handled.  In addition to the
+		 * simple case where the number of devices is a multiple of the
+		 * number of copies, we must also handle cases where the number
+		 * of devices is not a multiple of the number of copies.
+		 * E.g.    dev1 dev2 dev3 dev4 dev5
+		 *          A    A    B    B    C
+		 *          C    D    D    E    E
+		 */
+		rebuilds_per_group = 0;
+		for (i = 0; i < rs->md.raid_disks * copies; i++) {
+			d = i % rs->md.raid_disks;
+			if (!test_bit(In_sync, &rs->dev[d].rdev.flags) &&
+			    (++rebuilds_per_group >= copies))
+				goto too_many;
+			if (!((i + 1) % copies))
+				rebuilds_per_group = 0;
+		}
+		break;
+	default:
+		DMERR("The rebuild parameter is not supported for %s",
+		      rs->raid_type->name);
+		rs->ti->error = "Rebuild not supported for this RAID type";
+		return -EINVAL;
+	}
+
+	return 0;
+
+too_many:
+	rs->ti->error = "Too many rebuild devices specified";
+	return -EINVAL;
+}
+
+/*
  * Possible arguments are...
  *	<chunk_size> [optional_args]
  *
@@ -365,7 +443,7 @@ static int parse_raid_params(struct raid_set *rs, char **argv,
 {
 	char *raid10_format = "near";
 	unsigned raid10_copies = 2;
-	unsigned i, rebuild_cnt = 0;
+	unsigned i;
 	unsigned long value, region_size = 0;
 	sector_t sectors_per_dev = rs->ti->len;
 	sector_t max_io_len;
@@ -461,31 +539,7 @@ static int parse_raid_params(struct raid_set *rs, char **argv,
 
 		/* Parameters that take a numeric value are checked here */
 		if (!strcasecmp(key, "rebuild")) {
-			rebuild_cnt++;
-
-			switch (rs->raid_type->level) {
-			case 1:
-				if (rebuild_cnt >= rs->md.raid_disks) {
-					rs->ti->error = "Too many rebuild devices specified";
-					return -EINVAL;
-				}
-				break;
-			case 4:
-			case 5:
-			case 6:
-				if (rebuild_cnt > rs->raid_type->parity_devs) {
-					rs->ti->error = "Too many rebuild devices specified for given RAID type";
-					return -EINVAL;
-				}
-				break;
-			case 10:
-			default:
-				DMERR("The rebuild parameter is not supported for %s", rs->raid_type->name);
-				rs->ti->error = "Rebuild not supported for this RAID type";
-				return -EINVAL;
-			}
-
-			if (value > rs->md.raid_disks) {
+			if (value >= rs->md.raid_disks) {
 				rs->ti->error = "Invalid rebuild index given";
 				return -EINVAL;
 			}
@@ -608,6 +662,9 @@ static int parse_raid_params(struct raid_set *rs, char **argv,
 	}
 	rs->md.dev_sectors = sectors_per_dev;
 
+	if (validate_rebuild_devices(rs))
+		return -EINVAL;
+
 	/* Assume there are no metadata devices until the drives are parsed */
 	rs->md.persistent = 0;
 	rs->md.external = 1;
@@ -960,6 +1017,19 @@ static int analyse_superblocks(struct dm_target *ti, struct raid_set *rs)
 
 	freshest = NULL;
 	rdev_for_each_safe(rdev, tmp, mddev) {
+		/*
+		 * Skipping super_load due to DMPF_SYNC will cause
+		 * the array to undergo initialization again as
+		 * though it were new.  This is the intended effect
+		 * of the "sync" directive.
+		 *
+		 * When reshaping capability is added, we must ensure
+		 * that the "sync" directive is disallowed during the
+		 * reshape.
+		 */
+		if (rs->print_flags & DMPF_SYNC)
+			continue;
+
 		if (!rdev->meta_bdev)
 			continue;
 
@@ -1360,7 +1430,7 @@ static void raid_resume(struct dm_target *ti)
 
 static struct target_type raid_target = {
 	.name = "raid",
-	.version = {1, 3, 0},
+	.version = {1, 3, 1},
 	.module = THIS_MODULE,
 	.ctr = raid_ctr,
 	.dtr = raid_dtr,
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c
index bc5ddba8..fd61f98 100644
--- a/drivers/md/dm-raid1.c
+++ b/drivers/md/dm-raid1.c
@@ -1146,7 +1146,7 @@ static void mirror_dtr(struct dm_target *ti)
 
 	del_timer_sync(&ms->timer);
 	flush_workqueue(ms->kmirrord_wq);
-	flush_work_sync(&ms->trigger_event);
+	flush_work(&ms->trigger_event);
 	dm_kcopyd_client_destroy(ms->kcopyd_client);
 	destroy_workqueue(ms->kmirrord_wq);
 	free_context(ms, ti, ms->nr_mirrors);
diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c
index a087bf2..e2f87653 100644
--- a/drivers/md/dm-stripe.c
+++ b/drivers/md/dm-stripe.c
@@ -199,7 +199,7 @@ static void stripe_dtr(struct dm_target *ti)
 	for (i = 0; i < sc->stripes; i++)
 		dm_put_device(ti, sc->stripe[i].dev);
 
-	flush_work_sync(&sc->trigger_event);
+	flush_work(&sc->trigger_event);
 	kfree(sc);
 }
 
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index f900690..100368e 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -1212,6 +1212,41 @@ struct dm_target *dm_table_find_target(struct dm_table *t, sector_t sector)
 	return &t->targets[(KEYS_PER_NODE * n) + k];
 }
 
+static int count_device(struct dm_target *ti, struct dm_dev *dev,
+			sector_t start, sector_t len, void *data)
+{
+	unsigned *num_devices = data;
+
+	(*num_devices)++;
+
+	return 0;
+}
+
+/*
+ * Check whether a table has no data devices attached using each
+ * target's iterate_devices method.
+ * Returns false if the result is unknown because a target doesn't
+ * support iterate_devices.
+ */
+bool dm_table_has_no_data_devices(struct dm_table *table)
+{
+	struct dm_target *uninitialized_var(ti);
+	unsigned i = 0, num_devices = 0;
+
+	while (i < dm_table_get_num_targets(table)) {
+		ti = dm_table_get_target(table, i++);
+
+		if (!ti->type->iterate_devices)
+			return false;
+
+		ti->type->iterate_devices(ti, count_device, &num_devices);
+		if (num_devices)
+			return false;
+	}
+
+	return true;
+}
+
 /*
  * Establish the new table's queue_limits and validate them.
  */
@@ -1354,17 +1389,25 @@ static int device_is_nonrot(struct dm_target *ti, struct dm_dev *dev,
 	return q && blk_queue_nonrot(q);
 }
 
-static bool dm_table_is_nonrot(struct dm_table *t)
+static int device_is_not_random(struct dm_target *ti, struct dm_dev *dev,
+			     sector_t start, sector_t len, void *data)
+{
+	struct request_queue *q = bdev_get_queue(dev->bdev);
+
+	return q && !blk_queue_add_random(q);
+}
+
+static bool dm_table_all_devices_attribute(struct dm_table *t,
+					   iterate_devices_callout_fn func)
 {
 	struct dm_target *ti;
 	unsigned i = 0;
 
-	/* Ensure that all underlying device are non-rotational. */
 	while (i < dm_table_get_num_targets(t)) {
 		ti = dm_table_get_target(t, i++);
 
 		if (!ti->type->iterate_devices ||
-		    !ti->type->iterate_devices(ti, device_is_nonrot, NULL))
+		    !ti->type->iterate_devices(ti, func, NULL))
 			return 0;
 	}
 
@@ -1396,7 +1439,8 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
 	if (!dm_table_discard_zeroes_data(t))
 		q->limits.discard_zeroes_data = 0;
 
-	if (dm_table_is_nonrot(t))
+	/* Ensure that all underlying devices are non-rotational. */
+	if (dm_table_all_devices_attribute(t, device_is_nonrot))
 		queue_flag_set_unlocked(QUEUE_FLAG_NONROT, q);
 	else
 		queue_flag_clear_unlocked(QUEUE_FLAG_NONROT, q);
@@ -1404,6 +1448,15 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
 	dm_table_set_integrity(t);
 
 	/*
+	 * Determine whether or not this queue's I/O timings contribute
+	 * to the entropy pool, Only request-based targets use this.
+	 * Clear QUEUE_FLAG_ADD_RANDOM if any underlying device does not
+	 * have it set.
+	 */
+	if (blk_queue_add_random(q) && dm_table_all_devices_attribute(t, device_is_not_random))
+		queue_flag_clear_unlocked(QUEUE_FLAG_ADD_RANDOM, q);
+
+	/*
 	 * QUEUE_FLAG_STACKABLE must be set after all queue settings are
 	 * visible to other CPUs because, once the flag is set, incoming bios
 	 * are processed by request-based dm, which refers to the queue
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c
index af1fc3b..8e73f43 100644
--- a/drivers/md/dm-thin.c
+++ b/drivers/md/dm-thin.c
@@ -509,9 +509,9 @@ enum pool_mode {
 struct pool_features {
 	enum pool_mode mode;
 
-	unsigned zero_new_blocks:1;
-	unsigned discard_enabled:1;
-	unsigned discard_passdown:1;
+	bool zero_new_blocks:1;
+	bool discard_enabled:1;
+	bool discard_passdown:1;
 };
 
 struct thin_c;
@@ -580,7 +580,8 @@ struct pool_c {
 	struct dm_target_callbacks callbacks;
 
 	dm_block_t low_water_blocks;
-	struct pool_features pf;
+	struct pool_features requested_pf; /* Features requested during table load */
+	struct pool_features adjusted_pf;  /* Features used after adjusting for constituent devices */
 };
 
 /*
@@ -1839,6 +1840,47 @@ static void __requeue_bios(struct pool *pool)
 /*----------------------------------------------------------------
  * Binding of control targets to a pool object
  *--------------------------------------------------------------*/
+static bool data_dev_supports_discard(struct pool_c *pt)
+{
+	struct request_queue *q = bdev_get_queue(pt->data_dev->bdev);
+
+	return q && blk_queue_discard(q);
+}
+
+/*
+ * If discard_passdown was enabled verify that the data device
+ * supports discards.  Disable discard_passdown if not.
+ */
+static void disable_passdown_if_not_supported(struct pool_c *pt)
+{
+	struct pool *pool = pt->pool;
+	struct block_device *data_bdev = pt->data_dev->bdev;
+	struct queue_limits *data_limits = &bdev_get_queue(data_bdev)->limits;
+	sector_t block_size = pool->sectors_per_block << SECTOR_SHIFT;
+	const char *reason = NULL;
+	char buf[BDEVNAME_SIZE];
+
+	if (!pt->adjusted_pf.discard_passdown)
+		return;
+
+	if (!data_dev_supports_discard(pt))
+		reason = "discard unsupported";
+
+	else if (data_limits->max_discard_sectors < pool->sectors_per_block)
+		reason = "max discard sectors smaller than a block";
+
+	else if (data_limits->discard_granularity > block_size)
+		reason = "discard granularity larger than a block";
+
+	else if (block_size & (data_limits->discard_granularity - 1))
+		reason = "discard granularity not a factor of block size";
+
+	if (reason) {
+		DMWARN("Data device (%s) %s: Disabling discard passdown.", bdevname(data_bdev, buf), reason);
+		pt->adjusted_pf.discard_passdown = false;
+	}
+}
+
 static int bind_control_target(struct pool *pool, struct dm_target *ti)
 {
 	struct pool_c *pt = ti->private;
@@ -1847,31 +1889,16 @@ static int bind_control_target(struct pool *pool, struct dm_target *ti)
 	 * We want to make sure that degraded pools are never upgraded.
 	 */
 	enum pool_mode old_mode = pool->pf.mode;
-	enum pool_mode new_mode = pt->pf.mode;
+	enum pool_mode new_mode = pt->adjusted_pf.mode;
 
 	if (old_mode > new_mode)
 		new_mode = old_mode;
 
 	pool->ti = ti;
 	pool->low_water_blocks = pt->low_water_blocks;
-	pool->pf = pt->pf;
-	set_pool_mode(pool, new_mode);
+	pool->pf = pt->adjusted_pf;
 
-	/*
-	 * If discard_passdown was enabled verify that the data device
-	 * supports discards.  Disable discard_passdown if not; otherwise
-	 * -EOPNOTSUPP will be returned.
-	 */
-	/* FIXME: pull this out into a sep fn. */
-	if (pt->pf.discard_passdown) {
-		struct request_queue *q = bdev_get_queue(pt->data_dev->bdev);
-		if (!q || !blk_queue_discard(q)) {
-			char buf[BDEVNAME_SIZE];
-			DMWARN("Discard unsupported by data device (%s): Disabling discard passdown.",
-			       bdevname(pt->data_dev->bdev, buf));
-			pool->pf.discard_passdown = 0;
-		}
-	}
+	set_pool_mode(pool, new_mode);
 
 	return 0;
 }
@@ -1889,9 +1916,9 @@ static void unbind_control_target(struct pool *pool, struct dm_target *ti)
 static void pool_features_init(struct pool_features *pf)
 {
 	pf->mode = PM_WRITE;
-	pf->zero_new_blocks = 1;
-	pf->discard_enabled = 1;
-	pf->discard_passdown = 1;
+	pf->zero_new_blocks = true;
+	pf->discard_enabled = true;
+	pf->discard_passdown = true;
 }
 
 static void __pool_destroy(struct pool *pool)
@@ -2119,13 +2146,13 @@ static int parse_pool_features(struct dm_arg_set *as, struct pool_features *pf,
 		argc--;
 
 		if (!strcasecmp(arg_name, "skip_block_zeroing"))
-			pf->zero_new_blocks = 0;
+			pf->zero_new_blocks = false;
 
 		else if (!strcasecmp(arg_name, "ignore_discard"))
-			pf->discard_enabled = 0;
+			pf->discard_enabled = false;
 
 		else if (!strcasecmp(arg_name, "no_discard_passdown"))
-			pf->discard_passdown = 0;
+			pf->discard_passdown = false;
 
 		else if (!strcasecmp(arg_name, "read_only"))
 			pf->mode = PM_READ_ONLY;
@@ -2245,22 +2272,14 @@ static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv)
 		goto out_flags_changed;
 	}
 
-	/*
-	 * The block layer requires discard_granularity to be a power of 2.
-	 */
-	if (pf.discard_enabled && !is_power_of_2(block_size)) {
-		ti->error = "Discard support must be disabled when the block size is not a power of 2";
-		r = -EINVAL;
-		goto out_flags_changed;
-	}
-
 	pt->pool = pool;
 	pt->ti = ti;
 	pt->metadata_dev = metadata_dev;
 	pt->data_dev = data_dev;
 	pt->low_water_blocks = low_water_blocks;
-	pt->pf = pf;
+	pt->adjusted_pf = pt->requested_pf = pf;
 	ti->num_flush_requests = 1;
+
 	/*
 	 * Only need to enable discards if the pool should pass
 	 * them down to the data device.  The thin device's discard
@@ -2268,12 +2287,14 @@ static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv)
 	 */
 	if (pf.discard_enabled && pf.discard_passdown) {
 		ti->num_discard_requests = 1;
+
 		/*
 		 * Setting 'discards_supported' circumvents the normal
 		 * stacking of discard limits (this keeps the pool and
 		 * thin devices' discard limits consistent).
 		 */
 		ti->discards_supported = true;
+		ti->discard_zeroes_data_unsupported = true;
 	}
 	ti->private = pt;
 
@@ -2703,7 +2724,7 @@ static int pool_status(struct dm_target *ti, status_type_t type,
 		       format_dev_t(buf2, pt->data_dev->bdev->bd_dev),
 		       (unsigned long)pool->sectors_per_block,
 		       (unsigned long long)pt->low_water_blocks);
-		emit_flags(&pt->pf, result, sz, maxlen);
+		emit_flags(&pt->requested_pf, result, sz, maxlen);
 		break;
 	}
 
@@ -2732,20 +2753,34 @@ static int pool_merge(struct dm_target *ti, struct bvec_merge_data *bvm,
 	return min(max_size, q->merge_bvec_fn(q, bvm, biovec));
 }
 
-static void set_discard_limits(struct pool *pool, struct queue_limits *limits)
+static bool block_size_is_power_of_two(struct pool *pool)
 {
-	/*
-	 * FIXME: these limits may be incompatible with the pool's data device
-	 */
+	return pool->sectors_per_block_shift >= 0;
+}
+
+static void set_discard_limits(struct pool_c *pt, struct queue_limits *limits)
+{
+	struct pool *pool = pt->pool;
+	struct queue_limits *data_limits;
+
 	limits->max_discard_sectors = pool->sectors_per_block;
 
 	/*
-	 * This is just a hint, and not enforced.  We have to cope with
-	 * bios that cover a block partially.  A discard that spans a block
-	 * boundary is not sent to this target.
+	 * discard_granularity is just a hint, and not enforced.
 	 */
-	limits->discard_granularity = pool->sectors_per_block << SECTOR_SHIFT;
-	limits->discard_zeroes_data = pool->pf.zero_new_blocks;
+	if (pt->adjusted_pf.discard_passdown) {
+		data_limits = &bdev_get_queue(pt->data_dev->bdev)->limits;
+		limits->discard_granularity = data_limits->discard_granularity;
+	} else if (block_size_is_power_of_two(pool))
+		limits->discard_granularity = pool->sectors_per_block << SECTOR_SHIFT;
+	else
+		/*
+		 * Use largest power of 2 that is a factor of sectors_per_block
+		 * but at least DATA_DEV_BLOCK_SIZE_MIN_SECTORS.
+		 */
+		limits->discard_granularity = max(1 << (ffs(pool->sectors_per_block) - 1),
+						  DATA_DEV_BLOCK_SIZE_MIN_SECTORS) << SECTOR_SHIFT;
+
 }
 
 static void pool_io_hints(struct dm_target *ti, struct queue_limits *limits)
@@ -2755,15 +2790,25 @@ static void pool_io_hints(struct dm_target *ti, struct queue_limits *limits)
 
 	blk_limits_io_min(limits, 0);
 	blk_limits_io_opt(limits, pool->sectors_per_block << SECTOR_SHIFT);
-	if (pool->pf.discard_enabled)
-		set_discard_limits(pool, limits);
+
+	/*
+	 * pt->adjusted_pf is a staging area for the actual features to use.
+	 * They get transferred to the live pool in bind_control_target()
+	 * called from pool_preresume().
+	 */
+	if (!pt->adjusted_pf.discard_enabled)
+		return;
+
+	disable_passdown_if_not_supported(pt);
+
+	set_discard_limits(pt, limits);
 }
 
 static struct target_type pool_target = {
 	.name = "thin-pool",
 	.features = DM_TARGET_SINGLETON | DM_TARGET_ALWAYS_WRITEABLE |
 		    DM_TARGET_IMMUTABLE,
-	.version = {1, 3, 0},
+	.version = {1, 4, 0},
 	.module = THIS_MODULE,
 	.ctr = pool_ctr,
 	.dtr = pool_dtr,
@@ -3042,19 +3087,19 @@ static int thin_iterate_devices(struct dm_target *ti,
 	return 0;
 }
 
+/*
+ * A thin device always inherits its queue limits from its pool.
+ */
 static void thin_io_hints(struct dm_target *ti, struct queue_limits *limits)
 {
 	struct thin_c *tc = ti->private;
-	struct pool *pool = tc->pool;
 
-	blk_limits_io_min(limits, 0);
-	blk_limits_io_opt(limits, pool->sectors_per_block << SECTOR_SHIFT);
-	set_discard_limits(pool, limits);
+	*limits = bdev_get_queue(tc->pool_dev->bdev)->limits;
 }
 
 static struct target_type thin_target = {
 	.name = "thin",
-	.version = {1, 3, 0},
+	.version = {1, 4, 0},
 	.module	= THIS_MODULE,
 	.ctr = thin_ctr,
 	.dtr = thin_dtr,
diff --git a/drivers/md/dm-verity.c b/drivers/md/dm-verity.c
index 254d192..9e7328b 100644
--- a/drivers/md/dm-verity.c
+++ b/drivers/md/dm-verity.c
@@ -438,7 +438,7 @@ static void verity_prefetch_io(struct dm_verity *v, struct dm_verity_io *io)
 		verity_hash_at_level(v, io->block, i, &hash_block_start, NULL);
 		verity_hash_at_level(v, io->block + io->n_blocks - 1, i, &hash_block_end, NULL);
 		if (!i) {
-			unsigned cluster = *(volatile unsigned *)&dm_verity_prefetch_cluster;
+			unsigned cluster = ACCESS_ONCE(dm_verity_prefetch_cluster);
 
 			cluster >>= v->data_dev_block_bits;
 			if (unlikely(!cluster))
@@ -718,8 +718,8 @@ static int verity_ctr(struct dm_target *ti, unsigned argc, char **argv)
 	v->hash_dev_block_bits = ffs(num) - 1;
 
 	if (sscanf(argv[5], "%llu%c", &num_ll, &dummy) != 1 ||
-	    num_ll << (v->data_dev_block_bits - SECTOR_SHIFT) !=
-	    (sector_t)num_ll << (v->data_dev_block_bits - SECTOR_SHIFT)) {
+	    (sector_t)(num_ll << (v->data_dev_block_bits - SECTOR_SHIFT))
+	    >> (v->data_dev_block_bits - SECTOR_SHIFT) != num_ll) {
 		ti->error = "Invalid data blocks";
 		r = -EINVAL;
 		goto bad;
@@ -733,8 +733,8 @@ static int verity_ctr(struct dm_target *ti, unsigned argc, char **argv)
 	}
 
 	if (sscanf(argv[6], "%llu%c", &num_ll, &dummy) != 1 ||
-	    num_ll << (v->hash_dev_block_bits - SECTOR_SHIFT) !=
-	    (sector_t)num_ll << (v->hash_dev_block_bits - SECTOR_SHIFT)) {
+	    (sector_t)(num_ll << (v->hash_dev_block_bits - SECTOR_SHIFT))
+	    >> (v->hash_dev_block_bits - SECTOR_SHIFT) != num_ll) {
 		ti->error = "Invalid hash start";
 		r = -EINVAL;
 		goto bad;
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 4e09b6f..8cdc108 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -71,6 +71,7 @@ struct dm_target_io {
 	struct dm_io *io;
 	struct dm_target *ti;
 	union map_info info;
+	struct bio clone;
 };
 
 /*
@@ -86,12 +87,17 @@ struct dm_rq_target_io {
 };
 
 /*
- * For request-based dm.
- * One of these is allocated per bio.
+ * For request-based dm - the bio clones we allocate are embedded in these
+ * structs.
+ *
+ * We allocate these with bio_alloc_bioset, using the front_pad parameter when
+ * the bioset is created - this means the bio has to come at the end of the
+ * struct.
  */
 struct dm_rq_clone_bio_info {
 	struct bio *orig;
 	struct dm_rq_target_io *tio;
+	struct bio clone;
 };
 
 union map_info *dm_get_mapinfo(struct bio *bio)
@@ -211,6 +217,11 @@ struct dm_md_mempools {
 static struct kmem_cache *_io_cache;
 static struct kmem_cache *_tio_cache;
 static struct kmem_cache *_rq_tio_cache;
+
+/*
+ * Unused now, and needs to be deleted. But since io_pool is overloaded and it's
+ * still used for _io_cache, I'm leaving this for a later cleanup
+ */
 static struct kmem_cache *_rq_bio_info_cache;
 
 static int __init local_init(void)
@@ -453,7 +464,7 @@ static void free_io(struct mapped_device *md, struct dm_io *io)
 
 static void free_tio(struct mapped_device *md, struct dm_target_io *tio)
 {
-	mempool_free(tio, md->tio_pool);
+	bio_put(&tio->clone);
 }
 
 static struct dm_rq_target_io *alloc_rq_tio(struct mapped_device *md,
@@ -467,16 +478,6 @@ static void free_rq_tio(struct dm_rq_target_io *tio)
 	mempool_free(tio, tio->md->tio_pool);
 }
 
-static struct dm_rq_clone_bio_info *alloc_bio_info(struct mapped_device *md)
-{
-	return mempool_alloc(md->io_pool, GFP_ATOMIC);
-}
-
-static void free_bio_info(struct dm_rq_clone_bio_info *info)
-{
-	mempool_free(info, info->tio->md->io_pool);
-}
-
 static int md_in_flight(struct mapped_device *md)
 {
 	return atomic_read(&md->pending[READ]) +
@@ -681,13 +682,7 @@ static void clone_endio(struct bio *bio, int error)
 		}
 	}
 
-	/*
-	 * Store md for cleanup instead of tio which is about to get freed.
-	 */
-	bio->bi_private = md->bs;
-
 	free_tio(md, tio);
-	bio_put(bio);
 	dec_pending(io, error);
 }
 
@@ -865,10 +860,14 @@ static void dm_done(struct request *clone, int error, bool mapped)
 {
 	int r = error;
 	struct dm_rq_target_io *tio = clone->end_io_data;
-	dm_request_endio_fn rq_end_io = tio->ti->type->rq_end_io;
+	dm_request_endio_fn rq_end_io = NULL;
 
-	if (mapped && rq_end_io)
-		r = rq_end_io(tio->ti, clone, error, &tio->info);
+	if (tio->ti) {
+		rq_end_io = tio->ti->type->rq_end_io;
+
+		if (mapped && rq_end_io)
+			r = rq_end_io(tio->ti, clone, error, &tio->info);
+	}
 
 	if (r <= 0)
 		/* The target wants to complete the I/O */
@@ -1003,12 +1002,12 @@ int dm_set_target_max_io_len(struct dm_target *ti, sector_t len)
 }
 EXPORT_SYMBOL_GPL(dm_set_target_max_io_len);
 
-static void __map_bio(struct dm_target *ti, struct bio *clone,
-		      struct dm_target_io *tio)
+static void __map_bio(struct dm_target *ti, struct dm_target_io *tio)
 {
 	int r;
 	sector_t sector;
 	struct mapped_device *md;
+	struct bio *clone = &tio->clone;
 
 	clone->bi_end_io = clone_endio;
 	clone->bi_private = tio;
@@ -1032,12 +1031,6 @@ static void __map_bio(struct dm_target *ti, struct bio *clone,
 		/* error the io and bail out, or requeue it if needed */
 		md = tio->io->md;
 		dec_pending(tio->io, r);
-		/*
-		 * Store bio_set for cleanup.
-		 */
-		clone->bi_end_io = NULL;
-		clone->bi_private = md->bs;
-		bio_put(clone);
 		free_tio(md, tio);
 	} else if (r) {
 		DMWARN("unimplemented target map return value: %d", r);
@@ -1055,25 +1048,16 @@ struct clone_info {
 	unsigned short idx;
 };
 
-static void dm_bio_destructor(struct bio *bio)
-{
-	struct bio_set *bs = bio->bi_private;
-
-	bio_free(bio, bs);
-}
-
 /*
  * Creates a little bio that just does part of a bvec.
  */
-static struct bio *split_bvec(struct bio *bio, sector_t sector,
-			      unsigned short idx, unsigned int offset,
-			      unsigned int len, struct bio_set *bs)
+static void split_bvec(struct dm_target_io *tio, struct bio *bio,
+		       sector_t sector, unsigned short idx, unsigned int offset,
+		       unsigned int len, struct bio_set *bs)
 {
-	struct bio *clone;
+	struct bio *clone = &tio->clone;
 	struct bio_vec *bv = bio->bi_io_vec + idx;
 
-	clone = bio_alloc_bioset(GFP_NOIO, 1, bs);
-	clone->bi_destructor = dm_bio_destructor;
 	*clone->bi_io_vec = *bv;
 
 	clone->bi_sector = sector;
@@ -1086,26 +1070,23 @@ static struct bio *split_bvec(struct bio *bio, sector_t sector,
 	clone->bi_flags |= 1 << BIO_CLONED;
 
 	if (bio_integrity(bio)) {
-		bio_integrity_clone(clone, bio, GFP_NOIO, bs);
+		bio_integrity_clone(clone, bio, GFP_NOIO);
 		bio_integrity_trim(clone,
 				   bio_sector_offset(bio, idx, offset), len);
 	}
-
-	return clone;
 }
 
 /*
  * Creates a bio that consists of range of complete bvecs.
  */
-static struct bio *clone_bio(struct bio *bio, sector_t sector,
-			     unsigned short idx, unsigned short bv_count,
-			     unsigned int len, struct bio_set *bs)
+static void clone_bio(struct dm_target_io *tio, struct bio *bio,
+		      sector_t sector, unsigned short idx,
+		      unsigned short bv_count, unsigned int len,
+		      struct bio_set *bs)
 {
-	struct bio *clone;
+	struct bio *clone = &tio->clone;
 
-	clone = bio_alloc_bioset(GFP_NOIO, bio->bi_max_vecs, bs);
 	__bio_clone(clone, bio);
-	clone->bi_destructor = dm_bio_destructor;
 	clone->bi_sector = sector;
 	clone->bi_idx = idx;
 	clone->bi_vcnt = idx + bv_count;
@@ -1113,20 +1094,22 @@ static struct bio *clone_bio(struct bio *bio, sector_t sector,
 	clone->bi_flags &= ~(1 << BIO_SEG_VALID);
 
 	if (bio_integrity(bio)) {
-		bio_integrity_clone(clone, bio, GFP_NOIO, bs);
+		bio_integrity_clone(clone, bio, GFP_NOIO);
 
 		if (idx != bio->bi_idx || clone->bi_size < bio->bi_size)
 			bio_integrity_trim(clone,
 					   bio_sector_offset(bio, idx, 0), len);
 	}
-
-	return clone;
 }
 
 static struct dm_target_io *alloc_tio(struct clone_info *ci,
-				      struct dm_target *ti)
+				      struct dm_target *ti, int nr_iovecs)
 {
-	struct dm_target_io *tio = mempool_alloc(ci->md->tio_pool, GFP_NOIO);
+	struct dm_target_io *tio;
+	struct bio *clone;
+
+	clone = bio_alloc_bioset(GFP_NOIO, nr_iovecs, ci->md->bs);
+	tio = container_of(clone, struct dm_target_io, clone);
 
 	tio->io = ci->io;
 	tio->ti = ti;
@@ -1138,8 +1121,8 @@ static struct dm_target_io *alloc_tio(struct clone_info *ci,
 static void __issue_target_request(struct clone_info *ci, struct dm_target *ti,
 				   unsigned request_nr, sector_t len)
 {
-	struct dm_target_io *tio = alloc_tio(ci, ti);
-	struct bio *clone;
+	struct dm_target_io *tio = alloc_tio(ci, ti, ci->bio->bi_max_vecs);
+	struct bio *clone = &tio->clone;
 
 	tio->info.target_request_nr = request_nr;
 
@@ -1148,15 +1131,13 @@ static void __issue_target_request(struct clone_info *ci, struct dm_target *ti,
 	 * ci->bio->bi_max_vecs is BIO_INLINE_VECS anyway, for both flush
 	 * and discard, so no need for concern about wasted bvec allocations.
 	 */
-	clone = bio_alloc_bioset(GFP_NOIO, ci->bio->bi_max_vecs, ci->md->bs);
-	__bio_clone(clone, ci->bio);
-	clone->bi_destructor = dm_bio_destructor;
+
 	if (len) {
 		clone->bi_sector = ci->sector;
 		clone->bi_size = to_bytes(len);
 	}
 
-	__map_bio(ti, clone, tio);
+	__map_bio(ti, tio);
 }
 
 static void __issue_target_requests(struct clone_info *ci, struct dm_target *ti,
@@ -1185,14 +1166,13 @@ static int __clone_and_map_empty_flush(struct clone_info *ci)
  */
 static void __clone_and_map_simple(struct clone_info *ci, struct dm_target *ti)
 {
-	struct bio *clone, *bio = ci->bio;
+	struct bio *bio = ci->bio;
 	struct dm_target_io *tio;
 
-	tio = alloc_tio(ci, ti);
-	clone = clone_bio(bio, ci->sector, ci->idx,
-			  bio->bi_vcnt - ci->idx, ci->sector_count,
-			  ci->md->bs);
-	__map_bio(ti, clone, tio);
+	tio = alloc_tio(ci, ti, bio->bi_max_vecs);
+	clone_bio(tio, bio, ci->sector, ci->idx, bio->bi_vcnt - ci->idx,
+		  ci->sector_count, ci->md->bs);
+	__map_bio(ti, tio);
 	ci->sector_count = 0;
 }
 
@@ -1230,7 +1210,7 @@ static int __clone_and_map_discard(struct clone_info *ci)
 
 static int __clone_and_map(struct clone_info *ci)
 {
-	struct bio *clone, *bio = ci->bio;
+	struct bio *bio = ci->bio;
 	struct dm_target *ti;
 	sector_t len = 0, max;
 	struct dm_target_io *tio;
@@ -1270,10 +1250,10 @@ static int __clone_and_map(struct clone_info *ci)
 			len += bv_len;
 		}
 
-		tio = alloc_tio(ci, ti);
-		clone = clone_bio(bio, ci->sector, ci->idx, i - ci->idx, len,
-				  ci->md->bs);
-		__map_bio(ti, clone, tio);
+		tio = alloc_tio(ci, ti, bio->bi_max_vecs);
+		clone_bio(tio, bio, ci->sector, ci->idx, i - ci->idx, len,
+			  ci->md->bs);
+		__map_bio(ti, tio);
 
 		ci->sector += len;
 		ci->sector_count -= len;
@@ -1298,12 +1278,11 @@ static int __clone_and_map(struct clone_info *ci)
 
 			len = min(remaining, max);
 
-			tio = alloc_tio(ci, ti);
-			clone = split_bvec(bio, ci->sector, ci->idx,
-					   bv->bv_offset + offset, len,
-					   ci->md->bs);
+			tio = alloc_tio(ci, ti, 1);
+			split_bvec(tio, bio, ci->sector, ci->idx,
+				   bv->bv_offset + offset, len, ci->md->bs);
 
-			__map_bio(ti, clone, tio);
+			__map_bio(ti, tio);
 
 			ci->sector += len;
 			ci->sector_count -= len;
@@ -1480,30 +1459,17 @@ void dm_dispatch_request(struct request *rq)
 }
 EXPORT_SYMBOL_GPL(dm_dispatch_request);
 
-static void dm_rq_bio_destructor(struct bio *bio)
-{
-	struct dm_rq_clone_bio_info *info = bio->bi_private;
-	struct mapped_device *md = info->tio->md;
-
-	free_bio_info(info);
-	bio_free(bio, md->bs);
-}
-
 static int dm_rq_bio_constructor(struct bio *bio, struct bio *bio_orig,
 				 void *data)
 {
 	struct dm_rq_target_io *tio = data;
-	struct mapped_device *md = tio->md;
-	struct dm_rq_clone_bio_info *info = alloc_bio_info(md);
-
-	if (!info)
-		return -ENOMEM;
+	struct dm_rq_clone_bio_info *info =
+		container_of(bio, struct dm_rq_clone_bio_info, clone);
 
 	info->orig = bio_orig;
 	info->tio = tio;
 	bio->bi_end_io = end_clone_bio;
 	bio->bi_private = info;
-	bio->bi_destructor = dm_rq_bio_destructor;
 
 	return 0;
 }
@@ -1588,15 +1554,6 @@ static int map_request(struct dm_target *ti, struct request *clone,
 	int r, requeued = 0;
 	struct dm_rq_target_io *tio = clone->end_io_data;
 
-	/*
-	 * Hold the md reference here for the in-flight I/O.
-	 * We can't rely on the reference count by device opener,
-	 * because the device may be closed during the request completion
-	 * when all bios are completed.
-	 * See the comment in rq_completed() too.
-	 */
-	dm_get(md);
-
 	tio->ti = ti;
 	r = ti->type->map_rq(ti, clone, &tio->info);
 	switch (r) {
@@ -1628,6 +1585,26 @@ static int map_request(struct dm_target *ti, struct request *clone,
 	return requeued;
 }
 
+static struct request *dm_start_request(struct mapped_device *md, struct request *orig)
+{
+	struct request *clone;
+
+	blk_start_request(orig);
+	clone = orig->special;
+	atomic_inc(&md->pending[rq_data_dir(clone)]);
+
+	/*
+	 * Hold the md reference here for the in-flight I/O.
+	 * We can't rely on the reference count by device opener,
+	 * because the device may be closed during the request completion
+	 * when all bios are completed.
+	 * See the comment in rq_completed() too.
+	 */
+	dm_get(md);
+
+	return clone;
+}
+
 /*
  * q->request_fn for request-based dm.
  * Called with the queue lock held.
@@ -1657,14 +1634,21 @@ static void dm_request_fn(struct request_queue *q)
 			pos = blk_rq_pos(rq);
 
 		ti = dm_table_find_target(map, pos);
-		BUG_ON(!dm_target_is_valid(ti));
+		if (!dm_target_is_valid(ti)) {
+			/*
+			 * Must perform setup, that dm_done() requires,
+			 * before calling dm_kill_unmapped_request
+			 */
+			DMERR_LIMIT("request attempted access beyond the end of device");
+			clone = dm_start_request(md, rq);
+			dm_kill_unmapped_request(clone, -EIO);
+			continue;
+		}
 
 		if (ti->type->busy && ti->type->busy(ti))
 			goto delay_and_out;
 
-		blk_start_request(rq);
-		clone = rq->special;
-		atomic_inc(&md->pending[rq_data_dir(clone)]);
+		clone = dm_start_request(md, rq);
 
 		spin_unlock(q->queue_lock);
 		if (map_request(ti, clone, md))
@@ -1684,8 +1668,6 @@ delay_and_out:
 	blk_delay_queue(q, HZ / 10);
 out:
 	dm_table_put(map);
-
-	return;
 }
 
 int dm_underlying_device_busy(struct request_queue *q)
@@ -2409,7 +2391,7 @@ static void dm_queue_flush(struct mapped_device *md)
  */
 struct dm_table *dm_swap_table(struct mapped_device *md, struct dm_table *table)
 {
-	struct dm_table *map = ERR_PTR(-EINVAL);
+	struct dm_table *live_map, *map = ERR_PTR(-EINVAL);
 	struct queue_limits limits;
 	int r;
 
@@ -2419,6 +2401,19 @@ struct dm_table *dm_swap_table(struct mapped_device *md, struct dm_table *table)
 	if (!dm_suspended_md(md))
 		goto out;
 
+	/*
+	 * If the new table has no data devices, retain the existing limits.
+	 * This helps multipath with queue_if_no_path if all paths disappear,
+	 * then new I/O is queued based on these limits, and then some paths
+	 * reappear.
+	 */
+	if (dm_table_has_no_data_devices(table)) {
+		live_map = dm_get_live_table(md);
+		if (live_map)
+			limits = md->queue->limits;
+		dm_table_put(live_map);
+	}
+
 	r = dm_calculate_queue_limits(table, &limits);
 	if (r) {
 		map = ERR_PTR(r);
@@ -2738,7 +2733,11 @@ struct dm_md_mempools *dm_alloc_md_mempools(unsigned type, unsigned integrity)
 	if (!pools->tio_pool)
 		goto free_io_pool_and_out;
 
-	pools->bs = bioset_create(pool_size, 0);
+	pools->bs = (type == DM_TYPE_BIO_BASED) ?
+		bioset_create(pool_size,
+			      offsetof(struct dm_target_io, clone)) :
+		bioset_create(pool_size,
+			      offsetof(struct dm_rq_clone_bio_info, clone));
 	if (!pools->bs)
 		goto free_tio_pool_and_out;
 
diff --git a/drivers/md/dm.h b/drivers/md/dm.h
index 52eef49..6a99fef 100644
--- a/drivers/md/dm.h
+++ b/drivers/md/dm.h
@@ -54,6 +54,7 @@ void dm_table_event_callback(struct dm_table *t,
 			     void (*fn)(void *), void *context);
 struct dm_target *dm_table_get_target(struct dm_table *t, unsigned int index);
 struct dm_target *dm_table_find_target(struct dm_table *t, sector_t sector);
+bool dm_table_has_no_data_devices(struct dm_table *table);
 int dm_calculate_queue_limits(struct dm_table *table,
 			      struct queue_limits *limits);
 void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
diff --git a/drivers/md/linear.c b/drivers/md/linear.c
index fa211d8..2101483 100644
--- a/drivers/md/linear.c
+++ b/drivers/md/linear.c
@@ -138,6 +138,7 @@ static struct linear_conf *linear_conf(struct mddev *mddev, int raid_disks)
 	struct linear_conf *conf;
 	struct md_rdev *rdev;
 	int i, cnt;
+	bool discard_supported = false;
 
 	conf = kzalloc (sizeof (*conf) + raid_disks*sizeof(struct dev_info),
 			GFP_KERNEL);
@@ -171,6 +172,8 @@ static struct linear_conf *linear_conf(struct mddev *mddev, int raid_disks)
 		conf->array_sectors += rdev->sectors;
 		cnt++;
 
+		if (blk_queue_discard(bdev_get_queue(rdev->bdev)))
+			discard_supported = true;
 	}
 	if (cnt != raid_disks) {
 		printk(KERN_ERR "md/linear:%s: not enough drives present. Aborting!\n",
@@ -178,6 +181,11 @@ static struct linear_conf *linear_conf(struct mddev *mddev, int raid_disks)
 		goto out;
 	}
 
+	if (!discard_supported)
+		queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, mddev->queue);
+	else
+		queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, mddev->queue);
+
 	/*
 	 * Here we calculate the device offsets.
 	 */
@@ -244,7 +252,9 @@ static int linear_add(struct mddev *mddev, struct md_rdev *rdev)
 	if (!newconf)
 		return -ENOMEM;
 
-	oldconf = rcu_dereference(mddev->private);
+	oldconf = rcu_dereference_protected(mddev->private,
+					    lockdep_is_held(
+						    &mddev->reconfig_mutex));
 	mddev->raid_disks++;
 	rcu_assign_pointer(mddev->private, newconf);
 	md_set_array_sectors(mddev, linear_size(mddev, 0, 0));
@@ -256,7 +266,10 @@ static int linear_add(struct mddev *mddev, struct md_rdev *rdev)
 
 static int linear_stop (struct mddev *mddev)
 {
-	struct linear_conf *conf = mddev->private;
+	struct linear_conf *conf =
+		rcu_dereference_protected(mddev->private,
+					  lockdep_is_held(
+						  &mddev->reconfig_mutex));
 
 	/*
 	 * We do not require rcu protection here since
@@ -326,6 +339,14 @@ static void linear_make_request(struct mddev *mddev, struct bio *bio)
 	bio->bi_sector = bio->bi_sector - start_sector
 		+ tmp_dev->rdev->data_offset;
 	rcu_read_unlock();
+
+	if (unlikely((bio->bi_rw & REQ_DISCARD) &&
+		     !blk_queue_discard(bdev_get_queue(bio->bi_bdev)))) {
+		/* Just ignore it */
+		bio_endio(bio, 0);
+		return;
+	}
+
 	generic_make_request(bio);
 }
 
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 308e87b..c1d1547 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -155,32 +155,17 @@ static int start_readonly;
  * like bio_clone, but with a local bio set
  */
 
-static void mddev_bio_destructor(struct bio *bio)
-{
-	struct mddev *mddev, **mddevp;
-
-	mddevp = (void*)bio;
-	mddev = mddevp[-1];
-
-	bio_free(bio, mddev->bio_set);
-}
-
 struct bio *bio_alloc_mddev(gfp_t gfp_mask, int nr_iovecs,
 			    struct mddev *mddev)
 {
 	struct bio *b;
-	struct mddev **mddevp;
 
 	if (!mddev || !mddev->bio_set)
 		return bio_alloc(gfp_mask, nr_iovecs);
 
-	b = bio_alloc_bioset(gfp_mask, nr_iovecs,
-			     mddev->bio_set);
+	b = bio_alloc_bioset(gfp_mask, nr_iovecs, mddev->bio_set);
 	if (!b)
 		return NULL;
-	mddevp = (void*)b;
-	mddevp[-1] = mddev;
-	b->bi_destructor = mddev_bio_destructor;
 	return b;
 }
 EXPORT_SYMBOL_GPL(bio_alloc_mddev);
@@ -188,32 +173,10 @@ EXPORT_SYMBOL_GPL(bio_alloc_mddev);
 struct bio *bio_clone_mddev(struct bio *bio, gfp_t gfp_mask,
 			    struct mddev *mddev)
 {
-	struct bio *b;
-	struct mddev **mddevp;
-
 	if (!mddev || !mddev->bio_set)
 		return bio_clone(bio, gfp_mask);
 
-	b = bio_alloc_bioset(gfp_mask, bio->bi_max_vecs,
-			     mddev->bio_set);
-	if (!b)
-		return NULL;
-	mddevp = (void*)b;
-	mddevp[-1] = mddev;
-	b->bi_destructor = mddev_bio_destructor;
-	__bio_clone(b, bio);
-	if (bio_integrity(bio)) {
-		int ret;
-
-		ret = bio_integrity_clone(b, bio, gfp_mask, mddev->bio_set);
-
-		if (ret < 0) {
-			bio_put(b);
-			return NULL;
-		}
-	}
-
-	return b;
+	return bio_clone_bioset(bio, gfp_mask, mddev->bio_set);
 }
 EXPORT_SYMBOL_GPL(bio_clone_mddev);
 
@@ -640,9 +603,9 @@ static struct mddev * mddev_find(dev_t unit)
 	goto retry;
 }
 
-static inline int mddev_lock(struct mddev * mddev)
+int md_queue_misc_work(struct work_struct *work)
 {
-	return mutex_lock_interruptible(&mddev->reconfig_mutex);
+	return queue_work(md_misc_wq, work);
 }
 
 static inline int mddev_is_locked(struct mddev *mddev)
@@ -657,7 +620,7 @@ static inline int mddev_trylock(struct mddev * mddev)
 
 static struct attribute_group md_redundancy_group;
 
-static void mddev_unlock(struct mddev * mddev)
+void mddev_unlock(struct mddev * mddev)
 {
 	if (mddev->to_remove) {
 		/* These cannot be removed under reconfig_mutex as
@@ -711,6 +674,17 @@ static struct md_rdev * find_rdev_nr(struct mddev *mddev, int nr)
 	return NULL;
 }
 
+static struct md_rdev * find_rdev_nr_rcu(struct mddev *mddev, int nr)
+{
+	struct md_rdev *rdev;
+
+	rdev_for_each_rcu(rdev, mddev)
+		if (rdev->desc_nr == nr)
+			return rdev;
+
+	return NULL;
+}
+
 static struct md_rdev * find_rdev(struct mddev * mddev, dev_t dev)
 {
 	struct md_rdev *rdev;
@@ -722,6 +696,17 @@ static struct md_rdev * find_rdev(struct mddev * mddev, dev_t dev)
 	return NULL;
 }
 
+static struct md_rdev * find_rdev_rcu(struct mddev * mddev, dev_t dev)
+{
+	struct md_rdev *rdev;
+
+	rdev_for_each_rcu(rdev, mddev)
+		if (rdev->bdev->bd_dev == dev)
+			return rdev;
+
+	return NULL;
+}
+
 static struct md_personality *find_pers(int level, char *clevel)
 {
 	struct md_personality *pers;
@@ -2059,8 +2044,14 @@ EXPORT_SYMBOL(md_integrity_register);
 /* Disable data integrity if non-capable/non-matching disk is being added */
 void md_integrity_add_rdev(struct md_rdev *rdev, struct mddev *mddev)
 {
-	struct blk_integrity *bi_rdev = bdev_get_integrity(rdev->bdev);
-	struct blk_integrity *bi_mddev = blk_get_integrity(mddev->gendisk);
+	struct blk_integrity *bi_rdev;
+	struct blk_integrity *bi_mddev;
+
+	if (!mddev->gendisk)
+		return;
+
+	bi_rdev = bdev_get_integrity(rdev->bdev);
+	bi_mddev = blk_get_integrity(mddev->gendisk);
 
 	if (!bi_mddev) /* nothing to do */
 		return;
@@ -4399,6 +4390,10 @@ sync_completed_show(struct mddev *mddev, char *page)
 	if (!test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
 		return sprintf(page, "none\n");
 
+	if (mddev->curr_resync == 1 ||
+	    mddev->curr_resync == 2)
+		return sprintf(page, "delayed\n");
+
 	if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery) ||
 	    test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery))
 		max_sectors = mddev->resync_max_sectors;
@@ -5006,8 +5001,7 @@ int md_run(struct mddev *mddev)
 	}
 
 	if (mddev->bio_set == NULL)
-		mddev->bio_set = bioset_create(BIO_POOL_SIZE,
-					       sizeof(struct mddev *));
+		mddev->bio_set = bioset_create(BIO_POOL_SIZE, 0);
 
 	spin_lock(&pers_lock);
 	pers = find_pers(mddev->level, mddev->clevel);
@@ -5547,8 +5541,9 @@ static int get_array_info(struct mddev * mddev, void __user * arg)
 	int nr,working,insync,failed,spare;
 	struct md_rdev *rdev;
 
-	nr=working=insync=failed=spare=0;
-	rdev_for_each(rdev, mddev) {
+	nr = working = insync = failed = spare = 0;
+	rcu_read_lock();
+	rdev_for_each_rcu(rdev, mddev) {
 		nr++;
 		if (test_bit(Faulty, &rdev->flags))
 			failed++;
@@ -5560,6 +5555,7 @@ static int get_array_info(struct mddev * mddev, void __user * arg)
 				spare++;
 		}
 	}
+	rcu_read_unlock();
 
 	info.major_version = mddev->major_version;
 	info.minor_version = mddev->minor_version;
@@ -5643,7 +5639,8 @@ static int get_disk_info(struct mddev * mddev, void __user * arg)
 	if (copy_from_user(&info, arg, sizeof(info)))
 		return -EFAULT;
 
-	rdev = find_rdev_nr(mddev, info.number);
+	rcu_read_lock();
+	rdev = find_rdev_nr_rcu(mddev, info.number);
 	if (rdev) {
 		info.major = MAJOR(rdev->bdev->bd_dev);
 		info.minor = MINOR(rdev->bdev->bd_dev);
@@ -5662,6 +5659,7 @@ static int get_disk_info(struct mddev * mddev, void __user * arg)
 		info.raid_disk = -1;
 		info.state = (1<<MD_DISK_REMOVED);
 	}
+	rcu_read_unlock();
 
 	if (copy_to_user(arg, &info, sizeof(info)))
 		return -EFAULT;
@@ -6270,18 +6268,22 @@ static int update_array_info(struct mddev *mddev, mdu_array_info_t *info)
 static int set_disk_faulty(struct mddev *mddev, dev_t dev)
 {
 	struct md_rdev *rdev;
+	int err = 0;
 
 	if (mddev->pers == NULL)
 		return -ENODEV;
 
-	rdev = find_rdev(mddev, dev);
+	rcu_read_lock();
+	rdev = find_rdev_rcu(mddev, dev);
 	if (!rdev)
-		return -ENODEV;
-
-	md_error(mddev, rdev);
-	if (!test_bit(Faulty, &rdev->flags))
-		return -EBUSY;
-	return 0;
+		err =  -ENODEV;
+	else {
+		md_error(mddev, rdev);
+		if (!test_bit(Faulty, &rdev->flags))
+			err = -EBUSY;
+	}
+	rcu_read_unlock();
+	return err;
 }
 
 /*
@@ -6353,6 +6355,27 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode,
 		goto abort;
 	}
 
+	/* Some actions do not requires the mutex */
+	switch (cmd) {
+		case GET_ARRAY_INFO:
+			if (!mddev->raid_disks && !mddev->external)
+				err = -ENODEV;
+			else
+				err = get_array_info(mddev, argp);
+			goto abort;
+
+		case GET_DISK_INFO:
+			if (!mddev->raid_disks && !mddev->external)
+				err = -ENODEV;
+			else
+				err = get_disk_info(mddev, argp);
+			goto abort;
+
+		case SET_DISK_FAULTY:
+			err = set_disk_faulty(mddev, new_decode_dev(arg));
+			goto abort;
+	}
+
 	err = mddev_lock(mddev);
 	if (err) {
 		printk(KERN_INFO 
@@ -6425,18 +6448,10 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode,
 	 */
 	switch (cmd)
 	{
-		case GET_ARRAY_INFO:
-			err = get_array_info(mddev, argp);
-			goto done_unlock;
-
 		case GET_BITMAP_FILE:
 			err = get_bitmap_file(mddev, argp);
 			goto done_unlock;
 
-		case GET_DISK_INFO:
-			err = get_disk_info(mddev, argp);
-			goto done_unlock;
-
 		case RESTART_ARRAY_RW:
 			err = restart_array(mddev);
 			goto done_unlock;
@@ -6518,10 +6533,6 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode,
 			err = hot_add_disk(mddev, new_decode_dev(arg));
 			goto done_unlock;
 
-		case SET_DISK_FAULTY:
-			err = set_disk_faulty(mddev, new_decode_dev(arg));
-			goto done_unlock;
-
 		case RUN_ARRAY:
 			err = do_md_run(mddev);
 			goto done_unlock;
@@ -6679,7 +6690,7 @@ static int md_thread(void * arg)
 
 		clear_bit(THREAD_WAKEUP, &thread->flags);
 		if (!kthread_should_stop())
-			thread->run(thread->mddev);
+			thread->run(thread);
 	}
 
 	return 0;
@@ -6694,8 +6705,8 @@ void md_wakeup_thread(struct md_thread *thread)
 	}
 }
 
-struct md_thread *md_register_thread(void (*run) (struct mddev *), struct mddev *mddev,
-				 const char *name)
+struct md_thread *md_register_thread(void (*run) (struct md_thread *),
+		struct mddev *mddev, const char *name)
 {
 	struct md_thread *thread;
 
@@ -6790,7 +6801,11 @@ static void status_resync(struct seq_file *seq, struct mddev * mddev)
 	int scale;
 	unsigned int per_milli;
 
-	resync = mddev->curr_resync - atomic_read(&mddev->recovery_active);
+	if (mddev->curr_resync <= 3)
+		resync = 0;
+	else
+		resync = mddev->curr_resync
+			- atomic_read(&mddev->recovery_active);
 
 	if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery) ||
 	    test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery))
@@ -7016,7 +7031,7 @@ static int md_seq_show(struct seq_file *seq, void *v)
 				if (mddev->curr_resync > 2) {
 					status_resync(seq, mddev);
 					seq_printf(seq, "\n      ");
-				} else if (mddev->curr_resync == 1 || mddev->curr_resync == 2)
+				} else if (mddev->curr_resync >= 1)
 					seq_printf(seq, "\tresync=DELAYED\n      ");
 				else if (mddev->recovery_cp < MaxSector)
 					seq_printf(seq, "\tresync=PENDING\n      ");
@@ -7244,8 +7259,9 @@ EXPORT_SYMBOL_GPL(md_allow_write);
 
 #define SYNC_MARKS	10
 #define	SYNC_MARK_STEP	(3*HZ)
-void md_do_sync(struct mddev *mddev)
+void md_do_sync(struct md_thread *thread)
 {
+	struct mddev *mddev = thread->mddev;
 	struct mddev *mddev2;
 	unsigned int currspeed = 0,
 		 window;
@@ -7405,8 +7421,11 @@ void md_do_sync(struct mddev *mddev)
 		       "md: resuming %s of %s from checkpoint.\n",
 		       desc, mdname(mddev));
 		mddev->curr_resync = j;
-	}
+	} else
+		mddev->curr_resync = 3; /* no longer delayed */
 	mddev->curr_resync_completed = j;
+	sysfs_notify(&mddev->kobj, NULL, "sync_completed");
+	md_new_event(mddev);
 
 	blk_start_plug(&plug);
 	while (j < max_sectors) {
@@ -7459,7 +7478,7 @@ void md_do_sync(struct mddev *mddev)
 			break;
 
 		j += sectors;
-		if (j>1) mddev->curr_resync = j;
+		if (j>2) mddev->curr_resync = j;
 		mddev->curr_mark_cnt = io_sectors;
 		if (last_check == 0)
 			/* this is the earliest that rebuild will be
@@ -7581,8 +7600,6 @@ static int remove_and_add_spares(struct mddev *mddev)
 	int spares = 0;
 	int removed = 0;
 
-	mddev->curr_resync_completed = 0;
-
 	rdev_for_each(rdev, mddev)
 		if (rdev->raid_disk >= 0 &&
 		    !test_bit(Blocked, &rdev->flags) &&
@@ -7777,6 +7794,7 @@ void md_check_recovery(struct mddev *mddev)
 		/* Set RUNNING before clearing NEEDED to avoid
 		 * any transients in the value of "sync_action".
 		 */
+		mddev->curr_resync_completed = 0;
 		set_bit(MD_RECOVERY_RUNNING, &mddev->recovery);
 		/* Clear some bits that don't mean anything, but
 		 * might be left set
@@ -7790,7 +7808,7 @@ void md_check_recovery(struct mddev *mddev)
 		/* no recovery is running.
 		 * remove any failed drives, then
 		 * add spares if possible.
-		 * Spare are also removed and re-added, to allow
+		 * Spares are also removed and re-added, to allow
 		 * the personality to fail the re-add.
 		 */
 
@@ -8575,6 +8593,8 @@ EXPORT_SYMBOL(md_register_thread);
 EXPORT_SYMBOL(md_unregister_thread);
 EXPORT_SYMBOL(md_wakeup_thread);
 EXPORT_SYMBOL(md_check_recovery);
+EXPORT_SYMBOL(mddev_unlock);
+EXPORT_SYMBOL(md_queue_misc_work);
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("MD RAID framework");
 MODULE_ALIAS("md");
diff --git a/drivers/md/md.h b/drivers/md/md.h
index f385b03..dce301c 100644
--- a/drivers/md/md.h
+++ b/drivers/md/md.h
@@ -540,12 +540,13 @@ static inline void sysfs_unlink_rdev(struct mddev *mddev, struct md_rdev *rdev)
 	list_for_each_entry_rcu(rdev, &((mddev)->disks), same_set)
 
 struct md_thread {
-	void			(*run) (struct mddev *mddev);
+	void			(*run) (struct md_thread *thread);
 	struct mddev		*mddev;
 	wait_queue_head_t	wqueue;
 	unsigned long           flags;
 	struct task_struct	*tsk;
 	unsigned long		timeout;
+	void			*private;
 };
 
 #define THREAD_WAKEUP  0
@@ -584,7 +585,7 @@ static inline void safe_put_page(struct page *p)
 extern int register_md_personality(struct md_personality *p);
 extern int unregister_md_personality(struct md_personality *p);
 extern struct md_thread *md_register_thread(
-	void (*run)(struct mddev *mddev),
+	void (*run)(struct md_thread *thread),
 	struct mddev *mddev,
 	const char *name);
 extern void md_unregister_thread(struct md_thread **threadp);
@@ -603,7 +604,7 @@ extern void md_super_write(struct mddev *mddev, struct md_rdev *rdev,
 extern void md_super_wait(struct mddev *mddev);
 extern int sync_page_io(struct md_rdev *rdev, sector_t sector, int size, 
 			struct page *page, int rw, bool metadata_op);
-extern void md_do_sync(struct mddev *mddev);
+extern void md_do_sync(struct md_thread *thread);
 extern void md_new_event(struct mddev *mddev);
 extern int md_allow_write(struct mddev *mddev);
 extern void md_wait_for_blocked_rdev(struct md_rdev *rdev, struct mddev *mddev);
@@ -635,4 +636,12 @@ static inline int mddev_check_plugged(struct mddev *mddev)
 	return !!blk_check_plugged(md_unplug, mddev,
 				   sizeof(struct blk_plug_cb));
 }
+
+static inline int mddev_lock(struct mddev * mddev)
+{
+	return mutex_lock_interruptible(&mddev->reconfig_mutex);
+}
+extern void mddev_unlock(struct mddev *mddev);
+extern int md_queue_misc_work(struct work_struct *work);
+
 #endif /* _MD_MD_H */
diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c
index 61a1833..2ab23d0 100644
--- a/drivers/md/multipath.c
+++ b/drivers/md/multipath.c
@@ -335,8 +335,9 @@ abort:
  *	3.	Performs writes following reads for array syncronising.
  */
 
-static void multipathd (struct mddev *mddev)
+static void multipathd (struct md_thread *thread)
 {
+	struct mddev *mddev = thread->mddev;
 	struct multipath_bh *mp_bh;
 	struct bio *bio;
 	unsigned long flags;
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c
index de63a1f..24b3597 100644
--- a/drivers/md/raid0.c
+++ b/drivers/md/raid0.c
@@ -88,6 +88,7 @@ static int create_strip_zones(struct mddev *mddev, struct r0conf **private_conf)
 	char b[BDEVNAME_SIZE];
 	char b2[BDEVNAME_SIZE];
 	struct r0conf *conf = kzalloc(sizeof(*conf), GFP_KERNEL);
+	bool discard_supported = false;
 
 	if (!conf)
 		return -ENOMEM;
@@ -195,6 +196,9 @@ static int create_strip_zones(struct mddev *mddev, struct r0conf **private_conf)
 		if (!smallest || (rdev1->sectors < smallest->sectors))
 			smallest = rdev1;
 		cnt++;
+
+		if (blk_queue_discard(bdev_get_queue(rdev1->bdev)))
+			discard_supported = true;
 	}
 	if (cnt != mddev->raid_disks) {
 		printk(KERN_ERR "md/raid0:%s: too few disks (%d of %d) - "
@@ -272,6 +276,11 @@ static int create_strip_zones(struct mddev *mddev, struct r0conf **private_conf)
 	blk_queue_io_opt(mddev->queue,
 			 (mddev->chunk_sectors << 9) * mddev->raid_disks);
 
+	if (!discard_supported)
+		queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, mddev->queue);
+	else
+		queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, mddev->queue);
+
 	pr_debug("md/raid0:%s: done.\n", mdname(mddev));
 	*private_conf = conf;
 
@@ -422,6 +431,8 @@ static int raid0_run(struct mddev *mddev)
 	if (md_check_no_bitmap(mddev))
 		return -EINVAL;
 	blk_queue_max_hw_sectors(mddev->queue, mddev->chunk_sectors);
+	blk_queue_max_write_same_sectors(mddev->queue, mddev->chunk_sectors);
+	blk_queue_max_discard_sectors(mddev->queue, mddev->chunk_sectors);
 
 	/* if private is not null, we are here after takeover */
 	if (mddev->private == NULL) {
@@ -509,7 +520,7 @@ static void raid0_make_request(struct mddev *mddev, struct bio *bio)
 		sector_t sector = bio->bi_sector;
 		struct bio_pair *bp;
 		/* Sanity check -- queue functions should prevent this happening */
-		if (bio->bi_vcnt != 1 ||
+		if ((bio->bi_vcnt != 1 && bio->bi_vcnt != 0) ||
 		    bio->bi_idx != 0)
 			goto bad_map;
 		/* This is a one page bio that upper layers
@@ -535,6 +546,13 @@ static void raid0_make_request(struct mddev *mddev, struct bio *bio)
 	bio->bi_sector = sector_offset + zone->dev_start +
 		tmp_dev->data_offset;
 
+	if (unlikely((bio->bi_rw & REQ_DISCARD) &&
+		     !blk_queue_discard(bdev_get_queue(bio->bi_bdev)))) {
+		/* Just ignore it */
+		bio_endio(bio, 0);
+		return;
+	}
+
 	generic_make_request(bio);
 	return;
 
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 611b5f7..d705f9e 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -333,9 +333,10 @@ static void raid1_end_read_request(struct bio *bio, int error)
 		spin_unlock_irqrestore(&conf->device_lock, flags);
 	}
 
-	if (uptodate)
+	if (uptodate) {
 		raid_end_bio_io(r1_bio);
-	else {
+		rdev_dec_pending(conf->mirrors[mirror].rdev, conf->mddev);
+	} else {
 		/*
 		 * oops, read error:
 		 */
@@ -349,9 +350,8 @@ static void raid1_end_read_request(struct bio *bio, int error)
 			(unsigned long long)r1_bio->sector);
 		set_bit(R1BIO_ReadError, &r1_bio->state);
 		reschedule_retry(r1_bio);
+		/* don't drop the reference on read_disk yet */
 	}
-
-	rdev_dec_pending(conf->mirrors[mirror].rdev, conf->mddev);
 }
 
 static void close_write(struct r1bio *r1_bio)
@@ -781,7 +781,12 @@ static void flush_pending_writes(struct r1conf *conf)
 		while (bio) { /* submit pending writes */
 			struct bio *next = bio->bi_next;
 			bio->bi_next = NULL;
-			generic_make_request(bio);
+			if (unlikely((bio->bi_rw & REQ_DISCARD) &&
+			    !blk_queue_discard(bdev_get_queue(bio->bi_bdev))))
+				/* Just ignore it */
+				bio_endio(bio, 0);
+			else
+				generic_make_request(bio);
 			bio = next;
 		}
 	} else
@@ -994,6 +999,7 @@ static void make_request(struct mddev *mddev, struct bio * bio)
 	const int rw = bio_data_dir(bio);
 	const unsigned long do_sync = (bio->bi_rw & REQ_SYNC);
 	const unsigned long do_flush_fua = (bio->bi_rw & (REQ_FLUSH | REQ_FUA));
+	const unsigned long do_discard = (bio->bi_rw & (REQ_DISCARD | REQ_SECURE));
 	struct md_rdev *blocked_rdev;
 	struct blk_plug_cb *cb;
 	struct raid1_plug_cb *plug = NULL;
@@ -1295,7 +1301,7 @@ read_again:
 				   conf->mirrors[i].rdev->data_offset);
 		mbio->bi_bdev = conf->mirrors[i].rdev->bdev;
 		mbio->bi_end_io	= raid1_end_write_request;
-		mbio->bi_rw = WRITE | do_flush_fua | do_sync;
+		mbio->bi_rw = WRITE | do_flush_fua | do_sync | do_discard;
 		mbio->bi_private = r1_bio;
 
 		atomic_inc(&r1_bio->remaining);
@@ -1549,6 +1555,8 @@ static int raid1_add_disk(struct mddev *mddev, struct md_rdev *rdev)
 		clear_bit(Unmerged, &rdev->flags);
 	}
 	md_integrity_add_rdev(rdev, mddev);
+	if (blk_queue_discard(bdev_get_queue(rdev->bdev)))
+		queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, mddev->queue);
 	print_conf(conf);
 	return err;
 }
@@ -2220,6 +2228,7 @@ static void handle_read_error(struct r1conf *conf, struct r1bio *r1_bio)
 		unfreeze_array(conf);
 	} else
 		md_error(mddev, conf->mirrors[r1_bio->read_disk].rdev);
+	rdev_dec_pending(conf->mirrors[r1_bio->read_disk].rdev, conf->mddev);
 
 	bio = r1_bio->bios[r1_bio->read_disk];
 	bdevname(bio->bi_bdev, b);
@@ -2285,8 +2294,9 @@ read_more:
 	}
 }
 
-static void raid1d(struct mddev *mddev)
+static void raid1d(struct md_thread *thread)
 {
+	struct mddev *mddev = thread->mddev;
 	struct r1bio *r1_bio;
 	unsigned long flags;
 	struct r1conf *conf = mddev->private;
@@ -2783,6 +2793,7 @@ static int run(struct mddev *mddev)
 	int i;
 	struct md_rdev *rdev;
 	int ret;
+	bool discard_supported = false;
 
 	if (mddev->level != 1) {
 		printk(KERN_ERR "md/raid1:%s: raid level not set to mirroring (%d)\n",
@@ -2812,6 +2823,8 @@ static int run(struct mddev *mddev)
 			continue;
 		disk_stack_limits(mddev->gendisk, rdev->bdev,
 				  rdev->data_offset << 9);
+		if (blk_queue_discard(bdev_get_queue(rdev->bdev)))
+			discard_supported = true;
 	}
 
 	mddev->degraded = 0;
@@ -2846,6 +2859,11 @@ static int run(struct mddev *mddev)
 		mddev->queue->backing_dev_info.congested_fn = raid1_congested;
 		mddev->queue->backing_dev_info.congested_data = mddev;
 		blk_queue_merge_bvec(mddev->queue, raid1_mergeable_bvec);
+
+		if (discard_supported)
+			queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, mddev->queue);
+		else
+			queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, mddev->queue);
 	}
 
 	ret =  md_integrity_register(mddev);
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 1c2eb38..c0aae01 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -911,7 +911,12 @@ static void flush_pending_writes(struct r10conf *conf)
 		while (bio) { /* submit pending writes */
 			struct bio *next = bio->bi_next;
 			bio->bi_next = NULL;
-			generic_make_request(bio);
+			if (unlikely((bio->bi_rw & REQ_DISCARD) &&
+			    !blk_queue_discard(bdev_get_queue(bio->bi_bdev))))
+				/* Just ignore it */
+				bio_endio(bio, 0);
+			else
+				generic_make_request(bio);
 			bio = next;
 		}
 	} else
@@ -1050,6 +1055,44 @@ static sector_t choose_data_offset(struct r10bio *r10_bio,
 		return rdev->new_data_offset;
 }
 
+struct raid10_plug_cb {
+	struct blk_plug_cb	cb;
+	struct bio_list		pending;
+	int			pending_cnt;
+};
+
+static void raid10_unplug(struct blk_plug_cb *cb, bool from_schedule)
+{
+	struct raid10_plug_cb *plug = container_of(cb, struct raid10_plug_cb,
+						   cb);
+	struct mddev *mddev = plug->cb.data;
+	struct r10conf *conf = mddev->private;
+	struct bio *bio;
+
+	if (from_schedule) {
+		spin_lock_irq(&conf->device_lock);
+		bio_list_merge(&conf->pending_bio_list, &plug->pending);
+		conf->pending_count += plug->pending_cnt;
+		spin_unlock_irq(&conf->device_lock);
+		md_wakeup_thread(mddev->thread);
+		kfree(plug);
+		return;
+	}
+
+	/* we aren't scheduling, so we can do the write-out directly. */
+	bio = bio_list_get(&plug->pending);
+	bitmap_unplug(mddev->bitmap);
+	wake_up(&conf->wait_barrier);
+
+	while (bio) { /* submit pending writes */
+		struct bio *next = bio->bi_next;
+		bio->bi_next = NULL;
+		generic_make_request(bio);
+		bio = next;
+	}
+	kfree(plug);
+}
+
 static void make_request(struct mddev *mddev, struct bio * bio)
 {
 	struct r10conf *conf = mddev->private;
@@ -1061,8 +1104,11 @@ static void make_request(struct mddev *mddev, struct bio * bio)
 	const int rw = bio_data_dir(bio);
 	const unsigned long do_sync = (bio->bi_rw & REQ_SYNC);
 	const unsigned long do_fua = (bio->bi_rw & REQ_FUA);
+	const unsigned long do_discard = (bio->bi_rw & (REQ_DISCARD | REQ_SECURE));
 	unsigned long flags;
 	struct md_rdev *blocked_rdev;
+	struct blk_plug_cb *cb;
+	struct raid10_plug_cb *plug = NULL;
 	int sectors_handled;
 	int max_sectors;
 	int sectors;
@@ -1081,7 +1127,7 @@ static void make_request(struct mddev *mddev, struct bio * bio)
 			 || conf->prev.near_copies < conf->prev.raid_disks))) {
 		struct bio_pair *bp;
 		/* Sanity check -- queue functions should prevent this happening */
-		if (bio->bi_vcnt != 1 ||
+		if ((bio->bi_vcnt != 1 && bio->bi_vcnt !=0) ||
 		    bio->bi_idx != 0)
 			goto bad_map;
 		/* This is a one page bio that upper layers
@@ -1410,15 +1456,26 @@ retry_write:
 						      conf->mirrors[d].rdev));
 		mbio->bi_bdev = conf->mirrors[d].rdev->bdev;
 		mbio->bi_end_io	= raid10_end_write_request;
-		mbio->bi_rw = WRITE | do_sync | do_fua;
+		mbio->bi_rw = WRITE | do_sync | do_fua | do_discard;
 		mbio->bi_private = r10_bio;
 
 		atomic_inc(&r10_bio->remaining);
+
+		cb = blk_check_plugged(raid10_unplug, mddev, sizeof(*plug));
+		if (cb)
+			plug = container_of(cb, struct raid10_plug_cb, cb);
+		else
+			plug = NULL;
 		spin_lock_irqsave(&conf->device_lock, flags);
-		bio_list_add(&conf->pending_bio_list, mbio);
-		conf->pending_count++;
+		if (plug) {
+			bio_list_add(&plug->pending, mbio);
+			plug->pending_cnt++;
+		} else {
+			bio_list_add(&conf->pending_bio_list, mbio);
+			conf->pending_count++;
+		}
 		spin_unlock_irqrestore(&conf->device_lock, flags);
-		if (!mddev_check_plugged(mddev))
+		if (!plug)
 			md_wakeup_thread(mddev->thread);
 
 		if (!r10_bio->devs[i].repl_bio)
@@ -1439,7 +1496,7 @@ retry_write:
 					   conf->mirrors[d].replacement));
 		mbio->bi_bdev = conf->mirrors[d].replacement->bdev;
 		mbio->bi_end_io	= raid10_end_write_request;
-		mbio->bi_rw = WRITE | do_sync | do_fua;
+		mbio->bi_rw = WRITE | do_sync | do_fua | do_discard;
 		mbio->bi_private = r10_bio;
 
 		atomic_inc(&r10_bio->remaining);
@@ -1636,7 +1693,7 @@ static int raid10_spare_active(struct mddev *mddev)
 			   && !test_bit(Faulty, &tmp->rdev->flags)
 			   && !test_and_set_bit(In_sync, &tmp->rdev->flags)) {
 			count++;
-			sysfs_notify_dirent(tmp->rdev->sysfs_state);
+			sysfs_notify_dirent_safe(tmp->rdev->sysfs_state);
 		}
 	}
 	spin_lock_irqsave(&conf->device_lock, flags);
@@ -1723,6 +1780,9 @@ static int raid10_add_disk(struct mddev *mddev, struct md_rdev *rdev)
 		clear_bit(Unmerged, &rdev->flags);
 	}
 	md_integrity_add_rdev(rdev, mddev);
+	if (blk_queue_discard(bdev_get_queue(rdev->bdev)))
+		queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, mddev->queue);
+
 	print_conf(conf);
 	return err;
 }
@@ -2671,8 +2731,9 @@ static void handle_write_completed(struct r10conf *conf, struct r10bio *r10_bio)
 	}
 }
 
-static void raid10d(struct mddev *mddev)
+static void raid10d(struct md_thread *thread)
 {
+	struct mddev *mddev = thread->mddev;
 	struct r10bio *r10_bio;
 	unsigned long flags;
 	struct r10conf *conf = mddev->private;
@@ -3480,6 +3541,7 @@ static int run(struct mddev *mddev)
 	sector_t size;
 	sector_t min_offset_diff = 0;
 	int first = 1;
+	bool discard_supported = false;
 
 	if (mddev->private == NULL) {
 		conf = setup_conf(mddev);
@@ -3496,6 +3558,7 @@ static int run(struct mddev *mddev)
 
 	chunk_size = mddev->chunk_sectors << 9;
 	if (mddev->queue) {
+		blk_queue_max_discard_sectors(mddev->queue, mddev->chunk_sectors);
 		blk_queue_io_min(mddev->queue, chunk_size);
 		if (conf->geo.raid_disks % conf->geo.near_copies)
 			blk_queue_io_opt(mddev->queue, chunk_size * conf->geo.raid_disks);
@@ -3541,8 +3604,16 @@ static int run(struct mddev *mddev)
 					  rdev->data_offset << 9);
 
 		disk->head_position = 0;
+
+		if (blk_queue_discard(bdev_get_queue(rdev->bdev)))
+			discard_supported = true;
 	}
 
+	if (discard_supported)
+		queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, mddev->queue);
+	else
+		queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, mddev->queue);
+
 	/* need to check that every block has at least one working mirror */
 	if (!enough(conf, -1)) {
 		printk(KERN_ERR "md/raid10:%s: not enough operational mirrors.\n",
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 7031b86..3f4f565 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -53,6 +53,8 @@
 #include <linux/cpu.h>
 #include <linux/slab.h>
 #include <linux/ratelimit.h>
+#include <trace/events/block.h>
+
 #include "md.h"
 #include "raid5.h"
 #include "raid0.h"
@@ -182,6 +184,8 @@ static void return_io(struct bio *return_bi)
 		return_bi = bi->bi_next;
 		bi->bi_next = NULL;
 		bi->bi_size = 0;
+		trace_block_bio_complete(bdev_get_queue(bi->bi_bdev),
+					 bi, 0);
 		bio_endio(bi, 0);
 		bi = return_bi;
 	}
@@ -196,6 +200,21 @@ static int stripe_operations_active(struct stripe_head *sh)
 	       test_bit(STRIPE_COMPUTE_RUN, &sh->state);
 }
 
+static void raid5_wakeup_stripe_thread(struct stripe_head *sh)
+{
+	struct r5conf *conf = sh->raid_conf;
+	struct raid5_percpu *percpu;
+	int i, orphaned = 1;
+
+	percpu = per_cpu_ptr(conf->percpu, sh->cpu);
+	for_each_cpu(i, &percpu->handle_threads) {
+		md_wakeup_thread(conf->aux_threads[i]->thread);
+		orphaned = 0;
+	}
+	if (orphaned)
+		md_wakeup_thread(conf->mddev->thread);
+}
+
 static void do_release_stripe(struct r5conf *conf, struct stripe_head *sh)
 {
 	BUG_ON(!list_empty(&sh->lru));
@@ -208,9 +227,19 @@ static void do_release_stripe(struct r5conf *conf, struct stripe_head *sh)
 			   sh->bm_seq - conf->seq_write > 0)
 			list_add_tail(&sh->lru, &conf->bitmap_list);
 		else {
+			int cpu = sh->cpu;
+			struct raid5_percpu *percpu;
+			if (!cpu_online(cpu)) {
+				cpu = cpumask_any(cpu_online_mask);
+				sh->cpu = cpu;
+			}
+			percpu = per_cpu_ptr(conf->percpu, cpu);
+
 			clear_bit(STRIPE_DELAYED, &sh->state);
 			clear_bit(STRIPE_BIT_DELAY, &sh->state);
-			list_add_tail(&sh->lru, &conf->handle_list);
+			list_add_tail(&sh->lru, &percpu->handle_list);
+			raid5_wakeup_stripe_thread(sh);
+			return;
 		}
 		md_wakeup_thread(conf->mddev->thread);
 	} else {
@@ -355,6 +384,7 @@ static void init_stripe(struct stripe_head *sh, sector_t sector, int previous)
 		raid5_build_block(sh, i, previous);
 	}
 	insert_hash(conf, sh);
+	sh->cpu = smp_processor_id();
 }
 
 static struct stripe_head *__find_stripe(struct r5conf *conf, sector_t sector,
@@ -551,6 +581,8 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s)
 				rw = WRITE_FUA;
 			else
 				rw = WRITE;
+			if (test_bit(R5_Discard, &sh->dev[i].flags))
+				rw |= REQ_DISCARD;
 		} else if (test_and_clear_bit(R5_Wantread, &sh->dev[i].flags))
 			rw = READ;
 		else if (test_and_clear_bit(R5_WantReplace,
@@ -669,6 +701,9 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s)
 			bi->bi_next = NULL;
 			if (rrdev)
 				set_bit(R5_DOUBLE_LOCKED, &sh->dev[i].flags);
+			trace_block_bio_remap(bdev_get_queue(bi->bi_bdev),
+					      bi, disk_devt(conf->mddev->gendisk),
+					      sh->dev[i].sector);
 			generic_make_request(bi);
 		}
 		if (rrdev) {
@@ -696,6 +731,9 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s)
 			rbi->bi_io_vec[0].bv_offset = 0;
 			rbi->bi_size = STRIPE_SIZE;
 			rbi->bi_next = NULL;
+			trace_block_bio_remap(bdev_get_queue(rbi->bi_bdev),
+					      rbi, disk_devt(conf->mddev->gendisk),
+					      sh->dev[i].sector);
 			generic_make_request(rbi);
 		}
 		if (!rdev && !rrdev) {
@@ -1174,8 +1212,11 @@ ops_run_biodrain(struct stripe_head *sh, struct dma_async_tx_descriptor *tx)
 					set_bit(R5_WantFUA, &dev->flags);
 				if (wbi->bi_rw & REQ_SYNC)
 					set_bit(R5_SyncIO, &dev->flags);
-				tx = async_copy_data(1, wbi, dev->page,
-					dev->sector, tx);
+				if (wbi->bi_rw & REQ_DISCARD)
+					set_bit(R5_Discard, &dev->flags);
+				else
+					tx = async_copy_data(1, wbi, dev->page,
+						dev->sector, tx);
 				wbi = r5_next_bio(wbi, dev->sector);
 			}
 		}
@@ -1191,7 +1232,7 @@ static void ops_complete_reconstruct(void *stripe_head_ref)
 	int pd_idx = sh->pd_idx;
 	int qd_idx = sh->qd_idx;
 	int i;
-	bool fua = false, sync = false;
+	bool fua = false, sync = false, discard = false;
 
 	pr_debug("%s: stripe %llu\n", __func__,
 		(unsigned long long)sh->sector);
@@ -1199,13 +1240,15 @@ static void ops_complete_reconstruct(void *stripe_head_ref)
 	for (i = disks; i--; ) {
 		fua |= test_bit(R5_WantFUA, &sh->dev[i].flags);
 		sync |= test_bit(R5_SyncIO, &sh->dev[i].flags);
+		discard |= test_bit(R5_Discard, &sh->dev[i].flags);
 	}
 
 	for (i = disks; i--; ) {
 		struct r5dev *dev = &sh->dev[i];
 
 		if (dev->written || i == pd_idx || i == qd_idx) {
-			set_bit(R5_UPTODATE, &dev->flags);
+			if (!discard)
+				set_bit(R5_UPTODATE, &dev->flags);
 			if (fua)
 				set_bit(R5_WantFUA, &dev->flags);
 			if (sync)
@@ -1241,6 +1284,18 @@ ops_run_reconstruct5(struct stripe_head *sh, struct raid5_percpu *percpu,
 	pr_debug("%s: stripe %llu\n", __func__,
 		(unsigned long long)sh->sector);
 
+	for (i = 0; i < sh->disks; i++) {
+		if (pd_idx == i)
+			continue;
+		if (!test_bit(R5_Discard, &sh->dev[i].flags))
+			break;
+	}
+	if (i >= sh->disks) {
+		atomic_inc(&sh->count);
+		set_bit(R5_Discard, &sh->dev[pd_idx].flags);
+		ops_complete_reconstruct(sh);
+		return;
+	}
 	/* check if prexor is active which means only process blocks
 	 * that are part of a read-modify-write (written)
 	 */
@@ -1285,10 +1340,24 @@ ops_run_reconstruct6(struct stripe_head *sh, struct raid5_percpu *percpu,
 {
 	struct async_submit_ctl submit;
 	struct page **blocks = percpu->scribble;
-	int count;
+	int count, i;
 
 	pr_debug("%s: stripe %llu\n", __func__, (unsigned long long)sh->sector);
 
+	for (i = 0; i < sh->disks; i++) {
+		if (sh->pd_idx == i || sh->qd_idx == i)
+			continue;
+		if (!test_bit(R5_Discard, &sh->dev[i].flags))
+			break;
+	}
+	if (i >= sh->disks) {
+		atomic_inc(&sh->count);
+		set_bit(R5_Discard, &sh->dev[sh->pd_idx].flags);
+		set_bit(R5_Discard, &sh->dev[sh->qd_idx].flags);
+		ops_complete_reconstruct(sh);
+		return;
+	}
+
 	count = set_syndrome_sources(blocks, sh);
 
 	atomic_inc(&sh->count);
@@ -1591,6 +1660,7 @@ static int resize_stripes(struct r5conf *conf, int newsize)
 		#ifdef CONFIG_MULTICORE_RAID456
 		init_waitqueue_head(&nsh->ops.wait_for_ops);
 		#endif
+		spin_lock_init(&nsh->stripe_lock);
 
 		list_add(&nsh->lru, &newstripes);
 	}
@@ -2407,11 +2477,11 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in
 		if (sector >= sh->dev[dd_idx].sector + STRIPE_SECTORS)
 			set_bit(R5_OVERWRITE, &sh->dev[dd_idx].flags);
 	}
-	spin_unlock_irq(&sh->stripe_lock);
 
 	pr_debug("added bi b#%llu to stripe s#%llu, disk %d.\n",
 		(unsigned long long)(*bip)->bi_sector,
 		(unsigned long long)sh->sector, dd_idx);
+	spin_unlock_irq(&sh->stripe_lock);
 
 	if (conf->mddev->bitmap && firstwrite) {
 		bitmap_startwrite(conf->mddev->bitmap, sh->sector,
@@ -2478,10 +2548,8 @@ handle_failed_stripe(struct r5conf *conf, struct stripe_head *sh,
 		bi = sh->dev[i].towrite;
 		sh->dev[i].towrite = NULL;
 		spin_unlock_irq(&sh->stripe_lock);
-		if (bi) {
-			s->to_write--;
+		if (bi)
 			bitmap_end = 1;
-		}
 
 		if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
 			wake_up(&conf->wait_for_overlap);
@@ -2523,11 +2591,12 @@ handle_failed_stripe(struct r5conf *conf, struct stripe_head *sh,
 		if (!test_bit(R5_Wantfill, &sh->dev[i].flags) &&
 		    (!test_bit(R5_Insync, &sh->dev[i].flags) ||
 		      test_bit(R5_ReadError, &sh->dev[i].flags))) {
+			spin_lock_irq(&sh->stripe_lock);
 			bi = sh->dev[i].toread;
 			sh->dev[i].toread = NULL;
+			spin_unlock_irq(&sh->stripe_lock);
 			if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
 				wake_up(&conf->wait_for_overlap);
-			if (bi) s->to_read--;
 			while (bi && bi->bi_sector <
 			       sh->dev[i].sector + STRIPE_SECTORS) {
 				struct bio *nextbi =
@@ -2740,7 +2809,8 @@ static void handle_stripe_clean_event(struct r5conf *conf,
 		if (sh->dev[i].written) {
 			dev = &sh->dev[i];
 			if (!test_bit(R5_LOCKED, &dev->flags) &&
-				test_bit(R5_UPTODATE, &dev->flags)) {
+			    (test_bit(R5_UPTODATE, &dev->flags) ||
+			     test_and_clear_bit(R5_Discard, &dev->flags))) {
 				/* We can return any write requests */
 				struct bio *wbi, *wbi2;
 				pr_debug("Return write for disc %d\n", i);
@@ -2774,12 +2844,24 @@ static void handle_stripe_dirtying(struct r5conf *conf,
 				   int disks)
 {
 	int rmw = 0, rcw = 0, i;
-	if (conf->max_degraded == 2) {
-		/* RAID6 requires 'rcw' in current implementation
-		 * Calculate the real rcw later - for now fake it
+	sector_t recovery_cp = conf->mddev->recovery_cp;
+
+	/* RAID6 requires 'rcw' in current implementation.
+	 * Otherwise, check whether resync is now happening or should start.
+	 * If yes, then the array is dirty (after unclean shutdown or
+	 * initial creation), so parity in some stripes might be inconsistent.
+	 * In this case, we need to always do reconstruct-write, to ensure
+	 * that in case of drive failure or read-error correction, we
+	 * generate correct data from the parity.
+	 */
+	if (conf->max_degraded == 2 ||
+	    (recovery_cp < MaxSector && sh->sector >= recovery_cp)) {
+		/* Calculate the real rcw later - for now make it
 		 * look like rcw is cheaper
 		 */
 		rcw = 1; rmw = 2;
+		pr_debug("force RCW max_degraded=%u, recovery_cp=%lu sh->sector=%lu\n",
+			 conf->max_degraded, recovery_cp, sh->sector);
 	} else for (i = disks; i--; ) {
 		/* would I have to read this buffer for read_modify_write */
 		struct r5dev *dev = &sh->dev[i];
@@ -2805,8 +2887,10 @@ static void handle_stripe_dirtying(struct r5conf *conf,
 	pr_debug("for sector %llu, rmw=%d rcw=%d\n",
 		(unsigned long long)sh->sector, rmw, rcw);
 	set_bit(STRIPE_HANDLE, &sh->state);
-	if (rmw < rcw && rmw > 0)
+	if (rmw < rcw && rmw > 0) {
 		/* prefer read-modify-write, but need to get some data */
+		blk_add_trace_msg(conf->mddev->queue, "raid5 rmw %llu %d",
+				  (unsigned long long)sh->sector, rmw);
 		for (i = disks; i--; ) {
 			struct r5dev *dev = &sh->dev[i];
 			if ((dev->towrite || i == sh->pd_idx) &&
@@ -2817,7 +2901,7 @@ static void handle_stripe_dirtying(struct r5conf *conf,
 				if (
 				  test_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
 					pr_debug("Read_old block "
-						"%d for r-m-w\n", i);
+						 "%d for r-m-w\n", i);
 					set_bit(R5_LOCKED, &dev->flags);
 					set_bit(R5_Wantread, &dev->flags);
 					s->locked++;
@@ -2827,8 +2911,10 @@ static void handle_stripe_dirtying(struct r5conf *conf,
 				}
 			}
 		}
+	}
 	if (rcw <= rmw && rcw > 0) {
 		/* want reconstruct write, but need to get some data */
+		int qread =0;
 		rcw = 0;
 		for (i = disks; i--; ) {
 			struct r5dev *dev = &sh->dev[i];
@@ -2847,12 +2933,17 @@ static void handle_stripe_dirtying(struct r5conf *conf,
 					set_bit(R5_LOCKED, &dev->flags);
 					set_bit(R5_Wantread, &dev->flags);
 					s->locked++;
+					qread++;
 				} else {
 					set_bit(STRIPE_DELAYED, &sh->state);
 					set_bit(STRIPE_HANDLE, &sh->state);
 				}
 			}
 		}
+		if (rcw)
+			blk_add_trace_msg(conf->mddev->queue, "raid5 rcw %llu %d %d %d",
+					  (unsigned long long)sh->sector,
+					  rcw, qread, test_bit(STRIPE_DELAYED, &sh->state));
 	}
 	/* now if nothing is locked, and if we have enough data,
 	 * we can start a write request
@@ -3458,10 +3549,12 @@ static void handle_stripe(struct stripe_head *sh)
 	if (s.written &&
 	    (s.p_failed || ((test_bit(R5_Insync, &pdev->flags)
 			     && !test_bit(R5_LOCKED, &pdev->flags)
-			     && test_bit(R5_UPTODATE, &pdev->flags)))) &&
+			     && (test_bit(R5_UPTODATE, &pdev->flags) ||
+				 test_bit(R5_Discard, &pdev->flags))))) &&
 	    (s.q_failed || ((test_bit(R5_Insync, &qdev->flags)
 			     && !test_bit(R5_LOCKED, &qdev->flags)
-			     && test_bit(R5_UPTODATE, &qdev->flags)))))
+			     && (test_bit(R5_UPTODATE, &qdev->flags) ||
+				 test_bit(R5_Discard, &qdev->flags))))))
 		handle_stripe_clean_event(conf, sh, disks, &s.return_bi);
 
 	/* Now we might consider reading some blocks, either to check/generate
@@ -3488,9 +3581,11 @@ static void handle_stripe(struct stripe_head *sh)
 		/* All the 'written' buffers and the parity block are ready to
 		 * be written back to disk
 		 */
-		BUG_ON(!test_bit(R5_UPTODATE, &sh->dev[sh->pd_idx].flags));
+		BUG_ON(!test_bit(R5_UPTODATE, &sh->dev[sh->pd_idx].flags) &&
+		       !test_bit(R5_Discard, &sh->dev[sh->pd_idx].flags));
 		BUG_ON(sh->qd_idx >= 0 &&
-		       !test_bit(R5_UPTODATE, &sh->dev[sh->qd_idx].flags));
+		       !test_bit(R5_UPTODATE, &sh->dev[sh->qd_idx].flags) &&
+		       !test_bit(R5_Discard, &sh->dev[sh->qd_idx].flags));
 		for (i = disks; i--; ) {
 			struct r5dev *dev = &sh->dev[i];
 			if (test_bit(R5_LOCKED, &dev->flags) &&
@@ -3693,12 +3788,19 @@ static void raid5_activate_delayed(struct r5conf *conf)
 		while (!list_empty(&conf->delayed_list)) {
 			struct list_head *l = conf->delayed_list.next;
 			struct stripe_head *sh;
+			int cpu;
 			sh = list_entry(l, struct stripe_head, lru);
 			list_del_init(l);
 			clear_bit(STRIPE_DELAYED, &sh->state);
 			if (!test_and_set_bit(STRIPE_PREREAD_ACTIVE, &sh->state))
 				atomic_inc(&conf->preread_active_stripes);
 			list_add_tail(&sh->lru, &conf->hold_list);
+			cpu = sh->cpu;
+			if (!cpu_online(cpu)) {
+				cpu = cpumask_any(cpu_online_mask);
+				sh->cpu = cpu;
+			}
+			raid5_wakeup_stripe_thread(sh);
 		}
 	}
 }
@@ -3849,6 +3951,8 @@ static void raid5_align_endio(struct bio *bi, int error)
 	rdev_dec_pending(rdev, conf->mddev);
 
 	if (!error && uptodate) {
+		trace_block_bio_complete(bdev_get_queue(raid_bi->bi_bdev),
+					 raid_bi, 0);
 		bio_endio(raid_bi, 0);
 		if (atomic_dec_and_test(&conf->active_aligned_reads))
 			wake_up(&conf->wait_for_stripe);
@@ -3953,6 +4057,9 @@ static int chunk_aligned_read(struct mddev *mddev, struct bio * raid_bio)
 		atomic_inc(&conf->active_aligned_reads);
 		spin_unlock_irq(&conf->device_lock);
 
+		trace_block_bio_remap(bdev_get_queue(align_bi->bi_bdev),
+				      align_bi, disk_devt(mddev->gendisk),
+				      raid_bio->bi_sector);
 		generic_make_request(align_bi);
 		return 1;
 	} else {
@@ -3972,18 +4079,29 @@ static int chunk_aligned_read(struct mddev *mddev, struct bio * raid_bio)
  * head of the hold_list has changed, i.e. the head was promoted to the
  * handle_list.
  */
-static struct stripe_head *__get_priority_stripe(struct r5conf *conf)
-{
-	struct stripe_head *sh;
-
+static struct stripe_head *__get_priority_stripe(struct r5conf *conf,
+	cpumask_t *mask)
+{
+	struct stripe_head *sh = NULL, *tmp;
+	struct list_head *handle_list = NULL;
+	int cpu;
+
+	/* Should we take action to avoid starvation of latter CPUs ? */
+	for_each_cpu(cpu, mask) {
+		struct raid5_percpu *percpu = per_cpu_ptr(conf->percpu, cpu);
+		if (!list_empty(&percpu->handle_list)) {
+			handle_list = &percpu->handle_list;
+			break;
+		}
+	}
 	pr_debug("%s: handle: %s hold: %s full_writes: %d bypass_count: %d\n",
 		  __func__,
-		  list_empty(&conf->handle_list) ? "empty" : "busy",
+		  !handle_list ? "empty" : "busy",
 		  list_empty(&conf->hold_list) ? "empty" : "busy",
 		  atomic_read(&conf->pending_full_writes), conf->bypass_count);
 
-	if (!list_empty(&conf->handle_list)) {
-		sh = list_entry(conf->handle_list.next, typeof(*sh), lru);
+	if (handle_list) {
+		sh = list_entry(handle_list->next, typeof(*sh), lru);
 
 		if (list_empty(&conf->hold_list))
 			conf->bypass_count = 0;
@@ -4001,12 +4119,23 @@ static struct stripe_head *__get_priority_stripe(struct r5conf *conf)
 		   ((conf->bypass_threshold &&
 		     conf->bypass_count > conf->bypass_threshold) ||
 		    atomic_read(&conf->pending_full_writes) == 0)) {
-		sh = list_entry(conf->hold_list.next,
-				typeof(*sh), lru);
-		conf->bypass_count -= conf->bypass_threshold;
-		if (conf->bypass_count < 0)
-			conf->bypass_count = 0;
-	} else
+
+		list_for_each_entry(tmp, &conf->hold_list,  lru) {
+			if (cpumask_test_cpu(tmp->cpu, mask) ||
+			    !cpu_online(tmp->cpu)) {
+				sh = tmp;
+				break;
+			}
+		}
+
+		if (sh) {
+			conf->bypass_count -= conf->bypass_threshold;
+			if (conf->bypass_count < 0)
+				conf->bypass_count = 0;
+		}
+	}
+
+	if (!sh)
 		return NULL;
 
 	list_del_init(&sh->lru);
@@ -4027,6 +4156,7 @@ static void raid5_unplug(struct blk_plug_cb *blk_cb, bool from_schedule)
 	struct stripe_head *sh;
 	struct mddev *mddev = cb->cb.data;
 	struct r5conf *conf = mddev->private;
+	int cnt = 0;
 
 	if (cb->list.next && !list_empty(&cb->list)) {
 		spin_lock_irq(&conf->device_lock);
@@ -4041,9 +4171,11 @@ static void raid5_unplug(struct blk_plug_cb *blk_cb, bool from_schedule)
 			smp_mb__before_clear_bit();
 			clear_bit(STRIPE_ON_UNPLUG_LIST, &sh->state);
 			__release_stripe(conf, sh);
+			cnt++;
 		}
 		spin_unlock_irq(&conf->device_lock);
 	}
+	trace_block_unplug(mddev->queue, cnt, !from_schedule);
 	kfree(cb);
 }
 
@@ -4071,6 +4203,88 @@ static void release_stripe_plug(struct mddev *mddev,
 		release_stripe(sh);
 }
 
+static void make_discard_request(struct mddev *mddev, struct bio *bi)
+{
+	struct r5conf *conf = mddev->private;
+	sector_t logical_sector, last_sector;
+	struct stripe_head *sh;
+	int remaining;
+	int stripe_sectors;
+
+	if (mddev->reshape_position != MaxSector)
+		/* Skip discard while reshape is happening */
+		return;
+
+	logical_sector = bi->bi_sector & ~((sector_t)STRIPE_SECTORS-1);
+	last_sector = bi->bi_sector + (bi->bi_size>>9);
+
+	bi->bi_next = NULL;
+	bi->bi_phys_segments = 1; /* over-loaded to count active stripes */
+
+	stripe_sectors = conf->chunk_sectors *
+		(conf->raid_disks - conf->max_degraded);
+	logical_sector = DIV_ROUND_UP_SECTOR_T(logical_sector,
+					       stripe_sectors);
+	sector_div(last_sector, stripe_sectors);
+
+	logical_sector *= conf->chunk_sectors;
+	last_sector *= conf->chunk_sectors;
+
+	for (;logical_sector < last_sector;
+	     logical_sector += STRIPE_SECTORS) {
+		DEFINE_WAIT(w);
+		int d;
+	again:
+		sh = get_active_stripe(conf, logical_sector, 0, 0, 0);
+		prepare_to_wait(&conf->wait_for_overlap, &w,
+				TASK_UNINTERRUPTIBLE);
+		spin_lock_irq(&sh->stripe_lock);
+		for (d = 0; d < conf->raid_disks; d++) {
+			if (d == sh->pd_idx || d == sh->qd_idx)
+				continue;
+			if (sh->dev[d].towrite || sh->dev[d].toread) {
+				set_bit(R5_Overlap, &sh->dev[d].flags);
+				spin_unlock_irq(&sh->stripe_lock);
+				release_stripe(sh);
+				schedule();
+				goto again;
+			}
+		}
+		finish_wait(&conf->wait_for_overlap, &w);
+		for (d = 0; d < conf->raid_disks; d++) {
+			if (d == sh->pd_idx || d == sh->qd_idx)
+				continue;
+			sh->dev[d].towrite = bi;
+			set_bit(R5_OVERWRITE, &sh->dev[d].flags);
+			raid5_inc_bi_active_stripes(bi);
+		}
+		spin_unlock_irq(&sh->stripe_lock);
+		if (conf->mddev->bitmap) {
+			for (d = 0;
+			     d < conf->raid_disks - conf->max_degraded;
+			     d++)
+				bitmap_startwrite(mddev->bitmap,
+						  sh->sector,
+						  STRIPE_SECTORS,
+						  0);
+			sh->bm_seq = conf->seq_flush + 1;
+			set_bit(STRIPE_BIT_DELAY, &sh->state);
+		}
+
+		set_bit(STRIPE_HANDLE, &sh->state);
+		clear_bit(STRIPE_DELAYED, &sh->state);
+		if (!test_and_set_bit(STRIPE_PREREAD_ACTIVE, &sh->state))
+			atomic_inc(&conf->preread_active_stripes);
+		release_stripe_plug(mddev, sh);
+	}
+
+	remaining = raid5_dec_bi_active_stripes(bi);
+	if (remaining == 0) {
+		md_write_end(mddev);
+		bio_endio(bi, 0);
+	}
+}
+
 static void make_request(struct mddev *mddev, struct bio * bi)
 {
 	struct r5conf *conf = mddev->private;
@@ -4093,6 +4307,11 @@ static void make_request(struct mddev *mddev, struct bio * bi)
 	     chunk_aligned_read(mddev,bi))
 		return;
 
+	if (unlikely(bi->bi_rw & REQ_DISCARD)) {
+		make_discard_request(mddev, bi);
+		return;
+	}
+
 	logical_sector = bi->bi_sector & ~((sector_t)STRIPE_SECTORS-1);
 	last_sector = bi->bi_sector + (bi->bi_size>>9);
 	bi->bi_next = NULL;
@@ -4214,6 +4433,8 @@ static void make_request(struct mddev *mddev, struct bio * bi)
 		if ( rw == WRITE )
 			md_write_end(mddev);
 
+		trace_block_bio_complete(bdev_get_queue(bi->bi_bdev),
+					 bi, 0);
 		bio_endio(bi, 0);
 	}
 }
@@ -4590,21 +4811,24 @@ static int  retry_aligned_read(struct r5conf *conf, struct bio *raid_bio)
 		handled++;
 	}
 	remaining = raid5_dec_bi_active_stripes(raid_bio);
-	if (remaining == 0)
+	if (remaining == 0) {
+		trace_block_bio_complete(bdev_get_queue(raid_bio->bi_bdev),
+					 raid_bio, 0);
 		bio_endio(raid_bio, 0);
+	}
 	if (atomic_dec_and_test(&conf->active_aligned_reads))
 		wake_up(&conf->wait_for_stripe);
 	return handled;
 }
 
 #define MAX_STRIPE_BATCH 8
-static int handle_active_stripes(struct r5conf *conf)
+static int handle_active_stripes(struct r5conf *conf, cpumask_t *mask)
 {
 	struct stripe_head *batch[MAX_STRIPE_BATCH], *sh;
 	int i, batch_size = 0;
 
 	while (batch_size < MAX_STRIPE_BATCH &&
-			(sh = __get_priority_stripe(conf)) != NULL)
+			(sh = __get_priority_stripe(conf, mask)) != NULL)
 		batch[batch_size++] = sh;
 
 	if (batch_size == 0)
@@ -4622,6 +4846,35 @@ static int handle_active_stripes(struct r5conf *conf)
 	return batch_size;
 }
 
+static void raid5auxd(struct md_thread *thread)
+{
+	struct mddev *mddev = thread->mddev;
+	struct r5conf *conf = mddev->private;
+	struct blk_plug plug;
+	int handled;
+	struct raid5_auxth *auxth = thread->private;
+
+	pr_debug("+++ raid5auxd active\n");
+
+	blk_start_plug(&plug);
+	handled = 0;
+	spin_lock_irq(&conf->device_lock);
+	while (1) {
+		int batch_size;
+
+		batch_size = handle_active_stripes(conf, &auxth->work_mask);
+		if (!batch_size)
+			break;
+		handled += batch_size;
+	}
+	pr_debug("%d stripes handled\n", handled);
+
+	spin_unlock_irq(&conf->device_lock);
+	blk_finish_plug(&plug);
+
+	pr_debug("--- raid5auxd inactive\n");
+}
+
 /*
  * This is our raid5 kernel thread.
  *
@@ -4629,8 +4882,9 @@ static int handle_active_stripes(struct r5conf *conf)
  * During the scan, completed stripes are saved for us by the interrupt
  * handler, so that they will not have to wait for our next wakeup.
  */
-static void raid5d(struct mddev *mddev)
+static void raid5d(struct md_thread *thread)
 {
+	struct mddev *mddev = thread->mddev;
 	struct r5conf *conf = mddev->private;
 	int handled;
 	struct blk_plug plug;
@@ -4668,7 +4922,7 @@ static void raid5d(struct mddev *mddev)
 			handled++;
 		}
 
-		batch_size = handle_active_stripes(conf);
+		batch_size = handle_active_stripes(conf, &conf->work_mask);
 		if (!batch_size)
 			break;
 		handled += batch_size;
@@ -4797,10 +5051,270 @@ stripe_cache_active_show(struct mddev *mddev, char *page)
 static struct md_sysfs_entry
 raid5_stripecache_active = __ATTR_RO(stripe_cache_active);
 
+static void raid5_update_threads_handle_mask(struct mddev *mddev)
+{
+	int cpu, i;
+	struct raid5_percpu *percpu;
+	struct r5conf *conf = mddev->private;
+
+	for_each_online_cpu(cpu) {
+		percpu = per_cpu_ptr(conf->percpu, cpu);
+		cpumask_clear(&percpu->handle_threads);
+	}
+	cpumask_copy(&conf->work_mask, cpu_online_mask);
+
+	for (i = 0; i < conf->aux_thread_num; i++) {
+		cpumask_t *work_mask = &conf->aux_threads[i]->work_mask;
+		for_each_cpu(cpu, work_mask) {
+			percpu = per_cpu_ptr(conf->percpu, cpu);
+			cpumask_set_cpu(i, &percpu->handle_threads);
+		}
+		cpumask_andnot(&conf->work_mask, &conf->work_mask,
+				work_mask);
+	}
+}
+
+struct raid5_auxth_sysfs {
+	struct attribute attr;
+	ssize_t (*show)(struct mddev *, struct raid5_auxth *, char *);
+	ssize_t (*store)(struct mddev *, struct raid5_auxth *,
+		const char *, size_t);
+};
+
+static ssize_t raid5_show_thread_cpulist(struct mddev *mddev,
+	struct raid5_auxth *thread, char *page)
+{
+	if (!mddev->private)
+		return 0;
+	return cpulist_scnprintf(page, PAGE_SIZE, &thread->work_mask);
+}
+
+static ssize_t
+raid5_store_thread_cpulist(struct mddev *mddev, struct raid5_auxth *thread,
+	const char *page, size_t len)
+{
+	struct r5conf *conf = mddev->private;
+	cpumask_var_t mask;
+
+	if (!conf)
+		return -ENODEV;
+	if (!alloc_cpumask_var(&mask, GFP_KERNEL))
+		return -ENOMEM;
+
+	if (cpulist_parse(page, mask)) {
+		free_cpumask_var(mask);
+		return -EINVAL;
+	}
+
+	get_online_cpus();
+	spin_lock_irq(&conf->device_lock);
+	cpumask_copy(&thread->work_mask, mask);
+	raid5_update_threads_handle_mask(mddev);
+	spin_unlock_irq(&conf->device_lock);
+	put_online_cpus();
+	set_cpus_allowed_ptr(thread->thread->tsk, mask);
+
+	free_cpumask_var(mask);
+	return len;
+}
+
+static struct raid5_auxth_sysfs thread_cpulist =
+__ATTR(cpulist, S_IRUGO|S_IWUSR, raid5_show_thread_cpulist,
+	raid5_store_thread_cpulist);
+
+static struct attribute *auxth_attrs[] = {
+	&thread_cpulist.attr,
+	NULL,
+};
+
+static ssize_t
+raid5_auxth_attr_show(struct kobject *kobj, struct attribute *attr, char *page)
+{
+	struct raid5_auxth_sysfs *entry = container_of(attr,
+		struct raid5_auxth_sysfs, attr);
+	struct raid5_auxth *thread = container_of(kobj,
+		struct raid5_auxth, kobj);
+	struct mddev *mddev = thread->thread->mddev;
+	ssize_t ret;
+
+	if (!entry->show)
+		return -EIO;
+	mddev_lock(mddev);
+	ret = entry->show(mddev, thread, page);
+	mddev_unlock(mddev);
+	return ret;
+}
+
+static ssize_t
+raid5_auxth_attr_store(struct kobject *kobj, struct attribute *attr,
+	      const char *page, size_t length)
+{
+	struct raid5_auxth_sysfs *entry = container_of(attr,
+		struct raid5_auxth_sysfs, attr);
+	struct raid5_auxth *thread = container_of(kobj,
+		struct raid5_auxth, kobj);
+	struct mddev *mddev = thread->thread->mddev;
+	ssize_t ret;
+
+	if (!entry->store)
+		return -EIO;
+	if (!capable(CAP_SYS_ADMIN))
+		return -EACCES;
+	mddev_lock(mddev);
+	ret = entry->store(mddev, thread, page, length);
+	mddev_unlock(mddev);
+	return ret;
+}
+
+static void raid5_auxth_release(struct kobject *kobj)
+{
+	struct raid5_auxth *thread = container_of(kobj,
+		struct raid5_auxth, kobj);
+	kfree(thread);
+}
+
+static const struct sysfs_ops raid5_auxth_sysfsops = {
+	.show = raid5_auxth_attr_show,
+	.store = raid5_auxth_attr_store,
+};
+static struct kobj_type raid5_auxth_ktype = {
+	.release = raid5_auxth_release,
+	.sysfs_ops = &raid5_auxth_sysfsops,
+	.default_attrs = auxth_attrs,
+};
+
+static ssize_t
+raid5_show_auxthread_number(struct mddev *mddev, char *page)
+{
+	struct r5conf *conf = mddev->private;
+	if (conf)
+		return sprintf(page, "%d\n", conf->aux_thread_num);
+	else
+		return 0;
+}
+
+static void raid5_auxth_delete(struct work_struct *ws)
+{
+	struct raid5_auxth *thread = container_of(ws, struct raid5_auxth,
+		del_work);
+
+	kobject_del(&thread->kobj);
+	kobject_put(&thread->kobj);
+}
+
+static void __free_aux_thread(struct mddev *mddev, struct raid5_auxth *thread)
+{
+	md_unregister_thread(&thread->thread);
+	INIT_WORK(&thread->del_work, raid5_auxth_delete);
+	kobject_get(&thread->kobj);
+	md_queue_misc_work(&thread->del_work);
+}
+
+static struct raid5_auxth *__create_aux_thread(struct mddev *mddev, int i)
+{
+	struct raid5_auxth *thread;
+	char name[10];
+
+	thread = kzalloc(sizeof(*thread), GFP_KERNEL);
+	if (!thread)
+		return NULL;
+	snprintf(name, 10, "aux%d", i);
+	thread->thread = md_register_thread(raid5auxd, mddev, name);
+	if (!thread->thread) {
+		kfree(thread);
+		return NULL;
+	}
+	thread->thread->private = thread;
+
+	cpumask_copy(&thread->work_mask, cpu_online_mask);
+
+	if (kobject_init_and_add(&thread->kobj, &raid5_auxth_ktype,
+	    &mddev->kobj, "auxth%d", i)) {
+		md_unregister_thread(&thread->thread);
+		kfree(thread);
+		return NULL;
+	}
+	return thread;
+}
+
+static ssize_t
+raid5_store_auxthread_number(struct mddev *mddev, const char *page, size_t len)
+{
+	struct r5conf *conf = mddev->private;
+	unsigned long new;
+	int i;
+	struct raid5_auxth **threads;
+
+	if (len >= PAGE_SIZE)
+		return -EINVAL;
+	if (!conf)
+		return -ENODEV;
+
+	if (kstrtoul(page, 10, &new))
+		return -EINVAL;
+
+	if (new == conf->aux_thread_num)
+		return len;
+
+	/* There is no point creating more threads than cpu number */
+	if (new > num_online_cpus())
+		return -EINVAL;
+
+	if (new > conf->aux_thread_num) {
+		threads = kzalloc(sizeof(struct raid5_auxth *) * new,
+				GFP_KERNEL);
+		if (!threads)
+			return -ENOMEM;
+
+		i = conf->aux_thread_num;
+		while (i < new) {
+			threads[i] = __create_aux_thread(mddev, i);
+			if (!threads[i])
+				goto error;
+
+			i++;
+		}
+		memcpy(threads, conf->aux_threads,
+			sizeof(struct raid5_auxth *) * conf->aux_thread_num);
+		get_online_cpus();
+		spin_lock_irq(&conf->device_lock);
+		kfree(conf->aux_threads);
+		conf->aux_threads = threads;
+		conf->aux_thread_num = new;
+		raid5_update_threads_handle_mask(mddev);
+		spin_unlock_irq(&conf->device_lock);
+		put_online_cpus();
+	} else {
+		int old = conf->aux_thread_num;
+
+		get_online_cpus();
+		spin_lock_irq(&conf->device_lock);
+		conf->aux_thread_num = new;
+		raid5_update_threads_handle_mask(mddev);
+		spin_unlock_irq(&conf->device_lock);
+		put_online_cpus();
+		for (i = new; i < old; i++)
+			__free_aux_thread(mddev, conf->aux_threads[i]);
+	}
+
+	return len;
+error:
+	while (--i >= conf->aux_thread_num)
+		__free_aux_thread(mddev, threads[i]);
+	kfree(threads);
+	return -ENOMEM;
+}
+
+static struct md_sysfs_entry
+raid5_auxthread_number = __ATTR(auxthread_number, S_IRUGO|S_IWUSR,
+				raid5_show_auxthread_number,
+				raid5_store_auxthread_number);
+
 static struct attribute *raid5_attrs[] =  {
 	&raid5_stripecache_size.attr,
 	&raid5_stripecache_active.attr,
 	&raid5_preread_bypass_threshold.attr,
+	&raid5_auxthread_number.attr,
 	NULL,
 };
 static struct attribute_group raid5_attrs_group = {
@@ -4848,6 +5362,7 @@ static void raid5_free_percpu(struct r5conf *conf)
 
 static void free_conf(struct r5conf *conf)
 {
+	kfree(conf->aux_threads);
 	shrink_stripes(conf);
 	raid5_free_percpu(conf);
 	kfree(conf->disks);
@@ -4860,7 +5375,7 @@ static int raid456_cpu_notify(struct notifier_block *nfb, unsigned long action,
 			      void *hcpu)
 {
 	struct r5conf *conf = container_of(nfb, struct r5conf, cpu_notify);
-	long cpu = (long)hcpu;
+	long cpu = (long)hcpu, anycpu;
 	struct raid5_percpu *percpu = per_cpu_ptr(conf->percpu, cpu);
 
 	switch (action) {
@@ -4879,9 +5394,17 @@ static int raid456_cpu_notify(struct notifier_block *nfb, unsigned long action,
 			       __func__, cpu);
 			return notifier_from_errno(-ENOMEM);
 		}
+		INIT_LIST_HEAD(&(percpu->handle_list));
+		cpumask_clear(&percpu->handle_threads);
 		break;
 	case CPU_DEAD:
 	case CPU_DEAD_FROZEN:
+		spin_lock_irq(&conf->device_lock);
+		anycpu = cpumask_any(cpu_online_mask);
+		list_splice_tail_init(&percpu->handle_list,
+			&per_cpu_ptr(conf->percpu, anycpu)->handle_list);
+		spin_unlock_irq(&conf->device_lock);
+
 		safe_put_page(percpu->spare_page);
 		kfree(percpu->scribble);
 		percpu->spare_page = NULL;
@@ -4890,6 +5413,10 @@ static int raid456_cpu_notify(struct notifier_block *nfb, unsigned long action,
 	default:
 		break;
 	}
+
+	spin_lock_irq(&conf->device_lock);
+	raid5_update_threads_handle_mask(conf->mddev);
+	spin_unlock_irq(&conf->device_lock);
 	return NOTIFY_OK;
 }
 #endif
@@ -4910,20 +5437,24 @@ static int raid5_alloc_percpu(struct r5conf *conf)
 	get_online_cpus();
 	err = 0;
 	for_each_present_cpu(cpu) {
+		struct raid5_percpu *percpu = per_cpu_ptr(conf->percpu, cpu);
+
 		if (conf->level == 6) {
 			spare_page = alloc_page(GFP_KERNEL);
 			if (!spare_page) {
 				err = -ENOMEM;
 				break;
 			}
-			per_cpu_ptr(conf->percpu, cpu)->spare_page = spare_page;
+			percpu->spare_page = spare_page;
 		}
 		scribble = kmalloc(conf->scribble_len, GFP_KERNEL);
 		if (!scribble) {
 			err = -ENOMEM;
 			break;
 		}
-		per_cpu_ptr(conf->percpu, cpu)->scribble = scribble;
+		percpu->scribble = scribble;
+		INIT_LIST_HEAD(&percpu->handle_list);
+		cpumask_clear(&percpu->handle_threads);
 	}
 #ifdef CONFIG_HOTPLUG_CPU
 	conf->cpu_notify.notifier_call = raid456_cpu_notify;
@@ -4979,7 +5510,6 @@ static struct r5conf *setup_conf(struct mddev *mddev)
 	spin_lock_init(&conf->device_lock);
 	init_waitqueue_head(&conf->wait_for_stripe);
 	init_waitqueue_head(&conf->wait_for_overlap);
-	INIT_LIST_HEAD(&conf->handle_list);
 	INIT_LIST_HEAD(&conf->hold_list);
 	INIT_LIST_HEAD(&conf->delayed_list);
 	INIT_LIST_HEAD(&conf->bitmap_list);
@@ -4990,6 +5520,8 @@ static struct r5conf *setup_conf(struct mddev *mddev)
 	conf->bypass_threshold = BYPASS_THRESHOLD;
 	conf->recovery_disabled = mddev->recovery_disabled - 1;
 
+	cpumask_copy(&conf->work_mask, cpu_online_mask);
+
 	conf->raid_disks = mddev->raid_disks;
 	if (mddev->reshape_position == MaxSector)
 		conf->previous_raid_disks = mddev->raid_disks;
@@ -5365,6 +5897,7 @@ static int run(struct mddev *mddev)
 
 	if (mddev->queue) {
 		int chunk_size;
+		bool discard_supported = true;
 		/* read-ahead size must cover two whole stripes, which
 		 * is 2 * (datadisks) * chunksize where 'n' is the
 		 * number of raid devices
@@ -5384,13 +5917,48 @@ static int run(struct mddev *mddev)
 		blk_queue_io_min(mddev->queue, chunk_size);
 		blk_queue_io_opt(mddev->queue, chunk_size *
 				 (conf->raid_disks - conf->max_degraded));
+		/*
+		 * We can only discard a whole stripe. It doesn't make sense to
+		 * discard data disk but write parity disk
+		 */
+		stripe = stripe * PAGE_SIZE;
+		mddev->queue->limits.discard_alignment = stripe;
+		mddev->queue->limits.discard_granularity = stripe;
+		/*
+		 * unaligned part of discard request will be ignored, so can't
+		 * guarantee discard_zerors_data
+		 */
+		mddev->queue->limits.discard_zeroes_data = 0;
 
 		rdev_for_each(rdev, mddev) {
 			disk_stack_limits(mddev->gendisk, rdev->bdev,
 					  rdev->data_offset << 9);
 			disk_stack_limits(mddev->gendisk, rdev->bdev,
 					  rdev->new_data_offset << 9);
+			/*
+			 * discard_zeroes_data is required, otherwise data
+			 * could be lost. Consider a scenario: discard a stripe
+			 * (the stripe could be inconsistent if
+			 * discard_zeroes_data is 0); write one disk of the
+			 * stripe (the stripe could be inconsistent again
+			 * depending on which disks are used to calculate
+			 * parity); the disk is broken; The stripe data of this
+			 * disk is lost.
+			 */
+			if (!blk_queue_discard(bdev_get_queue(rdev->bdev)) ||
+			    !bdev_get_queue(rdev->bdev)->
+						limits.discard_zeroes_data)
+				discard_supported = false;
 		}
+
+		if (discard_supported &&
+		   mddev->queue->limits.max_discard_sectors >= stripe &&
+		   mddev->queue->limits.discard_granularity >= stripe)
+			queue_flag_set_unlocked(QUEUE_FLAG_DISCARD,
+						mddev->queue);
+		else
+			queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD,
+						mddev->queue);
 	}
 
 	return 0;
@@ -5406,6 +5974,10 @@ abort:
 static int stop(struct mddev *mddev)
 {
 	struct r5conf *conf = mddev->private;
+	int i;
+
+	for (i = 0; i < conf->aux_thread_num; i++)
+		__free_aux_thread(mddev, conf->aux_threads[i]);
 
 	md_unregister_thread(&mddev->thread);
 	if (mddev->queue)
@@ -5701,7 +6273,7 @@ static int check_reshape(struct mddev *mddev)
 	if (!check_stripe_cache(mddev))
 		return -ENOSPC;
 
-	return resize_stripes(conf, conf->raid_disks + mddev->delta_disks);
+	return resize_stripes(conf, conf->previous_raid_disks + mddev->delta_disks);
 }
 
 static int raid5_start_reshape(struct mddev *mddev)
diff --git a/drivers/md/raid5.h b/drivers/md/raid5.h
index a9fc249..2afd835 100644
--- a/drivers/md/raid5.h
+++ b/drivers/md/raid5.h
@@ -211,6 +211,7 @@ struct stripe_head {
 	enum check_states	check_state;
 	enum reconstruct_states reconstruct_state;
 	spinlock_t		stripe_lock;
+	int			cpu;
 	/**
 	 * struct stripe_operations
 	 * @target - STRIPE_OP_COMPUTE_BLK target
@@ -298,6 +299,7 @@ enum r5dev_flags {
 	R5_WantReplace, /* We need to update the replacement, we have read
 			 * data in, and now is a good time to write it out.
 			 */
+	R5_Discard,	/* Discard the stripe */
 };
 
 /*
@@ -364,6 +366,14 @@ struct disk_info {
 	struct md_rdev	*rdev, *replacement;
 };
 
+struct raid5_auxth {
+	struct md_thread	*thread;
+	/* which CPUs should the auxiliary thread handle stripes from */
+	cpumask_t		work_mask;
+	struct kobject		kobj;
+	struct work_struct	del_work;
+};
+
 struct r5conf {
 	struct hlist_head	*stripe_hashtbl;
 	struct mddev		*mddev;
@@ -432,6 +442,12 @@ struct r5conf {
 					      * lists and performing address
 					      * conversions
 					      */
+		struct list_head handle_list;
+		cpumask_t	handle_threads; /* Which threads can the CPU's
+						 * stripes be handled. It really
+						 * is a bitmap to aux_threads[],
+						 * but has max bits NR_CPUS
+						 */
 	} __percpu *percpu;
 	size_t			scribble_len; /* size of scribble region must be
 					       * associated with conf to handle
@@ -459,6 +475,10 @@ struct r5conf {
 	 * the new thread here until we fully activate the array.
 	 */
 	struct md_thread	*thread;
+	int			aux_thread_num;
+	struct raid5_auxth	**aux_threads;
+	/* which CPUs should raid5d thread handle stripes from */
+	cpumask_t		work_mask;
 };
 
 /*
diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig
index d941581..dd13e3a 100644
--- a/drivers/media/Kconfig
+++ b/drivers/media/Kconfig
@@ -99,11 +99,6 @@ config VIDEO_DEV
 	depends on MEDIA_CAMERA_SUPPORT || MEDIA_ANALOG_TV_SUPPORT || MEDIA_RADIO_SUPPORT
 	default y
 
-config VIDEO_V4L2_COMMON
-	tristate
-	depends on (I2C || I2C=n) && VIDEO_DEV
-	default (I2C || I2C=n) && VIDEO_DEV
-
 config VIDEO_V4L2_SUBDEV_API
 	bool "V4L2 sub-device userspace API (EXPERIMENTAL)"
 	depends on VIDEO_DEV && MEDIA_CONTROLLER && EXPERIMENTAL
@@ -113,6 +108,8 @@ config VIDEO_V4L2_SUBDEV_API
 
 	  This API is mostly used by camera interfaces in embedded platforms.
 
+source "drivers/media/v4l2-core/Kconfig"
+
 #
 # DVB Core
 #	Only enables if one of DTV is selected
@@ -138,28 +135,54 @@ config DVB_NET
 	  You may want to disable the network support on embedded devices. If
 	  unsure say Y.
 
+source "drivers/media/dvb-core/Kconfig"
+
 comment "Media drivers"
-source "drivers/media/common/Kconfig"
 source "drivers/media/rc/Kconfig"
 
 #
-# Tuner drivers for DVB and V4L
+# V4L platform/mem2mem drivers
 #
 
-source "drivers/media/common/tuners/Kconfig"
+source "drivers/media/usb/Kconfig"
+source "drivers/media/pci/Kconfig"
+source "drivers/media/platform/Kconfig"
+source "drivers/media/mmc/Kconfig"
+source "drivers/media/parport/Kconfig"
+source "drivers/media/radio/Kconfig"
+
+comment "Supported FireWire (IEEE 1394) Adapters"
+	depends on DVB_CORE && FIREWIRE
+source "drivers/media/firewire/Kconfig"
+
+# Common driver options
+source "drivers/media/common/Kconfig"
 
 #
-# Video/Radio/Hybrid adapters
+# Ancillary drivers (tuners, i2c, frontends)
 #
 
-source "drivers/media/video/Kconfig"
+config MEDIA_SUBDRV_AUTOSELECT
+	bool "Autoselect analog and hybrid tuner modules to build"
+	depends on MEDIA_TUNER
+	default y
+	help
+	  By default, a TV driver auto-selects all possible tuners
+	  thar could be used by the driver.
 
-source "drivers/media/radio/Kconfig"
+	  This is generally the right thing to do, except when there
+	  are strict constraints with regards to the kernel size.
 
-#
-# DVB adapters
-#
+	  Use this option with care, as deselecting tuner drivers which
+	  are in fact necessary will result in TV devices which cannot
+	  be tuned due to lack of the tuning driver.
+
+	  If unsure say Y.
+
+comment "Media ancillary drivers (tuners, sensors, i2c, frontends)"
 
-source "drivers/media/dvb/Kconfig"
+source "drivers/media/i2c/Kconfig"
+source "drivers/media/tuners/Kconfig"
+source "drivers/media/dvb-frontends/Kconfig"
 
 endif # MEDIA_SUPPORT
diff --git a/drivers/media/Makefile b/drivers/media/Makefile
index 64755c9..620f275 100644
--- a/drivers/media/Makefile
+++ b/drivers/media/Makefile
@@ -4,11 +4,30 @@
 
 media-objs	:= media-device.o media-devnode.o media-entity.o
 
+#
+# I2C drivers should come before other drivers, otherwise they'll fail
+# when compiled as builtin drivers
+#
+obj-y += i2c/ tuners/
+obj-$(CONFIG_DVB_CORE)  += dvb-frontends/
+
+#
+# Now, let's link-in the media core
+#
 ifeq ($(CONFIG_MEDIA_CONTROLLER),y)
   obj-$(CONFIG_MEDIA_SUPPORT) += media.o
 endif
 
-obj-y += common/ rc/ video/
+obj-$(CONFIG_VIDEO_DEV) += v4l2-core/
+obj-$(CONFIG_DVB_CORE)  += dvb-core/
 
+# There are both core and drivers at RC subtree - merge before drivers
+obj-y += rc/
+
+#
+# Finally, merge the drivers that require the core
+#
+
+obj-y += common/ platform/ pci/ usb/ mmc/ firewire/ parport/
 obj-$(CONFIG_VIDEO_DEV) += radio/
-obj-$(CONFIG_DVB_CORE)  += dvb/
+
diff --git a/drivers/media/common/Kconfig b/drivers/media/common/Kconfig
index 769c6f8..121b011 100644
--- a/drivers/media/common/Kconfig
+++ b/drivers/media/common/Kconfig
@@ -1,9 +1,3 @@
-config VIDEO_SAA7146
-	tristate
-	depends on I2C && PCI
-
-config VIDEO_SAA7146_VV
-	tristate
-	depends on VIDEO_V4L2
-	select VIDEOBUF_DMA_SG
-	select VIDEO_SAA7146
+source "drivers/media/common/b2c2/Kconfig"
+source "drivers/media/common/saa7146/Kconfig"
+source "drivers/media/common/siano/Kconfig"
diff --git a/drivers/media/common/Makefile b/drivers/media/common/Makefile
index e3ec963..b8e2e3a 100644
--- a/drivers/media/common/Makefile
+++ b/drivers/media/common/Makefile
@@ -1,6 +1 @@
-saa7146-objs    := saa7146_i2c.o saa7146_core.o
-saa7146_vv-objs := saa7146_fops.o saa7146_video.o saa7146_hlp.o saa7146_vbi.o
-
-obj-y += tuners/
-obj-$(CONFIG_VIDEO_SAA7146) += saa7146.o
-obj-$(CONFIG_VIDEO_SAA7146_VV) += saa7146_vv.o
+obj-y += b2c2/ saa7146/ siano/
diff --git a/drivers/media/common/b2c2/Kconfig b/drivers/media/common/b2c2/Kconfig
new file mode 100644
index 0000000..1df9e57
--- /dev/null
+++ b/drivers/media/common/b2c2/Kconfig
@@ -0,0 +1,28 @@
+config DVB_B2C2_FLEXCOP
+	tristate
+	depends on DVB_CORE && I2C
+	depends on DVB_B2C2_FLEXCOP_PCI || DVB_B2C2_FLEXCOP_USB
+	default y
+	select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_STV0299 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_MT352 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_MT312 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_NXT200X if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_STV0297 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_BCM3510 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_LGDT330X if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_S5H1420 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_TUNER_ITD1000 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_ISL6421 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_CX24123 if MEDIA_SUBDRV_AUTOSELECT
+	select MEDIA_TUNER_SIMPLE if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_TUNER_CX24113 if MEDIA_SUBDRV_AUTOSELECT
+	help
+	  Support for the digital TV receiver chip made by B2C2 Inc. included in
+	  Technisats PCI cards and USB boxes.
+
+	  Say Y if you own such a device and want to use it.
+
+# Selected via the PCI or USB flexcop drivers
+config DVB_B2C2_FLEXCOP_DEBUG
+	bool
diff --git a/drivers/media/common/b2c2/Makefile b/drivers/media/common/b2c2/Makefile
new file mode 100644
index 0000000..24993a5
--- /dev/null
+++ b/drivers/media/common/b2c2/Makefile
@@ -0,0 +1,8 @@
+b2c2-flexcop-objs += flexcop.o flexcop-fe-tuner.o flexcop-i2c.o
+b2c2-flexcop-objs += flexcop-sram.o flexcop-eeprom.o flexcop-misc.o
+b2c2-flexcop-objs += flexcop-hw-filter.o
+obj-$(CONFIG_DVB_B2C2_FLEXCOP) += b2c2-flexcop.o
+
+ccflags-y += -Idrivers/media/dvb-core/
+ccflags-y += -Idrivers/media/dvb-frontends/
+ccflags-y += -Idrivers/media/tuners/
diff --git a/drivers/media/common/b2c2/flexcop-common.h b/drivers/media/common/b2c2/flexcop-common.h
new file mode 100644
index 0000000..437912e
--- /dev/null
+++ b/drivers/media/common/b2c2/flexcop-common.h
@@ -0,0 +1,185 @@
+/*
+ * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
+ * flexcop-common.h - common header file for device-specific source files
+ * see flexcop.c for copyright information
+ */
+#ifndef __FLEXCOP_COMMON_H__
+#define __FLEXCOP_COMMON_H__
+
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/mutex.h>
+
+#include "flexcop-reg.h"
+
+#include "dmxdev.h"
+#include "dvb_demux.h"
+#include "dvb_filter.h"
+#include "dvb_net.h"
+#include "dvb_frontend.h"
+
+#define FC_MAX_FEED 256
+
+#ifndef FC_LOG_PREFIX
+#warning please define a log prefix for your file, using a default one
+#define FC_LOG_PREFIX "b2c2-undef"
+#endif
+
+/* Steal from usb.h */
+#undef err
+#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)
+#undef warn
+#define warn(format, arg...) \
+	printk(KERN_WARNING FC_LOG_PREFIX ": " format "\n" , ## arg)
+
+struct flexcop_dma {
+	struct pci_dev *pdev;
+
+	u8 *cpu_addr0;
+	dma_addr_t dma_addr0;
+	u8 *cpu_addr1;
+	dma_addr_t dma_addr1;
+	u32 size; /* size of each address in bytes */
+};
+
+struct flexcop_i2c_adapter {
+	struct flexcop_device *fc;
+	struct i2c_adapter i2c_adap;
+
+	u8 no_base_addr;
+	flexcop_i2c_port_t port;
+};
+
+/* Control structure for data definitions that are common to
+ * the B2C2-based PCI and USB devices.
+ */
+struct flexcop_device {
+	/* general */
+	struct device *dev; /* for firmware_class */
+
+#define FC_STATE_DVB_INIT 0x01
+#define FC_STATE_I2C_INIT 0x02
+#define FC_STATE_FE_INIT  0x04
+	int init_state;
+
+	/* device information */
+	int has_32_hw_pid_filter;
+	flexcop_revision_t rev;
+	flexcop_device_type_t dev_type;
+	flexcop_bus_t bus_type;
+
+	/* dvb stuff */
+	struct dvb_adapter dvb_adapter;
+	struct dvb_frontend *fe;
+	struct dvb_net dvbnet;
+	struct dvb_demux demux;
+	struct dmxdev dmxdev;
+	struct dmx_frontend hw_frontend;
+	struct dmx_frontend mem_frontend;
+	int (*fe_sleep) (struct dvb_frontend *);
+
+	struct flexcop_i2c_adapter fc_i2c_adap[3];
+	struct mutex i2c_mutex;
+	struct module *owner;
+
+	/* options and status */
+	int extra_feedcount;
+	int feedcount;
+	int pid_filtering;
+	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_access_op_t, u8 chipaddr, u8 addr, u8 *buf, u16 len);
+	int (*stream_control) (struct flexcop_device *, int);
+	int (*get_mac_addr) (struct flexcop_device *fc, int extended);
+	void *bus_specific;
+};
+
+/* exported prototypes */
+
+/* from flexcop.c */
+void flexcop_pass_dmx_data(struct flexcop_device *fc, u8 *buf, u32 len);
+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 *);
+
+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);
+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);
+
+/* from flexcop-eeprom.c */
+/* the PCI part uses this call to get the MAC address, the USB part has its own */
+int flexcop_eeprom_check_mac_addr(struct flexcop_device *fc, int extended);
+
+/* from flexcop-i2c.c */
+/* the PCI part uses this a i2c_request callback, whereas the usb part has its own
+ * one. We have it in flexcop-i2c.c, because it is going via the actual
+ * I2C-channel of the flexcop.
+ */
+int flexcop_i2c_request(struct flexcop_i2c_adapter*, flexcop_access_op_t,
+	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);
+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);
+
+/* global prototypes for the flexcop-chip */
+/* from flexcop-fe-tuner.c */
+int flexcop_frontend_init(struct flexcop_device *fc);
+void flexcop_frontend_exit(struct flexcop_device *fc);
+
+/* from flexcop-i2c.c */
+int flexcop_i2c_init(struct flexcop_device *fc);
+void flexcop_i2c_exit(struct flexcop_device *fc);
+
+/* from flexcop-sram.c */
+int flexcop_sram_init(struct flexcop_device *fc);
+
+/* 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);
+
+/* from flexcop-hw-filter.c */
+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);
+
+void flexcop_set_mac_filter(struct flexcop_device *fc, u8 mac[6]);
+void flexcop_mac_filter_ctrl(struct flexcop_device *fc, int onoff);
+
+#endif
diff --git a/drivers/media/common/b2c2/flexcop-eeprom.c b/drivers/media/common/b2c2/flexcop-eeprom.c
new file mode 100644
index 0000000..a25373a
--- /dev/null
+++ b/drivers/media/common/b2c2/flexcop-eeprom.c
@@ -0,0 +1,147 @@
+/*
+ * 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"
+
+#if 0
+/*EEPROM (Skystar2 has one "24LC08B" chip on board) */
+static int eeprom_write(struct adapter *adapter, u16 addr, u8 *buf, u16 len)
+{
+	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)
+{
+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;
+		}
+	}
+	return 0;
+}
+
+/* These functions could be used to unlock SkyStar2 cards. */
+
+static int eeprom_writeKey(struct adapter *adapter, u8 *key, u32 len)
+{
+	u8 rbuf[20];
+	u8 wbuf[20];
+
+	if (len != 16)
+		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);
+}
+
+static int eeprom_readKey(struct adapter *adapter, u8 *key, u32 len)
+{
+	u8 buf[20];
+
+	if (len != 16)
+		return 0;
+
+	if (eeprom_lrc_read(adapter, 0x3e4, 20, buf, 4) == 0)
+		return 0;
+
+	memcpy(key, buf, len);
+	return 1;
+}
+
+static char eeprom_set_mac_addr(struct adapter *adapter, char type, u8 *mac)
+{
+	u8 tmp[8];
+
+	if (type != 0) {
+		tmp[0] = mac[0];
+		tmp[1] = mac[1];
+		tmp[2] = mac[2];
+		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];
+		tmp[3] = mac[3];
+		tmp[4] = mac[4];
+		tmp[5] = mac[5];
+	}
+
+	tmp[6] = 0;
+	tmp[7] = calc_lrc(tmp, 7);
+
+	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)
+{
+	return fc->i2c_request(fc,FC_READ,FC_I2C_PORT_EEPROM,0x50,addr,buf,len);
+}
+
+#endif
+
+static u8 calc_lrc(u8 *buf, int len)
+{
+	int i;
+	u8 sum = 0;
+	for (i = 0; i < len; i++)
+		sum = sum ^ buf[i];
+	return sum;
+}
+
+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);
+	for (i = 0; i < retries; i++) {
+		ret = fc->i2c_request(&fc->fc_i2c_adap[1], op, chipaddr,
+			addr & 0xff, buf, len);
+		if (ret == 0)
+			break;
+	}
+	return ret;
+}
+
+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)
+		if (calc_lrc(buf, len - 1) != buf[len - 1])
+			ret = -EINVAL;
+	return ret;
+}
+
+/* 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 */
+int flexcop_eeprom_check_mac_addr(struct flexcop_device *fc, int extended)
+{
+	u8 buf[8];
+	int ret = 0;
+
+	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");
+			ret = -EINVAL;
+		} else
+			memcpy(fc->dvb_adapter.proposed_mac,buf,6);
+	}
+	return ret;
+}
+EXPORT_SYMBOL(flexcop_eeprom_check_mac_addr);
diff --git a/drivers/media/common/b2c2/flexcop-fe-tuner.c b/drivers/media/common/b2c2/flexcop-fe-tuner.c
new file mode 100644
index 0000000..850a6c6
--- /dev/null
+++ b/drivers/media/common/b2c2/flexcop-fe-tuner.c
@@ -0,0 +1,678 @@
+/*
+ * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
+ * flexcop-fe-tuner.c - methods for frontend attachment and DiSEqC controlling
+ * see flexcop.c for copyright information
+ */
+#include <media/tuner.h>
+#include "flexcop.h"
+#include "mt312.h"
+#include "stv0299.h"
+#include "s5h1420.h"
+#include "itd1000.h"
+#include "cx24113.h"
+#include "cx24123.h"
+#include "isl6421.h"
+#include "mt352.h"
+#include "bcm3510.h"
+#include "nxt200x.h"
+#include "dvb-pll.h"
+#include "lgdt330x.h"
+#include "tuner-simple.h"
+#include "stv0297.h"
+
+
+/* Can we use the specified front-end?  Remember that if we are compiled
+ * into the kernel we can't call code that's in modules.  */
+#define FE_SUPPORTED(fe) (defined(CONFIG_DVB_##fe) || \
+	(defined(CONFIG_DVB_##fe##_MODULE) && defined(MODULE)))
+
+/* lnb control */
+#if FE_SUPPORTED(MT312) || FE_SUPPORTED(STV0299)
+static int flexcop_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+{
+	struct flexcop_device *fc = fe->dvb->priv;
+	flexcop_ibi_value v;
+	deb_tuner("polarity/voltage = %u\n", voltage);
+
+	v = fc->read_ibi_reg(fc, misc_204);
+	switch (voltage) {
+	case SEC_VOLTAGE_OFF:
+		v.misc_204.ACPI1_sig = 1;
+		break;
+	case SEC_VOLTAGE_13:
+		v.misc_204.ACPI1_sig = 0;
+		v.misc_204.LNB_L_H_sig = 0;
+		break;
+	case SEC_VOLTAGE_18:
+		v.misc_204.ACPI1_sig = 0;
+		v.misc_204.LNB_L_H_sig = 1;
+		break;
+	default:
+		err("unknown SEC_VOLTAGE value");
+		return -EINVAL;
+	}
+	return fc->write_ibi_reg(fc, misc_204, v);
+}
+#endif
+
+#if FE_SUPPORTED(S5H1420) || FE_SUPPORTED(STV0299) || FE_SUPPORTED(MT312)
+static int flexcop_sleep(struct dvb_frontend* fe)
+{
+	struct flexcop_device *fc = fe->dvb->priv;
+	if (fc->fe_sleep)
+		return fc->fe_sleep(fe);
+	return 0;
+}
+#endif
+
+/* SkyStar2 DVB-S rev 2.3 */
+#if FE_SUPPORTED(MT312) && FE_SUPPORTED(PLL)
+static int flexcop_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
+{
+/* u16 wz_half_period_for_45_mhz[] = { 0x01ff, 0x0154, 0x00ff, 0x00cc }; */
+	struct flexcop_device *fc = fe->dvb->priv;
+	flexcop_ibi_value v;
+	u16 ax;
+	v.raw = 0;
+	deb_tuner("tone = %u\n",tone);
+
+	switch (tone) {
+	case SEC_TONE_ON:
+		ax = 0x01ff;
+		break;
+	case SEC_TONE_OFF:
+		ax = 0;
+		break;
+	default:
+		err("unknown SEC_TONE value");
+		return -EINVAL;
+	}
+
+	v.lnb_switch_freq_200.LNB_CTLPrescaler_sig = 1; /* divide by 2 */
+	v.lnb_switch_freq_200.LNB_CTLHighCount_sig = ax;
+	v.lnb_switch_freq_200.LNB_CTLLowCount_sig  = ax == 0 ? 0x1ff : ax;
+	return fc->write_ibi_reg(fc,lnb_switch_freq_200,v);
+}
+
+static void flexcop_diseqc_send_bit(struct dvb_frontend* fe, int data)
+{
+	flexcop_set_tone(fe, SEC_TONE_ON);
+	udelay(data ? 500 : 1000);
+	flexcop_set_tone(fe, SEC_TONE_OFF);
+	udelay(data ? 1000 : 500);
+}
+
+static void flexcop_diseqc_send_byte(struct dvb_frontend* fe, int data)
+{
+	int i, par = 1, d;
+	for (i = 7; i >= 0; i--) {
+		d = (data >> i) & 1;
+		par ^= d;
+		flexcop_diseqc_send_bit(fe, d);
+	}
+	flexcop_diseqc_send_bit(fe, par);
+}
+
+static int flexcop_send_diseqc_msg(struct dvb_frontend *fe,
+	int len, u8 *msg, unsigned long burst)
+{
+	int i;
+
+	flexcop_set_tone(fe, SEC_TONE_OFF);
+	mdelay(16);
+
+	for (i = 0; i < len; i++)
+		flexcop_diseqc_send_byte(fe,msg[i]);
+	mdelay(16);
+
+	if (burst != -1) {
+		if (burst)
+			flexcop_diseqc_send_byte(fe, 0xff);
+		else {
+			flexcop_set_tone(fe, SEC_TONE_ON);
+			mdelay(12);
+			udelay(500);
+			flexcop_set_tone(fe, SEC_TONE_OFF);
+		}
+		msleep(20);
+	}
+	return 0;
+}
+
+static int flexcop_diseqc_send_master_cmd(struct dvb_frontend *fe,
+	struct dvb_diseqc_master_cmd *cmd)
+{
+	return flexcop_send_diseqc_msg(fe, cmd->msg_len, cmd->msg, 0);
+}
+
+static int flexcop_diseqc_send_burst(struct dvb_frontend *fe,
+	fe_sec_mini_cmd_t minicmd)
+{
+	return flexcop_send_diseqc_msg(fe, 0, NULL, minicmd);
+}
+
+static struct mt312_config skystar23_samsung_tbdu18132_config = {
+	.demod_address = 0x0e,
+};
+
+static int skystar2_rev23_attach(struct flexcop_device *fc,
+	struct i2c_adapter *i2c)
+{
+	struct dvb_frontend_ops *ops;
+
+	fc->fe = dvb_attach(mt312_attach, &skystar23_samsung_tbdu18132_config, i2c);
+	if (!fc->fe)
+		return 0;
+
+	if (!dvb_attach(dvb_pll_attach, fc->fe, 0x61, i2c,
+			DVB_PLL_SAMSUNG_TBDU18132))
+		return 0;
+
+	ops = &fc->fe->ops;
+	ops->diseqc_send_master_cmd = flexcop_diseqc_send_master_cmd;
+	ops->diseqc_send_burst      = flexcop_diseqc_send_burst;
+	ops->set_tone               = flexcop_set_tone;
+	ops->set_voltage            = flexcop_set_voltage;
+	fc->fe_sleep                = ops->sleep;
+	ops->sleep                  = flexcop_sleep;
+	return 1;
+}
+#else
+#define skystar2_rev23_attach NULL
+#endif
+
+/* SkyStar2 DVB-S rev 2.6 */
+#if FE_SUPPORTED(STV0299) && FE_SUPPORTED(PLL)
+static int samsung_tbmu24112_set_symbol_rate(struct dvb_frontend *fe,
+	u32 srate, u32 ratio)
+{
+	u8 aclk = 0;
+	u8 bclk = 0;
+
+	if (srate < 1500000) {
+		aclk = 0xb7; bclk = 0x47;
+	} else if (srate < 3000000) {
+		aclk = 0xb7; bclk = 0x4b;
+	} else if (srate < 7000000) {
+		aclk = 0xb7; bclk = 0x4f;
+	} else if (srate < 14000000) {
+		aclk = 0xb7; bclk = 0x53;
+	} else if (srate < 30000000) {
+		aclk = 0xb6; bclk = 0x53;
+	} else if (srate < 45000000) {
+		aclk = 0xb4; bclk = 0x51;
+	}
+
+	stv0299_writereg(fe, 0x13, aclk);
+	stv0299_writereg(fe, 0x14, bclk);
+	stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
+	stv0299_writereg(fe, 0x20, (ratio >>  8) & 0xff);
+	stv0299_writereg(fe, 0x21,  ratio        & 0xf0);
+	return 0;
+}
+
+static u8 samsung_tbmu24112_inittab[] = {
+	0x01, 0x15,
+	0x02, 0x30,
+	0x03, 0x00,
+	0x04, 0x7D,
+	0x05, 0x35,
+	0x06, 0x02,
+	0x07, 0x00,
+	0x08, 0xC3,
+	0x0C, 0x00,
+	0x0D, 0x81,
+	0x0E, 0x23,
+	0x0F, 0x12,
+	0x10, 0x7E,
+	0x11, 0x84,
+	0x12, 0xB9,
+	0x13, 0x88,
+	0x14, 0x89,
+	0x15, 0xC9,
+	0x16, 0x00,
+	0x17, 0x5C,
+	0x18, 0x00,
+	0x19, 0x00,
+	0x1A, 0x00,
+	0x1C, 0x00,
+	0x1D, 0x00,
+	0x1E, 0x00,
+	0x1F, 0x3A,
+	0x20, 0x2E,
+	0x21, 0x80,
+	0x22, 0xFF,
+	0x23, 0xC1,
+	0x28, 0x00,
+	0x29, 0x1E,
+	0x2A, 0x14,
+	0x2B, 0x0F,
+	0x2C, 0x09,
+	0x2D, 0x05,
+	0x31, 0x1F,
+	0x32, 0x19,
+	0x33, 0xFE,
+	0x34, 0x93,
+	0xff, 0xff,
+};
+
+static struct stv0299_config samsung_tbmu24112_config = {
+	.demod_address = 0x68,
+	.inittab = samsung_tbmu24112_inittab,
+	.mclk = 88000000UL,
+	.invert = 0,
+	.skip_reinit = 0,
+	.lock_output = STV0299_LOCKOUTPUT_LK,
+	.volt13_op0_op1 = STV0299_VOLT13_OP1,
+	.min_delay_ms = 100,
+	.set_symbol_rate = samsung_tbmu24112_set_symbol_rate,
+};
+
+static int skystar2_rev26_attach(struct flexcop_device *fc,
+	struct i2c_adapter *i2c)
+{
+	fc->fe = dvb_attach(stv0299_attach, &samsung_tbmu24112_config, i2c);
+	if (!fc->fe)
+		return 0;
+
+	if (!dvb_attach(dvb_pll_attach, fc->fe, 0x61, i2c,
+			DVB_PLL_SAMSUNG_TBMU24112))
+		return 0;
+
+	fc->fe->ops.set_voltage = flexcop_set_voltage;
+	fc->fe_sleep = fc->fe->ops.sleep;
+	fc->fe->ops.sleep = flexcop_sleep;
+	return 1;
+
+}
+#else
+#define skystar2_rev26_attach NULL
+#endif
+
+/* SkyStar2 DVB-S rev 2.7 */
+#if FE_SUPPORTED(S5H1420) && FE_SUPPORTED(ISL6421) && FE_SUPPORTED(TUNER_ITD1000)
+static struct s5h1420_config skystar2_rev2_7_s5h1420_config = {
+	.demod_address = 0x53,
+	.invert = 1,
+	.repeated_start_workaround = 1,
+	.serial_mpeg = 1,
+};
+
+static struct itd1000_config skystar2_rev2_7_itd1000_config = {
+	.i2c_address = 0x61,
+};
+
+static int skystar2_rev27_attach(struct flexcop_device *fc,
+	struct i2c_adapter *i2c)
+{
+	flexcop_ibi_value r108;
+	struct i2c_adapter *i2c_tuner;
+
+	/* enable no_base_addr - no repeated start when reading */
+	fc->fc_i2c_adap[0].no_base_addr = 1;
+	fc->fe = dvb_attach(s5h1420_attach, &skystar2_rev2_7_s5h1420_config,
+			    i2c);
+	if (!fc->fe)
+		goto fail;
+
+	i2c_tuner = s5h1420_get_tuner_i2c_adapter(fc->fe);
+	if (!i2c_tuner)
+		goto fail;
+
+	fc->fe_sleep = fc->fe->ops.sleep;
+	fc->fe->ops.sleep = flexcop_sleep;
+
+	/* enable no_base_addr - no repeated start when reading */
+	fc->fc_i2c_adap[2].no_base_addr = 1;
+	if (!dvb_attach(isl6421_attach, fc->fe, &fc->fc_i2c_adap[2].i2c_adap,
+			0x08, 1, 1)) {
+		err("ISL6421 could NOT be attached");
+		goto fail_isl;
+	}
+	info("ISL6421 successfully attached");
+
+	/* the ITD1000 requires a lower i2c clock - is it a problem ? */
+	r108.raw = 0x00000506;
+	fc->write_ibi_reg(fc, tw_sm_c_108, r108);
+	if (!dvb_attach(itd1000_attach, fc->fe, i2c_tuner,
+			&skystar2_rev2_7_itd1000_config)) {
+		err("ITD1000 could NOT be attached");
+		/* Should i2c clock be restored? */
+		goto fail_isl;
+	}
+	info("ITD1000 successfully attached");
+
+	return 1;
+
+fail_isl:
+	fc->fc_i2c_adap[2].no_base_addr = 0;
+fail:
+	/* for the next devices we need it again */
+	fc->fc_i2c_adap[0].no_base_addr = 0;
+	return 0;
+}
+#else
+#define skystar2_rev27_attach NULL
+#endif
+
+/* SkyStar2 rev 2.8 */
+#if FE_SUPPORTED(CX24123) && FE_SUPPORTED(ISL6421) && FE_SUPPORTED(TUNER_CX24113)
+static struct cx24123_config skystar2_rev2_8_cx24123_config = {
+	.demod_address = 0x55,
+	.dont_use_pll = 1,
+	.agc_callback = cx24113_agc_callback,
+};
+
+static const struct cx24113_config skystar2_rev2_8_cx24113_config = {
+	.i2c_addr = 0x54,
+	.xtal_khz = 10111,
+};
+
+static int skystar2_rev28_attach(struct flexcop_device *fc,
+	struct i2c_adapter *i2c)
+{
+	struct i2c_adapter *i2c_tuner;
+
+	fc->fe = dvb_attach(cx24123_attach, &skystar2_rev2_8_cx24123_config,
+			    i2c);
+	if (!fc->fe)
+		return 0;
+
+	i2c_tuner = cx24123_get_tuner_i2c_adapter(fc->fe);
+	if (!i2c_tuner)
+		return 0;
+
+	if (!dvb_attach(cx24113_attach, fc->fe, &skystar2_rev2_8_cx24113_config,
+			i2c_tuner)) {
+		err("CX24113 could NOT be attached");
+		return 0;
+	}
+	info("CX24113 successfully attached");
+
+	fc->fc_i2c_adap[2].no_base_addr = 1;
+	if (!dvb_attach(isl6421_attach, fc->fe, &fc->fc_i2c_adap[2].i2c_adap,
+			0x08, 0, 0)) {
+		err("ISL6421 could NOT be attached");
+		fc->fc_i2c_adap[2].no_base_addr = 0;
+		return 0;
+	}
+	info("ISL6421 successfully attached");
+	/* TODO on i2c_adap[1] addr 0x11 (EEPROM) there seems to be an
+	 * IR-receiver (PIC16F818) - but the card has no input for that ??? */
+	return 1;
+}
+#else
+#define skystar2_rev28_attach NULL
+#endif
+
+/* AirStar DVB-T */
+#if FE_SUPPORTED(MT352) && FE_SUPPORTED(PLL)
+static int samsung_tdtc9251dh0_demod_init(struct dvb_frontend *fe)
+{
+	static u8 mt352_clock_config[] = { 0x89, 0x18, 0x2d };
+	static u8 mt352_reset[] = { 0x50, 0x80 };
+	static u8 mt352_adc_ctl_1_cfg[] = { 0x8E, 0x40 };
+	static u8 mt352_agc_cfg[] = { 0x67, 0x28, 0xa1 };
+	static u8 mt352_capt_range_cfg[] = { 0x75, 0x32 };
+
+	mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config));
+	udelay(2000);
+	mt352_write(fe, mt352_reset, sizeof(mt352_reset));
+	mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg));
+	mt352_write(fe, mt352_agc_cfg, sizeof(mt352_agc_cfg));
+	mt352_write(fe, mt352_capt_range_cfg, sizeof(mt352_capt_range_cfg));
+	return 0;
+}
+
+static struct mt352_config samsung_tdtc9251dh0_config = {
+	.demod_address = 0x0f,
+	.demod_init    = samsung_tdtc9251dh0_demod_init,
+};
+
+static int airstar_dvbt_attach(struct flexcop_device *fc,
+	struct i2c_adapter *i2c)
+{
+	fc->fe = dvb_attach(mt352_attach, &samsung_tdtc9251dh0_config, i2c);
+	if (!fc->fe)
+		return 0;
+
+	return !!dvb_attach(dvb_pll_attach, fc->fe, 0x61, NULL,
+			    DVB_PLL_SAMSUNG_TDTC9251DH0);
+}
+#else
+#define airstar_dvbt_attach NULL
+#endif
+
+/* AirStar ATSC 1st generation */
+#if FE_SUPPORTED(BCM3510)
+static int flexcop_fe_request_firmware(struct dvb_frontend *fe,
+	const struct firmware **fw, char* name)
+{
+	struct flexcop_device *fc = fe->dvb->priv;
+	return request_firmware(fw, name, fc->dev);
+}
+
+static struct bcm3510_config air2pc_atsc_first_gen_config = {
+	.demod_address    = 0x0f,
+	.request_firmware = flexcop_fe_request_firmware,
+};
+
+static int airstar_atsc1_attach(struct flexcop_device *fc,
+	struct i2c_adapter *i2c)
+{
+	fc->fe = dvb_attach(bcm3510_attach, &air2pc_atsc_first_gen_config, i2c);
+	return fc->fe != NULL;
+}
+#else
+#define airstar_atsc1_attach NULL
+#endif
+
+/* AirStar ATSC 2nd generation */
+#if FE_SUPPORTED(NXT200X) && FE_SUPPORTED(PLL)
+static struct nxt200x_config samsung_tbmv_config = {
+	.demod_address = 0x0a,
+};
+
+static int airstar_atsc2_attach(struct flexcop_device *fc,
+	struct i2c_adapter *i2c)
+{
+	fc->fe = dvb_attach(nxt200x_attach, &samsung_tbmv_config, i2c);
+	if (!fc->fe)
+		return 0;
+
+	return !!dvb_attach(dvb_pll_attach, fc->fe, 0x61, NULL,
+			    DVB_PLL_SAMSUNG_TBMV);
+}
+#else
+#define airstar_atsc2_attach NULL
+#endif
+
+/* AirStar ATSC 3rd generation */
+#if FE_SUPPORTED(LGDT330X)
+static struct lgdt330x_config air2pc_atsc_hd5000_config = {
+	.demod_address       = 0x59,
+	.demod_chip          = LGDT3303,
+	.serial_mpeg         = 0x04,
+	.clock_polarity_flip = 1,
+};
+
+static int airstar_atsc3_attach(struct flexcop_device *fc,
+	struct i2c_adapter *i2c)
+{
+	fc->fe = dvb_attach(lgdt330x_attach, &air2pc_atsc_hd5000_config, i2c);
+	if (!fc->fe)
+		return 0;
+
+	return !!dvb_attach(simple_tuner_attach, fc->fe, i2c, 0x61,
+			    TUNER_LG_TDVS_H06XF);
+}
+#else
+#define airstar_atsc3_attach NULL
+#endif
+
+/* CableStar2 DVB-C */
+#if FE_SUPPORTED(STV0297) && FE_SUPPORTED(PLL)
+static u8 alps_tdee4_stv0297_inittab[] = {
+	0x80, 0x01,
+	0x80, 0x00,
+	0x81, 0x01,
+	0x81, 0x00,
+	0x00, 0x48,
+	0x01, 0x58,
+	0x03, 0x00,
+	0x04, 0x00,
+	0x07, 0x00,
+	0x08, 0x00,
+	0x30, 0xff,
+	0x31, 0x9d,
+	0x32, 0xff,
+	0x33, 0x00,
+	0x34, 0x29,
+	0x35, 0x55,
+	0x36, 0x80,
+	0x37, 0x6e,
+	0x38, 0x9c,
+	0x40, 0x1a,
+	0x41, 0xfe,
+	0x42, 0x33,
+	0x43, 0x00,
+	0x44, 0xff,
+	0x45, 0x00,
+	0x46, 0x00,
+	0x49, 0x04,
+	0x4a, 0x51,
+	0x4b, 0xf8,
+	0x52, 0x30,
+	0x53, 0x06,
+	0x59, 0x06,
+	0x5a, 0x5e,
+	0x5b, 0x04,
+	0x61, 0x49,
+	0x62, 0x0a,
+	0x70, 0xff,
+	0x71, 0x04,
+	0x72, 0x00,
+	0x73, 0x00,
+	0x74, 0x0c,
+	0x80, 0x20,
+	0x81, 0x00,
+	0x82, 0x30,
+	0x83, 0x00,
+	0x84, 0x04,
+	0x85, 0x22,
+	0x86, 0x08,
+	0x87, 0x1b,
+	0x88, 0x00,
+	0x89, 0x00,
+	0x90, 0x00,
+	0x91, 0x04,
+	0xa0, 0x86,
+	0xa1, 0x00,
+	0xa2, 0x00,
+	0xb0, 0x91,
+	0xb1, 0x0b,
+	0xc0, 0x5b,
+	0xc1, 0x10,
+	0xc2, 0x12,
+	0xd0, 0x02,
+	0xd1, 0x00,
+	0xd2, 0x00,
+	0xd3, 0x00,
+	0xd4, 0x02,
+	0xd5, 0x00,
+	0xde, 0x00,
+	0xdf, 0x01,
+	0xff, 0xff,
+};
+
+static struct stv0297_config alps_tdee4_stv0297_config = {
+	.demod_address = 0x1c,
+	.inittab = alps_tdee4_stv0297_inittab,
+};
+
+static int cablestar2_attach(struct flexcop_device *fc,
+	struct i2c_adapter *i2c)
+{
+	fc->fc_i2c_adap[0].no_base_addr = 1;
+	fc->fe = dvb_attach(stv0297_attach, &alps_tdee4_stv0297_config, i2c);
+	if (!fc->fe)
+		goto fail;
+
+	/* This tuner doesn't use the stv0297's I2C gate, but instead the
+	 * tuner is connected to a different flexcop I2C adapter.  */
+	if (fc->fe->ops.i2c_gate_ctrl)
+		fc->fe->ops.i2c_gate_ctrl(fc->fe, 0);
+	fc->fe->ops.i2c_gate_ctrl = NULL;
+
+	if (!dvb_attach(dvb_pll_attach, fc->fe, 0x61,
+			&fc->fc_i2c_adap[2].i2c_adap, DVB_PLL_TDEE4))
+		goto fail;
+
+	return 1;
+
+fail:
+	/* Reset for next frontend to try */
+	fc->fc_i2c_adap[0].no_base_addr = 0;
+	return 0;
+}
+#else
+#define cablestar2_attach NULL
+#endif
+
+static struct {
+	flexcop_device_type_t type;
+	int (*attach)(struct flexcop_device *, struct i2c_adapter *);
+} flexcop_frontends[] = {
+	{ FC_SKY_REV27, skystar2_rev27_attach },
+	{ FC_SKY_REV28, skystar2_rev28_attach },
+	{ FC_SKY_REV26, skystar2_rev26_attach },
+	{ FC_AIR_DVBT, airstar_dvbt_attach },
+	{ FC_AIR_ATSC2, airstar_atsc2_attach },
+	{ FC_AIR_ATSC3, airstar_atsc3_attach },
+	{ FC_AIR_ATSC1, airstar_atsc1_attach },
+	{ FC_CABLE, cablestar2_attach },
+	{ FC_SKY_REV23, skystar2_rev23_attach },
+};
+
+/* try to figure out the frontend */
+int flexcop_frontend_init(struct flexcop_device *fc)
+{
+	int i;
+	for (i = 0; i < ARRAY_SIZE(flexcop_frontends); i++) {
+		if (!flexcop_frontends[i].attach)
+			continue;
+		/* type needs to be set before, because of some workarounds
+		 * done based on the probed card type */
+		fc->dev_type = flexcop_frontends[i].type;
+		if (flexcop_frontends[i].attach(fc, &fc->fc_i2c_adap[0].i2c_adap))
+			goto fe_found;
+		/* Clean up partially attached frontend */
+		if (fc->fe) {
+			dvb_frontend_detach(fc->fe);
+			fc->fe = NULL;
+		}
+	}
+	fc->dev_type = FC_UNK;
+	err("no frontend driver found for this B2C2/FlexCop adapter");
+	return -ENODEV;
+
+fe_found:
+	info("found '%s' .", fc->fe->ops.info.name);
+	if (dvb_register_frontend(&fc->dvb_adapter, fc->fe)) {
+		err("frontend registration failed!");
+		dvb_frontend_detach(fc->fe);
+		fc->fe = NULL;
+		return -EINVAL;
+	}
+	fc->init_state |= FC_STATE_FE_INIT;
+	return 0;
+}
+
+void flexcop_frontend_exit(struct flexcop_device *fc)
+{
+	if (fc->init_state & FC_STATE_FE_INIT) {
+		dvb_unregister_frontend(fc->fe);
+		dvb_frontend_detach(fc->fe);
+	}
+	fc->init_state &= ~FC_STATE_FE_INIT;
+}
diff --git a/drivers/media/common/b2c2/flexcop-hw-filter.c b/drivers/media/common/b2c2/flexcop-hw-filter.c
new file mode 100644
index 0000000..77e4547
--- /dev/null
+++ b/drivers/media/common/b2c2/flexcop-hw-filter.c
@@ -0,0 +1,232 @@
+/*
+ * 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");
+}
+
+void flexcop_smc_ctrl(struct flexcop_device *fc, int 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);
+}
+
+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);
+
+	v418.mac_address_418.MAC1 = mac[0];
+	v418.mac_address_418.MAC2 = mac[1];
+	v418.mac_address_418.MAC3 = mac[2];
+	v418.mac_address_418.MAC6 = mac[3];
+	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);
+}
+
+void flexcop_mac_filter_ctrl(struct flexcop_device *fc, int 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)
+{
+	/* 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);
+}
+
+static void flexcop_pid_group_filter_ctrl(struct flexcop_device *fc, int 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
+ * the first 6 PIDs
+ */
+
+#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);
+
+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);
+}
+
+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);
+}
+
+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);
+}
+
+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);
+}
+
+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);
+}
+
+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);
+}
+
+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");
+
+	/* 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;
+
+			/* 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;
+	}
+}
+
+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);
+		fc->fullts_streaming_state = onoff;
+	}
+	return 0;
+}
+
+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;
+
+	fc->feedcount += onoff ? 1 : -1; /* the number of PIDs/Feed currently requested */
+	if (dvbdmxfeed->index >= max_pid_filter)
+		fc->extra_feedcount += onoff ? 1 : -1;
+
+	/* toggle complete-TS-streaming when:
+	 * - pid_filtering is not enabled and it is the first or last feed requested
+	 * - pid_filtering is enabled,
+	 *   - but the number of requested feeds is exceeded
+	 *   - or the requested pid is 0x2000 */
+
+	if (!fc->pid_filtering && fc->feedcount == onoff)
+		flexcop_toggle_fullts_streaming(fc, onoff);
+
+	if (fc->pid_filtering) {
+		flexcop_pid_control \
+			(fc, dvbdmxfeed->index, dvbdmxfeed->pid, onoff);
+
+		if (fc->extra_feedcount > 0)
+			flexcop_toggle_fullts_streaming(fc, 1);
+		else if (dvbdmxfeed->pid == 0x2000)
+			flexcop_toggle_fullts_streaming(fc, onoff);
+		else
+			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);
+		if (fc->stream_control) /* device specific stream control */
+			fc->stream_control(fc, onoff);
+
+		/* feeding stopped -> reset the flexcop filter*/
+		if (onoff == 0) {
+			flexcop_reset_block_300(fc);
+			flexcop_hw_filter_init(fc);
+		}
+	}
+	return 0;
+}
+EXPORT_SYMBOL(flexcop_pid_feed_control);
+
+void flexcop_hw_filter_init(struct flexcop_device *fc)
+{
+	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_group_filter(fc, 0, 0x1fe0);
+	flexcop_pid_group_filter_ctrl(fc, 0);
+
+	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);
+
+	flexcop_null_filter_ctrl(fc, 1);
+}
diff --git a/drivers/media/common/b2c2/flexcop-i2c.c b/drivers/media/common/b2c2/flexcop-i2c.c
new file mode 100644
index 0000000..965d5eb
--- /dev/null
+++ b/drivers/media/common/b2c2/flexcop-i2c.c
@@ -0,0 +1,288 @@
+/*
+ * 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
+ */
+#include "flexcop.h"
+
+#define FC_MAX_I2C_RETRIES 100000
+
+static int flexcop_i2c_operation(struct flexcop_device *fc,
+		flexcop_ibi_value *r100)
+{
+	int i;
+	flexcop_ibi_value r;
+
+	r100->tw_sm_c_100.working_start = 1;
+	deb_i2c("r100 before: %08x\n",r100->raw);
+
+	fc->write_ibi_reg(fc, tw_sm_c_100, ibi_zero);
+	fc->write_ibi_reg(fc, tw_sm_c_100, *r100); /* initiating i2c operation */
+
+	for (i = 0; i < FC_MAX_I2C_RETRIES; i++) {
+		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) {
+				*r100 = r;
+				deb_i2c("i2c success\n");
+				return 0;
+			}
+		} else {
+			deb_i2c("suffering from an i2c ack_error\n");
+			return -EREMOTEIO;
+		}
+	}
+	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 r104;
+	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");
+		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("read failed. %d\n", ret);
+		return ret;
+	}
+
+	buf[0] = r100.tw_sm_c_100.data1_reg;
+
+	if (len > 0) {
+		r104 = i2c->fc->read_ibi_reg(i2c->fc, tw_sm_c_104);
+		deb_i2c("read: r100: %08x, r104: %08x\n", r100.raw, r104.raw);
+
+		/* there is at least one more byte, otherwise we wouldn't be here */
+		buf[1] = r104.tw_sm_c_104.data2_reg;
+		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)
+{
+	flexcop_ibi_value r104;
+	int len = r100.tw_sm_c_100.total_bytes; /* remember total_bytes is buflen-1 */
+	r104.raw = 0;
+
+	/* 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;
+
+	deb_i2c("write: r100: %08x, r104: %08x\n", r100.raw, r104.raw);
+
+	/* write the additional i2c data before doing the actual i2c operation */
+	fc->write_ibi_reg(fc, tw_sm_c_104, r104);
+	return flexcop_i2c_operation(fc, &r100);
+}
+
+int flexcop_i2c_request(struct flexcop_i2c_adapter *i2c,
+		flexcop_access_op_t op, u8 chipaddr, u8 addr, u8 *buf, u16 len)
+{
+	int ret;
+
+#ifdef DUMP_I2C_MESSAGES
+	int i;
+#endif
+
+	u16 bytes_to_transfer;
+	flexcop_ibi_value r100;
+
+	deb_i2c("op = %d\n",op);
+	r100.raw = 0;
+	r100.tw_sm_c_100.chipaddr = chipaddr;
+	r100.tw_sm_c_100.twoWS_rw = op;
+	r100.tw_sm_c_100.twoWS_port_reg = i2c->port;
+
+#ifdef DUMP_I2C_MESSAGES
+	printk(KERN_DEBUG "%d ", i2c->port);
+	if (op == FC_READ)
+		printk("rd(");
+	else
+		printk("wr(");
+	printk("%02x): %02x ", chipaddr, addr);
+#endif
+
+	/* in that case addr is the only value ->
+	 * we write it twice as baseaddr and val0
+	 * BBTI is doing it like that for ISL6421 at least */
+	if (i2c->no_base_addr && len == 0 && op == FC_WRITE) {
+		buf = &addr;
+		len = 1;
+	}
+
+	while (len != 0) {
+		bytes_to_transfer = len > 4 ? 4 : len;
+
+		r100.tw_sm_c_100.total_bytes = bytes_to_transfer - 1;
+		r100.tw_sm_c_100.baseaddr = addr;
+
+		if (op == FC_READ)
+			ret = flexcop_i2c_read4(i2c, r100, buf);
+		else
+			ret = flexcop_i2c_write4(i2c->fc, r100, buf);
+
+#ifdef DUMP_I2C_MESSAGES
+		for (i = 0; i < bytes_to_transfer; i++)
+			printk("%02x ", buf[i]);
+#endif
+
+		if (ret < 0)
+			return ret;
+
+		buf  += bytes_to_transfer;
+		addr += bytes_to_transfer;
+		len  -= bytes_to_transfer;
+	}
+
+#ifdef DUMP_I2C_MESSAGES
+	printk("\n");
+#endif
+
+	return 0;
+}
+/* exported for PCI i2c */
+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)
+{
+	struct flexcop_i2c_adapter *i2c = i2c_get_adapdata(i2c_adap);
+	int i, ret = 0;
+
+	/* Some drivers use 1 byte or 0 byte reads as probes, which this
+	 * driver doesn't support.  These probes will always fail, so this
+	 * hack makes them always succeed.  If one knew how, it would of
+	 * course be better to actually do the read.  */
+	if (num == 1 && msgs[0].flags == I2C_M_RD && msgs[0].len <= 1)
+		return 1;
+
+	if (mutex_lock_interruptible(&i2c->fc->i2c_mutex))
+		return -ERESTARTSYS;
+
+	for (i = 0; i < num; i++) {
+		/* 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);
+			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);
+		if (ret < 0) {
+			deb_i2c("i2c master_xfer failed");
+			break;
+		}
+	}
+
+	mutex_unlock(&i2c->fc->i2c_mutex);
+
+	if (ret == 0)
+		ret = num;
+	return ret;
+}
+
+static u32 flexcop_i2c_func(struct i2c_adapter *adapter)
+{
+	return I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm flexcop_algo = {
+	.master_xfer	= flexcop_master_xfer,
+	.functionality	= flexcop_i2c_func,
+};
+
+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));
+	strlcpy(fc->fc_i2c_adap[1].i2c_adap.name, "B2C2 FlexCop I2C to eeprom",
+			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));
+
+	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]);
+	i2c_set_adapdata(&fc->fc_i2c_adap[2].i2c_adap, &fc->fc_i2c_adap[2]);
+
+	fc->fc_i2c_adap[0].i2c_adap.algo =
+		fc->fc_i2c_adap[1].i2c_adap.algo =
+		fc->fc_i2c_adap[2].i2c_adap.algo = &flexcop_algo;
+	fc->fc_i2c_adap[0].i2c_adap.algo_data =
+		fc->fc_i2c_adap[1].i2c_adap.algo_data =
+		fc->fc_i2c_adap[2].i2c_adap.algo_data = NULL;
+	fc->fc_i2c_adap[0].i2c_adap.dev.parent =
+		fc->fc_i2c_adap[1].i2c_adap.dev.parent =
+		fc->fc_i2c_adap[2].i2c_adap.dev.parent = fc->dev;
+
+	ret = i2c_add_adapter(&fc->fc_i2c_adap[0].i2c_adap);
+	if (ret < 0)
+		return ret;
+
+	ret = i2c_add_adapter(&fc->fc_i2c_adap[1].i2c_adap);
+	if (ret < 0)
+		goto adap_1_failed;
+
+	ret = i2c_add_adapter(&fc->fc_i2c_adap[2].i2c_adap);
+	if (ret < 0)
+		goto adap_2_failed;
+
+	fc->init_state |= FC_STATE_I2C_INIT;
+	return 0;
+
+adap_2_failed:
+	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;
+}
+
+void flexcop_i2c_exit(struct flexcop_device *fc)
+{
+	if (fc->init_state & FC_STATE_I2C_INIT) {
+		i2c_del_adapter(&fc->fc_i2c_adap[2].i2c_adap);
+		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/common/b2c2/flexcop-misc.c b/drivers/media/common/b2c2/flexcop-misc.c
new file mode 100644
index 0000000..f06f3a9
--- /dev/null
+++ b/drivers/media/common/b2c2/flexcop-misc.c
@@ -0,0 +1,86 @@
+/*
+ * 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"
+
+void flexcop_determine_revision(struct flexcop_device *fc)
+{
+	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("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");
+	else
+		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[] = {
+	"Unknown chip",
+	"FlexCopII",
+	"FlexCopIIb",
+	"FlexCopIII",
+};
+
+static const char *flexcop_device_names[] = {
+	[FC_UNK]	= "Unknown device",
+	[FC_CABLE]	= "Cable2PC/CableStar 2 DVB-C",
+	[FC_AIR_DVBT]	= "Air2PC/AirStar 2 DVB-T",
+	[FC_AIR_ATSC1]	= "Air2PC/AirStar 2 ATSC 1st generation",
+	[FC_AIR_ATSC2]	= "Air2PC/AirStar 2 ATSC 2nd generation",
+	[FC_AIR_ATSC3]	= "Air2PC/AirStar 2 ATSC 3rd generation (HD5000)",
+	[FC_SKY_REV23]	= "Sky2PC/SkyStar 2 DVB-S rev 2.3 (old version)",
+	[FC_SKY_REV26]	= "Sky2PC/SkyStar 2 DVB-S rev 2.6",
+	[FC_SKY_REV27]	= "Sky2PC/SkyStar 2 DVB-S rev 2.7a/u",
+	[FC_SKY_REV28]	= "Sky2PC/SkyStar 2 DVB-S rev 2.8",
+};
+
+static const char *flexcop_bus_names[] = {
+	"USB",
+	"PCI",
+};
+
+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);
+}
+
+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);
+	}
+	deb_rdump("\n");
+}
+EXPORT_SYMBOL(flexcop_dump_reg);
diff --git a/drivers/media/common/b2c2/flexcop-reg.h b/drivers/media/common/b2c2/flexcop-reg.h
new file mode 100644
index 0000000..dc4528d
--- /dev/null
+++ b/drivers/media/common/b2c2/flexcop-reg.h
@@ -0,0 +1,166 @@
+/*
+ * 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
+ */
+#ifndef __FLEXCOP_REG_H__
+#define __FLEXCOP_REG_H__
+
+typedef enum {
+	FLEXCOP_UNK = 0,
+	FLEXCOP_II,
+	FLEXCOP_IIB,
+	FLEXCOP_III,
+} flexcop_revision_t;
+
+typedef enum {
+	FC_UNK = 0,
+	FC_CABLE,
+	FC_AIR_DVBT,
+	FC_AIR_ATSC1,
+	FC_AIR_ATSC2,
+	FC_AIR_ATSC3,
+	FC_SKY_REV23,
+	FC_SKY_REV26,
+	FC_SKY_REV27,
+	FC_SKY_REV28,
+} flexcop_device_type_t;
+
+typedef enum {
+	FC_USB = 0,
+	FC_PCI,
+} flexcop_bus_t;
+
+/* FlexCop IBI Registers */
+#if defined(__LITTLE_ENDIAN)
+#include "flexcop_ibi_value_le.h"
+#else
+#if defined(__BIG_ENDIAN)
+#include "flexcop_ibi_value_be.h"
+#else
+#error no endian defined
+#endif
+#endif
+
+#define fc_data_Tag_ID_DVB  0x3e
+#define fc_data_Tag_ID_ATSC 0x3f
+#define fc_data_Tag_ID_IDSB 0x8b
+
+#define fc_key_code_default 0x1
+#define fc_key_code_even    0x2
+#define fc_key_code_odd     0x3
+
+extern flexcop_ibi_value ibi_zero;
+
+typedef enum {
+	FC_I2C_PORT_DEMOD  = 1,
+	FC_I2C_PORT_EEPROM = 2,
+	FC_I2C_PORT_TUNER  = 3,
+} flexcop_i2c_port_t;
+
+typedef enum {
+	FC_WRITE = 0,
+	FC_READ  = 1,
+} flexcop_access_op_t;
+
+typedef enum {
+	FC_SRAM_DEST_NET   = 1,
+	FC_SRAM_DEST_CAI   = 2,
+	FC_SRAM_DEST_CAO   = 4,
+	FC_SRAM_DEST_MEDIA = 8
+} flexcop_sram_dest_t;
+
+typedef enum {
+	FC_SRAM_DEST_TARGET_WAN_USB = 0,
+	FC_SRAM_DEST_TARGET_DMA1    = 1,
+	FC_SRAM_DEST_TARGET_DMA2    = 2,
+	FC_SRAM_DEST_TARGET_FC3_CA  = 3
+} flexcop_sram_dest_target_t;
+
+typedef enum {
+	FC_SRAM_2_32KB  = 0, /*  64KB */
+	FC_SRAM_1_32KB  = 1, /*  32KB - default fow FCII */
+	FC_SRAM_1_128KB = 2, /* 128KB */
+	FC_SRAM_1_48KB  = 3, /*  48KB - default for FCIII */
+} flexcop_sram_type_t;
+
+typedef enum {
+	FC_WAN_SPEED_4MBITS  = 0,
+	FC_WAN_SPEED_8MBITS  = 1,
+	FC_WAN_SPEED_12MBITS = 2,
+	FC_WAN_SPEED_16MBITS = 3,
+} flexcop_wan_speed_t;
+
+typedef enum {
+	FC_DMA_1 = 1,
+	FC_DMA_2 = 2,
+} flexcop_dma_index_t;
+
+typedef enum {
+	FC_DMA_SUBADDR_0 = 1,
+	FC_DMA_SUBADDR_1 = 2,
+} flexcop_dma_addr_index_t;
+
+/* names of the particular registers */
+typedef enum {
+	dma1_000            = 0x000,
+	dma1_004            = 0x004,
+	dma1_008            = 0x008,
+	dma1_00c            = 0x00c,
+	dma2_010            = 0x010,
+	dma2_014            = 0x014,
+	dma2_018            = 0x018,
+	dma2_01c            = 0x01c,
+
+	tw_sm_c_100         = 0x100,
+	tw_sm_c_104         = 0x104,
+	tw_sm_c_108         = 0x108,
+	tw_sm_c_10c         = 0x10c,
+	tw_sm_c_110         = 0x110,
+
+	lnb_switch_freq_200 = 0x200,
+	misc_204            = 0x204,
+	ctrl_208            = 0x208,
+	irq_20c             = 0x20c,
+	sw_reset_210        = 0x210,
+	misc_214            = 0x214,
+	mbox_v8_to_host_218 = 0x218,
+	mbox_host_to_v8_21c = 0x21c,
+
+	pid_filter_300      = 0x300,
+	pid_filter_304      = 0x304,
+	pid_filter_308      = 0x308,
+	pid_filter_30c      = 0x30c,
+	index_reg_310       = 0x310,
+	pid_n_reg_314       = 0x314,
+	mac_low_reg_318     = 0x318,
+	mac_high_reg_31c    = 0x31c,
+
+	data_tag_400        = 0x400,
+	card_id_408         = 0x408,
+	card_id_40c         = 0x40c,
+	mac_address_418     = 0x418,
+	mac_address_41c     = 0x41c,
+
+	ci_600              = 0x600,
+	pi_604              = 0x604,
+	pi_608              = 0x608,
+	dvb_reg_60c         = 0x60c,
+
+	sram_ctrl_reg_700   = 0x700,
+	net_buf_reg_704     = 0x704,
+	cai_buf_reg_708     = 0x708,
+	cao_buf_reg_70c     = 0x70c,
+	media_buf_reg_710   = 0x710,
+	sram_dest_reg_714   = 0x714,
+	net_buf_reg_718     = 0x718,
+	wan_ctrl_reg_71c    = 0x71c,
+} flexcop_ibi_register;
+
+#define flexcop_set_ibi_value(reg,attr,val) { \
+	flexcop_ibi_value v = fc->read_ibi_reg(fc,reg); \
+	v.reg.attr = val; \
+	fc->write_ibi_reg(fc,reg,v); \
+}
+
+#endif
diff --git a/drivers/media/common/b2c2/flexcop-sram.c b/drivers/media/common/b2c2/flexcop-sram.c
new file mode 100644
index 0000000..f2199e4
--- /dev/null
+++ b/drivers/media/common/b2c2/flexcop-sram.c
@@ -0,0 +1,363 @@
+/*
+ * 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)
+{
+	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;
+	}
+	return 0;
+}
+
+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);
+
+	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);
+
+	if (dest & FC_SRAM_DEST_NET)
+		v.sram_dest_reg_714.NET_Dest = target;
+	if (dest & FC_SRAM_DEST_CAI)
+		v.sram_dest_reg_714.CAI_Dest = target;
+	if (dest & FC_SRAM_DEST_CAO)
+		v.sram_dest_reg_714.CAO_Dest = target;
+	if (dest & FC_SRAM_DEST_MEDIA)
+		v.sram_dest_reg_714.MEDIA_Dest = target;
+
+	fc->write_ibi_reg(fc,sram_dest_reg_714,v);
+	udelay(1000); /* TODO delay really necessary */
+
+	return 0;
+}
+EXPORT_SYMBOL(flexcop_sram_set_dest);
+
+void flexcop_wan_set_speed(struct flexcop_device *fc, flexcop_wan_speed_t s)
+{
+	flexcop_set_ibi_value(wan_ctrl_reg_71c,wan_speed_sig,s);
+}
+EXPORT_SYMBOL(flexcop_wan_set_speed);
+
+void flexcop_sram_ctrl(struct flexcop_device *fc, int usb_wan, int sramdma, int maximumfill)
+{
+	flexcop_ibi_value v = fc->read_ibi_reg(fc,sram_dest_reg_714);
+	v.sram_dest_reg_714.ctrl_usb_wan = usb_wan;
+	v.sram_dest_reg_714.ctrl_sramdma = sramdma;
+	v.sram_dest_reg_714.ctrl_maximumfill = maximumfill;
+	fc->write_ibi_reg(fc,sram_dest_reg_714,v);
+}
+EXPORT_SYMBOL(flexcop_sram_ctrl);
+
+#if 0
+static void flexcop_sram_write(struct adapter *adapter, u32 bank, u32 addr, u8 *buf, u32 len)
+{
+	int i, retries;
+	u32 command;
+
+	for (i = 0; i < len; i++) {
+		command = bank | addr | 0x04000000 | (*buf << 0x10);
+
+		retries = 2;
+
+		while (((read_reg_dw(adapter, 0x700) & 0x80000000) != 0) && (retries > 0)) {
+			mdelay(1);
+			retries--;
+		};
+
+		if (retries == 0)
+			printk("%s: SRAM timeout\n", __func__);
+
+		write_reg_dw(adapter, 0x700, command);
+
+		buf++;
+		addr++;
+	}
+}
+
+static void flex_sram_read(struct adapter *adapter, u32 bank, u32 addr, u8 *buf, u32 len)
+{
+	int i, retries;
+	u32 command, value;
+
+	for (i = 0; i < len; i++) {
+		command = bank | addr | 0x04008000;
+
+		retries = 10000;
+
+		while (((read_reg_dw(adapter, 0x700) & 0x80000000) != 0) && (retries > 0)) {
+			mdelay(1);
+			retries--;
+		};
+
+		if (retries == 0)
+			printk("%s: SRAM timeout\n", __func__);
+
+		write_reg_dw(adapter, 0x700, command);
+
+		retries = 10000;
+
+		while (((read_reg_dw(adapter, 0x700) & 0x80000000) != 0) && (retries > 0)) {
+			mdelay(1);
+			retries--;
+		};
+
+		if (retries == 0)
+			printk("%s: SRAM timeout\n", __func__);
+
+		value = read_reg_dw(adapter, 0x700) >> 0x10;
+
+		*buf = (value & 0xff);
+
+		addr++;
+		buf++;
+	}
+}
+
+static void sram_write_chunk(struct adapter *adapter, u32 addr, u8 *buf, u16 len)
+{
+	u32 bank;
+
+	bank = 0;
+
+	if (adapter->dw_sram_type == 0x20000) {
+		bank = (addr & 0x18000) << 0x0d;
+	}
+
+	if (adapter->dw_sram_type == 0x00000) {
+		if ((addr >> 0x0f) == 0)
+			bank = 0x20000000;
+		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) {
+		bank = (addr & 0x18000) << 0x0d;
+	}
+
+	if (adapter->dw_sram_type == 0x00000) {
+		if ((addr >> 0x0f) == 0)
+			bank = 0x20000000;
+		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 */
+		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;
+	}
+}
+
+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 */
+		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;
+	}
+}
+
+static void sram_set_size(struct adapter *adapter, u32 mask)
+{
+	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);
+	}
+}
+
+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);
+	sram_init(adapter);
+
+	tmp2 = 0xa5;
+	tmp1 = 0x4f;
+
+	sram_write(adapter, addr, &tmp2, 1);
+	sram_write(adapter, addr + 4, &tmp1, 1);
+
+	tmp2 = 0;
+	mdelay(20);
+
+	sram_read(adapter, addr, &tmp2, 1);
+	sram_read(adapter, addr, &tmp2, 1);
+
+	dprintk("%s: wrote 0xa5, read 0x%2x\n", __func__, tmp2);
+
+	if (tmp2 != 0xa5)
+		return 0;
+
+	tmp2 = 0x5a;
+	tmp1 = 0xf4;
+
+	sram_write(adapter, addr, &tmp2, 1);
+	sram_write(adapter, addr + 4, &tmp1, 1);
+
+	tmp2 = 0;
+	mdelay(20);
+
+	sram_read(adapter, addr, &tmp2, 1);
+	sram_read(adapter, addr, &tmp2, 1);
+
+	dprintk("%s: wrote 0x5a, read 0x%2x\n", __func__, tmp2);
+
+	if (tmp2 != 0x5a)
+		return 0;
+	return 1;
+}
+
+static u32 sram_length(struct adapter *adapter)
+{
+	if (adapter->dw_sram_type == 0x10000)
+		return 32768; /* 32K */
+	if (adapter->dw_sram_type == 0x00000)
+		return 65536; /* 64K */
+	if (adapter->dw_sram_type == 0x20000)
+		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.
+
+   FlexCop works only with one bank at a time. The bank is selected
+   by bits 28-29 of the 0x700 register.
+
+   bank 0 covers addresses 0x00000-0x07fff
+   bank 1 covers addresses 0x08000-0x0ffff
+   bank 2 covers addresses 0x10000-0x17fff
+   bank 3 covers addresses 0x18000-0x1ffff */
+
+static int flexcop_sram_detect(struct flexcop_device *fc)
+{
+	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 ???
+	tmp3--;
+	if (tmp3 != 0) {
+		sram_set_size(adapter, 0x10000);
+		sram_init(adapter);
+		write_reg_dw(adapter, 0x208, tmp);
+		dprintk("%s: sram size = 32K\n", __func__);
+		return 32;
+	}
+
+	if (sram_test_location(adapter, 0x20000, 0x18000) != 0) {
+		sram_set_size(adapter, 0x20000);
+		sram_init(adapter);
+		write_reg_dw(adapter, 0x208, tmp);
+		dprintk("%s: sram size = 128K\n", __func__);
+		return 128;
+	}
+
+	if (sram_test_location(adapter, 0x00000, 0x10000) != 0) {
+		sram_set_size(adapter, 0x00000);
+		sram_init(adapter);
+		write_reg_dw(adapter, 0x208, tmp);
+		dprintk("%s: sram size = 64K\n", __func__);
+		return 64;
+	}
+
+	if (sram_test_location(adapter, 0x10000, 0x00000) != 0) {
+		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;
+}
+
+static void sll_detect_sram_size(struct adapter *adapter)
+{
+	sram_detect_for_flex2(adapter);
+}
+
+#endif
diff --git a/drivers/media/common/b2c2/flexcop.c b/drivers/media/common/b2c2/flexcop.c
new file mode 100644
index 0000000..412c5da
--- /dev/null
+++ b/drivers/media/common/b2c2/flexcop.c
@@ -0,0 +1,325 @@
+/*
+ * 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)
+ *
+ * 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)
+ *   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
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public 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 "flexcop.h"
+
+#define DRIVER_NAME "B2C2 FlexcopII/II(b)/III digital TV receiver chip"
+#define DRIVER_AUTHOR "Patrick Boettcher <patrick.boettcher@desy.de"
+
+#ifdef CONFIG_DVB_B2C2_FLEXCOP_DEBUG
+#define DEBSTATUS ""
+#else
+#define DEBSTATUS " (debugging is not enabled)"
+#endif
+
+int b2c2_flexcop_debug;
+EXPORT_SYMBOL_GPL(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);
+#undef DEBSTATUS
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+/* global zero for ibi values */
+flexcop_ibi_value ibi_zero;
+
+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);
+}
+
+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);
+}
+
+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);
+	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.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;
+
+	ret = dvb_dmx_init(&fc->demux);
+	if (ret < 0) {
+		err("dvb_dmx failed: error %d", ret);
+		goto err_dmx;
+	}
+
+	fc->hw_frontend.source = DMX_FRONTEND_0;
+
+	fc->dmxdev.filternum = fc->demux.feednum;
+	fc->dmxdev.demux = &fc->demux.dmx;
+	fc->dmxdev.capabilities = 0;
+	ret = dvb_dmxdev_init(&fc->dmxdev, &fc->dvb_adapter);
+	if (ret < 0) {
+		err("dvb_dmxdev_init failed: error %d", ret);
+		goto err_dmx_dev;
+	}
+
+	ret = fc->demux.dmx.add_frontend(&fc->demux.dmx, &fc->hw_frontend);
+	if (ret < 0) {
+		err("adding hw_frontend to dmx failed: error %d", ret);
+		goto err_dmx_add_hw_frontend;
+	}
+
+	fc->mem_frontend.source = DMX_MEMORY_FE;
+	ret = fc->demux.dmx.add_frontend(&fc->demux.dmx, &fc->mem_frontend);
+	if (ret < 0) {
+		err("adding mem_frontend to dmx failed: error %d", ret);
+		goto err_dmx_add_mem_frontend;
+	}
+
+	ret = fc->demux.dmx.connect_frontend(&fc->demux.dmx, &fc->hw_frontend);
+	if (ret < 0) {
+		err("connect frontend failed: error %d", ret);
+		goto err_connect_frontend;
+	}
+
+	ret = dvb_net_init(&fc->dvb_adapter, &fc->dvbnet, &fc->demux.dmx);
+	if (ret < 0) {
+		err("dvb_net_init failed: error %d", ret);
+		goto err_net;
+	}
+
+	fc->init_state |= FC_STATE_DVB_INIT;
+	return 0;
+
+err_net:
+	fc->demux.dmx.disconnect_frontend(&fc->demux.dmx);
+err_connect_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);
+err_dmx_add_hw_frontend:
+	dvb_dmxdev_release(&fc->dmxdev);
+err_dmx_dev:
+	dvb_dmx_release(&fc->demux);
+err_dmx:
+	dvb_unregister_adapter(&fc->dvb_adapter);
+	return ret;
+}
+
+static void flexcop_dvb_exit(struct flexcop_device *fc)
+{
+	if (fc->init_state & FC_STATE_DVB_INIT) {
+		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);
+		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;
+}
+
+/* these methods are necessary to achieve the long-term-goal of hiding the
+ * struct flexcop_device from the bus-parts */
+void flexcop_pass_dmx_data(struct flexcop_device *fc, u8 *buf, u32 len)
+{
+	dvb_dmx_swfilter(&fc->demux, buf, len);
+}
+EXPORT_SYMBOL(flexcop_pass_dmx_data);
+
+void flexcop_pass_dmx_packets(struct flexcop_device *fc, u8 *buf, u32 no)
+{
+	dvb_dmx_swfilter_packets(&fc->demux, buf, no);
+}
+EXPORT_SYMBOL(flexcop_pass_dmx_packets);
+
+static void flexcop_reset(struct flexcop_device *fc)
+{
+	flexcop_ibi_value v210, v204;
+
+	/* reset the flexcop itself */
+	fc->write_ibi_reg(fc,ctrl_208,ibi_zero);
+
+	v210.raw = 0;
+	v210.sw_reset_210.reset_block_000 = 1;
+	v210.sw_reset_210.reset_block_100 = 1;
+	v210.sw_reset_210.reset_block_200 = 1;
+	v210.sw_reset_210.reset_block_300 = 1;
+	v210.sw_reset_210.reset_block_400 = 1;
+	v210.sw_reset_210.reset_block_500 = 1;
+	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 */
+
+	v204 = fc->read_ibi_reg(fc,misc_204);
+	v204.misc_204.Per_reset_sig = 0;
+	fc->write_ibi_reg(fc,misc_204,v204);
+	msleep(1);
+	v204.misc_204.Per_reset_sig = 1;
+	fc->write_ibi_reg(fc,misc_204,v204);
+}
+
+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);
+
+	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);
+	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);
+	if (!fc) {
+		err("no memory");
+		return NULL;
+	}
+
+	bus = kzalloc(bus_specific_len, GFP_KERNEL);
+	if (!bus) {
+		err("no memory");
+		kfree(fc);
+		return NULL;
+	}
+
+	fc->bus_specific = bus;
+
+	return fc;
+}
+EXPORT_SYMBOL(flexcop_device_kmalloc);
+
+void flexcop_device_kfree(struct flexcop_device *fc)
+{
+	kfree(fc->bus_specific);
+	kfree(fc);
+}
+EXPORT_SYMBOL(flexcop_device_kfree);
+
+int flexcop_device_initialize(struct flexcop_device *fc)
+{
+	int ret;
+	ibi_zero.raw = 0;
+
+	flexcop_reset(fc);
+	flexcop_determine_revision(fc);
+	flexcop_sram_init(fc);
+	flexcop_hw_filter_init(fc);
+	flexcop_smc_ctrl(fc, 0);
+
+	ret = flexcop_dvb_init(fc);
+	if (ret)
+		goto error;
+
+	/* i2c has to be done before doing EEProm stuff -
+	 * because the EEProm is accessed via i2c */
+	ret = flexcop_i2c_init(fc);
+	if (ret)
+		goto error;
+
+	/* do the MAC address reading after initializing the dvb_adapter */
+	if (fc->get_mac_addr(fc, 0) == 0) {
+		u8 *b = fc->dvb_adapter.proposed_mac;
+		info("MAC address = %pM", b);
+		flexcop_set_mac_filter(fc,b);
+		flexcop_mac_filter_ctrl(fc,1);
+	} else
+		warn("reading of MAC address failed.\n");
+
+	ret = flexcop_frontend_init(fc);
+	if (ret)
+		goto error;
+
+	flexcop_device_name(fc,"initialization of","complete");
+	return 0;
+
+error:
+	flexcop_device_exit(fc);
+	return ret;
+}
+EXPORT_SYMBOL(flexcop_device_initialize);
+
+void flexcop_device_exit(struct flexcop_device *fc)
+{
+	flexcop_frontend_exit(fc);
+	flexcop_i2c_exit(fc);
+	flexcop_dvb_exit(fc);
+}
+EXPORT_SYMBOL(flexcop_device_exit);
+
+static int flexcop_module_init(void)
+{
+	info(DRIVER_NAME " loaded successfully");
+	return 0;
+}
+
+static void flexcop_module_cleanup(void)
+{
+	info(DRIVER_NAME " unloaded successfully");
+}
+
+module_init(flexcop_module_init);
+module_exit(flexcop_module_cleanup);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_NAME);
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/common/b2c2/flexcop.h b/drivers/media/common/b2c2/flexcop.h
new file mode 100644
index 0000000..897b10c
--- /dev/null
+++ b/drivers/media/common/b2c2/flexcop.h
@@ -0,0 +1,29 @@
+/*
+ * 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___
+
+#define FC_LOG_PREFIX "b2c2-flexcop"
+#include "flexcop-common.h"
+
+extern int b2c2_flexcop_debug;
+
+/* debug */
+#ifdef CONFIG_DVB_B2C2_FLEXCOP_DEBUG
+#define dprintk(level,args...) \
+	do { if ((b2c2_flexcop_debug & level)) printk(args); } while (0)
+#else
+#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)
+
+#endif
diff --git a/drivers/media/common/b2c2/flexcop_ibi_value_be.h b/drivers/media/common/b2c2/flexcop_ibi_value_be.h
new file mode 100644
index 0000000..8f64bdb
--- /dev/null
+++ b/drivers/media/common/b2c2/flexcop_ibi_value_be.h
@@ -0,0 +1,455 @@
+/* Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
+ * register descriptions
+ * 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__
+
+typedef union {
+	u32 raw;
+
+	struct {
+		u32 dma_address0                   :30;
+		u32 dma_0No_update                 : 1;
+		u32 dma_0start                     : 1;
+	} dma_0x0;
+
+	struct {
+		u32 dma_addr_size                  :24;
+		u32 DMA_maxpackets                 : 8;
+	} dma_0x4_remap;
+
+	struct {
+		u32 dma_addr_size                  :24;
+		u32 unused                         : 1;
+		u32 dma1timer                      : 7;
+	} dma_0x4_read;
+
+	struct {
+		u32 dma_addr_size                  :24;
+		u32 dmatimer                       : 7;
+		u32 unused                         : 1;
+	} dma_0x4_write;
+
+	struct {
+		u32 dma_cur_addr                   :30;
+		u32 unused                         : 2;
+	} dma_0x8;
+
+	struct {
+		u32 dma_address1                   :30;
+		u32 remap_enable                   : 1;
+		u32 dma_1start                     : 1;
+	} dma_0xc;
+
+	struct {
+		u32 st_done                        : 1;
+		u32 no_base_addr_ack_error         : 1;
+		u32 twoWS_port_reg                 : 2;
+		u32 total_bytes                    : 2;
+		u32 twoWS_rw                       : 1;
+		u32 working_start                  : 1;
+		u32 data1_reg                      : 8;
+		u32 baseaddr                       : 8;
+		u32 reserved1                      : 1;
+		u32 chipaddr                       : 7;
+	} tw_sm_c_100;
+
+	struct {
+		u32 unused                         : 6;
+		u32 force_stop                     : 1;
+		u32 exlicit_stops                  : 1;
+		u32 data4_reg                      : 8;
+		u32 data3_reg                      : 8;
+		u32 data2_reg                      : 8;
+	} tw_sm_c_104;
+
+	struct {
+		u32 reserved2                      :19;
+		u32 tlo1                           : 5;
+		u32 reserved1                      : 2;
+		u32 thi1                           : 6;
+	} tw_sm_c_108;
+
+	struct {
+		u32 reserved2                      :19;
+		u32 tlo1                           : 5;
+		u32 reserved1                      : 2;
+		u32 thi1                           : 6;
+	} tw_sm_c_10c;
+
+	struct {
+		u32 reserved2                      :19;
+		u32 tlo1                           : 5;
+		u32 reserved1                      : 2;
+		u32 thi1                           : 6;
+	} tw_sm_c_110;
+
+	struct {
+		u32 LNB_CTLPrescaler_sig           : 2;
+		u32 LNB_CTLLowCount_sig            :15;
+		u32 LNB_CTLHighCount_sig           :15;
+	} lnb_switch_freq_200;
+
+	struct {
+		u32 Rev_N_sig_reserved2            : 1;
+		u32 Rev_N_sig_caps                 : 1;
+		u32 Rev_N_sig_reserved1            : 2;
+		u32 Rev_N_sig_revision_hi          : 4;
+		u32 reserved                       :20;
+		u32 Per_reset_sig                  : 1;
+		u32 LNB_L_H_sig                    : 1;
+		u32 ACPI3_sig                      : 1;
+		u32 ACPI1_sig                      : 1;
+	} misc_204;
+
+	struct {
+		u32 unused                         : 9;
+		u32 Mailbox_from_V8_Enable_sig     : 1;
+		u32 DMA2_Size_IRQ_Enable_sig       : 1;
+		u32 DMA1_Size_IRQ_Enable_sig       : 1;
+		u32 DMA2_Timer_Enable_sig          : 1;
+		u32 DMA2_IRQ_Enable_sig            : 1;
+		u32 DMA1_Timer_Enable_sig          : 1;
+		u32 DMA1_IRQ_Enable_sig            : 1;
+		u32 Rcv_Data_sig                   : 1;
+		u32 MAC_filter_Mode_sig            : 1;
+		u32 Multi2_Enable_sig              : 1;
+		u32 Per_CA_Enable_sig              : 1;
+		u32 SMC_Enable_sig                 : 1;
+		u32 CA_Enable_sig                  : 1;
+		u32 WAN_CA_Enable_sig              : 1;
+		u32 WAN_Enable_sig                 : 1;
+		u32 Mask_filter_sig                : 1;
+		u32 Null_filter_sig                : 1;
+		u32 ECM_filter_sig                 : 1;
+		u32 EMM_filter_sig                 : 1;
+		u32 PMT_filter_sig                 : 1;
+		u32 PCR_filter_sig                 : 1;
+		u32 Stream2_filter_sig             : 1;
+		u32 Stream1_filter_sig             : 1;
+	} ctrl_208;
+
+	struct {
+		u32 reserved                       :21;
+		u32 Transport_Error                : 1;
+		u32 LLC_SNAP_FLAG_set              : 1;
+		u32 Continuity_error_flag          : 1;
+		u32 Data_receiver_error            : 1;
+		u32 Mailbox_from_V8_Status_sig     : 1;
+		u32 DMA2_Size_IRQ_Status           : 1;
+		u32 DMA1_Size_IRQ_Status           : 1;
+		u32 DMA2_Timer_Status              : 1;
+		u32 DMA2_IRQ_Status                : 1;
+		u32 DMA1_Timer_Status              : 1;
+		u32 DMA1_IRQ_Status                : 1;
+	} irq_20c;
+
+	struct {
+		u32 Special_controls               :16;
+		u32 Block_reset_enable             : 8;
+		u32 reset_block_700                : 1;
+		u32 reset_block_600                : 1;
+		u32 reset_block_500                : 1;
+		u32 reset_block_400                : 1;
+		u32 reset_block_300                : 1;
+		u32 reset_block_200                : 1;
+		u32 reset_block_100                : 1;
+		u32 reset_block_000                : 1;
+	} sw_reset_210;
+
+	struct {
+		u32 unused2                        :20;
+		u32 polarity_PS_ERR_sig            : 1;
+		u32 polarity_PS_SYNC_sig           : 1;
+		u32 polarity_PS_VALID_sig          : 1;
+		u32 polarity_PS_CLK_sig            : 1;
+		u32 unused1                        : 3;
+		u32 s2p_sel_sig                    : 1;
+		u32 section_pkg_enable_sig         : 1;
+		u32 halt_V8_sig                    : 1;
+		u32 v2WS_oe_sig                    : 1;
+		u32 vuart_oe_sig                   : 1;
+	} misc_214;
+
+	struct {
+		u32 Mailbox_from_V8                :32;
+	} mbox_v8_to_host_218;
+
+	struct {
+		u32 sysramaccess_busmuster         : 1;
+		u32 sysramaccess_write             : 1;
+		u32 unused                         : 7;
+		u32 sysramaccess_addr              :15;
+		u32 sysramaccess_data              : 8;
+	} mbox_host_to_v8_21c;
+
+	struct {
+		u32 debug_fifo_problem             : 1;
+		u32 debug_flag_write_status00      : 1;
+		u32 Stream2_trans                  : 1;
+		u32 Stream2_PID                    :13;
+		u32 debug_flag_pid_saved           : 1;
+		u32 MAC_Multicast_filter           : 1;
+		u32 Stream1_trans                  : 1;
+		u32 Stream1_PID                    :13;
+	} pid_filter_300;
+
+	struct {
+		u32 reserved                       : 2;
+		u32 PMT_trans                      : 1;
+		u32 PMT_PID                        :13;
+		u32 debug_overrun2                 : 1;
+		u32 debug_overrun3                 : 1;
+		u32 PCR_trans                      : 1;
+		u32 PCR_PID                        :13;
+	} pid_filter_304;
+
+	struct {
+		u32 reserved                       : 2;
+		u32 ECM_trans                      : 1;
+		u32 ECM_PID                        :13;
+		u32 EMM_filter_6                   : 1;
+		u32 EMM_filter_4                   : 1;
+		u32 EMM_trans                      : 1;
+		u32 EMM_PID                        :13;
+	} pid_filter_308;
+
+	struct {
+		u32 unused2                        : 3;
+		u32 Group_mask                     :13;
+		u32 unused1                        : 2;
+		u32 Group_trans                    : 1;
+		u32 Group_PID                      :13;
+	} pid_filter_30c_ext_ind_0_7;
+
+	struct {
+		u32 unused                         :15;
+		u32 net_master_read                :17;
+	} pid_filter_30c_ext_ind_1;
+
+	struct {
+		u32 unused                         :15;
+		u32 net_master_write               :17;
+	} pid_filter_30c_ext_ind_2;
+
+	struct {
+		u32 unused                         :15;
+		u32 next_net_master_write          :17;
+	} pid_filter_30c_ext_ind_3;
+
+	struct {
+		u32 reserved2                      : 5;
+		u32 stack_read                     :10;
+		u32 reserved1                      : 6;
+		u32 state_write                    :10;
+		u32 unused1                        : 1;
+	} pid_filter_30c_ext_ind_4;
+
+	struct {
+		u32 unused                         :22;
+		u32 stack_cnt                      :10;
+	} pid_filter_30c_ext_ind_5;
+
+	struct {
+		u32 unused                         : 4;
+		u32 data_size_reg                  :12;
+		u32 write_status4                  : 2;
+		u32 write_status1                  : 2;
+		u32 pid_fsm_save_reg300            : 2;
+		u32 pid_fsm_save_reg4              : 2;
+		u32 pid_fsm_save_reg3              : 2;
+		u32 pid_fsm_save_reg2              : 2;
+		u32 pid_fsm_save_reg1              : 2;
+		u32 pid_fsm_save_reg0              : 2;
+	} pid_filter_30c_ext_ind_6;
+
+	struct {
+		u32 unused                         :22;
+		u32 pass_alltables                 : 1;
+		u32 AB_select                      : 1;
+		u32 extra_index_reg                : 3;
+		u32 index_reg                      : 5;
+	} index_reg_310;
+
+	struct {
+		u32 reserved                       :17;
+		u32 PID_enable_bit                 : 1;
+		u32 PID_trans                      : 1;
+		u32 PID                            :13;
+	} pid_n_reg_314;
+
+	struct {
+		u32 reserved                       : 6;
+		u32 HighAB_bit                     : 1;
+		u32 Enable_bit                     : 1;
+		u32 A6_byte                        : 8;
+		u32 A5_byte                        : 8;
+		u32 A4_byte                        : 8;
+	} mac_low_reg_318;
+
+	struct {
+		u32 reserved                       : 8;
+		u32 A3_byte                        : 8;
+		u32 A2_byte                        : 8;
+		u32 A1_byte                        : 8;
+	} mac_high_reg_31c;
+
+	struct {
+		u32 data_Tag_ID                    :16;
+		u32 reserved                       :16;
+	} data_tag_400;
+
+	struct {
+		u32 Card_IDbyte3                   : 8;
+		u32 Card_IDbyte4                   : 8;
+		u32 Card_IDbyte5                   : 8;
+		u32 Card_IDbyte6                   : 8;
+	} card_id_408;
+
+	struct {
+		u32 Card_IDbyte1                   : 8;
+		u32 Card_IDbyte2                   : 8;
+	} card_id_40c;
+
+	struct {
+		u32 MAC6                           : 8;
+		u32 MAC3                           : 8;
+		u32 MAC2                           : 8;
+		u32 MAC1                           : 8;
+	} mac_address_418;
+
+	struct {
+		u32 reserved                       :16;
+		u32 MAC8                           : 8;
+		u32 MAC7                           : 8;
+	} mac_address_41c;
+
+	struct {
+		u32 reserved                       :21;
+		u32 txbuffempty                    : 1;
+		u32 ReceiveByteFrameError          : 1;
+		u32 ReceiveDataReady               : 1;
+		u32 transmitter_data_byte          : 8;
+	} ci_600;
+
+	struct {
+		u32 pi_component_reg               : 3;
+		u32 pi_rw                          : 1;
+		u32 pi_ha                          :20;
+		u32 pi_d                           : 8;
+	} pi_604;
+
+	struct {
+		u32 pi_busy_n                      : 1;
+		u32 pi_wait_n                      : 1;
+		u32 pi_timeout_status              : 1;
+		u32 pi_CiMax_IRQ_n                 : 1;
+		u32 config_cclk                    : 1;
+		u32 config_cs_n                    : 1;
+		u32 config_wr_n                    : 1;
+		u32 config_Prog_n                  : 1;
+		u32 config_Init_stat               : 1;
+		u32 config_Done_stat               : 1;
+		u32 pcmcia_b_mod_pwr_n             : 1;
+		u32 pcmcia_a_mod_pwr_n             : 1;
+		u32 reserved                       : 3;
+		u32 Timer_addr                     : 5;
+		u32 unused                         : 1;
+		u32 timer_data                     : 7;
+		u32 Timer_Load_req                 : 1;
+		u32 Timer_Read_req                 : 1;
+		u32 oncecycle_read                 : 1;
+		u32 serialReset                    : 1;
+	} pi_608;
+
+	struct {
+		u32 reserved                       : 6;
+		u32 rw_flag                        : 1;
+		u32 dvb_en                         : 1;
+		u32 key_array_row                  : 5;
+		u32 key_array_col                  : 3;
+		u32 key_code                       : 2;
+		u32 key_enable                     : 1;
+		u32 PID                            :13;
+	} dvb_reg_60c;
+
+	struct {
+		u32 start_sram_ibi                 : 1;
+		u32 reserved2                      : 1;
+		u32 ce_pin_reg                     : 1;
+		u32 oe_pin_reg                     : 1;
+		u32 reserved1                      : 3;
+		u32 sc_xfer_bit                    : 1;
+		u32 sram_data                      : 8;
+		u32 sram_rw                        : 1;
+		u32 sram_addr                      :15;
+	} sram_ctrl_reg_700;
+
+	struct {
+		u32 net_addr_write                 :16;
+		u32 net_addr_read                  :16;
+	} net_buf_reg_704;
+
+	struct {
+		u32 cai_cnt                        : 4;
+		u32 reserved2                      : 6;
+		u32 cai_write                      :11;
+		u32 reserved1                      : 5;
+		u32 cai_read                       :11;
+	} cai_buf_reg_708;
+
+	struct {
+		u32 cao_cnt                        : 4;
+		u32 reserved2                      : 6;
+		u32 cap_write                      :11;
+		u32 reserved1                      : 5;
+		u32 cao_read                       :11;
+	} cao_buf_reg_70c;
+
+	struct {
+		u32 media_cnt                      : 4;
+		u32 reserved2                      : 6;
+		u32 media_write                    :11;
+		u32 reserved1                      : 5;
+		u32 media_read                     :11;
+	} media_buf_reg_710;
+
+	struct {
+		u32 reserved                       :17;
+		u32 ctrl_maximumfill               : 1;
+		u32 ctrl_sramdma                   : 1;
+		u32 ctrl_usb_wan                   : 1;
+		u32 cao_ovflow_error               : 1;
+		u32 cai_ovflow_error               : 1;
+		u32 media_ovflow_error             : 1;
+		u32 net_ovflow_error               : 1;
+		u32 MEDIA_Dest                     : 2;
+		u32 CAO_Dest                       : 2;
+		u32 CAI_Dest                       : 2;
+		u32 NET_Dest                       : 2;
+	} sram_dest_reg_714;
+
+	struct {
+		u32 reserved3                      :11;
+		u32 net_addr_write                 : 1;
+		u32 reserved2                      : 3;
+		u32 net_addr_read                  : 1;
+		u32 reserved1                      : 4;
+		u32 net_cnt                        :12;
+	} net_buf_reg_718;
+
+	struct {
+		u32 reserved3                      : 4;
+		u32 wan_pkt_frame                  : 4;
+		u32 reserved2                      : 4;
+		u32 sram_memmap                    : 2;
+		u32 sram_chip                      : 2;
+		u32 wan_wait_state                 : 8;
+		u32 reserved1                      : 6;
+		u32 wan_speed_sig                  : 2;
+	} wan_ctrl_reg_71c;
+} flexcop_ibi_value;
+
+#endif
diff --git a/drivers/media/common/b2c2/flexcop_ibi_value_le.h b/drivers/media/common/b2c2/flexcop_ibi_value_le.h
new file mode 100644
index 0000000..c75830d
--- /dev/null
+++ b/drivers/media/common/b2c2/flexcop_ibi_value_le.h
@@ -0,0 +1,455 @@
+/* Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
+ * register descriptions
+ * 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__
+
+typedef union {
+	u32 raw;
+
+	struct {
+		u32 dma_0start                     : 1;
+		u32 dma_0No_update                 : 1;
+		u32 dma_address0                   :30;
+	} dma_0x0;
+
+	struct {
+		u32 DMA_maxpackets                 : 8;
+		u32 dma_addr_size                  :24;
+	} dma_0x4_remap;
+
+	struct {
+		u32 dma1timer                      : 7;
+		u32 unused                         : 1;
+		u32 dma_addr_size                  :24;
+	} dma_0x4_read;
+
+	struct {
+		u32 unused                         : 1;
+		u32 dmatimer                       : 7;
+		u32 dma_addr_size                  :24;
+	} dma_0x4_write;
+
+	struct {
+		u32 unused                         : 2;
+		u32 dma_cur_addr                   :30;
+	} dma_0x8;
+
+	struct {
+		u32 dma_1start                     : 1;
+		u32 remap_enable                   : 1;
+		u32 dma_address1                   :30;
+	} dma_0xc;
+
+	struct {
+		u32 chipaddr                       : 7;
+		u32 reserved1                      : 1;
+		u32 baseaddr                       : 8;
+		u32 data1_reg                      : 8;
+		u32 working_start                  : 1;
+		u32 twoWS_rw                       : 1;
+		u32 total_bytes                    : 2;
+		u32 twoWS_port_reg                 : 2;
+		u32 no_base_addr_ack_error         : 1;
+		u32 st_done                        : 1;
+	} tw_sm_c_100;
+
+	struct {
+		u32 data2_reg                      : 8;
+		u32 data3_reg                      : 8;
+		u32 data4_reg                      : 8;
+		u32 exlicit_stops                  : 1;
+		u32 force_stop                     : 1;
+		u32 unused                         : 6;
+	} tw_sm_c_104;
+
+	struct {
+		u32 thi1                           : 6;
+		u32 reserved1                      : 2;
+		u32 tlo1                           : 5;
+		u32 reserved2                      :19;
+	} tw_sm_c_108;
+
+	struct {
+		u32 thi1                           : 6;
+		u32 reserved1                      : 2;
+		u32 tlo1                           : 5;
+		u32 reserved2                      :19;
+	} tw_sm_c_10c;
+
+	struct {
+		u32 thi1                           : 6;
+		u32 reserved1                      : 2;
+		u32 tlo1                           : 5;
+		u32 reserved2                      :19;
+	} tw_sm_c_110;
+
+	struct {
+		u32 LNB_CTLHighCount_sig           :15;
+		u32 LNB_CTLLowCount_sig            :15;
+		u32 LNB_CTLPrescaler_sig           : 2;
+	} lnb_switch_freq_200;
+
+	struct {
+		u32 ACPI1_sig                      : 1;
+		u32 ACPI3_sig                      : 1;
+		u32 LNB_L_H_sig                    : 1;
+		u32 Per_reset_sig                  : 1;
+		u32 reserved                       :20;
+		u32 Rev_N_sig_revision_hi          : 4;
+		u32 Rev_N_sig_reserved1            : 2;
+		u32 Rev_N_sig_caps                 : 1;
+		u32 Rev_N_sig_reserved2            : 1;
+	} misc_204;
+
+	struct {
+		u32 Stream1_filter_sig             : 1;
+		u32 Stream2_filter_sig             : 1;
+		u32 PCR_filter_sig                 : 1;
+		u32 PMT_filter_sig                 : 1;
+		u32 EMM_filter_sig                 : 1;
+		u32 ECM_filter_sig                 : 1;
+		u32 Null_filter_sig                : 1;
+		u32 Mask_filter_sig                : 1;
+		u32 WAN_Enable_sig                 : 1;
+		u32 WAN_CA_Enable_sig              : 1;
+		u32 CA_Enable_sig                  : 1;
+		u32 SMC_Enable_sig                 : 1;
+		u32 Per_CA_Enable_sig              : 1;
+		u32 Multi2_Enable_sig              : 1;
+		u32 MAC_filter_Mode_sig            : 1;
+		u32 Rcv_Data_sig                   : 1;
+		u32 DMA1_IRQ_Enable_sig            : 1;
+		u32 DMA1_Timer_Enable_sig          : 1;
+		u32 DMA2_IRQ_Enable_sig            : 1;
+		u32 DMA2_Timer_Enable_sig          : 1;
+		u32 DMA1_Size_IRQ_Enable_sig       : 1;
+		u32 DMA2_Size_IRQ_Enable_sig       : 1;
+		u32 Mailbox_from_V8_Enable_sig     : 1;
+		u32 unused                         : 9;
+	} ctrl_208;
+
+	struct {
+		u32 DMA1_IRQ_Status                : 1;
+		u32 DMA1_Timer_Status              : 1;
+		u32 DMA2_IRQ_Status                : 1;
+		u32 DMA2_Timer_Status              : 1;
+		u32 DMA1_Size_IRQ_Status           : 1;
+		u32 DMA2_Size_IRQ_Status           : 1;
+		u32 Mailbox_from_V8_Status_sig     : 1;
+		u32 Data_receiver_error            : 1;
+		u32 Continuity_error_flag          : 1;
+		u32 LLC_SNAP_FLAG_set              : 1;
+		u32 Transport_Error                : 1;
+		u32 reserved                       :21;
+	} irq_20c;
+
+	struct {
+		u32 reset_block_000                : 1;
+		u32 reset_block_100                : 1;
+		u32 reset_block_200                : 1;
+		u32 reset_block_300                : 1;
+		u32 reset_block_400                : 1;
+		u32 reset_block_500                : 1;
+		u32 reset_block_600                : 1;
+		u32 reset_block_700                : 1;
+		u32 Block_reset_enable             : 8;
+		u32 Special_controls               :16;
+	} sw_reset_210;
+
+	struct {
+		u32 vuart_oe_sig                   : 1;
+		u32 v2WS_oe_sig                    : 1;
+		u32 halt_V8_sig                    : 1;
+		u32 section_pkg_enable_sig         : 1;
+		u32 s2p_sel_sig                    : 1;
+		u32 unused1                        : 3;
+		u32 polarity_PS_CLK_sig            : 1;
+		u32 polarity_PS_VALID_sig          : 1;
+		u32 polarity_PS_SYNC_sig           : 1;
+		u32 polarity_PS_ERR_sig            : 1;
+		u32 unused2                        :20;
+	} misc_214;
+
+	struct {
+		u32 Mailbox_from_V8                :32;
+	} mbox_v8_to_host_218;
+
+	struct {
+		u32 sysramaccess_data              : 8;
+		u32 sysramaccess_addr              :15;
+		u32 unused                         : 7;
+		u32 sysramaccess_write             : 1;
+		u32 sysramaccess_busmuster         : 1;
+	} mbox_host_to_v8_21c;
+
+	struct {
+		u32 Stream1_PID                    :13;
+		u32 Stream1_trans                  : 1;
+		u32 MAC_Multicast_filter           : 1;
+		u32 debug_flag_pid_saved           : 1;
+		u32 Stream2_PID                    :13;
+		u32 Stream2_trans                  : 1;
+		u32 debug_flag_write_status00      : 1;
+		u32 debug_fifo_problem             : 1;
+	} pid_filter_300;
+
+	struct {
+		u32 PCR_PID                        :13;
+		u32 PCR_trans                      : 1;
+		u32 debug_overrun3                 : 1;
+		u32 debug_overrun2                 : 1;
+		u32 PMT_PID                        :13;
+		u32 PMT_trans                      : 1;
+		u32 reserved                       : 2;
+	} pid_filter_304;
+
+	struct {
+		u32 EMM_PID                        :13;
+		u32 EMM_trans                      : 1;
+		u32 EMM_filter_4                   : 1;
+		u32 EMM_filter_6                   : 1;
+		u32 ECM_PID                        :13;
+		u32 ECM_trans                      : 1;
+		u32 reserved                       : 2;
+	} pid_filter_308;
+
+	struct {
+		u32 Group_PID                      :13;
+		u32 Group_trans                    : 1;
+		u32 unused1                        : 2;
+		u32 Group_mask                     :13;
+		u32 unused2                        : 3;
+	} pid_filter_30c_ext_ind_0_7;
+
+	struct {
+		u32 net_master_read                :17;
+		u32 unused                         :15;
+	} pid_filter_30c_ext_ind_1;
+
+	struct {
+		u32 net_master_write               :17;
+		u32 unused                         :15;
+	} pid_filter_30c_ext_ind_2;
+
+	struct {
+		u32 next_net_master_write          :17;
+		u32 unused                         :15;
+	} pid_filter_30c_ext_ind_3;
+
+	struct {
+		u32 unused1                        : 1;
+		u32 state_write                    :10;
+		u32 reserved1                      : 6;
+		u32 stack_read                     :10;
+		u32 reserved2                      : 5;
+	} pid_filter_30c_ext_ind_4;
+
+	struct {
+		u32 stack_cnt                      :10;
+		u32 unused                         :22;
+	} pid_filter_30c_ext_ind_5;
+
+	struct {
+		u32 pid_fsm_save_reg0              : 2;
+		u32 pid_fsm_save_reg1              : 2;
+		u32 pid_fsm_save_reg2              : 2;
+		u32 pid_fsm_save_reg3              : 2;
+		u32 pid_fsm_save_reg4              : 2;
+		u32 pid_fsm_save_reg300            : 2;
+		u32 write_status1                  : 2;
+		u32 write_status4                  : 2;
+		u32 data_size_reg                  :12;
+		u32 unused                         : 4;
+	} pid_filter_30c_ext_ind_6;
+
+	struct {
+		u32 index_reg                      : 5;
+		u32 extra_index_reg                : 3;
+		u32 AB_select                      : 1;
+		u32 pass_alltables                 : 1;
+		u32 unused                         :22;
+	} index_reg_310;
+
+	struct {
+		u32 PID                            :13;
+		u32 PID_trans                      : 1;
+		u32 PID_enable_bit                 : 1;
+		u32 reserved                       :17;
+	} pid_n_reg_314;
+
+	struct {
+		u32 A4_byte                        : 8;
+		u32 A5_byte                        : 8;
+		u32 A6_byte                        : 8;
+		u32 Enable_bit                     : 1;
+		u32 HighAB_bit                     : 1;
+		u32 reserved                       : 6;
+	} mac_low_reg_318;
+
+	struct {
+		u32 A1_byte                        : 8;
+		u32 A2_byte                        : 8;
+		u32 A3_byte                        : 8;
+		u32 reserved                       : 8;
+	} mac_high_reg_31c;
+
+	struct {
+		u32 reserved                       :16;
+		u32 data_Tag_ID                    :16;
+	} data_tag_400;
+
+	struct {
+		u32 Card_IDbyte6                   : 8;
+		u32 Card_IDbyte5                   : 8;
+		u32 Card_IDbyte4                   : 8;
+		u32 Card_IDbyte3                   : 8;
+	} card_id_408;
+
+	struct {
+		u32 Card_IDbyte2                   : 8;
+		u32 Card_IDbyte1                   : 8;
+	} card_id_40c;
+
+	struct {
+		u32 MAC1                           : 8;
+		u32 MAC2                           : 8;
+		u32 MAC3                           : 8;
+		u32 MAC6                           : 8;
+	} mac_address_418;
+
+	struct {
+		u32 MAC7                           : 8;
+		u32 MAC8                           : 8;
+		u32 reserved                       :16;
+	} mac_address_41c;
+
+	struct {
+		u32 transmitter_data_byte          : 8;
+		u32 ReceiveDataReady               : 1;
+		u32 ReceiveByteFrameError          : 1;
+		u32 txbuffempty                    : 1;
+		u32 reserved                       :21;
+	} ci_600;
+
+	struct {
+		u32 pi_d                           : 8;
+		u32 pi_ha                          :20;
+		u32 pi_rw                          : 1;
+		u32 pi_component_reg               : 3;
+	} pi_604;
+
+	struct {
+		u32 serialReset                    : 1;
+		u32 oncecycle_read                 : 1;
+		u32 Timer_Read_req                 : 1;
+		u32 Timer_Load_req                 : 1;
+		u32 timer_data                     : 7;
+		u32 unused                         : 1;
+		u32 Timer_addr                     : 5;
+		u32 reserved                       : 3;
+		u32 pcmcia_a_mod_pwr_n             : 1;
+		u32 pcmcia_b_mod_pwr_n             : 1;
+		u32 config_Done_stat               : 1;
+		u32 config_Init_stat               : 1;
+		u32 config_Prog_n                  : 1;
+		u32 config_wr_n                    : 1;
+		u32 config_cs_n                    : 1;
+		u32 config_cclk                    : 1;
+		u32 pi_CiMax_IRQ_n                 : 1;
+		u32 pi_timeout_status              : 1;
+		u32 pi_wait_n                      : 1;
+		u32 pi_busy_n                      : 1;
+	} pi_608;
+
+	struct {
+		u32 PID                            :13;
+		u32 key_enable                     : 1;
+		u32 key_code                       : 2;
+		u32 key_array_col                  : 3;
+		u32 key_array_row                  : 5;
+		u32 dvb_en                         : 1;
+		u32 rw_flag                        : 1;
+		u32 reserved                       : 6;
+	} dvb_reg_60c;
+
+	struct {
+		u32 sram_addr                      :15;
+		u32 sram_rw                        : 1;
+		u32 sram_data                      : 8;
+		u32 sc_xfer_bit                    : 1;
+		u32 reserved1                      : 3;
+		u32 oe_pin_reg                     : 1;
+		u32 ce_pin_reg                     : 1;
+		u32 reserved2                      : 1;
+		u32 start_sram_ibi                 : 1;
+	} sram_ctrl_reg_700;
+
+	struct {
+		u32 net_addr_read                  :16;
+		u32 net_addr_write                 :16;
+	} net_buf_reg_704;
+
+	struct {
+		u32 cai_read                       :11;
+		u32 reserved1                      : 5;
+		u32 cai_write                      :11;
+		u32 reserved2                      : 6;
+		u32 cai_cnt                        : 4;
+	} cai_buf_reg_708;
+
+	struct {
+		u32 cao_read                       :11;
+		u32 reserved1                      : 5;
+		u32 cap_write                      :11;
+		u32 reserved2                      : 6;
+		u32 cao_cnt                        : 4;
+	} cao_buf_reg_70c;
+
+	struct {
+		u32 media_read                     :11;
+		u32 reserved1                      : 5;
+		u32 media_write                    :11;
+		u32 reserved2                      : 6;
+		u32 media_cnt                      : 4;
+	} media_buf_reg_710;
+
+	struct {
+		u32 NET_Dest                       : 2;
+		u32 CAI_Dest                       : 2;
+		u32 CAO_Dest                       : 2;
+		u32 MEDIA_Dest                     : 2;
+		u32 net_ovflow_error               : 1;
+		u32 media_ovflow_error             : 1;
+		u32 cai_ovflow_error               : 1;
+		u32 cao_ovflow_error               : 1;
+		u32 ctrl_usb_wan                   : 1;
+		u32 ctrl_sramdma                   : 1;
+		u32 ctrl_maximumfill               : 1;
+		u32 reserved                       :17;
+	} sram_dest_reg_714;
+
+	struct {
+		u32 net_cnt                        :12;
+		u32 reserved1                      : 4;
+		u32 net_addr_read                  : 1;
+		u32 reserved2                      : 3;
+		u32 net_addr_write                 : 1;
+		u32 reserved3                      :11;
+	} net_buf_reg_718;
+
+	struct {
+		u32 wan_speed_sig                  : 2;
+		u32 reserved1                      : 6;
+		u32 wan_wait_state                 : 8;
+		u32 sram_chip                      : 2;
+		u32 sram_memmap                    : 2;
+		u32 reserved2                      : 4;
+		u32 wan_pkt_frame                  : 4;
+		u32 reserved3                      : 4;
+	} wan_ctrl_reg_71c;
+} flexcop_ibi_value;
+
+#endif
diff --git a/drivers/media/common/saa7146/Kconfig b/drivers/media/common/saa7146/Kconfig
new file mode 100644
index 0000000..769c6f8
--- /dev/null
+++ b/drivers/media/common/saa7146/Kconfig
@@ -0,0 +1,9 @@
+config VIDEO_SAA7146
+	tristate
+	depends on I2C && PCI
+
+config VIDEO_SAA7146_VV
+	tristate
+	depends on VIDEO_V4L2
+	select VIDEOBUF_DMA_SG
+	select VIDEO_SAA7146
diff --git a/drivers/media/common/saa7146/Makefile b/drivers/media/common/saa7146/Makefile
new file mode 100644
index 0000000..3219b00
--- /dev/null
+++ b/drivers/media/common/saa7146/Makefile
@@ -0,0 +1,5 @@
+saa7146-objs    := saa7146_i2c.o saa7146_core.o
+saa7146_vv-objs := saa7146_fops.o saa7146_video.o saa7146_hlp.o saa7146_vbi.o
+
+obj-$(CONFIG_VIDEO_SAA7146) += saa7146.o
+obj-$(CONFIG_VIDEO_SAA7146_VV) += saa7146_vv.o
diff --git a/drivers/media/common/saa7146/saa7146_core.c b/drivers/media/common/saa7146/saa7146_core.c
new file mode 100644
index 0000000..bb6ee51
--- /dev/null
+++ b/drivers/media/common/saa7146/saa7146_core.c
@@ -0,0 +1,592 @@
+/*
+    saa7146.o - driver for generic saa7146-based hardware
+
+    Copyright (C) 1998-2003 Michael Hunold <michael@mihu.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.
+*/
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <media/saa7146.h>
+#include <linux/module.h>
+
+static int saa7146_num;
+
+unsigned int saa7146_debug;
+
+module_param(saa7146_debug, uint, 0644);
+MODULE_PARM_DESC(saa7146_debug, "debug level (default: 0)");
+
+#if 0
+static void dump_registers(struct saa7146_dev* dev)
+{
+	int i = 0;
+
+	pr_info(" @ %li jiffies:\n", jiffies);
+	for (i = 0; i <= 0x148; i += 4)
+		pr_info("0x%03x: 0x%08x\n", i, saa7146_read(dev, i));
+}
+#endif
+
+/****************************************************************************
+ * gpio and debi helper functions
+ ****************************************************************************/
+
+void saa7146_setgpio(struct saa7146_dev *dev, int port, u32 data)
+{
+	u32 value = 0;
+
+	BUG_ON(port > 3);
+
+	value = saa7146_read(dev, GPIO_CTRL);
+	value &= ~(0xff << (8*port));
+	value |= (data << (8*port));
+	saa7146_write(dev, GPIO_CTRL, value);
+}
+
+/* This DEBI code is based on the saa7146 Stradis driver by Nathan Laredo */
+static inline int saa7146_wait_for_debi_done_sleep(struct saa7146_dev *dev,
+				unsigned long us1, unsigned long us2)
+{
+	unsigned long timeout;
+	int err;
+
+	/* wait for registers to be programmed */
+	timeout = jiffies + usecs_to_jiffies(us1);
+	while (1) {
+		err = time_after(jiffies, timeout);
+		if (saa7146_read(dev, MC2) & 2)
+			break;
+		if (err) {
+			pr_err("%s: %s timed out while waiting for registers getting programmed\n",
+			       dev->name, __func__);
+			return -ETIMEDOUT;
+		}
+		msleep(1);
+	}
+
+	/* wait for transfer to complete */
+	timeout = jiffies + usecs_to_jiffies(us2);
+	while (1) {
+		err = time_after(jiffies, timeout);
+		if (!(saa7146_read(dev, PSR) & SPCI_DEBI_S))
+			break;
+		saa7146_read(dev, MC2);
+		if (err) {
+			DEB_S("%s: %s timed out while waiting for transfer completion\n",
+			      dev->name, __func__);
+			return -ETIMEDOUT;
+		}
+		msleep(1);
+	}
+
+	return 0;
+}
+
+static inline int saa7146_wait_for_debi_done_busyloop(struct saa7146_dev *dev,
+				unsigned long us1, unsigned long us2)
+{
+	unsigned long loops;
+
+	/* wait for registers to be programmed */
+	loops = us1;
+	while (1) {
+		if (saa7146_read(dev, MC2) & 2)
+			break;
+		if (!loops--) {
+			pr_err("%s: %s timed out while waiting for registers getting programmed\n",
+			       dev->name, __func__);
+			return -ETIMEDOUT;
+		}
+		udelay(1);
+	}
+
+	/* wait for transfer to complete */
+	loops = us2 / 5;
+	while (1) {
+		if (!(saa7146_read(dev, PSR) & SPCI_DEBI_S))
+			break;
+		saa7146_read(dev, MC2);
+		if (!loops--) {
+			DEB_S("%s: %s timed out while waiting for transfer completion\n",
+			      dev->name, __func__);
+			return -ETIMEDOUT;
+		}
+		udelay(5);
+	}
+
+	return 0;
+}
+
+int saa7146_wait_for_debi_done(struct saa7146_dev *dev, int nobusyloop)
+{
+	if (nobusyloop)
+		return saa7146_wait_for_debi_done_sleep(dev, 50000, 250000);
+	else
+		return saa7146_wait_for_debi_done_busyloop(dev, 50000, 250000);
+}
+
+/****************************************************************************
+ * general helper functions
+ ****************************************************************************/
+
+/* this is videobuf_vmalloc_to_sg() from videobuf-dma-sg.c
+   make sure virt has been allocated with vmalloc_32(), otherwise the BUG()
+   may be triggered on highmem machines */
+static struct scatterlist* vmalloc_to_sg(unsigned char *virt, int nr_pages)
+{
+	struct scatterlist *sglist;
+	struct page *pg;
+	int i;
+
+	sglist = kcalloc(nr_pages, sizeof(struct scatterlist), GFP_KERNEL);
+	if (NULL == sglist)
+		return NULL;
+	sg_init_table(sglist, nr_pages);
+	for (i = 0; i < nr_pages; i++, virt += PAGE_SIZE) {
+		pg = vmalloc_to_page(virt);
+		if (NULL == pg)
+			goto err;
+		BUG_ON(PageHighMem(pg));
+		sg_set_page(&sglist[i], pg, PAGE_SIZE, 0);
+	}
+	return sglist;
+
+ err:
+	kfree(sglist);
+	return NULL;
+}
+
+/********************************************************************************/
+/* common page table functions */
+
+void *saa7146_vmalloc_build_pgtable(struct pci_dev *pci, long length, struct saa7146_pgtable *pt)
+{
+	int pages = (length+PAGE_SIZE-1)/PAGE_SIZE;
+	void *mem = vmalloc_32(length);
+	int slen = 0;
+
+	if (NULL == mem)
+		goto err_null;
+
+	if (!(pt->slist = vmalloc_to_sg(mem, pages)))
+		goto err_free_mem;
+
+	if (saa7146_pgtable_alloc(pci, pt))
+		goto err_free_slist;
+
+	pt->nents = pages;
+	slen = pci_map_sg(pci,pt->slist,pt->nents,PCI_DMA_FROMDEVICE);
+	if (0 == slen)
+		goto err_free_pgtable;
+
+	if (0 != saa7146_pgtable_build_single(pci, pt, pt->slist, slen))
+		goto err_unmap_sg;
+
+	return mem;
+
+err_unmap_sg:
+	pci_unmap_sg(pci, pt->slist, pt->nents, PCI_DMA_FROMDEVICE);
+err_free_pgtable:
+	saa7146_pgtable_free(pci, pt);
+err_free_slist:
+	kfree(pt->slist);
+	pt->slist = NULL;
+err_free_mem:
+	vfree(mem);
+err_null:
+	return NULL;
+}
+
+void saa7146_vfree_destroy_pgtable(struct pci_dev *pci, void *mem, struct saa7146_pgtable *pt)
+{
+	pci_unmap_sg(pci, pt->slist, pt->nents, PCI_DMA_FROMDEVICE);
+	saa7146_pgtable_free(pci, pt);
+	kfree(pt->slist);
+	pt->slist = NULL;
+	vfree(mem);
+}
+
+void saa7146_pgtable_free(struct pci_dev *pci, struct saa7146_pgtable *pt)
+{
+	if (NULL == pt->cpu)
+		return;
+	pci_free_consistent(pci, pt->size, pt->cpu, pt->dma);
+	pt->cpu = NULL;
+}
+
+int saa7146_pgtable_alloc(struct pci_dev *pci, struct saa7146_pgtable *pt)
+{
+	__le32       *cpu;
+	dma_addr_t   dma_addr = 0;
+
+	cpu = pci_alloc_consistent(pci, PAGE_SIZE, &dma_addr);
+	if (NULL == cpu) {
+		return -ENOMEM;
+	}
+	pt->size = PAGE_SIZE;
+	pt->cpu  = cpu;
+	pt->dma  = dma_addr;
+
+	return 0;
+}
+
+int saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *pt,
+	struct scatterlist *list, int sglen  )
+{
+	__le32 *ptr, fill;
+	int nr_pages = 0;
+	int i,p;
+
+	BUG_ON(0 == sglen);
+	BUG_ON(list->offset > PAGE_SIZE);
+
+	/* if we have a user buffer, the first page may not be
+	   aligned to a page boundary. */
+	pt->offset = list->offset;
+
+	ptr = pt->cpu;
+	for (i = 0; i < sglen; i++, list++) {
+/*
+		pr_debug("i:%d, adr:0x%08x, len:%d, offset:%d\n",
+			 i, sg_dma_address(list), sg_dma_len(list),
+			 list->offset);
+*/
+		for (p = 0; p * 4096 < list->length; p++, ptr++) {
+			*ptr = cpu_to_le32(sg_dma_address(list) + p * 4096);
+			nr_pages++;
+		}
+	}
+
+
+	/* safety; fill the page table up with the last valid page */
+	fill = *(ptr-1);
+	for(i=nr_pages;i<1024;i++) {
+		*ptr++ = fill;
+	}
+
+/*
+	ptr = pt->cpu;
+	pr_debug("offset: %d\n", pt->offset);
+	for(i=0;i<5;i++) {
+		pr_debug("ptr1 %d: 0x%08x\n", i, ptr[i]);
+	}
+*/
+	return 0;
+}
+
+/********************************************************************************/
+/* interrupt handler */
+static irqreturn_t interrupt_hw(int irq, void *dev_id)
+{
+	struct saa7146_dev *dev = dev_id;
+	u32 isr;
+	u32 ack_isr;
+
+	/* read out the interrupt status register */
+	ack_isr = isr = saa7146_read(dev, ISR);
+
+	/* is this our interrupt? */
+	if ( 0 == isr ) {
+		/* nope, some other device */
+		return IRQ_NONE;
+	}
+
+	if (dev->ext) {
+		if (dev->ext->irq_mask & isr) {
+			if (dev->ext->irq_func)
+				dev->ext->irq_func(dev, &isr);
+			isr &= ~dev->ext->irq_mask;
+		}
+	}
+	if (0 != (isr & (MASK_27))) {
+		DEB_INT("irq: RPS0 (0x%08x)\n", isr);
+		if (dev->vv_data && dev->vv_callback)
+			dev->vv_callback(dev,isr);
+		isr &= ~MASK_27;
+	}
+	if (0 != (isr & (MASK_28))) {
+		if (dev->vv_data && dev->vv_callback)
+			dev->vv_callback(dev,isr);
+		isr &= ~MASK_28;
+	}
+	if (0 != (isr & (MASK_16|MASK_17))) {
+		SAA7146_IER_DISABLE(dev, MASK_16|MASK_17);
+		/* only wake up if we expect something */
+		if (0 != dev->i2c_op) {
+			dev->i2c_op = 0;
+			wake_up(&dev->i2c_wq);
+		} else {
+			u32 psr = saa7146_read(dev, PSR);
+			u32 ssr = saa7146_read(dev, SSR);
+			pr_warn("%s: unexpected i2c irq: isr %08x psr %08x ssr %08x\n",
+				dev->name, isr, psr, ssr);
+		}
+		isr &= ~(MASK_16|MASK_17);
+	}
+	if( 0 != isr ) {
+		ERR("warning: interrupt enabled, but not handled properly.(0x%08x)\n",
+		    isr);
+		ERR("disabling interrupt source(s)!\n");
+		SAA7146_IER_DISABLE(dev,isr);
+	}
+	saa7146_write(dev, ISR, ack_isr);
+	return IRQ_HANDLED;
+}
+
+/*********************************************************************************/
+/* configuration-functions                                                       */
+
+static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent)
+{
+	struct saa7146_pci_extension_data *pci_ext = (struct saa7146_pci_extension_data *)ent->driver_data;
+	struct saa7146_extension *ext = pci_ext->ext;
+	struct saa7146_dev *dev;
+	int err = -ENOMEM;
+
+	/* clear out mem for sure */
+	dev = kzalloc(sizeof(struct saa7146_dev), GFP_KERNEL);
+	if (!dev) {
+		ERR("out of memory\n");
+		goto out;
+	}
+
+	DEB_EE("pci:%p\n", pci);
+
+	err = pci_enable_device(pci);
+	if (err < 0) {
+		ERR("pci_enable_device() failed\n");
+		goto err_free;
+	}
+
+	/* enable bus-mastering */
+	pci_set_master(pci);
+
+	dev->pci = pci;
+
+	/* get chip-revision; this is needed to enable bug-fixes */
+	dev->revision = pci->revision;
+
+	/* remap the memory from virtual to physical address */
+
+	err = pci_request_region(pci, 0, "saa7146");
+	if (err < 0)
+		goto err_disable;
+
+	dev->mem = ioremap(pci_resource_start(pci, 0),
+			   pci_resource_len(pci, 0));
+	if (!dev->mem) {
+		ERR("ioremap() failed\n");
+		err = -ENODEV;
+		goto err_release;
+	}
+
+	/* we don't do a master reset here anymore, it screws up
+	   some boards that don't have an i2c-eeprom for configuration
+	   values */
+/*
+	saa7146_write(dev, MC1, MASK_31);
+*/
+
+	/* disable all irqs */
+	saa7146_write(dev, IER, 0);
+
+	/* shut down all dma transfers and rps tasks */
+	saa7146_write(dev, MC1, 0x30ff0000);
+
+	/* clear out any rps-signals pending */
+	saa7146_write(dev, MC2, 0xf8000000);
+
+	/* request an interrupt for the saa7146 */
+	err = request_irq(pci->irq, interrupt_hw, IRQF_SHARED | IRQF_DISABLED,
+			  dev->name, dev);
+	if (err < 0) {
+		ERR("request_irq() failed\n");
+		goto err_unmap;
+	}
+
+	err = -ENOMEM;
+
+	/* get memory for various stuff */
+	dev->d_rps0.cpu_addr = pci_alloc_consistent(pci, SAA7146_RPS_MEM,
+						    &dev->d_rps0.dma_handle);
+	if (!dev->d_rps0.cpu_addr)
+		goto err_free_irq;
+	memset(dev->d_rps0.cpu_addr, 0x0, SAA7146_RPS_MEM);
+
+	dev->d_rps1.cpu_addr = pci_alloc_consistent(pci, SAA7146_RPS_MEM,
+						    &dev->d_rps1.dma_handle);
+	if (!dev->d_rps1.cpu_addr)
+		goto err_free_rps0;
+	memset(dev->d_rps1.cpu_addr, 0x0, SAA7146_RPS_MEM);
+
+	dev->d_i2c.cpu_addr = pci_alloc_consistent(pci, SAA7146_RPS_MEM,
+						   &dev->d_i2c.dma_handle);
+	if (!dev->d_i2c.cpu_addr)
+		goto err_free_rps1;
+	memset(dev->d_i2c.cpu_addr, 0x0, SAA7146_RPS_MEM);
+
+	/* the rest + print status message */
+
+	/* create a nice device name */
+	sprintf(dev->name, "saa7146 (%d)", saa7146_num);
+
+	pr_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;
+
+	mutex_init(&dev->v4l2_lock);
+	spin_lock_init(&dev->int_slock);
+	spin_lock_init(&dev->slock);
+
+	mutex_init(&dev->i2c_lock);
+
+	dev->module = THIS_MODULE;
+	init_waitqueue_head(&dev->i2c_wq);
+
+	/* set some sane pci arbitrition values */
+	saa7146_write(dev, PCI_BT_V1, 0x1c00101f);
+
+	/* TODO: use the status code of the callback */
+
+	err = -ENODEV;
+
+	if (ext->probe && ext->probe(dev)) {
+		DEB_D("ext->probe() failed for %p. skipping device.\n", dev);
+		goto err_free_i2c;
+	}
+
+	if (ext->attach(dev, pci_ext)) {
+		DEB_D("ext->attach() failed for %p. skipping device.\n", dev);
+		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);
+
+	saa7146_num++;
+
+	err = 0;
+out:
+	return err;
+
+err_free_i2c:
+	pci_free_consistent(pci, SAA7146_RPS_MEM, dev->d_i2c.cpu_addr,
+			    dev->d_i2c.dma_handle);
+err_free_rps1:
+	pci_free_consistent(pci, SAA7146_RPS_MEM, dev->d_rps1.cpu_addr,
+			    dev->d_rps1.dma_handle);
+err_free_rps0:
+	pci_free_consistent(pci, SAA7146_RPS_MEM, dev->d_rps0.cpu_addr,
+			    dev->d_rps0.dma_handle);
+err_free_irq:
+	free_irq(pci->irq, (void *)dev);
+err_unmap:
+	iounmap(dev->mem);
+err_release:
+	pci_release_region(pci, 0);
+err_disable:
+	pci_disable_device(pci);
+err_free:
+	kfree(dev);
+	goto out;
+}
+
+static void saa7146_remove_one(struct pci_dev *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;
+	} dev_map[] = {
+		{ dev->d_i2c.cpu_addr, dev->d_i2c.dma_handle },
+		{ dev->d_rps1.cpu_addr, dev->d_rps1.dma_handle },
+		{ dev->d_rps0.cpu_addr, dev->d_rps0.dma_handle },
+		{ NULL, 0 }
+	}, *p;
+
+	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);
+
+	/* disable all irqs, release irq-routine */
+	saa7146_write(dev, IER, 0);
+
+	free_irq(pdev->irq, dev);
+
+	for (p = dev_map; p->addr; p++)
+		pci_free_consistent(pdev, SAA7146_RPS_MEM, p->addr, p->dma);
+
+	iounmap(dev->mem);
+	pci_release_region(pdev, 0);
+	pci_disable_device(pdev);
+	kfree(dev);
+
+	saa7146_num--;
+}
+
+/*********************************************************************************/
+/* extension handling functions                                                  */
+
+int saa7146_register_extension(struct saa7146_extension* ext)
+{
+	DEB_EE("ext:%p\n", ext);
+
+	ext->driver.name = ext->name;
+	ext->driver.id_table = ext->pci_tbl;
+	ext->driver.probe = saa7146_init_one;
+	ext->driver.remove = saa7146_remove_one;
+
+	pr_info("register extension '%s'\n", ext->name);
+	return pci_register_driver(&ext->driver);
+}
+
+int saa7146_unregister_extension(struct saa7146_extension* ext)
+{
+	DEB_EE("ext:%p\n", ext);
+	pr_info("unregister extension '%s'\n", ext->name);
+	pci_unregister_driver(&ext->driver);
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(saa7146_register_extension);
+EXPORT_SYMBOL_GPL(saa7146_unregister_extension);
+
+/* misc functions used by extension modules */
+EXPORT_SYMBOL_GPL(saa7146_pgtable_alloc);
+EXPORT_SYMBOL_GPL(saa7146_pgtable_free);
+EXPORT_SYMBOL_GPL(saa7146_pgtable_build_single);
+EXPORT_SYMBOL_GPL(saa7146_vmalloc_build_pgtable);
+EXPORT_SYMBOL_GPL(saa7146_vfree_destroy_pgtable);
+EXPORT_SYMBOL_GPL(saa7146_wait_for_debi_done);
+
+EXPORT_SYMBOL_GPL(saa7146_setgpio);
+
+EXPORT_SYMBOL_GPL(saa7146_i2c_adapter_prepare);
+
+EXPORT_SYMBOL_GPL(saa7146_debug);
+
+MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
+MODULE_DESCRIPTION("driver for generic saa7146-based hardware");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/common/saa7146/saa7146_fops.c b/drivers/media/common/saa7146/saa7146_fops.c
new file mode 100644
index 0000000..b3890bd
--- /dev/null
+++ b/drivers/media/common/saa7146/saa7146_fops.c
@@ -0,0 +1,664 @@
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <media/saa7146_vv.h>
+#include <linux/module.h>
+
+/****************************************************************************/
+/* resource management functions, shamelessly stolen from saa7134 driver */
+
+int saa7146_res_get(struct saa7146_fh *fh, unsigned int bit)
+{
+	struct saa7146_dev *dev = fh->dev;
+	struct saa7146_vv *vv = dev->vv_data;
+
+	if (fh->resources & bit) {
+		DEB_D("already allocated! want: 0x%02x, cur:0x%02x\n",
+		      bit, vv->resources);
+		/* have it already allocated */
+		return 1;
+	}
+
+	/* is it free? */
+	if (vv->resources & bit) {
+		DEB_D("locked! vv->resources:0x%02x, we want:0x%02x\n",
+		      vv->resources, bit);
+		/* no, someone else uses it */
+		return 0;
+	}
+	/* it's free, grab it */
+	fh->resources |= bit;
+	vv->resources |= bit;
+	DEB_D("res: get 0x%02x, cur:0x%02x\n", bit, vv->resources);
+	return 1;
+}
+
+void saa7146_res_free(struct saa7146_fh *fh, unsigned int bits)
+{
+	struct saa7146_dev *dev = fh->dev;
+	struct saa7146_vv *vv = dev->vv_data;
+
+	BUG_ON((fh->resources & bits) != bits);
+
+	fh->resources &= ~bits;
+	vv->resources &= ~bits;
+	DEB_D("res: put 0x%02x, cur:0x%02x\n", bits, vv->resources);
+}
+
+
+/********************************************************************************/
+/* common dma functions */
+
+void saa7146_dma_free(struct saa7146_dev *dev,struct videobuf_queue *q,
+						struct saa7146_buf *buf)
+{
+	struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
+	DEB_EE("dev:%p, buf:%p\n", dev, buf);
+
+	BUG_ON(in_interrupt());
+
+	videobuf_waiton(q, &buf->vb, 0, 0);
+	videobuf_dma_unmap(q->dev, dma);
+	videobuf_dma_free(dma);
+	buf->vb.state = VIDEOBUF_NEEDS_INIT;
+}
+
+
+/********************************************************************************/
+/* common buffer functions */
+
+int saa7146_buffer_queue(struct saa7146_dev *dev,
+			 struct saa7146_dmaqueue *q,
+			 struct saa7146_buf *buf)
+{
+	assert_spin_locked(&dev->slock);
+	DEB_EE("dev:%p, dmaq:%p, buf:%p\n", dev, q, buf);
+
+	BUG_ON(!q);
+
+	if (NULL == q->curr) {
+		q->curr = buf;
+		DEB_D("immediately activating buffer %p\n", buf);
+		buf->activate(dev,buf,NULL);
+	} else {
+		list_add_tail(&buf->vb.queue,&q->queue);
+		buf->vb.state = VIDEOBUF_QUEUED;
+		DEB_D("adding buffer %p to queue. (active buffer present)\n",
+		      buf);
+	}
+	return 0;
+}
+
+void saa7146_buffer_finish(struct saa7146_dev *dev,
+			   struct saa7146_dmaqueue *q,
+			   int state)
+{
+	assert_spin_locked(&dev->slock);
+	DEB_EE("dev:%p, dmaq:%p, state:%d\n", dev, q, state);
+	DEB_EE("q->curr:%p\n", q->curr);
+
+	BUG_ON(!q->curr);
+
+	/* finish current buffer */
+	if (NULL == q->curr) {
+		DEB_D("aiii. no current buffer\n");
+		return;
+	}
+
+	q->curr->vb.state = state;
+	do_gettimeofday(&q->curr->vb.ts);
+	wake_up(&q->curr->vb.done);
+
+	q->curr = NULL;
+}
+
+void saa7146_buffer_next(struct saa7146_dev *dev,
+			 struct saa7146_dmaqueue *q, int vbi)
+{
+	struct saa7146_buf *buf,*next = NULL;
+
+	BUG_ON(!q);
+
+	DEB_INT("dev:%p, dmaq:%p, vbi:%d\n", dev, q, vbi);
+
+	assert_spin_locked(&dev->slock);
+	if (!list_empty(&q->queue)) {
+		/* activate next one from queue */
+		buf = list_entry(q->queue.next,struct saa7146_buf,vb.queue);
+		list_del(&buf->vb.queue);
+		if (!list_empty(&q->queue))
+			next = list_entry(q->queue.next,struct saa7146_buf, vb.queue);
+		q->curr = buf;
+		DEB_INT("next buffer: buf:%p, prev:%p, next:%p\n",
+			buf, q->queue.prev, q->queue.next);
+		buf->activate(dev,buf,next);
+	} else {
+		DEB_INT("no next buffer. stopping.\n");
+		if( 0 != vbi ) {
+			/* turn off video-dma3 */
+			saa7146_write(dev,MC1, MASK_20);
+		} else {
+			/* nothing to do -- just prevent next video-dma1 transfer
+			   by lowering the protection address */
+
+			// fixme: fix this for vflip != 0
+
+			saa7146_write(dev, PROT_ADDR1, 0);
+			saa7146_write(dev, MC2, (MASK_02|MASK_18));
+
+			/* write the address of the rps-program */
+			saa7146_write(dev, RPS_ADDR0, dev->d_rps0.dma_handle);
+			/* turn on rps */
+			saa7146_write(dev, MC1, (MASK_12 | MASK_28));
+
+/*
+			printk("vdma%d.base_even:     0x%08x\n", 1,saa7146_read(dev,BASE_EVEN1));
+			printk("vdma%d.base_odd:      0x%08x\n", 1,saa7146_read(dev,BASE_ODD1));
+			printk("vdma%d.prot_addr:     0x%08x\n", 1,saa7146_read(dev,PROT_ADDR1));
+			printk("vdma%d.base_page:     0x%08x\n", 1,saa7146_read(dev,BASE_PAGE1));
+			printk("vdma%d.pitch:         0x%08x\n", 1,saa7146_read(dev,PITCH1));
+			printk("vdma%d.num_line_byte: 0x%08x\n", 1,saa7146_read(dev,NUM_LINE_BYTE1));
+*/
+		}
+		del_timer(&q->timeout);
+	}
+}
+
+void saa7146_buffer_timeout(unsigned long data)
+{
+	struct saa7146_dmaqueue *q = (struct saa7146_dmaqueue*)data;
+	struct saa7146_dev *dev = q->dev;
+	unsigned long flags;
+
+	DEB_EE("dev:%p, dmaq:%p\n", dev, q);
+
+	spin_lock_irqsave(&dev->slock,flags);
+	if (q->curr) {
+		DEB_D("timeout on %p\n", q->curr);
+		saa7146_buffer_finish(dev,q,VIDEOBUF_ERROR);
+	}
+
+	/* we don't restart the transfer here like other drivers do. when
+	   a streaming capture is disabled, the timeout function will be
+	   called for the current buffer. if we activate the next buffer now,
+	   we mess up our capture logic. if a timeout occurs on another buffer,
+	   then something is seriously broken before, so no need to buffer the
+	   next capture IMHO... */
+/*
+	saa7146_buffer_next(dev,q);
+*/
+	spin_unlock_irqrestore(&dev->slock,flags);
+}
+
+/********************************************************************************/
+/* file operations */
+
+static int fops_open(struct file *file)
+{
+	struct video_device *vdev = video_devdata(file);
+	struct saa7146_dev *dev = video_drvdata(file);
+	struct saa7146_fh *fh = NULL;
+	int result = 0;
+
+	DEB_EE("file:%p, dev:%s\n", file, video_device_node_name(vdev));
+
+	if (mutex_lock_interruptible(vdev->lock))
+		return -ERESTARTSYS;
+
+	DEB_D("using: %p\n", dev);
+
+	/* check if an extension is registered */
+	if( NULL == dev->ext ) {
+		DEB_S("no extension registered for this device\n");
+		result = -ENODEV;
+		goto out;
+	}
+
+	/* allocate per open data */
+	fh = kzalloc(sizeof(*fh),GFP_KERNEL);
+	if (NULL == fh) {
+		DEB_S("cannot allocate memory for per open data\n");
+		result = -ENOMEM;
+		goto out;
+	}
+
+	v4l2_fh_init(&fh->fh, vdev);
+
+	file->private_data = &fh->fh;
+	fh->dev = dev;
+
+	if (vdev->vfl_type == VFL_TYPE_VBI) {
+		DEB_S("initializing vbi...\n");
+		if (dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE)
+			result = saa7146_vbi_uops.open(dev,file);
+		if (dev->ext_vv_data->vbi_fops.open)
+			dev->ext_vv_data->vbi_fops.open(file);
+	} else {
+		DEB_S("initializing video...\n");
+		result = saa7146_video_uops.open(dev,file);
+	}
+
+	if (0 != result) {
+		goto out;
+	}
+
+	if( 0 == try_module_get(dev->ext->module)) {
+		result = -EINVAL;
+		goto out;
+	}
+
+	result = 0;
+	v4l2_fh_add(&fh->fh);
+out:
+	if (fh && result != 0) {
+		kfree(fh);
+		file->private_data = NULL;
+	}
+	mutex_unlock(vdev->lock);
+	return result;
+}
+
+static int fops_release(struct file *file)
+{
+	struct video_device *vdev = video_devdata(file);
+	struct saa7146_fh  *fh  = file->private_data;
+	struct saa7146_dev *dev = fh->dev;
+
+	DEB_EE("file:%p\n", file);
+
+	if (mutex_lock_interruptible(vdev->lock))
+		return -ERESTARTSYS;
+
+	if (vdev->vfl_type == VFL_TYPE_VBI) {
+		if (dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE)
+			saa7146_vbi_uops.release(dev,file);
+		if (dev->ext_vv_data->vbi_fops.release)
+			dev->ext_vv_data->vbi_fops.release(file);
+	} else {
+		saa7146_video_uops.release(dev,file);
+	}
+
+	v4l2_fh_del(&fh->fh);
+	v4l2_fh_exit(&fh->fh);
+	module_put(dev->ext->module);
+	file->private_data = NULL;
+	kfree(fh);
+
+	mutex_unlock(vdev->lock);
+
+	return 0;
+}
+
+static int fops_mmap(struct file *file, struct vm_area_struct * vma)
+{
+	struct video_device *vdev = video_devdata(file);
+	struct saa7146_fh *fh = file->private_data;
+	struct videobuf_queue *q;
+	int res;
+
+	switch (vdev->vfl_type) {
+	case VFL_TYPE_GRABBER: {
+		DEB_EE("V4L2_BUF_TYPE_VIDEO_CAPTURE: file:%p, vma:%p\n",
+		       file, vma);
+		q = &fh->video_q;
+		break;
+		}
+	case VFL_TYPE_VBI: {
+		DEB_EE("V4L2_BUF_TYPE_VBI_CAPTURE: file:%p, vma:%p\n",
+		       file, vma);
+		if (fh->dev->ext_vv_data->capabilities & V4L2_CAP_SLICED_VBI_OUTPUT)
+			return -ENODEV;
+		q = &fh->vbi_q;
+		break;
+		}
+	default:
+		BUG();
+		return 0;
+	}
+
+	if (mutex_lock_interruptible(vdev->lock))
+		return -ERESTARTSYS;
+	res = videobuf_mmap_mapper(q, vma);
+	mutex_unlock(vdev->lock);
+	return res;
+}
+
+static unsigned int __fops_poll(struct file *file, struct poll_table_struct *wait)
+{
+	struct video_device *vdev = video_devdata(file);
+	struct saa7146_fh *fh = file->private_data;
+	struct videobuf_buffer *buf = NULL;
+	struct videobuf_queue *q;
+	unsigned int res = v4l2_ctrl_poll(file, wait);
+
+	DEB_EE("file:%p, poll:%p\n", file, wait);
+
+	if (vdev->vfl_type == VFL_TYPE_VBI) {
+		if (fh->dev->ext_vv_data->capabilities & V4L2_CAP_SLICED_VBI_OUTPUT)
+			return res | POLLOUT | POLLWRNORM;
+		if( 0 == fh->vbi_q.streaming )
+			return res | videobuf_poll_stream(file, &fh->vbi_q, wait);
+		q = &fh->vbi_q;
+	} else {
+		DEB_D("using video queue\n");
+		q = &fh->video_q;
+	}
+
+	if (!list_empty(&q->stream))
+		buf = list_entry(q->stream.next, struct videobuf_buffer, stream);
+
+	if (!buf) {
+		DEB_D("buf == NULL!\n");
+		return res | POLLERR;
+	}
+
+	poll_wait(file, &buf->done, wait);
+	if (buf->state == VIDEOBUF_DONE || buf->state == VIDEOBUF_ERROR) {
+		DEB_D("poll succeeded!\n");
+		return res | POLLIN | POLLRDNORM;
+	}
+
+	DEB_D("nothing to poll for, buf->state:%d\n", buf->state);
+	return res;
+}
+
+static unsigned int fops_poll(struct file *file, struct poll_table_struct *wait)
+{
+	struct video_device *vdev = video_devdata(file);
+	unsigned int res;
+
+	mutex_lock(vdev->lock);
+	res = __fops_poll(file, wait);
+	mutex_unlock(vdev->lock);
+	return res;
+}
+
+static ssize_t fops_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
+{
+	struct video_device *vdev = video_devdata(file);
+	struct saa7146_fh *fh = file->private_data;
+	int ret;
+
+	switch (vdev->vfl_type) {
+	case VFL_TYPE_GRABBER:
+/*
+		DEB_EE("V4L2_BUF_TYPE_VIDEO_CAPTURE: file:%p, data:%p, count:%lun",
+		       file, data, (unsigned long)count);
+*/
+		return saa7146_video_uops.read(file,data,count,ppos);
+	case VFL_TYPE_VBI:
+/*
+		DEB_EE("V4L2_BUF_TYPE_VBI_CAPTURE: file:%p, data:%p, count:%lu\n",
+		       file, data, (unsigned long)count);
+*/
+		if (fh->dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE) {
+			if (mutex_lock_interruptible(vdev->lock))
+				return -ERESTARTSYS;
+			ret = saa7146_vbi_uops.read(file, data, count, ppos);
+			mutex_unlock(vdev->lock);
+			return ret;
+		}
+		return -EINVAL;
+	default:
+		BUG();
+		return 0;
+	}
+}
+
+static ssize_t fops_write(struct file *file, const char __user *data, size_t count, loff_t *ppos)
+{
+	struct video_device *vdev = video_devdata(file);
+	struct saa7146_fh *fh = file->private_data;
+	int ret;
+
+	switch (vdev->vfl_type) {
+	case VFL_TYPE_GRABBER:
+		return -EINVAL;
+	case VFL_TYPE_VBI:
+		if (fh->dev->ext_vv_data->vbi_fops.write) {
+			if (mutex_lock_interruptible(vdev->lock))
+				return -ERESTARTSYS;
+			ret = fh->dev->ext_vv_data->vbi_fops.write(file, data, count, ppos);
+			mutex_unlock(vdev->lock);
+			return ret;
+		}
+		return -EINVAL;
+	default:
+		BUG();
+		return -EINVAL;
+	}
+}
+
+static const struct v4l2_file_operations video_fops =
+{
+	.owner		= THIS_MODULE,
+	.open		= fops_open,
+	.release	= fops_release,
+	.read		= fops_read,
+	.write		= fops_write,
+	.poll		= fops_poll,
+	.mmap		= fops_mmap,
+	.unlocked_ioctl	= video_ioctl2,
+};
+
+static void vv_callback(struct saa7146_dev *dev, unsigned long status)
+{
+	u32 isr = status;
+
+	DEB_INT("dev:%p, isr:0x%08x\n", dev, (u32)status);
+
+	if (0 != (isr & (MASK_27))) {
+		DEB_INT("irq: RPS0 (0x%08x)\n", isr);
+		saa7146_video_uops.irq_done(dev,isr);
+	}
+
+	if (0 != (isr & (MASK_28))) {
+		u32 mc2 = saa7146_read(dev, MC2);
+		if( 0 != (mc2 & MASK_15)) {
+			DEB_INT("irq: RPS1 vbi workaround (0x%08x)\n", isr);
+			wake_up(&dev->vv_data->vbi_wq);
+			saa7146_write(dev,MC2, MASK_31);
+			return;
+		}
+		DEB_INT("irq: RPS1 (0x%08x)\n", isr);
+		saa7146_vbi_uops.irq_done(dev,isr);
+	}
+}
+
+static const struct v4l2_ctrl_ops saa7146_ctrl_ops = {
+	.s_ctrl = saa7146_s_ctrl,
+};
+
+int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv)
+{
+	struct v4l2_ctrl_handler *hdl = &dev->ctrl_handler;
+	struct v4l2_pix_format *fmt;
+	struct v4l2_vbi_format *vbi;
+	struct saa7146_vv *vv;
+	int err;
+
+	err = v4l2_device_register(&dev->pci->dev, &dev->v4l2_dev);
+	if (err)
+		return err;
+
+	v4l2_ctrl_handler_init(hdl, 6);
+	v4l2_ctrl_new_std(hdl, &saa7146_ctrl_ops,
+		V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
+	v4l2_ctrl_new_std(hdl, &saa7146_ctrl_ops,
+		V4L2_CID_CONTRAST, 0, 127, 1, 64);
+	v4l2_ctrl_new_std(hdl, &saa7146_ctrl_ops,
+		V4L2_CID_SATURATION, 0, 127, 1, 64);
+	v4l2_ctrl_new_std(hdl, &saa7146_ctrl_ops,
+		V4L2_CID_VFLIP, 0, 1, 1, 0);
+	v4l2_ctrl_new_std(hdl, &saa7146_ctrl_ops,
+		V4L2_CID_HFLIP, 0, 1, 1, 0);
+	if (hdl->error) {
+		err = hdl->error;
+		v4l2_ctrl_handler_free(hdl);
+		return err;
+	}
+	dev->v4l2_dev.ctrl_handler = hdl;
+
+	vv = kzalloc(sizeof(struct saa7146_vv), GFP_KERNEL);
+	if (vv == NULL) {
+		ERR("out of memory. aborting.\n");
+		v4l2_ctrl_handler_free(hdl);
+		return -ENOMEM;
+	}
+	ext_vv->vid_ops = saa7146_video_ioctl_ops;
+	ext_vv->vbi_ops = saa7146_vbi_ioctl_ops;
+	ext_vv->core_ops = &saa7146_video_ioctl_ops;
+
+	DEB_EE("dev:%p\n", dev);
+
+	/* set default values for video parts of the saa7146 */
+	saa7146_write(dev, BCS_CTRL, 0x80400040);
+
+	/* enable video-port pins */
+	saa7146_write(dev, MC1, (MASK_10 | MASK_26));
+
+	/* save per-device extension data (one extension can
+	   handle different devices that might need different
+	   configuration data) */
+	dev->ext_vv_data = ext_vv;
+
+	vv->d_clipping.cpu_addr = pci_alloc_consistent(dev->pci, SAA7146_CLIPPING_MEM, &vv->d_clipping.dma_handle);
+	if( NULL == vv->d_clipping.cpu_addr ) {
+		ERR("out of memory. aborting.\n");
+		kfree(vv);
+		v4l2_ctrl_handler_free(hdl);
+		return -1;
+	}
+	memset(vv->d_clipping.cpu_addr, 0x0, SAA7146_CLIPPING_MEM);
+
+	saa7146_video_uops.init(dev,vv);
+	if (dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE)
+		saa7146_vbi_uops.init(dev,vv);
+
+	fmt = &vv->ov_fb.fmt;
+	fmt->width = vv->standard->h_max_out;
+	fmt->height = vv->standard->v_max_out;
+	fmt->pixelformat = V4L2_PIX_FMT_RGB565;
+	fmt->bytesperline = 2 * fmt->width;
+	fmt->sizeimage = fmt->bytesperline * fmt->height;
+	fmt->colorspace = V4L2_COLORSPACE_SRGB;
+
+	fmt = &vv->video_fmt;
+	fmt->width = 384;
+	fmt->height = 288;
+	fmt->pixelformat = V4L2_PIX_FMT_BGR24;
+	fmt->field = V4L2_FIELD_ANY;
+	fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
+	fmt->bytesperline = 3 * fmt->width;
+	fmt->sizeimage = fmt->bytesperline * fmt->height;
+
+	vbi = &vv->vbi_fmt;
+	vbi->sampling_rate	= 27000000;
+	vbi->offset		= 248; /* todo */
+	vbi->samples_per_line	= 720 * 2;
+	vbi->sample_format	= V4L2_PIX_FMT_GREY;
+
+	/* fixme: this only works for PAL */
+	vbi->start[0] = 5;
+	vbi->count[0] = 16;
+	vbi->start[1] = 312;
+	vbi->count[1] = 16;
+
+	init_timer(&vv->vbi_read_timeout);
+
+	vv->ov_fb.capability = V4L2_FBUF_CAP_LIST_CLIPPING;
+	vv->ov_fb.flags = V4L2_FBUF_FLAG_PRIMARY;
+	dev->vv_data = vv;
+	dev->vv_callback = &vv_callback;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(saa7146_vv_init);
+
+int saa7146_vv_release(struct saa7146_dev* dev)
+{
+	struct saa7146_vv *vv = dev->vv_data;
+
+	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);
+	v4l2_ctrl_handler_free(&dev->ctrl_handler);
+	kfree(vv);
+	dev->vv_data = NULL;
+	dev->vv_callback = NULL;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(saa7146_vv_release);
+
+int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev,
+			    char *name, int type)
+{
+	struct video_device *vfd;
+	int err;
+	int i;
+
+	DEB_EE("dev:%p, name:'%s', type:%d\n", dev, name, type);
+
+	// released by vfd->release
+	vfd = video_device_alloc();
+	if (vfd == NULL)
+		return -ENOMEM;
+
+	vfd->fops = &video_fops;
+	if (type == VFL_TYPE_GRABBER)
+		vfd->ioctl_ops = &dev->ext_vv_data->vid_ops;
+	else
+		vfd->ioctl_ops = &dev->ext_vv_data->vbi_ops;
+	vfd->release = video_device_release;
+	vfd->lock = &dev->v4l2_lock;
+	vfd->v4l2_dev = &dev->v4l2_dev;
+	vfd->tvnorms = 0;
+	set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
+	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);
+
+	err = video_register_device(vfd, type, -1);
+	if (err < 0) {
+		ERR("cannot register v4l2 device. skipping.\n");
+		video_device_release(vfd);
+		return err;
+	}
+
+	pr_info("%s: registered device %s [v4l2]\n",
+		dev->name, video_device_node_name(vfd));
+
+	*vid = vfd;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(saa7146_register_device);
+
+int saa7146_unregister_device(struct video_device **vid, struct saa7146_dev* dev)
+{
+	DEB_EE("dev:%p\n", dev);
+
+	video_unregister_device(*vid);
+	*vid = NULL;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(saa7146_unregister_device);
+
+static int __init saa7146_vv_init_module(void)
+{
+	return 0;
+}
+
+
+static void __exit saa7146_vv_cleanup_module(void)
+{
+}
+
+module_init(saa7146_vv_init_module);
+module_exit(saa7146_vv_cleanup_module);
+
+MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
+MODULE_DESCRIPTION("video4linux driver for saa7146-based hardware");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/common/saa7146/saa7146_hlp.c b/drivers/media/common/saa7146/saa7146_hlp.c
new file mode 100644
index 0000000..be746d1
--- /dev/null
+++ b/drivers/media/common/saa7146/saa7146_hlp.c
@@ -0,0 +1,1048 @@
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/export.h>
+#include <media/saa7146_vv.h>
+
+static void calculate_output_format_register(struct saa7146_dev* saa, u32 palette, u32* clip_format)
+{
+	/* clear out the necessary bits */
+	*clip_format &= 0x0000ffff;
+	/* set these bits new */
+	*clip_format |=  (( ((palette&0xf00)>>8) << 30) | ((palette&0x00f) << 24) | (((palette&0x0f0)>>4) << 16));
+}
+
+static void calculate_hps_source_and_sync(struct saa7146_dev *dev, int source, int sync, u32* hps_ctrl)
+{
+	*hps_ctrl &= ~(MASK_30 | MASK_31 | MASK_28);
+	*hps_ctrl |= (source << 30) | (sync << 28);
+}
+
+static void calculate_hxo_and_hyo(struct saa7146_vv *vv, u32* hps_h_scale, u32* hps_ctrl)
+{
+	int hyo = 0, hxo = 0;
+
+	hyo = vv->standard->v_offset;
+	hxo = vv->standard->h_offset;
+
+	*hps_h_scale	&= ~(MASK_B0 | 0xf00);
+	*hps_h_scale	|= (hxo <<  0);
+
+	*hps_ctrl	&= ~(MASK_W0 | MASK_B2);
+	*hps_ctrl	|= (hyo << 12);
+}
+
+/* helper functions for the calculation of the horizontal- and vertical
+   scaling registers, clip-format-register etc ...
+   these functions take pointers to the (most-likely read-out
+   original-values) and manipulate them according to the requested
+   changes.
+*/
+
+/* hps_coeff used for CXY and CXUV; scale 1/1 -> scale 1/64 */
+static struct {
+	u16 hps_coeff;
+	u16 weight_sum;
+} hps_h_coeff_tab [] = {
+	{0x00,   2}, {0x02,   4}, {0x00,   4}, {0x06,   8}, {0x02,   8},
+	{0x08,   8}, {0x00,   8}, {0x1E,  16}, {0x0E,   8}, {0x26,   8},
+	{0x06,   8}, {0x42,   8}, {0x02,   8}, {0x80,   8}, {0x00,   8},
+	{0xFE,  16}, {0xFE,   8}, {0x7E,   8}, {0x7E,   8}, {0x3E,   8},
+	{0x3E,   8}, {0x1E,   8}, {0x1E,   8}, {0x0E,   8}, {0x0E,   8},
+	{0x06,   8}, {0x06,   8}, {0x02,   8}, {0x02,   8}, {0x00,   8},
+	{0x00,   8}, {0xFE,  16}, {0xFE,   8}, {0xFE,   8}, {0xFE,   8},
+	{0xFE,   8}, {0xFE,   8}, {0xFE,   8}, {0xFE,   8}, {0xFE,   8},
+	{0xFE,   8}, {0xFE,   8}, {0xFE,   8}, {0xFE,   8}, {0xFE,   8},
+	{0xFE,   8}, {0xFE,   8}, {0xFE,   8}, {0xFE,   8}, {0x7E,   8},
+	{0x7E,   8}, {0x3E,   8}, {0x3E,   8}, {0x1E,   8}, {0x1E,   8},
+	{0x0E,   8}, {0x0E,   8}, {0x06,   8}, {0x06,   8}, {0x02,   8},
+	{0x02,   8}, {0x00,   8}, {0x00,   8}, {0xFE,  16}
+};
+
+/* table of attenuation values for horizontal scaling */
+static u8 h_attenuation[] = { 1, 2, 4, 8, 2, 4, 8, 16, 0};
+
+/* calculate horizontal scale registers */
+static int calculate_h_scale_registers(struct saa7146_dev *dev,
+	int in_x, int out_x, int flip_lr,
+	u32* hps_ctrl, u32* hps_v_gain, u32* hps_h_prescale, u32* hps_h_scale)
+{
+	/* horizontal prescaler */
+	u32 dcgx = 0, xpsc = 0, xacm = 0, cxy = 0, cxuv = 0;
+	/* horizontal scaler */
+	u32 xim = 0, xp = 0, xsci =0;
+	/* vertical scale & gain */
+	u32 pfuv = 0;
+
+	/* helper variables */
+	u32 h_atten = 0, i = 0;
+
+	if ( 0 == out_x ) {
+		return -EINVAL;
+	}
+
+	/* mask out vanity-bit */
+	*hps_ctrl &= ~MASK_29;
+
+	/* calculate prescale-(xspc)-value:	[n   .. 1/2) : 1
+						[1/2 .. 1/3) : 2
+						[1/3 .. 1/4) : 3
+						...		*/
+	if (in_x > out_x) {
+		xpsc = in_x / out_x;
+	}
+	else {
+		/* zooming */
+		xpsc = 1;
+	}
+
+	/* if flip_lr-bit is set, number of pixels after
+	   horizontal prescaling must be < 384 */
+	if ( 0 != flip_lr ) {
+
+		/* set vanity bit */
+		*hps_ctrl |= MASK_29;
+
+		while (in_x / xpsc >= 384 )
+			xpsc++;
+	}
+	/* if zooming is wanted, number of pixels after
+	   horizontal prescaling must be < 768 */
+	else {
+		while ( in_x / xpsc >= 768 )
+			xpsc++;
+	}
+
+	/* maximum prescale is 64 (p.69) */
+	if ( xpsc > 64 )
+		xpsc = 64;
+
+	/* keep xacm clear*/
+	xacm = 0;
+
+	/* set horizontal filter parameters (CXY = CXUV) */
+	cxy = hps_h_coeff_tab[( (xpsc - 1) < 63 ? (xpsc - 1) : 63 )].hps_coeff;
+	cxuv = cxy;
+
+	/* calculate and set horizontal fine scale (xsci) */
+
+	/* bypass the horizontal scaler ? */
+	if ( (in_x == out_x) && ( 1 == xpsc ) )
+		xsci = 0x400;
+	else
+		xsci = ( (1024 * in_x) / (out_x * xpsc) ) + xpsc;
+
+	/* set start phase for horizontal fine scale (xp) to 0 */
+	xp = 0;
+
+	/* set xim, if we bypass the horizontal scaler */
+	if ( 0x400 == xsci )
+		xim = 1;
+	else
+		xim = 0;
+
+	/* if the prescaler is bypassed, enable horizontal
+	   accumulation mode (xacm) and clear dcgx */
+	if( 1 == xpsc ) {
+		xacm = 1;
+		dcgx = 0;
+	} else {
+		xacm = 0;
+		/* get best match in the table of attenuations
+		   for horizontal scaling */
+		h_atten = hps_h_coeff_tab[( (xpsc - 1) < 63 ? (xpsc - 1) : 63 )].weight_sum;
+
+		for (i = 0; h_attenuation[i] != 0; i++) {
+			if (h_attenuation[i] >= h_atten)
+				break;
+		}
+
+		dcgx = i;
+	}
+
+	/* the horizontal scaling increment controls the UV filter
+	   to reduce the bandwidth to improve the display quality,
+	   so set it ... */
+	if ( xsci == 0x400)
+		pfuv = 0x00;
+	else if ( xsci < 0x600)
+		pfuv = 0x01;
+	else if ( xsci < 0x680)
+		pfuv = 0x11;
+	else if ( xsci < 0x700)
+		pfuv = 0x22;
+	else
+		pfuv = 0x33;
+
+
+	*hps_v_gain  &= MASK_W0|MASK_B2;
+	*hps_v_gain  |= (pfuv << 24);
+
+	*hps_h_scale	&= ~(MASK_W1 | 0xf000);
+	*hps_h_scale	|= (xim << 31) | (xp << 24) | (xsci << 12);
+
+	*hps_h_prescale	|= (dcgx << 27) | ((xpsc-1) << 18) | (xacm << 17) | (cxy << 8) | (cxuv << 0);
+
+	return 0;
+}
+
+static struct {
+	u16 hps_coeff;
+	u16 weight_sum;
+} hps_v_coeff_tab [] = {
+ {0x0100,   2},  {0x0102,   4},  {0x0300,   4},  {0x0106,   8},  {0x0502,   8},
+ {0x0708,   8},  {0x0F00,   8},  {0x011E,  16},  {0x110E,  16},  {0x1926,  16},
+ {0x3906,  16},  {0x3D42,  16},  {0x7D02,  16},  {0x7F80,  16},  {0xFF00,  16},
+ {0x01FE,  32},  {0x01FE,  32},  {0x817E,  32},  {0x817E,  32},  {0xC13E,  32},
+ {0xC13E,  32},  {0xE11E,  32},  {0xE11E,  32},  {0xF10E,  32},  {0xF10E,  32},
+ {0xF906,  32},  {0xF906,  32},  {0xFD02,  32},  {0xFD02,  32},  {0xFF00,  32},
+ {0xFF00,  32},  {0x01FE,  64},  {0x01FE,  64},  {0x01FE,  64},  {0x01FE,  64},
+ {0x01FE,  64},  {0x01FE,  64},  {0x01FE,  64},  {0x01FE,  64},  {0x01FE,  64},
+ {0x01FE,  64},  {0x01FE,  64},  {0x01FE,  64},  {0x01FE,  64},  {0x01FE,  64},
+ {0x01FE,  64},  {0x01FE,  64},  {0x01FE,  64},  {0x01FE,  64},  {0x817E,  64},
+ {0x817E,  64},  {0xC13E,  64},  {0xC13E,  64},  {0xE11E,  64},  {0xE11E,  64},
+ {0xF10E,  64},  {0xF10E,  64},  {0xF906,  64},  {0xF906,  64},  {0xFD02,  64},
+ {0xFD02,  64},  {0xFF00,  64},  {0xFF00,  64},  {0x01FE, 128}
+};
+
+/* table of attenuation values for vertical scaling */
+static u16 v_attenuation[] = { 2, 4, 8, 16, 32, 64, 128, 256, 0};
+
+/* calculate vertical scale registers */
+static int calculate_v_scale_registers(struct saa7146_dev *dev, enum v4l2_field field,
+	int in_y, int out_y, u32* hps_v_scale, u32* hps_v_gain)
+{
+	int lpi = 0;
+
+	/* vertical scaling */
+	u32 yacm = 0, ysci = 0, yacl = 0, ypo = 0, ype = 0;
+	/* vertical scale & gain */
+	u32 dcgy = 0, cya_cyb = 0;
+
+	/* helper variables */
+	u32 v_atten = 0, i = 0;
+
+	/* error, if vertical zooming */
+	if ( in_y < out_y ) {
+		return -EINVAL;
+	}
+
+	/* linear phase interpolation may be used
+	   if scaling is between 1 and 1/2 (both fields used)
+	   or scaling is between 1/2 and 1/4 (if only one field is used) */
+
+	if (V4L2_FIELD_HAS_BOTH(field)) {
+		if( 2*out_y >= in_y) {
+			lpi = 1;
+		}
+	} else if (field == V4L2_FIELD_TOP
+		|| field == V4L2_FIELD_ALTERNATE
+		|| field == V4L2_FIELD_BOTTOM) {
+		if( 4*out_y >= in_y ) {
+			lpi = 1;
+		}
+		out_y *= 2;
+	}
+	if( 0 != lpi ) {
+
+		yacm = 0;
+		yacl = 0;
+		cya_cyb = 0x00ff;
+
+		/* calculate scaling increment */
+		if ( in_y > out_y )
+			ysci = ((1024 * in_y) / (out_y + 1)) - 1024;
+		else
+			ysci = 0;
+
+		dcgy = 0;
+
+		/* calculate ype and ypo */
+		ype = ysci / 16;
+		ypo = ype + (ysci / 64);
+
+	} else {
+		yacm = 1;
+
+		/* calculate scaling increment */
+		ysci = (((10 * 1024 * (in_y - out_y - 1)) / in_y) + 9) / 10;
+
+		/* calculate ype and ypo */
+		ypo = ype = ((ysci + 15) / 16);
+
+		/* the sequence length interval (yacl) has to be set according
+		   to the prescale value, e.g.	[n   .. 1/2) : 0
+						[1/2 .. 1/3) : 1
+						[1/3 .. 1/4) : 2
+						... */
+		if ( ysci < 512) {
+			yacl = 0;
+		} else {
+			yacl = ( ysci / (1024 - ysci) );
+		}
+
+		/* get filter coefficients for cya, cyb from table hps_v_coeff_tab */
+		cya_cyb = hps_v_coeff_tab[ (yacl < 63 ? yacl : 63 ) ].hps_coeff;
+
+		/* get best match in the table of attenuations for vertical scaling */
+		v_atten = hps_v_coeff_tab[ (yacl < 63 ? yacl : 63 ) ].weight_sum;
+
+		for (i = 0; v_attenuation[i] != 0; i++) {
+			if (v_attenuation[i] >= v_atten)
+				break;
+		}
+
+		dcgy = i;
+	}
+
+	/* ypo and ype swapped in spec ? */
+	*hps_v_scale	|= (yacm << 31) | (ysci << 21) | (yacl << 15) | (ypo << 8 ) | (ype << 1);
+
+	*hps_v_gain	&= ~(MASK_W0|MASK_B2);
+	*hps_v_gain	|= (dcgy << 16) | (cya_cyb << 0);
+
+	return 0;
+}
+
+/* simple bubble-sort algorithm with duplicate elimination */
+static int sort_and_eliminate(u32* values, int* count)
+{
+	int low = 0, high = 0, top = 0, temp = 0;
+	int cur = 0, next = 0;
+
+	/* sanity checks */
+	if( (0 > *count) || (NULL == values) ) {
+		return -EINVAL;
+	}
+
+	/* bubble sort the first @count items of the array @values */
+	for( top = *count; top > 0; top--) {
+		for( low = 0, high = 1; high < top; low++, high++) {
+			if( values[low] > values[high] ) {
+				temp = values[low];
+				values[low] = values[high];
+				values[high] = temp;
+			}
+		}
+	}
+
+	/* remove duplicate items */
+	for( cur = 0, next = 1; next < *count; next++) {
+		if( values[cur] != values[next])
+			values[++cur] = values[next];
+	}
+
+	*count = cur + 1;
+
+	return 0;
+}
+
+static void calculate_clipping_registers_rect(struct saa7146_dev *dev, struct saa7146_fh *fh,
+	struct saa7146_video_dma *vdma2, u32* clip_format, u32* arbtr_ctrl, enum v4l2_field field)
+{
+	struct saa7146_vv *vv = dev->vv_data;
+	__le32 *clipping = vv->d_clipping.cpu_addr;
+
+	int width = vv->ov.win.w.width;
+	int height =  vv->ov.win.w.height;
+	int clipcount = vv->ov.nclips;
+
+	u32 line_list[32];
+	u32 pixel_list[32];
+	int numdwords = 0;
+
+	int i = 0, j = 0;
+	int cnt_line = 0, cnt_pixel = 0;
+
+	int x[32], y[32], w[32], h[32];
+
+	/* clear out memory */
+	memset(&line_list[0],  0x00, sizeof(u32)*32);
+	memset(&pixel_list[0], 0x00, sizeof(u32)*32);
+	memset(clipping,  0x00, SAA7146_CLIPPING_MEM);
+
+	/* fill the line and pixel-lists */
+	for(i = 0; i < clipcount; i++) {
+		int l = 0, r = 0, t = 0, b = 0;
+
+		x[i] = vv->ov.clips[i].c.left;
+		y[i] = vv->ov.clips[i].c.top;
+		w[i] = vv->ov.clips[i].c.width;
+		h[i] = vv->ov.clips[i].c.height;
+
+		if( w[i] < 0) {
+			x[i] += w[i]; w[i] = -w[i];
+		}
+		if( h[i] < 0) {
+			y[i] += h[i]; h[i] = -h[i];
+		}
+		if( x[i] < 0) {
+			w[i] += x[i]; x[i] = 0;
+		}
+		if( y[i] < 0) {
+			h[i] += y[i]; y[i] = 0;
+		}
+		if( 0 != vv->vflip ) {
+			y[i] = height - y[i] - h[i];
+		}
+
+		l = x[i];
+		r = x[i]+w[i];
+		t = y[i];
+		b = y[i]+h[i];
+
+		/* insert left/right coordinates */
+		pixel_list[ 2*i   ] = min_t(int, l, width);
+		pixel_list[(2*i)+1] = min_t(int, r, width);
+		/* insert top/bottom coordinates */
+		line_list[ 2*i   ] = min_t(int, t, height);
+		line_list[(2*i)+1] = min_t(int, b, height);
+	}
+
+	/* sort and eliminate lists */
+	cnt_line = cnt_pixel = 2*clipcount;
+	sort_and_eliminate( &pixel_list[0], &cnt_pixel );
+	sort_and_eliminate( &line_list[0], &cnt_line );
+
+	/* calculate the number of used u32s */
+	numdwords = max_t(int, (cnt_line+1), (cnt_pixel+1))*2;
+	numdwords = max_t(int, 4, numdwords);
+	numdwords = min_t(int, 64, numdwords);
+
+	/* fill up cliptable */
+	for(i = 0; i < cnt_pixel; i++) {
+		clipping[2*i] |= cpu_to_le32(pixel_list[i] << 16);
+	}
+	for(i = 0; i < cnt_line; i++) {
+		clipping[(2*i)+1] |= cpu_to_le32(line_list[i] << 16);
+	}
+
+	/* fill up cliptable with the display infos */
+	for(j = 0; j < clipcount; j++) {
+
+		for(i = 0; i < cnt_pixel; i++) {
+
+			if( x[j] < 0)
+				x[j] = 0;
+
+			if( pixel_list[i] < (x[j] + w[j])) {
+
+				if ( pixel_list[i] >= x[j] ) {
+					clipping[2*i] |= cpu_to_le32(1 << j);
+				}
+			}
+		}
+		for(i = 0; i < cnt_line; i++) {
+
+			if( y[j] < 0)
+				y[j] = 0;
+
+			if( line_list[i] < (y[j] + h[j]) ) {
+
+				if( line_list[i] >= y[j] ) {
+					clipping[(2*i)+1] |= cpu_to_le32(1 << j);
+				}
+			}
+		}
+	}
+
+	/* adjust arbitration control register */
+	*arbtr_ctrl &= 0xffff00ff;
+	*arbtr_ctrl |= 0x00001c00;
+
+	vdma2->base_even	= vv->d_clipping.dma_handle;
+	vdma2->base_odd		= vv->d_clipping.dma_handle;
+	vdma2->prot_addr	= vv->d_clipping.dma_handle+((sizeof(u32))*(numdwords));
+	vdma2->base_page	= 0x04;
+	vdma2->pitch		= 0x00;
+	vdma2->num_line_byte	= (0 << 16 | (sizeof(u32))*(numdwords-1) );
+
+	/* set clipping-mode. this depends on the field(s) used */
+	*clip_format &= 0xfffffff7;
+	if (V4L2_FIELD_HAS_BOTH(field)) {
+		*clip_format |= 0x00000008;
+	} else {
+		*clip_format |= 0x00000000;
+	}
+}
+
+/* disable clipping */
+static void saa7146_disable_clipping(struct saa7146_dev *dev)
+{
+	u32 clip_format	= saa7146_read(dev, CLIP_FORMAT_CTRL);
+
+	/* mask out relevant bits (=lower word)*/
+	clip_format &= MASK_W1;
+
+	/* upload clipping-registers*/
+	saa7146_write(dev, CLIP_FORMAT_CTRL,clip_format);
+	saa7146_write(dev, MC2, (MASK_05 | MASK_21));
+
+	/* disable video dma2 */
+	saa7146_write(dev, MC1, MASK_21);
+}
+
+static void saa7146_set_clipping_rect(struct saa7146_fh *fh)
+{
+	struct saa7146_dev *dev = fh->dev;
+	struct saa7146_vv *vv = dev->vv_data;
+	enum v4l2_field field = vv->ov.win.field;
+	struct	saa7146_video_dma vdma2;
+	u32 clip_format;
+	u32 arbtr_ctrl;
+
+	/* check clipcount, disable clipping if clipcount == 0*/
+	if (vv->ov.nclips == 0) {
+		saa7146_disable_clipping(dev);
+		return;
+	}
+
+	clip_format = saa7146_read(dev, CLIP_FORMAT_CTRL);
+	arbtr_ctrl = saa7146_read(dev, PCI_BT_V1);
+
+	calculate_clipping_registers_rect(dev, fh, &vdma2, &clip_format, &arbtr_ctrl, field);
+
+	/* set clipping format */
+	clip_format &= 0xffff0008;
+	clip_format |= (SAA7146_CLIPPING_RECT << 4);
+
+	/* prepare video dma2 */
+	saa7146_write(dev, BASE_EVEN2,		vdma2.base_even);
+	saa7146_write(dev, BASE_ODD2,		vdma2.base_odd);
+	saa7146_write(dev, PROT_ADDR2,		vdma2.prot_addr);
+	saa7146_write(dev, BASE_PAGE2,		vdma2.base_page);
+	saa7146_write(dev, PITCH2,		vdma2.pitch);
+	saa7146_write(dev, NUM_LINE_BYTE2,	vdma2.num_line_byte);
+
+	/* prepare the rest */
+	saa7146_write(dev, CLIP_FORMAT_CTRL,clip_format);
+	saa7146_write(dev, PCI_BT_V1, arbtr_ctrl);
+
+	/* upload clip_control-register, clipping-registers, enable video dma2 */
+	saa7146_write(dev, MC2, (MASK_05 | MASK_21 | MASK_03 | MASK_19));
+	saa7146_write(dev, MC1, (MASK_05 | MASK_21));
+}
+
+static void saa7146_set_window(struct saa7146_dev *dev, int width, int height, enum v4l2_field field)
+{
+	struct saa7146_vv *vv = dev->vv_data;
+
+	int source = vv->current_hps_source;
+	int sync = vv->current_hps_sync;
+
+	u32 hps_v_scale = 0, hps_v_gain  = 0, hps_ctrl = 0, hps_h_prescale = 0, hps_h_scale = 0;
+
+	/* set vertical scale */
+	hps_v_scale = 0; /* all bits get set by the function-call */
+	hps_v_gain  = 0; /* fixme: saa7146_read(dev, HPS_V_GAIN);*/
+	calculate_v_scale_registers(dev, field, vv->standard->v_field*2, height, &hps_v_scale, &hps_v_gain);
+
+	/* set horizontal scale */
+	hps_ctrl	= 0;
+	hps_h_prescale	= 0; /* all bits get set in the function */
+	hps_h_scale	= 0;
+	calculate_h_scale_registers(dev, vv->standard->h_pixels, width, vv->hflip, &hps_ctrl, &hps_v_gain, &hps_h_prescale, &hps_h_scale);
+
+	/* set hyo and hxo */
+	calculate_hxo_and_hyo(vv, &hps_h_scale, &hps_ctrl);
+	calculate_hps_source_and_sync(dev, source, sync, &hps_ctrl);
+
+	/* write out new register contents */
+	saa7146_write(dev, HPS_V_SCALE,	hps_v_scale);
+	saa7146_write(dev, HPS_V_GAIN,	hps_v_gain);
+	saa7146_write(dev, HPS_CTRL,	hps_ctrl);
+	saa7146_write(dev, HPS_H_PRESCALE,hps_h_prescale);
+	saa7146_write(dev, HPS_H_SCALE,	hps_h_scale);
+
+	/* upload shadow-ram registers */
+	saa7146_write(dev, MC2, (MASK_05 | MASK_06 | MASK_21 | MASK_22) );
+}
+
+/* calculate the new memory offsets for a desired position */
+static void saa7146_set_position(struct saa7146_dev *dev, int w_x, int w_y, int w_height, enum v4l2_field field, u32 pixelformat)
+{
+	struct saa7146_vv *vv = dev->vv_data;
+	struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev, pixelformat);
+
+	int b_depth = vv->ov_fmt->depth;
+	int b_bpl = vv->ov_fb.fmt.bytesperline;
+	/* The unsigned long cast is to remove a 64-bit compile warning since
+	   it looks like a 64-bit address is cast to a 32-bit value, even
+	   though the base pointer is really a 32-bit physical address that
+	   goes into a 32-bit DMA register.
+	   FIXME: might not work on some 64-bit platforms, but see the FIXME
+	   in struct v4l2_framebuffer (videodev2.h) for that.
+	 */
+	u32 base = (u32)(unsigned long)vv->ov_fb.base;
+
+	struct	saa7146_video_dma vdma1;
+
+	/* calculate memory offsets for picture, look if we shall top-down-flip */
+	vdma1.pitch	= 2*b_bpl;
+	if ( 0 == vv->vflip ) {
+		vdma1.base_even = base + (w_y * (vdma1.pitch/2)) + (w_x * (b_depth / 8));
+		vdma1.base_odd  = vdma1.base_even + (vdma1.pitch / 2);
+		vdma1.prot_addr = vdma1.base_even + (w_height * (vdma1.pitch / 2));
+	}
+	else {
+		vdma1.base_even = base + ((w_y+w_height) * (vdma1.pitch/2)) + (w_x * (b_depth / 8));
+		vdma1.base_odd  = vdma1.base_even - (vdma1.pitch / 2);
+		vdma1.prot_addr = vdma1.base_odd - (w_height * (vdma1.pitch / 2));
+	}
+
+	if (V4L2_FIELD_HAS_BOTH(field)) {
+	} else if (field == V4L2_FIELD_ALTERNATE) {
+		/* fixme */
+		vdma1.base_odd = vdma1.prot_addr;
+		vdma1.pitch /= 2;
+	} else if (field == V4L2_FIELD_TOP) {
+		vdma1.base_odd = vdma1.prot_addr;
+		vdma1.pitch /= 2;
+	} else if (field == V4L2_FIELD_BOTTOM) {
+		vdma1.base_odd = vdma1.base_even;
+		vdma1.base_even = vdma1.prot_addr;
+		vdma1.pitch /= 2;
+	}
+
+	if ( 0 != vv->vflip ) {
+		vdma1.pitch *= -1;
+	}
+
+	vdma1.base_page = sfmt->swap;
+	vdma1.num_line_byte = (vv->standard->v_field<<16)+vv->standard->h_pixels;
+
+	saa7146_write_out_dma(dev, 1, &vdma1);
+}
+
+static void saa7146_set_output_format(struct saa7146_dev *dev, unsigned long palette)
+{
+	u32 clip_format = saa7146_read(dev, CLIP_FORMAT_CTRL);
+
+	/* call helper function */
+	calculate_output_format_register(dev,palette,&clip_format);
+
+	/* update the hps registers */
+	saa7146_write(dev, CLIP_FORMAT_CTRL, clip_format);
+	saa7146_write(dev, MC2, (MASK_05 | MASK_21));
+}
+
+/* select input-source */
+void saa7146_set_hps_source_and_sync(struct saa7146_dev *dev, int source, int sync)
+{
+	struct saa7146_vv *vv = dev->vv_data;
+	u32 hps_ctrl = 0;
+
+	/* read old state */
+	hps_ctrl = saa7146_read(dev, HPS_CTRL);
+
+	hps_ctrl &= ~( MASK_31 | MASK_30 | MASK_28 );
+	hps_ctrl |= (source << 30) | (sync << 28);
+
+	/* write back & upload register */
+	saa7146_write(dev, HPS_CTRL, hps_ctrl);
+	saa7146_write(dev, MC2, (MASK_05 | MASK_21));
+
+	vv->current_hps_source = source;
+	vv->current_hps_sync = sync;
+}
+EXPORT_SYMBOL_GPL(saa7146_set_hps_source_and_sync);
+
+int saa7146_enable_overlay(struct saa7146_fh *fh)
+{
+	struct saa7146_dev *dev = fh->dev;
+	struct saa7146_vv *vv = dev->vv_data;
+
+	saa7146_set_window(dev, vv->ov.win.w.width, vv->ov.win.w.height, vv->ov.win.field);
+	saa7146_set_position(dev, vv->ov.win.w.left, vv->ov.win.w.top, vv->ov.win.w.height, vv->ov.win.field, vv->ov_fmt->pixelformat);
+	saa7146_set_output_format(dev, vv->ov_fmt->trans);
+	saa7146_set_clipping_rect(fh);
+
+	/* enable video dma1 */
+	saa7146_write(dev, MC1, (MASK_06 | MASK_22));
+	return 0;
+}
+
+void saa7146_disable_overlay(struct saa7146_fh *fh)
+{
+	struct saa7146_dev *dev = fh->dev;
+
+	/* disable clipping + video dma1 */
+	saa7146_disable_clipping(dev);
+	saa7146_write(dev, MC1, MASK_22);
+}
+
+void saa7146_write_out_dma(struct saa7146_dev* dev, int which, struct saa7146_video_dma* vdma)
+{
+	int where = 0;
+
+	if( which < 1 || which > 3) {
+		return;
+	}
+
+	/* calculate starting address */
+	where  = (which-1)*0x18;
+
+	saa7146_write(dev, where,	vdma->base_odd);
+	saa7146_write(dev, where+0x04,	vdma->base_even);
+	saa7146_write(dev, where+0x08,	vdma->prot_addr);
+	saa7146_write(dev, where+0x0c,	vdma->pitch);
+	saa7146_write(dev, where+0x10,	vdma->base_page);
+	saa7146_write(dev, where+0x14,	vdma->num_line_byte);
+
+	/* upload */
+	saa7146_write(dev, MC2, (MASK_02<<(which-1))|(MASK_18<<(which-1)));
+/*
+	printk("vdma%d.base_even:     0x%08x\n", which,vdma->base_even);
+	printk("vdma%d.base_odd:      0x%08x\n", which,vdma->base_odd);
+	printk("vdma%d.prot_addr:     0x%08x\n", which,vdma->prot_addr);
+	printk("vdma%d.base_page:     0x%08x\n", which,vdma->base_page);
+	printk("vdma%d.pitch:         0x%08x\n", which,vdma->pitch);
+	printk("vdma%d.num_line_byte: 0x%08x\n", which,vdma->num_line_byte);
+*/
+}
+
+static int calculate_video_dma_grab_packed(struct saa7146_dev* dev, struct saa7146_buf *buf)
+{
+	struct saa7146_vv *vv = dev->vv_data;
+	struct saa7146_video_dma vdma1;
+
+	struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat);
+
+	int width = buf->fmt->width;
+	int height = buf->fmt->height;
+	int bytesperline = buf->fmt->bytesperline;
+	enum v4l2_field field = buf->fmt->field;
+
+	int depth = sfmt->depth;
+
+	DEB_CAP("[size=%dx%d,fields=%s]\n",
+		width, height, v4l2_field_names[field]);
+
+	if( bytesperline != 0) {
+		vdma1.pitch = bytesperline*2;
+	} else {
+		vdma1.pitch = (width*depth*2)/8;
+	}
+	vdma1.num_line_byte	= ((vv->standard->v_field<<16) + vv->standard->h_pixels);
+	vdma1.base_page		= buf->pt[0].dma | ME1 | sfmt->swap;
+
+	if( 0 != vv->vflip ) {
+		vdma1.prot_addr	= buf->pt[0].offset;
+		vdma1.base_even	= buf->pt[0].offset+(vdma1.pitch/2)*height;
+		vdma1.base_odd	= vdma1.base_even - (vdma1.pitch/2);
+	} else {
+		vdma1.base_even	= buf->pt[0].offset;
+		vdma1.base_odd	= vdma1.base_even + (vdma1.pitch/2);
+		vdma1.prot_addr	= buf->pt[0].offset+(vdma1.pitch/2)*height;
+	}
+
+	if (V4L2_FIELD_HAS_BOTH(field)) {
+	} else if (field == V4L2_FIELD_ALTERNATE) {
+		/* fixme */
+		if ( vv->last_field == V4L2_FIELD_TOP ) {
+			vdma1.base_odd	= vdma1.prot_addr;
+			vdma1.pitch /= 2;
+		} else if ( vv->last_field == V4L2_FIELD_BOTTOM ) {
+			vdma1.base_odd	= vdma1.base_even;
+			vdma1.base_even = vdma1.prot_addr;
+			vdma1.pitch /= 2;
+		}
+	} else if (field == V4L2_FIELD_TOP) {
+		vdma1.base_odd	= vdma1.prot_addr;
+		vdma1.pitch /= 2;
+	} else if (field == V4L2_FIELD_BOTTOM) {
+		vdma1.base_odd	= vdma1.base_even;
+		vdma1.base_even = vdma1.prot_addr;
+		vdma1.pitch /= 2;
+	}
+
+	if( 0 != vv->vflip ) {
+		vdma1.pitch *= -1;
+	}
+
+	saa7146_write_out_dma(dev, 1, &vdma1);
+	return 0;
+}
+
+static int calc_planar_422(struct saa7146_vv *vv, struct saa7146_buf *buf, struct saa7146_video_dma *vdma2, struct saa7146_video_dma *vdma3)
+{
+	int height = buf->fmt->height;
+	int width = buf->fmt->width;
+
+	vdma2->pitch	= width;
+	vdma3->pitch	= width;
+
+	/* fixme: look at bytesperline! */
+
+	if( 0 != vv->vflip ) {
+		vdma2->prot_addr	= buf->pt[1].offset;
+		vdma2->base_even	= ((vdma2->pitch/2)*height)+buf->pt[1].offset;
+		vdma2->base_odd		= vdma2->base_even - (vdma2->pitch/2);
+
+		vdma3->prot_addr	= buf->pt[2].offset;
+		vdma3->base_even	= ((vdma3->pitch/2)*height)+buf->pt[2].offset;
+		vdma3->base_odd		= vdma3->base_even - (vdma3->pitch/2);
+	} else {
+		vdma3->base_even	= buf->pt[2].offset;
+		vdma3->base_odd		= vdma3->base_even + (vdma3->pitch/2);
+		vdma3->prot_addr	= (vdma3->pitch/2)*height+buf->pt[2].offset;
+
+		vdma2->base_even	= buf->pt[1].offset;
+		vdma2->base_odd		= vdma2->base_even + (vdma2->pitch/2);
+		vdma2->prot_addr	= (vdma2->pitch/2)*height+buf->pt[1].offset;
+	}
+
+	return 0;
+}
+
+static int calc_planar_420(struct saa7146_vv *vv, struct saa7146_buf *buf, struct saa7146_video_dma *vdma2, struct saa7146_video_dma *vdma3)
+{
+	int height = buf->fmt->height;
+	int width = buf->fmt->width;
+
+	vdma2->pitch	= width/2;
+	vdma3->pitch	= width/2;
+
+	if( 0 != vv->vflip ) {
+		vdma2->prot_addr	= buf->pt[2].offset;
+		vdma2->base_even	= ((vdma2->pitch/2)*height)+buf->pt[2].offset;
+		vdma2->base_odd		= vdma2->base_even - (vdma2->pitch/2);
+
+		vdma3->prot_addr	= buf->pt[1].offset;
+		vdma3->base_even	= ((vdma3->pitch/2)*height)+buf->pt[1].offset;
+		vdma3->base_odd		= vdma3->base_even - (vdma3->pitch/2);
+
+	} else {
+		vdma3->base_even	= buf->pt[2].offset;
+		vdma3->base_odd		= vdma3->base_even + (vdma3->pitch);
+		vdma3->prot_addr	= (vdma3->pitch/2)*height+buf->pt[2].offset;
+
+		vdma2->base_even	= buf->pt[1].offset;
+		vdma2->base_odd		= vdma2->base_even + (vdma2->pitch);
+		vdma2->prot_addr	= (vdma2->pitch/2)*height+buf->pt[1].offset;
+	}
+	return 0;
+}
+
+static int calculate_video_dma_grab_planar(struct saa7146_dev* dev, struct saa7146_buf *buf)
+{
+	struct saa7146_vv *vv = dev->vv_data;
+	struct saa7146_video_dma vdma1;
+	struct saa7146_video_dma vdma2;
+	struct saa7146_video_dma vdma3;
+
+	struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat);
+
+	int width = buf->fmt->width;
+	int height = buf->fmt->height;
+	enum v4l2_field field = buf->fmt->field;
+
+	BUG_ON(0 == buf->pt[0].dma);
+	BUG_ON(0 == buf->pt[1].dma);
+	BUG_ON(0 == buf->pt[2].dma);
+
+	DEB_CAP("[size=%dx%d,fields=%s]\n",
+		width, height, v4l2_field_names[field]);
+
+	/* fixme: look at bytesperline! */
+
+	/* fixme: what happens for user space buffers here?. The offsets are
+	   most likely wrong, this version here only works for page-aligned
+	   buffers, modifications to the pagetable-functions are necessary...*/
+
+	vdma1.pitch		= width*2;
+	vdma1.num_line_byte	= ((vv->standard->v_field<<16) + vv->standard->h_pixels);
+	vdma1.base_page		= buf->pt[0].dma | ME1;
+
+	if( 0 != vv->vflip ) {
+		vdma1.prot_addr	= buf->pt[0].offset;
+		vdma1.base_even	= ((vdma1.pitch/2)*height)+buf->pt[0].offset;
+		vdma1.base_odd	= vdma1.base_even - (vdma1.pitch/2);
+	} else {
+		vdma1.base_even	= buf->pt[0].offset;
+		vdma1.base_odd	= vdma1.base_even + (vdma1.pitch/2);
+		vdma1.prot_addr	= (vdma1.pitch/2)*height+buf->pt[0].offset;
+	}
+
+	vdma2.num_line_byte	= 0; /* unused */
+	vdma2.base_page		= buf->pt[1].dma | ME1;
+
+	vdma3.num_line_byte	= 0; /* unused */
+	vdma3.base_page		= buf->pt[2].dma | ME1;
+
+	switch( sfmt->depth ) {
+		case 12: {
+			calc_planar_420(vv,buf,&vdma2,&vdma3);
+			break;
+		}
+		case 16: {
+			calc_planar_422(vv,buf,&vdma2,&vdma3);
+			break;
+		}
+		default: {
+			return -1;
+		}
+	}
+
+	if (V4L2_FIELD_HAS_BOTH(field)) {
+	} else if (field == V4L2_FIELD_ALTERNATE) {
+		/* fixme */
+		vdma1.base_odd	= vdma1.prot_addr;
+		vdma1.pitch /= 2;
+		vdma2.base_odd	= vdma2.prot_addr;
+		vdma2.pitch /= 2;
+		vdma3.base_odd	= vdma3.prot_addr;
+		vdma3.pitch /= 2;
+	} else if (field == V4L2_FIELD_TOP) {
+		vdma1.base_odd	= vdma1.prot_addr;
+		vdma1.pitch /= 2;
+		vdma2.base_odd	= vdma2.prot_addr;
+		vdma2.pitch /= 2;
+		vdma3.base_odd	= vdma3.prot_addr;
+		vdma3.pitch /= 2;
+	} else if (field == V4L2_FIELD_BOTTOM) {
+		vdma1.base_odd	= vdma1.base_even;
+		vdma1.base_even = vdma1.prot_addr;
+		vdma1.pitch /= 2;
+		vdma2.base_odd	= vdma2.base_even;
+		vdma2.base_even = vdma2.prot_addr;
+		vdma2.pitch /= 2;
+		vdma3.base_odd	= vdma3.base_even;
+		vdma3.base_even = vdma3.prot_addr;
+		vdma3.pitch /= 2;
+	}
+
+	if( 0 != vv->vflip ) {
+		vdma1.pitch *= -1;
+		vdma2.pitch *= -1;
+		vdma3.pitch *= -1;
+	}
+
+	saa7146_write_out_dma(dev, 1, &vdma1);
+	if( (sfmt->flags & FORMAT_BYTE_SWAP) != 0 ) {
+		saa7146_write_out_dma(dev, 3, &vdma2);
+		saa7146_write_out_dma(dev, 2, &vdma3);
+	} else {
+		saa7146_write_out_dma(dev, 2, &vdma2);
+		saa7146_write_out_dma(dev, 3, &vdma3);
+	}
+	return 0;
+}
+
+static void program_capture_engine(struct saa7146_dev *dev, int planar)
+{
+	struct saa7146_vv *vv = dev->vv_data;
+	int count = 0;
+
+	unsigned long e_wait = vv->current_hps_sync == SAA7146_HPS_SYNC_PORT_A ? CMD_E_FID_A : CMD_E_FID_B;
+	unsigned long o_wait = vv->current_hps_sync == SAA7146_HPS_SYNC_PORT_A ? CMD_O_FID_A : CMD_O_FID_B;
+
+	/* wait for o_fid_a/b / e_fid_a/b toggle only if rps register 0 is not set*/
+	WRITE_RPS0(CMD_PAUSE | CMD_OAN | CMD_SIG0 | o_wait);
+	WRITE_RPS0(CMD_PAUSE | CMD_OAN | CMD_SIG0 | e_wait);
+
+	/* set rps register 0 */
+	WRITE_RPS0(CMD_WR_REG | (1 << 8) | (MC2/4));
+	WRITE_RPS0(MASK_27 | MASK_11);
+
+	/* turn on video-dma1 */
+	WRITE_RPS0(CMD_WR_REG_MASK | (MC1/4));
+	WRITE_RPS0(MASK_06 | MASK_22);			/* => mask */
+	WRITE_RPS0(MASK_06 | MASK_22);			/* => values */
+	if( 0 != planar ) {
+		/* turn on video-dma2 */
+		WRITE_RPS0(CMD_WR_REG_MASK | (MC1/4));
+		WRITE_RPS0(MASK_05 | MASK_21);			/* => mask */
+		WRITE_RPS0(MASK_05 | MASK_21);			/* => values */
+
+		/* turn on video-dma3 */
+		WRITE_RPS0(CMD_WR_REG_MASK | (MC1/4));
+		WRITE_RPS0(MASK_04 | MASK_20);			/* => mask */
+		WRITE_RPS0(MASK_04 | MASK_20);			/* => values */
+	}
+
+	/* wait for o_fid_a/b / e_fid_a/b toggle */
+	if ( vv->last_field == V4L2_FIELD_INTERLACED ) {
+		WRITE_RPS0(CMD_PAUSE | o_wait);
+		WRITE_RPS0(CMD_PAUSE | e_wait);
+	} else if ( vv->last_field == V4L2_FIELD_TOP ) {
+		WRITE_RPS0(CMD_PAUSE | (vv->current_hps_sync == SAA7146_HPS_SYNC_PORT_A ? MASK_10 : MASK_09));
+		WRITE_RPS0(CMD_PAUSE | o_wait);
+	} else if ( vv->last_field == V4L2_FIELD_BOTTOM ) {
+		WRITE_RPS0(CMD_PAUSE | (vv->current_hps_sync == SAA7146_HPS_SYNC_PORT_A ? MASK_10 : MASK_09));
+		WRITE_RPS0(CMD_PAUSE | e_wait);
+	}
+
+	/* turn off video-dma1 */
+	WRITE_RPS0(CMD_WR_REG_MASK | (MC1/4));
+	WRITE_RPS0(MASK_22 | MASK_06);			/* => mask */
+	WRITE_RPS0(MASK_22);				/* => values */
+	if( 0 != planar ) {
+		/* turn off video-dma2 */
+		WRITE_RPS0(CMD_WR_REG_MASK | (MC1/4));
+		WRITE_RPS0(MASK_05 | MASK_21);			/* => mask */
+		WRITE_RPS0(MASK_21);				/* => values */
+
+		/* turn off video-dma3 */
+		WRITE_RPS0(CMD_WR_REG_MASK | (MC1/4));
+		WRITE_RPS0(MASK_04 | MASK_20);			/* => mask */
+		WRITE_RPS0(MASK_20);				/* => values */
+	}
+
+	/* generate interrupt */
+	WRITE_RPS0(CMD_INTERRUPT);
+
+	/* stop */
+	WRITE_RPS0(CMD_STOP);
+}
+
+void saa7146_set_capture(struct saa7146_dev *dev, struct saa7146_buf *buf, struct saa7146_buf *next)
+{
+	struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat);
+	struct saa7146_vv *vv = dev->vv_data;
+	u32 vdma1_prot_addr;
+
+	DEB_CAP("buf:%p, next:%p\n", buf, next);
+
+	vdma1_prot_addr = saa7146_read(dev, PROT_ADDR1);
+	if( 0 == vdma1_prot_addr ) {
+		/* clear out beginning of streaming bit (rps register 0)*/
+		DEB_CAP("forcing sync to new frame\n");
+		saa7146_write(dev, MC2, MASK_27 );
+	}
+
+	saa7146_set_window(dev, buf->fmt->width, buf->fmt->height, buf->fmt->field);
+	saa7146_set_output_format(dev, sfmt->trans);
+	saa7146_disable_clipping(dev);
+
+	if ( vv->last_field == V4L2_FIELD_INTERLACED ) {
+	} else if ( vv->last_field == V4L2_FIELD_TOP ) {
+		vv->last_field = V4L2_FIELD_BOTTOM;
+	} else if ( vv->last_field == V4L2_FIELD_BOTTOM ) {
+		vv->last_field = V4L2_FIELD_TOP;
+	}
+
+	if( 0 != IS_PLANAR(sfmt->trans)) {
+		calculate_video_dma_grab_planar(dev, buf);
+		program_capture_engine(dev,1);
+	} else {
+		calculate_video_dma_grab_packed(dev, buf);
+		program_capture_engine(dev,0);
+	}
+
+/*
+	printk("vdma%d.base_even:     0x%08x\n", 1,saa7146_read(dev,BASE_EVEN1));
+	printk("vdma%d.base_odd:      0x%08x\n", 1,saa7146_read(dev,BASE_ODD1));
+	printk("vdma%d.prot_addr:     0x%08x\n", 1,saa7146_read(dev,PROT_ADDR1));
+	printk("vdma%d.base_page:     0x%08x\n", 1,saa7146_read(dev,BASE_PAGE1));
+	printk("vdma%d.pitch:         0x%08x\n", 1,saa7146_read(dev,PITCH1));
+	printk("vdma%d.num_line_byte: 0x%08x\n", 1,saa7146_read(dev,NUM_LINE_BYTE1));
+	printk("vdma%d => vptr      : 0x%08x\n", 1,saa7146_read(dev,PCI_VDP1));
+*/
+
+	/* write the address of the rps-program */
+	saa7146_write(dev, RPS_ADDR0, dev->d_rps0.dma_handle);
+
+	/* turn on rps */
+	saa7146_write(dev, MC1, (MASK_12 | MASK_28));
+}
diff --git a/drivers/media/common/saa7146/saa7146_i2c.c b/drivers/media/common/saa7146/saa7146_i2c.c
new file mode 100644
index 0000000..2202719
--- /dev/null
+++ b/drivers/media/common/saa7146/saa7146_i2c.c
@@ -0,0 +1,423 @@
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <media/saa7146_vv.h>
+
+static u32 saa7146_i2c_func(struct i2c_adapter *adapter)
+{
+	/* DEB_I2C("'%s'\n", adapter->name); */
+
+	return	  I2C_FUNC_I2C
+		| I2C_FUNC_SMBUS_QUICK
+		| I2C_FUNC_SMBUS_READ_BYTE	| I2C_FUNC_SMBUS_WRITE_BYTE
+		| I2C_FUNC_SMBUS_READ_BYTE_DATA | I2C_FUNC_SMBUS_WRITE_BYTE_DATA;
+}
+
+/* this function returns the status-register of our i2c-device */
+static inline u32 saa7146_i2c_status(struct saa7146_dev *dev)
+{
+	u32 iicsta = saa7146_read(dev, I2C_STATUS);
+	/* DEB_I2C("status: 0x%08x\n", iicsta); */
+	return iicsta;
+}
+
+/* this function runs through the i2c-messages and prepares the data to be
+   sent through the saa7146. have a look at the specifications p. 122 ff
+   to understand this. it returns the number of u32s to send, or -1
+   in case of an error. */
+static int saa7146_i2c_msg_prepare(const struct i2c_msg *m, int num, __le32 *op)
+{
+	int h1, h2;
+	int i, j, addr;
+	int mem = 0, op_count = 0;
+
+	/* first determine size of needed memory */
+	for(i = 0; i < num; i++) {
+		mem += m[i].len + 1;
+	}
+
+	/* worst case: we need one u32 for three bytes to be send
+	   plus one extra byte to address the device */
+	mem = 1 + ((mem-1) / 3);
+
+	/* we assume that op points to a memory of at least
+	 * SAA7146_I2C_MEM bytes size. if we exceed this limit...
+	 */
+	if ((4 * mem) > SAA7146_I2C_MEM) {
+		/* DEB_I2C("cannot prepare i2c-message\n"); */
+		return -ENOMEM;
+	}
+
+	/* be careful: clear out the i2c-mem first */
+	memset(op,0,sizeof(__le32)*mem);
+
+	/* loop through all messages */
+	for(i = 0; i < num; i++) {
+
+		/* insert the address of the i2c-slave.
+		   note: we get 7 bit i2c-addresses,
+		   so we have to perform a translation */
+		addr = (m[i].addr*2) + ( (0 != (m[i].flags & I2C_M_RD)) ? 1 : 0);
+		h1 = op_count/3; h2 = op_count%3;
+		op[h1] |= cpu_to_le32(	    (u8)addr << ((3-h2)*8));
+		op[h1] |= cpu_to_le32(SAA7146_I2C_START << ((3-h2)*2));
+		op_count++;
+
+		/* loop through all bytes of message i */
+		for(j = 0; j < m[i].len; j++) {
+			/* insert the data bytes */
+			h1 = op_count/3; h2 = op_count%3;
+			op[h1] |= cpu_to_le32( (u32)((u8)m[i].buf[j]) << ((3-h2)*8));
+			op[h1] |= cpu_to_le32(       SAA7146_I2C_CONT << ((3-h2)*2));
+			op_count++;
+		}
+
+	}
+
+	/* have a look at the last byte inserted:
+	  if it was: ...CONT change it to ...STOP */
+	h1 = (op_count-1)/3; h2 = (op_count-1)%3;
+	if ( SAA7146_I2C_CONT == (0x3 & (le32_to_cpu(op[h1]) >> ((3-h2)*2))) ) {
+		op[h1] &= ~cpu_to_le32(0x2 << ((3-h2)*2));
+		op[h1] |= cpu_to_le32(SAA7146_I2C_STOP << ((3-h2)*2));
+	}
+
+	/* return the number of u32s to send */
+	return mem;
+}
+
+/* this functions loops through all i2c-messages. normally, it should determine
+   which bytes were read through the adapter and write them back to the corresponding
+   i2c-message. but instead, we simply write back all bytes.
+   fixme: this could be improved. */
+static int saa7146_i2c_msg_cleanup(const struct i2c_msg *m, int num, __le32 *op)
+{
+	int i, j;
+	int op_count = 0;
+
+	/* loop through all messages */
+	for(i = 0; i < num; i++) {
+
+		op_count++;
+
+		/* loop through all bytes of message i */
+		for(j = 0; j < m[i].len; j++) {
+			/* write back all bytes that could have been read */
+			m[i].buf[j] = (le32_to_cpu(op[op_count/3]) >> ((3-(op_count%3))*8));
+			op_count++;
+		}
+	}
+
+	return 0;
+}
+
+/* this functions resets the i2c-device and returns 0 if everything was fine, otherwise -1 */
+static int saa7146_i2c_reset(struct saa7146_dev *dev)
+{
+	/* get current status */
+	u32 status = saa7146_i2c_status(dev);
+
+	/* clear registers for sure */
+	saa7146_write(dev, I2C_STATUS, dev->i2c_bitrate);
+	saa7146_write(dev, I2C_TRANSFER, 0);
+
+	/* check if any operation is still in progress */
+	if ( 0 != ( status & SAA7146_I2C_BUSY) ) {
+
+		/* yes, kill ongoing operation */
+		DEB_I2C("busy_state detected\n");
+
+		/* set "ABORT-OPERATION"-bit (bit 7)*/
+		saa7146_write(dev, I2C_STATUS, (dev->i2c_bitrate | MASK_07));
+		saa7146_write(dev, MC2, (MASK_00 | MASK_16));
+		msleep(SAA7146_I2C_DELAY);
+
+		/* clear all error-bits pending; this is needed because p.123, note 1 */
+		saa7146_write(dev, I2C_STATUS, dev->i2c_bitrate);
+		saa7146_write(dev, MC2, (MASK_00 | MASK_16));
+		msleep(SAA7146_I2C_DELAY);
+	}
+
+	/* check if any error is (still) present. (this can be necessary because p.123, note 1) */
+	status = saa7146_i2c_status(dev);
+
+	if ( dev->i2c_bitrate != status ) {
+
+		DEB_I2C("error_state detected. status:0x%08x\n", status);
+
+		/* Repeat the abort operation. This seems to be necessary
+		   after serious protocol errors caused by e.g. the SAA7740 */
+		saa7146_write(dev, I2C_STATUS, (dev->i2c_bitrate | MASK_07));
+		saa7146_write(dev, MC2, (MASK_00 | MASK_16));
+		msleep(SAA7146_I2C_DELAY);
+
+		/* clear all error-bits pending */
+		saa7146_write(dev, I2C_STATUS, dev->i2c_bitrate);
+		saa7146_write(dev, MC2, (MASK_00 | MASK_16));
+		msleep(SAA7146_I2C_DELAY);
+
+		/* the data sheet says it might be necessary to clear the status
+		   twice after an abort */
+		saa7146_write(dev, I2C_STATUS, dev->i2c_bitrate);
+		saa7146_write(dev, MC2, (MASK_00 | MASK_16));
+		msleep(SAA7146_I2C_DELAY);
+	}
+
+	/* if any error is still present, a fatal error has occurred ... */
+	status = saa7146_i2c_status(dev);
+	if ( dev->i2c_bitrate != status ) {
+		DEB_I2C("fatal error. status:0x%08x\n", status);
+		return -1;
+	}
+
+	return 0;
+}
+
+/* this functions writes out the data-byte 'dword' to the i2c-device.
+   it returns 0 if ok, -1 if the transfer failed, -2 if the transfer
+   failed badly (e.g. address error) */
+static int saa7146_i2c_writeout(struct saa7146_dev *dev, __le32 *dword, int short_delay)
+{
+	u32 status = 0, mc2 = 0;
+	int trial = 0;
+	unsigned long timeout;
+
+	/* write out i2c-command */
+	DEB_I2C("before: 0x%08x (status: 0x%08x), %d\n",
+		*dword, saa7146_read(dev, I2C_STATUS), dev->i2c_op);
+
+	if( 0 != (SAA7146_USE_I2C_IRQ & dev->ext->flags)) {
+
+		saa7146_write(dev, I2C_STATUS,	 dev->i2c_bitrate);
+		saa7146_write(dev, I2C_TRANSFER, le32_to_cpu(*dword));
+
+		dev->i2c_op = 1;
+		SAA7146_ISR_CLEAR(dev, MASK_16|MASK_17);
+		SAA7146_IER_ENABLE(dev, MASK_16|MASK_17);
+		saa7146_write(dev, MC2, (MASK_00 | MASK_16));
+
+		timeout = HZ/100 + 1; /* 10ms */
+		timeout = wait_event_interruptible_timeout(dev->i2c_wq, dev->i2c_op == 0, timeout);
+		if (timeout == -ERESTARTSYS || dev->i2c_op) {
+			SAA7146_IER_DISABLE(dev, MASK_16|MASK_17);
+			SAA7146_ISR_CLEAR(dev, MASK_16|MASK_17);
+			if (timeout == -ERESTARTSYS)
+				/* a signal arrived */
+				return -ERESTARTSYS;
+
+			pr_warn("%s %s [irq]: timed out waiting for end of xfer\n",
+				dev->name, __func__);
+			return -EIO;
+		}
+		status = saa7146_read(dev, I2C_STATUS);
+	} else {
+		saa7146_write(dev, I2C_STATUS,	 dev->i2c_bitrate);
+		saa7146_write(dev, I2C_TRANSFER, le32_to_cpu(*dword));
+		saa7146_write(dev, MC2, (MASK_00 | MASK_16));
+
+		/* do not poll for i2c-status before upload is complete */
+		timeout = jiffies + HZ/100 + 1; /* 10ms */
+		while(1) {
+			mc2 = (saa7146_read(dev, MC2) & 0x1);
+			if( 0 != mc2 ) {
+				break;
+			}
+			if (time_after(jiffies,timeout)) {
+				pr_warn("%s %s: timed out waiting for MC2\n",
+					dev->name, __func__);
+				return -EIO;
+			}
+		}
+		/* wait until we get a transfer done or error */
+		timeout = jiffies + HZ/100 + 1; /* 10ms */
+		/* first read usually delivers bogus results... */
+		saa7146_i2c_status(dev);
+		while(1) {
+			status = saa7146_i2c_status(dev);
+			if ((status & 0x3) != 1)
+				break;
+			if (time_after(jiffies,timeout)) {
+				/* this is normal when probing the bus
+				 * (no answer from nonexisistant device...)
+				 */
+				pr_warn("%s %s [poll]: timed out waiting for end of xfer\n",
+					dev->name, __func__);
+				return -EIO;
+			}
+			if (++trial < 50 && short_delay)
+				udelay(10);
+			else
+				msleep(1);
+		}
+	}
+
+	/* give a detailed status report */
+	if ( 0 != (status & (SAA7146_I2C_SPERR | SAA7146_I2C_APERR |
+			     SAA7146_I2C_DTERR | SAA7146_I2C_DRERR |
+			     SAA7146_I2C_AL    | SAA7146_I2C_ERR   |
+			     SAA7146_I2C_BUSY)) ) {
+
+		if ( 0 == (status & SAA7146_I2C_ERR) ||
+		     0 == (status & SAA7146_I2C_BUSY) ) {
+			/* it may take some time until ERR goes high - ignore */
+			DEB_I2C("unexpected i2c status %04x\n", status);
+		}
+		if( 0 != (status & SAA7146_I2C_SPERR) ) {
+			DEB_I2C("error due to invalid start/stop condition\n");
+		}
+		if( 0 != (status & SAA7146_I2C_DTERR) ) {
+			DEB_I2C("error in data transmission\n");
+		}
+		if( 0 != (status & SAA7146_I2C_DRERR) ) {
+			DEB_I2C("error when receiving data\n");
+		}
+		if( 0 != (status & SAA7146_I2C_AL) ) {
+			DEB_I2C("error because arbitration lost\n");
+		}
+
+		/* we handle address-errors here */
+		if( 0 != (status & SAA7146_I2C_APERR) ) {
+			DEB_I2C("error in address phase\n");
+			return -EREMOTEIO;
+		}
+
+		return -EIO;
+	}
+
+	/* read back data, just in case we were reading ... */
+	*dword = cpu_to_le32(saa7146_read(dev, I2C_TRANSFER));
+
+	DEB_I2C("after: 0x%08x\n", *dword);
+	return 0;
+}
+
+static int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg *msgs, int num, int retries)
+{
+	int i = 0, count = 0;
+	__le32 *buffer = dev->d_i2c.cpu_addr;
+	int err = 0;
+	int short_delay = 0;
+
+	if (mutex_lock_interruptible(&dev->i2c_lock))
+		return -ERESTARTSYS;
+
+	for(i=0;i<num;i++) {
+		DEB_I2C("msg:%d/%d\n", i+1, num);
+	}
+
+	/* prepare the message(s), get number of u32s to transfer */
+	count = saa7146_i2c_msg_prepare(msgs, num, buffer);
+	if ( 0 > count ) {
+		err = -1;
+		goto out;
+	}
+
+	if ( count > 3 || 0 != (SAA7146_I2C_SHORT_DELAY & dev->ext->flags) )
+		short_delay = 1;
+
+	do {
+		/* reset the i2c-device if necessary */
+		err = saa7146_i2c_reset(dev);
+		if ( 0 > err ) {
+			DEB_I2C("could not reset i2c-device\n");
+			goto out;
+		}
+
+		/* write out the u32s one after another */
+		for(i = 0; i < count; i++) {
+			err = saa7146_i2c_writeout(dev, &buffer[i], short_delay);
+			if ( 0 != err) {
+				/* this one is unsatisfying: some i2c slaves on some
+				   dvb cards don't acknowledge correctly, so the saa7146
+				   thinks that an address error occurred. in that case, the
+				   transaction should be retrying, even if an address error
+				   occurred. analog saa7146 based cards extensively rely on
+				   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. 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;
+			}
+		}
+		if( 0 == err ) {
+			err = num;
+			break;
+		}
+
+		/* delay a bit before retrying */
+		msleep(10);
+
+	} while (err != num && 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)) {
+		DEB_I2C("could not cleanup i2c-message\n");
+		err = -1;
+		goto out;
+	}
+
+	/* return the number of delivered messages */
+	DEB_I2C("transmission successful. (msg:%d)\n", err);
+out:
+	/* another bug in revision 0: the i2c-registers get uploaded randomly by other
+	   uploads, so we better clear them out before continuing */
+	if( 0 == dev->revision ) {
+		__le32 zero = 0;
+		saa7146_i2c_reset(dev);
+		if( 0 != saa7146_i2c_writeout(dev, &zero, short_delay)) {
+			pr_info("revision 0 error. this should never happen\n");
+		}
+	}
+
+	mutex_unlock(&dev->i2c_lock);
+	return err;
+}
+
+/* utility functions */
+static int saa7146_i2c_xfer(struct i2c_adapter* adapter, struct i2c_msg *msg, int num)
+{
+	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);
+}
+
+
+/*****************************************************************************/
+/* i2c-adapter helper functions                                              */
+
+/* exported algorithm data */
+static struct i2c_algorithm saa7146_algo = {
+	.master_xfer	= saa7146_i2c_xfer,
+	.functionality	= saa7146_i2c_func,
+};
+
+int saa7146_i2c_adapter_prepare(struct saa7146_dev *dev, struct i2c_adapter *i2c_adapter, u32 bitrate)
+{
+	DEB_EE("bitrate: 0x%08x\n", bitrate);
+
+	/* enable i2c-port pins */
+	saa7146_write(dev, MC1, (MASK_08 | MASK_24));
+
+	dev->i2c_bitrate = bitrate;
+	saa7146_i2c_reset(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;
+		i2c_adapter->timeout = SAA7146_I2C_TIMEOUT;
+		i2c_adapter->retries = SAA7146_I2C_RETRIES;
+	}
+
+	return 0;
+}
diff --git a/drivers/media/common/saa7146/saa7146_vbi.c b/drivers/media/common/saa7146/saa7146_vbi.c
new file mode 100644
index 0000000..1e71e37
--- /dev/null
+++ b/drivers/media/common/saa7146/saa7146_vbi.c
@@ -0,0 +1,498 @@
+#include <media/saa7146_vv.h>
+
+static int vbi_pixel_to_capture = 720 * 2;
+
+static int vbi_workaround(struct saa7146_dev *dev)
+{
+	struct saa7146_vv *vv = dev->vv_data;
+
+	u32          *cpu;
+	dma_addr_t   dma_addr;
+
+	int count = 0;
+	int i;
+
+	DECLARE_WAITQUEUE(wait, current);
+
+	DEB_VBI("dev:%p\n", dev);
+
+	/* once again, a bug in the saa7146: the brs acquisition
+	   is buggy and especially the BXO-counter does not work
+	   as specified. there is this workaround, but please
+	   don't let me explain it. ;-) */
+
+	cpu = pci_alloc_consistent(dev->pci, 4096, &dma_addr);
+	if (NULL == cpu)
+		return -ENOMEM;
+
+	/* setup some basic programming, just for the workaround */
+	saa7146_write(dev, BASE_EVEN3,	dma_addr);
+	saa7146_write(dev, BASE_ODD3,	dma_addr+vbi_pixel_to_capture);
+	saa7146_write(dev, PROT_ADDR3,	dma_addr+4096);
+	saa7146_write(dev, PITCH3,	vbi_pixel_to_capture);
+	saa7146_write(dev, BASE_PAGE3,	0x0);
+	saa7146_write(dev, NUM_LINE_BYTE3, (2<<16)|((vbi_pixel_to_capture)<<0));
+	saa7146_write(dev, MC2, MASK_04|MASK_20);
+
+	/* load brs-control register */
+	WRITE_RPS1(CMD_WR_REG | (1 << 8) | (BRS_CTRL/4));
+	/* BXO = 1h, BRS to outbound */
+	WRITE_RPS1(0xc000008c);
+	/* wait for vbi_a or vbi_b*/
+	if ( 0 != (SAA7146_USE_PORT_B_FOR_VBI & dev->ext_vv_data->flags)) {
+		DEB_D("...using port b\n");
+		WRITE_RPS1(CMD_PAUSE | CMD_OAN | CMD_SIG1 | CMD_E_FID_B);
+		WRITE_RPS1(CMD_PAUSE | CMD_OAN | CMD_SIG1 | CMD_O_FID_B);
+/*
+		WRITE_RPS1(CMD_PAUSE | MASK_09);
+*/
+	} else {
+		DEB_D("...using port a\n");
+		WRITE_RPS1(CMD_PAUSE | MASK_10);
+	}
+	/* upload brs */
+	WRITE_RPS1(CMD_UPLOAD | MASK_08);
+	/* load brs-control register */
+	WRITE_RPS1(CMD_WR_REG | (1 << 8) | (BRS_CTRL/4));
+	/* BYO = 1, BXO = NQBIL (=1728 for PAL, for NTSC this is 858*2) - NumByte3 (=1440) = 288 */
+	WRITE_RPS1(((1728-(vbi_pixel_to_capture)) << 7) | MASK_19);
+	/* wait for brs_done */
+	WRITE_RPS1(CMD_PAUSE | MASK_08);
+	/* upload brs */
+	WRITE_RPS1(CMD_UPLOAD | MASK_08);
+	/* load video-dma3 NumLines3 and NumBytes3 */
+	WRITE_RPS1(CMD_WR_REG | (1 << 8) | (NUM_LINE_BYTE3/4));
+	/* dev->vbi_count*2 lines, 720 pixel (= 1440 Bytes) */
+	WRITE_RPS1((2 << 16) | (vbi_pixel_to_capture));
+	/* load brs-control register */
+	WRITE_RPS1(CMD_WR_REG | (1 << 8) | (BRS_CTRL/4));
+	/* Set BRS right: note: this is an experimental value for BXO (=> PAL!) */
+	WRITE_RPS1((540 << 7) | (5 << 19));  // 5 == vbi_start
+	/* wait for brs_done */
+	WRITE_RPS1(CMD_PAUSE | MASK_08);
+	/* upload brs and video-dma3*/
+	WRITE_RPS1(CMD_UPLOAD | MASK_08 | MASK_04);
+	/* load mc2 register: enable dma3 */
+	WRITE_RPS1(CMD_WR_REG | (1 << 8) | (MC1/4));
+	WRITE_RPS1(MASK_20 | MASK_04);
+	/* generate interrupt */
+	WRITE_RPS1(CMD_INTERRUPT);
+	/* stop rps1 */
+	WRITE_RPS1(CMD_STOP);
+
+	/* we have to do the workaround twice to be sure that
+	   everything is ok */
+	for(i = 0; i < 2; i++) {
+
+		/* indicate to the irq handler that we do the workaround */
+		saa7146_write(dev, MC2, MASK_31|MASK_15);
+
+		saa7146_write(dev, NUM_LINE_BYTE3, (1<<16)|(2<<0));
+		saa7146_write(dev, MC2, MASK_04|MASK_20);
+
+		/* enable rps1 irqs */
+		SAA7146_IER_ENABLE(dev,MASK_28);
+
+		/* prepare to wait to be woken up by the irq-handler */
+		add_wait_queue(&vv->vbi_wq, &wait);
+		current->state = TASK_INTERRUPTIBLE;
+
+		/* start rps1 to enable workaround */
+		saa7146_write(dev, RPS_ADDR1, dev->d_rps1.dma_handle);
+		saa7146_write(dev, MC1, (MASK_13 | MASK_29));
+
+		schedule();
+
+		DEB_VBI("brs bug workaround %d/1\n", i);
+
+		remove_wait_queue(&vv->vbi_wq, &wait);
+		current->state = TASK_RUNNING;
+
+		/* disable rps1 irqs */
+		SAA7146_IER_DISABLE(dev,MASK_28);
+
+		/* stop video-dma3 */
+		saa7146_write(dev, MC1, MASK_20);
+
+		if(signal_pending(current)) {
+
+			DEB_VBI("aborted (rps:0x%08x)\n",
+				saa7146_read(dev, RPS_ADDR1));
+
+			/* stop rps1 for sure */
+			saa7146_write(dev, MC1, MASK_29);
+
+			pci_free_consistent(dev->pci, 4096, cpu, dma_addr);
+			return -EINTR;
+		}
+	}
+
+	pci_free_consistent(dev->pci, 4096, cpu, dma_addr);
+	return 0;
+}
+
+static void saa7146_set_vbi_capture(struct saa7146_dev *dev, struct saa7146_buf *buf, struct saa7146_buf *next)
+{
+	struct saa7146_vv *vv = dev->vv_data;
+
+	struct saa7146_video_dma vdma3;
+
+	int count = 0;
+	unsigned long e_wait = vv->current_hps_sync == SAA7146_HPS_SYNC_PORT_A ? CMD_E_FID_A : CMD_E_FID_B;
+	unsigned long o_wait = vv->current_hps_sync == SAA7146_HPS_SYNC_PORT_A ? CMD_O_FID_A : CMD_O_FID_B;
+
+/*
+	vdma3.base_even	= 0xc8000000+2560*70;
+	vdma3.base_odd	= 0xc8000000;
+	vdma3.prot_addr	= 0xc8000000+2560*164;
+	vdma3.pitch	= 2560;
+	vdma3.base_page	= 0;
+	vdma3.num_line_byte = (64<<16)|((vbi_pixel_to_capture)<<0); // set above!
+*/
+	vdma3.base_even	= buf->pt[2].offset;
+	vdma3.base_odd	= buf->pt[2].offset + 16 * vbi_pixel_to_capture;
+	vdma3.prot_addr	= buf->pt[2].offset + 16 * 2 * vbi_pixel_to_capture;
+	vdma3.pitch	= vbi_pixel_to_capture;
+	vdma3.base_page	= buf->pt[2].dma | ME1;
+	vdma3.num_line_byte = (16 << 16) | vbi_pixel_to_capture;
+
+	saa7146_write_out_dma(dev, 3, &vdma3);
+
+	/* write beginning of rps-program */
+	count = 0;
+
+	/* wait for o_fid_a/b / e_fid_a/b toggle only if bit 1 is not set */
+
+	/* we don't wait here for the first field anymore. this is different from the video
+	   capture and might cause that the first buffer is only half filled (with only
+	   one field). but since this is some sort of streaming data, this is not that negative.
+	   but by doing this, we can use the whole engine from videobuf-dma-sg.c... */
+
+/*
+	WRITE_RPS1(CMD_PAUSE | CMD_OAN | CMD_SIG1 | e_wait);
+	WRITE_RPS1(CMD_PAUSE | CMD_OAN | CMD_SIG1 | o_wait);
+*/
+	/* set bit 1 */
+	WRITE_RPS1(CMD_WR_REG | (1 << 8) | (MC2/4));
+	WRITE_RPS1(MASK_28 | MASK_12);
+
+	/* turn on video-dma3 */
+	WRITE_RPS1(CMD_WR_REG_MASK | (MC1/4));
+	WRITE_RPS1(MASK_04 | MASK_20);			/* => mask */
+	WRITE_RPS1(MASK_04 | MASK_20);			/* => values */
+
+	/* wait for o_fid_a/b / e_fid_a/b toggle */
+	WRITE_RPS1(CMD_PAUSE | o_wait);
+	WRITE_RPS1(CMD_PAUSE | e_wait);
+
+	/* generate interrupt */
+	WRITE_RPS1(CMD_INTERRUPT);
+
+	/* stop */
+	WRITE_RPS1(CMD_STOP);
+
+	/* enable rps1 irqs */
+	SAA7146_IER_ENABLE(dev, MASK_28);
+
+	/* write the address of the rps-program */
+	saa7146_write(dev, RPS_ADDR1, dev->d_rps1.dma_handle);
+
+	/* turn on rps */
+	saa7146_write(dev, MC1, (MASK_13 | MASK_29));
+}
+
+static int buffer_activate(struct saa7146_dev *dev,
+			   struct saa7146_buf *buf,
+			   struct saa7146_buf *next)
+{
+	struct saa7146_vv *vv = dev->vv_data;
+	buf->vb.state = VIDEOBUF_ACTIVE;
+
+	DEB_VBI("dev:%p, buf:%p, next:%p\n", dev, buf, next);
+	saa7146_set_vbi_capture(dev,buf,next);
+
+	mod_timer(&vv->vbi_dmaq.timeout, jiffies+BUFFER_TIMEOUT);
+	return 0;
+}
+
+static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,enum v4l2_field field)
+{
+	struct file *file = q->priv_data;
+	struct saa7146_fh *fh = file->private_data;
+	struct saa7146_dev *dev = fh->dev;
+	struct saa7146_buf *buf = (struct saa7146_buf *)vb;
+
+	int err = 0;
+	int lines, llength, size;
+
+	lines   = 16 * 2 ; /* 2 fields */
+	llength = vbi_pixel_to_capture;
+	size = lines * llength;
+
+	DEB_VBI("vb:%p\n", vb);
+
+	if (0 != buf->vb.baddr  &&  buf->vb.bsize < size) {
+		DEB_VBI("size mismatch\n");
+		return -EINVAL;
+	}
+
+	if (buf->vb.size != size)
+		saa7146_dma_free(dev,q,buf);
+
+	if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
+		struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
+
+		buf->vb.width  = llength;
+		buf->vb.height = lines;
+		buf->vb.size   = size;
+		buf->vb.field  = field;	// FIXME: check this
+
+		saa7146_pgtable_free(dev->pci, &buf->pt[2]);
+		saa7146_pgtable_alloc(dev->pci, &buf->pt[2]);
+
+		err = videobuf_iolock(q,&buf->vb, NULL);
+		if (err)
+			goto oops;
+		err = saa7146_pgtable_build_single(dev->pci, &buf->pt[2],
+						 dma->sglist, dma->sglen);
+		if (0 != err)
+			return err;
+	}
+	buf->vb.state = VIDEOBUF_PREPARED;
+	buf->activate = buffer_activate;
+
+	return 0;
+
+ oops:
+	DEB_VBI("error out\n");
+	saa7146_dma_free(dev,q,buf);
+
+	return err;
+}
+
+static int buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
+{
+	int llength,lines;
+
+	lines   = 16 * 2 ; /* 2 fields */
+	llength = vbi_pixel_to_capture;
+
+	*size = lines * llength;
+	*count = 2;
+
+	DEB_VBI("count:%d, size:%d\n", *count, *size);
+
+	return 0;
+}
+
+static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
+{
+	struct file *file = q->priv_data;
+	struct saa7146_fh *fh = file->private_data;
+	struct saa7146_dev *dev = fh->dev;
+	struct saa7146_vv *vv = dev->vv_data;
+	struct saa7146_buf *buf = (struct saa7146_buf *)vb;
+
+	DEB_VBI("vb:%p\n", vb);
+	saa7146_buffer_queue(dev, &vv->vbi_dmaq, buf);
+}
+
+static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
+{
+	struct file *file = q->priv_data;
+	struct saa7146_fh *fh   = file->private_data;
+	struct saa7146_dev *dev = fh->dev;
+	struct saa7146_buf *buf = (struct saa7146_buf *)vb;
+
+	DEB_VBI("vb:%p\n", vb);
+	saa7146_dma_free(dev,q,buf);
+}
+
+static struct videobuf_queue_ops vbi_qops = {
+	.buf_setup    = buffer_setup,
+	.buf_prepare  = buffer_prepare,
+	.buf_queue    = buffer_queue,
+	.buf_release  = buffer_release,
+};
+
+/* ------------------------------------------------------------------ */
+
+static void vbi_stop(struct saa7146_fh *fh, struct file *file)
+{
+	struct saa7146_dev *dev = fh->dev;
+	struct saa7146_vv *vv = dev->vv_data;
+	unsigned long flags;
+	DEB_VBI("dev:%p, fh:%p\n", dev, fh);
+
+	spin_lock_irqsave(&dev->slock,flags);
+
+	/* disable rps1  */
+	saa7146_write(dev, MC1, MASK_29);
+
+	/* disable rps1 irqs */
+	SAA7146_IER_DISABLE(dev, MASK_28);
+
+	/* shut down dma 3 transfers */
+	saa7146_write(dev, MC1, MASK_20);
+
+	if (vv->vbi_dmaq.curr)
+		saa7146_buffer_finish(dev, &vv->vbi_dmaq, VIDEOBUF_DONE);
+
+	videobuf_queue_cancel(&fh->vbi_q);
+
+	vv->vbi_streaming = NULL;
+
+	del_timer(&vv->vbi_dmaq.timeout);
+	del_timer(&vv->vbi_read_timeout);
+
+	spin_unlock_irqrestore(&dev->slock, flags);
+}
+
+static void vbi_read_timeout(unsigned long data)
+{
+	struct file *file = (struct file*)data;
+	struct saa7146_fh *fh = file->private_data;
+	struct saa7146_dev *dev = fh->dev;
+
+	DEB_VBI("dev:%p, fh:%p\n", dev, fh);
+
+	vbi_stop(fh, file);
+}
+
+static void vbi_init(struct saa7146_dev *dev, struct saa7146_vv *vv)
+{
+	DEB_VBI("dev:%p\n", dev);
+
+	INIT_LIST_HEAD(&vv->vbi_dmaq.queue);
+
+	init_timer(&vv->vbi_dmaq.timeout);
+	vv->vbi_dmaq.timeout.function = saa7146_buffer_timeout;
+	vv->vbi_dmaq.timeout.data     = (unsigned long)(&vv->vbi_dmaq);
+	vv->vbi_dmaq.dev              = dev;
+
+	init_waitqueue_head(&vv->vbi_wq);
+}
+
+static int vbi_open(struct saa7146_dev *dev, struct file *file)
+{
+	struct saa7146_fh *fh = file->private_data;
+	struct saa7146_vv *vv = fh->dev->vv_data;
+
+	u32 arbtr_ctrl	= saa7146_read(dev, PCI_BT_V1);
+	int ret = 0;
+
+	DEB_VBI("dev:%p, fh:%p\n", dev, fh);
+
+	ret = saa7146_res_get(fh, RESOURCE_DMA3_BRS);
+	if (0 == ret) {
+		DEB_S("cannot get vbi RESOURCE_DMA3_BRS resource\n");
+		return -EBUSY;
+	}
+
+	/* adjust arbitrition control for video dma 3 */
+	arbtr_ctrl &= ~0x1f0000;
+	arbtr_ctrl |=  0x1d0000;
+	saa7146_write(dev, PCI_BT_V1, arbtr_ctrl);
+	saa7146_write(dev, MC2, (MASK_04|MASK_20));
+
+	videobuf_queue_sg_init(&fh->vbi_q, &vbi_qops,
+			    &dev->pci->dev, &dev->slock,
+			    V4L2_BUF_TYPE_VBI_CAPTURE,
+			    V4L2_FIELD_SEQ_TB, // FIXME: does this really work?
+			    sizeof(struct saa7146_buf),
+			    file, &dev->v4l2_lock);
+
+	vv->vbi_read_timeout.function = vbi_read_timeout;
+	vv->vbi_read_timeout.data = (unsigned long)file;
+
+	/* initialize the brs */
+	if ( 0 != (SAA7146_USE_PORT_B_FOR_VBI & dev->ext_vv_data->flags)) {
+		saa7146_write(dev, BRS_CTRL, MASK_30|MASK_29 | (7 << 19));
+	} else {
+		saa7146_write(dev, BRS_CTRL, 0x00000001);
+
+		if (0 != (ret = vbi_workaround(dev))) {
+			DEB_VBI("vbi workaround failed!\n");
+			/* return ret;*/
+		}
+	}
+
+	/* upload brs register */
+	saa7146_write(dev, MC2, (MASK_08|MASK_24));
+	return 0;
+}
+
+static void vbi_close(struct saa7146_dev *dev, struct file *file)
+{
+	struct saa7146_fh *fh = file->private_data;
+	struct saa7146_vv *vv = dev->vv_data;
+	DEB_VBI("dev:%p, fh:%p\n", dev, fh);
+
+	if( fh == vv->vbi_streaming ) {
+		vbi_stop(fh, file);
+	}
+	saa7146_res_free(fh, RESOURCE_DMA3_BRS);
+}
+
+static void vbi_irq_done(struct saa7146_dev *dev, unsigned long status)
+{
+	struct saa7146_vv *vv = dev->vv_data;
+	spin_lock(&dev->slock);
+
+	if (vv->vbi_dmaq.curr) {
+		DEB_VBI("dev:%p, curr:%p\n", dev, vv->vbi_dmaq.curr);
+		/* this must be += 2, one count for each field */
+		vv->vbi_fieldcount+=2;
+		vv->vbi_dmaq.curr->vb.field_count = vv->vbi_fieldcount;
+		saa7146_buffer_finish(dev, &vv->vbi_dmaq, VIDEOBUF_DONE);
+	} else {
+		DEB_VBI("dev:%p\n", dev);
+	}
+	saa7146_buffer_next(dev, &vv->vbi_dmaq, 1);
+
+	spin_unlock(&dev->slock);
+}
+
+static ssize_t vbi_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
+{
+	struct saa7146_fh *fh = file->private_data;
+	struct saa7146_dev *dev = fh->dev;
+	struct saa7146_vv *vv = dev->vv_data;
+	ssize_t ret = 0;
+
+	DEB_VBI("dev:%p, fh:%p\n", dev, fh);
+
+	if( NULL == vv->vbi_streaming ) {
+		// fixme: check if dma3 is available
+		// fixme: activate vbi engine here if necessary. (really?)
+		vv->vbi_streaming = fh;
+	}
+
+	if( fh != vv->vbi_streaming ) {
+		DEB_VBI("open %p is already using vbi capture\n",
+			vv->vbi_streaming);
+		return -EBUSY;
+	}
+
+	mod_timer(&vv->vbi_read_timeout, jiffies+BUFFER_TIMEOUT);
+	ret = videobuf_read_stream(&fh->vbi_q, data, count, ppos, 1,
+				   file->f_flags & O_NONBLOCK);
+/*
+	printk("BASE_ODD3:      0x%08x\n", saa7146_read(dev, BASE_ODD3));
+	printk("BASE_EVEN3:     0x%08x\n", saa7146_read(dev, BASE_EVEN3));
+	printk("PROT_ADDR3:     0x%08x\n", saa7146_read(dev, PROT_ADDR3));
+	printk("PITCH3:         0x%08x\n", saa7146_read(dev, PITCH3));
+	printk("BASE_PAGE3:     0x%08x\n", saa7146_read(dev, BASE_PAGE3));
+	printk("NUM_LINE_BYTE3: 0x%08x\n", saa7146_read(dev, NUM_LINE_BYTE3));
+	printk("BRS_CTRL:       0x%08x\n", saa7146_read(dev, BRS_CTRL));
+*/
+	return ret;
+}
+
+struct saa7146_use_ops saa7146_vbi_uops = {
+	.init		= vbi_init,
+	.open		= vbi_open,
+	.release	= vbi_close,
+	.irq_done	= vbi_irq_done,
+	.read		= vbi_read,
+};
diff --git a/drivers/media/common/saa7146/saa7146_video.c b/drivers/media/common/saa7146/saa7146_video.c
new file mode 100644
index 0000000..6d14785
--- /dev/null
+++ b/drivers/media/common/saa7146/saa7146_video.c
@@ -0,0 +1,1332 @@
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <media/saa7146_vv.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-ctrls.h>
+#include <linux/module.h>
+
+static int max_memory = 32;
+
+module_param(max_memory, int, 0644);
+MODULE_PARM_DESC(max_memory, "maximum memory usage for capture buffers (default: 32Mb)");
+
+#define IS_CAPTURE_ACTIVE(fh) \
+	(((vv->video_status & STATUS_CAPTURE) != 0) && (vv->video_fh == fh))
+
+#define IS_OVERLAY_ACTIVE(fh) \
+	(((vv->video_status & STATUS_OVERLAY) != 0) && (vv->video_fh == fh))
+
+/* format descriptions for capture and preview */
+static struct saa7146_format formats[] = {
+	{
+		.name		= "RGB-8 (3-3-2)",
+		.pixelformat	= V4L2_PIX_FMT_RGB332,
+		.trans		= RGB08_COMPOSED,
+		.depth		= 8,
+		.flags		= 0,
+	}, {
+		.name		= "RGB-16 (5/B-6/G-5/R)",
+		.pixelformat	= V4L2_PIX_FMT_RGB565,
+		.trans		= RGB16_COMPOSED,
+		.depth		= 16,
+		.flags		= 0,
+	}, {
+		.name		= "RGB-24 (B-G-R)",
+		.pixelformat	= V4L2_PIX_FMT_BGR24,
+		.trans		= RGB24_COMPOSED,
+		.depth		= 24,
+		.flags		= 0,
+	}, {
+		.name		= "RGB-32 (B-G-R)",
+		.pixelformat	= V4L2_PIX_FMT_BGR32,
+		.trans		= RGB32_COMPOSED,
+		.depth		= 32,
+		.flags		= 0,
+	}, {
+		.name		= "RGB-32 (R-G-B)",
+		.pixelformat	= V4L2_PIX_FMT_RGB32,
+		.trans		= RGB32_COMPOSED,
+		.depth		= 32,
+		.flags		= 0,
+		.swap		= 0x2,
+	}, {
+		.name		= "Greyscale-8",
+		.pixelformat	= V4L2_PIX_FMT_GREY,
+		.trans		= Y8,
+		.depth		= 8,
+		.flags		= 0,
+	}, {
+		.name		= "YUV 4:2:2 planar (Y-Cb-Cr)",
+		.pixelformat	= V4L2_PIX_FMT_YUV422P,
+		.trans		= YUV422_DECOMPOSED,
+		.depth		= 16,
+		.flags		= FORMAT_BYTE_SWAP|FORMAT_IS_PLANAR,
+	}, {
+		.name		= "YVU 4:2:0 planar (Y-Cb-Cr)",
+		.pixelformat	= V4L2_PIX_FMT_YVU420,
+		.trans		= YUV420_DECOMPOSED,
+		.depth		= 12,
+		.flags		= FORMAT_BYTE_SWAP|FORMAT_IS_PLANAR,
+	}, {
+		.name		= "YUV 4:2:0 planar (Y-Cb-Cr)",
+		.pixelformat	= V4L2_PIX_FMT_YUV420,
+		.trans		= YUV420_DECOMPOSED,
+		.depth		= 12,
+		.flags		= FORMAT_IS_PLANAR,
+	}, {
+		.name		= "YUV 4:2:2 (U-Y-V-Y)",
+		.pixelformat	= V4L2_PIX_FMT_UYVY,
+		.trans		= YUV422_COMPOSED,
+		.depth		= 16,
+		.flags		= 0,
+	}
+};
+
+/* unfortunately, the saa7146 contains a bug which prevents it from doing on-the-fly byte swaps.
+   due to this, it's impossible to provide additional *packed* formats, which are simply byte swapped
+   (like V4L2_PIX_FMT_YUYV) ... 8-( */
+
+static int NUM_FORMATS = sizeof(formats)/sizeof(struct saa7146_format);
+
+struct saa7146_format* saa7146_format_by_fourcc(struct saa7146_dev *dev, int fourcc)
+{
+	int i, j = NUM_FORMATS;
+
+	for (i = 0; i < j; i++) {
+		if (formats[i].pixelformat == fourcc) {
+			return formats+i;
+		}
+	}
+
+	DEB_D("unknown pixelformat:'%4.4s'\n", (char *)&fourcc);
+	return NULL;
+}
+
+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);
+
+	/* check if we have overlay information */
+	if (vv->ov.fh == NULL) {
+		DEB_D("no overlay data available. try S_FMT first.\n");
+		return -EAGAIN;
+	}
+
+	/* check if streaming capture is running */
+	if (IS_CAPTURE_ACTIVE(fh) != 0) {
+		DEB_D("streaming capture is active\n");
+		return -EBUSY;
+	}
+
+	/* check if overlay is running */
+	if (IS_OVERLAY_ACTIVE(fh) != 0) {
+		if (vv->video_fh == fh) {
+			DEB_D("overlay is already active\n");
+			return 0;
+		}
+		DEB_D("overlay is already active in another open\n");
+		return -EBUSY;
+	}
+
+	if (0 == saa7146_res_get(fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP)) {
+		DEB_D("cannot get necessary overlay resources\n");
+		return -EBUSY;
+	}
+
+	fmt.fmt.win = vv->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;
+	}
+	vv->ov.win = fmt.fmt.win;
+
+	DEB_D("%dx%d+%d+%d %s field=%s\n",
+	      vv->ov.win.w.width, vv->ov.win.w.height,
+	      vv->ov.win.w.left, vv->ov.win.w.top,
+	      vv->ov_fmt->name, v4l2_field_names[vv->ov.win.field]);
+
+	if (0 != (ret = saa7146_enable_overlay(fh))) {
+		DEB_D("enabling overlay failed: %d\n", ret);
+		saa7146_res_free(vv->video_fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP);
+		return ret;
+	}
+
+	vv->video_status = STATUS_OVERLAY;
+	vv->video_fh = fh;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(saa7146_start_preview);
+
+int saa7146_stop_preview(struct saa7146_fh *fh)
+{
+	struct saa7146_dev *dev = fh->dev;
+	struct saa7146_vv *vv = dev->vv_data;
+
+	DEB_EE("dev:%p, fh:%p\n", dev, fh);
+
+	/* check if streaming capture is running */
+	if (IS_CAPTURE_ACTIVE(fh) != 0) {
+		DEB_D("streaming capture is active\n");
+		return -EBUSY;
+	}
+
+	/* check if overlay is running at all */
+	if ((vv->video_status & STATUS_OVERLAY) == 0) {
+		DEB_D("no active overlay\n");
+		return 0;
+	}
+
+	if (vv->video_fh != fh) {
+		DEB_D("overlay is active, but in another open\n");
+		return -EBUSY;
+	}
+
+	vv->video_status = 0;
+	vv->video_fh = NULL;
+
+	saa7146_disable_overlay(fh);
+
+	saa7146_res_free(fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(saa7146_stop_preview);
+
+/********************************************************************************/
+/* common pagetable functions */
+
+static int saa7146_pgtable_build(struct saa7146_dev *dev, struct saa7146_buf *buf)
+{
+	struct pci_dev *pci = dev->pci;
+	struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
+	struct scatterlist *list = dma->sglist;
+	int length = dma->sglen;
+	struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat);
+
+	DEB_EE("dev:%p, buf:%p, sg_len:%d\n", dev, buf, length);
+
+	if( 0 != IS_PLANAR(sfmt->trans)) {
+		struct saa7146_pgtable *pt1 = &buf->pt[0];
+		struct saa7146_pgtable *pt2 = &buf->pt[1];
+		struct saa7146_pgtable *pt3 = &buf->pt[2];
+		__le32  *ptr1, *ptr2, *ptr3;
+		__le32 fill;
+
+		int size = buf->fmt->width*buf->fmt->height;
+		int i,p,m1,m2,m3,o1,o2;
+
+		switch( sfmt->depth ) {
+			case 12: {
+				/* create some offsets inside the page table */
+				m1 = ((size+PAGE_SIZE)/PAGE_SIZE)-1;
+				m2 = ((size+(size/4)+PAGE_SIZE)/PAGE_SIZE)-1;
+				m3 = ((size+(size/2)+PAGE_SIZE)/PAGE_SIZE)-1;
+				o1 = size%PAGE_SIZE;
+				o2 = (size+(size/4))%PAGE_SIZE;
+				DEB_CAP("size:%d, m1:%d, m2:%d, m3:%d, o1:%d, o2:%d\n",
+					size, m1, m2, m3, o1, o2);
+				break;
+			}
+			case 16: {
+				/* create some offsets inside the page table */
+				m1 = ((size+PAGE_SIZE)/PAGE_SIZE)-1;
+				m2 = ((size+(size/2)+PAGE_SIZE)/PAGE_SIZE)-1;
+				m3 = ((2*size+PAGE_SIZE)/PAGE_SIZE)-1;
+				o1 = size%PAGE_SIZE;
+				o2 = (size+(size/2))%PAGE_SIZE;
+				DEB_CAP("size:%d, m1:%d, m2:%d, m3:%d, o1:%d, o2:%d\n",
+					size, m1, m2, m3, o1, o2);
+				break;
+			}
+			default: {
+				return -1;
+			}
+		}
+
+		ptr1 = pt1->cpu;
+		ptr2 = pt2->cpu;
+		ptr3 = pt3->cpu;
+
+		/* walk all pages, copy all page addresses to ptr1 */
+		for (i = 0; i < length; i++, list++) {
+			for (p = 0; p * 4096 < list->length; p++, ptr1++) {
+				*ptr1 = cpu_to_le32(sg_dma_address(list) - list->offset);
+			}
+		}
+/*
+		ptr1 = pt1->cpu;
+		for(j=0;j<40;j++) {
+			printk("ptr1 %d: 0x%08x\n",j,ptr1[j]);
+		}
+*/
+
+		/* if we have a user buffer, the first page may not be
+		   aligned to a page boundary. */
+		pt1->offset = dma->sglist->offset;
+		pt2->offset = pt1->offset+o1;
+		pt3->offset = pt1->offset+o2;
+
+		/* create video-dma2 page table */
+		ptr1 = pt1->cpu;
+		for(i = m1; i <= m2 ; i++, ptr2++) {
+			*ptr2 = ptr1[i];
+		}
+		fill = *(ptr2-1);
+		for(;i<1024;i++,ptr2++) {
+			*ptr2 = fill;
+		}
+		/* create video-dma3 page table */
+		ptr1 = pt1->cpu;
+		for(i = m2; i <= m3; i++,ptr3++) {
+			*ptr3 = ptr1[i];
+		}
+		fill = *(ptr3-1);
+		for(;i<1024;i++,ptr3++) {
+			*ptr3 = fill;
+		}
+		/* finally: finish up video-dma1 page table */
+		ptr1 = pt1->cpu+m1;
+		fill = pt1->cpu[m1];
+		for(i=m1;i<1024;i++,ptr1++) {
+			*ptr1 = fill;
+		}
+/*
+		ptr1 = pt1->cpu;
+		ptr2 = pt2->cpu;
+		ptr3 = pt3->cpu;
+		for(j=0;j<40;j++) {
+			printk("ptr1 %d: 0x%08x\n",j,ptr1[j]);
+		}
+		for(j=0;j<40;j++) {
+			printk("ptr2 %d: 0x%08x\n",j,ptr2[j]);
+		}
+		for(j=0;j<40;j++) {
+			printk("ptr3 %d: 0x%08x\n",j,ptr3[j]);
+		}
+*/
+	} else {
+		struct saa7146_pgtable *pt = &buf->pt[0];
+		return saa7146_pgtable_build_single(pci, pt, list, length);
+	}
+
+	return 0;
+}
+
+
+/********************************************************************************/
+/* file operations */
+
+static int video_begin(struct saa7146_fh *fh)
+{
+	struct saa7146_dev *dev = fh->dev;
+	struct saa7146_vv *vv = dev->vv_data;
+	struct saa7146_format *fmt = NULL;
+	unsigned int resource;
+	int ret = 0, err = 0;
+
+	DEB_EE("dev:%p, fh:%p\n", dev, fh);
+
+	if ((vv->video_status & STATUS_CAPTURE) != 0) {
+		if (vv->video_fh == fh) {
+			DEB_S("already capturing\n");
+			return 0;
+		}
+		DEB_S("already capturing in another open\n");
+		return -EBUSY;
+	}
+
+	if ((vv->video_status & STATUS_OVERLAY) != 0) {
+		DEB_S("warning: suspending overlay video for streaming capture\n");
+		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;
+		}
+	}
+
+	fmt = saa7146_format_by_fourcc(dev, vv->video_fmt.pixelformat);
+	/* we need to have a valid format set here */
+	BUG_ON(NULL == fmt);
+
+	if (0 != (fmt->flags & FORMAT_IS_PLANAR)) {
+		resource = RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP|RESOURCE_DMA3_BRS;
+	} else {
+		resource = RESOURCE_DMA1_HPS;
+	}
+
+	ret = saa7146_res_get(fh, resource);
+	if (0 == ret) {
+		DEB_S("cannot get capture resource %d\n", resource);
+		if (vv->ov_suspend != NULL) {
+			saa7146_start_preview(vv->ov_suspend);
+			vv->ov_suspend = NULL;
+		}
+		return -EBUSY;
+	}
+
+	/* clear out beginning of streaming bit (rps register 0)*/
+	saa7146_write(dev, MC2, MASK_27 );
+
+	/* enable rps0 irqs */
+	SAA7146_IER_ENABLE(dev, MASK_27);
+
+	vv->video_fh = fh;
+	vv->video_status = STATUS_CAPTURE;
+
+	return 0;
+}
+
+static int video_end(struct saa7146_fh *fh, struct file *file)
+{
+	struct saa7146_dev *dev = fh->dev;
+	struct saa7146_vv *vv = dev->vv_data;
+	struct saa7146_format *fmt = NULL;
+	unsigned long flags;
+	unsigned int resource;
+	u32 dmas = 0;
+	DEB_EE("dev:%p, fh:%p\n", dev, fh);
+
+	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;
+	}
+
+	fmt = saa7146_format_by_fourcc(dev, vv->video_fmt.pixelformat);
+	/* we need to have a valid format set here */
+	BUG_ON(NULL == fmt);
+
+	if (0 != (fmt->flags & FORMAT_IS_PLANAR)) {
+		resource = RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP|RESOURCE_DMA3_BRS;
+		dmas = MASK_22 | MASK_21 | MASK_20;
+	} else {
+		resource = RESOURCE_DMA1_HPS;
+		dmas = MASK_22;
+	}
+	spin_lock_irqsave(&dev->slock,flags);
+
+	/* disable rps0  */
+	saa7146_write(dev, MC1, MASK_28);
+
+	/* disable rps0 irqs */
+	SAA7146_IER_DISABLE(dev, MASK_27);
+
+	/* shut down all used video dma transfers */
+	saa7146_write(dev, MC1, dmas);
+
+	spin_unlock_irqrestore(&dev->slock, flags);
+
+	vv->video_fh = NULL;
+	vv->video_status = 0;
+
+	saa7146_res_free(fh, resource);
+
+	if (vv->ov_suspend != NULL) {
+		saa7146_start_preview(vv->ov_suspend);
+		vv->ov_suspend = NULL;
+	}
+
+	return 0;
+}
+
+static int vidioc_querycap(struct file *file, void *fh, struct v4l2_capability *cap)
+{
+	struct video_device *vdev = video_devdata(file);
+	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->device_caps =
+		V4L2_CAP_VIDEO_CAPTURE |
+		V4L2_CAP_VIDEO_OVERLAY |
+		V4L2_CAP_READWRITE |
+		V4L2_CAP_STREAMING;
+	cap->device_caps |= dev->ext_vv_data->capabilities;
+	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+	if (vdev->vfl_type == VFL_TYPE_GRABBER)
+		cap->device_caps &=
+			~(V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_OUTPUT);
+	else
+		cap->device_caps &=
+			~(V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OVERLAY | V4L2_CAP_AUDIO);
+	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;
+
+	*fb = vv->ov_fb;
+	fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING;
+	fb->flags = V4L2_FBUF_FLAG_PRIMARY;
+	return 0;
+}
+
+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;
+
+	DEB_EE("VIDIOC_S_FBUF\n");
+
+	if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RAWIO))
+		return -EPERM;
+
+	/* check args */
+	fmt = saa7146_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;
+		}
+	}
+
+	/* ok, accept it */
+	vv->ov_fb = *fb;
+	vv->ov_fmt = fmt;
+
+	if (vv->ov_fb.fmt.bytesperline < vv->ov_fb.fmt.width) {
+		vv->ov_fb.fmt.bytesperline = vv->ov_fb.fmt.width * fmt->depth / 8;
+		DEB_D("setting bytesperline to %d\n", vv->ov_fb.fmt.bytesperline);
+	}
+	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;
+}
+
+int saa7146_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct saa7146_dev *dev = container_of(ctrl->handler,
+				struct saa7146_dev, ctrl_handler);
+	struct saa7146_vv *vv = dev->vv_data;
+	u32 val;
+
+	switch (ctrl->id) {
+	case V4L2_CID_BRIGHTNESS:
+		val = saa7146_read(dev, BCS_CTRL);
+		val &= 0x00ffffff;
+		val |= (ctrl->val << 24);
+		saa7146_write(dev, BCS_CTRL, val);
+		saa7146_write(dev, MC2, MASK_22 | MASK_06);
+		break;
+
+	case V4L2_CID_CONTRAST:
+		val = saa7146_read(dev, BCS_CTRL);
+		val &= 0xff00ffff;
+		val |= (ctrl->val << 16);
+		saa7146_write(dev, BCS_CTRL, val);
+		saa7146_write(dev, MC2, MASK_22 | MASK_06);
+		break;
+
+	case V4L2_CID_SATURATION:
+		val = saa7146_read(dev, BCS_CTRL);
+		val &= 0xffffff00;
+		val |= (ctrl->val << 0);
+		saa7146_write(dev, BCS_CTRL, val);
+		saa7146_write(dev, MC2, MASK_22 | MASK_06);
+		break;
+
+	case V4L2_CID_HFLIP:
+		/* fixme: we can support changing VFLIP and HFLIP here... */
+		if ((vv->video_status & STATUS_CAPTURE))
+			return -EBUSY;
+		vv->hflip = ctrl->val;
+		break;
+
+	case V4L2_CID_VFLIP:
+		if ((vv->video_status & STATUS_CAPTURE))
+			return -EBUSY;
+		vv->vflip = ctrl->val;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	if ((vv->video_status & STATUS_OVERLAY) != 0) { /* CHECK: && (vv->video_fh == fh)) */
+		struct saa7146_fh *fh = vv->video_fh;
+
+		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;
+
+	if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+	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)
+{
+	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
+	struct saa7146_vv *vv = dev->vv_data;
+
+	f->fmt.pix = vv->video_fmt;
+	return 0;
+}
+
+static int vidioc_g_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;
+
+	f->fmt.win = vv->ov.win;
+	return 0;
+}
+
+static int vidioc_g_fmt_vbi_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;
+
+	f->fmt.vbi = vv->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 = saa7146_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;
+	f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+	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;
+		}
+	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 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;
+	}
+	err = vidioc_try_fmt_vid_cap(file, fh, f);
+	if (0 != err)
+		return err;
+	vv->video_fmt = f->fmt.pix;
+	DEB_EE("set to pixelformat '%4.4s'\n",
+	       (char *)&vv->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;
+	vv->ov.win    = f->fmt.win;
+	vv->ov.nclips = f->fmt.win.clipcount;
+	if (vv->ov.nclips > 16)
+		vv->ov.nclips = 16;
+	if (copy_from_user(vv->ov.clips, f->fmt.win.clips,
+				sizeof(struct v4l2_clip) * vv->ov.nclips)) {
+		return -EFAULT;
+	}
+
+	/* vv->ov.fh is used to indicate that we have valid overlay informations, too */
+	vv->ov.fh = fh;
+
+	/* check if our current overlay is active */
+	if (IS_OVERLAY_ACTIVE(fh) != 0) {
+		saa7146_stop_preview(fh);
+		saa7146_start_preview(fh);
+	}
+	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;
+		if (e->index < 0 )
+			return -EINVAL;
+		if( e->index < dev->ext_vv_data->num_stds ) {
+			DEB_EE("VIDIOC_ENUMSTD: index:%d\n", e->index);
+			v4l2_video_std_construct(e, dev->ext_vv_data->stds[e->index].id, dev->ext_vv_data->stds[e->index].name);
+			return 0;
+		}
+		return -EINVAL;
+	}
+	*/
+
+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;
+
+	DEB_EE("VIDIOC_S_STD\n");
+
+	if ((vv->video_status & STATUS_CAPTURE) == STATUS_CAPTURE) {
+		DEB_D("cannot change video standard while streaming capture is active\n");
+		return -EBUSY;
+	}
+
+	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;
+		}
+	}
+
+	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;
+	}
+
+	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) {
+		if (v4l2_chip_match_host(&chip->match))
+			chip->ident = V4L2_IDENT_SAA7146;
+		return 0;
+	}
+	if (chip->match.type != V4L2_CHIP_MATCH_I2C_DRIVER &&
+	    chip->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
+		return -EINVAL;
+	return v4l2_device_call_until_err(&dev->v4l2_dev, 0,
+			core, g_chip_ident, chip);
+}
+
+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_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_streamon             = vidioc_streamon,
+	.vidioc_streamoff            = vidioc_streamoff,
+	.vidioc_g_parm 		     = vidioc_g_parm,
+	.vidioc_subscribe_event      = v4l2_ctrl_subscribe_event,
+	.vidioc_unsubscribe_event    = v4l2_event_unsubscribe,
+};
+
+const struct v4l2_ioctl_ops saa7146_vbi_ioctl_ops = {
+	.vidioc_querycap             = vidioc_querycap,
+	.vidioc_g_fmt_vbi_cap        = vidioc_g_fmt_vbi_cap,
+	.vidioc_g_chip_ident         = vidioc_g_chip_ident,
+
+	.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_streamon             = vidioc_streamon,
+	.vidioc_streamoff            = vidioc_streamoff,
+	.vidioc_g_parm		     = vidioc_g_parm,
+	.vidioc_subscribe_event      = v4l2_ctrl_subscribe_event,
+	.vidioc_unsubscribe_event    = v4l2_event_unsubscribe,
+};
+
+/*********************************************************************************/
+/* buffer handling functions                                                  */
+
+static int buffer_activate (struct saa7146_dev *dev,
+		     struct saa7146_buf *buf,
+		     struct saa7146_buf *next)
+{
+	struct saa7146_vv *vv = dev->vv_data;
+
+	buf->vb.state = VIDEOBUF_ACTIVE;
+	saa7146_set_capture(dev,buf,next);
+
+	mod_timer(&vv->video_dmaq.timeout, jiffies+BUFFER_TIMEOUT);
+	return 0;
+}
+
+static void release_all_pagetables(struct saa7146_dev *dev, struct saa7146_buf *buf)
+{
+	saa7146_pgtable_free(dev->pci, &buf->pt[0]);
+	saa7146_pgtable_free(dev->pci, &buf->pt[1]);
+	saa7146_pgtable_free(dev->pci, &buf->pt[2]);
+}
+
+static int buffer_prepare(struct videobuf_queue *q,
+			  struct videobuf_buffer *vb, enum v4l2_field field)
+{
+	struct file *file = q->priv_data;
+	struct saa7146_fh *fh = file->private_data;
+	struct saa7146_dev *dev = fh->dev;
+	struct saa7146_vv *vv = dev->vv_data;
+	struct saa7146_buf *buf = (struct saa7146_buf *)vb;
+	int size,err = 0;
+
+	DEB_CAP("vbuf:%p\n", vb);
+
+	/* sanity checks */
+	if (vv->video_fmt.width  < 48 ||
+	    vv->video_fmt.height < 32 ||
+	    vv->video_fmt.width  > vv->standard->h_max_out ||
+	    vv->video_fmt.height > vv->standard->v_max_out) {
+		DEB_D("w (%d) / h (%d) out of bounds\n",
+		      vv->video_fmt.width, vv->video_fmt.height);
+		return -EINVAL;
+	}
+
+	size = vv->video_fmt.sizeimage;
+	if (0 != buf->vb.baddr && buf->vb.bsize < size) {
+		DEB_D("size mismatch\n");
+		return -EINVAL;
+	}
+
+	DEB_CAP("buffer_prepare [size=%dx%d,bytes=%d,fields=%s]\n",
+		vv->video_fmt.width, vv->video_fmt.height,
+		size, v4l2_field_names[vv->video_fmt.field]);
+	if (buf->vb.width  != vv->video_fmt.width  ||
+	    buf->vb.bytesperline != vv->video_fmt.bytesperline ||
+	    buf->vb.height != vv->video_fmt.height ||
+	    buf->vb.size   != size ||
+	    buf->vb.field  != field      ||
+	    buf->vb.field  != vv->video_fmt.field  ||
+	    buf->fmt       != &vv->video_fmt) {
+		saa7146_dma_free(dev,q,buf);
+	}
+
+	if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
+		struct saa7146_format *sfmt;
+
+		buf->vb.bytesperline  = vv->video_fmt.bytesperline;
+		buf->vb.width  = vv->video_fmt.width;
+		buf->vb.height = vv->video_fmt.height;
+		buf->vb.size   = size;
+		buf->vb.field  = field;
+		buf->fmt       = &vv->video_fmt;
+		buf->vb.field  = vv->video_fmt.field;
+
+		sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat);
+
+		release_all_pagetables(dev, buf);
+		if( 0 != IS_PLANAR(sfmt->trans)) {
+			saa7146_pgtable_alloc(dev->pci, &buf->pt[0]);
+			saa7146_pgtable_alloc(dev->pci, &buf->pt[1]);
+			saa7146_pgtable_alloc(dev->pci, &buf->pt[2]);
+		} else {
+			saa7146_pgtable_alloc(dev->pci, &buf->pt[0]);
+		}
+
+		err = videobuf_iolock(q,&buf->vb, &vv->ov_fb);
+		if (err)
+			goto oops;
+		err = saa7146_pgtable_build(dev,buf);
+		if (err)
+			goto oops;
+	}
+	buf->vb.state = VIDEOBUF_PREPARED;
+	buf->activate = buffer_activate;
+
+	return 0;
+
+ oops:
+	DEB_D("error out\n");
+	saa7146_dma_free(dev,q,buf);
+
+	return err;
+}
+
+static int buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
+{
+	struct file *file = q->priv_data;
+	struct saa7146_fh *fh = file->private_data;
+	struct saa7146_vv *vv = fh->dev->vv_data;
+
+	if (0 == *count || *count > MAX_SAA7146_CAPTURE_BUFFERS)
+		*count = MAX_SAA7146_CAPTURE_BUFFERS;
+
+	*size = vv->video_fmt.sizeimage;
+
+	/* check if we exceed the "max_memory" parameter */
+	if( (*count * *size) > (max_memory*1048576) ) {
+		*count = (max_memory*1048576) / *size;
+	}
+
+	DEB_CAP("%d buffers, %d bytes each\n", *count, *size);
+
+	return 0;
+}
+
+static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
+{
+	struct file *file = q->priv_data;
+	struct saa7146_fh *fh = file->private_data;
+	struct saa7146_dev *dev = fh->dev;
+	struct saa7146_vv *vv = dev->vv_data;
+	struct saa7146_buf *buf = (struct saa7146_buf *)vb;
+
+	DEB_CAP("vbuf:%p\n", vb);
+	saa7146_buffer_queue(fh->dev, &vv->video_dmaq, buf);
+}
+
+static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
+{
+	struct file *file = q->priv_data;
+	struct saa7146_fh *fh = file->private_data;
+	struct saa7146_dev *dev = fh->dev;
+	struct saa7146_buf *buf = (struct saa7146_buf *)vb;
+
+	DEB_CAP("vbuf:%p\n", vb);
+
+	saa7146_dma_free(dev,q,buf);
+
+	release_all_pagetables(dev, buf);
+}
+
+static struct videobuf_queue_ops video_qops = {
+	.buf_setup    = buffer_setup,
+	.buf_prepare  = buffer_prepare,
+	.buf_queue    = buffer_queue,
+	.buf_release  = buffer_release,
+};
+
+/********************************************************************************/
+/* file operations */
+
+static void video_init(struct saa7146_dev *dev, struct saa7146_vv *vv)
+{
+	INIT_LIST_HEAD(&vv->video_dmaq.queue);
+
+	init_timer(&vv->video_dmaq.timeout);
+	vv->video_dmaq.timeout.function = saa7146_buffer_timeout;
+	vv->video_dmaq.timeout.data     = (unsigned long)(&vv->video_dmaq);
+	vv->video_dmaq.dev              = dev;
+
+	/* set some default values */
+	vv->standard = &dev->ext_vv_data->stds[0];
+
+	/* FIXME: what's this? */
+	vv->current_hps_source = SAA7146_HPS_SOURCE_PORT_A;
+	vv->current_hps_sync = SAA7146_HPS_SYNC_PORT_A;
+}
+
+
+static int video_open(struct saa7146_dev *dev, struct file *file)
+{
+	struct saa7146_fh *fh = file->private_data;
+
+	videobuf_queue_sg_init(&fh->video_q, &video_qops,
+			    &dev->pci->dev, &dev->slock,
+			    V4L2_BUF_TYPE_VIDEO_CAPTURE,
+			    V4L2_FIELD_INTERLACED,
+			    sizeof(struct saa7146_buf),
+			    file, &dev->v4l2_lock);
+
+	return 0;
+}
+
+
+static void video_close(struct saa7146_dev *dev, struct file *file)
+{
+	struct saa7146_fh *fh = file->private_data;
+	struct saa7146_vv *vv = dev->vv_data;
+	struct videobuf_queue *q = &fh->video_q;
+
+	if (IS_CAPTURE_ACTIVE(fh) != 0)
+		video_end(fh, file);
+	else if (IS_OVERLAY_ACTIVE(fh) != 0)
+		saa7146_stop_preview(fh);
+
+	videobuf_stop(q);
+	/* hmm, why is this function declared void? */
+}
+
+
+static void video_irq_done(struct saa7146_dev *dev, unsigned long st)
+{
+	struct saa7146_vv *vv = dev->vv_data;
+	struct saa7146_dmaqueue *q = &vv->video_dmaq;
+
+	spin_lock(&dev->slock);
+	DEB_CAP("called\n");
+
+	/* only finish the buffer if we have one... */
+	if( NULL != q->curr ) {
+		saa7146_buffer_finish(dev,q,VIDEOBUF_DONE);
+	}
+	saa7146_buffer_next(dev,q,0);
+
+	spin_unlock(&dev->slock);
+}
+
+static ssize_t video_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
+{
+	struct saa7146_fh *fh = file->private_data;
+	struct saa7146_dev *dev = fh->dev;
+	struct saa7146_vv *vv = dev->vv_data;
+	ssize_t ret = 0;
+
+	DEB_EE("called\n");
+
+	if ((vv->video_status & STATUS_CAPTURE) != 0) {
+		/* fixme: should we allow read() captures while streaming capture? */
+		if (vv->video_fh == fh) {
+			DEB_S("already capturing\n");
+			return -EBUSY;
+		}
+		DEB_S("already capturing in another open\n");
+		return -EBUSY;
+	}
+
+	ret = video_begin(fh);
+	if( 0 != ret) {
+		goto out;
+	}
+
+	ret = videobuf_read_one(&fh->video_q , data, count, ppos,
+				file->f_flags & O_NONBLOCK);
+	if (ret != 0) {
+		video_end(fh, file);
+	} else {
+		ret = video_end(fh, file);
+	}
+out:
+	/* restart overlay if it was active before */
+	if (vv->ov_suspend != NULL) {
+		saa7146_start_preview(vv->ov_suspend);
+		vv->ov_suspend = NULL;
+	}
+
+	return ret;
+}
+
+struct saa7146_use_ops saa7146_video_uops = {
+	.init = video_init,
+	.open = video_open,
+	.release = video_close,
+	.irq_done = video_irq_done,
+	.read = video_read,
+};
diff --git a/drivers/media/common/saa7146_core.c b/drivers/media/common/saa7146_core.c
deleted file mode 100644
index d6b1cf6..0000000
--- a/drivers/media/common/saa7146_core.c
+++ /dev/null
@@ -1,600 +0,0 @@
-/*
-    saa7146.o - driver for generic saa7146-based hardware
-
-    Copyright (C) 1998-2003 Michael Hunold <michael@mihu.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.
-*/
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <media/saa7146.h>
-#include <linux/module.h>
-
-LIST_HEAD(saa7146_devices);
-DEFINE_MUTEX(saa7146_devices_lock);
-
-static int saa7146_num;
-
-unsigned int saa7146_debug;
-
-module_param(saa7146_debug, uint, 0644);
-MODULE_PARM_DESC(saa7146_debug, "debug level (default: 0)");
-
-#if 0
-static void dump_registers(struct saa7146_dev* dev)
-{
-	int i = 0;
-
-	pr_info(" @ %li jiffies:\n", jiffies);
-	for (i = 0; i <= 0x148; i += 4)
-		pr_info("0x%03x: 0x%08x\n", i, saa7146_read(dev, i));
-}
-#endif
-
-/****************************************************************************
- * gpio and debi helper functions
- ****************************************************************************/
-
-void saa7146_setgpio(struct saa7146_dev *dev, int port, u32 data)
-{
-	u32 value = 0;
-
-	BUG_ON(port > 3);
-
-	value = saa7146_read(dev, GPIO_CTRL);
-	value &= ~(0xff << (8*port));
-	value |= (data << (8*port));
-	saa7146_write(dev, GPIO_CTRL, value);
-}
-
-/* This DEBI code is based on the saa7146 Stradis driver by Nathan Laredo */
-static inline int saa7146_wait_for_debi_done_sleep(struct saa7146_dev *dev,
-				unsigned long us1, unsigned long us2)
-{
-	unsigned long timeout;
-	int err;
-
-	/* wait for registers to be programmed */
-	timeout = jiffies + usecs_to_jiffies(us1);
-	while (1) {
-		err = time_after(jiffies, timeout);
-		if (saa7146_read(dev, MC2) & 2)
-			break;
-		if (err) {
-			pr_err("%s: %s timed out while waiting for registers getting programmed\n",
-			       dev->name, __func__);
-			return -ETIMEDOUT;
-		}
-		msleep(1);
-	}
-
-	/* wait for transfer to complete */
-	timeout = jiffies + usecs_to_jiffies(us2);
-	while (1) {
-		err = time_after(jiffies, timeout);
-		if (!(saa7146_read(dev, PSR) & SPCI_DEBI_S))
-			break;
-		saa7146_read(dev, MC2);
-		if (err) {
-			DEB_S("%s: %s timed out while waiting for transfer completion\n",
-			      dev->name, __func__);
-			return -ETIMEDOUT;
-		}
-		msleep(1);
-	}
-
-	return 0;
-}
-
-static inline int saa7146_wait_for_debi_done_busyloop(struct saa7146_dev *dev,
-				unsigned long us1, unsigned long us2)
-{
-	unsigned long loops;
-
-	/* wait for registers to be programmed */
-	loops = us1;
-	while (1) {
-		if (saa7146_read(dev, MC2) & 2)
-			break;
-		if (!loops--) {
-			pr_err("%s: %s timed out while waiting for registers getting programmed\n",
-			       dev->name, __func__);
-			return -ETIMEDOUT;
-		}
-		udelay(1);
-	}
-
-	/* wait for transfer to complete */
-	loops = us2 / 5;
-	while (1) {
-		if (!(saa7146_read(dev, PSR) & SPCI_DEBI_S))
-			break;
-		saa7146_read(dev, MC2);
-		if (!loops--) {
-			DEB_S("%s: %s timed out while waiting for transfer completion\n",
-			      dev->name, __func__);
-			return -ETIMEDOUT;
-		}
-		udelay(5);
-	}
-
-	return 0;
-}
-
-int saa7146_wait_for_debi_done(struct saa7146_dev *dev, int nobusyloop)
-{
-	if (nobusyloop)
-		return saa7146_wait_for_debi_done_sleep(dev, 50000, 250000);
-	else
-		return saa7146_wait_for_debi_done_busyloop(dev, 50000, 250000);
-}
-
-/****************************************************************************
- * general helper functions
- ****************************************************************************/
-
-/* this is videobuf_vmalloc_to_sg() from videobuf-dma-sg.c
-   make sure virt has been allocated with vmalloc_32(), otherwise the BUG()
-   may be triggered on highmem machines */
-static struct scatterlist* vmalloc_to_sg(unsigned char *virt, int nr_pages)
-{
-	struct scatterlist *sglist;
-	struct page *pg;
-	int i;
-
-	sglist = kcalloc(nr_pages, sizeof(struct scatterlist), GFP_KERNEL);
-	if (NULL == sglist)
-		return NULL;
-	sg_init_table(sglist, nr_pages);
-	for (i = 0; i < nr_pages; i++, virt += PAGE_SIZE) {
-		pg = vmalloc_to_page(virt);
-		if (NULL == pg)
-			goto err;
-		BUG_ON(PageHighMem(pg));
-		sg_set_page(&sglist[i], pg, PAGE_SIZE, 0);
-	}
-	return sglist;
-
- err:
-	kfree(sglist);
-	return NULL;
-}
-
-/********************************************************************************/
-/* common page table functions */
-
-void *saa7146_vmalloc_build_pgtable(struct pci_dev *pci, long length, struct saa7146_pgtable *pt)
-{
-	int pages = (length+PAGE_SIZE-1)/PAGE_SIZE;
-	void *mem = vmalloc_32(length);
-	int slen = 0;
-
-	if (NULL == mem)
-		goto err_null;
-
-	if (!(pt->slist = vmalloc_to_sg(mem, pages)))
-		goto err_free_mem;
-
-	if (saa7146_pgtable_alloc(pci, pt))
-		goto err_free_slist;
-
-	pt->nents = pages;
-	slen = pci_map_sg(pci,pt->slist,pt->nents,PCI_DMA_FROMDEVICE);
-	if (0 == slen)
-		goto err_free_pgtable;
-
-	if (0 != saa7146_pgtable_build_single(pci, pt, pt->slist, slen))
-		goto err_unmap_sg;
-
-	return mem;
-
-err_unmap_sg:
-	pci_unmap_sg(pci, pt->slist, pt->nents, PCI_DMA_FROMDEVICE);
-err_free_pgtable:
-	saa7146_pgtable_free(pci, pt);
-err_free_slist:
-	kfree(pt->slist);
-	pt->slist = NULL;
-err_free_mem:
-	vfree(mem);
-err_null:
-	return NULL;
-}
-
-void saa7146_vfree_destroy_pgtable(struct pci_dev *pci, void *mem, struct saa7146_pgtable *pt)
-{
-	pci_unmap_sg(pci, pt->slist, pt->nents, PCI_DMA_FROMDEVICE);
-	saa7146_pgtable_free(pci, pt);
-	kfree(pt->slist);
-	pt->slist = NULL;
-	vfree(mem);
-}
-
-void saa7146_pgtable_free(struct pci_dev *pci, struct saa7146_pgtable *pt)
-{
-	if (NULL == pt->cpu)
-		return;
-	pci_free_consistent(pci, pt->size, pt->cpu, pt->dma);
-	pt->cpu = NULL;
-}
-
-int saa7146_pgtable_alloc(struct pci_dev *pci, struct saa7146_pgtable *pt)
-{
-	__le32       *cpu;
-	dma_addr_t   dma_addr = 0;
-
-	cpu = pci_alloc_consistent(pci, PAGE_SIZE, &dma_addr);
-	if (NULL == cpu) {
-		return -ENOMEM;
-	}
-	pt->size = PAGE_SIZE;
-	pt->cpu  = cpu;
-	pt->dma  = dma_addr;
-
-	return 0;
-}
-
-int saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *pt,
-	struct scatterlist *list, int sglen  )
-{
-	__le32 *ptr, fill;
-	int nr_pages = 0;
-	int i,p;
-
-	BUG_ON(0 == sglen);
-	BUG_ON(list->offset > PAGE_SIZE);
-
-	/* if we have a user buffer, the first page may not be
-	   aligned to a page boundary. */
-	pt->offset = list->offset;
-
-	ptr = pt->cpu;
-	for (i = 0; i < sglen; i++, list++) {
-/*
-		pr_debug("i:%d, adr:0x%08x, len:%d, offset:%d\n",
-			 i, sg_dma_address(list), sg_dma_len(list),
-			 list->offset);
-*/
-		for (p = 0; p * 4096 < list->length; p++, ptr++) {
-			*ptr = cpu_to_le32(sg_dma_address(list) + p * 4096);
-			nr_pages++;
-		}
-	}
-
-
-	/* safety; fill the page table up with the last valid page */
-	fill = *(ptr-1);
-	for(i=nr_pages;i<1024;i++) {
-		*ptr++ = fill;
-	}
-
-/*
-	ptr = pt->cpu;
-	pr_debug("offset: %d\n", pt->offset);
-	for(i=0;i<5;i++) {
-		pr_debug("ptr1 %d: 0x%08x\n", i, ptr[i]);
-	}
-*/
-	return 0;
-}
-
-/********************************************************************************/
-/* interrupt handler */
-static irqreturn_t interrupt_hw(int irq, void *dev_id)
-{
-	struct saa7146_dev *dev = dev_id;
-	u32 isr;
-	u32 ack_isr;
-
-	/* read out the interrupt status register */
-	ack_isr = isr = saa7146_read(dev, ISR);
-
-	/* is this our interrupt? */
-	if ( 0 == isr ) {
-		/* nope, some other device */
-		return IRQ_NONE;
-	}
-
-	if (dev->ext) {
-		if (dev->ext->irq_mask & isr) {
-			if (dev->ext->irq_func)
-				dev->ext->irq_func(dev, &isr);
-			isr &= ~dev->ext->irq_mask;
-		}
-	}
-	if (0 != (isr & (MASK_27))) {
-		DEB_INT("irq: RPS0 (0x%08x)\n", isr);
-		if (dev->vv_data && dev->vv_callback)
-			dev->vv_callback(dev,isr);
-		isr &= ~MASK_27;
-	}
-	if (0 != (isr & (MASK_28))) {
-		if (dev->vv_data && dev->vv_callback)
-			dev->vv_callback(dev,isr);
-		isr &= ~MASK_28;
-	}
-	if (0 != (isr & (MASK_16|MASK_17))) {
-		SAA7146_IER_DISABLE(dev, MASK_16|MASK_17);
-		/* only wake up if we expect something */
-		if (0 != dev->i2c_op) {
-			dev->i2c_op = 0;
-			wake_up(&dev->i2c_wq);
-		} else {
-			u32 psr = saa7146_read(dev, PSR);
-			u32 ssr = saa7146_read(dev, SSR);
-			pr_warn("%s: unexpected i2c irq: isr %08x psr %08x ssr %08x\n",
-				dev->name, isr, psr, ssr);
-		}
-		isr &= ~(MASK_16|MASK_17);
-	}
-	if( 0 != isr ) {
-		ERR("warning: interrupt enabled, but not handled properly.(0x%08x)\n",
-		    isr);
-		ERR("disabling interrupt source(s)!\n");
-		SAA7146_IER_DISABLE(dev,isr);
-	}
-	saa7146_write(dev, ISR, ack_isr);
-	return IRQ_HANDLED;
-}
-
-/*********************************************************************************/
-/* configuration-functions                                                       */
-
-static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent)
-{
-	struct saa7146_pci_extension_data *pci_ext = (struct saa7146_pci_extension_data *)ent->driver_data;
-	struct saa7146_extension *ext = pci_ext->ext;
-	struct saa7146_dev *dev;
-	int err = -ENOMEM;
-
-	/* clear out mem for sure */
-	dev = kzalloc(sizeof(struct saa7146_dev), GFP_KERNEL);
-	if (!dev) {
-		ERR("out of memory\n");
-		goto out;
-	}
-
-	DEB_EE("pci:%p\n", pci);
-
-	err = pci_enable_device(pci);
-	if (err < 0) {
-		ERR("pci_enable_device() failed\n");
-		goto err_free;
-	}
-
-	/* enable bus-mastering */
-	pci_set_master(pci);
-
-	dev->pci = pci;
-
-	/* get chip-revision; this is needed to enable bug-fixes */
-	dev->revision = pci->revision;
-
-	/* remap the memory from virtual to physical address */
-
-	err = pci_request_region(pci, 0, "saa7146");
-	if (err < 0)
-		goto err_disable;
-
-	dev->mem = ioremap(pci_resource_start(pci, 0),
-			   pci_resource_len(pci, 0));
-	if (!dev->mem) {
-		ERR("ioremap() failed\n");
-		err = -ENODEV;
-		goto err_release;
-	}
-
-	/* we don't do a master reset here anymore, it screws up
-	   some boards that don't have an i2c-eeprom for configuration
-	   values */
-/*
-	saa7146_write(dev, MC1, MASK_31);
-*/
-
-	/* disable all irqs */
-	saa7146_write(dev, IER, 0);
-
-	/* shut down all dma transfers and rps tasks */
-	saa7146_write(dev, MC1, 0x30ff0000);
-
-	/* clear out any rps-signals pending */
-	saa7146_write(dev, MC2, 0xf8000000);
-
-	/* request an interrupt for the saa7146 */
-	err = request_irq(pci->irq, interrupt_hw, IRQF_SHARED | IRQF_DISABLED,
-			  dev->name, dev);
-	if (err < 0) {
-		ERR("request_irq() failed\n");
-		goto err_unmap;
-	}
-
-	err = -ENOMEM;
-
-	/* get memory for various stuff */
-	dev->d_rps0.cpu_addr = pci_alloc_consistent(pci, SAA7146_RPS_MEM,
-						    &dev->d_rps0.dma_handle);
-	if (!dev->d_rps0.cpu_addr)
-		goto err_free_irq;
-	memset(dev->d_rps0.cpu_addr, 0x0, SAA7146_RPS_MEM);
-
-	dev->d_rps1.cpu_addr = pci_alloc_consistent(pci, SAA7146_RPS_MEM,
-						    &dev->d_rps1.dma_handle);
-	if (!dev->d_rps1.cpu_addr)
-		goto err_free_rps0;
-	memset(dev->d_rps1.cpu_addr, 0x0, SAA7146_RPS_MEM);
-
-	dev->d_i2c.cpu_addr = pci_alloc_consistent(pci, SAA7146_RPS_MEM,
-						   &dev->d_i2c.dma_handle);
-	if (!dev->d_i2c.cpu_addr)
-		goto err_free_rps1;
-	memset(dev->d_i2c.cpu_addr, 0x0, SAA7146_RPS_MEM);
-
-	/* the rest + print status message */
-
-	/* create a nice device name */
-	sprintf(dev->name, "saa7146 (%d)", saa7146_num);
-
-	pr_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;
-
-	mutex_init(&dev->v4l2_lock);
-	spin_lock_init(&dev->int_slock);
-	spin_lock_init(&dev->slock);
-
-	mutex_init(&dev->i2c_lock);
-
-	dev->module = THIS_MODULE;
-	init_waitqueue_head(&dev->i2c_wq);
-
-	/* set some sane pci arbitrition values */
-	saa7146_write(dev, PCI_BT_V1, 0x1c00101f);
-
-	/* TODO: use the status code of the callback */
-
-	err = -ENODEV;
-
-	if (ext->probe && ext->probe(dev)) {
-		DEB_D("ext->probe() failed for %p. skipping device.\n", dev);
-		goto err_free_i2c;
-	}
-
-	if (ext->attach(dev, pci_ext)) {
-		DEB_D("ext->attach() failed for %p. skipping device.\n", dev);
-		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);
-	saa7146_num++;
-
-	err = 0;
-out:
-	return err;
-
-err_free_i2c:
-	pci_free_consistent(pci, SAA7146_RPS_MEM, dev->d_i2c.cpu_addr,
-			    dev->d_i2c.dma_handle);
-err_free_rps1:
-	pci_free_consistent(pci, SAA7146_RPS_MEM, dev->d_rps1.cpu_addr,
-			    dev->d_rps1.dma_handle);
-err_free_rps0:
-	pci_free_consistent(pci, SAA7146_RPS_MEM, dev->d_rps0.cpu_addr,
-			    dev->d_rps0.dma_handle);
-err_free_irq:
-	free_irq(pci->irq, (void *)dev);
-err_unmap:
-	iounmap(dev->mem);
-err_release:
-	pci_release_region(pci, 0);
-err_disable:
-	pci_disable_device(pci);
-err_free:
-	kfree(dev);
-	goto out;
-}
-
-static void saa7146_remove_one(struct pci_dev *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;
-	} dev_map[] = {
-		{ dev->d_i2c.cpu_addr, dev->d_i2c.dma_handle },
-		{ dev->d_rps1.cpu_addr, dev->d_rps1.dma_handle },
-		{ dev->d_rps0.cpu_addr, dev->d_rps0.dma_handle },
-		{ NULL, 0 }
-	}, *p;
-
-	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);
-
-	/* disable all irqs, release irq-routine */
-	saa7146_write(dev, IER, 0);
-
-	free_irq(pdev->irq, dev);
-
-	for (p = dev_map; p->addr; p++)
-		pci_free_consistent(pdev, SAA7146_RPS_MEM, p->addr, p->dma);
-
-	iounmap(dev->mem);
-	pci_release_region(pdev, 0);
-	list_del(&dev->item);
-	pci_disable_device(pdev);
-	kfree(dev);
-
-	saa7146_num--;
-}
-
-/*********************************************************************************/
-/* extension handling functions                                                  */
-
-int saa7146_register_extension(struct saa7146_extension* ext)
-{
-	DEB_EE("ext:%p\n", ext);
-
-	ext->driver.name = ext->name;
-	ext->driver.id_table = ext->pci_tbl;
-	ext->driver.probe = saa7146_init_one;
-	ext->driver.remove = saa7146_remove_one;
-
-	pr_info("register extension '%s'\n", ext->name);
-	return pci_register_driver(&ext->driver);
-}
-
-int saa7146_unregister_extension(struct saa7146_extension* ext)
-{
-	DEB_EE("ext:%p\n", ext);
-	pr_info("unregister extension '%s'\n", ext->name);
-	pci_unregister_driver(&ext->driver);
-	return 0;
-}
-
-EXPORT_SYMBOL_GPL(saa7146_register_extension);
-EXPORT_SYMBOL_GPL(saa7146_unregister_extension);
-
-/* misc functions used by extension modules */
-EXPORT_SYMBOL_GPL(saa7146_pgtable_alloc);
-EXPORT_SYMBOL_GPL(saa7146_pgtable_free);
-EXPORT_SYMBOL_GPL(saa7146_pgtable_build_single);
-EXPORT_SYMBOL_GPL(saa7146_vmalloc_build_pgtable);
-EXPORT_SYMBOL_GPL(saa7146_vfree_destroy_pgtable);
-EXPORT_SYMBOL_GPL(saa7146_wait_for_debi_done);
-
-EXPORT_SYMBOL_GPL(saa7146_setgpio);
-
-EXPORT_SYMBOL_GPL(saa7146_i2c_adapter_prepare);
-
-EXPORT_SYMBOL_GPL(saa7146_debug);
-EXPORT_SYMBOL_GPL(saa7146_devices);
-EXPORT_SYMBOL_GPL(saa7146_devices_lock);
-
-MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
-MODULE_DESCRIPTION("driver for generic saa7146-based hardware");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c
deleted file mode 100644
index 0cdbd74..0000000
--- a/drivers/media/common/saa7146_fops.c
+++ /dev/null
@@ -1,641 +0,0 @@
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <media/saa7146_vv.h>
-#include <linux/module.h>
-
-/****************************************************************************/
-/* resource management functions, shamelessly stolen from saa7134 driver */
-
-int saa7146_res_get(struct saa7146_fh *fh, unsigned int bit)
-{
-	struct saa7146_dev *dev = fh->dev;
-	struct saa7146_vv *vv = dev->vv_data;
-
-	if (fh->resources & bit) {
-		DEB_D("already allocated! want: 0x%02x, cur:0x%02x\n",
-		      bit, vv->resources);
-		/* have it already allocated */
-		return 1;
-	}
-
-	/* is it free? */
-	if (vv->resources & bit) {
-		DEB_D("locked! vv->resources:0x%02x, we want:0x%02x\n",
-		      vv->resources, bit);
-		/* no, someone else uses it */
-		return 0;
-	}
-	/* it's free, grab it */
-	fh->resources |= bit;
-	vv->resources |= bit;
-	DEB_D("res: get 0x%02x, cur:0x%02x\n", bit, vv->resources);
-	return 1;
-}
-
-void saa7146_res_free(struct saa7146_fh *fh, unsigned int bits)
-{
-	struct saa7146_dev *dev = fh->dev;
-	struct saa7146_vv *vv = dev->vv_data;
-
-	BUG_ON((fh->resources & bits) != bits);
-
-	fh->resources &= ~bits;
-	vv->resources &= ~bits;
-	DEB_D("res: put 0x%02x, cur:0x%02x\n", bits, vv->resources);
-}
-
-
-/********************************************************************************/
-/* common dma functions */
-
-void saa7146_dma_free(struct saa7146_dev *dev,struct videobuf_queue *q,
-						struct saa7146_buf *buf)
-{
-	struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
-	DEB_EE("dev:%p, buf:%p\n", dev, buf);
-
-	BUG_ON(in_interrupt());
-
-	videobuf_waiton(q, &buf->vb, 0, 0);
-	videobuf_dma_unmap(q->dev, dma);
-	videobuf_dma_free(dma);
-	buf->vb.state = VIDEOBUF_NEEDS_INIT;
-}
-
-
-/********************************************************************************/
-/* common buffer functions */
-
-int saa7146_buffer_queue(struct saa7146_dev *dev,
-			 struct saa7146_dmaqueue *q,
-			 struct saa7146_buf *buf)
-{
-	assert_spin_locked(&dev->slock);
-	DEB_EE("dev:%p, dmaq:%p, buf:%p\n", dev, q, buf);
-
-	BUG_ON(!q);
-
-	if (NULL == q->curr) {
-		q->curr = buf;
-		DEB_D("immediately activating buffer %p\n", buf);
-		buf->activate(dev,buf,NULL);
-	} else {
-		list_add_tail(&buf->vb.queue,&q->queue);
-		buf->vb.state = VIDEOBUF_QUEUED;
-		DEB_D("adding buffer %p to queue. (active buffer present)\n",
-		      buf);
-	}
-	return 0;
-}
-
-void saa7146_buffer_finish(struct saa7146_dev *dev,
-			   struct saa7146_dmaqueue *q,
-			   int state)
-{
-	assert_spin_locked(&dev->slock);
-	DEB_EE("dev:%p, dmaq:%p, state:%d\n", dev, q, state);
-	DEB_EE("q->curr:%p\n", q->curr);
-
-	BUG_ON(!q->curr);
-
-	/* finish current buffer */
-	if (NULL == q->curr) {
-		DEB_D("aiii. no current buffer\n");
-		return;
-	}
-
-	q->curr->vb.state = state;
-	do_gettimeofday(&q->curr->vb.ts);
-	wake_up(&q->curr->vb.done);
-
-	q->curr = NULL;
-}
-
-void saa7146_buffer_next(struct saa7146_dev *dev,
-			 struct saa7146_dmaqueue *q, int vbi)
-{
-	struct saa7146_buf *buf,*next = NULL;
-
-	BUG_ON(!q);
-
-	DEB_INT("dev:%p, dmaq:%p, vbi:%d\n", dev, q, vbi);
-
-	assert_spin_locked(&dev->slock);
-	if (!list_empty(&q->queue)) {
-		/* activate next one from queue */
-		buf = list_entry(q->queue.next,struct saa7146_buf,vb.queue);
-		list_del(&buf->vb.queue);
-		if (!list_empty(&q->queue))
-			next = list_entry(q->queue.next,struct saa7146_buf, vb.queue);
-		q->curr = buf;
-		DEB_INT("next buffer: buf:%p, prev:%p, next:%p\n",
-			buf, q->queue.prev, q->queue.next);
-		buf->activate(dev,buf,next);
-	} else {
-		DEB_INT("no next buffer. stopping.\n");
-		if( 0 != vbi ) {
-			/* turn off video-dma3 */
-			saa7146_write(dev,MC1, MASK_20);
-		} else {
-			/* nothing to do -- just prevent next video-dma1 transfer
-			   by lowering the protection address */
-
-			// fixme: fix this for vflip != 0
-
-			saa7146_write(dev, PROT_ADDR1, 0);
-			saa7146_write(dev, MC2, (MASK_02|MASK_18));
-
-			/* write the address of the rps-program */
-			saa7146_write(dev, RPS_ADDR0, dev->d_rps0.dma_handle);
-			/* turn on rps */
-			saa7146_write(dev, MC1, (MASK_12 | MASK_28));
-
-/*
-			printk("vdma%d.base_even:     0x%08x\n", 1,saa7146_read(dev,BASE_EVEN1));
-			printk("vdma%d.base_odd:      0x%08x\n", 1,saa7146_read(dev,BASE_ODD1));
-			printk("vdma%d.prot_addr:     0x%08x\n", 1,saa7146_read(dev,PROT_ADDR1));
-			printk("vdma%d.base_page:     0x%08x\n", 1,saa7146_read(dev,BASE_PAGE1));
-			printk("vdma%d.pitch:         0x%08x\n", 1,saa7146_read(dev,PITCH1));
-			printk("vdma%d.num_line_byte: 0x%08x\n", 1,saa7146_read(dev,NUM_LINE_BYTE1));
-*/
-		}
-		del_timer(&q->timeout);
-	}
-}
-
-void saa7146_buffer_timeout(unsigned long data)
-{
-	struct saa7146_dmaqueue *q = (struct saa7146_dmaqueue*)data;
-	struct saa7146_dev *dev = q->dev;
-	unsigned long flags;
-
-	DEB_EE("dev:%p, dmaq:%p\n", dev, q);
-
-	spin_lock_irqsave(&dev->slock,flags);
-	if (q->curr) {
-		DEB_D("timeout on %p\n", q->curr);
-		saa7146_buffer_finish(dev,q,VIDEOBUF_ERROR);
-	}
-
-	/* we don't restart the transfer here like other drivers do. when
-	   a streaming capture is disabled, the timeout function will be
-	   called for the current buffer. if we activate the next buffer now,
-	   we mess up our capture logic. if a timeout occurs on another buffer,
-	   then something is seriously broken before, so no need to buffer the
-	   next capture IMHO... */
-/*
-	saa7146_buffer_next(dev,q);
-*/
-	spin_unlock_irqrestore(&dev->slock,flags);
-}
-
-/********************************************************************************/
-/* file operations */
-
-static int fops_open(struct file *file)
-{
-	struct video_device *vdev = video_devdata(file);
-	struct saa7146_dev *dev = video_drvdata(file);
-	struct saa7146_fh *fh = NULL;
-	int result = 0;
-
-	DEB_EE("file:%p, dev:%s\n", file, video_device_node_name(vdev));
-
-	if (mutex_lock_interruptible(&saa7146_devices_lock))
-		return -ERESTARTSYS;
-
-	DEB_D("using: %p\n", dev);
-
-	/* check if an extension is registered */
-	if( NULL == dev->ext ) {
-		DEB_S("no extension registered for this device\n");
-		result = -ENODEV;
-		goto out;
-	}
-
-	/* allocate per open data */
-	fh = kzalloc(sizeof(*fh),GFP_KERNEL);
-	if (NULL == fh) {
-		DEB_S("cannot allocate memory for per open data\n");
-		result = -ENOMEM;
-		goto out;
-	}
-
-	v4l2_fh_init(&fh->fh, vdev);
-
-	file->private_data = &fh->fh;
-	fh->dev = dev;
-
-	if (vdev->vfl_type == VFL_TYPE_VBI) {
-		DEB_S("initializing vbi...\n");
-		if (dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE)
-			result = saa7146_vbi_uops.open(dev,file);
-		if (dev->ext_vv_data->vbi_fops.open)
-			dev->ext_vv_data->vbi_fops.open(file);
-	} else {
-		DEB_S("initializing video...\n");
-		result = saa7146_video_uops.open(dev,file);
-	}
-
-	if (0 != result) {
-		goto out;
-	}
-
-	if( 0 == try_module_get(dev->ext->module)) {
-		result = -EINVAL;
-		goto out;
-	}
-
-	result = 0;
-	v4l2_fh_add(&fh->fh);
-out:
-	if (fh && result != 0) {
-		kfree(fh);
-		file->private_data = NULL;
-	}
-	mutex_unlock(&saa7146_devices_lock);
-	return result;
-}
-
-static int fops_release(struct file *file)
-{
-	struct video_device *vdev = video_devdata(file);
-	struct saa7146_fh  *fh  = file->private_data;
-	struct saa7146_dev *dev = fh->dev;
-
-	DEB_EE("file:%p\n", file);
-
-	if (mutex_lock_interruptible(&saa7146_devices_lock))
-		return -ERESTARTSYS;
-
-	if (vdev->vfl_type == VFL_TYPE_VBI) {
-		if (dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE)
-			saa7146_vbi_uops.release(dev,file);
-		if (dev->ext_vv_data->vbi_fops.release)
-			dev->ext_vv_data->vbi_fops.release(file);
-	} else {
-		saa7146_video_uops.release(dev,file);
-	}
-
-	v4l2_fh_del(&fh->fh);
-	v4l2_fh_exit(&fh->fh);
-	module_put(dev->ext->module);
-	file->private_data = NULL;
-	kfree(fh);
-
-	mutex_unlock(&saa7146_devices_lock);
-
-	return 0;
-}
-
-static int fops_mmap(struct file *file, struct vm_area_struct * vma)
-{
-	struct video_device *vdev = video_devdata(file);
-	struct saa7146_fh *fh = file->private_data;
-	struct videobuf_queue *q;
-
-	switch (vdev->vfl_type) {
-	case VFL_TYPE_GRABBER: {
-		DEB_EE("V4L2_BUF_TYPE_VIDEO_CAPTURE: file:%p, vma:%p\n",
-		       file, vma);
-		q = &fh->video_q;
-		break;
-		}
-	case VFL_TYPE_VBI: {
-		DEB_EE("V4L2_BUF_TYPE_VBI_CAPTURE: file:%p, vma:%p\n",
-		       file, vma);
-		if (fh->dev->ext_vv_data->capabilities & V4L2_CAP_SLICED_VBI_OUTPUT)
-			return -ENODEV;
-		q = &fh->vbi_q;
-		break;
-		}
-	default:
-		BUG();
-		return 0;
-	}
-
-	return videobuf_mmap_mapper(q,vma);
-}
-
-static unsigned int fops_poll(struct file *file, struct poll_table_struct *wait)
-{
-	struct video_device *vdev = video_devdata(file);
-	struct saa7146_fh *fh = file->private_data;
-	struct videobuf_buffer *buf = NULL;
-	struct videobuf_queue *q;
-	unsigned int res = v4l2_ctrl_poll(file, wait);
-
-	DEB_EE("file:%p, poll:%p\n", file, wait);
-
-	if (vdev->vfl_type == VFL_TYPE_VBI) {
-		if (fh->dev->ext_vv_data->capabilities & V4L2_CAP_SLICED_VBI_OUTPUT)
-			return res | POLLOUT | POLLWRNORM;
-		if( 0 == fh->vbi_q.streaming )
-			return res | videobuf_poll_stream(file, &fh->vbi_q, wait);
-		q = &fh->vbi_q;
-	} else {
-		DEB_D("using video queue\n");
-		q = &fh->video_q;
-	}
-
-	if (!list_empty(&q->stream))
-		buf = list_entry(q->stream.next, struct videobuf_buffer, stream);
-
-	if (!buf) {
-		DEB_D("buf == NULL!\n");
-		return res | POLLERR;
-	}
-
-	poll_wait(file, &buf->done, wait);
-	if (buf->state == VIDEOBUF_DONE || buf->state == VIDEOBUF_ERROR) {
-		DEB_D("poll succeeded!\n");
-		return res | POLLIN | POLLRDNORM;
-	}
-
-	DEB_D("nothing to poll for, buf->state:%d\n", buf->state);
-	return res;
-}
-
-static ssize_t fops_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
-{
-	struct video_device *vdev = video_devdata(file);
-	struct saa7146_fh *fh = file->private_data;
-
-	switch (vdev->vfl_type) {
-	case VFL_TYPE_GRABBER:
-/*
-		DEB_EE("V4L2_BUF_TYPE_VIDEO_CAPTURE: file:%p, data:%p, count:%lun",
-		       file, data, (unsigned long)count);
-*/
-		return saa7146_video_uops.read(file,data,count,ppos);
-	case VFL_TYPE_VBI:
-/*
-		DEB_EE("V4L2_BUF_TYPE_VBI_CAPTURE: file:%p, data:%p, count:%lu\n",
-		       file, data, (unsigned long)count);
-*/
-		if (fh->dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE)
-			return saa7146_vbi_uops.read(file,data,count,ppos);
-		return -EINVAL;
-	default:
-		BUG();
-		return 0;
-	}
-}
-
-static ssize_t fops_write(struct file *file, const char __user *data, size_t count, loff_t *ppos)
-{
-	struct video_device *vdev = video_devdata(file);
-	struct saa7146_fh *fh = file->private_data;
-
-	switch (vdev->vfl_type) {
-	case VFL_TYPE_GRABBER:
-		return -EINVAL;
-	case VFL_TYPE_VBI:
-		if (fh->dev->ext_vv_data->vbi_fops.write)
-			return fh->dev->ext_vv_data->vbi_fops.write(file, data, count, ppos);
-		else
-			return -EINVAL;
-	default:
-		BUG();
-		return -EINVAL;
-	}
-}
-
-static const struct v4l2_file_operations video_fops =
-{
-	.owner		= THIS_MODULE,
-	.open		= fops_open,
-	.release	= fops_release,
-	.read		= fops_read,
-	.write		= fops_write,
-	.poll		= fops_poll,
-	.mmap		= fops_mmap,
-	.unlocked_ioctl	= video_ioctl2,
-};
-
-static void vv_callback(struct saa7146_dev *dev, unsigned long status)
-{
-	u32 isr = status;
-
-	DEB_INT("dev:%p, isr:0x%08x\n", dev, (u32)status);
-
-	if (0 != (isr & (MASK_27))) {
-		DEB_INT("irq: RPS0 (0x%08x)\n", isr);
-		saa7146_video_uops.irq_done(dev,isr);
-	}
-
-	if (0 != (isr & (MASK_28))) {
-		u32 mc2 = saa7146_read(dev, MC2);
-		if( 0 != (mc2 & MASK_15)) {
-			DEB_INT("irq: RPS1 vbi workaround (0x%08x)\n", isr);
-			wake_up(&dev->vv_data->vbi_wq);
-			saa7146_write(dev,MC2, MASK_31);
-			return;
-		}
-		DEB_INT("irq: RPS1 (0x%08x)\n", isr);
-		saa7146_vbi_uops.irq_done(dev,isr);
-	}
-}
-
-static const struct v4l2_ctrl_ops saa7146_ctrl_ops = {
-	.s_ctrl = saa7146_s_ctrl,
-};
-
-int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv)
-{
-	struct v4l2_ctrl_handler *hdl = &dev->ctrl_handler;
-	struct v4l2_pix_format *fmt;
-	struct v4l2_vbi_format *vbi;
-	struct saa7146_vv *vv;
-	int err;
-
-	err = v4l2_device_register(&dev->pci->dev, &dev->v4l2_dev);
-	if (err)
-		return err;
-
-	v4l2_ctrl_handler_init(hdl, 6);
-	v4l2_ctrl_new_std(hdl, &saa7146_ctrl_ops,
-		V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
-	v4l2_ctrl_new_std(hdl, &saa7146_ctrl_ops,
-		V4L2_CID_CONTRAST, 0, 127, 1, 64);
-	v4l2_ctrl_new_std(hdl, &saa7146_ctrl_ops,
-		V4L2_CID_SATURATION, 0, 127, 1, 64);
-	v4l2_ctrl_new_std(hdl, &saa7146_ctrl_ops,
-		V4L2_CID_VFLIP, 0, 1, 1, 0);
-	v4l2_ctrl_new_std(hdl, &saa7146_ctrl_ops,
-		V4L2_CID_HFLIP, 0, 1, 1, 0);
-	if (hdl->error) {
-		err = hdl->error;
-		v4l2_ctrl_handler_free(hdl);
-		return err;
-	}
-	dev->v4l2_dev.ctrl_handler = hdl;
-
-	vv = kzalloc(sizeof(struct saa7146_vv), GFP_KERNEL);
-	if (vv == NULL) {
-		ERR("out of memory. aborting.\n");
-		v4l2_ctrl_handler_free(hdl);
-		return -ENOMEM;
-	}
-	ext_vv->vid_ops = saa7146_video_ioctl_ops;
-	ext_vv->vbi_ops = saa7146_vbi_ioctl_ops;
-	ext_vv->core_ops = &saa7146_video_ioctl_ops;
-
-	DEB_EE("dev:%p\n", dev);
-
-	/* set default values for video parts of the saa7146 */
-	saa7146_write(dev, BCS_CTRL, 0x80400040);
-
-	/* enable video-port pins */
-	saa7146_write(dev, MC1, (MASK_10 | MASK_26));
-
-	/* save per-device extension data (one extension can
-	   handle different devices that might need different
-	   configuration data) */
-	dev->ext_vv_data = ext_vv;
-
-	vv->d_clipping.cpu_addr = pci_alloc_consistent(dev->pci, SAA7146_CLIPPING_MEM, &vv->d_clipping.dma_handle);
-	if( NULL == vv->d_clipping.cpu_addr ) {
-		ERR("out of memory. aborting.\n");
-		kfree(vv);
-		v4l2_ctrl_handler_free(hdl);
-		return -1;
-	}
-	memset(vv->d_clipping.cpu_addr, 0x0, SAA7146_CLIPPING_MEM);
-
-	saa7146_video_uops.init(dev,vv);
-	if (dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE)
-		saa7146_vbi_uops.init(dev,vv);
-
-	fmt = &vv->ov_fb.fmt;
-	fmt->width = vv->standard->h_max_out;
-	fmt->height = vv->standard->v_max_out;
-	fmt->pixelformat = V4L2_PIX_FMT_RGB565;
-	fmt->bytesperline = 2 * fmt->width;
-	fmt->sizeimage = fmt->bytesperline * fmt->height;
-	fmt->colorspace = V4L2_COLORSPACE_SRGB;
-
-	fmt = &vv->video_fmt;
-	fmt->width = 384;
-	fmt->height = 288;
-	fmt->pixelformat = V4L2_PIX_FMT_BGR24;
-	fmt->field = V4L2_FIELD_ANY;
-	fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
-	fmt->bytesperline = 3 * fmt->width;
-	fmt->sizeimage = fmt->bytesperline * fmt->height;
-
-	vbi = &vv->vbi_fmt;
-	vbi->sampling_rate	= 27000000;
-	vbi->offset		= 248; /* todo */
-	vbi->samples_per_line	= 720 * 2;
-	vbi->sample_format	= V4L2_PIX_FMT_GREY;
-
-	/* fixme: this only works for PAL */
-	vbi->start[0] = 5;
-	vbi->count[0] = 16;
-	vbi->start[1] = 312;
-	vbi->count[1] = 16;
-
-	init_timer(&vv->vbi_read_timeout);
-
-	vv->ov_fb.capability = V4L2_FBUF_CAP_LIST_CLIPPING;
-	vv->ov_fb.flags = V4L2_FBUF_FLAG_PRIMARY;
-	dev->vv_data = vv;
-	dev->vv_callback = &vv_callback;
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(saa7146_vv_init);
-
-int saa7146_vv_release(struct saa7146_dev* dev)
-{
-	struct saa7146_vv *vv = dev->vv_data;
-
-	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);
-	v4l2_ctrl_handler_free(&dev->ctrl_handler);
-	kfree(vv);
-	dev->vv_data = NULL;
-	dev->vv_callback = NULL;
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(saa7146_vv_release);
-
-int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev,
-			    char *name, int type)
-{
-	struct video_device *vfd;
-	int err;
-	int i;
-
-	DEB_EE("dev:%p, name:'%s', type:%d\n", dev, name, type);
-
-	// released by vfd->release
-	vfd = video_device_alloc();
-	if (vfd == NULL)
-		return -ENOMEM;
-
-	vfd->fops = &video_fops;
-	if (type == VFL_TYPE_GRABBER)
-		vfd->ioctl_ops = &dev->ext_vv_data->vid_ops;
-	else
-		vfd->ioctl_ops = &dev->ext_vv_data->vbi_ops;
-	vfd->release = video_device_release;
-	/* Locking in file operations other than ioctl should be done by
-	   the driver, not the V4L2 core.
-	   This driver needs auditing so that this flag can be removed. */
-	set_bit(V4L2_FL_LOCK_ALL_FOPS, &vfd->flags);
-	vfd->lock = &dev->v4l2_lock;
-	vfd->v4l2_dev = &dev->v4l2_dev;
-	vfd->tvnorms = 0;
-	set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
-	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);
-
-	err = video_register_device(vfd, type, -1);
-	if (err < 0) {
-		ERR("cannot register v4l2 device. skipping.\n");
-		video_device_release(vfd);
-		return err;
-	}
-
-	pr_info("%s: registered device %s [v4l2]\n",
-		dev->name, video_device_node_name(vfd));
-
-	*vid = vfd;
-	return 0;
-}
-EXPORT_SYMBOL_GPL(saa7146_register_device);
-
-int saa7146_unregister_device(struct video_device **vid, struct saa7146_dev* dev)
-{
-	DEB_EE("dev:%p\n", dev);
-
-	video_unregister_device(*vid);
-	*vid = NULL;
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(saa7146_unregister_device);
-
-static int __init saa7146_vv_init_module(void)
-{
-	return 0;
-}
-
-
-static void __exit saa7146_vv_cleanup_module(void)
-{
-}
-
-module_init(saa7146_vv_init_module);
-module_exit(saa7146_vv_cleanup_module);
-
-MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
-MODULE_DESCRIPTION("video4linux driver for saa7146-based hardware");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/common/saa7146_hlp.c b/drivers/media/common/saa7146_hlp.c
deleted file mode 100644
index be746d1..0000000
--- a/drivers/media/common/saa7146_hlp.c
+++ /dev/null
@@ -1,1048 +0,0 @@
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/kernel.h>
-#include <linux/export.h>
-#include <media/saa7146_vv.h>
-
-static void calculate_output_format_register(struct saa7146_dev* saa, u32 palette, u32* clip_format)
-{
-	/* clear out the necessary bits */
-	*clip_format &= 0x0000ffff;
-	/* set these bits new */
-	*clip_format |=  (( ((palette&0xf00)>>8) << 30) | ((palette&0x00f) << 24) | (((palette&0x0f0)>>4) << 16));
-}
-
-static void calculate_hps_source_and_sync(struct saa7146_dev *dev, int source, int sync, u32* hps_ctrl)
-{
-	*hps_ctrl &= ~(MASK_30 | MASK_31 | MASK_28);
-	*hps_ctrl |= (source << 30) | (sync << 28);
-}
-
-static void calculate_hxo_and_hyo(struct saa7146_vv *vv, u32* hps_h_scale, u32* hps_ctrl)
-{
-	int hyo = 0, hxo = 0;
-
-	hyo = vv->standard->v_offset;
-	hxo = vv->standard->h_offset;
-
-	*hps_h_scale	&= ~(MASK_B0 | 0xf00);
-	*hps_h_scale	|= (hxo <<  0);
-
-	*hps_ctrl	&= ~(MASK_W0 | MASK_B2);
-	*hps_ctrl	|= (hyo << 12);
-}
-
-/* helper functions for the calculation of the horizontal- and vertical
-   scaling registers, clip-format-register etc ...
-   these functions take pointers to the (most-likely read-out
-   original-values) and manipulate them according to the requested
-   changes.
-*/
-
-/* hps_coeff used for CXY and CXUV; scale 1/1 -> scale 1/64 */
-static struct {
-	u16 hps_coeff;
-	u16 weight_sum;
-} hps_h_coeff_tab [] = {
-	{0x00,   2}, {0x02,   4}, {0x00,   4}, {0x06,   8}, {0x02,   8},
-	{0x08,   8}, {0x00,   8}, {0x1E,  16}, {0x0E,   8}, {0x26,   8},
-	{0x06,   8}, {0x42,   8}, {0x02,   8}, {0x80,   8}, {0x00,   8},
-	{0xFE,  16}, {0xFE,   8}, {0x7E,   8}, {0x7E,   8}, {0x3E,   8},
-	{0x3E,   8}, {0x1E,   8}, {0x1E,   8}, {0x0E,   8}, {0x0E,   8},
-	{0x06,   8}, {0x06,   8}, {0x02,   8}, {0x02,   8}, {0x00,   8},
-	{0x00,   8}, {0xFE,  16}, {0xFE,   8}, {0xFE,   8}, {0xFE,   8},
-	{0xFE,   8}, {0xFE,   8}, {0xFE,   8}, {0xFE,   8}, {0xFE,   8},
-	{0xFE,   8}, {0xFE,   8}, {0xFE,   8}, {0xFE,   8}, {0xFE,   8},
-	{0xFE,   8}, {0xFE,   8}, {0xFE,   8}, {0xFE,   8}, {0x7E,   8},
-	{0x7E,   8}, {0x3E,   8}, {0x3E,   8}, {0x1E,   8}, {0x1E,   8},
-	{0x0E,   8}, {0x0E,   8}, {0x06,   8}, {0x06,   8}, {0x02,   8},
-	{0x02,   8}, {0x00,   8}, {0x00,   8}, {0xFE,  16}
-};
-
-/* table of attenuation values for horizontal scaling */
-static u8 h_attenuation[] = { 1, 2, 4, 8, 2, 4, 8, 16, 0};
-
-/* calculate horizontal scale registers */
-static int calculate_h_scale_registers(struct saa7146_dev *dev,
-	int in_x, int out_x, int flip_lr,
-	u32* hps_ctrl, u32* hps_v_gain, u32* hps_h_prescale, u32* hps_h_scale)
-{
-	/* horizontal prescaler */
-	u32 dcgx = 0, xpsc = 0, xacm = 0, cxy = 0, cxuv = 0;
-	/* horizontal scaler */
-	u32 xim = 0, xp = 0, xsci =0;
-	/* vertical scale & gain */
-	u32 pfuv = 0;
-
-	/* helper variables */
-	u32 h_atten = 0, i = 0;
-
-	if ( 0 == out_x ) {
-		return -EINVAL;
-	}
-
-	/* mask out vanity-bit */
-	*hps_ctrl &= ~MASK_29;
-
-	/* calculate prescale-(xspc)-value:	[n   .. 1/2) : 1
-						[1/2 .. 1/3) : 2
-						[1/3 .. 1/4) : 3
-						...		*/
-	if (in_x > out_x) {
-		xpsc = in_x / out_x;
-	}
-	else {
-		/* zooming */
-		xpsc = 1;
-	}
-
-	/* if flip_lr-bit is set, number of pixels after
-	   horizontal prescaling must be < 384 */
-	if ( 0 != flip_lr ) {
-
-		/* set vanity bit */
-		*hps_ctrl |= MASK_29;
-
-		while (in_x / xpsc >= 384 )
-			xpsc++;
-	}
-	/* if zooming is wanted, number of pixels after
-	   horizontal prescaling must be < 768 */
-	else {
-		while ( in_x / xpsc >= 768 )
-			xpsc++;
-	}
-
-	/* maximum prescale is 64 (p.69) */
-	if ( xpsc > 64 )
-		xpsc = 64;
-
-	/* keep xacm clear*/
-	xacm = 0;
-
-	/* set horizontal filter parameters (CXY = CXUV) */
-	cxy = hps_h_coeff_tab[( (xpsc - 1) < 63 ? (xpsc - 1) : 63 )].hps_coeff;
-	cxuv = cxy;
-
-	/* calculate and set horizontal fine scale (xsci) */
-
-	/* bypass the horizontal scaler ? */
-	if ( (in_x == out_x) && ( 1 == xpsc ) )
-		xsci = 0x400;
-	else
-		xsci = ( (1024 * in_x) / (out_x * xpsc) ) + xpsc;
-
-	/* set start phase for horizontal fine scale (xp) to 0 */
-	xp = 0;
-
-	/* set xim, if we bypass the horizontal scaler */
-	if ( 0x400 == xsci )
-		xim = 1;
-	else
-		xim = 0;
-
-	/* if the prescaler is bypassed, enable horizontal
-	   accumulation mode (xacm) and clear dcgx */
-	if( 1 == xpsc ) {
-		xacm = 1;
-		dcgx = 0;
-	} else {
-		xacm = 0;
-		/* get best match in the table of attenuations
-		   for horizontal scaling */
-		h_atten = hps_h_coeff_tab[( (xpsc - 1) < 63 ? (xpsc - 1) : 63 )].weight_sum;
-
-		for (i = 0; h_attenuation[i] != 0; i++) {
-			if (h_attenuation[i] >= h_atten)
-				break;
-		}
-
-		dcgx = i;
-	}
-
-	/* the horizontal scaling increment controls the UV filter
-	   to reduce the bandwidth to improve the display quality,
-	   so set it ... */
-	if ( xsci == 0x400)
-		pfuv = 0x00;
-	else if ( xsci < 0x600)
-		pfuv = 0x01;
-	else if ( xsci < 0x680)
-		pfuv = 0x11;
-	else if ( xsci < 0x700)
-		pfuv = 0x22;
-	else
-		pfuv = 0x33;
-
-
-	*hps_v_gain  &= MASK_W0|MASK_B2;
-	*hps_v_gain  |= (pfuv << 24);
-
-	*hps_h_scale	&= ~(MASK_W1 | 0xf000);
-	*hps_h_scale	|= (xim << 31) | (xp << 24) | (xsci << 12);
-
-	*hps_h_prescale	|= (dcgx << 27) | ((xpsc-1) << 18) | (xacm << 17) | (cxy << 8) | (cxuv << 0);
-
-	return 0;
-}
-
-static struct {
-	u16 hps_coeff;
-	u16 weight_sum;
-} hps_v_coeff_tab [] = {
- {0x0100,   2},  {0x0102,   4},  {0x0300,   4},  {0x0106,   8},  {0x0502,   8},
- {0x0708,   8},  {0x0F00,   8},  {0x011E,  16},  {0x110E,  16},  {0x1926,  16},
- {0x3906,  16},  {0x3D42,  16},  {0x7D02,  16},  {0x7F80,  16},  {0xFF00,  16},
- {0x01FE,  32},  {0x01FE,  32},  {0x817E,  32},  {0x817E,  32},  {0xC13E,  32},
- {0xC13E,  32},  {0xE11E,  32},  {0xE11E,  32},  {0xF10E,  32},  {0xF10E,  32},
- {0xF906,  32},  {0xF906,  32},  {0xFD02,  32},  {0xFD02,  32},  {0xFF00,  32},
- {0xFF00,  32},  {0x01FE,  64},  {0x01FE,  64},  {0x01FE,  64},  {0x01FE,  64},
- {0x01FE,  64},  {0x01FE,  64},  {0x01FE,  64},  {0x01FE,  64},  {0x01FE,  64},
- {0x01FE,  64},  {0x01FE,  64},  {0x01FE,  64},  {0x01FE,  64},  {0x01FE,  64},
- {0x01FE,  64},  {0x01FE,  64},  {0x01FE,  64},  {0x01FE,  64},  {0x817E,  64},
- {0x817E,  64},  {0xC13E,  64},  {0xC13E,  64},  {0xE11E,  64},  {0xE11E,  64},
- {0xF10E,  64},  {0xF10E,  64},  {0xF906,  64},  {0xF906,  64},  {0xFD02,  64},
- {0xFD02,  64},  {0xFF00,  64},  {0xFF00,  64},  {0x01FE, 128}
-};
-
-/* table of attenuation values for vertical scaling */
-static u16 v_attenuation[] = { 2, 4, 8, 16, 32, 64, 128, 256, 0};
-
-/* calculate vertical scale registers */
-static int calculate_v_scale_registers(struct saa7146_dev *dev, enum v4l2_field field,
-	int in_y, int out_y, u32* hps_v_scale, u32* hps_v_gain)
-{
-	int lpi = 0;
-
-	/* vertical scaling */
-	u32 yacm = 0, ysci = 0, yacl = 0, ypo = 0, ype = 0;
-	/* vertical scale & gain */
-	u32 dcgy = 0, cya_cyb = 0;
-
-	/* helper variables */
-	u32 v_atten = 0, i = 0;
-
-	/* error, if vertical zooming */
-	if ( in_y < out_y ) {
-		return -EINVAL;
-	}
-
-	/* linear phase interpolation may be used
-	   if scaling is between 1 and 1/2 (both fields used)
-	   or scaling is between 1/2 and 1/4 (if only one field is used) */
-
-	if (V4L2_FIELD_HAS_BOTH(field)) {
-		if( 2*out_y >= in_y) {
-			lpi = 1;
-		}
-	} else if (field == V4L2_FIELD_TOP
-		|| field == V4L2_FIELD_ALTERNATE
-		|| field == V4L2_FIELD_BOTTOM) {
-		if( 4*out_y >= in_y ) {
-			lpi = 1;
-		}
-		out_y *= 2;
-	}
-	if( 0 != lpi ) {
-
-		yacm = 0;
-		yacl = 0;
-		cya_cyb = 0x00ff;
-
-		/* calculate scaling increment */
-		if ( in_y > out_y )
-			ysci = ((1024 * in_y) / (out_y + 1)) - 1024;
-		else
-			ysci = 0;
-
-		dcgy = 0;
-
-		/* calculate ype and ypo */
-		ype = ysci / 16;
-		ypo = ype + (ysci / 64);
-
-	} else {
-		yacm = 1;
-
-		/* calculate scaling increment */
-		ysci = (((10 * 1024 * (in_y - out_y - 1)) / in_y) + 9) / 10;
-
-		/* calculate ype and ypo */
-		ypo = ype = ((ysci + 15) / 16);
-
-		/* the sequence length interval (yacl) has to be set according
-		   to the prescale value, e.g.	[n   .. 1/2) : 0
-						[1/2 .. 1/3) : 1
-						[1/3 .. 1/4) : 2
-						... */
-		if ( ysci < 512) {
-			yacl = 0;
-		} else {
-			yacl = ( ysci / (1024 - ysci) );
-		}
-
-		/* get filter coefficients for cya, cyb from table hps_v_coeff_tab */
-		cya_cyb = hps_v_coeff_tab[ (yacl < 63 ? yacl : 63 ) ].hps_coeff;
-
-		/* get best match in the table of attenuations for vertical scaling */
-		v_atten = hps_v_coeff_tab[ (yacl < 63 ? yacl : 63 ) ].weight_sum;
-
-		for (i = 0; v_attenuation[i] != 0; i++) {
-			if (v_attenuation[i] >= v_atten)
-				break;
-		}
-
-		dcgy = i;
-	}
-
-	/* ypo and ype swapped in spec ? */
-	*hps_v_scale	|= (yacm << 31) | (ysci << 21) | (yacl << 15) | (ypo << 8 ) | (ype << 1);
-
-	*hps_v_gain	&= ~(MASK_W0|MASK_B2);
-	*hps_v_gain	|= (dcgy << 16) | (cya_cyb << 0);
-
-	return 0;
-}
-
-/* simple bubble-sort algorithm with duplicate elimination */
-static int sort_and_eliminate(u32* values, int* count)
-{
-	int low = 0, high = 0, top = 0, temp = 0;
-	int cur = 0, next = 0;
-
-	/* sanity checks */
-	if( (0 > *count) || (NULL == values) ) {
-		return -EINVAL;
-	}
-
-	/* bubble sort the first @count items of the array @values */
-	for( top = *count; top > 0; top--) {
-		for( low = 0, high = 1; high < top; low++, high++) {
-			if( values[low] > values[high] ) {
-				temp = values[low];
-				values[low] = values[high];
-				values[high] = temp;
-			}
-		}
-	}
-
-	/* remove duplicate items */
-	for( cur = 0, next = 1; next < *count; next++) {
-		if( values[cur] != values[next])
-			values[++cur] = values[next];
-	}
-
-	*count = cur + 1;
-
-	return 0;
-}
-
-static void calculate_clipping_registers_rect(struct saa7146_dev *dev, struct saa7146_fh *fh,
-	struct saa7146_video_dma *vdma2, u32* clip_format, u32* arbtr_ctrl, enum v4l2_field field)
-{
-	struct saa7146_vv *vv = dev->vv_data;
-	__le32 *clipping = vv->d_clipping.cpu_addr;
-
-	int width = vv->ov.win.w.width;
-	int height =  vv->ov.win.w.height;
-	int clipcount = vv->ov.nclips;
-
-	u32 line_list[32];
-	u32 pixel_list[32];
-	int numdwords = 0;
-
-	int i = 0, j = 0;
-	int cnt_line = 0, cnt_pixel = 0;
-
-	int x[32], y[32], w[32], h[32];
-
-	/* clear out memory */
-	memset(&line_list[0],  0x00, sizeof(u32)*32);
-	memset(&pixel_list[0], 0x00, sizeof(u32)*32);
-	memset(clipping,  0x00, SAA7146_CLIPPING_MEM);
-
-	/* fill the line and pixel-lists */
-	for(i = 0; i < clipcount; i++) {
-		int l = 0, r = 0, t = 0, b = 0;
-
-		x[i] = vv->ov.clips[i].c.left;
-		y[i] = vv->ov.clips[i].c.top;
-		w[i] = vv->ov.clips[i].c.width;
-		h[i] = vv->ov.clips[i].c.height;
-
-		if( w[i] < 0) {
-			x[i] += w[i]; w[i] = -w[i];
-		}
-		if( h[i] < 0) {
-			y[i] += h[i]; h[i] = -h[i];
-		}
-		if( x[i] < 0) {
-			w[i] += x[i]; x[i] = 0;
-		}
-		if( y[i] < 0) {
-			h[i] += y[i]; y[i] = 0;
-		}
-		if( 0 != vv->vflip ) {
-			y[i] = height - y[i] - h[i];
-		}
-
-		l = x[i];
-		r = x[i]+w[i];
-		t = y[i];
-		b = y[i]+h[i];
-
-		/* insert left/right coordinates */
-		pixel_list[ 2*i   ] = min_t(int, l, width);
-		pixel_list[(2*i)+1] = min_t(int, r, width);
-		/* insert top/bottom coordinates */
-		line_list[ 2*i   ] = min_t(int, t, height);
-		line_list[(2*i)+1] = min_t(int, b, height);
-	}
-
-	/* sort and eliminate lists */
-	cnt_line = cnt_pixel = 2*clipcount;
-	sort_and_eliminate( &pixel_list[0], &cnt_pixel );
-	sort_and_eliminate( &line_list[0], &cnt_line );
-
-	/* calculate the number of used u32s */
-	numdwords = max_t(int, (cnt_line+1), (cnt_pixel+1))*2;
-	numdwords = max_t(int, 4, numdwords);
-	numdwords = min_t(int, 64, numdwords);
-
-	/* fill up cliptable */
-	for(i = 0; i < cnt_pixel; i++) {
-		clipping[2*i] |= cpu_to_le32(pixel_list[i] << 16);
-	}
-	for(i = 0; i < cnt_line; i++) {
-		clipping[(2*i)+1] |= cpu_to_le32(line_list[i] << 16);
-	}
-
-	/* fill up cliptable with the display infos */
-	for(j = 0; j < clipcount; j++) {
-
-		for(i = 0; i < cnt_pixel; i++) {
-
-			if( x[j] < 0)
-				x[j] = 0;
-
-			if( pixel_list[i] < (x[j] + w[j])) {
-
-				if ( pixel_list[i] >= x[j] ) {
-					clipping[2*i] |= cpu_to_le32(1 << j);
-				}
-			}
-		}
-		for(i = 0; i < cnt_line; i++) {
-
-			if( y[j] < 0)
-				y[j] = 0;
-
-			if( line_list[i] < (y[j] + h[j]) ) {
-
-				if( line_list[i] >= y[j] ) {
-					clipping[(2*i)+1] |= cpu_to_le32(1 << j);
-				}
-			}
-		}
-	}
-
-	/* adjust arbitration control register */
-	*arbtr_ctrl &= 0xffff00ff;
-	*arbtr_ctrl |= 0x00001c00;
-
-	vdma2->base_even	= vv->d_clipping.dma_handle;
-	vdma2->base_odd		= vv->d_clipping.dma_handle;
-	vdma2->prot_addr	= vv->d_clipping.dma_handle+((sizeof(u32))*(numdwords));
-	vdma2->base_page	= 0x04;
-	vdma2->pitch		= 0x00;
-	vdma2->num_line_byte	= (0 << 16 | (sizeof(u32))*(numdwords-1) );
-
-	/* set clipping-mode. this depends on the field(s) used */
-	*clip_format &= 0xfffffff7;
-	if (V4L2_FIELD_HAS_BOTH(field)) {
-		*clip_format |= 0x00000008;
-	} else {
-		*clip_format |= 0x00000000;
-	}
-}
-
-/* disable clipping */
-static void saa7146_disable_clipping(struct saa7146_dev *dev)
-{
-	u32 clip_format	= saa7146_read(dev, CLIP_FORMAT_CTRL);
-
-	/* mask out relevant bits (=lower word)*/
-	clip_format &= MASK_W1;
-
-	/* upload clipping-registers*/
-	saa7146_write(dev, CLIP_FORMAT_CTRL,clip_format);
-	saa7146_write(dev, MC2, (MASK_05 | MASK_21));
-
-	/* disable video dma2 */
-	saa7146_write(dev, MC1, MASK_21);
-}
-
-static void saa7146_set_clipping_rect(struct saa7146_fh *fh)
-{
-	struct saa7146_dev *dev = fh->dev;
-	struct saa7146_vv *vv = dev->vv_data;
-	enum v4l2_field field = vv->ov.win.field;
-	struct	saa7146_video_dma vdma2;
-	u32 clip_format;
-	u32 arbtr_ctrl;
-
-	/* check clipcount, disable clipping if clipcount == 0*/
-	if (vv->ov.nclips == 0) {
-		saa7146_disable_clipping(dev);
-		return;
-	}
-
-	clip_format = saa7146_read(dev, CLIP_FORMAT_CTRL);
-	arbtr_ctrl = saa7146_read(dev, PCI_BT_V1);
-
-	calculate_clipping_registers_rect(dev, fh, &vdma2, &clip_format, &arbtr_ctrl, field);
-
-	/* set clipping format */
-	clip_format &= 0xffff0008;
-	clip_format |= (SAA7146_CLIPPING_RECT << 4);
-
-	/* prepare video dma2 */
-	saa7146_write(dev, BASE_EVEN2,		vdma2.base_even);
-	saa7146_write(dev, BASE_ODD2,		vdma2.base_odd);
-	saa7146_write(dev, PROT_ADDR2,		vdma2.prot_addr);
-	saa7146_write(dev, BASE_PAGE2,		vdma2.base_page);
-	saa7146_write(dev, PITCH2,		vdma2.pitch);
-	saa7146_write(dev, NUM_LINE_BYTE2,	vdma2.num_line_byte);
-
-	/* prepare the rest */
-	saa7146_write(dev, CLIP_FORMAT_CTRL,clip_format);
-	saa7146_write(dev, PCI_BT_V1, arbtr_ctrl);
-
-	/* upload clip_control-register, clipping-registers, enable video dma2 */
-	saa7146_write(dev, MC2, (MASK_05 | MASK_21 | MASK_03 | MASK_19));
-	saa7146_write(dev, MC1, (MASK_05 | MASK_21));
-}
-
-static void saa7146_set_window(struct saa7146_dev *dev, int width, int height, enum v4l2_field field)
-{
-	struct saa7146_vv *vv = dev->vv_data;
-
-	int source = vv->current_hps_source;
-	int sync = vv->current_hps_sync;
-
-	u32 hps_v_scale = 0, hps_v_gain  = 0, hps_ctrl = 0, hps_h_prescale = 0, hps_h_scale = 0;
-
-	/* set vertical scale */
-	hps_v_scale = 0; /* all bits get set by the function-call */
-	hps_v_gain  = 0; /* fixme: saa7146_read(dev, HPS_V_GAIN);*/
-	calculate_v_scale_registers(dev, field, vv->standard->v_field*2, height, &hps_v_scale, &hps_v_gain);
-
-	/* set horizontal scale */
-	hps_ctrl	= 0;
-	hps_h_prescale	= 0; /* all bits get set in the function */
-	hps_h_scale	= 0;
-	calculate_h_scale_registers(dev, vv->standard->h_pixels, width, vv->hflip, &hps_ctrl, &hps_v_gain, &hps_h_prescale, &hps_h_scale);
-
-	/* set hyo and hxo */
-	calculate_hxo_and_hyo(vv, &hps_h_scale, &hps_ctrl);
-	calculate_hps_source_and_sync(dev, source, sync, &hps_ctrl);
-
-	/* write out new register contents */
-	saa7146_write(dev, HPS_V_SCALE,	hps_v_scale);
-	saa7146_write(dev, HPS_V_GAIN,	hps_v_gain);
-	saa7146_write(dev, HPS_CTRL,	hps_ctrl);
-	saa7146_write(dev, HPS_H_PRESCALE,hps_h_prescale);
-	saa7146_write(dev, HPS_H_SCALE,	hps_h_scale);
-
-	/* upload shadow-ram registers */
-	saa7146_write(dev, MC2, (MASK_05 | MASK_06 | MASK_21 | MASK_22) );
-}
-
-/* calculate the new memory offsets for a desired position */
-static void saa7146_set_position(struct saa7146_dev *dev, int w_x, int w_y, int w_height, enum v4l2_field field, u32 pixelformat)
-{
-	struct saa7146_vv *vv = dev->vv_data;
-	struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev, pixelformat);
-
-	int b_depth = vv->ov_fmt->depth;
-	int b_bpl = vv->ov_fb.fmt.bytesperline;
-	/* The unsigned long cast is to remove a 64-bit compile warning since
-	   it looks like a 64-bit address is cast to a 32-bit value, even
-	   though the base pointer is really a 32-bit physical address that
-	   goes into a 32-bit DMA register.
-	   FIXME: might not work on some 64-bit platforms, but see the FIXME
-	   in struct v4l2_framebuffer (videodev2.h) for that.
-	 */
-	u32 base = (u32)(unsigned long)vv->ov_fb.base;
-
-	struct	saa7146_video_dma vdma1;
-
-	/* calculate memory offsets for picture, look if we shall top-down-flip */
-	vdma1.pitch	= 2*b_bpl;
-	if ( 0 == vv->vflip ) {
-		vdma1.base_even = base + (w_y * (vdma1.pitch/2)) + (w_x * (b_depth / 8));
-		vdma1.base_odd  = vdma1.base_even + (vdma1.pitch / 2);
-		vdma1.prot_addr = vdma1.base_even + (w_height * (vdma1.pitch / 2));
-	}
-	else {
-		vdma1.base_even = base + ((w_y+w_height) * (vdma1.pitch/2)) + (w_x * (b_depth / 8));
-		vdma1.base_odd  = vdma1.base_even - (vdma1.pitch / 2);
-		vdma1.prot_addr = vdma1.base_odd - (w_height * (vdma1.pitch / 2));
-	}
-
-	if (V4L2_FIELD_HAS_BOTH(field)) {
-	} else if (field == V4L2_FIELD_ALTERNATE) {
-		/* fixme */
-		vdma1.base_odd = vdma1.prot_addr;
-		vdma1.pitch /= 2;
-	} else if (field == V4L2_FIELD_TOP) {
-		vdma1.base_odd = vdma1.prot_addr;
-		vdma1.pitch /= 2;
-	} else if (field == V4L2_FIELD_BOTTOM) {
-		vdma1.base_odd = vdma1.base_even;
-		vdma1.base_even = vdma1.prot_addr;
-		vdma1.pitch /= 2;
-	}
-
-	if ( 0 != vv->vflip ) {
-		vdma1.pitch *= -1;
-	}
-
-	vdma1.base_page = sfmt->swap;
-	vdma1.num_line_byte = (vv->standard->v_field<<16)+vv->standard->h_pixels;
-
-	saa7146_write_out_dma(dev, 1, &vdma1);
-}
-
-static void saa7146_set_output_format(struct saa7146_dev *dev, unsigned long palette)
-{
-	u32 clip_format = saa7146_read(dev, CLIP_FORMAT_CTRL);
-
-	/* call helper function */
-	calculate_output_format_register(dev,palette,&clip_format);
-
-	/* update the hps registers */
-	saa7146_write(dev, CLIP_FORMAT_CTRL, clip_format);
-	saa7146_write(dev, MC2, (MASK_05 | MASK_21));
-}
-
-/* select input-source */
-void saa7146_set_hps_source_and_sync(struct saa7146_dev *dev, int source, int sync)
-{
-	struct saa7146_vv *vv = dev->vv_data;
-	u32 hps_ctrl = 0;
-
-	/* read old state */
-	hps_ctrl = saa7146_read(dev, HPS_CTRL);
-
-	hps_ctrl &= ~( MASK_31 | MASK_30 | MASK_28 );
-	hps_ctrl |= (source << 30) | (sync << 28);
-
-	/* write back & upload register */
-	saa7146_write(dev, HPS_CTRL, hps_ctrl);
-	saa7146_write(dev, MC2, (MASK_05 | MASK_21));
-
-	vv->current_hps_source = source;
-	vv->current_hps_sync = sync;
-}
-EXPORT_SYMBOL_GPL(saa7146_set_hps_source_and_sync);
-
-int saa7146_enable_overlay(struct saa7146_fh *fh)
-{
-	struct saa7146_dev *dev = fh->dev;
-	struct saa7146_vv *vv = dev->vv_data;
-
-	saa7146_set_window(dev, vv->ov.win.w.width, vv->ov.win.w.height, vv->ov.win.field);
-	saa7146_set_position(dev, vv->ov.win.w.left, vv->ov.win.w.top, vv->ov.win.w.height, vv->ov.win.field, vv->ov_fmt->pixelformat);
-	saa7146_set_output_format(dev, vv->ov_fmt->trans);
-	saa7146_set_clipping_rect(fh);
-
-	/* enable video dma1 */
-	saa7146_write(dev, MC1, (MASK_06 | MASK_22));
-	return 0;
-}
-
-void saa7146_disable_overlay(struct saa7146_fh *fh)
-{
-	struct saa7146_dev *dev = fh->dev;
-
-	/* disable clipping + video dma1 */
-	saa7146_disable_clipping(dev);
-	saa7146_write(dev, MC1, MASK_22);
-}
-
-void saa7146_write_out_dma(struct saa7146_dev* dev, int which, struct saa7146_video_dma* vdma)
-{
-	int where = 0;
-
-	if( which < 1 || which > 3) {
-		return;
-	}
-
-	/* calculate starting address */
-	where  = (which-1)*0x18;
-
-	saa7146_write(dev, where,	vdma->base_odd);
-	saa7146_write(dev, where+0x04,	vdma->base_even);
-	saa7146_write(dev, where+0x08,	vdma->prot_addr);
-	saa7146_write(dev, where+0x0c,	vdma->pitch);
-	saa7146_write(dev, where+0x10,	vdma->base_page);
-	saa7146_write(dev, where+0x14,	vdma->num_line_byte);
-
-	/* upload */
-	saa7146_write(dev, MC2, (MASK_02<<(which-1))|(MASK_18<<(which-1)));
-/*
-	printk("vdma%d.base_even:     0x%08x\n", which,vdma->base_even);
-	printk("vdma%d.base_odd:      0x%08x\n", which,vdma->base_odd);
-	printk("vdma%d.prot_addr:     0x%08x\n", which,vdma->prot_addr);
-	printk("vdma%d.base_page:     0x%08x\n", which,vdma->base_page);
-	printk("vdma%d.pitch:         0x%08x\n", which,vdma->pitch);
-	printk("vdma%d.num_line_byte: 0x%08x\n", which,vdma->num_line_byte);
-*/
-}
-
-static int calculate_video_dma_grab_packed(struct saa7146_dev* dev, struct saa7146_buf *buf)
-{
-	struct saa7146_vv *vv = dev->vv_data;
-	struct saa7146_video_dma vdma1;
-
-	struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat);
-
-	int width = buf->fmt->width;
-	int height = buf->fmt->height;
-	int bytesperline = buf->fmt->bytesperline;
-	enum v4l2_field field = buf->fmt->field;
-
-	int depth = sfmt->depth;
-
-	DEB_CAP("[size=%dx%d,fields=%s]\n",
-		width, height, v4l2_field_names[field]);
-
-	if( bytesperline != 0) {
-		vdma1.pitch = bytesperline*2;
-	} else {
-		vdma1.pitch = (width*depth*2)/8;
-	}
-	vdma1.num_line_byte	= ((vv->standard->v_field<<16) + vv->standard->h_pixels);
-	vdma1.base_page		= buf->pt[0].dma | ME1 | sfmt->swap;
-
-	if( 0 != vv->vflip ) {
-		vdma1.prot_addr	= buf->pt[0].offset;
-		vdma1.base_even	= buf->pt[0].offset+(vdma1.pitch/2)*height;
-		vdma1.base_odd	= vdma1.base_even - (vdma1.pitch/2);
-	} else {
-		vdma1.base_even	= buf->pt[0].offset;
-		vdma1.base_odd	= vdma1.base_even + (vdma1.pitch/2);
-		vdma1.prot_addr	= buf->pt[0].offset+(vdma1.pitch/2)*height;
-	}
-
-	if (V4L2_FIELD_HAS_BOTH(field)) {
-	} else if (field == V4L2_FIELD_ALTERNATE) {
-		/* fixme */
-		if ( vv->last_field == V4L2_FIELD_TOP ) {
-			vdma1.base_odd	= vdma1.prot_addr;
-			vdma1.pitch /= 2;
-		} else if ( vv->last_field == V4L2_FIELD_BOTTOM ) {
-			vdma1.base_odd	= vdma1.base_even;
-			vdma1.base_even = vdma1.prot_addr;
-			vdma1.pitch /= 2;
-		}
-	} else if (field == V4L2_FIELD_TOP) {
-		vdma1.base_odd	= vdma1.prot_addr;
-		vdma1.pitch /= 2;
-	} else if (field == V4L2_FIELD_BOTTOM) {
-		vdma1.base_odd	= vdma1.base_even;
-		vdma1.base_even = vdma1.prot_addr;
-		vdma1.pitch /= 2;
-	}
-
-	if( 0 != vv->vflip ) {
-		vdma1.pitch *= -1;
-	}
-
-	saa7146_write_out_dma(dev, 1, &vdma1);
-	return 0;
-}
-
-static int calc_planar_422(struct saa7146_vv *vv, struct saa7146_buf *buf, struct saa7146_video_dma *vdma2, struct saa7146_video_dma *vdma3)
-{
-	int height = buf->fmt->height;
-	int width = buf->fmt->width;
-
-	vdma2->pitch	= width;
-	vdma3->pitch	= width;
-
-	/* fixme: look at bytesperline! */
-
-	if( 0 != vv->vflip ) {
-		vdma2->prot_addr	= buf->pt[1].offset;
-		vdma2->base_even	= ((vdma2->pitch/2)*height)+buf->pt[1].offset;
-		vdma2->base_odd		= vdma2->base_even - (vdma2->pitch/2);
-
-		vdma3->prot_addr	= buf->pt[2].offset;
-		vdma3->base_even	= ((vdma3->pitch/2)*height)+buf->pt[2].offset;
-		vdma3->base_odd		= vdma3->base_even - (vdma3->pitch/2);
-	} else {
-		vdma3->base_even	= buf->pt[2].offset;
-		vdma3->base_odd		= vdma3->base_even + (vdma3->pitch/2);
-		vdma3->prot_addr	= (vdma3->pitch/2)*height+buf->pt[2].offset;
-
-		vdma2->base_even	= buf->pt[1].offset;
-		vdma2->base_odd		= vdma2->base_even + (vdma2->pitch/2);
-		vdma2->prot_addr	= (vdma2->pitch/2)*height+buf->pt[1].offset;
-	}
-
-	return 0;
-}
-
-static int calc_planar_420(struct saa7146_vv *vv, struct saa7146_buf *buf, struct saa7146_video_dma *vdma2, struct saa7146_video_dma *vdma3)
-{
-	int height = buf->fmt->height;
-	int width = buf->fmt->width;
-
-	vdma2->pitch	= width/2;
-	vdma3->pitch	= width/2;
-
-	if( 0 != vv->vflip ) {
-		vdma2->prot_addr	= buf->pt[2].offset;
-		vdma2->base_even	= ((vdma2->pitch/2)*height)+buf->pt[2].offset;
-		vdma2->base_odd		= vdma2->base_even - (vdma2->pitch/2);
-
-		vdma3->prot_addr	= buf->pt[1].offset;
-		vdma3->base_even	= ((vdma3->pitch/2)*height)+buf->pt[1].offset;
-		vdma3->base_odd		= vdma3->base_even - (vdma3->pitch/2);
-
-	} else {
-		vdma3->base_even	= buf->pt[2].offset;
-		vdma3->base_odd		= vdma3->base_even + (vdma3->pitch);
-		vdma3->prot_addr	= (vdma3->pitch/2)*height+buf->pt[2].offset;
-
-		vdma2->base_even	= buf->pt[1].offset;
-		vdma2->base_odd		= vdma2->base_even + (vdma2->pitch);
-		vdma2->prot_addr	= (vdma2->pitch/2)*height+buf->pt[1].offset;
-	}
-	return 0;
-}
-
-static int calculate_video_dma_grab_planar(struct saa7146_dev* dev, struct saa7146_buf *buf)
-{
-	struct saa7146_vv *vv = dev->vv_data;
-	struct saa7146_video_dma vdma1;
-	struct saa7146_video_dma vdma2;
-	struct saa7146_video_dma vdma3;
-
-	struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat);
-
-	int width = buf->fmt->width;
-	int height = buf->fmt->height;
-	enum v4l2_field field = buf->fmt->field;
-
-	BUG_ON(0 == buf->pt[0].dma);
-	BUG_ON(0 == buf->pt[1].dma);
-	BUG_ON(0 == buf->pt[2].dma);
-
-	DEB_CAP("[size=%dx%d,fields=%s]\n",
-		width, height, v4l2_field_names[field]);
-
-	/* fixme: look at bytesperline! */
-
-	/* fixme: what happens for user space buffers here?. The offsets are
-	   most likely wrong, this version here only works for page-aligned
-	   buffers, modifications to the pagetable-functions are necessary...*/
-
-	vdma1.pitch		= width*2;
-	vdma1.num_line_byte	= ((vv->standard->v_field<<16) + vv->standard->h_pixels);
-	vdma1.base_page		= buf->pt[0].dma | ME1;
-
-	if( 0 != vv->vflip ) {
-		vdma1.prot_addr	= buf->pt[0].offset;
-		vdma1.base_even	= ((vdma1.pitch/2)*height)+buf->pt[0].offset;
-		vdma1.base_odd	= vdma1.base_even - (vdma1.pitch/2);
-	} else {
-		vdma1.base_even	= buf->pt[0].offset;
-		vdma1.base_odd	= vdma1.base_even + (vdma1.pitch/2);
-		vdma1.prot_addr	= (vdma1.pitch/2)*height+buf->pt[0].offset;
-	}
-
-	vdma2.num_line_byte	= 0; /* unused */
-	vdma2.base_page		= buf->pt[1].dma | ME1;
-
-	vdma3.num_line_byte	= 0; /* unused */
-	vdma3.base_page		= buf->pt[2].dma | ME1;
-
-	switch( sfmt->depth ) {
-		case 12: {
-			calc_planar_420(vv,buf,&vdma2,&vdma3);
-			break;
-		}
-		case 16: {
-			calc_planar_422(vv,buf,&vdma2,&vdma3);
-			break;
-		}
-		default: {
-			return -1;
-		}
-	}
-
-	if (V4L2_FIELD_HAS_BOTH(field)) {
-	} else if (field == V4L2_FIELD_ALTERNATE) {
-		/* fixme */
-		vdma1.base_odd	= vdma1.prot_addr;
-		vdma1.pitch /= 2;
-		vdma2.base_odd	= vdma2.prot_addr;
-		vdma2.pitch /= 2;
-		vdma3.base_odd	= vdma3.prot_addr;
-		vdma3.pitch /= 2;
-	} else if (field == V4L2_FIELD_TOP) {
-		vdma1.base_odd	= vdma1.prot_addr;
-		vdma1.pitch /= 2;
-		vdma2.base_odd	= vdma2.prot_addr;
-		vdma2.pitch /= 2;
-		vdma3.base_odd	= vdma3.prot_addr;
-		vdma3.pitch /= 2;
-	} else if (field == V4L2_FIELD_BOTTOM) {
-		vdma1.base_odd	= vdma1.base_even;
-		vdma1.base_even = vdma1.prot_addr;
-		vdma1.pitch /= 2;
-		vdma2.base_odd	= vdma2.base_even;
-		vdma2.base_even = vdma2.prot_addr;
-		vdma2.pitch /= 2;
-		vdma3.base_odd	= vdma3.base_even;
-		vdma3.base_even = vdma3.prot_addr;
-		vdma3.pitch /= 2;
-	}
-
-	if( 0 != vv->vflip ) {
-		vdma1.pitch *= -1;
-		vdma2.pitch *= -1;
-		vdma3.pitch *= -1;
-	}
-
-	saa7146_write_out_dma(dev, 1, &vdma1);
-	if( (sfmt->flags & FORMAT_BYTE_SWAP) != 0 ) {
-		saa7146_write_out_dma(dev, 3, &vdma2);
-		saa7146_write_out_dma(dev, 2, &vdma3);
-	} else {
-		saa7146_write_out_dma(dev, 2, &vdma2);
-		saa7146_write_out_dma(dev, 3, &vdma3);
-	}
-	return 0;
-}
-
-static void program_capture_engine(struct saa7146_dev *dev, int planar)
-{
-	struct saa7146_vv *vv = dev->vv_data;
-	int count = 0;
-
-	unsigned long e_wait = vv->current_hps_sync == SAA7146_HPS_SYNC_PORT_A ? CMD_E_FID_A : CMD_E_FID_B;
-	unsigned long o_wait = vv->current_hps_sync == SAA7146_HPS_SYNC_PORT_A ? CMD_O_FID_A : CMD_O_FID_B;
-
-	/* wait for o_fid_a/b / e_fid_a/b toggle only if rps register 0 is not set*/
-	WRITE_RPS0(CMD_PAUSE | CMD_OAN | CMD_SIG0 | o_wait);
-	WRITE_RPS0(CMD_PAUSE | CMD_OAN | CMD_SIG0 | e_wait);
-
-	/* set rps register 0 */
-	WRITE_RPS0(CMD_WR_REG | (1 << 8) | (MC2/4));
-	WRITE_RPS0(MASK_27 | MASK_11);
-
-	/* turn on video-dma1 */
-	WRITE_RPS0(CMD_WR_REG_MASK | (MC1/4));
-	WRITE_RPS0(MASK_06 | MASK_22);			/* => mask */
-	WRITE_RPS0(MASK_06 | MASK_22);			/* => values */
-	if( 0 != planar ) {
-		/* turn on video-dma2 */
-		WRITE_RPS0(CMD_WR_REG_MASK | (MC1/4));
-		WRITE_RPS0(MASK_05 | MASK_21);			/* => mask */
-		WRITE_RPS0(MASK_05 | MASK_21);			/* => values */
-
-		/* turn on video-dma3 */
-		WRITE_RPS0(CMD_WR_REG_MASK | (MC1/4));
-		WRITE_RPS0(MASK_04 | MASK_20);			/* => mask */
-		WRITE_RPS0(MASK_04 | MASK_20);			/* => values */
-	}
-
-	/* wait for o_fid_a/b / e_fid_a/b toggle */
-	if ( vv->last_field == V4L2_FIELD_INTERLACED ) {
-		WRITE_RPS0(CMD_PAUSE | o_wait);
-		WRITE_RPS0(CMD_PAUSE | e_wait);
-	} else if ( vv->last_field == V4L2_FIELD_TOP ) {
-		WRITE_RPS0(CMD_PAUSE | (vv->current_hps_sync == SAA7146_HPS_SYNC_PORT_A ? MASK_10 : MASK_09));
-		WRITE_RPS0(CMD_PAUSE | o_wait);
-	} else if ( vv->last_field == V4L2_FIELD_BOTTOM ) {
-		WRITE_RPS0(CMD_PAUSE | (vv->current_hps_sync == SAA7146_HPS_SYNC_PORT_A ? MASK_10 : MASK_09));
-		WRITE_RPS0(CMD_PAUSE | e_wait);
-	}
-
-	/* turn off video-dma1 */
-	WRITE_RPS0(CMD_WR_REG_MASK | (MC1/4));
-	WRITE_RPS0(MASK_22 | MASK_06);			/* => mask */
-	WRITE_RPS0(MASK_22);				/* => values */
-	if( 0 != planar ) {
-		/* turn off video-dma2 */
-		WRITE_RPS0(CMD_WR_REG_MASK | (MC1/4));
-		WRITE_RPS0(MASK_05 | MASK_21);			/* => mask */
-		WRITE_RPS0(MASK_21);				/* => values */
-
-		/* turn off video-dma3 */
-		WRITE_RPS0(CMD_WR_REG_MASK | (MC1/4));
-		WRITE_RPS0(MASK_04 | MASK_20);			/* => mask */
-		WRITE_RPS0(MASK_20);				/* => values */
-	}
-
-	/* generate interrupt */
-	WRITE_RPS0(CMD_INTERRUPT);
-
-	/* stop */
-	WRITE_RPS0(CMD_STOP);
-}
-
-void saa7146_set_capture(struct saa7146_dev *dev, struct saa7146_buf *buf, struct saa7146_buf *next)
-{
-	struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat);
-	struct saa7146_vv *vv = dev->vv_data;
-	u32 vdma1_prot_addr;
-
-	DEB_CAP("buf:%p, next:%p\n", buf, next);
-
-	vdma1_prot_addr = saa7146_read(dev, PROT_ADDR1);
-	if( 0 == vdma1_prot_addr ) {
-		/* clear out beginning of streaming bit (rps register 0)*/
-		DEB_CAP("forcing sync to new frame\n");
-		saa7146_write(dev, MC2, MASK_27 );
-	}
-
-	saa7146_set_window(dev, buf->fmt->width, buf->fmt->height, buf->fmt->field);
-	saa7146_set_output_format(dev, sfmt->trans);
-	saa7146_disable_clipping(dev);
-
-	if ( vv->last_field == V4L2_FIELD_INTERLACED ) {
-	} else if ( vv->last_field == V4L2_FIELD_TOP ) {
-		vv->last_field = V4L2_FIELD_BOTTOM;
-	} else if ( vv->last_field == V4L2_FIELD_BOTTOM ) {
-		vv->last_field = V4L2_FIELD_TOP;
-	}
-
-	if( 0 != IS_PLANAR(sfmt->trans)) {
-		calculate_video_dma_grab_planar(dev, buf);
-		program_capture_engine(dev,1);
-	} else {
-		calculate_video_dma_grab_packed(dev, buf);
-		program_capture_engine(dev,0);
-	}
-
-/*
-	printk("vdma%d.base_even:     0x%08x\n", 1,saa7146_read(dev,BASE_EVEN1));
-	printk("vdma%d.base_odd:      0x%08x\n", 1,saa7146_read(dev,BASE_ODD1));
-	printk("vdma%d.prot_addr:     0x%08x\n", 1,saa7146_read(dev,PROT_ADDR1));
-	printk("vdma%d.base_page:     0x%08x\n", 1,saa7146_read(dev,BASE_PAGE1));
-	printk("vdma%d.pitch:         0x%08x\n", 1,saa7146_read(dev,PITCH1));
-	printk("vdma%d.num_line_byte: 0x%08x\n", 1,saa7146_read(dev,NUM_LINE_BYTE1));
-	printk("vdma%d => vptr      : 0x%08x\n", 1,saa7146_read(dev,PCI_VDP1));
-*/
-
-	/* write the address of the rps-program */
-	saa7146_write(dev, RPS_ADDR0, dev->d_rps0.dma_handle);
-
-	/* turn on rps */
-	saa7146_write(dev, MC1, (MASK_12 | MASK_28));
-}
diff --git a/drivers/media/common/saa7146_i2c.c b/drivers/media/common/saa7146_i2c.c
deleted file mode 100644
index 2202719..0000000
--- a/drivers/media/common/saa7146_i2c.c
+++ /dev/null
@@ -1,423 +0,0 @@
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <media/saa7146_vv.h>
-
-static u32 saa7146_i2c_func(struct i2c_adapter *adapter)
-{
-	/* DEB_I2C("'%s'\n", adapter->name); */
-
-	return	  I2C_FUNC_I2C
-		| I2C_FUNC_SMBUS_QUICK
-		| I2C_FUNC_SMBUS_READ_BYTE	| I2C_FUNC_SMBUS_WRITE_BYTE
-		| I2C_FUNC_SMBUS_READ_BYTE_DATA | I2C_FUNC_SMBUS_WRITE_BYTE_DATA;
-}
-
-/* this function returns the status-register of our i2c-device */
-static inline u32 saa7146_i2c_status(struct saa7146_dev *dev)
-{
-	u32 iicsta = saa7146_read(dev, I2C_STATUS);
-	/* DEB_I2C("status: 0x%08x\n", iicsta); */
-	return iicsta;
-}
-
-/* this function runs through the i2c-messages and prepares the data to be
-   sent through the saa7146. have a look at the specifications p. 122 ff
-   to understand this. it returns the number of u32s to send, or -1
-   in case of an error. */
-static int saa7146_i2c_msg_prepare(const struct i2c_msg *m, int num, __le32 *op)
-{
-	int h1, h2;
-	int i, j, addr;
-	int mem = 0, op_count = 0;
-
-	/* first determine size of needed memory */
-	for(i = 0; i < num; i++) {
-		mem += m[i].len + 1;
-	}
-
-	/* worst case: we need one u32 for three bytes to be send
-	   plus one extra byte to address the device */
-	mem = 1 + ((mem-1) / 3);
-
-	/* we assume that op points to a memory of at least
-	 * SAA7146_I2C_MEM bytes size. if we exceed this limit...
-	 */
-	if ((4 * mem) > SAA7146_I2C_MEM) {
-		/* DEB_I2C("cannot prepare i2c-message\n"); */
-		return -ENOMEM;
-	}
-
-	/* be careful: clear out the i2c-mem first */
-	memset(op,0,sizeof(__le32)*mem);
-
-	/* loop through all messages */
-	for(i = 0; i < num; i++) {
-
-		/* insert the address of the i2c-slave.
-		   note: we get 7 bit i2c-addresses,
-		   so we have to perform a translation */
-		addr = (m[i].addr*2) + ( (0 != (m[i].flags & I2C_M_RD)) ? 1 : 0);
-		h1 = op_count/3; h2 = op_count%3;
-		op[h1] |= cpu_to_le32(	    (u8)addr << ((3-h2)*8));
-		op[h1] |= cpu_to_le32(SAA7146_I2C_START << ((3-h2)*2));
-		op_count++;
-
-		/* loop through all bytes of message i */
-		for(j = 0; j < m[i].len; j++) {
-			/* insert the data bytes */
-			h1 = op_count/3; h2 = op_count%3;
-			op[h1] |= cpu_to_le32( (u32)((u8)m[i].buf[j]) << ((3-h2)*8));
-			op[h1] |= cpu_to_le32(       SAA7146_I2C_CONT << ((3-h2)*2));
-			op_count++;
-		}
-
-	}
-
-	/* have a look at the last byte inserted:
-	  if it was: ...CONT change it to ...STOP */
-	h1 = (op_count-1)/3; h2 = (op_count-1)%3;
-	if ( SAA7146_I2C_CONT == (0x3 & (le32_to_cpu(op[h1]) >> ((3-h2)*2))) ) {
-		op[h1] &= ~cpu_to_le32(0x2 << ((3-h2)*2));
-		op[h1] |= cpu_to_le32(SAA7146_I2C_STOP << ((3-h2)*2));
-	}
-
-	/* return the number of u32s to send */
-	return mem;
-}
-
-/* this functions loops through all i2c-messages. normally, it should determine
-   which bytes were read through the adapter and write them back to the corresponding
-   i2c-message. but instead, we simply write back all bytes.
-   fixme: this could be improved. */
-static int saa7146_i2c_msg_cleanup(const struct i2c_msg *m, int num, __le32 *op)
-{
-	int i, j;
-	int op_count = 0;
-
-	/* loop through all messages */
-	for(i = 0; i < num; i++) {
-
-		op_count++;
-
-		/* loop through all bytes of message i */
-		for(j = 0; j < m[i].len; j++) {
-			/* write back all bytes that could have been read */
-			m[i].buf[j] = (le32_to_cpu(op[op_count/3]) >> ((3-(op_count%3))*8));
-			op_count++;
-		}
-	}
-
-	return 0;
-}
-
-/* this functions resets the i2c-device and returns 0 if everything was fine, otherwise -1 */
-static int saa7146_i2c_reset(struct saa7146_dev *dev)
-{
-	/* get current status */
-	u32 status = saa7146_i2c_status(dev);
-
-	/* clear registers for sure */
-	saa7146_write(dev, I2C_STATUS, dev->i2c_bitrate);
-	saa7146_write(dev, I2C_TRANSFER, 0);
-
-	/* check if any operation is still in progress */
-	if ( 0 != ( status & SAA7146_I2C_BUSY) ) {
-
-		/* yes, kill ongoing operation */
-		DEB_I2C("busy_state detected\n");
-
-		/* set "ABORT-OPERATION"-bit (bit 7)*/
-		saa7146_write(dev, I2C_STATUS, (dev->i2c_bitrate | MASK_07));
-		saa7146_write(dev, MC2, (MASK_00 | MASK_16));
-		msleep(SAA7146_I2C_DELAY);
-
-		/* clear all error-bits pending; this is needed because p.123, note 1 */
-		saa7146_write(dev, I2C_STATUS, dev->i2c_bitrate);
-		saa7146_write(dev, MC2, (MASK_00 | MASK_16));
-		msleep(SAA7146_I2C_DELAY);
-	}
-
-	/* check if any error is (still) present. (this can be necessary because p.123, note 1) */
-	status = saa7146_i2c_status(dev);
-
-	if ( dev->i2c_bitrate != status ) {
-
-		DEB_I2C("error_state detected. status:0x%08x\n", status);
-
-		/* Repeat the abort operation. This seems to be necessary
-		   after serious protocol errors caused by e.g. the SAA7740 */
-		saa7146_write(dev, I2C_STATUS, (dev->i2c_bitrate | MASK_07));
-		saa7146_write(dev, MC2, (MASK_00 | MASK_16));
-		msleep(SAA7146_I2C_DELAY);
-
-		/* clear all error-bits pending */
-		saa7146_write(dev, I2C_STATUS, dev->i2c_bitrate);
-		saa7146_write(dev, MC2, (MASK_00 | MASK_16));
-		msleep(SAA7146_I2C_DELAY);
-
-		/* the data sheet says it might be necessary to clear the status
-		   twice after an abort */
-		saa7146_write(dev, I2C_STATUS, dev->i2c_bitrate);
-		saa7146_write(dev, MC2, (MASK_00 | MASK_16));
-		msleep(SAA7146_I2C_DELAY);
-	}
-
-	/* if any error is still present, a fatal error has occurred ... */
-	status = saa7146_i2c_status(dev);
-	if ( dev->i2c_bitrate != status ) {
-		DEB_I2C("fatal error. status:0x%08x\n", status);
-		return -1;
-	}
-
-	return 0;
-}
-
-/* this functions writes out the data-byte 'dword' to the i2c-device.
-   it returns 0 if ok, -1 if the transfer failed, -2 if the transfer
-   failed badly (e.g. address error) */
-static int saa7146_i2c_writeout(struct saa7146_dev *dev, __le32 *dword, int short_delay)
-{
-	u32 status = 0, mc2 = 0;
-	int trial = 0;
-	unsigned long timeout;
-
-	/* write out i2c-command */
-	DEB_I2C("before: 0x%08x (status: 0x%08x), %d\n",
-		*dword, saa7146_read(dev, I2C_STATUS), dev->i2c_op);
-
-	if( 0 != (SAA7146_USE_I2C_IRQ & dev->ext->flags)) {
-
-		saa7146_write(dev, I2C_STATUS,	 dev->i2c_bitrate);
-		saa7146_write(dev, I2C_TRANSFER, le32_to_cpu(*dword));
-
-		dev->i2c_op = 1;
-		SAA7146_ISR_CLEAR(dev, MASK_16|MASK_17);
-		SAA7146_IER_ENABLE(dev, MASK_16|MASK_17);
-		saa7146_write(dev, MC2, (MASK_00 | MASK_16));
-
-		timeout = HZ/100 + 1; /* 10ms */
-		timeout = wait_event_interruptible_timeout(dev->i2c_wq, dev->i2c_op == 0, timeout);
-		if (timeout == -ERESTARTSYS || dev->i2c_op) {
-			SAA7146_IER_DISABLE(dev, MASK_16|MASK_17);
-			SAA7146_ISR_CLEAR(dev, MASK_16|MASK_17);
-			if (timeout == -ERESTARTSYS)
-				/* a signal arrived */
-				return -ERESTARTSYS;
-
-			pr_warn("%s %s [irq]: timed out waiting for end of xfer\n",
-				dev->name, __func__);
-			return -EIO;
-		}
-		status = saa7146_read(dev, I2C_STATUS);
-	} else {
-		saa7146_write(dev, I2C_STATUS,	 dev->i2c_bitrate);
-		saa7146_write(dev, I2C_TRANSFER, le32_to_cpu(*dword));
-		saa7146_write(dev, MC2, (MASK_00 | MASK_16));
-
-		/* do not poll for i2c-status before upload is complete */
-		timeout = jiffies + HZ/100 + 1; /* 10ms */
-		while(1) {
-			mc2 = (saa7146_read(dev, MC2) & 0x1);
-			if( 0 != mc2 ) {
-				break;
-			}
-			if (time_after(jiffies,timeout)) {
-				pr_warn("%s %s: timed out waiting for MC2\n",
-					dev->name, __func__);
-				return -EIO;
-			}
-		}
-		/* wait until we get a transfer done or error */
-		timeout = jiffies + HZ/100 + 1; /* 10ms */
-		/* first read usually delivers bogus results... */
-		saa7146_i2c_status(dev);
-		while(1) {
-			status = saa7146_i2c_status(dev);
-			if ((status & 0x3) != 1)
-				break;
-			if (time_after(jiffies,timeout)) {
-				/* this is normal when probing the bus
-				 * (no answer from nonexisistant device...)
-				 */
-				pr_warn("%s %s [poll]: timed out waiting for end of xfer\n",
-					dev->name, __func__);
-				return -EIO;
-			}
-			if (++trial < 50 && short_delay)
-				udelay(10);
-			else
-				msleep(1);
-		}
-	}
-
-	/* give a detailed status report */
-	if ( 0 != (status & (SAA7146_I2C_SPERR | SAA7146_I2C_APERR |
-			     SAA7146_I2C_DTERR | SAA7146_I2C_DRERR |
-			     SAA7146_I2C_AL    | SAA7146_I2C_ERR   |
-			     SAA7146_I2C_BUSY)) ) {
-
-		if ( 0 == (status & SAA7146_I2C_ERR) ||
-		     0 == (status & SAA7146_I2C_BUSY) ) {
-			/* it may take some time until ERR goes high - ignore */
-			DEB_I2C("unexpected i2c status %04x\n", status);
-		}
-		if( 0 != (status & SAA7146_I2C_SPERR) ) {
-			DEB_I2C("error due to invalid start/stop condition\n");
-		}
-		if( 0 != (status & SAA7146_I2C_DTERR) ) {
-			DEB_I2C("error in data transmission\n");
-		}
-		if( 0 != (status & SAA7146_I2C_DRERR) ) {
-			DEB_I2C("error when receiving data\n");
-		}
-		if( 0 != (status & SAA7146_I2C_AL) ) {
-			DEB_I2C("error because arbitration lost\n");
-		}
-
-		/* we handle address-errors here */
-		if( 0 != (status & SAA7146_I2C_APERR) ) {
-			DEB_I2C("error in address phase\n");
-			return -EREMOTEIO;
-		}
-
-		return -EIO;
-	}
-
-	/* read back data, just in case we were reading ... */
-	*dword = cpu_to_le32(saa7146_read(dev, I2C_TRANSFER));
-
-	DEB_I2C("after: 0x%08x\n", *dword);
-	return 0;
-}
-
-static int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg *msgs, int num, int retries)
-{
-	int i = 0, count = 0;
-	__le32 *buffer = dev->d_i2c.cpu_addr;
-	int err = 0;
-	int short_delay = 0;
-
-	if (mutex_lock_interruptible(&dev->i2c_lock))
-		return -ERESTARTSYS;
-
-	for(i=0;i<num;i++) {
-		DEB_I2C("msg:%d/%d\n", i+1, num);
-	}
-
-	/* prepare the message(s), get number of u32s to transfer */
-	count = saa7146_i2c_msg_prepare(msgs, num, buffer);
-	if ( 0 > count ) {
-		err = -1;
-		goto out;
-	}
-
-	if ( count > 3 || 0 != (SAA7146_I2C_SHORT_DELAY & dev->ext->flags) )
-		short_delay = 1;
-
-	do {
-		/* reset the i2c-device if necessary */
-		err = saa7146_i2c_reset(dev);
-		if ( 0 > err ) {
-			DEB_I2C("could not reset i2c-device\n");
-			goto out;
-		}
-
-		/* write out the u32s one after another */
-		for(i = 0; i < count; i++) {
-			err = saa7146_i2c_writeout(dev, &buffer[i], short_delay);
-			if ( 0 != err) {
-				/* this one is unsatisfying: some i2c slaves on some
-				   dvb cards don't acknowledge correctly, so the saa7146
-				   thinks that an address error occurred. in that case, the
-				   transaction should be retrying, even if an address error
-				   occurred. analog saa7146 based cards extensively rely on
-				   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. 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;
-			}
-		}
-		if( 0 == err ) {
-			err = num;
-			break;
-		}
-
-		/* delay a bit before retrying */
-		msleep(10);
-
-	} while (err != num && 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)) {
-		DEB_I2C("could not cleanup i2c-message\n");
-		err = -1;
-		goto out;
-	}
-
-	/* return the number of delivered messages */
-	DEB_I2C("transmission successful. (msg:%d)\n", err);
-out:
-	/* another bug in revision 0: the i2c-registers get uploaded randomly by other
-	   uploads, so we better clear them out before continuing */
-	if( 0 == dev->revision ) {
-		__le32 zero = 0;
-		saa7146_i2c_reset(dev);
-		if( 0 != saa7146_i2c_writeout(dev, &zero, short_delay)) {
-			pr_info("revision 0 error. this should never happen\n");
-		}
-	}
-
-	mutex_unlock(&dev->i2c_lock);
-	return err;
-}
-
-/* utility functions */
-static int saa7146_i2c_xfer(struct i2c_adapter* adapter, struct i2c_msg *msg, int num)
-{
-	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);
-}
-
-
-/*****************************************************************************/
-/* i2c-adapter helper functions                                              */
-
-/* exported algorithm data */
-static struct i2c_algorithm saa7146_algo = {
-	.master_xfer	= saa7146_i2c_xfer,
-	.functionality	= saa7146_i2c_func,
-};
-
-int saa7146_i2c_adapter_prepare(struct saa7146_dev *dev, struct i2c_adapter *i2c_adapter, u32 bitrate)
-{
-	DEB_EE("bitrate: 0x%08x\n", bitrate);
-
-	/* enable i2c-port pins */
-	saa7146_write(dev, MC1, (MASK_08 | MASK_24));
-
-	dev->i2c_bitrate = bitrate;
-	saa7146_i2c_reset(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;
-		i2c_adapter->timeout = SAA7146_I2C_TIMEOUT;
-		i2c_adapter->retries = SAA7146_I2C_RETRIES;
-	}
-
-	return 0;
-}
diff --git a/drivers/media/common/saa7146_vbi.c b/drivers/media/common/saa7146_vbi.c
deleted file mode 100644
index 1e71e37..0000000
--- a/drivers/media/common/saa7146_vbi.c
+++ /dev/null
@@ -1,498 +0,0 @@
-#include <media/saa7146_vv.h>
-
-static int vbi_pixel_to_capture = 720 * 2;
-
-static int vbi_workaround(struct saa7146_dev *dev)
-{
-	struct saa7146_vv *vv = dev->vv_data;
-
-	u32          *cpu;
-	dma_addr_t   dma_addr;
-
-	int count = 0;
-	int i;
-
-	DECLARE_WAITQUEUE(wait, current);
-
-	DEB_VBI("dev:%p\n", dev);
-
-	/* once again, a bug in the saa7146: the brs acquisition
-	   is buggy and especially the BXO-counter does not work
-	   as specified. there is this workaround, but please
-	   don't let me explain it. ;-) */
-
-	cpu = pci_alloc_consistent(dev->pci, 4096, &dma_addr);
-	if (NULL == cpu)
-		return -ENOMEM;
-
-	/* setup some basic programming, just for the workaround */
-	saa7146_write(dev, BASE_EVEN3,	dma_addr);
-	saa7146_write(dev, BASE_ODD3,	dma_addr+vbi_pixel_to_capture);
-	saa7146_write(dev, PROT_ADDR3,	dma_addr+4096);
-	saa7146_write(dev, PITCH3,	vbi_pixel_to_capture);
-	saa7146_write(dev, BASE_PAGE3,	0x0);
-	saa7146_write(dev, NUM_LINE_BYTE3, (2<<16)|((vbi_pixel_to_capture)<<0));
-	saa7146_write(dev, MC2, MASK_04|MASK_20);
-
-	/* load brs-control register */
-	WRITE_RPS1(CMD_WR_REG | (1 << 8) | (BRS_CTRL/4));
-	/* BXO = 1h, BRS to outbound */
-	WRITE_RPS1(0xc000008c);
-	/* wait for vbi_a or vbi_b*/
-	if ( 0 != (SAA7146_USE_PORT_B_FOR_VBI & dev->ext_vv_data->flags)) {
-		DEB_D("...using port b\n");
-		WRITE_RPS1(CMD_PAUSE | CMD_OAN | CMD_SIG1 | CMD_E_FID_B);
-		WRITE_RPS1(CMD_PAUSE | CMD_OAN | CMD_SIG1 | CMD_O_FID_B);
-/*
-		WRITE_RPS1(CMD_PAUSE | MASK_09);
-*/
-	} else {
-		DEB_D("...using port a\n");
-		WRITE_RPS1(CMD_PAUSE | MASK_10);
-	}
-	/* upload brs */
-	WRITE_RPS1(CMD_UPLOAD | MASK_08);
-	/* load brs-control register */
-	WRITE_RPS1(CMD_WR_REG | (1 << 8) | (BRS_CTRL/4));
-	/* BYO = 1, BXO = NQBIL (=1728 for PAL, for NTSC this is 858*2) - NumByte3 (=1440) = 288 */
-	WRITE_RPS1(((1728-(vbi_pixel_to_capture)) << 7) | MASK_19);
-	/* wait for brs_done */
-	WRITE_RPS1(CMD_PAUSE | MASK_08);
-	/* upload brs */
-	WRITE_RPS1(CMD_UPLOAD | MASK_08);
-	/* load video-dma3 NumLines3 and NumBytes3 */
-	WRITE_RPS1(CMD_WR_REG | (1 << 8) | (NUM_LINE_BYTE3/4));
-	/* dev->vbi_count*2 lines, 720 pixel (= 1440 Bytes) */
-	WRITE_RPS1((2 << 16) | (vbi_pixel_to_capture));
-	/* load brs-control register */
-	WRITE_RPS1(CMD_WR_REG | (1 << 8) | (BRS_CTRL/4));
-	/* Set BRS right: note: this is an experimental value for BXO (=> PAL!) */
-	WRITE_RPS1((540 << 7) | (5 << 19));  // 5 == vbi_start
-	/* wait for brs_done */
-	WRITE_RPS1(CMD_PAUSE | MASK_08);
-	/* upload brs and video-dma3*/
-	WRITE_RPS1(CMD_UPLOAD | MASK_08 | MASK_04);
-	/* load mc2 register: enable dma3 */
-	WRITE_RPS1(CMD_WR_REG | (1 << 8) | (MC1/4));
-	WRITE_RPS1(MASK_20 | MASK_04);
-	/* generate interrupt */
-	WRITE_RPS1(CMD_INTERRUPT);
-	/* stop rps1 */
-	WRITE_RPS1(CMD_STOP);
-
-	/* we have to do the workaround twice to be sure that
-	   everything is ok */
-	for(i = 0; i < 2; i++) {
-
-		/* indicate to the irq handler that we do the workaround */
-		saa7146_write(dev, MC2, MASK_31|MASK_15);
-
-		saa7146_write(dev, NUM_LINE_BYTE3, (1<<16)|(2<<0));
-		saa7146_write(dev, MC2, MASK_04|MASK_20);
-
-		/* enable rps1 irqs */
-		SAA7146_IER_ENABLE(dev,MASK_28);
-
-		/* prepare to wait to be woken up by the irq-handler */
-		add_wait_queue(&vv->vbi_wq, &wait);
-		current->state = TASK_INTERRUPTIBLE;
-
-		/* start rps1 to enable workaround */
-		saa7146_write(dev, RPS_ADDR1, dev->d_rps1.dma_handle);
-		saa7146_write(dev, MC1, (MASK_13 | MASK_29));
-
-		schedule();
-
-		DEB_VBI("brs bug workaround %d/1\n", i);
-
-		remove_wait_queue(&vv->vbi_wq, &wait);
-		current->state = TASK_RUNNING;
-
-		/* disable rps1 irqs */
-		SAA7146_IER_DISABLE(dev,MASK_28);
-
-		/* stop video-dma3 */
-		saa7146_write(dev, MC1, MASK_20);
-
-		if(signal_pending(current)) {
-
-			DEB_VBI("aborted (rps:0x%08x)\n",
-				saa7146_read(dev, RPS_ADDR1));
-
-			/* stop rps1 for sure */
-			saa7146_write(dev, MC1, MASK_29);
-
-			pci_free_consistent(dev->pci, 4096, cpu, dma_addr);
-			return -EINTR;
-		}
-	}
-
-	pci_free_consistent(dev->pci, 4096, cpu, dma_addr);
-	return 0;
-}
-
-static void saa7146_set_vbi_capture(struct saa7146_dev *dev, struct saa7146_buf *buf, struct saa7146_buf *next)
-{
-	struct saa7146_vv *vv = dev->vv_data;
-
-	struct saa7146_video_dma vdma3;
-
-	int count = 0;
-	unsigned long e_wait = vv->current_hps_sync == SAA7146_HPS_SYNC_PORT_A ? CMD_E_FID_A : CMD_E_FID_B;
-	unsigned long o_wait = vv->current_hps_sync == SAA7146_HPS_SYNC_PORT_A ? CMD_O_FID_A : CMD_O_FID_B;
-
-/*
-	vdma3.base_even	= 0xc8000000+2560*70;
-	vdma3.base_odd	= 0xc8000000;
-	vdma3.prot_addr	= 0xc8000000+2560*164;
-	vdma3.pitch	= 2560;
-	vdma3.base_page	= 0;
-	vdma3.num_line_byte = (64<<16)|((vbi_pixel_to_capture)<<0); // set above!
-*/
-	vdma3.base_even	= buf->pt[2].offset;
-	vdma3.base_odd	= buf->pt[2].offset + 16 * vbi_pixel_to_capture;
-	vdma3.prot_addr	= buf->pt[2].offset + 16 * 2 * vbi_pixel_to_capture;
-	vdma3.pitch	= vbi_pixel_to_capture;
-	vdma3.base_page	= buf->pt[2].dma | ME1;
-	vdma3.num_line_byte = (16 << 16) | vbi_pixel_to_capture;
-
-	saa7146_write_out_dma(dev, 3, &vdma3);
-
-	/* write beginning of rps-program */
-	count = 0;
-
-	/* wait for o_fid_a/b / e_fid_a/b toggle only if bit 1 is not set */
-
-	/* we don't wait here for the first field anymore. this is different from the video
-	   capture and might cause that the first buffer is only half filled (with only
-	   one field). but since this is some sort of streaming data, this is not that negative.
-	   but by doing this, we can use the whole engine from videobuf-dma-sg.c... */
-
-/*
-	WRITE_RPS1(CMD_PAUSE | CMD_OAN | CMD_SIG1 | e_wait);
-	WRITE_RPS1(CMD_PAUSE | CMD_OAN | CMD_SIG1 | o_wait);
-*/
-	/* set bit 1 */
-	WRITE_RPS1(CMD_WR_REG | (1 << 8) | (MC2/4));
-	WRITE_RPS1(MASK_28 | MASK_12);
-
-	/* turn on video-dma3 */
-	WRITE_RPS1(CMD_WR_REG_MASK | (MC1/4));
-	WRITE_RPS1(MASK_04 | MASK_20);			/* => mask */
-	WRITE_RPS1(MASK_04 | MASK_20);			/* => values */
-
-	/* wait for o_fid_a/b / e_fid_a/b toggle */
-	WRITE_RPS1(CMD_PAUSE | o_wait);
-	WRITE_RPS1(CMD_PAUSE | e_wait);
-
-	/* generate interrupt */
-	WRITE_RPS1(CMD_INTERRUPT);
-
-	/* stop */
-	WRITE_RPS1(CMD_STOP);
-
-	/* enable rps1 irqs */
-	SAA7146_IER_ENABLE(dev, MASK_28);
-
-	/* write the address of the rps-program */
-	saa7146_write(dev, RPS_ADDR1, dev->d_rps1.dma_handle);
-
-	/* turn on rps */
-	saa7146_write(dev, MC1, (MASK_13 | MASK_29));
-}
-
-static int buffer_activate(struct saa7146_dev *dev,
-			   struct saa7146_buf *buf,
-			   struct saa7146_buf *next)
-{
-	struct saa7146_vv *vv = dev->vv_data;
-	buf->vb.state = VIDEOBUF_ACTIVE;
-
-	DEB_VBI("dev:%p, buf:%p, next:%p\n", dev, buf, next);
-	saa7146_set_vbi_capture(dev,buf,next);
-
-	mod_timer(&vv->vbi_dmaq.timeout, jiffies+BUFFER_TIMEOUT);
-	return 0;
-}
-
-static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,enum v4l2_field field)
-{
-	struct file *file = q->priv_data;
-	struct saa7146_fh *fh = file->private_data;
-	struct saa7146_dev *dev = fh->dev;
-	struct saa7146_buf *buf = (struct saa7146_buf *)vb;
-
-	int err = 0;
-	int lines, llength, size;
-
-	lines   = 16 * 2 ; /* 2 fields */
-	llength = vbi_pixel_to_capture;
-	size = lines * llength;
-
-	DEB_VBI("vb:%p\n", vb);
-
-	if (0 != buf->vb.baddr  &&  buf->vb.bsize < size) {
-		DEB_VBI("size mismatch\n");
-		return -EINVAL;
-	}
-
-	if (buf->vb.size != size)
-		saa7146_dma_free(dev,q,buf);
-
-	if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
-		struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
-
-		buf->vb.width  = llength;
-		buf->vb.height = lines;
-		buf->vb.size   = size;
-		buf->vb.field  = field;	// FIXME: check this
-
-		saa7146_pgtable_free(dev->pci, &buf->pt[2]);
-		saa7146_pgtable_alloc(dev->pci, &buf->pt[2]);
-
-		err = videobuf_iolock(q,&buf->vb, NULL);
-		if (err)
-			goto oops;
-		err = saa7146_pgtable_build_single(dev->pci, &buf->pt[2],
-						 dma->sglist, dma->sglen);
-		if (0 != err)
-			return err;
-	}
-	buf->vb.state = VIDEOBUF_PREPARED;
-	buf->activate = buffer_activate;
-
-	return 0;
-
- oops:
-	DEB_VBI("error out\n");
-	saa7146_dma_free(dev,q,buf);
-
-	return err;
-}
-
-static int buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
-{
-	int llength,lines;
-
-	lines   = 16 * 2 ; /* 2 fields */
-	llength = vbi_pixel_to_capture;
-
-	*size = lines * llength;
-	*count = 2;
-
-	DEB_VBI("count:%d, size:%d\n", *count, *size);
-
-	return 0;
-}
-
-static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
-{
-	struct file *file = q->priv_data;
-	struct saa7146_fh *fh = file->private_data;
-	struct saa7146_dev *dev = fh->dev;
-	struct saa7146_vv *vv = dev->vv_data;
-	struct saa7146_buf *buf = (struct saa7146_buf *)vb;
-
-	DEB_VBI("vb:%p\n", vb);
-	saa7146_buffer_queue(dev, &vv->vbi_dmaq, buf);
-}
-
-static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
-{
-	struct file *file = q->priv_data;
-	struct saa7146_fh *fh   = file->private_data;
-	struct saa7146_dev *dev = fh->dev;
-	struct saa7146_buf *buf = (struct saa7146_buf *)vb;
-
-	DEB_VBI("vb:%p\n", vb);
-	saa7146_dma_free(dev,q,buf);
-}
-
-static struct videobuf_queue_ops vbi_qops = {
-	.buf_setup    = buffer_setup,
-	.buf_prepare  = buffer_prepare,
-	.buf_queue    = buffer_queue,
-	.buf_release  = buffer_release,
-};
-
-/* ------------------------------------------------------------------ */
-
-static void vbi_stop(struct saa7146_fh *fh, struct file *file)
-{
-	struct saa7146_dev *dev = fh->dev;
-	struct saa7146_vv *vv = dev->vv_data;
-	unsigned long flags;
-	DEB_VBI("dev:%p, fh:%p\n", dev, fh);
-
-	spin_lock_irqsave(&dev->slock,flags);
-
-	/* disable rps1  */
-	saa7146_write(dev, MC1, MASK_29);
-
-	/* disable rps1 irqs */
-	SAA7146_IER_DISABLE(dev, MASK_28);
-
-	/* shut down dma 3 transfers */
-	saa7146_write(dev, MC1, MASK_20);
-
-	if (vv->vbi_dmaq.curr)
-		saa7146_buffer_finish(dev, &vv->vbi_dmaq, VIDEOBUF_DONE);
-
-	videobuf_queue_cancel(&fh->vbi_q);
-
-	vv->vbi_streaming = NULL;
-
-	del_timer(&vv->vbi_dmaq.timeout);
-	del_timer(&vv->vbi_read_timeout);
-
-	spin_unlock_irqrestore(&dev->slock, flags);
-}
-
-static void vbi_read_timeout(unsigned long data)
-{
-	struct file *file = (struct file*)data;
-	struct saa7146_fh *fh = file->private_data;
-	struct saa7146_dev *dev = fh->dev;
-
-	DEB_VBI("dev:%p, fh:%p\n", dev, fh);
-
-	vbi_stop(fh, file);
-}
-
-static void vbi_init(struct saa7146_dev *dev, struct saa7146_vv *vv)
-{
-	DEB_VBI("dev:%p\n", dev);
-
-	INIT_LIST_HEAD(&vv->vbi_dmaq.queue);
-
-	init_timer(&vv->vbi_dmaq.timeout);
-	vv->vbi_dmaq.timeout.function = saa7146_buffer_timeout;
-	vv->vbi_dmaq.timeout.data     = (unsigned long)(&vv->vbi_dmaq);
-	vv->vbi_dmaq.dev              = dev;
-
-	init_waitqueue_head(&vv->vbi_wq);
-}
-
-static int vbi_open(struct saa7146_dev *dev, struct file *file)
-{
-	struct saa7146_fh *fh = file->private_data;
-	struct saa7146_vv *vv = fh->dev->vv_data;
-
-	u32 arbtr_ctrl	= saa7146_read(dev, PCI_BT_V1);
-	int ret = 0;
-
-	DEB_VBI("dev:%p, fh:%p\n", dev, fh);
-
-	ret = saa7146_res_get(fh, RESOURCE_DMA3_BRS);
-	if (0 == ret) {
-		DEB_S("cannot get vbi RESOURCE_DMA3_BRS resource\n");
-		return -EBUSY;
-	}
-
-	/* adjust arbitrition control for video dma 3 */
-	arbtr_ctrl &= ~0x1f0000;
-	arbtr_ctrl |=  0x1d0000;
-	saa7146_write(dev, PCI_BT_V1, arbtr_ctrl);
-	saa7146_write(dev, MC2, (MASK_04|MASK_20));
-
-	videobuf_queue_sg_init(&fh->vbi_q, &vbi_qops,
-			    &dev->pci->dev, &dev->slock,
-			    V4L2_BUF_TYPE_VBI_CAPTURE,
-			    V4L2_FIELD_SEQ_TB, // FIXME: does this really work?
-			    sizeof(struct saa7146_buf),
-			    file, &dev->v4l2_lock);
-
-	vv->vbi_read_timeout.function = vbi_read_timeout;
-	vv->vbi_read_timeout.data = (unsigned long)file;
-
-	/* initialize the brs */
-	if ( 0 != (SAA7146_USE_PORT_B_FOR_VBI & dev->ext_vv_data->flags)) {
-		saa7146_write(dev, BRS_CTRL, MASK_30|MASK_29 | (7 << 19));
-	} else {
-		saa7146_write(dev, BRS_CTRL, 0x00000001);
-
-		if (0 != (ret = vbi_workaround(dev))) {
-			DEB_VBI("vbi workaround failed!\n");
-			/* return ret;*/
-		}
-	}
-
-	/* upload brs register */
-	saa7146_write(dev, MC2, (MASK_08|MASK_24));
-	return 0;
-}
-
-static void vbi_close(struct saa7146_dev *dev, struct file *file)
-{
-	struct saa7146_fh *fh = file->private_data;
-	struct saa7146_vv *vv = dev->vv_data;
-	DEB_VBI("dev:%p, fh:%p\n", dev, fh);
-
-	if( fh == vv->vbi_streaming ) {
-		vbi_stop(fh, file);
-	}
-	saa7146_res_free(fh, RESOURCE_DMA3_BRS);
-}
-
-static void vbi_irq_done(struct saa7146_dev *dev, unsigned long status)
-{
-	struct saa7146_vv *vv = dev->vv_data;
-	spin_lock(&dev->slock);
-
-	if (vv->vbi_dmaq.curr) {
-		DEB_VBI("dev:%p, curr:%p\n", dev, vv->vbi_dmaq.curr);
-		/* this must be += 2, one count for each field */
-		vv->vbi_fieldcount+=2;
-		vv->vbi_dmaq.curr->vb.field_count = vv->vbi_fieldcount;
-		saa7146_buffer_finish(dev, &vv->vbi_dmaq, VIDEOBUF_DONE);
-	} else {
-		DEB_VBI("dev:%p\n", dev);
-	}
-	saa7146_buffer_next(dev, &vv->vbi_dmaq, 1);
-
-	spin_unlock(&dev->slock);
-}
-
-static ssize_t vbi_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
-{
-	struct saa7146_fh *fh = file->private_data;
-	struct saa7146_dev *dev = fh->dev;
-	struct saa7146_vv *vv = dev->vv_data;
-	ssize_t ret = 0;
-
-	DEB_VBI("dev:%p, fh:%p\n", dev, fh);
-
-	if( NULL == vv->vbi_streaming ) {
-		// fixme: check if dma3 is available
-		// fixme: activate vbi engine here if necessary. (really?)
-		vv->vbi_streaming = fh;
-	}
-
-	if( fh != vv->vbi_streaming ) {
-		DEB_VBI("open %p is already using vbi capture\n",
-			vv->vbi_streaming);
-		return -EBUSY;
-	}
-
-	mod_timer(&vv->vbi_read_timeout, jiffies+BUFFER_TIMEOUT);
-	ret = videobuf_read_stream(&fh->vbi_q, data, count, ppos, 1,
-				   file->f_flags & O_NONBLOCK);
-/*
-	printk("BASE_ODD3:      0x%08x\n", saa7146_read(dev, BASE_ODD3));
-	printk("BASE_EVEN3:     0x%08x\n", saa7146_read(dev, BASE_EVEN3));
-	printk("PROT_ADDR3:     0x%08x\n", saa7146_read(dev, PROT_ADDR3));
-	printk("PITCH3:         0x%08x\n", saa7146_read(dev, PITCH3));
-	printk("BASE_PAGE3:     0x%08x\n", saa7146_read(dev, BASE_PAGE3));
-	printk("NUM_LINE_BYTE3: 0x%08x\n", saa7146_read(dev, NUM_LINE_BYTE3));
-	printk("BRS_CTRL:       0x%08x\n", saa7146_read(dev, BRS_CTRL));
-*/
-	return ret;
-}
-
-struct saa7146_use_ops saa7146_vbi_uops = {
-	.init		= vbi_init,
-	.open		= vbi_open,
-	.release	= vbi_close,
-	.irq_done	= vbi_irq_done,
-	.read		= vbi_read,
-};
diff --git a/drivers/media/common/saa7146_video.c b/drivers/media/common/saa7146_video.c
deleted file mode 100644
index 6d14785..0000000
--- a/drivers/media/common/saa7146_video.c
+++ /dev/null
@@ -1,1332 +0,0 @@
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <media/saa7146_vv.h>
-#include <media/v4l2-chip-ident.h>
-#include <media/v4l2-event.h>
-#include <media/v4l2-ctrls.h>
-#include <linux/module.h>
-
-static int max_memory = 32;
-
-module_param(max_memory, int, 0644);
-MODULE_PARM_DESC(max_memory, "maximum memory usage for capture buffers (default: 32Mb)");
-
-#define IS_CAPTURE_ACTIVE(fh) \
-	(((vv->video_status & STATUS_CAPTURE) != 0) && (vv->video_fh == fh))
-
-#define IS_OVERLAY_ACTIVE(fh) \
-	(((vv->video_status & STATUS_OVERLAY) != 0) && (vv->video_fh == fh))
-
-/* format descriptions for capture and preview */
-static struct saa7146_format formats[] = {
-	{
-		.name		= "RGB-8 (3-3-2)",
-		.pixelformat	= V4L2_PIX_FMT_RGB332,
-		.trans		= RGB08_COMPOSED,
-		.depth		= 8,
-		.flags		= 0,
-	}, {
-		.name		= "RGB-16 (5/B-6/G-5/R)",
-		.pixelformat	= V4L2_PIX_FMT_RGB565,
-		.trans		= RGB16_COMPOSED,
-		.depth		= 16,
-		.flags		= 0,
-	}, {
-		.name		= "RGB-24 (B-G-R)",
-		.pixelformat	= V4L2_PIX_FMT_BGR24,
-		.trans		= RGB24_COMPOSED,
-		.depth		= 24,
-		.flags		= 0,
-	}, {
-		.name		= "RGB-32 (B-G-R)",
-		.pixelformat	= V4L2_PIX_FMT_BGR32,
-		.trans		= RGB32_COMPOSED,
-		.depth		= 32,
-		.flags		= 0,
-	}, {
-		.name		= "RGB-32 (R-G-B)",
-		.pixelformat	= V4L2_PIX_FMT_RGB32,
-		.trans		= RGB32_COMPOSED,
-		.depth		= 32,
-		.flags		= 0,
-		.swap		= 0x2,
-	}, {
-		.name		= "Greyscale-8",
-		.pixelformat	= V4L2_PIX_FMT_GREY,
-		.trans		= Y8,
-		.depth		= 8,
-		.flags		= 0,
-	}, {
-		.name		= "YUV 4:2:2 planar (Y-Cb-Cr)",
-		.pixelformat	= V4L2_PIX_FMT_YUV422P,
-		.trans		= YUV422_DECOMPOSED,
-		.depth		= 16,
-		.flags		= FORMAT_BYTE_SWAP|FORMAT_IS_PLANAR,
-	}, {
-		.name		= "YVU 4:2:0 planar (Y-Cb-Cr)",
-		.pixelformat	= V4L2_PIX_FMT_YVU420,
-		.trans		= YUV420_DECOMPOSED,
-		.depth		= 12,
-		.flags		= FORMAT_BYTE_SWAP|FORMAT_IS_PLANAR,
-	}, {
-		.name		= "YUV 4:2:0 planar (Y-Cb-Cr)",
-		.pixelformat	= V4L2_PIX_FMT_YUV420,
-		.trans		= YUV420_DECOMPOSED,
-		.depth		= 12,
-		.flags		= FORMAT_IS_PLANAR,
-	}, {
-		.name		= "YUV 4:2:2 (U-Y-V-Y)",
-		.pixelformat	= V4L2_PIX_FMT_UYVY,
-		.trans		= YUV422_COMPOSED,
-		.depth		= 16,
-		.flags		= 0,
-	}
-};
-
-/* unfortunately, the saa7146 contains a bug which prevents it from doing on-the-fly byte swaps.
-   due to this, it's impossible to provide additional *packed* formats, which are simply byte swapped
-   (like V4L2_PIX_FMT_YUYV) ... 8-( */
-
-static int NUM_FORMATS = sizeof(formats)/sizeof(struct saa7146_format);
-
-struct saa7146_format* saa7146_format_by_fourcc(struct saa7146_dev *dev, int fourcc)
-{
-	int i, j = NUM_FORMATS;
-
-	for (i = 0; i < j; i++) {
-		if (formats[i].pixelformat == fourcc) {
-			return formats+i;
-		}
-	}
-
-	DEB_D("unknown pixelformat:'%4.4s'\n", (char *)&fourcc);
-	return NULL;
-}
-
-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);
-
-	/* check if we have overlay information */
-	if (vv->ov.fh == NULL) {
-		DEB_D("no overlay data available. try S_FMT first.\n");
-		return -EAGAIN;
-	}
-
-	/* check if streaming capture is running */
-	if (IS_CAPTURE_ACTIVE(fh) != 0) {
-		DEB_D("streaming capture is active\n");
-		return -EBUSY;
-	}
-
-	/* check if overlay is running */
-	if (IS_OVERLAY_ACTIVE(fh) != 0) {
-		if (vv->video_fh == fh) {
-			DEB_D("overlay is already active\n");
-			return 0;
-		}
-		DEB_D("overlay is already active in another open\n");
-		return -EBUSY;
-	}
-
-	if (0 == saa7146_res_get(fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP)) {
-		DEB_D("cannot get necessary overlay resources\n");
-		return -EBUSY;
-	}
-
-	fmt.fmt.win = vv->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;
-	}
-	vv->ov.win = fmt.fmt.win;
-
-	DEB_D("%dx%d+%d+%d %s field=%s\n",
-	      vv->ov.win.w.width, vv->ov.win.w.height,
-	      vv->ov.win.w.left, vv->ov.win.w.top,
-	      vv->ov_fmt->name, v4l2_field_names[vv->ov.win.field]);
-
-	if (0 != (ret = saa7146_enable_overlay(fh))) {
-		DEB_D("enabling overlay failed: %d\n", ret);
-		saa7146_res_free(vv->video_fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP);
-		return ret;
-	}
-
-	vv->video_status = STATUS_OVERLAY;
-	vv->video_fh = fh;
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(saa7146_start_preview);
-
-int saa7146_stop_preview(struct saa7146_fh *fh)
-{
-	struct saa7146_dev *dev = fh->dev;
-	struct saa7146_vv *vv = dev->vv_data;
-
-	DEB_EE("dev:%p, fh:%p\n", dev, fh);
-
-	/* check if streaming capture is running */
-	if (IS_CAPTURE_ACTIVE(fh) != 0) {
-		DEB_D("streaming capture is active\n");
-		return -EBUSY;
-	}
-
-	/* check if overlay is running at all */
-	if ((vv->video_status & STATUS_OVERLAY) == 0) {
-		DEB_D("no active overlay\n");
-		return 0;
-	}
-
-	if (vv->video_fh != fh) {
-		DEB_D("overlay is active, but in another open\n");
-		return -EBUSY;
-	}
-
-	vv->video_status = 0;
-	vv->video_fh = NULL;
-
-	saa7146_disable_overlay(fh);
-
-	saa7146_res_free(fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP);
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(saa7146_stop_preview);
-
-/********************************************************************************/
-/* common pagetable functions */
-
-static int saa7146_pgtable_build(struct saa7146_dev *dev, struct saa7146_buf *buf)
-{
-	struct pci_dev *pci = dev->pci;
-	struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
-	struct scatterlist *list = dma->sglist;
-	int length = dma->sglen;
-	struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat);
-
-	DEB_EE("dev:%p, buf:%p, sg_len:%d\n", dev, buf, length);
-
-	if( 0 != IS_PLANAR(sfmt->trans)) {
-		struct saa7146_pgtable *pt1 = &buf->pt[0];
-		struct saa7146_pgtable *pt2 = &buf->pt[1];
-		struct saa7146_pgtable *pt3 = &buf->pt[2];
-		__le32  *ptr1, *ptr2, *ptr3;
-		__le32 fill;
-
-		int size = buf->fmt->width*buf->fmt->height;
-		int i,p,m1,m2,m3,o1,o2;
-
-		switch( sfmt->depth ) {
-			case 12: {
-				/* create some offsets inside the page table */
-				m1 = ((size+PAGE_SIZE)/PAGE_SIZE)-1;
-				m2 = ((size+(size/4)+PAGE_SIZE)/PAGE_SIZE)-1;
-				m3 = ((size+(size/2)+PAGE_SIZE)/PAGE_SIZE)-1;
-				o1 = size%PAGE_SIZE;
-				o2 = (size+(size/4))%PAGE_SIZE;
-				DEB_CAP("size:%d, m1:%d, m2:%d, m3:%d, o1:%d, o2:%d\n",
-					size, m1, m2, m3, o1, o2);
-				break;
-			}
-			case 16: {
-				/* create some offsets inside the page table */
-				m1 = ((size+PAGE_SIZE)/PAGE_SIZE)-1;
-				m2 = ((size+(size/2)+PAGE_SIZE)/PAGE_SIZE)-1;
-				m3 = ((2*size+PAGE_SIZE)/PAGE_SIZE)-1;
-				o1 = size%PAGE_SIZE;
-				o2 = (size+(size/2))%PAGE_SIZE;
-				DEB_CAP("size:%d, m1:%d, m2:%d, m3:%d, o1:%d, o2:%d\n",
-					size, m1, m2, m3, o1, o2);
-				break;
-			}
-			default: {
-				return -1;
-			}
-		}
-
-		ptr1 = pt1->cpu;
-		ptr2 = pt2->cpu;
-		ptr3 = pt3->cpu;
-
-		/* walk all pages, copy all page addresses to ptr1 */
-		for (i = 0; i < length; i++, list++) {
-			for (p = 0; p * 4096 < list->length; p++, ptr1++) {
-				*ptr1 = cpu_to_le32(sg_dma_address(list) - list->offset);
-			}
-		}
-/*
-		ptr1 = pt1->cpu;
-		for(j=0;j<40;j++) {
-			printk("ptr1 %d: 0x%08x\n",j,ptr1[j]);
-		}
-*/
-
-		/* if we have a user buffer, the first page may not be
-		   aligned to a page boundary. */
-		pt1->offset = dma->sglist->offset;
-		pt2->offset = pt1->offset+o1;
-		pt3->offset = pt1->offset+o2;
-
-		/* create video-dma2 page table */
-		ptr1 = pt1->cpu;
-		for(i = m1; i <= m2 ; i++, ptr2++) {
-			*ptr2 = ptr1[i];
-		}
-		fill = *(ptr2-1);
-		for(;i<1024;i++,ptr2++) {
-			*ptr2 = fill;
-		}
-		/* create video-dma3 page table */
-		ptr1 = pt1->cpu;
-		for(i = m2; i <= m3; i++,ptr3++) {
-			*ptr3 = ptr1[i];
-		}
-		fill = *(ptr3-1);
-		for(;i<1024;i++,ptr3++) {
-			*ptr3 = fill;
-		}
-		/* finally: finish up video-dma1 page table */
-		ptr1 = pt1->cpu+m1;
-		fill = pt1->cpu[m1];
-		for(i=m1;i<1024;i++,ptr1++) {
-			*ptr1 = fill;
-		}
-/*
-		ptr1 = pt1->cpu;
-		ptr2 = pt2->cpu;
-		ptr3 = pt3->cpu;
-		for(j=0;j<40;j++) {
-			printk("ptr1 %d: 0x%08x\n",j,ptr1[j]);
-		}
-		for(j=0;j<40;j++) {
-			printk("ptr2 %d: 0x%08x\n",j,ptr2[j]);
-		}
-		for(j=0;j<40;j++) {
-			printk("ptr3 %d: 0x%08x\n",j,ptr3[j]);
-		}
-*/
-	} else {
-		struct saa7146_pgtable *pt = &buf->pt[0];
-		return saa7146_pgtable_build_single(pci, pt, list, length);
-	}
-
-	return 0;
-}
-
-
-/********************************************************************************/
-/* file operations */
-
-static int video_begin(struct saa7146_fh *fh)
-{
-	struct saa7146_dev *dev = fh->dev;
-	struct saa7146_vv *vv = dev->vv_data;
-	struct saa7146_format *fmt = NULL;
-	unsigned int resource;
-	int ret = 0, err = 0;
-
-	DEB_EE("dev:%p, fh:%p\n", dev, fh);
-
-	if ((vv->video_status & STATUS_CAPTURE) != 0) {
-		if (vv->video_fh == fh) {
-			DEB_S("already capturing\n");
-			return 0;
-		}
-		DEB_S("already capturing in another open\n");
-		return -EBUSY;
-	}
-
-	if ((vv->video_status & STATUS_OVERLAY) != 0) {
-		DEB_S("warning: suspending overlay video for streaming capture\n");
-		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;
-		}
-	}
-
-	fmt = saa7146_format_by_fourcc(dev, vv->video_fmt.pixelformat);
-	/* we need to have a valid format set here */
-	BUG_ON(NULL == fmt);
-
-	if (0 != (fmt->flags & FORMAT_IS_PLANAR)) {
-		resource = RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP|RESOURCE_DMA3_BRS;
-	} else {
-		resource = RESOURCE_DMA1_HPS;
-	}
-
-	ret = saa7146_res_get(fh, resource);
-	if (0 == ret) {
-		DEB_S("cannot get capture resource %d\n", resource);
-		if (vv->ov_suspend != NULL) {
-			saa7146_start_preview(vv->ov_suspend);
-			vv->ov_suspend = NULL;
-		}
-		return -EBUSY;
-	}
-
-	/* clear out beginning of streaming bit (rps register 0)*/
-	saa7146_write(dev, MC2, MASK_27 );
-
-	/* enable rps0 irqs */
-	SAA7146_IER_ENABLE(dev, MASK_27);
-
-	vv->video_fh = fh;
-	vv->video_status = STATUS_CAPTURE;
-
-	return 0;
-}
-
-static int video_end(struct saa7146_fh *fh, struct file *file)
-{
-	struct saa7146_dev *dev = fh->dev;
-	struct saa7146_vv *vv = dev->vv_data;
-	struct saa7146_format *fmt = NULL;
-	unsigned long flags;
-	unsigned int resource;
-	u32 dmas = 0;
-	DEB_EE("dev:%p, fh:%p\n", dev, fh);
-
-	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;
-	}
-
-	fmt = saa7146_format_by_fourcc(dev, vv->video_fmt.pixelformat);
-	/* we need to have a valid format set here */
-	BUG_ON(NULL == fmt);
-
-	if (0 != (fmt->flags & FORMAT_IS_PLANAR)) {
-		resource = RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP|RESOURCE_DMA3_BRS;
-		dmas = MASK_22 | MASK_21 | MASK_20;
-	} else {
-		resource = RESOURCE_DMA1_HPS;
-		dmas = MASK_22;
-	}
-	spin_lock_irqsave(&dev->slock,flags);
-
-	/* disable rps0  */
-	saa7146_write(dev, MC1, MASK_28);
-
-	/* disable rps0 irqs */
-	SAA7146_IER_DISABLE(dev, MASK_27);
-
-	/* shut down all used video dma transfers */
-	saa7146_write(dev, MC1, dmas);
-
-	spin_unlock_irqrestore(&dev->slock, flags);
-
-	vv->video_fh = NULL;
-	vv->video_status = 0;
-
-	saa7146_res_free(fh, resource);
-
-	if (vv->ov_suspend != NULL) {
-		saa7146_start_preview(vv->ov_suspend);
-		vv->ov_suspend = NULL;
-	}
-
-	return 0;
-}
-
-static int vidioc_querycap(struct file *file, void *fh, struct v4l2_capability *cap)
-{
-	struct video_device *vdev = video_devdata(file);
-	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->device_caps =
-		V4L2_CAP_VIDEO_CAPTURE |
-		V4L2_CAP_VIDEO_OVERLAY |
-		V4L2_CAP_READWRITE |
-		V4L2_CAP_STREAMING;
-	cap->device_caps |= dev->ext_vv_data->capabilities;
-	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
-	if (vdev->vfl_type == VFL_TYPE_GRABBER)
-		cap->device_caps &=
-			~(V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_OUTPUT);
-	else
-		cap->device_caps &=
-			~(V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OVERLAY | V4L2_CAP_AUDIO);
-	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;
-
-	*fb = vv->ov_fb;
-	fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING;
-	fb->flags = V4L2_FBUF_FLAG_PRIMARY;
-	return 0;
-}
-
-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;
-
-	DEB_EE("VIDIOC_S_FBUF\n");
-
-	if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RAWIO))
-		return -EPERM;
-
-	/* check args */
-	fmt = saa7146_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;
-		}
-	}
-
-	/* ok, accept it */
-	vv->ov_fb = *fb;
-	vv->ov_fmt = fmt;
-
-	if (vv->ov_fb.fmt.bytesperline < vv->ov_fb.fmt.width) {
-		vv->ov_fb.fmt.bytesperline = vv->ov_fb.fmt.width * fmt->depth / 8;
-		DEB_D("setting bytesperline to %d\n", vv->ov_fb.fmt.bytesperline);
-	}
-	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;
-}
-
-int saa7146_s_ctrl(struct v4l2_ctrl *ctrl)
-{
-	struct saa7146_dev *dev = container_of(ctrl->handler,
-				struct saa7146_dev, ctrl_handler);
-	struct saa7146_vv *vv = dev->vv_data;
-	u32 val;
-
-	switch (ctrl->id) {
-	case V4L2_CID_BRIGHTNESS:
-		val = saa7146_read(dev, BCS_CTRL);
-		val &= 0x00ffffff;
-		val |= (ctrl->val << 24);
-		saa7146_write(dev, BCS_CTRL, val);
-		saa7146_write(dev, MC2, MASK_22 | MASK_06);
-		break;
-
-	case V4L2_CID_CONTRAST:
-		val = saa7146_read(dev, BCS_CTRL);
-		val &= 0xff00ffff;
-		val |= (ctrl->val << 16);
-		saa7146_write(dev, BCS_CTRL, val);
-		saa7146_write(dev, MC2, MASK_22 | MASK_06);
-		break;
-
-	case V4L2_CID_SATURATION:
-		val = saa7146_read(dev, BCS_CTRL);
-		val &= 0xffffff00;
-		val |= (ctrl->val << 0);
-		saa7146_write(dev, BCS_CTRL, val);
-		saa7146_write(dev, MC2, MASK_22 | MASK_06);
-		break;
-
-	case V4L2_CID_HFLIP:
-		/* fixme: we can support changing VFLIP and HFLIP here... */
-		if ((vv->video_status & STATUS_CAPTURE))
-			return -EBUSY;
-		vv->hflip = ctrl->val;
-		break;
-
-	case V4L2_CID_VFLIP:
-		if ((vv->video_status & STATUS_CAPTURE))
-			return -EBUSY;
-		vv->vflip = ctrl->val;
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	if ((vv->video_status & STATUS_OVERLAY) != 0) { /* CHECK: && (vv->video_fh == fh)) */
-		struct saa7146_fh *fh = vv->video_fh;
-
-		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;
-
-	if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		return -EINVAL;
-	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)
-{
-	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
-	struct saa7146_vv *vv = dev->vv_data;
-
-	f->fmt.pix = vv->video_fmt;
-	return 0;
-}
-
-static int vidioc_g_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;
-
-	f->fmt.win = vv->ov.win;
-	return 0;
-}
-
-static int vidioc_g_fmt_vbi_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;
-
-	f->fmt.vbi = vv->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 = saa7146_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;
-	f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
-	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;
-		}
-	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 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;
-	}
-	err = vidioc_try_fmt_vid_cap(file, fh, f);
-	if (0 != err)
-		return err;
-	vv->video_fmt = f->fmt.pix;
-	DEB_EE("set to pixelformat '%4.4s'\n",
-	       (char *)&vv->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;
-	vv->ov.win    = f->fmt.win;
-	vv->ov.nclips = f->fmt.win.clipcount;
-	if (vv->ov.nclips > 16)
-		vv->ov.nclips = 16;
-	if (copy_from_user(vv->ov.clips, f->fmt.win.clips,
-				sizeof(struct v4l2_clip) * vv->ov.nclips)) {
-		return -EFAULT;
-	}
-
-	/* vv->ov.fh is used to indicate that we have valid overlay informations, too */
-	vv->ov.fh = fh;
-
-	/* check if our current overlay is active */
-	if (IS_OVERLAY_ACTIVE(fh) != 0) {
-		saa7146_stop_preview(fh);
-		saa7146_start_preview(fh);
-	}
-	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;
-		if (e->index < 0 )
-			return -EINVAL;
-		if( e->index < dev->ext_vv_data->num_stds ) {
-			DEB_EE("VIDIOC_ENUMSTD: index:%d\n", e->index);
-			v4l2_video_std_construct(e, dev->ext_vv_data->stds[e->index].id, dev->ext_vv_data->stds[e->index].name);
-			return 0;
-		}
-		return -EINVAL;
-	}
-	*/
-
-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;
-
-	DEB_EE("VIDIOC_S_STD\n");
-
-	if ((vv->video_status & STATUS_CAPTURE) == STATUS_CAPTURE) {
-		DEB_D("cannot change video standard while streaming capture is active\n");
-		return -EBUSY;
-	}
-
-	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;
-		}
-	}
-
-	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;
-	}
-
-	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) {
-		if (v4l2_chip_match_host(&chip->match))
-			chip->ident = V4L2_IDENT_SAA7146;
-		return 0;
-	}
-	if (chip->match.type != V4L2_CHIP_MATCH_I2C_DRIVER &&
-	    chip->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
-		return -EINVAL;
-	return v4l2_device_call_until_err(&dev->v4l2_dev, 0,
-			core, g_chip_ident, chip);
-}
-
-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_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_streamon             = vidioc_streamon,
-	.vidioc_streamoff            = vidioc_streamoff,
-	.vidioc_g_parm 		     = vidioc_g_parm,
-	.vidioc_subscribe_event      = v4l2_ctrl_subscribe_event,
-	.vidioc_unsubscribe_event    = v4l2_event_unsubscribe,
-};
-
-const struct v4l2_ioctl_ops saa7146_vbi_ioctl_ops = {
-	.vidioc_querycap             = vidioc_querycap,
-	.vidioc_g_fmt_vbi_cap        = vidioc_g_fmt_vbi_cap,
-	.vidioc_g_chip_ident         = vidioc_g_chip_ident,
-
-	.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_streamon             = vidioc_streamon,
-	.vidioc_streamoff            = vidioc_streamoff,
-	.vidioc_g_parm		     = vidioc_g_parm,
-	.vidioc_subscribe_event      = v4l2_ctrl_subscribe_event,
-	.vidioc_unsubscribe_event    = v4l2_event_unsubscribe,
-};
-
-/*********************************************************************************/
-/* buffer handling functions                                                  */
-
-static int buffer_activate (struct saa7146_dev *dev,
-		     struct saa7146_buf *buf,
-		     struct saa7146_buf *next)
-{
-	struct saa7146_vv *vv = dev->vv_data;
-
-	buf->vb.state = VIDEOBUF_ACTIVE;
-	saa7146_set_capture(dev,buf,next);
-
-	mod_timer(&vv->video_dmaq.timeout, jiffies+BUFFER_TIMEOUT);
-	return 0;
-}
-
-static void release_all_pagetables(struct saa7146_dev *dev, struct saa7146_buf *buf)
-{
-	saa7146_pgtable_free(dev->pci, &buf->pt[0]);
-	saa7146_pgtable_free(dev->pci, &buf->pt[1]);
-	saa7146_pgtable_free(dev->pci, &buf->pt[2]);
-}
-
-static int buffer_prepare(struct videobuf_queue *q,
-			  struct videobuf_buffer *vb, enum v4l2_field field)
-{
-	struct file *file = q->priv_data;
-	struct saa7146_fh *fh = file->private_data;
-	struct saa7146_dev *dev = fh->dev;
-	struct saa7146_vv *vv = dev->vv_data;
-	struct saa7146_buf *buf = (struct saa7146_buf *)vb;
-	int size,err = 0;
-
-	DEB_CAP("vbuf:%p\n", vb);
-
-	/* sanity checks */
-	if (vv->video_fmt.width  < 48 ||
-	    vv->video_fmt.height < 32 ||
-	    vv->video_fmt.width  > vv->standard->h_max_out ||
-	    vv->video_fmt.height > vv->standard->v_max_out) {
-		DEB_D("w (%d) / h (%d) out of bounds\n",
-		      vv->video_fmt.width, vv->video_fmt.height);
-		return -EINVAL;
-	}
-
-	size = vv->video_fmt.sizeimage;
-	if (0 != buf->vb.baddr && buf->vb.bsize < size) {
-		DEB_D("size mismatch\n");
-		return -EINVAL;
-	}
-
-	DEB_CAP("buffer_prepare [size=%dx%d,bytes=%d,fields=%s]\n",
-		vv->video_fmt.width, vv->video_fmt.height,
-		size, v4l2_field_names[vv->video_fmt.field]);
-	if (buf->vb.width  != vv->video_fmt.width  ||
-	    buf->vb.bytesperline != vv->video_fmt.bytesperline ||
-	    buf->vb.height != vv->video_fmt.height ||
-	    buf->vb.size   != size ||
-	    buf->vb.field  != field      ||
-	    buf->vb.field  != vv->video_fmt.field  ||
-	    buf->fmt       != &vv->video_fmt) {
-		saa7146_dma_free(dev,q,buf);
-	}
-
-	if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
-		struct saa7146_format *sfmt;
-
-		buf->vb.bytesperline  = vv->video_fmt.bytesperline;
-		buf->vb.width  = vv->video_fmt.width;
-		buf->vb.height = vv->video_fmt.height;
-		buf->vb.size   = size;
-		buf->vb.field  = field;
-		buf->fmt       = &vv->video_fmt;
-		buf->vb.field  = vv->video_fmt.field;
-
-		sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat);
-
-		release_all_pagetables(dev, buf);
-		if( 0 != IS_PLANAR(sfmt->trans)) {
-			saa7146_pgtable_alloc(dev->pci, &buf->pt[0]);
-			saa7146_pgtable_alloc(dev->pci, &buf->pt[1]);
-			saa7146_pgtable_alloc(dev->pci, &buf->pt[2]);
-		} else {
-			saa7146_pgtable_alloc(dev->pci, &buf->pt[0]);
-		}
-
-		err = videobuf_iolock(q,&buf->vb, &vv->ov_fb);
-		if (err)
-			goto oops;
-		err = saa7146_pgtable_build(dev,buf);
-		if (err)
-			goto oops;
-	}
-	buf->vb.state = VIDEOBUF_PREPARED;
-	buf->activate = buffer_activate;
-
-	return 0;
-
- oops:
-	DEB_D("error out\n");
-	saa7146_dma_free(dev,q,buf);
-
-	return err;
-}
-
-static int buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
-{
-	struct file *file = q->priv_data;
-	struct saa7146_fh *fh = file->private_data;
-	struct saa7146_vv *vv = fh->dev->vv_data;
-
-	if (0 == *count || *count > MAX_SAA7146_CAPTURE_BUFFERS)
-		*count = MAX_SAA7146_CAPTURE_BUFFERS;
-
-	*size = vv->video_fmt.sizeimage;
-
-	/* check if we exceed the "max_memory" parameter */
-	if( (*count * *size) > (max_memory*1048576) ) {
-		*count = (max_memory*1048576) / *size;
-	}
-
-	DEB_CAP("%d buffers, %d bytes each\n", *count, *size);
-
-	return 0;
-}
-
-static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
-{
-	struct file *file = q->priv_data;
-	struct saa7146_fh *fh = file->private_data;
-	struct saa7146_dev *dev = fh->dev;
-	struct saa7146_vv *vv = dev->vv_data;
-	struct saa7146_buf *buf = (struct saa7146_buf *)vb;
-
-	DEB_CAP("vbuf:%p\n", vb);
-	saa7146_buffer_queue(fh->dev, &vv->video_dmaq, buf);
-}
-
-static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
-{
-	struct file *file = q->priv_data;
-	struct saa7146_fh *fh = file->private_data;
-	struct saa7146_dev *dev = fh->dev;
-	struct saa7146_buf *buf = (struct saa7146_buf *)vb;
-
-	DEB_CAP("vbuf:%p\n", vb);
-
-	saa7146_dma_free(dev,q,buf);
-
-	release_all_pagetables(dev, buf);
-}
-
-static struct videobuf_queue_ops video_qops = {
-	.buf_setup    = buffer_setup,
-	.buf_prepare  = buffer_prepare,
-	.buf_queue    = buffer_queue,
-	.buf_release  = buffer_release,
-};
-
-/********************************************************************************/
-/* file operations */
-
-static void video_init(struct saa7146_dev *dev, struct saa7146_vv *vv)
-{
-	INIT_LIST_HEAD(&vv->video_dmaq.queue);
-
-	init_timer(&vv->video_dmaq.timeout);
-	vv->video_dmaq.timeout.function = saa7146_buffer_timeout;
-	vv->video_dmaq.timeout.data     = (unsigned long)(&vv->video_dmaq);
-	vv->video_dmaq.dev              = dev;
-
-	/* set some default values */
-	vv->standard = &dev->ext_vv_data->stds[0];
-
-	/* FIXME: what's this? */
-	vv->current_hps_source = SAA7146_HPS_SOURCE_PORT_A;
-	vv->current_hps_sync = SAA7146_HPS_SYNC_PORT_A;
-}
-
-
-static int video_open(struct saa7146_dev *dev, struct file *file)
-{
-	struct saa7146_fh *fh = file->private_data;
-
-	videobuf_queue_sg_init(&fh->video_q, &video_qops,
-			    &dev->pci->dev, &dev->slock,
-			    V4L2_BUF_TYPE_VIDEO_CAPTURE,
-			    V4L2_FIELD_INTERLACED,
-			    sizeof(struct saa7146_buf),
-			    file, &dev->v4l2_lock);
-
-	return 0;
-}
-
-
-static void video_close(struct saa7146_dev *dev, struct file *file)
-{
-	struct saa7146_fh *fh = file->private_data;
-	struct saa7146_vv *vv = dev->vv_data;
-	struct videobuf_queue *q = &fh->video_q;
-
-	if (IS_CAPTURE_ACTIVE(fh) != 0)
-		video_end(fh, file);
-	else if (IS_OVERLAY_ACTIVE(fh) != 0)
-		saa7146_stop_preview(fh);
-
-	videobuf_stop(q);
-	/* hmm, why is this function declared void? */
-}
-
-
-static void video_irq_done(struct saa7146_dev *dev, unsigned long st)
-{
-	struct saa7146_vv *vv = dev->vv_data;
-	struct saa7146_dmaqueue *q = &vv->video_dmaq;
-
-	spin_lock(&dev->slock);
-	DEB_CAP("called\n");
-
-	/* only finish the buffer if we have one... */
-	if( NULL != q->curr ) {
-		saa7146_buffer_finish(dev,q,VIDEOBUF_DONE);
-	}
-	saa7146_buffer_next(dev,q,0);
-
-	spin_unlock(&dev->slock);
-}
-
-static ssize_t video_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
-{
-	struct saa7146_fh *fh = file->private_data;
-	struct saa7146_dev *dev = fh->dev;
-	struct saa7146_vv *vv = dev->vv_data;
-	ssize_t ret = 0;
-
-	DEB_EE("called\n");
-
-	if ((vv->video_status & STATUS_CAPTURE) != 0) {
-		/* fixme: should we allow read() captures while streaming capture? */
-		if (vv->video_fh == fh) {
-			DEB_S("already capturing\n");
-			return -EBUSY;
-		}
-		DEB_S("already capturing in another open\n");
-		return -EBUSY;
-	}
-
-	ret = video_begin(fh);
-	if( 0 != ret) {
-		goto out;
-	}
-
-	ret = videobuf_read_one(&fh->video_q , data, count, ppos,
-				file->f_flags & O_NONBLOCK);
-	if (ret != 0) {
-		video_end(fh, file);
-	} else {
-		ret = video_end(fh, file);
-	}
-out:
-	/* restart overlay if it was active before */
-	if (vv->ov_suspend != NULL) {
-		saa7146_start_preview(vv->ov_suspend);
-		vv->ov_suspend = NULL;
-	}
-
-	return ret;
-}
-
-struct saa7146_use_ops saa7146_video_uops = {
-	.init = video_init,
-	.open = video_open,
-	.release = video_close,
-	.irq_done = video_irq_done,
-	.read = video_read,
-};
diff --git a/drivers/media/common/siano/Kconfig b/drivers/media/common/siano/Kconfig
new file mode 100644
index 0000000..425aead
--- /dev/null
+++ b/drivers/media/common/siano/Kconfig
@@ -0,0 +1,17 @@
+#
+# Siano Mobile Silicon Digital TV device configuration
+#
+
+config SMS_SIANO_MDTV
+	tristate
+	depends on DVB_CORE && RC_CORE && HAS_DMA
+	depends on SMS_USB_DRV || SMS_SDIO_DRV
+	default y
+	---help---
+	  Choose Y or M here if you have MDTV receiver with a Siano chipset.
+
+	  To compile this driver as a module, choose M here
+	  (The module will be called smsmdtv).
+
+	  Further documentation on this driver can be found on the WWW
+	  at http://www.siano-ms.com/
diff --git a/drivers/media/common/siano/Makefile b/drivers/media/common/siano/Makefile
new file mode 100644
index 0000000..2a09279
--- /dev/null
+++ b/drivers/media/common/siano/Makefile
@@ -0,0 +1,7 @@
+smsmdtv-objs := smscoreapi.o sms-cards.o smsendian.o smsir.o
+
+obj-$(CONFIG_SMS_SIANO_MDTV) += smsmdtv.o smsdvb.o
+
+ccflags-y += -Idrivers/media/dvb-core
+ccflags-y += $(extra-cflags-y) $(extra-cflags-m)
+
diff --git a/drivers/media/common/siano/sms-cards.c b/drivers/media/common/siano/sms-cards.c
new file mode 100644
index 0000000..680c781
--- /dev/null
+++ b/drivers/media/common/siano/sms-cards.c
@@ -0,0 +1,311 @@
+/*
+ *  Card-specific functions for the Siano SMS1xxx USB dongle
+ *
+ *  Copyright (c) 2008 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 version 2 as
+ *  published by the Free Software Foundation;
+ *
+ *  Software distributed under the License is distributed on an "AS IS"
+ *  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
+ *
+ *  See the GNU General Public License for more details.
+ *
+ *  You 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 "sms-cards.h"
+#include "smsir.h"
+#include <linux/module.h>
+
+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] = {
+		.name	= "Unknown board",
+	},
+	[SMS1XXX_BOARD_SIANO_STELLAR] = {
+		.name	= "Siano Stellar Digital Receiver",
+		.type	= SMS_STELLAR,
+	},
+	[SMS1XXX_BOARD_SIANO_NOVA_A] = {
+		.name	= "Siano Nova A Digital Receiver",
+		.type	= SMS_NOVA_A0,
+	},
+	[SMS1XXX_BOARD_SIANO_NOVA_B] = {
+		.name	= "Siano Nova B Digital Receiver",
+		.type	= SMS_NOVA_B0,
+	},
+	[SMS1XXX_BOARD_SIANO_VEGA] = {
+		.name	= "Siano Vega Digital Receiver",
+		.type	= SMS_VEGA,
+	},
+	[SMS1XXX_BOARD_HAUPPAUGE_CATAMOUNT] = {
+		.name	= "Hauppauge Catamount",
+		.type	= SMS_STELLAR,
+		.fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-stellar-dvbt-01.fw",
+	},
+	[SMS1XXX_BOARD_HAUPPAUGE_OKEMO_A] = {
+		.name	= "Hauppauge Okemo-A",
+		.type	= SMS_NOVA_A0,
+		.fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-nova-a-dvbt-01.fw",
+	},
+	[SMS1XXX_BOARD_HAUPPAUGE_OKEMO_B] = {
+		.name	= "Hauppauge Okemo-B",
+		.type	= SMS_NOVA_B0,
+		.fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-nova-b-dvbt-01.fw",
+	},
+	[SMS1XXX_BOARD_HAUPPAUGE_WINDHAM] = {
+		.name	= "Hauppauge WinTV MiniStick",
+		.type	= SMS_NOVA_B0,
+		.fw[DEVICE_MODE_ISDBT_BDA] = "sms1xxx-hcw-55xxx-isdbt-02.fw",
+		.fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-02.fw",
+		.rc_codes = RC_MAP_HAUPPAUGE,
+		.board_cfg.leds_power = 26,
+		.board_cfg.led0 = 27,
+		.board_cfg.led1 = 28,
+		.board_cfg.ir = 9,
+		.led_power = 26,
+		.led_lo    = 27,
+		.led_hi    = 28,
+	},
+	[SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD] = {
+		.name	= "Hauppauge WinTV MiniCard",
+		.type	= SMS_NOVA_B0,
+		.fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-02.fw",
+		.lna_ctrl  = 29,
+		.board_cfg.foreign_lna0_ctrl = 29,
+		.rf_switch = 17,
+		.board_cfg.rf_switch_uhf = 17,
+	},
+	[SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2] = {
+		.name	= "Hauppauge WinTV MiniCard",
+		.type	= SMS_NOVA_B0,
+		.fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-02.fw",
+		.lna_ctrl  = -1,
+	},
+	[SMS1XXX_BOARD_SIANO_NICE] = {
+	/* 11 */
+		.name = "Siano Nice Digital Receiver",
+		.type = SMS_NOVA_B0,
+	},
+	[SMS1XXX_BOARD_SIANO_VENICE] = {
+	/* 12 */
+		.name = "Siano Venice Digital Receiver",
+		.type = SMS_VEGA,
+	},
+};
+
+struct sms_board *sms_get_board(unsigned id)
+{
+	BUG_ON(id >= ARRAY_SIZE(sms_boards));
+
+	return &sms_boards[id];
+}
+EXPORT_SYMBOL_GPL(sms_get_board);
+static inline void sms_gpio_assign_11xx_default_led_config(
+		struct smscore_gpio_config *pGpioConfig) {
+	pGpioConfig->Direction = SMS_GPIO_DIRECTION_OUTPUT;
+	pGpioConfig->InputCharacteristics =
+		SMS_GPIO_INPUT_CHARACTERISTICS_NORMAL;
+	pGpioConfig->OutputDriving = SMS_GPIO_OUTPUT_DRIVING_4mA;
+	pGpioConfig->OutputSlewRate = SMS_GPIO_OUTPUT_SLEW_RATE_0_45_V_NS;
+	pGpioConfig->PullUpDown = SMS_GPIO_PULL_UP_DOWN_NONE;
+}
+
+int sms_board_event(struct smscore_device_t *coredev,
+		enum SMS_BOARD_EVENTS gevent) {
+	struct smscore_gpio_config MyGpioConfig;
+
+	sms_gpio_assign_11xx_default_led_config(&MyGpioConfig);
+
+	switch (gevent) {
+	case BOARD_EVENT_POWER_INIT: /* including hotplug */
+		break; /* BOARD_EVENT_BIND */
+
+	case BOARD_EVENT_POWER_SUSPEND:
+		break; /* BOARD_EVENT_POWER_SUSPEND */
+
+	case BOARD_EVENT_POWER_RESUME:
+		break; /* BOARD_EVENT_POWER_RESUME */
+
+	case BOARD_EVENT_BIND:
+		break; /* BOARD_EVENT_BIND */
+
+	case BOARD_EVENT_SCAN_PROG:
+		break; /* BOARD_EVENT_SCAN_PROG */
+	case BOARD_EVENT_SCAN_COMP:
+		break; /* BOARD_EVENT_SCAN_COMP */
+	case BOARD_EVENT_EMERGENCY_WARNING_SIGNAL:
+		break; /* BOARD_EVENT_EMERGENCY_WARNING_SIGNAL */
+	case BOARD_EVENT_FE_LOCK:
+		break; /* BOARD_EVENT_FE_LOCK */
+	case BOARD_EVENT_FE_UNLOCK:
+		break; /* BOARD_EVENT_FE_UNLOCK */
+	case BOARD_EVENT_DEMOD_LOCK:
+		break; /* BOARD_EVENT_DEMOD_LOCK */
+	case BOARD_EVENT_DEMOD_UNLOCK:
+		break; /* BOARD_EVENT_DEMOD_UNLOCK */
+	case BOARD_EVENT_RECEPTION_MAX_4:
+		break; /* BOARD_EVENT_RECEPTION_MAX_4 */
+	case BOARD_EVENT_RECEPTION_3:
+		break; /* BOARD_EVENT_RECEPTION_3 */
+	case BOARD_EVENT_RECEPTION_2:
+		break; /* BOARD_EVENT_RECEPTION_2 */
+	case BOARD_EVENT_RECEPTION_1:
+		break; /* BOARD_EVENT_RECEPTION_1 */
+	case BOARD_EVENT_RECEPTION_LOST_0:
+		break; /* BOARD_EVENT_RECEPTION_LOST_0 */
+	case BOARD_EVENT_MULTIPLEX_OK:
+		break; /* BOARD_EVENT_MULTIPLEX_OK */
+	case BOARD_EVENT_MULTIPLEX_ERRORS:
+		break; /* BOARD_EVENT_MULTIPLEX_ERRORS */
+
+	default:
+		sms_err("Unknown SMS board event");
+		break;
+	}
+	return 0;
+}
+EXPORT_SYMBOL_GPL(sms_board_event);
+
+static int sms_set_gpio(struct smscore_device_t *coredev, int pin, int enable)
+{
+	int lvl, ret;
+	u32 gpio;
+	struct smscore_config_gpio gpioconfig = {
+		.direction            = SMS_GPIO_DIRECTION_OUTPUT,
+		.pullupdown           = SMS_GPIO_PULLUPDOWN_NONE,
+		.inputcharacteristics = SMS_GPIO_INPUTCHARACTERISTICS_NORMAL,
+		.outputslewrate       = SMS_GPIO_OUTPUTSLEWRATE_FAST,
+		.outputdriving        = SMS_GPIO_OUTPUTDRIVING_4mA,
+	};
+
+	if (pin == 0)
+		return -EINVAL;
+
+	if (pin < 0) {
+		/* inverted gpio */
+		gpio = pin * -1;
+		lvl = enable ? 0 : 1;
+	} else {
+		gpio = pin;
+		lvl = enable ? 1 : 0;
+	}
+
+	ret = smscore_configure_gpio(coredev, gpio, &gpioconfig);
+	if (ret < 0)
+		return ret;
+
+	return smscore_set_gpio(coredev, gpio, lvl);
+}
+
+int sms_board_setup(struct smscore_device_t *coredev)
+{
+	int board_id = smscore_get_board_id(coredev);
+	struct sms_board *board = sms_get_board(board_id);
+
+	switch (board_id) {
+	case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM:
+		/* turn off all LEDs */
+		sms_set_gpio(coredev, board->led_power, 0);
+		sms_set_gpio(coredev, board->led_hi, 0);
+		sms_set_gpio(coredev, board->led_lo, 0);
+		break;
+	case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2:
+	case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD:
+		/* turn off LNA */
+		sms_set_gpio(coredev, board->lna_ctrl, 0);
+		break;
+	}
+	return 0;
+}
+EXPORT_SYMBOL_GPL(sms_board_setup);
+
+int sms_board_power(struct smscore_device_t *coredev, int onoff)
+{
+	int board_id = smscore_get_board_id(coredev);
+	struct sms_board *board = sms_get_board(board_id);
+
+	switch (board_id) {
+	case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM:
+		/* power LED */
+		sms_set_gpio(coredev,
+			     board->led_power, onoff ? 1 : 0);
+		break;
+	case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2:
+	case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD:
+		/* LNA */
+		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)
+{
+	int board_id = smscore_get_board_id(coredev);
+	struct sms_board *board = sms_get_board(board_id);
+
+	/* dont touch GPIO if LEDs are already set */
+	if (smscore_led_state(coredev, -1) == led)
+		return 0;
+
+	switch (board_id) {
+	case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM:
+		sms_set_gpio(coredev,
+			     board->led_lo, (led & SMS_LED_LO) ? 1 : 0);
+		sms_set_gpio(coredev,
+			     board->led_hi, (led & SMS_LED_HI) ? 1 : 0);
+
+		smscore_led_state(coredev, led);
+		break;
+	}
+	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:
+	case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD:
+	case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2:
+		request_module("smsdvb");
+		break;
+	default:
+		/* do nothing */
+		break;
+	}
+	return 0;
+}
+EXPORT_SYMBOL_GPL(sms_board_load_modules);
diff --git a/drivers/media/common/siano/sms-cards.h b/drivers/media/common/siano/sms-cards.h
new file mode 100644
index 0000000..d8cdf75
--- /dev/null
+++ b/drivers/media/common/siano/sms-cards.h
@@ -0,0 +1,123 @@
+/*
+ *  Card-specific functions for the Siano SMS1xxx USB dongle
+ *
+ *  Copyright (c) 2008 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 version 2 as
+ *  published by the Free Software Foundation;
+ *
+ *  Software distributed under the License is distributed on an "AS IS"
+ *  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
+ *
+ *  See the GNU General Public License for more details.
+ *
+ *  You 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 __SMS_CARDS_H__
+#define __SMS_CARDS_H__
+
+#include <linux/usb.h>
+#include "smscoreapi.h"
+#include "smsir.h"
+
+#define SMS_BOARD_UNKNOWN 0
+#define SMS1XXX_BOARD_SIANO_STELLAR 1
+#define SMS1XXX_BOARD_SIANO_NOVA_A  2
+#define SMS1XXX_BOARD_SIANO_NOVA_B  3
+#define SMS1XXX_BOARD_SIANO_VEGA    4
+#define SMS1XXX_BOARD_HAUPPAUGE_CATAMOUNT 5
+#define SMS1XXX_BOARD_HAUPPAUGE_OKEMO_A 6
+#define SMS1XXX_BOARD_HAUPPAUGE_OKEMO_B 7
+#define SMS1XXX_BOARD_HAUPPAUGE_WINDHAM 8
+#define SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD 9
+#define SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2 10
+#define SMS1XXX_BOARD_SIANO_NICE	11
+#define SMS1XXX_BOARD_SIANO_VENICE	12
+
+struct sms_board_gpio_cfg {
+	int lna_vhf_exist;
+	int lna_vhf_ctrl;
+	int lna_uhf_exist;
+	int lna_uhf_ctrl;
+	int lna_uhf_d_ctrl;
+	int lna_sband_exist;
+	int lna_sband_ctrl;
+	int lna_sband_d_ctrl;
+	int foreign_lna0_ctrl;
+	int foreign_lna1_ctrl;
+	int foreign_lna2_ctrl;
+	int rf_switch_vhf;
+	int rf_switch_uhf;
+	int rf_switch_sband;
+	int leds_power;
+	int led0;
+	int led1;
+	int led2;
+	int led3;
+	int led4;
+	int ir;
+	int eeprom_wp;
+	int mrc_sense;
+	int mrc_pdn_resetn;
+	int mrc_gp0; /* mrcs spi int */
+	int mrc_gp1;
+	int mrc_gp2;
+	int mrc_gp3;
+	int mrc_gp4;
+	int host_spi_gsp_ts_int;
+};
+
+struct sms_board {
+	enum sms_device_type_st type;
+	char *name, *fw[DEVICE_MODE_MAX];
+	struct sms_board_gpio_cfg board_cfg;
+	char *rc_codes;				/* Name of IR codes table */
+
+	/* gpios */
+	int led_power, led_hi, led_lo, lna_ctrl, rf_switch;
+};
+
+struct sms_board *sms_get_board(unsigned id);
+
+extern struct smscore_device_t *coredev;
+
+enum SMS_BOARD_EVENTS {
+	BOARD_EVENT_POWER_INIT,
+	BOARD_EVENT_POWER_SUSPEND,
+	BOARD_EVENT_POWER_RESUME,
+	BOARD_EVENT_BIND,
+	BOARD_EVENT_SCAN_PROG,
+	BOARD_EVENT_SCAN_COMP,
+	BOARD_EVENT_EMERGENCY_WARNING_SIGNAL,
+	BOARD_EVENT_FE_LOCK,
+	BOARD_EVENT_FE_UNLOCK,
+	BOARD_EVENT_DEMOD_LOCK,
+	BOARD_EVENT_DEMOD_UNLOCK,
+	BOARD_EVENT_RECEPTION_MAX_4,
+	BOARD_EVENT_RECEPTION_3,
+	BOARD_EVENT_RECEPTION_2,
+	BOARD_EVENT_RECEPTION_1,
+	BOARD_EVENT_RECEPTION_LOST_0,
+	BOARD_EVENT_MULTIPLEX_OK,
+	BOARD_EVENT_MULTIPLEX_ERRORS
+};
+
+int sms_board_event(struct smscore_device_t *coredev,
+		enum SMS_BOARD_EVENTS gevent);
+
+int sms_board_setup(struct smscore_device_t *coredev);
+
+#define SMS_LED_OFF 0
+#define SMS_LED_LO  1
+#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 int sms_board_load_modules(int id);
+
+#endif /* __SMS_CARDS_H__ */
diff --git a/drivers/media/common/siano/smscoreapi.c b/drivers/media/common/siano/smscoreapi.c
new file mode 100644
index 0000000..9cc5554
--- /dev/null
+++ b/drivers/media/common/siano/smscoreapi.c
@@ -0,0 +1,1637 @@
+/*
+ *  Siano core API module
+ *
+ *  This file contains implementation for the interface to sms core component
+ *
+ *  author: Uri Shkolnik
+ *
+ *  Copyright (c), 2005-2008 Siano Mobile Silicon, 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;
+ *
+ *  Software distributed under the License is distributed on an "AS IS"
+ *  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
+ *
+ *  See the GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+
+#include <linux/firmware.h>
+#include <linux/wait.h>
+#include <asm/byteorder.h>
+
+#include "smscoreapi.h"
+#include "sms-cards.h"
+#include "smsir.h"
+#include "smsendian.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))");
+
+struct smscore_device_notifyee_t {
+	struct list_head entry;
+	hotplug_t hotplug;
+};
+
+struct smscore_idlist_t {
+	struct list_head entry;
+	int		id;
+	int		data_type;
+};
+
+struct smscore_client_t {
+	struct list_head entry;
+	struct smscore_device_t *coredev;
+	void			*context;
+	struct list_head 	idlist;
+	onresponse_t	onresponse_handler;
+	onremove_t		onremove_handler;
+};
+
+void smscore_set_board_id(struct smscore_device_t *core, int id)
+{
+	core->board_id = id;
+}
+
+int smscore_led_state(struct smscore_device_t *core, int led)
+{
+	if (led >= 0)
+		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;
+	char			devpath[32];
+	int				mode;
+	enum sms_device_type_st	type;
+};
+
+static struct list_head g_smscore_notifyees;
+static struct list_head g_smscore_devices;
+static struct mutex g_smscore_deviceslock;
+
+static struct list_head g_smscore_registry;
+static struct mutex g_smscore_registrylock;
+
+static int default_mode = 4;
+
+module_param(default_mode, int, 0644);
+MODULE_PARM_DESC(default_mode, "default firmware id (device mode)");
+
+static struct smscore_registry_entry_t *smscore_find_registry(char *devpath)
+{
+	struct smscore_registry_entry_t *entry;
+	struct list_head *next;
+
+	kmutex_lock(&g_smscore_registrylock);
+	for (next = g_smscore_registry.next;
+	     next != &g_smscore_registry;
+	     next = next->next) {
+		entry = (struct smscore_registry_entry_t *) next;
+		if (!strcmp(entry->devpath, devpath)) {
+			kmutex_unlock(&g_smscore_registrylock);
+			return entry;
+		}
+	}
+	entry = kmalloc(sizeof(struct smscore_registry_entry_t), GFP_KERNEL);
+	if (entry) {
+		entry->mode = default_mode;
+		strcpy(entry->devpath, devpath);
+		list_add(&entry->entry, &g_smscore_registry);
+	} else
+		sms_err("failed to create smscore_registry.");
+	kmutex_unlock(&g_smscore_registrylock);
+	return entry;
+}
+
+int smscore_registry_getmode(char *devpath)
+{
+	struct smscore_registry_entry_t *entry;
+
+	entry = smscore_find_registry(devpath);
+	if (entry)
+		return entry->mode;
+	else
+		sms_err("No registry found.");
+
+	return default_mode;
+}
+EXPORT_SYMBOL_GPL(smscore_registry_getmode);
+
+static enum sms_device_type_st smscore_registry_gettype(char *devpath)
+{
+	struct smscore_registry_entry_t *entry;
+
+	entry = smscore_find_registry(devpath);
+	if (entry)
+		return entry->type;
+	else
+		sms_err("No registry found.");
+
+	return -1;
+}
+
+void smscore_registry_setmode(char *devpath, int mode)
+{
+	struct smscore_registry_entry_t *entry;
+
+	entry = smscore_find_registry(devpath);
+	if (entry)
+		entry->mode = mode;
+	else
+		sms_err("No registry found.");
+}
+
+static void smscore_registry_settype(char *devpath,
+				     enum sms_device_type_st type)
+{
+	struct smscore_registry_entry_t *entry;
+
+	entry = smscore_find_registry(devpath);
+	if (entry)
+		entry->type = type;
+	else
+		sms_err("No registry found.");
+}
+
+
+static void list_add_locked(struct list_head *new, struct list_head *head,
+			    spinlock_t *lock)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(lock, flags);
+
+	list_add(new, head);
+
+	spin_unlock_irqrestore(lock, flags);
+}
+
+/**
+ * register a client callback that called when device plugged in/unplugged
+ * NOTE: if devices exist callback is called immediately for each device
+ *
+ * @param hotplug callback
+ *
+ * @return 0 on success, <0 on error.
+ */
+int smscore_register_hotplug(hotplug_t hotplug)
+{
+	struct smscore_device_notifyee_t *notifyee;
+	struct list_head *next, *first;
+	int rc = 0;
+
+	kmutex_lock(&g_smscore_deviceslock);
+
+	notifyee = kmalloc(sizeof(struct smscore_device_notifyee_t),
+			   GFP_KERNEL);
+	if (notifyee) {
+		/* now notify callback about existing devices */
+		first = &g_smscore_devices;
+		for (next = first->next;
+		     next != first && !rc;
+		     next = next->next) {
+			struct smscore_device_t *coredev =
+				(struct smscore_device_t *) next;
+			rc = hotplug(coredev, coredev->device, 1);
+		}
+
+		if (rc >= 0) {
+			notifyee->hotplug = hotplug;
+			list_add(&notifyee->entry, &g_smscore_notifyees);
+		} else
+			kfree(notifyee);
+	} else
+		rc = -ENOMEM;
+
+	kmutex_unlock(&g_smscore_deviceslock);
+
+	return rc;
+}
+EXPORT_SYMBOL_GPL(smscore_register_hotplug);
+
+/**
+ * unregister a client callback that called when device plugged in/unplugged
+ *
+ * @param hotplug callback
+ *
+ */
+void smscore_unregister_hotplug(hotplug_t hotplug)
+{
+	struct list_head *next, *first;
+
+	kmutex_lock(&g_smscore_deviceslock);
+
+	first = &g_smscore_notifyees;
+
+	for (next = first->next; next != first;) {
+		struct smscore_device_notifyee_t *notifyee =
+			(struct smscore_device_notifyee_t *) next;
+		next = next->next;
+
+		if (notifyee->hotplug == hotplug) {
+			list_del(&notifyee->entry);
+			kfree(notifyee);
+		}
+	}
+
+	kmutex_unlock(&g_smscore_deviceslock);
+}
+EXPORT_SYMBOL_GPL(smscore_unregister_hotplug);
+
+static void smscore_notify_clients(struct smscore_device_t *coredev)
+{
+	struct smscore_client_t *client;
+
+	/* the client must call smscore_unregister_client from remove handler */
+	while (!list_empty(&coredev->clients)) {
+		client = (struct smscore_client_t *) coredev->clients.next;
+		client->onremove_handler(client->context);
+	}
+}
+
+static int smscore_notify_callbacks(struct smscore_device_t *coredev,
+				    struct device *device, int arrival)
+{
+	struct smscore_device_notifyee_t *elem;
+	int rc = 0;
+
+	/* note: must be called under g_deviceslock */
+
+	list_for_each_entry(elem, &g_smscore_notifyees, entry) {
+		rc = elem->hotplug(coredev, device, arrival);
+		if (rc < 0)
+			break;
+	}
+
+	return rc;
+}
+
+static struct
+smscore_buffer_t *smscore_createbuffer(u8 *buffer, void *common_buffer,
+				       dma_addr_t common_buffer_phys)
+{
+	struct smscore_buffer_t *cb =
+		kmalloc(sizeof(struct smscore_buffer_t), GFP_KERNEL);
+	if (!cb) {
+		sms_info("kmalloc(...) failed");
+		return NULL;
+	}
+
+	cb->p = buffer;
+	cb->offset_in_common = buffer - (u8 *) common_buffer;
+	cb->phys = common_buffer_phys + cb->offset_in_common;
+
+	return cb;
+}
+
+/**
+ * creates coredev object for a device, prepares buffers,
+ * creates buffer mappings, notifies registered hotplugs about new device.
+ *
+ * @param params device pointer to struct with device specific parameters
+ *               and handlers
+ * @param coredev pointer to a value that receives created coredev object
+ *
+ * @return 0 on success, <0 on error.
+ */
+int smscore_register_device(struct smsdevice_params_t *params,
+			    struct smscore_device_t **coredev)
+{
+	struct smscore_device_t *dev;
+	u8 *buffer;
+
+	dev = kzalloc(sizeof(struct smscore_device_t), GFP_KERNEL);
+	if (!dev) {
+		sms_info("kzalloc(...) failed");
+		return -ENOMEM;
+	}
+
+	/* init list entry so it could be safe in smscore_unregister_device */
+	INIT_LIST_HEAD(&dev->entry);
+
+	/* init queues */
+	INIT_LIST_HEAD(&dev->clients);
+	INIT_LIST_HEAD(&dev->buffers);
+
+	/* init locks */
+	spin_lock_init(&dev->clientslock);
+	spin_lock_init(&dev->bufferslock);
+
+	/* init completion events */
+	init_completion(&dev->version_ex_done);
+	init_completion(&dev->data_download_done);
+	init_completion(&dev->trigger_done);
+	init_completion(&dev->init_device_done);
+	init_completion(&dev->reload_start_done);
+	init_completion(&dev->resume_done);
+	init_completion(&dev->gpio_configuration_done);
+	init_completion(&dev->gpio_set_level_done);
+	init_completion(&dev->gpio_get_level_done);
+	init_completion(&dev->ir_init_done);
+
+	/* Buffer management */
+	init_waitqueue_head(&dev->buffer_mng_waitq);
+
+	/* alloc common buffer */
+	dev->common_buffer_size = params->buffer_size * params->num_buffers;
+	dev->common_buffer = dma_alloc_coherent(NULL, dev->common_buffer_size,
+						&dev->common_buffer_phys,
+						GFP_KERNEL | GFP_DMA);
+	if (!dev->common_buffer) {
+		smscore_unregister_device(dev);
+		return -ENOMEM;
+	}
+
+	/* prepare dma buffers */
+	for (buffer = dev->common_buffer;
+	     dev->num_buffers < params->num_buffers;
+	     dev->num_buffers++, buffer += params->buffer_size) {
+		struct smscore_buffer_t *cb =
+			smscore_createbuffer(buffer, dev->common_buffer,
+					     dev->common_buffer_phys);
+		if (!cb) {
+			smscore_unregister_device(dev);
+			return -ENOMEM;
+		}
+
+		smscore_putbuffer(dev, cb);
+	}
+
+	sms_info("allocated %d buffers", dev->num_buffers);
+
+	dev->mode = DEVICE_MODE_NONE;
+	dev->context = params->context;
+	dev->device = params->device;
+	dev->setmode_handler = params->setmode_handler;
+	dev->detectmode_handler = params->detectmode_handler;
+	dev->sendrequest_handler = params->sendrequest_handler;
+	dev->preload_handler = params->preload_handler;
+	dev->postload_handler = params->postload_handler;
+
+	dev->device_flags = params->flags;
+	strcpy(dev->devpath, params->devpath);
+
+	smscore_registry_settype(dev->devpath, params->device_type);
+
+	/* add device to devices list */
+	kmutex_lock(&g_smscore_deviceslock);
+	list_add(&dev->entry, &g_smscore_devices);
+	kmutex_unlock(&g_smscore_deviceslock);
+
+	*coredev = dev;
+
+	sms_info("device %p created", dev);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(smscore_register_device);
+
+
+static int smscore_sendrequest_and_wait(struct smscore_device_t *coredev,
+		void *buffer, size_t size, struct completion *completion) {
+	int rc = coredev->sendrequest_handler(coredev->context, buffer, size);
+	if (rc < 0) {
+		sms_info("sendrequest returned error %d", rc);
+		return rc;
+	}
+
+	return wait_for_completion_timeout(completion,
+			msecs_to_jiffies(SMS_PROTOCOL_MAX_RAOUNDTRIP_MS)) ?
+			0 : -ETIME;
+}
+
+/**
+ * Starts & enables IR operations
+ *
+ * @return 0 on success, < 0 on error.
+ */
+static int smscore_init_ir(struct smscore_device_t *coredev)
+{
+	int ir_io;
+	int rc;
+	void *buffer;
+
+	coredev->ir.dev = NULL;
+	ir_io = sms_get_board(smscore_get_board_id(coredev))->board_cfg.ir;
+	if (ir_io) {/* only if IR port exist we use IR sub-module */
+		sms_info("IR loading");
+		rc = sms_ir_init(coredev);
+
+		if	(rc != 0)
+			sms_err("Error initialization DTV IR sub-module");
+		else {
+			buffer = kmalloc(sizeof(struct SmsMsgData_ST2) +
+						SMS_DMA_ALIGNMENT,
+						GFP_KERNEL | GFP_DMA);
+			if (buffer) {
+				struct SmsMsgData_ST2 *msg =
+				(struct SmsMsgData_ST2 *)
+				SMS_ALIGN_ADDRESS(buffer);
+
+				SMS_INIT_MSG(&msg->xMsgHeader,
+						MSG_SMS_START_IR_REQ,
+						sizeof(struct SmsMsgData_ST2));
+				msg->msgData[0] = coredev->ir.controller;
+				msg->msgData[1] = coredev->ir.timeout;
+
+				smsendian_handle_tx_message(
+					(struct SmsMsgHdr_ST2 *)msg);
+				rc = smscore_sendrequest_and_wait(coredev, msg,
+						msg->xMsgHeader. msgLength,
+						&coredev->ir_init_done);
+
+				kfree(buffer);
+			} else
+				sms_err
+				("Sending IR initialization message failed");
+		}
+	} else
+		sms_info("IR port has not been detected");
+
+	return 0;
+}
+
+/**
+ * sets initial device mode and notifies client hotplugs that device is ready
+ *
+ * @param coredev pointer to a coredev object returned by
+ * 		  smscore_register_device
+ *
+ * @return 0 on success, <0 on error.
+ */
+int smscore_start_device(struct smscore_device_t *coredev)
+{
+	int rc = smscore_set_device_mode(
+			coredev, smscore_registry_getmode(coredev->devpath));
+	if (rc < 0) {
+		sms_info("set device mode faile , rc %d", rc);
+		return rc;
+	}
+
+	kmutex_lock(&g_smscore_deviceslock);
+
+	rc = smscore_notify_callbacks(coredev, coredev->device, 1);
+	smscore_init_ir(coredev);
+
+	sms_info("device %p started, rc %d", coredev, rc);
+
+	kmutex_unlock(&g_smscore_deviceslock);
+
+	return rc;
+}
+EXPORT_SYMBOL_GPL(smscore_start_device);
+
+
+static int smscore_load_firmware_family2(struct smscore_device_t *coredev,
+					 void *buffer, size_t size)
+{
+	struct SmsFirmware_ST *firmware = (struct SmsFirmware_ST *) buffer;
+	struct SmsMsgHdr_ST *msg;
+	u32 mem_address;
+	u8 *payload = firmware->Payload;
+	int rc = 0;
+	firmware->StartAddress = le32_to_cpu(firmware->StartAddress);
+	firmware->Length = le32_to_cpu(firmware->Length);
+
+	mem_address = firmware->StartAddress;
+
+	sms_info("loading FW to addr 0x%x size %d",
+		 mem_address, firmware->Length);
+	if (coredev->preload_handler) {
+		rc = coredev->preload_handler(coredev->context);
+		if (rc < 0)
+			return rc;
+	}
+
+	/* PAGE_SIZE buffer shall be enough and dma aligned */
+	msg = kmalloc(PAGE_SIZE, GFP_KERNEL | GFP_DMA);
+	if (!msg)
+		return -ENOMEM;
+
+	if (coredev->mode != DEVICE_MODE_NONE) {
+		sms_debug("sending reload command.");
+		SMS_INIT_MSG(msg, MSG_SW_RELOAD_START_REQ,
+			     sizeof(struct SmsMsgHdr_ST));
+		rc = smscore_sendrequest_and_wait(coredev, msg,
+						  msg->msgLength,
+						  &coredev->reload_start_done);
+		mem_address = *(u32 *) &payload[20];
+	}
+
+	while (size && rc >= 0) {
+		struct SmsDataDownload_ST *DataMsg =
+			(struct SmsDataDownload_ST *) msg;
+		int payload_size = min((int) size, SMS_MAX_PAYLOAD_SIZE);
+
+		SMS_INIT_MSG(msg, MSG_SMS_DATA_DOWNLOAD_REQ,
+			     (u16)(sizeof(struct SmsMsgHdr_ST) +
+				      sizeof(u32) + payload_size));
+
+		DataMsg->MemAddr = mem_address;
+		memcpy(DataMsg->Payload, payload, payload_size);
+
+		if ((coredev->device_flags & SMS_ROM_NO_RESPONSE) &&
+		    (coredev->mode == DEVICE_MODE_NONE))
+			rc = coredev->sendrequest_handler(
+				coredev->context, DataMsg,
+				DataMsg->xMsgHeader.msgLength);
+		else
+			rc = smscore_sendrequest_and_wait(
+				coredev, DataMsg,
+				DataMsg->xMsgHeader.msgLength,
+				&coredev->data_download_done);
+
+		payload += payload_size;
+		size -= payload_size;
+		mem_address += payload_size;
+	}
+
+	if (rc >= 0) {
+		if (coredev->mode == DEVICE_MODE_NONE) {
+			struct SmsMsgData_ST *TriggerMsg =
+				(struct SmsMsgData_ST *) msg;
+
+			SMS_INIT_MSG(msg, MSG_SMS_SWDOWNLOAD_TRIGGER_REQ,
+				     sizeof(struct SmsMsgHdr_ST) +
+				     sizeof(u32) * 5);
+
+			TriggerMsg->msgData[0] = firmware->StartAddress;
+						/* Entry point */
+			TriggerMsg->msgData[1] = 5; /* Priority */
+			TriggerMsg->msgData[2] = 0x200; /* Stack size */
+			TriggerMsg->msgData[3] = 0; /* Parameter */
+			TriggerMsg->msgData[4] = 4; /* Task ID */
+
+			if (coredev->device_flags & SMS_ROM_NO_RESPONSE) {
+				rc = coredev->sendrequest_handler(
+					coredev->context, TriggerMsg,
+					TriggerMsg->xMsgHeader.msgLength);
+				msleep(100);
+			} else
+				rc = smscore_sendrequest_and_wait(
+					coredev, TriggerMsg,
+					TriggerMsg->xMsgHeader.msgLength,
+					&coredev->trigger_done);
+		} else {
+			SMS_INIT_MSG(msg, MSG_SW_RELOAD_EXEC_REQ,
+				     sizeof(struct SmsMsgHdr_ST));
+
+			rc = coredev->sendrequest_handler(coredev->context,
+							  msg, msg->msgLength);
+		}
+		msleep(500);
+	}
+
+	sms_debug("rc=%d, postload=%p ", rc,
+		  coredev->postload_handler);
+
+	kfree(msg);
+
+	return ((rc >= 0) && coredev->postload_handler) ?
+		coredev->postload_handler(coredev->context) :
+		rc;
+}
+
+/**
+ * loads specified firmware into a buffer and calls device loadfirmware_handler
+ *
+ * @param coredev pointer to a coredev object returned by
+ *                smscore_register_device
+ * @param filename null-terminated string specifies firmware file name
+ * @param loadfirmware_handler device handler that loads firmware
+ *
+ * @return 0 on success, <0 on error.
+ */
+static int smscore_load_firmware_from_file(struct smscore_device_t *coredev,
+					   char *filename,
+					   loadfirmware_t loadfirmware_handler)
+{
+	int rc = -ENOENT;
+	const struct firmware *fw;
+	u8 *fw_buffer;
+
+	if (loadfirmware_handler == NULL && !(coredev->device_flags &
+					      SMS_DEVICE_FAMILY2))
+		return -EINVAL;
+
+	rc = request_firmware(&fw, filename, coredev->device);
+	if (rc < 0) {
+		sms_info("failed to open \"%s\"", filename);
+		return rc;
+	}
+	sms_info("read FW %s, size=%zd", filename, fw->size);
+	fw_buffer = kmalloc(ALIGN(fw->size, SMS_ALLOC_ALIGNMENT),
+			    GFP_KERNEL | GFP_DMA);
+	if (fw_buffer) {
+		memcpy(fw_buffer, fw->data, fw->size);
+
+		rc = (coredev->device_flags & SMS_DEVICE_FAMILY2) ?
+		      smscore_load_firmware_family2(coredev,
+						    fw_buffer,
+						    fw->size) :
+		      loadfirmware_handler(coredev->context,
+					   fw_buffer, fw->size);
+
+		kfree(fw_buffer);
+	} else {
+		sms_info("failed to allocate firmware buffer");
+		rc = -ENOMEM;
+	}
+
+	release_firmware(fw);
+
+	return rc;
+}
+
+/**
+ * notifies all clients registered with the device, notifies hotplugs,
+ * frees all buffers and coredev object
+ *
+ * @param coredev pointer to a coredev object returned by
+ *                smscore_register_device
+ *
+ * @return 0 on success, <0 on error.
+ */
+void smscore_unregister_device(struct smscore_device_t *coredev)
+{
+	struct smscore_buffer_t *cb;
+	int num_buffers = 0;
+	int retry = 0;
+
+	kmutex_lock(&g_smscore_deviceslock);
+
+	/* Release input device (IR) resources */
+	sms_ir_exit(coredev);
+
+	smscore_notify_clients(coredev);
+	smscore_notify_callbacks(coredev, NULL, 0);
+
+	/* at this point all buffers should be back
+	 * onresponse must no longer be called */
+
+	while (1) {
+		while (!list_empty(&coredev->buffers)) {
+			cb = (struct smscore_buffer_t *) coredev->buffers.next;
+			list_del(&cb->entry);
+			kfree(cb);
+			num_buffers++;
+		}
+		if (num_buffers == coredev->num_buffers)
+			break;
+		if (++retry > 10) {
+			sms_info("exiting although "
+				 "not all buffers released.");
+			break;
+		}
+
+		sms_info("waiting for %d buffer(s)",
+			 coredev->num_buffers - num_buffers);
+		msleep(100);
+	}
+
+	sms_info("freed %d buffers", num_buffers);
+
+	if (coredev->common_buffer)
+		dma_free_coherent(NULL, coredev->common_buffer_size,
+			coredev->common_buffer, coredev->common_buffer_phys);
+
+	if (coredev->fw_buf != NULL)
+		kfree(coredev->fw_buf);
+
+	list_del(&coredev->entry);
+	kfree(coredev);
+
+	kmutex_unlock(&g_smscore_deviceslock);
+
+	sms_info("device %p destroyed", coredev);
+}
+EXPORT_SYMBOL_GPL(smscore_unregister_device);
+
+static int smscore_detect_mode(struct smscore_device_t *coredev)
+{
+	void *buffer = kmalloc(sizeof(struct SmsMsgHdr_ST) + SMS_DMA_ALIGNMENT,
+			       GFP_KERNEL | GFP_DMA);
+	struct SmsMsgHdr_ST *msg =
+		(struct SmsMsgHdr_ST *) SMS_ALIGN_ADDRESS(buffer);
+	int rc;
+
+	if (!buffer)
+		return -ENOMEM;
+
+	SMS_INIT_MSG(msg, MSG_SMS_GET_VERSION_EX_REQ,
+		     sizeof(struct SmsMsgHdr_ST));
+
+	rc = smscore_sendrequest_and_wait(coredev, msg, msg->msgLength,
+					  &coredev->version_ex_done);
+	if (rc == -ETIME) {
+		sms_err("MSG_SMS_GET_VERSION_EX_REQ failed first try");
+
+		if (wait_for_completion_timeout(&coredev->resume_done,
+						msecs_to_jiffies(5000))) {
+			rc = smscore_sendrequest_and_wait(
+				coredev, msg, msg->msgLength,
+				&coredev->version_ex_done);
+			if (rc < 0)
+				sms_err("MSG_SMS_GET_VERSION_EX_REQ failed "
+					"second try, rc %d", rc);
+		} else
+			rc = -ETIME;
+	}
+
+	kfree(buffer);
+
+	return rc;
+}
+
+static char *smscore_fw_lkup[][SMS_NUM_OF_DEVICE_TYPES] = {
+	/*Stellar		NOVA A0		Nova B0		VEGA*/
+	/*DVBT*/
+	{"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"},
+	/*DVBH*/
+	{"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"},
+	/*TDMB*/
+	{"none", "tdmb_nova_12mhz.inp", "tdmb_nova_12mhz_b0.inp", "none"},
+	/*DABIP*/
+	{"none", "none", "none", "none"},
+	/*BDA*/
+	{"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"},
+	/*ISDBT*/
+	{"none", "isdbt_nova_12mhz.inp", "isdbt_nova_12mhz_b0.inp", "none"},
+	/*ISDBTBDA*/
+	{"none", "isdbt_nova_12mhz.inp", "isdbt_nova_12mhz_b0.inp", "none"},
+	/*CMMB*/
+	{"none", "none", "none", "cmmb_vega_12mhz.inp"}
+};
+
+static inline char *sms_get_fw_name(struct smscore_device_t *coredev,
+				    int mode, enum sms_device_type_st type)
+{
+	char **fw = sms_get_board(smscore_get_board_id(coredev))->fw;
+	return (fw && fw[mode]) ? fw[mode] : smscore_fw_lkup[mode][type];
+}
+
+/**
+ * calls device handler to change mode of operation
+ * NOTE: stellar/usb may disconnect when changing mode
+ *
+ * @param coredev pointer to a coredev object returned by
+ *                smscore_register_device
+ * @param mode requested mode of operation
+ *
+ * @return 0 on success, <0 on error.
+ */
+int smscore_set_device_mode(struct smscore_device_t *coredev, int mode)
+{
+	void *buffer;
+	int rc = 0;
+	enum sms_device_type_st type;
+
+	sms_debug("set device mode to %d", mode);
+	if (coredev->device_flags & SMS_DEVICE_FAMILY2) {
+		if (mode < DEVICE_MODE_DVBT || mode >= DEVICE_MODE_RAW_TUNER) {
+			sms_err("invalid mode specified %d", mode);
+			return -EINVAL;
+		}
+
+		smscore_registry_setmode(coredev->devpath, mode);
+
+		if (!(coredev->device_flags & SMS_DEVICE_NOT_READY)) {
+			rc = smscore_detect_mode(coredev);
+			if (rc < 0) {
+				sms_err("mode detect failed %d", rc);
+				return rc;
+			}
+		}
+
+		if (coredev->mode == mode) {
+			sms_info("device mode %d already set", mode);
+			return 0;
+		}
+
+		if (!(coredev->modes_supported & (1 << mode))) {
+			char *fw_filename;
+
+			type = smscore_registry_gettype(coredev->devpath);
+			fw_filename = sms_get_fw_name(coredev, mode, type);
+
+			rc = smscore_load_firmware_from_file(coredev,
+							     fw_filename, NULL);
+			if (rc < 0) {
+				sms_warn("error %d loading firmware: %s, "
+					 "trying again with default firmware",
+					 rc, fw_filename);
+
+				/* try again with the default firmware */
+				fw_filename = smscore_fw_lkup[mode][type];
+				rc = smscore_load_firmware_from_file(coredev,
+							     fw_filename, NULL);
+
+				if (rc < 0) {
+					sms_warn("error %d loading "
+						 "firmware: %s", rc,
+						 fw_filename);
+					return rc;
+				}
+			}
+			sms_log("firmware download success: %s", fw_filename);
+		} else
+			sms_info("mode %d supported by running "
+				 "firmware", mode);
+
+		buffer = kmalloc(sizeof(struct SmsMsgData_ST) +
+				 SMS_DMA_ALIGNMENT, GFP_KERNEL | GFP_DMA);
+		if (buffer) {
+			struct SmsMsgData_ST *msg =
+				(struct SmsMsgData_ST *)
+					SMS_ALIGN_ADDRESS(buffer);
+
+			SMS_INIT_MSG(&msg->xMsgHeader, MSG_SMS_INIT_DEVICE_REQ,
+				     sizeof(struct SmsMsgData_ST));
+			msg->msgData[0] = mode;
+
+			rc = smscore_sendrequest_and_wait(
+				coredev, msg, msg->xMsgHeader.msgLength,
+				&coredev->init_device_done);
+
+			kfree(buffer);
+		} else {
+			sms_err("Could not allocate buffer for "
+				"init device message.");
+			rc = -ENOMEM;
+		}
+	} else {
+		if (mode < DEVICE_MODE_DVBT || mode > DEVICE_MODE_DVBT_BDA) {
+			sms_err("invalid mode specified %d", mode);
+			return -EINVAL;
+		}
+
+		smscore_registry_setmode(coredev->devpath, mode);
+
+		if (coredev->detectmode_handler)
+			coredev->detectmode_handler(coredev->context,
+						    &coredev->mode);
+
+		if (coredev->mode != mode && coredev->setmode_handler)
+			rc = coredev->setmode_handler(coredev->context, mode);
+	}
+
+	if (rc >= 0) {
+		coredev->mode = mode;
+		coredev->device_flags &= ~SMS_DEVICE_NOT_READY;
+	}
+
+	if (rc < 0)
+		sms_err("return error code %d.", rc);
+	return rc;
+}
+
+/**
+ * calls device handler to get current mode of operation
+ *
+ * @param coredev pointer to a coredev object returned by
+ *                smscore_register_device
+ *
+ * @return current mode
+ */
+int smscore_get_device_mode(struct smscore_device_t *coredev)
+{
+	return coredev->mode;
+}
+EXPORT_SYMBOL_GPL(smscore_get_device_mode);
+
+/**
+ * find client by response id & type within the clients list.
+ * return client handle or NULL.
+ *
+ * @param coredev pointer to a coredev object returned by
+ *                smscore_register_device
+ * @param data_type client data type (SMS_DONT_CARE for all types)
+ * @param id client id (SMS_DONT_CARE for all id)
+ *
+ */
+static struct
+smscore_client_t *smscore_find_client(struct smscore_device_t *coredev,
+				      int data_type, int id)
+{
+	struct list_head *first;
+	struct smscore_client_t *client;
+	unsigned long flags;
+	struct list_head *firstid;
+	struct smscore_idlist_t *client_id;
+
+	spin_lock_irqsave(&coredev->clientslock, flags);
+	first = &coredev->clients;
+	list_for_each_entry(client, first, entry) {
+		firstid = &client->idlist;
+		list_for_each_entry(client_id, firstid, entry) {
+			if ((client_id->id == id) &&
+			    (client_id->data_type == data_type ||
+			    (client_id->data_type == 0)))
+				goto found;
+		}
+	}
+	client = NULL;
+found:
+	spin_unlock_irqrestore(&coredev->clientslock, flags);
+	return client;
+}
+
+/**
+ * find client by response id/type, call clients onresponse handler
+ * return buffer to pool on error
+ *
+ * @param coredev pointer to a coredev object returned by
+ *                smscore_register_device
+ * @param cb pointer to response buffer descriptor
+ *
+ */
+void smscore_onresponse(struct smscore_device_t *coredev,
+		struct smscore_buffer_t *cb) {
+	struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *) ((u8 *) cb->p
+			+ cb->offset);
+	struct smscore_client_t *client;
+	int rc = -EBUSY;
+	static unsigned long last_sample_time; /* = 0; */
+	static int data_total; /* = 0; */
+	unsigned long time_now = jiffies_to_msecs(jiffies);
+
+	if (!last_sample_time)
+		last_sample_time = time_now;
+
+	if (time_now - last_sample_time > 10000) {
+		sms_debug("\ndata rate %d bytes/secs",
+			  (int)((data_total * 1000) /
+				(time_now - last_sample_time)));
+
+		last_sample_time = time_now;
+		data_total = 0;
+	}
+
+	data_total += cb->size;
+	/* Do we need to re-route? */
+	if ((phdr->msgType == MSG_SMS_HO_PER_SLICES_IND) ||
+			(phdr->msgType == MSG_SMS_TRANSMISSION_IND)) {
+		if (coredev->mode == DEVICE_MODE_DVBT_BDA)
+			phdr->msgDstId = DVBT_BDA_CONTROL_MSG_ID;
+	}
+
+
+	client = smscore_find_client(coredev, phdr->msgType, phdr->msgDstId);
+
+	/* If no client registered for type & id,
+	 * check for control client where type is not registered */
+	if (client)
+		rc = client->onresponse_handler(client->context, cb);
+
+	if (rc < 0) {
+		switch (phdr->msgType) {
+		case MSG_SMS_GET_VERSION_EX_RES:
+		{
+			struct SmsVersionRes_ST *ver =
+				(struct SmsVersionRes_ST *) phdr;
+			sms_debug("MSG_SMS_GET_VERSION_EX_RES "
+				  "id %d prots 0x%x ver %d.%d",
+				  ver->FirmwareId, ver->SupportedProtocols,
+				  ver->RomVersionMajor, ver->RomVersionMinor);
+
+			coredev->mode = ver->FirmwareId == 255 ?
+				DEVICE_MODE_NONE : ver->FirmwareId;
+			coredev->modes_supported = ver->SupportedProtocols;
+
+			complete(&coredev->version_ex_done);
+			break;
+		}
+		case MSG_SMS_INIT_DEVICE_RES:
+			sms_debug("MSG_SMS_INIT_DEVICE_RES");
+			complete(&coredev->init_device_done);
+			break;
+		case MSG_SW_RELOAD_START_RES:
+			sms_debug("MSG_SW_RELOAD_START_RES");
+			complete(&coredev->reload_start_done);
+			break;
+		case MSG_SMS_DATA_DOWNLOAD_RES:
+			complete(&coredev->data_download_done);
+			break;
+		case MSG_SW_RELOAD_EXEC_RES:
+			sms_debug("MSG_SW_RELOAD_EXEC_RES");
+			break;
+		case MSG_SMS_SWDOWNLOAD_TRIGGER_RES:
+			sms_debug("MSG_SMS_SWDOWNLOAD_TRIGGER_RES");
+			complete(&coredev->trigger_done);
+			break;
+		case MSG_SMS_SLEEP_RESUME_COMP_IND:
+			complete(&coredev->resume_done);
+			break;
+		case MSG_SMS_GPIO_CONFIG_EX_RES:
+			sms_debug("MSG_SMS_GPIO_CONFIG_EX_RES");
+			complete(&coredev->gpio_configuration_done);
+			break;
+		case MSG_SMS_GPIO_SET_LEVEL_RES:
+			sms_debug("MSG_SMS_GPIO_SET_LEVEL_RES");
+			complete(&coredev->gpio_set_level_done);
+			break;
+		case MSG_SMS_GPIO_GET_LEVEL_RES:
+		{
+			u32 *msgdata = (u32 *) phdr;
+			coredev->gpio_get_res = msgdata[1];
+			sms_debug("MSG_SMS_GPIO_GET_LEVEL_RES gpio level %d",
+					coredev->gpio_get_res);
+			complete(&coredev->gpio_get_level_done);
+			break;
+		}
+		case MSG_SMS_START_IR_RES:
+			complete(&coredev->ir_init_done);
+			break;
+		case MSG_SMS_IR_SAMPLES_IND:
+			sms_ir_event(coredev,
+				(const char *)
+				((char *)phdr
+				+ sizeof(struct SmsMsgHdr_ST)),
+				(int)phdr->msgLength
+				- sizeof(struct SmsMsgHdr_ST));
+			break;
+
+		default:
+			break;
+		}
+		smscore_putbuffer(coredev, cb);
+	}
+}
+EXPORT_SYMBOL_GPL(smscore_onresponse);
+
+/**
+ * return pointer to next free buffer descriptor from core pool
+ *
+ * @param coredev pointer to a coredev object returned by
+ *                smscore_register_device
+ *
+ * @return pointer to descriptor on success, NULL on error.
+ */
+
+struct smscore_buffer_t *get_entry(struct smscore_device_t *coredev)
+{
+	struct smscore_buffer_t *cb = NULL;
+	unsigned long flags;
+
+	spin_lock_irqsave(&coredev->bufferslock, flags);
+	if (!list_empty(&coredev->buffers)) {
+		cb = (struct smscore_buffer_t *) coredev->buffers.next;
+		list_del(&cb->entry);
+	}
+	spin_unlock_irqrestore(&coredev->bufferslock, flags);
+	return cb;
+}
+
+struct smscore_buffer_t *smscore_getbuffer(struct smscore_device_t *coredev)
+{
+	struct smscore_buffer_t *cb = NULL;
+
+	wait_event(coredev->buffer_mng_waitq, (cb = get_entry(coredev)));
+
+	return cb;
+}
+EXPORT_SYMBOL_GPL(smscore_getbuffer);
+
+/**
+ * return buffer descriptor to a pool
+ *
+ * @param coredev pointer to a coredev object returned by
+ *                smscore_register_device
+ * @param cb pointer buffer descriptor
+ *
+ */
+void smscore_putbuffer(struct smscore_device_t *coredev,
+		struct smscore_buffer_t *cb) {
+	wake_up_interruptible(&coredev->buffer_mng_waitq);
+	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,
+				   int data_type, int id)
+{
+	struct smscore_idlist_t *listentry;
+	struct smscore_client_t *registered_client;
+
+	if (!client) {
+		sms_err("bad parameter.");
+		return -EINVAL;
+	}
+	registered_client = smscore_find_client(coredev, data_type, id);
+	if (registered_client == client)
+		return 0;
+
+	if (registered_client) {
+		sms_err("The msg ID already registered to another client.");
+		return -EEXIST;
+	}
+	listentry = kzalloc(sizeof(struct smscore_idlist_t), GFP_KERNEL);
+	if (!listentry) {
+		sms_err("Can't allocate memory for client id.");
+		return -ENOMEM;
+	}
+	listentry->id = id;
+	listentry->data_type = data_type;
+	list_add_locked(&listentry->entry, &client->idlist,
+			&coredev->clientslock);
+	return 0;
+}
+
+/**
+ * creates smsclient object, check that id is taken by another client
+ *
+ * @param coredev pointer to a coredev object from clients hotplug
+ * @param initial_id all messages with this id would be sent to this client
+ * @param data_type all messages of this type would be sent to this client
+ * @param onresponse_handler client handler that is called to
+ *                           process incoming messages
+ * @param onremove_handler client handler that is called when device is removed
+ * @param context client-specific context
+ * @param client pointer to a value that receives created smsclient object
+ *
+ * @return 0 on success, <0 on error.
+ */
+int smscore_register_client(struct smscore_device_t *coredev,
+			    struct smsclient_params_t *params,
+			    struct smscore_client_t **client)
+{
+	struct smscore_client_t *newclient;
+	/* check that no other channel with same parameters exists */
+	if (smscore_find_client(coredev, params->data_type,
+				params->initial_id)) {
+		sms_err("Client already exist.");
+		return -EEXIST;
+	}
+
+	newclient = kzalloc(sizeof(struct smscore_client_t), GFP_KERNEL);
+	if (!newclient) {
+		sms_err("Failed to allocate memory for client.");
+		return -ENOMEM;
+	}
+
+	INIT_LIST_HEAD(&newclient->idlist);
+	newclient->coredev = coredev;
+	newclient->onresponse_handler = params->onresponse_handler;
+	newclient->onremove_handler = params->onremove_handler;
+	newclient->context = params->context;
+	list_add_locked(&newclient->entry, &coredev->clients,
+			&coredev->clientslock);
+	smscore_validate_client(coredev, newclient, params->data_type,
+				params->initial_id);
+	*client = newclient;
+	sms_debug("%p %d %d", params->context, params->data_type,
+		  params->initial_id);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(smscore_register_client);
+
+/**
+ * frees smsclient object and all subclients associated with it
+ *
+ * @param client pointer to smsclient object returned by
+ *               smscore_register_client
+ *
+ */
+void smscore_unregister_client(struct smscore_client_t *client)
+{
+	struct smscore_device_t *coredev = client->coredev;
+	unsigned long flags;
+
+	spin_lock_irqsave(&coredev->clientslock, flags);
+
+
+	while (!list_empty(&client->idlist)) {
+		struct smscore_idlist_t *identry =
+			(struct smscore_idlist_t *) client->idlist.next;
+		list_del(&identry->entry);
+		kfree(identry);
+	}
+
+	sms_info("%p", client->context);
+
+	list_del(&client->entry);
+	kfree(client);
+
+	spin_unlock_irqrestore(&coredev->clientslock, flags);
+}
+EXPORT_SYMBOL_GPL(smscore_unregister_client);
+
+/**
+ * verifies that source id is not taken by another client,
+ * calls device handler to send requests to the device
+ *
+ * @param client pointer to smsclient object returned by
+ *               smscore_register_client
+ * @param buffer pointer to a request buffer
+ * @param size size (in bytes) of request buffer
+ *
+ * @return 0 on success, <0 on error.
+ */
+int smsclient_sendrequest(struct smscore_client_t *client,
+			  void *buffer, size_t size)
+{
+	struct smscore_device_t *coredev;
+	struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *) buffer;
+	int rc;
+
+	if (client == NULL) {
+		sms_err("Got NULL client");
+		return -EINVAL;
+	}
+
+	coredev = client->coredev;
+
+	/* check that no other channel with same id exists */
+	if (coredev == NULL) {
+		sms_err("Got NULL coredev");
+		return -EINVAL;
+	}
+
+	rc = smscore_validate_client(client->coredev, client, 0,
+				     phdr->msgSrcId);
+	if (rc < 0)
+		return rc;
+
+	return coredev->sendrequest_handler(coredev->context, buffer, size);
+}
+EXPORT_SYMBOL_GPL(smsclient_sendrequest);
+
+
+/* old GPIO managements implementation */
+int smscore_configure_gpio(struct smscore_device_t *coredev, u32 pin,
+			   struct smscore_config_gpio *pinconfig)
+{
+	struct {
+		struct SmsMsgHdr_ST hdr;
+		u32 data[6];
+	} msg;
+
+	if (coredev->device_flags & SMS_DEVICE_FAMILY2) {
+		msg.hdr.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
+		msg.hdr.msgDstId = HIF_TASK;
+		msg.hdr.msgFlags = 0;
+		msg.hdr.msgType  = MSG_SMS_GPIO_CONFIG_EX_REQ;
+		msg.hdr.msgLength = sizeof(msg);
+
+		msg.data[0] = pin;
+		msg.data[1] = pinconfig->pullupdown;
+
+		/* Convert slew rate for Nova: Fast(0) = 3 / Slow(1) = 0; */
+		msg.data[2] = pinconfig->outputslewrate == 0 ? 3 : 0;
+
+		switch (pinconfig->outputdriving) {
+		case SMS_GPIO_OUTPUTDRIVING_16mA:
+			msg.data[3] = 7; /* Nova - 16mA */
+			break;
+		case SMS_GPIO_OUTPUTDRIVING_12mA:
+			msg.data[3] = 5; /* Nova - 11mA */
+			break;
+		case SMS_GPIO_OUTPUTDRIVING_8mA:
+			msg.data[3] = 3; /* Nova - 7mA */
+			break;
+		case SMS_GPIO_OUTPUTDRIVING_4mA:
+		default:
+			msg.data[3] = 2; /* Nova - 4mA */
+			break;
+		}
+
+		msg.data[4] = pinconfig->direction;
+		msg.data[5] = 0;
+	} else /* TODO: SMS_DEVICE_FAMILY1 */
+		return -EINVAL;
+
+	return coredev->sendrequest_handler(coredev->context,
+					    &msg, sizeof(msg));
+}
+
+int smscore_set_gpio(struct smscore_device_t *coredev, u32 pin, int level)
+{
+	struct {
+		struct SmsMsgHdr_ST hdr;
+		u32 data[3];
+	} msg;
+
+	if (pin > MAX_GPIO_PIN_NUMBER)
+		return -EINVAL;
+
+	msg.hdr.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
+	msg.hdr.msgDstId = HIF_TASK;
+	msg.hdr.msgFlags = 0;
+	msg.hdr.msgType  = MSG_SMS_GPIO_SET_LEVEL_REQ;
+	msg.hdr.msgLength = sizeof(msg);
+
+	msg.data[0] = pin;
+	msg.data[1] = level ? 1 : 0;
+	msg.data[2] = 0;
+
+	return coredev->sendrequest_handler(coredev->context,
+					    &msg, sizeof(msg));
+}
+
+/* new GPIO management implementation */
+static int GetGpioPinParams(u32 PinNum, u32 *pTranslatedPinNum,
+		u32 *pGroupNum, u32 *pGroupCfg) {
+
+	*pGroupCfg = 1;
+
+	if (PinNum <= 1)	{
+		*pTranslatedPinNum = 0;
+		*pGroupNum = 9;
+		*pGroupCfg = 2;
+	} else if (PinNum >= 2 && PinNum <= 6) {
+		*pTranslatedPinNum = 2;
+		*pGroupNum = 0;
+		*pGroupCfg = 2;
+	} else if (PinNum >= 7 && PinNum <= 11) {
+		*pTranslatedPinNum = 7;
+		*pGroupNum = 1;
+	} else if (PinNum >= 12 && PinNum <= 15) {
+		*pTranslatedPinNum = 12;
+		*pGroupNum = 2;
+		*pGroupCfg = 3;
+	} else if (PinNum == 16) {
+		*pTranslatedPinNum = 16;
+		*pGroupNum = 23;
+	} else if (PinNum >= 17 && PinNum <= 24) {
+		*pTranslatedPinNum = 17;
+		*pGroupNum = 3;
+	} else if (PinNum == 25) {
+		*pTranslatedPinNum = 25;
+		*pGroupNum = 6;
+	} else if (PinNum >= 26 && PinNum <= 28) {
+		*pTranslatedPinNum = 26;
+		*pGroupNum = 4;
+	} else if (PinNum == 29) {
+		*pTranslatedPinNum = 29;
+		*pGroupNum = 5;
+		*pGroupCfg = 2;
+	} else if (PinNum == 30) {
+		*pTranslatedPinNum = 30;
+		*pGroupNum = 8;
+	} else if (PinNum == 31) {
+		*pTranslatedPinNum = 31;
+		*pGroupNum = 17;
+	} else
+		return -1;
+
+	*pGroupCfg <<= 24;
+
+	return 0;
+}
+
+int smscore_gpio_configure(struct smscore_device_t *coredev, u8 PinNum,
+		struct smscore_gpio_config *pGpioConfig) {
+
+	u32 totalLen;
+	u32 TranslatedPinNum = 0;
+	u32 GroupNum = 0;
+	u32 ElectricChar;
+	u32 groupCfg;
+	void *buffer;
+	int rc;
+
+	struct SetGpioMsg {
+		struct SmsMsgHdr_ST xMsgHeader;
+		u32 msgData[6];
+	} *pMsg;
+
+
+	if (PinNum > MAX_GPIO_PIN_NUMBER)
+		return -EINVAL;
+
+	if (pGpioConfig == NULL)
+		return -EINVAL;
+
+	totalLen = sizeof(struct SmsMsgHdr_ST) + (sizeof(u32) * 6);
+
+	buffer = kmalloc(totalLen + SMS_DMA_ALIGNMENT,
+			GFP_KERNEL | GFP_DMA);
+	if (!buffer)
+		return -ENOMEM;
+
+	pMsg = (struct SetGpioMsg *) SMS_ALIGN_ADDRESS(buffer);
+
+	pMsg->xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
+	pMsg->xMsgHeader.msgDstId = HIF_TASK;
+	pMsg->xMsgHeader.msgFlags = 0;
+	pMsg->xMsgHeader.msgLength = (u16) totalLen;
+	pMsg->msgData[0] = PinNum;
+
+	if (!(coredev->device_flags & SMS_DEVICE_FAMILY2)) {
+		pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_CONFIG_REQ;
+		if (GetGpioPinParams(PinNum, &TranslatedPinNum, &GroupNum,
+				&groupCfg) != 0) {
+			rc = -EINVAL;
+			goto free;
+		}
+
+		pMsg->msgData[1] = TranslatedPinNum;
+		pMsg->msgData[2] = GroupNum;
+		ElectricChar = (pGpioConfig->PullUpDown)
+				| (pGpioConfig->InputCharacteristics << 2)
+				| (pGpioConfig->OutputSlewRate << 3)
+				| (pGpioConfig->OutputDriving << 4);
+		pMsg->msgData[3] = ElectricChar;
+		pMsg->msgData[4] = pGpioConfig->Direction;
+		pMsg->msgData[5] = groupCfg;
+	} else {
+		pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_CONFIG_EX_REQ;
+		pMsg->msgData[1] = pGpioConfig->PullUpDown;
+		pMsg->msgData[2] = pGpioConfig->OutputSlewRate;
+		pMsg->msgData[3] = pGpioConfig->OutputDriving;
+		pMsg->msgData[4] = pGpioConfig->Direction;
+		pMsg->msgData[5] = 0;
+	}
+
+	smsendian_handle_tx_message((struct SmsMsgHdr_ST *)pMsg);
+	rc = smscore_sendrequest_and_wait(coredev, pMsg, totalLen,
+			&coredev->gpio_configuration_done);
+
+	if (rc != 0) {
+		if (rc == -ETIME)
+			sms_err("smscore_gpio_configure timeout");
+		else
+			sms_err("smscore_gpio_configure error");
+	}
+free:
+	kfree(buffer);
+
+	return rc;
+}
+
+int smscore_gpio_set_level(struct smscore_device_t *coredev, u8 PinNum,
+		u8 NewLevel) {
+
+	u32 totalLen;
+	int rc;
+	void *buffer;
+
+	struct SetGpioMsg {
+		struct SmsMsgHdr_ST xMsgHeader;
+		u32 msgData[3]; /* keep it 3 ! */
+	} *pMsg;
+
+	if ((NewLevel > 1) || (PinNum > MAX_GPIO_PIN_NUMBER))
+		return -EINVAL;
+
+	totalLen = sizeof(struct SmsMsgHdr_ST) +
+			(3 * sizeof(u32)); /* keep it 3 ! */
+
+	buffer = kmalloc(totalLen + SMS_DMA_ALIGNMENT,
+			GFP_KERNEL | GFP_DMA);
+	if (!buffer)
+		return -ENOMEM;
+
+	pMsg = (struct SetGpioMsg *) SMS_ALIGN_ADDRESS(buffer);
+
+	pMsg->xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
+	pMsg->xMsgHeader.msgDstId = HIF_TASK;
+	pMsg->xMsgHeader.msgFlags = 0;
+	pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_SET_LEVEL_REQ;
+	pMsg->xMsgHeader.msgLength = (u16) totalLen;
+	pMsg->msgData[0] = PinNum;
+	pMsg->msgData[1] = NewLevel;
+
+	/* Send message to SMS */
+	smsendian_handle_tx_message((struct SmsMsgHdr_ST *)pMsg);
+	rc = smscore_sendrequest_and_wait(coredev, pMsg, totalLen,
+			&coredev->gpio_set_level_done);
+
+	if (rc != 0) {
+		if (rc == -ETIME)
+			sms_err("smscore_gpio_set_level timeout");
+		else
+			sms_err("smscore_gpio_set_level error");
+	}
+	kfree(buffer);
+
+	return rc;
+}
+
+int smscore_gpio_get_level(struct smscore_device_t *coredev, u8 PinNum,
+		u8 *level) {
+
+	u32 totalLen;
+	int rc;
+	void *buffer;
+
+	struct SetGpioMsg {
+		struct SmsMsgHdr_ST xMsgHeader;
+		u32 msgData[2];
+	} *pMsg;
+
+
+	if (PinNum > MAX_GPIO_PIN_NUMBER)
+		return -EINVAL;
+
+	totalLen = sizeof(struct SmsMsgHdr_ST) + (2 * sizeof(u32));
+
+	buffer = kmalloc(totalLen + SMS_DMA_ALIGNMENT,
+			GFP_KERNEL | GFP_DMA);
+	if (!buffer)
+		return -ENOMEM;
+
+	pMsg = (struct SetGpioMsg *) SMS_ALIGN_ADDRESS(buffer);
+
+	pMsg->xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
+	pMsg->xMsgHeader.msgDstId = HIF_TASK;
+	pMsg->xMsgHeader.msgFlags = 0;
+	pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_GET_LEVEL_REQ;
+	pMsg->xMsgHeader.msgLength = (u16) totalLen;
+	pMsg->msgData[0] = PinNum;
+	pMsg->msgData[1] = 0;
+
+	/* Send message to SMS */
+	smsendian_handle_tx_message((struct SmsMsgHdr_ST *)pMsg);
+	rc = smscore_sendrequest_and_wait(coredev, pMsg, totalLen,
+			&coredev->gpio_get_level_done);
+
+	if (rc != 0) {
+		if (rc == -ETIME)
+			sms_err("smscore_gpio_get_level timeout");
+		else
+			sms_err("smscore_gpio_get_level error");
+	}
+	kfree(buffer);
+
+	/* Its a race between other gpio_get_level() and the copy of the single
+	 * global 'coredev->gpio_get_res' to  the function's variable 'level'
+	 */
+	*level = coredev->gpio_get_res;
+
+	return rc;
+}
+
+static int __init smscore_module_init(void)
+{
+	int rc = 0;
+
+	INIT_LIST_HEAD(&g_smscore_notifyees);
+	INIT_LIST_HEAD(&g_smscore_devices);
+	kmutex_init(&g_smscore_deviceslock);
+
+	INIT_LIST_HEAD(&g_smscore_registry);
+	kmutex_init(&g_smscore_registrylock);
+
+	return rc;
+}
+
+static void __exit smscore_module_exit(void)
+{
+	kmutex_lock(&g_smscore_deviceslock);
+	while (!list_empty(&g_smscore_notifyees)) {
+		struct smscore_device_notifyee_t *notifyee =
+			(struct smscore_device_notifyee_t *)
+				g_smscore_notifyees.next;
+
+		list_del(&notifyee->entry);
+		kfree(notifyee);
+	}
+	kmutex_unlock(&g_smscore_deviceslock);
+
+	kmutex_lock(&g_smscore_registrylock);
+	while (!list_empty(&g_smscore_registry)) {
+		struct smscore_registry_entry_t *entry =
+			(struct smscore_registry_entry_t *)
+				g_smscore_registry.next;
+
+		list_del(&entry->entry);
+		kfree(entry);
+	}
+	kmutex_unlock(&g_smscore_registrylock);
+
+	sms_debug("");
+}
+
+module_init(smscore_module_init);
+module_exit(smscore_module_exit);
+
+MODULE_DESCRIPTION("Siano MDTV Core module");
+MODULE_AUTHOR("Siano Mobile Silicon, Inc. (uris@siano-ms.com)");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/common/siano/smscoreapi.h b/drivers/media/common/siano/smscoreapi.h
new file mode 100644
index 0000000..c592ae0
--- /dev/null
+++ b/drivers/media/common/siano/smscoreapi.h
@@ -0,0 +1,775 @@
+/****************************************************************
+
+Siano Mobile Silicon, Inc.
+MDTV receiver kernel modules.
+Copyright (C) 2006-2008, Uri Shkolnik, Anatoly Greenblat
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+****************************************************************/
+
+#ifndef __SMS_CORE_API_H__
+#define __SMS_CORE_API_H__
+
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/mm.h>
+#include <linux/scatterlist.h>
+#include <linux/types.h>
+#include <linux/mutex.h>
+#include <linux/wait.h>
+#include <linux/timer.h>
+
+#include <asm/page.h>
+
+#include "smsir.h"
+
+#define kmutex_init(_p_) mutex_init(_p_)
+#define kmutex_lock(_p_) mutex_lock(_p_)
+#define kmutex_trylock(_p_) mutex_trylock(_p_)
+#define kmutex_unlock(_p_) mutex_unlock(_p_)
+
+#ifndef min
+#define min(a, b) (((a) < (b)) ? (a) : (b))
+#endif
+
+#define SMS_PROTOCOL_MAX_RAOUNDTRIP_MS			(10000)
+#define SMS_ALLOC_ALIGNMENT				128
+#define SMS_DMA_ALIGNMENT				16
+#define SMS_ALIGN_ADDRESS(addr) \
+	((((uintptr_t)(addr)) + (SMS_DMA_ALIGNMENT-1)) & ~(SMS_DMA_ALIGNMENT-1))
+
+#define SMS_DEVICE_FAMILY2				1
+#define SMS_ROM_NO_RESPONSE				2
+#define SMS_DEVICE_NOT_READY				0x8000000
+
+enum sms_device_type_st {
+	SMS_STELLAR = 0,
+	SMS_NOVA_A0,
+	SMS_NOVA_B0,
+	SMS_VEGA,
+	SMS_NUM_OF_DEVICE_TYPES
+};
+
+struct smscore_device_t;
+struct smscore_client_t;
+struct smscore_buffer_t;
+
+typedef int (*hotplug_t)(struct smscore_device_t *coredev,
+			 struct device *device, int arrival);
+
+typedef int (*setmode_t)(void *context, int mode);
+typedef void (*detectmode_t)(void *context, int *mode);
+typedef int (*sendrequest_t)(void *context, void *buffer, size_t size);
+typedef int (*loadfirmware_t)(void *context, void *buffer, size_t size);
+typedef int (*preload_t)(void *context);
+typedef int (*postload_t)(void *context);
+
+typedef int (*onresponse_t)(void *context, struct smscore_buffer_t *cb);
+typedef void (*onremove_t)(void *context);
+
+struct smscore_buffer_t {
+	/* public members, once passed to clients can be changed freely */
+	struct list_head entry;
+	int size;
+	int offset;
+
+	/* private members, read-only for clients */
+	void *p;
+	dma_addr_t phys;
+	unsigned long offset_in_common;
+};
+
+struct smsdevice_params_t {
+	struct device	*device;
+
+	int				buffer_size;
+	int				num_buffers;
+
+	char			devpath[32];
+	unsigned long	flags;
+
+	setmode_t		setmode_handler;
+	detectmode_t	detectmode_handler;
+	sendrequest_t	sendrequest_handler;
+	preload_t		preload_handler;
+	postload_t		postload_handler;
+
+	void			*context;
+	enum sms_device_type_st device_type;
+};
+
+struct smsclient_params_t {
+	int				initial_id;
+	int				data_type;
+	onresponse_t	onresponse_handler;
+	onremove_t		onremove_handler;
+	void			*context;
+};
+
+struct smscore_device_t {
+	struct list_head entry;
+
+	struct list_head clients;
+	struct list_head subclients;
+	spinlock_t clientslock;
+
+	struct list_head buffers;
+	spinlock_t bufferslock;
+	int num_buffers;
+
+	void *common_buffer;
+	int common_buffer_size;
+	dma_addr_t common_buffer_phys;
+
+	void *context;
+	struct device *device;
+
+	char devpath[32];
+	unsigned long device_flags;
+
+	setmode_t setmode_handler;
+	detectmode_t detectmode_handler;
+	sendrequest_t sendrequest_handler;
+	preload_t preload_handler;
+	postload_t postload_handler;
+
+	int mode, modes_supported;
+
+	/* host <--> device messages */
+	struct completion version_ex_done, data_download_done, trigger_done;
+	struct completion init_device_done, reload_start_done, resume_done;
+	struct completion gpio_configuration_done, gpio_set_level_done;
+	struct completion gpio_get_level_done, ir_init_done;
+
+	/* Buffer management */
+	wait_queue_head_t buffer_mng_waitq;
+
+	/* GPIO */
+	int gpio_get_res;
+
+	/* Target hardware board */
+	int board_id;
+
+	/* Firmware */
+	u8 *fw_buf;
+	u32 fw_buf_size;
+
+	/* Infrared (IR) */
+	struct ir_t ir;
+
+	int led_state;
+};
+
+/* GPIO definitions for antenna frequency domain control (SMS8021) */
+#define SMS_ANTENNA_GPIO_0					1
+#define SMS_ANTENNA_GPIO_1					0
+
+#define BW_8_MHZ							0
+#define BW_7_MHZ							1
+#define BW_6_MHZ							2
+#define BW_5_MHZ							3
+#define BW_ISDBT_1SEG						4
+#define BW_ISDBT_3SEG						5
+
+#define MSG_HDR_FLAG_SPLIT_MSG				4
+
+#define MAX_GPIO_PIN_NUMBER					31
+
+#define HIF_TASK							11
+#define SMS_HOST_LIB						150
+#define DVBT_BDA_CONTROL_MSG_ID				201
+
+#define SMS_MAX_PAYLOAD_SIZE				240
+#define SMS_TUNE_TIMEOUT					500
+
+#define MSG_SMS_GPIO_CONFIG_REQ				507
+#define MSG_SMS_GPIO_CONFIG_RES				508
+#define MSG_SMS_GPIO_SET_LEVEL_REQ			509
+#define MSG_SMS_GPIO_SET_LEVEL_RES			510
+#define MSG_SMS_GPIO_GET_LEVEL_REQ			511
+#define MSG_SMS_GPIO_GET_LEVEL_RES			512
+#define MSG_SMS_RF_TUNE_REQ					561
+#define MSG_SMS_RF_TUNE_RES					562
+#define MSG_SMS_INIT_DEVICE_REQ				578
+#define MSG_SMS_INIT_DEVICE_RES				579
+#define MSG_SMS_ADD_PID_FILTER_REQ			601
+#define MSG_SMS_ADD_PID_FILTER_RES			602
+#define MSG_SMS_REMOVE_PID_FILTER_REQ			603
+#define MSG_SMS_REMOVE_PID_FILTER_RES			604
+#define MSG_SMS_DAB_CHANNEL				607
+#define MSG_SMS_GET_PID_FILTER_LIST_REQ			608
+#define MSG_SMS_GET_PID_FILTER_LIST_RES			609
+#define MSG_SMS_GET_STATISTICS_RES			616
+#define MSG_SMS_GET_STATISTICS_REQ			615
+#define MSG_SMS_HO_PER_SLICES_IND			630
+#define MSG_SMS_SET_ANTENNA_CONFIG_REQ			651
+#define MSG_SMS_SET_ANTENNA_CONFIG_RES			652
+#define MSG_SMS_SLEEP_RESUME_COMP_IND			655
+#define MSG_SMS_DATA_DOWNLOAD_REQ			660
+#define MSG_SMS_DATA_DOWNLOAD_RES			661
+#define MSG_SMS_SWDOWNLOAD_TRIGGER_REQ		664
+#define MSG_SMS_SWDOWNLOAD_TRIGGER_RES		665
+#define MSG_SMS_SWDOWNLOAD_BACKDOOR_REQ		666
+#define MSG_SMS_SWDOWNLOAD_BACKDOOR_RES		667
+#define MSG_SMS_GET_VERSION_EX_REQ			668
+#define MSG_SMS_GET_VERSION_EX_RES			669
+#define MSG_SMS_SET_CLOCK_OUTPUT_REQ		670
+#define MSG_SMS_I2C_SET_FREQ_REQ			685
+#define MSG_SMS_GENERIC_I2C_REQ				687
+#define MSG_SMS_GENERIC_I2C_RES				688
+#define MSG_SMS_DVBT_BDA_DATA				693
+#define MSG_SW_RELOAD_REQ					697
+#define MSG_SMS_DATA_MSG					699
+#define MSG_SW_RELOAD_START_REQ				702
+#define MSG_SW_RELOAD_START_RES				703
+#define MSG_SW_RELOAD_EXEC_REQ				704
+#define MSG_SW_RELOAD_EXEC_RES				705
+#define MSG_SMS_SPI_INT_LINE_SET_REQ		710
+#define MSG_SMS_GPIO_CONFIG_EX_REQ			712
+#define MSG_SMS_GPIO_CONFIG_EX_RES			713
+#define MSG_SMS_ISDBT_TUNE_REQ				776
+#define MSG_SMS_ISDBT_TUNE_RES				777
+#define MSG_SMS_TRANSMISSION_IND			782
+#define MSG_SMS_START_IR_REQ				800
+#define MSG_SMS_START_IR_RES				801
+#define MSG_SMS_IR_SAMPLES_IND				802
+#define MSG_SMS_SIGNAL_DETECTED_IND			827
+#define MSG_SMS_NO_SIGNAL_IND				828
+
+#define SMS_INIT_MSG_EX(ptr, type, src, dst, len) do { \
+	(ptr)->msgType = type; (ptr)->msgSrcId = src; (ptr)->msgDstId = dst; \
+	(ptr)->msgLength = len; (ptr)->msgFlags = 0; \
+} while (0)
+
+#define SMS_INIT_MSG(ptr, type, len) \
+	SMS_INIT_MSG_EX(ptr, type, 0, HIF_TASK, len)
+
+enum SMS_DVB3_EVENTS {
+	DVB3_EVENT_INIT = 0,
+	DVB3_EVENT_SLEEP,
+	DVB3_EVENT_HOTPLUG,
+	DVB3_EVENT_FE_LOCK,
+	DVB3_EVENT_FE_UNLOCK,
+	DVB3_EVENT_UNC_OK,
+	DVB3_EVENT_UNC_ERR
+};
+
+enum SMS_DEVICE_MODE {
+	DEVICE_MODE_NONE = -1,
+	DEVICE_MODE_DVBT = 0,
+	DEVICE_MODE_DVBH,
+	DEVICE_MODE_DAB_TDMB,
+	DEVICE_MODE_DAB_TDMB_DABIP,
+	DEVICE_MODE_DVBT_BDA,
+	DEVICE_MODE_ISDBT,
+	DEVICE_MODE_ISDBT_BDA,
+	DEVICE_MODE_CMMB,
+	DEVICE_MODE_RAW_TUNER,
+	DEVICE_MODE_MAX,
+};
+
+struct SmsMsgHdr_ST {
+	u16	msgType;
+	u8	msgSrcId;
+	u8	msgDstId;
+	u16	msgLength; /* Length of entire message, including header */
+	u16	msgFlags;
+};
+
+struct SmsMsgData_ST {
+	struct SmsMsgHdr_ST xMsgHeader;
+	u32 msgData[1];
+};
+
+struct SmsMsgData_ST2 {
+	struct SmsMsgHdr_ST xMsgHeader;
+	u32 msgData[2];
+};
+
+struct SmsDataDownload_ST {
+	struct SmsMsgHdr_ST	xMsgHeader;
+	u32			MemAddr;
+	u8			Payload[SMS_MAX_PAYLOAD_SIZE];
+};
+
+struct SmsVersionRes_ST {
+	struct SmsMsgHdr_ST	xMsgHeader;
+
+	u16		ChipModel; /* e.g. 0x1102 for SMS-1102 "Nova" */
+	u8		Step; /* 0 - Step A */
+	u8		MetalFix; /* 0 - Metal 0 */
+
+	/* FirmwareId 0xFF if ROM, otherwise the
+	 * value indicated by SMSHOSTLIB_DEVICE_MODES_E */
+	u8 FirmwareId;
+	/* SupportedProtocols Bitwise OR combination of
+					     * supported protocols */
+	u8 SupportedProtocols;
+
+	u8		VersionMajor;
+	u8		VersionMinor;
+	u8		VersionPatch;
+	u8		VersionFieldPatch;
+
+	u8		RomVersionMajor;
+	u8		RomVersionMinor;
+	u8		RomVersionPatch;
+	u8		RomVersionFieldPatch;
+
+	u8		TextLabel[34];
+};
+
+struct SmsFirmware_ST {
+	u32			CheckSum;
+	u32			Length;
+	u32			StartAddress;
+	u8			Payload[1];
+};
+
+/* Statistics information returned as response for
+ * SmsHostApiGetStatistics_Req */
+struct SMSHOSTLIB_STATISTICS_ST {
+	u32 Reserved;		/* Reserved */
+
+	/* Common parameters */
+	u32 IsRfLocked;		/* 0 - not locked, 1 - locked */
+	u32 IsDemodLocked;	/* 0 - not locked, 1 - locked */
+	u32 IsExternalLNAOn;	/* 0 - external LNA off, 1 - external LNA on */
+
+	/* Reception quality */
+	s32 SNR;		/* dB */
+	u32 BER;		/* Post Viterbi BER [1E-5] */
+	u32 FIB_CRC;		/* CRC errors percentage, valid only for DAB */
+	u32 TS_PER;		/* Transport stream PER,
+	0xFFFFFFFF indicate N/A, valid only for DVB-T/H */
+	u32 MFER;		/* DVB-H frame error rate in percentage,
+	0xFFFFFFFF indicate N/A, valid only for DVB-H */
+	s32 RSSI;		/* dBm */
+	s32 InBandPwr;		/* In band power in dBM */
+	s32 CarrierOffset;	/* Carrier Offset in bin/1024 */
+
+	/* Transmission parameters */
+	u32 Frequency;		/* Frequency in Hz */
+	u32 Bandwidth;		/* Bandwidth in MHz, valid only for DVB-T/H */
+	u32 TransmissionMode;	/* Transmission Mode, for DAB modes 1-4,
+	for DVB-T/H FFT mode carriers in Kilos */
+	u32 ModemState;		/* from SMSHOSTLIB_DVB_MODEM_STATE_ET,
+	valid only for DVB-T/H */
+	u32 GuardInterval;	/* Guard Interval from
+	SMSHOSTLIB_GUARD_INTERVALS_ET, 	valid only for DVB-T/H */
+	u32 CodeRate;		/* Code Rate from SMSHOSTLIB_CODE_RATE_ET,
+	valid only for DVB-T/H */
+	u32 LPCodeRate;		/* Low Priority Code Rate from
+	SMSHOSTLIB_CODE_RATE_ET, valid only for DVB-T/H */
+	u32 Hierarchy;		/* Hierarchy from SMSHOSTLIB_HIERARCHY_ET,
+	valid only for DVB-T/H */
+	u32 Constellation;	/* Constellation from
+	SMSHOSTLIB_CONSTELLATION_ET, valid only for DVB-T/H */
+
+	/* Burst parameters, valid only for DVB-H */
+	u32 BurstSize;		/* Current burst size in bytes,
+	valid only for DVB-H */
+	u32 BurstDuration;	/* Current burst duration in mSec,
+	valid only for DVB-H */
+	u32 BurstCycleTime;	/* Current burst cycle time in mSec,
+	valid only for DVB-H */
+	u32 CalculatedBurstCycleTime;/* Current burst cycle time in mSec,
+	as calculated by demodulator, valid only for DVB-H */
+	u32 NumOfRows;		/* Number of rows in MPE table,
+	valid only for DVB-H */
+	u32 NumOfPaddCols;	/* Number of padding columns in MPE table,
+	valid only for DVB-H */
+	u32 NumOfPunctCols;	/* Number of puncturing columns in MPE table,
+	valid only for DVB-H */
+	u32 ErrorTSPackets;	/* Number of erroneous
+	transport-stream packets */
+	u32 TotalTSPackets;	/* Total number of transport-stream packets */
+	u32 NumOfValidMpeTlbs;	/* Number of MPE tables which do not include
+	errors after MPE RS decoding */
+	u32 NumOfInvalidMpeTlbs;/* Number of MPE tables which include errors
+	after MPE RS decoding */
+	u32 NumOfCorrectedMpeTlbs;/* Number of MPE tables which were
+	corrected by MPE RS decoding */
+	/* Common params */
+	u32 BERErrorCount;	/* Number of errornous SYNC bits. */
+	u32 BERBitCount;	/* Total number of SYNC bits. */
+
+	/* Interface information */
+	u32 SmsToHostTxErrors;	/* Total number of transmission errors. */
+
+	/* DAB/T-DMB */
+	u32 PreBER; 		/* DAB/T-DMB only: Pre Viterbi BER [1E-5] */
+
+	/* DVB-H TPS parameters */
+	u32 CellId;		/* TPS Cell ID in bits 15..0, bits 31..16 zero;
+	 if set to 0xFFFFFFFF cell_id not yet recovered */
+	u32 DvbhSrvIndHP;	/* DVB-H service indication info, bit 1 -
+	Time Slicing indicator, bit 0 - MPE-FEC indicator */
+	u32 DvbhSrvIndLP;	/* DVB-H service indication info, bit 1 -
+	Time Slicing indicator, bit 0 - MPE-FEC indicator */
+
+	u32 NumMPEReceived;	/* DVB-H, Num MPE section received */
+
+	u32 ReservedFields[10];	/* Reserved */
+};
+
+struct SmsMsgStatisticsInfo_ST {
+	u32 RequestResult;
+
+	struct SMSHOSTLIB_STATISTICS_ST Stat;
+
+	/* Split the calc of the SNR in DAB */
+	u32 Signal; /* dB */
+	u32 Noise; /* dB */
+
+};
+
+struct SMSHOSTLIB_ISDBT_LAYER_STAT_ST {
+	/* Per-layer information */
+	u32 CodeRate; /* Code Rate from SMSHOSTLIB_CODE_RATE_ET,
+		       * 255 means layer does not exist */
+	u32 Constellation; /* Constellation from SMSHOSTLIB_CONSTELLATION_ET,
+			    * 255 means layer does not exist */
+	u32 BER; /* Post Viterbi BER [1E-5], 0xFFFFFFFF indicate N/A */
+	u32 BERErrorCount; /* Post Viterbi Error Bits Count */
+	u32 BERBitCount; /* Post Viterbi Total Bits Count */
+	u32 PreBER; /* Pre Viterbi BER [1E-5], 0xFFFFFFFF indicate N/A */
+	u32 TS_PER; /* Transport stream PER [%], 0xFFFFFFFF indicate N/A */
+	u32 ErrorTSPackets; /* Number of erroneous transport-stream packets */
+	u32 TotalTSPackets; /* Total number of transport-stream packets */
+	u32 TILdepthI; /* Time interleaver depth I parameter,
+			* 255 means layer does not exist */
+	u32 NumberOfSegments; /* Number of segments in layer A,
+			       * 255 means layer does not exist */
+	u32 TMCCErrors; /* TMCC errors */
+};
+
+struct SMSHOSTLIB_STATISTICS_ISDBT_ST {
+	u32 StatisticsType; /* Enumerator identifying the type of the
+				* structure.  Values are the same as
+				* SMSHOSTLIB_DEVICE_MODES_E
+				*
+				* This field MUST always be first in any
+				* statistics structure */
+
+	u32 FullSize; /* Total size of the structure returned by the modem.
+		       * If the size requested by the host is smaller than
+		       * FullSize, the struct will be truncated */
+
+	/* Common parameters */
+	u32 IsRfLocked; /* 0 - not locked, 1 - locked */
+	u32 IsDemodLocked; /* 0 - not locked, 1 - locked */
+	u32 IsExternalLNAOn; /* 0 - external LNA off, 1 - external LNA on */
+
+	/* Reception quality */
+	s32  SNR; /* dB */
+	s32  RSSI; /* dBm */
+	s32  InBandPwr; /* In band power in dBM */
+	s32  CarrierOffset; /* Carrier Offset in Hz */
+
+	/* Transmission parameters */
+	u32 Frequency; /* Frequency in Hz */
+	u32 Bandwidth; /* Bandwidth in MHz */
+	u32 TransmissionMode; /* ISDB-T transmission mode */
+	u32 ModemState; /* 0 - Acquisition, 1 - Locked */
+	u32 GuardInterval; /* Guard Interval, 1 divided by value */
+	u32 SystemType; /* ISDB-T system type (ISDB-T / ISDB-Tsb) */
+	u32 PartialReception; /* TRUE - partial reception, FALSE otherwise */
+	u32 NumOfLayers; /* Number of ISDB-T layers in the network */
+
+	/* Per-layer information */
+	/* Layers A, B and C */
+	struct SMSHOSTLIB_ISDBT_LAYER_STAT_ST	LayerInfo[3];
+	/* Per-layer statistics, see SMSHOSTLIB_ISDBT_LAYER_STAT_ST */
+
+	/* Interface information */
+	u32 SmsToHostTxErrors; /* Total number of transmission errors. */
+};
+
+struct PID_STATISTICS_DATA_S {
+	struct PID_BURST_S {
+		u32 size;
+		u32 padding_cols;
+		u32 punct_cols;
+		u32 duration;
+		u32 cycle;
+		u32 calc_cycle;
+	} burst;
+
+	u32 tot_tbl_cnt;
+	u32 invalid_tbl_cnt;
+	u32 tot_cor_tbl;
+};
+
+struct PID_DATA_S {
+	u32 pid;
+	u32 num_rows;
+	struct PID_STATISTICS_DATA_S pid_statistics;
+};
+
+#define CORRECT_STAT_RSSI(_stat) ((_stat).RSSI *= -1)
+#define CORRECT_STAT_BANDWIDTH(_stat) (_stat.Bandwidth = 8 - _stat.Bandwidth)
+#define CORRECT_STAT_TRANSMISSON_MODE(_stat) \
+	if (_stat.TransmissionMode == 0) \
+		_stat.TransmissionMode = 2; \
+	else if (_stat.TransmissionMode == 1) \
+		_stat.TransmissionMode = 8; \
+		else \
+			_stat.TransmissionMode = 4;
+
+struct TRANSMISSION_STATISTICS_S {
+	u32 Frequency;		/* Frequency in Hz */
+	u32 Bandwidth;		/* Bandwidth in MHz */
+	u32 TransmissionMode;	/* FFT mode carriers in Kilos */
+	u32 GuardInterval;	/* Guard Interval from
+	SMSHOSTLIB_GUARD_INTERVALS_ET */
+	u32 CodeRate;		/* Code Rate from SMSHOSTLIB_CODE_RATE_ET */
+	u32 LPCodeRate;		/* Low Priority Code Rate from
+	SMSHOSTLIB_CODE_RATE_ET */
+	u32 Hierarchy;		/* Hierarchy from SMSHOSTLIB_HIERARCHY_ET */
+	u32 Constellation;	/* Constellation from
+	SMSHOSTLIB_CONSTELLATION_ET */
+
+	/* DVB-H TPS parameters */
+	u32 CellId;		/* TPS Cell ID in bits 15..0, bits 31..16 zero;
+	 if set to 0xFFFFFFFF cell_id not yet recovered */
+	u32 DvbhSrvIndHP;	/* DVB-H service indication info, bit 1 -
+	 Time Slicing indicator, bit 0 - MPE-FEC indicator */
+	u32 DvbhSrvIndLP;	/* DVB-H service indication info, bit 1 -
+	 Time Slicing indicator, bit 0 - MPE-FEC indicator */
+	u32 IsDemodLocked;	/* 0 - not locked, 1 - locked */
+};
+
+struct RECEPTION_STATISTICS_S {
+	u32 IsRfLocked;		/* 0 - not locked, 1 - locked */
+	u32 IsDemodLocked;	/* 0 - not locked, 1 - locked */
+	u32 IsExternalLNAOn;	/* 0 - external LNA off, 1 - external LNA on */
+
+	u32 ModemState;		/* from SMSHOSTLIB_DVB_MODEM_STATE_ET */
+	s32 SNR;		/* dB */
+	u32 BER;		/* Post Viterbi BER [1E-5] */
+	u32 BERErrorCount;	/* Number of erronous SYNC bits. */
+	u32 BERBitCount;	/* Total number of SYNC bits. */
+	u32 TS_PER;		/* Transport stream PER,
+	0xFFFFFFFF indicate N/A */
+	u32 MFER;		/* DVB-H frame error rate in percentage,
+	0xFFFFFFFF indicate N/A, valid only for DVB-H */
+	s32 RSSI;		/* dBm */
+	s32 InBandPwr;		/* In band power in dBM */
+	s32 CarrierOffset;	/* Carrier Offset in bin/1024 */
+	u32 ErrorTSPackets;	/* Number of erroneous
+	transport-stream packets */
+	u32 TotalTSPackets;	/* Total number of transport-stream packets */
+
+	s32 MRC_SNR;		/* dB */
+	s32 MRC_RSSI;		/* dBm */
+	s32 MRC_InBandPwr;	/* In band power in dBM */
+};
+
+
+/* Statistics information returned as response for
+ * SmsHostApiGetStatisticsEx_Req for DVB applications, SMS1100 and up */
+struct SMSHOSTLIB_STATISTICS_DVB_S {
+	/* Reception */
+	struct RECEPTION_STATISTICS_S ReceptionData;
+
+	/* Transmission parameters */
+	struct TRANSMISSION_STATISTICS_S TransmissionData;
+
+	/* Burst parameters, valid only for DVB-H */
+#define	SRVM_MAX_PID_FILTERS 8
+	struct PID_DATA_S PidData[SRVM_MAX_PID_FILTERS];
+};
+
+struct SRVM_SIGNAL_STATUS_S {
+	u32 result;
+	u32 snr;
+	u32 tsPackets;
+	u32 etsPackets;
+	u32 constellation;
+	u32 hpCode;
+	u32 tpsSrvIndLP;
+	u32 tpsSrvIndHP;
+	u32 cellId;
+	u32 reason;
+
+	s32 inBandPower;
+	u32 requestId;
+};
+
+struct SMSHOSTLIB_I2C_REQ_ST {
+	u32	DeviceAddress; /* I2c device address */
+	u32	WriteCount; /* number of bytes to write */
+	u32	ReadCount; /* number of bytes to read */
+	u8	Data[1];
+};
+
+struct SMSHOSTLIB_I2C_RES_ST {
+	u32	Status; /* non-zero value in case of failure */
+	u32	ReadCount; /* number of bytes read */
+	u8	Data[1];
+};
+
+
+struct smscore_config_gpio {
+#define SMS_GPIO_DIRECTION_INPUT  0
+#define SMS_GPIO_DIRECTION_OUTPUT 1
+	u8 direction;
+
+#define SMS_GPIO_PULLUPDOWN_NONE     0
+#define SMS_GPIO_PULLUPDOWN_PULLDOWN 1
+#define SMS_GPIO_PULLUPDOWN_PULLUP   2
+#define SMS_GPIO_PULLUPDOWN_KEEPER   3
+	u8 pullupdown;
+
+#define SMS_GPIO_INPUTCHARACTERISTICS_NORMAL  0
+#define SMS_GPIO_INPUTCHARACTERISTICS_SCHMITT 1
+	u8 inputcharacteristics;
+
+#define SMS_GPIO_OUTPUTSLEWRATE_FAST 0
+#define SMS_GPIO_OUTPUTSLEWRATE_SLOW 1
+	u8 outputslewrate;
+
+#define SMS_GPIO_OUTPUTDRIVING_4mA  0
+#define SMS_GPIO_OUTPUTDRIVING_8mA  1
+#define SMS_GPIO_OUTPUTDRIVING_12mA 2
+#define SMS_GPIO_OUTPUTDRIVING_16mA 3
+	u8 outputdriving;
+};
+
+struct smscore_gpio_config {
+#define SMS_GPIO_DIRECTION_INPUT  0
+#define SMS_GPIO_DIRECTION_OUTPUT 1
+	u8 Direction;
+
+#define SMS_GPIO_PULL_UP_DOWN_NONE     0
+#define SMS_GPIO_PULL_UP_DOWN_PULLDOWN 1
+#define SMS_GPIO_PULL_UP_DOWN_PULLUP   2
+#define SMS_GPIO_PULL_UP_DOWN_KEEPER   3
+	u8 PullUpDown;
+
+#define SMS_GPIO_INPUT_CHARACTERISTICS_NORMAL  0
+#define SMS_GPIO_INPUT_CHARACTERISTICS_SCHMITT 1
+	u8 InputCharacteristics;
+
+#define SMS_GPIO_OUTPUT_SLEW_RATE_SLOW		1 /* 10xx */
+#define SMS_GPIO_OUTPUT_SLEW_RATE_FAST		0 /* 10xx */
+
+
+#define SMS_GPIO_OUTPUT_SLEW_RATE_0_45_V_NS	0 /* 11xx */
+#define SMS_GPIO_OUTPUT_SLEW_RATE_0_9_V_NS	1 /* 11xx */
+#define SMS_GPIO_OUTPUT_SLEW_RATE_1_7_V_NS	2 /* 11xx */
+#define SMS_GPIO_OUTPUT_SLEW_RATE_3_3_V_NS	3 /* 11xx */
+	u8 OutputSlewRate;
+
+#define SMS_GPIO_OUTPUT_DRIVING_S_4mA		0 /* 10xx */
+#define SMS_GPIO_OUTPUT_DRIVING_S_8mA		1 /* 10xx */
+#define SMS_GPIO_OUTPUT_DRIVING_S_12mA		2 /* 10xx */
+#define SMS_GPIO_OUTPUT_DRIVING_S_16mA		3 /* 10xx */
+
+#define SMS_GPIO_OUTPUT_DRIVING_1_5mA		0 /* 11xx */
+#define SMS_GPIO_OUTPUT_DRIVING_2_8mA		1 /* 11xx */
+#define SMS_GPIO_OUTPUT_DRIVING_4mA		2 /* 11xx */
+#define SMS_GPIO_OUTPUT_DRIVING_7mA		3 /* 11xx */
+#define SMS_GPIO_OUTPUT_DRIVING_10mA		4 /* 11xx */
+#define SMS_GPIO_OUTPUT_DRIVING_11mA		5 /* 11xx */
+#define SMS_GPIO_OUTPUT_DRIVING_14mA		6 /* 11xx */
+#define SMS_GPIO_OUTPUT_DRIVING_16mA		7 /* 11xx */
+	u8 OutputDriving;
+};
+
+extern void smscore_registry_setmode(char *devpath, int mode);
+extern int smscore_registry_getmode(char *devpath);
+
+extern int smscore_register_hotplug(hotplug_t hotplug);
+extern void smscore_unregister_hotplug(hotplug_t hotplug);
+
+extern int smscore_register_device(struct smsdevice_params_t *params,
+				   struct smscore_device_t **coredev);
+extern void smscore_unregister_device(struct smscore_device_t *coredev);
+
+extern int smscore_start_device(struct smscore_device_t *coredev);
+extern int smscore_load_firmware(struct smscore_device_t *coredev,
+				 char *filename,
+				 loadfirmware_t loadfirmware_handler);
+
+extern int smscore_set_device_mode(struct smscore_device_t *coredev, int mode);
+extern int smscore_get_device_mode(struct smscore_device_t *coredev);
+
+extern int smscore_register_client(struct smscore_device_t *coredev,
+				    struct smsclient_params_t *params,
+				    struct smscore_client_t **client);
+extern void smscore_unregister_client(struct smscore_client_t *client);
+
+extern int smsclient_sendrequest(struct smscore_client_t *client,
+				 void *buffer, size_t size);
+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);
+extern void smscore_putbuffer(struct smscore_device_t *coredev,
+			      struct smscore_buffer_t *cb);
+
+/* old GPIO management */
+int smscore_configure_gpio(struct smscore_device_t *coredev, u32 pin,
+			   struct smscore_config_gpio *pinconfig);
+int smscore_set_gpio(struct smscore_device_t *coredev, u32 pin, int level);
+
+/* new GPIO management */
+extern int smscore_gpio_configure(struct smscore_device_t *coredev, u8 PinNum,
+		struct smscore_gpio_config *pGpioConfig);
+extern int smscore_gpio_set_level(struct smscore_device_t *coredev, u8 PinNum,
+		u8 NewLevel);
+extern int smscore_gpio_get_level(struct smscore_device_t *coredev, u8 PinNum,
+		u8 *level);
+
+void smscore_set_board_id(struct smscore_device_t *core, int id);
+int smscore_get_board_id(struct smscore_device_t *core);
+
+int smscore_led_state(struct smscore_device_t *core, int led);
+
+
+/* ------------------------------------------------------------------------ */
+
+#define DBG_INFO 1
+#define DBG_ADV  2
+
+#define sms_printk(kern, fmt, arg...) \
+	printk(kern "%s: " fmt "\n", __func__, ##arg)
+
+#define dprintk(kern, lvl, fmt, arg...) do {\
+	if (sms_dbg & lvl) \
+		sms_printk(kern, fmt, ##arg); } while (0)
+
+#define sms_log(fmt, arg...) sms_printk(KERN_INFO, fmt, ##arg)
+#define sms_err(fmt, arg...) \
+	sms_printk(KERN_ERR, "line: %d: " fmt, __LINE__, ##arg)
+#define sms_warn(fmt, arg...)  sms_printk(KERN_WARNING, fmt, ##arg)
+#define sms_info(fmt, arg...) \
+	dprintk(KERN_INFO, DBG_INFO, fmt, ##arg)
+#define sms_debug(fmt, arg...) \
+	dprintk(KERN_DEBUG, DBG_ADV, fmt, ##arg)
+
+
+#endif /* __SMS_CORE_API_H__ */
diff --git a/drivers/media/common/siano/smsdvb.c b/drivers/media/common/siano/smsdvb.c
new file mode 100644
index 0000000..aa77e54
--- /dev/null
+++ b/drivers/media/common/siano/smsdvb.c
@@ -0,0 +1,1078 @@
+/****************************************************************
+
+Siano Mobile Silicon, Inc.
+MDTV receiver kernel modules.
+Copyright (C) 2006-2008, Uri Shkolnik
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+****************************************************************/
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+
+#include "dmxdev.h"
+#include "dvbdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+
+#include "smscoreapi.h"
+#include "smsendian.h"
+#include "sms-cards.h"
+
+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;
+
+	struct completion       tune_done;
+
+	struct SMSHOSTLIB_STATISTICS_DVB_S sms_stat_dvb;
+	int event_fe_state;
+	int event_unc_state;
+};
+
+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))");
+
+/* Events that may come from DVB v3 adapter */
+static void sms_board_dvb3_event(struct smsdvb_client_t *client,
+		enum SMS_DVB3_EVENTS event) {
+
+	struct smscore_device_t *coredev = client->coredev;
+	switch (event) {
+	case DVB3_EVENT_INIT:
+		sms_debug("DVB3_EVENT_INIT");
+		sms_board_event(coredev, BOARD_EVENT_BIND);
+		break;
+	case DVB3_EVENT_SLEEP:
+		sms_debug("DVB3_EVENT_SLEEP");
+		sms_board_event(coredev, BOARD_EVENT_POWER_SUSPEND);
+		break;
+	case DVB3_EVENT_HOTPLUG:
+		sms_debug("DVB3_EVENT_HOTPLUG");
+		sms_board_event(coredev, BOARD_EVENT_POWER_INIT);
+		break;
+	case DVB3_EVENT_FE_LOCK:
+		if (client->event_fe_state != DVB3_EVENT_FE_LOCK) {
+			client->event_fe_state = DVB3_EVENT_FE_LOCK;
+			sms_debug("DVB3_EVENT_FE_LOCK");
+			sms_board_event(coredev, BOARD_EVENT_FE_LOCK);
+		}
+		break;
+	case DVB3_EVENT_FE_UNLOCK:
+		if (client->event_fe_state != DVB3_EVENT_FE_UNLOCK) {
+			client->event_fe_state = DVB3_EVENT_FE_UNLOCK;
+			sms_debug("DVB3_EVENT_FE_UNLOCK");
+			sms_board_event(coredev, BOARD_EVENT_FE_UNLOCK);
+		}
+		break;
+	case DVB3_EVENT_UNC_OK:
+		if (client->event_unc_state != DVB3_EVENT_UNC_OK) {
+			client->event_unc_state = DVB3_EVENT_UNC_OK;
+			sms_debug("DVB3_EVENT_UNC_OK");
+			sms_board_event(coredev, BOARD_EVENT_MULTIPLEX_OK);
+		}
+		break;
+	case DVB3_EVENT_UNC_ERR:
+		if (client->event_unc_state != DVB3_EVENT_UNC_ERR) {
+			client->event_unc_state = DVB3_EVENT_UNC_ERR;
+			sms_debug("DVB3_EVENT_UNC_ERR");
+			sms_board_event(coredev, BOARD_EVENT_MULTIPLEX_ERRORS);
+		}
+		break;
+
+	default:
+		sms_err("Unknown dvb3 api event");
+		break;
+	}
+}
+
+
+static void smsdvb_update_dvb_stats(struct RECEPTION_STATISTICS_S *pReceptionData,
+				   struct SMSHOSTLIB_STATISTICS_ST *p)
+{
+	if (sms_dbg & 2) {
+		printk(KERN_DEBUG "Reserved = %d", p->Reserved);
+		printk(KERN_DEBUG "IsRfLocked = %d", p->IsRfLocked);
+		printk(KERN_DEBUG "IsDemodLocked = %d", p->IsDemodLocked);
+		printk(KERN_DEBUG "IsExternalLNAOn = %d", p->IsExternalLNAOn);
+		printk(KERN_DEBUG "SNR = %d", p->SNR);
+		printk(KERN_DEBUG "BER = %d", p->BER);
+		printk(KERN_DEBUG "FIB_CRC = %d", p->FIB_CRC);
+		printk(KERN_DEBUG "TS_PER = %d", p->TS_PER);
+		printk(KERN_DEBUG "MFER = %d", p->MFER);
+		printk(KERN_DEBUG "RSSI = %d", p->RSSI);
+		printk(KERN_DEBUG "InBandPwr = %d", p->InBandPwr);
+		printk(KERN_DEBUG "CarrierOffset = %d", p->CarrierOffset);
+		printk(KERN_DEBUG "Frequency = %d", p->Frequency);
+		printk(KERN_DEBUG "Bandwidth = %d", p->Bandwidth);
+		printk(KERN_DEBUG "TransmissionMode = %d", p->TransmissionMode);
+		printk(KERN_DEBUG "ModemState = %d", p->ModemState);
+		printk(KERN_DEBUG "GuardInterval = %d", p->GuardInterval);
+		printk(KERN_DEBUG "CodeRate = %d", p->CodeRate);
+		printk(KERN_DEBUG "LPCodeRate = %d", p->LPCodeRate);
+		printk(KERN_DEBUG "Hierarchy = %d", p->Hierarchy);
+		printk(KERN_DEBUG "Constellation = %d", p->Constellation);
+		printk(KERN_DEBUG "BurstSize = %d", p->BurstSize);
+		printk(KERN_DEBUG "BurstDuration = %d", p->BurstDuration);
+		printk(KERN_DEBUG "BurstCycleTime = %d", p->BurstCycleTime);
+		printk(KERN_DEBUG "CalculatedBurstCycleTime = %d", p->CalculatedBurstCycleTime);
+		printk(KERN_DEBUG "NumOfRows = %d", p->NumOfRows);
+		printk(KERN_DEBUG "NumOfPaddCols = %d", p->NumOfPaddCols);
+		printk(KERN_DEBUG "NumOfPunctCols = %d", p->NumOfPunctCols);
+		printk(KERN_DEBUG "ErrorTSPackets = %d", p->ErrorTSPackets);
+		printk(KERN_DEBUG "TotalTSPackets = %d", p->TotalTSPackets);
+		printk(KERN_DEBUG "NumOfValidMpeTlbs = %d", p->NumOfValidMpeTlbs);
+		printk(KERN_DEBUG "NumOfInvalidMpeTlbs = %d", p->NumOfInvalidMpeTlbs);
+		printk(KERN_DEBUG "NumOfCorrectedMpeTlbs = %d", p->NumOfCorrectedMpeTlbs);
+		printk(KERN_DEBUG "BERErrorCount = %d", p->BERErrorCount);
+		printk(KERN_DEBUG "BERBitCount = %d", p->BERBitCount);
+		printk(KERN_DEBUG "SmsToHostTxErrors = %d", p->SmsToHostTxErrors);
+		printk(KERN_DEBUG "PreBER = %d", p->PreBER);
+		printk(KERN_DEBUG "CellId = %d", p->CellId);
+		printk(KERN_DEBUG "DvbhSrvIndHP = %d", p->DvbhSrvIndHP);
+		printk(KERN_DEBUG "DvbhSrvIndLP = %d", p->DvbhSrvIndLP);
+		printk(KERN_DEBUG "NumMPEReceived = %d", p->NumMPEReceived);
+	}
+
+	pReceptionData->IsDemodLocked = p->IsDemodLocked;
+
+	pReceptionData->SNR = p->SNR;
+	pReceptionData->BER = p->BER;
+	pReceptionData->BERErrorCount = p->BERErrorCount;
+	pReceptionData->InBandPwr = p->InBandPwr;
+	pReceptionData->ErrorTSPackets = p->ErrorTSPackets;
+};
+
+
+static void smsdvb_update_isdbt_stats(struct RECEPTION_STATISTICS_S *pReceptionData,
+				    struct SMSHOSTLIB_STATISTICS_ISDBT_ST *p)
+{
+	int i;
+
+	if (sms_dbg & 2) {
+		printk(KERN_DEBUG "IsRfLocked = %d", p->IsRfLocked);
+		printk(KERN_DEBUG "IsDemodLocked = %d", p->IsDemodLocked);
+		printk(KERN_DEBUG "IsExternalLNAOn = %d", p->IsExternalLNAOn);
+		printk(KERN_DEBUG "SNR = %d", p->SNR);
+		printk(KERN_DEBUG "RSSI = %d", p->RSSI);
+		printk(KERN_DEBUG "InBandPwr = %d", p->InBandPwr);
+		printk(KERN_DEBUG "CarrierOffset = %d", p->CarrierOffset);
+		printk(KERN_DEBUG "Frequency = %d", p->Frequency);
+		printk(KERN_DEBUG "Bandwidth = %d", p->Bandwidth);
+		printk(KERN_DEBUG "TransmissionMode = %d", p->TransmissionMode);
+		printk(KERN_DEBUG "ModemState = %d", p->ModemState);
+		printk(KERN_DEBUG "GuardInterval = %d", p->GuardInterval);
+		printk(KERN_DEBUG "SystemType = %d", p->SystemType);
+		printk(KERN_DEBUG "PartialReception = %d", p->PartialReception);
+		printk(KERN_DEBUG "NumOfLayers = %d", p->NumOfLayers);
+		printk(KERN_DEBUG "SmsToHostTxErrors = %d", p->SmsToHostTxErrors);
+
+		for (i = 0; i < 3; i++) {
+			printk(KERN_DEBUG "%d: CodeRate = %d", i, p->LayerInfo[i].CodeRate);
+			printk(KERN_DEBUG "%d: Constellation = %d", i, p->LayerInfo[i].Constellation);
+			printk(KERN_DEBUG "%d: BER = %d", i, p->LayerInfo[i].BER);
+			printk(KERN_DEBUG "%d: BERErrorCount = %d", i, p->LayerInfo[i].BERErrorCount);
+			printk(KERN_DEBUG "%d: BERBitCount = %d", i, p->LayerInfo[i].BERBitCount);
+			printk(KERN_DEBUG "%d: PreBER = %d", i, p->LayerInfo[i].PreBER);
+			printk(KERN_DEBUG "%d: TS_PER = %d", i, p->LayerInfo[i].TS_PER);
+			printk(KERN_DEBUG "%d: ErrorTSPackets = %d", i, p->LayerInfo[i].ErrorTSPackets);
+			printk(KERN_DEBUG "%d: TotalTSPackets = %d", i, p->LayerInfo[i].TotalTSPackets);
+			printk(KERN_DEBUG "%d: TILdepthI = %d", i, p->LayerInfo[i].TILdepthI);
+			printk(KERN_DEBUG "%d: NumberOfSegments = %d", i, p->LayerInfo[i].NumberOfSegments);
+			printk(KERN_DEBUG "%d: TMCCErrors = %d", i, p->LayerInfo[i].TMCCErrors);
+		}
+	}
+
+	pReceptionData->IsDemodLocked = p->IsDemodLocked;
+
+	pReceptionData->SNR = p->SNR;
+	pReceptionData->InBandPwr = p->InBandPwr;
+
+	pReceptionData->ErrorTSPackets = 0;
+	pReceptionData->BER = 0;
+	pReceptionData->BERErrorCount = 0;
+	for (i = 0; i < 3; i++) {
+		pReceptionData->BER += p->LayerInfo[i].BER;
+		pReceptionData->BERErrorCount += p->LayerInfo[i].BERErrorCount;
+		pReceptionData->ErrorTSPackets += p->LayerInfo[i].ErrorTSPackets;
+	}
+}
+
+static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb)
+{
+	struct smsdvb_client_t *client = (struct smsdvb_client_t *) context;
+	struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *) (((u8 *) cb->p)
+			+ cb->offset);
+	u32 *pMsgData = (u32 *) phdr + 1;
+	/*u32 MsgDataLen = phdr->msgLength - sizeof(struct SmsMsgHdr_ST);*/
+	bool is_status_update = false;
+
+	smsendian_handle_rx_message((struct SmsMsgData_ST *) phdr);
+
+	switch (phdr->msgType) {
+	case MSG_SMS_DVBT_BDA_DATA:
+		dvb_dmx_swfilter(&client->demux, (u8 *)(phdr + 1),
+				 cb->size - sizeof(struct SmsMsgHdr_ST));
+		break;
+
+	case MSG_SMS_RF_TUNE_RES:
+	case MSG_SMS_ISDBT_TUNE_RES:
+		complete(&client->tune_done);
+		break;
+
+	case MSG_SMS_SIGNAL_DETECTED_IND:
+		sms_info("MSG_SMS_SIGNAL_DETECTED_IND");
+		client->sms_stat_dvb.TransmissionData.IsDemodLocked = true;
+		is_status_update = true;
+		break;
+
+	case MSG_SMS_NO_SIGNAL_IND:
+		sms_info("MSG_SMS_NO_SIGNAL_IND");
+		client->sms_stat_dvb.TransmissionData.IsDemodLocked = false;
+		is_status_update = true;
+		break;
+
+	case MSG_SMS_TRANSMISSION_IND: {
+		sms_info("MSG_SMS_TRANSMISSION_IND");
+
+		pMsgData++;
+		memcpy(&client->sms_stat_dvb.TransmissionData, pMsgData,
+				sizeof(struct TRANSMISSION_STATISTICS_S));
+
+		/* Mo need to correct guard interval
+		 * (as opposed to old statistics message).
+		 */
+		CORRECT_STAT_BANDWIDTH(client->sms_stat_dvb.TransmissionData);
+		CORRECT_STAT_TRANSMISSON_MODE(
+				client->sms_stat_dvb.TransmissionData);
+		is_status_update = true;
+		break;
+	}
+	case MSG_SMS_HO_PER_SLICES_IND: {
+		struct RECEPTION_STATISTICS_S *pReceptionData =
+				&client->sms_stat_dvb.ReceptionData;
+		struct SRVM_SIGNAL_STATUS_S SignalStatusData;
+
+		/*sms_info("MSG_SMS_HO_PER_SLICES_IND");*/
+		pMsgData++;
+		SignalStatusData.result = pMsgData[0];
+		SignalStatusData.snr = pMsgData[1];
+		SignalStatusData.inBandPower = (s32) pMsgData[2];
+		SignalStatusData.tsPackets = pMsgData[3];
+		SignalStatusData.etsPackets = pMsgData[4];
+		SignalStatusData.constellation = pMsgData[5];
+		SignalStatusData.hpCode = pMsgData[6];
+		SignalStatusData.tpsSrvIndLP = pMsgData[7] & 0x03;
+		SignalStatusData.tpsSrvIndHP = pMsgData[8] & 0x03;
+		SignalStatusData.cellId = pMsgData[9] & 0xFFFF;
+		SignalStatusData.reason = pMsgData[10];
+		SignalStatusData.requestId = pMsgData[11];
+		pReceptionData->IsRfLocked = pMsgData[16];
+		pReceptionData->IsDemodLocked = pMsgData[17];
+		pReceptionData->ModemState = pMsgData[12];
+		pReceptionData->SNR = pMsgData[1];
+		pReceptionData->BER = pMsgData[13];
+		pReceptionData->RSSI = pMsgData[14];
+		CORRECT_STAT_RSSI(client->sms_stat_dvb.ReceptionData);
+
+		pReceptionData->InBandPwr = (s32) pMsgData[2];
+		pReceptionData->CarrierOffset = (s32) pMsgData[15];
+		pReceptionData->TotalTSPackets = pMsgData[3];
+		pReceptionData->ErrorTSPackets = pMsgData[4];
+
+		/* TS PER */
+		if ((SignalStatusData.tsPackets + SignalStatusData.etsPackets)
+				> 0) {
+			pReceptionData->TS_PER = (SignalStatusData.etsPackets
+					* 100) / (SignalStatusData.tsPackets
+					+ SignalStatusData.etsPackets);
+		} else {
+			pReceptionData->TS_PER = 0;
+		}
+
+		pReceptionData->BERBitCount = pMsgData[18];
+		pReceptionData->BERErrorCount = pMsgData[19];
+
+		pReceptionData->MRC_SNR = pMsgData[20];
+		pReceptionData->MRC_InBandPwr = pMsgData[21];
+		pReceptionData->MRC_RSSI = pMsgData[22];
+
+		is_status_update = true;
+		break;
+	}
+	case MSG_SMS_GET_STATISTICS_RES: {
+		union {
+			struct SMSHOSTLIB_STATISTICS_ISDBT_ST  isdbt;
+			struct SmsMsgStatisticsInfo_ST         dvb;
+		} *p = (void *) (phdr + 1);
+		struct RECEPTION_STATISTICS_S *pReceptionData =
+				&client->sms_stat_dvb.ReceptionData;
+
+		sms_info("MSG_SMS_GET_STATISTICS_RES");
+
+		is_status_update = true;
+
+		switch (smscore_get_device_mode(client->coredev)) {
+		case DEVICE_MODE_ISDBT:
+		case DEVICE_MODE_ISDBT_BDA:
+			smsdvb_update_isdbt_stats(pReceptionData, &p->isdbt);
+			break;
+		default:
+			smsdvb_update_dvb_stats(pReceptionData, &p->dvb.Stat);
+		}
+		if (!pReceptionData->IsDemodLocked) {
+			pReceptionData->SNR = 0;
+			pReceptionData->BER = 0;
+			pReceptionData->BERErrorCount = 0;
+			pReceptionData->InBandPwr = 0;
+			pReceptionData->ErrorTSPackets = 0;
+		}
+
+		complete(&client->tune_done);
+		break;
+	}
+	default:
+		sms_info("Unhandled message %d", phdr->msgType);
+
+	}
+	smscore_putbuffer(client->coredev, cb);
+
+	if (is_status_update) {
+		if (client->sms_stat_dvb.ReceptionData.IsDemodLocked) {
+			client->fe_status = FE_HAS_SIGNAL | FE_HAS_CARRIER
+				| FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
+			sms_board_dvb3_event(client, DVB3_EVENT_FE_LOCK);
+			if (client->sms_stat_dvb.ReceptionData.ErrorTSPackets
+					== 0)
+				sms_board_dvb3_event(client, DVB3_EVENT_UNC_OK);
+			else
+				sms_board_dvb3_event(client,
+						DVB3_EVENT_UNC_ERR);
+
+		} else {
+			if (client->sms_stat_dvb.ReceptionData.IsRfLocked)
+				client->fe_status = FE_HAS_SIGNAL | FE_HAS_CARRIER;
+			else
+				client->fe_status = 0;
+			sms_board_dvb3_event(client, DVB3_EVENT_FE_UNLOCK);
+		}
+	}
+
+	return 0;
+}
+
+static void smsdvb_unregister_client(struct smsdvb_client_t *client)
+{
+	/* must be called under clientslock */
+
+	list_del(&client->entry);
+
+	smscore_unregister_client(client->smsclient);
+	dvb_unregister_frontend(&client->frontend);
+	dvb_dmxdev_release(&client->dmxdev);
+	dvb_dmx_release(&client->demux);
+	dvb_unregister_adapter(&client->adapter);
+	kfree(client);
+}
+
+static void smsdvb_onremove(void *context)
+{
+	kmutex_lock(&g_smsdvb_clientslock);
+
+	smsdvb_unregister_client((struct smsdvb_client_t *) context);
+
+	kmutex_unlock(&g_smsdvb_clientslock);
+}
+
+static int smsdvb_start_feed(struct dvb_demux_feed *feed)
+{
+	struct smsdvb_client_t *client =
+		container_of(feed->demux, struct smsdvb_client_t, demux);
+	struct SmsMsgData_ST PidMsg;
+
+	sms_debug("add pid %d(%x)",
+		  feed->pid, feed->pid);
+
+	PidMsg.xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
+	PidMsg.xMsgHeader.msgDstId = HIF_TASK;
+	PidMsg.xMsgHeader.msgFlags = 0;
+	PidMsg.xMsgHeader.msgType  = MSG_SMS_ADD_PID_FILTER_REQ;
+	PidMsg.xMsgHeader.msgLength = sizeof(PidMsg);
+	PidMsg.msgData[0] = feed->pid;
+
+	smsendian_handle_tx_message((struct SmsMsgHdr_ST *)&PidMsg);
+	return smsclient_sendrequest(client->smsclient,
+				     &PidMsg, sizeof(PidMsg));
+}
+
+static int smsdvb_stop_feed(struct dvb_demux_feed *feed)
+{
+	struct smsdvb_client_t *client =
+		container_of(feed->demux, struct smsdvb_client_t, demux);
+	struct SmsMsgData_ST PidMsg;
+
+	sms_debug("remove pid %d(%x)",
+		  feed->pid, feed->pid);
+
+	PidMsg.xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
+	PidMsg.xMsgHeader.msgDstId = HIF_TASK;
+	PidMsg.xMsgHeader.msgFlags = 0;
+	PidMsg.xMsgHeader.msgType  = MSG_SMS_REMOVE_PID_FILTER_REQ;
+	PidMsg.xMsgHeader.msgLength = sizeof(PidMsg);
+	PidMsg.msgData[0] = feed->pid;
+
+	smsendian_handle_tx_message((struct SmsMsgHdr_ST *)&PidMsg);
+	return smsclient_sendrequest(client->smsclient,
+				     &PidMsg, sizeof(PidMsg));
+}
+
+static int smsdvb_sendrequest_and_wait(struct smsdvb_client_t *client,
+					void *buffer, size_t size,
+					struct completion *completion)
+{
+	int rc;
+
+	smsendian_handle_tx_message((struct SmsMsgHdr_ST *)buffer);
+	rc = smsclient_sendrequest(client->smsclient, buffer, size);
+	if (rc < 0)
+		return rc;
+
+	return wait_for_completion_timeout(completion,
+					   msecs_to_jiffies(2000)) ?
+						0 : -ETIME;
+}
+
+static int smsdvb_send_statistics_request(struct smsdvb_client_t *client)
+{
+	int rc;
+	struct SmsMsgHdr_ST Msg = { MSG_SMS_GET_STATISTICS_REQ,
+				    DVBT_BDA_CONTROL_MSG_ID,
+				    HIF_TASK,
+				    sizeof(struct SmsMsgHdr_ST), 0 };
+
+	rc = smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg),
+					  &client->tune_done);
+
+	return rc;
+}
+
+static inline int led_feedback(struct smsdvb_client_t *client)
+{
+	if (client->fe_status & FE_HAS_LOCK)
+		return sms_board_led_feedback(client->coredev,
+			(client->sms_stat_dvb.ReceptionData.BER
+			== 0) ? SMS_LED_HI : SMS_LED_LO);
+	else
+		return sms_board_led_feedback(client->coredev, SMS_LED_OFF);
+}
+
+static int smsdvb_read_status(struct dvb_frontend *fe, fe_status_t *stat)
+{
+	int rc;
+	struct smsdvb_client_t *client;
+	client = container_of(fe, struct smsdvb_client_t, frontend);
+
+	rc = smsdvb_send_statistics_request(client);
+
+	*stat = client->fe_status;
+
+	led_feedback(client);
+
+	return rc;
+}
+
+static int smsdvb_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+	int rc;
+	struct smsdvb_client_t *client;
+	client = container_of(fe, struct smsdvb_client_t, frontend);
+
+	rc = smsdvb_send_statistics_request(client);
+
+	*ber = client->sms_stat_dvb.ReceptionData.BER;
+
+	led_feedback(client);
+
+	return rc;
+}
+
+static int smsdvb_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
+{
+	int rc;
+
+	struct smsdvb_client_t *client;
+	client = container_of(fe, struct smsdvb_client_t, frontend);
+
+	rc = smsdvb_send_statistics_request(client);
+
+	if (client->sms_stat_dvb.ReceptionData.InBandPwr < -95)
+		*strength = 0;
+		else if (client->sms_stat_dvb.ReceptionData.InBandPwr > -29)
+			*strength = 100;
+		else
+			*strength =
+				(client->sms_stat_dvb.ReceptionData.InBandPwr
+				+ 95) * 3 / 2;
+
+	led_feedback(client);
+
+	return rc;
+}
+
+static int smsdvb_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+	int rc;
+	struct smsdvb_client_t *client;
+	client = container_of(fe, struct smsdvb_client_t, frontend);
+
+	rc = smsdvb_send_statistics_request(client);
+
+	*snr = client->sms_stat_dvb.ReceptionData.SNR;
+
+	led_feedback(client);
+
+	return rc;
+}
+
+static int smsdvb_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+	int rc;
+	struct smsdvb_client_t *client;
+	client = container_of(fe, struct smsdvb_client_t, frontend);
+
+	rc = smsdvb_send_statistics_request(client);
+
+	*ucblocks = client->sms_stat_dvb.ReceptionData.ErrorTSPackets;
+
+	led_feedback(client);
+
+	return rc;
+}
+
+static int smsdvb_get_tune_settings(struct dvb_frontend *fe,
+				    struct dvb_frontend_tune_settings *tune)
+{
+	sms_debug("");
+
+	tune->min_delay_ms = 400;
+	tune->step_size = 250000;
+	tune->max_drift = 0;
+	return 0;
+}
+
+static int smsdvb_dvbt_set_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	struct smsdvb_client_t *client =
+		container_of(fe, struct smsdvb_client_t, frontend);
+
+	struct {
+		struct SmsMsgHdr_ST	Msg;
+		u32		Data[3];
+	} Msg;
+
+	int ret;
+
+	client->fe_status = FE_HAS_SIGNAL;
+	client->event_fe_state = -1;
+	client->event_unc_state = -1;
+	fe->dtv_property_cache.delivery_system = SYS_DVBT;
+
+	Msg.Msg.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
+	Msg.Msg.msgDstId = HIF_TASK;
+	Msg.Msg.msgFlags = 0;
+	Msg.Msg.msgType = MSG_SMS_RF_TUNE_REQ;
+	Msg.Msg.msgLength = sizeof(Msg);
+	Msg.Data[0] = c->frequency;
+	Msg.Data[2] = 12000000;
+
+	sms_info("%s: freq %d band %d", __func__, c->frequency,
+		 c->bandwidth_hz);
+
+	switch (c->bandwidth_hz / 1000000) {
+	case 8:
+		Msg.Data[1] = BW_8_MHZ;
+		break;
+	case 7:
+		Msg.Data[1] = BW_7_MHZ;
+		break;
+	case 6:
+		Msg.Data[1] = BW_6_MHZ;
+		break;
+	case 0:
+		return -EOPNOTSUPP;
+	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 didn't 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);
+}
+
+static int smsdvb_isdbt_set_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	struct smsdvb_client_t *client =
+		container_of(fe, struct smsdvb_client_t, frontend);
+
+	struct {
+		struct SmsMsgHdr_ST	Msg;
+		u32		Data[4];
+	} Msg;
+
+	fe->dtv_property_cache.delivery_system = SYS_ISDBT;
+
+	Msg.Msg.msgSrcId  = DVBT_BDA_CONTROL_MSG_ID;
+	Msg.Msg.msgDstId  = HIF_TASK;
+	Msg.Msg.msgFlags  = 0;
+	Msg.Msg.msgType   = MSG_SMS_ISDBT_TUNE_REQ;
+	Msg.Msg.msgLength = sizeof(Msg);
+
+	if (c->isdbt_sb_segment_idx == -1)
+		c->isdbt_sb_segment_idx = 0;
+
+	switch (c->isdbt_sb_segment_count) {
+	case 3:
+		Msg.Data[1] = BW_ISDBT_3SEG;
+		break;
+	case 1:
+		Msg.Data[1] = BW_ISDBT_1SEG;
+		break;
+	case 0:	/* AUTO */
+		switch (c->bandwidth_hz / 1000000) {
+		case 8:
+		case 7:
+			c->isdbt_sb_segment_count = 3;
+			Msg.Data[1] = BW_ISDBT_3SEG;
+			break;
+		case 6:
+			c->isdbt_sb_segment_count = 1;
+			Msg.Data[1] = BW_ISDBT_1SEG;
+			break;
+		default: /* Assumes 6 MHZ bw */
+			c->isdbt_sb_segment_count = 1;
+			c->bandwidth_hz = 6000;
+			Msg.Data[1] = BW_ISDBT_1SEG;
+			break;
+		}
+		break;
+	default:
+		sms_info("Segment count %d not supported", c->isdbt_sb_segment_count);
+		return -EINVAL;
+	}
+
+	Msg.Data[0] = c->frequency;
+	Msg.Data[2] = 12000000;
+	Msg.Data[3] = c->isdbt_sb_segment_idx;
+
+	sms_info("%s: freq %d segwidth %d segindex %d\n", __func__,
+		 c->frequency, c->isdbt_sb_segment_count,
+		 c->isdbt_sb_segment_idx);
+
+	return smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg),
+					   &client->tune_done);
+}
+
+static int smsdvb_set_frontend(struct dvb_frontend *fe)
+{
+	struct smsdvb_client_t *client =
+		container_of(fe, struct smsdvb_client_t, frontend);
+	struct smscore_device_t *coredev = client->coredev;
+
+	switch (smscore_get_device_mode(coredev)) {
+	case DEVICE_MODE_DVBT:
+	case DEVICE_MODE_DVBT_BDA:
+		return smsdvb_dvbt_set_frontend(fe);
+	case DEVICE_MODE_ISDBT:
+	case DEVICE_MODE_ISDBT_BDA:
+		return smsdvb_isdbt_set_frontend(fe);
+	default:
+		return -EINVAL;
+	}
+}
+
+static int smsdvb_get_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
+	struct smsdvb_client_t *client =
+		container_of(fe, struct smsdvb_client_t, frontend);
+	struct smscore_device_t *coredev = client->coredev;
+	struct TRANSMISSION_STATISTICS_S *td =
+		&client->sms_stat_dvb.TransmissionData;
+
+	switch (smscore_get_device_mode(coredev)) {
+	case DEVICE_MODE_DVBT:
+	case DEVICE_MODE_DVBT_BDA:
+		fep->frequency = td->Frequency;
+
+		switch (td->Bandwidth) {
+		case 6:
+			fep->bandwidth_hz = 6000000;
+			break;
+		case 7:
+			fep->bandwidth_hz = 7000000;
+			break;
+		case 8:
+			fep->bandwidth_hz = 8000000;
+			break;
+		}
+
+		switch (td->TransmissionMode) {
+		case 2:
+			fep->transmission_mode = TRANSMISSION_MODE_2K;
+			break;
+		case 8:
+			fep->transmission_mode = TRANSMISSION_MODE_8K;
+		}
+
+		switch (td->GuardInterval) {
+		case 0:
+			fep->guard_interval = GUARD_INTERVAL_1_32;
+			break;
+		case 1:
+			fep->guard_interval = GUARD_INTERVAL_1_16;
+			break;
+		case 2:
+			fep->guard_interval = GUARD_INTERVAL_1_8;
+			break;
+		case 3:
+			fep->guard_interval = GUARD_INTERVAL_1_4;
+			break;
+		}
+
+		switch (td->CodeRate) {
+		case 0:
+			fep->code_rate_HP = FEC_1_2;
+			break;
+		case 1:
+			fep->code_rate_HP = FEC_2_3;
+			break;
+		case 2:
+			fep->code_rate_HP = FEC_3_4;
+			break;
+		case 3:
+			fep->code_rate_HP = FEC_5_6;
+			break;
+		case 4:
+			fep->code_rate_HP = FEC_7_8;
+			break;
+		}
+
+		switch (td->LPCodeRate) {
+		case 0:
+			fep->code_rate_LP = FEC_1_2;
+			break;
+		case 1:
+			fep->code_rate_LP = FEC_2_3;
+			break;
+		case 2:
+			fep->code_rate_LP = FEC_3_4;
+			break;
+		case 3:
+			fep->code_rate_LP = FEC_5_6;
+			break;
+		case 4:
+			fep->code_rate_LP = FEC_7_8;
+			break;
+		}
+
+		switch (td->Constellation) {
+		case 0:
+			fep->modulation = QPSK;
+			break;
+		case 1:
+			fep->modulation = QAM_16;
+			break;
+		case 2:
+			fep->modulation = QAM_64;
+			break;
+		}
+
+		switch (td->Hierarchy) {
+		case 0:
+			fep->hierarchy = HIERARCHY_NONE;
+			break;
+		case 1:
+			fep->hierarchy = HIERARCHY_1;
+			break;
+		case 2:
+			fep->hierarchy = HIERARCHY_2;
+			break;
+		case 3:
+			fep->hierarchy = HIERARCHY_4;
+			break;
+		}
+
+		fep->inversion = INVERSION_AUTO;
+		break;
+	case DEVICE_MODE_ISDBT:
+	case DEVICE_MODE_ISDBT_BDA:
+		fep->frequency = td->Frequency;
+		fep->bandwidth_hz = 6000000;
+		/* todo: retrive the other parameters */
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int smsdvb_init(struct dvb_frontend *fe)
+{
+	struct smsdvb_client_t *client =
+		container_of(fe, struct smsdvb_client_t, frontend);
+
+	sms_board_power(client->coredev, 1);
+
+	sms_board_dvb3_event(client, DVB3_EVENT_INIT);
+	return 0;
+}
+
+static int smsdvb_sleep(struct dvb_frontend *fe)
+{
+	struct smsdvb_client_t *client =
+		container_of(fe, struct smsdvb_client_t, frontend);
+
+	sms_board_led_feedback(client->coredev, SMS_LED_OFF);
+	sms_board_power(client->coredev, 0);
+
+	sms_board_dvb3_event(client, DVB3_EVENT_SLEEP);
+
+	return 0;
+}
+
+static void smsdvb_release(struct dvb_frontend *fe)
+{
+	/* do nothing */
+}
+
+static struct dvb_frontend_ops smsdvb_fe_ops = {
+	.info = {
+		.name			= "Siano Mobile Digital MDTV Receiver",
+		.frequency_min		= 44250000,
+		.frequency_max		= 867250000,
+		.frequency_stepsize	= 250000,
+		.caps = FE_CAN_INVERSION_AUTO |
+			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_FEC_AUTO |
+			FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 |
+			FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO |
+			FE_CAN_GUARD_INTERVAL_AUTO |
+			FE_CAN_RECOVER |
+			FE_CAN_HIERARCHY_AUTO,
+	},
+
+	.release = smsdvb_release,
+
+	.set_frontend = smsdvb_set_frontend,
+	.get_frontend = smsdvb_get_frontend,
+	.get_tune_settings = smsdvb_get_tune_settings,
+
+	.read_status = smsdvb_read_status,
+	.read_ber = smsdvb_read_ber,
+	.read_signal_strength = smsdvb_read_signal_strength,
+	.read_snr = smsdvb_read_snr,
+	.read_ucblocks = smsdvb_read_ucblocks,
+
+	.init = smsdvb_init,
+	.sleep = smsdvb_sleep,
+};
+
+static int smsdvb_hotplug(struct smscore_device_t *coredev,
+			  struct device *device, int arrival)
+{
+	struct smsclient_params_t params;
+	struct smsdvb_client_t *client;
+	int rc;
+
+	/* device removal handled by onremove callback */
+	if (!arrival)
+		return 0;
+	client = kzalloc(sizeof(struct smsdvb_client_t), GFP_KERNEL);
+	if (!client) {
+		sms_err("kmalloc() failed");
+		return -ENOMEM;
+	}
+
+	/* register dvb adapter */
+	rc = dvb_register_adapter(&client->adapter,
+				  sms_get_board(
+					smscore_get_board_id(coredev))->name,
+				  THIS_MODULE, device, adapter_nr);
+	if (rc < 0) {
+		sms_err("dvb_register_adapter() failed %d", rc);
+		goto adapter_error;
+	}
+
+	/* init dvb demux */
+	client->demux.dmx.capabilities = DMX_TS_FILTERING;
+	client->demux.filternum = 32; /* todo: nova ??? */
+	client->demux.feednum = 32;
+	client->demux.start_feed = smsdvb_start_feed;
+	client->demux.stop_feed = smsdvb_stop_feed;
+
+	rc = dvb_dmx_init(&client->demux);
+	if (rc < 0) {
+		sms_err("dvb_dmx_init failed %d", rc);
+		goto dvbdmx_error;
+	}
+
+	/* init dmxdev */
+	client->dmxdev.filternum = 32;
+	client->dmxdev.demux = &client->demux.dmx;
+	client->dmxdev.capabilities = 0;
+
+	rc = dvb_dmxdev_init(&client->dmxdev, &client->adapter);
+	if (rc < 0) {
+		sms_err("dvb_dmxdev_init failed %d", rc);
+		goto dmxdev_error;
+	}
+
+	/* init and register frontend */
+	memcpy(&client->frontend.ops, &smsdvb_fe_ops,
+	       sizeof(struct dvb_frontend_ops));
+
+	switch (smscore_get_device_mode(coredev)) {
+	case DEVICE_MODE_DVBT:
+	case DEVICE_MODE_DVBT_BDA:
+		client->frontend.ops.delsys[0] = SYS_DVBT;
+		break;
+	case DEVICE_MODE_ISDBT:
+	case DEVICE_MODE_ISDBT_BDA:
+		client->frontend.ops.delsys[0] = SYS_ISDBT;
+		break;
+	}
+
+	rc = dvb_register_frontend(&client->adapter, &client->frontend);
+	if (rc < 0) {
+		sms_err("frontend registration failed %d", rc);
+		goto frontend_error;
+	}
+
+	params.initial_id = 1;
+	params.data_type = MSG_SMS_DVBT_BDA_DATA;
+	params.onresponse_handler = smsdvb_onresponse;
+	params.onremove_handler = smsdvb_onremove;
+	params.context = client;
+
+	rc = smscore_register_client(coredev, &params, &client->smsclient);
+	if (rc < 0) {
+		sms_err("smscore_register_client() failed %d", rc);
+		goto client_error;
+	}
+
+	client->coredev = coredev;
+
+	init_completion(&client->tune_done);
+
+	kmutex_lock(&g_smsdvb_clientslock);
+
+	list_add(&client->entry, &g_smsdvb_clients);
+
+	kmutex_unlock(&g_smsdvb_clientslock);
+
+	client->event_fe_state = -1;
+	client->event_unc_state = -1;
+	sms_board_dvb3_event(client, DVB3_EVENT_HOTPLUG);
+
+	sms_info("success");
+	sms_board_setup(coredev);
+
+	return 0;
+
+client_error:
+	dvb_unregister_frontend(&client->frontend);
+
+frontend_error:
+	dvb_dmxdev_release(&client->dmxdev);
+
+dmxdev_error:
+	dvb_dmx_release(&client->demux);
+
+dvbdmx_error:
+	dvb_unregister_adapter(&client->adapter);
+
+adapter_error:
+	kfree(client);
+	return rc;
+}
+
+static int __init smsdvb_module_init(void)
+{
+	int rc;
+
+	INIT_LIST_HEAD(&g_smsdvb_clients);
+	kmutex_init(&g_smsdvb_clientslock);
+
+	rc = smscore_register_hotplug(smsdvb_hotplug);
+
+	sms_debug("");
+
+	return rc;
+}
+
+static void __exit smsdvb_module_exit(void)
+{
+	smscore_unregister_hotplug(smsdvb_hotplug);
+
+	kmutex_lock(&g_smsdvb_clientslock);
+
+	while (!list_empty(&g_smsdvb_clients))
+	       smsdvb_unregister_client(
+			(struct smsdvb_client_t *) g_smsdvb_clients.next);
+
+	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/common/siano/smsendian.c b/drivers/media/common/siano/smsendian.c
new file mode 100644
index 0000000..e2657c2
--- /dev/null
+++ b/drivers/media/common/siano/smsendian.c
@@ -0,0 +1,103 @@
+/****************************************************************
+
+ Siano Mobile Silicon, Inc.
+ MDTV receiver kernel modules.
+ Copyright (C) 2006-2009, Uri Shkolnik
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+ ****************************************************************/
+
+#include <linux/export.h>
+#include <asm/byteorder.h>
+
+#include "smsendian.h"
+#include "smscoreapi.h"
+
+void smsendian_handle_tx_message(void *buffer)
+{
+#ifdef __BIG_ENDIAN
+	struct SmsMsgData_ST *msg = (struct SmsMsgData_ST *)buffer;
+	int i;
+	int msgWords;
+
+	switch (msg->xMsgHeader.msgType) {
+	case MSG_SMS_DATA_DOWNLOAD_REQ:
+	{
+		msg->msgData[0] = le32_to_cpu(msg->msgData[0]);
+		break;
+	}
+
+	default:
+		msgWords = (msg->xMsgHeader.msgLength -
+				sizeof(struct SmsMsgHdr_ST))/4;
+
+		for (i = 0; i < msgWords; i++)
+			msg->msgData[i] = le32_to_cpu(msg->msgData[i]);
+
+		break;
+	}
+#endif /* __BIG_ENDIAN */
+}
+EXPORT_SYMBOL_GPL(smsendian_handle_tx_message);
+
+void smsendian_handle_rx_message(void *buffer)
+{
+#ifdef __BIG_ENDIAN
+	struct SmsMsgData_ST *msg = (struct SmsMsgData_ST *)buffer;
+	int i;
+	int msgWords;
+
+	switch (msg->xMsgHeader.msgType) {
+	case MSG_SMS_GET_VERSION_EX_RES:
+	{
+		struct SmsVersionRes_ST *ver =
+			(struct SmsVersionRes_ST *) msg;
+		ver->ChipModel = le16_to_cpu(ver->ChipModel);
+		break;
+	}
+
+	case MSG_SMS_DVBT_BDA_DATA:
+	case MSG_SMS_DAB_CHANNEL:
+	case MSG_SMS_DATA_MSG:
+	{
+		break;
+	}
+
+	default:
+	{
+		msgWords = (msg->xMsgHeader.msgLength -
+				sizeof(struct SmsMsgHdr_ST))/4;
+
+		for (i = 0; i < msgWords; i++)
+			msg->msgData[i] = le32_to_cpu(msg->msgData[i]);
+
+		break;
+	}
+	}
+#endif /* __BIG_ENDIAN */
+}
+EXPORT_SYMBOL_GPL(smsendian_handle_rx_message);
+
+void smsendian_handle_message_header(void *msg)
+{
+#ifdef __BIG_ENDIAN
+	struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *)msg;
+
+	phdr->msgType = le16_to_cpu(phdr->msgType);
+	phdr->msgLength = le16_to_cpu(phdr->msgLength);
+	phdr->msgFlags = le16_to_cpu(phdr->msgFlags);
+#endif /* __BIG_ENDIAN */
+}
+EXPORT_SYMBOL_GPL(smsendian_handle_message_header);
diff --git a/drivers/media/common/siano/smsendian.h b/drivers/media/common/siano/smsendian.h
new file mode 100644
index 0000000..1624d6f
--- /dev/null
+++ b/drivers/media/common/siano/smsendian.h
@@ -0,0 +1,32 @@
+/****************************************************************
+
+Siano Mobile Silicon, Inc.
+MDTV receiver kernel modules.
+Copyright (C) 2006-2009, Uri Shkolnik
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+****************************************************************/
+
+#ifndef __SMS_ENDIAN_H__
+#define __SMS_ENDIAN_H__
+
+#include <asm/byteorder.h>
+
+extern void smsendian_handle_tx_message(void *buffer);
+extern void smsendian_handle_rx_message(void *buffer);
+extern void smsendian_handle_message_header(void *msg);
+
+#endif /* __SMS_ENDIAN_H__ */
+
diff --git a/drivers/media/common/siano/smsir.c b/drivers/media/common/siano/smsir.c
new file mode 100644
index 0000000..37bc5c4
--- /dev/null
+++ b/drivers/media/common/siano/smsir.c
@@ -0,0 +1,114 @@
+/****************************************************************
+
+ Siano Mobile Silicon, Inc.
+ MDTV receiver kernel modules.
+ Copyright (C) 2006-2009, Uri Shkolnik
+
+ Copyright (c) 2010 - Mauro Carvalho Chehab
+	- Ported the driver to use rc-core
+	- IR raw event decoding is now done at rc-core
+	- Code almost re-written
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+ ****************************************************************/
+
+
+#include <linux/types.h>
+#include <linux/input.h>
+
+#include "smscoreapi.h"
+#include "smsir.h"
+#include "sms-cards.h"
+
+#define MODULE_NAME "smsmdtv"
+
+void sms_ir_event(struct smscore_device_t *coredev, const char *buf, int len)
+{
+	int i;
+	const s32 *samples = (const void *)buf;
+
+	for (i = 0; i < len >> 2; i++) {
+		DEFINE_IR_RAW_EVENT(ev);
+
+		ev.duration = abs(samples[i]) * 1000; /* Convert to ns */
+		ev.pulse = (samples[i] > 0) ? false : true;
+
+		ir_raw_event_store(coredev->ir.dev, &ev);
+	}
+	ir_raw_event_handle(coredev->ir.dev);
+}
+
+int sms_ir_init(struct smscore_device_t *coredev)
+{
+	int err;
+	int board_id = smscore_get_board_id(coredev);
+	struct rc_dev *dev;
+
+	sms_log("Allocating rc device");
+	dev = rc_allocate_device();
+	if (!dev) {
+		sms_err("Not enough memory");
+		return -ENOMEM;
+	}
+
+	coredev->ir.controller = 0;	/* Todo: vega/nova SPI number */
+	coredev->ir.timeout = IR_DEFAULT_TIMEOUT;
+	sms_log("IR port %d, timeout %d ms",
+			coredev->ir.controller, coredev->ir.timeout);
+
+	snprintf(coredev->ir.name, sizeof(coredev->ir.name),
+		 "SMS IR (%s)", sms_get_board(board_id)->name);
+
+	strlcpy(coredev->ir.phys, coredev->devpath, sizeof(coredev->ir.phys));
+	strlcat(coredev->ir.phys, "/ir0", sizeof(coredev->ir.phys));
+
+	dev->input_name = coredev->ir.name;
+	dev->input_phys = coredev->ir.phys;
+	dev->dev.parent = coredev->device;
+
+#if 0
+	/* TODO: properly initialize the parameters bellow */
+	dev->input_id.bustype = BUS_USB;
+	dev->input_id.version = 1;
+	dev->input_id.vendor = le16_to_cpu(dev->udev->descriptor.idVendor);
+	dev->input_id.product = le16_to_cpu(dev->udev->descriptor.idProduct);
+#endif
+
+	dev->priv = coredev;
+	dev->driver_type = RC_DRIVER_IR_RAW;
+	dev->allowed_protos = RC_TYPE_ALL;
+	dev->map_name = sms_get_board(board_id)->rc_codes;
+	dev->driver_name = MODULE_NAME;
+
+	sms_log("Input device (IR) %s is set for key events", dev->input_name);
+
+	err = rc_register_device(dev);
+	if (err < 0) {
+		sms_err("Failed to register device");
+		rc_free_device(dev);
+		return err;
+	}
+
+	coredev->ir.dev = dev;
+	return 0;
+}
+
+void sms_ir_exit(struct smscore_device_t *coredev)
+{
+	if (coredev->ir.dev)
+		rc_unregister_device(coredev->ir.dev);
+
+	sms_log("");
+}
diff --git a/drivers/media/common/siano/smsir.h b/drivers/media/common/siano/smsir.h
new file mode 100644
index 0000000..ae92b3a
--- /dev/null
+++ b/drivers/media/common/siano/smsir.h
@@ -0,0 +1,55 @@
+/****************************************************************
+
+Siano Mobile Silicon, Inc.
+MDTV receiver kernel modules.
+Copyright (C) 2006-2009, Uri Shkolnik
+
+ Copyright (c) 2010 - Mauro Carvalho Chehab
+	- Ported the driver to use rc-core
+	- IR raw event decoding is now done at rc-core
+	- Code almost re-written
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+****************************************************************/
+
+#ifndef __SMS_IR_H__
+#define __SMS_IR_H__
+
+#include <linux/input.h>
+#include <media/rc-core.h>
+
+#define IR_DEFAULT_TIMEOUT		100
+
+struct smscore_device_t;
+
+struct ir_t {
+	struct rc_dev *dev;
+	char name[40];
+	char phys[32];
+
+	char *rc_codes;
+	u64 protocol;
+
+	u32 timeout;
+	u32 controller;
+};
+
+int sms_ir_init(struct smscore_device_t *coredev);
+void sms_ir_exit(struct smscore_device_t *coredev);
+void sms_ir_event(struct smscore_device_t *coredev,
+			const char *buf, int len);
+
+#endif /* __SMS_IR_H__ */
+
diff --git a/drivers/media/common/tuners/Kconfig b/drivers/media/common/tuners/Kconfig
deleted file mode 100644
index 94c6ff7..0000000
--- a/drivers/media/common/tuners/Kconfig
+++ /dev/null
@@ -1,243 +0,0 @@
-config MEDIA_ATTACH
-	bool "Load and attach frontend and tuner driver modules as needed"
-	depends on MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT || MEDIA_RADIO_SUPPORT
-	depends on MODULES
-	default y if !EXPERT
-	help
-	  Remove the static dependency of DVB card drivers on all
-	  frontend modules for all possible card variants. Instead,
-	  allow the card drivers to only load the frontend modules
-	  they require.
-
-	  Also, tuner module will automatically load a tuner driver
-	  when needed, for analog mode.
-
-	  This saves several KBytes of memory.
-
-	  Note: You will need module-init-tools v3.2 or later for this feature.
-
-	  If unsure say Y.
-
-config MEDIA_TUNER
-	tristate
-	depends on (MEDIA_ANALOG_TV_SUPPORT || MEDIA_RADIO_SUPPORT) && I2C
-	default y
-	select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMISE
-	select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMISE
-	select MEDIA_TUNER_XC4000 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 && MEDIA_RADIO_SUPPORT && EXPERIMENTAL
-	select MEDIA_TUNER_TEA5767 if !MEDIA_TUNER_CUSTOMISE && MEDIA_RADIO_SUPPORT
-	select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE
-	select MEDIA_TUNER_TDA9887 if !MEDIA_TUNER_CUSTOMISE
-	select MEDIA_TUNER_MC44S803 if !MEDIA_TUNER_CUSTOMISE
-
-config MEDIA_TUNER_CUSTOMISE
-	bool "Customize analog and hybrid tuner modules to build"
-	depends on MEDIA_TUNER
-	default y if EXPERT
-	help
-	  This allows the user to deselect tuner drivers unnecessary
-	  for their hardware from the build. Use this option with care
-	  as deselecting tuner drivers which are in fact necessary will
-	  result in V4L/DVB devices which cannot be tuned due to lack of
-	  driver support
-
-	  If unsure say N.
-
-menu "Customize TV tuners"
-	visible if MEDIA_TUNER_CUSTOMISE
-	depends on MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT || MEDIA_RADIO_SUPPORT
-
-config MEDIA_TUNER_SIMPLE
-	tristate "Simple tuner support"
-	depends on MEDIA_SUPPORT && I2C
-	select MEDIA_TUNER_TDA9887
-	default m if MEDIA_TUNER_CUSTOMISE
-	help
-	  Say Y here to include support for various simple tuners.
-
-config MEDIA_TUNER_TDA8290
-	tristate "TDA 8290/8295 + 8275(a)/18271 tuner combo"
-	depends on MEDIA_SUPPORT && I2C
-	select MEDIA_TUNER_TDA827X
-	select MEDIA_TUNER_TDA18271
-	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 MEDIA_SUPPORT && I2C
-	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 MEDIA_SUPPORT && I2C
-	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 MEDIA_SUPPORT && I2C
-	default m if MEDIA_TUNER_CUSTOMISE
-	help
-	  Say Y here to include support for Philips TDA9885/6/7
-	  analog IF demodulator.
-
-config MEDIA_TUNER_TEA5761
-	tristate "TEA 5761 radio tuner (EXPERIMENTAL)"
-	depends on MEDIA_SUPPORT && I2C
-	depends on EXPERIMENTAL
-	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 MEDIA_SUPPORT && I2C
-	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 MEDIA_SUPPORT && I2C
-	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 MEDIA_SUPPORT && I2C
-	default m if MEDIA_TUNER_CUSTOMISE
-	help
-	  A driver for the silicon IF tuner MT2060 from Microtune.
-
-config MEDIA_TUNER_MT2063
-	tristate "Microtune MT2063 silicon IF tuner"
-	depends on MEDIA_SUPPORT && I2C
-	default m if MEDIA_TUNER_CUSTOMISE
-	help
-	  A driver for the silicon IF tuner MT2063 from Microtune.
-
-config MEDIA_TUNER_MT2266
-	tristate "Microtune MT2266 silicon tuner"
-	depends on MEDIA_SUPPORT && I2C
-	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 MEDIA_SUPPORT && I2C
-	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 MEDIA_SUPPORT && I2C
-	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 MEDIA_SUPPORT && I2C
-	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 MEDIA_SUPPORT && I2C
-	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 together with a
-	  demodulator for now.
-
-config MEDIA_TUNER_XC4000
-	tristate "Xceive XC4000 silicon tuner"
-	depends on MEDIA_SUPPORT && I2C
-	default m if MEDIA_TUNER_CUSTOMISE
-	help
-	  A driver for the silicon tuner XC4000 from Xceive.
-	  This device is only used inside a SiP called together with a
-	  demodulator for now.
-
-config MEDIA_TUNER_MXL5005S
-	tristate "MaxLinear MSL5005S silicon tuner"
-	depends on MEDIA_SUPPORT && I2C
-	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 MEDIA_SUPPORT && I2C
-	default m if MEDIA_TUNER_CUSTOMISE
-	help
-	  A driver for the silicon tuner MxL5007T from MaxLinear.
-
-config MEDIA_TUNER_MC44S803
-	tristate "Freescale MC44S803 Low Power CMOS Broadband tuners"
-	depends on MEDIA_SUPPORT && I2C
-	default m if MEDIA_TUNER_CUSTOMISE
-	help
-	  Say Y here to support the Freescale MC44S803 based tuners
-
-config MEDIA_TUNER_MAX2165
-	tristate "Maxim MAX2165 silicon tuner"
-	depends on MEDIA_SUPPORT && I2C
-	default m if MEDIA_TUNER_CUSTOMISE
-	help
-	  A driver for the silicon tuner MAX2165 from Maxim.
-
-config MEDIA_TUNER_TDA18218
-	tristate "NXP TDA18218 silicon tuner"
-	depends on MEDIA_SUPPORT && I2C
-	default m if MEDIA_TUNER_CUSTOMISE
-	help
-	  NXP TDA18218 silicon tuner driver.
-
-config MEDIA_TUNER_FC0011
-	tristate "Fitipower FC0011 silicon tuner"
-	depends on MEDIA_SUPPORT && I2C
-	default m if MEDIA_TUNER_CUSTOMISE
-	help
-	  Fitipower FC0011 silicon tuner driver.
-
-config MEDIA_TUNER_FC0012
-	tristate "Fitipower FC0012 silicon tuner"
-	depends on MEDIA_SUPPORT && I2C
-	default m if MEDIA_TUNER_CUSTOMISE
-	help
-	  Fitipower FC0012 silicon tuner driver.
-
-config MEDIA_TUNER_FC0013
-	tristate "Fitipower FC0013 silicon tuner"
-	depends on MEDIA_SUPPORT && I2C
-	default m if MEDIA_TUNER_CUSTOMISE
-	help
-	  Fitipower FC0013 silicon tuner driver.
-
-config MEDIA_TUNER_TDA18212
-	tristate "NXP TDA18212 silicon tuner"
-	depends on MEDIA_SUPPORT && I2C
-	default m if MEDIA_TUNER_CUSTOMISE
-	help
-	  NXP TDA18212 silicon tuner driver.
-
-config MEDIA_TUNER_TUA9001
-	tristate "Infineon TUA 9001 silicon tuner"
-	depends on MEDIA_SUPPORT && I2C
-	default m if MEDIA_TUNER_CUSTOMISE
-	help
-	  Infineon TUA 9001 silicon tuner driver.
-endmenu
diff --git a/drivers/media/common/tuners/Makefile b/drivers/media/common/tuners/Makefile
deleted file mode 100644
index 891b80e..0000000
--- a/drivers/media/common/tuners/Makefile
+++ /dev/null
@@ -1,37 +0,0 @@
-#
-# Makefile for common V4L/DVB tuners
-#
-
-tda18271-objs := tda18271-maps.o tda18271-common.o tda18271-fe.o
-
-obj-$(CONFIG_MEDIA_TUNER_XC2028) += tuner-xc2028.o
-obj-$(CONFIG_MEDIA_TUNER_SIMPLE) += tuner-simple.o
-# tuner-types will be merged into tuner-simple, in the future
-obj-$(CONFIG_MEDIA_TUNER_SIMPLE) += tuner-types.o
-obj-$(CONFIG_MEDIA_TUNER_MT20XX) += mt20xx.o
-obj-$(CONFIG_MEDIA_TUNER_TDA8290) += tda8290.o
-obj-$(CONFIG_MEDIA_TUNER_TEA5767) += tea5767.o
-obj-$(CONFIG_MEDIA_TUNER_TEA5761) += tea5761.o
-obj-$(CONFIG_MEDIA_TUNER_TDA9887) += tda9887.o
-obj-$(CONFIG_MEDIA_TUNER_TDA827X) += tda827x.o
-obj-$(CONFIG_MEDIA_TUNER_TDA18271) += tda18271.o
-obj-$(CONFIG_MEDIA_TUNER_XC5000) += xc5000.o
-obj-$(CONFIG_MEDIA_TUNER_XC4000) += xc4000.o
-obj-$(CONFIG_MEDIA_TUNER_MT2060) += mt2060.o
-obj-$(CONFIG_MEDIA_TUNER_MT2063) += mt2063.o
-obj-$(CONFIG_MEDIA_TUNER_MT2266) += mt2266.o
-obj-$(CONFIG_MEDIA_TUNER_QT1010) += qt1010.o
-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
-obj-$(CONFIG_MEDIA_TUNER_MAX2165) += max2165.o
-obj-$(CONFIG_MEDIA_TUNER_TDA18218) += tda18218.o
-obj-$(CONFIG_MEDIA_TUNER_TDA18212) += tda18212.o
-obj-$(CONFIG_MEDIA_TUNER_TUA9001) += tua9001.o
-obj-$(CONFIG_MEDIA_TUNER_FC0011) += fc0011.o
-obj-$(CONFIG_MEDIA_TUNER_FC0012) += fc0012.o
-obj-$(CONFIG_MEDIA_TUNER_FC0013) += fc0013.o
-
-ccflags-y += -I$(srctree)/drivers/media/dvb/dvb-core
-ccflags-y += -I$(srctree)/drivers/media/dvb/frontends
diff --git a/drivers/media/common/tuners/fc0011.c b/drivers/media/common/tuners/fc0011.c
deleted file mode 100644
index e488254..0000000
--- a/drivers/media/common/tuners/fc0011.c
+++ /dev/null
@@ -1,524 +0,0 @@
-/*
- * Fitipower FC0011 tuner driver
- *
- * Copyright (C) 2012 Michael Buesch <m@bues.ch>
- *
- * Derived from FC0012 tuner driver:
- * Copyright (C) 2012 Hans-Frieder Vogt <hfvogt@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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You 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 "fc0011.h"
-
-
-/* Tuner registers */
-enum {
-	FC11_REG_0,
-	FC11_REG_FA,		/* FA */
-	FC11_REG_FP,		/* FP */
-	FC11_REG_XINHI,		/* XIN high 8 bit */
-	FC11_REG_XINLO,		/* XIN low 8 bit */
-	FC11_REG_VCO,		/* VCO */
-	FC11_REG_VCOSEL,	/* VCO select */
-	FC11_REG_7,		/* Unknown tuner reg 7 */
-	FC11_REG_8,		/* Unknown tuner reg 8 */
-	FC11_REG_9,
-	FC11_REG_10,		/* Unknown tuner reg 10 */
-	FC11_REG_11,		/* Unknown tuner reg 11 */
-	FC11_REG_12,
-	FC11_REG_RCCAL,		/* RC calibrate */
-	FC11_REG_VCOCAL,	/* VCO calibrate */
-	FC11_REG_15,
-	FC11_REG_16,		/* Unknown tuner reg 16 */
-	FC11_REG_17,
-
-	FC11_NR_REGS,		/* Number of registers */
-};
-
-enum FC11_REG_VCOSEL_bits {
-	FC11_VCOSEL_2		= 0x08, /* VCO select 2 */
-	FC11_VCOSEL_1		= 0x10, /* VCO select 1 */
-	FC11_VCOSEL_CLKOUT	= 0x20, /* Fix clock out */
-	FC11_VCOSEL_BW7M	= 0x40, /* 7MHz bw */
-	FC11_VCOSEL_BW6M	= 0x80, /* 6MHz bw */
-};
-
-enum FC11_REG_RCCAL_bits {
-	FC11_RCCAL_FORCE	= 0x10, /* force */
-};
-
-enum FC11_REG_VCOCAL_bits {
-	FC11_VCOCAL_RUN		= 0,	/* VCO calibration run */
-	FC11_VCOCAL_VALUEMASK	= 0x3F,	/* VCO calibration value mask */
-	FC11_VCOCAL_OK		= 0x40,	/* VCO calibration Ok */
-	FC11_VCOCAL_RESET	= 0x80, /* VCO calibration reset */
-};
-
-
-struct fc0011_priv {
-	struct i2c_adapter *i2c;
-	u8 addr;
-
-	u32 frequency;
-	u32 bandwidth;
-};
-
-
-static int fc0011_writereg(struct fc0011_priv *priv, u8 reg, u8 val)
-{
-	u8 buf[2] = { reg, val };
-	struct i2c_msg msg = { .addr = priv->addr,
-		.flags = 0, .buf = buf, .len = 2 };
-
-	if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
-		dev_err(&priv->i2c->dev,
-			"I2C write reg failed, reg: %02x, val: %02x\n",
-			reg, val);
-		return -EIO;
-	}
-
-	return 0;
-}
-
-static int fc0011_readreg(struct fc0011_priv *priv, u8 reg, u8 *val)
-{
-	u8 dummy;
-	struct i2c_msg msg[2] = {
-		{ .addr = priv->addr,
-		  .flags = 0, .buf = &reg, .len = 1 },
-		{ .addr = priv->addr,
-		  .flags = I2C_M_RD, .buf = val ? : &dummy, .len = 1 },
-	};
-
-	if (i2c_transfer(priv->i2c, msg, 2) != 2) {
-		dev_err(&priv->i2c->dev,
-			"I2C read failed, reg: %02x\n", reg);
-		return -EIO;
-	}
-
-	return 0;
-}
-
-static int fc0011_release(struct dvb_frontend *fe)
-{
-	kfree(fe->tuner_priv);
-	fe->tuner_priv = NULL;
-
-	return 0;
-}
-
-static int fc0011_init(struct dvb_frontend *fe)
-{
-	struct fc0011_priv *priv = fe->tuner_priv;
-	int err;
-
-	if (WARN_ON(!fe->callback))
-		return -EINVAL;
-
-	err = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER,
-			   FC0011_FE_CALLBACK_POWER, priv->addr);
-	if (err) {
-		dev_err(&priv->i2c->dev, "Power-on callback failed\n");
-		return err;
-	}
-	err = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER,
-			   FC0011_FE_CALLBACK_RESET, priv->addr);
-	if (err) {
-		dev_err(&priv->i2c->dev, "Reset callback failed\n");
-		return err;
-	}
-
-	return 0;
-}
-
-/* Initiate VCO calibration */
-static int fc0011_vcocal_trigger(struct fc0011_priv *priv)
-{
-	int err;
-
-	err = fc0011_writereg(priv, FC11_REG_VCOCAL, FC11_VCOCAL_RESET);
-	if (err)
-		return err;
-	err = fc0011_writereg(priv, FC11_REG_VCOCAL, FC11_VCOCAL_RUN);
-	if (err)
-		return err;
-
-	return 0;
-}
-
-/* Read VCO calibration value */
-static int fc0011_vcocal_read(struct fc0011_priv *priv, u8 *value)
-{
-	int err;
-
-	err = fc0011_writereg(priv, FC11_REG_VCOCAL, FC11_VCOCAL_RUN);
-	if (err)
-		return err;
-	usleep_range(10000, 20000);
-	err = fc0011_readreg(priv, FC11_REG_VCOCAL, value);
-	if (err)
-		return err;
-
-	return 0;
-}
-
-static int fc0011_set_params(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct fc0011_priv *priv = fe->tuner_priv;
-	int err;
-	unsigned int i, vco_retries;
-	u32 freq = p->frequency / 1000;
-	u32 bandwidth = p->bandwidth_hz / 1000;
-	u32 fvco, xin, xdiv, xdivr;
-	u16 frac;
-	u8 fa, fp, vco_sel, vco_cal;
-	u8 regs[FC11_NR_REGS] = { };
-
-	regs[FC11_REG_7] = 0x0F;
-	regs[FC11_REG_8] = 0x3E;
-	regs[FC11_REG_10] = 0xB8;
-	regs[FC11_REG_11] = 0x80;
-	regs[FC11_REG_RCCAL] = 0x04;
-	err = fc0011_writereg(priv, FC11_REG_7, regs[FC11_REG_7]);
-	err |= fc0011_writereg(priv, FC11_REG_8, regs[FC11_REG_8]);
-	err |= fc0011_writereg(priv, FC11_REG_10, regs[FC11_REG_10]);
-	err |= fc0011_writereg(priv, FC11_REG_11, regs[FC11_REG_11]);
-	err |= fc0011_writereg(priv, FC11_REG_RCCAL, regs[FC11_REG_RCCAL]);
-	if (err)
-		return -EIO;
-
-	/* Set VCO freq and VCO div */
-	if (freq < 54000) {
-		fvco = freq * 64;
-		regs[FC11_REG_VCO] = 0x82;
-	} else if (freq < 108000) {
-		fvco = freq * 32;
-		regs[FC11_REG_VCO] = 0x42;
-	} else if (freq < 216000) {
-		fvco = freq * 16;
-		regs[FC11_REG_VCO] = 0x22;
-	} else if (freq < 432000) {
-		fvco = freq * 8;
-		regs[FC11_REG_VCO] = 0x12;
-	} else {
-		fvco = freq * 4;
-		regs[FC11_REG_VCO] = 0x0A;
-	}
-
-	/* Calc XIN. The PLL reference frequency is 18 MHz. */
-	xdiv = fvco / 18000;
-	frac = fvco - xdiv * 18000;
-	frac = (frac << 15) / 18000;
-	if (frac >= 16384)
-		frac += 32786;
-	if (!frac)
-		xin = 0;
-	else if (frac < 511)
-		xin = 512;
-	else if (frac < 65026)
-		xin = frac;
-	else
-		xin = 65024;
-	regs[FC11_REG_XINHI] = xin >> 8;
-	regs[FC11_REG_XINLO] = xin;
-
-	/* Calc FP and FA */
-	xdivr = xdiv;
-	if (fvco - xdiv * 18000 >= 9000)
-		xdivr += 1; /* round */
-	fp = xdivr / 8;
-	fa = xdivr - fp * 8;
-	if (fa < 2) {
-		fp -= 1;
-		fa += 8;
-	}
-	if (fp > 0x1F) {
-		fp &= 0x1F;
-		fa &= 0xF;
-	}
-	if (fa >= fp) {
-		dev_warn(&priv->i2c->dev,
-			 "fa %02X >= fp %02X, but trying to continue\n",
-			 (unsigned int)(u8)fa, (unsigned int)(u8)fp);
-	}
-	regs[FC11_REG_FA] = fa;
-	regs[FC11_REG_FP] = fp;
-
-	/* Select bandwidth */
-	switch (bandwidth) {
-	case 8000:
-		break;
-	case 7000:
-		regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_BW7M;
-		break;
-	default:
-		dev_warn(&priv->i2c->dev, "Unsupported bandwidth %u kHz. "
-			 "Using 6000 kHz.\n",
-			 bandwidth);
-		bandwidth = 6000;
-		/* fallthrough */
-	case 6000:
-		regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_BW6M;
-		break;
-	}
-
-	/* Pre VCO select */
-	if (fvco < 2320000) {
-		vco_sel = 0;
-		regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2);
-	} else if (fvco < 3080000) {
-		vco_sel = 1;
-		regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2);
-		regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_1;
-	} else {
-		vco_sel = 2;
-		regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2);
-		regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_2;
-	}
-
-	/* Fix for low freqs */
-	if (freq < 45000) {
-		regs[FC11_REG_FA] = 0x6;
-		regs[FC11_REG_FP] = 0x11;
-	}
-
-	/* Clock out fix */
-	regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_CLKOUT;
-
-	/* Write the cached registers */
-	for (i = FC11_REG_FA; i <= FC11_REG_VCOSEL; i++) {
-		err = fc0011_writereg(priv, i, regs[i]);
-		if (err)
-			return err;
-	}
-
-	/* VCO calibration */
-	err = fc0011_vcocal_trigger(priv);
-	if (err)
-		return err;
-	err = fc0011_vcocal_read(priv, &vco_cal);
-	if (err)
-		return err;
-	vco_retries = 0;
-	while (!(vco_cal & FC11_VCOCAL_OK) && vco_retries < 3) {
-		/* Reset the tuner and try again */
-		err = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER,
-				   FC0011_FE_CALLBACK_RESET, priv->addr);
-		if (err) {
-			dev_err(&priv->i2c->dev, "Failed to reset tuner\n");
-			return err;
-		}
-		/* Reinit tuner config */
-		err = 0;
-		for (i = FC11_REG_FA; i <= FC11_REG_VCOSEL; i++)
-			err |= fc0011_writereg(priv, i, regs[i]);
-		err |= fc0011_writereg(priv, FC11_REG_7, regs[FC11_REG_7]);
-		err |= fc0011_writereg(priv, FC11_REG_8, regs[FC11_REG_8]);
-		err |= fc0011_writereg(priv, FC11_REG_10, regs[FC11_REG_10]);
-		err |= fc0011_writereg(priv, FC11_REG_11, regs[FC11_REG_11]);
-		err |= fc0011_writereg(priv, FC11_REG_RCCAL, regs[FC11_REG_RCCAL]);
-		if (err)
-			return -EIO;
-		/* VCO calibration */
-		err = fc0011_vcocal_trigger(priv);
-		if (err)
-			return err;
-		err = fc0011_vcocal_read(priv, &vco_cal);
-		if (err)
-			return err;
-		vco_retries++;
-	}
-	if (!(vco_cal & FC11_VCOCAL_OK)) {
-		dev_err(&priv->i2c->dev,
-			"Failed to read VCO calibration value (got %02X)\n",
-			(unsigned int)vco_cal);
-		return -EIO;
-	}
-	vco_cal &= FC11_VCOCAL_VALUEMASK;
-
-	switch (vco_sel) {
-	case 0:
-		if (vco_cal < 8) {
-			regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2);
-			regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_1;
-			err = fc0011_writereg(priv, FC11_REG_VCOSEL,
-					      regs[FC11_REG_VCOSEL]);
-			if (err)
-				return err;
-			err = fc0011_vcocal_trigger(priv);
-			if (err)
-				return err;
-		} else {
-			regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2);
-			err = fc0011_writereg(priv, FC11_REG_VCOSEL,
-					      regs[FC11_REG_VCOSEL]);
-			if (err)
-				return err;
-		}
-		break;
-	case 1:
-		if (vco_cal < 5) {
-			regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2);
-			regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_2;
-			err = fc0011_writereg(priv, FC11_REG_VCOSEL,
-					      regs[FC11_REG_VCOSEL]);
-			if (err)
-				return err;
-			err = fc0011_vcocal_trigger(priv);
-			if (err)
-				return err;
-		} else if (vco_cal <= 48) {
-			regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2);
-			regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_1;
-			err = fc0011_writereg(priv, FC11_REG_VCOSEL,
-					      regs[FC11_REG_VCOSEL]);
-			if (err)
-				return err;
-		} else {
-			regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2);
-			err = fc0011_writereg(priv, FC11_REG_VCOSEL,
-					      regs[FC11_REG_VCOSEL]);
-			if (err)
-				return err;
-			err = fc0011_vcocal_trigger(priv);
-			if (err)
-				return err;
-		}
-		break;
-	case 2:
-		if (vco_cal > 53) {
-			regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2);
-			regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_1;
-			err = fc0011_writereg(priv, FC11_REG_VCOSEL,
-					      regs[FC11_REG_VCOSEL]);
-			if (err)
-				return err;
-			err = fc0011_vcocal_trigger(priv);
-			if (err)
-				return err;
-		} else {
-			regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2);
-			regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_2;
-			err = fc0011_writereg(priv, FC11_REG_VCOSEL,
-					      regs[FC11_REG_VCOSEL]);
-			if (err)
-				return err;
-		}
-		break;
-	}
-	err = fc0011_vcocal_read(priv, NULL);
-	if (err)
-		return err;
-	usleep_range(10000, 50000);
-
-	err = fc0011_readreg(priv, FC11_REG_RCCAL, &regs[FC11_REG_RCCAL]);
-	if (err)
-		return err;
-	regs[FC11_REG_RCCAL] |= FC11_RCCAL_FORCE;
-	err = fc0011_writereg(priv, FC11_REG_RCCAL, regs[FC11_REG_RCCAL]);
-	if (err)
-		return err;
-	err = fc0011_writereg(priv, FC11_REG_16, 0xB);
-	if (err)
-		return err;
-
-	dev_dbg(&priv->i2c->dev, "Tuned to "
-		"fa=%02X fp=%02X xin=%02X%02X vco=%02X vcosel=%02X "
-		"vcocal=%02X(%u) bw=%u\n",
-		(unsigned int)regs[FC11_REG_FA],
-		(unsigned int)regs[FC11_REG_FP],
-		(unsigned int)regs[FC11_REG_XINHI],
-		(unsigned int)regs[FC11_REG_XINLO],
-		(unsigned int)regs[FC11_REG_VCO],
-		(unsigned int)regs[FC11_REG_VCOSEL],
-		(unsigned int)vco_cal, vco_retries,
-		(unsigned int)bandwidth);
-
-	priv->frequency = p->frequency;
-	priv->bandwidth = p->bandwidth_hz;
-
-	return 0;
-}
-
-static int fc0011_get_frequency(struct dvb_frontend *fe, u32 *frequency)
-{
-	struct fc0011_priv *priv = fe->tuner_priv;
-
-	*frequency = priv->frequency;
-
-	return 0;
-}
-
-static int fc0011_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
-{
-	*frequency = 0;
-
-	return 0;
-}
-
-static int fc0011_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
-{
-	struct fc0011_priv *priv = fe->tuner_priv;
-
-	*bandwidth = priv->bandwidth;
-
-	return 0;
-}
-
-static const struct dvb_tuner_ops fc0011_tuner_ops = {
-	.info = {
-		.name		= "Fitipower FC0011",
-
-		.frequency_min	= 45000000,
-		.frequency_max	= 1000000000,
-	},
-
-	.release		= fc0011_release,
-	.init			= fc0011_init,
-
-	.set_params		= fc0011_set_params,
-
-	.get_frequency		= fc0011_get_frequency,
-	.get_if_frequency	= fc0011_get_if_frequency,
-	.get_bandwidth		= fc0011_get_bandwidth,
-};
-
-struct dvb_frontend *fc0011_attach(struct dvb_frontend *fe,
-				   struct i2c_adapter *i2c,
-				   const struct fc0011_config *config)
-{
-	struct fc0011_priv *priv;
-
-	priv = kzalloc(sizeof(struct fc0011_priv), GFP_KERNEL);
-	if (!priv)
-		return NULL;
-
-	priv->i2c = i2c;
-	priv->addr = config->i2c_address;
-
-	fe->tuner_priv = priv;
-	fe->ops.tuner_ops = fc0011_tuner_ops;
-
-	dev_info(&priv->i2c->dev, "Fitipower FC0011 tuner attached\n");
-
-	return fe;
-}
-EXPORT_SYMBOL(fc0011_attach);
-
-MODULE_DESCRIPTION("Fitipower FC0011 silicon tuner driver");
-MODULE_AUTHOR("Michael Buesch <m@bues.ch>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/common/tuners/fc0011.h b/drivers/media/common/tuners/fc0011.h
deleted file mode 100644
index 0ee581f..0000000
--- a/drivers/media/common/tuners/fc0011.h
+++ /dev/null
@@ -1,41 +0,0 @@
-#ifndef LINUX_FC0011_H_
-#define LINUX_FC0011_H_
-
-#include "dvb_frontend.h"
-
-
-/** struct fc0011_config - fc0011 hardware config
- *
- * @i2c_address: I2C bus address.
- */
-struct fc0011_config {
-	u8 i2c_address;
-};
-
-/** enum fc0011_fe_callback_commands - Frontend callbacks
- *
- * @FC0011_FE_CALLBACK_POWER: Power on tuner hardware.
- * @FC0011_FE_CALLBACK_RESET: Request a tuner reset.
- */
-enum fc0011_fe_callback_commands {
-	FC0011_FE_CALLBACK_POWER,
-	FC0011_FE_CALLBACK_RESET,
-};
-
-#if defined(CONFIG_MEDIA_TUNER_FC0011) ||\
-    defined(CONFIG_MEDIA_TUNER_FC0011_MODULE)
-struct dvb_frontend *fc0011_attach(struct dvb_frontend *fe,
-				   struct i2c_adapter *i2c,
-				   const struct fc0011_config *config);
-#else
-static inline
-struct dvb_frontend *fc0011_attach(struct dvb_frontend *fe,
-				   struct i2c_adapter *i2c,
-				   const struct fc0011_config *config)
-{
-	dev_err(&i2c->dev, "fc0011 driver disabled in Kconfig\n");
-	return NULL;
-}
-#endif
-
-#endif /* LINUX_FC0011_H_ */
diff --git a/drivers/media/common/tuners/fc0012-priv.h b/drivers/media/common/tuners/fc0012-priv.h
deleted file mode 100644
index 4577c91..0000000
--- a/drivers/media/common/tuners/fc0012-priv.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Fitipower FC0012 tuner driver - private includes
- *
- * Copyright (C) 2012 Hans-Frieder Vogt <hfvogt@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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You 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 _FC0012_PRIV_H_
-#define _FC0012_PRIV_H_
-
-#define LOG_PREFIX "fc0012"
-
-#undef err
-#define err(f, arg...)  printk(KERN_ERR     LOG_PREFIX": " f "\n" , ## arg)
-#undef info
-#define info(f, arg...) printk(KERN_INFO    LOG_PREFIX": " f "\n" , ## arg)
-#undef warn
-#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg)
-
-struct fc0012_priv {
-	struct i2c_adapter *i2c;
-	u8 addr;
-	u8 dual_master;
-	u8 xtal_freq;
-
-	u32 frequency;
-	u32 bandwidth;
-};
-
-#endif
diff --git a/drivers/media/common/tuners/fc0012.c b/drivers/media/common/tuners/fc0012.c
deleted file mode 100644
index 308135a..0000000
--- a/drivers/media/common/tuners/fc0012.c
+++ /dev/null
@@ -1,467 +0,0 @@
-/*
- * Fitipower FC0012 tuner driver
- *
- * Copyright (C) 2012 Hans-Frieder Vogt <hfvogt@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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You 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 "fc0012.h"
-#include "fc0012-priv.h"
-
-static int fc0012_writereg(struct fc0012_priv *priv, u8 reg, u8 val)
-{
-	u8 buf[2] = {reg, val};
-	struct i2c_msg msg = {
-		.addr = priv->addr, .flags = 0, .buf = buf, .len = 2
-	};
-
-	if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
-		err("I2C write reg failed, reg: %02x, val: %02x", reg, val);
-		return -EREMOTEIO;
-	}
-	return 0;
-}
-
-static int fc0012_readreg(struct fc0012_priv *priv, u8 reg, u8 *val)
-{
-	struct i2c_msg msg[2] = {
-		{ .addr = priv->addr, .flags = 0, .buf = &reg, .len = 1 },
-		{ .addr = priv->addr, .flags = I2C_M_RD, .buf = val, .len = 1 },
-	};
-
-	if (i2c_transfer(priv->i2c, msg, 2) != 2) {
-		err("I2C read reg failed, reg: %02x", reg);
-		return -EREMOTEIO;
-	}
-	return 0;
-}
-
-static int fc0012_release(struct dvb_frontend *fe)
-{
-	kfree(fe->tuner_priv);
-	fe->tuner_priv = NULL;
-	return 0;
-}
-
-static int fc0012_init(struct dvb_frontend *fe)
-{
-	struct fc0012_priv *priv = fe->tuner_priv;
-	int i, ret = 0;
-	unsigned char reg[] = {
-		0x00,	/* dummy reg. 0 */
-		0x05,	/* reg. 0x01 */
-		0x10,	/* reg. 0x02 */
-		0x00,	/* reg. 0x03 */
-		0x00,	/* reg. 0x04 */
-		0x0f,	/* reg. 0x05: may also be 0x0a */
-		0x00,	/* reg. 0x06: divider 2, VCO slow */
-		0x00,	/* reg. 0x07: may also be 0x0f */
-		0xff,	/* reg. 0x08: AGC Clock divide by 256, AGC gain 1/256,
-			   Loop Bw 1/8 */
-		0x6e,	/* reg. 0x09: Disable LoopThrough, Enable LoopThrough: 0x6f */
-		0xb8,	/* reg. 0x0a: Disable LO Test Buffer */
-		0x82,	/* reg. 0x0b: Output Clock is same as clock frequency,
-			   may also be 0x83 */
-		0xfc,	/* reg. 0x0c: depending on AGC Up-Down mode, may need 0xf8 */
-		0x02,	/* reg. 0x0d: AGC Not Forcing & LNA Forcing, 0x02 for DVB-T */
-		0x00,	/* reg. 0x0e */
-		0x00,	/* reg. 0x0f */
-		0x00,	/* reg. 0x10: may also be 0x0d */
-		0x00,	/* reg. 0x11 */
-		0x1f,	/* reg. 0x12: Set to maximum gain */
-		0x08,	/* reg. 0x13: Set to Middle Gain: 0x08,
-			   Low Gain: 0x00, High Gain: 0x10, enable IX2: 0x80 */
-		0x00,	/* reg. 0x14 */
-		0x04,	/* reg. 0x15: Enable LNA COMPS */
-	};
-
-	switch (priv->xtal_freq) {
-	case FC_XTAL_27_MHZ:
-	case FC_XTAL_28_8_MHZ:
-		reg[0x07] |= 0x20;
-		break;
-	case FC_XTAL_36_MHZ:
-	default:
-		break;
-	}
-
-	if (priv->dual_master)
-		reg[0x0c] |= 0x02;
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
-
-	for (i = 1; i < sizeof(reg); i++) {
-		ret = fc0012_writereg(priv, i, reg[i]);
-		if (ret)
-			break;
-	}
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
-
-	if (ret)
-		err("fc0012_writereg failed: %d", ret);
-
-	return ret;
-}
-
-static int fc0012_sleep(struct dvb_frontend *fe)
-{
-	/* nothing to do here */
-	return 0;
-}
-
-static int fc0012_set_params(struct dvb_frontend *fe)
-{
-	struct fc0012_priv *priv = fe->tuner_priv;
-	int i, ret = 0;
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	u32 freq = p->frequency / 1000;
-	u32 delsys = p->delivery_system;
-	unsigned char reg[7], am, pm, multi, tmp;
-	unsigned long f_vco;
-	unsigned short xtal_freq_khz_2, xin, xdiv;
-	int vco_select = false;
-
-	if (fe->callback) {
-		ret = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER,
-			FC_FE_CALLBACK_VHF_ENABLE, (freq > 300000 ? 0 : 1));
-		if (ret)
-			goto exit;
-	}
-
-	switch (priv->xtal_freq) {
-	case FC_XTAL_27_MHZ:
-		xtal_freq_khz_2 = 27000 / 2;
-		break;
-	case FC_XTAL_36_MHZ:
-		xtal_freq_khz_2 = 36000 / 2;
-		break;
-	case FC_XTAL_28_8_MHZ:
-	default:
-		xtal_freq_khz_2 = 28800 / 2;
-		break;
-	}
-
-	/* select frequency divider and the frequency of VCO */
-	if (freq < 37084) {		/* freq * 96 < 3560000 */
-		multi = 96;
-		reg[5] = 0x82;
-		reg[6] = 0x00;
-	} else if (freq < 55625) {	/* freq * 64 < 3560000 */
-		multi = 64;
-		reg[5] = 0x82;
-		reg[6] = 0x02;
-	} else if (freq < 74167) {	/* freq * 48 < 3560000 */
-		multi = 48;
-		reg[5] = 0x42;
-		reg[6] = 0x00;
-	} else if (freq < 111250) {	/* freq * 32 < 3560000 */
-		multi = 32;
-		reg[5] = 0x42;
-		reg[6] = 0x02;
-	} else if (freq < 148334) {	/* freq * 24 < 3560000 */
-		multi = 24;
-		reg[5] = 0x22;
-		reg[6] = 0x00;
-	} else if (freq < 222500) {	/* freq * 16 < 3560000 */
-		multi = 16;
-		reg[5] = 0x22;
-		reg[6] = 0x02;
-	} else if (freq < 296667) {	/* freq * 12 < 3560000 */
-		multi = 12;
-		reg[5] = 0x12;
-		reg[6] = 0x00;
-	} else if (freq < 445000) {	/* freq * 8 < 3560000 */
-		multi = 8;
-		reg[5] = 0x12;
-		reg[6] = 0x02;
-	} else if (freq < 593334) {	/* freq * 6 < 3560000 */
-		multi = 6;
-		reg[5] = 0x0a;
-		reg[6] = 0x00;
-	} else {
-		multi = 4;
-		reg[5] = 0x0a;
-		reg[6] = 0x02;
-	}
-
-	f_vco = freq * multi;
-
-	if (f_vco >= 3060000) {
-		reg[6] |= 0x08;
-		vco_select = true;
-	}
-
-	if (freq >= 45000) {
-		/* From divided value (XDIV) determined the FA and FP value */
-		xdiv = (unsigned short)(f_vco / xtal_freq_khz_2);
-		if ((f_vco - xdiv * xtal_freq_khz_2) >= (xtal_freq_khz_2 / 2))
-			xdiv++;
-
-		pm = (unsigned char)(xdiv / 8);
-		am = (unsigned char)(xdiv - (8 * pm));
-
-		if (am < 2) {
-			reg[1] = am + 8;
-			reg[2] = pm - 1;
-		} else {
-			reg[1] = am;
-			reg[2] = pm;
-		}
-	} else {
-		/* fix for frequency less than 45 MHz */
-		reg[1] = 0x06;
-		reg[2] = 0x11;
-	}
-
-	/* fix clock out */
-	reg[6] |= 0x20;
-
-	/* From VCO frequency determines the XIN ( fractional part of Delta
-	   Sigma PLL) and divided value (XDIV) */
-	xin = (unsigned short)(f_vco - (f_vco / xtal_freq_khz_2) * xtal_freq_khz_2);
-	xin = (xin << 15) / xtal_freq_khz_2;
-	if (xin >= 16384)
-		xin += 32768;
-
-	reg[3] = xin >> 8;	/* xin with 9 bit resolution */
-	reg[4] = xin & 0xff;
-
-	if (delsys == SYS_DVBT) {
-		reg[6] &= 0x3f;	/* bits 6 and 7 describe the bandwidth */
-		switch (p->bandwidth_hz) {
-		case 6000000:
-			reg[6] |= 0x80;
-			break;
-		case 7000000:
-			reg[6] |= 0x40;
-			break;
-		case 8000000:
-		default:
-			break;
-		}
-	} else {
-		err("%s: modulation type not supported!", __func__);
-		return -EINVAL;
-	}
-
-	/* modified for Realtek demod */
-	reg[5] |= 0x07;
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
-
-	for (i = 1; i <= 6; i++) {
-		ret = fc0012_writereg(priv, i, reg[i]);
-		if (ret)
-			goto exit;
-	}
-
-	/* VCO Calibration */
-	ret = fc0012_writereg(priv, 0x0e, 0x80);
-	if (!ret)
-		ret = fc0012_writereg(priv, 0x0e, 0x00);
-
-	/* VCO Re-Calibration if needed */
-	if (!ret)
-		ret = fc0012_writereg(priv, 0x0e, 0x00);
-
-	if (!ret) {
-		msleep(10);
-		ret = fc0012_readreg(priv, 0x0e, &tmp);
-	}
-	if (ret)
-		goto exit;
-
-	/* vco selection */
-	tmp &= 0x3f;
-
-	if (vco_select) {
-		if (tmp > 0x3c) {
-			reg[6] &= ~0x08;
-			ret = fc0012_writereg(priv, 0x06, reg[6]);
-			if (!ret)
-				ret = fc0012_writereg(priv, 0x0e, 0x80);
-			if (!ret)
-				ret = fc0012_writereg(priv, 0x0e, 0x00);
-		}
-	} else {
-		if (tmp < 0x02) {
-			reg[6] |= 0x08;
-			ret = fc0012_writereg(priv, 0x06, reg[6]);
-			if (!ret)
-				ret = fc0012_writereg(priv, 0x0e, 0x80);
-			if (!ret)
-				ret = fc0012_writereg(priv, 0x0e, 0x00);
-		}
-	}
-
-	priv->frequency = p->frequency;
-	priv->bandwidth = p->bandwidth_hz;
-
-exit:
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
-	if (ret)
-		warn("%s: failed: %d", __func__, ret);
-	return ret;
-}
-
-static int fc0012_get_frequency(struct dvb_frontend *fe, u32 *frequency)
-{
-	struct fc0012_priv *priv = fe->tuner_priv;
-	*frequency = priv->frequency;
-	return 0;
-}
-
-static int fc0012_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
-{
-	/* CHECK: always ? */
-	*frequency = 0;
-	return 0;
-}
-
-static int fc0012_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
-{
-	struct fc0012_priv *priv = fe->tuner_priv;
-	*bandwidth = priv->bandwidth;
-	return 0;
-}
-
-#define INPUT_ADC_LEVEL	-8
-
-static int fc0012_get_rf_strength(struct dvb_frontend *fe, u16 *strength)
-{
-	struct fc0012_priv *priv = fe->tuner_priv;
-	int ret;
-	unsigned char tmp;
-	int int_temp, lna_gain, int_lna, tot_agc_gain, power;
-	const int fc0012_lna_gain_table[] = {
-		/* low gain */
-		-63, -58, -99, -73,
-		-63, -65, -54, -60,
-		/* middle gain */
-		 71,  70,  68,  67,
-		 65,  63,  61,  58,
-		/* high gain */
-		197, 191, 188, 186,
-		184, 182, 181, 179,
-	};
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
-
-	ret = fc0012_writereg(priv, 0x12, 0x00);
-	if (ret)
-		goto err;
-
-	ret = fc0012_readreg(priv, 0x12, &tmp);
-	if (ret)
-		goto err;
-	int_temp = tmp;
-
-	ret = fc0012_readreg(priv, 0x13, &tmp);
-	if (ret)
-		goto err;
-	lna_gain = tmp & 0x1f;
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
-
-	if (lna_gain < ARRAY_SIZE(fc0012_lna_gain_table)) {
-		int_lna = fc0012_lna_gain_table[lna_gain];
-		tot_agc_gain = (abs((int_temp >> 5) - 7) - 2 +
-				(int_temp & 0x1f)) * 2;
-		power = INPUT_ADC_LEVEL - tot_agc_gain - int_lna / 10;
-
-		if (power >= 45)
-			*strength = 255;	/* 100% */
-		else if (power < -95)
-			*strength = 0;
-		else
-			*strength = (power + 95) * 255 / 140;
-
-		*strength |= *strength << 8;
-	} else {
-		ret = -1;
-	}
-
-	goto exit;
-
-err:
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
-exit:
-	if (ret)
-		warn("%s: failed: %d", __func__, ret);
-	return ret;
-}
-
-static const struct dvb_tuner_ops fc0012_tuner_ops = {
-	.info = {
-		.name           = "Fitipower FC0012",
-
-		.frequency_min  = 37000000,	/* estimate */
-		.frequency_max  = 862000000,	/* estimate */
-		.frequency_step = 0,
-	},
-
-	.release	= fc0012_release,
-
-	.init		= fc0012_init,
-	.sleep		= fc0012_sleep,
-
-	.set_params	= fc0012_set_params,
-
-	.get_frequency	= fc0012_get_frequency,
-	.get_if_frequency = fc0012_get_if_frequency,
-	.get_bandwidth	= fc0012_get_bandwidth,
-
-	.get_rf_strength = fc0012_get_rf_strength,
-};
-
-struct dvb_frontend *fc0012_attach(struct dvb_frontend *fe,
-	struct i2c_adapter *i2c, u8 i2c_address, int dual_master,
-	enum fc001x_xtal_freq xtal_freq)
-{
-	struct fc0012_priv *priv = NULL;
-
-	priv = kzalloc(sizeof(struct fc0012_priv), GFP_KERNEL);
-	if (priv == NULL)
-		return NULL;
-
-	priv->i2c = i2c;
-	priv->dual_master = dual_master;
-	priv->addr = i2c_address;
-	priv->xtal_freq = xtal_freq;
-
-	info("Fitipower FC0012 successfully attached.");
-
-	fe->tuner_priv = priv;
-
-	memcpy(&fe->ops.tuner_ops, &fc0012_tuner_ops,
-		sizeof(struct dvb_tuner_ops));
-
-	return fe;
-}
-EXPORT_SYMBOL(fc0012_attach);
-
-MODULE_DESCRIPTION("Fitipower FC0012 silicon tuner driver");
-MODULE_AUTHOR("Hans-Frieder Vogt <hfvogt@gmx.net>");
-MODULE_LICENSE("GPL");
-MODULE_VERSION("0.6");
diff --git a/drivers/media/common/tuners/fc0012.h b/drivers/media/common/tuners/fc0012.h
deleted file mode 100644
index 4dbd5ef..0000000
--- a/drivers/media/common/tuners/fc0012.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Fitipower FC0012 tuner driver - include
- *
- * Copyright (C) 2012 Hans-Frieder Vogt <hfvogt@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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You 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 _FC0012_H_
-#define _FC0012_H_
-
-#include "dvb_frontend.h"
-#include "fc001x-common.h"
-
-#if defined(CONFIG_MEDIA_TUNER_FC0012) || \
-	(defined(CONFIG_MEDIA_TUNER_FC0012_MODULE) && defined(MODULE))
-extern struct dvb_frontend *fc0012_attach(struct dvb_frontend *fe,
-					struct i2c_adapter *i2c,
-					u8 i2c_address, int dual_master,
-					enum fc001x_xtal_freq xtal_freq);
-#else
-static inline struct dvb_frontend *fc0012_attach(struct dvb_frontend *fe,
-					struct i2c_adapter *i2c,
-					u8 i2c_address, int dual_master,
-					enum fc001x_xtal_freq xtal_freq)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif
-
-#endif
diff --git a/drivers/media/common/tuners/fc0013-priv.h b/drivers/media/common/tuners/fc0013-priv.h
deleted file mode 100644
index bfd49de..0000000
--- a/drivers/media/common/tuners/fc0013-priv.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Fitipower FC0013 tuner driver
- *
- * Copyright (C) 2012 Hans-Frieder Vogt <hfvogt@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.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You 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 _FC0013_PRIV_H_
-#define _FC0013_PRIV_H_
-
-#define LOG_PREFIX "fc0013"
-
-#undef err
-#define err(f, arg...)  printk(KERN_ERR     LOG_PREFIX": " f "\n" , ## arg)
-#undef info
-#define info(f, arg...) printk(KERN_INFO    LOG_PREFIX": " f "\n" , ## arg)
-#undef warn
-#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg)
-
-struct fc0013_priv {
-	struct i2c_adapter *i2c;
-	u8 addr;
-	u8 dual_master;
-	u8 xtal_freq;
-
-	u32 frequency;
-	u32 bandwidth;
-};
-
-#endif
diff --git a/drivers/media/common/tuners/fc0013.c b/drivers/media/common/tuners/fc0013.c
deleted file mode 100644
index bd8f0f1..0000000
--- a/drivers/media/common/tuners/fc0013.c
+++ /dev/null
@@ -1,634 +0,0 @@
-/*
- * Fitipower FC0013 tuner driver
- *
- * Copyright (C) 2012 Hans-Frieder Vogt <hfvogt@gmx.net>
- * partially based on driver code from Fitipower
- * Copyright (C) 2010 Fitipower Integrated Technology Inc
- *
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#include "fc0013.h"
-#include "fc0013-priv.h"
-
-static int fc0013_writereg(struct fc0013_priv *priv, u8 reg, u8 val)
-{
-	u8 buf[2] = {reg, val};
-	struct i2c_msg msg = {
-		.addr = priv->addr, .flags = 0, .buf = buf, .len = 2
-	};
-
-	if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
-		err("I2C write reg failed, reg: %02x, val: %02x", reg, val);
-		return -EREMOTEIO;
-	}
-	return 0;
-}
-
-static int fc0013_readreg(struct fc0013_priv *priv, u8 reg, u8 *val)
-{
-	struct i2c_msg msg[2] = {
-		{ .addr = priv->addr, .flags = 0, .buf = &reg, .len = 1 },
-		{ .addr = priv->addr, .flags = I2C_M_RD, .buf = val, .len = 1 },
-	};
-
-	if (i2c_transfer(priv->i2c, msg, 2) != 2) {
-		err("I2C read reg failed, reg: %02x", reg);
-		return -EREMOTEIO;
-	}
-	return 0;
-}
-
-static int fc0013_release(struct dvb_frontend *fe)
-{
-	kfree(fe->tuner_priv);
-	fe->tuner_priv = NULL;
-	return 0;
-}
-
-static int fc0013_init(struct dvb_frontend *fe)
-{
-	struct fc0013_priv *priv = fe->tuner_priv;
-	int i, ret = 0;
-	unsigned char reg[] = {
-		0x00,	/* reg. 0x00: dummy */
-		0x09,	/* reg. 0x01 */
-		0x16,	/* reg. 0x02 */
-		0x00,	/* reg. 0x03 */
-		0x00,	/* reg. 0x04 */
-		0x17,	/* reg. 0x05 */
-		0x02,	/* reg. 0x06 */
-		0x0a,	/* reg. 0x07: CHECK */
-		0xff,	/* reg. 0x08: AGC Clock divide by 256, AGC gain 1/256,
-			   Loop Bw 1/8 */
-		0x6f,	/* reg. 0x09: enable LoopThrough */
-		0xb8,	/* reg. 0x0a: Disable LO Test Buffer */
-		0x82,	/* reg. 0x0b: CHECK */
-		0xfc,	/* reg. 0x0c: depending on AGC Up-Down mode, may need 0xf8 */
-		0x01,	/* reg. 0x0d: AGC Not Forcing & LNA Forcing, may need 0x02 */
-		0x00,	/* reg. 0x0e */
-		0x00,	/* reg. 0x0f */
-		0x00,	/* reg. 0x10 */
-		0x00,	/* reg. 0x11 */
-		0x00,	/* reg. 0x12 */
-		0x00,	/* reg. 0x13 */
-		0x50,	/* reg. 0x14: DVB-t High Gain, UHF.
-			   Middle Gain: 0x48, Low Gain: 0x40 */
-		0x01,	/* reg. 0x15 */
-	};
-
-	switch (priv->xtal_freq) {
-	case FC_XTAL_27_MHZ:
-	case FC_XTAL_28_8_MHZ:
-		reg[0x07] |= 0x20;
-		break;
-	case FC_XTAL_36_MHZ:
-	default:
-		break;
-	}
-
-	if (priv->dual_master)
-		reg[0x0c] |= 0x02;
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
-
-	for (i = 1; i < sizeof(reg); i++) {
-		ret = fc0013_writereg(priv, i, reg[i]);
-		if (ret)
-			break;
-	}
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
-
-	if (ret)
-		err("fc0013_writereg failed: %d", ret);
-
-	return ret;
-}
-
-static int fc0013_sleep(struct dvb_frontend *fe)
-{
-	/* nothing to do here */
-	return 0;
-}
-
-int fc0013_rc_cal_add(struct dvb_frontend *fe, int rc_val)
-{
-	struct fc0013_priv *priv = fe->tuner_priv;
-	int ret;
-	u8 rc_cal;
-	int val;
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
-
-	/* push rc_cal value, get rc_cal value */
-	ret = fc0013_writereg(priv, 0x10, 0x00);
-	if (ret)
-		goto error_out;
-
-	/* get rc_cal value */
-	ret = fc0013_readreg(priv, 0x10, &rc_cal);
-	if (ret)
-		goto error_out;
-
-	rc_cal &= 0x0f;
-
-	val = (int)rc_cal + rc_val;
-
-	/* forcing rc_cal */
-	ret = fc0013_writereg(priv, 0x0d, 0x11);
-	if (ret)
-		goto error_out;
-
-	/* modify rc_cal value */
-	if (val > 15)
-		ret = fc0013_writereg(priv, 0x10, 0x0f);
-	else if (val < 0)
-		ret = fc0013_writereg(priv, 0x10, 0x00);
-	else
-		ret = fc0013_writereg(priv, 0x10, (u8)val);
-
-error_out:
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
-
-	return ret;
-}
-EXPORT_SYMBOL(fc0013_rc_cal_add);
-
-int fc0013_rc_cal_reset(struct dvb_frontend *fe)
-{
-	struct fc0013_priv *priv = fe->tuner_priv;
-	int ret;
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
-
-	ret = fc0013_writereg(priv, 0x0d, 0x01);
-	if (!ret)
-		ret = fc0013_writereg(priv, 0x10, 0x00);
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
-
-	return ret;
-}
-EXPORT_SYMBOL(fc0013_rc_cal_reset);
-
-static int fc0013_set_vhf_track(struct fc0013_priv *priv, u32 freq)
-{
-	int ret;
-	u8 tmp;
-
-	ret = fc0013_readreg(priv, 0x1d, &tmp);
-	if (ret)
-		goto error_out;
-	tmp &= 0xe3;
-	if (freq <= 177500) {		/* VHF Track: 7 */
-		ret = fc0013_writereg(priv, 0x1d, tmp | 0x1c);
-	} else if (freq <= 184500) {	/* VHF Track: 6 */
-		ret = fc0013_writereg(priv, 0x1d, tmp | 0x18);
-	} else if (freq <= 191500) {	/* VHF Track: 5 */
-		ret = fc0013_writereg(priv, 0x1d, tmp | 0x14);
-	} else if (freq <= 198500) {	/* VHF Track: 4 */
-		ret = fc0013_writereg(priv, 0x1d, tmp | 0x10);
-	} else if (freq <= 205500) {	/* VHF Track: 3 */
-		ret = fc0013_writereg(priv, 0x1d, tmp | 0x0c);
-	} else if (freq <= 219500) {	/* VHF Track: 2 */
-		ret = fc0013_writereg(priv, 0x1d, tmp | 0x08);
-	} else if (freq < 300000) {	/* VHF Track: 1 */
-		ret = fc0013_writereg(priv, 0x1d, tmp | 0x04);
-	} else {			/* UHF and GPS */
-		ret = fc0013_writereg(priv, 0x1d, tmp | 0x1c);
-	}
-	if (ret)
-		goto error_out;
-error_out:
-	return ret;
-}
-
-static int fc0013_set_params(struct dvb_frontend *fe)
-{
-	struct fc0013_priv *priv = fe->tuner_priv;
-	int i, ret = 0;
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	u32 freq = p->frequency / 1000;
-	u32 delsys = p->delivery_system;
-	unsigned char reg[7], am, pm, multi, tmp;
-	unsigned long f_vco;
-	unsigned short xtal_freq_khz_2, xin, xdiv;
-	int vco_select = false;
-
-	if (fe->callback) {
-		ret = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER,
-			FC_FE_CALLBACK_VHF_ENABLE, (freq > 300000 ? 0 : 1));
-		if (ret)
-			goto exit;
-	}
-
-	switch (priv->xtal_freq) {
-	case FC_XTAL_27_MHZ:
-		xtal_freq_khz_2 = 27000 / 2;
-		break;
-	case FC_XTAL_36_MHZ:
-		xtal_freq_khz_2 = 36000 / 2;
-		break;
-	case FC_XTAL_28_8_MHZ:
-	default:
-		xtal_freq_khz_2 = 28800 / 2;
-		break;
-	}
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
-
-	/* set VHF track */
-	ret = fc0013_set_vhf_track(priv, freq);
-	if (ret)
-		goto exit;
-
-	if (freq < 300000) {
-		/* enable VHF filter */
-		ret = fc0013_readreg(priv, 0x07, &tmp);
-		if (ret)
-			goto exit;
-		ret = fc0013_writereg(priv, 0x07, tmp | 0x10);
-		if (ret)
-			goto exit;
-
-		/* disable UHF & disable GPS */
-		ret = fc0013_readreg(priv, 0x14, &tmp);
-		if (ret)
-			goto exit;
-		ret = fc0013_writereg(priv, 0x14, tmp & 0x1f);
-		if (ret)
-			goto exit;
-	} else if (freq <= 862000) {
-		/* disable VHF filter */
-		ret = fc0013_readreg(priv, 0x07, &tmp);
-		if (ret)
-			goto exit;
-		ret = fc0013_writereg(priv, 0x07, tmp & 0xef);
-		if (ret)
-			goto exit;
-
-		/* enable UHF & disable GPS */
-		ret = fc0013_readreg(priv, 0x14, &tmp);
-		if (ret)
-			goto exit;
-		ret = fc0013_writereg(priv, 0x14, (tmp & 0x1f) | 0x40);
-		if (ret)
-			goto exit;
-	} else {
-		/* disable VHF filter */
-		ret = fc0013_readreg(priv, 0x07, &tmp);
-		if (ret)
-			goto exit;
-		ret = fc0013_writereg(priv, 0x07, tmp & 0xef);
-		if (ret)
-			goto exit;
-
-		/* disable UHF & enable GPS */
-		ret = fc0013_readreg(priv, 0x14, &tmp);
-		if (ret)
-			goto exit;
-		ret = fc0013_writereg(priv, 0x14, (tmp & 0x1f) | 0x20);
-		if (ret)
-			goto exit;
-	}
-
-	/* select frequency divider and the frequency of VCO */
-	if (freq < 37084) {		/* freq * 96 < 3560000 */
-		multi = 96;
-		reg[5] = 0x82;
-		reg[6] = 0x00;
-	} else if (freq < 55625) {	/* freq * 64 < 3560000 */
-		multi = 64;
-		reg[5] = 0x02;
-		reg[6] = 0x02;
-	} else if (freq < 74167) {	/* freq * 48 < 3560000 */
-		multi = 48;
-		reg[5] = 0x42;
-		reg[6] = 0x00;
-	} else if (freq < 111250) {	/* freq * 32 < 3560000 */
-		multi = 32;
-		reg[5] = 0x82;
-		reg[6] = 0x02;
-	} else if (freq < 148334) {	/* freq * 24 < 3560000 */
-		multi = 24;
-		reg[5] = 0x22;
-		reg[6] = 0x00;
-	} else if (freq < 222500) {	/* freq * 16 < 3560000 */
-		multi = 16;
-		reg[5] = 0x42;
-		reg[6] = 0x02;
-	} else if (freq < 296667) {	/* freq * 12 < 3560000 */
-		multi = 12;
-		reg[5] = 0x12;
-		reg[6] = 0x00;
-	} else if (freq < 445000) {	/* freq * 8 < 3560000 */
-		multi = 8;
-		reg[5] = 0x22;
-		reg[6] = 0x02;
-	} else if (freq < 593334) {	/* freq * 6 < 3560000 */
-		multi = 6;
-		reg[5] = 0x0a;
-		reg[6] = 0x00;
-	} else if (freq < 950000) {	/* freq * 4 < 3800000 */
-		multi = 4;
-		reg[5] = 0x12;
-		reg[6] = 0x02;
-	} else {
-		multi = 2;
-		reg[5] = 0x0a;
-		reg[6] = 0x02;
-	}
-
-	f_vco = freq * multi;
-
-	if (f_vco >= 3060000) {
-		reg[6] |= 0x08;
-		vco_select = true;
-	}
-
-	if (freq >= 45000) {
-		/* From divided value (XDIV) determined the FA and FP value */
-		xdiv = (unsigned short)(f_vco / xtal_freq_khz_2);
-		if ((f_vco - xdiv * xtal_freq_khz_2) >= (xtal_freq_khz_2 / 2))
-			xdiv++;
-
-		pm = (unsigned char)(xdiv / 8);
-		am = (unsigned char)(xdiv - (8 * pm));
-
-		if (am < 2) {
-			reg[1] = am + 8;
-			reg[2] = pm - 1;
-		} else {
-			reg[1] = am;
-			reg[2] = pm;
-		}
-	} else {
-		/* fix for frequency less than 45 MHz */
-		reg[1] = 0x06;
-		reg[2] = 0x11;
-	}
-
-	/* fix clock out */
-	reg[6] |= 0x20;
-
-	/* From VCO frequency determines the XIN ( fractional part of Delta
-	   Sigma PLL) and divided value (XDIV) */
-	xin = (unsigned short)(f_vco - (f_vco / xtal_freq_khz_2) * xtal_freq_khz_2);
-	xin = (xin << 15) / xtal_freq_khz_2;
-	if (xin >= 16384)
-		xin += 32768;
-
-	reg[3] = xin >> 8;
-	reg[4] = xin & 0xff;
-
-	if (delsys == SYS_DVBT) {
-		reg[6] &= 0x3f; /* bits 6 and 7 describe the bandwidth */
-		switch (p->bandwidth_hz) {
-		case 6000000:
-			reg[6] |= 0x80;
-			break;
-		case 7000000:
-			reg[6] |= 0x40;
-			break;
-		case 8000000:
-		default:
-			break;
-		}
-	} else {
-		err("%s: modulation type not supported!", __func__);
-		return -EINVAL;
-	}
-
-	/* modified for Realtek demod */
-	reg[5] |= 0x07;
-
-	for (i = 1; i <= 6; i++) {
-		ret = fc0013_writereg(priv, i, reg[i]);
-		if (ret)
-			goto exit;
-	}
-
-	ret = fc0013_readreg(priv, 0x11, &tmp);
-	if (ret)
-		goto exit;
-	if (multi == 64)
-		ret = fc0013_writereg(priv, 0x11, tmp | 0x04);
-	else
-		ret = fc0013_writereg(priv, 0x11, tmp & 0xfb);
-	if (ret)
-		goto exit;
-
-	/* VCO Calibration */
-	ret = fc0013_writereg(priv, 0x0e, 0x80);
-	if (!ret)
-		ret = fc0013_writereg(priv, 0x0e, 0x00);
-
-	/* VCO Re-Calibration if needed */
-	if (!ret)
-		ret = fc0013_writereg(priv, 0x0e, 0x00);
-
-	if (!ret) {
-		msleep(10);
-		ret = fc0013_readreg(priv, 0x0e, &tmp);
-	}
-	if (ret)
-		goto exit;
-
-	/* vco selection */
-	tmp &= 0x3f;
-
-	if (vco_select) {
-		if (tmp > 0x3c) {
-			reg[6] &= ~0x08;
-			ret = fc0013_writereg(priv, 0x06, reg[6]);
-			if (!ret)
-				ret = fc0013_writereg(priv, 0x0e, 0x80);
-			if (!ret)
-				ret = fc0013_writereg(priv, 0x0e, 0x00);
-		}
-	} else {
-		if (tmp < 0x02) {
-			reg[6] |= 0x08;
-			ret = fc0013_writereg(priv, 0x06, reg[6]);
-			if (!ret)
-				ret = fc0013_writereg(priv, 0x0e, 0x80);
-			if (!ret)
-				ret = fc0013_writereg(priv, 0x0e, 0x00);
-		}
-	}
-
-	priv->frequency = p->frequency;
-	priv->bandwidth = p->bandwidth_hz;
-
-exit:
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
-	if (ret)
-		warn("%s: failed: %d", __func__, ret);
-	return ret;
-}
-
-static int fc0013_get_frequency(struct dvb_frontend *fe, u32 *frequency)
-{
-	struct fc0013_priv *priv = fe->tuner_priv;
-	*frequency = priv->frequency;
-	return 0;
-}
-
-static int fc0013_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
-{
-	/* always ? */
-	*frequency = 0;
-	return 0;
-}
-
-static int fc0013_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
-{
-	struct fc0013_priv *priv = fe->tuner_priv;
-	*bandwidth = priv->bandwidth;
-	return 0;
-}
-
-#define INPUT_ADC_LEVEL	-8
-
-static int fc0013_get_rf_strength(struct dvb_frontend *fe, u16 *strength)
-{
-	struct fc0013_priv *priv = fe->tuner_priv;
-	int ret;
-	unsigned char tmp;
-	int int_temp, lna_gain, int_lna, tot_agc_gain, power;
-	const int fc0013_lna_gain_table[] = {
-		/* low gain */
-		-63, -58, -99, -73,
-		-63, -65, -54, -60,
-		/* middle gain */
-		 71,  70,  68,  67,
-		 65,  63,  61,  58,
-		/* high gain */
-		197, 191, 188, 186,
-		184, 182, 181, 179,
-	};
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
-
-	ret = fc0013_writereg(priv, 0x13, 0x00);
-	if (ret)
-		goto err;
-
-	ret = fc0013_readreg(priv, 0x13, &tmp);
-	if (ret)
-		goto err;
-	int_temp = tmp;
-
-	ret = fc0013_readreg(priv, 0x14, &tmp);
-	if (ret)
-		goto err;
-	lna_gain = tmp & 0x1f;
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
-
-	if (lna_gain < ARRAY_SIZE(fc0013_lna_gain_table)) {
-		int_lna = fc0013_lna_gain_table[lna_gain];
-		tot_agc_gain = (abs((int_temp >> 5) - 7) - 2 +
-				(int_temp & 0x1f)) * 2;
-		power = INPUT_ADC_LEVEL - tot_agc_gain - int_lna / 10;
-
-		if (power >= 45)
-			*strength = 255;	/* 100% */
-		else if (power < -95)
-			*strength = 0;
-		else
-			*strength = (power + 95) * 255 / 140;
-
-		*strength |= *strength << 8;
-	} else {
-		ret = -1;
-	}
-
-	goto exit;
-
-err:
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
-exit:
-	if (ret)
-		warn("%s: failed: %d", __func__, ret);
-	return ret;
-}
-
-static const struct dvb_tuner_ops fc0013_tuner_ops = {
-	.info = {
-		.name		= "Fitipower FC0013",
-
-		.frequency_min	= 37000000,	/* estimate */
-		.frequency_max	= 1680000000,	/* CHECK */
-		.frequency_step	= 0,
-	},
-
-	.release	= fc0013_release,
-
-	.init		= fc0013_init,
-	.sleep		= fc0013_sleep,
-
-	.set_params	= fc0013_set_params,
-
-	.get_frequency	= fc0013_get_frequency,
-	.get_if_frequency = fc0013_get_if_frequency,
-	.get_bandwidth	= fc0013_get_bandwidth,
-
-	.get_rf_strength = fc0013_get_rf_strength,
-};
-
-struct dvb_frontend *fc0013_attach(struct dvb_frontend *fe,
-	struct i2c_adapter *i2c, u8 i2c_address, int dual_master,
-	enum fc001x_xtal_freq xtal_freq)
-{
-	struct fc0013_priv *priv = NULL;
-
-	priv = kzalloc(sizeof(struct fc0013_priv), GFP_KERNEL);
-	if (priv == NULL)
-		return NULL;
-
-	priv->i2c = i2c;
-	priv->dual_master = dual_master;
-	priv->addr = i2c_address;
-	priv->xtal_freq = xtal_freq;
-
-	info("Fitipower FC0013 successfully attached.");
-
-	fe->tuner_priv = priv;
-
-	memcpy(&fe->ops.tuner_ops, &fc0013_tuner_ops,
-		sizeof(struct dvb_tuner_ops));
-
-	return fe;
-}
-EXPORT_SYMBOL(fc0013_attach);
-
-MODULE_DESCRIPTION("Fitipower FC0013 silicon tuner driver");
-MODULE_AUTHOR("Hans-Frieder Vogt <hfvogt@gmx.net>");
-MODULE_LICENSE("GPL");
-MODULE_VERSION("0.2");
diff --git a/drivers/media/common/tuners/fc0013.h b/drivers/media/common/tuners/fc0013.h
deleted file mode 100644
index 594efd6..0000000
--- a/drivers/media/common/tuners/fc0013.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Fitipower FC0013 tuner driver
- *
- * Copyright (C) 2012 Hans-Frieder Vogt <hfvogt@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.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You 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 _FC0013_H_
-#define _FC0013_H_
-
-#include "dvb_frontend.h"
-#include "fc001x-common.h"
-
-#if defined(CONFIG_MEDIA_TUNER_FC0013) || \
-	(defined(CONFIG_MEDIA_TUNER_FC0013_MODULE) && defined(MODULE))
-extern struct dvb_frontend *fc0013_attach(struct dvb_frontend *fe,
-					struct i2c_adapter *i2c,
-					u8 i2c_address, int dual_master,
-					enum fc001x_xtal_freq xtal_freq);
-extern int fc0013_rc_cal_add(struct dvb_frontend *fe, int rc_val);
-extern int fc0013_rc_cal_reset(struct dvb_frontend *fe);
-#else
-static inline struct dvb_frontend *fc0013_attach(struct dvb_frontend *fe,
-					struct i2c_adapter *i2c,
-					u8 i2c_address, int dual_master,
-					enum fc001x_xtal_freq xtal_freq)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-
-static inline int fc0013_rc_cal_add(struct dvb_frontend *fe, int rc_val)
-{
-	return 0;
-}
-
-static inline int fc0013_rc_cal_reset(struct dvb_frontend *fe)
-{
-	return 0;
-}
-#endif
-
-#endif
diff --git a/drivers/media/common/tuners/fc001x-common.h b/drivers/media/common/tuners/fc001x-common.h
deleted file mode 100644
index 7188181..0000000
--- a/drivers/media/common/tuners/fc001x-common.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Fitipower FC0012 & FC0013 tuner driver - common defines
- *
- * Copyright (C) 2012 Hans-Frieder Vogt <hfvogt@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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You 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 _FC001X_COMMON_H_
-#define _FC001X_COMMON_H_
-
-enum fc001x_xtal_freq {
-	FC_XTAL_27_MHZ,		/* 27000000 */
-	FC_XTAL_28_8_MHZ,	/* 28800000 */
-	FC_XTAL_36_MHZ,		/* 36000000 */
-};
-
-/*
- * enum fc001x_fe_callback_commands - Frontend callbacks
- *
- * @FC_FE_CALLBACK_VHF_ENABLE: enable VHF or UHF
- */
-enum fc001x_fe_callback_commands {
-	FC_FE_CALLBACK_VHF_ENABLE,
-};
-
-#endif
diff --git a/drivers/media/common/tuners/max2165.c b/drivers/media/common/tuners/max2165.c
deleted file mode 100644
index ba84936..0000000
--- a/drivers/media/common/tuners/max2165.c
+++ /dev/null
@@ -1,433 +0,0 @@
-/*
- *  Driver for Maxim MAX2165 silicon tuner
- *
- *  Copyright (c) 2009 David T. L. Wong <davidtlwong@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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/videodev2.h>
-#include <linux/delay.h>
-#include <linux/dvb/frontend.h>
-#include <linux/i2c.h>
-#include <linux/slab.h>
-
-#include "dvb_frontend.h"
-
-#include "max2165.h"
-#include "max2165_priv.h"
-#include "tuner-i2c.h"
-
-#define dprintk(args...) \
-	do { \
-		if (debug) \
-			printk(KERN_DEBUG "max2165: " args); \
-	} while (0)
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
-
-static int max2165_write_reg(struct max2165_priv *priv, u8 reg, u8 data)
-{
-	int ret;
-	u8 buf[] = { reg, data };
-	struct i2c_msg msg = { .flags = 0, .buf = buf, .len = 2 };
-
-	msg.addr = priv->config->i2c_address;
-
-	if (debug >= 2)
-		dprintk("%s: reg=0x%02X, data=0x%02X\n", __func__, reg, data);
-
-	ret = i2c_transfer(priv->i2c, &msg, 1);
-
-	if (ret != 1)
-		dprintk("%s: error reg=0x%x, data=0x%x, ret=%i\n",
-			__func__, reg, data, ret);
-
-	return (ret != 1) ? -EIO : 0;
-}
-
-static int max2165_read_reg(struct max2165_priv *priv, u8 reg, u8 *p_data)
-{
-	int ret;
-	u8 dev_addr = priv->config->i2c_address;
-
-	u8 b0[] = { reg };
-	u8 b1[] = { 0 };
-	struct i2c_msg msg[] = {
-		{ .addr = dev_addr, .flags = 0, .buf = b0, .len = 1 },
-		{ .addr = dev_addr, .flags = I2C_M_RD, .buf = b1, .len = 1 },
-	};
-
-	ret = i2c_transfer(priv->i2c, msg, 2);
-	if (ret != 2) {
-		dprintk("%s: error reg=0x%x, ret=%i\n", __func__, reg, ret);
-		return -EIO;
-	}
-
-	*p_data = b1[0];
-	if (debug >= 2)
-		dprintk("%s: reg=0x%02X, data=0x%02X\n",
-			__func__, reg, b1[0]);
-	return 0;
-}
-
-static int max2165_mask_write_reg(struct max2165_priv *priv, u8 reg,
-	u8 mask, u8 data)
-{
-	int ret;
-	u8 v;
-
-	data &= mask;
-	ret = max2165_read_reg(priv, reg, &v);
-	if (ret != 0)
-		return ret;
-	v &= ~mask;
-	v |= data;
-	ret = max2165_write_reg(priv, reg, v);
-
-	return ret;
-}
-
-static int max2165_read_rom_table(struct max2165_priv *priv)
-{
-	u8 dat[3];
-	int i;
-
-	for (i = 0; i < 3; i++) {
-		max2165_write_reg(priv, REG_ROM_TABLE_ADDR, i + 1);
-		max2165_read_reg(priv, REG_ROM_TABLE_DATA, &dat[i]);
-	}
-
-	priv->tf_ntch_low_cfg = dat[0] >> 4;
-	priv->tf_ntch_hi_cfg = dat[0] & 0x0F;
-	priv->tf_balun_low_ref = dat[1] & 0x0F;
-	priv->tf_balun_hi_ref = dat[1] >> 4;
-	priv->bb_filter_7mhz_cfg = dat[2] & 0x0F;
-	priv->bb_filter_8mhz_cfg = dat[2] >> 4;
-
-	dprintk("tf_ntch_low_cfg = 0x%X\n", priv->tf_ntch_low_cfg);
-	dprintk("tf_ntch_hi_cfg = 0x%X\n", priv->tf_ntch_hi_cfg);
-	dprintk("tf_balun_low_ref = 0x%X\n", priv->tf_balun_low_ref);
-	dprintk("tf_balun_hi_ref = 0x%X\n", priv->tf_balun_hi_ref);
-	dprintk("bb_filter_7mhz_cfg = 0x%X\n", priv->bb_filter_7mhz_cfg);
-	dprintk("bb_filter_8mhz_cfg = 0x%X\n", priv->bb_filter_8mhz_cfg);
-
-	return 0;
-}
-
-static int max2165_set_osc(struct max2165_priv *priv, u8 osc /*MHz*/)
-{
-	u8 v;
-
-	v = (osc / 2);
-	if (v == 2)
-		v = 0x7;
-	else
-		v -= 8;
-
-	max2165_mask_write_reg(priv, REG_PLL_CFG, 0x07, v);
-
-	return 0;
-}
-
-static int max2165_set_bandwidth(struct max2165_priv *priv, u32 bw)
-{
-	u8 val;
-
-	if (bw == 8000000)
-		val = priv->bb_filter_8mhz_cfg;
-	else
-		val = priv->bb_filter_7mhz_cfg;
-
-	max2165_mask_write_reg(priv, REG_BASEBAND_CTRL, 0xF0, val << 4);
-
-	return 0;
-}
-
-int fixpt_div32(u32 dividend, u32 divisor, u32 *quotient, u32 *fraction)
-{
-	u32 remainder;
-	u32 q, f = 0;
-	int i;
-
-	if (0 == divisor)
-		return -EINVAL;
-
-	q = dividend / divisor;
-	remainder = dividend - q * divisor;
-
-	for (i = 0; i < 31; i++) {
-		remainder <<= 1;
-		if (remainder >= divisor) {
-			f += 1;
-			remainder -= divisor;
-		}
-		f <<= 1;
-	}
-
-	*quotient = q;
-	*fraction = f;
-
-	return 0;
-}
-
-static int max2165_set_rf(struct max2165_priv *priv, u32 freq)
-{
-	u8 tf;
-	u8 tf_ntch;
-	u32 t;
-	u32 quotient, fraction;
-	int ret;
-
-	/* Set PLL divider according to RF frequency */
-	ret = fixpt_div32(freq / 1000, priv->config->osc_clk * 1000,
-			 &quotient, &fraction);
-	if (ret != 0)
-		return ret;
-
-	/* 20-bit fraction */
-	fraction >>= 12;
-
-	max2165_write_reg(priv, REG_NDIV_INT, quotient);
-	max2165_mask_write_reg(priv, REG_NDIV_FRAC2, 0x0F, fraction >> 16);
-	max2165_write_reg(priv, REG_NDIV_FRAC1, fraction >> 8);
-	max2165_write_reg(priv, REG_NDIV_FRAC0, fraction);
-
-	/* Norch Filter */
-	tf_ntch = (freq < 725000000) ?
-		priv->tf_ntch_low_cfg : priv->tf_ntch_hi_cfg;
-
-	/* Tracking filter balun */
-	t = priv->tf_balun_low_ref;
-	t += (priv->tf_balun_hi_ref - priv->tf_balun_low_ref)
-		* (freq / 1000 - 470000) / (780000 - 470000);
-
-	tf = t;
-	dprintk("tf = %X\n", tf);
-	tf |= tf_ntch << 4;
-
-	max2165_write_reg(priv, REG_TRACK_FILTER, tf);
-
-	return 0;
-}
-
-static void max2165_debug_status(struct max2165_priv *priv)
-{
-	u8 status, autotune;
-	u8 auto_vco_success, auto_vco_active;
-	u8 pll_locked;
-	u8 dc_offset_low, dc_offset_hi;
-	u8 signal_lv_over_threshold;
-	u8 vco, vco_sub_band, adc;
-
-	max2165_read_reg(priv, REG_STATUS, &status);
-	max2165_read_reg(priv, REG_AUTOTUNE, &autotune);
-
-	auto_vco_success = (status >> 6) & 0x01;
-	auto_vco_active = (status >> 5) & 0x01;
-	pll_locked = (status >> 4) & 0x01;
-	dc_offset_low = (status >> 3) & 0x01;
-	dc_offset_hi = (status >> 2) & 0x01;
-	signal_lv_over_threshold = status & 0x01;
-
-	vco = autotune >> 6;
-	vco_sub_band = (autotune >> 3) & 0x7;
-	adc = autotune & 0x7;
-
-	dprintk("auto VCO active: %d, auto VCO success: %d\n",
-		auto_vco_active, auto_vco_success);
-	dprintk("PLL locked: %d\n", pll_locked);
-	dprintk("DC offset low: %d, DC offset high: %d\n",
-		dc_offset_low, dc_offset_hi);
-	dprintk("Signal lvl over threshold: %d\n", signal_lv_over_threshold);
-	dprintk("VCO: %d, VCO Sub-band: %d, ADC: %d\n", vco, vco_sub_band, adc);
-}
-
-static int max2165_set_params(struct dvb_frontend *fe)
-{
-	struct max2165_priv *priv = fe->tuner_priv;
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	int ret;
-
-	switch (c->bandwidth_hz) {
-	case 7000000:
-	case 8000000:
-		priv->frequency = c->frequency;
-		break;
-	default:
-		printk(KERN_INFO "MAX2165: bandwidth %d Hz not supported.\n",
-		       c->bandwidth_hz);
-		return -EINVAL;
-	}
-
-	dprintk("%s() frequency=%d\n", __func__, c->frequency);
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	max2165_set_bandwidth(priv, c->bandwidth_hz);
-	ret = max2165_set_rf(priv, priv->frequency);
-	mdelay(50);
-	max2165_debug_status(priv);
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0);
-
-	if (ret != 0)
-		return -EREMOTEIO;
-
-	return 0;
-}
-
-static int max2165_get_frequency(struct dvb_frontend *fe, u32 *freq)
-{
-	struct max2165_priv *priv = fe->tuner_priv;
-	dprintk("%s()\n", __func__);
-	*freq = priv->frequency;
-	return 0;
-}
-
-static int max2165_get_bandwidth(struct dvb_frontend *fe, u32 *bw)
-{
-	struct max2165_priv *priv = fe->tuner_priv;
-	dprintk("%s()\n", __func__);
-
-	*bw = priv->bandwidth;
-	return 0;
-}
-
-static int max2165_get_status(struct dvb_frontend *fe, u32 *status)
-{
-	struct max2165_priv *priv = fe->tuner_priv;
-	u16 lock_status = 0;
-
-	dprintk("%s()\n", __func__);
-
-	if (fe->ops.i2c_gate_ctrl)
-			fe->ops.i2c_gate_ctrl(fe, 1);
-
-	max2165_debug_status(priv);
-	*status = lock_status;
-
-	if (fe->ops.i2c_gate_ctrl)
-			fe->ops.i2c_gate_ctrl(fe, 0);
-
-	return 0;
-}
-
-static int max2165_sleep(struct dvb_frontend *fe)
-{
-	dprintk("%s()\n", __func__);
-	return 0;
-}
-
-static int max2165_init(struct dvb_frontend *fe)
-{
-	struct max2165_priv *priv = fe->tuner_priv;
-	dprintk("%s()\n", __func__);
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-
-	/* Setup initial values */
-	/* Fractional Mode on */
-	max2165_write_reg(priv, REG_NDIV_FRAC2, 0x18);
-	/* LNA on */
-	max2165_write_reg(priv, REG_LNA, 0x01);
-	max2165_write_reg(priv, REG_PLL_CFG, 0x7A);
-	max2165_write_reg(priv, REG_TEST, 0x08);
-	max2165_write_reg(priv, REG_SHUTDOWN, 0x40);
-	max2165_write_reg(priv, REG_VCO_CTRL, 0x84);
-	max2165_write_reg(priv, REG_BASEBAND_CTRL, 0xC3);
-	max2165_write_reg(priv, REG_DC_OFFSET_CTRL, 0x75);
-	max2165_write_reg(priv, REG_DC_OFFSET_DAC, 0x00);
-	max2165_write_reg(priv, REG_ROM_TABLE_ADDR, 0x00);
-
-	max2165_set_osc(priv, priv->config->osc_clk);
-
-	max2165_read_rom_table(priv);
-
-	max2165_set_bandwidth(priv, 8000000);
-
-	if (fe->ops.i2c_gate_ctrl)
-			fe->ops.i2c_gate_ctrl(fe, 0);
-
-	return 0;
-}
-
-static int max2165_release(struct dvb_frontend *fe)
-{
-	struct max2165_priv *priv = fe->tuner_priv;
-	dprintk("%s()\n", __func__);
-
-	kfree(priv);
-	fe->tuner_priv = NULL;
-
-	return 0;
-}
-
-static const struct dvb_tuner_ops max2165_tuner_ops = {
-	.info = {
-		.name           = "Maxim MAX2165",
-		.frequency_min  = 470000000,
-		.frequency_max  = 780000000,
-		.frequency_step =     50000,
-	},
-
-	.release	   = max2165_release,
-	.init		   = max2165_init,
-	.sleep		   = max2165_sleep,
-
-	.set_params	   = max2165_set_params,
-	.set_analog_params = NULL,
-	.get_frequency	   = max2165_get_frequency,
-	.get_bandwidth	   = max2165_get_bandwidth,
-	.get_status	   = max2165_get_status
-};
-
-struct dvb_frontend *max2165_attach(struct dvb_frontend *fe,
-				   struct i2c_adapter *i2c,
-				   struct max2165_config *cfg)
-{
-	struct max2165_priv *priv = NULL;
-
-	dprintk("%s(%d-%04x)\n", __func__,
-		i2c ? i2c_adapter_id(i2c) : -1,
-		cfg ? cfg->i2c_address : -1);
-
-	priv = kzalloc(sizeof(struct max2165_priv), GFP_KERNEL);
-	if (priv == NULL)
-		return NULL;
-
-	memcpy(&fe->ops.tuner_ops, &max2165_tuner_ops,
-		sizeof(struct dvb_tuner_ops));
-
-	priv->config = cfg;
-	priv->i2c = i2c;
-	fe->tuner_priv = priv;
-
-	max2165_init(fe);
-	max2165_debug_status(priv);
-
-	return fe;
-}
-EXPORT_SYMBOL(max2165_attach);
-
-MODULE_AUTHOR("David T. L. Wong <davidtlwong@gmail.com>");
-MODULE_DESCRIPTION("Maxim MAX2165 silicon tuner driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/common/tuners/max2165.h b/drivers/media/common/tuners/max2165.h
deleted file mode 100644
index c063c36..0000000
--- a/drivers/media/common/tuners/max2165.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- *  Driver for Maxim MAX2165 silicon tuner
- *
- *  Copyright (c) 2009 David T. L. Wong <davidtlwong@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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef __MAX2165_H__
-#define __MAX2165_H__
-
-struct dvb_frontend;
-struct i2c_adapter;
-
-struct max2165_config {
-	u8 i2c_address;
-	u8 osc_clk; /* in MHz, selectable values: 4,16,18,20,22,24,26,28 */
-};
-
-#if defined(CONFIG_MEDIA_TUNER_MAX2165) || \
-    (defined(CONFIG_MEDIA_TUNER_MAX2165_MODULE) && defined(MODULE))
-extern struct dvb_frontend *max2165_attach(struct dvb_frontend *fe,
-	struct i2c_adapter *i2c,
-	struct max2165_config *cfg);
-#else
-static inline struct dvb_frontend *max2165_attach(struct dvb_frontend *fe,
-	struct i2c_adapter *i2c,
-	struct max2165_config *cfg)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif
-
-#endif
diff --git a/drivers/media/common/tuners/max2165_priv.h b/drivers/media/common/tuners/max2165_priv.h
deleted file mode 100644
index 91bbe02..0000000
--- a/drivers/media/common/tuners/max2165_priv.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- *  Driver for Maxim MAX2165 silicon tuner
- *
- *  Copyright (c) 2009 David T. L. Wong <davidtlwong@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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef __MAX2165_PRIV_H__
-#define __MAX2165_PRIV_H__
-
-#define REG_NDIV_INT 0x00
-#define REG_NDIV_FRAC2 0x01
-#define REG_NDIV_FRAC1 0x02
-#define REG_NDIV_FRAC0 0x03
-#define REG_TRACK_FILTER 0x04
-#define REG_LNA 0x05
-#define REG_PLL_CFG 0x06
-#define REG_TEST 0x07
-#define REG_SHUTDOWN 0x08
-#define REG_VCO_CTRL 0x09
-#define REG_BASEBAND_CTRL 0x0A
-#define REG_DC_OFFSET_CTRL 0x0B
-#define REG_DC_OFFSET_DAC 0x0C
-#define REG_ROM_TABLE_ADDR 0x0D
-
-/* Read Only Registers */
-#define REG_ROM_TABLE_DATA 0x10
-#define REG_STATUS 0x11
-#define REG_AUTOTUNE 0x12
-
-struct max2165_priv {
-	struct max2165_config *config;
-	struct i2c_adapter *i2c;
-
-	u32 frequency;
-	u32 bandwidth;
-
-	u8 tf_ntch_low_cfg;
-	u8 tf_ntch_hi_cfg;
-	u8 tf_balun_low_ref;
-	u8 tf_balun_hi_ref;
-	u8 bb_filter_7mhz_cfg;
-	u8 bb_filter_8mhz_cfg;
-};
-
-#endif
diff --git a/drivers/media/common/tuners/mc44s803.c b/drivers/media/common/tuners/mc44s803.c
deleted file mode 100644
index 5ddce7e..0000000
--- a/drivers/media/common/tuners/mc44s803.c
+++ /dev/null
@@ -1,372 +0,0 @@
-/*
- *  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 <linux/slab.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 mc44s803_priv *priv = fe->tuner_priv;
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	u32 r1, r2, n1, n2, lo1, lo2, freq, val;
-	int err;
-
-	priv->frequency = c->frequency;
-
-	r1 = MC44S803_OSC / 1000000;
-	r2 = MC44S803_OSC /  100000;
-
-	n1 = (c->frequency + MC44S803_IF1 + 500000) / 1000000;
-	freq = MC44S803_OSC / r1 * n1;
-	lo1 = ((60 * n1) + (r1 / 2)) / r1;
-	freq = freq - c->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
deleted file mode 100644
index 34f3892..0000000
--- a/drivers/media/common/tuners/mc44s803.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- *  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
deleted file mode 100644
index 14a9278..0000000
--- a/drivers/media/common/tuners/mc44s803_priv.h
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- *  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
deleted file mode 100644
index 13381de..0000000
--- a/drivers/media/common/tuners/mt2060.c
+++ /dev/null
@@ -1,403 +0,0 @@
-/*
- *  Driver for Microtune MT2060 "Single chip dual conversion broadband tuner"
- *
- *  Copyright (c) 2006 Olivier DANET <odanet@caramail.com>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.=
- */
-
-/* In that file, frequencies are expressed in kiloHertz to avoid 32 bits overflows */
-
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/dvb/frontend.h>
-#include <linux/i2c.h>
-#include <linux/slab.h>
-
-#include "dvb_frontend.h"
-
-#include "mt2060.h"
-#include "mt2060_priv.h"
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
-
-#define dprintk(args...) do { if (debug) {printk(KERN_DEBUG "MT2060: " args); printk("\n"); }} while (0)
-
-// Reads a single register
-static int mt2060_readreg(struct mt2060_priv *priv, u8 reg, u8 *val)
-{
-	struct i2c_msg msg[2] = {
-		{ .addr = priv->cfg->i2c_address, .flags = 0,        .buf = &reg, .len = 1 },
-		{ .addr = priv->cfg->i2c_address, .flags = I2C_M_RD, .buf = val,  .len = 1 },
-	};
-
-	if (i2c_transfer(priv->i2c, msg, 2) != 2) {
-		printk(KERN_WARNING "mt2060 I2C read failed\n");
-		return -EREMOTEIO;
-	}
-	return 0;
-}
-
-// Writes a single register
-static int mt2060_writereg(struct mt2060_priv *priv, u8 reg, u8 val)
-{
-	u8 buf[2] = { reg, val };
-	struct i2c_msg msg = {
-		.addr = priv->cfg->i2c_address, .flags = 0, .buf = buf, .len = 2
-	};
-
-	if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
-		printk(KERN_WARNING "mt2060 I2C write failed\n");
-		return -EREMOTEIO;
-	}
-	return 0;
-}
-
-// Writes a set of consecutive registers
-static int mt2060_writeregs(struct mt2060_priv *priv,u8 *buf, u8 len)
-{
-	struct i2c_msg msg = {
-		.addr = priv->cfg->i2c_address, .flags = 0, .buf = buf, .len = len
-	};
-	if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
-		printk(KERN_WARNING "mt2060 I2C write failed (len=%i)\n",(int)len);
-		return -EREMOTEIO;
-	}
-	return 0;
-}
-
-// Initialisation sequences
-// LNABAND=3, NUM1=0x3C, DIV1=0x74, NUM2=0x1080, DIV2=0x49
-static u8 mt2060_config1[] = {
-	REG_LO1C1,
-	0x3F,	0x74,	0x00,	0x08,	0x93
-};
-
-// FMCG=2, GP2=0, GP1=0
-static u8 mt2060_config2[] = {
-	REG_MISC_CTRL,
-	0x20,	0x1E,	0x30,	0xff,	0x80,	0xff,	0x00,	0x2c,	0x42
-};
-
-//  VGAG=3, V1CSE=1
-
-#ifdef  MT2060_SPURCHECK
-/* The function below calculates the frequency offset between the output frequency if2
- and the closer cross modulation subcarrier between lo1 and lo2 up to the tenth harmonic */
-static int mt2060_spurcalc(u32 lo1,u32 lo2,u32 if2)
-{
-	int I,J;
-	int dia,diamin,diff;
-	diamin=1000000;
-	for (I = 1; I < 10; I++) {
-		J = ((2*I*lo1)/lo2+1)/2;
-		diff = I*(int)lo1-J*(int)lo2;
-		if (diff < 0) diff=-diff;
-		dia = (diff-(int)if2);
-		if (dia < 0) dia=-dia;
-		if (diamin > dia) diamin=dia;
-	}
-	return diamin;
-}
-
-#define BANDWIDTH 4000 // kHz
-
-/* Calculates the frequency offset to add to avoid spurs. Returns 0 if no offset is needed */
-static int mt2060_spurcheck(u32 lo1,u32 lo2,u32 if2)
-{
-	u32 Spur,Sp1,Sp2;
-	int I,J;
-	I=0;
-	J=1000;
-
-	Spur=mt2060_spurcalc(lo1,lo2,if2);
-	if (Spur < BANDWIDTH) {
-		/* Potential spurs detected */
-		dprintk("Spurs before : f_lo1: %d  f_lo2: %d  (kHz)",
-			(int)lo1,(int)lo2);
-		I=1000;
-		Sp1 = mt2060_spurcalc(lo1+I,lo2+I,if2);
-		Sp2 = mt2060_spurcalc(lo1-I,lo2-I,if2);
-
-		if (Sp1 < Sp2) {
-			J=-J; I=-I; Spur=Sp2;
-		} else
-			Spur=Sp1;
-
-		while (Spur < BANDWIDTH) {
-			I += J;
-			Spur = mt2060_spurcalc(lo1+I,lo2+I,if2);
-		}
-		dprintk("Spurs after  : f_lo1: %d  f_lo2: %d  (kHz)",
-			(int)(lo1+I),(int)(lo2+I));
-	}
-	return I;
-}
-#endif
-
-#define IF2  36150       // IF2 frequency = 36.150 MHz
-#define FREF 16000       // Quartz oscillator 16 MHz
-
-static int mt2060_set_params(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	struct mt2060_priv *priv;
-	int ret=0;
-	int i=0;
-	u32 freq;
-	u8  lnaband;
-	u32 f_lo1,f_lo2;
-	u32 div1,num1,div2,num2;
-	u8  b[8];
-	u32 if1;
-
-	priv = fe->tuner_priv;
-
-	if1 = priv->if1_freq;
-	b[0] = REG_LO1B1;
-	b[1] = 0xFF;
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */
-
-	mt2060_writeregs(priv,b,2);
-
-	freq = c->frequency / 1000; /* Hz -> kHz */
-
-	f_lo1 = freq + if1 * 1000;
-	f_lo1 = (f_lo1 / 250) * 250;
-	f_lo2 = f_lo1 - freq - IF2;
-	// From the Comtech datasheet, the step used is 50kHz. The tuner chip could be more precise
-	f_lo2 = ((f_lo2 + 25) / 50) * 50;
-	priv->frequency =  (f_lo1 - f_lo2 - IF2) * 1000,
-
-#ifdef MT2060_SPURCHECK
-	// LO-related spurs detection and correction
-	num1   = mt2060_spurcheck(f_lo1,f_lo2,IF2);
-	f_lo1 += num1;
-	f_lo2 += num1;
-#endif
-	//Frequency LO1 = 16MHz * (DIV1 + NUM1/64 )
-	num1 = f_lo1 / (FREF / 64);
-	div1 = num1 / 64;
-	num1 &= 0x3f;
-
-	// Frequency LO2 = 16MHz * (DIV2 + NUM2/8192 )
-	num2 = f_lo2 * 64 / (FREF / 128);
-	div2 = num2 / 8192;
-	num2 &= 0x1fff;
-
-	if (freq <=  95000) lnaband = 0xB0; else
-	if (freq <= 180000) lnaband = 0xA0; else
-	if (freq <= 260000) lnaband = 0x90; else
-	if (freq <= 335000) lnaband = 0x80; else
-	if (freq <= 425000) lnaband = 0x70; else
-	if (freq <= 480000) lnaband = 0x60; else
-	if (freq <= 570000) lnaband = 0x50; else
-	if (freq <= 645000) lnaband = 0x40; else
-	if (freq <= 730000) lnaband = 0x30; else
-	if (freq <= 810000) lnaband = 0x20; else lnaband = 0x10;
-
-	b[0] = REG_LO1C1;
-	b[1] = lnaband | ((num1 >>2) & 0x0F);
-	b[2] = div1;
-	b[3] = (num2 & 0x0F)  | ((num1 & 3) << 4);
-	b[4] = num2 >> 4;
-	b[5] = ((num2 >>12) & 1) | (div2 << 1);
-
-	dprintk("IF1: %dMHz",(int)if1);
-	dprintk("PLL freq=%dkHz  f_lo1=%dkHz  f_lo2=%dkHz",(int)freq,(int)f_lo1,(int)f_lo2);
-	dprintk("PLL div1=%d  num1=%d  div2=%d  num2=%d",(int)div1,(int)num1,(int)div2,(int)num2);
-	dprintk("PLL [1..5]: %2x %2x %2x %2x %2x",(int)b[1],(int)b[2],(int)b[3],(int)b[4],(int)b[5]);
-
-	mt2060_writeregs(priv,b,6);
-
-	//Waits for pll lock or timeout
-	i = 0;
-	do {
-		mt2060_readreg(priv,REG_LO_STATUS,b);
-		if ((b[0] & 0x88)==0x88)
-			break;
-		msleep(4);
-		i++;
-	} while (i<10);
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */
-
-	return ret;
-}
-
-static void mt2060_calibrate(struct mt2060_priv *priv)
-{
-	u8 b = 0;
-	int i = 0;
-
-	if (mt2060_writeregs(priv,mt2060_config1,sizeof(mt2060_config1)))
-		return;
-	if (mt2060_writeregs(priv,mt2060_config2,sizeof(mt2060_config2)))
-		return;
-
-	/* initialize the clock output */
-	mt2060_writereg(priv, REG_VGAG, (priv->cfg->clock_out << 6) | 0x30);
-
-	do {
-		b |= (1 << 6); // FM1SS;
-		mt2060_writereg(priv, REG_LO2C1,b);
-		msleep(20);
-
-		if (i == 0) {
-			b |= (1 << 7); // FM1CA;
-			mt2060_writereg(priv, REG_LO2C1,b);
-			b &= ~(1 << 7); // FM1CA;
-			msleep(20);
-		}
-
-		b &= ~(1 << 6); // FM1SS
-		mt2060_writereg(priv, REG_LO2C1,b);
-
-		msleep(20);
-		i++;
-	} while (i < 9);
-
-	i = 0;
-	while (i++ < 10 && mt2060_readreg(priv, REG_MISC_STAT, &b) == 0 && (b & (1 << 6)) == 0)
-		msleep(20);
-
-	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
-		dprintk("FMCAL timed out");
-}
-
-static int mt2060_get_frequency(struct dvb_frontend *fe, u32 *frequency)
-{
-	struct mt2060_priv *priv = fe->tuner_priv;
-	*frequency = priv->frequency;
-	return 0;
-}
-
-static int mt2060_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
-{
-	*frequency = IF2 * 1000;
-	return 0;
-}
-
-static int mt2060_init(struct dvb_frontend *fe)
-{
-	struct mt2060_priv *priv = fe->tuner_priv;
-	int ret;
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */
-
-	ret = mt2060_writereg(priv, REG_VGAG,
-			      (priv->cfg->clock_out << 6) | 0x33);
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */
-
-	return ret;
-}
-
-static int mt2060_sleep(struct dvb_frontend *fe)
-{
-	struct mt2060_priv *priv = fe->tuner_priv;
-	int ret;
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */
-
-	ret = mt2060_writereg(priv, REG_VGAG,
-			      (priv->cfg->clock_out << 6) | 0x30);
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */
-
-	return ret;
-}
-
-static int mt2060_release(struct dvb_frontend *fe)
-{
-	kfree(fe->tuner_priv);
-	fe->tuner_priv = NULL;
-	return 0;
-}
-
-static const struct dvb_tuner_ops mt2060_tuner_ops = {
-	.info = {
-		.name           = "Microtune MT2060",
-		.frequency_min  =  48000000,
-		.frequency_max  = 860000000,
-		.frequency_step =     50000,
-	},
-
-	.release       = mt2060_release,
-
-	.init          = mt2060_init,
-	.sleep         = mt2060_sleep,
-
-	.set_params    = mt2060_set_params,
-	.get_frequency = mt2060_get_frequency,
-	.get_if_frequency = mt2060_get_if_frequency,
-};
-
-/* This functions tries to identify a MT2060 tuner by reading the PART/REV register. This is hasty. */
-struct dvb_frontend * mt2060_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct mt2060_config *cfg, u16 if1)
-{
-	struct mt2060_priv *priv = NULL;
-	u8 id = 0;
-
-	priv = kzalloc(sizeof(struct mt2060_priv), GFP_KERNEL);
-	if (priv == NULL)
-		return NULL;
-
-	priv->cfg      = cfg;
-	priv->i2c      = i2c;
-	priv->if1_freq = if1;
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */
-
-	if (mt2060_readreg(priv,REG_PART_REV,&id) != 0) {
-		kfree(priv);
-		return NULL;
-	}
-
-	if (id != PART_REV) {
-		kfree(priv);
-		return NULL;
-	}
-	printk(KERN_INFO "MT2060: successfully identified (IF1 = %d)\n", if1);
-	memcpy(&fe->ops.tuner_ops, &mt2060_tuner_ops, sizeof(struct dvb_tuner_ops));
-
-	fe->tuner_priv = priv;
-
-	mt2060_calibrate(priv);
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */
-
-	return fe;
-}
-EXPORT_SYMBOL(mt2060_attach);
-
-MODULE_AUTHOR("Olivier DANET");
-MODULE_DESCRIPTION("Microtune MT2060 silicon tuner driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/common/tuners/mt2060.h b/drivers/media/common/tuners/mt2060.h
deleted file mode 100644
index cb60caf..0000000
--- a/drivers/media/common/tuners/mt2060.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- *  Driver for Microtune MT2060 "Single chip dual conversion broadband tuner"
- *
- *  Copyright (c) 2006 Olivier DANET <odanet@caramail.com>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.=
- */
-
-#ifndef MT2060_H
-#define MT2060_H
-
-struct dvb_frontend;
-struct i2c_adapter;
-
-struct mt2060_config {
-	u8 i2c_address;
-	u8 clock_out; /* 0 = off, 1 = CLK/4, 2 = CLK/2, 3 = CLK/1 */
-};
-
-#if defined(CONFIG_MEDIA_TUNER_MT2060) || (defined(CONFIG_MEDIA_TUNER_MT2060_MODULE) && defined(MODULE))
-extern struct dvb_frontend * mt2060_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct mt2060_config *cfg, u16 if1);
-#else
-static inline struct dvb_frontend * mt2060_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct mt2060_config *cfg, u16 if1)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif // CONFIG_MEDIA_TUNER_MT2060
-
-#endif
diff --git a/drivers/media/common/tuners/mt2060_priv.h b/drivers/media/common/tuners/mt2060_priv.h
deleted file mode 100644
index 2b60de6..0000000
--- a/drivers/media/common/tuners/mt2060_priv.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- *  Driver for Microtune MT2060 "Single chip dual conversion broadband tuner"
- *
- *  Copyright (c) 2006 Olivier DANET <odanet@caramail.com>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.=
- */
-
-#ifndef MT2060_PRIV_H
-#define MT2060_PRIV_H
-
-// Uncomment the #define below to enable spurs checking. The results where quite unconvincing.
-// #define MT2060_SPURCHECK
-
-/* This driver is based on the information available in the datasheet of the
-   "Comtech SDVBT-3K6M" tuner ( K1000737843.pdf ) which features the MT2060 register map :
-
-   I2C Address : 0x60
-
-   Reg.No |   B7   |   B6   |   B5   |   B4   |   B3   |   B2   |   B1   |   B0   | ( defaults )
-   --------------------------------------------------------------------------------
-       00 | [              PART             ] | [              REV              ] | R  = 0x63
-       01 | [             LNABAND           ] | [              NUM1(5:2)        ] | RW = 0x3F
-       02 | [                               DIV1                                ] | RW = 0x74
-       03 | FM1CA  | FM1SS  | [  NUM1(1:0)  ] | [              NUM2(3:0)        ] | RW = 0x00
-       04 |                                 NUM2(11:4)                          ] | RW = 0x08
-       05 | [                               DIV2                       ] |NUM2(12)| RW = 0x93
-       06 | L1LK   | [        TAD1          ] | L2LK   | [         TAD2         ] | R
-       07 | [                               FMF                                 ] | R
-       08 |   ?    | FMCAL  |   ?    |   ?    |   ?    |   ?    |   ?    | TEMP   | R
-       09 |   0    |   0    | [    FMGC     ] |   0    | GP02   | GP01   |   0    | RW = 0x20
-       0A | ??
-       0B |   0    |   0    |   1    |   1    |   0    |   0    | [   VGAG      ] | RW = 0x30
-       0C | V1CSE  |   1    |   1    |   1    |   1    |   1    |   1    |   1    | RW = 0xFF
-       0D |   1    |   0    | [                      V1CS                       ] | RW = 0xB0
-       0E | ??
-       0F | ??
-       10 | ??
-       11 | [             LOTO              ] |   0    |   0    |   1    |   0    | RW = 0x42
-
-       PART    : Part code      : 6 for MT2060
-       REV     : Revision code  : 3 for current revision
-       LNABAND : Input frequency range : ( See code for details )
-       NUM1 / DIV1 / NUM2 / DIV2 : Frequencies programming ( See code for details )
-       FM1CA  : Calibration Start Bit
-       FM1SS  : Calibration Single Step bit
-       L1LK   : LO1 Lock Detect
-       TAD1   : Tune Line ADC ( ? )
-       L2LK   : LO2 Lock Detect
-       TAD2   : Tune Line ADC ( ? )
-       FMF    : Estimated first IF Center frequency Offset ( ? )
-       FM1CAL : Calibration done bit
-       TEMP   : On chip temperature sensor
-       FMCG   : Mixer 1 Cap Gain ( ? )
-       GP01 / GP02 : Programmable digital outputs. Unconnected pins ?
-       V1CSE  : LO1 VCO Automatic Capacitor Select Enable ( ? )
-       V1CS   : LO1 Capacitor Selection Value ( ? )
-       LOTO   : LO Timeout ( ? )
-       VGAG   : Tuner Output gain
-*/
-
-#define I2C_ADDRESS 0x60
-
-#define REG_PART_REV   0
-#define REG_LO1C1      1
-#define REG_LO1C2      2
-#define REG_LO2C1      3
-#define REG_LO2C2      4
-#define REG_LO2C3      5
-#define REG_LO_STATUS  6
-#define REG_FM_FREQ    7
-#define REG_MISC_STAT  8
-#define REG_MISC_CTRL  9
-#define REG_RESERVED_A 0x0A
-#define REG_VGAG       0x0B
-#define REG_LO1B1      0x0C
-#define REG_LO1B2      0x0D
-#define REG_LOTO       0x11
-
-#define PART_REV 0x63 // The current driver works only with PART=6 and REV=3 chips
-
-struct mt2060_priv {
-	struct mt2060_config *cfg;
-	struct i2c_adapter   *i2c;
-
-	u32 frequency;
-	u16 if1_freq;
-	u8  fmfreq;
-};
-
-#endif
diff --git a/drivers/media/common/tuners/mt2063.c b/drivers/media/common/tuners/mt2063.c
deleted file mode 100644
index 0ed9091..0000000
--- a/drivers/media/common/tuners/mt2063.c
+++ /dev/null
@@ -1,2307 +0,0 @@
-/*
- * Driver for mt2063 Micronas tuner
- *
- * Copyright (c) 2011 Mauro Carvalho Chehab <mchehab@redhat.com>
- *
- * This driver came from a driver originally written by:
- *		Henry Wang <Henry.wang@AzureWave.com>
- * Made publicly available by Terratec, at:
- *	http://linux.terratec.de/files/TERRATEC_H7/20110323_TERRATEC_H7_Linux.tar.gz
- * The original driver's license is GPL, as declared with MODULE_LICENSE()
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation under version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/videodev2.h>
-
-#include "mt2063.h"
-
-static unsigned int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Set Verbosity level");
-
-#define dprintk(level, fmt, arg...) do {				\
-if (debug >= level)							\
-	printk(KERN_DEBUG "mt2063 %s: " fmt, __func__, ## arg);	\
-} while (0)
-
-
-/* positive error codes used internally */
-
-/*  Info: Unavoidable LO-related spur may be present in the output  */
-#define MT2063_SPUR_PRESENT_ERR             (0x00800000)
-
-/*  Info: Mask of bits used for # of LO-related spurs that were avoided during tuning  */
-#define MT2063_SPUR_CNT_MASK                (0x001f0000)
-#define MT2063_SPUR_SHIFT                   (16)
-
-/*  Info: Upconverter frequency is out of range (may be reason for MT_UPC_UNLOCK) */
-#define MT2063_UPC_RANGE                    (0x04000000)
-
-/*  Info: Downconverter frequency is out of range (may be reason for MT_DPC_UNLOCK) */
-#define MT2063_DNC_RANGE                    (0x08000000)
-
-/*
- *  Constant defining the version of the following structure
- *  and therefore the API for this code.
- *
- *  When compiling the tuner driver, the preprocessor will
- *  check against this version number to make sure that
- *  it matches the version that the tuner driver knows about.
- */
-
-/* DECT Frequency Avoidance */
-#define MT2063_DECT_AVOID_US_FREQS      0x00000001
-
-#define MT2063_DECT_AVOID_EURO_FREQS    0x00000002
-
-#define MT2063_EXCLUDE_US_DECT_FREQUENCIES(s) (((s) & MT2063_DECT_AVOID_US_FREQS) != 0)
-
-#define MT2063_EXCLUDE_EURO_DECT_FREQUENCIES(s) (((s) & MT2063_DECT_AVOID_EURO_FREQS) != 0)
-
-enum MT2063_DECT_Avoid_Type {
-	MT2063_NO_DECT_AVOIDANCE = 0,				/* Do not create DECT exclusion zones.     */
-	MT2063_AVOID_US_DECT = MT2063_DECT_AVOID_US_FREQS,	/* Avoid US DECT frequencies.              */
-	MT2063_AVOID_EURO_DECT = MT2063_DECT_AVOID_EURO_FREQS,	/* Avoid European DECT frequencies.        */
-	MT2063_AVOID_BOTH					/* Avoid both regions. Not typically used. */
-};
-
-#define MT2063_MAX_ZONES 48
-
-struct MT2063_ExclZone_t {
-	u32 min_;
-	u32 max_;
-	struct MT2063_ExclZone_t *next_;
-};
-
-/*
- *  Structure of data needed for Spur Avoidance
- */
-struct MT2063_AvoidSpursData_t {
-	u32 f_ref;
-	u32 f_in;
-	u32 f_LO1;
-	u32 f_if1_Center;
-	u32 f_if1_Request;
-	u32 f_if1_bw;
-	u32 f_LO2;
-	u32 f_out;
-	u32 f_out_bw;
-	u32 f_LO1_Step;
-	u32 f_LO2_Step;
-	u32 f_LO1_FracN_Avoid;
-	u32 f_LO2_FracN_Avoid;
-	u32 f_zif_bw;
-	u32 f_min_LO_Separation;
-	u32 maxH1;
-	u32 maxH2;
-	enum MT2063_DECT_Avoid_Type avoidDECT;
-	u32 bSpurPresent;
-	u32 bSpurAvoided;
-	u32 nSpursFound;
-	u32 nZones;
-	struct MT2063_ExclZone_t *freeZones;
-	struct MT2063_ExclZone_t *usedZones;
-	struct MT2063_ExclZone_t MT2063_ExclZones[MT2063_MAX_ZONES];
-};
-
-/*
- * Parameter for function MT2063_SetPowerMask that specifies the power down
- * of various sections of the MT2063.
- */
-enum MT2063_Mask_Bits {
-	MT2063_REG_SD = 0x0040,		/* Shutdown regulator                 */
-	MT2063_SRO_SD = 0x0020,		/* Shutdown SRO                       */
-	MT2063_AFC_SD = 0x0010,		/* Shutdown AFC A/D                   */
-	MT2063_PD_SD = 0x0002,		/* Enable power detector shutdown     */
-	MT2063_PDADC_SD = 0x0001,	/* Enable power detector A/D shutdown */
-	MT2063_VCO_SD = 0x8000,		/* Enable VCO shutdown                */
-	MT2063_LTX_SD = 0x4000,		/* Enable LTX shutdown                */
-	MT2063_LT1_SD = 0x2000,		/* Enable LT1 shutdown                */
-	MT2063_LNA_SD = 0x1000,		/* Enable LNA shutdown                */
-	MT2063_UPC_SD = 0x0800,		/* Enable upconverter shutdown        */
-	MT2063_DNC_SD = 0x0400,		/* Enable downconverter shutdown      */
-	MT2063_VGA_SD = 0x0200,		/* Enable VGA shutdown                */
-	MT2063_AMP_SD = 0x0100,		/* Enable AMP shutdown                */
-	MT2063_ALL_SD = 0xFF73,		/* All shutdown bits for this tuner   */
-	MT2063_NONE_SD = 0x0000		/* No shutdown bits                   */
-};
-
-/*
- *  Possible values for MT2063_DNC_OUTPUT
- */
-enum MT2063_DNC_Output_Enable {
-	MT2063_DNC_NONE = 0,
-	MT2063_DNC_1,
-	MT2063_DNC_2,
-	MT2063_DNC_BOTH
-};
-
-/*
- *  Two-wire serial bus subaddresses of the tuner registers.
- *  Also known as the tuner's register addresses.
- */
-enum MT2063_Register_Offsets {
-	MT2063_REG_PART_REV = 0,	/*  0x00: Part/Rev Code         */
-	MT2063_REG_LO1CQ_1,		/*  0x01: LO1C Queued Byte 1    */
-	MT2063_REG_LO1CQ_2,		/*  0x02: LO1C Queued Byte 2    */
-	MT2063_REG_LO2CQ_1,		/*  0x03: LO2C Queued Byte 1    */
-	MT2063_REG_LO2CQ_2,		/*  0x04: LO2C Queued Byte 2    */
-	MT2063_REG_LO2CQ_3,		/*  0x05: LO2C Queued Byte 3    */
-	MT2063_REG_RSVD_06,		/*  0x06: Reserved              */
-	MT2063_REG_LO_STATUS,		/*  0x07: LO Status             */
-	MT2063_REG_FIFFC,		/*  0x08: FIFF Center           */
-	MT2063_REG_CLEARTUNE,		/*  0x09: ClearTune Filter      */
-	MT2063_REG_ADC_OUT,		/*  0x0A: ADC_OUT               */
-	MT2063_REG_LO1C_1,		/*  0x0B: LO1C Byte 1           */
-	MT2063_REG_LO1C_2,		/*  0x0C: LO1C Byte 2           */
-	MT2063_REG_LO2C_1,		/*  0x0D: LO2C Byte 1           */
-	MT2063_REG_LO2C_2,		/*  0x0E: LO2C Byte 2           */
-	MT2063_REG_LO2C_3,		/*  0x0F: LO2C Byte 3           */
-	MT2063_REG_RSVD_10,		/*  0x10: Reserved              */
-	MT2063_REG_PWR_1,		/*  0x11: PWR Byte 1            */
-	MT2063_REG_PWR_2,		/*  0x12: PWR Byte 2            */
-	MT2063_REG_TEMP_STATUS,		/*  0x13: Temp Status           */
-	MT2063_REG_XO_STATUS,		/*  0x14: Crystal Status        */
-	MT2063_REG_RF_STATUS,		/*  0x15: RF Attn Status        */
-	MT2063_REG_FIF_STATUS,		/*  0x16: FIF Attn Status       */
-	MT2063_REG_LNA_OV,		/*  0x17: LNA Attn Override     */
-	MT2063_REG_RF_OV,		/*  0x18: RF Attn Override      */
-	MT2063_REG_FIF_OV,		/*  0x19: FIF Attn Override     */
-	MT2063_REG_LNA_TGT,		/*  0x1A: Reserved              */
-	MT2063_REG_PD1_TGT,		/*  0x1B: Pwr Det 1 Target      */
-	MT2063_REG_PD2_TGT,		/*  0x1C: Pwr Det 2 Target      */
-	MT2063_REG_RSVD_1D,		/*  0x1D: Reserved              */
-	MT2063_REG_RSVD_1E,		/*  0x1E: Reserved              */
-	MT2063_REG_RSVD_1F,		/*  0x1F: Reserved              */
-	MT2063_REG_RSVD_20,		/*  0x20: Reserved              */
-	MT2063_REG_BYP_CTRL,		/*  0x21: Bypass Control        */
-	MT2063_REG_RSVD_22,		/*  0x22: Reserved              */
-	MT2063_REG_RSVD_23,		/*  0x23: Reserved              */
-	MT2063_REG_RSVD_24,		/*  0x24: Reserved              */
-	MT2063_REG_RSVD_25,		/*  0x25: Reserved              */
-	MT2063_REG_RSVD_26,		/*  0x26: Reserved              */
-	MT2063_REG_RSVD_27,		/*  0x27: Reserved              */
-	MT2063_REG_FIFF_CTRL,		/*  0x28: FIFF Control          */
-	MT2063_REG_FIFF_OFFSET,		/*  0x29: FIFF Offset           */
-	MT2063_REG_CTUNE_CTRL,		/*  0x2A: Reserved              */
-	MT2063_REG_CTUNE_OV,		/*  0x2B: Reserved              */
-	MT2063_REG_CTRL_2C,		/*  0x2C: Reserved              */
-	MT2063_REG_FIFF_CTRL2,		/*  0x2D: Fiff Control          */
-	MT2063_REG_RSVD_2E,		/*  0x2E: Reserved              */
-	MT2063_REG_DNC_GAIN,		/*  0x2F: DNC Control           */
-	MT2063_REG_VGA_GAIN,		/*  0x30: VGA Gain Ctrl         */
-	MT2063_REG_RSVD_31,		/*  0x31: Reserved              */
-	MT2063_REG_TEMP_SEL,		/*  0x32: Temperature Selection */
-	MT2063_REG_RSVD_33,		/*  0x33: Reserved              */
-	MT2063_REG_RSVD_34,		/*  0x34: Reserved              */
-	MT2063_REG_RSVD_35,		/*  0x35: Reserved              */
-	MT2063_REG_RSVD_36,		/*  0x36: Reserved              */
-	MT2063_REG_RSVD_37,		/*  0x37: Reserved              */
-	MT2063_REG_RSVD_38,		/*  0x38: Reserved              */
-	MT2063_REG_RSVD_39,		/*  0x39: Reserved              */
-	MT2063_REG_RSVD_3A,		/*  0x3A: Reserved              */
-	MT2063_REG_RSVD_3B,		/*  0x3B: Reserved              */
-	MT2063_REG_RSVD_3C,		/*  0x3C: Reserved              */
-	MT2063_REG_END_REGS
-};
-
-struct mt2063_state {
-	struct i2c_adapter *i2c;
-
-	bool init;
-
-	const struct mt2063_config *config;
-	struct dvb_tuner_ops ops;
-	struct dvb_frontend *frontend;
-	struct tuner_state status;
-
-	u32 frequency;
-	u32 srate;
-	u32 bandwidth;
-	u32 reference;
-
-	u32 tuner_id;
-	struct MT2063_AvoidSpursData_t AS_Data;
-	u32 f_IF1_actual;
-	u32 rcvr_mode;
-	u32 ctfilt_sw;
-	u32 CTFiltMax[31];
-	u32 num_regs;
-	u8 reg[MT2063_REG_END_REGS];
-};
-
-/*
- * mt2063_write - Write data into the I2C bus
- */
-static u32 mt2063_write(struct mt2063_state *state, u8 reg, u8 *data, u32 len)
-{
-	struct dvb_frontend *fe = state->frontend;
-	int ret;
-	u8 buf[60];
-	struct i2c_msg msg = {
-		.addr = state->config->tuner_address,
-		.flags = 0,
-		.buf = buf,
-		.len = len + 1
-	};
-
-	dprintk(2, "\n");
-
-	msg.buf[0] = reg;
-	memcpy(msg.buf + 1, data, len);
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	ret = i2c_transfer(state->i2c, &msg, 1);
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0);
-
-	if (ret < 0)
-		printk(KERN_ERR "%s error ret=%d\n", __func__, ret);
-
-	return ret;
-}
-
-/*
- * mt2063_write - Write register data into the I2C bus, caching the value
- */
-static u32 mt2063_setreg(struct mt2063_state *state, u8 reg, u8 val)
-{
-	u32 status;
-
-	dprintk(2, "\n");
-
-	if (reg >= MT2063_REG_END_REGS)
-		return -ERANGE;
-
-	status = mt2063_write(state, reg, &val, 1);
-	if (status < 0)
-		return status;
-
-	state->reg[reg] = val;
-
-	return 0;
-}
-
-/*
- * mt2063_read - Read data from the I2C bus
- */
-static u32 mt2063_read(struct mt2063_state *state,
-			   u8 subAddress, u8 *pData, u32 cnt)
-{
-	u32 status = 0;	/* Status to be returned        */
-	struct dvb_frontend *fe = state->frontend;
-	u32 i = 0;
-
-	dprintk(2, "addr 0x%02x, cnt %d\n", subAddress, cnt);
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-
-	for (i = 0; i < cnt; i++) {
-		u8 b0[] = { subAddress + i };
-		struct i2c_msg msg[] = {
-			{
-				.addr = state->config->tuner_address,
-				.flags = 0,
-				.buf = b0,
-				.len = 1
-			}, {
-				.addr = state->config->tuner_address,
-				.flags = I2C_M_RD,
-				.buf = pData + i,
-				.len = 1
-			}
-		};
-
-		status = i2c_transfer(state->i2c, msg, 2);
-		dprintk(2, "addr 0x%02x, ret = %d, val = 0x%02x\n",
-			   subAddress + i, status, *(pData + i));
-		if (status < 0)
-			break;
-	}
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0);
-
-	if (status < 0)
-		printk(KERN_ERR "Can't read from address 0x%02x,\n",
-		       subAddress + i);
-
-	return status;
-}
-
-/*
- * FIXME: Is this really needed?
- */
-static int MT2063_Sleep(struct dvb_frontend *fe)
-{
-	/*
-	 *  ToDo:  Add code here to implement a OS blocking
-	 */
-	msleep(100);
-
-	return 0;
-}
-
-/*
- * Microtune spur avoidance
- */
-
-/*  Implement ceiling, floor functions.  */
-#define ceil(n, d) (((n) < 0) ? (-((-(n))/(d))) : (n)/(d) + ((n)%(d) != 0))
-#define floor(n, d) (((n) < 0) ? (-((-(n))/(d))) - ((n)%(d) != 0) : (n)/(d))
-
-struct MT2063_FIFZone_t {
-	s32 min_;
-	s32 max_;
-};
-
-static struct MT2063_ExclZone_t *InsertNode(struct MT2063_AvoidSpursData_t
-					    *pAS_Info,
-					    struct MT2063_ExclZone_t *pPrevNode)
-{
-	struct MT2063_ExclZone_t *pNode;
-
-	dprintk(2, "\n");
-
-	/*  Check for a node in the free list  */
-	if (pAS_Info->freeZones != NULL) {
-		/*  Use one from the free list  */
-		pNode = pAS_Info->freeZones;
-		pAS_Info->freeZones = pNode->next_;
-	} else {
-		/*  Grab a node from the array  */
-		pNode = &pAS_Info->MT2063_ExclZones[pAS_Info->nZones];
-	}
-
-	if (pPrevNode != NULL) {
-		pNode->next_ = pPrevNode->next_;
-		pPrevNode->next_ = pNode;
-	} else {		/*  insert at the beginning of the list  */
-
-		pNode->next_ = pAS_Info->usedZones;
-		pAS_Info->usedZones = pNode;
-	}
-
-	pAS_Info->nZones++;
-	return pNode;
-}
-
-static struct MT2063_ExclZone_t *RemoveNode(struct MT2063_AvoidSpursData_t
-					    *pAS_Info,
-					    struct MT2063_ExclZone_t *pPrevNode,
-					    struct MT2063_ExclZone_t
-					    *pNodeToRemove)
-{
-	struct MT2063_ExclZone_t *pNext = pNodeToRemove->next_;
-
-	dprintk(2, "\n");
-
-	/*  Make previous node point to the subsequent node  */
-	if (pPrevNode != NULL)
-		pPrevNode->next_ = pNext;
-
-	/*  Add pNodeToRemove to the beginning of the freeZones  */
-	pNodeToRemove->next_ = pAS_Info->freeZones;
-	pAS_Info->freeZones = pNodeToRemove;
-
-	/*  Decrement node count  */
-	pAS_Info->nZones--;
-
-	return pNext;
-}
-
-/*
- * MT_AddExclZone()
- *
- * Add (and merge) an exclusion zone into the list.
- * If the range (f_min, f_max) is totally outside the
- * 1st IF BW, ignore the entry.
- * If the range (f_min, f_max) is negative, ignore the entry.
- */
-static void MT2063_AddExclZone(struct MT2063_AvoidSpursData_t *pAS_Info,
-			       u32 f_min, u32 f_max)
-{
-	struct MT2063_ExclZone_t *pNode = pAS_Info->usedZones;
-	struct MT2063_ExclZone_t *pPrev = NULL;
-	struct MT2063_ExclZone_t *pNext = NULL;
-
-	dprintk(2, "\n");
-
-	/*  Check to see if this overlaps the 1st IF filter  */
-	if ((f_max > (pAS_Info->f_if1_Center - (pAS_Info->f_if1_bw / 2)))
-	    && (f_min < (pAS_Info->f_if1_Center + (pAS_Info->f_if1_bw / 2)))
-	    && (f_min < f_max)) {
-		/*
-		 *                1        2         3      4       5        6
-		 *
-		 *   New entry:  |---|    |--|      |--|    |-|    |---|    |--|
-		 *                or       or        or     or      or
-		 *   Existing:  |--|      |--|      |--|    |---|  |-|      |--|
-		 */
-
-		/*  Check for our place in the list  */
-		while ((pNode != NULL) && (pNode->max_ < f_min)) {
-			pPrev = pNode;
-			pNode = pNode->next_;
-		}
-
-		if ((pNode != NULL) && (pNode->min_ < f_max)) {
-			/*  Combine me with pNode  */
-			if (f_min < pNode->min_)
-				pNode->min_ = f_min;
-			if (f_max > pNode->max_)
-				pNode->max_ = f_max;
-		} else {
-			pNode = InsertNode(pAS_Info, pPrev);
-			pNode->min_ = f_min;
-			pNode->max_ = f_max;
-		}
-
-		/*  Look for merging possibilities  */
-		pNext = pNode->next_;
-		while ((pNext != NULL) && (pNext->min_ < pNode->max_)) {
-			if (pNext->max_ > pNode->max_)
-				pNode->max_ = pNext->max_;
-			/*  Remove pNext, return ptr to pNext->next  */
-			pNext = RemoveNode(pAS_Info, pNode, pNext);
-		}
-	}
-}
-
-/*
- *  Reset all exclusion zones.
- *  Add zones to protect the PLL FracN regions near zero
- */
-static void MT2063_ResetExclZones(struct MT2063_AvoidSpursData_t *pAS_Info)
-{
-	u32 center;
-
-	dprintk(2, "\n");
-
-	pAS_Info->nZones = 0;	/*  this clears the used list  */
-	pAS_Info->usedZones = NULL;	/*  reset ptr                  */
-	pAS_Info->freeZones = NULL;	/*  reset ptr                  */
-
-	center =
-	    pAS_Info->f_ref *
-	    ((pAS_Info->f_if1_Center - pAS_Info->f_if1_bw / 2 +
-	      pAS_Info->f_in) / pAS_Info->f_ref) - pAS_Info->f_in;
-	while (center <
-	       pAS_Info->f_if1_Center + pAS_Info->f_if1_bw / 2 +
-	       pAS_Info->f_LO1_FracN_Avoid) {
-		/*  Exclude LO1 FracN  */
-		MT2063_AddExclZone(pAS_Info,
-				   center - pAS_Info->f_LO1_FracN_Avoid,
-				   center - 1);
-		MT2063_AddExclZone(pAS_Info, center + 1,
-				   center + pAS_Info->f_LO1_FracN_Avoid);
-		center += pAS_Info->f_ref;
-	}
-
-	center =
-	    pAS_Info->f_ref *
-	    ((pAS_Info->f_if1_Center - pAS_Info->f_if1_bw / 2 -
-	      pAS_Info->f_out) / pAS_Info->f_ref) + pAS_Info->f_out;
-	while (center <
-	       pAS_Info->f_if1_Center + pAS_Info->f_if1_bw / 2 +
-	       pAS_Info->f_LO2_FracN_Avoid) {
-		/*  Exclude LO2 FracN  */
-		MT2063_AddExclZone(pAS_Info,
-				   center - pAS_Info->f_LO2_FracN_Avoid,
-				   center - 1);
-		MT2063_AddExclZone(pAS_Info, center + 1,
-				   center + pAS_Info->f_LO2_FracN_Avoid);
-		center += pAS_Info->f_ref;
-	}
-
-	if (MT2063_EXCLUDE_US_DECT_FREQUENCIES(pAS_Info->avoidDECT)) {
-		/*  Exclude LO1 values that conflict with DECT channels */
-		MT2063_AddExclZone(pAS_Info, 1920836000 - pAS_Info->f_in, 1922236000 - pAS_Info->f_in);	/* Ctr = 1921.536 */
-		MT2063_AddExclZone(pAS_Info, 1922564000 - pAS_Info->f_in, 1923964000 - pAS_Info->f_in);	/* Ctr = 1923.264 */
-		MT2063_AddExclZone(pAS_Info, 1924292000 - pAS_Info->f_in, 1925692000 - pAS_Info->f_in);	/* Ctr = 1924.992 */
-		MT2063_AddExclZone(pAS_Info, 1926020000 - pAS_Info->f_in, 1927420000 - pAS_Info->f_in);	/* Ctr = 1926.720 */
-		MT2063_AddExclZone(pAS_Info, 1927748000 - pAS_Info->f_in, 1929148000 - pAS_Info->f_in);	/* Ctr = 1928.448 */
-	}
-
-	if (MT2063_EXCLUDE_EURO_DECT_FREQUENCIES(pAS_Info->avoidDECT)) {
-		MT2063_AddExclZone(pAS_Info, 1896644000 - pAS_Info->f_in, 1898044000 - pAS_Info->f_in);	/* Ctr = 1897.344 */
-		MT2063_AddExclZone(pAS_Info, 1894916000 - pAS_Info->f_in, 1896316000 - pAS_Info->f_in);	/* Ctr = 1895.616 */
-		MT2063_AddExclZone(pAS_Info, 1893188000 - pAS_Info->f_in, 1894588000 - pAS_Info->f_in);	/* Ctr = 1893.888 */
-		MT2063_AddExclZone(pAS_Info, 1891460000 - pAS_Info->f_in, 1892860000 - pAS_Info->f_in);	/* Ctr = 1892.16  */
-		MT2063_AddExclZone(pAS_Info, 1889732000 - pAS_Info->f_in, 1891132000 - pAS_Info->f_in);	/* Ctr = 1890.432 */
-		MT2063_AddExclZone(pAS_Info, 1888004000 - pAS_Info->f_in, 1889404000 - pAS_Info->f_in);	/* Ctr = 1888.704 */
-		MT2063_AddExclZone(pAS_Info, 1886276000 - pAS_Info->f_in, 1887676000 - pAS_Info->f_in);	/* Ctr = 1886.976 */
-		MT2063_AddExclZone(pAS_Info, 1884548000 - pAS_Info->f_in, 1885948000 - pAS_Info->f_in);	/* Ctr = 1885.248 */
-		MT2063_AddExclZone(pAS_Info, 1882820000 - pAS_Info->f_in, 1884220000 - pAS_Info->f_in);	/* Ctr = 1883.52  */
-		MT2063_AddExclZone(pAS_Info, 1881092000 - pAS_Info->f_in, 1882492000 - pAS_Info->f_in);	/* Ctr = 1881.792 */
-	}
-}
-
-/*
- * MT_ChooseFirstIF - Choose the best available 1st IF
- *                    If f_Desired is not excluded, choose that first.
- *                    Otherwise, return the value closest to f_Center that is
- *                    not excluded
- */
-static u32 MT2063_ChooseFirstIF(struct MT2063_AvoidSpursData_t *pAS_Info)
-{
-	/*
-	 * Update "f_Desired" to be the nearest "combinational-multiple" of
-	 * "f_LO1_Step".
-	 * The resulting number, F_LO1 must be a multiple of f_LO1_Step.
-	 * And F_LO1 is the arithmetic sum of f_in + f_Center.
-	 * Neither f_in, nor f_Center must be a multiple of f_LO1_Step.
-	 * However, the sum must be.
-	 */
-	const u32 f_Desired =
-	    pAS_Info->f_LO1_Step *
-	    ((pAS_Info->f_if1_Request + pAS_Info->f_in +
-	      pAS_Info->f_LO1_Step / 2) / pAS_Info->f_LO1_Step) -
-	    pAS_Info->f_in;
-	const u32 f_Step =
-	    (pAS_Info->f_LO1_Step >
-	     pAS_Info->f_LO2_Step) ? pAS_Info->f_LO1_Step : pAS_Info->
-	    f_LO2_Step;
-	u32 f_Center;
-	s32 i;
-	s32 j = 0;
-	u32 bDesiredExcluded = 0;
-	u32 bZeroExcluded = 0;
-	s32 tmpMin, tmpMax;
-	s32 bestDiff;
-	struct MT2063_ExclZone_t *pNode = pAS_Info->usedZones;
-	struct MT2063_FIFZone_t zones[MT2063_MAX_ZONES];
-
-	dprintk(2, "\n");
-
-	if (pAS_Info->nZones == 0)
-		return f_Desired;
-
-	/*
-	 *  f_Center needs to be an integer multiple of f_Step away
-	 *  from f_Desired
-	 */
-	if (pAS_Info->f_if1_Center > f_Desired)
-		f_Center =
-		    f_Desired +
-		    f_Step *
-		    ((pAS_Info->f_if1_Center - f_Desired +
-		      f_Step / 2) / f_Step);
-	else
-		f_Center =
-		    f_Desired -
-		    f_Step *
-		    ((f_Desired - pAS_Info->f_if1_Center +
-		      f_Step / 2) / f_Step);
-
-	/*
-	 * Take MT_ExclZones, center around f_Center and change the
-	 * resolution to f_Step
-	 */
-	while (pNode != NULL) {
-		/*  floor function  */
-		tmpMin =
-		    floor((s32) (pNode->min_ - f_Center), (s32) f_Step);
-
-		/*  ceil function  */
-		tmpMax =
-		    ceil((s32) (pNode->max_ - f_Center), (s32) f_Step);
-
-		if ((pNode->min_ < f_Desired) && (pNode->max_ > f_Desired))
-			bDesiredExcluded = 1;
-
-		if ((tmpMin < 0) && (tmpMax > 0))
-			bZeroExcluded = 1;
-
-		/*  See if this zone overlaps the previous  */
-		if ((j > 0) && (tmpMin < zones[j - 1].max_))
-			zones[j - 1].max_ = tmpMax;
-		else {
-			/*  Add new zone  */
-			zones[j].min_ = tmpMin;
-			zones[j].max_ = tmpMax;
-			j++;
-		}
-		pNode = pNode->next_;
-	}
-
-	/*
-	 *  If the desired is okay, return with it
-	 */
-	if (bDesiredExcluded == 0)
-		return f_Desired;
-
-	/*
-	 *  If the desired is excluded and the center is okay, return with it
-	 */
-	if (bZeroExcluded == 0)
-		return f_Center;
-
-	/*  Find the value closest to 0 (f_Center)  */
-	bestDiff = zones[0].min_;
-	for (i = 0; i < j; i++) {
-		if (abs(zones[i].min_) < abs(bestDiff))
-			bestDiff = zones[i].min_;
-		if (abs(zones[i].max_) < abs(bestDiff))
-			bestDiff = zones[i].max_;
-	}
-
-	if (bestDiff < 0)
-		return f_Center - ((u32) (-bestDiff) * f_Step);
-
-	return f_Center + (bestDiff * f_Step);
-}
-
-/**
- * gcd() - Uses Euclid's algorithm
- *
- * @u, @v:	Unsigned values whose GCD is desired.
- *
- * Returns THE greatest common divisor of u and v, if either value is 0,
- * the other value is returned as the result.
- */
-static u32 MT2063_gcd(u32 u, u32 v)
-{
-	u32 r;
-
-	while (v != 0) {
-		r = u % v;
-		u = v;
-		v = r;
-	}
-
-	return u;
-}
-
-/**
- * IsSpurInBand() - Checks to see if a spur will be present within the IF's
- *                  bandwidth. (fIFOut +/- fIFBW, -fIFOut +/- fIFBW)
- *
- *                    ma   mb                                     mc   md
- *                  <--+-+-+-------------------+-------------------+-+-+-->
- *                     |   ^                   0                   ^   |
- *                     ^   b=-fIFOut+fIFBW/2      -b=+fIFOut-fIFBW/2   ^
- *                     a=-fIFOut-fIFBW/2              -a=+fIFOut+fIFBW/2
- *
- *                  Note that some equations are doubled to prevent round-off
- *                  problems when calculating fIFBW/2
- *
- * @pAS_Info:	Avoid Spurs information block
- * @fm:		If spur, amount f_IF1 has to move negative
- * @fp:		If spur, amount f_IF1 has to move positive
- *
- *  Returns 1 if an LO spur would be present, otherwise 0.
- */
-static u32 IsSpurInBand(struct MT2063_AvoidSpursData_t *pAS_Info,
-			u32 *fm, u32 * fp)
-{
-	/*
-	 **  Calculate LO frequency settings.
-	 */
-	u32 n, n0;
-	const u32 f_LO1 = pAS_Info->f_LO1;
-	const u32 f_LO2 = pAS_Info->f_LO2;
-	const u32 d = pAS_Info->f_out + pAS_Info->f_out_bw / 2;
-	const u32 c = d - pAS_Info->f_out_bw;
-	const u32 f = pAS_Info->f_zif_bw / 2;
-	const u32 f_Scale = (f_LO1 / (UINT_MAX / 2 / pAS_Info->maxH1)) + 1;
-	s32 f_nsLO1, f_nsLO2;
-	s32 f_Spur;
-	u32 ma, mb, mc, md, me, mf;
-	u32 lo_gcd, gd_Scale, gc_Scale, gf_Scale, hgds, hgfs, hgcs;
-
-	dprintk(2, "\n");
-
-	*fm = 0;
-
-	/*
-	 ** For each edge (d, c & f), calculate a scale, based on the gcd
-	 ** of f_LO1, f_LO2 and the edge value.  Use the larger of this
-	 ** gcd-based scale factor or f_Scale.
-	 */
-	lo_gcd = MT2063_gcd(f_LO1, f_LO2);
-	gd_Scale = max((u32) MT2063_gcd(lo_gcd, d), f_Scale);
-	hgds = gd_Scale / 2;
-	gc_Scale = max((u32) MT2063_gcd(lo_gcd, c), f_Scale);
-	hgcs = gc_Scale / 2;
-	gf_Scale = max((u32) MT2063_gcd(lo_gcd, f), f_Scale);
-	hgfs = gf_Scale / 2;
-
-	n0 = DIV_ROUND_UP(f_LO2 - d, f_LO1 - f_LO2);
-
-	/*  Check out all multiples of LO1 from n0 to m_maxLOSpurHarmonic  */
-	for (n = n0; n <= pAS_Info->maxH1; ++n) {
-		md = (n * ((f_LO1 + hgds) / gd_Scale) -
-		      ((d + hgds) / gd_Scale)) / ((f_LO2 + hgds) / gd_Scale);
-
-		/*  If # fLO2 harmonics > m_maxLOSpurHarmonic, then no spurs present  */
-		if (md >= pAS_Info->maxH1)
-			break;
-
-		ma = (n * ((f_LO1 + hgds) / gd_Scale) +
-		      ((d + hgds) / gd_Scale)) / ((f_LO2 + hgds) / gd_Scale);
-
-		/*  If no spurs between +/- (f_out + f_IFBW/2), then try next harmonic  */
-		if (md == ma)
-			continue;
-
-		mc = (n * ((f_LO1 + hgcs) / gc_Scale) -
-		      ((c + hgcs) / gc_Scale)) / ((f_LO2 + hgcs) / gc_Scale);
-		if (mc != md) {
-			f_nsLO1 = (s32) (n * (f_LO1 / gc_Scale));
-			f_nsLO2 = (s32) (mc * (f_LO2 / gc_Scale));
-			f_Spur =
-			    (gc_Scale * (f_nsLO1 - f_nsLO2)) +
-			    n * (f_LO1 % gc_Scale) - mc * (f_LO2 % gc_Scale);
-
-			*fp = ((f_Spur - (s32) c) / (mc - n)) + 1;
-			*fm = (((s32) d - f_Spur) / (mc - n)) + 1;
-			return 1;
-		}
-
-		/*  Location of Zero-IF-spur to be checked  */
-		me = (n * ((f_LO1 + hgfs) / gf_Scale) +
-		      ((f + hgfs) / gf_Scale)) / ((f_LO2 + hgfs) / gf_Scale);
-		mf = (n * ((f_LO1 + hgfs) / gf_Scale) -
-		      ((f + hgfs) / gf_Scale)) / ((f_LO2 + hgfs) / gf_Scale);
-		if (me != mf) {
-			f_nsLO1 = n * (f_LO1 / gf_Scale);
-			f_nsLO2 = me * (f_LO2 / gf_Scale);
-			f_Spur =
-			    (gf_Scale * (f_nsLO1 - f_nsLO2)) +
-			    n * (f_LO1 % gf_Scale) - me * (f_LO2 % gf_Scale);
-
-			*fp = ((f_Spur + (s32) f) / (me - n)) + 1;
-			*fm = (((s32) f - f_Spur) / (me - n)) + 1;
-			return 1;
-		}
-
-		mb = (n * ((f_LO1 + hgcs) / gc_Scale) +
-		      ((c + hgcs) / gc_Scale)) / ((f_LO2 + hgcs) / gc_Scale);
-		if (ma != mb) {
-			f_nsLO1 = n * (f_LO1 / gc_Scale);
-			f_nsLO2 = ma * (f_LO2 / gc_Scale);
-			f_Spur =
-			    (gc_Scale * (f_nsLO1 - f_nsLO2)) +
-			    n * (f_LO1 % gc_Scale) - ma * (f_LO2 % gc_Scale);
-
-			*fp = (((s32) d + f_Spur) / (ma - n)) + 1;
-			*fm = (-(f_Spur + (s32) c) / (ma - n)) + 1;
-			return 1;
-		}
-	}
-
-	/*  No spurs found  */
-	return 0;
-}
-
-/*
- * MT_AvoidSpurs() - Main entry point to avoid spurs.
- *                   Checks for existing spurs in present LO1, LO2 freqs
- *                   and if present, chooses spur-free LO1, LO2 combination
- *                   that tunes the same input/output frequencies.
- */
-static u32 MT2063_AvoidSpurs(struct MT2063_AvoidSpursData_t *pAS_Info)
-{
-	u32 status = 0;
-	u32 fm, fp;		/*  restricted range on LO's        */
-	pAS_Info->bSpurAvoided = 0;
-	pAS_Info->nSpursFound = 0;
-
-	dprintk(2, "\n");
-
-	if (pAS_Info->maxH1 == 0)
-		return 0;
-
-	/*
-	 * Avoid LO Generated Spurs
-	 *
-	 * Make sure that have no LO-related spurs within the IF output
-	 * bandwidth.
-	 *
-	 * If there is an LO spur in this band, start at the current IF1 frequency
-	 * and work out until we find a spur-free frequency or run up against the
-	 * 1st IF SAW band edge.  Use temporary copies of fLO1 and fLO2 so that they
-	 * will be unchanged if a spur-free setting is not found.
-	 */
-	pAS_Info->bSpurPresent = IsSpurInBand(pAS_Info, &fm, &fp);
-	if (pAS_Info->bSpurPresent) {
-		u32 zfIF1 = pAS_Info->f_LO1 - pAS_Info->f_in;	/*  current attempt at a 1st IF  */
-		u32 zfLO1 = pAS_Info->f_LO1;	/*  current attempt at an LO1 freq  */
-		u32 zfLO2 = pAS_Info->f_LO2;	/*  current attempt at an LO2 freq  */
-		u32 delta_IF1;
-		u32 new_IF1;
-
-		/*
-		 **  Spur was found, attempt to find a spur-free 1st IF
-		 */
-		do {
-			pAS_Info->nSpursFound++;
-
-			/*  Raise f_IF1_upper, if needed  */
-			MT2063_AddExclZone(pAS_Info, zfIF1 - fm, zfIF1 + fp);
-
-			/*  Choose next IF1 that is closest to f_IF1_CENTER              */
-			new_IF1 = MT2063_ChooseFirstIF(pAS_Info);
-
-			if (new_IF1 > zfIF1) {
-				pAS_Info->f_LO1 += (new_IF1 - zfIF1);
-				pAS_Info->f_LO2 += (new_IF1 - zfIF1);
-			} else {
-				pAS_Info->f_LO1 -= (zfIF1 - new_IF1);
-				pAS_Info->f_LO2 -= (zfIF1 - new_IF1);
-			}
-			zfIF1 = new_IF1;
-
-			if (zfIF1 > pAS_Info->f_if1_Center)
-				delta_IF1 = zfIF1 - pAS_Info->f_if1_Center;
-			else
-				delta_IF1 = pAS_Info->f_if1_Center - zfIF1;
-
-			pAS_Info->bSpurPresent = IsSpurInBand(pAS_Info, &fm, &fp);
-		/*
-		 *  Continue while the new 1st IF is still within the 1st IF bandwidth
-		 *  and there is a spur in the band (again)
-		 */
-		} while ((2 * delta_IF1 + pAS_Info->f_out_bw <= pAS_Info->f_if1_bw) && pAS_Info->bSpurPresent);
-
-		/*
-		 * Use the LO-spur free values found.  If the search went all
-		 * the way to the 1st IF band edge and always found spurs, just
-		 * leave the original choice.  It's as "good" as any other.
-		 */
-		if (pAS_Info->bSpurPresent == 1) {
-			status |= MT2063_SPUR_PRESENT_ERR;
-			pAS_Info->f_LO1 = zfLO1;
-			pAS_Info->f_LO2 = zfLO2;
-		} else
-			pAS_Info->bSpurAvoided = 1;
-	}
-
-	status |=
-	    ((pAS_Info->
-	      nSpursFound << MT2063_SPUR_SHIFT) & MT2063_SPUR_CNT_MASK);
-
-	return status;
-}
-
-/*
- * Constants used by the tuning algorithm
- */
-#define MT2063_REF_FREQ          (16000000UL)	/* Reference oscillator Frequency (in Hz) */
-#define MT2063_IF1_BW            (22000000UL)	/* The IF1 filter bandwidth (in Hz) */
-#define MT2063_TUNE_STEP_SIZE       (50000UL)	/* Tune in steps of 50 kHz */
-#define MT2063_SPUR_STEP_HZ        (250000UL)	/* Step size (in Hz) to move IF1 when avoiding spurs */
-#define MT2063_ZIF_BW             (2000000UL)	/* Zero-IF spur-free bandwidth (in Hz) */
-#define MT2063_MAX_HARMONICS_1         (15UL)	/* Highest intra-tuner LO Spur Harmonic to be avoided */
-#define MT2063_MAX_HARMONICS_2          (5UL)	/* Highest inter-tuner LO Spur Harmonic to be avoided */
-#define MT2063_MIN_LO_SEP         (1000000UL)	/* Minimum inter-tuner LO frequency separation */
-#define MT2063_LO1_FRACN_AVOID          (0UL)	/* LO1 FracN numerator avoid region (in Hz) */
-#define MT2063_LO2_FRACN_AVOID     (199999UL)	/* LO2 FracN numerator avoid region (in Hz) */
-#define MT2063_MIN_FIN_FREQ      (44000000UL)	/* Minimum input frequency (in Hz) */
-#define MT2063_MAX_FIN_FREQ    (1100000000UL)	/* Maximum input frequency (in Hz) */
-#define MT2063_MIN_FOUT_FREQ     (36000000UL)	/* Minimum output frequency (in Hz) */
-#define MT2063_MAX_FOUT_FREQ     (57000000UL)	/* Maximum output frequency (in Hz) */
-#define MT2063_MIN_DNC_FREQ    (1293000000UL)	/* Minimum LO2 frequency (in Hz) */
-#define MT2063_MAX_DNC_FREQ    (1614000000UL)	/* Maximum LO2 frequency (in Hz) */
-#define MT2063_MIN_UPC_FREQ    (1396000000UL)	/* Minimum LO1 frequency (in Hz) */
-#define MT2063_MAX_UPC_FREQ    (2750000000UL)	/* Maximum LO1 frequency (in Hz) */
-
-/*
- *  Define the supported Part/Rev codes for the MT2063
- */
-#define MT2063_B0       (0x9B)
-#define MT2063_B1       (0x9C)
-#define MT2063_B2       (0x9D)
-#define MT2063_B3       (0x9E)
-
-/**
- * mt2063_lockStatus - Checks to see if LO1 and LO2 are locked
- *
- * @state:	struct mt2063_state pointer
- *
- * This function returns 0, if no lock, 1 if locked and a value < 1 if error
- */
-static unsigned int mt2063_lockStatus(struct mt2063_state *state)
-{
-	const u32 nMaxWait = 100;	/*  wait a maximum of 100 msec   */
-	const u32 nPollRate = 2;	/*  poll status bits every 2 ms */
-	const u32 nMaxLoops = nMaxWait / nPollRate;
-	const u8 LO1LK = 0x80;
-	u8 LO2LK = 0x08;
-	u32 status;
-	u32 nDelays = 0;
-
-	dprintk(2, "\n");
-
-	/*  LO2 Lock bit was in a different place for B0 version  */
-	if (state->tuner_id == MT2063_B0)
-		LO2LK = 0x40;
-
-	do {
-		status = mt2063_read(state, MT2063_REG_LO_STATUS,
-				     &state->reg[MT2063_REG_LO_STATUS], 1);
-
-		if (status < 0)
-			return status;
-
-		if ((state->reg[MT2063_REG_LO_STATUS] & (LO1LK | LO2LK)) ==
-		    (LO1LK | LO2LK)) {
-			return TUNER_STATUS_LOCKED | TUNER_STATUS_STEREO;
-		}
-		msleep(nPollRate);	/*  Wait between retries  */
-	} while (++nDelays < nMaxLoops);
-
-	/*
-	 * Got no lock or partial lock
-	 */
-	return 0;
-}
-
-/*
- *  Constants for setting receiver modes.
- *  (6 modes defined at this time, enumerated by mt2063_delivery_sys)
- *  (DNC1GC & DNC2GC are the values, which are used, when the specific
- *   DNC Output is selected, the other is always off)
- *
- *                enum mt2063_delivery_sys
- * -------------+----------------------------------------------
- * Mode 0 :     | MT2063_CABLE_QAM
- * Mode 1 :     | MT2063_CABLE_ANALOG
- * Mode 2 :     | MT2063_OFFAIR_COFDM
- * Mode 3 :     | MT2063_OFFAIR_COFDM_SAWLESS
- * Mode 4 :     | MT2063_OFFAIR_ANALOG
- * Mode 5 :     | MT2063_OFFAIR_8VSB
- * --------------+----------------------------------------------
- *
- *                |<----------   Mode  -------------->|
- *    Reg Field   |  0  |  1  |  2  |  3  |  4  |  5  |
- *    ------------+-----+-----+-----+-----+-----+-----+
- *    RFAGCen     | OFF | OFF | OFF | OFF | OFF | OFF
- *    LNARin      |   0 |   0 |   3 |   3 |  3  |  3
- *    FIFFQen     |   1 |   1 |   1 |   1 |  1  |  1
- *    FIFFq       |   0 |   0 |   0 |   0 |  0  |  0
- *    DNC1gc      |   0 |   0 |   0 |   0 |  0  |  0
- *    DNC2gc      |   0 |   0 |   0 |   0 |  0  |  0
- *    GCU Auto    |   1 |   1 |   1 |   1 |  1  |  1
- *    LNA max Atn |  31 |  31 |  31 |  31 | 31  | 31
- *    LNA Target  |  44 |  43 |  43 |  43 | 43  | 43
- *    ign  RF Ovl |   0 |   0 |   0 |   0 |  0  |  0
- *    RF  max Atn |  31 |  31 |  31 |  31 | 31  | 31
- *    PD1 Target  |  36 |  36 |  38 |  38 | 36  | 38
- *    ign FIF Ovl |   0 |   0 |   0 |   0 |  0  |  0
- *    FIF max Atn |   5 |   5 |   5 |   5 |  5  |  5
- *    PD2 Target  |  40 |  33 |  42 |  42 | 33  | 42
- */
-
-enum mt2063_delivery_sys {
-	MT2063_CABLE_QAM = 0,
-	MT2063_CABLE_ANALOG,
-	MT2063_OFFAIR_COFDM,
-	MT2063_OFFAIR_COFDM_SAWLESS,
-	MT2063_OFFAIR_ANALOG,
-	MT2063_OFFAIR_8VSB,
-	MT2063_NUM_RCVR_MODES
-};
-
-static const char *mt2063_mode_name[] = {
-	[MT2063_CABLE_QAM]		= "digital cable",
-	[MT2063_CABLE_ANALOG]		= "analog cable",
-	[MT2063_OFFAIR_COFDM]		= "digital offair",
-	[MT2063_OFFAIR_COFDM_SAWLESS]	= "digital offair without SAW",
-	[MT2063_OFFAIR_ANALOG]		= "analog offair",
-	[MT2063_OFFAIR_8VSB]		= "analog offair 8vsb",
-};
-
-static const u8 RFAGCEN[]	= {  0,  0,  0,  0,  0,  0 };
-static const u8 LNARIN[]	= {  0,  0,  3,  3,  3,  3 };
-static const u8 FIFFQEN[]	= {  1,  1,  1,  1,  1,  1 };
-static const u8 FIFFQ[]		= {  0,  0,  0,  0,  0,  0 };
-static const u8 DNC1GC[]	= {  0,  0,  0,  0,  0,  0 };
-static const u8 DNC2GC[]	= {  0,  0,  0,  0,  0,  0 };
-static const u8 ACLNAMAX[]	= { 31, 31, 31, 31, 31, 31 };
-static const u8 LNATGT[]	= { 44, 43, 43, 43, 43, 43 };
-static const u8 RFOVDIS[]	= {  0,  0,  0,  0,  0,  0 };
-static const u8 ACRFMAX[]	= { 31, 31, 31, 31, 31, 31 };
-static const u8 PD1TGT[]	= { 36, 36, 38, 38, 36, 38 };
-static const u8 FIFOVDIS[]	= {  0,  0,  0,  0,  0,  0 };
-static const u8 ACFIFMAX[]	= { 29, 29, 29, 29, 29, 29 };
-static const u8 PD2TGT[]	= { 40, 33, 38, 42, 30, 38 };
-
-/*
- * mt2063_set_dnc_output_enable()
- */
-static u32 mt2063_get_dnc_output_enable(struct mt2063_state *state,
-					enum MT2063_DNC_Output_Enable *pValue)
-{
-	dprintk(2, "\n");
-
-	if ((state->reg[MT2063_REG_DNC_GAIN] & 0x03) == 0x03) {	/* if DNC1 is off */
-		if ((state->reg[MT2063_REG_VGA_GAIN] & 0x03) == 0x03)	/* if DNC2 is off */
-			*pValue = MT2063_DNC_NONE;
-		else
-			*pValue = MT2063_DNC_2;
-	} else {	/* DNC1 is on */
-		if ((state->reg[MT2063_REG_VGA_GAIN] & 0x03) == 0x03)	/* if DNC2 is off */
-			*pValue = MT2063_DNC_1;
-		else
-			*pValue = MT2063_DNC_BOTH;
-	}
-	return 0;
-}
-
-/*
- * mt2063_set_dnc_output_enable()
- */
-static u32 mt2063_set_dnc_output_enable(struct mt2063_state *state,
-					enum MT2063_DNC_Output_Enable nValue)
-{
-	u32 status = 0;	/* Status to be returned        */
-	u8 val = 0;
-
-	dprintk(2, "\n");
-
-	/* selects, which DNC output is used */
-	switch (nValue) {
-	case MT2063_DNC_NONE:
-		val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | 0x03;	/* Set DNC1GC=3 */
-		if (state->reg[MT2063_REG_DNC_GAIN] !=
-		    val)
-			status |=
-			    mt2063_setreg(state,
-					  MT2063_REG_DNC_GAIN,
-					  val);
-
-		val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | 0x03;	/* Set DNC2GC=3 */
-		if (state->reg[MT2063_REG_VGA_GAIN] !=
-		    val)
-			status |=
-			    mt2063_setreg(state,
-					  MT2063_REG_VGA_GAIN,
-					  val);
-
-		val = (state->reg[MT2063_REG_RSVD_20] & ~0x40);	/* Set PD2MUX=0 */
-		if (state->reg[MT2063_REG_RSVD_20] !=
-		    val)
-			status |=
-			    mt2063_setreg(state,
-					  MT2063_REG_RSVD_20,
-					  val);
-
-		break;
-	case MT2063_DNC_1:
-		val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | (DNC1GC[state->rcvr_mode] & 0x03);	/* Set DNC1GC=x */
-		if (state->reg[MT2063_REG_DNC_GAIN] !=
-		    val)
-			status |=
-			    mt2063_setreg(state,
-					  MT2063_REG_DNC_GAIN,
-					  val);
-
-		val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | 0x03;	/* Set DNC2GC=3 */
-		if (state->reg[MT2063_REG_VGA_GAIN] !=
-		    val)
-			status |=
-			    mt2063_setreg(state,
-					  MT2063_REG_VGA_GAIN,
-					  val);
-
-		val = (state->reg[MT2063_REG_RSVD_20] & ~0x40);	/* Set PD2MUX=0 */
-		if (state->reg[MT2063_REG_RSVD_20] !=
-		    val)
-			status |=
-			    mt2063_setreg(state,
-					  MT2063_REG_RSVD_20,
-					  val);
-
-		break;
-	case MT2063_DNC_2:
-		val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | 0x03;	/* Set DNC1GC=3 */
-		if (state->reg[MT2063_REG_DNC_GAIN] !=
-		    val)
-			status |=
-			    mt2063_setreg(state,
-					  MT2063_REG_DNC_GAIN,
-					  val);
-
-		val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | (DNC2GC[state->rcvr_mode] & 0x03);	/* Set DNC2GC=x */
-		if (state->reg[MT2063_REG_VGA_GAIN] !=
-		    val)
-			status |=
-			    mt2063_setreg(state,
-					  MT2063_REG_VGA_GAIN,
-					  val);
-
-		val = (state->reg[MT2063_REG_RSVD_20] | 0x40);	/* Set PD2MUX=1 */
-		if (state->reg[MT2063_REG_RSVD_20] !=
-		    val)
-			status |=
-			    mt2063_setreg(state,
-					  MT2063_REG_RSVD_20,
-					  val);
-
-		break;
-	case MT2063_DNC_BOTH:
-		val = (state->reg[MT2063_REG_DNC_GAIN] & 0xFC) | (DNC1GC[state->rcvr_mode] & 0x03);	/* Set DNC1GC=x */
-		if (state->reg[MT2063_REG_DNC_GAIN] !=
-		    val)
-			status |=
-			    mt2063_setreg(state,
-					  MT2063_REG_DNC_GAIN,
-					  val);
-
-		val = (state->reg[MT2063_REG_VGA_GAIN] & 0xFC) | (DNC2GC[state->rcvr_mode] & 0x03);	/* Set DNC2GC=x */
-		if (state->reg[MT2063_REG_VGA_GAIN] !=
-		    val)
-			status |=
-			    mt2063_setreg(state,
-					  MT2063_REG_VGA_GAIN,
-					  val);
-
-		val = (state->reg[MT2063_REG_RSVD_20] | 0x40);	/* Set PD2MUX=1 */
-		if (state->reg[MT2063_REG_RSVD_20] !=
-		    val)
-			status |=
-			    mt2063_setreg(state,
-					  MT2063_REG_RSVD_20,
-					  val);
-
-		break;
-	default:
-		break;
-	}
-
-	return status;
-}
-
-/*
- * MT2063_SetReceiverMode() - Set the MT2063 receiver mode, according with
- * 			      the selected enum mt2063_delivery_sys type.
- *
- *  (DNC1GC & DNC2GC are the values, which are used, when the specific
- *   DNC Output is selected, the other is always off)
- *
- * @state:	ptr to mt2063_state structure
- * @Mode:	desired reciever delivery system
- *
- * Note: Register cache must be valid for it to work
- */
-
-static u32 MT2063_SetReceiverMode(struct mt2063_state *state,
-				  enum mt2063_delivery_sys Mode)
-{
-	u32 status = 0;	/* Status to be returned        */
-	u8 val;
-	u32 longval;
-
-	dprintk(2, "\n");
-
-	if (Mode >= MT2063_NUM_RCVR_MODES)
-		status = -ERANGE;
-
-	/* RFAGCen */
-	if (status >= 0) {
-		val =
-		    (state->
-		     reg[MT2063_REG_PD1_TGT] & (u8) ~0x40) | (RFAGCEN[Mode]
-								   ? 0x40 :
-								   0x00);
-		if (state->reg[MT2063_REG_PD1_TGT] != val)
-			status |= mt2063_setreg(state, MT2063_REG_PD1_TGT, val);
-	}
-
-	/* LNARin */
-	if (status >= 0) {
-		u8 val = (state->reg[MT2063_REG_CTRL_2C] & (u8) ~0x03) |
-			 (LNARIN[Mode] & 0x03);
-		if (state->reg[MT2063_REG_CTRL_2C] != val)
-			status |= mt2063_setreg(state, MT2063_REG_CTRL_2C, val);
-	}
-
-	/* FIFFQEN and FIFFQ */
-	if (status >= 0) {
-		val =
-		    (state->
-		     reg[MT2063_REG_FIFF_CTRL2] & (u8) ~0xF0) |
-		    (FIFFQEN[Mode] << 7) | (FIFFQ[Mode] << 4);
-		if (state->reg[MT2063_REG_FIFF_CTRL2] != val) {
-			status |=
-			    mt2063_setreg(state, MT2063_REG_FIFF_CTRL2, val);
-			/* trigger FIFF calibration, needed after changing FIFFQ */
-			val =
-			    (state->reg[MT2063_REG_FIFF_CTRL] | (u8) 0x01);
-			status |=
-			    mt2063_setreg(state, MT2063_REG_FIFF_CTRL, val);
-			val =
-			    (state->
-			     reg[MT2063_REG_FIFF_CTRL] & (u8) ~0x01);
-			status |=
-			    mt2063_setreg(state, MT2063_REG_FIFF_CTRL, val);
-		}
-	}
-
-	/* DNC1GC & DNC2GC */
-	status |= mt2063_get_dnc_output_enable(state, &longval);
-	status |= mt2063_set_dnc_output_enable(state, longval);
-
-	/* acLNAmax */
-	if (status >= 0) {
-		u8 val = (state->reg[MT2063_REG_LNA_OV] & (u8) ~0x1F) |
-			 (ACLNAMAX[Mode] & 0x1F);
-		if (state->reg[MT2063_REG_LNA_OV] != val)
-			status |= mt2063_setreg(state, MT2063_REG_LNA_OV, val);
-	}
-
-	/* LNATGT */
-	if (status >= 0) {
-		u8 val = (state->reg[MT2063_REG_LNA_TGT] & (u8) ~0x3F) |
-			 (LNATGT[Mode] & 0x3F);
-		if (state->reg[MT2063_REG_LNA_TGT] != val)
-			status |= mt2063_setreg(state, MT2063_REG_LNA_TGT, val);
-	}
-
-	/* ACRF */
-	if (status >= 0) {
-		u8 val = (state->reg[MT2063_REG_RF_OV] & (u8) ~0x1F) |
-			 (ACRFMAX[Mode] & 0x1F);
-		if (state->reg[MT2063_REG_RF_OV] != val)
-			status |= mt2063_setreg(state, MT2063_REG_RF_OV, val);
-	}
-
-	/* PD1TGT */
-	if (status >= 0) {
-		u8 val = (state->reg[MT2063_REG_PD1_TGT] & (u8) ~0x3F) |
-			 (PD1TGT[Mode] & 0x3F);
-		if (state->reg[MT2063_REG_PD1_TGT] != val)
-			status |= mt2063_setreg(state, MT2063_REG_PD1_TGT, val);
-	}
-
-	/* FIFATN */
-	if (status >= 0) {
-		u8 val = ACFIFMAX[Mode];
-		if (state->reg[MT2063_REG_PART_REV] != MT2063_B3 && val > 5)
-			val = 5;
-		val = (state->reg[MT2063_REG_FIF_OV] & (u8) ~0x1F) |
-		      (val & 0x1F);
-		if (state->reg[MT2063_REG_FIF_OV] != val)
-			status |= mt2063_setreg(state, MT2063_REG_FIF_OV, val);
-	}
-
-	/* PD2TGT */
-	if (status >= 0) {
-		u8 val = (state->reg[MT2063_REG_PD2_TGT] & (u8) ~0x3F) |
-		    (PD2TGT[Mode] & 0x3F);
-		if (state->reg[MT2063_REG_PD2_TGT] != val)
-			status |= mt2063_setreg(state, MT2063_REG_PD2_TGT, val);
-	}
-
-	/* Ignore ATN Overload */
-	if (status >= 0) {
-		val = (state->reg[MT2063_REG_LNA_TGT] & (u8) ~0x80) |
-		      (RFOVDIS[Mode] ? 0x80 : 0x00);
-		if (state->reg[MT2063_REG_LNA_TGT] != val)
-			status |= mt2063_setreg(state, MT2063_REG_LNA_TGT, val);
-	}
-
-	/* Ignore FIF Overload */
-	if (status >= 0) {
-		val = (state->reg[MT2063_REG_PD1_TGT] & (u8) ~0x80) |
-		      (FIFOVDIS[Mode] ? 0x80 : 0x00);
-		if (state->reg[MT2063_REG_PD1_TGT] != val)
-			status |= mt2063_setreg(state, MT2063_REG_PD1_TGT, val);
-	}
-
-	if (status >= 0) {
-		state->rcvr_mode = Mode;
-		dprintk(1, "mt2063 mode changed to %s\n",
-			mt2063_mode_name[state->rcvr_mode]);
-	}
-
-	return status;
-}
-
-/*
- * MT2063_ClearPowerMaskBits () - Clears the power-down mask bits for various
- *				  sections of the MT2063
- *
- * @Bits:		Mask bits to be cleared.
- *
- * See definition of MT2063_Mask_Bits type for description
- * of each of the power bits.
- */
-static u32 MT2063_ClearPowerMaskBits(struct mt2063_state *state,
-				     enum MT2063_Mask_Bits Bits)
-{
-	u32 status = 0;
-
-	dprintk(2, "\n");
-	Bits = (enum MT2063_Mask_Bits)(Bits & MT2063_ALL_SD);	/* Only valid bits for this tuner */
-	if ((Bits & 0xFF00) != 0) {
-		state->reg[MT2063_REG_PWR_2] &= ~(u8) (Bits >> 8);
-		status |=
-		    mt2063_write(state,
-				    MT2063_REG_PWR_2,
-				    &state->reg[MT2063_REG_PWR_2], 1);
-	}
-	if ((Bits & 0xFF) != 0) {
-		state->reg[MT2063_REG_PWR_1] &= ~(u8) (Bits & 0xFF);
-		status |=
-		    mt2063_write(state,
-				    MT2063_REG_PWR_1,
-				    &state->reg[MT2063_REG_PWR_1], 1);
-	}
-
-	return status;
-}
-
-/*
- * MT2063_SoftwareShutdown() - Enables or disables software shutdown function.
- *			       When Shutdown is 1, any section whose power
- *			       mask is set will be shutdown.
- */
-static u32 MT2063_SoftwareShutdown(struct mt2063_state *state, u8 Shutdown)
-{
-	u32 status;
-
-	dprintk(2, "\n");
-	if (Shutdown == 1)
-		state->reg[MT2063_REG_PWR_1] |= 0x04;
-	else
-		state->reg[MT2063_REG_PWR_1] &= ~0x04;
-
-	status = mt2063_write(state,
-			    MT2063_REG_PWR_1,
-			    &state->reg[MT2063_REG_PWR_1], 1);
-
-	if (Shutdown != 1) {
-		state->reg[MT2063_REG_BYP_CTRL] =
-		    (state->reg[MT2063_REG_BYP_CTRL] & 0x9F) | 0x40;
-		status |=
-		    mt2063_write(state,
-				    MT2063_REG_BYP_CTRL,
-				    &state->reg[MT2063_REG_BYP_CTRL],
-				    1);
-		state->reg[MT2063_REG_BYP_CTRL] =
-		    (state->reg[MT2063_REG_BYP_CTRL] & 0x9F);
-		status |=
-		    mt2063_write(state,
-				    MT2063_REG_BYP_CTRL,
-				    &state->reg[MT2063_REG_BYP_CTRL],
-				    1);
-	}
-
-	return status;
-}
-
-static u32 MT2063_Round_fLO(u32 f_LO, u32 f_LO_Step, u32 f_ref)
-{
-	return f_ref * (f_LO / f_ref)
-	    + f_LO_Step * (((f_LO % f_ref) + (f_LO_Step / 2)) / f_LO_Step);
-}
-
-/**
- * fLO_FractionalTerm() - Calculates the portion contributed by FracN / denom.
- *                        This function preserves maximum precision without
- *                        risk of overflow.  It accurately calculates
- *                        f_ref * num / denom to within 1 HZ with fixed math.
- *
- * @num :	Fractional portion of the multiplier
- * @denom:	denominator portion of the ratio
- * @f_Ref:	SRO frequency.
- *
- * This calculation handles f_ref as two separate 14-bit fields.
- * Therefore, a maximum value of 2^28-1 may safely be used for f_ref.
- * This is the genesis of the magic number "14" and the magic mask value of
- * 0x03FFF.
- *
- * This routine successfully handles denom values up to and including 2^18.
- *  Returns:        f_ref * num / denom
- */
-static u32 MT2063_fLO_FractionalTerm(u32 f_ref, u32 num, u32 denom)
-{
-	u32 t1 = (f_ref >> 14) * num;
-	u32 term1 = t1 / denom;
-	u32 loss = t1 % denom;
-	u32 term2 =
-	    (((f_ref & 0x00003FFF) * num + (loss << 14)) + (denom / 2)) / denom;
-	return (term1 << 14) + term2;
-}
-
-/*
- * CalcLO1Mult()- Calculates Integer divider value and the numerator
- *                value for a FracN PLL.
- *
- *                This function assumes that the f_LO and f_Ref are
- *                evenly divisible by f_LO_Step.
- *
- * @Div:	OUTPUT: Whole number portion of the multiplier
- * @FracN:	OUTPUT: Fractional portion of the multiplier
- * @f_LO:	desired LO frequency.
- * @f_LO_Step:	Minimum step size for the LO (in Hz).
- * @f_Ref:	SRO frequency.
- * @f_Avoid:	Range of PLL frequencies to avoid near integer multiples
- *		of f_Ref (in Hz).
- *
- * Returns:        Recalculated LO frequency.
- */
-static u32 MT2063_CalcLO1Mult(u32 *Div,
-			      u32 *FracN,
-			      u32 f_LO,
-			      u32 f_LO_Step, u32 f_Ref)
-{
-	/*  Calculate the whole number portion of the divider */
-	*Div = f_LO / f_Ref;
-
-	/*  Calculate the numerator value (round to nearest f_LO_Step) */
-	*FracN =
-	    (64 * (((f_LO % f_Ref) + (f_LO_Step / 2)) / f_LO_Step) +
-	     (f_Ref / f_LO_Step / 2)) / (f_Ref / f_LO_Step);
-
-	return (f_Ref * (*Div)) + MT2063_fLO_FractionalTerm(f_Ref, *FracN, 64);
-}
-
-/**
- * CalcLO2Mult() - Calculates Integer divider value and the numerator
- *                 value for a FracN PLL.
- *
- *                  This function assumes that the f_LO and f_Ref are
- *                  evenly divisible by f_LO_Step.
- *
- * @Div:	OUTPUT: Whole number portion of the multiplier
- * @FracN:	OUTPUT: Fractional portion of the multiplier
- * @f_LO:	desired LO frequency.
- * @f_LO_Step:	Minimum step size for the LO (in Hz).
- * @f_Ref:	SRO frequency.
- * @f_Avoid:	Range of PLL frequencies to avoid near
- *		integer multiples of f_Ref (in Hz).
- *
- * Returns: Recalculated LO frequency.
- */
-static u32 MT2063_CalcLO2Mult(u32 *Div,
-			      u32 *FracN,
-			      u32 f_LO,
-			      u32 f_LO_Step, u32 f_Ref)
-{
-	/*  Calculate the whole number portion of the divider */
-	*Div = f_LO / f_Ref;
-
-	/*  Calculate the numerator value (round to nearest f_LO_Step) */
-	*FracN =
-	    (8191 * (((f_LO % f_Ref) + (f_LO_Step / 2)) / f_LO_Step) +
-	     (f_Ref / f_LO_Step / 2)) / (f_Ref / f_LO_Step);
-
-	return (f_Ref * (*Div)) + MT2063_fLO_FractionalTerm(f_Ref, *FracN,
-							    8191);
-}
-
-/*
- * FindClearTuneFilter() - Calculate the corrrect ClearTune filter to be
- *			   used for a given input frequency.
- *
- * @state:	ptr to tuner data structure
- * @f_in:	RF input center frequency (in Hz).
- *
- * Returns: ClearTune filter number (0-31)
- */
-static u32 FindClearTuneFilter(struct mt2063_state *state, u32 f_in)
-{
-	u32 RFBand;
-	u32 idx;		/*  index loop                      */
-
-	/*
-	 **  Find RF Band setting
-	 */
-	RFBand = 31;		/*  def when f_in > all    */
-	for (idx = 0; idx < 31; ++idx) {
-		if (state->CTFiltMax[idx] >= f_in) {
-			RFBand = idx;
-			break;
-		}
-	}
-	return RFBand;
-}
-
-/*
- * MT2063_Tune() - Change the tuner's tuned frequency to RFin.
- */
-static u32 MT2063_Tune(struct mt2063_state *state, u32 f_in)
-{				/* RF input center frequency   */
-
-	u32 status = 0;
-	u32 LO1;		/*  1st LO register value           */
-	u32 Num1;		/*  Numerator for LO1 reg. value    */
-	u32 f_IF1;		/*  1st IF requested                */
-	u32 LO2;		/*  2nd LO register value           */
-	u32 Num2;		/*  Numerator for LO2 reg. value    */
-	u32 ofLO1, ofLO2;	/*  last time's LO frequencies      */
-	u8 fiffc = 0x80;	/*  FIFF center freq from tuner     */
-	u32 fiffof;		/*  Offset from FIFF center freq    */
-	const u8 LO1LK = 0x80;	/*  Mask for LO1 Lock bit           */
-	u8 LO2LK = 0x08;	/*  Mask for LO2 Lock bit           */
-	u8 val;
-	u32 RFBand;
-
-	dprintk(2, "\n");
-	/*  Check the input and output frequency ranges                   */
-	if ((f_in < MT2063_MIN_FIN_FREQ) || (f_in > MT2063_MAX_FIN_FREQ))
-		return -EINVAL;
-
-	if ((state->AS_Data.f_out < MT2063_MIN_FOUT_FREQ)
-	    || (state->AS_Data.f_out > MT2063_MAX_FOUT_FREQ))
-		return -EINVAL;
-
-	/*
-	 * Save original LO1 and LO2 register values
-	 */
-	ofLO1 = state->AS_Data.f_LO1;
-	ofLO2 = state->AS_Data.f_LO2; 
-
-	/*
-	 * Find and set RF Band setting
-	 */
-	if (state->ctfilt_sw == 1) {
-		val = (state->reg[MT2063_REG_CTUNE_CTRL] | 0x08);
-		if (state->reg[MT2063_REG_CTUNE_CTRL] != val) {
-			status |=
-			    mt2063_setreg(state, MT2063_REG_CTUNE_CTRL, val);
-		}
-		val = state->reg[MT2063_REG_CTUNE_OV];
-		RFBand = FindClearTuneFilter(state, f_in);
-		state->reg[MT2063_REG_CTUNE_OV] =
-		    (u8) ((state->reg[MT2063_REG_CTUNE_OV] & ~0x1F)
-			      | RFBand);
-		if (state->reg[MT2063_REG_CTUNE_OV] != val) {
-			status |=
-			    mt2063_setreg(state, MT2063_REG_CTUNE_OV, val);
-		}
-	}
-
-	/*
-	 * Read the FIFF Center Frequency from the tuner
-	 */
-	if (status >= 0) {
-		status |=
-		    mt2063_read(state,
-				   MT2063_REG_FIFFC,
-				   &state->reg[MT2063_REG_FIFFC], 1);
-		fiffc = state->reg[MT2063_REG_FIFFC];
-	}
-	/*
-	 * Assign in the requested values
-	 */
-	state->AS_Data.f_in = f_in;
-	/*  Request a 1st IF such that LO1 is on a step size */
-	state->AS_Data.f_if1_Request =
-	    MT2063_Round_fLO(state->AS_Data.f_if1_Request + f_in,
-			     state->AS_Data.f_LO1_Step,
-			     state->AS_Data.f_ref) - f_in;
-
-	/*
-	 * Calculate frequency settings.  f_IF1_FREQ + f_in is the
-	 * desired LO1 frequency
-	 */
-	MT2063_ResetExclZones(&state->AS_Data);
-
-	f_IF1 = MT2063_ChooseFirstIF(&state->AS_Data);
-
-	state->AS_Data.f_LO1 =
-	    MT2063_Round_fLO(f_IF1 + f_in, state->AS_Data.f_LO1_Step,
-			     state->AS_Data.f_ref);
-
-	state->AS_Data.f_LO2 =
-	    MT2063_Round_fLO(state->AS_Data.f_LO1 - state->AS_Data.f_out - f_in,
-			     state->AS_Data.f_LO2_Step, state->AS_Data.f_ref);
-
-	/*
-	 * Check for any LO spurs in the output bandwidth and adjust
-	 * the LO settings to avoid them if needed
-	 */
-	status |= MT2063_AvoidSpurs(&state->AS_Data);
-	/*
-	 * MT_AvoidSpurs spurs may have changed the LO1 & LO2 values.
-	 * Recalculate the LO frequencies and the values to be placed
-	 * in the tuning registers.
-	 */
-	state->AS_Data.f_LO1 =
-	    MT2063_CalcLO1Mult(&LO1, &Num1, state->AS_Data.f_LO1,
-			       state->AS_Data.f_LO1_Step, state->AS_Data.f_ref);
-	state->AS_Data.f_LO2 =
-	    MT2063_Round_fLO(state->AS_Data.f_LO1 - state->AS_Data.f_out - f_in,
-			     state->AS_Data.f_LO2_Step, state->AS_Data.f_ref);
-	state->AS_Data.f_LO2 =
-	    MT2063_CalcLO2Mult(&LO2, &Num2, state->AS_Data.f_LO2,
-			       state->AS_Data.f_LO2_Step, state->AS_Data.f_ref);
-
-	/*
-	 *  Check the upconverter and downconverter frequency ranges
-	 */
-	if ((state->AS_Data.f_LO1 < MT2063_MIN_UPC_FREQ)
-	    || (state->AS_Data.f_LO1 > MT2063_MAX_UPC_FREQ))
-		status |= MT2063_UPC_RANGE;
-	if ((state->AS_Data.f_LO2 < MT2063_MIN_DNC_FREQ)
-	    || (state->AS_Data.f_LO2 > MT2063_MAX_DNC_FREQ))
-		status |= MT2063_DNC_RANGE;
-	/*  LO2 Lock bit was in a different place for B0 version  */
-	if (state->tuner_id == MT2063_B0)
-		LO2LK = 0x40;
-
-	/*
-	 *  If we have the same LO frequencies and we're already locked,
-	 *  then skip re-programming the LO registers.
-	 */
-	if ((ofLO1 != state->AS_Data.f_LO1)
-	    || (ofLO2 != state->AS_Data.f_LO2)
-	    || ((state->reg[MT2063_REG_LO_STATUS] & (LO1LK | LO2LK)) !=
-		(LO1LK | LO2LK))) {
-		/*
-		 * Calculate the FIFFOF register value
-		 *
-		 *           IF1_Actual
-		 * FIFFOF = ------------ - 8 * FIFFC - 4992
-		 *            f_ref/64
-		 */
-		fiffof =
-		    (state->AS_Data.f_LO1 -
-		     f_in) / (state->AS_Data.f_ref / 64) - 8 * (u32) fiffc -
-		    4992;
-		if (fiffof > 0xFF)
-			fiffof = 0xFF;
-
-		/*
-		 * Place all of the calculated values into the local tuner
-		 * register fields.
-		 */
-		if (status >= 0) {
-			state->reg[MT2063_REG_LO1CQ_1] = (u8) (LO1 & 0xFF);	/* DIV1q */
-			state->reg[MT2063_REG_LO1CQ_2] = (u8) (Num1 & 0x3F);	/* NUM1q */
-			state->reg[MT2063_REG_LO2CQ_1] = (u8) (((LO2 & 0x7F) << 1)	/* DIV2q */
-								   |(Num2 >> 12));	/* NUM2q (hi) */
-			state->reg[MT2063_REG_LO2CQ_2] = (u8) ((Num2 & 0x0FF0) >> 4);	/* NUM2q (mid) */
-			state->reg[MT2063_REG_LO2CQ_3] = (u8) (0xE0 | (Num2 & 0x000F));	/* NUM2q (lo) */
-
-			/*
-			 * Now write out the computed register values
-			 * IMPORTANT: There is a required order for writing
-			 *            (0x05 must follow all the others).
-			 */
-			status |= mt2063_write(state, MT2063_REG_LO1CQ_1, &state->reg[MT2063_REG_LO1CQ_1], 5);	/* 0x01 - 0x05 */
-			if (state->tuner_id == MT2063_B0) {
-				/* Re-write the one-shot bits to trigger the tune operation */
-				status |= mt2063_write(state, MT2063_REG_LO2CQ_3, &state->reg[MT2063_REG_LO2CQ_3], 1);	/* 0x05 */
-			}
-			/* Write out the FIFF offset only if it's changing */
-			if (state->reg[MT2063_REG_FIFF_OFFSET] !=
-			    (u8) fiffof) {
-				state->reg[MT2063_REG_FIFF_OFFSET] =
-				    (u8) fiffof;
-				status |=
-				    mt2063_write(state,
-						    MT2063_REG_FIFF_OFFSET,
-						    &state->
-						    reg[MT2063_REG_FIFF_OFFSET],
-						    1);
-			}
-		}
-
-		/*
-		 * Check for LO's locking
-		 */
-
-		if (status < 0)
-			return status;
-
-		status = mt2063_lockStatus(state);
-		if (status < 0)
-			return status;
-		if (!status)
-			return -EINVAL;		/* Couldn't lock */
-
-		/*
-		 * If we locked OK, assign calculated data to mt2063_state structure
-		 */
-		state->f_IF1_actual = state->AS_Data.f_LO1 - f_in;
-	}
-
-	return status;
-}
-
-static const u8 MT2063B0_defaults[] = {
-	/* Reg,  Value */
-	0x19, 0x05,
-	0x1B, 0x1D,
-	0x1C, 0x1F,
-	0x1D, 0x0F,
-	0x1E, 0x3F,
-	0x1F, 0x0F,
-	0x20, 0x3F,
-	0x22, 0x21,
-	0x23, 0x3F,
-	0x24, 0x20,
-	0x25, 0x3F,
-	0x27, 0xEE,
-	0x2C, 0x27,	/*  bit at 0x20 is cleared below  */
-	0x30, 0x03,
-	0x2C, 0x07,	/*  bit at 0x20 is cleared here   */
-	0x2D, 0x87,
-	0x2E, 0xAA,
-	0x28, 0xE1,	/*  Set the FIFCrst bit here      */
-	0x28, 0xE0,	/*  Clear the FIFCrst bit here    */
-	0x00
-};
-
-/* writing 0x05 0xf0 sw-resets all registers, so we write only needed changes */
-static const u8 MT2063B1_defaults[] = {
-	/* Reg,  Value */
-	0x05, 0xF0,
-	0x11, 0x10,	/* New Enable AFCsd */
-	0x19, 0x05,
-	0x1A, 0x6C,
-	0x1B, 0x24,
-	0x1C, 0x28,
-	0x1D, 0x8F,
-	0x1E, 0x14,
-	0x1F, 0x8F,
-	0x20, 0x57,
-	0x22, 0x21,	/* New - ver 1.03 */
-	0x23, 0x3C,	/* New - ver 1.10 */
-	0x24, 0x20,	/* New - ver 1.03 */
-	0x2C, 0x24,	/*  bit at 0x20 is cleared below  */
-	0x2D, 0x87,	/*  FIFFQ=0  */
-	0x2F, 0xF3,
-	0x30, 0x0C,	/* New - ver 1.11 */
-	0x31, 0x1B,	/* New - ver 1.11 */
-	0x2C, 0x04,	/*  bit at 0x20 is cleared here  */
-	0x28, 0xE1,	/*  Set the FIFCrst bit here      */
-	0x28, 0xE0,	/*  Clear the FIFCrst bit here    */
-	0x00
-};
-
-/* writing 0x05 0xf0 sw-resets all registers, so we write only needed changes */
-static const u8 MT2063B3_defaults[] = {
-	/* Reg,  Value */
-	0x05, 0xF0,
-	0x19, 0x3D,
-	0x2C, 0x24,	/*  bit at 0x20 is cleared below  */
-	0x2C, 0x04,	/*  bit at 0x20 is cleared here  */
-	0x28, 0xE1,	/*  Set the FIFCrst bit here      */
-	0x28, 0xE0,	/*  Clear the FIFCrst bit here    */
-	0x00
-};
-
-static int mt2063_init(struct dvb_frontend *fe)
-{
-	u32 status;
-	struct mt2063_state *state = fe->tuner_priv;
-	u8 all_resets = 0xF0;	/* reset/load bits */
-	const u8 *def = NULL;
-	char *step;
-	u32 FCRUN;
-	s32 maxReads;
-	u32 fcu_osc;
-	u32 i;
-
-	dprintk(2, "\n");
-
-	state->rcvr_mode = MT2063_CABLE_QAM;
-
-	/*  Read the Part/Rev code from the tuner */
-	status = mt2063_read(state, MT2063_REG_PART_REV,
-			     &state->reg[MT2063_REG_PART_REV], 1);
-	if (status < 0) {
-		printk(KERN_ERR "Can't read mt2063 part ID\n");
-		return status;
-	}
-
-	/* Check the part/rev code */
-	switch (state->reg[MT2063_REG_PART_REV]) {
-	case MT2063_B0:
-		step = "B0";
-		break;
-	case MT2063_B1:
-		step = "B1";
-		break;
-	case MT2063_B2:
-		step = "B2";
-		break;
-	case MT2063_B3:
-		step = "B3";
-		break;
-	default:
-		printk(KERN_ERR "mt2063: Unknown mt2063 device ID (0x%02x)\n",
-		       state->reg[MT2063_REG_PART_REV]);
-		return -ENODEV;	/*  Wrong tuner Part/Rev code */
-	}
-
-	/*  Check the 2nd byte of the Part/Rev code from the tuner */
-	status = mt2063_read(state, MT2063_REG_RSVD_3B,
-			     &state->reg[MT2063_REG_RSVD_3B], 1);
-
-	/* b7 != 0 ==> NOT MT2063 */
-	if (status < 0 || ((state->reg[MT2063_REG_RSVD_3B] & 0x80) != 0x00)) {
-		printk(KERN_ERR "mt2063: Unknown part ID (0x%02x%02x)\n",
-		       state->reg[MT2063_REG_PART_REV],
-		       state->reg[MT2063_REG_RSVD_3B]);
-		return -ENODEV;	/*  Wrong tuner Part/Rev code */
-	}
-
-	printk(KERN_INFO "mt2063: detected a mt2063 %s\n", step);
-
-	/*  Reset the tuner  */
-	status = mt2063_write(state, MT2063_REG_LO2CQ_3, &all_resets, 1);
-	if (status < 0)
-		return status;
-
-	/* change all of the default values that vary from the HW reset values */
-	/*  def = (state->reg[PART_REV] == MT2063_B0) ? MT2063B0_defaults : MT2063B1_defaults; */
-	switch (state->reg[MT2063_REG_PART_REV]) {
-	case MT2063_B3:
-		def = MT2063B3_defaults;
-		break;
-
-	case MT2063_B1:
-		def = MT2063B1_defaults;
-		break;
-
-	case MT2063_B0:
-		def = MT2063B0_defaults;
-		break;
-
-	default:
-		return -ENODEV;
-		break;
-	}
-
-	while (status >= 0 && *def) {
-		u8 reg = *def++;
-		u8 val = *def++;
-		status = mt2063_write(state, reg, &val, 1);
-	}
-	if (status < 0)
-		return status;
-
-	/*  Wait for FIFF location to complete.  */
-	FCRUN = 1;
-	maxReads = 10;
-	while (status >= 0 && (FCRUN != 0) && (maxReads-- > 0)) {
-		msleep(2);
-		status = mt2063_read(state,
-					 MT2063_REG_XO_STATUS,
-					 &state->
-					 reg[MT2063_REG_XO_STATUS], 1);
-		FCRUN = (state->reg[MT2063_REG_XO_STATUS] & 0x40) >> 6;
-	}
-
-	if (FCRUN != 0 || status < 0)
-		return -ENODEV;
-
-	status = mt2063_read(state,
-			   MT2063_REG_FIFFC,
-			   &state->reg[MT2063_REG_FIFFC], 1);
-	if (status < 0)
-		return status;
-
-	/* Read back all the registers from the tuner */
-	status = mt2063_read(state,
-				MT2063_REG_PART_REV,
-				state->reg, MT2063_REG_END_REGS);
-	if (status < 0)
-		return status;
-
-	/*  Initialize the tuner state.  */
-	state->tuner_id = state->reg[MT2063_REG_PART_REV];
-	state->AS_Data.f_ref = MT2063_REF_FREQ;
-	state->AS_Data.f_if1_Center = (state->AS_Data.f_ref / 8) *
-				      ((u32) state->reg[MT2063_REG_FIFFC] + 640);
-	state->AS_Data.f_if1_bw = MT2063_IF1_BW;
-	state->AS_Data.f_out = 43750000UL;
-	state->AS_Data.f_out_bw = 6750000UL;
-	state->AS_Data.f_zif_bw = MT2063_ZIF_BW;
-	state->AS_Data.f_LO1_Step = state->AS_Data.f_ref / 64;
-	state->AS_Data.f_LO2_Step = MT2063_TUNE_STEP_SIZE;
-	state->AS_Data.maxH1 = MT2063_MAX_HARMONICS_1;
-	state->AS_Data.maxH2 = MT2063_MAX_HARMONICS_2;
-	state->AS_Data.f_min_LO_Separation = MT2063_MIN_LO_SEP;
-	state->AS_Data.f_if1_Request = state->AS_Data.f_if1_Center;
-	state->AS_Data.f_LO1 = 2181000000UL;
-	state->AS_Data.f_LO2 = 1486249786UL;
-	state->f_IF1_actual = state->AS_Data.f_if1_Center;
-	state->AS_Data.f_in = state->AS_Data.f_LO1 - state->f_IF1_actual;
-	state->AS_Data.f_LO1_FracN_Avoid = MT2063_LO1_FRACN_AVOID;
-	state->AS_Data.f_LO2_FracN_Avoid = MT2063_LO2_FRACN_AVOID;
-	state->num_regs = MT2063_REG_END_REGS;
-	state->AS_Data.avoidDECT = MT2063_AVOID_BOTH;
-	state->ctfilt_sw = 0;
-
-	state->CTFiltMax[0] = 69230000;
-	state->CTFiltMax[1] = 105770000;
-	state->CTFiltMax[2] = 140350000;
-	state->CTFiltMax[3] = 177110000;
-	state->CTFiltMax[4] = 212860000;
-	state->CTFiltMax[5] = 241130000;
-	state->CTFiltMax[6] = 274370000;
-	state->CTFiltMax[7] = 309820000;
-	state->CTFiltMax[8] = 342450000;
-	state->CTFiltMax[9] = 378870000;
-	state->CTFiltMax[10] = 416210000;
-	state->CTFiltMax[11] = 456500000;
-	state->CTFiltMax[12] = 495790000;
-	state->CTFiltMax[13] = 534530000;
-	state->CTFiltMax[14] = 572610000;
-	state->CTFiltMax[15] = 598970000;
-	state->CTFiltMax[16] = 635910000;
-	state->CTFiltMax[17] = 672130000;
-	state->CTFiltMax[18] = 714840000;
-	state->CTFiltMax[19] = 739660000;
-	state->CTFiltMax[20] = 770410000;
-	state->CTFiltMax[21] = 814660000;
-	state->CTFiltMax[22] = 846950000;
-	state->CTFiltMax[23] = 867820000;
-	state->CTFiltMax[24] = 915980000;
-	state->CTFiltMax[25] = 947450000;
-	state->CTFiltMax[26] = 983110000;
-	state->CTFiltMax[27] = 1021630000;
-	state->CTFiltMax[28] = 1061870000;
-	state->CTFiltMax[29] = 1098330000;
-	state->CTFiltMax[30] = 1138990000;
-
-	/*
-	 **   Fetch the FCU osc value and use it and the fRef value to
-	 **   scale all of the Band Max values
-	 */
-
-	state->reg[MT2063_REG_CTUNE_CTRL] = 0x0A;
-	status = mt2063_write(state, MT2063_REG_CTUNE_CTRL,
-			      &state->reg[MT2063_REG_CTUNE_CTRL], 1);
-	if (status < 0)
-		return status;
-
-	/*  Read the ClearTune filter calibration value  */
-	status = mt2063_read(state, MT2063_REG_FIFFC,
-			     &state->reg[MT2063_REG_FIFFC], 1);
-	if (status < 0)
-		return status;
-
-	fcu_osc = state->reg[MT2063_REG_FIFFC];
-
-	state->reg[MT2063_REG_CTUNE_CTRL] = 0x00;
-	status = mt2063_write(state, MT2063_REG_CTUNE_CTRL,
-			      &state->reg[MT2063_REG_CTUNE_CTRL], 1);
-	if (status < 0)
-		return status;
-
-	/*  Adjust each of the values in the ClearTune filter cross-over table  */
-	for (i = 0; i < 31; i++)
-		state->CTFiltMax[i] = (state->CTFiltMax[i] / 768) * (fcu_osc + 640);
-
-	status = MT2063_SoftwareShutdown(state, 1);
-	if (status < 0)
-		return status;
-	status = MT2063_ClearPowerMaskBits(state, MT2063_ALL_SD);
-	if (status < 0)
-		return status;
-
-	state->init = true;
-
-	return 0;
-}
-
-static int mt2063_get_status(struct dvb_frontend *fe, u32 *tuner_status)
-{
-	struct mt2063_state *state = fe->tuner_priv;
-	int status;
-
-	dprintk(2, "\n");
-
-	if (!state->init)
-		return -ENODEV;
-
-	*tuner_status = 0;
-	status = mt2063_lockStatus(state);
-	if (status < 0)
-		return status;
-	if (status)
-		*tuner_status = TUNER_STATUS_LOCKED;
-
-	dprintk(1, "Tuner status: %d", *tuner_status);
-
-	return 0;
-}
-
-static int mt2063_release(struct dvb_frontend *fe)
-{
-	struct mt2063_state *state = fe->tuner_priv;
-
-	dprintk(2, "\n");
-
-	fe->tuner_priv = NULL;
-	kfree(state);
-
-	return 0;
-}
-
-static int mt2063_set_analog_params(struct dvb_frontend *fe,
-				    struct analog_parameters *params)
-{
-	struct mt2063_state *state = fe->tuner_priv;
-	s32 pict_car;
-	s32 pict2chanb_vsb;
-	s32 ch_bw;
-	s32 if_mid;
-	s32 rcvr_mode;
-	int status;
-
-	dprintk(2, "\n");
-
-	if (!state->init) {
-		status = mt2063_init(fe);
-		if (status < 0)
-			return status;
-	}
-
-	switch (params->mode) {
-	case V4L2_TUNER_RADIO:
-		pict_car = 38900000;
-		ch_bw = 8000000;
-		pict2chanb_vsb = -(ch_bw / 2);
-		rcvr_mode = MT2063_OFFAIR_ANALOG;
-		break;
-	case V4L2_TUNER_ANALOG_TV:
-		rcvr_mode = MT2063_CABLE_ANALOG;
-		if (params->std & ~V4L2_STD_MN) {
-			pict_car = 38900000;
-			ch_bw = 6000000;
-			pict2chanb_vsb = -1250000;
-		} else if (params->std & V4L2_STD_PAL_G) {
-			pict_car = 38900000;
-			ch_bw = 7000000;
-			pict2chanb_vsb = -1250000;
-		} else {		/* PAL/SECAM standards */
-			pict_car = 38900000;
-			ch_bw = 8000000;
-			pict2chanb_vsb = -1250000;
-		}
-		break;
-	default:
-		return -EINVAL;
-	}
-	if_mid = pict_car - (pict2chanb_vsb + (ch_bw / 2));
-
-	state->AS_Data.f_LO2_Step = 125000;	/* FIXME: probably 5000 for FM */
-	state->AS_Data.f_out = if_mid;
-	state->AS_Data.f_out_bw = ch_bw + 750000;
-	status = MT2063_SetReceiverMode(state, rcvr_mode);
-	if (status < 0)
-		return status;
-
-	dprintk(1, "Tuning to frequency: %d, bandwidth %d, foffset %d\n",
-		params->frequency, ch_bw, pict2chanb_vsb);
-
-	status = MT2063_Tune(state, (params->frequency + (pict2chanb_vsb + (ch_bw / 2))));
-	if (status < 0)
-		return status;
-
-	state->frequency = params->frequency;
-	return 0;
-}
-
-/*
- * As defined on EN 300 429, the DVB-C roll-off factor is 0.15.
- * So, the amount of the needed bandwith is given by:
- *	Bw = Symbol_rate * (1 + 0.15)
- * As such, the maximum symbol rate supported by 6 MHz is given by:
- *	max_symbol_rate = 6 MHz / 1.15 = 5217391 Bauds
- */
-#define MAX_SYMBOL_RATE_6MHz	5217391
-
-static int mt2063_set_params(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	struct mt2063_state *state = fe->tuner_priv;
-	int status;
-	s32 pict_car;
-	s32 pict2chanb_vsb;
-	s32 ch_bw;
-	s32 if_mid;
-	s32 rcvr_mode;
-
-	if (!state->init) {
-		status = mt2063_init(fe);
-		if (status < 0)
-			return status;
-	}
-
-	dprintk(2, "\n");
-
-	if (c->bandwidth_hz == 0)
-		return -EINVAL;
-	if (c->bandwidth_hz <= 6000000)
-		ch_bw = 6000000;
-	else if (c->bandwidth_hz <= 7000000)
-		ch_bw = 7000000;
-	else
-		ch_bw = 8000000;
-
-	switch (c->delivery_system) {
-	case SYS_DVBT:
-		rcvr_mode = MT2063_OFFAIR_COFDM;
-		pict_car = 36125000;
-		pict2chanb_vsb = -(ch_bw / 2);
-		break;
-	case SYS_DVBC_ANNEX_A:
-	case SYS_DVBC_ANNEX_C:
-		rcvr_mode = MT2063_CABLE_QAM;
-		pict_car = 36125000;
-		pict2chanb_vsb = -(ch_bw / 2);
-		break;
-	default:
-		return -EINVAL;
-	}
-	if_mid = pict_car - (pict2chanb_vsb + (ch_bw / 2));
-
-	state->AS_Data.f_LO2_Step = 125000;	/* FIXME: probably 5000 for FM */
-	state->AS_Data.f_out = if_mid;
-	state->AS_Data.f_out_bw = ch_bw + 750000;
-	status = MT2063_SetReceiverMode(state, rcvr_mode);
-	if (status < 0)
-		return status;
-
-	dprintk(1, "Tuning to frequency: %d, bandwidth %d, foffset %d\n",
-		c->frequency, ch_bw, pict2chanb_vsb);
-
-	status = MT2063_Tune(state, (c->frequency + (pict2chanb_vsb + (ch_bw / 2))));
-
-	if (status < 0)
-		return status;
-
-	state->frequency = c->frequency;
-	return 0;
-}
-
-static int mt2063_get_if_frequency(struct dvb_frontend *fe, u32 *freq)
-{
-	struct mt2063_state *state = fe->tuner_priv;
-
-	dprintk(2, "\n");
-
-	if (!state->init)
-		return -ENODEV;
-
-	*freq = state->AS_Data.f_out;
-
-	dprintk(1, "IF frequency: %d\n", *freq);
-
-	return 0;
-}
-
-static int mt2063_get_bandwidth(struct dvb_frontend *fe, u32 *bw)
-{
-	struct mt2063_state *state = fe->tuner_priv;
-
-	dprintk(2, "\n");
-
-	if (!state->init)
-		return -ENODEV;
-
-	*bw = state->AS_Data.f_out_bw - 750000;
-
-	dprintk(1, "bandwidth: %d\n", *bw);
-
-	return 0;
-}
-
-static struct dvb_tuner_ops mt2063_ops = {
-	.info = {
-		 .name = "MT2063 Silicon Tuner",
-		 .frequency_min = 45000000,
-		 .frequency_max = 865000000,
-		 .frequency_step = 0,
-		 },
-
-	.init = mt2063_init,
-	.sleep = MT2063_Sleep,
-	.get_status = mt2063_get_status,
-	.set_analog_params = mt2063_set_analog_params,
-	.set_params    = mt2063_set_params,
-	.get_if_frequency = mt2063_get_if_frequency,
-	.get_bandwidth = mt2063_get_bandwidth,
-	.release = mt2063_release,
-};
-
-struct dvb_frontend *mt2063_attach(struct dvb_frontend *fe,
-				   struct mt2063_config *config,
-				   struct i2c_adapter *i2c)
-{
-	struct mt2063_state *state = NULL;
-
-	dprintk(2, "\n");
-
-	state = kzalloc(sizeof(struct mt2063_state), GFP_KERNEL);
-	if (state == NULL)
-		goto error;
-
-	state->config = config;
-	state->i2c = i2c;
-	state->frontend = fe;
-	state->reference = config->refclock / 1000;	/* kHz */
-	fe->tuner_priv = state;
-	fe->ops.tuner_ops = mt2063_ops;
-
-	printk(KERN_INFO "%s: Attaching MT2063\n", __func__);
-	return fe;
-
-error:
-	kfree(state);
-	return NULL;
-}
-EXPORT_SYMBOL_GPL(mt2063_attach);
-
-/*
- * Ancillary routines visible outside mt2063
- * FIXME: Remove them in favor of using standard tuner callbacks
- */
-unsigned int tuner_MT2063_SoftwareShutdown(struct dvb_frontend *fe)
-{
-	struct mt2063_state *state = fe->tuner_priv;
-	int err = 0;
-
-	dprintk(2, "\n");
-
-	err = MT2063_SoftwareShutdown(state, 1);
-	if (err < 0)
-		printk(KERN_ERR "%s: Couldn't shutdown\n", __func__);
-
-	return err;
-}
-EXPORT_SYMBOL_GPL(tuner_MT2063_SoftwareShutdown);
-
-unsigned int tuner_MT2063_ClearPowerMaskBits(struct dvb_frontend *fe)
-{
-	struct mt2063_state *state = fe->tuner_priv;
-	int err = 0;
-
-	dprintk(2, "\n");
-
-	err = MT2063_ClearPowerMaskBits(state, MT2063_ALL_SD);
-	if (err < 0)
-		printk(KERN_ERR "%s: Invalid parameter\n", __func__);
-
-	return err;
-}
-EXPORT_SYMBOL_GPL(tuner_MT2063_ClearPowerMaskBits);
-
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
-MODULE_DESCRIPTION("MT2063 Silicon tuner");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/common/tuners/mt2063.h b/drivers/media/common/tuners/mt2063.h
deleted file mode 100644
index 3f5cfd9..0000000
--- a/drivers/media/common/tuners/mt2063.h
+++ /dev/null
@@ -1,32 +0,0 @@
-#ifndef __MT2063_H__
-#define __MT2063_H__
-
-#include "dvb_frontend.h"
-
-struct mt2063_config {
-	u8 tuner_address;
-	u32 refclock;
-};
-
-#if defined(CONFIG_MEDIA_TUNER_MT2063) || (defined(CONFIG_MEDIA_TUNER_MT2063_MODULE) && defined(MODULE))
-struct dvb_frontend *mt2063_attach(struct dvb_frontend *fe,
-				   struct mt2063_config *config,
-				   struct i2c_adapter *i2c);
-
-#else
-
-static inline struct dvb_frontend *mt2063_attach(struct dvb_frontend *fe,
-				   struct mt2063_config *config,
-				   struct i2c_adapter *i2c)
-{
-	printk(KERN_WARNING "%s: Driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-
-/* FIXME: Should use the standard DVB attachment interfaces */
-unsigned int tuner_MT2063_SoftwareShutdown(struct dvb_frontend *fe);
-unsigned int tuner_MT2063_ClearPowerMaskBits(struct dvb_frontend *fe);
-
-#endif /* CONFIG_DVB_MT2063 */
-
-#endif /* __MT2063_H__ */
diff --git a/drivers/media/common/tuners/mt20xx.c b/drivers/media/common/tuners/mt20xx.c
deleted file mode 100644
index 0e74e97..0000000
--- a/drivers/media/common/tuners/mt20xx.c
+++ /dev/null
@@ -1,670 +0,0 @@
-/*
- * i2c tv tuner chip device driver
- * controls microtune tuners, mt2032 + mt2050 at the moment.
- *
- * This "mt20xx" module was split apart from the original "tuner" module.
- */
-#include <linux/delay.h>
-#include <linux/i2c.h>
-#include <linux/slab.h>
-#include <linux/videodev2.h>
-#include "tuner-i2c.h"
-#include "mt20xx.h"
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "enable verbose debug messages");
-
-/* ---------------------------------------------------------------------- */
-
-static unsigned int optimize_vco  = 1;
-module_param(optimize_vco,      int, 0644);
-
-static unsigned int tv_antenna    = 1;
-module_param(tv_antenna,        int, 0644);
-
-static unsigned int radio_antenna;
-module_param(radio_antenna,     int, 0644);
-
-/* ---------------------------------------------------------------------- */
-
-#define MT2032 0x04
-#define MT2030 0x06
-#define MT2040 0x07
-#define MT2050 0x42
-
-static char *microtune_part[] = {
-	[ MT2030 ] = "MT2030",
-	[ MT2032 ] = "MT2032",
-	[ MT2040 ] = "MT2040",
-	[ MT2050 ] = "MT2050",
-};
-
-struct microtune_priv {
-	struct tuner_i2c_props i2c_props;
-
-	unsigned int xogc;
-	//unsigned int radio_if2;
-
-	u32 frequency;
-};
-
-static int microtune_release(struct dvb_frontend *fe)
-{
-	kfree(fe->tuner_priv);
-	fe->tuner_priv = NULL;
-
-	return 0;
-}
-
-static int microtune_get_frequency(struct dvb_frontend *fe, u32 *frequency)
-{
-	struct microtune_priv *priv = fe->tuner_priv;
-	*frequency = priv->frequency;
-	return 0;
-}
-
-// IsSpurInBand()?
-static int mt2032_spurcheck(struct dvb_frontend *fe,
-			    int f1, int f2, int spectrum_from,int spectrum_to)
-{
-	struct microtune_priv *priv = fe->tuner_priv;
-	int n1=1,n2,f;
-
-	f1=f1/1000; //scale to kHz to avoid 32bit overflows
-	f2=f2/1000;
-	spectrum_from/=1000;
-	spectrum_to/=1000;
-
-	tuner_dbg("spurcheck f1=%d f2=%d  from=%d to=%d\n",
-		  f1,f2,spectrum_from,spectrum_to);
-
-	do {
-	    n2=-n1;
-	    f=n1*(f1-f2);
-	    do {
-		n2--;
-		f=f-f2;
-		tuner_dbg("spurtest n1=%d n2=%d ftest=%d\n",n1,n2,f);
-
-		if( (f>spectrum_from) && (f<spectrum_to))
-			tuner_dbg("mt2032 spurcheck triggered: %d\n",n1);
-	    } while ( (f>(f2-spectrum_to)) || (n2>-5));
-	    n1++;
-	} while (n1<5);
-
-	return 1;
-}
-
-static int mt2032_compute_freq(struct dvb_frontend *fe,
-			       unsigned int rfin,
-			       unsigned int if1, unsigned int if2,
-			       unsigned int spectrum_from,
-			       unsigned int spectrum_to,
-			       unsigned char *buf,
-			       int *ret_sel,
-			       unsigned int xogc) //all in Hz
-{
-	struct microtune_priv *priv = fe->tuner_priv;
-	unsigned int fref,lo1,lo1n,lo1a,s,sel,lo1freq, desired_lo1,
-		desired_lo2,lo2,lo2n,lo2a,lo2num,lo2freq;
-
-	fref= 5250 *1000; //5.25MHz
-	desired_lo1=rfin+if1;
-
-	lo1=(2*(desired_lo1/1000)+(fref/1000)) / (2*fref/1000);
-	lo1n=lo1/8;
-	lo1a=lo1-(lo1n*8);
-
-	s=rfin/1000/1000+1090;
-
-	if(optimize_vco) {
-		if(s>1890) sel=0;
-		else if(s>1720) sel=1;
-		else if(s>1530) sel=2;
-		else if(s>1370) sel=3;
-		else sel=4; // >1090
-	}
-	else {
-		if(s>1790) sel=0; // <1958
-		else if(s>1617) sel=1;
-		else if(s>1449) sel=2;
-		else if(s>1291) sel=3;
-		else sel=4; // >1090
-	}
-	*ret_sel=sel;
-
-	lo1freq=(lo1a+8*lo1n)*fref;
-
-	tuner_dbg("mt2032: rfin=%d lo1=%d lo1n=%d lo1a=%d sel=%d, lo1freq=%d\n",
-		  rfin,lo1,lo1n,lo1a,sel,lo1freq);
-
-	desired_lo2=lo1freq-rfin-if2;
-	lo2=(desired_lo2)/fref;
-	lo2n=lo2/8;
-	lo2a=lo2-(lo2n*8);
-	lo2num=((desired_lo2/1000)%(fref/1000))* 3780/(fref/1000); //scale to fit in 32bit arith
-	lo2freq=(lo2a+8*lo2n)*fref + lo2num*(fref/1000)/3780*1000;
-
-	tuner_dbg("mt2032: rfin=%d lo2=%d lo2n=%d lo2a=%d num=%d lo2freq=%d\n",
-		  rfin,lo2,lo2n,lo2a,lo2num,lo2freq);
-
-	if (lo1a > 7 || lo1n < 17 || lo1n > 48 || lo2a > 7 || lo2n < 17 ||
-			lo2n > 30) {
-		tuner_info("mt2032: frequency parameters out of range: %d %d %d %d\n",
-			   lo1a, lo1n, lo2a,lo2n);
-		return(-1);
-	}
-
-	mt2032_spurcheck(fe, lo1freq, desired_lo2,  spectrum_from, spectrum_to);
-	// should recalculate lo1 (one step up/down)
-
-	// set up MT2032 register map for transfer over i2c
-	buf[0]=lo1n-1;
-	buf[1]=lo1a | (sel<<4);
-	buf[2]=0x86; // LOGC
-	buf[3]=0x0f; //reserved
-	buf[4]=0x1f;
-	buf[5]=(lo2n-1) | (lo2a<<5);
-	if(rfin >400*1000*1000)
-		buf[6]=0xe4;
-	else
-		buf[6]=0xf4; // set PKEN per rev 1.2
-	buf[7]=8+xogc;
-	buf[8]=0xc3; //reserved
-	buf[9]=0x4e; //reserved
-	buf[10]=0xec; //reserved
-	buf[11]=(lo2num&0xff);
-	buf[12]=(lo2num>>8) |0x80; // Lo2RST
-
-	return 0;
-}
-
-static int mt2032_check_lo_lock(struct dvb_frontend *fe)
-{
-	struct microtune_priv *priv = fe->tuner_priv;
-	int try,lock=0;
-	unsigned char buf[2];
-
-	for(try=0;try<10;try++) {
-		buf[0]=0x0e;
-		tuner_i2c_xfer_send(&priv->i2c_props,buf,1);
-		tuner_i2c_xfer_recv(&priv->i2c_props,buf,1);
-		tuner_dbg("mt2032 Reg.E=0x%02x\n",buf[0]);
-		lock=buf[0] &0x06;
-
-		if (lock==6)
-			break;
-
-		tuner_dbg("mt2032: pll wait 1ms for lock (0x%2x)\n",buf[0]);
-		udelay(1000);
-	}
-	return lock;
-}
-
-static int mt2032_optimize_vco(struct dvb_frontend *fe,int sel,int lock)
-{
-	struct microtune_priv *priv = fe->tuner_priv;
-	unsigned char buf[2];
-	int tad1;
-
-	buf[0]=0x0f;
-	tuner_i2c_xfer_send(&priv->i2c_props,buf,1);
-	tuner_i2c_xfer_recv(&priv->i2c_props,buf,1);
-	tuner_dbg("mt2032 Reg.F=0x%02x\n",buf[0]);
-	tad1=buf[0]&0x07;
-
-	if(tad1 ==0) return lock;
-	if(tad1 ==1) return lock;
-
-	if(tad1==2) {
-		if(sel==0)
-			return lock;
-		else sel--;
-	}
-	else {
-		if(sel<4)
-			sel++;
-		else
-			return lock;
-	}
-
-	tuner_dbg("mt2032 optimize_vco: sel=%d\n",sel);
-
-	buf[0]=0x0f;
-	buf[1]=sel;
-	tuner_i2c_xfer_send(&priv->i2c_props,buf,2);
-	lock=mt2032_check_lo_lock(fe);
-	return lock;
-}
-
-
-static void mt2032_set_if_freq(struct dvb_frontend *fe, unsigned int rfin,
-			       unsigned int if1, unsigned int if2,
-			       unsigned int from, unsigned int to)
-{
-	unsigned char buf[21];
-	int lint_try,ret,sel,lock=0;
-	struct microtune_priv *priv = fe->tuner_priv;
-
-	tuner_dbg("mt2032_set_if_freq rfin=%d if1=%d if2=%d from=%d to=%d\n",
-		  rfin,if1,if2,from,to);
-
-	buf[0]=0;
-	ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,1);
-	tuner_i2c_xfer_recv(&priv->i2c_props,buf,21);
-
-	buf[0]=0;
-	ret=mt2032_compute_freq(fe,rfin,if1,if2,from,to,&buf[1],&sel,priv->xogc);
-	if (ret<0)
-		return;
-
-	// send only the relevant registers per Rev. 1.2
-	buf[0]=0;
-	ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,4);
-	buf[5]=5;
-	ret=tuner_i2c_xfer_send(&priv->i2c_props,buf+5,4);
-	buf[11]=11;
-	ret=tuner_i2c_xfer_send(&priv->i2c_props,buf+11,3);
-	if(ret!=3)
-		tuner_warn("i2c i/o error: rc == %d (should be 3)\n",ret);
-
-	// wait for PLLs to lock (per manual), retry LINT if not.
-	for(lint_try=0; lint_try<2; lint_try++) {
-		lock=mt2032_check_lo_lock(fe);
-
-		if(optimize_vco)
-			lock=mt2032_optimize_vco(fe,sel,lock);
-		if(lock==6) break;
-
-		tuner_dbg("mt2032: re-init PLLs by LINT\n");
-		buf[0]=7;
-		buf[1]=0x80 +8+priv->xogc; // set LINT to re-init PLLs
-		tuner_i2c_xfer_send(&priv->i2c_props,buf,2);
-		mdelay(10);
-		buf[1]=8+priv->xogc;
-		tuner_i2c_xfer_send(&priv->i2c_props,buf,2);
-	}
-
-	if (lock!=6)
-		tuner_warn("MT2032 Fatal Error: PLLs didn't lock.\n");
-
-	buf[0]=2;
-	buf[1]=0x20; // LOGC for optimal phase noise
-	ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,2);
-	if (ret!=2)
-		tuner_warn("i2c i/o error: rc == %d (should be 2)\n",ret);
-}
-
-
-static int mt2032_set_tv_freq(struct dvb_frontend *fe,
-			      struct analog_parameters *params)
-{
-	int if2,from,to;
-
-	// signal bandwidth and picture carrier
-	if (params->std & V4L2_STD_525_60) {
-		// NTSC
-		from = 40750*1000;
-		to   = 46750*1000;
-		if2  = 45750*1000;
-	} else {
-		// PAL
-		from = 32900*1000;
-		to   = 39900*1000;
-		if2  = 38900*1000;
-	}
-
-	mt2032_set_if_freq(fe, params->frequency*62500,
-			   1090*1000*1000, if2, from, to);
-
-	return 0;
-}
-
-static int mt2032_set_radio_freq(struct dvb_frontend *fe,
-				 struct analog_parameters *params)
-{
-	struct microtune_priv *priv = fe->tuner_priv;
-	int if2;
-
-	if (params->std & V4L2_STD_525_60) {
-		tuner_dbg("pinnacle ntsc\n");
-		if2 = 41300 * 1000;
-	} else {
-		tuner_dbg("pinnacle pal\n");
-		if2 = 33300 * 1000;
-	}
-
-	// per Manual for FM tuning: first if center freq. 1085 MHz
-	mt2032_set_if_freq(fe, params->frequency * 125 / 2,
-			   1085*1000*1000,if2,if2,if2);
-
-	return 0;
-}
-
-static int mt2032_set_params(struct dvb_frontend *fe,
-			     struct analog_parameters *params)
-{
-	struct microtune_priv *priv = fe->tuner_priv;
-	int ret = -EINVAL;
-
-	switch (params->mode) {
-	case V4L2_TUNER_RADIO:
-		ret = mt2032_set_radio_freq(fe, params);
-		priv->frequency = params->frequency * 125 / 2;
-		break;
-	case V4L2_TUNER_ANALOG_TV:
-	case V4L2_TUNER_DIGITAL_TV:
-		ret = mt2032_set_tv_freq(fe, params);
-		priv->frequency = params->frequency * 62500;
-		break;
-	}
-
-	return ret;
-}
-
-static struct dvb_tuner_ops mt2032_tuner_ops = {
-	.set_analog_params = mt2032_set_params,
-	.release           = microtune_release,
-	.get_frequency     = microtune_get_frequency,
-};
-
-// Initialization as described in "MT203x Programming Procedures", Rev 1.2, Feb.2001
-static int mt2032_init(struct dvb_frontend *fe)
-{
-	struct microtune_priv *priv = fe->tuner_priv;
-	unsigned char buf[21];
-	int ret,xogc,xok=0;
-
-	// Initialize Registers per spec.
-	buf[1]=2; // Index to register 2
-	buf[2]=0xff;
-	buf[3]=0x0f;
-	buf[4]=0x1f;
-	ret=tuner_i2c_xfer_send(&priv->i2c_props,buf+1,4);
-
-	buf[5]=6; // Index register 6
-	buf[6]=0xe4;
-	buf[7]=0x8f;
-	buf[8]=0xc3;
-	buf[9]=0x4e;
-	buf[10]=0xec;
-	ret=tuner_i2c_xfer_send(&priv->i2c_props,buf+5,6);
-
-	buf[12]=13;  // Index register 13
-	buf[13]=0x32;
-	ret=tuner_i2c_xfer_send(&priv->i2c_props,buf+12,2);
-
-	// Adjust XOGC (register 7), wait for XOK
-	xogc=7;
-	do {
-		tuner_dbg("mt2032: xogc = 0x%02x\n",xogc&0x07);
-		mdelay(10);
-		buf[0]=0x0e;
-		tuner_i2c_xfer_send(&priv->i2c_props,buf,1);
-		tuner_i2c_xfer_recv(&priv->i2c_props,buf,1);
-		xok=buf[0]&0x01;
-		tuner_dbg("mt2032: xok = 0x%02x\n",xok);
-		if (xok == 1) break;
-
-		xogc--;
-		tuner_dbg("mt2032: xogc = 0x%02x\n",xogc&0x07);
-		if (xogc == 3) {
-			xogc=4; // min. 4 per spec
-			break;
-		}
-		buf[0]=0x07;
-		buf[1]=0x88 + xogc;
-		ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,2);
-		if (ret!=2)
-			tuner_warn("i2c i/o error: rc == %d (should be 2)\n",ret);
-	} while (xok != 1 );
-	priv->xogc=xogc;
-
-	memcpy(&fe->ops.tuner_ops, &mt2032_tuner_ops, sizeof(struct dvb_tuner_ops));
-
-	return(1);
-}
-
-static void mt2050_set_antenna(struct dvb_frontend *fe, unsigned char antenna)
-{
-	struct microtune_priv *priv = fe->tuner_priv;
-	unsigned char buf[2];
-
-	buf[0] = 6;
-	buf[1] = antenna ? 0x11 : 0x10;
-	tuner_i2c_xfer_send(&priv->i2c_props, buf, 2);
-	tuner_dbg("mt2050: enabled antenna connector %d\n", antenna);
-}
-
-static void mt2050_set_if_freq(struct dvb_frontend *fe,unsigned int freq, unsigned int if2)
-{
-	struct microtune_priv *priv = fe->tuner_priv;
-	unsigned int if1=1218*1000*1000;
-	unsigned int f_lo1,f_lo2,lo1,lo2,f_lo1_modulo,f_lo2_modulo,num1,num2,div1a,div1b,div2a,div2b;
-	int ret;
-	unsigned char buf[6];
-
-	tuner_dbg("mt2050_set_if_freq freq=%d if1=%d if2=%d\n",
-		  freq,if1,if2);
-
-	f_lo1=freq+if1;
-	f_lo1=(f_lo1/1000000)*1000000;
-
-	f_lo2=f_lo1-freq-if2;
-	f_lo2=(f_lo2/50000)*50000;
-
-	lo1=f_lo1/4000000;
-	lo2=f_lo2/4000000;
-
-	f_lo1_modulo= f_lo1-(lo1*4000000);
-	f_lo2_modulo= f_lo2-(lo2*4000000);
-
-	num1=4*f_lo1_modulo/4000000;
-	num2=4096*(f_lo2_modulo/1000)/4000;
-
-	// todo spurchecks
-
-	div1a=(lo1/12)-1;
-	div1b=lo1-(div1a+1)*12;
-
-	div2a=(lo2/8)-1;
-	div2b=lo2-(div2a+1)*8;
-
-	if (debug > 1) {
-		tuner_dbg("lo1 lo2 = %d %d\n", lo1, lo2);
-		tuner_dbg("num1 num2 div1a div1b div2a div2b= %x %x %x %x %x %x\n",
-			  num1,num2,div1a,div1b,div2a,div2b);
-	}
-
-	buf[0]=1;
-	buf[1]= 4*div1b + num1;
-	if(freq<275*1000*1000) buf[1] = buf[1]|0x80;
-
-	buf[2]=div1a;
-	buf[3]=32*div2b + num2/256;
-	buf[4]=num2-(num2/256)*256;
-	buf[5]=div2a;
-	if(num2!=0) buf[5]=buf[5]|0x40;
-
-	if (debug > 1) {
-		int i;
-		tuner_dbg("bufs is: ");
-		for(i=0;i<6;i++)
-			printk("%x ",buf[i]);
-		printk("\n");
-	}
-
-	ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,6);
-	if (ret!=6)
-		tuner_warn("i2c i/o error: rc == %d (should be 6)\n",ret);
-}
-
-static int mt2050_set_tv_freq(struct dvb_frontend *fe,
-			      struct analog_parameters *params)
-{
-	unsigned int if2;
-
-	if (params->std & V4L2_STD_525_60) {
-		// NTSC
-		if2 = 45750*1000;
-	} else {
-		// PAL
-		if2 = 38900*1000;
-	}
-	if (V4L2_TUNER_DIGITAL_TV == params->mode) {
-		// DVB (pinnacle 300i)
-		if2 = 36150*1000;
-	}
-	mt2050_set_if_freq(fe, params->frequency*62500, if2);
-	mt2050_set_antenna(fe, tv_antenna);
-
-	return 0;
-}
-
-static int mt2050_set_radio_freq(struct dvb_frontend *fe,
-				 struct analog_parameters *params)
-{
-	struct microtune_priv *priv = fe->tuner_priv;
-	int if2;
-
-	if (params->std & V4L2_STD_525_60) {
-		tuner_dbg("pinnacle ntsc\n");
-		if2 = 41300 * 1000;
-	} else {
-		tuner_dbg("pinnacle pal\n");
-		if2 = 33300 * 1000;
-	}
-
-	mt2050_set_if_freq(fe, params->frequency * 125 / 2, if2);
-	mt2050_set_antenna(fe, radio_antenna);
-
-	return 0;
-}
-
-static int mt2050_set_params(struct dvb_frontend *fe,
-			     struct analog_parameters *params)
-{
-	struct microtune_priv *priv = fe->tuner_priv;
-	int ret = -EINVAL;
-
-	switch (params->mode) {
-	case V4L2_TUNER_RADIO:
-		ret = mt2050_set_radio_freq(fe, params);
-		priv->frequency = params->frequency * 125 / 2;
-		break;
-	case V4L2_TUNER_ANALOG_TV:
-	case V4L2_TUNER_DIGITAL_TV:
-		ret = mt2050_set_tv_freq(fe, params);
-		priv->frequency = params->frequency * 62500;
-		break;
-	}
-
-	return ret;
-}
-
-static struct dvb_tuner_ops mt2050_tuner_ops = {
-	.set_analog_params = mt2050_set_params,
-	.release           = microtune_release,
-	.get_frequency     = microtune_get_frequency,
-};
-
-static int mt2050_init(struct dvb_frontend *fe)
-{
-	struct microtune_priv *priv = fe->tuner_priv;
-	unsigned char buf[2];
-
-	buf[0] = 6;
-	buf[1] = 0x10;
-	tuner_i2c_xfer_send(&priv->i2c_props, buf, 2); /* power */
-
-	buf[0] = 0x0f;
-	buf[1] = 0x0f;
-	tuner_i2c_xfer_send(&priv->i2c_props, buf, 2); /* m1lo */
-
-	buf[0] = 0x0d;
-	tuner_i2c_xfer_send(&priv->i2c_props, buf, 1);
-	tuner_i2c_xfer_recv(&priv->i2c_props, buf, 1);
-
-	tuner_dbg("mt2050: sro is %x\n", buf[0]);
-
-	memcpy(&fe->ops.tuner_ops, &mt2050_tuner_ops, sizeof(struct dvb_tuner_ops));
-
-	return 0;
-}
-
-struct dvb_frontend *microtune_attach(struct dvb_frontend *fe,
-				      struct i2c_adapter* i2c_adap,
-				      u8 i2c_addr)
-{
-	struct microtune_priv *priv = NULL;
-	char *name;
-	unsigned char buf[21];
-	int company_code;
-
-	priv = kzalloc(sizeof(struct microtune_priv), GFP_KERNEL);
-	if (priv == NULL)
-		return NULL;
-	fe->tuner_priv = priv;
-
-	priv->i2c_props.addr = i2c_addr;
-	priv->i2c_props.adap = i2c_adap;
-	priv->i2c_props.name = "mt20xx";
-
-	//priv->radio_if2 = 10700 * 1000;	/* 10.7MHz - FM radio */
-
-	memset(buf,0,sizeof(buf));
-
-	name = "unknown";
-
-	tuner_i2c_xfer_send(&priv->i2c_props,buf,1);
-	tuner_i2c_xfer_recv(&priv->i2c_props,buf,21);
-	if (debug) {
-		int i;
-		tuner_dbg("MT20xx hexdump:");
-		for(i=0;i<21;i++) {
-			printk(" %02x",buf[i]);
-			if(((i+1)%8)==0) printk(" ");
-		}
-		printk("\n");
-	}
-	company_code = buf[0x11] << 8 | buf[0x12];
-	tuner_info("microtune: companycode=%04x part=%02x rev=%02x\n",
-		   company_code,buf[0x13],buf[0x14]);
-
-
-	if (buf[0x13] < ARRAY_SIZE(microtune_part) &&
-	    NULL != microtune_part[buf[0x13]])
-		name = microtune_part[buf[0x13]];
-	switch (buf[0x13]) {
-	case MT2032:
-		mt2032_init(fe);
-		break;
-	case MT2050:
-		mt2050_init(fe);
-		break;
-	default:
-		tuner_info("microtune %s found, not (yet?) supported, sorry :-/\n",
-			   name);
-		return NULL;
-	}
-
-	strlcpy(fe->ops.tuner_ops.info.name, name,
-		sizeof(fe->ops.tuner_ops.info.name));
-	tuner_info("microtune %s found, OK\n",name);
-	return fe;
-}
-
-EXPORT_SYMBOL_GPL(microtune_attach);
-
-MODULE_DESCRIPTION("Microtune tuner driver");
-MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer");
-MODULE_LICENSE("GPL");
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/common/tuners/mt20xx.h b/drivers/media/common/tuners/mt20xx.h
deleted file mode 100644
index 259553a..0000000
--- a/drivers/media/common/tuners/mt20xx.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the 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 __MT20XX_H__
-#define __MT20XX_H__
-
-#include <linux/i2c.h>
-#include "dvb_frontend.h"
-
-#if defined(CONFIG_MEDIA_TUNER_MT20XX) || (defined(CONFIG_MEDIA_TUNER_MT20XX_MODULE) && defined(MODULE))
-extern struct dvb_frontend *microtune_attach(struct dvb_frontend *fe,
-					     struct i2c_adapter* i2c_adap,
-					     u8 i2c_addr);
-#else
-static inline struct dvb_frontend *microtune_attach(struct dvb_frontend *fe,
-					     struct i2c_adapter* i2c_adap,
-					     u8 i2c_addr)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif
-
-#endif /* __MT20XX_H__ */
diff --git a/drivers/media/common/tuners/mt2131.c b/drivers/media/common/tuners/mt2131.c
deleted file mode 100644
index f83b0c1..0000000
--- a/drivers/media/common/tuners/mt2131.c
+++ /dev/null
@@ -1,301 +0,0 @@
-/*
- *  Driver for Microtune MT2131 "QAM/8VSB single chip tuner"
- *
- *  Copyright (c) 2006 Steven Toth <stoth@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/module.h>
-#include <linux/delay.h>
-#include <linux/dvb/frontend.h>
-#include <linux/i2c.h>
-#include <linux/slab.h>
-
-#include "dvb_frontend.h"
-
-#include "mt2131.h"
-#include "mt2131_priv.h"
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
-
-#define dprintk(level,fmt, arg...) if (debug >= level) \
-	printk(KERN_INFO "%s: " fmt, "mt2131", ## arg)
-
-static u8 mt2131_config1[] = {
-	0x01,
-	0x50, 0x00, 0x50, 0x80, 0x00, 0x49, 0xfa, 0x88,
-	0x08, 0x77, 0x41, 0x04, 0x00, 0x00, 0x00, 0x32,
-	0x7f, 0xda, 0x4c, 0x00, 0x10, 0xaa, 0x78, 0x80,
-	0xff, 0x68, 0xa0, 0xff, 0xdd, 0x00, 0x00
-};
-
-static u8 mt2131_config2[] = {
-	0x10,
-	0x7f, 0xc8, 0x0a, 0x5f, 0x00, 0x04
-};
-
-static int mt2131_readreg(struct mt2131_priv *priv, u8 reg, u8 *val)
-{
-	struct i2c_msg msg[2] = {
-		{ .addr = priv->cfg->i2c_address, .flags = 0,
-		  .buf = &reg, .len = 1 },
-		{ .addr = priv->cfg->i2c_address, .flags = I2C_M_RD,
-		  .buf = val,  .len = 1 },
-	};
-
-	if (i2c_transfer(priv->i2c, msg, 2) != 2) {
-		printk(KERN_WARNING "mt2131 I2C read failed\n");
-		return -EREMOTEIO;
-	}
-	return 0;
-}
-
-static int mt2131_writereg(struct mt2131_priv *priv, u8 reg, u8 val)
-{
-	u8 buf[2] = { reg, val };
-	struct i2c_msg msg = { .addr = priv->cfg->i2c_address, .flags = 0,
-			       .buf = buf, .len = 2 };
-
-	if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
-		printk(KERN_WARNING "mt2131 I2C write failed\n");
-		return -EREMOTEIO;
-	}
-	return 0;
-}
-
-static int mt2131_writeregs(struct mt2131_priv *priv,u8 *buf, u8 len)
-{
-	struct i2c_msg msg = { .addr = priv->cfg->i2c_address,
-			       .flags = 0, .buf = buf, .len = len };
-
-	if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
-		printk(KERN_WARNING "mt2131 I2C write failed (len=%i)\n",
-		       (int)len);
-		return -EREMOTEIO;
-	}
-	return 0;
-}
-
-static int mt2131_set_params(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	struct mt2131_priv *priv;
-	int ret=0, i;
-	u32 freq;
-	u8  if_band_center;
-	u32 f_lo1, f_lo2;
-	u32 div1, num1, div2, num2;
-	u8  b[8];
-	u8 lockval = 0;
-
-	priv = fe->tuner_priv;
-
-	freq = c->frequency / 1000;  /* Hz -> kHz */
-	dprintk(1, "%s() freq=%d\n", __func__, freq);
-
-	f_lo1 = freq + MT2131_IF1 * 1000;
-	f_lo1 = (f_lo1 / 250) * 250;
-	f_lo2 = f_lo1 - freq - MT2131_IF2;
-
-	priv->frequency =  (f_lo1 - f_lo2 - MT2131_IF2) * 1000;
-
-	/* Frequency LO1 = 16MHz * (DIV1 + NUM1/8192 ) */
-	num1 = f_lo1 * 64 / (MT2131_FREF / 128);
-	div1 = num1 / 8192;
-	num1 &= 0x1fff;
-
-	/* Frequency LO2 = 16MHz * (DIV2 + NUM2/8192 ) */
-	num2 = f_lo2 * 64 / (MT2131_FREF / 128);
-	div2 = num2 / 8192;
-	num2 &= 0x1fff;
-
-	if (freq <=   82500) if_band_center = 0x00; else
-	if (freq <=  137500) if_band_center = 0x01; else
-	if (freq <=  192500) if_band_center = 0x02; else
-	if (freq <=  247500) if_band_center = 0x03; else
-	if (freq <=  302500) if_band_center = 0x04; else
-	if (freq <=  357500) if_band_center = 0x05; else
-	if (freq <=  412500) if_band_center = 0x06; else
-	if (freq <=  467500) if_band_center = 0x07; else
-	if (freq <=  522500) if_band_center = 0x08; else
-	if (freq <=  577500) if_band_center = 0x09; else
-	if (freq <=  632500) if_band_center = 0x0A; else
-	if (freq <=  687500) if_band_center = 0x0B; else
-	if (freq <=  742500) if_band_center = 0x0C; else
-	if (freq <=  797500) if_band_center = 0x0D; else
-	if (freq <=  852500) if_band_center = 0x0E; else
-	if (freq <=  907500) if_band_center = 0x0F; else
-	if (freq <=  962500) if_band_center = 0x10; else
-	if (freq <= 1017500) if_band_center = 0x11; else
-	if (freq <= 1072500) if_band_center = 0x12; else if_band_center = 0x13;
-
-	b[0] = 1;
-	b[1] = (num1 >> 5) & 0xFF;
-	b[2] = (num1 & 0x1F);
-	b[3] = div1;
-	b[4] = (num2 >> 5) & 0xFF;
-	b[5] = num2 & 0x1F;
-	b[6] = div2;
-
-	dprintk(1, "IF1: %dMHz IF2: %dMHz\n", MT2131_IF1, MT2131_IF2);
-	dprintk(1, "PLL freq=%dkHz  band=%d\n", (int)freq, (int)if_band_center);
-	dprintk(1, "PLL f_lo1=%dkHz  f_lo2=%dkHz\n", (int)f_lo1, (int)f_lo2);
-	dprintk(1, "PLL div1=%d  num1=%d  div2=%d  num2=%d\n",
-		(int)div1, (int)num1, (int)div2, (int)num2);
-	dprintk(1, "PLL [1..6]: %2x %2x %2x %2x %2x %2x\n",
-		(int)b[1], (int)b[2], (int)b[3], (int)b[4], (int)b[5],
-		(int)b[6]);
-
-	ret = mt2131_writeregs(priv,b,7);
-	if (ret < 0)
-		return ret;
-
-	mt2131_writereg(priv, 0x0b, if_band_center);
-
-	/* Wait for lock */
-	i = 0;
-	do {
-		mt2131_readreg(priv, 0x08, &lockval);
-		if ((lockval & 0x88) == 0x88)
-			break;
-		msleep(4);
-		i++;
-	} while (i < 10);
-
-	return ret;
-}
-
-static int mt2131_get_frequency(struct dvb_frontend *fe, u32 *frequency)
-{
-	struct mt2131_priv *priv = fe->tuner_priv;
-	dprintk(1, "%s()\n", __func__);
-	*frequency = priv->frequency;
-	return 0;
-}
-
-static int mt2131_get_status(struct dvb_frontend *fe, u32 *status)
-{
-	struct mt2131_priv *priv = fe->tuner_priv;
-	u8 lock_status = 0;
-	u8 afc_status = 0;
-
-	*status = 0;
-
-	mt2131_readreg(priv, 0x08, &lock_status);
-	if ((lock_status & 0x88) == 0x88)
-		*status = TUNER_STATUS_LOCKED;
-
-	mt2131_readreg(priv, 0x09, &afc_status);
-	dprintk(1, "%s() - LO Status = 0x%x, AFC Status = 0x%x\n",
-		__func__, lock_status, afc_status);
-
-	return 0;
-}
-
-static int mt2131_init(struct dvb_frontend *fe)
-{
-	struct mt2131_priv *priv = fe->tuner_priv;
-	int ret;
-	dprintk(1, "%s()\n", __func__);
-
-	if ((ret = mt2131_writeregs(priv, mt2131_config1,
-				    sizeof(mt2131_config1))) < 0)
-		return ret;
-
-	mt2131_writereg(priv, 0x0b, 0x09);
-	mt2131_writereg(priv, 0x15, 0x47);
-	mt2131_writereg(priv, 0x07, 0xf2);
-	mt2131_writereg(priv, 0x0b, 0x01);
-
-	if ((ret = mt2131_writeregs(priv, mt2131_config2,
-				    sizeof(mt2131_config2))) < 0)
-		return ret;
-
-	return ret;
-}
-
-static int mt2131_release(struct dvb_frontend *fe)
-{
-	dprintk(1, "%s()\n", __func__);
-	kfree(fe->tuner_priv);
-	fe->tuner_priv = NULL;
-	return 0;
-}
-
-static const struct dvb_tuner_ops mt2131_tuner_ops = {
-	.info = {
-		.name           = "Microtune MT2131",
-		.frequency_min  =  48000000,
-		.frequency_max  = 860000000,
-		.frequency_step =     50000,
-	},
-
-	.release       = mt2131_release,
-	.init          = mt2131_init,
-
-	.set_params    = mt2131_set_params,
-	.get_frequency = mt2131_get_frequency,
-	.get_status    = mt2131_get_status
-};
-
-struct dvb_frontend * mt2131_attach(struct dvb_frontend *fe,
-				    struct i2c_adapter *i2c,
-				    struct mt2131_config *cfg, u16 if1)
-{
-	struct mt2131_priv *priv = NULL;
-	u8 id = 0;
-
-	dprintk(1, "%s()\n", __func__);
-
-	priv = kzalloc(sizeof(struct mt2131_priv), GFP_KERNEL);
-	if (priv == NULL)
-		return NULL;
-
-	priv->cfg = cfg;
-	priv->i2c = i2c;
-
-	if (mt2131_readreg(priv, 0, &id) != 0) {
-		kfree(priv);
-		return NULL;
-	}
-	if ( (id != 0x3E) && (id != 0x3F) ) {
-		printk(KERN_ERR "MT2131: Device not found at addr 0x%02x\n",
-		       cfg->i2c_address);
-		kfree(priv);
-		return NULL;
-	}
-
-	printk(KERN_INFO "MT2131: successfully identified at address 0x%02x\n",
-	       cfg->i2c_address);
-	memcpy(&fe->ops.tuner_ops, &mt2131_tuner_ops,
-	       sizeof(struct dvb_tuner_ops));
-
-	fe->tuner_priv = priv;
-	return fe;
-}
-EXPORT_SYMBOL(mt2131_attach);
-
-MODULE_AUTHOR("Steven Toth");
-MODULE_DESCRIPTION("Microtune MT2131 silicon tuner driver");
-MODULE_LICENSE("GPL");
-
-/*
- * Local variables:
- * c-basic-offset: 8
- */
diff --git a/drivers/media/common/tuners/mt2131.h b/drivers/media/common/tuners/mt2131.h
deleted file mode 100644
index 6632de6..0000000
--- a/drivers/media/common/tuners/mt2131.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- *  Driver for Microtune MT2131 "QAM/8VSB single chip tuner"
- *
- *  Copyright (c) 2006 Steven Toth <stoth@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 __MT2131_H__
-#define __MT2131_H__
-
-struct dvb_frontend;
-struct i2c_adapter;
-
-struct mt2131_config {
-	u8 i2c_address;
-	u8 clock_out; /* 0 = off, 1 = CLK/4, 2 = CLK/2, 3 = CLK/1 */
-};
-
-#if defined(CONFIG_MEDIA_TUNER_MT2131) || (defined(CONFIG_MEDIA_TUNER_MT2131_MODULE) && defined(MODULE))
-extern struct dvb_frontend* mt2131_attach(struct dvb_frontend *fe,
-					  struct i2c_adapter *i2c,
-					  struct mt2131_config *cfg,
-					  u16 if1);
-#else
-static inline struct dvb_frontend* mt2131_attach(struct dvb_frontend *fe,
-						 struct i2c_adapter *i2c,
-						 struct mt2131_config *cfg,
-						 u16 if1)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif /* CONFIG_MEDIA_TUNER_MT2131 */
-
-#endif /* __MT2131_H__ */
-
-/*
- * Local variables:
- * c-basic-offset: 8
- */
diff --git a/drivers/media/common/tuners/mt2131_priv.h b/drivers/media/common/tuners/mt2131_priv.h
deleted file mode 100644
index 62aeedf..0000000
--- a/drivers/media/common/tuners/mt2131_priv.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- *  Driver for Microtune MT2131 "QAM/8VSB single chip tuner"
- *
- *  Copyright (c) 2006 Steven Toth <stoth@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 __MT2131_PRIV_H__
-#define __MT2131_PRIV_H__
-
-/* Regs */
-#define MT2131_PWR              0x07
-#define MT2131_UPC_1            0x0b
-#define MT2131_AGC_RL           0x10
-#define MT2131_MISC_2           0x15
-
-/* frequency values in KHz */
-#define MT2131_IF1              1220
-#define MT2131_IF2              44000
-#define MT2131_FREF             16000
-
-struct mt2131_priv {
-	struct mt2131_config *cfg;
-	struct i2c_adapter   *i2c;
-
-	u32 frequency;
-};
-
-#endif /* __MT2131_PRIV_H__ */
-
-/*
- * Local variables:
- * c-basic-offset: 8
- */
diff --git a/drivers/media/common/tuners/mt2266.c b/drivers/media/common/tuners/mt2266.c
deleted file mode 100644
index bca4d75..0000000
--- a/drivers/media/common/tuners/mt2266.c
+++ /dev/null
@@ -1,353 +0,0 @@
-/*
- *  Driver for Microtune MT2266 "Direct conversion low power broadband tuner"
- *
- *  Copyright (c) 2007 Olivier DANET <odanet@caramail.com>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- */
-
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/dvb/frontend.h>
-#include <linux/i2c.h>
-#include <linux/slab.h>
-
-#include "dvb_frontend.h"
-#include "mt2266.h"
-
-#define I2C_ADDRESS 0x60
-
-#define REG_PART_REV   0
-#define REG_TUNE       1
-#define REG_BAND       6
-#define REG_BANDWIDTH  8
-#define REG_LOCK       0x12
-
-#define PART_REV 0x85
-
-struct mt2266_priv {
-	struct mt2266_config *cfg;
-	struct i2c_adapter   *i2c;
-
-	u32 frequency;
-	u32 bandwidth;
-	u8 band;
-};
-
-#define MT2266_VHF 1
-#define MT2266_UHF 0
-
-/* Here, frequencies are expressed in kiloHertz to avoid 32 bits overflows */
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
-
-#define dprintk(args...) do { if (debug) {printk(KERN_DEBUG "MT2266: " args); printk("\n"); }} while (0)
-
-// Reads a single register
-static int mt2266_readreg(struct mt2266_priv *priv, u8 reg, u8 *val)
-{
-	struct i2c_msg msg[2] = {
-		{ .addr = priv->cfg->i2c_address, .flags = 0,        .buf = &reg, .len = 1 },
-		{ .addr = priv->cfg->i2c_address, .flags = I2C_M_RD, .buf = val,  .len = 1 },
-	};
-	if (i2c_transfer(priv->i2c, msg, 2) != 2) {
-		printk(KERN_WARNING "MT2266 I2C read failed\n");
-		return -EREMOTEIO;
-	}
-	return 0;
-}
-
-// Writes a single register
-static int mt2266_writereg(struct mt2266_priv *priv, u8 reg, u8 val)
-{
-	u8 buf[2] = { reg, val };
-	struct i2c_msg msg = {
-		.addr = priv->cfg->i2c_address, .flags = 0, .buf = buf, .len = 2
-	};
-	if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
-		printk(KERN_WARNING "MT2266 I2C write failed\n");
-		return -EREMOTEIO;
-	}
-	return 0;
-}
-
-// Writes a set of consecutive registers
-static int mt2266_writeregs(struct mt2266_priv *priv,u8 *buf, u8 len)
-{
-	struct i2c_msg msg = {
-		.addr = priv->cfg->i2c_address, .flags = 0, .buf = buf, .len = len
-	};
-	if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
-		printk(KERN_WARNING "MT2266 I2C write failed (len=%i)\n",(int)len);
-		return -EREMOTEIO;
-	}
-	return 0;
-}
-
-// Initialisation sequences
-static u8 mt2266_init1[] = { REG_TUNE, 0x00, 0x00, 0x28,
-				 0x00, 0x52, 0x99, 0x3f };
-
-static u8 mt2266_init2[] = {
-    0x17, 0x6d, 0x71, 0x61, 0xc0, 0xbf, 0xff, 0xdc, 0x00, 0x0a, 0xd4,
-    0x03, 0x64, 0x64, 0x64, 0x64, 0x22, 0xaa, 0xf2, 0x1e, 0x80, 0x14,
-    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x7f, 0x5e, 0x3f, 0xff, 0xff,
-    0xff, 0x00, 0x77, 0x0f, 0x2d
-};
-
-static u8 mt2266_init_8mhz[] = { REG_BANDWIDTH, 0x22, 0x22, 0x22, 0x22,
-						0x22, 0x22, 0x22, 0x22 };
-
-static u8 mt2266_init_7mhz[] = { REG_BANDWIDTH, 0x32, 0x32, 0x32, 0x32,
-						0x32, 0x32, 0x32, 0x32 };
-
-static u8 mt2266_init_6mhz[] = { REG_BANDWIDTH, 0xa7, 0xa7, 0xa7, 0xa7,
-						0xa7, 0xa7, 0xa7, 0xa7 };
-
-static u8 mt2266_uhf[] = { 0x1d, 0xdc, 0x00, 0x0a, 0xd4, 0x03, 0x64, 0x64,
-			   0x64, 0x64, 0x22, 0xaa, 0xf2, 0x1e, 0x80, 0x14 };
-
-static u8 mt2266_vhf[] = { 0x1d, 0xfe, 0x00, 0x00, 0xb4, 0x03, 0xa5, 0xa5,
-			   0xa5, 0xa5, 0x82, 0xaa, 0xf1, 0x17, 0x80, 0x1f };
-
-#define FREF 30000       // Quartz oscillator 30 MHz
-
-static int mt2266_set_params(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	struct mt2266_priv *priv;
-	int ret=0;
-	u32 freq;
-	u32 tune;
-	u8  lnaband;
-	u8  b[10];
-	int i;
-	u8 band;
-
-	priv = fe->tuner_priv;
-
-	freq = priv->frequency / 1000; /* Hz -> kHz */
-	if (freq < 470000 && freq > 230000)
-		return -EINVAL; /* Gap between VHF and UHF bands */
-
-	priv->frequency = c->frequency;
-	tune = 2 * freq * (8192/16) / (FREF/16);
-	band = (freq < 300000) ? MT2266_VHF : MT2266_UHF;
-	if (band == MT2266_VHF)
-		tune *= 2;
-
-	switch (c->bandwidth_hz) {
-	case 6000000:
-		mt2266_writeregs(priv, mt2266_init_6mhz,
-				 sizeof(mt2266_init_6mhz));
-		break;
-	case 8000000:
-		mt2266_writeregs(priv, mt2266_init_8mhz,
-				 sizeof(mt2266_init_8mhz));
-		break;
-	case 7000000:
-	default:
-		mt2266_writeregs(priv, mt2266_init_7mhz,
-				 sizeof(mt2266_init_7mhz));
-		break;
-	}
-	priv->bandwidth = c->bandwidth_hz;
-
-	if (band == MT2266_VHF && priv->band == MT2266_UHF) {
-		dprintk("Switch from UHF to VHF");
-		mt2266_writereg(priv, 0x05, 0x04);
-		mt2266_writereg(priv, 0x19, 0x61);
-		mt2266_writeregs(priv, mt2266_vhf, sizeof(mt2266_vhf));
-	} else if (band == MT2266_UHF && priv->band == MT2266_VHF) {
-		dprintk("Switch from VHF to UHF");
-		mt2266_writereg(priv, 0x05, 0x52);
-		mt2266_writereg(priv, 0x19, 0x61);
-		mt2266_writeregs(priv, mt2266_uhf, sizeof(mt2266_uhf));
-	}
-	msleep(10);
-
-	if (freq <= 495000)
-		lnaband = 0xEE;
-	else if (freq <= 525000)
-		lnaband = 0xDD;
-	else if (freq <= 550000)
-		lnaband = 0xCC;
-	else if (freq <= 580000)
-		lnaband = 0xBB;
-	else if (freq <= 605000)
-		lnaband = 0xAA;
-	else if (freq <= 630000)
-		lnaband = 0x99;
-	else if (freq <= 655000)
-		lnaband = 0x88;
-	else if (freq <= 685000)
-		lnaband = 0x77;
-	else if (freq <= 710000)
-		lnaband = 0x66;
-	else if (freq <= 735000)
-		lnaband = 0x55;
-	else if (freq <= 765000)
-		lnaband = 0x44;
-	else if (freq <= 802000)
-		lnaband = 0x33;
-	else if (freq <= 840000)
-		lnaband = 0x22;
-	else
-		lnaband = 0x11;
-
-	b[0] = REG_TUNE;
-	b[1] = (tune >> 8) & 0x1F;
-	b[2] = tune & 0xFF;
-	b[3] = tune >> 13;
-	mt2266_writeregs(priv,b,4);
-
-	dprintk("set_parms: tune=%d band=%d %s",
-		(int) tune, (int) lnaband,
-		(band == MT2266_UHF) ? "UHF" : "VHF");
-	dprintk("set_parms: [1..3]: %2x %2x %2x",
-		(int) b[1], (int) b[2], (int)b[3]);
-
-	if (band == MT2266_UHF) {
-		b[0] = 0x05;
-		b[1] = (priv->band == MT2266_VHF) ? 0x52 : 0x62;
-		b[2] = lnaband;
-		mt2266_writeregs(priv, b, 3);
-	}
-
-	/* Wait for pll lock or timeout */
-	i = 0;
-	do {
-		mt2266_readreg(priv,REG_LOCK,b);
-		if (b[0] & 0x40)
-			break;
-		msleep(10);
-		i++;
-	} while (i<10);
-	dprintk("Lock when i=%i",(int)i);
-
-	if (band == MT2266_UHF && priv->band == MT2266_VHF)
-		mt2266_writereg(priv, 0x05, 0x62);
-
-	priv->band = band;
-
-	return ret;
-}
-
-static void mt2266_calibrate(struct mt2266_priv *priv)
-{
-	mt2266_writereg(priv, 0x11, 0x03);
-	mt2266_writereg(priv, 0x11, 0x01);
-	mt2266_writeregs(priv, mt2266_init1, sizeof(mt2266_init1));
-	mt2266_writeregs(priv, mt2266_init2, sizeof(mt2266_init2));
-	mt2266_writereg(priv, 0x33, 0x5e);
-	mt2266_writereg(priv, 0x10, 0x10);
-	mt2266_writereg(priv, 0x10, 0x00);
-	mt2266_writeregs(priv, mt2266_init_8mhz, sizeof(mt2266_init_8mhz));
-	msleep(25);
-	mt2266_writereg(priv, 0x17, 0x6d);
-	mt2266_writereg(priv, 0x1c, 0x00);
-	msleep(75);
-	mt2266_writereg(priv, 0x17, 0x6d);
-	mt2266_writereg(priv, 0x1c, 0xff);
-}
-
-static int mt2266_get_frequency(struct dvb_frontend *fe, u32 *frequency)
-{
-	struct mt2266_priv *priv = fe->tuner_priv;
-	*frequency = priv->frequency;
-	return 0;
-}
-
-static int mt2266_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
-{
-	struct mt2266_priv *priv = fe->tuner_priv;
-	*bandwidth = priv->bandwidth;
-	return 0;
-}
-
-static int mt2266_init(struct dvb_frontend *fe)
-{
-	int ret;
-	struct mt2266_priv *priv = fe->tuner_priv;
-	ret = mt2266_writereg(priv, 0x17, 0x6d);
-	if (ret < 0)
-		return ret;
-	ret = mt2266_writereg(priv, 0x1c, 0xff);
-	if (ret < 0)
-		return ret;
-	return 0;
-}
-
-static int mt2266_sleep(struct dvb_frontend *fe)
-{
-	struct mt2266_priv *priv = fe->tuner_priv;
-	mt2266_writereg(priv, 0x17, 0x6d);
-	mt2266_writereg(priv, 0x1c, 0x00);
-	return 0;
-}
-
-static int mt2266_release(struct dvb_frontend *fe)
-{
-	kfree(fe->tuner_priv);
-	fe->tuner_priv = NULL;
-	return 0;
-}
-
-static const struct dvb_tuner_ops mt2266_tuner_ops = {
-	.info = {
-		.name           = "Microtune MT2266",
-		.frequency_min  = 174000000,
-		.frequency_max  = 862000000,
-		.frequency_step =     50000,
-	},
-	.release       = mt2266_release,
-	.init          = mt2266_init,
-	.sleep         = mt2266_sleep,
-	.set_params    = mt2266_set_params,
-	.get_frequency = mt2266_get_frequency,
-	.get_bandwidth = mt2266_get_bandwidth
-};
-
-struct dvb_frontend * mt2266_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct mt2266_config *cfg)
-{
-	struct mt2266_priv *priv = NULL;
-	u8 id = 0;
-
-	priv = kzalloc(sizeof(struct mt2266_priv), GFP_KERNEL);
-	if (priv == NULL)
-		return NULL;
-
-	priv->cfg      = cfg;
-	priv->i2c      = i2c;
-	priv->band     = MT2266_UHF;
-
-	if (mt2266_readreg(priv, 0, &id)) {
-		kfree(priv);
-		return NULL;
-	}
-	if (id != PART_REV) {
-		kfree(priv);
-		return NULL;
-	}
-	printk(KERN_INFO "MT2266: successfully identified\n");
-	memcpy(&fe->ops.tuner_ops, &mt2266_tuner_ops, sizeof(struct dvb_tuner_ops));
-
-	fe->tuner_priv = priv;
-	mt2266_calibrate(priv);
-	return fe;
-}
-EXPORT_SYMBOL(mt2266_attach);
-
-MODULE_AUTHOR("Olivier DANET");
-MODULE_DESCRIPTION("Microtune MT2266 silicon tuner driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/common/tuners/mt2266.h b/drivers/media/common/tuners/mt2266.h
deleted file mode 100644
index 4d08388..0000000
--- a/drivers/media/common/tuners/mt2266.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- *  Driver for Microtune MT2266 "Direct conversion low power broadband tuner"
- *
- *  Copyright (c) 2007 Olivier DANET <odanet@caramail.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.
- */
-
-#ifndef MT2266_H
-#define MT2266_H
-
-struct dvb_frontend;
-struct i2c_adapter;
-
-struct mt2266_config {
-	u8 i2c_address;
-};
-
-#if defined(CONFIG_MEDIA_TUNER_MT2266) || (defined(CONFIG_MEDIA_TUNER_MT2266_MODULE) && defined(MODULE))
-extern struct dvb_frontend * mt2266_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct mt2266_config *cfg);
-#else
-static inline struct dvb_frontend * mt2266_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct mt2266_config *cfg)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif // CONFIG_MEDIA_TUNER_MT2266
-
-#endif
diff --git a/drivers/media/common/tuners/mxl5005s.c b/drivers/media/common/tuners/mxl5005s.c
deleted file mode 100644
index 6133315..0000000
--- a/drivers/media/common/tuners/mxl5005s.c
+++ /dev/null
@@ -1,4109 +0,0 @@
-/*
-    MaxLinear MXL5005S VSB/QAM/DVBT tuner driver
-
-    Copyright (C) 2008 MaxLinear
-    Copyright (C) 2006 Steven Toth <stoth@linuxtv.org>
-      Functions:
-	mxl5005s_reset()
-	mxl5005s_writereg()
-	mxl5005s_writeregs()
-	mxl5005s_init()
-	mxl5005s_reconfigure()
-	mxl5005s_AssignTunerMode()
-	mxl5005s_set_params()
-	mxl5005s_get_frequency()
-	mxl5005s_get_bandwidth()
-	mxl5005s_release()
-	mxl5005s_attach()
-
-    Copyright (C) 2008 Realtek
-    Copyright (C) 2008 Jan Hoogenraad
-      Functions:
-	mxl5005s_SetRfFreqHz()
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the 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.
-
-*/
-
-/*
-    History of this driver (Steven Toth):
-      I was given a public release of a linux driver that included
-      support for the MaxLinear MXL5005S silicon tuner. Analysis of
-      the tuner driver showed clearly three things.
-
-      1. The tuner driver didn't support the LinuxTV tuner API
-	 so the code Realtek added had to be removed.
-
-      2. A significant amount of the driver is reference driver code
-	 from MaxLinear, I felt it was important to identify and
-	 preserve this.
-
-      3. New code has to be added to interface correctly with the
-	 LinuxTV API, as a regular kernel module.
-
-      Other than the reference driver enum's, I've clearly marked
-      sections of the code and retained the copyright of the
-      respective owners.
-*/
-#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 "dvb_frontend.h"
-#include "mxl5005s.h"
-
-static int debug;
-
-#define dprintk(level, arg...) do {    \
-	if (level <= debug)            \
-		printk(arg);    \
-	} while (0)
-
-#define TUNER_REGS_NUM          104
-#define INITCTRL_NUM            40
-
-#ifdef _MXL_PRODUCTION
-#define CHCTRL_NUM              39
-#else
-#define CHCTRL_NUM              36
-#endif
-
-#define MXLCTRL_NUM             189
-#define MASTER_CONTROL_ADDR     9
-
-/* Enumeration of Master Control Register State */
-enum master_control_state {
-	MC_LOAD_START = 1,
-	MC_POWER_DOWN,
-	MC_SYNTH_RESET,
-	MC_SEQ_OFF
-};
-
-/* Enumeration of MXL5005 Tuner Modulation Type */
-enum {
-	MXL_DEFAULT_MODULATION = 0,
-	MXL_DVBT,
-	MXL_ATSC,
-	MXL_QAM,
-	MXL_ANALOG_CABLE,
-	MXL_ANALOG_OTA
-};
-
-/* MXL5005 Tuner Register Struct */
-struct TunerReg {
-	u16 Reg_Num;	/* Tuner Register Address */
-	u16 Reg_Val;	/* Current sw programmed value waiting to be written */
-};
-
-enum {
-	/* Initialization Control Names */
-	DN_IQTN_AMP_CUT = 1,       /* 1 */
-	BB_MODE,                   /* 2 */
-	BB_BUF,                    /* 3 */
-	BB_BUF_OA,                 /* 4 */
-	BB_ALPF_BANDSELECT,        /* 5 */
-	BB_IQSWAP,                 /* 6 */
-	BB_DLPF_BANDSEL,           /* 7 */
-	RFSYN_CHP_GAIN,            /* 8 */
-	RFSYN_EN_CHP_HIGAIN,       /* 9 */
-	AGC_IF,                    /* 10 */
-	AGC_RF,                    /* 11 */
-	IF_DIVVAL,                 /* 12 */
-	IF_VCO_BIAS,               /* 13 */
-	CHCAL_INT_MOD_IF,          /* 14 */
-	CHCAL_FRAC_MOD_IF,         /* 15 */
-	DRV_RES_SEL,               /* 16 */
-	I_DRIVER,                  /* 17 */
-	EN_AAF,                    /* 18 */
-	EN_3P,                     /* 19 */
-	EN_AUX_3P,                 /* 20 */
-	SEL_AAF_BAND,              /* 21 */
-	SEQ_ENCLK16_CLK_OUT,       /* 22 */
-	SEQ_SEL4_16B,              /* 23 */
-	XTAL_CAPSELECT,            /* 24 */
-	IF_SEL_DBL,                /* 25 */
-	RFSYN_R_DIV,               /* 26 */
-	SEQ_EXTSYNTHCALIF,         /* 27 */
-	SEQ_EXTDCCAL,              /* 28 */
-	AGC_EN_RSSI,               /* 29 */
-	RFA_ENCLKRFAGC,            /* 30 */
-	RFA_RSSI_REFH,             /* 31 */
-	RFA_RSSI_REF,              /* 32 */
-	RFA_RSSI_REFL,             /* 33 */
-	RFA_FLR,                   /* 34 */
-	RFA_CEIL,                  /* 35 */
-	SEQ_EXTIQFSMPULSE,         /* 36 */
-	OVERRIDE_1,                /* 37 */
-	BB_INITSTATE_DLPF_TUNE,    /* 38 */
-	TG_R_DIV,                  /* 39 */
-	EN_CHP_LIN_B,              /* 40 */
-
-	/* Channel Change Control Names */
-	DN_POLY = 51,              /* 51 */
-	DN_RFGAIN,                 /* 52 */
-	DN_CAP_RFLPF,              /* 53 */
-	DN_EN_VHFUHFBAR,           /* 54 */
-	DN_GAIN_ADJUST,            /* 55 */
-	DN_IQTNBUF_AMP,            /* 56 */
-	DN_IQTNGNBFBIAS_BST,       /* 57 */
-	RFSYN_EN_OUTMUX,           /* 58 */
-	RFSYN_SEL_VCO_OUT,         /* 59 */
-	RFSYN_SEL_VCO_HI,          /* 60 */
-	RFSYN_SEL_DIVM,            /* 61 */
-	RFSYN_RF_DIV_BIAS,         /* 62 */
-	DN_SEL_FREQ,               /* 63 */
-	RFSYN_VCO_BIAS,            /* 64 */
-	CHCAL_INT_MOD_RF,          /* 65 */
-	CHCAL_FRAC_MOD_RF,         /* 66 */
-	RFSYN_LPF_R,               /* 67 */
-	CHCAL_EN_INT_RF,           /* 68 */
-	TG_LO_DIVVAL,              /* 69 */
-	TG_LO_SELVAL,              /* 70 */
-	TG_DIV_VAL,                /* 71 */
-	TG_VCO_BIAS,               /* 72 */
-	SEQ_EXTPOWERUP,            /* 73 */
-	OVERRIDE_2,                /* 74 */
-	OVERRIDE_3,                /* 75 */
-	OVERRIDE_4,                /* 76 */
-	SEQ_FSM_PULSE,             /* 77 */
-	GPIO_4B,                   /* 78 */
-	GPIO_3B,                   /* 79 */
-	GPIO_4,                    /* 80 */
-	GPIO_3,                    /* 81 */
-	GPIO_1B,                   /* 82 */
-	DAC_A_ENABLE,              /* 83 */
-	DAC_B_ENABLE,              /* 84 */
-	DAC_DIN_A,                 /* 85 */
-	DAC_DIN_B,                 /* 86 */
-#ifdef _MXL_PRODUCTION
-	RFSYN_EN_DIV,              /* 87 */
-	RFSYN_DIVM,                /* 88 */
-	DN_BYPASS_AGC_I2C          /* 89 */
-#endif
-};
-
-/*
- * The following context is source code provided by MaxLinear.
- * MaxLinear source code - Common_MXL.h (?)
- */
-
-/* Constants */
-#define MXL5005S_REG_WRITING_TABLE_LEN_MAX	104
-#define MXL5005S_LATCH_BYTE			0xfe
-
-/* Register address, MSB, and LSB */
-#define MXL5005S_BB_IQSWAP_ADDR			59
-#define MXL5005S_BB_IQSWAP_MSB			0
-#define MXL5005S_BB_IQSWAP_LSB			0
-
-#define MXL5005S_BB_DLPF_BANDSEL_ADDR		53
-#define MXL5005S_BB_DLPF_BANDSEL_MSB		4
-#define MXL5005S_BB_DLPF_BANDSEL_LSB		3
-
-/* Standard modes */
-enum {
-	MXL5005S_STANDARD_DVBT,
-	MXL5005S_STANDARD_ATSC,
-};
-#define MXL5005S_STANDARD_MODE_NUM		2
-
-/* Bandwidth modes */
-enum {
-	MXL5005S_BANDWIDTH_6MHZ = 6000000,
-	MXL5005S_BANDWIDTH_7MHZ = 7000000,
-	MXL5005S_BANDWIDTH_8MHZ = 8000000,
-};
-#define MXL5005S_BANDWIDTH_MODE_NUM		3
-
-/* MXL5005 Tuner Control Struct */
-struct TunerControl {
-	u16 Ctrl_Num;	/* Control Number */
-	u16 size;	/* Number of bits to represent Value */
-	u16 addr[25];	/* Array of Tuner Register Address for each bit pos */
-	u16 bit[25];	/* Array of bit pos in Reg Addr for each bit pos */
-	u16 val[25];	/* Binary representation of Value */
-};
-
-/* MXL5005 Tuner Struct */
-struct mxl5005s_state {
-	u8	Mode;		/* 0: Analog Mode ; 1: Digital Mode */
-	u8	IF_Mode;	/* for Analog Mode, 0: zero IF; 1: low IF */
-	u32	Chan_Bandwidth;	/* filter  channel bandwidth (6, 7, 8) */
-	u32	IF_OUT;		/* Desired IF Out Frequency */
-	u16	IF_OUT_LOAD;	/* IF Out Load Resistor (200/300 Ohms) */
-	u32	RF_IN;		/* RF Input Frequency */
-	u32	Fxtal;		/* XTAL Frequency */
-	u8	AGC_Mode;	/* AGC Mode 0: Dual AGC; 1: Single AGC */
-	u16	TOP;		/* Value: take over point */
-	u8	CLOCK_OUT;	/* 0: turn off clk out; 1: turn on clock out */
-	u8	DIV_OUT;	/* 4MHz or 16MHz */
-	u8	CAPSELECT;	/* 0: disable On-Chip pulling cap; 1: enable */
-	u8	EN_RSSI;	/* 0: disable RSSI; 1: enable RSSI */
-
-	/* Modulation Type; */
-	/* 0 - Default;	1 - DVB-T; 2 - ATSC; 3 - QAM; 4 - Analog Cable */
-	u8	Mod_Type;
-
-	/* Tracking Filter Type */
-	/* 0 - Default; 1 - Off; 2 - Type C; 3 - Type C-H */
-	u8	TF_Type;
-
-	/* Calculated Settings */
-	u32	RF_LO;		/* Synth RF LO Frequency */
-	u32	IF_LO;		/* Synth IF LO Frequency */
-	u32	TG_LO;		/* Synth TG_LO Frequency */
-
-	/* Pointers to ControlName Arrays */
-	u16	Init_Ctrl_Num;		/* Number of INIT Control Names */
-	struct TunerControl
-		Init_Ctrl[INITCTRL_NUM]; /* INIT Control Names Array Pointer */
-
-	u16	CH_Ctrl_Num;		/* Number of CH Control Names */
-	struct TunerControl
-		CH_Ctrl[CHCTRL_NUM];	/* CH Control Name Array Pointer */
-
-	u16	MXL_Ctrl_Num;		/* Number of MXL Control Names */
-	struct TunerControl
-		MXL_Ctrl[MXLCTRL_NUM];	/* MXL Control Name Array Pointer */
-
-	/* Pointer to Tuner Register Array */
-	u16	TunerRegs_Num;		/* Number of Tuner Registers */
-	struct TunerReg
-		TunerRegs[TUNER_REGS_NUM]; /* Tuner Register Array Pointer */
-
-	/* Linux driver framework specific */
-	struct mxl5005s_config *config;
-	struct dvb_frontend *frontend;
-	struct i2c_adapter *i2c;
-
-	/* Cache values */
-	u32 current_mode;
-
-};
-
-static u16 MXL_GetMasterControl(u8 *MasterReg, int state);
-static u16 MXL_ControlWrite(struct dvb_frontend *fe, u16 ControlNum, u32 value);
-static u16 MXL_ControlRead(struct dvb_frontend *fe, u16 controlNum, u32 *value);
-static void MXL_RegWriteBit(struct dvb_frontend *fe, u8 address, u8 bit,
-	u8 bitVal);
-static u16 MXL_GetCHRegister(struct dvb_frontend *fe, u8 *RegNum,
-	u8 *RegVal, int *count);
-static u32 MXL_Ceiling(u32 value, u32 resolution);
-static u16 MXL_RegRead(struct dvb_frontend *fe, u8 RegNum, u8 *RegVal);
-static u16 MXL_ControlWrite_Group(struct dvb_frontend *fe, u16 controlNum,
-	u32 value, u16 controlGroup);
-static u16 MXL_SetGPIO(struct dvb_frontend *fe, u8 GPIO_Num, u8 GPIO_Val);
-static u16 MXL_GetInitRegister(struct dvb_frontend *fe, u8 *RegNum,
-	u8 *RegVal, int *count);
-static u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq);
-static void MXL_SynthIFLO_Calc(struct dvb_frontend *fe);
-static void MXL_SynthRFTGLO_Calc(struct dvb_frontend *fe);
-static u16 MXL_GetCHRegister_ZeroIF(struct dvb_frontend *fe, u8 *RegNum,
-	u8 *RegVal, int *count);
-static int mxl5005s_writeregs(struct dvb_frontend *fe, u8 *addrtable,
-	u8 *datatable, u8 len);
-static u16 MXL_IFSynthInit(struct dvb_frontend *fe);
-static int mxl5005s_AssignTunerMode(struct dvb_frontend *fe, u32 mod_type,
-	u32 bandwidth);
-static int mxl5005s_reconfigure(struct dvb_frontend *fe, u32 mod_type,
-	u32 bandwidth);
-
-/* ----------------------------------------------------------------
- * Begin: Custom code salvaged from the Realtek driver.
- * Copyright (C) 2008 Realtek
- * Copyright (C) 2008 Jan Hoogenraad
- * This code is placed under the terms of the GNU General Public License
- *
- * Released by Realtek under GPLv2.
- * Thanks to Realtek for a lot of support we received !
- *
- *  Revision: 080314 - original version
- */
-
-static int mxl5005s_SetRfFreqHz(struct dvb_frontend *fe, unsigned long RfFreqHz)
-{
-	struct mxl5005s_state *state = fe->tuner_priv;
-	unsigned char AddrTable[MXL5005S_REG_WRITING_TABLE_LEN_MAX];
-	unsigned char ByteTable[MXL5005S_REG_WRITING_TABLE_LEN_MAX];
-	int TableLen;
-
-	u32 IfDivval = 0;
-	unsigned char MasterControlByte;
-
-	dprintk(1, "%s() freq=%ld\n", __func__, RfFreqHz);
-
-	/* Set MxL5005S tuner RF frequency according to example code. */
-
-	/* Tuner RF frequency setting stage 0 */
-	MXL_GetMasterControl(ByteTable, MC_SYNTH_RESET);
-	AddrTable[0] = MASTER_CONTROL_ADDR;
-	ByteTable[0] |= state->config->AgcMasterByte;
-
-	mxl5005s_writeregs(fe, AddrTable, ByteTable, 1);
-
-	/* Tuner RF frequency setting stage 1 */
-	MXL_TuneRF(fe, RfFreqHz);
-
-	MXL_ControlRead(fe, IF_DIVVAL, &IfDivval);
-
-	MXL_ControlWrite(fe, SEQ_FSM_PULSE, 0);
-	MXL_ControlWrite(fe, SEQ_EXTPOWERUP, 1);
-	MXL_ControlWrite(fe, IF_DIVVAL, 8);
-	MXL_GetCHRegister(fe, AddrTable, ByteTable, &TableLen);
-
-	MXL_GetMasterControl(&MasterControlByte, MC_LOAD_START);
-	AddrTable[TableLen] = MASTER_CONTROL_ADDR ;
-	ByteTable[TableLen] = MasterControlByte |
-		state->config->AgcMasterByte;
-	TableLen += 1;
-
-	mxl5005s_writeregs(fe, AddrTable, ByteTable, TableLen);
-
-	/* Wait 30 ms. */
-	msleep(150);
-
-	/* Tuner RF frequency setting stage 2 */
-	MXL_ControlWrite(fe, SEQ_FSM_PULSE, 1);
-	MXL_ControlWrite(fe, IF_DIVVAL, IfDivval);
-	MXL_GetCHRegister_ZeroIF(fe, AddrTable, ByteTable, &TableLen);
-
-	MXL_GetMasterControl(&MasterControlByte, MC_LOAD_START);
-	AddrTable[TableLen] = MASTER_CONTROL_ADDR ;
-	ByteTable[TableLen] = MasterControlByte |
-		state->config->AgcMasterByte ;
-	TableLen += 1;
-
-	mxl5005s_writeregs(fe, AddrTable, ByteTable, TableLen);
-
-	msleep(100);
-
-	return 0;
-}
-/* End: Custom code taken from the Realtek driver */
-
-/* ----------------------------------------------------------------
- * Begin: Reference driver code found in the Realtek driver.
- * Copyright (C) 2008 MaxLinear
- */
-static u16 MXL5005_RegisterInit(struct dvb_frontend *fe)
-{
-	struct mxl5005s_state *state = fe->tuner_priv;
-	state->TunerRegs_Num = TUNER_REGS_NUM ;
-
-	state->TunerRegs[0].Reg_Num = 9 ;
-	state->TunerRegs[0].Reg_Val = 0x40 ;
-
-	state->TunerRegs[1].Reg_Num = 11 ;
-	state->TunerRegs[1].Reg_Val = 0x19 ;
-
-	state->TunerRegs[2].Reg_Num = 12 ;
-	state->TunerRegs[2].Reg_Val = 0x60 ;
-
-	state->TunerRegs[3].Reg_Num = 13 ;
-	state->TunerRegs[3].Reg_Val = 0x00 ;
-
-	state->TunerRegs[4].Reg_Num = 14 ;
-	state->TunerRegs[4].Reg_Val = 0x00 ;
-
-	state->TunerRegs[5].Reg_Num = 15 ;
-	state->TunerRegs[5].Reg_Val = 0xC0 ;
-
-	state->TunerRegs[6].Reg_Num = 16 ;
-	state->TunerRegs[6].Reg_Val = 0x00 ;
-
-	state->TunerRegs[7].Reg_Num = 17 ;
-	state->TunerRegs[7].Reg_Val = 0x00 ;
-
-	state->TunerRegs[8].Reg_Num = 18 ;
-	state->TunerRegs[8].Reg_Val = 0x00 ;
-
-	state->TunerRegs[9].Reg_Num = 19 ;
-	state->TunerRegs[9].Reg_Val = 0x34 ;
-
-	state->TunerRegs[10].Reg_Num = 21 ;
-	state->TunerRegs[10].Reg_Val = 0x00 ;
-
-	state->TunerRegs[11].Reg_Num = 22 ;
-	state->TunerRegs[11].Reg_Val = 0x6B ;
-
-	state->TunerRegs[12].Reg_Num = 23 ;
-	state->TunerRegs[12].Reg_Val = 0x35 ;
-
-	state->TunerRegs[13].Reg_Num = 24 ;
-	state->TunerRegs[13].Reg_Val = 0x70 ;
-
-	state->TunerRegs[14].Reg_Num = 25 ;
-	state->TunerRegs[14].Reg_Val = 0x3E ;
-
-	state->TunerRegs[15].Reg_Num = 26 ;
-	state->TunerRegs[15].Reg_Val = 0x82 ;
-
-	state->TunerRegs[16].Reg_Num = 31 ;
-	state->TunerRegs[16].Reg_Val = 0x00 ;
-
-	state->TunerRegs[17].Reg_Num = 32 ;
-	state->TunerRegs[17].Reg_Val = 0x40 ;
-
-	state->TunerRegs[18].Reg_Num = 33 ;
-	state->TunerRegs[18].Reg_Val = 0x53 ;
-
-	state->TunerRegs[19].Reg_Num = 34 ;
-	state->TunerRegs[19].Reg_Val = 0x81 ;
-
-	state->TunerRegs[20].Reg_Num = 35 ;
-	state->TunerRegs[20].Reg_Val = 0xC9 ;
-
-	state->TunerRegs[21].Reg_Num = 36 ;
-	state->TunerRegs[21].Reg_Val = 0x01 ;
-
-	state->TunerRegs[22].Reg_Num = 37 ;
-	state->TunerRegs[22].Reg_Val = 0x00 ;
-
-	state->TunerRegs[23].Reg_Num = 41 ;
-	state->TunerRegs[23].Reg_Val = 0x00 ;
-
-	state->TunerRegs[24].Reg_Num = 42 ;
-	state->TunerRegs[24].Reg_Val = 0xF8 ;
-
-	state->TunerRegs[25].Reg_Num = 43 ;
-	state->TunerRegs[25].Reg_Val = 0x43 ;
-
-	state->TunerRegs[26].Reg_Num = 44 ;
-	state->TunerRegs[26].Reg_Val = 0x20 ;
-
-	state->TunerRegs[27].Reg_Num = 45 ;
-	state->TunerRegs[27].Reg_Val = 0x80 ;
-
-	state->TunerRegs[28].Reg_Num = 46 ;
-	state->TunerRegs[28].Reg_Val = 0x88 ;
-
-	state->TunerRegs[29].Reg_Num = 47 ;
-	state->TunerRegs[29].Reg_Val = 0x86 ;
-
-	state->TunerRegs[30].Reg_Num = 48 ;
-	state->TunerRegs[30].Reg_Val = 0x00 ;
-
-	state->TunerRegs[31].Reg_Num = 49 ;
-	state->TunerRegs[31].Reg_Val = 0x00 ;
-
-	state->TunerRegs[32].Reg_Num = 53 ;
-	state->TunerRegs[32].Reg_Val = 0x94 ;
-
-	state->TunerRegs[33].Reg_Num = 54 ;
-	state->TunerRegs[33].Reg_Val = 0xFA ;
-
-	state->TunerRegs[34].Reg_Num = 55 ;
-	state->TunerRegs[34].Reg_Val = 0x92 ;
-
-	state->TunerRegs[35].Reg_Num = 56 ;
-	state->TunerRegs[35].Reg_Val = 0x80 ;
-
-	state->TunerRegs[36].Reg_Num = 57 ;
-	state->TunerRegs[36].Reg_Val = 0x41 ;
-
-	state->TunerRegs[37].Reg_Num = 58 ;
-	state->TunerRegs[37].Reg_Val = 0xDB ;
-
-	state->TunerRegs[38].Reg_Num = 59 ;
-	state->TunerRegs[38].Reg_Val = 0x00 ;
-
-	state->TunerRegs[39].Reg_Num = 60 ;
-	state->TunerRegs[39].Reg_Val = 0x00 ;
-
-	state->TunerRegs[40].Reg_Num = 61 ;
-	state->TunerRegs[40].Reg_Val = 0x00 ;
-
-	state->TunerRegs[41].Reg_Num = 62 ;
-	state->TunerRegs[41].Reg_Val = 0x00 ;
-
-	state->TunerRegs[42].Reg_Num = 65 ;
-	state->TunerRegs[42].Reg_Val = 0xF8 ;
-
-	state->TunerRegs[43].Reg_Num = 66 ;
-	state->TunerRegs[43].Reg_Val = 0xE4 ;
-
-	state->TunerRegs[44].Reg_Num = 67 ;
-	state->TunerRegs[44].Reg_Val = 0x90 ;
-
-	state->TunerRegs[45].Reg_Num = 68 ;
-	state->TunerRegs[45].Reg_Val = 0xC0 ;
-
-	state->TunerRegs[46].Reg_Num = 69 ;
-	state->TunerRegs[46].Reg_Val = 0x01 ;
-
-	state->TunerRegs[47].Reg_Num = 70 ;
-	state->TunerRegs[47].Reg_Val = 0x50 ;
-
-	state->TunerRegs[48].Reg_Num = 71 ;
-	state->TunerRegs[48].Reg_Val = 0x06 ;
-
-	state->TunerRegs[49].Reg_Num = 72 ;
-	state->TunerRegs[49].Reg_Val = 0x00 ;
-
-	state->TunerRegs[50].Reg_Num = 73 ;
-	state->TunerRegs[50].Reg_Val = 0x20 ;
-
-	state->TunerRegs[51].Reg_Num = 76 ;
-	state->TunerRegs[51].Reg_Val = 0xBB ;
-
-	state->TunerRegs[52].Reg_Num = 77 ;
-	state->TunerRegs[52].Reg_Val = 0x13 ;
-
-	state->TunerRegs[53].Reg_Num = 81 ;
-	state->TunerRegs[53].Reg_Val = 0x04 ;
-
-	state->TunerRegs[54].Reg_Num = 82 ;
-	state->TunerRegs[54].Reg_Val = 0x75 ;
-
-	state->TunerRegs[55].Reg_Num = 83 ;
-	state->TunerRegs[55].Reg_Val = 0x00 ;
-
-	state->TunerRegs[56].Reg_Num = 84 ;
-	state->TunerRegs[56].Reg_Val = 0x00 ;
-
-	state->TunerRegs[57].Reg_Num = 85 ;
-	state->TunerRegs[57].Reg_Val = 0x00 ;
-
-	state->TunerRegs[58].Reg_Num = 91 ;
-	state->TunerRegs[58].Reg_Val = 0x70 ;
-
-	state->TunerRegs[59].Reg_Num = 92 ;
-	state->TunerRegs[59].Reg_Val = 0x00 ;
-
-	state->TunerRegs[60].Reg_Num = 93 ;
-	state->TunerRegs[60].Reg_Val = 0x00 ;
-
-	state->TunerRegs[61].Reg_Num = 94 ;
-	state->TunerRegs[61].Reg_Val = 0x00 ;
-
-	state->TunerRegs[62].Reg_Num = 95 ;
-	state->TunerRegs[62].Reg_Val = 0x0C ;
-
-	state->TunerRegs[63].Reg_Num = 96 ;
-	state->TunerRegs[63].Reg_Val = 0x00 ;
-
-	state->TunerRegs[64].Reg_Num = 97 ;
-	state->TunerRegs[64].Reg_Val = 0x00 ;
-
-	state->TunerRegs[65].Reg_Num = 98 ;
-	state->TunerRegs[65].Reg_Val = 0xE2 ;
-
-	state->TunerRegs[66].Reg_Num = 99 ;
-	state->TunerRegs[66].Reg_Val = 0x00 ;
-
-	state->TunerRegs[67].Reg_Num = 100 ;
-	state->TunerRegs[67].Reg_Val = 0x00 ;
-
-	state->TunerRegs[68].Reg_Num = 101 ;
-	state->TunerRegs[68].Reg_Val = 0x12 ;
-
-	state->TunerRegs[69].Reg_Num = 102 ;
-	state->TunerRegs[69].Reg_Val = 0x80 ;
-
-	state->TunerRegs[70].Reg_Num = 103 ;
-	state->TunerRegs[70].Reg_Val = 0x32 ;
-
-	state->TunerRegs[71].Reg_Num = 104 ;
-	state->TunerRegs[71].Reg_Val = 0xB4 ;
-
-	state->TunerRegs[72].Reg_Num = 105 ;
-	state->TunerRegs[72].Reg_Val = 0x60 ;
-
-	state->TunerRegs[73].Reg_Num = 106 ;
-	state->TunerRegs[73].Reg_Val = 0x83 ;
-
-	state->TunerRegs[74].Reg_Num = 107 ;
-	state->TunerRegs[74].Reg_Val = 0x84 ;
-
-	state->TunerRegs[75].Reg_Num = 108 ;
-	state->TunerRegs[75].Reg_Val = 0x9C ;
-
-	state->TunerRegs[76].Reg_Num = 109 ;
-	state->TunerRegs[76].Reg_Val = 0x02 ;
-
-	state->TunerRegs[77].Reg_Num = 110 ;
-	state->TunerRegs[77].Reg_Val = 0x81 ;
-
-	state->TunerRegs[78].Reg_Num = 111 ;
-	state->TunerRegs[78].Reg_Val = 0xC0 ;
-
-	state->TunerRegs[79].Reg_Num = 112 ;
-	state->TunerRegs[79].Reg_Val = 0x10 ;
-
-	state->TunerRegs[80].Reg_Num = 131 ;
-	state->TunerRegs[80].Reg_Val = 0x8A ;
-
-	state->TunerRegs[81].Reg_Num = 132 ;
-	state->TunerRegs[81].Reg_Val = 0x10 ;
-
-	state->TunerRegs[82].Reg_Num = 133 ;
-	state->TunerRegs[82].Reg_Val = 0x24 ;
-
-	state->TunerRegs[83].Reg_Num = 134 ;
-	state->TunerRegs[83].Reg_Val = 0x00 ;
-
-	state->TunerRegs[84].Reg_Num = 135 ;
-	state->TunerRegs[84].Reg_Val = 0x00 ;
-
-	state->TunerRegs[85].Reg_Num = 136 ;
-	state->TunerRegs[85].Reg_Val = 0x7E ;
-
-	state->TunerRegs[86].Reg_Num = 137 ;
-	state->TunerRegs[86].Reg_Val = 0x40 ;
-
-	state->TunerRegs[87].Reg_Num = 138 ;
-	state->TunerRegs[87].Reg_Val = 0x38 ;
-
-	state->TunerRegs[88].Reg_Num = 146 ;
-	state->TunerRegs[88].Reg_Val = 0xF6 ;
-
-	state->TunerRegs[89].Reg_Num = 147 ;
-	state->TunerRegs[89].Reg_Val = 0x1A ;
-
-	state->TunerRegs[90].Reg_Num = 148 ;
-	state->TunerRegs[90].Reg_Val = 0x62 ;
-
-	state->TunerRegs[91].Reg_Num = 149 ;
-	state->TunerRegs[91].Reg_Val = 0x33 ;
-
-	state->TunerRegs[92].Reg_Num = 150 ;
-	state->TunerRegs[92].Reg_Val = 0x80 ;
-
-	state->TunerRegs[93].Reg_Num = 156 ;
-	state->TunerRegs[93].Reg_Val = 0x56 ;
-
-	state->TunerRegs[94].Reg_Num = 157 ;
-	state->TunerRegs[94].Reg_Val = 0x17 ;
-
-	state->TunerRegs[95].Reg_Num = 158 ;
-	state->TunerRegs[95].Reg_Val = 0xA9 ;
-
-	state->TunerRegs[96].Reg_Num = 159 ;
-	state->TunerRegs[96].Reg_Val = 0x00 ;
-
-	state->TunerRegs[97].Reg_Num = 160 ;
-	state->TunerRegs[97].Reg_Val = 0x00 ;
-
-	state->TunerRegs[98].Reg_Num = 161 ;
-	state->TunerRegs[98].Reg_Val = 0x00 ;
-
-	state->TunerRegs[99].Reg_Num = 162 ;
-	state->TunerRegs[99].Reg_Val = 0x40 ;
-
-	state->TunerRegs[100].Reg_Num = 166 ;
-	state->TunerRegs[100].Reg_Val = 0xAE ;
-
-	state->TunerRegs[101].Reg_Num = 167 ;
-	state->TunerRegs[101].Reg_Val = 0x1B ;
-
-	state->TunerRegs[102].Reg_Num = 168 ;
-	state->TunerRegs[102].Reg_Val = 0xF2 ;
-
-	state->TunerRegs[103].Reg_Num = 195 ;
-	state->TunerRegs[103].Reg_Val = 0x00 ;
-
-	return 0 ;
-}
-
-static u16 MXL5005_ControlInit(struct dvb_frontend *fe)
-{
-	struct mxl5005s_state *state = fe->tuner_priv;
-	state->Init_Ctrl_Num = INITCTRL_NUM;
-
-	state->Init_Ctrl[0].Ctrl_Num = DN_IQTN_AMP_CUT ;
-	state->Init_Ctrl[0].size = 1 ;
-	state->Init_Ctrl[0].addr[0] = 73;
-	state->Init_Ctrl[0].bit[0] = 7;
-	state->Init_Ctrl[0].val[0] = 0;
-
-	state->Init_Ctrl[1].Ctrl_Num = BB_MODE ;
-	state->Init_Ctrl[1].size = 1 ;
-	state->Init_Ctrl[1].addr[0] = 53;
-	state->Init_Ctrl[1].bit[0] = 2;
-	state->Init_Ctrl[1].val[0] = 1;
-
-	state->Init_Ctrl[2].Ctrl_Num = BB_BUF ;
-	state->Init_Ctrl[2].size = 2 ;
-	state->Init_Ctrl[2].addr[0] = 53;
-	state->Init_Ctrl[2].bit[0] = 1;
-	state->Init_Ctrl[2].val[0] = 0;
-	state->Init_Ctrl[2].addr[1] = 57;
-	state->Init_Ctrl[2].bit[1] = 0;
-	state->Init_Ctrl[2].val[1] = 1;
-
-	state->Init_Ctrl[3].Ctrl_Num = BB_BUF_OA ;
-	state->Init_Ctrl[3].size = 1 ;
-	state->Init_Ctrl[3].addr[0] = 53;
-	state->Init_Ctrl[3].bit[0] = 0;
-	state->Init_Ctrl[3].val[0] = 0;
-
-	state->Init_Ctrl[4].Ctrl_Num = BB_ALPF_BANDSELECT ;
-	state->Init_Ctrl[4].size = 3 ;
-	state->Init_Ctrl[4].addr[0] = 53;
-	state->Init_Ctrl[4].bit[0] = 5;
-	state->Init_Ctrl[4].val[0] = 0;
-	state->Init_Ctrl[4].addr[1] = 53;
-	state->Init_Ctrl[4].bit[1] = 6;
-	state->Init_Ctrl[4].val[1] = 0;
-	state->Init_Ctrl[4].addr[2] = 53;
-	state->Init_Ctrl[4].bit[2] = 7;
-	state->Init_Ctrl[4].val[2] = 1;
-
-	state->Init_Ctrl[5].Ctrl_Num = BB_IQSWAP ;
-	state->Init_Ctrl[5].size = 1 ;
-	state->Init_Ctrl[5].addr[0] = 59;
-	state->Init_Ctrl[5].bit[0] = 0;
-	state->Init_Ctrl[5].val[0] = 0;
-
-	state->Init_Ctrl[6].Ctrl_Num = BB_DLPF_BANDSEL ;
-	state->Init_Ctrl[6].size = 2 ;
-	state->Init_Ctrl[6].addr[0] = 53;
-	state->Init_Ctrl[6].bit[0] = 3;
-	state->Init_Ctrl[6].val[0] = 0;
-	state->Init_Ctrl[6].addr[1] = 53;
-	state->Init_Ctrl[6].bit[1] = 4;
-	state->Init_Ctrl[6].val[1] = 1;
-
-	state->Init_Ctrl[7].Ctrl_Num = RFSYN_CHP_GAIN ;
-	state->Init_Ctrl[7].size = 4 ;
-	state->Init_Ctrl[7].addr[0] = 22;
-	state->Init_Ctrl[7].bit[0] = 4;
-	state->Init_Ctrl[7].val[0] = 0;
-	state->Init_Ctrl[7].addr[1] = 22;
-	state->Init_Ctrl[7].bit[1] = 5;
-	state->Init_Ctrl[7].val[1] = 1;
-	state->Init_Ctrl[7].addr[2] = 22;
-	state->Init_Ctrl[7].bit[2] = 6;
-	state->Init_Ctrl[7].val[2] = 1;
-	state->Init_Ctrl[7].addr[3] = 22;
-	state->Init_Ctrl[7].bit[3] = 7;
-	state->Init_Ctrl[7].val[3] = 0;
-
-	state->Init_Ctrl[8].Ctrl_Num = RFSYN_EN_CHP_HIGAIN ;
-	state->Init_Ctrl[8].size = 1 ;
-	state->Init_Ctrl[8].addr[0] = 22;
-	state->Init_Ctrl[8].bit[0] = 2;
-	state->Init_Ctrl[8].val[0] = 0;
-
-	state->Init_Ctrl[9].Ctrl_Num = AGC_IF ;
-	state->Init_Ctrl[9].size = 4 ;
-	state->Init_Ctrl[9].addr[0] = 76;
-	state->Init_Ctrl[9].bit[0] = 0;
-	state->Init_Ctrl[9].val[0] = 1;
-	state->Init_Ctrl[9].addr[1] = 76;
-	state->Init_Ctrl[9].bit[1] = 1;
-	state->Init_Ctrl[9].val[1] = 1;
-	state->Init_Ctrl[9].addr[2] = 76;
-	state->Init_Ctrl[9].bit[2] = 2;
-	state->Init_Ctrl[9].val[2] = 0;
-	state->Init_Ctrl[9].addr[3] = 76;
-	state->Init_Ctrl[9].bit[3] = 3;
-	state->Init_Ctrl[9].val[3] = 1;
-
-	state->Init_Ctrl[10].Ctrl_Num = AGC_RF ;
-	state->Init_Ctrl[10].size = 4 ;
-	state->Init_Ctrl[10].addr[0] = 76;
-	state->Init_Ctrl[10].bit[0] = 4;
-	state->Init_Ctrl[10].val[0] = 1;
-	state->Init_Ctrl[10].addr[1] = 76;
-	state->Init_Ctrl[10].bit[1] = 5;
-	state->Init_Ctrl[10].val[1] = 1;
-	state->Init_Ctrl[10].addr[2] = 76;
-	state->Init_Ctrl[10].bit[2] = 6;
-	state->Init_Ctrl[10].val[2] = 0;
-	state->Init_Ctrl[10].addr[3] = 76;
-	state->Init_Ctrl[10].bit[3] = 7;
-	state->Init_Ctrl[10].val[3] = 1;
-
-	state->Init_Ctrl[11].Ctrl_Num = IF_DIVVAL ;
-	state->Init_Ctrl[11].size = 5 ;
-	state->Init_Ctrl[11].addr[0] = 43;
-	state->Init_Ctrl[11].bit[0] = 3;
-	state->Init_Ctrl[11].val[0] = 0;
-	state->Init_Ctrl[11].addr[1] = 43;
-	state->Init_Ctrl[11].bit[1] = 4;
-	state->Init_Ctrl[11].val[1] = 0;
-	state->Init_Ctrl[11].addr[2] = 43;
-	state->Init_Ctrl[11].bit[2] = 5;
-	state->Init_Ctrl[11].val[2] = 0;
-	state->Init_Ctrl[11].addr[3] = 43;
-	state->Init_Ctrl[11].bit[3] = 6;
-	state->Init_Ctrl[11].val[3] = 1;
-	state->Init_Ctrl[11].addr[4] = 43;
-	state->Init_Ctrl[11].bit[4] = 7;
-	state->Init_Ctrl[11].val[4] = 0;
-
-	state->Init_Ctrl[12].Ctrl_Num = IF_VCO_BIAS ;
-	state->Init_Ctrl[12].size = 6 ;
-	state->Init_Ctrl[12].addr[0] = 44;
-	state->Init_Ctrl[12].bit[0] = 2;
-	state->Init_Ctrl[12].val[0] = 0;
-	state->Init_Ctrl[12].addr[1] = 44;
-	state->Init_Ctrl[12].bit[1] = 3;
-	state->Init_Ctrl[12].val[1] = 0;
-	state->Init_Ctrl[12].addr[2] = 44;
-	state->Init_Ctrl[12].bit[2] = 4;
-	state->Init_Ctrl[12].val[2] = 0;
-	state->Init_Ctrl[12].addr[3] = 44;
-	state->Init_Ctrl[12].bit[3] = 5;
-	state->Init_Ctrl[12].val[3] = 1;
-	state->Init_Ctrl[12].addr[4] = 44;
-	state->Init_Ctrl[12].bit[4] = 6;
-	state->Init_Ctrl[12].val[4] = 0;
-	state->Init_Ctrl[12].addr[5] = 44;
-	state->Init_Ctrl[12].bit[5] = 7;
-	state->Init_Ctrl[12].val[5] = 0;
-
-	state->Init_Ctrl[13].Ctrl_Num = CHCAL_INT_MOD_IF ;
-	state->Init_Ctrl[13].size = 7 ;
-	state->Init_Ctrl[13].addr[0] = 11;
-	state->Init_Ctrl[13].bit[0] = 0;
-	state->Init_Ctrl[13].val[0] = 1;
-	state->Init_Ctrl[13].addr[1] = 11;
-	state->Init_Ctrl[13].bit[1] = 1;
-	state->Init_Ctrl[13].val[1] = 0;
-	state->Init_Ctrl[13].addr[2] = 11;
-	state->Init_Ctrl[13].bit[2] = 2;
-	state->Init_Ctrl[13].val[2] = 0;
-	state->Init_Ctrl[13].addr[3] = 11;
-	state->Init_Ctrl[13].bit[3] = 3;
-	state->Init_Ctrl[13].val[3] = 1;
-	state->Init_Ctrl[13].addr[4] = 11;
-	state->Init_Ctrl[13].bit[4] = 4;
-	state->Init_Ctrl[13].val[4] = 1;
-	state->Init_Ctrl[13].addr[5] = 11;
-	state->Init_Ctrl[13].bit[5] = 5;
-	state->Init_Ctrl[13].val[5] = 0;
-	state->Init_Ctrl[13].addr[6] = 11;
-	state->Init_Ctrl[13].bit[6] = 6;
-	state->Init_Ctrl[13].val[6] = 0;
-
-	state->Init_Ctrl[14].Ctrl_Num = CHCAL_FRAC_MOD_IF ;
-	state->Init_Ctrl[14].size = 16 ;
-	state->Init_Ctrl[14].addr[0] = 13;
-	state->Init_Ctrl[14].bit[0] = 0;
-	state->Init_Ctrl[14].val[0] = 0;
-	state->Init_Ctrl[14].addr[1] = 13;
-	state->Init_Ctrl[14].bit[1] = 1;
-	state->Init_Ctrl[14].val[1] = 0;
-	state->Init_Ctrl[14].addr[2] = 13;
-	state->Init_Ctrl[14].bit[2] = 2;
-	state->Init_Ctrl[14].val[2] = 0;
-	state->Init_Ctrl[14].addr[3] = 13;
-	state->Init_Ctrl[14].bit[3] = 3;
-	state->Init_Ctrl[14].val[3] = 0;
-	state->Init_Ctrl[14].addr[4] = 13;
-	state->Init_Ctrl[14].bit[4] = 4;
-	state->Init_Ctrl[14].val[4] = 0;
-	state->Init_Ctrl[14].addr[5] = 13;
-	state->Init_Ctrl[14].bit[5] = 5;
-	state->Init_Ctrl[14].val[5] = 0;
-	state->Init_Ctrl[14].addr[6] = 13;
-	state->Init_Ctrl[14].bit[6] = 6;
-	state->Init_Ctrl[14].val[6] = 0;
-	state->Init_Ctrl[14].addr[7] = 13;
-	state->Init_Ctrl[14].bit[7] = 7;
-	state->Init_Ctrl[14].val[7] = 0;
-	state->Init_Ctrl[14].addr[8] = 12;
-	state->Init_Ctrl[14].bit[8] = 0;
-	state->Init_Ctrl[14].val[8] = 0;
-	state->Init_Ctrl[14].addr[9] = 12;
-	state->Init_Ctrl[14].bit[9] = 1;
-	state->Init_Ctrl[14].val[9] = 0;
-	state->Init_Ctrl[14].addr[10] = 12;
-	state->Init_Ctrl[14].bit[10] = 2;
-	state->Init_Ctrl[14].val[10] = 0;
-	state->Init_Ctrl[14].addr[11] = 12;
-	state->Init_Ctrl[14].bit[11] = 3;
-	state->Init_Ctrl[14].val[11] = 0;
-	state->Init_Ctrl[14].addr[12] = 12;
-	state->Init_Ctrl[14].bit[12] = 4;
-	state->Init_Ctrl[14].val[12] = 0;
-	state->Init_Ctrl[14].addr[13] = 12;
-	state->Init_Ctrl[14].bit[13] = 5;
-	state->Init_Ctrl[14].val[13] = 1;
-	state->Init_Ctrl[14].addr[14] = 12;
-	state->Init_Ctrl[14].bit[14] = 6;
-	state->Init_Ctrl[14].val[14] = 1;
-	state->Init_Ctrl[14].addr[15] = 12;
-	state->Init_Ctrl[14].bit[15] = 7;
-	state->Init_Ctrl[14].val[15] = 0;
-
-	state->Init_Ctrl[15].Ctrl_Num = DRV_RES_SEL ;
-	state->Init_Ctrl[15].size = 3 ;
-	state->Init_Ctrl[15].addr[0] = 147;
-	state->Init_Ctrl[15].bit[0] = 2;
-	state->Init_Ctrl[15].val[0] = 0;
-	state->Init_Ctrl[15].addr[1] = 147;
-	state->Init_Ctrl[15].bit[1] = 3;
-	state->Init_Ctrl[15].val[1] = 1;
-	state->Init_Ctrl[15].addr[2] = 147;
-	state->Init_Ctrl[15].bit[2] = 4;
-	state->Init_Ctrl[15].val[2] = 1;
-
-	state->Init_Ctrl[16].Ctrl_Num = I_DRIVER ;
-	state->Init_Ctrl[16].size = 2 ;
-	state->Init_Ctrl[16].addr[0] = 147;
-	state->Init_Ctrl[16].bit[0] = 0;
-	state->Init_Ctrl[16].val[0] = 0;
-	state->Init_Ctrl[16].addr[1] = 147;
-	state->Init_Ctrl[16].bit[1] = 1;
-	state->Init_Ctrl[16].val[1] = 1;
-
-	state->Init_Ctrl[17].Ctrl_Num = EN_AAF ;
-	state->Init_Ctrl[17].size = 1 ;
-	state->Init_Ctrl[17].addr[0] = 147;
-	state->Init_Ctrl[17].bit[0] = 7;
-	state->Init_Ctrl[17].val[0] = 0;
-
-	state->Init_Ctrl[18].Ctrl_Num = EN_3P ;
-	state->Init_Ctrl[18].size = 1 ;
-	state->Init_Ctrl[18].addr[0] = 147;
-	state->Init_Ctrl[18].bit[0] = 6;
-	state->Init_Ctrl[18].val[0] = 0;
-
-	state->Init_Ctrl[19].Ctrl_Num = EN_AUX_3P ;
-	state->Init_Ctrl[19].size = 1 ;
-	state->Init_Ctrl[19].addr[0] = 156;
-	state->Init_Ctrl[19].bit[0] = 0;
-	state->Init_Ctrl[19].val[0] = 0;
-
-	state->Init_Ctrl[20].Ctrl_Num = SEL_AAF_BAND ;
-	state->Init_Ctrl[20].size = 1 ;
-	state->Init_Ctrl[20].addr[0] = 147;
-	state->Init_Ctrl[20].bit[0] = 5;
-	state->Init_Ctrl[20].val[0] = 0;
-
-	state->Init_Ctrl[21].Ctrl_Num = SEQ_ENCLK16_CLK_OUT ;
-	state->Init_Ctrl[21].size = 1 ;
-	state->Init_Ctrl[21].addr[0] = 137;
-	state->Init_Ctrl[21].bit[0] = 4;
-	state->Init_Ctrl[21].val[0] = 0;
-
-	state->Init_Ctrl[22].Ctrl_Num = SEQ_SEL4_16B ;
-	state->Init_Ctrl[22].size = 1 ;
-	state->Init_Ctrl[22].addr[0] = 137;
-	state->Init_Ctrl[22].bit[0] = 7;
-	state->Init_Ctrl[22].val[0] = 0;
-
-	state->Init_Ctrl[23].Ctrl_Num = XTAL_CAPSELECT ;
-	state->Init_Ctrl[23].size = 1 ;
-	state->Init_Ctrl[23].addr[0] = 91;
-	state->Init_Ctrl[23].bit[0] = 5;
-	state->Init_Ctrl[23].val[0] = 1;
-
-	state->Init_Ctrl[24].Ctrl_Num = IF_SEL_DBL ;
-	state->Init_Ctrl[24].size = 1 ;
-	state->Init_Ctrl[24].addr[0] = 43;
-	state->Init_Ctrl[24].bit[0] = 0;
-	state->Init_Ctrl[24].val[0] = 1;
-
-	state->Init_Ctrl[25].Ctrl_Num = RFSYN_R_DIV ;
-	state->Init_Ctrl[25].size = 2 ;
-	state->Init_Ctrl[25].addr[0] = 22;
-	state->Init_Ctrl[25].bit[0] = 0;
-	state->Init_Ctrl[25].val[0] = 1;
-	state->Init_Ctrl[25].addr[1] = 22;
-	state->Init_Ctrl[25].bit[1] = 1;
-	state->Init_Ctrl[25].val[1] = 1;
-
-	state->Init_Ctrl[26].Ctrl_Num = SEQ_EXTSYNTHCALIF ;
-	state->Init_Ctrl[26].size = 1 ;
-	state->Init_Ctrl[26].addr[0] = 134;
-	state->Init_Ctrl[26].bit[0] = 2;
-	state->Init_Ctrl[26].val[0] = 0;
-
-	state->Init_Ctrl[27].Ctrl_Num = SEQ_EXTDCCAL ;
-	state->Init_Ctrl[27].size = 1 ;
-	state->Init_Ctrl[27].addr[0] = 137;
-	state->Init_Ctrl[27].bit[0] = 3;
-	state->Init_Ctrl[27].val[0] = 0;
-
-	state->Init_Ctrl[28].Ctrl_Num = AGC_EN_RSSI ;
-	state->Init_Ctrl[28].size = 1 ;
-	state->Init_Ctrl[28].addr[0] = 77;
-	state->Init_Ctrl[28].bit[0] = 7;
-	state->Init_Ctrl[28].val[0] = 0;
-
-	state->Init_Ctrl[29].Ctrl_Num = RFA_ENCLKRFAGC ;
-	state->Init_Ctrl[29].size = 1 ;
-	state->Init_Ctrl[29].addr[0] = 166;
-	state->Init_Ctrl[29].bit[0] = 7;
-	state->Init_Ctrl[29].val[0] = 1;
-
-	state->Init_Ctrl[30].Ctrl_Num = RFA_RSSI_REFH ;
-	state->Init_Ctrl[30].size = 3 ;
-	state->Init_Ctrl[30].addr[0] = 166;
-	state->Init_Ctrl[30].bit[0] = 0;
-	state->Init_Ctrl[30].val[0] = 0;
-	state->Init_Ctrl[30].addr[1] = 166;
-	state->Init_Ctrl[30].bit[1] = 1;
-	state->Init_Ctrl[30].val[1] = 1;
-	state->Init_Ctrl[30].addr[2] = 166;
-	state->Init_Ctrl[30].bit[2] = 2;
-	state->Init_Ctrl[30].val[2] = 1;
-
-	state->Init_Ctrl[31].Ctrl_Num = RFA_RSSI_REF ;
-	state->Init_Ctrl[31].size = 3 ;
-	state->Init_Ctrl[31].addr[0] = 166;
-	state->Init_Ctrl[31].bit[0] = 3;
-	state->Init_Ctrl[31].val[0] = 1;
-	state->Init_Ctrl[31].addr[1] = 166;
-	state->Init_Ctrl[31].bit[1] = 4;
-	state->Init_Ctrl[31].val[1] = 0;
-	state->Init_Ctrl[31].addr[2] = 166;
-	state->Init_Ctrl[31].bit[2] = 5;
-	state->Init_Ctrl[31].val[2] = 1;
-
-	state->Init_Ctrl[32].Ctrl_Num = RFA_RSSI_REFL ;
-	state->Init_Ctrl[32].size = 3 ;
-	state->Init_Ctrl[32].addr[0] = 167;
-	state->Init_Ctrl[32].bit[0] = 0;
-	state->Init_Ctrl[32].val[0] = 1;
-	state->Init_Ctrl[32].addr[1] = 167;
-	state->Init_Ctrl[32].bit[1] = 1;
-	state->Init_Ctrl[32].val[1] = 1;
-	state->Init_Ctrl[32].addr[2] = 167;
-	state->Init_Ctrl[32].bit[2] = 2;
-	state->Init_Ctrl[32].val[2] = 0;
-
-	state->Init_Ctrl[33].Ctrl_Num = RFA_FLR ;
-	state->Init_Ctrl[33].size = 4 ;
-	state->Init_Ctrl[33].addr[0] = 168;
-	state->Init_Ctrl[33].bit[0] = 0;
-	state->Init_Ctrl[33].val[0] = 0;
-	state->Init_Ctrl[33].addr[1] = 168;
-	state->Init_Ctrl[33].bit[1] = 1;
-	state->Init_Ctrl[33].val[1] = 1;
-	state->Init_Ctrl[33].addr[2] = 168;
-	state->Init_Ctrl[33].bit[2] = 2;
-	state->Init_Ctrl[33].val[2] = 0;
-	state->Init_Ctrl[33].addr[3] = 168;
-	state->Init_Ctrl[33].bit[3] = 3;
-	state->Init_Ctrl[33].val[3] = 0;
-
-	state->Init_Ctrl[34].Ctrl_Num = RFA_CEIL ;
-	state->Init_Ctrl[34].size = 4 ;
-	state->Init_Ctrl[34].addr[0] = 168;
-	state->Init_Ctrl[34].bit[0] = 4;
-	state->Init_Ctrl[34].val[0] = 1;
-	state->Init_Ctrl[34].addr[1] = 168;
-	state->Init_Ctrl[34].bit[1] = 5;
-	state->Init_Ctrl[34].val[1] = 1;
-	state->Init_Ctrl[34].addr[2] = 168;
-	state->Init_Ctrl[34].bit[2] = 6;
-	state->Init_Ctrl[34].val[2] = 1;
-	state->Init_Ctrl[34].addr[3] = 168;
-	state->Init_Ctrl[34].bit[3] = 7;
-	state->Init_Ctrl[34].val[3] = 1;
-
-	state->Init_Ctrl[35].Ctrl_Num = SEQ_EXTIQFSMPULSE ;
-	state->Init_Ctrl[35].size = 1 ;
-	state->Init_Ctrl[35].addr[0] = 135;
-	state->Init_Ctrl[35].bit[0] = 0;
-	state->Init_Ctrl[35].val[0] = 0;
-
-	state->Init_Ctrl[36].Ctrl_Num = OVERRIDE_1 ;
-	state->Init_Ctrl[36].size = 1 ;
-	state->Init_Ctrl[36].addr[0] = 56;
-	state->Init_Ctrl[36].bit[0] = 3;
-	state->Init_Ctrl[36].val[0] = 0;
-
-	state->Init_Ctrl[37].Ctrl_Num = BB_INITSTATE_DLPF_TUNE ;
-	state->Init_Ctrl[37].size = 7 ;
-	state->Init_Ctrl[37].addr[0] = 59;
-	state->Init_Ctrl[37].bit[0] = 1;
-	state->Init_Ctrl[37].val[0] = 0;
-	state->Init_Ctrl[37].addr[1] = 59;
-	state->Init_Ctrl[37].bit[1] = 2;
-	state->Init_Ctrl[37].val[1] = 0;
-	state->Init_Ctrl[37].addr[2] = 59;
-	state->Init_Ctrl[37].bit[2] = 3;
-	state->Init_Ctrl[37].val[2] = 0;
-	state->Init_Ctrl[37].addr[3] = 59;
-	state->Init_Ctrl[37].bit[3] = 4;
-	state->Init_Ctrl[37].val[3] = 0;
-	state->Init_Ctrl[37].addr[4] = 59;
-	state->Init_Ctrl[37].bit[4] = 5;
-	state->Init_Ctrl[37].val[4] = 0;
-	state->Init_Ctrl[37].addr[5] = 59;
-	state->Init_Ctrl[37].bit[5] = 6;
-	state->Init_Ctrl[37].val[5] = 0;
-	state->Init_Ctrl[37].addr[6] = 59;
-	state->Init_Ctrl[37].bit[6] = 7;
-	state->Init_Ctrl[37].val[6] = 0;
-
-	state->Init_Ctrl[38].Ctrl_Num = TG_R_DIV ;
-	state->Init_Ctrl[38].size = 6 ;
-	state->Init_Ctrl[38].addr[0] = 32;
-	state->Init_Ctrl[38].bit[0] = 2;
-	state->Init_Ctrl[38].val[0] = 0;
-	state->Init_Ctrl[38].addr[1] = 32;
-	state->Init_Ctrl[38].bit[1] = 3;
-	state->Init_Ctrl[38].val[1] = 0;
-	state->Init_Ctrl[38].addr[2] = 32;
-	state->Init_Ctrl[38].bit[2] = 4;
-	state->Init_Ctrl[38].val[2] = 0;
-	state->Init_Ctrl[38].addr[3] = 32;
-	state->Init_Ctrl[38].bit[3] = 5;
-	state->Init_Ctrl[38].val[3] = 0;
-	state->Init_Ctrl[38].addr[4] = 32;
-	state->Init_Ctrl[38].bit[4] = 6;
-	state->Init_Ctrl[38].val[4] = 1;
-	state->Init_Ctrl[38].addr[5] = 32;
-	state->Init_Ctrl[38].bit[5] = 7;
-	state->Init_Ctrl[38].val[5] = 0;
-
-	state->Init_Ctrl[39].Ctrl_Num = EN_CHP_LIN_B ;
-	state->Init_Ctrl[39].size = 1 ;
-	state->Init_Ctrl[39].addr[0] = 25;
-	state->Init_Ctrl[39].bit[0] = 3;
-	state->Init_Ctrl[39].val[0] = 1;
-
-
-	state->CH_Ctrl_Num = CHCTRL_NUM ;
-
-	state->CH_Ctrl[0].Ctrl_Num = DN_POLY ;
-	state->CH_Ctrl[0].size = 2 ;
-	state->CH_Ctrl[0].addr[0] = 68;
-	state->CH_Ctrl[0].bit[0] = 6;
-	state->CH_Ctrl[0].val[0] = 1;
-	state->CH_Ctrl[0].addr[1] = 68;
-	state->CH_Ctrl[0].bit[1] = 7;
-	state->CH_Ctrl[0].val[1] = 1;
-
-	state->CH_Ctrl[1].Ctrl_Num = DN_RFGAIN ;
-	state->CH_Ctrl[1].size = 2 ;
-	state->CH_Ctrl[1].addr[0] = 70;
-	state->CH_Ctrl[1].bit[0] = 6;
-	state->CH_Ctrl[1].val[0] = 1;
-	state->CH_Ctrl[1].addr[1] = 70;
-	state->CH_Ctrl[1].bit[1] = 7;
-	state->CH_Ctrl[1].val[1] = 0;
-
-	state->CH_Ctrl[2].Ctrl_Num = DN_CAP_RFLPF ;
-	state->CH_Ctrl[2].size = 9 ;
-	state->CH_Ctrl[2].addr[0] = 69;
-	state->CH_Ctrl[2].bit[0] = 5;
-	state->CH_Ctrl[2].val[0] = 0;
-	state->CH_Ctrl[2].addr[1] = 69;
-	state->CH_Ctrl[2].bit[1] = 6;
-	state->CH_Ctrl[2].val[1] = 0;
-	state->CH_Ctrl[2].addr[2] = 69;
-	state->CH_Ctrl[2].bit[2] = 7;
-	state->CH_Ctrl[2].val[2] = 0;
-	state->CH_Ctrl[2].addr[3] = 68;
-	state->CH_Ctrl[2].bit[3] = 0;
-	state->CH_Ctrl[2].val[3] = 0;
-	state->CH_Ctrl[2].addr[4] = 68;
-	state->CH_Ctrl[2].bit[4] = 1;
-	state->CH_Ctrl[2].val[4] = 0;
-	state->CH_Ctrl[2].addr[5] = 68;
-	state->CH_Ctrl[2].bit[5] = 2;
-	state->CH_Ctrl[2].val[5] = 0;
-	state->CH_Ctrl[2].addr[6] = 68;
-	state->CH_Ctrl[2].bit[6] = 3;
-	state->CH_Ctrl[2].val[6] = 0;
-	state->CH_Ctrl[2].addr[7] = 68;
-	state->CH_Ctrl[2].bit[7] = 4;
-	state->CH_Ctrl[2].val[7] = 0;
-	state->CH_Ctrl[2].addr[8] = 68;
-	state->CH_Ctrl[2].bit[8] = 5;
-	state->CH_Ctrl[2].val[8] = 0;
-
-	state->CH_Ctrl[3].Ctrl_Num = DN_EN_VHFUHFBAR ;
-	state->CH_Ctrl[3].size = 1 ;
-	state->CH_Ctrl[3].addr[0] = 70;
-	state->CH_Ctrl[3].bit[0] = 5;
-	state->CH_Ctrl[3].val[0] = 0;
-
-	state->CH_Ctrl[4].Ctrl_Num = DN_GAIN_ADJUST ;
-	state->CH_Ctrl[4].size = 3 ;
-	state->CH_Ctrl[4].addr[0] = 73;
-	state->CH_Ctrl[4].bit[0] = 4;
-	state->CH_Ctrl[4].val[0] = 0;
-	state->CH_Ctrl[4].addr[1] = 73;
-	state->CH_Ctrl[4].bit[1] = 5;
-	state->CH_Ctrl[4].val[1] = 1;
-	state->CH_Ctrl[4].addr[2] = 73;
-	state->CH_Ctrl[4].bit[2] = 6;
-	state->CH_Ctrl[4].val[2] = 0;
-
-	state->CH_Ctrl[5].Ctrl_Num = DN_IQTNBUF_AMP ;
-	state->CH_Ctrl[5].size = 4 ;
-	state->CH_Ctrl[5].addr[0] = 70;
-	state->CH_Ctrl[5].bit[0] = 0;
-	state->CH_Ctrl[5].val[0] = 0;
-	state->CH_Ctrl[5].addr[1] = 70;
-	state->CH_Ctrl[5].bit[1] = 1;
-	state->CH_Ctrl[5].val[1] = 0;
-	state->CH_Ctrl[5].addr[2] = 70;
-	state->CH_Ctrl[5].bit[2] = 2;
-	state->CH_Ctrl[5].val[2] = 0;
-	state->CH_Ctrl[5].addr[3] = 70;
-	state->CH_Ctrl[5].bit[3] = 3;
-	state->CH_Ctrl[5].val[3] = 0;
-
-	state->CH_Ctrl[6].Ctrl_Num = DN_IQTNGNBFBIAS_BST ;
-	state->CH_Ctrl[6].size = 1 ;
-	state->CH_Ctrl[6].addr[0] = 70;
-	state->CH_Ctrl[6].bit[0] = 4;
-	state->CH_Ctrl[6].val[0] = 1;
-
-	state->CH_Ctrl[7].Ctrl_Num = RFSYN_EN_OUTMUX ;
-	state->CH_Ctrl[7].size = 1 ;
-	state->CH_Ctrl[7].addr[0] = 111;
-	state->CH_Ctrl[7].bit[0] = 4;
-	state->CH_Ctrl[7].val[0] = 0;
-
-	state->CH_Ctrl[8].Ctrl_Num = RFSYN_SEL_VCO_OUT ;
-	state->CH_Ctrl[8].size = 1 ;
-	state->CH_Ctrl[8].addr[0] = 111;
-	state->CH_Ctrl[8].bit[0] = 7;
-	state->CH_Ctrl[8].val[0] = 1;
-
-	state->CH_Ctrl[9].Ctrl_Num = RFSYN_SEL_VCO_HI ;
-	state->CH_Ctrl[9].size = 1 ;
-	state->CH_Ctrl[9].addr[0] = 111;
-	state->CH_Ctrl[9].bit[0] = 6;
-	state->CH_Ctrl[9].val[0] = 1;
-
-	state->CH_Ctrl[10].Ctrl_Num = RFSYN_SEL_DIVM ;
-	state->CH_Ctrl[10].size = 1 ;
-	state->CH_Ctrl[10].addr[0] = 111;
-	state->CH_Ctrl[10].bit[0] = 5;
-	state->CH_Ctrl[10].val[0] = 0;
-
-	state->CH_Ctrl[11].Ctrl_Num = RFSYN_RF_DIV_BIAS ;
-	state->CH_Ctrl[11].size = 2 ;
-	state->CH_Ctrl[11].addr[0] = 110;
-	state->CH_Ctrl[11].bit[0] = 0;
-	state->CH_Ctrl[11].val[0] = 1;
-	state->CH_Ctrl[11].addr[1] = 110;
-	state->CH_Ctrl[11].bit[1] = 1;
-	state->CH_Ctrl[11].val[1] = 0;
-
-	state->CH_Ctrl[12].Ctrl_Num = DN_SEL_FREQ ;
-	state->CH_Ctrl[12].size = 3 ;
-	state->CH_Ctrl[12].addr[0] = 69;
-	state->CH_Ctrl[12].bit[0] = 2;
-	state->CH_Ctrl[12].val[0] = 0;
-	state->CH_Ctrl[12].addr[1] = 69;
-	state->CH_Ctrl[12].bit[1] = 3;
-	state->CH_Ctrl[12].val[1] = 0;
-	state->CH_Ctrl[12].addr[2] = 69;
-	state->CH_Ctrl[12].bit[2] = 4;
-	state->CH_Ctrl[12].val[2] = 0;
-
-	state->CH_Ctrl[13].Ctrl_Num = RFSYN_VCO_BIAS ;
-	state->CH_Ctrl[13].size = 6 ;
-	state->CH_Ctrl[13].addr[0] = 110;
-	state->CH_Ctrl[13].bit[0] = 2;
-	state->CH_Ctrl[13].val[0] = 0;
-	state->CH_Ctrl[13].addr[1] = 110;
-	state->CH_Ctrl[13].bit[1] = 3;
-	state->CH_Ctrl[13].val[1] = 0;
-	state->CH_Ctrl[13].addr[2] = 110;
-	state->CH_Ctrl[13].bit[2] = 4;
-	state->CH_Ctrl[13].val[2] = 0;
-	state->CH_Ctrl[13].addr[3] = 110;
-	state->CH_Ctrl[13].bit[3] = 5;
-	state->CH_Ctrl[13].val[3] = 0;
-	state->CH_Ctrl[13].addr[4] = 110;
-	state->CH_Ctrl[13].bit[4] = 6;
-	state->CH_Ctrl[13].val[4] = 0;
-	state->CH_Ctrl[13].addr[5] = 110;
-	state->CH_Ctrl[13].bit[5] = 7;
-	state->CH_Ctrl[13].val[5] = 1;
-
-	state->CH_Ctrl[14].Ctrl_Num = CHCAL_INT_MOD_RF ;
-	state->CH_Ctrl[14].size = 7 ;
-	state->CH_Ctrl[14].addr[0] = 14;
-	state->CH_Ctrl[14].bit[0] = 0;
-	state->CH_Ctrl[14].val[0] = 0;
-	state->CH_Ctrl[14].addr[1] = 14;
-	state->CH_Ctrl[14].bit[1] = 1;
-	state->CH_Ctrl[14].val[1] = 0;
-	state->CH_Ctrl[14].addr[2] = 14;
-	state->CH_Ctrl[14].bit[2] = 2;
-	state->CH_Ctrl[14].val[2] = 0;
-	state->CH_Ctrl[14].addr[3] = 14;
-	state->CH_Ctrl[14].bit[3] = 3;
-	state->CH_Ctrl[14].val[3] = 0;
-	state->CH_Ctrl[14].addr[4] = 14;
-	state->CH_Ctrl[14].bit[4] = 4;
-	state->CH_Ctrl[14].val[4] = 0;
-	state->CH_Ctrl[14].addr[5] = 14;
-	state->CH_Ctrl[14].bit[5] = 5;
-	state->CH_Ctrl[14].val[5] = 0;
-	state->CH_Ctrl[14].addr[6] = 14;
-	state->CH_Ctrl[14].bit[6] = 6;
-	state->CH_Ctrl[14].val[6] = 0;
-
-	state->CH_Ctrl[15].Ctrl_Num = CHCAL_FRAC_MOD_RF ;
-	state->CH_Ctrl[15].size = 18 ;
-	state->CH_Ctrl[15].addr[0] = 17;
-	state->CH_Ctrl[15].bit[0] = 6;
-	state->CH_Ctrl[15].val[0] = 0;
-	state->CH_Ctrl[15].addr[1] = 17;
-	state->CH_Ctrl[15].bit[1] = 7;
-	state->CH_Ctrl[15].val[1] = 0;
-	state->CH_Ctrl[15].addr[2] = 16;
-	state->CH_Ctrl[15].bit[2] = 0;
-	state->CH_Ctrl[15].val[2] = 0;
-	state->CH_Ctrl[15].addr[3] = 16;
-	state->CH_Ctrl[15].bit[3] = 1;
-	state->CH_Ctrl[15].val[3] = 0;
-	state->CH_Ctrl[15].addr[4] = 16;
-	state->CH_Ctrl[15].bit[4] = 2;
-	state->CH_Ctrl[15].val[4] = 0;
-	state->CH_Ctrl[15].addr[5] = 16;
-	state->CH_Ctrl[15].bit[5] = 3;
-	state->CH_Ctrl[15].val[5] = 0;
-	state->CH_Ctrl[15].addr[6] = 16;
-	state->CH_Ctrl[15].bit[6] = 4;
-	state->CH_Ctrl[15].val[6] = 0;
-	state->CH_Ctrl[15].addr[7] = 16;
-	state->CH_Ctrl[15].bit[7] = 5;
-	state->CH_Ctrl[15].val[7] = 0;
-	state->CH_Ctrl[15].addr[8] = 16;
-	state->CH_Ctrl[15].bit[8] = 6;
-	state->CH_Ctrl[15].val[8] = 0;
-	state->CH_Ctrl[15].addr[9] = 16;
-	state->CH_Ctrl[15].bit[9] = 7;
-	state->CH_Ctrl[15].val[9] = 0;
-	state->CH_Ctrl[15].addr[10] = 15;
-	state->CH_Ctrl[15].bit[10] = 0;
-	state->CH_Ctrl[15].val[10] = 0;
-	state->CH_Ctrl[15].addr[11] = 15;
-	state->CH_Ctrl[15].bit[11] = 1;
-	state->CH_Ctrl[15].val[11] = 0;
-	state->CH_Ctrl[15].addr[12] = 15;
-	state->CH_Ctrl[15].bit[12] = 2;
-	state->CH_Ctrl[15].val[12] = 0;
-	state->CH_Ctrl[15].addr[13] = 15;
-	state->CH_Ctrl[15].bit[13] = 3;
-	state->CH_Ctrl[15].val[13] = 0;
-	state->CH_Ctrl[15].addr[14] = 15;
-	state->CH_Ctrl[15].bit[14] = 4;
-	state->CH_Ctrl[15].val[14] = 0;
-	state->CH_Ctrl[15].addr[15] = 15;
-	state->CH_Ctrl[15].bit[15] = 5;
-	state->CH_Ctrl[15].val[15] = 0;
-	state->CH_Ctrl[15].addr[16] = 15;
-	state->CH_Ctrl[15].bit[16] = 6;
-	state->CH_Ctrl[15].val[16] = 1;
-	state->CH_Ctrl[15].addr[17] = 15;
-	state->CH_Ctrl[15].bit[17] = 7;
-	state->CH_Ctrl[15].val[17] = 1;
-
-	state->CH_Ctrl[16].Ctrl_Num = RFSYN_LPF_R ;
-	state->CH_Ctrl[16].size = 5 ;
-	state->CH_Ctrl[16].addr[0] = 112;
-	state->CH_Ctrl[16].bit[0] = 0;
-	state->CH_Ctrl[16].val[0] = 0;
-	state->CH_Ctrl[16].addr[1] = 112;
-	state->CH_Ctrl[16].bit[1] = 1;
-	state->CH_Ctrl[16].val[1] = 0;
-	state->CH_Ctrl[16].addr[2] = 112;
-	state->CH_Ctrl[16].bit[2] = 2;
-	state->CH_Ctrl[16].val[2] = 0;
-	state->CH_Ctrl[16].addr[3] = 112;
-	state->CH_Ctrl[16].bit[3] = 3;
-	state->CH_Ctrl[16].val[3] = 0;
-	state->CH_Ctrl[16].addr[4] = 112;
-	state->CH_Ctrl[16].bit[4] = 4;
-	state->CH_Ctrl[16].val[4] = 1;
-
-	state->CH_Ctrl[17].Ctrl_Num = CHCAL_EN_INT_RF ;
-	state->CH_Ctrl[17].size = 1 ;
-	state->CH_Ctrl[17].addr[0] = 14;
-	state->CH_Ctrl[17].bit[0] = 7;
-	state->CH_Ctrl[17].val[0] = 0;
-
-	state->CH_Ctrl[18].Ctrl_Num = TG_LO_DIVVAL ;
-	state->CH_Ctrl[18].size = 4 ;
-	state->CH_Ctrl[18].addr[0] = 107;
-	state->CH_Ctrl[18].bit[0] = 3;
-	state->CH_Ctrl[18].val[0] = 0;
-	state->CH_Ctrl[18].addr[1] = 107;
-	state->CH_Ctrl[18].bit[1] = 4;
-	state->CH_Ctrl[18].val[1] = 0;
-	state->CH_Ctrl[18].addr[2] = 107;
-	state->CH_Ctrl[18].bit[2] = 5;
-	state->CH_Ctrl[18].val[2] = 0;
-	state->CH_Ctrl[18].addr[3] = 107;
-	state->CH_Ctrl[18].bit[3] = 6;
-	state->CH_Ctrl[18].val[3] = 0;
-
-	state->CH_Ctrl[19].Ctrl_Num = TG_LO_SELVAL ;
-	state->CH_Ctrl[19].size = 3 ;
-	state->CH_Ctrl[19].addr[0] = 107;
-	state->CH_Ctrl[19].bit[0] = 7;
-	state->CH_Ctrl[19].val[0] = 1;
-	state->CH_Ctrl[19].addr[1] = 106;
-	state->CH_Ctrl[19].bit[1] = 0;
-	state->CH_Ctrl[19].val[1] = 1;
-	state->CH_Ctrl[19].addr[2] = 106;
-	state->CH_Ctrl[19].bit[2] = 1;
-	state->CH_Ctrl[19].val[2] = 1;
-
-	state->CH_Ctrl[20].Ctrl_Num = TG_DIV_VAL ;
-	state->CH_Ctrl[20].size = 11 ;
-	state->CH_Ctrl[20].addr[0] = 109;
-	state->CH_Ctrl[20].bit[0] = 2;
-	state->CH_Ctrl[20].val[0] = 0;
-	state->CH_Ctrl[20].addr[1] = 109;
-	state->CH_Ctrl[20].bit[1] = 3;
-	state->CH_Ctrl[20].val[1] = 0;
-	state->CH_Ctrl[20].addr[2] = 109;
-	state->CH_Ctrl[20].bit[2] = 4;
-	state->CH_Ctrl[20].val[2] = 0;
-	state->CH_Ctrl[20].addr[3] = 109;
-	state->CH_Ctrl[20].bit[3] = 5;
-	state->CH_Ctrl[20].val[3] = 0;
-	state->CH_Ctrl[20].addr[4] = 109;
-	state->CH_Ctrl[20].bit[4] = 6;
-	state->CH_Ctrl[20].val[4] = 0;
-	state->CH_Ctrl[20].addr[5] = 109;
-	state->CH_Ctrl[20].bit[5] = 7;
-	state->CH_Ctrl[20].val[5] = 0;
-	state->CH_Ctrl[20].addr[6] = 108;
-	state->CH_Ctrl[20].bit[6] = 0;
-	state->CH_Ctrl[20].val[6] = 0;
-	state->CH_Ctrl[20].addr[7] = 108;
-	state->CH_Ctrl[20].bit[7] = 1;
-	state->CH_Ctrl[20].val[7] = 0;
-	state->CH_Ctrl[20].addr[8] = 108;
-	state->CH_Ctrl[20].bit[8] = 2;
-	state->CH_Ctrl[20].val[8] = 1;
-	state->CH_Ctrl[20].addr[9] = 108;
-	state->CH_Ctrl[20].bit[9] = 3;
-	state->CH_Ctrl[20].val[9] = 1;
-	state->CH_Ctrl[20].addr[10] = 108;
-	state->CH_Ctrl[20].bit[10] = 4;
-	state->CH_Ctrl[20].val[10] = 1;
-
-	state->CH_Ctrl[21].Ctrl_Num = TG_VCO_BIAS ;
-	state->CH_Ctrl[21].size = 6 ;
-	state->CH_Ctrl[21].addr[0] = 106;
-	state->CH_Ctrl[21].bit[0] = 2;
-	state->CH_Ctrl[21].val[0] = 0;
-	state->CH_Ctrl[21].addr[1] = 106;
-	state->CH_Ctrl[21].bit[1] = 3;
-	state->CH_Ctrl[21].val[1] = 0;
-	state->CH_Ctrl[21].addr[2] = 106;
-	state->CH_Ctrl[21].bit[2] = 4;
-	state->CH_Ctrl[21].val[2] = 0;
-	state->CH_Ctrl[21].addr[3] = 106;
-	state->CH_Ctrl[21].bit[3] = 5;
-	state->CH_Ctrl[21].val[3] = 0;
-	state->CH_Ctrl[21].addr[4] = 106;
-	state->CH_Ctrl[21].bit[4] = 6;
-	state->CH_Ctrl[21].val[4] = 0;
-	state->CH_Ctrl[21].addr[5] = 106;
-	state->CH_Ctrl[21].bit[5] = 7;
-	state->CH_Ctrl[21].val[5] = 1;
-
-	state->CH_Ctrl[22].Ctrl_Num = SEQ_EXTPOWERUP ;
-	state->CH_Ctrl[22].size = 1 ;
-	state->CH_Ctrl[22].addr[0] = 138;
-	state->CH_Ctrl[22].bit[0] = 4;
-	state->CH_Ctrl[22].val[0] = 1;
-
-	state->CH_Ctrl[23].Ctrl_Num = OVERRIDE_2 ;
-	state->CH_Ctrl[23].size = 1 ;
-	state->CH_Ctrl[23].addr[0] = 17;
-	state->CH_Ctrl[23].bit[0] = 5;
-	state->CH_Ctrl[23].val[0] = 0;
-
-	state->CH_Ctrl[24].Ctrl_Num = OVERRIDE_3 ;
-	state->CH_Ctrl[24].size = 1 ;
-	state->CH_Ctrl[24].addr[0] = 111;
-	state->CH_Ctrl[24].bit[0] = 3;
-	state->CH_Ctrl[24].val[0] = 0;
-
-	state->CH_Ctrl[25].Ctrl_Num = OVERRIDE_4 ;
-	state->CH_Ctrl[25].size = 1 ;
-	state->CH_Ctrl[25].addr[0] = 112;
-	state->CH_Ctrl[25].bit[0] = 7;
-	state->CH_Ctrl[25].val[0] = 0;
-
-	state->CH_Ctrl[26].Ctrl_Num = SEQ_FSM_PULSE ;
-	state->CH_Ctrl[26].size = 1 ;
-	state->CH_Ctrl[26].addr[0] = 136;
-	state->CH_Ctrl[26].bit[0] = 7;
-	state->CH_Ctrl[26].val[0] = 0;
-
-	state->CH_Ctrl[27].Ctrl_Num = GPIO_4B ;
-	state->CH_Ctrl[27].size = 1 ;
-	state->CH_Ctrl[27].addr[0] = 149;
-	state->CH_Ctrl[27].bit[0] = 7;
-	state->CH_Ctrl[27].val[0] = 0;
-
-	state->CH_Ctrl[28].Ctrl_Num = GPIO_3B ;
-	state->CH_Ctrl[28].size = 1 ;
-	state->CH_Ctrl[28].addr[0] = 149;
-	state->CH_Ctrl[28].bit[0] = 6;
-	state->CH_Ctrl[28].val[0] = 0;
-
-	state->CH_Ctrl[29].Ctrl_Num = GPIO_4 ;
-	state->CH_Ctrl[29].size = 1 ;
-	state->CH_Ctrl[29].addr[0] = 149;
-	state->CH_Ctrl[29].bit[0] = 5;
-	state->CH_Ctrl[29].val[0] = 1;
-
-	state->CH_Ctrl[30].Ctrl_Num = GPIO_3 ;
-	state->CH_Ctrl[30].size = 1 ;
-	state->CH_Ctrl[30].addr[0] = 149;
-	state->CH_Ctrl[30].bit[0] = 4;
-	state->CH_Ctrl[30].val[0] = 1;
-
-	state->CH_Ctrl[31].Ctrl_Num = GPIO_1B ;
-	state->CH_Ctrl[31].size = 1 ;
-	state->CH_Ctrl[31].addr[0] = 149;
-	state->CH_Ctrl[31].bit[0] = 3;
-	state->CH_Ctrl[31].val[0] = 0;
-
-	state->CH_Ctrl[32].Ctrl_Num = DAC_A_ENABLE ;
-	state->CH_Ctrl[32].size = 1 ;
-	state->CH_Ctrl[32].addr[0] = 93;
-	state->CH_Ctrl[32].bit[0] = 1;
-	state->CH_Ctrl[32].val[0] = 0;
-
-	state->CH_Ctrl[33].Ctrl_Num = DAC_B_ENABLE ;
-	state->CH_Ctrl[33].size = 1 ;
-	state->CH_Ctrl[33].addr[0] = 93;
-	state->CH_Ctrl[33].bit[0] = 0;
-	state->CH_Ctrl[33].val[0] = 0;
-
-	state->CH_Ctrl[34].Ctrl_Num = DAC_DIN_A ;
-	state->CH_Ctrl[34].size = 6 ;
-	state->CH_Ctrl[34].addr[0] = 92;
-	state->CH_Ctrl[34].bit[0] = 2;
-	state->CH_Ctrl[34].val[0] = 0;
-	state->CH_Ctrl[34].addr[1] = 92;
-	state->CH_Ctrl[34].bit[1] = 3;
-	state->CH_Ctrl[34].val[1] = 0;
-	state->CH_Ctrl[34].addr[2] = 92;
-	state->CH_Ctrl[34].bit[2] = 4;
-	state->CH_Ctrl[34].val[2] = 0;
-	state->CH_Ctrl[34].addr[3] = 92;
-	state->CH_Ctrl[34].bit[3] = 5;
-	state->CH_Ctrl[34].val[3] = 0;
-	state->CH_Ctrl[34].addr[4] = 92;
-	state->CH_Ctrl[34].bit[4] = 6;
-	state->CH_Ctrl[34].val[4] = 0;
-	state->CH_Ctrl[34].addr[5] = 92;
-	state->CH_Ctrl[34].bit[5] = 7;
-	state->CH_Ctrl[34].val[5] = 0;
-
-	state->CH_Ctrl[35].Ctrl_Num = DAC_DIN_B ;
-	state->CH_Ctrl[35].size = 6 ;
-	state->CH_Ctrl[35].addr[0] = 93;
-	state->CH_Ctrl[35].bit[0] = 2;
-	state->CH_Ctrl[35].val[0] = 0;
-	state->CH_Ctrl[35].addr[1] = 93;
-	state->CH_Ctrl[35].bit[1] = 3;
-	state->CH_Ctrl[35].val[1] = 0;
-	state->CH_Ctrl[35].addr[2] = 93;
-	state->CH_Ctrl[35].bit[2] = 4;
-	state->CH_Ctrl[35].val[2] = 0;
-	state->CH_Ctrl[35].addr[3] = 93;
-	state->CH_Ctrl[35].bit[3] = 5;
-	state->CH_Ctrl[35].val[3] = 0;
-	state->CH_Ctrl[35].addr[4] = 93;
-	state->CH_Ctrl[35].bit[4] = 6;
-	state->CH_Ctrl[35].val[4] = 0;
-	state->CH_Ctrl[35].addr[5] = 93;
-	state->CH_Ctrl[35].bit[5] = 7;
-	state->CH_Ctrl[35].val[5] = 0;
-
-#ifdef _MXL_PRODUCTION
-	state->CH_Ctrl[36].Ctrl_Num = RFSYN_EN_DIV ;
-	state->CH_Ctrl[36].size = 1 ;
-	state->CH_Ctrl[36].addr[0] = 109;
-	state->CH_Ctrl[36].bit[0] = 1;
-	state->CH_Ctrl[36].val[0] = 1;
-
-	state->CH_Ctrl[37].Ctrl_Num = RFSYN_DIVM ;
-	state->CH_Ctrl[37].size = 2 ;
-	state->CH_Ctrl[37].addr[0] = 112;
-	state->CH_Ctrl[37].bit[0] = 5;
-	state->CH_Ctrl[37].val[0] = 0;
-	state->CH_Ctrl[37].addr[1] = 112;
-	state->CH_Ctrl[37].bit[1] = 6;
-	state->CH_Ctrl[37].val[1] = 0;
-
-	state->CH_Ctrl[38].Ctrl_Num = DN_BYPASS_AGC_I2C ;
-	state->CH_Ctrl[38].size = 1 ;
-	state->CH_Ctrl[38].addr[0] = 65;
-	state->CH_Ctrl[38].bit[0] = 1;
-	state->CH_Ctrl[38].val[0] = 0;
-#endif
-
-	return 0 ;
-}
-
-static void InitTunerControls(struct dvb_frontend *fe)
-{
-	MXL5005_RegisterInit(fe);
-	MXL5005_ControlInit(fe);
-#ifdef _MXL_INTERNAL
-	MXL5005_MXLControlInit(fe);
-#endif
-}
-
-static u16 MXL5005_TunerConfig(struct dvb_frontend *fe,
-	u8	Mode,		/* 0: Analog Mode ; 1: Digital Mode */
-	u8	IF_mode,	/* for Analog Mode, 0: zero IF; 1: low IF */
-	u32	Bandwidth,	/* filter  channel bandwidth (6, 7, 8) */
-	u32	IF_out,		/* Desired IF Out Frequency */
-	u32	Fxtal,		/* XTAL Frequency */
-	u8	AGC_Mode,	/* AGC Mode - Dual AGC: 0, Single AGC: 1 */
-	u16	TOP,		/* 0: Dual AGC; Value: take over point */
-	u16	IF_OUT_LOAD,	/* IF Out Load Resistor (200 / 300 Ohms) */
-	u8	CLOCK_OUT, 	/* 0: turn off clk out; 1: turn on clock out */
-	u8	DIV_OUT,	/* 0: Div-1; 1: Div-4 */
-	u8	CAPSELECT, 	/* 0: disable On-Chip pulling cap; 1: enable */
-	u8	EN_RSSI, 	/* 0: disable RSSI; 1: enable RSSI */
-
-	/* Modulation Type; */
-	/* 0 - Default;	1 - DVB-T; 2 - ATSC; 3 - QAM; 4 - Analog Cable */
-	u8	Mod_Type,
-
-	/* Tracking Filter */
-	/* 0 - Default; 1 - Off; 2 - Type C; 3 - Type C-H */
-	u8	TF_Type
-	)
-{
-	struct mxl5005s_state *state = fe->tuner_priv;
-	u16 status = 0;
-
-	state->Mode = Mode;
-	state->IF_Mode = IF_mode;
-	state->Chan_Bandwidth = Bandwidth;
-	state->IF_OUT = IF_out;
-	state->Fxtal = Fxtal;
-	state->AGC_Mode = AGC_Mode;
-	state->TOP = TOP;
-	state->IF_OUT_LOAD = IF_OUT_LOAD;
-	state->CLOCK_OUT = CLOCK_OUT;
-	state->DIV_OUT = DIV_OUT;
-	state->CAPSELECT = CAPSELECT;
-	state->EN_RSSI = EN_RSSI;
-	state->Mod_Type = Mod_Type;
-	state->TF_Type = TF_Type;
-
-	/* Initialize all the controls and registers */
-	InitTunerControls(fe);
-
-	/* Synthesizer LO frequency calculation */
-	MXL_SynthIFLO_Calc(fe);
-
-	return status;
-}
-
-static void MXL_SynthIFLO_Calc(struct dvb_frontend *fe)
-{
-	struct mxl5005s_state *state = fe->tuner_priv;
-	if (state->Mode == 1) /* Digital Mode */
-		state->IF_LO = state->IF_OUT;
-	else /* Analog Mode */ {
-		if (state->IF_Mode == 0) /* Analog Zero IF mode */
-			state->IF_LO = state->IF_OUT + 400000;
-		else /* Analog Low IF mode */
-			state->IF_LO = state->IF_OUT + state->Chan_Bandwidth/2;
-	}
-}
-
-static void MXL_SynthRFTGLO_Calc(struct dvb_frontend *fe)
-{
-	struct mxl5005s_state *state = fe->tuner_priv;
-
-	if (state->Mode == 1) /* Digital Mode */ {
-			/* remove 20.48MHz setting for 2.6.10 */
-			state->RF_LO = state->RF_IN;
-			/* change for 2.6.6 */
-			state->TG_LO = state->RF_IN - 750000;
-	} else /* Analog Mode */ {
-		if (state->IF_Mode == 0) /* Analog Zero IF mode */ {
-			state->RF_LO = state->RF_IN - 400000;
-			state->TG_LO = state->RF_IN - 1750000;
-		} else /* Analog Low IF mode */ {
-			state->RF_LO = state->RF_IN - state->Chan_Bandwidth/2;
-			state->TG_LO = state->RF_IN -
-				state->Chan_Bandwidth + 500000;
-		}
-	}
-}
-
-static u16 MXL_OverwriteICDefault(struct dvb_frontend *fe)
-{
-	u16 status = 0;
-
-	status += MXL_ControlWrite(fe, OVERRIDE_1, 1);
-	status += MXL_ControlWrite(fe, OVERRIDE_2, 1);
-	status += MXL_ControlWrite(fe, OVERRIDE_3, 1);
-	status += MXL_ControlWrite(fe, OVERRIDE_4, 1);
-
-	return status;
-}
-
-static u16 MXL_BlockInit(struct dvb_frontend *fe)
-{
-	struct mxl5005s_state *state = fe->tuner_priv;
-	u16 status = 0;
-
-	status += MXL_OverwriteICDefault(fe);
-
-	/* Downconverter Control Dig Ana */
-	status += MXL_ControlWrite(fe, DN_IQTN_AMP_CUT, state->Mode ? 1 : 0);
-
-	/* Filter Control  Dig  Ana */
-	status += MXL_ControlWrite(fe, BB_MODE, state->Mode ? 0 : 1);
-	status += MXL_ControlWrite(fe, BB_BUF, state->Mode ? 3 : 2);
-	status += MXL_ControlWrite(fe, BB_BUF_OA, state->Mode ? 1 : 0);
-	status += MXL_ControlWrite(fe, BB_IQSWAP, state->Mode ? 0 : 1);
-	status += MXL_ControlWrite(fe, BB_INITSTATE_DLPF_TUNE, 0);
-
-	/* Initialize Low-Pass Filter */
-	if (state->Mode) { /* Digital Mode */
-		switch (state->Chan_Bandwidth) {
-		case 8000000:
-			status += MXL_ControlWrite(fe, BB_DLPF_BANDSEL, 0);
-			break;
-		case 7000000:
-			status += MXL_ControlWrite(fe, BB_DLPF_BANDSEL, 2);
-			break;
-		case 6000000:
-			status += MXL_ControlWrite(fe,
-					BB_DLPF_BANDSEL, 3);
-			break;
-		}
-	} else { /* Analog Mode */
-		switch (state->Chan_Bandwidth) {
-		case 8000000:	/* Low Zero */
-			status += MXL_ControlWrite(fe, BB_ALPF_BANDSELECT,
-					(state->IF_Mode ? 0 : 3));
-			break;
-		case 7000000:
-			status += MXL_ControlWrite(fe, BB_ALPF_BANDSELECT,
-					(state->IF_Mode ? 1 : 4));
-			break;
-		case 6000000:
-			status += MXL_ControlWrite(fe, BB_ALPF_BANDSELECT,
-					(state->IF_Mode ? 2 : 5));
-			break;
-		}
-	}
-
-	/* Charge Pump Control Dig  Ana */
-	status += MXL_ControlWrite(fe, RFSYN_CHP_GAIN, state->Mode ? 5 : 8);
-	status += MXL_ControlWrite(fe,
-		RFSYN_EN_CHP_HIGAIN, state->Mode ? 1 : 1);
-	status += MXL_ControlWrite(fe, EN_CHP_LIN_B, state->Mode ? 0 : 0);
-
-	/* AGC TOP Control */
-	if (state->AGC_Mode == 0) /* Dual AGC */ {
-		status += MXL_ControlWrite(fe, AGC_IF, 15);
-		status += MXL_ControlWrite(fe, AGC_RF, 15);
-	} else /*  Single AGC Mode Dig  Ana */
-		status += MXL_ControlWrite(fe, AGC_RF, state->Mode ? 15 : 12);
-
-	if (state->TOP == 55) /* TOP == 5.5 */
-		status += MXL_ControlWrite(fe, AGC_IF, 0x0);
-
-	if (state->TOP == 72) /* TOP == 7.2 */
-		status += MXL_ControlWrite(fe, AGC_IF, 0x1);
-
-	if (state->TOP == 92) /* TOP == 9.2 */
-		status += MXL_ControlWrite(fe, AGC_IF, 0x2);
-
-	if (state->TOP == 110) /* TOP == 11.0 */
-		status += MXL_ControlWrite(fe, AGC_IF, 0x3);
-
-	if (state->TOP == 129) /* TOP == 12.9 */
-		status += MXL_ControlWrite(fe, AGC_IF, 0x4);
-
-	if (state->TOP == 147) /* TOP == 14.7 */
-		status += MXL_ControlWrite(fe, AGC_IF, 0x5);
-
-	if (state->TOP == 168) /* TOP == 16.8 */
-		status += MXL_ControlWrite(fe, AGC_IF, 0x6);
-
-	if (state->TOP == 194) /* TOP == 19.4 */
-		status += MXL_ControlWrite(fe, AGC_IF, 0x7);
-
-	if (state->TOP == 212) /* TOP == 21.2 */
-		status += MXL_ControlWrite(fe, AGC_IF, 0x9);
-
-	if (state->TOP == 232) /* TOP == 23.2 */
-		status += MXL_ControlWrite(fe, AGC_IF, 0xA);
-
-	if (state->TOP == 252) /* TOP == 25.2 */
-		status += MXL_ControlWrite(fe, AGC_IF, 0xB);
-
-	if (state->TOP == 271) /* TOP == 27.1 */
-		status += MXL_ControlWrite(fe, AGC_IF, 0xC);
-
-	if (state->TOP == 292) /* TOP == 29.2 */
-		status += MXL_ControlWrite(fe, AGC_IF, 0xD);
-
-	if (state->TOP == 317) /* TOP == 31.7 */
-		status += MXL_ControlWrite(fe, AGC_IF, 0xE);
-
-	if (state->TOP == 349) /* TOP == 34.9 */
-		status += MXL_ControlWrite(fe, AGC_IF, 0xF);
-
-	/* IF Synthesizer Control */
-	status += MXL_IFSynthInit(fe);
-
-	/* IF UpConverter Control */
-	if (state->IF_OUT_LOAD == 200) {
-		status += MXL_ControlWrite(fe, DRV_RES_SEL, 6);
-		status += MXL_ControlWrite(fe, I_DRIVER, 2);
-	}
-	if (state->IF_OUT_LOAD == 300) {
-		status += MXL_ControlWrite(fe, DRV_RES_SEL, 4);
-		status += MXL_ControlWrite(fe, I_DRIVER, 1);
-	}
-
-	/* Anti-Alias Filtering Control
-	 * initialise Anti-Aliasing Filter
-	 */
-	if (state->Mode) { /* Digital Mode */
-		if (state->IF_OUT >= 4000000UL && state->IF_OUT <= 6280000UL) {
-			status += MXL_ControlWrite(fe, EN_AAF, 1);
-			status += MXL_ControlWrite(fe, EN_3P, 1);
-			status += MXL_ControlWrite(fe, EN_AUX_3P, 1);
-			status += MXL_ControlWrite(fe, SEL_AAF_BAND, 0);
-		}
-		if ((state->IF_OUT == 36125000UL) ||
-			(state->IF_OUT == 36150000UL)) {
-			status += MXL_ControlWrite(fe, EN_AAF, 1);
-			status += MXL_ControlWrite(fe, EN_3P, 1);
-			status += MXL_ControlWrite(fe, EN_AUX_3P, 1);
-			status += MXL_ControlWrite(fe, SEL_AAF_BAND, 1);
-		}
-		if (state->IF_OUT > 36150000UL) {
-			status += MXL_ControlWrite(fe, EN_AAF, 0);
-			status += MXL_ControlWrite(fe, EN_3P, 1);
-			status += MXL_ControlWrite(fe, EN_AUX_3P, 1);
-			status += MXL_ControlWrite(fe, SEL_AAF_BAND, 1);
-		}
-	} else { /* Analog Mode */
-		if (state->IF_OUT >= 4000000UL && state->IF_OUT <= 5000000UL) {
-			status += MXL_ControlWrite(fe, EN_AAF, 1);
-			status += MXL_ControlWrite(fe, EN_3P, 1);
-			status += MXL_ControlWrite(fe, EN_AUX_3P, 1);
-			status += MXL_ControlWrite(fe, SEL_AAF_BAND, 0);
-		}
-		if (state->IF_OUT > 5000000UL) {
-			status += MXL_ControlWrite(fe, EN_AAF, 0);
-			status += MXL_ControlWrite(fe, EN_3P, 0);
-			status += MXL_ControlWrite(fe, EN_AUX_3P, 0);
-			status += MXL_ControlWrite(fe, SEL_AAF_BAND, 0);
-		}
-	}
-
-	/* Demod Clock Out */
-	if (state->CLOCK_OUT)
-		status += MXL_ControlWrite(fe, SEQ_ENCLK16_CLK_OUT, 1);
-	else
-		status += MXL_ControlWrite(fe, SEQ_ENCLK16_CLK_OUT, 0);
-
-	if (state->DIV_OUT == 1)
-		status += MXL_ControlWrite(fe, SEQ_SEL4_16B, 1);
-	if (state->DIV_OUT == 0)
-		status += MXL_ControlWrite(fe, SEQ_SEL4_16B, 0);
-
-	/* Crystal Control */
-	if (state->CAPSELECT)
-		status += MXL_ControlWrite(fe, XTAL_CAPSELECT, 1);
-	else
-		status += MXL_ControlWrite(fe, XTAL_CAPSELECT, 0);
-
-	if (state->Fxtal >= 12000000UL && state->Fxtal <= 16000000UL)
-		status += MXL_ControlWrite(fe, IF_SEL_DBL, 1);
-	if (state->Fxtal > 16000000UL && state->Fxtal <= 32000000UL)
-		status += MXL_ControlWrite(fe, IF_SEL_DBL, 0);
-
-	if (state->Fxtal >= 12000000UL && state->Fxtal <= 22000000UL)
-		status += MXL_ControlWrite(fe, RFSYN_R_DIV, 3);
-	if (state->Fxtal > 22000000UL && state->Fxtal <= 32000000UL)
-		status += MXL_ControlWrite(fe, RFSYN_R_DIV, 0);
-
-	/* Misc Controls */
-	if (state->Mode == 0 && state->IF_Mode == 1) /* Analog LowIF mode */
-		status += MXL_ControlWrite(fe, SEQ_EXTIQFSMPULSE, 0);
-	else
-		status += MXL_ControlWrite(fe, SEQ_EXTIQFSMPULSE, 1);
-
-	/* status += MXL_ControlRead(fe, IF_DIVVAL, &IF_DIVVAL_Val); */
-
-	/* Set TG_R_DIV */
-	status += MXL_ControlWrite(fe, TG_R_DIV,
-		MXL_Ceiling(state->Fxtal, 1000000));
-
-	/* Apply Default value to BB_INITSTATE_DLPF_TUNE */
-
-	/* RSSI Control */
-	if (state->EN_RSSI) {
-		status += MXL_ControlWrite(fe, SEQ_EXTSYNTHCALIF, 1);
-		status += MXL_ControlWrite(fe, SEQ_EXTDCCAL, 1);
-		status += MXL_ControlWrite(fe, AGC_EN_RSSI, 1);
-		status += MXL_ControlWrite(fe, RFA_ENCLKRFAGC, 1);
-
-		/* RSSI reference point */
-		status += MXL_ControlWrite(fe, RFA_RSSI_REF, 2);
-		status += MXL_ControlWrite(fe, RFA_RSSI_REFH, 3);
-		status += MXL_ControlWrite(fe, RFA_RSSI_REFL, 1);
-
-		/* TOP point */
-		status += MXL_ControlWrite(fe, RFA_FLR, 0);
-		status += MXL_ControlWrite(fe, RFA_CEIL, 12);
-	}
-
-	/* Modulation type bit settings
-	 * Override the control values preset
-	 */
-	if (state->Mod_Type == MXL_DVBT) /* DVB-T Mode */ {
-		state->AGC_Mode = 1; /* Single AGC Mode */
-
-		/* Enable RSSI */
-		status += MXL_ControlWrite(fe, SEQ_EXTSYNTHCALIF, 1);
-		status += MXL_ControlWrite(fe, SEQ_EXTDCCAL, 1);
-		status += MXL_ControlWrite(fe, AGC_EN_RSSI, 1);
-		status += MXL_ControlWrite(fe, RFA_ENCLKRFAGC, 1);
-
-		/* RSSI reference point */
-		status += MXL_ControlWrite(fe, RFA_RSSI_REF, 3);
-		status += MXL_ControlWrite(fe, RFA_RSSI_REFH, 5);
-		status += MXL_ControlWrite(fe, RFA_RSSI_REFL, 1);
-
-		/* TOP point */
-		status += MXL_ControlWrite(fe, RFA_FLR, 2);
-		status += MXL_ControlWrite(fe, RFA_CEIL, 13);
-		if (state->IF_OUT <= 6280000UL)	/* Low IF */
-			status += MXL_ControlWrite(fe, BB_IQSWAP, 0);
-		else /* High IF */
-			status += MXL_ControlWrite(fe, BB_IQSWAP, 1);
-
-	}
-	if (state->Mod_Type == MXL_ATSC) /* ATSC Mode */ {
-		state->AGC_Mode = 1;	/* Single AGC Mode */
-
-		/* Enable RSSI */
-		status += MXL_ControlWrite(fe, SEQ_EXTSYNTHCALIF, 1);
-		status += MXL_ControlWrite(fe, SEQ_EXTDCCAL, 1);
-		status += MXL_ControlWrite(fe, AGC_EN_RSSI, 1);
-		status += MXL_ControlWrite(fe, RFA_ENCLKRFAGC, 1);
-
-		/* RSSI reference point */
-		status += MXL_ControlWrite(fe, RFA_RSSI_REF, 2);
-		status += MXL_ControlWrite(fe, RFA_RSSI_REFH, 4);
-		status += MXL_ControlWrite(fe, RFA_RSSI_REFL, 1);
-
-		/* TOP point */
-		status += MXL_ControlWrite(fe, RFA_FLR, 2);
-		status += MXL_ControlWrite(fe, RFA_CEIL, 13);
-		status += MXL_ControlWrite(fe, BB_INITSTATE_DLPF_TUNE, 1);
-		/* Low Zero */
-		status += MXL_ControlWrite(fe, RFSYN_CHP_GAIN, 5);
-
-		if (state->IF_OUT <= 6280000UL)	/* Low IF */
-			status += MXL_ControlWrite(fe, BB_IQSWAP, 0);
-		else /* High IF */
-			status += MXL_ControlWrite(fe, BB_IQSWAP, 1);
-	}
-	if (state->Mod_Type == MXL_QAM) /* QAM Mode */ {
-		state->Mode = MXL_DIGITAL_MODE;
-
-		/* state->AGC_Mode = 1; */ /* Single AGC Mode */
-
-		/* Disable RSSI */	/* change here for v2.6.5 */
-		status += MXL_ControlWrite(fe, SEQ_EXTSYNTHCALIF, 1);
-		status += MXL_ControlWrite(fe, SEQ_EXTDCCAL, 1);
-		status += MXL_ControlWrite(fe, AGC_EN_RSSI, 0);
-		status += MXL_ControlWrite(fe, RFA_ENCLKRFAGC, 1);
-
-		/* RSSI reference point */
-		status += MXL_ControlWrite(fe, RFA_RSSI_REFH, 5);
-		status += MXL_ControlWrite(fe, RFA_RSSI_REF, 3);
-		status += MXL_ControlWrite(fe, RFA_RSSI_REFL, 2);
-		/* change here for v2.6.5 */
-		status += MXL_ControlWrite(fe, RFSYN_CHP_GAIN, 3);
-
-		if (state->IF_OUT <= 6280000UL)	/* Low IF */
-			status += MXL_ControlWrite(fe, BB_IQSWAP, 0);
-		else /* High IF */
-			status += MXL_ControlWrite(fe, BB_IQSWAP, 1);
-		status += MXL_ControlWrite(fe, RFSYN_CHP_GAIN, 2);
-
-	}
-	if (state->Mod_Type == MXL_ANALOG_CABLE) {
-		/* Analog Cable Mode */
-		/* state->Mode = MXL_DIGITAL_MODE; */
-
-		state->AGC_Mode = 1; /* Single AGC Mode */
-
-		/* Disable RSSI */
-		status += MXL_ControlWrite(fe, SEQ_EXTSYNTHCALIF, 1);
-		status += MXL_ControlWrite(fe, SEQ_EXTDCCAL, 1);
-		status += MXL_ControlWrite(fe, AGC_EN_RSSI, 0);
-		status += MXL_ControlWrite(fe, RFA_ENCLKRFAGC, 1);
-		/* change for 2.6.3 */
-		status += MXL_ControlWrite(fe, AGC_IF, 1);
-		status += MXL_ControlWrite(fe, AGC_RF, 15);
-		status += MXL_ControlWrite(fe, BB_IQSWAP, 1);
-	}
-
-	if (state->Mod_Type == MXL_ANALOG_OTA) {
-		/* Analog OTA Terrestrial mode add for 2.6.7 */
-		/* state->Mode = MXL_ANALOG_MODE; */
-
-		/* Enable RSSI */
-		status += MXL_ControlWrite(fe, SEQ_EXTSYNTHCALIF, 1);
-		status += MXL_ControlWrite(fe, SEQ_EXTDCCAL, 1);
-		status += MXL_ControlWrite(fe, AGC_EN_RSSI, 1);
-		status += MXL_ControlWrite(fe, RFA_ENCLKRFAGC, 1);
-
-		/* RSSI reference point */
-		status += MXL_ControlWrite(fe, RFA_RSSI_REFH, 5);
-		status += MXL_ControlWrite(fe, RFA_RSSI_REF, 3);
-		status += MXL_ControlWrite(fe, RFA_RSSI_REFL, 2);
-		status += MXL_ControlWrite(fe, RFSYN_CHP_GAIN, 3);
-		status += MXL_ControlWrite(fe, BB_IQSWAP, 1);
-	}
-
-	/* RSSI disable */
-	if (state->EN_RSSI == 0) {
-		status += MXL_ControlWrite(fe, SEQ_EXTSYNTHCALIF, 1);
-		status += MXL_ControlWrite(fe, SEQ_EXTDCCAL, 1);
-		status += MXL_ControlWrite(fe, AGC_EN_RSSI, 0);
-		status += MXL_ControlWrite(fe, RFA_ENCLKRFAGC, 1);
-	}
-
-	return status;
-}
-
-static u16 MXL_IFSynthInit(struct dvb_frontend *fe)
-{
-	struct mxl5005s_state *state = fe->tuner_priv;
-	u16 status = 0 ;
-	u32	Fref = 0 ;
-	u32	Kdbl, intModVal ;
-	u32	fracModVal ;
-	Kdbl = 2 ;
-
-	if (state->Fxtal >= 12000000UL && state->Fxtal <= 16000000UL)
-		Kdbl = 2 ;
-	if (state->Fxtal > 16000000UL && state->Fxtal <= 32000000UL)
-		Kdbl = 1 ;
-
-	/* IF Synthesizer Control */
-	if (state->Mode == 0 && state->IF_Mode == 1) /* Analog Low IF mode */ {
-		if (state->IF_LO == 41000000UL) {
-			status += MXL_ControlWrite(fe, IF_DIVVAL,   0x08);
-			status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x0C);
-			Fref = 328000000UL ;
-		}
-		if (state->IF_LO == 47000000UL) {
-			status += MXL_ControlWrite(fe, IF_DIVVAL,   0x08);
-			status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08);
-			Fref = 376000000UL ;
-		}
-		if (state->IF_LO == 54000000UL) {
-			status += MXL_ControlWrite(fe, IF_DIVVAL,   0x10);
-			status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x0C);
-			Fref = 324000000UL ;
-		}
-		if (state->IF_LO == 60000000UL) {
-			status += MXL_ControlWrite(fe, IF_DIVVAL,   0x10);
-			status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08);
-			Fref = 360000000UL ;
-		}
-		if (state->IF_LO == 39250000UL) {
-			status += MXL_ControlWrite(fe, IF_DIVVAL,   0x08);
-			status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x0C);
-			Fref = 314000000UL ;
-		}
-		if (state->IF_LO == 39650000UL) {
-			status += MXL_ControlWrite(fe, IF_DIVVAL,   0x08);
-			status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x0C);
-			Fref = 317200000UL ;
-		}
-		if (state->IF_LO == 40150000UL) {
-			status += MXL_ControlWrite(fe, IF_DIVVAL,   0x08);
-			status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x0C);
-			Fref = 321200000UL ;
-		}
-		if (state->IF_LO == 40650000UL) {
-			status += MXL_ControlWrite(fe, IF_DIVVAL,   0x08);
-			status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x0C);
-			Fref = 325200000UL ;
-		}
-	}
-
-	if (state->Mode || (state->Mode == 0 && state->IF_Mode == 0)) {
-		if (state->IF_LO == 57000000UL) {
-			status += MXL_ControlWrite(fe, IF_DIVVAL,   0x10);
-			status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08);
-			Fref = 342000000UL ;
-		}
-		if (state->IF_LO == 44000000UL) {
-			status += MXL_ControlWrite(fe, IF_DIVVAL,   0x08);
-			status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08);
-			Fref = 352000000UL ;
-		}
-		if (state->IF_LO == 43750000UL) {
-			status += MXL_ControlWrite(fe, IF_DIVVAL,   0x08);
-			status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08);
-			Fref = 350000000UL ;
-		}
-		if (state->IF_LO == 36650000UL) {
-			status += MXL_ControlWrite(fe, IF_DIVVAL,   0x04);
-			status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08);
-			Fref = 366500000UL ;
-		}
-		if (state->IF_LO == 36150000UL) {
-			status += MXL_ControlWrite(fe, IF_DIVVAL,   0x04);
-			status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08);
-			Fref = 361500000UL ;
-		}
-		if (state->IF_LO == 36000000UL) {
-			status += MXL_ControlWrite(fe, IF_DIVVAL,   0x04);
-			status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08);
-			Fref = 360000000UL ;
-		}
-		if (state->IF_LO == 35250000UL) {
-			status += MXL_ControlWrite(fe, IF_DIVVAL,   0x04);
-			status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08);
-			Fref = 352500000UL ;
-		}
-		if (state->IF_LO == 34750000UL) {
-			status += MXL_ControlWrite(fe, IF_DIVVAL,   0x04);
-			status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08);
-			Fref = 347500000UL ;
-		}
-		if (state->IF_LO == 6280000UL) {
-			status += MXL_ControlWrite(fe, IF_DIVVAL,   0x07);
-			status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08);
-			Fref = 376800000UL ;
-		}
-		if (state->IF_LO == 5000000UL) {
-			status += MXL_ControlWrite(fe, IF_DIVVAL,   0x09);
-			status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08);
-			Fref = 360000000UL ;
-		}
-		if (state->IF_LO == 4500000UL) {
-			status += MXL_ControlWrite(fe, IF_DIVVAL,   0x06);
-			status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08);
-			Fref = 360000000UL ;
-		}
-		if (state->IF_LO == 4570000UL) {
-			status += MXL_ControlWrite(fe, IF_DIVVAL,   0x06);
-			status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08);
-			Fref = 365600000UL ;
-		}
-		if (state->IF_LO == 4000000UL) {
-			status += MXL_ControlWrite(fe, IF_DIVVAL,   0x05);
-			status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08);
-			Fref = 360000000UL ;
-		}
-		if (state->IF_LO == 57400000UL) {
-			status += MXL_ControlWrite(fe, IF_DIVVAL,   0x10);
-			status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08);
-			Fref = 344400000UL ;
-		}
-		if (state->IF_LO == 44400000UL) {
-			status += MXL_ControlWrite(fe, IF_DIVVAL,   0x08);
-			status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08);
-			Fref = 355200000UL ;
-		}
-		if (state->IF_LO == 44150000UL) {
-			status += MXL_ControlWrite(fe, IF_DIVVAL,   0x08);
-			status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08);
-			Fref = 353200000UL ;
-		}
-		if (state->IF_LO == 37050000UL) {
-			status += MXL_ControlWrite(fe, IF_DIVVAL,   0x04);
-			status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08);
-			Fref = 370500000UL ;
-		}
-		if (state->IF_LO == 36550000UL) {
-			status += MXL_ControlWrite(fe, IF_DIVVAL,   0x04);
-			status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08);
-			Fref = 365500000UL ;
-		}
-		if (state->IF_LO == 36125000UL) {
-			status += MXL_ControlWrite(fe, IF_DIVVAL,   0x04);
-			status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08);
-			Fref = 361250000UL ;
-		}
-		if (state->IF_LO == 6000000UL) {
-			status += MXL_ControlWrite(fe, IF_DIVVAL,   0x07);
-			status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08);
-			Fref = 360000000UL ;
-		}
-		if (state->IF_LO == 5400000UL) {
-			status += MXL_ControlWrite(fe, IF_DIVVAL,   0x07);
-			status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x0C);
-			Fref = 324000000UL ;
-		}
-		if (state->IF_LO == 5380000UL) {
-			status += MXL_ControlWrite(fe, IF_DIVVAL,   0x07);
-			status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x0C);
-			Fref = 322800000UL ;
-		}
-		if (state->IF_LO == 5200000UL) {
-			status += MXL_ControlWrite(fe, IF_DIVVAL,   0x09);
-			status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08);
-			Fref = 374400000UL ;
-		}
-		if (state->IF_LO == 4900000UL) {
-			status += MXL_ControlWrite(fe, IF_DIVVAL,   0x09);
-			status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08);
-			Fref = 352800000UL ;
-		}
-		if (state->IF_LO == 4400000UL) {
-			status += MXL_ControlWrite(fe, IF_DIVVAL,   0x06);
-			status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08);
-			Fref = 352000000UL ;
-		}
-		if (state->IF_LO == 4063000UL)  /* add for 2.6.8 */ {
-			status += MXL_ControlWrite(fe, IF_DIVVAL,   0x05);
-			status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08);
-			Fref = 365670000UL ;
-		}
-	}
-	/* CHCAL_INT_MOD_IF */
-	/* CHCAL_FRAC_MOD_IF */
-	intModVal = Fref / (state->Fxtal * Kdbl/2);
-	status += MXL_ControlWrite(fe, CHCAL_INT_MOD_IF, intModVal);
-
-	fracModVal = (2<<15)*(Fref/1000 - (state->Fxtal/1000 * Kdbl/2) *
-		intModVal);
-
-	fracModVal = fracModVal / ((state->Fxtal * Kdbl/2)/1000);
-	status += MXL_ControlWrite(fe, CHCAL_FRAC_MOD_IF, fracModVal);
-
-	return status ;
-}
-
-static u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq)
-{
-	struct mxl5005s_state *state = fe->tuner_priv;
-	u16 status = 0;
-	u32 divider_val, E3, E4, E5, E5A;
-	u32 Fmax, Fmin, FmaxBin, FminBin;
-	u32 Kdbl_RF = 2;
-	u32 tg_divval;
-	u32 tg_lo;
-
-	u32 Fref_TG;
-	u32 Fvco;
-
-	state->RF_IN = RF_Freq;
-
-	MXL_SynthRFTGLO_Calc(fe);
-
-	if (state->Fxtal >= 12000000UL && state->Fxtal <= 22000000UL)
-		Kdbl_RF = 2;
-	if (state->Fxtal > 22000000 && state->Fxtal <= 32000000)
-		Kdbl_RF = 1;
-
-	/* Downconverter Controls
-	 * Look-Up Table Implementation for:
-	 *	DN_POLY
-	 *	DN_RFGAIN
-	 *	DN_CAP_RFLPF
-	 *	DN_EN_VHFUHFBAR
-	 *	DN_GAIN_ADJUST
-	 *  Change the boundary reference from RF_IN to RF_LO
-	 */
-	if (state->RF_LO < 40000000UL)
-		return -1;
-
-	if (state->RF_LO >= 40000000UL && state->RF_LO <= 75000000UL) {
-		status += MXL_ControlWrite(fe, DN_POLY,              2);
-		status += MXL_ControlWrite(fe, DN_RFGAIN,            3);
-		status += MXL_ControlWrite(fe, DN_CAP_RFLPF,         423);
-		status += MXL_ControlWrite(fe, DN_EN_VHFUHFBAR,      1);
-		status += MXL_ControlWrite(fe, DN_GAIN_ADJUST,       1);
-	}
-	if (state->RF_LO > 75000000UL && state->RF_LO <= 100000000UL) {
-		status += MXL_ControlWrite(fe, DN_POLY,              3);
-		status += MXL_ControlWrite(fe, DN_RFGAIN,            3);
-		status += MXL_ControlWrite(fe, DN_CAP_RFLPF,         222);
-		status += MXL_ControlWrite(fe, DN_EN_VHFUHFBAR,      1);
-		status += MXL_ControlWrite(fe, DN_GAIN_ADJUST,       1);
-	}
-	if (state->RF_LO > 100000000UL && state->RF_LO <= 150000000UL) {
-		status += MXL_ControlWrite(fe, DN_POLY,              3);
-		status += MXL_ControlWrite(fe, DN_RFGAIN,            3);
-		status += MXL_ControlWrite(fe, DN_CAP_RFLPF,         147);
-		status += MXL_ControlWrite(fe, DN_EN_VHFUHFBAR,      1);
-		status += MXL_ControlWrite(fe, DN_GAIN_ADJUST,       2);
-	}
-	if (state->RF_LO > 150000000UL && state->RF_LO <= 200000000UL) {
-		status += MXL_ControlWrite(fe, DN_POLY,              3);
-		status += MXL_ControlWrite(fe, DN_RFGAIN,            3);
-		status += MXL_ControlWrite(fe, DN_CAP_RFLPF,         9);
-		status += MXL_ControlWrite(fe, DN_EN_VHFUHFBAR,      1);
-		status += MXL_ControlWrite(fe, DN_GAIN_ADJUST,       2);
-	}
-	if (state->RF_LO > 200000000UL && state->RF_LO <= 300000000UL) {
-		status += MXL_ControlWrite(fe, DN_POLY,              3);
-		status += MXL_ControlWrite(fe, DN_RFGAIN,            3);
-		status += MXL_ControlWrite(fe, DN_CAP_RFLPF,         0);
-		status += MXL_ControlWrite(fe, DN_EN_VHFUHFBAR,      1);
-		status += MXL_ControlWrite(fe, DN_GAIN_ADJUST,       3);
-	}
-	if (state->RF_LO > 300000000UL && state->RF_LO <= 650000000UL) {
-		status += MXL_ControlWrite(fe, DN_POLY,              3);
-		status += MXL_ControlWrite(fe, DN_RFGAIN,            1);
-		status += MXL_ControlWrite(fe, DN_CAP_RFLPF,         0);
-		status += MXL_ControlWrite(fe, DN_EN_VHFUHFBAR,      0);
-		status += MXL_ControlWrite(fe, DN_GAIN_ADJUST,       3);
-	}
-	if (state->RF_LO > 650000000UL && state->RF_LO <= 900000000UL) {
-		status += MXL_ControlWrite(fe, DN_POLY,              3);
-		status += MXL_ControlWrite(fe, DN_RFGAIN,            2);
-		status += MXL_ControlWrite(fe, DN_CAP_RFLPF,         0);
-		status += MXL_ControlWrite(fe, DN_EN_VHFUHFBAR,      0);
-		status += MXL_ControlWrite(fe, DN_GAIN_ADJUST,       3);
-	}
-	if (state->RF_LO > 900000000UL)
-		return -1;
-
-	/*	DN_IQTNBUF_AMP */
-	/*	DN_IQTNGNBFBIAS_BST */
-	if (state->RF_LO >= 40000000UL && state->RF_LO <= 75000000UL) {
-		status += MXL_ControlWrite(fe, DN_IQTNBUF_AMP,       1);
-		status += MXL_ControlWrite(fe, DN_IQTNGNBFBIAS_BST,  0);
-	}
-	if (state->RF_LO > 75000000UL && state->RF_LO <= 100000000UL) {
-		status += MXL_ControlWrite(fe, DN_IQTNBUF_AMP,       1);
-		status += MXL_ControlWrite(fe, DN_IQTNGNBFBIAS_BST,  0);
-	}
-	if (state->RF_LO > 100000000UL && state->RF_LO <= 150000000UL) {
-		status += MXL_ControlWrite(fe, DN_IQTNBUF_AMP,       1);
-		status += MXL_ControlWrite(fe, DN_IQTNGNBFBIAS_BST,  0);
-	}
-	if (state->RF_LO > 150000000UL && state->RF_LO <= 200000000UL) {
-		status += MXL_ControlWrite(fe, DN_IQTNBUF_AMP,       1);
-		status += MXL_ControlWrite(fe, DN_IQTNGNBFBIAS_BST,  0);
-	}
-	if (state->RF_LO > 200000000UL && state->RF_LO <= 300000000UL) {
-		status += MXL_ControlWrite(fe, DN_IQTNBUF_AMP,       1);
-		status += MXL_ControlWrite(fe, DN_IQTNGNBFBIAS_BST,  0);
-	}
-	if (state->RF_LO > 300000000UL && state->RF_LO <= 400000000UL) {
-		status += MXL_ControlWrite(fe, DN_IQTNBUF_AMP,       1);
-		status += MXL_ControlWrite(fe, DN_IQTNGNBFBIAS_BST,  0);
-	}
-	if (state->RF_LO > 400000000UL && state->RF_LO <= 450000000UL) {
-		status += MXL_ControlWrite(fe, DN_IQTNBUF_AMP,       1);
-		status += MXL_ControlWrite(fe, DN_IQTNGNBFBIAS_BST,  0);
-	}
-	if (state->RF_LO > 450000000UL && state->RF_LO <= 500000000UL) {
-		status += MXL_ControlWrite(fe, DN_IQTNBUF_AMP,       1);
-		status += MXL_ControlWrite(fe, DN_IQTNGNBFBIAS_BST,  0);
-	}
-	if (state->RF_LO > 500000000UL && state->RF_LO <= 550000000UL) {
-		status += MXL_ControlWrite(fe, DN_IQTNBUF_AMP,       1);
-		status += MXL_ControlWrite(fe, DN_IQTNGNBFBIAS_BST,  0);
-	}
-	if (state->RF_LO > 550000000UL && state->RF_LO <= 600000000UL) {
-		status += MXL_ControlWrite(fe, DN_IQTNBUF_AMP,       1);
-		status += MXL_ControlWrite(fe, DN_IQTNGNBFBIAS_BST,  0);
-	}
-	if (state->RF_LO > 600000000UL && state->RF_LO <= 650000000UL) {
-		status += MXL_ControlWrite(fe, DN_IQTNBUF_AMP,       1);
-		status += MXL_ControlWrite(fe, DN_IQTNGNBFBIAS_BST,  0);
-	}
-	if (state->RF_LO > 650000000UL && state->RF_LO <= 700000000UL) {
-		status += MXL_ControlWrite(fe, DN_IQTNBUF_AMP,       1);
-		status += MXL_ControlWrite(fe, DN_IQTNGNBFBIAS_BST,  0);
-	}
-	if (state->RF_LO > 700000000UL && state->RF_LO <= 750000000UL) {
-		status += MXL_ControlWrite(fe, DN_IQTNBUF_AMP,       1);
-		status += MXL_ControlWrite(fe, DN_IQTNGNBFBIAS_BST,  0);
-	}
-	if (state->RF_LO > 750000000UL && state->RF_LO <= 800000000UL) {
-		status += MXL_ControlWrite(fe, DN_IQTNBUF_AMP,       1);
-		status += MXL_ControlWrite(fe, DN_IQTNGNBFBIAS_BST,  0);
-	}
-	if (state->RF_LO > 800000000UL && state->RF_LO <= 850000000UL) {
-		status += MXL_ControlWrite(fe, DN_IQTNBUF_AMP,       10);
-		status += MXL_ControlWrite(fe, DN_IQTNGNBFBIAS_BST,  1);
-	}
-	if (state->RF_LO > 850000000UL && state->RF_LO <= 900000000UL) {
-		status += MXL_ControlWrite(fe, DN_IQTNBUF_AMP,       10);
-		status += MXL_ControlWrite(fe, DN_IQTNGNBFBIAS_BST,  1);
-	}
-
-	/*
-	 * Set RF Synth and LO Path Control
-	 *
-	 * Look-Up table implementation for:
-	 *	RFSYN_EN_OUTMUX
-	 *	RFSYN_SEL_VCO_OUT
-	 *	RFSYN_SEL_VCO_HI
-	 *  RFSYN_SEL_DIVM
-	 *	RFSYN_RF_DIV_BIAS
-	 *	DN_SEL_FREQ
-	 *
-	 * Set divider_val, Fmax, Fmix to use in Equations
-	 */
-	FminBin = 28000000UL ;
-	FmaxBin = 42500000UL ;
-	if (state->RF_LO >= 40000000UL && state->RF_LO <= FmaxBin) {
-		status += MXL_ControlWrite(fe, RFSYN_EN_OUTMUX,     1);
-		status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_OUT,   0);
-		status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI,    0);
-		status += MXL_ControlWrite(fe, RFSYN_SEL_DIVM,      0);
-		status += MXL_ControlWrite(fe, RFSYN_RF_DIV_BIAS,   1);
-		status += MXL_ControlWrite(fe, DN_SEL_FREQ,         1);
-		divider_val = 64 ;
-		Fmax = FmaxBin ;
-		Fmin = FminBin ;
-	}
-	FminBin = 42500000UL ;
-	FmaxBin = 56000000UL ;
-	if (state->RF_LO > FminBin && state->RF_LO <= FmaxBin) {
-		status += MXL_ControlWrite(fe, RFSYN_EN_OUTMUX,     1);
-		status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_OUT,   0);
-		status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI,    1);
-		status += MXL_ControlWrite(fe, RFSYN_SEL_DIVM,      0);
-		status += MXL_ControlWrite(fe, RFSYN_RF_DIV_BIAS,   1);
-		status += MXL_ControlWrite(fe, DN_SEL_FREQ,         1);
-		divider_val = 64 ;
-		Fmax = FmaxBin ;
-		Fmin = FminBin ;
-	}
-	FminBin = 56000000UL ;
-	FmaxBin = 85000000UL ;
-	if (state->RF_LO > FminBin && state->RF_LO <= FmaxBin) {
-		status += MXL_ControlWrite(fe, RFSYN_EN_OUTMUX,     0);
-		status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_OUT,   1);
-		status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI,    0);
-		status += MXL_ControlWrite(fe, RFSYN_SEL_DIVM,      0);
-		status += MXL_ControlWrite(fe, RFSYN_RF_DIV_BIAS,   1);
-		status += MXL_ControlWrite(fe, DN_SEL_FREQ,         1);
-		divider_val = 32 ;
-		Fmax = FmaxBin ;
-		Fmin = FminBin ;
-	}
-	FminBin = 85000000UL ;
-	FmaxBin = 112000000UL ;
-	if (state->RF_LO > FminBin && state->RF_LO <= FmaxBin) {
-		status += MXL_ControlWrite(fe, RFSYN_EN_OUTMUX,     0);
-		status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_OUT,   1);
-		status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI,    1);
-		status += MXL_ControlWrite(fe, RFSYN_SEL_DIVM,      0);
-		status += MXL_ControlWrite(fe, RFSYN_RF_DIV_BIAS,   1);
-		status += MXL_ControlWrite(fe, DN_SEL_FREQ,         1);
-		divider_val = 32 ;
-		Fmax = FmaxBin ;
-		Fmin = FminBin ;
-	}
-	FminBin = 112000000UL ;
-	FmaxBin = 170000000UL ;
-	if (state->RF_LO > FminBin && state->RF_LO <= FmaxBin) {
-		status += MXL_ControlWrite(fe, RFSYN_EN_OUTMUX,     0);
-		status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_OUT,   1);
-		status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI,    0);
-		status += MXL_ControlWrite(fe, RFSYN_SEL_DIVM,      0);
-		status += MXL_ControlWrite(fe, RFSYN_RF_DIV_BIAS,   1);
-		status += MXL_ControlWrite(fe, DN_SEL_FREQ,         2);
-		divider_val = 16 ;
-		Fmax = FmaxBin ;
-		Fmin = FminBin ;
-	}
-	FminBin = 170000000UL ;
-	FmaxBin = 225000000UL ;
-	if (state->RF_LO > FminBin && state->RF_LO <= FmaxBin) {
-		status += MXL_ControlWrite(fe, RFSYN_EN_OUTMUX,     0);
-		status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_OUT,   1);
-		status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI,    1);
-		status += MXL_ControlWrite(fe, RFSYN_SEL_DIVM,      0);
-		status += MXL_ControlWrite(fe, RFSYN_RF_DIV_BIAS,   1);
-		status += MXL_ControlWrite(fe, DN_SEL_FREQ,         2);
-		divider_val = 16 ;
-		Fmax = FmaxBin ;
-		Fmin = FminBin ;
-	}
-	FminBin = 225000000UL ;
-	FmaxBin = 300000000UL ;
-	if (state->RF_LO > FminBin && state->RF_LO <= FmaxBin) {
-		status += MXL_ControlWrite(fe, RFSYN_EN_OUTMUX,     0);
-		status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_OUT,   1);
-		status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI,    0);
-		status += MXL_ControlWrite(fe, RFSYN_SEL_DIVM,      0);
-		status += MXL_ControlWrite(fe, RFSYN_RF_DIV_BIAS,   1);
-		status += MXL_ControlWrite(fe, DN_SEL_FREQ,         4);
-		divider_val = 8 ;
-		Fmax = 340000000UL ;
-		Fmin = FminBin ;
-	}
-	FminBin = 300000000UL ;
-	FmaxBin = 340000000UL ;
-	if (state->RF_LO > FminBin && state->RF_LO <= FmaxBin) {
-		status += MXL_ControlWrite(fe, RFSYN_EN_OUTMUX,     1);
-		status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_OUT,   0);
-		status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI,    0);
-		status += MXL_ControlWrite(fe, RFSYN_SEL_DIVM,      0);
-		status += MXL_ControlWrite(fe, RFSYN_RF_DIV_BIAS,   1);
-		status += MXL_ControlWrite(fe, DN_SEL_FREQ,         0);
-		divider_val = 8 ;
-		Fmax = FmaxBin ;
-		Fmin = 225000000UL ;
-	}
-	FminBin = 340000000UL ;
-	FmaxBin = 450000000UL ;
-	if (state->RF_LO > FminBin && state->RF_LO <= FmaxBin) {
-		status += MXL_ControlWrite(fe, RFSYN_EN_OUTMUX,     1);
-		status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_OUT,   0);
-		status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI,    1);
-		status += MXL_ControlWrite(fe, RFSYN_SEL_DIVM,      0);
-		status += MXL_ControlWrite(fe, RFSYN_RF_DIV_BIAS,   2);
-		status += MXL_ControlWrite(fe, DN_SEL_FREQ,         0);
-		divider_val = 8 ;
-		Fmax = FmaxBin ;
-		Fmin = FminBin ;
-	}
-	FminBin = 450000000UL ;
-	FmaxBin = 680000000UL ;
-	if (state->RF_LO > FminBin && state->RF_LO <= FmaxBin) {
-		status += MXL_ControlWrite(fe, RFSYN_EN_OUTMUX,     0);
-		status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_OUT,   1);
-		status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI,    0);
-		status += MXL_ControlWrite(fe, RFSYN_SEL_DIVM,      1);
-		status += MXL_ControlWrite(fe, RFSYN_RF_DIV_BIAS,   1);
-		status += MXL_ControlWrite(fe, DN_SEL_FREQ,         0);
-		divider_val = 4 ;
-		Fmax = FmaxBin ;
-		Fmin = FminBin ;
-	}
-	FminBin = 680000000UL ;
-	FmaxBin = 900000000UL ;
-	if (state->RF_LO > FminBin && state->RF_LO <= FmaxBin) {
-		status += MXL_ControlWrite(fe, RFSYN_EN_OUTMUX,     0);
-		status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_OUT,   1);
-		status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI,    1);
-		status += MXL_ControlWrite(fe, RFSYN_SEL_DIVM,      1);
-		status += MXL_ControlWrite(fe, RFSYN_RF_DIV_BIAS,   1);
-		status += MXL_ControlWrite(fe, DN_SEL_FREQ,         0);
-		divider_val = 4 ;
-		Fmax = FmaxBin ;
-		Fmin = FminBin ;
-	}
-
-	/*	CHCAL_INT_MOD_RF
-	 *	CHCAL_FRAC_MOD_RF
-	 *	RFSYN_LPF_R
-	 *	CHCAL_EN_INT_RF
-	 */
-	/* Equation E3 RFSYN_VCO_BIAS */
-	E3 = (((Fmax-state->RF_LO)/1000)*32)/((Fmax-Fmin)/1000) + 8 ;
-	status += MXL_ControlWrite(fe, RFSYN_VCO_BIAS, E3);
-
-	/* Equation E4 CHCAL_INT_MOD_RF */
-	E4 = (state->RF_LO*divider_val/1000)/(2*state->Fxtal*Kdbl_RF/1000);
-	MXL_ControlWrite(fe, CHCAL_INT_MOD_RF, E4);
-
-	/* Equation E5 CHCAL_FRAC_MOD_RF CHCAL_EN_INT_RF */
-	E5 = ((2<<17)*(state->RF_LO/10000*divider_val -
-		(E4*(2*state->Fxtal*Kdbl_RF)/10000))) /
-		(2*state->Fxtal*Kdbl_RF/10000);
-
-	status += MXL_ControlWrite(fe, CHCAL_FRAC_MOD_RF, E5);
-
-	/* Equation E5A RFSYN_LPF_R */
-	E5A = (((Fmax - state->RF_LO)/1000)*4/((Fmax-Fmin)/1000)) + 1 ;
-	status += MXL_ControlWrite(fe, RFSYN_LPF_R, E5A);
-
-	/* Euqation E5B CHCAL_EN_INIT_RF */
-	status += MXL_ControlWrite(fe, CHCAL_EN_INT_RF, ((E5 == 0) ? 1 : 0));
-	/*if (E5 == 0)
-	 *	status += MXL_ControlWrite(fe, CHCAL_EN_INT_RF, 1);
-	 *else
-	 *	status += MXL_ControlWrite(fe, CHCAL_FRAC_MOD_RF, E5);
-	 */
-
-	/*
-	 * Set TG Synth
-	 *
-	 * Look-Up table implementation for:
-	 *	TG_LO_DIVVAL
-	 *	TG_LO_SELVAL
-	 *
-	 * Set divider_val, Fmax, Fmix to use in Equations
-	 */
-	if (state->TG_LO < 33000000UL)
-		return -1;
-
-	FminBin = 33000000UL ;
-	FmaxBin = 50000000UL ;
-	if (state->TG_LO >= FminBin && state->TG_LO <= FmaxBin) {
-		status += MXL_ControlWrite(fe, TG_LO_DIVVAL,	0x6);
-		status += MXL_ControlWrite(fe, TG_LO_SELVAL,	0x0);
-		divider_val = 36 ;
-		Fmax = FmaxBin ;
-		Fmin = FminBin ;
-	}
-	FminBin = 50000000UL ;
-	FmaxBin = 67000000UL ;
-	if (state->TG_LO > FminBin && state->TG_LO <= FmaxBin) {
-		status += MXL_ControlWrite(fe, TG_LO_DIVVAL,	0x1);
-		status += MXL_ControlWrite(fe, TG_LO_SELVAL,	0x0);
-		divider_val = 24 ;
-		Fmax = FmaxBin ;
-		Fmin = FminBin ;
-	}
-	FminBin = 67000000UL ;
-	FmaxBin = 100000000UL ;
-	if (state->TG_LO > FminBin && state->TG_LO <= FmaxBin) {
-		status += MXL_ControlWrite(fe, TG_LO_DIVVAL,	0xC);
-		status += MXL_ControlWrite(fe, TG_LO_SELVAL,	0x2);
-		divider_val = 18 ;
-		Fmax = FmaxBin ;
-		Fmin = FminBin ;
-	}
-	FminBin = 100000000UL ;
-	FmaxBin = 150000000UL ;
-	if (state->TG_LO > FminBin && state->TG_LO <= FmaxBin) {
-		status += MXL_ControlWrite(fe, TG_LO_DIVVAL,	0x8);
-		status += MXL_ControlWrite(fe, TG_LO_SELVAL,	0x2);
-		divider_val = 12 ;
-		Fmax = FmaxBin ;
-		Fmin = FminBin ;
-	}
-	FminBin = 150000000UL ;
-	FmaxBin = 200000000UL ;
-	if (state->TG_LO > FminBin && state->TG_LO <= FmaxBin) {
-		status += MXL_ControlWrite(fe, TG_LO_DIVVAL,	0x0);
-		status += MXL_ControlWrite(fe, TG_LO_SELVAL,	0x2);
-		divider_val = 8 ;
-		Fmax = FmaxBin ;
-		Fmin = FminBin ;
-	}
-	FminBin = 200000000UL ;
-	FmaxBin = 300000000UL ;
-	if (state->TG_LO > FminBin && state->TG_LO <= FmaxBin) {
-		status += MXL_ControlWrite(fe, TG_LO_DIVVAL,	0x8);
-		status += MXL_ControlWrite(fe, TG_LO_SELVAL,	0x3);
-		divider_val = 6 ;
-		Fmax = FmaxBin ;
-		Fmin = FminBin ;
-	}
-	FminBin = 300000000UL ;
-	FmaxBin = 400000000UL ;
-	if (state->TG_LO > FminBin && state->TG_LO <= FmaxBin) {
-		status += MXL_ControlWrite(fe, TG_LO_DIVVAL,	0x0);
-		status += MXL_ControlWrite(fe, TG_LO_SELVAL,	0x3);
-		divider_val = 4 ;
-		Fmax = FmaxBin ;
-		Fmin = FminBin ;
-	}
-	FminBin = 400000000UL ;
-	FmaxBin = 600000000UL ;
-	if (state->TG_LO > FminBin && state->TG_LO <= FmaxBin) {
-		status += MXL_ControlWrite(fe, TG_LO_DIVVAL,	0x8);
-		status += MXL_ControlWrite(fe, TG_LO_SELVAL,	0x7);
-		divider_val = 3 ;
-		Fmax = FmaxBin ;
-		Fmin = FminBin ;
-	}
-	FminBin = 600000000UL ;
-	FmaxBin = 900000000UL ;
-	if (state->TG_LO > FminBin && state->TG_LO <= FmaxBin) {
-		status += MXL_ControlWrite(fe, TG_LO_DIVVAL,	0x0);
-		status += MXL_ControlWrite(fe, TG_LO_SELVAL,	0x7);
-		divider_val = 2 ;
-		Fmax = FmaxBin ;
-		Fmin = FminBin ;
-	}
-
-	/* TG_DIV_VAL */
-	tg_divval = (state->TG_LO*divider_val/100000) *
-		(MXL_Ceiling(state->Fxtal, 1000000) * 100) /
-		(state->Fxtal/1000);
-
-	status += MXL_ControlWrite(fe, TG_DIV_VAL, tg_divval);
-
-	if (state->TG_LO > 600000000UL)
-		status += MXL_ControlWrite(fe, TG_DIV_VAL, tg_divval + 1);
-
-	Fmax = 1800000000UL ;
-	Fmin = 1200000000UL ;
-
-	/* prevent overflow of 32 bit unsigned integer, use
-	 * following equation. Edit for v2.6.4
-	 */
-	/* Fref_TF = Fref_TG * 1000 */
-	Fref_TG = (state->Fxtal/1000) / MXL_Ceiling(state->Fxtal, 1000000);
-
-	/* Fvco = Fvco/10 */
-	Fvco = (state->TG_LO/10000) * divider_val * Fref_TG;
-
-	tg_lo = (((Fmax/10 - Fvco)/100)*32) / ((Fmax-Fmin)/1000)+8;
-
-	/* below equation is same as above but much harder to debug.
-	 *
-	 * static u32 MXL_GetXtalInt(u32 Xtal_Freq)
-	 * {
-	 *	if ((Xtal_Freq % 1000000) == 0)
-	 *		return (Xtal_Freq / 10000);
-	 *	else
-	 *		return (((Xtal_Freq / 1000000) + 1)*100);
-	 * }
-	 *
-	 * u32 Xtal_Int = MXL_GetXtalInt(state->Fxtal);
-	 * tg_lo = ( ((Fmax/10000 * Xtal_Int)/100) -
-	 * ((state->TG_LO/10000)*divider_val *
-	 * (state->Fxtal/10000)/100) )*32/((Fmax-Fmin)/10000 *
-	 * Xtal_Int/100) + 8;
-	 */
-
-	status += MXL_ControlWrite(fe, TG_VCO_BIAS , tg_lo);
-
-	/* add for 2.6.5 Special setting for QAM */
-	if (state->Mod_Type == MXL_QAM) {
-		if (state->config->qam_gain != 0)
-			status += MXL_ControlWrite(fe, RFSYN_CHP_GAIN,
-						   state->config->qam_gain);
-		else if (state->RF_IN < 680000000)
-			status += MXL_ControlWrite(fe, RFSYN_CHP_GAIN, 3);
-		else
-			status += MXL_ControlWrite(fe, RFSYN_CHP_GAIN, 2);
-	}
-
-	/* Off Chip Tracking Filter Control */
-	if (state->TF_Type == MXL_TF_OFF) {
-		/* Tracking Filter Off State; turn off all the banks */
-		status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0);
-		status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0);
-		status += MXL_SetGPIO(fe, 3, 1); /* Bank1 Off */
-		status += MXL_SetGPIO(fe, 1, 1); /* Bank2 Off */
-		status += MXL_SetGPIO(fe, 4, 1); /* Bank3 Off */
-	}
-
-	if (state->TF_Type == MXL_TF_C) /* Tracking Filter type C */ {
-		status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1);
-		status += MXL_ControlWrite(fe, DAC_DIN_A, 0);
-
-		if (state->RF_IN >= 43000000 && state->RF_IN < 150000000) {
-			status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0);
-			status += MXL_ControlWrite(fe, DAC_DIN_B, 0);
-			status += MXL_SetGPIO(fe, 3, 0);
-			status += MXL_SetGPIO(fe, 1, 1);
-			status += MXL_SetGPIO(fe, 4, 1);
-		}
-		if (state->RF_IN >= 150000000 && state->RF_IN < 280000000) {
-			status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0);
-			status += MXL_ControlWrite(fe, DAC_DIN_B, 0);
-			status += MXL_SetGPIO(fe, 3, 1);
-			status += MXL_SetGPIO(fe, 1, 0);
-			status += MXL_SetGPIO(fe, 4, 1);
-		}
-		if (state->RF_IN >= 280000000 && state->RF_IN < 360000000) {
-			status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0);
-			status += MXL_ControlWrite(fe, DAC_DIN_B, 0);
-			status += MXL_SetGPIO(fe, 3, 1);
-			status += MXL_SetGPIO(fe, 1, 0);
-			status += MXL_SetGPIO(fe, 4, 0);
-		}
-		if (state->RF_IN >= 360000000 && state->RF_IN < 560000000) {
-			status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0);
-			status += MXL_ControlWrite(fe, DAC_DIN_B, 0);
-			status += MXL_SetGPIO(fe, 3, 1);
-			status += MXL_SetGPIO(fe, 1, 1);
-			status += MXL_SetGPIO(fe, 4, 0);
-		}
-		if (state->RF_IN >= 560000000 && state->RF_IN < 580000000) {
-			status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1);
-			status += MXL_ControlWrite(fe, DAC_DIN_B, 29);
-			status += MXL_SetGPIO(fe, 3, 1);
-			status += MXL_SetGPIO(fe, 1, 1);
-			status += MXL_SetGPIO(fe, 4, 0);
-		}
-		if (state->RF_IN >= 580000000 && state->RF_IN < 630000000) {
-			status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1);
-			status += MXL_ControlWrite(fe, DAC_DIN_B, 0);
-			status += MXL_SetGPIO(fe, 3, 1);
-			status += MXL_SetGPIO(fe, 1, 1);
-			status += MXL_SetGPIO(fe, 4, 0);
-		}
-		if (state->RF_IN >= 630000000 && state->RF_IN < 700000000) {
-			status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1);
-			status += MXL_ControlWrite(fe, DAC_DIN_B, 16);
-			status += MXL_SetGPIO(fe, 3, 1);
-			status += MXL_SetGPIO(fe, 1, 1);
-			status += MXL_SetGPIO(fe, 4, 1);
-		}
-		if (state->RF_IN >= 700000000 && state->RF_IN < 760000000) {
-			status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1);
-			status += MXL_ControlWrite(fe, DAC_DIN_B, 7);
-			status += MXL_SetGPIO(fe, 3, 1);
-			status += MXL_SetGPIO(fe, 1, 1);
-			status += MXL_SetGPIO(fe, 4, 1);
-		}
-		if (state->RF_IN >= 760000000 && state->RF_IN <= 900000000) {
-			status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1);
-			status += MXL_ControlWrite(fe, DAC_DIN_B, 0);
-			status += MXL_SetGPIO(fe, 3, 1);
-			status += MXL_SetGPIO(fe, 1, 1);
-			status += MXL_SetGPIO(fe, 4, 1);
-		}
-	}
-
-	if (state->TF_Type == MXL_TF_C_H) {
-
-		/* Tracking Filter type C-H for Hauppauge only */
-		status += MXL_ControlWrite(fe, DAC_DIN_A, 0);
-
-		if (state->RF_IN >= 43000000 && state->RF_IN < 150000000) {
-			status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0);
-			status += MXL_SetGPIO(fe, 4, 0);
-			status += MXL_SetGPIO(fe, 3, 1);
-			status += MXL_SetGPIO(fe, 1, 1);
-		}
-		if (state->RF_IN >= 150000000 && state->RF_IN < 280000000) {
-			status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0);
-			status += MXL_SetGPIO(fe, 4, 1);
-			status += MXL_SetGPIO(fe, 3, 0);
-			status += MXL_SetGPIO(fe, 1, 1);
-		}
-		if (state->RF_IN >= 280000000 && state->RF_IN < 360000000) {
-			status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0);
-			status += MXL_SetGPIO(fe, 4, 1);
-			status += MXL_SetGPIO(fe, 3, 0);
-			status += MXL_SetGPIO(fe, 1, 0);
-		}
-		if (state->RF_IN >= 360000000 && state->RF_IN < 560000000) {
-			status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0);
-			status += MXL_SetGPIO(fe, 4, 1);
-			status += MXL_SetGPIO(fe, 3, 1);
-			status += MXL_SetGPIO(fe, 1, 0);
-		}
-		if (state->RF_IN >= 560000000 && state->RF_IN < 580000000) {
-			status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1);
-			status += MXL_SetGPIO(fe, 4, 1);
-			status += MXL_SetGPIO(fe, 3, 1);
-			status += MXL_SetGPIO(fe, 1, 0);
-		}
-		if (state->RF_IN >= 580000000 && state->RF_IN < 630000000) {
-			status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1);
-			status += MXL_SetGPIO(fe, 4, 1);
-			status += MXL_SetGPIO(fe, 3, 1);
-			status += MXL_SetGPIO(fe, 1, 0);
-		}
-		if (state->RF_IN >= 630000000 && state->RF_IN < 700000000) {
-			status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1);
-			status += MXL_SetGPIO(fe, 4, 1);
-			status += MXL_SetGPIO(fe, 3, 1);
-			status += MXL_SetGPIO(fe, 1, 1);
-		}
-		if (state->RF_IN >= 700000000 && state->RF_IN < 760000000) {
-			status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1);
-			status += MXL_SetGPIO(fe, 4, 1);
-			status += MXL_SetGPIO(fe, 3, 1);
-			status += MXL_SetGPIO(fe, 1, 1);
-		}
-		if (state->RF_IN >= 760000000 && state->RF_IN <= 900000000) {
-			status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1);
-			status += MXL_SetGPIO(fe, 4, 1);
-			status += MXL_SetGPIO(fe, 3, 1);
-			status += MXL_SetGPIO(fe, 1, 1);
-		}
-	}
-
-	if (state->TF_Type == MXL_TF_D) { /* Tracking Filter type D */
-
-		status += MXL_ControlWrite(fe, DAC_DIN_B, 0);
-
-		if (state->RF_IN >= 43000000 && state->RF_IN < 174000000) {
-			status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0);
-			status += MXL_SetGPIO(fe, 4, 0);
-			status += MXL_SetGPIO(fe, 1, 1);
-			status += MXL_SetGPIO(fe, 3, 1);
-		}
-		if (state->RF_IN >= 174000000 && state->RF_IN < 250000000) {
-			status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0);
-			status += MXL_SetGPIO(fe, 4, 0);
-			status += MXL_SetGPIO(fe, 1, 0);
-			status += MXL_SetGPIO(fe, 3, 1);
-		}
-		if (state->RF_IN >= 250000000 && state->RF_IN < 310000000) {
-			status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0);
-			status += MXL_SetGPIO(fe, 4, 1);
-			status += MXL_SetGPIO(fe, 1, 0);
-			status += MXL_SetGPIO(fe, 3, 1);
-		}
-		if (state->RF_IN >= 310000000 && state->RF_IN < 360000000) {
-			status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0);
-			status += MXL_SetGPIO(fe, 4, 1);
-			status += MXL_SetGPIO(fe, 1, 0);
-			status += MXL_SetGPIO(fe, 3, 0);
-		}
-		if (state->RF_IN >= 360000000 && state->RF_IN < 470000000) {
-			status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0);
-			status += MXL_SetGPIO(fe, 4, 1);
-			status += MXL_SetGPIO(fe, 1, 1);
-			status += MXL_SetGPIO(fe, 3, 0);
-		}
-		if (state->RF_IN >= 470000000 && state->RF_IN < 640000000) {
-			status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1);
-			status += MXL_SetGPIO(fe, 4, 1);
-			status += MXL_SetGPIO(fe, 1, 1);
-			status += MXL_SetGPIO(fe, 3, 0);
-		}
-		if (state->RF_IN >= 640000000 && state->RF_IN <= 900000000) {
-			status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1);
-			status += MXL_SetGPIO(fe, 4, 1);
-			status += MXL_SetGPIO(fe, 1, 1);
-			status += MXL_SetGPIO(fe, 3, 1);
-		}
-	}
-
-	if (state->TF_Type == MXL_TF_D_L) {
-
-		/* Tracking Filter type D-L for Lumanate ONLY change 2.6.3 */
-		status += MXL_ControlWrite(fe, DAC_DIN_A, 0);
-
-		/* if UHF and terrestrial => Turn off Tracking Filter */
-		if (state->RF_IN >= 471000000 &&
-			(state->RF_IN - 471000000)%6000000 != 0) {
-			/* Turn off all the banks */
-			status += MXL_SetGPIO(fe, 3, 1);
-			status += MXL_SetGPIO(fe, 1, 1);
-			status += MXL_SetGPIO(fe, 4, 1);
-			status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0);
-			status += MXL_ControlWrite(fe, AGC_IF, 10);
-		} else {
-			/* if VHF or cable => Turn on Tracking Filter */
-			if (state->RF_IN >= 43000000 &&
-				state->RF_IN < 140000000) {
-
-				status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0);
-				status += MXL_SetGPIO(fe, 4, 1);
-				status += MXL_SetGPIO(fe, 1, 1);
-				status += MXL_SetGPIO(fe, 3, 0);
-			}
-			if (state->RF_IN >= 140000000 &&
-				state->RF_IN < 240000000) {
-				status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0);
-				status += MXL_SetGPIO(fe, 4, 1);
-				status += MXL_SetGPIO(fe, 1, 0);
-				status += MXL_SetGPIO(fe, 3, 0);
-			}
-			if (state->RF_IN >= 240000000 &&
-				state->RF_IN < 340000000) {
-				status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0);
-				status += MXL_SetGPIO(fe, 4, 0);
-				status += MXL_SetGPIO(fe, 1, 1);
-				status += MXL_SetGPIO(fe, 3, 0);
-			}
-			if (state->RF_IN >= 340000000 &&
-				state->RF_IN < 430000000) {
-				status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0);
-				status += MXL_SetGPIO(fe, 4, 0);
-				status += MXL_SetGPIO(fe, 1, 0);
-				status += MXL_SetGPIO(fe, 3, 1);
-			}
-			if (state->RF_IN >= 430000000 &&
-				state->RF_IN < 470000000) {
-				status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1);
-				status += MXL_SetGPIO(fe, 4, 1);
-				status += MXL_SetGPIO(fe, 1, 0);
-				status += MXL_SetGPIO(fe, 3, 1);
-			}
-			if (state->RF_IN >= 470000000 &&
-				state->RF_IN < 570000000) {
-				status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1);
-				status += MXL_SetGPIO(fe, 4, 0);
-				status += MXL_SetGPIO(fe, 1, 0);
-				status += MXL_SetGPIO(fe, 3, 1);
-			}
-			if (state->RF_IN >= 570000000 &&
-				state->RF_IN < 620000000) {
-				status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0);
-				status += MXL_SetGPIO(fe, 4, 0);
-				status += MXL_SetGPIO(fe, 1, 1);
-				status += MXL_SetGPIO(fe, 3, 1);
-			}
-			if (state->RF_IN >= 620000000 &&
-				state->RF_IN < 760000000) {
-				status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1);
-				status += MXL_SetGPIO(fe, 4, 0);
-				status += MXL_SetGPIO(fe, 1, 1);
-				status += MXL_SetGPIO(fe, 3, 1);
-			}
-			if (state->RF_IN >= 760000000 &&
-				state->RF_IN <= 900000000) {
-				status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1);
-				status += MXL_SetGPIO(fe, 4, 1);
-				status += MXL_SetGPIO(fe, 1, 1);
-				status += MXL_SetGPIO(fe, 3, 1);
-			}
-		}
-	}
-
-	if (state->TF_Type == MXL_TF_E) /* Tracking Filter type E */ {
-
-		status += MXL_ControlWrite(fe, DAC_DIN_B, 0);
-
-		if (state->RF_IN >= 43000000 && state->RF_IN < 174000000) {
-			status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0);
-			status += MXL_SetGPIO(fe, 4, 0);
-			status += MXL_SetGPIO(fe, 1, 1);
-			status += MXL_SetGPIO(fe, 3, 1);
-		}
-		if (state->RF_IN >= 174000000 && state->RF_IN < 250000000) {
-			status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0);
-			status += MXL_SetGPIO(fe, 4, 0);
-			status += MXL_SetGPIO(fe, 1, 0);
-			status += MXL_SetGPIO(fe, 3, 1);
-		}
-		if (state->RF_IN >= 250000000 && state->RF_IN < 310000000) {
-			status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0);
-			status += MXL_SetGPIO(fe, 4, 1);
-			status += MXL_SetGPIO(fe, 1, 0);
-			status += MXL_SetGPIO(fe, 3, 1);
-		}
-		if (state->RF_IN >= 310000000 && state->RF_IN < 360000000) {
-			status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0);
-			status += MXL_SetGPIO(fe, 4, 1);
-			status += MXL_SetGPIO(fe, 1, 0);
-			status += MXL_SetGPIO(fe, 3, 0);
-		}
-		if (state->RF_IN >= 360000000 && state->RF_IN < 470000000) {
-			status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0);
-			status += MXL_SetGPIO(fe, 4, 1);
-			status += MXL_SetGPIO(fe, 1, 1);
-			status += MXL_SetGPIO(fe, 3, 0);
-		}
-		if (state->RF_IN >= 470000000 && state->RF_IN < 640000000) {
-			status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1);
-			status += MXL_SetGPIO(fe, 4, 1);
-			status += MXL_SetGPIO(fe, 1, 1);
-			status += MXL_SetGPIO(fe, 3, 0);
-		}
-		if (state->RF_IN >= 640000000 && state->RF_IN <= 900000000) {
-			status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1);
-			status += MXL_SetGPIO(fe, 4, 1);
-			status += MXL_SetGPIO(fe, 1, 1);
-			status += MXL_SetGPIO(fe, 3, 1);
-		}
-	}
-
-	if (state->TF_Type == MXL_TF_F) {
-
-		/* Tracking Filter type F */
-		status += MXL_ControlWrite(fe, DAC_DIN_B, 0);
-
-		if (state->RF_IN >= 43000000 && state->RF_IN < 160000000) {
-			status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0);
-			status += MXL_SetGPIO(fe, 4, 0);
-			status += MXL_SetGPIO(fe, 1, 1);
-			status += MXL_SetGPIO(fe, 3, 1);
-		}
-		if (state->RF_IN >= 160000000 && state->RF_IN < 210000000) {
-			status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0);
-			status += MXL_SetGPIO(fe, 4, 0);
-			status += MXL_SetGPIO(fe, 1, 0);
-			status += MXL_SetGPIO(fe, 3, 1);
-		}
-		if (state->RF_IN >= 210000000 && state->RF_IN < 300000000) {
-			status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0);
-			status += MXL_SetGPIO(fe, 4, 1);
-			status += MXL_SetGPIO(fe, 1, 0);
-			status += MXL_SetGPIO(fe, 3, 1);
-		}
-		if (state->RF_IN >= 300000000 && state->RF_IN < 390000000) {
-			status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0);
-			status += MXL_SetGPIO(fe, 4, 1);
-			status += MXL_SetGPIO(fe, 1, 0);
-			status += MXL_SetGPIO(fe, 3, 0);
-		}
-		if (state->RF_IN >= 390000000 && state->RF_IN < 515000000) {
-			status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0);
-			status += MXL_SetGPIO(fe, 4, 1);
-			status += MXL_SetGPIO(fe, 1, 1);
-			status += MXL_SetGPIO(fe, 3, 0);
-		}
-		if (state->RF_IN >= 515000000 && state->RF_IN < 650000000) {
-			status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1);
-			status += MXL_SetGPIO(fe, 4, 1);
-			status += MXL_SetGPIO(fe, 1, 1);
-			status += MXL_SetGPIO(fe, 3, 0);
-		}
-		if (state->RF_IN >= 650000000 && state->RF_IN <= 900000000) {
-			status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1);
-			status += MXL_SetGPIO(fe, 4, 1);
-			status += MXL_SetGPIO(fe, 1, 1);
-			status += MXL_SetGPIO(fe, 3, 1);
-		}
-	}
-
-	if (state->TF_Type == MXL_TF_E_2) {
-
-		/* Tracking Filter type E_2 */
-		status += MXL_ControlWrite(fe, DAC_DIN_B, 0);
-
-		if (state->RF_IN >= 43000000 && state->RF_IN < 174000000) {
-			status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0);
-			status += MXL_SetGPIO(fe, 4, 0);
-			status += MXL_SetGPIO(fe, 1, 1);
-			status += MXL_SetGPIO(fe, 3, 1);
-		}
-		if (state->RF_IN >= 174000000 && state->RF_IN < 250000000) {
-			status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0);
-			status += MXL_SetGPIO(fe, 4, 0);
-			status += MXL_SetGPIO(fe, 1, 0);
-			status += MXL_SetGPIO(fe, 3, 1);
-		}
-		if (state->RF_IN >= 250000000 && state->RF_IN < 350000000) {
-			status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0);
-			status += MXL_SetGPIO(fe, 4, 1);
-			status += MXL_SetGPIO(fe, 1, 0);
-			status += MXL_SetGPIO(fe, 3, 1);
-		}
-		if (state->RF_IN >= 350000000 && state->RF_IN < 400000000) {
-			status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0);
-			status += MXL_SetGPIO(fe, 4, 1);
-			status += MXL_SetGPIO(fe, 1, 0);
-			status += MXL_SetGPIO(fe, 3, 0);
-		}
-		if (state->RF_IN >= 400000000 && state->RF_IN < 570000000) {
-			status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0);
-			status += MXL_SetGPIO(fe, 4, 1);
-			status += MXL_SetGPIO(fe, 1, 1);
-			status += MXL_SetGPIO(fe, 3, 0);
-		}
-		if (state->RF_IN >= 570000000 && state->RF_IN < 770000000) {
-			status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1);
-			status += MXL_SetGPIO(fe, 4, 1);
-			status += MXL_SetGPIO(fe, 1, 1);
-			status += MXL_SetGPIO(fe, 3, 0);
-		}
-		if (state->RF_IN >= 770000000 && state->RF_IN <= 900000000) {
-			status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1);
-			status += MXL_SetGPIO(fe, 4, 1);
-			status += MXL_SetGPIO(fe, 1, 1);
-			status += MXL_SetGPIO(fe, 3, 1);
-		}
-	}
-
-	if (state->TF_Type == MXL_TF_G) {
-
-		/* Tracking Filter type G add for v2.6.8 */
-		status += MXL_ControlWrite(fe, DAC_DIN_B, 0);
-
-		if (state->RF_IN >= 50000000 && state->RF_IN < 190000000) {
-
-			status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0);
-			status += MXL_SetGPIO(fe, 4, 0);
-			status += MXL_SetGPIO(fe, 1, 1);
-			status += MXL_SetGPIO(fe, 3, 1);
-		}
-		if (state->RF_IN >= 190000000 && state->RF_IN < 280000000) {
-			status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0);
-			status += MXL_SetGPIO(fe, 4, 0);
-			status += MXL_SetGPIO(fe, 1, 0);
-			status += MXL_SetGPIO(fe, 3, 1);
-		}
-		if (state->RF_IN >= 280000000 && state->RF_IN < 350000000) {
-			status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0);
-			status += MXL_SetGPIO(fe, 4, 1);
-			status += MXL_SetGPIO(fe, 1, 0);
-			status += MXL_SetGPIO(fe, 3, 1);
-		}
-		if (state->RF_IN >= 350000000 && state->RF_IN < 400000000) {
-			status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0);
-			status += MXL_SetGPIO(fe, 4, 1);
-			status += MXL_SetGPIO(fe, 1, 0);
-			status += MXL_SetGPIO(fe, 3, 0);
-		}
-		if (state->RF_IN >= 400000000 && state->RF_IN < 470000000) {
-			status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1);
-			status += MXL_SetGPIO(fe, 4, 1);
-			status += MXL_SetGPIO(fe, 1, 0);
-			status += MXL_SetGPIO(fe, 3, 1);
-		}
-		if (state->RF_IN >= 470000000 && state->RF_IN < 640000000) {
-			status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0);
-			status += MXL_SetGPIO(fe, 4, 1);
-			status += MXL_SetGPIO(fe, 1, 1);
-			status += MXL_SetGPIO(fe, 3, 0);
-		}
-		if (state->RF_IN >= 640000000 && state->RF_IN < 820000000) {
-			status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1);
-			status += MXL_SetGPIO(fe, 4, 1);
-			status += MXL_SetGPIO(fe, 1, 1);
-			status += MXL_SetGPIO(fe, 3, 0);
-		}
-		if (state->RF_IN >= 820000000 && state->RF_IN <= 900000000) {
-			status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1);
-			status += MXL_SetGPIO(fe, 4, 1);
-			status += MXL_SetGPIO(fe, 1, 1);
-			status += MXL_SetGPIO(fe, 3, 1);
-		}
-	}
-
-	if (state->TF_Type == MXL_TF_E_NA) {
-
-		/* Tracking Filter type E-NA for Empia ONLY change for 2.6.8 */
-		status += MXL_ControlWrite(fe, DAC_DIN_B, 0);
-
-		/* if UHF and terrestrial=> Turn off Tracking Filter */
-		if (state->RF_IN >= 471000000 &&
-			(state->RF_IN - 471000000)%6000000 != 0) {
-
-			/* Turn off all the banks */
-			status += MXL_SetGPIO(fe, 3, 1);
-			status += MXL_SetGPIO(fe, 1, 1);
-			status += MXL_SetGPIO(fe, 4, 1);
-			status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0);
-
-			/* 2.6.12 Turn on RSSI */
-			status += MXL_ControlWrite(fe, SEQ_EXTSYNTHCALIF, 1);
-			status += MXL_ControlWrite(fe, SEQ_EXTDCCAL, 1);
-			status += MXL_ControlWrite(fe, AGC_EN_RSSI, 1);
-			status += MXL_ControlWrite(fe, RFA_ENCLKRFAGC, 1);
-
-			/* RSSI reference point */
-			status += MXL_ControlWrite(fe, RFA_RSSI_REFH, 5);
-			status += MXL_ControlWrite(fe, RFA_RSSI_REF, 3);
-			status += MXL_ControlWrite(fe, RFA_RSSI_REFL, 2);
-
-			/* following parameter is from analog OTA mode,
-			 * can be change to seek better performance */
-			status += MXL_ControlWrite(fe, RFSYN_CHP_GAIN, 3);
-		} else {
-		/* if VHF or Cable =>  Turn on Tracking Filter */
-
-		/* 2.6.12 Turn off RSSI */
-		status += MXL_ControlWrite(fe, AGC_EN_RSSI, 0);
-
-		/* change back from above condition */
-		status += MXL_ControlWrite(fe, RFSYN_CHP_GAIN, 5);
-
-
-		if (state->RF_IN >= 43000000 && state->RF_IN < 174000000) {
-
-			status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0);
-			status += MXL_SetGPIO(fe, 4, 0);
-			status += MXL_SetGPIO(fe, 1, 1);
-			status += MXL_SetGPIO(fe, 3, 1);
-		}
-		if (state->RF_IN >= 174000000 && state->RF_IN < 250000000) {
-			status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0);
-			status += MXL_SetGPIO(fe, 4, 0);
-			status += MXL_SetGPIO(fe, 1, 0);
-			status += MXL_SetGPIO(fe, 3, 1);
-		}
-		if (state->RF_IN >= 250000000 && state->RF_IN < 350000000) {
-			status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0);
-			status += MXL_SetGPIO(fe, 4, 1);
-			status += MXL_SetGPIO(fe, 1, 0);
-			status += MXL_SetGPIO(fe, 3, 1);
-		}
-		if (state->RF_IN >= 350000000 && state->RF_IN < 400000000) {
-			status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0);
-			status += MXL_SetGPIO(fe, 4, 1);
-			status += MXL_SetGPIO(fe, 1, 0);
-			status += MXL_SetGPIO(fe, 3, 0);
-		}
-		if (state->RF_IN >= 400000000 && state->RF_IN < 570000000) {
-			status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0);
-			status += MXL_SetGPIO(fe, 4, 1);
-			status += MXL_SetGPIO(fe, 1, 1);
-			status += MXL_SetGPIO(fe, 3, 0);
-		}
-		if (state->RF_IN >= 570000000 && state->RF_IN < 770000000) {
-			status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1);
-			status += MXL_SetGPIO(fe, 4, 1);
-			status += MXL_SetGPIO(fe, 1, 1);
-			status += MXL_SetGPIO(fe, 3, 0);
-		}
-		if (state->RF_IN >= 770000000 && state->RF_IN <= 900000000) {
-			status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1);
-			status += MXL_SetGPIO(fe, 4, 1);
-			status += MXL_SetGPIO(fe, 1, 1);
-			status += MXL_SetGPIO(fe, 3, 1);
-		}
-		}
-	}
-	return status ;
-}
-
-static u16 MXL_SetGPIO(struct dvb_frontend *fe, u8 GPIO_Num, u8 GPIO_Val)
-{
-	u16 status = 0;
-
-	if (GPIO_Num == 1)
-		status += MXL_ControlWrite(fe, GPIO_1B, GPIO_Val ? 0 : 1);
-
-	/* GPIO2 is not available */
-
-	if (GPIO_Num == 3) {
-		if (GPIO_Val == 1) {
-			status += MXL_ControlWrite(fe, GPIO_3, 0);
-			status += MXL_ControlWrite(fe, GPIO_3B, 0);
-		}
-		if (GPIO_Val == 0) {
-			status += MXL_ControlWrite(fe, GPIO_3, 1);
-			status += MXL_ControlWrite(fe, GPIO_3B, 1);
-		}
-		if (GPIO_Val == 3) { /* tri-state */
-			status += MXL_ControlWrite(fe, GPIO_3, 0);
-			status += MXL_ControlWrite(fe, GPIO_3B, 1);
-		}
-	}
-	if (GPIO_Num == 4) {
-		if (GPIO_Val == 1) {
-			status += MXL_ControlWrite(fe, GPIO_4, 0);
-			status += MXL_ControlWrite(fe, GPIO_4B, 0);
-		}
-		if (GPIO_Val == 0) {
-			status += MXL_ControlWrite(fe, GPIO_4, 1);
-			status += MXL_ControlWrite(fe, GPIO_4B, 1);
-		}
-		if (GPIO_Val == 3) { /* tri-state */
-			status += MXL_ControlWrite(fe, GPIO_4, 0);
-			status += MXL_ControlWrite(fe, GPIO_4B, 1);
-		}
-	}
-
-	return status;
-}
-
-static u16 MXL_ControlWrite(struct dvb_frontend *fe, u16 ControlNum, u32 value)
-{
-	u16 status = 0;
-
-	/* Will write ALL Matching Control Name */
-	/* Write Matching INIT Control */
-	status += MXL_ControlWrite_Group(fe, ControlNum, value, 1);
-	/* Write Matching CH Control */
-	status += MXL_ControlWrite_Group(fe, ControlNum, value, 2);
-#ifdef _MXL_INTERNAL
-	/* Write Matching MXL Control */
-	status += MXL_ControlWrite_Group(fe, ControlNum, value, 3);
-#endif
-	return status;
-}
-
-static u16 MXL_ControlWrite_Group(struct dvb_frontend *fe, u16 controlNum,
-	u32 value, u16 controlGroup)
-{
-	struct mxl5005s_state *state = fe->tuner_priv;
-	u16 i, j, k;
-	u32 highLimit;
-	u32 ctrlVal;
-
-	if (controlGroup == 1) /* Initial Control */ {
-
-		for (i = 0; i < state->Init_Ctrl_Num; i++) {
-
-			if (controlNum == state->Init_Ctrl[i].Ctrl_Num) {
-
-				highLimit = 1 << state->Init_Ctrl[i].size;
-				if (value < highLimit) {
-					for (j = 0; j < state->Init_Ctrl[i].size; j++) {
-						state->Init_Ctrl[i].val[j] = (u8)((value >> j) & 0x01);
-						MXL_RegWriteBit(fe, (u8)(state->Init_Ctrl[i].addr[j]),
-							(u8)(state->Init_Ctrl[i].bit[j]),
-							(u8)((value>>j) & 0x01));
-					}
-					ctrlVal = 0;
-					for (k = 0; k < state->Init_Ctrl[i].size; k++)
-						ctrlVal += state->Init_Ctrl[i].val[k] * (1 << k);
-				} else
-					return -1;
-			}
-		}
-	}
-	if (controlGroup == 2) /* Chan change Control */ {
-
-		for (i = 0; i < state->CH_Ctrl_Num; i++) {
-
-			if (controlNum == state->CH_Ctrl[i].Ctrl_Num) {
-
-				highLimit = 1 << state->CH_Ctrl[i].size;
-				if (value < highLimit) {
-					for (j = 0; j < state->CH_Ctrl[i].size; j++) {
-						state->CH_Ctrl[i].val[j] = (u8)((value >> j) & 0x01);
-						MXL_RegWriteBit(fe, (u8)(state->CH_Ctrl[i].addr[j]),
-							(u8)(state->CH_Ctrl[i].bit[j]),
-							(u8)((value>>j) & 0x01));
-					}
-					ctrlVal = 0;
-					for (k = 0; k < state->CH_Ctrl[i].size; k++)
-						ctrlVal += state->CH_Ctrl[i].val[k] * (1 << k);
-				} else
-					return -1;
-			}
-		}
-	}
-#ifdef _MXL_INTERNAL
-	if (controlGroup == 3) /* Maxlinear Control */ {
-
-		for (i = 0; i < state->MXL_Ctrl_Num; i++) {
-
-			if (controlNum == state->MXL_Ctrl[i].Ctrl_Num) {
-
-				highLimit = (1 << state->MXL_Ctrl[i].size);
-				if (value < highLimit) {
-					for (j = 0; j < state->MXL_Ctrl[i].size; j++) {
-						state->MXL_Ctrl[i].val[j] = (u8)((value >> j) & 0x01);
-						MXL_RegWriteBit(fe, (u8)(state->MXL_Ctrl[i].addr[j]),
-							(u8)(state->MXL_Ctrl[i].bit[j]),
-							(u8)((value>>j) & 0x01));
-					}
-					ctrlVal = 0;
-					for (k = 0; k < state->MXL_Ctrl[i].size; k++)
-						ctrlVal += state->
-							MXL_Ctrl[i].val[k] *
-							(1 << k);
-				} else
-					return -1;
-			}
-		}
-	}
-#endif
-	return 0 ; /* successful return */
-}
-
-static u16 MXL_RegRead(struct dvb_frontend *fe, u8 RegNum, u8 *RegVal)
-{
-	struct mxl5005s_state *state = fe->tuner_priv;
-	int i ;
-
-	for (i = 0; i < 104; i++) {
-		if (RegNum == state->TunerRegs[i].Reg_Num) {
-			*RegVal = (u8)(state->TunerRegs[i].Reg_Val);
-			return 0;
-		}
-	}
-
-	return 1;
-}
-
-static u16 MXL_ControlRead(struct dvb_frontend *fe, u16 controlNum, u32 *value)
-{
-	struct mxl5005s_state *state = fe->tuner_priv;
-	u32 ctrlVal ;
-	u16 i, k ;
-
-	for (i = 0; i < state->Init_Ctrl_Num ; i++) {
-
-		if (controlNum == state->Init_Ctrl[i].Ctrl_Num) {
-
-			ctrlVal = 0;
-			for (k = 0; k < state->Init_Ctrl[i].size; k++)
-				ctrlVal += state->Init_Ctrl[i].val[k] * (1<<k);
-			*value = ctrlVal;
-			return 0;
-		}
-	}
-
-	for (i = 0; i < state->CH_Ctrl_Num ; i++) {
-
-		if (controlNum == state->CH_Ctrl[i].Ctrl_Num) {
-
-			ctrlVal = 0;
-			for (k = 0; k < state->CH_Ctrl[i].size; k++)
-				ctrlVal += state->CH_Ctrl[i].val[k] * (1 << k);
-			*value = ctrlVal;
-			return 0;
-
-		}
-	}
-
-#ifdef _MXL_INTERNAL
-	for (i = 0; i < state->MXL_Ctrl_Num ; i++) {
-
-		if (controlNum == state->MXL_Ctrl[i].Ctrl_Num) {
-
-			ctrlVal = 0;
-			for (k = 0; k < state->MXL_Ctrl[i].size; k++)
-				ctrlVal += state->MXL_Ctrl[i].val[k] * (1<<k);
-			*value = ctrlVal;
-			return 0;
-
-		}
-	}
-#endif
-	return 1;
-}
-
-static void MXL_RegWriteBit(struct dvb_frontend *fe, u8 address, u8 bit,
-	u8 bitVal)
-{
-	struct mxl5005s_state *state = fe->tuner_priv;
-	int i ;
-
-	const u8 AND_MAP[8] = {
-		0xFE, 0xFD, 0xFB, 0xF7,
-		0xEF, 0xDF, 0xBF, 0x7F } ;
-
-	const u8 OR_MAP[8] = {
-		0x01, 0x02, 0x04, 0x08,
-		0x10, 0x20, 0x40, 0x80 } ;
-
-	for (i = 0; i < state->TunerRegs_Num; i++) {
-		if (state->TunerRegs[i].Reg_Num == address) {
-			if (bitVal)
-				state->TunerRegs[i].Reg_Val |= OR_MAP[bit];
-			else
-				state->TunerRegs[i].Reg_Val &= AND_MAP[bit];
-			break ;
-		}
-	}
-}
-
-static u32 MXL_Ceiling(u32 value, u32 resolution)
-{
-	return value / resolution + (value % resolution > 0 ? 1 : 0);
-}
-
-/* Retrieve the Initialzation Registers */
-static u16 MXL_GetInitRegister(struct dvb_frontend *fe, u8 *RegNum,
-	u8 *RegVal, int *count)
-{
-	u16 status = 0;
-	int i ;
-
-	u8 RegAddr[] = {
-		11, 12, 13, 22, 32, 43, 44, 53, 56, 59, 73,
-		76, 77, 91, 134, 135, 137, 147,
-		156, 166, 167, 168, 25 };
-
-	*count = ARRAY_SIZE(RegAddr);
-
-	status += MXL_BlockInit(fe);
-
-	for (i = 0 ; i < *count; i++) {
-		RegNum[i] = RegAddr[i];
-		status += MXL_RegRead(fe, RegNum[i], &RegVal[i]);
-	}
-
-	return status;
-}
-
-static u16 MXL_GetCHRegister(struct dvb_frontend *fe, u8 *RegNum, u8 *RegVal,
-	int *count)
-{
-	u16 status = 0;
-	int i ;
-
-/* add 77, 166, 167, 168 register for 2.6.12 */
-#ifdef _MXL_PRODUCTION
-	u8 RegAddr[] = {14, 15, 16, 17, 22, 43, 65, 68, 69, 70, 73, 92, 93, 106,
-	   107, 108, 109, 110, 111, 112, 136, 138, 149, 77, 166, 167, 168 } ;
-#else
-	u8 RegAddr[] = {14, 15, 16, 17, 22, 43, 68, 69, 70, 73, 92, 93, 106,
-	   107, 108, 109, 110, 111, 112, 136, 138, 149, 77, 166, 167, 168 } ;
-	/*
-	u8 RegAddr[171];
-	for (i = 0; i <= 170; i++)
-		RegAddr[i] = i;
-	*/
-#endif
-
-	*count = ARRAY_SIZE(RegAddr);
-
-	for (i = 0 ; i < *count; i++) {
-		RegNum[i] = RegAddr[i];
-		status += MXL_RegRead(fe, RegNum[i], &RegVal[i]);
-	}
-
-	return status;
-}
-
-static u16 MXL_GetCHRegister_ZeroIF(struct dvb_frontend *fe, u8 *RegNum,
-	u8 *RegVal, int *count)
-{
-	u16 status = 0;
-	int i;
-
-	u8 RegAddr[] = {43, 136};
-
-	*count = ARRAY_SIZE(RegAddr);
-
-	for (i = 0; i < *count; i++) {
-		RegNum[i] = RegAddr[i];
-		status += MXL_RegRead(fe, RegNum[i], &RegVal[i]);
-	}
-
-	return status;
-}
-
-static u16 MXL_GetMasterControl(u8 *MasterReg, int state)
-{
-	if (state == 1) /* Load_Start */
-		*MasterReg = 0xF3;
-	if (state == 2) /* Power_Down */
-		*MasterReg = 0x41;
-	if (state == 3) /* Synth_Reset */
-		*MasterReg = 0xB1;
-	if (state == 4) /* Seq_Off */
-		*MasterReg = 0xF1;
-
-	return 0;
-}
-
-#ifdef _MXL_PRODUCTION
-static u16 MXL_VCORange_Test(struct dvb_frontend *fe, int VCO_Range)
-{
-	struct mxl5005s_state *state = fe->tuner_priv;
-	u16 status = 0 ;
-
-	if (VCO_Range == 1) {
-		status += MXL_ControlWrite(fe, RFSYN_EN_DIV, 1);
-		status += MXL_ControlWrite(fe, RFSYN_EN_OUTMUX, 0);
-		status += MXL_ControlWrite(fe, RFSYN_SEL_DIVM, 0);
-		status += MXL_ControlWrite(fe, RFSYN_DIVM, 1);
-		status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_OUT, 1);
-		status += MXL_ControlWrite(fe, RFSYN_RF_DIV_BIAS, 1);
-		status += MXL_ControlWrite(fe, DN_SEL_FREQ, 0);
-		if (state->Mode == 0 && state->IF_Mode == 1) {
-			/* Analog Low IF Mode */
-			status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 1);
-			status += MXL_ControlWrite(fe, RFSYN_VCO_BIAS, 8);
-			status += MXL_ControlWrite(fe, CHCAL_INT_MOD_RF, 56);
-			status += MXL_ControlWrite(fe,
-				CHCAL_FRAC_MOD_RF, 180224);
-		}
-		if (state->Mode == 0 && state->IF_Mode == 0) {
-			/* Analog Zero IF Mode */
-			status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 1);
-			status += MXL_ControlWrite(fe, RFSYN_VCO_BIAS, 8);
-			status += MXL_ControlWrite(fe, CHCAL_INT_MOD_RF, 56);
-			status += MXL_ControlWrite(fe,
-				CHCAL_FRAC_MOD_RF, 222822);
-		}
-		if (state->Mode == 1) /* Digital Mode */ {
-			status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 1);
-			status += MXL_ControlWrite(fe, RFSYN_VCO_BIAS, 8);
-			status += MXL_ControlWrite(fe, CHCAL_INT_MOD_RF, 56);
-			status += MXL_ControlWrite(fe,
-				CHCAL_FRAC_MOD_RF, 229376);
-		}
-	}
-
-	if (VCO_Range == 2) {
-		status += MXL_ControlWrite(fe, RFSYN_EN_DIV, 1);
-		status += MXL_ControlWrite(fe, RFSYN_EN_OUTMUX, 0);
-		status += MXL_ControlWrite(fe, RFSYN_SEL_DIVM, 0);
-		status += MXL_ControlWrite(fe, RFSYN_DIVM, 1);
-		status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_OUT, 1);
-		status += MXL_ControlWrite(fe, RFSYN_RF_DIV_BIAS, 1);
-		status += MXL_ControlWrite(fe, DN_SEL_FREQ, 0);
-		status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 1);
-		status += MXL_ControlWrite(fe, RFSYN_VCO_BIAS, 40);
-		status += MXL_ControlWrite(fe, CHCAL_INT_MOD_RF, 41);
-		if (state->Mode == 0 && state->IF_Mode == 1) {
-			/* Analog Low IF Mode */
-			status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 1);
-			status += MXL_ControlWrite(fe, RFSYN_VCO_BIAS, 40);
-			status += MXL_ControlWrite(fe, CHCAL_INT_MOD_RF, 42);
-			status += MXL_ControlWrite(fe,
-				CHCAL_FRAC_MOD_RF, 206438);
-		}
-		if (state->Mode == 0 && state->IF_Mode == 0) {
-			/* Analog Zero IF Mode */
-			status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 1);
-			status += MXL_ControlWrite(fe, RFSYN_VCO_BIAS, 40);
-			status += MXL_ControlWrite(fe, CHCAL_INT_MOD_RF, 42);
-			status += MXL_ControlWrite(fe,
-				CHCAL_FRAC_MOD_RF, 206438);
-		}
-		if (state->Mode == 1) /* Digital Mode */ {
-			status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 1);
-			status += MXL_ControlWrite(fe, RFSYN_VCO_BIAS, 40);
-			status += MXL_ControlWrite(fe, CHCAL_INT_MOD_RF, 41);
-			status += MXL_ControlWrite(fe,
-				CHCAL_FRAC_MOD_RF, 16384);
-		}
-	}
-
-	if (VCO_Range == 3) {
-		status += MXL_ControlWrite(fe, RFSYN_EN_DIV, 1);
-		status += MXL_ControlWrite(fe, RFSYN_EN_OUTMUX, 0);
-		status += MXL_ControlWrite(fe, RFSYN_SEL_DIVM, 0);
-		status += MXL_ControlWrite(fe, RFSYN_DIVM, 1);
-		status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_OUT, 1);
-		status += MXL_ControlWrite(fe, RFSYN_RF_DIV_BIAS, 1);
-		status += MXL_ControlWrite(fe, DN_SEL_FREQ, 0);
-		status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 0);
-		status += MXL_ControlWrite(fe, RFSYN_VCO_BIAS, 8);
-		status += MXL_ControlWrite(fe, CHCAL_INT_MOD_RF, 42);
-		if (state->Mode == 0 && state->IF_Mode == 1) {
-			/* Analog Low IF Mode */
-			status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 0);
-			status += MXL_ControlWrite(fe, RFSYN_VCO_BIAS, 8);
-			status += MXL_ControlWrite(fe, CHCAL_INT_MOD_RF, 44);
-			status += MXL_ControlWrite(fe,
-				CHCAL_FRAC_MOD_RF, 173670);
-		}
-		if (state->Mode == 0 && state->IF_Mode == 0) {
-			/* Analog Zero IF Mode */
-			status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 0);
-			status += MXL_ControlWrite(fe, RFSYN_VCO_BIAS, 8);
-			status += MXL_ControlWrite(fe, CHCAL_INT_MOD_RF, 44);
-			status += MXL_ControlWrite(fe,
-				CHCAL_FRAC_MOD_RF, 173670);
-		}
-		if (state->Mode == 1) /* Digital Mode */ {
-			status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 0);
-			status += MXL_ControlWrite(fe, RFSYN_VCO_BIAS, 8);
-			status += MXL_ControlWrite(fe, CHCAL_INT_MOD_RF, 42);
-			status += MXL_ControlWrite(fe,
-				CHCAL_FRAC_MOD_RF, 245760);
-		}
-	}
-
-	if (VCO_Range == 4) {
-		status += MXL_ControlWrite(fe, RFSYN_EN_DIV, 1);
-		status += MXL_ControlWrite(fe, RFSYN_EN_OUTMUX, 0);
-		status += MXL_ControlWrite(fe, RFSYN_SEL_DIVM, 0);
-		status += MXL_ControlWrite(fe, RFSYN_DIVM, 1);
-		status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_OUT, 1);
-		status += MXL_ControlWrite(fe, RFSYN_RF_DIV_BIAS, 1);
-		status += MXL_ControlWrite(fe, DN_SEL_FREQ, 0);
-		status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 0);
-		status += MXL_ControlWrite(fe, RFSYN_VCO_BIAS, 40);
-		status += MXL_ControlWrite(fe, CHCAL_INT_MOD_RF, 27);
-		if (state->Mode == 0 && state->IF_Mode == 1) {
-			/* Analog Low IF Mode */
-			status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 0);
-			status += MXL_ControlWrite(fe, RFSYN_VCO_BIAS, 40);
-			status += MXL_ControlWrite(fe, CHCAL_INT_MOD_RF, 27);
-			status += MXL_ControlWrite(fe,
-				CHCAL_FRAC_MOD_RF, 206438);
-		}
-		if (state->Mode == 0 && state->IF_Mode == 0) {
-			/* Analog Zero IF Mode */
-			status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 0);
-			status += MXL_ControlWrite(fe, RFSYN_VCO_BIAS, 40);
-			status += MXL_ControlWrite(fe, CHCAL_INT_MOD_RF, 27);
-			status += MXL_ControlWrite(fe,
-				CHCAL_FRAC_MOD_RF, 206438);
-		}
-		if (state->Mode == 1) /* Digital Mode */ {
-			status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 0);
-			status += MXL_ControlWrite(fe, RFSYN_VCO_BIAS, 40);
-			status += MXL_ControlWrite(fe, CHCAL_INT_MOD_RF, 27);
-			status += MXL_ControlWrite(fe,
-				CHCAL_FRAC_MOD_RF, 212992);
-		}
-	}
-
-	return status;
-}
-
-static u16 MXL_Hystersis_Test(struct dvb_frontend *fe, int Hystersis)
-{
-	struct mxl5005s_state *state = fe->tuner_priv;
-	u16 status = 0;
-
-	if (Hystersis == 1)
-		status += MXL_ControlWrite(fe, DN_BYPASS_AGC_I2C, 1);
-
-	return status;
-}
-#endif
-/* End: Reference driver code found in the Realtek driver that
- * is copyright MaxLinear */
-
-/* ----------------------------------------------------------------
- * Begin: Everything after here is new code to adapt the
- * proprietary Realtek driver into a Linux API tuner.
- * Copyright (C) 2008 Steven Toth <stoth@linuxtv.org>
- */
-static int mxl5005s_reset(struct dvb_frontend *fe)
-{
-	struct mxl5005s_state *state = fe->tuner_priv;
-	int ret = 0;
-
-	u8 buf[2] = { 0xff, 0x00 };
-	struct i2c_msg msg = { .addr = state->config->i2c_address, .flags = 0,
-			       .buf = buf, .len = 2 };
-
-	dprintk(2, "%s()\n", __func__);
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-
-	if (i2c_transfer(state->i2c, &msg, 1) != 1) {
-		printk(KERN_WARNING "mxl5005s I2C reset failed\n");
-		ret = -EREMOTEIO;
-	}
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0);
-
-	return ret;
-}
-
-/* Write a single byte to a single reg, latch the value if required by
- * following the transaction with the latch byte.
- */
-static int mxl5005s_writereg(struct dvb_frontend *fe, u8 reg, u8 val, int latch)
-{
-	struct mxl5005s_state *state = fe->tuner_priv;
-	u8 buf[3] = { reg, val, MXL5005S_LATCH_BYTE };
-	struct i2c_msg msg = { .addr = state->config->i2c_address, .flags = 0,
-			       .buf = buf, .len = 3 };
-
-	if (latch == 0)
-		msg.len = 2;
-
-	dprintk(2, "%s(0x%x, 0x%x, 0x%x)\n", __func__, reg, val, msg.addr);
-
-	if (i2c_transfer(state->i2c, &msg, 1) != 1) {
-		printk(KERN_WARNING "mxl5005s I2C write failed\n");
-		return -EREMOTEIO;
-	}
-	return 0;
-}
-
-static int mxl5005s_writeregs(struct dvb_frontend *fe, u8 *addrtable,
-	u8 *datatable, u8 len)
-{
-	int ret = 0, i;
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-
-	for (i = 0 ; i < len-1; i++) {
-		ret = mxl5005s_writereg(fe, addrtable[i], datatable[i], 0);
-		if (ret < 0)
-			break;
-	}
-
-	ret = mxl5005s_writereg(fe, addrtable[i], datatable[i], 1);
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0);
-
-	return ret;
-}
-
-static int mxl5005s_init(struct dvb_frontend *fe)
-{
-	struct mxl5005s_state *state = fe->tuner_priv;
-
-	dprintk(1, "%s()\n", __func__);
-	state->current_mode = MXL_QAM;
-	return mxl5005s_reconfigure(fe, MXL_QAM, MXL5005S_BANDWIDTH_6MHZ);
-}
-
-static int mxl5005s_reconfigure(struct dvb_frontend *fe, u32 mod_type,
-	u32 bandwidth)
-{
-	struct mxl5005s_state *state = fe->tuner_priv;
-
-	u8 AddrTable[MXL5005S_REG_WRITING_TABLE_LEN_MAX];
-	u8 ByteTable[MXL5005S_REG_WRITING_TABLE_LEN_MAX];
-	int TableLen;
-
-	dprintk(1, "%s(type=%d, bw=%d)\n", __func__, mod_type, bandwidth);
-
-	mxl5005s_reset(fe);
-
-	/* Tuner initialization stage 0 */
-	MXL_GetMasterControl(ByteTable, MC_SYNTH_RESET);
-	AddrTable[0] = MASTER_CONTROL_ADDR;
-	ByteTable[0] |= state->config->AgcMasterByte;
-
-	mxl5005s_writeregs(fe, AddrTable, ByteTable, 1);
-
-	mxl5005s_AssignTunerMode(fe, mod_type, bandwidth);
-
-	/* Tuner initialization stage 1 */
-	MXL_GetInitRegister(fe, AddrTable, ByteTable, &TableLen);
-
-	mxl5005s_writeregs(fe, AddrTable, ByteTable, TableLen);
-
-	return 0;
-}
-
-static int mxl5005s_AssignTunerMode(struct dvb_frontend *fe, u32 mod_type,
-	u32 bandwidth)
-{
-	struct mxl5005s_state *state = fe->tuner_priv;
-	struct mxl5005s_config *c = state->config;
-
-	InitTunerControls(fe);
-
-	/* Set MxL5005S parameters. */
-	MXL5005_TunerConfig(
-		fe,
-		c->mod_mode,
-		c->if_mode,
-		bandwidth,
-		c->if_freq,
-		c->xtal_freq,
-		c->agc_mode,
-		c->top,
-		c->output_load,
-		c->clock_out,
-		c->div_out,
-		c->cap_select,
-		c->rssi_enable,
-		mod_type,
-		c->tracking_filter);
-
-	return 0;
-}
-
-static int mxl5005s_set_params(struct dvb_frontend *fe)
-{
-	struct mxl5005s_state *state = fe->tuner_priv;
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	u32 delsys = c->delivery_system;
-	u32 bw = c->bandwidth_hz;
-	u32 req_mode, req_bw = 0;
-	int ret;
-
-	dprintk(1, "%s()\n", __func__);
-
-	switch (delsys) {
-	case SYS_ATSC:
-		req_mode = MXL_ATSC;
-		req_bw  = MXL5005S_BANDWIDTH_6MHZ;
-		break;
-	case SYS_DVBC_ANNEX_B:
-		req_mode = MXL_QAM;
-		req_bw  = MXL5005S_BANDWIDTH_6MHZ;
-		break;
-	default:	/* Assume DVB-T */
-		req_mode = MXL_DVBT;
-		switch (bw) {
-		case 6000000:
-			req_bw = MXL5005S_BANDWIDTH_6MHZ;
-			break;
-		case 7000000:
-			req_bw = MXL5005S_BANDWIDTH_7MHZ;
-			break;
-		case 8000000:
-		case 0:
-			req_bw = MXL5005S_BANDWIDTH_8MHZ;
-			break;
-		default:
-			return -EINVAL;
-		}
-	}
-
-	/* Change tuner for new modulation type if reqd */
-	if (req_mode != state->current_mode ||
-	    req_bw != state->Chan_Bandwidth) {
-		state->current_mode = req_mode;
-		ret = mxl5005s_reconfigure(fe, req_mode, req_bw);
-
-	} else
-		ret = 0;
-
-	if (ret == 0) {
-		dprintk(1, "%s() freq=%d\n", __func__, c->frequency);
-		ret = mxl5005s_SetRfFreqHz(fe, c->frequency);
-	}
-
-	return ret;
-}
-
-static int mxl5005s_get_frequency(struct dvb_frontend *fe, u32 *frequency)
-{
-	struct mxl5005s_state *state = fe->tuner_priv;
-	dprintk(1, "%s()\n", __func__);
-
-	*frequency = state->RF_IN;
-
-	return 0;
-}
-
-static int mxl5005s_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
-{
-	struct mxl5005s_state *state = fe->tuner_priv;
-	dprintk(1, "%s()\n", __func__);
-
-	*bandwidth = state->Chan_Bandwidth;
-
-	return 0;
-}
-
-static int mxl5005s_release(struct dvb_frontend *fe)
-{
-	dprintk(1, "%s()\n", __func__);
-	kfree(fe->tuner_priv);
-	fe->tuner_priv = NULL;
-	return 0;
-}
-
-static const struct dvb_tuner_ops mxl5005s_tuner_ops = {
-	.info = {
-		.name           = "MaxLinear MXL5005S",
-		.frequency_min  =  48000000,
-		.frequency_max  = 860000000,
-		.frequency_step =     50000,
-	},
-
-	.release       = mxl5005s_release,
-	.init          = mxl5005s_init,
-
-	.set_params    = mxl5005s_set_params,
-	.get_frequency = mxl5005s_get_frequency,
-	.get_bandwidth = mxl5005s_get_bandwidth,
-};
-
-struct dvb_frontend *mxl5005s_attach(struct dvb_frontend *fe,
-				     struct i2c_adapter *i2c,
-				     struct mxl5005s_config *config)
-{
-	struct mxl5005s_state *state = NULL;
-	dprintk(1, "%s()\n", __func__);
-
-	state = kzalloc(sizeof(struct mxl5005s_state), GFP_KERNEL);
-	if (state == NULL)
-		return NULL;
-
-	state->frontend = fe;
-	state->config = config;
-	state->i2c = i2c;
-
-	printk(KERN_INFO "MXL5005S: Attached at address 0x%02x\n",
-		config->i2c_address);
-
-	memcpy(&fe->ops.tuner_ops, &mxl5005s_tuner_ops,
-		sizeof(struct dvb_tuner_ops));
-
-	fe->tuner_priv = state;
-	return fe;
-}
-EXPORT_SYMBOL(mxl5005s_attach);
-
-MODULE_DESCRIPTION("MaxLinear MXL5005S silicon tuner driver");
-MODULE_AUTHOR("Steven Toth");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/common/tuners/mxl5005s.h b/drivers/media/common/tuners/mxl5005s.h
deleted file mode 100644
index fc8a1ff..0000000
--- a/drivers/media/common/tuners/mxl5005s.h
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
-    MaxLinear MXL5005S VSB/QAM/DVBT tuner driver
-
-    Copyright (C) 2008 MaxLinear
-    Copyright (C) 2008 Steven Toth <stoth@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 __MXL5005S_H
-#define __MXL5005S_H
-
-#include <linux/i2c.h>
-#include "dvb_frontend.h"
-
-struct mxl5005s_config {
-
-	/* 7 bit i2c address */
-	u8 i2c_address;
-
-#define IF_FREQ_4570000HZ    4570000
-#define IF_FREQ_4571429HZ    4571429
-#define IF_FREQ_5380000HZ    5380000
-#define IF_FREQ_36000000HZ  36000000
-#define IF_FREQ_36125000HZ  36125000
-#define IF_FREQ_36166667HZ  36166667
-#define IF_FREQ_44000000HZ  44000000
-	u32 if_freq;
-
-#define CRYSTAL_FREQ_4000000HZ    4000000
-#define CRYSTAL_FREQ_16000000HZ  16000000
-#define CRYSTAL_FREQ_25000000HZ  25000000
-#define CRYSTAL_FREQ_28800000HZ  28800000
-	u32 xtal_freq;
-
-#define MXL_DUAL_AGC   0
-#define MXL_SINGLE_AGC 1
-	u8 agc_mode;
-
-#define MXL_TF_DEFAULT	0
-#define MXL_TF_OFF	1
-#define MXL_TF_C	2
-#define MXL_TF_C_H	3
-#define MXL_TF_D	4
-#define MXL_TF_D_L	5
-#define MXL_TF_E	6
-#define MXL_TF_F	7
-#define MXL_TF_E_2	8
-#define MXL_TF_E_NA	9
-#define MXL_TF_G	10
-	u8 tracking_filter;
-
-#define MXL_RSSI_DISABLE	0
-#define MXL_RSSI_ENABLE		1
-	u8 rssi_enable;
-
-#define MXL_CAP_SEL_DISABLE	0
-#define MXL_CAP_SEL_ENABLE	1
-	u8 cap_select;
-
-#define MXL_DIV_OUT_1	0
-#define MXL_DIV_OUT_4	1
-	u8 div_out;
-
-#define MXL_CLOCK_OUT_DISABLE	0
-#define MXL_CLOCK_OUT_ENABLE	1
-	u8 clock_out;
-
-#define MXL5005S_IF_OUTPUT_LOAD_200_OHM 200
-#define MXL5005S_IF_OUTPUT_LOAD_300_OHM 300
-	u32 output_load;
-
-#define MXL5005S_TOP_5P5   55
-#define MXL5005S_TOP_7P2   72
-#define MXL5005S_TOP_9P2   92
-#define MXL5005S_TOP_11P0 110
-#define MXL5005S_TOP_12P9 129
-#define MXL5005S_TOP_14P7 147
-#define MXL5005S_TOP_16P8 168
-#define MXL5005S_TOP_19P4 194
-#define MXL5005S_TOP_21P2 212
-#define MXL5005S_TOP_23P2 232
-#define MXL5005S_TOP_25P2 252
-#define MXL5005S_TOP_27P1 271
-#define MXL5005S_TOP_29P2 292
-#define MXL5005S_TOP_31P7 317
-#define MXL5005S_TOP_34P9 349
-	u32 top;
-
-#define MXL_ANALOG_MODE  0
-#define MXL_DIGITAL_MODE 1
-	u8 mod_mode;
-
-#define MXL_ZERO_IF 0
-#define MXL_LOW_IF  1
-	u8 if_mode;
-
-	/* Some boards need to override the built-in logic for determining
-	   the gain when in QAM mode (the HVR-1600 is one such case) */
-	u8 qam_gain;
-
-	/* Stuff I don't know what to do with */
-	u8 AgcMasterByte;
-};
-
-#if defined(CONFIG_MEDIA_TUNER_MXL5005S) || \
-	(defined(CONFIG_MEDIA_TUNER_MXL5005S_MODULE) && defined(MODULE))
-extern struct dvb_frontend *mxl5005s_attach(struct dvb_frontend *fe,
-					    struct i2c_adapter *i2c,
-					    struct mxl5005s_config *config);
-#else
-static inline struct dvb_frontend *mxl5005s_attach(struct dvb_frontend *fe,
-					    struct i2c_adapter *i2c,
-					    struct mxl5005s_config *config)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif /* CONFIG_DVB_TUNER_MXL5005S */
-
-#endif /* __MXL5005S_H */
-
diff --git a/drivers/media/common/tuners/mxl5007t.c b/drivers/media/common/tuners/mxl5007t.c
deleted file mode 100644
index 69e453e..0000000
--- a/drivers/media/common/tuners/mxl5007t.c
+++ /dev/null
@@ -1,928 +0,0 @@
-/*
- *  mxl5007t.c - driver for the MaxLinear MxL5007T silicon tuner
- *
- *  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/i2c.h>
-#include <linux/types.h>
-#include <linux/videodev2.h>
-#include "tuner-i2c.h"
-#include "mxl5007t.h"
-
-static DEFINE_MUTEX(mxl5007t_list_mutex);
-static LIST_HEAD(hybrid_tuner_instance_list);
-
-static int mxl5007t_debug;
-module_param_named(debug, mxl5007t_debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debug level");
-
-/* ------------------------------------------------------------------------- */
-
-#define mxl_printk(kern, fmt, arg...) \
-	printk(kern "%s: " fmt "\n", __func__, ##arg)
-
-#define mxl_err(fmt, arg...) \
-	mxl_printk(KERN_ERR, "%d: " fmt, __LINE__, ##arg)
-
-#define mxl_warn(fmt, arg...) \
-	mxl_printk(KERN_WARNING, fmt, ##arg)
-
-#define mxl_info(fmt, arg...) \
-	mxl_printk(KERN_INFO, fmt, ##arg)
-
-#define mxl_debug(fmt, arg...)				\
-({							\
-	if (mxl5007t_debug)				\
-		mxl_printk(KERN_DEBUG, fmt, ##arg);	\
-})
-
-#define mxl_fail(ret)							\
-({									\
-	int __ret;							\
-	__ret = (ret < 0);						\
-	if (__ret)							\
-		mxl_printk(KERN_ERR, "error %d on line %d",		\
-			   ret, __LINE__);				\
-	__ret;								\
-})
-
-/* ------------------------------------------------------------------------- */
-
-#define MHz 1000000
-
-enum mxl5007t_mode {
-	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,
-	MxL_5007_V2_200_F2 = 0x24,
-};
-
-struct reg_pair_t {
-	u8 reg;
-	u8 val;
-};
-
-/* ------------------------------------------------------------------------- */
-
-static struct reg_pair_t init_tab[] = {
-	{ 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[] = {
-	{ 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[] = {
-	{ 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 }
-};
-
-/* ------------------------------------------------------------------------- */
-
-struct mxl5007t_state {
-	struct list_head hybrid_tuner_instance_list;
-	struct tuner_i2c_props i2c_props;
-
-	struct mutex lock;
-
-	struct mxl5007t_config *config;
-
-	enum mxl5007t_chip_version chip_id;
-
-	struct reg_pair_t tab_init[ARRAY_SIZE(init_tab)];
-	struct reg_pair_t tab_init_cable[ARRAY_SIZE(init_tab_cable)];
-	struct reg_pair_t tab_rftune[ARRAY_SIZE(reg_pair_rftune)];
-
-	enum mxl5007t_if_freq if_freq;
-
-	u32 frequency;
-	u32 bandwidth;
-};
-
-/* ------------------------------------------------------------------------- */
-
-/* called by _init and _rftun to manipulate the register arrays */
-
-static void set_reg_bits(struct reg_pair_t *reg_pair, u8 reg, u8 mask, u8 val)
-{
-	unsigned int i = 0;
-
-	while (reg_pair[i].reg || reg_pair[i].val) {
-		if (reg_pair[i].reg == reg) {
-			reg_pair[i].val &= ~mask;
-			reg_pair[i].val |= val;
-		}
-		i++;
-
-	}
-	return;
-}
-
-static void copy_reg_bits(struct reg_pair_t *reg_pair1,
-			  struct reg_pair_t *reg_pair2)
-{
-	unsigned int i, j;
-
-	i = j = 0;
-
-	while (reg_pair1[i].reg || reg_pair1[i].val) {
-		while (reg_pair2[j].reg || reg_pair2[j].val) {
-			if (reg_pair1[i].reg != reg_pair2[j].reg) {
-				j++;
-				continue;
-			}
-			reg_pair2[j].val = reg_pair1[i].val;
-			break;
-		}
-		i++;
-	}
-	return;
-}
-
-/* ------------------------------------------------------------------------- */
-
-static void mxl5007t_set_mode_bits(struct mxl5007t_state *state,
-				   enum mxl5007t_mode mode,
-				   s32 if_diff_out_level)
-{
-	switch (mode) {
-	case MxL_MODE_ATSC:
-		set_reg_bits(state->tab_init, 0x06, 0x1f, 0x12);
-		break;
-	case MxL_MODE_DVBT:
-		set_reg_bits(state->tab_init, 0x06, 0x1f, 0x11);
-		break;
-	case MxL_MODE_ISDBT:
-		set_reg_bits(state->tab_init, 0x06, 0x1f, 0x10);
-		break;
-	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, 0x0b, 0xff, 0x17);
-		break;
-	default:
-		mxl_fail(-EINVAL);
-	}
-	return;
-}
-
-static void mxl5007t_set_if_freq_bits(struct mxl5007t_state *state,
-				      enum mxl5007t_if_freq if_freq,
-				      int invert_if)
-{
-	u8 val;
-
-	switch (if_freq) {
-	case MxL_IF_4_MHZ:
-		val = 0x00;
-		break;
-	case MxL_IF_4_5_MHZ:
-		val = 0x02;
-		break;
-	case MxL_IF_4_57_MHZ:
-		val = 0x03;
-		break;
-	case MxL_IF_5_MHZ:
-		val = 0x04;
-		break;
-	case MxL_IF_5_38_MHZ:
-		val = 0x05;
-		break;
-	case MxL_IF_6_MHZ:
-		val = 0x06;
-		break;
-	case MxL_IF_6_28_MHZ:
-		val = 0x07;
-		break;
-	case MxL_IF_9_1915_MHZ:
-		val = 0x08;
-		break;
-	case MxL_IF_35_25_MHZ:
-		val = 0x09;
-		break;
-	case MxL_IF_36_15_MHZ:
-		val = 0x0a;
-		break;
-	case MxL_IF_44_MHZ:
-		val = 0x0b;
-		break;
-	default:
-		mxl_fail(-EINVAL);
-		return;
-	}
-	set_reg_bits(state->tab_init, 0x02, 0x0f, val);
-
-	/* set inverted IF or normal IF */
-	set_reg_bits(state->tab_init, 0x02, 0x10, invert_if ? 0x10 : 0x00);
-
-	state->if_freq = if_freq;
-
-	return;
-}
-
-static void mxl5007t_set_xtal_freq_bits(struct mxl5007t_state *state,
-					enum mxl5007t_xtal_freq xtal_freq)
-{
-	switch (xtal_freq) {
-	case MxL_XTAL_16_MHZ:
-		/* 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:
-		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:
-		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:
-		set_reg_bits(state->tab_init, 0x03, 0xf0, 0x30);
-		set_reg_bits(state->tab_init, 0x05, 0x0f, 0x03);
-		break;
-	case MxL_XTAL_24_MHZ:
-		set_reg_bits(state->tab_init, 0x03, 0xf0, 0x40);
-		set_reg_bits(state->tab_init, 0x05, 0x0f, 0x04);
-		break;
-	case MxL_XTAL_25_MHZ:
-		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:
-		set_reg_bits(state->tab_init, 0x03, 0xf0, 0x60);
-		set_reg_bits(state->tab_init, 0x05, 0x0f, 0x06);
-		break;
-	case MxL_XTAL_27_MHZ:
-		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:
-		set_reg_bits(state->tab_init, 0x03, 0xf0, 0x80);
-		set_reg_bits(state->tab_init, 0x05, 0x0f, 0x08);
-		break;
-	case MxL_XTAL_32_MHZ:
-		set_reg_bits(state->tab_init, 0x03, 0xf0, 0x90);
-		set_reg_bits(state->tab_init, 0x05, 0x0f, 0x09);
-		break;
-	case MxL_XTAL_40_MHZ:
-		set_reg_bits(state->tab_init, 0x03, 0xf0, 0xa0);
-		set_reg_bits(state->tab_init, 0x05, 0x0f, 0x0a);
-		break;
-	case MxL_XTAL_44_MHZ:
-		set_reg_bits(state->tab_init, 0x03, 0xf0, 0xb0);
-		set_reg_bits(state->tab_init, 0x05, 0x0f, 0x0b);
-		break;
-	case MxL_XTAL_48_MHZ:
-		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:
-		set_reg_bits(state->tab_init, 0x03, 0xf0, 0xd0);
-		set_reg_bits(state->tab_init, 0x05, 0x0f, 0x0d);
-		break;
-	default:
-		mxl_fail(-EINVAL);
-		return;
-	}
-
-	return;
-}
-
-static struct reg_pair_t *mxl5007t_calc_init_regs(struct mxl5007t_state *state,
-						  enum mxl5007t_mode mode)
-{
-	struct mxl5007t_config *cfg = state->config;
-
-	memcpy(&state->tab_init, &init_tab, sizeof(init_tab));
-	memcpy(&state->tab_init_cable, &init_tab_cable, sizeof(init_tab_cable));
-
-	mxl5007t_set_mode_bits(state, mode, cfg->if_diff_out_level);
-	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, 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);
-
-	if (mode >= MxL_MODE_CABLE) {
-		copy_reg_bits(state->tab_init, state->tab_init_cable);
-		return state->tab_init_cable;
-	} else
-		return state->tab_init;
-}
-
-/* ------------------------------------------------------------------------- */
-
-enum mxl5007t_bw_mhz {
-	MxL_BW_6MHz = 6,
-	MxL_BW_7MHz = 7,
-	MxL_BW_8MHz = 8,
-};
-
-static void mxl5007t_set_bw_bits(struct mxl5007t_state *state,
-				 enum mxl5007t_bw_mhz bw)
-{
-	u8 val;
-
-	switch (bw) {
-	case MxL_BW_6MHz:
-		val = 0x15; /* set DIG_MODEINDEX, DIG_MODEINDEX_A,
-			     * and DIG_MODEINDEX_CSF */
-		break;
-	case MxL_BW_7MHz:
-		val = 0x2a;
-		break;
-	case MxL_BW_8MHz:
-		val = 0x3f;
-		break;
-	default:
-		mxl_fail(-EINVAL);
-		return;
-	}
-	set_reg_bits(state->tab_rftune, 0x0c, 0x3f, val);
-
-	return;
-}
-
-static struct
-reg_pair_t *mxl5007t_calc_rf_tune_regs(struct mxl5007t_state *state,
-				       u32 rf_freq, enum mxl5007t_bw_mhz bw)
-{
-	u32 dig_rf_freq = 0;
-	u32 temp;
-	u32 frac_divider = 1000000;
-	unsigned int i;
-
-	memcpy(&state->tab_rftune, &reg_pair_rftune, sizeof(reg_pair_rftune));
-
-	mxl5007t_set_bw_bits(state, bw);
-
-	/* Convert RF frequency into 16 bits =>
-	 * 10 bit integer (MHz) + 6 bit fraction */
-	dig_rf_freq = rf_freq / MHz;
-
-	temp = rf_freq % MHz;
-
-	for (i = 0; i < 6; i++) {
-		dig_rf_freq <<= 1;
-		frac_divider /= 2;
-		if (temp > frac_divider) {
-			temp -= frac_divider;
-			dig_rf_freq++;
-		}
-	}
-
-	/* add to have shift center point by 7.8124 kHz */
-	if (temp > 7812)
-		dig_rf_freq++;
-
-	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;
-}
-
-/* ------------------------------------------------------------------------- */
-
-static int mxl5007t_write_reg(struct mxl5007t_state *state, u8 reg, u8 val)
-{
-	u8 buf[] = { reg, val };
-	struct i2c_msg msg = { .addr = state->i2c_props.addr, .flags = 0,
-			       .buf = buf, .len = 2 };
-	int ret;
-
-	ret = i2c_transfer(state->i2c_props.adap, &msg, 1);
-	if (ret != 1) {
-		mxl_err("failed!");
-		return -EREMOTEIO;
-	}
-	return 0;
-}
-
-static int mxl5007t_write_regs(struct mxl5007t_state *state,
-			       struct reg_pair_t *reg_pair)
-{
-	unsigned int i = 0;
-	int ret = 0;
-
-	while ((ret == 0) && (reg_pair[i].reg || reg_pair[i].val)) {
-		ret = mxl5007t_write_reg(state,
-					 reg_pair[i].reg, reg_pair[i].val);
-		i++;
-	}
-	return ret;
-}
-
-static int mxl5007t_read_reg(struct mxl5007t_state *state, u8 reg, u8 *val)
-{
-	u8 buf[2] = { 0xfb, reg };
-	struct i2c_msg msg[] = {
-		{ .addr = state->i2c_props.addr, .flags = 0,
-		  .buf = buf, .len = 2 },
-		{ .addr = state->i2c_props.addr, .flags = I2C_M_RD,
-		  .buf = val, .len = 1 },
-	};
-	int ret;
-
-	ret = i2c_transfer(state->i2c_props.adap, msg, 2);
-	if (ret != 2) {
-		mxl_err("failed!");
-		return -EREMOTEIO;
-	}
-	return 0;
-}
-
-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
-	};
-	int ret = i2c_transfer(state->i2c_props.adap, &msg, 1);
-
-	if (ret != 1) {
-		mxl_err("failed!");
-		return -EREMOTEIO;
-	}
-	return 0;
-}
-
-static int mxl5007t_tuner_init(struct mxl5007t_state *state,
-			       enum mxl5007t_mode mode)
-{
-	struct reg_pair_t *init_regs;
-	int ret;
-
-	ret = mxl5007t_soft_reset(state);
-	if (mxl_fail(ret))
-		goto fail;
-
-	/* calculate initialization reg array */
-	init_regs = mxl5007t_calc_init_regs(state, mode);
-
-	ret = mxl5007t_write_regs(state, init_regs);
-	if (mxl_fail(ret))
-		goto fail;
-	mdelay(1);
-fail:
-	return ret;
-}
-
-static int mxl5007t_tuner_rf_tune(struct mxl5007t_state *state, u32 rf_freq_hz,
-				  enum mxl5007t_bw_mhz bw)
-{
-	struct reg_pair_t *rf_tune_regs;
-	int ret;
-
-	/* calculate channel change reg array */
-	rf_tune_regs = mxl5007t_calc_rf_tune_regs(state, rf_freq_hz, bw);
-
-	ret = mxl5007t_write_regs(state, rf_tune_regs);
-	if (mxl_fail(ret))
-		goto fail;
-	msleep(3);
-fail:
-	return ret;
-}
-
-/* ------------------------------------------------------------------------- */
-
-static int mxl5007t_synth_lock_status(struct mxl5007t_state *state,
-				      int *rf_locked, int *ref_locked)
-{
-	u8 d;
-	int ret;
-
-	*rf_locked = 0;
-	*ref_locked = 0;
-
-	ret = mxl5007t_read_reg(state, 0xd8, &d);
-	if (mxl_fail(ret))
-		goto fail;
-
-	if ((d & 0x0c) == 0x0c)
-		*rf_locked = 1;
-
-	if ((d & 0x03) == 0x03)
-		*ref_locked = 1;
-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, ret;
-
-	*status = 0;
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-
-	ret = mxl5007t_synth_lock_status(state, &rf_locked, &ref_locked);
-	if (mxl_fail(ret))
-		goto fail;
-	mxl_debug("%s%s", rf_locked ? "rf locked " : "",
-		  ref_locked ? "ref locked" : "");
-
-	if ((rf_locked) || (ref_locked))
-		*status |= TUNER_STATUS_LOCKED;
-fail:
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0);
-
-	return ret;
-}
-
-/* ------------------------------------------------------------------------- */
-
-static int mxl5007t_set_params(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	u32 delsys = c->delivery_system;
-	struct mxl5007t_state *state = fe->tuner_priv;
-	enum mxl5007t_bw_mhz bw;
-	enum mxl5007t_mode mode;
-	int ret;
-	u32 freq = c->frequency;
-
-	switch (delsys) {
-	case SYS_ATSC:
-		mode = MxL_MODE_ATSC;
-		bw = MxL_BW_6MHz;
-		break;
-	case SYS_DVBC_ANNEX_B:
-		mode = MxL_MODE_CABLE;
-		bw = MxL_BW_6MHz;
-		break;
-	case SYS_DVBT:
-	case SYS_DVBT2:
-		mode = MxL_MODE_DVBT;
-		switch (c->bandwidth_hz) {
-		case 6000000:
-			bw = MxL_BW_6MHz;
-			break;
-		case 7000000:
-			bw = MxL_BW_7MHz;
-			break;
-		case 8000000:
-			bw = MxL_BW_8MHz;
-			break;
-		default:
-			return -EINVAL;
-		}
-		break;
-	default:
-		mxl_err("modulation type not supported!");
-		return -EINVAL;
-	}
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-
-	mutex_lock(&state->lock);
-
-	ret = mxl5007t_tuner_init(state, 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 = c->bandwidth_hz;
-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;
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-
-	/* wake from standby */
-	ret = mxl5007t_write_reg(state, 0x01, 0x01);
-	mxl_fail(ret);
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0);
-
-	return ret;
-}
-
-static int mxl5007t_sleep(struct dvb_frontend *fe)
-{
-	struct mxl5007t_state *state = fe->tuner_priv;
-	int ret;
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-
-	/* enter standby mode */
-	ret = mxl5007t_write_reg(state, 0x01, 0x00);
-	mxl_fail(ret);
-	ret = mxl5007t_write_reg(state, 0x0f, 0x00);
-	mxl_fail(ret);
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0);
-
-	return ret;
-}
-
-/* ------------------------------------------------------------------------- */
-
-static int mxl5007t_get_frequency(struct dvb_frontend *fe, u32 *frequency)
-{
-	struct mxl5007t_state *state = fe->tuner_priv;
-	*frequency = state->frequency;
-	return 0;
-}
-
-static int mxl5007t_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
-{
-	struct mxl5007t_state *state = fe->tuner_priv;
-	*bandwidth = state->bandwidth;
-	return 0;
-}
-
-static int mxl5007t_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
-{
-	struct mxl5007t_state *state = fe->tuner_priv;
-
-	*frequency = 0;
-
-	switch (state->if_freq) {
-	case MxL_IF_4_MHZ:
-		*frequency = 4000000;
-		break;
-	case MxL_IF_4_5_MHZ:
-		*frequency = 4500000;
-		break;
-	case MxL_IF_4_57_MHZ:
-		*frequency = 4570000;
-		break;
-	case MxL_IF_5_MHZ:
-		*frequency = 5000000;
-		break;
-	case MxL_IF_5_38_MHZ:
-		*frequency = 5380000;
-		break;
-	case MxL_IF_6_MHZ:
-		*frequency = 6000000;
-		break;
-	case MxL_IF_6_28_MHZ:
-		*frequency = 6280000;
-		break;
-	case MxL_IF_9_1915_MHZ:
-		*frequency = 9191500;
-		break;
-	case MxL_IF_35_25_MHZ:
-		*frequency = 35250000;
-		break;
-	case MxL_IF_36_15_MHZ:
-		*frequency = 36150000;
-		break;
-	case MxL_IF_44_MHZ:
-		*frequency = 44000000;
-		break;
-	}
-	return 0;
-}
-
-static int mxl5007t_release(struct dvb_frontend *fe)
-{
-	struct mxl5007t_state *state = fe->tuner_priv;
-
-	mutex_lock(&mxl5007t_list_mutex);
-
-	if (state)
-		hybrid_tuner_release_state(state);
-
-	mutex_unlock(&mxl5007t_list_mutex);
-
-	fe->tuner_priv = NULL;
-
-	return 0;
-}
-
-/* ------------------------------------------------------------------------- */
-
-static struct dvb_tuner_ops mxl5007t_tuner_ops = {
-	.info = {
-		.name = "MaxLinear MxL5007T",
-	},
-	.init              = mxl5007t_init,
-	.sleep             = mxl5007t_sleep,
-	.set_params        = mxl5007t_set_params,
-	.get_status        = mxl5007t_get_status,
-	.get_frequency     = mxl5007t_get_frequency,
-	.get_bandwidth     = mxl5007t_get_bandwidth,
-	.release           = mxl5007t_release,
-	.get_if_frequency  = mxl5007t_get_if_frequency,
-};
-
-static int mxl5007t_get_chip_id(struct mxl5007t_state *state)
-{
-	char *name;
-	int ret;
-	u8 id;
-
-	ret = mxl5007t_read_reg(state, 0xd9, &id);
-	if (mxl_fail(ret))
-		goto fail;
-
-	switch (id) {
-	case MxL_5007_V1_F1:
-		name = "MxL5007.v1.f1";
-		break;
-	case MxL_5007_V1_F2:
-		name = "MxL5007.v1.f2";
-		break;
-	case MxL_5007_V2_100_F1:
-		name = "MxL5007.v2.100.f1";
-		break;
-	case MxL_5007_V2_100_F2:
-		name = "MxL5007.v2.100.f2";
-		break;
-	case MxL_5007_V2_200_F1:
-		name = "MxL5007.v2.200.f1";
-		break;
-	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;
-	mxl_info("%s detected @ %d-%04x", name,
-		 i2c_adapter_id(state->i2c_props.adap),
-		 state->i2c_props.addr);
-	return 0;
-fail:
-	mxl_warn("unable to identify device @ %d-%04x",
-		 i2c_adapter_id(state->i2c_props.adap),
-		 state->i2c_props.addr);
-
-	state->chip_id = MxL_UNKNOWN_ID;
-	return ret;
-}
-
-struct dvb_frontend *mxl5007t_attach(struct dvb_frontend *fe,
-				     struct i2c_adapter *i2c, u8 addr,
-				     struct mxl5007t_config *cfg)
-{
-	struct mxl5007t_state *state = NULL;
-	int instance, ret;
-
-	mutex_lock(&mxl5007t_list_mutex);
-	instance = hybrid_tuner_request_state(struct mxl5007t_state, state,
-					      hybrid_tuner_instance_list,
-					      i2c, addr, "mxl5007t");
-	switch (instance) {
-	case 0:
-		goto fail;
-	case 1:
-		/* new tuner instance */
-		state->config = cfg;
-
-		mutex_init(&state->lock);
-
-		if (fe->ops.i2c_gate_ctrl)
-			fe->ops.i2c_gate_ctrl(fe, 1);
-
-		ret = mxl5007t_get_chip_id(state);
-
-		if (fe->ops.i2c_gate_ctrl)
-			fe->ops.i2c_gate_ctrl(fe, 0);
-
-		/* check return value of mxl5007t_get_chip_id */
-		if (mxl_fail(ret))
-			goto fail;
-		break;
-	default:
-		/* existing tuner instance */
-		break;
-	}
-	fe->tuner_priv = state;
-	mutex_unlock(&mxl5007t_list_mutex);
-
-	memcpy(&fe->ops.tuner_ops, &mxl5007t_tuner_ops,
-	       sizeof(struct dvb_tuner_ops));
-
-	return fe;
-fail:
-	mutex_unlock(&mxl5007t_list_mutex);
-
-	mxl5007t_release(fe);
-	return NULL;
-}
-EXPORT_SYMBOL_GPL(mxl5007t_attach);
-MODULE_DESCRIPTION("MaxLinear MxL5007T Silicon IC tuner driver");
-MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
-MODULE_LICENSE("GPL");
-MODULE_VERSION("0.2");
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/common/tuners/mxl5007t.h b/drivers/media/common/tuners/mxl5007t.h
deleted file mode 100644
index aa3eea0..0000000
--- a/drivers/media/common/tuners/mxl5007t.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- *  mxl5007t.h - driver for the MaxLinear MxL5007T silicon tuner
- *
- *  Copyright (C) 2008 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 __MXL5007T_H__
-#define __MXL5007T_H__
-
-#include "dvb_frontend.h"
-
-/* ------------------------------------------------------------------------- */
-
-enum mxl5007t_if_freq {
-	MxL_IF_4_MHZ,      /*  4000000 */
-	MxL_IF_4_5_MHZ,    /*  4500000 */
-	MxL_IF_4_57_MHZ,   /*  4570000 */
-	MxL_IF_5_MHZ,      /*  5000000 */
-	MxL_IF_5_38_MHZ,   /*  5380000 */
-	MxL_IF_6_MHZ,      /*  6000000 */
-	MxL_IF_6_28_MHZ,   /*  6280000 */
-	MxL_IF_9_1915_MHZ, /*  9191500 */
-	MxL_IF_35_25_MHZ,  /* 35250000 */
-	MxL_IF_36_15_MHZ,  /* 36150000 */
-	MxL_IF_44_MHZ,     /* 44000000 */
-};
-
-enum mxl5007t_xtal_freq {
-	MxL_XTAL_16_MHZ,      /* 16000000 */
-	MxL_XTAL_20_MHZ,      /* 20000000 */
-	MxL_XTAL_20_25_MHZ,   /* 20250000 */
-	MxL_XTAL_20_48_MHZ,   /* 20480000 */
-	MxL_XTAL_24_MHZ,      /* 24000000 */
-	MxL_XTAL_25_MHZ,      /* 25000000 */
-	MxL_XTAL_25_14_MHZ,   /* 25140000 */
-	MxL_XTAL_27_MHZ,      /* 27000000 */
-	MxL_XTAL_28_8_MHZ,    /* 28800000 */
-	MxL_XTAL_32_MHZ,      /* 32000000 */
-	MxL_XTAL_40_MHZ,      /* 40000000 */
-	MxL_XTAL_44_MHZ,      /* 44000000 */
-	MxL_XTAL_48_MHZ,      /* 48000000 */
-	MxL_XTAL_49_3811_MHZ, /* 49381100 */
-};
-
-enum mxl5007t_clkout_amp {
-	MxL_CLKOUT_AMP_0_94V = 0,
-	MxL_CLKOUT_AMP_0_53V = 1,
-	MxL_CLKOUT_AMP_0_37V = 2,
-	MxL_CLKOUT_AMP_0_28V = 3,
-	MxL_CLKOUT_AMP_0_23V = 4,
-	MxL_CLKOUT_AMP_0_20V = 5,
-	MxL_CLKOUT_AMP_0_17V = 6,
-	MxL_CLKOUT_AMP_0_15V = 7,
-};
-
-struct mxl5007t_config {
-	s32 if_diff_out_level;
-	enum mxl5007t_clkout_amp clk_out_amp;
-	enum mxl5007t_xtal_freq xtal_freq_hz;
-	enum mxl5007t_if_freq if_freq_hz;
-	unsigned int invert_if:1;
-	unsigned int loop_thru_enable:1;
-	unsigned int clk_out_enable:1;
-};
-
-#if defined(CONFIG_MEDIA_TUNER_MXL5007T) || (defined(CONFIG_MEDIA_TUNER_MXL5007T_MODULE) && defined(MODULE))
-extern struct dvb_frontend *mxl5007t_attach(struct dvb_frontend *fe,
-					    struct i2c_adapter *i2c, u8 addr,
-					    struct mxl5007t_config *cfg);
-#else
-static inline struct dvb_frontend *mxl5007t_attach(struct dvb_frontend *fe,
-						   struct i2c_adapter *i2c,
-						   u8 addr,
-						   struct mxl5007t_config *cfg)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif
-
-#endif /* __MXL5007T_H__ */
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
-
diff --git a/drivers/media/common/tuners/qt1010.c b/drivers/media/common/tuners/qt1010.c
deleted file mode 100644
index 2d79b1f..0000000
--- a/drivers/media/common/tuners/qt1010.c
+++ /dev/null
@@ -1,480 +0,0 @@
-/*
- *  Driver for Quantek QT1010 silicon tuner
- *
- *  Copyright (C) 2006 Antti Palosaari <crope@iki.fi>
- *                     Aapo Tahkola <aet@rasterburn.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 "qt1010.h"
-#include "qt1010_priv.h"
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
-
-#define dprintk(args...) \
-	do { \
-		if (debug) printk(KERN_DEBUG "QT1010: " args); \
-	} while (0)
-
-/* read single register */
-static int qt1010_readreg(struct qt1010_priv *priv, u8 reg, u8 *val)
-{
-	struct i2c_msg msg[2] = {
-		{ .addr = priv->cfg->i2c_address,
-		  .flags = 0, .buf = &reg, .len = 1 },
-		{ .addr = priv->cfg->i2c_address,
-		  .flags = I2C_M_RD, .buf = val, .len = 1 },
-	};
-
-	if (i2c_transfer(priv->i2c, msg, 2) != 2) {
-		printk(KERN_WARNING "qt1010 I2C read failed\n");
-		return -EREMOTEIO;
-	}
-	return 0;
-}
-
-/* write single register */
-static int qt1010_writereg(struct qt1010_priv *priv, u8 reg, u8 val)
-{
-	u8 buf[2] = { reg, val };
-	struct i2c_msg msg = { .addr = priv->cfg->i2c_address,
-			       .flags = 0, .buf = buf, .len = 2 };
-
-	if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
-		printk(KERN_WARNING "qt1010 I2C write failed\n");
-		return -EREMOTEIO;
-	}
-	return 0;
-}
-
-/* dump all registers */
-static void qt1010_dump_regs(struct qt1010_priv *priv)
-{
-	u8 reg, val;
-
-	for (reg = 0; ; reg++) {
-		if (reg % 16 == 0) {
-			if (reg)
-				printk(KERN_CONT "\n");
-			printk(KERN_DEBUG "%02x:", reg);
-		}
-		if (qt1010_readreg(priv, reg, &val) == 0)
-			printk(KERN_CONT " %02x", val);
-		else
-			printk(KERN_CONT " --");
-		if (reg == 0x2f)
-			break;
-	}
-	printk(KERN_CONT "\n");
-}
-
-static int qt1010_set_params(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	struct qt1010_priv *priv;
-	int err;
-	u32 freq, div, mod1, mod2;
-	u8 i, tmpval, reg05;
-	qt1010_i2c_oper_t rd[48] = {
-		{ QT1010_WR, 0x01, 0x80 },
-		{ QT1010_WR, 0x02, 0x3f },
-		{ QT1010_WR, 0x05, 0xff }, /* 02 c write */
-		{ QT1010_WR, 0x06, 0x44 },
-		{ QT1010_WR, 0x07, 0xff }, /* 04 c write */
-		{ QT1010_WR, 0x08, 0x08 },
-		{ QT1010_WR, 0x09, 0xff }, /* 06 c write */
-		{ QT1010_WR, 0x0a, 0xff }, /* 07 c write */
-		{ QT1010_WR, 0x0b, 0xff }, /* 08 c write */
-		{ QT1010_WR, 0x0c, 0xe1 },
-		{ QT1010_WR, 0x1a, 0xff }, /* 10 c write */
-		{ QT1010_WR, 0x1b, 0x00 },
-		{ QT1010_WR, 0x1c, 0x89 },
-		{ QT1010_WR, 0x11, 0xff }, /* 13 c write */
-		{ QT1010_WR, 0x12, 0xff }, /* 14 c write */
-		{ QT1010_WR, 0x22, 0xff }, /* 15 c write */
-		{ QT1010_WR, 0x1e, 0x00 },
-		{ QT1010_WR, 0x1e, 0xd0 },
-		{ QT1010_RD, 0x22, 0xff }, /* 16 c read */
-		{ QT1010_WR, 0x1e, 0x00 },
-		{ QT1010_RD, 0x05, 0xff }, /* 20 c read */
-		{ QT1010_RD, 0x22, 0xff }, /* 21 c read */
-		{ QT1010_WR, 0x23, 0xd0 },
-		{ QT1010_WR, 0x1e, 0x00 },
-		{ QT1010_WR, 0x1e, 0xe0 },
-		{ QT1010_RD, 0x23, 0xff }, /* 25 c read */
-		{ QT1010_RD, 0x23, 0xff }, /* 26 c read */
-		{ QT1010_WR, 0x1e, 0x00 },
-		{ QT1010_WR, 0x24, 0xd0 },
-		{ QT1010_WR, 0x1e, 0x00 },
-		{ QT1010_WR, 0x1e, 0xf0 },
-		{ QT1010_RD, 0x24, 0xff }, /* 31 c read */
-		{ QT1010_WR, 0x1e, 0x00 },
-		{ QT1010_WR, 0x14, 0x7f },
-		{ QT1010_WR, 0x15, 0x7f },
-		{ QT1010_WR, 0x05, 0xff }, /* 35 c write */
-		{ QT1010_WR, 0x06, 0x00 },
-		{ QT1010_WR, 0x15, 0x1f },
-		{ QT1010_WR, 0x16, 0xff },
-		{ QT1010_WR, 0x18, 0xff },
-		{ QT1010_WR, 0x1f, 0xff }, /* 40 c write */
-		{ QT1010_WR, 0x20, 0xff }, /* 41 c write */
-		{ QT1010_WR, 0x21, 0x53 },
-		{ QT1010_WR, 0x25, 0xff }, /* 43 c write */
-		{ QT1010_WR, 0x26, 0x15 },
-		{ QT1010_WR, 0x00, 0xff }, /* 45 c write */
-		{ QT1010_WR, 0x02, 0x00 },
-		{ QT1010_WR, 0x01, 0x00 }
-	};
-
-#define FREQ1 32000000 /* 32 MHz */
-#define FREQ2  4000000 /* 4 MHz Quartz oscillator in the stick? */
-
-	priv = fe->tuner_priv;
-	freq = c->frequency;
-	div = (freq + QT1010_OFFSET) / QT1010_STEP;
-	freq = (div * QT1010_STEP) - QT1010_OFFSET;
-	mod1 = (freq + QT1010_OFFSET) % FREQ1;
-	mod2 = (freq + QT1010_OFFSET) % FREQ2;
-	priv->frequency = freq;
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */
-
-	/* reg 05 base value */
-	if      (freq < 290000000) reg05 = 0x14; /* 290 MHz */
-	else if (freq < 610000000) reg05 = 0x34; /* 610 MHz */
-	else if (freq < 802000000) reg05 = 0x54; /* 802 MHz */
-	else                       reg05 = 0x74;
-
-	/* 0x5 */
-	rd[2].val = reg05;
-
-	/* 07 - set frequency: 32 MHz scale */
-	rd[4].val = (freq + QT1010_OFFSET) / FREQ1;
-
-	/* 09 - changes every 8/24 MHz */
-	if (mod1 < 8000000) rd[6].val = 0x1d;
-	else                rd[6].val = 0x1c;
-
-	/* 0a - set frequency: 4 MHz scale (max 28 MHz) */
-	if      (mod1 < 1*FREQ2) rd[7].val = 0x09; /*  +0 MHz */
-	else if (mod1 < 2*FREQ2) rd[7].val = 0x08; /*  +4 MHz */
-	else if (mod1 < 3*FREQ2) rd[7].val = 0x0f; /*  +8 MHz */
-	else if (mod1 < 4*FREQ2) rd[7].val = 0x0e; /* +12 MHz */
-	else if (mod1 < 5*FREQ2) rd[7].val = 0x0d; /* +16 MHz */
-	else if (mod1 < 6*FREQ2) rd[7].val = 0x0c; /* +20 MHz */
-	else if (mod1 < 7*FREQ2) rd[7].val = 0x0b; /* +24 MHz */
-	else                     rd[7].val = 0x0a; /* +28 MHz */
-
-	/* 0b - changes every 2/2 MHz */
-	if (mod2 < 2000000) rd[8].val = 0x45;
-	else                rd[8].val = 0x44;
-
-	/* 1a - set frequency: 125 kHz scale (max 3875 kHz)*/
-	tmpval = 0x78; /* byte, overflows intentionally */
-	rd[10].val = tmpval-((mod2/QT1010_STEP)*0x08);
-
-	/* 11 */
-	rd[13].val = 0xfd; /* TODO: correct value calculation */
-
-	/* 12 */
-	rd[14].val = 0x91; /* TODO: correct value calculation */
-
-	/* 22 */
-	if      (freq < 450000000) rd[15].val = 0xd0; /* 450 MHz */
-	else if (freq < 482000000) rd[15].val = 0xd1; /* 482 MHz */
-	else if (freq < 514000000) rd[15].val = 0xd4; /* 514 MHz */
-	else if (freq < 546000000) rd[15].val = 0xd7; /* 546 MHz */
-	else if (freq < 610000000) rd[15].val = 0xda; /* 610 MHz */
-	else                       rd[15].val = 0xd0;
-
-	/* 05 */
-	rd[35].val = (reg05 & 0xf0);
-
-	/* 1f */
-	if      (mod1 <  8000000) tmpval = 0x00;
-	else if (mod1 < 12000000) tmpval = 0x01;
-	else if (mod1 < 16000000) tmpval = 0x02;
-	else if (mod1 < 24000000) tmpval = 0x03;
-	else if (mod1 < 28000000) tmpval = 0x04;
-	else                      tmpval = 0x05;
-	rd[40].val = (priv->reg1f_init_val + 0x0e + tmpval);
-
-	/* 20 */
-	if      (mod1 <  8000000) tmpval = 0x00;
-	else if (mod1 < 12000000) tmpval = 0x01;
-	else if (mod1 < 20000000) tmpval = 0x02;
-	else if (mod1 < 24000000) tmpval = 0x03;
-	else if (mod1 < 28000000) tmpval = 0x04;
-	else                      tmpval = 0x05;
-	rd[41].val = (priv->reg20_init_val + 0x0d + tmpval);
-
-	/* 25 */
-	rd[43].val = priv->reg25_init_val;
-
-	/* 00 */
-	rd[45].val = 0x92; /* TODO: correct value calculation */
-
-	dprintk("freq:%u 05:%02x 07:%02x 09:%02x 0a:%02x 0b:%02x " \
-		"1a:%02x 11:%02x 12:%02x 22:%02x 05:%02x 1f:%02x " \
-		"20:%02x 25:%02x 00:%02x", \
-		freq, rd[2].val, rd[4].val, rd[6].val, rd[7].val, rd[8].val, \
-		rd[10].val, rd[13].val, rd[14].val, rd[15].val, rd[35].val, \
-		rd[40].val, rd[41].val, rd[43].val, rd[45].val);
-
-	for (i = 0; i < ARRAY_SIZE(rd); i++) {
-		if (rd[i].oper == QT1010_WR) {
-			err = qt1010_writereg(priv, rd[i].reg, rd[i].val);
-		} else { /* read is required to proper locking */
-			err = qt1010_readreg(priv, rd[i].reg, &tmpval);
-		}
-		if (err) return err;
-	}
-
-	if (debug)
-		qt1010_dump_regs(priv);
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */
-
-	return 0;
-}
-
-static int qt1010_init_meas1(struct qt1010_priv *priv,
-			     u8 oper, u8 reg, u8 reg_init_val, u8 *retval)
-{
-	u8 i, val1, val2;
-	int err;
-
-	qt1010_i2c_oper_t i2c_data[] = {
-		{ QT1010_WR, reg, reg_init_val },
-		{ QT1010_WR, 0x1e, 0x00 },
-		{ QT1010_WR, 0x1e, oper },
-		{ QT1010_RD, reg, 0xff }
-	};
-
-	for (i = 0; i < ARRAY_SIZE(i2c_data); i++) {
-		if (i2c_data[i].oper == QT1010_WR) {
-			err = qt1010_writereg(priv, i2c_data[i].reg,
-					      i2c_data[i].val);
-		} else {
-			err = qt1010_readreg(priv, i2c_data[i].reg, &val2);
-		}
-		if (err) return err;
-	}
-
-	do {
-		val1 = val2;
-		err = qt1010_readreg(priv, reg, &val2);
-		if (err) return err;
-		dprintk("compare reg:%02x %02x %02x", reg, val1, val2);
-	} while (val1 != val2);
-	*retval = val1;
-
-	return qt1010_writereg(priv, 0x1e, 0x00);
-}
-
-static u8 qt1010_init_meas2(struct qt1010_priv *priv,
-			    u8 reg_init_val, u8 *retval)
-{
-	u8 i, val;
-	int err;
-	qt1010_i2c_oper_t i2c_data[] = {
-		{ QT1010_WR, 0x07, reg_init_val },
-		{ QT1010_WR, 0x22, 0xd0 },
-		{ QT1010_WR, 0x1e, 0x00 },
-		{ QT1010_WR, 0x1e, 0xd0 },
-		{ QT1010_RD, 0x22, 0xff },
-		{ QT1010_WR, 0x1e, 0x00 },
-		{ QT1010_WR, 0x22, 0xff }
-	};
-	for (i = 0; i < ARRAY_SIZE(i2c_data); i++) {
-		if (i2c_data[i].oper == QT1010_WR) {
-			err = qt1010_writereg(priv, i2c_data[i].reg,
-					      i2c_data[i].val);
-		} else {
-			err = qt1010_readreg(priv, i2c_data[i].reg, &val);
-		}
-		if (err) return err;
-	}
-	*retval = val;
-	return 0;
-}
-
-static int qt1010_init(struct dvb_frontend *fe)
-{
-	struct qt1010_priv *priv = fe->tuner_priv;
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	int err = 0;
-	u8 i, tmpval, *valptr = NULL;
-
-	qt1010_i2c_oper_t i2c_data[] = {
-		{ QT1010_WR, 0x01, 0x80 },
-		{ QT1010_WR, 0x0d, 0x84 },
-		{ QT1010_WR, 0x0e, 0xb7 },
-		{ QT1010_WR, 0x2a, 0x23 },
-		{ QT1010_WR, 0x2c, 0xdc },
-		{ QT1010_M1, 0x25, 0x40 }, /* get reg 25 init value */
-		{ QT1010_M1, 0x81, 0xff }, /* get reg 25 init value */
-		{ QT1010_WR, 0x2b, 0x70 },
-		{ QT1010_WR, 0x2a, 0x23 },
-		{ QT1010_M1, 0x26, 0x08 },
-		{ QT1010_M1, 0x82, 0xff },
-		{ QT1010_WR, 0x05, 0x14 },
-		{ QT1010_WR, 0x06, 0x44 },
-		{ QT1010_WR, 0x07, 0x28 },
-		{ QT1010_WR, 0x08, 0x0b },
-		{ QT1010_WR, 0x11, 0xfd },
-		{ QT1010_M1, 0x22, 0x0d },
-		{ QT1010_M1, 0xd0, 0xff },
-		{ QT1010_WR, 0x06, 0x40 },
-		{ QT1010_WR, 0x16, 0xf0 },
-		{ QT1010_WR, 0x02, 0x38 },
-		{ QT1010_WR, 0x03, 0x18 },
-		{ QT1010_WR, 0x20, 0xe0 },
-		{ QT1010_M1, 0x1f, 0x20 }, /* get reg 1f init value */
-		{ QT1010_M1, 0x84, 0xff }, /* get reg 1f init value */
-		{ QT1010_RD, 0x20, 0x20 }, /* get reg 20 init value */
-		{ QT1010_WR, 0x03, 0x19 },
-		{ QT1010_WR, 0x02, 0x3f },
-		{ QT1010_WR, 0x21, 0x53 },
-		{ QT1010_RD, 0x21, 0xff },
-		{ QT1010_WR, 0x11, 0xfd },
-		{ QT1010_WR, 0x05, 0x34 },
-		{ QT1010_WR, 0x06, 0x44 },
-		{ QT1010_WR, 0x08, 0x08 }
-	};
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */
-
-	for (i = 0; i < ARRAY_SIZE(i2c_data); i++) {
-		switch (i2c_data[i].oper) {
-		case QT1010_WR:
-			err = qt1010_writereg(priv, i2c_data[i].reg,
-					      i2c_data[i].val);
-			break;
-		case QT1010_RD:
-			if (i2c_data[i].val == 0x20)
-				valptr = &priv->reg20_init_val;
-			else
-				valptr = &tmpval;
-			err = qt1010_readreg(priv, i2c_data[i].reg, valptr);
-			break;
-		case QT1010_M1:
-			if (i2c_data[i].val == 0x25)
-				valptr = &priv->reg25_init_val;
-			else if (i2c_data[i].val == 0x1f)
-				valptr = &priv->reg1f_init_val;
-			else
-				valptr = &tmpval;
-			err = qt1010_init_meas1(priv, i2c_data[i+1].reg,
-						i2c_data[i].reg,
-						i2c_data[i].val, valptr);
-			i++;
-			break;
-		}
-		if (err) return err;
-	}
-
-	for (i = 0x31; i < 0x3a; i++) /* 0x31 - 0x39 */
-		if ((err = qt1010_init_meas2(priv, i, &tmpval)))
-			return err;
-
-	c->frequency = 545000000; /* Sigmatek DVB-110 545000000 */
-				      /* MSI Megasky 580 GL861 533000000 */
-	return qt1010_set_params(fe);
-}
-
-static int qt1010_release(struct dvb_frontend *fe)
-{
-	kfree(fe->tuner_priv);
-	fe->tuner_priv = NULL;
-	return 0;
-}
-
-static int qt1010_get_frequency(struct dvb_frontend *fe, u32 *frequency)
-{
-	struct qt1010_priv *priv = fe->tuner_priv;
-	*frequency = priv->frequency;
-	return 0;
-}
-
-static int qt1010_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
-{
-	*frequency = 36125000;
-	return 0;
-}
-
-static const struct dvb_tuner_ops qt1010_tuner_ops = {
-	.info = {
-		.name           = "Quantek QT1010",
-		.frequency_min  = QT1010_MIN_FREQ,
-		.frequency_max  = QT1010_MAX_FREQ,
-		.frequency_step = QT1010_STEP,
-	},
-
-	.release       = qt1010_release,
-	.init          = qt1010_init,
-	/* TODO: implement sleep */
-
-	.set_params    = qt1010_set_params,
-	.get_frequency = qt1010_get_frequency,
-	.get_if_frequency = qt1010_get_if_frequency,
-};
-
-struct dvb_frontend * qt1010_attach(struct dvb_frontend *fe,
-				    struct i2c_adapter *i2c,
-				    struct qt1010_config *cfg)
-{
-	struct qt1010_priv *priv = NULL;
-	u8 id;
-
-	priv = kzalloc(sizeof(struct qt1010_priv), GFP_KERNEL);
-	if (priv == NULL)
-		return NULL;
-
-	priv->cfg = cfg;
-	priv->i2c = i2c;
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c_gate */
-
-
-	/* Try to detect tuner chip. Probably this is not correct register. */
-	if (qt1010_readreg(priv, 0x29, &id) != 0 || (id != 0x39)) {
-		kfree(priv);
-		return NULL;
-	}
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */
-
-	printk(KERN_INFO "Quantek QT1010 successfully identified.\n");
-	memcpy(&fe->ops.tuner_ops, &qt1010_tuner_ops,
-	       sizeof(struct dvb_tuner_ops));
-
-	fe->tuner_priv = priv;
-	return fe;
-}
-EXPORT_SYMBOL(qt1010_attach);
-
-MODULE_DESCRIPTION("Quantek QT1010 silicon tuner driver");
-MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
-MODULE_AUTHOR("Aapo Tahkola <aet@rasterburn.org>");
-MODULE_VERSION("0.1");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/common/tuners/qt1010.h b/drivers/media/common/tuners/qt1010.h
deleted file mode 100644
index 807fb7b..0000000
--- a/drivers/media/common/tuners/qt1010.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- *  Driver for Quantek QT1010 silicon tuner
- *
- *  Copyright (C) 2006 Antti Palosaari <crope@iki.fi>
- *                     Aapo Tahkola <aet@rasterburn.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 QT1010_H
-#define QT1010_H
-
-#include "dvb_frontend.h"
-
-struct qt1010_config {
-	u8 i2c_address;
-};
-
-/**
- * Attach a qt1010 tuner to the supplied frontend structure.
- *
- * @param fe   frontend to attach to
- * @param i2c  i2c adapter to use
- * @param cfg  tuner hw based configuration
- * @return fe  pointer on success, NULL on failure
- */
-#if defined(CONFIG_MEDIA_TUNER_QT1010) || (defined(CONFIG_MEDIA_TUNER_QT1010_MODULE) && defined(MODULE))
-extern struct dvb_frontend *qt1010_attach(struct dvb_frontend *fe,
-					  struct i2c_adapter *i2c,
-					  struct qt1010_config *cfg);
-#else
-static inline struct dvb_frontend *qt1010_attach(struct dvb_frontend *fe,
-						 struct i2c_adapter *i2c,
-						 struct qt1010_config *cfg)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif // CONFIG_MEDIA_TUNER_QT1010
-
-#endif
diff --git a/drivers/media/common/tuners/qt1010_priv.h b/drivers/media/common/tuners/qt1010_priv.h
deleted file mode 100644
index 2c42d3f..0000000
--- a/drivers/media/common/tuners/qt1010_priv.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- *  Driver for Quantek QT1010 silicon tuner
- *
- *  Copyright (C) 2006 Antti Palosaari <crope@iki.fi>
- *                     Aapo Tahkola <aet@rasterburn.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 QT1010_PRIV_H
-#define QT1010_PRIV_H
-
-/*
-reg def meaning
-=== === =======
-00  00  ?
-01  a0  ? operation start/stop; start=80, stop=00
-02  00  ?
-03  19  ?
-04  00  ?
-05  00  ? maybe band selection
-06  00  ?
-07  2b  set frequency: 32 MHz scale, n*32 MHz
-08  0b  ?
-09  10  ? changes every 8/24 MHz; values 1d/1c
-0a  08  set frequency: 4 MHz scale, n*4 MHz
-0b  41  ? changes every 2/2 MHz; values 45/45
-0c  e1  ?
-0d  94  ?
-0e  b6  ?
-0f  2c  ?
-10  10  ?
-11  f1  ? maybe device specified adjustment
-12  11  ? maybe device specified adjustment
-13  3f  ?
-14  1f  ?
-15  3f  ?
-16  ff  ?
-17  ff  ?
-18  f7  ?
-19  80  ?
-1a  d0  set frequency: 125 kHz scale, n*125 kHz
-1b  00  ?
-1c  89  ?
-1d  00  ?
-1e  00  ? looks like operation register; write cmd here, read result from 1f-26
-1f  20  ? chip initialization
-20  e0  ? chip initialization
-21  20  ?
-22  d0  ?
-23  d0  ?
-24  d0  ?
-25  40  ? chip initialization
-26  08  ?
-27  29  ?
-28  55  ?
-29  39  ?
-2a  13  ?
-2b  01  ?
-2c  ea  ?
-2d  00  ?
-2e  00  ? not used?
-2f  00  ? not used?
-*/
-
-#define QT1010_STEP         125000 /*  125 kHz used by Windows drivers,
-				      hw could be more precise but we don't
-				      know how to use */
-#define QT1010_MIN_FREQ   48000000 /*   48 MHz */
-#define QT1010_MAX_FREQ  860000000 /*  860 MHz */
-#define QT1010_OFFSET   1246000000 /* 1246 MHz */
-
-#define QT1010_WR 0
-#define QT1010_RD 1
-#define QT1010_M1 3
-
-typedef struct {
-	u8 oper, reg, val;
-} qt1010_i2c_oper_t;
-
-struct qt1010_priv {
-	struct qt1010_config *cfg;
-	struct i2c_adapter   *i2c;
-
-	u8 reg1f_init_val;
-	u8 reg20_init_val;
-	u8 reg25_init_val;
-
-	u32 frequency;
-};
-
-#endif
diff --git a/drivers/media/common/tuners/tda18212.c b/drivers/media/common/tuners/tda18212.c
deleted file mode 100644
index 602c2e3..0000000
--- a/drivers/media/common/tuners/tda18212.c
+++ /dev/null
@@ -1,326 +0,0 @@
-/*
- * NXP TDA18212HN silicon tuner driver
- *
- * Copyright (C) 2011 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.,
- *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include "tda18212.h"
-
-struct tda18212_priv {
-	struct tda18212_config *cfg;
-	struct i2c_adapter *i2c;
-
-	u32 if_frequency;
-};
-
-#define dbg(fmt, arg...)					\
-do {								\
-	if (debug)						\
-		pr_info("%s: " fmt, __func__, ##arg);		\
-} while (0)
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
-
-/* write multiple registers */
-static int tda18212_wr_regs(struct tda18212_priv *priv, u8 reg, u8 *val,
-	int len)
-{
-	int ret;
-	u8 buf[len+1];
-	struct i2c_msg msg[1] = {
-		{
-			.addr = priv->cfg->i2c_address,
-			.flags = 0,
-			.len = sizeof(buf),
-			.buf = buf,
-		}
-	};
-
-	buf[0] = reg;
-	memcpy(&buf[1], val, len);
-
-	ret = i2c_transfer(priv->i2c, msg, 1);
-	if (ret == 1) {
-		ret = 0;
-	} else {
-		pr_warn("i2c wr failed ret:%d reg:%02x len:%d\n",
-			ret, reg, len);
-		ret = -EREMOTEIO;
-	}
-	return ret;
-}
-
-/* read multiple registers */
-static int tda18212_rd_regs(struct tda18212_priv *priv, u8 reg, u8 *val,
-	int len)
-{
-	int ret;
-	u8 buf[len];
-	struct i2c_msg msg[2] = {
-		{
-			.addr = priv->cfg->i2c_address,
-			.flags = 0,
-			.len = 1,
-			.buf = &reg,
-		}, {
-			.addr = priv->cfg->i2c_address,
-			.flags = I2C_M_RD,
-			.len = sizeof(buf),
-			.buf = buf,
-		}
-	};
-
-	ret = i2c_transfer(priv->i2c, msg, 2);
-	if (ret == 2) {
-		memcpy(val, buf, len);
-		ret = 0;
-	} else {
-		pr_warn("i2c rd failed ret:%d reg:%02x len:%d\n",
-			ret, reg, len);
-		ret = -EREMOTEIO;
-	}
-
-	return ret;
-}
-
-/* write single register */
-static int tda18212_wr_reg(struct tda18212_priv *priv, u8 reg, u8 val)
-{
-	return tda18212_wr_regs(priv, reg, &val, 1);
-}
-
-/* read single register */
-static int tda18212_rd_reg(struct tda18212_priv *priv, u8 reg, u8 *val)
-{
-	return tda18212_rd_regs(priv, reg, val, 1);
-}
-
-#if 0 /* keep, useful when developing driver */
-static void tda18212_dump_regs(struct tda18212_priv *priv)
-{
-	int i;
-	u8 buf[256];
-
-	#define TDA18212_RD_LEN 32
-	for (i = 0; i < sizeof(buf); i += TDA18212_RD_LEN)
-		tda18212_rd_regs(priv, i, &buf[i], TDA18212_RD_LEN);
-
-	print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 32, 1, buf,
-		sizeof(buf), true);
-
-	return;
-}
-#endif
-
-static int tda18212_set_params(struct dvb_frontend *fe)
-{
-	struct tda18212_priv *priv = fe->tuner_priv;
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	int ret, i;
-	u32 if_khz;
-	u8 buf[9];
-	#define DVBT_6   0
-	#define DVBT_7   1
-	#define DVBT_8   2
-	#define DVBT2_6  3
-	#define DVBT2_7  4
-	#define DVBT2_8  5
-	#define DVBC_6   6
-	#define DVBC_8   7
-	static const u8 bw_params[][3] = {
-		     /* reg:   0f    13    23 */
-		[DVBT_6]  = { 0xb3, 0x20, 0x03 },
-		[DVBT_7]  = { 0xb3, 0x31, 0x01 },
-		[DVBT_8]  = { 0xb3, 0x22, 0x01 },
-		[DVBT2_6] = { 0xbc, 0x20, 0x03 },
-		[DVBT2_7] = { 0xbc, 0x72, 0x03 },
-		[DVBT2_8] = { 0xbc, 0x22, 0x01 },
-		[DVBC_6]  = { 0x92, 0x50, 0x03 },
-		[DVBC_8]  = { 0x92, 0x53, 0x03 },
-	};
-
-	dbg("delsys=%d RF=%d BW=%d\n",
-	    c->delivery_system, c->frequency, c->bandwidth_hz);
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
-
-	switch (c->delivery_system) {
-	case SYS_DVBT:
-		switch (c->bandwidth_hz) {
-		case 6000000:
-			if_khz = priv->cfg->if_dvbt_6;
-			i = DVBT_6;
-			break;
-		case 7000000:
-			if_khz = priv->cfg->if_dvbt_7;
-			i = DVBT_7;
-			break;
-		case 8000000:
-			if_khz = priv->cfg->if_dvbt_8;
-			i = DVBT_8;
-			break;
-		default:
-			ret = -EINVAL;
-			goto error;
-		}
-		break;
-	case SYS_DVBT2:
-		switch (c->bandwidth_hz) {
-		case 6000000:
-			if_khz = priv->cfg->if_dvbt2_6;
-			i = DVBT2_6;
-			break;
-		case 7000000:
-			if_khz = priv->cfg->if_dvbt2_7;
-			i = DVBT2_7;
-			break;
-		case 8000000:
-			if_khz = priv->cfg->if_dvbt2_8;
-			i = DVBT2_8;
-			break;
-		default:
-			ret = -EINVAL;
-			goto error;
-		}
-		break;
-	case SYS_DVBC_ANNEX_A:
-	case SYS_DVBC_ANNEX_C:
-		if_khz = priv->cfg->if_dvbc;
-		i = DVBC_8;
-		break;
-	default:
-		ret = -EINVAL;
-		goto error;
-	}
-
-	ret = tda18212_wr_reg(priv, 0x23, bw_params[i][2]);
-	if (ret)
-		goto error;
-
-	ret = tda18212_wr_reg(priv, 0x06, 0x00);
-	if (ret)
-		goto error;
-
-	ret = tda18212_wr_reg(priv, 0x0f, bw_params[i][0]);
-	if (ret)
-		goto error;
-
-	buf[0] = 0x02;
-	buf[1] = bw_params[i][1];
-	buf[2] = 0x03; /* default value */
-	buf[3] = DIV_ROUND_CLOSEST(if_khz, 50);
-	buf[4] = ((c->frequency / 1000) >> 16) & 0xff;
-	buf[5] = ((c->frequency / 1000) >>  8) & 0xff;
-	buf[6] = ((c->frequency / 1000) >>  0) & 0xff;
-	buf[7] = 0xc1;
-	buf[8] = 0x01;
-	ret = tda18212_wr_regs(priv, 0x12, buf, sizeof(buf));
-	if (ret)
-		goto error;
-
-	/* actual IF rounded as it is on register */
-	priv->if_frequency = buf[3] * 50 * 1000;
-
-exit:
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
-
-	return ret;
-
-error:
-	dbg("failed:%d\n", ret);
-	goto exit;
-}
-
-static int tda18212_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
-{
-	struct tda18212_priv *priv = fe->tuner_priv;
-
-	*frequency = priv->if_frequency;
-
-	return 0;
-}
-
-static int tda18212_release(struct dvb_frontend *fe)
-{
-	kfree(fe->tuner_priv);
-	fe->tuner_priv = NULL;
-	return 0;
-}
-
-static const struct dvb_tuner_ops tda18212_tuner_ops = {
-	.info = {
-		.name           = "NXP TDA18212",
-
-		.frequency_min  =  48000000,
-		.frequency_max  = 864000000,
-		.frequency_step =      1000,
-	},
-
-	.release       = tda18212_release,
-
-	.set_params    = tda18212_set_params,
-	.get_if_frequency = tda18212_get_if_frequency,
-};
-
-struct dvb_frontend *tda18212_attach(struct dvb_frontend *fe,
-	struct i2c_adapter *i2c, struct tda18212_config *cfg)
-{
-	struct tda18212_priv *priv = NULL;
-	int ret;
-	u8 val;
-
-	priv = kzalloc(sizeof(struct tda18212_priv), GFP_KERNEL);
-	if (priv == NULL)
-		return NULL;
-
-	priv->cfg = cfg;
-	priv->i2c = i2c;
-	fe->tuner_priv = priv;
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
-
-	/* check if the tuner is there */
-	ret = tda18212_rd_reg(priv, 0x00, &val);
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
-
-	dbg("ret:%d chip ID:%02x\n", ret, val);
-	if (ret || val != 0xc7) {
-		kfree(priv);
-		return NULL;
-	}
-
-	pr_info("NXP TDA18212HN successfully identified\n");
-
-	memcpy(&fe->ops.tuner_ops, &tda18212_tuner_ops,
-		sizeof(struct dvb_tuner_ops));
-
-	return fe;
-}
-EXPORT_SYMBOL(tda18212_attach);
-
-MODULE_DESCRIPTION("NXP TDA18212HN silicon tuner driver");
-MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/common/tuners/tda18212.h b/drivers/media/common/tuners/tda18212.h
deleted file mode 100644
index 9bd5da4..0000000
--- a/drivers/media/common/tuners/tda18212.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * NXP TDA18212HN silicon tuner driver
- *
- * Copyright (C) 2011 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.,
- *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef TDA18212_H
-#define TDA18212_H
-
-#include "dvb_frontend.h"
-
-struct tda18212_config {
-	u8 i2c_address;
-
-	u16 if_dvbt_6;
-	u16 if_dvbt_7;
-	u16 if_dvbt_8;
-	u16 if_dvbt2_5;
-	u16 if_dvbt2_6;
-	u16 if_dvbt2_7;
-	u16 if_dvbt2_8;
-	u16 if_dvbc;
-};
-
-#if defined(CONFIG_MEDIA_TUNER_TDA18212) || \
-	(defined(CONFIG_MEDIA_TUNER_TDA18212_MODULE) && defined(MODULE))
-extern struct dvb_frontend *tda18212_attach(struct dvb_frontend *fe,
-	struct i2c_adapter *i2c, struct tda18212_config *cfg);
-#else
-static inline struct dvb_frontend *tda18212_attach(struct dvb_frontend *fe,
-	struct i2c_adapter *i2c, struct tda18212_config *cfg)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif
-
-#endif
diff --git a/drivers/media/common/tuners/tda18218.c b/drivers/media/common/tuners/tda18218.c
deleted file mode 100644
index dfb3a83..0000000
--- a/drivers/media/common/tuners/tda18218.c
+++ /dev/null
@@ -1,342 +0,0 @@
-/*
- * NXP TDA18218HN silicon tuner driver
- *
- * Copyright (C) 2010 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 "tda18218.h"
-#include "tda18218_priv.h"
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
-
-/* write multiple registers */
-static int tda18218_wr_regs(struct tda18218_priv *priv, u8 reg, u8 *val, u8 len)
-{
-	int ret = 0;
-	u8 buf[1+len], quotient, remainder, i, msg_len, msg_len_max;
-	struct i2c_msg msg[1] = {
-		{
-			.addr = priv->cfg->i2c_address,
-			.flags = 0,
-			.buf = buf,
-		}
-	};
-
-	msg_len_max = priv->cfg->i2c_wr_max - 1;
-	quotient = len / msg_len_max;
-	remainder = len % msg_len_max;
-	msg_len = msg_len_max;
-	for (i = 0; (i <= quotient && remainder); i++) {
-		if (i == quotient)  /* set len of the last msg */
-			msg_len = remainder;
-
-		msg[0].len = msg_len + 1;
-		buf[0] = reg + i * msg_len_max;
-		memcpy(&buf[1], &val[i * msg_len_max], msg_len);
-
-		ret = i2c_transfer(priv->i2c, msg, 1);
-		if (ret != 1)
-			break;
-	}
-
-	if (ret == 1) {
-		ret = 0;
-	} else {
-		warn("i2c wr failed ret:%d reg:%02x len:%d", ret, reg, len);
-		ret = -EREMOTEIO;
-	}
-
-	return ret;
-}
-
-/* read multiple registers */
-static int tda18218_rd_regs(struct tda18218_priv *priv, u8 reg, u8 *val, u8 len)
-{
-	int ret;
-	u8 buf[reg+len]; /* we must start read always from reg 0x00 */
-	struct i2c_msg msg[2] = {
-		{
-			.addr = priv->cfg->i2c_address,
-			.flags = 0,
-			.len = 1,
-			.buf = "\x00",
-		}, {
-			.addr = priv->cfg->i2c_address,
-			.flags = I2C_M_RD,
-			.len = sizeof(buf),
-			.buf = buf,
-		}
-	};
-
-	ret = i2c_transfer(priv->i2c, msg, 2);
-	if (ret == 2) {
-		memcpy(val, &buf[reg], len);
-		ret = 0;
-	} else {
-		warn("i2c rd failed ret:%d reg:%02x len:%d", ret, reg, len);
-		ret = -EREMOTEIO;
-	}
-
-	return ret;
-}
-
-/* write single register */
-static int tda18218_wr_reg(struct tda18218_priv *priv, u8 reg, u8 val)
-{
-	return tda18218_wr_regs(priv, reg, &val, 1);
-}
-
-/* read single register */
-
-static int tda18218_rd_reg(struct tda18218_priv *priv, u8 reg, u8 *val)
-{
-	return tda18218_rd_regs(priv, reg, val, 1);
-}
-
-static int tda18218_set_params(struct dvb_frontend *fe)
-{
-	struct tda18218_priv *priv = fe->tuner_priv;
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	u32 bw = c->bandwidth_hz;
-	int ret;
-	u8 buf[3], i, BP_Filter, LP_Fc;
-	u32 LO_Frac;
-	/* TODO: find out correct AGC algorithm */
-	u8 agc[][2] = {
-		{ R20_AGC11, 0x60 },
-		{ R23_AGC21, 0x02 },
-		{ R20_AGC11, 0xa0 },
-		{ R23_AGC21, 0x09 },
-		{ R20_AGC11, 0xe0 },
-		{ R23_AGC21, 0x0c },
-		{ R20_AGC11, 0x40 },
-		{ R23_AGC21, 0x01 },
-		{ R20_AGC11, 0x80 },
-		{ R23_AGC21, 0x08 },
-		{ R20_AGC11, 0xc0 },
-		{ R23_AGC21, 0x0b },
-		{ R24_AGC22, 0x1c },
-		{ R24_AGC22, 0x0c },
-	};
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
-
-	/* low-pass filter cut-off frequency */
-	if (bw <= 6000000) {
-		LP_Fc = 0;
-		priv->if_frequency = 3000000;
-	} else if (bw <= 7000000) {
-		LP_Fc = 1;
-		priv->if_frequency = 3500000;
-	} else {
-		LP_Fc = 2;
-		priv->if_frequency = 4000000;
-	}
-
-	LO_Frac = c->frequency + priv->if_frequency;
-
-	/* band-pass filter */
-	if (LO_Frac < 188000000)
-		BP_Filter = 3;
-	else if (LO_Frac < 253000000)
-		BP_Filter = 4;
-	else if (LO_Frac < 343000000)
-		BP_Filter = 5;
-	else
-		BP_Filter = 6;
-
-	buf[0] = (priv->regs[R1A_IF1] & ~7) | BP_Filter; /* BP_Filter */
-	buf[1] = (priv->regs[R1B_IF2] & ~3) | LP_Fc; /* LP_Fc */
-	buf[2] = priv->regs[R1C_AGC2B];
-	ret = tda18218_wr_regs(priv, R1A_IF1, buf, 3);
-	if (ret)
-		goto error;
-
-	buf[0] = (LO_Frac / 1000) >> 12; /* LO_Frac_0 */
-	buf[1] = (LO_Frac / 1000) >> 4; /* LO_Frac_1 */
-	buf[2] = (LO_Frac / 1000) << 4 |
-		(priv->regs[R0C_MD5] & 0x0f); /* LO_Frac_2 */
-	ret = tda18218_wr_regs(priv, R0A_MD3, buf, 3);
-	if (ret)
-		goto error;
-
-	buf[0] = priv->regs[R0F_MD8] | (1 << 6); /* Freq_prog_Start */
-	ret = tda18218_wr_regs(priv, R0F_MD8, buf, 1);
-	if (ret)
-		goto error;
-
-	buf[0] = priv->regs[R0F_MD8] & ~(1 << 6); /* Freq_prog_Start */
-	ret = tda18218_wr_regs(priv, R0F_MD8, buf, 1);
-	if (ret)
-		goto error;
-
-	/* trigger AGC */
-	for (i = 0; i < ARRAY_SIZE(agc); i++) {
-		ret = tda18218_wr_reg(priv, agc[i][0], agc[i][1]);
-		if (ret)
-			goto error;
-	}
-
-error:
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
-
-	if (ret)
-		dbg("%s: failed ret:%d", __func__, ret);
-
-	return ret;
-}
-
-static int tda18218_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
-{
-	struct tda18218_priv *priv = fe->tuner_priv;
-	*frequency = priv->if_frequency;
-	dbg("%s: if=%d", __func__, *frequency);
-	return 0;
-}
-
-static int tda18218_sleep(struct dvb_frontend *fe)
-{
-	struct tda18218_priv *priv = fe->tuner_priv;
-	int ret;
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
-
-	/* standby */
-	ret = tda18218_wr_reg(priv, R17_PD1, priv->regs[R17_PD1] | (1 << 0));
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
-
-	if (ret)
-		dbg("%s: failed ret:%d", __func__, ret);
-
-	return ret;
-}
-
-static int tda18218_init(struct dvb_frontend *fe)
-{
-	struct tda18218_priv *priv = fe->tuner_priv;
-	int ret;
-
-	/* TODO: calibrations */
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
-
-	ret = tda18218_wr_regs(priv, R00_ID, priv->regs, TDA18218_NUM_REGS);
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
-
-	if (ret)
-		dbg("%s: failed ret:%d", __func__, ret);
-
-	return ret;
-}
-
-static int tda18218_release(struct dvb_frontend *fe)
-{
-	kfree(fe->tuner_priv);
-	fe->tuner_priv = NULL;
-	return 0;
-}
-
-static const struct dvb_tuner_ops tda18218_tuner_ops = {
-	.info = {
-		.name           = "NXP TDA18218",
-
-		.frequency_min  = 174000000,
-		.frequency_max  = 864000000,
-		.frequency_step =      1000,
-	},
-
-	.release       = tda18218_release,
-	.init          = tda18218_init,
-	.sleep         = tda18218_sleep,
-
-	.set_params    = tda18218_set_params,
-
-	.get_if_frequency = tda18218_get_if_frequency,
-};
-
-struct dvb_frontend *tda18218_attach(struct dvb_frontend *fe,
-	struct i2c_adapter *i2c, struct tda18218_config *cfg)
-{
-	struct tda18218_priv *priv = NULL;
-	u8 val;
-	int ret;
-	/* chip default registers values */
-	static u8 def_regs[] = {
-		0xc0, 0x88, 0x00, 0x8e, 0x03, 0x00, 0x00, 0xd0, 0x00, 0x40,
-		0x00, 0x00, 0x07, 0xff, 0x84, 0x09, 0x00, 0x13, 0x00, 0x00,
-		0x01, 0x84, 0x09, 0xf0, 0x19, 0x0a, 0x8e, 0x69, 0x98, 0x01,
-		0x00, 0x58, 0x10, 0x40, 0x8c, 0x00, 0x0c, 0x48, 0x85, 0xc9,
-		0xa7, 0x00, 0x00, 0x00, 0x30, 0x81, 0x80, 0x00, 0x39, 0x00,
-		0x8a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0xf6
-	};
-
-	priv = kzalloc(sizeof(struct tda18218_priv), GFP_KERNEL);
-	if (priv == NULL)
-		return NULL;
-
-	priv->cfg = cfg;
-	priv->i2c = i2c;
-	fe->tuner_priv = priv;
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
-
-	/* check if the tuner is there */
-	ret = tda18218_rd_reg(priv, R00_ID, &val);
-	dbg("%s: ret:%d chip ID:%02x", __func__, ret, val);
-	if (ret || val != def_regs[R00_ID]) {
-		kfree(priv);
-		return NULL;
-	}
-
-	info("NXP TDA18218HN successfully identified.");
-
-	memcpy(&fe->ops.tuner_ops, &tda18218_tuner_ops,
-		sizeof(struct dvb_tuner_ops));
-	memcpy(priv->regs, def_regs, sizeof(def_regs));
-
-	/* loop-through enabled chip default register values */
-	if (priv->cfg->loop_through) {
-		priv->regs[R17_PD1] = 0xb0;
-		priv->regs[R18_PD2] = 0x59;
-	}
-
-	/* standby */
-	ret = tda18218_wr_reg(priv, R17_PD1, priv->regs[R17_PD1] | (1 << 0));
-	if (ret)
-		dbg("%s: failed ret:%d", __func__, ret);
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
-
-	return fe;
-}
-EXPORT_SYMBOL(tda18218_attach);
-
-MODULE_DESCRIPTION("NXP TDA18218HN silicon tuner driver");
-MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/common/tuners/tda18218.h b/drivers/media/common/tuners/tda18218.h
deleted file mode 100644
index b4180d1..0000000
--- a/drivers/media/common/tuners/tda18218.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * NXP TDA18218HN silicon tuner driver
- *
- * Copyright (C) 2010 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 TDA18218_H
-#define TDA18218_H
-
-#include "dvb_frontend.h"
-
-struct tda18218_config {
-	u8 i2c_address;
-	u8 i2c_wr_max;
-	u8 loop_through:1;
-};
-
-#if defined(CONFIG_MEDIA_TUNER_TDA18218) || \
-	(defined(CONFIG_MEDIA_TUNER_TDA18218_MODULE) && defined(MODULE))
-extern struct dvb_frontend *tda18218_attach(struct dvb_frontend *fe,
-	struct i2c_adapter *i2c, struct tda18218_config *cfg);
-#else
-static inline struct dvb_frontend *tda18218_attach(struct dvb_frontend *fe,
-	struct i2c_adapter *i2c, struct tda18218_config *cfg)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif
-
-#endif
diff --git a/drivers/media/common/tuners/tda18218_priv.h b/drivers/media/common/tuners/tda18218_priv.h
deleted file mode 100644
index dc52b72..0000000
--- a/drivers/media/common/tuners/tda18218_priv.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * NXP TDA18218HN silicon tuner driver
- *
- * Copyright (C) 2010 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 TDA18218_PRIV_H
-#define TDA18218_PRIV_H
-
-#define LOG_PREFIX "tda18218"
-
-#undef dbg
-#define dbg(f, arg...) \
-	if (debug) \
-		printk(KERN_DEBUG   LOG_PREFIX": " f "\n" , ## arg)
-#undef err
-#define err(f, arg...)  printk(KERN_ERR     LOG_PREFIX": " f "\n" , ## arg)
-#undef info
-#define info(f, arg...) printk(KERN_INFO    LOG_PREFIX": " f "\n" , ## arg)
-#undef warn
-#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg)
-
-#define R00_ID         0x00	/* ID byte */
-#define R01_R1         0x01	/* Read byte 1 */
-#define R02_R2         0x02	/* Read byte 2 */
-#define R03_R3         0x03	/* Read byte 3 */
-#define R04_R4         0x04	/* Read byte 4 */
-#define R05_R5         0x05	/* Read byte 5 */
-#define R06_R6         0x06	/* Read byte 6 */
-#define R07_MD1        0x07	/* Main divider byte 1 */
-#define R08_PSM1       0x08	/* PSM byte 1 */
-#define R09_MD2        0x09	/* Main divider byte 2 */
-#define R0A_MD3        0x0a	/* Main divider byte 1 */
-#define R0B_MD4        0x0b	/* Main divider byte 4 */
-#define R0C_MD5        0x0c	/* Main divider byte 5 */
-#define R0D_MD6        0x0d	/* Main divider byte 6 */
-#define R0E_MD7        0x0e	/* Main divider byte 7 */
-#define R0F_MD8        0x0f	/* Main divider byte 8 */
-#define R10_CD1        0x10	/* Call divider byte 1 */
-#define R11_CD2        0x11	/* Call divider byte 2 */
-#define R12_CD3        0x12	/* Call divider byte 3 */
-#define R13_CD4        0x13	/* Call divider byte 4 */
-#define R14_CD5        0x14	/* Call divider byte 5 */
-#define R15_CD6        0x15	/* Call divider byte 6 */
-#define R16_CD7        0x16	/* Call divider byte 7 */
-#define R17_PD1        0x17	/* Power-down byte 1 */
-#define R18_PD2        0x18	/* Power-down byte 2 */
-#define R19_XTOUT      0x19	/* XTOUT byte */
-#define R1A_IF1        0x1a	/* IF byte 1 */
-#define R1B_IF2        0x1b	/* IF byte 2 */
-#define R1C_AGC2B      0x1c	/* AGC2b byte */
-#define R1D_PSM2       0x1d	/* PSM byte 2 */
-#define R1E_PSM3       0x1e	/* PSM byte 3 */
-#define R1F_PSM4       0x1f	/* PSM byte 4 */
-#define R20_AGC11      0x20	/* AGC1 byte 1 */
-#define R21_AGC12      0x21	/* AGC1 byte 2 */
-#define R22_AGC13      0x22	/* AGC1 byte 3 */
-#define R23_AGC21      0x23	/* AGC2 byte 1 */
-#define R24_AGC22      0x24	/* AGC2 byte 2 */
-#define R25_AAGC       0x25	/* Analog AGC byte */
-#define R26_RC         0x26	/* RC byte */
-#define R27_RSSI       0x27	/* RSSI byte */
-#define R28_IRCAL1     0x28	/* IR CAL byte 1 */
-#define R29_IRCAL2     0x29	/* IR CAL byte 2 */
-#define R2A_IRCAL3     0x2a	/* IR CAL byte 3 */
-#define R2B_IRCAL4     0x2b	/* IR CAL byte 4 */
-#define R2C_RFCAL1     0x2c	/* RF CAL byte 1 */
-#define R2D_RFCAL2     0x2d	/* RF CAL byte 2 */
-#define R2E_RFCAL3     0x2e	/* RF CAL byte 3 */
-#define R2F_RFCAL4     0x2f	/* RF CAL byte 4 */
-#define R30_RFCAL5     0x30	/* RF CAL byte 5 */
-#define R31_RFCAL6     0x31	/* RF CAL byte 6 */
-#define R32_RFCAL7     0x32	/* RF CAL byte 7 */
-#define R33_RFCAL8     0x33	/* RF CAL byte 8 */
-#define R34_RFCAL9     0x34	/* RF CAL byte 9 */
-#define R35_RFCAL10    0x35	/* RF CAL byte 10 */
-#define R36_RFCALRAM1  0x36	/* RF CAL RAM byte 1 */
-#define R37_RFCALRAM2  0x37	/* RF CAL RAM byte 2 */
-#define R38_MARGIN     0x38	/* Margin byte */
-#define R39_FMAX1      0x39	/* Fmax byte 1 */
-#define R3A_FMAX2      0x3a	/* Fmax byte 2 */
-
-#define TDA18218_NUM_REGS 59
-
-struct tda18218_priv {
-	struct tda18218_config *cfg;
-	struct i2c_adapter *i2c;
-
-	u32 if_frequency;
-
-	u8 regs[TDA18218_NUM_REGS];
-};
-
-#endif
diff --git a/drivers/media/common/tuners/tda18271-common.c b/drivers/media/common/tuners/tda18271-common.c
deleted file mode 100644
index 39c6457..0000000
--- a/drivers/media/common/tuners/tda18271-common.c
+++ /dev/null
@@ -1,703 +0,0 @@
-/*
-    tda18271-common.c - driver for the Philips / NXP TDA18271 silicon tuner
-
-    Copyright (C) 2007, 2008 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 "tda18271-priv.h"
-
-static int tda18271_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
-{
-	struct tda18271_priv *priv = fe->tuner_priv;
-	enum tda18271_i2c_gate gate;
-	int ret = 0;
-
-	switch (priv->gate) {
-	case TDA18271_GATE_DIGITAL:
-	case TDA18271_GATE_ANALOG:
-		gate = priv->gate;
-		break;
-	case TDA18271_GATE_AUTO:
-	default:
-		switch (priv->mode) {
-		case TDA18271_DIGITAL:
-			gate = TDA18271_GATE_DIGITAL;
-			break;
-		case TDA18271_ANALOG:
-		default:
-			gate = TDA18271_GATE_ANALOG;
-			break;
-		}
-	}
-
-	switch (gate) {
-	case TDA18271_GATE_ANALOG:
-		if (fe->ops.analog_ops.i2c_gate_ctrl)
-			ret = fe->ops.analog_ops.i2c_gate_ctrl(fe, enable);
-		break;
-	case TDA18271_GATE_DIGITAL:
-		if (fe->ops.i2c_gate_ctrl)
-			ret = fe->ops.i2c_gate_ctrl(fe, enable);
-		break;
-	default:
-		ret = -EINVAL;
-		break;
-	}
-
-	return ret;
-};
-
-/*---------------------------------------------------------------------*/
-
-static void tda18271_dump_regs(struct dvb_frontend *fe, int extended)
-{
-	struct tda18271_priv *priv = fe->tuner_priv;
-	unsigned char *regs = priv->tda18271_regs;
-
-	tda_reg("=== TDA18271 REG DUMP ===\n");
-	tda_reg("ID_BYTE            = 0x%02x\n", 0xff & regs[R_ID]);
-	tda_reg("THERMO_BYTE        = 0x%02x\n", 0xff & regs[R_TM]);
-	tda_reg("POWER_LEVEL_BYTE   = 0x%02x\n", 0xff & regs[R_PL]);
-	tda_reg("EASY_PROG_BYTE_1   = 0x%02x\n", 0xff & regs[R_EP1]);
-	tda_reg("EASY_PROG_BYTE_2   = 0x%02x\n", 0xff & regs[R_EP2]);
-	tda_reg("EASY_PROG_BYTE_3   = 0x%02x\n", 0xff & regs[R_EP3]);
-	tda_reg("EASY_PROG_BYTE_4   = 0x%02x\n", 0xff & regs[R_EP4]);
-	tda_reg("EASY_PROG_BYTE_5   = 0x%02x\n", 0xff & regs[R_EP5]);
-	tda_reg("CAL_POST_DIV_BYTE  = 0x%02x\n", 0xff & regs[R_CPD]);
-	tda_reg("CAL_DIV_BYTE_1     = 0x%02x\n", 0xff & regs[R_CD1]);
-	tda_reg("CAL_DIV_BYTE_2     = 0x%02x\n", 0xff & regs[R_CD2]);
-	tda_reg("CAL_DIV_BYTE_3     = 0x%02x\n", 0xff & regs[R_CD3]);
-	tda_reg("MAIN_POST_DIV_BYTE = 0x%02x\n", 0xff & regs[R_MPD]);
-	tda_reg("MAIN_DIV_BYTE_1    = 0x%02x\n", 0xff & regs[R_MD1]);
-	tda_reg("MAIN_DIV_BYTE_2    = 0x%02x\n", 0xff & regs[R_MD2]);
-	tda_reg("MAIN_DIV_BYTE_3    = 0x%02x\n", 0xff & regs[R_MD3]);
-
-	/* only dump extended regs if DBG_ADV is set */
-	if (!(tda18271_debug & DBG_ADV))
-		return;
-
-	/* W indicates write-only registers.
-	 * Register dump for write-only registers shows last value written. */
-
-	tda_reg("EXTENDED_BYTE_1    = 0x%02x\n", 0xff & regs[R_EB1]);
-	tda_reg("EXTENDED_BYTE_2    = 0x%02x\n", 0xff & regs[R_EB2]);
-	tda_reg("EXTENDED_BYTE_3    = 0x%02x\n", 0xff & regs[R_EB3]);
-	tda_reg("EXTENDED_BYTE_4    = 0x%02x\n", 0xff & regs[R_EB4]);
-	tda_reg("EXTENDED_BYTE_5    = 0x%02x\n", 0xff & regs[R_EB5]);
-	tda_reg("EXTENDED_BYTE_6    = 0x%02x\n", 0xff & regs[R_EB6]);
-	tda_reg("EXTENDED_BYTE_7    = 0x%02x\n", 0xff & regs[R_EB7]);
-	tda_reg("EXTENDED_BYTE_8    = 0x%02x\n", 0xff & regs[R_EB8]);
-	tda_reg("EXTENDED_BYTE_9  W = 0x%02x\n", 0xff & regs[R_EB9]);
-	tda_reg("EXTENDED_BYTE_10   = 0x%02x\n", 0xff & regs[R_EB10]);
-	tda_reg("EXTENDED_BYTE_11   = 0x%02x\n", 0xff & regs[R_EB11]);
-	tda_reg("EXTENDED_BYTE_12   = 0x%02x\n", 0xff & regs[R_EB12]);
-	tda_reg("EXTENDED_BYTE_13   = 0x%02x\n", 0xff & regs[R_EB13]);
-	tda_reg("EXTENDED_BYTE_14   = 0x%02x\n", 0xff & regs[R_EB14]);
-	tda_reg("EXTENDED_BYTE_15   = 0x%02x\n", 0xff & regs[R_EB15]);
-	tda_reg("EXTENDED_BYTE_16 W = 0x%02x\n", 0xff & regs[R_EB16]);
-	tda_reg("EXTENDED_BYTE_17 W = 0x%02x\n", 0xff & regs[R_EB17]);
-	tda_reg("EXTENDED_BYTE_18   = 0x%02x\n", 0xff & regs[R_EB18]);
-	tda_reg("EXTENDED_BYTE_19 W = 0x%02x\n", 0xff & regs[R_EB19]);
-	tda_reg("EXTENDED_BYTE_20 W = 0x%02x\n", 0xff & regs[R_EB20]);
-	tda_reg("EXTENDED_BYTE_21   = 0x%02x\n", 0xff & regs[R_EB21]);
-	tda_reg("EXTENDED_BYTE_22   = 0x%02x\n", 0xff & regs[R_EB22]);
-	tda_reg("EXTENDED_BYTE_23   = 0x%02x\n", 0xff & regs[R_EB23]);
-}
-
-int tda18271_read_regs(struct dvb_frontend *fe)
-{
-	struct tda18271_priv *priv = fe->tuner_priv;
-	unsigned char *regs = priv->tda18271_regs;
-	unsigned char buf = 0x00;
-	int ret;
-	struct i2c_msg msg[] = {
-		{ .addr = priv->i2c_props.addr, .flags = 0,
-		  .buf = &buf, .len = 1 },
-		{ .addr = priv->i2c_props.addr, .flags = I2C_M_RD,
-		  .buf = regs, .len = 16 }
-	};
-
-	tda18271_i2c_gate_ctrl(fe, 1);
-
-	/* read all registers */
-	ret = i2c_transfer(priv->i2c_props.adap, msg, 2);
-
-	tda18271_i2c_gate_ctrl(fe, 0);
-
-	if (ret != 2)
-		tda_err("ERROR: i2c_transfer returned: %d\n", ret);
-
-	if (tda18271_debug & DBG_REG)
-		tda18271_dump_regs(fe, 0);
-
-	return (ret == 2 ? 0 : ret);
-}
-
-int tda18271_read_extended(struct dvb_frontend *fe)
-{
-	struct tda18271_priv *priv = fe->tuner_priv;
-	unsigned char *regs = priv->tda18271_regs;
-	unsigned char regdump[TDA18271_NUM_REGS];
-	unsigned char buf = 0x00;
-	int ret, i;
-	struct i2c_msg msg[] = {
-		{ .addr = priv->i2c_props.addr, .flags = 0,
-		  .buf = &buf, .len = 1 },
-		{ .addr = priv->i2c_props.addr, .flags = I2C_M_RD,
-		  .buf = regdump, .len = TDA18271_NUM_REGS }
-	};
-
-	tda18271_i2c_gate_ctrl(fe, 1);
-
-	/* read all registers */
-	ret = i2c_transfer(priv->i2c_props.adap, msg, 2);
-
-	tda18271_i2c_gate_ctrl(fe, 0);
-
-	if (ret != 2)
-		tda_err("ERROR: i2c_transfer returned: %d\n", ret);
-
-	for (i = 0; i < TDA18271_NUM_REGS; i++) {
-		/* don't update write-only registers */
-		if ((i != R_EB9)  &&
-		    (i != R_EB16) &&
-		    (i != R_EB17) &&
-		    (i != R_EB19) &&
-		    (i != R_EB20))
-		regs[i] = regdump[i];
-	}
-
-	if (tda18271_debug & DBG_REG)
-		tda18271_dump_regs(fe, 1);
-
-	return (ret == 2 ? 0 : ret);
-}
-
-int tda18271_write_regs(struct dvb_frontend *fe, int idx, int len)
-{
-	struct tda18271_priv *priv = fe->tuner_priv;
-	unsigned char *regs = priv->tda18271_regs;
-	unsigned char buf[TDA18271_NUM_REGS + 1];
-	struct i2c_msg msg = { .addr = priv->i2c_props.addr, .flags = 0,
-			       .buf = buf };
-	int i, ret = 1, max;
-
-	BUG_ON((len == 0) || (idx + len > sizeof(buf)));
-
-
-	switch (priv->small_i2c) {
-	case TDA18271_03_BYTE_CHUNK_INIT:
-		max = 3;
-		break;
-	case TDA18271_08_BYTE_CHUNK_INIT:
-		max = 8;
-		break;
-	case TDA18271_16_BYTE_CHUNK_INIT:
-		max = 16;
-		break;
-	case TDA18271_39_BYTE_CHUNK_INIT:
-	default:
-		max = 39;
-	}
-
-	tda18271_i2c_gate_ctrl(fe, 1);
-	while (len) {
-		if (max > len)
-			max = len;
-
-		buf[0] = idx;
-		for (i = 1; i <= max; i++)
-			buf[i] = regs[idx - 1 + i];
-
-		msg.len = max + 1;
-
-		/* write registers */
-		ret = i2c_transfer(priv->i2c_props.adap, &msg, 1);
-		if (ret != 1)
-			break;
-
-		idx += max;
-		len -= max;
-	}
-	tda18271_i2c_gate_ctrl(fe, 0);
-
-	if (ret != 1)
-		tda_err("ERROR: idx = 0x%x, len = %d, "
-			"i2c_transfer returned: %d\n", idx, max, ret);
-
-	return (ret == 1 ? 0 : ret);
-}
-
-/*---------------------------------------------------------------------*/
-
-int tda18271_charge_pump_source(struct dvb_frontend *fe,
-				enum tda18271_pll pll, int force)
-{
-	struct tda18271_priv *priv = fe->tuner_priv;
-	unsigned char *regs = priv->tda18271_regs;
-
-	int r_cp = (pll == TDA18271_CAL_PLL) ? R_EB7 : R_EB4;
-
-	regs[r_cp] &= ~0x20;
-	regs[r_cp] |= ((force & 1) << 5);
-
-	return tda18271_write_regs(fe, r_cp, 1);
-}
-
-int tda18271_init_regs(struct dvb_frontend *fe)
-{
-	struct tda18271_priv *priv = fe->tuner_priv;
-	unsigned char *regs = priv->tda18271_regs;
-
-	tda_dbg("initializing registers for device @ %d-%04x\n",
-		i2c_adapter_id(priv->i2c_props.adap),
-		priv->i2c_props.addr);
-
-	/* initialize registers */
-	switch (priv->id) {
-	case TDA18271HDC1:
-		regs[R_ID]   = 0x83;
-		break;
-	case TDA18271HDC2:
-		regs[R_ID]   = 0x84;
-		break;
-	};
-
-	regs[R_TM]   = 0x08;
-	regs[R_PL]   = 0x80;
-	regs[R_EP1]  = 0xc6;
-	regs[R_EP2]  = 0xdf;
-	regs[R_EP3]  = 0x16;
-	regs[R_EP4]  = 0x60;
-	regs[R_EP5]  = 0x80;
-	regs[R_CPD]  = 0x80;
-	regs[R_CD1]  = 0x00;
-	regs[R_CD2]  = 0x00;
-	regs[R_CD3]  = 0x00;
-	regs[R_MPD]  = 0x00;
-	regs[R_MD1]  = 0x00;
-	regs[R_MD2]  = 0x00;
-	regs[R_MD3]  = 0x00;
-
-	switch (priv->id) {
-	case TDA18271HDC1:
-		regs[R_EB1]  = 0xff;
-		break;
-	case TDA18271HDC2:
-		regs[R_EB1]  = 0xfc;
-		break;
-	};
-
-	regs[R_EB2]  = 0x01;
-	regs[R_EB3]  = 0x84;
-	regs[R_EB4]  = 0x41;
-	regs[R_EB5]  = 0x01;
-	regs[R_EB6]  = 0x84;
-	regs[R_EB7]  = 0x40;
-	regs[R_EB8]  = 0x07;
-	regs[R_EB9]  = 0x00;
-	regs[R_EB10] = 0x00;
-	regs[R_EB11] = 0x96;
-
-	switch (priv->id) {
-	case TDA18271HDC1:
-		regs[R_EB12] = 0x0f;
-		break;
-	case TDA18271HDC2:
-		regs[R_EB12] = 0x33;
-		break;
-	};
-
-	regs[R_EB13] = 0xc1;
-	regs[R_EB14] = 0x00;
-	regs[R_EB15] = 0x8f;
-	regs[R_EB16] = 0x00;
-	regs[R_EB17] = 0x00;
-
-	switch (priv->id) {
-	case TDA18271HDC1:
-		regs[R_EB18] = 0x00;
-		break;
-	case TDA18271HDC2:
-		regs[R_EB18] = 0x8c;
-		break;
-	};
-
-	regs[R_EB19] = 0x00;
-	regs[R_EB20] = 0x20;
-
-	switch (priv->id) {
-	case TDA18271HDC1:
-		regs[R_EB21] = 0x33;
-		break;
-	case TDA18271HDC2:
-		regs[R_EB21] = 0xb3;
-		break;
-	};
-
-	regs[R_EB22] = 0x48;
-	regs[R_EB23] = 0xb0;
-
-	tda18271_write_regs(fe, 0x00, TDA18271_NUM_REGS);
-
-	/* setup agc1 gain */
-	regs[R_EB17] = 0x00;
-	tda18271_write_regs(fe, R_EB17, 1);
-	regs[R_EB17] = 0x03;
-	tda18271_write_regs(fe, R_EB17, 1);
-	regs[R_EB17] = 0x43;
-	tda18271_write_regs(fe, R_EB17, 1);
-	regs[R_EB17] = 0x4c;
-	tda18271_write_regs(fe, R_EB17, 1);
-
-	/* setup agc2 gain */
-	if ((priv->id) == TDA18271HDC1) {
-		regs[R_EB20] = 0xa0;
-		tda18271_write_regs(fe, R_EB20, 1);
-		regs[R_EB20] = 0xa7;
-		tda18271_write_regs(fe, R_EB20, 1);
-		regs[R_EB20] = 0xe7;
-		tda18271_write_regs(fe, R_EB20, 1);
-		regs[R_EB20] = 0xec;
-		tda18271_write_regs(fe, R_EB20, 1);
-	}
-
-	/* image rejection calibration */
-
-	/* low-band */
-	regs[R_EP3] = 0x1f;
-	regs[R_EP4] = 0x66;
-	regs[R_EP5] = 0x81;
-	regs[R_CPD] = 0xcc;
-	regs[R_CD1] = 0x6c;
-	regs[R_CD2] = 0x00;
-	regs[R_CD3] = 0x00;
-	regs[R_MPD] = 0xcd;
-	regs[R_MD1] = 0x77;
-	regs[R_MD2] = 0x08;
-	regs[R_MD3] = 0x00;
-
-	tda18271_write_regs(fe, R_EP3, 11);
-
-	if ((priv->id) == TDA18271HDC2) {
-		/* main pll cp source on */
-		tda18271_charge_pump_source(fe, TDA18271_MAIN_PLL, 1);
-		msleep(1);
-
-		/* main pll cp source off */
-		tda18271_charge_pump_source(fe, TDA18271_MAIN_PLL, 0);
-	}
-
-	msleep(5); /* pll locking */
-
-	/* launch detector */
-	tda18271_write_regs(fe, R_EP1, 1);
-	msleep(5); /* wanted low measurement */
-
-	regs[R_EP5] = 0x85;
-	regs[R_CPD] = 0xcb;
-	regs[R_CD1] = 0x66;
-	regs[R_CD2] = 0x70;
-
-	tda18271_write_regs(fe, R_EP3, 7);
-	msleep(5); /* pll locking */
-
-	/* launch optimization algorithm */
-	tda18271_write_regs(fe, R_EP2, 1);
-	msleep(30); /* image low optimization completion */
-
-	/* mid-band */
-	regs[R_EP5] = 0x82;
-	regs[R_CPD] = 0xa8;
-	regs[R_CD2] = 0x00;
-	regs[R_MPD] = 0xa9;
-	regs[R_MD1] = 0x73;
-	regs[R_MD2] = 0x1a;
-
-	tda18271_write_regs(fe, R_EP3, 11);
-	msleep(5); /* pll locking */
-
-	/* launch detector */
-	tda18271_write_regs(fe, R_EP1, 1);
-	msleep(5); /* wanted mid measurement */
-
-	regs[R_EP5] = 0x86;
-	regs[R_CPD] = 0xa8;
-	regs[R_CD1] = 0x66;
-	regs[R_CD2] = 0xa0;
-
-	tda18271_write_regs(fe, R_EP3, 7);
-	msleep(5); /* pll locking */
-
-	/* launch optimization algorithm */
-	tda18271_write_regs(fe, R_EP2, 1);
-	msleep(30); /* image mid optimization completion */
-
-	/* high-band */
-	regs[R_EP5] = 0x83;
-	regs[R_CPD] = 0x98;
-	regs[R_CD1] = 0x65;
-	regs[R_CD2] = 0x00;
-	regs[R_MPD] = 0x99;
-	regs[R_MD1] = 0x71;
-	regs[R_MD2] = 0xcd;
-
-	tda18271_write_regs(fe, R_EP3, 11);
-	msleep(5); /* pll locking */
-
-	/* launch detector */
-	tda18271_write_regs(fe, R_EP1, 1);
-	msleep(5); /* wanted high measurement */
-
-	regs[R_EP5] = 0x87;
-	regs[R_CD1] = 0x65;
-	regs[R_CD2] = 0x50;
-
-	tda18271_write_regs(fe, R_EP3, 7);
-	msleep(5); /* pll locking */
-
-	/* launch optimization algorithm */
-	tda18271_write_regs(fe, R_EP2, 1);
-	msleep(30); /* image high optimization completion */
-
-	/* return to normal mode */
-	regs[R_EP4] = 0x64;
-	tda18271_write_regs(fe, R_EP4, 1);
-
-	/* synchronize */
-	tda18271_write_regs(fe, R_EP1, 1);
-
-	return 0;
-}
-
-/*---------------------------------------------------------------------*/
-
-/*
- *  Standby modes, EP3 [7:5]
- *
- *  | SM  || SM_LT || SM_XT || mode description
- *  |=====\\=======\\=======\\===================================
- *  |  0  ||   0   ||   0   || normal mode
- *  |-----||-------||-------||-----------------------------------
- *  |     ||       ||       || standby mode w/ slave tuner output
- *  |  1  ||   0   ||   0   || & loop thru & xtal oscillator on
- *  |-----||-------||-------||-----------------------------------
- *  |  1  ||   1   ||   0   || standby mode w/ xtal oscillator on
- *  |-----||-------||-------||-----------------------------------
- *  |  1  ||   1   ||   1   || power off
- *
- */
-
-int tda18271_set_standby_mode(struct dvb_frontend *fe,
-			      int sm, int sm_lt, int sm_xt)
-{
-	struct tda18271_priv *priv = fe->tuner_priv;
-	unsigned char *regs = priv->tda18271_regs;
-
-	if (tda18271_debug & DBG_ADV)
-		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);
-
-	return tda18271_write_regs(fe, R_EP3, 1);
-}
-
-/*---------------------------------------------------------------------*/
-
-int tda18271_calc_main_pll(struct dvb_frontend *fe, u32 freq)
-{
-	/* sets main post divider & divider bytes, but does not write them */
-	struct tda18271_priv *priv = fe->tuner_priv;
-	unsigned char *regs = priv->tda18271_regs;
-	u8 d, pd;
-	u32 div;
-
-	int ret = tda18271_lookup_pll_map(fe, MAIN_PLL, &freq, &pd, &d);
-	if (tda_fail(ret))
-		goto fail;
-
-	regs[R_MPD]   = (0x7f & pd);
-
-	div =  ((d * (freq / 1000)) << 7) / 125;
-
-	regs[R_MD1]   = 0x7f & (div >> 16);
-	regs[R_MD2]   = 0xff & (div >> 8);
-	regs[R_MD3]   = 0xff & div;
-fail:
-	return ret;
-}
-
-int tda18271_calc_cal_pll(struct dvb_frontend *fe, u32 freq)
-{
-	/* sets cal post divider & divider bytes, but does not write them */
-	struct tda18271_priv *priv = fe->tuner_priv;
-	unsigned char *regs = priv->tda18271_regs;
-	u8 d, pd;
-	u32 div;
-
-	int ret = tda18271_lookup_pll_map(fe, CAL_PLL, &freq, &pd, &d);
-	if (tda_fail(ret))
-		goto fail;
-
-	regs[R_CPD]   = pd;
-
-	div =  ((d * (freq / 1000)) << 7) / 125;
-
-	regs[R_CD1]   = 0x7f & (div >> 16);
-	regs[R_CD2]   = 0xff & (div >> 8);
-	regs[R_CD3]   = 0xff & div;
-fail:
-	return ret;
-}
-
-/*---------------------------------------------------------------------*/
-
-int tda18271_calc_bp_filter(struct dvb_frontend *fe, u32 *freq)
-{
-	/* sets bp filter bits, but does not write them */
-	struct tda18271_priv *priv = fe->tuner_priv;
-	unsigned char *regs = priv->tda18271_regs;
-	u8 val;
-
-	int ret = tda18271_lookup_map(fe, BP_FILTER, freq, &val);
-	if (tda_fail(ret))
-		goto fail;
-
-	regs[R_EP1]  &= ~0x07; /* clear bp filter bits */
-	regs[R_EP1]  |= (0x07 & val);
-fail:
-	return ret;
-}
-
-int tda18271_calc_km(struct dvb_frontend *fe, u32 *freq)
-{
-	/* sets K & M bits, but does not write them */
-	struct tda18271_priv *priv = fe->tuner_priv;
-	unsigned char *regs = priv->tda18271_regs;
-	u8 val;
-
-	int ret = tda18271_lookup_map(fe, RF_CAL_KMCO, freq, &val);
-	if (tda_fail(ret))
-		goto fail;
-
-	regs[R_EB13] &= ~0x7c; /* clear k & m bits */
-	regs[R_EB13] |= (0x7c & val);
-fail:
-	return ret;
-}
-
-int tda18271_calc_rf_band(struct dvb_frontend *fe, u32 *freq)
-{
-	/* sets rf band bits, but does not write them */
-	struct tda18271_priv *priv = fe->tuner_priv;
-	unsigned char *regs = priv->tda18271_regs;
-	u8 val;
-
-	int ret = tda18271_lookup_map(fe, RF_BAND, freq, &val);
-	if (tda_fail(ret))
-		goto fail;
-
-	regs[R_EP2]  &= ~0xe0; /* clear rf band bits */
-	regs[R_EP2]  |= (0xe0 & (val << 5));
-fail:
-	return ret;
-}
-
-int tda18271_calc_gain_taper(struct dvb_frontend *fe, u32 *freq)
-{
-	/* sets gain taper bits, but does not write them */
-	struct tda18271_priv *priv = fe->tuner_priv;
-	unsigned char *regs = priv->tda18271_regs;
-	u8 val;
-
-	int ret = tda18271_lookup_map(fe, GAIN_TAPER, freq, &val);
-	if (tda_fail(ret))
-		goto fail;
-
-	regs[R_EP2]  &= ~0x1f; /* clear gain taper bits */
-	regs[R_EP2]  |= (0x1f & val);
-fail:
-	return ret;
-}
-
-int tda18271_calc_ir_measure(struct dvb_frontend *fe, u32 *freq)
-{
-	/* sets IR Meas bits, but does not write them */
-	struct tda18271_priv *priv = fe->tuner_priv;
-	unsigned char *regs = priv->tda18271_regs;
-	u8 val;
-
-	int ret = tda18271_lookup_map(fe, IR_MEASURE, freq, &val);
-	if (tda_fail(ret))
-		goto fail;
-
-	regs[R_EP5] &= ~0x07;
-	regs[R_EP5] |= (0x07 & val);
-fail:
-	return ret;
-}
-
-int tda18271_calc_rf_cal(struct dvb_frontend *fe, u32 *freq)
-{
-	/* sets rf cal byte (RFC_Cprog), but does not write it */
-	struct tda18271_priv *priv = fe->tuner_priv;
-	unsigned char *regs = priv->tda18271_regs;
-	u8 val;
-
-	int ret = tda18271_lookup_map(fe, RF_CAL, freq, &val);
-	/* The TDA18271HD/C1 rf_cal map lookup is expected to go out of range
-	 * for frequencies above 61.1 MHz.  In these cases, the internal RF
-	 * tracking filters calibration mechanism is used.
-	 *
-	 * There is no need to warn the user about this.
-	 */
-	if (ret < 0)
-		goto fail;
-
-	regs[R_EB14] = val;
-fail:
-	return ret;
-}
-
-int _tda_printk(struct tda18271_priv *state, const char *level,
-		const char *func, const char *fmt, ...)
-{
-	struct va_format vaf;
-	va_list args;
-	int rtn;
-
-	va_start(args, fmt);
-
-	vaf.fmt = fmt;
-	vaf.va = &args;
-
-	if (state)
-		rtn = printk("%s%s: [%d-%04x|%c] %pV",
-			     level, func, i2c_adapter_id(state->i2c_props.adap),
-			     state->i2c_props.addr,
-			     (state->role == TDA18271_MASTER) ? 'M' : 'S',
-			     &vaf);
-	else
-		rtn = printk("%s%s: %pV", level, func, &vaf);
-
-	va_end(args);
-
-	return rtn;
-}
diff --git a/drivers/media/common/tuners/tda18271-fe.c b/drivers/media/common/tuners/tda18271-fe.c
deleted file mode 100644
index 2e67f44..0000000
--- a/drivers/media/common/tuners/tda18271-fe.c
+++ /dev/null
@@ -1,1345 +0,0 @@
-/*
-    tda18271-fe.c - driver for the Philips / NXP TDA18271 silicon tuner
-
-    Copyright (C) 2007, 2008 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/delay.h>
-#include <linux/videodev2.h>
-#include "tda18271-priv.h"
-
-int tda18271_debug;
-module_param_named(debug, tda18271_debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debug level "
-		 "(info=1, map=2, reg=4, adv=8, cal=16 (or-able))");
-
-static int tda18271_cal_on_startup = -1;
-module_param_named(cal, tda18271_cal_on_startup, int, 0644);
-MODULE_PARM_DESC(cal, "perform RF tracking filter calibration on startup");
-
-static DEFINE_MUTEX(tda18271_list_mutex);
-static LIST_HEAD(hybrid_tuner_instance_list);
-
-/*---------------------------------------------------------------------*/
-
-static int tda18271_toggle_output(struct dvb_frontend *fe, int standby)
-{
-	struct tda18271_priv *priv = fe->tuner_priv;
-
-	int ret = tda18271_set_standby_mode(fe, standby ? 1 : 0,
-			priv->output_opt & TDA18271_OUTPUT_LT_OFF ? 1 : 0,
-			priv->output_opt & TDA18271_OUTPUT_XT_OFF ? 1 : 0);
-
-	if (tda_fail(ret))
-		goto fail;
-
-	tda_dbg("%s mode: xtal oscillator %s, slave tuner loop thru %s\n",
-		standby ? "standby" : "active",
-		priv->output_opt & TDA18271_OUTPUT_XT_OFF ? "off" : "on",
-		priv->output_opt & TDA18271_OUTPUT_LT_OFF ? "off" : "on");
-fail:
-	return ret;
-}
-
-/*---------------------------------------------------------------------*/
-
-static inline int charge_pump_source(struct dvb_frontend *fe, int force)
-{
-	struct tda18271_priv *priv = fe->tuner_priv;
-	return tda18271_charge_pump_source(fe,
-					   (priv->role == TDA18271_SLAVE) ?
-					   TDA18271_CAL_PLL :
-					   TDA18271_MAIN_PLL, force);
-}
-
-static inline void tda18271_set_if_notch(struct dvb_frontend *fe)
-{
-	struct tda18271_priv *priv = fe->tuner_priv;
-	unsigned char *regs = priv->tda18271_regs;
-
-	switch (priv->mode) {
-	case TDA18271_ANALOG:
-		regs[R_MPD]  &= ~0x80; /* IF notch = 0 */
-		break;
-	case TDA18271_DIGITAL:
-		regs[R_MPD]  |= 0x80; /* IF notch = 1 */
-		break;
-	}
-}
-
-static int tda18271_channel_configuration(struct dvb_frontend *fe,
-					  struct tda18271_std_map_item *map,
-					  u32 freq, u32 bw)
-{
-	struct tda18271_priv *priv = fe->tuner_priv;
-	unsigned char *regs = priv->tda18271_regs;
-	int ret;
-	u32 N;
-
-	/* update TV broadcast parameters */
-
-	/* set standard */
-	regs[R_EP3]  &= ~0x1f; /* clear std bits */
-	regs[R_EP3]  |= (map->agc_mode << 3) | map->std;
-
-	if (priv->id == TDA18271HDC2) {
-		/* set rfagc to high speed mode */
-		regs[R_EP3] &= ~0x04;
-	}
-
-	/* set cal mode to normal */
-	regs[R_EP4]  &= ~0x03;
-
-	/* update IF output level */
-	regs[R_EP4]  &= ~0x1c; /* clear if level bits */
-	regs[R_EP4]  |= (map->if_lvl << 2);
-
-	/* update FM_RFn */
-	regs[R_EP4]  &= ~0x80;
-	regs[R_EP4]  |= map->fm_rfn << 7;
-
-	/* update rf top / if top */
-	regs[R_EB22]  = 0x00;
-	regs[R_EB22] |= map->rfagc_top;
-	ret = tda18271_write_regs(fe, R_EB22, 1);
-	if (tda_fail(ret))
-		goto fail;
-
-	/* --------------------------------------------------------------- */
-
-	/* disable Power Level Indicator */
-	regs[R_EP1]  |= 0x40;
-
-	/* make sure thermometer is off */
-	regs[R_TM]   &= ~0x10;
-
-	/* frequency dependent parameters */
-
-	tda18271_calc_ir_measure(fe, &freq);
-
-	tda18271_calc_bp_filter(fe, &freq);
-
-	tda18271_calc_rf_band(fe, &freq);
-
-	tda18271_calc_gain_taper(fe, &freq);
-
-	/* --------------------------------------------------------------- */
-
-	/* dual tuner and agc1 extra configuration */
-
-	switch (priv->role) {
-	case TDA18271_MASTER:
-		regs[R_EB1]  |= 0x04; /* main vco */
-		break;
-	case TDA18271_SLAVE:
-		regs[R_EB1]  &= ~0x04; /* cal vco */
-		break;
-	}
-
-	/* agc1 always active */
-	regs[R_EB1]  &= ~0x02;
-
-	/* agc1 has priority on agc2 */
-	regs[R_EB1]  &= ~0x01;
-
-	ret = tda18271_write_regs(fe, R_EB1, 1);
-	if (tda_fail(ret))
-		goto fail;
-
-	/* --------------------------------------------------------------- */
-
-	N = map->if_freq * 1000 + freq;
-
-	switch (priv->role) {
-	case TDA18271_MASTER:
-		tda18271_calc_main_pll(fe, N);
-		tda18271_set_if_notch(fe);
-		tda18271_write_regs(fe, R_MPD, 4);
-		break;
-	case TDA18271_SLAVE:
-		tda18271_calc_cal_pll(fe, N);
-		tda18271_write_regs(fe, R_CPD, 4);
-
-		regs[R_MPD] = regs[R_CPD] & 0x7f;
-		tda18271_set_if_notch(fe);
-		tda18271_write_regs(fe, R_MPD, 1);
-		break;
-	}
-
-	ret = tda18271_write_regs(fe, R_TM, 7);
-	if (tda_fail(ret))
-		goto fail;
-
-	/* force charge pump source */
-	charge_pump_source(fe, 1);
-
-	msleep(1);
-
-	/* return pll to normal operation */
-	charge_pump_source(fe, 0);
-
-	msleep(20);
-
-	if (priv->id == TDA18271HDC2) {
-		/* set rfagc to normal speed mode */
-		if (map->fm_rfn)
-			regs[R_EP3] &= ~0x04;
-		else
-			regs[R_EP3] |= 0x04;
-		ret = tda18271_write_regs(fe, R_EP3, 1);
-	}
-fail:
-	return ret;
-}
-
-static int tda18271_read_thermometer(struct dvb_frontend *fe)
-{
-	struct tda18271_priv *priv = fe->tuner_priv;
-	unsigned char *regs = priv->tda18271_regs;
-	int tm;
-
-	/* switch thermometer on */
-	regs[R_TM]   |= 0x10;
-	tda18271_write_regs(fe, R_TM, 1);
-
-	/* read thermometer info */
-	tda18271_read_regs(fe);
-
-	if ((((regs[R_TM] & 0x0f) == 0x00) && ((regs[R_TM] & 0x20) == 0x20)) ||
-	    (((regs[R_TM] & 0x0f) == 0x08) && ((regs[R_TM] & 0x20) == 0x00))) {
-
-		if ((regs[R_TM] & 0x20) == 0x20)
-			regs[R_TM] &= ~0x20;
-		else
-			regs[R_TM] |= 0x20;
-
-		tda18271_write_regs(fe, R_TM, 1);
-
-		msleep(10); /* temperature sensing */
-
-		/* read thermometer info */
-		tda18271_read_regs(fe);
-	}
-
-	tm = tda18271_lookup_thermometer(fe);
-
-	/* switch thermometer off */
-	regs[R_TM]   &= ~0x10;
-	tda18271_write_regs(fe, R_TM, 1);
-
-	/* set CAL mode to normal */
-	regs[R_EP4]  &= ~0x03;
-	tda18271_write_regs(fe, R_EP4, 1);
-
-	return tm;
-}
-
-/* ------------------------------------------------------------------ */
-
-static int tda18271c2_rf_tracking_filters_correction(struct dvb_frontend *fe,
-						     u32 freq)
-{
-	struct tda18271_priv *priv = fe->tuner_priv;
-	struct tda18271_rf_tracking_filter_cal *map = priv->rf_cal_state;
-	unsigned char *regs = priv->tda18271_regs;
-	int i, ret;
-	u8 tm_current, dc_over_dt, rf_tab;
-	s32 rfcal_comp, approx;
-
-	/* power up */
-	ret = tda18271_set_standby_mode(fe, 0, 0, 0);
-	if (tda_fail(ret))
-		goto fail;
-
-	/* read die current temperature */
-	tm_current = tda18271_read_thermometer(fe);
-
-	/* frequency dependent parameters */
-
-	tda18271_calc_rf_cal(fe, &freq);
-	rf_tab = regs[R_EB14];
-
-	i = tda18271_lookup_rf_band(fe, &freq, NULL);
-	if (tda_fail(i))
-		return i;
-
-	if ((0 == map[i].rf3) || (freq / 1000 < map[i].rf2)) {
-		approx = map[i].rf_a1 * (s32)(freq / 1000 - map[i].rf1) +
-			map[i].rf_b1 + rf_tab;
-	} else {
-		approx = map[i].rf_a2 * (s32)(freq / 1000 - map[i].rf2) +
-			map[i].rf_b2 + rf_tab;
-	}
-
-	if (approx < 0)
-		approx = 0;
-	if (approx > 255)
-		approx = 255;
-
-	tda18271_lookup_map(fe, RF_CAL_DC_OVER_DT, &freq, &dc_over_dt);
-
-	/* calculate temperature compensation */
-	rfcal_comp = dc_over_dt * (s32)(tm_current - priv->tm_rfcal) / 1000;
-
-	regs[R_EB14] = (unsigned char)(approx + rfcal_comp);
-	ret = tda18271_write_regs(fe, R_EB14, 1);
-fail:
-	return ret;
-}
-
-static int tda18271_por(struct dvb_frontend *fe)
-{
-	struct tda18271_priv *priv = fe->tuner_priv;
-	unsigned char *regs = priv->tda18271_regs;
-	int ret;
-
-	/* power up detector 1 */
-	regs[R_EB12] &= ~0x20;
-	ret = tda18271_write_regs(fe, R_EB12, 1);
-	if (tda_fail(ret))
-		goto fail;
-
-	regs[R_EB18] &= ~0x80; /* turn agc1 loop on */
-	regs[R_EB18] &= ~0x03; /* set agc1_gain to  6 dB */
-	ret = tda18271_write_regs(fe, R_EB18, 1);
-	if (tda_fail(ret))
-		goto fail;
-
-	regs[R_EB21] |= 0x03; /* set agc2_gain to -6 dB */
-
-	/* POR mode */
-	ret = tda18271_set_standby_mode(fe, 1, 0, 0);
-	if (tda_fail(ret))
-		goto fail;
-
-	/* disable 1.5 MHz low pass filter */
-	regs[R_EB23] &= ~0x04; /* forcelp_fc2_en = 0 */
-	regs[R_EB23] &= ~0x02; /* XXX: lp_fc[2] = 0 */
-	ret = tda18271_write_regs(fe, R_EB21, 3);
-fail:
-	return ret;
-}
-
-static int tda18271_calibrate_rf(struct dvb_frontend *fe, u32 freq)
-{
-	struct tda18271_priv *priv = fe->tuner_priv;
-	unsigned char *regs = priv->tda18271_regs;
-	u32 N;
-
-	/* set CAL mode to normal */
-	regs[R_EP4]  &= ~0x03;
-	tda18271_write_regs(fe, R_EP4, 1);
-
-	/* switch off agc1 */
-	regs[R_EP3]  |= 0x40; /* sm_lt = 1 */
-
-	regs[R_EB18] |= 0x03; /* set agc1_gain to 15 dB */
-	tda18271_write_regs(fe, R_EB18, 1);
-
-	/* frequency dependent parameters */
-
-	tda18271_calc_bp_filter(fe, &freq);
-	tda18271_calc_gain_taper(fe, &freq);
-	tda18271_calc_rf_band(fe, &freq);
-	tda18271_calc_km(fe, &freq);
-
-	tda18271_write_regs(fe, R_EP1, 3);
-	tda18271_write_regs(fe, R_EB13, 1);
-
-	/* main pll charge pump source */
-	tda18271_charge_pump_source(fe, TDA18271_MAIN_PLL, 1);
-
-	/* cal pll charge pump source */
-	tda18271_charge_pump_source(fe, TDA18271_CAL_PLL, 1);
-
-	/* force dcdc converter to 0 V */
-	regs[R_EB14] = 0x00;
-	tda18271_write_regs(fe, R_EB14, 1);
-
-	/* disable plls lock */
-	regs[R_EB20] &= ~0x20;
-	tda18271_write_regs(fe, R_EB20, 1);
-
-	/* set CAL mode to RF tracking filter calibration */
-	regs[R_EP4]  |= 0x03;
-	tda18271_write_regs(fe, R_EP4, 2);
-
-	/* --------------------------------------------------------------- */
-
-	/* set the internal calibration signal */
-	N = freq;
-
-	tda18271_calc_cal_pll(fe, N);
-	tda18271_write_regs(fe, R_CPD, 4);
-
-	/* downconvert internal calibration */
-	N += 1000000;
-
-	tda18271_calc_main_pll(fe, N);
-	tda18271_write_regs(fe, R_MPD, 4);
-
-	msleep(5);
-
-	tda18271_write_regs(fe, R_EP2, 1);
-	tda18271_write_regs(fe, R_EP1, 1);
-	tda18271_write_regs(fe, R_EP2, 1);
-	tda18271_write_regs(fe, R_EP1, 1);
-
-	/* --------------------------------------------------------------- */
-
-	/* normal operation for the main pll */
-	tda18271_charge_pump_source(fe, TDA18271_MAIN_PLL, 0);
-
-	/* normal operation for the cal pll  */
-	tda18271_charge_pump_source(fe, TDA18271_CAL_PLL, 0);
-
-	msleep(10); /* plls locking */
-
-	/* launch the rf tracking filters calibration */
-	regs[R_EB20]  |= 0x20;
-	tda18271_write_regs(fe, R_EB20, 1);
-
-	msleep(60); /* calibration */
-
-	/* --------------------------------------------------------------- */
-
-	/* set CAL mode to normal */
-	regs[R_EP4]  &= ~0x03;
-
-	/* switch on agc1 */
-	regs[R_EP3]  &= ~0x40; /* sm_lt = 0 */
-
-	regs[R_EB18] &= ~0x03; /* set agc1_gain to  6 dB */
-	tda18271_write_regs(fe, R_EB18, 1);
-
-	tda18271_write_regs(fe, R_EP3, 2);
-
-	/* synchronization */
-	tda18271_write_regs(fe, R_EP1, 1);
-
-	/* get calibration result */
-	tda18271_read_extended(fe);
-
-	return regs[R_EB14];
-}
-
-static int tda18271_powerscan(struct dvb_frontend *fe,
-			      u32 *freq_in, u32 *freq_out)
-{
-	struct tda18271_priv *priv = fe->tuner_priv;
-	unsigned char *regs = priv->tda18271_regs;
-	int sgn, bcal, count, wait, ret;
-	u8 cid_target;
-	u16 count_limit;
-	u32 freq;
-
-	freq = *freq_in;
-
-	tda18271_calc_rf_band(fe, &freq);
-	tda18271_calc_rf_cal(fe, &freq);
-	tda18271_calc_gain_taper(fe, &freq);
-	tda18271_lookup_cid_target(fe, &freq, &cid_target, &count_limit);
-
-	tda18271_write_regs(fe, R_EP2, 1);
-	tda18271_write_regs(fe, R_EB14, 1);
-
-	/* downconvert frequency */
-	freq += 1000000;
-
-	tda18271_calc_main_pll(fe, freq);
-	tda18271_write_regs(fe, R_MPD, 4);
-
-	msleep(5); /* pll locking */
-
-	/* detection mode */
-	regs[R_EP4]  &= ~0x03;
-	regs[R_EP4]  |= 0x01;
-	tda18271_write_regs(fe, R_EP4, 1);
-
-	/* launch power detection measurement */
-	tda18271_write_regs(fe, R_EP2, 1);
-
-	/* read power detection info, stored in EB10 */
-	ret = tda18271_read_extended(fe);
-	if (tda_fail(ret))
-		return ret;
-
-	/* algorithm initialization */
-	sgn = 1;
-	*freq_out = *freq_in;
-	bcal = 0;
-	count = 0;
-	wait = false;
-
-	while ((regs[R_EB10] & 0x3f) < cid_target) {
-		/* downconvert updated freq to 1 MHz */
-		freq = *freq_in + (sgn * count) + 1000000;
-
-		tda18271_calc_main_pll(fe, freq);
-		tda18271_write_regs(fe, R_MPD, 4);
-
-		if (wait) {
-			msleep(5); /* pll locking */
-			wait = false;
-		} else
-			udelay(100); /* pll locking */
-
-		/* launch power detection measurement */
-		tda18271_write_regs(fe, R_EP2, 1);
-
-		/* read power detection info, stored in EB10 */
-		ret = tda18271_read_extended(fe);
-		if (tda_fail(ret))
-			return ret;
-
-		count += 200;
-
-		if (count <= count_limit)
-			continue;
-
-		if (sgn <= 0)
-			break;
-
-		sgn = -1 * sgn;
-		count = 200;
-		wait = true;
-	}
-
-	if ((regs[R_EB10] & 0x3f) >= cid_target) {
-		bcal = 1;
-		*freq_out = freq - 1000000;
-	} else
-		bcal = 0;
-
-	tda_cal("bcal = %d, freq_in = %d, freq_out = %d (freq = %d)\n",
-		bcal, *freq_in, *freq_out, freq);
-
-	return bcal;
-}
-
-static int tda18271_powerscan_init(struct dvb_frontend *fe)
-{
-	struct tda18271_priv *priv = fe->tuner_priv;
-	unsigned char *regs = priv->tda18271_regs;
-	int ret;
-
-	/* set standard to digital */
-	regs[R_EP3]  &= ~0x1f; /* clear std bits */
-	regs[R_EP3]  |= 0x12;
-
-	/* set cal mode to normal */
-	regs[R_EP4]  &= ~0x03;
-
-	/* update IF output level */
-	regs[R_EP4]  &= ~0x1c; /* clear if level bits */
-
-	ret = tda18271_write_regs(fe, R_EP3, 2);
-	if (tda_fail(ret))
-		goto fail;
-
-	regs[R_EB18] &= ~0x03; /* set agc1_gain to   6 dB */
-	ret = tda18271_write_regs(fe, R_EB18, 1);
-	if (tda_fail(ret))
-		goto fail;
-
-	regs[R_EB21] &= ~0x03; /* set agc2_gain to -15 dB */
-
-	/* 1.5 MHz low pass filter */
-	regs[R_EB23] |= 0x04; /* forcelp_fc2_en = 1 */
-	regs[R_EB23] |= 0x02; /* lp_fc[2] = 1 */
-
-	ret = tda18271_write_regs(fe, R_EB21, 3);
-fail:
-	return ret;
-}
-
-static int tda18271_rf_tracking_filters_init(struct dvb_frontend *fe, u32 freq)
-{
-	struct tda18271_priv *priv = fe->tuner_priv;
-	struct tda18271_rf_tracking_filter_cal *map = priv->rf_cal_state;
-	unsigned char *regs = priv->tda18271_regs;
-	int bcal, rf, i;
-	s32 divisor, dividend;
-#define RF1 0
-#define RF2 1
-#define RF3 2
-	u32 rf_default[3];
-	u32 rf_freq[3];
-	s32 prog_cal[3];
-	s32 prog_tab[3];
-
-	i = tda18271_lookup_rf_band(fe, &freq, NULL);
-
-	if (tda_fail(i))
-		return i;
-
-	rf_default[RF1] = 1000 * map[i].rf1_def;
-	rf_default[RF2] = 1000 * map[i].rf2_def;
-	rf_default[RF3] = 1000 * map[i].rf3_def;
-
-	for (rf = RF1; rf <= RF3; rf++) {
-		if (0 == rf_default[rf])
-			return 0;
-		tda_cal("freq = %d, rf = %d\n", freq, rf);
-
-		/* look for optimized calibration frequency */
-		bcal = tda18271_powerscan(fe, &rf_default[rf], &rf_freq[rf]);
-		if (tda_fail(bcal))
-			return bcal;
-
-		tda18271_calc_rf_cal(fe, &rf_freq[rf]);
-		prog_tab[rf] = (s32)regs[R_EB14];
-
-		if (1 == bcal)
-			prog_cal[rf] =
-				(s32)tda18271_calibrate_rf(fe, rf_freq[rf]);
-		else
-			prog_cal[rf] = prog_tab[rf];
-
-		switch (rf) {
-		case RF1:
-			map[i].rf_a1 = 0;
-			map[i].rf_b1 = (prog_cal[RF1] - prog_tab[RF1]);
-			map[i].rf1   = rf_freq[RF1] / 1000;
-			break;
-		case RF2:
-			dividend = (prog_cal[RF2] - prog_tab[RF2] -
-				    prog_cal[RF1] + prog_tab[RF1]);
-			divisor = (s32)(rf_freq[RF2] - rf_freq[RF1]) / 1000;
-			map[i].rf_a1 = (dividend / divisor);
-			map[i].rf2   = rf_freq[RF2] / 1000;
-			break;
-		case RF3:
-			dividend = (prog_cal[RF3] - prog_tab[RF3] -
-				    prog_cal[RF2] + prog_tab[RF2]);
-			divisor = (s32)(rf_freq[RF3] - rf_freq[RF2]) / 1000;
-			map[i].rf_a2 = (dividend / divisor);
-			map[i].rf_b2 = (prog_cal[RF2] - prog_tab[RF2]);
-			map[i].rf3   = rf_freq[RF3] / 1000;
-			break;
-		default:
-			BUG();
-		}
-	}
-
-	return 0;
-}
-
-static int tda18271_calc_rf_filter_curve(struct dvb_frontend *fe)
-{
-	struct tda18271_priv *priv = fe->tuner_priv;
-	unsigned int i;
-	int ret;
-
-	tda_info("tda18271: performing RF tracking filter calibration\n");
-
-	/* wait for die temperature stabilization */
-	msleep(200);
-
-	ret = tda18271_powerscan_init(fe);
-	if (tda_fail(ret))
-		goto fail;
-
-	/* rf band calibration */
-	for (i = 0; priv->rf_cal_state[i].rfmax != 0; i++) {
-		ret =
-		tda18271_rf_tracking_filters_init(fe, 1000 *
-						  priv->rf_cal_state[i].rfmax);
-		if (tda_fail(ret))
-			goto fail;
-	}
-
-	priv->tm_rfcal = tda18271_read_thermometer(fe);
-fail:
-	return ret;
-}
-
-/* ------------------------------------------------------------------ */
-
-static int tda18271c2_rf_cal_init(struct dvb_frontend *fe)
-{
-	struct tda18271_priv *priv = fe->tuner_priv;
-	unsigned char *regs = priv->tda18271_regs;
-	int ret;
-
-	/* test RF_CAL_OK to see if we need init */
-	if ((regs[R_EP1] & 0x10) == 0)
-		priv->cal_initialized = false;
-
-	if (priv->cal_initialized)
-		return 0;
-
-	ret = tda18271_calc_rf_filter_curve(fe);
-	if (tda_fail(ret))
-		goto fail;
-
-	ret = tda18271_por(fe);
-	if (tda_fail(ret))
-		goto fail;
-
-	tda_info("tda18271: RF tracking filter calibration complete\n");
-
-	priv->cal_initialized = true;
-	goto end;
-fail:
-	tda_info("tda18271: RF tracking filter calibration failed!\n");
-end:
-	return ret;
-}
-
-static int tda18271c1_rf_tracking_filter_calibration(struct dvb_frontend *fe,
-						     u32 freq, u32 bw)
-{
-	struct tda18271_priv *priv = fe->tuner_priv;
-	unsigned char *regs = priv->tda18271_regs;
-	int ret;
-	u32 N = 0;
-
-	/* calculate bp filter */
-	tda18271_calc_bp_filter(fe, &freq);
-	tda18271_write_regs(fe, R_EP1, 1);
-
-	regs[R_EB4]  &= 0x07;
-	regs[R_EB4]  |= 0x60;
-	tda18271_write_regs(fe, R_EB4, 1);
-
-	regs[R_EB7]   = 0x60;
-	tda18271_write_regs(fe, R_EB7, 1);
-
-	regs[R_EB14]  = 0x00;
-	tda18271_write_regs(fe, R_EB14, 1);
-
-	regs[R_EB20]  = 0xcc;
-	tda18271_write_regs(fe, R_EB20, 1);
-
-	/* set cal mode to RF tracking filter calibration */
-	regs[R_EP4]  |= 0x03;
-
-	/* calculate cal pll */
-
-	switch (priv->mode) {
-	case TDA18271_ANALOG:
-		N = freq - 1250000;
-		break;
-	case TDA18271_DIGITAL:
-		N = freq + bw / 2;
-		break;
-	}
-
-	tda18271_calc_cal_pll(fe, N);
-
-	/* calculate main pll */
-
-	switch (priv->mode) {
-	case TDA18271_ANALOG:
-		N = freq - 250000;
-		break;
-	case TDA18271_DIGITAL:
-		N = freq + bw / 2 + 1000000;
-		break;
-	}
-
-	tda18271_calc_main_pll(fe, N);
-
-	ret = tda18271_write_regs(fe, R_EP3, 11);
-	if (tda_fail(ret))
-		return ret;
-
-	msleep(5); /* RF tracking filter calibration initialization */
-
-	/* search for K,M,CO for RF calibration */
-	tda18271_calc_km(fe, &freq);
-	tda18271_write_regs(fe, R_EB13, 1);
-
-	/* search for rf band */
-	tda18271_calc_rf_band(fe, &freq);
-
-	/* search for gain taper */
-	tda18271_calc_gain_taper(fe, &freq);
-
-	tda18271_write_regs(fe, R_EP2, 1);
-	tda18271_write_regs(fe, R_EP1, 1);
-	tda18271_write_regs(fe, R_EP2, 1);
-	tda18271_write_regs(fe, R_EP1, 1);
-
-	regs[R_EB4]  &= 0x07;
-	regs[R_EB4]  |= 0x40;
-	tda18271_write_regs(fe, R_EB4, 1);
-
-	regs[R_EB7]   = 0x40;
-	tda18271_write_regs(fe, R_EB7, 1);
-	msleep(10); /* pll locking */
-
-	regs[R_EB20]  = 0xec;
-	tda18271_write_regs(fe, R_EB20, 1);
-	msleep(60); /* RF tracking filter calibration completion */
-
-	regs[R_EP4]  &= ~0x03; /* set cal mode to normal */
-	tda18271_write_regs(fe, R_EP4, 1);
-
-	tda18271_write_regs(fe, R_EP1, 1);
-
-	/* RF tracking filter correction for VHF_Low band */
-	if (0 == tda18271_calc_rf_cal(fe, &freq))
-		tda18271_write_regs(fe, R_EB14, 1);
-
-	return 0;
-}
-
-/* ------------------------------------------------------------------ */
-
-static int tda18271_ir_cal_init(struct dvb_frontend *fe)
-{
-	struct tda18271_priv *priv = fe->tuner_priv;
-	unsigned char *regs = priv->tda18271_regs;
-	int ret;
-
-	ret = tda18271_read_regs(fe);
-	if (tda_fail(ret))
-		goto fail;
-
-	/* test IR_CAL_OK to see if we need init */
-	if ((regs[R_EP1] & 0x08) == 0)
-		ret = tda18271_init_regs(fe);
-fail:
-	return ret;
-}
-
-static int tda18271_init(struct dvb_frontend *fe)
-{
-	struct tda18271_priv *priv = fe->tuner_priv;
-	int ret;
-
-	mutex_lock(&priv->lock);
-
-	/* full power up */
-	ret = tda18271_set_standby_mode(fe, 0, 0, 0);
-	if (tda_fail(ret))
-		goto fail;
-
-	/* initialization */
-	ret = tda18271_ir_cal_init(fe);
-	if (tda_fail(ret))
-		goto fail;
-
-	if (priv->id == TDA18271HDC2)
-		tda18271c2_rf_cal_init(fe);
-fail:
-	mutex_unlock(&priv->lock);
-
-	return ret;
-}
-
-static int tda18271_sleep(struct dvb_frontend *fe)
-{
-	struct tda18271_priv *priv = fe->tuner_priv;
-	int ret;
-
-	mutex_lock(&priv->lock);
-
-	/* enter standby mode, with required output features enabled */
-	ret = tda18271_toggle_output(fe, 1);
-
-	mutex_unlock(&priv->lock);
-
-	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 external agc configuration required */
-		if (tda18271_debug & DBG_ADV)
-			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)
-{
-	struct tda18271_priv *priv = fe->tuner_priv;
-	int ret;
-
-	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;
-
-	mutex_lock(&priv->lock);
-
-	switch (priv->id) {
-	case TDA18271HDC1:
-		tda18271c1_rf_tracking_filter_calibration(fe, freq, bw);
-		break;
-	case TDA18271HDC2:
-		tda18271c2_rf_tracking_filters_correction(fe, freq);
-		break;
-	}
-	ret = tda18271_channel_configuration(fe, map, freq, bw);
-
-	mutex_unlock(&priv->lock);
-fail:
-	return ret;
-}
-
-/* ------------------------------------------------------------------ */
-
-static int tda18271_set_params(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	u32 delsys = c->delivery_system;
-	u32 bw = c->bandwidth_hz;
-	u32 freq = c->frequency;
-	struct tda18271_priv *priv = fe->tuner_priv;
-	struct tda18271_std_map *std_map = &priv->std;
-	struct tda18271_std_map_item *map;
-	int ret;
-
-	priv->mode = TDA18271_DIGITAL;
-
-	switch (delsys) {
-	case SYS_ATSC:
-		map = &std_map->atsc_6;
-		bw = 6000000;
-		break;
-	case SYS_ISDBT:
-	case SYS_DVBT:
-	case SYS_DVBT2:
-		if (bw <= 6000000) {
-			map = &std_map->dvbt_6;
-		} else if (bw <= 7000000) {
-			map = &std_map->dvbt_7;
-		} else {
-			map = &std_map->dvbt_8;
-		}
-		break;
-	case SYS_DVBC_ANNEX_B:
-		bw = 6000000;
-		/* falltrough */
-	case SYS_DVBC_ANNEX_A:
-	case SYS_DVBC_ANNEX_C:
-		if (bw <= 6000000) {
-			map = &std_map->qam_6;
-		} else if (bw <= 7000000) {
-			map = &std_map->qam_7;
-		} else {
-			map = &std_map->qam_8;
-		}
-		break;
-	default:
-		tda_warn("modulation type not supported!\n");
-		return -EINVAL;
-	}
-
-	/* When tuning digital, the analog demod must be tri-stated */
-	if (fe->ops.analog_ops.standby)
-		fe->ops.analog_ops.standby(fe);
-
-	ret = tda18271_tune(fe, map, freq, bw);
-
-	if (tda_fail(ret))
-		goto fail;
-
-	priv->if_freq   = map->if_freq;
-	priv->frequency = freq;
-	priv->bandwidth = bw;
-fail:
-	return ret;
-}
-
-static int tda18271_set_analog_params(struct dvb_frontend *fe,
-				      struct analog_parameters *params)
-{
-	struct tda18271_priv *priv = fe->tuner_priv;
-	struct tda18271_std_map *std_map = &priv->std;
-	struct tda18271_std_map_item *map;
-	char *mode;
-	int ret;
-	u32 freq = params->frequency * 125 *
-		((params->mode == V4L2_TUNER_RADIO) ? 1 : 1000) / 2;
-
-	priv->mode = TDA18271_ANALOG;
-
-	if (params->mode == V4L2_TUNER_RADIO) {
-		map = &std_map->fm_radio;
-		mode = "fm";
-	} else if (params->std & V4L2_STD_MN) {
-		map = &std_map->atv_mn;
-		mode = "MN";
-	} else if (params->std & V4L2_STD_B) {
-		map = &std_map->atv_b;
-		mode = "B";
-	} else if (params->std & V4L2_STD_GH) {
-		map = &std_map->atv_gh;
-		mode = "GH";
-	} else if (params->std & V4L2_STD_PAL_I) {
-		map = &std_map->atv_i;
-		mode = "I";
-	} else if (params->std & V4L2_STD_DK) {
-		map = &std_map->atv_dk;
-		mode = "DK";
-	} else if (params->std & V4L2_STD_SECAM_L) {
-		map = &std_map->atv_l;
-		mode = "L";
-	} else if (params->std & V4L2_STD_SECAM_LC) {
-		map = &std_map->atv_lc;
-		mode = "L'";
-	} else {
-		map = &std_map->atv_i;
-		mode = "xx";
-	}
-
-	tda_dbg("setting tda18271 to system %s\n", mode);
-
-	ret = tda18271_tune(fe, map, freq, 0);
-
-	if (tda_fail(ret))
-		goto fail;
-
-	priv->if_freq   = map->if_freq;
-	priv->frequency = freq;
-	priv->bandwidth = 0;
-fail:
-	return ret;
-}
-
-static int tda18271_release(struct dvb_frontend *fe)
-{
-	struct tda18271_priv *priv = fe->tuner_priv;
-
-	mutex_lock(&tda18271_list_mutex);
-
-	if (priv)
-		hybrid_tuner_release_state(priv);
-
-	mutex_unlock(&tda18271_list_mutex);
-
-	fe->tuner_priv = NULL;
-
-	return 0;
-}
-
-static int tda18271_get_frequency(struct dvb_frontend *fe, u32 *frequency)
-{
-	struct tda18271_priv *priv = fe->tuner_priv;
-	*frequency = priv->frequency;
-	return 0;
-}
-
-static int tda18271_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
-{
-	struct tda18271_priv *priv = fe->tuner_priv;
-	*bandwidth = priv->bandwidth;
-	return 0;
-}
-
-static int tda18271_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
-{
-	struct tda18271_priv *priv = fe->tuner_priv;
-	*frequency = (u32)priv->if_freq * 1000;
-	return 0;
-}
-
-/* ------------------------------------------------------------------ */
-
-#define tda18271_update_std(std_cfg, name) do {				\
-	if (map->std_cfg.if_freq +					\
-		map->std_cfg.agc_mode + map->std_cfg.std +		\
-		map->std_cfg.if_lvl + map->std_cfg.rfagc_top > 0) {	\
-		tda_dbg("Using custom std config for %s\n", name);	\
-		memcpy(&std->std_cfg, &map->std_cfg,			\
-			sizeof(struct tda18271_std_map_item));		\
-	} } while (0)
-
-#define tda18271_dump_std_item(std_cfg, name) do {			\
-	tda_dbg("(%s) if_freq = %d, agc_mode = %d, std = %d, "		\
-		"if_lvl = %d, rfagc_top = 0x%02x\n",			\
-		name, std->std_cfg.if_freq,				\
-		std->std_cfg.agc_mode, std->std_cfg.std,		\
-		std->std_cfg.if_lvl, std->std_cfg.rfagc_top);		\
-	} while (0)
-
-static int tda18271_dump_std_map(struct dvb_frontend *fe)
-{
-	struct tda18271_priv *priv = fe->tuner_priv;
-	struct tda18271_std_map *std = &priv->std;
-
-	tda_dbg("========== STANDARD MAP SETTINGS ==========\n");
-	tda18271_dump_std_item(fm_radio, "  fm  ");
-	tda18271_dump_std_item(atv_b,  "atv b ");
-	tda18271_dump_std_item(atv_dk, "atv dk");
-	tda18271_dump_std_item(atv_gh, "atv gh");
-	tda18271_dump_std_item(atv_i,  "atv i ");
-	tda18271_dump_std_item(atv_l,  "atv l ");
-	tda18271_dump_std_item(atv_lc, "atv l'");
-	tda18271_dump_std_item(atv_mn, "atv mn");
-	tda18271_dump_std_item(atsc_6, "atsc 6");
-	tda18271_dump_std_item(dvbt_6, "dvbt 6");
-	tda18271_dump_std_item(dvbt_7, "dvbt 7");
-	tda18271_dump_std_item(dvbt_8, "dvbt 8");
-	tda18271_dump_std_item(qam_6,  "qam 6 ");
-	tda18271_dump_std_item(qam_8,  "qam 8 ");
-
-	return 0;
-}
-
-static int tda18271_update_std_map(struct dvb_frontend *fe,
-				   struct tda18271_std_map *map)
-{
-	struct tda18271_priv *priv = fe->tuner_priv;
-	struct tda18271_std_map *std = &priv->std;
-
-	if (!map)
-		return -EINVAL;
-
-	tda18271_update_std(fm_radio, "fm");
-	tda18271_update_std(atv_b,  "atv b");
-	tda18271_update_std(atv_dk, "atv dk");
-	tda18271_update_std(atv_gh, "atv gh");
-	tda18271_update_std(atv_i,  "atv i");
-	tda18271_update_std(atv_l,  "atv l");
-	tda18271_update_std(atv_lc, "atv l'");
-	tda18271_update_std(atv_mn, "atv mn");
-	tda18271_update_std(atsc_6, "atsc 6");
-	tda18271_update_std(dvbt_6, "dvbt 6");
-	tda18271_update_std(dvbt_7, "dvbt 7");
-	tda18271_update_std(dvbt_8, "dvbt 8");
-	tda18271_update_std(qam_6,  "qam 6");
-	tda18271_update_std(qam_8,  "qam 8");
-
-	return 0;
-}
-
-static int tda18271_get_id(struct dvb_frontend *fe)
-{
-	struct tda18271_priv *priv = fe->tuner_priv;
-	unsigned char *regs = priv->tda18271_regs;
-	char *name;
-
-	mutex_lock(&priv->lock);
-	tda18271_read_regs(fe);
-	mutex_unlock(&priv->lock);
-
-	switch (regs[R_ID] & 0x7f) {
-	case 3:
-		name = "TDA18271HD/C1";
-		priv->id = TDA18271HDC1;
-		break;
-	case 4:
-		name = "TDA18271HD/C2";
-		priv->id = TDA18271HDC2;
-		break;
-	default:
-		tda_info("Unknown device (%i) detected @ %d-%04x, device not supported.\n",
-			 regs[R_ID], i2c_adapter_id(priv->i2c_props.adap),
-			 priv->i2c_props.addr);
-		return -EINVAL;
-	}
-
-	tda_info("%s detected @ %d-%04x\n", name,
-		 i2c_adapter_id(priv->i2c_props.adap), priv->i2c_props.addr);
-
-	return 0;
-}
-
-static int tda18271_setup_configuration(struct dvb_frontend *fe,
-					struct tda18271_config *cfg)
-{
-	struct tda18271_priv *priv = fe->tuner_priv;
-
-	priv->gate = (cfg) ? cfg->gate : TDA18271_GATE_AUTO;
-	priv->role = (cfg) ? cfg->role : TDA18271_MASTER;
-	priv->config = (cfg) ? cfg->config : 0;
-	priv->small_i2c = (cfg) ?
-		cfg->small_i2c : TDA18271_39_BYTE_CHUNK_INIT;
-	priv->output_opt = (cfg) ?
-		cfg->output_opt : TDA18271_OUTPUT_LT_XT_ON;
-
-	return 0;
-}
-
-static inline int tda18271_need_cal_on_startup(struct tda18271_config *cfg)
-{
-	/* tda18271_cal_on_startup == -1 when cal module option is unset */
-	return ((tda18271_cal_on_startup == -1) ?
-		/* honor configuration setting */
-		((cfg) && (cfg->rf_cal_on_startup)) :
-		/* module option overrides configuration setting */
-		(tda18271_cal_on_startup)) ? 1 : 0;
-}
-
-static int tda18271_set_config(struct dvb_frontend *fe, void *priv_cfg)
-{
-	struct tda18271_config *cfg = (struct tda18271_config *) priv_cfg;
-
-	tda18271_setup_configuration(fe, cfg);
-
-	if (tda18271_need_cal_on_startup(cfg))
-		tda18271_init(fe);
-
-	/* override default std map with values in config struct */
-	if ((cfg) && (cfg->std_map))
-		tda18271_update_std_map(fe, cfg->std_map);
-
-	return 0;
-}
-
-static const struct dvb_tuner_ops tda18271_tuner_ops = {
-	.info = {
-		.name = "NXP TDA18271HD",
-		.frequency_min  =  45000000,
-		.frequency_max  = 864000000,
-		.frequency_step =     62500
-	},
-	.init              = tda18271_init,
-	.sleep             = tda18271_sleep,
-	.set_params        = tda18271_set_params,
-	.set_analog_params = tda18271_set_analog_params,
-	.release           = tda18271_release,
-	.set_config        = tda18271_set_config,
-	.get_frequency     = tda18271_get_frequency,
-	.get_bandwidth     = tda18271_get_bandwidth,
-	.get_if_frequency  = tda18271_get_if_frequency,
-};
-
-struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr,
-				     struct i2c_adapter *i2c,
-				     struct tda18271_config *cfg)
-{
-	struct tda18271_priv *priv = NULL;
-	int instance, ret;
-
-	mutex_lock(&tda18271_list_mutex);
-
-	instance = hybrid_tuner_request_state(struct tda18271_priv, priv,
-					      hybrid_tuner_instance_list,
-					      i2c, addr, "tda18271");
-	switch (instance) {
-	case 0:
-		goto fail;
-	case 1:
-		/* new tuner instance */
-		fe->tuner_priv = priv;
-
-		tda18271_setup_configuration(fe, cfg);
-
-		priv->cal_initialized = false;
-		mutex_init(&priv->lock);
-
-		ret = tda18271_get_id(fe);
-		if (tda_fail(ret))
-			goto fail;
-
-		ret = tda18271_assign_map_layout(fe);
-		if (tda_fail(ret))
-			goto fail;
-
-		mutex_lock(&priv->lock);
-		tda18271_init_regs(fe);
-
-		if ((tda18271_need_cal_on_startup(cfg)) &&
-		    (priv->id == TDA18271HDC2))
-			tda18271c2_rf_cal_init(fe);
-
-		mutex_unlock(&priv->lock);
-		break;
-	default:
-		/* existing tuner instance */
-		fe->tuner_priv = priv;
-
-		/* allow dvb driver to override configuration settings */
-		if (cfg) {
-			if (cfg->gate != TDA18271_GATE_ANALOG)
-				priv->gate = cfg->gate;
-			if (cfg->role)
-				priv->role = cfg->role;
-			if (cfg->config)
-				priv->config = cfg->config;
-			if (cfg->small_i2c)
-				priv->small_i2c = cfg->small_i2c;
-			if (cfg->output_opt)
-				priv->output_opt = cfg->output_opt;
-			if (cfg->std_map)
-				tda18271_update_std_map(fe, cfg->std_map);
-		}
-		if (tda18271_need_cal_on_startup(cfg))
-			tda18271_init(fe);
-		break;
-	}
-
-	/* override default std map with values in config struct */
-	if ((cfg) && (cfg->std_map))
-		tda18271_update_std_map(fe, cfg->std_map);
-
-	mutex_unlock(&tda18271_list_mutex);
-
-	memcpy(&fe->ops.tuner_ops, &tda18271_tuner_ops,
-	       sizeof(struct dvb_tuner_ops));
-
-	if (tda18271_debug & (DBG_MAP | DBG_ADV))
-		tda18271_dump_std_map(fe);
-
-	return fe;
-fail:
-	mutex_unlock(&tda18271_list_mutex);
-
-	tda18271_release(fe);
-	return NULL;
-}
-EXPORT_SYMBOL_GPL(tda18271_attach);
-MODULE_DESCRIPTION("NXP TDA18271HD analog / digital tuner driver");
-MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
-MODULE_LICENSE("GPL");
-MODULE_VERSION("0.4");
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/common/tuners/tda18271-maps.c b/drivers/media/common/tuners/tda18271-maps.c
deleted file mode 100644
index fb881c6..0000000
--- a/drivers/media/common/tuners/tda18271-maps.c
+++ /dev/null
@@ -1,1317 +0,0 @@
-/*
-    tda18271-maps.c - driver for the Philips / NXP TDA18271 silicon tuner
-
-    Copyright (C) 2007, 2008 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 "tda18271-priv.h"
-
-struct tda18271_pll_map {
-	u32 lomax;
-	u8 pd; /* post div */
-	u8 d;  /*      div */
-};
-
-struct tda18271_map {
-	u32 rfmax;
-	u8  val;
-};
-
-/*---------------------------------------------------------------------*/
-
-static struct tda18271_pll_map tda18271c1_main_pll[] = {
-	{ .lomax =  32000, .pd = 0x5f, .d = 0xf0 },
-	{ .lomax =  35000, .pd = 0x5e, .d = 0xe0 },
-	{ .lomax =  37000, .pd = 0x5d, .d = 0xd0 },
-	{ .lomax =  41000, .pd = 0x5c, .d = 0xc0 },
-	{ .lomax =  44000, .pd = 0x5b, .d = 0xb0 },
-	{ .lomax =  49000, .pd = 0x5a, .d = 0xa0 },
-	{ .lomax =  54000, .pd = 0x59, .d = 0x90 },
-	{ .lomax =  61000, .pd = 0x58, .d = 0x80 },
-	{ .lomax =  65000, .pd = 0x4f, .d = 0x78 },
-	{ .lomax =  70000, .pd = 0x4e, .d = 0x70 },
-	{ .lomax =  75000, .pd = 0x4d, .d = 0x68 },
-	{ .lomax =  82000, .pd = 0x4c, .d = 0x60 },
-	{ .lomax =  89000, .pd = 0x4b, .d = 0x58 },
-	{ .lomax =  98000, .pd = 0x4a, .d = 0x50 },
-	{ .lomax = 109000, .pd = 0x49, .d = 0x48 },
-	{ .lomax = 123000, .pd = 0x48, .d = 0x40 },
-	{ .lomax = 131000, .pd = 0x3f, .d = 0x3c },
-	{ .lomax = 141000, .pd = 0x3e, .d = 0x38 },
-	{ .lomax = 151000, .pd = 0x3d, .d = 0x34 },
-	{ .lomax = 164000, .pd = 0x3c, .d = 0x30 },
-	{ .lomax = 179000, .pd = 0x3b, .d = 0x2c },
-	{ .lomax = 197000, .pd = 0x3a, .d = 0x28 },
-	{ .lomax = 219000, .pd = 0x39, .d = 0x24 },
-	{ .lomax = 246000, .pd = 0x38, .d = 0x20 },
-	{ .lomax = 263000, .pd = 0x2f, .d = 0x1e },
-	{ .lomax = 282000, .pd = 0x2e, .d = 0x1c },
-	{ .lomax = 303000, .pd = 0x2d, .d = 0x1a },
-	{ .lomax = 329000, .pd = 0x2c, .d = 0x18 },
-	{ .lomax = 359000, .pd = 0x2b, .d = 0x16 },
-	{ .lomax = 395000, .pd = 0x2a, .d = 0x14 },
-	{ .lomax = 438000, .pd = 0x29, .d = 0x12 },
-	{ .lomax = 493000, .pd = 0x28, .d = 0x10 },
-	{ .lomax = 526000, .pd = 0x1f, .d = 0x0f },
-	{ .lomax = 564000, .pd = 0x1e, .d = 0x0e },
-	{ .lomax = 607000, .pd = 0x1d, .d = 0x0d },
-	{ .lomax = 658000, .pd = 0x1c, .d = 0x0c },
-	{ .lomax = 718000, .pd = 0x1b, .d = 0x0b },
-	{ .lomax = 790000, .pd = 0x1a, .d = 0x0a },
-	{ .lomax = 877000, .pd = 0x19, .d = 0x09 },
-	{ .lomax = 987000, .pd = 0x18, .d = 0x08 },
-	{ .lomax =      0, .pd = 0x00, .d = 0x00 }, /* end */
-};
-
-static struct tda18271_pll_map tda18271c2_main_pll[] = {
-	{ .lomax =  33125, .pd = 0x57, .d = 0xf0 },
-	{ .lomax =  35500, .pd = 0x56, .d = 0xe0 },
-	{ .lomax =  38188, .pd = 0x55, .d = 0xd0 },
-	{ .lomax =  41375, .pd = 0x54, .d = 0xc0 },
-	{ .lomax =  45125, .pd = 0x53, .d = 0xb0 },
-	{ .lomax =  49688, .pd = 0x52, .d = 0xa0 },
-	{ .lomax =  55188, .pd = 0x51, .d = 0x90 },
-	{ .lomax =  62125, .pd = 0x50, .d = 0x80 },
-	{ .lomax =  66250, .pd = 0x47, .d = 0x78 },
-	{ .lomax =  71000, .pd = 0x46, .d = 0x70 },
-	{ .lomax =  76375, .pd = 0x45, .d = 0x68 },
-	{ .lomax =  82750, .pd = 0x44, .d = 0x60 },
-	{ .lomax =  90250, .pd = 0x43, .d = 0x58 },
-	{ .lomax =  99375, .pd = 0x42, .d = 0x50 },
-	{ .lomax = 110375, .pd = 0x41, .d = 0x48 },
-	{ .lomax = 124250, .pd = 0x40, .d = 0x40 },
-	{ .lomax = 132500, .pd = 0x37, .d = 0x3c },
-	{ .lomax = 142000, .pd = 0x36, .d = 0x38 },
-	{ .lomax = 152750, .pd = 0x35, .d = 0x34 },
-	{ .lomax = 165500, .pd = 0x34, .d = 0x30 },
-	{ .lomax = 180500, .pd = 0x33, .d = 0x2c },
-	{ .lomax = 198750, .pd = 0x32, .d = 0x28 },
-	{ .lomax = 220750, .pd = 0x31, .d = 0x24 },
-	{ .lomax = 248500, .pd = 0x30, .d = 0x20 },
-	{ .lomax = 265000, .pd = 0x27, .d = 0x1e },
-	{ .lomax = 284000, .pd = 0x26, .d = 0x1c },
-	{ .lomax = 305500, .pd = 0x25, .d = 0x1a },
-	{ .lomax = 331000, .pd = 0x24, .d = 0x18 },
-	{ .lomax = 361000, .pd = 0x23, .d = 0x16 },
-	{ .lomax = 397500, .pd = 0x22, .d = 0x14 },
-	{ .lomax = 441500, .pd = 0x21, .d = 0x12 },
-	{ .lomax = 497000, .pd = 0x20, .d = 0x10 },
-	{ .lomax = 530000, .pd = 0x17, .d = 0x0f },
-	{ .lomax = 568000, .pd = 0x16, .d = 0x0e },
-	{ .lomax = 611000, .pd = 0x15, .d = 0x0d },
-	{ .lomax = 662000, .pd = 0x14, .d = 0x0c },
-	{ .lomax = 722000, .pd = 0x13, .d = 0x0b },
-	{ .lomax = 795000, .pd = 0x12, .d = 0x0a },
-	{ .lomax = 883000, .pd = 0x11, .d = 0x09 },
-	{ .lomax = 994000, .pd = 0x10, .d = 0x08 },
-	{ .lomax =      0, .pd = 0x00, .d = 0x00 }, /* end */
-};
-
-static struct tda18271_pll_map tda18271c1_cal_pll[] = {
-	{ .lomax =   33000, .pd = 0xdd, .d = 0xd0 },
-	{ .lomax =   36000, .pd = 0xdc, .d = 0xc0 },
-	{ .lomax =   40000, .pd = 0xdb, .d = 0xb0 },
-	{ .lomax =   44000, .pd = 0xda, .d = 0xa0 },
-	{ .lomax =   49000, .pd = 0xd9, .d = 0x90 },
-	{ .lomax =   55000, .pd = 0xd8, .d = 0x80 },
-	{ .lomax =   63000, .pd = 0xd3, .d = 0x70 },
-	{ .lomax =   67000, .pd = 0xcd, .d = 0x68 },
-	{ .lomax =   73000, .pd = 0xcc, .d = 0x60 },
-	{ .lomax =   80000, .pd = 0xcb, .d = 0x58 },
-	{ .lomax =   88000, .pd = 0xca, .d = 0x50 },
-	{ .lomax =   98000, .pd = 0xc9, .d = 0x48 },
-	{ .lomax =  110000, .pd = 0xc8, .d = 0x40 },
-	{ .lomax =  126000, .pd = 0xc3, .d = 0x38 },
-	{ .lomax =  135000, .pd = 0xbd, .d = 0x34 },
-	{ .lomax =  147000, .pd = 0xbc, .d = 0x30 },
-	{ .lomax =  160000, .pd = 0xbb, .d = 0x2c },
-	{ .lomax =  176000, .pd = 0xba, .d = 0x28 },
-	{ .lomax =  196000, .pd = 0xb9, .d = 0x24 },
-	{ .lomax =  220000, .pd = 0xb8, .d = 0x20 },
-	{ .lomax =  252000, .pd = 0xb3, .d = 0x1c },
-	{ .lomax =  271000, .pd = 0xad, .d = 0x1a },
-	{ .lomax =  294000, .pd = 0xac, .d = 0x18 },
-	{ .lomax =  321000, .pd = 0xab, .d = 0x16 },
-	{ .lomax =  353000, .pd = 0xaa, .d = 0x14 },
-	{ .lomax =  392000, .pd = 0xa9, .d = 0x12 },
-	{ .lomax =  441000, .pd = 0xa8, .d = 0x10 },
-	{ .lomax =  505000, .pd = 0xa3, .d = 0x0e },
-	{ .lomax =  543000, .pd = 0x9d, .d = 0x0d },
-	{ .lomax =  589000, .pd = 0x9c, .d = 0x0c },
-	{ .lomax =  642000, .pd = 0x9b, .d = 0x0b },
-	{ .lomax =  707000, .pd = 0x9a, .d = 0x0a },
-	{ .lomax =  785000, .pd = 0x99, .d = 0x09 },
-	{ .lomax =  883000, .pd = 0x98, .d = 0x08 },
-	{ .lomax = 1010000, .pd = 0x93, .d = 0x07 },
-	{ .lomax =       0, .pd = 0x00, .d = 0x00 }, /* end */
-};
-
-static struct tda18271_pll_map tda18271c2_cal_pll[] = {
-	{ .lomax =   33813, .pd = 0xdd, .d = 0xd0 },
-	{ .lomax =   36625, .pd = 0xdc, .d = 0xc0 },
-	{ .lomax =   39938, .pd = 0xdb, .d = 0xb0 },
-	{ .lomax =   43938, .pd = 0xda, .d = 0xa0 },
-	{ .lomax =   48813, .pd = 0xd9, .d = 0x90 },
-	{ .lomax =   54938, .pd = 0xd8, .d = 0x80 },
-	{ .lomax =   62813, .pd = 0xd3, .d = 0x70 },
-	{ .lomax =   67625, .pd = 0xcd, .d = 0x68 },
-	{ .lomax =   73250, .pd = 0xcc, .d = 0x60 },
-	{ .lomax =   79875, .pd = 0xcb, .d = 0x58 },
-	{ .lomax =   87875, .pd = 0xca, .d = 0x50 },
-	{ .lomax =   97625, .pd = 0xc9, .d = 0x48 },
-	{ .lomax =  109875, .pd = 0xc8, .d = 0x40 },
-	{ .lomax =  125625, .pd = 0xc3, .d = 0x38 },
-	{ .lomax =  135250, .pd = 0xbd, .d = 0x34 },
-	{ .lomax =  146500, .pd = 0xbc, .d = 0x30 },
-	{ .lomax =  159750, .pd = 0xbb, .d = 0x2c },
-	{ .lomax =  175750, .pd = 0xba, .d = 0x28 },
-	{ .lomax =  195250, .pd = 0xb9, .d = 0x24 },
-	{ .lomax =  219750, .pd = 0xb8, .d = 0x20 },
-	{ .lomax =  251250, .pd = 0xb3, .d = 0x1c },
-	{ .lomax =  270500, .pd = 0xad, .d = 0x1a },
-	{ .lomax =  293000, .pd = 0xac, .d = 0x18 },
-	{ .lomax =  319500, .pd = 0xab, .d = 0x16 },
-	{ .lomax =  351500, .pd = 0xaa, .d = 0x14 },
-	{ .lomax =  390500, .pd = 0xa9, .d = 0x12 },
-	{ .lomax =  439500, .pd = 0xa8, .d = 0x10 },
-	{ .lomax =  502500, .pd = 0xa3, .d = 0x0e },
-	{ .lomax =  541000, .pd = 0x9d, .d = 0x0d },
-	{ .lomax =  586000, .pd = 0x9c, .d = 0x0c },
-	{ .lomax =  639000, .pd = 0x9b, .d = 0x0b },
-	{ .lomax =  703000, .pd = 0x9a, .d = 0x0a },
-	{ .lomax =  781000, .pd = 0x99, .d = 0x09 },
-	{ .lomax =  879000, .pd = 0x98, .d = 0x08 },
-	{ .lomax =       0, .pd = 0x00, .d = 0x00 }, /* end */
-};
-
-static struct tda18271_map tda18271_bp_filter[] = {
-	{ .rfmax =  62000, .val = 0x00 },
-	{ .rfmax =  84000, .val = 0x01 },
-	{ .rfmax = 100000, .val = 0x02 },
-	{ .rfmax = 140000, .val = 0x03 },
-	{ .rfmax = 170000, .val = 0x04 },
-	{ .rfmax = 180000, .val = 0x05 },
-	{ .rfmax = 865000, .val = 0x06 },
-	{ .rfmax =      0, .val = 0x00 }, /* end */
-};
-
-static struct tda18271_map tda18271c1_km[] = {
-	{ .rfmax =  61100, .val = 0x74 },
-	{ .rfmax = 350000, .val = 0x40 },
-	{ .rfmax = 720000, .val = 0x30 },
-	{ .rfmax = 865000, .val = 0x40 },
-	{ .rfmax =      0, .val = 0x00 }, /* end */
-};
-
-static struct tda18271_map tda18271c2_km[] = {
-	{ .rfmax =  47900, .val = 0x38 },
-	{ .rfmax =  61100, .val = 0x44 },
-	{ .rfmax = 350000, .val = 0x30 },
-	{ .rfmax = 720000, .val = 0x24 },
-	{ .rfmax = 865000, .val = 0x3c },
-	{ .rfmax =      0, .val = 0x00 }, /* end */
-};
-
-static struct tda18271_map tda18271_rf_band[] = {
-	{ .rfmax =  47900, .val = 0x00 },
-	{ .rfmax =  61100, .val = 0x01 },
-	{ .rfmax = 152600, .val = 0x02 },
-	{ .rfmax = 164700, .val = 0x03 },
-	{ .rfmax = 203500, .val = 0x04 },
-	{ .rfmax = 457800, .val = 0x05 },
-	{ .rfmax = 865000, .val = 0x06 },
-	{ .rfmax =      0, .val = 0x00 }, /* end */
-};
-
-static struct tda18271_map tda18271_gain_taper[] = {
-	{ .rfmax =  45400, .val = 0x1f },
-	{ .rfmax =  45800, .val = 0x1e },
-	{ .rfmax =  46200, .val = 0x1d },
-	{ .rfmax =  46700, .val = 0x1c },
-	{ .rfmax =  47100, .val = 0x1b },
-	{ .rfmax =  47500, .val = 0x1a },
-	{ .rfmax =  47900, .val = 0x19 },
-	{ .rfmax =  49600, .val = 0x17 },
-	{ .rfmax =  51200, .val = 0x16 },
-	{ .rfmax =  52900, .val = 0x15 },
-	{ .rfmax =  54500, .val = 0x14 },
-	{ .rfmax =  56200, .val = 0x13 },
-	{ .rfmax =  57800, .val = 0x12 },
-	{ .rfmax =  59500, .val = 0x11 },
-	{ .rfmax =  61100, .val = 0x10 },
-	{ .rfmax =  67600, .val = 0x0d },
-	{ .rfmax =  74200, .val = 0x0c },
-	{ .rfmax =  80700, .val = 0x0b },
-	{ .rfmax =  87200, .val = 0x0a },
-	{ .rfmax =  93800, .val = 0x09 },
-	{ .rfmax = 100300, .val = 0x08 },
-	{ .rfmax = 106900, .val = 0x07 },
-	{ .rfmax = 113400, .val = 0x06 },
-	{ .rfmax = 119900, .val = 0x05 },
-	{ .rfmax = 126500, .val = 0x04 },
-	{ .rfmax = 133000, .val = 0x03 },
-	{ .rfmax = 139500, .val = 0x02 },
-	{ .rfmax = 146100, .val = 0x01 },
-	{ .rfmax = 152600, .val = 0x00 },
-	{ .rfmax = 154300, .val = 0x1f },
-	{ .rfmax = 156100, .val = 0x1e },
-	{ .rfmax = 157800, .val = 0x1d },
-	{ .rfmax = 159500, .val = 0x1c },
-	{ .rfmax = 161200, .val = 0x1b },
-	{ .rfmax = 163000, .val = 0x1a },
-	{ .rfmax = 164700, .val = 0x19 },
-	{ .rfmax = 170200, .val = 0x17 },
-	{ .rfmax = 175800, .val = 0x16 },
-	{ .rfmax = 181300, .val = 0x15 },
-	{ .rfmax = 186900, .val = 0x14 },
-	{ .rfmax = 192400, .val = 0x13 },
-	{ .rfmax = 198000, .val = 0x12 },
-	{ .rfmax = 203500, .val = 0x11 },
-	{ .rfmax = 216200, .val = 0x14 },
-	{ .rfmax = 228900, .val = 0x13 },
-	{ .rfmax = 241600, .val = 0x12 },
-	{ .rfmax = 254400, .val = 0x11 },
-	{ .rfmax = 267100, .val = 0x10 },
-	{ .rfmax = 279800, .val = 0x0f },
-	{ .rfmax = 292500, .val = 0x0e },
-	{ .rfmax = 305200, .val = 0x0d },
-	{ .rfmax = 317900, .val = 0x0c },
-	{ .rfmax = 330700, .val = 0x0b },
-	{ .rfmax = 343400, .val = 0x0a },
-	{ .rfmax = 356100, .val = 0x09 },
-	{ .rfmax = 368800, .val = 0x08 },
-	{ .rfmax = 381500, .val = 0x07 },
-	{ .rfmax = 394200, .val = 0x06 },
-	{ .rfmax = 406900, .val = 0x05 },
-	{ .rfmax = 419700, .val = 0x04 },
-	{ .rfmax = 432400, .val = 0x03 },
-	{ .rfmax = 445100, .val = 0x02 },
-	{ .rfmax = 457800, .val = 0x01 },
-	{ .rfmax = 476300, .val = 0x19 },
-	{ .rfmax = 494800, .val = 0x18 },
-	{ .rfmax = 513300, .val = 0x17 },
-	{ .rfmax = 531800, .val = 0x16 },
-	{ .rfmax = 550300, .val = 0x15 },
-	{ .rfmax = 568900, .val = 0x14 },
-	{ .rfmax = 587400, .val = 0x13 },
-	{ .rfmax = 605900, .val = 0x12 },
-	{ .rfmax = 624400, .val = 0x11 },
-	{ .rfmax = 642900, .val = 0x10 },
-	{ .rfmax = 661400, .val = 0x0f },
-	{ .rfmax = 679900, .val = 0x0e },
-	{ .rfmax = 698400, .val = 0x0d },
-	{ .rfmax = 716900, .val = 0x0c },
-	{ .rfmax = 735400, .val = 0x0b },
-	{ .rfmax = 753900, .val = 0x0a },
-	{ .rfmax = 772500, .val = 0x09 },
-	{ .rfmax = 791000, .val = 0x08 },
-	{ .rfmax = 809500, .val = 0x07 },
-	{ .rfmax = 828000, .val = 0x06 },
-	{ .rfmax = 846500, .val = 0x05 },
-	{ .rfmax = 865000, .val = 0x04 },
-	{ .rfmax =      0, .val = 0x00 }, /* end */
-};
-
-static struct tda18271_map tda18271c1_rf_cal[] = {
-	{ .rfmax = 41000, .val = 0x1e },
-	{ .rfmax = 43000, .val = 0x30 },
-	{ .rfmax = 45000, .val = 0x43 },
-	{ .rfmax = 46000, .val = 0x4d },
-	{ .rfmax = 47000, .val = 0x54 },
-	{ .rfmax = 47900, .val = 0x64 },
-	{ .rfmax = 49100, .val = 0x20 },
-	{ .rfmax = 50000, .val = 0x22 },
-	{ .rfmax = 51000, .val = 0x2a },
-	{ .rfmax = 53000, .val = 0x32 },
-	{ .rfmax = 55000, .val = 0x35 },
-	{ .rfmax = 56000, .val = 0x3c },
-	{ .rfmax = 57000, .val = 0x3f },
-	{ .rfmax = 58000, .val = 0x48 },
-	{ .rfmax = 59000, .val = 0x4d },
-	{ .rfmax = 60000, .val = 0x58 },
-	{ .rfmax = 61100, .val = 0x5f },
-	{ .rfmax =     0, .val = 0x00 }, /* end */
-};
-
-static struct tda18271_map tda18271c2_rf_cal[] = {
-	{ .rfmax =  41000, .val = 0x0f },
-	{ .rfmax =  43000, .val = 0x1c },
-	{ .rfmax =  45000, .val = 0x2f },
-	{ .rfmax =  46000, .val = 0x39 },
-	{ .rfmax =  47000, .val = 0x40 },
-	{ .rfmax =  47900, .val = 0x50 },
-	{ .rfmax =  49100, .val = 0x16 },
-	{ .rfmax =  50000, .val = 0x18 },
-	{ .rfmax =  51000, .val = 0x20 },
-	{ .rfmax =  53000, .val = 0x28 },
-	{ .rfmax =  55000, .val = 0x2b },
-	{ .rfmax =  56000, .val = 0x32 },
-	{ .rfmax =  57000, .val = 0x35 },
-	{ .rfmax =  58000, .val = 0x3e },
-	{ .rfmax =  59000, .val = 0x43 },
-	{ .rfmax =  60000, .val = 0x4e },
-	{ .rfmax =  61100, .val = 0x55 },
-	{ .rfmax =  63000, .val = 0x0f },
-	{ .rfmax =  64000, .val = 0x11 },
-	{ .rfmax =  65000, .val = 0x12 },
-	{ .rfmax =  66000, .val = 0x15 },
-	{ .rfmax =  67000, .val = 0x16 },
-	{ .rfmax =  68000, .val = 0x17 },
-	{ .rfmax =  70000, .val = 0x19 },
-	{ .rfmax =  71000, .val = 0x1c },
-	{ .rfmax =  72000, .val = 0x1d },
-	{ .rfmax =  73000, .val = 0x1f },
-	{ .rfmax =  74000, .val = 0x20 },
-	{ .rfmax =  75000, .val = 0x21 },
-	{ .rfmax =  76000, .val = 0x24 },
-	{ .rfmax =  77000, .val = 0x25 },
-	{ .rfmax =  78000, .val = 0x27 },
-	{ .rfmax =  80000, .val = 0x28 },
-	{ .rfmax =  81000, .val = 0x29 },
-	{ .rfmax =  82000, .val = 0x2d },
-	{ .rfmax =  83000, .val = 0x2e },
-	{ .rfmax =  84000, .val = 0x2f },
-	{ .rfmax =  85000, .val = 0x31 },
-	{ .rfmax =  86000, .val = 0x33 },
-	{ .rfmax =  87000, .val = 0x34 },
-	{ .rfmax =  88000, .val = 0x35 },
-	{ .rfmax =  89000, .val = 0x37 },
-	{ .rfmax =  90000, .val = 0x38 },
-	{ .rfmax =  91000, .val = 0x39 },
-	{ .rfmax =  93000, .val = 0x3c },
-	{ .rfmax =  94000, .val = 0x3e },
-	{ .rfmax =  95000, .val = 0x3f },
-	{ .rfmax =  96000, .val = 0x40 },
-	{ .rfmax =  97000, .val = 0x42 },
-	{ .rfmax =  99000, .val = 0x45 },
-	{ .rfmax = 100000, .val = 0x46 },
-	{ .rfmax = 102000, .val = 0x48 },
-	{ .rfmax = 103000, .val = 0x4a },
-	{ .rfmax = 105000, .val = 0x4d },
-	{ .rfmax = 106000, .val = 0x4e },
-	{ .rfmax = 107000, .val = 0x50 },
-	{ .rfmax = 108000, .val = 0x51 },
-	{ .rfmax = 110000, .val = 0x54 },
-	{ .rfmax = 111000, .val = 0x56 },
-	{ .rfmax = 112000, .val = 0x57 },
-	{ .rfmax = 113000, .val = 0x58 },
-	{ .rfmax = 114000, .val = 0x59 },
-	{ .rfmax = 115000, .val = 0x5c },
-	{ .rfmax = 116000, .val = 0x5d },
-	{ .rfmax = 117000, .val = 0x5f },
-	{ .rfmax = 119000, .val = 0x60 },
-	{ .rfmax = 120000, .val = 0x64 },
-	{ .rfmax = 121000, .val = 0x65 },
-	{ .rfmax = 122000, .val = 0x66 },
-	{ .rfmax = 123000, .val = 0x68 },
-	{ .rfmax = 124000, .val = 0x69 },
-	{ .rfmax = 125000, .val = 0x6c },
-	{ .rfmax = 126000, .val = 0x6d },
-	{ .rfmax = 127000, .val = 0x6e },
-	{ .rfmax = 128000, .val = 0x70 },
-	{ .rfmax = 129000, .val = 0x71 },
-	{ .rfmax = 130000, .val = 0x75 },
-	{ .rfmax = 131000, .val = 0x77 },
-	{ .rfmax = 132000, .val = 0x78 },
-	{ .rfmax = 133000, .val = 0x7b },
-	{ .rfmax = 134000, .val = 0x7e },
-	{ .rfmax = 135000, .val = 0x81 },
-	{ .rfmax = 136000, .val = 0x82 },
-	{ .rfmax = 137000, .val = 0x87 },
-	{ .rfmax = 138000, .val = 0x88 },
-	{ .rfmax = 139000, .val = 0x8d },
-	{ .rfmax = 140000, .val = 0x8e },
-	{ .rfmax = 141000, .val = 0x91 },
-	{ .rfmax = 142000, .val = 0x95 },
-	{ .rfmax = 143000, .val = 0x9a },
-	{ .rfmax = 144000, .val = 0x9d },
-	{ .rfmax = 145000, .val = 0xa1 },
-	{ .rfmax = 146000, .val = 0xa2 },
-	{ .rfmax = 147000, .val = 0xa4 },
-	{ .rfmax = 148000, .val = 0xa9 },
-	{ .rfmax = 149000, .val = 0xae },
-	{ .rfmax = 150000, .val = 0xb0 },
-	{ .rfmax = 151000, .val = 0xb1 },
-	{ .rfmax = 152000, .val = 0xb7 },
-	{ .rfmax = 152600, .val = 0xbd },
-	{ .rfmax = 154000, .val = 0x20 },
-	{ .rfmax = 155000, .val = 0x22 },
-	{ .rfmax = 156000, .val = 0x24 },
-	{ .rfmax = 157000, .val = 0x25 },
-	{ .rfmax = 158000, .val = 0x27 },
-	{ .rfmax = 159000, .val = 0x29 },
-	{ .rfmax = 160000, .val = 0x2c },
-	{ .rfmax = 161000, .val = 0x2d },
-	{ .rfmax = 163000, .val = 0x2e },
-	{ .rfmax = 164000, .val = 0x2f },
-	{ .rfmax = 164700, .val = 0x30 },
-	{ .rfmax = 166000, .val = 0x11 },
-	{ .rfmax = 167000, .val = 0x12 },
-	{ .rfmax = 168000, .val = 0x13 },
-	{ .rfmax = 169000, .val = 0x14 },
-	{ .rfmax = 170000, .val = 0x15 },
-	{ .rfmax = 172000, .val = 0x16 },
-	{ .rfmax = 173000, .val = 0x17 },
-	{ .rfmax = 174000, .val = 0x18 },
-	{ .rfmax = 175000, .val = 0x1a },
-	{ .rfmax = 176000, .val = 0x1b },
-	{ .rfmax = 178000, .val = 0x1d },
-	{ .rfmax = 179000, .val = 0x1e },
-	{ .rfmax = 180000, .val = 0x1f },
-	{ .rfmax = 181000, .val = 0x20 },
-	{ .rfmax = 182000, .val = 0x21 },
-	{ .rfmax = 183000, .val = 0x22 },
-	{ .rfmax = 184000, .val = 0x24 },
-	{ .rfmax = 185000, .val = 0x25 },
-	{ .rfmax = 186000, .val = 0x26 },
-	{ .rfmax = 187000, .val = 0x27 },
-	{ .rfmax = 188000, .val = 0x29 },
-	{ .rfmax = 189000, .val = 0x2a },
-	{ .rfmax = 190000, .val = 0x2c },
-	{ .rfmax = 191000, .val = 0x2d },
-	{ .rfmax = 192000, .val = 0x2e },
-	{ .rfmax = 193000, .val = 0x2f },
-	{ .rfmax = 194000, .val = 0x30 },
-	{ .rfmax = 195000, .val = 0x33 },
-	{ .rfmax = 196000, .val = 0x35 },
-	{ .rfmax = 198000, .val = 0x36 },
-	{ .rfmax = 200000, .val = 0x38 },
-	{ .rfmax = 201000, .val = 0x3c },
-	{ .rfmax = 202000, .val = 0x3d },
-	{ .rfmax = 203500, .val = 0x3e },
-	{ .rfmax = 206000, .val = 0x0e },
-	{ .rfmax = 208000, .val = 0x0f },
-	{ .rfmax = 212000, .val = 0x10 },
-	{ .rfmax = 216000, .val = 0x11 },
-	{ .rfmax = 217000, .val = 0x12 },
-	{ .rfmax = 218000, .val = 0x13 },
-	{ .rfmax = 220000, .val = 0x14 },
-	{ .rfmax = 222000, .val = 0x15 },
-	{ .rfmax = 225000, .val = 0x16 },
-	{ .rfmax = 228000, .val = 0x17 },
-	{ .rfmax = 231000, .val = 0x18 },
-	{ .rfmax = 234000, .val = 0x19 },
-	{ .rfmax = 235000, .val = 0x1a },
-	{ .rfmax = 236000, .val = 0x1b },
-	{ .rfmax = 237000, .val = 0x1c },
-	{ .rfmax = 240000, .val = 0x1d },
-	{ .rfmax = 242000, .val = 0x1e },
-	{ .rfmax = 244000, .val = 0x1f },
-	{ .rfmax = 247000, .val = 0x20 },
-	{ .rfmax = 249000, .val = 0x21 },
-	{ .rfmax = 252000, .val = 0x22 },
-	{ .rfmax = 253000, .val = 0x23 },
-	{ .rfmax = 254000, .val = 0x24 },
-	{ .rfmax = 256000, .val = 0x25 },
-	{ .rfmax = 259000, .val = 0x26 },
-	{ .rfmax = 262000, .val = 0x27 },
-	{ .rfmax = 264000, .val = 0x28 },
-	{ .rfmax = 267000, .val = 0x29 },
-	{ .rfmax = 269000, .val = 0x2a },
-	{ .rfmax = 271000, .val = 0x2b },
-	{ .rfmax = 273000, .val = 0x2c },
-	{ .rfmax = 275000, .val = 0x2d },
-	{ .rfmax = 277000, .val = 0x2e },
-	{ .rfmax = 279000, .val = 0x2f },
-	{ .rfmax = 282000, .val = 0x30 },
-	{ .rfmax = 284000, .val = 0x31 },
-	{ .rfmax = 286000, .val = 0x32 },
-	{ .rfmax = 287000, .val = 0x33 },
-	{ .rfmax = 290000, .val = 0x34 },
-	{ .rfmax = 293000, .val = 0x35 },
-	{ .rfmax = 295000, .val = 0x36 },
-	{ .rfmax = 297000, .val = 0x37 },
-	{ .rfmax = 300000, .val = 0x38 },
-	{ .rfmax = 303000, .val = 0x39 },
-	{ .rfmax = 305000, .val = 0x3a },
-	{ .rfmax = 306000, .val = 0x3b },
-	{ .rfmax = 307000, .val = 0x3c },
-	{ .rfmax = 310000, .val = 0x3d },
-	{ .rfmax = 312000, .val = 0x3e },
-	{ .rfmax = 315000, .val = 0x3f },
-	{ .rfmax = 318000, .val = 0x40 },
-	{ .rfmax = 320000, .val = 0x41 },
-	{ .rfmax = 323000, .val = 0x42 },
-	{ .rfmax = 324000, .val = 0x43 },
-	{ .rfmax = 325000, .val = 0x44 },
-	{ .rfmax = 327000, .val = 0x45 },
-	{ .rfmax = 331000, .val = 0x46 },
-	{ .rfmax = 334000, .val = 0x47 },
-	{ .rfmax = 337000, .val = 0x48 },
-	{ .rfmax = 339000, .val = 0x49 },
-	{ .rfmax = 340000, .val = 0x4a },
-	{ .rfmax = 341000, .val = 0x4b },
-	{ .rfmax = 343000, .val = 0x4c },
-	{ .rfmax = 345000, .val = 0x4d },
-	{ .rfmax = 349000, .val = 0x4e },
-	{ .rfmax = 352000, .val = 0x4f },
-	{ .rfmax = 353000, .val = 0x50 },
-	{ .rfmax = 355000, .val = 0x51 },
-	{ .rfmax = 357000, .val = 0x52 },
-	{ .rfmax = 359000, .val = 0x53 },
-	{ .rfmax = 361000, .val = 0x54 },
-	{ .rfmax = 362000, .val = 0x55 },
-	{ .rfmax = 364000, .val = 0x56 },
-	{ .rfmax = 368000, .val = 0x57 },
-	{ .rfmax = 370000, .val = 0x58 },
-	{ .rfmax = 372000, .val = 0x59 },
-	{ .rfmax = 375000, .val = 0x5a },
-	{ .rfmax = 376000, .val = 0x5b },
-	{ .rfmax = 377000, .val = 0x5c },
-	{ .rfmax = 379000, .val = 0x5d },
-	{ .rfmax = 382000, .val = 0x5e },
-	{ .rfmax = 384000, .val = 0x5f },
-	{ .rfmax = 385000, .val = 0x60 },
-	{ .rfmax = 386000, .val = 0x61 },
-	{ .rfmax = 388000, .val = 0x62 },
-	{ .rfmax = 390000, .val = 0x63 },
-	{ .rfmax = 393000, .val = 0x64 },
-	{ .rfmax = 394000, .val = 0x65 },
-	{ .rfmax = 396000, .val = 0x66 },
-	{ .rfmax = 397000, .val = 0x67 },
-	{ .rfmax = 398000, .val = 0x68 },
-	{ .rfmax = 400000, .val = 0x69 },
-	{ .rfmax = 402000, .val = 0x6a },
-	{ .rfmax = 403000, .val = 0x6b },
-	{ .rfmax = 407000, .val = 0x6c },
-	{ .rfmax = 408000, .val = 0x6d },
-	{ .rfmax = 409000, .val = 0x6e },
-	{ .rfmax = 410000, .val = 0x6f },
-	{ .rfmax = 411000, .val = 0x70 },
-	{ .rfmax = 412000, .val = 0x71 },
-	{ .rfmax = 413000, .val = 0x72 },
-	{ .rfmax = 414000, .val = 0x73 },
-	{ .rfmax = 417000, .val = 0x74 },
-	{ .rfmax = 418000, .val = 0x75 },
-	{ .rfmax = 420000, .val = 0x76 },
-	{ .rfmax = 422000, .val = 0x77 },
-	{ .rfmax = 423000, .val = 0x78 },
-	{ .rfmax = 424000, .val = 0x79 },
-	{ .rfmax = 427000, .val = 0x7a },
-	{ .rfmax = 428000, .val = 0x7b },
-	{ .rfmax = 429000, .val = 0x7d },
-	{ .rfmax = 432000, .val = 0x7f },
-	{ .rfmax = 434000, .val = 0x80 },
-	{ .rfmax = 435000, .val = 0x81 },
-	{ .rfmax = 436000, .val = 0x83 },
-	{ .rfmax = 437000, .val = 0x84 },
-	{ .rfmax = 438000, .val = 0x85 },
-	{ .rfmax = 439000, .val = 0x86 },
-	{ .rfmax = 440000, .val = 0x87 },
-	{ .rfmax = 441000, .val = 0x88 },
-	{ .rfmax = 442000, .val = 0x89 },
-	{ .rfmax = 445000, .val = 0x8a },
-	{ .rfmax = 446000, .val = 0x8b },
-	{ .rfmax = 447000, .val = 0x8c },
-	{ .rfmax = 448000, .val = 0x8e },
-	{ .rfmax = 449000, .val = 0x8f },
-	{ .rfmax = 450000, .val = 0x90 },
-	{ .rfmax = 452000, .val = 0x91 },
-	{ .rfmax = 453000, .val = 0x93 },
-	{ .rfmax = 454000, .val = 0x94 },
-	{ .rfmax = 456000, .val = 0x96 },
-	{ .rfmax = 457800, .val = 0x98 },
-	{ .rfmax = 461000, .val = 0x11 },
-	{ .rfmax = 468000, .val = 0x12 },
-	{ .rfmax = 472000, .val = 0x13 },
-	{ .rfmax = 473000, .val = 0x14 },
-	{ .rfmax = 474000, .val = 0x15 },
-	{ .rfmax = 481000, .val = 0x16 },
-	{ .rfmax = 486000, .val = 0x17 },
-	{ .rfmax = 491000, .val = 0x18 },
-	{ .rfmax = 498000, .val = 0x19 },
-	{ .rfmax = 499000, .val = 0x1a },
-	{ .rfmax = 501000, .val = 0x1b },
-	{ .rfmax = 506000, .val = 0x1c },
-	{ .rfmax = 511000, .val = 0x1d },
-	{ .rfmax = 516000, .val = 0x1e },
-	{ .rfmax = 520000, .val = 0x1f },
-	{ .rfmax = 521000, .val = 0x20 },
-	{ .rfmax = 525000, .val = 0x21 },
-	{ .rfmax = 529000, .val = 0x22 },
-	{ .rfmax = 533000, .val = 0x23 },
-	{ .rfmax = 539000, .val = 0x24 },
-	{ .rfmax = 541000, .val = 0x25 },
-	{ .rfmax = 547000, .val = 0x26 },
-	{ .rfmax = 549000, .val = 0x27 },
-	{ .rfmax = 551000, .val = 0x28 },
-	{ .rfmax = 556000, .val = 0x29 },
-	{ .rfmax = 561000, .val = 0x2a },
-	{ .rfmax = 563000, .val = 0x2b },
-	{ .rfmax = 565000, .val = 0x2c },
-	{ .rfmax = 569000, .val = 0x2d },
-	{ .rfmax = 571000, .val = 0x2e },
-	{ .rfmax = 577000, .val = 0x2f },
-	{ .rfmax = 580000, .val = 0x30 },
-	{ .rfmax = 582000, .val = 0x31 },
-	{ .rfmax = 584000, .val = 0x32 },
-	{ .rfmax = 588000, .val = 0x33 },
-	{ .rfmax = 591000, .val = 0x34 },
-	{ .rfmax = 596000, .val = 0x35 },
-	{ .rfmax = 598000, .val = 0x36 },
-	{ .rfmax = 603000, .val = 0x37 },
-	{ .rfmax = 604000, .val = 0x38 },
-	{ .rfmax = 606000, .val = 0x39 },
-	{ .rfmax = 612000, .val = 0x3a },
-	{ .rfmax = 615000, .val = 0x3b },
-	{ .rfmax = 617000, .val = 0x3c },
-	{ .rfmax = 621000, .val = 0x3d },
-	{ .rfmax = 622000, .val = 0x3e },
-	{ .rfmax = 625000, .val = 0x3f },
-	{ .rfmax = 632000, .val = 0x40 },
-	{ .rfmax = 633000, .val = 0x41 },
-	{ .rfmax = 634000, .val = 0x42 },
-	{ .rfmax = 642000, .val = 0x43 },
-	{ .rfmax = 643000, .val = 0x44 },
-	{ .rfmax = 647000, .val = 0x45 },
-	{ .rfmax = 650000, .val = 0x46 },
-	{ .rfmax = 652000, .val = 0x47 },
-	{ .rfmax = 657000, .val = 0x48 },
-	{ .rfmax = 661000, .val = 0x49 },
-	{ .rfmax = 662000, .val = 0x4a },
-	{ .rfmax = 665000, .val = 0x4b },
-	{ .rfmax = 667000, .val = 0x4c },
-	{ .rfmax = 670000, .val = 0x4d },
-	{ .rfmax = 673000, .val = 0x4e },
-	{ .rfmax = 676000, .val = 0x4f },
-	{ .rfmax = 677000, .val = 0x50 },
-	{ .rfmax = 681000, .val = 0x51 },
-	{ .rfmax = 683000, .val = 0x52 },
-	{ .rfmax = 686000, .val = 0x53 },
-	{ .rfmax = 688000, .val = 0x54 },
-	{ .rfmax = 689000, .val = 0x55 },
-	{ .rfmax = 691000, .val = 0x56 },
-	{ .rfmax = 695000, .val = 0x57 },
-	{ .rfmax = 698000, .val = 0x58 },
-	{ .rfmax = 703000, .val = 0x59 },
-	{ .rfmax = 704000, .val = 0x5a },
-	{ .rfmax = 705000, .val = 0x5b },
-	{ .rfmax = 707000, .val = 0x5c },
-	{ .rfmax = 710000, .val = 0x5d },
-	{ .rfmax = 712000, .val = 0x5e },
-	{ .rfmax = 717000, .val = 0x5f },
-	{ .rfmax = 718000, .val = 0x60 },
-	{ .rfmax = 721000, .val = 0x61 },
-	{ .rfmax = 722000, .val = 0x62 },
-	{ .rfmax = 723000, .val = 0x63 },
-	{ .rfmax = 725000, .val = 0x64 },
-	{ .rfmax = 727000, .val = 0x65 },
-	{ .rfmax = 730000, .val = 0x66 },
-	{ .rfmax = 732000, .val = 0x67 },
-	{ .rfmax = 735000, .val = 0x68 },
-	{ .rfmax = 740000, .val = 0x69 },
-	{ .rfmax = 741000, .val = 0x6a },
-	{ .rfmax = 742000, .val = 0x6b },
-	{ .rfmax = 743000, .val = 0x6c },
-	{ .rfmax = 745000, .val = 0x6d },
-	{ .rfmax = 747000, .val = 0x6e },
-	{ .rfmax = 748000, .val = 0x6f },
-	{ .rfmax = 750000, .val = 0x70 },
-	{ .rfmax = 752000, .val = 0x71 },
-	{ .rfmax = 754000, .val = 0x72 },
-	{ .rfmax = 757000, .val = 0x73 },
-	{ .rfmax = 758000, .val = 0x74 },
-	{ .rfmax = 760000, .val = 0x75 },
-	{ .rfmax = 763000, .val = 0x76 },
-	{ .rfmax = 764000, .val = 0x77 },
-	{ .rfmax = 766000, .val = 0x78 },
-	{ .rfmax = 767000, .val = 0x79 },
-	{ .rfmax = 768000, .val = 0x7a },
-	{ .rfmax = 773000, .val = 0x7b },
-	{ .rfmax = 774000, .val = 0x7c },
-	{ .rfmax = 776000, .val = 0x7d },
-	{ .rfmax = 777000, .val = 0x7e },
-	{ .rfmax = 778000, .val = 0x7f },
-	{ .rfmax = 779000, .val = 0x80 },
-	{ .rfmax = 781000, .val = 0x81 },
-	{ .rfmax = 783000, .val = 0x82 },
-	{ .rfmax = 784000, .val = 0x83 },
-	{ .rfmax = 785000, .val = 0x84 },
-	{ .rfmax = 786000, .val = 0x85 },
-	{ .rfmax = 793000, .val = 0x86 },
-	{ .rfmax = 794000, .val = 0x87 },
-	{ .rfmax = 795000, .val = 0x88 },
-	{ .rfmax = 797000, .val = 0x89 },
-	{ .rfmax = 799000, .val = 0x8a },
-	{ .rfmax = 801000, .val = 0x8b },
-	{ .rfmax = 802000, .val = 0x8c },
-	{ .rfmax = 803000, .val = 0x8d },
-	{ .rfmax = 804000, .val = 0x8e },
-	{ .rfmax = 810000, .val = 0x90 },
-	{ .rfmax = 811000, .val = 0x91 },
-	{ .rfmax = 812000, .val = 0x92 },
-	{ .rfmax = 814000, .val = 0x93 },
-	{ .rfmax = 816000, .val = 0x94 },
-	{ .rfmax = 817000, .val = 0x96 },
-	{ .rfmax = 818000, .val = 0x97 },
-	{ .rfmax = 820000, .val = 0x98 },
-	{ .rfmax = 821000, .val = 0x99 },
-	{ .rfmax = 822000, .val = 0x9a },
-	{ .rfmax = 828000, .val = 0x9b },
-	{ .rfmax = 829000, .val = 0x9d },
-	{ .rfmax = 830000, .val = 0x9f },
-	{ .rfmax = 831000, .val = 0xa0 },
-	{ .rfmax = 833000, .val = 0xa1 },
-	{ .rfmax = 835000, .val = 0xa2 },
-	{ .rfmax = 836000, .val = 0xa3 },
-	{ .rfmax = 837000, .val = 0xa4 },
-	{ .rfmax = 838000, .val = 0xa6 },
-	{ .rfmax = 840000, .val = 0xa8 },
-	{ .rfmax = 842000, .val = 0xa9 },
-	{ .rfmax = 845000, .val = 0xaa },
-	{ .rfmax = 846000, .val = 0xab },
-	{ .rfmax = 847000, .val = 0xad },
-	{ .rfmax = 848000, .val = 0xae },
-	{ .rfmax = 852000, .val = 0xaf },
-	{ .rfmax = 853000, .val = 0xb0 },
-	{ .rfmax = 858000, .val = 0xb1 },
-	{ .rfmax = 860000, .val = 0xb2 },
-	{ .rfmax = 861000, .val = 0xb3 },
-	{ .rfmax = 862000, .val = 0xb4 },
-	{ .rfmax = 863000, .val = 0xb6 },
-	{ .rfmax = 864000, .val = 0xb8 },
-	{ .rfmax = 865000, .val = 0xb9 },
-	{ .rfmax =      0, .val = 0x00 }, /* end */
-};
-
-static struct tda18271_map tda18271_ir_measure[] = {
-	{ .rfmax =  30000, .val = 4 },
-	{ .rfmax = 200000, .val = 5 },
-	{ .rfmax = 600000, .val = 6 },
-	{ .rfmax = 865000, .val = 7 },
-	{ .rfmax =      0, .val = 0 }, /* end */
-};
-
-static struct tda18271_map tda18271_rf_cal_dc_over_dt[] = {
-	{ .rfmax =  47900, .val = 0x00 },
-	{ .rfmax =  55000, .val = 0x00 },
-	{ .rfmax =  61100, .val = 0x0a },
-	{ .rfmax =  64000, .val = 0x0a },
-	{ .rfmax =  82000, .val = 0x14 },
-	{ .rfmax =  84000, .val = 0x19 },
-	{ .rfmax = 119000, .val = 0x1c },
-	{ .rfmax = 124000, .val = 0x20 },
-	{ .rfmax = 129000, .val = 0x2a },
-	{ .rfmax = 134000, .val = 0x32 },
-	{ .rfmax = 139000, .val = 0x39 },
-	{ .rfmax = 144000, .val = 0x3e },
-	{ .rfmax = 149000, .val = 0x3f },
-	{ .rfmax = 152600, .val = 0x40 },
-	{ .rfmax = 154000, .val = 0x40 },
-	{ .rfmax = 164700, .val = 0x41 },
-	{ .rfmax = 203500, .val = 0x32 },
-	{ .rfmax = 353000, .val = 0x19 },
-	{ .rfmax = 356000, .val = 0x1a },
-	{ .rfmax = 359000, .val = 0x1b },
-	{ .rfmax = 363000, .val = 0x1c },
-	{ .rfmax = 366000, .val = 0x1d },
-	{ .rfmax = 369000, .val = 0x1e },
-	{ .rfmax = 373000, .val = 0x1f },
-	{ .rfmax = 376000, .val = 0x20 },
-	{ .rfmax = 379000, .val = 0x21 },
-	{ .rfmax = 383000, .val = 0x22 },
-	{ .rfmax = 386000, .val = 0x23 },
-	{ .rfmax = 389000, .val = 0x24 },
-	{ .rfmax = 393000, .val = 0x25 },
-	{ .rfmax = 396000, .val = 0x26 },
-	{ .rfmax = 399000, .val = 0x27 },
-	{ .rfmax = 402000, .val = 0x28 },
-	{ .rfmax = 404000, .val = 0x29 },
-	{ .rfmax = 407000, .val = 0x2a },
-	{ .rfmax = 409000, .val = 0x2b },
-	{ .rfmax = 412000, .val = 0x2c },
-	{ .rfmax = 414000, .val = 0x2d },
-	{ .rfmax = 417000, .val = 0x2e },
-	{ .rfmax = 419000, .val = 0x2f },
-	{ .rfmax = 422000, .val = 0x30 },
-	{ .rfmax = 424000, .val = 0x31 },
-	{ .rfmax = 427000, .val = 0x32 },
-	{ .rfmax = 429000, .val = 0x33 },
-	{ .rfmax = 432000, .val = 0x34 },
-	{ .rfmax = 434000, .val = 0x35 },
-	{ .rfmax = 437000, .val = 0x36 },
-	{ .rfmax = 439000, .val = 0x37 },
-	{ .rfmax = 442000, .val = 0x38 },
-	{ .rfmax = 444000, .val = 0x39 },
-	{ .rfmax = 447000, .val = 0x3a },
-	{ .rfmax = 449000, .val = 0x3b },
-	{ .rfmax = 457800, .val = 0x3c },
-	{ .rfmax = 465000, .val = 0x0f },
-	{ .rfmax = 477000, .val = 0x12 },
-	{ .rfmax = 483000, .val = 0x14 },
-	{ .rfmax = 502000, .val = 0x19 },
-	{ .rfmax = 508000, .val = 0x1b },
-	{ .rfmax = 519000, .val = 0x1c },
-	{ .rfmax = 522000, .val = 0x1d },
-	{ .rfmax = 524000, .val = 0x1e },
-	{ .rfmax = 534000, .val = 0x1f },
-	{ .rfmax = 549000, .val = 0x20 },
-	{ .rfmax = 554000, .val = 0x22 },
-	{ .rfmax = 584000, .val = 0x24 },
-	{ .rfmax = 589000, .val = 0x26 },
-	{ .rfmax = 658000, .val = 0x27 },
-	{ .rfmax = 664000, .val = 0x2c },
-	{ .rfmax = 669000, .val = 0x2d },
-	{ .rfmax = 699000, .val = 0x2e },
-	{ .rfmax = 704000, .val = 0x30 },
-	{ .rfmax = 709000, .val = 0x31 },
-	{ .rfmax = 714000, .val = 0x32 },
-	{ .rfmax = 724000, .val = 0x33 },
-	{ .rfmax = 729000, .val = 0x36 },
-	{ .rfmax = 739000, .val = 0x38 },
-	{ .rfmax = 744000, .val = 0x39 },
-	{ .rfmax = 749000, .val = 0x3b },
-	{ .rfmax = 754000, .val = 0x3c },
-	{ .rfmax = 759000, .val = 0x3d },
-	{ .rfmax = 764000, .val = 0x3e },
-	{ .rfmax = 769000, .val = 0x3f },
-	{ .rfmax = 774000, .val = 0x40 },
-	{ .rfmax = 779000, .val = 0x41 },
-	{ .rfmax = 784000, .val = 0x43 },
-	{ .rfmax = 789000, .val = 0x46 },
-	{ .rfmax = 794000, .val = 0x48 },
-	{ .rfmax = 799000, .val = 0x4b },
-	{ .rfmax = 804000, .val = 0x4f },
-	{ .rfmax = 809000, .val = 0x54 },
-	{ .rfmax = 814000, .val = 0x59 },
-	{ .rfmax = 819000, .val = 0x5d },
-	{ .rfmax = 824000, .val = 0x61 },
-	{ .rfmax = 829000, .val = 0x68 },
-	{ .rfmax = 834000, .val = 0x6e },
-	{ .rfmax = 839000, .val = 0x75 },
-	{ .rfmax = 844000, .val = 0x7e },
-	{ .rfmax = 849000, .val = 0x82 },
-	{ .rfmax = 854000, .val = 0x84 },
-	{ .rfmax = 859000, .val = 0x8f },
-	{ .rfmax = 865000, .val = 0x9a },
-	{ .rfmax =      0, .val = 0x00 }, /* end */
-};
-
-/*---------------------------------------------------------------------*/
-
-struct tda18271_thermo_map {
-	u8 d;
-	u8 r0;
-	u8 r1;
-};
-
-static struct tda18271_thermo_map tda18271_thermometer[] = {
-	{ .d = 0x00, .r0 = 60, .r1 =  92 },
-	{ .d = 0x01, .r0 = 62, .r1 =  94 },
-	{ .d = 0x02, .r0 = 66, .r1 =  98 },
-	{ .d = 0x03, .r0 = 64, .r1 =  96 },
-	{ .d = 0x04, .r0 = 74, .r1 = 106 },
-	{ .d = 0x05, .r0 = 72, .r1 = 104 },
-	{ .d = 0x06, .r0 = 68, .r1 = 100 },
-	{ .d = 0x07, .r0 = 70, .r1 = 102 },
-	{ .d = 0x08, .r0 = 90, .r1 = 122 },
-	{ .d = 0x09, .r0 = 88, .r1 = 120 },
-	{ .d = 0x0a, .r0 = 84, .r1 = 116 },
-	{ .d = 0x0b, .r0 = 86, .r1 = 118 },
-	{ .d = 0x0c, .r0 = 76, .r1 = 108 },
-	{ .d = 0x0d, .r0 = 78, .r1 = 110 },
-	{ .d = 0x0e, .r0 = 82, .r1 = 114 },
-	{ .d = 0x0f, .r0 = 80, .r1 = 112 },
-	{ .d = 0x00, .r0 =  0, .r1 =   0 }, /* end */
-};
-
-int tda18271_lookup_thermometer(struct dvb_frontend *fe)
-{
-	struct tda18271_priv *priv = fe->tuner_priv;
-	unsigned char *regs = priv->tda18271_regs;
-	int val, i = 0;
-
-	while (tda18271_thermometer[i].d < (regs[R_TM] & 0x0f)) {
-		if (tda18271_thermometer[i + 1].d == 0)
-			break;
-		i++;
-	}
-
-	if ((regs[R_TM] & 0x20) == 0x20)
-		val = tda18271_thermometer[i].r1;
-	else
-		val = tda18271_thermometer[i].r0;
-
-	tda_map("(%d) tm = %d\n", i, val);
-
-	return val;
-}
-
-/*---------------------------------------------------------------------*/
-
-struct tda18271_cid_target_map {
-	u32 rfmax;
-	u8  target;
-	u16 limit;
-};
-
-static struct tda18271_cid_target_map tda18271_cid_target[] = {
-	{ .rfmax =  46000, .target = 0x04, .limit =  1800 },
-	{ .rfmax =  52200, .target = 0x0a, .limit =  1500 },
-	{ .rfmax =  70100, .target = 0x01, .limit =  4000 },
-	{ .rfmax = 136800, .target = 0x18, .limit =  4000 },
-	{ .rfmax = 156700, .target = 0x18, .limit =  4000 },
-	{ .rfmax = 186250, .target = 0x0a, .limit =  4000 },
-	{ .rfmax = 230000, .target = 0x0a, .limit =  4000 },
-	{ .rfmax = 345000, .target = 0x18, .limit =  4000 },
-	{ .rfmax = 426000, .target = 0x0e, .limit =  4000 },
-	{ .rfmax = 489500, .target = 0x1e, .limit =  4000 },
-	{ .rfmax = 697500, .target = 0x32, .limit =  4000 },
-	{ .rfmax = 842000, .target = 0x3a, .limit =  4000 },
-	{ .rfmax =      0, .target = 0x00, .limit =     0 }, /* end */
-};
-
-int tda18271_lookup_cid_target(struct dvb_frontend *fe,
-			       u32 *freq, u8 *cid_target, u16 *count_limit)
-{
-	struct tda18271_priv *priv = fe->tuner_priv;
-	int i = 0;
-
-	while ((tda18271_cid_target[i].rfmax * 1000) < *freq) {
-		if (tda18271_cid_target[i + 1].rfmax == 0)
-			break;
-		i++;
-	}
-	*cid_target  = tda18271_cid_target[i].target;
-	*count_limit = tda18271_cid_target[i].limit;
-
-	tda_map("(%d) cid_target = %02x, count_limit = %d\n", i,
-		tda18271_cid_target[i].target, tda18271_cid_target[i].limit);
-
-	return 0;
-}
-
-/*---------------------------------------------------------------------*/
-
-static struct tda18271_rf_tracking_filter_cal tda18271_rf_band_template[] = {
-	{ .rfmax =  47900, .rfband = 0x00,
-	  .rf1_def =  46000, .rf2_def =      0, .rf3_def =      0 },
-	{ .rfmax =  61100, .rfband = 0x01,
-	  .rf1_def =  52200, .rf2_def =      0, .rf3_def =      0 },
-	{ .rfmax = 152600, .rfband = 0x02,
-	  .rf1_def =  70100, .rf2_def = 136800, .rf3_def =      0 },
-	{ .rfmax = 164700, .rfband = 0x03,
-	  .rf1_def = 156700, .rf2_def =      0, .rf3_def =      0 },
-	{ .rfmax = 203500, .rfband = 0x04,
-	  .rf1_def = 186250, .rf2_def =      0, .rf3_def =      0 },
-	{ .rfmax = 457800, .rfband = 0x05,
-	  .rf1_def = 230000, .rf2_def = 345000, .rf3_def = 426000 },
-	{ .rfmax = 865000, .rfband = 0x06,
-	  .rf1_def = 489500, .rf2_def = 697500, .rf3_def = 842000 },
-	{ .rfmax =      0, .rfband = 0x00,
-	  .rf1_def =      0, .rf2_def =      0, .rf3_def =      0 }, /* end */
-};
-
-int tda18271_lookup_rf_band(struct dvb_frontend *fe, u32 *freq, u8 *rf_band)
-{
-	struct tda18271_priv *priv = fe->tuner_priv;
-	struct tda18271_rf_tracking_filter_cal *map = priv->rf_cal_state;
-	int i = 0;
-
-	while ((map[i].rfmax * 1000) < *freq) {
-		if (tda18271_debug & DBG_ADV)
-			tda_map("(%d) rfmax = %d < freq = %d, "
-				"rf1_def = %d, rf2_def = %d, rf3_def = %d, "
-				"rf1 = %d, rf2 = %d, rf3 = %d, "
-				"rf_a1 = %d, rf_a2 = %d, "
-				"rf_b1 = %d, rf_b2 = %d\n",
-				i, map[i].rfmax * 1000, *freq,
-				map[i].rf1_def, map[i].rf2_def, map[i].rf3_def,
-				map[i].rf1, map[i].rf2, map[i].rf3,
-				map[i].rf_a1, map[i].rf_a2,
-				map[i].rf_b1, map[i].rf_b2);
-		if (map[i].rfmax == 0)
-			return -EINVAL;
-		i++;
-	}
-	if (rf_band)
-		*rf_band = map[i].rfband;
-
-	tda_map("(%d) rf_band = %02x\n", i, map[i].rfband);
-
-	return i;
-}
-
-/*---------------------------------------------------------------------*/
-
-struct tda18271_map_layout {
-	struct tda18271_pll_map *main_pll;
-	struct tda18271_pll_map *cal_pll;
-
-	struct tda18271_map *rf_cal;
-	struct tda18271_map *rf_cal_kmco;
-	struct tda18271_map *rf_cal_dc_over_dt;
-
-	struct tda18271_map *bp_filter;
-	struct tda18271_map *rf_band;
-	struct tda18271_map *gain_taper;
-	struct tda18271_map *ir_measure;
-};
-
-/*---------------------------------------------------------------------*/
-
-int tda18271_lookup_pll_map(struct dvb_frontend *fe,
-			    enum tda18271_map_type map_type,
-			    u32 *freq, u8 *post_div, u8 *div)
-{
-	struct tda18271_priv *priv = fe->tuner_priv;
-	struct tda18271_pll_map *map = NULL;
-	unsigned int i = 0;
-	char *map_name;
-	int ret = 0;
-
-	BUG_ON(!priv->maps);
-
-	switch (map_type) {
-	case MAIN_PLL:
-		map = priv->maps->main_pll;
-		map_name = "main_pll";
-		break;
-	case CAL_PLL:
-		map = priv->maps->cal_pll;
-		map_name = "cal_pll";
-		break;
-	default:
-		/* we should never get here */
-		map_name = "undefined";
-		break;
-	}
-
-	if (!map) {
-		tda_warn("%s map is not set!\n", map_name);
-		ret = -EINVAL;
-		goto fail;
-	}
-
-	while ((map[i].lomax * 1000) < *freq) {
-		if (map[i + 1].lomax == 0) {
-			tda_map("%s: frequency (%d) out of range\n",
-				map_name, *freq);
-			ret = -ERANGE;
-			break;
-		}
-		i++;
-	}
-	*post_div = map[i].pd;
-	*div      = map[i].d;
-
-	tda_map("(%d) %s: post div = 0x%02x, div = 0x%02x\n",
-		i, map_name, *post_div, *div);
-fail:
-	return ret;
-}
-
-int tda18271_lookup_map(struct dvb_frontend *fe,
-			enum tda18271_map_type map_type,
-			u32 *freq, u8 *val)
-{
-	struct tda18271_priv *priv = fe->tuner_priv;
-	struct tda18271_map *map = NULL;
-	unsigned int i = 0;
-	char *map_name;
-	int ret = 0;
-
-	BUG_ON(!priv->maps);
-
-	switch (map_type) {
-	case BP_FILTER:
-		map = priv->maps->bp_filter;
-		map_name = "bp_filter";
-		break;
-	case RF_CAL_KMCO:
-		map = priv->maps->rf_cal_kmco;
-		map_name = "km";
-		break;
-	case RF_BAND:
-		map = priv->maps->rf_band;
-		map_name = "rf_band";
-		break;
-	case GAIN_TAPER:
-		map = priv->maps->gain_taper;
-		map_name = "gain_taper";
-		break;
-	case RF_CAL:
-		map = priv->maps->rf_cal;
-		map_name = "rf_cal";
-		break;
-	case IR_MEASURE:
-		map = priv->maps->ir_measure;
-		map_name = "ir_measure";
-		break;
-	case RF_CAL_DC_OVER_DT:
-		map = priv->maps->rf_cal_dc_over_dt;
-		map_name = "rf_cal_dc_over_dt";
-		break;
-	default:
-		/* we should never get here */
-		map_name = "undefined";
-		break;
-	}
-
-	if (!map) {
-		tda_warn("%s map is not set!\n", map_name);
-		ret = -EINVAL;
-		goto fail;
-	}
-
-	while ((map[i].rfmax * 1000) < *freq) {
-		if (map[i + 1].rfmax == 0) {
-			tda_map("%s: frequency (%d) out of range\n",
-				map_name, *freq);
-			ret = -ERANGE;
-			break;
-		}
-		i++;
-	}
-	*val = map[i].val;
-
-	tda_map("(%d) %s: 0x%02x\n", i, map_name, *val);
-fail:
-	return ret;
-}
-
-/*---------------------------------------------------------------------*/
-
-static struct tda18271_std_map tda18271c1_std_map = {
-	.fm_radio = { .if_freq = 1250, .fm_rfn = 1, .agc_mode = 3, .std = 0,
-		      .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x18 */
-	.atv_b    = { .if_freq = 6750, .fm_rfn = 0, .agc_mode = 1, .std = 6,
-		      .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0e */
-	.atv_dk   = { .if_freq = 7750, .fm_rfn = 0, .agc_mode = 1, .std = 7,
-		      .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0f */
-	.atv_gh   = { .if_freq = 7750, .fm_rfn = 0, .agc_mode = 1, .std = 7,
-		      .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0f */
-	.atv_i    = { .if_freq = 7750, .fm_rfn = 0, .agc_mode = 1, .std = 7,
-		      .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0f */
-	.atv_l    = { .if_freq = 7750, .fm_rfn = 0, .agc_mode = 1, .std = 7,
-		      .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0f */
-	.atv_lc   = { .if_freq = 1250, .fm_rfn = 0, .agc_mode = 1, .std = 7,
-		      .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0f */
-	.atv_mn   = { .if_freq = 5750, .fm_rfn = 0, .agc_mode = 1, .std = 5,
-		      .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0d */
-	.atsc_6   = { .if_freq = 3250, .fm_rfn = 0, .agc_mode = 3, .std = 4,
-		      .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1c */
-	.dvbt_6   = { .if_freq = 3300, .fm_rfn = 0, .agc_mode = 3, .std = 4,
-		      .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1c */
-	.dvbt_7   = { .if_freq = 3800, .fm_rfn = 0, .agc_mode = 3, .std = 5,
-		      .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1d */
-	.dvbt_8   = { .if_freq = 4300, .fm_rfn = 0, .agc_mode = 3, .std = 6,
-		      .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1e */
-	.qam_6    = { .if_freq = 4000, .fm_rfn = 0, .agc_mode = 3, .std = 5,
-		      .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1d */
-	.qam_7    = { .if_freq = 4500, .fm_rfn = 0, .agc_mode = 3, .std = 6,
-		      .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1e */
-	.qam_8    = { .if_freq = 5000, .fm_rfn = 0, .agc_mode = 3, .std = 7,
-		      .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1f */
-};
-
-static struct tda18271_std_map tda18271c2_std_map = {
-	.fm_radio = { .if_freq = 1250, .fm_rfn = 1, .agc_mode = 3, .std = 0,
-		      .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x18 */
-	.atv_b    = { .if_freq = 6000, .fm_rfn = 0, .agc_mode = 1, .std = 5,
-		      .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0d */
-	.atv_dk   = { .if_freq = 6900, .fm_rfn = 0, .agc_mode = 1, .std = 6,
-		      .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0e */
-	.atv_gh   = { .if_freq = 7100, .fm_rfn = 0, .agc_mode = 1, .std = 6,
-		      .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0e */
-	.atv_i    = { .if_freq = 7250, .fm_rfn = 0, .agc_mode = 1, .std = 6,
-		      .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0e */
-	.atv_l    = { .if_freq = 6900, .fm_rfn = 0, .agc_mode = 1, .std = 6,
-		      .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0e */
-	.atv_lc   = { .if_freq = 1250, .fm_rfn = 0, .agc_mode = 1, .std = 6,
-		      .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0e */
-	.atv_mn   = { .if_freq = 5400, .fm_rfn = 0, .agc_mode = 1, .std = 4,
-		      .if_lvl = 0, .rfagc_top = 0x2c, }, /* EP3[4:0] 0x0c */
-	.atsc_6   = { .if_freq = 3250, .fm_rfn = 0, .agc_mode = 3, .std = 4,
-		      .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1c */
-	.dvbt_6   = { .if_freq = 3300, .fm_rfn = 0, .agc_mode = 3, .std = 4,
-		      .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1c */
-	.dvbt_7   = { .if_freq = 3500, .fm_rfn = 0, .agc_mode = 3, .std = 4,
-		      .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1c */
-	.dvbt_8   = { .if_freq = 4000, .fm_rfn = 0, .agc_mode = 3, .std = 5,
-		      .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1d */
-	.qam_6    = { .if_freq = 4000, .fm_rfn = 0, .agc_mode = 3, .std = 5,
-		      .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1d */
-	.qam_7    = { .if_freq = 4500, .fm_rfn = 0, .agc_mode = 3, .std = 6,
-		      .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1e */
-	.qam_8    = { .if_freq = 5000, .fm_rfn = 0, .agc_mode = 3, .std = 7,
-		      .if_lvl = 1, .rfagc_top = 0x37, }, /* EP3[4:0] 0x1f */
-};
-
-/*---------------------------------------------------------------------*/
-
-static struct tda18271_map_layout tda18271c1_map_layout = {
-	.main_pll          = tda18271c1_main_pll,
-	.cal_pll           = tda18271c1_cal_pll,
-
-	.rf_cal            = tda18271c1_rf_cal,
-	.rf_cal_kmco       = tda18271c1_km,
-
-	.bp_filter         = tda18271_bp_filter,
-	.rf_band           = tda18271_rf_band,
-	.gain_taper        = tda18271_gain_taper,
-	.ir_measure        = tda18271_ir_measure,
-};
-
-static struct tda18271_map_layout tda18271c2_map_layout = {
-	.main_pll          = tda18271c2_main_pll,
-	.cal_pll           = tda18271c2_cal_pll,
-
-	.rf_cal            = tda18271c2_rf_cal,
-	.rf_cal_kmco       = tda18271c2_km,
-
-	.rf_cal_dc_over_dt = tda18271_rf_cal_dc_over_dt,
-
-	.bp_filter         = tda18271_bp_filter,
-	.rf_band           = tda18271_rf_band,
-	.gain_taper        = tda18271_gain_taper,
-	.ir_measure        = tda18271_ir_measure,
-};
-
-int tda18271_assign_map_layout(struct dvb_frontend *fe)
-{
-	struct tda18271_priv *priv = fe->tuner_priv;
-	int ret = 0;
-
-	switch (priv->id) {
-	case TDA18271HDC1:
-		priv->maps = &tda18271c1_map_layout;
-		memcpy(&priv->std, &tda18271c1_std_map,
-		       sizeof(struct tda18271_std_map));
-		break;
-	case TDA18271HDC2:
-		priv->maps = &tda18271c2_map_layout;
-		memcpy(&priv->std, &tda18271c2_std_map,
-		       sizeof(struct tda18271_std_map));
-		break;
-	default:
-		ret = -EINVAL;
-		break;
-	}
-	memcpy(priv->rf_cal_state, &tda18271_rf_band_template,
-	       sizeof(tda18271_rf_band_template));
-
-	return ret;
-}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/common/tuners/tda18271-priv.h b/drivers/media/common/tuners/tda18271-priv.h
deleted file mode 100644
index 454c152..0000000
--- a/drivers/media/common/tuners/tda18271-priv.h
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
-    tda18271-priv.h - private header for the NXP TDA18271 silicon tuner
-
-    Copyright (C) 2007, 2008 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 __TDA18271_PRIV_H__
-#define __TDA18271_PRIV_H__
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/mutex.h>
-#include "tuner-i2c.h"
-#include "tda18271.h"
-
-#define R_ID     0x00	/* ID byte                */
-#define R_TM     0x01	/* Thermo byte            */
-#define R_PL     0x02	/* Power level byte       */
-#define R_EP1    0x03	/* Easy Prog byte 1       */
-#define R_EP2    0x04	/* Easy Prog byte 2       */
-#define R_EP3    0x05	/* Easy Prog byte 3       */
-#define R_EP4    0x06	/* Easy Prog byte 4       */
-#define R_EP5    0x07	/* Easy Prog byte 5       */
-#define R_CPD    0x08	/* Cal Post-Divider byte  */
-#define R_CD1    0x09	/* Cal Divider byte 1     */
-#define R_CD2    0x0a	/* Cal Divider byte 2     */
-#define R_CD3    0x0b	/* Cal Divider byte 3     */
-#define R_MPD    0x0c	/* Main Post-Divider byte */
-#define R_MD1    0x0d	/* Main Divider byte 1    */
-#define R_MD2    0x0e	/* Main Divider byte 2    */
-#define R_MD3    0x0f	/* Main Divider byte 3    */
-#define R_EB1    0x10	/* Extended byte 1        */
-#define R_EB2    0x11	/* Extended byte 2        */
-#define R_EB3    0x12	/* Extended byte 3        */
-#define R_EB4    0x13	/* Extended byte 4        */
-#define R_EB5    0x14	/* Extended byte 5        */
-#define R_EB6    0x15	/* Extended byte 6        */
-#define R_EB7    0x16	/* Extended byte 7        */
-#define R_EB8    0x17	/* Extended byte 8        */
-#define R_EB9    0x18	/* Extended byte 9        */
-#define R_EB10   0x19	/* Extended byte 10       */
-#define R_EB11   0x1a	/* Extended byte 11       */
-#define R_EB12   0x1b	/* Extended byte 12       */
-#define R_EB13   0x1c	/* Extended byte 13       */
-#define R_EB14   0x1d	/* Extended byte 14       */
-#define R_EB15   0x1e	/* Extended byte 15       */
-#define R_EB16   0x1f	/* Extended byte 16       */
-#define R_EB17   0x20	/* Extended byte 17       */
-#define R_EB18   0x21	/* Extended byte 18       */
-#define R_EB19   0x22	/* Extended byte 19       */
-#define R_EB20   0x23	/* Extended byte 20       */
-#define R_EB21   0x24	/* Extended byte 21       */
-#define R_EB22   0x25	/* Extended byte 22       */
-#define R_EB23   0x26	/* Extended byte 23       */
-
-#define TDA18271_NUM_REGS 39
-
-/*---------------------------------------------------------------------*/
-
-struct tda18271_rf_tracking_filter_cal {
-	u32 rfmax;
-	u8  rfband;
-	u32 rf1_def;
-	u32 rf2_def;
-	u32 rf3_def;
-	u32 rf1;
-	u32 rf2;
-	u32 rf3;
-	s32 rf_a1;
-	s32 rf_b1;
-	s32 rf_a2;
-	s32 rf_b2;
-};
-
-enum tda18271_pll {
-	TDA18271_MAIN_PLL,
-	TDA18271_CAL_PLL,
-};
-
-struct tda18271_map_layout;
-
-enum tda18271_ver {
-	TDA18271HDC1,
-	TDA18271HDC2,
-};
-
-struct tda18271_priv {
-	unsigned char tda18271_regs[TDA18271_NUM_REGS];
-
-	struct list_head	hybrid_tuner_instance_list;
-	struct tuner_i2c_props	i2c_props;
-
-	enum tda18271_mode mode;
-	enum tda18271_role role;
-	enum tda18271_i2c_gate gate;
-	enum tda18271_ver id;
-	enum tda18271_output_options output_opt;
-	enum tda18271_small_i2c small_i2c;
-
-	unsigned int config; /* interface to saa713x / tda829x */
-	unsigned int cal_initialized:1;
-
-	u8 tm_rfcal;
-
-	struct tda18271_map_layout *maps;
-	struct tda18271_std_map std;
-	struct tda18271_rf_tracking_filter_cal rf_cal_state[8];
-
-	struct mutex lock;
-
-	u16 if_freq;
-
-	u32 frequency;
-	u32 bandwidth;
-};
-
-/*---------------------------------------------------------------------*/
-
-extern int tda18271_debug;
-
-#define DBG_INFO 1
-#define DBG_MAP  2
-#define DBG_REG  4
-#define DBG_ADV  8
-#define DBG_CAL  16
-
-__attribute__((format(printf, 4, 5)))
-int _tda_printk(struct tda18271_priv *state, const char *level,
-		const char *func, const char *fmt, ...);
-
-#define tda_printk(st, lvl, fmt, arg...)			\
-	_tda_printk(st, lvl, __func__, fmt, ##arg)
-
-#define tda_dprintk(st, lvl, fmt, arg...)			\
-do {								\
-	if (tda18271_debug & lvl)				\
-		tda_printk(st, KERN_DEBUG, fmt, ##arg);		\
-} while (0)
-
-#define tda_info(fmt, arg...)	pr_info(fmt, ##arg)
-#define tda_warn(fmt, arg...)	tda_printk(priv, KERN_WARNING, fmt, ##arg)
-#define tda_err(fmt, arg...)	tda_printk(priv, KERN_ERR,     fmt, ##arg)
-#define tda_dbg(fmt, arg...)	tda_dprintk(priv, DBG_INFO,    fmt, ##arg)
-#define tda_map(fmt, arg...)	tda_dprintk(priv, DBG_MAP,     fmt, ##arg)
-#define tda_reg(fmt, arg...)	tda_dprintk(priv, DBG_REG,     fmt, ##arg)
-#define tda_cal(fmt, arg...)	tda_dprintk(priv, DBG_CAL,     fmt, ##arg)
-
-#define tda_fail(ret)							     \
-({									     \
-	int __ret;							     \
-	__ret = (ret < 0);						     \
-	if (__ret)							     \
-		tda_printk(priv, KERN_ERR,				     \
-			   "error %d on line %d\n", ret, __LINE__);	     \
-	__ret;								     \
-})
-
-/*---------------------------------------------------------------------*/
-
-enum tda18271_map_type {
-	/* tda18271_pll_map */
-	MAIN_PLL,
-	CAL_PLL,
-	/* tda18271_map */
-	RF_CAL,
-	RF_CAL_KMCO,
-	RF_CAL_DC_OVER_DT,
-	BP_FILTER,
-	RF_BAND,
-	GAIN_TAPER,
-	IR_MEASURE,
-};
-
-extern int tda18271_lookup_pll_map(struct dvb_frontend *fe,
-				   enum tda18271_map_type map_type,
-				   u32 *freq, u8 *post_div, u8 *div);
-extern int tda18271_lookup_map(struct dvb_frontend *fe,
-			       enum tda18271_map_type map_type,
-			       u32 *freq, u8 *val);
-
-extern int tda18271_lookup_thermometer(struct dvb_frontend *fe);
-
-extern int tda18271_lookup_rf_band(struct dvb_frontend *fe,
-				   u32 *freq, u8 *rf_band);
-
-extern int tda18271_lookup_cid_target(struct dvb_frontend *fe,
-				      u32 *freq, u8 *cid_target,
-				      u16 *count_limit);
-
-extern int tda18271_assign_map_layout(struct dvb_frontend *fe);
-
-/*---------------------------------------------------------------------*/
-
-extern int tda18271_read_regs(struct dvb_frontend *fe);
-extern int tda18271_read_extended(struct dvb_frontend *fe);
-extern int tda18271_write_regs(struct dvb_frontend *fe, int idx, int len);
-extern int tda18271_init_regs(struct dvb_frontend *fe);
-
-extern int tda18271_charge_pump_source(struct dvb_frontend *fe,
-				       enum tda18271_pll pll, int force);
-extern int tda18271_set_standby_mode(struct dvb_frontend *fe,
-				     int sm, int sm_lt, int sm_xt);
-
-extern int tda18271_calc_main_pll(struct dvb_frontend *fe, u32 freq);
-extern int tda18271_calc_cal_pll(struct dvb_frontend *fe, u32 freq);
-
-extern int tda18271_calc_bp_filter(struct dvb_frontend *fe, u32 *freq);
-extern int tda18271_calc_km(struct dvb_frontend *fe, u32 *freq);
-extern int tda18271_calc_rf_band(struct dvb_frontend *fe, u32 *freq);
-extern int tda18271_calc_gain_taper(struct dvb_frontend *fe, u32 *freq);
-extern int tda18271_calc_ir_measure(struct dvb_frontend *fe, u32 *freq);
-extern int tda18271_calc_rf_cal(struct dvb_frontend *fe, u32 *freq);
-
-#endif /* __TDA18271_PRIV_H__ */
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/common/tuners/tda18271.h b/drivers/media/common/tuners/tda18271.h
deleted file mode 100644
index 640bae4..0000000
--- a/drivers/media/common/tuners/tda18271.h
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
-    tda18271.h - header for the Philips / NXP TDA18271 silicon tuner
-
-    Copyright (C) 2007, 2008 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 __TDA18271_H__
-#define __TDA18271_H__
-
-#include <linux/i2c.h>
-#include "dvb_frontend.h"
-
-struct tda18271_std_map_item {
-	u16 if_freq;
-
-	/* EP3[4:3] */
-	unsigned int agc_mode:2;
-	/* EP3[2:0] */
-	unsigned int std:3;
-	/* EP4[7] */
-	unsigned int fm_rfn:1;
-	/* EP4[4:2] */
-	unsigned int if_lvl:3;
-	/* EB22[6:0] */
-	unsigned int rfagc_top:7;
-};
-
-struct tda18271_std_map {
-	struct tda18271_std_map_item fm_radio;
-	struct tda18271_std_map_item atv_b;
-	struct tda18271_std_map_item atv_dk;
-	struct tda18271_std_map_item atv_gh;
-	struct tda18271_std_map_item atv_i;
-	struct tda18271_std_map_item atv_l;
-	struct tda18271_std_map_item atv_lc;
-	struct tda18271_std_map_item atv_mn;
-	struct tda18271_std_map_item atsc_6;
-	struct tda18271_std_map_item dvbt_6;
-	struct tda18271_std_map_item dvbt_7;
-	struct tda18271_std_map_item dvbt_8;
-	struct tda18271_std_map_item qam_6;
-	struct tda18271_std_map_item qam_7;
-	struct tda18271_std_map_item qam_8;
-};
-
-enum tda18271_role {
-	TDA18271_MASTER = 0,
-	TDA18271_SLAVE,
-};
-
-enum tda18271_i2c_gate {
-	TDA18271_GATE_AUTO = 0,
-	TDA18271_GATE_ANALOG,
-	TDA18271_GATE_DIGITAL,
-};
-
-enum tda18271_output_options {
-	/* slave tuner output & loop thru & xtal oscillator always on */
-	TDA18271_OUTPUT_LT_XT_ON = 0,
-
-	/* slave tuner output loop thru off */
-	TDA18271_OUTPUT_LT_OFF = 1,
-
-	/* xtal oscillator off */
-	TDA18271_OUTPUT_XT_OFF = 2,
-};
-
-enum tda18271_small_i2c {
-	TDA18271_39_BYTE_CHUNK_INIT = 0,
-	TDA18271_16_BYTE_CHUNK_INIT = 16,
-	TDA18271_08_BYTE_CHUNK_INIT = 8,
-	TDA18271_03_BYTE_CHUNK_INIT = 3,
-};
-
-struct tda18271_config {
-	/* override default if freq / std settings (optional) */
-	struct tda18271_std_map *std_map;
-
-	/* master / slave tuner: master uses main pll, slave uses cal pll */
-	enum tda18271_role role;
-
-	/* use i2c gate provided by analog or digital demod */
-	enum tda18271_i2c_gate gate;
-
-	/* output options that can be disabled */
-	enum tda18271_output_options output_opt;
-
-	/* some i2c providers can't write all 39 registers at once */
-	enum tda18271_small_i2c small_i2c;
-
-	/* force rf tracking filter calibration on startup */
-	unsigned int rf_cal_on_startup: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))
-extern struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr,
-					    struct i2c_adapter *i2c,
-					    struct tda18271_config *cfg);
-#else
-static inline struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe,
-						   u8 addr,
-						   struct i2c_adapter *i2c,
-						   struct tda18271_config *cfg)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif
-
-#endif /* __TDA18271_H__ */
diff --git a/drivers/media/common/tuners/tda827x.c b/drivers/media/common/tuners/tda827x.c
deleted file mode 100644
index a0d1762..0000000
--- a/drivers/media/common/tuners/tda827x.c
+++ /dev/null
@@ -1,917 +0,0 @@
-/*
- *
- * (c) 2005 Hartmut Hackmann
- * (c) 2007 Michael Krufky
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the 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/slab.h>
-#include <asm/types.h>
-#include <linux/dvb/frontend.h>
-#include <linux/videodev2.h>
-
-#include "tda827x.h"
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
-
-#define dprintk(args...) \
-	do {					    \
-		if (debug) printk(KERN_DEBUG "tda827x: " args); \
-	} while (0)
-
-struct tda827x_priv {
-	int i2c_addr;
-	struct i2c_adapter *i2c_adap;
-	struct tda827x_config *cfg;
-
-	unsigned int sgIF;
-	unsigned char lpsel;
-
-	u32 frequency;
-	u32 bandwidth;
-};
-
-static void tda827x_set_std(struct dvb_frontend *fe,
-			    struct analog_parameters *params)
-{
-	struct tda827x_priv *priv = fe->tuner_priv;
-	char *mode;
-
-	priv->lpsel = 0;
-	if (params->std & V4L2_STD_MN) {
-		priv->sgIF = 92;
-		priv->lpsel = 1;
-		mode = "MN";
-	} else if (params->std & V4L2_STD_B) {
-		priv->sgIF = 108;
-		mode = "B";
-	} else if (params->std & V4L2_STD_GH) {
-		priv->sgIF = 124;
-		mode = "GH";
-	} else if (params->std & V4L2_STD_PAL_I) {
-		priv->sgIF = 124;
-		mode = "I";
-	} else if (params->std & V4L2_STD_DK) {
-		priv->sgIF = 124;
-		mode = "DK";
-	} else if (params->std & V4L2_STD_SECAM_L) {
-		priv->sgIF = 124;
-		mode = "L";
-	} else if (params->std & V4L2_STD_SECAM_LC) {
-		priv->sgIF = 20;
-		mode = "LC";
-	} else {
-		priv->sgIF = 124;
-		mode = "xx";
-	}
-
-	if (params->mode == V4L2_TUNER_RADIO) {
-		priv->sgIF = 88; /* if frequency is 5.5 MHz */
-		dprintk("setting tda827x to radio FM\n");
-	} else
-		dprintk("setting tda827x to system %s\n", mode);
-}
-
-
-/* ------------------------------------------------------------------ */
-
-struct tda827x_data {
-	u32 lomax;
-	u8  spd;
-	u8  bs;
-	u8  bp;
-	u8  cp;
-	u8  gc3;
-	u8 div1p5;
-};
-
-static const struct tda827x_data tda827x_table[] = {
-	{ .lomax =  62000000, .spd = 3, .bs = 2, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 1},
-	{ .lomax =  66000000, .spd = 3, .bs = 3, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 1},
-	{ .lomax =  76000000, .spd = 3, .bs = 1, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 0},
-	{ .lomax =  84000000, .spd = 3, .bs = 2, .bp = 0, .cp = 0, .gc3 = 3, .div1p5 = 0},
-	{ .lomax =  93000000, .spd = 3, .bs = 2, .bp = 0, .cp = 0, .gc3 = 1, .div1p5 = 0},
-	{ .lomax =  98000000, .spd = 3, .bs = 3, .bp = 0, .cp = 0, .gc3 = 1, .div1p5 = 0},
-	{ .lomax = 109000000, .spd = 3, .bs = 3, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 0},
-	{ .lomax = 123000000, .spd = 2, .bs = 2, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 1},
-	{ .lomax = 133000000, .spd = 2, .bs = 3, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 1},
-	{ .lomax = 151000000, .spd = 2, .bs = 1, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 0},
-	{ .lomax = 154000000, .spd = 2, .bs = 2, .bp = 1, .cp = 0, .gc3 = 1, .div1p5 = 0},
-	{ .lomax = 181000000, .spd = 2, .bs = 2, .bp = 1, .cp = 0, .gc3 = 0, .div1p5 = 0},
-	{ .lomax = 185000000, .spd = 2, .bs = 2, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0},
-	{ .lomax = 217000000, .spd = 2, .bs = 3, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0},
-	{ .lomax = 244000000, .spd = 1, .bs = 2, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 1},
-	{ .lomax = 265000000, .spd = 1, .bs = 3, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 1},
-	{ .lomax = 302000000, .spd = 1, .bs = 1, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0},
-	{ .lomax = 324000000, .spd = 1, .bs = 2, .bp = 2, .cp = 0, .gc3 = 1, .div1p5 = 0},
-	{ .lomax = 370000000, .spd = 1, .bs = 2, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 0},
-	{ .lomax = 454000000, .spd = 1, .bs = 3, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 0},
-	{ .lomax = 493000000, .spd = 0, .bs = 2, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 1},
-	{ .lomax = 530000000, .spd = 0, .bs = 3, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 1},
-	{ .lomax = 554000000, .spd = 0, .bs = 1, .bp = 3, .cp = 0, .gc3 = 1, .div1p5 = 0},
-	{ .lomax = 604000000, .spd = 0, .bs = 1, .bp = 4, .cp = 0, .gc3 = 0, .div1p5 = 0},
-	{ .lomax = 696000000, .spd = 0, .bs = 2, .bp = 4, .cp = 0, .gc3 = 0, .div1p5 = 0},
-	{ .lomax = 740000000, .spd = 0, .bs = 2, .bp = 4, .cp = 1, .gc3 = 0, .div1p5 = 0},
-	{ .lomax = 820000000, .spd = 0, .bs = 3, .bp = 4, .cp = 0, .gc3 = 0, .div1p5 = 0},
-	{ .lomax = 865000000, .spd = 0, .bs = 3, .bp = 4, .cp = 1, .gc3 = 0, .div1p5 = 0},
-	{ .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 dtv_frontend_properties *c = &fe->dtv_property_cache;
-	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) };
-	int i, tuner_freq, if_freq;
-	u32 N;
-
-	dprintk("%s:\n", __func__);
-	if (c->bandwidth_hz == 0) {
-		if_freq = 5000000;
-	} else if (c->bandwidth_hz <= 6000000) {
-		if_freq = 4000000;
-	} else if (c->bandwidth_hz <= 7000000) {
-		if_freq = 4500000;
-	} else {	/* 8 MHz */
-		if_freq = 5000000;
-	}
-	tuner_freq = c->frequency;
-
-	i = 0;
-	while (tda827x_table[i].lomax < tuner_freq) {
-		if (tda827x_table[i + 1].lomax == 0)
-			break;
-		i++;
-	}
-
-	tuner_freq += if_freq;
-
-	N = ((tuner_freq + 125000) / 250000) << (tda827x_table[i].spd + 2);
-	buf[0] = 0;
-	buf[1] = (N>>8) | 0x40;
-	buf[2] = N & 0xff;
-	buf[3] = 0;
-	buf[4] = 0x52;
-	buf[5] = (tda827x_table[i].spd << 6) + (tda827x_table[i].div1p5 << 5) +
-				(tda827x_table[i].bs << 3) +
-				tda827x_table[i].bp;
-	buf[6] = (tda827x_table[i].gc3 << 4) + 0x8f;
-	buf[7] = 0xbf;
-	buf[8] = 0x2a;
-	buf[9] = 0x05;
-	buf[10] = 0xff;
-	buf[11] = 0x00;
-	buf[12] = 0x00;
-	buf[13] = 0x40;
-
-	msg.len = 14;
-	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;
-
-	rc = tuner_transfer(fe, &msg, 1);
-	if (rc < 0)
-		goto err;
-
-	priv->frequency = c->frequency;
-	priv->bandwidth = c->bandwidth_hz;
-
-	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)
-{
-	struct tda827x_priv *priv = fe->tuner_priv;
-	static u8 buf[] = { 0x30, 0xd0 };
-	struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
-			       .buf = buf, .len = sizeof(buf) };
-
-	dprintk("%s:\n", __func__);
-	tuner_transfer(fe, &msg, 1);
-
-	if (priv->cfg && priv->cfg->sleep)
-		priv->cfg->sleep(fe);
-
-	return 0;
-}
-
-/* ------------------------------------------------------------------ */
-
-static int tda827xo_set_analog_params(struct dvb_frontend *fe,
-				      struct analog_parameters *params)
-{
-	unsigned char tuner_reg[8];
-	unsigned char reg2[2];
-	u32 N;
-	int i;
-	struct tda827x_priv *priv = fe->tuner_priv;
-	struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0 };
-	unsigned int freq = params->frequency;
-
-	tda827x_set_std(fe, params);
-
-	if (params->mode == V4L2_TUNER_RADIO)
-		freq = freq / 1000;
-
-	N = freq + priv->sgIF;
-
-	i = 0;
-	while (tda827x_table[i].lomax < N * 62500) {
-		if (tda827x_table[i + 1].lomax == 0)
-			break;
-		i++;
-	}
-
-	N = N << tda827x_table[i].spd;
-
-	tuner_reg[0] = 0;
-	tuner_reg[1] = (unsigned char)(N>>8);
-	tuner_reg[2] = (unsigned char) N;
-	tuner_reg[3] = 0x40;
-	tuner_reg[4] = 0x52 + (priv->lpsel << 5);
-	tuner_reg[5] = (tda827x_table[i].spd    << 6) +
-		       (tda827x_table[i].div1p5 << 5) +
-		       (tda827x_table[i].bs     << 3) + tda827x_table[i].bp;
-	tuner_reg[6] = 0x8f + (tda827x_table[i].gc3 << 4);
-	tuner_reg[7] = 0x8f;
-
-	msg.buf = tuner_reg;
-	msg.len = 8;
-	tuner_transfer(fe, &msg, 1);
-
-	msg.buf = reg2;
-	msg.len = 2;
-	reg2[0] = 0x80;
-	reg2[1] = 0;
-	tuner_transfer(fe, &msg, 1);
-
-	reg2[0] = 0x60;
-	reg2[1] = 0xbf;
-	tuner_transfer(fe, &msg, 1);
-
-	reg2[0] = 0x30;
-	reg2[1] = tuner_reg[4] + 0x80;
-	tuner_transfer(fe, &msg, 1);
-
-	msleep(1);
-	reg2[0] = 0x30;
-	reg2[1] = tuner_reg[4] + 4;
-	tuner_transfer(fe, &msg, 1);
-
-	msleep(1);
-	reg2[0] = 0x30;
-	reg2[1] = tuner_reg[4];
-	tuner_transfer(fe, &msg, 1);
-
-	msleep(550);
-	reg2[0] = 0x30;
-	reg2[1] = (tuner_reg[4] & 0xfc) + tda827x_table[i].cp;
-	tuner_transfer(fe, &msg, 1);
-
-	reg2[0] = 0x60;
-	reg2[1] = 0x3f;
-	tuner_transfer(fe, &msg, 1);
-
-	reg2[0] = 0x80;
-	reg2[1] = 0x08;   /* Vsync en */
-	tuner_transfer(fe, &msg, 1);
-
-	priv->frequency = params->frequency;
-
-	return 0;
-}
-
-static void tda827xo_agcf(struct dvb_frontend *fe)
-{
-	struct tda827x_priv *priv = fe->tuner_priv;
-	unsigned char data[] = { 0x80, 0x0c };
-	struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
-			       .buf = data, .len = 2};
-
-	tuner_transfer(fe, &msg, 1);
-}
-
-/* ------------------------------------------------------------------ */
-
-struct tda827xa_data {
-	u32 lomax;
-	u8  svco;
-	u8  spd;
-	u8  scr;
-	u8  sbs;
-	u8  gc3;
-};
-
-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},
-	{ .lomax =  97500000, .svco = 2, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 1},
-	{ .lomax = 113750000, .svco = 3, .spd = 3, .scr = 0, .sbs = 1, .gc3 = 1},
-	{ .lomax = 134500000, .svco = 0, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
-	{ .lomax = 154000000, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
-	{ .lomax = 162500000, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
-	{ .lomax = 183000000, .svco = 2, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
-	{ .lomax = 195000000, .svco = 2, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 1},
-	{ .lomax = 227500000, .svco = 3, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 1},
-	{ .lomax = 269000000, .svco = 0, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 1},
-	{ .lomax = 290000000, .svco = 1, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 1},
-	{ .lomax = 325000000, .svco = 1, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 1},
-	{ .lomax = 390000000, .svco = 2, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 1},
-	{ .lomax = 455000000, .svco = 3, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 1},
-	{ .lomax = 520000000, .svco = 0, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1},
-	{ .lomax = 538000000, .svco = 0, .spd = 0, .scr = 1, .sbs = 3, .gc3 = 1},
-	{ .lomax = 550000000, .svco = 1, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1},
-	{ .lomax = 620000000, .svco = 1, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0},
-	{ .lomax = 650000000, .svco = 1, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0},
-	{ .lomax = 700000000, .svco = 2, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0},
-	{ .lomax = 780000000, .svco = 2, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0},
-	{ .lomax = 820000000, .svco = 3, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0},
-	{ .lomax = 870000000, .svco = 3, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0},
-	{ .lomax = 911000000, .svco = 3, .spd = 0, .scr = 2, .sbs = 4, .gc3 = 0},
-	{ .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},
-	{ .lomax =  81250000, .svco = 1, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 3},
-	{ .lomax =  97500000, .svco = 2, .spd = 3, .scr = 0, .sbs = 0, .gc3 = 3},
-	{ .lomax = 113750000, .svco = 3, .spd = 3, .scr = 0, .sbs = 1, .gc3 = 1},
-	{ .lomax = 134500000, .svco = 0, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
-	{ .lomax = 154000000, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
-	{ .lomax = 162500000, .svco = 1, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
-	{ .lomax = 183000000, .svco = 2, .spd = 2, .scr = 0, .sbs = 1, .gc3 = 1},
-	{ .lomax = 195000000, .svco = 2, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 1},
-	{ .lomax = 227500000, .svco = 3, .spd = 2, .scr = 0, .sbs = 2, .gc3 = 3},
-	{ .lomax = 269000000, .svco = 0, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 3},
-	{ .lomax = 325000000, .svco = 1, .spd = 1, .scr = 0, .sbs = 2, .gc3 = 1},
-	{ .lomax = 390000000, .svco = 2, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 3},
-	{ .lomax = 455000000, .svco = 3, .spd = 1, .scr = 0, .sbs = 3, .gc3 = 3},
-	{ .lomax = 520000000, .svco = 0, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1},
-	{ .lomax = 538000000, .svco = 0, .spd = 0, .scr = 1, .sbs = 3, .gc3 = 1},
-	{ .lomax = 554000000, .svco = 1, .spd = 0, .scr = 0, .sbs = 3, .gc3 = 1},
-	{ .lomax = 620000000, .svco = 1, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0},
-	{ .lomax = 650000000, .svco = 1, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0},
-	{ .lomax = 700000000, .svco = 2, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0},
-	{ .lomax = 780000000, .svco = 2, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0},
-	{ .lomax = 820000000, .svco = 3, .spd = 0, .scr = 0, .sbs = 4, .gc3 = 0},
-	{ .lomax = 870000000, .svco = 3, .spd = 0, .scr = 1, .sbs = 4, .gc3 = 0},
-	{ .lomax = 911000000, .svco = 3, .spd = 0, .scr = 2, .sbs = 4, .gc3 = 0},
-	{ .lomax =         0, .svco = 0, .spd = 0, .scr = 0, .sbs = 0, .gc3 = 0}
-};
-
-static int tda827xa_sleep(struct dvb_frontend *fe)
-{
-	struct tda827x_priv *priv = fe->tuner_priv;
-	static u8 buf[] = { 0x30, 0x90 };
-	struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
-			       .buf = buf, .len = sizeof(buf) };
-
-	dprintk("%s:\n", __func__);
-
-	tuner_transfer(fe, &msg, 1);
-
-	if (priv->cfg && priv->cfg->sleep)
-		priv->cfg->sleep(fe);
-
-	return 0;
-}
-
-static void tda827xa_lna_gain(struct dvb_frontend *fe, int high,
-			      struct analog_parameters *params)
-{
-	struct tda827x_priv *priv = fe->tuner_priv;
-	unsigned char buf[] = {0x22, 0x01};
-	int arg;
-	int gp_func;
-	struct i2c_msg msg = { .flags = 0, .buf = buf, .len = sizeof(buf) };
-
-	if (NULL == priv->cfg) {
-		dprintk("tda827x_config not defined, cannot set LNA gain!\n");
-		return;
-	}
-	msg.addr = priv->cfg->switch_addr;
-	if (priv->cfg->config) {
-		if (high)
-			dprintk("setting LNA to high gain\n");
-		else
-			dprintk("setting LNA to low gain\n");
-	}
-	switch (priv->cfg->config) {
-	case 0: /* no LNA */
-		break;
-	case 1: /* switch is GPIO 0 of tda8290 */
-	case 2:
-		if (params == NULL) {
-			gp_func = 0;
-			arg  = 0;
-		} else {
-			/* turn Vsync on */
-			gp_func = 1;
-			if (params->std & V4L2_STD_MN)
-				arg = 1;
-			else
-				arg = 0;
-		}
-		if (fe->callback)
-			fe->callback(priv->i2c_adap->algo_data,
-				     DVB_FRONTEND_COMPONENT_TUNER,
-				     gp_func, arg);
-		buf[1] = high ? 0 : 1;
-		if (priv->cfg->config == 2)
-			buf[1] = high ? 1 : 0;
-		tuner_transfer(fe, &msg, 1);
-		break;
-	case 3: /* switch with GPIO of saa713x */
-		if (fe->callback)
-			fe->callback(priv->i2c_adap->algo_data,
-				     DVB_FRONTEND_COMPONENT_TUNER, 0, high);
-		break;
-	}
-}
-
-static int tda827xa_set_params(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	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, rc;
-	u32 N;
-
-	dprintk("%s:\n", __func__);
-
-	tda827xa_lna_gain(fe, 1, NULL);
-	msleep(20);
-
-	if (c->bandwidth_hz == 0) {
-		if_freq = 5000000;
-	} else if (c->bandwidth_hz <= 6000000) {
-		if_freq = 4000000;
-	} else if (c->bandwidth_hz <= 7000000) {
-		if_freq = 4500000;
-	} else {	/* 8 MHz */
-		if_freq = 5000000;
-	}
-	tuner_freq = c->frequency;
-
-	switch (c->delivery_system) {
-	case SYS_DVBC_ANNEX_A:
-	case SYS_DVBC_ANNEX_C:
-		dprintk("%s select tda827xa_dvbc\n", __func__);
-		frequency_map = tda827xa_dvbc;
-		break;
-	default:
-		break;
-	}
-
-	i = 0;
-	while (frequency_map[i].lomax < tuner_freq) {
-		if (frequency_map[i + 1].lomax == 0)
-			break;
-		i++;
-	}
-
-	tuner_freq += if_freq;
-
-	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] = (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;
-	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;
-	rc = tuner_transfer(fe, &msg, 1);
-	if (rc < 0)
-		goto err;
-
-	buf[0] = 0xa0;
-	buf[1] = 0x40;
-	msg.len = 2;
-	rc = tuner_transfer(fe, &msg, 1);
-	if (rc < 0)
-		goto err;
-
-	msleep(11);
-	msg.flags = I2C_M_RD;
-	rc = tuner_transfer(fe, &msg, 1);
-	if (rc < 0)
-		goto err;
-	msg.flags = 0;
-
-	buf[1] >>= 4;
-	dprintk("tda8275a AGC2 gain is: %d\n", buf[1]);
-	if ((buf[1]) < 2) {
-		tda827xa_lna_gain(fe, 0, NULL);
-		buf[0] = 0x60;
-		buf[1] = 0x0c;
-		rc = tuner_transfer(fe, &msg, 1);
-		if (rc < 0)
-			goto err;
-	}
-
-	buf[0] = 0xc0;
-	buf[1] = 0x99;    // lpsel, for 6MHz + 2
-	rc = tuner_transfer(fe, &msg, 1);
-	if (rc < 0)
-		goto err;
-
-	buf[0] = 0x60;
-	buf[1] = 0x3c;
-	rc = tuner_transfer(fe, &msg, 1);
-	if (rc < 0)
-		goto err;
-
-	/* correct CP value */
-	buf[0] = 0x30;
-	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
-	rc = tuner_transfer(fe, &msg, 1);
-	if (rc < 0)
-		goto err;
-
-	msleep(3);
-	/* freeze AGC1 */
-	buf[0] = 0x50;
-	buf[1] = 0x4f + (frequency_map[i].gc3 << 4);
-	rc = tuner_transfer(fe, &msg, 1);
-	if (rc < 0)
-		goto err;
-
-	priv->frequency = c->frequency;
-	priv->bandwidth = c->bandwidth_hz;
-
-	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 tda827xa_set_analog_params(struct dvb_frontend *fe,
-				      struct analog_parameters *params)
-{
-	unsigned char tuner_reg[11];
-	u32 N;
-	int i;
-	struct tda827x_priv *priv = fe->tuner_priv;
-	struct i2c_msg msg = { .addr = priv->i2c_addr, .flags = 0,
-			       .buf = tuner_reg, .len = sizeof(tuner_reg) };
-	unsigned int freq = params->frequency;
-
-	tda827x_set_std(fe, params);
-
-	tda827xa_lna_gain(fe, 1, params);
-	msleep(10);
-
-	if (params->mode == V4L2_TUNER_RADIO)
-		freq = freq / 1000;
-
-	N = freq + priv->sgIF;
-
-	i = 0;
-	while (tda827xa_analog[i].lomax < N * 62500) {
-		if (tda827xa_analog[i + 1].lomax == 0)
-			break;
-		i++;
-	}
-
-	N = N << tda827xa_analog[i].spd;
-
-	tuner_reg[0] = 0;
-	tuner_reg[1] = (unsigned char)(N>>8);
-	tuner_reg[2] = (unsigned char) N;
-	tuner_reg[3] = 0;
-	tuner_reg[4] = 0x16;
-	tuner_reg[5] = (tda827xa_analog[i].spd << 5) +
-		       (tda827xa_analog[i].svco << 3) +
-			tda827xa_analog[i].sbs;
-	tuner_reg[6] = 0x8b + (tda827xa_analog[i].gc3 << 4);
-	tuner_reg[7] = 0x1c;
-	tuner_reg[8] = 4;
-	tuner_reg[9] = 0x20;
-	tuner_reg[10] = 0x00;
-	msg.len = 11;
-	tuner_transfer(fe, &msg, 1);
-
-	tuner_reg[0] = 0x90;
-	tuner_reg[1] = 0xff;
-	tuner_reg[2] = 0xe0;
-	tuner_reg[3] = 0;
-	tuner_reg[4] = 0x99 + (priv->lpsel << 1);
-	msg.len = 5;
-	tuner_transfer(fe, &msg, 1);
-
-	tuner_reg[0] = 0xa0;
-	tuner_reg[1] = 0xc0;
-	msg.len = 2;
-	tuner_transfer(fe, &msg, 1);
-
-	tuner_reg[0] = 0x30;
-	tuner_reg[1] = 0x10 + tda827xa_analog[i].scr;
-	tuner_transfer(fe, &msg, 1);
-
-	msg.flags = I2C_M_RD;
-	tuner_transfer(fe, &msg, 1);
-	msg.flags = 0;
-	tuner_reg[1] >>= 4;
-	dprintk("AGC2 gain is: %d\n", tuner_reg[1]);
-	if (tuner_reg[1] < 1)
-		tda827xa_lna_gain(fe, 0, params);
-
-	msleep(100);
-	tuner_reg[0] = 0x60;
-	tuner_reg[1] = 0x3c;
-	tuner_transfer(fe, &msg, 1);
-
-	msleep(163);
-	tuner_reg[0] = 0x50;
-	tuner_reg[1] = 0x8f + (tda827xa_analog[i].gc3 << 4);
-	tuner_transfer(fe, &msg, 1);
-
-	tuner_reg[0] = 0x80;
-	tuner_reg[1] = 0x28;
-	tuner_transfer(fe, &msg, 1);
-
-	tuner_reg[0] = 0xb0;
-	tuner_reg[1] = 0x01;
-	tuner_transfer(fe, &msg, 1);
-
-	tuner_reg[0] = 0xc0;
-	tuner_reg[1] = 0x19 + (priv->lpsel << 1);
-	tuner_transfer(fe, &msg, 1);
-
-	priv->frequency = params->frequency;
-
-	return 0;
-}
-
-static void tda827xa_agcf(struct dvb_frontend *fe)
-{
-	struct tda827x_priv *priv = fe->tuner_priv;
-	unsigned char data[] = {0x80, 0x2c};
-	struct i2c_msg msg = {.addr = priv->i2c_addr, .flags = 0,
-			      .buf = data, .len = 2};
-	tuner_transfer(fe, &msg, 1);
-}
-
-/* ------------------------------------------------------------------ */
-
-static int tda827x_release(struct dvb_frontend *fe)
-{
-	kfree(fe->tuner_priv);
-	fe->tuner_priv = NULL;
-	return 0;
-}
-
-static int tda827x_get_frequency(struct dvb_frontend *fe, u32 *frequency)
-{
-	struct tda827x_priv *priv = fe->tuner_priv;
-	*frequency = priv->frequency;
-	return 0;
-}
-
-static int tda827x_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
-{
-	struct tda827x_priv *priv = fe->tuner_priv;
-	*bandwidth = priv->bandwidth;
-	return 0;
-}
-
-static int tda827x_init(struct dvb_frontend *fe)
-{
-	struct tda827x_priv *priv = fe->tuner_priv;
-	dprintk("%s:\n", __func__);
-	if (priv->cfg && priv->cfg->init)
-		priv->cfg->init(fe);
-
-	return 0;
-}
-
-static int tda827x_probe_version(struct dvb_frontend *fe);
-
-static int tda827x_initial_init(struct dvb_frontend *fe)
-{
-	int ret;
-	ret = tda827x_probe_version(fe);
-	if (ret)
-		return ret;
-	return fe->ops.tuner_ops.init(fe);
-}
-
-static int tda827x_initial_sleep(struct dvb_frontend *fe)
-{
-	int ret;
-	ret = tda827x_probe_version(fe);
-	if (ret)
-		return ret;
-	return fe->ops.tuner_ops.sleep(fe);
-}
-
-static struct dvb_tuner_ops tda827xo_tuner_ops = {
-	.info = {
-		.name = "Philips TDA827X",
-		.frequency_min  =  55000000,
-		.frequency_max  = 860000000,
-		.frequency_step =    250000
-	},
-	.release = tda827x_release,
-	.init = tda827x_initial_init,
-	.sleep = tda827x_initial_sleep,
-	.set_params = tda827xo_set_params,
-	.set_analog_params = tda827xo_set_analog_params,
-	.get_frequency = tda827x_get_frequency,
-	.get_bandwidth = tda827x_get_bandwidth,
-};
-
-static struct dvb_tuner_ops tda827xa_tuner_ops = {
-	.info = {
-		.name = "Philips TDA827XA",
-		.frequency_min  =  44000000,
-		.frequency_max  = 906000000,
-		.frequency_step =     62500
-	},
-	.release = tda827x_release,
-	.init = tda827x_init,
-	.sleep = tda827xa_sleep,
-	.set_params = tda827xa_set_params,
-	.set_analog_params = tda827xa_set_analog_params,
-	.get_frequency = tda827x_get_frequency,
-	.get_bandwidth = tda827x_get_bandwidth,
-};
-
-static int tda827x_probe_version(struct dvb_frontend *fe)
-{
-	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 };
-
-	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 rc;
-	}
-	if ((data & 0x3c) == 0) {
-		dprintk("tda827x tuner found\n");
-		fe->ops.tuner_ops.init  = tda827x_init;
-		fe->ops.tuner_ops.sleep = tda827xo_sleep;
-		if (priv->cfg)
-			priv->cfg->agcf = tda827xo_agcf;
-	} else {
-		dprintk("tda827xa tuner found\n");
-		memcpy(&fe->ops.tuner_ops, &tda827xa_tuner_ops, sizeof(struct dvb_tuner_ops));
-		if (priv->cfg)
-			priv->cfg->agcf = tda827xa_agcf;
-	}
-	return 0;
-}
-
-struct dvb_frontend *tda827x_attach(struct dvb_frontend *fe, int addr,
-				    struct i2c_adapter *i2c,
-				    struct tda827x_config *cfg)
-{
-	struct tda827x_priv *priv = NULL;
-
-	dprintk("%s:\n", __func__);
-	priv = kzalloc(sizeof(struct tda827x_priv), GFP_KERNEL);
-	if (priv == NULL)
-		return NULL;
-
-	priv->i2c_addr = addr;
-	priv->i2c_adap = i2c;
-	priv->cfg = cfg;
-	memcpy(&fe->ops.tuner_ops, &tda827xo_tuner_ops, sizeof(struct dvb_tuner_ops));
-	fe->tuner_priv = priv;
-
-	dprintk("type set to %s\n", fe->ops.tuner_ops.info.name);
-
-	return fe;
-}
-EXPORT_SYMBOL_GPL(tda827x_attach);
-
-MODULE_DESCRIPTION("DVB TDA827x driver");
-MODULE_AUTHOR("Hartmut Hackmann <hartmut.hackmann@t-online.de>");
-MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
-MODULE_LICENSE("GPL");
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/common/tuners/tda827x.h b/drivers/media/common/tuners/tda827x.h
deleted file mode 100644
index 7d72ce0..0000000
--- a/drivers/media/common/tuners/tda827x.h
+++ /dev/null
@@ -1,68 +0,0 @@
-  /*
-     DVB Driver for Philips tda827x / tda827xa Silicon tuners
-
-     (c) 2005 Hartmut Hackmann
-     (c) 2007 Michael Krufky
-
-     This program is free software; you can redistribute it and/or modify
-     it under the terms of the 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_TDA827X_H__
-#define __DVB_TDA827X_H__
-
-#include <linux/i2c.h>
-#include "dvb_frontend.h"
-
-struct tda827x_config
-{
-	/* saa7134 - provided callbacks */
-	int (*init) (struct dvb_frontend *fe);
-	int (*sleep) (struct dvb_frontend *fe);
-
-	/* interface to tda829x driver */
-	unsigned int config;
-	int 	     switch_addr;
-
-	void (*agcf)(struct dvb_frontend *fe);
-};
-
-
-/**
- * Attach a tda827x tuner to the supplied frontend structure.
- *
- * @param fe Frontend to attach to.
- * @param addr i2c address of the tuner.
- * @param i2c i2c adapter to use.
- * @param cfg optional callback function pointers.
- * @return FE pointer on success, NULL on failure.
- */
-#if defined(CONFIG_MEDIA_TUNER_TDA827X) || (defined(CONFIG_MEDIA_TUNER_TDA827X_MODULE) && defined(MODULE))
-extern struct dvb_frontend* tda827x_attach(struct dvb_frontend *fe, int addr,
-					   struct i2c_adapter *i2c,
-					   struct tda827x_config *cfg);
-#else
-static inline struct dvb_frontend* tda827x_attach(struct dvb_frontend *fe,
-						  int addr,
-						  struct i2c_adapter *i2c,
-						  struct tda827x_config *cfg)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif // CONFIG_MEDIA_TUNER_TDA827X
-
-#endif // __DVB_TDA827X_H__
diff --git a/drivers/media/common/tuners/tda8290.c b/drivers/media/common/tuners/tda8290.c
deleted file mode 100644
index 8c48521..0000000
--- a/drivers/media/common/tuners/tda8290.c
+++ /dev/null
@@ -1,874 +0,0 @@
-/*
-
-   i2c tv tuner chip device driver
-   controls the philips tda8290+75 tuner chip combo.
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the 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.
-
-   This "tda8290" module was split apart from the original "tuner" module.
-*/
-
-#include <linux/i2c.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/videodev2.h>
-#include "tuner-i2c.h"
-#include "tda8290.h"
-#include "tda827x.h"
-#include "tda18271.h"
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "enable verbose debug messages");
-
-static int deemphasis_50;
-module_param(deemphasis_50, int, 0644);
-MODULE_PARM_DESC(deemphasis_50, "0 - 75us deemphasis; 1 - 50us deemphasis");
-
-/* ---------------------------------------------------------------------- */
-
-struct tda8290_priv {
-	struct tuner_i2c_props i2c_props;
-
-	unsigned char tda8290_easy_mode;
-
-	unsigned char tda827x_addr;
-
-	unsigned char ver;
-#define TDA8290   1
-#define TDA8295   2
-#define TDA8275   4
-#define TDA8275A  8
-#define TDA18271 16
-
-	struct tda827x_config cfg;
-};
-
-/*---------------------------------------------------------------------*/
-
-static int tda8290_i2c_bridge(struct dvb_frontend *fe, int close)
-{
-	struct tda8290_priv *priv = fe->analog_demod_priv;
-
-	unsigned char  enable[2] = { 0x21, 0xC0 };
-	unsigned char disable[2] = { 0x21, 0x00 };
-	unsigned char *msg;
-
-	if (close) {
-		msg = enable;
-		tuner_i2c_xfer_send(&priv->i2c_props, msg, 2);
-		/* let the bridge stabilize */
-		msleep(20);
-	} else {
-		msg = disable;
-		tuner_i2c_xfer_send(&priv->i2c_props, msg, 2);
-	}
-
-	return 0;
-}
-
-static int tda8295_i2c_bridge(struct dvb_frontend *fe, int close)
-{
-	struct tda8290_priv *priv = fe->analog_demod_priv;
-
-	unsigned char  enable[2] = { 0x45, 0xc1 };
-	unsigned char disable[2] = { 0x46, 0x00 };
-	unsigned char buf[3] = { 0x45, 0x01, 0x00 };
-	unsigned char *msg;
-
-	if (close) {
-		msg = enable;
-		tuner_i2c_xfer_send(&priv->i2c_props, msg, 2);
-		/* let the bridge stabilize */
-		msleep(20);
-	} else {
-		msg = disable;
-		tuner_i2c_xfer_send_recv(&priv->i2c_props, msg, 1, &msg[1], 1);
-
-		buf[2] = msg[1];
-		buf[2] &= ~0x04;
-		tuner_i2c_xfer_send(&priv->i2c_props, buf, 3);
-		msleep(5);
-
-		msg[1] |= 0x04;
-		tuner_i2c_xfer_send(&priv->i2c_props, msg, 2);
-	}
-
-	return 0;
-}
-
-/*---------------------------------------------------------------------*/
-
-static void set_audio(struct dvb_frontend *fe,
-		      struct analog_parameters *params)
-{
-	struct tda8290_priv *priv = fe->analog_demod_priv;
-	char* mode;
-
-	if (params->std & V4L2_STD_MN) {
-		priv->tda8290_easy_mode = 0x01;
-		mode = "MN";
-	} else if (params->std & V4L2_STD_B) {
-		priv->tda8290_easy_mode = 0x02;
-		mode = "B";
-	} else if (params->std & V4L2_STD_GH) {
-		priv->tda8290_easy_mode = 0x04;
-		mode = "GH";
-	} else if (params->std & V4L2_STD_PAL_I) {
-		priv->tda8290_easy_mode = 0x08;
-		mode = "I";
-	} else if (params->std & V4L2_STD_DK) {
-		priv->tda8290_easy_mode = 0x10;
-		mode = "DK";
-	} else if (params->std & V4L2_STD_SECAM_L) {
-		priv->tda8290_easy_mode = 0x20;
-		mode = "L";
-	} else if (params->std & V4L2_STD_SECAM_LC) {
-		priv->tda8290_easy_mode = 0x40;
-		mode = "LC";
-	} else {
-		priv->tda8290_easy_mode = 0x10;
-		mode = "xx";
-	}
-
-	if (params->mode == V4L2_TUNER_RADIO) {
-		/* Set TDA8295 to FM radio; Start TDA8290 with MN values */
-		priv->tda8290_easy_mode = (priv->ver & TDA8295) ? 0x80 : 0x01;
-		tuner_dbg("setting to radio FM\n");
-	} else {
-		tuner_dbg("setting tda829x to system %s\n", mode);
-	}
-}
-
-static struct {
-	unsigned char seq[2];
-} fm_mode[] = {
-	{ { 0x01, 0x81} },	/* Put device into expert mode */
-	{ { 0x03, 0x48} },	/* Disable NOTCH and VIDEO filters */
-	{ { 0x04, 0x04} },	/* Disable color carrier filter (SSIF) */
-	{ { 0x05, 0x04} },	/* ADC headroom */
-	{ { 0x06, 0x10} },	/* group delay flat */
-
-	{ { 0x07, 0x00} },	/* use the same radio DTO values as a tda8295 */
-	{ { 0x08, 0x00} },
-	{ { 0x09, 0x80} },
-	{ { 0x0a, 0xda} },
-	{ { 0x0b, 0x4b} },
-	{ { 0x0c, 0x68} },
-
-	{ { 0x0d, 0x00} },	/* PLL off, no video carrier detect */
-	{ { 0x14, 0x00} },	/* disable auto mute if no video */
-};
-
-static void tda8290_set_params(struct dvb_frontend *fe,
-			       struct analog_parameters *params)
-{
-	struct tda8290_priv *priv = fe->analog_demod_priv;
-
-	unsigned char soft_reset[]  = { 0x00, 0x00 };
-	unsigned char easy_mode[]   = { 0x01, priv->tda8290_easy_mode };
-	unsigned char expert_mode[] = { 0x01, 0x80 };
-	unsigned char agc_out_on[]  = { 0x02, 0x00 };
-	unsigned char gainset_off[] = { 0x28, 0x14 };
-	unsigned char if_agc_spd[]  = { 0x0f, 0x88 };
-	unsigned char adc_head_6[]  = { 0x05, 0x04 };
-	unsigned char adc_head_9[]  = { 0x05, 0x02 };
-	unsigned char adc_head_12[] = { 0x05, 0x01 };
-	unsigned char pll_bw_nom[]  = { 0x0d, 0x47 };
-	unsigned char pll_bw_low[]  = { 0x0d, 0x27 };
-	unsigned char gainset_2[]   = { 0x28, 0x64 };
-	unsigned char agc_rst_on[]  = { 0x0e, 0x0b };
-	unsigned char agc_rst_off[] = { 0x0e, 0x09 };
-	unsigned char if_agc_set[]  = { 0x0f, 0x81 };
-	unsigned char addr_adc_sat  = 0x1a;
-	unsigned char addr_agc_stat = 0x1d;
-	unsigned char addr_pll_stat = 0x1b;
-	unsigned char adc_sat, agc_stat,
-		      pll_stat;
-	int i;
-
-	set_audio(fe, params);
-
-	if (priv->cfg.config)
-		tuner_dbg("tda827xa config is 0x%02x\n", priv->cfg.config);
-	tuner_i2c_xfer_send(&priv->i2c_props, easy_mode, 2);
-	tuner_i2c_xfer_send(&priv->i2c_props, agc_out_on, 2);
-	tuner_i2c_xfer_send(&priv->i2c_props, soft_reset, 2);
-	msleep(1);
-
-	if (params->mode == V4L2_TUNER_RADIO) {
-		unsigned char deemphasis[]  = { 0x13, 1 };
-
-		/* FIXME: allow using a different deemphasis */
-
-		if (deemphasis_50)
-			deemphasis[1] = 2;
-
-		for (i = 0; i < ARRAY_SIZE(fm_mode); i++)
-			tuner_i2c_xfer_send(&priv->i2c_props, fm_mode[i].seq, 2);
-
-		tuner_i2c_xfer_send(&priv->i2c_props, deemphasis, 2);
-	} else {
-		expert_mode[1] = priv->tda8290_easy_mode + 0x80;
-		tuner_i2c_xfer_send(&priv->i2c_props, expert_mode, 2);
-		tuner_i2c_xfer_send(&priv->i2c_props, gainset_off, 2);
-		tuner_i2c_xfer_send(&priv->i2c_props, if_agc_spd, 2);
-		if (priv->tda8290_easy_mode & 0x60)
-			tuner_i2c_xfer_send(&priv->i2c_props, adc_head_9, 2);
-		else
-			tuner_i2c_xfer_send(&priv->i2c_props, adc_head_6, 2);
-		tuner_i2c_xfer_send(&priv->i2c_props, pll_bw_nom, 2);
-	}
-
-
-	tda8290_i2c_bridge(fe, 1);
-
-	if (fe->ops.tuner_ops.set_analog_params)
-		fe->ops.tuner_ops.set_analog_params(fe, params);
-
-	for (i = 0; i < 3; i++) {
-		tuner_i2c_xfer_send_recv(&priv->i2c_props,
-					 &addr_pll_stat, 1, &pll_stat, 1);
-		if (pll_stat & 0x80) {
-			tuner_i2c_xfer_send_recv(&priv->i2c_props,
-						 &addr_adc_sat, 1,
-						 &adc_sat, 1);
-			tuner_i2c_xfer_send_recv(&priv->i2c_props,
-						 &addr_agc_stat, 1,
-						 &agc_stat, 1);
-			tuner_dbg("tda8290 is locked, AGC: %d\n", agc_stat);
-			break;
-		} else {
-			tuner_dbg("tda8290 not locked, no signal?\n");
-			msleep(100);
-		}
-	}
-	/* adjust headroom resp. gain */
-	if ((agc_stat > 115) || (!(pll_stat & 0x80) && (adc_sat < 20))) {
-		tuner_dbg("adjust gain, step 1. Agc: %d, ADC stat: %d, lock: %d\n",
-			   agc_stat, adc_sat, pll_stat & 0x80);
-		tuner_i2c_xfer_send(&priv->i2c_props, gainset_2, 2);
-		msleep(100);
-		tuner_i2c_xfer_send_recv(&priv->i2c_props,
-					 &addr_agc_stat, 1, &agc_stat, 1);
-		tuner_i2c_xfer_send_recv(&priv->i2c_props,
-					 &addr_pll_stat, 1, &pll_stat, 1);
-		if ((agc_stat > 115) || !(pll_stat & 0x80)) {
-			tuner_dbg("adjust gain, step 2. Agc: %d, lock: %d\n",
-				   agc_stat, pll_stat & 0x80);
-			if (priv->cfg.agcf)
-				priv->cfg.agcf(fe);
-			msleep(100);
-			tuner_i2c_xfer_send_recv(&priv->i2c_props,
-						 &addr_agc_stat, 1,
-						 &agc_stat, 1);
-			tuner_i2c_xfer_send_recv(&priv->i2c_props,
-						 &addr_pll_stat, 1,
-						 &pll_stat, 1);
-			if((agc_stat > 115) || !(pll_stat & 0x80)) {
-				tuner_dbg("adjust gain, step 3. Agc: %d\n", agc_stat);
-				tuner_i2c_xfer_send(&priv->i2c_props, adc_head_12, 2);
-				tuner_i2c_xfer_send(&priv->i2c_props, pll_bw_low, 2);
-				msleep(100);
-			}
-		}
-	}
-
-	/* l/ l' deadlock? */
-	if(priv->tda8290_easy_mode & 0x60) {
-		tuner_i2c_xfer_send_recv(&priv->i2c_props,
-					 &addr_adc_sat, 1,
-					 &adc_sat, 1);
-		tuner_i2c_xfer_send_recv(&priv->i2c_props,
-					 &addr_pll_stat, 1,
-					 &pll_stat, 1);
-		if ((adc_sat > 20) || !(pll_stat & 0x80)) {
-			tuner_dbg("trying to resolve SECAM L deadlock\n");
-			tuner_i2c_xfer_send(&priv->i2c_props, agc_rst_on, 2);
-			msleep(40);
-			tuner_i2c_xfer_send(&priv->i2c_props, agc_rst_off, 2);
-		}
-	}
-
-	tda8290_i2c_bridge(fe, 0);
-	tuner_i2c_xfer_send(&priv->i2c_props, if_agc_set, 2);
-}
-
-/*---------------------------------------------------------------------*/
-
-static void tda8295_power(struct dvb_frontend *fe, int enable)
-{
-	struct tda8290_priv *priv = fe->analog_demod_priv;
-	unsigned char buf[] = { 0x30, 0x00 }; /* clb_stdbt */
-
-	tuner_i2c_xfer_send_recv(&priv->i2c_props, &buf[0], 1, &buf[1], 1);
-
-	if (enable)
-		buf[1] = 0x01;
-	else
-		buf[1] = 0x03;
-
-	tuner_i2c_xfer_send(&priv->i2c_props, buf, 2);
-}
-
-static void tda8295_set_easy_mode(struct dvb_frontend *fe, int enable)
-{
-	struct tda8290_priv *priv = fe->analog_demod_priv;
-	unsigned char buf[] = { 0x01, 0x00 };
-
-	tuner_i2c_xfer_send_recv(&priv->i2c_props, &buf[0], 1, &buf[1], 1);
-
-	if (enable)
-		buf[1] = 0x01; /* rising edge sets regs 0x02 - 0x23 */
-	else
-		buf[1] = 0x00; /* reset active bit */
-
-	tuner_i2c_xfer_send(&priv->i2c_props, buf, 2);
-}
-
-static void tda8295_set_video_std(struct dvb_frontend *fe)
-{
-	struct tda8290_priv *priv = fe->analog_demod_priv;
-	unsigned char buf[] = { 0x00, priv->tda8290_easy_mode };
-
-	tuner_i2c_xfer_send(&priv->i2c_props, buf, 2);
-
-	tda8295_set_easy_mode(fe, 1);
-	msleep(20);
-	tda8295_set_easy_mode(fe, 0);
-}
-
-/*---------------------------------------------------------------------*/
-
-static void tda8295_agc1_out(struct dvb_frontend *fe, int enable)
-{
-	struct tda8290_priv *priv = fe->analog_demod_priv;
-	unsigned char buf[] = { 0x02, 0x00 }; /* DIV_FUNC */
-
-	tuner_i2c_xfer_send_recv(&priv->i2c_props, &buf[0], 1, &buf[1], 1);
-
-	if (enable)
-		buf[1] &= ~0x40;
-	else
-		buf[1] |= 0x40;
-
-	tuner_i2c_xfer_send(&priv->i2c_props, buf, 2);
-}
-
-static void tda8295_agc2_out(struct dvb_frontend *fe, int enable)
-{
-	struct tda8290_priv *priv = fe->analog_demod_priv;
-	unsigned char set_gpio_cf[]    = { 0x44, 0x00 };
-	unsigned char set_gpio_val[]   = { 0x46, 0x00 };
-
-	tuner_i2c_xfer_send_recv(&priv->i2c_props,
-				 &set_gpio_cf[0], 1, &set_gpio_cf[1], 1);
-	tuner_i2c_xfer_send_recv(&priv->i2c_props,
-				 &set_gpio_val[0], 1, &set_gpio_val[1], 1);
-
-	set_gpio_cf[1] &= 0xf0; /* clear GPIO_0 bits 3-0 */
-
-	if (enable) {
-		set_gpio_cf[1]  |= 0x01; /* config GPIO_0 as Open Drain Out */
-		set_gpio_val[1] &= 0xfe; /* set GPIO_0 pin low */
-	}
-	tuner_i2c_xfer_send(&priv->i2c_props, set_gpio_cf, 2);
-	tuner_i2c_xfer_send(&priv->i2c_props, set_gpio_val, 2);
-}
-
-static int tda8295_has_signal(struct dvb_frontend *fe)
-{
-	struct tda8290_priv *priv = fe->analog_demod_priv;
-
-	unsigned char hvpll_stat = 0x26;
-	unsigned char ret;
-
-	tuner_i2c_xfer_send_recv(&priv->i2c_props, &hvpll_stat, 1, &ret, 1);
-	return (ret & 0x01) ? 65535 : 0;
-}
-
-/*---------------------------------------------------------------------*/
-
-static void tda8295_set_params(struct dvb_frontend *fe,
-			       struct analog_parameters *params)
-{
-	struct tda8290_priv *priv = fe->analog_demod_priv;
-
-	unsigned char blanking_mode[]     = { 0x1d, 0x00 };
-
-	set_audio(fe, params);
-
-	tuner_dbg("%s: freq = %d\n", __func__, params->frequency);
-
-	tda8295_power(fe, 1);
-	tda8295_agc1_out(fe, 1);
-
-	tuner_i2c_xfer_send_recv(&priv->i2c_props,
-				 &blanking_mode[0], 1, &blanking_mode[1], 1);
-
-	tda8295_set_video_std(fe);
-
-	blanking_mode[1] = 0x03;
-	tuner_i2c_xfer_send(&priv->i2c_props, blanking_mode, 2);
-	msleep(20);
-
-	tda8295_i2c_bridge(fe, 1);
-
-	if (fe->ops.tuner_ops.set_analog_params)
-		fe->ops.tuner_ops.set_analog_params(fe, params);
-
-	if (priv->cfg.agcf)
-		priv->cfg.agcf(fe);
-
-	if (tda8295_has_signal(fe))
-		tuner_dbg("tda8295 is locked\n");
-	else
-		tuner_dbg("tda8295 not locked, no signal?\n");
-
-	tda8295_i2c_bridge(fe, 0);
-}
-
-/*---------------------------------------------------------------------*/
-
-static int tda8290_has_signal(struct dvb_frontend *fe)
-{
-	struct tda8290_priv *priv = fe->analog_demod_priv;
-
-	unsigned char i2c_get_afc[1] = { 0x1B };
-	unsigned char afc = 0;
-
-	tuner_i2c_xfer_send_recv(&priv->i2c_props,
-				 i2c_get_afc, ARRAY_SIZE(i2c_get_afc), &afc, 1);
-	return (afc & 0x80)? 65535:0;
-}
-
-/*---------------------------------------------------------------------*/
-
-static void tda8290_standby(struct dvb_frontend *fe)
-{
-	struct tda8290_priv *priv = fe->analog_demod_priv;
-
-	unsigned char cb1[] = { 0x30, 0xD0 };
-	unsigned char tda8290_standby[] = { 0x00, 0x02 };
-	unsigned char tda8290_agc_tri[] = { 0x02, 0x20 };
-	struct i2c_msg msg = {.addr = priv->tda827x_addr, .flags=0, .buf=cb1, .len = 2};
-
-	tda8290_i2c_bridge(fe, 1);
-	if (priv->ver & TDA8275A)
-		cb1[1] = 0x90;
-	i2c_transfer(priv->i2c_props.adap, &msg, 1);
-	tda8290_i2c_bridge(fe, 0);
-	tuner_i2c_xfer_send(&priv->i2c_props, tda8290_agc_tri, 2);
-	tuner_i2c_xfer_send(&priv->i2c_props, tda8290_standby, 2);
-}
-
-static void tda8295_standby(struct dvb_frontend *fe)
-{
-	tda8295_agc1_out(fe, 0); /* Put AGC in tri-state */
-
-	tda8295_power(fe, 0);
-}
-
-static void tda8290_init_if(struct dvb_frontend *fe)
-{
-	struct tda8290_priv *priv = fe->analog_demod_priv;
-
-	unsigned char set_VS[] = { 0x30, 0x6F };
-	unsigned char set_GP00_CF[] = { 0x20, 0x01 };
-	unsigned char set_GP01_CF[] = { 0x20, 0x0B };
-
-	if ((priv->cfg.config == 1) || (priv->cfg.config == 2))
-		tuner_i2c_xfer_send(&priv->i2c_props, set_GP00_CF, 2);
-	else
-		tuner_i2c_xfer_send(&priv->i2c_props, set_GP01_CF, 2);
-	tuner_i2c_xfer_send(&priv->i2c_props, set_VS, 2);
-}
-
-static void tda8295_init_if(struct dvb_frontend *fe)
-{
-	struct tda8290_priv *priv = fe->analog_demod_priv;
-
-	static unsigned char set_adc_ctl[]       = { 0x33, 0x14 };
-	static unsigned char set_adc_ctl2[]      = { 0x34, 0x00 };
-	static unsigned char set_pll_reg6[]      = { 0x3e, 0x63 };
-	static unsigned char set_pll_reg0[]      = { 0x38, 0x23 };
-	static unsigned char set_pll_reg7[]      = { 0x3f, 0x01 };
-	static unsigned char set_pll_reg10[]     = { 0x42, 0x61 };
-	static unsigned char set_gpio_reg0[]     = { 0x44, 0x0b };
-
-	tda8295_power(fe, 1);
-
-	tda8295_set_easy_mode(fe, 0);
-	tda8295_set_video_std(fe);
-
-	tuner_i2c_xfer_send(&priv->i2c_props, set_adc_ctl, 2);
-	tuner_i2c_xfer_send(&priv->i2c_props, set_adc_ctl2, 2);
-	tuner_i2c_xfer_send(&priv->i2c_props, set_pll_reg6, 2);
-	tuner_i2c_xfer_send(&priv->i2c_props, set_pll_reg0, 2);
-	tuner_i2c_xfer_send(&priv->i2c_props, set_pll_reg7, 2);
-	tuner_i2c_xfer_send(&priv->i2c_props, set_pll_reg10, 2);
-	tuner_i2c_xfer_send(&priv->i2c_props, set_gpio_reg0, 2);
-
-	tda8295_agc1_out(fe, 0);
-	tda8295_agc2_out(fe, 0);
-}
-
-static void tda8290_init_tuner(struct dvb_frontend *fe)
-{
-	struct tda8290_priv *priv = fe->analog_demod_priv;
-	unsigned char tda8275_init[]  = { 0x00, 0x00, 0x00, 0x40, 0xdC, 0x04, 0xAf,
-					  0x3F, 0x2A, 0x04, 0xFF, 0x00, 0x00, 0x40 };
-	unsigned char tda8275a_init[] = { 0x00, 0x00, 0x00, 0x00, 0xdC, 0x05, 0x8b,
-					  0x0c, 0x04, 0x20, 0xFF, 0x00, 0x00, 0x4b };
-	struct i2c_msg msg = {.addr = priv->tda827x_addr, .flags=0,
-			      .buf=tda8275_init, .len = 14};
-	if (priv->ver & TDA8275A)
-		msg.buf = tda8275a_init;
-
-	tda8290_i2c_bridge(fe, 1);
-	i2c_transfer(priv->i2c_props.adap, &msg, 1);
-	tda8290_i2c_bridge(fe, 0);
-}
-
-/*---------------------------------------------------------------------*/
-
-static void tda829x_release(struct dvb_frontend *fe)
-{
-	struct tda8290_priv *priv = fe->analog_demod_priv;
-
-	/* only try to release the tuner if we've
-	 * attached it from within this module */
-	if (priv->ver & (TDA18271 | TDA8275 | TDA8275A))
-		if (fe->ops.tuner_ops.release)
-			fe->ops.tuner_ops.release(fe);
-
-	kfree(fe->analog_demod_priv);
-	fe->analog_demod_priv = NULL;
-}
-
-static struct tda18271_config tda829x_tda18271_config = {
-	.gate    = TDA18271_GATE_ANALOG,
-};
-
-static int tda829x_find_tuner(struct dvb_frontend *fe)
-{
-	struct tda8290_priv *priv = fe->analog_demod_priv;
-	struct analog_demod_ops *analog_ops = &fe->ops.analog_ops;
-	int i, ret, tuners_found;
-	u32 tuner_addrs;
-	u8 data;
-	struct i2c_msg msg = { .flags = I2C_M_RD, .buf = &data, .len = 1 };
-
-	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);
-
-	/* probe for tuner chip */
-	tuners_found = 0;
-	tuner_addrs = 0;
-	for (i = 0x60; i <= 0x63; i++) {
-		msg.addr = i;
-		ret = i2c_transfer(priv->i2c_props.adap, &msg, 1);
-		if (ret == 1) {
-			tuners_found++;
-			tuner_addrs = (tuner_addrs << 8) + i;
-		}
-	}
-	/* if there is more than one tuner, we expect the right one is
-	   behind the bridge and we choose the highest address that doesn't
-	   give a response now
-	 */
-
-	analog_ops->i2c_gate_ctrl(fe, 0);
-
-	if (tuners_found > 1)
-		for (i = 0; i < tuners_found; i++) {
-			msg.addr = tuner_addrs  & 0xff;
-			ret = i2c_transfer(priv->i2c_props.adap, &msg, 1);
-			if (ret == 1)
-				tuner_addrs = tuner_addrs >> 8;
-			else
-				break;
-		}
-
-	if (tuner_addrs == 0) {
-		tuner_addrs = 0x60;
-		tuner_info("could not clearly identify tuner address, "
-			   "defaulting to %x\n", tuner_addrs);
-	} else {
-		tuner_addrs = tuner_addrs & 0xff;
-		tuner_info("setting tuner address to %x\n", tuner_addrs);
-	}
-	priv->tda827x_addr = tuner_addrs;
-	msg.addr = tuner_addrs;
-
-	analog_ops->i2c_gate_ctrl(fe, 1);
-	ret = i2c_transfer(priv->i2c_props.adap, &msg, 1);
-
-	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 {
-		if ((data & 0x3c) == 0)
-			priv->ver |= TDA8275;
-		else
-			priv->ver |= TDA8275A;
-
-		dvb_attach(tda827x_attach, fe, priv->tda827x_addr,
-			   priv->i2c_props.adap, &priv->cfg);
-		priv->cfg.switch_addr = priv->i2c_props.addr;
-	}
-	if (fe->ops.tuner_ops.init)
-		fe->ops.tuner_ops.init(fe);
-
-	if (fe->ops.tuner_ops.sleep)
-		fe->ops.tuner_ops.sleep(fe);
-
-	analog_ops->i2c_gate_ctrl(fe, 0);
-
-	return 0;
-}
-
-static int tda8290_probe(struct tuner_i2c_props *i2c_props)
-{
-#define TDA8290_ID 0x89
-	u8 reg = 0x1f, id;
-	struct i2c_msg msg_read[] = {
-		{ .addr = i2c_props->addr, .flags = 0, .len = 1, .buf = &reg },
-		{ .addr = i2c_props->addr, .flags = I2C_M_RD, .len = 1, .buf = &id },
-	};
-
-	/* detect tda8290 */
-	if (i2c_transfer(i2c_props->adap, msg_read, 2) != 2) {
-		printk(KERN_WARNING "%s: couldn't read register 0x%02x\n",
-			       __func__, reg);
-		return -ENODEV;
-	}
-
-	if (id == TDA8290_ID) {
-		if (debug)
-			printk(KERN_DEBUG "%s: tda8290 detected @ %d-%04x\n",
-			       __func__, i2c_adapter_id(i2c_props->adap),
-			       i2c_props->addr);
-		return 0;
-	}
-	return -ENODEV;
-}
-
-static int tda8295_probe(struct tuner_i2c_props *i2c_props)
-{
-#define TDA8295_ID 0x8a
-#define TDA8295C2_ID 0x8b
-	u8 reg = 0x2f, id;
-	struct i2c_msg msg_read[] = {
-		{ .addr = i2c_props->addr, .flags = 0, .len = 1, .buf = &reg },
-		{ .addr = i2c_props->addr, .flags = I2C_M_RD, .len = 1, .buf = &id },
-	};
-
-	/* detect tda8295 */
-	if (i2c_transfer(i2c_props->adap, msg_read, 2) != 2) {
-		printk(KERN_WARNING "%s: couldn't read register 0x%02x\n",
-			       __func__, reg);
-		return -ENODEV;
-	}
-
-	if ((id & 0xfe) == TDA8295_ID) {
-		if (debug)
-			printk(KERN_DEBUG "%s: %s detected @ %d-%04x\n",
-			       __func__, (id == TDA8295_ID) ?
-			       "tda8295c1" : "tda8295c2",
-			       i2c_adapter_id(i2c_props->adap),
-			       i2c_props->addr);
-		return 0;
-	}
-
-	return -ENODEV;
-}
-
-static struct analog_demod_ops tda8290_ops = {
-	.set_params     = tda8290_set_params,
-	.has_signal     = tda8290_has_signal,
-	.standby        = tda8290_standby,
-	.release        = tda829x_release,
-	.i2c_gate_ctrl  = tda8290_i2c_bridge,
-};
-
-static struct analog_demod_ops tda8295_ops = {
-	.set_params     = tda8295_set_params,
-	.has_signal     = tda8295_has_signal,
-	.standby        = tda8295_standby,
-	.release        = tda829x_release,
-	.i2c_gate_ctrl  = tda8295_i2c_bridge,
-};
-
-struct dvb_frontend *tda829x_attach(struct dvb_frontend *fe,
-				    struct i2c_adapter *i2c_adap, u8 i2c_addr,
-				    struct tda829x_config *cfg)
-{
-	struct tda8290_priv *priv = NULL;
-	char *name;
-
-	priv = kzalloc(sizeof(struct tda8290_priv), GFP_KERNEL);
-	if (priv == NULL)
-		return NULL;
-	fe->analog_demod_priv = priv;
-
-	priv->i2c_props.addr     = i2c_addr;
-	priv->i2c_props.adap     = i2c_adap;
-	priv->i2c_props.name     = "tda829x";
-	if (cfg)
-		priv->cfg.config         = cfg->lna_cfg;
-
-	if (tda8290_probe(&priv->i2c_props) == 0) {
-		priv->ver = TDA8290;
-		memcpy(&fe->ops.analog_ops, &tda8290_ops,
-		       sizeof(struct analog_demod_ops));
-	}
-
-	if (tda8295_probe(&priv->i2c_props) == 0) {
-		priv->ver = TDA8295;
-		memcpy(&fe->ops.analog_ops, &tda8295_ops,
-		       sizeof(struct analog_demod_ops));
-	}
-
-	if (!(cfg) || (TDA829X_PROBE_TUNER == cfg->probe_tuner)) {
-		tda8295_power(fe, 1);
-		if (tda829x_find_tuner(fe) < 0)
-			goto fail;
-	}
-
-	switch (priv->ver) {
-	case TDA8290:
-		name = "tda8290";
-		break;
-	case TDA8295:
-		name = "tda8295";
-		break;
-	case TDA8290 | TDA8275:
-		name = "tda8290+75";
-		break;
-	case TDA8295 | TDA8275:
-		name = "tda8295+75";
-		break;
-	case TDA8290 | TDA8275A:
-		name = "tda8290+75a";
-		break;
-	case TDA8295 | TDA8275A:
-		name = "tda8295+75a";
-		break;
-	case TDA8290 | TDA18271:
-		name = "tda8290+18271";
-		break;
-	case TDA8295 | TDA18271:
-		name = "tda8295+18271";
-		break;
-	default:
-		goto fail;
-	}
-	tuner_info("type set to %s\n", name);
-
-	fe->ops.analog_ops.info.name = name;
-
-	if (priv->ver & TDA8290) {
-		if (priv->ver & (TDA8275 | TDA8275A))
-			tda8290_init_tuner(fe);
-		tda8290_init_if(fe);
-	} else if (priv->ver & TDA8295)
-		tda8295_init_if(fe);
-
-	return fe;
-
-fail:
-	memset(&fe->ops.analog_ops, 0, sizeof(struct analog_demod_ops));
-
-	tda829x_release(fe);
-	return NULL;
-}
-EXPORT_SYMBOL_GPL(tda829x_attach);
-
-int tda829x_probe(struct i2c_adapter *i2c_adap, u8 i2c_addr)
-{
-	struct tuner_i2c_props i2c_props = {
-		.adap = i2c_adap,
-		.addr = i2c_addr,
-	};
-
-	unsigned char soft_reset[]   = { 0x00, 0x00 };
-	unsigned char easy_mode_b[]  = { 0x01, 0x02 };
-	unsigned char easy_mode_g[]  = { 0x01, 0x04 };
-	unsigned char restore_9886[] = { 0x00, 0xd6, 0x30 };
-	unsigned char addr_dto_lsb = 0x07;
-	unsigned char data;
-#define PROBE_BUFFER_SIZE 8
-	unsigned char buf[PROBE_BUFFER_SIZE];
-	int i;
-
-	/* rule out tda9887, which would return the same byte repeatedly */
-	tuner_i2c_xfer_send_recv(&i2c_props,
-				 soft_reset, 1, buf, PROBE_BUFFER_SIZE);
-	for (i = 1; i < PROBE_BUFFER_SIZE; i++) {
-		if (buf[i] != buf[0])
-			break;
-	}
-
-	/* all bytes are equal, not a tda829x - probably a tda9887 */
-	if (i == PROBE_BUFFER_SIZE)
-		return -ENODEV;
-
-	if ((tda8290_probe(&i2c_props) == 0) ||
-	    (tda8295_probe(&i2c_props) == 0))
-		return 0;
-
-	/* fall back to old probing method */
-	tuner_i2c_xfer_send(&i2c_props, easy_mode_b, 2);
-	tuner_i2c_xfer_send(&i2c_props, soft_reset, 2);
-	tuner_i2c_xfer_send_recv(&i2c_props, &addr_dto_lsb, 1, &data, 1);
-	if (data == 0) {
-		tuner_i2c_xfer_send(&i2c_props, easy_mode_g, 2);
-		tuner_i2c_xfer_send(&i2c_props, soft_reset, 2);
-		tuner_i2c_xfer_send_recv(&i2c_props,
-					 &addr_dto_lsb, 1, &data, 1);
-		if (data == 0x7b) {
-			return 0;
-		}
-	}
-	tuner_i2c_xfer_send(&i2c_props, restore_9886, 3);
-	return -ENODEV;
-}
-EXPORT_SYMBOL_GPL(tda829x_probe);
-
-MODULE_DESCRIPTION("Philips/NXP TDA8290/TDA8295 analog IF demodulator driver");
-MODULE_AUTHOR("Gerd Knorr, Hartmut Hackmann, Michael Krufky");
-MODULE_LICENSE("GPL");
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/common/tuners/tda8290.h b/drivers/media/common/tuners/tda8290.h
deleted file mode 100644
index 7e288b2..0000000
--- a/drivers/media/common/tuners/tda8290.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the 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 __TDA8290_H__
-#define __TDA8290_H__
-
-#include <linux/i2c.h>
-#include "dvb_frontend.h"
-
-struct tda829x_config {
-	unsigned int lna_cfg;
-
-	unsigned int probe_tuner:1;
-#define TDA829X_PROBE_TUNER 0
-#define TDA829X_DONT_PROBE  1
-};
-
-#if defined(CONFIG_MEDIA_TUNER_TDA8290) || (defined(CONFIG_MEDIA_TUNER_TDA8290_MODULE) && defined(MODULE))
-extern int tda829x_probe(struct i2c_adapter *i2c_adap, u8 i2c_addr);
-
-extern struct dvb_frontend *tda829x_attach(struct dvb_frontend *fe,
-					   struct i2c_adapter *i2c_adap,
-					   u8 i2c_addr,
-					   struct tda829x_config *cfg);
-#else
-static inline int tda829x_probe(struct i2c_adapter *i2c_adap, u8 i2c_addr)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return -EINVAL;
-}
-
-static inline struct dvb_frontend *tda829x_attach(struct dvb_frontend *fe,
-						  struct i2c_adapter *i2c_adap,
-						  u8 i2c_addr,
-						  struct tda829x_config *cfg)
-{
-	printk(KERN_INFO "%s: not probed - driver disabled by Kconfig\n",
-	       __func__);
-	return NULL;
-}
-#endif
-
-#endif /* __TDA8290_H__ */
diff --git a/drivers/media/common/tuners/tda9887.c b/drivers/media/common/tuners/tda9887.c
deleted file mode 100644
index cdb645d..0000000
--- a/drivers/media/common/tuners/tda9887.c
+++ /dev/null
@@ -1,717 +0,0 @@
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/i2c.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/delay.h>
-#include <linux/videodev2.h>
-#include <media/v4l2-common.h>
-#include <media/tuner.h>
-#include "tuner-i2c.h"
-#include "tda9887.h"
-
-
-/* Chips:
-   TDA9885 (PAL, NTSC)
-   TDA9886 (PAL, SECAM, NTSC)
-   TDA9887 (PAL, SECAM, NTSC, FM Radio)
-
-   Used as part of several tuners
-*/
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "enable verbose debug messages");
-
-static DEFINE_MUTEX(tda9887_list_mutex);
-static LIST_HEAD(hybrid_tuner_instance_list);
-
-struct tda9887_priv {
-	struct tuner_i2c_props i2c_props;
-	struct list_head hybrid_tuner_instance_list;
-
-	unsigned char 	   data[4];
-	unsigned int       config;
-	unsigned int       mode;
-	unsigned int       audmode;
-	v4l2_std_id        std;
-
-	bool               standby;
-};
-
-/* ---------------------------------------------------------------------- */
-
-#define UNSET       (-1U)
-
-struct tvnorm {
-	v4l2_std_id       std;
-	char              *name;
-	unsigned char     b;
-	unsigned char     c;
-	unsigned char     e;
-};
-
-/* ---------------------------------------------------------------------- */
-
-//
-// TDA defines
-//
-
-//// first reg (b)
-#define cVideoTrapBypassOFF     0x00    // bit b0
-#define cVideoTrapBypassON      0x01    // bit b0
-
-#define cAutoMuteFmInactive     0x00    // bit b1
-#define cAutoMuteFmActive       0x02    // bit b1
-
-#define cIntercarrier           0x00    // bit b2
-#define cQSS                    0x04    // bit b2
-
-#define cPositiveAmTV           0x00    // bit b3:4
-#define cFmRadio                0x08    // bit b3:4
-#define cNegativeFmTV           0x10    // bit b3:4
-
-
-#define cForcedMuteAudioON      0x20    // bit b5
-#define cForcedMuteAudioOFF     0x00    // bit b5
-
-#define cOutputPort1Active      0x00    // bit b6
-#define cOutputPort1Inactive    0x40    // bit b6
-
-#define cOutputPort2Active      0x00    // bit b7
-#define cOutputPort2Inactive    0x80    // bit b7
-
-
-//// second reg (c)
-#define cDeemphasisOFF          0x00    // bit c5
-#define cDeemphasisON           0x20    // bit c5
-
-#define cDeemphasis75           0x00    // bit c6
-#define cDeemphasis50           0x40    // bit c6
-
-#define cAudioGain0             0x00    // bit c7
-#define cAudioGain6             0x80    // bit c7
-
-#define cTopMask                0x1f    // bit c0:4
-#define cTopDefault		0x10 	// bit c0:4
-
-//// third reg (e)
-#define cAudioIF_4_5             0x00    // bit e0:1
-#define cAudioIF_5_5             0x01    // bit e0:1
-#define cAudioIF_6_0             0x02    // bit e0:1
-#define cAudioIF_6_5             0x03    // bit e0:1
-
-
-#define cVideoIFMask		0x1c	// bit e2:4
-/* Video IF selection in TV Mode (bit B3=0) */
-#define cVideoIF_58_75           0x00    // bit e2:4
-#define cVideoIF_45_75           0x04    // bit e2:4
-#define cVideoIF_38_90           0x08    // bit e2:4
-#define cVideoIF_38_00           0x0C    // bit e2:4
-#define cVideoIF_33_90           0x10    // bit e2:4
-#define cVideoIF_33_40           0x14    // bit e2:4
-#define cRadioIF_45_75           0x18    // bit e2:4
-#define cRadioIF_38_90           0x1C    // bit e2:4
-
-/* IF1 selection in Radio Mode (bit B3=1) */
-#define cRadioIF_33_30		0x00	// bit e2,4 (also 0x10,0x14)
-#define cRadioIF_41_30		0x04	// bit e2,4
-
-/* Output of AFC pin in radio mode when bit E7=1 */
-#define cRadioAGC_SIF		0x00	// bit e3
-#define cRadioAGC_FM		0x08	// bit e3
-
-#define cTunerGainNormal         0x00    // bit e5
-#define cTunerGainLow            0x20    // bit e5
-
-#define cGating_18               0x00    // bit e6
-#define cGating_36               0x40    // bit e6
-
-#define cAgcOutON                0x80    // bit e7
-#define cAgcOutOFF               0x00    // bit e7
-
-/* ---------------------------------------------------------------------- */
-
-static struct tvnorm tvnorms[] = {
-	{
-		.std   = V4L2_STD_PAL_BG | V4L2_STD_PAL_H | V4L2_STD_PAL_N,
-		.name  = "PAL-BGHN",
-		.b     = ( cNegativeFmTV  |
-			   cQSS           ),
-		.c     = ( cDeemphasisON  |
-			   cDeemphasis50  |
-			   cTopDefault),
-		.e     = ( cGating_36     |
-			   cAudioIF_5_5   |
-			   cVideoIF_38_90 ),
-	},{
-		.std   = V4L2_STD_PAL_I,
-		.name  = "PAL-I",
-		.b     = ( cNegativeFmTV  |
-			   cQSS           ),
-		.c     = ( cDeemphasisON  |
-			   cDeemphasis50  |
-			   cTopDefault),
-		.e     = ( cGating_36     |
-			   cAudioIF_6_0   |
-			   cVideoIF_38_90 ),
-	},{
-		.std   = V4L2_STD_PAL_DK,
-		.name  = "PAL-DK",
-		.b     = ( cNegativeFmTV  |
-			   cQSS           ),
-		.c     = ( cDeemphasisON  |
-			   cDeemphasis50  |
-			   cTopDefault),
-		.e     = ( cGating_36     |
-			   cAudioIF_6_5   |
-			   cVideoIF_38_90 ),
-	},{
-		.std   = V4L2_STD_PAL_M | V4L2_STD_PAL_Nc,
-		.name  = "PAL-M/Nc",
-		.b     = ( cNegativeFmTV  |
-			   cQSS           ),
-		.c     = ( cDeemphasisON  |
-			   cDeemphasis75  |
-			   cTopDefault),
-		.e     = ( cGating_36     |
-			   cAudioIF_4_5   |
-			   cVideoIF_45_75 ),
-	},{
-		.std   = V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H,
-		.name  = "SECAM-BGH",
-		.b     = ( cNegativeFmTV  |
-			   cQSS           ),
-		.c     = ( cTopDefault),
-		.e     = ( cAudioIF_5_5   |
-			   cVideoIF_38_90 ),
-	},{
-		.std   = V4L2_STD_SECAM_L,
-		.name  = "SECAM-L",
-		.b     = ( cPositiveAmTV  |
-			   cQSS           ),
-		.c     = ( cTopDefault),
-		.e     = ( cGating_36	  |
-			   cAudioIF_6_5   |
-			   cVideoIF_38_90 ),
-	},{
-		.std   = V4L2_STD_SECAM_LC,
-		.name  = "SECAM-L'",
-		.b     = ( cOutputPort2Inactive |
-			   cPositiveAmTV  |
-			   cQSS           ),
-		.c     = ( cTopDefault),
-		.e     = ( cGating_36	  |
-			   cAudioIF_6_5   |
-			   cVideoIF_33_90 ),
-	},{
-		.std   = V4L2_STD_SECAM_DK,
-		.name  = "SECAM-DK",
-		.b     = ( cNegativeFmTV  |
-			   cQSS           ),
-		.c     = ( cDeemphasisON  |
-			   cDeemphasis50  |
-			   cTopDefault),
-		.e     = ( cGating_36     |
-			   cAudioIF_6_5   |
-			   cVideoIF_38_90 ),
-	},{
-		.std   = V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_KR,
-		.name  = "NTSC-M",
-		.b     = ( cNegativeFmTV  |
-			   cQSS           ),
-		.c     = ( cDeemphasisON  |
-			   cDeemphasis75  |
-			   cTopDefault),
-		.e     = ( cGating_36     |
-			   cAudioIF_4_5   |
-			   cVideoIF_45_75 ),
-	},{
-		.std   = V4L2_STD_NTSC_M_JP,
-		.name  = "NTSC-M-JP",
-		.b     = ( cNegativeFmTV  |
-			   cQSS           ),
-		.c     = ( cDeemphasisON  |
-			   cDeemphasis50  |
-			   cTopDefault),
-		.e     = ( cGating_36     |
-			   cAudioIF_4_5   |
-			   cVideoIF_58_75 ),
-	}
-};
-
-static struct tvnorm radio_stereo = {
-	.name = "Radio Stereo",
-	.b    = ( cFmRadio       |
-		  cQSS           ),
-	.c    = ( cDeemphasisOFF |
-		  cAudioGain6    |
-		  cTopDefault),
-	.e    = ( cTunerGainLow  |
-		  cAudioIF_5_5   |
-		  cRadioIF_38_90 ),
-};
-
-static struct tvnorm radio_mono = {
-	.name = "Radio Mono",
-	.b    = ( cFmRadio       |
-		  cQSS           ),
-	.c    = ( cDeemphasisON  |
-		  cDeemphasis75  |
-		  cTopDefault),
-	.e    = ( cTunerGainLow  |
-		  cAudioIF_5_5   |
-		  cRadioIF_38_90 ),
-};
-
-/* ---------------------------------------------------------------------- */
-
-static void dump_read_message(struct dvb_frontend *fe, unsigned char *buf)
-{
-	struct tda9887_priv *priv = fe->analog_demod_priv;
-
-	static char *afc[16] = {
-		"- 12.5 kHz",
-		"- 37.5 kHz",
-		"- 62.5 kHz",
-		"- 87.5 kHz",
-		"-112.5 kHz",
-		"-137.5 kHz",
-		"-162.5 kHz",
-		"-187.5 kHz [min]",
-		"+187.5 kHz [max]",
-		"+162.5 kHz",
-		"+137.5 kHz",
-		"+112.5 kHz",
-		"+ 87.5 kHz",
-		"+ 62.5 kHz",
-		"+ 37.5 kHz",
-		"+ 12.5 kHz",
-	};
-	tuner_info("read: 0x%2x\n", buf[0]);
-	tuner_info("  after power on : %s\n", (buf[0] & 0x01) ? "yes" : "no");
-	tuner_info("  afc            : %s\n", afc[(buf[0] >> 1) & 0x0f]);
-	tuner_info("  fmif level     : %s\n", (buf[0] & 0x20) ? "high" : "low");
-	tuner_info("  afc window     : %s\n", (buf[0] & 0x40) ? "in" : "out");
-	tuner_info("  vfi level      : %s\n", (buf[0] & 0x80) ? "high" : "low");
-}
-
-static void dump_write_message(struct dvb_frontend *fe, unsigned char *buf)
-{
-	struct tda9887_priv *priv = fe->analog_demod_priv;
-
-	static char *sound[4] = {
-		"AM/TV",
-		"FM/radio",
-		"FM/TV",
-		"FM/radio"
-	};
-	static char *adjust[32] = {
-		"-16", "-15", "-14", "-13", "-12", "-11", "-10", "-9",
-		"-8",  "-7",  "-6",  "-5",  "-4",  "-3",  "-2",  "-1",
-		"0",   "+1",  "+2",  "+3",  "+4",  "+5",  "+6",  "+7",
-		"+8",  "+9",  "+10", "+11", "+12", "+13", "+14", "+15"
-	};
-	static char *deemph[4] = {
-		"no", "no", "75", "50"
-	};
-	static char *carrier[4] = {
-		"4.5 MHz",
-		"5.5 MHz",
-		"6.0 MHz",
-		"6.5 MHz / AM"
-	};
-	static char *vif[8] = {
-		"58.75 MHz",
-		"45.75 MHz",
-		"38.9 MHz",
-		"38.0 MHz",
-		"33.9 MHz",
-		"33.4 MHz",
-		"45.75 MHz + pin13",
-		"38.9 MHz + pin13",
-	};
-	static char *rif[4] = {
-		"44 MHz",
-		"52 MHz",
-		"52 MHz",
-		"44 MHz",
-	};
-
-	tuner_info("write: byte B 0x%02x\n", buf[1]);
-	tuner_info("  B0   video mode      : %s\n",
-		   (buf[1] & 0x01) ? "video trap" : "sound trap");
-	tuner_info("  B1   auto mute fm    : %s\n",
-		   (buf[1] & 0x02) ? "yes" : "no");
-	tuner_info("  B2   carrier mode    : %s\n",
-		   (buf[1] & 0x04) ? "QSS" : "Intercarrier");
-	tuner_info("  B3-4 tv sound/radio  : %s\n",
-		   sound[(buf[1] & 0x18) >> 3]);
-	tuner_info("  B5   force mute audio: %s\n",
-		   (buf[1] & 0x20) ? "yes" : "no");
-	tuner_info("  B6   output port 1   : %s\n",
-		   (buf[1] & 0x40) ? "high (inactive)" : "low (active)");
-	tuner_info("  B7   output port 2   : %s\n",
-		   (buf[1] & 0x80) ? "high (inactive)" : "low (active)");
-
-	tuner_info("write: byte C 0x%02x\n", buf[2]);
-	tuner_info("  C0-4 top adjustment  : %s dB\n",
-		   adjust[buf[2] & 0x1f]);
-	tuner_info("  C5-6 de-emphasis     : %s\n",
-		   deemph[(buf[2] & 0x60) >> 5]);
-	tuner_info("  C7   audio gain      : %s\n",
-		   (buf[2] & 0x80) ? "-6" : "0");
-
-	tuner_info("write: byte E 0x%02x\n", buf[3]);
-	tuner_info("  E0-1 sound carrier   : %s\n",
-		   carrier[(buf[3] & 0x03)]);
-	tuner_info("  E6   l pll gating   : %s\n",
-		   (buf[3] & 0x40) ? "36" : "13");
-
-	if (buf[1] & 0x08) {
-		/* radio */
-		tuner_info("  E2-4 video if        : %s\n",
-			   rif[(buf[3] & 0x0c) >> 2]);
-		tuner_info("  E7   vif agc output  : %s\n",
-			   (buf[3] & 0x80)
-			   ? ((buf[3] & 0x10) ? "fm-agc radio" :
-						"sif-agc radio")
-			   : "fm radio carrier afc");
-	} else {
-		/* video */
-		tuner_info("  E2-4 video if        : %s\n",
-			   vif[(buf[3] & 0x1c) >> 2]);
-		tuner_info("  E5   tuner gain      : %s\n",
-			   (buf[3] & 0x80)
-			   ? ((buf[3] & 0x20) ? "external" : "normal")
-			   : ((buf[3] & 0x20) ? "minimum"  : "normal"));
-		tuner_info("  E7   vif agc output  : %s\n",
-			   (buf[3] & 0x80) ? ((buf[3] & 0x20)
-				? "pin3 port, pin22 vif agc out"
-				: "pin22 port, pin3 vif acg ext in")
-				: "pin3+pin22 port");
-	}
-	tuner_info("--\n");
-}
-
-/* ---------------------------------------------------------------------- */
-
-static int tda9887_set_tvnorm(struct dvb_frontend *fe)
-{
-	struct tda9887_priv *priv = fe->analog_demod_priv;
-	struct tvnorm *norm = NULL;
-	char *buf = priv->data;
-	int i;
-
-	if (priv->mode == V4L2_TUNER_RADIO) {
-		if (priv->audmode == V4L2_TUNER_MODE_MONO)
-			norm = &radio_mono;
-		else
-			norm = &radio_stereo;
-	} else {
-		for (i = 0; i < ARRAY_SIZE(tvnorms); i++) {
-			if (tvnorms[i].std & priv->std) {
-				norm = tvnorms+i;
-				break;
-			}
-		}
-	}
-	if (NULL == norm) {
-		tuner_dbg("Unsupported tvnorm entry - audio muted\n");
-		return -1;
-	}
-
-	tuner_dbg("configure for: %s\n", norm->name);
-	buf[1] = norm->b;
-	buf[2] = norm->c;
-	buf[3] = norm->e;
-	return 0;
-}
-
-static unsigned int port1  = UNSET;
-static unsigned int port2  = UNSET;
-static unsigned int qss    = UNSET;
-static unsigned int adjust = UNSET;
-
-module_param(port1, int, 0644);
-module_param(port2, int, 0644);
-module_param(qss, int, 0644);
-module_param(adjust, int, 0644);
-
-static int tda9887_set_insmod(struct dvb_frontend *fe)
-{
-	struct tda9887_priv *priv = fe->analog_demod_priv;
-	char *buf = priv->data;
-
-	if (UNSET != port1) {
-		if (port1)
-			buf[1] |= cOutputPort1Inactive;
-		else
-			buf[1] &= ~cOutputPort1Inactive;
-	}
-	if (UNSET != port2) {
-		if (port2)
-			buf[1] |= cOutputPort2Inactive;
-		else
-			buf[1] &= ~cOutputPort2Inactive;
-	}
-
-	if (UNSET != qss) {
-		if (qss)
-			buf[1] |= cQSS;
-		else
-			buf[1] &= ~cQSS;
-	}
-
-	if (adjust < 0x20) {
-		buf[2] &= ~cTopMask;
-		buf[2] |= adjust;
-	}
-	return 0;
-}
-
-static int tda9887_do_config(struct dvb_frontend *fe)
-{
-	struct tda9887_priv *priv = fe->analog_demod_priv;
-	char *buf = priv->data;
-
-	if (priv->config & TDA9887_PORT1_ACTIVE)
-		buf[1] &= ~cOutputPort1Inactive;
-	if (priv->config & TDA9887_PORT1_INACTIVE)
-		buf[1] |= cOutputPort1Inactive;
-	if (priv->config & TDA9887_PORT2_ACTIVE)
-		buf[1] &= ~cOutputPort2Inactive;
-	if (priv->config & TDA9887_PORT2_INACTIVE)
-		buf[1] |= cOutputPort2Inactive;
-
-	if (priv->config & TDA9887_QSS)
-		buf[1] |= cQSS;
-	if (priv->config & TDA9887_INTERCARRIER)
-		buf[1] &= ~cQSS;
-
-	if (priv->config & TDA9887_AUTOMUTE)
-		buf[1] |= cAutoMuteFmActive;
-	if (priv->config & TDA9887_DEEMPHASIS_MASK) {
-		buf[2] &= ~0x60;
-		switch (priv->config & TDA9887_DEEMPHASIS_MASK) {
-		case TDA9887_DEEMPHASIS_NONE:
-			buf[2] |= cDeemphasisOFF;
-			break;
-		case TDA9887_DEEMPHASIS_50:
-			buf[2] |= cDeemphasisON | cDeemphasis50;
-			break;
-		case TDA9887_DEEMPHASIS_75:
-			buf[2] |= cDeemphasisON | cDeemphasis75;
-			break;
-		}
-	}
-	if (priv->config & TDA9887_TOP_SET) {
-		buf[2] &= ~cTopMask;
-		buf[2] |= (priv->config >> 8) & cTopMask;
-	}
-	if ((priv->config & TDA9887_INTERCARRIER_NTSC) &&
-	    (priv->std & V4L2_STD_NTSC))
-		buf[1] &= ~cQSS;
-	if (priv->config & TDA9887_GATING_18)
-		buf[3] &= ~cGating_36;
-
-	if (priv->mode == V4L2_TUNER_RADIO) {
-		if (priv->config & TDA9887_RIF_41_3) {
-			buf[3] &= ~cVideoIFMask;
-			buf[3] |= cRadioIF_41_30;
-		}
-		if (priv->config & TDA9887_GAIN_NORMAL)
-			buf[3] &= ~cTunerGainLow;
-	}
-
-	return 0;
-}
-
-/* ---------------------------------------------------------------------- */
-
-static int tda9887_status(struct dvb_frontend *fe)
-{
-	struct tda9887_priv *priv = fe->analog_demod_priv;
-	unsigned char buf[1];
-	int rc;
-
-	memset(buf,0,sizeof(buf));
-	if (1 != (rc = tuner_i2c_xfer_recv(&priv->i2c_props,buf,1)))
-		tuner_info("i2c i/o error: rc == %d (should be 1)\n", rc);
-	dump_read_message(fe, buf);
-	return 0;
-}
-
-static void tda9887_configure(struct dvb_frontend *fe)
-{
-	struct tda9887_priv *priv = fe->analog_demod_priv;
-	int rc;
-
-	memset(priv->data,0,sizeof(priv->data));
-	tda9887_set_tvnorm(fe);
-
-	/* A note on the port settings:
-	   These settings tend to depend on the specifics of the board.
-	   By default they are set to inactive (bit value 1) by this driver,
-	   overwriting any changes made by the tvnorm. This means that it
-	   is the responsibility of the module using the tda9887 to set
-	   these values in case of changes in the tvnorm.
-	   In many cases port 2 should be made active (0) when selecting
-	   SECAM-L, and port 2 should remain inactive (1) for SECAM-L'.
-
-	   For the other standards the tda9887 application note says that
-	   the ports should be set to active (0), but, again, that may
-	   differ depending on the precise hardware configuration.
-	 */
-	priv->data[1] |= cOutputPort1Inactive;
-	priv->data[1] |= cOutputPort2Inactive;
-
-	tda9887_do_config(fe);
-	tda9887_set_insmod(fe);
-
-	if (priv->standby)
-		priv->data[1] |= cForcedMuteAudioON;
-
-	tuner_dbg("writing: b=0x%02x c=0x%02x e=0x%02x\n",
-		  priv->data[1], priv->data[2], priv->data[3]);
-	if (debug > 1)
-		dump_write_message(fe, priv->data);
-
-	if (4 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,priv->data,4)))
-		tuner_info("i2c i/o error: rc == %d (should be 4)\n", rc);
-
-	if (debug > 2) {
-		msleep_interruptible(1000);
-		tda9887_status(fe);
-	}
-}
-
-/* ---------------------------------------------------------------------- */
-
-static void tda9887_tuner_status(struct dvb_frontend *fe)
-{
-	struct tda9887_priv *priv = fe->analog_demod_priv;
-	tuner_info("Data bytes: b=0x%02x c=0x%02x e=0x%02x\n",
-		   priv->data[1], priv->data[2], priv->data[3]);
-}
-
-static int tda9887_get_afc(struct dvb_frontend *fe)
-{
-	struct tda9887_priv *priv = fe->analog_demod_priv;
-	static int AFC_BITS_2_kHz[] = {
-		-12500,  -37500,  -62500,  -97500,
-		-112500, -137500, -162500, -187500,
-		187500,  162500,  137500,  112500,
-		97500 ,  62500,   37500 ,  12500
-	};
-	int afc=0;
-	__u8 reg = 0;
-
-	if (1 == tuner_i2c_xfer_recv(&priv->i2c_props,&reg,1))
-		afc = AFC_BITS_2_kHz[(reg>>1)&0x0f];
-
-	return afc;
-}
-
-static void tda9887_standby(struct dvb_frontend *fe)
-{
-	struct tda9887_priv *priv = fe->analog_demod_priv;
-
-	priv->standby = true;
-
-	tda9887_configure(fe);
-}
-
-static void tda9887_set_params(struct dvb_frontend *fe,
-			       struct analog_parameters *params)
-{
-	struct tda9887_priv *priv = fe->analog_demod_priv;
-
-	priv->standby = false;
-	priv->mode    = params->mode;
-	priv->audmode = params->audmode;
-	priv->std     = params->std;
-	tda9887_configure(fe);
-}
-
-static int tda9887_set_config(struct dvb_frontend *fe, void *priv_cfg)
-{
-	struct tda9887_priv *priv = fe->analog_demod_priv;
-
-	priv->config = *(unsigned int *)priv_cfg;
-	tda9887_configure(fe);
-
-	return 0;
-}
-
-static void tda9887_release(struct dvb_frontend *fe)
-{
-	struct tda9887_priv *priv = fe->analog_demod_priv;
-
-	mutex_lock(&tda9887_list_mutex);
-
-	if (priv)
-		hybrid_tuner_release_state(priv);
-
-	mutex_unlock(&tda9887_list_mutex);
-
-	fe->analog_demod_priv = NULL;
-}
-
-static struct analog_demod_ops tda9887_ops = {
-	.info		= {
-		.name	= "tda9887",
-	},
-	.set_params     = tda9887_set_params,
-	.standby        = tda9887_standby,
-	.tuner_status   = tda9887_tuner_status,
-	.get_afc        = tda9887_get_afc,
-	.release        = tda9887_release,
-	.set_config     = tda9887_set_config,
-};
-
-struct dvb_frontend *tda9887_attach(struct dvb_frontend *fe,
-				    struct i2c_adapter *i2c_adap,
-				    u8 i2c_addr)
-{
-	struct tda9887_priv *priv = NULL;
-	int instance;
-
-	mutex_lock(&tda9887_list_mutex);
-
-	instance = hybrid_tuner_request_state(struct tda9887_priv, priv,
-					      hybrid_tuner_instance_list,
-					      i2c_adap, i2c_addr, "tda9887");
-	switch (instance) {
-	case 0:
-		mutex_unlock(&tda9887_list_mutex);
-		return NULL;
-	case 1:
-		fe->analog_demod_priv = priv;
-		priv->standby = true;
-		tuner_info("tda988[5/6/7] found\n");
-		break;
-	default:
-		fe->analog_demod_priv = priv;
-		break;
-	}
-
-	mutex_unlock(&tda9887_list_mutex);
-
-	memcpy(&fe->ops.analog_ops, &tda9887_ops,
-	       sizeof(struct analog_demod_ops));
-
-	return fe;
-}
-EXPORT_SYMBOL_GPL(tda9887_attach);
-
-MODULE_LICENSE("GPL");
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/common/tuners/tda9887.h b/drivers/media/common/tuners/tda9887.h
deleted file mode 100644
index acc419e..0000000
--- a/drivers/media/common/tuners/tda9887.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the 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 __TDA9887_H__
-#define __TDA9887_H__
-
-#include <linux/i2c.h>
-#include "dvb_frontend.h"
-
-/* ------------------------------------------------------------------------ */
-#if defined(CONFIG_MEDIA_TUNER_TDA9887) || (defined(CONFIG_MEDIA_TUNER_TDA9887_MODULE) && defined(MODULE))
-extern struct dvb_frontend *tda9887_attach(struct dvb_frontend *fe,
-					   struct i2c_adapter *i2c_adap,
-					   u8 i2c_addr);
-#else
-static inline struct dvb_frontend *tda9887_attach(struct dvb_frontend *fe,
-						  struct i2c_adapter *i2c_adap,
-						  u8 i2c_addr)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif
-
-#endif /* __TDA9887_H__ */
diff --git a/drivers/media/common/tuners/tea5761.c b/drivers/media/common/tuners/tea5761.c
deleted file mode 100644
index bf78cb9..0000000
--- a/drivers/media/common/tuners/tea5761.c
+++ /dev/null
@@ -1,348 +0,0 @@
-/*
- * For Philips TEA5761 FM Chip
- * I2C address is allways 0x20 (0x10 at 7-bit mode).
- *
- * Copyright (c) 2005-2007 Mauro Carvalho Chehab (mchehab@infradead.org)
- * This code is placed under the terms of the GNUv2 General Public License
- *
- */
-
-#include <linux/i2c.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/videodev2.h>
-#include <media/tuner.h>
-#include "tuner-i2c.h"
-#include "tea5761.h"
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "enable verbose debug messages");
-
-struct tea5761_priv {
-	struct tuner_i2c_props i2c_props;
-
-	u32 frequency;
-	bool standby;
-};
-
-/*****************************************************************************/
-
-/***************************
- * TEA5761HN I2C registers *
- ***************************/
-
-/* INTREG - Read: bytes 0 and 1 / Write: byte 0 */
-
-	/* first byte for reading */
-#define TEA5761_INTREG_IFFLAG		0x10
-#define TEA5761_INTREG_LEVFLAG		0x8
-#define TEA5761_INTREG_FRRFLAG		0x2
-#define TEA5761_INTREG_BLFLAG		0x1
-
-	/* second byte for reading / byte for writing */
-#define TEA5761_INTREG_IFMSK		0x10
-#define TEA5761_INTREG_LEVMSK		0x8
-#define TEA5761_INTREG_FRMSK		0x2
-#define TEA5761_INTREG_BLMSK		0x1
-
-/* FRQSET - Read: bytes 2 and 3 / Write: byte 1 and 2 */
-
-	/* First byte */
-#define TEA5761_FRQSET_SEARCH_UP 0x80		/* 1=Station search from botton to up */
-#define TEA5761_FRQSET_SEARCH_MODE 0x40		/* 1=Search mode */
-
-	/* Bits 0-5 for divider MSB */
-
-	/* Second byte */
-	/* Bits 0-7 for divider LSB */
-
-/* TNCTRL - Read: bytes 4 and 5 / Write: Bytes 3 and 4 */
-
-	/* first byte */
-
-#define TEA5761_TNCTRL_PUPD_0	0x40	/* Power UP/Power Down MSB */
-#define TEA5761_TNCTRL_BLIM	0X20	/* 1= Japan Frequencies, 0= European frequencies */
-#define TEA5761_TNCTRL_SWPM	0x10	/* 1= software port is FRRFLAG */
-#define TEA5761_TNCTRL_IFCTC	0x08	/* 1= IF count time 15.02 ms, 0= IF count time 2.02 ms */
-#define TEA5761_TNCTRL_AFM	0x04
-#define TEA5761_TNCTRL_SMUTE	0x02	/* 1= Soft mute */
-#define TEA5761_TNCTRL_SNC	0x01
-
-	/* second byte */
-
-#define TEA5761_TNCTRL_MU	0x80	/* 1=Hard mute */
-#define TEA5761_TNCTRL_SSL_1	0x40
-#define TEA5761_TNCTRL_SSL_0	0x20
-#define TEA5761_TNCTRL_HLSI	0x10
-#define TEA5761_TNCTRL_MST	0x08	/* 1 = mono */
-#define TEA5761_TNCTRL_SWP	0x04
-#define TEA5761_TNCTRL_DTC	0x02	/* 1 = deemphasis 50 us, 0 = deemphasis 75 us */
-#define TEA5761_TNCTRL_AHLSI	0x01
-
-/* FRQCHECK - Read: bytes 6 and 7  */
-	/* First byte */
-
-	/* Bits 0-5 for divider MSB */
-
-	/* Second byte */
-	/* Bits 0-7 for divider LSB */
-
-/* TUNCHECK - Read: bytes 8 and 9  */
-
-	/* First byte */
-#define TEA5761_TUNCHECK_IF_MASK	0x7e	/* IF count */
-#define TEA5761_TUNCHECK_TUNTO		0x01
-
-	/* Second byte */
-#define TEA5761_TUNCHECK_LEV_MASK	0xf0	/* Level Count */
-#define TEA5761_TUNCHECK_LD		0x08
-#define TEA5761_TUNCHECK_STEREO		0x04
-
-/* TESTREG - Read: bytes 10 and 11 / Write: bytes 5 and 6 */
-
-	/* All zero = no test mode */
-
-/* MANID - Read: bytes 12 and 13 */
-
-	/* First byte - should be 0x10 */
-#define TEA5767_MANID_VERSION_MASK	0xf0	/* Version = 1 */
-#define TEA5767_MANID_ID_MSB_MASK	0x0f	/* Manufacurer ID - should be 0 */
-
-	/* Second byte - Should be 0x2b */
-
-#define TEA5767_MANID_ID_LSB_MASK	0xfe	/* Manufacturer ID - should be 0x15 */
-#define TEA5767_MANID_IDAV		0x01	/* 1 = Chip has ID, 0 = Chip has no ID */
-
-/* Chip ID - Read: bytes 14 and 15 */
-
-	/* First byte - should be 0x57 */
-
-	/* Second byte - should be 0x61 */
-
-/*****************************************************************************/
-
-#define FREQ_OFFSET 0 /* for TEA5767, it is 700 to give the right freq */
-static void tea5761_status_dump(unsigned char *buffer)
-{
-	unsigned int div, frq;
-
-	div = ((buffer[2] & 0x3f) << 8) | buffer[3];
-
-	frq = 1000 * (div * 32768 / 1000 + FREQ_OFFSET + 225) / 4;	/* Freq in KHz */
-
-	printk(KERN_INFO "tea5761: Frequency %d.%03d KHz (divider = 0x%04x)\n",
-	       frq / 1000, frq % 1000, div);
-}
-
-/* Freq should be specifyed at 62.5 Hz */
-static int __set_radio_freq(struct dvb_frontend *fe,
-			    unsigned int freq,
-			    bool mono)
-{
-	struct tea5761_priv *priv = fe->tuner_priv;
-	unsigned int frq = freq;
-	unsigned char buffer[7] = {0, 0, 0, 0, 0, 0, 0 };
-	unsigned div;
-	int rc;
-
-	tuner_dbg("radio freq counter %d\n", frq);
-
-	if (priv->standby) {
-		tuner_dbg("TEA5761 set to standby mode\n");
-		buffer[5] |= TEA5761_TNCTRL_MU;
-	} else {
-		buffer[4] |= TEA5761_TNCTRL_PUPD_0;
-	}
-
-
-	if (mono) {
-		tuner_dbg("TEA5761 set to mono\n");
-		buffer[5] |= TEA5761_TNCTRL_MST;
-	} else {
-		tuner_dbg("TEA5761 set to stereo\n");
-	}
-
-	div = (1000 * (frq * 4 / 16 + 700 + 225) ) >> 15;
-	buffer[1] = (div >> 8) & 0x3f;
-	buffer[2] = div & 0xff;
-
-	if (debug)
-		tea5761_status_dump(buffer);
-
-	if (7 != (rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 7)))
-		tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc);
-
-	priv->frequency = frq * 125 / 2;
-
-	return 0;
-}
-
-static int set_radio_freq(struct dvb_frontend *fe,
-			  struct analog_parameters *params)
-{
-	struct tea5761_priv *priv = fe->analog_demod_priv;
-
-	priv->standby = false;
-
-	return __set_radio_freq(fe, params->frequency,
-				params->audmode == V4L2_TUNER_MODE_MONO);
-}
-
-static int set_radio_sleep(struct dvb_frontend *fe)
-{
-	struct tea5761_priv *priv = fe->analog_demod_priv;
-
-	priv->standby = true;
-
-	return __set_radio_freq(fe, priv->frequency, false);
-}
-
-static int tea5761_read_status(struct dvb_frontend *fe, char *buffer)
-{
-	struct tea5761_priv *priv = fe->tuner_priv;
-	int rc;
-
-	memset(buffer, 0, 16);
-	if (16 != (rc = tuner_i2c_xfer_recv(&priv->i2c_props, buffer, 16))) {
-		tuner_warn("i2c i/o error: rc == %d (should be 16)\n", rc);
-		return -EREMOTEIO;
-	}
-
-	return 0;
-}
-
-static inline int tea5761_signal(struct dvb_frontend *fe, const char *buffer)
-{
-	struct tea5761_priv *priv = fe->tuner_priv;
-
-	int signal = ((buffer[9] & TEA5761_TUNCHECK_LEV_MASK) << (13 - 4));
-
-	tuner_dbg("Signal strength: %d\n", signal);
-
-	return signal;
-}
-
-static inline int tea5761_stereo(struct dvb_frontend *fe, const char *buffer)
-{
-	struct tea5761_priv *priv = fe->tuner_priv;
-
-	int stereo = buffer[9] & TEA5761_TUNCHECK_STEREO;
-
-	tuner_dbg("Radio ST GET = %02x\n", stereo);
-
-	return (stereo ? V4L2_TUNER_SUB_STEREO : 0);
-}
-
-static int tea5761_get_status(struct dvb_frontend *fe, u32 *status)
-{
-	unsigned char buffer[16];
-
-	*status = 0;
-
-	if (0 == tea5761_read_status(fe, buffer)) {
-		if (tea5761_signal(fe, buffer))
-			*status = TUNER_STATUS_LOCKED;
-		if (tea5761_stereo(fe, buffer))
-			*status |= TUNER_STATUS_STEREO;
-	}
-
-	return 0;
-}
-
-static int tea5761_get_rf_strength(struct dvb_frontend *fe, u16 *strength)
-{
-	unsigned char buffer[16];
-
-	*strength = 0;
-
-	if (0 == tea5761_read_status(fe, buffer))
-		*strength = tea5761_signal(fe, buffer);
-
-	return 0;
-}
-
-int tea5761_autodetection(struct i2c_adapter* i2c_adap, u8 i2c_addr)
-{
-	unsigned char buffer[16];
-	int rc;
-	struct tuner_i2c_props i2c = { .adap = i2c_adap, .addr = i2c_addr };
-
-	if (16 != (rc = tuner_i2c_xfer_recv(&i2c, buffer, 16))) {
-		printk(KERN_WARNING "it is not a TEA5761. Received %i chars.\n", rc);
-		return -EINVAL;
-	}
-
-	if ((buffer[13] != 0x2b) || (buffer[14] != 0x57) || (buffer[15] != 0x061)) {
-		printk(KERN_WARNING "Manufacturer ID= 0x%02x, Chip ID = %02x%02x."
-				    " It is not a TEA5761\n",
-				    buffer[13], buffer[14], buffer[15]);
-		return -EINVAL;
-	}
-	printk(KERN_WARNING "tea5761: TEA%02x%02x detected. "
-			    "Manufacturer ID= 0x%02x\n",
-			    buffer[14], buffer[15], buffer[13]);
-
-	return 0;
-}
-
-static int tea5761_release(struct dvb_frontend *fe)
-{
-	kfree(fe->tuner_priv);
-	fe->tuner_priv = NULL;
-
-	return 0;
-}
-
-static int tea5761_get_frequency(struct dvb_frontend *fe, u32 *frequency)
-{
-	struct tea5761_priv *priv = fe->tuner_priv;
-	*frequency = priv->frequency;
-	return 0;
-}
-
-static struct dvb_tuner_ops tea5761_tuner_ops = {
-	.info = {
-		.name           = "tea5761", // Philips TEA5761HN FM Radio
-	},
-	.set_analog_params = set_radio_freq,
-	.sleep		   = set_radio_sleep,
-	.release           = tea5761_release,
-	.get_frequency     = tea5761_get_frequency,
-	.get_status        = tea5761_get_status,
-	.get_rf_strength   = tea5761_get_rf_strength,
-};
-
-struct dvb_frontend *tea5761_attach(struct dvb_frontend *fe,
-				    struct i2c_adapter* i2c_adap,
-				    u8 i2c_addr)
-{
-	struct tea5761_priv *priv = NULL;
-
-	if (tea5761_autodetection(i2c_adap, i2c_addr) != 0)
-		return NULL;
-
-	priv = kzalloc(sizeof(struct tea5761_priv), GFP_KERNEL);
-	if (priv == NULL)
-		return NULL;
-	fe->tuner_priv = priv;
-
-	priv->i2c_props.addr = i2c_addr;
-	priv->i2c_props.adap = i2c_adap;
-	priv->i2c_props.name = "tea5761";
-
-	memcpy(&fe->ops.tuner_ops, &tea5761_tuner_ops,
-	       sizeof(struct dvb_tuner_ops));
-
-	tuner_info("type set to %s\n", "Philips TEA5761HN FM Radio");
-
-	return fe;
-}
-
-
-EXPORT_SYMBOL_GPL(tea5761_attach);
-EXPORT_SYMBOL_GPL(tea5761_autodetection);
-
-MODULE_DESCRIPTION("Philips TEA5761 FM tuner driver");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/common/tuners/tea5761.h b/drivers/media/common/tuners/tea5761.h
deleted file mode 100644
index 2e2ff82..0000000
--- a/drivers/media/common/tuners/tea5761.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the 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 __TEA5761_H__
-#define __TEA5761_H__
-
-#include <linux/i2c.h>
-#include "dvb_frontend.h"
-
-#if defined(CONFIG_MEDIA_TUNER_TEA5761) || (defined(CONFIG_MEDIA_TUNER_TEA5761_MODULE) && defined(MODULE))
-extern int tea5761_autodetection(struct i2c_adapter* i2c_adap, u8 i2c_addr);
-
-extern struct dvb_frontend *tea5761_attach(struct dvb_frontend *fe,
-					   struct i2c_adapter* i2c_adap,
-					   u8 i2c_addr);
-#else
-static inline int tea5761_autodetection(struct i2c_adapter* i2c_adap,
-					u8 i2c_addr)
-{
-	printk(KERN_INFO "%s: not probed - driver disabled by Kconfig\n",
-	       __func__);
-	return -EINVAL;
-}
-
-static inline struct dvb_frontend *tea5761_attach(struct dvb_frontend *fe,
-						   struct i2c_adapter* i2c_adap,
-						   u8 i2c_addr)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif
-
-#endif /* __TEA5761_H__ */
diff --git a/drivers/media/common/tuners/tea5767.c b/drivers/media/common/tuners/tea5767.c
deleted file mode 100644
index 36e85d8..0000000
--- a/drivers/media/common/tuners/tea5767.c
+++ /dev/null
@@ -1,475 +0,0 @@
-/*
- * For Philips TEA5767 FM Chip used on some TV Cards like Prolink Pixelview
- * I2C address is allways 0xC0.
- *
- *
- * Copyright (c) 2005 Mauro Carvalho Chehab (mchehab@infradead.org)
- * This code is placed under the terms of the GNU General Public License
- *
- * tea5767 autodetection thanks to Torsten Seeboth and Atsushi Nakagawa
- * from their contributions on DScaler.
- */
-
-#include <linux/i2c.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/videodev2.h>
-#include "tuner-i2c.h"
-#include "tea5767.h"
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "enable verbose debug messages");
-
-/*****************************************************************************/
-
-struct tea5767_priv {
-	struct tuner_i2c_props	i2c_props;
-	u32			frequency;
-	struct tea5767_ctrl	ctrl;
-};
-
-/*****************************************************************************/
-
-/******************************
- * Write mode register values *
- ******************************/
-
-/* First register */
-#define TEA5767_MUTE		0x80	/* Mutes output */
-#define TEA5767_SEARCH		0x40	/* Activates station search */
-/* Bits 0-5 for divider MSB */
-
-/* Second register */
-/* Bits 0-7 for divider LSB */
-
-/* Third register */
-
-/* Station search from botton to up */
-#define TEA5767_SEARCH_UP	0x80
-
-/* Searches with ADC output = 10 */
-#define TEA5767_SRCH_HIGH_LVL	0x60
-
-/* Searches with ADC output = 10 */
-#define TEA5767_SRCH_MID_LVL	0x40
-
-/* Searches with ADC output = 5 */
-#define TEA5767_SRCH_LOW_LVL	0x20
-
-/* if on, div=4*(Frf+Fif)/Fref otherwise, div=4*(Frf-Fif)/Freq) */
-#define TEA5767_HIGH_LO_INJECT	0x10
-
-/* Disable stereo */
-#define TEA5767_MONO		0x08
-
-/* Disable right channel and turns to mono */
-#define TEA5767_MUTE_RIGHT	0x04
-
-/* Disable left channel and turns to mono */
-#define TEA5767_MUTE_LEFT	0x02
-
-#define TEA5767_PORT1_HIGH	0x01
-
-/* Fourth register */
-#define TEA5767_PORT2_HIGH	0x80
-/* Chips stops working. Only I2C bus remains on */
-#define TEA5767_STDBY		0x40
-
-/* Japan freq (76-108 MHz. If disabled, 87.5-108 MHz */
-#define TEA5767_JAPAN_BAND	0x20
-
-/* Unselected means 32.768 KHz freq as reference. Otherwise Xtal at 13 MHz */
-#define TEA5767_XTAL_32768	0x10
-
-/* Cuts weak signals */
-#define TEA5767_SOFT_MUTE	0x08
-
-/* Activates high cut control */
-#define TEA5767_HIGH_CUT_CTRL	0x04
-
-/* Activates stereo noise control */
-#define TEA5767_ST_NOISE_CTL	0x02
-
-/* If activate PORT 1 indicates SEARCH or else it is used as PORT1 */
-#define TEA5767_SRCH_IND	0x01
-
-/* Fifth register */
-
-/* By activating, it will use Xtal at 13 MHz as reference for divider */
-#define TEA5767_PLLREF_ENABLE	0x80
-
-/* By activating, deemphasis=50, or else, deemphasis of 50us */
-#define TEA5767_DEEMPH_75	0X40
-
-/*****************************
- * Read mode register values *
- *****************************/
-
-/* First register */
-#define TEA5767_READY_FLAG_MASK	0x80
-#define TEA5767_BAND_LIMIT_MASK	0X40
-/* Bits 0-5 for divider MSB after search or preset */
-
-/* Second register */
-/* Bits 0-7 for divider LSB after search or preset */
-
-/* Third register */
-#define TEA5767_STEREO_MASK	0x80
-#define TEA5767_IF_CNTR_MASK	0x7f
-
-/* Fourth register */
-#define TEA5767_ADC_LEVEL_MASK	0xf0
-
-/* should be 0 */
-#define TEA5767_CHIP_ID_MASK	0x0f
-
-/* Fifth register */
-/* Reserved for future extensions */
-#define TEA5767_RESERVED_MASK	0xff
-
-/*****************************************************************************/
-
-static void tea5767_status_dump(struct tea5767_priv *priv,
-				unsigned char *buffer)
-{
-	unsigned int div, frq;
-
-	if (TEA5767_READY_FLAG_MASK & buffer[0])
-		tuner_info("Ready Flag ON\n");
-	else
-		tuner_info("Ready Flag OFF\n");
-
-	if (TEA5767_BAND_LIMIT_MASK & buffer[0])
-		tuner_info("Tuner at band limit\n");
-	else
-		tuner_info("Tuner not at band limit\n");
-
-	div = ((buffer[0] & 0x3f) << 8) | buffer[1];
-
-	switch (priv->ctrl.xtal_freq) {
-	case TEA5767_HIGH_LO_13MHz:
-		frq = (div * 50000 - 700000 - 225000) / 4;	/* Freq in KHz */
-		break;
-	case TEA5767_LOW_LO_13MHz:
-		frq = (div * 50000 + 700000 + 225000) / 4;	/* Freq in KHz */
-		break;
-	case TEA5767_LOW_LO_32768:
-		frq = (div * 32768 + 700000 + 225000) / 4;	/* Freq in KHz */
-		break;
-	case TEA5767_HIGH_LO_32768:
-	default:
-		frq = (div * 32768 - 700000 - 225000) / 4;	/* Freq in KHz */
-		break;
-	}
-	buffer[0] = (div >> 8) & 0x3f;
-	buffer[1] = div & 0xff;
-
-	tuner_info("Frequency %d.%03d KHz (divider = 0x%04x)\n",
-		   frq / 1000, frq % 1000, div);
-
-	if (TEA5767_STEREO_MASK & buffer[2])
-		tuner_info("Stereo\n");
-	else
-		tuner_info("Mono\n");
-
-	tuner_info("IF Counter = %d\n", buffer[2] & TEA5767_IF_CNTR_MASK);
-
-	tuner_info("ADC Level = %d\n",
-		   (buffer[3] & TEA5767_ADC_LEVEL_MASK) >> 4);
-
-	tuner_info("Chip ID = %d\n", (buffer[3] & TEA5767_CHIP_ID_MASK));
-
-	tuner_info("Reserved = 0x%02x\n",
-		   (buffer[4] & TEA5767_RESERVED_MASK));
-}
-
-/* Freq should be specifyed at 62.5 Hz */
-static int set_radio_freq(struct dvb_frontend *fe,
-			  struct analog_parameters *params)
-{
-	struct tea5767_priv *priv = fe->tuner_priv;
-	unsigned int frq = params->frequency;
-	unsigned char buffer[5];
-	unsigned div;
-	int rc;
-
-	tuner_dbg("radio freq = %d.%03d MHz\n", frq/16000,(frq/16)%1000);
-
-	buffer[2] = 0;
-
-	if (priv->ctrl.port1)
-		buffer[2] |= TEA5767_PORT1_HIGH;
-
-	if (params->audmode == V4L2_TUNER_MODE_MONO) {
-		tuner_dbg("TEA5767 set to mono\n");
-		buffer[2] |= TEA5767_MONO;
-	} else {
-		tuner_dbg("TEA5767 set to stereo\n");
-	}
-
-
-	buffer[3] = 0;
-
-	if (priv->ctrl.port2)
-		buffer[3] |= TEA5767_PORT2_HIGH;
-
-	if (priv->ctrl.high_cut)
-		buffer[3] |= TEA5767_HIGH_CUT_CTRL;
-
-	if (priv->ctrl.st_noise)
-		buffer[3] |= TEA5767_ST_NOISE_CTL;
-
-	if (priv->ctrl.soft_mute)
-		buffer[3] |= TEA5767_SOFT_MUTE;
-
-	if (priv->ctrl.japan_band)
-		buffer[3] |= TEA5767_JAPAN_BAND;
-
-	buffer[4] = 0;
-
-	if (priv->ctrl.deemph_75)
-		buffer[4] |= TEA5767_DEEMPH_75;
-
-	if (priv->ctrl.pllref)
-		buffer[4] |= TEA5767_PLLREF_ENABLE;
-
-
-	/* Rounds freq to next decimal value - for 62.5 KHz step */
-	/* frq = 20*(frq/16)+radio_frq[frq%16]; */
-
-	switch (priv->ctrl.xtal_freq) {
-	case TEA5767_HIGH_LO_13MHz:
-		tuner_dbg("radio HIGH LO inject xtal @ 13 MHz\n");
-		buffer[2] |= TEA5767_HIGH_LO_INJECT;
-		div = (frq * (4000 / 16) + 700000 + 225000 + 25000) / 50000;
-		break;
-	case TEA5767_LOW_LO_13MHz:
-		tuner_dbg("radio LOW LO inject xtal @ 13 MHz\n");
-
-		div = (frq * (4000 / 16) - 700000 - 225000 + 25000) / 50000;
-		break;
-	case TEA5767_LOW_LO_32768:
-		tuner_dbg("radio LOW LO inject xtal @ 32,768 MHz\n");
-		buffer[3] |= TEA5767_XTAL_32768;
-		/* const 700=4000*175 Khz - to adjust freq to right value */
-		div = ((frq * (4000 / 16) - 700000 - 225000) + 16384) >> 15;
-		break;
-	case TEA5767_HIGH_LO_32768:
-	default:
-		tuner_dbg("radio HIGH LO inject xtal @ 32,768 MHz\n");
-
-		buffer[2] |= TEA5767_HIGH_LO_INJECT;
-		buffer[3] |= TEA5767_XTAL_32768;
-		div = ((frq * (4000 / 16) + 700000 + 225000) + 16384) >> 15;
-		break;
-	}
-	buffer[0] = (div >> 8) & 0x3f;
-	buffer[1] = div & 0xff;
-
-	if (5 != (rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 5)))
-		tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc);
-
-	if (debug) {
-		if (5 != (rc = tuner_i2c_xfer_recv(&priv->i2c_props, buffer, 5)))
-			tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc);
-		else
-			tea5767_status_dump(priv, buffer);
-	}
-
-	priv->frequency = frq * 125 / 2;
-
-	return 0;
-}
-
-static int tea5767_read_status(struct dvb_frontend *fe, char *buffer)
-{
-	struct tea5767_priv *priv = fe->tuner_priv;
-	int rc;
-
-	memset(buffer, 0, 5);
-	if (5 != (rc = tuner_i2c_xfer_recv(&priv->i2c_props, buffer, 5))) {
-		tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc);
-		return -EREMOTEIO;
-	}
-
-	return 0;
-}
-
-static inline int tea5767_signal(struct dvb_frontend *fe, const char *buffer)
-{
-	struct tea5767_priv *priv = fe->tuner_priv;
-
-	int signal = ((buffer[3] & TEA5767_ADC_LEVEL_MASK) << 8);
-
-	tuner_dbg("Signal strength: %d\n", signal);
-
-	return signal;
-}
-
-static inline int tea5767_stereo(struct dvb_frontend *fe, const char *buffer)
-{
-	struct tea5767_priv *priv = fe->tuner_priv;
-
-	int stereo = buffer[2] & TEA5767_STEREO_MASK;
-
-	tuner_dbg("Radio ST GET = %02x\n", stereo);
-
-	return (stereo ? V4L2_TUNER_SUB_STEREO : 0);
-}
-
-static int tea5767_get_status(struct dvb_frontend *fe, u32 *status)
-{
-	unsigned char buffer[5];
-
-	*status = 0;
-
-	if (0 == tea5767_read_status(fe, buffer)) {
-		if (tea5767_signal(fe, buffer))
-			*status = TUNER_STATUS_LOCKED;
-		if (tea5767_stereo(fe, buffer))
-			*status |= TUNER_STATUS_STEREO;
-	}
-
-	return 0;
-}
-
-static int tea5767_get_rf_strength(struct dvb_frontend *fe, u16 *strength)
-{
-	unsigned char buffer[5];
-
-	*strength = 0;
-
-	if (0 == tea5767_read_status(fe, buffer))
-		*strength = tea5767_signal(fe, buffer);
-
-	return 0;
-}
-
-static int tea5767_standby(struct dvb_frontend *fe)
-{
-	unsigned char buffer[5];
-	struct tea5767_priv *priv = fe->tuner_priv;
-	unsigned div, rc;
-
-	div = (87500 * 4 + 700 + 225 + 25) / 50; /* Set frequency to 87.5 MHz */
-	buffer[0] = (div >> 8) & 0x3f;
-	buffer[1] = div & 0xff;
-	buffer[2] = TEA5767_PORT1_HIGH;
-	buffer[3] = TEA5767_PORT2_HIGH | TEA5767_HIGH_CUT_CTRL |
-		    TEA5767_ST_NOISE_CTL | TEA5767_JAPAN_BAND | TEA5767_STDBY;
-	buffer[4] = 0;
-
-	if (5 != (rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 5)))
-		tuner_warn("i2c i/o error: rc == %d (should be 5)\n", rc);
-
-	return 0;
-}
-
-int tea5767_autodetection(struct i2c_adapter* i2c_adap, u8 i2c_addr)
-{
-	struct tuner_i2c_props i2c = { .adap = i2c_adap, .addr = i2c_addr };
-	unsigned char buffer[7] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
-	int rc;
-
-	if ((rc = tuner_i2c_xfer_recv(&i2c, buffer, 7))< 5) {
-		printk(KERN_WARNING "It is not a TEA5767. Received %i bytes.\n", rc);
-		return -EINVAL;
-	}
-
-	/* If all bytes are the same then it's a TV tuner and not a tea5767 */
-	if (buffer[0] == buffer[1] && buffer[0] == buffer[2] &&
-	    buffer[0] == buffer[3] && buffer[0] == buffer[4]) {
-		printk(KERN_WARNING "All bytes are equal. It is not a TEA5767\n");
-		return -EINVAL;
-	}
-
-	/*  Status bytes:
-	 *  Byte 4: bit 3:1 : CI (Chip Identification) == 0
-	 *          bit 0   : internally set to 0
-	 *  Byte 5: bit 7:0 : == 0
-	 */
-	if (((buffer[3] & 0x0f) != 0x00) || (buffer[4] != 0x00)) {
-		printk(KERN_WARNING "Chip ID is not zero. It is not a TEA5767\n");
-		return -EINVAL;
-	}
-
-
-	return 0;
-}
-
-static int tea5767_release(struct dvb_frontend *fe)
-{
-	kfree(fe->tuner_priv);
-	fe->tuner_priv = NULL;
-
-	return 0;
-}
-
-static int tea5767_get_frequency(struct dvb_frontend *fe, u32 *frequency)
-{
-	struct tea5767_priv *priv = fe->tuner_priv;
-	*frequency = priv->frequency;
-
-	return 0;
-}
-
-static int tea5767_set_config (struct dvb_frontend *fe, void *priv_cfg)
-{
-	struct tea5767_priv *priv = fe->tuner_priv;
-
-	memcpy(&priv->ctrl, priv_cfg, sizeof(priv->ctrl));
-
-	return 0;
-}
-
-static struct dvb_tuner_ops tea5767_tuner_ops = {
-	.info = {
-		.name           = "tea5767", // Philips TEA5767HN FM Radio
-	},
-
-	.set_analog_params = set_radio_freq,
-	.set_config	   = tea5767_set_config,
-	.sleep             = tea5767_standby,
-	.release           = tea5767_release,
-	.get_frequency     = tea5767_get_frequency,
-	.get_status        = tea5767_get_status,
-	.get_rf_strength   = tea5767_get_rf_strength,
-};
-
-struct dvb_frontend *tea5767_attach(struct dvb_frontend *fe,
-				    struct i2c_adapter* i2c_adap,
-				    u8 i2c_addr)
-{
-	struct tea5767_priv *priv = NULL;
-
-	priv = kzalloc(sizeof(struct tea5767_priv), GFP_KERNEL);
-	if (priv == NULL)
-		return NULL;
-	fe->tuner_priv = priv;
-
-	priv->i2c_props.addr  = i2c_addr;
-	priv->i2c_props.adap  = i2c_adap;
-	priv->i2c_props.name  = "tea5767";
-
-	priv->ctrl.xtal_freq  = TEA5767_HIGH_LO_32768;
-	priv->ctrl.port1      = 1;
-	priv->ctrl.port2      = 1;
-	priv->ctrl.high_cut   = 1;
-	priv->ctrl.st_noise   = 1;
-	priv->ctrl.japan_band = 1;
-
-	memcpy(&fe->ops.tuner_ops, &tea5767_tuner_ops,
-	       sizeof(struct dvb_tuner_ops));
-
-	tuner_info("type set to %s\n", "Philips TEA5767HN FM Radio");
-
-	return fe;
-}
-
-EXPORT_SYMBOL_GPL(tea5767_attach);
-EXPORT_SYMBOL_GPL(tea5767_autodetection);
-
-MODULE_DESCRIPTION("Philips TEA5767 FM tuner driver");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/common/tuners/tea5767.h b/drivers/media/common/tuners/tea5767.h
deleted file mode 100644
index d30ab1b..0000000
--- a/drivers/media/common/tuners/tea5767.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the 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 __TEA5767_H__
-#define __TEA5767_H__
-
-#include <linux/i2c.h>
-#include "dvb_frontend.h"
-
-enum tea5767_xtal {
-	TEA5767_LOW_LO_32768    = 0,
-	TEA5767_HIGH_LO_32768   = 1,
-	TEA5767_LOW_LO_13MHz    = 2,
-	TEA5767_HIGH_LO_13MHz   = 3,
-};
-
-struct tea5767_ctrl {
-	unsigned int		port1:1;
-	unsigned int		port2:1;
-	unsigned int		high_cut:1;
-	unsigned int		st_noise:1;
-	unsigned int		soft_mute:1;
-	unsigned int		japan_band:1;
-	unsigned int		deemph_75:1;
-	unsigned int		pllref:1;
-	enum tea5767_xtal	xtal_freq;
-};
-
-#if defined(CONFIG_MEDIA_TUNER_TEA5767) || (defined(CONFIG_MEDIA_TUNER_TEA5767_MODULE) && defined(MODULE))
-extern int tea5767_autodetection(struct i2c_adapter* i2c_adap, u8 i2c_addr);
-
-extern struct dvb_frontend *tea5767_attach(struct dvb_frontend *fe,
-					   struct i2c_adapter* i2c_adap,
-					   u8 i2c_addr);
-#else
-static inline int tea5767_autodetection(struct i2c_adapter* i2c_adap,
-					u8 i2c_addr)
-{
-	printk(KERN_INFO "%s: not probed - driver disabled by Kconfig\n",
-	       __func__);
-	return -EINVAL;
-}
-
-static inline struct dvb_frontend *tea5767_attach(struct dvb_frontend *fe,
-						   struct i2c_adapter* i2c_adap,
-						   u8 i2c_addr)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif
-
-#endif /* __TEA5767_H__ */
diff --git a/drivers/media/common/tuners/tua9001.c b/drivers/media/common/tuners/tua9001.c
deleted file mode 100644
index de26070..0000000
--- a/drivers/media/common/tuners/tua9001.c
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- * Infineon TUA 9001 silicon tuner driver
- *
- * 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.,
- *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include "tua9001.h"
-#include "tua9001_priv.h"
-
-/* write register */
-static int tua9001_wr_reg(struct tua9001_priv *priv, u8 reg, u16 val)
-{
-	int ret;
-	u8 buf[3] = { reg, (val >> 8) & 0xff, (val >> 0) & 0xff };
-	struct i2c_msg msg[1] = {
-		{
-			.addr = priv->cfg->i2c_addr,
-			.flags = 0,
-			.len = sizeof(buf),
-			.buf = buf,
-		}
-	};
-
-	ret = i2c_transfer(priv->i2c, msg, 1);
-	if (ret == 1) {
-		ret = 0;
-	} else {
-		printk(KERN_WARNING "%s: I2C wr failed=%d reg=%02x\n",
-				__func__, ret, reg);
-		ret = -EREMOTEIO;
-	}
-
-	return ret;
-}
-
-static int tua9001_release(struct dvb_frontend *fe)
-{
-	kfree(fe->tuner_priv);
-	fe->tuner_priv = NULL;
-
-	return 0;
-}
-
-static int tua9001_init(struct dvb_frontend *fe)
-{
-	struct tua9001_priv *priv = fe->tuner_priv;
-	int ret = 0;
-	u8 i;
-	struct reg_val data[] = {
-		{ 0x1e, 0x6512 },
-		{ 0x25, 0xb888 },
-		{ 0x39, 0x5460 },
-		{ 0x3b, 0x00c0 },
-		{ 0x3a, 0xf000 },
-		{ 0x08, 0x0000 },
-		{ 0x32, 0x0030 },
-		{ 0x41, 0x703a },
-		{ 0x40, 0x1c78 },
-		{ 0x2c, 0x1c00 },
-		{ 0x36, 0xc013 },
-		{ 0x37, 0x6f18 },
-		{ 0x27, 0x0008 },
-		{ 0x2a, 0x0001 },
-		{ 0x34, 0x0a40 },
-	};
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c-gate */
-
-	for (i = 0; i < ARRAY_SIZE(data); i++) {
-		ret = tua9001_wr_reg(priv, data[i].reg, data[i].val);
-		if (ret)
-			break;
-	}
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c-gate */
-
-	if (ret < 0)
-		pr_debug("%s: failed=%d\n", __func__, ret);
-
-	return ret;
-}
-
-static int tua9001_set_params(struct dvb_frontend *fe)
-{
-	struct tua9001_priv *priv = fe->tuner_priv;
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	int ret, i;
-	u16 val;
-	u32 frequency;
-	struct reg_val data[2];
-
-	pr_debug("%s: delivery_system=%d frequency=%d bandwidth_hz=%d\n",
-			__func__, c->delivery_system, c->frequency,
-			c->bandwidth_hz);
-
-	switch (c->delivery_system) {
-	case SYS_DVBT:
-		switch (c->bandwidth_hz) {
-		case 8000000:
-			val  = 0x0000;
-			break;
-		case 7000000:
-			val  = 0x1000;
-			break;
-		case 6000000:
-			val  = 0x2000;
-			break;
-		case 5000000:
-			val  = 0x3000;
-			break;
-		default:
-			ret = -EINVAL;
-			goto err;
-		}
-		break;
-	default:
-		ret = -EINVAL;
-		goto err;
-	}
-
-	data[0].reg = 0x04;
-	data[0].val = val;
-
-	frequency = (c->frequency - 150000000);
-	frequency /= 100;
-	frequency *= 48;
-	frequency /= 10000;
-
-	data[1].reg = 0x1f;
-	data[1].val = frequency;
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c-gate */
-
-	for (i = 0; i < ARRAY_SIZE(data); i++) {
-		ret = tua9001_wr_reg(priv, data[i].reg, data[i].val);
-		if (ret < 0)
-			break;
-	}
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c-gate */
-
-err:
-	if (ret < 0)
-		pr_debug("%s: failed=%d\n", __func__, ret);
-
-	return ret;
-}
-
-static int tua9001_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
-{
-	*frequency = 0; /* Zero-IF */
-
-	return 0;
-}
-
-static const struct dvb_tuner_ops tua9001_tuner_ops = {
-	.info = {
-		.name           = "Infineon TUA 9001",
-
-		.frequency_min  = 170000000,
-		.frequency_max  = 862000000,
-		.frequency_step = 0,
-	},
-
-	.release = tua9001_release,
-
-	.init = tua9001_init,
-	.set_params = tua9001_set_params,
-
-	.get_if_frequency = tua9001_get_if_frequency,
-};
-
-struct dvb_frontend *tua9001_attach(struct dvb_frontend *fe,
-		struct i2c_adapter *i2c, struct tua9001_config *cfg)
-{
-	struct tua9001_priv *priv = NULL;
-
-	priv = kzalloc(sizeof(struct tua9001_priv), GFP_KERNEL);
-	if (priv == NULL)
-		return NULL;
-
-	priv->cfg = cfg;
-	priv->i2c = i2c;
-
-	printk(KERN_INFO "Infineon TUA 9001 successfully attached.");
-
-	memcpy(&fe->ops.tuner_ops, &tua9001_tuner_ops,
-			sizeof(struct dvb_tuner_ops));
-
-	fe->tuner_priv = priv;
-	return fe;
-}
-EXPORT_SYMBOL(tua9001_attach);
-
-MODULE_DESCRIPTION("Infineon TUA 9001 silicon tuner driver");
-MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/common/tuners/tua9001.h b/drivers/media/common/tuners/tua9001.h
deleted file mode 100644
index 38d6ae7..0000000
--- a/drivers/media/common/tuners/tua9001.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Infineon TUA 9001 silicon tuner driver
- *
- * 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.,
- *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef TUA9001_H
-#define TUA9001_H
-
-#include "dvb_frontend.h"
-
-struct tua9001_config {
-	/*
-	 * I2C address
-	 */
-	u8 i2c_addr;
-};
-
-#if defined(CONFIG_MEDIA_TUNER_TUA9001) || \
-	(defined(CONFIG_MEDIA_TUNER_TUA9001_MODULE) && defined(MODULE))
-extern struct dvb_frontend *tua9001_attach(struct dvb_frontend *fe,
-		struct i2c_adapter *i2c, struct tua9001_config *cfg);
-#else
-static inline struct dvb_frontend *tua9001_attach(struct dvb_frontend *fe,
-		struct i2c_adapter *i2c, struct tua9001_config *cfg)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif
-
-#endif
diff --git a/drivers/media/common/tuners/tua9001_priv.h b/drivers/media/common/tuners/tua9001_priv.h
deleted file mode 100644
index 73cc1ce..0000000
--- a/drivers/media/common/tuners/tua9001_priv.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Infineon TUA 9001 silicon tuner driver
- *
- * 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.,
- *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef TUA9001_PRIV_H
-#define TUA9001_PRIV_H
-
-struct reg_val {
-	u8 reg;
-	u16 val;
-};
-
-struct tua9001_priv {
-	struct tua9001_config *cfg;
-	struct i2c_adapter *i2c;
-};
-
-#endif
diff --git a/drivers/media/common/tuners/tuner-i2c.h b/drivers/media/common/tuners/tuner-i2c.h
deleted file mode 100644
index 18f0056..0000000
--- a/drivers/media/common/tuners/tuner-i2c.h
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
-    tuner-i2c.h - i2c interface for different tuners
-
-    Copyright (C) 2007 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 __TUNER_I2C_H__
-#define __TUNER_I2C_H__
-
-#include <linux/i2c.h>
-#include <linux/slab.h>
-
-struct tuner_i2c_props {
-	u8 addr;
-	struct i2c_adapter *adap;
-
-	/* used for tuner instance management */
-	int count;
-	char *name;
-};
-
-static inline int tuner_i2c_xfer_send(struct tuner_i2c_props *props, char *buf, int len)
-{
-	struct i2c_msg msg = { .addr = props->addr, .flags = 0,
-			       .buf = buf, .len = len };
-	int ret = i2c_transfer(props->adap, &msg, 1);
-
-	return (ret == 1) ? len : ret;
-}
-
-static inline int tuner_i2c_xfer_recv(struct tuner_i2c_props *props, char *buf, int len)
-{
-	struct i2c_msg msg = { .addr = props->addr, .flags = I2C_M_RD,
-			       .buf = buf, .len = len };
-	int ret = i2c_transfer(props->adap, &msg, 1);
-
-	return (ret == 1) ? len : ret;
-}
-
-static inline int tuner_i2c_xfer_send_recv(struct tuner_i2c_props *props,
-					   char *obuf, int olen,
-					   char *ibuf, int ilen)
-{
-	struct i2c_msg msg[2] = { { .addr = props->addr, .flags = 0,
-				    .buf = obuf, .len = olen },
-				  { .addr = props->addr, .flags = I2C_M_RD,
-				    .buf = ibuf, .len = ilen } };
-	int ret = i2c_transfer(props->adap, msg, 2);
-
-	return (ret == 2) ? ilen : ret;
-}
-
-/* Callers must declare as a global for the module:
- *
- * static LIST_HEAD(hybrid_tuner_instance_list);
- *
- * hybrid_tuner_instance_list should be the third argument
- * passed into hybrid_tuner_request_state().
- *
- * state structure must contain the following:
- *
- * 	struct list_head	hybrid_tuner_instance_list;
- *	struct tuner_i2c_props	i2c_props;
- *
- * hybrid_tuner_instance_list (both within state structure and globally)
- * is only required if the driver is using hybrid_tuner_request_state
- * and hybrid_tuner_release_state to manage state sharing between
- * multiple instances of hybrid tuners.
- */
-
-#define tuner_printk(kernlvl, i2cprops, fmt, arg...) do {		\
-	printk(kernlvl "%s %d-%04x: " fmt, i2cprops.name,		\
-			i2cprops.adap ?					\
-				i2c_adapter_id(i2cprops.adap) : -1,	\
-			i2cprops.addr, ##arg);				\
-	 } while (0)
-
-/* TO DO: convert all callers of these macros to pass in
- * struct tuner_i2c_props, then remove the macro wrappers */
-
-#define __tuner_warn(i2cprops, fmt, arg...) do {			\
-	tuner_printk(KERN_WARNING, i2cprops, fmt, ##arg);		\
-	} while (0)
-
-#define __tuner_info(i2cprops, fmt, arg...) do {			\
-	tuner_printk(KERN_INFO, i2cprops, fmt, ##arg);			\
-	} while (0)
-
-#define __tuner_err(i2cprops, fmt, arg...) do {				\
-	tuner_printk(KERN_ERR, i2cprops, fmt, ##arg);			\
-	} while (0)
-
-#define __tuner_dbg(i2cprops, fmt, arg...) do {				\
-	if ((debug))							\
-		tuner_printk(KERN_DEBUG, i2cprops, fmt, ##arg);		\
-	} while (0)
-
-#define tuner_warn(fmt, arg...) __tuner_warn(priv->i2c_props, fmt, ##arg)
-#define tuner_info(fmt, arg...) __tuner_info(priv->i2c_props, fmt, ##arg)
-#define tuner_err(fmt, arg...) __tuner_err(priv->i2c_props, fmt, ##arg)
-#define tuner_dbg(fmt, arg...) __tuner_dbg(priv->i2c_props, fmt, ##arg)
-
-/****************************************************************************/
-
-/* The return value of hybrid_tuner_request_state indicates the number of
- * instances using this tuner object.
- *
- * 0 - no instances, indicates an error - kzalloc must have failed
- *
- * 1 - one instance, indicates that the tuner object was created successfully
- *
- * 2 (or more) instances, indicates that an existing tuner object was found
- */
-
-#define hybrid_tuner_request_state(type, state, list, i2cadap, i2caddr, devname)\
-({									\
-	int __ret = 0;							\
-	list_for_each_entry(state, &list, hybrid_tuner_instance_list) {	\
-		if (((i2cadap) && (state->i2c_props.adap)) &&		\
-		    ((i2c_adapter_id(state->i2c_props.adap) ==		\
-		      i2c_adapter_id(i2cadap)) &&			\
-		     (i2caddr == state->i2c_props.addr))) {		\
-			__tuner_info(state->i2c_props,			\
-				     "attaching existing instance\n");	\
-			state->i2c_props.count++;			\
-			__ret = state->i2c_props.count;			\
-			break;						\
-		}							\
-	}								\
-	if (0 == __ret) {						\
-		state = kzalloc(sizeof(type), GFP_KERNEL);		\
-		if (NULL == state)					\
-			goto __fail;					\
-		state->i2c_props.addr = i2caddr;			\
-		state->i2c_props.adap = i2cadap;			\
-		state->i2c_props.name = devname;			\
-		__tuner_info(state->i2c_props,				\
-			     "creating new instance\n");		\
-		list_add_tail(&state->hybrid_tuner_instance_list, &list);\
-		state->i2c_props.count++;				\
-		__ret = state->i2c_props.count;				\
-	}								\
-__fail:									\
-	__ret;								\
-})
-
-#define hybrid_tuner_release_state(state)				\
-({									\
-	int __ret;							\
-	state->i2c_props.count--;					\
-	__ret = state->i2c_props.count;					\
-	if (!state->i2c_props.count) {					\
-		__tuner_info(state->i2c_props, "destroying instance\n");\
-		list_del(&state->hybrid_tuner_instance_list);		\
-		kfree(state);						\
-	}								\
-	__ret;								\
-})
-
-#define hybrid_tuner_report_instance_count(state)			\
-({									\
-	int __ret = 0;							\
-	if (state)							\
-		__ret = state->i2c_props.count;				\
-	__ret;								\
-})
-
-#endif /* __TUNER_I2C_H__ */
diff --git a/drivers/media/common/tuners/tuner-simple.c b/drivers/media/common/tuners/tuner-simple.c
deleted file mode 100644
index 39e7e58..0000000
--- a/drivers/media/common/tuners/tuner-simple.c
+++ /dev/null
@@ -1,1155 +0,0 @@
-/*
- * i2c tv tuner chip device driver
- * controls all those simple 4-control-bytes style tuners.
- *
- * This "tuner-simple" module was split apart from the original "tuner" module.
- */
-#include <linux/delay.h>
-#include <linux/i2c.h>
-#include <linux/videodev2.h>
-#include <media/tuner.h>
-#include <media/v4l2-common.h>
-#include <media/tuner-types.h>
-#include "tuner-i2c.h"
-#include "tuner-simple.h"
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "enable verbose debug messages");
-
-#define TUNER_SIMPLE_MAX 64
-static unsigned int simple_devcount;
-
-static int offset;
-module_param(offset, int, 0664);
-MODULE_PARM_DESC(offset, "Allows to specify an offset for tuner");
-
-static unsigned int atv_input[TUNER_SIMPLE_MAX] = \
-			{ [0 ... (TUNER_SIMPLE_MAX-1)] = 0 };
-static unsigned int dtv_input[TUNER_SIMPLE_MAX] = \
-			{ [0 ... (TUNER_SIMPLE_MAX-1)] = 0 };
-module_param_array(atv_input, int, NULL, 0644);
-module_param_array(dtv_input, int, NULL, 0644);
-MODULE_PARM_DESC(atv_input, "specify atv rf input, 0 for autoselect");
-MODULE_PARM_DESC(dtv_input, "specify dtv rf input, 0 for autoselect");
-
-/* ---------------------------------------------------------------------- */
-
-/* tv standard selection for Temic 4046 FM5
-   this value takes the low bits of control byte 2
-   from datasheet Rev.01, Feb.00
-     standard     BG      I       L       L2      D
-     picture IF   38.9    38.9    38.9    33.95   38.9
-     sound 1      33.4    32.9    32.4    40.45   32.4
-     sound 2      33.16
-     NICAM        33.05   32.348  33.05           33.05
- */
-#define TEMIC_SET_PAL_I         0x05
-#define TEMIC_SET_PAL_DK        0x09
-#define TEMIC_SET_PAL_L         0x0a /* SECAM ? */
-#define TEMIC_SET_PAL_L2        0x0b /* change IF ! */
-#define TEMIC_SET_PAL_BG        0x0c
-
-/* tv tuner system standard selection for Philips FQ1216ME
-   this value takes the low bits of control byte 2
-   from datasheet "1999 Nov 16" (supersedes "1999 Mar 23")
-     standard 		BG	DK	I	L	L`
-     picture carrier	38.90	38.90	38.90	38.90	33.95
-     colour		34.47	34.47	34.47	34.47	38.38
-     sound 1		33.40	32.40	32.90	32.40	40.45
-     sound 2		33.16	-	-	-	-
-     NICAM		33.05	33.05	32.35	33.05	39.80
- */
-#define PHILIPS_SET_PAL_I	0x01 /* Bit 2 always zero !*/
-#define PHILIPS_SET_PAL_BGDK	0x09
-#define PHILIPS_SET_PAL_L2	0x0a
-#define PHILIPS_SET_PAL_L	0x0b
-
-/* system switching for Philips FI1216MF MK2
-   from datasheet "1996 Jul 09",
-    standard         BG     L      L'
-    picture carrier  38.90  38.90  33.95
-    colour	     34.47  34.37  38.38
-    sound 1          33.40  32.40  40.45
-    sound 2          33.16  -      -
-    NICAM            33.05  33.05  39.80
- */
-#define PHILIPS_MF_SET_STD_BG	0x01 /* Bit 2 must be zero, Bit 3 is system output */
-#define PHILIPS_MF_SET_STD_L	0x03 /* Used on Secam France */
-#define PHILIPS_MF_SET_STD_LC	0x02 /* Used on SECAM L' */
-
-/* Control byte */
-
-#define TUNER_RATIO_MASK        0x06 /* Bit cb1:cb2 */
-#define TUNER_RATIO_SELECT_50   0x00
-#define TUNER_RATIO_SELECT_32   0x02
-#define TUNER_RATIO_SELECT_166  0x04
-#define TUNER_RATIO_SELECT_62   0x06
-
-#define TUNER_CHARGE_PUMP       0x40  /* Bit cb6 */
-
-/* Status byte */
-
-#define TUNER_POR	  0x80
-#define TUNER_FL          0x40
-#define TUNER_MODE        0x38
-#define TUNER_AFC         0x07
-#define TUNER_SIGNAL      0x07
-#define TUNER_STEREO      0x10
-
-#define TUNER_PLL_LOCKED   0x40
-#define TUNER_STEREO_MK3   0x04
-
-static DEFINE_MUTEX(tuner_simple_list_mutex);
-static LIST_HEAD(hybrid_tuner_instance_list);
-
-struct tuner_simple_priv {
-	unsigned int nr;
-	u16 last_div;
-
-	struct tuner_i2c_props i2c_props;
-	struct list_head hybrid_tuner_instance_list;
-
-	unsigned int type;
-	struct tunertype *tun;
-
-	u32 frequency;
-	u32 bandwidth;
-};
-
-/* ---------------------------------------------------------------------- */
-
-static int tuner_read_status(struct dvb_frontend *fe)
-{
-	struct tuner_simple_priv *priv = fe->tuner_priv;
-	unsigned char byte;
-
-	if (1 != tuner_i2c_xfer_recv(&priv->i2c_props, &byte, 1))
-		return 0;
-
-	return byte;
-}
-
-static inline int tuner_signal(const int status)
-{
-	return (status & TUNER_SIGNAL) << 13;
-}
-
-static inline int tuner_stereo(const int type, const int status)
-{
-	switch (type) {
-	case TUNER_PHILIPS_FM1216ME_MK3:
-	case TUNER_PHILIPS_FM1236_MK3:
-	case TUNER_PHILIPS_FM1256_IH3:
-	case TUNER_LG_NTSC_TAPE:
-	case TUNER_TCL_MF02GIP_5N:
-		return ((status & TUNER_SIGNAL) == TUNER_STEREO_MK3);
-	case TUNER_PHILIPS_FM1216MK5:
-		return status | TUNER_STEREO;
-	default:
-		return status & TUNER_STEREO;
-	}
-}
-
-static inline int tuner_islocked(const int status)
-{
-	return (status & TUNER_FL);
-}
-
-static inline int tuner_afcstatus(const int status)
-{
-	return (status & TUNER_AFC) - 2;
-}
-
-
-static int simple_get_status(struct dvb_frontend *fe, u32 *status)
-{
-	struct tuner_simple_priv *priv = fe->tuner_priv;
-	int tuner_status;
-
-	if (priv->i2c_props.adap == NULL)
-		return -EINVAL;
-
-	tuner_status = tuner_read_status(fe);
-
-	*status = 0;
-
-	if (tuner_islocked(tuner_status))
-		*status = TUNER_STATUS_LOCKED;
-	if (tuner_stereo(priv->type, tuner_status))
-		*status |= TUNER_STATUS_STEREO;
-
-	tuner_dbg("AFC Status: %d\n", tuner_afcstatus(tuner_status));
-
-	return 0;
-}
-
-static int simple_get_rf_strength(struct dvb_frontend *fe, u16 *strength)
-{
-	struct tuner_simple_priv *priv = fe->tuner_priv;
-	int signal;
-
-	if (priv->i2c_props.adap == NULL)
-		return -EINVAL;
-
-	signal = tuner_signal(tuner_read_status(fe));
-
-	*strength = signal;
-
-	tuner_dbg("Signal strength: %d\n", signal);
-
-	return 0;
-}
-
-/* ---------------------------------------------------------------------- */
-
-static inline char *tuner_param_name(enum param_type type)
-{
-	char *name;
-
-	switch (type) {
-	case TUNER_PARAM_TYPE_RADIO:
-		name = "radio";
-		break;
-	case TUNER_PARAM_TYPE_PAL:
-		name = "pal";
-		break;
-	case TUNER_PARAM_TYPE_SECAM:
-		name = "secam";
-		break;
-	case TUNER_PARAM_TYPE_NTSC:
-		name = "ntsc";
-		break;
-	case TUNER_PARAM_TYPE_DIGITAL:
-		name = "digital";
-		break;
-	default:
-		name = "unknown";
-		break;
-	}
-	return name;
-}
-
-static struct tuner_params *simple_tuner_params(struct dvb_frontend *fe,
-						enum param_type desired_type)
-{
-	struct tuner_simple_priv *priv = fe->tuner_priv;
-	struct tunertype *tun = priv->tun;
-	int i;
-
-	for (i = 0; i < tun->count; i++)
-		if (desired_type == tun->params[i].type)
-			break;
-
-	/* use default tuner params if desired_type not available */
-	if (i == tun->count) {
-		tuner_dbg("desired params (%s) undefined for tuner %d\n",
-			  tuner_param_name(desired_type), priv->type);
-		i = 0;
-	}
-
-	tuner_dbg("using tuner params #%d (%s)\n", i,
-		  tuner_param_name(tun->params[i].type));
-
-	return &tun->params[i];
-}
-
-static int simple_config_lookup(struct dvb_frontend *fe,
-				struct tuner_params *t_params,
-				unsigned *frequency, u8 *config, u8 *cb)
-{
-	struct tuner_simple_priv *priv = fe->tuner_priv;
-	int i;
-
-	for (i = 0; i < t_params->count; i++) {
-		if (*frequency > t_params->ranges[i].limit)
-			continue;
-		break;
-	}
-	if (i == t_params->count) {
-		tuner_dbg("frequency out of range (%d > %d)\n",
-			  *frequency, t_params->ranges[i - 1].limit);
-		*frequency = t_params->ranges[--i].limit;
-	}
-	*config = t_params->ranges[i].config;
-	*cb     = t_params->ranges[i].cb;
-
-	tuner_dbg("freq = %d.%02d (%d), range = %d, "
-		  "config = 0x%02x, cb = 0x%02x\n",
-		  *frequency / 16, *frequency % 16 * 100 / 16, *frequency,
-		  i, *config, *cb);
-
-	return i;
-}
-
-/* ---------------------------------------------------------------------- */
-
-static void simple_set_rf_input(struct dvb_frontend *fe,
-				u8 *config, u8 *cb, unsigned int rf)
-{
-	struct tuner_simple_priv *priv = fe->tuner_priv;
-
-	switch (priv->type) {
-	case TUNER_PHILIPS_TUV1236D:
-		switch (rf) {
-		case 1:
-			*cb |= 0x08;
-			break;
-		default:
-			*cb &= ~0x08;
-			break;
-		}
-		break;
-	case TUNER_PHILIPS_FCV1236D:
-		switch (rf) {
-		case 1:
-			*cb |= 0x01;
-			break;
-		default:
-			*cb &= ~0x01;
-			break;
-		}
-		break;
-	default:
-		break;
-	}
-}
-
-static int simple_std_setup(struct dvb_frontend *fe,
-			    struct analog_parameters *params,
-			    u8 *config, u8 *cb)
-{
-	struct tuner_simple_priv *priv = fe->tuner_priv;
-	int rc;
-
-	/* tv norm specific stuff for multi-norm tuners */
-	switch (priv->type) {
-	case TUNER_PHILIPS_SECAM: /* FI1216MF */
-		/* 0x01 -> ??? no change ??? */
-		/* 0x02 -> PAL BDGHI / SECAM L */
-		/* 0x04 -> ??? PAL others / SECAM others ??? */
-		*cb &= ~0x03;
-		if (params->std & V4L2_STD_SECAM_L)
-			/* also valid for V4L2_STD_SECAM */
-			*cb |= PHILIPS_MF_SET_STD_L;
-		else if (params->std & V4L2_STD_SECAM_LC)
-			*cb |= PHILIPS_MF_SET_STD_LC;
-		else /* V4L2_STD_B|V4L2_STD_GH */
-			*cb |= PHILIPS_MF_SET_STD_BG;
-		break;
-
-	case TUNER_TEMIC_4046FM5:
-		*cb &= ~0x0f;
-
-		if (params->std & V4L2_STD_PAL_BG) {
-			*cb |= TEMIC_SET_PAL_BG;
-
-		} else if (params->std & V4L2_STD_PAL_I) {
-			*cb |= TEMIC_SET_PAL_I;
-
-		} else if (params->std & V4L2_STD_PAL_DK) {
-			*cb |= TEMIC_SET_PAL_DK;
-
-		} else if (params->std & V4L2_STD_SECAM_L) {
-			*cb |= TEMIC_SET_PAL_L;
-
-		}
-		break;
-
-	case TUNER_PHILIPS_FQ1216ME:
-		*cb &= ~0x0f;
-
-		if (params->std & (V4L2_STD_PAL_BG|V4L2_STD_PAL_DK)) {
-			*cb |= PHILIPS_SET_PAL_BGDK;
-
-		} else if (params->std & V4L2_STD_PAL_I) {
-			*cb |= PHILIPS_SET_PAL_I;
-
-		} else if (params->std & V4L2_STD_SECAM_L) {
-			*cb |= PHILIPS_SET_PAL_L;
-
-		}
-		break;
-
-	case TUNER_PHILIPS_FCV1236D:
-		/* 0x00 -> ATSC antenna input 1 */
-		/* 0x01 -> ATSC antenna input 2 */
-		/* 0x02 -> NTSC antenna input 1 */
-		/* 0x03 -> NTSC antenna input 2 */
-		*cb &= ~0x03;
-		if (!(params->std & V4L2_STD_ATSC))
-			*cb |= 2;
-		break;
-
-	case TUNER_MICROTUNE_4042FI5:
-		/* Set the charge pump for fast tuning */
-		*config |= TUNER_CHARGE_PUMP;
-		break;
-
-	case TUNER_PHILIPS_TUV1236D:
-	{
-		struct tuner_i2c_props i2c = priv->i2c_props;
-		/* 0x40 -> ATSC antenna input 1 */
-		/* 0x48 -> ATSC antenna input 2 */
-		/* 0x00 -> NTSC antenna input 1 */
-		/* 0x08 -> NTSC antenna input 2 */
-		u8 buffer[4] = { 0x14, 0x00, 0x17, 0x00};
-		*cb &= ~0x40;
-		if (params->std & V4L2_STD_ATSC) {
-			*cb |= 0x40;
-			buffer[1] = 0x04;
-		}
-		/* set to the correct mode (analog or digital) */
-		i2c.addr = 0x0a;
-		rc = tuner_i2c_xfer_send(&i2c, &buffer[0], 2);
-		if (2 != rc)
-			tuner_warn("i2c i/o error: rc == %d "
-				   "(should be 2)\n", rc);
-		rc = tuner_i2c_xfer_send(&i2c, &buffer[2], 2);
-		if (2 != rc)
-			tuner_warn("i2c i/o error: rc == %d "
-				   "(should be 2)\n", rc);
-		break;
-	}
-	}
-	if (atv_input[priv->nr])
-		simple_set_rf_input(fe, config, cb, atv_input[priv->nr]);
-
-	return 0;
-}
-
-static int simple_set_aux_byte(struct dvb_frontend *fe, u8 config, u8 aux)
-{
-	struct tuner_simple_priv *priv = fe->tuner_priv;
-	int rc;
-	u8 buffer[2];
-
-	buffer[0] = (config & ~0x38) | 0x18;
-	buffer[1] = aux;
-
-	tuner_dbg("setting aux byte: 0x%02x 0x%02x\n", buffer[0], buffer[1]);
-
-	rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 2);
-	if (2 != rc)
-		tuner_warn("i2c i/o error: rc == %d (should be 2)\n", rc);
-
-	return rc == 2 ? 0 : rc;
-}
-
-static int simple_post_tune(struct dvb_frontend *fe, u8 *buffer,
-			    u16 div, u8 config, u8 cb)
-{
-	struct tuner_simple_priv *priv = fe->tuner_priv;
-	int rc;
-
-	switch (priv->type) {
-	case TUNER_LG_TDVS_H06XF:
-		simple_set_aux_byte(fe, config, 0x20);
-		break;
-	case TUNER_PHILIPS_FQ1216LME_MK3:
-		simple_set_aux_byte(fe, config, 0x60); /* External AGC */
-		break;
-	case TUNER_MICROTUNE_4042FI5:
-	{
-		/* FIXME - this may also work for other tuners */
-		unsigned long timeout = jiffies + msecs_to_jiffies(1);
-		u8 status_byte = 0;
-
-		/* Wait until the PLL locks */
-		for (;;) {
-			if (time_after(jiffies, timeout))
-				return 0;
-			rc = tuner_i2c_xfer_recv(&priv->i2c_props,
-						 &status_byte, 1);
-			if (1 != rc) {
-				tuner_warn("i2c i/o read error: rc == %d "
-					   "(should be 1)\n", rc);
-				break;
-			}
-			if (status_byte & TUNER_PLL_LOCKED)
-				break;
-			udelay(10);
-		}
-
-		/* Set the charge pump for optimized phase noise figure */
-		config &= ~TUNER_CHARGE_PUMP;
-		buffer[0] = (div>>8) & 0x7f;
-		buffer[1] = div      & 0xff;
-		buffer[2] = config;
-		buffer[3] = cb;
-		tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n",
-			  buffer[0], buffer[1], buffer[2], buffer[3]);
-
-		rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 4);
-		if (4 != rc)
-			tuner_warn("i2c i/o error: rc == %d "
-				   "(should be 4)\n", rc);
-		break;
-	}
-	}
-
-	return 0;
-}
-
-static int simple_radio_bandswitch(struct dvb_frontend *fe, u8 *buffer)
-{
-	struct tuner_simple_priv *priv = fe->tuner_priv;
-
-	switch (priv->type) {
-	case TUNER_TENA_9533_DI:
-	case TUNER_YMEC_TVF_5533MF:
-		tuner_dbg("This tuner doesn't have FM. "
-			  "Most cards have a TEA5767 for FM\n");
-		return 0;
-	case TUNER_PHILIPS_FM1216ME_MK3:
-	case TUNER_PHILIPS_FM1236_MK3:
-	case TUNER_PHILIPS_FMD1216ME_MK3:
-	case TUNER_PHILIPS_FMD1216MEX_MK3:
-	case TUNER_LG_NTSC_TAPE:
-	case TUNER_PHILIPS_FM1256_IH3:
-	case TUNER_TCL_MF02GIP_5N:
-		buffer[3] = 0x19;
-		break;
-	case TUNER_PHILIPS_FM1216MK5:
-		buffer[2] = 0x88;
-		buffer[3] = 0x09;
-		break;
-	case TUNER_TNF_5335MF:
-		buffer[3] = 0x11;
-		break;
-	case TUNER_LG_PAL_FM:
-		buffer[3] = 0xa5;
-		break;
-	case TUNER_THOMSON_DTT761X:
-		buffer[3] = 0x39;
-		break;
-	case TUNER_PHILIPS_FQ1216LME_MK3:
-	case TUNER_PHILIPS_FQ1236_MK5:
-		tuner_err("This tuner doesn't have FM\n");
-		/* Set the low band for sanity, since it covers 88-108 MHz */
-		buffer[3] = 0x01;
-		break;
-	case TUNER_MICROTUNE_4049FM5:
-	default:
-		buffer[3] = 0xa4;
-		break;
-	}
-
-	return 0;
-}
-
-/* ---------------------------------------------------------------------- */
-
-static int simple_set_tv_freq(struct dvb_frontend *fe,
-			      struct analog_parameters *params)
-{
-	struct tuner_simple_priv *priv = fe->tuner_priv;
-	u8 config, cb;
-	u16 div;
-	u8 buffer[4];
-	int rc, IFPCoff, i;
-	enum param_type desired_type;
-	struct tuner_params *t_params;
-
-	/* IFPCoff = Video Intermediate Frequency - Vif:
-		940  =16*58.75  NTSC/J (Japan)
-		732  =16*45.75  M/N STD
-		704  =16*44     ATSC (at DVB code)
-		632  =16*39.50  I U.K.
-		622.4=16*38.90  B/G D/K I, L STD
-		592  =16*37.00  D China
-		590  =16.36.875 B Australia
-		543.2=16*33.95  L' STD
-		171.2=16*10.70  FM Radio (at set_radio_freq)
-	*/
-
-	if (params->std == V4L2_STD_NTSC_M_JP) {
-		IFPCoff      = 940;
-		desired_type = TUNER_PARAM_TYPE_NTSC;
-	} else if ((params->std & V4L2_STD_MN) &&
-		  !(params->std & ~V4L2_STD_MN)) {
-		IFPCoff      = 732;
-		desired_type = TUNER_PARAM_TYPE_NTSC;
-	} else if (params->std == V4L2_STD_SECAM_LC) {
-		IFPCoff      = 543;
-		desired_type = TUNER_PARAM_TYPE_SECAM;
-	} else {
-		IFPCoff      = 623;
-		desired_type = TUNER_PARAM_TYPE_PAL;
-	}
-
-	t_params = simple_tuner_params(fe, desired_type);
-
-	i = simple_config_lookup(fe, t_params, &params->frequency,
-				 &config, &cb);
-
-	div = params->frequency + IFPCoff + offset;
-
-	tuner_dbg("Freq= %d.%02d MHz, V_IF=%d.%02d MHz, "
-		  "Offset=%d.%02d MHz, div=%0d\n",
-		  params->frequency / 16, params->frequency % 16 * 100 / 16,
-		  IFPCoff / 16, IFPCoff % 16 * 100 / 16,
-		  offset / 16, offset % 16 * 100 / 16, div);
-
-	/* tv norm specific stuff for multi-norm tuners */
-	simple_std_setup(fe, params, &config, &cb);
-
-	if (t_params->cb_first_if_lower_freq && div < priv->last_div) {
-		buffer[0] = config;
-		buffer[1] = cb;
-		buffer[2] = (div>>8) & 0x7f;
-		buffer[3] = div      & 0xff;
-	} else {
-		buffer[0] = (div>>8) & 0x7f;
-		buffer[1] = div      & 0xff;
-		buffer[2] = config;
-		buffer[3] = cb;
-	}
-	priv->last_div = div;
-	if (t_params->has_tda9887) {
-		struct v4l2_priv_tun_config tda9887_cfg;
-		int tda_config = 0;
-		int is_secam_l = (params->std & (V4L2_STD_SECAM_L |
-						 V4L2_STD_SECAM_LC)) &&
-			!(params->std & ~(V4L2_STD_SECAM_L |
-					  V4L2_STD_SECAM_LC));
-
-		tda9887_cfg.tuner = TUNER_TDA9887;
-		tda9887_cfg.priv  = &tda_config;
-
-		if (params->std == V4L2_STD_SECAM_LC) {
-			if (t_params->port1_active ^ t_params->port1_invert_for_secam_lc)
-				tda_config |= TDA9887_PORT1_ACTIVE;
-			if (t_params->port2_active ^ t_params->port2_invert_for_secam_lc)
-				tda_config |= TDA9887_PORT2_ACTIVE;
-		} else {
-			if (t_params->port1_active)
-				tda_config |= TDA9887_PORT1_ACTIVE;
-			if (t_params->port2_active)
-				tda_config |= TDA9887_PORT2_ACTIVE;
-		}
-		if (t_params->intercarrier_mode)
-			tda_config |= TDA9887_INTERCARRIER;
-		if (is_secam_l) {
-			if (i == 0 && t_params->default_top_secam_low)
-				tda_config |= TDA9887_TOP(t_params->default_top_secam_low);
-			else if (i == 1 && t_params->default_top_secam_mid)
-				tda_config |= TDA9887_TOP(t_params->default_top_secam_mid);
-			else if (t_params->default_top_secam_high)
-				tda_config |= TDA9887_TOP(t_params->default_top_secam_high);
-		} else {
-			if (i == 0 && t_params->default_top_low)
-				tda_config |= TDA9887_TOP(t_params->default_top_low);
-			else if (i == 1 && t_params->default_top_mid)
-				tda_config |= TDA9887_TOP(t_params->default_top_mid);
-			else if (t_params->default_top_high)
-				tda_config |= TDA9887_TOP(t_params->default_top_high);
-		}
-		if (t_params->default_pll_gating_18)
-			tda_config |= TDA9887_GATING_18;
-		i2c_clients_command(priv->i2c_props.adap, TUNER_SET_CONFIG,
-				    &tda9887_cfg);
-	}
-	tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n",
-		  buffer[0], buffer[1], buffer[2], buffer[3]);
-
-	rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 4);
-	if (4 != rc)
-		tuner_warn("i2c i/o error: rc == %d (should be 4)\n", rc);
-
-	simple_post_tune(fe, &buffer[0], div, config, cb);
-
-	return 0;
-}
-
-static int simple_set_radio_freq(struct dvb_frontend *fe,
-				 struct analog_parameters *params)
-{
-	struct tunertype *tun;
-	struct tuner_simple_priv *priv = fe->tuner_priv;
-	u8 buffer[4];
-	u16 div;
-	int rc, j;
-	struct tuner_params *t_params;
-	unsigned int freq = params->frequency;
-
-	tun = priv->tun;
-
-	for (j = tun->count-1; j > 0; j--)
-		if (tun->params[j].type == TUNER_PARAM_TYPE_RADIO)
-			break;
-	/* default t_params (j=0) will be used if desired type wasn't found */
-	t_params = &tun->params[j];
-
-	/* Select Radio 1st IF used */
-	switch (t_params->radio_if) {
-	case 0: /* 10.7 MHz */
-		freq += (unsigned int)(10.7*16000);
-		break;
-	case 1: /* 33.3 MHz */
-		freq += (unsigned int)(33.3*16000);
-		break;
-	case 2: /* 41.3 MHz */
-		freq += (unsigned int)(41.3*16000);
-		break;
-	default:
-		tuner_warn("Unsupported radio_if value %d\n",
-			   t_params->radio_if);
-		return 0;
-	}
-
-	buffer[2] = (t_params->ranges[0].config & ~TUNER_RATIO_MASK) |
-		    TUNER_RATIO_SELECT_50; /* 50 kHz step */
-
-	/* Bandswitch byte */
-	simple_radio_bandswitch(fe, &buffer[0]);
-
-	/* Convert from 1/16 kHz V4L steps to 1/20 MHz (=50 kHz) PLL steps
-	   freq * (1 Mhz / 16000 V4L steps) * (20 PLL steps / 1 MHz) =
-	   freq * (1/800) */
-	div = (freq + 400) / 800;
-
-	if (t_params->cb_first_if_lower_freq && div < priv->last_div) {
-		buffer[0] = buffer[2];
-		buffer[1] = buffer[3];
-		buffer[2] = (div>>8) & 0x7f;
-		buffer[3] = div      & 0xff;
-	} else {
-		buffer[0] = (div>>8) & 0x7f;
-		buffer[1] = div      & 0xff;
-	}
-
-	tuner_dbg("radio 0x%02x 0x%02x 0x%02x 0x%02x\n",
-	       buffer[0], buffer[1], buffer[2], buffer[3]);
-	priv->last_div = div;
-
-	if (t_params->has_tda9887) {
-		int config = 0;
-		struct v4l2_priv_tun_config tda9887_cfg;
-
-		tda9887_cfg.tuner = TUNER_TDA9887;
-		tda9887_cfg.priv = &config;
-
-		if (t_params->port1_active &&
-		    !t_params->port1_fm_high_sensitivity)
-			config |= TDA9887_PORT1_ACTIVE;
-		if (t_params->port2_active &&
-		    !t_params->port2_fm_high_sensitivity)
-			config |= TDA9887_PORT2_ACTIVE;
-		if (t_params->intercarrier_mode)
-			config |= TDA9887_INTERCARRIER;
-/*		if (t_params->port1_set_for_fm_mono)
-			config &= ~TDA9887_PORT1_ACTIVE;*/
-		if (t_params->fm_gain_normal)
-			config |= TDA9887_GAIN_NORMAL;
-		if (t_params->radio_if == 2)
-			config |= TDA9887_RIF_41_3;
-		i2c_clients_command(priv->i2c_props.adap, TUNER_SET_CONFIG,
-				    &tda9887_cfg);
-	}
-	rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 4);
-	if (4 != rc)
-		tuner_warn("i2c i/o error: rc == %d (should be 4)\n", rc);
-
-	/* Write AUX byte */
-	switch (priv->type) {
-	case TUNER_PHILIPS_FM1216ME_MK3:
-		buffer[2] = 0x98;
-		buffer[3] = 0x20; /* set TOP AGC */
-		rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 4);
-		if (4 != rc)
-			tuner_warn("i2c i/o error: rc == %d (should be 4)\n", rc);
-		break;
-	}
-
-	return 0;
-}
-
-static int simple_set_params(struct dvb_frontend *fe,
-			     struct analog_parameters *params)
-{
-	struct tuner_simple_priv *priv = fe->tuner_priv;
-	int ret = -EINVAL;
-
-	if (priv->i2c_props.adap == NULL)
-		return -EINVAL;
-
-	switch (params->mode) {
-	case V4L2_TUNER_RADIO:
-		ret = simple_set_radio_freq(fe, params);
-		priv->frequency = params->frequency * 125 / 2;
-		break;
-	case V4L2_TUNER_ANALOG_TV:
-	case V4L2_TUNER_DIGITAL_TV:
-		ret = simple_set_tv_freq(fe, params);
-		priv->frequency = params->frequency * 62500;
-		break;
-	}
-	priv->bandwidth = 0;
-
-	return ret;
-}
-
-static void simple_set_dvb(struct dvb_frontend *fe, u8 *buf,
-			   const u32 delsys,
-			   const u32 frequency,
-			   const u32 bandwidth)
-{
-	struct tuner_simple_priv *priv = fe->tuner_priv;
-
-	switch (priv->type) {
-	case TUNER_PHILIPS_FMD1216ME_MK3:
-	case TUNER_PHILIPS_FMD1216MEX_MK3:
-		if (bandwidth == 8000000 &&
-		    frequency >= 158870000)
-			buf[3] |= 0x08;
-		break;
-	case TUNER_PHILIPS_TD1316:
-		/* determine band */
-		buf[3] |= (frequency < 161000000) ? 1 :
-			  (frequency < 444000000) ? 2 : 4;
-
-		/* setup PLL filter */
-		if (bandwidth == 8000000)
-			buf[3] |= 1 << 3;
-		break;
-	case TUNER_PHILIPS_TUV1236D:
-	case TUNER_PHILIPS_FCV1236D:
-	{
-		unsigned int new_rf;
-
-		if (dtv_input[priv->nr])
-			new_rf = dtv_input[priv->nr];
-		else
-			switch (delsys) {
-			case SYS_DVBC_ANNEX_B:
-				new_rf = 1;
-				break;
-			case SYS_ATSC:
-			default:
-				new_rf = 0;
-				break;
-			}
-		simple_set_rf_input(fe, &buf[2], &buf[3], new_rf);
-		break;
-	}
-	default:
-		break;
-	}
-}
-
-static u32 simple_dvb_configure(struct dvb_frontend *fe, u8 *buf,
-				const u32 delsys,
-				const u32 freq,
-				const u32 bw)
-{
-	/* This function returns the tuned frequency on success, 0 on error */
-	struct tuner_simple_priv *priv = fe->tuner_priv;
-	struct tunertype *tun = priv->tun;
-	static struct tuner_params *t_params;
-	u8 config, cb;
-	u32 div;
-	int ret;
-	u32 frequency = freq / 62500;
-
-	if (!tun->stepsize) {
-		/* tuner-core was loaded before the digital tuner was
-		 * configured and somehow picked the wrong tuner type */
-		tuner_err("attempt to treat tuner %d (%s) as digital tuner "
-			  "without stepsize defined.\n",
-			  priv->type, priv->tun->name);
-		return 0; /* failure */
-	}
-
-	t_params = simple_tuner_params(fe, TUNER_PARAM_TYPE_DIGITAL);
-	ret = simple_config_lookup(fe, t_params, &frequency, &config, &cb);
-	if (ret < 0)
-		return 0; /* failure */
-
-	div = ((frequency + t_params->iffreq) * 62500 + offset +
-	       tun->stepsize/2) / tun->stepsize;
-
-	buf[0] = div >> 8;
-	buf[1] = div & 0xff;
-	buf[2] = config;
-	buf[3] = cb;
-
-	simple_set_dvb(fe, buf, delsys, freq, bw);
-
-	tuner_dbg("%s: div=%d | buf=0x%02x,0x%02x,0x%02x,0x%02x\n",
-		  tun->name, div, buf[0], buf[1], buf[2], buf[3]);
-
-	/* calculate the frequency we set it to */
-	return (div * tun->stepsize) - t_params->iffreq;
-}
-
-static int simple_dvb_calc_regs(struct dvb_frontend *fe,
-				u8 *buf, int buf_len)
-{
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	u32 delsys = c->delivery_system;
-	u32 bw = c->bandwidth_hz;
-	struct tuner_simple_priv *priv = fe->tuner_priv;
-	u32 frequency;
-
-	if (buf_len < 5)
-		return -EINVAL;
-
-	frequency = simple_dvb_configure(fe, buf+1, delsys, c->frequency, bw);
-	if (frequency == 0)
-		return -EINVAL;
-
-	buf[0] = priv->i2c_props.addr;
-
-	priv->frequency = frequency;
-	priv->bandwidth = c->bandwidth_hz;
-
-	return 5;
-}
-
-static int simple_dvb_set_params(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	u32 delsys = c->delivery_system;
-	u32 bw = c->bandwidth_hz;
-	u32 freq = c->frequency;
-	struct tuner_simple_priv *priv = fe->tuner_priv;
-	u32 frequency;
-	u32 prev_freq, prev_bw;
-	int ret;
-	u8 buf[5];
-
-	if (priv->i2c_props.adap == NULL)
-		return -EINVAL;
-
-	prev_freq = priv->frequency;
-	prev_bw   = priv->bandwidth;
-
-	frequency = simple_dvb_configure(fe, buf+1, delsys, freq, bw);
-	if (frequency == 0)
-		return -EINVAL;
-
-	buf[0] = priv->i2c_props.addr;
-
-	priv->frequency = frequency;
-	priv->bandwidth = bw;
-
-	/* put analog demod in standby when tuning digital */
-	if (fe->ops.analog_ops.standby)
-		fe->ops.analog_ops.standby(fe);
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-
-	/* buf[0] contains the i2c address, but *
-	 * we already have it in i2c_props.addr */
-	ret = tuner_i2c_xfer_send(&priv->i2c_props, buf+1, 4);
-	if (ret != 4)
-		goto fail;
-
-	return 0;
-fail:
-	/* calc_regs sets frequency and bandwidth. if we failed, unset them */
-	priv->frequency = prev_freq;
-	priv->bandwidth = prev_bw;
-
-	return ret;
-}
-
-static int simple_init(struct dvb_frontend *fe)
-{
-	struct tuner_simple_priv *priv = fe->tuner_priv;
-
-	if (priv->i2c_props.adap == NULL)
-		return -EINVAL;
-
-	if (priv->tun->initdata) {
-		int ret;
-
-		if (fe->ops.i2c_gate_ctrl)
-			fe->ops.i2c_gate_ctrl(fe, 1);
-
-		ret = tuner_i2c_xfer_send(&priv->i2c_props,
-					  priv->tun->initdata + 1,
-					  priv->tun->initdata[0]);
-		if (ret != priv->tun->initdata[0])
-			return ret;
-	}
-
-	return 0;
-}
-
-static int simple_sleep(struct dvb_frontend *fe)
-{
-	struct tuner_simple_priv *priv = fe->tuner_priv;
-
-	if (priv->i2c_props.adap == NULL)
-		return -EINVAL;
-
-	if (priv->tun->sleepdata) {
-		int ret;
-
-		if (fe->ops.i2c_gate_ctrl)
-			fe->ops.i2c_gate_ctrl(fe, 1);
-
-		ret = tuner_i2c_xfer_send(&priv->i2c_props,
-					  priv->tun->sleepdata + 1,
-					  priv->tun->sleepdata[0]);
-		if (ret != priv->tun->sleepdata[0])
-			return ret;
-	}
-
-	return 0;
-}
-
-static int simple_release(struct dvb_frontend *fe)
-{
-	struct tuner_simple_priv *priv = fe->tuner_priv;
-
-	mutex_lock(&tuner_simple_list_mutex);
-
-	if (priv)
-		hybrid_tuner_release_state(priv);
-
-	mutex_unlock(&tuner_simple_list_mutex);
-
-	fe->tuner_priv = NULL;
-
-	return 0;
-}
-
-static int simple_get_frequency(struct dvb_frontend *fe, u32 *frequency)
-{
-	struct tuner_simple_priv *priv = fe->tuner_priv;
-	*frequency = priv->frequency;
-	return 0;
-}
-
-static int simple_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
-{
-	struct tuner_simple_priv *priv = fe->tuner_priv;
-	*bandwidth = priv->bandwidth;
-	return 0;
-}
-
-static struct dvb_tuner_ops simple_tuner_ops = {
-	.init              = simple_init,
-	.sleep             = simple_sleep,
-	.set_analog_params = simple_set_params,
-	.set_params        = simple_dvb_set_params,
-	.calc_regs         = simple_dvb_calc_regs,
-	.release           = simple_release,
-	.get_frequency     = simple_get_frequency,
-	.get_bandwidth     = simple_get_bandwidth,
-	.get_status        = simple_get_status,
-	.get_rf_strength   = simple_get_rf_strength,
-};
-
-struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe,
-					 struct i2c_adapter *i2c_adap,
-					 u8 i2c_addr,
-					 unsigned int type)
-{
-	struct tuner_simple_priv *priv = NULL;
-	int instance;
-
-	if (type >= tuner_count) {
-		printk(KERN_WARNING "%s: invalid tuner type: %d (max: %d)\n",
-		       __func__, type, tuner_count-1);
-		return NULL;
-	}
-
-	/* If i2c_adap is set, check that the tuner is at the correct address.
-	 * Otherwise, if i2c_adap is NULL, the tuner will be programmed directly
-	 * by the digital demod via calc_regs.
-	 */
-	if (i2c_adap != NULL) {
-		u8 b[1];
-		struct i2c_msg msg = {
-			.addr = i2c_addr, .flags = I2C_M_RD,
-			.buf = b, .len = 1,
-		};
-
-		if (fe->ops.i2c_gate_ctrl)
-			fe->ops.i2c_gate_ctrl(fe, 1);
-
-		if (1 != i2c_transfer(i2c_adap, &msg, 1))
-			printk(KERN_WARNING "tuner-simple %d-%04x: "
-			       "unable to probe %s, proceeding anyway.",
-			       i2c_adapter_id(i2c_adap), i2c_addr,
-			       tuners[type].name);
-
-		if (fe->ops.i2c_gate_ctrl)
-			fe->ops.i2c_gate_ctrl(fe, 0);
-	}
-
-	mutex_lock(&tuner_simple_list_mutex);
-
-	instance = hybrid_tuner_request_state(struct tuner_simple_priv, priv,
-					      hybrid_tuner_instance_list,
-					      i2c_adap, i2c_addr,
-					      "tuner-simple");
-	switch (instance) {
-	case 0:
-		mutex_unlock(&tuner_simple_list_mutex);
-		return NULL;
-	case 1:
-		fe->tuner_priv = priv;
-
-		priv->type = type;
-		priv->tun  = &tuners[type];
-		priv->nr   = simple_devcount++;
-		break;
-	default:
-		fe->tuner_priv = priv;
-		break;
-	}
-
-	mutex_unlock(&tuner_simple_list_mutex);
-
-	memcpy(&fe->ops.tuner_ops, &simple_tuner_ops,
-	       sizeof(struct dvb_tuner_ops));
-
-	if (type != priv->type)
-		tuner_warn("couldn't set type to %d. Using %d (%s) instead\n",
-			    type, priv->type, priv->tun->name);
-	else
-		tuner_info("type set to %d (%s)\n",
-			   priv->type, priv->tun->name);
-
-	if ((debug) || ((atv_input[priv->nr] > 0) ||
-			(dtv_input[priv->nr] > 0))) {
-		if (0 == atv_input[priv->nr])
-			tuner_info("tuner %d atv rf input will be "
-				   "autoselected\n", priv->nr);
-		else
-			tuner_info("tuner %d atv rf input will be "
-				   "set to input %d (insmod option)\n",
-				   priv->nr, atv_input[priv->nr]);
-		if (0 == dtv_input[priv->nr])
-			tuner_info("tuner %d dtv rf input will be "
-				   "autoselected\n", priv->nr);
-		else
-			tuner_info("tuner %d dtv rf input will be "
-				   "set to input %d (insmod option)\n",
-				   priv->nr, dtv_input[priv->nr]);
-	}
-
-	strlcpy(fe->ops.tuner_ops.info.name, priv->tun->name,
-		sizeof(fe->ops.tuner_ops.info.name));
-
-	return fe;
-}
-EXPORT_SYMBOL_GPL(simple_tuner_attach);
-
-MODULE_DESCRIPTION("Simple 4-control-bytes style tuner driver");
-MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer");
-MODULE_LICENSE("GPL");
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/common/tuners/tuner-simple.h b/drivers/media/common/tuners/tuner-simple.h
deleted file mode 100644
index 381fa5d..0000000
--- a/drivers/media/common/tuners/tuner-simple.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the 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 __TUNER_SIMPLE_H__
-#define __TUNER_SIMPLE_H__
-
-#include <linux/i2c.h>
-#include "dvb_frontend.h"
-
-#if defined(CONFIG_MEDIA_TUNER_SIMPLE) || (defined(CONFIG_MEDIA_TUNER_SIMPLE_MODULE) && defined(MODULE))
-extern struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe,
-						struct i2c_adapter *i2c_adap,
-						u8 i2c_addr,
-						unsigned int type);
-#else
-static inline struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe,
-						       struct i2c_adapter *i2c_adap,
-						       u8 i2c_addr,
-						       unsigned int type)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif
-
-#endif /* __TUNER_SIMPLE_H__ */
diff --git a/drivers/media/common/tuners/tuner-types.c b/drivers/media/common/tuners/tuner-types.c
deleted file mode 100644
index 2da4440..0000000
--- a/drivers/media/common/tuners/tuner-types.c
+++ /dev/null
@@ -1,1883 +0,0 @@
-/*
- *
- * i2c tv tuner chip device type database.
- *
- */
-
-#include <linux/i2c.h>
-#include <linux/module.h>
-#include <media/tuner.h>
-#include <media/tuner-types.h>
-
-/* ---------------------------------------------------------------------- */
-
-/*
- *	The floats in the tuner struct are computed at compile time
- *	by gcc and cast back to integers. Thus we don't violate the
- *	"no float in kernel" rule.
- *
- *	A tuner_range may be referenced by multiple tuner_params structs.
- *	There are many duplicates in here. Reusing tuner_range structs,
- *	rather than defining new ones for each tuner, will cut down on
- *	memory usage, and is preferred when possible.
- *
- *	Each tuner_params array may contain one or more elements, one
- *	for each video standard.
- *
- *	FIXME: tuner_params struct contains an element, tda988x. We must
- *	set this for all tuners that contain a tda988x chip, and then we
- *	can remove this setting from the various card structs.
- *
- *	FIXME: Right now, all tuners are using the first tuner_params[]
- *	array element for analog mode. In the future, we will be merging
- *	similar tuner definitions together, such that each tuner definition
- *	will have a tuner_params struct for each available video standard.
- *	At that point, the tuner_params[] array element will be chosen
- *	based on the video standard in use.
- */
-
-/* The following was taken from dvb-pll.c: */
-
-/* Set AGC TOP value to 103 dBuV:
- *	0x80 = Control Byte
- *	0x40 = 250 uA charge pump (irrelevant)
- *	0x18 = Aux Byte to follow
- *	0x06 = 64.5 kHz divider (irrelevant)
- *	0x01 = Disable Vt (aka sleep)
- *
- *	0x00 = AGC Time constant 2s Iagc = 300 nA (vs 0x80 = 9 nA)
- *	0x50 = AGC Take over point = 103 dBuV
- */
-static u8 tua603x_agc103[] = { 2, 0x80|0x40|0x18|0x06|0x01, 0x00|0x50 };
-
-/*	0x04 = 166.67 kHz divider
- *
- *	0x80 = AGC Time constant 50ms Iagc = 9 uA
- *	0x20 = AGC Take over point = 112 dBuV
- */
-static u8 tua603x_agc112[] = { 2, 0x80|0x40|0x18|0x04|0x01, 0x80|0x20 };
-
-/* 0-9 */
-/* ------------ TUNER_TEMIC_PAL - TEMIC PAL ------------ */
-
-static struct tuner_range tuner_temic_pal_ranges[] = {
-	{ 16 * 140.25 /*MHz*/, 0x8e, 0x02, },
-	{ 16 * 463.25 /*MHz*/, 0x8e, 0x04, },
-	{ 16 * 999.99        , 0x8e, 0x01, },
-};
-
-static struct tuner_params tuner_temic_pal_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_PAL,
-		.ranges = tuner_temic_pal_ranges,
-		.count  = ARRAY_SIZE(tuner_temic_pal_ranges),
-	},
-};
-
-/* ------------ TUNER_PHILIPS_PAL_I - Philips PAL_I ------------ */
-
-static struct tuner_range tuner_philips_pal_i_ranges[] = {
-	{ 16 * 140.25 /*MHz*/, 0x8e, 0xa0, },
-	{ 16 * 463.25 /*MHz*/, 0x8e, 0x90, },
-	{ 16 * 999.99        , 0x8e, 0x30, },
-};
-
-static struct tuner_params tuner_philips_pal_i_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_PAL,
-		.ranges = tuner_philips_pal_i_ranges,
-		.count  = ARRAY_SIZE(tuner_philips_pal_i_ranges),
-	},
-};
-
-/* ------------ TUNER_PHILIPS_NTSC - Philips NTSC ------------ */
-
-static struct tuner_range tuner_philips_ntsc_ranges[] = {
-	{ 16 * 157.25 /*MHz*/, 0x8e, 0xa0, },
-	{ 16 * 451.25 /*MHz*/, 0x8e, 0x90, },
-	{ 16 * 999.99        , 0x8e, 0x30, },
-};
-
-static struct tuner_params tuner_philips_ntsc_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_NTSC,
-		.ranges = tuner_philips_ntsc_ranges,
-		.count  = ARRAY_SIZE(tuner_philips_ntsc_ranges),
-		.cb_first_if_lower_freq = 1,
-	},
-};
-
-/* ------------ TUNER_PHILIPS_SECAM - Philips SECAM ------------ */
-
-static struct tuner_range tuner_philips_secam_ranges[] = {
-	{ 16 * 168.25 /*MHz*/, 0x8e, 0xa7, },
-	{ 16 * 447.25 /*MHz*/, 0x8e, 0x97, },
-	{ 16 * 999.99        , 0x8e, 0x37, },
-};
-
-static struct tuner_params tuner_philips_secam_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_SECAM,
-		.ranges = tuner_philips_secam_ranges,
-		.count  = ARRAY_SIZE(tuner_philips_secam_ranges),
-		.cb_first_if_lower_freq = 1,
-	},
-};
-
-/* ------------ TUNER_PHILIPS_PAL - Philips PAL ------------ */
-
-static struct tuner_range tuner_philips_pal_ranges[] = {
-	{ 16 * 168.25 /*MHz*/, 0x8e, 0xa0, },
-	{ 16 * 447.25 /*MHz*/, 0x8e, 0x90, },
-	{ 16 * 999.99        , 0x8e, 0x30, },
-};
-
-static struct tuner_params tuner_philips_pal_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_PAL,
-		.ranges = tuner_philips_pal_ranges,
-		.count  = ARRAY_SIZE(tuner_philips_pal_ranges),
-		.cb_first_if_lower_freq = 1,
-	},
-};
-
-/* ------------ TUNER_TEMIC_NTSC - TEMIC NTSC ------------ */
-
-static struct tuner_range tuner_temic_ntsc_ranges[] = {
-	{ 16 * 157.25 /*MHz*/, 0x8e, 0x02, },
-	{ 16 * 463.25 /*MHz*/, 0x8e, 0x04, },
-	{ 16 * 999.99        , 0x8e, 0x01, },
-};
-
-static struct tuner_params tuner_temic_ntsc_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_NTSC,
-		.ranges = tuner_temic_ntsc_ranges,
-		.count  = ARRAY_SIZE(tuner_temic_ntsc_ranges),
-	},
-};
-
-/* ------------ TUNER_TEMIC_PAL_I - TEMIC PAL_I ------------ */
-
-static struct tuner_range tuner_temic_pal_i_ranges[] = {
-	{ 16 * 170.00 /*MHz*/, 0x8e, 0x02, },
-	{ 16 * 450.00 /*MHz*/, 0x8e, 0x04, },
-	{ 16 * 999.99        , 0x8e, 0x01, },
-};
-
-static struct tuner_params tuner_temic_pal_i_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_PAL,
-		.ranges = tuner_temic_pal_i_ranges,
-		.count  = ARRAY_SIZE(tuner_temic_pal_i_ranges),
-	},
-};
-
-/* ------------ TUNER_TEMIC_4036FY5_NTSC - TEMIC NTSC ------------ */
-
-static struct tuner_range tuner_temic_4036fy5_ntsc_ranges[] = {
-	{ 16 * 157.25 /*MHz*/, 0x8e, 0xa0, },
-	{ 16 * 463.25 /*MHz*/, 0x8e, 0x90, },
-	{ 16 * 999.99        , 0x8e, 0x30, },
-};
-
-static struct tuner_params tuner_temic_4036fy5_ntsc_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_NTSC,
-		.ranges = tuner_temic_4036fy5_ntsc_ranges,
-		.count  = ARRAY_SIZE(tuner_temic_4036fy5_ntsc_ranges),
-	},
-};
-
-/* ------------ TUNER_ALPS_TSBH1_NTSC - TEMIC NTSC ------------ */
-
-static struct tuner_range tuner_alps_tsb_1_ranges[] = {
-	{ 16 * 137.25 /*MHz*/, 0x8e, 0x01, },
-	{ 16 * 385.25 /*MHz*/, 0x8e, 0x02, },
-	{ 16 * 999.99        , 0x8e, 0x08, },
-};
-
-static struct tuner_params tuner_alps_tsbh1_ntsc_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_NTSC,
-		.ranges = tuner_alps_tsb_1_ranges,
-		.count  = ARRAY_SIZE(tuner_alps_tsb_1_ranges),
-	},
-};
-
-/* 10-19 */
-/* ------------ TUNER_ALPS_TSBE1_PAL - TEMIC PAL ------------ */
-
-static struct tuner_params tuner_alps_tsb_1_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_PAL,
-		.ranges = tuner_alps_tsb_1_ranges,
-		.count  = ARRAY_SIZE(tuner_alps_tsb_1_ranges),
-	},
-};
-
-/* ------------ TUNER_ALPS_TSBB5_PAL_I - Alps PAL_I ------------ */
-
-static struct tuner_range tuner_alps_tsb_5_pal_ranges[] = {
-	{ 16 * 133.25 /*MHz*/, 0x8e, 0x01, },
-	{ 16 * 351.25 /*MHz*/, 0x8e, 0x02, },
-	{ 16 * 999.99        , 0x8e, 0x08, },
-};
-
-static struct tuner_params tuner_alps_tsbb5_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_PAL,
-		.ranges = tuner_alps_tsb_5_pal_ranges,
-		.count  = ARRAY_SIZE(tuner_alps_tsb_5_pal_ranges),
-	},
-};
-
-/* ------------ TUNER_ALPS_TSBE5_PAL - Alps PAL ------------ */
-
-static struct tuner_params tuner_alps_tsbe5_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_PAL,
-		.ranges = tuner_alps_tsb_5_pal_ranges,
-		.count  = ARRAY_SIZE(tuner_alps_tsb_5_pal_ranges),
-	},
-};
-
-/* ------------ TUNER_ALPS_TSBC5_PAL - Alps PAL ------------ */
-
-static struct tuner_params tuner_alps_tsbc5_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_PAL,
-		.ranges = tuner_alps_tsb_5_pal_ranges,
-		.count  = ARRAY_SIZE(tuner_alps_tsb_5_pal_ranges),
-	},
-};
-
-/* ------------ TUNER_TEMIC_4006FH5_PAL - TEMIC PAL ------------ */
-
-static struct tuner_range tuner_lg_pal_ranges[] = {
-	{ 16 * 170.00 /*MHz*/, 0x8e, 0xa0, },
-	{ 16 * 450.00 /*MHz*/, 0x8e, 0x90, },
-	{ 16 * 999.99        , 0x8e, 0x30, },
-};
-
-static struct tuner_params tuner_temic_4006fh5_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_PAL,
-		.ranges = tuner_lg_pal_ranges,
-		.count  = ARRAY_SIZE(tuner_lg_pal_ranges),
-	},
-};
-
-/* ------------ TUNER_ALPS_TSHC6_NTSC - Alps NTSC ------------ */
-
-static struct tuner_range tuner_alps_tshc6_ntsc_ranges[] = {
-	{ 16 * 137.25 /*MHz*/, 0x8e, 0x14, },
-	{ 16 * 385.25 /*MHz*/, 0x8e, 0x12, },
-	{ 16 * 999.99        , 0x8e, 0x11, },
-};
-
-static struct tuner_params tuner_alps_tshc6_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_NTSC,
-		.ranges = tuner_alps_tshc6_ntsc_ranges,
-		.count  = ARRAY_SIZE(tuner_alps_tshc6_ntsc_ranges),
-	},
-};
-
-/* ------------ TUNER_TEMIC_PAL_DK - TEMIC PAL ------------ */
-
-static struct tuner_range tuner_temic_pal_dk_ranges[] = {
-	{ 16 * 168.25 /*MHz*/, 0x8e, 0xa0, },
-	{ 16 * 456.25 /*MHz*/, 0x8e, 0x90, },
-	{ 16 * 999.99        , 0x8e, 0x30, },
-};
-
-static struct tuner_params tuner_temic_pal_dk_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_PAL,
-		.ranges = tuner_temic_pal_dk_ranges,
-		.count  = ARRAY_SIZE(tuner_temic_pal_dk_ranges),
-	},
-};
-
-/* ------------ TUNER_PHILIPS_NTSC_M - Philips NTSC ------------ */
-
-static struct tuner_range tuner_philips_ntsc_m_ranges[] = {
-	{ 16 * 160.00 /*MHz*/, 0x8e, 0xa0, },
-	{ 16 * 454.00 /*MHz*/, 0x8e, 0x90, },
-	{ 16 * 999.99        , 0x8e, 0x30, },
-};
-
-static struct tuner_params tuner_philips_ntsc_m_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_NTSC,
-		.ranges = tuner_philips_ntsc_m_ranges,
-		.count  = ARRAY_SIZE(tuner_philips_ntsc_m_ranges),
-	},
-};
-
-/* ------------ TUNER_TEMIC_4066FY5_PAL_I - TEMIC PAL_I ------------ */
-
-static struct tuner_range tuner_temic_40x6f_5_pal_ranges[] = {
-	{ 16 * 169.00 /*MHz*/, 0x8e, 0xa0, },
-	{ 16 * 454.00 /*MHz*/, 0x8e, 0x90, },
-	{ 16 * 999.99        , 0x8e, 0x30, },
-};
-
-static struct tuner_params tuner_temic_4066fy5_pal_i_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_PAL,
-		.ranges = tuner_temic_40x6f_5_pal_ranges,
-		.count  = ARRAY_SIZE(tuner_temic_40x6f_5_pal_ranges),
-	},
-};
-
-/* ------------ TUNER_TEMIC_4006FN5_MULTI_PAL - TEMIC PAL ------------ */
-
-static struct tuner_params tuner_temic_4006fn5_multi_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_PAL,
-		.ranges = tuner_temic_40x6f_5_pal_ranges,
-		.count  = ARRAY_SIZE(tuner_temic_40x6f_5_pal_ranges),
-	},
-};
-
-/* 20-29 */
-/* ------------ TUNER_TEMIC_4009FR5_PAL - TEMIC PAL ------------ */
-
-static struct tuner_range tuner_temic_4009f_5_pal_ranges[] = {
-	{ 16 * 141.00 /*MHz*/, 0x8e, 0xa0, },
-	{ 16 * 464.00 /*MHz*/, 0x8e, 0x90, },
-	{ 16 * 999.99        , 0x8e, 0x30, },
-};
-
-static struct tuner_params tuner_temic_4009f_5_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_PAL,
-		.ranges = tuner_temic_4009f_5_pal_ranges,
-		.count  = ARRAY_SIZE(tuner_temic_4009f_5_pal_ranges),
-	},
-};
-
-/* ------------ TUNER_TEMIC_4039FR5_NTSC - TEMIC NTSC ------------ */
-
-static struct tuner_range tuner_temic_4x3x_f_5_ntsc_ranges[] = {
-	{ 16 * 158.00 /*MHz*/, 0x8e, 0xa0, },
-	{ 16 * 453.00 /*MHz*/, 0x8e, 0x90, },
-	{ 16 * 999.99        , 0x8e, 0x30, },
-};
-
-static struct tuner_params tuner_temic_4039fr5_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_NTSC,
-		.ranges = tuner_temic_4x3x_f_5_ntsc_ranges,
-		.count  = ARRAY_SIZE(tuner_temic_4x3x_f_5_ntsc_ranges),
-	},
-};
-
-/* ------------ TUNER_TEMIC_4046FM5 - TEMIC PAL ------------ */
-
-static struct tuner_params tuner_temic_4046fm5_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_PAL,
-		.ranges = tuner_temic_40x6f_5_pal_ranges,
-		.count  = ARRAY_SIZE(tuner_temic_40x6f_5_pal_ranges),
-	},
-};
-
-/* ------------ TUNER_PHILIPS_PAL_DK - Philips PAL ------------ */
-
-static struct tuner_params tuner_philips_pal_dk_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_PAL,
-		.ranges = tuner_lg_pal_ranges,
-		.count  = ARRAY_SIZE(tuner_lg_pal_ranges),
-	},
-};
-
-/* ------------ TUNER_PHILIPS_FQ1216ME - Philips PAL ------------ */
-
-static struct tuner_params tuner_philips_fq1216me_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_PAL,
-		.ranges = tuner_lg_pal_ranges,
-		.count  = ARRAY_SIZE(tuner_lg_pal_ranges),
-		.has_tda9887 = 1,
-		.port1_active = 1,
-		.port2_active = 1,
-		.port2_invert_for_secam_lc = 1,
-	},
-};
-
-/* ------------ TUNER_LG_PAL_I_FM - LGINNOTEK PAL_I ------------ */
-
-static struct tuner_params tuner_lg_pal_i_fm_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_PAL,
-		.ranges = tuner_lg_pal_ranges,
-		.count  = ARRAY_SIZE(tuner_lg_pal_ranges),
-	},
-};
-
-/* ------------ TUNER_LG_PAL_I - LGINNOTEK PAL_I ------------ */
-
-static struct tuner_params tuner_lg_pal_i_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_PAL,
-		.ranges = tuner_lg_pal_ranges,
-		.count  = ARRAY_SIZE(tuner_lg_pal_ranges),
-	},
-};
-
-/* ------------ TUNER_LG_NTSC_FM - LGINNOTEK NTSC ------------ */
-
-static struct tuner_range tuner_lg_ntsc_fm_ranges[] = {
-	{ 16 * 210.00 /*MHz*/, 0x8e, 0xa0, },
-	{ 16 * 497.00 /*MHz*/, 0x8e, 0x90, },
-	{ 16 * 999.99        , 0x8e, 0x30, },
-};
-
-static struct tuner_params tuner_lg_ntsc_fm_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_NTSC,
-		.ranges = tuner_lg_ntsc_fm_ranges,
-		.count  = ARRAY_SIZE(tuner_lg_ntsc_fm_ranges),
-	},
-};
-
-/* ------------ TUNER_LG_PAL_FM - LGINNOTEK PAL ------------ */
-
-static struct tuner_params tuner_lg_pal_fm_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_PAL,
-		.ranges = tuner_lg_pal_ranges,
-		.count  = ARRAY_SIZE(tuner_lg_pal_ranges),
-	},
-};
-
-/* ------------ TUNER_LG_PAL - LGINNOTEK PAL ------------ */
-
-static struct tuner_params tuner_lg_pal_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_PAL,
-		.ranges = tuner_lg_pal_ranges,
-		.count  = ARRAY_SIZE(tuner_lg_pal_ranges),
-	},
-};
-
-/* 30-39 */
-/* ------------ TUNER_TEMIC_4009FN5_MULTI_PAL_FM - TEMIC PAL ------------ */
-
-static struct tuner_params tuner_temic_4009_fn5_multi_pal_fm_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_PAL,
-		.ranges = tuner_temic_4009f_5_pal_ranges,
-		.count  = ARRAY_SIZE(tuner_temic_4009f_5_pal_ranges),
-	},
-};
-
-/* ------------ TUNER_SHARP_2U5JF5540_NTSC - SHARP NTSC ------------ */
-
-static struct tuner_range tuner_sharp_2u5jf5540_ntsc_ranges[] = {
-	{ 16 * 137.25 /*MHz*/, 0x8e, 0x01, },
-	{ 16 * 317.25 /*MHz*/, 0x8e, 0x02, },
-	{ 16 * 999.99        , 0x8e, 0x08, },
-};
-
-static struct tuner_params tuner_sharp_2u5jf5540_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_NTSC,
-		.ranges = tuner_sharp_2u5jf5540_ntsc_ranges,
-		.count  = ARRAY_SIZE(tuner_sharp_2u5jf5540_ntsc_ranges),
-	},
-};
-
-/* ------------ TUNER_Samsung_PAL_TCPM9091PD27 - Samsung PAL ------------ */
-
-static struct tuner_range tuner_samsung_pal_tcpm9091pd27_ranges[] = {
-	{ 16 * 169 /*MHz*/, 0x8e, 0xa0, },
-	{ 16 * 464 /*MHz*/, 0x8e, 0x90, },
-	{ 16 * 999.99     , 0x8e, 0x30, },
-};
-
-static struct tuner_params tuner_samsung_pal_tcpm9091pd27_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_PAL,
-		.ranges = tuner_samsung_pal_tcpm9091pd27_ranges,
-		.count  = ARRAY_SIZE(tuner_samsung_pal_tcpm9091pd27_ranges),
-	},
-};
-
-/* ------------ TUNER_TEMIC_4106FH5 - TEMIC PAL ------------ */
-
-static struct tuner_params tuner_temic_4106fh5_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_PAL,
-		.ranges = tuner_temic_4009f_5_pal_ranges,
-		.count  = ARRAY_SIZE(tuner_temic_4009f_5_pal_ranges),
-	},
-};
-
-/* ------------ TUNER_TEMIC_4012FY5 - TEMIC PAL ------------ */
-
-static struct tuner_params tuner_temic_4012fy5_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_PAL,
-		.ranges = tuner_temic_pal_ranges,
-		.count  = ARRAY_SIZE(tuner_temic_pal_ranges),
-	},
-};
-
-/* ------------ TUNER_TEMIC_4136FY5 - TEMIC NTSC ------------ */
-
-static struct tuner_params tuner_temic_4136_fy5_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_NTSC,
-		.ranges = tuner_temic_4x3x_f_5_ntsc_ranges,
-		.count  = ARRAY_SIZE(tuner_temic_4x3x_f_5_ntsc_ranges),
-	},
-};
-
-/* ------------ TUNER_LG_PAL_NEW_TAPC - LGINNOTEK PAL ------------ */
-
-static struct tuner_range tuner_lg_new_tapc_ranges[] = {
-	{ 16 * 170.00 /*MHz*/, 0x8e, 0x01, },
-	{ 16 * 450.00 /*MHz*/, 0x8e, 0x02, },
-	{ 16 * 999.99        , 0x8e, 0x08, },
-};
-
-static struct tuner_params tuner_lg_pal_new_tapc_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_PAL,
-		.ranges = tuner_lg_new_tapc_ranges,
-		.count  = ARRAY_SIZE(tuner_lg_new_tapc_ranges),
-	},
-};
-
-/* ------------ TUNER_PHILIPS_FM1216ME_MK3 - Philips PAL ------------ */
-
-static struct tuner_range tuner_fm1216me_mk3_pal_ranges[] = {
-	{ 16 * 158.00 /*MHz*/, 0x8e, 0x01, },
-	{ 16 * 442.00 /*MHz*/, 0x8e, 0x02, },
-	{ 16 * 999.99        , 0x8e, 0x04, },
-};
-
-static struct tuner_params tuner_fm1216me_mk3_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_PAL,
-		.ranges = tuner_fm1216me_mk3_pal_ranges,
-		.count  = ARRAY_SIZE(tuner_fm1216me_mk3_pal_ranges),
-		.cb_first_if_lower_freq = 1,
-		.has_tda9887 = 1,
-		.port1_active = 1,
-		.port2_active = 1,
-		.port2_invert_for_secam_lc = 1,
-		.port1_fm_high_sensitivity = 1,
-		.default_top_mid = -2,
-		.default_top_secam_mid = -2,
-		.default_top_secam_high = -2,
-	},
-};
-
-/* ------------ TUNER_PHILIPS_FM1216MK5 - Philips PAL ------------ */
-
-static struct tuner_range tuner_fm1216mk5_pal_ranges[] = {
-	{ 16 * 158.00 /*MHz*/, 0xce, 0x01, },
-	{ 16 * 441.00 /*MHz*/, 0xce, 0x02, },
-	{ 16 * 864.00        , 0xce, 0x04, },
-};
-
-static struct tuner_params tuner_fm1216mk5_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_PAL,
-		.ranges = tuner_fm1216mk5_pal_ranges,
-		.count  = ARRAY_SIZE(tuner_fm1216mk5_pal_ranges),
-		.cb_first_if_lower_freq = 1,
-		.has_tda9887 = 1,
-		.port1_active = 1,
-		.port2_active = 1,
-		.port2_invert_for_secam_lc = 1,
-		.port1_fm_high_sensitivity = 1,
-		.default_top_mid = -2,
-		.default_top_secam_mid = -2,
-		.default_top_secam_high = -2,
-	},
-};
-
-/* ------------ TUNER_LG_NTSC_NEW_TAPC - LGINNOTEK NTSC ------------ */
-
-static struct tuner_params tuner_lg_ntsc_new_tapc_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_NTSC,
-		.ranges = tuner_lg_new_tapc_ranges,
-		.count  = ARRAY_SIZE(tuner_lg_new_tapc_ranges),
-	},
-};
-
-/* 40-49 */
-/* ------------ TUNER_HITACHI_NTSC - HITACHI NTSC ------------ */
-
-static struct tuner_params tuner_hitachi_ntsc_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_NTSC,
-		.ranges = tuner_lg_new_tapc_ranges,
-		.count  = ARRAY_SIZE(tuner_lg_new_tapc_ranges),
-	},
-};
-
-/* ------------ TUNER_PHILIPS_PAL_MK - Philips PAL ------------ */
-
-static struct tuner_range tuner_philips_pal_mk_pal_ranges[] = {
-	{ 16 * 140.25 /*MHz*/, 0x8e, 0x01, },
-	{ 16 * 463.25 /*MHz*/, 0x8e, 0xc2, },
-	{ 16 * 999.99        , 0x8e, 0xcf, },
-};
-
-static struct tuner_params tuner_philips_pal_mk_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_PAL,
-		.ranges = tuner_philips_pal_mk_pal_ranges,
-		.count  = ARRAY_SIZE(tuner_philips_pal_mk_pal_ranges),
-	},
-};
-
-/* ---- TUNER_PHILIPS_FCV1236D - Philips FCV1236D (ATSC/NTSC) ---- */
-
-static struct tuner_range tuner_philips_fcv1236d_ntsc_ranges[] = {
-	{ 16 * 157.25 /*MHz*/, 0x8e, 0xa2, },
-	{ 16 * 451.25 /*MHz*/, 0x8e, 0x92, },
-	{ 16 * 999.99        , 0x8e, 0x32, },
-};
-
-static struct tuner_range tuner_philips_fcv1236d_atsc_ranges[] = {
-	{ 16 * 159.00 /*MHz*/, 0x8e, 0xa0, },
-	{ 16 * 453.00 /*MHz*/, 0x8e, 0x90, },
-	{ 16 * 999.99        , 0x8e, 0x30, },
-};
-
-static struct tuner_params tuner_philips_fcv1236d_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_NTSC,
-		.ranges = tuner_philips_fcv1236d_ntsc_ranges,
-		.count  = ARRAY_SIZE(tuner_philips_fcv1236d_ntsc_ranges),
-	},
-	{
-		.type   = TUNER_PARAM_TYPE_DIGITAL,
-		.ranges = tuner_philips_fcv1236d_atsc_ranges,
-		.count  = ARRAY_SIZE(tuner_philips_fcv1236d_atsc_ranges),
-		.iffreq = 16 * 44.00,
-	},
-};
-
-/* ------------ TUNER_PHILIPS_FM1236_MK3 - Philips NTSC ------------ */
-
-static struct tuner_range tuner_fm1236_mk3_ntsc_ranges[] = {
-	{ 16 * 160.00 /*MHz*/, 0x8e, 0x01, },
-	{ 16 * 442.00 /*MHz*/, 0x8e, 0x02, },
-	{ 16 * 999.99        , 0x8e, 0x04, },
-};
-
-static struct tuner_params tuner_fm1236_mk3_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_NTSC,
-		.ranges = tuner_fm1236_mk3_ntsc_ranges,
-		.count  = ARRAY_SIZE(tuner_fm1236_mk3_ntsc_ranges),
-		.cb_first_if_lower_freq = 1,
-		.has_tda9887 = 1,
-		.port1_active = 1,
-		.port2_active = 1,
-		.port1_fm_high_sensitivity = 1,
-	},
-};
-
-/* ------------ TUNER_PHILIPS_4IN1 - Philips NTSC ------------ */
-
-static struct tuner_params tuner_philips_4in1_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_NTSC,
-		.ranges = tuner_fm1236_mk3_ntsc_ranges,
-		.count  = ARRAY_SIZE(tuner_fm1236_mk3_ntsc_ranges),
-	},
-};
-
-/* ------------ TUNER_MICROTUNE_4049FM5 - Microtune PAL ------------ */
-
-static struct tuner_params tuner_microtune_4049_fm5_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_PAL,
-		.ranges = tuner_temic_4009f_5_pal_ranges,
-		.count  = ARRAY_SIZE(tuner_temic_4009f_5_pal_ranges),
-		.has_tda9887 = 1,
-		.port1_invert_for_secam_lc = 1,
-		.default_pll_gating_18 = 1,
-		.fm_gain_normal=1,
-		.radio_if = 1, /* 33.3 MHz */
-	},
-};
-
-/* ------------ TUNER_PANASONIC_VP27 - Panasonic NTSC ------------ */
-
-static struct tuner_range tuner_panasonic_vp27_ntsc_ranges[] = {
-	{ 16 * 160.00 /*MHz*/, 0xce, 0x01, },
-	{ 16 * 454.00 /*MHz*/, 0xce, 0x02, },
-	{ 16 * 999.99        , 0xce, 0x08, },
-};
-
-static struct tuner_params tuner_panasonic_vp27_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_NTSC,
-		.ranges = tuner_panasonic_vp27_ntsc_ranges,
-		.count  = ARRAY_SIZE(tuner_panasonic_vp27_ntsc_ranges),
-		.has_tda9887 = 1,
-		.intercarrier_mode = 1,
-		.default_top_low = -3,
-		.default_top_mid = -3,
-		.default_top_high = -3,
-	},
-};
-
-/* ------------ TUNER_TNF_8831BGFF - Philips PAL ------------ */
-
-static struct tuner_range tuner_tnf_8831bgff_pal_ranges[] = {
-	{ 16 * 161.25 /*MHz*/, 0x8e, 0xa0, },
-	{ 16 * 463.25 /*MHz*/, 0x8e, 0x90, },
-	{ 16 * 999.99        , 0x8e, 0x30, },
-};
-
-static struct tuner_params tuner_tnf_8831bgff_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_PAL,
-		.ranges = tuner_tnf_8831bgff_pal_ranges,
-		.count  = ARRAY_SIZE(tuner_tnf_8831bgff_pal_ranges),
-	},
-};
-
-/* ------------ TUNER_MICROTUNE_4042FI5 - Microtune NTSC ------------ */
-
-static struct tuner_range tuner_microtune_4042fi5_ntsc_ranges[] = {
-	{ 16 * 162.00 /*MHz*/, 0x8e, 0xa2, },
-	{ 16 * 457.00 /*MHz*/, 0x8e, 0x94, },
-	{ 16 * 999.99        , 0x8e, 0x31, },
-};
-
-static struct tuner_range tuner_microtune_4042fi5_atsc_ranges[] = {
-	{ 16 * 162.00 /*MHz*/, 0x8e, 0xa1, },
-	{ 16 * 457.00 /*MHz*/, 0x8e, 0x91, },
-	{ 16 * 999.99        , 0x8e, 0x31, },
-};
-
-static struct tuner_params tuner_microtune_4042fi5_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_NTSC,
-		.ranges = tuner_microtune_4042fi5_ntsc_ranges,
-		.count  = ARRAY_SIZE(tuner_microtune_4042fi5_ntsc_ranges),
-	},
-	{
-		.type   = TUNER_PARAM_TYPE_DIGITAL,
-		.ranges = tuner_microtune_4042fi5_atsc_ranges,
-		.count  = ARRAY_SIZE(tuner_microtune_4042fi5_atsc_ranges),
-		.iffreq = 16 * 44.00 /*MHz*/,
-	},
-};
-
-/* 50-59 */
-/* ------------ TUNER_TCL_2002N - TCL NTSC ------------ */
-
-static struct tuner_range tuner_tcl_2002n_ntsc_ranges[] = {
-	{ 16 * 172.00 /*MHz*/, 0x8e, 0x01, },
-	{ 16 * 448.00 /*MHz*/, 0x8e, 0x02, },
-	{ 16 * 999.99        , 0x8e, 0x08, },
-};
-
-static struct tuner_params tuner_tcl_2002n_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_NTSC,
-		.ranges = tuner_tcl_2002n_ntsc_ranges,
-		.count  = ARRAY_SIZE(tuner_tcl_2002n_ntsc_ranges),
-		.cb_first_if_lower_freq = 1,
-	},
-};
-
-/* ------------ TUNER_PHILIPS_FM1256_IH3 - Philips PAL ------------ */
-
-static struct tuner_params tuner_philips_fm1256_ih3_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_PAL,
-		.ranges = tuner_fm1236_mk3_ntsc_ranges,
-		.count  = ARRAY_SIZE(tuner_fm1236_mk3_ntsc_ranges),
-		.radio_if = 1, /* 33.3 MHz */
-	},
-};
-
-/* ------------ TUNER_THOMSON_DTT7610 - THOMSON ATSC ------------ */
-
-/* single range used for both ntsc and atsc */
-static struct tuner_range tuner_thomson_dtt7610_ntsc_ranges[] = {
-	{ 16 * 157.25 /*MHz*/, 0x8e, 0x39, },
-	{ 16 * 454.00 /*MHz*/, 0x8e, 0x3a, },
-	{ 16 * 999.99        , 0x8e, 0x3c, },
-};
-
-static struct tuner_params tuner_thomson_dtt7610_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_NTSC,
-		.ranges = tuner_thomson_dtt7610_ntsc_ranges,
-		.count  = ARRAY_SIZE(tuner_thomson_dtt7610_ntsc_ranges),
-	},
-	{
-		.type   = TUNER_PARAM_TYPE_DIGITAL,
-		.ranges = tuner_thomson_dtt7610_ntsc_ranges,
-		.count  = ARRAY_SIZE(tuner_thomson_dtt7610_ntsc_ranges),
-		.iffreq = 16 * 44.00 /*MHz*/,
-	},
-};
-
-/* ------------ TUNER_PHILIPS_FQ1286 - Philips NTSC ------------ */
-
-static struct tuner_range tuner_philips_fq1286_ntsc_ranges[] = {
-	{ 16 * 160.00 /*MHz*/, 0x8e, 0x41, },
-	{ 16 * 454.00 /*MHz*/, 0x8e, 0x42, },
-	{ 16 * 999.99        , 0x8e, 0x04, },
-};
-
-static struct tuner_params tuner_philips_fq1286_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_NTSC,
-		.ranges = tuner_philips_fq1286_ntsc_ranges,
-		.count  = ARRAY_SIZE(tuner_philips_fq1286_ntsc_ranges),
-	},
-};
-
-/* ------------ TUNER_TCL_2002MB - TCL PAL ------------ */
-
-static struct tuner_range tuner_tcl_2002mb_pal_ranges[] = {
-	{ 16 * 170.00 /*MHz*/, 0xce, 0x01, },
-	{ 16 * 450.00 /*MHz*/, 0xce, 0x02, },
-	{ 16 * 999.99        , 0xce, 0x08, },
-};
-
-static struct tuner_params tuner_tcl_2002mb_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_PAL,
-		.ranges = tuner_tcl_2002mb_pal_ranges,
-		.count  = ARRAY_SIZE(tuner_tcl_2002mb_pal_ranges),
-	},
-};
-
-/* ------------ TUNER_PHILIPS_FQ1216AME_MK4 - Philips PAL ------------ */
-
-static struct tuner_range tuner_philips_fq12_6a___mk4_pal_ranges[] = {
-	{ 16 * 160.00 /*MHz*/, 0xce, 0x01, },
-	{ 16 * 442.00 /*MHz*/, 0xce, 0x02, },
-	{ 16 * 999.99        , 0xce, 0x04, },
-};
-
-static struct tuner_params tuner_philips_fq1216ame_mk4_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_PAL,
-		.ranges = tuner_philips_fq12_6a___mk4_pal_ranges,
-		.count  = ARRAY_SIZE(tuner_philips_fq12_6a___mk4_pal_ranges),
-		.has_tda9887 = 1,
-		.port1_active = 1,
-		.port2_invert_for_secam_lc = 1,
-		.default_top_mid = -2,
-		.default_top_secam_low = -2,
-		.default_top_secam_mid = -2,
-		.default_top_secam_high = -2,
-	},
-};
-
-/* ------------ TUNER_PHILIPS_FQ1236A_MK4 - Philips NTSC ------------ */
-
-static struct tuner_params tuner_philips_fq1236a_mk4_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_NTSC,
-		.ranges = tuner_fm1236_mk3_ntsc_ranges,
-		.count  = ARRAY_SIZE(tuner_fm1236_mk3_ntsc_ranges),
-	},
-};
-
-/* ------------ TUNER_YMEC_TVF_8531MF - Philips NTSC ------------ */
-
-static struct tuner_params tuner_ymec_tvf_8531mf_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_NTSC,
-		.ranges = tuner_philips_ntsc_m_ranges,
-		.count  = ARRAY_SIZE(tuner_philips_ntsc_m_ranges),
-	},
-};
-
-/* ------------ TUNER_YMEC_TVF_5533MF - Philips NTSC ------------ */
-
-static struct tuner_range tuner_ymec_tvf_5533mf_ntsc_ranges[] = {
-	{ 16 * 160.00 /*MHz*/, 0x8e, 0x01, },
-	{ 16 * 454.00 /*MHz*/, 0x8e, 0x02, },
-	{ 16 * 999.99        , 0x8e, 0x04, },
-};
-
-static struct tuner_params tuner_ymec_tvf_5533mf_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_NTSC,
-		.ranges = tuner_ymec_tvf_5533mf_ntsc_ranges,
-		.count  = ARRAY_SIZE(tuner_ymec_tvf_5533mf_ntsc_ranges),
-	},
-};
-
-/* 60-69 */
-/* ------------ TUNER_THOMSON_DTT761X - THOMSON ATSC ------------ */
-/* DTT 7611 7611A 7612 7613 7613A 7614 7615 7615A */
-
-static struct tuner_range tuner_thomson_dtt761x_ntsc_ranges[] = {
-	{ 16 * 145.25 /*MHz*/, 0x8e, 0x39, },
-	{ 16 * 415.25 /*MHz*/, 0x8e, 0x3a, },
-	{ 16 * 999.99        , 0x8e, 0x3c, },
-};
-
-static struct tuner_range tuner_thomson_dtt761x_atsc_ranges[] = {
-	{ 16 * 147.00 /*MHz*/, 0x8e, 0x39, },
-	{ 16 * 417.00 /*MHz*/, 0x8e, 0x3a, },
-	{ 16 * 999.99        , 0x8e, 0x3c, },
-};
-
-static struct tuner_params tuner_thomson_dtt761x_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_NTSC,
-		.ranges = tuner_thomson_dtt761x_ntsc_ranges,
-		.count  = ARRAY_SIZE(tuner_thomson_dtt761x_ntsc_ranges),
-		.has_tda9887 = 1,
-		.fm_gain_normal = 1,
-		.radio_if = 2, /* 41.3 MHz */
-	},
-	{
-		.type   = TUNER_PARAM_TYPE_DIGITAL,
-		.ranges = tuner_thomson_dtt761x_atsc_ranges,
-		.count  = ARRAY_SIZE(tuner_thomson_dtt761x_atsc_ranges),
-		.iffreq = 16 * 44.00, /*MHz*/
-	},
-};
-
-/* ------------ TUNER_TENA_9533_DI - Philips PAL ------------ */
-
-static struct tuner_range tuner_tena_9533_di_pal_ranges[] = {
-	{ 16 * 160.25 /*MHz*/, 0x8e, 0x01, },
-	{ 16 * 464.25 /*MHz*/, 0x8e, 0x02, },
-	{ 16 * 999.99        , 0x8e, 0x04, },
-};
-
-static struct tuner_params tuner_tena_9533_di_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_PAL,
-		.ranges = tuner_tena_9533_di_pal_ranges,
-		.count  = ARRAY_SIZE(tuner_tena_9533_di_pal_ranges),
-	},
-};
-
-/* ------------ TUNER_TENA_TNF_5337 - Tena tnf5337MFD STD M/N ------------ */
-
-static struct tuner_range tuner_tena_tnf_5337_ntsc_ranges[] = {
-	{ 16 * 166.25 /*MHz*/, 0x86, 0x01, },
-	{ 16 * 466.25 /*MHz*/, 0x86, 0x02, },
-	{ 16 * 999.99        , 0x86, 0x08, },
-};
-
-static struct tuner_params tuner_tena_tnf_5337_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_NTSC,
-		.ranges = tuner_tena_tnf_5337_ntsc_ranges,
-		.count  = ARRAY_SIZE(tuner_tena_tnf_5337_ntsc_ranges),
-	},
-};
-
-/* ------------ TUNER_PHILIPS_FMD1216ME(X)_MK3 - Philips PAL ------------ */
-
-static struct tuner_range tuner_philips_fmd1216me_mk3_pal_ranges[] = {
-	{ 16 * 160.00 /*MHz*/, 0x86, 0x51, },
-	{ 16 * 442.00 /*MHz*/, 0x86, 0x52, },
-	{ 16 * 999.99        , 0x86, 0x54, },
-};
-
-static struct tuner_range tuner_philips_fmd1216me_mk3_dvb_ranges[] = {
-	{ 16 * 143.87 /*MHz*/, 0xbc, 0x41 },
-	{ 16 * 158.87 /*MHz*/, 0xf4, 0x41 },
-	{ 16 * 329.87 /*MHz*/, 0xbc, 0x42 },
-	{ 16 * 441.87 /*MHz*/, 0xf4, 0x42 },
-	{ 16 * 625.87 /*MHz*/, 0xbc, 0x44 },
-	{ 16 * 803.87 /*MHz*/, 0xf4, 0x44 },
-	{ 16 * 999.99        , 0xfc, 0x44 },
-};
-
-static struct tuner_params tuner_philips_fmd1216me_mk3_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_PAL,
-		.ranges = tuner_philips_fmd1216me_mk3_pal_ranges,
-		.count  = ARRAY_SIZE(tuner_philips_fmd1216me_mk3_pal_ranges),
-		.has_tda9887 = 1,
-		.port1_active = 1,
-		.port2_active = 1,
-		.port2_fm_high_sensitivity = 1,
-		.port2_invert_for_secam_lc = 1,
-		.port1_set_for_fm_mono = 1,
-	},
-	{
-		.type   = TUNER_PARAM_TYPE_DIGITAL,
-		.ranges = tuner_philips_fmd1216me_mk3_dvb_ranges,
-		.count  = ARRAY_SIZE(tuner_philips_fmd1216me_mk3_dvb_ranges),
-		.iffreq = 16 * 36.125, /*MHz*/
-	},
-};
-
-static struct tuner_params tuner_philips_fmd1216mex_mk3_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_PAL,
-		.ranges = tuner_philips_fmd1216me_mk3_pal_ranges,
-		.count  = ARRAY_SIZE(tuner_philips_fmd1216me_mk3_pal_ranges),
-		.has_tda9887 = 1,
-		.port1_active = 1,
-		.port2_active = 1,
-		.port2_fm_high_sensitivity = 1,
-		.port2_invert_for_secam_lc = 1,
-		.port1_set_for_fm_mono = 1,
-		.radio_if = 1,
-		.fm_gain_normal = 1,
-	},
-	{
-		.type   = TUNER_PARAM_TYPE_DIGITAL,
-		.ranges = tuner_philips_fmd1216me_mk3_dvb_ranges,
-		.count  = ARRAY_SIZE(tuner_philips_fmd1216me_mk3_dvb_ranges),
-		.iffreq = 16 * 36.125, /*MHz*/
-	},
-};
-
-/* ------ TUNER_LG_TDVS_H06XF - LG INNOTEK / INFINEON ATSC ----- */
-
-static struct tuner_range tuner_tua6034_ntsc_ranges[] = {
-	{ 16 * 165.00 /*MHz*/, 0x8e, 0x01 },
-	{ 16 * 450.00 /*MHz*/, 0x8e, 0x02 },
-	{ 16 * 999.99        , 0x8e, 0x04 },
-};
-
-static struct tuner_range tuner_tua6034_atsc_ranges[] = {
-	{ 16 * 165.00 /*MHz*/, 0xce, 0x01 },
-	{ 16 * 450.00 /*MHz*/, 0xce, 0x02 },
-	{ 16 * 999.99        , 0xce, 0x04 },
-};
-
-static struct tuner_params tuner_lg_tdvs_h06xf_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_NTSC,
-		.ranges = tuner_tua6034_ntsc_ranges,
-		.count  = ARRAY_SIZE(tuner_tua6034_ntsc_ranges),
-	},
-	{
-		.type   = TUNER_PARAM_TYPE_DIGITAL,
-		.ranges = tuner_tua6034_atsc_ranges,
-		.count  = ARRAY_SIZE(tuner_tua6034_atsc_ranges),
-		.iffreq = 16 * 44.00,
-	},
-};
-
-/* ------------ TUNER_YMEC_TVF66T5_B_DFF - Philips PAL ------------ */
-
-static struct tuner_range tuner_ymec_tvf66t5_b_dff_pal_ranges[] = {
-	{ 16 * 160.25 /*MHz*/, 0x8e, 0x01, },
-	{ 16 * 464.25 /*MHz*/, 0x8e, 0x02, },
-	{ 16 * 999.99        , 0x8e, 0x08, },
-};
-
-static struct tuner_params tuner_ymec_tvf66t5_b_dff_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_PAL,
-		.ranges = tuner_ymec_tvf66t5_b_dff_pal_ranges,
-		.count  = ARRAY_SIZE(tuner_ymec_tvf66t5_b_dff_pal_ranges),
-	},
-};
-
-/* ------------ TUNER_LG_NTSC_TALN_MINI - LGINNOTEK NTSC ------------ */
-
-static struct tuner_range tuner_lg_taln_ntsc_ranges[] = {
-	{ 16 * 137.25 /*MHz*/, 0x8e, 0x01, },
-	{ 16 * 373.25 /*MHz*/, 0x8e, 0x02, },
-	{ 16 * 999.99        , 0x8e, 0x08, },
-};
-
-static struct tuner_range tuner_lg_taln_pal_secam_ranges[] = {
-	{ 16 * 150.00 /*MHz*/, 0x8e, 0x01, },
-	{ 16 * 425.00 /*MHz*/, 0x8e, 0x02, },
-	{ 16 * 999.99        , 0x8e, 0x08, },
-};
-
-static struct tuner_params tuner_lg_taln_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_NTSC,
-		.ranges = tuner_lg_taln_ntsc_ranges,
-		.count  = ARRAY_SIZE(tuner_lg_taln_ntsc_ranges),
-	},{
-		.type   = TUNER_PARAM_TYPE_PAL,
-		.ranges = tuner_lg_taln_pal_secam_ranges,
-		.count  = ARRAY_SIZE(tuner_lg_taln_pal_secam_ranges),
-	},
-};
-
-/* ------------ TUNER_PHILIPS_TD1316 - Philips PAL ------------ */
-
-static struct tuner_range tuner_philips_td1316_pal_ranges[] = {
-	{ 16 * 160.00 /*MHz*/, 0xc8, 0xa1, },
-	{ 16 * 442.00 /*MHz*/, 0xc8, 0xa2, },
-	{ 16 * 999.99        , 0xc8, 0xa4, },
-};
-
-static struct tuner_range tuner_philips_td1316_dvb_ranges[] = {
-	{ 16 *  93.834 /*MHz*/, 0xca, 0x60, },
-	{ 16 * 123.834 /*MHz*/, 0xca, 0xa0, },
-	{ 16 * 163.834 /*MHz*/, 0xca, 0xc0, },
-	{ 16 * 253.834 /*MHz*/, 0xca, 0x60, },
-	{ 16 * 383.834 /*MHz*/, 0xca, 0xa0, },
-	{ 16 * 443.834 /*MHz*/, 0xca, 0xc0, },
-	{ 16 * 583.834 /*MHz*/, 0xca, 0x60, },
-	{ 16 * 793.834 /*MHz*/, 0xca, 0xa0, },
-	{ 16 * 999.999        , 0xca, 0xe0, },
-};
-
-static struct tuner_params tuner_philips_td1316_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_PAL,
-		.ranges = tuner_philips_td1316_pal_ranges,
-		.count  = ARRAY_SIZE(tuner_philips_td1316_pal_ranges),
-	},
-	{
-		.type   = TUNER_PARAM_TYPE_DIGITAL,
-		.ranges = tuner_philips_td1316_dvb_ranges,
-		.count  = ARRAY_SIZE(tuner_philips_td1316_dvb_ranges),
-		.iffreq = 16 * 36.166667 /*MHz*/,
-	},
-};
-
-/* ------------ TUNER_PHILIPS_TUV1236D - Philips ATSC ------------ */
-
-static struct tuner_range tuner_tuv1236d_ntsc_ranges[] = {
-	{ 16 * 157.25 /*MHz*/, 0xce, 0x01, },
-	{ 16 * 454.00 /*MHz*/, 0xce, 0x02, },
-	{ 16 * 999.99        , 0xce, 0x04, },
-};
-
-static struct tuner_range tuner_tuv1236d_atsc_ranges[] = {
-	{ 16 * 157.25 /*MHz*/, 0xc6, 0x41, },
-	{ 16 * 454.00 /*MHz*/, 0xc6, 0x42, },
-	{ 16 * 999.99        , 0xc6, 0x44, },
-};
-
-static struct tuner_params tuner_tuv1236d_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_NTSC,
-		.ranges = tuner_tuv1236d_ntsc_ranges,
-		.count  = ARRAY_SIZE(tuner_tuv1236d_ntsc_ranges),
-	},
-	{
-		.type   = TUNER_PARAM_TYPE_DIGITAL,
-		.ranges = tuner_tuv1236d_atsc_ranges,
-		.count  = ARRAY_SIZE(tuner_tuv1236d_atsc_ranges),
-		.iffreq = 16 * 44.00,
-	},
-};
-
-/* ------------ TUNER_TNF_xxx5  - Texas Instruments--------- */
-/* This is known to work with Tenna TVF58t5-MFF and TVF5835 MFF
- *	but it is expected to work also with other Tenna/Ymec
- *	models based on TI SN 761677 chip on both PAL and NTSC
- */
-
-static struct tuner_range tuner_tnf_5335_d_if_pal_ranges[] = {
-	{ 16 * 168.25 /*MHz*/, 0x8e, 0x01, },
-	{ 16 * 471.25 /*MHz*/, 0x8e, 0x02, },
-	{ 16 * 999.99        , 0x8e, 0x08, },
-};
-
-static struct tuner_range tuner_tnf_5335mf_ntsc_ranges[] = {
-	{ 16 * 169.25 /*MHz*/, 0x8e, 0x01, },
-	{ 16 * 469.25 /*MHz*/, 0x8e, 0x02, },
-	{ 16 * 999.99        , 0x8e, 0x08, },
-};
-
-static struct tuner_params tuner_tnf_5335mf_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_NTSC,
-		.ranges = tuner_tnf_5335mf_ntsc_ranges,
-		.count  = ARRAY_SIZE(tuner_tnf_5335mf_ntsc_ranges),
-	},
-	{
-		.type   = TUNER_PARAM_TYPE_PAL,
-		.ranges = tuner_tnf_5335_d_if_pal_ranges,
-		.count  = ARRAY_SIZE(tuner_tnf_5335_d_if_pal_ranges),
-	},
-};
-
-/* 70-79 */
-/* ------------ TUNER_SAMSUNG_TCPN_2121P30A - Samsung NTSC ------------ */
-
-/* '+ 4' turns on the Low Noise Amplifier */
-static struct tuner_range tuner_samsung_tcpn_2121p30a_ntsc_ranges[] = {
-	{ 16 * 130.00 /*MHz*/, 0xce, 0x01 + 4, },
-	{ 16 * 364.50 /*MHz*/, 0xce, 0x02 + 4, },
-	{ 16 * 999.99        , 0xce, 0x08 + 4, },
-};
-
-static struct tuner_params tuner_samsung_tcpn_2121p30a_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_NTSC,
-		.ranges = tuner_samsung_tcpn_2121p30a_ntsc_ranges,
-		.count  = ARRAY_SIZE(tuner_samsung_tcpn_2121p30a_ntsc_ranges),
-	},
-};
-
-/* ------------ TUNER_THOMSON_FE6600 - DViCO Hybrid PAL ------------ */
-
-static struct tuner_range tuner_thomson_fe6600_pal_ranges[] = {
-	{ 16 * 160.00 /*MHz*/, 0xfe, 0x11, },
-	{ 16 * 442.00 /*MHz*/, 0xf6, 0x12, },
-	{ 16 * 999.99        , 0xf6, 0x18, },
-};
-
-static struct tuner_range tuner_thomson_fe6600_dvb_ranges[] = {
-	{ 16 * 250.00 /*MHz*/, 0xb4, 0x12, },
-	{ 16 * 455.00 /*MHz*/, 0xfe, 0x11, },
-	{ 16 * 775.50 /*MHz*/, 0xbc, 0x18, },
-	{ 16 * 999.99        , 0xf4, 0x18, },
-};
-
-static struct tuner_params tuner_thomson_fe6600_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_PAL,
-		.ranges = tuner_thomson_fe6600_pal_ranges,
-		.count  = ARRAY_SIZE(tuner_thomson_fe6600_pal_ranges),
-	},
-	{
-		.type   = TUNER_PARAM_TYPE_DIGITAL,
-		.ranges = tuner_thomson_fe6600_dvb_ranges,
-		.count  = ARRAY_SIZE(tuner_thomson_fe6600_dvb_ranges),
-		.iffreq = 16 * 36.125 /*MHz*/,
-	},
-};
-
-/* ------------ TUNER_SAMSUNG_TCPG_6121P30A - Samsung PAL ------------ */
-
-/* '+ 4' turns on the Low Noise Amplifier */
-static struct tuner_range tuner_samsung_tcpg_6121p30a_pal_ranges[] = {
-	{ 16 * 146.25 /*MHz*/, 0xce, 0x01 + 4, },
-	{ 16 * 428.50 /*MHz*/, 0xce, 0x02 + 4, },
-	{ 16 * 999.99        , 0xce, 0x08 + 4, },
-};
-
-static struct tuner_params tuner_samsung_tcpg_6121p30a_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_PAL,
-		.ranges = tuner_samsung_tcpg_6121p30a_pal_ranges,
-		.count  = ARRAY_SIZE(tuner_samsung_tcpg_6121p30a_pal_ranges),
-		.has_tda9887 = 1,
-		.port1_active = 1,
-		.port2_active = 1,
-		.port2_invert_for_secam_lc = 1,
-	},
-};
-
-/* ------------ TUNER_TCL_MF02GIP-5N-E - TCL MF02GIP-5N ------------ */
-
-static struct tuner_range tuner_tcl_mf02gip_5n_ntsc_ranges[] = {
-	{ 16 * 172.00 /*MHz*/, 0x8e, 0x01, },
-	{ 16 * 448.00 /*MHz*/, 0x8e, 0x02, },
-	{ 16 * 999.99        , 0x8e, 0x04, },
-};
-
-static struct tuner_params tuner_tcl_mf02gip_5n_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_NTSC,
-		.ranges = tuner_tcl_mf02gip_5n_ntsc_ranges,
-		.count  = ARRAY_SIZE(tuner_tcl_mf02gip_5n_ntsc_ranges),
-		.cb_first_if_lower_freq = 1,
-	},
-};
-
-/* 80-89 */
-/* --------- TUNER_PHILIPS_FQ1216LME_MK3 -- active loopthrough, no FM ------- */
-
-static struct tuner_params tuner_fq1216lme_mk3_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_PAL,
-		.ranges = tuner_fm1216me_mk3_pal_ranges,
-		.count  = ARRAY_SIZE(tuner_fm1216me_mk3_pal_ranges),
-		.cb_first_if_lower_freq = 1, /* not specified, but safe to do */
-		.has_tda9887 = 1, /* TDA9886 */
-		.port1_active = 1,
-		.port2_active = 1,
-		.port2_invert_for_secam_lc = 1,
-		.default_top_low = 4,
-		.default_top_mid = 4,
-		.default_top_high = 4,
-		.default_top_secam_low = 4,
-		.default_top_secam_mid = 4,
-		.default_top_secam_high = 4,
-	},
-};
-
-/* ----- TUNER_PARTSNIC_PTI_5NF05 - Partsnic (Daewoo) PTI-5NF05 NTSC ----- */
-
-static struct tuner_range tuner_partsnic_pti_5nf05_ranges[] = {
-	/* The datasheet specified channel ranges and the bandswitch byte */
-	/* The control byte value of 0x8e is just a guess */
-	{ 16 * 133.25 /*MHz*/, 0x8e, 0x01, }, /* Channels    2 -    B */
-	{ 16 * 367.25 /*MHz*/, 0x8e, 0x02, }, /* Channels    C - W+11 */
-	{ 16 * 999.99        , 0x8e, 0x08, }, /* Channels W+12 -   69 */
-};
-
-static struct tuner_params tuner_partsnic_pti_5nf05_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_NTSC,
-		.ranges = tuner_partsnic_pti_5nf05_ranges,
-		.count  = ARRAY_SIZE(tuner_partsnic_pti_5nf05_ranges),
-		.cb_first_if_lower_freq = 1, /* not specified but safe to do */
-	},
-};
-
-/* --------- TUNER_PHILIPS_CU1216L - DVB-C NIM ------------------------- */
-
-static struct tuner_range tuner_cu1216l_ranges[] = {
-	{ 16 * 160.25 /*MHz*/, 0xce, 0x01 },
-	{ 16 * 444.25 /*MHz*/, 0xce, 0x02 },
-	{ 16 * 999.99        , 0xce, 0x04 },
-};
-
-static struct tuner_params tuner_philips_cu1216l_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_DIGITAL,
-		.ranges = tuner_cu1216l_ranges,
-		.count  = ARRAY_SIZE(tuner_cu1216l_ranges),
-		.iffreq = 16 * 36.125, /*MHz*/
-	},
-};
-
-/* ---------------------- TUNER_SONY_BTF_PXN01Z ------------------------ */
-
-static struct tuner_range tuner_sony_btf_pxn01z_ranges[] = {
-	{ 16 * 137.25 /*MHz*/, 0x8e, 0x01, },
-	{ 16 * 367.25 /*MHz*/, 0x8e, 0x02, },
-	{ 16 * 999.99        , 0x8e, 0x04, },
-};
-
-static struct tuner_params tuner_sony_btf_pxn01z_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_NTSC,
-		.ranges = tuner_sony_btf_pxn01z_ranges,
-		.count  = ARRAY_SIZE(tuner_sony_btf_pxn01z_ranges),
-	},
-};
-
-/* ------------ TUNER_PHILIPS_FQ1236_MK5 - Philips NTSC ------------ */
-
-static struct tuner_params tuner_philips_fq1236_mk5_params[] = {
-	{
-		.type   = TUNER_PARAM_TYPE_NTSC,
-		.ranges = tuner_fm1236_mk3_ntsc_ranges,
-		.count  = ARRAY_SIZE(tuner_fm1236_mk3_ntsc_ranges),
-		.has_tda9887 = 1, /* TDA9885, no FM radio */
-	},
-};
-
-/* --------------------------------------------------------------------- */
-
-struct tunertype tuners[] = {
-	/* 0-9 */
-	[TUNER_TEMIC_PAL] = { /* TEMIC PAL */
-		.name   = "Temic PAL (4002 FH5)",
-		.params = tuner_temic_pal_params,
-		.count  = ARRAY_SIZE(tuner_temic_pal_params),
-	},
-	[TUNER_PHILIPS_PAL_I] = { /* Philips PAL_I */
-		.name   = "Philips PAL_I (FI1246 and compatibles)",
-		.params = tuner_philips_pal_i_params,
-		.count  = ARRAY_SIZE(tuner_philips_pal_i_params),
-	},
-	[TUNER_PHILIPS_NTSC] = { /* Philips NTSC */
-		.name   = "Philips NTSC (FI1236,FM1236 and compatibles)",
-		.params = tuner_philips_ntsc_params,
-		.count  = ARRAY_SIZE(tuner_philips_ntsc_params),
-	},
-	[TUNER_PHILIPS_SECAM] = { /* Philips SECAM */
-		.name   = "Philips (SECAM+PAL_BG) (FI1216MF, FM1216MF, FR1216MF)",
-		.params = tuner_philips_secam_params,
-		.count  = ARRAY_SIZE(tuner_philips_secam_params),
-	},
-	[TUNER_ABSENT] = { /* Tuner Absent */
-		.name   = "NoTuner",
-	},
-	[TUNER_PHILIPS_PAL] = { /* Philips PAL */
-		.name   = "Philips PAL_BG (FI1216 and compatibles)",
-		.params = tuner_philips_pal_params,
-		.count  = ARRAY_SIZE(tuner_philips_pal_params),
-	},
-	[TUNER_TEMIC_NTSC] = { /* TEMIC NTSC */
-		.name   = "Temic NTSC (4032 FY5)",
-		.params = tuner_temic_ntsc_params,
-		.count  = ARRAY_SIZE(tuner_temic_ntsc_params),
-	},
-	[TUNER_TEMIC_PAL_I] = { /* TEMIC PAL_I */
-		.name   = "Temic PAL_I (4062 FY5)",
-		.params = tuner_temic_pal_i_params,
-		.count  = ARRAY_SIZE(tuner_temic_pal_i_params),
-	},
-	[TUNER_TEMIC_4036FY5_NTSC] = { /* TEMIC NTSC */
-		.name   = "Temic NTSC (4036 FY5)",
-		.params = tuner_temic_4036fy5_ntsc_params,
-		.count  = ARRAY_SIZE(tuner_temic_4036fy5_ntsc_params),
-	},
-	[TUNER_ALPS_TSBH1_NTSC] = { /* TEMIC NTSC */
-		.name   = "Alps HSBH1",
-		.params = tuner_alps_tsbh1_ntsc_params,
-		.count  = ARRAY_SIZE(tuner_alps_tsbh1_ntsc_params),
-	},
-
-	/* 10-19 */
-	[TUNER_ALPS_TSBE1_PAL] = { /* TEMIC PAL */
-		.name   = "Alps TSBE1",
-		.params = tuner_alps_tsb_1_params,
-		.count  = ARRAY_SIZE(tuner_alps_tsb_1_params),
-	},
-	[TUNER_ALPS_TSBB5_PAL_I] = { /* Alps PAL_I */
-		.name   = "Alps TSBB5",
-		.params = tuner_alps_tsbb5_params,
-		.count  = ARRAY_SIZE(tuner_alps_tsbb5_params),
-	},
-	[TUNER_ALPS_TSBE5_PAL] = { /* Alps PAL */
-		.name   = "Alps TSBE5",
-		.params = tuner_alps_tsbe5_params,
-		.count  = ARRAY_SIZE(tuner_alps_tsbe5_params),
-	},
-	[TUNER_ALPS_TSBC5_PAL] = { /* Alps PAL */
-		.name   = "Alps TSBC5",
-		.params = tuner_alps_tsbc5_params,
-		.count  = ARRAY_SIZE(tuner_alps_tsbc5_params),
-	},
-	[TUNER_TEMIC_4006FH5_PAL] = { /* TEMIC PAL */
-		.name   = "Temic PAL_BG (4006FH5)",
-		.params = tuner_temic_4006fh5_params,
-		.count  = ARRAY_SIZE(tuner_temic_4006fh5_params),
-	},
-	[TUNER_ALPS_TSHC6_NTSC] = { /* Alps NTSC */
-		.name   = "Alps TSCH6",
-		.params = tuner_alps_tshc6_params,
-		.count  = ARRAY_SIZE(tuner_alps_tshc6_params),
-	},
-	[TUNER_TEMIC_PAL_DK] = { /* TEMIC PAL */
-		.name   = "Temic PAL_DK (4016 FY5)",
-		.params = tuner_temic_pal_dk_params,
-		.count  = ARRAY_SIZE(tuner_temic_pal_dk_params),
-	},
-	[TUNER_PHILIPS_NTSC_M] = { /* Philips NTSC */
-		.name   = "Philips NTSC_M (MK2)",
-		.params = tuner_philips_ntsc_m_params,
-		.count  = ARRAY_SIZE(tuner_philips_ntsc_m_params),
-	},
-	[TUNER_TEMIC_4066FY5_PAL_I] = { /* TEMIC PAL_I */
-		.name   = "Temic PAL_I (4066 FY5)",
-		.params = tuner_temic_4066fy5_pal_i_params,
-		.count  = ARRAY_SIZE(tuner_temic_4066fy5_pal_i_params),
-	},
-	[TUNER_TEMIC_4006FN5_MULTI_PAL] = { /* TEMIC PAL */
-		.name   = "Temic PAL* auto (4006 FN5)",
-		.params = tuner_temic_4006fn5_multi_params,
-		.count  = ARRAY_SIZE(tuner_temic_4006fn5_multi_params),
-	},
-
-	/* 20-29 */
-	[TUNER_TEMIC_4009FR5_PAL] = { /* TEMIC PAL */
-		.name   = "Temic PAL_BG (4009 FR5) or PAL_I (4069 FR5)",
-		.params = tuner_temic_4009f_5_params,
-		.count  = ARRAY_SIZE(tuner_temic_4009f_5_params),
-	},
-	[TUNER_TEMIC_4039FR5_NTSC] = { /* TEMIC NTSC */
-		.name   = "Temic NTSC (4039 FR5)",
-		.params = tuner_temic_4039fr5_params,
-		.count  = ARRAY_SIZE(tuner_temic_4039fr5_params),
-	},
-	[TUNER_TEMIC_4046FM5] = { /* TEMIC PAL */
-		.name   = "Temic PAL/SECAM multi (4046 FM5)",
-		.params = tuner_temic_4046fm5_params,
-		.count  = ARRAY_SIZE(tuner_temic_4046fm5_params),
-	},
-	[TUNER_PHILIPS_PAL_DK] = { /* Philips PAL */
-		.name   = "Philips PAL_DK (FI1256 and compatibles)",
-		.params = tuner_philips_pal_dk_params,
-		.count  = ARRAY_SIZE(tuner_philips_pal_dk_params),
-	},
-	[TUNER_PHILIPS_FQ1216ME] = { /* Philips PAL */
-		.name   = "Philips PAL/SECAM multi (FQ1216ME)",
-		.params = tuner_philips_fq1216me_params,
-		.count  = ARRAY_SIZE(tuner_philips_fq1216me_params),
-	},
-	[TUNER_LG_PAL_I_FM] = { /* LGINNOTEK PAL_I */
-		.name   = "LG PAL_I+FM (TAPC-I001D)",
-		.params = tuner_lg_pal_i_fm_params,
-		.count  = ARRAY_SIZE(tuner_lg_pal_i_fm_params),
-	},
-	[TUNER_LG_PAL_I] = { /* LGINNOTEK PAL_I */
-		.name   = "LG PAL_I (TAPC-I701D)",
-		.params = tuner_lg_pal_i_params,
-		.count  = ARRAY_SIZE(tuner_lg_pal_i_params),
-	},
-	[TUNER_LG_NTSC_FM] = { /* LGINNOTEK NTSC */
-		.name   = "LG NTSC+FM (TPI8NSR01F)",
-		.params = tuner_lg_ntsc_fm_params,
-		.count  = ARRAY_SIZE(tuner_lg_ntsc_fm_params),
-	},
-	[TUNER_LG_PAL_FM] = { /* LGINNOTEK PAL */
-		.name   = "LG PAL_BG+FM (TPI8PSB01D)",
-		.params = tuner_lg_pal_fm_params,
-		.count  = ARRAY_SIZE(tuner_lg_pal_fm_params),
-	},
-	[TUNER_LG_PAL] = { /* LGINNOTEK PAL */
-		.name   = "LG PAL_BG (TPI8PSB11D)",
-		.params = tuner_lg_pal_params,
-		.count  = ARRAY_SIZE(tuner_lg_pal_params),
-	},
-
-	/* 30-39 */
-	[TUNER_TEMIC_4009FN5_MULTI_PAL_FM] = { /* TEMIC PAL */
-		.name   = "Temic PAL* auto + FM (4009 FN5)",
-		.params = tuner_temic_4009_fn5_multi_pal_fm_params,
-		.count  = ARRAY_SIZE(tuner_temic_4009_fn5_multi_pal_fm_params),
-	},
-	[TUNER_SHARP_2U5JF5540_NTSC] = { /* SHARP NTSC */
-		.name   = "SHARP NTSC_JP (2U5JF5540)",
-		.params = tuner_sharp_2u5jf5540_params,
-		.count  = ARRAY_SIZE(tuner_sharp_2u5jf5540_params),
-	},
-	[TUNER_Samsung_PAL_TCPM9091PD27] = { /* Samsung PAL */
-		.name   = "Samsung PAL TCPM9091PD27",
-		.params = tuner_samsung_pal_tcpm9091pd27_params,
-		.count  = ARRAY_SIZE(tuner_samsung_pal_tcpm9091pd27_params),
-	},
-	[TUNER_MT2032] = { /* Microtune PAL|NTSC */
-		.name   = "MT20xx universal",
-		/* see mt20xx.c for details */ },
-	[TUNER_TEMIC_4106FH5] = { /* TEMIC PAL */
-		.name   = "Temic PAL_BG (4106 FH5)",
-		.params = tuner_temic_4106fh5_params,
-		.count  = ARRAY_SIZE(tuner_temic_4106fh5_params),
-	},
-	[TUNER_TEMIC_4012FY5] = { /* TEMIC PAL */
-		.name   = "Temic PAL_DK/SECAM_L (4012 FY5)",
-		.params = tuner_temic_4012fy5_params,
-		.count  = ARRAY_SIZE(tuner_temic_4012fy5_params),
-	},
-	[TUNER_TEMIC_4136FY5] = { /* TEMIC NTSC */
-		.name   = "Temic NTSC (4136 FY5)",
-		.params = tuner_temic_4136_fy5_params,
-		.count  = ARRAY_SIZE(tuner_temic_4136_fy5_params),
-	},
-	[TUNER_LG_PAL_NEW_TAPC] = { /* LGINNOTEK PAL */
-		.name   = "LG PAL (newer TAPC series)",
-		.params = tuner_lg_pal_new_tapc_params,
-		.count  = ARRAY_SIZE(tuner_lg_pal_new_tapc_params),
-	},
-	[TUNER_PHILIPS_FM1216ME_MK3] = { /* Philips PAL */
-		.name   = "Philips PAL/SECAM multi (FM1216ME MK3)",
-		.params = tuner_fm1216me_mk3_params,
-		.count  = ARRAY_SIZE(tuner_fm1216me_mk3_params),
-	},
-	[TUNER_LG_NTSC_NEW_TAPC] = { /* LGINNOTEK NTSC */
-		.name   = "LG NTSC (newer TAPC series)",
-		.params = tuner_lg_ntsc_new_tapc_params,
-		.count  = ARRAY_SIZE(tuner_lg_ntsc_new_tapc_params),
-	},
-
-	/* 40-49 */
-	[TUNER_HITACHI_NTSC] = { /* HITACHI NTSC */
-		.name   = "HITACHI V7-J180AT",
-		.params = tuner_hitachi_ntsc_params,
-		.count  = ARRAY_SIZE(tuner_hitachi_ntsc_params),
-	},
-	[TUNER_PHILIPS_PAL_MK] = { /* Philips PAL */
-		.name   = "Philips PAL_MK (FI1216 MK)",
-		.params = tuner_philips_pal_mk_params,
-		.count  = ARRAY_SIZE(tuner_philips_pal_mk_params),
-	},
-	[TUNER_PHILIPS_FCV1236D] = { /* Philips ATSC */
-		.name   = "Philips FCV1236D ATSC/NTSC dual in",
-		.params = tuner_philips_fcv1236d_params,
-		.count  = ARRAY_SIZE(tuner_philips_fcv1236d_params),
-		.min = 16 *  53.00,
-		.max = 16 * 803.00,
-		.stepsize = 62500,
-	},
-	[TUNER_PHILIPS_FM1236_MK3] = { /* Philips NTSC */
-		.name   = "Philips NTSC MK3 (FM1236MK3 or FM1236/F)",
-		.params = tuner_fm1236_mk3_params,
-		.count  = ARRAY_SIZE(tuner_fm1236_mk3_params),
-	},
-	[TUNER_PHILIPS_4IN1] = { /* Philips NTSC */
-		.name   = "Philips 4 in 1 (ATI TV Wonder Pro/Conexant)",
-		.params = tuner_philips_4in1_params,
-		.count  = ARRAY_SIZE(tuner_philips_4in1_params),
-	},
-	[TUNER_MICROTUNE_4049FM5] = { /* Microtune PAL */
-		.name   = "Microtune 4049 FM5",
-		.params = tuner_microtune_4049_fm5_params,
-		.count  = ARRAY_SIZE(tuner_microtune_4049_fm5_params),
-	},
-	[TUNER_PANASONIC_VP27] = { /* Panasonic NTSC */
-		.name   = "Panasonic VP27s/ENGE4324D",
-		.params = tuner_panasonic_vp27_params,
-		.count  = ARRAY_SIZE(tuner_panasonic_vp27_params),
-	},
-	[TUNER_LG_NTSC_TAPE] = { /* LGINNOTEK NTSC */
-		.name   = "LG NTSC (TAPE series)",
-		.params = tuner_fm1236_mk3_params,
-		.count  = ARRAY_SIZE(tuner_fm1236_mk3_params),
-	},
-	[TUNER_TNF_8831BGFF] = { /* Philips PAL */
-		.name   = "Tenna TNF 8831 BGFF)",
-		.params = tuner_tnf_8831bgff_params,
-		.count  = ARRAY_SIZE(tuner_tnf_8831bgff_params),
-	},
-	[TUNER_MICROTUNE_4042FI5] = { /* Microtune NTSC */
-		.name   = "Microtune 4042 FI5 ATSC/NTSC dual in",
-		.params = tuner_microtune_4042fi5_params,
-		.count  = ARRAY_SIZE(tuner_microtune_4042fi5_params),
-		.min    = 16 *  57.00,
-		.max    = 16 * 858.00,
-		.stepsize = 62500,
-	},
-
-	/* 50-59 */
-	[TUNER_TCL_2002N] = { /* TCL NTSC */
-		.name   = "TCL 2002N",
-		.params = tuner_tcl_2002n_params,
-		.count  = ARRAY_SIZE(tuner_tcl_2002n_params),
-	},
-	[TUNER_PHILIPS_FM1256_IH3] = { /* Philips PAL */
-		.name   = "Philips PAL/SECAM_D (FM 1256 I-H3)",
-		.params = tuner_philips_fm1256_ih3_params,
-		.count  = ARRAY_SIZE(tuner_philips_fm1256_ih3_params),
-	},
-	[TUNER_THOMSON_DTT7610] = { /* THOMSON ATSC */
-		.name   = "Thomson DTT 7610 (ATSC/NTSC)",
-		.params = tuner_thomson_dtt7610_params,
-		.count  = ARRAY_SIZE(tuner_thomson_dtt7610_params),
-		.min    = 16 *  44.00,
-		.max    = 16 * 958.00,
-		.stepsize = 62500,
-	},
-	[TUNER_PHILIPS_FQ1286] = { /* Philips NTSC */
-		.name   = "Philips FQ1286",
-		.params = tuner_philips_fq1286_params,
-		.count  = ARRAY_SIZE(tuner_philips_fq1286_params),
-	},
-	[TUNER_PHILIPS_TDA8290] = { /* Philips PAL|NTSC */
-		.name   = "Philips/NXP TDA 8290/8295 + 8275/8275A/18271",
-		/* see tda8290.c for details */ },
-	[TUNER_TCL_2002MB] = { /* TCL PAL */
-		.name   = "TCL 2002MB",
-		.params = tuner_tcl_2002mb_params,
-		.count  = ARRAY_SIZE(tuner_tcl_2002mb_params),
-	},
-	[TUNER_PHILIPS_FQ1216AME_MK4] = { /* Philips PAL */
-		.name   = "Philips PAL/SECAM multi (FQ1216AME MK4)",
-		.params = tuner_philips_fq1216ame_mk4_params,
-		.count  = ARRAY_SIZE(tuner_philips_fq1216ame_mk4_params),
-	},
-	[TUNER_PHILIPS_FQ1236A_MK4] = { /* Philips NTSC */
-		.name   = "Philips FQ1236A MK4",
-		.params = tuner_philips_fq1236a_mk4_params,
-		.count  = ARRAY_SIZE(tuner_philips_fq1236a_mk4_params),
-	},
-	[TUNER_YMEC_TVF_8531MF] = { /* Philips NTSC */
-		.name   = "Ymec TVision TVF-8531MF/8831MF/8731MF",
-		.params = tuner_ymec_tvf_8531mf_params,
-		.count  = ARRAY_SIZE(tuner_ymec_tvf_8531mf_params),
-	},
-	[TUNER_YMEC_TVF_5533MF] = { /* Philips NTSC */
-		.name   = "Ymec TVision TVF-5533MF",
-		.params = tuner_ymec_tvf_5533mf_params,
-		.count  = ARRAY_SIZE(tuner_ymec_tvf_5533mf_params),
-	},
-
-	/* 60-69 */
-	[TUNER_THOMSON_DTT761X] = { /* THOMSON ATSC */
-		/* DTT 7611 7611A 7612 7613 7613A 7614 7615 7615A */
-		.name   = "Thomson DTT 761X (ATSC/NTSC)",
-		.params = tuner_thomson_dtt761x_params,
-		.count  = ARRAY_SIZE(tuner_thomson_dtt761x_params),
-		.min    = 16 *  57.00,
-		.max    = 16 * 863.00,
-		.stepsize = 62500,
-		.initdata = tua603x_agc103,
-	},
-	[TUNER_TENA_9533_DI] = { /* Philips PAL */
-		.name   = "Tena TNF9533-D/IF/TNF9533-B/DF",
-		.params = tuner_tena_9533_di_params,
-		.count  = ARRAY_SIZE(tuner_tena_9533_di_params),
-	},
-	[TUNER_TEA5767] = { /* Philips RADIO */
-		.name   = "Philips TEA5767HN FM Radio",
-		/* see tea5767.c for details */
-	},
-	[TUNER_PHILIPS_FMD1216ME_MK3] = { /* Philips PAL */
-		.name   = "Philips FMD1216ME MK3 Hybrid Tuner",
-		.params = tuner_philips_fmd1216me_mk3_params,
-		.count  = ARRAY_SIZE(tuner_philips_fmd1216me_mk3_params),
-		.min = 16 *  50.87,
-		.max = 16 * 858.00,
-		.stepsize = 166667,
-		.initdata = tua603x_agc112,
-		.sleepdata = (u8[]){ 4, 0x9c, 0x60, 0x85, 0x54 },
-	},
-	[TUNER_LG_TDVS_H06XF] = { /* LGINNOTEK ATSC */
-		.name   = "LG TDVS-H06xF", /* H061F, H062F & H064F */
-		.params = tuner_lg_tdvs_h06xf_params,
-		.count  = ARRAY_SIZE(tuner_lg_tdvs_h06xf_params),
-		.min    = 16 *  54.00,
-		.max    = 16 * 863.00,
-		.stepsize = 62500,
-		.initdata = tua603x_agc103,
-	},
-	[TUNER_YMEC_TVF66T5_B_DFF] = { /* Philips PAL */
-		.name   = "Ymec TVF66T5-B/DFF",
-		.params = tuner_ymec_tvf66t5_b_dff_params,
-		.count  = ARRAY_SIZE(tuner_ymec_tvf66t5_b_dff_params),
-	},
-	[TUNER_LG_TALN] = { /* LGINNOTEK NTSC / PAL / SECAM */
-		.name   = "LG TALN series",
-		.params = tuner_lg_taln_params,
-		.count  = ARRAY_SIZE(tuner_lg_taln_params),
-	},
-	[TUNER_PHILIPS_TD1316] = { /* Philips PAL */
-		.name   = "Philips TD1316 Hybrid Tuner",
-		.params = tuner_philips_td1316_params,
-		.count  = ARRAY_SIZE(tuner_philips_td1316_params),
-		.min    = 16 *  87.00,
-		.max    = 16 * 895.00,
-		.stepsize = 166667,
-	},
-	[TUNER_PHILIPS_TUV1236D] = { /* Philips ATSC */
-		.name   = "Philips TUV1236D ATSC/NTSC dual in",
-		.params = tuner_tuv1236d_params,
-		.count  = ARRAY_SIZE(tuner_tuv1236d_params),
-		.min    = 16 *  54.00,
-		.max    = 16 * 864.00,
-		.stepsize = 62500,
-	},
-	[TUNER_TNF_5335MF] = { /* Tenna PAL/NTSC */
-		.name   = "Tena TNF 5335 and similar models",
-		.params = tuner_tnf_5335mf_params,
-		.count  = ARRAY_SIZE(tuner_tnf_5335mf_params),
-	},
-
-	/* 70-79 */
-	[TUNER_SAMSUNG_TCPN_2121P30A] = { /* Samsung NTSC */
-		.name   = "Samsung TCPN 2121P30A",
-		.params = tuner_samsung_tcpn_2121p30a_params,
-		.count  = ARRAY_SIZE(tuner_samsung_tcpn_2121p30a_params),
-	},
-	[TUNER_XC2028] = { /* Xceive 2028 */
-		.name   = "Xceive xc2028/xc3028 tuner",
-		/* see tuner-xc2028.c for details */
-	},
-	[TUNER_THOMSON_FE6600] = { /* Thomson PAL / DVB-T */
-		.name   = "Thomson FE6600",
-		.params = tuner_thomson_fe6600_params,
-		.count  = ARRAY_SIZE(tuner_thomson_fe6600_params),
-		.min    = 16 *  44.25,
-		.max    = 16 * 858.00,
-		.stepsize = 166667,
-	},
-	[TUNER_SAMSUNG_TCPG_6121P30A] = { /* Samsung PAL */
-		.name   = "Samsung TCPG 6121P30A",
-		.params = tuner_samsung_tcpg_6121p30a_params,
-		.count  = ARRAY_SIZE(tuner_samsung_tcpg_6121p30a_params),
-	},
-	[TUNER_TDA9887] = { /* Philips TDA 9887 IF PLL Demodulator.
-				This chip is part of some modern tuners */
-		.name   = "Philips TDA988[5,6,7] IF PLL Demodulator",
-		/* see tda9887.c for details */
-	},
-	[TUNER_TEA5761] = { /* Philips RADIO */
-		.name   = "Philips TEA5761 FM Radio",
-		/* see tea5767.c for details */
-	},
-	[TUNER_XC5000] = { /* Xceive 5000 */
-		.name   = "Xceive 5000 tuner",
-		/* see xc5000.c for details */
-	},
-	[TUNER_XC4000] = { /* Xceive 4000 */
-		.name   = "Xceive 4000 tuner",
-		/* see xc4000.c for details */
-	},
-	[TUNER_TCL_MF02GIP_5N] = { /* TCL tuner MF02GIP-5N-E */
-		.name   = "TCL tuner MF02GIP-5N-E",
-		.params = tuner_tcl_mf02gip_5n_params,
-		.count  = ARRAY_SIZE(tuner_tcl_mf02gip_5n_params),
-	},
-	[TUNER_PHILIPS_FMD1216MEX_MK3] = { /* Philips PAL */
-		.name   = "Philips FMD1216MEX MK3 Hybrid Tuner",
-		.params = tuner_philips_fmd1216mex_mk3_params,
-		.count  = ARRAY_SIZE(tuner_philips_fmd1216mex_mk3_params),
-		.min = 16 *  50.87,
-		.max = 16 * 858.00,
-		.stepsize = 166667,
-		.initdata = tua603x_agc112,
-		.sleepdata = (u8[]){ 4, 0x9c, 0x60, 0x85, 0x54 },
-	},
-		[TUNER_PHILIPS_FM1216MK5] = { /* Philips PAL */
-		.name   = "Philips PAL/SECAM multi (FM1216 MK5)",
-		.params = tuner_fm1216mk5_params,
-		.count  = ARRAY_SIZE(tuner_fm1216mk5_params),
-	},
-
-	/* 80-89 */
-	[TUNER_PHILIPS_FQ1216LME_MK3] = { /* PAL/SECAM, Loop-thru, no FM */
-		.name = "Philips FQ1216LME MK3 PAL/SECAM w/active loopthrough",
-		.params = tuner_fq1216lme_mk3_params,
-		.count  = ARRAY_SIZE(tuner_fq1216lme_mk3_params),
-	},
-
-	[TUNER_PARTSNIC_PTI_5NF05] = {
-		.name = "Partsnic (Daewoo) PTI-5NF05",
-		.params = tuner_partsnic_pti_5nf05_params,
-		.count  = ARRAY_SIZE(tuner_partsnic_pti_5nf05_params),
-	},
-	[TUNER_PHILIPS_CU1216L] = {
-		.name = "Philips CU1216L",
-		.params = tuner_philips_cu1216l_params,
-		.count  = ARRAY_SIZE(tuner_philips_cu1216l_params),
-		.stepsize = 62500,
-	},
-	[TUNER_NXP_TDA18271] = {
-		.name   = "NXP TDA18271",
-		/* see tda18271-fe.c for details */
-	},
-	[TUNER_SONY_BTF_PXN01Z] = {
-		.name   = "Sony BTF-Pxn01Z",
-		.params = tuner_sony_btf_pxn01z_params,
-		.count  = ARRAY_SIZE(tuner_sony_btf_pxn01z_params),
-	},
-	[TUNER_PHILIPS_FQ1236_MK5] = { /* NTSC, TDA9885, no FM radio */
-		.name   = "Philips FQ1236 MK5",
-		.params = tuner_philips_fq1236_mk5_params,
-		.count  = ARRAY_SIZE(tuner_philips_fq1236_mk5_params),
-	},
-	[TUNER_TENA_TNF_5337] = { /* Tena 5337 MFD */
-		.name   = "Tena TNF5337 MFD",
-		.params = tuner_tena_tnf_5337_params,
-		.count  = ARRAY_SIZE(tuner_tena_tnf_5337_params),
-	},
-	[TUNER_XC5000C] = { /* Xceive 5000C */
-		.name   = "Xceive 5000C tuner",
-		/* see xc5000.c for details */
-	},
-};
-EXPORT_SYMBOL(tuners);
-
-unsigned const int tuner_count = ARRAY_SIZE(tuners);
-EXPORT_SYMBOL(tuner_count);
-
-MODULE_DESCRIPTION("Simple tuner device type database");
-MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/common/tuners/tuner-xc2028-types.h b/drivers/media/common/tuners/tuner-xc2028-types.h
deleted file mode 100644
index 74dc46a..0000000
--- a/drivers/media/common/tuners/tuner-xc2028-types.h
+++ /dev/null
@@ -1,141 +0,0 @@
-/* tuner-xc2028_types
- *
- * This file includes internal tipes to be used inside tuner-xc2028.
- * Shouldn't be included outside tuner-xc2028
- *
- * Copyright (c) 2007-2008 Mauro Carvalho Chehab (mchehab@infradead.org)
- * This code is placed under the terms of the GNU General Public License v2
- */
-
-/* xc3028 firmware types */
-
-/* BASE firmware should be loaded before any other firmware */
-#define BASE		(1<<0)
-#define BASE_TYPES	(BASE|F8MHZ|MTS|FM|INPUT1|INPUT2|INIT1)
-
-/* F8MHZ marks BASE firmwares for 8 MHz Bandwidth */
-#define F8MHZ		(1<<1)
-
-/* Multichannel Television Sound (MTS)
-   Those firmwares are capable of using xc2038 DSP to decode audio and
-   produce a baseband audio output on some pins of the chip.
-   There are MTS firmwares for the most used video standards. It should be
-   required to use MTS firmwares, depending on the way audio is routed into
-   the bridge chip
- */
-#define MTS		(1<<2)
-
-/* FIXME: I have no idea what's the difference between
-   D2620 and D2633 firmwares
- */
-#define D2620		(1<<3)
-#define D2633		(1<<4)
-
-/* DTV firmwares for 6, 7 and 8 MHz
-   DTV6 - 6MHz - ATSC/DVB-C/DVB-T/ISDB-T/DOCSIS
-   DTV8 - 8MHz - DVB-C/DVB-T
- */
-#define DTV6           (1 << 5)
-#define QAM            (1 << 6)
-#define DTV7		(1<<7)
-#define DTV78		(1<<8)
-#define DTV8		(1<<9)
-
-#define DTV_TYPES	(D2620|D2633|DTV6|QAM|DTV7|DTV78|DTV8|ATSC)
-
-/* There's a FM | BASE firmware + FM specific firmware (std=0) */
-#define	FM		(1<<10)
-
-#define STD_SPECIFIC_TYPES (MTS|FM|LCD|NOGD)
-
-/* Applies only for FM firmware
-   Makes it use RF input 1 (pin #2) instead of input 2 (pin #4)
- */
-#define INPUT1		(1<<11)
-
-
-/* LCD firmwares exist only for MTS STD/MN (PAL or NTSC/M)
-	and for non-MTS STD/MN (PAL, NTSC/M or NTSC/Kr)
-	There are variants both with and without NOGD
-	Those firmwares produce better result with LCD displays
- */
-#define LCD		(1<<12)
-
-/* NOGD firmwares exist only for MTS STD/MN (PAL or NTSC/M)
-	and for non-MTS STD/MN (PAL, NTSC/M or NTSC/Kr)
-	The NOGD firmwares don't have group delay compensation filter
- */
-#define NOGD		(1<<13)
-
-/* Old firmwares were broken into init0 and init1 */
-#define INIT1		(1<<14)
-
-/* SCODE firmware selects particular behaviours */
-#define MONO           (1 << 15)
-#define ATSC           (1 << 16)
-#define IF             (1 << 17)
-#define LG60           (1 << 18)
-#define ATI638         (1 << 19)
-#define OREN538        (1 << 20)
-#define OREN36         (1 << 21)
-#define TOYOTA388      (1 << 22)
-#define TOYOTA794      (1 << 23)
-#define DIBCOM52       (1 << 24)
-#define ZARLINK456     (1 << 25)
-#define CHINA          (1 << 26)
-#define F6MHZ          (1 << 27)
-#define INPUT2         (1 << 28)
-#define SCODE          (1 << 29)
-
-/* This flag identifies that the scode table has a new format */
-#define HAS_IF         (1 << 30)
-
-/* There are different scode tables for MTS and non-MTS.
-   The MTS firmwares support mono only
-  */
-#define SCODE_TYPES (SCODE | MTS)
-
-
-/* Newer types not defined on videodev2.h.
-   The original idea were to move all those types to videodev2.h, but
-   it seemed overkill, since, with the exception of SECAM/K3, the other
-   types seem to be autodetected.
-   It is not clear where secam/k3 is used, nor we have a feedback of this
-   working or being autodetected by the standard secam firmware.
- */
-
-#define V4L2_STD_SECAM_K3	(0x04000000)
-
-/* Audio types */
-
-#define V4L2_STD_A2_A		(1LL<<32)
-#define V4L2_STD_A2_B		(1LL<<33)
-#define V4L2_STD_NICAM_A	(1LL<<34)
-#define V4L2_STD_NICAM_B	(1LL<<35)
-#define V4L2_STD_AM		(1LL<<36)
-#define V4L2_STD_BTSC		(1LL<<37)
-#define V4L2_STD_EIAJ		(1LL<<38)
-
-#define V4L2_STD_A2		(V4L2_STD_A2_A    | V4L2_STD_A2_B)
-#define V4L2_STD_NICAM		(V4L2_STD_NICAM_A | V4L2_STD_NICAM_B)
-
-/* To preserve backward compatibilty,
-   (std & V4L2_STD_AUDIO) = 0 means that ALL audio stds are supported
- */
-
-#define V4L2_STD_AUDIO		(V4L2_STD_A2    | \
-				 V4L2_STD_NICAM | \
-				 V4L2_STD_AM    | \
-				 V4L2_STD_BTSC  | \
-				 V4L2_STD_EIAJ)
-
-/* Used standards with audio restrictions */
-
-#define V4L2_STD_PAL_BG_A2_A	(V4L2_STD_PAL_BG | V4L2_STD_A2_A)
-#define V4L2_STD_PAL_BG_A2_B	(V4L2_STD_PAL_BG | V4L2_STD_A2_B)
-#define V4L2_STD_PAL_BG_NICAM_A	(V4L2_STD_PAL_BG | V4L2_STD_NICAM_A)
-#define V4L2_STD_PAL_BG_NICAM_B	(V4L2_STD_PAL_BG | V4L2_STD_NICAM_B)
-#define V4L2_STD_PAL_DK_A2	(V4L2_STD_PAL_DK | V4L2_STD_A2)
-#define V4L2_STD_PAL_DK_NICAM	(V4L2_STD_PAL_DK | V4L2_STD_NICAM)
-#define V4L2_STD_SECAM_L_NICAM	(V4L2_STD_SECAM_L | V4L2_STD_NICAM)
-#define V4L2_STD_SECAM_L_AM	(V4L2_STD_SECAM_L | V4L2_STD_AM)
diff --git a/drivers/media/common/tuners/tuner-xc2028.c b/drivers/media/common/tuners/tuner-xc2028.c
deleted file mode 100644
index ea0550e..0000000
--- a/drivers/media/common/tuners/tuner-xc2028.c
+++ /dev/null
@@ -1,1510 +0,0 @@
-/* tuner-xc2028
- *
- * Copyright (c) 2007-2008 Mauro Carvalho Chehab (mchehab@infradead.org)
- *
- * Copyright (c) 2007 Michel Ludwig (michel.ludwig@gmail.com)
- *       - frontend interface
- *
- * This code is placed under the terms of the GNU General Public License v2
- */
-
-#include <linux/i2c.h>
-#include <asm/div64.h>
-#include <linux/firmware.h>
-#include <linux/videodev2.h>
-#include <linux/delay.h>
-#include <media/tuner.h>
-#include <linux/mutex.h>
-#include <linux/slab.h>
-#include <asm/unaligned.h>
-#include "tuner-i2c.h"
-#include "tuner-xc2028.h"
-#include "tuner-xc2028-types.h"
-
-#include <linux/dvb/frontend.h>
-#include "dvb_frontend.h"
-
-/* Registers (Write-only) */
-#define XREG_INIT         0x00
-#define XREG_RF_FREQ      0x02
-#define XREG_POWER_DOWN   0x08
-
-/* Registers (Read-only) */
-#define XREG_FREQ_ERROR   0x01
-#define XREG_LOCK         0x02
-#define XREG_VERSION      0x04
-#define XREG_PRODUCT_ID   0x08
-#define XREG_HSYNC_FREQ   0x10
-#define XREG_FRAME_LINES  0x20
-#define XREG_SNR          0x40
-
-#define XREG_ADC_ENV      0x0100
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "enable verbose debug messages");
-
-static int no_poweroff;
-module_param(no_poweroff, int, 0644);
-MODULE_PARM_DESC(no_poweroff, "0 (default) powers device off when not used.\n"
-	"1 keep device energized and with tuner ready all the times.\n"
-	"  Faster, but consumes more power and keeps the device hotter\n");
-
-static char audio_std[8];
-module_param_string(audio_std, audio_std, sizeof(audio_std), 0);
-MODULE_PARM_DESC(audio_std,
-	"Audio standard. XC3028 audio decoder explicitly "
-	"needs to know what audio\n"
-	"standard is needed for some video standards with audio A2 or NICAM.\n"
-	"The valid values are:\n"
-	"A2\n"
-	"A2/A\n"
-	"A2/B\n"
-	"NICAM\n"
-	"NICAM/A\n"
-	"NICAM/B\n");
-
-static char firmware_name[30];
-module_param_string(firmware_name, firmware_name, sizeof(firmware_name), 0);
-MODULE_PARM_DESC(firmware_name, "Firmware file name. Allows overriding the "
-				"default firmware name\n");
-
-static LIST_HEAD(hybrid_tuner_instance_list);
-static DEFINE_MUTEX(xc2028_list_mutex);
-
-/* struct for storing firmware table */
-struct firmware_description {
-	unsigned int  type;
-	v4l2_std_id   id;
-	__u16         int_freq;
-	unsigned char *ptr;
-	unsigned int  size;
-};
-
-struct firmware_properties {
-	unsigned int	type;
-	v4l2_std_id	id;
-	v4l2_std_id	std_req;
-	__u16		int_freq;
-	unsigned int	scode_table;
-	int 		scode_nr;
-};
-
-enum xc2028_state {
-	XC2028_NO_FIRMWARE = 0,
-	XC2028_WAITING_FIRMWARE,
-	XC2028_ACTIVE,
-	XC2028_SLEEP,
-	XC2028_NODEV,
-};
-
-struct xc2028_data {
-	struct list_head        hybrid_tuner_instance_list;
-	struct tuner_i2c_props  i2c_props;
-	__u32			frequency;
-
-	enum xc2028_state	state;
-	const char		*fname;
-
-	struct firmware_description *firm;
-	int			firm_size;
-	__u16			firm_version;
-
-	__u16			hwmodel;
-	__u16			hwvers;
-
-	struct xc2028_ctrl	ctrl;
-
-	struct firmware_properties cur_fw;
-
-	struct mutex lock;
-};
-
-#define i2c_send(priv, buf, size) ({					\
-	int _rc;							\
-	_rc = tuner_i2c_xfer_send(&priv->i2c_props, buf, size);		\
-	if (size != _rc)						\
-		tuner_info("i2c output error: rc = %d (should be %d)\n",\
-			   _rc, (int)size);				\
-	if (priv->ctrl.msleep)						\
-		msleep(priv->ctrl.msleep);				\
-	_rc;								\
-})
-
-#define i2c_rcv(priv, buf, size) ({					\
-	int _rc;							\
-	_rc = tuner_i2c_xfer_recv(&priv->i2c_props, buf, size);		\
-	if (size != _rc)						\
-		tuner_err("i2c input error: rc = %d (should be %d)\n",	\
-			   _rc, (int)size); 				\
-	_rc;								\
-})
-
-#define i2c_send_recv(priv, obuf, osize, ibuf, isize) ({		\
-	int _rc;							\
-	_rc = tuner_i2c_xfer_send_recv(&priv->i2c_props, obuf, osize,	\
-				       ibuf, isize);			\
-	if (isize != _rc)						\
-		tuner_err("i2c input error: rc = %d (should be %d)\n",	\
-			   _rc, (int)isize); 				\
-	if (priv->ctrl.msleep)						\
-		msleep(priv->ctrl.msleep);				\
-	_rc;								\
-})
-
-#define send_seq(priv, data...)	({					\
-	static u8 _val[] = data;					\
-	int _rc;							\
-	if (sizeof(_val) !=						\
-			(_rc = tuner_i2c_xfer_send(&priv->i2c_props,	\
-						_val, sizeof(_val)))) {	\
-		tuner_err("Error on line %d: %d\n", __LINE__, _rc);	\
-	} else if (priv->ctrl.msleep)					\
-		msleep(priv->ctrl.msleep);				\
-	_rc;								\
-})
-
-static int xc2028_get_reg(struct xc2028_data *priv, u16 reg, u16 *val)
-{
-	unsigned char buf[2];
-	unsigned char ibuf[2];
-
-	tuner_dbg("%s %04x called\n", __func__, reg);
-
-	buf[0] = reg >> 8;
-	buf[1] = (unsigned char) reg;
-
-	if (i2c_send_recv(priv, buf, 2, ibuf, 2) != 2)
-		return -EIO;
-
-	*val = (ibuf[1]) | (ibuf[0] << 8);
-	return 0;
-}
-
-#define dump_firm_type(t) 	dump_firm_type_and_int_freq(t, 0)
-static void dump_firm_type_and_int_freq(unsigned int type, u16 int_freq)
-{
-	 if (type & BASE)
-		printk("BASE ");
-	 if (type & INIT1)
-		printk("INIT1 ");
-	 if (type & F8MHZ)
-		printk("F8MHZ ");
-	 if (type & MTS)
-		printk("MTS ");
-	 if (type & D2620)
-		printk("D2620 ");
-	 if (type & D2633)
-		printk("D2633 ");
-	 if (type & DTV6)
-		printk("DTV6 ");
-	 if (type & QAM)
-		printk("QAM ");
-	 if (type & DTV7)
-		printk("DTV7 ");
-	 if (type & DTV78)
-		printk("DTV78 ");
-	 if (type & DTV8)
-		printk("DTV8 ");
-	 if (type & FM)
-		printk("FM ");
-	 if (type & INPUT1)
-		printk("INPUT1 ");
-	 if (type & LCD)
-		printk("LCD ");
-	 if (type & NOGD)
-		printk("NOGD ");
-	 if (type & MONO)
-		printk("MONO ");
-	 if (type & ATSC)
-		printk("ATSC ");
-	 if (type & IF)
-		printk("IF ");
-	 if (type & LG60)
-		printk("LG60 ");
-	 if (type & ATI638)
-		printk("ATI638 ");
-	 if (type & OREN538)
-		printk("OREN538 ");
-	 if (type & OREN36)
-		printk("OREN36 ");
-	 if (type & TOYOTA388)
-		printk("TOYOTA388 ");
-	 if (type & TOYOTA794)
-		printk("TOYOTA794 ");
-	 if (type & DIBCOM52)
-		printk("DIBCOM52 ");
-	 if (type & ZARLINK456)
-		printk("ZARLINK456 ");
-	 if (type & CHINA)
-		printk("CHINA ");
-	 if (type & F6MHZ)
-		printk("F6MHZ ");
-	 if (type & INPUT2)
-		printk("INPUT2 ");
-	 if (type & SCODE)
-		printk("SCODE ");
-	 if (type & HAS_IF)
-		printk("HAS_IF_%d ", int_freq);
-}
-
-static  v4l2_std_id parse_audio_std_option(void)
-{
-	if (strcasecmp(audio_std, "A2") == 0)
-		return V4L2_STD_A2;
-	if (strcasecmp(audio_std, "A2/A") == 0)
-		return V4L2_STD_A2_A;
-	if (strcasecmp(audio_std, "A2/B") == 0)
-		return V4L2_STD_A2_B;
-	if (strcasecmp(audio_std, "NICAM") == 0)
-		return V4L2_STD_NICAM;
-	if (strcasecmp(audio_std, "NICAM/A") == 0)
-		return V4L2_STD_NICAM_A;
-	if (strcasecmp(audio_std, "NICAM/B") == 0)
-		return V4L2_STD_NICAM_B;
-
-	return 0;
-}
-
-static int check_device_status(struct xc2028_data *priv)
-{
-	switch (priv->state) {
-	case XC2028_NO_FIRMWARE:
-	case XC2028_WAITING_FIRMWARE:
-		return -EAGAIN;
-	case XC2028_ACTIVE:
-	case XC2028_SLEEP:
-		return 0;
-	case XC2028_NODEV:
-		return -ENODEV;
-	}
-	return 0;
-}
-
-static void free_firmware(struct xc2028_data *priv)
-{
-	int i;
-	tuner_dbg("%s called\n", __func__);
-
-	if (!priv->firm)
-		return;
-
-	for (i = 0; i < priv->firm_size; i++)
-		kfree(priv->firm[i].ptr);
-
-	kfree(priv->firm);
-
-	priv->firm = NULL;
-	priv->firm_size = 0;
-	priv->state = XC2028_NO_FIRMWARE;
-
-	memset(&priv->cur_fw, 0, sizeof(priv->cur_fw));
-}
-
-static int load_all_firmwares(struct dvb_frontend *fe,
-			      const struct firmware *fw)
-{
-	struct xc2028_data    *priv = fe->tuner_priv;
-	const unsigned char   *p, *endp;
-	int                   rc = 0;
-	int		      n, n_array;
-	char		      name[33];
-
-	tuner_dbg("%s called\n", __func__);
-
-	p = fw->data;
-	endp = p + fw->size;
-
-	if (fw->size < sizeof(name) - 1 + 2 + 2) {
-		tuner_err("Error: firmware file %s has invalid size!\n",
-			  priv->fname);
-		goto corrupt;
-	}
-
-	memcpy(name, p, sizeof(name) - 1);
-	name[sizeof(name) - 1] = 0;
-	p += sizeof(name) - 1;
-
-	priv->firm_version = get_unaligned_le16(p);
-	p += 2;
-
-	n_array = get_unaligned_le16(p);
-	p += 2;
-
-	tuner_info("Loading %d firmware images from %s, type: %s, ver %d.%d\n",
-		   n_array, priv->fname, name,
-		   priv->firm_version >> 8, priv->firm_version & 0xff);
-
-	priv->firm = kcalloc(n_array, sizeof(*priv->firm), GFP_KERNEL);
-	if (priv->firm == NULL) {
-		tuner_err("Not enough memory to load firmware file.\n");
-		rc = -ENOMEM;
-		goto err;
-	}
-	priv->firm_size = n_array;
-
-	n = -1;
-	while (p < endp) {
-		__u32 type, size;
-		v4l2_std_id id;
-		__u16 int_freq = 0;
-
-		n++;
-		if (n >= n_array) {
-			tuner_err("More firmware images in file than "
-				  "were expected!\n");
-			goto corrupt;
-		}
-
-		/* Checks if there's enough bytes to read */
-		if (endp - p < sizeof(type) + sizeof(id) + sizeof(size))
-			goto header;
-
-		type = get_unaligned_le32(p);
-		p += sizeof(type);
-
-		id = get_unaligned_le64(p);
-		p += sizeof(id);
-
-		if (type & HAS_IF) {
-			int_freq = get_unaligned_le16(p);
-			p += sizeof(int_freq);
-			if (endp - p < sizeof(size))
-				goto header;
-		}
-
-		size = get_unaligned_le32(p);
-		p += sizeof(size);
-
-		if (!size || size > endp - p) {
-			tuner_err("Firmware type ");
-			dump_firm_type(type);
-			printk("(%x), id %llx is corrupted "
-			       "(size=%d, expected %d)\n",
-			       type, (unsigned long long)id,
-			       (unsigned)(endp - p), size);
-			goto corrupt;
-		}
-
-		priv->firm[n].ptr = kzalloc(size, GFP_KERNEL);
-		if (priv->firm[n].ptr == NULL) {
-			tuner_err("Not enough memory to load firmware file.\n");
-			rc = -ENOMEM;
-			goto err;
-		}
-		tuner_dbg("Reading firmware type ");
-		if (debug) {
-			dump_firm_type_and_int_freq(type, int_freq);
-			printk("(%x), id %llx, size=%d.\n",
-			       type, (unsigned long long)id, size);
-		}
-
-		memcpy(priv->firm[n].ptr, p, size);
-		priv->firm[n].type = type;
-		priv->firm[n].id   = id;
-		priv->firm[n].size = size;
-		priv->firm[n].int_freq = int_freq;
-
-		p += size;
-	}
-
-	if (n + 1 != priv->firm_size) {
-		tuner_err("Firmware file is incomplete!\n");
-		goto corrupt;
-	}
-
-	goto done;
-
-header:
-	tuner_err("Firmware header is incomplete!\n");
-corrupt:
-	rc = -EINVAL;
-	tuner_err("Error: firmware file is corrupted!\n");
-
-err:
-	tuner_info("Releasing partially loaded firmware file.\n");
-	free_firmware(priv);
-
-done:
-	if (rc == 0)
-		tuner_dbg("Firmware files loaded.\n");
-	else
-		priv->state = XC2028_NODEV;
-
-	return rc;
-}
-
-static int seek_firmware(struct dvb_frontend *fe, unsigned int type,
-			 v4l2_std_id *id)
-{
-	struct xc2028_data *priv = fe->tuner_priv;
-	int                 i, best_i = -1, best_nr_matches = 0;
-	unsigned int        type_mask = 0;
-
-	tuner_dbg("%s called, want type=", __func__);
-	if (debug) {
-		dump_firm_type(type);
-		printk("(%x), id %016llx.\n", type, (unsigned long long)*id);
-	}
-
-	if (!priv->firm) {
-		tuner_err("Error! firmware not loaded\n");
-		return -EINVAL;
-	}
-
-	if (((type & ~SCODE) == 0) && (*id == 0))
-		*id = V4L2_STD_PAL;
-
-	if (type & BASE)
-		type_mask = BASE_TYPES;
-	else if (type & SCODE) {
-		type &= SCODE_TYPES;
-		type_mask = SCODE_TYPES & ~HAS_IF;
-	} else if (type & DTV_TYPES)
-		type_mask = DTV_TYPES;
-	else if (type & STD_SPECIFIC_TYPES)
-		type_mask = STD_SPECIFIC_TYPES;
-
-	type &= type_mask;
-
-	if (!(type & SCODE))
-		type_mask = ~0;
-
-	/* Seek for exact match */
-	for (i = 0; i < priv->firm_size; i++) {
-		if ((type == (priv->firm[i].type & type_mask)) &&
-		    (*id == priv->firm[i].id))
-			goto found;
-	}
-
-	/* Seek for generic video standard match */
-	for (i = 0; i < priv->firm_size; i++) {
-		v4l2_std_id match_mask;
-		int nr_matches;
-
-		if (type != (priv->firm[i].type & type_mask))
-			continue;
-
-		match_mask = *id & priv->firm[i].id;
-		if (!match_mask)
-			continue;
-
-		if ((*id & match_mask) == *id)
-			goto found; /* Supports all the requested standards */
-
-		nr_matches = hweight64(match_mask);
-		if (nr_matches > best_nr_matches) {
-			best_nr_matches = nr_matches;
-			best_i = i;
-		}
-	}
-
-	if (best_nr_matches > 0) {
-		tuner_dbg("Selecting best matching firmware (%d bits) for "
-			  "type=", best_nr_matches);
-		dump_firm_type(type);
-		printk("(%x), id %016llx:\n", type, (unsigned long long)*id);
-		i = best_i;
-		goto found;
-	}
-
-	/*FIXME: Would make sense to seek for type "hint" match ? */
-
-	i = -ENOENT;
-	goto ret;
-
-found:
-	*id = priv->firm[i].id;
-
-ret:
-	tuner_dbg("%s firmware for type=", (i < 0) ? "Can't find" : "Found");
-	if (debug) {
-		dump_firm_type(type);
-		printk("(%x), id %016llx.\n", type, (unsigned long long)*id);
-	}
-	return i;
-}
-
-static inline int do_tuner_callback(struct dvb_frontend *fe, int cmd, int arg)
-{
-	struct xc2028_data *priv = fe->tuner_priv;
-
-	/* analog side (tuner-core) uses i2c_adap->algo_data.
-	 * digital side is not guaranteed to have algo_data defined.
-	 *
-	 * digital side will always have fe->dvb defined.
-	 * analog side (tuner-core) doesn't (yet) define fe->dvb.
-	 */
-
-	return (!fe->callback) ? -EINVAL :
-		fe->callback(((fe->dvb) && (fe->dvb->priv)) ?
-				fe->dvb->priv : priv->i2c_props.adap->algo_data,
-			     DVB_FRONTEND_COMPONENT_TUNER, cmd, arg);
-}
-
-static int load_firmware(struct dvb_frontend *fe, unsigned int type,
-			 v4l2_std_id *id)
-{
-	struct xc2028_data *priv = fe->tuner_priv;
-	int                pos, rc;
-	unsigned char      *p, *endp, buf[priv->ctrl.max_len];
-
-	tuner_dbg("%s called\n", __func__);
-
-	pos = seek_firmware(fe, type, id);
-	if (pos < 0)
-		return pos;
-
-	tuner_info("Loading firmware for type=");
-	dump_firm_type(priv->firm[pos].type);
-	printk("(%x), id %016llx.\n", priv->firm[pos].type,
-	       (unsigned long long)*id);
-
-	p = priv->firm[pos].ptr;
-	endp = p + priv->firm[pos].size;
-
-	while (p < endp) {
-		__u16 size;
-
-		/* Checks if there's enough bytes to read */
-		if (p + sizeof(size) > endp) {
-			tuner_err("Firmware chunk size is wrong\n");
-			return -EINVAL;
-		}
-
-		size = le16_to_cpu(*(__u16 *) p);
-		p += sizeof(size);
-
-		if (size == 0xffff)
-			return 0;
-
-		if (!size) {
-			/* Special callback command received */
-			rc = do_tuner_callback(fe, XC2028_TUNER_RESET, 0);
-			if (rc < 0) {
-				tuner_err("Error at RESET code %d\n",
-					   (*p) & 0x7f);
-				return -EINVAL;
-			}
-			continue;
-		}
-		if (size >= 0xff00) {
-			switch (size) {
-			case 0xff00:
-				rc = do_tuner_callback(fe, XC2028_RESET_CLK, 0);
-				if (rc < 0) {
-					tuner_err("Error at RESET code %d\n",
-						  (*p) & 0x7f);
-					return -EINVAL;
-				}
-				break;
-			default:
-				tuner_info("Invalid RESET code %d\n",
-					   size & 0x7f);
-				return -EINVAL;
-
-			}
-			continue;
-		}
-
-		/* Checks for a sleep command */
-		if (size & 0x8000) {
-			msleep(size & 0x7fff);
-			continue;
-		}
-
-		if ((size + p > endp)) {
-			tuner_err("missing bytes: need %d, have %d\n",
-				   size, (int)(endp - p));
-			return -EINVAL;
-		}
-
-		buf[0] = *p;
-		p++;
-		size--;
-
-		/* Sends message chunks */
-		while (size > 0) {
-			int len = (size < priv->ctrl.max_len - 1) ?
-				   size : priv->ctrl.max_len - 1;
-
-			memcpy(buf + 1, p, len);
-
-			rc = i2c_send(priv, buf, len + 1);
-			if (rc < 0) {
-				tuner_err("%d returned from send\n", rc);
-				return -EINVAL;
-			}
-
-			p += len;
-			size -= len;
-		}
-
-		/* silently fail if the frontend doesn't support I2C flush */
-		rc = do_tuner_callback(fe, XC2028_I2C_FLUSH, 0);
-		if ((rc < 0) && (rc != -EINVAL)) {
-			tuner_err("error executing flush: %d\n", rc);
-			return rc;
-		}
-	}
-	return 0;
-}
-
-static int load_scode(struct dvb_frontend *fe, unsigned int type,
-			 v4l2_std_id *id, __u16 int_freq, int scode)
-{
-	struct xc2028_data *priv = fe->tuner_priv;
-	int                pos, rc;
-	unsigned char	   *p;
-
-	tuner_dbg("%s called\n", __func__);
-
-	if (!int_freq) {
-		pos = seek_firmware(fe, type, id);
-		if (pos < 0)
-			return pos;
-	} else {
-		for (pos = 0; pos < priv->firm_size; pos++) {
-			if ((priv->firm[pos].int_freq == int_freq) &&
-			    (priv->firm[pos].type & HAS_IF))
-				break;
-		}
-		if (pos == priv->firm_size)
-			return -ENOENT;
-	}
-
-	p = priv->firm[pos].ptr;
-
-	if (priv->firm[pos].type & HAS_IF) {
-		if (priv->firm[pos].size != 12 * 16 || scode >= 16)
-			return -EINVAL;
-		p += 12 * scode;
-	} else {
-		/* 16 SCODE entries per file; each SCODE entry is 12 bytes and
-		 * has a 2-byte size header in the firmware format. */
-		if (priv->firm[pos].size != 14 * 16 || scode >= 16 ||
-		    le16_to_cpu(*(__u16 *)(p + 14 * scode)) != 12)
-			return -EINVAL;
-		p += 14 * scode + 2;
-	}
-
-	tuner_info("Loading SCODE for type=");
-	dump_firm_type_and_int_freq(priv->firm[pos].type,
-				    priv->firm[pos].int_freq);
-	printk("(%x), id %016llx.\n", priv->firm[pos].type,
-	       (unsigned long long)*id);
-
-	if (priv->firm_version < 0x0202)
-		rc = send_seq(priv, {0x20, 0x00, 0x00, 0x00});
-	else
-		rc = send_seq(priv, {0xa0, 0x00, 0x00, 0x00});
-	if (rc < 0)
-		return -EIO;
-
-	rc = i2c_send(priv, p, 12);
-	if (rc < 0)
-		return -EIO;
-
-	rc = send_seq(priv, {0x00, 0x8c});
-	if (rc < 0)
-		return -EIO;
-
-	return 0;
-}
-
-static int check_firmware(struct dvb_frontend *fe, unsigned int type,
-			  v4l2_std_id std, __u16 int_freq)
-{
-	struct xc2028_data         *priv = fe->tuner_priv;
-	struct firmware_properties new_fw;
-	int			   rc, retry_count = 0;
-	u16			   version, hwmodel;
-	v4l2_std_id		   std0;
-
-	tuner_dbg("%s called\n", __func__);
-
-	rc = check_device_status(priv);
-	if (rc < 0)
-		return rc;
-
-	if (priv->ctrl.mts && !(type & FM))
-		type |= MTS;
-
-retry:
-	new_fw.type = type;
-	new_fw.id = std;
-	new_fw.std_req = std;
-	new_fw.scode_table = SCODE | priv->ctrl.scode_table;
-	new_fw.scode_nr = 0;
-	new_fw.int_freq = int_freq;
-
-	tuner_dbg("checking firmware, user requested type=");
-	if (debug) {
-		dump_firm_type(new_fw.type);
-		printk("(%x), id %016llx, ", new_fw.type,
-		       (unsigned long long)new_fw.std_req);
-		if (!int_freq) {
-			printk("scode_tbl ");
-			dump_firm_type(priv->ctrl.scode_table);
-			printk("(%x), ", priv->ctrl.scode_table);
-		} else
-			printk("int_freq %d, ", new_fw.int_freq);
-		printk("scode_nr %d\n", new_fw.scode_nr);
-	}
-
-	/*
-	 * No need to reload base firmware if it matches and if the tuner
-	 * is not at sleep mode
-	 */
-	if ((priv->state == XC2028_ACTIVE) &&
-	    (((BASE | new_fw.type) & BASE_TYPES) ==
-	    (priv->cur_fw.type & BASE_TYPES))) {
-		tuner_dbg("BASE firmware not changed.\n");
-		goto skip_base;
-	}
-
-	/* Updating BASE - forget about all currently loaded firmware */
-	memset(&priv->cur_fw, 0, sizeof(priv->cur_fw));
-
-	/* Reset is needed before loading firmware */
-	rc = do_tuner_callback(fe, XC2028_TUNER_RESET, 0);
-	if (rc < 0)
-		goto fail;
-
-	/* BASE firmwares are all std0 */
-	std0 = 0;
-	rc = load_firmware(fe, BASE | new_fw.type, &std0);
-	if (rc < 0) {
-		tuner_err("Error %d while loading base firmware\n",
-			  rc);
-		goto fail;
-	}
-
-	/* Load INIT1, if needed */
-	tuner_dbg("Load init1 firmware, if exists\n");
-
-	rc = load_firmware(fe, BASE | INIT1 | new_fw.type, &std0);
-	if (rc == -ENOENT)
-		rc = load_firmware(fe, (BASE | INIT1 | new_fw.type) & ~F8MHZ,
-				   &std0);
-	if (rc < 0 && rc != -ENOENT) {
-		tuner_err("Error %d while loading init1 firmware\n",
-			  rc);
-		goto fail;
-	}
-
-skip_base:
-	/*
-	 * No need to reload standard specific firmware if base firmware
-	 * was not reloaded and requested video standards have not changed.
-	 */
-	if (priv->cur_fw.type == (BASE | new_fw.type) &&
-	    priv->cur_fw.std_req == std) {
-		tuner_dbg("Std-specific firmware already loaded.\n");
-		goto skip_std_specific;
-	}
-
-	/* Reloading std-specific firmware forces a SCODE update */
-	priv->cur_fw.scode_table = 0;
-
-	rc = load_firmware(fe, new_fw.type, &new_fw.id);
-	if (rc == -ENOENT)
-		rc = load_firmware(fe, new_fw.type & ~F8MHZ, &new_fw.id);
-
-	if (rc < 0)
-		goto fail;
-
-skip_std_specific:
-	if (priv->cur_fw.scode_table == new_fw.scode_table &&
-	    priv->cur_fw.scode_nr == new_fw.scode_nr) {
-		tuner_dbg("SCODE firmware already loaded.\n");
-		goto check_device;
-	}
-
-	if (new_fw.type & FM)
-		goto check_device;
-
-	/* Load SCODE firmware, if exists */
-	tuner_dbg("Trying to load scode %d\n", new_fw.scode_nr);
-
-	rc = load_scode(fe, new_fw.type | new_fw.scode_table, &new_fw.id,
-			new_fw.int_freq, new_fw.scode_nr);
-
-check_device:
-	if (xc2028_get_reg(priv, 0x0004, &version) < 0 ||
-	    xc2028_get_reg(priv, 0x0008, &hwmodel) < 0) {
-		tuner_err("Unable to read tuner registers.\n");
-		goto fail;
-	}
-
-	tuner_dbg("Device is Xceive %d version %d.%d, "
-		  "firmware version %d.%d\n",
-		  hwmodel, (version & 0xf000) >> 12, (version & 0xf00) >> 8,
-		  (version & 0xf0) >> 4, version & 0xf);
-
-
-	if (priv->ctrl.read_not_reliable)
-		goto read_not_reliable;
-
-	/* Check firmware version against what we downloaded. */
-	if (priv->firm_version != ((version & 0xf0) << 4 | (version & 0x0f))) {
-		if (!priv->ctrl.read_not_reliable) {
-			tuner_err("Incorrect readback of firmware version.\n");
-			goto fail;
-		} else {
-			tuner_err("Returned an incorrect version. However, "
-				  "read is not reliable enough. Ignoring it.\n");
-			hwmodel = 3028;
-		}
-	}
-
-	/* Check that the tuner hardware model remains consistent over time. */
-	if (priv->hwmodel == 0 && (hwmodel == 2028 || hwmodel == 3028)) {
-		priv->hwmodel = hwmodel;
-		priv->hwvers  = version & 0xff00;
-	} else if (priv->hwmodel == 0 || priv->hwmodel != hwmodel ||
-		   priv->hwvers != (version & 0xff00)) {
-		tuner_err("Read invalid device hardware information - tuner "
-			  "hung?\n");
-		goto fail;
-	}
-
-read_not_reliable:
-	memcpy(&priv->cur_fw, &new_fw, sizeof(priv->cur_fw));
-
-	/*
-	 * By setting BASE in cur_fw.type only after successfully loading all
-	 * firmwares, we can:
-	 * 1. Identify that BASE firmware with type=0 has been loaded;
-	 * 2. Tell whether BASE firmware was just changed the next time through.
-	 */
-	priv->cur_fw.type |= BASE;
-	priv->state = XC2028_ACTIVE;
-
-	return 0;
-
-fail:
-	priv->state = XC2028_SLEEP;
-
-	memset(&priv->cur_fw, 0, sizeof(priv->cur_fw));
-	if (retry_count < 8) {
-		msleep(50);
-		retry_count++;
-		tuner_dbg("Retrying firmware load\n");
-		goto retry;
-	}
-
-	if (rc == -ENOENT)
-		rc = -EINVAL;
-	return rc;
-}
-
-static int xc2028_signal(struct dvb_frontend *fe, u16 *strength)
-{
-	struct xc2028_data *priv = fe->tuner_priv;
-	u16                 frq_lock, signal = 0;
-	int                 rc, i;
-
-	tuner_dbg("%s called\n", __func__);
-
-	rc = check_device_status(priv);
-	if (rc < 0)
-		return rc;
-
-	mutex_lock(&priv->lock);
-
-	/* Sync Lock Indicator */
-	for (i = 0; i < 3; i++) {
-		rc = xc2028_get_reg(priv, XREG_LOCK, &frq_lock);
-		if (rc < 0)
-			goto ret;
-
-		if (frq_lock)
-			break;
-		msleep(6);
-	}
-
-	/* Frequency didn't lock */
-	if (frq_lock == 2)
-		goto ret;
-
-	/* Get SNR of the video signal */
-	rc = xc2028_get_reg(priv, XREG_SNR, &signal);
-	if (rc < 0)
-		goto ret;
-
-	/* Signal level is 3 bits only */
-
-	signal = ((1 << 12) - 1) | ((signal & 0x07) << 12);
-
-ret:
-	mutex_unlock(&priv->lock);
-
-	*strength = signal;
-
-	tuner_dbg("signal strength is %d\n", signal);
-
-	return rc;
-}
-
-static int xc2028_get_afc(struct dvb_frontend *fe, s32 *afc)
-{
-	struct xc2028_data *priv = fe->tuner_priv;
-	int i, rc;
-	u16 frq_lock = 0;
-	s16 afc_reg = 0;
-
-	rc = check_device_status(priv);
-	if (rc < 0)
-		return rc;
-
-	mutex_lock(&priv->lock);
-
-	/* Sync Lock Indicator */
-	for (i = 0; i < 3; i++) {
-		rc = xc2028_get_reg(priv, XREG_LOCK, &frq_lock);
-		if (rc < 0)
-			goto ret;
-
-		if (frq_lock)
-			break;
-		msleep(6);
-	}
-
-	/* Frequency didn't lock */
-	if (frq_lock == 2)
-		goto ret;
-
-	/* Get AFC */
-	rc = xc2028_get_reg(priv, XREG_FREQ_ERROR, &afc_reg);
-	if (rc < 0)
-		goto ret;
-
-	*afc = afc_reg * 15625; /* Hz */
-
-	tuner_dbg("AFC is %d Hz\n", *afc);
-
-ret:
-	mutex_unlock(&priv->lock);
-
-	return rc;
-}
-
-#define DIV 15625
-
-static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */,
-			    enum v4l2_tuner_type new_type,
-			    unsigned int type,
-			    v4l2_std_id std,
-			    u16 int_freq)
-{
-	struct xc2028_data *priv = fe->tuner_priv;
-	int		   rc = -EINVAL;
-	unsigned char	   buf[4];
-	u32		   div, offset = 0;
-
-	tuner_dbg("%s called\n", __func__);
-
-	mutex_lock(&priv->lock);
-
-	tuner_dbg("should set frequency %d kHz\n", freq / 1000);
-
-	if (check_firmware(fe, type, std, int_freq) < 0)
-		goto ret;
-
-	/* On some cases xc2028 can disable video output, if
-	 * very weak signals are received. By sending a soft
-	 * reset, this is re-enabled. So, it is better to always
-	 * send a soft reset before changing channels, to be sure
-	 * that xc2028 will be in a safe state.
-	 * Maybe this might also be needed for DTV.
-	 */
-	switch (new_type) {
-	case V4L2_TUNER_ANALOG_TV:
-		rc = send_seq(priv, {0x00, 0x00});
-
-		/* Analog mode requires offset = 0 */
-		break;
-	case V4L2_TUNER_RADIO:
-		/* Radio mode requires offset = 0 */
-		break;
-	case V4L2_TUNER_DIGITAL_TV:
-		/*
-		 * Digital modes require an offset to adjust to the
-		 * proper frequency. The offset depends on what
-		 * firmware version is used.
-		 */
-
-		/*
-		 * Adjust to the center frequency. This is calculated by the
-		 * formula: offset = 1.25MHz - BW/2
-		 * For DTV 7/8, the firmware uses BW = 8000, so it needs a
-		 * further adjustment to get the frequency center on VHF
-		 */
-
-		/*
-		 * The firmware DTV78 used to work fine in UHF band (8 MHz
-		 * bandwidth) but not at all in VHF band (7 MHz bandwidth).
-		 * The real problem was connected to the formula used to
-		 * calculate the center frequency offset in VHF band.
-		 * In fact, removing the 500KHz adjustment fixed the problem.
-		 * This is coherent to what was implemented for the DTV7
-		 * firmware.
-		 * In the end, now the center frequency is the same for all 3
-		 * firmwares (DTV7, DTV8, DTV78) and doesn't depend on channel
-		 * bandwidth.
-		 */
-
-		if (priv->cur_fw.type & DTV6)
-			offset = 1750000;
-		else	/* DTV7 or DTV8 or DTV78 */
-			offset = 2750000;
-
-		/*
-		 * xc3028 additional "magic"
-		 * Depending on the firmware version, it needs some adjustments
-		 * to properly centralize the frequency. This seems to be
-		 * needed to compensate the SCODE table adjustments made by
-		 * newer firmwares
-		 */
-
-		/*
-		 * The proper adjustment would be to do it at s-code table.
-		 * However, this didn't work, as reported by
-		 * Robert Lowery <rglowery@exemail.com.au>
-		 */
-
-#if 0
-		/*
-		 * Still need tests for XC3028L (firmware 3.2 or upper)
-		 * So, for now, let's just comment the per-firmware
-		 * version of this change. Reports with xc3028l working
-		 * with and without the lines bellow are welcome
-		 */
-
-		if (priv->firm_version < 0x0302) {
-			if (priv->cur_fw.type & DTV7)
-				offset += 500000;
-		} else {
-			if (priv->cur_fw.type & DTV7)
-				offset -= 300000;
-			else if (type != ATSC) /* DVB @6MHz, DTV 8 and DTV 7/8 */
-				offset += 200000;
-		}
-#endif
-	}
-
-	div = (freq - offset + DIV / 2) / DIV;
-
-	/* CMD= Set frequency */
-	if (priv->firm_version < 0x0202)
-		rc = send_seq(priv, {0x00, XREG_RF_FREQ, 0x00, 0x00});
-	else
-		rc = send_seq(priv, {0x80, XREG_RF_FREQ, 0x00, 0x00});
-	if (rc < 0)
-		goto ret;
-
-	/* Return code shouldn't be checked.
-	   The reset CLK is needed only with tm6000.
-	   Driver should work fine even if this fails.
-	 */
-	if (priv->ctrl.msleep)
-		msleep(priv->ctrl.msleep);
-	do_tuner_callback(fe, XC2028_RESET_CLK, 1);
-
-	msleep(10);
-
-	buf[0] = 0xff & (div >> 24);
-	buf[1] = 0xff & (div >> 16);
-	buf[2] = 0xff & (div >> 8);
-	buf[3] = 0xff & (div);
-
-	rc = i2c_send(priv, buf, sizeof(buf));
-	if (rc < 0)
-		goto ret;
-	msleep(100);
-
-	priv->frequency = freq;
-
-	tuner_dbg("divisor= %02x %02x %02x %02x (freq=%d.%03d)\n",
-	       buf[0], buf[1], buf[2], buf[3],
-	       freq / 1000000, (freq % 1000000) / 1000);
-
-	rc = 0;
-
-ret:
-	mutex_unlock(&priv->lock);
-
-	return rc;
-}
-
-static int xc2028_set_analog_freq(struct dvb_frontend *fe,
-			      struct analog_parameters *p)
-{
-	struct xc2028_data *priv = fe->tuner_priv;
-	unsigned int       type=0;
-
-	tuner_dbg("%s called\n", __func__);
-
-	if (p->mode == V4L2_TUNER_RADIO) {
-		type |= FM;
-		if (priv->ctrl.input1)
-			type |= INPUT1;
-		return generic_set_freq(fe, (625l * p->frequency) / 10,
-				V4L2_TUNER_RADIO, type, 0, 0);
-	}
-
-	/* if std is not defined, choose one */
-	if (!p->std)
-		p->std = V4L2_STD_MN;
-
-	/* PAL/M, PAL/N, PAL/Nc and NTSC variants should use 6MHz firmware */
-	if (!(p->std & V4L2_STD_MN))
-		type |= F8MHZ;
-
-	/* Add audio hack to std mask */
-	p->std |= parse_audio_std_option();
-
-	return generic_set_freq(fe, 62500l * p->frequency,
-				V4L2_TUNER_ANALOG_TV, type, p->std, 0);
-}
-
-static int xc2028_set_params(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	u32 delsys = c->delivery_system;
-	u32 bw = c->bandwidth_hz;
-	struct xc2028_data *priv = fe->tuner_priv;
-	int rc;
-	unsigned int       type = 0;
-	u16                demod = 0;
-
-	tuner_dbg("%s called\n", __func__);
-
-	rc = check_device_status(priv);
-	if (rc < 0)
-		return rc;
-
-	switch (delsys) {
-	case SYS_DVBT:
-	case SYS_DVBT2:
-		/*
-		 * The only countries with 6MHz seem to be Taiwan/Uruguay.
-		 * Both seem to require QAM firmware for OFDM decoding
-		 * Tested in Taiwan by Terry Wu <terrywu2009@gmail.com>
-		 */
-		if (bw <= 6000000)
-			type |= QAM;
-
-		switch (priv->ctrl.type) {
-		case XC2028_D2633:
-			type |= D2633;
-			break;
-		case XC2028_D2620:
-			type |= D2620;
-			break;
-		case XC2028_AUTO:
-		default:
-			/* Zarlink seems to need D2633 */
-			if (priv->ctrl.demod == XC3028_FE_ZARLINK456)
-				type |= D2633;
-			else
-				type |= D2620;
-		}
-		break;
-	case SYS_ATSC:
-		/* The only ATSC firmware (at least on v2.7) is D2633 */
-		type |= ATSC | D2633;
-		break;
-	/* DVB-S and pure QAM (FE_QAM) are not supported */
-	default:
-		return -EINVAL;
-	}
-
-	if (bw <= 6000000) {
-		type |= DTV6;
-		priv->ctrl.vhfbw7 = 0;
-		priv->ctrl.uhfbw8 = 0;
-	} else if (bw <= 7000000) {
-		if (c->frequency < 470000000)
-			priv->ctrl.vhfbw7 = 1;
-		else
-			priv->ctrl.uhfbw8 = 0;
-		type |= (priv->ctrl.vhfbw7 && priv->ctrl.uhfbw8) ? DTV78 : DTV7;
-		type |= F8MHZ;
-	} else {
-		if (c->frequency < 470000000)
-			priv->ctrl.vhfbw7 = 0;
-		else
-			priv->ctrl.uhfbw8 = 1;
-		type |= (priv->ctrl.vhfbw7 && priv->ctrl.uhfbw8) ? DTV78 : DTV8;
-		type |= F8MHZ;
-	}
-
-	/* All S-code tables need a 200kHz shift */
-	if (priv->ctrl.demod) {
-		demod = priv->ctrl.demod;
-
-		/*
-		 * Newer firmwares require a 200 kHz offset only for ATSC
-		 */
-		if (type == ATSC || priv->firm_version < 0x0302)
-			demod += 200;
-		/*
-		 * The DTV7 S-code table needs a 700 kHz shift.
-		 *
-		 * DTV7 is only used in Australia.  Germany or Italy may also
-		 * use this firmware after initialization, but a tune to a UHF
-		 * channel should then cause DTV78 to be used.
-		 *
-		 * Unfortunately, on real-field tests, the s-code offset
-		 * didn't work as expected, as reported by
-		 * Robert Lowery <rglowery@exemail.com.au>
-		 */
-	}
-
-	return generic_set_freq(fe, c->frequency,
-				V4L2_TUNER_DIGITAL_TV, type, 0, demod);
-}
-
-static int xc2028_sleep(struct dvb_frontend *fe)
-{
-	struct xc2028_data *priv = fe->tuner_priv;
-	int rc;
-
-	rc = check_device_status(priv);
-	if (rc < 0)
-		return rc;
-
-	/* Avoid firmware reload on slow devices or if PM disabled */
-	if (no_poweroff || priv->ctrl.disable_power_mgmt)
-		return 0;
-
-	tuner_dbg("Putting xc2028/3028 into poweroff mode.\n");
-	if (debug > 1) {
-		tuner_dbg("Printing sleep stack trace:\n");
-		dump_stack();
-	}
-
-	mutex_lock(&priv->lock);
-
-	if (priv->firm_version < 0x0202)
-		rc = send_seq(priv, {0x00, XREG_POWER_DOWN, 0x00, 0x00});
-	else
-		rc = send_seq(priv, {0x80, XREG_POWER_DOWN, 0x00, 0x00});
-
-	priv->state = XC2028_SLEEP;
-
-	mutex_unlock(&priv->lock);
-
-	return rc;
-}
-
-static int xc2028_dvb_release(struct dvb_frontend *fe)
-{
-	struct xc2028_data *priv = fe->tuner_priv;
-
-	tuner_dbg("%s called\n", __func__);
-
-	mutex_lock(&xc2028_list_mutex);
-
-	/* only perform final cleanup if this is the last instance */
-	if (hybrid_tuner_report_instance_count(priv) == 1) {
-		free_firmware(priv);
-		kfree(priv->ctrl.fname);
-		priv->ctrl.fname = NULL;
-	}
-
-	if (priv)
-		hybrid_tuner_release_state(priv);
-
-	mutex_unlock(&xc2028_list_mutex);
-
-	fe->tuner_priv = NULL;
-
-	return 0;
-}
-
-static int xc2028_get_frequency(struct dvb_frontend *fe, u32 *frequency)
-{
-	struct xc2028_data *priv = fe->tuner_priv;
-	int rc;
-
-	tuner_dbg("%s called\n", __func__);
-
-	rc = check_device_status(priv);
-	if (rc < 0)
-		return rc;
-
-	*frequency = priv->frequency;
-
-	return 0;
-}
-
-static void load_firmware_cb(const struct firmware *fw,
-			     void *context)
-{
-	struct dvb_frontend *fe = context;
-	struct xc2028_data *priv = fe->tuner_priv;
-	int rc;
-
-	tuner_dbg("request_firmware_nowait(): %s\n", fw ? "OK" : "error");
-	if (!fw) {
-		tuner_err("Could not load firmware %s.\n", priv->fname);
-		priv->state = XC2028_NODEV;
-		return;
-	}
-
-	rc = load_all_firmwares(fe, fw);
-
-	release_firmware(fw);
-
-	if (rc < 0)
-		return;
-	priv->state = XC2028_SLEEP;
-}
-
-static int xc2028_set_config(struct dvb_frontend *fe, void *priv_cfg)
-{
-	struct xc2028_data *priv = fe->tuner_priv;
-	struct xc2028_ctrl *p    = priv_cfg;
-	int                 rc   = 0;
-
-	tuner_dbg("%s called\n", __func__);
-
-	mutex_lock(&priv->lock);
-
-	/*
-	 * Copy the config data.
-	 * For the firmware name, keep a local copy of the string,
-	 * in order to avoid troubles during device release.
-	 */
-	if (priv->ctrl.fname)
-		kfree(priv->ctrl.fname);
-	memcpy(&priv->ctrl, p, sizeof(priv->ctrl));
-	if (p->fname) {
-		priv->ctrl.fname = kstrdup(p->fname, GFP_KERNEL);
-		if (priv->ctrl.fname == NULL)
-			rc = -ENOMEM;
-	}
-
-	/*
-	 * If firmware name changed, frees firmware. As free_firmware will
-	 * reset the status to NO_FIRMWARE, this forces a new request_firmware
-	 */
-	if (!firmware_name[0] && p->fname &&
-	    priv->fname && strcmp(p->fname, priv->fname))
-		free_firmware(priv);
-
-	if (priv->ctrl.max_len < 9)
-		priv->ctrl.max_len = 13;
-
-	if (priv->state == XC2028_NO_FIRMWARE) {
-		if (!firmware_name[0])
-			priv->fname = priv->ctrl.fname;
-		else
-			priv->fname = firmware_name;
-
-		rc = request_firmware_nowait(THIS_MODULE, 1,
-					     priv->fname,
-					     priv->i2c_props.adap->dev.parent,
-					     GFP_KERNEL,
-					     fe, load_firmware_cb);
-		if (rc < 0) {
-			tuner_err("Failed to request firmware %s\n",
-				  priv->fname);
-			priv->state = XC2028_NODEV;
-		}
-		priv->state = XC2028_WAITING_FIRMWARE;
-	}
-	mutex_unlock(&priv->lock);
-
-	return rc;
-}
-
-static const struct dvb_tuner_ops xc2028_dvb_tuner_ops = {
-	.info = {
-		 .name = "Xceive XC3028",
-		 .frequency_min = 42000000,
-		 .frequency_max = 864000000,
-		 .frequency_step = 50000,
-		 },
-
-	.set_config	   = xc2028_set_config,
-	.set_analog_params = xc2028_set_analog_freq,
-	.release           = xc2028_dvb_release,
-	.get_frequency     = xc2028_get_frequency,
-	.get_rf_strength   = xc2028_signal,
-	.get_afc           = xc2028_get_afc,
-	.set_params        = xc2028_set_params,
-	.sleep             = xc2028_sleep,
-};
-
-struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe,
-				   struct xc2028_config *cfg)
-{
-	struct xc2028_data *priv;
-	int instance;
-
-	if (debug)
-		printk(KERN_DEBUG "xc2028: Xcv2028/3028 init called!\n");
-
-	if (NULL == cfg)
-		return NULL;
-
-	if (!fe) {
-		printk(KERN_ERR "xc2028: No frontend!\n");
-		return NULL;
-	}
-
-	mutex_lock(&xc2028_list_mutex);
-
-	instance = hybrid_tuner_request_state(struct xc2028_data, priv,
-					      hybrid_tuner_instance_list,
-					      cfg->i2c_adap, cfg->i2c_addr,
-					      "xc2028");
-	switch (instance) {
-	case 0:
-		/* memory allocation failure */
-		goto fail;
-		break;
-	case 1:
-		/* new tuner instance */
-		priv->ctrl.max_len = 13;
-
-		mutex_init(&priv->lock);
-
-		fe->tuner_priv = priv;
-		break;
-	case 2:
-		/* existing tuner instance */
-		fe->tuner_priv = priv;
-		break;
-	}
-
-	memcpy(&fe->ops.tuner_ops, &xc2028_dvb_tuner_ops,
-	       sizeof(xc2028_dvb_tuner_ops));
-
-	tuner_info("type set to %s\n", "XCeive xc2028/xc3028 tuner");
-
-	if (cfg->ctrl)
-		xc2028_set_config(fe, cfg->ctrl);
-
-	mutex_unlock(&xc2028_list_mutex);
-
-	return fe;
-fail:
-	mutex_unlock(&xc2028_list_mutex);
-
-	xc2028_dvb_release(fe);
-	return NULL;
-}
-
-EXPORT_SYMBOL(xc2028_attach);
-
-MODULE_DESCRIPTION("Xceive xc2028/xc3028 tuner driver");
-MODULE_AUTHOR("Michel Ludwig <michel.ludwig@gmail.com>");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
-MODULE_LICENSE("GPL");
-MODULE_FIRMWARE(XC2028_DEFAULT_FIRMWARE);
-MODULE_FIRMWARE(XC3028L_DEFAULT_FIRMWARE);
diff --git a/drivers/media/common/tuners/tuner-xc2028.h b/drivers/media/common/tuners/tuner-xc2028.h
deleted file mode 100644
index 9ebfb2d..0000000
--- a/drivers/media/common/tuners/tuner-xc2028.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/* tuner-xc2028
- *
- * Copyright (c) 2007-2008 Mauro Carvalho Chehab (mchehab@infradead.org)
- * This code is placed under the terms of the GNU General Public License v2
- */
-
-#ifndef __TUNER_XC2028_H__
-#define __TUNER_XC2028_H__
-
-#include "dvb_frontend.h"
-
-#define XC2028_DEFAULT_FIRMWARE "xc3028-v27.fw"
-#define XC3028L_DEFAULT_FIRMWARE "xc3028L-v36.fw"
-
-/*      Dmoduler		IF (kHz) */
-#define	XC3028_FE_DEFAULT	0		/* Don't load SCODE */
-#define XC3028_FE_LG60		6000
-#define	XC3028_FE_ATI638	6380
-#define	XC3028_FE_OREN538	5380
-#define	XC3028_FE_OREN36	3600
-#define	XC3028_FE_TOYOTA388	3880
-#define	XC3028_FE_TOYOTA794	7940
-#define	XC3028_FE_DIBCOM52	5200
-#define	XC3028_FE_ZARLINK456	4560
-#define	XC3028_FE_CHINA		5200
-
-enum firmware_type {
-	XC2028_AUTO = 0,        /* By default, auto-detects */
-	XC2028_D2633,
-	XC2028_D2620,
-};
-
-struct xc2028_ctrl {
-	char			*fname;
-	int			max_len;
-	int			msleep;
-	unsigned int		scode_table;
-	unsigned int		mts   :1;
-	unsigned int		input1:1;
-	unsigned int		vhfbw7:1;
-	unsigned int		uhfbw8:1;
-	unsigned int		disable_power_mgmt:1;
-	unsigned int            read_not_reliable:1;
-	unsigned int		demod;
-	enum firmware_type	type:2;
-};
-
-struct xc2028_config {
-	struct i2c_adapter *i2c_adap;
-	u8 		   i2c_addr;
-	struct xc2028_ctrl *ctrl;
-};
-
-/* xc2028 commands for callback */
-#define XC2028_TUNER_RESET	0
-#define XC2028_RESET_CLK	1
-#define XC2028_I2C_FLUSH	2
-
-#if defined(CONFIG_MEDIA_TUNER_XC2028) || (defined(CONFIG_MEDIA_TUNER_XC2028_MODULE) && defined(MODULE))
-extern struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe,
-					  struct xc2028_config *cfg);
-#else
-static inline struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe,
-						 struct xc2028_config *cfg)
-{
-	printk(KERN_INFO "%s: not probed - driver disabled by Kconfig\n",
-	       __func__);
-	return NULL;
-}
-#endif
-
-#endif /* __TUNER_XC2028_H__ */
diff --git a/drivers/media/common/tuners/xc4000.c b/drivers/media/common/tuners/xc4000.c
deleted file mode 100644
index 6839711..0000000
--- a/drivers/media/common/tuners/xc4000.c
+++ /dev/null
@@ -1,1758 +0,0 @@
-/*
- *  Driver for Xceive XC4000 "QAM/8VSB single chip tuner"
- *
- *  Copyright (c) 2007 Xceive Corporation
- *  Copyright (c) 2007 Steven Toth <stoth@linuxtv.org>
- *  Copyright (c) 2009 Devin Heitmueller <dheitmueller@kernellabs.com>
- *  Copyright (c) 2009 Davide Ferri <d.ferri@zero11.it>
- *  Copyright (c) 2010 Istvan Varga <istvan_v@mailbox.hu>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the 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/moduleparam.h>
-#include <linux/videodev2.h>
-#include <linux/delay.h>
-#include <linux/dvb/frontend.h>
-#include <linux/i2c.h>
-#include <linux/mutex.h>
-#include <asm/unaligned.h>
-
-#include "dvb_frontend.h"
-
-#include "xc4000.h"
-#include "tuner-i2c.h"
-#include "tuner-xc2028-types.h"
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Debugging level (0 to 2, default: 0 (off)).");
-
-static int no_poweroff;
-module_param(no_poweroff, int, 0644);
-MODULE_PARM_DESC(no_poweroff, "Power management (1: disabled, 2: enabled, "
-	"0 (default): use device-specific default mode).");
-
-static int audio_std;
-module_param(audio_std, int, 0644);
-MODULE_PARM_DESC(audio_std, "Audio standard. XC4000 audio decoder explicitly "
-	"needs to know what audio standard is needed for some video standards "
-	"with audio A2 or NICAM. The valid settings are a sum of:\n"
-	" 1: use NICAM/B or A2/B instead of NICAM/A or A2/A\n"
-	" 2: use A2 instead of NICAM or BTSC\n"
-	" 4: use SECAM/K3 instead of K1\n"
-	" 8: use PAL-D/K audio for SECAM-D/K\n"
-	"16: use FM radio input 1 instead of input 2\n"
-	"32: use mono audio (the lower three bits are ignored)");
-
-static char firmware_name[30];
-module_param_string(firmware_name, firmware_name, sizeof(firmware_name), 0);
-MODULE_PARM_DESC(firmware_name, "Firmware file name. Allows overriding the "
-	"default firmware name.");
-
-static DEFINE_MUTEX(xc4000_list_mutex);
-static LIST_HEAD(hybrid_tuner_instance_list);
-
-#define dprintk(level, fmt, arg...) if (debug >= level) \
-	printk(KERN_INFO "%s: " fmt, "xc4000", ## arg)
-
-/* struct for storing firmware table */
-struct firmware_description {
-	unsigned int  type;
-	v4l2_std_id   id;
-	__u16         int_freq;
-	unsigned char *ptr;
-	unsigned int  size;
-};
-
-struct firmware_properties {
-	unsigned int	type;
-	v4l2_std_id	id;
-	v4l2_std_id	std_req;
-	__u16		int_freq;
-	unsigned int	scode_table;
-	int		scode_nr;
-};
-
-struct xc4000_priv {
-	struct tuner_i2c_props i2c_props;
-	struct list_head hybrid_tuner_instance_list;
-	struct firmware_description *firm;
-	int	firm_size;
-	u32	if_khz;
-	u32	freq_hz;
-	u32	bandwidth;
-	u8	video_standard;
-	u8	rf_mode;
-	u8	default_pm;
-	u8	dvb_amplitude;
-	u8	set_smoothedcvbs;
-	u8	ignore_i2c_write_errors;
-	__u16	firm_version;
-	struct firmware_properties cur_fw;
-	__u16	hwmodel;
-	__u16	hwvers;
-	struct mutex	lock;
-};
-
-#define XC4000_AUDIO_STD_B		 1
-#define XC4000_AUDIO_STD_A2		 2
-#define XC4000_AUDIO_STD_K3		 4
-#define XC4000_AUDIO_STD_L		 8
-#define XC4000_AUDIO_STD_INPUT1		16
-#define XC4000_AUDIO_STD_MONO		32
-
-#define XC4000_DEFAULT_FIRMWARE "dvb-fe-xc4000-1.4.fw"
-
-/* Misc Defines */
-#define MAX_TV_STANDARD			24
-#define XC_MAX_I2C_WRITE_LENGTH		64
-#define XC_POWERED_DOWN			0x80000000U
-
-/* Signal Types */
-#define XC_RF_MODE_AIR			0
-#define XC_RF_MODE_CABLE		1
-
-/* Product id */
-#define XC_PRODUCT_ID_FW_NOT_LOADED	0x2000
-#define XC_PRODUCT_ID_XC4000		0x0FA0
-#define XC_PRODUCT_ID_XC4100		0x1004
-
-/* Registers (Write-only) */
-#define XREG_INIT         0x00
-#define XREG_VIDEO_MODE   0x01
-#define XREG_AUDIO_MODE   0x02
-#define XREG_RF_FREQ      0x03
-#define XREG_D_CODE       0x04
-#define XREG_DIRECTSITTING_MODE 0x05
-#define XREG_SEEK_MODE    0x06
-#define XREG_POWER_DOWN   0x08
-#define XREG_SIGNALSOURCE 0x0A
-#define XREG_SMOOTHEDCVBS 0x0E
-#define XREG_AMPLITUDE    0x10
-
-/* Registers (Read-only) */
-#define XREG_ADC_ENV      0x00
-#define XREG_QUALITY      0x01
-#define XREG_FRAME_LINES  0x02
-#define XREG_HSYNC_FREQ   0x03
-#define XREG_LOCK         0x04
-#define XREG_FREQ_ERROR   0x05
-#define XREG_SNR          0x06
-#define XREG_VERSION      0x07
-#define XREG_PRODUCT_ID   0x08
-#define XREG_SIGNAL_LEVEL 0x0A
-#define XREG_NOISE_LEVEL  0x0B
-
-/*
-   Basic firmware description. This will remain with
-   the driver for documentation purposes.
-
-   This represents an I2C firmware file encoded as a
-   string of unsigned char. Format is as follows:
-
-   char[0  ]=len0_MSB  -> len = len_MSB * 256 + len_LSB
-   char[1  ]=len0_LSB  -> length of first write transaction
-   char[2  ]=data0 -> first byte to be sent
-   char[3  ]=data1
-   char[4  ]=data2
-   char[   ]=...
-   char[M  ]=dataN  -> last byte to be sent
-   char[M+1]=len1_MSB  -> len = len_MSB * 256 + len_LSB
-   char[M+2]=len1_LSB  -> length of second write transaction
-   char[M+3]=data0
-   char[M+4]=data1
-   ...
-   etc.
-
-   The [len] value should be interpreted as follows:
-
-   len= len_MSB _ len_LSB
-   len=1111_1111_1111_1111   : End of I2C_SEQUENCE
-   len=0000_0000_0000_0000   : Reset command: Do hardware reset
-   len=0NNN_NNNN_NNNN_NNNN   : Normal transaction: number of bytes = {1:32767)
-   len=1WWW_WWWW_WWWW_WWWW   : Wait command: wait for {1:32767} ms
-
-   For the RESET and WAIT commands, the two following bytes will contain
-   immediately the length of the following transaction.
-*/
-
-struct XC_TV_STANDARD {
-	const char  *Name;
-	u16	    audio_mode;
-	u16	    video_mode;
-	u16	    int_freq;
-};
-
-/* Tuner standards */
-#define XC4000_MN_NTSC_PAL_BTSC		0
-#define XC4000_MN_NTSC_PAL_A2		1
-#define XC4000_MN_NTSC_PAL_EIAJ		2
-#define XC4000_MN_NTSC_PAL_Mono		3
-#define XC4000_BG_PAL_A2		4
-#define XC4000_BG_PAL_NICAM		5
-#define XC4000_BG_PAL_MONO		6
-#define XC4000_I_PAL_NICAM		7
-#define XC4000_I_PAL_NICAM_MONO		8
-#define XC4000_DK_PAL_A2		9
-#define XC4000_DK_PAL_NICAM		10
-#define XC4000_DK_PAL_MONO		11
-#define XC4000_DK_SECAM_A2DK1		12
-#define XC4000_DK_SECAM_A2LDK3		13
-#define XC4000_DK_SECAM_A2MONO		14
-#define XC4000_DK_SECAM_NICAM		15
-#define XC4000_L_SECAM_NICAM		16
-#define XC4000_LC_SECAM_NICAM		17
-#define XC4000_DTV6			18
-#define XC4000_DTV8			19
-#define XC4000_DTV7_8			20
-#define XC4000_DTV7			21
-#define XC4000_FM_Radio_INPUT2		22
-#define XC4000_FM_Radio_INPUT1		23
-
-static struct XC_TV_STANDARD xc4000_standard[MAX_TV_STANDARD] = {
-	{"M/N-NTSC/PAL-BTSC",	0x0000, 0x80A0, 4500},
-	{"M/N-NTSC/PAL-A2",	0x0000, 0x80A0, 4600},
-	{"M/N-NTSC/PAL-EIAJ",	0x0040, 0x80A0, 4500},
-	{"M/N-NTSC/PAL-Mono",	0x0078, 0x80A0, 4500},
-	{"B/G-PAL-A2",		0x0000, 0x8159, 5640},
-	{"B/G-PAL-NICAM",	0x0004, 0x8159, 5740},
-	{"B/G-PAL-MONO",	0x0078, 0x8159, 5500},
-	{"I-PAL-NICAM",		0x0080, 0x8049, 6240},
-	{"I-PAL-NICAM-MONO",	0x0078, 0x8049, 6000},
-	{"D/K-PAL-A2",		0x0000, 0x8049, 6380},
-	{"D/K-PAL-NICAM",	0x0080, 0x8049, 6200},
-	{"D/K-PAL-MONO",	0x0078, 0x8049, 6500},
-	{"D/K-SECAM-A2 DK1",	0x0000, 0x8049, 6340},
-	{"D/K-SECAM-A2 L/DK3",	0x0000, 0x8049, 6000},
-	{"D/K-SECAM-A2 MONO",	0x0078, 0x8049, 6500},
-	{"D/K-SECAM-NICAM",	0x0080, 0x8049, 6200},
-	{"L-SECAM-NICAM",	0x8080, 0x0009, 6200},
-	{"L'-SECAM-NICAM",	0x8080, 0x4009, 6200},
-	{"DTV6",		0x00C0, 0x8002,    0},
-	{"DTV8",		0x00C0, 0x800B,    0},
-	{"DTV7/8",		0x00C0, 0x801B,    0},
-	{"DTV7",		0x00C0, 0x8007,    0},
-	{"FM Radio-INPUT2",	0x0008, 0x9800, 10700},
-	{"FM Radio-INPUT1",	0x0008, 0x9000, 10700}
-};
-
-static int xc4000_readreg(struct xc4000_priv *priv, u16 reg, u16 *val);
-static int xc4000_tuner_reset(struct dvb_frontend *fe);
-static void xc_debug_dump(struct xc4000_priv *priv);
-
-static int xc_send_i2c_data(struct xc4000_priv *priv, u8 *buf, int len)
-{
-	struct i2c_msg msg = { .addr = priv->i2c_props.addr,
-			       .flags = 0, .buf = buf, .len = len };
-	if (i2c_transfer(priv->i2c_props.adap, &msg, 1) != 1) {
-		if (priv->ignore_i2c_write_errors == 0) {
-			printk(KERN_ERR "xc4000: I2C write failed (len=%i)\n",
-			       len);
-			if (len == 4) {
-				printk(KERN_ERR "bytes %02x %02x %02x %02x\n", buf[0],
-				       buf[1], buf[2], buf[3]);
-			}
-			return -EREMOTEIO;
-		}
-	}
-	return 0;
-}
-
-static int xc4000_tuner_reset(struct dvb_frontend *fe)
-{
-	struct xc4000_priv *priv = fe->tuner_priv;
-	int ret;
-
-	dprintk(1, "%s()\n", __func__);
-
-	if (fe->callback) {
-		ret = fe->callback(((fe->dvb) && (fe->dvb->priv)) ?
-					   fe->dvb->priv :
-					   priv->i2c_props.adap->algo_data,
-					   DVB_FRONTEND_COMPONENT_TUNER,
-					   XC4000_TUNER_RESET, 0);
-		if (ret) {
-			printk(KERN_ERR "xc4000: reset failed\n");
-			return -EREMOTEIO;
-		}
-	} else {
-		printk(KERN_ERR "xc4000: no tuner reset callback function, "
-				"fatal\n");
-		return -EINVAL;
-	}
-	return 0;
-}
-
-static int xc_write_reg(struct xc4000_priv *priv, u16 regAddr, u16 i2cData)
-{
-	u8 buf[4];
-	int result;
-
-	buf[0] = (regAddr >> 8) & 0xFF;
-	buf[1] = regAddr & 0xFF;
-	buf[2] = (i2cData >> 8) & 0xFF;
-	buf[3] = i2cData & 0xFF;
-	result = xc_send_i2c_data(priv, buf, 4);
-
-	return result;
-}
-
-static int xc_load_i2c_sequence(struct dvb_frontend *fe, const u8 *i2c_sequence)
-{
-	struct xc4000_priv *priv = fe->tuner_priv;
-
-	int i, nbytes_to_send, result;
-	unsigned int len, pos, index;
-	u8 buf[XC_MAX_I2C_WRITE_LENGTH];
-
-	index = 0;
-	while ((i2c_sequence[index] != 0xFF) ||
-		(i2c_sequence[index + 1] != 0xFF)) {
-		len = i2c_sequence[index] * 256 + i2c_sequence[index+1];
-		if (len == 0x0000) {
-			/* RESET command */
-			/* NOTE: this is ignored, as the reset callback was */
-			/* already called by check_firmware() */
-			index += 2;
-		} else if (len & 0x8000) {
-			/* WAIT command */
-			msleep(len & 0x7FFF);
-			index += 2;
-		} else {
-			/* Send i2c data whilst ensuring individual transactions
-			 * do not exceed XC_MAX_I2C_WRITE_LENGTH bytes.
-			 */
-			index += 2;
-			buf[0] = i2c_sequence[index];
-			buf[1] = i2c_sequence[index + 1];
-			pos = 2;
-			while (pos < len) {
-				if ((len - pos) > XC_MAX_I2C_WRITE_LENGTH - 2)
-					nbytes_to_send =
-						XC_MAX_I2C_WRITE_LENGTH;
-				else
-					nbytes_to_send = (len - pos + 2);
-				for (i = 2; i < nbytes_to_send; i++) {
-					buf[i] = i2c_sequence[index + pos +
-						i - 2];
-				}
-				result = xc_send_i2c_data(priv, buf,
-					nbytes_to_send);
-
-				if (result != 0)
-					return result;
-
-				pos += nbytes_to_send - 2;
-			}
-			index += len;
-		}
-	}
-	return 0;
-}
-
-static int xc_set_tv_standard(struct xc4000_priv *priv,
-	u16 video_mode, u16 audio_mode)
-{
-	int ret;
-	dprintk(1, "%s(0x%04x,0x%04x)\n", __func__, video_mode, audio_mode);
-	dprintk(1, "%s() Standard = %s\n",
-		__func__,
-		xc4000_standard[priv->video_standard].Name);
-
-	/* Don't complain when the request fails because of i2c stretching */
-	priv->ignore_i2c_write_errors = 1;
-
-	ret = xc_write_reg(priv, XREG_VIDEO_MODE, video_mode);
-	if (ret == 0)
-		ret = xc_write_reg(priv, XREG_AUDIO_MODE, audio_mode);
-
-	priv->ignore_i2c_write_errors = 0;
-
-	return ret;
-}
-
-static int xc_set_signal_source(struct xc4000_priv *priv, u16 rf_mode)
-{
-	dprintk(1, "%s(%d) Source = %s\n", __func__, rf_mode,
-		rf_mode == XC_RF_MODE_AIR ? "ANTENNA" : "CABLE");
-
-	if ((rf_mode != XC_RF_MODE_AIR) && (rf_mode != XC_RF_MODE_CABLE)) {
-		rf_mode = XC_RF_MODE_CABLE;
-		printk(KERN_ERR
-			"%s(), Invalid mode, defaulting to CABLE",
-			__func__);
-	}
-	return xc_write_reg(priv, XREG_SIGNALSOURCE, rf_mode);
-}
-
-static const struct dvb_tuner_ops xc4000_tuner_ops;
-
-static int xc_set_rf_frequency(struct xc4000_priv *priv, u32 freq_hz)
-{
-	u16 freq_code;
-
-	dprintk(1, "%s(%u)\n", __func__, freq_hz);
-
-	if ((freq_hz > xc4000_tuner_ops.info.frequency_max) ||
-	    (freq_hz < xc4000_tuner_ops.info.frequency_min))
-		return -EINVAL;
-
-	freq_code = (u16)(freq_hz / 15625);
-
-	/* WAS: Starting in firmware version 1.1.44, Xceive recommends using the
-	   FINERFREQ for all normal tuning (the doc indicates reg 0x03 should
-	   only be used for fast scanning for channel lock) */
-	/* WAS: XREG_FINERFREQ */
-	return xc_write_reg(priv, XREG_RF_FREQ, freq_code);
-}
-
-static int xc_get_adc_envelope(struct xc4000_priv *priv, u16 *adc_envelope)
-{
-	return xc4000_readreg(priv, XREG_ADC_ENV, adc_envelope);
-}
-
-static int xc_get_frequency_error(struct xc4000_priv *priv, u32 *freq_error_hz)
-{
-	int result;
-	u16 regData;
-	u32 tmp;
-
-	result = xc4000_readreg(priv, XREG_FREQ_ERROR, &regData);
-	if (result != 0)
-		return result;
-
-	tmp = (u32)regData & 0xFFFFU;
-	tmp = (tmp < 0x8000U ? tmp : 0x10000U - tmp);
-	(*freq_error_hz) = tmp * 15625;
-	return result;
-}
-
-static int xc_get_lock_status(struct xc4000_priv *priv, u16 *lock_status)
-{
-	return xc4000_readreg(priv, XREG_LOCK, lock_status);
-}
-
-static int xc_get_version(struct xc4000_priv *priv,
-	u8 *hw_majorversion, u8 *hw_minorversion,
-	u8 *fw_majorversion, u8 *fw_minorversion)
-{
-	u16 data;
-	int result;
-
-	result = xc4000_readreg(priv, XREG_VERSION, &data);
-	if (result != 0)
-		return result;
-
-	(*hw_majorversion) = (data >> 12) & 0x0F;
-	(*hw_minorversion) = (data >>  8) & 0x0F;
-	(*fw_majorversion) = (data >>  4) & 0x0F;
-	(*fw_minorversion) = data & 0x0F;
-
-	return 0;
-}
-
-static int xc_get_hsync_freq(struct xc4000_priv *priv, u32 *hsync_freq_hz)
-{
-	u16 regData;
-	int result;
-
-	result = xc4000_readreg(priv, XREG_HSYNC_FREQ, &regData);
-	if (result != 0)
-		return result;
-
-	(*hsync_freq_hz) = ((regData & 0x0fff) * 763)/100;
-	return result;
-}
-
-static int xc_get_frame_lines(struct xc4000_priv *priv, u16 *frame_lines)
-{
-	return xc4000_readreg(priv, XREG_FRAME_LINES, frame_lines);
-}
-
-static int xc_get_quality(struct xc4000_priv *priv, u16 *quality)
-{
-	return xc4000_readreg(priv, XREG_QUALITY, quality);
-}
-
-static int xc_get_signal_level(struct xc4000_priv *priv, u16 *signal)
-{
-	return xc4000_readreg(priv, XREG_SIGNAL_LEVEL, signal);
-}
-
-static int xc_get_noise_level(struct xc4000_priv *priv, u16 *noise)
-{
-	return xc4000_readreg(priv, XREG_NOISE_LEVEL, noise);
-}
-
-static u16 xc_wait_for_lock(struct xc4000_priv *priv)
-{
-	u16	lock_state = 0;
-	int	watchdog_count = 40;
-
-	while ((lock_state == 0) && (watchdog_count > 0)) {
-		xc_get_lock_status(priv, &lock_state);
-		if (lock_state != 1) {
-			msleep(5);
-			watchdog_count--;
-		}
-	}
-	return lock_state;
-}
-
-static int xc_tune_channel(struct xc4000_priv *priv, u32 freq_hz)
-{
-	int	found = 1;
-	int	result;
-
-	dprintk(1, "%s(%u)\n", __func__, freq_hz);
-
-	/* Don't complain when the request fails because of i2c stretching */
-	priv->ignore_i2c_write_errors = 1;
-	result = xc_set_rf_frequency(priv, freq_hz);
-	priv->ignore_i2c_write_errors = 0;
-
-	if (result != 0)
-		return 0;
-
-	/* wait for lock only in analog TV mode */
-	if ((priv->cur_fw.type & (FM | DTV6 | DTV7 | DTV78 | DTV8)) == 0) {
-		if (xc_wait_for_lock(priv) != 1)
-			found = 0;
-	}
-
-	/* Wait for stats to stabilize.
-	 * Frame Lines needs two frame times after initial lock
-	 * before it is valid.
-	 */
-	msleep(debug ? 100 : 10);
-
-	if (debug)
-		xc_debug_dump(priv);
-
-	return found;
-}
-
-static int xc4000_readreg(struct xc4000_priv *priv, u16 reg, u16 *val)
-{
-	u8 buf[2] = { reg >> 8, reg & 0xff };
-	u8 bval[2] = { 0, 0 };
-	struct i2c_msg msg[2] = {
-		{ .addr = priv->i2c_props.addr,
-			.flags = 0, .buf = &buf[0], .len = 2 },
-		{ .addr = priv->i2c_props.addr,
-			.flags = I2C_M_RD, .buf = &bval[0], .len = 2 },
-	};
-
-	if (i2c_transfer(priv->i2c_props.adap, msg, 2) != 2) {
-		printk(KERN_ERR "xc4000: I2C read failed\n");
-		return -EREMOTEIO;
-	}
-
-	*val = (bval[0] << 8) | bval[1];
-	return 0;
-}
-
-#define dump_firm_type(t)	dump_firm_type_and_int_freq(t, 0)
-static void dump_firm_type_and_int_freq(unsigned int type, u16 int_freq)
-{
-	 if (type & BASE)
-		printk(KERN_CONT "BASE ");
-	 if (type & INIT1)
-		printk(KERN_CONT "INIT1 ");
-	 if (type & F8MHZ)
-		printk(KERN_CONT "F8MHZ ");
-	 if (type & MTS)
-		printk(KERN_CONT "MTS ");
-	 if (type & D2620)
-		printk(KERN_CONT "D2620 ");
-	 if (type & D2633)
-		printk(KERN_CONT "D2633 ");
-	 if (type & DTV6)
-		printk(KERN_CONT "DTV6 ");
-	 if (type & QAM)
-		printk(KERN_CONT "QAM ");
-	 if (type & DTV7)
-		printk(KERN_CONT "DTV7 ");
-	 if (type & DTV78)
-		printk(KERN_CONT "DTV78 ");
-	 if (type & DTV8)
-		printk(KERN_CONT "DTV8 ");
-	 if (type & FM)
-		printk(KERN_CONT "FM ");
-	 if (type & INPUT1)
-		printk(KERN_CONT "INPUT1 ");
-	 if (type & LCD)
-		printk(KERN_CONT "LCD ");
-	 if (type & NOGD)
-		printk(KERN_CONT "NOGD ");
-	 if (type & MONO)
-		printk(KERN_CONT "MONO ");
-	 if (type & ATSC)
-		printk(KERN_CONT "ATSC ");
-	 if (type & IF)
-		printk(KERN_CONT "IF ");
-	 if (type & LG60)
-		printk(KERN_CONT "LG60 ");
-	 if (type & ATI638)
-		printk(KERN_CONT "ATI638 ");
-	 if (type & OREN538)
-		printk(KERN_CONT "OREN538 ");
-	 if (type & OREN36)
-		printk(KERN_CONT "OREN36 ");
-	 if (type & TOYOTA388)
-		printk(KERN_CONT "TOYOTA388 ");
-	 if (type & TOYOTA794)
-		printk(KERN_CONT "TOYOTA794 ");
-	 if (type & DIBCOM52)
-		printk(KERN_CONT "DIBCOM52 ");
-	 if (type & ZARLINK456)
-		printk(KERN_CONT "ZARLINK456 ");
-	 if (type & CHINA)
-		printk(KERN_CONT "CHINA ");
-	 if (type & F6MHZ)
-		printk(KERN_CONT "F6MHZ ");
-	 if (type & INPUT2)
-		printk(KERN_CONT "INPUT2 ");
-	 if (type & SCODE)
-		printk(KERN_CONT "SCODE ");
-	 if (type & HAS_IF)
-		printk(KERN_CONT "HAS_IF_%d ", int_freq);
-}
-
-static int seek_firmware(struct dvb_frontend *fe, unsigned int type,
-			 v4l2_std_id *id)
-{
-	struct xc4000_priv *priv = fe->tuner_priv;
-	int		i, best_i = -1;
-	unsigned int	best_nr_diffs = 255U;
-
-	if (!priv->firm) {
-		printk(KERN_ERR "Error! firmware not loaded\n");
-		return -EINVAL;
-	}
-
-	if (((type & ~SCODE) == 0) && (*id == 0))
-		*id = V4L2_STD_PAL;
-
-	/* Seek for generic video standard match */
-	for (i = 0; i < priv->firm_size; i++) {
-		v4l2_std_id	id_diff_mask =
-			(priv->firm[i].id ^ (*id)) & (*id);
-		unsigned int	type_diff_mask =
-			(priv->firm[i].type ^ type)
-			& (BASE_TYPES | DTV_TYPES | LCD | NOGD | MONO | SCODE);
-		unsigned int	nr_diffs;
-
-		if (type_diff_mask
-		    & (BASE | INIT1 | FM | DTV6 | DTV7 | DTV78 | DTV8 | SCODE))
-			continue;
-
-		nr_diffs = hweight64(id_diff_mask) + hweight32(type_diff_mask);
-		if (!nr_diffs)	/* Supports all the requested standards */
-			goto found;
-
-		if (nr_diffs < best_nr_diffs) {
-			best_nr_diffs = nr_diffs;
-			best_i = i;
-		}
-	}
-
-	/* FIXME: Would make sense to seek for type "hint" match ? */
-	if (best_i < 0) {
-		i = -ENOENT;
-		goto ret;
-	}
-
-	if (best_nr_diffs > 0U) {
-		printk(KERN_WARNING
-		       "Selecting best matching firmware (%u bits differ) for "
-		       "type=(%x), id %016llx:\n",
-		       best_nr_diffs, type, (unsigned long long)*id);
-		i = best_i;
-	}
-
-found:
-	*id = priv->firm[i].id;
-
-ret:
-	if (debug) {
-		printk(KERN_DEBUG "%s firmware for type=",
-		       (i < 0) ? "Can't find" : "Found");
-		dump_firm_type(type);
-		printk(KERN_DEBUG "(%x), id %016llx.\n", type, (unsigned long long)*id);
-	}
-	return i;
-}
-
-static int load_firmware(struct dvb_frontend *fe, unsigned int type,
-			 v4l2_std_id *id)
-{
-	struct xc4000_priv *priv = fe->tuner_priv;
-	int                pos, rc;
-	unsigned char      *p;
-
-	pos = seek_firmware(fe, type, id);
-	if (pos < 0)
-		return pos;
-
-	p = priv->firm[pos].ptr;
-
-	/* Don't complain when the request fails because of i2c stretching */
-	priv->ignore_i2c_write_errors = 1;
-
-	rc = xc_load_i2c_sequence(fe, p);
-
-	priv->ignore_i2c_write_errors = 0;
-
-	return rc;
-}
-
-static int xc4000_fwupload(struct dvb_frontend *fe)
-{
-	struct xc4000_priv *priv = fe->tuner_priv;
-	const struct firmware *fw   = NULL;
-	const unsigned char   *p, *endp;
-	int                   rc = 0;
-	int		      n, n_array;
-	char		      name[33];
-	const char	      *fname;
-
-	if (firmware_name[0] != '\0')
-		fname = firmware_name;
-	else
-		fname = XC4000_DEFAULT_FIRMWARE;
-
-	dprintk(1, "Reading firmware %s\n", fname);
-	rc = request_firmware(&fw, fname, priv->i2c_props.adap->dev.parent);
-	if (rc < 0) {
-		if (rc == -ENOENT)
-			printk(KERN_ERR "Error: firmware %s not found.\n", fname);
-		else
-			printk(KERN_ERR "Error %d while requesting firmware %s\n",
-			       rc, fname);
-
-		return rc;
-	}
-	p = fw->data;
-	endp = p + fw->size;
-
-	if (fw->size < sizeof(name) - 1 + 2 + 2) {
-		printk(KERN_ERR "Error: firmware file %s has invalid size!\n",
-		       fname);
-		goto corrupt;
-	}
-
-	memcpy(name, p, sizeof(name) - 1);
-	name[sizeof(name) - 1] = '\0';
-	p += sizeof(name) - 1;
-
-	priv->firm_version = get_unaligned_le16(p);
-	p += 2;
-
-	n_array = get_unaligned_le16(p);
-	p += 2;
-
-	dprintk(1, "Loading %d firmware images from %s, type: %s, ver %d.%d\n",
-		n_array, fname, name,
-		priv->firm_version >> 8, priv->firm_version & 0xff);
-
-	priv->firm = kcalloc(n_array, sizeof(*priv->firm), GFP_KERNEL);
-	if (priv->firm == NULL) {
-		printk(KERN_ERR "Not enough memory to load firmware file.\n");
-		rc = -ENOMEM;
-		goto done;
-	}
-	priv->firm_size = n_array;
-
-	n = -1;
-	while (p < endp) {
-		__u32 type, size;
-		v4l2_std_id id;
-		__u16 int_freq = 0;
-
-		n++;
-		if (n >= n_array) {
-			printk(KERN_ERR "More firmware images in file than "
-			       "were expected!\n");
-			goto corrupt;
-		}
-
-		/* Checks if there's enough bytes to read */
-		if (endp - p < sizeof(type) + sizeof(id) + sizeof(size))
-			goto header;
-
-		type = get_unaligned_le32(p);
-		p += sizeof(type);
-
-		id = get_unaligned_le64(p);
-		p += sizeof(id);
-
-		if (type & HAS_IF) {
-			int_freq = get_unaligned_le16(p);
-			p += sizeof(int_freq);
-			if (endp - p < sizeof(size))
-				goto header;
-		}
-
-		size = get_unaligned_le32(p);
-		p += sizeof(size);
-
-		if (!size || size > endp - p) {
-			printk(KERN_ERR "Firmware type (%x), id %llx is corrupted (size=%d, expected %d)\n",
-			       type, (unsigned long long)id,
-			       (unsigned)(endp - p), size);
-			goto corrupt;
-		}
-
-		priv->firm[n].ptr = kzalloc(size, GFP_KERNEL);
-		if (priv->firm[n].ptr == NULL) {
-			printk(KERN_ERR "Not enough memory to load firmware file.\n");
-			rc = -ENOMEM;
-			goto done;
-		}
-
-		if (debug) {
-			printk(KERN_DEBUG "Reading firmware type ");
-			dump_firm_type_and_int_freq(type, int_freq);
-			printk(KERN_DEBUG "(%x), id %llx, size=%d.\n",
-			       type, (unsigned long long)id, size);
-		}
-
-		memcpy(priv->firm[n].ptr, p, size);
-		priv->firm[n].type = type;
-		priv->firm[n].id   = id;
-		priv->firm[n].size = size;
-		priv->firm[n].int_freq = int_freq;
-
-		p += size;
-	}
-
-	if (n + 1 != priv->firm_size) {
-		printk(KERN_ERR "Firmware file is incomplete!\n");
-		goto corrupt;
-	}
-
-	goto done;
-
-header:
-	printk(KERN_ERR "Firmware header is incomplete!\n");
-corrupt:
-	rc = -EINVAL;
-	printk(KERN_ERR "Error: firmware file is corrupted!\n");
-
-done:
-	release_firmware(fw);
-	if (rc == 0)
-		dprintk(1, "Firmware files loaded.\n");
-
-	return rc;
-}
-
-static int load_scode(struct dvb_frontend *fe, unsigned int type,
-			 v4l2_std_id *id, __u16 int_freq, int scode)
-{
-	struct xc4000_priv *priv = fe->tuner_priv;
-	int		pos, rc;
-	unsigned char	*p;
-	u8		scode_buf[13];
-	u8		indirect_mode[5];
-
-	dprintk(1, "%s called int_freq=%d\n", __func__, int_freq);
-
-	if (!int_freq) {
-		pos = seek_firmware(fe, type, id);
-		if (pos < 0)
-			return pos;
-	} else {
-		for (pos = 0; pos < priv->firm_size; pos++) {
-			if ((priv->firm[pos].int_freq == int_freq) &&
-			    (priv->firm[pos].type & HAS_IF))
-				break;
-		}
-		if (pos == priv->firm_size)
-			return -ENOENT;
-	}
-
-	p = priv->firm[pos].ptr;
-
-	if (priv->firm[pos].size != 12 * 16 || scode >= 16)
-		return -EINVAL;
-	p += 12 * scode;
-
-	if (debug) {
-		tuner_info("Loading SCODE for type=");
-		dump_firm_type_and_int_freq(priv->firm[pos].type,
-					    priv->firm[pos].int_freq);
-		printk(KERN_CONT "(%x), id %016llx.\n", priv->firm[pos].type,
-		       (unsigned long long)*id);
-	}
-
-	scode_buf[0] = 0x00;
-	memcpy(&scode_buf[1], p, 12);
-
-	/* Enter direct-mode */
-	rc = xc_write_reg(priv, XREG_DIRECTSITTING_MODE, 0);
-	if (rc < 0) {
-		printk(KERN_ERR "failed to put device into direct mode!\n");
-		return -EIO;
-	}
-
-	rc = xc_send_i2c_data(priv, scode_buf, 13);
-	if (rc != 0) {
-		/* Even if the send failed, make sure we set back to indirect
-		   mode */
-		printk(KERN_ERR "Failed to set scode %d\n", rc);
-	}
-
-	/* Switch back to indirect-mode */
-	memset(indirect_mode, 0, sizeof(indirect_mode));
-	indirect_mode[4] = 0x88;
-	xc_send_i2c_data(priv, indirect_mode, sizeof(indirect_mode));
-	msleep(10);
-
-	return 0;
-}
-
-static int check_firmware(struct dvb_frontend *fe, unsigned int type,
-			  v4l2_std_id std, __u16 int_freq)
-{
-	struct xc4000_priv         *priv = fe->tuner_priv;
-	struct firmware_properties new_fw;
-	int			   rc = 0, is_retry = 0;
-	u16			   hwmodel;
-	v4l2_std_id		   std0;
-	u8			   hw_major, hw_minor, fw_major, fw_minor;
-
-	dprintk(1, "%s called\n", __func__);
-
-	if (!priv->firm) {
-		rc = xc4000_fwupload(fe);
-		if (rc < 0)
-			return rc;
-	}
-
-retry:
-	new_fw.type = type;
-	new_fw.id = std;
-	new_fw.std_req = std;
-	new_fw.scode_table = SCODE;
-	new_fw.scode_nr = 0;
-	new_fw.int_freq = int_freq;
-
-	dprintk(1, "checking firmware, user requested type=");
-	if (debug) {
-		dump_firm_type(new_fw.type);
-		printk(KERN_CONT "(%x), id %016llx, ", new_fw.type,
-		       (unsigned long long)new_fw.std_req);
-		if (!int_freq)
-			printk(KERN_CONT "scode_tbl ");
-		else
-			printk(KERN_CONT "int_freq %d, ", new_fw.int_freq);
-		printk(KERN_CONT "scode_nr %d\n", new_fw.scode_nr);
-	}
-
-	/* No need to reload base firmware if it matches */
-	if (priv->cur_fw.type & BASE) {
-		dprintk(1, "BASE firmware not changed.\n");
-		goto skip_base;
-	}
-
-	/* Updating BASE - forget about all currently loaded firmware */
-	memset(&priv->cur_fw, 0, sizeof(priv->cur_fw));
-
-	/* Reset is needed before loading firmware */
-	rc = xc4000_tuner_reset(fe);
-	if (rc < 0)
-		goto fail;
-
-	/* BASE firmwares are all std0 */
-	std0 = 0;
-	rc = load_firmware(fe, BASE, &std0);
-	if (rc < 0) {
-		printk(KERN_ERR "Error %d while loading base firmware\n", rc);
-		goto fail;
-	}
-
-	/* Load INIT1, if needed */
-	dprintk(1, "Load init1 firmware, if exists\n");
-
-	rc = load_firmware(fe, BASE | INIT1, &std0);
-	if (rc == -ENOENT)
-		rc = load_firmware(fe, BASE | INIT1, &std0);
-	if (rc < 0 && rc != -ENOENT) {
-		tuner_err("Error %d while loading init1 firmware\n",
-			  rc);
-		goto fail;
-	}
-
-skip_base:
-	/*
-	 * No need to reload standard specific firmware if base firmware
-	 * was not reloaded and requested video standards have not changed.
-	 */
-	if (priv->cur_fw.type == (BASE | new_fw.type) &&
-	    priv->cur_fw.std_req == std) {
-		dprintk(1, "Std-specific firmware already loaded.\n");
-		goto skip_std_specific;
-	}
-
-	/* Reloading std-specific firmware forces a SCODE update */
-	priv->cur_fw.scode_table = 0;
-
-	/* Load the standard firmware */
-	rc = load_firmware(fe, new_fw.type, &new_fw.id);
-
-	if (rc < 0)
-		goto fail;
-
-skip_std_specific:
-	if (priv->cur_fw.scode_table == new_fw.scode_table &&
-	    priv->cur_fw.scode_nr == new_fw.scode_nr) {
-		dprintk(1, "SCODE firmware already loaded.\n");
-		goto check_device;
-	}
-
-	/* Load SCODE firmware, if exists */
-	rc = load_scode(fe, new_fw.type | new_fw.scode_table, &new_fw.id,
-			new_fw.int_freq, new_fw.scode_nr);
-	if (rc != 0)
-		dprintk(1, "load scode failed %d\n", rc);
-
-check_device:
-	rc = xc4000_readreg(priv, XREG_PRODUCT_ID, &hwmodel);
-
-	if (xc_get_version(priv, &hw_major, &hw_minor, &fw_major,
-			   &fw_minor) != 0) {
-		printk(KERN_ERR "Unable to read tuner registers.\n");
-		goto fail;
-	}
-
-	dprintk(1, "Device is Xceive %d version %d.%d, "
-		"firmware version %d.%d\n",
-		hwmodel, hw_major, hw_minor, fw_major, fw_minor);
-
-	/* Check firmware version against what we downloaded. */
-	if (priv->firm_version != ((fw_major << 8) | fw_minor)) {
-		printk(KERN_WARNING
-		       "Incorrect readback of firmware version %d.%d.\n",
-		       fw_major, fw_minor);
-		goto fail;
-	}
-
-	/* Check that the tuner hardware model remains consistent over time. */
-	if (priv->hwmodel == 0 &&
-	    (hwmodel == XC_PRODUCT_ID_XC4000 ||
-	     hwmodel == XC_PRODUCT_ID_XC4100)) {
-		priv->hwmodel = hwmodel;
-		priv->hwvers = (hw_major << 8) | hw_minor;
-	} else if (priv->hwmodel == 0 || priv->hwmodel != hwmodel ||
-		   priv->hwvers != ((hw_major << 8) | hw_minor)) {
-		printk(KERN_WARNING
-		       "Read invalid device hardware information - tuner "
-		       "hung?\n");
-		goto fail;
-	}
-
-	memcpy(&priv->cur_fw, &new_fw, sizeof(priv->cur_fw));
-
-	/*
-	 * By setting BASE in cur_fw.type only after successfully loading all
-	 * firmwares, we can:
-	 * 1. Identify that BASE firmware with type=0 has been loaded;
-	 * 2. Tell whether BASE firmware was just changed the next time through.
-	 */
-	priv->cur_fw.type |= BASE;
-
-	return 0;
-
-fail:
-	memset(&priv->cur_fw, 0, sizeof(priv->cur_fw));
-	if (!is_retry) {
-		msleep(50);
-		is_retry = 1;
-		dprintk(1, "Retrying firmware load\n");
-		goto retry;
-	}
-
-	if (rc == -ENOENT)
-		rc = -EINVAL;
-	return rc;
-}
-
-static void xc_debug_dump(struct xc4000_priv *priv)
-{
-	u16	adc_envelope;
-	u32	freq_error_hz = 0;
-	u16	lock_status;
-	u32	hsync_freq_hz = 0;
-	u16	frame_lines;
-	u16	quality;
-	u16	signal = 0;
-	u16	noise = 0;
-	u8	hw_majorversion = 0, hw_minorversion = 0;
-	u8	fw_majorversion = 0, fw_minorversion = 0;
-
-	xc_get_adc_envelope(priv, &adc_envelope);
-	dprintk(1, "*** ADC envelope (0-1023) = %d\n", adc_envelope);
-
-	xc_get_frequency_error(priv, &freq_error_hz);
-	dprintk(1, "*** Frequency error = %d Hz\n", freq_error_hz);
-
-	xc_get_lock_status(priv, &lock_status);
-	dprintk(1, "*** Lock status (0-Wait, 1-Locked, 2-No-signal) = %d\n",
-		lock_status);
-
-	xc_get_version(priv, &hw_majorversion, &hw_minorversion,
-		       &fw_majorversion, &fw_minorversion);
-	dprintk(1, "*** HW: V%02x.%02x, FW: V%02x.%02x\n",
-		hw_majorversion, hw_minorversion,
-		fw_majorversion, fw_minorversion);
-
-	if (priv->video_standard < XC4000_DTV6) {
-		xc_get_hsync_freq(priv, &hsync_freq_hz);
-		dprintk(1, "*** Horizontal sync frequency = %d Hz\n",
-			hsync_freq_hz);
-
-		xc_get_frame_lines(priv, &frame_lines);
-		dprintk(1, "*** Frame lines = %d\n", frame_lines);
-	}
-
-	xc_get_quality(priv, &quality);
-	dprintk(1, "*** Quality (0:<8dB, 7:>56dB) = %d\n", quality);
-
-	xc_get_signal_level(priv, &signal);
-	dprintk(1, "*** Signal level = -%ddB (%d)\n", signal >> 8, signal);
-
-	xc_get_noise_level(priv, &noise);
-	dprintk(1, "*** Noise level = %ddB (%d)\n", noise >> 8, noise);
-}
-
-static int xc4000_set_params(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	u32 delsys = c->delivery_system;
-	u32 bw = c->bandwidth_hz;
-	struct xc4000_priv *priv = fe->tuner_priv;
-	unsigned int type;
-	int	ret = -EREMOTEIO;
-
-	dprintk(1, "%s() frequency=%d (Hz)\n", __func__, c->frequency);
-
-	mutex_lock(&priv->lock);
-
-	switch (delsys) {
-	case SYS_ATSC:
-		dprintk(1, "%s() VSB modulation\n", __func__);
-		priv->rf_mode = XC_RF_MODE_AIR;
-		priv->freq_hz = c->frequency - 1750000;
-		priv->video_standard = XC4000_DTV6;
-		type = DTV6;
-		break;
-	case SYS_DVBC_ANNEX_B:
-		dprintk(1, "%s() QAM modulation\n", __func__);
-		priv->rf_mode = XC_RF_MODE_CABLE;
-		priv->freq_hz = c->frequency - 1750000;
-		priv->video_standard = XC4000_DTV6;
-		type = DTV6;
-		break;
-	case SYS_DVBT:
-	case SYS_DVBT2:
-		dprintk(1, "%s() OFDM\n", __func__);
-		if (bw == 0) {
-			if (c->frequency < 400000000) {
-				priv->freq_hz = c->frequency - 2250000;
-			} else {
-				priv->freq_hz = c->frequency - 2750000;
-			}
-			priv->video_standard = XC4000_DTV7_8;
-			type = DTV78;
-		} else if (bw <= 6000000) {
-			priv->video_standard = XC4000_DTV6;
-			priv->freq_hz = c->frequency - 1750000;
-			type = DTV6;
-		} else if (bw <= 7000000) {
-			priv->video_standard = XC4000_DTV7;
-			priv->freq_hz = c->frequency - 2250000;
-			type = DTV7;
-		} else {
-			priv->video_standard = XC4000_DTV8;
-			priv->freq_hz = c->frequency - 2750000;
-			type = DTV8;
-		}
-		priv->rf_mode = XC_RF_MODE_AIR;
-		break;
-	default:
-		printk(KERN_ERR "xc4000 delivery system not supported!\n");
-		ret = -EINVAL;
-		goto fail;
-	}
-
-	dprintk(1, "%s() frequency=%d (compensated)\n",
-		__func__, priv->freq_hz);
-
-	/* Make sure the correct firmware type is loaded */
-	if (check_firmware(fe, type, 0, priv->if_khz) != 0)
-		goto fail;
-
-	priv->bandwidth = c->bandwidth_hz;
-
-	ret = xc_set_signal_source(priv, priv->rf_mode);
-	if (ret != 0) {
-		printk(KERN_ERR "xc4000: xc_set_signal_source(%d) failed\n",
-		       priv->rf_mode);
-		goto fail;
-	} else {
-		u16	video_mode, audio_mode;
-		video_mode = xc4000_standard[priv->video_standard].video_mode;
-		audio_mode = xc4000_standard[priv->video_standard].audio_mode;
-		if (type == DTV6 && priv->firm_version != 0x0102)
-			video_mode |= 0x0001;
-		ret = xc_set_tv_standard(priv, video_mode, audio_mode);
-		if (ret != 0) {
-			printk(KERN_ERR "xc4000: xc_set_tv_standard failed\n");
-			/* DJH - do not return when it fails... */
-			/* goto fail; */
-		}
-	}
-
-	if (xc_write_reg(priv, XREG_D_CODE, 0) == 0)
-		ret = 0;
-	if (priv->dvb_amplitude != 0) {
-		if (xc_write_reg(priv, XREG_AMPLITUDE,
-				 (priv->firm_version != 0x0102 ||
-				  priv->dvb_amplitude != 134 ?
-				  priv->dvb_amplitude : 132)) != 0)
-			ret = -EREMOTEIO;
-	}
-	if (priv->set_smoothedcvbs != 0) {
-		if (xc_write_reg(priv, XREG_SMOOTHEDCVBS, 1) != 0)
-			ret = -EREMOTEIO;
-	}
-	if (ret != 0) {
-		printk(KERN_ERR "xc4000: setting registers failed\n");
-		/* goto fail; */
-	}
-
-	xc_tune_channel(priv, priv->freq_hz);
-
-	ret = 0;
-
-fail:
-	mutex_unlock(&priv->lock);
-
-	return ret;
-}
-
-static int xc4000_set_analog_params(struct dvb_frontend *fe,
-	struct analog_parameters *params)
-{
-	struct xc4000_priv *priv = fe->tuner_priv;
-	unsigned int type = 0;
-	int	ret = -EREMOTEIO;
-
-	if (params->mode == V4L2_TUNER_RADIO) {
-		dprintk(1, "%s() frequency=%d (in units of 62.5Hz)\n",
-			__func__, params->frequency);
-
-		mutex_lock(&priv->lock);
-
-		params->std = 0;
-		priv->freq_hz = params->frequency * 125L / 2;
-
-		if (audio_std & XC4000_AUDIO_STD_INPUT1) {
-			priv->video_standard = XC4000_FM_Radio_INPUT1;
-			type = FM | INPUT1;
-		} else {
-			priv->video_standard = XC4000_FM_Radio_INPUT2;
-			type = FM | INPUT2;
-		}
-
-		goto tune_channel;
-	}
-
-	dprintk(1, "%s() frequency=%d (in units of 62.5khz)\n",
-		__func__, params->frequency);
-
-	mutex_lock(&priv->lock);
-
-	/* params->frequency is in units of 62.5khz */
-	priv->freq_hz = params->frequency * 62500;
-
-	params->std &= V4L2_STD_ALL;
-	/* if std is not defined, choose one */
-	if (!params->std)
-		params->std = V4L2_STD_PAL_BG;
-
-	if (audio_std & XC4000_AUDIO_STD_MONO)
-		type = MONO;
-
-	if (params->std & V4L2_STD_MN) {
-		params->std = V4L2_STD_MN;
-		if (audio_std & XC4000_AUDIO_STD_MONO) {
-			priv->video_standard = XC4000_MN_NTSC_PAL_Mono;
-		} else if (audio_std & XC4000_AUDIO_STD_A2) {
-			params->std |= V4L2_STD_A2;
-			priv->video_standard = XC4000_MN_NTSC_PAL_A2;
-		} else {
-			params->std |= V4L2_STD_BTSC;
-			priv->video_standard = XC4000_MN_NTSC_PAL_BTSC;
-		}
-		goto tune_channel;
-	}
-
-	if (params->std & V4L2_STD_PAL_BG) {
-		params->std = V4L2_STD_PAL_BG;
-		if (audio_std & XC4000_AUDIO_STD_MONO) {
-			priv->video_standard = XC4000_BG_PAL_MONO;
-		} else if (!(audio_std & XC4000_AUDIO_STD_A2)) {
-			if (!(audio_std & XC4000_AUDIO_STD_B)) {
-				params->std |= V4L2_STD_NICAM_A;
-				priv->video_standard = XC4000_BG_PAL_NICAM;
-			} else {
-				params->std |= V4L2_STD_NICAM_B;
-				priv->video_standard = XC4000_BG_PAL_NICAM;
-			}
-		} else {
-			if (!(audio_std & XC4000_AUDIO_STD_B)) {
-				params->std |= V4L2_STD_A2_A;
-				priv->video_standard = XC4000_BG_PAL_A2;
-			} else {
-				params->std |= V4L2_STD_A2_B;
-				priv->video_standard = XC4000_BG_PAL_A2;
-			}
-		}
-		goto tune_channel;
-	}
-
-	if (params->std & V4L2_STD_PAL_I) {
-		/* default to NICAM audio standard */
-		params->std = V4L2_STD_PAL_I | V4L2_STD_NICAM;
-		if (audio_std & XC4000_AUDIO_STD_MONO)
-			priv->video_standard = XC4000_I_PAL_NICAM_MONO;
-		else
-			priv->video_standard = XC4000_I_PAL_NICAM;
-		goto tune_channel;
-	}
-
-	if (params->std & V4L2_STD_PAL_DK) {
-		params->std = V4L2_STD_PAL_DK;
-		if (audio_std & XC4000_AUDIO_STD_MONO) {
-			priv->video_standard = XC4000_DK_PAL_MONO;
-		} else if (audio_std & XC4000_AUDIO_STD_A2) {
-			params->std |= V4L2_STD_A2;
-			priv->video_standard = XC4000_DK_PAL_A2;
-		} else {
-			params->std |= V4L2_STD_NICAM;
-			priv->video_standard = XC4000_DK_PAL_NICAM;
-		}
-		goto tune_channel;
-	}
-
-	if (params->std & V4L2_STD_SECAM_DK) {
-		/* default to A2 audio standard */
-		params->std = V4L2_STD_SECAM_DK | V4L2_STD_A2;
-		if (audio_std & XC4000_AUDIO_STD_L) {
-			type = 0;
-			priv->video_standard = XC4000_DK_SECAM_NICAM;
-		} else if (audio_std & XC4000_AUDIO_STD_MONO) {
-			priv->video_standard = XC4000_DK_SECAM_A2MONO;
-		} else if (audio_std & XC4000_AUDIO_STD_K3) {
-			params->std |= V4L2_STD_SECAM_K3;
-			priv->video_standard = XC4000_DK_SECAM_A2LDK3;
-		} else {
-			priv->video_standard = XC4000_DK_SECAM_A2DK1;
-		}
-		goto tune_channel;
-	}
-
-	if (params->std & V4L2_STD_SECAM_L) {
-		/* default to NICAM audio standard */
-		type = 0;
-		params->std = V4L2_STD_SECAM_L | V4L2_STD_NICAM;
-		priv->video_standard = XC4000_L_SECAM_NICAM;
-		goto tune_channel;
-	}
-
-	if (params->std & V4L2_STD_SECAM_LC) {
-		/* default to NICAM audio standard */
-		type = 0;
-		params->std = V4L2_STD_SECAM_LC | V4L2_STD_NICAM;
-		priv->video_standard = XC4000_LC_SECAM_NICAM;
-		goto tune_channel;
-	}
-
-tune_channel:
-	/* FIXME: it could be air. */
-	priv->rf_mode = XC_RF_MODE_CABLE;
-
-	if (check_firmware(fe, type, params->std,
-			   xc4000_standard[priv->video_standard].int_freq) != 0)
-		goto fail;
-
-	ret = xc_set_signal_source(priv, priv->rf_mode);
-	if (ret != 0) {
-		printk(KERN_ERR
-		       "xc4000: xc_set_signal_source(%d) failed\n",
-		       priv->rf_mode);
-		goto fail;
-	} else {
-		u16	video_mode, audio_mode;
-		video_mode = xc4000_standard[priv->video_standard].video_mode;
-		audio_mode = xc4000_standard[priv->video_standard].audio_mode;
-		if (priv->video_standard < XC4000_BG_PAL_A2) {
-			if (type & NOGD)
-				video_mode &= 0xFF7F;
-		} else if (priv->video_standard < XC4000_I_PAL_NICAM) {
-			if (priv->firm_version == 0x0102)
-				video_mode &= 0xFEFF;
-			if (audio_std & XC4000_AUDIO_STD_B)
-				video_mode |= 0x0080;
-		}
-		ret = xc_set_tv_standard(priv, video_mode, audio_mode);
-		if (ret != 0) {
-			printk(KERN_ERR "xc4000: xc_set_tv_standard failed\n");
-			goto fail;
-		}
-	}
-
-	if (xc_write_reg(priv, XREG_D_CODE, 0) == 0)
-		ret = 0;
-	if (xc_write_reg(priv, XREG_AMPLITUDE, 1) != 0)
-		ret = -EREMOTEIO;
-	if (priv->set_smoothedcvbs != 0) {
-		if (xc_write_reg(priv, XREG_SMOOTHEDCVBS, 1) != 0)
-			ret = -EREMOTEIO;
-	}
-	if (ret != 0) {
-		printk(KERN_ERR "xc4000: setting registers failed\n");
-		goto fail;
-	}
-
-	xc_tune_channel(priv, priv->freq_hz);
-
-	ret = 0;
-
-fail:
-	mutex_unlock(&priv->lock);
-
-	return ret;
-}
-
-static int xc4000_get_signal(struct dvb_frontend *fe, u16 *strength)
-{
-	struct xc4000_priv *priv = fe->tuner_priv;
-	u16 value = 0;
-	int rc;
-
-	mutex_lock(&priv->lock);
-	rc = xc4000_readreg(priv, XREG_SIGNAL_LEVEL, &value);
-	mutex_unlock(&priv->lock);
-
-	if (rc < 0)
-		goto ret;
-
-	/* Informations from real testing of DVB-T and radio part,
-	   coeficient for one dB is 0xff.
-	 */
-	tuner_dbg("Signal strength: -%ddB (%05d)\n", value >> 8, value);
-
-	/* all known digital modes */
-	if ((priv->video_standard == XC4000_DTV6) ||
-	    (priv->video_standard == XC4000_DTV7) ||
-	    (priv->video_standard == XC4000_DTV7_8) ||
-	    (priv->video_standard == XC4000_DTV8))
-		goto digital;
-
-	/* Analog mode has NOISE LEVEL important, signal
-	   depends only on gain of antenna and amplifiers,
-	   but it doesn't tell anything about real quality
-	   of reception.
-	 */
-	mutex_lock(&priv->lock);
-	rc = xc4000_readreg(priv, XREG_NOISE_LEVEL, &value);
-	mutex_unlock(&priv->lock);
-
-	tuner_dbg("Noise level: %ddB (%05d)\n", value >> 8, value);
-
-	/* highest noise level: 32dB */
-	if (value >= 0x2000) {
-		value = 0;
-	} else {
-		value = ~value << 3;
-	}
-
-	goto ret;
-
-	/* Digital mode has SIGNAL LEVEL important and real
-	   noise level is stored in demodulator registers.
-	 */
-digital:
-	/* best signal: -50dB */
-	if (value <= 0x3200) {
-		value = 0xffff;
-	/* minimum: -114dB - should be 0x7200 but real zero is 0x713A */
-	} else if (value >= 0x713A) {
-		value = 0;
-	} else {
-		value = ~(value - 0x3200) << 2;
-	}
-
-ret:
-	*strength = value;
-
-	return rc;
-}
-
-static int xc4000_get_frequency(struct dvb_frontend *fe, u32 *freq)
-{
-	struct xc4000_priv *priv = fe->tuner_priv;
-
-	*freq = priv->freq_hz;
-
-	if (debug) {
-		mutex_lock(&priv->lock);
-		if ((priv->cur_fw.type
-		     & (BASE | FM | DTV6 | DTV7 | DTV78 | DTV8)) == BASE) {
-			u16	snr = 0;
-			if (xc4000_readreg(priv, XREG_SNR, &snr) == 0) {
-				mutex_unlock(&priv->lock);
-				dprintk(1, "%s() freq = %u, SNR = %d\n",
-					__func__, *freq, snr);
-				return 0;
-			}
-		}
-		mutex_unlock(&priv->lock);
-	}
-
-	dprintk(1, "%s()\n", __func__);
-
-	return 0;
-}
-
-static int xc4000_get_bandwidth(struct dvb_frontend *fe, u32 *bw)
-{
-	struct xc4000_priv *priv = fe->tuner_priv;
-	dprintk(1, "%s()\n", __func__);
-
-	*bw = priv->bandwidth;
-	return 0;
-}
-
-static int xc4000_get_status(struct dvb_frontend *fe, u32 *status)
-{
-	struct xc4000_priv *priv = fe->tuner_priv;
-	u16	lock_status = 0;
-
-	mutex_lock(&priv->lock);
-
-	if (priv->cur_fw.type & BASE)
-		xc_get_lock_status(priv, &lock_status);
-
-	*status = (lock_status == 1 ?
-		   TUNER_STATUS_LOCKED | TUNER_STATUS_STEREO : 0);
-	if (priv->cur_fw.type & (DTV6 | DTV7 | DTV78 | DTV8))
-		*status &= (~TUNER_STATUS_STEREO);
-
-	mutex_unlock(&priv->lock);
-
-	dprintk(2, "%s() lock_status = %d\n", __func__, lock_status);
-
-	return 0;
-}
-
-static int xc4000_sleep(struct dvb_frontend *fe)
-{
-	struct xc4000_priv *priv = fe->tuner_priv;
-	int	ret = 0;
-
-	dprintk(1, "%s()\n", __func__);
-
-	mutex_lock(&priv->lock);
-
-	/* Avoid firmware reload on slow devices */
-	if ((no_poweroff == 2 ||
-	     (no_poweroff == 0 && priv->default_pm != 0)) &&
-	    (priv->cur_fw.type & BASE) != 0) {
-		/* force reset and firmware reload */
-		priv->cur_fw.type = XC_POWERED_DOWN;
-
-		if (xc_write_reg(priv, XREG_POWER_DOWN, 0) != 0) {
-			printk(KERN_ERR
-			       "xc4000: %s() unable to shutdown tuner\n",
-			       __func__);
-			ret = -EREMOTEIO;
-		}
-		msleep(20);
-	}
-
-	mutex_unlock(&priv->lock);
-
-	return ret;
-}
-
-static int xc4000_init(struct dvb_frontend *fe)
-{
-	dprintk(1, "%s()\n", __func__);
-
-	return 0;
-}
-
-static int xc4000_release(struct dvb_frontend *fe)
-{
-	struct xc4000_priv *priv = fe->tuner_priv;
-
-	dprintk(1, "%s()\n", __func__);
-
-	mutex_lock(&xc4000_list_mutex);
-
-	if (priv)
-		hybrid_tuner_release_state(priv);
-
-	mutex_unlock(&xc4000_list_mutex);
-
-	fe->tuner_priv = NULL;
-
-	return 0;
-}
-
-static const struct dvb_tuner_ops xc4000_tuner_ops = {
-	.info = {
-		.name           = "Xceive XC4000",
-		.frequency_min  =    1000000,
-		.frequency_max  = 1023000000,
-		.frequency_step =      50000,
-	},
-
-	.release	   = xc4000_release,
-	.init		   = xc4000_init,
-	.sleep		   = xc4000_sleep,
-
-	.set_params	   = xc4000_set_params,
-	.set_analog_params = xc4000_set_analog_params,
-	.get_frequency	   = xc4000_get_frequency,
-	.get_rf_strength   = xc4000_get_signal,
-	.get_bandwidth	   = xc4000_get_bandwidth,
-	.get_status	   = xc4000_get_status
-};
-
-struct dvb_frontend *xc4000_attach(struct dvb_frontend *fe,
-				   struct i2c_adapter *i2c,
-				   struct xc4000_config *cfg)
-{
-	struct xc4000_priv *priv = NULL;
-	int	instance;
-	u16	id = 0;
-
-	dprintk(1, "%s(%d-%04x)\n", __func__,
-		i2c ? i2c_adapter_id(i2c) : -1,
-		cfg ? cfg->i2c_address : -1);
-
-	mutex_lock(&xc4000_list_mutex);
-
-	instance = hybrid_tuner_request_state(struct xc4000_priv, priv,
-					      hybrid_tuner_instance_list,
-					      i2c, cfg->i2c_address, "xc4000");
-	switch (instance) {
-	case 0:
-		goto fail;
-		break;
-	case 1:
-		/* new tuner instance */
-		priv->bandwidth = 6000000;
-		/* set default configuration */
-		priv->if_khz = 4560;
-		priv->default_pm = 0;
-		priv->dvb_amplitude = 134;
-		priv->set_smoothedcvbs = 1;
-		mutex_init(&priv->lock);
-		fe->tuner_priv = priv;
-		break;
-	default:
-		/* existing tuner instance */
-		fe->tuner_priv = priv;
-		break;
-	}
-
-	if (cfg->if_khz != 0) {
-		/* copy configuration if provided by the caller */
-		priv->if_khz = cfg->if_khz;
-		priv->default_pm = cfg->default_pm;
-		priv->dvb_amplitude = cfg->dvb_amplitude;
-		priv->set_smoothedcvbs = cfg->set_smoothedcvbs;
-	}
-
-	/* Check if firmware has been loaded. It is possible that another
-	   instance of the driver has loaded the firmware.
-	 */
-
-	if (instance == 1) {
-		if (xc4000_readreg(priv, XREG_PRODUCT_ID, &id) != 0)
-			goto fail;
-	} else {
-		id = ((priv->cur_fw.type & BASE) != 0 ?
-		      priv->hwmodel : XC_PRODUCT_ID_FW_NOT_LOADED);
-	}
-
-	switch (id) {
-	case XC_PRODUCT_ID_XC4000:
-	case XC_PRODUCT_ID_XC4100:
-		printk(KERN_INFO
-			"xc4000: Successfully identified at address 0x%02x\n",
-			cfg->i2c_address);
-		printk(KERN_INFO
-			"xc4000: Firmware has been loaded previously\n");
-		break;
-	case XC_PRODUCT_ID_FW_NOT_LOADED:
-		printk(KERN_INFO
-			"xc4000: Successfully identified at address 0x%02x\n",
-			cfg->i2c_address);
-		printk(KERN_INFO
-			"xc4000: Firmware has not been loaded previously\n");
-		break;
-	default:
-		printk(KERN_ERR
-			"xc4000: Device not found at addr 0x%02x (0x%x)\n",
-			cfg->i2c_address, id);
-		goto fail;
-	}
-
-	mutex_unlock(&xc4000_list_mutex);
-
-	memcpy(&fe->ops.tuner_ops, &xc4000_tuner_ops,
-		sizeof(struct dvb_tuner_ops));
-
-	if (instance == 1) {
-		int	ret;
-		mutex_lock(&priv->lock);
-		ret = xc4000_fwupload(fe);
-		mutex_unlock(&priv->lock);
-		if (ret != 0)
-			goto fail2;
-	}
-
-	return fe;
-fail:
-	mutex_unlock(&xc4000_list_mutex);
-fail2:
-	xc4000_release(fe);
-	return NULL;
-}
-EXPORT_SYMBOL(xc4000_attach);
-
-MODULE_AUTHOR("Steven Toth, Davide Ferri");
-MODULE_DESCRIPTION("Xceive xc4000 silicon tuner driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/common/tuners/xc4000.h b/drivers/media/common/tuners/xc4000.h
deleted file mode 100644
index e6a44d1..0000000
--- a/drivers/media/common/tuners/xc4000.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- *  Driver for Xceive XC4000 "QAM/8VSB single chip tuner"
- *
- *  Copyright (c) 2007 Steven Toth <stoth@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 __XC4000_H__
-#define __XC4000_H__
-
-#include <linux/firmware.h>
-
-struct dvb_frontend;
-struct i2c_adapter;
-
-struct xc4000_config {
-	u8	i2c_address;
-	/* if non-zero, power management is enabled by default */
-	u8	default_pm;
-	/* value to be written to XREG_AMPLITUDE in DVB-T mode (0: no write) */
-	u8	dvb_amplitude;
-	/* if non-zero, register 0x0E is set to filter analog TV video output */
-	u8	set_smoothedcvbs;
-	/* IF for DVB-T */
-	u32	if_khz;
-};
-
-/* xc4000 callback command */
-#define XC4000_TUNER_RESET		0
-
-/* For each bridge framework, when it attaches either analog or digital,
- * it has to store a reference back to its _core equivalent structure,
- * so that it can service the hardware by steering gpio's etc.
- * Each bridge implementation is different so cast devptr accordingly.
- * The xc4000 driver cares not for this value, other than ensuring
- * it's passed back to a bridge during tuner_callback().
- */
-
-#if defined(CONFIG_MEDIA_TUNER_XC4000) || (defined(CONFIG_MEDIA_TUNER_XC4000_MODULE) && defined(MODULE))
-extern struct dvb_frontend *xc4000_attach(struct dvb_frontend *fe,
-					  struct i2c_adapter *i2c,
-					  struct xc4000_config *cfg);
-#else
-static inline struct dvb_frontend *xc4000_attach(struct dvb_frontend *fe,
-						 struct i2c_adapter *i2c,
-						 struct xc4000_config *cfg)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif
-
-#endif
diff --git a/drivers/media/common/tuners/xc5000.c b/drivers/media/common/tuners/xc5000.c
deleted file mode 100644
index 362a8d7..0000000
--- a/drivers/media/common/tuners/xc5000.c
+++ /dev/null
@@ -1,1265 +0,0 @@
-/*
- *  Driver for Xceive XC5000 "QAM/8VSB single chip tuner"
- *
- *  Copyright (c) 2007 Xceive Corporation
- *  Copyright (c) 2007 Steven Toth <stoth@linuxtv.org>
- *  Copyright (c) 2009 Devin Heitmueller <dheitmueller@kernellabs.com>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/videodev2.h>
-#include <linux/delay.h>
-#include <linux/dvb/frontend.h>
-#include <linux/i2c.h>
-
-#include "dvb_frontend.h"
-
-#include "xc5000.h"
-#include "tuner-i2c.h"
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
-
-static int no_poweroff;
-module_param(no_poweroff, int, 0644);
-MODULE_PARM_DESC(no_poweroff, "0 (default) powers device off when not used.\n"
-	"\t\t1 keep device energized and with tuner ready all the times.\n"
-	"\t\tFaster, but consumes more power and keeps the device hotter");
-
-static DEFINE_MUTEX(xc5000_list_mutex);
-static LIST_HEAD(hybrid_tuner_instance_list);
-
-#define dprintk(level, fmt, arg...) if (debug >= level) \
-	printk(KERN_INFO "%s: " fmt, "xc5000", ## arg)
-
-struct xc5000_priv {
-	struct tuner_i2c_props i2c_props;
-	struct list_head hybrid_tuner_instance_list;
-
-	u32 if_khz;
-	u16 xtal_khz;
-	u32 freq_hz;
-	u32 bandwidth;
-	u8  video_standard;
-	u8  rf_mode;
-	u8  radio_input;
-
-	int chip_id;
-};
-
-/* Misc Defines */
-#define MAX_TV_STANDARD			24
-#define XC_MAX_I2C_WRITE_LENGTH		64
-
-/* Signal Types */
-#define XC_RF_MODE_AIR			0
-#define XC_RF_MODE_CABLE		1
-
-/* Result codes */
-#define XC_RESULT_SUCCESS		0
-#define XC_RESULT_RESET_FAILURE		1
-#define XC_RESULT_I2C_WRITE_FAILURE	2
-#define XC_RESULT_I2C_READ_FAILURE	3
-#define XC_RESULT_OUT_OF_RANGE		5
-
-/* Product id */
-#define XC_PRODUCT_ID_FW_NOT_LOADED	0x2000
-#define XC_PRODUCT_ID_FW_LOADED 	0x1388
-
-/* Registers */
-#define XREG_INIT         0x00
-#define XREG_VIDEO_MODE   0x01
-#define XREG_AUDIO_MODE   0x02
-#define XREG_RF_FREQ      0x03
-#define XREG_D_CODE       0x04
-#define XREG_IF_OUT       0x05
-#define XREG_SEEK_MODE    0x07
-#define XREG_POWER_DOWN   0x0A /* Obsolete */
-/* Set the output amplitude - SIF for analog, DTVP/DTVN for digital */
-#define XREG_OUTPUT_AMP   0x0B
-#define XREG_SIGNALSOURCE 0x0D /* 0=Air, 1=Cable */
-#define XREG_SMOOTHEDCVBS 0x0E
-#define XREG_XTALFREQ     0x0F
-#define XREG_FINERFREQ    0x10
-#define XREG_DDIMODE      0x11
-
-#define XREG_ADC_ENV      0x00
-#define XREG_QUALITY      0x01
-#define XREG_FRAME_LINES  0x02
-#define XREG_HSYNC_FREQ   0x03
-#define XREG_LOCK         0x04
-#define XREG_FREQ_ERROR   0x05
-#define XREG_SNR          0x06
-#define XREG_VERSION      0x07
-#define XREG_PRODUCT_ID   0x08
-#define XREG_BUSY         0x09
-#define XREG_BUILD        0x0D
-
-/*
-   Basic firmware description. This will remain with
-   the driver for documentation purposes.
-
-   This represents an I2C firmware file encoded as a
-   string of unsigned char. Format is as follows:
-
-   char[0  ]=len0_MSB  -> len = len_MSB * 256 + len_LSB
-   char[1  ]=len0_LSB  -> length of first write transaction
-   char[2  ]=data0 -> first byte to be sent
-   char[3  ]=data1
-   char[4  ]=data2
-   char[   ]=...
-   char[M  ]=dataN  -> last byte to be sent
-   char[M+1]=len1_MSB  -> len = len_MSB * 256 + len_LSB
-   char[M+2]=len1_LSB  -> length of second write transaction
-   char[M+3]=data0
-   char[M+4]=data1
-   ...
-   etc.
-
-   The [len] value should be interpreted as follows:
-
-   len= len_MSB _ len_LSB
-   len=1111_1111_1111_1111   : End of I2C_SEQUENCE
-   len=0000_0000_0000_0000   : Reset command: Do hardware reset
-   len=0NNN_NNNN_NNNN_NNNN   : Normal transaction: number of bytes = {1:32767)
-   len=1WWW_WWWW_WWWW_WWWW   : Wait command: wait for {1:32767} ms
-
-   For the RESET and WAIT commands, the two following bytes will contain
-   immediately the length of the following transaction.
-
-*/
-struct XC_TV_STANDARD {
-	char *Name;
-	u16 AudioMode;
-	u16 VideoMode;
-};
-
-/* Tuner standards */
-#define MN_NTSC_PAL_BTSC	0
-#define MN_NTSC_PAL_A2		1
-#define MN_NTSC_PAL_EIAJ	2
-#define MN_NTSC_PAL_Mono	3
-#define BG_PAL_A2		4
-#define BG_PAL_NICAM		5
-#define BG_PAL_MONO		6
-#define I_PAL_NICAM		7
-#define I_PAL_NICAM_MONO	8
-#define DK_PAL_A2		9
-#define DK_PAL_NICAM		10
-#define DK_PAL_MONO		11
-#define DK_SECAM_A2DK1		12
-#define DK_SECAM_A2LDK3 	13
-#define DK_SECAM_A2MONO 	14
-#define L_SECAM_NICAM		15
-#define LC_SECAM_NICAM		16
-#define DTV6			17
-#define DTV8			18
-#define DTV7_8			19
-#define DTV7			20
-#define FM_Radio_INPUT2 	21
-#define FM_Radio_INPUT1 	22
-#define FM_Radio_INPUT1_MONO	23
-
-static struct XC_TV_STANDARD XC5000_Standard[MAX_TV_STANDARD] = {
-	{"M/N-NTSC/PAL-BTSC", 0x0400, 0x8020},
-	{"M/N-NTSC/PAL-A2",   0x0600, 0x8020},
-	{"M/N-NTSC/PAL-EIAJ", 0x0440, 0x8020},
-	{"M/N-NTSC/PAL-Mono", 0x0478, 0x8020},
-	{"B/G-PAL-A2",        0x0A00, 0x8049},
-	{"B/G-PAL-NICAM",     0x0C04, 0x8049},
-	{"B/G-PAL-MONO",      0x0878, 0x8059},
-	{"I-PAL-NICAM",       0x1080, 0x8009},
-	{"I-PAL-NICAM-MONO",  0x0E78, 0x8009},
-	{"D/K-PAL-A2",        0x1600, 0x8009},
-	{"D/K-PAL-NICAM",     0x0E80, 0x8009},
-	{"D/K-PAL-MONO",      0x1478, 0x8009},
-	{"D/K-SECAM-A2 DK1",  0x1200, 0x8009},
-	{"D/K-SECAM-A2 L/DK3", 0x0E00, 0x8009},
-	{"D/K-SECAM-A2 MONO", 0x1478, 0x8009},
-	{"L-SECAM-NICAM",     0x8E82, 0x0009},
-	{"L'-SECAM-NICAM",    0x8E82, 0x4009},
-	{"DTV6",              0x00C0, 0x8002},
-	{"DTV8",              0x00C0, 0x800B},
-	{"DTV7/8",            0x00C0, 0x801B},
-	{"DTV7",              0x00C0, 0x8007},
-	{"FM Radio-INPUT2",   0x9802, 0x9002},
-	{"FM Radio-INPUT1",   0x0208, 0x9002},
-	{"FM Radio-INPUT1_MONO", 0x0278, 0x9002}
-};
-
-
-struct xc5000_fw_cfg {
-	char *name;
-	u16 size;
-};
-
-#define XC5000A_FIRMWARE "dvb-fe-xc5000-1.6.114.fw"
-static const struct xc5000_fw_cfg xc5000a_1_6_114 = {
-	.name = XC5000A_FIRMWARE,
-	.size = 12401,
-};
-
-#define XC5000C_FIRMWARE "dvb-fe-xc5000c-41.024.5.fw"
-static const struct xc5000_fw_cfg xc5000c_41_024_5 = {
-	.name = XC5000C_FIRMWARE,
-	.size = 16497,
-};
-
-static inline const struct xc5000_fw_cfg *xc5000_assign_firmware(int chip_id)
-{
-	switch (chip_id) {
-	default:
-	case XC5000A:
-		return &xc5000a_1_6_114;
-	case XC5000C:
-		return &xc5000c_41_024_5;
-	}
-}
-
-static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe);
-static int xc5000_is_firmware_loaded(struct dvb_frontend *fe);
-static int xc5000_readreg(struct xc5000_priv *priv, u16 reg, u16 *val);
-static int xc5000_TunerReset(struct dvb_frontend *fe);
-
-static int xc_send_i2c_data(struct xc5000_priv *priv, u8 *buf, int len)
-{
-	struct i2c_msg msg = { .addr = priv->i2c_props.addr,
-			       .flags = 0, .buf = buf, .len = len };
-
-	if (i2c_transfer(priv->i2c_props.adap, &msg, 1) != 1) {
-		printk(KERN_ERR "xc5000: I2C write failed (len=%i)\n", len);
-		return XC_RESULT_I2C_WRITE_FAILURE;
-	}
-	return XC_RESULT_SUCCESS;
-}
-
-#if 0
-/* This routine is never used because the only time we read data from the
-   i2c bus is when we read registers, and we want that to be an atomic i2c
-   transaction in case we are on a multi-master bus */
-static int xc_read_i2c_data(struct xc5000_priv *priv, u8 *buf, int len)
-{
-	struct i2c_msg msg = { .addr = priv->i2c_props.addr,
-		.flags = I2C_M_RD, .buf = buf, .len = len };
-
-	if (i2c_transfer(priv->i2c_props.adap, &msg, 1) != 1) {
-		printk(KERN_ERR "xc5000 I2C read failed (len=%i)\n", len);
-		return -EREMOTEIO;
-	}
-	return 0;
-}
-#endif
-
-static int xc5000_readreg(struct xc5000_priv *priv, u16 reg, u16 *val)
-{
-	u8 buf[2] = { reg >> 8, reg & 0xff };
-	u8 bval[2] = { 0, 0 };
-	struct i2c_msg msg[2] = {
-		{ .addr = priv->i2c_props.addr,
-			.flags = 0, .buf = &buf[0], .len = 2 },
-		{ .addr = priv->i2c_props.addr,
-			.flags = I2C_M_RD, .buf = &bval[0], .len = 2 },
-	};
-
-	if (i2c_transfer(priv->i2c_props.adap, msg, 2) != 2) {
-		printk(KERN_WARNING "xc5000: I2C read failed\n");
-		return -EREMOTEIO;
-	}
-
-	*val = (bval[0] << 8) | bval[1];
-	return XC_RESULT_SUCCESS;
-}
-
-static void xc_wait(int wait_ms)
-{
-	msleep(wait_ms);
-}
-
-static int xc5000_TunerReset(struct dvb_frontend *fe)
-{
-	struct xc5000_priv *priv = fe->tuner_priv;
-	int ret;
-
-	dprintk(1, "%s()\n", __func__);
-
-	if (fe->callback) {
-		ret = fe->callback(((fe->dvb) && (fe->dvb->priv)) ?
-					   fe->dvb->priv :
-					   priv->i2c_props.adap->algo_data,
-					   DVB_FRONTEND_COMPONENT_TUNER,
-					   XC5000_TUNER_RESET, 0);
-		if (ret) {
-			printk(KERN_ERR "xc5000: reset failed\n");
-			return XC_RESULT_RESET_FAILURE;
-		}
-	} else {
-		printk(KERN_ERR "xc5000: no tuner reset callback function, fatal\n");
-		return XC_RESULT_RESET_FAILURE;
-	}
-	return XC_RESULT_SUCCESS;
-}
-
-static int xc_write_reg(struct xc5000_priv *priv, u16 regAddr, u16 i2cData)
-{
-	u8 buf[4];
-	int WatchDogTimer = 100;
-	int result;
-
-	buf[0] = (regAddr >> 8) & 0xFF;
-	buf[1] = regAddr & 0xFF;
-	buf[2] = (i2cData >> 8) & 0xFF;
-	buf[3] = i2cData & 0xFF;
-	result = xc_send_i2c_data(priv, buf, 4);
-	if (result == XC_RESULT_SUCCESS) {
-		/* wait for busy flag to clear */
-		while ((WatchDogTimer > 0) && (result == XC_RESULT_SUCCESS)) {
-			result = xc5000_readreg(priv, XREG_BUSY, (u16 *)buf);
-			if (result == XC_RESULT_SUCCESS) {
-				if ((buf[0] == 0) && (buf[1] == 0)) {
-					/* busy flag cleared */
-					break;
-				} else {
-					xc_wait(5); /* wait 5 ms */
-					WatchDogTimer--;
-				}
-			}
-		}
-	}
-	if (WatchDogTimer < 0)
-		result = XC_RESULT_I2C_WRITE_FAILURE;
-
-	return result;
-}
-
-static int xc_load_i2c_sequence(struct dvb_frontend *fe, const u8 *i2c_sequence)
-{
-	struct xc5000_priv *priv = fe->tuner_priv;
-
-	int i, nbytes_to_send, result;
-	unsigned int len, pos, index;
-	u8 buf[XC_MAX_I2C_WRITE_LENGTH];
-
-	index = 0;
-	while ((i2c_sequence[index] != 0xFF) ||
-		(i2c_sequence[index + 1] != 0xFF)) {
-		len = i2c_sequence[index] * 256 + i2c_sequence[index+1];
-		if (len == 0x0000) {
-			/* RESET command */
-			result = xc5000_TunerReset(fe);
-			index += 2;
-			if (result != XC_RESULT_SUCCESS)
-				return result;
-		} else if (len & 0x8000) {
-			/* WAIT command */
-			xc_wait(len & 0x7FFF);
-			index += 2;
-		} else {
-			/* Send i2c data whilst ensuring individual transactions
-			 * do not exceed XC_MAX_I2C_WRITE_LENGTH bytes.
-			 */
-			index += 2;
-			buf[0] = i2c_sequence[index];
-			buf[1] = i2c_sequence[index + 1];
-			pos = 2;
-			while (pos < len) {
-				if ((len - pos) > XC_MAX_I2C_WRITE_LENGTH - 2)
-					nbytes_to_send =
-						XC_MAX_I2C_WRITE_LENGTH;
-				else
-					nbytes_to_send = (len - pos + 2);
-				for (i = 2; i < nbytes_to_send; i++) {
-					buf[i] = i2c_sequence[index + pos +
-						i - 2];
-				}
-				result = xc_send_i2c_data(priv, buf,
-					nbytes_to_send);
-
-				if (result != XC_RESULT_SUCCESS)
-					return result;
-
-				pos += nbytes_to_send - 2;
-			}
-			index += len;
-		}
-	}
-	return XC_RESULT_SUCCESS;
-}
-
-static int xc_initialize(struct xc5000_priv *priv)
-{
-	dprintk(1, "%s()\n", __func__);
-	return xc_write_reg(priv, XREG_INIT, 0);
-}
-
-static int xc_SetTVStandard(struct xc5000_priv *priv,
-	u16 VideoMode, u16 AudioMode)
-{
-	int ret;
-	dprintk(1, "%s(0x%04x,0x%04x)\n", __func__, VideoMode, AudioMode);
-	dprintk(1, "%s() Standard = %s\n",
-		__func__,
-		XC5000_Standard[priv->video_standard].Name);
-
-	ret = xc_write_reg(priv, XREG_VIDEO_MODE, VideoMode);
-	if (ret == XC_RESULT_SUCCESS)
-		ret = xc_write_reg(priv, XREG_AUDIO_MODE, AudioMode);
-
-	return ret;
-}
-
-static int xc_SetSignalSource(struct xc5000_priv *priv, u16 rf_mode)
-{
-	dprintk(1, "%s(%d) Source = %s\n", __func__, rf_mode,
-		rf_mode == XC_RF_MODE_AIR ? "ANTENNA" : "CABLE");
-
-	if ((rf_mode != XC_RF_MODE_AIR) && (rf_mode != XC_RF_MODE_CABLE)) {
-		rf_mode = XC_RF_MODE_CABLE;
-		printk(KERN_ERR
-			"%s(), Invalid mode, defaulting to CABLE",
-			__func__);
-	}
-	return xc_write_reg(priv, XREG_SIGNALSOURCE, rf_mode);
-}
-
-static const struct dvb_tuner_ops xc5000_tuner_ops;
-
-static int xc_set_RF_frequency(struct xc5000_priv *priv, u32 freq_hz)
-{
-	u16 freq_code;
-
-	dprintk(1, "%s(%u)\n", __func__, freq_hz);
-
-	if ((freq_hz > xc5000_tuner_ops.info.frequency_max) ||
-		(freq_hz < xc5000_tuner_ops.info.frequency_min))
-		return XC_RESULT_OUT_OF_RANGE;
-
-	freq_code = (u16)(freq_hz / 15625);
-
-	/* Starting in firmware version 1.1.44, Xceive recommends using the
-	   FINERFREQ for all normal tuning (the doc indicates reg 0x03 should
-	   only be used for fast scanning for channel lock) */
-	return xc_write_reg(priv, XREG_FINERFREQ, freq_code);
-}
-
-
-static int xc_set_IF_frequency(struct xc5000_priv *priv, u32 freq_khz)
-{
-	u32 freq_code = (freq_khz * 1024)/1000;
-	dprintk(1, "%s(freq_khz = %d) freq_code = 0x%x\n",
-		__func__, freq_khz, freq_code);
-
-	return xc_write_reg(priv, XREG_IF_OUT, freq_code);
-}
-
-
-static int xc_get_ADC_Envelope(struct xc5000_priv *priv, u16 *adc_envelope)
-{
-	return xc5000_readreg(priv, XREG_ADC_ENV, adc_envelope);
-}
-
-static int xc_get_frequency_error(struct xc5000_priv *priv, u32 *freq_error_hz)
-{
-	int result;
-	u16 regData;
-	u32 tmp;
-
-	result = xc5000_readreg(priv, XREG_FREQ_ERROR, &regData);
-	if (result != XC_RESULT_SUCCESS)
-		return result;
-
-	tmp = (u32)regData;
-	(*freq_error_hz) = (tmp * 15625) / 1000;
-	return result;
-}
-
-static int xc_get_lock_status(struct xc5000_priv *priv, u16 *lock_status)
-{
-	return xc5000_readreg(priv, XREG_LOCK, lock_status);
-}
-
-static int xc_get_version(struct xc5000_priv *priv,
-	u8 *hw_majorversion, u8 *hw_minorversion,
-	u8 *fw_majorversion, u8 *fw_minorversion)
-{
-	u16 data;
-	int result;
-
-	result = xc5000_readreg(priv, XREG_VERSION, &data);
-	if (result != XC_RESULT_SUCCESS)
-		return result;
-
-	(*hw_majorversion) = (data >> 12) & 0x0F;
-	(*hw_minorversion) = (data >>  8) & 0x0F;
-	(*fw_majorversion) = (data >>  4) & 0x0F;
-	(*fw_minorversion) = data & 0x0F;
-
-	return 0;
-}
-
-static int xc_get_buildversion(struct xc5000_priv *priv, u16 *buildrev)
-{
-	return xc5000_readreg(priv, XREG_BUILD, buildrev);
-}
-
-static int xc_get_hsync_freq(struct xc5000_priv *priv, u32 *hsync_freq_hz)
-{
-	u16 regData;
-	int result;
-
-	result = xc5000_readreg(priv, XREG_HSYNC_FREQ, &regData);
-	if (result != XC_RESULT_SUCCESS)
-		return result;
-
-	(*hsync_freq_hz) = ((regData & 0x0fff) * 763)/100;
-	return result;
-}
-
-static int xc_get_frame_lines(struct xc5000_priv *priv, u16 *frame_lines)
-{
-	return xc5000_readreg(priv, XREG_FRAME_LINES, frame_lines);
-}
-
-static int xc_get_quality(struct xc5000_priv *priv, u16 *quality)
-{
-	return xc5000_readreg(priv, XREG_QUALITY, quality);
-}
-
-static u16 WaitForLock(struct xc5000_priv *priv)
-{
-	u16 lockState = 0;
-	int watchDogCount = 40;
-
-	while ((lockState == 0) && (watchDogCount > 0)) {
-		xc_get_lock_status(priv, &lockState);
-		if (lockState != 1) {
-			xc_wait(5);
-			watchDogCount--;
-		}
-	}
-	return lockState;
-}
-
-#define XC_TUNE_ANALOG  0
-#define XC_TUNE_DIGITAL 1
-static int xc_tune_channel(struct xc5000_priv *priv, u32 freq_hz, int mode)
-{
-	int found = 0;
-
-	dprintk(1, "%s(%u)\n", __func__, freq_hz);
-
-	if (xc_set_RF_frequency(priv, freq_hz) != XC_RESULT_SUCCESS)
-		return 0;
-
-	if (mode == XC_TUNE_ANALOG) {
-		if (WaitForLock(priv) == 1)
-			found = 1;
-	}
-
-	return found;
-}
-
-static int xc_set_xtal(struct dvb_frontend *fe)
-{
-	struct xc5000_priv *priv = fe->tuner_priv;
-	int ret = XC_RESULT_SUCCESS;
-
-	switch (priv->chip_id) {
-	default:
-	case XC5000A:
-		/* 32.000 MHz xtal is default */
-		break;
-	case XC5000C:
-		switch (priv->xtal_khz) {
-		default:
-		case 32000:
-			/* 32.000 MHz xtal is default */
-			break;
-		case 31875:
-			/* 31.875 MHz xtal configuration */
-			ret = xc_write_reg(priv, 0x000f, 0x8081);
-			break;
-		}
-		break;
-	}
-	return ret;
-}
-
-static int xc5000_fwupload(struct dvb_frontend *fe)
-{
-	struct xc5000_priv *priv = fe->tuner_priv;
-	const struct firmware *fw;
-	int ret;
-	const struct xc5000_fw_cfg *desired_fw =
-		xc5000_assign_firmware(priv->chip_id);
-
-	/* request the firmware, this will block and timeout */
-	printk(KERN_INFO "xc5000: waiting for firmware upload (%s)...\n",
-		desired_fw->name);
-
-	ret = request_firmware(&fw, desired_fw->name,
-		priv->i2c_props.adap->dev.parent);
-	if (ret) {
-		printk(KERN_ERR "xc5000: Upload failed. (file not found?)\n");
-		ret = XC_RESULT_RESET_FAILURE;
-		goto out;
-	} else {
-		printk(KERN_DEBUG "xc5000: firmware read %Zu bytes.\n",
-		       fw->size);
-		ret = XC_RESULT_SUCCESS;
-	}
-
-	if (fw->size != desired_fw->size) {
-		printk(KERN_ERR "xc5000: firmware incorrect size\n");
-		ret = XC_RESULT_RESET_FAILURE;
-	} else {
-		printk(KERN_INFO "xc5000: firmware uploading...\n");
-		ret = xc_load_i2c_sequence(fe,  fw->data);
-		if (XC_RESULT_SUCCESS == ret)
-			ret = xc_set_xtal(fe);
-		if (XC_RESULT_SUCCESS == ret)
-			printk(KERN_INFO "xc5000: firmware upload complete...\n");
-		else
-			printk(KERN_ERR "xc5000: firmware upload failed...\n");
-	}
-
-out:
-	release_firmware(fw);
-	return ret;
-}
-
-static void xc_debug_dump(struct xc5000_priv *priv)
-{
-	u16 adc_envelope;
-	u32 freq_error_hz = 0;
-	u16 lock_status;
-	u32 hsync_freq_hz = 0;
-	u16 frame_lines;
-	u16 quality;
-	u8 hw_majorversion = 0, hw_minorversion = 0;
-	u8 fw_majorversion = 0, fw_minorversion = 0;
-	u16 fw_buildversion = 0;
-
-	/* Wait for stats to stabilize.
-	 * Frame Lines needs two frame times after initial lock
-	 * before it is valid.
-	 */
-	xc_wait(100);
-
-	xc_get_ADC_Envelope(priv,  &adc_envelope);
-	dprintk(1, "*** ADC envelope (0-1023) = %d\n", adc_envelope);
-
-	xc_get_frequency_error(priv, &freq_error_hz);
-	dprintk(1, "*** Frequency error = %d Hz\n", freq_error_hz);
-
-	xc_get_lock_status(priv,  &lock_status);
-	dprintk(1, "*** Lock status (0-Wait, 1-Locked, 2-No-signal) = %d\n",
-		lock_status);
-
-	xc_get_version(priv,  &hw_majorversion, &hw_minorversion,
-		&fw_majorversion, &fw_minorversion);
-	xc_get_buildversion(priv,  &fw_buildversion);
-	dprintk(1, "*** HW: V%02x.%02x, FW: V%02x.%02x.%04x\n",
-		hw_majorversion, hw_minorversion,
-		fw_majorversion, fw_minorversion, fw_buildversion);
-
-	xc_get_hsync_freq(priv,  &hsync_freq_hz);
-	dprintk(1, "*** Horizontal sync frequency = %d Hz\n", hsync_freq_hz);
-
-	xc_get_frame_lines(priv,  &frame_lines);
-	dprintk(1, "*** Frame lines = %d\n", frame_lines);
-
-	xc_get_quality(priv,  &quality);
-	dprintk(1, "*** Quality (0:<8dB, 7:>56dB) = %d\n", quality);
-}
-
-static int xc5000_set_params(struct dvb_frontend *fe)
-{
-	int ret, b;
-	struct xc5000_priv *priv = fe->tuner_priv;
-	u32 bw = fe->dtv_property_cache.bandwidth_hz;
-	u32 freq = fe->dtv_property_cache.frequency;
-	u32 delsys  = fe->dtv_property_cache.delivery_system;
-
-	if (xc5000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS) {
-		if (xc_load_fw_and_init_tuner(fe) != XC_RESULT_SUCCESS) {
-			dprintk(1, "Unable to load firmware and init tuner\n");
-			return -EINVAL;
-		}
-	}
-
-	dprintk(1, "%s() frequency=%d (Hz)\n", __func__, freq);
-
-	switch (delsys) {
-	case SYS_ATSC:
-		dprintk(1, "%s() VSB modulation\n", __func__);
-		priv->rf_mode = XC_RF_MODE_AIR;
-		priv->freq_hz = freq - 1750000;
-		priv->video_standard = DTV6;
-		break;
-	case SYS_DVBC_ANNEX_B:
-		dprintk(1, "%s() QAM modulation\n", __func__);
-		priv->rf_mode = XC_RF_MODE_CABLE;
-		priv->freq_hz = freq - 1750000;
-		priv->video_standard = DTV6;
-		break;
-	case SYS_ISDBT:
-		/* All ISDB-T are currently for 6 MHz bw */
-		if (!bw)
-			bw = 6000000;
-		/* fall to OFDM handling */
-	case SYS_DMBTH:
-	case SYS_DVBT:
-	case SYS_DVBT2:
-		dprintk(1, "%s() OFDM\n", __func__);
-		switch (bw) {
-		case 6000000:
-			priv->video_standard = DTV6;
-			priv->freq_hz = freq - 1750000;
-			break;
-		case 7000000:
-			priv->video_standard = DTV7;
-			priv->freq_hz = freq - 2250000;
-			break;
-		case 8000000:
-			priv->video_standard = DTV8;
-			priv->freq_hz = freq - 2750000;
-			break;
-		default:
-			printk(KERN_ERR "xc5000 bandwidth not set!\n");
-			return -EINVAL;
-		}
-		priv->rf_mode = XC_RF_MODE_AIR;
-	case SYS_DVBC_ANNEX_A:
-	case SYS_DVBC_ANNEX_C:
-		dprintk(1, "%s() QAM modulation\n", __func__);
-		priv->rf_mode = XC_RF_MODE_CABLE;
-		if (bw <= 6000000) {
-			priv->video_standard = DTV6;
-			priv->freq_hz = freq - 1750000;
-			b = 6;
-		} else if (bw <= 7000000) {
-			priv->video_standard = DTV7;
-			priv->freq_hz = freq - 2250000;
-			b = 7;
-		} else {
-			priv->video_standard = DTV7_8;
-			priv->freq_hz = freq - 2750000;
-			b = 8;
-		}
-		dprintk(1, "%s() Bandwidth %dMHz (%d)\n", __func__,
-			b, bw);
-		break;
-	default:
-		printk(KERN_ERR "xc5000: delivery system is not supported!\n");
-		return -EINVAL;
-	}
-
-	dprintk(1, "%s() frequency=%d (compensated to %d)\n",
-		__func__, freq, priv->freq_hz);
-
-	ret = xc_SetSignalSource(priv, priv->rf_mode);
-	if (ret != XC_RESULT_SUCCESS) {
-		printk(KERN_ERR
-			"xc5000: xc_SetSignalSource(%d) failed\n",
-			priv->rf_mode);
-		return -EREMOTEIO;
-	}
-
-	ret = xc_SetTVStandard(priv,
-		XC5000_Standard[priv->video_standard].VideoMode,
-		XC5000_Standard[priv->video_standard].AudioMode);
-	if (ret != XC_RESULT_SUCCESS) {
-		printk(KERN_ERR "xc5000: xc_SetTVStandard failed\n");
-		return -EREMOTEIO;
-	}
-
-	ret = xc_set_IF_frequency(priv, priv->if_khz);
-	if (ret != XC_RESULT_SUCCESS) {
-		printk(KERN_ERR "xc5000: xc_Set_IF_frequency(%d) failed\n",
-		       priv->if_khz);
-		return -EIO;
-	}
-
-	xc_write_reg(priv, XREG_OUTPUT_AMP, 0x8a);
-
-	xc_tune_channel(priv, priv->freq_hz, XC_TUNE_DIGITAL);
-
-	if (debug)
-		xc_debug_dump(priv);
-
-	priv->bandwidth = bw;
-
-	return 0;
-}
-
-static int xc5000_is_firmware_loaded(struct dvb_frontend *fe)
-{
-	struct xc5000_priv *priv = fe->tuner_priv;
-	int ret;
-	u16 id;
-
-	ret = xc5000_readreg(priv, XREG_PRODUCT_ID, &id);
-	if (ret == XC_RESULT_SUCCESS) {
-		if (id == XC_PRODUCT_ID_FW_NOT_LOADED)
-			ret = XC_RESULT_RESET_FAILURE;
-		else
-			ret = XC_RESULT_SUCCESS;
-	}
-
-	dprintk(1, "%s() returns %s id = 0x%x\n", __func__,
-		ret == XC_RESULT_SUCCESS ? "True" : "False", id);
-	return ret;
-}
-
-static int xc5000_set_tv_freq(struct dvb_frontend *fe,
-	struct analog_parameters *params)
-{
-	struct xc5000_priv *priv = fe->tuner_priv;
-	int ret;
-
-	dprintk(1, "%s() frequency=%d (in units of 62.5khz)\n",
-		__func__, params->frequency);
-
-	/* 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;
-
-	/* FIX ME: Some video standards may have several possible audio
-		   standards. We simply default to one of them here.
-	 */
-	if (params->std & V4L2_STD_MN) {
-		/* default to BTSC audio standard */
-		priv->video_standard = MN_NTSC_PAL_BTSC;
-		goto tune_channel;
-	}
-
-	if (params->std & V4L2_STD_PAL_BG) {
-		/* default to NICAM audio standard */
-		priv->video_standard = BG_PAL_NICAM;
-		goto tune_channel;
-	}
-
-	if (params->std & V4L2_STD_PAL_I) {
-		/* default to NICAM audio standard */
-		priv->video_standard = I_PAL_NICAM;
-		goto tune_channel;
-	}
-
-	if (params->std & V4L2_STD_PAL_DK) {
-		/* default to NICAM audio standard */
-		priv->video_standard = DK_PAL_NICAM;
-		goto tune_channel;
-	}
-
-	if (params->std & V4L2_STD_SECAM_DK) {
-		/* default to A2 DK1 audio standard */
-		priv->video_standard = DK_SECAM_A2DK1;
-		goto tune_channel;
-	}
-
-	if (params->std & V4L2_STD_SECAM_L) {
-		priv->video_standard = L_SECAM_NICAM;
-		goto tune_channel;
-	}
-
-	if (params->std & V4L2_STD_SECAM_LC) {
-		priv->video_standard = LC_SECAM_NICAM;
-		goto tune_channel;
-	}
-
-tune_channel:
-	ret = xc_SetSignalSource(priv, priv->rf_mode);
-	if (ret != XC_RESULT_SUCCESS) {
-		printk(KERN_ERR
-			"xc5000: xc_SetSignalSource(%d) failed\n",
-			priv->rf_mode);
-		return -EREMOTEIO;
-	}
-
-	ret = xc_SetTVStandard(priv,
-		XC5000_Standard[priv->video_standard].VideoMode,
-		XC5000_Standard[priv->video_standard].AudioMode);
-	if (ret != XC_RESULT_SUCCESS) {
-		printk(KERN_ERR "xc5000: xc_SetTVStandard failed\n");
-		return -EREMOTEIO;
-	}
-
-	xc_write_reg(priv, XREG_OUTPUT_AMP, 0x09);
-
-	xc_tune_channel(priv, priv->freq_hz, XC_TUNE_ANALOG);
-
-	if (debug)
-		xc_debug_dump(priv);
-
-	return 0;
-}
-
-static int xc5000_set_radio_freq(struct dvb_frontend *fe,
-	struct analog_parameters *params)
-{
-	struct xc5000_priv *priv = fe->tuner_priv;
-	int ret = -EINVAL;
-	u8 radio_input;
-
-	dprintk(1, "%s() frequency=%d (in units of khz)\n",
-		__func__, params->frequency);
-
-	if (priv->radio_input == XC5000_RADIO_NOT_CONFIGURED) {
-		dprintk(1, "%s() radio input not configured\n", __func__);
-		return -EINVAL;
-	}
-
-	if (priv->radio_input == XC5000_RADIO_FM1)
-		radio_input = FM_Radio_INPUT1;
-	else if  (priv->radio_input == XC5000_RADIO_FM2)
-		radio_input = FM_Radio_INPUT2;
-	else if  (priv->radio_input == XC5000_RADIO_FM1_MONO)
-		radio_input = FM_Radio_INPUT1_MONO;
-	else {
-		dprintk(1, "%s() unknown radio input %d\n", __func__,
-			priv->radio_input);
-		return -EINVAL;
-	}
-
-	priv->freq_hz = params->frequency * 125 / 2;
-
-	priv->rf_mode = XC_RF_MODE_AIR;
-
-	ret = xc_SetTVStandard(priv, XC5000_Standard[radio_input].VideoMode,
-			       XC5000_Standard[radio_input].AudioMode);
-
-	if (ret != XC_RESULT_SUCCESS) {
-		printk(KERN_ERR "xc5000: xc_SetTVStandard failed\n");
-		return -EREMOTEIO;
-	}
-
-	ret = xc_SetSignalSource(priv, priv->rf_mode);
-	if (ret != XC_RESULT_SUCCESS) {
-		printk(KERN_ERR
-			"xc5000: xc_SetSignalSource(%d) failed\n",
-			priv->rf_mode);
-		return -EREMOTEIO;
-	}
-
-	if ((priv->radio_input == XC5000_RADIO_FM1) ||
-				(priv->radio_input == XC5000_RADIO_FM2))
-		xc_write_reg(priv, XREG_OUTPUT_AMP, 0x09);
-	else if  (priv->radio_input == XC5000_RADIO_FM1_MONO)
-		xc_write_reg(priv, XREG_OUTPUT_AMP, 0x06);
-
-	xc_tune_channel(priv, priv->freq_hz, XC_TUNE_ANALOG);
-
-	return 0;
-}
-
-static int xc5000_set_analog_params(struct dvb_frontend *fe,
-			     struct analog_parameters *params)
-{
-	struct xc5000_priv *priv = fe->tuner_priv;
-	int ret = -EINVAL;
-
-	if (priv->i2c_props.adap == NULL)
-		return -EINVAL;
-
-	if (xc5000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS) {
-		if (xc_load_fw_and_init_tuner(fe) != XC_RESULT_SUCCESS) {
-			dprintk(1, "Unable to load firmware and init tuner\n");
-			return -EINVAL;
-		}
-	}
-
-	switch (params->mode) {
-	case V4L2_TUNER_RADIO:
-		ret = xc5000_set_radio_freq(fe, params);
-		break;
-	case V4L2_TUNER_ANALOG_TV:
-	case V4L2_TUNER_DIGITAL_TV:
-		ret = xc5000_set_tv_freq(fe, params);
-		break;
-	}
-
-	return ret;
-}
-
-
-static int xc5000_get_frequency(struct dvb_frontend *fe, u32 *freq)
-{
-	struct xc5000_priv *priv = fe->tuner_priv;
-	dprintk(1, "%s()\n", __func__);
-	*freq = priv->freq_hz;
-	return 0;
-}
-
-static int xc5000_get_if_frequency(struct dvb_frontend *fe, u32 *freq)
-{
-	struct xc5000_priv *priv = fe->tuner_priv;
-	dprintk(1, "%s()\n", __func__);
-	*freq = priv->if_khz * 1000;
-	return 0;
-}
-
-static int xc5000_get_bandwidth(struct dvb_frontend *fe, u32 *bw)
-{
-	struct xc5000_priv *priv = fe->tuner_priv;
-	dprintk(1, "%s()\n", __func__);
-
-	*bw = priv->bandwidth;
-	return 0;
-}
-
-static int xc5000_get_status(struct dvb_frontend *fe, u32 *status)
-{
-	struct xc5000_priv *priv = fe->tuner_priv;
-	u16 lock_status = 0;
-
-	xc_get_lock_status(priv, &lock_status);
-
-	dprintk(1, "%s() lock_status = 0x%08x\n", __func__, lock_status);
-
-	*status = lock_status;
-
-	return 0;
-}
-
-static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe)
-{
-	struct xc5000_priv *priv = fe->tuner_priv;
-	int ret = 0;
-
-	if (xc5000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS) {
-		ret = xc5000_fwupload(fe);
-		if (ret != XC_RESULT_SUCCESS)
-			return ret;
-	}
-
-	/* Start the tuner self-calibration process */
-	ret |= xc_initialize(priv);
-
-	/* Wait for calibration to complete.
-	 * We could continue but XC5000 will clock stretch subsequent
-	 * I2C transactions until calibration is complete.  This way we
-	 * don't have to rely on clock stretching working.
-	 */
-	xc_wait(100);
-
-	/* Default to "CABLE" mode */
-	ret |= xc_write_reg(priv, XREG_SIGNALSOURCE, XC_RF_MODE_CABLE);
-
-	return ret;
-}
-
-static int xc5000_sleep(struct dvb_frontend *fe)
-{
-	int ret;
-
-	dprintk(1, "%s()\n", __func__);
-
-	/* Avoid firmware reload on slow devices */
-	if (no_poweroff)
-		return 0;
-
-	/* According to Xceive technical support, the "powerdown" register
-	   was removed in newer versions of the firmware.  The "supported"
-	   way to sleep the tuner is to pull the reset pin low for 10ms */
-	ret = xc5000_TunerReset(fe);
-	if (ret != XC_RESULT_SUCCESS) {
-		printk(KERN_ERR
-			"xc5000: %s() unable to shutdown tuner\n",
-			__func__);
-		return -EREMOTEIO;
-	} else
-		return XC_RESULT_SUCCESS;
-}
-
-static int xc5000_init(struct dvb_frontend *fe)
-{
-	struct xc5000_priv *priv = fe->tuner_priv;
-	dprintk(1, "%s()\n", __func__);
-
-	if (xc_load_fw_and_init_tuner(fe) != XC_RESULT_SUCCESS) {
-		printk(KERN_ERR "xc5000: Unable to initialise tuner\n");
-		return -EREMOTEIO;
-	}
-
-	if (debug)
-		xc_debug_dump(priv);
-
-	return 0;
-}
-
-static int xc5000_release(struct dvb_frontend *fe)
-{
-	struct xc5000_priv *priv = fe->tuner_priv;
-
-	dprintk(1, "%s()\n", __func__);
-
-	mutex_lock(&xc5000_list_mutex);
-
-	if (priv)
-		hybrid_tuner_release_state(priv);
-
-	mutex_unlock(&xc5000_list_mutex);
-
-	fe->tuner_priv = NULL;
-
-	return 0;
-}
-
-static int xc5000_set_config(struct dvb_frontend *fe, void *priv_cfg)
-{
-	struct xc5000_priv *priv = fe->tuner_priv;
-	struct xc5000_config *p = priv_cfg;
-
-	dprintk(1, "%s()\n", __func__);
-
-	if (p->if_khz)
-		priv->if_khz = p->if_khz;
-
-	if (p->radio_input)
-		priv->radio_input = p->radio_input;
-
-	return 0;
-}
-
-
-static const struct dvb_tuner_ops xc5000_tuner_ops = {
-	.info = {
-		.name           = "Xceive XC5000",
-		.frequency_min  =    1000000,
-		.frequency_max  = 1023000000,
-		.frequency_step =      50000,
-	},
-
-	.release	   = xc5000_release,
-	.init		   = xc5000_init,
-	.sleep		   = xc5000_sleep,
-
-	.set_config	   = xc5000_set_config,
-	.set_params	   = xc5000_set_params,
-	.set_analog_params = xc5000_set_analog_params,
-	.get_frequency	   = xc5000_get_frequency,
-	.get_if_frequency  = xc5000_get_if_frequency,
-	.get_bandwidth	   = xc5000_get_bandwidth,
-	.get_status	   = xc5000_get_status
-};
-
-struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe,
-				   struct i2c_adapter *i2c,
-				   const struct xc5000_config *cfg)
-{
-	struct xc5000_priv *priv = NULL;
-	int instance;
-	u16 id = 0;
-
-	dprintk(1, "%s(%d-%04x)\n", __func__,
-		i2c ? i2c_adapter_id(i2c) : -1,
-		cfg ? cfg->i2c_address : -1);
-
-	mutex_lock(&xc5000_list_mutex);
-
-	instance = hybrid_tuner_request_state(struct xc5000_priv, priv,
-					      hybrid_tuner_instance_list,
-					      i2c, cfg->i2c_address, "xc5000");
-	switch (instance) {
-	case 0:
-		goto fail;
-		break;
-	case 1:
-		/* new tuner instance */
-		priv->bandwidth = 6000000;
-		fe->tuner_priv = priv;
-		break;
-	default:
-		/* existing tuner instance */
-		fe->tuner_priv = priv;
-		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;
-	}
-
-	if (priv->xtal_khz == 0)
-		priv->xtal_khz = cfg->xtal_khz;
-
-	if (priv->radio_input == 0)
-		priv->radio_input = cfg->radio_input;
-
-	/* don't override chip id if it's already been set
-	   unless explicitly specified */
-	if ((priv->chip_id == 0) || (cfg->chip_id))
-		/* use default chip id if none specified, set to 0 so
-		   it can be overridden if this is a hybrid driver */
-		priv->chip_id = (cfg->chip_id) ? cfg->chip_id : 0;
-
-	/* Check if firmware has been loaded. It is possible that another
-	   instance of the driver has loaded the firmware.
-	 */
-	if (xc5000_readreg(priv, XREG_PRODUCT_ID, &id) != XC_RESULT_SUCCESS)
-		goto fail;
-
-	switch (id) {
-	case XC_PRODUCT_ID_FW_LOADED:
-		printk(KERN_INFO
-			"xc5000: Successfully identified at address 0x%02x\n",
-			cfg->i2c_address);
-		printk(KERN_INFO
-			"xc5000: Firmware has been loaded previously\n");
-		break;
-	case XC_PRODUCT_ID_FW_NOT_LOADED:
-		printk(KERN_INFO
-			"xc5000: Successfully identified at address 0x%02x\n",
-			cfg->i2c_address);
-		printk(KERN_INFO
-			"xc5000: Firmware has not been loaded previously\n");
-		break;
-	default:
-		printk(KERN_ERR
-			"xc5000: Device not found at addr 0x%02x (0x%x)\n",
-			cfg->i2c_address, id);
-		goto fail;
-	}
-
-	mutex_unlock(&xc5000_list_mutex);
-
-	memcpy(&fe->ops.tuner_ops, &xc5000_tuner_ops,
-		sizeof(struct dvb_tuner_ops));
-
-	return fe;
-fail:
-	mutex_unlock(&xc5000_list_mutex);
-
-	xc5000_release(fe);
-	return NULL;
-}
-EXPORT_SYMBOL(xc5000_attach);
-
-MODULE_AUTHOR("Steven Toth");
-MODULE_DESCRIPTION("Xceive xc5000 silicon tuner driver");
-MODULE_LICENSE("GPL");
-MODULE_FIRMWARE(XC5000A_FIRMWARE);
-MODULE_FIRMWARE(XC5000C_FIRMWARE);
diff --git a/drivers/media/common/tuners/xc5000.h b/drivers/media/common/tuners/xc5000.h
deleted file mode 100644
index b1a5474..0000000
--- a/drivers/media/common/tuners/xc5000.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- *  Driver for Xceive XC5000 "QAM/8VSB single chip tuner"
- *
- *  Copyright (c) 2007 Steven Toth <stoth@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 __XC5000_H__
-#define __XC5000_H__
-
-#include <linux/firmware.h>
-
-struct dvb_frontend;
-struct i2c_adapter;
-
-#define XC5000A 1
-#define XC5000C 2
-
-struct xc5000_config {
-	u8   i2c_address;
-	u32  if_khz;
-	u8   radio_input;
-	u16  xtal_khz;
-
-	int chip_id;
-};
-
-/* xc5000 callback command */
-#define XC5000_TUNER_RESET		0
-
-/* Possible Radio inputs */
-#define XC5000_RADIO_NOT_CONFIGURED		0
-#define XC5000_RADIO_FM1			1
-#define XC5000_RADIO_FM2			2
-#define XC5000_RADIO_FM1_MONO			3
-
-/* For each bridge framework, when it attaches either analog or digital,
- * it has to store a reference back to its _core equivalent structure,
- * so that it can service the hardware by steering gpio's etc.
- * Each bridge implementation is different so cast devptr accordingly.
- * The xc5000 driver cares not for this value, other than ensuring
- * it's passed back to a bridge during tuner_callback().
- */
-
-#if defined(CONFIG_MEDIA_TUNER_XC5000) || \
-    (defined(CONFIG_MEDIA_TUNER_XC5000_MODULE) && defined(MODULE))
-extern struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe,
-					  struct i2c_adapter *i2c,
-					  const struct xc5000_config *cfg);
-#else
-static inline struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe,
-						 struct i2c_adapter *i2c,
-						 const struct xc5000_config *cfg)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif
-
-#endif
diff --git a/drivers/media/dvb-core/Kconfig b/drivers/media/dvb-core/Kconfig
new file mode 100644
index 0000000..fa7a249
--- /dev/null
+++ b/drivers/media/dvb-core/Kconfig
@@ -0,0 +1,29 @@
+#
+# DVB device configuration
+#
+
+config DVB_MAX_ADAPTERS
+	int "maximum number of DVB/ATSC adapters"
+	depends on DVB_CORE
+	default 8
+	range 1 255
+	help
+	  Maximum number of DVB/ATSC adapters. Increasing this number
+	  increases the memory consumption of the DVB subsystem even
+	  if a much lower number of DVB/ATSC adapters is present.
+	  Only values in the range 4-32 are tested.
+
+	  If you are unsure about this, use the default value 8
+
+config DVB_DYNAMIC_MINORS
+	bool "Dynamic DVB minor allocation"
+	depends on DVB_CORE
+	default n
+	help
+	  If you say Y here, the DVB subsystem will use dynamic minor
+	  allocation for any device that uses the DVB major number.
+	  This means that you can have more than 4 of a single type
+	  of device (like demuxes and frontends) per adapter, but udev
+	  will be required to manage the device nodes.
+
+	  If you are unsure about this, say N here.
diff --git a/drivers/media/dvb-core/Makefile b/drivers/media/dvb-core/Makefile
new file mode 100644
index 0000000..8f22bcd
--- /dev/null
+++ b/drivers/media/dvb-core/Makefile
@@ -0,0 +1,11 @@
+#
+# Makefile for the kernel DVB device drivers.
+#
+
+dvb-net-$(CONFIG_DVB_NET) := dvb_net.o
+
+dvb-core-objs := dvbdev.o dmxdev.o dvb_demux.o dvb_filter.o 	\
+		 dvb_ca_en50221.o dvb_frontend.o 		\
+		 $(dvb-net-y) dvb_ringbuffer.o dvb_math.o
+
+obj-$(CONFIG_DVB_CORE) += dvb-core.o
diff --git a/drivers/media/dvb-core/demux.h b/drivers/media/dvb-core/demux.h
new file mode 100644
index 0000000..eb91fd8
--- /dev/null
+++ b/drivers/media/dvb-core/demux.h
@@ -0,0 +1,280 @@
+/*
+ * demux.h
+ *
+ * Copyright (c) 2002 Convergence GmbH
+ *
+ * based on code:
+ * Copyright (c) 2000 Nokia Research Center
+ *                    Tampere, FINLAND
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public 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 __DEMUX_H
+#define __DEMUX_H
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/list.h>
+#include <linux/time.h>
+#include <linux/dvb/dmx.h>
+
+/*--------------------------------------------------------------------------*/
+/* Common definitions */
+/*--------------------------------------------------------------------------*/
+
+/*
+ * DMX_MAX_FILTER_SIZE: Maximum length (in bytes) of a section/PES filter.
+ */
+
+#ifndef DMX_MAX_FILTER_SIZE
+#define DMX_MAX_FILTER_SIZE 18
+#endif
+
+/*
+ * DMX_MAX_SECFEED_SIZE: Maximum length (in bytes) of a private section feed filter.
+ */
+
+#ifndef DMX_MAX_SECTION_SIZE
+#define DMX_MAX_SECTION_SIZE 4096
+#endif
+#ifndef DMX_MAX_SECFEED_SIZE
+#define DMX_MAX_SECFEED_SIZE (DMX_MAX_SECTION_SIZE + 188)
+#endif
+
+
+/*
+ * enum dmx_success: Success codes for the Demux Callback API.
+ */
+
+enum dmx_success {
+  DMX_OK = 0, /* Received Ok */
+  DMX_LENGTH_ERROR, /* Incorrect length */
+  DMX_OVERRUN_ERROR, /* Receiver ring buffer overrun */
+  DMX_CRC_ERROR, /* Incorrect CRC */
+  DMX_FRAME_ERROR, /* Frame alignment error */
+  DMX_FIFO_ERROR, /* Receiver FIFO overrun */
+  DMX_MISSED_ERROR /* Receiver missed packet */
+} ;
+
+/*--------------------------------------------------------------------------*/
+/* TS packet reception */
+/*--------------------------------------------------------------------------*/
+
+/* TS filter type for set() */
+
+#define TS_PACKET       1   /* send TS packets (188 bytes) to callback (default) */
+#define	TS_PAYLOAD_ONLY 2   /* in case TS_PACKET is set, only send the TS
+			       payload (<=184 bytes per packet) to callback */
+#define TS_DECODER      4   /* send stream to built-in decoder (if present) */
+#define TS_DEMUX        8   /* in case TS_PACKET is set, send the TS to
+			       the demux device, not to the dvr device */
+
+/* PES type for filters which write to built-in decoder */
+/* these should be kept identical to the types in dmx.h */
+
+enum dmx_ts_pes
+{  /* also send packets to decoder (if it exists) */
+	DMX_TS_PES_AUDIO0,
+	DMX_TS_PES_VIDEO0,
+	DMX_TS_PES_TELETEXT0,
+	DMX_TS_PES_SUBTITLE0,
+	DMX_TS_PES_PCR0,
+
+	DMX_TS_PES_AUDIO1,
+	DMX_TS_PES_VIDEO1,
+	DMX_TS_PES_TELETEXT1,
+	DMX_TS_PES_SUBTITLE1,
+	DMX_TS_PES_PCR1,
+
+	DMX_TS_PES_AUDIO2,
+	DMX_TS_PES_VIDEO2,
+	DMX_TS_PES_TELETEXT2,
+	DMX_TS_PES_SUBTITLE2,
+	DMX_TS_PES_PCR2,
+
+	DMX_TS_PES_AUDIO3,
+	DMX_TS_PES_VIDEO3,
+	DMX_TS_PES_TELETEXT3,
+	DMX_TS_PES_SUBTITLE3,
+	DMX_TS_PES_PCR3,
+
+	DMX_TS_PES_OTHER
+};
+
+#define DMX_TS_PES_AUDIO    DMX_TS_PES_AUDIO0
+#define DMX_TS_PES_VIDEO    DMX_TS_PES_VIDEO0
+#define DMX_TS_PES_TELETEXT DMX_TS_PES_TELETEXT0
+#define DMX_TS_PES_SUBTITLE DMX_TS_PES_SUBTITLE0
+#define DMX_TS_PES_PCR      DMX_TS_PES_PCR0
+
+
+struct dmx_ts_feed {
+	int is_filtering; /* Set to non-zero when filtering in progress */
+	struct dmx_demux *parent; /* Back-pointer */
+	void *priv; /* Pointer to private data of the API client */
+	int (*set) (struct dmx_ts_feed *feed,
+		    u16 pid,
+		    int type,
+		    enum dmx_ts_pes pes_type,
+		    size_t circular_buffer_size,
+		    struct timespec timeout);
+	int (*start_filtering) (struct dmx_ts_feed* feed);
+	int (*stop_filtering) (struct dmx_ts_feed* feed);
+};
+
+/*--------------------------------------------------------------------------*/
+/* Section reception */
+/*--------------------------------------------------------------------------*/
+
+struct dmx_section_filter {
+	u8 filter_value [DMX_MAX_FILTER_SIZE];
+	u8 filter_mask [DMX_MAX_FILTER_SIZE];
+	u8 filter_mode [DMX_MAX_FILTER_SIZE];
+	struct dmx_section_feed* parent; /* Back-pointer */
+	void* priv; /* Pointer to private data of the API client */
+};
+
+struct dmx_section_feed {
+	int is_filtering; /* Set to non-zero when filtering in progress */
+	struct dmx_demux* parent; /* Back-pointer */
+	void* priv; /* Pointer to private data of the API client */
+
+	int check_crc;
+	u32 crc_val;
+
+	u8 *secbuf;
+	u8 secbuf_base[DMX_MAX_SECFEED_SIZE];
+	u16 secbufp, seclen, tsfeedp;
+
+	int (*set) (struct dmx_section_feed* feed,
+		    u16 pid,
+		    size_t circular_buffer_size,
+		    int check_crc);
+	int (*allocate_filter) (struct dmx_section_feed* feed,
+				struct dmx_section_filter** filter);
+	int (*release_filter) (struct dmx_section_feed* feed,
+			       struct dmx_section_filter* filter);
+	int (*start_filtering) (struct dmx_section_feed* feed);
+	int (*stop_filtering) (struct dmx_section_feed* feed);
+};
+
+/*--------------------------------------------------------------------------*/
+/* Callback functions */
+/*--------------------------------------------------------------------------*/
+
+typedef int (*dmx_ts_cb) ( const u8 * buffer1,
+			   size_t buffer1_length,
+			   const u8 * buffer2,
+			   size_t buffer2_length,
+			   struct dmx_ts_feed* source,
+			   enum dmx_success success);
+
+typedef int (*dmx_section_cb) (	const u8 * buffer1,
+				size_t buffer1_len,
+				const u8 * buffer2,
+				size_t buffer2_len,
+				struct dmx_section_filter * source,
+				enum dmx_success success);
+
+/*--------------------------------------------------------------------------*/
+/* DVB Front-End */
+/*--------------------------------------------------------------------------*/
+
+enum dmx_frontend_source {
+	DMX_MEMORY_FE,
+	DMX_FRONTEND_0,
+	DMX_FRONTEND_1,
+	DMX_FRONTEND_2,
+	DMX_FRONTEND_3,
+	DMX_STREAM_0,    /* external stream input, e.g. LVDS */
+	DMX_STREAM_1,
+	DMX_STREAM_2,
+	DMX_STREAM_3
+};
+
+struct dmx_frontend {
+	struct list_head connectivity_list; /* List of front-ends that can
+					       be connected to a particular
+					       demux */
+	enum dmx_frontend_source source;
+};
+
+/*--------------------------------------------------------------------------*/
+/* MPEG-2 TS Demux */
+/*--------------------------------------------------------------------------*/
+
+/*
+ * Flags OR'ed in the capabilities field of struct dmx_demux.
+ */
+
+#define DMX_TS_FILTERING                        1
+#define DMX_PES_FILTERING                       2
+#define DMX_SECTION_FILTERING                   4
+#define DMX_MEMORY_BASED_FILTERING              8    /* write() available */
+#define DMX_CRC_CHECKING                        16
+#define DMX_TS_DESCRAMBLING                     32
+
+/*
+ * Demux resource type identifier.
+*/
+
+/*
+ * DMX_FE_ENTRY(): Casts elements in the list of registered
+ * front-ends from the generic type struct list_head
+ * to the type * struct dmx_frontend
+ *.
+*/
+
+#define DMX_FE_ENTRY(list) list_entry(list, struct dmx_frontend, connectivity_list)
+
+struct dmx_demux {
+	u32 capabilities;            /* Bitfield of capability flags */
+	struct dmx_frontend* frontend;    /* Front-end connected to the demux */
+	void* priv;                  /* Pointer to private data of the API client */
+	int (*open) (struct dmx_demux* demux);
+	int (*close) (struct dmx_demux* demux);
+	int (*write) (struct dmx_demux* demux, const char __user *buf, size_t count);
+	int (*allocate_ts_feed) (struct dmx_demux* demux,
+				 struct dmx_ts_feed** feed,
+				 dmx_ts_cb callback);
+	int (*release_ts_feed) (struct dmx_demux* demux,
+				struct dmx_ts_feed* feed);
+	int (*allocate_section_feed) (struct dmx_demux* demux,
+				      struct dmx_section_feed** feed,
+				      dmx_section_cb callback);
+	int (*release_section_feed) (struct dmx_demux* demux,
+				     struct dmx_section_feed* feed);
+	int (*add_frontend) (struct dmx_demux* demux,
+			     struct dmx_frontend* frontend);
+	int (*remove_frontend) (struct dmx_demux* demux,
+				struct dmx_frontend* frontend);
+	struct list_head* (*get_frontends) (struct dmx_demux* demux);
+	int (*connect_frontend) (struct dmx_demux* demux,
+				 struct dmx_frontend* frontend);
+	int (*disconnect_frontend) (struct dmx_demux* demux);
+
+	int (*get_pes_pids) (struct dmx_demux* demux, u16 *pids);
+
+	int (*get_caps) (struct dmx_demux* demux, struct dmx_caps *caps);
+
+	int (*set_source) (struct dmx_demux* demux, const dmx_source_t *src);
+
+	int (*get_stc) (struct dmx_demux* demux, unsigned int num,
+			u64 *stc, unsigned int *base);
+};
+
+#endif /* #ifndef __DEMUX_H */
diff --git a/drivers/media/dvb-core/dmxdev.c b/drivers/media/dvb-core/dmxdev.c
new file mode 100644
index 0000000..889c9c1
--- /dev/null
+++ b/drivers/media/dvb-core/dmxdev.c
@@ -0,0 +1,1275 @@
+/*
+ * dmxdev.c - DVB demultiplexer device
+ *
+ * Copyright (C) 2000 Ralph Metzler & Marcus Metzler
+ *		      for convergence integrated media GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public 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/sched.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/module.h>
+#include <linux/poll.h>
+#include <linux/ioctl.h>
+#include <linux/wait.h>
+#include <asm/uaccess.h>
+#include "dmxdev.h"
+
+static int debug;
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
+
+#define dprintk	if (debug) printk
+
+static int dvb_dmxdev_buffer_write(struct dvb_ringbuffer *buf,
+				   const u8 *src, size_t len)
+{
+	ssize_t free;
+
+	if (!len)
+		return 0;
+	if (!buf->data)
+		return 0;
+
+	free = dvb_ringbuffer_free(buf);
+	if (len > free) {
+		dprintk("dmxdev: buffer overflow\n");
+		return -EOVERFLOW;
+	}
+
+	return dvb_ringbuffer_write(buf, src, len);
+}
+
+static ssize_t dvb_dmxdev_buffer_read(struct dvb_ringbuffer *src,
+				      int non_blocking, char __user *buf,
+				      size_t count, loff_t *ppos)
+{
+	size_t todo;
+	ssize_t avail;
+	ssize_t ret = 0;
+
+	if (!src->data)
+		return 0;
+
+	if (src->error) {
+		ret = src->error;
+		dvb_ringbuffer_flush(src);
+		return ret;
+	}
+
+	for (todo = count; todo > 0; todo -= ret) {
+		if (non_blocking && dvb_ringbuffer_empty(src)) {
+			ret = -EWOULDBLOCK;
+			break;
+		}
+
+		ret = wait_event_interruptible(src->queue,
+					       !dvb_ringbuffer_empty(src) ||
+					       (src->error != 0));
+		if (ret < 0)
+			break;
+
+		if (src->error) {
+			ret = src->error;
+			dvb_ringbuffer_flush(src);
+			break;
+		}
+
+		avail = dvb_ringbuffer_avail(src);
+		if (avail > todo)
+			avail = todo;
+
+		ret = dvb_ringbuffer_read_user(src, buf, avail);
+		if (ret < 0)
+			break;
+
+		buf += ret;
+	}
+
+	return (count - todo) ? (count - todo) : ret;
+}
+
+static struct dmx_frontend *get_fe(struct dmx_demux *demux, int type)
+{
+	struct list_head *head, *pos;
+
+	head = demux->get_frontends(demux);
+	if (!head)
+		return NULL;
+	list_for_each(pos, head)
+		if (DMX_FE_ENTRY(pos)->source == type)
+			return DMX_FE_ENTRY(pos);
+
+	return NULL;
+}
+
+static int dvb_dvr_open(struct inode *inode, struct file *file)
+{
+	struct dvb_device *dvbdev = file->private_data;
+	struct dmxdev *dmxdev = dvbdev->priv;
+	struct dmx_frontend *front;
+
+	dprintk("function : %s\n", __func__);
+
+	if (mutex_lock_interruptible(&dmxdev->mutex))
+		return -ERESTARTSYS;
+
+	if (dmxdev->exit) {
+		mutex_unlock(&dmxdev->mutex);
+		return -ENODEV;
+	}
+
+	if ((file->f_flags & O_ACCMODE) == O_RDWR) {
+		if (!(dmxdev->capabilities & DMXDEV_CAP_DUPLEX)) {
+			mutex_unlock(&dmxdev->mutex);
+			return -EOPNOTSUPP;
+		}
+	}
+
+	if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
+		void *mem;
+		if (!dvbdev->readers) {
+			mutex_unlock(&dmxdev->mutex);
+			return -EBUSY;
+		}
+		mem = vmalloc(DVR_BUFFER_SIZE);
+		if (!mem) {
+			mutex_unlock(&dmxdev->mutex);
+			return -ENOMEM;
+		}
+		dvb_ringbuffer_init(&dmxdev->dvr_buffer, mem, DVR_BUFFER_SIZE);
+		dvbdev->readers--;
+	}
+
+	if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
+		dmxdev->dvr_orig_fe = dmxdev->demux->frontend;
+
+		if (!dmxdev->demux->write) {
+			mutex_unlock(&dmxdev->mutex);
+			return -EOPNOTSUPP;
+		}
+
+		front = get_fe(dmxdev->demux, DMX_MEMORY_FE);
+
+		if (!front) {
+			mutex_unlock(&dmxdev->mutex);
+			return -EINVAL;
+		}
+		dmxdev->demux->disconnect_frontend(dmxdev->demux);
+		dmxdev->demux->connect_frontend(dmxdev->demux, front);
+	}
+	dvbdev->users++;
+	mutex_unlock(&dmxdev->mutex);
+	return 0;
+}
+
+static int dvb_dvr_release(struct inode *inode, struct file *file)
+{
+	struct dvb_device *dvbdev = file->private_data;
+	struct dmxdev *dmxdev = dvbdev->priv;
+
+	mutex_lock(&dmxdev->mutex);
+
+	if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
+		dmxdev->demux->disconnect_frontend(dmxdev->demux);
+		dmxdev->demux->connect_frontend(dmxdev->demux,
+						dmxdev->dvr_orig_fe);
+	}
+	if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
+		dvbdev->readers++;
+		if (dmxdev->dvr_buffer.data) {
+			void *mem = dmxdev->dvr_buffer.data;
+			mb();
+			spin_lock_irq(&dmxdev->lock);
+			dmxdev->dvr_buffer.data = NULL;
+			spin_unlock_irq(&dmxdev->lock);
+			vfree(mem);
+		}
+	}
+	/* TODO */
+	dvbdev->users--;
+	if (dvbdev->users == 1 && dmxdev->exit == 1) {
+		fops_put(file->f_op);
+		file->f_op = NULL;
+		mutex_unlock(&dmxdev->mutex);
+		wake_up(&dvbdev->wait_queue);
+	} else
+		mutex_unlock(&dmxdev->mutex);
+
+	return 0;
+}
+
+static ssize_t dvb_dvr_write(struct file *file, const char __user *buf,
+			     size_t count, loff_t *ppos)
+{
+	struct dvb_device *dvbdev = file->private_data;
+	struct dmxdev *dmxdev = dvbdev->priv;
+	int ret;
+
+	if (!dmxdev->demux->write)
+		return -EOPNOTSUPP;
+	if ((file->f_flags & O_ACCMODE) != O_WRONLY)
+		return -EINVAL;
+	if (mutex_lock_interruptible(&dmxdev->mutex))
+		return -ERESTARTSYS;
+
+	if (dmxdev->exit) {
+		mutex_unlock(&dmxdev->mutex);
+		return -ENODEV;
+	}
+	ret = dmxdev->demux->write(dmxdev->demux, buf, count);
+	mutex_unlock(&dmxdev->mutex);
+	return ret;
+}
+
+static ssize_t dvb_dvr_read(struct file *file, char __user *buf, size_t count,
+			    loff_t *ppos)
+{
+	struct dvb_device *dvbdev = file->private_data;
+	struct dmxdev *dmxdev = dvbdev->priv;
+
+	if (dmxdev->exit)
+		return -ENODEV;
+
+	return dvb_dmxdev_buffer_read(&dmxdev->dvr_buffer,
+				      file->f_flags & O_NONBLOCK,
+				      buf, count, ppos);
+}
+
+static int dvb_dvr_set_buffer_size(struct dmxdev *dmxdev,
+				      unsigned long size)
+{
+	struct dvb_ringbuffer *buf = &dmxdev->dvr_buffer;
+	void *newmem;
+	void *oldmem;
+
+	dprintk("function : %s\n", __func__);
+
+	if (buf->size == size)
+		return 0;
+	if (!size)
+		return -EINVAL;
+
+	newmem = vmalloc(size);
+	if (!newmem)
+		return -ENOMEM;
+
+	oldmem = buf->data;
+
+	spin_lock_irq(&dmxdev->lock);
+	buf->data = newmem;
+	buf->size = size;
+
+	/* reset and not flush in case the buffer shrinks */
+	dvb_ringbuffer_reset(buf);
+	spin_unlock_irq(&dmxdev->lock);
+
+	vfree(oldmem);
+
+	return 0;
+}
+
+static inline void dvb_dmxdev_filter_state_set(struct dmxdev_filter
+					       *dmxdevfilter, int state)
+{
+	spin_lock_irq(&dmxdevfilter->dev->lock);
+	dmxdevfilter->state = state;
+	spin_unlock_irq(&dmxdevfilter->dev->lock);
+}
+
+static int dvb_dmxdev_set_buffer_size(struct dmxdev_filter *dmxdevfilter,
+				      unsigned long size)
+{
+	struct dvb_ringbuffer *buf = &dmxdevfilter->buffer;
+	void *newmem;
+	void *oldmem;
+
+	if (buf->size == size)
+		return 0;
+	if (!size)
+		return -EINVAL;
+	if (dmxdevfilter->state >= DMXDEV_STATE_GO)
+		return -EBUSY;
+
+	newmem = vmalloc(size);
+	if (!newmem)
+		return -ENOMEM;
+
+	oldmem = buf->data;
+
+	spin_lock_irq(&dmxdevfilter->dev->lock);
+	buf->data = newmem;
+	buf->size = size;
+
+	/* reset and not flush in case the buffer shrinks */
+	dvb_ringbuffer_reset(buf);
+	spin_unlock_irq(&dmxdevfilter->dev->lock);
+
+	vfree(oldmem);
+
+	return 0;
+}
+
+static void dvb_dmxdev_filter_timeout(unsigned long data)
+{
+	struct dmxdev_filter *dmxdevfilter = (struct dmxdev_filter *)data;
+
+	dmxdevfilter->buffer.error = -ETIMEDOUT;
+	spin_lock_irq(&dmxdevfilter->dev->lock);
+	dmxdevfilter->state = DMXDEV_STATE_TIMEDOUT;
+	spin_unlock_irq(&dmxdevfilter->dev->lock);
+	wake_up(&dmxdevfilter->buffer.queue);
+}
+
+static void dvb_dmxdev_filter_timer(struct dmxdev_filter *dmxdevfilter)
+{
+	struct dmx_sct_filter_params *para = &dmxdevfilter->params.sec;
+
+	del_timer(&dmxdevfilter->timer);
+	if (para->timeout) {
+		dmxdevfilter->timer.function = dvb_dmxdev_filter_timeout;
+		dmxdevfilter->timer.data = (unsigned long)dmxdevfilter;
+		dmxdevfilter->timer.expires =
+		    jiffies + 1 + (HZ / 2 + HZ * para->timeout) / 1000;
+		add_timer(&dmxdevfilter->timer);
+	}
+}
+
+static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
+				       const u8 *buffer2, size_t buffer2_len,
+				       struct dmx_section_filter *filter,
+				       enum dmx_success success)
+{
+	struct dmxdev_filter *dmxdevfilter = filter->priv;
+	int ret;
+
+	if (dmxdevfilter->buffer.error) {
+		wake_up(&dmxdevfilter->buffer.queue);
+		return 0;
+	}
+	spin_lock(&dmxdevfilter->dev->lock);
+	if (dmxdevfilter->state != DMXDEV_STATE_GO) {
+		spin_unlock(&dmxdevfilter->dev->lock);
+		return 0;
+	}
+	del_timer(&dmxdevfilter->timer);
+	dprintk("dmxdev: section callback %*ph\n", 6, buffer1);
+	ret = dvb_dmxdev_buffer_write(&dmxdevfilter->buffer, buffer1,
+				      buffer1_len);
+	if (ret == buffer1_len) {
+		ret = dvb_dmxdev_buffer_write(&dmxdevfilter->buffer, buffer2,
+					      buffer2_len);
+	}
+	if (ret < 0) {
+		dvb_ringbuffer_flush(&dmxdevfilter->buffer);
+		dmxdevfilter->buffer.error = ret;
+	}
+	if (dmxdevfilter->params.sec.flags & DMX_ONESHOT)
+		dmxdevfilter->state = DMXDEV_STATE_DONE;
+	spin_unlock(&dmxdevfilter->dev->lock);
+	wake_up(&dmxdevfilter->buffer.queue);
+	return 0;
+}
+
+static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
+				  const u8 *buffer2, size_t buffer2_len,
+				  struct dmx_ts_feed *feed,
+				  enum dmx_success success)
+{
+	struct dmxdev_filter *dmxdevfilter = feed->priv;
+	struct dvb_ringbuffer *buffer;
+	int ret;
+
+	spin_lock(&dmxdevfilter->dev->lock);
+	if (dmxdevfilter->params.pes.output == DMX_OUT_DECODER) {
+		spin_unlock(&dmxdevfilter->dev->lock);
+		return 0;
+	}
+
+	if (dmxdevfilter->params.pes.output == DMX_OUT_TAP
+	    || dmxdevfilter->params.pes.output == DMX_OUT_TSDEMUX_TAP)
+		buffer = &dmxdevfilter->buffer;
+	else
+		buffer = &dmxdevfilter->dev->dvr_buffer;
+	if (buffer->error) {
+		spin_unlock(&dmxdevfilter->dev->lock);
+		wake_up(&buffer->queue);
+		return 0;
+	}
+	ret = dvb_dmxdev_buffer_write(buffer, buffer1, buffer1_len);
+	if (ret == buffer1_len)
+		ret = dvb_dmxdev_buffer_write(buffer, buffer2, buffer2_len);
+	if (ret < 0) {
+		dvb_ringbuffer_flush(buffer);
+		buffer->error = ret;
+	}
+	spin_unlock(&dmxdevfilter->dev->lock);
+	wake_up(&buffer->queue);
+	return 0;
+}
+
+/* stop feed but only mark the specified filter as stopped (state set) */
+static int dvb_dmxdev_feed_stop(struct dmxdev_filter *dmxdevfilter)
+{
+	struct dmxdev_feed *feed;
+
+	dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_SET);
+
+	switch (dmxdevfilter->type) {
+	case DMXDEV_TYPE_SEC:
+		del_timer(&dmxdevfilter->timer);
+		dmxdevfilter->feed.sec->stop_filtering(dmxdevfilter->feed.sec);
+		break;
+	case DMXDEV_TYPE_PES:
+		list_for_each_entry(feed, &dmxdevfilter->feed.ts, next)
+			feed->ts->stop_filtering(feed->ts);
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+/* start feed associated with the specified filter */
+static int dvb_dmxdev_feed_start(struct dmxdev_filter *filter)
+{
+	struct dmxdev_feed *feed;
+	int ret;
+
+	dvb_dmxdev_filter_state_set(filter, DMXDEV_STATE_GO);
+
+	switch (filter->type) {
+	case DMXDEV_TYPE_SEC:
+		return filter->feed.sec->start_filtering(filter->feed.sec);
+	case DMXDEV_TYPE_PES:
+		list_for_each_entry(feed, &filter->feed.ts, next) {
+			ret = feed->ts->start_filtering(feed->ts);
+			if (ret < 0) {
+				dvb_dmxdev_feed_stop(filter);
+				return ret;
+			}
+		}
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/* restart section feed if it has filters left associated with it,
+   otherwise release the feed */
+static int dvb_dmxdev_feed_restart(struct dmxdev_filter *filter)
+{
+	int i;
+	struct dmxdev *dmxdev = filter->dev;
+	u16 pid = filter->params.sec.pid;
+
+	for (i = 0; i < dmxdev->filternum; i++)
+		if (dmxdev->filter[i].state >= DMXDEV_STATE_GO &&
+		    dmxdev->filter[i].type == DMXDEV_TYPE_SEC &&
+		    dmxdev->filter[i].params.sec.pid == pid) {
+			dvb_dmxdev_feed_start(&dmxdev->filter[i]);
+			return 0;
+		}
+
+	filter->dev->demux->release_section_feed(dmxdev->demux,
+						 filter->feed.sec);
+
+	return 0;
+}
+
+static int dvb_dmxdev_filter_stop(struct dmxdev_filter *dmxdevfilter)
+{
+	struct dmxdev_feed *feed;
+	struct dmx_demux *demux;
+
+	if (dmxdevfilter->state < DMXDEV_STATE_GO)
+		return 0;
+
+	switch (dmxdevfilter->type) {
+	case DMXDEV_TYPE_SEC:
+		if (!dmxdevfilter->feed.sec)
+			break;
+		dvb_dmxdev_feed_stop(dmxdevfilter);
+		if (dmxdevfilter->filter.sec)
+			dmxdevfilter->feed.sec->
+			    release_filter(dmxdevfilter->feed.sec,
+					   dmxdevfilter->filter.sec);
+		dvb_dmxdev_feed_restart(dmxdevfilter);
+		dmxdevfilter->feed.sec = NULL;
+		break;
+	case DMXDEV_TYPE_PES:
+		dvb_dmxdev_feed_stop(dmxdevfilter);
+		demux = dmxdevfilter->dev->demux;
+		list_for_each_entry(feed, &dmxdevfilter->feed.ts, next) {
+			demux->release_ts_feed(demux, feed->ts);
+			feed->ts = NULL;
+		}
+		break;
+	default:
+		if (dmxdevfilter->state == DMXDEV_STATE_ALLOCATED)
+			return 0;
+		return -EINVAL;
+	}
+
+	dvb_ringbuffer_flush(&dmxdevfilter->buffer);
+	return 0;
+}
+
+static void dvb_dmxdev_delete_pids(struct dmxdev_filter *dmxdevfilter)
+{
+	struct dmxdev_feed *feed, *tmp;
+
+	/* delete all PIDs */
+	list_for_each_entry_safe(feed, tmp, &dmxdevfilter->feed.ts, next) {
+		list_del(&feed->next);
+		kfree(feed);
+	}
+
+	BUG_ON(!list_empty(&dmxdevfilter->feed.ts));
+}
+
+static inline int dvb_dmxdev_filter_reset(struct dmxdev_filter *dmxdevfilter)
+{
+	if (dmxdevfilter->state < DMXDEV_STATE_SET)
+		return 0;
+
+	if (dmxdevfilter->type == DMXDEV_TYPE_PES)
+		dvb_dmxdev_delete_pids(dmxdevfilter);
+
+	dmxdevfilter->type = DMXDEV_TYPE_NONE;
+	dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_ALLOCATED);
+	return 0;
+}
+
+static int dvb_dmxdev_start_feed(struct dmxdev *dmxdev,
+				 struct dmxdev_filter *filter,
+				 struct dmxdev_feed *feed)
+{
+	struct timespec timeout = { 0 };
+	struct dmx_pes_filter_params *para = &filter->params.pes;
+	dmx_output_t otype;
+	int ret;
+	int ts_type;
+	dmx_pes_type_t ts_pes;
+	struct dmx_ts_feed *tsfeed;
+
+	feed->ts = NULL;
+	otype = para->output;
+
+	ts_pes = para->pes_type;
+
+	if (ts_pes < DMX_PES_OTHER)
+		ts_type = TS_DECODER;
+	else
+		ts_type = 0;
+
+	if (otype == DMX_OUT_TS_TAP)
+		ts_type |= TS_PACKET;
+	else if (otype == DMX_OUT_TSDEMUX_TAP)
+		ts_type |= TS_PACKET | TS_DEMUX;
+	else if (otype == DMX_OUT_TAP)
+		ts_type |= TS_PACKET | TS_DEMUX | TS_PAYLOAD_ONLY;
+
+	ret = dmxdev->demux->allocate_ts_feed(dmxdev->demux, &feed->ts,
+					      dvb_dmxdev_ts_callback);
+	if (ret < 0)
+		return ret;
+
+	tsfeed = feed->ts;
+	tsfeed->priv = filter;
+
+	ret = tsfeed->set(tsfeed, feed->pid, ts_type, ts_pes, 32768, timeout);
+	if (ret < 0) {
+		dmxdev->demux->release_ts_feed(dmxdev->demux, tsfeed);
+		return ret;
+	}
+
+	ret = tsfeed->start_filtering(tsfeed);
+	if (ret < 0) {
+		dmxdev->demux->release_ts_feed(dmxdev->demux, tsfeed);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter)
+{
+	struct dmxdev *dmxdev = filter->dev;
+	struct dmxdev_feed *feed;
+	void *mem;
+	int ret, i;
+
+	if (filter->state < DMXDEV_STATE_SET)
+		return -EINVAL;
+
+	if (filter->state >= DMXDEV_STATE_GO)
+		dvb_dmxdev_filter_stop(filter);
+
+	if (!filter->buffer.data) {
+		mem = vmalloc(filter->buffer.size);
+		if (!mem)
+			return -ENOMEM;
+		spin_lock_irq(&filter->dev->lock);
+		filter->buffer.data = mem;
+		spin_unlock_irq(&filter->dev->lock);
+	}
+
+	dvb_ringbuffer_flush(&filter->buffer);
+
+	switch (filter->type) {
+	case DMXDEV_TYPE_SEC:
+	{
+		struct dmx_sct_filter_params *para = &filter->params.sec;
+		struct dmx_section_filter **secfilter = &filter->filter.sec;
+		struct dmx_section_feed **secfeed = &filter->feed.sec;
+
+		*secfilter = NULL;
+		*secfeed = NULL;
+
+
+		/* find active filter/feed with same PID */
+		for (i = 0; i < dmxdev->filternum; i++) {
+			if (dmxdev->filter[i].state >= DMXDEV_STATE_GO &&
+			    dmxdev->filter[i].type == DMXDEV_TYPE_SEC &&
+			    dmxdev->filter[i].params.sec.pid == para->pid) {
+				*secfeed = dmxdev->filter[i].feed.sec;
+				break;
+			}
+		}
+
+		/* if no feed found, try to allocate new one */
+		if (!*secfeed) {
+			ret = dmxdev->demux->allocate_section_feed(dmxdev->demux,
+								   secfeed,
+								   dvb_dmxdev_section_callback);
+			if (ret < 0) {
+				printk("DVB (%s): could not alloc feed\n",
+				       __func__);
+				return ret;
+			}
+
+			ret = (*secfeed)->set(*secfeed, para->pid, 32768,
+					      (para->flags & DMX_CHECK_CRC) ? 1 : 0);
+			if (ret < 0) {
+				printk("DVB (%s): could not set feed\n",
+				       __func__);
+				dvb_dmxdev_feed_restart(filter);
+				return ret;
+			}
+		} else {
+			dvb_dmxdev_feed_stop(filter);
+		}
+
+		ret = (*secfeed)->allocate_filter(*secfeed, secfilter);
+		if (ret < 0) {
+			dvb_dmxdev_feed_restart(filter);
+			filter->feed.sec->start_filtering(*secfeed);
+			dprintk("could not get filter\n");
+			return ret;
+		}
+
+		(*secfilter)->priv = filter;
+
+		memcpy(&((*secfilter)->filter_value[3]),
+		       &(para->filter.filter[1]), DMX_FILTER_SIZE - 1);
+		memcpy(&(*secfilter)->filter_mask[3],
+		       &para->filter.mask[1], DMX_FILTER_SIZE - 1);
+		memcpy(&(*secfilter)->filter_mode[3],
+		       &para->filter.mode[1], DMX_FILTER_SIZE - 1);
+
+		(*secfilter)->filter_value[0] = para->filter.filter[0];
+		(*secfilter)->filter_mask[0] = para->filter.mask[0];
+		(*secfilter)->filter_mode[0] = para->filter.mode[0];
+		(*secfilter)->filter_mask[1] = 0;
+		(*secfilter)->filter_mask[2] = 0;
+
+		filter->todo = 0;
+
+		ret = filter->feed.sec->start_filtering(filter->feed.sec);
+		if (ret < 0)
+			return ret;
+
+		dvb_dmxdev_filter_timer(filter);
+		break;
+	}
+	case DMXDEV_TYPE_PES:
+		list_for_each_entry(feed, &filter->feed.ts, next) {
+			ret = dvb_dmxdev_start_feed(dmxdev, filter, feed);
+			if (ret < 0) {
+				dvb_dmxdev_filter_stop(filter);
+				return ret;
+			}
+		}
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	dvb_dmxdev_filter_state_set(filter, DMXDEV_STATE_GO);
+	return 0;
+}
+
+static int dvb_demux_open(struct inode *inode, struct file *file)
+{
+	struct dvb_device *dvbdev = file->private_data;
+	struct dmxdev *dmxdev = dvbdev->priv;
+	int i;
+	struct dmxdev_filter *dmxdevfilter;
+
+	if (!dmxdev->filter)
+		return -EINVAL;
+
+	if (mutex_lock_interruptible(&dmxdev->mutex))
+		return -ERESTARTSYS;
+
+	for (i = 0; i < dmxdev->filternum; i++)
+		if (dmxdev->filter[i].state == DMXDEV_STATE_FREE)
+			break;
+
+	if (i == dmxdev->filternum) {
+		mutex_unlock(&dmxdev->mutex);
+		return -EMFILE;
+	}
+
+	dmxdevfilter = &dmxdev->filter[i];
+	mutex_init(&dmxdevfilter->mutex);
+	file->private_data = dmxdevfilter;
+
+	dvb_ringbuffer_init(&dmxdevfilter->buffer, NULL, 8192);
+	dmxdevfilter->type = DMXDEV_TYPE_NONE;
+	dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_ALLOCATED);
+	init_timer(&dmxdevfilter->timer);
+
+	dvbdev->users++;
+
+	mutex_unlock(&dmxdev->mutex);
+	return 0;
+}
+
+static int dvb_dmxdev_filter_free(struct dmxdev *dmxdev,
+				  struct dmxdev_filter *dmxdevfilter)
+{
+	mutex_lock(&dmxdev->mutex);
+	mutex_lock(&dmxdevfilter->mutex);
+
+	dvb_dmxdev_filter_stop(dmxdevfilter);
+	dvb_dmxdev_filter_reset(dmxdevfilter);
+
+	if (dmxdevfilter->buffer.data) {
+		void *mem = dmxdevfilter->buffer.data;
+
+		spin_lock_irq(&dmxdev->lock);
+		dmxdevfilter->buffer.data = NULL;
+		spin_unlock_irq(&dmxdev->lock);
+		vfree(mem);
+	}
+
+	dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_FREE);
+	wake_up(&dmxdevfilter->buffer.queue);
+	mutex_unlock(&dmxdevfilter->mutex);
+	mutex_unlock(&dmxdev->mutex);
+	return 0;
+}
+
+static inline void invert_mode(dmx_filter_t *filter)
+{
+	int i;
+
+	for (i = 0; i < DMX_FILTER_SIZE; i++)
+		filter->mode[i] ^= 0xff;
+}
+
+static int dvb_dmxdev_add_pid(struct dmxdev *dmxdev,
+			      struct dmxdev_filter *filter, u16 pid)
+{
+	struct dmxdev_feed *feed;
+
+	if ((filter->type != DMXDEV_TYPE_PES) ||
+	    (filter->state < DMXDEV_STATE_SET))
+		return -EINVAL;
+
+	/* only TS packet filters may have multiple PIDs */
+	if ((filter->params.pes.output != DMX_OUT_TSDEMUX_TAP) &&
+	    (!list_empty(&filter->feed.ts)))
+		return -EINVAL;
+
+	feed = kzalloc(sizeof(struct dmxdev_feed), GFP_KERNEL);
+	if (feed == NULL)
+		return -ENOMEM;
+
+	feed->pid = pid;
+	list_add(&feed->next, &filter->feed.ts);
+
+	if (filter->state >= DMXDEV_STATE_GO)
+		return dvb_dmxdev_start_feed(dmxdev, filter, feed);
+
+	return 0;
+}
+
+static int dvb_dmxdev_remove_pid(struct dmxdev *dmxdev,
+				  struct dmxdev_filter *filter, u16 pid)
+{
+	struct dmxdev_feed *feed, *tmp;
+
+	if ((filter->type != DMXDEV_TYPE_PES) ||
+	    (filter->state < DMXDEV_STATE_SET))
+		return -EINVAL;
+
+	list_for_each_entry_safe(feed, tmp, &filter->feed.ts, next) {
+		if ((feed->pid == pid) && (feed->ts != NULL)) {
+			feed->ts->stop_filtering(feed->ts);
+			filter->dev->demux->release_ts_feed(filter->dev->demux,
+							    feed->ts);
+			list_del(&feed->next);
+			kfree(feed);
+		}
+	}
+
+	return 0;
+}
+
+static int dvb_dmxdev_filter_set(struct dmxdev *dmxdev,
+				 struct dmxdev_filter *dmxdevfilter,
+				 struct dmx_sct_filter_params *params)
+{
+	dprintk("function : %s\n", __func__);
+
+	dvb_dmxdev_filter_stop(dmxdevfilter);
+
+	dmxdevfilter->type = DMXDEV_TYPE_SEC;
+	memcpy(&dmxdevfilter->params.sec,
+	       params, sizeof(struct dmx_sct_filter_params));
+	invert_mode(&dmxdevfilter->params.sec.filter);
+	dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_SET);
+
+	if (params->flags & DMX_IMMEDIATE_START)
+		return dvb_dmxdev_filter_start(dmxdevfilter);
+
+	return 0;
+}
+
+static int dvb_dmxdev_pes_filter_set(struct dmxdev *dmxdev,
+				     struct dmxdev_filter *dmxdevfilter,
+				     struct dmx_pes_filter_params *params)
+{
+	int ret;
+
+	dvb_dmxdev_filter_stop(dmxdevfilter);
+	dvb_dmxdev_filter_reset(dmxdevfilter);
+
+	if (params->pes_type > DMX_PES_OTHER || params->pes_type < 0)
+		return -EINVAL;
+
+	dmxdevfilter->type = DMXDEV_TYPE_PES;
+	memcpy(&dmxdevfilter->params, params,
+	       sizeof(struct dmx_pes_filter_params));
+	INIT_LIST_HEAD(&dmxdevfilter->feed.ts);
+
+	dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_SET);
+
+	ret = dvb_dmxdev_add_pid(dmxdev, dmxdevfilter,
+				 dmxdevfilter->params.pes.pid);
+	if (ret < 0)
+		return ret;
+
+	if (params->flags & DMX_IMMEDIATE_START)
+		return dvb_dmxdev_filter_start(dmxdevfilter);
+
+	return 0;
+}
+
+static ssize_t dvb_dmxdev_read_sec(struct dmxdev_filter *dfil,
+				   struct file *file, char __user *buf,
+				   size_t count, loff_t *ppos)
+{
+	int result, hcount;
+	int done = 0;
+
+	if (dfil->todo <= 0) {
+		hcount = 3 + dfil->todo;
+		if (hcount > count)
+			hcount = count;
+		result = dvb_dmxdev_buffer_read(&dfil->buffer,
+						file->f_flags & O_NONBLOCK,
+						buf, hcount, ppos);
+		if (result < 0) {
+			dfil->todo = 0;
+			return result;
+		}
+		if (copy_from_user(dfil->secheader - dfil->todo, buf, result))
+			return -EFAULT;
+		buf += result;
+		done = result;
+		count -= result;
+		dfil->todo -= result;
+		if (dfil->todo > -3)
+			return done;
+		dfil->todo = ((dfil->secheader[1] << 8) | dfil->secheader[2]) & 0xfff;
+		if (!count)
+			return done;
+	}
+	if (count > dfil->todo)
+		count = dfil->todo;
+	result = dvb_dmxdev_buffer_read(&dfil->buffer,
+					file->f_flags & O_NONBLOCK,
+					buf, count, ppos);
+	if (result < 0)
+		return result;
+	dfil->todo -= result;
+	return (result + done);
+}
+
+static ssize_t
+dvb_demux_read(struct file *file, char __user *buf, size_t count,
+	       loff_t *ppos)
+{
+	struct dmxdev_filter *dmxdevfilter = file->private_data;
+	int ret;
+
+	if (mutex_lock_interruptible(&dmxdevfilter->mutex))
+		return -ERESTARTSYS;
+
+	if (dmxdevfilter->type == DMXDEV_TYPE_SEC)
+		ret = dvb_dmxdev_read_sec(dmxdevfilter, file, buf, count, ppos);
+	else
+		ret = dvb_dmxdev_buffer_read(&dmxdevfilter->buffer,
+					     file->f_flags & O_NONBLOCK,
+					     buf, count, ppos);
+
+	mutex_unlock(&dmxdevfilter->mutex);
+	return ret;
+}
+
+static int dvb_demux_do_ioctl(struct file *file,
+			      unsigned int cmd, void *parg)
+{
+	struct dmxdev_filter *dmxdevfilter = file->private_data;
+	struct dmxdev *dmxdev = dmxdevfilter->dev;
+	unsigned long arg = (unsigned long)parg;
+	int ret = 0;
+
+	if (mutex_lock_interruptible(&dmxdev->mutex))
+		return -ERESTARTSYS;
+
+	switch (cmd) {
+	case DMX_START:
+		if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
+			mutex_unlock(&dmxdev->mutex);
+			return -ERESTARTSYS;
+		}
+		if (dmxdevfilter->state < DMXDEV_STATE_SET)
+			ret = -EINVAL;
+		else
+			ret = dvb_dmxdev_filter_start(dmxdevfilter);
+		mutex_unlock(&dmxdevfilter->mutex);
+		break;
+
+	case DMX_STOP:
+		if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
+			mutex_unlock(&dmxdev->mutex);
+			return -ERESTARTSYS;
+		}
+		ret = dvb_dmxdev_filter_stop(dmxdevfilter);
+		mutex_unlock(&dmxdevfilter->mutex);
+		break;
+
+	case DMX_SET_FILTER:
+		if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
+			mutex_unlock(&dmxdev->mutex);
+			return -ERESTARTSYS;
+		}
+		ret = dvb_dmxdev_filter_set(dmxdev, dmxdevfilter, parg);
+		mutex_unlock(&dmxdevfilter->mutex);
+		break;
+
+	case DMX_SET_PES_FILTER:
+		if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
+			mutex_unlock(&dmxdev->mutex);
+			return -ERESTARTSYS;
+		}
+		ret = dvb_dmxdev_pes_filter_set(dmxdev, dmxdevfilter, parg);
+		mutex_unlock(&dmxdevfilter->mutex);
+		break;
+
+	case DMX_SET_BUFFER_SIZE:
+		if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
+			mutex_unlock(&dmxdev->mutex);
+			return -ERESTARTSYS;
+		}
+		ret = dvb_dmxdev_set_buffer_size(dmxdevfilter, arg);
+		mutex_unlock(&dmxdevfilter->mutex);
+		break;
+
+	case DMX_GET_PES_PIDS:
+		if (!dmxdev->demux->get_pes_pids) {
+			ret = -EINVAL;
+			break;
+		}
+		dmxdev->demux->get_pes_pids(dmxdev->demux, parg);
+		break;
+
+	case DMX_GET_CAPS:
+		if (!dmxdev->demux->get_caps) {
+			ret = -EINVAL;
+			break;
+		}
+		ret = dmxdev->demux->get_caps(dmxdev->demux, parg);
+		break;
+
+	case DMX_SET_SOURCE:
+		if (!dmxdev->demux->set_source) {
+			ret = -EINVAL;
+			break;
+		}
+		ret = dmxdev->demux->set_source(dmxdev->demux, parg);
+		break;
+
+	case DMX_GET_STC:
+		if (!dmxdev->demux->get_stc) {
+			ret = -EINVAL;
+			break;
+		}
+		ret = dmxdev->demux->get_stc(dmxdev->demux,
+					     ((struct dmx_stc *)parg)->num,
+					     &((struct dmx_stc *)parg)->stc,
+					     &((struct dmx_stc *)parg)->base);
+		break;
+
+	case DMX_ADD_PID:
+		if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
+			ret = -ERESTARTSYS;
+			break;
+		}
+		ret = dvb_dmxdev_add_pid(dmxdev, dmxdevfilter, *(u16 *)parg);
+		mutex_unlock(&dmxdevfilter->mutex);
+		break;
+
+	case DMX_REMOVE_PID:
+		if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
+			ret = -ERESTARTSYS;
+			break;
+		}
+		ret = dvb_dmxdev_remove_pid(dmxdev, dmxdevfilter, *(u16 *)parg);
+		mutex_unlock(&dmxdevfilter->mutex);
+		break;
+
+	default:
+		ret = -EINVAL;
+		break;
+	}
+	mutex_unlock(&dmxdev->mutex);
+	return ret;
+}
+
+static long dvb_demux_ioctl(struct file *file, unsigned int cmd,
+			    unsigned long arg)
+{
+	return dvb_usercopy(file, cmd, arg, dvb_demux_do_ioctl);
+}
+
+static unsigned int dvb_demux_poll(struct file *file, poll_table *wait)
+{
+	struct dmxdev_filter *dmxdevfilter = file->private_data;
+	unsigned int mask = 0;
+
+	if (!dmxdevfilter)
+		return -EINVAL;
+
+	poll_wait(file, &dmxdevfilter->buffer.queue, wait);
+
+	if (dmxdevfilter->state != DMXDEV_STATE_GO &&
+	    dmxdevfilter->state != DMXDEV_STATE_DONE &&
+	    dmxdevfilter->state != DMXDEV_STATE_TIMEDOUT)
+		return 0;
+
+	if (dmxdevfilter->buffer.error)
+		mask |= (POLLIN | POLLRDNORM | POLLPRI | POLLERR);
+
+	if (!dvb_ringbuffer_empty(&dmxdevfilter->buffer))
+		mask |= (POLLIN | POLLRDNORM | POLLPRI);
+
+	return mask;
+}
+
+static int dvb_demux_release(struct inode *inode, struct file *file)
+{
+	struct dmxdev_filter *dmxdevfilter = file->private_data;
+	struct dmxdev *dmxdev = dmxdevfilter->dev;
+
+	int ret;
+
+	ret = dvb_dmxdev_filter_free(dmxdev, dmxdevfilter);
+
+	mutex_lock(&dmxdev->mutex);
+	dmxdev->dvbdev->users--;
+	if(dmxdev->dvbdev->users==1 && dmxdev->exit==1) {
+		fops_put(file->f_op);
+		file->f_op = NULL;
+		mutex_unlock(&dmxdev->mutex);
+		wake_up(&dmxdev->dvbdev->wait_queue);
+	} else
+		mutex_unlock(&dmxdev->mutex);
+
+	return ret;
+}
+
+static const struct file_operations dvb_demux_fops = {
+	.owner = THIS_MODULE,
+	.read = dvb_demux_read,
+	.unlocked_ioctl = dvb_demux_ioctl,
+	.open = dvb_demux_open,
+	.release = dvb_demux_release,
+	.poll = dvb_demux_poll,
+	.llseek = default_llseek,
+};
+
+static struct dvb_device dvbdev_demux = {
+	.priv = NULL,
+	.users = 1,
+	.writers = 1,
+	.fops = &dvb_demux_fops
+};
+
+static int dvb_dvr_do_ioctl(struct file *file,
+			    unsigned int cmd, void *parg)
+{
+	struct dvb_device *dvbdev = file->private_data;
+	struct dmxdev *dmxdev = dvbdev->priv;
+	unsigned long arg = (unsigned long)parg;
+	int ret;
+
+	if (mutex_lock_interruptible(&dmxdev->mutex))
+		return -ERESTARTSYS;
+
+	switch (cmd) {
+	case DMX_SET_BUFFER_SIZE:
+		ret = dvb_dvr_set_buffer_size(dmxdev, arg);
+		break;
+
+	default:
+		ret = -EINVAL;
+		break;
+	}
+	mutex_unlock(&dmxdev->mutex);
+	return ret;
+}
+
+static long dvb_dvr_ioctl(struct file *file,
+			 unsigned int cmd, unsigned long arg)
+{
+	return dvb_usercopy(file, cmd, arg, dvb_dvr_do_ioctl);
+}
+
+static unsigned int dvb_dvr_poll(struct file *file, poll_table *wait)
+{
+	struct dvb_device *dvbdev = file->private_data;
+	struct dmxdev *dmxdev = dvbdev->priv;
+	unsigned int mask = 0;
+
+	dprintk("function : %s\n", __func__);
+
+	poll_wait(file, &dmxdev->dvr_buffer.queue, wait);
+
+	if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
+		if (dmxdev->dvr_buffer.error)
+			mask |= (POLLIN | POLLRDNORM | POLLPRI | POLLERR);
+
+		if (!dvb_ringbuffer_empty(&dmxdev->dvr_buffer))
+			mask |= (POLLIN | POLLRDNORM | POLLPRI);
+	} else
+		mask |= (POLLOUT | POLLWRNORM | POLLPRI);
+
+	return mask;
+}
+
+static const struct file_operations dvb_dvr_fops = {
+	.owner = THIS_MODULE,
+	.read = dvb_dvr_read,
+	.write = dvb_dvr_write,
+	.unlocked_ioctl = dvb_dvr_ioctl,
+	.open = dvb_dvr_open,
+	.release = dvb_dvr_release,
+	.poll = dvb_dvr_poll,
+	.llseek = default_llseek,
+};
+
+static struct dvb_device dvbdev_dvr = {
+	.priv = NULL,
+	.readers = 1,
+	.users = 1,
+	.fops = &dvb_dvr_fops
+};
+
+int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *dvb_adapter)
+{
+	int i;
+
+	if (dmxdev->demux->open(dmxdev->demux) < 0)
+		return -EUSERS;
+
+	dmxdev->filter = vmalloc(dmxdev->filternum * sizeof(struct dmxdev_filter));
+	if (!dmxdev->filter)
+		return -ENOMEM;
+
+	mutex_init(&dmxdev->mutex);
+	spin_lock_init(&dmxdev->lock);
+	for (i = 0; i < dmxdev->filternum; i++) {
+		dmxdev->filter[i].dev = dmxdev;
+		dmxdev->filter[i].buffer.data = NULL;
+		dvb_dmxdev_filter_state_set(&dmxdev->filter[i],
+					    DMXDEV_STATE_FREE);
+	}
+
+	dvb_register_device(dvb_adapter, &dmxdev->dvbdev, &dvbdev_demux, dmxdev,
+			    DVB_DEVICE_DEMUX);
+	dvb_register_device(dvb_adapter, &dmxdev->dvr_dvbdev, &dvbdev_dvr,
+			    dmxdev, DVB_DEVICE_DVR);
+
+	dvb_ringbuffer_init(&dmxdev->dvr_buffer, NULL, 8192);
+
+	return 0;
+}
+
+EXPORT_SYMBOL(dvb_dmxdev_init);
+
+void dvb_dmxdev_release(struct dmxdev *dmxdev)
+{
+	dmxdev->exit=1;
+	if (dmxdev->dvbdev->users > 1) {
+		wait_event(dmxdev->dvbdev->wait_queue,
+				dmxdev->dvbdev->users==1);
+	}
+	if (dmxdev->dvr_dvbdev->users > 1) {
+		wait_event(dmxdev->dvr_dvbdev->wait_queue,
+				dmxdev->dvr_dvbdev->users==1);
+	}
+
+	dvb_unregister_device(dmxdev->dvbdev);
+	dvb_unregister_device(dmxdev->dvr_dvbdev);
+
+	vfree(dmxdev->filter);
+	dmxdev->filter = NULL;
+	dmxdev->demux->close(dmxdev->demux);
+}
+
+EXPORT_SYMBOL(dvb_dmxdev_release);
diff --git a/drivers/media/dvb-core/dmxdev.h b/drivers/media/dvb-core/dmxdev.h
new file mode 100644
index 0000000..02ebe28
--- /dev/null
+++ b/drivers/media/dvb-core/dmxdev.h
@@ -0,0 +1,118 @@
+/*
+ * dmxdev.h
+ *
+ * Copyright (C) 2000 Ralph Metzler & Marcus Metzler
+ *                    for convergence integrated media GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public 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 _DMXDEV_H_
+#define _DMXDEV_H_
+
+#include <linux/types.h>
+#include <linux/spinlock.h>
+#include <linux/kernel.h>
+#include <linux/timer.h>
+#include <linux/wait.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+
+#include <linux/dvb/dmx.h>
+
+#include "dvbdev.h"
+#include "demux.h"
+#include "dvb_ringbuffer.h"
+
+enum dmxdev_type {
+	DMXDEV_TYPE_NONE,
+	DMXDEV_TYPE_SEC,
+	DMXDEV_TYPE_PES,
+};
+
+enum dmxdev_state {
+	DMXDEV_STATE_FREE,
+	DMXDEV_STATE_ALLOCATED,
+	DMXDEV_STATE_SET,
+	DMXDEV_STATE_GO,
+	DMXDEV_STATE_DONE,
+	DMXDEV_STATE_TIMEDOUT
+};
+
+struct dmxdev_feed {
+	u16 pid;
+	struct dmx_ts_feed *ts;
+	struct list_head next;
+};
+
+struct dmxdev_filter {
+	union {
+		struct dmx_section_filter *sec;
+	} filter;
+
+	union {
+		/* list of TS and PES feeds (struct dmxdev_feed) */
+		struct list_head ts;
+		struct dmx_section_feed *sec;
+	} feed;
+
+	union {
+		struct dmx_sct_filter_params sec;
+		struct dmx_pes_filter_params pes;
+	} params;
+
+	enum dmxdev_type type;
+	enum dmxdev_state state;
+	struct dmxdev *dev;
+	struct dvb_ringbuffer buffer;
+
+	struct mutex mutex;
+
+	/* only for sections */
+	struct timer_list timer;
+	int todo;
+	u8 secheader[3];
+};
+
+
+struct dmxdev {
+	struct dvb_device *dvbdev;
+	struct dvb_device *dvr_dvbdev;
+
+	struct dmxdev_filter *filter;
+	struct dmx_demux *demux;
+
+	int filternum;
+	int capabilities;
+
+	unsigned int exit:1;
+#define DMXDEV_CAP_DUPLEX 1
+	struct dmx_frontend *dvr_orig_fe;
+
+	struct dvb_ringbuffer dvr_buffer;
+#define DVR_BUFFER_SIZE (10*188*1024)
+
+	struct mutex mutex;
+	spinlock_t lock;
+};
+
+
+int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *);
+void dvb_dmxdev_release(struct dmxdev *dmxdev);
+
+#endif /* _DMXDEV_H_ */
diff --git a/drivers/media/dvb-core/dvb-usb-ids.h b/drivers/media/dvb-core/dvb-usb-ids.h
new file mode 100644
index 0000000..d572307
--- /dev/null
+++ b/drivers/media/dvb-core/dvb-usb-ids.h
@@ -0,0 +1,363 @@
+/* dvb-usb-ids.h is part of the DVB USB library.
+ *
+ * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) see
+ * dvb-usb-init.c for copyright information.
+ *
+ * a header file containing define's for the USB device supported by the
+ * various drivers.
+ */
+#ifndef _DVB_USB_IDS_H_
+#define _DVB_USB_IDS_H_
+
+/* Vendor IDs */
+#define USB_VID_ADSTECH				0x06e1
+#define USB_VID_AFATECH				0x15a4
+#define USB_VID_ALCOR_MICRO			0x058f
+#define USB_VID_ALINK				0x05e3
+#define USB_VID_AMT				0x1c73
+#define USB_VID_ANCHOR				0x0547
+#define USB_VID_ANSONIC				0x10b9
+#define USB_VID_ANUBIS_ELECTRONIC		0x10fd
+#define USB_VID_ASUS				0x0b05
+#define USB_VID_AVERMEDIA			0x07ca
+#define USB_VID_COMPRO				0x185b
+#define USB_VID_COMPRO_UNK			0x145f
+#define USB_VID_CONEXANT			0x0572
+#define USB_VID_CYPRESS				0x04b4
+#define USB_VID_DEXATEK				0x1d19
+#define USB_VID_DIBCOM				0x10b8
+#define USB_VID_DPOSH				0x1498
+#define USB_VID_DVICO				0x0fe9
+#define USB_VID_E3C				0x18b4
+#define USB_VID_ELGATO				0x0fd9
+#define USB_VID_EMPIA				0xeb1a
+#define USB_VID_GENPIX				0x09c0
+#define USB_VID_GRANDTEC			0x5032
+#define USB_VID_GTEK				0x1f4d
+#define USB_VID_HANFTEK				0x15f4
+#define USB_VID_HAUPPAUGE			0x2040
+#define USB_VID_HYPER_PALTEK			0x1025
+#define USB_VID_INTEL				0x8086
+#define USB_VID_ITETECH				0x048d
+#define USB_VID_KWORLD				0xeb2a
+#define USB_VID_KWORLD_2			0x1b80
+#define USB_VID_KYE				0x0458
+#define USB_VID_LEADTEK				0x0413
+#define USB_VID_LITEON				0x04ca
+#define USB_VID_MEDION				0x1660
+#define USB_VID_MIGLIA				0x18f3
+#define USB_VID_MSI				0x0db0
+#define USB_VID_MSI_2				0x1462
+#define USB_VID_OPERA1				0x695c
+#define USB_VID_PINNACLE			0x2304
+#define USB_VID_PCTV				0x2013
+#define USB_VID_PIXELVIEW			0x1554
+#define USB_VID_REALTEK				0x0bda
+#define USB_VID_TECHNOTREND			0x0b48
+#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
+#define USB_VID_WIDEVIEW			0x14aa
+#define USB_VID_GIGABYTE			0x1044
+#define USB_VID_YUAN				0x1164
+#define USB_VID_XTENSIONS			0x1ae7
+#define USB_VID_HUMAX_COEX			0x10b9
+#define USB_VID_774				0x7a69
+#define USB_VID_EVOLUTEPC			0x1e59
+#define USB_VID_AZUREWAVE			0x13d3
+#define USB_VID_TECHNISAT			0x14f7
+
+/* Product IDs */
+#define USB_PID_ADSTECH_USB2_COLD			0xa333
+#define USB_PID_ADSTECH_USB2_WARM			0xa334
+#define USB_PID_AFATECH_AF9005				0x9020
+#define USB_PID_AFATECH_AF9015_9015			0x9015
+#define USB_PID_AFATECH_AF9015_9016			0x9016
+#define USB_PID_AFATECH_AF9035_1000			0x1000
+#define USB_PID_AFATECH_AF9035_1001			0x1001
+#define USB_PID_AFATECH_AF9035_1002			0x1002
+#define USB_PID_AFATECH_AF9035_1003			0x1003
+#define USB_PID_AFATECH_AF9035_9035			0x9035
+#define USB_PID_TREKSTOR_DVBT				0x901b
+#define USB_PID_TREKSTOR_TERRES_2_0			0xC803
+#define USB_VID_ALINK_DTU				0xf170
+#define USB_PID_ANSONIC_DVBT_USB			0x6000
+#define USB_PID_ANYSEE					0x861f
+#define USB_PID_AZUREWAVE_AD_TU700			0x3237
+#define USB_PID_AZUREWAVE_6007				0x0ccd
+#define USB_PID_AVERMEDIA_DVBT_USB_COLD			0x0001
+#define USB_PID_AVERMEDIA_DVBT_USB_WARM			0x0002
+#define USB_PID_AVERMEDIA_DVBT_USB2_COLD		0xa800
+#define USB_PID_AVERMEDIA_DVBT_USB2_WARM		0xa801
+#define USB_PID_COMPRO_DVBU2000_COLD			0xd000
+#define USB_PID_COMPRO_DVBU2000_WARM			0xd001
+#define USB_PID_COMPRO_DVBU2000_UNK_COLD		0x010c
+#define USB_PID_COMPRO_DVBU2000_UNK_WARM		0x010d
+#define USB_PID_COMPRO_VIDEOMATE_U500			0x1e78
+#define USB_PID_COMPRO_VIDEOMATE_U500_PC		0x1e80
+#define USB_PID_CONCEPTRONIC_CTVDIGRCU			0xe397
+#define USB_PID_CONEXANT_D680_DMB			0x86d6
+#define USB_PID_CREATIX_CTX1921				0x1921
+#define USB_PID_DELOCK_USB2_DVBT			0xb803
+#define USB_PID_DIBCOM_HOOK_DEFAULT			0x0064
+#define USB_PID_DIBCOM_HOOK_DEFAULT_REENUM		0x0065
+#define USB_PID_DIBCOM_MOD3000_COLD			0x0bb8
+#define USB_PID_DIBCOM_MOD3000_WARM			0x0bb9
+#define USB_PID_DIBCOM_MOD3001_COLD			0x0bc6
+#define USB_PID_DIBCOM_MOD3001_WARM			0x0bc7
+#define USB_PID_DIBCOM_STK7700P				0x1e14
+#define USB_PID_DIBCOM_STK7700P_PC			0x1e78
+#define USB_PID_DIBCOM_STK7700D				0x1ef0
+#define USB_PID_DIBCOM_STK7700_U7000			0x7001
+#define USB_PID_DIBCOM_STK7070P				0x1ebc
+#define USB_PID_DIBCOM_STK7070PD			0x1ebe
+#define USB_PID_DIBCOM_STK807XP				0x1f90
+#define USB_PID_DIBCOM_STK807XPVR			0x1f98
+#define USB_PID_DIBCOM_STK8096GP                        0x1fa0
+#define USB_PID_DIBCOM_NIM8096MD                        0x1fa8
+#define USB_PID_DIBCOM_TFE8096P				0x1f9C
+#define USB_PID_DIBCOM_ANCHOR_2135_COLD			0x2131
+#define USB_PID_DIBCOM_STK7770P				0x1e80
+#define USB_PID_DIBCOM_NIM7090				0x1bb2
+#define USB_PID_DIBCOM_TFE7090PVR			0x1bb4
+#define USB_PID_DIBCOM_TFE7090E				0x1bb7
+#define USB_PID_DIBCOM_TFE7790E				0x1e6e
+#define USB_PID_DIBCOM_NIM9090M				0x2383
+#define USB_PID_DIBCOM_NIM9090MD			0x2384
+#define USB_PID_DPOSH_M9206_COLD			0x9206
+#define USB_PID_DPOSH_M9206_WARM			0xa090
+#define USB_PID_E3C_EC168				0x1689
+#define USB_PID_E3C_EC168_2				0xfffa
+#define USB_PID_E3C_EC168_3				0xfffb
+#define USB_PID_E3C_EC168_4				0x1001
+#define USB_PID_E3C_EC168_5				0x1002
+#define USB_PID_FREECOM_DVBT				0x0160
+#define USB_PID_FREECOM_DVBT_2				0x0161
+#define USB_PID_UNIWILL_STK7700P			0x6003
+#define USB_PID_GENIUS_TVGO_DVB_T03			0x4012
+#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_ITETECH_IT9135				0x9135
+#define USB_PID_ITETECH_IT9135_9005			0x9005
+#define USB_PID_ITETECH_IT9135_9006			0x9006
+#define USB_PID_KWORLD_399U				0xe399
+#define USB_PID_KWORLD_399U_2				0xe400
+#define USB_PID_KWORLD_395U				0xe396
+#define USB_PID_KWORLD_395U_2				0xe39b
+#define USB_PID_KWORLD_395U_3				0xe395
+#define USB_PID_KWORLD_395U_4				0xe39a
+#define USB_PID_KWORLD_MC810				0xc810
+#define USB_PID_KWORLD_PC160_2T				0xc160
+#define USB_PID_KWORLD_PC160_T				0xc161
+#define USB_PID_KWORLD_UB383_T				0xe383
+#define USB_PID_KWORLD_UB499_2T_T09			0xe409
+#define USB_PID_KWORLD_VSTREAM_COLD			0x17de
+#define USB_PID_KWORLD_VSTREAM_WARM			0x17df
+#define USB_PID_TERRATEC_CINERGY_T_USB_XE		0x0055
+#define USB_PID_TERRATEC_CINERGY_T_USB_XE_REV2		0x0069
+#define USB_PID_TERRATEC_CINERGY_T_STICK		0x0093
+#define USB_PID_TERRATEC_CINERGY_T_STICK_RC		0x0097
+#define USB_PID_TERRATEC_CINERGY_T_STICK_DUAL_RC	0x0099
+#define USB_PID_TERRATEC_CINERGY_T_STICK_BLACK_REV1	0x00a9
+#define USB_PID_TWINHAN_VP7041_COLD			0x3201
+#define USB_PID_TWINHAN_VP7041_WARM			0x3202
+#define USB_PID_TWINHAN_VP7020_COLD			0x3203
+#define USB_PID_TWINHAN_VP7020_WARM			0x3204
+#define USB_PID_TWINHAN_VP7045_COLD			0x3205
+#define USB_PID_TWINHAN_VP7045_WARM			0x3206
+#define USB_PID_TWINHAN_VP7021_COLD			0x3207
+#define USB_PID_TWINHAN_VP7021_WARM			0x3208
+#define USB_PID_TINYTWIN				0x3226
+#define USB_PID_TINYTWIN_2				0xe402
+#define USB_PID_TINYTWIN_3				0x9016
+#define USB_PID_DNTV_TINYUSB2_COLD			0x3223
+#define USB_PID_DNTV_TINYUSB2_WARM			0x3224
+#define USB_PID_ULTIMA_TVBOX_COLD			0x8105
+#define USB_PID_ULTIMA_TVBOX_WARM			0x8106
+#define USB_PID_ULTIMA_TVBOX_AN2235_COLD		0x8107
+#define USB_PID_ULTIMA_TVBOX_AN2235_WARM		0x8108
+#define USB_PID_ULTIMA_TVBOX_ANCHOR_COLD		0x2235
+#define USB_PID_ULTIMA_TVBOX_USB2_COLD			0x8109
+#define USB_PID_ULTIMA_TVBOX_USB2_WARM			0x810a
+#define USB_PID_ARTEC_T14_COLD				0x810b
+#define USB_PID_ARTEC_T14_WARM				0x810c
+#define USB_PID_ARTEC_T14BR				0x810f
+#define USB_PID_ULTIMA_TVBOX_USB2_FX_COLD		0x8613
+#define USB_PID_ULTIMA_TVBOX_USB2_FX_WARM		0x1002
+#define USB_PID_UNK_HYPER_PALTEK_COLD			0x005e
+#define USB_PID_UNK_HYPER_PALTEK_WARM			0x005f
+#define USB_PID_HANFTEK_UMT_010_COLD			0x0001
+#define USB_PID_HANFTEK_UMT_010_WARM			0x0015
+#define USB_PID_DTT200U_COLD				0x0201
+#define USB_PID_DTT200U_WARM				0x0301
+#define USB_PID_WT220U_ZAP250_COLD			0x0220
+#define USB_PID_WT220U_COLD				0x0222
+#define USB_PID_WT220U_WARM				0x0221
+#define USB_PID_WT220U_FC_COLD				0x0225
+#define USB_PID_WT220U_FC_WARM				0x0226
+#define USB_PID_WT220U_ZL0353_COLD			0x022a
+#define USB_PID_WT220U_ZL0353_WARM			0x022b
+#define USB_PID_WINTV_NOVA_T_USB2_COLD			0x9300
+#define USB_PID_WINTV_NOVA_T_USB2_WARM			0x9301
+#define USB_PID_HAUPPAUGE_NOVA_T_500			0x9941
+#define USB_PID_HAUPPAUGE_NOVA_T_500_2			0x9950
+#define USB_PID_HAUPPAUGE_NOVA_T_500_3			0x8400
+#define USB_PID_HAUPPAUGE_NOVA_T_STICK			0x7050
+#define USB_PID_HAUPPAUGE_NOVA_T_STICK_2		0x7060
+#define USB_PID_HAUPPAUGE_NOVA_T_STICK_3		0x7070
+#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
+#define USB_PID_AVERMEDIA_VOLAR_A868R			0xa868
+#define USB_PID_AVERMEDIA_MCE_USB_M038			0x1228
+#define USB_PID_AVERMEDIA_HYBRID_ULTRA_USB_M039R	0x0039
+#define USB_PID_AVERMEDIA_HYBRID_ULTRA_USB_M039R_ATSC	0x1039
+#define USB_PID_AVERMEDIA_HYBRID_ULTRA_USB_M039R_DVBT	0x2039
+#define USB_PID_AVERMEDIA_VOLAR_X			0xa815
+#define USB_PID_AVERMEDIA_VOLAR_X_2			0x8150
+#define USB_PID_AVERMEDIA_A309				0xa309
+#define USB_PID_AVERMEDIA_A310				0xa310
+#define USB_PID_AVERMEDIA_A850				0x850a
+#define USB_PID_AVERMEDIA_A850T				0x850b
+#define USB_PID_AVERMEDIA_A805				0xa805
+#define USB_PID_AVERMEDIA_A815M				0x815a
+#define USB_PID_AVERMEDIA_A835				0xa835
+#define USB_PID_AVERMEDIA_B835				0xb835
+#define USB_PID_AVERMEDIA_1867				0x1867
+#define USB_PID_AVERMEDIA_A867				0xa867
+#define USB_PID_AVERMEDIA_TWINSTAR			0x0825
+#define USB_PID_TECHNOTREND_CONNECT_S2400               0x3006
+#define USB_PID_TECHNOTREND_CONNECT_CT3650		0x300d
+#define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY	0x005a
+#define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY_2	0x0081
+#define USB_PID_TERRATEC_CINERGY_HT_USB_XE		0x0058
+#define USB_PID_TERRATEC_CINERGY_HT_EXPRESS		0x0060
+#define USB_PID_TERRATEC_CINERGY_T_EXPRESS		0x0062
+#define USB_PID_TERRATEC_CINERGY_T_XXS			0x0078
+#define USB_PID_TERRATEC_CINERGY_T_XXS_2		0x00ab
+#define USB_PID_TERRATEC_H7				0x10b4
+#define USB_PID_TERRATEC_H7_2				0x10a3
+#define USB_PID_TERRATEC_T3				0x10a0
+#define USB_PID_TERRATEC_T5				0x10a1
+#define USB_PID_NOXON_DAB_STICK				0x00b3
+#define USB_PID_PINNACLE_EXPRESSCARD_320CX		0x022e
+#define USB_PID_PINNACLE_PCTV2000E			0x022c
+#define USB_PID_PINNACLE_PCTV_DVB_T_FLASH		0x0228
+#define USB_PID_PINNACLE_PCTV_DUAL_DIVERSITY_DVB_T	0x0229
+#define USB_PID_PINNACLE_PCTV71E			0x022b
+#define USB_PID_PINNACLE_PCTV72E			0x0236
+#define USB_PID_PINNACLE_PCTV73E			0x0237
+#define USB_PID_PINNACLE_PCTV310E			0x3211
+#define USB_PID_PINNACLE_PCTV801E			0x023a
+#define USB_PID_PINNACLE_PCTV801E_SE			0x023b
+#define USB_PID_PINNACLE_PCTV340E			0x023d
+#define USB_PID_PINNACLE_PCTV340E_SE			0x023e
+#define USB_PID_PINNACLE_PCTV73A			0x0243
+#define USB_PID_PINNACLE_PCTV73ESE			0x0245
+#define USB_PID_PINNACLE_PCTV74E			0x0246
+#define USB_PID_PINNACLE_PCTV282E			0x0248
+#define USB_PID_PIXELVIEW_SBTVD				0x5010
+#define USB_PID_PCTV_200E				0x020e
+#define USB_PID_PCTV_400E				0x020f
+#define USB_PID_PCTV_450E				0x0222
+#define USB_PID_PCTV_452E				0x021f
+#define USB_PID_REALTEK_RTL2831U			0x2831
+#define USB_PID_REALTEK_RTL2832U			0x2832
+#define USB_PID_TECHNOTREND_CONNECT_S2_3600		0x3007
+#define USB_PID_TECHNOTREND_CONNECT_S2_3650_CI		0x300a
+#define USB_PID_NEBULA_DIGITV				0x0201
+#define USB_PID_DVICO_BLUEBIRD_LGDT			0xd820
+#define USB_PID_DVICO_BLUEBIRD_LG064F_COLD		0xd500
+#define USB_PID_DVICO_BLUEBIRD_LG064F_WARM		0xd501
+#define USB_PID_DVICO_BLUEBIRD_LGZ201_COLD		0xdb00
+#define USB_PID_DVICO_BLUEBIRD_LGZ201_WARM		0xdb01
+#define USB_PID_DVICO_BLUEBIRD_TH7579_COLD		0xdb10
+#define USB_PID_DVICO_BLUEBIRD_TH7579_WARM		0xdb11
+#define USB_PID_DVICO_BLUEBIRD_DUAL_1_COLD		0xdb50
+#define USB_PID_DVICO_BLUEBIRD_DUAL_1_WARM		0xdb51
+#define USB_PID_DVICO_BLUEBIRD_DUAL_2_COLD		0xdb58
+#define USB_PID_DVICO_BLUEBIRD_DUAL_2_WARM		0xdb59
+#define USB_PID_DVICO_BLUEBIRD_DUAL_4			0xdb78
+#define USB_PID_DVICO_BLUEBIRD_DUAL_4_REV_2		0xdb98
+#define USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2		0xdb70
+#define USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2_NFW_WARM	0xdb71
+#define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_COLD		0xdb54
+#define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_WARM		0xdb55
+#define USB_PID_MEDION_MD95700				0x0932
+#define USB_PID_MSI_MEGASKY580				0x5580
+#define USB_PID_MSI_MEGASKY580_55801			0x5581
+#define USB_PID_KYE_DVB_T_COLD				0x701e
+#define USB_PID_KYE_DVB_T_WARM				0x701f
+#define USB_PID_LITEON_DVB_T_COLD			0xf000
+#define USB_PID_LITEON_DVB_T_WARM			0xf001
+#define USB_PID_DIGIVOX_MINI_SL_COLD			0xe360
+#define USB_PID_DIGIVOX_MINI_SL_WARM			0xe361
+#define USB_PID_GRANDTEC_DVBT_USB2_COLD			0x0bc6
+#define USB_PID_GRANDTEC_DVBT_USB2_WARM			0x0bc7
+#define USB_PID_WINFAST_DTV2000DS			0x6a04
+#define USB_PID_WINFAST_DTV_DONGLE_COLD			0x6025
+#define USB_PID_WINFAST_DTV_DONGLE_WARM			0x6026
+#define USB_PID_WINFAST_DTV_DONGLE_STK7700P		0x6f00
+#define USB_PID_WINFAST_DTV_DONGLE_H			0x60f6
+#define USB_PID_WINFAST_DTV_DONGLE_STK7700P_2		0x6f01
+#define USB_PID_WINFAST_DTV_DONGLE_GOLD			0x6029
+#define USB_PID_GENPIX_8PSK_REV_1_COLD			0x0200
+#define USB_PID_GENPIX_8PSK_REV_1_WARM			0x0201
+#define USB_PID_GENPIX_8PSK_REV_2			0x0202
+#define USB_PID_GENPIX_SKYWALKER_1			0x0203
+#define USB_PID_GENPIX_SKYWALKER_CW3K			0x0204
+#define USB_PID_GENPIX_SKYWALKER_2			0x0206
+#define USB_PID_SIGMATEK_DVB_110			0x6610
+#define USB_PID_MSI_DIGI_VOX_MINI_II			0x1513
+#define USB_PID_MSI_DIGIVOX_DUO				0x8801
+#define USB_PID_OPERA1_COLD				0x2830
+#define USB_PID_OPERA1_WARM				0x3829
+#define USB_PID_LIFEVIEW_TV_WALKER_TWIN_COLD		0x0514
+#define USB_PID_LIFEVIEW_TV_WALKER_TWIN_WARM		0x0513
+#define USB_PID_GIGABYTE_U7000				0x7001
+#define USB_PID_GIGABYTE_U8000				0x7002
+#define USB_PID_ASUS_U3000				0x171f
+#define USB_PID_ASUS_U3000H				0x1736
+#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_YUAN_STK7700D				0x1efc
+#define USB_PID_YUAN_STK7700D_2				0x1e8c
+#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_MYGICA_D689				0xd811
+#define USB_PID_ELGATO_EYETV_DIVERSITY			0x0011
+#define USB_PID_ELGATO_EYETV_DTT			0x0021
+#define USB_PID_ELGATO_EYETV_DTT_2			0x003f
+#define USB_PID_ELGATO_EYETV_DTT_Dlx			0x0020
+#define USB_PID_ELGATO_EYETV_SAT			0x002a
+#define USB_PID_DVB_T_USB_STICK_HIGH_SPEED_COLD		0x5000
+#define USB_PID_DVB_T_USB_STICK_HIGH_SPEED_WARM		0x5001
+#define USB_PID_FRIIO_WHITE				0x0001
+#define USB_PID_TVWAY_PLUS				0x0002
+#define USB_PID_SVEON_STV20				0xe39d
+#define USB_PID_SVEON_STV22				0xe401
+#define USB_PID_SVEON_STV22_IT9137			0xe411
+#define USB_PID_AZUREWAVE_AZ6027			0x3275
+#define USB_PID_TERRATEC_DVBS2CI_V1			0x10a4
+#define USB_PID_TERRATEC_DVBS2CI_V2			0x10ac
+#define USB_PID_TECHNISAT_USB2_HDCI_V1			0x0001
+#define USB_PID_TECHNISAT_USB2_HDCI_V2			0x0002
+#define USB_PID_TECHNISAT_AIRSTAR_TELESTICK_2		0x0004
+#define USB_PID_TECHNISAT_USB2_DVB_S2			0x0500
+#endif
diff --git a/drivers/media/dvb-core/dvb_ca_en50221.c b/drivers/media/dvb-core/dvb_ca_en50221.c
new file mode 100644
index 0000000..9be65a3
--- /dev/null
+++ b/drivers/media/dvb-core/dvb_ca_en50221.c
@@ -0,0 +1,1753 @@
+/*
+ * dvb_ca.c: generic DVB functions for EN50221 CAM interfaces
+ *
+ * Copyright (C) 2004 Andrew de Quincey
+ *
+ * Parts of this file were based on sources as follows:
+ *
+ * Copyright (C) 2003 Ralph Metzler <rjkm@metzlerbros.de>
+ *
+ * based on code:
+ *
+ * Copyright (C) 1999-2002 Ralph  Metzler
+ *                       & Marcus Metzler for convergence integrated media GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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.
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <linux/sched.h>
+#include <linux/kthread.h>
+
+#include "dvb_ca_en50221.h"
+#include "dvb_ringbuffer.h"
+
+static int dvb_ca_en50221_debug;
+
+module_param_named(cam_debug, dvb_ca_en50221_debug, int, 0644);
+MODULE_PARM_DESC(cam_debug, "enable verbose debug messages");
+
+#define dprintk if (dvb_ca_en50221_debug) printk
+
+#define INIT_TIMEOUT_SECS 10
+
+#define HOST_LINK_BUF_SIZE 0x200
+
+#define RX_BUFFER_SIZE 65535
+
+#define MAX_RX_PACKETS_PER_ITERATION 10
+
+#define CTRLIF_DATA      0
+#define CTRLIF_COMMAND   1
+#define CTRLIF_STATUS    1
+#define CTRLIF_SIZE_LOW  2
+#define CTRLIF_SIZE_HIGH 3
+
+#define CMDREG_HC        1	/* Host control */
+#define CMDREG_SW        2	/* Size write */
+#define CMDREG_SR        4	/* Size read */
+#define CMDREG_RS        8	/* Reset interface */
+#define CMDREG_FRIE   0x40	/* Enable FR interrupt */
+#define CMDREG_DAIE   0x80	/* Enable DA interrupt */
+#define IRQEN (CMDREG_DAIE)
+
+#define STATUSREG_RE     1	/* read error */
+#define STATUSREG_WE     2	/* write error */
+#define STATUSREG_FR  0x40	/* module free */
+#define STATUSREG_DA  0x80	/* data available */
+#define STATUSREG_TXERR (STATUSREG_RE|STATUSREG_WE)	/* general transfer error */
+
+
+#define DVB_CA_SLOTSTATE_NONE           0
+#define DVB_CA_SLOTSTATE_UNINITIALISED  1
+#define DVB_CA_SLOTSTATE_RUNNING        2
+#define DVB_CA_SLOTSTATE_INVALID        3
+#define DVB_CA_SLOTSTATE_WAITREADY      4
+#define DVB_CA_SLOTSTATE_VALIDATE       5
+#define DVB_CA_SLOTSTATE_WAITFR         6
+#define DVB_CA_SLOTSTATE_LINKINIT       7
+
+
+/* Information on a CA slot */
+struct dvb_ca_slot {
+
+	/* current state of the CAM */
+	int slot_state;
+
+	/* mutex used for serializing access to one CI slot */
+	struct mutex slot_lock;
+
+	/* Number of CAMCHANGES that have occurred since last processing */
+	atomic_t camchange_count;
+
+	/* Type of last CAMCHANGE */
+	int camchange_type;
+
+	/* base address of CAM config */
+	u32 config_base;
+
+	/* value to write into Config Control register */
+	u8 config_option;
+
+	/* if 1, the CAM supports DA IRQs */
+	u8 da_irq_supported:1;
+
+	/* size of the buffer to use when talking to the CAM */
+	int link_buf_size;
+
+	/* buffer for incoming packets */
+	struct dvb_ringbuffer rx_buffer;
+
+	/* timer used during various states of the slot */
+	unsigned long timeout;
+};
+
+/* Private CA-interface information */
+struct dvb_ca_private {
+
+	/* pointer back to the public data structure */
+	struct dvb_ca_en50221 *pub;
+
+	/* the DVB device */
+	struct dvb_device *dvbdev;
+
+	/* Flags describing the interface (DVB_CA_FLAG_*) */
+	u32 flags;
+
+	/* number of slots supported by this CA interface */
+	unsigned int slot_count;
+
+	/* information on each slot */
+	struct dvb_ca_slot *slot_info;
+
+	/* wait queues for read() and write() operations */
+	wait_queue_head_t wait_queue;
+
+	/* PID of the monitoring thread */
+	struct task_struct *thread;
+
+	/* Flag indicating if the CA device is open */
+	unsigned int open:1;
+
+	/* Flag indicating the thread should wake up now */
+	unsigned int wakeup:1;
+
+	/* Delay the main thread should use */
+	unsigned long delay;
+
+	/* Slot to start looking for data to read from in the next user-space read operation */
+	int next_read_slot;
+};
+
+static void dvb_ca_en50221_thread_wakeup(struct dvb_ca_private *ca);
+static int dvb_ca_en50221_read_data(struct dvb_ca_private *ca, int slot, u8 * ebuf, int ecount);
+static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot, u8 * ebuf, int ecount);
+
+
+/**
+ * Safely find needle in haystack.
+ *
+ * @param haystack Buffer to look in.
+ * @param hlen Number of bytes in haystack.
+ * @param needle Buffer to find.
+ * @param nlen Number of bytes in needle.
+ * @return Pointer into haystack needle was found at, or NULL if not found.
+ */
+static char *findstr(char * haystack, int hlen, char * needle, int nlen)
+{
+	int i;
+
+	if (hlen < nlen)
+		return NULL;
+
+	for (i = 0; i <= hlen - nlen; i++) {
+		if (!strncmp(haystack + i, needle, nlen))
+			return haystack + i;
+	}
+
+	return NULL;
+}
+
+
+
+/* ******************************************************************************** */
+/* EN50221 physical interface functions */
+
+
+/**
+ * Check CAM status.
+ */
+static int dvb_ca_en50221_check_camstatus(struct dvb_ca_private *ca, int slot)
+{
+	int slot_status;
+	int cam_present_now;
+	int cam_changed;
+
+	/* IRQ mode */
+	if (ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE) {
+		return (atomic_read(&ca->slot_info[slot].camchange_count) != 0);
+	}
+
+	/* poll mode */
+	slot_status = ca->pub->poll_slot_status(ca->pub, slot, ca->open);
+
+	cam_present_now = (slot_status & DVB_CA_EN50221_POLL_CAM_PRESENT) ? 1 : 0;
+	cam_changed = (slot_status & DVB_CA_EN50221_POLL_CAM_CHANGED) ? 1 : 0;
+	if (!cam_changed) {
+		int cam_present_old = (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_NONE);
+		cam_changed = (cam_present_now != cam_present_old);
+	}
+
+	if (cam_changed) {
+		if (!cam_present_now) {
+			ca->slot_info[slot].camchange_type = DVB_CA_EN50221_CAMCHANGE_REMOVED;
+		} else {
+			ca->slot_info[slot].camchange_type = DVB_CA_EN50221_CAMCHANGE_INSERTED;
+		}
+		atomic_set(&ca->slot_info[slot].camchange_count, 1);
+	} else {
+		if ((ca->slot_info[slot].slot_state == DVB_CA_SLOTSTATE_WAITREADY) &&
+		    (slot_status & DVB_CA_EN50221_POLL_CAM_READY)) {
+			// move to validate state if reset is completed
+			ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_VALIDATE;
+		}
+	}
+
+	return cam_changed;
+}
+
+
+/**
+ * Wait for flags to become set on the STATUS register on a CAM interface,
+ * checking for errors and timeout.
+ *
+ * @param ca CA instance.
+ * @param slot Slot on interface.
+ * @param waitfor Flags to wait for.
+ * @param timeout_ms Timeout in milliseconds.
+ *
+ * @return 0 on success, nonzero on error.
+ */
+static int dvb_ca_en50221_wait_if_status(struct dvb_ca_private *ca, int slot,
+					 u8 waitfor, int timeout_hz)
+{
+	unsigned long timeout;
+	unsigned long start;
+
+	dprintk("%s\n", __func__);
+
+	/* loop until timeout elapsed */
+	start = jiffies;
+	timeout = jiffies + timeout_hz;
+	while (1) {
+		/* read the status and check for error */
+		int res = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS);
+		if (res < 0)
+			return -EIO;
+
+		/* if we got the flags, it was successful! */
+		if (res & waitfor) {
+			dprintk("%s succeeded timeout:%lu\n", __func__, jiffies - start);
+			return 0;
+		}
+
+		/* check for timeout */
+		if (time_after(jiffies, timeout)) {
+			break;
+		}
+
+		/* wait for a bit */
+		msleep(1);
+	}
+
+	dprintk("%s failed timeout:%lu\n", __func__, jiffies - start);
+
+	/* if we get here, we've timed out */
+	return -ETIMEDOUT;
+}
+
+
+/**
+ * Initialise the link layer connection to a CAM.
+ *
+ * @param ca CA instance.
+ * @param slot Slot id.
+ *
+ * @return 0 on success, nonzero on failure.
+ */
+static int dvb_ca_en50221_link_init(struct dvb_ca_private *ca, int slot)
+{
+	int ret;
+	int buf_size;
+	u8 buf[2];
+
+	dprintk("%s\n", __func__);
+
+	/* we'll be determining these during this function */
+	ca->slot_info[slot].da_irq_supported = 0;
+
+	/* set the host link buffer size temporarily. it will be overwritten with the
+	 * real negotiated size later. */
+	ca->slot_info[slot].link_buf_size = 2;
+
+	/* read the buffer size from the CAM */
+	if ((ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN | CMDREG_SR)) != 0)
+		return ret;
+	if ((ret = dvb_ca_en50221_wait_if_status(ca, slot, STATUSREG_DA, HZ / 10)) != 0)
+		return ret;
+	if ((ret = dvb_ca_en50221_read_data(ca, slot, buf, 2)) != 2)
+		return -EIO;
+	if ((ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN)) != 0)
+		return ret;
+
+	/* store it, and choose the minimum of our buffer and the CAM's buffer size */
+	buf_size = (buf[0] << 8) | buf[1];
+	if (buf_size > HOST_LINK_BUF_SIZE)
+		buf_size = HOST_LINK_BUF_SIZE;
+	ca->slot_info[slot].link_buf_size = buf_size;
+	buf[0] = buf_size >> 8;
+	buf[1] = buf_size & 0xff;
+	dprintk("Chosen link buffer size of %i\n", buf_size);
+
+	/* write the buffer size to the CAM */
+	if ((ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN | CMDREG_SW)) != 0)
+		return ret;
+	if ((ret = dvb_ca_en50221_wait_if_status(ca, slot, STATUSREG_FR, HZ / 10)) != 0)
+		return ret;
+	if ((ret = dvb_ca_en50221_write_data(ca, slot, buf, 2)) != 2)
+		return -EIO;
+	if ((ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN)) != 0)
+		return ret;
+
+	/* success */
+	return 0;
+}
+
+/**
+ * Read a tuple from attribute memory.
+ *
+ * @param ca CA instance.
+ * @param slot Slot id.
+ * @param address Address to read from. Updated.
+ * @param tupleType Tuple id byte. Updated.
+ * @param tupleLength Tuple length. Updated.
+ * @param tuple Dest buffer for tuple (must be 256 bytes). Updated.
+ *
+ * @return 0 on success, nonzero on error.
+ */
+static int dvb_ca_en50221_read_tuple(struct dvb_ca_private *ca, int slot,
+				     int *address, int *tupleType, int *tupleLength, u8 * tuple)
+{
+	int i;
+	int _tupleType;
+	int _tupleLength;
+	int _address = *address;
+
+	/* grab the next tuple length and type */
+	if ((_tupleType = ca->pub->read_attribute_mem(ca->pub, slot, _address)) < 0)
+		return _tupleType;
+	if (_tupleType == 0xff) {
+		dprintk("END OF CHAIN TUPLE type:0x%x\n", _tupleType);
+		*address += 2;
+		*tupleType = _tupleType;
+		*tupleLength = 0;
+		return 0;
+	}
+	if ((_tupleLength = ca->pub->read_attribute_mem(ca->pub, slot, _address + 2)) < 0)
+		return _tupleLength;
+	_address += 4;
+
+	dprintk("TUPLE type:0x%x length:%i\n", _tupleType, _tupleLength);
+
+	/* read in the whole tuple */
+	for (i = 0; i < _tupleLength; i++) {
+		tuple[i] = ca->pub->read_attribute_mem(ca->pub, slot, _address + (i * 2));
+		dprintk("  0x%02x: 0x%02x %c\n",
+			i, tuple[i] & 0xff,
+			((tuple[i] > 31) && (tuple[i] < 127)) ? tuple[i] : '.');
+	}
+	_address += (_tupleLength * 2);
+
+	// success
+	*tupleType = _tupleType;
+	*tupleLength = _tupleLength;
+	*address = _address;
+	return 0;
+}
+
+
+/**
+ * Parse attribute memory of a CAM module, extracting Config register, and checking
+ * it is a DVB CAM module.
+ *
+ * @param ca CA instance.
+ * @param slot Slot id.
+ *
+ * @return 0 on success, <0 on failure.
+ */
+static int dvb_ca_en50221_parse_attributes(struct dvb_ca_private *ca, int slot)
+{
+	int address = 0;
+	int tupleLength;
+	int tupleType;
+	u8 tuple[257];
+	char *dvb_str;
+	int rasz;
+	int status;
+	int got_cftableentry = 0;
+	int end_chain = 0;
+	int i;
+	u16 manfid = 0;
+	u16 devid = 0;
+
+
+	// CISTPL_DEVICE_0A
+	if ((status =
+	     dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType, &tupleLength, tuple)) < 0)
+		return status;
+	if (tupleType != 0x1D)
+		return -EINVAL;
+
+
+
+	// CISTPL_DEVICE_0C
+	if ((status =
+	     dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType, &tupleLength, tuple)) < 0)
+		return status;
+	if (tupleType != 0x1C)
+		return -EINVAL;
+
+
+
+	// CISTPL_VERS_1
+	if ((status =
+	     dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType, &tupleLength, tuple)) < 0)
+		return status;
+	if (tupleType != 0x15)
+		return -EINVAL;
+
+
+
+	// CISTPL_MANFID
+	if ((status = dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType,
+						&tupleLength, tuple)) < 0)
+		return status;
+	if (tupleType != 0x20)
+		return -EINVAL;
+	if (tupleLength != 4)
+		return -EINVAL;
+	manfid = (tuple[1] << 8) | tuple[0];
+	devid = (tuple[3] << 8) | tuple[2];
+
+
+
+	// CISTPL_CONFIG
+	if ((status = dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType,
+						&tupleLength, tuple)) < 0)
+		return status;
+	if (tupleType != 0x1A)
+		return -EINVAL;
+	if (tupleLength < 3)
+		return -EINVAL;
+
+	/* extract the configbase */
+	rasz = tuple[0] & 3;
+	if (tupleLength < (3 + rasz + 14))
+		return -EINVAL;
+	ca->slot_info[slot].config_base = 0;
+	for (i = 0; i < rasz + 1; i++) {
+		ca->slot_info[slot].config_base |= (tuple[2 + i] << (8 * i));
+	}
+
+	/* check it contains the correct DVB string */
+	dvb_str = findstr((char *)tuple, tupleLength, "DVB_CI_V", 8);
+	if (dvb_str == NULL)
+		return -EINVAL;
+	if (tupleLength < ((dvb_str - (char *) tuple) + 12))
+		return -EINVAL;
+
+	/* is it a version we support? */
+	if (strncmp(dvb_str + 8, "1.00", 4)) {
+		printk("dvb_ca adapter %d: Unsupported DVB CAM module version %c%c%c%c\n",
+		       ca->dvbdev->adapter->num, dvb_str[8], dvb_str[9], dvb_str[10], dvb_str[11]);
+		return -EINVAL;
+	}
+
+	/* process the CFTABLE_ENTRY tuples, and any after those */
+	while ((!end_chain) && (address < 0x1000)) {
+		if ((status = dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType,
+							&tupleLength, tuple)) < 0)
+			return status;
+		switch (tupleType) {
+		case 0x1B:	// CISTPL_CFTABLE_ENTRY
+			if (tupleLength < (2 + 11 + 17))
+				break;
+
+			/* if we've already parsed one, just use it */
+			if (got_cftableentry)
+				break;
+
+			/* get the config option */
+			ca->slot_info[slot].config_option = tuple[0] & 0x3f;
+
+			/* OK, check it contains the correct strings */
+			if ((findstr((char *)tuple, tupleLength, "DVB_HOST", 8) == NULL) ||
+			    (findstr((char *)tuple, tupleLength, "DVB_CI_MODULE", 13) == NULL))
+				break;
+
+			got_cftableentry = 1;
+			break;
+
+		case 0x14:	// CISTPL_NO_LINK
+			break;
+
+		case 0xFF:	// CISTPL_END
+			end_chain = 1;
+			break;
+
+		default:	/* Unknown tuple type - just skip this tuple and move to the next one */
+			dprintk("dvb_ca: Skipping unknown tuple type:0x%x length:0x%x\n", tupleType,
+				tupleLength);
+			break;
+		}
+	}
+
+	if ((address > 0x1000) || (!got_cftableentry))
+		return -EINVAL;
+
+	dprintk("Valid DVB CAM detected MANID:%x DEVID:%x CONFIGBASE:0x%x CONFIGOPTION:0x%x\n",
+		manfid, devid, ca->slot_info[slot].config_base, ca->slot_info[slot].config_option);
+
+	// success!
+	return 0;
+}
+
+
+/**
+ * Set CAM's configoption correctly.
+ *
+ * @param ca CA instance.
+ * @param slot Slot containing the CAM.
+ */
+static int dvb_ca_en50221_set_configoption(struct dvb_ca_private *ca, int slot)
+{
+	int configoption;
+
+	dprintk("%s\n", __func__);
+
+	/* set the config option */
+	ca->pub->write_attribute_mem(ca->pub, slot,
+				     ca->slot_info[slot].config_base,
+				     ca->slot_info[slot].config_option);
+
+	/* check it */
+	configoption = ca->pub->read_attribute_mem(ca->pub, slot, ca->slot_info[slot].config_base);
+	dprintk("Set configoption 0x%x, read configoption 0x%x\n",
+		ca->slot_info[slot].config_option, configoption & 0x3f);
+
+	/* fine! */
+	return 0;
+
+}
+
+
+/**
+ * This function talks to an EN50221 CAM control interface. It reads a buffer of
+ * data from the CAM. The data can either be stored in a supplied buffer, or
+ * automatically be added to the slot's rx_buffer.
+ *
+ * @param ca CA instance.
+ * @param slot Slot to read from.
+ * @param ebuf If non-NULL, the data will be written to this buffer. If NULL,
+ * the data will be added into the buffering system as a normal fragment.
+ * @param ecount Size of ebuf. Ignored if ebuf is NULL.
+ *
+ * @return Number of bytes read, or < 0 on error
+ */
+static int dvb_ca_en50221_read_data(struct dvb_ca_private *ca, int slot, u8 * ebuf, int ecount)
+{
+	int bytes_read;
+	int status;
+	u8 buf[HOST_LINK_BUF_SIZE];
+	int i;
+
+	dprintk("%s\n", __func__);
+
+	/* check if we have space for a link buf in the rx_buffer */
+	if (ebuf == NULL) {
+		int buf_free;
+
+		if (ca->slot_info[slot].rx_buffer.data == NULL) {
+			status = -EIO;
+			goto exit;
+		}
+		buf_free = dvb_ringbuffer_free(&ca->slot_info[slot].rx_buffer);
+
+		if (buf_free < (ca->slot_info[slot].link_buf_size + DVB_RINGBUFFER_PKTHDRSIZE)) {
+			status = -EAGAIN;
+			goto exit;
+		}
+	}
+
+	/* check if there is data available */
+	if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0)
+		goto exit;
+	if (!(status & STATUSREG_DA)) {
+		/* no data */
+		status = 0;
+		goto exit;
+	}
+
+	/* read the amount of data */
+	if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_SIZE_HIGH)) < 0)
+		goto exit;
+	bytes_read = status << 8;
+	if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_SIZE_LOW)) < 0)
+		goto exit;
+	bytes_read |= status;
+
+	/* check it will fit */
+	if (ebuf == NULL) {
+		if (bytes_read > ca->slot_info[slot].link_buf_size) {
+			printk("dvb_ca adapter %d: CAM tried to send a buffer larger than the link buffer size (%i > %i)!\n",
+			       ca->dvbdev->adapter->num, bytes_read, ca->slot_info[slot].link_buf_size);
+			ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT;
+			status = -EIO;
+			goto exit;
+		}
+		if (bytes_read < 2) {
+			printk("dvb_ca adapter %d: CAM sent a buffer that was less than 2 bytes!\n",
+			       ca->dvbdev->adapter->num);
+			ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT;
+			status = -EIO;
+			goto exit;
+		}
+	} else {
+		if (bytes_read > ecount) {
+			printk("dvb_ca adapter %d: CAM tried to send a buffer larger than the ecount size!\n",
+			       ca->dvbdev->adapter->num);
+			status = -EIO;
+			goto exit;
+		}
+	}
+
+	/* fill the buffer */
+	for (i = 0; i < bytes_read; i++) {
+		/* read byte and check */
+		if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_DATA)) < 0)
+			goto exit;
+
+		/* OK, store it in the buffer */
+		buf[i] = status;
+	}
+
+	/* check for read error (RE should now be 0) */
+	if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0)
+		goto exit;
+	if (status & STATUSREG_RE) {
+		ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT;
+		status = -EIO;
+		goto exit;
+	}
+
+	/* OK, add it to the receive buffer, or copy into external buffer if supplied */
+	if (ebuf == NULL) {
+		if (ca->slot_info[slot].rx_buffer.data == NULL) {
+			status = -EIO;
+			goto exit;
+		}
+		dvb_ringbuffer_pkt_write(&ca->slot_info[slot].rx_buffer, buf, bytes_read);
+	} else {
+		memcpy(ebuf, buf, bytes_read);
+	}
+
+	dprintk("Received CA packet for slot %i connection id 0x%x last_frag:%i size:0x%x\n", slot,
+		buf[0], (buf[1] & 0x80) == 0, bytes_read);
+
+	/* wake up readers when a last_fragment is received */
+	if ((buf[1] & 0x80) == 0x00) {
+		wake_up_interruptible(&ca->wait_queue);
+	}
+	status = bytes_read;
+
+exit:
+	return status;
+}
+
+
+/**
+ * This function talks to an EN50221 CAM control interface. It writes a buffer of data
+ * to a CAM.
+ *
+ * @param ca CA instance.
+ * @param slot Slot to write to.
+ * @param ebuf The data in this buffer is treated as a complete link-level packet to
+ * be written.
+ * @param count Size of ebuf.
+ *
+ * @return Number of bytes written, or < 0 on error.
+ */
+static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot, u8 * buf, int bytes_write)
+{
+	int status;
+	int i;
+
+	dprintk("%s\n", __func__);
+
+
+	/* sanity check */
+	if (bytes_write > ca->slot_info[slot].link_buf_size)
+		return -EINVAL;
+
+	/* it is possible we are dealing with a single buffer implementation,
+	   thus if there is data available for read or if there is even a read
+	   already in progress, we do nothing but awake the kernel thread to
+	   process the data if necessary. */
+	if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0)
+		goto exitnowrite;
+	if (status & (STATUSREG_DA | STATUSREG_RE)) {
+		if (status & STATUSREG_DA)
+			dvb_ca_en50221_thread_wakeup(ca);
+
+		status = -EAGAIN;
+		goto exitnowrite;
+	}
+
+	/* OK, set HC bit */
+	if ((status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND,
+						 IRQEN | CMDREG_HC)) != 0)
+		goto exit;
+
+	/* check if interface is still free */
+	if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0)
+		goto exit;
+	if (!(status & STATUSREG_FR)) {
+		/* it wasn't free => try again later */
+		status = -EAGAIN;
+		goto exit;
+	}
+
+	/* send the amount of data */
+	if ((status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_SIZE_HIGH, bytes_write >> 8)) != 0)
+		goto exit;
+	if ((status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_SIZE_LOW,
+						 bytes_write & 0xff)) != 0)
+		goto exit;
+
+	/* send the buffer */
+	for (i = 0; i < bytes_write; i++) {
+		if ((status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_DATA, buf[i])) != 0)
+			goto exit;
+	}
+
+	/* check for write error (WE should now be 0) */
+	if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0)
+		goto exit;
+	if (status & STATUSREG_WE) {
+		ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT;
+		status = -EIO;
+		goto exit;
+	}
+	status = bytes_write;
+
+	dprintk("Wrote CA packet for slot %i, connection id 0x%x last_frag:%i size:0x%x\n", slot,
+		buf[0], (buf[1] & 0x80) == 0, bytes_write);
+
+exit:
+	ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN);
+
+exitnowrite:
+	return status;
+}
+EXPORT_SYMBOL(dvb_ca_en50221_camchange_irq);
+
+
+
+/* ******************************************************************************** */
+/* EN50221 higher level functions */
+
+
+/**
+ * A CAM has been removed => shut it down.
+ *
+ * @param ca CA instance.
+ * @param slot Slot to shut down.
+ */
+static int dvb_ca_en50221_slot_shutdown(struct dvb_ca_private *ca, int slot)
+{
+	dprintk("%s\n", __func__);
+
+	ca->pub->slot_shutdown(ca->pub, slot);
+	ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_NONE;
+
+	/* need to wake up all processes to check if they're now
+	   trying to write to a defunct CAM */
+	wake_up_interruptible(&ca->wait_queue);
+
+	dprintk("Slot %i shutdown\n", slot);
+
+	/* success */
+	return 0;
+}
+EXPORT_SYMBOL(dvb_ca_en50221_camready_irq);
+
+
+/**
+ * A CAMCHANGE IRQ has occurred.
+ *
+ * @param ca CA instance.
+ * @param slot Slot concerned.
+ * @param change_type One of the DVB_CA_CAMCHANGE_* values.
+ */
+void dvb_ca_en50221_camchange_irq(struct dvb_ca_en50221 *pubca, int slot, int change_type)
+{
+	struct dvb_ca_private *ca = pubca->private;
+
+	dprintk("CAMCHANGE IRQ slot:%i change_type:%i\n", slot, change_type);
+
+	switch (change_type) {
+	case DVB_CA_EN50221_CAMCHANGE_REMOVED:
+	case DVB_CA_EN50221_CAMCHANGE_INSERTED:
+		break;
+
+	default:
+		return;
+	}
+
+	ca->slot_info[slot].camchange_type = change_type;
+	atomic_inc(&ca->slot_info[slot].camchange_count);
+	dvb_ca_en50221_thread_wakeup(ca);
+}
+EXPORT_SYMBOL(dvb_ca_en50221_frda_irq);
+
+
+/**
+ * A CAMREADY IRQ has occurred.
+ *
+ * @param ca CA instance.
+ * @param slot Slot concerned.
+ */
+void dvb_ca_en50221_camready_irq(struct dvb_ca_en50221 *pubca, int slot)
+{
+	struct dvb_ca_private *ca = pubca->private;
+
+	dprintk("CAMREADY IRQ slot:%i\n", slot);
+
+	if (ca->slot_info[slot].slot_state == DVB_CA_SLOTSTATE_WAITREADY) {
+		ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_VALIDATE;
+		dvb_ca_en50221_thread_wakeup(ca);
+	}
+}
+
+
+/**
+ * An FR or DA IRQ has occurred.
+ *
+ * @param ca CA instance.
+ * @param slot Slot concerned.
+ */
+void dvb_ca_en50221_frda_irq(struct dvb_ca_en50221 *pubca, int slot)
+{
+	struct dvb_ca_private *ca = pubca->private;
+	int flags;
+
+	dprintk("FR/DA IRQ slot:%i\n", slot);
+
+	switch (ca->slot_info[slot].slot_state) {
+	case DVB_CA_SLOTSTATE_LINKINIT:
+		flags = ca->pub->read_cam_control(pubca, slot, CTRLIF_STATUS);
+		if (flags & STATUSREG_DA) {
+			dprintk("CAM supports DA IRQ\n");
+			ca->slot_info[slot].da_irq_supported = 1;
+		}
+		break;
+
+	case DVB_CA_SLOTSTATE_RUNNING:
+		if (ca->open)
+			dvb_ca_en50221_thread_wakeup(ca);
+		break;
+	}
+}
+
+
+
+/* ******************************************************************************** */
+/* EN50221 thread functions */
+
+/**
+ * Wake up the DVB CA thread
+ *
+ * @param ca CA instance.
+ */
+static void dvb_ca_en50221_thread_wakeup(struct dvb_ca_private *ca)
+{
+
+	dprintk("%s\n", __func__);
+
+	ca->wakeup = 1;
+	mb();
+	wake_up_process(ca->thread);
+}
+
+/**
+ * Update the delay used by the thread.
+ *
+ * @param ca CA instance.
+ */
+static void dvb_ca_en50221_thread_update_delay(struct dvb_ca_private *ca)
+{
+	int delay;
+	int curdelay = 100000000;
+	int slot;
+
+	/* Beware of too high polling frequency, because one polling
+	 * call might take several hundred milliseconds until timeout!
+	 */
+	for (slot = 0; slot < ca->slot_count; slot++) {
+		switch (ca->slot_info[slot].slot_state) {
+		default:
+		case DVB_CA_SLOTSTATE_NONE:
+			delay = HZ * 60;  /* 60s */
+			if (!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE))
+				delay = HZ * 5;  /* 5s */
+			break;
+		case DVB_CA_SLOTSTATE_INVALID:
+			delay = HZ * 60;  /* 60s */
+			if (!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE))
+				delay = HZ / 10;  /* 100ms */
+			break;
+
+		case DVB_CA_SLOTSTATE_UNINITIALISED:
+		case DVB_CA_SLOTSTATE_WAITREADY:
+		case DVB_CA_SLOTSTATE_VALIDATE:
+		case DVB_CA_SLOTSTATE_WAITFR:
+		case DVB_CA_SLOTSTATE_LINKINIT:
+			delay = HZ / 10;  /* 100ms */
+			break;
+
+		case DVB_CA_SLOTSTATE_RUNNING:
+			delay = HZ * 60;  /* 60s */
+			if (!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE))
+				delay = HZ / 10;  /* 100ms */
+			if (ca->open) {
+				if ((!ca->slot_info[slot].da_irq_supported) ||
+				    (!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_DA)))
+					delay = HZ / 10;  /* 100ms */
+			}
+			break;
+		}
+
+		if (delay < curdelay)
+			curdelay = delay;
+	}
+
+	ca->delay = curdelay;
+}
+
+
+
+/**
+ * Kernel thread which monitors CA slots for CAM changes, and performs data transfers.
+ */
+static int dvb_ca_en50221_thread(void *data)
+{
+	struct dvb_ca_private *ca = data;
+	int slot;
+	int flags;
+	int status;
+	int pktcount;
+	void *rxbuf;
+
+	dprintk("%s\n", __func__);
+
+	/* choose the correct initial delay */
+	dvb_ca_en50221_thread_update_delay(ca);
+
+	/* main loop */
+	while (!kthread_should_stop()) {
+		/* sleep for a bit */
+		if (!ca->wakeup) {
+			set_current_state(TASK_INTERRUPTIBLE);
+			schedule_timeout(ca->delay);
+			if (kthread_should_stop())
+				return 0;
+		}
+		ca->wakeup = 0;
+
+		/* go through all the slots processing them */
+		for (slot = 0; slot < ca->slot_count; slot++) {
+
+			mutex_lock(&ca->slot_info[slot].slot_lock);
+
+			// check the cam status + deal with CAMCHANGEs
+			while (dvb_ca_en50221_check_camstatus(ca, slot)) {
+				/* clear down an old CI slot if necessary */
+				if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_NONE)
+					dvb_ca_en50221_slot_shutdown(ca, slot);
+
+				/* if a CAM is NOW present, initialise it */
+				if (ca->slot_info[slot].camchange_type == DVB_CA_EN50221_CAMCHANGE_INSERTED) {
+					ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_UNINITIALISED;
+				}
+
+				/* we've handled one CAMCHANGE */
+				dvb_ca_en50221_thread_update_delay(ca);
+				atomic_dec(&ca->slot_info[slot].camchange_count);
+			}
+
+			// CAM state machine
+			switch (ca->slot_info[slot].slot_state) {
+			case DVB_CA_SLOTSTATE_NONE:
+			case DVB_CA_SLOTSTATE_INVALID:
+				// no action needed
+				break;
+
+			case DVB_CA_SLOTSTATE_UNINITIALISED:
+				ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_WAITREADY;
+				ca->pub->slot_reset(ca->pub, slot);
+				ca->slot_info[slot].timeout = jiffies + (INIT_TIMEOUT_SECS * HZ);
+				break;
+
+			case DVB_CA_SLOTSTATE_WAITREADY:
+				if (time_after(jiffies, ca->slot_info[slot].timeout)) {
+					printk("dvb_ca adaptor %d: PC card did not respond :(\n",
+					       ca->dvbdev->adapter->num);
+					ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
+					dvb_ca_en50221_thread_update_delay(ca);
+					break;
+				}
+				// no other action needed; will automatically change state when ready
+				break;
+
+			case DVB_CA_SLOTSTATE_VALIDATE:
+				if (dvb_ca_en50221_parse_attributes(ca, slot) != 0) {
+					/* we need this extra check for annoying interfaces like the budget-av */
+					if ((!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) &&
+					    (ca->pub->poll_slot_status)) {
+						status = ca->pub->poll_slot_status(ca->pub, slot, 0);
+						if (!(status & DVB_CA_EN50221_POLL_CAM_PRESENT)) {
+							ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_NONE;
+							dvb_ca_en50221_thread_update_delay(ca);
+							break;
+						}
+					}
+
+					printk("dvb_ca adapter %d: Invalid PC card inserted :(\n",
+					       ca->dvbdev->adapter->num);
+					ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
+					dvb_ca_en50221_thread_update_delay(ca);
+					break;
+				}
+				if (dvb_ca_en50221_set_configoption(ca, slot) != 0) {
+					printk("dvb_ca adapter %d: Unable to initialise CAM :(\n",
+					       ca->dvbdev->adapter->num);
+					ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
+					dvb_ca_en50221_thread_update_delay(ca);
+					break;
+				}
+				if (ca->pub->write_cam_control(ca->pub, slot,
+							       CTRLIF_COMMAND, CMDREG_RS) != 0) {
+					printk("dvb_ca adapter %d: Unable to reset CAM IF\n",
+					       ca->dvbdev->adapter->num);
+					ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
+					dvb_ca_en50221_thread_update_delay(ca);
+					break;
+				}
+				dprintk("DVB CAM validated successfully\n");
+
+				ca->slot_info[slot].timeout = jiffies + (INIT_TIMEOUT_SECS * HZ);
+				ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_WAITFR;
+				ca->wakeup = 1;
+				break;
+
+			case DVB_CA_SLOTSTATE_WAITFR:
+				if (time_after(jiffies, ca->slot_info[slot].timeout)) {
+					printk("dvb_ca adapter %d: DVB CAM did not respond :(\n",
+					       ca->dvbdev->adapter->num);
+					ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
+					dvb_ca_en50221_thread_update_delay(ca);
+					break;
+				}
+
+				flags = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS);
+				if (flags & STATUSREG_FR) {
+					ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT;
+					ca->wakeup = 1;
+				}
+				break;
+
+			case DVB_CA_SLOTSTATE_LINKINIT:
+				if (dvb_ca_en50221_link_init(ca, slot) != 0) {
+					/* we need this extra check for annoying interfaces like the budget-av */
+					if ((!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) &&
+					    (ca->pub->poll_slot_status)) {
+						status = ca->pub->poll_slot_status(ca->pub, slot, 0);
+						if (!(status & DVB_CA_EN50221_POLL_CAM_PRESENT)) {
+							ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_NONE;
+							dvb_ca_en50221_thread_update_delay(ca);
+							break;
+						}
+					}
+
+					printk("dvb_ca adapter %d: DVB CAM link initialisation failed :(\n", ca->dvbdev->adapter->num);
+					ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
+					dvb_ca_en50221_thread_update_delay(ca);
+					break;
+				}
+
+				if (ca->slot_info[slot].rx_buffer.data == NULL) {
+					rxbuf = vmalloc(RX_BUFFER_SIZE);
+					if (rxbuf == NULL) {
+						printk("dvb_ca adapter %d: Unable to allocate CAM rx buffer :(\n", ca->dvbdev->adapter->num);
+						ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
+						dvb_ca_en50221_thread_update_delay(ca);
+						break;
+					}
+					dvb_ringbuffer_init(&ca->slot_info[slot].rx_buffer, rxbuf, RX_BUFFER_SIZE);
+				}
+
+				ca->pub->slot_ts_enable(ca->pub, slot);
+				ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_RUNNING;
+				dvb_ca_en50221_thread_update_delay(ca);
+				printk("dvb_ca adapter %d: DVB CAM detected and initialised successfully\n", ca->dvbdev->adapter->num);
+				break;
+
+			case DVB_CA_SLOTSTATE_RUNNING:
+				if (!ca->open)
+					break;
+
+				// poll slots for data
+				pktcount = 0;
+				while ((status = dvb_ca_en50221_read_data(ca, slot, NULL, 0)) > 0) {
+					if (!ca->open)
+						break;
+
+					/* if a CAMCHANGE occurred at some point, do not do any more processing of this slot */
+					if (dvb_ca_en50221_check_camstatus(ca, slot)) {
+						// we dont want to sleep on the next iteration so we can handle the cam change
+						ca->wakeup = 1;
+						break;
+					}
+
+					/* check if we've hit our limit this time */
+					if (++pktcount >= MAX_RX_PACKETS_PER_ITERATION) {
+						// dont sleep; there is likely to be more data to read
+						ca->wakeup = 1;
+						break;
+					}
+				}
+				break;
+			}
+
+			mutex_unlock(&ca->slot_info[slot].slot_lock);
+		}
+	}
+
+	return 0;
+}
+
+
+
+/* ******************************************************************************** */
+/* EN50221 IO interface functions */
+
+/**
+ * Real ioctl implementation.
+ * NOTE: CA_SEND_MSG/CA_GET_MSG ioctls have userspace buffers passed to them.
+ *
+ * @param inode Inode concerned.
+ * @param file File concerned.
+ * @param cmd IOCTL command.
+ * @param arg Associated argument.
+ *
+ * @return 0 on success, <0 on error.
+ */
+static int dvb_ca_en50221_io_do_ioctl(struct file *file,
+				      unsigned int cmd, void *parg)
+{
+	struct dvb_device *dvbdev = file->private_data;
+	struct dvb_ca_private *ca = dvbdev->priv;
+	int err = 0;
+	int slot;
+
+	dprintk("%s\n", __func__);
+
+	switch (cmd) {
+	case CA_RESET:
+		for (slot = 0; slot < ca->slot_count; slot++) {
+			mutex_lock(&ca->slot_info[slot].slot_lock);
+			if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_NONE) {
+				dvb_ca_en50221_slot_shutdown(ca, slot);
+				if (ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)
+					dvb_ca_en50221_camchange_irq(ca->pub,
+								     slot,
+								     DVB_CA_EN50221_CAMCHANGE_INSERTED);
+			}
+			mutex_unlock(&ca->slot_info[slot].slot_lock);
+		}
+		ca->next_read_slot = 0;
+		dvb_ca_en50221_thread_wakeup(ca);
+		break;
+
+	case CA_GET_CAP: {
+		struct ca_caps *caps = parg;
+
+		caps->slot_num = ca->slot_count;
+		caps->slot_type = CA_CI_LINK;
+		caps->descr_num = 0;
+		caps->descr_type = 0;
+		break;
+	}
+
+	case CA_GET_SLOT_INFO: {
+		struct ca_slot_info *info = parg;
+
+		if ((info->num > ca->slot_count) || (info->num < 0))
+			return -EINVAL;
+
+		info->type = CA_CI_LINK;
+		info->flags = 0;
+		if ((ca->slot_info[info->num].slot_state != DVB_CA_SLOTSTATE_NONE)
+			&& (ca->slot_info[info->num].slot_state != DVB_CA_SLOTSTATE_INVALID)) {
+			info->flags = CA_CI_MODULE_PRESENT;
+		}
+		if (ca->slot_info[info->num].slot_state == DVB_CA_SLOTSTATE_RUNNING) {
+			info->flags |= CA_CI_MODULE_READY;
+		}
+		break;
+	}
+
+	default:
+		err = -EINVAL;
+		break;
+	}
+
+	return err;
+}
+
+
+/**
+ * Wrapper for ioctl implementation.
+ *
+ * @param inode Inode concerned.
+ * @param file File concerned.
+ * @param cmd IOCTL command.
+ * @param arg Associated argument.
+ *
+ * @return 0 on success, <0 on error.
+ */
+static long dvb_ca_en50221_io_ioctl(struct file *file,
+				    unsigned int cmd, unsigned long arg)
+{
+	return dvb_usercopy(file, cmd, arg, dvb_ca_en50221_io_do_ioctl);
+}
+
+
+/**
+ * Implementation of write() syscall.
+ *
+ * @param file File structure.
+ * @param buf Source buffer.
+ * @param count Size of source buffer.
+ * @param ppos Position in file (ignored).
+ *
+ * @return Number of bytes read, or <0 on error.
+ */
+static ssize_t dvb_ca_en50221_io_write(struct file *file,
+				       const char __user * buf, size_t count, loff_t * ppos)
+{
+	struct dvb_device *dvbdev = file->private_data;
+	struct dvb_ca_private *ca = dvbdev->priv;
+	u8 slot, connection_id;
+	int status;
+	u8 fragbuf[HOST_LINK_BUF_SIZE];
+	int fragpos = 0;
+	int fraglen;
+	unsigned long timeout;
+	int written;
+
+	dprintk("%s\n", __func__);
+
+	/* Incoming packet has a 2 byte header. hdr[0] = slot_id, hdr[1] = connection_id */
+	if (count < 2)
+		return -EINVAL;
+
+	/* extract slot & connection id */
+	if (copy_from_user(&slot, buf, 1))
+		return -EFAULT;
+	if (copy_from_user(&connection_id, buf + 1, 1))
+		return -EFAULT;
+	buf += 2;
+	count -= 2;
+
+	/* check if the slot is actually running */
+	if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_RUNNING)
+		return -EINVAL;
+
+	/* fragment the packets & store in the buffer */
+	while (fragpos < count) {
+		fraglen = ca->slot_info[slot].link_buf_size - 2;
+		if (fraglen < 0)
+			break;
+		if (fraglen > HOST_LINK_BUF_SIZE - 2)
+			fraglen = HOST_LINK_BUF_SIZE - 2;
+		if ((count - fragpos) < fraglen)
+			fraglen = count - fragpos;
+
+		fragbuf[0] = connection_id;
+		fragbuf[1] = ((fragpos + fraglen) < count) ? 0x80 : 0x00;
+		status = copy_from_user(fragbuf + 2, buf + fragpos, fraglen);
+		if (status) {
+			status = -EFAULT;
+			goto exit;
+		}
+
+		timeout = jiffies + HZ / 2;
+		written = 0;
+		while (!time_after(jiffies, timeout)) {
+			/* check the CAM hasn't been removed/reset in the meantime */
+			if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_RUNNING) {
+				status = -EIO;
+				goto exit;
+			}
+
+			mutex_lock(&ca->slot_info[slot].slot_lock);
+			status = dvb_ca_en50221_write_data(ca, slot, fragbuf, fraglen + 2);
+			mutex_unlock(&ca->slot_info[slot].slot_lock);
+			if (status == (fraglen + 2)) {
+				written = 1;
+				break;
+			}
+			if (status != -EAGAIN)
+				goto exit;
+
+			msleep(1);
+		}
+		if (!written) {
+			status = -EIO;
+			goto exit;
+		}
+
+		fragpos += fraglen;
+	}
+	status = count + 2;
+
+exit:
+	return status;
+}
+
+
+/**
+ * Condition for waking up in dvb_ca_en50221_io_read_condition
+ */
+static int dvb_ca_en50221_io_read_condition(struct dvb_ca_private *ca,
+					    int *result, int *_slot)
+{
+	int slot;
+	int slot_count = 0;
+	int idx;
+	size_t fraglen;
+	int connection_id = -1;
+	int found = 0;
+	u8 hdr[2];
+
+	slot = ca->next_read_slot;
+	while ((slot_count < ca->slot_count) && (!found)) {
+		if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_RUNNING)
+			goto nextslot;
+
+		if (ca->slot_info[slot].rx_buffer.data == NULL) {
+			return 0;
+		}
+
+		idx = dvb_ringbuffer_pkt_next(&ca->slot_info[slot].rx_buffer, -1, &fraglen);
+		while (idx != -1) {
+			dvb_ringbuffer_pkt_read(&ca->slot_info[slot].rx_buffer, idx, 0, hdr, 2);
+			if (connection_id == -1)
+				connection_id = hdr[0];
+			if ((hdr[0] == connection_id) && ((hdr[1] & 0x80) == 0)) {
+				*_slot = slot;
+				found = 1;
+				break;
+			}
+
+			idx = dvb_ringbuffer_pkt_next(&ca->slot_info[slot].rx_buffer, idx, &fraglen);
+		}
+
+nextslot:
+		slot = (slot + 1) % ca->slot_count;
+		slot_count++;
+	}
+
+	ca->next_read_slot = slot;
+	return found;
+}
+
+
+/**
+ * Implementation of read() syscall.
+ *
+ * @param file File structure.
+ * @param buf Destination buffer.
+ * @param count Size of destination buffer.
+ * @param ppos Position in file (ignored).
+ *
+ * @return Number of bytes read, or <0 on error.
+ */
+static ssize_t dvb_ca_en50221_io_read(struct file *file, char __user * buf,
+				      size_t count, loff_t * ppos)
+{
+	struct dvb_device *dvbdev = file->private_data;
+	struct dvb_ca_private *ca = dvbdev->priv;
+	int status;
+	int result = 0;
+	u8 hdr[2];
+	int slot;
+	int connection_id = -1;
+	size_t idx, idx2;
+	int last_fragment = 0;
+	size_t fraglen;
+	int pktlen;
+	int dispose = 0;
+
+	dprintk("%s\n", __func__);
+
+	/* Outgoing packet has a 2 byte header. hdr[0] = slot_id, hdr[1] = connection_id */
+	if (count < 2)
+		return -EINVAL;
+
+	/* wait for some data */
+	if ((status = dvb_ca_en50221_io_read_condition(ca, &result, &slot)) == 0) {
+
+		/* if we're in nonblocking mode, exit immediately */
+		if (file->f_flags & O_NONBLOCK)
+			return -EWOULDBLOCK;
+
+		/* wait for some data */
+		status = wait_event_interruptible(ca->wait_queue,
+						  dvb_ca_en50221_io_read_condition
+						  (ca, &result, &slot));
+	}
+	if ((status < 0) || (result < 0)) {
+		if (result)
+			return result;
+		return status;
+	}
+
+	idx = dvb_ringbuffer_pkt_next(&ca->slot_info[slot].rx_buffer, -1, &fraglen);
+	pktlen = 2;
+	do {
+		if (idx == -1) {
+			printk("dvb_ca adapter %d: BUG: read packet ended before last_fragment encountered\n", ca->dvbdev->adapter->num);
+			status = -EIO;
+			goto exit;
+		}
+
+		dvb_ringbuffer_pkt_read(&ca->slot_info[slot].rx_buffer, idx, 0, hdr, 2);
+		if (connection_id == -1)
+			connection_id = hdr[0];
+		if (hdr[0] == connection_id) {
+			if (pktlen < count) {
+				if ((pktlen + fraglen - 2) > count) {
+					fraglen = count - pktlen;
+				} else {
+					fraglen -= 2;
+				}
+
+				if ((status = dvb_ringbuffer_pkt_read_user(&ca->slot_info[slot].rx_buffer, idx, 2,
+								      buf + pktlen, fraglen)) < 0) {
+					goto exit;
+				}
+				pktlen += fraglen;
+			}
+
+			if ((hdr[1] & 0x80) == 0)
+				last_fragment = 1;
+			dispose = 1;
+		}
+
+		idx2 = dvb_ringbuffer_pkt_next(&ca->slot_info[slot].rx_buffer, idx, &fraglen);
+		if (dispose)
+			dvb_ringbuffer_pkt_dispose(&ca->slot_info[slot].rx_buffer, idx);
+		idx = idx2;
+		dispose = 0;
+	} while (!last_fragment);
+
+	hdr[0] = slot;
+	hdr[1] = connection_id;
+	status = copy_to_user(buf, hdr, 2);
+	if (status) {
+		status = -EFAULT;
+		goto exit;
+	}
+	status = pktlen;
+
+exit:
+	return status;
+}
+
+
+/**
+ * Implementation of file open syscall.
+ *
+ * @param inode Inode concerned.
+ * @param file File concerned.
+ *
+ * @return 0 on success, <0 on failure.
+ */
+static int dvb_ca_en50221_io_open(struct inode *inode, struct file *file)
+{
+	struct dvb_device *dvbdev = file->private_data;
+	struct dvb_ca_private *ca = dvbdev->priv;
+	int err;
+	int i;
+
+	dprintk("%s\n", __func__);
+
+	if (!try_module_get(ca->pub->owner))
+		return -EIO;
+
+	err = dvb_generic_open(inode, file);
+	if (err < 0) {
+		module_put(ca->pub->owner);
+		return err;
+	}
+
+	for (i = 0; i < ca->slot_count; i++) {
+
+		if (ca->slot_info[i].slot_state == DVB_CA_SLOTSTATE_RUNNING) {
+			if (ca->slot_info[i].rx_buffer.data != NULL) {
+				/* it is safe to call this here without locks because
+				 * ca->open == 0. Data is not read in this case */
+				dvb_ringbuffer_flush(&ca->slot_info[i].rx_buffer);
+			}
+		}
+	}
+
+	ca->open = 1;
+	dvb_ca_en50221_thread_update_delay(ca);
+	dvb_ca_en50221_thread_wakeup(ca);
+
+	return 0;
+}
+
+
+/**
+ * Implementation of file close syscall.
+ *
+ * @param inode Inode concerned.
+ * @param file File concerned.
+ *
+ * @return 0 on success, <0 on failure.
+ */
+static int dvb_ca_en50221_io_release(struct inode *inode, struct file *file)
+{
+	struct dvb_device *dvbdev = file->private_data;
+	struct dvb_ca_private *ca = dvbdev->priv;
+	int err;
+
+	dprintk("%s\n", __func__);
+
+	/* mark the CA device as closed */
+	ca->open = 0;
+	dvb_ca_en50221_thread_update_delay(ca);
+
+	err = dvb_generic_release(inode, file);
+
+	module_put(ca->pub->owner);
+
+	return err;
+}
+
+
+/**
+ * Implementation of poll() syscall.
+ *
+ * @param file File concerned.
+ * @param wait poll wait table.
+ *
+ * @return Standard poll mask.
+ */
+static unsigned int dvb_ca_en50221_io_poll(struct file *file, poll_table * wait)
+{
+	struct dvb_device *dvbdev = file->private_data;
+	struct dvb_ca_private *ca = dvbdev->priv;
+	unsigned int mask = 0;
+	int slot;
+	int result = 0;
+
+	dprintk("%s\n", __func__);
+
+	if (dvb_ca_en50221_io_read_condition(ca, &result, &slot) == 1) {
+		mask |= POLLIN;
+	}
+
+	/* if there is something, return now */
+	if (mask)
+		return mask;
+
+	/* wait for something to happen */
+	poll_wait(file, &ca->wait_queue, wait);
+
+	if (dvb_ca_en50221_io_read_condition(ca, &result, &slot) == 1) {
+		mask |= POLLIN;
+	}
+
+	return mask;
+}
+EXPORT_SYMBOL(dvb_ca_en50221_init);
+
+
+static const struct file_operations dvb_ca_fops = {
+	.owner = THIS_MODULE,
+	.read = dvb_ca_en50221_io_read,
+	.write = dvb_ca_en50221_io_write,
+	.unlocked_ioctl = dvb_ca_en50221_io_ioctl,
+	.open = dvb_ca_en50221_io_open,
+	.release = dvb_ca_en50221_io_release,
+	.poll = dvb_ca_en50221_io_poll,
+	.llseek = noop_llseek,
+};
+
+static struct dvb_device dvbdev_ca = {
+	.priv = NULL,
+	.users = 1,
+	.readers = 1,
+	.writers = 1,
+	.fops = &dvb_ca_fops,
+};
+
+
+/* ******************************************************************************** */
+/* Initialisation/shutdown functions */
+
+
+/**
+ * Initialise a new DVB CA EN50221 interface device.
+ *
+ * @param dvb_adapter DVB adapter to attach the new CA device to.
+ * @param ca The dvb_ca instance.
+ * @param flags Flags describing the CA device (DVB_CA_FLAG_*).
+ * @param slot_count Number of slots supported.
+ *
+ * @return 0 on success, nonzero on failure
+ */
+int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter,
+			struct dvb_ca_en50221 *pubca, int flags, int slot_count)
+{
+	int ret;
+	struct dvb_ca_private *ca = NULL;
+	int i;
+
+	dprintk("%s\n", __func__);
+
+	if (slot_count < 1)
+		return -EINVAL;
+
+	/* initialise the system data */
+	if ((ca = kzalloc(sizeof(struct dvb_ca_private), GFP_KERNEL)) == NULL) {
+		ret = -ENOMEM;
+		goto error;
+	}
+	ca->pub = pubca;
+	ca->flags = flags;
+	ca->slot_count = slot_count;
+	if ((ca->slot_info = kcalloc(slot_count, sizeof(struct dvb_ca_slot), GFP_KERNEL)) == NULL) {
+		ret = -ENOMEM;
+		goto error;
+	}
+	init_waitqueue_head(&ca->wait_queue);
+	ca->open = 0;
+	ca->wakeup = 0;
+	ca->next_read_slot = 0;
+	pubca->private = ca;
+
+	/* register the DVB device */
+	ret = dvb_register_device(dvb_adapter, &ca->dvbdev, &dvbdev_ca, ca, DVB_DEVICE_CA);
+	if (ret)
+		goto error;
+
+	/* now initialise each slot */
+	for (i = 0; i < slot_count; i++) {
+		memset(&ca->slot_info[i], 0, sizeof(struct dvb_ca_slot));
+		ca->slot_info[i].slot_state = DVB_CA_SLOTSTATE_NONE;
+		atomic_set(&ca->slot_info[i].camchange_count, 0);
+		ca->slot_info[i].camchange_type = DVB_CA_EN50221_CAMCHANGE_REMOVED;
+		mutex_init(&ca->slot_info[i].slot_lock);
+	}
+
+	if (signal_pending(current)) {
+		ret = -EINTR;
+		goto error;
+	}
+	mb();
+
+	/* create a kthread for monitoring this CA device */
+	ca->thread = kthread_run(dvb_ca_en50221_thread, ca, "kdvb-ca-%i:%i",
+				 ca->dvbdev->adapter->num, ca->dvbdev->id);
+	if (IS_ERR(ca->thread)) {
+		ret = PTR_ERR(ca->thread);
+		printk("dvb_ca_init: failed to start kernel_thread (%d)\n",
+			ret);
+		goto error;
+	}
+	return 0;
+
+error:
+	if (ca != NULL) {
+		if (ca->dvbdev != NULL)
+			dvb_unregister_device(ca->dvbdev);
+		kfree(ca->slot_info);
+		kfree(ca);
+	}
+	pubca->private = NULL;
+	return ret;
+}
+EXPORT_SYMBOL(dvb_ca_en50221_release);
+
+
+
+/**
+ * Release a DVB CA EN50221 interface device.
+ *
+ * @param ca_dev The dvb_device_t instance for the CA device.
+ * @param ca The associated dvb_ca instance.
+ */
+void dvb_ca_en50221_release(struct dvb_ca_en50221 *pubca)
+{
+	struct dvb_ca_private *ca = pubca->private;
+	int i;
+
+	dprintk("%s\n", __func__);
+
+	/* shutdown the thread if there was one */
+	kthread_stop(ca->thread);
+
+	for (i = 0; i < ca->slot_count; i++) {
+		dvb_ca_en50221_slot_shutdown(ca, i);
+		vfree(ca->slot_info[i].rx_buffer.data);
+	}
+	kfree(ca->slot_info);
+	dvb_unregister_device(ca->dvbdev);
+	kfree(ca);
+	pubca->private = NULL;
+}
diff --git a/drivers/media/dvb-core/dvb_ca_en50221.h b/drivers/media/dvb-core/dvb_ca_en50221.h
new file mode 100644
index 0000000..7df2e14
--- /dev/null
+++ b/drivers/media/dvb-core/dvb_ca_en50221.h
@@ -0,0 +1,136 @@
+/*
+ * dvb_ca.h: generic DVB functions for EN50221 CA interfaces
+ *
+ * Copyright (C) 2004 Andrew de Quincey
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public 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 _DVB_CA_EN50221_H_
+#define _DVB_CA_EN50221_H_
+
+#include <linux/list.h>
+#include <linux/dvb/ca.h>
+
+#include "dvbdev.h"
+
+#define DVB_CA_EN50221_POLL_CAM_PRESENT	1
+#define DVB_CA_EN50221_POLL_CAM_CHANGED	2
+#define DVB_CA_EN50221_POLL_CAM_READY		4
+
+#define DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE	1
+#define DVB_CA_EN50221_FLAG_IRQ_FR		2
+#define DVB_CA_EN50221_FLAG_IRQ_DA		4
+
+#define DVB_CA_EN50221_CAMCHANGE_REMOVED		0
+#define DVB_CA_EN50221_CAMCHANGE_INSERTED		1
+
+
+
+/* Structure describing a CA interface */
+struct dvb_ca_en50221 {
+
+	/* the module owning this structure */
+	struct module* owner;
+
+	/* NOTE: the read_*, write_* and poll_slot_status functions will be
+	 * called for different slots concurrently and need to use locks where
+	 * and if appropriate. There will be no concurrent access to one slot.
+	 */
+
+	/* functions for accessing attribute memory on the CAM */
+	int (*read_attribute_mem)(struct dvb_ca_en50221* ca, int slot, int address);
+	int (*write_attribute_mem)(struct dvb_ca_en50221* ca, int slot, int address, u8 value);
+
+	/* functions for accessing the control interface on the CAM */
+	int (*read_cam_control)(struct dvb_ca_en50221* ca, int slot, u8 address);
+	int (*write_cam_control)(struct dvb_ca_en50221* ca, int slot, u8 address, u8 value);
+
+	/* Functions for controlling slots */
+	int (*slot_reset)(struct dvb_ca_en50221* ca, int slot);
+	int (*slot_shutdown)(struct dvb_ca_en50221* ca, int slot);
+	int (*slot_ts_enable)(struct dvb_ca_en50221* ca, int slot);
+
+	/*
+	* Poll slot status.
+	* Only necessary if DVB_CA_FLAG_EN50221_IRQ_CAMCHANGE is not set
+	*/
+	int (*poll_slot_status)(struct dvb_ca_en50221* ca, int slot, int open);
+
+	/* private data, used by caller */
+	void* data;
+
+	/* Opaque data used by the dvb_ca core. Do not modify! */
+	void* private;
+};
+
+
+
+
+/* ******************************************************************************** */
+/* Functions for reporting IRQ events */
+
+/**
+ * A CAMCHANGE IRQ has occurred.
+ *
+ * @param ca CA instance.
+ * @param slot Slot concerned.
+ * @param change_type One of the DVB_CA_CAMCHANGE_* values
+ */
+void dvb_ca_en50221_camchange_irq(struct dvb_ca_en50221* pubca, int slot, int change_type);
+
+/**
+ * A CAMREADY IRQ has occurred.
+ *
+ * @param ca CA instance.
+ * @param slot Slot concerned.
+ */
+void dvb_ca_en50221_camready_irq(struct dvb_ca_en50221* pubca, int slot);
+
+/**
+ * An FR or a DA IRQ has occurred.
+ *
+ * @param ca CA instance.
+ * @param slot Slot concerned.
+ */
+void dvb_ca_en50221_frda_irq(struct dvb_ca_en50221* ca, int slot);
+
+
+
+/* ******************************************************************************** */
+/* Initialisation/shutdown functions */
+
+/**
+ * Initialise a new DVB CA device.
+ *
+ * @param dvb_adapter DVB adapter to attach the new CA device to.
+ * @param ca The dvb_ca instance.
+ * @param flags Flags describing the CA device (DVB_CA_EN50221_FLAG_*).
+ * @param slot_count Number of slots supported.
+ *
+ * @return 0 on success, nonzero on failure
+ */
+extern int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter, struct dvb_ca_en50221* ca, int flags, int slot_count);
+
+/**
+ * Release a DVB CA device.
+ *
+ * @param ca The associated dvb_ca instance.
+ */
+extern void dvb_ca_en50221_release(struct dvb_ca_en50221* ca);
+
+
+
+#endif
diff --git a/drivers/media/dvb-core/dvb_demux.c b/drivers/media/dvb-core/dvb_demux.c
new file mode 100644
index 0000000..d319717
--- /dev/null
+++ b/drivers/media/dvb-core/dvb_demux.c
@@ -0,0 +1,1318 @@
+/*
+ * dvb_demux.c - DVB kernel demux API
+ *
+ * Copyright (C) 2000-2001 Ralph  Metzler <ralph@convergence.de>
+ *		       & Marcus Metzler <marcus@convergence.de>
+ *			 for convergence integrated media GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public 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/sched.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/module.h>
+#include <linux/poll.h>
+#include <linux/string.h>
+#include <linux/crc32.h>
+#include <asm/uaccess.h>
+#include <asm/div64.h>
+
+#include "dvb_demux.h"
+
+#define NOBUFS
+/*
+** #define DVB_DEMUX_SECTION_LOSS_LOG to monitor payload loss in the syslog
+*/
+// #define DVB_DEMUX_SECTION_LOSS_LOG
+
+static int dvb_demux_tscheck;
+module_param(dvb_demux_tscheck, int, 0644);
+MODULE_PARM_DESC(dvb_demux_tscheck,
+		"enable transport stream continuity and TEI check");
+
+static int dvb_demux_speedcheck;
+module_param(dvb_demux_speedcheck, int, 0644);
+MODULE_PARM_DESC(dvb_demux_speedcheck,
+		"enable transport stream speed check");
+
+static int dvb_demux_feed_err_pkts = 1;
+module_param(dvb_demux_feed_err_pkts, int, 0644);
+MODULE_PARM_DESC(dvb_demux_feed_err_pkts,
+		 "when set to 0, drop packets with the TEI bit set (1 by default)");
+
+#define dprintk_tscheck(x...) do {                              \
+		if (dvb_demux_tscheck && printk_ratelimit())    \
+			printk(x);                              \
+	} while (0)
+
+/******************************************************************************
+ * static inlined helper functions
+ ******************************************************************************/
+
+static inline u16 section_length(const u8 *buf)
+{
+	return 3 + ((buf[1] & 0x0f) << 8) + buf[2];
+}
+
+static inline u16 ts_pid(const u8 *buf)
+{
+	return ((buf[1] & 0x1f) << 8) + buf[2];
+}
+
+static inline u8 payload(const u8 *tsp)
+{
+	if (!(tsp[3] & 0x10))	// no payload?
+		return 0;
+
+	if (tsp[3] & 0x20) {	// adaptation field?
+		if (tsp[4] > 183)	// corrupted data?
+			return 0;
+		else
+			return 184 - 1 - tsp[4];
+	}
+
+	return 184;
+}
+
+static u32 dvb_dmx_crc32(struct dvb_demux_feed *f, const u8 *src, size_t len)
+{
+	return (f->feed.sec.crc_val = crc32_be(f->feed.sec.crc_val, src, len));
+}
+
+static void dvb_dmx_memcopy(struct dvb_demux_feed *f, u8 *d, const u8 *s,
+			    size_t len)
+{
+	memcpy(d, s, len);
+}
+
+/******************************************************************************
+ * Software filter functions
+ ******************************************************************************/
+
+static inline int dvb_dmx_swfilter_payload(struct dvb_demux_feed *feed,
+					   const u8 *buf)
+{
+	int count = payload(buf);
+	int p;
+	//int ccok;
+	//u8 cc;
+
+	if (count == 0)
+		return -1;
+
+	p = 188 - count;
+
+	/*
+	cc = buf[3] & 0x0f;
+	ccok = ((feed->cc + 1) & 0x0f) == cc;
+	feed->cc = cc;
+	if (!ccok)
+		printk("missed packet!\n");
+	*/
+
+	if (buf[1] & 0x40)	// PUSI ?
+		feed->peslen = 0xfffa;
+
+	feed->peslen += count;
+
+	return feed->cb.ts(&buf[p], count, NULL, 0, &feed->feed.ts, DMX_OK);
+}
+
+static int dvb_dmx_swfilter_sectionfilter(struct dvb_demux_feed *feed,
+					  struct dvb_demux_filter *f)
+{
+	u8 neq = 0;
+	int i;
+
+	for (i = 0; i < DVB_DEMUX_MASK_MAX; i++) {
+		u8 xor = f->filter.filter_value[i] ^ feed->feed.sec.secbuf[i];
+
+		if (f->maskandmode[i] & xor)
+			return 0;
+
+		neq |= f->maskandnotmode[i] & xor;
+	}
+
+	if (f->doneq && !neq)
+		return 0;
+
+	return feed->cb.sec(feed->feed.sec.secbuf, feed->feed.sec.seclen,
+			    NULL, 0, &f->filter, DMX_OK);
+}
+
+static inline int dvb_dmx_swfilter_section_feed(struct dvb_demux_feed *feed)
+{
+	struct dvb_demux *demux = feed->demux;
+	struct dvb_demux_filter *f = feed->filter;
+	struct dmx_section_feed *sec = &feed->feed.sec;
+	int section_syntax_indicator;
+
+	if (!sec->is_filtering)
+		return 0;
+
+	if (!f)
+		return 0;
+
+	if (sec->check_crc) {
+		section_syntax_indicator = ((sec->secbuf[1] & 0x80) != 0);
+		if (section_syntax_indicator &&
+		    demux->check_crc32(feed, sec->secbuf, sec->seclen))
+			return -1;
+	}
+
+	do {
+		if (dvb_dmx_swfilter_sectionfilter(feed, f) < 0)
+			return -1;
+	} while ((f = f->next) && sec->is_filtering);
+
+	sec->seclen = 0;
+
+	return 0;
+}
+
+static void dvb_dmx_swfilter_section_new(struct dvb_demux_feed *feed)
+{
+	struct dmx_section_feed *sec = &feed->feed.sec;
+
+#ifdef DVB_DEMUX_SECTION_LOSS_LOG
+	if (sec->secbufp < sec->tsfeedp) {
+		int i, n = sec->tsfeedp - sec->secbufp;
+
+		/*
+		 * Section padding is done with 0xff bytes entirely.
+		 * Due to speed reasons, we won't check all of them
+		 * but just first and last.
+		 */
+		if (sec->secbuf[0] != 0xff || sec->secbuf[n - 1] != 0xff) {
+			printk("dvb_demux.c section ts padding loss: %d/%d\n",
+			       n, sec->tsfeedp);
+			printk("dvb_demux.c pad data:");
+			for (i = 0; i < n; i++)
+				printk(" %02x", sec->secbuf[i]);
+			printk("\n");
+		}
+	}
+#endif
+
+	sec->tsfeedp = sec->secbufp = sec->seclen = 0;
+	sec->secbuf = sec->secbuf_base;
+}
+
+/*
+ * Losless Section Demux 1.4.1 by Emard
+ * Valsecchi Patrick:
+ *  - middle of section A  (no PUSI)
+ *  - end of section A and start of section B
+ *    (with PUSI pointing to the start of the second section)
+ *
+ *  In this case, without feed->pusi_seen you'll receive a garbage section
+ *  consisting of the end of section A. Basically because tsfeedp
+ *  is incemented and the use=0 condition is not raised
+ *  when the second packet arrives.
+ *
+ * Fix:
+ * when demux is started, let feed->pusi_seen = 0 to
+ * prevent initial feeding of garbage from the end of
+ * previous section. When you for the first time see PUSI=1
+ * then set feed->pusi_seen = 1
+ */
+static int dvb_dmx_swfilter_section_copy_dump(struct dvb_demux_feed *feed,
+					      const u8 *buf, u8 len)
+{
+	struct dvb_demux *demux = feed->demux;
+	struct dmx_section_feed *sec = &feed->feed.sec;
+	u16 limit, seclen, n;
+
+	if (sec->tsfeedp >= DMX_MAX_SECFEED_SIZE)
+		return 0;
+
+	if (sec->tsfeedp + len > DMX_MAX_SECFEED_SIZE) {
+#ifdef DVB_DEMUX_SECTION_LOSS_LOG
+		printk("dvb_demux.c section buffer full loss: %d/%d\n",
+		       sec->tsfeedp + len - DMX_MAX_SECFEED_SIZE,
+		       DMX_MAX_SECFEED_SIZE);
+#endif
+		len = DMX_MAX_SECFEED_SIZE - sec->tsfeedp;
+	}
+
+	if (len <= 0)
+		return 0;
+
+	demux->memcopy(feed, sec->secbuf_base + sec->tsfeedp, buf, len);
+	sec->tsfeedp += len;
+
+	/*
+	 * Dump all the sections we can find in the data (Emard)
+	 */
+	limit = sec->tsfeedp;
+	if (limit > DMX_MAX_SECFEED_SIZE)
+		return -1;	/* internal error should never happen */
+
+	/* to be sure always set secbuf */
+	sec->secbuf = sec->secbuf_base + sec->secbufp;
+
+	for (n = 0; sec->secbufp + 2 < limit; n++) {
+		seclen = section_length(sec->secbuf);
+		if (seclen <= 0 || seclen > DMX_MAX_SECTION_SIZE
+		    || seclen + sec->secbufp > limit)
+			return 0;
+		sec->seclen = seclen;
+		sec->crc_val = ~0;
+		/* dump [secbuf .. secbuf+seclen) */
+		if (feed->pusi_seen)
+			dvb_dmx_swfilter_section_feed(feed);
+#ifdef DVB_DEMUX_SECTION_LOSS_LOG
+		else
+			printk("dvb_demux.c pusi not seen, discarding section data\n");
+#endif
+		sec->secbufp += seclen;	/* secbufp and secbuf moving together is */
+		sec->secbuf += seclen;	/* redundant but saves pointer arithmetic */
+	}
+
+	return 0;
+}
+
+static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed,
+					   const u8 *buf)
+{
+	u8 p, count;
+	int ccok, dc_i = 0;
+	u8 cc;
+
+	count = payload(buf);
+
+	if (count == 0)		/* count == 0 if no payload or out of range */
+		return -1;
+
+	p = 188 - count;	/* payload start */
+
+	cc = buf[3] & 0x0f;
+	ccok = ((feed->cc + 1) & 0x0f) == cc;
+	feed->cc = cc;
+
+	if (buf[3] & 0x20) {
+		/* adaption field present, check for discontinuity_indicator */
+		if ((buf[4] > 0) && (buf[5] & 0x80))
+			dc_i = 1;
+	}
+
+	if (!ccok || dc_i) {
+#ifdef DVB_DEMUX_SECTION_LOSS_LOG
+		printk("dvb_demux.c discontinuity detected %d bytes lost\n",
+		       count);
+		/*
+		 * those bytes under sume circumstances will again be reported
+		 * in the following dvb_dmx_swfilter_section_new
+		 */
+#endif
+		/*
+		 * Discontinuity detected. Reset pusi_seen = 0 to
+		 * stop feeding of suspicious data until next PUSI=1 arrives
+		 */
+		feed->pusi_seen = 0;
+		dvb_dmx_swfilter_section_new(feed);
+	}
+
+	if (buf[1] & 0x40) {
+		/* PUSI=1 (is set), section boundary is here */
+		if (count > 1 && buf[p] < count) {
+			const u8 *before = &buf[p + 1];
+			u8 before_len = buf[p];
+			const u8 *after = &before[before_len];
+			u8 after_len = count - 1 - before_len;
+
+			dvb_dmx_swfilter_section_copy_dump(feed, before,
+							   before_len);
+			/* before start of new section, set pusi_seen = 1 */
+			feed->pusi_seen = 1;
+			dvb_dmx_swfilter_section_new(feed);
+			dvb_dmx_swfilter_section_copy_dump(feed, after,
+							   after_len);
+		}
+#ifdef DVB_DEMUX_SECTION_LOSS_LOG
+		else if (count > 0)
+			printk("dvb_demux.c PUSI=1 but %d bytes lost\n", count);
+#endif
+	} else {
+		/* PUSI=0 (is not set), no section boundary */
+		dvb_dmx_swfilter_section_copy_dump(feed, &buf[p], count);
+	}
+
+	return 0;
+}
+
+static inline void dvb_dmx_swfilter_packet_type(struct dvb_demux_feed *feed,
+						const u8 *buf)
+{
+	switch (feed->type) {
+	case DMX_TYPE_TS:
+		if (!feed->feed.ts.is_filtering)
+			break;
+		if (feed->ts_type & TS_PACKET) {
+			if (feed->ts_type & TS_PAYLOAD_ONLY)
+				dvb_dmx_swfilter_payload(feed, buf);
+			else
+				feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts,
+					    DMX_OK);
+		}
+		if (feed->ts_type & TS_DECODER)
+			if (feed->demux->write_to_decoder)
+				feed->demux->write_to_decoder(feed, buf, 188);
+		break;
+
+	case DMX_TYPE_SEC:
+		if (!feed->feed.sec.is_filtering)
+			break;
+		if (dvb_dmx_swfilter_section_packet(feed, buf) < 0)
+			feed->feed.sec.seclen = feed->feed.sec.secbufp = 0;
+		break;
+
+	default:
+		break;
+	}
+}
+
+#define DVR_FEED(f)							\
+	(((f)->type == DMX_TYPE_TS) &&					\
+	((f)->feed.ts.is_filtering) &&					\
+	(((f)->ts_type & (TS_PACKET | TS_DEMUX)) == TS_PACKET))
+
+static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf)
+{
+	struct dvb_demux_feed *feed;
+	u16 pid = ts_pid(buf);
+	int dvr_done = 0;
+
+	if (dvb_demux_speedcheck) {
+		struct timespec cur_time, delta_time;
+		u64 speed_bytes, speed_timedelta;
+
+		demux->speed_pkts_cnt++;
+
+		/* show speed every SPEED_PKTS_INTERVAL packets */
+		if (!(demux->speed_pkts_cnt % SPEED_PKTS_INTERVAL)) {
+			cur_time = current_kernel_time();
+
+			if (demux->speed_last_time.tv_sec != 0 &&
+					demux->speed_last_time.tv_nsec != 0) {
+				delta_time = timespec_sub(cur_time,
+						demux->speed_last_time);
+				speed_bytes = (u64)demux->speed_pkts_cnt
+					* 188 * 8;
+				/* convert to 1024 basis */
+				speed_bytes = 1000 * div64_u64(speed_bytes,
+						1024);
+				speed_timedelta =
+					(u64)timespec_to_ns(&delta_time);
+				speed_timedelta = div64_u64(speed_timedelta,
+						1000000); /* nsec -> usec */
+				printk(KERN_INFO "TS speed %llu Kbits/sec \n",
+						div64_u64(speed_bytes,
+							speed_timedelta));
+			}
+
+			demux->speed_last_time = cur_time;
+			demux->speed_pkts_cnt = 0;
+		}
+	}
+
+	if (buf[1] & 0x80) {
+		dprintk_tscheck("TEI detected. "
+				"PID=0x%x data1=0x%x\n",
+				pid, buf[1]);
+		/* data in this packet cant be trusted - drop it unless
+		 * module option dvb_demux_feed_err_pkts is set */
+		if (!dvb_demux_feed_err_pkts)
+			return;
+	} else /* if TEI bit is set, pid may be wrong- skip pkt counter */
+	if (demux->cnt_storage && dvb_demux_tscheck) {
+		/* check pkt counter */
+		if (pid < MAX_PID) {
+			if ((buf[3] & 0xf) != demux->cnt_storage[pid])
+				dprintk_tscheck("TS packet counter mismatch. "
+						"PID=0x%x expected 0x%x "
+						"got 0x%x\n",
+						pid, demux->cnt_storage[pid],
+						buf[3] & 0xf);
+
+			demux->cnt_storage[pid] = ((buf[3] & 0xf) + 1)&0xf;
+		}
+		/* end check */
+	}
+
+	list_for_each_entry(feed, &demux->feed_list, list_head) {
+		if ((feed->pid != pid) && (feed->pid != 0x2000))
+			continue;
+
+		/* copy each packet only once to the dvr device, even
+		 * if a PID is in multiple filters (e.g. video + PCR) */
+		if ((DVR_FEED(feed)) && (dvr_done++))
+			continue;
+
+		if (feed->pid == pid)
+			dvb_dmx_swfilter_packet_type(feed, buf);
+		else if (feed->pid == 0x2000)
+			feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts, DMX_OK);
+	}
+}
+
+void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf,
+			      size_t count)
+{
+	spin_lock(&demux->lock);
+
+	while (count--) {
+		if (buf[0] == 0x47)
+			dvb_dmx_swfilter_packet(demux, buf);
+		buf += 188;
+	}
+
+	spin_unlock(&demux->lock);
+}
+
+EXPORT_SYMBOL(dvb_dmx_swfilter_packets);
+
+static inline int find_next_packet(const u8 *buf, int pos, size_t count,
+				   const int pktsize)
+{
+	int start = pos, lost;
+
+	while (pos < count) {
+		if (buf[pos] == 0x47 ||
+		    (pktsize == 204 && buf[pos] == 0xB8))
+			break;
+		pos++;
+	}
+
+	lost = pos - start;
+	if (lost) {
+		/* This garbage is part of a valid packet? */
+		int backtrack = pos - pktsize;
+		if (backtrack >= 0 && (buf[backtrack] == 0x47 ||
+		    (pktsize == 204 && buf[backtrack] == 0xB8)))
+			return backtrack;
+	}
+
+	return pos;
+}
+
+/* Filter all pktsize= 188 or 204 sized packets and skip garbage. */
+static inline void _dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf,
+		size_t count, const int pktsize)
+{
+	int p = 0, i, j;
+	const u8 *q;
+
+	spin_lock(&demux->lock);
+
+	if (demux->tsbufp) { /* tsbuf[0] is now 0x47. */
+		i = demux->tsbufp;
+		j = pktsize - i;
+		if (count < j) {
+			memcpy(&demux->tsbuf[i], buf, count);
+			demux->tsbufp += count;
+			goto bailout;
+		}
+		memcpy(&demux->tsbuf[i], buf, j);
+		if (demux->tsbuf[0] == 0x47) /* double check */
+			dvb_dmx_swfilter_packet(demux, demux->tsbuf);
+		demux->tsbufp = 0;
+		p += j;
+	}
+
+	while (1) {
+		p = find_next_packet(buf, p, count, pktsize);
+		if (p >= count)
+			break;
+		if (count - p < pktsize)
+			break;
+
+		q = &buf[p];
+
+		if (pktsize == 204 && (*q == 0xB8)) {
+			memcpy(demux->tsbuf, q, 188);
+			demux->tsbuf[0] = 0x47;
+			q = demux->tsbuf;
+		}
+		dvb_dmx_swfilter_packet(demux, q);
+		p += pktsize;
+	}
+
+	i = count - p;
+	if (i) {
+		memcpy(demux->tsbuf, &buf[p], i);
+		demux->tsbufp = i;
+		if (pktsize == 204 && demux->tsbuf[0] == 0xB8)
+			demux->tsbuf[0] = 0x47;
+	}
+
+bailout:
+	spin_unlock(&demux->lock);
+}
+
+void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count)
+{
+	_dvb_dmx_swfilter(demux, buf, count, 188);
+}
+EXPORT_SYMBOL(dvb_dmx_swfilter);
+
+void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count)
+{
+	_dvb_dmx_swfilter(demux, buf, count, 204);
+}
+EXPORT_SYMBOL(dvb_dmx_swfilter_204);
+
+void dvb_dmx_swfilter_raw(struct dvb_demux *demux, const u8 *buf, size_t count)
+{
+	spin_lock(&demux->lock);
+
+	demux->feed->cb.ts(buf, count, NULL, 0, &demux->feed->feed.ts, DMX_OK);
+
+	spin_unlock(&demux->lock);
+}
+EXPORT_SYMBOL(dvb_dmx_swfilter_raw);
+
+static struct dvb_demux_filter *dvb_dmx_filter_alloc(struct dvb_demux *demux)
+{
+	int i;
+
+	for (i = 0; i < demux->filternum; i++)
+		if (demux->filter[i].state == DMX_STATE_FREE)
+			break;
+
+	if (i == demux->filternum)
+		return NULL;
+
+	demux->filter[i].state = DMX_STATE_ALLOCATED;
+
+	return &demux->filter[i];
+}
+
+static struct dvb_demux_feed *dvb_dmx_feed_alloc(struct dvb_demux *demux)
+{
+	int i;
+
+	for (i = 0; i < demux->feednum; i++)
+		if (demux->feed[i].state == DMX_STATE_FREE)
+			break;
+
+	if (i == demux->feednum)
+		return NULL;
+
+	demux->feed[i].state = DMX_STATE_ALLOCATED;
+
+	return &demux->feed[i];
+}
+
+static int dvb_demux_feed_find(struct dvb_demux_feed *feed)
+{
+	struct dvb_demux_feed *entry;
+
+	list_for_each_entry(entry, &feed->demux->feed_list, list_head)
+		if (entry == feed)
+			return 1;
+
+	return 0;
+}
+
+static void dvb_demux_feed_add(struct dvb_demux_feed *feed)
+{
+	spin_lock_irq(&feed->demux->lock);
+	if (dvb_demux_feed_find(feed)) {
+		printk(KERN_ERR "%s: feed already in list (type=%x state=%x pid=%x)\n",
+		       __func__, feed->type, feed->state, feed->pid);
+		goto out;
+	}
+
+	list_add(&feed->list_head, &feed->demux->feed_list);
+out:
+	spin_unlock_irq(&feed->demux->lock);
+}
+
+static void dvb_demux_feed_del(struct dvb_demux_feed *feed)
+{
+	spin_lock_irq(&feed->demux->lock);
+	if (!(dvb_demux_feed_find(feed))) {
+		printk(KERN_ERR "%s: feed not in list (type=%x state=%x pid=%x)\n",
+		       __func__, feed->type, feed->state, feed->pid);
+		goto out;
+	}
+
+	list_del(&feed->list_head);
+out:
+	spin_unlock_irq(&feed->demux->lock);
+}
+
+static int dmx_ts_feed_set(struct dmx_ts_feed *ts_feed, u16 pid, int ts_type,
+			   enum dmx_ts_pes pes_type,
+			   size_t circular_buffer_size, struct timespec timeout)
+{
+	struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed;
+	struct dvb_demux *demux = feed->demux;
+
+	if (pid > DMX_MAX_PID)
+		return -EINVAL;
+
+	if (mutex_lock_interruptible(&demux->mutex))
+		return -ERESTARTSYS;
+
+	if (ts_type & TS_DECODER) {
+		if (pes_type >= DMX_TS_PES_OTHER) {
+			mutex_unlock(&demux->mutex);
+			return -EINVAL;
+		}
+
+		if (demux->pesfilter[pes_type] &&
+		    demux->pesfilter[pes_type] != feed) {
+			mutex_unlock(&demux->mutex);
+			return -EINVAL;
+		}
+
+		demux->pesfilter[pes_type] = feed;
+		demux->pids[pes_type] = pid;
+	}
+
+	dvb_demux_feed_add(feed);
+
+	feed->pid = pid;
+	feed->buffer_size = circular_buffer_size;
+	feed->timeout = timeout;
+	feed->ts_type = ts_type;
+	feed->pes_type = pes_type;
+
+	if (feed->buffer_size) {
+#ifdef NOBUFS
+		feed->buffer = NULL;
+#else
+		feed->buffer = vmalloc(feed->buffer_size);
+		if (!feed->buffer) {
+			mutex_unlock(&demux->mutex);
+			return -ENOMEM;
+		}
+#endif
+	}
+
+	feed->state = DMX_STATE_READY;
+	mutex_unlock(&demux->mutex);
+
+	return 0;
+}
+
+static int dmx_ts_feed_start_filtering(struct dmx_ts_feed *ts_feed)
+{
+	struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed;
+	struct dvb_demux *demux = feed->demux;
+	int ret;
+
+	if (mutex_lock_interruptible(&demux->mutex))
+		return -ERESTARTSYS;
+
+	if (feed->state != DMX_STATE_READY || feed->type != DMX_TYPE_TS) {
+		mutex_unlock(&demux->mutex);
+		return -EINVAL;
+	}
+
+	if (!demux->start_feed) {
+		mutex_unlock(&demux->mutex);
+		return -ENODEV;
+	}
+
+	if ((ret = demux->start_feed(feed)) < 0) {
+		mutex_unlock(&demux->mutex);
+		return ret;
+	}
+
+	spin_lock_irq(&demux->lock);
+	ts_feed->is_filtering = 1;
+	feed->state = DMX_STATE_GO;
+	spin_unlock_irq(&demux->lock);
+	mutex_unlock(&demux->mutex);
+
+	return 0;
+}
+
+static int dmx_ts_feed_stop_filtering(struct dmx_ts_feed *ts_feed)
+{
+	struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed;
+	struct dvb_demux *demux = feed->demux;
+	int ret;
+
+	mutex_lock(&demux->mutex);
+
+	if (feed->state < DMX_STATE_GO) {
+		mutex_unlock(&demux->mutex);
+		return -EINVAL;
+	}
+
+	if (!demux->stop_feed) {
+		mutex_unlock(&demux->mutex);
+		return -ENODEV;
+	}
+
+	ret = demux->stop_feed(feed);
+
+	spin_lock_irq(&demux->lock);
+	ts_feed->is_filtering = 0;
+	feed->state = DMX_STATE_ALLOCATED;
+	spin_unlock_irq(&demux->lock);
+	mutex_unlock(&demux->mutex);
+
+	return ret;
+}
+
+static int dvbdmx_allocate_ts_feed(struct dmx_demux *dmx,
+				   struct dmx_ts_feed **ts_feed,
+				   dmx_ts_cb callback)
+{
+	struct dvb_demux *demux = (struct dvb_demux *)dmx;
+	struct dvb_demux_feed *feed;
+
+	if (mutex_lock_interruptible(&demux->mutex))
+		return -ERESTARTSYS;
+
+	if (!(feed = dvb_dmx_feed_alloc(demux))) {
+		mutex_unlock(&demux->mutex);
+		return -EBUSY;
+	}
+
+	feed->type = DMX_TYPE_TS;
+	feed->cb.ts = callback;
+	feed->demux = demux;
+	feed->pid = 0xffff;
+	feed->peslen = 0xfffa;
+	feed->buffer = NULL;
+
+	(*ts_feed) = &feed->feed.ts;
+	(*ts_feed)->parent = dmx;
+	(*ts_feed)->priv = NULL;
+	(*ts_feed)->is_filtering = 0;
+	(*ts_feed)->start_filtering = dmx_ts_feed_start_filtering;
+	(*ts_feed)->stop_filtering = dmx_ts_feed_stop_filtering;
+	(*ts_feed)->set = dmx_ts_feed_set;
+
+	if (!(feed->filter = dvb_dmx_filter_alloc(demux))) {
+		feed->state = DMX_STATE_FREE;
+		mutex_unlock(&demux->mutex);
+		return -EBUSY;
+	}
+
+	feed->filter->type = DMX_TYPE_TS;
+	feed->filter->feed = feed;
+	feed->filter->state = DMX_STATE_READY;
+
+	mutex_unlock(&demux->mutex);
+
+	return 0;
+}
+
+static int dvbdmx_release_ts_feed(struct dmx_demux *dmx,
+				  struct dmx_ts_feed *ts_feed)
+{
+	struct dvb_demux *demux = (struct dvb_demux *)dmx;
+	struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed;
+
+	mutex_lock(&demux->mutex);
+
+	if (feed->state == DMX_STATE_FREE) {
+		mutex_unlock(&demux->mutex);
+		return -EINVAL;
+	}
+#ifndef NOBUFS
+	vfree(feed->buffer);
+	feed->buffer = NULL;
+#endif
+
+	feed->state = DMX_STATE_FREE;
+	feed->filter->state = DMX_STATE_FREE;
+
+	dvb_demux_feed_del(feed);
+
+	feed->pid = 0xffff;
+
+	if (feed->ts_type & TS_DECODER && feed->pes_type < DMX_TS_PES_OTHER)
+		demux->pesfilter[feed->pes_type] = NULL;
+
+	mutex_unlock(&demux->mutex);
+	return 0;
+}
+
+/******************************************************************************
+ * dmx_section_feed API calls
+ ******************************************************************************/
+
+static int dmx_section_feed_allocate_filter(struct dmx_section_feed *feed,
+					    struct dmx_section_filter **filter)
+{
+	struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed;
+	struct dvb_demux *dvbdemux = dvbdmxfeed->demux;
+	struct dvb_demux_filter *dvbdmxfilter;
+
+	if (mutex_lock_interruptible(&dvbdemux->mutex))
+		return -ERESTARTSYS;
+
+	dvbdmxfilter = dvb_dmx_filter_alloc(dvbdemux);
+	if (!dvbdmxfilter) {
+		mutex_unlock(&dvbdemux->mutex);
+		return -EBUSY;
+	}
+
+	spin_lock_irq(&dvbdemux->lock);
+	*filter = &dvbdmxfilter->filter;
+	(*filter)->parent = feed;
+	(*filter)->priv = NULL;
+	dvbdmxfilter->feed = dvbdmxfeed;
+	dvbdmxfilter->type = DMX_TYPE_SEC;
+	dvbdmxfilter->state = DMX_STATE_READY;
+	dvbdmxfilter->next = dvbdmxfeed->filter;
+	dvbdmxfeed->filter = dvbdmxfilter;
+	spin_unlock_irq(&dvbdemux->lock);
+
+	mutex_unlock(&dvbdemux->mutex);
+	return 0;
+}
+
+static int dmx_section_feed_set(struct dmx_section_feed *feed,
+				u16 pid, size_t circular_buffer_size,
+				int check_crc)
+{
+	struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed;
+	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
+
+	if (pid > 0x1fff)
+		return -EINVAL;
+
+	if (mutex_lock_interruptible(&dvbdmx->mutex))
+		return -ERESTARTSYS;
+
+	dvb_demux_feed_add(dvbdmxfeed);
+
+	dvbdmxfeed->pid = pid;
+	dvbdmxfeed->buffer_size = circular_buffer_size;
+	dvbdmxfeed->feed.sec.check_crc = check_crc;
+
+#ifdef NOBUFS
+	dvbdmxfeed->buffer = NULL;
+#else
+	dvbdmxfeed->buffer = vmalloc(dvbdmxfeed->buffer_size);
+	if (!dvbdmxfeed->buffer) {
+		mutex_unlock(&dvbdmx->mutex);
+		return -ENOMEM;
+	}
+#endif
+
+	dvbdmxfeed->state = DMX_STATE_READY;
+	mutex_unlock(&dvbdmx->mutex);
+	return 0;
+}
+
+static void prepare_secfilters(struct dvb_demux_feed *dvbdmxfeed)
+{
+	int i;
+	struct dvb_demux_filter *f;
+	struct dmx_section_filter *sf;
+	u8 mask, mode, doneq;
+
+	if (!(f = dvbdmxfeed->filter))
+		return;
+	do {
+		sf = &f->filter;
+		doneq = 0;
+		for (i = 0; i < DVB_DEMUX_MASK_MAX; i++) {
+			mode = sf->filter_mode[i];
+			mask = sf->filter_mask[i];
+			f->maskandmode[i] = mask & mode;
+			doneq |= f->maskandnotmode[i] = mask & ~mode;
+		}
+		f->doneq = doneq ? 1 : 0;
+	} while ((f = f->next));
+}
+
+static int dmx_section_feed_start_filtering(struct dmx_section_feed *feed)
+{
+	struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed;
+	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
+	int ret;
+
+	if (mutex_lock_interruptible(&dvbdmx->mutex))
+		return -ERESTARTSYS;
+
+	if (feed->is_filtering) {
+		mutex_unlock(&dvbdmx->mutex);
+		return -EBUSY;
+	}
+
+	if (!dvbdmxfeed->filter) {
+		mutex_unlock(&dvbdmx->mutex);
+		return -EINVAL;
+	}
+
+	dvbdmxfeed->feed.sec.tsfeedp = 0;
+	dvbdmxfeed->feed.sec.secbuf = dvbdmxfeed->feed.sec.secbuf_base;
+	dvbdmxfeed->feed.sec.secbufp = 0;
+	dvbdmxfeed->feed.sec.seclen = 0;
+
+	if (!dvbdmx->start_feed) {
+		mutex_unlock(&dvbdmx->mutex);
+		return -ENODEV;
+	}
+
+	prepare_secfilters(dvbdmxfeed);
+
+	if ((ret = dvbdmx->start_feed(dvbdmxfeed)) < 0) {
+		mutex_unlock(&dvbdmx->mutex);
+		return ret;
+	}
+
+	spin_lock_irq(&dvbdmx->lock);
+	feed->is_filtering = 1;
+	dvbdmxfeed->state = DMX_STATE_GO;
+	spin_unlock_irq(&dvbdmx->lock);
+
+	mutex_unlock(&dvbdmx->mutex);
+	return 0;
+}
+
+static int dmx_section_feed_stop_filtering(struct dmx_section_feed *feed)
+{
+	struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed;
+	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
+	int ret;
+
+	mutex_lock(&dvbdmx->mutex);
+
+	if (!dvbdmx->stop_feed) {
+		mutex_unlock(&dvbdmx->mutex);
+		return -ENODEV;
+	}
+
+	ret = dvbdmx->stop_feed(dvbdmxfeed);
+
+	spin_lock_irq(&dvbdmx->lock);
+	dvbdmxfeed->state = DMX_STATE_READY;
+	feed->is_filtering = 0;
+	spin_unlock_irq(&dvbdmx->lock);
+
+	mutex_unlock(&dvbdmx->mutex);
+	return ret;
+}
+
+static int dmx_section_feed_release_filter(struct dmx_section_feed *feed,
+					   struct dmx_section_filter *filter)
+{
+	struct dvb_demux_filter *dvbdmxfilter = (struct dvb_demux_filter *)filter, *f;
+	struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed;
+	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
+
+	mutex_lock(&dvbdmx->mutex);
+
+	if (dvbdmxfilter->feed != dvbdmxfeed) {
+		mutex_unlock(&dvbdmx->mutex);
+		return -EINVAL;
+	}
+
+	if (feed->is_filtering)
+		feed->stop_filtering(feed);
+
+	spin_lock_irq(&dvbdmx->lock);
+	f = dvbdmxfeed->filter;
+
+	if (f == dvbdmxfilter) {
+		dvbdmxfeed->filter = dvbdmxfilter->next;
+	} else {
+		while (f->next != dvbdmxfilter)
+			f = f->next;
+		f->next = f->next->next;
+	}
+
+	dvbdmxfilter->state = DMX_STATE_FREE;
+	spin_unlock_irq(&dvbdmx->lock);
+	mutex_unlock(&dvbdmx->mutex);
+	return 0;
+}
+
+static int dvbdmx_allocate_section_feed(struct dmx_demux *demux,
+					struct dmx_section_feed **feed,
+					dmx_section_cb callback)
+{
+	struct dvb_demux *dvbdmx = (struct dvb_demux *)demux;
+	struct dvb_demux_feed *dvbdmxfeed;
+
+	if (mutex_lock_interruptible(&dvbdmx->mutex))
+		return -ERESTARTSYS;
+
+	if (!(dvbdmxfeed = dvb_dmx_feed_alloc(dvbdmx))) {
+		mutex_unlock(&dvbdmx->mutex);
+		return -EBUSY;
+	}
+
+	dvbdmxfeed->type = DMX_TYPE_SEC;
+	dvbdmxfeed->cb.sec = callback;
+	dvbdmxfeed->demux = dvbdmx;
+	dvbdmxfeed->pid = 0xffff;
+	dvbdmxfeed->feed.sec.secbuf = dvbdmxfeed->feed.sec.secbuf_base;
+	dvbdmxfeed->feed.sec.secbufp = dvbdmxfeed->feed.sec.seclen = 0;
+	dvbdmxfeed->feed.sec.tsfeedp = 0;
+	dvbdmxfeed->filter = NULL;
+	dvbdmxfeed->buffer = NULL;
+
+	(*feed) = &dvbdmxfeed->feed.sec;
+	(*feed)->is_filtering = 0;
+	(*feed)->parent = demux;
+	(*feed)->priv = NULL;
+
+	(*feed)->set = dmx_section_feed_set;
+	(*feed)->allocate_filter = dmx_section_feed_allocate_filter;
+	(*feed)->start_filtering = dmx_section_feed_start_filtering;
+	(*feed)->stop_filtering = dmx_section_feed_stop_filtering;
+	(*feed)->release_filter = dmx_section_feed_release_filter;
+
+	mutex_unlock(&dvbdmx->mutex);
+	return 0;
+}
+
+static int dvbdmx_release_section_feed(struct dmx_demux *demux,
+				       struct dmx_section_feed *feed)
+{
+	struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed;
+	struct dvb_demux *dvbdmx = (struct dvb_demux *)demux;
+
+	mutex_lock(&dvbdmx->mutex);
+
+	if (dvbdmxfeed->state == DMX_STATE_FREE) {
+		mutex_unlock(&dvbdmx->mutex);
+		return -EINVAL;
+	}
+#ifndef NOBUFS
+	vfree(dvbdmxfeed->buffer);
+	dvbdmxfeed->buffer = NULL;
+#endif
+	dvbdmxfeed->state = DMX_STATE_FREE;
+
+	dvb_demux_feed_del(dvbdmxfeed);
+
+	dvbdmxfeed->pid = 0xffff;
+
+	mutex_unlock(&dvbdmx->mutex);
+	return 0;
+}
+
+/******************************************************************************
+ * dvb_demux kernel data API calls
+ ******************************************************************************/
+
+static int dvbdmx_open(struct dmx_demux *demux)
+{
+	struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
+
+	if (dvbdemux->users >= MAX_DVB_DEMUX_USERS)
+		return -EUSERS;
+
+	dvbdemux->users++;
+	return 0;
+}
+
+static int dvbdmx_close(struct dmx_demux *demux)
+{
+	struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
+
+	if (dvbdemux->users == 0)
+		return -ENODEV;
+
+	dvbdemux->users--;
+	//FIXME: release any unneeded resources if users==0
+	return 0;
+}
+
+static int dvbdmx_write(struct dmx_demux *demux, const char __user *buf, size_t count)
+{
+	struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
+	void *p;
+
+	if ((!demux->frontend) || (demux->frontend->source != DMX_MEMORY_FE))
+		return -EINVAL;
+
+	p = memdup_user(buf, count);
+	if (IS_ERR(p))
+		return PTR_ERR(p);
+	if (mutex_lock_interruptible(&dvbdemux->mutex)) {
+		kfree(p);
+		return -ERESTARTSYS;
+	}
+	dvb_dmx_swfilter(dvbdemux, p, count);
+	kfree(p);
+	mutex_unlock(&dvbdemux->mutex);
+
+	if (signal_pending(current))
+		return -EINTR;
+	return count;
+}
+
+static int dvbdmx_add_frontend(struct dmx_demux *demux,
+			       struct dmx_frontend *frontend)
+{
+	struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
+	struct list_head *head = &dvbdemux->frontend_list;
+
+	list_add(&(frontend->connectivity_list), head);
+
+	return 0;
+}
+
+static int dvbdmx_remove_frontend(struct dmx_demux *demux,
+				  struct dmx_frontend *frontend)
+{
+	struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
+	struct list_head *pos, *n, *head = &dvbdemux->frontend_list;
+
+	list_for_each_safe(pos, n, head) {
+		if (DMX_FE_ENTRY(pos) == frontend) {
+			list_del(pos);
+			return 0;
+		}
+	}
+
+	return -ENODEV;
+}
+
+static struct list_head *dvbdmx_get_frontends(struct dmx_demux *demux)
+{
+	struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
+
+	if (list_empty(&dvbdemux->frontend_list))
+		return NULL;
+
+	return &dvbdemux->frontend_list;
+}
+
+static int dvbdmx_connect_frontend(struct dmx_demux *demux,
+				   struct dmx_frontend *frontend)
+{
+	struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
+
+	if (demux->frontend)
+		return -EINVAL;
+
+	mutex_lock(&dvbdemux->mutex);
+
+	demux->frontend = frontend;
+	mutex_unlock(&dvbdemux->mutex);
+	return 0;
+}
+
+static int dvbdmx_disconnect_frontend(struct dmx_demux *demux)
+{
+	struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
+
+	mutex_lock(&dvbdemux->mutex);
+
+	demux->frontend = NULL;
+	mutex_unlock(&dvbdemux->mutex);
+	return 0;
+}
+
+static int dvbdmx_get_pes_pids(struct dmx_demux *demux, u16 * pids)
+{
+	struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
+
+	memcpy(pids, dvbdemux->pids, 5 * sizeof(u16));
+	return 0;
+}
+
+int dvb_dmx_init(struct dvb_demux *dvbdemux)
+{
+	int i;
+	struct dmx_demux *dmx = &dvbdemux->dmx;
+
+	dvbdemux->cnt_storage = NULL;
+	dvbdemux->users = 0;
+	dvbdemux->filter = vmalloc(dvbdemux->filternum * sizeof(struct dvb_demux_filter));
+
+	if (!dvbdemux->filter)
+		return -ENOMEM;
+
+	dvbdemux->feed = vmalloc(dvbdemux->feednum * sizeof(struct dvb_demux_feed));
+	if (!dvbdemux->feed) {
+		vfree(dvbdemux->filter);
+		dvbdemux->filter = NULL;
+		return -ENOMEM;
+	}
+	for (i = 0; i < dvbdemux->filternum; i++) {
+		dvbdemux->filter[i].state = DMX_STATE_FREE;
+		dvbdemux->filter[i].index = i;
+	}
+	for (i = 0; i < dvbdemux->feednum; i++) {
+		dvbdemux->feed[i].state = DMX_STATE_FREE;
+		dvbdemux->feed[i].index = i;
+	}
+
+	dvbdemux->cnt_storage = vmalloc(MAX_PID + 1);
+	if (!dvbdemux->cnt_storage)
+		printk(KERN_WARNING "Couldn't allocate memory for TS/TEI check. Disabling it\n");
+
+	INIT_LIST_HEAD(&dvbdemux->frontend_list);
+
+	for (i = 0; i < DMX_TS_PES_OTHER; i++) {
+		dvbdemux->pesfilter[i] = NULL;
+		dvbdemux->pids[i] = 0xffff;
+	}
+
+	INIT_LIST_HEAD(&dvbdemux->feed_list);
+
+	dvbdemux->playing = 0;
+	dvbdemux->recording = 0;
+	dvbdemux->tsbufp = 0;
+
+	if (!dvbdemux->check_crc32)
+		dvbdemux->check_crc32 = dvb_dmx_crc32;
+
+	if (!dvbdemux->memcopy)
+		dvbdemux->memcopy = dvb_dmx_memcopy;
+
+	dmx->frontend = NULL;
+	dmx->priv = dvbdemux;
+	dmx->open = dvbdmx_open;
+	dmx->close = dvbdmx_close;
+	dmx->write = dvbdmx_write;
+	dmx->allocate_ts_feed = dvbdmx_allocate_ts_feed;
+	dmx->release_ts_feed = dvbdmx_release_ts_feed;
+	dmx->allocate_section_feed = dvbdmx_allocate_section_feed;
+	dmx->release_section_feed = dvbdmx_release_section_feed;
+
+	dmx->add_frontend = dvbdmx_add_frontend;
+	dmx->remove_frontend = dvbdmx_remove_frontend;
+	dmx->get_frontends = dvbdmx_get_frontends;
+	dmx->connect_frontend = dvbdmx_connect_frontend;
+	dmx->disconnect_frontend = dvbdmx_disconnect_frontend;
+	dmx->get_pes_pids = dvbdmx_get_pes_pids;
+
+	mutex_init(&dvbdemux->mutex);
+	spin_lock_init(&dvbdemux->lock);
+
+	return 0;
+}
+
+EXPORT_SYMBOL(dvb_dmx_init);
+
+void dvb_dmx_release(struct dvb_demux *dvbdemux)
+{
+	vfree(dvbdemux->cnt_storage);
+	vfree(dvbdemux->filter);
+	vfree(dvbdemux->feed);
+}
+
+EXPORT_SYMBOL(dvb_dmx_release);
diff --git a/drivers/media/dvb-core/dvb_demux.h b/drivers/media/dvb-core/dvb_demux.h
new file mode 100644
index 0000000..fa7188a
--- /dev/null
+++ b/drivers/media/dvb-core/dvb_demux.h
@@ -0,0 +1,151 @@
+/*
+ * dvb_demux.h: DVB kernel demux API
+ *
+ * Copyright (C) 2000-2001 Marcus Metzler & Ralph Metzler
+ *                         for convergence integrated media GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public 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 _DVB_DEMUX_H_
+#define _DVB_DEMUX_H_
+
+#include <linux/time.h>
+#include <linux/timer.h>
+#include <linux/spinlock.h>
+#include <linux/mutex.h>
+
+#include "demux.h"
+
+#define DMX_TYPE_TS  0
+#define DMX_TYPE_SEC 1
+#define DMX_TYPE_PES 2
+
+#define DMX_STATE_FREE      0
+#define DMX_STATE_ALLOCATED 1
+#define DMX_STATE_SET       2
+#define DMX_STATE_READY     3
+#define DMX_STATE_GO        4
+
+#define DVB_DEMUX_MASK_MAX 18
+
+#define MAX_PID 0x1fff
+
+#define SPEED_PKTS_INTERVAL 50000
+
+struct dvb_demux_filter {
+	struct dmx_section_filter filter;
+	u8 maskandmode[DMX_MAX_FILTER_SIZE];
+	u8 maskandnotmode[DMX_MAX_FILTER_SIZE];
+	int doneq;
+
+	struct dvb_demux_filter *next;
+	struct dvb_demux_feed *feed;
+	int index;
+	int state;
+	int type;
+
+	u16 hw_handle;
+	struct timer_list timer;
+};
+
+#define DMX_FEED_ENTRY(pos) list_entry(pos, struct dvb_demux_feed, list_head)
+
+struct dvb_demux_feed {
+	union {
+		struct dmx_ts_feed ts;
+		struct dmx_section_feed sec;
+	} feed;
+
+	union {
+		dmx_ts_cb ts;
+		dmx_section_cb sec;
+	} cb;
+
+	struct dvb_demux *demux;
+	void *priv;
+	int type;
+	int state;
+	u16 pid;
+	u8 *buffer;
+	int buffer_size;
+
+	struct timespec timeout;
+	struct dvb_demux_filter *filter;
+
+	int ts_type;
+	enum dmx_ts_pes pes_type;
+
+	int cc;
+	int pusi_seen;		/* prevents feeding of garbage from previous section */
+
+	u16 peslen;
+
+	struct list_head list_head;
+	unsigned int index;	/* a unique index for each feed (can be used as hardware pid filter index) */
+};
+
+struct dvb_demux {
+	struct dmx_demux dmx;
+	void *priv;
+	int filternum;
+	int feednum;
+	int (*start_feed)(struct dvb_demux_feed *feed);
+	int (*stop_feed)(struct dvb_demux_feed *feed);
+	int (*write_to_decoder)(struct dvb_demux_feed *feed,
+				 const u8 *buf, size_t len);
+	u32 (*check_crc32)(struct dvb_demux_feed *feed,
+			    const u8 *buf, size_t len);
+	void (*memcopy)(struct dvb_demux_feed *feed, u8 *dst,
+			 const u8 *src, size_t len);
+
+	int users;
+#define MAX_DVB_DEMUX_USERS 10
+	struct dvb_demux_filter *filter;
+	struct dvb_demux_feed *feed;
+
+	struct list_head frontend_list;
+
+	struct dvb_demux_feed *pesfilter[DMX_TS_PES_OTHER];
+	u16 pids[DMX_TS_PES_OTHER];
+	int playing;
+	int recording;
+
+#define DMX_MAX_PID 0x2000
+	struct list_head feed_list;
+	u8 tsbuf[204];
+	int tsbufp;
+
+	struct mutex mutex;
+	spinlock_t lock;
+
+	uint8_t *cnt_storage; /* for TS continuity check */
+
+	struct timespec speed_last_time; /* for TS speed check */
+	uint32_t speed_pkts_cnt; /* for TS speed check */
+};
+
+int dvb_dmx_init(struct dvb_demux *dvbdemux);
+void dvb_dmx_release(struct dvb_demux *dvbdemux);
+void dvb_dmx_swfilter_packets(struct dvb_demux *dvbdmx, const u8 *buf,
+			      size_t count);
+void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count);
+void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf,
+			  size_t count);
+void dvb_dmx_swfilter_raw(struct dvb_demux *demux, const u8 *buf,
+			  size_t count);
+
+#endif /* _DVB_DEMUX_H_ */
diff --git a/drivers/media/dvb-core/dvb_filter.c b/drivers/media/dvb-core/dvb_filter.c
new file mode 100644
index 0000000..772003f
--- /dev/null
+++ b/drivers/media/dvb-core/dvb_filter.c
@@ -0,0 +1,603 @@
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include "dvb_filter.h"
+
+#if 0
+static unsigned int bitrates[3][16] =
+{{0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,0},
+ {0,32,48,56,64,80,96,112,128,160,192,224,256,320,384,0},
+ {0,32,40,48,56,64,80,96,112,128,160,192,224,256,320,0}};
+#endif
+
+static u32 freq[4] = {480, 441, 320, 0};
+
+static unsigned int ac3_bitrates[32] =
+    {32,40,48,56,64,80,96,112,128,160,192,224,256,320,384,448,512,576,640,
+     0,0,0,0,0,0,0,0,0,0,0,0,0};
+
+static u32 ac3_frames[3][32] =
+    {{64,80,96,112,128,160,192,224,256,320,384,448,512,640,768,896,1024,
+      1152,1280,0,0,0,0,0,0,0,0,0,0,0,0,0},
+     {69,87,104,121,139,174,208,243,278,348,417,487,557,696,835,975,1114,
+      1253,1393,0,0,0,0,0,0,0,0,0,0,0,0,0},
+     {96,120,144,168,192,240,288,336,384,480,576,672,768,960,1152,1344,
+      1536,1728,1920,0,0,0,0,0,0,0,0,0,0,0,0,0}};
+
+
+
+#if 0
+static void setup_ts2pes(ipack *pa, ipack *pv, u16 *pida, u16 *pidv,
+		  void (*pes_write)(u8 *buf, int count, void *data),
+		  void *priv)
+{
+	dvb_filter_ipack_init(pa, IPACKS, pes_write);
+	dvb_filter_ipack_init(pv, IPACKS, pes_write);
+	pa->pid = pida;
+	pv->pid = pidv;
+	pa->data = priv;
+	pv->data = priv;
+}
+#endif
+
+#if 0
+static void ts_to_pes(ipack *p, u8 *buf) // don't need count (=188)
+{
+	u8 off = 0;
+
+	if (!buf || !p ){
+		printk("NULL POINTER IDIOT\n");
+		return;
+	}
+	if (buf[1]&PAY_START) {
+		if (p->plength == MMAX_PLENGTH-6 && p->found>6){
+			p->plength = p->found-6;
+			p->found = 0;
+			send_ipack(p);
+			dvb_filter_ipack_reset(p);
+		}
+	}
+	if (buf[3] & ADAPT_FIELD) {  // adaptation field?
+		off = buf[4] + 1;
+		if (off+4 > 187) return;
+	}
+	dvb_filter_instant_repack(buf+4+off, TS_SIZE-4-off, p);
+}
+#endif
+
+#if 0
+/* needs 5 byte input, returns picture coding type*/
+static int read_picture_header(u8 *headr, struct mpg_picture *pic, int field, int pr)
+{
+	u8 pct;
+
+	if (pr) printk( "Pic header: ");
+	pic->temporal_reference[field] = (( headr[0] << 2 ) |
+					  (headr[1] & 0x03) )& 0x03ff;
+	if (pr) printk( " temp ref: 0x%04x", pic->temporal_reference[field]);
+
+	pct = ( headr[1] >> 2 ) & 0x07;
+	pic->picture_coding_type[field] = pct;
+	if (pr) {
+		switch(pct){
+			case I_FRAME:
+				printk( "  I-FRAME");
+				break;
+			case B_FRAME:
+				printk( "  B-FRAME");
+				break;
+			case P_FRAME:
+				printk( "  P-FRAME");
+				break;
+		}
+	}
+
+
+	pic->vinfo.vbv_delay  = (( headr[1] >> 5 ) | ( headr[2] << 3) |
+				 ( (headr[3] & 0x1F) << 11) ) & 0xffff;
+
+	if (pr) printk( " vbv delay: 0x%04x", pic->vinfo.vbv_delay);
+
+	pic->picture_header_parameter = ( headr[3] & 0xe0 ) |
+		((headr[4] & 0x80) >> 3);
+
+	if ( pct == B_FRAME ){
+		pic->picture_header_parameter |= ( headr[4] >> 3 ) & 0x0f;
+	}
+	if (pr) printk( " pic head param: 0x%x",
+			pic->picture_header_parameter);
+
+	return pct;
+}
+#endif
+
+#if 0
+/* needs 4 byte input */
+static int read_gop_header(u8 *headr, struct mpg_picture *pic, int pr)
+{
+	if (pr) printk("GOP header: ");
+
+	pic->time_code  = (( headr[0] << 17 ) | ( headr[1] << 9) |
+			   ( headr[2] << 1 ) | (headr[3] &0x01)) & 0x1ffffff;
+
+	if (pr) printk(" time: %d:%d.%d ", (headr[0]>>2)& 0x1F,
+		       ((headr[0]<<4)& 0x30)| ((headr[1]>>4)& 0x0F),
+		       ((headr[1]<<3)& 0x38)| ((headr[2]>>5)& 0x0F));
+
+	if ( ( headr[3] & 0x40 ) != 0 ){
+		pic->closed_gop = 1;
+	} else {
+		pic->closed_gop = 0;
+	}
+	if (pr) printk("closed: %d", pic->closed_gop);
+
+	if ( ( headr[3] & 0x20 ) != 0 ){
+		pic->broken_link = 1;
+	} else {
+		pic->broken_link = 0;
+	}
+	if (pr) printk(" broken: %d\n", pic->broken_link);
+
+	return 0;
+}
+#endif
+
+#if 0
+/* needs 8 byte input */
+static int read_sequence_header(u8 *headr, struct dvb_video_info *vi, int pr)
+{
+	int sw;
+	int form = -1;
+
+	if (pr) printk("Reading sequence header\n");
+
+	vi->horizontal_size	= ((headr[1] &0xF0) >> 4) | (headr[0] << 4);
+	vi->vertical_size	= ((headr[1] &0x0F) << 8) | (headr[2]);
+
+	sw = (int)((headr[3]&0xF0) >> 4) ;
+
+	switch( sw ){
+	case 1:
+		if (pr)
+			printk("Videostream: ASPECT: 1:1");
+		vi->aspect_ratio = 100;
+		break;
+	case 2:
+		if (pr)
+			printk("Videostream: ASPECT: 4:3");
+		vi->aspect_ratio = 133;
+		break;
+	case 3:
+		if (pr)
+			printk("Videostream: ASPECT: 16:9");
+		vi->aspect_ratio = 177;
+		break;
+	case 4:
+		if (pr)
+			printk("Videostream: ASPECT: 2.21:1");
+		vi->aspect_ratio = 221;
+		break;
+
+	case 5 ... 15:
+		if (pr)
+			printk("Videostream: ASPECT: reserved");
+		vi->aspect_ratio = 0;
+		break;
+
+	default:
+		vi->aspect_ratio = 0;
+		return -1;
+	}
+
+	if (pr)
+		printk("  Size = %dx%d",vi->horizontal_size,vi->vertical_size);
+
+	sw = (int)(headr[3]&0x0F);
+
+	switch ( sw ) {
+	case 1:
+		if (pr)
+			printk("  FRate: 23.976 fps");
+		vi->framerate = 23976;
+		form = -1;
+		break;
+	case 2:
+		if (pr)
+			printk("  FRate: 24 fps");
+		vi->framerate = 24000;
+		form = -1;
+		break;
+	case 3:
+		if (pr)
+			printk("  FRate: 25 fps");
+		vi->framerate = 25000;
+		form = VIDEO_MODE_PAL;
+		break;
+	case 4:
+		if (pr)
+			printk("  FRate: 29.97 fps");
+		vi->framerate = 29970;
+		form = VIDEO_MODE_NTSC;
+		break;
+	case 5:
+		if (pr)
+			printk("  FRate: 30 fps");
+		vi->framerate = 30000;
+		form = VIDEO_MODE_NTSC;
+		break;
+	case 6:
+		if (pr)
+			printk("  FRate: 50 fps");
+		vi->framerate = 50000;
+		form = VIDEO_MODE_PAL;
+		break;
+	case 7:
+		if (pr)
+			printk("  FRate: 60 fps");
+		vi->framerate = 60000;
+		form = VIDEO_MODE_NTSC;
+		break;
+	}
+
+	vi->bit_rate = (headr[4] << 10) | (headr[5] << 2) | (headr[6] & 0x03);
+
+	vi->vbv_buffer_size
+		= (( headr[6] & 0xF8) >> 3 ) | (( headr[7] & 0x1F )<< 5);
+
+	if (pr){
+		printk("  BRate: %d Mbit/s",4*(vi->bit_rate)/10000);
+		printk("  vbvbuffer %d",16*1024*(vi->vbv_buffer_size));
+		printk("\n");
+	}
+
+	vi->video_format = form;
+
+	return 0;
+}
+#endif
+
+
+#if 0
+static int get_vinfo(u8 *mbuf, int count, struct dvb_video_info *vi, int pr)
+{
+	u8 *headr;
+	int found = 0;
+	int c = 0;
+
+	while (found < 4 && c+4 < count){
+		u8 *b;
+
+		b = mbuf+c;
+		if ( b[0] == 0x00 && b[1] == 0x00 && b[2] == 0x01
+		     && b[3] == 0xb3) found = 4;
+		else {
+			c++;
+		}
+	}
+
+	if (! found) return -1;
+	c += 4;
+	if (c+12 >= count) return -1;
+	headr = mbuf+c;
+	if (read_sequence_header(headr, vi, pr) < 0) return -1;
+	vi->off = c-4;
+	return 0;
+}
+#endif
+
+
+#if 0
+static int get_ainfo(u8 *mbuf, int count, struct dvb_audio_info *ai, int pr)
+{
+	u8 *headr;
+	int found = 0;
+	int c = 0;
+	int fr = 0;
+
+	while (found < 2 && c < count){
+		u8 b[2];
+		memcpy( b, mbuf+c, 2);
+
+		if ( b[0] == 0xff && (b[1] & 0xf8) == 0xf8)
+			found = 2;
+		else {
+			c++;
+		}
+	}
+
+	if (!found) return -1;
+
+	if (c+3 >= count) return -1;
+	headr = mbuf+c;
+
+	ai->layer = (headr[1] & 0x06) >> 1;
+
+	if (pr)
+		printk("Audiostream: Layer: %d", 4-ai->layer);
+
+
+	ai->bit_rate = bitrates[(3-ai->layer)][(headr[2] >> 4 )]*1000;
+
+	if (pr){
+		if (ai->bit_rate == 0)
+			printk("  Bit rate: free");
+		else if (ai->bit_rate == 0xf)
+			printk("  BRate: reserved");
+		else
+			printk("  BRate: %d kb/s", ai->bit_rate/1000);
+	}
+
+	fr = (headr[2] & 0x0c ) >> 2;
+	ai->frequency = freq[fr]*100;
+	if (pr){
+		if (ai->frequency == 3)
+			printk("  Freq: reserved\n");
+		else
+			printk("  Freq: %d kHz\n",ai->frequency);
+
+	}
+	ai->off = c;
+	return 0;
+}
+#endif
+
+
+int dvb_filter_get_ac3info(u8 *mbuf, int count, struct dvb_audio_info *ai, int pr)
+{
+	u8 *headr;
+	int found = 0;
+	int c = 0;
+	u8 frame = 0;
+	int fr = 0;
+
+	while ( !found  && c < count){
+		u8 *b = mbuf+c;
+
+		if ( b[0] == 0x0b &&  b[1] == 0x77 )
+			found = 1;
+		else {
+			c++;
+		}
+	}
+
+	if (!found) return -1;
+	if (pr)
+		printk("Audiostream: AC3");
+
+	ai->off = c;
+	if (c+5 >= count) return -1;
+
+	ai->layer = 0;  // 0 for AC3
+	headr = mbuf+c+2;
+
+	frame = (headr[2]&0x3f);
+	ai->bit_rate = ac3_bitrates[frame >> 1]*1000;
+
+	if (pr)
+		printk("  BRate: %d kb/s", (int) ai->bit_rate/1000);
+
+	ai->frequency = (headr[2] & 0xc0 ) >> 6;
+	fr = (headr[2] & 0xc0 ) >> 6;
+	ai->frequency = freq[fr]*100;
+	if (pr) printk ("  Freq: %d Hz\n", (int) ai->frequency);
+
+
+	ai->framesize = ac3_frames[fr][frame >> 1];
+	if ((frame & 1) &&  (fr == 1)) ai->framesize++;
+	ai->framesize = ai->framesize << 1;
+	if (pr) printk ("  Framesize %d\n",(int) ai->framesize);
+
+
+	return 0;
+}
+EXPORT_SYMBOL(dvb_filter_get_ac3info);
+
+
+#if 0
+static u8 *skip_pes_header(u8 **bufp)
+{
+	u8 *inbuf = *bufp;
+	u8 *buf = inbuf;
+	u8 *pts = NULL;
+	int skip = 0;
+
+	static const int mpeg1_skip_table[16] = {
+		1, 0xffff,      5,     10, 0xffff, 0xffff, 0xffff, 0xffff,
+		0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff
+	};
+
+
+	if ((inbuf[6] & 0xc0) == 0x80){ /* mpeg2 */
+		if (buf[7] & PTS_ONLY)
+			pts = buf+9;
+		else pts = NULL;
+		buf = inbuf + 9 + inbuf[8];
+	} else {        /* mpeg1 */
+		for (buf = inbuf + 6; *buf == 0xff; buf++)
+			if (buf == inbuf + 6 + 16) {
+				break;
+			}
+		if ((*buf & 0xc0) == 0x40)
+			buf += 2;
+		skip = mpeg1_skip_table [*buf >> 4];
+		if (skip == 5 || skip == 10) pts = buf;
+		else pts = NULL;
+
+		buf += mpeg1_skip_table [*buf >> 4];
+	}
+
+	*bufp = buf;
+	return pts;
+}
+#endif
+
+#if 0
+static void initialize_quant_matrix( u32 *matrix )
+{
+	int i;
+
+	matrix[0]  = 0x08101013;
+	matrix[1]  = 0x10131616;
+	matrix[2]  = 0x16161616;
+	matrix[3]  = 0x1a181a1b;
+	matrix[4]  = 0x1b1b1a1a;
+	matrix[5]  = 0x1a1a1b1b;
+	matrix[6]  = 0x1b1d1d1d;
+	matrix[7]  = 0x2222221d;
+	matrix[8]  = 0x1d1d1b1b;
+	matrix[9]  = 0x1d1d2020;
+	matrix[10] = 0x22222526;
+	matrix[11] = 0x25232322;
+	matrix[12] = 0x23262628;
+	matrix[13] = 0x28283030;
+	matrix[14] = 0x2e2e3838;
+	matrix[15] = 0x3a454553;
+
+	for ( i = 16 ; i < 32 ; i++ )
+		matrix[i] = 0x10101010;
+}
+#endif
+
+#if 0
+static void initialize_mpg_picture(struct mpg_picture *pic)
+{
+	int i;
+
+	/* set MPEG1 */
+	pic->mpeg1_flag = 1;
+	pic->profile_and_level = 0x4A ;        /* MP@LL */
+	pic->progressive_sequence = 1;
+	pic->low_delay = 0;
+
+	pic->sequence_display_extension_flag = 0;
+	for ( i = 0 ; i < 4 ; i++ ){
+		pic->frame_centre_horizontal_offset[i] = 0;
+		pic->frame_centre_vertical_offset[i] = 0;
+	}
+	pic->last_frame_centre_horizontal_offset = 0;
+	pic->last_frame_centre_vertical_offset = 0;
+
+	pic->picture_display_extension_flag[0] = 0;
+	pic->picture_display_extension_flag[1] = 0;
+	pic->sequence_header_flag = 0;
+	pic->gop_flag = 0;
+	pic->sequence_end_flag = 0;
+}
+#endif
+
+#if 0
+static void mpg_set_picture_parameter( int32_t field_type, struct mpg_picture *pic )
+{
+	int16_t last_h_offset;
+	int16_t last_v_offset;
+
+	int16_t *p_h_offset;
+	int16_t *p_v_offset;
+
+	if ( pic->mpeg1_flag ){
+		pic->picture_structure[field_type] = VIDEO_FRAME_PICTURE;
+		pic->top_field_first = 0;
+		pic->repeat_first_field = 0;
+		pic->progressive_frame = 1;
+		pic->picture_coding_parameter = 0x000010;
+	}
+
+	/* Reset flag */
+	pic->picture_display_extension_flag[field_type] = 0;
+
+	last_h_offset = pic->last_frame_centre_horizontal_offset;
+	last_v_offset = pic->last_frame_centre_vertical_offset;
+	if ( field_type == FIRST_FIELD ){
+		p_h_offset = pic->frame_centre_horizontal_offset;
+		p_v_offset = pic->frame_centre_vertical_offset;
+		*p_h_offset = last_h_offset;
+		*(p_h_offset + 1) = last_h_offset;
+		*(p_h_offset + 2) = last_h_offset;
+		*p_v_offset = last_v_offset;
+		*(p_v_offset + 1) = last_v_offset;
+		*(p_v_offset + 2) = last_v_offset;
+	} else {
+		pic->frame_centre_horizontal_offset[3] = last_h_offset;
+		pic->frame_centre_vertical_offset[3] = last_v_offset;
+	}
+}
+#endif
+
+#if 0
+static void init_mpg_picture( struct mpg_picture *pic, int chan, int32_t field_type)
+{
+	pic->picture_header = 0;
+	pic->sequence_header_data
+		= ( INIT_HORIZONTAL_SIZE << 20 )
+			| ( INIT_VERTICAL_SIZE << 8 )
+			| ( INIT_ASPECT_RATIO << 4 )
+			| ( INIT_FRAME_RATE );
+	pic->mpeg1_flag = 0;
+	pic->vinfo.horizontal_size
+		= INIT_DISP_HORIZONTAL_SIZE;
+	pic->vinfo.vertical_size
+		= INIT_DISP_VERTICAL_SIZE;
+	pic->picture_display_extension_flag[field_type]
+		= 0;
+	pic->pts_flag[field_type] = 0;
+
+	pic->sequence_gop_header = 0;
+	pic->picture_header = 0;
+	pic->sequence_header_flag = 0;
+	pic->gop_flag = 0;
+	pic->sequence_end_flag = 0;
+	pic->sequence_display_extension_flag = 0;
+	pic->last_frame_centre_horizontal_offset = 0;
+	pic->last_frame_centre_vertical_offset = 0;
+	pic->channel = chan;
+}
+#endif
+
+void dvb_filter_pes2ts_init(struct dvb_filter_pes2ts *p2ts, unsigned short pid,
+			    dvb_filter_pes2ts_cb_t *cb, void *priv)
+{
+	unsigned char *buf=p2ts->buf;
+
+	buf[0]=0x47;
+	buf[1]=(pid>>8);
+	buf[2]=pid&0xff;
+	p2ts->cc=0;
+	p2ts->cb=cb;
+	p2ts->priv=priv;
+}
+EXPORT_SYMBOL(dvb_filter_pes2ts_init);
+
+int dvb_filter_pes2ts(struct dvb_filter_pes2ts *p2ts, unsigned char *pes,
+		      int len, int payload_start)
+{
+	unsigned char *buf=p2ts->buf;
+	int ret=0, rest;
+
+	//len=6+((pes[4]<<8)|pes[5]);
+
+	if (payload_start)
+		buf[1]|=0x40;
+	else
+		buf[1]&=~0x40;
+	while (len>=184) {
+		buf[3]=0x10|((p2ts->cc++)&0x0f);
+		memcpy(buf+4, pes, 184);
+		if ((ret=p2ts->cb(p2ts->priv, buf)))
+			return ret;
+		len-=184; pes+=184;
+		buf[1]&=~0x40;
+	}
+	if (!len)
+		return 0;
+	buf[3]=0x30|((p2ts->cc++)&0x0f);
+	rest=183-len;
+	if (rest) {
+		buf[5]=0x00;
+		if (rest-1)
+			memset(buf+6, 0xff, rest-1);
+	}
+	buf[4]=rest;
+	memcpy(buf+5+rest, pes, len);
+	return p2ts->cb(p2ts->priv, buf);
+}
+EXPORT_SYMBOL(dvb_filter_pes2ts);
diff --git a/drivers/media/dvb-core/dvb_filter.h b/drivers/media/dvb-core/dvb_filter.h
new file mode 100644
index 0000000..375e3be
--- /dev/null
+++ b/drivers/media/dvb-core/dvb_filter.h
@@ -0,0 +1,246 @@
+/*
+ * dvb_filter.h
+ *
+ * Copyright (C) 2003 Convergence GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public 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 _DVB_FILTER_H_
+#define _DVB_FILTER_H_
+
+#include <linux/slab.h>
+
+#include "demux.h"
+
+typedef int (dvb_filter_pes2ts_cb_t) (void *, unsigned char *);
+
+struct dvb_filter_pes2ts {
+	unsigned char buf[188];
+	unsigned char cc;
+	dvb_filter_pes2ts_cb_t *cb;
+	void *priv;
+};
+
+void dvb_filter_pes2ts_init(struct dvb_filter_pes2ts *p2ts, unsigned short pid,
+			    dvb_filter_pes2ts_cb_t *cb, void *priv);
+
+int dvb_filter_pes2ts(struct dvb_filter_pes2ts *p2ts, unsigned char *pes,
+		      int len, int payload_start);
+
+
+#define PROG_STREAM_MAP  0xBC
+#define PRIVATE_STREAM1  0xBD
+#define PADDING_STREAM   0xBE
+#define PRIVATE_STREAM2  0xBF
+#define AUDIO_STREAM_S   0xC0
+#define AUDIO_STREAM_E   0xDF
+#define VIDEO_STREAM_S   0xE0
+#define VIDEO_STREAM_E   0xEF
+#define ECM_STREAM       0xF0
+#define EMM_STREAM       0xF1
+#define DSM_CC_STREAM    0xF2
+#define ISO13522_STREAM  0xF3
+#define PROG_STREAM_DIR  0xFF
+
+#define DVB_PICTURE_START    0x00
+#define DVB_USER_START       0xb2
+#define DVB_SEQUENCE_HEADER  0xb3
+#define DVB_SEQUENCE_ERROR   0xb4
+#define DVB_EXTENSION_START  0xb5
+#define DVB_SEQUENCE_END     0xb7
+#define DVB_GOP_START        0xb8
+#define DVB_EXCEPT_SLICE     0xb0
+
+#define SEQUENCE_EXTENSION           0x01
+#define SEQUENCE_DISPLAY_EXTENSION   0x02
+#define PICTURE_CODING_EXTENSION     0x08
+#define QUANT_MATRIX_EXTENSION       0x03
+#define PICTURE_DISPLAY_EXTENSION    0x07
+
+#define I_FRAME 0x01
+#define B_FRAME 0x02
+#define P_FRAME 0x03
+
+/* Initialize sequence_data */
+#define INIT_HORIZONTAL_SIZE        720
+#define INIT_VERTICAL_SIZE          576
+#define INIT_ASPECT_RATIO          0x02
+#define INIT_FRAME_RATE            0x03
+#define INIT_DISP_HORIZONTAL_SIZE   540
+#define INIT_DISP_VERTICAL_SIZE     576
+
+
+//flags2
+#define PTS_DTS_FLAGS    0xC0
+#define ESCR_FLAG        0x20
+#define ES_RATE_FLAG     0x10
+#define DSM_TRICK_FLAG   0x08
+#define ADD_CPY_FLAG     0x04
+#define PES_CRC_FLAG     0x02
+#define PES_EXT_FLAG     0x01
+
+//pts_dts flags
+#define PTS_ONLY         0x80
+#define PTS_DTS          0xC0
+
+#define TS_SIZE        188
+#define TRANS_ERROR    0x80
+#define PAY_START      0x40
+#define TRANS_PRIO     0x20
+#define PID_MASK_HI    0x1F
+//flags
+#define TRANS_SCRMBL1  0x80
+#define TRANS_SCRMBL2  0x40
+#define ADAPT_FIELD    0x20
+#define PAYLOAD        0x10
+#define COUNT_MASK     0x0F
+
+// adaptation flags
+#define DISCON_IND     0x80
+#define RAND_ACC_IND   0x40
+#define ES_PRI_IND     0x20
+#define PCR_FLAG       0x10
+#define OPCR_FLAG      0x08
+#define SPLICE_FLAG    0x04
+#define TRANS_PRIV     0x02
+#define ADAP_EXT_FLAG  0x01
+
+// adaptation extension flags
+#define LTW_FLAG       0x80
+#define PIECE_RATE     0x40
+#define SEAM_SPLICE    0x20
+
+
+#define MAX_PLENGTH 0xFFFF
+#define MMAX_PLENGTH (256*MAX_PLENGTH)
+
+#ifndef IPACKS
+#define IPACKS 2048
+#endif
+
+struct ipack {
+	int size;
+	int found;
+	u8 *buf;
+	u8 cid;
+	u32 plength;
+	u8 plen[2];
+	u8 flag1;
+	u8 flag2;
+	u8 hlength;
+	u8 pts[5];
+	u16 *pid;
+	int mpeg;
+	u8 check;
+	int which;
+	int done;
+	void *data;
+	void (*func)(u8 *buf,  int size, void *priv);
+	int count;
+	int repack_subids;
+};
+
+struct dvb_video_info {
+	u32 horizontal_size;
+	u32 vertical_size;
+	u32 aspect_ratio;
+	u32 framerate;
+	u32 video_format;
+	u32 bit_rate;
+	u32 comp_bit_rate;
+	u32 vbv_buffer_size;
+	s16 vbv_delay;
+	u32 CSPF;
+	u32 off;
+};
+
+#define OFF_SIZE 4
+#define FIRST_FIELD 0
+#define SECOND_FIELD 1
+#define VIDEO_FRAME_PICTURE 0x03
+
+struct mpg_picture {
+	int       channel;
+	struct dvb_video_info vinfo;
+	u32      *sequence_gop_header;
+	u32      *picture_header;
+	s32       time_code;
+	int       low_delay;
+	int       closed_gop;
+	int       broken_link;
+	int       sequence_header_flag;
+	int       gop_flag;
+	int       sequence_end_flag;
+
+	u8        profile_and_level;
+	s32       picture_coding_parameter;
+	u32       matrix[32];
+	s8        matrix_change_flag;
+
+	u8        picture_header_parameter;
+  /* bit 0 - 2: bwd f code
+     bit 3    : fpb vector
+     bit 4 - 6: fwd f code
+     bit 7    : fpf vector */
+
+	int       mpeg1_flag;
+	int       progressive_sequence;
+	int       sequence_display_extension_flag;
+	u32       sequence_header_data;
+	s16       last_frame_centre_horizontal_offset;
+	s16       last_frame_centre_vertical_offset;
+
+	u32       pts[2]; /* [0] 1st field, [1] 2nd field */
+	int       top_field_first;
+	int       repeat_first_field;
+	int       progressive_frame;
+	int       bank;
+	int       forward_bank;
+	int       backward_bank;
+	int       compress;
+	s16       frame_centre_horizontal_offset[OFF_SIZE];
+		  /* [0-2] 1st field, [3] 2nd field */
+	s16       frame_centre_vertical_offset[OFF_SIZE];
+		  /* [0-2] 1st field, [3] 2nd field */
+	s16       temporal_reference[2];
+		  /* [0] 1st field, [1] 2nd field */
+
+	s8        picture_coding_type[2];
+		  /* [0] 1st field, [1] 2nd field */
+	s8        picture_structure[2];
+		  /* [0] 1st field, [1] 2nd field */
+	s8        picture_display_extension_flag[2];
+		  /* [0] 1st field, [1] 2nd field */
+		  /* picture_display_extenion() 0:no 1:exit*/
+	s8        pts_flag[2];
+		  /* [0] 1st field, [1] 2nd field */
+};
+
+struct dvb_audio_info {
+	int layer;
+	u32 bit_rate;
+	u32 frequency;
+	u32 mode;
+	u32 mode_extension ;
+	u32 emphasis;
+	u32 framesize;
+	u32 off;
+};
+
+int dvb_filter_get_ac3info(u8 *mbuf, int count, struct dvb_audio_info *ai, int pr);
+
+
+#endif
diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c
new file mode 100644
index 0000000..479a5e5
--- /dev/null
+++ b/drivers/media/dvb-core/dvb_frontend.c
@@ -0,0 +1,2596 @@
+/*
+ * dvb_frontend.c: DVB frontend tuning interface/thread
+ *
+ *
+ * Copyright (C) 1999-2001 Ralph  Metzler
+ *			   Marcus Metzler
+ *			   Holger Waechtler
+ *				      for convergence integrated media GmbH
+ *
+ * Copyright (C) 2004 Andrew de Quincey (tuning thread cleanup)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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.
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ */
+
+/* Enables DVBv3 compatibility bits at the headers */
+#define __DVB_CORE__
+
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/slab.h>
+#include <linux/poll.h>
+#include <linux/semaphore.h>
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/freezer.h>
+#include <linux/jiffies.h>
+#include <linux/kthread.h>
+#include <asm/processor.h>
+
+#include "dvb_frontend.h"
+#include "dvbdev.h"
+#include <linux/dvb/version.h>
+
+static int dvb_frontend_debug;
+static int dvb_shutdown_timeout;
+static int dvb_force_auto_inversion;
+static int dvb_override_tune_delay;
+static int dvb_powerdown_on_sleep = 1;
+static int dvb_mfe_wait_time = 5;
+
+module_param_named(frontend_debug, dvb_frontend_debug, int, 0644);
+MODULE_PARM_DESC(frontend_debug, "Turn on/off frontend core debugging (default:off).");
+module_param(dvb_shutdown_timeout, int, 0644);
+MODULE_PARM_DESC(dvb_shutdown_timeout, "wait <shutdown_timeout> seconds after close() before suspending hardware");
+module_param(dvb_force_auto_inversion, int, 0644);
+MODULE_PARM_DESC(dvb_force_auto_inversion, "0: normal (default), 1: INVERSION_AUTO forced always");
+module_param(dvb_override_tune_delay, int, 0644);
+MODULE_PARM_DESC(dvb_override_tune_delay, "0: normal (default), >0 => delay in milliseconds to wait for lock after a tune attempt");
+module_param(dvb_powerdown_on_sleep, int, 0644);
+MODULE_PARM_DESC(dvb_powerdown_on_sleep, "0: do not power down, 1: turn LNB voltage off on sleep (default)");
+module_param(dvb_mfe_wait_time, int, 0644);
+MODULE_PARM_DESC(dvb_mfe_wait_time, "Wait up to <mfe_wait_time> seconds on open() for multi-frontend to become available (default:5 seconds)");
+
+#define FESTATE_IDLE 1
+#define FESTATE_RETUNE 2
+#define FESTATE_TUNING_FAST 4
+#define FESTATE_TUNING_SLOW 8
+#define FESTATE_TUNED 16
+#define FESTATE_ZIGZAG_FAST 32
+#define FESTATE_ZIGZAG_SLOW 64
+#define FESTATE_DISEQC 128
+#define FESTATE_ERROR 256
+#define FESTATE_WAITFORLOCK (FESTATE_TUNING_FAST | FESTATE_TUNING_SLOW | FESTATE_ZIGZAG_FAST | FESTATE_ZIGZAG_SLOW | FESTATE_DISEQC)
+#define FESTATE_SEARCHING_FAST (FESTATE_TUNING_FAST | FESTATE_ZIGZAG_FAST)
+#define FESTATE_SEARCHING_SLOW (FESTATE_TUNING_SLOW | FESTATE_ZIGZAG_SLOW)
+#define FESTATE_LOSTLOCK (FESTATE_ZIGZAG_FAST | FESTATE_ZIGZAG_SLOW)
+
+#define FE_ALGO_HW		1
+/*
+ * FESTATE_IDLE. No tuning parameters have been supplied and the loop is idling.
+ * FESTATE_RETUNE. Parameters have been supplied, but we have not yet performed the first tune.
+ * FESTATE_TUNING_FAST. Tuning parameters have been supplied and fast zigzag scan is in progress.
+ * FESTATE_TUNING_SLOW. Tuning parameters have been supplied. Fast zigzag failed, so we're trying again, but slower.
+ * FESTATE_TUNED. The frontend has successfully locked on.
+ * FESTATE_ZIGZAG_FAST. The lock has been lost, and a fast zigzag has been initiated to try and regain it.
+ * FESTATE_ZIGZAG_SLOW. The lock has been lost. Fast zigzag has been failed, so we're trying again, but slower.
+ * FESTATE_DISEQC. A DISEQC command has just been issued.
+ * FESTATE_WAITFORLOCK. When we're waiting for a lock.
+ * FESTATE_SEARCHING_FAST. When we're searching for a signal using a fast zigzag scan.
+ * FESTATE_SEARCHING_SLOW. When we're searching for a signal using a slow zigzag scan.
+ * FESTATE_LOSTLOCK. When the lock has been lost, and we're searching it again.
+ */
+
+#define DVB_FE_NO_EXIT	0
+#define DVB_FE_NORMAL_EXIT	1
+#define DVB_FE_DEVICE_REMOVED	2
+
+static DEFINE_MUTEX(frontend_mutex);
+
+struct dvb_frontend_private {
+
+	/* thread/frontend values */
+	struct dvb_device *dvbdev;
+	struct dvb_frontend_parameters parameters_out;
+	struct dvb_fe_events events;
+	struct semaphore sem;
+	struct list_head list_head;
+	wait_queue_head_t wait_queue;
+	struct task_struct *thread;
+	unsigned long release_jiffies;
+	unsigned int exit;
+	unsigned int wakeup;
+	fe_status_t status;
+	unsigned long tune_mode_flags;
+	unsigned int delay;
+	unsigned int reinitialise;
+	int tone;
+	int voltage;
+
+	/* swzigzag values */
+	unsigned int state;
+	unsigned int bending;
+	int lnb_drift;
+	unsigned int inversion;
+	unsigned int auto_step;
+	unsigned int auto_sub_step;
+	unsigned int started_auto_step;
+	unsigned int min_delay;
+	unsigned int max_drift;
+	unsigned int step_size;
+	int quality;
+	unsigned int check_wrapped;
+	enum dvbfe_search algo_status;
+};
+
+static void dvb_frontend_wakeup(struct dvb_frontend *fe);
+static int dtv_get_frontend(struct dvb_frontend *fe,
+			    struct dvb_frontend_parameters *p_out);
+static int dtv_property_legacy_params_sync(struct dvb_frontend *fe,
+					   struct dvb_frontend_parameters *p);
+
+static bool has_get_frontend(struct dvb_frontend *fe)
+{
+	return fe->ops.get_frontend != NULL;
+}
+
+/*
+ * Due to DVBv3 API calls, a delivery system should be mapped into one of
+ * the 4 DVBv3 delivery systems (FE_QPSK, FE_QAM, FE_OFDM or FE_ATSC),
+ * otherwise, a DVBv3 call will fail.
+ */
+enum dvbv3_emulation_type {
+	DVBV3_UNKNOWN,
+	DVBV3_QPSK,
+	DVBV3_QAM,
+	DVBV3_OFDM,
+	DVBV3_ATSC,
+};
+
+static enum dvbv3_emulation_type dvbv3_type(u32 delivery_system)
+{
+	switch (delivery_system) {
+	case SYS_DVBC_ANNEX_A:
+	case SYS_DVBC_ANNEX_C:
+		return DVBV3_QAM;
+	case SYS_DVBS:
+	case SYS_DVBS2:
+	case SYS_TURBO:
+	case SYS_ISDBS:
+	case SYS_DSS:
+		return DVBV3_QPSK;
+	case SYS_DVBT:
+	case SYS_DVBT2:
+	case SYS_ISDBT:
+	case SYS_DTMB:
+		return DVBV3_OFDM;
+	case SYS_ATSC:
+	case SYS_ATSCMH:
+	case SYS_DVBC_ANNEX_B:
+		return DVBV3_ATSC;
+	case SYS_UNDEFINED:
+	case SYS_ISDBC:
+	case SYS_DVBH:
+	case SYS_DAB:
+	default:
+		/*
+		 * Doesn't know how to emulate those types and/or
+		 * there's no frontend driver from this type yet
+		 * with some emulation code, so, we're not sure yet how
+		 * to handle them, or they're not compatible with a DVBv3 call.
+		 */
+		return DVBV3_UNKNOWN;
+	}
+}
+
+static void dvb_frontend_add_event(struct dvb_frontend *fe, fe_status_t status)
+{
+	struct dvb_frontend_private *fepriv = fe->frontend_priv;
+	struct dvb_fe_events *events = &fepriv->events;
+	struct dvb_frontend_event *e;
+	int wp;
+
+	dev_dbg(fe->dvb->device, "%s:\n", __func__);
+
+	if ((status & FE_HAS_LOCK) && has_get_frontend(fe))
+		dtv_get_frontend(fe, &fepriv->parameters_out);
+
+	mutex_lock(&events->mtx);
+
+	wp = (events->eventw + 1) % MAX_EVENT;
+	if (wp == events->eventr) {
+		events->overflow = 1;
+		events->eventr = (events->eventr + 1) % MAX_EVENT;
+	}
+
+	e = &events->events[events->eventw];
+	e->status = status;
+	e->parameters = fepriv->parameters_out;
+
+	events->eventw = wp;
+
+	mutex_unlock(&events->mtx);
+
+	wake_up_interruptible (&events->wait_queue);
+}
+
+static int dvb_frontend_get_event(struct dvb_frontend *fe,
+			    struct dvb_frontend_event *event, int flags)
+{
+	struct dvb_frontend_private *fepriv = fe->frontend_priv;
+	struct dvb_fe_events *events = &fepriv->events;
+
+	dev_dbg(fe->dvb->device, "%s:\n", __func__);
+
+	if (events->overflow) {
+		events->overflow = 0;
+		return -EOVERFLOW;
+	}
+
+	if (events->eventw == events->eventr) {
+		int ret;
+
+		if (flags & O_NONBLOCK)
+			return -EWOULDBLOCK;
+
+		up(&fepriv->sem);
+
+		ret = wait_event_interruptible (events->wait_queue,
+						events->eventw != events->eventr);
+
+		if (down_interruptible (&fepriv->sem))
+			return -ERESTARTSYS;
+
+		if (ret < 0)
+			return ret;
+	}
+
+	mutex_lock(&events->mtx);
+	*event = events->events[events->eventr];
+	events->eventr = (events->eventr + 1) % MAX_EVENT;
+	mutex_unlock(&events->mtx);
+
+	return 0;
+}
+
+static void dvb_frontend_clear_events(struct dvb_frontend *fe)
+{
+	struct dvb_frontend_private *fepriv = fe->frontend_priv;
+	struct dvb_fe_events *events = &fepriv->events;
+
+	mutex_lock(&events->mtx);
+	events->eventr = events->eventw;
+	mutex_unlock(&events->mtx);
+}
+
+static void dvb_frontend_init(struct dvb_frontend *fe)
+{
+	dev_dbg(fe->dvb->device,
+			"%s: initialising adapter %i frontend %i (%s)...\n",
+			__func__, fe->dvb->num, fe->id, fe->ops.info.name);
+
+	if (fe->ops.init)
+		fe->ops.init(fe);
+	if (fe->ops.tuner_ops.init) {
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 1);
+		fe->ops.tuner_ops.init(fe);
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 0);
+	}
+}
+
+void dvb_frontend_reinitialise(struct dvb_frontend *fe)
+{
+	struct dvb_frontend_private *fepriv = fe->frontend_priv;
+
+	fepriv->reinitialise = 1;
+	dvb_frontend_wakeup(fe);
+}
+EXPORT_SYMBOL(dvb_frontend_reinitialise);
+
+static void dvb_frontend_swzigzag_update_delay(struct dvb_frontend_private *fepriv, int locked)
+{
+	int q2;
+	struct dvb_frontend *fe = fepriv->dvbdev->priv;
+
+	dev_dbg(fe->dvb->device, "%s:\n", __func__);
+
+	if (locked)
+		(fepriv->quality) = (fepriv->quality * 220 + 36*256) / 256;
+	else
+		(fepriv->quality) = (fepriv->quality * 220 + 0) / 256;
+
+	q2 = fepriv->quality - 128;
+	q2 *= q2;
+
+	fepriv->delay = fepriv->min_delay + q2 * HZ / (128*128);
+}
+
+/**
+ * Performs automatic twiddling of frontend parameters.
+ *
+ * @param fe The frontend concerned.
+ * @param check_wrapped Checks if an iteration has completed. DO NOT SET ON THE FIRST ATTEMPT
+ * @returns Number of complete iterations that have been performed.
+ */
+static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wrapped)
+{
+	int autoinversion;
+	int ready = 0;
+	int fe_set_err = 0;
+	struct dvb_frontend_private *fepriv = fe->frontend_priv;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache, tmp;
+	int original_inversion = c->inversion;
+	u32 original_frequency = c->frequency;
+
+	/* are we using autoinversion? */
+	autoinversion = ((!(fe->ops.info.caps & FE_CAN_INVERSION_AUTO)) &&
+			 (c->inversion == INVERSION_AUTO));
+
+	/* setup parameters correctly */
+	while(!ready) {
+		/* calculate the lnb_drift */
+		fepriv->lnb_drift = fepriv->auto_step * fepriv->step_size;
+
+		/* wrap the auto_step if we've exceeded the maximum drift */
+		if (fepriv->lnb_drift > fepriv->max_drift) {
+			fepriv->auto_step = 0;
+			fepriv->auto_sub_step = 0;
+			fepriv->lnb_drift = 0;
+		}
+
+		/* perform inversion and +/- zigzag */
+		switch(fepriv->auto_sub_step) {
+		case 0:
+			/* try with the current inversion and current drift setting */
+			ready = 1;
+			break;
+
+		case 1:
+			if (!autoinversion) break;
+
+			fepriv->inversion = (fepriv->inversion == INVERSION_OFF) ? INVERSION_ON : INVERSION_OFF;
+			ready = 1;
+			break;
+
+		case 2:
+			if (fepriv->lnb_drift == 0) break;
+
+			fepriv->lnb_drift = -fepriv->lnb_drift;
+			ready = 1;
+			break;
+
+		case 3:
+			if (fepriv->lnb_drift == 0) break;
+			if (!autoinversion) break;
+
+			fepriv->inversion = (fepriv->inversion == INVERSION_OFF) ? INVERSION_ON : INVERSION_OFF;
+			fepriv->lnb_drift = -fepriv->lnb_drift;
+			ready = 1;
+			break;
+
+		default:
+			fepriv->auto_step++;
+			fepriv->auto_sub_step = -1; /* it'll be incremented to 0 in a moment */
+			break;
+		}
+
+		if (!ready) fepriv->auto_sub_step++;
+	}
+
+	/* if this attempt would hit where we started, indicate a complete
+	 * iteration has occurred */
+	if ((fepriv->auto_step == fepriv->started_auto_step) &&
+	    (fepriv->auto_sub_step == 0) && check_wrapped) {
+		return 1;
+	}
+
+	dev_dbg(fe->dvb->device, "%s: drift:%i inversion:%i auto_step:%i " \
+			"auto_sub_step:%i started_auto_step:%i\n",
+			__func__, fepriv->lnb_drift, fepriv->inversion,
+			fepriv->auto_step, fepriv->auto_sub_step,
+			fepriv->started_auto_step);
+
+	/* set the frontend itself */
+	c->frequency += fepriv->lnb_drift;
+	if (autoinversion)
+		c->inversion = fepriv->inversion;
+	tmp = *c;
+	if (fe->ops.set_frontend)
+		fe_set_err = fe->ops.set_frontend(fe);
+	*c = tmp;
+	if (fe_set_err < 0) {
+		fepriv->state = FESTATE_ERROR;
+		return fe_set_err;
+	}
+
+	c->frequency = original_frequency;
+	c->inversion = original_inversion;
+
+	fepriv->auto_sub_step++;
+	return 0;
+}
+
+static void dvb_frontend_swzigzag(struct dvb_frontend *fe)
+{
+	fe_status_t s = 0;
+	int retval = 0;
+	struct dvb_frontend_private *fepriv = fe->frontend_priv;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache, tmp;
+
+	/* if we've got no parameters, just keep idling */
+	if (fepriv->state & FESTATE_IDLE) {
+		fepriv->delay = 3*HZ;
+		fepriv->quality = 0;
+		return;
+	}
+
+	/* in SCAN mode, we just set the frontend when asked and leave it alone */
+	if (fepriv->tune_mode_flags & FE_TUNE_MODE_ONESHOT) {
+		if (fepriv->state & FESTATE_RETUNE) {
+			tmp = *c;
+			if (fe->ops.set_frontend)
+				retval = fe->ops.set_frontend(fe);
+			*c = tmp;
+			if (retval < 0)
+				fepriv->state = FESTATE_ERROR;
+			else
+				fepriv->state = FESTATE_TUNED;
+		}
+		fepriv->delay = 3*HZ;
+		fepriv->quality = 0;
+		return;
+	}
+
+	/* get the frontend status */
+	if (fepriv->state & FESTATE_RETUNE) {
+		s = 0;
+	} else {
+		if (fe->ops.read_status)
+			fe->ops.read_status(fe, &s);
+		if (s != fepriv->status) {
+			dvb_frontend_add_event(fe, s);
+			fepriv->status = s;
+		}
+	}
+
+	/* if we're not tuned, and we have a lock, move to the TUNED state */
+	if ((fepriv->state & FESTATE_WAITFORLOCK) && (s & FE_HAS_LOCK)) {
+		dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK);
+		fepriv->state = FESTATE_TUNED;
+
+		/* if we're tuned, then we have determined the correct inversion */
+		if ((!(fe->ops.info.caps & FE_CAN_INVERSION_AUTO)) &&
+		    (c->inversion == INVERSION_AUTO)) {
+			c->inversion = fepriv->inversion;
+		}
+		return;
+	}
+
+	/* if we are tuned already, check we're still locked */
+	if (fepriv->state & FESTATE_TUNED) {
+		dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK);
+
+		/* we're tuned, and the lock is still good... */
+		if (s & FE_HAS_LOCK) {
+			return;
+		} else { /* if we _WERE_ tuned, but now don't have a lock */
+			fepriv->state = FESTATE_ZIGZAG_FAST;
+			fepriv->started_auto_step = fepriv->auto_step;
+			fepriv->check_wrapped = 0;
+		}
+	}
+
+	/* don't actually do anything if we're in the LOSTLOCK state,
+	 * the frontend is set to FE_CAN_RECOVER, and the max_drift is 0 */
+	if ((fepriv->state & FESTATE_LOSTLOCK) &&
+	    (fe->ops.info.caps & FE_CAN_RECOVER) && (fepriv->max_drift == 0)) {
+		dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK);
+		return;
+	}
+
+	/* don't do anything if we're in the DISEQC state, since this
+	 * might be someone with a motorized dish controlled by DISEQC.
+	 * If its actually a re-tune, there will be a SET_FRONTEND soon enough.	*/
+	if (fepriv->state & FESTATE_DISEQC) {
+		dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK);
+		return;
+	}
+
+	/* if we're in the RETUNE state, set everything up for a brand
+	 * new scan, keeping the current inversion setting, as the next
+	 * tune is _very_ likely to require the same */
+	if (fepriv->state & FESTATE_RETUNE) {
+		fepriv->lnb_drift = 0;
+		fepriv->auto_step = 0;
+		fepriv->auto_sub_step = 0;
+		fepriv->started_auto_step = 0;
+		fepriv->check_wrapped = 0;
+	}
+
+	/* fast zigzag. */
+	if ((fepriv->state & FESTATE_SEARCHING_FAST) || (fepriv->state & FESTATE_RETUNE)) {
+		fepriv->delay = fepriv->min_delay;
+
+		/* perform a tune */
+		retval = dvb_frontend_swzigzag_autotune(fe,
+							fepriv->check_wrapped);
+		if (retval < 0) {
+			return;
+		} else if (retval) {
+			/* OK, if we've run out of trials at the fast speed.
+			 * Drop back to slow for the _next_ attempt */
+			fepriv->state = FESTATE_SEARCHING_SLOW;
+			fepriv->started_auto_step = fepriv->auto_step;
+			return;
+		}
+		fepriv->check_wrapped = 1;
+
+		/* if we've just retuned, enter the ZIGZAG_FAST state.
+		 * This ensures we cannot return from an
+		 * FE_SET_FRONTEND ioctl before the first frontend tune
+		 * occurs */
+		if (fepriv->state & FESTATE_RETUNE) {
+			fepriv->state = FESTATE_TUNING_FAST;
+		}
+	}
+
+	/* slow zigzag */
+	if (fepriv->state & FESTATE_SEARCHING_SLOW) {
+		dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK);
+
+		/* Note: don't bother checking for wrapping; we stay in this
+		 * state until we get a lock */
+		dvb_frontend_swzigzag_autotune(fe, 0);
+	}
+}
+
+static int dvb_frontend_is_exiting(struct dvb_frontend *fe)
+{
+	struct dvb_frontend_private *fepriv = fe->frontend_priv;
+
+	if (fepriv->exit != DVB_FE_NO_EXIT)
+		return 1;
+
+	if (fepriv->dvbdev->writers == 1)
+		if (time_after_eq(jiffies, fepriv->release_jiffies +
+				  dvb_shutdown_timeout * HZ))
+			return 1;
+
+	return 0;
+}
+
+static int dvb_frontend_should_wakeup(struct dvb_frontend *fe)
+{
+	struct dvb_frontend_private *fepriv = fe->frontend_priv;
+
+	if (fepriv->wakeup) {
+		fepriv->wakeup = 0;
+		return 1;
+	}
+	return dvb_frontend_is_exiting(fe);
+}
+
+static void dvb_frontend_wakeup(struct dvb_frontend *fe)
+{
+	struct dvb_frontend_private *fepriv = fe->frontend_priv;
+
+	fepriv->wakeup = 1;
+	wake_up_interruptible(&fepriv->wait_queue);
+}
+
+static int dvb_frontend_thread(void *data)
+{
+	struct dvb_frontend *fe = data;
+	struct dvb_frontend_private *fepriv = fe->frontend_priv;
+	fe_status_t s;
+	enum dvbfe_algo algo;
+
+	bool re_tune = false;
+
+	dev_dbg(fe->dvb->device, "%s:\n", __func__);
+
+	fepriv->check_wrapped = 0;
+	fepriv->quality = 0;
+	fepriv->delay = 3*HZ;
+	fepriv->status = 0;
+	fepriv->wakeup = 0;
+	fepriv->reinitialise = 0;
+
+	dvb_frontend_init(fe);
+
+	set_freezable();
+	while (1) {
+		up(&fepriv->sem);	    /* is locked when we enter the thread... */
+restart:
+		wait_event_interruptible_timeout(fepriv->wait_queue,
+			dvb_frontend_should_wakeup(fe) || kthread_should_stop()
+				|| freezing(current),
+			fepriv->delay);
+
+		if (kthread_should_stop() || dvb_frontend_is_exiting(fe)) {
+			/* got signal or quitting */
+			fepriv->exit = DVB_FE_NORMAL_EXIT;
+			break;
+		}
+
+		if (try_to_freeze())
+			goto restart;
+
+		if (down_interruptible(&fepriv->sem))
+			break;
+
+		if (fepriv->reinitialise) {
+			dvb_frontend_init(fe);
+			if (fe->ops.set_tone && fepriv->tone != -1)
+				fe->ops.set_tone(fe, fepriv->tone);
+			if (fe->ops.set_voltage && fepriv->voltage != -1)
+				fe->ops.set_voltage(fe, fepriv->voltage);
+			fepriv->reinitialise = 0;
+		}
+
+		/* do an iteration of the tuning loop */
+		if (fe->ops.get_frontend_algo) {
+			algo = fe->ops.get_frontend_algo(fe);
+			switch (algo) {
+			case DVBFE_ALGO_HW:
+				dev_dbg(fe->dvb->device, "%s: Frontend ALGO = DVBFE_ALGO_HW\n", __func__);
+
+				if (fepriv->state & FESTATE_RETUNE) {
+					dev_dbg(fe->dvb->device, "%s: Retune requested, FESTATE_RETUNE\n", __func__);
+					re_tune = true;
+					fepriv->state = FESTATE_TUNED;
+				} else {
+					re_tune = false;
+				}
+
+				if (fe->ops.tune)
+					fe->ops.tune(fe, re_tune, fepriv->tune_mode_flags, &fepriv->delay, &s);
+
+				if (s != fepriv->status && !(fepriv->tune_mode_flags & FE_TUNE_MODE_ONESHOT)) {
+					dev_dbg(fe->dvb->device, "%s: state changed, adding current state\n", __func__);
+					dvb_frontend_add_event(fe, s);
+					fepriv->status = s;
+				}
+				break;
+			case DVBFE_ALGO_SW:
+				dev_dbg(fe->dvb->device, "%s: Frontend ALGO = DVBFE_ALGO_SW\n", __func__);
+				dvb_frontend_swzigzag(fe);
+				break;
+			case DVBFE_ALGO_CUSTOM:
+				dev_dbg(fe->dvb->device, "%s: Frontend ALGO = DVBFE_ALGO_CUSTOM, state=%d\n", __func__, fepriv->state);
+				if (fepriv->state & FESTATE_RETUNE) {
+					dev_dbg(fe->dvb->device, "%s: Retune requested, FESTAT_RETUNE\n", __func__);
+					fepriv->state = FESTATE_TUNED;
+				}
+				/* Case where we are going to search for a carrier
+				 * User asked us to retune again for some reason, possibly
+				 * requesting a search with a new set of parameters
+				 */
+				if (fepriv->algo_status & DVBFE_ALGO_SEARCH_AGAIN) {
+					if (fe->ops.search) {
+						fepriv->algo_status = fe->ops.search(fe);
+						/* We did do a search as was requested, the flags are
+						 * now unset as well and has the flags wrt to search.
+						 */
+					} else {
+						fepriv->algo_status &= ~DVBFE_ALGO_SEARCH_AGAIN;
+					}
+				}
+				/* Track the carrier if the search was successful */
+				if (fepriv->algo_status != DVBFE_ALGO_SEARCH_SUCCESS) {
+					fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN;
+					fepriv->delay = HZ / 2;
+				}
+				dtv_property_legacy_params_sync(fe, &fepriv->parameters_out);
+				fe->ops.read_status(fe, &s);
+				if (s != fepriv->status) {
+					dvb_frontend_add_event(fe, s); /* update event list */
+					fepriv->status = s;
+					if (!(s & FE_HAS_LOCK)) {
+						fepriv->delay = HZ / 10;
+						fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN;
+					} else {
+						fepriv->delay = 60 * HZ;
+					}
+				}
+				break;
+			default:
+				dev_dbg(fe->dvb->device, "%s: UNDEFINED ALGO !\n", __func__);
+				break;
+			}
+		} else {
+			dvb_frontend_swzigzag(fe);
+		}
+	}
+
+	if (dvb_powerdown_on_sleep) {
+		if (fe->ops.set_voltage)
+			fe->ops.set_voltage(fe, SEC_VOLTAGE_OFF);
+		if (fe->ops.tuner_ops.sleep) {
+			if (fe->ops.i2c_gate_ctrl)
+				fe->ops.i2c_gate_ctrl(fe, 1);
+			fe->ops.tuner_ops.sleep(fe);
+			if (fe->ops.i2c_gate_ctrl)
+				fe->ops.i2c_gate_ctrl(fe, 0);
+		}
+		if (fe->ops.sleep)
+			fe->ops.sleep(fe);
+	}
+
+	fepriv->thread = NULL;
+	if (kthread_should_stop())
+		fepriv->exit = DVB_FE_DEVICE_REMOVED;
+	else
+		fepriv->exit = DVB_FE_NO_EXIT;
+	mb();
+
+	dvb_frontend_wakeup(fe);
+	return 0;
+}
+
+static void dvb_frontend_stop(struct dvb_frontend *fe)
+{
+	struct dvb_frontend_private *fepriv = fe->frontend_priv;
+
+	dev_dbg(fe->dvb->device, "%s:\n", __func__);
+
+	fepriv->exit = DVB_FE_NORMAL_EXIT;
+	mb();
+
+	if (!fepriv->thread)
+		return;
+
+	kthread_stop(fepriv->thread);
+
+	sema_init(&fepriv->sem, 1);
+	fepriv->state = FESTATE_IDLE;
+
+	/* paranoia check in case a signal arrived */
+	if (fepriv->thread)
+		dev_warn(fe->dvb->device,
+				"dvb_frontend_stop: warning: thread %p won't exit\n",
+				fepriv->thread);
+}
+
+s32 timeval_usec_diff(struct timeval lasttime, struct timeval curtime)
+{
+	return ((curtime.tv_usec < lasttime.tv_usec) ?
+		1000000 - lasttime.tv_usec + curtime.tv_usec :
+		curtime.tv_usec - lasttime.tv_usec);
+}
+EXPORT_SYMBOL(timeval_usec_diff);
+
+static inline void timeval_usec_add(struct timeval *curtime, u32 add_usec)
+{
+	curtime->tv_usec += add_usec;
+	if (curtime->tv_usec >= 1000000) {
+		curtime->tv_usec -= 1000000;
+		curtime->tv_sec++;
+	}
+}
+
+/*
+ * Sleep until gettimeofday() > waketime + add_usec
+ * This needs to be as precise as possible, but as the delay is
+ * usually between 2ms and 32ms, it is done using a scheduled msleep
+ * followed by usleep (normally a busy-wait loop) for the remainder
+ */
+void dvb_frontend_sleep_until(struct timeval *waketime, u32 add_usec)
+{
+	struct timeval lasttime;
+	s32 delta, newdelta;
+
+	timeval_usec_add(waketime, add_usec);
+
+	do_gettimeofday(&lasttime);
+	delta = timeval_usec_diff(lasttime, *waketime);
+	if (delta > 2500) {
+		msleep((delta - 1500) / 1000);
+		do_gettimeofday(&lasttime);
+		newdelta = timeval_usec_diff(lasttime, *waketime);
+		delta = (newdelta > delta) ? 0 : newdelta;
+	}
+	if (delta > 0)
+		udelay(delta);
+}
+EXPORT_SYMBOL(dvb_frontend_sleep_until);
+
+static int dvb_frontend_start(struct dvb_frontend *fe)
+{
+	int ret;
+	struct dvb_frontend_private *fepriv = fe->frontend_priv;
+	struct task_struct *fe_thread;
+
+	dev_dbg(fe->dvb->device, "%s:\n", __func__);
+
+	if (fepriv->thread) {
+		if (fepriv->exit == DVB_FE_NO_EXIT)
+			return 0;
+		else
+			dvb_frontend_stop (fe);
+	}
+
+	if (signal_pending(current))
+		return -EINTR;
+	if (down_interruptible (&fepriv->sem))
+		return -EINTR;
+
+	fepriv->state = FESTATE_IDLE;
+	fepriv->exit = DVB_FE_NO_EXIT;
+	fepriv->thread = NULL;
+	mb();
+
+	fe_thread = kthread_run(dvb_frontend_thread, fe,
+		"kdvb-ad-%i-fe-%i", fe->dvb->num,fe->id);
+	if (IS_ERR(fe_thread)) {
+		ret = PTR_ERR(fe_thread);
+		dev_warn(fe->dvb->device,
+				"dvb_frontend_start: failed to start kthread (%d)\n",
+				ret);
+		up(&fepriv->sem);
+		return ret;
+	}
+	fepriv->thread = fe_thread;
+	return 0;
+}
+
+static void dvb_frontend_get_frequency_limits(struct dvb_frontend *fe,
+					u32 *freq_min, u32 *freq_max)
+{
+	*freq_min = max(fe->ops.info.frequency_min, fe->ops.tuner_ops.info.frequency_min);
+
+	if (fe->ops.info.frequency_max == 0)
+		*freq_max = fe->ops.tuner_ops.info.frequency_max;
+	else if (fe->ops.tuner_ops.info.frequency_max == 0)
+		*freq_max = fe->ops.info.frequency_max;
+	else
+		*freq_max = min(fe->ops.info.frequency_max, fe->ops.tuner_ops.info.frequency_max);
+
+	if (*freq_min == 0 || *freq_max == 0)
+		dev_warn(fe->dvb->device, "DVB: adapter %i frontend %u frequency limits undefined - fix the driver\n",
+				fe->dvb->num, fe->id);
+}
+
+static int dvb_frontend_check_parameters(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	u32 freq_min;
+	u32 freq_max;
+
+	/* range check: frequency */
+	dvb_frontend_get_frequency_limits(fe, &freq_min, &freq_max);
+	if ((freq_min && c->frequency < freq_min) ||
+	    (freq_max && c->frequency > freq_max)) {
+		dev_warn(fe->dvb->device, "DVB: adapter %i frontend %i frequency %u out of range (%u..%u)\n",
+				fe->dvb->num, fe->id, c->frequency,
+				freq_min, freq_max);
+		return -EINVAL;
+	}
+
+	/* range check: symbol rate */
+	switch (c->delivery_system) {
+	case SYS_DVBS:
+	case SYS_DVBS2:
+	case SYS_TURBO:
+	case SYS_DVBC_ANNEX_A:
+	case SYS_DVBC_ANNEX_C:
+		if ((fe->ops.info.symbol_rate_min &&
+		     c->symbol_rate < fe->ops.info.symbol_rate_min) ||
+		    (fe->ops.info.symbol_rate_max &&
+		     c->symbol_rate > fe->ops.info.symbol_rate_max)) {
+			dev_warn(fe->dvb->device, "DVB: adapter %i frontend %i symbol rate %u out of range (%u..%u)\n",
+					fe->dvb->num, fe->id, c->symbol_rate,
+					fe->ops.info.symbol_rate_min,
+					fe->ops.info.symbol_rate_max);
+			return -EINVAL;
+		}
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static int dvb_frontend_clear_cache(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	int i;
+	u32 delsys;
+
+	delsys = c->delivery_system;
+	memset(c, 0, sizeof(struct dtv_frontend_properties));
+	c->delivery_system = delsys;
+
+	c->state = DTV_CLEAR;
+
+	dev_dbg(fe->dvb->device, "%s: Clearing cache for delivery system %d\n",
+			__func__, c->delivery_system);
+
+	c->transmission_mode = TRANSMISSION_MODE_AUTO;
+	c->bandwidth_hz = 0;	/* AUTO */
+	c->guard_interval = GUARD_INTERVAL_AUTO;
+	c->hierarchy = HIERARCHY_AUTO;
+	c->symbol_rate = 0;
+	c->code_rate_HP = FEC_AUTO;
+	c->code_rate_LP = FEC_AUTO;
+	c->fec_inner = FEC_AUTO;
+	c->rolloff = ROLLOFF_AUTO;
+	c->voltage = SEC_VOLTAGE_OFF;
+	c->sectone = SEC_TONE_OFF;
+	c->pilot = PILOT_AUTO;
+
+	c->isdbt_partial_reception = 0;
+	c->isdbt_sb_mode = 0;
+	c->isdbt_sb_subchannel = 0;
+	c->isdbt_sb_segment_idx = 0;
+	c->isdbt_sb_segment_count = 0;
+	c->isdbt_layer_enabled = 0;
+	for (i = 0; i < 3; i++) {
+		c->layer[i].fec = FEC_AUTO;
+		c->layer[i].modulation = QAM_AUTO;
+		c->layer[i].interleaving = 0;
+		c->layer[i].segment_count = 0;
+	}
+
+	c->stream_id = NO_STREAM_ID_FILTER;
+
+	switch (c->delivery_system) {
+	case SYS_DVBS:
+	case SYS_DVBS2:
+	case SYS_TURBO:
+		c->modulation = QPSK;   /* implied for DVB-S in legacy API */
+		c->rolloff = ROLLOFF_35;/* implied for DVB-S */
+		break;
+	case SYS_ATSC:
+		c->modulation = VSB_8;
+		break;
+	default:
+		c->modulation = QAM_AUTO;
+		break;
+	}
+
+	return 0;
+}
+
+#define _DTV_CMD(n, s, b) \
+[n] = { \
+	.name = #n, \
+	.cmd  = n, \
+	.set  = s,\
+	.buffer = b \
+}
+
+static struct dtv_cmds_h dtv_cmds[DTV_MAX_COMMAND + 1] = {
+	_DTV_CMD(DTV_TUNE, 1, 0),
+	_DTV_CMD(DTV_CLEAR, 1, 0),
+
+	/* Set */
+	_DTV_CMD(DTV_FREQUENCY, 1, 0),
+	_DTV_CMD(DTV_BANDWIDTH_HZ, 1, 0),
+	_DTV_CMD(DTV_MODULATION, 1, 0),
+	_DTV_CMD(DTV_INVERSION, 1, 0),
+	_DTV_CMD(DTV_DISEQC_MASTER, 1, 1),
+	_DTV_CMD(DTV_SYMBOL_RATE, 1, 0),
+	_DTV_CMD(DTV_INNER_FEC, 1, 0),
+	_DTV_CMD(DTV_VOLTAGE, 1, 0),
+	_DTV_CMD(DTV_TONE, 1, 0),
+	_DTV_CMD(DTV_PILOT, 1, 0),
+	_DTV_CMD(DTV_ROLLOFF, 1, 0),
+	_DTV_CMD(DTV_DELIVERY_SYSTEM, 1, 0),
+	_DTV_CMD(DTV_HIERARCHY, 1, 0),
+	_DTV_CMD(DTV_CODE_RATE_HP, 1, 0),
+	_DTV_CMD(DTV_CODE_RATE_LP, 1, 0),
+	_DTV_CMD(DTV_GUARD_INTERVAL, 1, 0),
+	_DTV_CMD(DTV_TRANSMISSION_MODE, 1, 0),
+	_DTV_CMD(DTV_INTERLEAVING, 1, 0),
+
+	_DTV_CMD(DTV_ISDBT_PARTIAL_RECEPTION, 1, 0),
+	_DTV_CMD(DTV_ISDBT_SOUND_BROADCASTING, 1, 0),
+	_DTV_CMD(DTV_ISDBT_SB_SUBCHANNEL_ID, 1, 0),
+	_DTV_CMD(DTV_ISDBT_SB_SEGMENT_IDX, 1, 0),
+	_DTV_CMD(DTV_ISDBT_SB_SEGMENT_COUNT, 1, 0),
+	_DTV_CMD(DTV_ISDBT_LAYER_ENABLED, 1, 0),
+	_DTV_CMD(DTV_ISDBT_LAYERA_FEC, 1, 0),
+	_DTV_CMD(DTV_ISDBT_LAYERA_MODULATION, 1, 0),
+	_DTV_CMD(DTV_ISDBT_LAYERA_SEGMENT_COUNT, 1, 0),
+	_DTV_CMD(DTV_ISDBT_LAYERA_TIME_INTERLEAVING, 1, 0),
+	_DTV_CMD(DTV_ISDBT_LAYERB_FEC, 1, 0),
+	_DTV_CMD(DTV_ISDBT_LAYERB_MODULATION, 1, 0),
+	_DTV_CMD(DTV_ISDBT_LAYERB_SEGMENT_COUNT, 1, 0),
+	_DTV_CMD(DTV_ISDBT_LAYERB_TIME_INTERLEAVING, 1, 0),
+	_DTV_CMD(DTV_ISDBT_LAYERC_FEC, 1, 0),
+	_DTV_CMD(DTV_ISDBT_LAYERC_MODULATION, 1, 0),
+	_DTV_CMD(DTV_ISDBT_LAYERC_SEGMENT_COUNT, 1, 0),
+	_DTV_CMD(DTV_ISDBT_LAYERC_TIME_INTERLEAVING, 1, 0),
+
+	_DTV_CMD(DTV_STREAM_ID, 1, 0),
+	_DTV_CMD(DTV_DVBT2_PLP_ID_LEGACY, 1, 0),
+
+	/* Get */
+	_DTV_CMD(DTV_DISEQC_SLAVE_REPLY, 0, 1),
+	_DTV_CMD(DTV_API_VERSION, 0, 0),
+	_DTV_CMD(DTV_CODE_RATE_HP, 0, 0),
+	_DTV_CMD(DTV_CODE_RATE_LP, 0, 0),
+	_DTV_CMD(DTV_GUARD_INTERVAL, 0, 0),
+	_DTV_CMD(DTV_TRANSMISSION_MODE, 0, 0),
+	_DTV_CMD(DTV_HIERARCHY, 0, 0),
+	_DTV_CMD(DTV_INTERLEAVING, 0, 0),
+
+	_DTV_CMD(DTV_ENUM_DELSYS, 0, 0),
+
+	_DTV_CMD(DTV_ATSCMH_PARADE_ID, 1, 0),
+	_DTV_CMD(DTV_ATSCMH_RS_FRAME_ENSEMBLE, 1, 0),
+
+	_DTV_CMD(DTV_ATSCMH_FIC_VER, 0, 0),
+	_DTV_CMD(DTV_ATSCMH_PARADE_ID, 0, 0),
+	_DTV_CMD(DTV_ATSCMH_NOG, 0, 0),
+	_DTV_CMD(DTV_ATSCMH_TNOG, 0, 0),
+	_DTV_CMD(DTV_ATSCMH_SGN, 0, 0),
+	_DTV_CMD(DTV_ATSCMH_PRC, 0, 0),
+	_DTV_CMD(DTV_ATSCMH_RS_FRAME_MODE, 0, 0),
+	_DTV_CMD(DTV_ATSCMH_RS_FRAME_ENSEMBLE, 0, 0),
+	_DTV_CMD(DTV_ATSCMH_RS_CODE_MODE_PRI, 0, 0),
+	_DTV_CMD(DTV_ATSCMH_RS_CODE_MODE_SEC, 0, 0),
+	_DTV_CMD(DTV_ATSCMH_SCCC_BLOCK_MODE, 0, 0),
+	_DTV_CMD(DTV_ATSCMH_SCCC_CODE_MODE_A, 0, 0),
+	_DTV_CMD(DTV_ATSCMH_SCCC_CODE_MODE_B, 0, 0),
+	_DTV_CMD(DTV_ATSCMH_SCCC_CODE_MODE_C, 0, 0),
+	_DTV_CMD(DTV_ATSCMH_SCCC_CODE_MODE_D, 0, 0),
+};
+
+static void dtv_property_dump(struct dvb_frontend *fe, struct dtv_property *tvp)
+{
+	int i;
+
+	if (tvp->cmd <= 0 || tvp->cmd > DTV_MAX_COMMAND) {
+		dev_warn(fe->dvb->device, "%s: tvp.cmd = 0x%08x undefined\n",
+				__func__, tvp->cmd);
+		return;
+	}
+
+	dev_dbg(fe->dvb->device, "%s: tvp.cmd    = 0x%08x (%s)\n", __func__,
+			tvp->cmd, dtv_cmds[tvp->cmd].name);
+
+	if (dtv_cmds[tvp->cmd].buffer) {
+		dev_dbg(fe->dvb->device, "%s: tvp.u.buffer.len = 0x%02x\n",
+			__func__, tvp->u.buffer.len);
+
+		for(i = 0; i < tvp->u.buffer.len; i++)
+			dev_dbg(fe->dvb->device,
+					"%s: tvp.u.buffer.data[0x%02x] = 0x%02x\n",
+					__func__, i, tvp->u.buffer.data[i]);
+	} else {
+		dev_dbg(fe->dvb->device, "%s: tvp.u.data = 0x%08x\n", __func__,
+				tvp->u.data);
+	}
+}
+
+/* Synchronise the legacy tuning parameters into the cache, so that demodulator
+ * drivers can use a single set_frontend tuning function, regardless of whether
+ * it's being used for the legacy or new API, reducing code and complexity.
+ */
+static int dtv_property_cache_sync(struct dvb_frontend *fe,
+				   struct dtv_frontend_properties *c,
+				   const struct dvb_frontend_parameters *p)
+{
+	c->frequency = p->frequency;
+	c->inversion = p->inversion;
+
+	switch (dvbv3_type(c->delivery_system)) {
+	case DVBV3_QPSK:
+		dev_dbg(fe->dvb->device, "%s: Preparing QPSK req\n", __func__);
+		c->symbol_rate = p->u.qpsk.symbol_rate;
+		c->fec_inner = p->u.qpsk.fec_inner;
+		break;
+	case DVBV3_QAM:
+		dev_dbg(fe->dvb->device, "%s: Preparing QAM req\n", __func__);
+		c->symbol_rate = p->u.qam.symbol_rate;
+		c->fec_inner = p->u.qam.fec_inner;
+		c->modulation = p->u.qam.modulation;
+		break;
+	case DVBV3_OFDM:
+		dev_dbg(fe->dvb->device, "%s: Preparing OFDM req\n", __func__);
+
+		switch (p->u.ofdm.bandwidth) {
+		case BANDWIDTH_10_MHZ:
+			c->bandwidth_hz = 10000000;
+			break;
+		case BANDWIDTH_8_MHZ:
+			c->bandwidth_hz = 8000000;
+			break;
+		case BANDWIDTH_7_MHZ:
+			c->bandwidth_hz = 7000000;
+			break;
+		case BANDWIDTH_6_MHZ:
+			c->bandwidth_hz = 6000000;
+			break;
+		case BANDWIDTH_5_MHZ:
+			c->bandwidth_hz = 5000000;
+			break;
+		case BANDWIDTH_1_712_MHZ:
+			c->bandwidth_hz = 1712000;
+			break;
+		case BANDWIDTH_AUTO:
+			c->bandwidth_hz = 0;
+		}
+
+		c->code_rate_HP = p->u.ofdm.code_rate_HP;
+		c->code_rate_LP = p->u.ofdm.code_rate_LP;
+		c->modulation = p->u.ofdm.constellation;
+		c->transmission_mode = p->u.ofdm.transmission_mode;
+		c->guard_interval = p->u.ofdm.guard_interval;
+		c->hierarchy = p->u.ofdm.hierarchy_information;
+		break;
+	case DVBV3_ATSC:
+		dev_dbg(fe->dvb->device, "%s: Preparing ATSC req\n", __func__);
+		c->modulation = p->u.vsb.modulation;
+		if (c->delivery_system == SYS_ATSCMH)
+			break;
+		if ((c->modulation == VSB_8) || (c->modulation == VSB_16))
+			c->delivery_system = SYS_ATSC;
+		else
+			c->delivery_system = SYS_DVBC_ANNEX_B;
+		break;
+	case DVBV3_UNKNOWN:
+		dev_err(fe->dvb->device,
+				"%s: doesn't know how to handle a DVBv3 call to delivery system %i\n",
+				__func__, c->delivery_system);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/* Ensure the cached values are set correctly in the frontend
+ * legacy tuning structures, for the advanced tuning API.
+ */
+static int dtv_property_legacy_params_sync(struct dvb_frontend *fe,
+					    struct dvb_frontend_parameters *p)
+{
+	const struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+
+	p->frequency = c->frequency;
+	p->inversion = c->inversion;
+
+	switch (dvbv3_type(c->delivery_system)) {
+	case DVBV3_UNKNOWN:
+		dev_err(fe->dvb->device,
+				"%s: doesn't know how to handle a DVBv3 call to delivery system %i\n",
+				__func__, c->delivery_system);
+		return -EINVAL;
+	case DVBV3_QPSK:
+		dev_dbg(fe->dvb->device, "%s: Preparing QPSK req\n", __func__);
+		p->u.qpsk.symbol_rate = c->symbol_rate;
+		p->u.qpsk.fec_inner = c->fec_inner;
+		break;
+	case DVBV3_QAM:
+		dev_dbg(fe->dvb->device, "%s: Preparing QAM req\n", __func__);
+		p->u.qam.symbol_rate = c->symbol_rate;
+		p->u.qam.fec_inner = c->fec_inner;
+		p->u.qam.modulation = c->modulation;
+		break;
+	case DVBV3_OFDM:
+		dev_dbg(fe->dvb->device, "%s: Preparing OFDM req\n", __func__);
+		switch (c->bandwidth_hz) {
+		case 10000000:
+			p->u.ofdm.bandwidth = BANDWIDTH_10_MHZ;
+			break;
+		case 8000000:
+			p->u.ofdm.bandwidth = BANDWIDTH_8_MHZ;
+			break;
+		case 7000000:
+			p->u.ofdm.bandwidth = BANDWIDTH_7_MHZ;
+			break;
+		case 6000000:
+			p->u.ofdm.bandwidth = BANDWIDTH_6_MHZ;
+			break;
+		case 5000000:
+			p->u.ofdm.bandwidth = BANDWIDTH_5_MHZ;
+			break;
+		case 1712000:
+			p->u.ofdm.bandwidth = BANDWIDTH_1_712_MHZ;
+			break;
+		case 0:
+		default:
+			p->u.ofdm.bandwidth = BANDWIDTH_AUTO;
+		}
+		p->u.ofdm.code_rate_HP = c->code_rate_HP;
+		p->u.ofdm.code_rate_LP = c->code_rate_LP;
+		p->u.ofdm.constellation = c->modulation;
+		p->u.ofdm.transmission_mode = c->transmission_mode;
+		p->u.ofdm.guard_interval = c->guard_interval;
+		p->u.ofdm.hierarchy_information = c->hierarchy;
+		break;
+	case DVBV3_ATSC:
+		dev_dbg(fe->dvb->device, "%s: Preparing VSB req\n", __func__);
+		p->u.vsb.modulation = c->modulation;
+		break;
+	}
+	return 0;
+}
+
+/**
+ * dtv_get_frontend - calls a callback for retrieving DTV parameters
+ * @fe:		struct dvb_frontend pointer
+ * @c:		struct dtv_frontend_properties pointer (DVBv5 cache)
+ * @p_out	struct dvb_frontend_parameters pointer (DVBv3 FE struct)
+ *
+ * This routine calls either the DVBv3 or DVBv5 get_frontend call.
+ * If c is not null, it will update the DVBv5 cache struct pointed by it.
+ * If p_out is not null, it will update the DVBv3 params pointed by it.
+ */
+static int dtv_get_frontend(struct dvb_frontend *fe,
+			    struct dvb_frontend_parameters *p_out)
+{
+	int r;
+
+	if (fe->ops.get_frontend) {
+		r = fe->ops.get_frontend(fe);
+		if (unlikely(r < 0))
+			return r;
+		if (p_out)
+			dtv_property_legacy_params_sync(fe, p_out);
+		return 0;
+	}
+
+	/* As everything is in cache, get_frontend fops are always supported */
+	return 0;
+}
+
+static int dvb_frontend_ioctl_legacy(struct file *file,
+			unsigned int cmd, void *parg);
+static int dvb_frontend_ioctl_properties(struct file *file,
+			unsigned int cmd, void *parg);
+
+static int dtv_property_process_get(struct dvb_frontend *fe,
+				    const struct dtv_frontend_properties *c,
+				    struct dtv_property *tvp,
+				    struct file *file)
+{
+	int r, ncaps;
+
+	switch(tvp->cmd) {
+	case DTV_ENUM_DELSYS:
+		ncaps = 0;
+		while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) {
+			tvp->u.buffer.data[ncaps] = fe->ops.delsys[ncaps];
+			ncaps++;
+		}
+		tvp->u.buffer.len = ncaps;
+		break;
+	case DTV_FREQUENCY:
+		tvp->u.data = c->frequency;
+		break;
+	case DTV_MODULATION:
+		tvp->u.data = c->modulation;
+		break;
+	case DTV_BANDWIDTH_HZ:
+		tvp->u.data = c->bandwidth_hz;
+		break;
+	case DTV_INVERSION:
+		tvp->u.data = c->inversion;
+		break;
+	case DTV_SYMBOL_RATE:
+		tvp->u.data = c->symbol_rate;
+		break;
+	case DTV_INNER_FEC:
+		tvp->u.data = c->fec_inner;
+		break;
+	case DTV_PILOT:
+		tvp->u.data = c->pilot;
+		break;
+	case DTV_ROLLOFF:
+		tvp->u.data = c->rolloff;
+		break;
+	case DTV_DELIVERY_SYSTEM:
+		tvp->u.data = c->delivery_system;
+		break;
+	case DTV_VOLTAGE:
+		tvp->u.data = c->voltage;
+		break;
+	case DTV_TONE:
+		tvp->u.data = c->sectone;
+		break;
+	case DTV_API_VERSION:
+		tvp->u.data = (DVB_API_VERSION << 8) | DVB_API_VERSION_MINOR;
+		break;
+	case DTV_CODE_RATE_HP:
+		tvp->u.data = c->code_rate_HP;
+		break;
+	case DTV_CODE_RATE_LP:
+		tvp->u.data = c->code_rate_LP;
+		break;
+	case DTV_GUARD_INTERVAL:
+		tvp->u.data = c->guard_interval;
+		break;
+	case DTV_TRANSMISSION_MODE:
+		tvp->u.data = c->transmission_mode;
+		break;
+	case DTV_HIERARCHY:
+		tvp->u.data = c->hierarchy;
+		break;
+	case DTV_INTERLEAVING:
+		tvp->u.data = c->interleaving;
+		break;
+
+	/* ISDB-T Support here */
+	case DTV_ISDBT_PARTIAL_RECEPTION:
+		tvp->u.data = c->isdbt_partial_reception;
+		break;
+	case DTV_ISDBT_SOUND_BROADCASTING:
+		tvp->u.data = c->isdbt_sb_mode;
+		break;
+	case DTV_ISDBT_SB_SUBCHANNEL_ID:
+		tvp->u.data = c->isdbt_sb_subchannel;
+		break;
+	case DTV_ISDBT_SB_SEGMENT_IDX:
+		tvp->u.data = c->isdbt_sb_segment_idx;
+		break;
+	case DTV_ISDBT_SB_SEGMENT_COUNT:
+		tvp->u.data = c->isdbt_sb_segment_count;
+		break;
+	case DTV_ISDBT_LAYER_ENABLED:
+		tvp->u.data = c->isdbt_layer_enabled;
+		break;
+	case DTV_ISDBT_LAYERA_FEC:
+		tvp->u.data = c->layer[0].fec;
+		break;
+	case DTV_ISDBT_LAYERA_MODULATION:
+		tvp->u.data = c->layer[0].modulation;
+		break;
+	case DTV_ISDBT_LAYERA_SEGMENT_COUNT:
+		tvp->u.data = c->layer[0].segment_count;
+		break;
+	case DTV_ISDBT_LAYERA_TIME_INTERLEAVING:
+		tvp->u.data = c->layer[0].interleaving;
+		break;
+	case DTV_ISDBT_LAYERB_FEC:
+		tvp->u.data = c->layer[1].fec;
+		break;
+	case DTV_ISDBT_LAYERB_MODULATION:
+		tvp->u.data = c->layer[1].modulation;
+		break;
+	case DTV_ISDBT_LAYERB_SEGMENT_COUNT:
+		tvp->u.data = c->layer[1].segment_count;
+		break;
+	case DTV_ISDBT_LAYERB_TIME_INTERLEAVING:
+		tvp->u.data = c->layer[1].interleaving;
+		break;
+	case DTV_ISDBT_LAYERC_FEC:
+		tvp->u.data = c->layer[2].fec;
+		break;
+	case DTV_ISDBT_LAYERC_MODULATION:
+		tvp->u.data = c->layer[2].modulation;
+		break;
+	case DTV_ISDBT_LAYERC_SEGMENT_COUNT:
+		tvp->u.data = c->layer[2].segment_count;
+		break;
+	case DTV_ISDBT_LAYERC_TIME_INTERLEAVING:
+		tvp->u.data = c->layer[2].interleaving;
+		break;
+
+	/* Multistream support */
+	case DTV_STREAM_ID:
+	case DTV_DVBT2_PLP_ID_LEGACY:
+		tvp->u.data = c->stream_id;
+		break;
+
+	/* ATSC-MH */
+	case DTV_ATSCMH_FIC_VER:
+		tvp->u.data = fe->dtv_property_cache.atscmh_fic_ver;
+		break;
+	case DTV_ATSCMH_PARADE_ID:
+		tvp->u.data = fe->dtv_property_cache.atscmh_parade_id;
+		break;
+	case DTV_ATSCMH_NOG:
+		tvp->u.data = fe->dtv_property_cache.atscmh_nog;
+		break;
+	case DTV_ATSCMH_TNOG:
+		tvp->u.data = fe->dtv_property_cache.atscmh_tnog;
+		break;
+	case DTV_ATSCMH_SGN:
+		tvp->u.data = fe->dtv_property_cache.atscmh_sgn;
+		break;
+	case DTV_ATSCMH_PRC:
+		tvp->u.data = fe->dtv_property_cache.atscmh_prc;
+		break;
+	case DTV_ATSCMH_RS_FRAME_MODE:
+		tvp->u.data = fe->dtv_property_cache.atscmh_rs_frame_mode;
+		break;
+	case DTV_ATSCMH_RS_FRAME_ENSEMBLE:
+		tvp->u.data = fe->dtv_property_cache.atscmh_rs_frame_ensemble;
+		break;
+	case DTV_ATSCMH_RS_CODE_MODE_PRI:
+		tvp->u.data = fe->dtv_property_cache.atscmh_rs_code_mode_pri;
+		break;
+	case DTV_ATSCMH_RS_CODE_MODE_SEC:
+		tvp->u.data = fe->dtv_property_cache.atscmh_rs_code_mode_sec;
+		break;
+	case DTV_ATSCMH_SCCC_BLOCK_MODE:
+		tvp->u.data = fe->dtv_property_cache.atscmh_sccc_block_mode;
+		break;
+	case DTV_ATSCMH_SCCC_CODE_MODE_A:
+		tvp->u.data = fe->dtv_property_cache.atscmh_sccc_code_mode_a;
+		break;
+	case DTV_ATSCMH_SCCC_CODE_MODE_B:
+		tvp->u.data = fe->dtv_property_cache.atscmh_sccc_code_mode_b;
+		break;
+	case DTV_ATSCMH_SCCC_CODE_MODE_C:
+		tvp->u.data = fe->dtv_property_cache.atscmh_sccc_code_mode_c;
+		break;
+	case DTV_ATSCMH_SCCC_CODE_MODE_D:
+		tvp->u.data = fe->dtv_property_cache.atscmh_sccc_code_mode_d;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	/* Allow the frontend to override outgoing properties */
+	if (fe->ops.get_property) {
+		r = fe->ops.get_property(fe, tvp);
+		if (r < 0)
+			return r;
+	}
+
+	dtv_property_dump(fe, tvp);
+
+	return 0;
+}
+
+static int dtv_set_frontend(struct dvb_frontend *fe);
+
+static bool is_dvbv3_delsys(u32 delsys)
+{
+	bool status;
+
+	status = (delsys == SYS_DVBT) || (delsys == SYS_DVBC_ANNEX_A) ||
+		 (delsys == SYS_DVBS) || (delsys == SYS_ATSC);
+
+	return status;
+}
+
+static int set_delivery_system(struct dvb_frontend *fe, u32 desired_system)
+{
+	int ncaps, i;
+	u32 delsys = SYS_UNDEFINED;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	enum dvbv3_emulation_type type;
+
+	/*
+	 * It was reported that some old DVBv5 applications were
+	 * filling delivery_system with SYS_UNDEFINED. If this happens,
+	 * assume that the application wants to use the first supported
+	 * delivery system.
+	 */
+	if (c->delivery_system == SYS_UNDEFINED)
+	        c->delivery_system = fe->ops.delsys[0];
+
+	if (desired_system == SYS_UNDEFINED) {
+		/*
+		 * A DVBv3 call doesn't know what's the desired system.
+		 * Also, DVBv3 applications don't know that ops.info->type
+		 * could be changed, and they simply dies when it doesn't
+		 * match.
+		 * So, don't change the current delivery system, as it
+		 * may be trying to do the wrong thing, like setting an
+		 * ISDB-T frontend as DVB-T. Instead, find the closest
+		 * DVBv3 system that matches the delivery system.
+		 */
+		if (is_dvbv3_delsys(c->delivery_system)) {
+			dev_dbg(fe->dvb->device,
+					"%s: Using delivery system to %d\n",
+					__func__, c->delivery_system);
+			return 0;
+		}
+		type = dvbv3_type(c->delivery_system);
+		switch (type) {
+		case DVBV3_QPSK:
+			desired_system = SYS_DVBS;
+			break;
+		case DVBV3_QAM:
+			desired_system = SYS_DVBC_ANNEX_A;
+			break;
+		case DVBV3_ATSC:
+			desired_system = SYS_ATSC;
+			break;
+		case DVBV3_OFDM:
+			desired_system = SYS_DVBT;
+			break;
+		default:
+			dev_dbg(fe->dvb->device, "%s: This frontend doesn't support DVBv3 calls\n",
+					__func__);
+			return -EINVAL;
+		}
+		/*
+		 * Get a delivery system that is compatible with DVBv3
+		 * NOTE: in order for this to work with softwares like Kaffeine that
+		 *	uses a DVBv5 call for DVB-S2 and a DVBv3 call to go back to
+		 *	DVB-S, drivers that support both should put the SYS_DVBS entry
+		 *	before the SYS_DVBS2, otherwise it won't switch back to DVB-S.
+		 *	The real fix is that userspace applications should not use DVBv3
+		 *	and not trust on calling FE_SET_FRONTEND to switch the delivery
+		 *	system.
+		 */
+		ncaps = 0;
+		while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) {
+			if (fe->ops.delsys[ncaps] == desired_system) {
+				delsys = desired_system;
+				break;
+			}
+			ncaps++;
+		}
+		if (delsys == SYS_UNDEFINED) {
+			dev_dbg(fe->dvb->device, "%s: Couldn't find a delivery system that matches %d\n",
+					__func__, desired_system);
+		}
+	} else {
+		/*
+		 * This is a DVBv5 call. So, it likely knows the supported
+		 * delivery systems.
+		 */
+
+		/* Check if the desired delivery system is supported */
+		ncaps = 0;
+		while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) {
+			if (fe->ops.delsys[ncaps] == desired_system) {
+				c->delivery_system = desired_system;
+				dev_dbg(fe->dvb->device,
+						"%s: Changing delivery system to %d\n",
+						__func__, desired_system);
+				return 0;
+			}
+			ncaps++;
+		}
+		type = dvbv3_type(desired_system);
+
+		/*
+		 * The delivery system is not supported. See if it can be
+		 * emulated.
+		 * The emulation only works if the desired system is one of the
+		 * DVBv3 delivery systems
+		 */
+		if (!is_dvbv3_delsys(desired_system)) {
+			dev_dbg(fe->dvb->device,
+					"%s: can't use a DVBv3 FE_SET_FRONTEND call on this frontend\n",
+					__func__);
+			return -EINVAL;
+		}
+
+		/*
+		 * Get the last non-DVBv3 delivery system that has the same type
+		 * of the desired system
+		 */
+		ncaps = 0;
+		while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) {
+			if ((dvbv3_type(fe->ops.delsys[ncaps]) == type) &&
+			    !is_dvbv3_delsys(fe->ops.delsys[ncaps]))
+				delsys = fe->ops.delsys[ncaps];
+			ncaps++;
+		}
+		/* There's nothing compatible with the desired delivery system */
+		if (delsys == SYS_UNDEFINED) {
+			dev_dbg(fe->dvb->device,
+					"%s: Incompatible DVBv3 FE_SET_FRONTEND call for this frontend\n",
+					__func__);
+			return -EINVAL;
+		}
+	}
+
+	c->delivery_system = delsys;
+
+	/*
+	 * The DVBv3 or DVBv5 call is requesting a different system. So,
+	 * emulation is needed.
+	 *
+	 * Emulate newer delivery systems like ISDBT, DVBT and DTMB
+	 * for older DVBv5 applications. The emulation will try to use
+	 * the auto mode for most things, and will assume that the desired
+	 * delivery system is the last one at the ops.delsys[] array
+	 */
+	dev_dbg(fe->dvb->device,
+			"%s: Using delivery system %d emulated as if it were a %d\n",
+			__func__, delsys, desired_system);
+
+	/*
+	 * For now, handles ISDB-T calls. More code may be needed here for the
+	 * other emulated stuff
+	 */
+	if (type == DVBV3_OFDM) {
+		if (c->delivery_system == SYS_ISDBT) {
+			dev_dbg(fe->dvb->device,
+					"%s: Using defaults for SYS_ISDBT\n",
+					__func__);
+
+			if (!c->bandwidth_hz)
+				c->bandwidth_hz = 6000000;
+
+			c->isdbt_partial_reception = 0;
+			c->isdbt_sb_mode = 0;
+			c->isdbt_sb_subchannel = 0;
+			c->isdbt_sb_segment_idx = 0;
+			c->isdbt_sb_segment_count = 0;
+			c->isdbt_layer_enabled = 0;
+			for (i = 0; i < 3; i++) {
+				c->layer[i].fec = FEC_AUTO;
+				c->layer[i].modulation = QAM_AUTO;
+				c->layer[i].interleaving = 0;
+				c->layer[i].segment_count = 0;
+			}
+		}
+	}
+	dev_dbg(fe->dvb->device, "%s: change delivery system on cache to %d\n",
+			__func__, c->delivery_system);
+
+	return 0;
+}
+
+static int dtv_property_process_set(struct dvb_frontend *fe,
+				    struct dtv_property *tvp,
+				    struct file *file)
+{
+	int r = 0;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+
+	/* Allow the frontend to validate incoming properties */
+	if (fe->ops.set_property) {
+		r = fe->ops.set_property(fe, tvp);
+		if (r < 0)
+			return r;
+	}
+
+	switch(tvp->cmd) {
+	case DTV_CLEAR:
+		/*
+		 * Reset a cache of data specific to the frontend here. This does
+		 * not effect hardware.
+		 */
+		dvb_frontend_clear_cache(fe);
+		break;
+	case DTV_TUNE:
+		/* interpret the cache of data, build either a traditional frontend
+		 * tunerequest so we can pass validation in the FE_SET_FRONTEND
+		 * ioctl.
+		 */
+		c->state = tvp->cmd;
+		dev_dbg(fe->dvb->device, "%s: Finalised property cache\n",
+				__func__);
+
+		r = dtv_set_frontend(fe);
+		break;
+	case DTV_FREQUENCY:
+		c->frequency = tvp->u.data;
+		break;
+	case DTV_MODULATION:
+		c->modulation = tvp->u.data;
+		break;
+	case DTV_BANDWIDTH_HZ:
+		c->bandwidth_hz = tvp->u.data;
+		break;
+	case DTV_INVERSION:
+		c->inversion = tvp->u.data;
+		break;
+	case DTV_SYMBOL_RATE:
+		c->symbol_rate = tvp->u.data;
+		break;
+	case DTV_INNER_FEC:
+		c->fec_inner = tvp->u.data;
+		break;
+	case DTV_PILOT:
+		c->pilot = tvp->u.data;
+		break;
+	case DTV_ROLLOFF:
+		c->rolloff = tvp->u.data;
+		break;
+	case DTV_DELIVERY_SYSTEM:
+		r = set_delivery_system(fe, tvp->u.data);
+		break;
+	case DTV_VOLTAGE:
+		c->voltage = tvp->u.data;
+		r = dvb_frontend_ioctl_legacy(file, FE_SET_VOLTAGE,
+			(void *)c->voltage);
+		break;
+	case DTV_TONE:
+		c->sectone = tvp->u.data;
+		r = dvb_frontend_ioctl_legacy(file, FE_SET_TONE,
+			(void *)c->sectone);
+		break;
+	case DTV_CODE_RATE_HP:
+		c->code_rate_HP = tvp->u.data;
+		break;
+	case DTV_CODE_RATE_LP:
+		c->code_rate_LP = tvp->u.data;
+		break;
+	case DTV_GUARD_INTERVAL:
+		c->guard_interval = tvp->u.data;
+		break;
+	case DTV_TRANSMISSION_MODE:
+		c->transmission_mode = tvp->u.data;
+		break;
+	case DTV_HIERARCHY:
+		c->hierarchy = tvp->u.data;
+		break;
+	case DTV_INTERLEAVING:
+		c->interleaving = tvp->u.data;
+		break;
+
+	/* ISDB-T Support here */
+	case DTV_ISDBT_PARTIAL_RECEPTION:
+		c->isdbt_partial_reception = tvp->u.data;
+		break;
+	case DTV_ISDBT_SOUND_BROADCASTING:
+		c->isdbt_sb_mode = tvp->u.data;
+		break;
+	case DTV_ISDBT_SB_SUBCHANNEL_ID:
+		c->isdbt_sb_subchannel = tvp->u.data;
+		break;
+	case DTV_ISDBT_SB_SEGMENT_IDX:
+		c->isdbt_sb_segment_idx = tvp->u.data;
+		break;
+	case DTV_ISDBT_SB_SEGMENT_COUNT:
+		c->isdbt_sb_segment_count = tvp->u.data;
+		break;
+	case DTV_ISDBT_LAYER_ENABLED:
+		c->isdbt_layer_enabled = tvp->u.data;
+		break;
+	case DTV_ISDBT_LAYERA_FEC:
+		c->layer[0].fec = tvp->u.data;
+		break;
+	case DTV_ISDBT_LAYERA_MODULATION:
+		c->layer[0].modulation = tvp->u.data;
+		break;
+	case DTV_ISDBT_LAYERA_SEGMENT_COUNT:
+		c->layer[0].segment_count = tvp->u.data;
+		break;
+	case DTV_ISDBT_LAYERA_TIME_INTERLEAVING:
+		c->layer[0].interleaving = tvp->u.data;
+		break;
+	case DTV_ISDBT_LAYERB_FEC:
+		c->layer[1].fec = tvp->u.data;
+		break;
+	case DTV_ISDBT_LAYERB_MODULATION:
+		c->layer[1].modulation = tvp->u.data;
+		break;
+	case DTV_ISDBT_LAYERB_SEGMENT_COUNT:
+		c->layer[1].segment_count = tvp->u.data;
+		break;
+	case DTV_ISDBT_LAYERB_TIME_INTERLEAVING:
+		c->layer[1].interleaving = tvp->u.data;
+		break;
+	case DTV_ISDBT_LAYERC_FEC:
+		c->layer[2].fec = tvp->u.data;
+		break;
+	case DTV_ISDBT_LAYERC_MODULATION:
+		c->layer[2].modulation = tvp->u.data;
+		break;
+	case DTV_ISDBT_LAYERC_SEGMENT_COUNT:
+		c->layer[2].segment_count = tvp->u.data;
+		break;
+	case DTV_ISDBT_LAYERC_TIME_INTERLEAVING:
+		c->layer[2].interleaving = tvp->u.data;
+		break;
+
+	/* Multistream support */
+	case DTV_STREAM_ID:
+	case DTV_DVBT2_PLP_ID_LEGACY:
+		c->stream_id = tvp->u.data;
+		break;
+
+	/* ATSC-MH */
+	case DTV_ATSCMH_PARADE_ID:
+		fe->dtv_property_cache.atscmh_parade_id = tvp->u.data;
+		break;
+	case DTV_ATSCMH_RS_FRAME_ENSEMBLE:
+		fe->dtv_property_cache.atscmh_rs_frame_ensemble = tvp->u.data;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	return r;
+}
+
+static int dvb_frontend_ioctl(struct file *file,
+			unsigned int cmd, void *parg)
+{
+	struct dvb_device *dvbdev = file->private_data;
+	struct dvb_frontend *fe = dvbdev->priv;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	struct dvb_frontend_private *fepriv = fe->frontend_priv;
+	int err = -ENOTTY;
+
+	dev_dbg(fe->dvb->device, "%s: (%d)\n", __func__, _IOC_NR(cmd));
+	if (fepriv->exit != DVB_FE_NO_EXIT)
+		return -ENODEV;
+
+	if ((file->f_flags & O_ACCMODE) == O_RDONLY &&
+	    (_IOC_DIR(cmd) != _IOC_READ || cmd == FE_GET_EVENT ||
+	     cmd == FE_DISEQC_RECV_SLAVE_REPLY))
+		return -EPERM;
+
+	if (down_interruptible (&fepriv->sem))
+		return -ERESTARTSYS;
+
+	if ((cmd == FE_SET_PROPERTY) || (cmd == FE_GET_PROPERTY))
+		err = dvb_frontend_ioctl_properties(file, cmd, parg);
+	else {
+		c->state = DTV_UNDEFINED;
+		err = dvb_frontend_ioctl_legacy(file, cmd, parg);
+	}
+
+	up(&fepriv->sem);
+	return err;
+}
+
+static int dvb_frontend_ioctl_properties(struct file *file,
+			unsigned int cmd, void *parg)
+{
+	struct dvb_device *dvbdev = file->private_data;
+	struct dvb_frontend *fe = dvbdev->priv;
+	struct dvb_frontend_private *fepriv = fe->frontend_priv;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	int err = 0;
+
+	struct dtv_properties *tvps = NULL;
+	struct dtv_property *tvp = NULL;
+	int i;
+
+	dev_dbg(fe->dvb->device, "%s:\n", __func__);
+
+	if(cmd == FE_SET_PROPERTY) {
+		tvps = (struct dtv_properties __user *)parg;
+
+		dev_dbg(fe->dvb->device, "%s: properties.num = %d\n", __func__, tvps->num);
+		dev_dbg(fe->dvb->device, "%s: properties.props = %p\n", __func__, tvps->props);
+
+		/* Put an arbitrary limit on the number of messages that can
+		 * be sent at once */
+		if ((tvps->num == 0) || (tvps->num > DTV_IOCTL_MAX_MSGS))
+			return -EINVAL;
+
+		tvp = kmalloc(tvps->num * sizeof(struct dtv_property), GFP_KERNEL);
+		if (!tvp) {
+			err = -ENOMEM;
+			goto out;
+		}
+
+		if (copy_from_user(tvp, tvps->props, tvps->num * sizeof(struct dtv_property))) {
+			err = -EFAULT;
+			goto out;
+		}
+
+		for (i = 0; i < tvps->num; i++) {
+			err = dtv_property_process_set(fe, tvp + i, file);
+			if (err < 0)
+				goto out;
+			(tvp + i)->result = err;
+		}
+
+		if (c->state == DTV_TUNE)
+			dev_dbg(fe->dvb->device, "%s: Property cache is full, tuning\n", __func__);
+
+	} else
+	if(cmd == FE_GET_PROPERTY) {
+		tvps = (struct dtv_properties __user *)parg;
+
+		dev_dbg(fe->dvb->device, "%s: properties.num = %d\n", __func__, tvps->num);
+		dev_dbg(fe->dvb->device, "%s: properties.props = %p\n", __func__, tvps->props);
+
+		/* Put an arbitrary limit on the number of messages that can
+		 * be sent at once */
+		if ((tvps->num == 0) || (tvps->num > DTV_IOCTL_MAX_MSGS))
+			return -EINVAL;
+
+		tvp = kmalloc(tvps->num * sizeof(struct dtv_property), GFP_KERNEL);
+		if (!tvp) {
+			err = -ENOMEM;
+			goto out;
+		}
+
+		if (copy_from_user(tvp, tvps->props, tvps->num * sizeof(struct dtv_property))) {
+			err = -EFAULT;
+			goto out;
+		}
+
+		/*
+		 * Fills the cache out struct with the cache contents, plus
+		 * the data retrieved from get_frontend, if the frontend
+		 * is not idle. Otherwise, returns the cached content
+		 */
+		if (fepriv->state != FESTATE_IDLE) {
+			err = dtv_get_frontend(fe, NULL);
+			if (err < 0)
+				goto out;
+		}
+		for (i = 0; i < tvps->num; i++) {
+			err = dtv_property_process_get(fe, c, tvp + i, file);
+			if (err < 0)
+				goto out;
+			(tvp + i)->result = err;
+		}
+
+		if (copy_to_user(tvps->props, tvp, tvps->num * sizeof(struct dtv_property))) {
+			err = -EFAULT;
+			goto out;
+		}
+
+	} else
+		err = -ENOTTY;
+
+out:
+	kfree(tvp);
+	return err;
+}
+
+static int dtv_set_frontend(struct dvb_frontend *fe)
+{
+	struct dvb_frontend_private *fepriv = fe->frontend_priv;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	struct dvb_frontend_tune_settings fetunesettings;
+	u32 rolloff = 0;
+
+	if (dvb_frontend_check_parameters(fe) < 0)
+		return -EINVAL;
+
+	/*
+	 * Initialize output parameters to match the values given by
+	 * the user. FE_SET_FRONTEND triggers an initial frontend event
+	 * with status = 0, which copies output parameters to userspace.
+	 */
+	dtv_property_legacy_params_sync(fe, &fepriv->parameters_out);
+
+	/*
+	 * Be sure that the bandwidth will be filled for all
+	 * non-satellite systems, as tuners need to know what
+	 * low pass/Nyquist half filter should be applied, in
+	 * order to avoid inter-channel noise.
+	 *
+	 * ISDB-T and DVB-T/T2 already sets bandwidth.
+	 * ATSC and DVB-C don't set, so, the core should fill it.
+	 *
+	 * On DVB-C Annex A and C, the bandwidth is a function of
+	 * the roll-off and symbol rate. Annex B defines different
+	 * roll-off factors depending on the modulation. Fortunately,
+	 * Annex B is only used with 6MHz, so there's no need to
+	 * calculate it.
+	 *
+	 * While not officially supported, a side effect of handling it at
+	 * the cache level is that a program could retrieve the bandwidth
+	 * via DTV_BANDWIDTH_HZ, which may be useful for test programs.
+	 */
+	switch (c->delivery_system) {
+	case SYS_ATSC:
+	case SYS_DVBC_ANNEX_B:
+		c->bandwidth_hz = 6000000;
+		break;
+	case SYS_DVBC_ANNEX_A:
+		rolloff = 115;
+		break;
+	case SYS_DVBC_ANNEX_C:
+		rolloff = 113;
+		break;
+	default:
+		break;
+	}
+	if (rolloff)
+		c->bandwidth_hz = (c->symbol_rate * rolloff) / 100;
+
+	/* force auto frequency inversion if requested */
+	if (dvb_force_auto_inversion)
+		c->inversion = INVERSION_AUTO;
+
+	/*
+	 * without hierarchical coding code_rate_LP is irrelevant,
+	 * so we tolerate the otherwise invalid FEC_NONE setting
+	 */
+	if (c->hierarchy == HIERARCHY_NONE && c->code_rate_LP == FEC_NONE)
+		c->code_rate_LP = FEC_AUTO;
+
+	/* get frontend-specific tuning settings */
+	memset(&fetunesettings, 0, sizeof(struct dvb_frontend_tune_settings));
+	if (fe->ops.get_tune_settings && (fe->ops.get_tune_settings(fe, &fetunesettings) == 0)) {
+		fepriv->min_delay = (fetunesettings.min_delay_ms * HZ) / 1000;
+		fepriv->max_drift = fetunesettings.max_drift;
+		fepriv->step_size = fetunesettings.step_size;
+	} else {
+		/* default values */
+		switch (c->delivery_system) {
+		case SYS_DVBS:
+		case SYS_DVBS2:
+		case SYS_ISDBS:
+		case SYS_TURBO:
+		case SYS_DVBC_ANNEX_A:
+		case SYS_DVBC_ANNEX_C:
+			fepriv->min_delay = HZ / 20;
+			fepriv->step_size = c->symbol_rate / 16000;
+			fepriv->max_drift = c->symbol_rate / 2000;
+			break;
+		case SYS_DVBT:
+		case SYS_DVBT2:
+		case SYS_ISDBT:
+		case SYS_DTMB:
+			fepriv->min_delay = HZ / 20;
+			fepriv->step_size = fe->ops.info.frequency_stepsize * 2;
+			fepriv->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1;
+			break;
+		default:
+			/*
+			 * FIXME: This sounds wrong! if freqency_stepsize is
+			 * defined by the frontend, why not use it???
+			 */
+			fepriv->min_delay = HZ / 20;
+			fepriv->step_size = 0; /* no zigzag */
+			fepriv->max_drift = 0;
+			break;
+		}
+	}
+	if (dvb_override_tune_delay > 0)
+		fepriv->min_delay = (dvb_override_tune_delay * HZ) / 1000;
+
+	fepriv->state = FESTATE_RETUNE;
+
+	/* Request the search algorithm to search */
+	fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN;
+
+	dvb_frontend_clear_events(fe);
+	dvb_frontend_add_event(fe, 0);
+	dvb_frontend_wakeup(fe);
+	fepriv->status = 0;
+
+	return 0;
+}
+
+
+static int dvb_frontend_ioctl_legacy(struct file *file,
+			unsigned int cmd, void *parg)
+{
+	struct dvb_device *dvbdev = file->private_data;
+	struct dvb_frontend *fe = dvbdev->priv;
+	struct dvb_frontend_private *fepriv = fe->frontend_priv;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	int err = -ENOTTY;
+
+	switch (cmd) {
+	case FE_GET_INFO: {
+		struct dvb_frontend_info* info = parg;
+
+		memcpy(info, &fe->ops.info, sizeof(struct dvb_frontend_info));
+		dvb_frontend_get_frequency_limits(fe, &info->frequency_min, &info->frequency_max);
+
+		/*
+		 * Associate the 4 delivery systems supported by DVBv3
+		 * API with their DVBv5 counterpart. For the other standards,
+		 * use the closest type, assuming that it would hopefully
+		 * work with a DVBv3 application.
+		 * It should be noticed that, on multi-frontend devices with
+		 * different types (terrestrial and cable, for example),
+		 * a pure DVBv3 application won't be able to use all delivery
+		 * systems. Yet, changing the DVBv5 cache to the other delivery
+		 * system should be enough for making it work.
+		 */
+		switch (dvbv3_type(c->delivery_system)) {
+		case DVBV3_QPSK:
+			info->type = FE_QPSK;
+			break;
+		case DVBV3_ATSC:
+			info->type = FE_ATSC;
+			break;
+		case DVBV3_QAM:
+			info->type = FE_QAM;
+			break;
+		case DVBV3_OFDM:
+			info->type = FE_OFDM;
+			break;
+		default:
+			dev_err(fe->dvb->device,
+					"%s: doesn't know how to handle a DVBv3 call to delivery system %i\n",
+					__func__, c->delivery_system);
+			fe->ops.info.type = FE_OFDM;
+		}
+		dev_dbg(fe->dvb->device, "%s: current delivery system on cache: %d, V3 type: %d\n",
+				 __func__, c->delivery_system, fe->ops.info.type);
+
+		/* Force the CAN_INVERSION_AUTO bit on. If the frontend doesn't
+		 * do it, it is done for it. */
+		info->caps |= FE_CAN_INVERSION_AUTO;
+		err = 0;
+		break;
+	}
+
+	case FE_READ_STATUS: {
+		fe_status_t* status = parg;
+
+		/* if retune was requested but hasn't occurred yet, prevent
+		 * that user get signal state from previous tuning */
+		if (fepriv->state == FESTATE_RETUNE ||
+		    fepriv->state == FESTATE_ERROR) {
+			err=0;
+			*status = 0;
+			break;
+		}
+
+		if (fe->ops.read_status)
+			err = fe->ops.read_status(fe, status);
+		break;
+	}
+	case FE_READ_BER:
+		if (fe->ops.read_ber)
+			err = fe->ops.read_ber(fe, (__u32*) parg);
+		break;
+
+	case FE_READ_SIGNAL_STRENGTH:
+		if (fe->ops.read_signal_strength)
+			err = fe->ops.read_signal_strength(fe, (__u16*) parg);
+		break;
+
+	case FE_READ_SNR:
+		if (fe->ops.read_snr)
+			err = fe->ops.read_snr(fe, (__u16*) parg);
+		break;
+
+	case FE_READ_UNCORRECTED_BLOCKS:
+		if (fe->ops.read_ucblocks)
+			err = fe->ops.read_ucblocks(fe, (__u32*) parg);
+		break;
+
+
+	case FE_DISEQC_RESET_OVERLOAD:
+		if (fe->ops.diseqc_reset_overload) {
+			err = fe->ops.diseqc_reset_overload(fe);
+			fepriv->state = FESTATE_DISEQC;
+			fepriv->status = 0;
+		}
+		break;
+
+	case FE_DISEQC_SEND_MASTER_CMD:
+		if (fe->ops.diseqc_send_master_cmd) {
+			err = fe->ops.diseqc_send_master_cmd(fe, (struct dvb_diseqc_master_cmd*) parg);
+			fepriv->state = FESTATE_DISEQC;
+			fepriv->status = 0;
+		}
+		break;
+
+	case FE_DISEQC_SEND_BURST:
+		if (fe->ops.diseqc_send_burst) {
+			err = fe->ops.diseqc_send_burst(fe, (fe_sec_mini_cmd_t) parg);
+			fepriv->state = FESTATE_DISEQC;
+			fepriv->status = 0;
+		}
+		break;
+
+	case FE_SET_TONE:
+		if (fe->ops.set_tone) {
+			err = fe->ops.set_tone(fe, (fe_sec_tone_mode_t) parg);
+			fepriv->tone = (fe_sec_tone_mode_t) parg;
+			fepriv->state = FESTATE_DISEQC;
+			fepriv->status = 0;
+		}
+		break;
+
+	case FE_SET_VOLTAGE:
+		if (fe->ops.set_voltage) {
+			err = fe->ops.set_voltage(fe, (fe_sec_voltage_t) parg);
+			fepriv->voltage = (fe_sec_voltage_t) parg;
+			fepriv->state = FESTATE_DISEQC;
+			fepriv->status = 0;
+		}
+		break;
+
+	case FE_DISHNETWORK_SEND_LEGACY_CMD:
+		if (fe->ops.dishnetwork_send_legacy_command) {
+			err = fe->ops.dishnetwork_send_legacy_command(fe, (unsigned long) parg);
+			fepriv->state = FESTATE_DISEQC;
+			fepriv->status = 0;
+		} else if (fe->ops.set_voltage) {
+			/*
+			 * NOTE: This is a fallback condition.  Some frontends
+			 * (stv0299 for instance) take longer than 8msec to
+			 * respond to a set_voltage command.  Those switches
+			 * need custom routines to switch properly.  For all
+			 * other frontends, the following should work ok.
+			 * Dish network legacy switches (as used by Dish500)
+			 * are controlled by sending 9-bit command words
+			 * spaced 8msec apart.
+			 * the actual command word is switch/port dependent
+			 * so it is up to the userspace application to send
+			 * the right command.
+			 * The command must always start with a '0' after
+			 * initialization, so parg is 8 bits and does not
+			 * include the initialization or start bit
+			 */
+			unsigned long swcmd = ((unsigned long) parg) << 1;
+			struct timeval nexttime;
+			struct timeval tv[10];
+			int i;
+			u8 last = 1;
+			if (dvb_frontend_debug)
+				printk("%s switch command: 0x%04lx\n", __func__, swcmd);
+			do_gettimeofday(&nexttime);
+			if (dvb_frontend_debug)
+				memcpy(&tv[0], &nexttime, sizeof(struct timeval));
+			/* before sending a command, initialize by sending
+			 * a 32ms 18V to the switch
+			 */
+			fe->ops.set_voltage(fe, SEC_VOLTAGE_18);
+			dvb_frontend_sleep_until(&nexttime, 32000);
+
+			for (i = 0; i < 9; i++) {
+				if (dvb_frontend_debug)
+					do_gettimeofday(&tv[i + 1]);
+				if ((swcmd & 0x01) != last) {
+					/* set voltage to (last ? 13V : 18V) */
+					fe->ops.set_voltage(fe, (last) ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18);
+					last = (last) ? 0 : 1;
+				}
+				swcmd = swcmd >> 1;
+				if (i != 8)
+					dvb_frontend_sleep_until(&nexttime, 8000);
+			}
+			if (dvb_frontend_debug) {
+				printk("%s(%d): switch delay (should be 32k followed by all 8k\n",
+					__func__, fe->dvb->num);
+				for (i = 1; i < 10; i++)
+					printk("%d: %d\n", i, timeval_usec_diff(tv[i-1] , tv[i]));
+			}
+			err = 0;
+			fepriv->state = FESTATE_DISEQC;
+			fepriv->status = 0;
+		}
+		break;
+
+	case FE_DISEQC_RECV_SLAVE_REPLY:
+		if (fe->ops.diseqc_recv_slave_reply)
+			err = fe->ops.diseqc_recv_slave_reply(fe, (struct dvb_diseqc_slave_reply*) parg);
+		break;
+
+	case FE_ENABLE_HIGH_LNB_VOLTAGE:
+		if (fe->ops.enable_high_lnb_voltage)
+			err = fe->ops.enable_high_lnb_voltage(fe, (long) parg);
+		break;
+
+	case FE_SET_FRONTEND:
+		err = set_delivery_system(fe, SYS_UNDEFINED);
+		if (err)
+			break;
+
+		err = dtv_property_cache_sync(fe, c, parg);
+		if (err)
+			break;
+		err = dtv_set_frontend(fe);
+		break;
+	case FE_GET_EVENT:
+		err = dvb_frontend_get_event (fe, parg, file->f_flags);
+		break;
+
+	case FE_GET_FRONTEND:
+		err = dtv_get_frontend(fe, parg);
+		break;
+
+	case FE_SET_FRONTEND_TUNE_MODE:
+		fepriv->tune_mode_flags = (unsigned long) parg;
+		err = 0;
+		break;
+	};
+
+	return err;
+}
+
+
+static unsigned int dvb_frontend_poll(struct file *file, struct poll_table_struct *wait)
+{
+	struct dvb_device *dvbdev = file->private_data;
+	struct dvb_frontend *fe = dvbdev->priv;
+	struct dvb_frontend_private *fepriv = fe->frontend_priv;
+
+	dev_dbg_ratelimited(fe->dvb->device, "%s:\n", __func__);
+
+	poll_wait (file, &fepriv->events.wait_queue, wait);
+
+	if (fepriv->events.eventw != fepriv->events.eventr)
+		return (POLLIN | POLLRDNORM | POLLPRI);
+
+	return 0;
+}
+
+static int dvb_frontend_open(struct inode *inode, struct file *file)
+{
+	struct dvb_device *dvbdev = file->private_data;
+	struct dvb_frontend *fe = dvbdev->priv;
+	struct dvb_frontend_private *fepriv = fe->frontend_priv;
+	struct dvb_adapter *adapter = fe->dvb;
+	int ret;
+
+	dev_dbg(fe->dvb->device, "%s:\n", __func__);
+	if (fepriv->exit == DVB_FE_DEVICE_REMOVED)
+		return -ENODEV;
+
+	if (adapter->mfe_shared) {
+		mutex_lock (&adapter->mfe_lock);
+
+		if (adapter->mfe_dvbdev == NULL)
+			adapter->mfe_dvbdev = dvbdev;
+
+		else if (adapter->mfe_dvbdev != dvbdev) {
+			struct dvb_device
+				*mfedev = adapter->mfe_dvbdev;
+			struct dvb_frontend
+				*mfe = mfedev->priv;
+			struct dvb_frontend_private
+				*mfepriv = mfe->frontend_priv;
+			int mferetry = (dvb_mfe_wait_time << 1);
+
+			mutex_unlock (&adapter->mfe_lock);
+			while (mferetry-- && (mfedev->users != -1 ||
+					mfepriv->thread != NULL)) {
+				if(msleep_interruptible(500)) {
+					if(signal_pending(current))
+						return -EINTR;
+				}
+			}
+
+			mutex_lock (&adapter->mfe_lock);
+			if(adapter->mfe_dvbdev != dvbdev) {
+				mfedev = adapter->mfe_dvbdev;
+				mfe = mfedev->priv;
+				mfepriv = mfe->frontend_priv;
+				if (mfedev->users != -1 ||
+						mfepriv->thread != NULL) {
+					mutex_unlock (&adapter->mfe_lock);
+					return -EBUSY;
+				}
+				adapter->mfe_dvbdev = dvbdev;
+			}
+		}
+	}
+
+	if (dvbdev->users == -1 && fe->ops.ts_bus_ctrl) {
+		if ((ret = fe->ops.ts_bus_ctrl(fe, 1)) < 0)
+			goto err0;
+
+		/* If we took control of the bus, we need to force
+		   reinitialization.  This is because many ts_bus_ctrl()
+		   functions strobe the RESET pin on the demod, and if the
+		   frontend thread already exists then the dvb_init() routine
+		   won't get called (which is what usually does initial
+		   register configuration). */
+		fepriv->reinitialise = 1;
+	}
+
+	if ((ret = dvb_generic_open (inode, file)) < 0)
+		goto err1;
+
+	if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
+		/* normal tune mode when opened R/W */
+		fepriv->tune_mode_flags &= ~FE_TUNE_MODE_ONESHOT;
+		fepriv->tone = -1;
+		fepriv->voltage = -1;
+
+		ret = dvb_frontend_start (fe);
+		if (ret)
+			goto err2;
+
+		/*  empty event queue */
+		fepriv->events.eventr = fepriv->events.eventw = 0;
+	}
+
+	if (adapter->mfe_shared)
+		mutex_unlock (&adapter->mfe_lock);
+	return ret;
+
+err2:
+	dvb_generic_release(inode, file);
+err1:
+	if (dvbdev->users == -1 && fe->ops.ts_bus_ctrl)
+		fe->ops.ts_bus_ctrl(fe, 0);
+err0:
+	if (adapter->mfe_shared)
+		mutex_unlock (&adapter->mfe_lock);
+	return ret;
+}
+
+static int dvb_frontend_release(struct inode *inode, struct file *file)
+{
+	struct dvb_device *dvbdev = file->private_data;
+	struct dvb_frontend *fe = dvbdev->priv;
+	struct dvb_frontend_private *fepriv = fe->frontend_priv;
+	int ret;
+
+	dev_dbg(fe->dvb->device, "%s:\n", __func__);
+
+	if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
+		fepriv->release_jiffies = jiffies;
+		mb();
+	}
+
+	ret = dvb_generic_release (inode, file);
+
+	if (dvbdev->users == -1) {
+		wake_up(&fepriv->wait_queue);
+		if (fepriv->exit != DVB_FE_NO_EXIT) {
+			fops_put(file->f_op);
+			file->f_op = NULL;
+			wake_up(&dvbdev->wait_queue);
+		}
+		if (fe->ops.ts_bus_ctrl)
+			fe->ops.ts_bus_ctrl(fe, 0);
+	}
+
+	return ret;
+}
+
+static const struct file_operations dvb_frontend_fops = {
+	.owner		= THIS_MODULE,
+	.unlocked_ioctl	= dvb_generic_ioctl,
+	.poll		= dvb_frontend_poll,
+	.open		= dvb_frontend_open,
+	.release	= dvb_frontend_release,
+	.llseek		= noop_llseek,
+};
+
+int dvb_frontend_suspend(struct dvb_frontend *fe)
+{
+	int ret = 0;
+
+	dev_dbg(fe->dvb->device, "%s: adap=%d fe=%d\n", __func__, fe->dvb->num,
+			fe->id);
+
+	if (fe->ops.tuner_ops.sleep)
+		ret = fe->ops.tuner_ops.sleep(fe);
+
+	if (fe->ops.sleep)
+		ret = fe->ops.sleep(fe);
+
+	return ret;
+}
+EXPORT_SYMBOL(dvb_frontend_suspend);
+
+int dvb_frontend_resume(struct dvb_frontend *fe)
+{
+	struct dvb_frontend_private *fepriv = fe->frontend_priv;
+	int ret = 0;
+
+	dev_dbg(fe->dvb->device, "%s: adap=%d fe=%d\n", __func__, fe->dvb->num,
+			fe->id);
+
+	if (fe->ops.init)
+		ret = fe->ops.init(fe);
+
+	if (fe->ops.tuner_ops.init)
+		ret = fe->ops.tuner_ops.init(fe);
+
+	fepriv->state = FESTATE_RETUNE;
+	dvb_frontend_wakeup(fe);
+
+	return ret;
+}
+EXPORT_SYMBOL(dvb_frontend_resume);
+
+int dvb_register_frontend(struct dvb_adapter* dvb,
+			  struct dvb_frontend* fe)
+{
+	struct dvb_frontend_private *fepriv;
+	static const struct dvb_device dvbdev_template = {
+		.users = ~0,
+		.writers = 1,
+		.readers = (~0)-1,
+		.fops = &dvb_frontend_fops,
+		.kernel_ioctl = dvb_frontend_ioctl
+	};
+
+	dev_dbg(dvb->device, "%s:\n", __func__);
+
+	if (mutex_lock_interruptible(&frontend_mutex))
+		return -ERESTARTSYS;
+
+	fe->frontend_priv = kzalloc(sizeof(struct dvb_frontend_private), GFP_KERNEL);
+	if (fe->frontend_priv == NULL) {
+		mutex_unlock(&frontend_mutex);
+		return -ENOMEM;
+	}
+	fepriv = fe->frontend_priv;
+
+	sema_init(&fepriv->sem, 1);
+	init_waitqueue_head (&fepriv->wait_queue);
+	init_waitqueue_head (&fepriv->events.wait_queue);
+	mutex_init(&fepriv->events.mtx);
+	fe->dvb = dvb;
+	fepriv->inversion = INVERSION_OFF;
+
+	dev_info(fe->dvb->device,
+			"DVB: registering adapter %i frontend %i (%s)...\n",
+			fe->dvb->num, fe->id, fe->ops.info.name);
+
+	dvb_register_device (fe->dvb, &fepriv->dvbdev, &dvbdev_template,
+			     fe, DVB_DEVICE_FRONTEND);
+
+	/*
+	 * Initialize the cache to the proper values according with the
+	 * first supported delivery system (ops->delsys[0])
+	 */
+
+        fe->dtv_property_cache.delivery_system = fe->ops.delsys[0];
+	dvb_frontend_clear_cache(fe);
+
+	mutex_unlock(&frontend_mutex);
+	return 0;
+}
+EXPORT_SYMBOL(dvb_register_frontend);
+
+int dvb_unregister_frontend(struct dvb_frontend* fe)
+{
+	struct dvb_frontend_private *fepriv = fe->frontend_priv;
+	dev_dbg(fe->dvb->device, "%s:\n", __func__);
+
+	mutex_lock(&frontend_mutex);
+	dvb_frontend_stop (fe);
+	mutex_unlock(&frontend_mutex);
+
+	if (fepriv->dvbdev->users < -1)
+		wait_event(fepriv->dvbdev->wait_queue,
+				fepriv->dvbdev->users==-1);
+
+	mutex_lock(&frontend_mutex);
+	dvb_unregister_device (fepriv->dvbdev);
+
+	/* fe is invalid now */
+	kfree(fepriv);
+	mutex_unlock(&frontend_mutex);
+	return 0;
+}
+EXPORT_SYMBOL(dvb_unregister_frontend);
+
+#ifdef CONFIG_MEDIA_ATTACH
+void dvb_frontend_detach(struct dvb_frontend* fe)
+{
+	void *ptr;
+
+	if (fe->ops.release_sec) {
+		fe->ops.release_sec(fe);
+		symbol_put_addr(fe->ops.release_sec);
+	}
+	if (fe->ops.tuner_ops.release) {
+		fe->ops.tuner_ops.release(fe);
+		symbol_put_addr(fe->ops.tuner_ops.release);
+	}
+	if (fe->ops.analog_ops.release) {
+		fe->ops.analog_ops.release(fe);
+		symbol_put_addr(fe->ops.analog_ops.release);
+	}
+	ptr = (void*)fe->ops.release;
+	if (ptr) {
+		fe->ops.release(fe);
+		symbol_put_addr(ptr);
+	}
+}
+#else
+void dvb_frontend_detach(struct dvb_frontend* fe)
+{
+	if (fe->ops.release_sec)
+		fe->ops.release_sec(fe);
+	if (fe->ops.tuner_ops.release)
+		fe->ops.tuner_ops.release(fe);
+	if (fe->ops.analog_ops.release)
+		fe->ops.analog_ops.release(fe);
+	if (fe->ops.release)
+		fe->ops.release(fe);
+}
+#endif
+EXPORT_SYMBOL(dvb_frontend_detach);
diff --git a/drivers/media/dvb-core/dvb_frontend.h b/drivers/media/dvb-core/dvb_frontend.h
new file mode 100644
index 0000000..33996a0
--- /dev/null
+++ b/drivers/media/dvb-core/dvb_frontend.h
@@ -0,0 +1,424 @@
+/*
+ * dvb_frontend.h
+ *
+ * Copyright (C) 2001 convergence integrated media GmbH
+ * Copyright (C) 2004 convergence GmbH
+ *
+ * Written by Ralph Metzler
+ * Overhauled by Holger Waechtler
+ * Kernel I2C stuff by Michael Hunold <hunold@convergence.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public 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 _DVB_FRONTEND_H_
+#define _DVB_FRONTEND_H_
+
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/ioctl.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+
+#include <linux/dvb/frontend.h>
+
+#include "dvbdev.h"
+
+/*
+ * Maximum number of Delivery systems per frontend. It
+ * should be smaller or equal to 32
+ */
+#define MAX_DELSYS	8
+
+struct dvb_frontend_tune_settings {
+	int min_delay_ms;
+	int step_size;
+	int max_drift;
+};
+
+struct dvb_frontend;
+
+struct dvb_tuner_info {
+	char name[128];
+
+	u32 frequency_min;
+	u32 frequency_max;
+	u32 frequency_step;
+
+	u32 bandwidth_min;
+	u32 bandwidth_max;
+	u32 bandwidth_step;
+};
+
+struct analog_parameters {
+	unsigned int frequency;
+	unsigned int mode;
+	unsigned int audmode;
+	u64 std;
+};
+
+enum dvbfe_modcod {
+	DVBFE_MODCOD_DUMMY_PLFRAME	= 0,
+	DVBFE_MODCOD_QPSK_1_4,
+	DVBFE_MODCOD_QPSK_1_3,
+	DVBFE_MODCOD_QPSK_2_5,
+	DVBFE_MODCOD_QPSK_1_2,
+	DVBFE_MODCOD_QPSK_3_5,
+	DVBFE_MODCOD_QPSK_2_3,
+	DVBFE_MODCOD_QPSK_3_4,
+	DVBFE_MODCOD_QPSK_4_5,
+	DVBFE_MODCOD_QPSK_5_6,
+	DVBFE_MODCOD_QPSK_8_9,
+	DVBFE_MODCOD_QPSK_9_10,
+	DVBFE_MODCOD_8PSK_3_5,
+	DVBFE_MODCOD_8PSK_2_3,
+	DVBFE_MODCOD_8PSK_3_4,
+	DVBFE_MODCOD_8PSK_5_6,
+	DVBFE_MODCOD_8PSK_8_9,
+	DVBFE_MODCOD_8PSK_9_10,
+	DVBFE_MODCOD_16APSK_2_3,
+	DVBFE_MODCOD_16APSK_3_4,
+	DVBFE_MODCOD_16APSK_4_5,
+	DVBFE_MODCOD_16APSK_5_6,
+	DVBFE_MODCOD_16APSK_8_9,
+	DVBFE_MODCOD_16APSK_9_10,
+	DVBFE_MODCOD_32APSK_3_4,
+	DVBFE_MODCOD_32APSK_4_5,
+	DVBFE_MODCOD_32APSK_5_6,
+	DVBFE_MODCOD_32APSK_8_9,
+	DVBFE_MODCOD_32APSK_9_10,
+	DVBFE_MODCOD_RESERVED_1,
+	DVBFE_MODCOD_BPSK_1_3,
+	DVBFE_MODCOD_BPSK_1_4,
+	DVBFE_MODCOD_RESERVED_2
+};
+
+enum tuner_param {
+	DVBFE_TUNER_FREQUENCY		= (1 <<  0),
+	DVBFE_TUNER_TUNERSTEP		= (1 <<  1),
+	DVBFE_TUNER_IFFREQ		= (1 <<  2),
+	DVBFE_TUNER_BANDWIDTH		= (1 <<  3),
+	DVBFE_TUNER_REFCLOCK		= (1 <<  4),
+	DVBFE_TUNER_IQSENSE		= (1 <<  5),
+	DVBFE_TUNER_DUMMY		= (1 << 31)
+};
+
+/*
+ * ALGO_HW: (Hardware Algorithm)
+ * ----------------------------------------------------------------
+ * Devices that support this algorithm do everything in hardware
+ * and no software support is needed to handle them.
+ * Requesting these devices to LOCK is the only thing required,
+ * device is supposed to do everything in the hardware.
+ *
+ * ALGO_SW: (Software Algorithm)
+ * ----------------------------------------------------------------
+ * These are dumb devices, that require software to do everything
+ *
+ * ALGO_CUSTOM: (Customizable Agorithm)
+ * ----------------------------------------------------------------
+ * Devices having this algorithm can be customized to have specific
+ * algorithms in the frontend driver, rather than simply doing a
+ * software zig-zag. In this case the zigzag maybe hardware assisted
+ * or it maybe completely done in hardware. In all cases, usage of
+ * this algorithm, in conjunction with the search and track
+ * callbacks, utilizes the driver specific algorithm.
+ *
+ * ALGO_RECOVERY: (Recovery Algorithm)
+ * ----------------------------------------------------------------
+ * These devices have AUTO recovery capabilities from LOCK failure
+ */
+enum dvbfe_algo {
+	DVBFE_ALGO_HW			= (1 <<  0),
+	DVBFE_ALGO_SW			= (1 <<  1),
+	DVBFE_ALGO_CUSTOM		= (1 <<  2),
+	DVBFE_ALGO_RECOVERY		= (1 << 31)
+};
+
+struct tuner_state {
+	u32 frequency;
+	u32 tunerstep;
+	u32 ifreq;
+	u32 bandwidth;
+	u32 iqsense;
+	u32 refclock;
+};
+
+/*
+ * search callback possible return status
+ *
+ * DVBFE_ALGO_SEARCH_SUCCESS
+ * The frontend search algorithm completed and returned successfully
+ *
+ * DVBFE_ALGO_SEARCH_ASLEEP
+ * The frontend search algorithm is sleeping
+ *
+ * DVBFE_ALGO_SEARCH_FAILED
+ * The frontend search for a signal failed
+ *
+ * DVBFE_ALGO_SEARCH_INVALID
+ * The frontend search algorith was probably supplied with invalid
+ * parameters and the search is an invalid one
+ *
+ * DVBFE_ALGO_SEARCH_ERROR
+ * The frontend search algorithm failed due to some error
+ *
+ * DVBFE_ALGO_SEARCH_AGAIN
+ * The frontend search algorithm was requested to search again
+ */
+enum dvbfe_search {
+	DVBFE_ALGO_SEARCH_SUCCESS	= (1 <<  0),
+	DVBFE_ALGO_SEARCH_ASLEEP	= (1 <<  1),
+	DVBFE_ALGO_SEARCH_FAILED	= (1 <<  2),
+	DVBFE_ALGO_SEARCH_INVALID	= (1 <<  3),
+	DVBFE_ALGO_SEARCH_AGAIN		= (1 <<  4),
+	DVBFE_ALGO_SEARCH_ERROR		= (1 << 31),
+};
+
+
+struct dvb_tuner_ops {
+
+	struct dvb_tuner_info info;
+
+	int (*release)(struct dvb_frontend *fe);
+	int (*init)(struct dvb_frontend *fe);
+	int (*sleep)(struct dvb_frontend *fe);
+
+	/** This is for simple PLLs - set all parameters in one go. */
+	int (*set_params)(struct dvb_frontend *fe);
+	int (*set_analog_params)(struct dvb_frontend *fe, struct analog_parameters *p);
+
+	/** This is support for demods like the mt352 - fills out the supplied buffer with what to write. */
+	int (*calc_regs)(struct dvb_frontend *fe, u8 *buf, int buf_len);
+
+	/** This is to allow setting tuner-specific configs */
+	int (*set_config)(struct dvb_frontend *fe, void *priv_cfg);
+
+	int (*get_frequency)(struct dvb_frontend *fe, u32 *frequency);
+	int (*get_bandwidth)(struct dvb_frontend *fe, u32 *bandwidth);
+	int (*get_if_frequency)(struct dvb_frontend *fe, u32 *frequency);
+
+#define TUNER_STATUS_LOCKED 1
+#define TUNER_STATUS_STEREO 2
+	int (*get_status)(struct dvb_frontend *fe, u32 *status);
+	int (*get_rf_strength)(struct dvb_frontend *fe, u16 *strength);
+	int (*get_afc)(struct dvb_frontend *fe, s32 *afc);
+
+	/** These are provided separately from set_params in order to facilitate silicon
+	 * tuners which require sophisticated tuning loops, controlling each parameter separately. */
+	int (*set_frequency)(struct dvb_frontend *fe, u32 frequency);
+	int (*set_bandwidth)(struct dvb_frontend *fe, u32 bandwidth);
+
+	/*
+	 * These are provided separately from set_params in order to facilitate silicon
+	 * tuners which require sophisticated tuning loops, controlling each parameter separately.
+	 */
+	int (*set_state)(struct dvb_frontend *fe, enum tuner_param param, struct tuner_state *state);
+	int (*get_state)(struct dvb_frontend *fe, enum tuner_param param, struct tuner_state *state);
+};
+
+struct analog_demod_info {
+	char *name;
+};
+
+struct analog_demod_ops {
+
+	struct analog_demod_info info;
+
+	void (*set_params)(struct dvb_frontend *fe,
+			   struct analog_parameters *params);
+	int  (*has_signal)(struct dvb_frontend *fe);
+	int  (*get_afc)(struct dvb_frontend *fe);
+	void (*tuner_status)(struct dvb_frontend *fe);
+	void (*standby)(struct dvb_frontend *fe);
+	void (*release)(struct dvb_frontend *fe);
+	int  (*i2c_gate_ctrl)(struct dvb_frontend *fe, int enable);
+
+	/** This is to allow setting tuner-specific configuration */
+	int (*set_config)(struct dvb_frontend *fe, void *priv_cfg);
+};
+
+struct dtv_frontend_properties;
+
+struct dvb_frontend_ops {
+
+	struct dvb_frontend_info info;
+
+	u8 delsys[MAX_DELSYS];
+
+	void (*release)(struct dvb_frontend* fe);
+	void (*release_sec)(struct dvb_frontend* fe);
+
+	int (*init)(struct dvb_frontend* fe);
+	int (*sleep)(struct dvb_frontend* fe);
+
+	int (*write)(struct dvb_frontend* fe, const u8 buf[], int len);
+
+	/* if this is set, it overrides the default swzigzag */
+	int (*tune)(struct dvb_frontend* fe,
+		    bool re_tune,
+		    unsigned int mode_flags,
+		    unsigned int *delay,
+		    fe_status_t *status);
+	/* get frontend tuning algorithm from the module */
+	enum dvbfe_algo (*get_frontend_algo)(struct dvb_frontend *fe);
+
+	/* these two are only used for the swzigzag code */
+	int (*set_frontend)(struct dvb_frontend *fe);
+	int (*get_tune_settings)(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* settings);
+
+	int (*get_frontend)(struct dvb_frontend *fe);
+
+	int (*read_status)(struct dvb_frontend* fe, fe_status_t* status);
+	int (*read_ber)(struct dvb_frontend* fe, u32* ber);
+	int (*read_signal_strength)(struct dvb_frontend* fe, u16* strength);
+	int (*read_snr)(struct dvb_frontend* fe, u16* snr);
+	int (*read_ucblocks)(struct dvb_frontend* fe, u32* ucblocks);
+
+	int (*diseqc_reset_overload)(struct dvb_frontend* fe);
+	int (*diseqc_send_master_cmd)(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd);
+	int (*diseqc_recv_slave_reply)(struct dvb_frontend* fe, struct dvb_diseqc_slave_reply* reply);
+	int (*diseqc_send_burst)(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd);
+	int (*set_tone)(struct dvb_frontend* fe, fe_sec_tone_mode_t tone);
+	int (*set_voltage)(struct dvb_frontend* fe, fe_sec_voltage_t voltage);
+	int (*enable_high_lnb_voltage)(struct dvb_frontend* fe, long arg);
+	int (*dishnetwork_send_legacy_command)(struct dvb_frontend* fe, unsigned long cmd);
+	int (*i2c_gate_ctrl)(struct dvb_frontend* fe, int enable);
+	int (*ts_bus_ctrl)(struct dvb_frontend* fe, int acquire);
+
+	/* These callbacks are for devices that implement their own
+	 * tuning algorithms, rather than a simple swzigzag
+	 */
+	enum dvbfe_search (*search)(struct dvb_frontend *fe);
+
+	struct dvb_tuner_ops tuner_ops;
+	struct analog_demod_ops analog_ops;
+
+	int (*set_property)(struct dvb_frontend* fe, struct dtv_property* tvp);
+	int (*get_property)(struct dvb_frontend* fe, struct dtv_property* tvp);
+};
+
+#ifdef __DVB_CORE__
+#define MAX_EVENT 8
+
+struct dvb_fe_events {
+	struct dvb_frontend_event events[MAX_EVENT];
+	int			  eventw;
+	int			  eventr;
+	int			  overflow;
+	wait_queue_head_t	  wait_queue;
+	struct mutex		  mtx;
+};
+#endif
+
+struct dtv_frontend_properties {
+
+	/* Cache State */
+	u32			state;
+
+	u32			frequency;
+	fe_modulation_t		modulation;
+
+	fe_sec_voltage_t	voltage;
+	fe_sec_tone_mode_t	sectone;
+	fe_spectral_inversion_t	inversion;
+	fe_code_rate_t		fec_inner;
+	fe_transmit_mode_t	transmission_mode;
+	u32			bandwidth_hz;	/* 0 = AUTO */
+	fe_guard_interval_t	guard_interval;
+	fe_hierarchy_t		hierarchy;
+	u32			symbol_rate;
+	fe_code_rate_t		code_rate_HP;
+	fe_code_rate_t		code_rate_LP;
+
+	fe_pilot_t		pilot;
+	fe_rolloff_t		rolloff;
+
+	fe_delivery_system_t	delivery_system;
+
+	enum fe_interleaving	interleaving;
+
+	/* ISDB-T specifics */
+	u8			isdbt_partial_reception;
+	u8			isdbt_sb_mode;
+	u8			isdbt_sb_subchannel;
+	u32			isdbt_sb_segment_idx;
+	u32			isdbt_sb_segment_count;
+	u8			isdbt_layer_enabled;
+	struct {
+	    u8			segment_count;
+	    fe_code_rate_t	fec;
+	    fe_modulation_t	modulation;
+	    u8			interleaving;
+	} layer[3];
+
+	/* Multistream specifics */
+	u32			stream_id;
+
+	/* ATSC-MH specifics */
+	u8			atscmh_fic_ver;
+	u8			atscmh_parade_id;
+	u8			atscmh_nog;
+	u8			atscmh_tnog;
+	u8			atscmh_sgn;
+	u8			atscmh_prc;
+
+	u8			atscmh_rs_frame_mode;
+	u8			atscmh_rs_frame_ensemble;
+	u8			atscmh_rs_code_mode_pri;
+	u8			atscmh_rs_code_mode_sec;
+	u8			atscmh_sccc_block_mode;
+	u8			atscmh_sccc_code_mode_a;
+	u8			atscmh_sccc_code_mode_b;
+	u8			atscmh_sccc_code_mode_c;
+	u8			atscmh_sccc_code_mode_d;
+};
+
+struct dvb_frontend {
+	struct dvb_frontend_ops ops;
+	struct dvb_adapter *dvb;
+	void *demodulator_priv;
+	void *tuner_priv;
+	void *frontend_priv;
+	void *sec_priv;
+	void *analog_demod_priv;
+	struct dtv_frontend_properties dtv_property_cache;
+#define DVB_FRONTEND_COMPONENT_TUNER 0
+#define DVB_FRONTEND_COMPONENT_DEMOD 1
+	int (*callback)(void *adapter_priv, int component, int cmd, int arg);
+	int id;
+};
+
+extern int dvb_register_frontend(struct dvb_adapter *dvb,
+				 struct dvb_frontend *fe);
+
+extern int dvb_unregister_frontend(struct dvb_frontend *fe);
+
+extern void dvb_frontend_detach(struct dvb_frontend *fe);
+
+extern void dvb_frontend_reinitialise(struct dvb_frontend *fe);
+extern int dvb_frontend_suspend(struct dvb_frontend *fe);
+extern int dvb_frontend_resume(struct dvb_frontend *fe);
+
+extern void dvb_frontend_sleep_until(struct timeval *waketime, u32 add_usec);
+extern s32 timeval_usec_diff(struct timeval lasttime, struct timeval curtime);
+
+#endif
diff --git a/drivers/media/dvb-core/dvb_math.c b/drivers/media/dvb-core/dvb_math.c
new file mode 100644
index 0000000..beb7c93
--- /dev/null
+++ b/drivers/media/dvb-core/dvb_math.c
@@ -0,0 +1,145 @@
+/*
+ * dvb-math provides some complex fixed-point math
+ * operations shared between the dvb related stuff
+ *
+ * Copyright (C) 2006 Christoph Pfister (christophpfister@gmail.com)
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/bitops.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <asm/bug.h>
+#include "dvb_math.h"
+
+static const unsigned short logtable[256] = {
+	0x0000, 0x0171, 0x02e0, 0x044e, 0x05ba, 0x0725, 0x088e, 0x09f7,
+	0x0b5d, 0x0cc3, 0x0e27, 0x0f8a, 0x10eb, 0x124b, 0x13aa, 0x1508,
+	0x1664, 0x17bf, 0x1919, 0x1a71, 0x1bc8, 0x1d1e, 0x1e73, 0x1fc6,
+	0x2119, 0x226a, 0x23ba, 0x2508, 0x2656, 0x27a2, 0x28ed, 0x2a37,
+	0x2b80, 0x2cc8, 0x2e0f, 0x2f54, 0x3098, 0x31dc, 0x331e, 0x345f,
+	0x359f, 0x36de, 0x381b, 0x3958, 0x3a94, 0x3bce, 0x3d08, 0x3e41,
+	0x3f78, 0x40af, 0x41e4, 0x4319, 0x444c, 0x457f, 0x46b0, 0x47e1,
+	0x4910, 0x4a3f, 0x4b6c, 0x4c99, 0x4dc5, 0x4eef, 0x5019, 0x5142,
+	0x526a, 0x5391, 0x54b7, 0x55dc, 0x5700, 0x5824, 0x5946, 0x5a68,
+	0x5b89, 0x5ca8, 0x5dc7, 0x5ee5, 0x6003, 0x611f, 0x623a, 0x6355,
+	0x646f, 0x6588, 0x66a0, 0x67b7, 0x68ce, 0x69e4, 0x6af8, 0x6c0c,
+	0x6d20, 0x6e32, 0x6f44, 0x7055, 0x7165, 0x7274, 0x7383, 0x7490,
+	0x759d, 0x76aa, 0x77b5, 0x78c0, 0x79ca, 0x7ad3, 0x7bdb, 0x7ce3,
+	0x7dea, 0x7ef0, 0x7ff6, 0x80fb, 0x81ff, 0x8302, 0x8405, 0x8507,
+	0x8608, 0x8709, 0x8809, 0x8908, 0x8a06, 0x8b04, 0x8c01, 0x8cfe,
+	0x8dfa, 0x8ef5, 0x8fef, 0x90e9, 0x91e2, 0x92db, 0x93d2, 0x94ca,
+	0x95c0, 0x96b6, 0x97ab, 0x98a0, 0x9994, 0x9a87, 0x9b7a, 0x9c6c,
+	0x9d5e, 0x9e4f, 0x9f3f, 0xa02e, 0xa11e, 0xa20c, 0xa2fa, 0xa3e7,
+	0xa4d4, 0xa5c0, 0xa6ab, 0xa796, 0xa881, 0xa96a, 0xaa53, 0xab3c,
+	0xac24, 0xad0c, 0xadf2, 0xaed9, 0xafbe, 0xb0a4, 0xb188, 0xb26c,
+	0xb350, 0xb433, 0xb515, 0xb5f7, 0xb6d9, 0xb7ba, 0xb89a, 0xb97a,
+	0xba59, 0xbb38, 0xbc16, 0xbcf4, 0xbdd1, 0xbead, 0xbf8a, 0xc065,
+	0xc140, 0xc21b, 0xc2f5, 0xc3cf, 0xc4a8, 0xc580, 0xc658, 0xc730,
+	0xc807, 0xc8de, 0xc9b4, 0xca8a, 0xcb5f, 0xcc34, 0xcd08, 0xcddc,
+	0xceaf, 0xcf82, 0xd054, 0xd126, 0xd1f7, 0xd2c8, 0xd399, 0xd469,
+	0xd538, 0xd607, 0xd6d6, 0xd7a4, 0xd872, 0xd93f, 0xda0c, 0xdad9,
+	0xdba5, 0xdc70, 0xdd3b, 0xde06, 0xded0, 0xdf9a, 0xe063, 0xe12c,
+	0xe1f5, 0xe2bd, 0xe385, 0xe44c, 0xe513, 0xe5d9, 0xe69f, 0xe765,
+	0xe82a, 0xe8ef, 0xe9b3, 0xea77, 0xeb3b, 0xebfe, 0xecc1, 0xed83,
+	0xee45, 0xef06, 0xefc8, 0xf088, 0xf149, 0xf209, 0xf2c8, 0xf387,
+	0xf446, 0xf505, 0xf5c3, 0xf680, 0xf73e, 0xf7fb, 0xf8b7, 0xf973,
+	0xfa2f, 0xfaea, 0xfba5, 0xfc60, 0xfd1a, 0xfdd4, 0xfe8e, 0xff47
+};
+
+unsigned int intlog2(u32 value)
+{
+	/**
+	 *	returns: log2(value) * 2^24
+	 *	wrong result if value = 0 (log2(0) is undefined)
+	 */
+	unsigned int msb;
+	unsigned int logentry;
+	unsigned int significand;
+	unsigned int interpolation;
+
+	if (unlikely(value == 0)) {
+		WARN_ON(1);
+		return 0;
+	}
+
+	/* first detect the msb (count begins at 0) */
+	msb = fls(value) - 1;
+
+	/**
+	 *	now we use a logtable after the following method:
+	 *
+	 *	log2(2^x * y) * 2^24 = x * 2^24 + log2(y) * 2^24
+	 *	where x = msb and therefore 1 <= y < 2
+	 *	first y is determined by shifting the value left
+	 *	so that msb is bit 31
+	 *		0x00231f56 -> 0x8C7D5800
+	 *	the result is y * 2^31 -> "significand"
+	 *	then the highest 9 bits are used for a table lookup
+	 *	the highest bit is discarded because it's always set
+	 *	the highest nine bits in our example are 100011000
+	 *	so we would use the entry 0x18
+	 */
+	significand = value << (31 - msb);
+	logentry = (significand >> 23) & 0xff;
+
+	/**
+	 *	last step we do is interpolation because of the
+	 *	limitations of the log table the error is that part of
+	 *	the significand which isn't used for lookup then we
+	 *	compute the ratio between the error and the next table entry
+	 *	and interpolate it between the log table entry used and the
+	 *	next one the biggest error possible is 0x7fffff
+	 *	(in our example it's 0x7D5800)
+	 *	needed value for next table entry is 0x800000
+	 *	so the interpolation is
+	 *	(error / 0x800000) * (logtable_next - logtable_current)
+	 *	in the implementation the division is moved to the end for
+	 *	better accuracy there is also an overflow correction if
+	 *	logtable_next is 256
+	 */
+	interpolation = ((significand & 0x7fffff) *
+			((logtable[(logentry + 1) & 0xff] -
+			  logtable[logentry]) & 0xffff)) >> 15;
+
+	/* now we return the result */
+	return ((msb << 24) + (logtable[logentry] << 8) + interpolation);
+}
+EXPORT_SYMBOL(intlog2);
+
+unsigned int intlog10(u32 value)
+{
+	/**
+	 *	returns: log10(value) * 2^24
+	 *	wrong result if value = 0 (log10(0) is undefined)
+	 */
+	u64 log;
+
+	if (unlikely(value == 0)) {
+		WARN_ON(1);
+		return 0;
+	}
+
+	log = intlog2(value);
+
+	/**
+	 *	we use the following method:
+	 *	log10(x) = log2(x) * log10(2)
+	 */
+
+	return (log * 646456993) >> 31;
+}
+EXPORT_SYMBOL(intlog10);
diff --git a/drivers/media/dvb-core/dvb_math.h b/drivers/media/dvb-core/dvb_math.h
new file mode 100644
index 0000000..aecc867
--- /dev/null
+++ b/drivers/media/dvb-core/dvb_math.h
@@ -0,0 +1,58 @@
+/*
+ * dvb-math provides some complex fixed-point math
+ * operations shared between the dvb related stuff
+ *
+ * Copyright (C) 2006 Christoph Pfister (christophpfister@gmail.com)
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __DVB_MATH_H
+#define __DVB_MATH_H
+
+#include <linux/types.h>
+
+/**
+ * computes log2 of a value; the result is shifted left by 24 bits
+ *
+ * to use rational values you can use the following method:
+ *   intlog2(value) = intlog2(value * 2^x) - x * 2^24
+ *
+ * example: intlog2(8) will give 3 << 24 = 3 * 2^24
+ * example: intlog2(9) will give 3 << 24 + ... = 3.16... * 2^24
+ * example: intlog2(1.5) = intlog2(3) - 2^24 = 0.584... * 2^24
+ *
+ * @param value The value (must be != 0)
+ * @return log2(value) * 2^24
+ */
+extern unsigned int intlog2(u32 value);
+
+/**
+ * computes log10 of a value; the result is shifted left by 24 bits
+ *
+ * to use rational values you can use the following method:
+ *   intlog10(value) = intlog10(value * 10^x) - x * 2^24
+ *
+ * example: intlog10(1000) will give 3 << 24 = 3 * 2^24
+ *   due to the implementation intlog10(1000) might be not exactly 3 * 2^24
+ *
+ * look at intlog2 for similar examples
+ *
+ * @param value The value (must be != 0)
+ * @return log10(value) * 2^24
+ */
+extern unsigned int intlog10(u32 value);
+
+#endif
diff --git a/drivers/media/dvb-core/dvb_net.c b/drivers/media/dvb-core/dvb_net.c
new file mode 100644
index 0000000..c211768
--- /dev/null
+++ b/drivers/media/dvb-core/dvb_net.c
@@ -0,0 +1,1516 @@
+/*
+ * dvb_net.c
+ *
+ * Copyright (C) 2001 Convergence integrated media GmbH
+ *                    Ralph Metzler <ralph@convergence.de>
+ * Copyright (C) 2002 Ralph Metzler <rjkm@metzlerbros.de>
+ *
+ * ULE Decapsulation code:
+ * Copyright (C) 2003, 2004 gcs - Global Communication & Services GmbH.
+ *                      and Department of Scientific Computing
+ *                          Paris Lodron University of Salzburg.
+ *                          Hilmar Linder <hlinder@cosy.sbg.ac.at>
+ *                      and Wolfram Stering <wstering@cosy.sbg.ac.at>
+ *
+ * ULE Decaps according to RFC 4326.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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.
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ */
+
+/*
+ * ULE ChangeLog:
+ * Feb 2004: hl/ws v1: Implementing draft-fair-ipdvb-ule-01.txt
+ *
+ * Dec 2004: hl/ws v2: Implementing draft-ietf-ipdvb-ule-03.txt:
+ *                       ULE Extension header handling.
+ *                     Bugreports by Moritz Vieth and Hanno Tersteegen,
+ *                       Fraunhofer Institute for Open Communication Systems
+ *                       Competence Center for Advanced Satellite Communications.
+ *                     Bugfixes and robustness improvements.
+ *                     Filtering on dest MAC addresses, if present (D-Bit = 0)
+ *                     ULE_DEBUG compile-time option.
+ * Apr 2006: cp v3:    Bugfixes and compliency with RFC 4326 (ULE) by
+ *                       Christian Praehauser <cpraehaus@cosy.sbg.ac.at>,
+ *                       Paris Lodron University of Salzburg.
+ */
+
+/*
+ * FIXME / TODO (dvb_net.c):
+ *
+ * Unloading does not work for 2.6.9 kernels: a refcount doesn't go to zero.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/dvb/net.h>
+#include <linux/uio.h>
+#include <asm/uaccess.h>
+#include <linux/crc32.h>
+#include <linux/mutex.h>
+#include <linux/sched.h>
+
+#include "dvb_demux.h"
+#include "dvb_net.h"
+
+static int dvb_net_debug;
+module_param(dvb_net_debug, int, 0444);
+MODULE_PARM_DESC(dvb_net_debug, "enable debug messages");
+
+#define dprintk(x...) do { if (dvb_net_debug) printk(x); } while (0)
+
+
+static inline __u32 iov_crc32( __u32 c, struct kvec *iov, unsigned int cnt )
+{
+	unsigned int j;
+	for (j = 0; j < cnt; j++)
+		c = crc32_be( c, iov[j].iov_base, iov[j].iov_len );
+	return c;
+}
+
+
+#define DVB_NET_MULTICAST_MAX 10
+
+#undef ULE_DEBUG
+
+#ifdef ULE_DEBUG
+
+#define MAC_ADDR_PRINTFMT "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x"
+#define MAX_ADDR_PRINTFMT_ARGS(macap) (macap)[0],(macap)[1],(macap)[2],(macap)[3],(macap)[4],(macap)[5]
+
+#define isprint(c)	((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'))
+
+static void hexdump( const unsigned char *buf, unsigned short len )
+{
+	char str[80], octet[10];
+	int ofs, i, l;
+
+	for (ofs = 0; ofs < len; ofs += 16) {
+		sprintf( str, "%03d: ", ofs );
+
+		for (i = 0; i < 16; i++) {
+			if ((i + ofs) < len)
+				sprintf( octet, "%02x ", buf[ofs + i] );
+			else
+				strcpy( octet, "   " );
+
+			strcat( str, octet );
+		}
+		strcat( str, "  " );
+		l = strlen( str );
+
+		for (i = 0; (i < 16) && ((i + ofs) < len); i++)
+			str[l++] = isprint( buf[ofs + i] ) ? buf[ofs + i] : '.';
+
+		str[l] = '\0';
+		printk( KERN_WARNING "%s\n", str );
+	}
+}
+
+#endif
+
+struct dvb_net_priv {
+	int in_use;
+	u16 pid;
+	struct net_device *net;
+	struct dvb_net *host;
+	struct dmx_demux *demux;
+	struct dmx_section_feed *secfeed;
+	struct dmx_section_filter *secfilter;
+	struct dmx_ts_feed *tsfeed;
+	int multi_num;
+	struct dmx_section_filter *multi_secfilter[DVB_NET_MULTICAST_MAX];
+	unsigned char multi_macs[DVB_NET_MULTICAST_MAX][6];
+	int rx_mode;
+#define RX_MODE_UNI 0
+#define RX_MODE_MULTI 1
+#define RX_MODE_ALL_MULTI 2
+#define RX_MODE_PROMISC 3
+	struct work_struct set_multicast_list_wq;
+	struct work_struct restart_net_feed_wq;
+	unsigned char feedtype;			/* Either FEED_TYPE_ or FEED_TYPE_ULE */
+	int need_pusi;				/* Set to 1, if synchronization on PUSI required. */
+	unsigned char tscc;			/* TS continuity counter after sync on PUSI. */
+	struct sk_buff *ule_skb;		/* ULE SNDU decodes into this buffer. */
+	unsigned char *ule_next_hdr;		/* Pointer into skb to next ULE extension header. */
+	unsigned short ule_sndu_len;		/* ULE SNDU length in bytes, w/o D-Bit. */
+	unsigned short ule_sndu_type;		/* ULE SNDU type field, complete. */
+	unsigned char ule_sndu_type_1;		/* ULE SNDU type field, if split across 2 TS cells. */
+	unsigned char ule_dbit;			/* Whether the DestMAC address present
+						 * or not (bit is set). */
+	unsigned char ule_bridged;		/* Whether the ULE_BRIDGED extension header was found. */
+	int ule_sndu_remain;			/* Nr. of bytes still required for current ULE SNDU. */
+	unsigned long ts_count;			/* Current ts cell counter. */
+	struct mutex mutex;
+};
+
+
+/**
+ *	Determine the packet's protocol ID. The rule here is that we
+ *	assume 802.3 if the type field is short enough to be a length.
+ *	This is normal practice and works for any 'now in use' protocol.
+ *
+ *  stolen from eth.c out of the linux kernel, hacked for dvb-device
+ *  by Michael Holzt <kju@debian.org>
+ */
+static __be16 dvb_net_eth_type_trans(struct sk_buff *skb,
+				      struct net_device *dev)
+{
+	struct ethhdr *eth;
+	unsigned char *rawp;
+
+	skb_reset_mac_header(skb);
+	skb_pull(skb,dev->hard_header_len);
+	eth = eth_hdr(skb);
+
+	if (*eth->h_dest & 1) {
+		if(memcmp(eth->h_dest,dev->broadcast, ETH_ALEN)==0)
+			skb->pkt_type=PACKET_BROADCAST;
+		else
+			skb->pkt_type=PACKET_MULTICAST;
+	}
+
+	if (ntohs(eth->h_proto) >= 1536)
+		return eth->h_proto;
+
+	rawp = skb->data;
+
+	/**
+	 *	This is a magic hack to spot IPX packets. Older Novell breaks
+	 *	the protocol design and runs IPX over 802.3 without an 802.2 LLC
+	 *	layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This
+	 *	won't work for fault tolerant netware but does for the rest.
+	 */
+	if (*(unsigned short *)rawp == 0xFFFF)
+		return htons(ETH_P_802_3);
+
+	/**
+	 *	Real 802.2 LLC
+	 */
+	return htons(ETH_P_802_2);
+}
+
+#define TS_SZ	188
+#define TS_SYNC	0x47
+#define TS_TEI	0x80
+#define TS_SC	0xC0
+#define TS_PUSI	0x40
+#define TS_AF_A	0x20
+#define TS_AF_D	0x10
+
+/* ULE Extension Header handlers. */
+
+#define ULE_TEST	0
+#define ULE_BRIDGED	1
+
+#define ULE_OPTEXTHDR_PADDING 0
+
+static int ule_test_sndu( struct dvb_net_priv *p )
+{
+	return -1;
+}
+
+static int ule_bridged_sndu( struct dvb_net_priv *p )
+{
+	struct ethhdr *hdr = (struct ethhdr*) p->ule_next_hdr;
+	if(ntohs(hdr->h_proto) < 1536) {
+		int framelen = p->ule_sndu_len - ((p->ule_next_hdr+sizeof(struct ethhdr)) - p->ule_skb->data);
+		/* A frame Type < 1536 for a bridged frame, introduces a LLC Length field. */
+		if(framelen != ntohs(hdr->h_proto)) {
+			return -1;
+		}
+	}
+	/* Note:
+	 * From RFC4326:
+	 *  "A bridged SNDU is a Mandatory Extension Header of Type 1.
+	 *   It must be the final (or only) extension header specified in the header chain of a SNDU."
+	 * The 'ule_bridged' flag will cause the extension header processing loop to terminate.
+	 */
+	p->ule_bridged = 1;
+	return 0;
+}
+
+static int ule_exthdr_padding(struct dvb_net_priv *p)
+{
+	return 0;
+}
+
+/** Handle ULE extension headers.
+ *  Function is called after a successful CRC32 verification of an ULE SNDU to complete its decoding.
+ *  Returns: >= 0: nr. of bytes consumed by next extension header
+ *	     -1:   Mandatory extension header that is not recognized or TEST SNDU; discard.
+ */
+static int handle_one_ule_extension( struct dvb_net_priv *p )
+{
+	/* Table of mandatory extension header handlers.  The header type is the index. */
+	static int (*ule_mandatory_ext_handlers[255])( struct dvb_net_priv *p ) =
+		{ [0] = ule_test_sndu, [1] = ule_bridged_sndu, [2] = NULL,  };
+
+	/* Table of optional extension header handlers.  The header type is the index. */
+	static int (*ule_optional_ext_handlers[255])( struct dvb_net_priv *p ) =
+		{ [0] = ule_exthdr_padding, [1] = NULL, };
+
+	int ext_len = 0;
+	unsigned char hlen = (p->ule_sndu_type & 0x0700) >> 8;
+	unsigned char htype = p->ule_sndu_type & 0x00FF;
+
+	/* Discriminate mandatory and optional extension headers. */
+	if (hlen == 0) {
+		/* Mandatory extension header */
+		if (ule_mandatory_ext_handlers[htype]) {
+			ext_len = ule_mandatory_ext_handlers[htype]( p );
+			if(ext_len >= 0) {
+				p->ule_next_hdr += ext_len;
+				if (!p->ule_bridged) {
+					p->ule_sndu_type = ntohs(*(__be16 *)p->ule_next_hdr);
+					p->ule_next_hdr += 2;
+				} else {
+					p->ule_sndu_type = ntohs(*(__be16 *)(p->ule_next_hdr + ((p->ule_dbit ? 2 : 3) * ETH_ALEN)));
+					/* This assures the extension handling loop will terminate. */
+				}
+			}
+			// else: extension handler failed or SNDU should be discarded
+		} else
+			ext_len = -1;	/* SNDU has to be discarded. */
+	} else {
+		/* Optional extension header.  Calculate the length. */
+		ext_len = hlen << 1;
+		/* Process the optional extension header according to its type. */
+		if (ule_optional_ext_handlers[htype])
+			(void)ule_optional_ext_handlers[htype]( p );
+		p->ule_next_hdr += ext_len;
+		p->ule_sndu_type = ntohs( *(__be16 *)(p->ule_next_hdr-2) );
+		/*
+		 * note: the length of the next header type is included in the
+		 * length of THIS optional extension header
+		 */
+	}
+
+	return ext_len;
+}
+
+static int handle_ule_extensions( struct dvb_net_priv *p )
+{
+	int total_ext_len = 0, l;
+
+	p->ule_next_hdr = p->ule_skb->data;
+	do {
+		l = handle_one_ule_extension( p );
+		if (l < 0)
+			return l;	/* Stop extension header processing and discard SNDU. */
+		total_ext_len += l;
+#ifdef ULE_DEBUG
+		dprintk("handle_ule_extensions: ule_next_hdr=%p, ule_sndu_type=%i, "
+			"l=%i, total_ext_len=%i\n", p->ule_next_hdr,
+			(int) p->ule_sndu_type, l, total_ext_len);
+#endif
+
+	} while (p->ule_sndu_type < 1536);
+
+	return total_ext_len;
+}
+
+
+/** Prepare for a new ULE SNDU: reset the decoder state. */
+static inline void reset_ule( struct dvb_net_priv *p )
+{
+	p->ule_skb = NULL;
+	p->ule_next_hdr = NULL;
+	p->ule_sndu_len = 0;
+	p->ule_sndu_type = 0;
+	p->ule_sndu_type_1 = 0;
+	p->ule_sndu_remain = 0;
+	p->ule_dbit = 0xFF;
+	p->ule_bridged = 0;
+}
+
+/**
+ * Decode ULE SNDUs according to draft-ietf-ipdvb-ule-03.txt from a sequence of
+ * TS cells of a single PID.
+ */
+static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
+{
+	struct dvb_net_priv *priv = netdev_priv(dev);
+	unsigned long skipped = 0L;
+	const u8 *ts, *ts_end, *from_where = NULL;
+	u8 ts_remain = 0, how_much = 0, new_ts = 1;
+	struct ethhdr *ethh = NULL;
+	bool error = false;
+
+#ifdef ULE_DEBUG
+	/* The code inside ULE_DEBUG keeps a history of the last 100 TS cells processed. */
+	static unsigned char ule_hist[100*TS_SZ];
+	static unsigned char *ule_where = ule_hist, ule_dump;
+#endif
+
+	/* For all TS cells in current buffer.
+	 * Appearently, we are called for every single TS cell.
+	 */
+	for (ts = buf, ts_end = buf + buf_len; ts < ts_end; /* no default incr. */ ) {
+
+		if (new_ts) {
+			/* We are about to process a new TS cell. */
+
+#ifdef ULE_DEBUG
+			if (ule_where >= &ule_hist[100*TS_SZ]) ule_where = ule_hist;
+			memcpy( ule_where, ts, TS_SZ );
+			if (ule_dump) {
+				hexdump( ule_where, TS_SZ );
+				ule_dump = 0;
+			}
+			ule_where += TS_SZ;
+#endif
+
+			/* Check TS error conditions: sync_byte, transport_error_indicator, scrambling_control . */
+			if ((ts[0] != TS_SYNC) || (ts[1] & TS_TEI) || ((ts[3] & TS_SC) != 0)) {
+				printk(KERN_WARNING "%lu: Invalid TS cell: SYNC %#x, TEI %u, SC %#x.\n",
+				       priv->ts_count, ts[0], ts[1] & TS_TEI >> 7, ts[3] & 0xC0 >> 6);
+
+				/* Drop partly decoded SNDU, reset state, resync on PUSI. */
+				if (priv->ule_skb) {
+					dev_kfree_skb( priv->ule_skb );
+					/* Prepare for next SNDU. */
+					dev->stats.rx_errors++;
+					dev->stats.rx_frame_errors++;
+				}
+				reset_ule(priv);
+				priv->need_pusi = 1;
+
+				/* Continue with next TS cell. */
+				ts += TS_SZ;
+				priv->ts_count++;
+				continue;
+			}
+
+			ts_remain = 184;
+			from_where = ts + 4;
+		}
+		/* Synchronize on PUSI, if required. */
+		if (priv->need_pusi) {
+			if (ts[1] & TS_PUSI) {
+				/* Find beginning of first ULE SNDU in current TS cell. */
+				/* Synchronize continuity counter. */
+				priv->tscc = ts[3] & 0x0F;
+				/* There is a pointer field here. */
+				if (ts[4] > ts_remain) {
+					printk(KERN_ERR "%lu: Invalid ULE packet "
+					       "(pointer field %d)\n", priv->ts_count, ts[4]);
+					ts += TS_SZ;
+					priv->ts_count++;
+					continue;
+				}
+				/* Skip to destination of pointer field. */
+				from_where = &ts[5] + ts[4];
+				ts_remain -= 1 + ts[4];
+				skipped = 0;
+			} else {
+				skipped++;
+				ts += TS_SZ;
+				priv->ts_count++;
+				continue;
+			}
+		}
+
+		if (new_ts) {
+			/* Check continuity counter. */
+			if ((ts[3] & 0x0F) == priv->tscc)
+				priv->tscc = (priv->tscc + 1) & 0x0F;
+			else {
+				/* TS discontinuity handling: */
+				printk(KERN_WARNING "%lu: TS discontinuity: got %#x, "
+				       "expected %#x.\n", priv->ts_count, ts[3] & 0x0F, priv->tscc);
+				/* Drop partly decoded SNDU, reset state, resync on PUSI. */
+				if (priv->ule_skb) {
+					dev_kfree_skb( priv->ule_skb );
+					/* Prepare for next SNDU. */
+					// reset_ule(priv);  moved to below.
+					dev->stats.rx_errors++;
+					dev->stats.rx_frame_errors++;
+				}
+				reset_ule(priv);
+				/* skip to next PUSI. */
+				priv->need_pusi = 1;
+				continue;
+			}
+			/* If we still have an incomplete payload, but PUSI is
+			 * set; some TS cells are missing.
+			 * This is only possible here, if we missed exactly 16 TS
+			 * cells (continuity counter wrap). */
+			if (ts[1] & TS_PUSI) {
+				if (! priv->need_pusi) {
+					if (!(*from_where < (ts_remain-1)) || *from_where != priv->ule_sndu_remain) {
+						/* Pointer field is invalid.  Drop this TS cell and any started ULE SNDU. */
+						printk(KERN_WARNING "%lu: Invalid pointer "
+						       "field: %u.\n", priv->ts_count, *from_where);
+
+						/* Drop partly decoded SNDU, reset state, resync on PUSI. */
+						if (priv->ule_skb) {
+							error = true;
+							dev_kfree_skb(priv->ule_skb);
+						}
+
+						if (error || priv->ule_sndu_remain) {
+							dev->stats.rx_errors++;
+							dev->stats.rx_frame_errors++;
+							error = false;
+						}
+
+						reset_ule(priv);
+						priv->need_pusi = 1;
+						continue;
+					}
+					/* Skip pointer field (we're processing a
+					 * packed payload). */
+					from_where += 1;
+					ts_remain -= 1;
+				} else
+					priv->need_pusi = 0;
+
+				if (priv->ule_sndu_remain > 183) {
+					/* Current SNDU lacks more data than there could be available in the
+					 * current TS cell. */
+					dev->stats.rx_errors++;
+					dev->stats.rx_length_errors++;
+					printk(KERN_WARNING "%lu: Expected %d more SNDU bytes, but "
+					       "got PUSI (pf %d, ts_remain %d).  Flushing incomplete payload.\n",
+					       priv->ts_count, priv->ule_sndu_remain, ts[4], ts_remain);
+					dev_kfree_skb(priv->ule_skb);
+					/* Prepare for next SNDU. */
+					reset_ule(priv);
+					/* Resync: go to where pointer field points to: start of next ULE SNDU. */
+					from_where += ts[4];
+					ts_remain -= ts[4];
+				}
+			}
+		}
+
+		/* Check if new payload needs to be started. */
+		if (priv->ule_skb == NULL) {
+			/* Start a new payload with skb.
+			 * Find ULE header.  It is only guaranteed that the
+			 * length field (2 bytes) is contained in the current
+			 * TS.
+			 * Check ts_remain has to be >= 2 here. */
+			if (ts_remain < 2) {
+				printk(KERN_WARNING "Invalid payload packing: only %d "
+				       "bytes left in TS.  Resyncing.\n", ts_remain);
+				priv->ule_sndu_len = 0;
+				priv->need_pusi = 1;
+				ts += TS_SZ;
+				continue;
+			}
+
+			if (! priv->ule_sndu_len) {
+				/* Got at least two bytes, thus extrace the SNDU length. */
+				priv->ule_sndu_len = from_where[0] << 8 | from_where[1];
+				if (priv->ule_sndu_len & 0x8000) {
+					/* D-Bit is set: no dest mac present. */
+					priv->ule_sndu_len &= 0x7FFF;
+					priv->ule_dbit = 1;
+				} else
+					priv->ule_dbit = 0;
+
+				if (priv->ule_sndu_len < 5) {
+					printk(KERN_WARNING "%lu: Invalid ULE SNDU length %u. "
+					       "Resyncing.\n", priv->ts_count, priv->ule_sndu_len);
+					dev->stats.rx_errors++;
+					dev->stats.rx_length_errors++;
+					priv->ule_sndu_len = 0;
+					priv->need_pusi = 1;
+					new_ts = 1;
+					ts += TS_SZ;
+					priv->ts_count++;
+					continue;
+				}
+				ts_remain -= 2;	/* consume the 2 bytes SNDU length. */
+				from_where += 2;
+			}
+
+			priv->ule_sndu_remain = priv->ule_sndu_len + 2;
+			/*
+			 * State of current TS:
+			 *   ts_remain (remaining bytes in the current TS cell)
+			 *   0	ule_type is not available now, we need the next TS cell
+			 *   1	the first byte of the ule_type is present
+			 * >=2	full ULE header present, maybe some payload data as well.
+			 */
+			switch (ts_remain) {
+				case 1:
+					priv->ule_sndu_remain--;
+					priv->ule_sndu_type = from_where[0] << 8;
+					priv->ule_sndu_type_1 = 1; /* first byte of ule_type is set. */
+					ts_remain -= 1; from_where += 1;
+					/* Continue w/ next TS. */
+				case 0:
+					new_ts = 1;
+					ts += TS_SZ;
+					priv->ts_count++;
+					continue;
+
+				default: /* complete ULE header is present in current TS. */
+					/* Extract ULE type field. */
+					if (priv->ule_sndu_type_1) {
+						priv->ule_sndu_type_1 = 0;
+						priv->ule_sndu_type |= from_where[0];
+						from_where += 1; /* points to payload start. */
+						ts_remain -= 1;
+					} else {
+						/* Complete type is present in new TS. */
+						priv->ule_sndu_type = from_where[0] << 8 | from_where[1];
+						from_where += 2; /* points to payload start. */
+						ts_remain -= 2;
+					}
+					break;
+			}
+
+			/* Allocate the skb (decoder target buffer) with the correct size, as follows:
+			 * prepare for the largest case: bridged SNDU with MAC address (dbit = 0). */
+			priv->ule_skb = dev_alloc_skb( priv->ule_sndu_len + ETH_HLEN + ETH_ALEN );
+			if (priv->ule_skb == NULL) {
+				printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n",
+				       dev->name);
+				dev->stats.rx_dropped++;
+				return;
+			}
+
+			/* This includes the CRC32 _and_ dest mac, if !dbit. */
+			priv->ule_sndu_remain = priv->ule_sndu_len;
+			priv->ule_skb->dev = dev;
+			/* Leave space for Ethernet or bridged SNDU header (eth hdr plus one MAC addr). */
+			skb_reserve( priv->ule_skb, ETH_HLEN + ETH_ALEN );
+		}
+
+		/* Copy data into our current skb. */
+		how_much = min(priv->ule_sndu_remain, (int)ts_remain);
+		memcpy(skb_put(priv->ule_skb, how_much), from_where, how_much);
+		priv->ule_sndu_remain -= how_much;
+		ts_remain -= how_much;
+		from_where += how_much;
+
+		/* Check for complete payload. */
+		if (priv->ule_sndu_remain <= 0) {
+			/* Check CRC32, we've got it in our skb already. */
+			__be16 ulen = htons(priv->ule_sndu_len);
+			__be16 utype = htons(priv->ule_sndu_type);
+			const u8 *tail;
+			struct kvec iov[3] = {
+				{ &ulen, sizeof ulen },
+				{ &utype, sizeof utype },
+				{ priv->ule_skb->data, priv->ule_skb->len - 4 }
+			};
+			u32 ule_crc = ~0L, expected_crc;
+			if (priv->ule_dbit) {
+				/* Set D-bit for CRC32 verification,
+				 * if it was set originally. */
+				ulen |= htons(0x8000);
+			}
+
+			ule_crc = iov_crc32(ule_crc, iov, 3);
+			tail = skb_tail_pointer(priv->ule_skb);
+			expected_crc = *(tail - 4) << 24 |
+				       *(tail - 3) << 16 |
+				       *(tail - 2) << 8 |
+				       *(tail - 1);
+			if (ule_crc != expected_crc) {
+				printk(KERN_WARNING "%lu: CRC32 check FAILED: %08x / %08x, SNDU len %d type %#x, ts_remain %d, next 2: %x.\n",
+				       priv->ts_count, ule_crc, expected_crc, priv->ule_sndu_len, priv->ule_sndu_type, ts_remain, ts_remain > 2 ? *(unsigned short *)from_where : 0);
+
+#ifdef ULE_DEBUG
+				hexdump( iov[0].iov_base, iov[0].iov_len );
+				hexdump( iov[1].iov_base, iov[1].iov_len );
+				hexdump( iov[2].iov_base, iov[2].iov_len );
+
+				if (ule_where == ule_hist) {
+					hexdump( &ule_hist[98*TS_SZ], TS_SZ );
+					hexdump( &ule_hist[99*TS_SZ], TS_SZ );
+				} else if (ule_where == &ule_hist[TS_SZ]) {
+					hexdump( &ule_hist[99*TS_SZ], TS_SZ );
+					hexdump( ule_hist, TS_SZ );
+				} else {
+					hexdump( ule_where - TS_SZ - TS_SZ, TS_SZ );
+					hexdump( ule_where - TS_SZ, TS_SZ );
+				}
+				ule_dump = 1;
+#endif
+
+				dev->stats.rx_errors++;
+				dev->stats.rx_crc_errors++;
+				dev_kfree_skb(priv->ule_skb);
+			} else {
+				/* CRC32 verified OK. */
+				u8 dest_addr[ETH_ALEN];
+				static const u8 bc_addr[ETH_ALEN] =
+					{ [ 0 ... ETH_ALEN-1] = 0xff };
+
+				/* CRC32 was OK. Remove it from skb. */
+				priv->ule_skb->tail -= 4;
+				priv->ule_skb->len -= 4;
+
+				if (!priv->ule_dbit) {
+					/*
+					 * The destination MAC address is the
+					 * next data in the skb.  It comes
+					 * before any extension headers.
+					 *
+					 * Check if the payload of this SNDU
+					 * should be passed up the stack.
+					 */
+					register int drop = 0;
+					if (priv->rx_mode != RX_MODE_PROMISC) {
+						if (priv->ule_skb->data[0] & 0x01) {
+							/* multicast or broadcast */
+							if (memcmp(priv->ule_skb->data, bc_addr, ETH_ALEN)) {
+								/* multicast */
+								if (priv->rx_mode == RX_MODE_MULTI) {
+									int i;
+									for(i = 0; i < priv->multi_num && memcmp(priv->ule_skb->data, priv->multi_macs[i], ETH_ALEN); i++)
+										;
+									if (i == priv->multi_num)
+										drop = 1;
+								} else if (priv->rx_mode != RX_MODE_ALL_MULTI)
+									drop = 1; /* no broadcast; */
+								/* else: all multicast mode: accept all multicast packets */
+							}
+							/* else: broadcast */
+						}
+						else if (memcmp(priv->ule_skb->data, dev->dev_addr, ETH_ALEN))
+							drop = 1;
+						/* else: destination address matches the MAC address of our receiver device */
+					}
+					/* else: promiscuous mode; pass everything up the stack */
+
+					if (drop) {
+#ifdef ULE_DEBUG
+						dprintk("Dropping SNDU: MAC destination address does not match: dest addr: "MAC_ADDR_PRINTFMT", dev addr: "MAC_ADDR_PRINTFMT"\n",
+							MAX_ADDR_PRINTFMT_ARGS(priv->ule_skb->data), MAX_ADDR_PRINTFMT_ARGS(dev->dev_addr));
+#endif
+						dev_kfree_skb(priv->ule_skb);
+						goto sndu_done;
+					}
+					else
+					{
+						skb_copy_from_linear_data(priv->ule_skb,
+							      dest_addr,
+							      ETH_ALEN);
+						skb_pull(priv->ule_skb, ETH_ALEN);
+					}
+				}
+
+				/* Handle ULE Extension Headers. */
+				if (priv->ule_sndu_type < 1536) {
+					/* There is an extension header.  Handle it accordingly. */
+					int l = handle_ule_extensions(priv);
+					if (l < 0) {
+						/* Mandatory extension header unknown or TEST SNDU.  Drop it. */
+						// printk( KERN_WARNING "Dropping SNDU, extension headers.\n" );
+						dev_kfree_skb(priv->ule_skb);
+						goto sndu_done;
+					}
+					skb_pull(priv->ule_skb, l);
+				}
+
+				/*
+				 * Construct/assure correct ethernet header.
+				 * Note: in bridged mode (priv->ule_bridged !=
+				 * 0) we already have the (original) ethernet
+				 * header at the start of the payload (after
+				 * optional dest. address and any extension
+				 * headers).
+				 */
+
+				if (!priv->ule_bridged) {
+					skb_push(priv->ule_skb, ETH_HLEN);
+					ethh = (struct ethhdr *)priv->ule_skb->data;
+					if (!priv->ule_dbit) {
+						 /* dest_addr buffer is only valid if priv->ule_dbit == 0 */
+						memcpy(ethh->h_dest, dest_addr, ETH_ALEN);
+						memset(ethh->h_source, 0, ETH_ALEN);
+					}
+					else /* zeroize source and dest */
+						memset( ethh, 0, ETH_ALEN*2 );
+
+					ethh->h_proto = htons(priv->ule_sndu_type);
+				}
+				/* else:  skb is in correct state; nothing to do. */
+				priv->ule_bridged = 0;
+
+				/* Stuff into kernel's protocol stack. */
+				priv->ule_skb->protocol = dvb_net_eth_type_trans(priv->ule_skb, dev);
+				/* If D-bit is set (i.e. destination MAC address not present),
+				 * receive the packet anyhow. */
+				/* if (priv->ule_dbit && skb->pkt_type == PACKET_OTHERHOST)
+					priv->ule_skb->pkt_type = PACKET_HOST; */
+				dev->stats.rx_packets++;
+				dev->stats.rx_bytes += priv->ule_skb->len;
+				netif_rx(priv->ule_skb);
+			}
+			sndu_done:
+			/* Prepare for next SNDU. */
+			reset_ule(priv);
+		}
+
+		/* More data in current TS (look at the bytes following the CRC32)? */
+		if (ts_remain >= 2 && *((unsigned short *)from_where) != 0xFFFF) {
+			/* Next ULE SNDU starts right there. */
+			new_ts = 0;
+			priv->ule_skb = NULL;
+			priv->ule_sndu_type_1 = 0;
+			priv->ule_sndu_len = 0;
+			// printk(KERN_WARNING "More data in current TS: [%#x %#x %#x %#x]\n",
+			//	*(from_where + 0), *(from_where + 1),
+			//	*(from_where + 2), *(from_where + 3));
+			// printk(KERN_WARNING "ts @ %p, stopped @ %p:\n", ts, from_where + 0);
+			// hexdump(ts, 188);
+		} else {
+			new_ts = 1;
+			ts += TS_SZ;
+			priv->ts_count++;
+			if (priv->ule_skb == NULL) {
+				priv->need_pusi = 1;
+				priv->ule_sndu_type_1 = 0;
+				priv->ule_sndu_len = 0;
+			}
+		}
+	}	/* for all available TS cells */
+}
+
+static int dvb_net_ts_callback(const u8 *buffer1, size_t buffer1_len,
+			       const u8 *buffer2, size_t buffer2_len,
+			       struct dmx_ts_feed *feed, enum dmx_success success)
+{
+	struct net_device *dev = feed->priv;
+
+	if (buffer2)
+		printk(KERN_WARNING "buffer2 not NULL: %p.\n", buffer2);
+	if (buffer1_len > 32768)
+		printk(KERN_WARNING "length > 32k: %zu.\n", buffer1_len);
+	/* printk("TS callback: %u bytes, %u TS cells @ %p.\n",
+		  buffer1_len, buffer1_len / TS_SZ, buffer1); */
+	dvb_net_ule(dev, buffer1, buffer1_len);
+	return 0;
+}
+
+
+static void dvb_net_sec(struct net_device *dev,
+			const u8 *pkt, int pkt_len)
+{
+	u8 *eth;
+	struct sk_buff *skb;
+	struct net_device_stats *stats = &dev->stats;
+	int snap = 0;
+
+	/* note: pkt_len includes a 32bit checksum */
+	if (pkt_len < 16) {
+		printk("%s: IP/MPE packet length = %d too small.\n",
+			dev->name, pkt_len);
+		stats->rx_errors++;
+		stats->rx_length_errors++;
+		return;
+	}
+/* it seems some ISPs manage to screw up here, so we have to
+ * relax the error checks... */
+#if 0
+	if ((pkt[5] & 0xfd) != 0xc1) {
+		/* drop scrambled or broken packets */
+#else
+	if ((pkt[5] & 0x3c) != 0x00) {
+		/* drop scrambled */
+#endif
+		stats->rx_errors++;
+		stats->rx_crc_errors++;
+		return;
+	}
+	if (pkt[5] & 0x02) {
+		/* handle LLC/SNAP, see rfc-1042 */
+		if (pkt_len < 24 || memcmp(&pkt[12], "\xaa\xaa\x03\0\0\0", 6)) {
+			stats->rx_dropped++;
+			return;
+		}
+		snap = 8;
+	}
+	if (pkt[7]) {
+		/* FIXME: assemble datagram from multiple sections */
+		stats->rx_errors++;
+		stats->rx_frame_errors++;
+		return;
+	}
+
+	/* we have 14 byte ethernet header (ip header follows);
+	 * 12 byte MPE header; 4 byte checksum; + 2 byte alignment, 8 byte LLC/SNAP
+	 */
+	if (!(skb = dev_alloc_skb(pkt_len - 4 - 12 + 14 + 2 - snap))) {
+		//printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name);
+		stats->rx_dropped++;
+		return;
+	}
+	skb_reserve(skb, 2);    /* longword align L3 header */
+	skb->dev = dev;
+
+	/* copy L3 payload */
+	eth = (u8 *) skb_put(skb, pkt_len - 12 - 4 + 14 - snap);
+	memcpy(eth + 14, pkt + 12 + snap, pkt_len - 12 - 4 - snap);
+
+	/* create ethernet header: */
+	eth[0]=pkt[0x0b];
+	eth[1]=pkt[0x0a];
+	eth[2]=pkt[0x09];
+	eth[3]=pkt[0x08];
+	eth[4]=pkt[0x04];
+	eth[5]=pkt[0x03];
+
+	eth[6]=eth[7]=eth[8]=eth[9]=eth[10]=eth[11]=0;
+
+	if (snap) {
+		eth[12] = pkt[18];
+		eth[13] = pkt[19];
+	} else {
+		/* protocol numbers are from rfc-1700 or
+		 * http://www.iana.org/assignments/ethernet-numbers
+		 */
+		if (pkt[12] >> 4 == 6) { /* version field from IP header */
+			eth[12] = 0x86;	/* IPv6 */
+			eth[13] = 0xdd;
+		} else {
+			eth[12] = 0x08;	/* IPv4 */
+			eth[13] = 0x00;
+		}
+	}
+
+	skb->protocol = dvb_net_eth_type_trans(skb, dev);
+
+	stats->rx_packets++;
+	stats->rx_bytes+=skb->len;
+	netif_rx(skb);
+}
+
+static int dvb_net_sec_callback(const u8 *buffer1, size_t buffer1_len,
+		 const u8 *buffer2, size_t buffer2_len,
+		 struct dmx_section_filter *filter,
+		 enum dmx_success success)
+{
+	struct net_device *dev = filter->priv;
+
+	/**
+	 * we rely on the DVB API definition where exactly one complete
+	 * section is delivered in buffer1
+	 */
+	dvb_net_sec (dev, buffer1, buffer1_len);
+	return 0;
+}
+
+static int dvb_net_tx(struct sk_buff *skb, struct net_device *dev)
+{
+	dev_kfree_skb(skb);
+	return NETDEV_TX_OK;
+}
+
+static u8 mask_normal[6]={0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+static u8 mask_allmulti[6]={0xff, 0xff, 0xff, 0x00, 0x00, 0x00};
+static u8 mac_allmulti[6]={0x01, 0x00, 0x5e, 0x00, 0x00, 0x00};
+static u8 mask_promisc[6]={0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+static int dvb_net_filter_sec_set(struct net_device *dev,
+		   struct dmx_section_filter **secfilter,
+		   u8 *mac, u8 *mac_mask)
+{
+	struct dvb_net_priv *priv = netdev_priv(dev);
+	int ret;
+
+	*secfilter=NULL;
+	ret = priv->secfeed->allocate_filter(priv->secfeed, secfilter);
+	if (ret<0) {
+		printk("%s: could not get filter\n", dev->name);
+		return ret;
+	}
+
+	(*secfilter)->priv=(void *) dev;
+
+	memset((*secfilter)->filter_value, 0x00, DMX_MAX_FILTER_SIZE);
+	memset((*secfilter)->filter_mask,  0x00, DMX_MAX_FILTER_SIZE);
+	memset((*secfilter)->filter_mode,  0xff, DMX_MAX_FILTER_SIZE);
+
+	(*secfilter)->filter_value[0]=0x3e;
+	(*secfilter)->filter_value[3]=mac[5];
+	(*secfilter)->filter_value[4]=mac[4];
+	(*secfilter)->filter_value[8]=mac[3];
+	(*secfilter)->filter_value[9]=mac[2];
+	(*secfilter)->filter_value[10]=mac[1];
+	(*secfilter)->filter_value[11]=mac[0];
+
+	(*secfilter)->filter_mask[0] = 0xff;
+	(*secfilter)->filter_mask[3] = mac_mask[5];
+	(*secfilter)->filter_mask[4] = mac_mask[4];
+	(*secfilter)->filter_mask[8] = mac_mask[3];
+	(*secfilter)->filter_mask[9] = mac_mask[2];
+	(*secfilter)->filter_mask[10] = mac_mask[1];
+	(*secfilter)->filter_mask[11]=mac_mask[0];
+
+	dprintk("%s: filter mac=%pM\n", dev->name, mac);
+	dprintk("%s: filter mask=%pM\n", dev->name, mac_mask);
+
+	return 0;
+}
+
+static int dvb_net_feed_start(struct net_device *dev)
+{
+	int ret = 0, i;
+	struct dvb_net_priv *priv = netdev_priv(dev);
+	struct dmx_demux *demux = priv->demux;
+	unsigned char *mac = (unsigned char *) dev->dev_addr;
+
+	dprintk("%s: rx_mode %i\n", __func__, priv->rx_mode);
+	mutex_lock(&priv->mutex);
+	if (priv->tsfeed || priv->secfeed || priv->secfilter || priv->multi_secfilter[0])
+		printk("%s: BUG %d\n", __func__, __LINE__);
+
+	priv->secfeed=NULL;
+	priv->secfilter=NULL;
+	priv->tsfeed = NULL;
+
+	if (priv->feedtype == DVB_NET_FEEDTYPE_MPE) {
+		dprintk("%s: alloc secfeed\n", __func__);
+		ret=demux->allocate_section_feed(demux, &priv->secfeed,
+					 dvb_net_sec_callback);
+		if (ret<0) {
+			printk("%s: could not allocate section feed\n", dev->name);
+			goto error;
+		}
+
+		ret = priv->secfeed->set(priv->secfeed, priv->pid, 32768, 1);
+
+		if (ret<0) {
+			printk("%s: could not set section feed\n", dev->name);
+			priv->demux->release_section_feed(priv->demux, priv->secfeed);
+			priv->secfeed=NULL;
+			goto error;
+		}
+
+		if (priv->rx_mode != RX_MODE_PROMISC) {
+			dprintk("%s: set secfilter\n", __func__);
+			dvb_net_filter_sec_set(dev, &priv->secfilter, mac, mask_normal);
+		}
+
+		switch (priv->rx_mode) {
+		case RX_MODE_MULTI:
+			for (i = 0; i < priv->multi_num; i++) {
+				dprintk("%s: set multi_secfilter[%d]\n", __func__, i);
+				dvb_net_filter_sec_set(dev, &priv->multi_secfilter[i],
+						       priv->multi_macs[i], mask_normal);
+			}
+			break;
+		case RX_MODE_ALL_MULTI:
+			priv->multi_num=1;
+			dprintk("%s: set multi_secfilter[0]\n", __func__);
+			dvb_net_filter_sec_set(dev, &priv->multi_secfilter[0],
+					       mac_allmulti, mask_allmulti);
+			break;
+		case RX_MODE_PROMISC:
+			priv->multi_num=0;
+			dprintk("%s: set secfilter\n", __func__);
+			dvb_net_filter_sec_set(dev, &priv->secfilter, mac, mask_promisc);
+			break;
+		}
+
+		dprintk("%s: start filtering\n", __func__);
+		priv->secfeed->start_filtering(priv->secfeed);
+	} else if (priv->feedtype == DVB_NET_FEEDTYPE_ULE) {
+		struct timespec timeout = { 0, 10000000 }; // 10 msec
+
+		/* we have payloads encapsulated in TS */
+		dprintk("%s: alloc tsfeed\n", __func__);
+		ret = demux->allocate_ts_feed(demux, &priv->tsfeed, dvb_net_ts_callback);
+		if (ret < 0) {
+			printk("%s: could not allocate ts feed\n", dev->name);
+			goto error;
+		}
+
+		/* Set netdevice pointer for ts decaps callback. */
+		priv->tsfeed->priv = (void *)dev;
+		ret = priv->tsfeed->set(priv->tsfeed,
+					priv->pid, /* pid */
+					TS_PACKET, /* type */
+					DMX_TS_PES_OTHER, /* pes type */
+					32768,     /* circular buffer size */
+					timeout    /* timeout */
+					);
+
+		if (ret < 0) {
+			printk("%s: could not set ts feed\n", dev->name);
+			priv->demux->release_ts_feed(priv->demux, priv->tsfeed);
+			priv->tsfeed = NULL;
+			goto error;
+		}
+
+		dprintk("%s: start filtering\n", __func__);
+		priv->tsfeed->start_filtering(priv->tsfeed);
+	} else
+		ret = -EINVAL;
+
+error:
+	mutex_unlock(&priv->mutex);
+	return ret;
+}
+
+static int dvb_net_feed_stop(struct net_device *dev)
+{
+	struct dvb_net_priv *priv = netdev_priv(dev);
+	int i, ret = 0;
+
+	dprintk("%s\n", __func__);
+	mutex_lock(&priv->mutex);
+	if (priv->feedtype == DVB_NET_FEEDTYPE_MPE) {
+		if (priv->secfeed) {
+			if (priv->secfeed->is_filtering) {
+				dprintk("%s: stop secfeed\n", __func__);
+				priv->secfeed->stop_filtering(priv->secfeed);
+			}
+
+			if (priv->secfilter) {
+				dprintk("%s: release secfilter\n", __func__);
+				priv->secfeed->release_filter(priv->secfeed,
+							      priv->secfilter);
+				priv->secfilter=NULL;
+			}
+
+			for (i=0; i<priv->multi_num; i++) {
+				if (priv->multi_secfilter[i]) {
+					dprintk("%s: release multi_filter[%d]\n",
+						__func__, i);
+					priv->secfeed->release_filter(priv->secfeed,
+								      priv->multi_secfilter[i]);
+					priv->multi_secfilter[i] = NULL;
+				}
+			}
+
+			priv->demux->release_section_feed(priv->demux, priv->secfeed);
+			priv->secfeed = NULL;
+		} else
+			printk("%s: no feed to stop\n", dev->name);
+	} else if (priv->feedtype == DVB_NET_FEEDTYPE_ULE) {
+		if (priv->tsfeed) {
+			if (priv->tsfeed->is_filtering) {
+				dprintk("%s: stop tsfeed\n", __func__);
+				priv->tsfeed->stop_filtering(priv->tsfeed);
+			}
+			priv->demux->release_ts_feed(priv->demux, priv->tsfeed);
+			priv->tsfeed = NULL;
+		}
+		else
+			printk("%s: no ts feed to stop\n", dev->name);
+	} else
+		ret = -EINVAL;
+	mutex_unlock(&priv->mutex);
+	return ret;
+}
+
+
+static int dvb_set_mc_filter(struct net_device *dev, unsigned char *addr)
+{
+	struct dvb_net_priv *priv = netdev_priv(dev);
+
+	if (priv->multi_num == DVB_NET_MULTICAST_MAX)
+		return -ENOMEM;
+
+	memcpy(priv->multi_macs[priv->multi_num], addr, ETH_ALEN);
+
+	priv->multi_num++;
+	return 0;
+}
+
+
+static void wq_set_multicast_list (struct work_struct *work)
+{
+	struct dvb_net_priv *priv =
+		container_of(work, struct dvb_net_priv, set_multicast_list_wq);
+	struct net_device *dev = priv->net;
+
+	dvb_net_feed_stop(dev);
+	priv->rx_mode = RX_MODE_UNI;
+	netif_addr_lock_bh(dev);
+
+	if (dev->flags & IFF_PROMISC) {
+		dprintk("%s: promiscuous mode\n", dev->name);
+		priv->rx_mode = RX_MODE_PROMISC;
+	} else if ((dev->flags & IFF_ALLMULTI)) {
+		dprintk("%s: allmulti mode\n", dev->name);
+		priv->rx_mode = RX_MODE_ALL_MULTI;
+	} else if (!netdev_mc_empty(dev)) {
+		struct netdev_hw_addr *ha;
+
+		dprintk("%s: set_mc_list, %d entries\n",
+			dev->name, netdev_mc_count(dev));
+
+		priv->rx_mode = RX_MODE_MULTI;
+		priv->multi_num = 0;
+
+		netdev_for_each_mc_addr(ha, dev)
+			dvb_set_mc_filter(dev, ha->addr);
+	}
+
+	netif_addr_unlock_bh(dev);
+	dvb_net_feed_start(dev);
+}
+
+
+static void dvb_net_set_multicast_list (struct net_device *dev)
+{
+	struct dvb_net_priv *priv = netdev_priv(dev);
+	schedule_work(&priv->set_multicast_list_wq);
+}
+
+
+static void wq_restart_net_feed (struct work_struct *work)
+{
+	struct dvb_net_priv *priv =
+		container_of(work, struct dvb_net_priv, restart_net_feed_wq);
+	struct net_device *dev = priv->net;
+
+	if (netif_running(dev)) {
+		dvb_net_feed_stop(dev);
+		dvb_net_feed_start(dev);
+	}
+}
+
+
+static int dvb_net_set_mac (struct net_device *dev, void *p)
+{
+	struct dvb_net_priv *priv = netdev_priv(dev);
+	struct sockaddr *addr=p;
+
+	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+
+	if (netif_running(dev))
+		schedule_work(&priv->restart_net_feed_wq);
+
+	return 0;
+}
+
+
+static int dvb_net_open(struct net_device *dev)
+{
+	struct dvb_net_priv *priv = netdev_priv(dev);
+
+	priv->in_use++;
+	dvb_net_feed_start(dev);
+	return 0;
+}
+
+
+static int dvb_net_stop(struct net_device *dev)
+{
+	struct dvb_net_priv *priv = netdev_priv(dev);
+
+	priv->in_use--;
+	return dvb_net_feed_stop(dev);
+}
+
+static const struct header_ops dvb_header_ops = {
+	.create		= eth_header,
+	.parse		= eth_header_parse,
+	.rebuild	= eth_rebuild_header,
+};
+
+
+static const struct net_device_ops dvb_netdev_ops = {
+	.ndo_open		= dvb_net_open,
+	.ndo_stop		= dvb_net_stop,
+	.ndo_start_xmit		= dvb_net_tx,
+	.ndo_set_rx_mode	= dvb_net_set_multicast_list,
+	.ndo_set_mac_address    = dvb_net_set_mac,
+	.ndo_change_mtu		= eth_change_mtu,
+	.ndo_validate_addr	= eth_validate_addr,
+};
+
+static void dvb_net_setup(struct net_device *dev)
+{
+	ether_setup(dev);
+
+	dev->header_ops		= &dvb_header_ops;
+	dev->netdev_ops		= &dvb_netdev_ops;
+	dev->mtu		= 4096;
+
+	dev->flags |= IFF_NOARP;
+}
+
+static int get_if(struct dvb_net *dvbnet)
+{
+	int i;
+
+	for (i=0; i<DVB_NET_DEVICES_MAX; i++)
+		if (!dvbnet->state[i])
+			break;
+
+	if (i == DVB_NET_DEVICES_MAX)
+		return -1;
+
+	dvbnet->state[i]=1;
+	return i;
+}
+
+static int dvb_net_add_if(struct dvb_net *dvbnet, u16 pid, u8 feedtype)
+{
+	struct net_device *net;
+	struct dvb_net_priv *priv;
+	int result;
+	int if_num;
+
+	if (feedtype != DVB_NET_FEEDTYPE_MPE && feedtype != DVB_NET_FEEDTYPE_ULE)
+		return -EINVAL;
+	if ((if_num = get_if(dvbnet)) < 0)
+		return -EINVAL;
+
+	net = alloc_netdev(sizeof(struct dvb_net_priv), "dvb", dvb_net_setup);
+	if (!net)
+		return -ENOMEM;
+
+	if (dvbnet->dvbdev->id)
+		snprintf(net->name, IFNAMSIZ, "dvb%d%u%d",
+			 dvbnet->dvbdev->adapter->num, dvbnet->dvbdev->id, if_num);
+	else
+		/* compatibility fix to keep dvb0_0 format */
+		snprintf(net->name, IFNAMSIZ, "dvb%d_%d",
+			 dvbnet->dvbdev->adapter->num, if_num);
+
+	net->addr_len = 6;
+	memcpy(net->dev_addr, dvbnet->dvbdev->adapter->proposed_mac, 6);
+
+	dvbnet->device[if_num] = net;
+
+	priv = netdev_priv(net);
+	priv->net = net;
+	priv->demux = dvbnet->demux;
+	priv->pid = pid;
+	priv->rx_mode = RX_MODE_UNI;
+	priv->need_pusi = 1;
+	priv->tscc = 0;
+	priv->feedtype = feedtype;
+	reset_ule(priv);
+
+	INIT_WORK(&priv->set_multicast_list_wq, wq_set_multicast_list);
+	INIT_WORK(&priv->restart_net_feed_wq, wq_restart_net_feed);
+	mutex_init(&priv->mutex);
+
+	net->base_addr = pid;
+
+	if ((result = register_netdev(net)) < 0) {
+		dvbnet->device[if_num] = NULL;
+		free_netdev(net);
+		return result;
+	}
+	printk("dvb_net: created network interface %s\n", net->name);
+
+	return if_num;
+}
+
+static int dvb_net_remove_if(struct dvb_net *dvbnet, unsigned long num)
+{
+	struct net_device *net = dvbnet->device[num];
+	struct dvb_net_priv *priv;
+
+	if (!dvbnet->state[num])
+		return -EINVAL;
+	priv = netdev_priv(net);
+	if (priv->in_use)
+		return -EBUSY;
+
+	dvb_net_stop(net);
+	flush_work(&priv->set_multicast_list_wq);
+	flush_work(&priv->restart_net_feed_wq);
+	printk("dvb_net: removed network interface %s\n", net->name);
+	unregister_netdev(net);
+	dvbnet->state[num]=0;
+	dvbnet->device[num] = NULL;
+	free_netdev(net);
+
+	return 0;
+}
+
+static int dvb_net_do_ioctl(struct file *file,
+		  unsigned int cmd, void *parg)
+{
+	struct dvb_device *dvbdev = file->private_data;
+	struct dvb_net *dvbnet = dvbdev->priv;
+
+	if (((file->f_flags&O_ACCMODE)==O_RDONLY))
+		return -EPERM;
+
+	switch (cmd) {
+	case NET_ADD_IF:
+	{
+		struct dvb_net_if *dvbnetif = parg;
+		int result;
+
+		if (!capable(CAP_SYS_ADMIN))
+			return -EPERM;
+
+		if (!try_module_get(dvbdev->adapter->module))
+			return -EPERM;
+
+		result=dvb_net_add_if(dvbnet, dvbnetif->pid, dvbnetif->feedtype);
+		if (result<0) {
+			module_put(dvbdev->adapter->module);
+			return result;
+		}
+		dvbnetif->if_num=result;
+		break;
+	}
+	case NET_GET_IF:
+	{
+		struct net_device *netdev;
+		struct dvb_net_priv *priv_data;
+		struct dvb_net_if *dvbnetif = parg;
+
+		if (dvbnetif->if_num >= DVB_NET_DEVICES_MAX ||
+		    !dvbnet->state[dvbnetif->if_num])
+			return -EINVAL;
+
+		netdev = dvbnet->device[dvbnetif->if_num];
+
+		priv_data = netdev_priv(netdev);
+		dvbnetif->pid=priv_data->pid;
+		dvbnetif->feedtype=priv_data->feedtype;
+		break;
+	}
+	case NET_REMOVE_IF:
+	{
+		int ret;
+
+		if (!capable(CAP_SYS_ADMIN))
+			return -EPERM;
+		if ((unsigned long) parg >= DVB_NET_DEVICES_MAX)
+			return -EINVAL;
+		ret = dvb_net_remove_if(dvbnet, (unsigned long) parg);
+		if (!ret)
+			module_put(dvbdev->adapter->module);
+		return ret;
+	}
+
+	/* binary compatibility cruft */
+	case __NET_ADD_IF_OLD:
+	{
+		struct __dvb_net_if_old *dvbnetif = parg;
+		int result;
+
+		if (!capable(CAP_SYS_ADMIN))
+			return -EPERM;
+
+		if (!try_module_get(dvbdev->adapter->module))
+			return -EPERM;
+
+		result=dvb_net_add_if(dvbnet, dvbnetif->pid, DVB_NET_FEEDTYPE_MPE);
+		if (result<0) {
+			module_put(dvbdev->adapter->module);
+			return result;
+		}
+		dvbnetif->if_num=result;
+		break;
+	}
+	case __NET_GET_IF_OLD:
+	{
+		struct net_device *netdev;
+		struct dvb_net_priv *priv_data;
+		struct __dvb_net_if_old *dvbnetif = parg;
+
+		if (dvbnetif->if_num >= DVB_NET_DEVICES_MAX ||
+		    !dvbnet->state[dvbnetif->if_num])
+			return -EINVAL;
+
+		netdev = dvbnet->device[dvbnetif->if_num];
+
+		priv_data = netdev_priv(netdev);
+		dvbnetif->pid=priv_data->pid;
+		break;
+	}
+	default:
+		return -ENOTTY;
+	}
+	return 0;
+}
+
+static long dvb_net_ioctl(struct file *file,
+	      unsigned int cmd, unsigned long arg)
+{
+	return dvb_usercopy(file, cmd, arg, dvb_net_do_ioctl);
+}
+
+static int dvb_net_close(struct inode *inode, struct file *file)
+{
+	struct dvb_device *dvbdev = file->private_data;
+	struct dvb_net *dvbnet = dvbdev->priv;
+
+	dvb_generic_release(inode, file);
+
+	if(dvbdev->users == 1 && dvbnet->exit == 1) {
+		fops_put(file->f_op);
+		file->f_op = NULL;
+		wake_up(&dvbdev->wait_queue);
+	}
+	return 0;
+}
+
+
+static const struct file_operations dvb_net_fops = {
+	.owner = THIS_MODULE,
+	.unlocked_ioctl = dvb_net_ioctl,
+	.open =	dvb_generic_open,
+	.release = dvb_net_close,
+	.llseek = noop_llseek,
+};
+
+static struct dvb_device dvbdev_net = {
+	.priv = NULL,
+	.users = 1,
+	.writers = 1,
+	.fops = &dvb_net_fops,
+};
+
+
+void dvb_net_release (struct dvb_net *dvbnet)
+{
+	int i;
+
+	dvbnet->exit = 1;
+	if (dvbnet->dvbdev->users < 1)
+		wait_event(dvbnet->dvbdev->wait_queue,
+				dvbnet->dvbdev->users==1);
+
+	dvb_unregister_device(dvbnet->dvbdev);
+
+	for (i=0; i<DVB_NET_DEVICES_MAX; i++) {
+		if (!dvbnet->state[i])
+			continue;
+		dvb_net_remove_if(dvbnet, i);
+	}
+}
+EXPORT_SYMBOL(dvb_net_release);
+
+
+int dvb_net_init (struct dvb_adapter *adap, struct dvb_net *dvbnet,
+		  struct dmx_demux *dmx)
+{
+	int i;
+
+	dvbnet->demux = dmx;
+
+	for (i=0; i<DVB_NET_DEVICES_MAX; i++)
+		dvbnet->state[i] = 0;
+
+	return dvb_register_device(adap, &dvbnet->dvbdev, &dvbdev_net,
+			     dvbnet, DVB_DEVICE_NET);
+}
+EXPORT_SYMBOL(dvb_net_init);
diff --git a/drivers/media/dvb-core/dvb_net.h b/drivers/media/dvb-core/dvb_net.h
new file mode 100644
index 0000000..1e53acd
--- /dev/null
+++ b/drivers/media/dvb-core/dvb_net.h
@@ -0,0 +1,66 @@
+/*
+ * dvb_net.h
+ *
+ * Copyright (C) 2001 Ralph Metzler for convergence integrated media GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public 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 _DVB_NET_H_
+#define _DVB_NET_H_
+
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/inetdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+
+#include "dvbdev.h"
+
+#define DVB_NET_DEVICES_MAX 10
+
+#ifdef CONFIG_DVB_NET
+
+struct dvb_net {
+	struct dvb_device *dvbdev;
+	struct net_device *device[DVB_NET_DEVICES_MAX];
+	int state[DVB_NET_DEVICES_MAX];
+	unsigned int exit:1;
+	struct dmx_demux *demux;
+};
+
+void dvb_net_release(struct dvb_net *);
+int  dvb_net_init(struct dvb_adapter *, struct dvb_net *, struct dmx_demux *);
+
+#else
+
+struct dvb_net {
+	struct dvb_device *dvbdev;
+};
+
+static inline void dvb_net_release(struct dvb_net *dvbnet)
+{
+}
+
+static inline int dvb_net_init(struct dvb_adapter *adap,
+			       struct dvb_net *dvbnet, struct dmx_demux *dmx)
+{
+	return 0;
+}
+
+#endif /* ifdef CONFIG_DVB_NET */
+
+#endif
diff --git a/drivers/media/dvb-core/dvb_ringbuffer.c b/drivers/media/dvb-core/dvb_ringbuffer.c
new file mode 100644
index 0000000..a5712cd
--- /dev/null
+++ b/drivers/media/dvb-core/dvb_ringbuffer.c
@@ -0,0 +1,299 @@
+/*
+ *
+ * dvb_ringbuffer.c: ring buffer implementation for the dvb driver
+ *
+ * Copyright (C) 2003 Oliver Endriss
+ * Copyright (C) 2004 Andrew de Quincey
+ *
+ * based on code originally found in av7110.c & dvb_ci.c:
+ * Copyright (C) 1999-2003 Ralph  Metzler
+ *                       & Marcus Metzler for convergence integrated media GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public 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/errno.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <asm/uaccess.h>
+
+#include "dvb_ringbuffer.h"
+
+#define PKT_READY 0
+#define PKT_DISPOSED 1
+
+
+void dvb_ringbuffer_init(struct dvb_ringbuffer *rbuf, void *data, size_t len)
+{
+	rbuf->pread=rbuf->pwrite=0;
+	rbuf->data=data;
+	rbuf->size=len;
+	rbuf->error=0;
+
+	init_waitqueue_head(&rbuf->queue);
+
+	spin_lock_init(&(rbuf->lock));
+}
+
+
+
+int dvb_ringbuffer_empty(struct dvb_ringbuffer *rbuf)
+{
+	return (rbuf->pread==rbuf->pwrite);
+}
+
+
+
+ssize_t dvb_ringbuffer_free(struct dvb_ringbuffer *rbuf)
+{
+	ssize_t free;
+
+	free = rbuf->pread - rbuf->pwrite;
+	if (free <= 0)
+		free += rbuf->size;
+	return free-1;
+}
+
+
+
+ssize_t dvb_ringbuffer_avail(struct dvb_ringbuffer *rbuf)
+{
+	ssize_t avail;
+
+	avail = rbuf->pwrite - rbuf->pread;
+	if (avail < 0)
+		avail += rbuf->size;
+	return avail;
+}
+
+
+
+void dvb_ringbuffer_flush(struct dvb_ringbuffer *rbuf)
+{
+	rbuf->pread = rbuf->pwrite;
+	rbuf->error = 0;
+}
+EXPORT_SYMBOL(dvb_ringbuffer_flush);
+
+void dvb_ringbuffer_reset(struct dvb_ringbuffer *rbuf)
+{
+	rbuf->pread = rbuf->pwrite = 0;
+	rbuf->error = 0;
+}
+
+void dvb_ringbuffer_flush_spinlock_wakeup(struct dvb_ringbuffer *rbuf)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&rbuf->lock, flags);
+	dvb_ringbuffer_flush(rbuf);
+	spin_unlock_irqrestore(&rbuf->lock, flags);
+
+	wake_up(&rbuf->queue);
+}
+
+ssize_t dvb_ringbuffer_read_user(struct dvb_ringbuffer *rbuf, u8 __user *buf, size_t len)
+{
+	size_t todo = len;
+	size_t split;
+
+	split = (rbuf->pread + len > rbuf->size) ? rbuf->size - rbuf->pread : 0;
+	if (split > 0) {
+		if (copy_to_user(buf, rbuf->data+rbuf->pread, split))
+			return -EFAULT;
+		buf += split;
+		todo -= split;
+		rbuf->pread = 0;
+	}
+	if (copy_to_user(buf, rbuf->data+rbuf->pread, todo))
+		return -EFAULT;
+
+	rbuf->pread = (rbuf->pread + todo) % rbuf->size;
+
+	return len;
+}
+
+void dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf, u8 *buf, size_t len)
+{
+	size_t todo = len;
+	size_t split;
+
+	split = (rbuf->pread + len > rbuf->size) ? rbuf->size - rbuf->pread : 0;
+	if (split > 0) {
+		memcpy(buf, rbuf->data+rbuf->pread, split);
+		buf += split;
+		todo -= split;
+		rbuf->pread = 0;
+	}
+	memcpy(buf, rbuf->data+rbuf->pread, todo);
+
+	rbuf->pread = (rbuf->pread + todo) % rbuf->size;
+}
+
+
+ssize_t dvb_ringbuffer_write(struct dvb_ringbuffer *rbuf, const u8 *buf, size_t len)
+{
+	size_t todo = len;
+	size_t split;
+
+	split = (rbuf->pwrite + len > rbuf->size) ? rbuf->size - rbuf->pwrite : 0;
+
+	if (split > 0) {
+		memcpy(rbuf->data+rbuf->pwrite, buf, split);
+		buf += split;
+		todo -= split;
+		rbuf->pwrite = 0;
+	}
+	memcpy(rbuf->data+rbuf->pwrite, buf, todo);
+	rbuf->pwrite = (rbuf->pwrite + todo) % rbuf->size;
+
+	return len;
+}
+
+ssize_t dvb_ringbuffer_pkt_write(struct dvb_ringbuffer *rbuf, u8* buf, size_t len)
+{
+	int status;
+	ssize_t oldpwrite = rbuf->pwrite;
+
+	DVB_RINGBUFFER_WRITE_BYTE(rbuf, len >> 8);
+	DVB_RINGBUFFER_WRITE_BYTE(rbuf, len & 0xff);
+	DVB_RINGBUFFER_WRITE_BYTE(rbuf, PKT_READY);
+	status = dvb_ringbuffer_write(rbuf, buf, len);
+
+	if (status < 0) rbuf->pwrite = oldpwrite;
+	return status;
+}
+
+ssize_t dvb_ringbuffer_pkt_read_user(struct dvb_ringbuffer *rbuf, size_t idx,
+				int offset, u8 __user *buf, size_t len)
+{
+	size_t todo;
+	size_t split;
+	size_t pktlen;
+
+	pktlen = rbuf->data[idx] << 8;
+	pktlen |= rbuf->data[(idx + 1) % rbuf->size];
+	if (offset > pktlen) return -EINVAL;
+	if ((offset + len) > pktlen) len = pktlen - offset;
+
+	idx = (idx + DVB_RINGBUFFER_PKTHDRSIZE + offset) % rbuf->size;
+	todo = len;
+	split = ((idx + len) > rbuf->size) ? rbuf->size - idx : 0;
+	if (split > 0) {
+		if (copy_to_user(buf, rbuf->data+idx, split))
+			return -EFAULT;
+		buf += split;
+		todo -= split;
+		idx = 0;
+	}
+	if (copy_to_user(buf, rbuf->data+idx, todo))
+		return -EFAULT;
+
+	return len;
+}
+
+ssize_t dvb_ringbuffer_pkt_read(struct dvb_ringbuffer *rbuf, size_t idx,
+				int offset, u8* buf, size_t len)
+{
+	size_t todo;
+	size_t split;
+	size_t pktlen;
+
+	pktlen = rbuf->data[idx] << 8;
+	pktlen |= rbuf->data[(idx + 1) % rbuf->size];
+	if (offset > pktlen) return -EINVAL;
+	if ((offset + len) > pktlen) len = pktlen - offset;
+
+	idx = (idx + DVB_RINGBUFFER_PKTHDRSIZE + offset) % rbuf->size;
+	todo = len;
+	split = ((idx + len) > rbuf->size) ? rbuf->size - idx : 0;
+	if (split > 0) {
+		memcpy(buf, rbuf->data+idx, split);
+		buf += split;
+		todo -= split;
+		idx = 0;
+	}
+	memcpy(buf, rbuf->data+idx, todo);
+	return len;
+}
+
+void dvb_ringbuffer_pkt_dispose(struct dvb_ringbuffer *rbuf, size_t idx)
+{
+	size_t pktlen;
+
+	rbuf->data[(idx + 2) % rbuf->size] = PKT_DISPOSED;
+
+	// clean up disposed packets
+	while(dvb_ringbuffer_avail(rbuf) > DVB_RINGBUFFER_PKTHDRSIZE) {
+		if (DVB_RINGBUFFER_PEEK(rbuf, 2) == PKT_DISPOSED) {
+			pktlen = DVB_RINGBUFFER_PEEK(rbuf, 0) << 8;
+			pktlen |= DVB_RINGBUFFER_PEEK(rbuf, 1);
+			DVB_RINGBUFFER_SKIP(rbuf, pktlen + DVB_RINGBUFFER_PKTHDRSIZE);
+		} else {
+			// first packet is not disposed, so we stop cleaning now
+			break;
+		}
+	}
+}
+
+ssize_t dvb_ringbuffer_pkt_next(struct dvb_ringbuffer *rbuf, size_t idx, size_t* pktlen)
+{
+	int consumed;
+	int curpktlen;
+	int curpktstatus;
+
+	if (idx == -1) {
+	       idx = rbuf->pread;
+	} else {
+		curpktlen = rbuf->data[idx] << 8;
+		curpktlen |= rbuf->data[(idx + 1) % rbuf->size];
+		idx = (idx + curpktlen + DVB_RINGBUFFER_PKTHDRSIZE) % rbuf->size;
+	}
+
+	consumed = (idx - rbuf->pread) % rbuf->size;
+
+	while((dvb_ringbuffer_avail(rbuf) - consumed) > DVB_RINGBUFFER_PKTHDRSIZE) {
+
+		curpktlen = rbuf->data[idx] << 8;
+		curpktlen |= rbuf->data[(idx + 1) % rbuf->size];
+		curpktstatus = rbuf->data[(idx + 2) % rbuf->size];
+
+		if (curpktstatus == PKT_READY) {
+			*pktlen = curpktlen;
+			return idx;
+		}
+
+		consumed += curpktlen + DVB_RINGBUFFER_PKTHDRSIZE;
+		idx = (idx + curpktlen + DVB_RINGBUFFER_PKTHDRSIZE) % rbuf->size;
+	}
+
+	// no packets available
+	return -1;
+}
+
+
+
+EXPORT_SYMBOL(dvb_ringbuffer_init);
+EXPORT_SYMBOL(dvb_ringbuffer_empty);
+EXPORT_SYMBOL(dvb_ringbuffer_free);
+EXPORT_SYMBOL(dvb_ringbuffer_avail);
+EXPORT_SYMBOL(dvb_ringbuffer_flush_spinlock_wakeup);
+EXPORT_SYMBOL(dvb_ringbuffer_read_user);
+EXPORT_SYMBOL(dvb_ringbuffer_read);
+EXPORT_SYMBOL(dvb_ringbuffer_write);
diff --git a/drivers/media/dvb-core/dvb_ringbuffer.h b/drivers/media/dvb-core/dvb_ringbuffer.h
new file mode 100644
index 0000000..41f04da
--- /dev/null
+++ b/drivers/media/dvb-core/dvb_ringbuffer.h
@@ -0,0 +1,186 @@
+/*
+ *
+ * dvb_ringbuffer.h: ring buffer implementation for the dvb driver
+ *
+ * Copyright (C) 2003 Oliver Endriss
+ * Copyright (C) 2004 Andrew de Quincey
+ *
+ * based on code originally found in av7110.c & dvb_ci.c:
+ * Copyright (C) 1999-2003 Ralph Metzler & Marcus Metzler
+ *                         for convergence integrated media GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public 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 _DVB_RINGBUFFER_H_
+#define _DVB_RINGBUFFER_H_
+
+#include <linux/spinlock.h>
+#include <linux/wait.h>
+
+struct dvb_ringbuffer {
+	u8               *data;
+	ssize_t           size;
+	ssize_t           pread;
+	ssize_t           pwrite;
+	int               error;
+
+	wait_queue_head_t queue;
+	spinlock_t        lock;
+};
+
+#define DVB_RINGBUFFER_PKTHDRSIZE 3
+
+
+/*
+** Notes:
+** ------
+** (1) For performance reasons read and write routines don't check buffer sizes
+**     and/or number of bytes free/available. This has to be done before these
+**     routines are called. For example:
+**
+**     *** write <buflen> bytes ***
+**     free = dvb_ringbuffer_free(rbuf);
+**     if (free >= buflen)
+**         count = dvb_ringbuffer_write(rbuf, buffer, buflen);
+**     else
+**         ...
+**
+**     *** read min. 1000, max. <bufsize> bytes ***
+**     avail = dvb_ringbuffer_avail(rbuf);
+**     if (avail >= 1000)
+**         count = dvb_ringbuffer_read(rbuf, buffer, min(avail, bufsize));
+**     else
+**         ...
+**
+** (2) If there is exactly one reader and one writer, there is no need
+**     to lock read or write operations.
+**     Two or more readers must be locked against each other.
+**     Flushing the buffer counts as a read operation.
+**     Resetting the buffer counts as a read and write operation.
+**     Two or more writers must be locked against each other.
+*/
+
+/* initialize ring buffer, lock and queue */
+extern void dvb_ringbuffer_init(struct dvb_ringbuffer *rbuf, void *data, size_t len);
+
+/* test whether buffer is empty */
+extern int dvb_ringbuffer_empty(struct dvb_ringbuffer *rbuf);
+
+/* return the number of free bytes in the buffer */
+extern ssize_t dvb_ringbuffer_free(struct dvb_ringbuffer *rbuf);
+
+/* return the number of bytes waiting in the buffer */
+extern ssize_t dvb_ringbuffer_avail(struct dvb_ringbuffer *rbuf);
+
+
+/*
+** Reset the read and write pointers to zero and flush the buffer
+** This counts as a read and write operation
+*/
+extern void dvb_ringbuffer_reset(struct dvb_ringbuffer *rbuf);
+
+
+/* read routines & macros */
+/* ---------------------- */
+/* flush buffer */
+extern void dvb_ringbuffer_flush(struct dvb_ringbuffer *rbuf);
+
+/* flush buffer protected by spinlock and wake-up waiting task(s) */
+extern void dvb_ringbuffer_flush_spinlock_wakeup(struct dvb_ringbuffer *rbuf);
+
+/* peek at byte <offs> in the buffer */
+#define DVB_RINGBUFFER_PEEK(rbuf,offs)	\
+			(rbuf)->data[((rbuf)->pread+(offs))%(rbuf)->size]
+
+/* advance read ptr by <num> bytes */
+#define DVB_RINGBUFFER_SKIP(rbuf,num)	\
+			(rbuf)->pread=((rbuf)->pread+(num))%(rbuf)->size
+
+/*
+** read <len> bytes from ring buffer into <buf>
+** <usermem> specifies whether <buf> resides in user space
+** returns number of bytes transferred or -EFAULT
+*/
+extern ssize_t dvb_ringbuffer_read_user(struct dvb_ringbuffer *rbuf,
+				   u8 __user *buf, size_t len);
+extern void dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf,
+				   u8 *buf, size_t len);
+
+
+/* write routines & macros */
+/* ----------------------- */
+/* write single byte to ring buffer */
+#define DVB_RINGBUFFER_WRITE_BYTE(rbuf,byte)	\
+			{ (rbuf)->data[(rbuf)->pwrite]=(byte); \
+			(rbuf)->pwrite=((rbuf)->pwrite+1)%(rbuf)->size; }
+/*
+** write <len> bytes to ring buffer
+** <usermem> specifies whether <buf> resides in user space
+** returns number of bytes transferred or -EFAULT
+*/
+extern ssize_t dvb_ringbuffer_write(struct dvb_ringbuffer *rbuf, const u8 *buf,
+				    size_t len);
+
+
+/**
+ * Write a packet into the ringbuffer.
+ *
+ * <rbuf> Ringbuffer to write to.
+ * <buf> Buffer to write.
+ * <len> Length of buffer (currently limited to 65535 bytes max).
+ * returns Number of bytes written, or -EFAULT, -ENOMEM, -EVINAL.
+ */
+extern ssize_t dvb_ringbuffer_pkt_write(struct dvb_ringbuffer *rbuf, u8* buf,
+					size_t len);
+
+/**
+ * Read from a packet in the ringbuffer. Note: unlike dvb_ringbuffer_read(), this
+ * does NOT update the read pointer in the ringbuffer. You must use
+ * dvb_ringbuffer_pkt_dispose() to mark a packet as no longer required.
+ *
+ * <rbuf> Ringbuffer concerned.
+ * <idx> Packet index as returned by dvb_ringbuffer_pkt_next().
+ * <offset> Offset into packet to read from.
+ * <buf> Destination buffer for data.
+ * <len> Size of destination buffer.
+ * <usermem> Set to 1 if <buf> is in userspace.
+ * returns Number of bytes read, or -EFAULT.
+ */
+extern ssize_t dvb_ringbuffer_pkt_read_user(struct dvb_ringbuffer *rbuf, size_t idx,
+				       int offset, u8 __user *buf, size_t len);
+extern ssize_t dvb_ringbuffer_pkt_read(struct dvb_ringbuffer *rbuf, size_t idx,
+				       int offset, u8 *buf, size_t len);
+
+/**
+ * Dispose of a packet in the ring buffer.
+ *
+ * <rbuf> Ring buffer concerned.
+ * <idx> Packet index as returned by dvb_ringbuffer_pkt_next().
+ */
+extern void dvb_ringbuffer_pkt_dispose(struct dvb_ringbuffer *rbuf, size_t idx);
+
+/**
+ * Get the index of the next packet in a ringbuffer.
+ *
+ * <rbuf> Ringbuffer concerned.
+ * <idx> Previous packet index, or -1 to return the first packet index.
+ * <pktlen> On success, will be updated to contain the length of the packet in bytes.
+ * returns Packet index (if >=0), or -1 if no packets available.
+ */
+extern ssize_t dvb_ringbuffer_pkt_next(struct dvb_ringbuffer *rbuf, size_t idx, size_t* pktlen);
+
+
+#endif /* _DVB_RINGBUFFER_H_ */
diff --git a/drivers/media/dvb-core/dvbdev.c b/drivers/media/dvb-core/dvbdev.c
new file mode 100644
index 0000000..d33101a
--- /dev/null
+++ b/drivers/media/dvb-core/dvbdev.c
@@ -0,0 +1,507 @@
+/*
+ * dvbdev.c
+ *
+ * Copyright (C) 2000 Ralph  Metzler <ralph@convergence.de>
+ *                  & Marcus Metzler <marcus@convergence.de>
+ *                    for convergence integrated media GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public 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/errno.h>
+#include <linux/string.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/fs.h>
+#include <linux/cdev.h>
+#include <linux/mutex.h>
+#include "dvbdev.h"
+
+static DEFINE_MUTEX(dvbdev_mutex);
+static int dvbdev_debug;
+
+module_param(dvbdev_debug, int, 0644);
+MODULE_PARM_DESC(dvbdev_debug, "Turn on/off device debugging (default:off).");
+
+#define dprintk if (dvbdev_debug) printk
+
+static LIST_HEAD(dvb_adapter_list);
+static DEFINE_MUTEX(dvbdev_register_lock);
+
+static const char * const dnames[] = {
+	"video", "audio", "sec", "frontend", "demux", "dvr", "ca",
+	"net", "osd"
+};
+
+#ifdef CONFIG_DVB_DYNAMIC_MINORS
+#define MAX_DVB_MINORS		256
+#define DVB_MAX_IDS		MAX_DVB_MINORS
+#else
+#define DVB_MAX_IDS		4
+#define nums2minor(num,type,id)	((num << 6) | (id << 4) | type)
+#define MAX_DVB_MINORS		(DVB_MAX_ADAPTERS*64)
+#endif
+
+static struct class *dvb_class;
+
+static struct dvb_device *dvb_minors[MAX_DVB_MINORS];
+static DECLARE_RWSEM(minor_rwsem);
+
+static int dvb_device_open(struct inode *inode, struct file *file)
+{
+	struct dvb_device *dvbdev;
+
+	mutex_lock(&dvbdev_mutex);
+	down_read(&minor_rwsem);
+	dvbdev = dvb_minors[iminor(inode)];
+
+	if (dvbdev && dvbdev->fops) {
+		int err = 0;
+		const struct file_operations *old_fops;
+
+		file->private_data = dvbdev;
+		old_fops = file->f_op;
+		file->f_op = fops_get(dvbdev->fops);
+		if (file->f_op == NULL) {
+			file->f_op = old_fops;
+			goto fail;
+		}
+		if(file->f_op->open)
+			err = file->f_op->open(inode,file);
+		if (err) {
+			fops_put(file->f_op);
+			file->f_op = fops_get(old_fops);
+		}
+		fops_put(old_fops);
+		up_read(&minor_rwsem);
+		mutex_unlock(&dvbdev_mutex);
+		return err;
+	}
+fail:
+	up_read(&minor_rwsem);
+	mutex_unlock(&dvbdev_mutex);
+	return -ENODEV;
+}
+
+
+static const struct file_operations dvb_device_fops =
+{
+	.owner =	THIS_MODULE,
+	.open =		dvb_device_open,
+	.llseek =	noop_llseek,
+};
+
+static struct cdev dvb_device_cdev;
+
+int dvb_generic_open(struct inode *inode, struct file *file)
+{
+	struct dvb_device *dvbdev = file->private_data;
+
+	if (!dvbdev)
+		return -ENODEV;
+
+	if (!dvbdev->users)
+		return -EBUSY;
+
+	if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
+		if (!dvbdev->readers)
+			return -EBUSY;
+		dvbdev->readers--;
+	} else {
+		if (!dvbdev->writers)
+			return -EBUSY;
+		dvbdev->writers--;
+	}
+
+	dvbdev->users--;
+	return 0;
+}
+EXPORT_SYMBOL(dvb_generic_open);
+
+
+int dvb_generic_release(struct inode *inode, struct file *file)
+{
+	struct dvb_device *dvbdev = file->private_data;
+
+	if (!dvbdev)
+		return -ENODEV;
+
+	if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
+		dvbdev->readers++;
+	} else {
+		dvbdev->writers++;
+	}
+
+	dvbdev->users++;
+	return 0;
+}
+EXPORT_SYMBOL(dvb_generic_release);
+
+
+long dvb_generic_ioctl(struct file *file,
+		       unsigned int cmd, unsigned long arg)
+{
+	struct dvb_device *dvbdev = file->private_data;
+
+	if (!dvbdev)
+		return -ENODEV;
+
+	if (!dvbdev->kernel_ioctl)
+		return -EINVAL;
+
+	return dvb_usercopy(file, cmd, arg, dvbdev->kernel_ioctl);
+}
+EXPORT_SYMBOL(dvb_generic_ioctl);
+
+
+static int dvbdev_get_free_id (struct dvb_adapter *adap, int type)
+{
+	u32 id = 0;
+
+	while (id < DVB_MAX_IDS) {
+		struct dvb_device *dev;
+		list_for_each_entry(dev, &adap->device_list, list_head)
+			if (dev->type == type && dev->id == id)
+				goto skip;
+		return id;
+skip:
+		id++;
+	}
+	return -ENFILE;
+}
+
+
+int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
+			const struct dvb_device *template, void *priv, int type)
+{
+	struct dvb_device *dvbdev;
+	struct file_operations *dvbdevfops;
+	struct device *clsdev;
+	int minor;
+	int id;
+
+	mutex_lock(&dvbdev_register_lock);
+
+	if ((id = dvbdev_get_free_id (adap, type)) < 0){
+		mutex_unlock(&dvbdev_register_lock);
+		*pdvbdev = NULL;
+		printk(KERN_ERR "%s: couldn't find free device id\n", __func__);
+		return -ENFILE;
+	}
+
+	*pdvbdev = dvbdev = kmalloc(sizeof(struct dvb_device), GFP_KERNEL);
+
+	if (!dvbdev){
+		mutex_unlock(&dvbdev_register_lock);
+		return -ENOMEM;
+	}
+
+	dvbdevfops = kzalloc(sizeof(struct file_operations), GFP_KERNEL);
+
+	if (!dvbdevfops){
+		kfree (dvbdev);
+		mutex_unlock(&dvbdev_register_lock);
+		return -ENOMEM;
+	}
+
+	memcpy(dvbdev, template, sizeof(struct dvb_device));
+	dvbdev->type = type;
+	dvbdev->id = id;
+	dvbdev->adapter = adap;
+	dvbdev->priv = priv;
+	dvbdev->fops = dvbdevfops;
+	init_waitqueue_head (&dvbdev->wait_queue);
+
+	memcpy(dvbdevfops, template->fops, sizeof(struct file_operations));
+	dvbdevfops->owner = adap->module;
+
+	list_add_tail (&dvbdev->list_head, &adap->device_list);
+
+	down_write(&minor_rwsem);
+#ifdef CONFIG_DVB_DYNAMIC_MINORS
+	for (minor = 0; minor < MAX_DVB_MINORS; minor++)
+		if (dvb_minors[minor] == NULL)
+			break;
+
+	if (minor == MAX_DVB_MINORS) {
+		kfree(dvbdevfops);
+		kfree(dvbdev);
+		up_write(&minor_rwsem);
+		mutex_unlock(&dvbdev_register_lock);
+		return -EINVAL;
+	}
+#else
+	minor = nums2minor(adap->num, type, id);
+#endif
+
+	dvbdev->minor = minor;
+	dvb_minors[minor] = dvbdev;
+	up_write(&minor_rwsem);
+
+	mutex_unlock(&dvbdev_register_lock);
+
+	clsdev = device_create(dvb_class, adap->device,
+			       MKDEV(DVB_MAJOR, minor),
+			       dvbdev, "dvb%d.%s%d", adap->num, dnames[type], id);
+	if (IS_ERR(clsdev)) {
+		printk(KERN_ERR "%s: failed to create device dvb%d.%s%d (%ld)\n",
+		       __func__, adap->num, dnames[type], id, PTR_ERR(clsdev));
+		return PTR_ERR(clsdev);
+	}
+
+	dprintk(KERN_DEBUG "DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n",
+		adap->num, dnames[type], id, minor, minor);
+
+	return 0;
+}
+EXPORT_SYMBOL(dvb_register_device);
+
+
+void dvb_unregister_device(struct dvb_device *dvbdev)
+{
+	if (!dvbdev)
+		return;
+
+	down_write(&minor_rwsem);
+	dvb_minors[dvbdev->minor] = NULL;
+	up_write(&minor_rwsem);
+
+	device_destroy(dvb_class, MKDEV(DVB_MAJOR, dvbdev->minor));
+
+	list_del (&dvbdev->list_head);
+	kfree (dvbdev->fops);
+	kfree (dvbdev);
+}
+EXPORT_SYMBOL(dvb_unregister_device);
+
+static int dvbdev_check_free_adapter_num(int num)
+{
+	struct list_head *entry;
+	list_for_each(entry, &dvb_adapter_list) {
+		struct dvb_adapter *adap;
+		adap = list_entry(entry, struct dvb_adapter, list_head);
+		if (adap->num == num)
+			return 0;
+	}
+	return 1;
+}
+
+static int dvbdev_get_free_adapter_num (void)
+{
+	int num = 0;
+
+	while (num < DVB_MAX_ADAPTERS) {
+		if (dvbdev_check_free_adapter_num(num))
+			return num;
+		num++;
+	}
+
+	return -ENFILE;
+}
+
+
+int dvb_register_adapter(struct dvb_adapter *adap, const char *name,
+			 struct module *module, struct device *device,
+			 short *adapter_nums)
+{
+	int i, num;
+
+	mutex_lock(&dvbdev_register_lock);
+
+	for (i = 0; i < DVB_MAX_ADAPTERS; ++i) {
+		num = adapter_nums[i];
+		if (num >= 0  &&  num < DVB_MAX_ADAPTERS) {
+		/* use the one the driver asked for */
+			if (dvbdev_check_free_adapter_num(num))
+				break;
+		} else {
+			num = dvbdev_get_free_adapter_num();
+			break;
+		}
+		num = -1;
+	}
+
+	if (num < 0) {
+		mutex_unlock(&dvbdev_register_lock);
+		return -ENFILE;
+	}
+
+	memset (adap, 0, sizeof(struct dvb_adapter));
+	INIT_LIST_HEAD (&adap->device_list);
+
+	printk(KERN_INFO "DVB: registering new adapter (%s)\n", name);
+
+	adap->num = num;
+	adap->name = name;
+	adap->module = module;
+	adap->device = device;
+	adap->mfe_shared = 0;
+	adap->mfe_dvbdev = NULL;
+	mutex_init (&adap->mfe_lock);
+
+	list_add_tail (&adap->list_head, &dvb_adapter_list);
+
+	mutex_unlock(&dvbdev_register_lock);
+
+	return num;
+}
+EXPORT_SYMBOL(dvb_register_adapter);
+
+
+int dvb_unregister_adapter(struct dvb_adapter *adap)
+{
+	mutex_lock(&dvbdev_register_lock);
+	list_del (&adap->list_head);
+	mutex_unlock(&dvbdev_register_lock);
+	return 0;
+}
+EXPORT_SYMBOL(dvb_unregister_adapter);
+
+/* if the miracle happens and "generic_usercopy()" is included into
+   the kernel, then this can vanish. please don't make the mistake and
+   define this as video_usercopy(). this will introduce a dependecy
+   to the v4l "videodev.o" module, which is unnecessary for some
+   cards (ie. the budget dvb-cards don't need the v4l module...) */
+int dvb_usercopy(struct file *file,
+		     unsigned int cmd, unsigned long arg,
+		     int (*func)(struct file *file,
+		     unsigned int cmd, void *arg))
+{
+	char    sbuf[128];
+	void    *mbuf = NULL;
+	void    *parg = NULL;
+	int     err  = -EINVAL;
+
+	/*  Copy arguments into temp kernel buffer  */
+	switch (_IOC_DIR(cmd)) {
+	case _IOC_NONE:
+		/*
+		 * For this command, the pointer is actually an integer
+		 * argument.
+		 */
+		parg = (void *) arg;
+		break;
+	case _IOC_READ: /* some v4l ioctls are marked wrong ... */
+	case _IOC_WRITE:
+	case (_IOC_WRITE | _IOC_READ):
+		if (_IOC_SIZE(cmd) <= sizeof(sbuf)) {
+			parg = sbuf;
+		} else {
+			/* too big to allocate from stack */
+			mbuf = kmalloc(_IOC_SIZE(cmd),GFP_KERNEL);
+			if (NULL == mbuf)
+				return -ENOMEM;
+			parg = mbuf;
+		}
+
+		err = -EFAULT;
+		if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd)))
+			goto out;
+		break;
+	}
+
+	/* call driver */
+	mutex_lock(&dvbdev_mutex);
+	if ((err = func(file, cmd, parg)) == -ENOIOCTLCMD)
+		err = -ENOTTY;
+	mutex_unlock(&dvbdev_mutex);
+
+	if (err < 0)
+		goto out;
+
+	/*  Copy results into user buffer  */
+	switch (_IOC_DIR(cmd))
+	{
+	case _IOC_READ:
+	case (_IOC_WRITE | _IOC_READ):
+		if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd)))
+			err = -EFAULT;
+		break;
+	}
+
+out:
+	kfree(mbuf);
+	return err;
+}
+
+static int dvb_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+	struct dvb_device *dvbdev = dev_get_drvdata(dev);
+
+	add_uevent_var(env, "DVB_ADAPTER_NUM=%d", dvbdev->adapter->num);
+	add_uevent_var(env, "DVB_DEVICE_TYPE=%s", dnames[dvbdev->type]);
+	add_uevent_var(env, "DVB_DEVICE_NUM=%d", dvbdev->id);
+	return 0;
+}
+
+static char *dvb_devnode(struct device *dev, umode_t *mode)
+{
+	struct dvb_device *dvbdev = dev_get_drvdata(dev);
+
+	return kasprintf(GFP_KERNEL, "dvb/adapter%d/%s%d",
+		dvbdev->adapter->num, dnames[dvbdev->type], dvbdev->id);
+}
+
+
+static int __init init_dvbdev(void)
+{
+	int retval;
+	dev_t dev = MKDEV(DVB_MAJOR, 0);
+
+	if ((retval = register_chrdev_region(dev, MAX_DVB_MINORS, "DVB")) != 0) {
+		printk(KERN_ERR "dvb-core: unable to get major %d\n", DVB_MAJOR);
+		return retval;
+	}
+
+	cdev_init(&dvb_device_cdev, &dvb_device_fops);
+	if ((retval = cdev_add(&dvb_device_cdev, dev, MAX_DVB_MINORS)) != 0) {
+		printk(KERN_ERR "dvb-core: unable register character device\n");
+		goto error;
+	}
+
+	dvb_class = class_create(THIS_MODULE, "dvb");
+	if (IS_ERR(dvb_class)) {
+		retval = PTR_ERR(dvb_class);
+		goto error;
+	}
+	dvb_class->dev_uevent = dvb_uevent;
+	dvb_class->devnode = dvb_devnode;
+	return 0;
+
+error:
+	cdev_del(&dvb_device_cdev);
+	unregister_chrdev_region(dev, MAX_DVB_MINORS);
+	return retval;
+}
+
+
+static void __exit exit_dvbdev(void)
+{
+	class_destroy(dvb_class);
+	cdev_del(&dvb_device_cdev);
+	unregister_chrdev_region(MKDEV(DVB_MAJOR, 0), MAX_DVB_MINORS);
+}
+
+subsys_initcall(init_dvbdev);
+module_exit(exit_dvbdev);
+
+MODULE_DESCRIPTION("DVB Core Driver");
+MODULE_AUTHOR("Marcus Metzler, Ralph Metzler, Holger Waechtler");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb-core/dvbdev.h b/drivers/media/dvb-core/dvbdev.h
new file mode 100644
index 0000000..93a9470
--- /dev/null
+++ b/drivers/media/dvb-core/dvbdev.h
@@ -0,0 +1,146 @@
+/*
+ * dvbdev.h
+ *
+ * Copyright (C) 2000 Ralph Metzler & Marcus Metzler
+ *                    for convergence integrated media GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Lesser Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public 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 _DVBDEV_H_
+#define _DVBDEV_H_
+
+#include <linux/types.h>
+#include <linux/poll.h>
+#include <linux/fs.h>
+#include <linux/list.h>
+
+#define DVB_MAJOR 212
+
+#if defined(CONFIG_DVB_MAX_ADAPTERS) && CONFIG_DVB_MAX_ADAPTERS > 0
+  #define DVB_MAX_ADAPTERS CONFIG_DVB_MAX_ADAPTERS
+#else
+  #define DVB_MAX_ADAPTERS 8
+#endif
+
+#define DVB_UNSET (-1)
+
+#define DVB_DEVICE_VIDEO      0
+#define DVB_DEVICE_AUDIO      1
+#define DVB_DEVICE_SEC        2
+#define DVB_DEVICE_FRONTEND   3
+#define DVB_DEVICE_DEMUX      4
+#define DVB_DEVICE_DVR        5
+#define DVB_DEVICE_CA         6
+#define DVB_DEVICE_NET        7
+#define DVB_DEVICE_OSD        8
+
+#define DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr) \
+	static short adapter_nr[] = \
+		{[0 ... (DVB_MAX_ADAPTERS - 1)] = DVB_UNSET }; \
+	module_param_array(adapter_nr, short, NULL, 0444); \
+	MODULE_PARM_DESC(adapter_nr, "DVB adapter numbers")
+
+struct dvb_frontend;
+
+struct dvb_adapter {
+	int num;
+	struct list_head list_head;
+	struct list_head device_list;
+	const char *name;
+	u8 proposed_mac [6];
+	void* priv;
+
+	struct device *device;
+
+	struct module *module;
+
+	int mfe_shared;			/* indicates mutually exclusive frontends */
+	struct dvb_device *mfe_dvbdev;	/* frontend device in use */
+	struct mutex mfe_lock;		/* access lock for thread creation */
+};
+
+
+struct dvb_device {
+	struct list_head list_head;
+	const struct file_operations *fops;
+	struct dvb_adapter *adapter;
+	int type;
+	int minor;
+	u32 id;
+
+	/* in theory, 'users' can vanish now,
+	   but I don't want to change too much now... */
+	int readers;
+	int writers;
+	int users;
+
+	wait_queue_head_t	  wait_queue;
+	/* don't really need those !? -- FIXME: use video_usercopy  */
+	int (*kernel_ioctl)(struct file *file, unsigned int cmd, void *arg);
+
+	void *priv;
+};
+
+
+extern int dvb_register_adapter(struct dvb_adapter *adap, const char *name,
+				struct module *module, struct device *device,
+				short *adapter_nums);
+extern int dvb_unregister_adapter (struct dvb_adapter *adap);
+
+extern int dvb_register_device (struct dvb_adapter *adap,
+				struct dvb_device **pdvbdev,
+				const struct dvb_device *template,
+				void *priv,
+				int type);
+
+extern void dvb_unregister_device (struct dvb_device *dvbdev);
+
+extern int dvb_generic_open (struct inode *inode, struct file *file);
+extern int dvb_generic_release (struct inode *inode, struct file *file);
+extern long dvb_generic_ioctl (struct file *file,
+			      unsigned int cmd, unsigned long arg);
+
+/* we don't mess with video_usercopy() any more,
+we simply define out own dvb_usercopy(), which will hopefully become
+generic_usercopy()  someday... */
+
+extern int dvb_usercopy(struct file *file, unsigned int cmd, unsigned long arg,
+			    int (*func)(struct file *file, unsigned int cmd, void *arg));
+
+/** generic DVB attach function. */
+#ifdef CONFIG_MEDIA_ATTACH
+#define dvb_attach(FUNCTION, ARGS...) ({ \
+	void *__r = NULL; \
+	typeof(&FUNCTION) __a = symbol_request(FUNCTION); \
+	if (__a) { \
+		__r = (void *) __a(ARGS); \
+		if (__r == NULL) \
+			symbol_put(FUNCTION); \
+	} else { \
+		printk(KERN_ERR "DVB: Unable to find symbol "#FUNCTION"()\n"); \
+	} \
+	__r; \
+})
+
+#else
+#define dvb_attach(FUNCTION, ARGS...) ({ \
+	FUNCTION(ARGS); \
+})
+
+#endif
+
+#endif /* #ifndef _DVBDEV_H_ */
diff --git a/drivers/media/dvb-frontends/Kconfig b/drivers/media/dvb-frontends/Kconfig
new file mode 100644
index 0000000..5efec73
--- /dev/null
+++ b/drivers/media/dvb-frontends/Kconfig
@@ -0,0 +1,741 @@
+menu "Customise DVB Frontends"
+	visible if !MEDIA_SUBDRV_AUTOSELECT
+
+comment "Multistandard (satellite) frontends"
+	depends on DVB_CORE
+
+config DVB_STB0899
+	tristate "STB0899 based"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  A DVB-S/S2/DSS Multistandard demodulator. Say Y when you want
+	  to support this demodulator based frontends
+
+config DVB_STB6100
+	tristate "STB6100 based tuners"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  A Silicon tuner from ST used in conjunction with the STB0899
+	  demodulator. Say Y when you want to support this tuner.
+
+config DVB_STV090x
+	tristate "STV0900/STV0903(A/B) based"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  DVB-S/S2/DSS Multistandard Professional/Broadcast demodulators.
+	  Say Y when you want to support these frontends.
+
+config DVB_STV6110x
+	tristate "STV6110/(A) based tuners"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  A Silicon tuner that supports DVB-S and DVB-S2 modes
+
+comment "Multistandard (cable + terrestrial) frontends"
+	depends on DVB_CORE
+
+config DVB_DRXK
+	tristate "Micronas DRXK based"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  Micronas DRX-K DVB-C/T demodulator.
+
+	  Say Y when you want to support this frontend.
+
+config DVB_TDA18271C2DD
+	tristate "NXP TDA18271C2 silicon tuner"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  NXP TDA18271 silicon tuner.
+
+	  Say Y when you want to support this tuner.
+
+comment "DVB-S (satellite) frontends"
+	depends on DVB_CORE
+
+config DVB_CX24110
+	tristate "Conexant CX24110 based"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  A DVB-S tuner module. Say Y when you want to support this frontend.
+
+config DVB_CX24123
+	tristate "Conexant CX24123 based"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  A DVB-S tuner module. Say Y when you want to support this frontend.
+
+config DVB_MT312
+	tristate "Zarlink VP310/MT312/ZL10313 based"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	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 !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  A DVB-S tuner module. Say Y when you want to support this frontend.
+
+config DVB_ZL10039
+	tristate "Zarlink ZL10039 silicon tuner"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	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
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  A DVB-S tuner module. Say Y when you want to support this frontend.
+
+config DVB_STV0288
+	tristate "ST STV0288 based"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  A DVB-S tuner module. Say Y when you want to support this frontend.
+
+config DVB_STB6000
+	tristate "ST STB6000 silicon tuner"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	  help
+	  A DVB-S silicon tuner module. Say Y when you want to support this tuner.
+
+config DVB_STV0299
+	tristate "ST STV0299 based"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	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 !MEDIA_SUBDRV_AUTOSELECT
+	  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 !MEDIA_SUBDRV_AUTOSELECT
+	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
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  A DVB-S tuner module. Say Y when you want to support this frontend.
+
+config DVB_TDA10086
+	tristate "Philips TDA10086 based"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  A DVB-S tuner module. Say Y when you want to support this frontend.
+
+config DVB_TDA8261
+	tristate "Philips TDA8261 based"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  A DVB-S tuner module. Say Y when you want to support this frontend.
+
+config DVB_VES1X93
+	tristate "VLSI VES1893 or VES1993 based"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  A DVB-S tuner module. Say Y when you want to support this frontend.
+
+config DVB_TUNER_ITD1000
+	tristate "Integrant ITD1000 Zero IF tuner for DVB-S/DSS"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  A DVB-S tuner module. Say Y when you want to support this frontend.
+
+config DVB_TUNER_CX24113
+	tristate "Conexant CX24113/CX24128 tuner for DVB-S/DSS"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  A DVB-S tuner module. Say Y when you want to support this frontend.
+
+
+config DVB_TDA826X
+	tristate "Philips TDA826X silicon tuner"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  A DVB-S silicon tuner module. Say Y when you want to support this tuner.
+
+config DVB_TUA6100
+	tristate "Infineon TUA6100 PLL"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  A DVB-S PLL chip.
+
+config DVB_CX24116
+	tristate "Conexant CX24116 based"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  A DVB-S/S2 tuner module. Say Y when you want to support this frontend.
+
+config DVB_SI21XX
+	tristate "Silicon Labs SI21XX based"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  A DVB-S tuner module. Say Y when you want to support this frontend.
+
+config DVB_DS3000
+	tristate "Montage Tehnology DS3000 based"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  A DVB-S/S2 tuner module. Say Y when you want to support this frontend.
+
+config DVB_MB86A16
+	tristate "Fujitsu MB86A16 based"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  A DVB-S/DSS Direct Conversion reveiver.
+	  Say Y when you want to support this frontend.
+
+config DVB_TDA10071
+	tristate "NXP TDA10071"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  Say Y when you want to support this frontend.
+
+comment "DVB-T (terrestrial) frontends"
+	depends on DVB_CORE
+
+config DVB_SP8870
+	tristate "Spase sp8870 based"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  A DVB-T tuner module. Say Y when you want to support this frontend.
+
+	  This driver needs external firmware. Please use the command
+	  "<kerneldir>/Documentation/dvb/get_dvb_firmware sp8870" to
+	  download/extract it, and then copy it to /usr/lib/hotplug/firmware
+	  or /lib/firmware (depending on configuration of firmware hotplug).
+
+config DVB_SP887X
+	tristate "Spase sp887x based"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  A DVB-T tuner module. Say Y when you want to support this frontend.
+
+	  This driver needs external firmware. Please use the command
+	  "<kerneldir>/Documentation/dvb/get_dvb_firmware sp887x" to
+	  download/extract it, and then copy it to /usr/lib/hotplug/firmware
+	  or /lib/firmware (depending on configuration of firmware hotplug).
+
+config DVB_CX22700
+	tristate "Conexant CX22700 based"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  A DVB-T tuner module. Say Y when you want to support this frontend.
+
+config DVB_CX22702
+	tristate "Conexant cx22702 demodulator (OFDM)"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  A DVB-T tuner module. Say Y when you want to support this frontend.
+
+config DVB_S5H1432
+	tristate "Samsung s5h1432 demodulator (OFDM)"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  A DVB-T tuner module. Say Y when you want to support this frontend.
+
+config DVB_DRXD
+	tristate "Micronas DRXD driver"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  A DVB-T tuner module. Say Y when you want to support this frontend.
+
+	  Note: this driver was based on vendor driver reference code (released
+	  under the GPL) as opposed to the existing drx397xd driver, which
+	  was written via reverse engineering.
+
+config DVB_L64781
+	tristate "LSI L64781"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  A DVB-T tuner module. Say Y when you want to support this frontend.
+
+config DVB_TDA1004X
+	tristate "Philips TDA10045H/TDA10046H based"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  A DVB-T tuner module. Say Y when you want to support this frontend.
+
+	  This driver needs external firmware. Please use the commands
+	  "<kerneldir>/Documentation/dvb/get_dvb_firmware tda10045",
+	  "<kerneldir>/Documentation/dvb/get_dvb_firmware tda10046" to
+	  download/extract them, and then copy them to /usr/lib/hotplug/firmware
+	  or /lib/firmware (depending on configuration of firmware hotplug).
+
+config DVB_NXT6000
+	tristate "NxtWave Communications NXT6000 based"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  A DVB-T tuner module. Say Y when you want to support this frontend.
+
+config DVB_MT352
+	tristate "Zarlink MT352 based"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  A DVB-T tuner module. Say Y when you want to support this frontend.
+
+config DVB_ZL10353
+	tristate "Zarlink ZL10353 based"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  A DVB-T tuner module. Say Y when you want to support this frontend.
+
+config DVB_DIB3000MB
+	tristate "DiBcom 3000M-B"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  A DVB-T tuner module. Designed for mobile usage. Say Y when you want
+	  to support this frontend.
+
+config DVB_DIB3000MC
+	tristate "DiBcom 3000P/M-C"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  A DVB-T tuner module. Designed for mobile usage. Say Y when you want
+	  to support this frontend.
+
+config DVB_DIB7000M
+	tristate "DiBcom 7000MA/MB/PA/PB/MC"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  A DVB-T tuner module. Designed for mobile usage. Say Y when you want
+	  to support this frontend.
+
+config DVB_DIB7000P
+	tristate "DiBcom 7000PC"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  A DVB-T tuner module. Designed for mobile usage. Say Y when you want
+	  to support this frontend.
+
+config DVB_DIB9000
+	tristate "DiBcom 9000"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  A DVB-T tuner module. Designed for mobile usage. Say Y when you want
+	  to support this frontend.
+
+config DVB_TDA10048
+	tristate "Philips TDA10048HN based"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	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 !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  Say Y when you want to support this frontend.
+
+config DVB_EC100
+	tristate "E3C EC100"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  Say Y when you want to support this frontend.
+
+config DVB_HD29L2
+	tristate "HDIC HD29L2"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  Say Y when you want to support this frontend.
+
+config DVB_STV0367
+	tristate "ST STV0367 based"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  A DVB-T/C tuner module. Say Y when you want to support this frontend.
+
+config DVB_CXD2820R
+	tristate "Sony CXD2820R"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  Say Y when you want to support this frontend.
+
+config DVB_RTL2830
+	tristate "Realtek RTL2830 DVB-T"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  Say Y when you want to support this frontend.
+
+config DVB_RTL2832
+	tristate "Realtek RTL2832 DVB-T"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  Say Y when you want to support this frontend.
+
+comment "DVB-C (cable) frontends"
+	depends on DVB_CORE
+
+config DVB_VES1820
+	tristate "VLSI VES1820 based"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  A DVB-C tuner module. Say Y when you want to support this frontend.
+
+config DVB_TDA10021
+	tristate "Philips TDA10021 based"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  A DVB-C tuner module. Say Y when you want to support this frontend.
+
+config DVB_TDA10023
+	tristate "Philips TDA10023 based"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  A DVB-C tuner module. Say Y when you want to support this frontend.
+
+config DVB_STV0297
+	tristate "ST STV0297 based"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  A DVB-C tuner module. Say Y when you want to support this frontend.
+
+comment "ATSC (North American/Korean Terrestrial/Cable DTV) frontends"
+	depends on DVB_CORE
+
+config DVB_NXT200X
+	tristate "NxtWave Communications NXT2002/NXT2004 based"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
+	  to support this frontend.
+
+	  This driver needs external firmware. Please use the commands
+	  "<kerneldir>/Documentation/dvb/get_dvb_firmware nxt2002" and
+	  "<kerneldir>/Documentation/dvb/get_dvb_firmware nxt2004" to
+	  download/extract them, and then copy them to /usr/lib/hotplug/firmware
+	  or /lib/firmware (depending on configuration of firmware hotplug).
+
+config DVB_OR51211
+	tristate "Oren OR51211 based"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  An ATSC 8VSB tuner module. Say Y when you want to support this frontend.
+
+	  This driver needs external firmware. Please use the command
+	  "<kerneldir>/Documentation/dvb/get_dvb_firmware or51211" to
+	  download it, and then copy it to /usr/lib/hotplug/firmware
+	  or /lib/firmware (depending on configuration of firmware hotplug).
+
+config DVB_OR51132
+	tristate "Oren OR51132 based"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
+	  to support this frontend.
+
+	  This driver needs external firmware. Please use the commands
+	  "<kerneldir>/Documentation/dvb/get_dvb_firmware or51132_vsb" and/or
+	  "<kerneldir>/Documentation/dvb/get_dvb_firmware or51132_qam" to
+	  download firmwares for 8VSB and QAM64/256, respectively. Copy them to
+	  /usr/lib/hotplug/firmware or /lib/firmware (depending on
+	  configuration of firmware hotplug).
+
+config DVB_BCM3510
+	tristate "Broadcom BCM3510"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  An ATSC 8VSB/16VSB and QAM64/256 tuner module. Say Y when you want to
+	  support this frontend.
+
+config DVB_LGDT330X
+	tristate "LG Electronics LGDT3302/LGDT3303 based"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
+	  to support this frontend.
+
+config DVB_LGDT3305
+	tristate "LG Electronics LGDT3304 and LGDT3305 based"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
+	  to support this frontend.
+
+config DVB_LG2160
+	tristate "LG Electronics LG216x based"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  An ATSC/MH demodulator module. Say Y when you want
+	  to support this frontend.
+
+config DVB_S5H1409
+	tristate "Samsung S5H1409 based"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
+	  to support this frontend.
+
+config DVB_AU8522
+	depends on I2C
+	tristate
+
+config DVB_AU8522_DTV
+	tristate "Auvitek AU8522 based DTV demod"
+	depends on DVB_CORE && I2C
+	select DVB_AU8522
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  An ATSC 8VSB, QAM64/256 & NTSC demodulator module. Say Y when
+	  you want to enable DTV demodulation support for this frontend.
+
+config DVB_AU8522_V4L
+	tristate "Auvitek AU8522 based ATV demod"
+	depends on VIDEO_V4L2 && I2C
+	select DVB_AU8522
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  An ATSC 8VSB, QAM64/256 & NTSC demodulator module. Say Y when
+	  you want to enable ATV demodulation support for this frontend.
+
+config DVB_S5H1411
+	tristate "Samsung S5H1411 based"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
+	  to support this frontend.
+
+comment "ISDB-T (terrestrial) frontends"
+	depends on DVB_CORE
+
+config DVB_S921
+	tristate "Sharp S921 frontend"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  AN ISDB-T DQPSK, QPSK, 16QAM and 64QAM 1seg tuner module.
+	  Say Y when you want to support this frontend.
+
+config DVB_DIB8000
+	tristate "DiBcom 8000MB/MC"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  A driver for DiBcom's DiB8000 ISDB-T/ISDB-Tsb demodulator.
+	  Say Y when you want to support this frontend.
+
+config DVB_MB86A20S
+	tristate "Fujitsu mb86a20s"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  A driver for Fujitsu mb86a20s ISDB-T/ISDB-Tsb demodulator.
+	  Say Y when you want to support this frontend.
+
+comment "Digital terrestrial only tuners/PLL"
+	depends on DVB_CORE
+
+config DVB_PLL
+	tristate "Generic I2C PLL based tuners"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  This module drives a number of tuners based on PLL chips with a
+	  common I2C interface. Say Y when you want to support these tuners.
+
+config DVB_TUNER_DIB0070
+	tristate "DiBcom DiB0070 silicon base-band tuner"
+	depends on I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  A driver for the silicon baseband tuner DiB0070 from DiBcom.
+	  This device is only used inside a SiP called together with a
+	  demodulator for now.
+
+config DVB_TUNER_DIB0090
+	tristate "DiBcom DiB0090 silicon base-band tuner"
+	depends on I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  A driver for the silicon baseband tuner DiB0090 from DiBcom.
+	  This device is only used inside a SiP called together with a
+	  demodulator for now.
+
+comment "SEC control devices for DVB-S"
+	depends on DVB_CORE
+
+config DVB_LNBP21
+	tristate "LNBP21/LNBH24 SEC controllers"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  An SEC control chips.
+
+config DVB_LNBP22
+	tristate "LNBP22 SEC controllers"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  LNB power supply and control voltage
+	  regulator chip with step-up converter
+	  and I2C interface.
+	  Say Y when you want to support this chip.
+
+config DVB_ISL6405
+	tristate "ISL6405 SEC controller"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  An SEC control chip.
+
+config DVB_ISL6421
+	tristate "ISL6421 SEC controller"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  An SEC control chip.
+
+config DVB_ISL6423
+	tristate "ISL6423 SEC controller"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  A SEC controller chip from Intersil
+
+config DVB_A8293
+	tristate "Allegro A8293"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+
+config DVB_LGS8GL5
+	tristate "Silicon Legend LGS-8GL5 demodulator (OFDM)"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  A DMB-TH tuner module. Say Y when you want to support this frontend.
+
+config DVB_LGS8GXX
+	tristate "Legend Silicon LGS8913/LGS8GL5/LGS8GXX DMB-TH demodulator"
+	depends on DVB_CORE && I2C
+	select FW_LOADER
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  A DMB-TH tuner module. Say Y when you want to support this frontend.
+
+config DVB_ATBM8830
+	tristate "AltoBeam ATBM8830/8831 DMB-TH demodulator"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  A DMB-TH tuner module. Say Y when you want to support this frontend.
+
+config DVB_TDA665x
+	tristate "TDA665x tuner"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  Support for tuner modules based on Philips TDA6650/TDA6651 chips.
+	  Say Y when you want to support this chip.
+
+	  Currently supported tuners:
+	  * Panasonic ENV57H12D5 (ET-50DT)
+
+config DVB_IX2505V
+	tristate "Sharp IX2505V silicon tuner"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  A DVB-S tuner module. Say Y when you want to support this frontend.
+
+config DVB_IT913X_FE
+	tristate "it913x frontend and it9137 tuner"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  A DVB-T tuner module.
+	  Say Y when you want to support this frontend.
+
+config DVB_M88RS2000
+	tristate "M88RS2000 DVB-S demodulator and tuner"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  A DVB-S tuner module.
+	  Say Y when you want to support this frontend.
+
+config DVB_AF9033
+	tristate "Afatech AF9033 DVB-T demodulator"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+
+comment "Tools to develop new frontends"
+
+config DVB_DUMMY_FE
+	tristate "Dummy frontend driver"
+	default n
+endmenu
diff --git a/drivers/media/dvb-frontends/Makefile b/drivers/media/dvb-frontends/Makefile
new file mode 100644
index 0000000..7eb73bb
--- /dev/null
+++ b/drivers/media/dvb-frontends/Makefile
@@ -0,0 +1,105 @@
+#
+# Makefile for the kernel DVB frontend device drivers.
+#
+
+ccflags-y += -I$(srctree)/drivers/media/dvb-core/
+ccflags-y += -I$(srctree)/drivers/media/tuners/
+
+stb0899-objs := stb0899_drv.o stb0899_algo.o
+stv0900-objs := stv0900_core.o stv0900_sw.o
+drxd-objs := drxd_firm.o drxd_hard.o
+cxd2820r-objs := cxd2820r_core.o cxd2820r_c.o cxd2820r_t.o cxd2820r_t2.o
+drxk-objs := drxk_hard.o
+
+obj-$(CONFIG_DVB_PLL) += dvb-pll.o
+obj-$(CONFIG_DVB_STV0299) += stv0299.o
+obj-$(CONFIG_DVB_STB0899) += stb0899.o
+obj-$(CONFIG_DVB_STB6100) += stb6100.o
+obj-$(CONFIG_DVB_SP8870) += sp8870.o
+obj-$(CONFIG_DVB_CX22700) += cx22700.o
+obj-$(CONFIG_DVB_S5H1432) += s5h1432.o
+obj-$(CONFIG_DVB_CX24110) += cx24110.o
+obj-$(CONFIG_DVB_TDA8083) += tda8083.o
+obj-$(CONFIG_DVB_L64781) += l64781.o
+obj-$(CONFIG_DVB_DIB3000MB) += dib3000mb.o
+obj-$(CONFIG_DVB_DIB3000MC) += dib3000mc.o dibx000_common.o
+obj-$(CONFIG_DVB_DIB7000M) += dib7000m.o dibx000_common.o
+obj-$(CONFIG_DVB_DIB7000P) += dib7000p.o dibx000_common.o
+obj-$(CONFIG_DVB_DIB8000) += dib8000.o dibx000_common.o
+obj-$(CONFIG_DVB_DIB9000) += dib9000.o dibx000_common.o
+obj-$(CONFIG_DVB_MT312) += mt312.o
+obj-$(CONFIG_DVB_VES1820) += ves1820.o
+obj-$(CONFIG_DVB_VES1X93) += ves1x93.o
+obj-$(CONFIG_DVB_TDA1004X) += tda1004x.o
+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_ZL10039) += zl10039.o
+obj-$(CONFIG_DVB_ZL10353) += zl10353.o
+obj-$(CONFIG_DVB_CX22702) += cx22702.o
+obj-$(CONFIG_DVB_DRXD) += drxd.o
+obj-$(CONFIG_DVB_TDA10021) += tda10021.o
+obj-$(CONFIG_DVB_TDA10023) += tda10023.o
+obj-$(CONFIG_DVB_STV0297) += stv0297.o
+obj-$(CONFIG_DVB_NXT200X) += nxt200x.o
+obj-$(CONFIG_DVB_OR51211) += or51211.o
+obj-$(CONFIG_DVB_OR51132) += or51132.o
+obj-$(CONFIG_DVB_BCM3510) += bcm3510.o
+obj-$(CONFIG_DVB_S5H1420) += s5h1420.o
+obj-$(CONFIG_DVB_LGDT330X) += lgdt330x.o
+obj-$(CONFIG_DVB_LGDT3305) += lgdt3305.o
+obj-$(CONFIG_DVB_LG2160) += lg2160.o
+obj-$(CONFIG_DVB_CX24123) += cx24123.o
+obj-$(CONFIG_DVB_LNBP21) += lnbp21.o
+obj-$(CONFIG_DVB_LNBP22) += lnbp22.o
+obj-$(CONFIG_DVB_ISL6405) += isl6405.o
+obj-$(CONFIG_DVB_ISL6421) += isl6421.o
+obj-$(CONFIG_DVB_TDA10086) += tda10086.o
+obj-$(CONFIG_DVB_TDA826X) += tda826x.o
+obj-$(CONFIG_DVB_TDA8261) += tda8261.o
+obj-$(CONFIG_DVB_TUNER_DIB0070) += dib0070.o
+obj-$(CONFIG_DVB_TUNER_DIB0090) += dib0090.o
+obj-$(CONFIG_DVB_TUA6100) += tua6100.o
+obj-$(CONFIG_DVB_S5H1409) += s5h1409.o
+obj-$(CONFIG_DVB_TUNER_ITD1000) += itd1000.o
+obj-$(CONFIG_DVB_AU8522) += au8522_common.o
+obj-$(CONFIG_DVB_AU8522_DTV) += au8522_dig.o
+obj-$(CONFIG_DVB_AU8522_V4L) += au8522_decoder.o
+obj-$(CONFIG_DVB_TDA10048) += tda10048.o
+obj-$(CONFIG_DVB_TUNER_CX24113) += cx24113.o
+obj-$(CONFIG_DVB_S5H1411) += s5h1411.o
+obj-$(CONFIG_DVB_LGS8GL5) += lgs8gl5.o
+obj-$(CONFIG_DVB_TDA665x) += tda665x.o
+obj-$(CONFIG_DVB_LGS8GXX) += lgs8gxx.o
+obj-$(CONFIG_DVB_ATBM8830) += atbm8830.o
+obj-$(CONFIG_DVB_DUMMY_FE) += dvb_dummy_fe.o
+obj-$(CONFIG_DVB_AF9013) += af9013.o
+obj-$(CONFIG_DVB_CX24116) += cx24116.o
+obj-$(CONFIG_DVB_SI21XX) += si21xx.o
+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
+obj-$(CONFIG_DVB_STV090x) += stv090x.o
+obj-$(CONFIG_DVB_STV6110x) += stv6110x.o
+obj-$(CONFIG_DVB_ISL6423) += isl6423.o
+obj-$(CONFIG_DVB_EC100) += ec100.o
+obj-$(CONFIG_DVB_HD29L2) += hd29l2.o
+obj-$(CONFIG_DVB_DS3000) += ds3000.o
+obj-$(CONFIG_DVB_MB86A16) += mb86a16.o
+obj-$(CONFIG_DVB_MB86A20S) += mb86a20s.o
+obj-$(CONFIG_DVB_IX2505V) += ix2505v.o
+obj-$(CONFIG_DVB_STV0367) += stv0367.o
+obj-$(CONFIG_DVB_CXD2820R) += cxd2820r.o
+obj-$(CONFIG_DVB_DRXK) += drxk.o
+obj-$(CONFIG_DVB_TDA18271C2DD) += tda18271c2dd.o
+obj-$(CONFIG_DVB_IT913X_FE) += it913x-fe.o
+obj-$(CONFIG_DVB_A8293) += a8293.o
+obj-$(CONFIG_DVB_TDA10071) += tda10071.o
+obj-$(CONFIG_DVB_RTL2830) += rtl2830.o
+obj-$(CONFIG_DVB_RTL2832) += rtl2832.o
+obj-$(CONFIG_DVB_M88RS2000) += m88rs2000.o
+obj-$(CONFIG_DVB_AF9033) += af9033.o
+
diff --git a/drivers/media/dvb-frontends/a8293.c b/drivers/media/dvb-frontends/a8293.c
new file mode 100644
index 0000000..cff44a3
--- /dev/null
+++ b/drivers/media/dvb-frontends/a8293.c
@@ -0,0 +1,167 @@
+/*
+ * Allegro A8293 SEC driver
+ *
+ * Copyright (C) 2011 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.,
+ *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "dvb_frontend.h"
+#include "a8293.h"
+
+struct a8293_priv {
+	struct i2c_adapter *i2c;
+	const struct a8293_config *cfg;
+	u8 reg[2];
+};
+
+static int a8293_i2c(struct a8293_priv *priv, u8 *val, int len, bool rd)
+{
+	int ret;
+	struct i2c_msg msg[1] = {
+		{
+			.addr = priv->cfg->i2c_addr,
+			.len = len,
+			.buf = val,
+		}
+	};
+
+	if (rd)
+		msg[0].flags = I2C_M_RD;
+	else
+		msg[0].flags = 0;
+
+	ret = i2c_transfer(priv->i2c, msg, 1);
+	if (ret == 1) {
+		ret = 0;
+	} else {
+		dev_warn(&priv->i2c->dev, "%s: i2c failed=%d rd=%d\n",
+				KBUILD_MODNAME, ret, rd);
+		ret = -EREMOTEIO;
+	}
+
+	return ret;
+}
+
+static int a8293_wr(struct a8293_priv *priv, u8 *val, int len)
+{
+	return a8293_i2c(priv, val, len, 0);
+}
+
+static int a8293_rd(struct a8293_priv *priv, u8 *val, int len)
+{
+	return a8293_i2c(priv, val, len, 1);
+}
+
+static int a8293_set_voltage(struct dvb_frontend *fe,
+	fe_sec_voltage_t fe_sec_voltage)
+{
+	struct a8293_priv *priv = fe->sec_priv;
+	int ret;
+
+	dev_dbg(&priv->i2c->dev, "%s: fe_sec_voltage=%d\n", __func__,
+			fe_sec_voltage);
+
+	switch (fe_sec_voltage) {
+	case SEC_VOLTAGE_OFF:
+		/* ENB=0 */
+		priv->reg[0] = 0x10;
+		break;
+	case SEC_VOLTAGE_13:
+		/* VSEL0=1, VSEL1=0, VSEL2=0, VSEL3=0, ENB=1*/
+		priv->reg[0] = 0x31;
+		break;
+	case SEC_VOLTAGE_18:
+		/* VSEL0=0, VSEL1=0, VSEL2=0, VSEL3=1, ENB=1*/
+		priv->reg[0] = 0x38;
+		break;
+	default:
+		ret = -EINVAL;
+		goto err;
+	};
+
+	ret = a8293_wr(priv, &priv->reg[0], 1);
+	if (ret)
+		goto err;
+
+	return ret;
+err:
+	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	return ret;
+}
+
+static void a8293_release_sec(struct dvb_frontend *fe)
+{
+	a8293_set_voltage(fe, SEC_VOLTAGE_OFF);
+
+	kfree(fe->sec_priv);
+	fe->sec_priv = NULL;
+}
+
+struct dvb_frontend *a8293_attach(struct dvb_frontend *fe,
+	struct i2c_adapter *i2c, const struct a8293_config *cfg)
+{
+	int ret;
+	struct a8293_priv *priv = NULL;
+	u8 buf[2];
+
+	/* allocate memory for the internal priv */
+	priv = kzalloc(sizeof(struct a8293_priv), GFP_KERNEL);
+	if (priv == NULL) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	/* setup the priv */
+	priv->i2c = i2c;
+	priv->cfg = cfg;
+	fe->sec_priv = priv;
+
+	/* check if the SEC is there */
+	ret = a8293_rd(priv, buf, 2);
+	if (ret)
+		goto err;
+
+	/* ENB=0 */
+	priv->reg[0] = 0x10;
+	ret = a8293_wr(priv, &priv->reg[0], 1);
+	if (ret)
+		goto err;
+
+	/* TMODE=0, TGATE=1 */
+	priv->reg[1] = 0x82;
+	ret = a8293_wr(priv, &priv->reg[1], 1);
+	if (ret)
+		goto err;
+
+	fe->ops.release_sec = a8293_release_sec;
+
+	/* override frontend ops */
+	fe->ops.set_voltage = a8293_set_voltage;
+
+	dev_info(&priv->i2c->dev, "%s: Allegro A8293 SEC attached\n",
+			KBUILD_MODNAME);
+
+	return fe;
+err:
+	dev_dbg(&i2c->dev, "%s: failed=%d\n", __func__, ret);
+	kfree(priv);
+	return NULL;
+}
+EXPORT_SYMBOL(a8293_attach);
+
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
+MODULE_DESCRIPTION("Allegro A8293 SEC driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb-frontends/a8293.h b/drivers/media/dvb-frontends/a8293.h
new file mode 100644
index 0000000..ed29e55
--- /dev/null
+++ b/drivers/media/dvb-frontends/a8293.h
@@ -0,0 +1,41 @@
+/*
+ * Allegro A8293 SEC driver
+ *
+ * Copyright (C) 2011 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.,
+ *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef A8293_H
+#define A8293_H
+
+struct a8293_config {
+	u8 i2c_addr;
+};
+
+#if defined(CONFIG_DVB_A8293) || \
+	(defined(CONFIG_DVB_A8293_MODULE) && defined(MODULE))
+extern struct dvb_frontend *a8293_attach(struct dvb_frontend *fe,
+	struct i2c_adapter *i2c, const struct a8293_config *cfg);
+#else
+static inline struct dvb_frontend *a8293_attach(struct dvb_frontend *fe,
+	struct i2c_adapter *i2c, const struct a8293_config *cfg)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif
+
+#endif /* A8293_H */
diff --git a/drivers/media/dvb-frontends/af9013.c b/drivers/media/dvb-frontends/af9013.c
new file mode 100644
index 0000000..e9f04a3
--- /dev/null
+++ b/drivers/media/dvb-frontends/af9013.c
@@ -0,0 +1,1548 @@
+/*
+ * Afatech AF9013 demodulator driver
+ *
+ * Copyright (C) 2007 Antti Palosaari <crope@iki.fi>
+ * Copyright (C) 2011 Antti Palosaari <crope@iki.fi>
+ *
+ * Thanks to Afatech who kindly provided information.
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You 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 "af9013_priv.h"
+
+struct af9013_state {
+	struct i2c_adapter *i2c;
+	struct dvb_frontend fe;
+	struct af9013_config config;
+
+	/* tuner/demod RF and IF AGC limits used for signal strength calc */
+	u8 signal_strength_en, rf_50, rf_80, if_50, if_80;
+	u16 signal_strength;
+	u32 ber;
+	u32 ucblocks;
+	u16 snr;
+	u32 bandwidth_hz;
+	fe_status_t fe_status;
+	unsigned long set_frontend_jiffies;
+	unsigned long read_status_jiffies;
+	bool first_tune;
+	bool i2c_gate_state;
+	unsigned int statistics_step:3;
+	struct delayed_work statistics_work;
+};
+
+/* write multiple registers */
+static int af9013_wr_regs_i2c(struct af9013_state *priv, u8 mbox, u16 reg,
+	const u8 *val, int len)
+{
+	int ret;
+	u8 buf[3+len];
+	struct i2c_msg msg[1] = {
+		{
+			.addr = priv->config.i2c_addr,
+			.flags = 0,
+			.len = sizeof(buf),
+			.buf = buf,
+		}
+	};
+
+	buf[0] = (reg >> 8) & 0xff;
+	buf[1] = (reg >> 0) & 0xff;
+	buf[2] = mbox;
+	memcpy(&buf[3], val, len);
+
+	ret = i2c_transfer(priv->i2c, msg, 1);
+	if (ret == 1) {
+		ret = 0;
+	} else {
+		dev_warn(&priv->i2c->dev, "%s: i2c wr failed=%d reg=%04x " \
+				"len=%d\n", KBUILD_MODNAME, ret, reg, len);
+		ret = -EREMOTEIO;
+	}
+	return ret;
+}
+
+/* read multiple registers */
+static int af9013_rd_regs_i2c(struct af9013_state *priv, u8 mbox, u16 reg,
+	u8 *val, int len)
+{
+	int ret;
+	u8 buf[3];
+	struct i2c_msg msg[2] = {
+		{
+			.addr = priv->config.i2c_addr,
+			.flags = 0,
+			.len = 3,
+			.buf = buf,
+		}, {
+			.addr = priv->config.i2c_addr,
+			.flags = I2C_M_RD,
+			.len = len,
+			.buf = val,
+		}
+	};
+
+	buf[0] = (reg >> 8) & 0xff;
+	buf[1] = (reg >> 0) & 0xff;
+	buf[2] = mbox;
+
+	ret = i2c_transfer(priv->i2c, msg, 2);
+	if (ret == 2) {
+		ret = 0;
+	} else {
+		dev_warn(&priv->i2c->dev, "%s: i2c rd failed=%d reg=%04x " \
+				"len=%d\n", KBUILD_MODNAME, ret, reg, len);
+		ret = -EREMOTEIO;
+	}
+	return ret;
+}
+
+/* write multiple registers */
+static int af9013_wr_regs(struct af9013_state *priv, u16 reg, const u8 *val,
+	int len)
+{
+	int ret, i;
+	u8 mbox = (0 << 7)|(0 << 6)|(1 << 1)|(1 << 0);
+
+	if ((priv->config.ts_mode == AF9013_TS_USB) &&
+		((reg & 0xff00) != 0xff00) && ((reg & 0xff00) != 0xae00)) {
+		mbox |= ((len - 1) << 2);
+		ret = af9013_wr_regs_i2c(priv, mbox, reg, val, len);
+	} else {
+		for (i = 0; i < len; i++) {
+			ret = af9013_wr_regs_i2c(priv, mbox, reg+i, val+i, 1);
+			if (ret)
+				goto err;
+		}
+	}
+
+err:
+	return 0;
+}
+
+/* read multiple registers */
+static int af9013_rd_regs(struct af9013_state *priv, u16 reg, u8 *val, int len)
+{
+	int ret, i;
+	u8 mbox = (0 << 7)|(0 << 6)|(1 << 1)|(0 << 0);
+
+	if ((priv->config.ts_mode == AF9013_TS_USB) &&
+		((reg & 0xff00) != 0xff00) && ((reg & 0xff00) != 0xae00)) {
+		mbox |= ((len - 1) << 2);
+		ret = af9013_rd_regs_i2c(priv, mbox, reg, val, len);
+	} else {
+		for (i = 0; i < len; i++) {
+			ret = af9013_rd_regs_i2c(priv, mbox, reg+i, val+i, 1);
+			if (ret)
+				goto err;
+		}
+	}
+
+err:
+	return 0;
+}
+
+/* write single register */
+static int af9013_wr_reg(struct af9013_state *priv, u16 reg, u8 val)
+{
+	return af9013_wr_regs(priv, reg, &val, 1);
+}
+
+/* read single register */
+static int af9013_rd_reg(struct af9013_state *priv, u16 reg, u8 *val)
+{
+	return af9013_rd_regs(priv, reg, val, 1);
+}
+
+static int af9013_write_ofsm_regs(struct af9013_state *state, u16 reg, u8 *val,
+	u8 len)
+{
+	u8 mbox = (1 << 7)|(1 << 6)|((len - 1) << 2)|(1 << 1)|(1 << 0);
+	return af9013_wr_regs_i2c(state, mbox, reg, val, len);
+}
+
+static int af9013_wr_reg_bits(struct af9013_state *state, u16 reg, int pos,
+	int len, u8 val)
+{
+	int ret;
+	u8 tmp, mask;
+
+	/* no need for read if whole reg is written */
+	if (len != 8) {
+		ret = af9013_rd_reg(state, reg, &tmp);
+		if (ret)
+			return ret;
+
+		mask = (0xff >> (8 - len)) << pos;
+		val <<= pos;
+		tmp &= ~mask;
+		val |= tmp;
+	}
+
+	return af9013_wr_reg(state, reg, val);
+}
+
+static int af9013_rd_reg_bits(struct af9013_state *state, u16 reg, int pos,
+	int len, u8 *val)
+{
+	int ret;
+	u8 tmp;
+
+	ret = af9013_rd_reg(state, reg, &tmp);
+	if (ret)
+		return ret;
+
+	*val = (tmp >> pos);
+	*val &= (0xff >> (8 - len));
+
+	return 0;
+}
+
+static int af9013_set_gpio(struct af9013_state *state, u8 gpio, u8 gpioval)
+{
+	int ret;
+	u8 pos;
+	u16 addr;
+
+	dev_dbg(&state->i2c->dev, "%s: gpio=%d gpioval=%02x\n",
+			__func__, gpio, gpioval);
+
+	/*
+	 * GPIO0 & GPIO1 0xd735
+	 * GPIO2 & GPIO3 0xd736
+	 */
+
+	switch (gpio) {
+	case 0:
+	case 1:
+		addr = 0xd735;
+		break;
+	case 2:
+	case 3:
+		addr = 0xd736;
+		break;
+
+	default:
+		dev_err(&state->i2c->dev, "%s: invalid gpio=%d\n",
+				KBUILD_MODNAME, gpio);
+		ret = -EINVAL;
+		goto err;
+	};
+
+	switch (gpio) {
+	case 0:
+	case 2:
+		pos = 0;
+		break;
+	case 1:
+	case 3:
+	default:
+		pos = 4;
+		break;
+	};
+
+	ret = af9013_wr_reg_bits(state, addr, pos, 4, gpioval);
+	if (ret)
+		goto err;
+
+	return ret;
+err:
+	dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	return ret;
+}
+
+static u32 af9013_div(struct af9013_state *state, u32 a, u32 b, u32 x)
+{
+	u32 r = 0, c = 0, i;
+
+	dev_dbg(&state->i2c->dev, "%s: a=%d b=%d x=%d\n", __func__, a, b, x);
+
+	if (a > b) {
+		c = a / b;
+		a = a - c * b;
+	}
+
+	for (i = 0; i < x; i++) {
+		if (a >= b) {
+			r += 1;
+			a -= b;
+		}
+		a <<= 1;
+		r <<= 1;
+	}
+	r = (c << (u32)x) + r;
+
+	dev_dbg(&state->i2c->dev, "%s: a=%d b=%d x=%d r=%d r=%x\n",
+			__func__, a, b, x, r, r);
+
+	return r;
+}
+
+static int af9013_power_ctrl(struct af9013_state *state, u8 onoff)
+{
+	int ret, i;
+	u8 tmp;
+
+	dev_dbg(&state->i2c->dev, "%s: onoff=%d\n", __func__, onoff);
+
+	/* enable reset */
+	ret = af9013_wr_reg_bits(state, 0xd417, 4, 1, 1);
+	if (ret)
+		goto err;
+
+	/* start reset mechanism */
+	ret = af9013_wr_reg(state, 0xaeff, 1);
+	if (ret)
+		goto err;
+
+	/* wait reset performs */
+	for (i = 0; i < 150; i++) {
+		ret = af9013_rd_reg_bits(state, 0xd417, 1, 1, &tmp);
+		if (ret)
+			goto err;
+
+		if (tmp)
+			break; /* reset done */
+
+		usleep_range(5000, 25000);
+	}
+
+	if (!tmp)
+		return -ETIMEDOUT;
+
+	if (onoff) {
+		/* clear reset */
+		ret = af9013_wr_reg_bits(state, 0xd417, 1, 1, 0);
+		if (ret)
+			goto err;
+
+		/* disable reset */
+		ret = af9013_wr_reg_bits(state, 0xd417, 4, 1, 0);
+
+		/* power on */
+		ret = af9013_wr_reg_bits(state, 0xd73a, 3, 1, 0);
+	} else {
+		/* power off */
+		ret = af9013_wr_reg_bits(state, 0xd73a, 3, 1, 1);
+	}
+
+	return ret;
+err:
+	dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	return ret;
+}
+
+static int af9013_statistics_ber_unc_start(struct dvb_frontend *fe)
+{
+	struct af9013_state *state = fe->demodulator_priv;
+	int ret;
+
+	dev_dbg(&state->i2c->dev, "%s:\n", __func__);
+
+	/* reset and start BER counter */
+	ret = af9013_wr_reg_bits(state, 0xd391, 4, 1, 1);
+	if (ret)
+		goto err;
+
+	return ret;
+err:
+	dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	return ret;
+}
+
+static int af9013_statistics_ber_unc_result(struct dvb_frontend *fe)
+{
+	struct af9013_state *state = fe->demodulator_priv;
+	int ret;
+	u8 buf[5];
+
+	dev_dbg(&state->i2c->dev, "%s:\n", __func__);
+
+	/* check if error bit count is ready */
+	ret = af9013_rd_reg_bits(state, 0xd391, 4, 1, &buf[0]);
+	if (ret)
+		goto err;
+
+	if (!buf[0]) {
+		dev_dbg(&state->i2c->dev, "%s: not ready\n", __func__);
+		return 0;
+	}
+
+	ret = af9013_rd_regs(state, 0xd387, buf, 5);
+	if (ret)
+		goto err;
+
+	state->ber = (buf[2] << 16) | (buf[1] << 8) | buf[0];
+	state->ucblocks += (buf[4] << 8) | buf[3];
+
+	return ret;
+err:
+	dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	return ret;
+}
+
+static int af9013_statistics_snr_start(struct dvb_frontend *fe)
+{
+	struct af9013_state *state = fe->demodulator_priv;
+	int ret;
+
+	dev_dbg(&state->i2c->dev, "%s:\n", __func__);
+
+	/* start SNR meas */
+	ret = af9013_wr_reg_bits(state, 0xd2e1, 3, 1, 1);
+	if (ret)
+		goto err;
+
+	return ret;
+err:
+	dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	return ret;
+}
+
+static int af9013_statistics_snr_result(struct dvb_frontend *fe)
+{
+	struct af9013_state *state = fe->demodulator_priv;
+	int ret, i, len;
+	u8 buf[3], tmp;
+	u32 snr_val;
+	const struct af9013_snr *uninitialized_var(snr_lut);
+
+	dev_dbg(&state->i2c->dev, "%s:\n", __func__);
+
+	/* check if SNR ready */
+	ret = af9013_rd_reg_bits(state, 0xd2e1, 3, 1, &tmp);
+	if (ret)
+		goto err;
+
+	if (!tmp) {
+		dev_dbg(&state->i2c->dev, "%s: not ready\n", __func__);
+		return 0;
+	}
+
+	/* read value */
+	ret = af9013_rd_regs(state, 0xd2e3, buf, 3);
+	if (ret)
+		goto err;
+
+	snr_val = (buf[2] << 16) | (buf[1] << 8) | buf[0];
+
+	/* read current modulation */
+	ret = af9013_rd_reg(state, 0xd3c1, &tmp);
+	if (ret)
+		goto err;
+
+	switch ((tmp >> 6) & 3) {
+	case 0:
+		len = ARRAY_SIZE(qpsk_snr_lut);
+		snr_lut = qpsk_snr_lut;
+		break;
+	case 1:
+		len = ARRAY_SIZE(qam16_snr_lut);
+		snr_lut = qam16_snr_lut;
+		break;
+	case 2:
+		len = ARRAY_SIZE(qam64_snr_lut);
+		snr_lut = qam64_snr_lut;
+		break;
+	default:
+		goto err;
+		break;
+	}
+
+	for (i = 0; i < len; i++) {
+		tmp = snr_lut[i].snr;
+
+		if (snr_val < snr_lut[i].val)
+			break;
+	}
+	state->snr = tmp * 10; /* dB/10 */
+
+	return ret;
+err:
+	dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	return ret;
+}
+
+static int af9013_statistics_signal_strength(struct dvb_frontend *fe)
+{
+	struct af9013_state *state = fe->demodulator_priv;
+	int ret = 0;
+	u8 buf[2], rf_gain, if_gain;
+	int signal_strength;
+
+	dev_dbg(&state->i2c->dev, "%s:\n", __func__);
+
+	if (!state->signal_strength_en)
+		return 0;
+
+	ret = af9013_rd_regs(state, 0xd07c, buf, 2);
+	if (ret)
+		goto err;
+
+	rf_gain = buf[0];
+	if_gain = buf[1];
+
+	signal_strength = (0xffff / \
+		(9 * (state->rf_50 + state->if_50) - \
+		11 * (state->rf_80 + state->if_80))) * \
+		(10 * (rf_gain + if_gain) - \
+		11 * (state->rf_80 + state->if_80));
+	if (signal_strength < 0)
+		signal_strength = 0;
+	else if (signal_strength > 0xffff)
+		signal_strength = 0xffff;
+
+	state->signal_strength = signal_strength;
+
+	return ret;
+err:
+	dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	return ret;
+}
+
+static void af9013_statistics_work(struct work_struct *work)
+{
+	struct af9013_state *state = container_of(work,
+		struct af9013_state, statistics_work.work);
+	unsigned int next_msec;
+
+	/* update only signal strength when demod is not locked */
+	if (!(state->fe_status & FE_HAS_LOCK)) {
+		state->statistics_step = 0;
+		state->ber = 0;
+		state->snr = 0;
+	}
+
+	switch (state->statistics_step) {
+	default:
+		state->statistics_step = 0;
+	case 0:
+		af9013_statistics_signal_strength(&state->fe);
+		state->statistics_step++;
+		next_msec = 300;
+		break;
+	case 1:
+		af9013_statistics_snr_start(&state->fe);
+		state->statistics_step++;
+		next_msec = 200;
+		break;
+	case 2:
+		af9013_statistics_ber_unc_start(&state->fe);
+		state->statistics_step++;
+		next_msec = 1000;
+		break;
+	case 3:
+		af9013_statistics_snr_result(&state->fe);
+		state->statistics_step++;
+		next_msec = 400;
+		break;
+	case 4:
+		af9013_statistics_ber_unc_result(&state->fe);
+		state->statistics_step++;
+		next_msec = 100;
+		break;
+	}
+
+	schedule_delayed_work(&state->statistics_work,
+		msecs_to_jiffies(next_msec));
+}
+
+static int af9013_get_tune_settings(struct dvb_frontend *fe,
+	struct dvb_frontend_tune_settings *fesettings)
+{
+	fesettings->min_delay_ms = 800;
+	fesettings->step_size = 0;
+	fesettings->max_drift = 0;
+
+	return 0;
+}
+
+static int af9013_set_frontend(struct dvb_frontend *fe)
+{
+	struct af9013_state *state = fe->demodulator_priv;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	int ret, i, sampling_freq;
+	bool auto_mode, spec_inv;
+	u8 buf[6];
+	u32 if_frequency, freq_cw;
+
+	dev_dbg(&state->i2c->dev, "%s: frequency=%d bandwidth_hz=%d\n",
+			__func__, c->frequency, c->bandwidth_hz);
+
+	/* program tuner */
+	if (fe->ops.tuner_ops.set_params)
+		fe->ops.tuner_ops.set_params(fe);
+
+	/* program CFOE coefficients */
+	if (c->bandwidth_hz != state->bandwidth_hz) {
+		for (i = 0; i < ARRAY_SIZE(coeff_lut); i++) {
+			if (coeff_lut[i].clock == state->config.clock &&
+				coeff_lut[i].bandwidth_hz == c->bandwidth_hz) {
+				break;
+			}
+		}
+
+		ret = af9013_wr_regs(state, 0xae00, coeff_lut[i].val,
+			sizeof(coeff_lut[i].val));
+	}
+
+	/* program frequency control */
+	if (c->bandwidth_hz != state->bandwidth_hz || state->first_tune) {
+		/* get used IF frequency */
+		if (fe->ops.tuner_ops.get_if_frequency)
+			fe->ops.tuner_ops.get_if_frequency(fe, &if_frequency);
+		else
+			if_frequency = state->config.if_frequency;
+
+		dev_dbg(&state->i2c->dev, "%s: if_frequency=%d\n",
+				__func__, if_frequency);
+
+		sampling_freq = if_frequency;
+
+		while (sampling_freq > (state->config.clock / 2))
+			sampling_freq -= state->config.clock;
+
+		if (sampling_freq < 0) {
+			sampling_freq *= -1;
+			spec_inv = state->config.spec_inv;
+		} else {
+			spec_inv = !state->config.spec_inv;
+		}
+
+		freq_cw = af9013_div(state, sampling_freq, state->config.clock,
+				23);
+
+		if (spec_inv)
+			freq_cw = 0x800000 - freq_cw;
+
+		buf[0] = (freq_cw >>  0) & 0xff;
+		buf[1] = (freq_cw >>  8) & 0xff;
+		buf[2] = (freq_cw >> 16) & 0x7f;
+
+		freq_cw = 0x800000 - freq_cw;
+
+		buf[3] = (freq_cw >>  0) & 0xff;
+		buf[4] = (freq_cw >>  8) & 0xff;
+		buf[5] = (freq_cw >> 16) & 0x7f;
+
+		ret = af9013_wr_regs(state, 0xd140, buf, 3);
+		if (ret)
+			goto err;
+
+		ret = af9013_wr_regs(state, 0x9be7, buf, 6);
+		if (ret)
+			goto err;
+	}
+
+	/* clear TPS lock flag */
+	ret = af9013_wr_reg_bits(state, 0xd330, 3, 1, 1);
+	if (ret)
+		goto err;
+
+	/* clear MPEG2 lock flag */
+	ret = af9013_wr_reg_bits(state, 0xd507, 6, 1, 0);
+	if (ret)
+		goto err;
+
+	/* empty channel function */
+	ret = af9013_wr_reg_bits(state, 0x9bfe, 0, 1, 0);
+	if (ret)
+		goto err;
+
+	/* empty DVB-T channel function */
+	ret = af9013_wr_reg_bits(state, 0x9bc2, 0, 1, 0);
+	if (ret)
+		goto err;
+
+	/* transmission parameters */
+	auto_mode = false;
+	memset(buf, 0, 3);
+
+	switch (c->transmission_mode) {
+	case TRANSMISSION_MODE_AUTO:
+		auto_mode = 1;
+		break;
+	case TRANSMISSION_MODE_2K:
+		break;
+	case TRANSMISSION_MODE_8K:
+		buf[0] |= (1 << 0);
+		break;
+	default:
+		dev_dbg(&state->i2c->dev, "%s: invalid transmission_mode\n",
+				__func__);
+		auto_mode = 1;
+	}
+
+	switch (c->guard_interval) {
+	case GUARD_INTERVAL_AUTO:
+		auto_mode = 1;
+		break;
+	case GUARD_INTERVAL_1_32:
+		break;
+	case GUARD_INTERVAL_1_16:
+		buf[0] |= (1 << 2);
+		break;
+	case GUARD_INTERVAL_1_8:
+		buf[0] |= (2 << 2);
+		break;
+	case GUARD_INTERVAL_1_4:
+		buf[0] |= (3 << 2);
+		break;
+	default:
+		dev_dbg(&state->i2c->dev, "%s: invalid guard_interval\n",
+				__func__);
+		auto_mode = 1;
+	}
+
+	switch (c->hierarchy) {
+	case HIERARCHY_AUTO:
+		auto_mode = 1;
+		break;
+	case HIERARCHY_NONE:
+		break;
+	case HIERARCHY_1:
+		buf[0] |= (1 << 4);
+		break;
+	case HIERARCHY_2:
+		buf[0] |= (2 << 4);
+		break;
+	case HIERARCHY_4:
+		buf[0] |= (3 << 4);
+		break;
+	default:
+		dev_dbg(&state->i2c->dev, "%s: invalid hierarchy\n", __func__);
+		auto_mode = 1;
+	};
+
+	switch (c->modulation) {
+	case QAM_AUTO:
+		auto_mode = 1;
+		break;
+	case QPSK:
+		break;
+	case QAM_16:
+		buf[1] |= (1 << 6);
+		break;
+	case QAM_64:
+		buf[1] |= (2 << 6);
+		break;
+	default:
+		dev_dbg(&state->i2c->dev, "%s: invalid modulation\n", __func__);
+		auto_mode = 1;
+	}
+
+	/* Use HP. How and which case we can switch to LP? */
+	buf[1] |= (1 << 4);
+
+	switch (c->code_rate_HP) {
+	case FEC_AUTO:
+		auto_mode = 1;
+		break;
+	case FEC_1_2:
+		break;
+	case FEC_2_3:
+		buf[2] |= (1 << 0);
+		break;
+	case FEC_3_4:
+		buf[2] |= (2 << 0);
+		break;
+	case FEC_5_6:
+		buf[2] |= (3 << 0);
+		break;
+	case FEC_7_8:
+		buf[2] |= (4 << 0);
+		break;
+	default:
+		dev_dbg(&state->i2c->dev, "%s: invalid code_rate_HP\n",
+				__func__);
+		auto_mode = 1;
+	}
+
+	switch (c->code_rate_LP) {
+	case FEC_AUTO:
+		auto_mode = 1;
+		break;
+	case FEC_1_2:
+		break;
+	case FEC_2_3:
+		buf[2] |= (1 << 3);
+		break;
+	case FEC_3_4:
+		buf[2] |= (2 << 3);
+		break;
+	case FEC_5_6:
+		buf[2] |= (3 << 3);
+		break;
+	case FEC_7_8:
+		buf[2] |= (4 << 3);
+		break;
+	case FEC_NONE:
+		break;
+	default:
+		dev_dbg(&state->i2c->dev, "%s: invalid code_rate_LP\n",
+				__func__);
+		auto_mode = 1;
+	}
+
+	switch (c->bandwidth_hz) {
+	case 6000000:
+		break;
+	case 7000000:
+		buf[1] |= (1 << 2);
+		break;
+	case 8000000:
+		buf[1] |= (2 << 2);
+		break;
+	default:
+		dev_dbg(&state->i2c->dev, "%s: invalid bandwidth_hz\n",
+				__func__);
+		ret = -EINVAL;
+		goto err;
+	}
+
+	ret = af9013_wr_regs(state, 0xd3c0, buf, 3);
+	if (ret)
+		goto err;
+
+	if (auto_mode) {
+		/* clear easy mode flag */
+		ret = af9013_wr_reg(state, 0xaefd, 0);
+		if (ret)
+			goto err;
+
+		dev_dbg(&state->i2c->dev, "%s: auto params\n", __func__);
+	} else {
+		/* set easy mode flag */
+		ret = af9013_wr_reg(state, 0xaefd, 1);
+		if (ret)
+			goto err;
+
+		ret = af9013_wr_reg(state, 0xaefe, 0);
+		if (ret)
+			goto err;
+
+		dev_dbg(&state->i2c->dev, "%s: manual params\n", __func__);
+	}
+
+	/* tune */
+	ret = af9013_wr_reg(state, 0xffff, 0);
+	if (ret)
+		goto err;
+
+	state->bandwidth_hz = c->bandwidth_hz;
+	state->set_frontend_jiffies = jiffies;
+	state->first_tune = false;
+
+	return ret;
+err:
+	dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	return ret;
+}
+
+static int af9013_get_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	struct af9013_state *state = fe->demodulator_priv;
+	int ret;
+	u8 buf[3];
+
+	dev_dbg(&state->i2c->dev, "%s:\n", __func__);
+
+	ret = af9013_rd_regs(state, 0xd3c0, buf, 3);
+	if (ret)
+		goto err;
+
+	switch ((buf[1] >> 6) & 3) {
+	case 0:
+		c->modulation = QPSK;
+		break;
+	case 1:
+		c->modulation = QAM_16;
+		break;
+	case 2:
+		c->modulation = QAM_64;
+		break;
+	}
+
+	switch ((buf[0] >> 0) & 3) {
+	case 0:
+		c->transmission_mode = TRANSMISSION_MODE_2K;
+		break;
+	case 1:
+		c->transmission_mode = TRANSMISSION_MODE_8K;
+	}
+
+	switch ((buf[0] >> 2) & 3) {
+	case 0:
+		c->guard_interval = GUARD_INTERVAL_1_32;
+		break;
+	case 1:
+		c->guard_interval = GUARD_INTERVAL_1_16;
+		break;
+	case 2:
+		c->guard_interval = GUARD_INTERVAL_1_8;
+		break;
+	case 3:
+		c->guard_interval = GUARD_INTERVAL_1_4;
+		break;
+	}
+
+	switch ((buf[0] >> 4) & 7) {
+	case 0:
+		c->hierarchy = HIERARCHY_NONE;
+		break;
+	case 1:
+		c->hierarchy = HIERARCHY_1;
+		break;
+	case 2:
+		c->hierarchy = HIERARCHY_2;
+		break;
+	case 3:
+		c->hierarchy = HIERARCHY_4;
+		break;
+	}
+
+	switch ((buf[2] >> 0) & 7) {
+	case 0:
+		c->code_rate_HP = FEC_1_2;
+		break;
+	case 1:
+		c->code_rate_HP = FEC_2_3;
+		break;
+	case 2:
+		c->code_rate_HP = FEC_3_4;
+		break;
+	case 3:
+		c->code_rate_HP = FEC_5_6;
+		break;
+	case 4:
+		c->code_rate_HP = FEC_7_8;
+		break;
+	}
+
+	switch ((buf[2] >> 3) & 7) {
+	case 0:
+		c->code_rate_LP = FEC_1_2;
+		break;
+	case 1:
+		c->code_rate_LP = FEC_2_3;
+		break;
+	case 2:
+		c->code_rate_LP = FEC_3_4;
+		break;
+	case 3:
+		c->code_rate_LP = FEC_5_6;
+		break;
+	case 4:
+		c->code_rate_LP = FEC_7_8;
+		break;
+	}
+
+	switch ((buf[1] >> 2) & 3) {
+	case 0:
+		c->bandwidth_hz = 6000000;
+		break;
+	case 1:
+		c->bandwidth_hz = 7000000;
+		break;
+	case 2:
+		c->bandwidth_hz = 8000000;
+		break;
+	}
+
+	return ret;
+err:
+	dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	return ret;
+}
+
+static int af9013_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+	struct af9013_state *state = fe->demodulator_priv;
+	int ret;
+	u8 tmp;
+
+	/*
+	 * Return status from the cache if it is younger than 2000ms with the
+	 * exception of last tune is done during 4000ms.
+	 */
+	if (time_is_after_jiffies(
+		state->read_status_jiffies + msecs_to_jiffies(2000)) &&
+		time_is_before_jiffies(
+		state->set_frontend_jiffies + msecs_to_jiffies(4000))
+	) {
+			*status = state->fe_status;
+			return 0;
+	} else {
+		*status = 0;
+	}
+
+	/* MPEG2 lock */
+	ret = af9013_rd_reg_bits(state, 0xd507, 6, 1, &tmp);
+	if (ret)
+		goto err;
+
+	if (tmp)
+		*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI |
+			FE_HAS_SYNC | FE_HAS_LOCK;
+
+	if (!*status) {
+		/* TPS lock */
+		ret = af9013_rd_reg_bits(state, 0xd330, 3, 1, &tmp);
+		if (ret)
+			goto err;
+
+		if (tmp)
+			*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
+				FE_HAS_VITERBI;
+	}
+
+	state->fe_status = *status;
+	state->read_status_jiffies = jiffies;
+
+	return ret;
+err:
+	dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	return ret;
+}
+
+static int af9013_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+	struct af9013_state *state = fe->demodulator_priv;
+	*snr = state->snr;
+	return 0;
+}
+
+static int af9013_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
+{
+	struct af9013_state *state = fe->demodulator_priv;
+	*strength = state->signal_strength;
+	return 0;
+}
+
+static int af9013_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+	struct af9013_state *state = fe->demodulator_priv;
+	*ber = state->ber;
+	return 0;
+}
+
+static int af9013_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+	struct af9013_state *state = fe->demodulator_priv;
+	*ucblocks = state->ucblocks;
+	return 0;
+}
+
+static int af9013_init(struct dvb_frontend *fe)
+{
+	struct af9013_state *state = fe->demodulator_priv;
+	int ret, i, len;
+	u8 buf[3], tmp;
+	u32 adc_cw;
+	const struct af9013_reg_bit *init;
+
+	dev_dbg(&state->i2c->dev, "%s:\n", __func__);
+
+	/* power on */
+	ret = af9013_power_ctrl(state, 1);
+	if (ret)
+		goto err;
+
+	/* enable ADC */
+	ret = af9013_wr_reg(state, 0xd73a, 0xa4);
+	if (ret)
+		goto err;
+
+	/* write API version to firmware */
+	ret = af9013_wr_regs(state, 0x9bf2, state->config.api_version, 4);
+	if (ret)
+		goto err;
+
+	/* program ADC control */
+	switch (state->config.clock) {
+	case 28800000: /* 28.800 MHz */
+		tmp = 0;
+		break;
+	case 20480000: /* 20.480 MHz */
+		tmp = 1;
+		break;
+	case 28000000: /* 28.000 MHz */
+		tmp = 2;
+		break;
+	case 25000000: /* 25.000 MHz */
+		tmp = 3;
+		break;
+	default:
+		dev_err(&state->i2c->dev, "%s: invalid clock\n",
+				KBUILD_MODNAME);
+		return -EINVAL;
+	}
+
+	adc_cw = af9013_div(state, state->config.clock, 1000000ul, 19);
+	buf[0] = (adc_cw >>  0) & 0xff;
+	buf[1] = (adc_cw >>  8) & 0xff;
+	buf[2] = (adc_cw >> 16) & 0xff;
+
+	ret = af9013_wr_regs(state, 0xd180, buf, 3);
+	if (ret)
+		goto err;
+
+	ret = af9013_wr_reg_bits(state, 0x9bd2, 0, 4, tmp);
+	if (ret)
+		goto err;
+
+	/* set I2C master clock */
+	ret = af9013_wr_reg(state, 0xd416, 0x14);
+	if (ret)
+		goto err;
+
+	/* set 16 embx */
+	ret = af9013_wr_reg_bits(state, 0xd700, 1, 1, 1);
+	if (ret)
+		goto err;
+
+	/* set no trigger */
+	ret = af9013_wr_reg_bits(state, 0xd700, 2, 1, 0);
+	if (ret)
+		goto err;
+
+	/* set read-update bit for constellation */
+	ret = af9013_wr_reg_bits(state, 0xd371, 1, 1, 1);
+	if (ret)
+		goto err;
+
+	/* settings for mp2if */
+	if (state->config.ts_mode == AF9013_TS_USB) {
+		/* AF9015 split PSB to 1.5k + 0.5k */
+		ret = af9013_wr_reg_bits(state, 0xd50b, 2, 1, 1);
+		if (ret)
+			goto err;
+	} else {
+		/* AF9013 change the output bit to data7 */
+		ret = af9013_wr_reg_bits(state, 0xd500, 3, 1, 1);
+		if (ret)
+			goto err;
+
+		/* AF9013 set mpeg to full speed */
+		ret = af9013_wr_reg_bits(state, 0xd502, 4, 1, 1);
+		if (ret)
+			goto err;
+	}
+
+	ret = af9013_wr_reg_bits(state, 0xd520, 4, 1, 1);
+	if (ret)
+		goto err;
+
+	/* load OFSM settings */
+	dev_dbg(&state->i2c->dev, "%s: load ofsm settings\n", __func__);
+	len = ARRAY_SIZE(ofsm_init);
+	init = ofsm_init;
+	for (i = 0; i < len; i++) {
+		ret = af9013_wr_reg_bits(state, init[i].addr, init[i].pos,
+			init[i].len, init[i].val);
+		if (ret)
+			goto err;
+	}
+
+	/* load tuner specific settings */
+	dev_dbg(&state->i2c->dev, "%s: load tuner specific settings\n",
+			__func__);
+	switch (state->config.tuner) {
+	case AF9013_TUNER_MXL5003D:
+		len = ARRAY_SIZE(tuner_init_mxl5003d);
+		init = tuner_init_mxl5003d;
+		break;
+	case AF9013_TUNER_MXL5005D:
+	case AF9013_TUNER_MXL5005R:
+	case AF9013_TUNER_MXL5007T:
+		len = ARRAY_SIZE(tuner_init_mxl5005);
+		init = tuner_init_mxl5005;
+		break;
+	case AF9013_TUNER_ENV77H11D5:
+		len = ARRAY_SIZE(tuner_init_env77h11d5);
+		init = tuner_init_env77h11d5;
+		break;
+	case AF9013_TUNER_MT2060:
+		len = ARRAY_SIZE(tuner_init_mt2060);
+		init = tuner_init_mt2060;
+		break;
+	case AF9013_TUNER_MC44S803:
+		len = ARRAY_SIZE(tuner_init_mc44s803);
+		init = tuner_init_mc44s803;
+		break;
+	case AF9013_TUNER_QT1010:
+	case AF9013_TUNER_QT1010A:
+		len = ARRAY_SIZE(tuner_init_qt1010);
+		init = tuner_init_qt1010;
+		break;
+	case AF9013_TUNER_MT2060_2:
+		len = ARRAY_SIZE(tuner_init_mt2060_2);
+		init = tuner_init_mt2060_2;
+		break;
+	case AF9013_TUNER_TDA18271:
+	case AF9013_TUNER_TDA18218:
+		len = ARRAY_SIZE(tuner_init_tda18271);
+		init = tuner_init_tda18271;
+		break;
+	case AF9013_TUNER_UNKNOWN:
+	default:
+		len = ARRAY_SIZE(tuner_init_unknown);
+		init = tuner_init_unknown;
+		break;
+	}
+
+	for (i = 0; i < len; i++) {
+		ret = af9013_wr_reg_bits(state, init[i].addr, init[i].pos,
+			init[i].len, init[i].val);
+		if (ret)
+			goto err;
+	}
+
+	/* TS mode */
+	ret = af9013_wr_reg_bits(state, 0xd500, 1, 2, state->config.ts_mode);
+	if (ret)
+		goto err;
+
+	/* enable lock led */
+	ret = af9013_wr_reg_bits(state, 0xd730, 0, 1, 1);
+	if (ret)
+		goto err;
+
+	/* check if we support signal strength */
+	if (!state->signal_strength_en) {
+		ret = af9013_rd_reg_bits(state, 0x9bee, 0, 1,
+			&state->signal_strength_en);
+		if (ret)
+			goto err;
+	}
+
+	/* read values needed for signal strength calculation */
+	if (state->signal_strength_en && !state->rf_50) {
+		ret = af9013_rd_reg(state, 0x9bbd, &state->rf_50);
+		if (ret)
+			goto err;
+
+		ret = af9013_rd_reg(state, 0x9bd0, &state->rf_80);
+		if (ret)
+			goto err;
+
+		ret = af9013_rd_reg(state, 0x9be2, &state->if_50);
+		if (ret)
+			goto err;
+
+		ret = af9013_rd_reg(state, 0x9be4, &state->if_80);
+		if (ret)
+			goto err;
+	}
+
+	/* SNR */
+	ret = af9013_wr_reg(state, 0xd2e2, 1);
+	if (ret)
+		goto err;
+
+	/* BER / UCB */
+	buf[0] = (10000 >> 0) & 0xff;
+	buf[1] = (10000 >> 8) & 0xff;
+	ret = af9013_wr_regs(state, 0xd385, buf, 2);
+	if (ret)
+		goto err;
+
+	/* enable FEC monitor */
+	ret = af9013_wr_reg_bits(state, 0xd392, 1, 1, 1);
+	if (ret)
+		goto err;
+
+	state->first_tune = true;
+	schedule_delayed_work(&state->statistics_work, msecs_to_jiffies(400));
+
+	return ret;
+err:
+	dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	return ret;
+}
+
+static int af9013_sleep(struct dvb_frontend *fe)
+{
+	struct af9013_state *state = fe->demodulator_priv;
+	int ret;
+
+	dev_dbg(&state->i2c->dev, "%s:\n", __func__);
+
+	/* stop statistics polling */
+	cancel_delayed_work_sync(&state->statistics_work);
+
+	/* disable lock led */
+	ret = af9013_wr_reg_bits(state, 0xd730, 0, 1, 0);
+	if (ret)
+		goto err;
+
+	/* power off */
+	ret = af9013_power_ctrl(state, 0);
+	if (ret)
+		goto err;
+
+	return ret;
+err:
+	dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	return ret;
+}
+
+static int af9013_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+	int ret;
+	struct af9013_state *state = fe->demodulator_priv;
+
+	dev_dbg(&state->i2c->dev, "%s: enable=%d\n", __func__, enable);
+
+	/* gate already open or close */
+	if (state->i2c_gate_state == enable)
+		return 0;
+
+	if (state->config.ts_mode == AF9013_TS_USB)
+		ret = af9013_wr_reg_bits(state, 0xd417, 3, 1, enable);
+	else
+		ret = af9013_wr_reg_bits(state, 0xd607, 2, 1, enable);
+	if (ret)
+		goto err;
+
+	state->i2c_gate_state = enable;
+
+	return ret;
+err:
+	dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	return ret;
+}
+
+static void af9013_release(struct dvb_frontend *fe)
+{
+	struct af9013_state *state = fe->demodulator_priv;
+	kfree(state);
+}
+
+static struct dvb_frontend_ops af9013_ops;
+
+static int af9013_download_firmware(struct af9013_state *state)
+{
+	int i, len, remaining, ret;
+	const struct firmware *fw;
+	u16 checksum = 0;
+	u8 val;
+	u8 fw_params[4];
+	u8 *fw_file = AF9013_FIRMWARE;
+
+	msleep(100);
+	/* check whether firmware is already running */
+	ret = af9013_rd_reg(state, 0x98be, &val);
+	if (ret)
+		goto err;
+	else
+		dev_dbg(&state->i2c->dev, "%s: firmware status=%02x\n",
+				__func__, val);
+
+	if (val == 0x0c) /* fw is running, no need for download */
+		goto exit;
+
+	dev_info(&state->i2c->dev, "%s: found a '%s' in cold state, will try " \
+			"to load a firmware\n",
+			KBUILD_MODNAME, af9013_ops.info.name);
+
+	/* request the firmware, this will block and timeout */
+	ret = request_firmware(&fw, fw_file, state->i2c->dev.parent);
+	if (ret) {
+		dev_info(&state->i2c->dev, "%s: did not find the firmware " \
+			"file. (%s) Please see linux/Documentation/dvb/ for " \
+			"more details on firmware-problems. (%d)\n",
+			KBUILD_MODNAME, fw_file, ret);
+		goto err;
+	}
+
+	dev_info(&state->i2c->dev, "%s: downloading firmware from file '%s'\n",
+			KBUILD_MODNAME, fw_file);
+
+	/* calc checksum */
+	for (i = 0; i < fw->size; i++)
+		checksum += fw->data[i];
+
+	fw_params[0] = checksum >> 8;
+	fw_params[1] = checksum & 0xff;
+	fw_params[2] = fw->size >> 8;
+	fw_params[3] = fw->size & 0xff;
+
+	/* write fw checksum & size */
+	ret = af9013_write_ofsm_regs(state, 0x50fc,
+		fw_params, sizeof(fw_params));
+	if (ret)
+		goto err_release;
+
+	#define FW_ADDR 0x5100 /* firmware start address */
+	#define LEN_MAX 16 /* max packet size */
+	for (remaining = fw->size; remaining > 0; remaining -= LEN_MAX) {
+		len = remaining;
+		if (len > LEN_MAX)
+			len = LEN_MAX;
+
+		ret = af9013_write_ofsm_regs(state,
+			FW_ADDR + fw->size - remaining,
+			(u8 *) &fw->data[fw->size - remaining], len);
+		if (ret) {
+			dev_err(&state->i2c->dev,
+					"%s: firmware download failed=%d\n",
+					KBUILD_MODNAME, ret);
+			goto err_release;
+		}
+	}
+
+	/* request boot firmware */
+	ret = af9013_wr_reg(state, 0xe205, 1);
+	if (ret)
+		goto err_release;
+
+	for (i = 0; i < 15; i++) {
+		msleep(100);
+
+		/* check firmware status */
+		ret = af9013_rd_reg(state, 0x98be, &val);
+		if (ret)
+			goto err_release;
+
+		dev_dbg(&state->i2c->dev, "%s: firmware status=%02x\n",
+				__func__, val);
+
+		if (val == 0x0c || val == 0x04) /* success or fail */
+			break;
+	}
+
+	if (val == 0x04) {
+		dev_err(&state->i2c->dev, "%s: firmware did not run\n",
+				KBUILD_MODNAME);
+		ret = -ENODEV;
+	} else if (val != 0x0c) {
+		dev_err(&state->i2c->dev, "%s: firmware boot timeout\n",
+				KBUILD_MODNAME);
+		ret = -ENODEV;
+	}
+
+err_release:
+	release_firmware(fw);
+err:
+exit:
+	if (!ret)
+		dev_info(&state->i2c->dev, "%s: found a '%s' in warm state\n",
+				KBUILD_MODNAME, af9013_ops.info.name);
+	return ret;
+}
+
+struct dvb_frontend *af9013_attach(const struct af9013_config *config,
+	struct i2c_adapter *i2c)
+{
+	int ret;
+	struct af9013_state *state = NULL;
+	u8 buf[4], i;
+
+	/* allocate memory for the internal state */
+	state = kzalloc(sizeof(struct af9013_state), GFP_KERNEL);
+	if (state == NULL)
+		goto err;
+
+	/* setup the state */
+	state->i2c = i2c;
+	memcpy(&state->config, config, sizeof(struct af9013_config));
+
+	/* download firmware */
+	if (state->config.ts_mode != AF9013_TS_USB) {
+		ret = af9013_download_firmware(state);
+		if (ret)
+			goto err;
+	}
+
+	/* firmware version */
+	ret = af9013_rd_regs(state, 0x5103, buf, 4);
+	if (ret)
+		goto err;
+
+	dev_info(&state->i2c->dev, "%s: firmware version %d.%d.%d.%d\n",
+			KBUILD_MODNAME, buf[0], buf[1], buf[2], buf[3]);
+
+	/* set GPIOs */
+	for (i = 0; i < sizeof(state->config.gpio); i++) {
+		ret = af9013_set_gpio(state, i, state->config.gpio[i]);
+		if (ret)
+			goto err;
+	}
+
+	/* create dvb_frontend */
+	memcpy(&state->fe.ops, &af9013_ops,
+		sizeof(struct dvb_frontend_ops));
+	state->fe.demodulator_priv = state;
+
+	INIT_DELAYED_WORK(&state->statistics_work, af9013_statistics_work);
+
+	return &state->fe;
+err:
+	kfree(state);
+	return NULL;
+}
+EXPORT_SYMBOL(af9013_attach);
+
+static struct dvb_frontend_ops af9013_ops = {
+	.delsys = { SYS_DVBT },
+	.info = {
+		.name = "Afatech AF9013",
+		.frequency_min = 174000000,
+		.frequency_max = 862000000,
+		.frequency_stepsize = 250000,
+		.frequency_tolerance = 0,
+		.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_FEC_AUTO |
+			FE_CAN_QPSK |
+			FE_CAN_QAM_16 |
+			FE_CAN_QAM_64 |
+			FE_CAN_QAM_AUTO |
+			FE_CAN_TRANSMISSION_MODE_AUTO |
+			FE_CAN_GUARD_INTERVAL_AUTO |
+			FE_CAN_HIERARCHY_AUTO |
+			FE_CAN_RECOVER |
+			FE_CAN_MUTE_TS
+	},
+
+	.release = af9013_release,
+
+	.init = af9013_init,
+	.sleep = af9013_sleep,
+
+	.get_tune_settings = af9013_get_tune_settings,
+	.set_frontend = af9013_set_frontend,
+	.get_frontend = af9013_get_frontend,
+
+	.read_status = af9013_read_status,
+	.read_snr = af9013_read_snr,
+	.read_signal_strength = af9013_read_signal_strength,
+	.read_ber = af9013_read_ber,
+	.read_ucblocks = af9013_read_ucblocks,
+
+	.i2c_gate_ctrl = af9013_i2c_gate_ctrl,
+};
+
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
+MODULE_DESCRIPTION("Afatech AF9013 DVB-T demodulator driver");
+MODULE_LICENSE("GPL");
+MODULE_FIRMWARE(AF9013_FIRMWARE);
diff --git a/drivers/media/dvb-frontends/af9013.h b/drivers/media/dvb-frontends/af9013.h
new file mode 100644
index 0000000..dc837d9
--- /dev/null
+++ b/drivers/media/dvb-frontends/af9013.h
@@ -0,0 +1,118 @@
+/*
+ * Afatech AF9013 demodulator driver
+ *
+ * Copyright (C) 2007 Antti Palosaari <crope@iki.fi>
+ * Copyright (C) 2011 Antti Palosaari <crope@iki.fi>
+ *
+ * Thanks to Afatech who kindly provided information.
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You 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 AF9013_H
+#define AF9013_H
+
+#include <linux/dvb/frontend.h>
+
+/* AF9013/5 GPIOs (mostly guessed)
+   demod#1-gpio#0 - set demod#2 i2c-addr for dual devices
+   demod#1-gpio#1 - xtal setting (?)
+   demod#1-gpio#3 - tuner#1
+   demod#2-gpio#0 - tuner#2
+   demod#2-gpio#1 - xtal setting (?)
+*/
+
+struct af9013_config {
+	/*
+	 * I2C address
+	 */
+	u8 i2c_addr;
+
+	/*
+	 * clock
+	 * 20480000, 25000000, 28000000, 28800000
+	 */
+	u32 clock;
+
+	/*
+	 * tuner
+	 */
+#define AF9013_TUNER_MXL5003D      3 /* MaxLinear */
+#define AF9013_TUNER_MXL5005D     13 /* MaxLinear */
+#define AF9013_TUNER_MXL5005R     30 /* MaxLinear */
+#define AF9013_TUNER_ENV77H11D5  129 /* Panasonic */
+#define AF9013_TUNER_MT2060      130 /* Microtune */
+#define AF9013_TUNER_MC44S803    133 /* Freescale */
+#define AF9013_TUNER_QT1010      134 /* Quantek */
+#define AF9013_TUNER_UNKNOWN     140 /* for can tuners ? */
+#define AF9013_TUNER_MT2060_2    147 /* Microtune */
+#define AF9013_TUNER_TDA18271    156 /* NXP */
+#define AF9013_TUNER_QT1010A     162 /* Quantek */
+#define AF9013_TUNER_MXL5007T    177 /* MaxLinear */
+#define AF9013_TUNER_TDA18218    179 /* NXP */
+	u8 tuner;
+
+	/*
+	 * IF frequency
+	 */
+	u32 if_frequency;
+
+	/*
+	 * TS settings
+	 */
+#define AF9013_TS_USB       0
+#define AF9013_TS_PARALLEL  1
+#define AF9013_TS_SERIAL    2
+	u8 ts_mode:2;
+
+	/*
+	 * input spectrum inversion
+	 */
+	bool spec_inv;
+
+	/*
+	 * firmware API version
+	 */
+	u8 api_version[4];
+
+	/*
+	 * GPIOs
+	 */
+#define AF9013_GPIO_ON (1 << 0)
+#define AF9013_GPIO_EN (1 << 1)
+#define AF9013_GPIO_O  (1 << 2)
+#define AF9013_GPIO_I  (1 << 3)
+#define AF9013_GPIO_LO (AF9013_GPIO_ON|AF9013_GPIO_EN)
+#define AF9013_GPIO_HI (AF9013_GPIO_ON|AF9013_GPIO_EN|AF9013_GPIO_O)
+#define AF9013_GPIO_TUNER_ON  (AF9013_GPIO_ON|AF9013_GPIO_EN)
+#define AF9013_GPIO_TUNER_OFF (AF9013_GPIO_ON|AF9013_GPIO_EN|AF9013_GPIO_O)
+	u8 gpio[4];
+};
+
+#if defined(CONFIG_DVB_AF9013) || \
+	(defined(CONFIG_DVB_AF9013_MODULE) && defined(MODULE))
+extern struct dvb_frontend *af9013_attach(const struct af9013_config *config,
+	struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend *af9013_attach(
+const struct af9013_config *config, struct i2c_adapter *i2c)
+{
+	pr_warn("%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif /* CONFIG_DVB_AF9013 */
+
+#endif /* AF9013_H */
diff --git a/drivers/media/dvb-frontends/af9013_priv.h b/drivers/media/dvb-frontends/af9013_priv.h
new file mode 100644
index 0000000..8b9392c
--- /dev/null
+++ b/drivers/media/dvb-frontends/af9013_priv.h
@@ -0,0 +1,909 @@
+/*
+ * Afatech AF9013 demodulator driver
+ *
+ * Copyright (C) 2007 Antti Palosaari <crope@iki.fi>
+ * Copyright (C) 2011 Antti Palosaari <crope@iki.fi>
+ *
+ * Thanks to Afatech who kindly provided information.
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You 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 AF9013_PRIV_H
+#define AF9013_PRIV_H
+
+#include "dvb_frontend.h"
+#include "af9013.h"
+#include <linux/firmware.h>
+
+#define AF9013_FIRMWARE "dvb-fe-af9013.fw"
+
+struct af9013_reg_bit {
+	u16 addr;
+	u8  pos:4;
+	u8  len:4;
+	u8  val;
+};
+
+struct af9013_snr {
+	u32 val;
+	u8 snr;
+};
+
+struct af9013_coeff {
+	u32 clock;
+	u32 bandwidth_hz;
+	u8 val[24];
+};
+
+/* pre-calculated coeff lookup table */
+static const struct af9013_coeff coeff_lut[] = {
+	/* 28.800 MHz */
+	{ 28800000, 8000000, { 0x02, 0x8a, 0x28, 0xa3, 0x05, 0x14,
+		0x51, 0x11, 0x00, 0xa2, 0x8f, 0x3d, 0x00, 0xa2, 0x8a,
+		0x29, 0x00, 0xa2, 0x85, 0x14, 0x01, 0x45, 0x14, 0x14 } },
+	{ 28800000, 7000000, { 0x02, 0x38, 0xe3, 0x8e, 0x04, 0x71,
+		0xc7, 0x07, 0x00, 0x8e, 0x3d, 0x55, 0x00, 0x8e, 0x38,
+		0xe4, 0x00, 0x8e, 0x34, 0x72, 0x01, 0x1c, 0x71, 0x32 } },
+	{ 28800000, 6000000, { 0x01, 0xe7, 0x9e, 0x7a, 0x03, 0xcf,
+		0x3c, 0x3d, 0x00, 0x79, 0xeb, 0x6e, 0x00, 0x79, 0xe7,
+		0x9e, 0x00, 0x79, 0xe3, 0xcf, 0x00, 0xf3, 0xcf, 0x0f } },
+	/* 20.480 MHz */
+	{ 20480000, 8000000, { 0x03, 0x92, 0x49, 0x26, 0x07, 0x24,
+		0x92, 0x13, 0x00, 0xe4, 0x99, 0x6e, 0x00, 0xe4, 0x92,
+		0x49, 0x00, 0xe4, 0x8b, 0x25, 0x01, 0xc9, 0x24, 0x25 } },
+	{ 20480000, 7000000, { 0x03, 0x20, 0x00, 0x01, 0x06, 0x40,
+		0x00, 0x00, 0x00, 0xc8, 0x06, 0x40, 0x00, 0xc8, 0x00,
+		0x00, 0x00, 0xc7, 0xf9, 0xc0, 0x01, 0x90, 0x00, 0x00 } },
+	{ 20480000, 6000000, { 0x02, 0xad, 0xb6, 0xdc, 0x05, 0x5b,
+		0x6d, 0x2e, 0x00, 0xab, 0x73, 0x13, 0x00, 0xab, 0x6d,
+		0xb7, 0x00, 0xab, 0x68, 0x5c, 0x01, 0x56, 0xdb, 0x1c } },
+	/* 28.000 MHz */
+	{ 28000000, 8000000, { 0x02, 0x9c, 0xbc, 0x15, 0x05, 0x39,
+		0x78, 0x0a, 0x00, 0xa7, 0x34, 0x3f, 0x00, 0xa7, 0x2f,
+		0x05, 0x00, 0xa7, 0x29, 0xcc, 0x01, 0x4e, 0x5e, 0x03 } },
+	{ 28000000, 7000000, { 0x02, 0x49, 0x24, 0x92, 0x04, 0x92,
+		0x49, 0x09, 0x00, 0x92, 0x4d, 0xb7, 0x00, 0x92, 0x49,
+		0x25, 0x00, 0x92, 0x44, 0x92, 0x01, 0x24, 0x92, 0x12 } },
+	{ 28000000, 6000000, { 0x01, 0xf5, 0x8d, 0x10, 0x03, 0xeb,
+		0x1a, 0x08, 0x00, 0x7d, 0x67, 0x2f, 0x00, 0x7d, 0x63,
+		0x44, 0x00, 0x7d, 0x5f, 0x59, 0x00, 0xfa, 0xc6, 0x22 } },
+	/* 25.000 MHz */
+	{ 25000000, 8000000, { 0x02, 0xec, 0xfb, 0x9d, 0x05, 0xd9,
+		0xf7, 0x0e, 0x00, 0xbb, 0x44, 0xc1, 0x00, 0xbb, 0x3e,
+		0xe7, 0x00, 0xbb, 0x39, 0x0d, 0x01, 0x76, 0x7d, 0x34 } },
+	{ 25000000, 7000000, { 0x02, 0x8f, 0x5c, 0x29, 0x05, 0x1e,
+		0xb8, 0x14, 0x00, 0xa3, 0xdc, 0x29, 0x00, 0xa3, 0xd7,
+		0x0a, 0x00, 0xa3, 0xd1, 0xec, 0x01, 0x47, 0xae, 0x05 } },
+	{ 25000000, 6000000, { 0x02, 0x31, 0xbc, 0xb5, 0x04, 0x63,
+		0x79, 0x1b, 0x00, 0x8c, 0x73, 0x91, 0x00, 0x8c, 0x6f,
+		0x2d, 0x00, 0x8c, 0x6a, 0xca, 0x01, 0x18, 0xde, 0x17 } },
+};
+
+/* QPSK SNR lookup table */
+static const struct af9013_snr qpsk_snr_lut[] = {
+	{ 0x000000,  0 },
+	{ 0x0b4771,  0 },
+	{ 0x0c1aed,  1 },
+	{ 0x0d0d27,  2 },
+	{ 0x0e4d19,  3 },
+	{ 0x0e5da8,  4 },
+	{ 0x107097,  5 },
+	{ 0x116975,  6 },
+	{ 0x1252d9,  7 },
+	{ 0x131fa4,  8 },
+	{ 0x13d5e1,  9 },
+	{ 0x148e53, 10 },
+	{ 0x15358b, 11 },
+	{ 0x15dd29, 12 },
+	{ 0x168112, 13 },
+	{ 0x170b61, 14 },
+	{ 0xffffff, 15 },
+};
+
+/* QAM16 SNR lookup table */
+static const struct af9013_snr qam16_snr_lut[] = {
+	{ 0x000000,  0 },
+	{ 0x05eb62,  5 },
+	{ 0x05fecf,  6 },
+	{ 0x060b80,  7 },
+	{ 0x062501,  8 },
+	{ 0x064865,  9 },
+	{ 0x069604, 10 },
+	{ 0x06f356, 11 },
+	{ 0x07706a, 12 },
+	{ 0x0804d3, 13 },
+	{ 0x089d1a, 14 },
+	{ 0x093e3d, 15 },
+	{ 0x09e35d, 16 },
+	{ 0x0a7c3c, 17 },
+	{ 0x0afaf8, 18 },
+	{ 0x0b719d, 19 },
+	{ 0xffffff, 20 },
+};
+
+/* QAM64 SNR lookup table */
+static const struct af9013_snr qam64_snr_lut[] = {
+	{ 0x000000,  0 },
+	{ 0x03109b, 12 },
+	{ 0x0310d4, 13 },
+	{ 0x031920, 14 },
+	{ 0x0322d0, 15 },
+	{ 0x0339fc, 16 },
+	{ 0x0364a1, 17 },
+	{ 0x038bcc, 18 },
+	{ 0x03c7d3, 19 },
+	{ 0x0408cc, 20 },
+	{ 0x043bed, 21 },
+	{ 0x048061, 22 },
+	{ 0x04be95, 23 },
+	{ 0x04fa7d, 24 },
+	{ 0x052405, 25 },
+	{ 0x05570d, 26 },
+	{ 0xffffff, 27 },
+};
+
+static const struct af9013_reg_bit ofsm_init[] = {
+	{ 0xd73a, 0, 8, 0xa1 },
+	{ 0xd73b, 0, 8, 0x1f },
+	{ 0xd73c, 4, 4, 0x0a },
+	{ 0xd732, 3, 1, 0x00 },
+	{ 0xd731, 4, 2, 0x03 },
+	{ 0xd73d, 7, 1, 0x01 },
+	{ 0xd740, 0, 1, 0x00 },
+	{ 0xd740, 1, 1, 0x00 },
+	{ 0xd740, 2, 1, 0x00 },
+	{ 0xd740, 3, 1, 0x01 },
+	{ 0xd3c1, 4, 1, 0x01 },
+	{ 0x9124, 0, 8, 0x58 },
+	{ 0x9125, 0, 2, 0x02 },
+	{ 0xd3a2, 0, 8, 0x00 },
+	{ 0xd3a3, 0, 8, 0x04 },
+	{ 0xd305, 0, 8, 0x32 },
+	{ 0xd306, 0, 8, 0x10 },
+	{ 0xd304, 0, 8, 0x04 },
+	{ 0x9112, 0, 1, 0x01 },
+	{ 0x911d, 0, 1, 0x01 },
+	{ 0x911a, 0, 1, 0x01 },
+	{ 0x911b, 0, 1, 0x01 },
+	{ 0x9bce, 0, 4, 0x02 },
+	{ 0x9116, 0, 1, 0x01 },
+	{ 0x9122, 0, 8, 0xd0 },
+	{ 0xd2e0, 0, 8, 0xd0 },
+	{ 0xd2e9, 0, 4, 0x0d },
+	{ 0xd38c, 0, 8, 0xfc },
+	{ 0xd38d, 0, 8, 0x00 },
+	{ 0xd38e, 0, 8, 0x7e },
+	{ 0xd38f, 0, 8, 0x00 },
+	{ 0xd390, 0, 8, 0x2f },
+	{ 0xd145, 4, 1, 0x01 },
+	{ 0xd1a9, 4, 1, 0x01 },
+	{ 0xd158, 5, 3, 0x01 },
+	{ 0xd159, 0, 6, 0x06 },
+	{ 0xd167, 0, 8, 0x00 },
+	{ 0xd168, 0, 4, 0x07 },
+	{ 0xd1c3, 5, 3, 0x00 },
+	{ 0xd1c4, 0, 6, 0x00 },
+	{ 0xd1c5, 0, 7, 0x10 },
+	{ 0xd1c6, 0, 3, 0x02 },
+	{ 0xd080, 2, 5, 0x03 },
+	{ 0xd081, 4, 4, 0x09 },
+	{ 0xd098, 4, 4, 0x0f },
+	{ 0xd098, 0, 4, 0x03 },
+	{ 0xdbc0, 4, 1, 0x01 },
+	{ 0xdbc7, 0, 8, 0x08 },
+	{ 0xdbc8, 4, 4, 0x00 },
+	{ 0xdbc9, 0, 5, 0x01 },
+	{ 0xd280, 0, 8, 0xe0 },
+	{ 0xd281, 0, 8, 0xff },
+	{ 0xd282, 0, 8, 0xff },
+	{ 0xd283, 0, 8, 0xc3 },
+	{ 0xd284, 0, 8, 0xff },
+	{ 0xd285, 0, 4, 0x01 },
+	{ 0xd0f0, 0, 7, 0x1a },
+	{ 0xd0f1, 4, 1, 0x01 },
+	{ 0xd0f2, 0, 8, 0x0c },
+	{ 0xd101, 5, 3, 0x06 },
+	{ 0xd103, 0, 4, 0x08 },
+	{ 0xd0f8, 0, 7, 0x20 },
+	{ 0xd111, 5, 1, 0x00 },
+	{ 0xd111, 6, 1, 0x00 },
+	{ 0x910b, 0, 8, 0x0a },
+	{ 0x9115, 0, 8, 0x02 },
+	{ 0x910c, 0, 8, 0x02 },
+	{ 0x910d, 0, 8, 0x08 },
+	{ 0x910e, 0, 8, 0x0a },
+	{ 0x9bf6, 0, 8, 0x06 },
+	{ 0x9bf8, 0, 8, 0x02 },
+	{ 0x9bf7, 0, 8, 0x05 },
+	{ 0x9bf9, 0, 8, 0x0f },
+	{ 0x9bfc, 0, 8, 0x13 },
+	{ 0x9bd3, 0, 8, 0xff },
+	{ 0x9bbe, 0, 1, 0x01 },
+	{ 0x9bcc, 0, 1, 0x01 },
+};
+
+/* Panasonic ENV77H11D5 tuner init
+   AF9013_TUNER_ENV77H11D5 = 129 */
+static const struct af9013_reg_bit tuner_init_env77h11d5[] = {
+	{ 0x9bd5, 0, 8, 0x01 },
+	{ 0x9bd6, 0, 8, 0x03 },
+	{ 0x9bbe, 0, 8, 0x01 },
+	{ 0xd1a0, 1, 1, 0x01 },
+	{ 0xd000, 0, 1, 0x01 },
+	{ 0xd000, 1, 1, 0x00 },
+	{ 0xd001, 1, 1, 0x01 },
+	{ 0xd001, 0, 1, 0x00 },
+	{ 0xd001, 5, 1, 0x00 },
+	{ 0xd002, 0, 5, 0x19 },
+	{ 0xd003, 0, 5, 0x1a },
+	{ 0xd004, 0, 5, 0x19 },
+	{ 0xd005, 0, 5, 0x1a },
+	{ 0xd00e, 0, 5, 0x10 },
+	{ 0xd00f, 0, 3, 0x04 },
+	{ 0xd00f, 3, 3, 0x05 },
+	{ 0xd010, 0, 3, 0x04 },
+	{ 0xd010, 3, 3, 0x05 },
+	{ 0xd016, 4, 4, 0x03 },
+	{ 0xd01f, 0, 6, 0x0a },
+	{ 0xd020, 0, 6, 0x0a },
+	{ 0x9bda, 0, 8, 0x00 },
+	{ 0x9be3, 0, 8, 0x00 },
+	{ 0xd015, 0, 8, 0x50 },
+	{ 0xd016, 0, 1, 0x00 },
+	{ 0xd044, 0, 8, 0x46 },
+	{ 0xd045, 0, 1, 0x00 },
+	{ 0xd008, 0, 8, 0xdf },
+	{ 0xd009, 0, 2, 0x02 },
+	{ 0xd006, 0, 8, 0x44 },
+	{ 0xd007, 0, 2, 0x01 },
+	{ 0xd00c, 0, 8, 0xeb },
+	{ 0xd00d, 0, 2, 0x02 },
+	{ 0xd00a, 0, 8, 0xf4 },
+	{ 0xd00b, 0, 2, 0x01 },
+	{ 0x9bba, 0, 8, 0xf9 },
+	{ 0x9bc3, 0, 8, 0xdf },
+	{ 0x9bc4, 0, 8, 0x02 },
+	{ 0x9bc5, 0, 8, 0xeb },
+	{ 0x9bc6, 0, 8, 0x02 },
+	{ 0x9bc9, 0, 8, 0x52 },
+	{ 0xd011, 0, 8, 0x3c },
+	{ 0xd012, 0, 2, 0x01 },
+	{ 0xd013, 0, 8, 0xf7 },
+	{ 0xd014, 0, 2, 0x02 },
+	{ 0xd040, 0, 8, 0x0b },
+	{ 0xd041, 0, 2, 0x02 },
+	{ 0xd042, 0, 8, 0x4d },
+	{ 0xd043, 0, 2, 0x00 },
+	{ 0xd045, 1, 1, 0x00 },
+	{ 0x9bcf, 0, 1, 0x01 },
+	{ 0xd045, 2, 1, 0x01 },
+	{ 0xd04f, 0, 8, 0x9a },
+	{ 0xd050, 0, 1, 0x01 },
+	{ 0xd051, 0, 8, 0x5a },
+	{ 0xd052, 0, 1, 0x01 },
+	{ 0xd053, 0, 8, 0x50 },
+	{ 0xd054, 0, 8, 0x46 },
+	{ 0x9bd7, 0, 8, 0x0a },
+	{ 0x9bd8, 0, 8, 0x14 },
+	{ 0x9bd9, 0, 8, 0x08 },
+};
+
+/* Microtune MT2060 tuner init
+   AF9013_TUNER_MT2060     = 130 */
+static const struct af9013_reg_bit tuner_init_mt2060[] = {
+	{ 0x9bd5, 0, 8, 0x01 },
+	{ 0x9bd6, 0, 8, 0x07 },
+	{ 0xd1a0, 1, 1, 0x01 },
+	{ 0xd000, 0, 1, 0x01 },
+	{ 0xd000, 1, 1, 0x00 },
+	{ 0xd001, 1, 1, 0x01 },
+	{ 0xd001, 0, 1, 0x00 },
+	{ 0xd001, 5, 1, 0x00 },
+	{ 0xd002, 0, 5, 0x19 },
+	{ 0xd003, 0, 5, 0x1a },
+	{ 0xd004, 0, 5, 0x19 },
+	{ 0xd005, 0, 5, 0x1a },
+	{ 0xd00e, 0, 5, 0x10 },
+	{ 0xd00f, 0, 3, 0x04 },
+	{ 0xd00f, 3, 3, 0x05 },
+	{ 0xd010, 0, 3, 0x04 },
+	{ 0xd010, 3, 3, 0x05 },
+	{ 0xd016, 4, 4, 0x03 },
+	{ 0xd01f, 0, 6, 0x0a },
+	{ 0xd020, 0, 6, 0x0a },
+	{ 0x9bda, 0, 8, 0x00 },
+	{ 0x9be3, 0, 8, 0x00 },
+	{ 0x9bbe, 0, 1, 0x00 },
+	{ 0x9bcc, 0, 1, 0x00 },
+	{ 0x9bb9, 0, 8, 0x75 },
+	{ 0x9bcd, 0, 8, 0x24 },
+	{ 0x9bff, 0, 8, 0x30 },
+	{ 0xd015, 0, 8, 0x46 },
+	{ 0xd016, 0, 1, 0x00 },
+	{ 0xd044, 0, 8, 0x46 },
+	{ 0xd045, 0, 1, 0x00 },
+	{ 0xd008, 0, 8, 0x0f },
+	{ 0xd009, 0, 2, 0x02 },
+	{ 0xd006, 0, 8, 0x32 },
+	{ 0xd007, 0, 2, 0x01 },
+	{ 0xd00c, 0, 8, 0x36 },
+	{ 0xd00d, 0, 2, 0x03 },
+	{ 0xd00a, 0, 8, 0x35 },
+	{ 0xd00b, 0, 2, 0x01 },
+	{ 0x9bc7, 0, 8, 0x07 },
+	{ 0x9bc8, 0, 8, 0x90 },
+	{ 0x9bc3, 0, 8, 0x0f },
+	{ 0x9bc4, 0, 8, 0x02 },
+	{ 0x9bc5, 0, 8, 0x36 },
+	{ 0x9bc6, 0, 8, 0x03 },
+	{ 0x9bba, 0, 8, 0xc9 },
+	{ 0x9bc9, 0, 8, 0x79 },
+	{ 0xd011, 0, 8, 0x10 },
+	{ 0xd012, 0, 2, 0x01 },
+	{ 0xd013, 0, 8, 0x45 },
+	{ 0xd014, 0, 2, 0x03 },
+	{ 0xd040, 0, 8, 0x98 },
+	{ 0xd041, 0, 2, 0x00 },
+	{ 0xd042, 0, 8, 0xcf },
+	{ 0xd043, 0, 2, 0x03 },
+	{ 0xd045, 1, 1, 0x00 },
+	{ 0x9bcf, 0, 1, 0x01 },
+	{ 0xd045, 2, 1, 0x01 },
+	{ 0xd04f, 0, 8, 0x9a },
+	{ 0xd050, 0, 1, 0x01 },
+	{ 0xd051, 0, 8, 0x5a },
+	{ 0xd052, 0, 1, 0x01 },
+	{ 0xd053, 0, 8, 0x50 },
+	{ 0xd054, 0, 8, 0x46 },
+	{ 0x9bd7, 0, 8, 0x0a },
+	{ 0x9bd8, 0, 8, 0x14 },
+	{ 0x9bd9, 0, 8, 0x08 },
+	{ 0x9bd0, 0, 8, 0xcc },
+	{ 0x9be4, 0, 8, 0xa0 },
+	{ 0x9bbd, 0, 8, 0x8e },
+	{ 0x9be2, 0, 8, 0x4d },
+	{ 0x9bee, 0, 1, 0x01 },
+};
+
+/* Microtune MT2060 tuner init
+   AF9013_TUNER_MT2060_2   = 147 */
+static const struct af9013_reg_bit tuner_init_mt2060_2[] = {
+	{ 0x9bd5, 0, 8, 0x01 },
+	{ 0x9bd6, 0, 8, 0x06 },
+	{ 0x9bbe, 0, 8, 0x01 },
+	{ 0xd1a0, 1, 1, 0x01 },
+	{ 0xd000, 0, 1, 0x01 },
+	{ 0xd000, 1, 1, 0x00 },
+	{ 0xd001, 1, 1, 0x01 },
+	{ 0xd001, 0, 1, 0x00 },
+	{ 0xd001, 5, 1, 0x00 },
+	{ 0xd002, 0, 5, 0x19 },
+	{ 0xd003, 0, 5, 0x1a },
+	{ 0xd004, 0, 5, 0x19 },
+	{ 0xd005, 0, 5, 0x1a },
+	{ 0xd00e, 0, 5, 0x10 },
+	{ 0xd00f, 0, 3, 0x04 },
+	{ 0xd00f, 3, 3, 0x05 },
+	{ 0xd010, 0, 3, 0x04 },
+	{ 0xd010, 3, 3, 0x05 },
+	{ 0xd016, 4, 4, 0x03 },
+	{ 0xd01f, 0, 6, 0x0a },
+	{ 0xd020, 0, 6, 0x0a },
+	{ 0xd015, 0, 8, 0x46 },
+	{ 0xd016, 0, 1, 0x00 },
+	{ 0xd044, 0, 8, 0x46 },
+	{ 0xd045, 0, 1, 0x00 },
+	{ 0xd008, 0, 8, 0x0f },
+	{ 0xd009, 0, 2, 0x02 },
+	{ 0xd006, 0, 8, 0x32 },
+	{ 0xd007, 0, 2, 0x01 },
+	{ 0xd00c, 0, 8, 0x36 },
+	{ 0xd00d, 0, 2, 0x03 },
+	{ 0xd00a, 0, 8, 0x35 },
+	{ 0xd00b, 0, 2, 0x01 },
+	{ 0x9bc7, 0, 8, 0x07 },
+	{ 0x9bc8, 0, 8, 0x90 },
+	{ 0x9bc3, 0, 8, 0x0f },
+	{ 0x9bc4, 0, 8, 0x02 },
+	{ 0x9bc5, 0, 8, 0x36 },
+	{ 0x9bc6, 0, 8, 0x03 },
+	{ 0x9bba, 0, 8, 0xc9 },
+	{ 0x9bc9, 0, 8, 0x79 },
+	{ 0xd011, 0, 8, 0x10 },
+	{ 0xd012, 0, 2, 0x01 },
+	{ 0xd013, 0, 8, 0x45 },
+	{ 0xd014, 0, 2, 0x03 },
+	{ 0xd040, 0, 8, 0x98 },
+	{ 0xd041, 0, 2, 0x00 },
+	{ 0xd042, 0, 8, 0xcf },
+	{ 0xd043, 0, 2, 0x03 },
+	{ 0xd045, 1, 1, 0x00 },
+	{ 0x9bcf, 0, 8, 0x01 },
+	{ 0xd045, 2, 1, 0x01 },
+	{ 0xd04f, 0, 8, 0x9a },
+	{ 0xd050, 0, 1, 0x01 },
+	{ 0xd051, 0, 8, 0x5a },
+	{ 0xd052, 0, 1, 0x01 },
+	{ 0xd053, 0, 8, 0x96 },
+	{ 0xd054, 0, 8, 0x46 },
+	{ 0xd045, 7, 1, 0x00 },
+	{ 0x9bd7, 0, 8, 0x0a },
+	{ 0x9bd8, 0, 8, 0x14 },
+	{ 0x9bd9, 0, 8, 0x08 },
+};
+
+/* MaxLinear MXL5003 tuner init
+   AF9013_TUNER_MXL5003D   =   3 */
+static const struct af9013_reg_bit tuner_init_mxl5003d[] = {
+	{ 0x9bd5, 0, 8, 0x01 },
+	{ 0x9bd6, 0, 8, 0x09 },
+	{ 0xd1a0, 1, 1, 0x01 },
+	{ 0xd000, 0, 1, 0x01 },
+	{ 0xd000, 1, 1, 0x00 },
+	{ 0xd001, 1, 1, 0x01 },
+	{ 0xd001, 0, 1, 0x00 },
+	{ 0xd001, 5, 1, 0x00 },
+	{ 0xd002, 0, 5, 0x19 },
+	{ 0xd003, 0, 5, 0x1a },
+	{ 0xd004, 0, 5, 0x19 },
+	{ 0xd005, 0, 5, 0x1a },
+	{ 0xd00e, 0, 5, 0x10 },
+	{ 0xd00f, 0, 3, 0x04 },
+	{ 0xd00f, 3, 3, 0x05 },
+	{ 0xd010, 0, 3, 0x04 },
+	{ 0xd010, 3, 3, 0x05 },
+	{ 0xd016, 4, 4, 0x03 },
+	{ 0xd01f, 0, 6, 0x0a },
+	{ 0xd020, 0, 6, 0x0a },
+	{ 0x9bda, 0, 8, 0x00 },
+	{ 0x9be3, 0, 8, 0x00 },
+	{ 0x9bfc, 0, 8, 0x0f },
+	{ 0x9bf6, 0, 8, 0x01 },
+	{ 0x9bbe, 0, 1, 0x01 },
+	{ 0xd015, 0, 8, 0x33 },
+	{ 0xd016, 0, 1, 0x00 },
+	{ 0xd044, 0, 8, 0x40 },
+	{ 0xd045, 0, 1, 0x00 },
+	{ 0xd008, 0, 8, 0x0f },
+	{ 0xd009, 0, 2, 0x02 },
+	{ 0xd006, 0, 8, 0x6c },
+	{ 0xd007, 0, 2, 0x00 },
+	{ 0xd00c, 0, 8, 0x3d },
+	{ 0xd00d, 0, 2, 0x00 },
+	{ 0xd00a, 0, 8, 0x45 },
+	{ 0xd00b, 0, 2, 0x01 },
+	{ 0x9bc7, 0, 8, 0x07 },
+	{ 0x9bc8, 0, 8, 0x52 },
+	{ 0x9bc3, 0, 8, 0x0f },
+	{ 0x9bc4, 0, 8, 0x02 },
+	{ 0x9bc5, 0, 8, 0x3d },
+	{ 0x9bc6, 0, 8, 0x00 },
+	{ 0x9bba, 0, 8, 0xa2 },
+	{ 0x9bc9, 0, 8, 0xa0 },
+	{ 0xd011, 0, 8, 0x56 },
+	{ 0xd012, 0, 2, 0x00 },
+	{ 0xd013, 0, 8, 0x50 },
+	{ 0xd014, 0, 2, 0x00 },
+	{ 0xd040, 0, 8, 0x56 },
+	{ 0xd041, 0, 2, 0x00 },
+	{ 0xd042, 0, 8, 0x50 },
+	{ 0xd043, 0, 2, 0x00 },
+	{ 0xd045, 1, 1, 0x00 },
+	{ 0x9bcf, 0, 8, 0x01 },
+	{ 0xd045, 2, 1, 0x01 },
+	{ 0xd04f, 0, 8, 0x9a },
+	{ 0xd050, 0, 1, 0x01 },
+	{ 0xd051, 0, 8, 0x5a },
+	{ 0xd052, 0, 1, 0x01 },
+	{ 0xd053, 0, 8, 0x50 },
+	{ 0xd054, 0, 8, 0x46 },
+	{ 0x9bd7, 0, 8, 0x0a },
+	{ 0x9bd8, 0, 8, 0x14 },
+	{ 0x9bd9, 0, 8, 0x08 },
+};
+
+/* MaxLinear MXL5005S & MXL5007T tuner init
+   AF9013_TUNER_MXL5005D   =  13
+   AF9013_TUNER_MXL5005R   =  30
+   AF9013_TUNER_MXL5007T   = 177 */
+static const struct af9013_reg_bit tuner_init_mxl5005[] = {
+	{ 0x9bd5, 0, 8, 0x01 },
+	{ 0x9bd6, 0, 8, 0x07 },
+	{ 0xd1a0, 1, 1, 0x01 },
+	{ 0xd000, 0, 1, 0x01 },
+	{ 0xd000, 1, 1, 0x00 },
+	{ 0xd001, 1, 1, 0x01 },
+	{ 0xd001, 0, 1, 0x00 },
+	{ 0xd001, 5, 1, 0x00 },
+	{ 0xd002, 0, 5, 0x19 },
+	{ 0xd003, 0, 5, 0x1a },
+	{ 0xd004, 0, 5, 0x19 },
+	{ 0xd005, 0, 5, 0x1a },
+	{ 0xd00e, 0, 5, 0x10 },
+	{ 0xd00f, 0, 3, 0x04 },
+	{ 0xd00f, 3, 3, 0x05 },
+	{ 0xd010, 0, 3, 0x04 },
+	{ 0xd010, 3, 3, 0x05 },
+	{ 0xd016, 4, 4, 0x03 },
+	{ 0xd01f, 0, 6, 0x0a },
+	{ 0xd020, 0, 6, 0x0a },
+	{ 0x9bda, 0, 8, 0x01 },
+	{ 0x9be3, 0, 8, 0x01 },
+	{ 0x9bbe, 0, 1, 0x01 },
+	{ 0x9bcc, 0, 1, 0x01 },
+	{ 0x9bb9, 0, 8, 0x00 },
+	{ 0x9bcd, 0, 8, 0x28 },
+	{ 0x9bff, 0, 8, 0x24 },
+	{ 0xd015, 0, 8, 0x40 },
+	{ 0xd016, 0, 1, 0x00 },
+	{ 0xd044, 0, 8, 0x40 },
+	{ 0xd045, 0, 1, 0x00 },
+	{ 0xd008, 0, 8, 0x0f },
+	{ 0xd009, 0, 2, 0x02 },
+	{ 0xd006, 0, 8, 0x73 },
+	{ 0xd007, 0, 2, 0x01 },
+	{ 0xd00c, 0, 8, 0xfa },
+	{ 0xd00d, 0, 2, 0x01 },
+	{ 0xd00a, 0, 8, 0xff },
+	{ 0xd00b, 0, 2, 0x01 },
+	{ 0x9bc7, 0, 8, 0x23 },
+	{ 0x9bc8, 0, 8, 0x55 },
+	{ 0x9bc3, 0, 8, 0x01 },
+	{ 0x9bc4, 0, 8, 0x02 },
+	{ 0x9bc5, 0, 8, 0xfa },
+	{ 0x9bc6, 0, 8, 0x01 },
+	{ 0x9bba, 0, 8, 0xff },
+	{ 0x9bc9, 0, 8, 0xff },
+	{ 0x9bd3, 0, 8, 0x95 },
+	{ 0xd011, 0, 8, 0x70 },
+	{ 0xd012, 0, 2, 0x01 },
+	{ 0xd013, 0, 8, 0xfb },
+	{ 0xd014, 0, 2, 0x01 },
+	{ 0xd040, 0, 8, 0x70 },
+	{ 0xd041, 0, 2, 0x01 },
+	{ 0xd042, 0, 8, 0xfb },
+	{ 0xd043, 0, 2, 0x01 },
+	{ 0xd045, 1, 1, 0x00 },
+	{ 0x9bcf, 0, 1, 0x01 },
+	{ 0xd045, 2, 1, 0x01 },
+	{ 0xd04f, 0, 8, 0x9a },
+	{ 0xd050, 0, 1, 0x01 },
+	{ 0xd051, 0, 8, 0x5a },
+	{ 0xd052, 0, 1, 0x01 },
+	{ 0xd053, 0, 8, 0x50 },
+	{ 0xd054, 0, 8, 0x46 },
+	{ 0x9bd7, 0, 8, 0x0a },
+	{ 0x9bd8, 0, 8, 0x14 },
+	{ 0x9bd9, 0, 8, 0x08 },
+	{ 0x9bd0, 0, 8, 0x93 },
+	{ 0x9be4, 0, 8, 0xfe },
+	{ 0x9bbd, 0, 8, 0x63 },
+	{ 0x9be2, 0, 8, 0xfe },
+	{ 0x9bee, 0, 1, 0x01 },
+};
+
+/* Quantek QT1010 tuner init
+   AF9013_TUNER_QT1010     = 134
+   AF9013_TUNER_QT1010A    = 162 */
+static const struct af9013_reg_bit tuner_init_qt1010[] = {
+	{ 0x9bd5, 0, 8, 0x01 },
+	{ 0x9bd6, 0, 8, 0x09 },
+	{ 0xd1a0, 1, 1, 0x01 },
+	{ 0xd000, 0, 1, 0x01 },
+	{ 0xd000, 1, 1, 0x00 },
+	{ 0xd001, 1, 1, 0x01 },
+	{ 0xd001, 0, 1, 0x00 },
+	{ 0xd001, 5, 1, 0x00 },
+	{ 0xd002, 0, 5, 0x19 },
+	{ 0xd003, 0, 5, 0x1a },
+	{ 0xd004, 0, 5, 0x19 },
+	{ 0xd005, 0, 5, 0x1a },
+	{ 0xd00e, 0, 5, 0x10 },
+	{ 0xd00f, 0, 3, 0x04 },
+	{ 0xd00f, 3, 3, 0x05 },
+	{ 0xd010, 0, 3, 0x04 },
+	{ 0xd010, 3, 3, 0x05 },
+	{ 0xd016, 4, 4, 0x03 },
+	{ 0xd01f, 0, 6, 0x0a },
+	{ 0xd020, 0, 6, 0x0a },
+	{ 0x9bda, 0, 8, 0x01 },
+	{ 0x9be3, 0, 8, 0x01 },
+	{ 0xd015, 0, 8, 0x46 },
+	{ 0xd016, 0, 1, 0x00 },
+	{ 0xd044, 0, 8, 0x46 },
+	{ 0xd045, 0, 1, 0x00 },
+	{ 0x9bbe, 0, 1, 0x01 },
+	{ 0x9bcc, 0, 1, 0x01 },
+	{ 0x9bb9, 0, 8, 0x00 },
+	{ 0x9bcd, 0, 8, 0x28 },
+	{ 0x9bff, 0, 8, 0x20 },
+	{ 0xd008, 0, 8, 0x0f },
+	{ 0xd009, 0, 2, 0x02 },
+	{ 0xd006, 0, 8, 0x99 },
+	{ 0xd007, 0, 2, 0x01 },
+	{ 0xd00c, 0, 8, 0x0f },
+	{ 0xd00d, 0, 2, 0x02 },
+	{ 0xd00a, 0, 8, 0x50 },
+	{ 0xd00b, 0, 2, 0x01 },
+	{ 0x9bc7, 0, 8, 0x00 },
+	{ 0x9bc8, 0, 8, 0x00 },
+	{ 0x9bc3, 0, 8, 0x0f },
+	{ 0x9bc4, 0, 8, 0x02 },
+	{ 0x9bc5, 0, 8, 0x0f },
+	{ 0x9bc6, 0, 8, 0x02 },
+	{ 0x9bba, 0, 8, 0xc5 },
+	{ 0x9bc9, 0, 8, 0xff },
+	{ 0xd011, 0, 8, 0x58 },
+	{ 0xd012, 0, 2, 0x02 },
+	{ 0xd013, 0, 8, 0x89 },
+	{ 0xd014, 0, 2, 0x01 },
+	{ 0xd040, 0, 8, 0x58 },
+	{ 0xd041, 0, 2, 0x02 },
+	{ 0xd042, 0, 8, 0x89 },
+	{ 0xd043, 0, 2, 0x01 },
+	{ 0xd045, 1, 1, 0x00 },
+	{ 0x9bcf, 0, 1, 0x01 },
+	{ 0xd045, 2, 1, 0x01 },
+	{ 0xd04f, 0, 8, 0x9a },
+	{ 0xd050, 0, 1, 0x01 },
+	{ 0xd051, 0, 8, 0x5a },
+	{ 0xd052, 0, 1, 0x01 },
+	{ 0xd053, 0, 8, 0x50 },
+	{ 0xd054, 0, 8, 0x46 },
+	{ 0x9bd7, 0, 8, 0x0a },
+	{ 0x9bd8, 0, 8, 0x14 },
+	{ 0x9bd9, 0, 8, 0x08 },
+	{ 0x9bd0, 0, 8, 0xcd },
+	{ 0x9be4, 0, 8, 0xbb },
+	{ 0x9bbd, 0, 8, 0x93 },
+	{ 0x9be2, 0, 8, 0x80 },
+	{ 0x9bee, 0, 1, 0x01 },
+};
+
+/* Freescale MC44S803 tuner init
+   AF9013_TUNER_MC44S803   = 133 */
+static const struct af9013_reg_bit tuner_init_mc44s803[] = {
+	{ 0x9bd5, 0, 8, 0x01 },
+	{ 0x9bd6, 0, 8, 0x06 },
+	{ 0xd1a0, 1, 1, 0x01 },
+	{ 0xd000, 0, 1, 0x01 },
+	{ 0xd000, 1, 1, 0x00 },
+	{ 0xd001, 1, 1, 0x01 },
+	{ 0xd001, 0, 1, 0x00 },
+	{ 0xd001, 5, 1, 0x00 },
+	{ 0xd002, 0, 5, 0x19 },
+	{ 0xd003, 0, 5, 0x1a },
+	{ 0xd004, 0, 5, 0x19 },
+	{ 0xd005, 0, 5, 0x1a },
+	{ 0xd00e, 0, 5, 0x10 },
+	{ 0xd00f, 0, 3, 0x04 },
+	{ 0xd00f, 3, 3, 0x05 },
+	{ 0xd010, 0, 3, 0x04 },
+	{ 0xd010, 3, 3, 0x05 },
+	{ 0xd016, 4, 4, 0x03 },
+	{ 0xd01f, 0, 6, 0x0a },
+	{ 0xd020, 0, 6, 0x0a },
+	{ 0x9bda, 0, 8, 0x00 },
+	{ 0x9be3, 0, 8, 0x00 },
+	{ 0x9bf6, 0, 8, 0x01 },
+	{ 0x9bf8, 0, 8, 0x02 },
+	{ 0x9bf9, 0, 8, 0x02 },
+	{ 0x9bfc, 0, 8, 0x1f },
+	{ 0x9bbe, 0, 1, 0x01 },
+	{ 0x9bcc, 0, 1, 0x01 },
+	{ 0x9bb9, 0, 8, 0x00 },
+	{ 0x9bcd, 0, 8, 0x24 },
+	{ 0x9bff, 0, 8, 0x24 },
+	{ 0xd015, 0, 8, 0x46 },
+	{ 0xd016, 0, 1, 0x00 },
+	{ 0xd044, 0, 8, 0x46 },
+	{ 0xd045, 0, 1, 0x00 },
+	{ 0xd008, 0, 8, 0x01 },
+	{ 0xd009, 0, 2, 0x02 },
+	{ 0xd006, 0, 8, 0x7b },
+	{ 0xd007, 0, 2, 0x00 },
+	{ 0xd00c, 0, 8, 0x7c },
+	{ 0xd00d, 0, 2, 0x02 },
+	{ 0xd00a, 0, 8, 0xfe },
+	{ 0xd00b, 0, 2, 0x01 },
+	{ 0x9bc7, 0, 8, 0x08 },
+	{ 0x9bc8, 0, 8, 0x9a },
+	{ 0x9bc3, 0, 8, 0x01 },
+	{ 0x9bc4, 0, 8, 0x02 },
+	{ 0x9bc5, 0, 8, 0x7c },
+	{ 0x9bc6, 0, 8, 0x02 },
+	{ 0x9bba, 0, 8, 0xfc },
+	{ 0x9bc9, 0, 8, 0xaa },
+	{ 0xd011, 0, 8, 0x6b },
+	{ 0xd012, 0, 2, 0x00 },
+	{ 0xd013, 0, 8, 0x88 },
+	{ 0xd014, 0, 2, 0x02 },
+	{ 0xd040, 0, 8, 0x6b },
+	{ 0xd041, 0, 2, 0x00 },
+	{ 0xd042, 0, 8, 0x7c },
+	{ 0xd043, 0, 2, 0x02 },
+	{ 0xd045, 1, 1, 0x00 },
+	{ 0x9bcf, 0, 1, 0x01 },
+	{ 0xd045, 2, 1, 0x01 },
+	{ 0xd04f, 0, 8, 0x9a },
+	{ 0xd050, 0, 1, 0x01 },
+	{ 0xd051, 0, 8, 0x5a },
+	{ 0xd052, 0, 1, 0x01 },
+	{ 0xd053, 0, 8, 0x50 },
+	{ 0xd054, 0, 8, 0x46 },
+	{ 0x9bd7, 0, 8, 0x0a },
+	{ 0x9bd8, 0, 8, 0x14 },
+	{ 0x9bd9, 0, 8, 0x08 },
+	{ 0x9bd0, 0, 8, 0x9e },
+	{ 0x9be4, 0, 8, 0xff },
+	{ 0x9bbd, 0, 8, 0x9e },
+	{ 0x9be2, 0, 8, 0x25 },
+	{ 0x9bee, 0, 1, 0x01 },
+	{ 0xd73b, 3, 1, 0x00 },
+};
+
+/* unknown, probably for tin can tuner, tuner init
+   AF9013_TUNER_UNKNOWN   = 140 */
+static const struct af9013_reg_bit tuner_init_unknown[] = {
+	{ 0x9bd5, 0, 8, 0x01 },
+	{ 0x9bd6, 0, 8, 0x02 },
+	{ 0xd1a0, 1, 1, 0x01 },
+	{ 0xd000, 0, 1, 0x01 },
+	{ 0xd000, 1, 1, 0x00 },
+	{ 0xd001, 1, 1, 0x01 },
+	{ 0xd001, 0, 1, 0x00 },
+	{ 0xd001, 5, 1, 0x00 },
+	{ 0xd002, 0, 5, 0x19 },
+	{ 0xd003, 0, 5, 0x1a },
+	{ 0xd004, 0, 5, 0x19 },
+	{ 0xd005, 0, 5, 0x1a },
+	{ 0xd00e, 0, 5, 0x10 },
+	{ 0xd00f, 0, 3, 0x04 },
+	{ 0xd00f, 3, 3, 0x05 },
+	{ 0xd010, 0, 3, 0x04 },
+	{ 0xd010, 3, 3, 0x05 },
+	{ 0xd016, 4, 4, 0x03 },
+	{ 0xd01f, 0, 6, 0x0a },
+	{ 0xd020, 0, 6, 0x0a },
+	{ 0x9bda, 0, 8, 0x01 },
+	{ 0x9be3, 0, 8, 0x01 },
+	{ 0xd1a0, 1, 1, 0x00 },
+	{ 0x9bbe, 0, 1, 0x01 },
+	{ 0x9bcc, 0, 1, 0x01 },
+	{ 0x9bb9, 0, 8, 0x00 },
+	{ 0x9bcd, 0, 8, 0x18 },
+	{ 0x9bff, 0, 8, 0x2c },
+	{ 0xd015, 0, 8, 0x46 },
+	{ 0xd016, 0, 1, 0x00 },
+	{ 0xd044, 0, 8, 0x46 },
+	{ 0xd045, 0, 1, 0x00 },
+	{ 0xd008, 0, 8, 0xdf },
+	{ 0xd009, 0, 2, 0x02 },
+	{ 0xd006, 0, 8, 0x44 },
+	{ 0xd007, 0, 2, 0x01 },
+	{ 0xd00c, 0, 8, 0x00 },
+	{ 0xd00d, 0, 2, 0x02 },
+	{ 0xd00a, 0, 8, 0xf6 },
+	{ 0xd00b, 0, 2, 0x01 },
+	{ 0x9bba, 0, 8, 0xf9 },
+	{ 0x9bc8, 0, 8, 0xaa },
+	{ 0x9bc3, 0, 8, 0xdf },
+	{ 0x9bc4, 0, 8, 0x02 },
+	{ 0x9bc5, 0, 8, 0x00 },
+	{ 0x9bc6, 0, 8, 0x02 },
+	{ 0x9bc9, 0, 8, 0xf0 },
+	{ 0xd011, 0, 8, 0x3c },
+	{ 0xd012, 0, 2, 0x01 },
+	{ 0xd013, 0, 8, 0xf7 },
+	{ 0xd014, 0, 2, 0x02 },
+	{ 0xd040, 0, 8, 0x0b },
+	{ 0xd041, 0, 2, 0x02 },
+	{ 0xd042, 0, 8, 0x4d },
+	{ 0xd043, 0, 2, 0x00 },
+	{ 0xd045, 1, 1, 0x00 },
+	{ 0x9bcf, 0, 1, 0x01 },
+	{ 0xd045, 2, 1, 0x01 },
+	{ 0xd04f, 0, 8, 0x9a },
+	{ 0xd050, 0, 1, 0x01 },
+	{ 0xd051, 0, 8, 0x5a },
+	{ 0xd052, 0, 1, 0x01 },
+	{ 0xd053, 0, 8, 0x50 },
+	{ 0xd054, 0, 8, 0x46 },
+	{ 0x9bd7, 0, 8, 0x0a },
+	{ 0x9bd8, 0, 8, 0x14 },
+	{ 0x9bd9, 0, 8, 0x08 },
+};
+
+/* NXP TDA18271 & TDA18218 tuner init
+   AF9013_TUNER_TDA18271   = 156
+   AF9013_TUNER_TDA18218   = 179 */
+static const struct af9013_reg_bit tuner_init_tda18271[] = {
+	{ 0x9bd5, 0, 8, 0x01 },
+	{ 0x9bd6, 0, 8, 0x04 },
+	{ 0xd1a0, 1, 1, 0x01 },
+	{ 0xd000, 0, 1, 0x01 },
+	{ 0xd000, 1, 1, 0x00 },
+	{ 0xd001, 1, 1, 0x01 },
+	{ 0xd001, 0, 1, 0x00 },
+	{ 0xd001, 5, 1, 0x00 },
+	{ 0xd002, 0, 5, 0x19 },
+	{ 0xd003, 0, 5, 0x1a },
+	{ 0xd004, 0, 5, 0x19 },
+	{ 0xd005, 0, 5, 0x1a },
+	{ 0xd00e, 0, 5, 0x10 },
+	{ 0xd00f, 0, 3, 0x04 },
+	{ 0xd00f, 3, 3, 0x05 },
+	{ 0xd010, 0, 3, 0x04 },
+	{ 0xd010, 3, 3, 0x05 },
+	{ 0xd016, 4, 4, 0x03 },
+	{ 0xd01f, 0, 6, 0x0a },
+	{ 0xd020, 0, 6, 0x0a },
+	{ 0x9bda, 0, 8, 0x01 },
+	{ 0x9be3, 0, 8, 0x01 },
+	{ 0xd1a0, 1, 1, 0x00 },
+	{ 0x9bbe, 0, 1, 0x01 },
+	{ 0x9bcc, 0, 1, 0x01 },
+	{ 0x9bb9, 0, 8, 0x00 },
+	{ 0x9bcd, 0, 8, 0x18 },
+	{ 0x9bff, 0, 8, 0x2c },
+	{ 0xd015, 0, 8, 0x46 },
+	{ 0xd016, 0, 1, 0x00 },
+	{ 0xd044, 0, 8, 0x46 },
+	{ 0xd045, 0, 1, 0x00 },
+	{ 0xd008, 0, 8, 0xdf },
+	{ 0xd009, 0, 2, 0x02 },
+	{ 0xd006, 0, 8, 0x44 },
+	{ 0xd007, 0, 2, 0x01 },
+	{ 0xd00c, 0, 8, 0x00 },
+	{ 0xd00d, 0, 2, 0x02 },
+	{ 0xd00a, 0, 8, 0xf6 },
+	{ 0xd00b, 0, 2, 0x01 },
+	{ 0x9bba, 0, 8, 0xf9 },
+	{ 0x9bc8, 0, 8, 0xaa },
+	{ 0x9bc3, 0, 8, 0xdf },
+	{ 0x9bc4, 0, 8, 0x02 },
+	{ 0x9bc5, 0, 8, 0x00 },
+	{ 0x9bc6, 0, 8, 0x02 },
+	{ 0x9bc9, 0, 8, 0xf0 },
+	{ 0xd011, 0, 8, 0x3c },
+	{ 0xd012, 0, 2, 0x01 },
+	{ 0xd013, 0, 8, 0xf7 },
+	{ 0xd014, 0, 2, 0x02 },
+	{ 0xd040, 0, 8, 0x0b },
+	{ 0xd041, 0, 2, 0x02 },
+	{ 0xd042, 0, 8, 0x4d },
+	{ 0xd043, 0, 2, 0x00 },
+	{ 0xd045, 1, 1, 0x00 },
+	{ 0x9bcf, 0, 1, 0x01 },
+	{ 0xd045, 2, 1, 0x01 },
+	{ 0xd04f, 0, 8, 0x9a },
+	{ 0xd050, 0, 1, 0x01 },
+	{ 0xd051, 0, 8, 0x5a },
+	{ 0xd052, 0, 1, 0x01 },
+	{ 0xd053, 0, 8, 0x50 },
+	{ 0xd054, 0, 8, 0x46 },
+	{ 0x9bd7, 0, 8, 0x0a },
+	{ 0x9bd8, 0, 8, 0x14 },
+	{ 0x9bd9, 0, 8, 0x08 },
+	{ 0x9bd0, 0, 8, 0xa8 },
+	{ 0x9be4, 0, 8, 0x7f },
+	{ 0x9bbd, 0, 8, 0xa8 },
+	{ 0x9be2, 0, 8, 0x20 },
+	{ 0x9bee, 0, 1, 0x01 },
+};
+
+#endif /* AF9013_PRIV_H */
diff --git a/drivers/media/dvb-frontends/af9033.c b/drivers/media/dvb-frontends/af9033.c
new file mode 100644
index 0000000..0979ada
--- /dev/null
+++ b/drivers/media/dvb-frontends/af9033.c
@@ -0,0 +1,983 @@
+/*
+ * Afatech AF9033 demodulator driver
+ *
+ * Copyright (C) 2009 Antti Palosaari <crope@iki.fi>
+ * Copyright (C) 2012 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.,
+ *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "af9033_priv.h"
+
+struct af9033_state {
+	struct i2c_adapter *i2c;
+	struct dvb_frontend fe;
+	struct af9033_config cfg;
+
+	u32 bandwidth_hz;
+	bool ts_mode_parallel;
+	bool ts_mode_serial;
+
+	u32 ber;
+	u32 ucb;
+	unsigned long last_stat_check;
+};
+
+/* write multiple registers */
+static int af9033_wr_regs(struct af9033_state *state, u32 reg, const u8 *val,
+		int len)
+{
+	int ret;
+	u8 buf[3 + len];
+	struct i2c_msg msg[1] = {
+		{
+			.addr = state->cfg.i2c_addr,
+			.flags = 0,
+			.len = sizeof(buf),
+			.buf = buf,
+		}
+	};
+
+	buf[0] = (reg >> 16) & 0xff;
+	buf[1] = (reg >>  8) & 0xff;
+	buf[2] = (reg >>  0) & 0xff;
+	memcpy(&buf[3], val, len);
+
+	ret = i2c_transfer(state->i2c, msg, 1);
+	if (ret == 1) {
+		ret = 0;
+	} else {
+		dev_warn(&state->i2c->dev, "%s: i2c wr failed=%d reg=%06x " \
+				"len=%d\n", KBUILD_MODNAME, ret, reg, len);
+		ret = -EREMOTEIO;
+	}
+
+	return ret;
+}
+
+/* read multiple registers */
+static int af9033_rd_regs(struct af9033_state *state, u32 reg, u8 *val, int len)
+{
+	int ret;
+	u8 buf[3] = { (reg >> 16) & 0xff, (reg >> 8) & 0xff,
+			(reg >> 0) & 0xff };
+	struct i2c_msg msg[2] = {
+		{
+			.addr = state->cfg.i2c_addr,
+			.flags = 0,
+			.len = sizeof(buf),
+			.buf = buf
+		}, {
+			.addr = state->cfg.i2c_addr,
+			.flags = I2C_M_RD,
+			.len = len,
+			.buf = val
+		}
+	};
+
+	ret = i2c_transfer(state->i2c, msg, 2);
+	if (ret == 2) {
+		ret = 0;
+	} else {
+		dev_warn(&state->i2c->dev, "%s: i2c rd failed=%d reg=%06x " \
+				"len=%d\n", KBUILD_MODNAME, ret, reg, len);
+		ret = -EREMOTEIO;
+	}
+
+	return ret;
+}
+
+
+/* write single register */
+static int af9033_wr_reg(struct af9033_state *state, u32 reg, u8 val)
+{
+	return af9033_wr_regs(state, reg, &val, 1);
+}
+
+/* read single register */
+static int af9033_rd_reg(struct af9033_state *state, u32 reg, u8 *val)
+{
+	return af9033_rd_regs(state, reg, val, 1);
+}
+
+/* write single register with mask */
+static int af9033_wr_reg_mask(struct af9033_state *state, u32 reg, u8 val,
+		u8 mask)
+{
+	int ret;
+	u8 tmp;
+
+	/* no need for read if whole reg is written */
+	if (mask != 0xff) {
+		ret = af9033_rd_regs(state, reg, &tmp, 1);
+		if (ret)
+			return ret;
+
+		val &= mask;
+		tmp &= ~mask;
+		val |= tmp;
+	}
+
+	return af9033_wr_regs(state, reg, &val, 1);
+}
+
+/* read single register with mask */
+static int af9033_rd_reg_mask(struct af9033_state *state, u32 reg, u8 *val,
+		u8 mask)
+{
+	int ret, i;
+	u8 tmp;
+
+	ret = af9033_rd_regs(state, reg, &tmp, 1);
+	if (ret)
+		return ret;
+
+	tmp &= mask;
+
+	/* find position of the first bit */
+	for (i = 0; i < 8; i++) {
+		if ((mask >> i) & 0x01)
+			break;
+	}
+	*val = tmp >> i;
+
+	return 0;
+}
+
+static u32 af9033_div(struct af9033_state *state, u32 a, u32 b, u32 x)
+{
+	u32 r = 0, c = 0, i;
+
+	dev_dbg(&state->i2c->dev, "%s: a=%d b=%d x=%d\n", __func__, a, b, x);
+
+	if (a > b) {
+		c = a / b;
+		a = a - c * b;
+	}
+
+	for (i = 0; i < x; i++) {
+		if (a >= b) {
+			r += 1;
+			a -= b;
+		}
+		a <<= 1;
+		r <<= 1;
+	}
+	r = (c << (u32)x) + r;
+
+	dev_dbg(&state->i2c->dev, "%s: a=%d b=%d x=%d r=%d r=%x\n",
+			__func__, a, b, x, r, r);
+
+	return r;
+}
+
+static void af9033_release(struct dvb_frontend *fe)
+{
+	struct af9033_state *state = fe->demodulator_priv;
+
+	kfree(state);
+}
+
+static int af9033_init(struct dvb_frontend *fe)
+{
+	struct af9033_state *state = fe->demodulator_priv;
+	int ret, i, len;
+	const struct reg_val *init;
+	u8 buf[4];
+	u32 adc_cw, clock_cw;
+	struct reg_val_mask tab[] = {
+		{ 0x80fb24, 0x00, 0x08 },
+		{ 0x80004c, 0x00, 0xff },
+		{ 0x00f641, state->cfg.tuner, 0xff },
+		{ 0x80f5ca, 0x01, 0x01 },
+		{ 0x80f715, 0x01, 0x01 },
+		{ 0x00f41f, 0x04, 0x04 },
+		{ 0x00f41a, 0x01, 0x01 },
+		{ 0x80f731, 0x00, 0x01 },
+		{ 0x00d91e, 0x00, 0x01 },
+		{ 0x00d919, 0x00, 0x01 },
+		{ 0x80f732, 0x00, 0x01 },
+		{ 0x00d91f, 0x00, 0x01 },
+		{ 0x00d91a, 0x00, 0x01 },
+		{ 0x80f730, 0x00, 0x01 },
+		{ 0x80f778, 0x00, 0xff },
+		{ 0x80f73c, 0x01, 0x01 },
+		{ 0x80f776, 0x00, 0x01 },
+		{ 0x00d8fd, 0x01, 0xff },
+		{ 0x00d830, 0x01, 0xff },
+		{ 0x00d831, 0x00, 0xff },
+		{ 0x00d832, 0x00, 0xff },
+		{ 0x80f985, state->ts_mode_serial, 0x01 },
+		{ 0x80f986, state->ts_mode_parallel, 0x01 },
+		{ 0x00d827, 0x00, 0xff },
+		{ 0x00d829, 0x00, 0xff },
+	};
+
+	/* program clock control */
+	clock_cw = af9033_div(state, state->cfg.clock, 1000000ul, 19ul);
+	buf[0] = (clock_cw >>  0) & 0xff;
+	buf[1] = (clock_cw >>  8) & 0xff;
+	buf[2] = (clock_cw >> 16) & 0xff;
+	buf[3] = (clock_cw >> 24) & 0xff;
+
+	dev_dbg(&state->i2c->dev, "%s: clock=%d clock_cw=%08x\n",
+			__func__, state->cfg.clock, clock_cw);
+
+	ret = af9033_wr_regs(state, 0x800025, buf, 4);
+	if (ret < 0)
+		goto err;
+
+	/* program ADC control */
+	for (i = 0; i < ARRAY_SIZE(clock_adc_lut); i++) {
+		if (clock_adc_lut[i].clock == state->cfg.clock)
+			break;
+	}
+
+	adc_cw = af9033_div(state, clock_adc_lut[i].adc, 1000000ul, 19ul);
+	buf[0] = (adc_cw >>  0) & 0xff;
+	buf[1] = (adc_cw >>  8) & 0xff;
+	buf[2] = (adc_cw >> 16) & 0xff;
+
+	dev_dbg(&state->i2c->dev, "%s: adc=%d adc_cw=%06x\n",
+			__func__, clock_adc_lut[i].adc, adc_cw);
+
+	ret = af9033_wr_regs(state, 0x80f1cd, buf, 3);
+	if (ret < 0)
+		goto err;
+
+	/* program register table */
+	for (i = 0; i < ARRAY_SIZE(tab); i++) {
+		ret = af9033_wr_reg_mask(state, tab[i].reg, tab[i].val,
+				tab[i].mask);
+		if (ret < 0)
+			goto err;
+	}
+
+	/* settings for TS interface */
+	if (state->cfg.ts_mode == AF9033_TS_MODE_USB) {
+		ret = af9033_wr_reg_mask(state, 0x80f9a5, 0x00, 0x01);
+		if (ret < 0)
+			goto err;
+
+		ret = af9033_wr_reg_mask(state, 0x80f9b5, 0x01, 0x01);
+		if (ret < 0)
+			goto err;
+	} else {
+		ret = af9033_wr_reg_mask(state, 0x80f990, 0x00, 0x01);
+		if (ret < 0)
+			goto err;
+
+		ret = af9033_wr_reg_mask(state, 0x80f9b5, 0x00, 0x01);
+		if (ret < 0)
+			goto err;
+	}
+
+	/* load OFSM settings */
+	dev_dbg(&state->i2c->dev, "%s: load ofsm settings\n", __func__);
+	len = ARRAY_SIZE(ofsm_init);
+	init = ofsm_init;
+	for (i = 0; i < len; i++) {
+		ret = af9033_wr_reg(state, init[i].reg, init[i].val);
+		if (ret < 0)
+			goto err;
+	}
+
+	/* load tuner specific settings */
+	dev_dbg(&state->i2c->dev, "%s: load tuner specific settings\n",
+			__func__);
+	switch (state->cfg.tuner) {
+	case AF9033_TUNER_TUA9001:
+		len = ARRAY_SIZE(tuner_init_tua9001);
+		init = tuner_init_tua9001;
+		break;
+	case AF9033_TUNER_FC0011:
+		len = ARRAY_SIZE(tuner_init_fc0011);
+		init = tuner_init_fc0011;
+		break;
+	case AF9033_TUNER_MXL5007T:
+		len = ARRAY_SIZE(tuner_init_mxl5007t);
+		init = tuner_init_mxl5007t;
+		break;
+	case AF9033_TUNER_TDA18218:
+		len = ARRAY_SIZE(tuner_init_tda18218);
+		init = tuner_init_tda18218;
+		break;
+	default:
+		dev_dbg(&state->i2c->dev, "%s: unsupported tuner ID=%d\n",
+				__func__, state->cfg.tuner);
+		ret = -ENODEV;
+		goto err;
+	}
+
+	for (i = 0; i < len; i++) {
+		ret = af9033_wr_reg(state, init[i].reg, init[i].val);
+		if (ret < 0)
+			goto err;
+	}
+
+	state->bandwidth_hz = 0; /* force to program all parameters */
+
+	return 0;
+
+err:
+	dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret);
+
+	return ret;
+}
+
+static int af9033_sleep(struct dvb_frontend *fe)
+{
+	struct af9033_state *state = fe->demodulator_priv;
+	int ret, i;
+	u8 tmp;
+
+	ret = af9033_wr_reg(state, 0x80004c, 1);
+	if (ret < 0)
+		goto err;
+
+	ret = af9033_wr_reg(state, 0x800000, 0);
+	if (ret < 0)
+		goto err;
+
+	for (i = 100, tmp = 1; i && tmp; i--) {
+		ret = af9033_rd_reg(state, 0x80004c, &tmp);
+		if (ret < 0)
+			goto err;
+
+		usleep_range(200, 10000);
+	}
+
+	dev_dbg(&state->i2c->dev, "%s: loop=%d\n", __func__, i);
+
+	if (i == 0) {
+		ret = -ETIMEDOUT;
+		goto err;
+	}
+
+	ret = af9033_wr_reg_mask(state, 0x80fb24, 0x08, 0x08);
+	if (ret < 0)
+		goto err;
+
+	/* prevent current leak (?) */
+	if (state->cfg.ts_mode == AF9033_TS_MODE_SERIAL) {
+		/* enable parallel TS */
+		ret = af9033_wr_reg_mask(state, 0x00d917, 0x00, 0x01);
+		if (ret < 0)
+			goto err;
+
+		ret = af9033_wr_reg_mask(state, 0x00d916, 0x01, 0x01);
+		if (ret < 0)
+			goto err;
+	}
+
+	return 0;
+
+err:
+	dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret);
+
+	return ret;
+}
+
+static int af9033_get_tune_settings(struct dvb_frontend *fe,
+		struct dvb_frontend_tune_settings *fesettings)
+{
+	fesettings->min_delay_ms = 800;
+	fesettings->step_size = 0;
+	fesettings->max_drift = 0;
+
+	return 0;
+}
+
+static int af9033_set_frontend(struct dvb_frontend *fe)
+{
+	struct af9033_state *state = fe->demodulator_priv;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	int ret, i, spec_inv;
+	u8 tmp, buf[3], bandwidth_reg_val;
+	u32 if_frequency, freq_cw, adc_freq;
+
+	dev_dbg(&state->i2c->dev, "%s: frequency=%d bandwidth_hz=%d\n",
+			__func__, c->frequency, c->bandwidth_hz);
+
+	/* check bandwidth */
+	switch (c->bandwidth_hz) {
+	case 6000000:
+		bandwidth_reg_val = 0x00;
+		break;
+	case 7000000:
+		bandwidth_reg_val = 0x01;
+		break;
+	case 8000000:
+		bandwidth_reg_val = 0x02;
+		break;
+	default:
+		dev_dbg(&state->i2c->dev, "%s: invalid bandwidth_hz\n",
+				__func__);
+		ret = -EINVAL;
+		goto err;
+	}
+
+	/* program tuner */
+	if (fe->ops.tuner_ops.set_params)
+		fe->ops.tuner_ops.set_params(fe);
+
+	/* program CFOE coefficients */
+	if (c->bandwidth_hz != state->bandwidth_hz) {
+		for (i = 0; i < ARRAY_SIZE(coeff_lut); i++) {
+			if (coeff_lut[i].clock == state->cfg.clock &&
+				coeff_lut[i].bandwidth_hz == c->bandwidth_hz) {
+				break;
+			}
+		}
+		ret =  af9033_wr_regs(state, 0x800001,
+				coeff_lut[i].val, sizeof(coeff_lut[i].val));
+	}
+
+	/* program frequency control */
+	if (c->bandwidth_hz != state->bandwidth_hz) {
+		spec_inv = state->cfg.spec_inv ? -1 : 1;
+
+		for (i = 0; i < ARRAY_SIZE(clock_adc_lut); i++) {
+			if (clock_adc_lut[i].clock == state->cfg.clock)
+				break;
+		}
+		adc_freq = clock_adc_lut[i].adc;
+
+		/* get used IF frequency */
+		if (fe->ops.tuner_ops.get_if_frequency)
+			fe->ops.tuner_ops.get_if_frequency(fe, &if_frequency);
+		else
+			if_frequency = 0;
+
+		while (if_frequency > (adc_freq / 2))
+			if_frequency -= adc_freq;
+
+		if (if_frequency >= 0)
+			spec_inv *= -1;
+		else
+			if_frequency *= -1;
+
+		freq_cw = af9033_div(state, if_frequency, adc_freq, 23ul);
+
+		if (spec_inv == -1)
+			freq_cw *= -1;
+
+		/* get adc multiplies */
+		ret = af9033_rd_reg(state, 0x800045, &tmp);
+		if (ret < 0)
+			goto err;
+
+		if (tmp == 1)
+			freq_cw /= 2;
+
+		buf[0] = (freq_cw >>  0) & 0xff;
+		buf[1] = (freq_cw >>  8) & 0xff;
+		buf[2] = (freq_cw >> 16) & 0x7f;
+		ret = af9033_wr_regs(state, 0x800029, buf, 3);
+		if (ret < 0)
+			goto err;
+
+		state->bandwidth_hz = c->bandwidth_hz;
+	}
+
+	ret = af9033_wr_reg_mask(state, 0x80f904, bandwidth_reg_val, 0x03);
+	if (ret < 0)
+		goto err;
+
+	ret = af9033_wr_reg(state, 0x800040, 0x00);
+	if (ret < 0)
+		goto err;
+
+	ret = af9033_wr_reg(state, 0x800047, 0x00);
+	if (ret < 0)
+		goto err;
+
+	ret = af9033_wr_reg_mask(state, 0x80f999, 0x00, 0x01);
+	if (ret < 0)
+		goto err;
+
+	if (c->frequency <= 230000000)
+		tmp = 0x00; /* VHF */
+	else
+		tmp = 0x01; /* UHF */
+
+	ret = af9033_wr_reg(state, 0x80004b, tmp);
+	if (ret < 0)
+		goto err;
+
+	ret = af9033_wr_reg(state, 0x800000, 0x00);
+	if (ret < 0)
+		goto err;
+
+	return 0;
+
+err:
+	dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret);
+
+	return ret;
+}
+
+static int af9033_get_frontend(struct dvb_frontend *fe)
+{
+	struct af9033_state *state = fe->demodulator_priv;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	int ret;
+	u8 buf[8];
+
+	dev_dbg(&state->i2c->dev, "%s:\n", __func__);
+
+	/* read all needed registers */
+	ret = af9033_rd_regs(state, 0x80f900, buf, sizeof(buf));
+	if (ret < 0)
+		goto err;
+
+	switch ((buf[0] >> 0) & 3) {
+	case 0:
+		c->transmission_mode = TRANSMISSION_MODE_2K;
+		break;
+	case 1:
+		c->transmission_mode = TRANSMISSION_MODE_8K;
+		break;
+	}
+
+	switch ((buf[1] >> 0) & 3) {
+	case 0:
+		c->guard_interval = GUARD_INTERVAL_1_32;
+		break;
+	case 1:
+		c->guard_interval = GUARD_INTERVAL_1_16;
+		break;
+	case 2:
+		c->guard_interval = GUARD_INTERVAL_1_8;
+		break;
+	case 3:
+		c->guard_interval = GUARD_INTERVAL_1_4;
+		break;
+	}
+
+	switch ((buf[2] >> 0) & 7) {
+	case 0:
+		c->hierarchy = HIERARCHY_NONE;
+		break;
+	case 1:
+		c->hierarchy = HIERARCHY_1;
+		break;
+	case 2:
+		c->hierarchy = HIERARCHY_2;
+		break;
+	case 3:
+		c->hierarchy = HIERARCHY_4;
+		break;
+	}
+
+	switch ((buf[3] >> 0) & 3) {
+	case 0:
+		c->modulation = QPSK;
+		break;
+	case 1:
+		c->modulation = QAM_16;
+		break;
+	case 2:
+		c->modulation = QAM_64;
+		break;
+	}
+
+	switch ((buf[4] >> 0) & 3) {
+	case 0:
+		c->bandwidth_hz = 6000000;
+		break;
+	case 1:
+		c->bandwidth_hz = 7000000;
+		break;
+	case 2:
+		c->bandwidth_hz = 8000000;
+		break;
+	}
+
+	switch ((buf[6] >> 0) & 7) {
+	case 0:
+		c->code_rate_HP = FEC_1_2;
+		break;
+	case 1:
+		c->code_rate_HP = FEC_2_3;
+		break;
+	case 2:
+		c->code_rate_HP = FEC_3_4;
+		break;
+	case 3:
+		c->code_rate_HP = FEC_5_6;
+		break;
+	case 4:
+		c->code_rate_HP = FEC_7_8;
+		break;
+	case 5:
+		c->code_rate_HP = FEC_NONE;
+		break;
+	}
+
+	switch ((buf[7] >> 0) & 7) {
+	case 0:
+		c->code_rate_LP = FEC_1_2;
+		break;
+	case 1:
+		c->code_rate_LP = FEC_2_3;
+		break;
+	case 2:
+		c->code_rate_LP = FEC_3_4;
+		break;
+	case 3:
+		c->code_rate_LP = FEC_5_6;
+		break;
+	case 4:
+		c->code_rate_LP = FEC_7_8;
+		break;
+	case 5:
+		c->code_rate_LP = FEC_NONE;
+		break;
+	}
+
+	return 0;
+
+err:
+	dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret);
+
+	return ret;
+}
+
+static int af9033_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+	struct af9033_state *state = fe->demodulator_priv;
+	int ret;
+	u8 tmp;
+
+	*status = 0;
+
+	/* radio channel status, 0=no result, 1=has signal, 2=no signal */
+	ret = af9033_rd_reg(state, 0x800047, &tmp);
+	if (ret < 0)
+		goto err;
+
+	/* has signal */
+	if (tmp == 0x01)
+		*status |= FE_HAS_SIGNAL;
+
+	if (tmp != 0x02) {
+		/* TPS lock */
+		ret = af9033_rd_reg_mask(state, 0x80f5a9, &tmp, 0x01);
+		if (ret < 0)
+			goto err;
+
+		if (tmp)
+			*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
+					FE_HAS_VITERBI;
+
+		/* full lock */
+		ret = af9033_rd_reg_mask(state, 0x80f999, &tmp, 0x01);
+		if (ret < 0)
+			goto err;
+
+		if (tmp)
+			*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
+					FE_HAS_VITERBI | FE_HAS_SYNC |
+					FE_HAS_LOCK;
+	}
+
+	return 0;
+
+err:
+	dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret);
+
+	return ret;
+}
+
+static int af9033_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+	struct af9033_state *state = fe->demodulator_priv;
+	int ret, i, len;
+	u8 buf[3], tmp;
+	u32 snr_val;
+	const struct val_snr *uninitialized_var(snr_lut);
+
+	/* read value */
+	ret = af9033_rd_regs(state, 0x80002c, buf, 3);
+	if (ret < 0)
+		goto err;
+
+	snr_val = (buf[2] << 16) | (buf[1] << 8) | buf[0];
+
+	/* read current modulation */
+	ret = af9033_rd_reg(state, 0x80f903, &tmp);
+	if (ret < 0)
+		goto err;
+
+	switch ((tmp >> 0) & 3) {
+	case 0:
+		len = ARRAY_SIZE(qpsk_snr_lut);
+		snr_lut = qpsk_snr_lut;
+		break;
+	case 1:
+		len = ARRAY_SIZE(qam16_snr_lut);
+		snr_lut = qam16_snr_lut;
+		break;
+	case 2:
+		len = ARRAY_SIZE(qam64_snr_lut);
+		snr_lut = qam64_snr_lut;
+		break;
+	default:
+		goto err;
+	}
+
+	for (i = 0; i < len; i++) {
+		tmp = snr_lut[i].snr;
+
+		if (snr_val < snr_lut[i].val)
+			break;
+	}
+
+	*snr = tmp * 10; /* dB/10 */
+
+	return 0;
+
+err:
+	dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret);
+
+	return ret;
+}
+
+static int af9033_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
+{
+	struct af9033_state *state = fe->demodulator_priv;
+	int ret;
+	u8 strength2;
+
+	/* read signal strength of 0-100 scale */
+	ret = af9033_rd_reg(state, 0x800048, &strength2);
+	if (ret < 0)
+		goto err;
+
+	/* scale value to 0x0000-0xffff */
+	*strength = strength2 * 0xffff / 100;
+
+	return 0;
+
+err:
+	dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret);
+
+	return ret;
+}
+
+static int af9033_update_ch_stat(struct af9033_state *state)
+{
+	int ret = 0;
+	u32 err_cnt, bit_cnt;
+	u16 abort_cnt;
+	u8 buf[7];
+
+	/* only update data every half second */
+	if (time_after(jiffies, state->last_stat_check + msecs_to_jiffies(500))) {
+		ret = af9033_rd_regs(state, 0x800032, buf, sizeof(buf));
+		if (ret < 0)
+			goto err;
+		/* in 8 byte packets? */
+		abort_cnt = (buf[1] << 8) + buf[0];
+		/* in bits */
+		err_cnt = (buf[4] << 16) + (buf[3] << 8) + buf[2];
+		/* in 8 byte packets? always(?) 0x2710 = 10000 */
+		bit_cnt = (buf[6] << 8) + buf[5];
+
+		if (bit_cnt < abort_cnt) {
+			abort_cnt = 1000;
+			state->ber = 0xffffffff;
+		} else {
+			/* 8 byte packets, that have not been rejected already */
+			bit_cnt -= (u32)abort_cnt;
+			if (bit_cnt == 0) {
+				state->ber = 0xffffffff;
+			} else {
+				err_cnt -= (u32)abort_cnt * 8 * 8;
+				bit_cnt *= 8 * 8;
+				state->ber = err_cnt * (0xffffffff / bit_cnt);
+			}
+		}
+		state->ucb += abort_cnt;
+		state->last_stat_check = jiffies;
+	}
+
+	return 0;
+err:
+	dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret);
+
+	return ret;
+}
+
+static int af9033_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+	struct af9033_state *state = fe->demodulator_priv;
+	int ret;
+
+	ret = af9033_update_ch_stat(state);
+	if (ret < 0)
+		return ret;
+
+	*ber = state->ber;
+
+	return 0;
+}
+
+static int af9033_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+	struct af9033_state *state = fe->demodulator_priv;
+	int ret;
+
+	ret = af9033_update_ch_stat(state);
+	if (ret < 0)
+		return ret;
+
+	*ucblocks = state->ucb;
+
+	return 0;
+}
+
+static int af9033_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+	struct af9033_state *state = fe->demodulator_priv;
+	int ret;
+
+	dev_dbg(&state->i2c->dev, "%s: enable=%d\n", __func__, enable);
+
+	ret = af9033_wr_reg_mask(state, 0x00fa04, enable, 0x01);
+	if (ret < 0)
+		goto err;
+
+	return 0;
+
+err:
+	dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret);
+
+	return ret;
+}
+
+static struct dvb_frontend_ops af9033_ops;
+
+struct dvb_frontend *af9033_attach(const struct af9033_config *config,
+		struct i2c_adapter *i2c)
+{
+	int ret;
+	struct af9033_state *state;
+	u8 buf[8];
+
+	dev_dbg(&i2c->dev, "%s:\n", __func__);
+
+	/* allocate memory for the internal state */
+	state = kzalloc(sizeof(struct af9033_state), GFP_KERNEL);
+	if (state == NULL)
+		goto err;
+
+	/* setup the state */
+	state->i2c = i2c;
+	memcpy(&state->cfg, config, sizeof(struct af9033_config));
+
+	if (state->cfg.clock != 12000000) {
+		dev_err(&state->i2c->dev, "%s: af9033: unsupported clock=%d, " \
+				"only 12000000 Hz is supported currently\n",
+				KBUILD_MODNAME, state->cfg.clock);
+		goto err;
+	}
+
+	/* firmware version */
+	ret = af9033_rd_regs(state, 0x0083e9, &buf[0], 4);
+	if (ret < 0)
+		goto err;
+
+	ret = af9033_rd_regs(state, 0x804191, &buf[4], 4);
+	if (ret < 0)
+		goto err;
+
+	dev_info(&state->i2c->dev, "%s: firmware version: LINK=%d.%d.%d.%d " \
+			"OFDM=%d.%d.%d.%d\n", KBUILD_MODNAME, buf[0], buf[1],
+			buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);
+
+	/* configure internal TS mode */
+	switch (state->cfg.ts_mode) {
+	case AF9033_TS_MODE_PARALLEL:
+		state->ts_mode_parallel = true;
+		break;
+	case AF9033_TS_MODE_SERIAL:
+		state->ts_mode_serial = true;
+		break;
+	case AF9033_TS_MODE_USB:
+		/* usb mode for AF9035 */
+	default:
+		break;
+	}
+
+	/* create dvb_frontend */
+	memcpy(&state->fe.ops, &af9033_ops, sizeof(struct dvb_frontend_ops));
+	state->fe.demodulator_priv = state;
+
+	return &state->fe;
+
+err:
+	kfree(state);
+	return NULL;
+}
+EXPORT_SYMBOL(af9033_attach);
+
+static struct dvb_frontend_ops af9033_ops = {
+	.delsys = { SYS_DVBT },
+	.info = {
+		.name = "Afatech AF9033 (DVB-T)",
+		.frequency_min = 174000000,
+		.frequency_max = 862000000,
+		.frequency_stepsize = 250000,
+		.frequency_tolerance = 0,
+		.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_FEC_AUTO |
+			FE_CAN_QPSK |
+			FE_CAN_QAM_16 |
+			FE_CAN_QAM_64 |
+			FE_CAN_QAM_AUTO |
+			FE_CAN_TRANSMISSION_MODE_AUTO |
+			FE_CAN_GUARD_INTERVAL_AUTO |
+			FE_CAN_HIERARCHY_AUTO |
+			FE_CAN_RECOVER |
+			FE_CAN_MUTE_TS
+	},
+
+	.release = af9033_release,
+
+	.init = af9033_init,
+	.sleep = af9033_sleep,
+
+	.get_tune_settings = af9033_get_tune_settings,
+	.set_frontend = af9033_set_frontend,
+	.get_frontend = af9033_get_frontend,
+
+	.read_status = af9033_read_status,
+	.read_snr = af9033_read_snr,
+	.read_signal_strength = af9033_read_signal_strength,
+	.read_ber = af9033_read_ber,
+	.read_ucblocks = af9033_read_ucblocks,
+
+	.i2c_gate_ctrl = af9033_i2c_gate_ctrl,
+};
+
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
+MODULE_DESCRIPTION("Afatech AF9033 DVB-T demodulator driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb-frontends/af9033.h b/drivers/media/dvb-frontends/af9033.h
new file mode 100644
index 0000000..288622b
--- /dev/null
+++ b/drivers/media/dvb-frontends/af9033.h
@@ -0,0 +1,75 @@
+/*
+ * Afatech AF9033 demodulator driver
+ *
+ * Copyright (C) 2009 Antti Palosaari <crope@iki.fi>
+ * Copyright (C) 2012 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.,
+ *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef AF9033_H
+#define AF9033_H
+
+struct af9033_config {
+	/*
+	 * I2C address
+	 */
+	u8 i2c_addr;
+
+	/*
+	 * clock Hz
+	 * 12000000, 22000000, 24000000, 34000000, 32000000, 28000000, 26000000,
+	 * 30000000, 36000000, 20480000, 16384000
+	 */
+	u32 clock;
+
+	/*
+	 * tuner
+	 */
+#define AF9033_TUNER_TUA9001     0x27 /* Infineon TUA 9001 */
+#define AF9033_TUNER_FC0011      0x28 /* Fitipower FC0011 */
+#define AF9033_TUNER_MXL5007T    0xa0 /* MaxLinear MxL5007T */
+#define AF9033_TUNER_TDA18218    0xa1 /* NXP TDA 18218HN */
+	u8 tuner;
+
+	/*
+	 * TS settings
+	 */
+#define AF9033_TS_MODE_USB       0
+#define AF9033_TS_MODE_PARALLEL  1
+#define AF9033_TS_MODE_SERIAL    2
+	u8 ts_mode:2;
+
+	/*
+	 * input spectrum inversion
+	 */
+	bool spec_inv;
+};
+
+
+#if defined(CONFIG_DVB_AF9033) || \
+	(defined(CONFIG_DVB_AF9033_MODULE) && defined(MODULE))
+extern struct dvb_frontend *af9033_attach(const struct af9033_config *config,
+	struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend *af9033_attach(
+	const struct af9033_config *config, struct i2c_adapter *i2c)
+{
+	pr_warn("%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif
+
+#endif /* AF9033_H */
diff --git a/drivers/media/dvb-frontends/af9033_priv.h b/drivers/media/dvb-frontends/af9033_priv.h
new file mode 100644
index 0000000..0b783b9
--- /dev/null
+++ b/drivers/media/dvb-frontends/af9033_priv.h
@@ -0,0 +1,470 @@
+/*
+ * Afatech AF9033 demodulator driver
+ *
+ * Copyright (C) 2009 Antti Palosaari <crope@iki.fi>
+ * Copyright (C) 2012 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.,
+ *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef AF9033_PRIV_H
+#define AF9033_PRIV_H
+
+#include "dvb_frontend.h"
+#include "af9033.h"
+
+struct reg_val {
+	u32 reg;
+	u8  val;
+};
+
+struct reg_val_mask {
+	u32 reg;
+	u8  val;
+	u8  mask;
+};
+
+struct coeff {
+	u32 clock;
+	u32 bandwidth_hz;
+	u8 val[36];
+};
+
+struct clock_adc {
+	u32 clock;
+	u32 adc;
+};
+
+struct val_snr {
+	u32 val;
+	u8 snr;
+};
+
+/* Xtal clock vs. ADC clock lookup table */
+static const struct clock_adc clock_adc_lut[] = {
+	{ 16384000, 20480000 },
+	{ 20480000, 20480000 },
+	{ 36000000, 20250000 },
+	{ 30000000, 20156250 },
+	{ 26000000, 20583333 },
+	{ 28000000, 20416667 },
+	{ 32000000, 20500000 },
+	{ 34000000, 20187500 },
+	{ 24000000, 20500000 },
+	{ 22000000, 20625000 },
+	{ 12000000, 20250000 },
+};
+
+/* pre-calculated coeff lookup table */
+static const struct coeff coeff_lut[] = {
+	/* 12.000 MHz */
+	{ 12000000, 8000000, {
+		0x01, 0xce, 0x55, 0xc9, 0x00, 0xe7, 0x2a, 0xe4, 0x00, 0x73,
+		0x99, 0x0f, 0x00, 0x73, 0x95, 0x72, 0x00, 0x73, 0x91, 0xd5,
+		0x00, 0x39, 0xca, 0xb9, 0x00, 0xe7, 0x2a, 0xe4, 0x00, 0x73,
+		0x95, 0x72, 0x37, 0x02, 0xce, 0x01 }
+	},
+	{ 12000000, 7000000, {
+		0x01, 0x94, 0x8b, 0x10, 0x00, 0xca, 0x45, 0x88, 0x00, 0x65,
+		0x25, 0xed, 0x00, 0x65, 0x22, 0xc4, 0x00, 0x65, 0x1f, 0x9b,
+		0x00, 0x32, 0x91, 0x62, 0x00, 0xca, 0x45, 0x88, 0x00, 0x65,
+		0x22, 0xc4, 0x88, 0x02, 0x95, 0x01 }
+	},
+	{ 12000000, 6000000, {
+		0x01, 0x5a, 0xc0, 0x56, 0x00, 0xad, 0x60, 0x2b, 0x00, 0x56,
+		0xb2, 0xcb, 0x00, 0x56, 0xb0, 0x15, 0x00, 0x56, 0xad, 0x60,
+		0x00, 0x2b, 0x58, 0x0b, 0x00, 0xad, 0x60, 0x2b, 0x00, 0x56,
+		0xb0, 0x15, 0xf4, 0x02, 0x5b, 0x01 }
+	},
+};
+
+/* QPSK SNR lookup table */
+static const struct val_snr qpsk_snr_lut[] = {
+	{ 0x0b4771,  0 },
+	{ 0x0c1aed,  1 },
+	{ 0x0d0d27,  2 },
+	{ 0x0e4d19,  3 },
+	{ 0x0e5da8,  4 },
+	{ 0x107097,  5 },
+	{ 0x116975,  6 },
+	{ 0x1252d9,  7 },
+	{ 0x131fa4,  8 },
+	{ 0x13d5e1,  9 },
+	{ 0x148e53, 10 },
+	{ 0x15358b, 11 },
+	{ 0x15dd29, 12 },
+	{ 0x168112, 13 },
+	{ 0x170b61, 14 },
+	{ 0x17a532, 15 },
+	{ 0x180f94, 16 },
+	{ 0x186ed2, 17 },
+	{ 0x18b271, 18 },
+	{ 0x18e118, 19 },
+	{ 0x18ff4b, 20 },
+	{ 0x190af1, 21 },
+	{ 0x191451, 22 },
+	{ 0xffffff, 23 },
+};
+
+/* QAM16 SNR lookup table */
+static const struct val_snr qam16_snr_lut[] = {
+	{ 0x04f0d5,  0 },
+	{ 0x05387a,  1 },
+	{ 0x0573a4,  2 },
+	{ 0x05a99e,  3 },
+	{ 0x05cc80,  4 },
+	{ 0x05eb62,  5 },
+	{ 0x05fecf,  6 },
+	{ 0x060b80,  7 },
+	{ 0x062501,  8 },
+	{ 0x064865,  9 },
+	{ 0x069604, 10 },
+	{ 0x06f356, 11 },
+	{ 0x07706a, 12 },
+	{ 0x0804d3, 13 },
+	{ 0x089d1a, 14 },
+	{ 0x093e3d, 15 },
+	{ 0x09e35d, 16 },
+	{ 0x0a7c3c, 17 },
+	{ 0x0afaf8, 18 },
+	{ 0x0b719d, 19 },
+	{ 0x0bda6a, 20 },
+	{ 0x0c0c75, 21 },
+	{ 0x0c3f7d, 22 },
+	{ 0x0c5e62, 23 },
+	{ 0x0c6c31, 24 },
+	{ 0x0c7925, 25 },
+	{ 0xffffff, 26 },
+};
+
+/* QAM64 SNR lookup table */
+static const struct val_snr qam64_snr_lut[] = {
+	{ 0x0256d0,  0 },
+	{ 0x027a65,  1 },
+	{ 0x029873,  2 },
+	{ 0x02b7fe,  3 },
+	{ 0x02cf1e,  4 },
+	{ 0x02e234,  5 },
+	{ 0x02f409,  6 },
+	{ 0x030046,  7 },
+	{ 0x030844,  8 },
+	{ 0x030a02,  9 },
+	{ 0x030cde, 10 },
+	{ 0x031031, 11 },
+	{ 0x03144c, 12 },
+	{ 0x0315dd, 13 },
+	{ 0x031920, 14 },
+	{ 0x0322d0, 15 },
+	{ 0x0339fc, 16 },
+	{ 0x0364a1, 17 },
+	{ 0x038bcc, 18 },
+	{ 0x03c7d3, 19 },
+	{ 0x0408cc, 20 },
+	{ 0x043bed, 21 },
+	{ 0x048061, 22 },
+	{ 0x04be95, 23 },
+	{ 0x04fa7d, 24 },
+	{ 0x052405, 25 },
+	{ 0x05570d, 26 },
+	{ 0x059feb, 27 },
+	{ 0x05bf38, 28 },
+	{ 0xffffff, 29 },
+};
+
+static const struct reg_val ofsm_init[] = {
+	{ 0x800051, 0x01 },
+	{ 0x800070, 0x0a },
+	{ 0x80007e, 0x04 },
+	{ 0x800081, 0x0a },
+	{ 0x80008a, 0x01 },
+	{ 0x80008e, 0x01 },
+	{ 0x800092, 0x06 },
+	{ 0x800099, 0x01 },
+	{ 0x80009f, 0xe1 },
+	{ 0x8000a0, 0xcf },
+	{ 0x8000a3, 0x01 },
+	{ 0x8000a5, 0x01 },
+	{ 0x8000a6, 0x01 },
+	{ 0x8000a9, 0x00 },
+	{ 0x8000aa, 0x01 },
+	{ 0x8000ab, 0x01 },
+	{ 0x8000b0, 0x01 },
+	{ 0x8000c0, 0x05 },
+	{ 0x8000c4, 0x19 },
+	{ 0x80f000, 0x0f },
+	{ 0x80f016, 0x10 },
+	{ 0x80f017, 0x04 },
+	{ 0x80f018, 0x05 },
+	{ 0x80f019, 0x04 },
+	{ 0x80f01a, 0x05 },
+	{ 0x80f021, 0x03 },
+	{ 0x80f022, 0x0a },
+	{ 0x80f023, 0x0a },
+	{ 0x80f02b, 0x00 },
+	{ 0x80f02c, 0x01 },
+	{ 0x80f064, 0x03 },
+	{ 0x80f065, 0xf9 },
+	{ 0x80f066, 0x03 },
+	{ 0x80f067, 0x01 },
+	{ 0x80f06f, 0xe0 },
+	{ 0x80f070, 0x03 },
+	{ 0x80f072, 0x0f },
+	{ 0x80f073, 0x03 },
+	{ 0x80f078, 0x00 },
+	{ 0x80f087, 0x00 },
+	{ 0x80f09b, 0x3f },
+	{ 0x80f09c, 0x00 },
+	{ 0x80f09d, 0x20 },
+	{ 0x80f09e, 0x00 },
+	{ 0x80f09f, 0x0c },
+	{ 0x80f0a0, 0x00 },
+	{ 0x80f130, 0x04 },
+	{ 0x80f132, 0x04 },
+	{ 0x80f144, 0x1a },
+	{ 0x80f146, 0x00 },
+	{ 0x80f14a, 0x01 },
+	{ 0x80f14c, 0x00 },
+	{ 0x80f14d, 0x00 },
+	{ 0x80f14f, 0x04 },
+	{ 0x80f158, 0x7f },
+	{ 0x80f15a, 0x00 },
+	{ 0x80f15b, 0x08 },
+	{ 0x80f15d, 0x03 },
+	{ 0x80f15e, 0x05 },
+	{ 0x80f163, 0x05 },
+	{ 0x80f166, 0x01 },
+	{ 0x80f167, 0x40 },
+	{ 0x80f168, 0x0f },
+	{ 0x80f17a, 0x00 },
+	{ 0x80f17b, 0x00 },
+	{ 0x80f183, 0x01 },
+	{ 0x80f19d, 0x40 },
+	{ 0x80f1bc, 0x36 },
+	{ 0x80f1bd, 0x00 },
+	{ 0x80f1cb, 0xa0 },
+	{ 0x80f1cc, 0x01 },
+	{ 0x80f204, 0x10 },
+	{ 0x80f214, 0x00 },
+	{ 0x80f40e, 0x0a },
+	{ 0x80f40f, 0x40 },
+	{ 0x80f410, 0x08 },
+	{ 0x80f55f, 0x0a },
+	{ 0x80f561, 0x15 },
+	{ 0x80f562, 0x20 },
+	{ 0x80f5df, 0xfb },
+	{ 0x80f5e0, 0x00 },
+	{ 0x80f5e3, 0x09 },
+	{ 0x80f5e4, 0x01 },
+	{ 0x80f5e5, 0x01 },
+	{ 0x80f5f8, 0x01 },
+	{ 0x80f5fd, 0x01 },
+	{ 0x80f600, 0x05 },
+	{ 0x80f601, 0x08 },
+	{ 0x80f602, 0x0b },
+	{ 0x80f603, 0x0e },
+	{ 0x80f604, 0x11 },
+	{ 0x80f605, 0x14 },
+	{ 0x80f606, 0x17 },
+	{ 0x80f607, 0x1f },
+	{ 0x80f60e, 0x00 },
+	{ 0x80f60f, 0x04 },
+	{ 0x80f610, 0x32 },
+	{ 0x80f611, 0x10 },
+	{ 0x80f707, 0xfc },
+	{ 0x80f708, 0x00 },
+	{ 0x80f709, 0x37 },
+	{ 0x80f70a, 0x00 },
+	{ 0x80f78b, 0x01 },
+	{ 0x80f80f, 0x40 },
+	{ 0x80f810, 0x54 },
+	{ 0x80f811, 0x5a },
+	{ 0x80f905, 0x01 },
+	{ 0x80fb06, 0x03 },
+	{ 0x80fd8b, 0x00 },
+};
+
+/* Infineon TUA 9001 tuner init
+   AF9033_TUNER_TUA9001    = 0x27 */
+static const struct reg_val tuner_init_tua9001[] = {
+	{ 0x800046, 0x27 },
+	{ 0x800057, 0x00 },
+	{ 0x800058, 0x01 },
+	{ 0x80005f, 0x00 },
+	{ 0x800060, 0x00 },
+	{ 0x80006d, 0x00 },
+	{ 0x800071, 0x05 },
+	{ 0x800072, 0x02 },
+	{ 0x800074, 0x01 },
+	{ 0x800075, 0x03 },
+	{ 0x800076, 0x02 },
+	{ 0x800077, 0x00 },
+	{ 0x800078, 0x01 },
+	{ 0x800079, 0x00 },
+	{ 0x80007a, 0x7e },
+	{ 0x80007b, 0x3e },
+	{ 0x800093, 0x00 },
+	{ 0x800094, 0x01 },
+	{ 0x800095, 0x02 },
+	{ 0x800096, 0x01 },
+	{ 0x800098, 0x0a },
+	{ 0x80009b, 0x05 },
+	{ 0x80009c, 0x80 },
+	{ 0x8000b3, 0x00 },
+	{ 0x8000c1, 0x01 },
+	{ 0x8000c2, 0x00 },
+	{ 0x80f007, 0x00 },
+	{ 0x80f01f, 0x82 },
+	{ 0x80f020, 0x00 },
+	{ 0x80f029, 0x82 },
+	{ 0x80f02a, 0x00 },
+	{ 0x80f047, 0x00 },
+	{ 0x80f054, 0x00 },
+	{ 0x80f055, 0x00 },
+	{ 0x80f077, 0x01 },
+	{ 0x80f1e6, 0x00 },
+};
+
+/* Fitipower fc0011 tuner init
+   AF9033_TUNER_FC0011    = 0x28 */
+static const struct reg_val tuner_init_fc0011[] = {
+	{ 0x800046, AF9033_TUNER_FC0011 },
+	{ 0x800057, 0x00 },
+	{ 0x800058, 0x01 },
+	{ 0x80005f, 0x00 },
+	{ 0x800060, 0x00 },
+	{ 0x800068, 0xa5 },
+	{ 0x80006e, 0x01 },
+	{ 0x800071, 0x0A },
+	{ 0x800072, 0x02 },
+	{ 0x800074, 0x01 },
+	{ 0x800079, 0x01 },
+	{ 0x800093, 0x00 },
+	{ 0x800094, 0x00 },
+	{ 0x800095, 0x00 },
+	{ 0x800096, 0x00 },
+	{ 0x80009b, 0x2D },
+	{ 0x80009c, 0x60 },
+	{ 0x80009d, 0x23 },
+	{ 0x8000a4, 0x50 },
+	{ 0x8000ad, 0x50 },
+	{ 0x8000b3, 0x01 },
+	{ 0x8000b7, 0x88 },
+	{ 0x8000b8, 0xa6 },
+	{ 0x8000c3, 0x01 },
+	{ 0x8000c4, 0x01 },
+	{ 0x8000c7, 0x69 },
+	{ 0x80F007, 0x00 },
+	{ 0x80F00A, 0x1B },
+	{ 0x80F00B, 0x1B },
+	{ 0x80F00C, 0x1B },
+	{ 0x80F00D, 0x1B },
+	{ 0x80F00E, 0xFF },
+	{ 0x80F00F, 0x01 },
+	{ 0x80F010, 0x00 },
+	{ 0x80F011, 0x02 },
+	{ 0x80F012, 0xFF },
+	{ 0x80F013, 0x01 },
+	{ 0x80F014, 0x00 },
+	{ 0x80F015, 0x02 },
+	{ 0x80F01B, 0xEF },
+	{ 0x80F01C, 0x01 },
+	{ 0x80F01D, 0x0f },
+	{ 0x80F01E, 0x02 },
+	{ 0x80F01F, 0x6E },
+	{ 0x80F020, 0x00 },
+	{ 0x80F025, 0xDE },
+	{ 0x80F026, 0x00 },
+	{ 0x80F027, 0x0A },
+	{ 0x80F028, 0x03 },
+	{ 0x80F029, 0x6E },
+	{ 0x80F02A, 0x00 },
+	{ 0x80F047, 0x00 },
+	{ 0x80F054, 0x00 },
+	{ 0x80F055, 0x00 },
+	{ 0x80F077, 0x01 },
+	{ 0x80F1E6, 0x00 },
+};
+
+/* MaxLinear MxL5007T tuner init
+   AF9033_TUNER_MXL5007T    = 0xa0 */
+static const struct reg_val tuner_init_mxl5007t[] = {
+	{ 0x800046, 0x1b },
+	{ 0x800057, 0x01 },
+	{ 0x800058, 0x01 },
+	{ 0x80005f, 0x00 },
+	{ 0x800060, 0x00 },
+	{ 0x800068, 0x96 },
+	{ 0x800071, 0x05 },
+	{ 0x800072, 0x02 },
+	{ 0x800074, 0x01 },
+	{ 0x800079, 0x01 },
+	{ 0x800093, 0x00 },
+	{ 0x800094, 0x00 },
+	{ 0x800095, 0x00 },
+	{ 0x800096, 0x00 },
+	{ 0x8000b3, 0x01 },
+	{ 0x8000c1, 0x01 },
+	{ 0x8000c2, 0x00 },
+	{ 0x80f007, 0x00 },
+	{ 0x80f00c, 0x19 },
+	{ 0x80f00d, 0x1a },
+	{ 0x80f012, 0xda },
+	{ 0x80f013, 0x00 },
+	{ 0x80f014, 0x00 },
+	{ 0x80f015, 0x02 },
+	{ 0x80f01f, 0x82 },
+	{ 0x80f020, 0x00 },
+	{ 0x80f029, 0x82 },
+	{ 0x80f02a, 0x00 },
+	{ 0x80f077, 0x02 },
+	{ 0x80f1e6, 0x00 },
+};
+
+/* NXP TDA 18218HN tuner init
+   AF9033_TUNER_TDA18218    = 0xa1 */
+static const struct reg_val tuner_init_tda18218[] = {
+	{0x800046, 0xa1},
+	{0x800057, 0x01},
+	{0x800058, 0x01},
+	{0x80005f, 0x00},
+	{0x800060, 0x00},
+	{0x800071, 0x05},
+	{0x800072, 0x02},
+	{0x800074, 0x01},
+	{0x800079, 0x01},
+	{0x800093, 0x00},
+	{0x800094, 0x00},
+	{0x800095, 0x00},
+	{0x800096, 0x00},
+	{0x8000b3, 0x01},
+	{0x8000c3, 0x01},
+	{0x8000c4, 0x00},
+	{0x80f007, 0x00},
+	{0x80f00c, 0x19},
+	{0x80f00d, 0x1a},
+	{0x80f012, 0xda},
+	{0x80f013, 0x00},
+	{0x80f014, 0x00},
+	{0x80f015, 0x02},
+	{0x80f01f, 0x82},
+	{0x80f020, 0x00},
+	{0x80f029, 0x82},
+	{0x80f02a, 0x00},
+	{0x80f077, 0x02},
+	{0x80f1e6, 0x00},
+};
+
+#endif /* AF9033_PRIV_H */
+
diff --git a/drivers/media/dvb-frontends/atbm8830.c b/drivers/media/dvb-frontends/atbm8830.c
new file mode 100644
index 0000000..4e11dc4
--- /dev/null
+++ b/drivers/media/dvb-frontends/atbm8830.c
@@ -0,0 +1,508 @@
+/*
+ *    Support for AltoBeam GB20600 (a.k.a DMB-TH) demodulator
+ *    ATBM8830, ATBM8831
+ *
+ *    Copyright (C) 2009 David T.L. Wong <davidtlwong@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <asm/div64.h>
+#include "dvb_frontend.h"
+
+#include "atbm8830.h"
+#include "atbm8830_priv.h"
+
+#define dprintk(args...) \
+	do { \
+		if (debug) \
+			printk(KERN_DEBUG "atbm8830: " args); \
+	} while (0)
+
+static int debug;
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+
+static int atbm8830_write_reg(struct atbm_state *priv, u16 reg, u8 data)
+{
+	int ret = 0;
+	u8 dev_addr;
+	u8 buf1[] = { reg >> 8, reg & 0xFF };
+	u8 buf2[] = { data };
+	struct i2c_msg msg1 = { .flags = 0, .buf = buf1, .len = 2 };
+	struct i2c_msg msg2 = { .flags = 0, .buf = buf2, .len = 1 };
+
+	dev_addr = priv->config->demod_address;
+	msg1.addr = dev_addr;
+	msg2.addr = dev_addr;
+
+	if (debug >= 2)
+		dprintk("%s: reg=0x%04X, data=0x%02X\n", __func__, reg, data);
+
+	ret = i2c_transfer(priv->i2c, &msg1, 1);
+	if (ret != 1)
+		return -EIO;
+
+	ret = i2c_transfer(priv->i2c, &msg2, 1);
+	return (ret != 1) ? -EIO : 0;
+}
+
+static int atbm8830_read_reg(struct atbm_state *priv, u16 reg, u8 *p_data)
+{
+	int ret;
+	u8 dev_addr;
+
+	u8 buf1[] = { reg >> 8, reg & 0xFF };
+	u8 buf2[] = { 0 };
+	struct i2c_msg msg1 = { .flags = 0, .buf = buf1, .len = 2 };
+	struct i2c_msg msg2 = { .flags = I2C_M_RD, .buf = buf2, .len = 1 };
+
+	dev_addr = priv->config->demod_address;
+	msg1.addr = dev_addr;
+	msg2.addr = dev_addr;
+
+	ret = i2c_transfer(priv->i2c, &msg1, 1);
+	if (ret != 1) {
+		dprintk("%s: error reg=0x%04x, ret=%i\n", __func__, reg, ret);
+		return -EIO;
+	}
+
+	ret = i2c_transfer(priv->i2c, &msg2, 1);
+	if (ret != 1)
+		return -EIO;
+
+	*p_data = buf2[0];
+	if (debug >= 2)
+		dprintk("%s: reg=0x%04X, data=0x%02X\n",
+			__func__, reg, buf2[0]);
+
+	return 0;
+}
+
+/* Lock register latch so that multi-register read is atomic */
+static inline int atbm8830_reglatch_lock(struct atbm_state *priv, int lock)
+{
+	return atbm8830_write_reg(priv, REG_READ_LATCH, lock ? 1 : 0);
+}
+
+static int set_osc_freq(struct atbm_state *priv, u32 freq /*in kHz*/)
+{
+	u32 val;
+	u64 t;
+
+	/* 0x100000 * freq / 30.4MHz */
+	t = (u64)0x100000 * freq;
+	do_div(t, 30400);
+	val = t;
+
+	atbm8830_write_reg(priv, REG_OSC_CLK, val);
+	atbm8830_write_reg(priv, REG_OSC_CLK + 1, val >> 8);
+	atbm8830_write_reg(priv, REG_OSC_CLK + 2, val >> 16);
+
+	return 0;
+}
+
+static int set_if_freq(struct atbm_state *priv, u32 freq /*in kHz*/)
+{
+
+	u32 fs = priv->config->osc_clk_freq;
+	u64 t;
+	u32 val;
+	u8 dat;
+
+	if (freq != 0) {
+		/* 2 * PI * (freq - fs) / fs * (2 ^ 22) */
+		t = (u64) 2 * 31416 * (freq - fs);
+		t <<= 22;
+		do_div(t, fs);
+		do_div(t, 1000);
+		val = t;
+
+		atbm8830_write_reg(priv, REG_TUNER_BASEBAND, 1);
+		atbm8830_write_reg(priv, REG_IF_FREQ, val);
+		atbm8830_write_reg(priv, REG_IF_FREQ+1, val >> 8);
+		atbm8830_write_reg(priv, REG_IF_FREQ+2, val >> 16);
+
+		atbm8830_read_reg(priv, REG_ADC_CONFIG, &dat);
+		dat &= 0xFC;
+		atbm8830_write_reg(priv, REG_ADC_CONFIG, dat);
+	} else {
+		/* Zero IF */
+		atbm8830_write_reg(priv, REG_TUNER_BASEBAND, 0);
+
+		atbm8830_read_reg(priv, REG_ADC_CONFIG, &dat);
+		dat &= 0xFC;
+		dat |= 0x02;
+		atbm8830_write_reg(priv, REG_ADC_CONFIG, dat);
+
+		if (priv->config->zif_swap_iq)
+			atbm8830_write_reg(priv, REG_SWAP_I_Q, 0x03);
+		else
+			atbm8830_write_reg(priv, REG_SWAP_I_Q, 0x01);
+	}
+
+	return 0;
+}
+
+static int is_locked(struct atbm_state *priv, u8 *locked)
+{
+	u8 status;
+
+	atbm8830_read_reg(priv, REG_LOCK_STATUS, &status);
+
+	if (locked != NULL)
+		*locked = (status == 1);
+	return 0;
+}
+
+static int set_agc_config(struct atbm_state *priv,
+	u8 min, u8 max, u8 hold_loop)
+{
+	/* no effect if both min and max are zero */
+	if (!min && !max)
+	    return 0;
+
+	atbm8830_write_reg(priv, REG_AGC_MIN, min);
+	atbm8830_write_reg(priv, REG_AGC_MAX, max);
+	atbm8830_write_reg(priv, REG_AGC_HOLD_LOOP, hold_loop);
+
+	return 0;
+}
+
+static int set_static_channel_mode(struct atbm_state *priv)
+{
+	int i;
+
+	for (i = 0; i < 5; i++)
+		atbm8830_write_reg(priv, 0x099B + i, 0x08);
+
+	atbm8830_write_reg(priv, 0x095B, 0x7F);
+	atbm8830_write_reg(priv, 0x09CB, 0x01);
+	atbm8830_write_reg(priv, 0x09CC, 0x7F);
+	atbm8830_write_reg(priv, 0x09CD, 0x7F);
+	atbm8830_write_reg(priv, 0x0E01, 0x20);
+
+	/* For single carrier */
+	atbm8830_write_reg(priv, 0x0B03, 0x0A);
+	atbm8830_write_reg(priv, 0x0935, 0x10);
+	atbm8830_write_reg(priv, 0x0936, 0x08);
+	atbm8830_write_reg(priv, 0x093E, 0x08);
+	atbm8830_write_reg(priv, 0x096E, 0x06);
+
+	/* frame_count_max0 */
+	atbm8830_write_reg(priv, 0x0B09, 0x00);
+	/* frame_count_max1 */
+	atbm8830_write_reg(priv, 0x0B0A, 0x08);
+
+	return 0;
+}
+
+static int set_ts_config(struct atbm_state *priv)
+{
+	const struct atbm8830_config *cfg = priv->config;
+
+	/*Set parallel/serial ts mode*/
+	atbm8830_write_reg(priv, REG_TS_SERIAL, cfg->serial_ts ? 1 : 0);
+	atbm8830_write_reg(priv, REG_TS_CLK_MODE, cfg->serial_ts ? 1 : 0);
+	/*Set ts sampling edge*/
+	atbm8830_write_reg(priv, REG_TS_SAMPLE_EDGE,
+		cfg->ts_sampling_edge ? 1 : 0);
+	/*Set ts clock freerun*/
+	atbm8830_write_reg(priv, REG_TS_CLK_FREERUN,
+		cfg->ts_clk_gated ? 0 : 1);
+
+	return 0;
+}
+
+static int atbm8830_init(struct dvb_frontend *fe)
+{
+	struct atbm_state *priv = fe->demodulator_priv;
+	const struct atbm8830_config *cfg = priv->config;
+
+	/*Set oscillator frequency*/
+	set_osc_freq(priv, cfg->osc_clk_freq);
+
+	/*Set IF frequency*/
+	set_if_freq(priv, cfg->if_freq);
+
+	/*Set AGC Config*/
+	set_agc_config(priv, cfg->agc_min, cfg->agc_max,
+		cfg->agc_hold_loop);
+
+	/*Set static channel mode*/
+	set_static_channel_mode(priv);
+
+	set_ts_config(priv);
+	/*Turn off DSP reset*/
+	atbm8830_write_reg(priv, 0x000A, 0);
+
+	/*SW version test*/
+	atbm8830_write_reg(priv, 0x020C, 11);
+
+	/* Run */
+	atbm8830_write_reg(priv, REG_DEMOD_RUN, 1);
+
+	return 0;
+}
+
+
+static void atbm8830_release(struct dvb_frontend *fe)
+{
+	struct atbm_state *state = fe->demodulator_priv;
+	dprintk("%s\n", __func__);
+
+	kfree(state);
+}
+
+static int atbm8830_set_fe(struct dvb_frontend *fe)
+{
+	struct atbm_state *priv = fe->demodulator_priv;
+	int i;
+	u8 locked = 0;
+	dprintk("%s\n", __func__);
+
+	/* set frequency */
+	if (fe->ops.tuner_ops.set_params) {
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 1);
+		fe->ops.tuner_ops.set_params(fe);
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 0);
+	}
+
+	/* start auto lock */
+	for (i = 0; i < 10; i++) {
+		mdelay(100);
+		dprintk("Try %d\n", i);
+		is_locked(priv, &locked);
+		if (locked != 0) {
+			dprintk("ATBM8830 locked!\n");
+			break;
+		}
+	}
+
+	return 0;
+}
+
+static int atbm8830_get_fe(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	dprintk("%s\n", __func__);
+
+	/* TODO: get real readings from device */
+	/* inversion status */
+	c->inversion = INVERSION_OFF;
+
+	/* bandwidth */
+	c->bandwidth_hz = 8000000;
+
+	c->code_rate_HP = FEC_AUTO;
+	c->code_rate_LP = FEC_AUTO;
+
+	c->modulation = QAM_AUTO;
+
+	/* transmission mode */
+	c->transmission_mode = TRANSMISSION_MODE_AUTO;
+
+	/* guard interval */
+	c->guard_interval = GUARD_INTERVAL_AUTO;
+
+	/* hierarchy */
+	c->hierarchy = HIERARCHY_NONE;
+
+	return 0;
+}
+
+static int atbm8830_get_tune_settings(struct dvb_frontend *fe,
+	struct dvb_frontend_tune_settings *fesettings)
+{
+	fesettings->min_delay_ms = 0;
+	fesettings->step_size = 0;
+	fesettings->max_drift = 0;
+	return 0;
+}
+
+static int atbm8830_read_status(struct dvb_frontend *fe, fe_status_t *fe_status)
+{
+	struct atbm_state *priv = fe->demodulator_priv;
+	u8 locked = 0;
+	u8 agc_locked = 0;
+
+	dprintk("%s\n", __func__);
+	*fe_status = 0;
+
+	is_locked(priv, &locked);
+	if (locked) {
+		*fe_status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
+			FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
+	}
+	dprintk("%s: fe_status=0x%x\n", __func__, *fe_status);
+
+	atbm8830_read_reg(priv, REG_AGC_LOCK, &agc_locked);
+	dprintk("AGC Lock: %d\n", agc_locked);
+
+	return 0;
+}
+
+static int atbm8830_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+	struct atbm_state *priv = fe->demodulator_priv;
+	u32 frame_err;
+	u8 t;
+
+	dprintk("%s\n", __func__);
+
+	atbm8830_reglatch_lock(priv, 1);
+
+	atbm8830_read_reg(priv, REG_FRAME_ERR_CNT + 1, &t);
+	frame_err = t & 0x7F;
+	frame_err <<= 8;
+	atbm8830_read_reg(priv, REG_FRAME_ERR_CNT, &t);
+	frame_err |= t;
+
+	atbm8830_reglatch_lock(priv, 0);
+
+	*ber = frame_err * 100 / 32767;
+
+	dprintk("%s: ber=0x%x\n", __func__, *ber);
+	return 0;
+}
+
+static int atbm8830_read_signal_strength(struct dvb_frontend *fe, u16 *signal)
+{
+	struct atbm_state *priv = fe->demodulator_priv;
+	u32 pwm;
+	u8 t;
+
+	dprintk("%s\n", __func__);
+	atbm8830_reglatch_lock(priv, 1);
+
+	atbm8830_read_reg(priv, REG_AGC_PWM_VAL + 1, &t);
+	pwm = t & 0x03;
+	pwm <<= 8;
+	atbm8830_read_reg(priv, REG_AGC_PWM_VAL, &t);
+	pwm |= t;
+
+	atbm8830_reglatch_lock(priv, 0);
+
+	dprintk("AGC PWM = 0x%02X\n", pwm);
+	pwm = 0x400 - pwm;
+
+	*signal = pwm * 0x10000 / 0x400;
+
+	return 0;
+}
+
+static int atbm8830_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+	dprintk("%s\n", __func__);
+	*snr = 0;
+	return 0;
+}
+
+static int atbm8830_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+	dprintk("%s\n", __func__);
+	*ucblocks = 0;
+	return 0;
+}
+
+static int atbm8830_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+	struct atbm_state *priv = fe->demodulator_priv;
+
+	return atbm8830_write_reg(priv, REG_I2C_GATE, enable ? 1 : 0);
+}
+
+static struct dvb_frontend_ops atbm8830_ops = {
+	.delsys = { SYS_DTMB },
+	.info = {
+		.name = "AltoBeam ATBM8830/8831 DMB-TH",
+		.frequency_min = 474000000,
+		.frequency_max = 858000000,
+		.frequency_stepsize = 10000,
+		.caps =
+			FE_CAN_FEC_AUTO |
+			FE_CAN_QAM_AUTO |
+			FE_CAN_TRANSMISSION_MODE_AUTO |
+			FE_CAN_GUARD_INTERVAL_AUTO
+	},
+
+	.release = atbm8830_release,
+
+	.init = atbm8830_init,
+	.sleep = NULL,
+	.write = NULL,
+	.i2c_gate_ctrl = atbm8830_i2c_gate_ctrl,
+
+	.set_frontend = atbm8830_set_fe,
+	.get_frontend = atbm8830_get_fe,
+	.get_tune_settings = atbm8830_get_tune_settings,
+
+	.read_status = atbm8830_read_status,
+	.read_ber = atbm8830_read_ber,
+	.read_signal_strength = atbm8830_read_signal_strength,
+	.read_snr = atbm8830_read_snr,
+	.read_ucblocks = atbm8830_read_ucblocks,
+};
+
+struct dvb_frontend *atbm8830_attach(const struct atbm8830_config *config,
+	struct i2c_adapter *i2c)
+{
+	struct atbm_state *priv = NULL;
+	u8 data = 0;
+
+	dprintk("%s()\n", __func__);
+
+	if (config == NULL || i2c == NULL)
+		return NULL;
+
+	priv = kzalloc(sizeof(struct atbm_state), GFP_KERNEL);
+	if (priv == NULL)
+		goto error_out;
+
+	priv->config = config;
+	priv->i2c = i2c;
+
+	/* check if the demod is there */
+	if (atbm8830_read_reg(priv, REG_CHIP_ID, &data) != 0) {
+		dprintk("%s atbm8830/8831 not found at i2c addr 0x%02X\n",
+			__func__, priv->config->demod_address);
+		goto error_out;
+	}
+	dprintk("atbm8830 chip id: 0x%02X\n", data);
+
+	memcpy(&priv->frontend.ops, &atbm8830_ops,
+	       sizeof(struct dvb_frontend_ops));
+	priv->frontend.demodulator_priv = priv;
+
+	atbm8830_init(&priv->frontend);
+
+	atbm8830_i2c_gate_ctrl(&priv->frontend, 1);
+
+	return &priv->frontend;
+
+error_out:
+	dprintk("%s() error_out\n", __func__);
+	kfree(priv);
+	return NULL;
+
+}
+EXPORT_SYMBOL(atbm8830_attach);
+
+MODULE_DESCRIPTION("AltoBeam ATBM8830/8831 GB20600 demodulator driver");
+MODULE_AUTHOR("David T. L. Wong <davidtlwong@gmail.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb-frontends/atbm8830.h b/drivers/media/dvb-frontends/atbm8830.h
new file mode 100644
index 0000000..0242733
--- /dev/null
+++ b/drivers/media/dvb-frontends/atbm8830.h
@@ -0,0 +1,76 @@
+/*
+ *    Support for AltoBeam GB20600 (a.k.a DMB-TH) demodulator
+ *    ATBM8830, ATBM8831
+ *
+ *    Copyright (C) 2009 David T.L. Wong <davidtlwong@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __ATBM8830_H__
+#define __ATBM8830_H__
+
+#include <linux/dvb/frontend.h>
+#include <linux/i2c.h>
+
+#define ATBM8830_PROD_8830 0
+#define ATBM8830_PROD_8831 1
+
+struct atbm8830_config {
+
+	/* product type */
+	u8 prod;
+
+	/* the demodulator's i2c address */
+	u8 demod_address;
+
+	/* parallel or serial transport stream */
+	u8 serial_ts;
+
+	/* transport stream clock output only when receiving valid stream */
+	u8 ts_clk_gated;
+
+	/* Decoder sample TS data at rising edge of clock */
+	u8 ts_sampling_edge;
+
+	/* Oscillator clock frequency */
+	u32 osc_clk_freq; /* in kHz */
+
+	/* IF frequency */
+	u32 if_freq; /* in kHz */
+
+	/* Swap I/Q for zero IF */
+	u8 zif_swap_iq;
+
+	/* Tuner AGC settings */
+	u8 agc_min;
+	u8 agc_max;
+	u8 agc_hold_loop;
+};
+
+#if defined(CONFIG_DVB_ATBM8830) || \
+	(defined(CONFIG_DVB_ATBM8830_MODULE) && defined(MODULE))
+extern struct dvb_frontend *atbm8830_attach(const struct atbm8830_config *config,
+		struct i2c_adapter *i2c);
+#else
+static inline
+struct dvb_frontend *atbm8830_attach(const struct atbm8830_config *config,
+		struct i2c_adapter *i2c) {
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif /* CONFIG_DVB_ATBM8830 */
+
+#endif /* __ATBM8830_H__ */
diff --git a/drivers/media/dvb-frontends/atbm8830_priv.h b/drivers/media/dvb-frontends/atbm8830_priv.h
new file mode 100644
index 0000000..d460058
--- /dev/null
+++ b/drivers/media/dvb-frontends/atbm8830_priv.h
@@ -0,0 +1,75 @@
+/*
+ *    Support for AltoBeam GB20600 (a.k.a DMB-TH) demodulator
+ *    ATBM8830, ATBM8831
+ *
+ *    Copyright (C) 2009 David T.L. Wong <davidtlwong@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __ATBM8830_PRIV_H
+#define __ATBM8830_PRIV_H
+
+struct atbm_state {
+	struct i2c_adapter *i2c;
+	/* configuration settings */
+	const struct atbm8830_config *config;
+	struct dvb_frontend frontend;
+};
+
+#define REG_CHIP_ID	0x0000
+#define REG_TUNER_BASEBAND	0x0001
+#define REG_DEMOD_RUN	0x0004
+#define REG_DSP_RESET	0x0005
+#define REG_RAM_RESET	0x0006
+#define REG_ADC_RESET	0x0007
+#define REG_TSPORT_RESET	0x0008
+#define REG_BLKERR_POL	0x000C
+#define REG_I2C_GATE	0x0103
+#define REG_TS_SAMPLE_EDGE	0x0301
+#define REG_TS_PKT_LEN_204	0x0302
+#define REG_TS_PKT_LEN_AUTO	0x0303
+#define REG_TS_SERIAL	0x0305
+#define REG_TS_CLK_FREERUN	0x0306
+#define REG_TS_VALID_MODE	0x0307
+#define REG_TS_CLK_MODE	0x030B /* 1 for serial, 0 for parallel */
+
+#define REG_TS_ERRBIT_USE	0x030C
+#define REG_LOCK_STATUS	0x030D
+#define REG_ADC_CONFIG	0x0602
+#define REG_CARRIER_OFFSET	0x0827 /* 0x0827-0x0829 little endian */
+#define REG_DETECTED_PN_MODE	0x082D
+#define REG_READ_LATCH	0x084D
+#define REG_IF_FREQ	0x0A00 /* 0x0A00-0x0A02 little endian */
+#define REG_OSC_CLK	0x0A03 /* 0x0A03-0x0A05 little endian */
+#define REG_BYPASS_CCI	0x0A06
+#define REG_ANALOG_LUMA_DETECTED	0x0A25
+#define REG_ANALOG_AUDIO_DETECTED	0x0A26
+#define REG_ANALOG_CHROMA_DETECTED	0x0A39
+#define REG_FRAME_ERR_CNT	0x0B04
+#define REG_USE_EXT_ADC	0x0C00
+#define REG_SWAP_I_Q	0x0C01
+#define REG_TPS_MANUAL	0x0D01
+#define REG_TPS_CONFIG	0x0D02
+#define REG_BYPASS_DEINTERLEAVER	0x0E00
+#define REG_AGC_TARGET	0x1003 /* 0x1003-0x1005 little endian */
+#define REG_AGC_MIN	0x1020
+#define REG_AGC_MAX	0x1023
+#define REG_AGC_LOCK	0x1027
+#define REG_AGC_PWM_VAL	0x1028 /* 0x1028-0x1029 little endian */
+#define REG_AGC_HOLD_LOOP	0x1031
+
+#endif
+
diff --git a/drivers/media/dvb-frontends/au8522.h b/drivers/media/dvb-frontends/au8522.h
new file mode 100644
index 0000000..565dcf3
--- /dev/null
+++ b/drivers/media/dvb-frontends/au8522.h
@@ -0,0 +1,98 @@
+/*
+    Auvitek AU8522 QAM/8VSB demodulator driver
+
+    Copyright (C) 2008 Steven Toth <stoth@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 __AU8522_H__
+#define __AU8522_H__
+
+#include <linux/dvb/frontend.h>
+
+enum au8522_if_freq {
+	AU8522_IF_6MHZ = 0,
+	AU8522_IF_4MHZ,
+	AU8522_IF_3_25MHZ,
+};
+
+struct au8522_led_config {
+	u16 vsb8_strong;
+	u16 qam64_strong;
+	u16 qam256_strong;
+
+	u16 gpio_output;
+	/* unset hi bits, set low bits */
+	u16 gpio_output_enable;
+	u16 gpio_output_disable;
+
+	u16 gpio_leds;
+	u8 *led_states;
+	unsigned int num_led_states;
+};
+
+struct au8522_config {
+	/* the demodulator's i2c address */
+	u8 demod_address;
+
+	/* Return lock status based on tuner lock, or demod lock */
+#define AU8522_TUNERLOCKING 0
+#define AU8522_DEMODLOCKING 1
+	u8 status_mode;
+
+	struct au8522_led_config *led_cfg;
+
+	enum au8522_if_freq vsb_if;
+	enum au8522_if_freq qam_if;
+};
+
+#if defined(CONFIG_DVB_AU8522) || 				\
+	    (defined(CONFIG_DVB_AU8522_MODULE) && defined(MODULE))
+extern struct dvb_frontend *au8522_attach(const struct au8522_config *config,
+					  struct i2c_adapter *i2c);
+#else
+static inline
+struct dvb_frontend *au8522_attach(const struct au8522_config *config,
+				   struct i2c_adapter *i2c)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#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__ */
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ */
diff --git a/drivers/media/dvb-frontends/au8522_common.c b/drivers/media/dvb-frontends/au8522_common.c
new file mode 100644
index 0000000..3559ff2
--- /dev/null
+++ b/drivers/media/dvb-frontends/au8522_common.c
@@ -0,0 +1,277 @@
+/*
+    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.
+    Copyright (C) 2012 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/i2c.h>
+#include "dvb_frontend.h"
+#include "au8522_priv.h"
+
+static int debug;
+
+#define dprintk(arg...)\
+  do { if (debug)\
+	 printk(arg);\
+  } while (0)
+
+/* 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);
+
+/* 16 bit registers, 8 bit values */
+int au8522_writereg(struct au8522_state *state, u16 reg, u8 data)
+{
+	int ret;
+	u8 buf[] = { (reg >> 8) | 0x80, reg & 0xff, data };
+
+	struct i2c_msg msg = { .addr = state->config->demod_address,
+			       .flags = 0, .buf = buf, .len = 3 };
+
+	ret = i2c_transfer(state->i2c, &msg, 1);
+
+	if (ret != 1)
+		printk("%s: writereg error (reg == 0x%02x, val == 0x%04x, "
+		       "ret == %i)\n", __func__, reg, data, ret);
+
+	return (ret != 1) ? -1 : 0;
+}
+EXPORT_SYMBOL(au8522_writereg);
+
+u8 au8522_readreg(struct au8522_state *state, u16 reg)
+{
+	int ret;
+	u8 b0[] = { (reg >> 8) | 0x40, reg & 0xff };
+	u8 b1[] = { 0 };
+
+	struct i2c_msg msg[] = {
+		{ .addr = state->config->demod_address, .flags = 0,
+		  .buf = b0, .len = 2 },
+		{ .addr = state->config->demod_address, .flags = I2C_M_RD,
+		  .buf = b1, .len = 1 } };
+
+	ret = i2c_transfer(state->i2c, msg, 2);
+
+	if (ret != 2)
+		printk(KERN_ERR "%s: readreg error (ret == %i)\n",
+		       __func__, ret);
+	return b1[0];
+}
+EXPORT_SYMBOL(au8522_readreg);
+
+int au8522_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+	struct au8522_state *state = fe->demodulator_priv;
+
+	dprintk("%s(%d)\n", __func__, enable);
+
+	if (state->operational_mode == AU8522_ANALOG_MODE) {
+		/* We're being asked to manage the gate even though we're
+		   not in digital mode.  This can occur if we get switched
+		   over to analog mode before the dvb_frontend kernel thread
+		   has completely shutdown */
+		return 0;
+	}
+
+	if (enable)
+		return au8522_writereg(state, 0x106, 1);
+	else
+		return au8522_writereg(state, 0x106, 0);
+}
+EXPORT_SYMBOL(au8522_i2c_gate_ctrl);
+
+int au8522_analog_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+	struct au8522_state *state = fe->demodulator_priv;
+
+	dprintk("%s(%d)\n", __func__, enable);
+
+	if (enable)
+		return au8522_writereg(state, 0x106, 1);
+	else
+		return au8522_writereg(state, 0x106, 0);
+}
+EXPORT_SYMBOL(au8522_analog_i2c_gate_ctrl);
+
+/* Reset the demod hardware and reset all of the configuration registers
+   to a default state. */
+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;
+}
+EXPORT_SYMBOL(au8522_get_state);
+
+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);
+}
+EXPORT_SYMBOL(au8522_release_state);
+
+static int au8522_led_gpio_enable(struct au8522_state *state, int onoff)
+{
+	struct au8522_led_config *led_config = state->config->led_cfg;
+	u8 val;
+
+	/* bail out if we can't control an LED */
+	if (!led_config || !led_config->gpio_output ||
+	    !led_config->gpio_output_enable || !led_config->gpio_output_disable)
+		return 0;
+
+	val = au8522_readreg(state, 0x4000 |
+			     (led_config->gpio_output & ~0xc000));
+	if (onoff) {
+		/* enable GPIO output */
+		val &= ~((led_config->gpio_output_enable >> 8) & 0xff);
+		val |=  (led_config->gpio_output_enable & 0xff);
+	} else {
+		/* disable GPIO output */
+		val &= ~((led_config->gpio_output_disable >> 8) & 0xff);
+		val |=  (led_config->gpio_output_disable & 0xff);
+	}
+	return au8522_writereg(state, 0x8000 |
+			       (led_config->gpio_output & ~0xc000), val);
+}
+
+/* led = 0 | off
+ * led = 1 | signal ok
+ * led = 2 | signal strong
+ * led < 0 | only light led if leds are currently off
+ */
+int au8522_led_ctrl(struct au8522_state *state, int led)
+{
+	struct au8522_led_config *led_config = state->config->led_cfg;
+	int i, ret = 0;
+
+	/* bail out if we can't control an LED */
+	if (!led_config || !led_config->gpio_leds ||
+	    !led_config->num_led_states || !led_config->led_states)
+		return 0;
+
+	if (led < 0) {
+		/* if LED is already lit, then leave it as-is */
+		if (state->led_state)
+			return 0;
+		else
+			led *= -1;
+	}
+
+	/* toggle LED if changing state */
+	if (state->led_state != led) {
+		u8 val;
+
+		dprintk("%s: %d\n", __func__, led);
+
+		au8522_led_gpio_enable(state, 1);
+
+		val = au8522_readreg(state, 0x4000 |
+				     (led_config->gpio_leds & ~0xc000));
+
+		/* start with all leds off */
+		for (i = 0; i < led_config->num_led_states; i++)
+			val &= ~led_config->led_states[i];
+
+		/* set selected LED state */
+		if (led < led_config->num_led_states)
+			val |= led_config->led_states[led];
+		else if (led_config->num_led_states)
+			val |=
+			led_config->led_states[led_config->num_led_states - 1];
+
+		ret = au8522_writereg(state, 0x8000 |
+				      (led_config->gpio_leds & ~0xc000), val);
+		if (ret < 0)
+			return ret;
+
+		state->led_state = led;
+
+		if (led == 0)
+			au8522_led_gpio_enable(state, 0);
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(au8522_led_ctrl);
+
+int au8522_init(struct dvb_frontend *fe)
+{
+	struct au8522_state *state = fe->demodulator_priv;
+	dprintk("%s()\n", __func__);
+
+	state->operational_mode = AU8522_DIGITAL_MODE;
+
+	/* Clear out any state associated with the digital side of the
+	   chip, so that when it gets powered back up it won't think
+	   that it is already tuned */
+	state->current_frequency = 0;
+
+	au8522_writereg(state, 0xa4, 1 << 5);
+
+	au8522_i2c_gate_ctrl(fe, 1);
+
+	return 0;
+}
+EXPORT_SYMBOL(au8522_init);
+
+int au8522_sleep(struct dvb_frontend *fe)
+{
+	struct au8522_state *state = fe->demodulator_priv;
+	dprintk("%s()\n", __func__);
+
+	/* Only power down if the digital side is currently using the chip */
+	if (state->operational_mode == AU8522_ANALOG_MODE) {
+		/* We're not in one of the expected power modes, which means
+		   that the DVB thread is probably telling us to go to sleep
+		   even though the analog frontend has already started using
+		   the chip.  So ignore the request */
+		return 0;
+	}
+
+	/* turn off led */
+	au8522_led_ctrl(state, 0);
+
+	/* Power down the chip */
+	au8522_writereg(state, 0xa4, 1 << 5);
+
+	state->current_frequency = 0;
+
+	return 0;
+}
+EXPORT_SYMBOL(au8522_sleep);
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Enable verbose debug messages");
+
+MODULE_DESCRIPTION("Auvitek AU8522 QAM-B/ATSC Demodulator driver");
+MODULE_AUTHOR("Steven Toth");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb-frontends/au8522_decoder.c b/drivers/media/dvb-frontends/au8522_decoder.c
new file mode 100644
index 0000000..5243ba6
--- /dev/null
+++ b/drivers/media/dvb-frontends/au8522_decoder.c
@@ -0,0 +1,839 @@
+/*
+ * 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
+ * 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-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"
+*/
+static const 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
+*/
+static const 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);
+	state->saturation = 0x80;
+	au8522_writereg(state, AU8522_TVDEC_HUE_H_REG00EH, 0x00);
+	au8522_writereg(state, AU8522_TVDEC_HUE_L_REG00FH, 0x00);
+	state->hue = 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_FIELD_LEN_525 |
+			AU8522_TVDEC_FORMAT_CTRL1_REG061H_LINE_LEN_63_492 |
+			AU8522_TVDEC_FORMAT_CTRL1_REG061H_SUBCARRIER_NTSC_MN);
+	au8522_writereg(state, AU8522_TVDEC_FORMAT_CTRL2_REG062H,
+			AU8522_TVDEC_FORMAT_CTRL2_REG062H_STD_NTSC);
+	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);
+	if (input_mode == AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13 ||
+	    input_mode == AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH24) {
+		au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH,
+				AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH_SVIDEO);
+		au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH,
+				AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH_SVIDEO);
+	} else {
+		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 unknown). */
+		/* 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);
+
+	/* PGA in automatic mode */
+	au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x00);
+
+	/* Enable clamping control */
+	au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x00);
+
+	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 we have to have the PGA in automatic mode while
+	   enabling clamp control, but it's what Windows does */
+	au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x00);
+
+	/* Enable clamping control */
+	au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x0e);
+
+	/* Disable automatic PGA (since the CVBS is coming from the tuner) */
+	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);
+
+	/* PGA in automatic mode */
+	au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x00);
+
+	/* Enable clamping control */
+	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)
+{
+	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_SYSTEM_MODULE_CONTROL_1_REG0A5H, 0x04);
+	au8522_writereg(state, AU8522_I2S_CTRL_2_REG112H, 0x02);
+
+	au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
+			AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_SVIDEO);
+}
+
+/* 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:
+		state->saturation = ctrl->value;
+		au8522_writereg(state, AU8522_TVDEC_SATURATION_CB_REG00CH,
+				ctrl->value);
+		au8522_writereg(state, AU8522_TVDEC_SATURATION_CR_REG00DH,
+				ctrl->value);
+		break;
+	case V4L2_CID_HUE:
+		state->hue = ctrl->value;
+		au8522_writereg(state, AU8522_TVDEC_HUE_H_REG00EH,
+				ctrl->value >> 8);
+		au8522_writereg(state, AU8522_TVDEC_HUE_L_REG00FH,
+				ctrl->value & 0xFF);
+		break;
+	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:
+		ctrl->value = state->saturation;
+		break;
+	case V4L2_CID_HUE:
+		ctrl->value = state->hue;
+		break;
+	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;
+}
+
+/* ----------------------------------------------------------------------- */
+
+#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, 109);
+	case V4L2_CID_SATURATION:
+		return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128);
+	case V4L2_CID_HUE:
+		return v4l2_ctrl_query_fill(qc, -32768, 32768, 1, 0);
+	default:
+		break;
+	}
+
+	qc->type = 0;
+	return -EINVAL;
+}
+
+static int au8522_reset(struct v4l2_subdev *sd, u32 val)
+{
+	struct au8522_state *state = to_state(sd);
+
+	state->operational_mode = AU8522_ANALOG_MODE;
+
+	/* Clear out any state associated with the digital side of the
+	   chip, so that when it gets powered back up it won't think
+	   that it is already tuned */
+	state->current_frequency = 0;
+
+	au8522_writereg(state, 0xa4, 1 << 5);
+
+	return 0;
+}
+
+static int au8522_s_video_routing(struct v4l2_subdev *sd,
+					u32 input, u32 output, u32 config)
+{
+	struct au8522_state *state = to_state(sd);
+
+	au8522_reset(sd, 0);
+
+	if (input == AU8522_COMPOSITE_CH1) {
+		au8522_setup_cvbs_mode(state);
+	} else if (input == AU8522_SVIDEO_CH13) {
+		au8522_setup_svideo_mode(state);
+	} else if (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,
+					u32 input, u32 output, u32 config)
+{
+	struct au8522_state *state = to_state(sd);
+	set_audio_input(state, 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 = 0xffff;
+	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,
+	.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);
+	if (demod_config == NULL) {
+		if (instance == 1)
+			kfree(state);
+		return -ENOMEM;
+	}
+	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 i2c_driver au8522_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "au8522",
+	},
+	.probe		= au8522_probe,
+	.remove		= au8522_remove,
+	.id_table	= au8522_id,
+};
+
+module_i2c_driver(au8522_driver);
diff --git a/drivers/media/dvb-frontends/au8522_dig.c b/drivers/media/dvb-frontends/au8522_dig.c
new file mode 100644
index 0000000..a68974f
--- /dev/null
+++ b/drivers/media/dvb-frontends/au8522_dig.c
@@ -0,0 +1,828 @@
+/*
+    Auvitek AU8522 QAM/8VSB demodulator driver
+
+    Copyright (C) 2008 Steven Toth <stoth@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/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include "dvb_frontend.h"
+#include "au8522.h"
+#include "au8522_priv.h"
+
+static int debug;
+
+#define dprintk(arg...)\
+	do { if (debug)\
+		printk(arg);\
+	} while (0)
+
+struct mse2snr_tab {
+	u16 val;
+	u16 data;
+};
+
+/* VSB SNR lookup table */
+static struct mse2snr_tab vsb_mse2snr_tab[] = {
+	{   0, 270 },
+	{   2, 250 },
+	{   3, 240 },
+	{   5, 230 },
+	{   7, 220 },
+	{   9, 210 },
+	{  12, 200 },
+	{  13, 195 },
+	{  15, 190 },
+	{  17, 185 },
+	{  19, 180 },
+	{  21, 175 },
+	{  24, 170 },
+	{  27, 165 },
+	{  31, 160 },
+	{  32, 158 },
+	{  33, 156 },
+	{  36, 152 },
+	{  37, 150 },
+	{  39, 148 },
+	{  40, 146 },
+	{  41, 144 },
+	{  43, 142 },
+	{  44, 140 },
+	{  48, 135 },
+	{  50, 130 },
+	{  43, 142 },
+	{  53, 125 },
+	{  56, 120 },
+	{ 256, 115 },
+};
+
+/* QAM64 SNR lookup table */
+static struct mse2snr_tab qam64_mse2snr_tab[] = {
+	{  15,   0 },
+	{  16, 290 },
+	{  17, 288 },
+	{  18, 286 },
+	{  19, 284 },
+	{  20, 282 },
+	{  21, 281 },
+	{  22, 279 },
+	{  23, 277 },
+	{  24, 275 },
+	{  25, 273 },
+	{  26, 271 },
+	{  27, 269 },
+	{  28, 268 },
+	{  29, 266 },
+	{  30, 264 },
+	{  31, 262 },
+	{  32, 260 },
+	{  33, 259 },
+	{  34, 258 },
+	{  35, 256 },
+	{  36, 255 },
+	{  37, 254 },
+	{  38, 252 },
+	{  39, 251 },
+	{  40, 250 },
+	{  41, 249 },
+	{  42, 248 },
+	{  43, 246 },
+	{  44, 245 },
+	{  45, 244 },
+	{  46, 242 },
+	{  47, 241 },
+	{  48, 240 },
+	{  50, 239 },
+	{  51, 238 },
+	{  53, 237 },
+	{  54, 236 },
+	{  56, 235 },
+	{  57, 234 },
+	{  59, 233 },
+	{  60, 232 },
+	{  62, 231 },
+	{  63, 230 },
+	{  65, 229 },
+	{  67, 228 },
+	{  68, 227 },
+	{  70, 226 },
+	{  71, 225 },
+	{  73, 224 },
+	{  74, 223 },
+	{  76, 222 },
+	{  78, 221 },
+	{  80, 220 },
+	{  82, 219 },
+	{  85, 218 },
+	{  88, 217 },
+	{  90, 216 },
+	{  92, 215 },
+	{  93, 214 },
+	{  94, 212 },
+	{  95, 211 },
+	{  97, 210 },
+	{  99, 209 },
+	{ 101, 208 },
+	{ 102, 207 },
+	{ 104, 206 },
+	{ 107, 205 },
+	{ 111, 204 },
+	{ 114, 203 },
+	{ 118, 202 },
+	{ 122, 201 },
+	{ 125, 200 },
+	{ 128, 199 },
+	{ 130, 198 },
+	{ 132, 197 },
+	{ 256, 190 },
+};
+
+/* QAM256 SNR lookup table */
+static struct mse2snr_tab qam256_mse2snr_tab[] = {
+	{  15,   0 },
+	{  16, 400 },
+	{  17, 398 },
+	{  18, 396 },
+	{  19, 394 },
+	{  20, 392 },
+	{  21, 390 },
+	{  22, 388 },
+	{  23, 386 },
+	{  24, 384 },
+	{  25, 382 },
+	{  26, 380 },
+	{  27, 379 },
+	{  28, 378 },
+	{  29, 377 },
+	{  30, 376 },
+	{  31, 375 },
+	{  32, 374 },
+	{  33, 373 },
+	{  34, 372 },
+	{  35, 371 },
+	{  36, 370 },
+	{  37, 362 },
+	{  38, 354 },
+	{  39, 346 },
+	{  40, 338 },
+	{  41, 330 },
+	{  42, 328 },
+	{  43, 326 },
+	{  44, 324 },
+	{  45, 322 },
+	{  46, 320 },
+	{  47, 319 },
+	{  48, 318 },
+	{  49, 317 },
+	{  50, 316 },
+	{  51, 315 },
+	{  52, 314 },
+	{  53, 313 },
+	{  54, 312 },
+	{  55, 311 },
+	{  56, 310 },
+	{  57, 308 },
+	{  58, 306 },
+	{  59, 304 },
+	{  60, 302 },
+	{  61, 300 },
+	{  62, 298 },
+	{  65, 295 },
+	{  68, 294 },
+	{  70, 293 },
+	{  73, 292 },
+	{  76, 291 },
+	{  78, 290 },
+	{  79, 289 },
+	{  81, 288 },
+	{  82, 287 },
+	{  83, 286 },
+	{  84, 285 },
+	{  85, 284 },
+	{  86, 283 },
+	{  88, 282 },
+	{  89, 281 },
+	{ 256, 280 },
+};
+
+static int au8522_mse2snr_lookup(struct mse2snr_tab *tab, int sz, int mse,
+				 u16 *snr)
+{
+	int i, ret = -EINVAL;
+	dprintk("%s()\n", __func__);
+
+	for (i = 0; i < sz; i++) {
+		if (mse < tab[i].val) {
+			*snr = tab[i].data;
+			ret = 0;
+			break;
+		}
+	}
+	dprintk("%s() snr=%d\n", __func__, *snr);
+	return ret;
+}
+
+static int au8522_set_if(struct dvb_frontend *fe, enum au8522_if_freq if_freq)
+{
+	struct au8522_state *state = fe->demodulator_priv;
+	u8 r0b5, r0b6, r0b7;
+	char *ifmhz;
+
+	switch (if_freq) {
+	case AU8522_IF_3_25MHZ:
+		ifmhz = "3.25";
+		r0b5 = 0x00;
+		r0b6 = 0x3d;
+		r0b7 = 0xa0;
+		break;
+	case AU8522_IF_4MHZ:
+		ifmhz = "4.00";
+		r0b5 = 0x00;
+		r0b6 = 0x4b;
+		r0b7 = 0xd9;
+		break;
+	case AU8522_IF_6MHZ:
+		ifmhz = "6.00";
+		r0b5 = 0xfb;
+		r0b6 = 0x8e;
+		r0b7 = 0x39;
+		break;
+	default:
+		dprintk("%s() IF Frequency not supported\n", __func__);
+		return -EINVAL;
+	}
+	dprintk("%s() %s MHz\n", __func__, ifmhz);
+	au8522_writereg(state, 0x80b5, r0b5);
+	au8522_writereg(state, 0x80b6, r0b6);
+	au8522_writereg(state, 0x80b7, r0b7);
+
+	return 0;
+}
+
+/* VSB Modulation table */
+static struct {
+	u16 reg;
+	u16 data;
+} VSB_mod_tab[] = {
+	{ 0x8090, 0x84 },
+	{ 0x4092, 0x11 },
+	{ 0x2005, 0x00 },
+	{ 0x8091, 0x80 },
+	{ 0x80a3, 0x0c },
+	{ 0x80a4, 0xe8 },
+	{ 0x8081, 0xc4 },
+	{ 0x80a5, 0x40 },
+	{ 0x80a7, 0x40 },
+	{ 0x80a6, 0x67 },
+	{ 0x8262, 0x20 },
+	{ 0x821c, 0x30 },
+	{ 0x80d8, 0x1a },
+	{ 0x8227, 0xa0 },
+	{ 0x8121, 0xff },
+	{ 0x80a8, 0xf0 },
+	{ 0x80a9, 0x05 },
+	{ 0x80aa, 0x77 },
+	{ 0x80ab, 0xf0 },
+	{ 0x80ac, 0x05 },
+	{ 0x80ad, 0x77 },
+	{ 0x80ae, 0x41 },
+	{ 0x80af, 0x66 },
+	{ 0x821b, 0xcc },
+	{ 0x821d, 0x80 },
+	{ 0x80a4, 0xe8 },
+	{ 0x8231, 0x13 },
+};
+
+/* QAM64 Modulation table */
+static struct {
+	u16 reg;
+	u16 data;
+} QAM64_mod_tab[] = {
+	{ 0x00a3, 0x09 },
+	{ 0x00a4, 0x00 },
+	{ 0x0081, 0xc4 },
+	{ 0x00a5, 0x40 },
+	{ 0x00aa, 0x77 },
+	{ 0x00ad, 0x77 },
+	{ 0x00a6, 0x67 },
+	{ 0x0262, 0x20 },
+	{ 0x021c, 0x30 },
+	{ 0x00b8, 0x3e },
+	{ 0x00b9, 0xf0 },
+	{ 0x00ba, 0x01 },
+	{ 0x00bb, 0x18 },
+	{ 0x00bc, 0x50 },
+	{ 0x00bd, 0x00 },
+	{ 0x00be, 0xea },
+	{ 0x00bf, 0xef },
+	{ 0x00c0, 0xfc },
+	{ 0x00c1, 0xbd },
+	{ 0x00c2, 0x1f },
+	{ 0x00c3, 0xfc },
+	{ 0x00c4, 0xdd },
+	{ 0x00c5, 0xaf },
+	{ 0x00c6, 0x00 },
+	{ 0x00c7, 0x38 },
+	{ 0x00c8, 0x30 },
+	{ 0x00c9, 0x05 },
+	{ 0x00ca, 0x4a },
+	{ 0x00cb, 0xd0 },
+	{ 0x00cc, 0x01 },
+	{ 0x00cd, 0xd9 },
+	{ 0x00ce, 0x6f },
+	{ 0x00cf, 0xf9 },
+	{ 0x00d0, 0x70 },
+	{ 0x00d1, 0xdf },
+	{ 0x00d2, 0xf7 },
+	{ 0x00d3, 0xc2 },
+	{ 0x00d4, 0xdf },
+	{ 0x00d5, 0x02 },
+	{ 0x00d6, 0x9a },
+	{ 0x00d7, 0xd0 },
+	{ 0x0250, 0x0d },
+	{ 0x0251, 0xcd },
+	{ 0x0252, 0xe0 },
+	{ 0x0253, 0x05 },
+	{ 0x0254, 0xa7 },
+	{ 0x0255, 0xff },
+	{ 0x0256, 0xed },
+	{ 0x0257, 0x5b },
+	{ 0x0258, 0xae },
+	{ 0x0259, 0xe6 },
+	{ 0x025a, 0x3d },
+	{ 0x025b, 0x0f },
+	{ 0x025c, 0x0d },
+	{ 0x025d, 0xea },
+	{ 0x025e, 0xf2 },
+	{ 0x025f, 0x51 },
+	{ 0x0260, 0xf5 },
+	{ 0x0261, 0x06 },
+	{ 0x021a, 0x00 },
+	{ 0x0546, 0x40 },
+	{ 0x0210, 0xc7 },
+	{ 0x0211, 0xaa },
+	{ 0x0212, 0xab },
+	{ 0x0213, 0x02 },
+	{ 0x0502, 0x00 },
+	{ 0x0121, 0x04 },
+	{ 0x0122, 0x04 },
+	{ 0x052e, 0x10 },
+	{ 0x00a4, 0xca },
+	{ 0x00a7, 0x40 },
+	{ 0x0526, 0x01 },
+};
+
+/* QAM256 Modulation table */
+static struct {
+	u16 reg;
+	u16 data;
+} QAM256_mod_tab[] = {
+	{ 0x80a3, 0x09 },
+	{ 0x80a4, 0x00 },
+	{ 0x8081, 0xc4 },
+	{ 0x80a5, 0x40 },
+	{ 0x80aa, 0x77 },
+	{ 0x80ad, 0x77 },
+	{ 0x80a6, 0x67 },
+	{ 0x8262, 0x20 },
+	{ 0x821c, 0x30 },
+	{ 0x80b8, 0x3e },
+	{ 0x80b9, 0xf0 },
+	{ 0x80ba, 0x01 },
+	{ 0x80bb, 0x18 },
+	{ 0x80bc, 0x50 },
+	{ 0x80bd, 0x00 },
+	{ 0x80be, 0xea },
+	{ 0x80bf, 0xef },
+	{ 0x80c0, 0xfc },
+	{ 0x80c1, 0xbd },
+	{ 0x80c2, 0x1f },
+	{ 0x80c3, 0xfc },
+	{ 0x80c4, 0xdd },
+	{ 0x80c5, 0xaf },
+	{ 0x80c6, 0x00 },
+	{ 0x80c7, 0x38 },
+	{ 0x80c8, 0x30 },
+	{ 0x80c9, 0x05 },
+	{ 0x80ca, 0x4a },
+	{ 0x80cb, 0xd0 },
+	{ 0x80cc, 0x01 },
+	{ 0x80cd, 0xd9 },
+	{ 0x80ce, 0x6f },
+	{ 0x80cf, 0xf9 },
+	{ 0x80d0, 0x70 },
+	{ 0x80d1, 0xdf },
+	{ 0x80d2, 0xf7 },
+	{ 0x80d3, 0xc2 },
+	{ 0x80d4, 0xdf },
+	{ 0x80d5, 0x02 },
+	{ 0x80d6, 0x9a },
+	{ 0x80d7, 0xd0 },
+	{ 0x8250, 0x0d },
+	{ 0x8251, 0xcd },
+	{ 0x8252, 0xe0 },
+	{ 0x8253, 0x05 },
+	{ 0x8254, 0xa7 },
+	{ 0x8255, 0xff },
+	{ 0x8256, 0xed },
+	{ 0x8257, 0x5b },
+	{ 0x8258, 0xae },
+	{ 0x8259, 0xe6 },
+	{ 0x825a, 0x3d },
+	{ 0x825b, 0x0f },
+	{ 0x825c, 0x0d },
+	{ 0x825d, 0xea },
+	{ 0x825e, 0xf2 },
+	{ 0x825f, 0x51 },
+	{ 0x8260, 0xf5 },
+	{ 0x8261, 0x06 },
+	{ 0x821a, 0x00 },
+	{ 0x8546, 0x40 },
+	{ 0x8210, 0x26 },
+	{ 0x8211, 0xf6 },
+	{ 0x8212, 0x84 },
+	{ 0x8213, 0x02 },
+	{ 0x8502, 0x01 },
+	{ 0x8121, 0x04 },
+	{ 0x8122, 0x04 },
+	{ 0x852e, 0x10 },
+	{ 0x80a4, 0xca },
+	{ 0x80a7, 0x40 },
+	{ 0x8526, 0x01 },
+};
+
+static int au8522_enable_modulation(struct dvb_frontend *fe,
+				    fe_modulation_t m)
+{
+	struct au8522_state *state = fe->demodulator_priv;
+	int i;
+
+	dprintk("%s(0x%08x)\n", __func__, m);
+
+	switch (m) {
+	case VSB_8:
+		dprintk("%s() VSB_8\n", __func__);
+		for (i = 0; i < ARRAY_SIZE(VSB_mod_tab); i++)
+			au8522_writereg(state,
+				VSB_mod_tab[i].reg,
+				VSB_mod_tab[i].data);
+		au8522_set_if(fe, state->config->vsb_if);
+		break;
+	case QAM_64:
+		dprintk("%s() QAM 64\n", __func__);
+		for (i = 0; i < ARRAY_SIZE(QAM64_mod_tab); i++)
+			au8522_writereg(state,
+				QAM64_mod_tab[i].reg,
+				QAM64_mod_tab[i].data);
+		au8522_set_if(fe, state->config->qam_if);
+		break;
+	case QAM_256:
+		dprintk("%s() QAM 256\n", __func__);
+		for (i = 0; i < ARRAY_SIZE(QAM256_mod_tab); i++)
+			au8522_writereg(state,
+				QAM256_mod_tab[i].reg,
+				QAM256_mod_tab[i].data);
+		au8522_set_if(fe, state->config->qam_if);
+		break;
+	default:
+		dprintk("%s() Invalid modulation\n", __func__);
+		return -EINVAL;
+	}
+
+	state->current_modulation = m;
+
+	return 0;
+}
+
+/* Talk to the demod, set the FEC, GUARD, QAM settings etc */
+static int au8522_set_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	struct au8522_state *state = fe->demodulator_priv;
+	int ret = -EINVAL;
+
+	dprintk("%s(frequency=%d)\n", __func__, c->frequency);
+
+	if ((state->current_frequency == c->frequency) &&
+	    (state->current_modulation == c->modulation))
+		return 0;
+
+	if (fe->ops.tuner_ops.set_params) {
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 1);
+		ret = fe->ops.tuner_ops.set_params(fe);
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 0);
+	}
+
+	if (ret < 0)
+		return ret;
+
+	/* Allow the tuner to settle */
+	msleep(100);
+
+	au8522_enable_modulation(fe, c->modulation);
+
+	state->current_frequency = c->frequency;
+
+	return 0;
+}
+
+static int au8522_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+	struct au8522_state *state = fe->demodulator_priv;
+	u8 reg;
+	u32 tuner_status = 0;
+
+	*status = 0;
+
+	if (state->current_modulation == VSB_8) {
+		dprintk("%s() Checking VSB_8\n", __func__);
+		reg = au8522_readreg(state, 0x4088);
+		if ((reg & 0x03) == 0x03)
+			*status |= FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI;
+	} else {
+		dprintk("%s() Checking QAM\n", __func__);
+		reg = au8522_readreg(state, 0x4541);
+		if (reg & 0x80)
+			*status |= FE_HAS_VITERBI;
+		if (reg & 0x20)
+			*status |= FE_HAS_LOCK | FE_HAS_SYNC;
+	}
+
+	switch (state->config->status_mode) {
+	case AU8522_DEMODLOCKING:
+		dprintk("%s() DEMODLOCKING\n", __func__);
+		if (*status & FE_HAS_VITERBI)
+			*status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
+		break;
+	case AU8522_TUNERLOCKING:
+		/* Get the tuner status */
+		dprintk("%s() TUNERLOCKING\n", __func__);
+		if (fe->ops.tuner_ops.get_status) {
+			if (fe->ops.i2c_gate_ctrl)
+				fe->ops.i2c_gate_ctrl(fe, 1);
+
+			fe->ops.tuner_ops.get_status(fe, &tuner_status);
+
+			if (fe->ops.i2c_gate_ctrl)
+				fe->ops.i2c_gate_ctrl(fe, 0);
+		}
+		if (tuner_status)
+			*status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
+		break;
+	}
+	state->fe_status = *status;
+
+	if (*status & FE_HAS_LOCK)
+		/* turn on LED, if it isn't on already */
+		au8522_led_ctrl(state, -1);
+	else
+		/* turn off LED */
+		au8522_led_ctrl(state, 0);
+
+	dprintk("%s() status 0x%08x\n", __func__, *status);
+
+	return 0;
+}
+
+static int au8522_led_status(struct au8522_state *state, const u16 *snr)
+{
+	struct au8522_led_config *led_config = state->config->led_cfg;
+	int led;
+	u16 strong;
+
+	/* bail out if we can't control an LED */
+	if (!led_config)
+		return 0;
+
+	if (0 == (state->fe_status & FE_HAS_LOCK))
+		return au8522_led_ctrl(state, 0);
+	else if (state->current_modulation == QAM_256)
+		strong = led_config->qam256_strong;
+	else if (state->current_modulation == QAM_64)
+		strong = led_config->qam64_strong;
+	else /* (state->current_modulation == VSB_8) */
+		strong = led_config->vsb8_strong;
+
+	if (*snr >= strong)
+		led = 2;
+	else
+		led = 1;
+
+	if ((state->led_state) &&
+	    (((strong < *snr) ? (*snr - strong) : (strong - *snr)) <= 10))
+		/* snr didn't change enough to bother
+		 * changing the color of the led */
+		return 0;
+
+	return au8522_led_ctrl(state, led);
+}
+
+static int au8522_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+	struct au8522_state *state = fe->demodulator_priv;
+	int ret = -EINVAL;
+
+	dprintk("%s()\n", __func__);
+
+	if (state->current_modulation == QAM_256)
+		ret = au8522_mse2snr_lookup(qam256_mse2snr_tab,
+					    ARRAY_SIZE(qam256_mse2snr_tab),
+					    au8522_readreg(state, 0x4522),
+					    snr);
+	else if (state->current_modulation == QAM_64)
+		ret = au8522_mse2snr_lookup(qam64_mse2snr_tab,
+					    ARRAY_SIZE(qam64_mse2snr_tab),
+					    au8522_readreg(state, 0x4522),
+					    snr);
+	else /* VSB_8 */
+		ret = au8522_mse2snr_lookup(vsb_mse2snr_tab,
+					    ARRAY_SIZE(vsb_mse2snr_tab),
+					    au8522_readreg(state, 0x4311),
+					    snr);
+
+	if (state->config->led_cfg)
+		au8522_led_status(state, snr);
+
+	return ret;
+}
+
+static int au8522_read_signal_strength(struct dvb_frontend *fe,
+				       u16 *signal_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%
+	 */
+	u16 snr;
+	u32 tmp;
+	int ret = au8522_read_snr(fe, &snr);
+
+	*signal_strength = 0;
+
+	if (0 == ret) {
+		/* The following calculation method was chosen
+		 * purely for the sake of code re-use from the
+		 * other demod drivers that use this method */
+
+		/* Convert from SNR in dB * 10 to 8.24 fixed-point */
+		tmp = (snr * ((1 << 24) / 10));
+
+		/* Convert from 8.24 fixed-point to
+		 * scale the range 0 - 35*2^24 into 0 - 65535*/
+		if (tmp >= 8960 * 0x10000)
+			*signal_strength = 0xffff;
+		else
+			*signal_strength = tmp / 8960;
+	}
+
+	return ret;
+}
+
+static int au8522_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+	struct au8522_state *state = fe->demodulator_priv;
+
+	if (state->current_modulation == VSB_8)
+		*ucblocks = au8522_readreg(state, 0x4087);
+	else
+		*ucblocks = au8522_readreg(state, 0x4543);
+
+	return 0;
+}
+
+static int au8522_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+	return au8522_read_ucblocks(fe, ber);
+}
+
+static int au8522_get_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	struct au8522_state *state = fe->demodulator_priv;
+
+	c->frequency = state->current_frequency;
+	c->modulation = state->current_modulation;
+
+	return 0;
+}
+
+static int au8522_get_tune_settings(struct dvb_frontend *fe,
+				    struct dvb_frontend_tune_settings *tune)
+{
+	tune->min_delay_ms = 1000;
+	return 0;
+}
+
+static struct dvb_frontend_ops au8522_ops;
+
+
+static void au8522_release(struct dvb_frontend *fe)
+{
+	struct au8522_state *state = fe->demodulator_priv;
+	au8522_release_state(state);
+}
+
+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 */
+	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;
+	state->i2c = i2c;
+	state->operational_mode = AU8522_DIGITAL_MODE;
+
+	/* create dvb_frontend */
+	memcpy(&state->frontend.ops, &au8522_ops,
+	       sizeof(struct dvb_frontend_ops));
+	state->frontend.demodulator_priv = state;
+
+	state->frontend.ops.analog_ops.i2c_gate_ctrl = au8522_analog_i2c_gate_ctrl;
+
+	if (au8522_init(&state->frontend) != 0) {
+		printk(KERN_ERR "%s: Failed to initialize correctly\n",
+			__func__);
+		goto error;
+	}
+
+	/* Note: Leaving the I2C gate open here. */
+	au8522_i2c_gate_ctrl(&state->frontend, 1);
+
+	return &state->frontend;
+
+error:
+	au8522_release_state(state);
+	return NULL;
+}
+EXPORT_SYMBOL(au8522_attach);
+
+static struct dvb_frontend_ops au8522_ops = {
+	.delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
+	.info = {
+		.name			= "Auvitek AU8522 QAM/8VSB Frontend",
+		.frequency_min		= 54000000,
+		.frequency_max		= 858000000,
+		.frequency_stepsize	= 62500,
+		.caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
+	},
+
+	.init                 = au8522_init,
+	.sleep                = au8522_sleep,
+	.i2c_gate_ctrl        = au8522_i2c_gate_ctrl,
+	.set_frontend         = au8522_set_frontend,
+	.get_frontend         = au8522_get_frontend,
+	.get_tune_settings    = au8522_get_tune_settings,
+	.read_status          = au8522_read_status,
+	.read_ber             = au8522_read_ber,
+	.read_signal_strength = au8522_read_signal_strength,
+	.read_snr             = au8522_read_snr,
+	.read_ucblocks        = au8522_read_ucblocks,
+	.release              = au8522_release,
+};
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Enable verbose debug messages");
+
+MODULE_DESCRIPTION("Auvitek AU8522 QAM-B/ATSC Demodulator driver");
+MODULE_AUTHOR("Steven Toth");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb-frontends/au8522_priv.h b/drivers/media/dvb-frontends/au8522_priv.h
new file mode 100644
index 0000000..0529699
--- /dev/null
+++ b/drivers/media/dvb-frontends/au8522_priv.h
@@ -0,0 +1,446 @@
+/*
+    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"
+
+#define AU8522_ANALOG_MODE 0
+#define AU8522_DIGITAL_MODE 1
+
+struct au8522_state {
+	struct i2c_client *c;
+	struct i2c_adapter *i2c;
+
+	u8 operational_mode;
+
+	/* 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;
+	u8 saturation;
+	s16 hue;
+};
+
+/* 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);
+int au8522_i2c_gate_ctrl(struct dvb_frontend *fe, int enable);
+int au8522_analog_i2c_gate_ctrl(struct dvb_frontend *fe, int enable);
+int au8522_led_ctrl(struct au8522_state *state, int led);
+
+/* 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
+
+
+/**************************************************************/
+
+/* Format control 1 */
+
+/* VCR Mode 7-6 */
+#define AU8522_TVDEC_FORMAT_CTRL1_REG061H_VCR_MODE_YES		0x80
+#define AU8522_TVDEC_FORMAT_CTRL1_REG061H_VCR_MODE_NO		0x40
+#define AU8522_TVDEC_FORMAT_CTRL1_REG061H_VCR_MODE_AUTO		0x00
+/* Field len 5-4 */
+#define AU8522_TVDEC_FORMAT_CTRL1_REG061H_FIELD_LEN_625		0x20
+#define AU8522_TVDEC_FORMAT_CTRL1_REG061H_FIELD_LEN_525		0x10
+#define AU8522_TVDEC_FORMAT_CTRL1_REG061H_FIELD_LEN_AUTO	0x00
+/* Line len (us) 3-2 */
+#define AU8522_TVDEC_FORMAT_CTRL1_REG061H_LINE_LEN_64_000	0x0b
+#define AU8522_TVDEC_FORMAT_CTRL1_REG061H_LINE_LEN_63_492	0x08
+#define AU8522_TVDEC_FORMAT_CTRL1_REG061H_LINE_LEN_63_556	0x04
+/* Subcarrier freq 1-0 */
+#define AU8522_TVDEC_FORMAT_CTRL1_REG061H_SUBCARRIER_NTSC_AUTO	0x03
+#define AU8522_TVDEC_FORMAT_CTRL1_REG061H_SUBCARRIER_NTSC_443	0x02
+#define AU8522_TVDEC_FORMAT_CTRL1_REG061H_SUBCARRIER_NTSC_MN	0x01
+#define AU8522_TVDEC_FORMAT_CTRL1_REG061H_SUBCARRIER_NTSC_50	0x00
+
+/* Format control 2 */
+#define AU8522_TVDEC_FORMAT_CTRL2_REG062H_STD_AUTODETECT	0x00
+#define AU8522_TVDEC_FORMAT_CTRL2_REG062H_STD_NTSC		0x01
+
+
+#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_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_THR1_REG06CH_SVIDEO		0x2a
+#define AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH_CVBS		0x05
+#define AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH_SVIDEO		0x15
+#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/bcm3510.c b/drivers/media/dvb-frontends/bcm3510.c
new file mode 100644
index 0000000..033cd7a
--- /dev/null
+++ b/drivers/media/dvb-frontends/bcm3510.c
@@ -0,0 +1,856 @@
+/*
+ * Support for the Broadcom BCM3510 ATSC demodulator (1st generation Air2PC)
+ *
+ *  Copyright (C) 2001-5, B2C2 inc.
+ *
+ *  GPL/Linux driver written by Patrick Boettcher <patrick.boettcher@desy.de>
+ *
+ *  This driver is "hard-coded" to be used with the 1st generation of
+ *  Technisat/B2C2's Air2PC ATSC PCI/USB cards/boxes. The pll-programming
+ *  (Panasonic CT10S) is located here, which is actually wrong. Unless there is
+ *  another device with a BCM3510, this is no problem.
+ *
+ *  The driver works also with QAM64 DVB-C, but had an unreasonable high
+ *  UNC. (Tested with the Air2PC ATSC 1st generation)
+ *
+ *  You'll need a firmware for this driver in order to get it running. It is
+ *  called "dvb-fe-bcm3510-01.fw".
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the 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/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/firmware.h>
+#include <linux/jiffies.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/mutex.h>
+
+#include "dvb_frontend.h"
+#include "bcm3510.h"
+#include "bcm3510_priv.h"
+
+struct bcm3510_state {
+
+	struct i2c_adapter* i2c;
+	const struct bcm3510_config* config;
+	struct dvb_frontend frontend;
+
+	/* demodulator private data */
+	struct mutex hab_mutex;
+	u8 firmware_loaded:1;
+
+	unsigned long next_status_check;
+	unsigned long status_check_interval;
+	struct bcm3510_hab_cmd_status1 status1;
+	struct bcm3510_hab_cmd_status2 status2;
+};
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level (1=info,2=i2c (|-able)).");
+
+#define dprintk(level,x...) if (level & debug) printk(x)
+#define dbufout(b,l,m) {\
+	    int i; \
+	    for (i = 0; i < l; i++) \
+		m("%02x ",b[i]); \
+}
+#define deb_info(args...) dprintk(0x01,args)
+#define deb_i2c(args...)  dprintk(0x02,args)
+#define deb_hab(args...)  dprintk(0x04,args)
+
+/* transfer functions */
+static int bcm3510_writebytes (struct bcm3510_state *state, u8 reg, u8 *buf, u8 len)
+{
+	u8 b[256];
+	int err;
+	struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = b, .len = len + 1 };
+
+	b[0] = reg;
+	memcpy(&b[1],buf,len);
+
+	deb_i2c("i2c wr %02x: ",reg);
+	dbufout(buf,len,deb_i2c);
+	deb_i2c("\n");
+
+	if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
+
+		deb_info("%s: i2c write error (addr %02x, reg %02x, err == %i)\n",
+			__func__, state->config->demod_address, reg,  err);
+		return -EREMOTEIO;
+	}
+
+	return 0;
+}
+
+static int bcm3510_readbytes (struct bcm3510_state *state, u8 reg, u8 *buf, u8 len)
+{
+	struct i2c_msg msg[] = {
+		{ .addr = state->config->demod_address, .flags = 0,        .buf = &reg, .len = 1 },
+		{ .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = buf,  .len = len }
+	};
+	int err;
+
+	memset(buf,0,len);
+
+	if ((err = i2c_transfer (state->i2c, msg, 2)) != 2) {
+		deb_info("%s: i2c read error (addr %02x, reg %02x, err == %i)\n",
+			__func__, state->config->demod_address, reg,  err);
+		return -EREMOTEIO;
+	}
+	deb_i2c("i2c rd %02x: ",reg);
+	dbufout(buf,len,deb_i2c);
+	deb_i2c("\n");
+
+	return 0;
+}
+
+static int bcm3510_writeB(struct bcm3510_state *state, u8 reg, bcm3510_register_value v)
+{
+	return bcm3510_writebytes(state,reg,&v.raw,1);
+}
+
+static int bcm3510_readB(struct bcm3510_state *state, u8 reg, bcm3510_register_value *v)
+{
+	return bcm3510_readbytes(state,reg,&v->raw,1);
+}
+
+/* Host Access Buffer transfers */
+static int bcm3510_hab_get_response(struct bcm3510_state *st, u8 *buf, int len)
+{
+	bcm3510_register_value v;
+	int ret,i;
+
+	v.HABADR_a6.HABADR = 0;
+	if ((ret = bcm3510_writeB(st,0xa6,v)) < 0)
+		return ret;
+
+	for (i = 0; i < len; i++) {
+		if ((ret = bcm3510_readB(st,0xa7,&v)) < 0)
+			return ret;
+		buf[i] = v.HABDATA_a7;
+	}
+	return 0;
+}
+
+static int bcm3510_hab_send_request(struct bcm3510_state *st, u8 *buf, int len)
+{
+	bcm3510_register_value v,hab;
+	int ret,i;
+	unsigned long t;
+
+/* Check if any previous HAB request still needs to be serviced by the
+ * Acquisition Processor before sending new request */
+	if ((ret = bcm3510_readB(st,0xa8,&v)) < 0)
+		return ret;
+	if (v.HABSTAT_a8.HABR) {
+		deb_info("HAB is running already - clearing it.\n");
+		v.HABSTAT_a8.HABR = 0;
+		bcm3510_writeB(st,0xa8,v);
+//		return -EBUSY;
+	}
+
+/* Send the start HAB Address (automatically incremented after write of
+ * HABDATA) and write the HAB Data */
+	hab.HABADR_a6.HABADR = 0;
+	if ((ret = bcm3510_writeB(st,0xa6,hab)) < 0)
+		return ret;
+
+	for (i = 0; i < len; i++) {
+		hab.HABDATA_a7 = buf[i];
+		if ((ret = bcm3510_writeB(st,0xa7,hab)) < 0)
+			return ret;
+	}
+
+/* Set the HABR bit to indicate AP request in progress (LBHABR allows HABR to
+ * be written) */
+	v.raw = 0; v.HABSTAT_a8.HABR = 1; v.HABSTAT_a8.LDHABR = 1;
+	if ((ret = bcm3510_writeB(st,0xa8,v)) < 0)
+		return ret;
+
+/* Polling method: Wait until the AP finishes processing the HAB request */
+	t = jiffies + 1*HZ;
+	while (time_before(jiffies, t)) {
+		deb_info("waiting for HAB to complete\n");
+		msleep(10);
+		if ((ret = bcm3510_readB(st,0xa8,&v)) < 0)
+			return ret;
+
+		if (!v.HABSTAT_a8.HABR)
+			return 0;
+	}
+
+	deb_info("send_request execution timed out.\n");
+	return -ETIMEDOUT;
+}
+
+static int bcm3510_do_hab_cmd(struct bcm3510_state *st, u8 cmd, u8 msgid, u8 *obuf, u8 olen, u8 *ibuf, u8 ilen)
+{
+	u8 ob[olen+2],ib[ilen+2];
+	int ret = 0;
+
+	ob[0] = cmd;
+	ob[1] = msgid;
+	memcpy(&ob[2],obuf,olen);
+
+	deb_hab("hab snd: ");
+	dbufout(ob,olen+2,deb_hab);
+	deb_hab("\n");
+
+	if (mutex_lock_interruptible(&st->hab_mutex) < 0)
+		return -EAGAIN;
+
+	if ((ret = bcm3510_hab_send_request(st, ob, olen+2)) < 0 ||
+		(ret = bcm3510_hab_get_response(st, ib, ilen+2)) < 0)
+		goto error;
+
+	deb_hab("hab get: ");
+	dbufout(ib,ilen+2,deb_hab);
+	deb_hab("\n");
+
+	memcpy(ibuf,&ib[2],ilen);
+error:
+	mutex_unlock(&st->hab_mutex);
+	return ret;
+}
+
+#if 0
+/* not needed, we use a semaphore to prevent HAB races */
+static int bcm3510_is_ap_ready(struct bcm3510_state *st)
+{
+	bcm3510_register_value ap,hab;
+	int ret;
+
+	if ((ret = bcm3510_readB(st,0xa8,&hab)) < 0 ||
+		(ret = bcm3510_readB(st,0xa2,&ap) < 0))
+		return ret;
+
+	if (ap.APSTAT1_a2.RESET || ap.APSTAT1_a2.IDLE || ap.APSTAT1_a2.STOP || hab.HABSTAT_a8.HABR) {
+		deb_info("AP is busy\n");
+		return -EBUSY;
+	}
+
+	return 0;
+}
+#endif
+
+static int bcm3510_bert_reset(struct bcm3510_state *st)
+{
+	bcm3510_register_value b;
+	int ret;
+
+	if ((ret = bcm3510_readB(st,0xfa,&b)) < 0)
+		return ret;
+
+	b.BERCTL_fa.RESYNC = 0; bcm3510_writeB(st,0xfa,b);
+	b.BERCTL_fa.RESYNC = 1; bcm3510_writeB(st,0xfa,b);
+	b.BERCTL_fa.RESYNC = 0; bcm3510_writeB(st,0xfa,b);
+	b.BERCTL_fa.CNTCTL = 1; b.BERCTL_fa.BITCNT = 1; bcm3510_writeB(st,0xfa,b);
+
+	/* clear residual bit counter TODO  */
+	return 0;
+}
+
+static int bcm3510_refresh_state(struct bcm3510_state *st)
+{
+	if (time_after(jiffies,st->next_status_check)) {
+		bcm3510_do_hab_cmd(st, CMD_STATUS, MSGID_STATUS1, NULL,0, (u8 *)&st->status1, sizeof(st->status1));
+		bcm3510_do_hab_cmd(st, CMD_STATUS, MSGID_STATUS2, NULL,0, (u8 *)&st->status2, sizeof(st->status2));
+		st->next_status_check = jiffies + (st->status_check_interval*HZ)/1000;
+	}
+	return 0;
+}
+
+static int bcm3510_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+	struct bcm3510_state* st = fe->demodulator_priv;
+	bcm3510_refresh_state(st);
+
+	*status = 0;
+	if (st->status1.STATUS1.RECEIVER_LOCK)
+		*status |= FE_HAS_LOCK | FE_HAS_SYNC;
+
+	if (st->status1.STATUS1.FEC_LOCK)
+		*status |= FE_HAS_VITERBI;
+
+	if (st->status1.STATUS1.OUT_PLL_LOCK)
+		*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER;
+
+	if (*status & FE_HAS_LOCK)
+		st->status_check_interval = 1500;
+	else /* more frequently checks if no lock has been achieved yet */
+		st->status_check_interval = 500;
+
+	deb_info("real_status: %02x\n",*status);
+	return 0;
+}
+
+static int bcm3510_read_ber(struct dvb_frontend* fe, u32* ber)
+{
+	struct bcm3510_state* st = fe->demodulator_priv;
+	bcm3510_refresh_state(st);
+
+	*ber = (st->status2.LDBER0 << 16) | (st->status2.LDBER1 << 8) | st->status2.LDBER2;
+	return 0;
+}
+
+static int bcm3510_read_unc(struct dvb_frontend* fe, u32* unc)
+{
+	struct bcm3510_state* st = fe->demodulator_priv;
+	bcm3510_refresh_state(st);
+	*unc = (st->status2.LDUERC0 << 8) | st->status2.LDUERC1;
+	return 0;
+}
+
+static int bcm3510_read_signal_strength(struct dvb_frontend* fe, u16* strength)
+{
+	struct bcm3510_state* st = fe->demodulator_priv;
+	s32 t;
+
+	bcm3510_refresh_state(st);
+	t = st->status2.SIGNAL;
+
+	if (t > 190)
+		t = 190;
+	if (t < 90)
+		t = 90;
+
+	t -= 90;
+	t = t * 0xff / 100;
+	/* normalize if necessary */
+	*strength = (t << 8) | t;
+	return 0;
+}
+
+static int bcm3510_read_snr(struct dvb_frontend* fe, u16* snr)
+{
+	struct bcm3510_state* st = fe->demodulator_priv;
+	bcm3510_refresh_state(st);
+
+	*snr = st->status1.SNR_EST0*1000 + ((st->status1.SNR_EST1*1000) >> 8);
+	return 0;
+}
+
+/* tuner frontend programming */
+static int bcm3510_tuner_cmd(struct bcm3510_state* st,u8 bc, u16 n, u8 a)
+{
+	struct bcm3510_hab_cmd_tune c;
+	memset(&c,0,sizeof(struct bcm3510_hab_cmd_tune));
+
+/* I2C Mode disabled,  set 16 control / Data pairs */
+	c.length = 0x10;
+	c.clock_width = 0;
+/* CS1, CS0, DATA, CLK bits control the tuner RF_AGC_SEL pin is set to
+ * logic high (as Configuration) */
+	c.misc = 0x10;
+/* Set duration of the initial state of TUNCTL = 3.34 micro Sec */
+	c.TUNCTL_state = 0x40;
+
+/* PRESCALER DIVIDE RATIO | BC1_2_3_4; (band switch), 1stosc REFERENCE COUNTER REF_S12 and REF_S11 */
+	c.ctl_dat[0].ctrl.size = BITS_8;
+	c.ctl_dat[0].data      = 0x80 | bc;
+
+/* Control DATA pin, 1stosc REFERENCE COUNTER REF_S10 to REF_S3 */
+	c.ctl_dat[1].ctrl.size = BITS_8;
+	c.ctl_dat[1].data      = 4;
+
+/* set CONTROL BIT 1 to 1, 1stosc REFERENCE COUNTER REF_S2 to REF_S1 */
+	c.ctl_dat[2].ctrl.size = BITS_3;
+	c.ctl_dat[2].data      = 0x20;
+
+/* control CS0 pin, pulse byte ? */
+	c.ctl_dat[3].ctrl.size = BITS_3;
+	c.ctl_dat[3].ctrl.clk_off = 1;
+	c.ctl_dat[3].ctrl.cs0  = 1;
+	c.ctl_dat[3].data      = 0x40;
+
+/* PGM_S18 to PGM_S11 */
+	c.ctl_dat[4].ctrl.size = BITS_8;
+	c.ctl_dat[4].data      = n >> 3;
+
+/* PGM_S10 to PGM_S8, SWL_S7 to SWL_S3 */
+	c.ctl_dat[5].ctrl.size = BITS_8;
+	c.ctl_dat[5].data      = ((n & 0x7) << 5) | (a >> 2);
+
+/* SWL_S2 and SWL_S1, set CONTROL BIT 2 to 0 */
+	c.ctl_dat[6].ctrl.size = BITS_3;
+	c.ctl_dat[6].data      = (a << 6) & 0xdf;
+
+/* control CS0 pin, pulse byte ? */
+	c.ctl_dat[7].ctrl.size = BITS_3;
+	c.ctl_dat[7].ctrl.clk_off = 1;
+	c.ctl_dat[7].ctrl.cs0  = 1;
+	c.ctl_dat[7].data      = 0x40;
+
+/* PRESCALER DIVIDE RATIO, 2ndosc REFERENCE COUNTER REF_S12 and REF_S11 */
+	c.ctl_dat[8].ctrl.size = BITS_8;
+	c.ctl_dat[8].data      = 0x80;
+
+/* 2ndosc REFERENCE COUNTER REF_S10 to REF_S3 */
+	c.ctl_dat[9].ctrl.size = BITS_8;
+	c.ctl_dat[9].data      = 0x10;
+
+/* set CONTROL BIT 1 to 1, 2ndosc REFERENCE COUNTER REF_S2 to REF_S1 */
+	c.ctl_dat[10].ctrl.size = BITS_3;
+	c.ctl_dat[10].data      = 0x20;
+
+/* pulse byte */
+	c.ctl_dat[11].ctrl.size = BITS_3;
+	c.ctl_dat[11].ctrl.clk_off = 1;
+	c.ctl_dat[11].ctrl.cs1  = 1;
+	c.ctl_dat[11].data      = 0x40;
+
+/* PGM_S18 to PGM_S11 */
+	c.ctl_dat[12].ctrl.size = BITS_8;
+	c.ctl_dat[12].data      = 0x2a;
+
+/* PGM_S10 to PGM_S8 and SWL_S7 to SWL_S3 */
+	c.ctl_dat[13].ctrl.size = BITS_8;
+	c.ctl_dat[13].data      = 0x8e;
+
+/* SWL_S2 and SWL_S1 and set CONTROL BIT 2 to 0 */
+	c.ctl_dat[14].ctrl.size = BITS_3;
+	c.ctl_dat[14].data      = 0;
+
+/* Pulse Byte */
+	c.ctl_dat[15].ctrl.size = BITS_3;
+	c.ctl_dat[15].ctrl.clk_off = 1;
+	c.ctl_dat[15].ctrl.cs1  = 1;
+	c.ctl_dat[15].data      = 0x40;
+
+	return bcm3510_do_hab_cmd(st,CMD_TUNE, MSGID_TUNE,(u8 *) &c,sizeof(c), NULL, 0);
+}
+
+static int bcm3510_set_freq(struct bcm3510_state* st,u32 freq)
+{
+	u8 bc,a;
+	u16 n;
+	s32 YIntercept,Tfvco1;
+
+	freq /= 1000;
+
+	deb_info("%dkHz:",freq);
+	/* set Band Switch */
+	if (freq <= 168000)
+		bc = 0x1c;
+	else if (freq <= 378000)
+		bc = 0x2c;
+	else
+		bc = 0x30;
+
+	if (freq >= 470000) {
+		freq -= 470001;
+		YIntercept = 18805;
+	} else if (freq >= 90000) {
+		freq -= 90001;
+		YIntercept = 15005;
+	} else if (freq >= 76000){
+		freq -= 76001;
+		YIntercept = 14865;
+	} else {
+		freq -= 54001;
+		YIntercept = 14645;
+	}
+
+	Tfvco1 = (((freq/6000)*60 + YIntercept)*4)/10;
+
+	n = Tfvco1 >> 6;
+	a = Tfvco1 & 0x3f;
+
+	deb_info(" BC1_2_3_4: %x, N: %x A: %x\n", bc, n, a);
+	if (n >= 16 && n <= 2047)
+		return bcm3510_tuner_cmd(st,bc,n,a);
+
+	return -EINVAL;
+}
+
+static int bcm3510_set_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	struct bcm3510_state* st = fe->demodulator_priv;
+	struct bcm3510_hab_cmd_ext_acquire cmd;
+	struct bcm3510_hab_cmd_bert_control bert;
+	int ret;
+
+	memset(&cmd,0,sizeof(cmd));
+	switch (c->modulation) {
+		case QAM_256:
+			cmd.ACQUIRE0.MODE = 0x1;
+			cmd.ACQUIRE1.SYM_RATE = 0x1;
+			cmd.ACQUIRE1.IF_FREQ = 0x1;
+			break;
+		case QAM_64:
+			cmd.ACQUIRE0.MODE = 0x2;
+			cmd.ACQUIRE1.SYM_RATE = 0x2;
+			cmd.ACQUIRE1.IF_FREQ = 0x1;
+			break;
+#if 0
+		case QAM_256:
+			cmd.ACQUIRE0.MODE = 0x3;
+			break;
+		case QAM_128:
+			cmd.ACQUIRE0.MODE = 0x4;
+			break;
+		case QAM_64:
+			cmd.ACQUIRE0.MODE = 0x5;
+			break;
+		case QAM_32:
+			cmd.ACQUIRE0.MODE = 0x6;
+			break;
+		case QAM_16:
+			cmd.ACQUIRE0.MODE = 0x7;
+			break;
+#endif
+		case VSB_8:
+			cmd.ACQUIRE0.MODE = 0x8;
+			cmd.ACQUIRE1.SYM_RATE = 0x0;
+			cmd.ACQUIRE1.IF_FREQ = 0x0;
+			break;
+		case VSB_16:
+			cmd.ACQUIRE0.MODE = 0x9;
+			cmd.ACQUIRE1.SYM_RATE = 0x0;
+			cmd.ACQUIRE1.IF_FREQ = 0x0;
+		default:
+			return -EINVAL;
+	};
+	cmd.ACQUIRE0.OFFSET = 0;
+	cmd.ACQUIRE0.NTSCSWEEP = 1;
+	cmd.ACQUIRE0.FA = 1;
+	cmd.ACQUIRE0.BW = 0;
+
+/*	if (enableOffset) {
+		cmd.IF_OFFSET0 = xx;
+		cmd.IF_OFFSET1 = xx;
+
+		cmd.SYM_OFFSET0 = xx;
+		cmd.SYM_OFFSET1 = xx;
+		if (enableNtscSweep) {
+			cmd.NTSC_OFFSET0;
+			cmd.NTSC_OFFSET1;
+		}
+	} */
+	bcm3510_do_hab_cmd(st, CMD_ACQUIRE, MSGID_EXT_TUNER_ACQUIRE, (u8 *) &cmd, sizeof(cmd), NULL, 0);
+
+/* doing it with different MSGIDs, data book and source differs */
+	bert.BE = 0;
+	bert.unused = 0;
+	bcm3510_do_hab_cmd(st, CMD_STATE_CONTROL, MSGID_BERT_CONTROL, (u8 *) &bert, sizeof(bert), NULL, 0);
+	bcm3510_do_hab_cmd(st, CMD_STATE_CONTROL, MSGID_BERT_SET, (u8 *) &bert, sizeof(bert), NULL, 0);
+
+	bcm3510_bert_reset(st);
+
+	ret = bcm3510_set_freq(st, c->frequency);
+	if (ret < 0)
+		return ret;
+
+	memset(&st->status1,0,sizeof(st->status1));
+	memset(&st->status2,0,sizeof(st->status2));
+	st->status_check_interval = 500;
+
+/* Give the AP some time */
+	msleep(200);
+
+	return 0;
+}
+
+static int bcm3510_sleep(struct dvb_frontend* fe)
+{
+	return 0;
+}
+
+static int bcm3510_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings *s)
+{
+	s->min_delay_ms = 1000;
+	s->step_size = 0;
+	s->max_drift = 0;
+	return 0;
+}
+
+static void bcm3510_release(struct dvb_frontend* fe)
+{
+	struct bcm3510_state* state = fe->demodulator_priv;
+	kfree(state);
+}
+
+/* firmware download:
+ * firmware file is build up like this:
+ * 16bit addr, 16bit length, 8byte of length
+ */
+#define BCM3510_DEFAULT_FIRMWARE "dvb-fe-bcm3510-01.fw"
+
+static int bcm3510_write_ram(struct bcm3510_state *st, u16 addr, const u8 *b,
+			     u16 len)
+{
+	int ret = 0,i;
+	bcm3510_register_value vH, vL,vD;
+
+	vH.MADRH_a9 = addr >> 8;
+	vL.MADRL_aa = addr;
+	if ((ret = bcm3510_writeB(st,0xa9,vH)) < 0) return ret;
+	if ((ret = bcm3510_writeB(st,0xaa,vL)) < 0) return ret;
+
+	for (i = 0; i < len; i++) {
+		vD.MDATA_ab = b[i];
+		if ((ret = bcm3510_writeB(st,0xab,vD)) < 0)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int bcm3510_download_firmware(struct dvb_frontend* fe)
+{
+	struct bcm3510_state* st = fe->demodulator_priv;
+	const struct firmware *fw;
+	u16 addr,len;
+	const u8 *b;
+	int ret,i;
+
+	deb_info("requesting firmware\n");
+	if ((ret = st->config->request_firmware(fe, &fw, BCM3510_DEFAULT_FIRMWARE)) < 0) {
+		err("could not load firmware (%s): %d",BCM3510_DEFAULT_FIRMWARE,ret);
+		return ret;
+	}
+	deb_info("got firmware: %zd\n",fw->size);
+
+	b = fw->data;
+	for (i = 0; i < fw->size;) {
+		addr = le16_to_cpu( *( (u16 *)&b[i] ) );
+		len  = le16_to_cpu( *( (u16 *)&b[i+2] ) );
+		deb_info("firmware chunk, addr: 0x%04x, len: 0x%04x, total length: 0x%04zx\n",addr,len,fw->size);
+		if ((ret = bcm3510_write_ram(st,addr,&b[i+4],len)) < 0) {
+			err("firmware download failed: %d\n",ret);
+			return ret;
+		}
+		i += 4 + len;
+	}
+	release_firmware(fw);
+	deb_info("firmware download successfully completed\n");
+	return 0;
+}
+
+static int bcm3510_check_firmware_version(struct bcm3510_state *st)
+{
+	struct bcm3510_hab_cmd_get_version_info ver;
+	bcm3510_do_hab_cmd(st,CMD_GET_VERSION_INFO,MSGID_GET_VERSION_INFO,NULL,0,(u8*)&ver,sizeof(ver));
+
+	deb_info("Version information: 0x%02x 0x%02x 0x%02x 0x%02x\n",
+		ver.microcode_version, ver.script_version, ver.config_version, ver.demod_version);
+
+	if (ver.script_version == BCM3510_DEF_SCRIPT_VERSION &&
+		ver.config_version == BCM3510_DEF_CONFIG_VERSION &&
+		ver.demod_version  == BCM3510_DEF_DEMOD_VERSION)
+		return 0;
+
+	deb_info("version check failed\n");
+	return -ENODEV;
+}
+
+/* (un)resetting the AP */
+static int bcm3510_reset(struct bcm3510_state *st)
+{
+	int ret;
+	unsigned long  t;
+	bcm3510_register_value v;
+
+	bcm3510_readB(st,0xa0,&v); v.HCTL1_a0.RESET = 1;
+	if ((ret = bcm3510_writeB(st,0xa0,v)) < 0)
+		return ret;
+
+    t = jiffies + 3*HZ;
+	while (time_before(jiffies, t)) {
+		msleep(10);
+		if ((ret = bcm3510_readB(st,0xa2,&v)) < 0)
+			return ret;
+
+		if (v.APSTAT1_a2.RESET)
+			return 0;
+	}
+	deb_info("reset timed out\n");
+	return -ETIMEDOUT;
+}
+
+static int bcm3510_clear_reset(struct bcm3510_state *st)
+{
+	bcm3510_register_value v;
+	int ret;
+	unsigned long t;
+
+	v.raw = 0;
+	if ((ret = bcm3510_writeB(st,0xa0,v)) < 0)
+		return ret;
+
+    t = jiffies + 3*HZ;
+	while (time_before(jiffies, t)) {
+		msleep(10);
+		if ((ret = bcm3510_readB(st,0xa2,&v)) < 0)
+			return ret;
+
+		/* verify that reset is cleared */
+		if (!v.APSTAT1_a2.RESET)
+			return 0;
+	}
+	deb_info("reset clear timed out\n");
+	return -ETIMEDOUT;
+}
+
+static int bcm3510_init_cold(struct bcm3510_state *st)
+{
+	int ret;
+	bcm3510_register_value v;
+
+	/* read Acquisation Processor status register and check it is not in RUN mode */
+	if ((ret = bcm3510_readB(st,0xa2,&v)) < 0)
+		return ret;
+	if (v.APSTAT1_a2.RUN) {
+		deb_info("AP is already running - firmware already loaded.\n");
+		return 0;
+	}
+
+	deb_info("reset?\n");
+	if ((ret = bcm3510_reset(st)) < 0)
+		return ret;
+
+	deb_info("tristate?\n");
+	/* tri-state */
+	v.TSTCTL_2e.CTL = 0;
+	if ((ret = bcm3510_writeB(st,0x2e,v)) < 0)
+		return ret;
+
+	deb_info("firmware?\n");
+	if ((ret = bcm3510_download_firmware(&st->frontend)) < 0 ||
+		(ret = bcm3510_clear_reset(st)) < 0)
+		return ret;
+
+	/* anything left here to Let the acquisition processor begin execution at program counter 0000 ??? */
+
+	return 0;
+}
+
+static int bcm3510_init(struct dvb_frontend* fe)
+{
+	struct bcm3510_state* st = fe->demodulator_priv;
+	bcm3510_register_value j;
+	struct bcm3510_hab_cmd_set_agc c;
+	int ret;
+
+	if ((ret = bcm3510_readB(st,0xca,&j)) < 0)
+		return ret;
+
+	deb_info("JDEC: %02x\n",j.raw);
+
+	switch (j.JDEC_ca.JDEC) {
+		case JDEC_WAIT_AT_RAM:
+			deb_info("attempting to download firmware\n");
+			if ((ret = bcm3510_init_cold(st)) < 0)
+				return ret;
+		case JDEC_EEPROM_LOAD_WAIT: /* fall-through is wanted */
+			deb_info("firmware is loaded\n");
+			bcm3510_check_firmware_version(st);
+			break;
+		default:
+			return -ENODEV;
+	}
+
+	memset(&c,0,1);
+	c.SEL = 1;
+	bcm3510_do_hab_cmd(st,CMD_AUTO_PARAM,MSGID_SET_RF_AGC_SEL,(u8 *)&c,sizeof(c),NULL,0);
+
+	return 0;
+}
+
+
+static struct dvb_frontend_ops bcm3510_ops;
+
+struct dvb_frontend* bcm3510_attach(const struct bcm3510_config *config,
+				   struct i2c_adapter *i2c)
+{
+	struct bcm3510_state* state = NULL;
+	int ret;
+	bcm3510_register_value v;
+
+	/* allocate memory for the internal state */
+	state = kzalloc(sizeof(struct bcm3510_state), GFP_KERNEL);
+	if (state == NULL)
+		goto error;
+
+	/* setup the state */
+
+	state->config = config;
+	state->i2c = i2c;
+
+	/* create dvb_frontend */
+	memcpy(&state->frontend.ops, &bcm3510_ops, sizeof(struct dvb_frontend_ops));
+	state->frontend.demodulator_priv = state;
+
+	mutex_init(&state->hab_mutex);
+
+	if ((ret = bcm3510_readB(state,0xe0,&v)) < 0)
+		goto error;
+
+	deb_info("Revision: 0x%1x, Layer: 0x%1x.\n",v.REVID_e0.REV,v.REVID_e0.LAYER);
+
+	if ((v.REVID_e0.REV != 0x1 && v.REVID_e0.LAYER != 0xb) && /* cold */
+		(v.REVID_e0.REV != 0x8 && v.REVID_e0.LAYER != 0x0))   /* warm */
+		goto error;
+
+	info("Revision: 0x%1x, Layer: 0x%1x.",v.REVID_e0.REV,v.REVID_e0.LAYER);
+
+	bcm3510_reset(state);
+
+	return &state->frontend;
+
+error:
+	kfree(state);
+	return NULL;
+}
+EXPORT_SYMBOL(bcm3510_attach);
+
+static struct dvb_frontend_ops bcm3510_ops = {
+	.delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
+	.info = {
+		.name = "Broadcom BCM3510 VSB/QAM frontend",
+		.frequency_min =  54000000,
+		.frequency_max = 803000000,
+		/* stepsize is just a guess */
+		.frequency_stepsize = 0,
+		.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_FEC_AUTO |
+			FE_CAN_8VSB | FE_CAN_16VSB |
+			FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_128 | FE_CAN_QAM_256
+	},
+
+	.release = bcm3510_release,
+
+	.init = bcm3510_init,
+	.sleep = bcm3510_sleep,
+
+	.set_frontend = bcm3510_set_frontend,
+	.get_tune_settings = bcm3510_get_tune_settings,
+
+	.read_status = bcm3510_read_status,
+	.read_ber = bcm3510_read_ber,
+	.read_signal_strength = bcm3510_read_signal_strength,
+	.read_snr = bcm3510_read_snr,
+	.read_ucblocks = bcm3510_read_unc,
+};
+
+MODULE_DESCRIPTION("Broadcom BCM3510 ATSC (8VSB/16VSB & ITU J83 AnnexB FEC QAM64/256) demodulator driver");
+MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb-frontends/bcm3510.h b/drivers/media/dvb-frontends/bcm3510.h
new file mode 100644
index 0000000..f4575c0
--- /dev/null
+++ b/drivers/media/dvb-frontends/bcm3510.h
@@ -0,0 +1,49 @@
+/*
+ * Support for the Broadcom BCM3510 ATSC demodulator (1st generation Air2PC)
+ *
+ *  Copyright (C) 2001-5, B2C2 inc.
+ *
+ *  GPL/Linux driver written by Patrick Boettcher <patrick.boettcher@desy.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 BCM3510_H
+#define BCM3510_H
+
+#include <linux/dvb/frontend.h>
+#include <linux/firmware.h>
+
+struct bcm3510_config
+{
+	/* the demodulator's i2c address */
+	u8 demod_address;
+
+	/* request firmware for device */
+	int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name);
+};
+
+#if defined(CONFIG_DVB_BCM3510) || (defined(CONFIG_DVB_BCM3510_MODULE) && defined(MODULE))
+extern struct dvb_frontend* bcm3510_attach(const struct bcm3510_config* config,
+					   struct i2c_adapter* i2c);
+#else
+static inline struct dvb_frontend* bcm3510_attach(const struct bcm3510_config* config,
+						  struct i2c_adapter* i2c)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif // CONFIG_DVB_BCM3510
+
+#endif
diff --git a/drivers/media/dvb-frontends/bcm3510_priv.h b/drivers/media/dvb-frontends/bcm3510_priv.h
new file mode 100644
index 0000000..3bb1bc2
--- /dev/null
+++ b/drivers/media/dvb-frontends/bcm3510_priv.h
@@ -0,0 +1,460 @@
+/*
+ * Support for the Broadcom BCM3510 ATSC demodulator (1st generation Air2PC)
+ *
+ *  Copyright (C) 2001-5, B2C2 inc.
+ *
+ *  GPL/Linux driver written by Patrick Boettcher <patrick.boettcher@desy.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 __BCM3510_PRIV_H__
+#define __BCM3510_PRIV_H__
+
+#define PACKED __attribute__((packed))
+
+#undef err
+#define err(format, arg...)  printk(KERN_ERR     "bcm3510: " format "\n" , ## arg)
+#undef info
+#define info(format, arg...) printk(KERN_INFO    "bcm3510: " format "\n" , ## arg)
+#undef warn
+#define warn(format, arg...) printk(KERN_WARNING "bcm3510: " format "\n" , ## arg)
+
+
+#define PANASONIC_FIRST_IF_BASE_IN_KHz  1407500
+#define BCM3510_SYMBOL_RATE             5381000
+
+typedef union {
+	u8 raw;
+
+	struct {
+		u8 CTL   :8;
+	} TSTCTL_2e;
+
+	u8 LDCERC_4e;
+	u8 LDUERC_4f;
+	u8 LD_BER0_65;
+	u8 LD_BER1_66;
+	u8 LD_BER2_67;
+	u8 LD_BER3_68;
+
+	struct {
+		u8 RESET :1;
+		u8 IDLE  :1;
+		u8 STOP  :1;
+		u8 HIRQ0 :1;
+		u8 HIRQ1 :1;
+		u8 na0   :1;
+		u8 HABAV :1;
+		u8 na1   :1;
+	} HCTL1_a0;
+
+	struct {
+		u8 na0    :1;
+		u8 IDLMSK :1;
+		u8 STMSK  :1;
+		u8 I0MSK  :1;
+		u8 I1MSK  :1;
+		u8 na1    :1;
+		u8 HABMSK :1;
+		u8 na2    :1;
+	} HCTLMSK_a1;
+
+	struct {
+		u8 RESET  :1;
+		u8 IDLE   :1;
+		u8 STOP   :1;
+		u8 RUN    :1;
+		u8 HABAV  :1;
+		u8 MEMAV  :1;
+		u8 ALDONE :1;
+		u8 REIRQ  :1;
+	} APSTAT1_a2;
+
+	struct {
+		u8 RSTMSK :1;
+		u8 IMSK   :1;
+		u8 SMSK   :1;
+		u8 RMSK   :1;
+		u8 HABMSK :1;
+		u8 MAVMSK :1;
+		u8 ALDMSK :1;
+		u8 REMSK  :1;
+	} APMSK1_a3;
+
+	u8 APSTAT2_a4;
+	u8 APMSK2_a5;
+
+	struct {
+		u8 HABADR :7;
+		u8 na     :1;
+	} HABADR_a6;
+
+	u8 HABDATA_a7;
+
+	struct {
+		u8 HABR   :1;
+		u8 LDHABR :1;
+		u8 APMSK  :1;
+		u8 HMSK   :1;
+		u8 LDMSK  :1;
+		u8 na     :3;
+	} HABSTAT_a8;
+
+	u8 MADRH_a9;
+	u8 MADRL_aa;
+	u8 MDATA_ab;
+
+	struct {
+#define JDEC_WAIT_AT_RAM      0x7
+#define JDEC_EEPROM_LOAD_WAIT 0x4
+		u8 JDEC   :3;
+		u8 na     :5;
+	} JDEC_ca;
+
+	struct {
+		u8 REV   :4;
+		u8 LAYER :4;
+	} REVID_e0;
+
+	struct {
+		u8 unk0   :1;
+		u8 CNTCTL :1;
+		u8 BITCNT :1;
+		u8 unk1   :1;
+		u8 RESYNC :1;
+		u8 unk2   :3;
+	} BERCTL_fa;
+
+	struct {
+		u8 CSEL0  :1;
+		u8 CLKED0 :1;
+		u8 CSEL1  :1;
+		u8 CLKED1 :1;
+		u8 CLKLEV :1;
+		u8 SPIVAR :1;
+		u8 na     :2;
+	} TUNSET_fc;
+
+	struct {
+		u8 CLK    :1;
+		u8 DATA   :1;
+		u8 CS0    :1;
+		u8 CS1    :1;
+		u8 AGCSEL :1;
+		u8 na0    :1;
+		u8 TUNSEL :1;
+		u8 na1    :1;
+	} TUNCTL_fd;
+
+	u8 TUNSEL0_fe;
+	u8 TUNSEL1_ff;
+
+} bcm3510_register_value;
+
+/* HAB commands */
+
+/* version */
+#define CMD_GET_VERSION_INFO   0x3D
+#define MSGID_GET_VERSION_INFO 0x15
+struct bcm3510_hab_cmd_get_version_info {
+	u8 microcode_version;
+	u8 script_version;
+	u8 config_version;
+	u8 demod_version;
+} PACKED;
+
+#define BCM3510_DEF_MICROCODE_VERSION 0x0E
+#define BCM3510_DEF_SCRIPT_VERSION    0x06
+#define BCM3510_DEF_CONFIG_VERSION    0x01
+#define BCM3510_DEF_DEMOD_VERSION     0xB1
+
+/* acquire */
+#define CMD_ACQUIRE            0x38
+
+#define MSGID_EXT_TUNER_ACQUIRE 0x0A
+struct bcm3510_hab_cmd_ext_acquire {
+	struct {
+		u8 MODE      :4;
+		u8 BW        :1;
+		u8 FA        :1;
+		u8 NTSCSWEEP :1;
+		u8 OFFSET    :1;
+	} PACKED ACQUIRE0; /* control_byte */
+
+	struct {
+		u8 IF_FREQ  :3;
+		u8 zero0    :1;
+		u8 SYM_RATE :3;
+		u8 zero1    :1;
+	} PACKED ACQUIRE1; /* sym_if */
+
+	u8 IF_OFFSET0;   /* IF_Offset_10hz */
+	u8 IF_OFFSET1;
+	u8 SYM_OFFSET0;  /* SymbolRateOffset */
+	u8 SYM_OFFSET1;
+	u8 NTSC_OFFSET0; /* NTSC_Offset_10hz */
+	u8 NTSC_OFFSET1;
+} PACKED;
+
+#define MSGID_INT_TUNER_ACQUIRE 0x0B
+struct bcm3510_hab_cmd_int_acquire {
+	struct {
+		u8 MODE      :4;
+		u8 BW        :1;
+		u8 FA        :1;
+		u8 NTSCSWEEP :1;
+		u8 OFFSET    :1;
+	} PACKED ACQUIRE0; /* control_byte */
+
+	struct {
+		u8 IF_FREQ  :3;
+		u8 zero0    :1;
+		u8 SYM_RATE :3;
+		u8 zero1    :1;
+	} PACKED ACQUIRE1; /* sym_if */
+
+	u8 TUNER_FREQ0;
+	u8 TUNER_FREQ1;
+	u8 TUNER_FREQ2;
+	u8 TUNER_FREQ3;
+	u8 IF_OFFSET0;   /* IF_Offset_10hz */
+	u8 IF_OFFSET1;
+	u8 SYM_OFFSET0;  /* SymbolRateOffset */
+	u8 SYM_OFFSET1;
+	u8 NTSC_OFFSET0; /* NTSC_Offset_10hz */
+	u8 NTSC_OFFSET1;
+} PACKED;
+
+/* modes */
+#define BCM3510_QAM16           =   0x01
+#define BCM3510_QAM32           =   0x02
+#define BCM3510_QAM64           =   0x03
+#define BCM3510_QAM128          =   0x04
+#define BCM3510_QAM256          =   0x05
+#define BCM3510_8VSB            =   0x0B
+#define BCM3510_16VSB           =   0x0D
+
+/* IF_FREQS */
+#define BCM3510_IF_TERRESTRIAL 0x0
+#define BCM3510_IF_CABLE       0x1
+#define BCM3510_IF_USE_CMD     0x7
+
+/* SYM_RATE */
+#define BCM3510_SR_8VSB        0x0 /* 5381119 s/sec */
+#define BCM3510_SR_256QAM      0x1 /* 5360537 s/sec */
+#define BCM3510_SR_16QAM       0x2 /* 5056971 s/sec */
+#define BCM3510_SR_MISC        0x3 /* 5000000 s/sec */
+#define BCM3510_SR_USE_CMD     0x7
+
+/* special symbol rate */
+#define CMD_SET_VALUE_NOT_LISTED  0x2d
+#define MSGID_SET_SYMBOL_RATE_NOT_LISTED 0x0c
+struct bcm3510_hab_cmd_set_sr_not_listed {
+	u8 HOST_SYM_RATE0;
+	u8 HOST_SYM_RATE1;
+	u8 HOST_SYM_RATE2;
+	u8 HOST_SYM_RATE3;
+} PACKED;
+
+/* special IF */
+#define MSGID_SET_IF_FREQ_NOT_LISTED 0x0d
+struct bcm3510_hab_cmd_set_if_freq_not_listed {
+	u8 HOST_IF_FREQ0;
+	u8 HOST_IF_FREQ1;
+	u8 HOST_IF_FREQ2;
+	u8 HOST_IF_FREQ3;
+} PACKED;
+
+/* auto reacquire */
+#define CMD_AUTO_PARAM       0x2a
+#define MSGID_AUTO_REACQUIRE 0x0e
+struct bcm3510_hab_cmd_auto_reacquire {
+	u8 ACQ    :1; /* on/off*/
+	u8 unused :7;
+} PACKED;
+
+#define MSGID_SET_RF_AGC_SEL 0x12
+struct bcm3510_hab_cmd_set_agc {
+	u8 LVL    :1;
+	u8 unused :6;
+	u8 SEL    :1;
+} PACKED;
+
+#define MSGID_SET_AUTO_INVERSION 0x14
+struct bcm3510_hab_cmd_auto_inversion {
+	u8 AI     :1;
+	u8 unused :7;
+} PACKED;
+
+
+/* bert control */
+#define CMD_STATE_CONTROL  0x12
+#define MSGID_BERT_CONTROL 0x0e
+#define MSGID_BERT_SET     0xfa
+struct bcm3510_hab_cmd_bert_control {
+	u8 BE     :1;
+	u8 unused :7;
+} PACKED;
+
+#define MSGID_TRI_STATE 0x2e
+struct bcm3510_hab_cmd_tri_state {
+	u8 RE :1; /* a/d ram port pins */
+	u8 PE :1; /* baud clock pin */
+	u8 AC :1; /* a/d clock pin */
+	u8 BE :1; /* baud clock pin */
+	u8 unused :4;
+} PACKED;
+
+
+/* tune */
+#define CMD_TUNE   0x38
+#define MSGID_TUNE 0x16
+struct bcm3510_hab_cmd_tune_ctrl_data_pair {
+	struct {
+#define BITS_8 0x07
+#define BITS_7 0x06
+#define BITS_6 0x05
+#define BITS_5 0x04
+#define BITS_4 0x03
+#define BITS_3 0x02
+#define BITS_2 0x01
+#define BITS_1 0x00
+		u8 size    :3;
+		u8 unk     :2;
+		u8 clk_off :1;
+		u8 cs0     :1;
+		u8 cs1     :1;
+
+	} PACKED ctrl;
+
+	u8 data;
+} PACKED;
+
+struct bcm3510_hab_cmd_tune {
+	u8 length;
+	u8 clock_width;
+	u8 misc;
+	u8 TUNCTL_state;
+
+	struct bcm3510_hab_cmd_tune_ctrl_data_pair ctl_dat[16];
+} PACKED;
+
+#define CMD_STATUS    0x38
+#define MSGID_STATUS1 0x08
+struct bcm3510_hab_cmd_status1 {
+	struct {
+		u8 EQ_MODE       :4;
+		u8 reserved      :2;
+		u8 QRE           :1; /* if QSE and the spectrum is inversed */
+		u8 QSE           :1; /* automatic spectral inversion */
+	} PACKED STATUS0;
+
+	struct {
+		u8 RECEIVER_LOCK :1;
+		u8 FEC_LOCK      :1;
+		u8 OUT_PLL_LOCK  :1;
+		u8 reserved      :5;
+	} PACKED STATUS1;
+
+	struct {
+		u8 reserved      :2;
+		u8 BW            :1;
+		u8 NTE           :1; /* NTSC filter sweep enabled */
+		u8 AQI           :1; /* currently acquiring */
+		u8 FA            :1; /* fast acquisition */
+		u8 ARI           :1; /* auto reacquire */
+		u8 TI            :1; /* programming the tuner */
+	} PACKED STATUS2;
+	u8 STATUS3;
+	u8 SNR_EST0;
+	u8 SNR_EST1;
+	u8 TUNER_FREQ0;
+	u8 TUNER_FREQ1;
+	u8 TUNER_FREQ2;
+	u8 TUNER_FREQ3;
+	u8 SYM_RATE0;
+	u8 SYM_RATE1;
+	u8 SYM_RATE2;
+	u8 SYM_RATE3;
+	u8 SYM_OFFSET0;
+	u8 SYM_OFFSET1;
+	u8 SYM_ERROR0;
+	u8 SYM_ERROR1;
+	u8 IF_FREQ0;
+	u8 IF_FREQ1;
+	u8 IF_FREQ2;
+	u8 IF_FREQ3;
+	u8 IF_OFFSET0;
+	u8 IF_OFFSET1;
+	u8 IF_ERROR0;
+	u8 IF_ERROR1;
+	u8 NTSC_FILTER0;
+	u8 NTSC_FILTER1;
+	u8 NTSC_FILTER2;
+	u8 NTSC_FILTER3;
+	u8 NTSC_OFFSET0;
+	u8 NTSC_OFFSET1;
+	u8 NTSC_ERROR0;
+	u8 NTSC_ERROR1;
+	u8 INT_AGC_LEVEL0;
+	u8 INT_AGC_LEVEL1;
+	u8 EXT_AGC_LEVEL0;
+	u8 EXT_AGC_LEVEL1;
+} PACKED;
+
+#define MSGID_STATUS2 0x14
+struct bcm3510_hab_cmd_status2 {
+	struct {
+		u8 EQ_MODE  :4;
+		u8 reserved :2;
+		u8 QRE      :1;
+		u8 QSR      :1;
+	} PACKED STATUS0;
+	struct {
+		u8 RL       :1;
+		u8 FL       :1;
+		u8 OL       :1;
+		u8 reserved :5;
+	} PACKED STATUS1;
+	u8 SYMBOL_RATE0;
+	u8 SYMBOL_RATE1;
+	u8 SYMBOL_RATE2;
+	u8 SYMBOL_RATE3;
+	u8 LDCERC0;
+	u8 LDCERC1;
+	u8 LDCERC2;
+	u8 LDCERC3;
+	u8 LDUERC0;
+	u8 LDUERC1;
+	u8 LDUERC2;
+	u8 LDUERC3;
+	u8 LDBER0;
+	u8 LDBER1;
+	u8 LDBER2;
+	u8 LDBER3;
+	struct {
+		u8 MODE_TYPE :4; /* acquire mode 0 */
+		u8 reservd   :4;
+	} MODE_TYPE;
+	u8 SNR_EST0;
+	u8 SNR_EST1;
+	u8 SIGNAL;
+} PACKED;
+
+#define CMD_SET_RF_BW_NOT_LISTED   0x3f
+#define MSGID_SET_RF_BW_NOT_LISTED 0x11
+/* TODO */
+
+#endif
diff --git a/drivers/media/dvb-frontends/bsbe1-d01a.h b/drivers/media/dvb-frontends/bsbe1-d01a.h
new file mode 100644
index 0000000..7ed3c42
--- /dev/null
+++ b/drivers/media/dvb-frontends/bsbe1-d01a.h
@@ -0,0 +1,146 @@
+/*
+ * bsbe1-d01a.h - ALPS BSBE1-D01A tuner support
+ *
+ * Copyright (C) 2011 Oliver Endriss <o.endriss@gmx.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * 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.
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ *
+ *
+ * the project's page is at http://www.linuxtv.org
+ */
+
+#ifndef BSBE1_D01A_H
+#define BSBE1_D01A_H
+
+#include "stb6000.h"
+#include "stv0288.h"
+
+static u8 stv0288_bsbe1_d01a_inittab[] = {
+	0x01, 0x15,
+	0x02, 0x20,
+	0x09, 0x0,
+	0x0a, 0x4,
+	0x0b, 0x0,
+	0x0c, 0x0,
+	0x0d, 0x0,
+	0x0e, 0xd4,
+	0x0f, 0x30,
+	0x11, 0x80,
+	0x12, 0x03,
+	0x13, 0x48,
+	0x14, 0x84,
+	0x15, 0x45,
+	0x16, 0xb7,
+	0x17, 0x9c,
+	0x18, 0x0,
+	0x19, 0xa6,
+	0x1a, 0x88,
+	0x1b, 0x8f,
+	0x1c, 0xf0,
+	0x20, 0x0b,
+	0x21, 0x54,
+	0x22, 0x0,
+	0x23, 0x0,
+	0x2b, 0xff,
+	0x2c, 0xf7,
+	0x30, 0x0,
+	0x31, 0x1e,
+	0x32, 0x14,
+	0x33, 0x0f,
+	0x34, 0x09,
+	0x35, 0x0c,
+	0x36, 0x05,
+	0x37, 0x2f,
+	0x38, 0x16,
+	0x39, 0xbd,
+	0x3a, 0x03,
+	0x3b, 0x13,
+	0x3c, 0x11,
+	0x3d, 0x30,
+	0x40, 0x63,
+	0x41, 0x04,
+	0x42, 0x60,
+	0x43, 0x00,
+	0x44, 0x00,
+	0x45, 0x00,
+	0x46, 0x00,
+	0x47, 0x00,
+	0x4a, 0x00,
+	0x50, 0x10,
+	0x51, 0x36,
+	0x52, 0x09,
+	0x53, 0x94,
+	0x54, 0x62,
+	0x55, 0x29,
+	0x56, 0x64,
+	0x57, 0x2b,
+	0x58, 0x54,
+	0x59, 0x86,
+	0x5a, 0x0,
+	0x5b, 0x9b,
+	0x5c, 0x08,
+	0x5d, 0x7f,
+	0x5e, 0x0,
+	0x5f, 0xff,
+	0x70, 0x0,
+	0x71, 0x0,
+	0x72, 0x0,
+	0x74, 0x0,
+	0x75, 0x0,
+	0x76, 0x0,
+	0x81, 0x0,
+	0x82, 0x3f,
+	0x83, 0x3f,
+	0x84, 0x0,
+	0x85, 0x0,
+	0x88, 0x0,
+	0x89, 0x0,
+	0x8a, 0x0,
+	0x8b, 0x0,
+	0x8c, 0x0,
+	0x90, 0x0,
+	0x91, 0x0,
+	0x92, 0x0,
+	0x93, 0x0,
+	0x94, 0x1c,
+	0x97, 0x0,
+	0xa0, 0x48,
+	0xa1, 0x0,
+	0xb0, 0xb8,
+	0xb1, 0x3a,
+	0xb2, 0x10,
+	0xb3, 0x82,
+	0xb4, 0x80,
+	0xb5, 0x82,
+	0xb6, 0x82,
+	0xb7, 0x82,
+	0xb8, 0x20,
+	0xb9, 0x0,
+	0xf0, 0x0,
+	0xf1, 0x0,
+	0xf2, 0xc0,
+	0xff, 0xff,
+};
+
+static struct stv0288_config stv0288_bsbe1_d01a_config = {
+	.demod_address = 0x68,
+	.min_delay_ms = 100,
+	.inittab = stv0288_bsbe1_d01a_inittab,
+};
+
+#endif
diff --git a/drivers/media/dvb-frontends/bsbe1.h b/drivers/media/dvb-frontends/bsbe1.h
new file mode 100644
index 0000000..53e4d0d
--- /dev/null
+++ b/drivers/media/dvb-frontends/bsbe1.h
@@ -0,0 +1,106 @@
+/*
+ * bsbe1.h - ALPS BSBE1 tuner support
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ *
+ *
+ * the project's page is at http://www.linuxtv.org
+ */
+
+#ifndef BSBE1_H
+#define BSBE1_H
+
+static u8 alps_bsbe1_inittab[] = {
+	0x01, 0x15,   /* XTAL = 4MHz, VCO = 352 MHz */
+	0x02, 0x30,   /* MCLK = 88 MHz */
+	0x03, 0x00,   /* ACR output 0 */
+	0x04, 0x7d,   /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */
+	0x05, 0x05,   /* I2CT = 0, SCLT = 1, SDAT = 1 */
+	0x06, 0x00,   /* DAC output 0 */
+	0x08, 0x40,   /* DiSEqC off, LNB power on OP2/LOCK pin on */
+	0x09, 0x00,   /* FIFO */
+	0x0c, 0x51,   /* OP1/OP0 normal, val = 1 (LNB power on) */
+	0x0d, 0x82,   /* DC offset compensation = on, beta_agc1 = 2 */
+	0x0f, 0x92,   /* AGC1R */
+	0x10, 0x34,   /* AGC2O */
+	0x11, 0x84,   /* TLSR */
+	0x12, 0xb9,   /* CFD */
+	0x15, 0xc9,   /* lock detector threshold */
+	0x28, 0x00,   /* out imp: normal, type: parallel, FEC mode: QPSK */
+	0x33, 0xfc,   /* RS control */
+	0x34, 0x93,   /* count viterbi bit errors per 2E18 bytes */
+	0xff, 0xff
+};
+
+
+static int alps_bsbe1_set_symbol_rate(struct dvb_frontend* fe, u32 srate, u32 ratio)
+{
+	u8 aclk = 0;
+	u8 bclk = 0;
+
+	if (srate < 1500000) { aclk = 0xb7; bclk = 0x47; }
+	else if (srate < 3000000) { aclk = 0xb7; bclk = 0x4b; }
+	else if (srate < 7000000) { aclk = 0xb7; bclk = 0x4f; }
+	else if (srate < 14000000) { aclk = 0xb7; bclk = 0x53; }
+	else if (srate < 30000000) { aclk = 0xb6; bclk = 0x53; }
+	else if (srate < 45000000) { aclk = 0xb4; bclk = 0x51; }
+
+	stv0299_writereg(fe, 0x13, aclk);
+	stv0299_writereg(fe, 0x14, bclk);
+	stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
+	stv0299_writereg(fe, 0x20, (ratio >>  8) & 0xff);
+	stv0299_writereg(fe, 0x21, (ratio      ) & 0xf0);
+
+	return 0;
+}
+
+static int alps_bsbe1_tuner_set_params(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	int ret;
+	u8 data[4];
+	u32 div;
+	struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
+	struct i2c_adapter *i2c = fe->tuner_priv;
+
+	if ((p->frequency < 950000) || (p->frequency > 2150000))
+		return -EINVAL;
+
+	div = p->frequency / 1000;
+	data[0] = (div >> 8) & 0x7f;
+	data[1] = div & 0xff;
+	data[2] = 0x80 | ((div & 0x18000) >> 10) | 0x1;
+	data[3] = 0xe0;
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+	ret = i2c_transfer(i2c, &msg, 1);
+	return (ret != 1) ? -EIO : 0;
+}
+
+static struct stv0299_config alps_bsbe1_config = {
+	.demod_address = 0x68,
+	.inittab = alps_bsbe1_inittab,
+	.mclk = 88000000UL,
+	.invert = 1,
+	.skip_reinit = 0,
+	.min_delay_ms = 100,
+	.set_symbol_rate = alps_bsbe1_set_symbol_rate,
+};
+
+#endif
diff --git a/drivers/media/dvb-frontends/bsru6.h b/drivers/media/dvb-frontends/bsru6.h
new file mode 100644
index 0000000..c2a578e
--- /dev/null
+++ b/drivers/media/dvb-frontends/bsru6.h
@@ -0,0 +1,143 @@
+/*
+ * bsru6.h - ALPS BSRU6 tuner support (moved from budget-ci.c)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ *
+ *
+ * the project's page is at http://www.linuxtv.org
+ */
+
+#ifndef BSRU6_H
+#define BSRU6_H
+
+static u8 alps_bsru6_inittab[] = {
+	0x01, 0x15,
+	0x02, 0x30,
+	0x03, 0x00,
+	0x04, 0x7d,   /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */
+	0x05, 0x35,   /* I2CT = 0, SCLT = 1, SDAT = 1 */
+	0x06, 0x40,   /* DAC not used, set to high impendance mode */
+	0x07, 0x00,   /* DAC LSB */
+	0x08, 0x40,   /* DiSEqC off, LNB power on OP2/LOCK pin on */
+	0x09, 0x00,   /* FIFO */
+	0x0c, 0x51,   /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */
+	0x0d, 0x82,   /* DC offset compensation = ON, beta_agc1 = 2 */
+	0x0e, 0x23,   /* alpha_tmg = 2, beta_tmg = 3 */
+	0x10, 0x3f,   // AGC2  0x3d
+	0x11, 0x84,
+	0x12, 0xb9,
+	0x15, 0xc9,   // lock detector threshold
+	0x16, 0x00,
+	0x17, 0x00,
+	0x18, 0x00,
+	0x19, 0x00,
+	0x1a, 0x00,
+	0x1f, 0x50,
+	0x20, 0x00,
+	0x21, 0x00,
+	0x22, 0x00,
+	0x23, 0x00,
+	0x28, 0x00,  // out imp: normal  out type: parallel FEC mode:0
+	0x29, 0x1e,  // 1/2 threshold
+	0x2a, 0x14,  // 2/3 threshold
+	0x2b, 0x0f,  // 3/4 threshold
+	0x2c, 0x09,  // 5/6 threshold
+	0x2d, 0x05,  // 7/8 threshold
+	0x2e, 0x01,
+	0x31, 0x1f,  // test all FECs
+	0x32, 0x19,  // viterbi and synchro search
+	0x33, 0xfc,  // rs control
+	0x34, 0x93,  // error control
+	0x0f, 0x52,
+	0xff, 0xff
+};
+
+static int alps_bsru6_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ratio)
+{
+	u8 aclk = 0;
+	u8 bclk = 0;
+
+	if (srate < 1500000) {
+		aclk = 0xb7;
+		bclk = 0x47;
+	} else if (srate < 3000000) {
+		aclk = 0xb7;
+		bclk = 0x4b;
+	} else if (srate < 7000000) {
+		aclk = 0xb7;
+		bclk = 0x4f;
+	} else if (srate < 14000000) {
+		aclk = 0xb7;
+		bclk = 0x53;
+	} else if (srate < 30000000) {
+		aclk = 0xb6;
+		bclk = 0x53;
+	} else if (srate < 45000000) {
+		aclk = 0xb4;
+		bclk = 0x51;
+	}
+
+	stv0299_writereg(fe, 0x13, aclk);
+	stv0299_writereg(fe, 0x14, bclk);
+	stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
+	stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff);
+	stv0299_writereg(fe, 0x21, ratio & 0xf0);
+
+	return 0;
+}
+
+static int alps_bsru6_tuner_set_params(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	u8 buf[4];
+	u32 div;
+	struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
+	struct i2c_adapter *i2c = fe->tuner_priv;
+
+	if ((p->frequency < 950000) || (p->frequency > 2150000))
+		return -EINVAL;
+
+	div = (p->frequency + (125 - 1)) / 125;	/* round correctly */
+	buf[0] = (div >> 8) & 0x7f;
+	buf[1] = div & 0xff;
+	buf[2] = 0x80 | ((div & 0x18000) >> 10) | 4;
+	buf[3] = 0xC4;
+
+	if (p->frequency > 1530000)
+		buf[3] = 0xc0;
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+	if (i2c_transfer(i2c, &msg, 1) != 1)
+		return -EIO;
+	return 0;
+}
+
+static struct stv0299_config alps_bsru6_config = {
+	.demod_address = 0x68,
+	.inittab = alps_bsru6_inittab,
+	.mclk = 88000000UL,
+	.invert = 1,
+	.skip_reinit = 0,
+	.lock_output = STV0299_LOCKOUTPUT_1,
+	.volt13_op0_op1 = STV0299_VOLT13_OP1,
+	.min_delay_ms = 100,
+	.set_symbol_rate = alps_bsru6_set_symbol_rate,
+};
+
+#endif
diff --git a/drivers/media/dvb-frontends/cx22700.c b/drivers/media/dvb-frontends/cx22700.c
new file mode 100644
index 0000000..f2a90f9
--- /dev/null
+++ b/drivers/media/dvb-frontends/cx22700.c
@@ -0,0 +1,443 @@
+/*
+    Conexant cx22700 DVB OFDM demodulator driver
+
+    Copyright (C) 2001-2002 Convergence Integrated Media GmbH
+	Holger Waechtler <holger@convergence.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/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include "dvb_frontend.h"
+#include "cx22700.h"
+
+
+struct cx22700_state {
+
+	struct i2c_adapter* i2c;
+
+	const struct cx22700_config* config;
+
+	struct dvb_frontend frontend;
+};
+
+
+static int debug;
+#define dprintk(args...) \
+	do { \
+		if (debug) printk(KERN_DEBUG "cx22700: " args); \
+	} while (0)
+
+static u8 init_tab [] = {
+	0x04, 0x10,
+	0x05, 0x09,
+	0x06, 0x00,
+	0x08, 0x04,
+	0x09, 0x00,
+	0x0a, 0x01,
+	0x15, 0x40,
+	0x16, 0x10,
+	0x17, 0x87,
+	0x18, 0x17,
+	0x1a, 0x10,
+	0x25, 0x04,
+	0x2e, 0x00,
+	0x39, 0x00,
+	0x3a, 0x04,
+	0x45, 0x08,
+	0x46, 0x02,
+	0x47, 0x05,
+};
+
+
+static int cx22700_writereg (struct cx22700_state* state, u8 reg, u8 data)
+{
+	int ret;
+	u8 buf [] = { reg, data };
+	struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 };
+
+	dprintk ("%s\n", __func__);
+
+	ret = i2c_transfer (state->i2c, &msg, 1);
+
+	if (ret != 1)
+		printk("%s: writereg error (reg == 0x%02x, val == 0x%02x, ret == %i)\n",
+			__func__, reg, data, ret);
+
+	return (ret != 1) ? -1 : 0;
+}
+
+static int cx22700_readreg (struct cx22700_state* state, u8 reg)
+{
+	int ret;
+	u8 b0 [] = { reg };
+	u8 b1 [] = { 0 };
+	struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 },
+			   { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } };
+
+	dprintk ("%s\n", __func__);
+
+	ret = i2c_transfer (state->i2c, msg, 2);
+
+	if (ret != 2) return -EIO;
+
+	return b1[0];
+}
+
+static int cx22700_set_inversion (struct cx22700_state* state, int inversion)
+{
+	u8 val;
+
+	dprintk ("%s\n", __func__);
+
+	switch (inversion) {
+	case INVERSION_AUTO:
+		return -EOPNOTSUPP;
+	case INVERSION_ON:
+		val = cx22700_readreg (state, 0x09);
+		return cx22700_writereg (state, 0x09, val | 0x01);
+	case INVERSION_OFF:
+		val = cx22700_readreg (state, 0x09);
+		return cx22700_writereg (state, 0x09, val & 0xfe);
+	default:
+		return -EINVAL;
+	}
+}
+
+static int cx22700_set_tps(struct cx22700_state *state,
+			   struct dtv_frontend_properties *p)
+{
+	static const u8 qam_tab [4] = { 0, 1, 0, 2 };
+	static const u8 fec_tab [6] = { 0, 1, 2, 0, 3, 4 };
+	u8 val;
+
+	dprintk ("%s\n", __func__);
+
+	if (p->code_rate_HP < FEC_1_2 || p->code_rate_HP > FEC_7_8)
+		return -EINVAL;
+
+	if (p->code_rate_LP < FEC_1_2 || p->code_rate_LP > FEC_7_8)
+		return -EINVAL;
+
+	if (p->code_rate_HP == FEC_4_5 || p->code_rate_LP == FEC_4_5)
+		return -EINVAL;
+
+	if (p->guard_interval < GUARD_INTERVAL_1_32 ||
+	    p->guard_interval > GUARD_INTERVAL_1_4)
+		return -EINVAL;
+
+	if (p->transmission_mode != TRANSMISSION_MODE_2K &&
+	    p->transmission_mode != TRANSMISSION_MODE_8K)
+		return -EINVAL;
+
+	if (p->modulation != QPSK &&
+	    p->modulation != QAM_16 &&
+	    p->modulation != QAM_64)
+		return -EINVAL;
+
+	if (p->hierarchy < HIERARCHY_NONE ||
+	    p->hierarchy > HIERARCHY_4)
+		return -EINVAL;
+
+	if (p->bandwidth_hz > 8000000 || p->bandwidth_hz < 6000000)
+		return -EINVAL;
+
+	if (p->bandwidth_hz == 7000000)
+		cx22700_writereg (state, 0x09, cx22700_readreg (state, 0x09 | 0x10));
+	else
+		cx22700_writereg (state, 0x09, cx22700_readreg (state, 0x09 & ~0x10));
+
+	val = qam_tab[p->modulation - QPSK];
+	val |= p->hierarchy - HIERARCHY_NONE;
+
+	cx22700_writereg (state, 0x04, val);
+
+	val = fec_tab[p->code_rate_HP - FEC_1_2] << 3;
+	val |= fec_tab[p->code_rate_LP - FEC_1_2];
+
+	cx22700_writereg (state, 0x05, val);
+
+	val = (p->guard_interval - GUARD_INTERVAL_1_32) << 2;
+	val |= p->transmission_mode - TRANSMISSION_MODE_2K;
+
+	cx22700_writereg (state, 0x06, val);
+
+	cx22700_writereg (state, 0x08, 0x04 | 0x02);  /* use user tps parameters */
+	cx22700_writereg (state, 0x08, 0x04);         /* restart acquisition */
+
+	return 0;
+}
+
+static int cx22700_get_tps(struct cx22700_state *state,
+			   struct dtv_frontend_properties *p)
+{
+	static const fe_modulation_t qam_tab [3] = { QPSK, QAM_16, QAM_64 };
+	static const fe_code_rate_t fec_tab [5] = { FEC_1_2, FEC_2_3, FEC_3_4,
+						    FEC_5_6, FEC_7_8 };
+	u8 val;
+
+	dprintk ("%s\n", __func__);
+
+	if (!(cx22700_readreg(state, 0x07) & 0x20))  /*  tps valid? */
+		return -EAGAIN;
+
+	val = cx22700_readreg (state, 0x01);
+
+	if ((val & 0x7) > 4)
+		p->hierarchy = HIERARCHY_AUTO;
+	else
+		p->hierarchy = HIERARCHY_NONE + (val & 0x7);
+
+	if (((val >> 3) & 0x3) > 2)
+		p->modulation = QAM_AUTO;
+	else
+		p->modulation = qam_tab[(val >> 3) & 0x3];
+
+	val = cx22700_readreg (state, 0x02);
+
+	if (((val >> 3) & 0x07) > 4)
+		p->code_rate_HP = FEC_AUTO;
+	else
+		p->code_rate_HP = fec_tab[(val >> 3) & 0x07];
+
+	if ((val & 0x07) > 4)
+		p->code_rate_LP = FEC_AUTO;
+	else
+		p->code_rate_LP = fec_tab[val & 0x07];
+
+	val = cx22700_readreg (state, 0x03);
+
+	p->guard_interval = GUARD_INTERVAL_1_32 + ((val >> 6) & 0x3);
+	p->transmission_mode = TRANSMISSION_MODE_2K + ((val >> 5) & 0x1);
+
+	return 0;
+}
+
+static int cx22700_init (struct dvb_frontend* fe)
+
+{	struct cx22700_state* state = fe->demodulator_priv;
+	int i;
+
+	dprintk("cx22700_init: init chip\n");
+
+	cx22700_writereg (state, 0x00, 0x02);   /*  soft reset */
+	cx22700_writereg (state, 0x00, 0x00);
+
+	msleep(10);
+
+	for (i=0; i<sizeof(init_tab); i+=2)
+		cx22700_writereg (state, init_tab[i], init_tab[i+1]);
+
+	cx22700_writereg (state, 0x00, 0x01);
+
+	return 0;
+}
+
+static int cx22700_read_status(struct dvb_frontend* fe, fe_status_t* status)
+{
+	struct cx22700_state* state = fe->demodulator_priv;
+
+	u16 rs_ber = (cx22700_readreg (state, 0x0d) << 9)
+		   | (cx22700_readreg (state, 0x0e) << 1);
+	u8 sync = cx22700_readreg (state, 0x07);
+
+	*status = 0;
+
+	if (rs_ber < 0xff00)
+		*status |= FE_HAS_SIGNAL;
+
+	if (sync & 0x20)
+		*status |= FE_HAS_CARRIER;
+
+	if (sync & 0x10)
+		*status |= FE_HAS_VITERBI;
+
+	if (sync & 0x10)
+		*status |= FE_HAS_SYNC;
+
+	if (*status == 0x0f)
+		*status |= FE_HAS_LOCK;
+
+	return 0;
+}
+
+static int cx22700_read_ber(struct dvb_frontend* fe, u32* ber)
+{
+	struct cx22700_state* state = fe->demodulator_priv;
+
+	*ber = cx22700_readreg (state, 0x0c) & 0x7f;
+	cx22700_writereg (state, 0x0c, 0x00);
+
+	return 0;
+}
+
+static int cx22700_read_signal_strength(struct dvb_frontend* fe, u16* signal_strength)
+{
+	struct cx22700_state* state = fe->demodulator_priv;
+
+	u16 rs_ber = (cx22700_readreg (state, 0x0d) << 9)
+		   | (cx22700_readreg (state, 0x0e) << 1);
+	*signal_strength = ~rs_ber;
+
+	return 0;
+}
+
+static int cx22700_read_snr(struct dvb_frontend* fe, u16* snr)
+{
+	struct cx22700_state* state = fe->demodulator_priv;
+
+	u16 rs_ber = (cx22700_readreg (state, 0x0d) << 9)
+		   | (cx22700_readreg (state, 0x0e) << 1);
+	*snr = ~rs_ber;
+
+	return 0;
+}
+
+static int cx22700_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
+{
+	struct cx22700_state* state = fe->demodulator_priv;
+
+	*ucblocks = cx22700_readreg (state, 0x0f);
+	cx22700_writereg (state, 0x0f, 0x00);
+
+	return 0;
+}
+
+static int cx22700_set_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	struct cx22700_state* state = fe->demodulator_priv;
+
+	cx22700_writereg (state, 0x00, 0x02); /* XXX CHECKME: soft reset*/
+	cx22700_writereg (state, 0x00, 0x00);
+
+	if (fe->ops.tuner_ops.set_params) {
+		fe->ops.tuner_ops.set_params(fe);
+		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+	}
+
+	cx22700_set_inversion(state, c->inversion);
+	cx22700_set_tps(state, c);
+	cx22700_writereg (state, 0x37, 0x01);  /* PAL loop filter off */
+	cx22700_writereg (state, 0x00, 0x01);  /* restart acquire */
+
+	return 0;
+}
+
+static int cx22700_get_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	struct cx22700_state* state = fe->demodulator_priv;
+	u8 reg09 = cx22700_readreg (state, 0x09);
+
+	c->inversion = reg09 & 0x1 ? INVERSION_ON : INVERSION_OFF;
+	return cx22700_get_tps(state, c);
+}
+
+static int cx22700_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+{
+	struct cx22700_state* state = fe->demodulator_priv;
+
+	if (enable) {
+		return cx22700_writereg(state, 0x0a, 0x00);
+	} else {
+		return cx22700_writereg(state, 0x0a, 0x01);
+	}
+}
+
+static int cx22700_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings)
+{
+	fesettings->min_delay_ms = 150;
+	fesettings->step_size = 166667;
+	fesettings->max_drift = 166667*2;
+	return 0;
+}
+
+static void cx22700_release(struct dvb_frontend* fe)
+{
+	struct cx22700_state* state = fe->demodulator_priv;
+	kfree(state);
+}
+
+static struct dvb_frontend_ops cx22700_ops;
+
+struct dvb_frontend* cx22700_attach(const struct cx22700_config* config,
+				    struct i2c_adapter* i2c)
+{
+	struct cx22700_state* state = NULL;
+
+	/* allocate memory for the internal state */
+	state = kzalloc(sizeof(struct cx22700_state), GFP_KERNEL);
+	if (state == NULL) goto error;
+
+	/* setup the state */
+	state->config = config;
+	state->i2c = i2c;
+
+	/* check if the demod is there */
+	if (cx22700_readreg(state, 0x07) < 0) goto error;
+
+	/* create dvb_frontend */
+	memcpy(&state->frontend.ops, &cx22700_ops, sizeof(struct dvb_frontend_ops));
+	state->frontend.demodulator_priv = state;
+	return &state->frontend;
+
+error:
+	kfree(state);
+	return NULL;
+}
+
+static struct dvb_frontend_ops cx22700_ops = {
+	.delsys = { SYS_DVBT },
+	.info = {
+		.name			= "Conexant CX22700 DVB-T",
+		.frequency_min		= 470000000,
+		.frequency_max		= 860000000,
+		.frequency_stepsize	= 166667,
+		.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_FEC_AUTO |
+		      FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 |
+		      FE_CAN_RECOVER
+	},
+
+	.release = cx22700_release,
+
+	.init = cx22700_init,
+	.i2c_gate_ctrl = cx22700_i2c_gate_ctrl,
+
+	.set_frontend = cx22700_set_frontend,
+	.get_frontend = cx22700_get_frontend,
+	.get_tune_settings = cx22700_get_tune_settings,
+
+	.read_status = cx22700_read_status,
+	.read_ber = cx22700_read_ber,
+	.read_signal_strength = cx22700_read_signal_strength,
+	.read_snr = cx22700_read_snr,
+	.read_ucblocks = cx22700_read_ucblocks,
+};
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+
+MODULE_DESCRIPTION("Conexant CX22700 DVB-T Demodulator driver");
+MODULE_AUTHOR("Holger Waechtler");
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(cx22700_attach);
diff --git a/drivers/media/dvb-frontends/cx22700.h b/drivers/media/dvb-frontends/cx22700.h
new file mode 100644
index 0000000..4757a93
--- /dev/null
+++ b/drivers/media/dvb-frontends/cx22700.h
@@ -0,0 +1,46 @@
+/*
+    Conexant CX22700 DVB OFDM demodulator driver
+
+    Copyright (C) 2001-2002 Convergence Integrated Media GmbH
+	Holger Waechtler <holger@convergence.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 CX22700_H
+#define CX22700_H
+
+#include <linux/dvb/frontend.h>
+
+struct cx22700_config
+{
+	/* the demodulator's i2c address */
+	u8 demod_address;
+};
+
+#if defined(CONFIG_DVB_CX22700) || (defined(CONFIG_DVB_CX22700_MODULE) && defined(MODULE))
+extern struct dvb_frontend* cx22700_attach(const struct cx22700_config* config,
+					   struct i2c_adapter* i2c);
+#else
+static inline struct dvb_frontend* cx22700_attach(const struct cx22700_config* config,
+					   struct i2c_adapter* i2c)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif // CONFIG_DVB_CX22700
+
+#endif // CX22700_H
diff --git a/drivers/media/dvb-frontends/cx22702.c b/drivers/media/dvb-frontends/cx22702.c
new file mode 100644
index 0000000..edc8eaf
--- /dev/null
+++ b/drivers/media/dvb-frontends/cx22702.c
@@ -0,0 +1,653 @@
+/*
+    Conexant 22702 DVB OFDM demodulator driver
+
+    based on:
+	Alps TDMB7 DVB OFDM demodulator driver
+
+    Copyright (C) 2001-2002 Convergence Integrated Media GmbH
+	  Holger Waechtler <holger@convergence.de>
+
+    Copyright (C) 2004 Steven Toth <stoth@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/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include "dvb_frontend.h"
+#include "cx22702.h"
+
+struct cx22702_state {
+
+	struct i2c_adapter *i2c;
+
+	/* configuration settings */
+	const struct cx22702_config *config;
+
+	struct dvb_frontend frontend;
+
+	/* previous uncorrected block counter */
+	u8 prevUCBlocks;
+};
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Enable verbose debug messages");
+
+#define dprintk	if (debug) printk
+
+/* Register values to initialise the demod */
+static const u8 init_tab[] = {
+	0x00, 0x00, /* Stop acquisition */
+	0x0B, 0x06,
+	0x09, 0x01,
+	0x0D, 0x41,
+	0x16, 0x32,
+	0x20, 0x0A,
+	0x21, 0x17,
+	0x24, 0x3e,
+	0x26, 0xff,
+	0x27, 0x10,
+	0x28, 0x00,
+	0x29, 0x00,
+	0x2a, 0x10,
+	0x2b, 0x00,
+	0x2c, 0x10,
+	0x2d, 0x00,
+	0x48, 0xd4,
+	0x49, 0x56,
+	0x6b, 0x1e,
+	0xc8, 0x02,
+	0xf9, 0x00,
+	0xfa, 0x00,
+	0xfb, 0x00,
+	0xfc, 0x00,
+	0xfd, 0x00,
+};
+
+static int cx22702_writereg(struct cx22702_state *state, u8 reg, u8 data)
+{
+	int ret;
+	u8 buf[] = { reg, data };
+	struct i2c_msg msg = {
+		.addr = state->config->demod_address, .flags = 0,
+			.buf = buf, .len = 2 };
+
+	ret = i2c_transfer(state->i2c, &msg, 1);
+
+	if (unlikely(ret != 1)) {
+		printk(KERN_ERR
+			"%s: error (reg == 0x%02x, val == 0x%02x, ret == %i)\n",
+			__func__, reg, data, ret);
+		return -1;
+	}
+
+	return 0;
+}
+
+static u8 cx22702_readreg(struct cx22702_state *state, u8 reg)
+{
+	int ret;
+	u8 data;
+
+	struct i2c_msg msg[] = {
+		{ .addr = state->config->demod_address, .flags = 0,
+			.buf = &reg, .len = 1 },
+		{ .addr = state->config->demod_address, .flags = I2C_M_RD,
+			.buf = &data, .len = 1 } };
+
+	ret = i2c_transfer(state->i2c, msg, 2);
+
+	if (unlikely(ret != 2)) {
+		printk(KERN_ERR "%s: error (reg == 0x%02x, ret == %i)\n",
+			__func__, reg, ret);
+		return 0;
+	}
+
+	return data;
+}
+
+static int cx22702_set_inversion(struct cx22702_state *state, int inversion)
+{
+	u8 val;
+
+	val = cx22702_readreg(state, 0x0C);
+	switch (inversion) {
+	case INVERSION_AUTO:
+		return -EOPNOTSUPP;
+	case INVERSION_ON:
+		val |= 0x01;
+		break;
+	case INVERSION_OFF:
+		val &= 0xfe;
+		break;
+	default:
+		return -EINVAL;
+	}
+	return cx22702_writereg(state, 0x0C, val);
+}
+
+/* Retrieve the demod settings */
+static int cx22702_get_tps(struct cx22702_state *state,
+			   struct dtv_frontend_properties *p)
+{
+	u8 val;
+
+	/* Make sure the TPS regs are valid */
+	if (!(cx22702_readreg(state, 0x0A) & 0x20))
+		return -EAGAIN;
+
+	val = cx22702_readreg(state, 0x01);
+	switch ((val & 0x18) >> 3) {
+	case 0:
+		p->modulation = QPSK;
+		break;
+	case 1:
+		p->modulation = QAM_16;
+		break;
+	case 2:
+		p->modulation = QAM_64;
+		break;
+	}
+	switch (val & 0x07) {
+	case 0:
+		p->hierarchy = HIERARCHY_NONE;
+		break;
+	case 1:
+		p->hierarchy = HIERARCHY_1;
+		break;
+	case 2:
+		p->hierarchy = HIERARCHY_2;
+		break;
+	case 3:
+		p->hierarchy = HIERARCHY_4;
+		break;
+	}
+
+
+	val = cx22702_readreg(state, 0x02);
+	switch ((val & 0x38) >> 3) {
+	case 0:
+		p->code_rate_HP = FEC_1_2;
+		break;
+	case 1:
+		p->code_rate_HP = FEC_2_3;
+		break;
+	case 2:
+		p->code_rate_HP = FEC_3_4;
+		break;
+	case 3:
+		p->code_rate_HP = FEC_5_6;
+		break;
+	case 4:
+		p->code_rate_HP = FEC_7_8;
+		break;
+	}
+	switch (val & 0x07) {
+	case 0:
+		p->code_rate_LP = FEC_1_2;
+		break;
+	case 1:
+		p->code_rate_LP = FEC_2_3;
+		break;
+	case 2:
+		p->code_rate_LP = FEC_3_4;
+		break;
+	case 3:
+		p->code_rate_LP = FEC_5_6;
+		break;
+	case 4:
+		p->code_rate_LP = FEC_7_8;
+		break;
+	}
+
+	val = cx22702_readreg(state, 0x03);
+	switch ((val & 0x0c) >> 2) {
+	case 0:
+		p->guard_interval = GUARD_INTERVAL_1_32;
+		break;
+	case 1:
+		p->guard_interval = GUARD_INTERVAL_1_16;
+		break;
+	case 2:
+		p->guard_interval = GUARD_INTERVAL_1_8;
+		break;
+	case 3:
+		p->guard_interval = GUARD_INTERVAL_1_4;
+		break;
+	}
+	switch (val & 0x03) {
+	case 0:
+		p->transmission_mode = TRANSMISSION_MODE_2K;
+		break;
+	case 1:
+		p->transmission_mode = TRANSMISSION_MODE_8K;
+		break;
+	}
+
+	return 0;
+}
+
+static int cx22702_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+	struct cx22702_state *state = fe->demodulator_priv;
+	u8 val;
+
+	dprintk("%s(%d)\n", __func__, enable);
+	val = cx22702_readreg(state, 0x0D);
+	if (enable)
+		val &= 0xfe;
+	else
+		val |= 0x01;
+	return cx22702_writereg(state, 0x0D, val);
+}
+
+/* Talk to the demod, set the FEC, GUARD, QAM settings etc */
+static int cx22702_set_tps(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	u8 val;
+	struct cx22702_state *state = fe->demodulator_priv;
+
+	if (fe->ops.tuner_ops.set_params) {
+		fe->ops.tuner_ops.set_params(fe);
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 0);
+	}
+
+	/* set inversion */
+	cx22702_set_inversion(state, p->inversion);
+
+	/* set bandwidth */
+	val = cx22702_readreg(state, 0x0C) & 0xcf;
+	switch (p->bandwidth_hz) {
+	case 6000000:
+		val |= 0x20;
+		break;
+	case 7000000:
+		val |= 0x10;
+		break;
+	case 8000000:
+		break;
+	default:
+		dprintk("%s: invalid bandwidth\n", __func__);
+		return -EINVAL;
+	}
+	cx22702_writereg(state, 0x0C, val);
+
+	p->code_rate_LP = FEC_AUTO; /* temp hack as manual not working */
+
+	/* use auto configuration? */
+	if ((p->hierarchy == HIERARCHY_AUTO) ||
+	   (p->modulation == QAM_AUTO) ||
+	   (p->code_rate_HP == FEC_AUTO) ||
+	   (p->code_rate_LP == FEC_AUTO) ||
+	   (p->guard_interval == GUARD_INTERVAL_AUTO) ||
+	   (p->transmission_mode == TRANSMISSION_MODE_AUTO)) {
+
+		/* TPS Source - use hardware driven values */
+		cx22702_writereg(state, 0x06, 0x10);
+		cx22702_writereg(state, 0x07, 0x9);
+		cx22702_writereg(state, 0x08, 0xC1);
+		cx22702_writereg(state, 0x0B, cx22702_readreg(state, 0x0B)
+			& 0xfc);
+		cx22702_writereg(state, 0x0C,
+			(cx22702_readreg(state, 0x0C) & 0xBF) | 0x40);
+		cx22702_writereg(state, 0x00, 0x01); /* Begin acquisition */
+		dprintk("%s: Autodetecting\n", __func__);
+		return 0;
+	}
+
+	/* manually programmed values */
+	switch (p->modulation) {		/* mask 0x18 */
+	case QPSK:
+		val = 0x00;
+		break;
+	case QAM_16:
+		val = 0x08;
+		break;
+	case QAM_64:
+		val = 0x10;
+		break;
+	default:
+		dprintk("%s: invalid modulation\n", __func__);
+		return -EINVAL;
+	}
+	switch (p->hierarchy) {	/* mask 0x07 */
+	case HIERARCHY_NONE:
+		break;
+	case HIERARCHY_1:
+		val |= 0x01;
+		break;
+	case HIERARCHY_2:
+		val |= 0x02;
+		break;
+	case HIERARCHY_4:
+		val |= 0x03;
+		break;
+	default:
+		dprintk("%s: invalid hierarchy\n", __func__);
+		return -EINVAL;
+	}
+	cx22702_writereg(state, 0x06, val);
+
+	switch (p->code_rate_HP) {		/* mask 0x38 */
+	case FEC_NONE:
+	case FEC_1_2:
+		val = 0x00;
+		break;
+	case FEC_2_3:
+		val = 0x08;
+		break;
+	case FEC_3_4:
+		val = 0x10;
+		break;
+	case FEC_5_6:
+		val = 0x18;
+		break;
+	case FEC_7_8:
+		val = 0x20;
+		break;
+	default:
+		dprintk("%s: invalid code_rate_HP\n", __func__);
+		return -EINVAL;
+	}
+	switch (p->code_rate_LP) {		/* mask 0x07 */
+	case FEC_NONE:
+	case FEC_1_2:
+		break;
+	case FEC_2_3:
+		val |= 0x01;
+		break;
+	case FEC_3_4:
+		val |= 0x02;
+		break;
+	case FEC_5_6:
+		val |= 0x03;
+		break;
+	case FEC_7_8:
+		val |= 0x04;
+		break;
+	default:
+		dprintk("%s: invalid code_rate_LP\n", __func__);
+		return -EINVAL;
+	}
+	cx22702_writereg(state, 0x07, val);
+
+	switch (p->guard_interval) {		/* mask 0x0c */
+	case GUARD_INTERVAL_1_32:
+		val = 0x00;
+		break;
+	case GUARD_INTERVAL_1_16:
+		val = 0x04;
+		break;
+	case GUARD_INTERVAL_1_8:
+		val = 0x08;
+		break;
+	case GUARD_INTERVAL_1_4:
+		val = 0x0c;
+		break;
+	default:
+		dprintk("%s: invalid guard_interval\n", __func__);
+		return -EINVAL;
+	}
+	switch (p->transmission_mode) {		/* mask 0x03 */
+	case TRANSMISSION_MODE_2K:
+		break;
+	case TRANSMISSION_MODE_8K:
+		val |= 0x1;
+		break;
+	default:
+		dprintk("%s: invalid transmission_mode\n", __func__);
+		return -EINVAL;
+	}
+	cx22702_writereg(state, 0x08, val);
+	cx22702_writereg(state, 0x0B,
+		(cx22702_readreg(state, 0x0B) & 0xfc) | 0x02);
+	cx22702_writereg(state, 0x0C,
+		(cx22702_readreg(state, 0x0C) & 0xBF) | 0x40);
+
+	/* Begin channel acquisition */
+	cx22702_writereg(state, 0x00, 0x01);
+
+	return 0;
+}
+
+/* Reset the demod hardware and reset all of the configuration registers
+   to a default state. */
+static int cx22702_init(struct dvb_frontend *fe)
+{
+	int i;
+	struct cx22702_state *state = fe->demodulator_priv;
+
+	cx22702_writereg(state, 0x00, 0x02);
+
+	msleep(10);
+
+	for (i = 0; i < ARRAY_SIZE(init_tab); i += 2)
+		cx22702_writereg(state, init_tab[i], init_tab[i + 1]);
+
+	cx22702_writereg(state, 0xf8, (state->config->output_mode << 1)
+		& 0x02);
+
+	cx22702_i2c_gate_ctrl(fe, 0);
+
+	return 0;
+}
+
+static int cx22702_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+	struct cx22702_state *state = fe->demodulator_priv;
+	u8 reg0A;
+	u8 reg23;
+
+	*status = 0;
+
+	reg0A = cx22702_readreg(state, 0x0A);
+	reg23 = cx22702_readreg(state, 0x23);
+
+	dprintk("%s: status demod=0x%02x agc=0x%02x\n"
+		, __func__, reg0A, reg23);
+
+	if (reg0A & 0x10) {
+		*status |= FE_HAS_LOCK;
+		*status |= FE_HAS_VITERBI;
+		*status |= FE_HAS_SYNC;
+	}
+
+	if (reg0A & 0x20)
+		*status |= FE_HAS_CARRIER;
+
+	if (reg23 < 0xf0)
+		*status |= FE_HAS_SIGNAL;
+
+	return 0;
+}
+
+static int cx22702_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+	struct cx22702_state *state = fe->demodulator_priv;
+
+	if (cx22702_readreg(state, 0xE4) & 0x02) {
+		/* Realtime statistics */
+		*ber = (cx22702_readreg(state, 0xDE) & 0x7F) << 7
+			| (cx22702_readreg(state, 0xDF) & 0x7F);
+	} else {
+		/* Averagtine statistics */
+		*ber = (cx22702_readreg(state, 0xDE) & 0x7F) << 7
+			| cx22702_readreg(state, 0xDF);
+	}
+
+	return 0;
+}
+
+static int cx22702_read_signal_strength(struct dvb_frontend *fe,
+	u16 *signal_strength)
+{
+	struct cx22702_state *state = fe->demodulator_priv;
+	u8 reg23;
+
+	/*
+	 * Experience suggests that the strength signal register works as
+	 * follows:
+	 * - In the absence of signal, value is 0xff.
+	 * - In the presence of a weak signal, bit 7 is set, not sure what
+	 *   the lower 7 bits mean.
+	 * - In the presence of a strong signal, the register holds a 7-bit
+	 *   value (bit 7 is cleared), with greater values standing for
+	 *   weaker signals.
+	 */
+	reg23 = cx22702_readreg(state, 0x23);
+	if (reg23 & 0x80) {
+		*signal_strength = 0;
+	} else {
+		reg23 = ~reg23 & 0x7f;
+		/* Scale to 16 bit */
+		*signal_strength = (reg23 << 9) | (reg23 << 2) | (reg23 >> 5);
+	}
+
+	return 0;
+}
+
+static int cx22702_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+	struct cx22702_state *state = fe->demodulator_priv;
+
+	u16 rs_ber;
+	if (cx22702_readreg(state, 0xE4) & 0x02) {
+		/* Realtime statistics */
+		rs_ber = (cx22702_readreg(state, 0xDE) & 0x7F) << 7
+			| (cx22702_readreg(state, 0xDF) & 0x7F);
+	} else {
+		/* Averagine statistics */
+		rs_ber = (cx22702_readreg(state, 0xDE) & 0x7F) << 8
+			| cx22702_readreg(state, 0xDF);
+	}
+	*snr = ~rs_ber;
+
+	return 0;
+}
+
+static int cx22702_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+	struct cx22702_state *state = fe->demodulator_priv;
+
+	u8 _ucblocks;
+
+	/* RS Uncorrectable Packet Count then reset */
+	_ucblocks = cx22702_readreg(state, 0xE3);
+	if (state->prevUCBlocks < _ucblocks)
+		*ucblocks = (_ucblocks - state->prevUCBlocks);
+	else
+		*ucblocks = state->prevUCBlocks - _ucblocks;
+	state->prevUCBlocks = _ucblocks;
+
+	return 0;
+}
+
+static int cx22702_get_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	struct cx22702_state *state = fe->demodulator_priv;
+
+	u8 reg0C = cx22702_readreg(state, 0x0C);
+
+	c->inversion = reg0C & 0x1 ? INVERSION_ON : INVERSION_OFF;
+	return cx22702_get_tps(state, c);
+}
+
+static int cx22702_get_tune_settings(struct dvb_frontend *fe,
+	struct dvb_frontend_tune_settings *tune)
+{
+	tune->min_delay_ms = 1000;
+	return 0;
+}
+
+static void cx22702_release(struct dvb_frontend *fe)
+{
+	struct cx22702_state *state = fe->demodulator_priv;
+	kfree(state);
+}
+
+static const struct dvb_frontend_ops cx22702_ops;
+
+struct dvb_frontend *cx22702_attach(const struct cx22702_config *config,
+	struct i2c_adapter *i2c)
+{
+	struct cx22702_state *state = NULL;
+
+	/* allocate memory for the internal state */
+	state = kzalloc(sizeof(struct cx22702_state), GFP_KERNEL);
+	if (state == NULL)
+		goto error;
+
+	/* setup the state */
+	state->config = config;
+	state->i2c = i2c;
+
+	/* check if the demod is there */
+	if (cx22702_readreg(state, 0x1f) != 0x3)
+		goto error;
+
+	/* create dvb_frontend */
+	memcpy(&state->frontend.ops, &cx22702_ops,
+		sizeof(struct dvb_frontend_ops));
+	state->frontend.demodulator_priv = state;
+	return &state->frontend;
+
+error:
+	kfree(state);
+	return NULL;
+}
+EXPORT_SYMBOL(cx22702_attach);
+
+static const struct dvb_frontend_ops cx22702_ops = {
+	.delsys = { SYS_DVBT },
+	.info = {
+		.name			= "Conexant CX22702 DVB-T",
+		.frequency_min		= 177000000,
+		.frequency_max		= 858000000,
+		.frequency_stepsize	= 166666,
+		.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_FEC_AUTO |
+		FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
+		FE_CAN_HIERARCHY_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |
+		FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_RECOVER
+	},
+
+	.release = cx22702_release,
+
+	.init = cx22702_init,
+	.i2c_gate_ctrl = cx22702_i2c_gate_ctrl,
+
+	.set_frontend = cx22702_set_tps,
+	.get_frontend = cx22702_get_frontend,
+	.get_tune_settings = cx22702_get_tune_settings,
+
+	.read_status = cx22702_read_status,
+	.read_ber = cx22702_read_ber,
+	.read_signal_strength = cx22702_read_signal_strength,
+	.read_snr = cx22702_read_snr,
+	.read_ucblocks = cx22702_read_ucblocks,
+};
+
+MODULE_DESCRIPTION("Conexant CX22702 DVB-T Demodulator driver");
+MODULE_AUTHOR("Steven Toth");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb-frontends/cx22702.h b/drivers/media/dvb-frontends/cx22702.h
new file mode 100644
index 0000000..f154e1f
--- /dev/null
+++ b/drivers/media/dvb-frontends/cx22702.h
@@ -0,0 +1,58 @@
+/*
+    Conexant 22702 DVB OFDM demodulator driver
+
+    based on:
+	Alps TDMB7 DVB OFDM demodulator driver
+
+    Copyright (C) 2001-2002 Convergence Integrated Media GmbH
+	  Holger Waechtler <holger@convergence.de>
+
+    Copyright (C) 2004 Steven Toth <stoth@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 CX22702_H
+#define CX22702_H
+
+#include <linux/dvb/frontend.h>
+
+struct cx22702_config {
+	/* the demodulator's i2c address */
+	u8 demod_address;
+
+	/* serial/parallel output */
+#define CX22702_PARALLEL_OUTPUT 0
+#define CX22702_SERIAL_OUTPUT   1
+	u8 output_mode;
+};
+
+#if defined(CONFIG_DVB_CX22702) || (defined(CONFIG_DVB_CX22702_MODULE) \
+	&& defined(MODULE))
+extern struct dvb_frontend *cx22702_attach(
+	const struct cx22702_config *config,
+	struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend *cx22702_attach(
+	const struct cx22702_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/cx24110.c b/drivers/media/dvb-frontends/cx24110.c
new file mode 100644
index 0000000..3180f5b
--- /dev/null
+++ b/drivers/media/dvb-frontends/cx24110.c
@@ -0,0 +1,666 @@
+/*
+    cx24110 - Single Chip Satellite Channel Receiver driver module
+
+    Copyright (C) 2002 Peter Hettkamp <peter.hettkamp@htp-tel.de> based on
+    work
+    Copyright (C) 1999 Convergence Integrated Media GmbH <ralph@convergence.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/slab.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include "dvb_frontend.h"
+#include "cx24110.h"
+
+
+struct cx24110_state {
+
+	struct i2c_adapter* i2c;
+
+	const struct cx24110_config* config;
+
+	struct dvb_frontend frontend;
+
+	u32 lastber;
+	u32 lastbler;
+	u32 lastesn0;
+};
+
+static int debug;
+#define dprintk(args...) \
+	do { \
+		if (debug) printk(KERN_DEBUG "cx24110: " args); \
+	} while (0)
+
+static struct {u8 reg; u8 data;} cx24110_regdata[]=
+		      /* Comments beginning with @ denote this value should
+			 be the default */
+	{{0x09,0x01}, /* SoftResetAll */
+	 {0x09,0x00}, /* release reset */
+	 {0x01,0xe8}, /* MSB of code rate 27.5MS/s */
+	 {0x02,0x17}, /* middle byte " */
+	 {0x03,0x29}, /* LSB         " */
+	 {0x05,0x03}, /* @ DVB mode, standard code rate 3/4 */
+	 {0x06,0xa5}, /* @ PLL 60MHz */
+	 {0x07,0x01}, /* @ Fclk, i.e. sampling clock, 60MHz */
+	 {0x0a,0x00}, /* @ partial chip disables, do not set */
+	 {0x0b,0x01}, /* set output clock in gapped mode, start signal low
+			 active for first byte */
+	 {0x0c,0x11}, /* no parity bytes, large hold time, serial data out */
+	 {0x0d,0x6f}, /* @ RS Sync/Unsync thresholds */
+	 {0x10,0x40}, /* chip doc is misleading here: write bit 6 as 1
+			 to avoid starting the BER counter. Reset the
+			 CRC test bit. Finite counting selected */
+	 {0x15,0xff}, /* @ size of the limited time window for RS BER
+			 estimation. It is <value>*256 RS blocks, this
+			 gives approx. 2.6 sec at 27.5MS/s, rate 3/4 */
+	 {0x16,0x00}, /* @ enable all RS output ports */
+	 {0x17,0x04}, /* @ time window allowed for the RS to sync */
+	 {0x18,0xae}, /* @ allow all standard DVB code rates to be scanned
+			 for automatically */
+		      /* leave the current code rate and normalization
+			 registers as they are after reset... */
+	 {0x21,0x10}, /* @ during AutoAcq, search each viterbi setting
+			 only once */
+	 {0x23,0x18}, /* @ size of the limited time window for Viterbi BER
+			 estimation. It is <value>*65536 channel bits, i.e.
+			 approx. 38ms at 27.5MS/s, rate 3/4 */
+	 {0x24,0x24}, /* do not trigger Viterbi CRC test. Finite count window */
+		      /* leave front-end AGC parameters at default values */
+		      /* leave decimation AGC parameters at default values */
+	 {0x35,0x40}, /* disable all interrupts. They are not connected anyway */
+	 {0x36,0xff}, /* clear all interrupt pending flags */
+	 {0x37,0x00}, /* @ fully enable AutoAcqq state machine */
+	 {0x38,0x07}, /* @ enable fade recovery, but not autostart AutoAcq */
+		      /* leave the equalizer parameters on their default values */
+		      /* leave the final AGC parameters on their default values */
+	 {0x41,0x00}, /* @ MSB of front-end derotator frequency */
+	 {0x42,0x00}, /* @ middle bytes " */
+	 {0x43,0x00}, /* @ LSB          " */
+		      /* leave the carrier tracking loop parameters on default */
+		      /* leave the bit timing loop parameters at default */
+	 {0x56,0x4d}, /* set the filtune voltage to 2.7V, as recommended by */
+		      /* the cx24108 data sheet for symbol rates above 15MS/s */
+	 {0x57,0x00}, /* @ Filter sigma delta enabled, positive */
+	 {0x61,0x95}, /* GPIO pins 1-4 have special function */
+	 {0x62,0x05}, /* GPIO pin 5 has special function, pin 6 is GPIO */
+	 {0x63,0x00}, /* All GPIO pins use CMOS output characteristics */
+	 {0x64,0x20}, /* GPIO 6 is input, all others are outputs */
+	 {0x6d,0x30}, /* tuner auto mode clock freq 62kHz */
+	 {0x70,0x15}, /* use auto mode, tuner word is 21 bits long */
+	 {0x73,0x00}, /* @ disable several demod bypasses */
+	 {0x74,0x00}, /* @  " */
+	 {0x75,0x00}  /* @  " */
+		      /* the remaining registers are for SEC */
+	};
+
+
+static int cx24110_writereg (struct cx24110_state* state, int reg, int data)
+{
+	u8 buf [] = { reg, data };
+	struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 };
+	int err;
+
+	if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
+		dprintk ("%s: writereg error (err == %i, reg == 0x%02x,"
+			 " data == 0x%02x)\n", __func__, err, reg, data);
+		return -EREMOTEIO;
+	}
+
+	return 0;
+}
+
+static int cx24110_readreg (struct cx24110_state* state, u8 reg)
+{
+	int ret;
+	u8 b0 [] = { reg };
+	u8 b1 [] = { 0 };
+	struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 },
+			   { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } };
+
+	ret = i2c_transfer(state->i2c, msg, 2);
+
+	if (ret != 2) return ret;
+
+	return b1[0];
+}
+
+static int cx24110_set_inversion (struct cx24110_state* state, fe_spectral_inversion_t inversion)
+{
+/* fixme (low): error handling */
+
+	switch (inversion) {
+	case INVERSION_OFF:
+		cx24110_writereg(state,0x37,cx24110_readreg(state,0x37)|0x1);
+		/* AcqSpectrInvDis on. No idea why someone should want this */
+		cx24110_writereg(state,0x5,cx24110_readreg(state,0x5)&0xf7);
+		/* Initial value 0 at start of acq */
+		cx24110_writereg(state,0x22,cx24110_readreg(state,0x22)&0xef);
+		/* current value 0 */
+		/* The cx24110 manual tells us this reg is read-only.
+		   But what the heck... set it ayways */
+		break;
+	case INVERSION_ON:
+		cx24110_writereg(state,0x37,cx24110_readreg(state,0x37)|0x1);
+		/* AcqSpectrInvDis on. No idea why someone should want this */
+		cx24110_writereg(state,0x5,cx24110_readreg(state,0x5)|0x08);
+		/* Initial value 1 at start of acq */
+		cx24110_writereg(state,0x22,cx24110_readreg(state,0x22)|0x10);
+		/* current value 1 */
+		break;
+	case INVERSION_AUTO:
+		cx24110_writereg(state,0x37,cx24110_readreg(state,0x37)&0xfe);
+		/* AcqSpectrInvDis off. Leave initial & current states as is */
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int cx24110_set_fec (struct cx24110_state* state, fe_code_rate_t fec)
+{
+/* fixme (low): error handling */
+
+	static const int rate[]={-1,1,2,3,5,7,-1};
+	static const int g1[]={-1,0x01,0x02,0x05,0x15,0x45,-1};
+	static const int g2[]={-1,0x01,0x03,0x06,0x1a,0x7a,-1};
+
+	/* Well, the AutoAcq engine of the cx24106 and 24110 automatically
+	   searches all enabled viterbi rates, and can handle non-standard
+	   rates as well. */
+
+	if (fec>FEC_AUTO)
+		fec=FEC_AUTO;
+
+	if (fec==FEC_AUTO) { /* (re-)establish AutoAcq behaviour */
+		cx24110_writereg(state,0x37,cx24110_readreg(state,0x37)&0xdf);
+		/* clear AcqVitDis bit */
+		cx24110_writereg(state,0x18,0xae);
+		/* allow all DVB standard code rates */
+		cx24110_writereg(state,0x05,(cx24110_readreg(state,0x05)&0xf0)|0x3);
+		/* set nominal Viterbi rate 3/4 */
+		cx24110_writereg(state,0x22,(cx24110_readreg(state,0x22)&0xf0)|0x3);
+		/* set current Viterbi rate 3/4 */
+		cx24110_writereg(state,0x1a,0x05); cx24110_writereg(state,0x1b,0x06);
+		/* set the puncture registers for code rate 3/4 */
+		return 0;
+	} else {
+		cx24110_writereg(state,0x37,cx24110_readreg(state,0x37)|0x20);
+		/* set AcqVitDis bit */
+		if(rate[fec]>0) {
+			cx24110_writereg(state,0x05,(cx24110_readreg(state,0x05)&0xf0)|rate[fec]);
+			/* set nominal Viterbi rate */
+			cx24110_writereg(state,0x22,(cx24110_readreg(state,0x22)&0xf0)|rate[fec]);
+			/* set current Viterbi rate */
+			cx24110_writereg(state,0x1a,g1[fec]);
+			cx24110_writereg(state,0x1b,g2[fec]);
+			/* not sure if this is the right way: I always used AutoAcq mode */
+	   } else
+		   return -EOPNOTSUPP;
+/* fixme (low): which is the correct return code? */
+	};
+	return 0;
+}
+
+static fe_code_rate_t cx24110_get_fec (struct cx24110_state* state)
+{
+	int i;
+
+	i=cx24110_readreg(state,0x22)&0x0f;
+	if(!(i&0x08)) {
+		return FEC_1_2 + i - 1;
+	} else {
+/* fixme (low): a special code rate has been selected. In theory, we need to
+   return a denominator value, a numerator value, and a pair of puncture
+   maps to correctly describe this mode. But this should never happen in
+   practice, because it cannot be set by cx24110_get_fec. */
+	   return FEC_NONE;
+	}
+}
+
+static int cx24110_set_symbolrate (struct cx24110_state* state, u32 srate)
+{
+/* fixme (low): add error handling */
+	u32 ratio;
+	u32 tmp, fclk, BDRI;
+
+	static const u32 bands[]={5000000UL,15000000UL,90999000UL/2};
+	int i;
+
+	dprintk("cx24110 debug: entering %s(%d)\n",__func__,srate);
+	if (srate>90999000UL/2)
+		srate=90999000UL/2;
+	if (srate<500000)
+		srate=500000;
+
+	for(i = 0; (i < ARRAY_SIZE(bands)) && (srate>bands[i]); i++)
+		;
+	/* first, check which sample rate is appropriate: 45, 60 80 or 90 MHz,
+	   and set the PLL accordingly (R07[1:0] Fclk, R06[7:4] PLLmult,
+	   R06[3:0] PLLphaseDetGain */
+	tmp=cx24110_readreg(state,0x07)&0xfc;
+	if(srate<90999000UL/4) { /* sample rate 45MHz*/
+		cx24110_writereg(state,0x07,tmp);
+		cx24110_writereg(state,0x06,0x78);
+		fclk=90999000UL/2;
+	} else if(srate<60666000UL/2) { /* sample rate 60MHz */
+		cx24110_writereg(state,0x07,tmp|0x1);
+		cx24110_writereg(state,0x06,0xa5);
+		fclk=60666000UL;
+	} else if(srate<80888000UL/2) { /* sample rate 80MHz */
+		cx24110_writereg(state,0x07,tmp|0x2);
+		cx24110_writereg(state,0x06,0x87);
+		fclk=80888000UL;
+	} else { /* sample rate 90MHz */
+		cx24110_writereg(state,0x07,tmp|0x3);
+		cx24110_writereg(state,0x06,0x78);
+		fclk=90999000UL;
+	};
+	dprintk("cx24110 debug: fclk %d Hz\n",fclk);
+	/* we need to divide two integers with approx. 27 bits in 32 bit
+	   arithmetic giving a 25 bit result */
+	/* the maximum dividend is 90999000/2, 0x02b6446c, this number is
+	   also the most complex divisor. Hence, the dividend has,
+	   assuming 32bit unsigned arithmetic, 6 clear bits on top, the
+	   divisor 2 unused bits at the bottom. Also, the quotient is
+	   always less than 1/2. Borrowed from VES1893.c, of course */
+
+	tmp=srate<<6;
+	BDRI=fclk>>2;
+	ratio=(tmp/BDRI);
+
+	tmp=(tmp%BDRI)<<8;
+	ratio=(ratio<<8)+(tmp/BDRI);
+
+	tmp=(tmp%BDRI)<<8;
+	ratio=(ratio<<8)+(tmp/BDRI);
+
+	tmp=(tmp%BDRI)<<1;
+	ratio=(ratio<<1)+(tmp/BDRI);
+
+	dprintk("srate= %d (range %d, up to %d)\n", srate,i,bands[i]);
+	dprintk("fclk = %d\n", fclk);
+	dprintk("ratio= %08x\n", ratio);
+
+	cx24110_writereg(state, 0x1, (ratio>>16)&0xff);
+	cx24110_writereg(state, 0x2, (ratio>>8)&0xff);
+	cx24110_writereg(state, 0x3, (ratio)&0xff);
+
+	return 0;
+
+}
+
+static int _cx24110_pll_write (struct dvb_frontend* fe, const u8 buf[], int len)
+{
+	struct cx24110_state *state = fe->demodulator_priv;
+
+	if (len != 3)
+		return -EINVAL;
+
+/* tuner data is 21 bits long, must be left-aligned in data */
+/* tuner cx24108 is written through a dedicated 3wire interface on the demod chip */
+/* FIXME (low): add error handling, avoid infinite loops if HW fails... */
+
+	cx24110_writereg(state,0x6d,0x30); /* auto mode at 62kHz */
+	cx24110_writereg(state,0x70,0x15); /* auto mode 21 bits */
+
+	/* if the auto tuner writer is still busy, clear it out */
+	while (cx24110_readreg(state,0x6d)&0x80)
+		cx24110_writereg(state,0x72,0);
+
+	/* write the topmost 8 bits */
+	cx24110_writereg(state,0x72,buf[0]);
+
+	/* wait for the send to be completed */
+	while ((cx24110_readreg(state,0x6d)&0xc0)==0x80)
+		;
+
+	/* send another 8 bytes */
+	cx24110_writereg(state,0x72,buf[1]);
+	while ((cx24110_readreg(state,0x6d)&0xc0)==0x80)
+		;
+
+	/* and the topmost 5 bits of this byte */
+	cx24110_writereg(state,0x72,buf[2]);
+	while ((cx24110_readreg(state,0x6d)&0xc0)==0x80)
+		;
+
+	/* now strobe the enable line once */
+	cx24110_writereg(state,0x6d,0x32);
+	cx24110_writereg(state,0x6d,0x30);
+
+	return 0;
+}
+
+static int cx24110_initfe(struct dvb_frontend* fe)
+{
+	struct cx24110_state *state = fe->demodulator_priv;
+/* fixme (low): error handling */
+	int i;
+
+	dprintk("%s: init chip\n", __func__);
+
+	for(i = 0; i < ARRAY_SIZE(cx24110_regdata); i++) {
+		cx24110_writereg(state, cx24110_regdata[i].reg, cx24110_regdata[i].data);
+	};
+
+	return 0;
+}
+
+static int cx24110_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltage)
+{
+	struct cx24110_state *state = fe->demodulator_priv;
+
+	switch (voltage) {
+	case SEC_VOLTAGE_13:
+		return cx24110_writereg(state,0x76,(cx24110_readreg(state,0x76)&0x3b)|0xc0);
+	case SEC_VOLTAGE_18:
+		return cx24110_writereg(state,0x76,(cx24110_readreg(state,0x76)&0x3b)|0x40);
+	default:
+		return -EINVAL;
+	};
+}
+
+static int cx24110_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t burst)
+{
+	int rv, bit;
+	struct cx24110_state *state = fe->demodulator_priv;
+	unsigned long timeout;
+
+	if (burst == SEC_MINI_A)
+		bit = 0x00;
+	else if (burst == SEC_MINI_B)
+		bit = 0x08;
+	else
+		return -EINVAL;
+
+	rv = cx24110_readreg(state, 0x77);
+	if (!(rv & 0x04))
+		cx24110_writereg(state, 0x77, rv | 0x04);
+
+	rv = cx24110_readreg(state, 0x76);
+	cx24110_writereg(state, 0x76, ((rv & 0x90) | 0x40 | bit));
+	timeout = jiffies + msecs_to_jiffies(100);
+	while (!time_after(jiffies, timeout) && !(cx24110_readreg(state, 0x76) & 0x40))
+		; /* wait for LNB ready */
+
+	return 0;
+}
+
+static int cx24110_send_diseqc_msg(struct dvb_frontend* fe,
+				   struct dvb_diseqc_master_cmd *cmd)
+{
+	int i, rv;
+	struct cx24110_state *state = fe->demodulator_priv;
+	unsigned long timeout;
+
+	if (cmd->msg_len < 3 || cmd->msg_len > 6)
+		return -EINVAL;  /* not implemented */
+
+	for (i = 0; i < cmd->msg_len; i++)
+		cx24110_writereg(state, 0x79 + i, cmd->msg[i]);
+
+	rv = cx24110_readreg(state, 0x77);
+	if (rv & 0x04) {
+		cx24110_writereg(state, 0x77, rv & ~0x04);
+		msleep(30); /* reportedly fixes switching problems */
+	}
+
+	rv = cx24110_readreg(state, 0x76);
+
+	cx24110_writereg(state, 0x76, ((rv & 0x90) | 0x40) | ((cmd->msg_len-3) & 3));
+	timeout = jiffies + msecs_to_jiffies(100);
+	while (!time_after(jiffies, timeout) && !(cx24110_readreg(state, 0x76) & 0x40))
+		; /* wait for LNB ready */
+
+	return 0;
+}
+
+static int cx24110_read_status(struct dvb_frontend* fe, fe_status_t* status)
+{
+	struct cx24110_state *state = fe->demodulator_priv;
+
+	int sync = cx24110_readreg (state, 0x55);
+
+	*status = 0;
+
+	if (sync & 0x10)
+		*status |= FE_HAS_SIGNAL;
+
+	if (sync & 0x08)
+		*status |= FE_HAS_CARRIER;
+
+	sync = cx24110_readreg (state, 0x08);
+
+	if (sync & 0x40)
+		*status |= FE_HAS_VITERBI;
+
+	if (sync & 0x20)
+		*status |= FE_HAS_SYNC;
+
+	if ((sync & 0x60) == 0x60)
+		*status |= FE_HAS_LOCK;
+
+	return 0;
+}
+
+static int cx24110_read_ber(struct dvb_frontend* fe, u32* ber)
+{
+	struct cx24110_state *state = fe->demodulator_priv;
+
+	/* fixme (maybe): value range is 16 bit. Scale? */
+	if(cx24110_readreg(state,0x24)&0x10) {
+		/* the Viterbi error counter has finished one counting window */
+		cx24110_writereg(state,0x24,0x04); /* select the ber reg */
+		state->lastber=cx24110_readreg(state,0x25)|
+			(cx24110_readreg(state,0x26)<<8);
+		cx24110_writereg(state,0x24,0x04); /* start new count window */
+		cx24110_writereg(state,0x24,0x14);
+	}
+	*ber = state->lastber;
+
+	return 0;
+}
+
+static int cx24110_read_signal_strength(struct dvb_frontend* fe, u16* signal_strength)
+{
+	struct cx24110_state *state = fe->demodulator_priv;
+
+/* no provision in hardware. Read the frontend AGC accumulator. No idea how to scale this, but I know it is 2s complement */
+	u8 signal = cx24110_readreg (state, 0x27)+128;
+	*signal_strength = (signal << 8) | signal;
+
+	return 0;
+}
+
+static int cx24110_read_snr(struct dvb_frontend* fe, u16* snr)
+{
+	struct cx24110_state *state = fe->demodulator_priv;
+
+	/* no provision in hardware. Can be computed from the Es/N0 estimator, but I don't know how. */
+	if(cx24110_readreg(state,0x6a)&0x80) {
+		/* the Es/N0 error counter has finished one counting window */
+		state->lastesn0=cx24110_readreg(state,0x69)|
+			(cx24110_readreg(state,0x68)<<8);
+		cx24110_writereg(state,0x6a,0x84); /* start new count window */
+	}
+	*snr = state->lastesn0;
+
+	return 0;
+}
+
+static int cx24110_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
+{
+	struct cx24110_state *state = fe->demodulator_priv;
+
+	if(cx24110_readreg(state,0x10)&0x40) {
+		/* the RS error counter has finished one counting window */
+		cx24110_writereg(state,0x10,0x60); /* select the byer reg */
+		(void)(cx24110_readreg(state, 0x12) |
+			(cx24110_readreg(state, 0x13) << 8) |
+			(cx24110_readreg(state, 0x14) << 16));
+		cx24110_writereg(state,0x10,0x70); /* select the bler reg */
+		state->lastbler=cx24110_readreg(state,0x12)|
+			(cx24110_readreg(state,0x13)<<8)|
+			(cx24110_readreg(state,0x14)<<16);
+		cx24110_writereg(state,0x10,0x20); /* start new count window */
+	}
+	*ucblocks = state->lastbler;
+
+	return 0;
+}
+
+static int cx24110_set_frontend(struct dvb_frontend *fe)
+{
+	struct cx24110_state *state = fe->demodulator_priv;
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+
+	if (fe->ops.tuner_ops.set_params) {
+		fe->ops.tuner_ops.set_params(fe);
+		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+	}
+
+	cx24110_set_inversion(state, p->inversion);
+	cx24110_set_fec(state, p->fec_inner);
+	cx24110_set_symbolrate(state, p->symbol_rate);
+	cx24110_writereg(state,0x04,0x05); /* start acquisition */
+
+	return 0;
+}
+
+static int cx24110_get_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct cx24110_state *state = fe->demodulator_priv;
+	s32 afc; unsigned sclk;
+
+/* cannot read back tuner settings (freq). Need to have some private storage */
+
+	sclk = cx24110_readreg (state, 0x07) & 0x03;
+/* ok, real AFC (FEDR) freq. is afc/2^24*fsamp, fsamp=45/60/80/90MHz.
+ * Need 64 bit arithmetic. Is thiss possible in the kernel? */
+	if (sclk==0) sclk=90999000L/2L;
+	else if (sclk==1) sclk=60666000L;
+	else if (sclk==2) sclk=80888000L;
+	else sclk=90999000L;
+	sclk>>=8;
+	afc = sclk*(cx24110_readreg (state, 0x44)&0x1f)+
+	      ((sclk*cx24110_readreg (state, 0x45))>>8)+
+	      ((sclk*cx24110_readreg (state, 0x46))>>16);
+
+	p->frequency += afc;
+	p->inversion = (cx24110_readreg (state, 0x22) & 0x10) ?
+				INVERSION_ON : INVERSION_OFF;
+	p->fec_inner = cx24110_get_fec(state);
+
+	return 0;
+}
+
+static int cx24110_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
+{
+	struct cx24110_state *state = fe->demodulator_priv;
+
+	return cx24110_writereg(state,0x76,(cx24110_readreg(state,0x76)&~0x10)|(((tone==SEC_TONE_ON))?0x10:0));
+}
+
+static void cx24110_release(struct dvb_frontend* fe)
+{
+	struct cx24110_state* state = fe->demodulator_priv;
+	kfree(state);
+}
+
+static struct dvb_frontend_ops cx24110_ops;
+
+struct dvb_frontend* cx24110_attach(const struct cx24110_config* config,
+				    struct i2c_adapter* i2c)
+{
+	struct cx24110_state* state = NULL;
+	int ret;
+
+	/* allocate memory for the internal state */
+	state = kzalloc(sizeof(struct cx24110_state), GFP_KERNEL);
+	if (state == NULL) goto error;
+
+	/* setup the state */
+	state->config = config;
+	state->i2c = i2c;
+	state->lastber = 0;
+	state->lastbler = 0;
+	state->lastesn0 = 0;
+
+	/* check if the demod is there */
+	ret = cx24110_readreg(state, 0x00);
+	if ((ret != 0x5a) && (ret != 0x69)) goto error;
+
+	/* create dvb_frontend */
+	memcpy(&state->frontend.ops, &cx24110_ops, sizeof(struct dvb_frontend_ops));
+	state->frontend.demodulator_priv = state;
+	return &state->frontend;
+
+error:
+	kfree(state);
+	return NULL;
+}
+
+static struct dvb_frontend_ops cx24110_ops = {
+	.delsys = { SYS_DVBS },
+	.info = {
+		.name = "Conexant CX24110 DVB-S",
+		.frequency_min = 950000,
+		.frequency_max = 2150000,
+		.frequency_stepsize = 1011,  /* kHz for QPSK frontends */
+		.frequency_tolerance = 29500,
+		.symbol_rate_min = 1000000,
+		.symbol_rate_max = 45000000,
+		.caps = FE_CAN_INVERSION_AUTO |
+			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_FEC_AUTO |
+			FE_CAN_QPSK | FE_CAN_RECOVER
+	},
+
+	.release = cx24110_release,
+
+	.init = cx24110_initfe,
+	.write = _cx24110_pll_write,
+	.set_frontend = cx24110_set_frontend,
+	.get_frontend = cx24110_get_frontend,
+	.read_status = cx24110_read_status,
+	.read_ber = cx24110_read_ber,
+	.read_signal_strength = cx24110_read_signal_strength,
+	.read_snr = cx24110_read_snr,
+	.read_ucblocks = cx24110_read_ucblocks,
+
+	.diseqc_send_master_cmd = cx24110_send_diseqc_msg,
+	.set_tone = cx24110_set_tone,
+	.set_voltage = cx24110_set_voltage,
+	.diseqc_send_burst = cx24110_diseqc_send_burst,
+};
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+
+MODULE_DESCRIPTION("Conexant CX24110 DVB-S Demodulator driver");
+MODULE_AUTHOR("Peter Hettkamp");
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(cx24110_attach);
diff --git a/drivers/media/dvb-frontends/cx24110.h b/drivers/media/dvb-frontends/cx24110.h
new file mode 100644
index 0000000..fdcceee
--- /dev/null
+++ b/drivers/media/dvb-frontends/cx24110.h
@@ -0,0 +1,61 @@
+/*
+    cx24110 - Single Chip Satellite Channel Receiver driver module
+
+    Copyright (C) 2002 Peter Hettkamp <peter.hettkamp@htp-tel.de> based on
+    work
+    Copyright (C) 1999 Convergence Integrated Media GmbH <ralph@convergence.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 CX24110_H
+#define CX24110_H
+
+#include <linux/dvb/frontend.h>
+
+struct cx24110_config
+{
+	/* the demodulator's i2c address */
+	u8 demod_address;
+};
+
+static inline int cx24110_pll_write(struct dvb_frontend *fe, u32 val)
+{
+	u8 buf[] = {
+		(u8)((val >> 24) & 0xff),
+		(u8)((val >> 16) & 0xff),
+		(u8)((val >> 8) & 0xff)
+	};
+
+	if (fe->ops.write)
+		return fe->ops.write(fe, buf, 3);
+	return 0;
+}
+
+#if defined(CONFIG_DVB_CX24110) || (defined(CONFIG_DVB_CX24110_MODULE) && defined(MODULE))
+extern struct dvb_frontend* cx24110_attach(const struct cx24110_config* config,
+					   struct i2c_adapter* i2c);
+#else
+static inline struct dvb_frontend* cx24110_attach(const struct cx24110_config* config,
+						  struct i2c_adapter* i2c)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif // CONFIG_DVB_CX24110
+
+#endif // CX24110_H
diff --git a/drivers/media/dvb-frontends/cx24113.c b/drivers/media/dvb-frontends/cx24113.c
new file mode 100644
index 0000000..3883c3b
--- /dev/null
+++ b/drivers/media/dvb-frontends/cx24113.c
@@ -0,0 +1,618 @@
+/*
+ *  Driver for Conexant CX24113/CX24128 Tuner (Satellite)
+ *
+ *  Copyright (C) 2007-8 Patrick Boettcher <pb@linuxtv.org>
+ *
+ *  Developed for BBTI / Technisat
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the 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/slab.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include "dvb_frontend.h"
+#include "cx24113.h"
+
+static int debug;
+
+#define cx_info(args...) do { printk(KERN_INFO "CX24113: " args); } while (0)
+#define cx_err(args...)  do { printk(KERN_ERR  "CX24113: " args); } while (0)
+
+#define dprintk(args...) \
+	do { \
+		if (debug) { \
+			printk(KERN_DEBUG "CX24113: %s: ", __func__); \
+			printk(args); \
+		} \
+	} while (0)
+
+struct cx24113_state {
+	struct i2c_adapter *i2c;
+	const struct cx24113_config *config;
+
+#define REV_CX24113 0x23
+	u8 rev;
+	u8 ver;
+
+	u8 icp_mode:1;
+
+#define ICP_LEVEL1 0
+#define ICP_LEVEL2 1
+#define ICP_LEVEL3 2
+#define ICP_LEVEL4 3
+	u8 icp_man:2;
+	u8 icp_auto_low:2;
+	u8 icp_auto_mlow:2;
+	u8 icp_auto_mhi:2;
+	u8 icp_auto_hi:2;
+	u8 icp_dig;
+
+#define LNA_MIN_GAIN 0
+#define LNA_MID_GAIN 1
+#define LNA_MAX_GAIN 2
+	u8 lna_gain:2;
+
+	u8 acp_on:1;
+
+	u8 vco_mode:2;
+	u8 vco_shift:1;
+#define VCOBANDSEL_6 0x80
+#define VCOBANDSEL_5 0x01
+#define VCOBANDSEL_4 0x02
+#define VCOBANDSEL_3 0x04
+#define VCOBANDSEL_2 0x08
+#define VCOBANDSEL_1 0x10
+	u8 vco_band;
+
+#define VCODIV4 4
+#define VCODIV2 2
+	u8 vcodiv;
+
+	u8 bs_delay:4;
+	u16 bs_freqcnt:13;
+	u16 bs_rdiv;
+	u8 prescaler_mode:1;
+
+	u8 rfvga_bias_ctrl;
+
+	s16 tuner_gain_thres;
+	u8  gain_level;
+
+	u32 frequency;
+
+	u8 refdiv;
+
+	u8 Fwindow_enabled;
+};
+
+static int cx24113_writereg(struct cx24113_state *state, int reg, int data)
+{
+	u8 buf[] = { reg, data };
+	struct i2c_msg msg = { .addr = state->config->i2c_addr,
+		.flags = 0, .buf = buf, .len = 2 };
+	int err = i2c_transfer(state->i2c, &msg, 1);
+	if (err != 1) {
+		printk(KERN_DEBUG "%s: writereg error(err == %i, reg == 0x%02x,"
+			 " data == 0x%02x)\n", __func__, err, reg, data);
+		return err;
+	}
+
+	return 0;
+}
+
+static int cx24113_readreg(struct cx24113_state *state, u8 reg)
+{
+	int ret;
+	u8 b;
+	struct i2c_msg msg[] = {
+		{ .addr = state->config->i2c_addr,
+			.flags = 0, .buf = &reg, .len = 1 },
+		{ .addr = state->config->i2c_addr,
+			.flags = I2C_M_RD, .buf = &b, .len = 1 }
+	};
+
+	ret = i2c_transfer(state->i2c, msg, 2);
+
+	if (ret != 2) {
+		printk(KERN_DEBUG "%s: reg=0x%x (error=%d)\n",
+			__func__, reg, ret);
+		return ret;
+	}
+
+	return b;
+}
+
+static void cx24113_set_parameters(struct cx24113_state *state)
+{
+	u8 r;
+
+	r = cx24113_readreg(state, 0x10) & 0x82;
+	r |= state->icp_mode;
+	r |= state->icp_man << 4;
+	r |= state->icp_dig << 2;
+	r |= state->prescaler_mode << 5;
+	cx24113_writereg(state, 0x10, r);
+
+	r = (state->icp_auto_low  << 0) | (state->icp_auto_mlow << 2)
+		| (state->icp_auto_mhi << 4) | (state->icp_auto_hi << 6);
+	cx24113_writereg(state, 0x11, r);
+
+	if (state->rev == REV_CX24113) {
+		r = cx24113_readreg(state, 0x20) & 0xec;
+		r |= state->lna_gain;
+		r |= state->rfvga_bias_ctrl << 4;
+		cx24113_writereg(state, 0x20, r);
+	}
+
+	r = cx24113_readreg(state, 0x12) & 0x03;
+	r |= state->acp_on << 2;
+	r |= state->bs_delay << 4;
+	cx24113_writereg(state, 0x12, r);
+
+	r = cx24113_readreg(state, 0x18) & 0x40;
+	r |= state->vco_shift;
+	if (state->vco_band == VCOBANDSEL_6)
+		r |= (1 << 7);
+	else
+		r |= (state->vco_band << 1);
+	cx24113_writereg(state, 0x18, r);
+
+	r  = cx24113_readreg(state, 0x14) & 0x20;
+	r |= (state->vco_mode << 6) | ((state->bs_freqcnt >> 8) & 0x1f);
+	cx24113_writereg(state, 0x14, r);
+	cx24113_writereg(state, 0x15, (state->bs_freqcnt        & 0xff));
+
+	cx24113_writereg(state, 0x16, (state->bs_rdiv >> 4) & 0xff);
+	r = (cx24113_readreg(state, 0x17) & 0x0f) |
+		((state->bs_rdiv & 0x0f) << 4);
+	cx24113_writereg(state, 0x17, r);
+}
+
+#define VGA_0 0x00
+#define VGA_1 0x04
+#define VGA_2 0x02
+#define VGA_3 0x06
+#define VGA_4 0x01
+#define VGA_5 0x05
+#define VGA_6 0x03
+#define VGA_7 0x07
+
+#define RFVGA_0 0x00
+#define RFVGA_1 0x01
+#define RFVGA_2 0x02
+#define RFVGA_3 0x03
+
+static int cx24113_set_gain_settings(struct cx24113_state *state,
+		s16 power_estimation)
+{
+	u8 ampout = cx24113_readreg(state, 0x1d) & 0xf0,
+	   vga    = cx24113_readreg(state, 0x1f) & 0x3f,
+	   rfvga  = cx24113_readreg(state, 0x20) & 0xf3;
+	u8 gain_level = power_estimation >= state->tuner_gain_thres;
+
+	dprintk("power estimation: %d, thres: %d, gain_level: %d/%d\n",
+			power_estimation, state->tuner_gain_thres,
+			state->gain_level, gain_level);
+
+	if (gain_level == state->gain_level)
+		return 0; /* nothing to be done */
+
+	ampout |= 0xf;
+
+	if (gain_level) {
+		rfvga |= RFVGA_0 << 2;
+		vga   |= (VGA_7 << 3) | VGA_7;
+	} else {
+		rfvga |= RFVGA_2 << 2;
+		vga  |= (VGA_6 << 3) | VGA_2;
+	}
+	state->gain_level = gain_level;
+
+	cx24113_writereg(state, 0x1d, ampout);
+	cx24113_writereg(state, 0x1f, vga);
+	cx24113_writereg(state, 0x20, rfvga);
+
+	return 1; /* did something */
+}
+
+static int cx24113_set_Fref(struct cx24113_state *state, u8 high)
+{
+	u8 xtal = cx24113_readreg(state, 0x02);
+	if (state->rev == 0x43 && state->vcodiv == VCODIV4)
+		high = 1;
+
+	xtal &= ~0x2;
+	if (high)
+		xtal |= high << 1;
+	return cx24113_writereg(state, 0x02, xtal);
+}
+
+static int cx24113_enable(struct cx24113_state *state, u8 enable)
+{
+	u8 r21 = (cx24113_readreg(state, 0x21) & 0xc0) | enable;
+	if (state->rev == REV_CX24113)
+		r21 |= (1 << 1);
+	return cx24113_writereg(state, 0x21, r21);
+}
+
+static int cx24113_set_bandwidth(struct cx24113_state *state, u32 bandwidth_khz)
+{
+	u8 r;
+
+	if (bandwidth_khz <= 19000)
+		r = 0x03 << 6;
+	else if (bandwidth_khz <= 25000)
+		r = 0x02 << 6;
+	else
+		r = 0x01 << 6;
+
+	dprintk("bandwidth to be set: %d\n", bandwidth_khz);
+	bandwidth_khz *= 10;
+	bandwidth_khz -= 10000;
+	bandwidth_khz /= 1000;
+	bandwidth_khz += 5;
+	bandwidth_khz /= 10;
+
+	dprintk("bandwidth: %d %d\n", r >> 6, bandwidth_khz);
+
+	r |= bandwidth_khz & 0x3f;
+
+	return cx24113_writereg(state, 0x1e, r);
+}
+
+static int cx24113_set_clk_inversion(struct cx24113_state *state, u8 on)
+{
+	u8 r = (cx24113_readreg(state, 0x10) & 0x7f) | ((on & 0x1) << 7);
+	return cx24113_writereg(state, 0x10, r);
+}
+
+static int cx24113_get_status(struct dvb_frontend *fe, u32 *status)
+{
+	struct cx24113_state *state = fe->tuner_priv;
+	u8 r = (cx24113_readreg(state, 0x10) & 0x02) >> 1;
+	if (r)
+		*status |= TUNER_STATUS_LOCKED;
+	dprintk("PLL locked: %d\n", r);
+	return 0;
+}
+
+static u8 cx24113_set_ref_div(struct cx24113_state *state, u8 refdiv)
+{
+	if (state->rev == 0x43 && state->vcodiv == VCODIV4)
+		refdiv = 2;
+	return state->refdiv = refdiv;
+}
+
+static void cx24113_calc_pll_nf(struct cx24113_state *state, u16 *n, s32 *f)
+{
+	s32 N;
+	s64 F;
+	u64 dividend;
+	u8 R, r;
+	u8 vcodiv;
+	u8 factor;
+	s32 freq_hz = state->frequency * 1000;
+
+	if (state->config->xtal_khz < 20000)
+		factor = 1;
+	else
+		factor = 2;
+
+	if (state->rev == REV_CX24113) {
+		if (state->frequency >= 1100000)
+			vcodiv = VCODIV2;
+		else
+			vcodiv = VCODIV4;
+	} else {
+		if (state->frequency >= 1165000)
+			vcodiv = VCODIV2;
+		else
+			vcodiv = VCODIV4;
+	}
+	state->vcodiv = vcodiv;
+
+	dprintk("calculating N/F for %dHz with vcodiv %d\n", freq_hz, vcodiv);
+	R = 0;
+	do {
+		R = cx24113_set_ref_div(state, R + 1);
+
+		/* calculate tuner PLL settings: */
+		N =  (freq_hz / 100 * vcodiv) * R;
+		N /= (state->config->xtal_khz) * factor * 2;
+		N += 5;     /* For round up. */
+		N /= 10;
+		N -= 32;
+	} while (N < 6 && R < 3);
+
+	if (N < 6) {
+		cx_err("strange frequency: N < 6\n");
+		return;
+	}
+	F = freq_hz;
+	F *= (u64) (R * vcodiv * 262144);
+	dprintk("1 N: %d, F: %lld, R: %d\n", N, (long long)F, R);
+	/* do_div needs an u64 as first argument */
+	dividend = F;
+	do_div(dividend, state->config->xtal_khz * 1000 * factor * 2);
+	F = dividend;
+	dprintk("2 N: %d, F: %lld, R: %d\n", N, (long long)F, R);
+	F -= (N + 32) * 262144;
+
+	dprintk("3 N: %d, F: %lld, R: %d\n", N, (long long)F, R);
+
+	if (state->Fwindow_enabled) {
+		if (F > (262144 / 2 - 1638))
+			F = 262144 / 2 - 1638;
+		if (F < (-262144 / 2 + 1638))
+			F = -262144 / 2 + 1638;
+		if ((F < 3277 && F > 0) || (F > -3277 && F < 0)) {
+			F = 0;
+			r = cx24113_readreg(state, 0x10);
+			cx24113_writereg(state, 0x10, r | (1 << 6));
+		}
+	}
+	dprintk("4 N: %d, F: %lld, R: %d\n", N, (long long)F, R);
+
+	*n = (u16) N;
+	*f = (s32) F;
+}
+
+
+static void cx24113_set_nfr(struct cx24113_state *state, u16 n, s32 f, u8 r)
+{
+	u8 reg;
+	cx24113_writereg(state, 0x19, (n >> 1) & 0xff);
+
+	reg = ((n & 0x1) << 7) | ((f >> 11) & 0x7f);
+	cx24113_writereg(state, 0x1a, reg);
+
+	cx24113_writereg(state, 0x1b, (f >> 3) & 0xff);
+
+	reg = cx24113_readreg(state, 0x1c) & 0x1f;
+	cx24113_writereg(state, 0x1c, reg | ((f & 0x7) << 5));
+
+	cx24113_set_Fref(state, r - 1);
+}
+
+static int cx24113_set_frequency(struct cx24113_state *state, u32 frequency)
+{
+	u8 r = 1; /* or 2 */
+	u16 n = 6;
+	s32 f = 0;
+
+	r = cx24113_readreg(state, 0x14);
+	cx24113_writereg(state, 0x14, r & 0x3f);
+
+	r = cx24113_readreg(state, 0x10);
+	cx24113_writereg(state, 0x10, r & 0xbf);
+
+	state->frequency = frequency;
+
+	dprintk("tuning to frequency: %d\n", frequency);
+
+	cx24113_calc_pll_nf(state, &n, &f);
+	cx24113_set_nfr(state, n, f, state->refdiv);
+
+	r = cx24113_readreg(state, 0x18) & 0xbf;
+	if (state->vcodiv != VCODIV2)
+		r |= 1 << 6;
+	cx24113_writereg(state, 0x18, r);
+
+	/* The need for this sleep is not clear. But helps in some cases */
+	msleep(5);
+
+	r = cx24113_readreg(state, 0x1c) & 0xef;
+	cx24113_writereg(state, 0x1c, r | (1 << 4));
+	return 0;
+}
+
+static int cx24113_init(struct dvb_frontend *fe)
+{
+	struct cx24113_state *state = fe->tuner_priv;
+	int ret;
+
+	state->tuner_gain_thres = -50;
+	state->gain_level = 255; /* to force a gain-setting initialization */
+	state->icp_mode = 0;
+
+	if (state->config->xtal_khz < 11000) {
+		state->icp_auto_hi  = ICP_LEVEL4;
+		state->icp_auto_mhi  = ICP_LEVEL4;
+		state->icp_auto_mlow = ICP_LEVEL3;
+		state->icp_auto_low = ICP_LEVEL3;
+	} else {
+		state->icp_auto_hi  = ICP_LEVEL4;
+		state->icp_auto_mhi  = ICP_LEVEL4;
+		state->icp_auto_mlow = ICP_LEVEL3;
+		state->icp_auto_low = ICP_LEVEL2;
+	}
+
+	state->icp_dig = ICP_LEVEL3;
+	state->icp_man = ICP_LEVEL1;
+	state->acp_on  = 1;
+	state->vco_mode = 0;
+	state->vco_shift = 0;
+	state->vco_band = VCOBANDSEL_1;
+	state->bs_delay = 8;
+	state->bs_freqcnt = 0x0fff;
+	state->bs_rdiv = 0x0fff;
+	state->prescaler_mode = 0;
+	state->lna_gain = LNA_MAX_GAIN;
+	state->rfvga_bias_ctrl = 1;
+	state->Fwindow_enabled = 1;
+
+	cx24113_set_Fref(state, 0);
+	cx24113_enable(state, 0x3d);
+	cx24113_set_parameters(state);
+
+	cx24113_set_gain_settings(state, -30);
+
+	cx24113_set_bandwidth(state, 18025);
+	cx24113_set_clk_inversion(state, 1);
+
+	if (state->config->xtal_khz >= 40000)
+		ret = cx24113_writereg(state, 0x02,
+			(cx24113_readreg(state, 0x02) & 0xfb) | (1 << 2));
+	else
+		ret = cx24113_writereg(state, 0x02,
+			(cx24113_readreg(state, 0x02) & 0xfb) | (0 << 2));
+
+	return ret;
+}
+
+static int cx24113_set_params(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	struct cx24113_state *state = fe->tuner_priv;
+	/* for a ROLL-OFF factor of 0.35, 0.2: 600, 0.25: 625 */
+	u32 roll_off = 675;
+	u32 bw;
+
+	bw  = ((c->symbol_rate/100) * roll_off) / 1000;
+	bw += (10000000/100) + 5;
+	bw /= 10;
+	bw += 1000;
+	cx24113_set_bandwidth(state, bw);
+
+	cx24113_set_frequency(state, c->frequency);
+	msleep(5);
+	return cx24113_get_status(fe, &bw);
+}
+
+static s8 cx24113_agc_table[2][10] = {
+	{-54, -41, -35, -30, -25, -21, -16, -10,  -6,  -2},
+	{-39, -35, -30, -25, -19, -15, -11,  -5,   1,   9},
+};
+
+void cx24113_agc_callback(struct dvb_frontend *fe)
+{
+	struct cx24113_state *state = fe->tuner_priv;
+	s16 s, i;
+	if (!fe->ops.read_signal_strength)
+		return;
+
+	do {
+		/* this only works with the current CX24123 implementation */
+		fe->ops.read_signal_strength(fe, (u16 *) &s);
+		s >>= 8;
+		dprintk("signal strength: %d\n", s);
+		for (i = 0; i < sizeof(cx24113_agc_table[0]); i++)
+			if (cx24113_agc_table[state->gain_level][i] > s)
+				break;
+		s = -25 - i*5;
+	} while (cx24113_set_gain_settings(state, s));
+}
+EXPORT_SYMBOL(cx24113_agc_callback);
+
+static int cx24113_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+	struct cx24113_state *state = fe->tuner_priv;
+	*frequency = state->frequency;
+	return 0;
+}
+
+static int cx24113_release(struct dvb_frontend *fe)
+{
+	struct cx24113_state *state = fe->tuner_priv;
+	dprintk("\n");
+	fe->tuner_priv = NULL;
+	kfree(state);
+	return 0;
+}
+
+static const struct dvb_tuner_ops cx24113_tuner_ops = {
+	.info = {
+		.name           = "Conexant CX24113",
+		.frequency_min  = 950000,
+		.frequency_max  = 2150000,
+		.frequency_step = 125,
+	},
+
+	.release       = cx24113_release,
+
+	.init          = cx24113_init,
+
+	.set_params    = cx24113_set_params,
+	.get_frequency = cx24113_get_frequency,
+	.get_status    = cx24113_get_status,
+};
+
+struct dvb_frontend *cx24113_attach(struct dvb_frontend *fe,
+		const struct cx24113_config *config, struct i2c_adapter *i2c)
+{
+	/* allocate memory for the internal state */
+	struct cx24113_state *state =
+		kzalloc(sizeof(struct cx24113_state), GFP_KERNEL);
+	int rc;
+	if (state == NULL) {
+		cx_err("Unable to kzalloc\n");
+		goto error;
+	}
+
+	/* setup the state */
+	state->config = config;
+	state->i2c = i2c;
+
+	cx_info("trying to detect myself\n");
+
+	/* making a dummy read, because of some expected troubles
+	 * after power on */
+	cx24113_readreg(state, 0x00);
+
+	rc = cx24113_readreg(state, 0x00);
+	if (rc < 0) {
+		cx_info("CX24113 not found.\n");
+		goto error;
+	}
+	state->rev = rc;
+
+	switch (rc) {
+	case 0x43:
+		cx_info("detected CX24113 variant\n");
+		break;
+	case REV_CX24113:
+		cx_info("successfully detected\n");
+		break;
+	default:
+		cx_err("unsupported device id: %x\n", state->rev);
+		goto error;
+	}
+	state->ver = cx24113_readreg(state, 0x01);
+	cx_info("version: %x\n", state->ver);
+
+	/* create dvb_frontend */
+	memcpy(&fe->ops.tuner_ops, &cx24113_tuner_ops,
+			sizeof(struct dvb_tuner_ops));
+	fe->tuner_priv = state;
+	return fe;
+
+error:
+	kfree(state);
+
+	return NULL;
+}
+EXPORT_SYMBOL(cx24113_attach);
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)");
+
+MODULE_AUTHOR("Patrick Boettcher <pb@linuxtv.org>");
+MODULE_DESCRIPTION("DVB Frontend module for Conexant CX24113/CX24128hardware");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/media/dvb-frontends/cx24113.h b/drivers/media/dvb-frontends/cx24113.h
new file mode 100644
index 0000000..01eb7b9
--- /dev/null
+++ b/drivers/media/dvb-frontends/cx24113.h
@@ -0,0 +1,53 @@
+/*
+ *  Driver for Conexant CX24113/CX24128 Tuner (Satellite)
+ *
+ *  Copyright (C) 2007-8 Patrick Boettcher <pb@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 CX24113_H
+#define CX24113_H
+
+struct dvb_frontend;
+
+struct cx24113_config {
+	u8 i2c_addr; /* 0x14 or 0x54 */
+
+	u32 xtal_khz;
+};
+
+#if defined(CONFIG_DVB_TUNER_CX24113) || \
+	(defined(CONFIG_DVB_TUNER_CX24113_MODULE) && defined(MODULE))
+extern struct dvb_frontend *cx24113_attach(struct dvb_frontend *,
+	const struct cx24113_config *config, struct i2c_adapter *i2c);
+
+extern void cx24113_agc_callback(struct dvb_frontend *fe);
+#else
+static inline struct dvb_frontend *cx24113_attach(struct dvb_frontend *fe,
+	const struct cx24113_config *config, struct i2c_adapter *i2c)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+
+static inline void cx24113_agc_callback(struct dvb_frontend *fe)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+}
+#endif
+
+#endif /* CX24113_H */
diff --git a/drivers/media/dvb-frontends/cx24116.c b/drivers/media/dvb-frontends/cx24116.c
new file mode 100644
index 0000000..b488791
--- /dev/null
+++ b/drivers/media/dvb-frontends/cx24116.c
@@ -0,0 +1,1508 @@
+/*
+    Conexant cx24116/cx24118 - DVBS/S2 Satellite demod/tuner driver
+
+    Copyright (C) 2006-2008 Steven Toth <stoth@hauppauge.com>
+    Copyright (C) 2006-2007 Georg Acher
+    Copyright (C) 2007-2008 Darron Broad
+	March 2007
+	    Fixed some bugs.
+	    Added diseqc support.
+	    Added corrected signal strength support.
+	August 2007
+	    Sync with legacy version.
+	    Some clean ups.
+    Copyright (C) 2008 Igor Liplianin
+	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
+    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/slab.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/firmware.h>
+
+#include "dvb_frontend.h"
+#include "cx24116.h"
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)");
+
+#define dprintk(args...) \
+	do { \
+		if (debug) \
+			printk(KERN_INFO "cx24116: " args); \
+	} while (0)
+
+#define CX24116_DEFAULT_FIRMWARE "dvb-fe-cx24116.fw"
+#define CX24116_SEARCH_RANGE_KHZ 5000
+
+/* known registers */
+#define CX24116_REG_COMMAND (0x00)      /* command args 0x00..0x1e */
+#define CX24116_REG_EXECUTE (0x1f)      /* execute command */
+#define CX24116_REG_MAILBOX (0x96)      /* FW or multipurpose mailbox? */
+#define CX24116_REG_RESET   (0x20)      /* reset status > 0     */
+#define CX24116_REG_SIGNAL  (0x9e)      /* signal low           */
+#define CX24116_REG_SSTATUS (0x9d)      /* signal high / status */
+#define CX24116_REG_QUALITY8 (0xa3)
+#define CX24116_REG_QSTATUS (0xbc)
+#define CX24116_REG_QUALITY0 (0xd5)
+#define CX24116_REG_BER0    (0xc9)
+#define CX24116_REG_BER8    (0xc8)
+#define CX24116_REG_BER16   (0xc7)
+#define CX24116_REG_BER24   (0xc6)
+#define CX24116_REG_UCB0    (0xcb)
+#define CX24116_REG_UCB8    (0xca)
+#define CX24116_REG_CLKDIV  (0xf3)
+#define CX24116_REG_RATEDIV (0xf9)
+
+/* configured fec (not tuned) or actual FEC (tuned) 1=1/2 2=2/3 etc */
+#define CX24116_REG_FECSTATUS (0x9c)
+
+/* FECSTATUS bits */
+/* mask to determine configured fec (not tuned) or actual fec (tuned) */
+#define CX24116_FEC_FECMASK   (0x1f)
+
+/* Select DVB-S demodulator, else DVB-S2 */
+#define CX24116_FEC_DVBS      (0x20)
+#define CX24116_FEC_UNKNOWN   (0x40)    /* Unknown/unused */
+
+/* Pilot mode requested when tuning else always reset when tuned */
+#define CX24116_FEC_PILOT     (0x80)
+
+/* arg buffer size */
+#define CX24116_ARGLEN (0x1e)
+
+/* rolloff */
+#define CX24116_ROLLOFF_020 (0x00)
+#define CX24116_ROLLOFF_025 (0x01)
+#define CX24116_ROLLOFF_035 (0x02)
+
+/* pilot bit */
+#define CX24116_PILOT_OFF (0x00)
+#define CX24116_PILOT_ON (0x40)
+
+/* signal status */
+#define CX24116_HAS_SIGNAL   (0x01)
+#define CX24116_HAS_CARRIER  (0x02)
+#define CX24116_HAS_VITERBI  (0x04)
+#define CX24116_HAS_SYNCLOCK (0x08)
+#define CX24116_HAS_UNKNOWN1 (0x10)
+#define CX24116_HAS_UNKNOWN2 (0x20)
+#define CX24116_STATUS_MASK  (0x0f)
+#define CX24116_SIGNAL_MASK  (0xc0)
+
+#define CX24116_DISEQC_TONEOFF   (0)    /* toneburst never sent */
+#define CX24116_DISEQC_TONECACHE (1)    /* toneburst cached     */
+#define CX24116_DISEQC_MESGCACHE (2)    /* message cached       */
+
+/* arg offset for DiSEqC */
+#define CX24116_DISEQC_BURST  (1)
+#define CX24116_DISEQC_ARG2_2 (2)   /* unknown value=2 */
+#define CX24116_DISEQC_ARG3_0 (3)   /* unknown value=0 */
+#define CX24116_DISEQC_ARG4_0 (4)   /* unknown value=0 */
+#define CX24116_DISEQC_MSGLEN (5)
+#define CX24116_DISEQC_MSGOFS (6)
+
+/* DiSEqC burst */
+#define CX24116_DISEQC_MINI_A (0)
+#define CX24116_DISEQC_MINI_B (1)
+
+/* DiSEqC tone burst */
+static int toneburst = 1;
+module_param(toneburst, int, 0644);
+MODULE_PARM_DESC(toneburst, "DiSEqC toneburst 0=OFF, 1=TONE CACHE, "\
+	"2=MESSAGE CACHE (default:1)");
+
+/* SNR measurements */
+static int esno_snr;
+module_param(esno_snr, int, 0644);
+MODULE_PARM_DESC(esno_snr, "SNR return units, 0=PERCENTAGE 0-100, "\
+	"1=ESNO(db * 10) (default:0)");
+
+enum cmds {
+	CMD_SET_VCO     = 0x10,
+	CMD_TUNEREQUEST = 0x11,
+	CMD_MPEGCONFIG  = 0x13,
+	CMD_TUNERINIT   = 0x14,
+	CMD_BANDWIDTH   = 0x15,
+	CMD_GETAGC      = 0x19,
+	CMD_LNBCONFIG   = 0x20,
+	CMD_LNBSEND     = 0x21, /* Formerly CMD_SEND_DISEQC */
+	CMD_LNBDCLEVEL  = 0x22,
+	CMD_SET_TONE    = 0x23,
+	CMD_UPDFWVERS   = 0x35,
+	CMD_TUNERSLEEP  = 0x36,
+	CMD_AGCCONTROL  = 0x3b, /* Unknown */
+};
+
+/* The Demod/Tuner can't easily provide these, we cache them */
+struct cx24116_tuning {
+	u32 frequency;
+	u32 symbol_rate;
+	fe_spectral_inversion_t inversion;
+	fe_code_rate_t fec;
+
+	fe_delivery_system_t delsys;
+	fe_modulation_t modulation;
+	fe_pilot_t pilot;
+	fe_rolloff_t rolloff;
+
+	/* Demod values */
+	u8 fec_val;
+	u8 fec_mask;
+	u8 inversion_val;
+	u8 pilot_val;
+	u8 rolloff_val;
+};
+
+/* Basic commands that are sent to the firmware */
+struct cx24116_cmd {
+	u8 len;
+	u8 args[CX24116_ARGLEN];
+};
+
+struct cx24116_state {
+	struct i2c_adapter *i2c;
+	const struct cx24116_config *config;
+
+	struct dvb_frontend frontend;
+
+	struct cx24116_tuning dcur;
+	struct cx24116_tuning dnxt;
+
+	u8 skip_fw_load;
+	u8 burst;
+	struct cx24116_cmd dsec_cmd;
+};
+
+static int cx24116_writereg(struct cx24116_state *state, int reg, int data)
+{
+	u8 buf[] = { reg, data };
+	struct i2c_msg msg = { .addr = state->config->demod_address,
+		.flags = 0, .buf = buf, .len = 2 };
+	int err;
+
+	if (debug > 1)
+		printk("cx24116: %s: write reg 0x%02x, value 0x%02x\n",
+			__func__, reg, data);
+
+	err = i2c_transfer(state->i2c, &msg, 1);
+	if (err != 1) {
+		printk(KERN_ERR "%s: writereg error(err == %i, reg == 0x%02x,"
+			 " value == 0x%02x)\n", __func__, err, reg, data);
+		return -EREMOTEIO;
+	}
+
+	return 0;
+}
+
+/* Bulk byte writes to a single I2C address, for 32k firmware load */
+static int cx24116_writeregN(struct cx24116_state *state, int reg,
+			     const u8 *data, u16 len)
+{
+	int ret = -EREMOTEIO;
+	struct i2c_msg msg;
+	u8 *buf;
+
+	buf = kmalloc(len + 1, GFP_KERNEL);
+	if (buf == NULL) {
+		printk("Unable to kmalloc\n");
+		ret = -ENOMEM;
+		goto error;
+	}
+
+	*(buf) = reg;
+	memcpy(buf + 1, data, len);
+
+	msg.addr = state->config->demod_address;
+	msg.flags = 0;
+	msg.buf = buf;
+	msg.len = len + 1;
+
+	if (debug > 1)
+		printk(KERN_INFO "cx24116: %s:  write regN 0x%02x, len = %d\n",
+			__func__, reg, len);
+
+	ret = i2c_transfer(state->i2c, &msg, 1);
+	if (ret != 1) {
+		printk(KERN_ERR "%s: writereg error(err == %i, reg == 0x%02x\n",
+			 __func__, ret, reg);
+		ret = -EREMOTEIO;
+	}
+
+error:
+	kfree(buf);
+
+	return ret;
+}
+
+static int cx24116_readreg(struct cx24116_state *state, u8 reg)
+{
+	int ret;
+	u8 b0[] = { reg };
+	u8 b1[] = { 0 };
+	struct i2c_msg msg[] = {
+		{ .addr = state->config->demod_address, .flags = 0,
+			.buf = b0, .len = 1 },
+		{ .addr = state->config->demod_address, .flags = I2C_M_RD,
+			.buf = b1, .len = 1 }
+	};
+
+	ret = i2c_transfer(state->i2c, msg, 2);
+
+	if (ret != 2) {
+		printk(KERN_ERR "%s: reg=0x%x (error=%d)\n",
+			__func__, reg, ret);
+		return ret;
+	}
+
+	if (debug > 1)
+		printk(KERN_INFO "cx24116: read reg 0x%02x, value 0x%02x\n",
+			reg, b1[0]);
+
+	return b1[0];
+}
+
+static int cx24116_set_inversion(struct cx24116_state *state,
+	fe_spectral_inversion_t inversion)
+{
+	dprintk("%s(%d)\n", __func__, inversion);
+
+	switch (inversion) {
+	case INVERSION_OFF:
+		state->dnxt.inversion_val = 0x00;
+		break;
+	case INVERSION_ON:
+		state->dnxt.inversion_val = 0x04;
+		break;
+	case INVERSION_AUTO:
+		state->dnxt.inversion_val = 0x0C;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	state->dnxt.inversion = inversion;
+
+	return 0;
+}
+
+/*
+ * modfec (modulation and FEC)
+ * ===========================
+ *
+ * MOD          FEC             mask/val    standard
+ * ----         --------        ----------- --------
+ * QPSK         FEC_1_2         0x02 0x02+X DVB-S
+ * QPSK         FEC_2_3         0x04 0x02+X DVB-S
+ * QPSK         FEC_3_4         0x08 0x02+X DVB-S
+ * QPSK         FEC_4_5         0x10 0x02+X DVB-S (?)
+ * QPSK         FEC_5_6         0x20 0x02+X DVB-S
+ * QPSK         FEC_6_7         0x40 0x02+X DVB-S
+ * QPSK         FEC_7_8         0x80 0x02+X DVB-S
+ * QPSK         FEC_8_9         0x01 0x02+X DVB-S (?) (NOT SUPPORTED?)
+ * QPSK         AUTO            0xff 0x02+X DVB-S
+ *
+ * For DVB-S high byte probably represents FEC
+ * and low byte selects the modulator. The high
+ * byte is search range mask. Bit 5 may turn
+ * on DVB-S and remaining bits represent some
+ * kind of calibration (how/what i do not know).
+ *
+ * Eg.(2/3) szap "Zone Horror"
+ *
+ * mask/val = 0x04, 0x20
+ * status 1f | signal c3c0 | snr a333 | ber 00000098 | unc 0 | FE_HAS_LOCK
+ *
+ * mask/val = 0x04, 0x30
+ * status 1f | signal c3c0 | snr a333 | ber 00000000 | unc 0 | FE_HAS_LOCK
+ *
+ * After tuning FECSTATUS contains actual FEC
+ * in use numbered 1 through to 8 for 1/2 .. 2/3 etc
+ *
+ * NBC=NOT/NON BACKWARD COMPATIBLE WITH DVB-S (DVB-S2 only)
+ *
+ * NBC-QPSK     FEC_1_2         0x00, 0x04      DVB-S2
+ * NBC-QPSK     FEC_3_5         0x00, 0x05      DVB-S2
+ * NBC-QPSK     FEC_2_3         0x00, 0x06      DVB-S2
+ * NBC-QPSK     FEC_3_4         0x00, 0x07      DVB-S2
+ * NBC-QPSK     FEC_4_5         0x00, 0x08      DVB-S2
+ * NBC-QPSK     FEC_5_6         0x00, 0x09      DVB-S2
+ * NBC-QPSK     FEC_8_9         0x00, 0x0a      DVB-S2
+ * NBC-QPSK     FEC_9_10        0x00, 0x0b      DVB-S2
+ *
+ * NBC-8PSK     FEC_3_5         0x00, 0x0c      DVB-S2
+ * NBC-8PSK     FEC_2_3         0x00, 0x0d      DVB-S2
+ * NBC-8PSK     FEC_3_4         0x00, 0x0e      DVB-S2
+ * NBC-8PSK     FEC_5_6         0x00, 0x0f      DVB-S2
+ * NBC-8PSK     FEC_8_9         0x00, 0x10      DVB-S2
+ * NBC-8PSK     FEC_9_10        0x00, 0x11      DVB-S2
+ *
+ * For DVB-S2 low bytes selects both modulator
+ * and FEC. High byte is meaningless here. To
+ * set pilot, bit 6 (0x40) is set. When inspecting
+ * FECSTATUS bit 7 (0x80) represents the pilot
+ * selection whilst not tuned. When tuned, actual FEC
+ * in use is found in FECSTATUS as per above. Pilot
+ * value is reset.
+ */
+
+/* A table of modulation, fec and configuration bytes for the demod.
+ * Not all S2 mmodulation schemes are support and not all rates with
+ * a scheme are support. Especially, no auto detect when in S2 mode.
+ */
+static struct cx24116_modfec {
+	fe_delivery_system_t delivery_system;
+	fe_modulation_t modulation;
+	fe_code_rate_t fec;
+	u8 mask;	/* In DVBS mode this is used to autodetect */
+	u8 val;		/* Passed to the firmware to indicate mode selection */
+} CX24116_MODFEC_MODES[] = {
+ /* QPSK. For unknown rates we set hardware to auto detect 0xfe 0x30 */
+
+ /*mod   fec       mask  val */
+ { SYS_DVBS, QPSK, FEC_NONE, 0xfe, 0x30 },
+ { SYS_DVBS, QPSK, FEC_1_2,  0x02, 0x2e }, /* 00000010 00101110 */
+ { SYS_DVBS, QPSK, FEC_2_3,  0x04, 0x2f }, /* 00000100 00101111 */
+ { SYS_DVBS, QPSK, FEC_3_4,  0x08, 0x30 }, /* 00001000 00110000 */
+ { SYS_DVBS, QPSK, FEC_4_5,  0xfe, 0x30 }, /* 000?0000 ?        */
+ { SYS_DVBS, QPSK, FEC_5_6,  0x20, 0x31 }, /* 00100000 00110001 */
+ { SYS_DVBS, QPSK, FEC_6_7,  0xfe, 0x30 }, /* 0?000000 ?        */
+ { SYS_DVBS, QPSK, FEC_7_8,  0x80, 0x32 }, /* 10000000 00110010 */
+ { SYS_DVBS, QPSK, FEC_8_9,  0xfe, 0x30 }, /* 0000000? ?        */
+ { SYS_DVBS, QPSK, FEC_AUTO, 0xfe, 0x30 },
+ /* NBC-QPSK */
+ { SYS_DVBS2, QPSK, FEC_1_2,  0x00, 0x04 },
+ { SYS_DVBS2, QPSK, FEC_3_5,  0x00, 0x05 },
+ { SYS_DVBS2, QPSK, FEC_2_3,  0x00, 0x06 },
+ { SYS_DVBS2, QPSK, FEC_3_4,  0x00, 0x07 },
+ { SYS_DVBS2, QPSK, FEC_4_5,  0x00, 0x08 },
+ { SYS_DVBS2, QPSK, FEC_5_6,  0x00, 0x09 },
+ { SYS_DVBS2, QPSK, FEC_8_9,  0x00, 0x0a },
+ { SYS_DVBS2, QPSK, FEC_9_10, 0x00, 0x0b },
+ /* 8PSK */
+ { SYS_DVBS2, PSK_8, FEC_3_5,  0x00, 0x0c },
+ { SYS_DVBS2, PSK_8, FEC_2_3,  0x00, 0x0d },
+ { SYS_DVBS2, PSK_8, FEC_3_4,  0x00, 0x0e },
+ { SYS_DVBS2, PSK_8, FEC_5_6,  0x00, 0x0f },
+ { SYS_DVBS2, PSK_8, FEC_8_9,  0x00, 0x10 },
+ { SYS_DVBS2, PSK_8, FEC_9_10, 0x00, 0x11 },
+ /*
+  * `val' can be found in the FECSTATUS register when tuning.
+  * FECSTATUS will give the actual FEC in use if tuning was successful.
+  */
+};
+
+static int cx24116_lookup_fecmod(struct cx24116_state *state,
+	fe_delivery_system_t d, fe_modulation_t m, fe_code_rate_t f)
+{
+	int i, ret = -EOPNOTSUPP;
+
+	dprintk("%s(0x%02x,0x%02x)\n", __func__, m, f);
+
+	for (i = 0; i < ARRAY_SIZE(CX24116_MODFEC_MODES); i++) {
+		if ((d == CX24116_MODFEC_MODES[i].delivery_system) &&
+			(m == CX24116_MODFEC_MODES[i].modulation) &&
+			(f == CX24116_MODFEC_MODES[i].fec)) {
+				ret = i;
+				break;
+			}
+	}
+
+	return ret;
+}
+
+static int cx24116_set_fec(struct cx24116_state *state,
+	fe_delivery_system_t delsys, fe_modulation_t mod, fe_code_rate_t fec)
+{
+	int ret = 0;
+
+	dprintk("%s(0x%02x,0x%02x)\n", __func__, mod, fec);
+
+	ret = cx24116_lookup_fecmod(state, delsys, mod, fec);
+
+	if (ret < 0)
+		return ret;
+
+	state->dnxt.fec = fec;
+	state->dnxt.fec_val = CX24116_MODFEC_MODES[ret].val;
+	state->dnxt.fec_mask = CX24116_MODFEC_MODES[ret].mask;
+	dprintk("%s() mask/val = 0x%02x/0x%02x\n", __func__,
+		state->dnxt.fec_mask, state->dnxt.fec_val);
+
+	return 0;
+}
+
+static int cx24116_set_symbolrate(struct cx24116_state *state, u32 rate)
+{
+	dprintk("%s(%d)\n", __func__, rate);
+
+	/*  check if symbol rate is within limits */
+	if ((rate > state->frontend.ops.info.symbol_rate_max) ||
+	    (rate < state->frontend.ops.info.symbol_rate_min)) {
+		dprintk("%s() unsupported symbol_rate = %d\n", __func__, rate);
+		return -EOPNOTSUPP;
+	}
+
+	state->dnxt.symbol_rate = rate;
+	dprintk("%s() symbol_rate = %d\n", __func__, rate);
+
+	return 0;
+}
+
+static int cx24116_load_firmware(struct dvb_frontend *fe,
+	const struct firmware *fw);
+
+static int cx24116_firmware_ondemand(struct dvb_frontend *fe)
+{
+	struct cx24116_state *state = fe->demodulator_priv;
+	const struct firmware *fw;
+	int ret = 0;
+
+	dprintk("%s()\n", __func__);
+
+	if (cx24116_readreg(state, 0x20) > 0) {
+
+		if (state->skip_fw_load)
+			return 0;
+
+		/* Load firmware */
+		/* request the firmware, this will block until loaded */
+		printk(KERN_INFO "%s: Waiting for firmware upload (%s)...\n",
+			__func__, CX24116_DEFAULT_FIRMWARE);
+		ret = request_firmware(&fw, CX24116_DEFAULT_FIRMWARE,
+			state->i2c->dev.parent);
+		printk(KERN_INFO "%s: Waiting for firmware upload(2)...\n",
+			__func__);
+		if (ret) {
+			printk(KERN_ERR "%s: No firmware uploaded "
+				"(timeout or file not found?)\n", __func__);
+			return ret;
+		}
+
+		/* Make sure we don't recurse back through here
+		 * during loading */
+		state->skip_fw_load = 1;
+
+		ret = cx24116_load_firmware(fe, fw);
+		if (ret)
+			printk(KERN_ERR "%s: Writing firmware to device failed\n",
+				__func__);
+
+		release_firmware(fw);
+
+		printk(KERN_INFO "%s: Firmware upload %s\n", __func__,
+			ret == 0 ? "complete" : "failed");
+
+		/* Ensure firmware is always loaded if required */
+		state->skip_fw_load = 0;
+	}
+
+	return ret;
+}
+
+/* Take a basic firmware command structure, format it
+ * and forward it for processing
+ */
+static int cx24116_cmd_execute(struct dvb_frontend *fe, struct cx24116_cmd *cmd)
+{
+	struct cx24116_state *state = fe->demodulator_priv;
+	int i, ret;
+
+	dprintk("%s()\n", __func__);
+
+	/* Load the firmware if required */
+	ret = cx24116_firmware_ondemand(fe);
+	if (ret != 0) {
+		printk(KERN_ERR "%s(): Unable initialise the firmware\n",
+			__func__);
+		return ret;
+	}
+
+	/* Write the command */
+	for (i = 0; i < cmd->len ; i++) {
+		dprintk("%s: 0x%02x == 0x%02x\n", __func__, i, cmd->args[i]);
+		cx24116_writereg(state, i, cmd->args[i]);
+	}
+
+	/* Start execution and wait for cmd to terminate */
+	cx24116_writereg(state, CX24116_REG_EXECUTE, 0x01);
+	while (cx24116_readreg(state, CX24116_REG_EXECUTE)) {
+		msleep(10);
+		if (i++ > 64) {
+			/* Avoid looping forever if the firmware does
+				not respond */
+			printk(KERN_WARNING "%s() Firmware not responding\n",
+				__func__);
+			return -EREMOTEIO;
+		}
+	}
+	return 0;
+}
+
+static int cx24116_load_firmware(struct dvb_frontend *fe,
+	const struct firmware *fw)
+{
+	struct cx24116_state *state = fe->demodulator_priv;
+	struct cx24116_cmd cmd;
+	int i, ret, len, max, remaining;
+	unsigned char vers[4];
+
+	dprintk("%s\n", __func__);
+	dprintk("Firmware is %zu bytes (%02x %02x .. %02x %02x)\n",
+			fw->size,
+			fw->data[0],
+			fw->data[1],
+			fw->data[fw->size-2],
+			fw->data[fw->size-1]);
+
+	/* Toggle 88x SRST pin to reset demod */
+	if (state->config->reset_device)
+		state->config->reset_device(fe);
+
+	/* Begin the firmware load process */
+	/* Prepare the demod, load the firmware, cleanup after load */
+
+	/* Init PLL */
+	cx24116_writereg(state, 0xE5, 0x00);
+	cx24116_writereg(state, 0xF1, 0x08);
+	cx24116_writereg(state, 0xF2, 0x13);
+
+	/* Start PLL */
+	cx24116_writereg(state, 0xe0, 0x03);
+	cx24116_writereg(state, 0xe0, 0x00);
+
+	/* Unknown */
+	cx24116_writereg(state, CX24116_REG_CLKDIV, 0x46);
+	cx24116_writereg(state, CX24116_REG_RATEDIV, 0x00);
+
+	/* Unknown */
+	cx24116_writereg(state, 0xF0, 0x03);
+	cx24116_writereg(state, 0xF4, 0x81);
+	cx24116_writereg(state, 0xF5, 0x00);
+	cx24116_writereg(state, 0xF6, 0x00);
+
+	/* Split firmware to the max I2C write len and write.
+	 * Writes whole firmware as one write when i2c_wr_max is set to 0. */
+	if (state->config->i2c_wr_max)
+		max = state->config->i2c_wr_max;
+	else
+		max = INT_MAX; /* enough for 32k firmware */
+
+	for (remaining = fw->size; remaining > 0; remaining -= max - 1) {
+		len = remaining;
+		if (len > max - 1)
+			len = max - 1;
+
+		cx24116_writeregN(state, 0xF7, &fw->data[fw->size - remaining],
+			len);
+	}
+
+	cx24116_writereg(state, 0xF4, 0x10);
+	cx24116_writereg(state, 0xF0, 0x00);
+	cx24116_writereg(state, 0xF8, 0x06);
+
+	/* Firmware CMD 10: VCO config */
+	cmd.args[0x00] = CMD_SET_VCO;
+	cmd.args[0x01] = 0x05;
+	cmd.args[0x02] = 0xdc;
+	cmd.args[0x03] = 0xda;
+	cmd.args[0x04] = 0xae;
+	cmd.args[0x05] = 0xaa;
+	cmd.args[0x06] = 0x04;
+	cmd.args[0x07] = 0x9d;
+	cmd.args[0x08] = 0xfc;
+	cmd.args[0x09] = 0x06;
+	cmd.len = 0x0a;
+	ret = cx24116_cmd_execute(fe, &cmd);
+	if (ret != 0)
+		return ret;
+
+	cx24116_writereg(state, CX24116_REG_SSTATUS, 0x00);
+
+	/* Firmware CMD 14: Tuner config */
+	cmd.args[0x00] = CMD_TUNERINIT;
+	cmd.args[0x01] = 0x00;
+	cmd.args[0x02] = 0x00;
+	cmd.len = 0x03;
+	ret = cx24116_cmd_execute(fe, &cmd);
+	if (ret != 0)
+		return ret;
+
+	cx24116_writereg(state, 0xe5, 0x00);
+
+	/* Firmware CMD 13: MPEG config */
+	cmd.args[0x00] = CMD_MPEGCONFIG;
+	cmd.args[0x01] = 0x01;
+	cmd.args[0x02] = 0x75;
+	cmd.args[0x03] = 0x00;
+	if (state->config->mpg_clk_pos_pol)
+		cmd.args[0x04] = state->config->mpg_clk_pos_pol;
+	else
+		cmd.args[0x04] = 0x02;
+	cmd.args[0x05] = 0x00;
+	cmd.len = 0x06;
+	ret = cx24116_cmd_execute(fe, &cmd);
+	if (ret != 0)
+		return ret;
+
+	/* Firmware CMD 35: Get firmware version */
+	cmd.args[0x00] = CMD_UPDFWVERS;
+	cmd.len = 0x02;
+	for (i = 0; i < 4; i++) {
+		cmd.args[0x01] = i;
+		ret = cx24116_cmd_execute(fe, &cmd);
+		if (ret != 0)
+			return ret;
+		vers[i] = cx24116_readreg(state, CX24116_REG_MAILBOX);
+	}
+	printk(KERN_INFO "%s: FW version %i.%i.%i.%i\n", __func__,
+		vers[0], vers[1], vers[2], vers[3]);
+
+	return 0;
+}
+
+static int cx24116_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+	struct cx24116_state *state = fe->demodulator_priv;
+
+	int lock = cx24116_readreg(state, CX24116_REG_SSTATUS) &
+		CX24116_STATUS_MASK;
+
+	dprintk("%s: status = 0x%02x\n", __func__, lock);
+
+	*status = 0;
+
+	if (lock & CX24116_HAS_SIGNAL)
+		*status |= FE_HAS_SIGNAL;
+	if (lock & CX24116_HAS_CARRIER)
+		*status |= FE_HAS_CARRIER;
+	if (lock & CX24116_HAS_VITERBI)
+		*status |= FE_HAS_VITERBI;
+	if (lock & CX24116_HAS_SYNCLOCK)
+		*status |= FE_HAS_SYNC | FE_HAS_LOCK;
+
+	return 0;
+}
+
+static int cx24116_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+	struct cx24116_state *state = fe->demodulator_priv;
+
+	dprintk("%s()\n", __func__);
+
+	*ber =  (cx24116_readreg(state, CX24116_REG_BER24) << 24) |
+		(cx24116_readreg(state, CX24116_REG_BER16) << 16) |
+		(cx24116_readreg(state, CX24116_REG_BER8)  << 8)  |
+		 cx24116_readreg(state, CX24116_REG_BER0);
+
+	return 0;
+}
+
+/* TODO Determine function and scale appropriately */
+static int cx24116_read_signal_strength(struct dvb_frontend *fe,
+	u16 *signal_strength)
+{
+	struct cx24116_state *state = fe->demodulator_priv;
+	struct cx24116_cmd cmd;
+	int ret;
+	u16 sig_reading;
+
+	dprintk("%s()\n", __func__);
+
+	/* Firmware CMD 19: Get AGC */
+	cmd.args[0x00] = CMD_GETAGC;
+	cmd.len = 0x01;
+	ret = cx24116_cmd_execute(fe, &cmd);
+	if (ret != 0)
+		return ret;
+
+	sig_reading =
+		(cx24116_readreg(state,
+			CX24116_REG_SSTATUS) & CX24116_SIGNAL_MASK) |
+		(cx24116_readreg(state, CX24116_REG_SIGNAL) << 6);
+	*signal_strength = 0 - sig_reading;
+
+	dprintk("%s: raw / cooked = 0x%04x / 0x%04x\n",
+		__func__, sig_reading, *signal_strength);
+
+	return 0;
+}
+
+/* SNR (0..100)% = (sig & 0xf0) * 10 + (sig & 0x0f) * 10 / 16 */
+static int cx24116_read_snr_pct(struct dvb_frontend *fe, u16 *snr)
+{
+	struct cx24116_state *state = fe->demodulator_priv;
+	u8 snr_reading;
+	static const u32 snr_tab[] = { /* 10 x Table (rounded up) */
+		0x00000, 0x0199A, 0x03333, 0x04ccD, 0x06667,
+		0x08000, 0x0999A, 0x0b333, 0x0cccD, 0x0e667,
+		0x10000, 0x1199A, 0x13333, 0x14ccD, 0x16667,
+		0x18000 };
+
+	dprintk("%s()\n", __func__);
+
+	snr_reading = cx24116_readreg(state, CX24116_REG_QUALITY0);
+
+	if (snr_reading >= 0xa0 /* 100% */)
+		*snr = 0xffff;
+	else
+		*snr = snr_tab[(snr_reading & 0xf0) >> 4] +
+			(snr_tab[(snr_reading & 0x0f)] >> 4);
+
+	dprintk("%s: raw / cooked = 0x%02x / 0x%04x\n", __func__,
+		snr_reading, *snr);
+
+	return 0;
+}
+
+/* The reelbox patches show the value in the registers represents
+ * ESNO, from 0->30db (values 0->300). We provide this value by
+ * default.
+ */
+static int cx24116_read_snr_esno(struct dvb_frontend *fe, u16 *snr)
+{
+	struct cx24116_state *state = fe->demodulator_priv;
+
+	dprintk("%s()\n", __func__);
+
+	*snr = cx24116_readreg(state, CX24116_REG_QUALITY8) << 8 |
+		cx24116_readreg(state, CX24116_REG_QUALITY0);
+
+	dprintk("%s: raw 0x%04x\n", __func__, *snr);
+
+	return 0;
+}
+
+static int cx24116_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+	if (esno_snr == 1)
+		return cx24116_read_snr_esno(fe, snr);
+	else
+		return cx24116_read_snr_pct(fe, snr);
+}
+
+static int cx24116_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+	struct cx24116_state *state = fe->demodulator_priv;
+
+	dprintk("%s()\n", __func__);
+
+	*ucblocks = (cx24116_readreg(state, CX24116_REG_UCB8) << 8) |
+		cx24116_readreg(state, CX24116_REG_UCB0);
+
+	return 0;
+}
+
+/* Overwrite the current tuning params, we are about to tune */
+static void cx24116_clone_params(struct dvb_frontend *fe)
+{
+	struct cx24116_state *state = fe->demodulator_priv;
+	memcpy(&state->dcur, &state->dnxt, sizeof(state->dcur));
+}
+
+/* Wait for LNB */
+static int cx24116_wait_for_lnb(struct dvb_frontend *fe)
+{
+	struct cx24116_state *state = fe->demodulator_priv;
+	int i;
+
+	dprintk("%s() qstatus = 0x%02x\n", __func__,
+		cx24116_readreg(state, CX24116_REG_QSTATUS));
+
+	/* Wait for up to 300 ms */
+	for (i = 0; i < 30 ; i++) {
+		if (cx24116_readreg(state, CX24116_REG_QSTATUS) & 0x20)
+			return 0;
+		msleep(10);
+	}
+
+	dprintk("%s(): LNB not ready\n", __func__);
+
+	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)
+{
+	struct cx24116_cmd cmd;
+	int ret;
+
+	dprintk("%s(%d)\n", __func__, tone);
+	if ((tone != SEC_TONE_ON) && (tone != SEC_TONE_OFF)) {
+		printk(KERN_ERR "%s: Invalid, tone=%d\n", __func__, tone);
+		return -EINVAL;
+	}
+
+	/* Wait for LNB ready */
+	ret = cx24116_wait_for_lnb(fe);
+	if (ret != 0)
+		return ret;
+
+	/* Min delay time after DiSEqC send */
+	msleep(15); /* XXX determine is FW does this, see send_diseqc/burst */
+
+	/* Now we set the tone */
+	cmd.args[0x00] = CMD_SET_TONE;
+	cmd.args[0x01] = 0x00;
+	cmd.args[0x02] = 0x00;
+
+	switch (tone) {
+	case SEC_TONE_ON:
+		dprintk("%s: setting tone on\n", __func__);
+		cmd.args[0x03] = 0x01;
+		break;
+	case SEC_TONE_OFF:
+		dprintk("%s: setting tone off\n", __func__);
+		cmd.args[0x03] = 0x00;
+		break;
+	}
+	cmd.len = 0x04;
+
+	/* Min delay time before DiSEqC send */
+	msleep(15); /* XXX determine is FW does this, see send_diseqc/burst */
+
+	return cx24116_cmd_execute(fe, &cmd);
+}
+
+/* Initialise DiSEqC */
+static int cx24116_diseqc_init(struct dvb_frontend *fe)
+{
+	struct cx24116_state *state = fe->demodulator_priv;
+	struct cx24116_cmd cmd;
+	int ret;
+
+	/* Firmware CMD 20: LNB/DiSEqC config */
+	cmd.args[0x00] = CMD_LNBCONFIG;
+	cmd.args[0x01] = 0x00;
+	cmd.args[0x02] = 0x10;
+	cmd.args[0x03] = 0x00;
+	cmd.args[0x04] = 0x8f;
+	cmd.args[0x05] = 0x28;
+	cmd.args[0x06] = (toneburst == CX24116_DISEQC_TONEOFF) ? 0x00 : 0x01;
+	cmd.args[0x07] = 0x01;
+	cmd.len = 0x08;
+	ret = cx24116_cmd_execute(fe, &cmd);
+	if (ret != 0)
+		return ret;
+
+	/* Prepare a DiSEqC command */
+	state->dsec_cmd.args[0x00] = CMD_LNBSEND;
+
+	/* DiSEqC burst */
+	state->dsec_cmd.args[CX24116_DISEQC_BURST]  = CX24116_DISEQC_MINI_A;
+
+	/* Unknown */
+	state->dsec_cmd.args[CX24116_DISEQC_ARG2_2] = 0x02;
+	state->dsec_cmd.args[CX24116_DISEQC_ARG3_0] = 0x00;
+	/* Continuation flag? */
+	state->dsec_cmd.args[CX24116_DISEQC_ARG4_0] = 0x00;
+
+	/* DiSEqC message length */
+	state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] = 0x00;
+
+	/* Command length */
+	state->dsec_cmd.len = CX24116_DISEQC_MSGOFS;
+
+	return 0;
+}
+
+/* Send DiSEqC message with derived burst (hack) || previous burst */
+static int cx24116_send_diseqc_msg(struct dvb_frontend *fe,
+	struct dvb_diseqc_master_cmd *d)
+{
+	struct cx24116_state *state = fe->demodulator_priv;
+	int i, ret;
+
+	/* Dump DiSEqC message */
+	if (debug) {
+		printk(KERN_INFO "cx24116: %s(", __func__);
+		for (i = 0 ; i < d->msg_len ;) {
+			printk(KERN_INFO "0x%02x", d->msg[i]);
+			if (++i < d->msg_len)
+				printk(KERN_INFO ", ");
+		}
+		printk(") toneburst=%d\n", toneburst);
+	}
+
+	/* Validate length */
+	if (d->msg_len > (CX24116_ARGLEN - CX24116_DISEQC_MSGOFS))
+		return -EINVAL;
+
+	/* DiSEqC message */
+	for (i = 0; i < d->msg_len; i++)
+		state->dsec_cmd.args[CX24116_DISEQC_MSGOFS + i] = d->msg[i];
+
+	/* DiSEqC message length */
+	state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] = d->msg_len;
+
+	/* Command length */
+	state->dsec_cmd.len = CX24116_DISEQC_MSGOFS +
+		state->dsec_cmd.args[CX24116_DISEQC_MSGLEN];
+
+	/* DiSEqC toneburst */
+	if (toneburst == CX24116_DISEQC_MESGCACHE)
+		/* Message is cached */
+		return 0;
+
+	else if (toneburst == CX24116_DISEQC_TONEOFF)
+		/* Message is sent without burst */
+		state->dsec_cmd.args[CX24116_DISEQC_BURST] = 0;
+
+	else if (toneburst == CX24116_DISEQC_TONECACHE) {
+		/*
+		 * Message is sent with derived else cached burst
+		 *
+		 * WRITE PORT GROUP COMMAND 38
+		 *
+		 * 0/A/A: E0 10 38 F0..F3
+		 * 1/B/B: E0 10 38 F4..F7
+		 * 2/C/A: E0 10 38 F8..FB
+		 * 3/D/B: E0 10 38 FC..FF
+		 *
+		 * databyte[3]= 8421:8421
+		 *              ABCD:WXYZ
+		 *              CLR :SET
+		 *
+		 *              WX= PORT SELECT 0..3    (X=TONEBURST)
+		 *              Y = VOLTAGE             (0=13V, 1=18V)
+		 *              Z = BAND                (0=LOW, 1=HIGH(22K))
+		 */
+		if (d->msg_len >= 4 && d->msg[2] == 0x38)
+			state->dsec_cmd.args[CX24116_DISEQC_BURST] =
+				((d->msg[3] & 4) >> 2);
+		if (debug)
+			dprintk("%s burst=%d\n", __func__,
+				state->dsec_cmd.args[CX24116_DISEQC_BURST]);
+	}
+
+	/* Wait for LNB ready */
+	ret = cx24116_wait_for_lnb(fe);
+	if (ret != 0)
+		return ret;
+
+	/* Wait for voltage/min repeat delay */
+	msleep(100);
+
+	/* Command */
+	ret = cx24116_cmd_execute(fe, &state->dsec_cmd);
+	if (ret != 0)
+		return ret;
+	/*
+	 * Wait for send
+	 *
+	 * Eutelsat spec:
+	 * >15ms delay          + (XXX determine if FW does this, see set_tone)
+	 *  13.5ms per byte     +
+	 * >15ms delay          +
+	 *  12.5ms burst        +
+	 * >15ms delay            (XXX determine if FW does this, see set_tone)
+	 */
+	msleep((state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] << 4) +
+		((toneburst == CX24116_DISEQC_TONEOFF) ? 30 : 60));
+
+	return 0;
+}
+
+/* Send DiSEqC burst */
+static int cx24116_diseqc_send_burst(struct dvb_frontend *fe,
+	fe_sec_mini_cmd_t burst)
+{
+	struct cx24116_state *state = fe->demodulator_priv;
+	int ret;
+
+	dprintk("%s(%d) toneburst=%d\n", __func__, burst, toneburst);
+
+	/* DiSEqC burst */
+	if (burst == SEC_MINI_A)
+		state->dsec_cmd.args[CX24116_DISEQC_BURST] =
+			CX24116_DISEQC_MINI_A;
+	else if (burst == SEC_MINI_B)
+		state->dsec_cmd.args[CX24116_DISEQC_BURST] =
+			CX24116_DISEQC_MINI_B;
+	else
+		return -EINVAL;
+
+	/* DiSEqC toneburst */
+	if (toneburst != CX24116_DISEQC_MESGCACHE)
+		/* Burst is cached */
+		return 0;
+
+	/* Burst is to be sent with cached message */
+
+	/* Wait for LNB ready */
+	ret = cx24116_wait_for_lnb(fe);
+	if (ret != 0)
+		return ret;
+
+	/* Wait for voltage/min repeat delay */
+	msleep(100);
+
+	/* Command */
+	ret = cx24116_cmd_execute(fe, &state->dsec_cmd);
+	if (ret != 0)
+		return ret;
+
+	/*
+	 * Wait for send
+	 *
+	 * Eutelsat spec:
+	 * >15ms delay          + (XXX determine if FW does this, see set_tone)
+	 *  13.5ms per byte     +
+	 * >15ms delay          +
+	 *  12.5ms burst        +
+	 * >15ms delay            (XXX determine if FW does this, see set_tone)
+	 */
+	msleep((state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] << 4) + 60);
+
+	return 0;
+}
+
+static void cx24116_release(struct dvb_frontend *fe)
+{
+	struct cx24116_state *state = fe->demodulator_priv;
+	dprintk("%s\n", __func__);
+	kfree(state);
+}
+
+static struct dvb_frontend_ops cx24116_ops;
+
+struct dvb_frontend *cx24116_attach(const struct cx24116_config *config,
+	struct i2c_adapter *i2c)
+{
+	struct cx24116_state *state = NULL;
+	int ret;
+
+	dprintk("%s\n", __func__);
+
+	/* allocate memory for the internal state */
+	state = kzalloc(sizeof(struct cx24116_state), GFP_KERNEL);
+	if (state == NULL)
+		goto error1;
+
+	state->config = config;
+	state->i2c = i2c;
+
+	/* check if the demod is present */
+	ret = (cx24116_readreg(state, 0xFF) << 8) |
+		cx24116_readreg(state, 0xFE);
+	if (ret != 0x0501) {
+		printk(KERN_INFO "Invalid probe, probably not a CX24116 device\n");
+		goto error2;
+	}
+
+	/* create dvb_frontend */
+	memcpy(&state->frontend.ops, &cx24116_ops,
+		sizeof(struct dvb_frontend_ops));
+	state->frontend.demodulator_priv = state;
+	return &state->frontend;
+
+error2: kfree(state);
+error1: return NULL;
+}
+EXPORT_SYMBOL(cx24116_attach);
+
+/*
+ * Initialise or wake up device
+ *
+ * Power config will reset and load initial firmware if required
+ */
+static int cx24116_initfe(struct dvb_frontend *fe)
+{
+	struct cx24116_state *state = fe->demodulator_priv;
+	struct cx24116_cmd cmd;
+	int ret;
+
+	dprintk("%s()\n", __func__);
+
+	/* Power on */
+	cx24116_writereg(state, 0xe0, 0);
+	cx24116_writereg(state, 0xe1, 0);
+	cx24116_writereg(state, 0xea, 0);
+
+	/* Firmware CMD 36: Power config */
+	cmd.args[0x00] = CMD_TUNERSLEEP;
+	cmd.args[0x01] = 0;
+	cmd.len = 0x02;
+	ret = cx24116_cmd_execute(fe, &cmd);
+	if (ret != 0)
+		return ret;
+
+	ret = cx24116_diseqc_init(fe);
+	if (ret != 0)
+		return ret;
+
+	/* HVR-4000 needs this */
+	return cx24116_set_voltage(fe, SEC_VOLTAGE_13);
+}
+
+/*
+ * Put device to sleep
+ */
+static int cx24116_sleep(struct dvb_frontend *fe)
+{
+	struct cx24116_state *state = fe->demodulator_priv;
+	struct cx24116_cmd cmd;
+	int ret;
+
+	dprintk("%s()\n", __func__);
+
+	/* Firmware CMD 36: Power config */
+	cmd.args[0x00] = CMD_TUNERSLEEP;
+	cmd.args[0x01] = 1;
+	cmd.len = 0x02;
+	ret = cx24116_cmd_execute(fe, &cmd);
+	if (ret != 0)
+		return ret;
+
+	/* Power off (Shutdown clocks) */
+	cx24116_writereg(state, 0xea, 0xff);
+	cx24116_writereg(state, 0xe1, 1);
+	cx24116_writereg(state, 0xe0, 1);
+
+	return 0;
+}
+
+/* dvb-core told us to tune, the tv property cache will be complete,
+ * it's safe for is to pull values and use them for tuning purposes.
+ */
+static int cx24116_set_frontend(struct dvb_frontend *fe)
+{
+	struct cx24116_state *state = fe->demodulator_priv;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	struct cx24116_cmd cmd;
+	fe_status_t tunerstat;
+	int i, status, ret, retune = 1;
+
+	dprintk("%s()\n", __func__);
+
+	switch (c->delivery_system) {
+	case SYS_DVBS:
+		dprintk("%s: DVB-S delivery system selected\n", __func__);
+
+		/* Only QPSK is supported for DVB-S */
+		if (c->modulation != QPSK) {
+			dprintk("%s: unsupported modulation selected (%d)\n",
+				__func__, c->modulation);
+			return -EOPNOTSUPP;
+		}
+
+		/* Pilot doesn't exist in DVB-S, turn bit off */
+		state->dnxt.pilot_val = CX24116_PILOT_OFF;
+
+		/* DVB-S only supports 0.35 */
+		if (c->rolloff != ROLLOFF_35) {
+			dprintk("%s: unsupported rolloff selected (%d)\n",
+				__func__, c->rolloff);
+			return -EOPNOTSUPP;
+		}
+		state->dnxt.rolloff_val = CX24116_ROLLOFF_035;
+		break;
+
+	case SYS_DVBS2:
+		dprintk("%s: DVB-S2 delivery system selected\n", __func__);
+
+		/*
+		 * NBC 8PSK/QPSK with DVB-S is supported for DVB-S2,
+		 * but not hardware auto detection
+		 */
+		if (c->modulation != PSK_8 && c->modulation != QPSK) {
+			dprintk("%s: unsupported modulation selected (%d)\n",
+				__func__, c->modulation);
+			return -EOPNOTSUPP;
+		}
+
+		switch (c->pilot) {
+		case PILOT_AUTO:	/* Not supported but emulated */
+			state->dnxt.pilot_val = (c->modulation == QPSK)
+				? CX24116_PILOT_OFF : CX24116_PILOT_ON;
+			retune++;
+			break;
+		case PILOT_OFF:
+			state->dnxt.pilot_val = CX24116_PILOT_OFF;
+			break;
+		case PILOT_ON:
+			state->dnxt.pilot_val = CX24116_PILOT_ON;
+			break;
+		default:
+			dprintk("%s: unsupported pilot mode selected (%d)\n",
+				__func__, c->pilot);
+			return -EOPNOTSUPP;
+		}
+
+		switch (c->rolloff) {
+		case ROLLOFF_20:
+			state->dnxt.rolloff_val = CX24116_ROLLOFF_020;
+			break;
+		case ROLLOFF_25:
+			state->dnxt.rolloff_val = CX24116_ROLLOFF_025;
+			break;
+		case ROLLOFF_35:
+			state->dnxt.rolloff_val = CX24116_ROLLOFF_035;
+			break;
+		case ROLLOFF_AUTO:	/* Rolloff must be explicit */
+		default:
+			dprintk("%s: unsupported rolloff selected (%d)\n",
+				__func__, c->rolloff);
+			return -EOPNOTSUPP;
+		}
+		break;
+
+	default:
+		dprintk("%s: unsupported delivery system selected (%d)\n",
+			__func__, c->delivery_system);
+		return -EOPNOTSUPP;
+	}
+	state->dnxt.delsys = c->delivery_system;
+	state->dnxt.modulation = c->modulation;
+	state->dnxt.frequency = c->frequency;
+	state->dnxt.pilot = c->pilot;
+	state->dnxt.rolloff = c->rolloff;
+
+	ret = cx24116_set_inversion(state, c->inversion);
+	if (ret !=  0)
+		return ret;
+
+	/* FEC_NONE/AUTO for DVB-S2 is not supported and detected here */
+	ret = cx24116_set_fec(state, c->delivery_system, c->modulation, c->fec_inner);
+	if (ret !=  0)
+		return ret;
+
+	ret = cx24116_set_symbolrate(state, c->symbol_rate);
+	if (ret !=  0)
+		return ret;
+
+	/* discard the 'current' tuning parameters and prepare to tune */
+	cx24116_clone_params(fe);
+
+	dprintk("%s:   delsys      = %d\n", __func__, state->dcur.delsys);
+	dprintk("%s:   modulation  = %d\n", __func__, state->dcur.modulation);
+	dprintk("%s:   frequency   = %d\n", __func__, state->dcur.frequency);
+	dprintk("%s:   pilot       = %d (val = 0x%02x)\n", __func__,
+		state->dcur.pilot, state->dcur.pilot_val);
+	dprintk("%s:   retune      = %d\n", __func__, retune);
+	dprintk("%s:   rolloff     = %d (val = 0x%02x)\n", __func__,
+		state->dcur.rolloff, state->dcur.rolloff_val);
+	dprintk("%s:   symbol_rate = %d\n", __func__, state->dcur.symbol_rate);
+	dprintk("%s:   FEC         = %d (mask/val = 0x%02x/0x%02x)\n", __func__,
+		state->dcur.fec, state->dcur.fec_mask, state->dcur.fec_val);
+	dprintk("%s:   Inversion   = %d (val = 0x%02x)\n", __func__,
+		state->dcur.inversion, state->dcur.inversion_val);
+
+	/* This is also done in advise/acquire on HVR4000 but not on LITE */
+	if (state->config->set_ts_params)
+		state->config->set_ts_params(fe, 0);
+
+	/* Set/Reset B/W */
+	cmd.args[0x00] = CMD_BANDWIDTH;
+	cmd.args[0x01] = 0x01;
+	cmd.len = 0x02;
+	ret = cx24116_cmd_execute(fe, &cmd);
+	if (ret != 0)
+		return ret;
+
+	/* Prepare a tune request */
+	cmd.args[0x00] = CMD_TUNEREQUEST;
+
+	/* Frequency */
+	cmd.args[0x01] = (state->dcur.frequency & 0xff0000) >> 16;
+	cmd.args[0x02] = (state->dcur.frequency & 0x00ff00) >> 8;
+	cmd.args[0x03] = (state->dcur.frequency & 0x0000ff);
+
+	/* Symbol Rate */
+	cmd.args[0x04] = ((state->dcur.symbol_rate / 1000) & 0xff00) >> 8;
+	cmd.args[0x05] = ((state->dcur.symbol_rate / 1000) & 0x00ff);
+
+	/* Automatic Inversion */
+	cmd.args[0x06] = state->dcur.inversion_val;
+
+	/* Modulation / FEC / Pilot */
+	cmd.args[0x07] = state->dcur.fec_val | state->dcur.pilot_val;
+
+	cmd.args[0x08] = CX24116_SEARCH_RANGE_KHZ >> 8;
+	cmd.args[0x09] = CX24116_SEARCH_RANGE_KHZ & 0xff;
+	cmd.args[0x0a] = 0x00;
+	cmd.args[0x0b] = 0x00;
+	cmd.args[0x0c] = state->dcur.rolloff_val;
+	cmd.args[0x0d] = state->dcur.fec_mask;
+
+	if (state->dcur.symbol_rate > 30000000) {
+		cmd.args[0x0e] = 0x04;
+		cmd.args[0x0f] = 0x00;
+		cmd.args[0x10] = 0x01;
+		cmd.args[0x11] = 0x77;
+		cmd.args[0x12] = 0x36;
+		cx24116_writereg(state, CX24116_REG_CLKDIV, 0x44);
+		cx24116_writereg(state, CX24116_REG_RATEDIV, 0x01);
+	} else {
+		cmd.args[0x0e] = 0x06;
+		cmd.args[0x0f] = 0x00;
+		cmd.args[0x10] = 0x00;
+		cmd.args[0x11] = 0xFA;
+		cmd.args[0x12] = 0x24;
+		cx24116_writereg(state, CX24116_REG_CLKDIV, 0x46);
+		cx24116_writereg(state, CX24116_REG_RATEDIV, 0x00);
+	}
+
+	cmd.len = 0x13;
+
+	/* We need to support pilot and non-pilot tuning in the
+	 * driver automatically. This is a workaround for because
+	 * the demod does not support autodetect.
+	 */
+	do {
+		/* Reset status register */
+		status = cx24116_readreg(state, CX24116_REG_SSTATUS)
+			& CX24116_SIGNAL_MASK;
+		cx24116_writereg(state, CX24116_REG_SSTATUS, status);
+
+		/* Tune */
+		ret = cx24116_cmd_execute(fe, &cmd);
+		if (ret != 0)
+			break;
+
+		/*
+		 * Wait for up to 500 ms before retrying
+		 *
+		 * If we are able to tune then generally it occurs within 100ms.
+		 * If it takes longer, try a different toneburst setting.
+		 */
+		for (i = 0; i < 50 ; i++) {
+			cx24116_read_status(fe, &tunerstat);
+			status = tunerstat & (FE_HAS_SIGNAL | FE_HAS_SYNC);
+			if (status == (FE_HAS_SIGNAL | FE_HAS_SYNC)) {
+				dprintk("%s: Tuned\n", __func__);
+				goto tuned;
+			}
+			msleep(10);
+		}
+
+		dprintk("%s: Not tuned\n", __func__);
+
+		/* Toggle pilot bit when in auto-pilot */
+		if (state->dcur.pilot == PILOT_AUTO)
+			cmd.args[0x07] ^= CX24116_PILOT_ON;
+	} while (--retune);
+
+tuned:  /* Set/Reset B/W */
+	cmd.args[0x00] = CMD_BANDWIDTH;
+	cmd.args[0x01] = 0x00;
+	cmd.len = 0x02;
+	return cx24116_cmd_execute(fe, &cmd);
+}
+
+static int cx24116_tune(struct dvb_frontend *fe, bool re_tune,
+	unsigned int mode_flags, unsigned int *delay, fe_status_t *status)
+{
+	/*
+	 * It is safe to discard "params" here, as the DVB core will sync
+	 * fe->dtv_property_cache with fepriv->parameters_in, where the
+	 * DVBv3 params are stored. The only practical usage for it indicate
+	 * that re-tuning is needed, e. g. (fepriv->state & FESTATE_RETUNE) is
+	 * true.
+	 */
+
+	*delay = HZ / 5;
+	if (re_tune) {
+		int ret = cx24116_set_frontend(fe);
+		if (ret)
+			return ret;
+	}
+	return cx24116_read_status(fe, status);
+}
+
+static int cx24116_get_algo(struct dvb_frontend *fe)
+{
+	return DVBFE_ALGO_HW;
+}
+
+static struct dvb_frontend_ops cx24116_ops = {
+	.delsys = { SYS_DVBS, SYS_DVBS2 },
+	.info = {
+		.name = "Conexant CX24116/CX24118",
+		.frequency_min = 950000,
+		.frequency_max = 2150000,
+		.frequency_stepsize = 1011, /* kHz for QPSK frontends */
+		.frequency_tolerance = 5000,
+		.symbol_rate_min = 1000000,
+		.symbol_rate_max = 45000000,
+		.caps = FE_CAN_INVERSION_AUTO |
+			FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
+			FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
+			FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
+			FE_CAN_2G_MODULATION |
+			FE_CAN_QPSK | FE_CAN_RECOVER
+	},
+
+	.release = cx24116_release,
+
+	.init = cx24116_initfe,
+	.sleep = cx24116_sleep,
+	.read_status = cx24116_read_status,
+	.read_ber = cx24116_read_ber,
+	.read_signal_strength = cx24116_read_signal_strength,
+	.read_snr = cx24116_read_snr,
+	.read_ucblocks = cx24116_read_ucblocks,
+	.set_tone = cx24116_set_tone,
+	.set_voltage = cx24116_set_voltage,
+	.diseqc_send_master_cmd = cx24116_send_diseqc_msg,
+	.diseqc_send_burst = cx24116_diseqc_send_burst,
+	.get_frontend_algo = cx24116_get_algo,
+	.tune = cx24116_tune,
+
+	.set_frontend = cx24116_set_frontend,
+};
+
+MODULE_DESCRIPTION("DVB Frontend module for Conexant cx24116/cx24118 hardware");
+MODULE_AUTHOR("Steven Toth");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/media/dvb-frontends/cx24116.h b/drivers/media/dvb-frontends/cx24116.h
new file mode 100644
index 0000000..7d90ab9
--- /dev/null
+++ b/drivers/media/dvb-frontends/cx24116.h
@@ -0,0 +1,58 @@
+/*
+    Conexant cx24116/cx24118 - DVBS/S2 Satellite demod/tuner driver
+
+    Copyright (C) 2006 Steven Toth <stoth@linuxtv.com>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef CX24116_H
+#define CX24116_H
+
+#include <linux/dvb/frontend.h>
+
+struct cx24116_config {
+	/* the demodulator's i2c address */
+	u8 demod_address;
+
+	/* Need to set device param for start_dma */
+	int (*set_ts_params)(struct dvb_frontend *fe, int is_punctured);
+
+	/* Need to reset device during firmware loading */
+	int (*reset_device)(struct dvb_frontend *fe);
+
+	/* Need to set MPEG parameters */
+	u8 mpg_clk_pos_pol:0x02;
+
+	/* max bytes I2C provider can write at once */
+	u16 i2c_wr_max;
+};
+
+#if defined(CONFIG_DVB_CX24116) || \
+	(defined(CONFIG_DVB_CX24116_MODULE) && defined(MODULE))
+extern struct dvb_frontend *cx24116_attach(
+	const struct cx24116_config *config,
+	struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend *cx24116_attach(
+	const struct cx24116_config *config,
+	struct i2c_adapter *i2c)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif
+
+#endif /* CX24116_H */
diff --git a/drivers/media/dvb-frontends/cx24123.c b/drivers/media/dvb-frontends/cx24123.c
new file mode 100644
index 0000000..7e28b4e
--- /dev/null
+++ b/drivers/media/dvb-frontends/cx24123.c
@@ -0,0 +1,1165 @@
+/*
+ *   Conexant cx24123/cx24109 - DVB QPSK Satellite demod/tuner driver
+ *
+ *   Copyright (C) 2005 Steven Toth <stoth@linuxtv.org>
+ *
+ *   Support for KWorld DVB-S 100 by Vadim Catana <skystar@moldova.cc>
+ *
+ *   Support for CX24123/CX24113-NIM by Patrick Boettcher <pb@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/slab.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include "dvb_frontend.h"
+#include "cx24123.h"
+
+#define XTAL 10111000
+
+static int force_band;
+module_param(force_band, int, 0644);
+MODULE_PARM_DESC(force_band, "Force a specific band select "\
+	"(1-9, default:off).");
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)");
+
+#define info(args...) do { printk(KERN_INFO "CX24123: " args); } while (0)
+#define err(args...)  do { printk(KERN_ERR  "CX24123: " args); } while (0)
+
+#define dprintk(args...) \
+	do { \
+		if (debug) { \
+			printk(KERN_DEBUG "CX24123: %s: ", __func__); \
+			printk(args); \
+		} \
+	} while (0)
+
+struct cx24123_state {
+	struct i2c_adapter *i2c;
+	const struct cx24123_config *config;
+
+	struct dvb_frontend frontend;
+
+	/* Some PLL specifics for tuning */
+	u32 VCAarg;
+	u32 VGAarg;
+	u32 bandselectarg;
+	u32 pllarg;
+	u32 FILTune;
+
+	struct i2c_adapter tuner_i2c_adapter;
+
+	u8 demod_rev;
+
+	/* The Demod/Tuner can't easily provide these, we cache them */
+	u32 currentfreq;
+	u32 currentsymbolrate;
+};
+
+/* Various tuner defaults need to be established for a given symbol rate Sps */
+static struct cx24123_AGC_val {
+	u32 symbolrate_low;
+	u32 symbolrate_high;
+	u32 VCAprogdata;
+	u32 VGAprogdata;
+	u32 FILTune;
+} cx24123_AGC_vals[] =
+{
+	{
+		.symbolrate_low		= 1000000,
+		.symbolrate_high	= 4999999,
+		/* the specs recommend other values for VGA offsets,
+		   but tests show they are wrong */
+		.VGAprogdata		= (1 << 19) | (0x180 << 9) | 0x1e0,
+		.VCAprogdata		= (2 << 19) | (0x07 << 9) | 0x07,
+		.FILTune		= 0x27f /* 0.41 V */
+	},
+	{
+		.symbolrate_low		=  5000000,
+		.symbolrate_high	= 14999999,
+		.VGAprogdata		= (1 << 19) | (0x180 << 9) | 0x1e0,
+		.VCAprogdata		= (2 << 19) | (0x07 << 9) | 0x1f,
+		.FILTune		= 0x317 /* 0.90 V */
+	},
+	{
+		.symbolrate_low		= 15000000,
+		.symbolrate_high	= 45000000,
+		.VGAprogdata		= (1 << 19) | (0x100 << 9) | 0x180,
+		.VCAprogdata		= (2 << 19) | (0x07 << 9) | 0x3f,
+		.FILTune		= 0x145 /* 2.70 V */
+	},
+};
+
+/*
+ * Various tuner defaults need to be established for a given frequency kHz.
+ * fixme: The bounds on the bands do not match the doc in real life.
+ * fixme: Some of them have been moved, other might need adjustment.
+ */
+static struct cx24123_bandselect_val {
+	u32 freq_low;
+	u32 freq_high;
+	u32 VCOdivider;
+	u32 progdata;
+} cx24123_bandselect_vals[] =
+{
+	/* band 1 */
+	{
+		.freq_low	= 950000,
+		.freq_high	= 1074999,
+		.VCOdivider	= 4,
+		.progdata	= (0 << 19) | (0 << 9) | 0x40,
+	},
+
+	/* band 2 */
+	{
+		.freq_low	= 1075000,
+		.freq_high	= 1177999,
+		.VCOdivider	= 4,
+		.progdata	= (0 << 19) | (0 << 9) | 0x80,
+	},
+
+	/* band 3 */
+	{
+		.freq_low	= 1178000,
+		.freq_high	= 1295999,
+		.VCOdivider	= 2,
+		.progdata	= (0 << 19) | (1 << 9) | 0x01,
+	},
+
+	/* band 4 */
+	{
+		.freq_low	= 1296000,
+		.freq_high	= 1431999,
+		.VCOdivider	= 2,
+		.progdata	= (0 << 19) | (1 << 9) | 0x02,
+	},
+
+	/* band 5 */
+	{
+		.freq_low	= 1432000,
+		.freq_high	= 1575999,
+		.VCOdivider	= 2,
+		.progdata	= (0 << 19) | (1 << 9) | 0x04,
+	},
+
+	/* band 6 */
+	{
+		.freq_low	= 1576000,
+		.freq_high	= 1717999,
+		.VCOdivider	= 2,
+		.progdata	= (0 << 19) | (1 << 9) | 0x08,
+	},
+
+	/* band 7 */
+	{
+		.freq_low	= 1718000,
+		.freq_high	= 1855999,
+		.VCOdivider	= 2,
+		.progdata	= (0 << 19) | (1 << 9) | 0x10,
+	},
+
+	/* band 8 */
+	{
+		.freq_low	= 1856000,
+		.freq_high	= 2035999,
+		.VCOdivider	= 2,
+		.progdata	= (0 << 19) | (1 << 9) | 0x20,
+	},
+
+	/* band 9 */
+	{
+		.freq_low	= 2036000,
+		.freq_high	= 2150000,
+		.VCOdivider	= 2,
+		.progdata	= (0 << 19) | (1 << 9) | 0x40,
+	},
+};
+
+static struct {
+	u8 reg;
+	u8 data;
+} cx24123_regdata[] =
+{
+	{0x00, 0x03}, /* Reset system */
+	{0x00, 0x00}, /* Clear reset */
+	{0x03, 0x07}, /* QPSK, DVB, Auto Acquisition (default) */
+	{0x04, 0x10}, /* MPEG */
+	{0x05, 0x04}, /* MPEG */
+	{0x06, 0x31}, /* MPEG (default) */
+	{0x0b, 0x00}, /* Freq search start point (default) */
+	{0x0c, 0x00}, /* Demodulator sample gain (default) */
+	{0x0d, 0x7f}, /* Force driver to shift until the maximum (+-10 MHz) */
+	{0x0e, 0x03}, /* Default non-inverted, FEC 3/4 (default) */
+	{0x0f, 0xfe}, /* FEC search mask (all supported codes) */
+	{0x10, 0x01}, /* Default search inversion, no repeat (default) */
+	{0x16, 0x00}, /* Enable reading of frequency */
+	{0x17, 0x01}, /* Enable EsNO Ready Counter */
+	{0x1c, 0x80}, /* Enable error counter */
+	{0x20, 0x00}, /* Tuner burst clock rate = 500KHz */
+	{0x21, 0x15}, /* Tuner burst mode, word length = 0x15 */
+	{0x28, 0x00}, /* Enable FILTERV with positive pol., DiSEqC 2.x off */
+	{0x29, 0x00}, /* DiSEqC LNB_DC off */
+	{0x2a, 0xb0}, /* DiSEqC Parameters (default) */
+	{0x2b, 0x73}, /* DiSEqC Tone Frequency (default) */
+	{0x2c, 0x00}, /* DiSEqC Message (0x2c - 0x31) */
+	{0x2d, 0x00},
+	{0x2e, 0x00},
+	{0x2f, 0x00},
+	{0x30, 0x00},
+	{0x31, 0x00},
+	{0x32, 0x8c}, /* DiSEqC Parameters (default) */
+	{0x33, 0x00}, /* Interrupts off (0x33 - 0x34) */
+	{0x34, 0x00},
+	{0x35, 0x03}, /* DiSEqC Tone Amplitude (default) */
+	{0x36, 0x02}, /* DiSEqC Parameters (default) */
+	{0x37, 0x3a}, /* DiSEqC Parameters (default) */
+	{0x3a, 0x00}, /* Enable AGC accumulator (for signal strength) */
+	{0x44, 0x00}, /* Constellation (default) */
+	{0x45, 0x00}, /* Symbol count (default) */
+	{0x46, 0x0d}, /* Symbol rate estimator on (default) */
+	{0x56, 0xc1}, /* Error Counter = Viterbi BER */
+	{0x57, 0xff}, /* Error Counter Window (default) */
+	{0x5c, 0x20}, /* Acquisition AFC Expiration window (default is 0x10) */
+	{0x67, 0x83}, /* Non-DCII symbol clock */
+};
+
+static int cx24123_i2c_writereg(struct cx24123_state *state,
+	u8 i2c_addr, int reg, int data)
+{
+	u8 buf[] = { reg, data };
+	struct i2c_msg msg = {
+		.addr = i2c_addr, .flags = 0, .buf = buf, .len = 2
+	};
+	int err;
+
+	/* printk(KERN_DEBUG "wr(%02x): %02x %02x\n", i2c_addr, reg, data); */
+
+	err = i2c_transfer(state->i2c, &msg, 1);
+	if (err != 1) {
+		printk("%s: writereg error(err == %i, reg == 0x%02x,"
+			 " data == 0x%02x)\n", __func__, err, reg, data);
+		return err;
+	}
+
+	return 0;
+}
+
+static int cx24123_i2c_readreg(struct cx24123_state *state, u8 i2c_addr, u8 reg)
+{
+	int ret;
+	u8 b = 0;
+	struct i2c_msg msg[] = {
+		{ .addr = i2c_addr, .flags = 0, .buf = &reg, .len = 1 },
+		{ .addr = i2c_addr, .flags = I2C_M_RD, .buf = &b, .len = 1 }
+	};
+
+	ret = i2c_transfer(state->i2c, msg, 2);
+
+	if (ret != 2) {
+		err("%s: reg=0x%x (error=%d)\n", __func__, reg, ret);
+		return ret;
+	}
+
+	/* printk(KERN_DEBUG "rd(%02x): %02x %02x\n", i2c_addr, reg, b); */
+
+	return b;
+}
+
+#define cx24123_readreg(state, reg) \
+	cx24123_i2c_readreg(state, state->config->demod_address, reg)
+#define cx24123_writereg(state, reg, val) \
+	cx24123_i2c_writereg(state, state->config->demod_address, reg, val)
+
+static int cx24123_set_inversion(struct cx24123_state *state,
+	fe_spectral_inversion_t inversion)
+{
+	u8 nom_reg = cx24123_readreg(state, 0x0e);
+	u8 auto_reg = cx24123_readreg(state, 0x10);
+
+	switch (inversion) {
+	case INVERSION_OFF:
+		dprintk("inversion off\n");
+		cx24123_writereg(state, 0x0e, nom_reg & ~0x80);
+		cx24123_writereg(state, 0x10, auto_reg | 0x80);
+		break;
+	case INVERSION_ON:
+		dprintk("inversion on\n");
+		cx24123_writereg(state, 0x0e, nom_reg | 0x80);
+		cx24123_writereg(state, 0x10, auto_reg | 0x80);
+		break;
+	case INVERSION_AUTO:
+		dprintk("inversion auto\n");
+		cx24123_writereg(state, 0x10, auto_reg & ~0x80);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int cx24123_get_inversion(struct cx24123_state *state,
+	fe_spectral_inversion_t *inversion)
+{
+	u8 val;
+
+	val = cx24123_readreg(state, 0x1b) >> 7;
+
+	if (val == 0) {
+		dprintk("read inversion off\n");
+		*inversion = INVERSION_OFF;
+	} else {
+		dprintk("read inversion on\n");
+		*inversion = INVERSION_ON;
+	}
+
+	return 0;
+}
+
+static int cx24123_set_fec(struct cx24123_state *state, fe_code_rate_t fec)
+{
+	u8 nom_reg = cx24123_readreg(state, 0x0e) & ~0x07;
+
+	if ((fec < FEC_NONE) || (fec > FEC_AUTO))
+		fec = FEC_AUTO;
+
+	/* Set the soft decision threshold */
+	if (fec == FEC_1_2)
+		cx24123_writereg(state, 0x43,
+			cx24123_readreg(state, 0x43) | 0x01);
+	else
+		cx24123_writereg(state, 0x43,
+			cx24123_readreg(state, 0x43) & ~0x01);
+
+	switch (fec) {
+	case FEC_1_2:
+		dprintk("set FEC to 1/2\n");
+		cx24123_writereg(state, 0x0e, nom_reg | 0x01);
+		cx24123_writereg(state, 0x0f, 0x02);
+		break;
+	case FEC_2_3:
+		dprintk("set FEC to 2/3\n");
+		cx24123_writereg(state, 0x0e, nom_reg | 0x02);
+		cx24123_writereg(state, 0x0f, 0x04);
+		break;
+	case FEC_3_4:
+		dprintk("set FEC to 3/4\n");
+		cx24123_writereg(state, 0x0e, nom_reg | 0x03);
+		cx24123_writereg(state, 0x0f, 0x08);
+		break;
+	case FEC_4_5:
+		dprintk("set FEC to 4/5\n");
+		cx24123_writereg(state, 0x0e, nom_reg | 0x04);
+		cx24123_writereg(state, 0x0f, 0x10);
+		break;
+	case FEC_5_6:
+		dprintk("set FEC to 5/6\n");
+		cx24123_writereg(state, 0x0e, nom_reg | 0x05);
+		cx24123_writereg(state, 0x0f, 0x20);
+		break;
+	case FEC_6_7:
+		dprintk("set FEC to 6/7\n");
+		cx24123_writereg(state, 0x0e, nom_reg | 0x06);
+		cx24123_writereg(state, 0x0f, 0x40);
+		break;
+	case FEC_7_8:
+		dprintk("set FEC to 7/8\n");
+		cx24123_writereg(state, 0x0e, nom_reg | 0x07);
+		cx24123_writereg(state, 0x0f, 0x80);
+		break;
+	case FEC_AUTO:
+		dprintk("set FEC to auto\n");
+		cx24123_writereg(state, 0x0f, 0xfe);
+		break;
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	return 0;
+}
+
+static int cx24123_get_fec(struct cx24123_state *state, fe_code_rate_t *fec)
+{
+	int ret;
+
+	ret = cx24123_readreg(state, 0x1b);
+	if (ret < 0)
+		return ret;
+	ret = ret & 0x07;
+
+	switch (ret) {
+	case 1:
+		*fec = FEC_1_2;
+		break;
+	case 2:
+		*fec = FEC_2_3;
+		break;
+	case 3:
+		*fec = FEC_3_4;
+		break;
+	case 4:
+		*fec = FEC_4_5;
+		break;
+	case 5:
+		*fec = FEC_5_6;
+		break;
+	case 6:
+		*fec = FEC_6_7;
+		break;
+	case 7:
+		*fec = FEC_7_8;
+		break;
+	default:
+		/* this can happen when there's no lock */
+		*fec = FEC_NONE;
+	}
+
+	return 0;
+}
+
+/* Approximation of closest integer of log2(a/b). It actually gives the
+   lowest integer i such that 2^i >= round(a/b) */
+static u32 cx24123_int_log2(u32 a, u32 b)
+{
+	u32 exp, nearest = 0;
+	u32 div = a / b;
+	if (a % b >= b / 2)
+		++div;
+	if (div < (1 << 31)) {
+		for (exp = 1; div > exp; nearest++)
+			exp += exp;
+	}
+	return nearest;
+}
+
+static int cx24123_set_symbolrate(struct cx24123_state *state, u32 srate)
+{
+	u32 tmp, sample_rate, ratio, sample_gain;
+	u8 pll_mult;
+
+	/*  check if symbol rate is within limits */
+	if ((srate > state->frontend.ops.info.symbol_rate_max) ||
+	    (srate < state->frontend.ops.info.symbol_rate_min))
+		return -EOPNOTSUPP;
+
+	/* choose the sampling rate high enough for the required operation,
+	   while optimizing the power consumed by the demodulator */
+	if (srate < (XTAL*2)/2)
+		pll_mult = 2;
+	else if (srate < (XTAL*3)/2)
+		pll_mult = 3;
+	else if (srate < (XTAL*4)/2)
+		pll_mult = 4;
+	else if (srate < (XTAL*5)/2)
+		pll_mult = 5;
+	else if (srate < (XTAL*6)/2)
+		pll_mult = 6;
+	else if (srate < (XTAL*7)/2)
+		pll_mult = 7;
+	else if (srate < (XTAL*8)/2)
+		pll_mult = 8;
+	else
+		pll_mult = 9;
+
+
+	sample_rate = pll_mult * XTAL;
+
+	/*
+	    SYSSymbolRate[21:0] = (srate << 23) / sample_rate
+
+	    We have to use 32 bit unsigned arithmetic without precision loss.
+	    The maximum srate is 45000000 or 0x02AEA540. This number has
+	    only 6 clear bits on top, hence we can shift it left only 6 bits
+	    at a time. Borrowed from cx24110.c
+	*/
+
+	tmp = srate << 6;
+	ratio = tmp / sample_rate;
+
+	tmp = (tmp % sample_rate) << 6;
+	ratio = (ratio << 6) + (tmp / sample_rate);
+
+	tmp = (tmp % sample_rate) << 6;
+	ratio = (ratio << 6) + (tmp / sample_rate);
+
+	tmp = (tmp % sample_rate) << 5;
+	ratio = (ratio << 5) + (tmp / sample_rate);
+
+
+	cx24123_writereg(state, 0x01, pll_mult * 6);
+
+	cx24123_writereg(state, 0x08, (ratio >> 16) & 0x3f);
+	cx24123_writereg(state, 0x09, (ratio >> 8) & 0xff);
+	cx24123_writereg(state, 0x0a, ratio & 0xff);
+
+	/* also set the demodulator sample gain */
+	sample_gain = cx24123_int_log2(sample_rate, srate);
+	tmp = cx24123_readreg(state, 0x0c) & ~0xe0;
+	cx24123_writereg(state, 0x0c, tmp | sample_gain << 5);
+
+	dprintk("srate=%d, ratio=0x%08x, sample_rate=%i sample_gain=%d\n",
+		srate, ratio, sample_rate, sample_gain);
+
+	return 0;
+}
+
+/*
+ * Based on the required frequency and symbolrate, the tuner AGC has
+ * to be configured and the correct band selected.
+ * Calculate those values.
+ */
+static int cx24123_pll_calculate(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct cx24123_state *state = fe->demodulator_priv;
+	u32 ndiv = 0, adiv = 0, vco_div = 0;
+	int i = 0;
+	int pump = 2;
+	int band = 0;
+	int num_bands = ARRAY_SIZE(cx24123_bandselect_vals);
+	struct cx24123_bandselect_val *bsv = NULL;
+	struct cx24123_AGC_val *agcv = NULL;
+
+	/* Defaults for low freq, low rate */
+	state->VCAarg = cx24123_AGC_vals[0].VCAprogdata;
+	state->VGAarg = cx24123_AGC_vals[0].VGAprogdata;
+	state->bandselectarg = cx24123_bandselect_vals[0].progdata;
+	vco_div = cx24123_bandselect_vals[0].VCOdivider;
+
+	/* For the given symbol rate, determine the VCA, VGA and
+	 * FILTUNE programming bits */
+	for (i = 0; i < ARRAY_SIZE(cx24123_AGC_vals); i++) {
+		agcv = &cx24123_AGC_vals[i];
+		if ((agcv->symbolrate_low <= p->symbol_rate) &&
+		    (agcv->symbolrate_high >= p->symbol_rate)) {
+			state->VCAarg = agcv->VCAprogdata;
+			state->VGAarg = agcv->VGAprogdata;
+			state->FILTune = agcv->FILTune;
+		}
+	}
+
+	/* determine the band to use */
+	if (force_band < 1 || force_band > num_bands) {
+		for (i = 0; i < num_bands; i++) {
+			bsv = &cx24123_bandselect_vals[i];
+			if ((bsv->freq_low <= p->frequency) &&
+				(bsv->freq_high >= p->frequency))
+				band = i;
+		}
+	} else
+		band = force_band - 1;
+
+	state->bandselectarg = cx24123_bandselect_vals[band].progdata;
+	vco_div = cx24123_bandselect_vals[band].VCOdivider;
+
+	/* determine the charge pump current */
+	if (p->frequency < (cx24123_bandselect_vals[band].freq_low +
+		cx24123_bandselect_vals[band].freq_high) / 2)
+		pump = 0x01;
+	else
+		pump = 0x02;
+
+	/* Determine the N/A dividers for the requested lband freq (in kHz). */
+	/* Note: the reference divider R=10, frequency is in KHz,
+	 * XTAL is in Hz */
+	ndiv = (((p->frequency * vco_div * 10) /
+		(2 * XTAL / 1000)) / 32) & 0x1ff;
+	adiv = (((p->frequency * vco_div * 10) /
+		(2 * XTAL / 1000)) % 32) & 0x1f;
+
+	if (adiv == 0 && ndiv > 0)
+		ndiv--;
+
+	/* control bits 11, refdiv 11, charge pump polarity 1,
+	 * charge pump current, ndiv, adiv */
+	state->pllarg = (3 << 19) | (3 << 17) | (1 << 16) |
+		(pump << 14) | (ndiv << 5) | adiv;
+
+	return 0;
+}
+
+/*
+ * Tuner data is 21 bits long, must be left-aligned in data.
+ * Tuner cx24109 is written through a dedicated 3wire interface
+ * on the demod chip.
+ */
+static int cx24123_pll_writereg(struct dvb_frontend *fe, u32 data)
+{
+	struct cx24123_state *state = fe->demodulator_priv;
+	unsigned long timeout;
+
+	dprintk("pll writereg called, data=0x%08x\n", data);
+
+	/* align the 21 bytes into to bit23 boundary */
+	data = data << 3;
+
+	/* Reset the demod pll word length to 0x15 bits */
+	cx24123_writereg(state, 0x21, 0x15);
+
+	/* write the msb 8 bits, wait for the send to be completed */
+	timeout = jiffies + msecs_to_jiffies(40);
+	cx24123_writereg(state, 0x22, (data >> 16) & 0xff);
+	while ((cx24123_readreg(state, 0x20) & 0x40) == 0) {
+		if (time_after(jiffies, timeout)) {
+			err("%s:  demodulator is not responding, "\
+				"possibly hung, aborting.\n", __func__);
+			return -EREMOTEIO;
+		}
+		msleep(10);
+	}
+
+	/* send another 8 bytes, wait for the send to be completed */
+	timeout = jiffies + msecs_to_jiffies(40);
+	cx24123_writereg(state, 0x22, (data >> 8) & 0xff);
+	while ((cx24123_readreg(state, 0x20) & 0x40) == 0) {
+		if (time_after(jiffies, timeout)) {
+			err("%s:  demodulator is not responding, "\
+				"possibly hung, aborting.\n", __func__);
+			return -EREMOTEIO;
+		}
+		msleep(10);
+	}
+
+	/* send the lower 5 bits of this byte, padded with 3 LBB,
+	 * wait for the send to be completed */
+	timeout = jiffies + msecs_to_jiffies(40);
+	cx24123_writereg(state, 0x22, (data) & 0xff);
+	while ((cx24123_readreg(state, 0x20) & 0x80)) {
+		if (time_after(jiffies, timeout)) {
+			err("%s:  demodulator is not responding," \
+				"possibly hung, aborting.\n", __func__);
+			return -EREMOTEIO;
+		}
+		msleep(10);
+	}
+
+	/* Trigger the demod to configure the tuner */
+	cx24123_writereg(state, 0x20, cx24123_readreg(state, 0x20) | 2);
+	cx24123_writereg(state, 0x20, cx24123_readreg(state, 0x20) & 0xfd);
+
+	return 0;
+}
+
+static int cx24123_pll_tune(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct cx24123_state *state = fe->demodulator_priv;
+	u8 val;
+
+	dprintk("frequency=%i\n", p->frequency);
+
+	if (cx24123_pll_calculate(fe) != 0) {
+		err("%s: cx24123_pll_calcutate failed\n", __func__);
+		return -EINVAL;
+	}
+
+	/* Write the new VCO/VGA */
+	cx24123_pll_writereg(fe, state->VCAarg);
+	cx24123_pll_writereg(fe, state->VGAarg);
+
+	/* Write the new bandselect and pll args */
+	cx24123_pll_writereg(fe, state->bandselectarg);
+	cx24123_pll_writereg(fe, state->pllarg);
+
+	/* set the FILTUNE voltage */
+	val = cx24123_readreg(state, 0x28) & ~0x3;
+	cx24123_writereg(state, 0x27, state->FILTune >> 2);
+	cx24123_writereg(state, 0x28, val | (state->FILTune & 0x3));
+
+	dprintk("pll tune VCA=%d, band=%d, pll=%d\n", state->VCAarg,
+			state->bandselectarg, state->pllarg);
+
+	return 0;
+}
+
+
+/*
+ * 0x23:
+ *    [7:7] = BTI enabled
+ *    [6:6] = I2C repeater enabled
+ *    [5:5] = I2C repeater start
+ *    [0:0] = BTI start
+ */
+
+/* mode == 1 -> i2c-repeater, 0 -> bti */
+static int cx24123_repeater_mode(struct cx24123_state *state, u8 mode, u8 start)
+{
+	u8 r = cx24123_readreg(state, 0x23) & 0x1e;
+	if (mode)
+		r |= (1 << 6) | (start << 5);
+	else
+		r |= (1 << 7) | (start);
+	return cx24123_writereg(state, 0x23, r);
+}
+
+static int cx24123_initfe(struct dvb_frontend *fe)
+{
+	struct cx24123_state *state = fe->demodulator_priv;
+	int i;
+
+	dprintk("init frontend\n");
+
+	/* Configure the demod to a good set of defaults */
+	for (i = 0; i < ARRAY_SIZE(cx24123_regdata); i++)
+		cx24123_writereg(state, cx24123_regdata[i].reg,
+			cx24123_regdata[i].data);
+
+	/* Set the LNB polarity */
+	if (state->config->lnb_polarity)
+		cx24123_writereg(state, 0x32,
+			cx24123_readreg(state, 0x32) | 0x02);
+
+	if (state->config->dont_use_pll)
+		cx24123_repeater_mode(state, 1, 0);
+
+	return 0;
+}
+
+static int cx24123_set_voltage(struct dvb_frontend *fe,
+	fe_sec_voltage_t voltage)
+{
+	struct cx24123_state *state = fe->demodulator_priv;
+	u8 val;
+
+	val = cx24123_readreg(state, 0x29) & ~0x40;
+
+	switch (voltage) {
+	case SEC_VOLTAGE_13:
+		dprintk("setting voltage 13V\n");
+		return cx24123_writereg(state, 0x29, val & 0x7f);
+	case SEC_VOLTAGE_18:
+		dprintk("setting voltage 18V\n");
+		return cx24123_writereg(state, 0x29, val | 0x80);
+	case SEC_VOLTAGE_OFF:
+		/* already handled in cx88-dvb */
+		return 0;
+	default:
+		return -EINVAL;
+	};
+
+	return 0;
+}
+
+/* wait for diseqc queue to become ready (or timeout) */
+static void cx24123_wait_for_diseqc(struct cx24123_state *state)
+{
+	unsigned long timeout = jiffies + msecs_to_jiffies(200);
+	while (!(cx24123_readreg(state, 0x29) & 0x40)) {
+		if (time_after(jiffies, timeout)) {
+			err("%s: diseqc queue not ready, " \
+				"command may be lost.\n", __func__);
+			break;
+		}
+		msleep(10);
+	}
+}
+
+static int cx24123_send_diseqc_msg(struct dvb_frontend *fe,
+	struct dvb_diseqc_master_cmd *cmd)
+{
+	struct cx24123_state *state = fe->demodulator_priv;
+	int i, val, tone;
+
+	dprintk("\n");
+
+	/* stop continuous tone if enabled */
+	tone = cx24123_readreg(state, 0x29);
+	if (tone & 0x10)
+		cx24123_writereg(state, 0x29, tone & ~0x50);
+
+	/* wait for diseqc queue ready */
+	cx24123_wait_for_diseqc(state);
+
+	/* select tone mode */
+	cx24123_writereg(state, 0x2a, cx24123_readreg(state, 0x2a) & 0xfb);
+
+	for (i = 0; i < cmd->msg_len; i++)
+		cx24123_writereg(state, 0x2C + i, cmd->msg[i]);
+
+	val = cx24123_readreg(state, 0x29);
+	cx24123_writereg(state, 0x29, ((val & 0x90) | 0x40) |
+		((cmd->msg_len-3) & 3));
+
+	/* wait for diseqc message to finish sending */
+	cx24123_wait_for_diseqc(state);
+
+	/* restart continuous tone if enabled */
+	if (tone & 0x10)
+		cx24123_writereg(state, 0x29, tone & ~0x40);
+
+	return 0;
+}
+
+static int cx24123_diseqc_send_burst(struct dvb_frontend *fe,
+	fe_sec_mini_cmd_t burst)
+{
+	struct cx24123_state *state = fe->demodulator_priv;
+	int val, tone;
+
+	dprintk("\n");
+
+	/* stop continuous tone if enabled */
+	tone = cx24123_readreg(state, 0x29);
+	if (tone & 0x10)
+		cx24123_writereg(state, 0x29, tone & ~0x50);
+
+	/* wait for diseqc queue ready */
+	cx24123_wait_for_diseqc(state);
+
+	/* select tone mode */
+	cx24123_writereg(state, 0x2a, cx24123_readreg(state, 0x2a) | 0x4);
+	msleep(30);
+	val = cx24123_readreg(state, 0x29);
+	if (burst == SEC_MINI_A)
+		cx24123_writereg(state, 0x29, ((val & 0x90) | 0x40 | 0x00));
+	else if (burst == SEC_MINI_B)
+		cx24123_writereg(state, 0x29, ((val & 0x90) | 0x40 | 0x08));
+	else
+		return -EINVAL;
+
+	cx24123_wait_for_diseqc(state);
+	cx24123_writereg(state, 0x2a, cx24123_readreg(state, 0x2a) & 0xfb);
+
+	/* restart continuous tone if enabled */
+	if (tone & 0x10)
+		cx24123_writereg(state, 0x29, tone & ~0x40);
+
+	return 0;
+}
+
+static int cx24123_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+	struct cx24123_state *state = fe->demodulator_priv;
+	int sync = cx24123_readreg(state, 0x14);
+
+	*status = 0;
+	if (state->config->dont_use_pll) {
+		u32 tun_status = 0;
+		if (fe->ops.tuner_ops.get_status)
+			fe->ops.tuner_ops.get_status(fe, &tun_status);
+		if (tun_status & TUNER_STATUS_LOCKED)
+			*status |= FE_HAS_SIGNAL;
+	} else {
+		int lock = cx24123_readreg(state, 0x20);
+		if (lock & 0x01)
+			*status |= FE_HAS_SIGNAL;
+	}
+
+	if (sync & 0x02)
+		*status |= FE_HAS_CARRIER;	/* Phase locked */
+	if (sync & 0x04)
+		*status |= FE_HAS_VITERBI;
+
+	/* Reed-Solomon Status */
+	if (sync & 0x08)
+		*status |= FE_HAS_SYNC;
+	if (sync & 0x80)
+		*status |= FE_HAS_LOCK;		/*Full Sync */
+
+	return 0;
+}
+
+/*
+ * Configured to return the measurement of errors in blocks,
+ * because no UCBLOCKS value is available, so this value doubles up
+ * to satisfy both measurements.
+ */
+static int cx24123_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+	struct cx24123_state *state = fe->demodulator_priv;
+
+	/* The true bit error rate is this value divided by
+	   the window size (set as 256 * 255) */
+	*ber = ((cx24123_readreg(state, 0x1c) & 0x3f) << 16) |
+		(cx24123_readreg(state, 0x1d) << 8 |
+		 cx24123_readreg(state, 0x1e));
+
+	dprintk("BER = %d\n", *ber);
+
+	return 0;
+}
+
+static int cx24123_read_signal_strength(struct dvb_frontend *fe,
+	u16 *signal_strength)
+{
+	struct cx24123_state *state = fe->demodulator_priv;
+
+	/* larger = better */
+	*signal_strength = cx24123_readreg(state, 0x3b) << 8;
+
+	dprintk("Signal strength = %d\n", *signal_strength);
+
+	return 0;
+}
+
+static int cx24123_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+	struct cx24123_state *state = fe->demodulator_priv;
+
+	/* Inverted raw Es/N0 count, totally bogus but better than the
+	   BER threshold. */
+	*snr = 65535 - (((u16)cx24123_readreg(state, 0x18) << 8) |
+			 (u16)cx24123_readreg(state, 0x19));
+
+	dprintk("read S/N index = %d\n", *snr);
+
+	return 0;
+}
+
+static int cx24123_set_frontend(struct dvb_frontend *fe)
+{
+	struct cx24123_state *state = fe->demodulator_priv;
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+
+	dprintk("\n");
+
+	if (state->config->set_ts_params)
+		state->config->set_ts_params(fe, 0);
+
+	state->currentfreq = p->frequency;
+	state->currentsymbolrate = p->symbol_rate;
+
+	cx24123_set_inversion(state, p->inversion);
+	cx24123_set_fec(state, p->fec_inner);
+	cx24123_set_symbolrate(state, p->symbol_rate);
+
+	if (!state->config->dont_use_pll)
+		cx24123_pll_tune(fe);
+	else if (fe->ops.tuner_ops.set_params)
+		fe->ops.tuner_ops.set_params(fe);
+	else
+		err("it seems I don't have a tuner...");
+
+	/* Enable automatic acquisition and reset cycle */
+	cx24123_writereg(state, 0x03, (cx24123_readreg(state, 0x03) | 0x07));
+	cx24123_writereg(state, 0x00, 0x10);
+	cx24123_writereg(state, 0x00, 0);
+
+	if (state->config->agc_callback)
+		state->config->agc_callback(fe);
+
+	return 0;
+}
+
+static int cx24123_get_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct cx24123_state *state = fe->demodulator_priv;
+
+	dprintk("\n");
+
+	if (cx24123_get_inversion(state, &p->inversion) != 0) {
+		err("%s: Failed to get inversion status\n", __func__);
+		return -EREMOTEIO;
+	}
+	if (cx24123_get_fec(state, &p->fec_inner) != 0) {
+		err("%s: Failed to get fec status\n", __func__);
+		return -EREMOTEIO;
+	}
+	p->frequency = state->currentfreq;
+	p->symbol_rate = state->currentsymbolrate;
+
+	return 0;
+}
+
+static int cx24123_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
+{
+	struct cx24123_state *state = fe->demodulator_priv;
+	u8 val;
+
+	/* wait for diseqc queue ready */
+	cx24123_wait_for_diseqc(state);
+
+	val = cx24123_readreg(state, 0x29) & ~0x40;
+
+	switch (tone) {
+	case SEC_TONE_ON:
+		dprintk("setting tone on\n");
+		return cx24123_writereg(state, 0x29, val | 0x10);
+	case SEC_TONE_OFF:
+		dprintk("setting tone off\n");
+		return cx24123_writereg(state, 0x29, val & 0xef);
+	default:
+		err("CASE reached default with tone=%d\n", tone);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int cx24123_tune(struct dvb_frontend *fe,
+			bool re_tune,
+			unsigned int mode_flags,
+			unsigned int *delay,
+			fe_status_t *status)
+{
+	int retval = 0;
+
+	if (re_tune)
+		retval = cx24123_set_frontend(fe);
+
+	if (!(mode_flags & FE_TUNE_MODE_ONESHOT))
+		cx24123_read_status(fe, status);
+	*delay = HZ/10;
+
+	return retval;
+}
+
+static int cx24123_get_algo(struct dvb_frontend *fe)
+{
+	return 1; /* FE_ALGO_HW */
+}
+
+static void cx24123_release(struct dvb_frontend *fe)
+{
+	struct cx24123_state *state = fe->demodulator_priv;
+	dprintk("\n");
+	i2c_del_adapter(&state->tuner_i2c_adapter);
+	kfree(state);
+}
+
+static int cx24123_tuner_i2c_tuner_xfer(struct i2c_adapter *i2c_adap,
+	struct i2c_msg msg[], int num)
+{
+	struct cx24123_state *state = i2c_get_adapdata(i2c_adap);
+	/* this repeater closes after the first stop */
+	cx24123_repeater_mode(state, 1, 1);
+	return i2c_transfer(state->i2c, msg, num);
+}
+
+static u32 cx24123_tuner_i2c_func(struct i2c_adapter *adapter)
+{
+	return I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm cx24123_tuner_i2c_algo = {
+	.master_xfer   = cx24123_tuner_i2c_tuner_xfer,
+	.functionality = cx24123_tuner_i2c_func,
+};
+
+struct i2c_adapter *
+	cx24123_get_tuner_i2c_adapter(struct dvb_frontend *fe)
+{
+	struct cx24123_state *state = fe->demodulator_priv;
+	return &state->tuner_i2c_adapter;
+}
+EXPORT_SYMBOL(cx24123_get_tuner_i2c_adapter);
+
+static struct dvb_frontend_ops cx24123_ops;
+
+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");
+	if (state == NULL) {
+		err("Unable to kzalloc\n");
+		goto error;
+	}
+
+	/* setup the state */
+	state->config = config;
+	state->i2c = i2c;
+
+	/* check if the demod is there */
+	state->demod_rev = cx24123_readreg(state, 0x00);
+	switch (state->demod_rev) {
+	case 0xe1:
+		info("detected CX24123C\n");
+		break;
+	case 0xd1:
+		info("detected CX24123\n");
+		break;
+	default:
+		err("wrong demod revision: %x\n", state->demod_rev);
+		goto error;
+	}
+
+	/* create dvb_frontend */
+	memcpy(&state->frontend.ops, &cx24123_ops,
+		sizeof(struct dvb_frontend_ops));
+	state->frontend.demodulator_priv = state;
+
+	/* create tuner i2c adapter */
+	if (config->dont_use_pll)
+		cx24123_repeater_mode(state, 1, 0);
+
+	strlcpy(state->tuner_i2c_adapter.name, "CX24123 tuner I2C bus",
+		sizeof(state->tuner_i2c_adapter.name));
+	state->tuner_i2c_adapter.algo      = &cx24123_tuner_i2c_algo;
+	state->tuner_i2c_adapter.algo_data = NULL;
+	i2c_set_adapdata(&state->tuner_i2c_adapter, state);
+	if (i2c_add_adapter(&state->tuner_i2c_adapter) < 0) {
+		err("tuner i2c bus could not be initialized\n");
+		goto error;
+	}
+
+	return &state->frontend;
+
+error:
+	kfree(state);
+
+	return NULL;
+}
+EXPORT_SYMBOL(cx24123_attach);
+
+static struct dvb_frontend_ops cx24123_ops = {
+	.delsys = { SYS_DVBS },
+	.info = {
+		.name = "Conexant CX24123/CX24109",
+		.frequency_min = 950000,
+		.frequency_max = 2150000,
+		.frequency_stepsize = 1011, /* kHz for QPSK frontends */
+		.frequency_tolerance = 5000,
+		.symbol_rate_min = 1000000,
+		.symbol_rate_max = 45000000,
+		.caps = FE_CAN_INVERSION_AUTO |
+			FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
+			FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
+			FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
+			FE_CAN_QPSK | FE_CAN_RECOVER
+	},
+
+	.release = cx24123_release,
+
+	.init = cx24123_initfe,
+	.set_frontend = cx24123_set_frontend,
+	.get_frontend = cx24123_get_frontend,
+	.read_status = cx24123_read_status,
+	.read_ber = cx24123_read_ber,
+	.read_signal_strength = cx24123_read_signal_strength,
+	.read_snr = cx24123_read_snr,
+	.diseqc_send_master_cmd = cx24123_send_diseqc_msg,
+	.diseqc_send_burst = cx24123_diseqc_send_burst,
+	.set_tone = cx24123_set_tone,
+	.set_voltage = cx24123_set_voltage,
+	.tune = cx24123_tune,
+	.get_frontend_algo = cx24123_get_algo,
+};
+
+MODULE_DESCRIPTION("DVB Frontend module for Conexant " \
+	"CX24123/CX24109/CX24113 hardware");
+MODULE_AUTHOR("Steven Toth");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/media/dvb-frontends/cx24123.h b/drivers/media/dvb-frontends/cx24123.h
new file mode 100644
index 0000000..51ae866
--- /dev/null
+++ b/drivers/media/dvb-frontends/cx24123.h
@@ -0,0 +1,61 @@
+/*
+    Conexant cx24123/cx24109 - DVB QPSK Satellite demod/tuner driver
+
+    Copyright (C) 2005 Steven Toth <stoth@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 CX24123_H
+#define CX24123_H
+
+#include <linux/dvb/frontend.h>
+
+struct cx24123_config {
+	/* the demodulator's i2c address */
+	u8 demod_address;
+
+	/* Need to set device param for start_dma */
+	int (*set_ts_params)(struct dvb_frontend *fe, int is_punctured);
+
+	/* 0 = LNB voltage normal, 1 = LNB voltage inverted */
+	int lnb_polarity;
+
+	/* this device has another tuner */
+	u8 dont_use_pll;
+	void (*agc_callback) (struct dvb_frontend *);
+};
+
+#if defined(CONFIG_DVB_CX24123) || (defined(CONFIG_DVB_CX24123_MODULE) \
+	&& defined(MODULE))
+extern struct dvb_frontend *cx24123_attach(const struct cx24123_config *config,
+					   struct i2c_adapter *i2c);
+extern struct i2c_adapter *cx24123_get_tuner_i2c_adapter(struct dvb_frontend *);
+#else
+static inline struct dvb_frontend *cx24123_attach(
+	const struct cx24123_config *config, struct i2c_adapter *i2c)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+static struct i2c_adapter *
+	cx24123_get_tuner_i2c_adapter(struct dvb_frontend *fe)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif
+
+#endif /* CX24123_H */
diff --git a/drivers/media/dvb-frontends/cxd2820r.h b/drivers/media/dvb-frontends/cxd2820r.h
new file mode 100644
index 0000000..5aa306e
--- /dev/null
+++ b/drivers/media/dvb-frontends/cxd2820r.h
@@ -0,0 +1,94 @@
+/*
+ * Sony CXD2820R demodulator driver
+ *
+ * Copyright (C) 2010 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.,
+ *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+
+#ifndef CXD2820R_H
+#define CXD2820R_H
+
+#include <linux/dvb/frontend.h>
+
+#define CXD2820R_GPIO_D (0 << 0) /* disable */
+#define CXD2820R_GPIO_E (1 << 0) /* enable */
+#define CXD2820R_GPIO_O (0 << 1) /* output */
+#define CXD2820R_GPIO_I (1 << 1) /* input */
+#define CXD2820R_GPIO_L (0 << 2) /* output low */
+#define CXD2820R_GPIO_H (1 << 2) /* output high */
+
+#define CXD2820R_TS_SERIAL        0x08
+#define CXD2820R_TS_SERIAL_MSB    0x28
+#define CXD2820R_TS_PARALLEL      0x30
+#define CXD2820R_TS_PARALLEL_MSB  0x70
+
+struct cxd2820r_config {
+	/* Demodulator I2C address.
+	 * Driver determines DVB-C slave I2C address automatically from master
+	 * address.
+	 * Default: none, must set
+	 * Values: 0x6c, 0x6d
+	 */
+	u8 i2c_address;
+
+	/* TS output mode.
+	 * Default: none, must set.
+	 * Values:
+	 */
+	u8 ts_mode;
+
+	/* IF AGC polarity.
+	 * Default: 0
+	 * Values: 0, 1
+	 */
+	bool if_agc_polarity;
+
+	/* Spectrum inversion.
+	 * Default: 0
+	 * Values: 0, 1
+	 */
+	bool spec_inv;
+
+	/* GPIOs for all used modes.
+	 * Default: none, disabled
+	 * Values: <see above>
+	 */
+	u8 gpio_dvbt[3];
+	u8 gpio_dvbt2[3];
+	u8 gpio_dvbc[3];
+};
+
+
+#if defined(CONFIG_DVB_CXD2820R) || \
+	(defined(CONFIG_DVB_CXD2820R_MODULE) && defined(MODULE))
+extern struct dvb_frontend *cxd2820r_attach(
+	const struct cxd2820r_config *config,
+	struct i2c_adapter *i2c
+);
+#else
+static inline struct dvb_frontend *cxd2820r_attach(
+	const struct cxd2820r_config *config,
+	struct i2c_adapter *i2c
+)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+
+#endif
+
+#endif /* CXD2820R_H */
diff --git a/drivers/media/dvb-frontends/cxd2820r_c.c b/drivers/media/dvb-frontends/cxd2820r_c.c
new file mode 100644
index 0000000..ed3b0ba6
--- /dev/null
+++ b/drivers/media/dvb-frontends/cxd2820r_c.c
@@ -0,0 +1,346 @@
+/*
+ * Sony CXD2820R demodulator driver
+ *
+ * Copyright (C) 2010 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.,
+ *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+
+#include "cxd2820r_priv.h"
+
+int cxd2820r_set_frontend_c(struct dvb_frontend *fe)
+{
+	struct cxd2820r_priv *priv = fe->demodulator_priv;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	int ret, i;
+	u8 buf[2];
+	u32 if_freq;
+	u16 if_ctl;
+	u64 num;
+	struct reg_val_mask tab[] = {
+		{ 0x00080, 0x01, 0xff },
+		{ 0x00081, 0x05, 0xff },
+		{ 0x00085, 0x07, 0xff },
+		{ 0x00088, 0x01, 0xff },
+
+		{ 0x00082, 0x20, 0x60 },
+		{ 0x1016a, 0x48, 0xff },
+		{ 0x100a5, 0x00, 0x01 },
+		{ 0x10020, 0x06, 0x07 },
+		{ 0x10059, 0x50, 0xff },
+		{ 0x10087, 0x0c, 0x3c },
+		{ 0x1008b, 0x07, 0xff },
+		{ 0x1001f, priv->cfg.if_agc_polarity << 7, 0x80 },
+		{ 0x10070, priv->cfg.ts_mode, 0xff },
+	};
+
+	dbg("%s: RF=%d SR=%d", __func__, c->frequency, c->symbol_rate);
+
+	/* update GPIOs */
+	ret = cxd2820r_gpio(fe);
+	if (ret)
+		goto error;
+
+	/* program tuner */
+	if (fe->ops.tuner_ops.set_params)
+		fe->ops.tuner_ops.set_params(fe);
+
+	if (priv->delivery_system !=  SYS_DVBC_ANNEX_A) {
+		for (i = 0; i < ARRAY_SIZE(tab); i++) {
+			ret = cxd2820r_wr_reg_mask(priv, tab[i].reg,
+				tab[i].val, tab[i].mask);
+			if (ret)
+				goto error;
+		}
+	}
+
+	priv->delivery_system = SYS_DVBC_ANNEX_A;
+	priv->ber_running = 0; /* tune stops BER counter */
+
+	/* program IF frequency */
+	if (fe->ops.tuner_ops.get_if_frequency) {
+		ret = fe->ops.tuner_ops.get_if_frequency(fe, &if_freq);
+		if (ret)
+			goto error;
+	} else
+		if_freq = 0;
+
+	dbg("%s: if_freq=%d", __func__, if_freq);
+
+	num = if_freq / 1000; /* Hz => kHz */
+	num *= 0x4000;
+	if_ctl = cxd2820r_div_u64_round_closest(num, 41000);
+	buf[0] = (if_ctl >> 8) & 0x3f;
+	buf[1] = (if_ctl >> 0) & 0xff;
+
+	ret = cxd2820r_wr_regs(priv, 0x10042, buf, 2);
+	if (ret)
+		goto error;
+
+	ret = cxd2820r_wr_reg(priv, 0x000ff, 0x08);
+	if (ret)
+		goto error;
+
+	ret = cxd2820r_wr_reg(priv, 0x000fe, 0x01);
+	if (ret)
+		goto error;
+
+	return ret;
+error:
+	dbg("%s: failed:%d", __func__, ret);
+	return ret;
+}
+
+int cxd2820r_get_frontend_c(struct dvb_frontend *fe)
+{
+	struct cxd2820r_priv *priv = fe->demodulator_priv;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	int ret;
+	u8 buf[2];
+
+	ret = cxd2820r_rd_regs(priv, 0x1001a, buf, 2);
+	if (ret)
+		goto error;
+
+	c->symbol_rate = 2500 * ((buf[0] & 0x0f) << 8 | buf[1]);
+
+	ret = cxd2820r_rd_reg(priv, 0x10019, &buf[0]);
+	if (ret)
+		goto error;
+
+	switch ((buf[0] >> 0) & 0x07) {
+	case 0:
+		c->modulation = QAM_16;
+		break;
+	case 1:
+		c->modulation = QAM_32;
+		break;
+	case 2:
+		c->modulation = QAM_64;
+		break;
+	case 3:
+		c->modulation = QAM_128;
+		break;
+	case 4:
+		c->modulation = QAM_256;
+		break;
+	}
+
+	switch ((buf[0] >> 7) & 0x01) {
+	case 0:
+		c->inversion = INVERSION_OFF;
+		break;
+	case 1:
+		c->inversion = INVERSION_ON;
+		break;
+	}
+
+	return ret;
+error:
+	dbg("%s: failed:%d", __func__, ret);
+	return ret;
+}
+
+int cxd2820r_read_ber_c(struct dvb_frontend *fe, u32 *ber)
+{
+	struct cxd2820r_priv *priv = fe->demodulator_priv;
+	int ret;
+	u8 buf[3], start_ber = 0;
+	*ber = 0;
+
+	if (priv->ber_running) {
+		ret = cxd2820r_rd_regs(priv, 0x10076, buf, sizeof(buf));
+		if (ret)
+			goto error;
+
+		if ((buf[2] >> 7) & 0x01 || (buf[2] >> 4) & 0x01) {
+			*ber = (buf[2] & 0x0f) << 16 | buf[1] << 8 | buf[0];
+			start_ber = 1;
+		}
+	} else {
+		priv->ber_running = 1;
+		start_ber = 1;
+	}
+
+	if (start_ber) {
+		/* (re)start BER */
+		ret = cxd2820r_wr_reg(priv, 0x10079, 0x01);
+		if (ret)
+			goto error;
+	}
+
+	return ret;
+error:
+	dbg("%s: failed:%d", __func__, ret);
+	return ret;
+}
+
+int cxd2820r_read_signal_strength_c(struct dvb_frontend *fe,
+	u16 *strength)
+{
+	struct cxd2820r_priv *priv = fe->demodulator_priv;
+	int ret;
+	u8 buf[2];
+	u16 tmp;
+
+	ret = cxd2820r_rd_regs(priv, 0x10049, buf, sizeof(buf));
+	if (ret)
+		goto error;
+
+	tmp = (buf[0] & 0x03) << 8 | buf[1];
+	tmp = (~tmp & 0x03ff);
+
+	if (tmp == 512)
+		/* ~no signal */
+		tmp = 0;
+	else if (tmp > 350)
+		tmp = 350;
+
+	/* scale value to 0x0000-0xffff */
+	*strength = tmp * 0xffff / (350-0);
+
+	return ret;
+error:
+	dbg("%s: failed:%d", __func__, ret);
+	return ret;
+}
+
+int cxd2820r_read_snr_c(struct dvb_frontend *fe, u16 *snr)
+{
+	struct cxd2820r_priv *priv = fe->demodulator_priv;
+	int ret;
+	u8 tmp;
+	unsigned int A, B;
+	/* report SNR in dB * 10 */
+
+	ret = cxd2820r_rd_reg(priv, 0x10019, &tmp);
+	if (ret)
+		goto error;
+
+	if (((tmp >> 0) & 0x03) % 2) {
+		A = 875;
+		B = 650;
+	} else {
+		A = 950;
+		B = 760;
+	}
+
+	ret = cxd2820r_rd_reg(priv, 0x1004d, &tmp);
+	if (ret)
+		goto error;
+
+	#define CXD2820R_LOG2_E_24 24204406 /* log2(e) << 24 */
+	if (tmp)
+		*snr = A * (intlog2(B / tmp) >> 5) / (CXD2820R_LOG2_E_24 >> 5)
+			/ 10;
+	else
+		*snr = 0;
+
+	return ret;
+error:
+	dbg("%s: failed:%d", __func__, ret);
+	return ret;
+}
+
+int cxd2820r_read_ucblocks_c(struct dvb_frontend *fe, u32 *ucblocks)
+{
+	*ucblocks = 0;
+	/* no way to read ? */
+	return 0;
+}
+
+int cxd2820r_read_status_c(struct dvb_frontend *fe, fe_status_t *status)
+{
+	struct cxd2820r_priv *priv = fe->demodulator_priv;
+	int ret;
+	u8 buf[2];
+	*status = 0;
+
+	ret = cxd2820r_rd_regs(priv, 0x10088, buf, sizeof(buf));
+	if (ret)
+		goto error;
+
+	if (((buf[0] >> 0) & 0x01) == 1) {
+		*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
+			FE_HAS_VITERBI | FE_HAS_SYNC;
+
+		if (((buf[1] >> 3) & 0x01) == 1) {
+			*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
+				FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
+		}
+	}
+
+	dbg("%s: lock=%02x %02x", __func__, buf[0], buf[1]);
+
+	return ret;
+error:
+	dbg("%s: failed:%d", __func__, ret);
+	return ret;
+}
+
+int cxd2820r_init_c(struct dvb_frontend *fe)
+{
+	struct cxd2820r_priv *priv = fe->demodulator_priv;
+	int ret;
+
+	ret = cxd2820r_wr_reg(priv, 0x00085, 0x07);
+	if (ret)
+		goto error;
+
+	return ret;
+error:
+	dbg("%s: failed:%d", __func__, ret);
+	return ret;
+}
+
+int cxd2820r_sleep_c(struct dvb_frontend *fe)
+{
+	struct cxd2820r_priv *priv = fe->demodulator_priv;
+	int ret, i;
+	struct reg_val_mask tab[] = {
+		{ 0x000ff, 0x1f, 0xff },
+		{ 0x00085, 0x00, 0xff },
+		{ 0x00088, 0x01, 0xff },
+		{ 0x00081, 0x00, 0xff },
+		{ 0x00080, 0x00, 0xff },
+	};
+
+	dbg("%s", __func__);
+
+	priv->delivery_system = SYS_UNDEFINED;
+
+	for (i = 0; i < ARRAY_SIZE(tab); i++) {
+		ret = cxd2820r_wr_reg_mask(priv, tab[i].reg, tab[i].val,
+			tab[i].mask);
+		if (ret)
+			goto error;
+	}
+
+	return ret;
+error:
+	dbg("%s: failed:%d", __func__, ret);
+	return ret;
+}
+
+int cxd2820r_get_tune_settings_c(struct dvb_frontend *fe,
+	struct dvb_frontend_tune_settings *s)
+{
+	s->min_delay_ms = 500;
+	s->step_size = 0; /* no zigzag */
+	s->max_drift = 0;
+
+	return 0;
+}
diff --git a/drivers/media/dvb-frontends/cxd2820r_core.c b/drivers/media/dvb-frontends/cxd2820r_core.c
new file mode 100644
index 0000000..3bba37d
--- /dev/null
+++ b/drivers/media/dvb-frontends/cxd2820r_core.c
@@ -0,0 +1,646 @@
+/*
+ * Sony CXD2820R demodulator driver
+ *
+ * Copyright (C) 2010 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.,
+ *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+
+#include "cxd2820r_priv.h"
+
+int cxd2820r_debug;
+module_param_named(debug, cxd2820r_debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+
+/* write multiple registers */
+static int cxd2820r_wr_regs_i2c(struct cxd2820r_priv *priv, u8 i2c, u8 reg,
+	u8 *val, int len)
+{
+	int ret;
+	u8 buf[len+1];
+	struct i2c_msg msg[1] = {
+		{
+			.addr = i2c,
+			.flags = 0,
+			.len = sizeof(buf),
+			.buf = buf,
+		}
+	};
+
+	buf[0] = reg;
+	memcpy(&buf[1], val, len);
+
+	ret = i2c_transfer(priv->i2c, msg, 1);
+	if (ret == 1) {
+		ret = 0;
+	} else {
+		warn("i2c wr failed ret:%d reg:%02x len:%d", ret, reg, len);
+		ret = -EREMOTEIO;
+	}
+	return ret;
+}
+
+/* read multiple registers */
+static int cxd2820r_rd_regs_i2c(struct cxd2820r_priv *priv, u8 i2c, u8 reg,
+	u8 *val, int len)
+{
+	int ret;
+	u8 buf[len];
+	struct i2c_msg msg[2] = {
+		{
+			.addr = i2c,
+			.flags = 0,
+			.len = 1,
+			.buf = &reg,
+		}, {
+			.addr = i2c,
+			.flags = I2C_M_RD,
+			.len = sizeof(buf),
+			.buf = buf,
+		}
+	};
+
+	ret = i2c_transfer(priv->i2c, msg, 2);
+	if (ret == 2) {
+		memcpy(val, buf, len);
+		ret = 0;
+	} else {
+		warn("i2c rd failed ret:%d reg:%02x len:%d", ret, reg, len);
+		ret = -EREMOTEIO;
+	}
+
+	return ret;
+}
+
+/* write multiple registers */
+int cxd2820r_wr_regs(struct cxd2820r_priv *priv, u32 reginfo, u8 *val,
+	int len)
+{
+	int ret;
+	u8 i2c_addr;
+	u8 reg = (reginfo >> 0) & 0xff;
+	u8 bank = (reginfo >> 8) & 0xff;
+	u8 i2c = (reginfo >> 16) & 0x01;
+
+	/* select I2C */
+	if (i2c)
+		i2c_addr = priv->cfg.i2c_address | (1 << 1); /* DVB-C */
+	else
+		i2c_addr = priv->cfg.i2c_address; /* DVB-T/T2 */
+
+	/* switch bank if needed */
+	if (bank != priv->bank[i2c]) {
+		ret = cxd2820r_wr_regs_i2c(priv, i2c_addr, 0x00, &bank, 1);
+		if (ret)
+			return ret;
+		priv->bank[i2c] = bank;
+	}
+	return cxd2820r_wr_regs_i2c(priv, i2c_addr, reg, val, len);
+}
+
+/* read multiple registers */
+int cxd2820r_rd_regs(struct cxd2820r_priv *priv, u32 reginfo, u8 *val,
+	int len)
+{
+	int ret;
+	u8 i2c_addr;
+	u8 reg = (reginfo >> 0) & 0xff;
+	u8 bank = (reginfo >> 8) & 0xff;
+	u8 i2c = (reginfo >> 16) & 0x01;
+
+	/* select I2C */
+	if (i2c)
+		i2c_addr = priv->cfg.i2c_address | (1 << 1); /* DVB-C */
+	else
+		i2c_addr = priv->cfg.i2c_address; /* DVB-T/T2 */
+
+	/* switch bank if needed */
+	if (bank != priv->bank[i2c]) {
+		ret = cxd2820r_wr_regs_i2c(priv, i2c_addr, 0x00, &bank, 1);
+		if (ret)
+			return ret;
+		priv->bank[i2c] = bank;
+	}
+	return cxd2820r_rd_regs_i2c(priv, i2c_addr, reg, val, len);
+}
+
+/* write single register */
+int cxd2820r_wr_reg(struct cxd2820r_priv *priv, u32 reg, u8 val)
+{
+	return cxd2820r_wr_regs(priv, reg, &val, 1);
+}
+
+/* read single register */
+int cxd2820r_rd_reg(struct cxd2820r_priv *priv, u32 reg, u8 *val)
+{
+	return cxd2820r_rd_regs(priv, reg, val, 1);
+}
+
+/* write single register with mask */
+int cxd2820r_wr_reg_mask(struct cxd2820r_priv *priv, u32 reg, u8 val,
+	u8 mask)
+{
+	int ret;
+	u8 tmp;
+
+	/* no need for read if whole reg is written */
+	if (mask != 0xff) {
+		ret = cxd2820r_rd_reg(priv, reg, &tmp);
+		if (ret)
+			return ret;
+
+		val &= mask;
+		tmp &= ~mask;
+		val |= tmp;
+	}
+
+	return cxd2820r_wr_reg(priv, reg, val);
+}
+
+int cxd2820r_gpio(struct dvb_frontend *fe)
+{
+	struct cxd2820r_priv *priv = fe->demodulator_priv;
+	int ret, i;
+	u8 *gpio, tmp0, tmp1;
+	dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
+
+	switch (fe->dtv_property_cache.delivery_system) {
+	case SYS_DVBT:
+		gpio = priv->cfg.gpio_dvbt;
+		break;
+	case SYS_DVBT2:
+		gpio = priv->cfg.gpio_dvbt2;
+		break;
+	case SYS_DVBC_ANNEX_AC:
+		gpio = priv->cfg.gpio_dvbc;
+		break;
+	default:
+		ret = -EINVAL;
+		goto error;
+	}
+
+	/* update GPIOs only when needed */
+	if (!memcmp(gpio, priv->gpio, sizeof(priv->gpio)))
+		return 0;
+
+	tmp0 = 0x00;
+	tmp1 = 0x00;
+	for (i = 0; i < sizeof(priv->gpio); i++) {
+		/* enable / disable */
+		if (gpio[i] & CXD2820R_GPIO_E)
+			tmp0 |= (2 << 6) >> (2 * i);
+		else
+			tmp0 |= (1 << 6) >> (2 * i);
+
+		/* input / output */
+		if (gpio[i] & CXD2820R_GPIO_I)
+			tmp1 |= (1 << (3 + i));
+		else
+			tmp1 |= (0 << (3 + i));
+
+		/* high / low */
+		if (gpio[i] & CXD2820R_GPIO_H)
+			tmp1 |= (1 << (0 + i));
+		else
+			tmp1 |= (0 << (0 + i));
+
+		dbg("%s: GPIO i=%d %02x %02x", __func__, i, tmp0, tmp1);
+	}
+
+	dbg("%s: wr gpio=%02x %02x", __func__, tmp0, tmp1);
+
+	/* write bits [7:2] */
+	ret = cxd2820r_wr_reg_mask(priv, 0x00089, tmp0, 0xfc);
+	if (ret)
+		goto error;
+
+	/* write bits [5:0] */
+	ret = cxd2820r_wr_reg_mask(priv, 0x0008e, tmp1, 0x3f);
+	if (ret)
+		goto error;
+
+	memcpy(priv->gpio, gpio, sizeof(priv->gpio));
+
+	return ret;
+error:
+	dbg("%s: failed:%d", __func__, ret);
+	return ret;
+}
+
+/* 64 bit div with round closest, like DIV_ROUND_CLOSEST but 64 bit */
+u32 cxd2820r_div_u64_round_closest(u64 dividend, u32 divisor)
+{
+	return div_u64(dividend + (divisor / 2), divisor);
+}
+
+static int cxd2820r_set_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	int ret;
+
+	dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
+	switch (c->delivery_system) {
+	case SYS_DVBT:
+		ret = cxd2820r_init_t(fe);
+		if (ret < 0)
+			goto err;
+		ret = cxd2820r_set_frontend_t(fe);
+		if (ret < 0)
+			goto err;
+		break;
+	case SYS_DVBT2:
+		ret = cxd2820r_init_t(fe);
+		if (ret < 0)
+			goto err;
+		ret = cxd2820r_set_frontend_t2(fe);
+		if (ret < 0)
+			goto err;
+		break;
+	case SYS_DVBC_ANNEX_A:
+		ret = cxd2820r_init_c(fe);
+		if (ret < 0)
+			goto err;
+		ret = cxd2820r_set_frontend_c(fe);
+		if (ret < 0)
+			goto err;
+		break;
+	default:
+		dbg("%s: error state=%d", __func__, fe->dtv_property_cache.delivery_system);
+		ret = -EINVAL;
+		break;
+	}
+err:
+	return ret;
+}
+static int cxd2820r_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+	int ret;
+
+	dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
+	switch (fe->dtv_property_cache.delivery_system) {
+	case SYS_DVBT:
+		ret = cxd2820r_read_status_t(fe, status);
+		break;
+	case SYS_DVBT2:
+		ret = cxd2820r_read_status_t2(fe, status);
+		break;
+	case SYS_DVBC_ANNEX_A:
+		ret = cxd2820r_read_status_c(fe, status);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+	return ret;
+}
+
+static int cxd2820r_get_frontend(struct dvb_frontend *fe)
+{
+	struct cxd2820r_priv *priv = fe->demodulator_priv;
+	int ret;
+
+	dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
+
+	if (priv->delivery_system == SYS_UNDEFINED)
+		return 0;
+
+	switch (fe->dtv_property_cache.delivery_system) {
+	case SYS_DVBT:
+		ret = cxd2820r_get_frontend_t(fe);
+		break;
+	case SYS_DVBT2:
+		ret = cxd2820r_get_frontend_t2(fe);
+		break;
+	case SYS_DVBC_ANNEX_A:
+		ret = cxd2820r_get_frontend_c(fe);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+	return ret;
+}
+
+static int cxd2820r_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+	int ret;
+
+	dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
+	switch (fe->dtv_property_cache.delivery_system) {
+	case SYS_DVBT:
+		ret = cxd2820r_read_ber_t(fe, ber);
+		break;
+	case SYS_DVBT2:
+		ret = cxd2820r_read_ber_t2(fe, ber);
+		break;
+	case SYS_DVBC_ANNEX_A:
+		ret = cxd2820r_read_ber_c(fe, ber);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+	return ret;
+}
+
+static int cxd2820r_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
+{
+	int ret;
+
+	dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
+	switch (fe->dtv_property_cache.delivery_system) {
+	case SYS_DVBT:
+		ret = cxd2820r_read_signal_strength_t(fe, strength);
+		break;
+	case SYS_DVBT2:
+		ret = cxd2820r_read_signal_strength_t2(fe, strength);
+		break;
+	case SYS_DVBC_ANNEX_A:
+		ret = cxd2820r_read_signal_strength_c(fe, strength);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+	return ret;
+}
+
+static int cxd2820r_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+	int ret;
+
+	dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
+	switch (fe->dtv_property_cache.delivery_system) {
+	case SYS_DVBT:
+		ret = cxd2820r_read_snr_t(fe, snr);
+		break;
+	case SYS_DVBT2:
+		ret = cxd2820r_read_snr_t2(fe, snr);
+		break;
+	case SYS_DVBC_ANNEX_A:
+		ret = cxd2820r_read_snr_c(fe, snr);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+	return ret;
+}
+
+static int cxd2820r_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+	int ret;
+
+	dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
+	switch (fe->dtv_property_cache.delivery_system) {
+	case SYS_DVBT:
+		ret = cxd2820r_read_ucblocks_t(fe, ucblocks);
+		break;
+	case SYS_DVBT2:
+		ret = cxd2820r_read_ucblocks_t2(fe, ucblocks);
+		break;
+	case SYS_DVBC_ANNEX_A:
+		ret = cxd2820r_read_ucblocks_c(fe, ucblocks);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+	return ret;
+}
+
+static int cxd2820r_init(struct dvb_frontend *fe)
+{
+	return 0;
+}
+
+static int cxd2820r_sleep(struct dvb_frontend *fe)
+{
+	int ret;
+
+	dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
+	switch (fe->dtv_property_cache.delivery_system) {
+	case SYS_DVBT:
+		ret = cxd2820r_sleep_t(fe);
+		break;
+	case SYS_DVBT2:
+		ret = cxd2820r_sleep_t2(fe);
+		break;
+	case SYS_DVBC_ANNEX_A:
+		ret = cxd2820r_sleep_c(fe);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+	return ret;
+}
+
+static int cxd2820r_get_tune_settings(struct dvb_frontend *fe,
+				      struct dvb_frontend_tune_settings *s)
+{
+	int ret;
+
+	dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
+	switch (fe->dtv_property_cache.delivery_system) {
+	case SYS_DVBT:
+		ret = cxd2820r_get_tune_settings_t(fe, s);
+		break;
+	case SYS_DVBT2:
+		ret = cxd2820r_get_tune_settings_t2(fe, s);
+		break;
+	case SYS_DVBC_ANNEX_A:
+		ret = cxd2820r_get_tune_settings_c(fe, s);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+	return ret;
+}
+
+static enum dvbfe_search cxd2820r_search(struct dvb_frontend *fe)
+{
+	struct cxd2820r_priv *priv = fe->demodulator_priv;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	int ret, i;
+	fe_status_t status = 0;
+	dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
+
+	/* switch between DVB-T and DVB-T2 when tune fails */
+	if (priv->last_tune_failed) {
+		if (priv->delivery_system == SYS_DVBT) {
+			ret = cxd2820r_sleep_t(fe);
+			if (ret)
+				goto error;
+
+			c->delivery_system = SYS_DVBT2;
+		} else if (priv->delivery_system == SYS_DVBT2) {
+			ret = cxd2820r_sleep_t2(fe);
+			if (ret)
+				goto error;
+
+			c->delivery_system = SYS_DVBT;
+		}
+	}
+
+	/* set frontend */
+	ret = cxd2820r_set_frontend(fe);
+	if (ret)
+		goto error;
+
+
+	/* frontend lock wait loop count */
+	switch (priv->delivery_system) {
+	case SYS_DVBT:
+	case SYS_DVBC_ANNEX_A:
+		i = 20;
+		break;
+	case SYS_DVBT2:
+		i = 40;
+		break;
+	case SYS_UNDEFINED:
+	default:
+		i = 0;
+		break;
+	}
+
+	/* wait frontend lock */
+	for (; i > 0; i--) {
+		dbg("%s: LOOP=%d", __func__, i);
+		msleep(50);
+		ret = cxd2820r_read_status(fe, &status);
+		if (ret)
+			goto error;
+
+		if (status & FE_HAS_LOCK)
+			break;
+	}
+
+	/* check if we have a valid signal */
+	if (status & FE_HAS_LOCK) {
+		priv->last_tune_failed = 0;
+		return DVBFE_ALGO_SEARCH_SUCCESS;
+	} else {
+		priv->last_tune_failed = 1;
+		return DVBFE_ALGO_SEARCH_AGAIN;
+	}
+
+error:
+	dbg("%s: failed:%d", __func__, ret);
+	return DVBFE_ALGO_SEARCH_ERROR;
+}
+
+static int cxd2820r_get_frontend_algo(struct dvb_frontend *fe)
+{
+	return DVBFE_ALGO_CUSTOM;
+}
+
+static void cxd2820r_release(struct dvb_frontend *fe)
+{
+	struct cxd2820r_priv *priv = fe->demodulator_priv;
+	dbg("%s", __func__);
+
+	kfree(priv);
+	return;
+}
+
+static int cxd2820r_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+	struct cxd2820r_priv *priv = fe->demodulator_priv;
+	dbg("%s: %d", __func__, enable);
+
+	/* Bit 0 of reg 0xdb in bank 0x00 controls I2C repeater */
+	return cxd2820r_wr_reg_mask(priv, 0xdb, enable ? 1 : 0, 0x1);
+}
+
+static const struct dvb_frontend_ops cxd2820r_ops = {
+	.delsys = { SYS_DVBT, SYS_DVBT2, SYS_DVBC_ANNEX_A },
+	/* default: DVB-T/T2 */
+	.info = {
+		.name = "Sony CXD2820R",
+
+		.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_FEC_AUTO			|
+			FE_CAN_QPSK			|
+			FE_CAN_QAM_16			|
+			FE_CAN_QAM_32			|
+			FE_CAN_QAM_64			|
+			FE_CAN_QAM_128			|
+			FE_CAN_QAM_256			|
+			FE_CAN_QAM_AUTO			|
+			FE_CAN_TRANSMISSION_MODE_AUTO	|
+			FE_CAN_GUARD_INTERVAL_AUTO	|
+			FE_CAN_HIERARCHY_AUTO		|
+			FE_CAN_MUTE_TS			|
+			FE_CAN_2G_MODULATION
+		},
+
+	.release		= cxd2820r_release,
+	.init			= cxd2820r_init,
+	.sleep			= cxd2820r_sleep,
+
+	.get_tune_settings	= cxd2820r_get_tune_settings,
+	.i2c_gate_ctrl		= cxd2820r_i2c_gate_ctrl,
+
+	.get_frontend		= cxd2820r_get_frontend,
+
+	.get_frontend_algo	= cxd2820r_get_frontend_algo,
+	.search			= cxd2820r_search,
+
+	.read_status		= cxd2820r_read_status,
+	.read_snr		= cxd2820r_read_snr,
+	.read_ber		= cxd2820r_read_ber,
+	.read_ucblocks		= cxd2820r_read_ucblocks,
+	.read_signal_strength	= cxd2820r_read_signal_strength,
+};
+
+struct dvb_frontend *cxd2820r_attach(const struct cxd2820r_config *cfg,
+		struct i2c_adapter *i2c)
+{
+	struct cxd2820r_priv *priv = NULL;
+	int ret;
+	u8 tmp;
+
+	priv = kzalloc(sizeof (struct cxd2820r_priv), GFP_KERNEL);
+	if (!priv)
+		goto error;
+
+	priv->i2c = i2c;
+	memcpy(&priv->cfg, cfg, sizeof (struct cxd2820r_config));
+
+	priv->bank[0] = priv->bank[1] = 0xff;
+	ret = cxd2820r_rd_reg(priv, 0x000fd, &tmp);
+	dbg("%s: chip id=%02x", __func__, tmp);
+	if (ret || tmp != 0xe1)
+		goto error;
+
+	memcpy(&priv->fe.ops, &cxd2820r_ops, sizeof (struct dvb_frontend_ops));
+	priv->fe.demodulator_priv = priv;
+	return &priv->fe;
+error:
+	kfree(priv);
+	return NULL;
+}
+EXPORT_SYMBOL(cxd2820r_attach);
+
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
+MODULE_DESCRIPTION("Sony CXD2820R demodulator driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb-frontends/cxd2820r_priv.h b/drivers/media/dvb-frontends/cxd2820r_priv.h
new file mode 100644
index 0000000..9a9822c
--- /dev/null
+++ b/drivers/media/dvb-frontends/cxd2820r_priv.h
@@ -0,0 +1,156 @@
+/*
+ * Sony CXD2820R demodulator driver
+ *
+ * Copyright (C) 2010 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.,
+ *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+
+#ifndef CXD2820R_PRIV_H
+#define CXD2820R_PRIV_H
+
+#include <linux/dvb/version.h>
+#include "dvb_frontend.h"
+#include "dvb_math.h"
+#include "cxd2820r.h"
+
+#define LOG_PREFIX "cxd2820r"
+
+#undef dbg
+#define dbg(f, arg...) \
+	if (cxd2820r_debug) \
+		printk(KERN_INFO   LOG_PREFIX": " f "\n" , ## arg)
+#undef err
+#define err(f, arg...)  printk(KERN_ERR     LOG_PREFIX": " f "\n" , ## arg)
+#undef info
+#define info(f, arg...) printk(KERN_INFO    LOG_PREFIX": " f "\n" , ## arg)
+#undef warn
+#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg)
+
+struct reg_val_mask {
+	u32 reg;
+	u8  val;
+	u8  mask;
+};
+
+struct cxd2820r_priv {
+	struct i2c_adapter *i2c;
+	struct dvb_frontend fe;
+	struct cxd2820r_config cfg;
+
+	bool ber_running;
+
+	u8 bank[2];
+	u8 gpio[3];
+
+	fe_delivery_system_t delivery_system;
+	bool last_tune_failed; /* for switch between T and T2 tune */
+};
+
+/* cxd2820r_core.c */
+
+extern int cxd2820r_debug;
+
+int cxd2820r_gpio(struct dvb_frontend *fe);
+
+int cxd2820r_wr_reg_mask(struct cxd2820r_priv *priv, u32 reg, u8 val,
+	u8 mask);
+
+int cxd2820r_wr_regs(struct cxd2820r_priv *priv, u32 reginfo, u8 *val,
+	int len);
+
+u32 cxd2820r_div_u64_round_closest(u64 dividend, u32 divisor);
+
+int cxd2820r_wr_regs(struct cxd2820r_priv *priv, u32 reginfo, u8 *val,
+	int len);
+
+int cxd2820r_rd_regs(struct cxd2820r_priv *priv, u32 reginfo, u8 *val,
+	int len);
+
+int cxd2820r_wr_reg(struct cxd2820r_priv *priv, u32 reg, u8 val);
+
+int cxd2820r_rd_reg(struct cxd2820r_priv *priv, u32 reg, u8 *val);
+
+/* cxd2820r_c.c */
+
+int cxd2820r_get_frontend_c(struct dvb_frontend *fe);
+
+int cxd2820r_set_frontend_c(struct dvb_frontend *fe);
+
+int cxd2820r_read_status_c(struct dvb_frontend *fe, fe_status_t *status);
+
+int cxd2820r_read_ber_c(struct dvb_frontend *fe, u32 *ber);
+
+int cxd2820r_read_signal_strength_c(struct dvb_frontend *fe, u16 *strength);
+
+int cxd2820r_read_snr_c(struct dvb_frontend *fe, u16 *snr);
+
+int cxd2820r_read_ucblocks_c(struct dvb_frontend *fe, u32 *ucblocks);
+
+int cxd2820r_init_c(struct dvb_frontend *fe);
+
+int cxd2820r_sleep_c(struct dvb_frontend *fe);
+
+int cxd2820r_get_tune_settings_c(struct dvb_frontend *fe,
+	struct dvb_frontend_tune_settings *s);
+
+/* cxd2820r_t.c */
+
+int cxd2820r_get_frontend_t(struct dvb_frontend *fe);
+
+int cxd2820r_set_frontend_t(struct dvb_frontend *fe);
+
+int cxd2820r_read_status_t(struct dvb_frontend *fe, fe_status_t *status);
+
+int cxd2820r_read_ber_t(struct dvb_frontend *fe, u32 *ber);
+
+int cxd2820r_read_signal_strength_t(struct dvb_frontend *fe, u16 *strength);
+
+int cxd2820r_read_snr_t(struct dvb_frontend *fe, u16 *snr);
+
+int cxd2820r_read_ucblocks_t(struct dvb_frontend *fe, u32 *ucblocks);
+
+int cxd2820r_init_t(struct dvb_frontend *fe);
+
+int cxd2820r_sleep_t(struct dvb_frontend *fe);
+
+int cxd2820r_get_tune_settings_t(struct dvb_frontend *fe,
+	struct dvb_frontend_tune_settings *s);
+
+/* cxd2820r_t2.c */
+
+int cxd2820r_get_frontend_t2(struct dvb_frontend *fe);
+
+int cxd2820r_set_frontend_t2(struct dvb_frontend *fe);
+
+int cxd2820r_read_status_t2(struct dvb_frontend *fe, fe_status_t *status);
+
+int cxd2820r_read_ber_t2(struct dvb_frontend *fe, u32 *ber);
+
+int cxd2820r_read_signal_strength_t2(struct dvb_frontend *fe, u16 *strength);
+
+int cxd2820r_read_snr_t2(struct dvb_frontend *fe, u16 *snr);
+
+int cxd2820r_read_ucblocks_t2(struct dvb_frontend *fe, u32 *ucblocks);
+
+int cxd2820r_init_t2(struct dvb_frontend *fe);
+
+int cxd2820r_sleep_t2(struct dvb_frontend *fe);
+
+int cxd2820r_get_tune_settings_t2(struct dvb_frontend *fe,
+	struct dvb_frontend_tune_settings *s);
+
+#endif /* CXD2820R_PRIV_H */
diff --git a/drivers/media/dvb-frontends/cxd2820r_t.c b/drivers/media/dvb-frontends/cxd2820r_t.c
new file mode 100644
index 0000000..e5dd22b
--- /dev/null
+++ b/drivers/media/dvb-frontends/cxd2820r_t.c
@@ -0,0 +1,452 @@
+/*
+ * Sony CXD2820R demodulator driver
+ *
+ * Copyright (C) 2010 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.,
+ *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+
+#include "cxd2820r_priv.h"
+
+int cxd2820r_set_frontend_t(struct dvb_frontend *fe)
+{
+	struct cxd2820r_priv *priv = fe->demodulator_priv;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	int ret, i, bw_i;
+	u32 if_freq, if_ctl;
+	u64 num;
+	u8 buf[3], bw_param;
+	u8 bw_params1[][5] = {
+		{ 0x17, 0xea, 0xaa, 0xaa, 0xaa }, /* 6 MHz */
+		{ 0x14, 0x80, 0x00, 0x00, 0x00 }, /* 7 MHz */
+		{ 0x11, 0xf0, 0x00, 0x00, 0x00 }, /* 8 MHz */
+	};
+	u8 bw_params2[][2] = {
+		{ 0x1f, 0xdc }, /* 6 MHz */
+		{ 0x12, 0xf8 }, /* 7 MHz */
+		{ 0x01, 0xe0 }, /* 8 MHz */
+	};
+	struct reg_val_mask tab[] = {
+		{ 0x00080, 0x00, 0xff },
+		{ 0x00081, 0x03, 0xff },
+		{ 0x00085, 0x07, 0xff },
+		{ 0x00088, 0x01, 0xff },
+
+		{ 0x00070, priv->cfg.ts_mode, 0xff },
+		{ 0x000cb, priv->cfg.if_agc_polarity << 6, 0x40 },
+		{ 0x000a5, 0x00, 0x01 },
+		{ 0x00082, 0x20, 0x60 },
+		{ 0x000c2, 0xc3, 0xff },
+		{ 0x0016a, 0x50, 0xff },
+		{ 0x00427, 0x41, 0xff },
+	};
+
+	dbg("%s: RF=%d BW=%d", __func__, c->frequency, c->bandwidth_hz);
+
+	switch (c->bandwidth_hz) {
+	case 6000000:
+		bw_i = 0;
+		bw_param = 2;
+		break;
+	case 7000000:
+		bw_i = 1;
+		bw_param = 1;
+		break;
+	case 8000000:
+		bw_i = 2;
+		bw_param = 0;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* update GPIOs */
+	ret = cxd2820r_gpio(fe);
+	if (ret)
+		goto error;
+
+	/* program tuner */
+	if (fe->ops.tuner_ops.set_params)
+		fe->ops.tuner_ops.set_params(fe);
+
+	if (priv->delivery_system != SYS_DVBT) {
+		for (i = 0; i < ARRAY_SIZE(tab); i++) {
+			ret = cxd2820r_wr_reg_mask(priv, tab[i].reg,
+				tab[i].val, tab[i].mask);
+			if (ret)
+				goto error;
+		}
+	}
+
+	priv->delivery_system = SYS_DVBT;
+	priv->ber_running = 0; /* tune stops BER counter */
+
+	/* program IF frequency */
+	if (fe->ops.tuner_ops.get_if_frequency) {
+		ret = fe->ops.tuner_ops.get_if_frequency(fe, &if_freq);
+		if (ret)
+			goto error;
+	} else
+		if_freq = 0;
+
+	dbg("%s: if_freq=%d", __func__, if_freq);
+
+	num = if_freq / 1000; /* Hz => kHz */
+	num *= 0x1000000;
+	if_ctl = cxd2820r_div_u64_round_closest(num, 41000);
+	buf[0] = ((if_ctl >> 16) & 0xff);
+	buf[1] = ((if_ctl >>  8) & 0xff);
+	buf[2] = ((if_ctl >>  0) & 0xff);
+
+	ret = cxd2820r_wr_regs(priv, 0x000b6, buf, 3);
+	if (ret)
+		goto error;
+
+	ret = cxd2820r_wr_regs(priv, 0x0009f, bw_params1[bw_i], 5);
+	if (ret)
+		goto error;
+
+	ret = cxd2820r_wr_reg_mask(priv, 0x000d7, bw_param << 6, 0xc0);
+	if (ret)
+		goto error;
+
+	ret = cxd2820r_wr_regs(priv, 0x000d9, bw_params2[bw_i], 2);
+	if (ret)
+		goto error;
+
+	ret = cxd2820r_wr_reg(priv, 0x000ff, 0x08);
+	if (ret)
+		goto error;
+
+	ret = cxd2820r_wr_reg(priv, 0x000fe, 0x01);
+	if (ret)
+		goto error;
+
+	return ret;
+error:
+	dbg("%s: failed:%d", __func__, ret);
+	return ret;
+}
+
+int cxd2820r_get_frontend_t(struct dvb_frontend *fe)
+{
+	struct cxd2820r_priv *priv = fe->demodulator_priv;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	int ret;
+	u8 buf[2];
+
+	ret = cxd2820r_rd_regs(priv, 0x0002f, buf, sizeof(buf));
+	if (ret)
+		goto error;
+
+	switch ((buf[0] >> 6) & 0x03) {
+	case 0:
+		c->modulation = QPSK;
+		break;
+	case 1:
+		c->modulation = QAM_16;
+		break;
+	case 2:
+		c->modulation = QAM_64;
+		break;
+	}
+
+	switch ((buf[1] >> 1) & 0x03) {
+	case 0:
+		c->transmission_mode = TRANSMISSION_MODE_2K;
+		break;
+	case 1:
+		c->transmission_mode = TRANSMISSION_MODE_8K;
+		break;
+	}
+
+	switch ((buf[1] >> 3) & 0x03) {
+	case 0:
+		c->guard_interval = GUARD_INTERVAL_1_32;
+		break;
+	case 1:
+		c->guard_interval = GUARD_INTERVAL_1_16;
+		break;
+	case 2:
+		c->guard_interval = GUARD_INTERVAL_1_8;
+		break;
+	case 3:
+		c->guard_interval = GUARD_INTERVAL_1_4;
+		break;
+	}
+
+	switch ((buf[0] >> 3) & 0x07) {
+	case 0:
+		c->hierarchy = HIERARCHY_NONE;
+		break;
+	case 1:
+		c->hierarchy = HIERARCHY_1;
+		break;
+	case 2:
+		c->hierarchy = HIERARCHY_2;
+		break;
+	case 3:
+		c->hierarchy = HIERARCHY_4;
+		break;
+	}
+
+	switch ((buf[0] >> 0) & 0x07) {
+	case 0:
+		c->code_rate_HP = FEC_1_2;
+		break;
+	case 1:
+		c->code_rate_HP = FEC_2_3;
+		break;
+	case 2:
+		c->code_rate_HP = FEC_3_4;
+		break;
+	case 3:
+		c->code_rate_HP = FEC_5_6;
+		break;
+	case 4:
+		c->code_rate_HP = FEC_7_8;
+		break;
+	}
+
+	switch ((buf[1] >> 5) & 0x07) {
+	case 0:
+		c->code_rate_LP = FEC_1_2;
+		break;
+	case 1:
+		c->code_rate_LP = FEC_2_3;
+		break;
+	case 2:
+		c->code_rate_LP = FEC_3_4;
+		break;
+	case 3:
+		c->code_rate_LP = FEC_5_6;
+		break;
+	case 4:
+		c->code_rate_LP = FEC_7_8;
+		break;
+	}
+
+	ret = cxd2820r_rd_reg(priv, 0x007c6, &buf[0]);
+	if (ret)
+		goto error;
+
+	switch ((buf[0] >> 0) & 0x01) {
+	case 0:
+		c->inversion = INVERSION_OFF;
+		break;
+	case 1:
+		c->inversion = INVERSION_ON;
+		break;
+	}
+
+	return ret;
+error:
+	dbg("%s: failed:%d", __func__, ret);
+	return ret;
+}
+
+int cxd2820r_read_ber_t(struct dvb_frontend *fe, u32 *ber)
+{
+	struct cxd2820r_priv *priv = fe->demodulator_priv;
+	int ret;
+	u8 buf[3], start_ber = 0;
+	*ber = 0;
+
+	if (priv->ber_running) {
+		ret = cxd2820r_rd_regs(priv, 0x00076, buf, sizeof(buf));
+		if (ret)
+			goto error;
+
+		if ((buf[2] >> 7) & 0x01 || (buf[2] >> 4) & 0x01) {
+			*ber = (buf[2] & 0x0f) << 16 | buf[1] << 8 | buf[0];
+			start_ber = 1;
+		}
+	} else {
+		priv->ber_running = 1;
+		start_ber = 1;
+	}
+
+	if (start_ber) {
+		/* (re)start BER */
+		ret = cxd2820r_wr_reg(priv, 0x00079, 0x01);
+		if (ret)
+			goto error;
+	}
+
+	return ret;
+error:
+	dbg("%s: failed:%d", __func__, ret);
+	return ret;
+}
+
+int cxd2820r_read_signal_strength_t(struct dvb_frontend *fe,
+	u16 *strength)
+{
+	struct cxd2820r_priv *priv = fe->demodulator_priv;
+	int ret;
+	u8 buf[2];
+	u16 tmp;
+
+	ret = cxd2820r_rd_regs(priv, 0x00026, buf, sizeof(buf));
+	if (ret)
+		goto error;
+
+	tmp = (buf[0] & 0x0f) << 8 | buf[1];
+	tmp = ~tmp & 0x0fff;
+
+	/* scale value to 0x0000-0xffff from 0x0000-0x0fff */
+	*strength = tmp * 0xffff / 0x0fff;
+
+	return ret;
+error:
+	dbg("%s: failed:%d", __func__, ret);
+	return ret;
+}
+
+int cxd2820r_read_snr_t(struct dvb_frontend *fe, u16 *snr)
+{
+	struct cxd2820r_priv *priv = fe->demodulator_priv;
+	int ret;
+	u8 buf[2];
+	u16 tmp;
+	/* report SNR in dB * 10 */
+
+	ret = cxd2820r_rd_regs(priv, 0x00028, buf, sizeof(buf));
+	if (ret)
+		goto error;
+
+	tmp = (buf[0] & 0x1f) << 8 | buf[1];
+	#define CXD2820R_LOG10_8_24 15151336 /* log10(8) << 24 */
+	if (tmp)
+		*snr = (intlog10(tmp) - CXD2820R_LOG10_8_24) / ((1 << 24)
+			/ 100);
+	else
+		*snr = 0;
+
+	dbg("%s: dBx10=%d val=%04x", __func__, *snr, tmp);
+
+	return ret;
+error:
+	dbg("%s: failed:%d", __func__, ret);
+	return ret;
+}
+
+int cxd2820r_read_ucblocks_t(struct dvb_frontend *fe, u32 *ucblocks)
+{
+	*ucblocks = 0;
+	/* no way to read ? */
+	return 0;
+}
+
+int cxd2820r_read_status_t(struct dvb_frontend *fe, fe_status_t *status)
+{
+	struct cxd2820r_priv *priv = fe->demodulator_priv;
+	int ret;
+	u8 buf[4];
+	*status = 0;
+
+	ret = cxd2820r_rd_reg(priv, 0x00010, &buf[0]);
+	if (ret)
+		goto error;
+
+	if ((buf[0] & 0x07) == 6) {
+		ret = cxd2820r_rd_reg(priv, 0x00073, &buf[1]);
+		if (ret)
+			goto error;
+
+		if (((buf[1] >> 3) & 0x01) == 1) {
+			*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
+				FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
+		} else {
+			*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
+				FE_HAS_VITERBI | FE_HAS_SYNC;
+		}
+	} else {
+		ret = cxd2820r_rd_reg(priv, 0x00014, &buf[2]);
+		if (ret)
+			goto error;
+
+		if ((buf[2] & 0x0f) >= 4) {
+			ret = cxd2820r_rd_reg(priv, 0x00a14, &buf[3]);
+			if (ret)
+				goto error;
+
+			if (((buf[3] >> 4) & 0x01) == 1)
+				*status |= FE_HAS_SIGNAL;
+		}
+	}
+
+	dbg("%s: lock=%*ph", __func__, 4, buf);
+
+	return ret;
+error:
+	dbg("%s: failed:%d", __func__, ret);
+	return ret;
+}
+
+int cxd2820r_init_t(struct dvb_frontend *fe)
+{
+	struct cxd2820r_priv *priv = fe->demodulator_priv;
+	int ret;
+
+	ret = cxd2820r_wr_reg(priv, 0x00085, 0x07);
+	if (ret)
+		goto error;
+
+	return ret;
+error:
+	dbg("%s: failed:%d", __func__, ret);
+	return ret;
+}
+
+int cxd2820r_sleep_t(struct dvb_frontend *fe)
+{
+	struct cxd2820r_priv *priv = fe->demodulator_priv;
+	int ret, i;
+	struct reg_val_mask tab[] = {
+		{ 0x000ff, 0x1f, 0xff },
+		{ 0x00085, 0x00, 0xff },
+		{ 0x00088, 0x01, 0xff },
+		{ 0x00081, 0x00, 0xff },
+		{ 0x00080, 0x00, 0xff },
+	};
+
+	dbg("%s", __func__);
+
+	priv->delivery_system = SYS_UNDEFINED;
+
+	for (i = 0; i < ARRAY_SIZE(tab); i++) {
+		ret = cxd2820r_wr_reg_mask(priv, tab[i].reg, tab[i].val,
+			tab[i].mask);
+		if (ret)
+			goto error;
+	}
+
+	return ret;
+error:
+	dbg("%s: failed:%d", __func__, ret);
+	return ret;
+}
+
+int cxd2820r_get_tune_settings_t(struct dvb_frontend *fe,
+	struct dvb_frontend_tune_settings *s)
+{
+	s->min_delay_ms = 500;
+	s->step_size = fe->ops.info.frequency_stepsize * 2;
+	s->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1;
+
+	return 0;
+}
diff --git a/drivers/media/dvb-frontends/cxd2820r_t2.c b/drivers/media/dvb-frontends/cxd2820r_t2.c
new file mode 100644
index 0000000..3a5759e
--- /dev/null
+++ b/drivers/media/dvb-frontends/cxd2820r_t2.c
@@ -0,0 +1,426 @@
+/*
+ * Sony CXD2820R demodulator driver
+ *
+ * Copyright (C) 2010 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.,
+ *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+
+#include "cxd2820r_priv.h"
+
+int cxd2820r_set_frontend_t2(struct dvb_frontend *fe)
+{
+	struct cxd2820r_priv *priv = fe->demodulator_priv;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	int ret, i, bw_i;
+	u32 if_freq, if_ctl;
+	u64 num;
+	u8 buf[3], bw_param;
+	u8 bw_params1[][5] = {
+		{ 0x1c, 0xb3, 0x33, 0x33, 0x33 }, /* 5 MHz */
+		{ 0x17, 0xea, 0xaa, 0xaa, 0xaa }, /* 6 MHz */
+		{ 0x14, 0x80, 0x00, 0x00, 0x00 }, /* 7 MHz */
+		{ 0x11, 0xf0, 0x00, 0x00, 0x00 }, /* 8 MHz */
+	};
+	struct reg_val_mask tab[] = {
+		{ 0x00080, 0x02, 0xff },
+		{ 0x00081, 0x20, 0xff },
+		{ 0x00085, 0x07, 0xff },
+		{ 0x00088, 0x01, 0xff },
+		{ 0x02069, 0x01, 0xff },
+
+		{ 0x0207f, 0x2a, 0xff },
+		{ 0x02082, 0x0a, 0xff },
+		{ 0x02083, 0x0a, 0xff },
+		{ 0x020cb, priv->cfg.if_agc_polarity << 6, 0x40 },
+		{ 0x02070, priv->cfg.ts_mode, 0xff },
+		{ 0x020b5, priv->cfg.spec_inv << 4, 0x10 },
+		{ 0x02567, 0x07, 0x0f },
+		{ 0x02569, 0x03, 0x03 },
+		{ 0x02595, 0x1a, 0xff },
+		{ 0x02596, 0x50, 0xff },
+		{ 0x02a8c, 0x00, 0xff },
+		{ 0x02a8d, 0x34, 0xff },
+		{ 0x02a45, 0x06, 0x07 },
+		{ 0x03f10, 0x0d, 0xff },
+		{ 0x03f11, 0x02, 0xff },
+		{ 0x03f12, 0x01, 0xff },
+		{ 0x03f23, 0x2c, 0xff },
+		{ 0x03f51, 0x13, 0xff },
+		{ 0x03f52, 0x01, 0xff },
+		{ 0x03f53, 0x00, 0xff },
+		{ 0x027e6, 0x14, 0xff },
+		{ 0x02786, 0x02, 0x07 },
+		{ 0x02787, 0x40, 0xe0 },
+		{ 0x027ef, 0x10, 0x18 },
+	};
+
+	dbg("%s: RF=%d BW=%d", __func__, c->frequency, c->bandwidth_hz);
+
+	switch (c->bandwidth_hz) {
+	case 5000000:
+		bw_i = 0;
+		bw_param = 3;
+		break;
+	case 6000000:
+		bw_i = 1;
+		bw_param = 2;
+		break;
+	case 7000000:
+		bw_i = 2;
+		bw_param = 1;
+		break;
+	case 8000000:
+		bw_i = 3;
+		bw_param = 0;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* update GPIOs */
+	ret = cxd2820r_gpio(fe);
+	if (ret)
+		goto error;
+
+	/* program tuner */
+	if (fe->ops.tuner_ops.set_params)
+		fe->ops.tuner_ops.set_params(fe);
+
+	if (priv->delivery_system != SYS_DVBT2) {
+		for (i = 0; i < ARRAY_SIZE(tab); i++) {
+			ret = cxd2820r_wr_reg_mask(priv, tab[i].reg,
+				tab[i].val, tab[i].mask);
+			if (ret)
+				goto error;
+		}
+	}
+
+	priv->delivery_system = SYS_DVBT2;
+
+	/* program IF frequency */
+	if (fe->ops.tuner_ops.get_if_frequency) {
+		ret = fe->ops.tuner_ops.get_if_frequency(fe, &if_freq);
+		if (ret)
+			goto error;
+	} else
+		if_freq = 0;
+
+	dbg("%s: if_freq=%d", __func__, if_freq);
+
+	num = if_freq / 1000; /* Hz => kHz */
+	num *= 0x1000000;
+	if_ctl = cxd2820r_div_u64_round_closest(num, 41000);
+	buf[0] = ((if_ctl >> 16) & 0xff);
+	buf[1] = ((if_ctl >>  8) & 0xff);
+	buf[2] = ((if_ctl >>  0) & 0xff);
+
+	ret = cxd2820r_wr_regs(priv, 0x020b6, buf, 3);
+	if (ret)
+		goto error;
+
+	ret = cxd2820r_wr_regs(priv, 0x0209f, bw_params1[bw_i], 5);
+	if (ret)
+		goto error;
+
+	ret = cxd2820r_wr_reg_mask(priv, 0x020d7, bw_param << 6, 0xc0);
+	if (ret)
+		goto error;
+
+	ret = cxd2820r_wr_reg(priv, 0x000ff, 0x08);
+	if (ret)
+		goto error;
+
+	ret = cxd2820r_wr_reg(priv, 0x000fe, 0x01);
+	if (ret)
+		goto error;
+
+	return ret;
+error:
+	dbg("%s: failed:%d", __func__, ret);
+	return ret;
+
+}
+
+int cxd2820r_get_frontend_t2(struct dvb_frontend *fe)
+{
+	struct cxd2820r_priv *priv = fe->demodulator_priv;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	int ret;
+	u8 buf[2];
+
+	ret = cxd2820r_rd_regs(priv, 0x0205c, buf, 2);
+	if (ret)
+		goto error;
+
+	switch ((buf[0] >> 0) & 0x07) {
+	case 0:
+		c->transmission_mode = TRANSMISSION_MODE_2K;
+		break;
+	case 1:
+		c->transmission_mode = TRANSMISSION_MODE_8K;
+		break;
+	case 2:
+		c->transmission_mode = TRANSMISSION_MODE_4K;
+		break;
+	case 3:
+		c->transmission_mode = TRANSMISSION_MODE_1K;
+		break;
+	case 4:
+		c->transmission_mode = TRANSMISSION_MODE_16K;
+		break;
+	case 5:
+		c->transmission_mode = TRANSMISSION_MODE_32K;
+		break;
+	}
+
+	switch ((buf[1] >> 4) & 0x07) {
+	case 0:
+		c->guard_interval = GUARD_INTERVAL_1_32;
+		break;
+	case 1:
+		c->guard_interval = GUARD_INTERVAL_1_16;
+		break;
+	case 2:
+		c->guard_interval = GUARD_INTERVAL_1_8;
+		break;
+	case 3:
+		c->guard_interval = GUARD_INTERVAL_1_4;
+		break;
+	case 4:
+		c->guard_interval = GUARD_INTERVAL_1_128;
+		break;
+	case 5:
+		c->guard_interval = GUARD_INTERVAL_19_128;
+		break;
+	case 6:
+		c->guard_interval = GUARD_INTERVAL_19_256;
+		break;
+	}
+
+	ret = cxd2820r_rd_regs(priv, 0x0225b, buf, 2);
+	if (ret)
+		goto error;
+
+	switch ((buf[0] >> 0) & 0x07) {
+	case 0:
+		c->fec_inner = FEC_1_2;
+		break;
+	case 1:
+		c->fec_inner = FEC_3_5;
+		break;
+	case 2:
+		c->fec_inner = FEC_2_3;
+		break;
+	case 3:
+		c->fec_inner = FEC_3_4;
+		break;
+	case 4:
+		c->fec_inner = FEC_4_5;
+		break;
+	case 5:
+		c->fec_inner = FEC_5_6;
+		break;
+	}
+
+	switch ((buf[1] >> 0) & 0x07) {
+	case 0:
+		c->modulation = QPSK;
+		break;
+	case 1:
+		c->modulation = QAM_16;
+		break;
+	case 2:
+		c->modulation = QAM_64;
+		break;
+	case 3:
+		c->modulation = QAM_256;
+		break;
+	}
+
+	ret = cxd2820r_rd_reg(priv, 0x020b5, &buf[0]);
+	if (ret)
+		goto error;
+
+	switch ((buf[0] >> 4) & 0x01) {
+	case 0:
+		c->inversion = INVERSION_OFF;
+		break;
+	case 1:
+		c->inversion = INVERSION_ON;
+		break;
+	}
+
+	return ret;
+error:
+	dbg("%s: failed:%d", __func__, ret);
+	return ret;
+}
+
+int cxd2820r_read_status_t2(struct dvb_frontend *fe, fe_status_t *status)
+{
+	struct cxd2820r_priv *priv = fe->demodulator_priv;
+	int ret;
+	u8 buf[1];
+	*status = 0;
+
+	ret = cxd2820r_rd_reg(priv, 0x02010 , &buf[0]);
+	if (ret)
+		goto error;
+
+	if ((buf[0] & 0x07) == 6) {
+		if (((buf[0] >> 5) & 0x01) == 1) {
+			*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
+				FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
+		} else {
+			*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
+				FE_HAS_VITERBI | FE_HAS_SYNC;
+		}
+	}
+
+	dbg("%s: lock=%02x", __func__, buf[0]);
+
+	return ret;
+error:
+	dbg("%s: failed:%d", __func__, ret);
+	return ret;
+}
+
+int cxd2820r_read_ber_t2(struct dvb_frontend *fe, u32 *ber)
+{
+	struct cxd2820r_priv *priv = fe->demodulator_priv;
+	int ret;
+	u8 buf[4];
+	unsigned int errbits;
+	*ber = 0;
+	/* FIXME: correct calculation */
+
+	ret = cxd2820r_rd_regs(priv, 0x02039, buf, sizeof(buf));
+	if (ret)
+		goto error;
+
+	if ((buf[0] >> 4) & 0x01) {
+		errbits = (buf[0] & 0x0f) << 24 | buf[1] << 16 |
+			buf[2] << 8 | buf[3];
+
+		if (errbits)
+			*ber = errbits * 64 / 16588800;
+	}
+
+	return ret;
+error:
+	dbg("%s: failed:%d", __func__, ret);
+	return ret;
+}
+
+int cxd2820r_read_signal_strength_t2(struct dvb_frontend *fe,
+	u16 *strength)
+{
+	struct cxd2820r_priv *priv = fe->demodulator_priv;
+	int ret;
+	u8 buf[2];
+	u16 tmp;
+
+	ret = cxd2820r_rd_regs(priv, 0x02026, buf, sizeof(buf));
+	if (ret)
+		goto error;
+
+	tmp = (buf[0] & 0x0f) << 8 | buf[1];
+	tmp = ~tmp & 0x0fff;
+
+	/* scale value to 0x0000-0xffff from 0x0000-0x0fff */
+	*strength = tmp * 0xffff / 0x0fff;
+
+	return ret;
+error:
+	dbg("%s: failed:%d", __func__, ret);
+	return ret;
+}
+
+int cxd2820r_read_snr_t2(struct dvb_frontend *fe, u16 *snr)
+{
+	struct cxd2820r_priv *priv = fe->demodulator_priv;
+	int ret;
+	u8 buf[2];
+	u16 tmp;
+	/* report SNR in dB * 10 */
+
+	ret = cxd2820r_rd_regs(priv, 0x02028, buf, sizeof(buf));
+	if (ret)
+		goto error;
+
+	tmp = (buf[0] & 0x0f) << 8 | buf[1];
+	#define CXD2820R_LOG10_8_24 15151336 /* log10(8) << 24 */
+	if (tmp)
+		*snr = (intlog10(tmp) - CXD2820R_LOG10_8_24) / ((1 << 24)
+			/ 100);
+	else
+		*snr = 0;
+
+	dbg("%s: dBx10=%d val=%04x", __func__, *snr, tmp);
+
+	return ret;
+error:
+	dbg("%s: failed:%d", __func__, ret);
+	return ret;
+}
+
+int cxd2820r_read_ucblocks_t2(struct dvb_frontend *fe, u32 *ucblocks)
+{
+	*ucblocks = 0;
+	/* no way to read ? */
+	return 0;
+}
+
+int cxd2820r_sleep_t2(struct dvb_frontend *fe)
+{
+	struct cxd2820r_priv *priv = fe->demodulator_priv;
+	int ret, i;
+	struct reg_val_mask tab[] = {
+		{ 0x000ff, 0x1f, 0xff },
+		{ 0x00085, 0x00, 0xff },
+		{ 0x00088, 0x01, 0xff },
+		{ 0x02069, 0x00, 0xff },
+		{ 0x00081, 0x00, 0xff },
+		{ 0x00080, 0x00, 0xff },
+	};
+
+	dbg("%s", __func__);
+
+	for (i = 0; i < ARRAY_SIZE(tab); i++) {
+		ret = cxd2820r_wr_reg_mask(priv, tab[i].reg, tab[i].val,
+			tab[i].mask);
+		if (ret)
+			goto error;
+	}
+
+	priv->delivery_system = SYS_UNDEFINED;
+
+	return ret;
+error:
+	dbg("%s: failed:%d", __func__, ret);
+	return ret;
+}
+
+int cxd2820r_get_tune_settings_t2(struct dvb_frontend *fe,
+	struct dvb_frontend_tune_settings *s)
+{
+	s->min_delay_ms = 1500;
+	s->step_size = fe->ops.info.frequency_stepsize * 2;
+	s->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1;
+
+	return 0;
+}
diff --git a/drivers/media/dvb-frontends/dib0070.c b/drivers/media/dvb-frontends/dib0070.c
new file mode 100644
index 0000000..3b024bf
--- /dev/null
+++ b/drivers/media/dvb-frontends/dib0070.c
@@ -0,0 +1,780 @@
+/*
+ * Linux-DVB Driver for DiBcom's DiB0070 base-band RF Tuner.
+ *
+ * Copyright (C) 2005-9 DiBcom (http://www.dibcom.fr/)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ * This code is more or less generated from another driver, please
+ * excuse some codingstyle oddities.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+
+#include "dvb_frontend.h"
+
+#include "dib0070.h"
+#include "dibx000_common.h"
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
+
+#define dprintk(args...) do { \
+	if (debug) { \
+		printk(KERN_DEBUG "DiB0070: "); \
+		printk(args); \
+		printk("\n"); \
+	} \
+} while (0)
+
+#define DIB0070_P1D  0x00
+#define DIB0070_P1F  0x01
+#define DIB0070_P1G  0x03
+#define DIB0070S_P1A 0x02
+
+struct dib0070_state {
+	struct i2c_adapter *i2c;
+	struct dvb_frontend *fe;
+	const struct dib0070_config *cfg;
+	u16 wbd_ff_offset;
+	u8 revision;
+
+    enum frontend_tune_state tune_state;
+    u32 current_rf;
+
+    /* for the captrim binary search */
+	s8 step;
+	u16 adc_diff;
+
+	s8 captrim;
+	s8 fcaptrim;
+	u16 lo4;
+
+	const struct dib0070_tuning *current_tune_table_index;
+	const struct dib0070_lna_match *lna_match;
+
+    u8  wbd_gain_current;
+	u16 wbd_offset_3_3[2];
+
+	/* for the I2C transfer */
+	struct i2c_msg msg[2];
+	u8 i2c_write_buffer[3];
+	u8 i2c_read_buffer[2];
+	struct mutex i2c_buffer_lock;
+};
+
+static u16 dib0070_read_reg(struct dib0070_state *state, u8 reg)
+{
+	u16 ret;
+
+	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
+		dprintk("could not acquire lock");
+		return 0;
+	}
+
+	state->i2c_write_buffer[0] = reg;
+
+	memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
+	state->msg[0].addr = state->cfg->i2c_address;
+	state->msg[0].flags = 0;
+	state->msg[0].buf = state->i2c_write_buffer;
+	state->msg[0].len = 1;
+	state->msg[1].addr = state->cfg->i2c_address;
+	state->msg[1].flags = I2C_M_RD;
+	state->msg[1].buf = state->i2c_read_buffer;
+	state->msg[1].len = 2;
+
+	if (i2c_transfer(state->i2c, state->msg, 2) != 2) {
+		printk(KERN_WARNING "DiB0070 I2C read failed\n");
+		ret = 0;
+	} else
+		ret = (state->i2c_read_buffer[0] << 8)
+			| state->i2c_read_buffer[1];
+
+	mutex_unlock(&state->i2c_buffer_lock);
+	return ret;
+}
+
+static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val)
+{
+	int ret;
+
+	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
+		dprintk("could not acquire lock");
+		return -EINVAL;
+	}
+	state->i2c_write_buffer[0] = reg;
+	state->i2c_write_buffer[1] = val >> 8;
+	state->i2c_write_buffer[2] = val & 0xff;
+
+	memset(state->msg, 0, sizeof(struct i2c_msg));
+	state->msg[0].addr = state->cfg->i2c_address;
+	state->msg[0].flags = 0;
+	state->msg[0].buf = state->i2c_write_buffer;
+	state->msg[0].len = 3;
+
+	if (i2c_transfer(state->i2c, state->msg, 1) != 1) {
+		printk(KERN_WARNING "DiB0070 I2C write failed\n");
+		ret = -EREMOTEIO;
+	} else
+		ret = 0;
+
+	mutex_unlock(&state->i2c_buffer_lock);
+	return ret;
+}
+
+#define HARD_RESET(state) do { \
+    state->cfg->sleep(state->fe, 0); \
+    if (state->cfg->reset) { \
+	state->cfg->reset(state->fe,1); msleep(10); \
+	state->cfg->reset(state->fe,0); msleep(10); \
+    } \
+} while (0)
+
+static int dib0070_set_bandwidth(struct dvb_frontend *fe)
+{
+    struct dib0070_state *state = fe->tuner_priv;
+    u16 tmp = dib0070_read_reg(state, 0x02) & 0x3fff;
+
+    if (state->fe->dtv_property_cache.bandwidth_hz/1000 > 7000)
+	tmp |= (0 << 14);
+    else if (state->fe->dtv_property_cache.bandwidth_hz/1000 > 6000)
+	tmp |= (1 << 14);
+    else if (state->fe->dtv_property_cache.bandwidth_hz/1000 > 5000)
+	tmp |= (2 << 14);
+    else
+	tmp |= (3 << 14);
+
+    dib0070_write_reg(state, 0x02, tmp);
+
+    /* sharpen the BB filter in ISDB-T to have higher immunity to adjacent channels */
+    if (state->fe->dtv_property_cache.delivery_system == SYS_ISDBT) {
+	u16 value = dib0070_read_reg(state, 0x17);
+
+	dib0070_write_reg(state, 0x17, value & 0xfffc);
+	tmp = dib0070_read_reg(state, 0x01) & 0x01ff;
+	dib0070_write_reg(state, 0x01, tmp | (60 << 9));
+
+	dib0070_write_reg(state, 0x17, value);
+    }
+	return 0;
+}
+
+static int dib0070_captrim(struct dib0070_state *state, enum frontend_tune_state *tune_state)
+{
+	int8_t step_sign;
+	u16 adc;
+	int ret = 0;
+
+	if (*tune_state == CT_TUNER_STEP_0) {
+
+		dib0070_write_reg(state, 0x0f, 0xed10);
+		dib0070_write_reg(state, 0x17,    0x0034);
+
+		dib0070_write_reg(state, 0x18, 0x0032);
+		state->step = state->captrim = state->fcaptrim = 64;
+		state->adc_diff = 3000;
+		ret = 20;
+
+	*tune_state = CT_TUNER_STEP_1;
+	} else if (*tune_state == CT_TUNER_STEP_1) {
+		state->step /= 2;
+		dib0070_write_reg(state, 0x14, state->lo4 | state->captrim);
+		ret = 15;
+
+		*tune_state = CT_TUNER_STEP_2;
+	} else if (*tune_state == CT_TUNER_STEP_2) {
+
+		adc = dib0070_read_reg(state, 0x19);
+
+		dprintk("CAPTRIM=%hd; ADC = %hd (ADC) & %dmV", state->captrim, adc, (u32) adc*(u32)1800/(u32)1024);
+
+		if (adc >= 400) {
+			adc -= 400;
+			step_sign = -1;
+		} else {
+			adc = 400 - adc;
+			step_sign = 1;
+		}
+
+		if (adc < state->adc_diff) {
+			dprintk("CAPTRIM=%hd is closer to target (%hd/%hd)", state->captrim, adc, state->adc_diff);
+			state->adc_diff = adc;
+			state->fcaptrim = state->captrim;
+
+
+
+		}
+		state->captrim += (step_sign * state->step);
+
+		if (state->step >= 1)
+			*tune_state = CT_TUNER_STEP_1;
+		else
+			*tune_state = CT_TUNER_STEP_3;
+
+	} else if (*tune_state == CT_TUNER_STEP_3) {
+		dib0070_write_reg(state, 0x14, state->lo4 | state->fcaptrim);
+		dib0070_write_reg(state, 0x18, 0x07ff);
+		*tune_state = CT_TUNER_STEP_4;
+	}
+
+	return ret;
+}
+
+static int dib0070_set_ctrl_lo5(struct dvb_frontend *fe, u8 vco_bias_trim, u8 hf_div_trim, u8 cp_current, u8 third_order_filt)
+{
+	struct dib0070_state *state = fe->tuner_priv;
+    u16 lo5 = (third_order_filt << 14) | (0 << 13) | (1 << 12) | (3 << 9) | (cp_current << 6) | (hf_div_trim << 3) | (vco_bias_trim << 0);
+	dprintk("CTRL_LO5: 0x%x", lo5);
+	return dib0070_write_reg(state, 0x15, lo5);
+}
+
+void dib0070_ctrl_agc_filter(struct dvb_frontend *fe, u8 open)
+{
+	struct dib0070_state *state = fe->tuner_priv;
+
+	if (open) {
+		dib0070_write_reg(state, 0x1b, 0xff00);
+		dib0070_write_reg(state, 0x1a, 0x0000);
+	} else {
+		dib0070_write_reg(state, 0x1b, 0x4112);
+	if (state->cfg->vga_filter != 0) {
+		dib0070_write_reg(state, 0x1a, state->cfg->vga_filter);
+		dprintk("vga filter register is set to %x", state->cfg->vga_filter);
+	} else
+		dib0070_write_reg(state, 0x1a, 0x0009);
+	}
+}
+
+EXPORT_SYMBOL(dib0070_ctrl_agc_filter);
+struct dib0070_tuning {
+    u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */
+    u8 switch_trim;
+    u8 vco_band;
+    u8 hfdiv;
+    u8 vco_multi;
+    u8 presc;
+    u8 wbdmux;
+    u16 tuner_enable;
+};
+
+struct dib0070_lna_match {
+    u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */
+    u8 lna_band;
+};
+
+static const struct dib0070_tuning dib0070s_tuning_table[] = {
+    {     570000, 2, 1, 3, 6, 6, 2, 0x4000 | 0x0800 }, /* UHF */
+    {     700000, 2, 0, 2, 4, 2, 2, 0x4000 | 0x0800 },
+    {     863999, 2, 1, 2, 4, 2, 2, 0x4000 | 0x0800 },
+    {    1500000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 }, /* LBAND */
+    {    1600000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 },
+    {    2000000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 },
+    { 0xffffffff, 0, 0, 8, 1, 2, 1, 0x8000 | 0x1000 }, /* SBAND */
+};
+
+static const struct dib0070_tuning dib0070_tuning_table[] = {
+    {     115000, 1, 0, 7, 24, 2, 1, 0x8000 | 0x1000 }, /* FM below 92MHz cannot be tuned */
+    {     179500, 1, 0, 3, 16, 2, 1, 0x8000 | 0x1000 }, /* VHF */
+    {     189999, 1, 1, 3, 16, 2, 1, 0x8000 | 0x1000 },
+    {     250000, 1, 0, 6, 12, 2, 1, 0x8000 | 0x1000 },
+    {     569999, 2, 1, 5,  6, 2, 2, 0x4000 | 0x0800 }, /* UHF */
+    {     699999, 2, 0, 1,  4, 2, 2, 0x4000 | 0x0800 },
+    {     863999, 2, 1, 1,  4, 2, 2, 0x4000 | 0x0800 },
+    { 0xffffffff, 0, 1, 0,  2, 2, 4, 0x2000 | 0x0400 }, /* LBAND or everything higher than UHF */
+};
+
+static const struct dib0070_lna_match dib0070_lna_flip_chip[] = {
+    {     180000, 0 }, /* VHF */
+    {     188000, 1 },
+    {     196400, 2 },
+    {     250000, 3 },
+    {     550000, 0 }, /* UHF */
+    {     590000, 1 },
+    {     666000, 3 },
+    {     864000, 5 },
+    {    1500000, 0 }, /* LBAND or everything higher than UHF */
+    {    1600000, 1 },
+    {    2000000, 3 },
+    { 0xffffffff, 7 },
+};
+
+static const struct dib0070_lna_match dib0070_lna[] = {
+    {     180000, 0 }, /* VHF */
+    {     188000, 1 },
+    {     196400, 2 },
+    {     250000, 3 },
+    {     550000, 2 }, /* UHF */
+    {     650000, 3 },
+    {     750000, 5 },
+    {     850000, 6 },
+    {     864000, 7 },
+    {    1500000, 0 }, /* LBAND or everything higher than UHF */
+    {    1600000, 1 },
+    {    2000000, 3 },
+    { 0xffffffff, 7 },
+};
+
+#define LPF	100
+static int dib0070_tune_digital(struct dvb_frontend *fe)
+{
+    struct dib0070_state *state = fe->tuner_priv;
+
+    const struct dib0070_tuning *tune;
+    const struct dib0070_lna_match *lna_match;
+
+    enum frontend_tune_state *tune_state = &state->tune_state;
+    int ret = 10; /* 1ms is the default delay most of the time */
+
+    u8  band = (u8)BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency/1000);
+    u32 freq = fe->dtv_property_cache.frequency/1000 + (band == BAND_VHF ? state->cfg->freq_offset_khz_vhf : state->cfg->freq_offset_khz_uhf);
+
+#ifdef CONFIG_SYS_ISDBT
+    if (state->fe->dtv_property_cache.delivery_system == SYS_ISDBT && state->fe->dtv_property_cache.isdbt_sb_mode == 1)
+		if (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2)
+		     && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == ((state->fe->dtv_property_cache.isdbt_sb_segment_count / 2) + 1)))
+		    || (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2) == 0)
+			&& (state->fe->dtv_property_cache.isdbt_sb_segment_idx == (state->fe->dtv_property_cache.isdbt_sb_segment_count / 2)))
+		    || (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2) == 0)
+			&& (state->fe->dtv_property_cache.isdbt_sb_segment_idx == ((state->fe->dtv_property_cache.isdbt_sb_segment_count / 2) + 1))))
+			freq += 850;
+#endif
+    if (state->current_rf != freq) {
+
+	switch (state->revision) {
+	case DIB0070S_P1A:
+	    tune = dib0070s_tuning_table;
+	    lna_match = dib0070_lna;
+	    break;
+	default:
+	    tune = dib0070_tuning_table;
+	    if (state->cfg->flip_chip)
+		lna_match = dib0070_lna_flip_chip;
+	    else
+		lna_match = dib0070_lna;
+	    break;
+	}
+	while (freq > tune->max_freq) /* find the right one */
+	    tune++;
+	while (freq > lna_match->max_freq) /* find the right one */
+	    lna_match++;
+
+	state->current_tune_table_index = tune;
+	state->lna_match = lna_match;
+    }
+
+    if (*tune_state == CT_TUNER_START) {
+	dprintk("Tuning for Band: %hd (%d kHz)", band, freq);
+	if (state->current_rf != freq) {
+		u8 REFDIV;
+		u32 FBDiv, Rest, FREF, VCOF_kHz;
+		u8 Den;
+
+		state->current_rf = freq;
+		state->lo4 = (state->current_tune_table_index->vco_band << 11) | (state->current_tune_table_index->hfdiv << 7);
+
+
+		dib0070_write_reg(state, 0x17, 0x30);
+
+
+		VCOF_kHz = state->current_tune_table_index->vco_multi * freq * 2;
+
+		switch (band) {
+		case BAND_VHF:
+			REFDIV = (u8) ((state->cfg->clock_khz + 9999) / 10000);
+			break;
+		case BAND_FM:
+			REFDIV = (u8) ((state->cfg->clock_khz) / 1000);
+			break;
+		default:
+			REFDIV = (u8) (state->cfg->clock_khz  / 10000);
+			break;
+		}
+		FREF = state->cfg->clock_khz / REFDIV;
+
+
+
+		switch (state->revision) {
+		case DIB0070S_P1A:
+			FBDiv = (VCOF_kHz / state->current_tune_table_index->presc / FREF);
+			Rest  = (VCOF_kHz / state->current_tune_table_index->presc) - FBDiv * FREF;
+			break;
+
+		case DIB0070_P1G:
+		case DIB0070_P1F:
+		default:
+			FBDiv = (freq / (FREF / 2));
+			Rest  = 2 * freq - FBDiv * FREF;
+			break;
+		}
+
+		if (Rest < LPF)
+			Rest = 0;
+		else if (Rest < 2 * LPF)
+			Rest = 2 * LPF;
+		else if (Rest > (FREF - LPF)) {
+			Rest = 0;
+			FBDiv += 1;
+		} else if (Rest > (FREF - 2 * LPF))
+			Rest = FREF - 2 * LPF;
+		Rest = (Rest * 6528) / (FREF / 10);
+
+		Den = 1;
+		if (Rest > 0) {
+			state->lo4 |= (1 << 14) | (1 << 12);
+			Den = 255;
+		}
+
+
+		dib0070_write_reg(state, 0x11, (u16)FBDiv);
+		dib0070_write_reg(state, 0x12, (Den << 8) | REFDIV);
+		dib0070_write_reg(state, 0x13, (u16) Rest);
+
+		if (state->revision == DIB0070S_P1A) {
+
+			if (band == BAND_SBAND) {
+				dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0);
+				dib0070_write_reg(state, 0x1d, 0xFFFF);
+			} else
+				dib0070_set_ctrl_lo5(fe, 5, 4, 3, 1);
+		}
+
+		dib0070_write_reg(state, 0x20,
+			0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001 | state->current_tune_table_index->tuner_enable);
+
+		dprintk("REFDIV: %hd, FREF: %d", REFDIV, FREF);
+		dprintk("FBDIV: %d, Rest: %d", FBDiv, Rest);
+		dprintk("Num: %hd, Den: %hd, SD: %hd", (u16) Rest, Den, (state->lo4 >> 12) & 0x1);
+		dprintk("HFDIV code: %hd", state->current_tune_table_index->hfdiv);
+		dprintk("VCO = %hd", state->current_tune_table_index->vco_band);
+		dprintk("VCOF: ((%hd*%d) << 1))", state->current_tune_table_index->vco_multi, freq);
+
+		*tune_state = CT_TUNER_STEP_0;
+	} else { /* we are already tuned to this frequency - the configuration is correct  */
+		ret = 50; /* wakeup time */
+		*tune_state = CT_TUNER_STEP_5;
+	}
+    } else if ((*tune_state > CT_TUNER_START) && (*tune_state < CT_TUNER_STEP_4)) {
+
+	ret = dib0070_captrim(state, tune_state);
+
+    } else if (*tune_state == CT_TUNER_STEP_4) {
+	const struct dib0070_wbd_gain_cfg *tmp = state->cfg->wbd_gain;
+	if (tmp != NULL) {
+		while (freq/1000 > tmp->freq) /* find the right one */
+			tmp++;
+		dib0070_write_reg(state, 0x0f,
+			(0 << 15) | (1 << 14) | (3 << 12)
+			| (tmp->wbd_gain_val << 9) | (0 << 8) | (1 << 7)
+			| (state->current_tune_table_index->wbdmux << 0));
+		state->wbd_gain_current = tmp->wbd_gain_val;
+	} else {
+			dib0070_write_reg(state, 0x0f,
+					  (0 << 15) | (1 << 14) | (3 << 12) | (6 << 9) | (0 << 8) | (1 << 7) | (state->current_tune_table_index->
+														wbdmux << 0));
+	    state->wbd_gain_current = 6;
+	}
+
+	dib0070_write_reg(state, 0x06, 0x3fff);
+		dib0070_write_reg(state, 0x07,
+				  (state->current_tune_table_index->switch_trim << 11) | (7 << 8) | (state->lna_match->lna_band << 3) | (3 << 0));
+	dib0070_write_reg(state, 0x08, (state->lna_match->lna_band << 10) | (3 << 7) | (127));
+	dib0070_write_reg(state, 0x0d, 0x0d80);
+
+
+	dib0070_write_reg(state, 0x18,   0x07ff);
+	dib0070_write_reg(state, 0x17, 0x0033);
+
+
+	*tune_state = CT_TUNER_STEP_5;
+    } else if (*tune_state == CT_TUNER_STEP_5) {
+	dib0070_set_bandwidth(fe);
+	*tune_state = CT_TUNER_STOP;
+    } else {
+	ret = FE_CALLBACK_TIME_NEVER; /* tuner finished, time to call again infinite */
+    }
+    return ret;
+}
+
+
+static int dib0070_tune(struct dvb_frontend *fe)
+{
+    struct dib0070_state *state = fe->tuner_priv;
+    uint32_t ret;
+
+    state->tune_state = CT_TUNER_START;
+
+    do {
+	ret = dib0070_tune_digital(fe);
+	if (ret != FE_CALLBACK_TIME_NEVER)
+		msleep(ret/10);
+	else
+	    break;
+    } while (state->tune_state != CT_TUNER_STOP);
+
+    return 0;
+}
+
+static int dib0070_wakeup(struct dvb_frontend *fe)
+{
+	struct dib0070_state *state = fe->tuner_priv;
+	if (state->cfg->sleep)
+		state->cfg->sleep(fe, 0);
+	return 0;
+}
+
+static int dib0070_sleep(struct dvb_frontend *fe)
+{
+	struct dib0070_state *state = fe->tuner_priv;
+	if (state->cfg->sleep)
+		state->cfg->sleep(fe, 1);
+	return 0;
+}
+
+u8 dib0070_get_rf_output(struct dvb_frontend *fe)
+{
+	struct dib0070_state *state = fe->tuner_priv;
+	return (dib0070_read_reg(state, 0x07) >> 11) & 0x3;
+}
+EXPORT_SYMBOL(dib0070_get_rf_output);
+
+int dib0070_set_rf_output(struct dvb_frontend *fe, u8 no)
+{
+	struct dib0070_state *state = fe->tuner_priv;
+	u16 rxrf2 = dib0070_read_reg(state, 0x07) & 0xfe7ff;
+	if (no > 3)
+		no = 3;
+	if (no < 1)
+		no = 1;
+	return dib0070_write_reg(state, 0x07, rxrf2 | (no << 11));
+}
+EXPORT_SYMBOL(dib0070_set_rf_output);
+
+static const u16 dib0070_p1f_defaults[] =
+
+{
+	7, 0x02,
+		0x0008,
+		0x0000,
+		0x0000,
+		0x0000,
+		0x0000,
+		0x0002,
+		0x0100,
+
+	3, 0x0d,
+		0x0d80,
+		0x0001,
+		0x0000,
+
+	4, 0x11,
+		0x0000,
+		0x0103,
+		0x0000,
+		0x0000,
+
+	3, 0x16,
+		0x0004 | 0x0040,
+		0x0030,
+		0x07ff,
+
+	6, 0x1b,
+		0x4112,
+		0xff00,
+		0xc07f,
+		0x0000,
+		0x0180,
+		0x4000 | 0x0800 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001,
+
+	0,
+};
+
+static u16 dib0070_read_wbd_offset(struct dib0070_state *state, u8 gain)
+{
+    u16 tuner_en = dib0070_read_reg(state, 0x20);
+    u16 offset;
+
+    dib0070_write_reg(state, 0x18, 0x07ff);
+    dib0070_write_reg(state, 0x20, 0x0800 | 0x4000 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001);
+    dib0070_write_reg(state, 0x0f, (1 << 14) | (2 << 12) | (gain << 9) | (1 << 8) | (1 << 7) | (0 << 0));
+    msleep(9);
+    offset = dib0070_read_reg(state, 0x19);
+    dib0070_write_reg(state, 0x20, tuner_en);
+    return offset;
+}
+
+static void dib0070_wbd_offset_calibration(struct dib0070_state *state)
+{
+    u8 gain;
+    for (gain = 6; gain < 8; gain++) {
+	state->wbd_offset_3_3[gain - 6] = ((dib0070_read_wbd_offset(state, gain) * 8 * 18 / 33 + 1) / 2);
+	dprintk("Gain: %d, WBDOffset (3.3V) = %hd", gain, state->wbd_offset_3_3[gain-6]);
+    }
+}
+
+u16 dib0070_wbd_offset(struct dvb_frontend *fe)
+{
+    struct dib0070_state *state = fe->tuner_priv;
+    const struct dib0070_wbd_gain_cfg *tmp = state->cfg->wbd_gain;
+    u32 freq = fe->dtv_property_cache.frequency/1000;
+
+    if (tmp != NULL) {
+	while (freq/1000 > tmp->freq) /* find the right one */
+	    tmp++;
+	state->wbd_gain_current = tmp->wbd_gain_val;
+	} else
+	state->wbd_gain_current = 6;
+
+    return state->wbd_offset_3_3[state->wbd_gain_current - 6];
+}
+EXPORT_SYMBOL(dib0070_wbd_offset);
+
+#define pgm_read_word(w) (*w)
+static int dib0070_reset(struct dvb_frontend *fe)
+{
+    struct dib0070_state *state = fe->tuner_priv;
+	u16 l, r, *n;
+
+	HARD_RESET(state);
+
+
+#ifndef FORCE_SBAND_TUNER
+	if ((dib0070_read_reg(state, 0x22) >> 9) & 0x1)
+		state->revision = (dib0070_read_reg(state, 0x1f) >> 8) & 0xff;
+	else
+#else
+#warning forcing SBAND
+#endif
+		state->revision = DIB0070S_P1A;
+
+	/* P1F or not */
+	dprintk("Revision: %x", state->revision);
+
+	if (state->revision == DIB0070_P1D) {
+		dprintk("Error: this driver is not to be used meant for P1D or earlier");
+		return -EINVAL;
+	}
+
+	n = (u16 *) dib0070_p1f_defaults;
+	l = pgm_read_word(n++);
+	while (l) {
+		r = pgm_read_word(n++);
+		do {
+			dib0070_write_reg(state, (u8)r, pgm_read_word(n++));
+			r++;
+		} while (--l);
+		l = pgm_read_word(n++);
+	}
+
+	if (state->cfg->force_crystal_mode != 0)
+		r = state->cfg->force_crystal_mode;
+	else if (state->cfg->clock_khz >= 24000)
+		r = 1;
+	else
+		r = 2;
+
+
+	r |= state->cfg->osc_buffer_state << 3;
+
+	dib0070_write_reg(state, 0x10, r);
+	dib0070_write_reg(state, 0x1f, (1 << 8) | ((state->cfg->clock_pad_drive & 0xf) << 5));
+
+	if (state->cfg->invert_iq) {
+		r = dib0070_read_reg(state, 0x02) & 0xffdf;
+		dib0070_write_reg(state, 0x02, r | (1 << 5));
+	}
+
+    if (state->revision == DIB0070S_P1A)
+	dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0);
+    else
+		dib0070_set_ctrl_lo5(fe, 5, 4, state->cfg->charge_pump, state->cfg->enable_third_order_filter);
+
+	dib0070_write_reg(state, 0x01, (54 << 9) | 0xc8);
+
+    dib0070_wbd_offset_calibration(state);
+
+    return 0;
+}
+
+static int dib0070_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+    struct dib0070_state *state = fe->tuner_priv;
+
+    *frequency = 1000 * state->current_rf;
+    return 0;
+}
+
+static int dib0070_release(struct dvb_frontend *fe)
+{
+	kfree(fe->tuner_priv);
+	fe->tuner_priv = NULL;
+	return 0;
+}
+
+static const struct dvb_tuner_ops dib0070_ops = {
+	.info = {
+		.name           = "DiBcom DiB0070",
+		.frequency_min  =  45000000,
+		.frequency_max  = 860000000,
+		.frequency_step =      1000,
+	},
+	.release       = dib0070_release,
+
+	.init          = dib0070_wakeup,
+	.sleep         = dib0070_sleep,
+	.set_params    = dib0070_tune,
+
+	.get_frequency = dib0070_get_frequency,
+//      .get_bandwidth = dib0070_get_bandwidth
+};
+
+struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg)
+{
+	struct dib0070_state *state = kzalloc(sizeof(struct dib0070_state), GFP_KERNEL);
+	if (state == NULL)
+		return NULL;
+
+	state->cfg = cfg;
+	state->i2c = i2c;
+	state->fe  = fe;
+	mutex_init(&state->i2c_buffer_lock);
+	fe->tuner_priv = state;
+
+	if (dib0070_reset(fe) != 0)
+		goto free_mem;
+
+	printk(KERN_INFO "DiB0070: successfully identified\n");
+	memcpy(&fe->ops.tuner_ops, &dib0070_ops, sizeof(struct dvb_tuner_ops));
+
+	fe->tuner_priv = state;
+	return fe;
+
+free_mem:
+	kfree(state);
+	fe->tuner_priv = NULL;
+	return NULL;
+}
+EXPORT_SYMBOL(dib0070_attach);
+
+MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
+MODULE_DESCRIPTION("Driver for the DiBcom 0070 base-band RF Tuner");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb-frontends/dib0070.h b/drivers/media/dvb-frontends/dib0070.h
new file mode 100644
index 0000000..45c31fa
--- /dev/null
+++ b/drivers/media/dvb-frontends/dib0070.h
@@ -0,0 +1,76 @@
+/*
+ * Linux-DVB Driver for DiBcom's DiB0070 base-band RF Tuner.
+ *
+ * Copyright (C) 2005-7 DiBcom (http://www.dibcom.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, version 2.
+ */
+#ifndef DIB0070_H
+#define DIB0070_H
+
+struct dvb_frontend;
+struct i2c_adapter;
+
+#define DEFAULT_DIB0070_I2C_ADDRESS 0x60
+
+struct dib0070_wbd_gain_cfg {
+	u16 freq;
+	u16 wbd_gain_val;
+};
+
+struct dib0070_config {
+	u8 i2c_address;
+
+	/* tuner pins controlled externally */
+	int (*reset) (struct dvb_frontend *, int);
+	int (*sleep) (struct dvb_frontend *, int);
+
+	/*  offset in kHz */
+	int freq_offset_khz_uhf;
+	int freq_offset_khz_vhf;
+
+	u8 osc_buffer_state;	/* 0= normal, 1= tri-state */
+	u32 clock_khz;
+	u8 clock_pad_drive;	/* (Drive + 1) * 2mA */
+
+	u8 invert_iq;		/* invert Q - in case I or Q is inverted on the board */
+
+	u8 force_crystal_mode;	/* if == 0 -> decision is made in the driver default: <24 -> 2, >=24 -> 1 */
+
+	u8 flip_chip;
+	u8 enable_third_order_filter;
+	u8 charge_pump;
+
+	const struct dib0070_wbd_gain_cfg *wbd_gain;
+
+	u8 vga_filter;
+};
+
+#if defined(CONFIG_DVB_TUNER_DIB0070) || (defined(CONFIG_DVB_TUNER_DIB0070_MODULE) && defined(MODULE))
+extern struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg);
+extern u16 dib0070_wbd_offset(struct dvb_frontend *);
+extern void dib0070_ctrl_agc_filter(struct dvb_frontend *, u8 open);
+extern u8 dib0070_get_rf_output(struct dvb_frontend *fe);
+extern int dib0070_set_rf_output(struct dvb_frontend *fe, u8 no);
+#else
+static inline struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+
+static inline u16 dib0070_wbd_offset(struct dvb_frontend *fe)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return 0;
+}
+
+static inline void dib0070_ctrl_agc_filter(struct dvb_frontend *fe, u8 open)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+}
+#endif
+
+#endif
diff --git a/drivers/media/dvb-frontends/dib0090.c b/drivers/media/dvb-frontends/dib0090.c
new file mode 100644
index 0000000..d9fe60b
--- /dev/null
+++ b/drivers/media/dvb-frontends/dib0090.c
@@ -0,0 +1,2686 @@
+/*
+ * Linux-DVB Driver for DiBcom's DiB0090 base-band RF Tuner.
+ *
+ * Copyright (C) 2005-9 DiBcom (http://www.dibcom.fr/)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ * This code is more or less generated from another driver, please
+ * excuse some codingstyle oddities.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+
+#include "dvb_frontend.h"
+
+#include "dib0090.h"
+#include "dibx000_common.h"
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
+
+#define dprintk(args...) do { \
+	if (debug) { \
+		printk(KERN_DEBUG "DiB0090: "); \
+		printk(args); \
+		printk("\n"); \
+	} \
+} while (0)
+
+#define CONFIG_SYS_DVBT
+#define CONFIG_SYS_ISDBT
+#define CONFIG_BAND_CBAND
+#define CONFIG_BAND_VHF
+#define CONFIG_BAND_UHF
+#define CONFIG_DIB0090_USE_PWM_AGC
+
+#define EN_LNA0      0x8000
+#define EN_LNA1      0x4000
+#define EN_LNA2      0x2000
+#define EN_LNA3      0x1000
+#define EN_MIX0      0x0800
+#define EN_MIX1      0x0400
+#define EN_MIX2      0x0200
+#define EN_MIX3      0x0100
+#define EN_IQADC     0x0040
+#define EN_PLL       0x0020
+#define EN_TX        0x0010
+#define EN_BB        0x0008
+#define EN_LO        0x0004
+#define EN_BIAS      0x0001
+
+#define EN_IQANA     0x0002
+#define EN_DIGCLK    0x0080	/* not in the 0x24 reg, only in 0x1b */
+#define EN_CRYSTAL   0x0002
+
+#define EN_UHF		 0x22E9
+#define EN_VHF		 0x44E9
+#define EN_LBD		 0x11E9
+#define EN_SBD		 0x44E9
+#define EN_CAB		 0x88E9
+
+/* Calibration defines */
+#define      DC_CAL 0x1
+#define     WBD_CAL 0x2
+#define    TEMP_CAL 0x4
+#define CAPTRIM_CAL 0x8
+
+#define KROSUS_PLL_LOCKED   0x800
+#define KROSUS              0x2
+
+/* Use those defines to identify SOC version */
+#define SOC               0x02
+#define SOC_7090_P1G_11R1 0x82
+#define SOC_7090_P1G_21R1 0x8a
+#define SOC_8090_P1G_11R1 0x86
+#define SOC_8090_P1G_21R1 0x8e
+
+/* else use thos ones to check */
+#define P1A_B      0x0
+#define P1C	   0x1
+#define P1D_E_F    0x3
+#define P1G	   0x7
+#define P1G_21R2   0xf
+
+#define MP001 0x1		/* Single 9090/8096 */
+#define MP005 0x4		/* Single Sband */
+#define MP008 0x6		/* Dual diversity VHF-UHF-LBAND */
+#define MP009 0x7		/* Dual diversity 29098 CBAND-UHF-LBAND-SBAND */
+
+#define pgm_read_word(w) (*w)
+
+struct dc_calibration;
+
+struct dib0090_tuning {
+	u32 max_freq;		/* for every frequency less than or equal to that field: this information is correct */
+	u8 switch_trim;
+	u8 lna_tune;
+	u16 lna_bias;
+	u16 v2i;
+	u16 mix;
+	u16 load;
+	u16 tuner_enable;
+};
+
+struct dib0090_pll {
+	u32 max_freq;		/* for every frequency less than or equal to that field: this information is correct */
+	u8 vco_band;
+	u8 hfdiv_code;
+	u8 hfdiv;
+	u8 topresc;
+};
+
+struct dib0090_identity {
+	u8 version;
+	u8 product;
+	u8 p1g;
+	u8 in_soc;
+};
+
+struct dib0090_state {
+	struct i2c_adapter *i2c;
+	struct dvb_frontend *fe;
+	const struct dib0090_config *config;
+
+	u8 current_band;
+	enum frontend_tune_state tune_state;
+	u32 current_rf;
+
+	u16 wbd_offset;
+	s16 wbd_target;		/* in dB */
+
+	s16 rf_gain_limit;	/* take-over-point: where to split between bb and rf gain */
+	s16 current_gain;	/* keeps the currently programmed gain */
+	u8 agc_step;		/* new binary search */
+
+	u16 gain[2];		/* for channel monitoring */
+
+	const u16 *rf_ramp;
+	const u16 *bb_ramp;
+
+	/* for the software AGC ramps */
+	u16 bb_1_def;
+	u16 rf_lt_def;
+	u16 gain_reg[4];
+
+	/* for the captrim/dc-offset search */
+	s8 step;
+	s16 adc_diff;
+	s16 min_adc_diff;
+
+	s8 captrim;
+	s8 fcaptrim;
+
+	const struct dc_calibration *dc;
+	u16 bb6, bb7;
+
+	const struct dib0090_tuning *current_tune_table_index;
+	const struct dib0090_pll *current_pll_table_index;
+
+	u8 tuner_is_tuned;
+	u8 agc_freeze;
+
+	struct dib0090_identity identity;
+
+	u32 rf_request;
+	u8 current_standard;
+
+	u8 calibrate;
+	u32 rest;
+	u16 bias;
+	s16 temperature;
+
+	u8 wbd_calibration_gain;
+	const struct dib0090_wbd_slope *current_wbd_table;
+	u16 wbdmux;
+
+	/* for the I2C transfer */
+	struct i2c_msg msg[2];
+	u8 i2c_write_buffer[3];
+	u8 i2c_read_buffer[2];
+	struct mutex i2c_buffer_lock;
+};
+
+struct dib0090_fw_state {
+	struct i2c_adapter *i2c;
+	struct dvb_frontend *fe;
+	struct dib0090_identity identity;
+	const struct dib0090_config *config;
+
+	/* for the I2C transfer */
+	struct i2c_msg msg;
+	u8 i2c_write_buffer[2];
+	u8 i2c_read_buffer[2];
+	struct mutex i2c_buffer_lock;
+};
+
+static u16 dib0090_read_reg(struct dib0090_state *state, u8 reg)
+{
+	u16 ret;
+
+	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
+		dprintk("could not acquire lock");
+		return 0;
+	}
+
+	state->i2c_write_buffer[0] = reg;
+
+	memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
+	state->msg[0].addr = state->config->i2c_address;
+	state->msg[0].flags = 0;
+	state->msg[0].buf = state->i2c_write_buffer;
+	state->msg[0].len = 1;
+	state->msg[1].addr = state->config->i2c_address;
+	state->msg[1].flags = I2C_M_RD;
+	state->msg[1].buf = state->i2c_read_buffer;
+	state->msg[1].len = 2;
+
+	if (i2c_transfer(state->i2c, state->msg, 2) != 2) {
+		printk(KERN_WARNING "DiB0090 I2C read failed\n");
+		ret = 0;
+	} else
+		ret = (state->i2c_read_buffer[0] << 8)
+			| state->i2c_read_buffer[1];
+
+	mutex_unlock(&state->i2c_buffer_lock);
+	return ret;
+}
+
+static int dib0090_write_reg(struct dib0090_state *state, u32 reg, u16 val)
+{
+	int ret;
+
+	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
+		dprintk("could not acquire lock");
+		return -EINVAL;
+	}
+
+	state->i2c_write_buffer[0] = reg & 0xff;
+	state->i2c_write_buffer[1] = val >> 8;
+	state->i2c_write_buffer[2] = val & 0xff;
+
+	memset(state->msg, 0, sizeof(struct i2c_msg));
+	state->msg[0].addr = state->config->i2c_address;
+	state->msg[0].flags = 0;
+	state->msg[0].buf = state->i2c_write_buffer;
+	state->msg[0].len = 3;
+
+	if (i2c_transfer(state->i2c, state->msg, 1) != 1) {
+		printk(KERN_WARNING "DiB0090 I2C write failed\n");
+		ret = -EREMOTEIO;
+	} else
+		ret = 0;
+
+	mutex_unlock(&state->i2c_buffer_lock);
+	return ret;
+}
+
+static u16 dib0090_fw_read_reg(struct dib0090_fw_state *state, u8 reg)
+{
+	u16 ret;
+
+	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
+		dprintk("could not acquire lock");
+		return 0;
+	}
+
+	state->i2c_write_buffer[0] = reg;
+
+	memset(&state->msg, 0, sizeof(struct i2c_msg));
+	state->msg.addr = reg;
+	state->msg.flags = I2C_M_RD;
+	state->msg.buf = state->i2c_read_buffer;
+	state->msg.len = 2;
+	if (i2c_transfer(state->i2c, &state->msg, 1) != 1) {
+		printk(KERN_WARNING "DiB0090 I2C read failed\n");
+		ret = 0;
+	} else
+		ret = (state->i2c_read_buffer[0] << 8)
+			| state->i2c_read_buffer[1];
+
+	mutex_unlock(&state->i2c_buffer_lock);
+	return ret;
+}
+
+static int dib0090_fw_write_reg(struct dib0090_fw_state *state, u8 reg, u16 val)
+{
+	int ret;
+
+	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
+		dprintk("could not acquire lock");
+		return -EINVAL;
+	}
+
+	state->i2c_write_buffer[0] = val >> 8;
+	state->i2c_write_buffer[1] = val & 0xff;
+
+	memset(&state->msg, 0, sizeof(struct i2c_msg));
+	state->msg.addr = reg;
+	state->msg.flags = 0;
+	state->msg.buf = state->i2c_write_buffer;
+	state->msg.len = 2;
+	if (i2c_transfer(state->i2c, &state->msg, 1) != 1) {
+		printk(KERN_WARNING "DiB0090 I2C write failed\n");
+		ret = -EREMOTEIO;
+	} else
+		ret = 0;
+
+	mutex_unlock(&state->i2c_buffer_lock);
+	return ret;
+}
+
+#define HARD_RESET(state) do {  if (cfg->reset) {  if (cfg->sleep) cfg->sleep(fe, 0); msleep(10);  cfg->reset(fe, 1); msleep(10);  cfg->reset(fe, 0); msleep(10);  }  } while (0)
+#define ADC_TARGET -220
+#define GAIN_ALPHA 5
+#define WBD_ALPHA 6
+#define LPF	100
+static void dib0090_write_regs(struct dib0090_state *state, u8 r, const u16 * b, u8 c)
+{
+	do {
+		dib0090_write_reg(state, r++, *b++);
+	} while (--c);
+}
+
+static int dib0090_identify(struct dvb_frontend *fe)
+{
+	struct dib0090_state *state = fe->tuner_priv;
+	u16 v;
+	struct dib0090_identity *identity = &state->identity;
+
+	v = dib0090_read_reg(state, 0x1a);
+
+	identity->p1g = 0;
+	identity->in_soc = 0;
+
+	dprintk("Tuner identification (Version = 0x%04x)", v);
+
+	/* without PLL lock info */
+	v &= ~KROSUS_PLL_LOCKED;
+
+	identity->version = v & 0xff;
+	identity->product = (v >> 8) & 0xf;
+
+	if (identity->product != KROSUS)
+		goto identification_error;
+
+	if ((identity->version & 0x3) == SOC) {
+		identity->in_soc = 1;
+		switch (identity->version) {
+		case SOC_8090_P1G_11R1:
+			dprintk("SOC 8090 P1-G11R1 Has been detected");
+			identity->p1g = 1;
+			break;
+		case SOC_8090_P1G_21R1:
+			dprintk("SOC 8090 P1-G21R1 Has been detected");
+			identity->p1g = 1;
+			break;
+		case SOC_7090_P1G_11R1:
+			dprintk("SOC 7090 P1-G11R1 Has been detected");
+			identity->p1g = 1;
+			break;
+		case SOC_7090_P1G_21R1:
+			dprintk("SOC 7090 P1-G21R1 Has been detected");
+			identity->p1g = 1;
+			break;
+		default:
+			goto identification_error;
+		}
+	} else {
+		switch ((identity->version >> 5) & 0x7) {
+		case MP001:
+			dprintk("MP001 : 9090/8096");
+			break;
+		case MP005:
+			dprintk("MP005 : Single Sband");
+			break;
+		case MP008:
+			dprintk("MP008 : diversity VHF-UHF-LBAND");
+			break;
+		case MP009:
+			dprintk("MP009 : diversity 29098 CBAND-UHF-LBAND-SBAND");
+			break;
+		default:
+			goto identification_error;
+		}
+
+		switch (identity->version & 0x1f) {
+		case P1G_21R2:
+			dprintk("P1G_21R2 detected");
+			identity->p1g = 1;
+			break;
+		case P1G:
+			dprintk("P1G detected");
+			identity->p1g = 1;
+			break;
+		case P1D_E_F:
+			dprintk("P1D/E/F detected");
+			break;
+		case P1C:
+			dprintk("P1C detected");
+			break;
+		case P1A_B:
+			dprintk("P1-A/B detected: driver is deactivated - not available");
+			goto identification_error;
+			break;
+		default:
+			goto identification_error;
+		}
+	}
+
+	return 0;
+
+identification_error:
+	return -EIO;
+}
+
+static int dib0090_fw_identify(struct dvb_frontend *fe)
+{
+	struct dib0090_fw_state *state = fe->tuner_priv;
+	struct dib0090_identity *identity = &state->identity;
+
+	u16 v = dib0090_fw_read_reg(state, 0x1a);
+	identity->p1g = 0;
+	identity->in_soc = 0;
+
+	dprintk("FE: Tuner identification (Version = 0x%04x)", v);
+
+	/* without PLL lock info */
+	v &= ~KROSUS_PLL_LOCKED;
+
+	identity->version = v & 0xff;
+	identity->product = (v >> 8) & 0xf;
+
+	if (identity->product != KROSUS)
+		goto identification_error;
+
+	if ((identity->version & 0x3) == SOC) {
+		identity->in_soc = 1;
+		switch (identity->version) {
+		case SOC_8090_P1G_11R1:
+			dprintk("SOC 8090 P1-G11R1 Has been detected");
+			identity->p1g = 1;
+			break;
+		case SOC_8090_P1G_21R1:
+			dprintk("SOC 8090 P1-G21R1 Has been detected");
+			identity->p1g = 1;
+			break;
+		case SOC_7090_P1G_11R1:
+			dprintk("SOC 7090 P1-G11R1 Has been detected");
+			identity->p1g = 1;
+			break;
+		case SOC_7090_P1G_21R1:
+			dprintk("SOC 7090 P1-G21R1 Has been detected");
+			identity->p1g = 1;
+			break;
+		default:
+			goto identification_error;
+		}
+	} else {
+		switch ((identity->version >> 5) & 0x7) {
+		case MP001:
+			dprintk("MP001 : 9090/8096");
+			break;
+		case MP005:
+			dprintk("MP005 : Single Sband");
+			break;
+		case MP008:
+			dprintk("MP008 : diversity VHF-UHF-LBAND");
+			break;
+		case MP009:
+			dprintk("MP009 : diversity 29098 CBAND-UHF-LBAND-SBAND");
+			break;
+		default:
+			goto identification_error;
+		}
+
+		switch (identity->version & 0x1f) {
+		case P1G_21R2:
+			dprintk("P1G_21R2 detected");
+			identity->p1g = 1;
+			break;
+		case P1G:
+			dprintk("P1G detected");
+			identity->p1g = 1;
+			break;
+		case P1D_E_F:
+			dprintk("P1D/E/F detected");
+			break;
+		case P1C:
+			dprintk("P1C detected");
+			break;
+		case P1A_B:
+			dprintk("P1-A/B detected: driver is deactivated - not available");
+			goto identification_error;
+			break;
+		default:
+			goto identification_error;
+		}
+	}
+
+	return 0;
+
+identification_error:
+	return -EIO;
+}
+
+static void dib0090_reset_digital(struct dvb_frontend *fe, const struct dib0090_config *cfg)
+{
+	struct dib0090_state *state = fe->tuner_priv;
+	u16 PllCfg, i, v;
+
+	HARD_RESET(state);
+
+	dib0090_write_reg(state, 0x24, EN_PLL | EN_CRYSTAL);
+	dib0090_write_reg(state, 0x1b, EN_DIGCLK | EN_PLL | EN_CRYSTAL);	/* PLL, DIG_CLK and CRYSTAL remain */
+
+	if (!cfg->in_soc) {
+		/* adcClkOutRatio=8->7, release reset */
+		dib0090_write_reg(state, 0x20, ((cfg->io.adc_clock_ratio - 1) << 11) | (0 << 10) | (1 << 9) | (1 << 8) | (0 << 4) | 0);
+		if (cfg->clkoutdrive != 0)
+			dib0090_write_reg(state, 0x23, (0 << 15) | ((!cfg->analog_output) << 14) | (2 << 10) | (1 << 9) | (0 << 8)
+					  | (cfg->clkoutdrive << 5) | (cfg->clkouttobamse << 4) | (0 << 2) | (0));
+		else
+			dib0090_write_reg(state, 0x23, (0 << 15) | ((!cfg->analog_output) << 14) | (2 << 10) | (1 << 9) | (0 << 8)
+					  | (7 << 5) | (cfg->clkouttobamse << 4) | (0 << 2) | (0));
+	}
+
+	/* Read Pll current config * */
+	PllCfg = dib0090_read_reg(state, 0x21);
+
+	/** Reconfigure PLL if current setting is different from default setting **/
+	if ((PllCfg & 0x1FFF) != ((cfg->io.pll_range << 12) | (cfg->io.pll_loopdiv << 6) | (cfg->io.pll_prediv)) && (!cfg->in_soc)
+			&& !cfg->io.pll_bypass) {
+
+		/* Set Bypass mode */
+		PllCfg |= (1 << 15);
+		dib0090_write_reg(state, 0x21, PllCfg);
+
+		/* Set Reset Pll */
+		PllCfg &= ~(1 << 13);
+		dib0090_write_reg(state, 0x21, PllCfg);
+
+	/*** Set new Pll configuration in bypass and reset state ***/
+		PllCfg = (1 << 15) | (0 << 13) | (cfg->io.pll_range << 12) | (cfg->io.pll_loopdiv << 6) | (cfg->io.pll_prediv);
+		dib0090_write_reg(state, 0x21, PllCfg);
+
+		/* Remove Reset Pll */
+		PllCfg |= (1 << 13);
+		dib0090_write_reg(state, 0x21, PllCfg);
+
+	/*** Wait for PLL lock ***/
+		i = 100;
+		do {
+			v = !!(dib0090_read_reg(state, 0x1a) & 0x800);
+			if (v)
+				break;
+		} while (--i);
+
+		if (i == 0) {
+			dprintk("Pll: Unable to lock Pll");
+			return;
+		}
+
+		/* Finally Remove Bypass mode */
+		PllCfg &= ~(1 << 15);
+		dib0090_write_reg(state, 0x21, PllCfg);
+	}
+
+	if (cfg->io.pll_bypass) {
+		PllCfg |= (cfg->io.pll_bypass << 15);
+		dib0090_write_reg(state, 0x21, PllCfg);
+	}
+}
+
+static int dib0090_fw_reset_digital(struct dvb_frontend *fe, const struct dib0090_config *cfg)
+{
+	struct dib0090_fw_state *state = fe->tuner_priv;
+	u16 PllCfg;
+	u16 v;
+	int i;
+
+	dprintk("fw reset digital");
+	HARD_RESET(state);
+
+	dib0090_fw_write_reg(state, 0x24, EN_PLL | EN_CRYSTAL);
+	dib0090_fw_write_reg(state, 0x1b, EN_DIGCLK | EN_PLL | EN_CRYSTAL);	/* PLL, DIG_CLK and CRYSTAL remain */
+
+	dib0090_fw_write_reg(state, 0x20,
+			((cfg->io.adc_clock_ratio - 1) << 11) | (0 << 10) | (1 << 9) | (1 << 8) | (cfg->data_tx_drv << 4) | cfg->ls_cfg_pad_drv);
+
+	v = (0 << 15) | ((!cfg->analog_output) << 14) | (1 << 9) | (0 << 8) | (cfg->clkouttobamse << 4) | (0 << 2) | (0);
+	if (cfg->clkoutdrive != 0)
+		v |= cfg->clkoutdrive << 5;
+	else
+		v |= 7 << 5;
+
+	v |= 2 << 10;
+	dib0090_fw_write_reg(state, 0x23, v);
+
+	/* Read Pll current config * */
+	PllCfg = dib0090_fw_read_reg(state, 0x21);
+
+	/** Reconfigure PLL if current setting is different from default setting **/
+	if ((PllCfg & 0x1FFF) != ((cfg->io.pll_range << 12) | (cfg->io.pll_loopdiv << 6) | (cfg->io.pll_prediv)) && !cfg->io.pll_bypass) {
+
+		/* Set Bypass mode */
+		PllCfg |= (1 << 15);
+		dib0090_fw_write_reg(state, 0x21, PllCfg);
+
+		/* Set Reset Pll */
+		PllCfg &= ~(1 << 13);
+		dib0090_fw_write_reg(state, 0x21, PllCfg);
+
+	/*** Set new Pll configuration in bypass and reset state ***/
+		PllCfg = (1 << 15) | (0 << 13) | (cfg->io.pll_range << 12) | (cfg->io.pll_loopdiv << 6) | (cfg->io.pll_prediv);
+		dib0090_fw_write_reg(state, 0x21, PllCfg);
+
+		/* Remove Reset Pll */
+		PllCfg |= (1 << 13);
+		dib0090_fw_write_reg(state, 0x21, PllCfg);
+
+	/*** Wait for PLL lock ***/
+		i = 100;
+		do {
+			v = !!(dib0090_fw_read_reg(state, 0x1a) & 0x800);
+			if (v)
+				break;
+		} while (--i);
+
+		if (i == 0) {
+			dprintk("Pll: Unable to lock Pll");
+			return -EIO;
+		}
+
+		/* Finally Remove Bypass mode */
+		PllCfg &= ~(1 << 15);
+		dib0090_fw_write_reg(state, 0x21, PllCfg);
+	}
+
+	if (cfg->io.pll_bypass) {
+		PllCfg |= (cfg->io.pll_bypass << 15);
+		dib0090_fw_write_reg(state, 0x21, PllCfg);
+	}
+
+	return dib0090_fw_identify(fe);
+}
+
+static int dib0090_wakeup(struct dvb_frontend *fe)
+{
+	struct dib0090_state *state = fe->tuner_priv;
+	if (state->config->sleep)
+		state->config->sleep(fe, 0);
+
+	/* enable dataTX in case we have been restarted in the wrong moment */
+	dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) | (1 << 14));
+	return 0;
+}
+
+static int dib0090_sleep(struct dvb_frontend *fe)
+{
+	struct dib0090_state *state = fe->tuner_priv;
+	if (state->config->sleep)
+		state->config->sleep(fe, 1);
+	return 0;
+}
+
+void dib0090_dcc_freq(struct dvb_frontend *fe, u8 fast)
+{
+	struct dib0090_state *state = fe->tuner_priv;
+	if (fast)
+		dib0090_write_reg(state, 0x04, 0);
+	else
+		dib0090_write_reg(state, 0x04, 1);
+}
+
+EXPORT_SYMBOL(dib0090_dcc_freq);
+
+static const u16 bb_ramp_pwm_normal_socs[] = {
+	550,			/* max BB gain in 10th of dB */
+	(1 << 9) | 8,		/* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> BB_RAMP2 */
+	440,
+	(4 << 9) | 0,		/* BB_RAMP3 = 26dB */
+	(0 << 9) | 208,		/* BB_RAMP4 */
+	(4 << 9) | 208,		/* BB_RAMP5 = 29dB */
+	(0 << 9) | 440,		/* BB_RAMP6 */
+};
+
+static const u16 rf_ramp_pwm_cband_7090[] = {
+	280,			/* max RF gain in 10th of dB */
+	18,			/* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
+	504,			/* ramp_max = maximum X used on the ramp */
+	(29 << 10) | 364,	/* RF_RAMP5, LNA 1 = 8dB */
+	(0 << 10) | 504,	/* RF_RAMP6, LNA 1 */
+	(60 << 10) | 228,	/* RF_RAMP7, LNA 2 = 7.7dB */
+	(0 << 10) | 364,	/* RF_RAMP8, LNA 2 */
+	(34 << 10) | 109,	/* GAIN_4_1, LNA 3 = 6.8dB */
+	(0 << 10) | 228,	/* GAIN_4_2, LNA 3 */
+	(37 << 10) | 0,		/* RF_RAMP3, LNA 4 = 6.2dB */
+	(0 << 10) | 109,	/* RF_RAMP4, LNA 4 */
+};
+
+static const uint16_t rf_ramp_pwm_cband_7090e_sensitivity[] = {
+	186,
+	40,
+	746,
+	(10 << 10) | 345,
+	(0  << 10) | 746,
+	(0 << 10) | 0,
+	(0  << 10) | 0,
+	(28 << 10) | 200,
+	(0  << 10) | 345,
+	(20 << 10) | 0,
+	(0  << 10) | 200,
+};
+
+static const uint16_t rf_ramp_pwm_cband_7090e_aci[] = {
+	86,
+	40,
+	345,
+	(0 << 10) | 0,
+	(0 << 10) | 0,
+	(0 << 10) | 0,
+	(0 << 10) | 0,
+	(28 << 10) | 200,
+	(0  << 10) | 345,
+	(20 << 10) | 0,
+	(0  << 10) | 200,
+};
+
+static const u16 rf_ramp_pwm_cband_8090[] = {
+	345,			/* max RF gain in 10th of dB */
+	29,			/* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
+	1000,			/* ramp_max = maximum X used on the ramp */
+	(35 << 10) | 772,	/* RF_RAMP3, LNA 1 = 8dB */
+	(0 << 10) | 1000,	/* RF_RAMP4, LNA 1 */
+	(58 << 10) | 496,	/* RF_RAMP5, LNA 2 = 9.5dB */
+	(0 << 10) | 772,	/* RF_RAMP6, LNA 2 */
+	(27 << 10) | 200,	/* RF_RAMP7, LNA 3 = 10.5dB */
+	(0 << 10) | 496,	/* RF_RAMP8, LNA 3 */
+	(40 << 10) | 0,		/* GAIN_4_1, LNA 4 = 7dB */
+	(0 << 10) | 200,	/* GAIN_4_2, LNA 4 */
+};
+
+static const u16 rf_ramp_pwm_uhf_7090[] = {
+	407,			/* max RF gain in 10th of dB */
+	13,			/* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
+	529,			/* ramp_max = maximum X used on the ramp */
+	(23 << 10) | 0,		/* RF_RAMP3, LNA 1 = 14.7dB */
+	(0 << 10) | 176,	/* RF_RAMP4, LNA 1 */
+	(63 << 10) | 400,	/* RF_RAMP5, LNA 2 = 8dB */
+	(0 << 10) | 529,	/* RF_RAMP6, LNA 2 */
+	(48 << 10) | 316,	/* RF_RAMP7, LNA 3 = 6.8dB */
+	(0 << 10) | 400,	/* RF_RAMP8, LNA 3 */
+	(29 << 10) | 176,	/* GAIN_4_1, LNA 4 = 11.5dB */
+	(0 << 10) | 316,	/* GAIN_4_2, LNA 4 */
+};
+
+static const u16 rf_ramp_pwm_uhf_8090[] = {
+	388,			/* max RF gain in 10th of dB */
+	26,			/* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
+	1008,			/* ramp_max = maximum X used on the ramp */
+	(11 << 10) | 0,		/* RF_RAMP3, LNA 1 = 14.7dB */
+	(0 << 10) | 369,	/* RF_RAMP4, LNA 1 */
+	(41 << 10) | 809,	/* RF_RAMP5, LNA 2 = 8dB */
+	(0 << 10) | 1008,	/* RF_RAMP6, LNA 2 */
+	(27 << 10) | 659,	/* RF_RAMP7, LNA 3 = 6dB */
+	(0 << 10) | 809,	/* RF_RAMP8, LNA 3 */
+	(14 << 10) | 369,	/* GAIN_4_1, LNA 4 = 11.5dB */
+	(0 << 10) | 659,	/* GAIN_4_2, LNA 4 */
+};
+
+static const u16 rf_ramp_pwm_cband[] = {
+	0,			/* max RF gain in 10th of dB */
+	0,			/* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> 0x2b */
+	0,			/* ramp_max = maximum X used on the ramp */
+	(0 << 10) | 0,		/* 0x2c, LNA 1 = 0dB */
+	(0 << 10) | 0,		/* 0x2d, LNA 1 */
+	(0 << 10) | 0,		/* 0x2e, LNA 2 = 0dB */
+	(0 << 10) | 0,		/* 0x2f, LNA 2 */
+	(0 << 10) | 0,		/* 0x30, LNA 3 = 0dB */
+	(0 << 10) | 0,		/* 0x31, LNA 3 */
+	(0 << 10) | 0,		/* GAIN_4_1, LNA 4 = 0dB */
+	(0 << 10) | 0,		/* GAIN_4_2, LNA 4 */
+};
+
+static const u16 rf_ramp_vhf[] = {
+	412,			/* max RF gain in 10th of dB */
+	132, 307, 127,		/* LNA1,  13.2dB */
+	105, 412, 255,		/* LNA2,  10.5dB */
+	50, 50, 127,		/* LNA3,  5dB */
+	125, 175, 127,		/* LNA4,  12.5dB */
+	0, 0, 127,		/* CBAND, 0dB */
+};
+
+static const u16 rf_ramp_uhf[] = {
+	412,			/* max RF gain in 10th of dB */
+	132, 307, 127,		/* LNA1  : total gain = 13.2dB, point on the ramp where this amp is full gain, value to write to get full gain */
+	105, 412, 255,		/* LNA2  : 10.5 dB */
+	50, 50, 127,		/* LNA3  :  5.0 dB */
+	125, 175, 127,		/* LNA4  : 12.5 dB */
+	0, 0, 127,		/* CBAND :  0.0 dB */
+};
+
+static const u16 rf_ramp_cband_broadmatching[] =	/* for p1G only */
+{
+	314,			/* Calibrated at 200MHz order has been changed g4-g3-g2-g1 */
+	84, 314, 127,		/* LNA1 */
+	80, 230, 255,		/* LNA2 */
+	80, 150, 127,		/* LNA3  It was measured 12dB, do not lock if 120 */
+	70, 70, 127,		/* LNA4 */
+	0, 0, 127,		/* CBAND */
+};
+
+static const u16 rf_ramp_cband[] = {
+	332,			/* max RF gain in 10th of dB */
+	132, 252, 127,		/* LNA1,  dB */
+	80, 332, 255,		/* LNA2,  dB */
+	0, 0, 127,		/* LNA3,  dB */
+	0, 0, 127,		/* LNA4,  dB */
+	120, 120, 127,		/* LT1 CBAND */
+};
+
+static const u16 rf_ramp_pwm_vhf[] = {
+	404,			/* max RF gain in 10th of dB */
+	25,			/* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> 0x2b */
+	1011,			/* ramp_max = maximum X used on the ramp */
+	(6 << 10) | 417,	/* 0x2c, LNA 1 = 13.2dB */
+	(0 << 10) | 756,	/* 0x2d, LNA 1 */
+	(16 << 10) | 756,	/* 0x2e, LNA 2 = 10.5dB */
+	(0 << 10) | 1011,	/* 0x2f, LNA 2 */
+	(16 << 10) | 290,	/* 0x30, LNA 3 = 5dB */
+	(0 << 10) | 417,	/* 0x31, LNA 3 */
+	(7 << 10) | 0,		/* GAIN_4_1, LNA 4 = 12.5dB */
+	(0 << 10) | 290,	/* GAIN_4_2, LNA 4 */
+};
+
+static const u16 rf_ramp_pwm_uhf[] = {
+	404,			/* max RF gain in 10th of dB */
+	25,			/* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> 0x2b */
+	1011,			/* ramp_max = maximum X used on the ramp */
+	(6 << 10) | 417,	/* 0x2c, LNA 1 = 13.2dB */
+	(0 << 10) | 756,	/* 0x2d, LNA 1 */
+	(16 << 10) | 756,	/* 0x2e, LNA 2 = 10.5dB */
+	(0 << 10) | 1011,	/* 0x2f, LNA 2 */
+	(16 << 10) | 0,		/* 0x30, LNA 3 = 5dB */
+	(0 << 10) | 127,	/* 0x31, LNA 3 */
+	(7 << 10) | 127,	/* GAIN_4_1, LNA 4 = 12.5dB */
+	(0 << 10) | 417,	/* GAIN_4_2, LNA 4 */
+};
+
+static const u16 bb_ramp_boost[] = {
+	550,			/* max BB gain in 10th of dB */
+	260, 260, 26,		/* BB1, 26dB */
+	290, 550, 29,		/* BB2, 29dB */
+};
+
+static const u16 bb_ramp_pwm_normal[] = {
+	500,			/* max RF gain in 10th of dB */
+	8,			/* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> 0x34 */
+	400,
+	(2 << 9) | 0,		/* 0x35 = 21dB */
+	(0 << 9) | 168,		/* 0x36 */
+	(2 << 9) | 168,		/* 0x37 = 29dB */
+	(0 << 9) | 400,		/* 0x38 */
+};
+
+struct slope {
+	s16 range;
+	s16 slope;
+};
+static u16 slopes_to_scale(const struct slope *slopes, u8 num, s16 val)
+{
+	u8 i;
+	u16 rest;
+	u16 ret = 0;
+	for (i = 0; i < num; i++) {
+		if (val > slopes[i].range)
+			rest = slopes[i].range;
+		else
+			rest = val;
+		ret += (rest * slopes[i].slope) / slopes[i].range;
+		val -= rest;
+	}
+	return ret;
+}
+
+static const struct slope dib0090_wbd_slopes[3] = {
+	{66, 120},		/* -64,-52: offset -   65 */
+	{600, 170},		/* -52,-35: 65     -  665 */
+	{170, 250},		/* -45,-10: 665    - 835 */
+};
+
+static s16 dib0090_wbd_to_db(struct dib0090_state *state, u16 wbd)
+{
+	wbd &= 0x3ff;
+	if (wbd < state->wbd_offset)
+		wbd = 0;
+	else
+		wbd -= state->wbd_offset;
+	/* -64dB is the floor */
+	return -640 + (s16) slopes_to_scale(dib0090_wbd_slopes, ARRAY_SIZE(dib0090_wbd_slopes), wbd);
+}
+
+static void dib0090_wbd_target(struct dib0090_state *state, u32 rf)
+{
+	u16 offset = 250;
+
+	/* TODO : DAB digital N+/-1 interferer perfs : offset = 10 */
+
+	if (state->current_band == BAND_VHF)
+		offset = 650;
+#ifndef FIRMWARE_FIREFLY
+	if (state->current_band == BAND_VHF)
+		offset = state->config->wbd_vhf_offset;
+	if (state->current_band == BAND_CBAND)
+		offset = state->config->wbd_cband_offset;
+#endif
+
+	state->wbd_target = dib0090_wbd_to_db(state, state->wbd_offset + offset);
+	dprintk("wbd-target: %d dB", (u32) state->wbd_target);
+}
+
+static const int gain_reg_addr[4] = {
+	0x08, 0x0a, 0x0f, 0x01
+};
+
+static void dib0090_gain_apply(struct dib0090_state *state, s16 gain_delta, s16 top_delta, u8 force)
+{
+	u16 rf, bb, ref;
+	u16 i, v, gain_reg[4] = { 0 }, gain;
+	const u16 *g;
+
+	if (top_delta < -511)
+		top_delta = -511;
+	if (top_delta > 511)
+		top_delta = 511;
+
+	if (force) {
+		top_delta *= (1 << WBD_ALPHA);
+		gain_delta *= (1 << GAIN_ALPHA);
+	}
+
+	if (top_delta >= ((s16) (state->rf_ramp[0] << WBD_ALPHA) - state->rf_gain_limit))	/* overflow */
+		state->rf_gain_limit = state->rf_ramp[0] << WBD_ALPHA;
+	else
+		state->rf_gain_limit += top_delta;
+
+	if (state->rf_gain_limit < 0)	/*underflow */
+		state->rf_gain_limit = 0;
+
+	/* use gain as a temporary variable and correct current_gain */
+	gain = ((state->rf_gain_limit >> WBD_ALPHA) + state->bb_ramp[0]) << GAIN_ALPHA;
+	if (gain_delta >= ((s16) gain - state->current_gain))	/* overflow */
+		state->current_gain = gain;
+	else
+		state->current_gain += gain_delta;
+	/* cannot be less than 0 (only if gain_delta is less than 0 we can have current_gain < 0) */
+	if (state->current_gain < 0)
+		state->current_gain = 0;
+
+	/* now split total gain to rf and bb gain */
+	gain = state->current_gain >> GAIN_ALPHA;
+
+	/* requested gain is bigger than rf gain limit - ACI/WBD adjustment */
+	if (gain > (state->rf_gain_limit >> WBD_ALPHA)) {
+		rf = state->rf_gain_limit >> WBD_ALPHA;
+		bb = gain - rf;
+		if (bb > state->bb_ramp[0])
+			bb = state->bb_ramp[0];
+	} else {		/* high signal level -> all gains put on RF */
+		rf = gain;
+		bb = 0;
+	}
+
+	state->gain[0] = rf;
+	state->gain[1] = bb;
+
+	/* software ramp */
+	/* Start with RF gains */
+	g = state->rf_ramp + 1;	/* point on RF LNA1 max gain */
+	ref = rf;
+	for (i = 0; i < 7; i++) {	/* Go over all amplifiers => 5RF amps + 2 BB amps = 7 amps */
+		if (g[0] == 0 || ref < (g[1] - g[0]))	/* if total gain of the current amp is null or this amp is not concerned because it starts to work from an higher gain value */
+			v = 0;	/* force the gain to write for the current amp to be null */
+		else if (ref >= g[1])	/* Gain to set is higher than the high working point of this amp */
+			v = g[2];	/* force this amp to be full gain */
+		else		/* compute the value to set to this amp because we are somewhere in his range */
+			v = ((ref - (g[1] - g[0])) * g[2]) / g[0];
+
+		if (i == 0)	/* LNA 1 reg mapping */
+			gain_reg[0] = v;
+		else if (i == 1)	/* LNA 2 reg mapping */
+			gain_reg[0] |= v << 7;
+		else if (i == 2)	/* LNA 3 reg mapping */
+			gain_reg[1] = v;
+		else if (i == 3)	/* LNA 4 reg mapping */
+			gain_reg[1] |= v << 7;
+		else if (i == 4)	/* CBAND LNA reg mapping */
+			gain_reg[2] = v | state->rf_lt_def;
+		else if (i == 5)	/* BB gain 1 reg mapping */
+			gain_reg[3] = v << 3;
+		else if (i == 6)	/* BB gain 2 reg mapping */
+			gain_reg[3] |= v << 8;
+
+		g += 3;		/* go to next gain bloc */
+
+		/* When RF is finished, start with BB */
+		if (i == 4) {
+			g = state->bb_ramp + 1;	/* point on BB gain 1 max gain */
+			ref = bb;
+		}
+	}
+	gain_reg[3] |= state->bb_1_def;
+	gain_reg[3] |= ((bb % 10) * 100) / 125;
+
+#ifdef DEBUG_AGC
+	dprintk("GA CALC: DB: %3d(rf) + %3d(bb) = %3d gain_reg[0]=%04x gain_reg[1]=%04x gain_reg[2]=%04x gain_reg[0]=%04x", rf, bb, rf + bb,
+		gain_reg[0], gain_reg[1], gain_reg[2], gain_reg[3]);
+#endif
+
+	/* Write the amplifier regs */
+	for (i = 0; i < 4; i++) {
+		v = gain_reg[i];
+		if (force || state->gain_reg[i] != v) {
+			state->gain_reg[i] = v;
+			dib0090_write_reg(state, gain_reg_addr[i], v);
+		}
+	}
+}
+
+static void dib0090_set_boost(struct dib0090_state *state, int onoff)
+{
+	state->bb_1_def &= 0xdfff;
+	state->bb_1_def |= onoff << 13;
+}
+
+static void dib0090_set_rframp(struct dib0090_state *state, const u16 * cfg)
+{
+	state->rf_ramp = cfg;
+}
+
+static void dib0090_set_rframp_pwm(struct dib0090_state *state, const u16 * cfg)
+{
+	state->rf_ramp = cfg;
+
+	dib0090_write_reg(state, 0x2a, 0xffff);
+
+	dprintk("total RF gain: %ddB, step: %d", (u32) cfg[0], dib0090_read_reg(state, 0x2a));
+
+	dib0090_write_regs(state, 0x2c, cfg + 3, 6);
+	dib0090_write_regs(state, 0x3e, cfg + 9, 2);
+}
+
+static void dib0090_set_bbramp(struct dib0090_state *state, const u16 * cfg)
+{
+	state->bb_ramp = cfg;
+	dib0090_set_boost(state, cfg[0] > 500);	/* we want the boost if the gain is higher that 50dB */
+}
+
+static void dib0090_set_bbramp_pwm(struct dib0090_state *state, const u16 * cfg)
+{
+	state->bb_ramp = cfg;
+
+	dib0090_set_boost(state, cfg[0] > 500);	/* we want the boost if the gain is higher that 50dB */
+
+	dib0090_write_reg(state, 0x33, 0xffff);
+	dprintk("total BB gain: %ddB, step: %d", (u32) cfg[0], dib0090_read_reg(state, 0x33));
+	dib0090_write_regs(state, 0x35, cfg + 3, 4);
+}
+
+void dib0090_pwm_gain_reset(struct dvb_frontend *fe)
+{
+	struct dib0090_state *state = fe->tuner_priv;
+	/* reset the AGC */
+
+	if (state->config->use_pwm_agc) {
+#ifdef CONFIG_BAND_SBAND
+		if (state->current_band == BAND_SBAND) {
+			dib0090_set_rframp_pwm(state, rf_ramp_pwm_sband);
+			dib0090_set_bbramp_pwm(state, bb_ramp_pwm_boost);
+		} else
+#endif
+#ifdef CONFIG_BAND_CBAND
+		if (state->current_band == BAND_CBAND) {
+			if (state->identity.in_soc) {
+				dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal_socs);
+				if (state->identity.version == SOC_8090_P1G_11R1 || state->identity.version == SOC_8090_P1G_21R1)
+					dib0090_set_rframp_pwm(state, rf_ramp_pwm_cband_8090);
+				else if (state->identity.version == SOC_7090_P1G_11R1
+						|| state->identity.version == SOC_7090_P1G_21R1) {
+					if (state->config->is_dib7090e) {
+						if (state->rf_ramp == NULL)
+							dib0090_set_rframp_pwm(state, rf_ramp_pwm_cband_7090e_sensitivity);
+						else
+							dib0090_set_rframp_pwm(state, state->rf_ramp);
+					} else
+						dib0090_set_rframp_pwm(state, rf_ramp_pwm_cband_7090);
+				}
+			} else {
+				dib0090_set_rframp_pwm(state, rf_ramp_pwm_cband);
+				dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal);
+			}
+		} else
+#endif
+#ifdef CONFIG_BAND_VHF
+		if (state->current_band == BAND_VHF) {
+			if (state->identity.in_soc) {
+				dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal_socs);
+			} else {
+				dib0090_set_rframp_pwm(state, rf_ramp_pwm_vhf);
+				dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal);
+			}
+		} else
+#endif
+		{
+			if (state->identity.in_soc) {
+				if (state->identity.version == SOC_8090_P1G_11R1 || state->identity.version == SOC_8090_P1G_21R1)
+					dib0090_set_rframp_pwm(state, rf_ramp_pwm_uhf_8090);
+				else if (state->identity.version == SOC_7090_P1G_11R1 || state->identity.version == SOC_7090_P1G_21R1)
+					dib0090_set_rframp_pwm(state, rf_ramp_pwm_uhf_7090);
+				dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal_socs);
+			} else {
+				dib0090_set_rframp_pwm(state, rf_ramp_pwm_uhf);
+				dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal);
+			}
+		}
+
+		if (state->rf_ramp[0] != 0)
+			dib0090_write_reg(state, 0x32, (3 << 11));
+		else
+			dib0090_write_reg(state, 0x32, (0 << 11));
+
+		dib0090_write_reg(state, 0x04, 0x03);
+		dib0090_write_reg(state, 0x39, (1 << 10));
+	}
+}
+
+EXPORT_SYMBOL(dib0090_pwm_gain_reset);
+
+void dib0090_set_dc_servo(struct dvb_frontend *fe, u8 DC_servo_cutoff)
+{
+	struct dib0090_state *state = fe->tuner_priv;
+	if (DC_servo_cutoff < 4)
+		dib0090_write_reg(state, 0x04, DC_servo_cutoff);
+}
+EXPORT_SYMBOL(dib0090_set_dc_servo);
+
+static u32 dib0090_get_slow_adc_val(struct dib0090_state *state)
+{
+	u16 adc_val = dib0090_read_reg(state, 0x1d);
+	if (state->identity.in_soc)
+		adc_val >>= 2;
+	return adc_val;
+}
+
+int dib0090_gain_control(struct dvb_frontend *fe)
+{
+	struct dib0090_state *state = fe->tuner_priv;
+	enum frontend_tune_state *tune_state = &state->tune_state;
+	int ret = 10;
+
+	u16 wbd_val = 0;
+	u8 apply_gain_immediatly = 1;
+	s16 wbd_error = 0, adc_error = 0;
+
+	if (*tune_state == CT_AGC_START) {
+		state->agc_freeze = 0;
+		dib0090_write_reg(state, 0x04, 0x0);
+
+#ifdef CONFIG_BAND_SBAND
+		if (state->current_band == BAND_SBAND) {
+			dib0090_set_rframp(state, rf_ramp_sband);
+			dib0090_set_bbramp(state, bb_ramp_boost);
+		} else
+#endif
+#ifdef CONFIG_BAND_VHF
+		if (state->current_band == BAND_VHF && !state->identity.p1g) {
+			dib0090_set_rframp(state, rf_ramp_vhf);
+			dib0090_set_bbramp(state, bb_ramp_boost);
+		} else
+#endif
+#ifdef CONFIG_BAND_CBAND
+		if (state->current_band == BAND_CBAND && !state->identity.p1g) {
+			dib0090_set_rframp(state, rf_ramp_cband);
+			dib0090_set_bbramp(state, bb_ramp_boost);
+		} else
+#endif
+		if ((state->current_band == BAND_CBAND || state->current_band == BAND_VHF) && state->identity.p1g) {
+			dib0090_set_rframp(state, rf_ramp_cband_broadmatching);
+			dib0090_set_bbramp(state, bb_ramp_boost);
+		} else {
+			dib0090_set_rframp(state, rf_ramp_uhf);
+			dib0090_set_bbramp(state, bb_ramp_boost);
+		}
+
+		dib0090_write_reg(state, 0x32, 0);
+		dib0090_write_reg(state, 0x39, 0);
+
+		dib0090_wbd_target(state, state->current_rf);
+
+		state->rf_gain_limit = state->rf_ramp[0] << WBD_ALPHA;
+		state->current_gain = ((state->rf_ramp[0] + state->bb_ramp[0]) / 2) << GAIN_ALPHA;
+
+		*tune_state = CT_AGC_STEP_0;
+	} else if (!state->agc_freeze) {
+		s16 wbd = 0, i, cnt;
+
+		int adc;
+		wbd_val = dib0090_get_slow_adc_val(state);
+
+		if (*tune_state == CT_AGC_STEP_0)
+			cnt = 5;
+		else
+			cnt = 1;
+
+		for (i = 0; i < cnt; i++) {
+			wbd_val = dib0090_get_slow_adc_val(state);
+			wbd += dib0090_wbd_to_db(state, wbd_val);
+		}
+		wbd /= cnt;
+		wbd_error = state->wbd_target - wbd;
+
+		if (*tune_state == CT_AGC_STEP_0) {
+			if (wbd_error < 0 && state->rf_gain_limit > 0 && !state->identity.p1g) {
+#ifdef CONFIG_BAND_CBAND
+				/* in case of CBAND tune reduce first the lt_gain2 before adjusting the RF gain */
+				u8 ltg2 = (state->rf_lt_def >> 10) & 0x7;
+				if (state->current_band == BAND_CBAND && ltg2) {
+					ltg2 >>= 1;
+					state->rf_lt_def &= ltg2 << 10;	/* reduce in 3 steps from 7 to 0 */
+				}
+#endif
+			} else {
+				state->agc_step = 0;
+				*tune_state = CT_AGC_STEP_1;
+			}
+		} else {
+			/* calc the adc power */
+			adc = state->config->get_adc_power(fe);
+			adc = (adc * ((s32) 355774) + (((s32) 1) << 20)) >> 21;	/* included in [0:-700] */
+
+			adc_error = (s16) (((s32) ADC_TARGET) - adc);
+#ifdef CONFIG_STANDARD_DAB
+			if (state->fe->dtv_property_cache.delivery_system == STANDARD_DAB)
+				adc_error -= 10;
+#endif
+#ifdef CONFIG_STANDARD_DVBT
+			if (state->fe->dtv_property_cache.delivery_system == STANDARD_DVBT &&
+					(state->fe->dtv_property_cache.modulation == QAM_64 || state->fe->dtv_property_cache.modulation == QAM_16))
+				adc_error += 60;
+#endif
+#ifdef CONFIG_SYS_ISDBT
+			if ((state->fe->dtv_property_cache.delivery_system == SYS_ISDBT) && (((state->fe->dtv_property_cache.layer[0].segment_count >
+								0)
+							&&
+							((state->fe->dtv_property_cache.layer[0].modulation ==
+							  QAM_64)
+							 || (state->fe->dtv_property_cache.
+								 layer[0].modulation == QAM_16)))
+						||
+						((state->fe->dtv_property_cache.layer[1].segment_count >
+						  0)
+						 &&
+						 ((state->fe->dtv_property_cache.layer[1].modulation ==
+						   QAM_64)
+						  || (state->fe->dtv_property_cache.
+							  layer[1].modulation == QAM_16)))
+						||
+						((state->fe->dtv_property_cache.layer[2].segment_count >
+						  0)
+						 &&
+						 ((state->fe->dtv_property_cache.layer[2].modulation ==
+						   QAM_64)
+						  || (state->fe->dtv_property_cache.
+							  layer[2].modulation == QAM_16)))
+						)
+				)
+				adc_error += 60;
+#endif
+
+			if (*tune_state == CT_AGC_STEP_1) {	/* quickly go to the correct range of the ADC power */
+				if (ABS(adc_error) < 50 || state->agc_step++ > 5) {
+
+#ifdef CONFIG_STANDARD_DAB
+					if (state->fe->dtv_property_cache.delivery_system == STANDARD_DAB) {
+						dib0090_write_reg(state, 0x02, (1 << 15) | (15 << 11) | (31 << 6) | (63));	/* cap value = 63 : narrow BB filter : Fc = 1.8MHz */
+						dib0090_write_reg(state, 0x04, 0x0);
+					} else
+#endif
+					{
+						dib0090_write_reg(state, 0x02, (1 << 15) | (3 << 11) | (6 << 6) | (32));
+						dib0090_write_reg(state, 0x04, 0x01);	/*0 = 1KHz ; 1 = 150Hz ; 2 = 50Hz ; 3 = 50KHz ; 4 = servo fast */
+					}
+
+					*tune_state = CT_AGC_STOP;
+				}
+			} else {
+				/* everything higher than or equal to CT_AGC_STOP means tracking */
+				ret = 100;	/* 10ms interval */
+				apply_gain_immediatly = 0;
+			}
+		}
+#ifdef DEBUG_AGC
+		dprintk
+			("tune state %d, ADC = %3ddB (ADC err %3d) WBD %3ddB (WBD err %3d, WBD val SADC: %4d), RFGainLimit (TOP): %3d, signal: %3ddBm",
+			 (u32) *tune_state, (u32) adc, (u32) adc_error, (u32) wbd, (u32) wbd_error, (u32) wbd_val,
+			 (u32) state->rf_gain_limit >> WBD_ALPHA, (s32) 200 + adc - (state->current_gain >> GAIN_ALPHA));
+#endif
+	}
+
+	/* apply gain */
+	if (!state->agc_freeze)
+		dib0090_gain_apply(state, adc_error, wbd_error, apply_gain_immediatly);
+	return ret;
+}
+
+EXPORT_SYMBOL(dib0090_gain_control);
+
+void dib0090_get_current_gain(struct dvb_frontend *fe, u16 * rf, u16 * bb, u16 * rf_gain_limit, u16 * rflt)
+{
+	struct dib0090_state *state = fe->tuner_priv;
+	if (rf)
+		*rf = state->gain[0];
+	if (bb)
+		*bb = state->gain[1];
+	if (rf_gain_limit)
+		*rf_gain_limit = state->rf_gain_limit;
+	if (rflt)
+		*rflt = (state->rf_lt_def >> 10) & 0x7;
+}
+
+EXPORT_SYMBOL(dib0090_get_current_gain);
+
+u16 dib0090_get_wbd_target(struct dvb_frontend *fe)
+{
+	struct dib0090_state *state = fe->tuner_priv;
+	u32 f_MHz = state->fe->dtv_property_cache.frequency / 1000000;
+	s32 current_temp = state->temperature;
+	s32 wbd_thot, wbd_tcold;
+	const struct dib0090_wbd_slope *wbd = state->current_wbd_table;
+
+	while (f_MHz > wbd->max_freq)
+		wbd++;
+
+	dprintk("using wbd-table-entry with max freq %d", wbd->max_freq);
+
+	if (current_temp < 0)
+		current_temp = 0;
+	if (current_temp > 128)
+		current_temp = 128;
+
+	state->wbdmux &= ~(7 << 13);
+	if (wbd->wbd_gain != 0)
+		state->wbdmux |= (wbd->wbd_gain << 13);
+	else
+		state->wbdmux |= (4 << 13);
+
+	dib0090_write_reg(state, 0x10, state->wbdmux);
+
+	wbd_thot = wbd->offset_hot - (((u32) wbd->slope_hot * f_MHz) >> 6);
+	wbd_tcold = wbd->offset_cold - (((u32) wbd->slope_cold * f_MHz) >> 6);
+
+	wbd_tcold += ((wbd_thot - wbd_tcold) * current_temp) >> 7;
+
+	state->wbd_target = dib0090_wbd_to_db(state, state->wbd_offset + wbd_tcold);
+	dprintk("wbd-target: %d dB", (u32) state->wbd_target);
+	dprintk("wbd offset applied is %d", wbd_tcold);
+
+	return state->wbd_offset + wbd_tcold;
+}
+EXPORT_SYMBOL(dib0090_get_wbd_target);
+
+u16 dib0090_get_wbd_offset(struct dvb_frontend *fe)
+{
+	struct dib0090_state *state = fe->tuner_priv;
+	return state->wbd_offset;
+}
+EXPORT_SYMBOL(dib0090_get_wbd_offset);
+
+int dib0090_set_switch(struct dvb_frontend *fe, u8 sw1, u8 sw2, u8 sw3)
+{
+	struct dib0090_state *state = fe->tuner_priv;
+
+	dib0090_write_reg(state, 0x0b, (dib0090_read_reg(state, 0x0b) & 0xfff8)
+			| ((sw3 & 1) << 2) | ((sw2 & 1) << 1) | (sw1 & 1));
+
+	return 0;
+}
+EXPORT_SYMBOL(dib0090_set_switch);
+
+int dib0090_set_vga(struct dvb_frontend *fe, u8 onoff)
+{
+	struct dib0090_state *state = fe->tuner_priv;
+
+	dib0090_write_reg(state, 0x09, (dib0090_read_reg(state, 0x09) & 0x7fff)
+			| ((onoff & 1) << 15));
+	return 0;
+}
+EXPORT_SYMBOL(dib0090_set_vga);
+
+int dib0090_update_rframp_7090(struct dvb_frontend *fe, u8 cfg_sensitivity)
+{
+	struct dib0090_state *state = fe->tuner_priv;
+
+	if ((!state->identity.p1g) || (!state->identity.in_soc)
+			|| ((state->identity.version != SOC_7090_P1G_21R1)
+				&& (state->identity.version != SOC_7090_P1G_11R1))) {
+		dprintk("%s() function can only be used for dib7090P", __func__);
+		return -ENODEV;
+	}
+
+	if (cfg_sensitivity)
+		state->rf_ramp = (const u16 *)&rf_ramp_pwm_cband_7090e_sensitivity;
+	else
+		state->rf_ramp = (const u16 *)&rf_ramp_pwm_cband_7090e_aci;
+	dib0090_pwm_gain_reset(fe);
+
+	return 0;
+}
+EXPORT_SYMBOL(dib0090_update_rframp_7090);
+
+static const u16 dib0090_defaults[] = {
+
+	25, 0x01,
+	0x0000,
+	0x99a0,
+	0x6008,
+	0x0000,
+	0x8bcb,
+	0x0000,
+	0x0405,
+	0x0000,
+	0x0000,
+	0x0000,
+	0xb802,
+	0x0300,
+	0x2d12,
+	0xbac0,
+	0x7c00,
+	0xdbb9,
+	0x0954,
+	0x0743,
+	0x8000,
+	0x0001,
+	0x0040,
+	0x0100,
+	0x0000,
+	0xe910,
+	0x149e,
+
+	1, 0x1c,
+	0xff2d,
+
+	1, 0x39,
+	0x0000,
+
+	2, 0x1e,
+	0x07FF,
+	0x0007,
+
+	1, 0x24,
+	EN_UHF | EN_CRYSTAL,
+
+	2, 0x3c,
+	0x3ff,
+	0x111,
+	0
+};
+
+static const u16 dib0090_p1g_additionnal_defaults[] = {
+	1, 0x05,
+	0xabcd,
+
+	1, 0x11,
+	0x00b4,
+
+	1, 0x1c,
+	0xfffd,
+
+	1, 0x40,
+	0x108,
+	0
+};
+
+static void dib0090_set_default_config(struct dib0090_state *state, const u16 * n)
+{
+	u16 l, r;
+
+	l = pgm_read_word(n++);
+	while (l) {
+		r = pgm_read_word(n++);
+		do {
+			dib0090_write_reg(state, r, pgm_read_word(n++));
+			r++;
+		} while (--l);
+		l = pgm_read_word(n++);
+	}
+}
+
+#define CAP_VALUE_MIN (u8)  9
+#define CAP_VALUE_MAX (u8) 40
+#define HR_MIN	      (u8) 25
+#define HR_MAX	      (u8) 40
+#define POLY_MIN      (u8)  0
+#define POLY_MAX      (u8)  8
+
+static void dib0090_set_EFUSE(struct dib0090_state *state)
+{
+	u8 c, h, n;
+	u16 e2, e4;
+	u16 cal;
+
+	e2 = dib0090_read_reg(state, 0x26);
+	e4 = dib0090_read_reg(state, 0x28);
+
+	if ((state->identity.version == P1D_E_F) ||
+			(state->identity.version == P1G) || (e2 == 0xffff)) {
+
+		dib0090_write_reg(state, 0x22, 0x10);
+		cal = (dib0090_read_reg(state, 0x22) >> 6) & 0x3ff;
+
+		if ((cal < 670) || (cal == 1023))
+			cal = 850;
+		n = 165 - ((cal * 10)>>6) ;
+		e2 = e4 = (3<<12) | (34<<6) | (n);
+	}
+
+	if (e2 != e4)
+		e2 &= e4; /* Remove the redundancy  */
+
+	if (e2 != 0xffff) {
+		c = e2 & 0x3f;
+		n = (e2 >> 12) & 0xf;
+		h = (e2 >> 6) & 0x3f;
+
+		if ((c >= CAP_VALUE_MAX) || (c <= CAP_VALUE_MIN))
+			c = 32;
+		if ((h >= HR_MAX) || (h <= HR_MIN))
+			h = 34;
+		if ((n >= POLY_MAX) || (n <= POLY_MIN))
+			n = 3;
+
+		dib0090_write_reg(state, 0x13, (h << 10)) ;
+		e2 = (n<<11) | ((h>>2)<<6) | (c);
+		dib0090_write_reg(state, 0x2, e2) ; /* Load the BB_2 */
+	}
+}
+
+static int dib0090_reset(struct dvb_frontend *fe)
+{
+	struct dib0090_state *state = fe->tuner_priv;
+
+	dib0090_reset_digital(fe, state->config);
+	if (dib0090_identify(fe) < 0)
+		return -EIO;
+
+#ifdef CONFIG_TUNER_DIB0090_P1B_SUPPORT
+	if (!(state->identity.version & 0x1))	/* it is P1B - reset is already done */
+		return 0;
+#endif
+
+	if (!state->identity.in_soc) {
+		if ((dib0090_read_reg(state, 0x1a) >> 5) & 0x2)
+			dib0090_write_reg(state, 0x1b, (EN_IQADC | EN_BB | EN_BIAS | EN_DIGCLK | EN_PLL | EN_CRYSTAL));
+		else
+			dib0090_write_reg(state, 0x1b, (EN_DIGCLK | EN_PLL | EN_CRYSTAL));
+	}
+
+	dib0090_set_default_config(state, dib0090_defaults);
+
+	if (state->identity.in_soc)
+		dib0090_write_reg(state, 0x18, 0x2910);  /* charge pump current = 0 */
+
+	if (state->identity.p1g)
+		dib0090_set_default_config(state, dib0090_p1g_additionnal_defaults);
+
+	/* Update the efuse : Only available for KROSUS > P1C  and SOC as well*/
+	if (((state->identity.version & 0x1f) >= P1D_E_F) || (state->identity.in_soc))
+		dib0090_set_EFUSE(state);
+
+	/* Congigure in function of the crystal */
+	if (state->config->force_crystal_mode != 0)
+		dib0090_write_reg(state, 0x14,
+				state->config->force_crystal_mode & 3);
+	else if (state->config->io.clock_khz >= 24000)
+		dib0090_write_reg(state, 0x14, 1);
+	else
+		dib0090_write_reg(state, 0x14, 2);
+	dprintk("Pll lock : %d", (dib0090_read_reg(state, 0x1a) >> 11) & 0x1);
+
+	state->calibrate = DC_CAL | WBD_CAL | TEMP_CAL;	/* enable iq-offset-calibration and wbd-calibration when tuning next time */
+
+	return 0;
+}
+
+#define steps(u) (((u) > 15) ? ((u)-16) : (u))
+#define INTERN_WAIT 10
+static int dib0090_get_offset(struct dib0090_state *state, enum frontend_tune_state *tune_state)
+{
+	int ret = INTERN_WAIT * 10;
+
+	switch (*tune_state) {
+	case CT_TUNER_STEP_2:
+		/* Turns to positive */
+		dib0090_write_reg(state, 0x1f, 0x7);
+		*tune_state = CT_TUNER_STEP_3;
+		break;
+
+	case CT_TUNER_STEP_3:
+		state->adc_diff = dib0090_read_reg(state, 0x1d);
+
+		/* Turns to negative */
+		dib0090_write_reg(state, 0x1f, 0x4);
+		*tune_state = CT_TUNER_STEP_4;
+		break;
+
+	case CT_TUNER_STEP_4:
+		state->adc_diff -= dib0090_read_reg(state, 0x1d);
+		*tune_state = CT_TUNER_STEP_5;
+		ret = 0;
+		break;
+
+	default:
+		break;
+	}
+
+	return ret;
+}
+
+struct dc_calibration {
+	u8 addr;
+	u8 offset;
+	u8 pga:1;
+	u16 bb1;
+	u8 i:1;
+};
+
+static const struct dc_calibration dc_table[] = {
+	/* Step1 BB gain1= 26 with boost 1, gain 2 = 0 */
+	{0x06, 5, 1, (1 << 13) | (0 << 8) | (26 << 3), 1},
+	{0x07, 11, 1, (1 << 13) | (0 << 8) | (26 << 3), 0},
+	/* Step 2 BB gain 1 = 26 with boost = 1 & gain 2 = 29 */
+	{0x06, 0, 0, (1 << 13) | (29 << 8) | (26 << 3), 1},
+	{0x06, 10, 0, (1 << 13) | (29 << 8) | (26 << 3), 0},
+	{0},
+};
+
+static const struct dc_calibration dc_p1g_table[] = {
+	/* Step1 BB gain1= 26 with boost 1, gain 2 = 0 */
+	/* addr ; trim reg offset ; pga ; CTRL_BB1 value ; i or q */
+	{0x06, 5, 1, (1 << 13) | (0 << 8) | (15 << 3), 1},
+	{0x07, 11, 1, (1 << 13) | (0 << 8) | (15 << 3), 0},
+	/* Step 2 BB gain 1 = 26 with boost = 1 & gain 2 = 29 */
+	{0x06, 0, 0, (1 << 13) | (29 << 8) | (15 << 3), 1},
+	{0x06, 10, 0, (1 << 13) | (29 << 8) | (15 << 3), 0},
+	{0},
+};
+
+static void dib0090_set_trim(struct dib0090_state *state)
+{
+	u16 *val;
+
+	if (state->dc->addr == 0x07)
+		val = &state->bb7;
+	else
+		val = &state->bb6;
+
+	*val &= ~(0x1f << state->dc->offset);
+	*val |= state->step << state->dc->offset;
+
+	dib0090_write_reg(state, state->dc->addr, *val);
+}
+
+static int dib0090_dc_offset_calibration(struct dib0090_state *state, enum frontend_tune_state *tune_state)
+{
+	int ret = 0;
+	u16 reg;
+
+	switch (*tune_state) {
+	case CT_TUNER_START:
+		dprintk("Start DC offset calibration");
+
+		/* force vcm2 = 0.8V */
+		state->bb6 = 0;
+		state->bb7 = 0x040d;
+
+		/* the LNA AND LO are off */
+		reg = dib0090_read_reg(state, 0x24) & 0x0ffb;	/* shutdown lna and lo */
+		dib0090_write_reg(state, 0x24, reg);
+
+		state->wbdmux = dib0090_read_reg(state, 0x10);
+		dib0090_write_reg(state, 0x10, (state->wbdmux & ~(0xff << 3)) | (0x7 << 3) | 0x3);
+		dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) & ~(1 << 14));
+
+		state->dc = dc_table;
+
+		if (state->identity.p1g)
+			state->dc = dc_p1g_table;
+		*tune_state = CT_TUNER_STEP_0;
+
+		/* fall through */
+
+	case CT_TUNER_STEP_0:
+		dprintk("Sart/continue DC calibration for %s path", (state->dc->i == 1) ? "I" : "Q");
+		dib0090_write_reg(state, 0x01, state->dc->bb1);
+		dib0090_write_reg(state, 0x07, state->bb7 | (state->dc->i << 7));
+
+		state->step = 0;
+		state->min_adc_diff = 1023;
+		*tune_state = CT_TUNER_STEP_1;
+		ret = 50;
+		break;
+
+	case CT_TUNER_STEP_1:
+		dib0090_set_trim(state);
+		*tune_state = CT_TUNER_STEP_2;
+		break;
+
+	case CT_TUNER_STEP_2:
+	case CT_TUNER_STEP_3:
+	case CT_TUNER_STEP_4:
+		ret = dib0090_get_offset(state, tune_state);
+		break;
+
+	case CT_TUNER_STEP_5:	/* found an offset */
+		dprintk("adc_diff = %d, current step= %d", (u32) state->adc_diff, state->step);
+		if (state->step == 0 && state->adc_diff < 0) {
+			state->min_adc_diff = -1023;
+			dprintk("Change of sign of the minimum adc diff");
+		}
+
+		dprintk("adc_diff = %d, min_adc_diff = %d current_step = %d", state->adc_diff, state->min_adc_diff, state->step);
+
+		/* first turn for this frequency */
+		if (state->step == 0) {
+			if (state->dc->pga && state->adc_diff < 0)
+				state->step = 0x10;
+			if (state->dc->pga == 0 && state->adc_diff > 0)
+				state->step = 0x10;
+		}
+
+		/* Look for a change of Sign in the Adc_diff.min_adc_diff is used to STORE the setp N-1 */
+		if ((state->adc_diff & 0x8000) == (state->min_adc_diff & 0x8000) && steps(state->step) < 15) {
+			/* stop search when the delta the sign is changing and Steps =15 and Step=0 is force for continuance */
+			state->step++;
+			state->min_adc_diff = state->adc_diff;
+			*tune_state = CT_TUNER_STEP_1;
+		} else {
+			/* the minimum was what we have seen in the step before */
+			if (ABS(state->adc_diff) > ABS(state->min_adc_diff)) {
+				dprintk("Since adc_diff N = %d  > adc_diff step N-1 = %d, Come back one step", state->adc_diff, state->min_adc_diff);
+				state->step--;
+			}
+
+			dib0090_set_trim(state);
+			dprintk("BB Offset Cal, BBreg=%hd,Offset=%hd,Value Set=%hd", state->dc->addr, state->adc_diff, state->step);
+
+			state->dc++;
+			if (state->dc->addr == 0)	/* done */
+				*tune_state = CT_TUNER_STEP_6;
+			else
+				*tune_state = CT_TUNER_STEP_0;
+
+		}
+		break;
+
+	case CT_TUNER_STEP_6:
+		dib0090_write_reg(state, 0x07, state->bb7 & ~0x0008);
+		dib0090_write_reg(state, 0x1f, 0x7);
+		*tune_state = CT_TUNER_START;	/* reset done -> real tuning can now begin */
+		state->calibrate &= ~DC_CAL;
+	default:
+		break;
+	}
+	return ret;
+}
+
+static int dib0090_wbd_calibration(struct dib0090_state *state, enum frontend_tune_state *tune_state)
+{
+	u8 wbd_gain;
+	const struct dib0090_wbd_slope *wbd = state->current_wbd_table;
+
+	switch (*tune_state) {
+	case CT_TUNER_START:
+		while (state->current_rf / 1000 > wbd->max_freq)
+			wbd++;
+		if (wbd->wbd_gain != 0)
+			wbd_gain = wbd->wbd_gain;
+		else {
+			wbd_gain = 4;
+#if defined(CONFIG_BAND_LBAND) || defined(CONFIG_BAND_SBAND)
+			if ((state->current_band == BAND_LBAND) || (state->current_band == BAND_SBAND))
+				wbd_gain = 2;
+#endif
+		}
+
+		if (wbd_gain == state->wbd_calibration_gain) {	/* the WBD calibration has already been done */
+			*tune_state = CT_TUNER_START;
+			state->calibrate &= ~WBD_CAL;
+			return 0;
+		}
+
+		dib0090_write_reg(state, 0x10, 0x1b81 | (1 << 10) | (wbd_gain << 13) | (1 << 3));
+
+		dib0090_write_reg(state, 0x24, ((EN_UHF & 0x0fff) | (1 << 1)));
+		*tune_state = CT_TUNER_STEP_0;
+		state->wbd_calibration_gain = wbd_gain;
+		return 90;	/* wait for the WBDMUX to switch and for the ADC to sample */
+
+	case CT_TUNER_STEP_0:
+		state->wbd_offset = dib0090_get_slow_adc_val(state);
+		dprintk("WBD calibration offset = %d", state->wbd_offset);
+		*tune_state = CT_TUNER_START;	/* reset done -> real tuning can now begin */
+		state->calibrate &= ~WBD_CAL;
+		break;
+
+	default:
+		break;
+	}
+	return 0;
+}
+
+static void dib0090_set_bandwidth(struct dib0090_state *state)
+{
+	u16 tmp;
+
+	if (state->fe->dtv_property_cache.bandwidth_hz / 1000 <= 5000)
+		tmp = (3 << 14);
+	else if (state->fe->dtv_property_cache.bandwidth_hz / 1000 <= 6000)
+		tmp = (2 << 14);
+	else if (state->fe->dtv_property_cache.bandwidth_hz / 1000 <= 7000)
+		tmp = (1 << 14);
+	else
+		tmp = (0 << 14);
+
+	state->bb_1_def &= 0x3fff;
+	state->bb_1_def |= tmp;
+
+	dib0090_write_reg(state, 0x01, state->bb_1_def);	/* be sure that we have the right bb-filter */
+
+	dib0090_write_reg(state, 0x03, 0x6008);	/* = 0x6008 : vcm3_trim = 1 ; filter2_gm1_trim = 8 ; filter2_cutoff_freq = 0 */
+	dib0090_write_reg(state, 0x04, 0x1);	/* 0 = 1KHz ; 1 = 50Hz ; 2 = 150Hz ; 3 = 50KHz ; 4 = servo fast */
+	if (state->identity.in_soc) {
+		dib0090_write_reg(state, 0x05, 0x9bcf); /* attenuator_ibias_tri = 2 ; input_stage_ibias_tr = 1 ; nc = 11 ; ext_gm_trim = 1 ; obuf_ibias_trim = 4 ; filter13_gm2_ibias_t = 15 */
+	} else {
+		dib0090_write_reg(state, 0x02, (5 << 11) | (8 << 6) | (22 & 0x3f));	/* 22 = cap_value */
+		dib0090_write_reg(state, 0x05, 0xabcd);	/* = 0xabcd : attenuator_ibias_tri = 2 ; input_stage_ibias_tr = 2 ; nc = 11 ; ext_gm_trim = 1 ; obuf_ibias_trim = 4 ; filter13_gm2_ibias_t = 13 */
+	}
+}
+
+static const struct dib0090_pll dib0090_pll_table[] = {
+#ifdef CONFIG_BAND_CBAND
+	{56000, 0, 9, 48, 6},
+	{70000, 1, 9, 48, 6},
+	{87000, 0, 8, 32, 4},
+	{105000, 1, 8, 32, 4},
+	{115000, 0, 7, 24, 6},
+	{140000, 1, 7, 24, 6},
+	{170000, 0, 6, 16, 4},
+#endif
+#ifdef CONFIG_BAND_VHF
+	{200000, 1, 6, 16, 4},
+	{230000, 0, 5, 12, 6},
+	{280000, 1, 5, 12, 6},
+	{340000, 0, 4, 8, 4},
+	{380000, 1, 4, 8, 4},
+	{450000, 0, 3, 6, 6},
+#endif
+#ifdef CONFIG_BAND_UHF
+	{580000, 1, 3, 6, 6},
+	{700000, 0, 2, 4, 4},
+	{860000, 1, 2, 4, 4},
+#endif
+#ifdef CONFIG_BAND_LBAND
+	{1800000, 1, 0, 2, 4},
+#endif
+#ifdef CONFIG_BAND_SBAND
+	{2900000, 0, 14, 1, 4},
+#endif
+};
+
+static const struct dib0090_tuning dib0090_tuning_table_fm_vhf_on_cband[] = {
+
+#ifdef CONFIG_BAND_CBAND
+	{184000, 4, 1, 15, 0x280, 0x2912, 0xb94e, EN_CAB},
+	{227000, 4, 3, 15, 0x280, 0x2912, 0xb94e, EN_CAB},
+	{380000, 4, 7, 15, 0x280, 0x2912, 0xb94e, EN_CAB},
+#endif
+#ifdef CONFIG_BAND_UHF
+	{520000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
+	{550000, 2, 2, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
+	{650000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
+	{750000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
+	{850000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
+	{900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
+#endif
+#ifdef CONFIG_BAND_LBAND
+	{1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
+	{1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
+	{1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
+#endif
+#ifdef CONFIG_BAND_SBAND
+	{2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD},
+	{2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD},
+#endif
+};
+
+static const struct dib0090_tuning dib0090_tuning_table[] = {
+
+#ifdef CONFIG_BAND_CBAND
+	{170000, 4, 1, 15, 0x280, 0x2912, 0xb94e, EN_CAB},
+#endif
+#ifdef CONFIG_BAND_VHF
+	{184000, 1, 1, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
+	{227000, 1, 3, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
+	{380000, 1, 7, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
+#endif
+#ifdef CONFIG_BAND_UHF
+	{520000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
+	{550000, 2, 2, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
+	{650000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
+	{750000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
+	{850000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
+	{900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
+#endif
+#ifdef CONFIG_BAND_LBAND
+	{1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
+	{1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
+	{1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
+#endif
+#ifdef CONFIG_BAND_SBAND
+	{2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD},
+	{2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD},
+#endif
+};
+
+static const struct dib0090_tuning dib0090_p1g_tuning_table[] = {
+#ifdef CONFIG_BAND_CBAND
+	{170000, 4, 1, 0x820f, 0x300, 0x2d22, 0x82cb, EN_CAB},
+#endif
+#ifdef CONFIG_BAND_VHF
+	{184000, 1, 1, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
+	{227000, 1, 3, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
+	{380000, 1, 7, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
+#endif
+#ifdef CONFIG_BAND_UHF
+	{510000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
+	{540000, 2, 1, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
+	{600000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
+	{630000, 2, 4, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
+	{680000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
+	{720000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
+	{900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
+#endif
+#ifdef CONFIG_BAND_LBAND
+	{1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
+	{1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
+	{1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
+#endif
+#ifdef CONFIG_BAND_SBAND
+	{2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD},
+	{2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD},
+#endif
+};
+
+static const struct dib0090_pll dib0090_p1g_pll_table[] = {
+#ifdef CONFIG_BAND_CBAND
+	{57000, 0, 11, 48, 6},
+	{70000, 1, 11, 48, 6},
+	{86000, 0, 10, 32, 4},
+	{105000, 1, 10, 32, 4},
+	{115000, 0, 9, 24, 6},
+	{140000, 1, 9, 24, 6},
+	{170000, 0, 8, 16, 4},
+#endif
+#ifdef CONFIG_BAND_VHF
+	{200000, 1, 8, 16, 4},
+	{230000, 0, 7, 12, 6},
+	{280000, 1, 7, 12, 6},
+	{340000, 0, 6, 8, 4},
+	{380000, 1, 6, 8, 4},
+	{455000, 0, 5, 6, 6},
+#endif
+#ifdef CONFIG_BAND_UHF
+	{580000, 1, 5, 6, 6},
+	{680000, 0, 4, 4, 4},
+	{860000, 1, 4, 4, 4},
+#endif
+#ifdef CONFIG_BAND_LBAND
+	{1800000, 1, 2, 2, 4},
+#endif
+#ifdef CONFIG_BAND_SBAND
+	{2900000, 0, 1, 1, 6},
+#endif
+};
+
+static const struct dib0090_tuning dib0090_p1g_tuning_table_fm_vhf_on_cband[] = {
+#ifdef CONFIG_BAND_CBAND
+	{184000, 4, 3, 0x4187, 0x2c0, 0x2d22, 0x81cb, EN_CAB},
+	{227000, 4, 3, 0x4187, 0x2c0, 0x2d22, 0x81cb, EN_CAB},
+	{380000, 4, 3, 0x4187, 0x2c0, 0x2d22, 0x81cb, EN_CAB},
+#endif
+#ifdef CONFIG_BAND_UHF
+	{520000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
+	{550000, 2, 2, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
+	{650000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
+	{750000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
+	{850000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
+	{900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
+#endif
+#ifdef CONFIG_BAND_LBAND
+	{1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
+	{1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
+	{1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
+#endif
+#ifdef CONFIG_BAND_SBAND
+	{2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD},
+	{2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD},
+#endif
+};
+
+static const struct dib0090_tuning dib0090_tuning_table_cband_7090[] = {
+#ifdef CONFIG_BAND_CBAND
+	{300000, 4, 3, 0x018F, 0x2c0, 0x2d22, 0xb9ce, EN_CAB},
+	{380000, 4, 10, 0x018F, 0x2c0, 0x2d22, 0xb9ce, EN_CAB},
+	{570000, 4, 10, 0x8190, 0x2c0, 0x2d22, 0xb9ce, EN_CAB},
+	{858000, 4, 5, 0x8190, 0x2c0, 0x2d22, 0xb9ce, EN_CAB},
+#endif
+};
+
+static const struct dib0090_tuning dib0090_tuning_table_cband_7090e_sensitivity[] = {
+#ifdef CONFIG_BAND_CBAND
+	{ 300000,  0 ,  3,  0x8105, 0x2c0, 0x2d12, 0xb84e, EN_CAB },
+	{ 380000,  0 ,  10, 0x810F, 0x2c0, 0x2d12, 0xb84e, EN_CAB },
+	{ 600000,  0 ,  10, 0x815E, 0x280, 0x2d12, 0xb84e, EN_CAB },
+	{ 660000,  0 ,  5,  0x85E3, 0x280, 0x2d12, 0xb84e, EN_CAB },
+	{ 720000,  0 ,  5,  0x852E, 0x280, 0x2d12, 0xb84e, EN_CAB },
+	{ 860000,  0 ,  4,  0x85E5, 0x280, 0x2d12, 0xb84e, EN_CAB },
+#endif
+};
+
+int dib0090_update_tuning_table_7090(struct dvb_frontend *fe,
+		u8 cfg_sensitivity)
+{
+	struct dib0090_state *state = fe->tuner_priv;
+	const struct dib0090_tuning *tune =
+		dib0090_tuning_table_cband_7090e_sensitivity;
+	const struct dib0090_tuning dib0090_tuning_table_cband_7090e_aci[] = {
+		{ 300000,  0 ,  3,  0x8165, 0x2c0, 0x2d12, 0xb84e, EN_CAB },
+		{ 650000,  0 ,  4,  0x815B, 0x280, 0x2d12, 0xb84e, EN_CAB },
+		{ 860000,  0 ,  5,  0x84EF, 0x280, 0x2d12, 0xb84e, EN_CAB },
+	};
+
+	if ((!state->identity.p1g) || (!state->identity.in_soc)
+			|| ((state->identity.version != SOC_7090_P1G_21R1)
+				&& (state->identity.version != SOC_7090_P1G_11R1))) {
+		dprintk("%s() function can only be used for dib7090", __func__);
+		return -ENODEV;
+	}
+
+	if (cfg_sensitivity)
+		tune = dib0090_tuning_table_cband_7090e_sensitivity;
+	else
+		tune = dib0090_tuning_table_cband_7090e_aci;
+
+	while (state->rf_request > tune->max_freq)
+		tune++;
+
+	dib0090_write_reg(state, 0x09, (dib0090_read_reg(state, 0x09) & 0x8000)
+			| (tune->lna_bias & 0x7fff));
+	dib0090_write_reg(state, 0x0b, (dib0090_read_reg(state, 0x0b) & 0xf83f)
+			| ((tune->lna_tune << 6) & 0x07c0));
+	return 0;
+}
+EXPORT_SYMBOL(dib0090_update_tuning_table_7090);
+
+static int dib0090_captrim_search(struct dib0090_state *state, enum frontend_tune_state *tune_state)
+{
+	int ret = 0;
+	u16 lo4 = 0xe900;
+
+	s16 adc_target;
+	u16 adc;
+	s8 step_sign;
+	u8 force_soft_search = 0;
+
+	if (state->identity.version == SOC_8090_P1G_11R1 || state->identity.version == SOC_8090_P1G_21R1)
+		force_soft_search = 1;
+
+	if (*tune_state == CT_TUNER_START) {
+		dprintk("Start Captrim search : %s", (force_soft_search == 1) ? "FORCE SOFT SEARCH" : "AUTO");
+		dib0090_write_reg(state, 0x10, 0x2B1);
+		dib0090_write_reg(state, 0x1e, 0x0032);
+
+		if (!state->tuner_is_tuned) {
+			/* prepare a complete captrim */
+			if (!state->identity.p1g || force_soft_search)
+				state->step = state->captrim = state->fcaptrim = 64;
+
+			state->current_rf = state->rf_request;
+		} else {	/* we are already tuned to this frequency - the configuration is correct  */
+			if (!state->identity.p1g || force_soft_search) {
+				/* do a minimal captrim even if the frequency has not changed */
+				state->step = 4;
+				state->captrim = state->fcaptrim = dib0090_read_reg(state, 0x18) & 0x7f;
+			}
+		}
+		state->adc_diff = 3000;
+		*tune_state = CT_TUNER_STEP_0;
+
+	} else if (*tune_state == CT_TUNER_STEP_0) {
+		if (state->identity.p1g && !force_soft_search) {
+			u8 ratio = 31;
+
+			dib0090_write_reg(state, 0x40, (3 << 7) | (ratio << 2) | (1 << 1) | 1);
+			dib0090_read_reg(state, 0x40);
+			ret = 50;
+		} else {
+			state->step /= 2;
+			dib0090_write_reg(state, 0x18, lo4 | state->captrim);
+
+			if (state->identity.in_soc)
+				ret = 25;
+		}
+		*tune_state = CT_TUNER_STEP_1;
+
+	} else if (*tune_state == CT_TUNER_STEP_1) {
+		if (state->identity.p1g && !force_soft_search) {
+			dib0090_write_reg(state, 0x40, 0x18c | (0 << 1) | 0);
+			dib0090_read_reg(state, 0x40);
+
+			state->fcaptrim = dib0090_read_reg(state, 0x18) & 0x7F;
+			dprintk("***Final Captrim= 0x%x", state->fcaptrim);
+			*tune_state = CT_TUNER_STEP_3;
+
+		} else {
+			/* MERGE for all krosus before P1G */
+			adc = dib0090_get_slow_adc_val(state);
+			dprintk("CAPTRIM=%d; ADC = %d (ADC) & %dmV", (u32) state->captrim, (u32) adc, (u32) (adc) * (u32) 1800 / (u32) 1024);
+
+			if (state->rest == 0 || state->identity.in_soc) {	/* Just for 8090P SOCS where auto captrim HW bug : TO CHECK IN ACI for SOCS !!! if 400 for 8090p SOC => tune issue !!! */
+				adc_target = 200;
+			} else
+				adc_target = 400;
+
+			if (adc >= adc_target) {
+				adc -= adc_target;
+				step_sign = -1;
+			} else {
+				adc = adc_target - adc;
+				step_sign = 1;
+			}
+
+			if (adc < state->adc_diff) {
+				dprintk("CAPTRIM=%d is closer to target (%d/%d)", (u32) state->captrim, (u32) adc, (u32) state->adc_diff);
+				state->adc_diff = adc;
+				state->fcaptrim = state->captrim;
+			}
+
+			state->captrim += step_sign * state->step;
+			if (state->step >= 1)
+				*tune_state = CT_TUNER_STEP_0;
+			else
+				*tune_state = CT_TUNER_STEP_2;
+
+			ret = 25;
+		}
+	} else if (*tune_state == CT_TUNER_STEP_2) {	/* this step is only used by krosus < P1G */
+		/*write the final cptrim config */
+		dib0090_write_reg(state, 0x18, lo4 | state->fcaptrim);
+
+		*tune_state = CT_TUNER_STEP_3;
+
+	} else if (*tune_state == CT_TUNER_STEP_3) {
+		state->calibrate &= ~CAPTRIM_CAL;
+		*tune_state = CT_TUNER_STEP_0;
+	}
+
+	return ret;
+}
+
+static int dib0090_get_temperature(struct dib0090_state *state, enum frontend_tune_state *tune_state)
+{
+	int ret = 15;
+	s16 val;
+
+	switch (*tune_state) {
+	case CT_TUNER_START:
+		state->wbdmux = dib0090_read_reg(state, 0x10);
+		dib0090_write_reg(state, 0x10, (state->wbdmux & ~(0xff << 3)) | (0x8 << 3));
+
+		state->bias = dib0090_read_reg(state, 0x13);
+		dib0090_write_reg(state, 0x13, state->bias | (0x3 << 8));
+
+		*tune_state = CT_TUNER_STEP_0;
+		/* wait for the WBDMUX to switch and for the ADC to sample */
+		break;
+
+	case CT_TUNER_STEP_0:
+		state->adc_diff = dib0090_get_slow_adc_val(state);
+		dib0090_write_reg(state, 0x13, (state->bias & ~(0x3 << 8)) | (0x2 << 8));
+		*tune_state = CT_TUNER_STEP_1;
+		break;
+
+	case CT_TUNER_STEP_1:
+		val = dib0090_get_slow_adc_val(state);
+		state->temperature = ((s16) ((val - state->adc_diff) * 180) >> 8) + 55;
+
+		dprintk("temperature: %d C", state->temperature - 30);
+
+		*tune_state = CT_TUNER_STEP_2;
+		break;
+
+	case CT_TUNER_STEP_2:
+		dib0090_write_reg(state, 0x13, state->bias);
+		dib0090_write_reg(state, 0x10, state->wbdmux);	/* write back original WBDMUX */
+
+		*tune_state = CT_TUNER_START;
+		state->calibrate &= ~TEMP_CAL;
+		if (state->config->analog_output == 0)
+			dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) | (1 << 14));
+
+		break;
+
+	default:
+		ret = 0;
+		break;
+	}
+	return ret;
+}
+
+#define WBD     0x781		/* 1 1 1 1 0000 0 0 1 */
+static int dib0090_tune(struct dvb_frontend *fe)
+{
+	struct dib0090_state *state = fe->tuner_priv;
+	const struct dib0090_tuning *tune = state->current_tune_table_index;
+	const struct dib0090_pll *pll = state->current_pll_table_index;
+	enum frontend_tune_state *tune_state = &state->tune_state;
+
+	u16 lo5, lo6, Den, tmp;
+	u32 FBDiv, Rest, FREF, VCOF_kHz = 0;
+	int ret = 10;		/* 1ms is the default delay most of the time */
+	u8 c, i;
+
+	/************************* VCO ***************************/
+	/* Default values for FG                                 */
+	/* from these are needed :                               */
+	/* Cp,HFdiv,VCOband,SD,Num,Den,FB and REFDiv             */
+
+	/* in any case we first need to do a calibration if needed */
+	if (*tune_state == CT_TUNER_START) {
+		/* deactivate DataTX before some calibrations */
+		if (state->calibrate & (DC_CAL | TEMP_CAL | WBD_CAL))
+			dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) & ~(1 << 14));
+		else
+			/* Activate DataTX in case a calibration has been done before */
+			if (state->config->analog_output == 0)
+				dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) | (1 << 14));
+	}
+
+	if (state->calibrate & DC_CAL)
+		return dib0090_dc_offset_calibration(state, tune_state);
+	else if (state->calibrate & WBD_CAL) {
+		if (state->current_rf == 0)
+			state->current_rf = state->fe->dtv_property_cache.frequency / 1000;
+		return dib0090_wbd_calibration(state, tune_state);
+	} else if (state->calibrate & TEMP_CAL)
+		return dib0090_get_temperature(state, tune_state);
+	else if (state->calibrate & CAPTRIM_CAL)
+		return dib0090_captrim_search(state, tune_state);
+
+	if (*tune_state == CT_TUNER_START) {
+		/* if soc and AGC pwm control, disengage mux to be able to R/W access to 0x01 register to set the right filter (cutoff_freq_select) during the tune sequence, otherwise, SOC SERPAR error when accessing to 0x01 */
+		if (state->config->use_pwm_agc && state->identity.in_soc) {
+			tmp = dib0090_read_reg(state, 0x39);
+			if ((tmp >> 10) & 0x1)
+				dib0090_write_reg(state, 0x39, tmp & ~(1 << 10));
+		}
+
+		state->current_band = (u8) BAND_OF_FREQUENCY(state->fe->dtv_property_cache.frequency / 1000);
+		state->rf_request =
+			state->fe->dtv_property_cache.frequency / 1000 + (state->current_band ==
+					BAND_UHF ? state->config->freq_offset_khz_uhf : state->config->
+					freq_offset_khz_vhf);
+
+		/* in ISDB-T 1seg we shift tuning frequency */
+		if ((state->fe->dtv_property_cache.delivery_system == SYS_ISDBT && state->fe->dtv_property_cache.isdbt_sb_mode == 1
+					&& state->fe->dtv_property_cache.isdbt_partial_reception == 0)) {
+			const struct dib0090_low_if_offset_table *LUT_offset = state->config->low_if;
+			u8 found_offset = 0;
+			u32 margin_khz = 100;
+
+			if (LUT_offset != NULL) {
+				while (LUT_offset->RF_freq != 0xffff) {
+					if (((state->rf_request > (LUT_offset->RF_freq - margin_khz))
+								&& (state->rf_request < (LUT_offset->RF_freq + margin_khz)))
+							&& LUT_offset->std == state->fe->dtv_property_cache.delivery_system) {
+						state->rf_request += LUT_offset->offset_khz;
+						found_offset = 1;
+						break;
+					}
+					LUT_offset++;
+				}
+			}
+
+			if (found_offset == 0)
+				state->rf_request += 400;
+		}
+		if (state->current_rf != state->rf_request || (state->current_standard != state->fe->dtv_property_cache.delivery_system)) {
+			state->tuner_is_tuned = 0;
+			state->current_rf = 0;
+			state->current_standard = 0;
+
+			tune = dib0090_tuning_table;
+			if (state->identity.p1g)
+				tune = dib0090_p1g_tuning_table;
+
+			tmp = (state->identity.version >> 5) & 0x7;
+
+			if (state->identity.in_soc) {
+				if (state->config->force_cband_input) {	/* Use the CBAND input for all band */
+					if (state->current_band & BAND_CBAND || state->current_band & BAND_FM || state->current_band & BAND_VHF
+							|| state->current_band & BAND_UHF) {
+						state->current_band = BAND_CBAND;
+						if (state->config->is_dib7090e)
+							tune = dib0090_tuning_table_cband_7090e_sensitivity;
+						else
+							tune = dib0090_tuning_table_cband_7090;
+					}
+				} else {	/* Use the CBAND input for all band under UHF */
+					if (state->current_band & BAND_CBAND || state->current_band & BAND_FM || state->current_band & BAND_VHF) {
+						state->current_band = BAND_CBAND;
+						if (state->config->is_dib7090e)
+							tune = dib0090_tuning_table_cband_7090e_sensitivity;
+						else
+							tune = dib0090_tuning_table_cband_7090;
+					}
+				}
+			} else
+			 if (tmp == 0x4 || tmp == 0x7) {
+				/* CBAND tuner version for VHF */
+				if (state->current_band == BAND_FM || state->current_band == BAND_CBAND || state->current_band == BAND_VHF) {
+					state->current_band = BAND_CBAND;	/* Force CBAND */
+
+					tune = dib0090_tuning_table_fm_vhf_on_cband;
+					if (state->identity.p1g)
+						tune = dib0090_p1g_tuning_table_fm_vhf_on_cband;
+				}
+			}
+
+			pll = dib0090_pll_table;
+			if (state->identity.p1g)
+				pll = dib0090_p1g_pll_table;
+
+			/* Look for the interval */
+			while (state->rf_request > tune->max_freq)
+				tune++;
+			while (state->rf_request > pll->max_freq)
+				pll++;
+
+			state->current_tune_table_index = tune;
+			state->current_pll_table_index = pll;
+
+			dib0090_write_reg(state, 0x0b, 0xb800 | (tune->switch_trim));
+
+			VCOF_kHz = (pll->hfdiv * state->rf_request) * 2;
+
+			FREF = state->config->io.clock_khz;
+			if (state->config->fref_clock_ratio != 0)
+				FREF /= state->config->fref_clock_ratio;
+
+			FBDiv = (VCOF_kHz / pll->topresc / FREF);
+			Rest = (VCOF_kHz / pll->topresc) - FBDiv * FREF;
+
+			if (Rest < LPF)
+				Rest = 0;
+			else if (Rest < 2 * LPF)
+				Rest = 2 * LPF;
+			else if (Rest > (FREF - LPF)) {
+				Rest = 0;
+				FBDiv += 1;
+			} else if (Rest > (FREF - 2 * LPF))
+				Rest = FREF - 2 * LPF;
+			Rest = (Rest * 6528) / (FREF / 10);
+			state->rest = Rest;
+
+			/* external loop filter, otherwise:
+			 * lo5 = (0 << 15) | (0 << 12) | (0 << 11) | (3 << 9) | (4 << 6) | (3 << 4) | 4;
+			 * lo6 = 0x0e34 */
+
+			if (Rest == 0) {
+				if (pll->vco_band)
+					lo5 = 0x049f;
+				else
+					lo5 = 0x041f;
+			} else {
+				if (pll->vco_band)
+					lo5 = 0x049e;
+				else if (state->config->analog_output)
+					lo5 = 0x041d;
+				else
+					lo5 = 0x041c;
+			}
+
+			if (state->identity.p1g) {	/* Bias is done automatically in P1G */
+				if (state->identity.in_soc) {
+					if (state->identity.version == SOC_8090_P1G_11R1)
+						lo5 = 0x46f;
+					else
+						lo5 = 0x42f;
+				} else
+					lo5 = 0x42c;
+			}
+
+			lo5 |= (pll->hfdiv_code << 11) | (pll->vco_band << 7);	/* bit 15 is the split to the slave, we do not do it here */
+
+			if (!state->config->io.pll_int_loop_filt) {
+				if (state->identity.in_soc)
+					lo6 = 0xff98;
+				else if (state->identity.p1g || (Rest == 0))
+					lo6 = 0xfff8;
+				else
+					lo6 = 0xff28;
+			} else
+				lo6 = (state->config->io.pll_int_loop_filt << 3);
+
+			Den = 1;
+
+			if (Rest > 0) {
+				if (state->config->analog_output)
+					lo6 |= (1 << 2) | 2;
+				else {
+					if (state->identity.in_soc)
+						lo6 |= (1 << 2) | 2;
+					else
+						lo6 |= (1 << 2) | 2;
+				}
+				Den = 255;
+			}
+			dib0090_write_reg(state, 0x15, (u16) FBDiv);
+			if (state->config->fref_clock_ratio != 0)
+				dib0090_write_reg(state, 0x16, (Den << 8) | state->config->fref_clock_ratio);
+			else
+				dib0090_write_reg(state, 0x16, (Den << 8) | 1);
+			dib0090_write_reg(state, 0x17, (u16) Rest);
+			dib0090_write_reg(state, 0x19, lo5);
+			dib0090_write_reg(state, 0x1c, lo6);
+
+			lo6 = tune->tuner_enable;
+			if (state->config->analog_output)
+				lo6 = (lo6 & 0xff9f) | 0x2;
+
+			dib0090_write_reg(state, 0x24, lo6 | EN_LO | state->config->use_pwm_agc * EN_CRYSTAL);
+
+		}
+
+		state->current_rf = state->rf_request;
+		state->current_standard = state->fe->dtv_property_cache.delivery_system;
+
+		ret = 20;
+		state->calibrate = CAPTRIM_CAL;	/* captrim serach now */
+	}
+
+	else if (*tune_state == CT_TUNER_STEP_0) {	/* Warning : because of captrim cal, if you change this step, change it also in _cal.c file because it is the step following captrim cal state machine */
+		const struct dib0090_wbd_slope *wbd = state->current_wbd_table;
+
+		while (state->current_rf / 1000 > wbd->max_freq)
+			wbd++;
+
+		dib0090_write_reg(state, 0x1e, 0x07ff);
+		dprintk("Final Captrim: %d", (u32) state->fcaptrim);
+		dprintk("HFDIV code: %d", (u32) pll->hfdiv_code);
+		dprintk("VCO = %d", (u32) pll->vco_band);
+		dprintk("VCOF in kHz: %d ((%d*%d) << 1))", (u32) ((pll->hfdiv * state->rf_request) * 2), (u32) pll->hfdiv, (u32) state->rf_request);
+		dprintk("REFDIV: %d, FREF: %d", (u32) 1, (u32) state->config->io.clock_khz);
+		dprintk("FBDIV: %d, Rest: %d", (u32) dib0090_read_reg(state, 0x15), (u32) dib0090_read_reg(state, 0x17));
+		dprintk("Num: %d, Den: %d, SD: %d", (u32) dib0090_read_reg(state, 0x17), (u32) (dib0090_read_reg(state, 0x16) >> 8),
+			(u32) dib0090_read_reg(state, 0x1c) & 0x3);
+
+#define WBD     0x781		/* 1 1 1 1 0000 0 0 1 */
+		c = 4;
+		i = 3;
+
+		if (wbd->wbd_gain != 0)
+			c = wbd->wbd_gain;
+
+		state->wbdmux = (c << 13) | (i << 11) | (WBD | (state->config->use_pwm_agc << 1));
+		dib0090_write_reg(state, 0x10, state->wbdmux);
+
+		if ((tune->tuner_enable == EN_CAB) && state->identity.p1g) {
+			dprintk("P1G : The cable band is selected and lna_tune = %d", tune->lna_tune);
+			dib0090_write_reg(state, 0x09, tune->lna_bias);
+			dib0090_write_reg(state, 0x0b, 0xb800 | (tune->lna_tune << 6) | (tune->switch_trim));
+		} else
+			dib0090_write_reg(state, 0x09, (tune->lna_tune << 5) | tune->lna_bias);
+
+		dib0090_write_reg(state, 0x0c, tune->v2i);
+		dib0090_write_reg(state, 0x0d, tune->mix);
+		dib0090_write_reg(state, 0x0e, tune->load);
+		*tune_state = CT_TUNER_STEP_1;
+
+	} else if (*tune_state == CT_TUNER_STEP_1) {
+		/* initialize the lt gain register */
+		state->rf_lt_def = 0x7c00;
+
+		dib0090_set_bandwidth(state);
+		state->tuner_is_tuned = 1;
+
+		state->calibrate |= WBD_CAL;
+		state->calibrate |= TEMP_CAL;
+		*tune_state = CT_TUNER_STOP;
+	} else
+		ret = FE_CALLBACK_TIME_NEVER;
+	return ret;
+}
+
+static int dib0090_release(struct dvb_frontend *fe)
+{
+	kfree(fe->tuner_priv);
+	fe->tuner_priv = NULL;
+	return 0;
+}
+
+enum frontend_tune_state dib0090_get_tune_state(struct dvb_frontend *fe)
+{
+	struct dib0090_state *state = fe->tuner_priv;
+
+	return state->tune_state;
+}
+
+EXPORT_SYMBOL(dib0090_get_tune_state);
+
+int dib0090_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state)
+{
+	struct dib0090_state *state = fe->tuner_priv;
+
+	state->tune_state = tune_state;
+	return 0;
+}
+
+EXPORT_SYMBOL(dib0090_set_tune_state);
+
+static int dib0090_get_frequency(struct dvb_frontend *fe, u32 * frequency)
+{
+	struct dib0090_state *state = fe->tuner_priv;
+
+	*frequency = 1000 * state->current_rf;
+	return 0;
+}
+
+static int dib0090_set_params(struct dvb_frontend *fe)
+{
+	struct dib0090_state *state = fe->tuner_priv;
+	u32 ret;
+
+	state->tune_state = CT_TUNER_START;
+
+	do {
+		ret = dib0090_tune(fe);
+		if (ret != FE_CALLBACK_TIME_NEVER)
+			msleep(ret / 10);
+		else
+			break;
+	} while (state->tune_state != CT_TUNER_STOP);
+
+	return 0;
+}
+
+static const struct dvb_tuner_ops dib0090_ops = {
+	.info = {
+		 .name = "DiBcom DiB0090",
+		 .frequency_min = 45000000,
+		 .frequency_max = 860000000,
+		 .frequency_step = 1000,
+		 },
+	.release = dib0090_release,
+
+	.init = dib0090_wakeup,
+	.sleep = dib0090_sleep,
+	.set_params = dib0090_set_params,
+	.get_frequency = dib0090_get_frequency,
+};
+
+static const struct dvb_tuner_ops dib0090_fw_ops = {
+	.info = {
+		 .name = "DiBcom DiB0090",
+		 .frequency_min = 45000000,
+		 .frequency_max = 860000000,
+		 .frequency_step = 1000,
+		 },
+	.release = dib0090_release,
+
+	.init = NULL,
+	.sleep = NULL,
+	.set_params = NULL,
+	.get_frequency = NULL,
+};
+
+static const struct dib0090_wbd_slope dib0090_wbd_table_default[] = {
+	{470, 0, 250, 0, 100, 4},
+	{860, 51, 866, 21, 375, 4},
+	{1700, 0, 800, 0, 850, 4},
+	{2900, 0, 250, 0, 100, 6},
+	{0xFFFF, 0, 0, 0, 0, 0},
+};
+
+struct dvb_frontend *dib0090_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config)
+{
+	struct dib0090_state *st = kzalloc(sizeof(struct dib0090_state), GFP_KERNEL);
+	if (st == NULL)
+		return NULL;
+
+	st->config = config;
+	st->i2c = i2c;
+	st->fe = fe;
+	mutex_init(&st->i2c_buffer_lock);
+	fe->tuner_priv = st;
+
+	if (config->wbd == NULL)
+		st->current_wbd_table = dib0090_wbd_table_default;
+	else
+		st->current_wbd_table = config->wbd;
+
+	if (dib0090_reset(fe) != 0)
+		goto free_mem;
+
+	printk(KERN_INFO "DiB0090: successfully identified\n");
+	memcpy(&fe->ops.tuner_ops, &dib0090_ops, sizeof(struct dvb_tuner_ops));
+
+	return fe;
+ free_mem:
+	kfree(st);
+	fe->tuner_priv = NULL;
+	return NULL;
+}
+
+EXPORT_SYMBOL(dib0090_register);
+
+struct dvb_frontend *dib0090_fw_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config)
+{
+	struct dib0090_fw_state *st = kzalloc(sizeof(struct dib0090_fw_state), GFP_KERNEL);
+	if (st == NULL)
+		return NULL;
+
+	st->config = config;
+	st->i2c = i2c;
+	st->fe = fe;
+	mutex_init(&st->i2c_buffer_lock);
+	fe->tuner_priv = st;
+
+	if (dib0090_fw_reset_digital(fe, st->config) != 0)
+		goto free_mem;
+
+	dprintk("DiB0090 FW: successfully identified");
+	memcpy(&fe->ops.tuner_ops, &dib0090_fw_ops, sizeof(struct dvb_tuner_ops));
+
+	return fe;
+free_mem:
+	kfree(st);
+	fe->tuner_priv = NULL;
+	return NULL;
+}
+EXPORT_SYMBOL(dib0090_fw_register);
+
+MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
+MODULE_AUTHOR("Olivier Grenie <olivier.grenie@dibcom.fr>");
+MODULE_DESCRIPTION("Driver for the DiBcom 0090 base-band RF Tuner");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb-frontends/dib0090.h b/drivers/media/dvb-frontends/dib0090.h
new file mode 100644
index 0000000..781dc49
--- /dev/null
+++ b/drivers/media/dvb-frontends/dib0090.h
@@ -0,0 +1,187 @@
+/*
+ * Linux-DVB Driver for DiBcom's DiB0090 base-band RF Tuner.
+ *
+ * Copyright (C) 2005-7 DiBcom (http://www.dibcom.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, version 2.
+ */
+#ifndef DIB0090_H
+#define DIB0090_H
+
+struct dvb_frontend;
+struct i2c_adapter;
+
+#define DEFAULT_DIB0090_I2C_ADDRESS 0x60
+
+struct dib0090_io_config {
+	u32 clock_khz;
+
+	u8 pll_bypass:1;
+	u8 pll_range:1;
+	u8 pll_prediv:6;
+	u8 pll_loopdiv:6;
+
+	u8 adc_clock_ratio;	/* valid is 8, 7 ,6 */
+	u16 pll_int_loop_filt;
+};
+
+struct dib0090_wbd_slope {
+	u16 max_freq;		/* for every frequency less than or equal to that field: this information is correct */
+	u16 slope_cold;
+	u16 offset_cold;
+	u16 slope_hot;
+	u16 offset_hot;
+	u8 wbd_gain;
+};
+
+struct dib0090_low_if_offset_table {
+	int std;
+	u32 RF_freq;
+	s32 offset_khz;
+};
+
+struct dib0090_config {
+	struct dib0090_io_config io;
+	int (*reset) (struct dvb_frontend *, int);
+	int (*sleep) (struct dvb_frontend *, int);
+
+	/*  offset in kHz */
+	int freq_offset_khz_uhf;
+	int freq_offset_khz_vhf;
+
+	int (*get_adc_power) (struct dvb_frontend *);
+
+	u8 clkouttobamse:1;	/* activate or deactivate clock output */
+	u8 analog_output;
+
+	u8 i2c_address;
+	/* add drives and other things if necessary */
+	u16 wbd_vhf_offset;
+	u16 wbd_cband_offset;
+	u8 use_pwm_agc;
+	u8 clkoutdrive;
+
+	u8 ls_cfg_pad_drv;
+	u8 data_tx_drv;
+
+	u8 in_soc;
+	const struct dib0090_low_if_offset_table *low_if;
+	u8 fref_clock_ratio;
+	u16 force_cband_input;
+	struct dib0090_wbd_slope *wbd;
+	u8 is_dib7090e;
+	u8 force_crystal_mode;
+};
+
+#if defined(CONFIG_DVB_TUNER_DIB0090) || (defined(CONFIG_DVB_TUNER_DIB0090_MODULE) && defined(MODULE))
+extern struct dvb_frontend *dib0090_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config);
+extern struct dvb_frontend *dib0090_fw_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config);
+extern void dib0090_dcc_freq(struct dvb_frontend *fe, u8 fast);
+extern void dib0090_pwm_gain_reset(struct dvb_frontend *fe);
+extern u16 dib0090_get_wbd_target(struct dvb_frontend *tuner);
+extern u16 dib0090_get_wbd_offset(struct dvb_frontend *fe);
+extern int dib0090_gain_control(struct dvb_frontend *fe);
+extern enum frontend_tune_state dib0090_get_tune_state(struct dvb_frontend *fe);
+extern int dib0090_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state);
+extern void dib0090_get_current_gain(struct dvb_frontend *fe, u16 * rf, u16 * bb, u16 * rf_gain_limit, u16 * rflt);
+extern void dib0090_set_dc_servo(struct dvb_frontend *fe, u8 DC_servo_cutoff);
+extern int dib0090_set_switch(struct dvb_frontend *fe, u8 sw1, u8 sw2, u8 sw3);
+extern int dib0090_set_vga(struct dvb_frontend *fe, u8 onoff);
+extern int dib0090_update_rframp_7090(struct dvb_frontend *fe,
+		u8 cfg_sensitivity);
+extern int dib0090_update_tuning_table_7090(struct dvb_frontend *fe,
+		u8 cfg_sensitivity);
+#else
+static inline struct dvb_frontend *dib0090_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+
+static inline struct dvb_frontend *dib0090_fw_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0090_config *config)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+
+static inline void dib0090_dcc_freq(struct dvb_frontend *fe, u8 fast)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+}
+
+static inline void dib0090_pwm_gain_reset(struct dvb_frontend *fe)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+}
+
+static inline u16 dib0090_get_wbd_target(struct dvb_frontend *tuner)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return 0;
+}
+
+static inline u16 dib0090_get_wbd_offset(struct dvb_frontend *fe)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return 0;
+}
+
+static inline int dib0090_gain_control(struct dvb_frontend *fe)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return -ENODEV;
+}
+
+static inline enum frontend_tune_state dib0090_get_tune_state(struct dvb_frontend *fe)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return CT_DONE;
+}
+
+static inline int dib0090_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return -ENODEV;
+}
+
+static inline void dib0090_get_current_gain(struct dvb_frontend *fe, u16 * rf, u16 * bb, u16 * rf_gain_limit, u16 * rflt)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+}
+
+static inline void dib0090_set_dc_servo(struct dvb_frontend *fe, u8 DC_servo_cutoff)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+}
+
+static inline int dib0090_set_switch(struct dvb_frontend *fe,
+		u8 sw1, u8 sw2, u8 sw3)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return -ENODEV;
+}
+
+static inline int dib0090_set_vga(struct dvb_frontend *fe, u8 onoff)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return -ENODEV;
+}
+
+static inline int dib0090_update_rframp_7090(struct dvb_frontend *fe,
+		u8 cfg_sensitivity)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return -ENODEV;
+}
+
+static inline int dib0090_update_tuning_table_7090(struct dvb_frontend *fe,
+		u8 cfg_sensitivity)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return -ENODEV;
+}
+#endif
+
+#endif
diff --git a/drivers/media/dvb-frontends/dib3000.h b/drivers/media/dvb-frontends/dib3000.h
new file mode 100644
index 0000000..404f63a
--- /dev/null
+++ b/drivers/media/dvb-frontends/dib3000.h
@@ -0,0 +1,56 @@
+/*
+ * public header file of the frontend drivers for mobile DVB-T demodulators
+ * DiBcom 3000M-B and DiBcom 3000P/M-C (http://www.dibcom.fr/)
+ *
+ * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
+ *
+ * based on GPL code from DibCom, which has
+ *
+ * Copyright (C) 2004 Amaury Demol for DiBcom (ademol@dibcom.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, version 2.
+ *
+ * Acknowledgements
+ *
+ *  Amaury Demol (ademol@dibcom.fr) from DiBcom for providing specs and driver
+ *  sources, on which this driver (and the dvb-dibusb) are based.
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ *
+ */
+
+#ifndef DIB3000_H
+#define DIB3000_H
+
+#include <linux/dvb/frontend.h>
+
+struct dib3000_config
+{
+	/* the demodulator's i2c address */
+	u8 demod_address;
+};
+
+struct dib_fe_xfer_ops
+{
+	/* pid and transfer handling is done in the demodulator */
+	int (*pid_parse)(struct dvb_frontend *fe, int onoff);
+	int (*fifo_ctrl)(struct dvb_frontend *fe, int onoff);
+	int (*pid_ctrl)(struct dvb_frontend *fe, int index, int pid, int onoff);
+	int (*tuner_pass_ctrl)(struct dvb_frontend *fe, int onoff, u8 pll_ctrl);
+};
+
+#if defined(CONFIG_DVB_DIB3000MB) || (defined(CONFIG_DVB_DIB3000MB_MODULE) && defined(MODULE))
+extern struct dvb_frontend* dib3000mb_attach(const struct dib3000_config* config,
+					     struct i2c_adapter* i2c, struct dib_fe_xfer_ops *xfer_ops);
+#else
+static inline struct dvb_frontend* dib3000mb_attach(const struct dib3000_config* config,
+					     struct i2c_adapter* i2c, struct dib_fe_xfer_ops *xfer_ops)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif // CONFIG_DVB_DIB3000MB
+
+#endif // DIB3000_H
diff --git a/drivers/media/dvb-frontends/dib3000mb.c b/drivers/media/dvb-frontends/dib3000mb.c
new file mode 100644
index 0000000..af91e0c
--- /dev/null
+++ b/drivers/media/dvb-frontends/dib3000mb.c
@@ -0,0 +1,829 @@
+/*
+ * Frontend driver for mobile DVB-T demodulator DiBcom 3000M-B
+ * DiBcom (http://www.dibcom.fr/)
+ *
+ * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
+ *
+ * based on GPL code from DibCom, which has
+ *
+ * Copyright (C) 2004 Amaury Demol for DiBcom (ademol@dibcom.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, version 2.
+ *
+ * Acknowledgements
+ *
+ *  Amaury Demol (ademol@dibcom.fr) from DiBcom for providing specs and driver
+ *  sources, on which this driver (and the dvb-dibusb) are based.
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+
+#include "dvb_frontend.h"
+
+#include "dib3000.h"
+#include "dib3000mb_priv.h"
+
+/* Version information */
+#define DRIVER_VERSION "0.1"
+#define DRIVER_DESC "DiBcom 3000M-B DVB-T demodulator"
+#define DRIVER_AUTHOR "Patrick Boettcher, patrick.boettcher@desy.de"
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level (1=info,2=xfer,4=setfe,8=getfe (|-able)).");
+
+#define deb_info(args...) dprintk(0x01,args)
+#define deb_i2c(args...)  dprintk(0x02,args)
+#define deb_srch(args...) dprintk(0x04,args)
+#define deb_info(args...) dprintk(0x01,args)
+#define deb_xfer(args...) dprintk(0x02,args)
+#define deb_setf(args...) dprintk(0x04,args)
+#define deb_getf(args...) dprintk(0x08,args)
+
+static int dib3000_read_reg(struct dib3000_state *state, u16 reg)
+{
+	u8 wb[] = { ((reg >> 8) | 0x80) & 0xff, reg & 0xff };
+	u8 rb[2];
+	struct i2c_msg msg[] = {
+		{ .addr = state->config.demod_address, .flags = 0,        .buf = wb, .len = 2 },
+		{ .addr = state->config.demod_address, .flags = I2C_M_RD, .buf = rb, .len = 2 },
+	};
+
+	if (i2c_transfer(state->i2c, msg, 2) != 2)
+		deb_i2c("i2c read error\n");
+
+	deb_i2c("reading i2c bus (reg: %5d 0x%04x, val: %5d 0x%04x)\n",reg,reg,
+			(rb[0] << 8) | rb[1],(rb[0] << 8) | rb[1]);
+
+	return (rb[0] << 8) | rb[1];
+}
+
+static int dib3000_write_reg(struct dib3000_state *state, u16 reg, u16 val)
+{
+	u8 b[] = {
+		(reg >> 8) & 0xff, reg & 0xff,
+		(val >> 8) & 0xff, val & 0xff,
+	};
+	struct i2c_msg msg[] = {
+		{ .addr = state->config.demod_address, .flags = 0, .buf = b, .len = 4 }
+	};
+	deb_i2c("writing i2c bus (reg: %5d 0x%04x, val: %5d 0x%04x)\n",reg,reg,val,val);
+
+	return i2c_transfer(state->i2c,msg, 1) != 1 ? -EREMOTEIO : 0;
+}
+
+static int dib3000_search_status(u16 irq,u16 lock)
+{
+	if (irq & 0x02) {
+		if (lock & 0x01) {
+			deb_srch("auto search succeeded\n");
+			return 1; // auto search succeeded
+		} else {
+			deb_srch("auto search not successful\n");
+			return 0; // auto search failed
+		}
+	} else if (irq & 0x01)  {
+		deb_srch("auto search failed\n");
+		return 0; // auto search failed
+	}
+	return -1; // try again
+}
+
+/* for auto search */
+static u16 dib3000_seq[2][2][2] =     /* fft,gua,   inv   */
+	{ /* fft */
+		{ /* gua */
+			{ 0, 1 },                   /*  0   0   { 0,1 } */
+			{ 3, 9 },                   /*  0   1   { 0,1 } */
+		},
+		{
+			{ 2, 5 },                   /*  1   0   { 0,1 } */
+			{ 6, 11 },                  /*  1   1   { 0,1 } */
+		}
+	};
+
+static int dib3000mb_get_frontend(struct dvb_frontend* fe);
+
+static int dib3000mb_set_frontend(struct dvb_frontend *fe, int tuner)
+{
+	struct dib3000_state* state = fe->demodulator_priv;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	fe_code_rate_t fe_cr = FEC_NONE;
+	int search_state, seq;
+
+	if (tuner && fe->ops.tuner_ops.set_params) {
+		fe->ops.tuner_ops.set_params(fe);
+		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+
+		deb_setf("bandwidth: ");
+		switch (c->bandwidth_hz) {
+			case 8000000:
+				deb_setf("8 MHz\n");
+				wr_foreach(dib3000mb_reg_timing_freq, dib3000mb_timing_freq[2]);
+				wr_foreach(dib3000mb_reg_bandwidth, dib3000mb_bandwidth_8mhz);
+				break;
+			case 7000000:
+				deb_setf("7 MHz\n");
+				wr_foreach(dib3000mb_reg_timing_freq, dib3000mb_timing_freq[1]);
+				wr_foreach(dib3000mb_reg_bandwidth, dib3000mb_bandwidth_7mhz);
+				break;
+			case 6000000:
+				deb_setf("6 MHz\n");
+				wr_foreach(dib3000mb_reg_timing_freq, dib3000mb_timing_freq[0]);
+				wr_foreach(dib3000mb_reg_bandwidth, dib3000mb_bandwidth_6mhz);
+				break;
+			case 0:
+				return -EOPNOTSUPP;
+			default:
+				err("unknown bandwidth value.");
+				return -EINVAL;
+		}
+	}
+	wr(DIB3000MB_REG_LOCK1_MASK, DIB3000MB_LOCK1_SEARCH_4);
+
+	deb_setf("transmission mode: ");
+	switch (c->transmission_mode) {
+		case TRANSMISSION_MODE_2K:
+			deb_setf("2k\n");
+			wr(DIB3000MB_REG_FFT, DIB3000_TRANSMISSION_MODE_2K);
+			break;
+		case TRANSMISSION_MODE_8K:
+			deb_setf("8k\n");
+			wr(DIB3000MB_REG_FFT, DIB3000_TRANSMISSION_MODE_8K);
+			break;
+		case TRANSMISSION_MODE_AUTO:
+			deb_setf("auto\n");
+			break;
+		default:
+			return -EINVAL;
+	}
+
+	deb_setf("guard: ");
+	switch (c->guard_interval) {
+		case GUARD_INTERVAL_1_32:
+			deb_setf("1_32\n");
+			wr(DIB3000MB_REG_GUARD_TIME, DIB3000_GUARD_TIME_1_32);
+			break;
+		case GUARD_INTERVAL_1_16:
+			deb_setf("1_16\n");
+			wr(DIB3000MB_REG_GUARD_TIME, DIB3000_GUARD_TIME_1_16);
+			break;
+		case GUARD_INTERVAL_1_8:
+			deb_setf("1_8\n");
+			wr(DIB3000MB_REG_GUARD_TIME, DIB3000_GUARD_TIME_1_8);
+			break;
+		case GUARD_INTERVAL_1_4:
+			deb_setf("1_4\n");
+			wr(DIB3000MB_REG_GUARD_TIME, DIB3000_GUARD_TIME_1_4);
+			break;
+		case GUARD_INTERVAL_AUTO:
+			deb_setf("auto\n");
+			break;
+		default:
+			return -EINVAL;
+	}
+
+	deb_setf("inversion: ");
+	switch (c->inversion) {
+		case INVERSION_OFF:
+			deb_setf("off\n");
+			wr(DIB3000MB_REG_DDS_INV, DIB3000_DDS_INVERSION_OFF);
+			break;
+		case INVERSION_AUTO:
+			deb_setf("auto ");
+			break;
+		case INVERSION_ON:
+			deb_setf("on\n");
+			wr(DIB3000MB_REG_DDS_INV, DIB3000_DDS_INVERSION_ON);
+			break;
+		default:
+			return -EINVAL;
+	}
+
+	deb_setf("modulation: ");
+	switch (c->modulation) {
+		case QPSK:
+			deb_setf("qpsk\n");
+			wr(DIB3000MB_REG_QAM, DIB3000_CONSTELLATION_QPSK);
+			break;
+		case QAM_16:
+			deb_setf("qam16\n");
+			wr(DIB3000MB_REG_QAM, DIB3000_CONSTELLATION_16QAM);
+			break;
+		case QAM_64:
+			deb_setf("qam64\n");
+			wr(DIB3000MB_REG_QAM, DIB3000_CONSTELLATION_64QAM);
+			break;
+		case QAM_AUTO:
+			break;
+		default:
+			return -EINVAL;
+	}
+	deb_setf("hierarchy: ");
+	switch (c->hierarchy) {
+		case HIERARCHY_NONE:
+			deb_setf("none ");
+			/* fall through */
+		case HIERARCHY_1:
+			deb_setf("alpha=1\n");
+			wr(DIB3000MB_REG_VIT_ALPHA, DIB3000_ALPHA_1);
+			break;
+		case HIERARCHY_2:
+			deb_setf("alpha=2\n");
+			wr(DIB3000MB_REG_VIT_ALPHA, DIB3000_ALPHA_2);
+			break;
+		case HIERARCHY_4:
+			deb_setf("alpha=4\n");
+			wr(DIB3000MB_REG_VIT_ALPHA, DIB3000_ALPHA_4);
+			break;
+		case HIERARCHY_AUTO:
+			deb_setf("alpha=auto\n");
+			break;
+		default:
+			return -EINVAL;
+	}
+
+	deb_setf("hierarchy: ");
+	if (c->hierarchy == HIERARCHY_NONE) {
+		deb_setf("none\n");
+		wr(DIB3000MB_REG_VIT_HRCH, DIB3000_HRCH_OFF);
+		wr(DIB3000MB_REG_VIT_HP, DIB3000_SELECT_HP);
+		fe_cr = c->code_rate_HP;
+	} else if (c->hierarchy != HIERARCHY_AUTO) {
+		deb_setf("on\n");
+		wr(DIB3000MB_REG_VIT_HRCH, DIB3000_HRCH_ON);
+		wr(DIB3000MB_REG_VIT_HP, DIB3000_SELECT_LP);
+		fe_cr = c->code_rate_LP;
+	}
+	deb_setf("fec: ");
+	switch (fe_cr) {
+		case FEC_1_2:
+			deb_setf("1_2\n");
+			wr(DIB3000MB_REG_VIT_CODE_RATE, DIB3000_FEC_1_2);
+			break;
+		case FEC_2_3:
+			deb_setf("2_3\n");
+			wr(DIB3000MB_REG_VIT_CODE_RATE, DIB3000_FEC_2_3);
+			break;
+		case FEC_3_4:
+			deb_setf("3_4\n");
+			wr(DIB3000MB_REG_VIT_CODE_RATE, DIB3000_FEC_3_4);
+			break;
+		case FEC_5_6:
+			deb_setf("5_6\n");
+			wr(DIB3000MB_REG_VIT_CODE_RATE, DIB3000_FEC_5_6);
+			break;
+		case FEC_7_8:
+			deb_setf("7_8\n");
+			wr(DIB3000MB_REG_VIT_CODE_RATE, DIB3000_FEC_7_8);
+			break;
+		case FEC_NONE:
+			deb_setf("none ");
+			break;
+		case FEC_AUTO:
+			deb_setf("auto\n");
+			break;
+		default:
+			return -EINVAL;
+	}
+
+	seq = dib3000_seq
+		[c->transmission_mode == TRANSMISSION_MODE_AUTO]
+		[c->guard_interval == GUARD_INTERVAL_AUTO]
+		[c->inversion == INVERSION_AUTO];
+
+	deb_setf("seq? %d\n", seq);
+
+	wr(DIB3000MB_REG_SEQ, seq);
+
+	wr(DIB3000MB_REG_ISI, seq ? DIB3000MB_ISI_INHIBIT : DIB3000MB_ISI_ACTIVATE);
+
+	if (c->transmission_mode == TRANSMISSION_MODE_2K) {
+		if (c->guard_interval == GUARD_INTERVAL_1_8) {
+			wr(DIB3000MB_REG_SYNC_IMPROVEMENT, DIB3000MB_SYNC_IMPROVE_2K_1_8);
+		} else {
+			wr(DIB3000MB_REG_SYNC_IMPROVEMENT, DIB3000MB_SYNC_IMPROVE_DEFAULT);
+		}
+
+		wr(DIB3000MB_REG_UNK_121, DIB3000MB_UNK_121_2K);
+	} else {
+		wr(DIB3000MB_REG_UNK_121, DIB3000MB_UNK_121_DEFAULT);
+	}
+
+	wr(DIB3000MB_REG_MOBILE_ALGO, DIB3000MB_MOBILE_ALGO_OFF);
+	wr(DIB3000MB_REG_MOBILE_MODE_QAM, DIB3000MB_MOBILE_MODE_QAM_OFF);
+	wr(DIB3000MB_REG_MOBILE_MODE, DIB3000MB_MOBILE_MODE_OFF);
+
+	wr_foreach(dib3000mb_reg_agc_bandwidth, dib3000mb_agc_bandwidth_high);
+
+	wr(DIB3000MB_REG_ISI, DIB3000MB_ISI_ACTIVATE);
+
+	wr(DIB3000MB_REG_RESTART, DIB3000MB_RESTART_AGC + DIB3000MB_RESTART_CTRL);
+	wr(DIB3000MB_REG_RESTART, DIB3000MB_RESTART_OFF);
+
+	/* wait for AGC lock */
+	msleep(70);
+
+	wr_foreach(dib3000mb_reg_agc_bandwidth, dib3000mb_agc_bandwidth_low);
+
+	/* something has to be auto searched */
+	if (c->modulation == QAM_AUTO ||
+		c->hierarchy == HIERARCHY_AUTO ||
+		fe_cr == FEC_AUTO ||
+		c->inversion == INVERSION_AUTO) {
+		int as_count=0;
+
+		deb_setf("autosearch enabled.\n");
+
+		wr(DIB3000MB_REG_ISI, DIB3000MB_ISI_INHIBIT);
+
+		wr(DIB3000MB_REG_RESTART, DIB3000MB_RESTART_AUTO_SEARCH);
+		wr(DIB3000MB_REG_RESTART, DIB3000MB_RESTART_OFF);
+
+		while ((search_state =
+				dib3000_search_status(
+					rd(DIB3000MB_REG_AS_IRQ_PENDING),
+					rd(DIB3000MB_REG_LOCK2_VALUE))) < 0 && as_count++ < 100)
+			msleep(1);
+
+		deb_setf("search_state after autosearch %d after %d checks\n",search_state,as_count);
+
+		if (search_state == 1) {
+			if (dib3000mb_get_frontend(fe) == 0) {
+				deb_setf("reading tuning data from frontend succeeded.\n");
+				return dib3000mb_set_frontend(fe, 0);
+			}
+		}
+
+	} else {
+		wr(DIB3000MB_REG_RESTART, DIB3000MB_RESTART_CTRL);
+		wr(DIB3000MB_REG_RESTART, DIB3000MB_RESTART_OFF);
+	}
+
+	return 0;
+}
+
+static int dib3000mb_fe_init(struct dvb_frontend* fe, int mobile_mode)
+{
+	struct dib3000_state* state = fe->demodulator_priv;
+
+	deb_info("dib3000mb is getting up.\n");
+	wr(DIB3000MB_REG_POWER_CONTROL, DIB3000MB_POWER_UP);
+
+	wr(DIB3000MB_REG_RESTART, DIB3000MB_RESTART_AGC);
+
+	wr(DIB3000MB_REG_RESET_DEVICE, DIB3000MB_RESET_DEVICE);
+	wr(DIB3000MB_REG_RESET_DEVICE, DIB3000MB_RESET_DEVICE_RST);
+
+	wr(DIB3000MB_REG_CLOCK, DIB3000MB_CLOCK_DEFAULT);
+
+	wr(DIB3000MB_REG_ELECT_OUT_MODE, DIB3000MB_ELECT_OUT_MODE_ON);
+
+	wr(DIB3000MB_REG_DDS_FREQ_MSB, DIB3000MB_DDS_FREQ_MSB);
+	wr(DIB3000MB_REG_DDS_FREQ_LSB, DIB3000MB_DDS_FREQ_LSB);
+
+	wr_foreach(dib3000mb_reg_timing_freq, dib3000mb_timing_freq[2]);
+
+	wr_foreach(dib3000mb_reg_impulse_noise,
+			dib3000mb_impulse_noise_values[DIB3000MB_IMPNOISE_OFF]);
+
+	wr_foreach(dib3000mb_reg_agc_gain, dib3000mb_default_agc_gain);
+
+	wr(DIB3000MB_REG_PHASE_NOISE, DIB3000MB_PHASE_NOISE_DEFAULT);
+
+	wr_foreach(dib3000mb_reg_phase_noise, dib3000mb_default_noise_phase);
+
+	wr_foreach(dib3000mb_reg_lock_duration, dib3000mb_default_lock_duration);
+
+	wr_foreach(dib3000mb_reg_agc_bandwidth, dib3000mb_agc_bandwidth_low);
+
+	wr(DIB3000MB_REG_LOCK0_MASK, DIB3000MB_LOCK0_DEFAULT);
+	wr(DIB3000MB_REG_LOCK1_MASK, DIB3000MB_LOCK1_SEARCH_4);
+	wr(DIB3000MB_REG_LOCK2_MASK, DIB3000MB_LOCK2_DEFAULT);
+	wr(DIB3000MB_REG_SEQ, dib3000_seq[1][1][1]);
+
+	wr_foreach(dib3000mb_reg_bandwidth, dib3000mb_bandwidth_8mhz);
+
+	wr(DIB3000MB_REG_UNK_68, DIB3000MB_UNK_68);
+	wr(DIB3000MB_REG_UNK_69, DIB3000MB_UNK_69);
+	wr(DIB3000MB_REG_UNK_71, DIB3000MB_UNK_71);
+	wr(DIB3000MB_REG_UNK_77, DIB3000MB_UNK_77);
+	wr(DIB3000MB_REG_UNK_78, DIB3000MB_UNK_78);
+	wr(DIB3000MB_REG_ISI, DIB3000MB_ISI_INHIBIT);
+	wr(DIB3000MB_REG_UNK_92, DIB3000MB_UNK_92);
+	wr(DIB3000MB_REG_UNK_96, DIB3000MB_UNK_96);
+	wr(DIB3000MB_REG_UNK_97, DIB3000MB_UNK_97);
+	wr(DIB3000MB_REG_UNK_106, DIB3000MB_UNK_106);
+	wr(DIB3000MB_REG_UNK_107, DIB3000MB_UNK_107);
+	wr(DIB3000MB_REG_UNK_108, DIB3000MB_UNK_108);
+	wr(DIB3000MB_REG_UNK_122, DIB3000MB_UNK_122);
+	wr(DIB3000MB_REG_MOBILE_MODE_QAM, DIB3000MB_MOBILE_MODE_QAM_OFF);
+	wr(DIB3000MB_REG_BERLEN, DIB3000MB_BERLEN_DEFAULT);
+
+	wr_foreach(dib3000mb_reg_filter_coeffs, dib3000mb_filter_coeffs);
+
+	wr(DIB3000MB_REG_MOBILE_ALGO, DIB3000MB_MOBILE_ALGO_ON);
+	wr(DIB3000MB_REG_MULTI_DEMOD_MSB, DIB3000MB_MULTI_DEMOD_MSB);
+	wr(DIB3000MB_REG_MULTI_DEMOD_LSB, DIB3000MB_MULTI_DEMOD_LSB);
+
+	wr(DIB3000MB_REG_OUTPUT_MODE, DIB3000MB_OUTPUT_MODE_SLAVE);
+
+	wr(DIB3000MB_REG_FIFO_142, DIB3000MB_FIFO_142);
+	wr(DIB3000MB_REG_MPEG2_OUT_MODE, DIB3000MB_MPEG2_OUT_MODE_188);
+	wr(DIB3000MB_REG_PID_PARSE, DIB3000MB_PID_PARSE_ACTIVATE);
+	wr(DIB3000MB_REG_FIFO, DIB3000MB_FIFO_INHIBIT);
+	wr(DIB3000MB_REG_FIFO_146, DIB3000MB_FIFO_146);
+	wr(DIB3000MB_REG_FIFO_147, DIB3000MB_FIFO_147);
+
+	wr(DIB3000MB_REG_DATA_IN_DIVERSITY, DIB3000MB_DATA_DIVERSITY_IN_OFF);
+
+	return 0;
+}
+
+static int dib3000mb_get_frontend(struct dvb_frontend* fe)
+{
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	struct dib3000_state* state = fe->demodulator_priv;
+	fe_code_rate_t *cr;
+	u16 tps_val;
+	int inv_test1,inv_test2;
+	u32 dds_val, threshold = 0x800000;
+
+	if (!rd(DIB3000MB_REG_TPS_LOCK))
+		return 0;
+
+	dds_val = ((rd(DIB3000MB_REG_DDS_VALUE_MSB) & 0xff) << 16) + rd(DIB3000MB_REG_DDS_VALUE_LSB);
+	deb_getf("DDS_VAL: %x %x %x",dds_val, rd(DIB3000MB_REG_DDS_VALUE_MSB), rd(DIB3000MB_REG_DDS_VALUE_LSB));
+	if (dds_val < threshold)
+		inv_test1 = 0;
+	else if (dds_val == threshold)
+		inv_test1 = 1;
+	else
+		inv_test1 = 2;
+
+	dds_val = ((rd(DIB3000MB_REG_DDS_FREQ_MSB) & 0xff) << 16) + rd(DIB3000MB_REG_DDS_FREQ_LSB);
+	deb_getf("DDS_FREQ: %x %x %x",dds_val, rd(DIB3000MB_REG_DDS_FREQ_MSB), rd(DIB3000MB_REG_DDS_FREQ_LSB));
+	if (dds_val < threshold)
+		inv_test2 = 0;
+	else if (dds_val == threshold)
+		inv_test2 = 1;
+	else
+		inv_test2 = 2;
+
+	c->inversion =
+		((inv_test2 == 2) && (inv_test1==1 || inv_test1==0)) ||
+		((inv_test2 == 0) && (inv_test1==1 || inv_test1==2)) ?
+		INVERSION_ON : INVERSION_OFF;
+
+	deb_getf("inversion %d %d, %d\n", inv_test2, inv_test1, c->inversion);
+
+	switch ((tps_val = rd(DIB3000MB_REG_TPS_QAM))) {
+		case DIB3000_CONSTELLATION_QPSK:
+			deb_getf("QPSK ");
+			c->modulation = QPSK;
+			break;
+		case DIB3000_CONSTELLATION_16QAM:
+			deb_getf("QAM16 ");
+			c->modulation = QAM_16;
+			break;
+		case DIB3000_CONSTELLATION_64QAM:
+			deb_getf("QAM64 ");
+			c->modulation = QAM_64;
+			break;
+		default:
+			err("Unexpected constellation returned by TPS (%d)", tps_val);
+			break;
+	}
+	deb_getf("TPS: %d\n", tps_val);
+
+	if (rd(DIB3000MB_REG_TPS_HRCH)) {
+		deb_getf("HRCH ON\n");
+		cr = &c->code_rate_LP;
+		c->code_rate_HP = FEC_NONE;
+		switch ((tps_val = rd(DIB3000MB_REG_TPS_VIT_ALPHA))) {
+			case DIB3000_ALPHA_0:
+				deb_getf("HIERARCHY_NONE ");
+				c->hierarchy = HIERARCHY_NONE;
+				break;
+			case DIB3000_ALPHA_1:
+				deb_getf("HIERARCHY_1 ");
+				c->hierarchy = HIERARCHY_1;
+				break;
+			case DIB3000_ALPHA_2:
+				deb_getf("HIERARCHY_2 ");
+				c->hierarchy = HIERARCHY_2;
+				break;
+			case DIB3000_ALPHA_4:
+				deb_getf("HIERARCHY_4 ");
+				c->hierarchy = HIERARCHY_4;
+				break;
+			default:
+				err("Unexpected ALPHA value returned by TPS (%d)", tps_val);
+				break;
+		}
+		deb_getf("TPS: %d\n", tps_val);
+
+		tps_val = rd(DIB3000MB_REG_TPS_CODE_RATE_LP);
+	} else {
+		deb_getf("HRCH OFF\n");
+		cr = &c->code_rate_HP;
+		c->code_rate_LP = FEC_NONE;
+		c->hierarchy = HIERARCHY_NONE;
+
+		tps_val = rd(DIB3000MB_REG_TPS_CODE_RATE_HP);
+	}
+
+	switch (tps_val) {
+		case DIB3000_FEC_1_2:
+			deb_getf("FEC_1_2 ");
+			*cr = FEC_1_2;
+			break;
+		case DIB3000_FEC_2_3:
+			deb_getf("FEC_2_3 ");
+			*cr = FEC_2_3;
+			break;
+		case DIB3000_FEC_3_4:
+			deb_getf("FEC_3_4 ");
+			*cr = FEC_3_4;
+			break;
+		case DIB3000_FEC_5_6:
+			deb_getf("FEC_5_6 ");
+			*cr = FEC_4_5;
+			break;
+		case DIB3000_FEC_7_8:
+			deb_getf("FEC_7_8 ");
+			*cr = FEC_7_8;
+			break;
+		default:
+			err("Unexpected FEC returned by TPS (%d)", tps_val);
+			break;
+	}
+	deb_getf("TPS: %d\n",tps_val);
+
+	switch ((tps_val = rd(DIB3000MB_REG_TPS_GUARD_TIME))) {
+		case DIB3000_GUARD_TIME_1_32:
+			deb_getf("GUARD_INTERVAL_1_32 ");
+			c->guard_interval = GUARD_INTERVAL_1_32;
+			break;
+		case DIB3000_GUARD_TIME_1_16:
+			deb_getf("GUARD_INTERVAL_1_16 ");
+			c->guard_interval = GUARD_INTERVAL_1_16;
+			break;
+		case DIB3000_GUARD_TIME_1_8:
+			deb_getf("GUARD_INTERVAL_1_8 ");
+			c->guard_interval = GUARD_INTERVAL_1_8;
+			break;
+		case DIB3000_GUARD_TIME_1_4:
+			deb_getf("GUARD_INTERVAL_1_4 ");
+			c->guard_interval = GUARD_INTERVAL_1_4;
+			break;
+		default:
+			err("Unexpected Guard Time returned by TPS (%d)", tps_val);
+			break;
+	}
+	deb_getf("TPS: %d\n", tps_val);
+
+	switch ((tps_val = rd(DIB3000MB_REG_TPS_FFT))) {
+		case DIB3000_TRANSMISSION_MODE_2K:
+			deb_getf("TRANSMISSION_MODE_2K ");
+			c->transmission_mode = TRANSMISSION_MODE_2K;
+			break;
+		case DIB3000_TRANSMISSION_MODE_8K:
+			deb_getf("TRANSMISSION_MODE_8K ");
+			c->transmission_mode = TRANSMISSION_MODE_8K;
+			break;
+		default:
+			err("unexpected transmission mode return by TPS (%d)", tps_val);
+			break;
+	}
+	deb_getf("TPS: %d\n", tps_val);
+
+	return 0;
+}
+
+static int dib3000mb_read_status(struct dvb_frontend* fe, fe_status_t *stat)
+{
+	struct dib3000_state* state = fe->demodulator_priv;
+
+	*stat = 0;
+
+	if (rd(DIB3000MB_REG_AGC_LOCK))
+		*stat |= FE_HAS_SIGNAL;
+	if (rd(DIB3000MB_REG_CARRIER_LOCK))
+		*stat |= FE_HAS_CARRIER;
+	if (rd(DIB3000MB_REG_VIT_LCK))
+		*stat |= FE_HAS_VITERBI;
+	if (rd(DIB3000MB_REG_TS_SYNC_LOCK))
+		*stat |= (FE_HAS_SYNC | FE_HAS_LOCK);
+
+	deb_getf("actual status is %2x\n",*stat);
+
+	deb_getf("autoval: tps: %d, qam: %d, hrch: %d, alpha: %d, hp: %d, lp: %d, guard: %d, fft: %d cell: %d\n",
+			rd(DIB3000MB_REG_TPS_LOCK),
+			rd(DIB3000MB_REG_TPS_QAM),
+			rd(DIB3000MB_REG_TPS_HRCH),
+			rd(DIB3000MB_REG_TPS_VIT_ALPHA),
+			rd(DIB3000MB_REG_TPS_CODE_RATE_HP),
+			rd(DIB3000MB_REG_TPS_CODE_RATE_LP),
+			rd(DIB3000MB_REG_TPS_GUARD_TIME),
+			rd(DIB3000MB_REG_TPS_FFT),
+			rd(DIB3000MB_REG_TPS_CELL_ID));
+
+	//*stat = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
+	return 0;
+}
+
+static int dib3000mb_read_ber(struct dvb_frontend* fe, u32 *ber)
+{
+	struct dib3000_state* state = fe->demodulator_priv;
+
+	*ber = ((rd(DIB3000MB_REG_BER_MSB) << 16) | rd(DIB3000MB_REG_BER_LSB));
+	return 0;
+}
+
+/* see dib3000-watch dvb-apps for exact calcuations of signal_strength and snr */
+static int dib3000mb_read_signal_strength(struct dvb_frontend* fe, u16 *strength)
+{
+	struct dib3000_state* state = fe->demodulator_priv;
+
+	*strength = rd(DIB3000MB_REG_SIGNAL_POWER) * 0xffff / 0x170;
+	return 0;
+}
+
+static int dib3000mb_read_snr(struct dvb_frontend* fe, u16 *snr)
+{
+	struct dib3000_state* state = fe->demodulator_priv;
+	short sigpow = rd(DIB3000MB_REG_SIGNAL_POWER);
+	int icipow = ((rd(DIB3000MB_REG_NOISE_POWER_MSB) & 0xff) << 16) |
+		rd(DIB3000MB_REG_NOISE_POWER_LSB);
+	*snr = (sigpow << 8) / ((icipow > 0) ? icipow : 1);
+	return 0;
+}
+
+static int dib3000mb_read_unc_blocks(struct dvb_frontend* fe, u32 *unc)
+{
+	struct dib3000_state* state = fe->demodulator_priv;
+
+	*unc = rd(DIB3000MB_REG_PACKET_ERROR_RATE);
+	return 0;
+}
+
+static int dib3000mb_sleep(struct dvb_frontend* fe)
+{
+	struct dib3000_state* state = fe->demodulator_priv;
+	deb_info("dib3000mb is going to bed.\n");
+	wr(DIB3000MB_REG_POWER_CONTROL, DIB3000MB_POWER_DOWN);
+	return 0;
+}
+
+static int dib3000mb_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
+{
+	tune->min_delay_ms = 800;
+	return 0;
+}
+
+static int dib3000mb_fe_init_nonmobile(struct dvb_frontend* fe)
+{
+	return dib3000mb_fe_init(fe, 0);
+}
+
+static int dib3000mb_set_frontend_and_tuner(struct dvb_frontend *fe)
+{
+	return dib3000mb_set_frontend(fe, 1);
+}
+
+static void dib3000mb_release(struct dvb_frontend* fe)
+{
+	struct dib3000_state *state = fe->demodulator_priv;
+	kfree(state);
+}
+
+/* pid filter and transfer stuff */
+static int dib3000mb_pid_control(struct dvb_frontend *fe,int index, int pid,int onoff)
+{
+	struct dib3000_state *state = fe->demodulator_priv;
+	pid = (onoff ? pid | DIB3000_ACTIVATE_PID_FILTERING : 0);
+	wr(index+DIB3000MB_REG_FIRST_PID,pid);
+	return 0;
+}
+
+static int dib3000mb_fifo_control(struct dvb_frontend *fe, int onoff)
+{
+	struct dib3000_state *state = fe->demodulator_priv;
+
+	deb_xfer("%s fifo\n",onoff ? "enabling" : "disabling");
+	if (onoff) {
+		wr(DIB3000MB_REG_FIFO, DIB3000MB_FIFO_ACTIVATE);
+	} else {
+		wr(DIB3000MB_REG_FIFO, DIB3000MB_FIFO_INHIBIT);
+	}
+	return 0;
+}
+
+static int dib3000mb_pid_parse(struct dvb_frontend *fe, int onoff)
+{
+	struct dib3000_state *state = fe->demodulator_priv;
+	deb_xfer("%s pid parsing\n",onoff ? "enabling" : "disabling");
+	wr(DIB3000MB_REG_PID_PARSE,onoff);
+	return 0;
+}
+
+static int dib3000mb_tuner_pass_ctrl(struct dvb_frontend *fe, int onoff, u8 pll_addr)
+{
+	struct dib3000_state *state = fe->demodulator_priv;
+	if (onoff) {
+		wr(DIB3000MB_REG_TUNER, DIB3000_TUNER_WRITE_ENABLE(pll_addr));
+	} else {
+		wr(DIB3000MB_REG_TUNER, DIB3000_TUNER_WRITE_DISABLE(pll_addr));
+	}
+	return 0;
+}
+
+static struct dvb_frontend_ops dib3000mb_ops;
+
+struct dvb_frontend* dib3000mb_attach(const struct dib3000_config* config,
+				      struct i2c_adapter* i2c, struct dib_fe_xfer_ops *xfer_ops)
+{
+	struct dib3000_state* state = NULL;
+
+	/* allocate memory for the internal state */
+	state = kzalloc(sizeof(struct dib3000_state), GFP_KERNEL);
+	if (state == NULL)
+		goto error;
+
+	/* setup the state */
+	state->i2c = i2c;
+	memcpy(&state->config,config,sizeof(struct dib3000_config));
+
+	/* check for the correct demod */
+	if (rd(DIB3000_REG_MANUFACTOR_ID) != DIB3000_I2C_ID_DIBCOM)
+		goto error;
+
+	if (rd(DIB3000_REG_DEVICE_ID) != DIB3000MB_DEVICE_ID)
+		goto error;
+
+	/* create dvb_frontend */
+	memcpy(&state->frontend.ops, &dib3000mb_ops, sizeof(struct dvb_frontend_ops));
+	state->frontend.demodulator_priv = state;
+
+	/* set the xfer operations */
+	xfer_ops->pid_parse = dib3000mb_pid_parse;
+	xfer_ops->fifo_ctrl = dib3000mb_fifo_control;
+	xfer_ops->pid_ctrl = dib3000mb_pid_control;
+	xfer_ops->tuner_pass_ctrl = dib3000mb_tuner_pass_ctrl;
+
+	return &state->frontend;
+
+error:
+	kfree(state);
+	return NULL;
+}
+
+static struct dvb_frontend_ops dib3000mb_ops = {
+	.delsys = { SYS_DVBT },
+	.info = {
+		.name			= "DiBcom 3000M-B DVB-T",
+		.frequency_min		= 44250000,
+		.frequency_max		= 867250000,
+		.frequency_stepsize	= 62500,
+		.caps = FE_CAN_INVERSION_AUTO |
+				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_FEC_AUTO |
+				FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
+				FE_CAN_TRANSMISSION_MODE_AUTO |
+				FE_CAN_GUARD_INTERVAL_AUTO |
+				FE_CAN_RECOVER |
+				FE_CAN_HIERARCHY_AUTO,
+	},
+
+	.release = dib3000mb_release,
+
+	.init = dib3000mb_fe_init_nonmobile,
+	.sleep = dib3000mb_sleep,
+
+	.set_frontend = dib3000mb_set_frontend_and_tuner,
+	.get_frontend = dib3000mb_get_frontend,
+	.get_tune_settings = dib3000mb_fe_get_tune_settings,
+
+	.read_status = dib3000mb_read_status,
+	.read_ber = dib3000mb_read_ber,
+	.read_signal_strength = dib3000mb_read_signal_strength,
+	.read_snr = dib3000mb_read_snr,
+	.read_ucblocks = dib3000mb_read_unc_blocks,
+};
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(dib3000mb_attach);
diff --git a/drivers/media/dvb-frontends/dib3000mb_priv.h b/drivers/media/dvb-frontends/dib3000mb_priv.h
new file mode 100644
index 0000000..9dc235a
--- /dev/null
+++ b/drivers/media/dvb-frontends/dib3000mb_priv.h
@@ -0,0 +1,556 @@
+/*
+ * dib3000mb_priv.h
+ *
+ * Copyright (C) 2004 Patrick Boettcher (patrick.boettcher@desy.de)
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License as
+ *	published by the Free Software Foundation, version 2.
+ *
+ * for more information see dib3000mb.c .
+ */
+
+#ifndef __DIB3000MB_PRIV_H_INCLUDED__
+#define __DIB3000MB_PRIV_H_INCLUDED__
+
+/* info and err, taken from usb.h, if there is anything available like by default. */
+#define err(format, arg...)  printk(KERN_ERR     "dib3000: " format "\n" , ## arg)
+#define info(format, arg...) printk(KERN_INFO    "dib3000: " format "\n" , ## arg)
+#define warn(format, arg...) printk(KERN_WARNING "dib3000: " format "\n" , ## arg)
+
+/* handy shortcuts */
+#define rd(reg) dib3000_read_reg(state,reg)
+
+#define wr(reg,val) if (dib3000_write_reg(state,reg,val)) \
+	{ err("while sending 0x%04x to 0x%04x.",val,reg); return -EREMOTEIO; }
+
+#define wr_foreach(a,v) { int i; \
+	if (sizeof(a) != sizeof(v)) \
+		err("sizeof: %zu %zu is different",sizeof(a),sizeof(v));\
+	for (i=0; i < sizeof(a)/sizeof(u16); i++) \
+		wr(a[i],v[i]); \
+	}
+
+#define set_or(reg,val) wr(reg,rd(reg) | val)
+
+#define set_and(reg,val) wr(reg,rd(reg) & val)
+
+/* debug */
+
+#define dprintk(level,args...) \
+    do { if ((debug & level)) { printk(args); } } while (0)
+
+/* mask for enabling a specific pid for the pid_filter */
+#define DIB3000_ACTIVATE_PID_FILTERING	(0x2000)
+
+/* common values for tuning */
+#define DIB3000_ALPHA_0					(     0)
+#define DIB3000_ALPHA_1					(     1)
+#define DIB3000_ALPHA_2					(     2)
+#define DIB3000_ALPHA_4					(     4)
+
+#define DIB3000_CONSTELLATION_QPSK		(     0)
+#define DIB3000_CONSTELLATION_16QAM		(     1)
+#define DIB3000_CONSTELLATION_64QAM		(     2)
+
+#define DIB3000_GUARD_TIME_1_32			(     0)
+#define DIB3000_GUARD_TIME_1_16			(     1)
+#define DIB3000_GUARD_TIME_1_8			(     2)
+#define DIB3000_GUARD_TIME_1_4			(     3)
+
+#define DIB3000_TRANSMISSION_MODE_2K	(     0)
+#define DIB3000_TRANSMISSION_MODE_8K	(     1)
+
+#define DIB3000_SELECT_LP				(     0)
+#define DIB3000_SELECT_HP				(     1)
+
+#define DIB3000_FEC_1_2					(     1)
+#define DIB3000_FEC_2_3					(     2)
+#define DIB3000_FEC_3_4					(     3)
+#define DIB3000_FEC_5_6					(     5)
+#define DIB3000_FEC_7_8					(     7)
+
+#define DIB3000_HRCH_OFF				(     0)
+#define DIB3000_HRCH_ON					(     1)
+
+#define DIB3000_DDS_INVERSION_OFF		(     0)
+#define DIB3000_DDS_INVERSION_ON		(     1)
+
+#define DIB3000_TUNER_WRITE_ENABLE(a)	(0xffff & (a << 8))
+#define DIB3000_TUNER_WRITE_DISABLE(a)	(0xffff & ((a << 8) | (1 << 7)))
+
+#define DIB3000_REG_MANUFACTOR_ID		(  1025)
+#define DIB3000_I2C_ID_DIBCOM			(0x01b3)
+
+#define DIB3000_REG_DEVICE_ID			(  1026)
+#define DIB3000MB_DEVICE_ID				(0x3000)
+#define DIB3000MC_DEVICE_ID				(0x3001)
+#define DIB3000P_DEVICE_ID				(0x3002)
+
+/* frontend state */
+struct dib3000_state {
+	struct i2c_adapter* i2c;
+
+/* configuration settings */
+	struct dib3000_config config;
+
+	struct dvb_frontend frontend;
+	int timing_offset;
+	int timing_offset_comp_done;
+
+	u32 last_tuned_bw;
+	u32 last_tuned_freq;
+};
+
+/* register addresses and some of their default values */
+
+/* restart subsystems */
+#define DIB3000MB_REG_RESTART			(     0)
+
+#define DIB3000MB_RESTART_OFF			(     0)
+#define DIB3000MB_RESTART_AUTO_SEARCH		(1 << 1)
+#define DIB3000MB_RESTART_CTRL				(1 << 2)
+#define DIB3000MB_RESTART_AGC				(1 << 3)
+
+/* FFT size */
+#define DIB3000MB_REG_FFT				(     1)
+
+/* Guard time */
+#define DIB3000MB_REG_GUARD_TIME		(     2)
+
+/* QAM */
+#define DIB3000MB_REG_QAM				(     3)
+
+/* Alpha coefficient high priority Viterbi algorithm */
+#define DIB3000MB_REG_VIT_ALPHA			(     4)
+
+/* spectrum inversion */
+#define DIB3000MB_REG_DDS_INV			(     5)
+
+/* DDS frequency value (IF position) ad ? values don't match reg_3000mb.txt */
+#define DIB3000MB_REG_DDS_FREQ_MSB		(     6)
+#define DIB3000MB_REG_DDS_FREQ_LSB		(     7)
+#define DIB3000MB_DDS_FREQ_MSB				(   178)
+#define DIB3000MB_DDS_FREQ_LSB				(  8990)
+
+/* timing frequency (carrier spacing) */
+static u16 dib3000mb_reg_timing_freq[] = { 8,9 };
+static u16 dib3000mb_timing_freq[][2] = {
+	{ 126 , 48873 }, /* 6 MHz */
+	{ 147 , 57019 }, /* 7 MHz */
+	{ 168 , 65164 }, /* 8 MHz */
+};
+
+/* impulse noise parameter */
+/* 36 ??? */
+
+static u16 dib3000mb_reg_impulse_noise[] = { 10,11,12,15,36 };
+
+enum dib3000mb_impulse_noise_type {
+	DIB3000MB_IMPNOISE_OFF,
+	DIB3000MB_IMPNOISE_MOBILE,
+	DIB3000MB_IMPNOISE_FIXED,
+	DIB3000MB_IMPNOISE_DEFAULT
+};
+
+static u16 dib3000mb_impulse_noise_values[][5] = {
+	{ 0x0000, 0x0004, 0x0014, 0x01ff, 0x0399 }, /* off */
+	{ 0x0001, 0x0004, 0x0014, 0x01ff, 0x037b }, /* mobile */
+	{ 0x0001, 0x0004, 0x0020, 0x01bd, 0x0399 }, /* fixed */
+	{ 0x0000, 0x0002, 0x000a, 0x01ff, 0x0399 }, /* default */
+};
+
+/*
+ * Dual Automatic-Gain-Control
+ * - gains RF in tuner (AGC1)
+ * - gains IF after filtering (AGC2)
+ */
+
+/* also from 16 to 18 */
+static u16 dib3000mb_reg_agc_gain[] = {
+	19,20,21,22,23,24,25,26,27,28,29,30,31,32
+};
+
+static u16 dib3000mb_default_agc_gain[] =
+	{ 0x0001, 52429,   623, 128, 166, 195, 61,   /* RF ??? */
+	  0x0001, 53766, 38011,   0,  90,  33, 23 }; /* IF ??? */
+
+/* phase noise */
+/* 36 is set when setting the impulse noise */
+static u16 dib3000mb_reg_phase_noise[] = { 33,34,35,37,38 };
+
+static u16 dib3000mb_default_noise_phase[] = { 2, 544, 0, 5, 4 };
+
+/* lock duration */
+static u16 dib3000mb_reg_lock_duration[] = { 39,40 };
+static u16 dib3000mb_default_lock_duration[] = { 135, 135 };
+
+/* AGC loop bandwidth */
+static u16 dib3000mb_reg_agc_bandwidth[] = { 43,44,45,46,47,48,49,50 };
+
+static u16 dib3000mb_agc_bandwidth_low[]  =
+	{ 2088, 10, 2088, 10, 3448, 5, 3448, 5 };
+static u16 dib3000mb_agc_bandwidth_high[] =
+	{ 2349,  5, 2349,  5, 2586, 2, 2586, 2 };
+
+/*
+ * lock0 definition (coff_lock)
+ */
+#define DIB3000MB_REG_LOCK0_MASK		(    51)
+#define DIB3000MB_LOCK0_DEFAULT				(     4)
+
+/*
+ * lock1 definition (cpil_lock)
+ * for auto search
+ * which values hide behind the lock masks
+ */
+#define DIB3000MB_REG_LOCK1_MASK		(    52)
+#define DIB3000MB_LOCK1_SEARCH_4			(0x0004)
+#define DIB3000MB_LOCK1_SEARCH_2048			(0x0800)
+#define DIB3000MB_LOCK1_DEFAULT				(0x0001)
+
+/*
+ * lock2 definition (fec_lock) */
+#define DIB3000MB_REG_LOCK2_MASK		(    53)
+#define DIB3000MB_LOCK2_DEFAULT				(0x0080)
+
+/*
+ * SEQ ? what was that again ... :)
+ * changes when, inversion, guard time and fft is
+ * either automatically detected or not
+ */
+#define DIB3000MB_REG_SEQ				(    54)
+
+/* bandwidth */
+static u16 dib3000mb_reg_bandwidth[] = { 55,56,57,58,59,60,61,62,63,64,65,66,67 };
+static u16 dib3000mb_bandwidth_6mhz[] =
+	{ 0, 33, 53312, 112, 46635, 563, 36565, 0, 1000, 0, 1010, 1, 45264 };
+
+static u16 dib3000mb_bandwidth_7mhz[] =
+	{ 0, 28, 64421,  96, 39973, 483,  3255, 0, 1000, 0, 1010, 1, 45264 };
+
+static u16 dib3000mb_bandwidth_8mhz[] =
+	{ 0, 25, 23600,  84, 34976, 422, 43808, 0, 1000, 0, 1010, 1, 45264 };
+
+#define DIB3000MB_REG_UNK_68				(    68)
+#define DIB3000MB_UNK_68						(     0)
+
+#define DIB3000MB_REG_UNK_69				(    69)
+#define DIB3000MB_UNK_69						(     0)
+
+#define DIB3000MB_REG_UNK_71				(    71)
+#define DIB3000MB_UNK_71						(     0)
+
+#define DIB3000MB_REG_UNK_77				(    77)
+#define DIB3000MB_UNK_77						(     6)
+
+#define DIB3000MB_REG_UNK_78				(    78)
+#define DIB3000MB_UNK_78						(0x0080)
+
+/* isi */
+#define DIB3000MB_REG_ISI				(    79)
+#define DIB3000MB_ISI_ACTIVATE				(     0)
+#define DIB3000MB_ISI_INHIBIT				(     1)
+
+/* sync impovement */
+#define DIB3000MB_REG_SYNC_IMPROVEMENT	(    84)
+#define DIB3000MB_SYNC_IMPROVE_2K_1_8		(     3)
+#define DIB3000MB_SYNC_IMPROVE_DEFAULT		(     0)
+
+/* phase noise compensation inhibition */
+#define DIB3000MB_REG_PHASE_NOISE		(    87)
+#define DIB3000MB_PHASE_NOISE_DEFAULT	(     0)
+
+#define DIB3000MB_REG_UNK_92				(    92)
+#define DIB3000MB_UNK_92						(0x0080)
+
+#define DIB3000MB_REG_UNK_96				(    96)
+#define DIB3000MB_UNK_96						(0x0010)
+
+#define DIB3000MB_REG_UNK_97				(    97)
+#define DIB3000MB_UNK_97						(0x0009)
+
+/* mobile mode ??? */
+#define DIB3000MB_REG_MOBILE_MODE		(   101)
+#define DIB3000MB_MOBILE_MODE_ON			(     1)
+#define DIB3000MB_MOBILE_MODE_OFF			(     0)
+
+#define DIB3000MB_REG_UNK_106			(   106)
+#define DIB3000MB_UNK_106					(0x0080)
+
+#define DIB3000MB_REG_UNK_107			(   107)
+#define DIB3000MB_UNK_107					(0x0080)
+
+#define DIB3000MB_REG_UNK_108			(   108)
+#define DIB3000MB_UNK_108					(0x0080)
+
+/* fft */
+#define DIB3000MB_REG_UNK_121			(   121)
+#define DIB3000MB_UNK_121_2K				(     7)
+#define DIB3000MB_UNK_121_DEFAULT			(     5)
+
+#define DIB3000MB_REG_UNK_122			(   122)
+#define DIB3000MB_UNK_122					(  2867)
+
+/* QAM for mobile mode */
+#define DIB3000MB_REG_MOBILE_MODE_QAM	(   126)
+#define DIB3000MB_MOBILE_MODE_QAM_64		(     3)
+#define DIB3000MB_MOBILE_MODE_QAM_QPSK_16	(     1)
+#define DIB3000MB_MOBILE_MODE_QAM_OFF		(     0)
+
+/*
+ * data diversity when having more than one chip on-board
+ * see also DIB3000MB_OUTPUT_MODE_DATA_DIVERSITY
+ */
+#define DIB3000MB_REG_DATA_IN_DIVERSITY		(   127)
+#define DIB3000MB_DATA_DIVERSITY_IN_OFF			(     0)
+#define DIB3000MB_DATA_DIVERSITY_IN_ON			(     2)
+
+/* vit hrch */
+#define DIB3000MB_REG_VIT_HRCH			(   128)
+
+/* vit code rate */
+#define DIB3000MB_REG_VIT_CODE_RATE		(   129)
+
+/* vit select hp */
+#define DIB3000MB_REG_VIT_HP			(   130)
+
+/* time frame for Bit-Error-Rate calculation */
+#define DIB3000MB_REG_BERLEN			(   135)
+#define DIB3000MB_BERLEN_LONG				(     0)
+#define DIB3000MB_BERLEN_DEFAULT			(     1)
+#define DIB3000MB_BERLEN_MEDIUM				(     2)
+#define DIB3000MB_BERLEN_SHORT				(     3)
+
+/* 142 - 152 FIFO parameters
+ * which is what ?
+ */
+
+#define DIB3000MB_REG_FIFO_142			(   142)
+#define DIB3000MB_FIFO_142					(     0)
+
+/* MPEG2 TS output mode */
+#define DIB3000MB_REG_MPEG2_OUT_MODE	(   143)
+#define DIB3000MB_MPEG2_OUT_MODE_204		(     0)
+#define DIB3000MB_MPEG2_OUT_MODE_188		(     1)
+
+#define DIB3000MB_REG_PID_PARSE			(   144)
+#define DIB3000MB_PID_PARSE_INHIBIT		(     0)
+#define DIB3000MB_PID_PARSE_ACTIVATE	(     1)
+
+#define DIB3000MB_REG_FIFO				(   145)
+#define DIB3000MB_FIFO_INHIBIT				(     1)
+#define DIB3000MB_FIFO_ACTIVATE				(     0)
+
+#define DIB3000MB_REG_FIFO_146			(   146)
+#define DIB3000MB_FIFO_146					(     3)
+
+#define DIB3000MB_REG_FIFO_147			(   147)
+#define DIB3000MB_FIFO_147					(0x0100)
+
+/*
+ * pidfilter
+ * it is not a hardware pidfilter but a filter which drops all pids
+ * except the ones set. Necessary because of the limited USB1.1 bandwidth.
+ * regs 153-168
+ */
+
+#define DIB3000MB_REG_FIRST_PID			(   153)
+#define DIB3000MB_NUM_PIDS				(    16)
+
+/*
+ * output mode
+ * USB devices have to use 'slave'-mode
+ * see also DIB3000MB_REG_ELECT_OUT_MODE
+ */
+#define DIB3000MB_REG_OUTPUT_MODE		(   169)
+#define DIB3000MB_OUTPUT_MODE_GATED_CLK		(     0)
+#define DIB3000MB_OUTPUT_MODE_CONT_CLK		(     1)
+#define DIB3000MB_OUTPUT_MODE_SERIAL		(     2)
+#define DIB3000MB_OUTPUT_MODE_DATA_DIVERSITY	(     5)
+#define DIB3000MB_OUTPUT_MODE_SLAVE			(     6)
+
+/* irq event mask */
+#define DIB3000MB_REG_IRQ_EVENT_MASK		(   170)
+#define DIB3000MB_IRQ_EVENT_MASK				(     0)
+
+/* filter coefficients */
+static u16 dib3000mb_reg_filter_coeffs[] = {
+	171, 172, 173, 174, 175, 176, 177, 178,
+	179, 180, 181, 182, 183, 184, 185, 186,
+	188, 189, 190, 191, 192, 194
+};
+
+static u16 dib3000mb_filter_coeffs[] = {
+	 226,  160,   29,
+	 979,  998,   19,
+	  22, 1019, 1006,
+	1022,   12,    6,
+	1017, 1017,    3,
+	   6,       1019,
+	1021,    2,    3,
+	   1,          0,
+};
+
+/*
+ * mobile algorithm (when you are moving with your device)
+ * but not faster than 90 km/h
+ */
+#define DIB3000MB_REG_MOBILE_ALGO		(   195)
+#define DIB3000MB_MOBILE_ALGO_ON			(     0)
+#define DIB3000MB_MOBILE_ALGO_OFF			(     1)
+
+/* multiple demodulators algorithm */
+#define DIB3000MB_REG_MULTI_DEMOD_MSB	(   206)
+#define DIB3000MB_REG_MULTI_DEMOD_LSB	(   207)
+
+/* terminator, no more demods */
+#define DIB3000MB_MULTI_DEMOD_MSB			( 32767)
+#define DIB3000MB_MULTI_DEMOD_LSB			(  4095)
+
+/* bring the device into a known  */
+#define DIB3000MB_REG_RESET_DEVICE		(  1024)
+#define DIB3000MB_RESET_DEVICE				(0x812c)
+#define DIB3000MB_RESET_DEVICE_RST			(     0)
+
+/* hardware clock configuration */
+#define DIB3000MB_REG_CLOCK				(  1027)
+#define DIB3000MB_CLOCK_DEFAULT				(0x9000)
+#define DIB3000MB_CLOCK_DIVERSITY			(0x92b0)
+
+/* power down config */
+#define DIB3000MB_REG_POWER_CONTROL		(  1028)
+#define DIB3000MB_POWER_DOWN				(     1)
+#define DIB3000MB_POWER_UP					(     0)
+
+/* electrical output mode */
+#define DIB3000MB_REG_ELECT_OUT_MODE	(  1029)
+#define DIB3000MB_ELECT_OUT_MODE_OFF		(     0)
+#define DIB3000MB_ELECT_OUT_MODE_ON			(     1)
+
+/* set the tuner i2c address */
+#define DIB3000MB_REG_TUNER				(  1089)
+
+/* monitoring registers (read only) */
+
+/* agc loop locked (size: 1) */
+#define DIB3000MB_REG_AGC_LOCK			(   324)
+
+/* agc power (size: 16) */
+#define DIB3000MB_REG_AGC_POWER			(   325)
+
+/* agc1 value (16) */
+#define DIB3000MB_REG_AGC1_VALUE		(   326)
+
+/* agc2 value (16) */
+#define DIB3000MB_REG_AGC2_VALUE		(   327)
+
+/* total RF power (16), can be used for signal strength */
+#define DIB3000MB_REG_RF_POWER			(   328)
+
+/* dds_frequency with offset (24) */
+#define DIB3000MB_REG_DDS_VALUE_MSB		(   339)
+#define DIB3000MB_REG_DDS_VALUE_LSB		(   340)
+
+/* timing offset signed (24) */
+#define DIB3000MB_REG_TIMING_OFFSET_MSB	(   341)
+#define DIB3000MB_REG_TIMING_OFFSET_LSB	(   342)
+
+/* fft start position (13) */
+#define DIB3000MB_REG_FFT_WINDOW_POS	(   353)
+
+/* carriers locked (1) */
+#define DIB3000MB_REG_CARRIER_LOCK		(   355)
+
+/* noise power (24) */
+#define DIB3000MB_REG_NOISE_POWER_MSB	(   372)
+#define DIB3000MB_REG_NOISE_POWER_LSB	(   373)
+
+#define DIB3000MB_REG_MOBILE_NOISE_MSB	(   374)
+#define DIB3000MB_REG_MOBILE_NOISE_LSB	(   375)
+
+/*
+ * signal power (16), this and the above can be
+ * used to calculate the signal/noise - ratio
+ */
+#define DIB3000MB_REG_SIGNAL_POWER		(   380)
+
+/* mer (24) */
+#define DIB3000MB_REG_MER_MSB			(   381)
+#define DIB3000MB_REG_MER_LSB			(   382)
+
+/*
+ * Transmission Parameter Signalling (TPS)
+ * the following registers can be used to get TPS-information.
+ * The values are according to the DVB-T standard.
+ */
+
+/* TPS locked (1) */
+#define DIB3000MB_REG_TPS_LOCK			(   394)
+
+/* QAM from TPS (2) (values according to DIB3000MB_REG_QAM) */
+#define DIB3000MB_REG_TPS_QAM			(   398)
+
+/* hierarchy from TPS (1) */
+#define DIB3000MB_REG_TPS_HRCH			(   399)
+
+/* alpha from TPS (3) (values according to DIB3000MB_REG_VIT_ALPHA) */
+#define DIB3000MB_REG_TPS_VIT_ALPHA		(   400)
+
+/* code rate high priority from TPS (3) (values according to DIB3000MB_FEC_*) */
+#define DIB3000MB_REG_TPS_CODE_RATE_HP	(   401)
+
+/* code rate low priority from TPS (3) if DIB3000MB_REG_TPS_VIT_ALPHA */
+#define DIB3000MB_REG_TPS_CODE_RATE_LP	(   402)
+
+/* guard time from TPS (2) (values according to DIB3000MB_REG_GUARD_TIME */
+#define DIB3000MB_REG_TPS_GUARD_TIME	(   403)
+
+/* fft size from TPS (2) (values according to DIB3000MB_REG_FFT) */
+#define DIB3000MB_REG_TPS_FFT			(   404)
+
+/* cell id from TPS (16) */
+#define DIB3000MB_REG_TPS_CELL_ID		(   406)
+
+/* TPS (68) */
+#define DIB3000MB_REG_TPS_1				(   408)
+#define DIB3000MB_REG_TPS_2				(   409)
+#define DIB3000MB_REG_TPS_3				(   410)
+#define DIB3000MB_REG_TPS_4				(   411)
+#define DIB3000MB_REG_TPS_5				(   412)
+
+/* bit error rate (before RS correction) (21) */
+#define DIB3000MB_REG_BER_MSB			(   414)
+#define DIB3000MB_REG_BER_LSB			(   415)
+
+/* packet error rate (uncorrected TS packets) (16) */
+#define DIB3000MB_REG_PACKET_ERROR_RATE	(   417)
+
+/* uncorrected packet count (16) */
+#define DIB3000MB_REG_UNC				(   420)
+
+/* viterbi locked (1) */
+#define DIB3000MB_REG_VIT_LCK			(   421)
+
+/* viterbi inidcator (16) */
+#define DIB3000MB_REG_VIT_INDICATOR		(   422)
+
+/* transport stream sync lock (1) */
+#define DIB3000MB_REG_TS_SYNC_LOCK		(   423)
+
+/* transport stream RS lock (1) */
+#define DIB3000MB_REG_TS_RS_LOCK		(   424)
+
+/* lock mask 0 value (1) */
+#define DIB3000MB_REG_LOCK0_VALUE		(   425)
+
+/* lock mask 1 value (1) */
+#define DIB3000MB_REG_LOCK1_VALUE		(   426)
+
+/* lock mask 2 value (1) */
+#define DIB3000MB_REG_LOCK2_VALUE		(   427)
+
+/* interrupt pending for auto search */
+#define DIB3000MB_REG_AS_IRQ_PENDING	(   434)
+
+#endif
diff --git a/drivers/media/dvb-frontends/dib3000mc.c b/drivers/media/dvb-frontends/dib3000mc.c
new file mode 100644
index 0000000..ffad181
--- /dev/null
+++ b/drivers/media/dvb-frontends/dib3000mc.c
@@ -0,0 +1,940 @@
+/*
+ * Driver for DiBcom DiB3000MC/P-demodulator.
+ *
+ * Copyright (C) 2004-7 DiBcom (http://www.dibcom.fr/)
+ * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
+ *
+ * This code is partially based on the previous dib3000mc.c .
+ *
+ * This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License as
+ *	published by the Free Software Foundation, version 2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+
+#include "dvb_frontend.h"
+
+#include "dib3000mc.h"
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
+
+static int buggy_sfn_workaround;
+module_param(buggy_sfn_workaround, int, 0644);
+MODULE_PARM_DESC(buggy_sfn_workaround, "Enable work-around for buggy SFNs (default: 0)");
+
+#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB3000MC/P:"); printk(args); printk("\n"); } } while (0)
+
+struct dib3000mc_state {
+	struct dvb_frontend demod;
+	struct dib3000mc_config *cfg;
+
+	u8 i2c_addr;
+	struct i2c_adapter *i2c_adap;
+
+	struct dibx000_i2c_master i2c_master;
+
+	u32 timf;
+
+	u32 current_bandwidth;
+
+	u16 dev_id;
+
+	u8 sfn_workaround_active :1;
+};
+
+static u16 dib3000mc_read_word(struct dib3000mc_state *state, u16 reg)
+{
+	u8 wb[2] = { (reg >> 8) | 0x80, reg & 0xff };
+	u8 rb[2];
+	struct i2c_msg msg[2] = {
+		{ .addr = state->i2c_addr >> 1, .flags = 0,        .buf = wb, .len = 2 },
+		{ .addr = state->i2c_addr >> 1, .flags = I2C_M_RD, .buf = rb, .len = 2 },
+	};
+
+	if (i2c_transfer(state->i2c_adap, msg, 2) != 2)
+		dprintk("i2c read error on %d\n",reg);
+
+	return (rb[0] << 8) | rb[1];
+}
+
+static int dib3000mc_write_word(struct dib3000mc_state *state, u16 reg, u16 val)
+{
+	u8 b[4] = {
+		(reg >> 8) & 0xff, reg & 0xff,
+		(val >> 8) & 0xff, val & 0xff,
+	};
+	struct i2c_msg msg = {
+		.addr = state->i2c_addr >> 1, .flags = 0, .buf = b, .len = 4
+	};
+	return i2c_transfer(state->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
+}
+
+static int dib3000mc_identify(struct dib3000mc_state *state)
+{
+	u16 value;
+	if ((value = dib3000mc_read_word(state, 1025)) != 0x01b3) {
+		dprintk("-E-  DiB3000MC/P: wrong Vendor ID (read=0x%x)\n",value);
+		return -EREMOTEIO;
+	}
+
+	value = dib3000mc_read_word(state, 1026);
+	if (value != 0x3001 && value != 0x3002) {
+		dprintk("-E-  DiB3000MC/P: wrong Device ID (%x)\n",value);
+		return -EREMOTEIO;
+	}
+	state->dev_id = value;
+
+	dprintk("-I-  found DiB3000MC/P: %x\n",state->dev_id);
+
+	return 0;
+}
+
+static int dib3000mc_set_timing(struct dib3000mc_state *state, s16 nfft, u32 bw, u8 update_offset)
+{
+	u32 timf;
+
+	if (state->timf == 0) {
+		timf = 1384402; // default value for 8MHz
+		if (update_offset)
+			msleep(200); // first time we do an update
+	} else
+		timf = state->timf;
+
+	timf *= (bw / 1000);
+
+	if (update_offset) {
+		s16 tim_offs = dib3000mc_read_word(state, 416);
+
+		if (tim_offs &  0x2000)
+			tim_offs -= 0x4000;
+
+		if (nfft == TRANSMISSION_MODE_2K)
+			tim_offs *= 4;
+
+		timf += tim_offs;
+		state->timf = timf / (bw / 1000);
+	}
+
+	dprintk("timf: %d\n", timf);
+
+	dib3000mc_write_word(state, 23, (u16) (timf >> 16));
+	dib3000mc_write_word(state, 24, (u16) (timf      ) & 0xffff);
+
+	return 0;
+}
+
+static int dib3000mc_setup_pwm_state(struct dib3000mc_state *state)
+{
+	u16 reg_51, reg_52 = state->cfg->agc->setup & 0xfefb;
+    if (state->cfg->pwm3_inversion) {
+		reg_51 =  (2 << 14) | (0 << 10) | (7 << 6) | (2 << 2) | (2 << 0);
+		reg_52 |= (1 << 2);
+	} else {
+		reg_51 = (2 << 14) | (4 << 10) | (7 << 6) | (2 << 2) | (2 << 0);
+		reg_52 |= (1 << 8);
+	}
+	dib3000mc_write_word(state, 51, reg_51);
+	dib3000mc_write_word(state, 52, reg_52);
+
+    if (state->cfg->use_pwm3)
+		dib3000mc_write_word(state, 245, (1 << 3) | (1 << 0));
+	else
+		dib3000mc_write_word(state, 245, 0);
+
+    dib3000mc_write_word(state, 1040, 0x3);
+	return 0;
+}
+
+static int dib3000mc_set_output_mode(struct dib3000mc_state *state, int mode)
+{
+	int    ret = 0;
+	u16 fifo_threshold = 1792;
+	u16 outreg = 0;
+	u16 outmode = 0;
+	u16 elecout = 1;
+	u16 smo_reg = dib3000mc_read_word(state, 206) & 0x0010; /* keep the pid_parse bit */
+
+	dprintk("-I-  Setting output mode for demod %p to %d\n",
+			&state->demod, mode);
+
+	switch (mode) {
+		case OUTMODE_HIGH_Z:  // disable
+			elecout = 0;
+			break;
+		case OUTMODE_MPEG2_PAR_GATED_CLK:   // STBs with parallel gated clock
+			outmode = 0;
+			break;
+		case OUTMODE_MPEG2_PAR_CONT_CLK:    // STBs with parallel continues clock
+			outmode = 1;
+			break;
+		case OUTMODE_MPEG2_SERIAL:          // STBs with serial input
+			outmode = 2;
+			break;
+		case OUTMODE_MPEG2_FIFO:            // e.g. USB feeding
+			elecout = 3;
+			/*ADDR @ 206 :
+			P_smo_error_discard  [1;6:6] = 0
+			P_smo_rs_discard     [1;5:5] = 0
+			P_smo_pid_parse      [1;4:4] = 0
+			P_smo_fifo_flush     [1;3:3] = 0
+			P_smo_mode           [2;2:1] = 11
+			P_smo_ovf_prot       [1;0:0] = 0
+			*/
+			smo_reg |= 3 << 1;
+			fifo_threshold = 512;
+			outmode = 5;
+			break;
+		case OUTMODE_DIVERSITY:
+			outmode = 4;
+			elecout = 1;
+			break;
+		default:
+			dprintk("Unhandled output_mode passed to be set for demod %p\n",&state->demod);
+			outmode = 0;
+			break;
+	}
+
+	if ((state->cfg->output_mpeg2_in_188_bytes))
+		smo_reg |= (1 << 5); // P_smo_rs_discard     [1;5:5] = 1
+
+	outreg = dib3000mc_read_word(state, 244) & 0x07FF;
+	outreg |= (outmode << 11);
+	ret |= dib3000mc_write_word(state,  244, outreg);
+	ret |= dib3000mc_write_word(state,  206, smo_reg);   /*smo_ mode*/
+	ret |= dib3000mc_write_word(state,  207, fifo_threshold); /* synchronous fread */
+	ret |= dib3000mc_write_word(state, 1040, elecout);         /* P_out_cfg */
+	return ret;
+}
+
+static int dib3000mc_set_bandwidth(struct dib3000mc_state *state, u32 bw)
+{
+	u16 bw_cfg[6] = { 0 };
+	u16 imp_bw_cfg[3] = { 0 };
+	u16 reg;
+
+/* settings here are for 27.7MHz */
+	switch (bw) {
+		case 8000:
+			bw_cfg[0] = 0x0019; bw_cfg[1] = 0x5c30; bw_cfg[2] = 0x0054; bw_cfg[3] = 0x88a0; bw_cfg[4] = 0x01a6; bw_cfg[5] = 0xab20;
+			imp_bw_cfg[0] = 0x04db; imp_bw_cfg[1] = 0x00db; imp_bw_cfg[2] = 0x00b7;
+			break;
+
+		case 7000:
+			bw_cfg[0] = 0x001c; bw_cfg[1] = 0xfba5; bw_cfg[2] = 0x0060; bw_cfg[3] = 0x9c25; bw_cfg[4] = 0x01e3; bw_cfg[5] = 0x0cb7;
+			imp_bw_cfg[0] = 0x04c0; imp_bw_cfg[1] = 0x00c0; imp_bw_cfg[2] = 0x00a0;
+			break;
+
+		case 6000:
+			bw_cfg[0] = 0x0021; bw_cfg[1] = 0xd040; bw_cfg[2] = 0x0070; bw_cfg[3] = 0xb62b; bw_cfg[4] = 0x0233; bw_cfg[5] = 0x8ed5;
+			imp_bw_cfg[0] = 0x04a5; imp_bw_cfg[1] = 0x00a5; imp_bw_cfg[2] = 0x0089;
+			break;
+
+		case 5000:
+			bw_cfg[0] = 0x0028; bw_cfg[1] = 0x9380; bw_cfg[2] = 0x0087; bw_cfg[3] = 0x4100; bw_cfg[4] = 0x02a4; bw_cfg[5] = 0x4500;
+			imp_bw_cfg[0] = 0x0489; imp_bw_cfg[1] = 0x0089; imp_bw_cfg[2] = 0x0072;
+			break;
+
+		default: return -EINVAL;
+	}
+
+	for (reg = 6; reg < 12; reg++)
+		dib3000mc_write_word(state, reg, bw_cfg[reg - 6]);
+	dib3000mc_write_word(state, 12, 0x0000);
+	dib3000mc_write_word(state, 13, 0x03e8);
+	dib3000mc_write_word(state, 14, 0x0000);
+	dib3000mc_write_word(state, 15, 0x03f2);
+	dib3000mc_write_word(state, 16, 0x0001);
+	dib3000mc_write_word(state, 17, 0xb0d0);
+	// P_sec_len
+	dib3000mc_write_word(state, 18, 0x0393);
+	dib3000mc_write_word(state, 19, 0x8700);
+
+	for (reg = 55; reg < 58; reg++)
+		dib3000mc_write_word(state, reg, imp_bw_cfg[reg - 55]);
+
+	// Timing configuration
+	dib3000mc_set_timing(state, TRANSMISSION_MODE_2K, bw, 0);
+
+	return 0;
+}
+
+static u16 impulse_noise_val[29] =
+
+{
+	0x38, 0x6d9, 0x3f28, 0x7a7, 0x3a74, 0x196, 0x32a, 0x48c, 0x3ffe, 0x7f3,
+	0x2d94, 0x76, 0x53d, 0x3ff8, 0x7e3, 0x3320, 0x76, 0x5b3, 0x3feb, 0x7d2,
+	0x365e, 0x76, 0x48c, 0x3ffe, 0x5b3, 0x3feb, 0x76, 0x0000, 0xd
+};
+
+static void dib3000mc_set_impulse_noise(struct dib3000mc_state *state, u8 mode, s16 nfft)
+{
+	u16 i;
+	for (i = 58; i < 87; i++)
+		dib3000mc_write_word(state, i, impulse_noise_val[i-58]);
+
+	if (nfft == TRANSMISSION_MODE_8K) {
+		dib3000mc_write_word(state, 58, 0x3b);
+		dib3000mc_write_word(state, 84, 0x00);
+		dib3000mc_write_word(state, 85, 0x8200);
+	}
+
+	dib3000mc_write_word(state, 34, 0x1294);
+	dib3000mc_write_word(state, 35, 0x1ff8);
+	if (mode == 1)
+		dib3000mc_write_word(state, 55, dib3000mc_read_word(state, 55) | (1 << 10));
+}
+
+static int dib3000mc_init(struct dvb_frontend *demod)
+{
+	struct dib3000mc_state *state = demod->demodulator_priv;
+	struct dibx000_agc_config *agc = state->cfg->agc;
+
+	// Restart Configuration
+	dib3000mc_write_word(state, 1027, 0x8000);
+	dib3000mc_write_word(state, 1027, 0x0000);
+
+	// power up the demod + mobility configuration
+	dib3000mc_write_word(state, 140, 0x0000);
+	dib3000mc_write_word(state, 1031, 0);
+
+	if (state->cfg->mobile_mode) {
+		dib3000mc_write_word(state, 139,  0x0000);
+		dib3000mc_write_word(state, 141,  0x0000);
+		dib3000mc_write_word(state, 175,  0x0002);
+		dib3000mc_write_word(state, 1032, 0x0000);
+	} else {
+		dib3000mc_write_word(state, 139,  0x0001);
+		dib3000mc_write_word(state, 141,  0x0000);
+		dib3000mc_write_word(state, 175,  0x0000);
+		dib3000mc_write_word(state, 1032, 0x012C);
+	}
+	dib3000mc_write_word(state, 1033, 0x0000);
+
+	// P_clk_cfg
+	dib3000mc_write_word(state, 1037, 0x3130);
+
+	// other configurations
+
+	// P_ctrl_sfreq
+	dib3000mc_write_word(state, 33, (5 << 0));
+	dib3000mc_write_word(state, 88, (1 << 10) | (0x10 << 0));
+
+	// Phase noise control
+	// P_fft_phacor_inh, P_fft_phacor_cpe, P_fft_powrange
+	dib3000mc_write_word(state, 99, (1 << 9) | (0x20 << 0));
+
+	if (state->cfg->phase_noise_mode == 0)
+		dib3000mc_write_word(state, 111, 0x00);
+	else
+		dib3000mc_write_word(state, 111, 0x02);
+
+	// P_agc_global
+	dib3000mc_write_word(state, 50, 0x8000);
+
+	// agc setup misc
+	dib3000mc_setup_pwm_state(state);
+
+	// P_agc_counter_lock
+	dib3000mc_write_word(state, 53, 0x87);
+	// P_agc_counter_unlock
+	dib3000mc_write_word(state, 54, 0x87);
+
+	/* agc */
+	dib3000mc_write_word(state, 36, state->cfg->max_time);
+	dib3000mc_write_word(state, 37, (state->cfg->agc_command1 << 13) | (state->cfg->agc_command2 << 12) | (0x1d << 0));
+	dib3000mc_write_word(state, 38, state->cfg->pwm3_value);
+	dib3000mc_write_word(state, 39, state->cfg->ln_adc_level);
+
+	// set_agc_loop_Bw
+	dib3000mc_write_word(state, 40, 0x0179);
+	dib3000mc_write_word(state, 41, 0x03f0);
+
+	dib3000mc_write_word(state, 42, agc->agc1_max);
+	dib3000mc_write_word(state, 43, agc->agc1_min);
+	dib3000mc_write_word(state, 44, agc->agc2_max);
+	dib3000mc_write_word(state, 45, agc->agc2_min);
+	dib3000mc_write_word(state, 46, (agc->agc1_pt1 << 8) | agc->agc1_pt2);
+	dib3000mc_write_word(state, 47, (agc->agc1_slope1 << 8) | agc->agc1_slope2);
+	dib3000mc_write_word(state, 48, (agc->agc2_pt1 << 8) | agc->agc2_pt2);
+	dib3000mc_write_word(state, 49, (agc->agc2_slope1 << 8) | agc->agc2_slope2);
+
+// Begin: TimeOut registers
+	// P_pha3_thres
+	dib3000mc_write_word(state, 110, 3277);
+	// P_timf_alpha = 6, P_corm_alpha = 6, P_corm_thres = 0x80
+	dib3000mc_write_word(state,  26, 0x6680);
+	// lock_mask0
+	dib3000mc_write_word(state, 1, 4);
+	// lock_mask1
+	dib3000mc_write_word(state, 2, 4);
+	// lock_mask2
+	dib3000mc_write_word(state, 3, 0x1000);
+	// P_search_maxtrial=1
+	dib3000mc_write_word(state, 5, 1);
+
+	dib3000mc_set_bandwidth(state, 8000);
+
+	// div_lock_mask
+	dib3000mc_write_word(state,  4, 0x814);
+
+	dib3000mc_write_word(state, 21, (1 << 9) | 0x164);
+	dib3000mc_write_word(state, 22, 0x463d);
+
+	// Spurious rm cfg
+	// P_cspu_regul, P_cspu_win_cut
+	dib3000mc_write_word(state, 120, 0x200f);
+	// P_adp_selec_monit
+	dib3000mc_write_word(state, 134, 0);
+
+	// Fec cfg
+	dib3000mc_write_word(state, 195, 0x10);
+
+	// diversity register: P_dvsy_sync_wait..
+	dib3000mc_write_word(state, 180, 0x2FF0);
+
+	// Impulse noise configuration
+	dib3000mc_set_impulse_noise(state, 0, TRANSMISSION_MODE_8K);
+
+	// output mode set-up
+	dib3000mc_set_output_mode(state, OUTMODE_HIGH_Z);
+
+	/* close the i2c-gate */
+	dib3000mc_write_word(state, 769, (1 << 7) );
+
+	return 0;
+}
+
+static int dib3000mc_sleep(struct dvb_frontend *demod)
+{
+	struct dib3000mc_state *state = demod->demodulator_priv;
+
+	dib3000mc_write_word(state, 1031, 0xFFFF);
+	dib3000mc_write_word(state, 1032, 0xFFFF);
+	dib3000mc_write_word(state, 1033, 0xFFF0);
+
+    return 0;
+}
+
+static void dib3000mc_set_adp_cfg(struct dib3000mc_state *state, s16 qam)
+{
+	u16 cfg[4] = { 0 },reg;
+	switch (qam) {
+		case QPSK:
+			cfg[0] = 0x099a; cfg[1] = 0x7fae; cfg[2] = 0x0333; cfg[3] = 0x7ff0;
+			break;
+		case QAM_16:
+			cfg[0] = 0x023d; cfg[1] = 0x7fdf; cfg[2] = 0x00a4; cfg[3] = 0x7ff0;
+			break;
+		case QAM_64:
+			cfg[0] = 0x0148; cfg[1] = 0x7ff0; cfg[2] = 0x00a4; cfg[3] = 0x7ff8;
+			break;
+	}
+	for (reg = 129; reg < 133; reg++)
+		dib3000mc_write_word(state, reg, cfg[reg - 129]);
+}
+
+static void dib3000mc_set_channel_cfg(struct dib3000mc_state *state,
+				      struct dtv_frontend_properties *ch, u16 seq)
+{
+	u16 value;
+	u32 bw = BANDWIDTH_TO_KHZ(ch->bandwidth_hz);
+
+	dib3000mc_set_bandwidth(state, bw);
+	dib3000mc_set_timing(state, ch->transmission_mode, bw, 0);
+
+//	if (boost)
+//		dib3000mc_write_word(state, 100, (11 << 6) + 6);
+//	else
+		dib3000mc_write_word(state, 100, (16 << 6) + 9);
+
+	dib3000mc_write_word(state, 1027, 0x0800);
+	dib3000mc_write_word(state, 1027, 0x0000);
+
+	//Default cfg isi offset adp
+	dib3000mc_write_word(state, 26,  0x6680);
+	dib3000mc_write_word(state, 29,  0x1273);
+	dib3000mc_write_word(state, 33,       5);
+	dib3000mc_set_adp_cfg(state, QAM_16);
+	dib3000mc_write_word(state, 133,  15564);
+
+	dib3000mc_write_word(state, 12 , 0x0);
+	dib3000mc_write_word(state, 13 , 0x3e8);
+	dib3000mc_write_word(state, 14 , 0x0);
+	dib3000mc_write_word(state, 15 , 0x3f2);
+
+	dib3000mc_write_word(state, 93,0);
+	dib3000mc_write_word(state, 94,0);
+	dib3000mc_write_word(state, 95,0);
+	dib3000mc_write_word(state, 96,0);
+	dib3000mc_write_word(state, 97,0);
+	dib3000mc_write_word(state, 98,0);
+
+	dib3000mc_set_impulse_noise(state, 0, ch->transmission_mode);
+
+	value = 0;
+	switch (ch->transmission_mode) {
+		case TRANSMISSION_MODE_2K: value |= (0 << 7); break;
+		default:
+		case TRANSMISSION_MODE_8K: value |= (1 << 7); break;
+	}
+	switch (ch->guard_interval) {
+		case GUARD_INTERVAL_1_32: value |= (0 << 5); break;
+		case GUARD_INTERVAL_1_16: value |= (1 << 5); break;
+		case GUARD_INTERVAL_1_4:  value |= (3 << 5); break;
+		default:
+		case GUARD_INTERVAL_1_8:  value |= (2 << 5); break;
+	}
+	switch (ch->modulation) {
+		case QPSK:  value |= (0 << 3); break;
+		case QAM_16: value |= (1 << 3); break;
+		default:
+		case QAM_64: value |= (2 << 3); break;
+	}
+	switch (HIERARCHY_1) {
+		case HIERARCHY_2: value |= 2; break;
+		case HIERARCHY_4: value |= 4; break;
+		default:
+		case HIERARCHY_1: value |= 1; break;
+	}
+	dib3000mc_write_word(state, 0, value);
+	dib3000mc_write_word(state, 5, (1 << 8) | ((seq & 0xf) << 4));
+
+	value = 0;
+	if (ch->hierarchy == 1)
+		value |= (1 << 4);
+	if (1 == 1)
+		value |= 1;
+	switch ((ch->hierarchy == 0 || 1 == 1) ? ch->code_rate_HP : ch->code_rate_LP) {
+		case FEC_2_3: value |= (2 << 1); break;
+		case FEC_3_4: value |= (3 << 1); break;
+		case FEC_5_6: value |= (5 << 1); break;
+		case FEC_7_8: value |= (7 << 1); break;
+		default:
+		case FEC_1_2: value |= (1 << 1); break;
+	}
+	dib3000mc_write_word(state, 181, value);
+
+	// diversity synchro delay add 50% SFN margin
+	switch (ch->transmission_mode) {
+		case TRANSMISSION_MODE_8K: value = 256; break;
+		case TRANSMISSION_MODE_2K:
+		default: value = 64; break;
+	}
+	switch (ch->guard_interval) {
+		case GUARD_INTERVAL_1_16: value *= 2; break;
+		case GUARD_INTERVAL_1_8:  value *= 4; break;
+		case GUARD_INTERVAL_1_4:  value *= 8; break;
+		default:
+		case GUARD_INTERVAL_1_32: value *= 1; break;
+	}
+	value <<= 4;
+	value |= dib3000mc_read_word(state, 180) & 0x000f;
+	dib3000mc_write_word(state, 180, value);
+
+	// restart demod
+	value = dib3000mc_read_word(state, 0);
+	dib3000mc_write_word(state, 0, value | (1 << 9));
+	dib3000mc_write_word(state, 0, value);
+
+	msleep(30);
+
+	dib3000mc_set_impulse_noise(state, state->cfg->impulse_noise_mode, ch->transmission_mode);
+}
+
+static int dib3000mc_autosearch_start(struct dvb_frontend *demod)
+{
+	struct dtv_frontend_properties *chan = &demod->dtv_property_cache;
+	struct dib3000mc_state *state = demod->demodulator_priv;
+	u16 reg;
+//	u32 val;
+	struct dtv_frontend_properties schan;
+
+	schan = *chan;
+
+	/* TODO what is that ? */
+
+	/* a channel for autosearch */
+	schan.transmission_mode = TRANSMISSION_MODE_8K;
+	schan.guard_interval = GUARD_INTERVAL_1_32;
+	schan.modulation = QAM_64;
+	schan.code_rate_HP = FEC_2_3;
+	schan.code_rate_LP = FEC_2_3;
+	schan.hierarchy = 0;
+
+	dib3000mc_set_channel_cfg(state, &schan, 11);
+
+	reg = dib3000mc_read_word(state, 0);
+	dib3000mc_write_word(state, 0, reg | (1 << 8));
+	dib3000mc_read_word(state, 511);
+	dib3000mc_write_word(state, 0, reg);
+
+	return 0;
+}
+
+static int dib3000mc_autosearch_is_irq(struct dvb_frontend *demod)
+{
+	struct dib3000mc_state *state = demod->demodulator_priv;
+	u16 irq_pending = dib3000mc_read_word(state, 511);
+
+	if (irq_pending & 0x1) // failed
+		return 1;
+
+	if (irq_pending & 0x2) // succeeded
+		return 2;
+
+	return 0; // still pending
+}
+
+static int dib3000mc_tune(struct dvb_frontend *demod)
+{
+	struct dtv_frontend_properties *ch = &demod->dtv_property_cache;
+	struct dib3000mc_state *state = demod->demodulator_priv;
+
+	// ** configure demod **
+	dib3000mc_set_channel_cfg(state, ch, 0);
+
+	// activates isi
+	if (state->sfn_workaround_active) {
+		dprintk("SFN workaround is active\n");
+		dib3000mc_write_word(state, 29, 0x1273);
+		dib3000mc_write_word(state, 108, 0x4000); // P_pha3_force_pha_shift
+	} else {
+		dib3000mc_write_word(state, 29, 0x1073);
+		dib3000mc_write_word(state, 108, 0x0000); // P_pha3_force_pha_shift
+	}
+
+	dib3000mc_set_adp_cfg(state, (u8)ch->modulation);
+	if (ch->transmission_mode == TRANSMISSION_MODE_8K) {
+		dib3000mc_write_word(state, 26, 38528);
+		dib3000mc_write_word(state, 33, 8);
+	} else {
+		dib3000mc_write_word(state, 26, 30336);
+		dib3000mc_write_word(state, 33, 6);
+	}
+
+	if (dib3000mc_read_word(state, 509) & 0x80)
+		dib3000mc_set_timing(state, ch->transmission_mode,
+				     BANDWIDTH_TO_KHZ(ch->bandwidth_hz), 1);
+
+	return 0;
+}
+
+struct i2c_adapter * dib3000mc_get_tuner_i2c_master(struct dvb_frontend *demod, int gating)
+{
+	struct dib3000mc_state *st = demod->demodulator_priv;
+	return dibx000_get_i2c_adapter(&st->i2c_master, DIBX000_I2C_INTERFACE_TUNER, gating);
+}
+
+EXPORT_SYMBOL(dib3000mc_get_tuner_i2c_master);
+
+static int dib3000mc_get_frontend(struct dvb_frontend* fe)
+{
+	struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
+	struct dib3000mc_state *state = fe->demodulator_priv;
+	u16 tps = dib3000mc_read_word(state,458);
+
+	fep->inversion = INVERSION_AUTO;
+
+	fep->bandwidth_hz = state->current_bandwidth;
+
+	switch ((tps >> 8) & 0x1) {
+		case 0: fep->transmission_mode = TRANSMISSION_MODE_2K; break;
+		case 1: fep->transmission_mode = TRANSMISSION_MODE_8K; break;
+	}
+
+	switch (tps & 0x3) {
+		case 0: fep->guard_interval = GUARD_INTERVAL_1_32; break;
+		case 1: fep->guard_interval = GUARD_INTERVAL_1_16; break;
+		case 2: fep->guard_interval = GUARD_INTERVAL_1_8; break;
+		case 3: fep->guard_interval = GUARD_INTERVAL_1_4; break;
+	}
+
+	switch ((tps >> 13) & 0x3) {
+		case 0: fep->modulation = QPSK; break;
+		case 1: fep->modulation = QAM_16; break;
+		case 2:
+		default: fep->modulation = QAM_64; break;
+	}
+
+	/* as long as the frontend_param structure is fixed for hierarchical transmission I refuse to use it */
+	/* (tps >> 12) & 0x1 == hrch is used, (tps >> 9) & 0x7 == alpha */
+
+	fep->hierarchy = HIERARCHY_NONE;
+	switch ((tps >> 5) & 0x7) {
+		case 1: fep->code_rate_HP = FEC_1_2; break;
+		case 2: fep->code_rate_HP = FEC_2_3; break;
+		case 3: fep->code_rate_HP = FEC_3_4; break;
+		case 5: fep->code_rate_HP = FEC_5_6; break;
+		case 7:
+		default: fep->code_rate_HP = FEC_7_8; break;
+
+	}
+
+	switch ((tps >> 2) & 0x7) {
+		case 1: fep->code_rate_LP = FEC_1_2; break;
+		case 2: fep->code_rate_LP = FEC_2_3; break;
+		case 3: fep->code_rate_LP = FEC_3_4; break;
+		case 5: fep->code_rate_LP = FEC_5_6; break;
+		case 7:
+		default: fep->code_rate_LP = FEC_7_8; break;
+	}
+
+	return 0;
+}
+
+static int dib3000mc_set_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
+	struct dib3000mc_state *state = fe->demodulator_priv;
+	int ret;
+
+	dib3000mc_set_output_mode(state, OUTMODE_HIGH_Z);
+
+	state->current_bandwidth = fep->bandwidth_hz;
+	dib3000mc_set_bandwidth(state, BANDWIDTH_TO_KHZ(fep->bandwidth_hz));
+
+	/* maybe the parameter has been changed */
+	state->sfn_workaround_active = buggy_sfn_workaround;
+
+	if (fe->ops.tuner_ops.set_params) {
+		fe->ops.tuner_ops.set_params(fe);
+		msleep(100);
+	}
+
+	if (fep->transmission_mode  == TRANSMISSION_MODE_AUTO ||
+	    fep->guard_interval == GUARD_INTERVAL_AUTO ||
+	    fep->modulation     == QAM_AUTO ||
+	    fep->code_rate_HP   == FEC_AUTO) {
+		int i = 1000, found;
+
+		dib3000mc_autosearch_start(fe);
+		do {
+			msleep(1);
+			found = dib3000mc_autosearch_is_irq(fe);
+		} while (found == 0 && i--);
+
+		dprintk("autosearch returns: %d\n",found);
+		if (found == 0 || found == 1)
+			return 0; // no channel found
+
+		dib3000mc_get_frontend(fe);
+	}
+
+	ret = dib3000mc_tune(fe);
+
+	/* make this a config parameter */
+	dib3000mc_set_output_mode(state, OUTMODE_MPEG2_FIFO);
+	return ret;
+}
+
+static int dib3000mc_read_status(struct dvb_frontend *fe, fe_status_t *stat)
+{
+	struct dib3000mc_state *state = fe->demodulator_priv;
+	u16 lock = dib3000mc_read_word(state, 509);
+
+	*stat = 0;
+
+	if (lock & 0x8000)
+		*stat |= FE_HAS_SIGNAL;
+	if (lock & 0x3000)
+		*stat |= FE_HAS_CARRIER;
+	if (lock & 0x0100)
+		*stat |= FE_HAS_VITERBI;
+	if (lock & 0x0010)
+		*stat |= FE_HAS_SYNC;
+	if (lock & 0x0008)
+		*stat |= FE_HAS_LOCK;
+
+	return 0;
+}
+
+static int dib3000mc_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+	struct dib3000mc_state *state = fe->demodulator_priv;
+	*ber = (dib3000mc_read_word(state, 500) << 16) | dib3000mc_read_word(state, 501);
+	return 0;
+}
+
+static int dib3000mc_read_unc_blocks(struct dvb_frontend *fe, u32 *unc)
+{
+	struct dib3000mc_state *state = fe->demodulator_priv;
+	*unc = dib3000mc_read_word(state, 508);
+	return 0;
+}
+
+static int dib3000mc_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
+{
+	struct dib3000mc_state *state = fe->demodulator_priv;
+	u16 val = dib3000mc_read_word(state, 392);
+	*strength = 65535 - val;
+	return 0;
+}
+
+static int dib3000mc_read_snr(struct dvb_frontend* fe, u16 *snr)
+{
+	*snr = 0x0000;
+	return 0;
+}
+
+static int dib3000mc_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
+{
+	tune->min_delay_ms = 1000;
+	return 0;
+}
+
+static void dib3000mc_release(struct dvb_frontend *fe)
+{
+	struct dib3000mc_state *state = fe->demodulator_priv;
+	dibx000_exit_i2c_master(&state->i2c_master);
+	kfree(state);
+}
+
+int dib3000mc_pid_control(struct dvb_frontend *fe, int index, int pid,int onoff)
+{
+	struct dib3000mc_state *state = fe->demodulator_priv;
+	dib3000mc_write_word(state, 212 + index,  onoff ? (1 << 13) | pid : 0);
+	return 0;
+}
+EXPORT_SYMBOL(dib3000mc_pid_control);
+
+int dib3000mc_pid_parse(struct dvb_frontend *fe, int onoff)
+{
+	struct dib3000mc_state *state = fe->demodulator_priv;
+	u16 tmp = dib3000mc_read_word(state, 206) & ~(1 << 4);
+	tmp |= (onoff << 4);
+	return dib3000mc_write_word(state, 206, tmp);
+}
+EXPORT_SYMBOL(dib3000mc_pid_parse);
+
+void dib3000mc_set_config(struct dvb_frontend *fe, struct dib3000mc_config *cfg)
+{
+	struct dib3000mc_state *state = fe->demodulator_priv;
+	state->cfg = cfg;
+}
+EXPORT_SYMBOL(dib3000mc_set_config);
+
+int dib3000mc_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib3000mc_config cfg[])
+{
+	struct dib3000mc_state *dmcst;
+	int k;
+	u8 new_addr;
+
+	static u8 DIB3000MC_I2C_ADDRESS[] = {20,22,24,26};
+
+	dmcst = kzalloc(sizeof(struct dib3000mc_state), GFP_KERNEL);
+	if (dmcst == NULL)
+		return -ENOMEM;
+
+	dmcst->i2c_adap = i2c;
+
+	for (k = no_of_demods-1; k >= 0; k--) {
+		dmcst->cfg = &cfg[k];
+
+		/* designated i2c address */
+		new_addr          = DIB3000MC_I2C_ADDRESS[k];
+		dmcst->i2c_addr = new_addr;
+		if (dib3000mc_identify(dmcst) != 0) {
+			dmcst->i2c_addr = default_addr;
+			if (dib3000mc_identify(dmcst) != 0) {
+				dprintk("-E-  DiB3000P/MC #%d: not identified\n", k);
+				kfree(dmcst);
+				return -ENODEV;
+			}
+		}
+
+		dib3000mc_set_output_mode(dmcst, OUTMODE_MPEG2_PAR_CONT_CLK);
+
+		// set new i2c address and force divstr (Bit 1) to value 0 (Bit 0)
+		dib3000mc_write_word(dmcst, 1024, (new_addr << 3) | 0x1);
+		dmcst->i2c_addr = new_addr;
+	}
+
+	for (k = 0; k < no_of_demods; k++) {
+		dmcst->cfg = &cfg[k];
+		dmcst->i2c_addr = DIB3000MC_I2C_ADDRESS[k];
+
+		dib3000mc_write_word(dmcst, 1024, dmcst->i2c_addr << 3);
+
+		/* turn off data output */
+		dib3000mc_set_output_mode(dmcst, OUTMODE_HIGH_Z);
+	}
+
+	kfree(dmcst);
+	return 0;
+}
+EXPORT_SYMBOL(dib3000mc_i2c_enumeration);
+
+static struct dvb_frontend_ops dib3000mc_ops;
+
+struct dvb_frontend * dib3000mc_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib3000mc_config *cfg)
+{
+	struct dvb_frontend *demod;
+	struct dib3000mc_state *st;
+	st = kzalloc(sizeof(struct dib3000mc_state), GFP_KERNEL);
+	if (st == NULL)
+		return NULL;
+
+	st->cfg = cfg;
+	st->i2c_adap = i2c_adap;
+	st->i2c_addr = i2c_addr;
+
+	demod                   = &st->demod;
+	demod->demodulator_priv = st;
+	memcpy(&st->demod.ops, &dib3000mc_ops, sizeof(struct dvb_frontend_ops));
+
+	if (dib3000mc_identify(st) != 0)
+		goto error;
+
+	dibx000_init_i2c_master(&st->i2c_master, DIB3000MC, st->i2c_adap, st->i2c_addr);
+
+	dib3000mc_write_word(st, 1037, 0x3130);
+
+	return demod;
+
+error:
+	kfree(st);
+	return NULL;
+}
+EXPORT_SYMBOL(dib3000mc_attach);
+
+static struct dvb_frontend_ops dib3000mc_ops = {
+	.delsys = { SYS_DVBT },
+	.info = {
+		.name = "DiBcom 3000MC/P",
+		.frequency_min      = 44250000,
+		.frequency_max      = 867250000,
+		.frequency_stepsize = 62500,
+		.caps = FE_CAN_INVERSION_AUTO |
+			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_FEC_AUTO |
+			FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
+			FE_CAN_TRANSMISSION_MODE_AUTO |
+			FE_CAN_GUARD_INTERVAL_AUTO |
+			FE_CAN_RECOVER |
+			FE_CAN_HIERARCHY_AUTO,
+	},
+
+	.release              = dib3000mc_release,
+
+	.init                 = dib3000mc_init,
+	.sleep                = dib3000mc_sleep,
+
+	.set_frontend         = dib3000mc_set_frontend,
+	.get_tune_settings    = dib3000mc_fe_get_tune_settings,
+	.get_frontend         = dib3000mc_get_frontend,
+
+	.read_status          = dib3000mc_read_status,
+	.read_ber             = dib3000mc_read_ber,
+	.read_signal_strength = dib3000mc_read_signal_strength,
+	.read_snr             = dib3000mc_read_snr,
+	.read_ucblocks        = dib3000mc_read_unc_blocks,
+};
+
+MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
+MODULE_DESCRIPTION("Driver for the DiBcom 3000MC/P COFDM demodulator");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb-frontends/dib3000mc.h b/drivers/media/dvb-frontends/dib3000mc.h
new file mode 100644
index 0000000..d75ffad
--- /dev/null
+++ b/drivers/media/dvb-frontends/dib3000mc.h
@@ -0,0 +1,85 @@
+/*
+ * Driver for DiBcom DiB3000MC/P-demodulator.
+ *
+ * Copyright (C) 2004-6 DiBcom (http://www.dibcom.fr/)
+ * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher\@desy.de)
+ *
+ * This code is partially based on the previous dib3000mc.c .
+ *
+ * This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License as
+ *	published by the Free Software Foundation, version 2.
+ */
+#ifndef DIB3000MC_H
+#define DIB3000MC_H
+
+#include "dibx000_common.h"
+
+struct dib3000mc_config {
+	struct dibx000_agc_config *agc;
+
+	u8 phase_noise_mode;
+	u8 impulse_noise_mode;
+
+	u8  pwm3_inversion;
+	u8  use_pwm3;
+	u16 pwm3_value;
+
+	u16 max_time;
+	u16 ln_adc_level;
+
+	u8 agc_command1 :1;
+	u8 agc_command2 :1;
+
+	u8 mobile_mode;
+
+	u8 output_mpeg2_in_188_bytes;
+};
+
+#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);
+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)
+{
+	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_pid_control(struct dvb_frontend *fe, int index, int pid,int onoff);
+extern int dib3000mc_pid_parse(struct dvb_frontend *fe, int onoff);
+
+extern void dib3000mc_set_config(struct dvb_frontend *, struct dib3000mc_config *);
+
+#endif
diff --git a/drivers/media/dvb-frontends/dib7000m.c b/drivers/media/dvb-frontends/dib7000m.c
new file mode 100644
index 0000000..148bf79
--- /dev/null
+++ b/drivers/media/dvb-frontends/dib7000m.c
@@ -0,0 +1,1473 @@
+/*
+ * Linux-DVB Driver for DiBcom's DiB7000M and
+ *              first generation DiB7000P-demodulator-family.
+ *
+ * Copyright (C) 2005-7 DiBcom (http://www.dibcom.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, version 2.
+ */
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+
+#include "dvb_frontend.h"
+
+#include "dib7000m.h"
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
+
+#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB7000M: "); printk(args); printk("\n"); } } while (0)
+
+struct dib7000m_state {
+	struct dvb_frontend demod;
+    struct dib7000m_config cfg;
+
+	u8 i2c_addr;
+	struct i2c_adapter   *i2c_adap;
+
+	struct dibx000_i2c_master i2c_master;
+
+/* offset is 1 in case of the 7000MC */
+	u8 reg_offs;
+
+	u16 wbd_ref;
+
+	u8 current_band;
+	u32 current_bandwidth;
+	struct dibx000_agc_config *current_agc;
+	u32 timf;
+	u32 timf_default;
+	u32 internal_clk;
+
+	u8 div_force_off : 1;
+	u8 div_state : 1;
+	u16 div_sync_wait;
+
+	u16 revision;
+
+	u8 agc_state;
+
+	/* for the I2C transfer */
+	struct i2c_msg msg[2];
+	u8 i2c_write_buffer[4];
+	u8 i2c_read_buffer[2];
+	struct mutex i2c_buffer_lock;
+};
+
+enum dib7000m_power_mode {
+	DIB7000M_POWER_ALL = 0,
+
+	DIB7000M_POWER_NO,
+	DIB7000M_POWER_INTERF_ANALOG_AGC,
+	DIB7000M_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD,
+	DIB7000M_POWER_COR4_CRY_ESRAM_MOUT_NUD,
+	DIB7000M_POWER_INTERFACE_ONLY,
+};
+
+static u16 dib7000m_read_word(struct dib7000m_state *state, u16 reg)
+{
+	u16 ret;
+
+	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
+		dprintk("could not acquire lock");
+		return 0;
+	}
+
+	state->i2c_write_buffer[0] = (reg >> 8) | 0x80;
+	state->i2c_write_buffer[1] = reg & 0xff;
+
+	memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
+	state->msg[0].addr = state->i2c_addr >> 1;
+	state->msg[0].flags = 0;
+	state->msg[0].buf = state->i2c_write_buffer;
+	state->msg[0].len = 2;
+	state->msg[1].addr = state->i2c_addr >> 1;
+	state->msg[1].flags = I2C_M_RD;
+	state->msg[1].buf = state->i2c_read_buffer;
+	state->msg[1].len = 2;
+
+	if (i2c_transfer(state->i2c_adap, state->msg, 2) != 2)
+		dprintk("i2c read error on %d",reg);
+
+	ret = (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
+	mutex_unlock(&state->i2c_buffer_lock);
+
+	return ret;
+}
+
+static int dib7000m_write_word(struct dib7000m_state *state, u16 reg, u16 val)
+{
+	int ret;
+
+	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
+		dprintk("could not acquire lock");
+		return -EINVAL;
+	}
+
+	state->i2c_write_buffer[0] = (reg >> 8) & 0xff;
+	state->i2c_write_buffer[1] = reg & 0xff;
+	state->i2c_write_buffer[2] = (val >> 8) & 0xff;
+	state->i2c_write_buffer[3] = val & 0xff;
+
+	memset(&state->msg[0], 0, sizeof(struct i2c_msg));
+	state->msg[0].addr = state->i2c_addr >> 1;
+	state->msg[0].flags = 0;
+	state->msg[0].buf = state->i2c_write_buffer;
+	state->msg[0].len = 4;
+
+	ret = (i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ?
+			-EREMOTEIO : 0);
+	mutex_unlock(&state->i2c_buffer_lock);
+	return ret;
+}
+static void dib7000m_write_tab(struct dib7000m_state *state, u16 *buf)
+{
+	u16 l = 0, r, *n;
+	n = buf;
+	l = *n++;
+	while (l) {
+		r = *n++;
+
+		if (state->reg_offs && (r >= 112 && r <= 331)) // compensate for 7000MC
+			r++;
+
+		do {
+			dib7000m_write_word(state, r, *n++);
+			r++;
+		} while (--l);
+		l = *n++;
+	}
+}
+
+static int dib7000m_set_output_mode(struct dib7000m_state *state, int mode)
+{
+	int    ret = 0;
+	u16 outreg, fifo_threshold, smo_mode,
+		sram = 0x0005; /* by default SRAM output is disabled */
+
+	outreg = 0;
+	fifo_threshold = 1792;
+	smo_mode = (dib7000m_read_word(state, 294 + state->reg_offs) & 0x0010) | (1 << 1);
+
+	dprintk( "setting output mode for demod %p to %d", &state->demod, mode);
+
+	switch (mode) {
+		case OUTMODE_MPEG2_PAR_GATED_CLK:   // STBs with parallel gated clock
+			outreg = (1 << 10);  /* 0x0400 */
+			break;
+		case OUTMODE_MPEG2_PAR_CONT_CLK:    // STBs with parallel continues clock
+			outreg = (1 << 10) | (1 << 6); /* 0x0440 */
+			break;
+		case OUTMODE_MPEG2_SERIAL:          // STBs with serial input
+			outreg = (1 << 10) | (2 << 6) | (0 << 1); /* 0x0482 */
+			break;
+		case OUTMODE_DIVERSITY:
+			if (state->cfg.hostbus_diversity)
+				outreg = (1 << 10) | (4 << 6); /* 0x0500 */
+			else
+				sram   |= 0x0c00;
+			break;
+		case OUTMODE_MPEG2_FIFO:            // e.g. USB feeding
+			smo_mode |= (3 << 1);
+			fifo_threshold = 512;
+			outreg = (1 << 10) | (5 << 6);
+			break;
+		case OUTMODE_HIGH_Z:  // disable
+			outreg = 0;
+			break;
+		default:
+			dprintk( "Unhandled output_mode passed to be set for demod %p",&state->demod);
+			break;
+	}
+
+	if (state->cfg.output_mpeg2_in_188_bytes)
+		smo_mode |= (1 << 5) ;
+
+	ret |= dib7000m_write_word(state,  294 + state->reg_offs, smo_mode);
+	ret |= dib7000m_write_word(state,  295 + state->reg_offs, fifo_threshold); /* synchronous fread */
+	ret |= dib7000m_write_word(state, 1795, outreg);
+	ret |= dib7000m_write_word(state, 1805, sram);
+
+	if (state->revision == 0x4003) {
+		u16 clk_cfg1 = dib7000m_read_word(state, 909) & 0xfffd;
+		if (mode == OUTMODE_DIVERSITY)
+			clk_cfg1 |= (1 << 1); // P_O_CLK_en
+		dib7000m_write_word(state, 909, clk_cfg1);
+	}
+	return ret;
+}
+
+static void dib7000m_set_power_mode(struct dib7000m_state *state, enum dib7000m_power_mode mode)
+{
+	/* by default everything is going to be powered off */
+	u16 reg_903 = 0xffff, reg_904 = 0xffff, reg_905 = 0xffff, reg_906  = 0x3fff;
+	u8  offset = 0;
+
+	/* now, depending on the requested mode, we power on */
+	switch (mode) {
+		/* power up everything in the demod */
+		case DIB7000M_POWER_ALL:
+			reg_903 = 0x0000; reg_904 = 0x0000; reg_905 = 0x0000; reg_906 = 0x0000;
+			break;
+
+		/* just leave power on the control-interfaces: GPIO and (I2C or SDIO or SRAM) */
+		case DIB7000M_POWER_INTERFACE_ONLY: /* TODO power up either SDIO or I2C or SRAM */
+			reg_905 &= ~((1 << 7) | (1 << 6) | (1 << 5) | (1 << 2));
+			break;
+
+		case DIB7000M_POWER_INTERF_ANALOG_AGC:
+			reg_903 &= ~((1 << 15) | (1 << 14) | (1 << 11) | (1 << 10));
+			reg_905 &= ~((1 << 7) | (1 << 6) | (1 << 5) | (1 << 4) | (1 << 2));
+			reg_906 &= ~((1 << 0));
+			break;
+
+		case DIB7000M_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD:
+			reg_903 = 0x0000; reg_904 = 0x801f; reg_905 = 0x0000; reg_906 = 0x0000;
+			break;
+
+		case DIB7000M_POWER_COR4_CRY_ESRAM_MOUT_NUD:
+			reg_903 = 0x0000; reg_904 = 0x8000; reg_905 = 0x010b; reg_906 = 0x0000;
+			break;
+		case DIB7000M_POWER_NO:
+			break;
+	}
+
+	/* always power down unused parts */
+	if (!state->cfg.mobile_mode)
+		reg_904 |= (1 << 7) | (1 << 6) | (1 << 4) | (1 << 2) | (1 << 1);
+
+	/* P_sdio_select_clk = 0 on MC and after*/
+	if (state->revision != 0x4000)
+		reg_906 <<= 1;
+
+	if (state->revision == 0x4003)
+		offset = 1;
+
+	dib7000m_write_word(state, 903 + offset, reg_903);
+	dib7000m_write_word(state, 904 + offset, reg_904);
+	dib7000m_write_word(state, 905 + offset, reg_905);
+	dib7000m_write_word(state, 906 + offset, reg_906);
+}
+
+static int dib7000m_set_adc_state(struct dib7000m_state *state, enum dibx000_adc_states no)
+{
+	int ret = 0;
+	u16 reg_913 = dib7000m_read_word(state, 913),
+	       reg_914 = dib7000m_read_word(state, 914);
+
+	switch (no) {
+		case DIBX000_SLOW_ADC_ON:
+			reg_914 |= (1 << 1) | (1 << 0);
+			ret |= dib7000m_write_word(state, 914, reg_914);
+			reg_914 &= ~(1 << 1);
+			break;
+
+		case DIBX000_SLOW_ADC_OFF:
+			reg_914 |=  (1 << 1) | (1 << 0);
+			break;
+
+		case DIBX000_ADC_ON:
+			if (state->revision == 0x4000) { // workaround for PA/MA
+				// power-up ADC
+				dib7000m_write_word(state, 913, 0);
+				dib7000m_write_word(state, 914, reg_914 & 0x3);
+				// power-down bandgag
+				dib7000m_write_word(state, 913, (1 << 15));
+				dib7000m_write_word(state, 914, reg_914 & 0x3);
+			}
+
+			reg_913 &= 0x0fff;
+			reg_914 &= 0x0003;
+			break;
+
+		case DIBX000_ADC_OFF: // leave the VBG voltage on
+			reg_913 |= (1 << 14) | (1 << 13) | (1 << 12);
+			reg_914 |= (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2);
+			break;
+
+		case DIBX000_VBG_ENABLE:
+			reg_913 &= ~(1 << 15);
+			break;
+
+		case DIBX000_VBG_DISABLE:
+			reg_913 |= (1 << 15);
+			break;
+
+		default:
+			break;
+	}
+
+//	dprintk( "913: %x, 914: %x", reg_913, reg_914);
+	ret |= dib7000m_write_word(state, 913, reg_913);
+	ret |= dib7000m_write_word(state, 914, reg_914);
+
+	return ret;
+}
+
+static int dib7000m_set_bandwidth(struct dib7000m_state *state, u32 bw)
+{
+	u32 timf;
+
+	if (!bw)
+		bw = 8000;
+
+	// store the current bandwidth for later use
+	state->current_bandwidth = bw;
+
+	if (state->timf == 0) {
+		dprintk( "using default timf");
+		timf = state->timf_default;
+	} else {
+		dprintk( "using updated timf");
+		timf = state->timf;
+	}
+
+	timf = timf * (bw / 50) / 160;
+
+	dib7000m_write_word(state, 23, (u16) ((timf >> 16) & 0xffff));
+	dib7000m_write_word(state, 24, (u16) ((timf      ) & 0xffff));
+
+	return 0;
+}
+
+static int dib7000m_set_diversity_in(struct dvb_frontend *demod, int onoff)
+{
+	struct dib7000m_state *state = demod->demodulator_priv;
+
+	if (state->div_force_off) {
+		dprintk( "diversity combination deactivated - forced by COFDM parameters");
+		onoff = 0;
+	}
+	state->div_state = (u8)onoff;
+
+	if (onoff) {
+		dib7000m_write_word(state, 263 + state->reg_offs, 6);
+		dib7000m_write_word(state, 264 + state->reg_offs, 6);
+		dib7000m_write_word(state, 266 + state->reg_offs, (state->div_sync_wait << 4) | (1 << 2) | (2 << 0));
+	} else {
+		dib7000m_write_word(state, 263 + state->reg_offs, 1);
+		dib7000m_write_word(state, 264 + state->reg_offs, 0);
+		dib7000m_write_word(state, 266 + state->reg_offs, 0);
+	}
+
+	return 0;
+}
+
+static int dib7000m_sad_calib(struct dib7000m_state *state)
+{
+
+/* internal */
+//	dib7000m_write_word(state, 928, (3 << 14) | (1 << 12) | (524 << 0)); // sampling clock of the SAD is writting in set_bandwidth
+	dib7000m_write_word(state, 929, (0 << 1) | (0 << 0));
+	dib7000m_write_word(state, 930, 776); // 0.625*3.3 / 4096
+
+	/* do the calibration */
+	dib7000m_write_word(state, 929, (1 << 0));
+	dib7000m_write_word(state, 929, (0 << 0));
+
+	msleep(1);
+
+	return 0;
+}
+
+static void dib7000m_reset_pll_common(struct dib7000m_state *state, const struct dibx000_bandwidth_config *bw)
+{
+	dib7000m_write_word(state, 18, (u16) (((bw->internal*1000) >> 16) & 0xffff));
+	dib7000m_write_word(state, 19, (u16) ( (bw->internal*1000)        & 0xffff));
+	dib7000m_write_word(state, 21, (u16) ( (bw->ifreq          >> 16) & 0xffff));
+	dib7000m_write_word(state, 22, (u16) (  bw->ifreq                 & 0xffff));
+
+	dib7000m_write_word(state, 928, bw->sad_cfg);
+}
+
+static void dib7000m_reset_pll(struct dib7000m_state *state)
+{
+	const struct dibx000_bandwidth_config *bw = state->cfg.bw;
+	u16 reg_907,reg_910;
+
+	/* default */
+	reg_907 = (bw->pll_bypass << 15) | (bw->modulo << 7) |
+		(bw->ADClkSrc << 6) | (bw->IO_CLK_en_core << 5) | (bw->bypclk_div << 2) |
+		(bw->enable_refdiv << 1) | (0 << 0);
+	reg_910 = (((bw->pll_ratio >> 6) & 0x3) << 3) | (bw->pll_range << 1) | bw->pll_reset;
+
+	// for this oscillator frequency should be 30 MHz for the Master (default values in the board_parameters give that value)
+	// this is only working only for 30 MHz crystals
+	if (!state->cfg.quartz_direct) {
+		reg_910 |= (1 << 5);  // forcing the predivider to 1
+
+		// if the previous front-end is baseband, its output frequency is 15 MHz (prev freq divided by 2)
+		if(state->cfg.input_clk_is_div_2)
+			reg_907 |= (16 << 9);
+		else // otherwise the previous front-end puts out its input (default 30MHz) - no extra division necessary
+			reg_907 |= (8 << 9);
+	} else {
+		reg_907 |= (bw->pll_ratio & 0x3f) << 9;
+		reg_910 |= (bw->pll_prediv << 5);
+	}
+
+	dib7000m_write_word(state, 910, reg_910); // pll cfg
+	dib7000m_write_word(state, 907, reg_907); // clk cfg0
+	dib7000m_write_word(state, 908, 0x0006);  // clk_cfg1
+
+	dib7000m_reset_pll_common(state, bw);
+}
+
+static void dib7000mc_reset_pll(struct dib7000m_state *state)
+{
+	const struct dibx000_bandwidth_config *bw = state->cfg.bw;
+	u16 clk_cfg1;
+
+	// clk_cfg0
+	dib7000m_write_word(state, 907, (bw->pll_prediv << 8) | (bw->pll_ratio << 0));
+
+	// clk_cfg1
+	//dib7000m_write_word(state, 908, (1 << 14) | (3 << 12) |(0 << 11) |
+	clk_cfg1 = (0 << 14) | (3 << 12) |(0 << 11) |
+			(bw->IO_CLK_en_core << 10) | (bw->bypclk_div << 5) | (bw->enable_refdiv << 4) |
+			(1 << 3) | (bw->pll_range << 1) | (bw->pll_reset << 0);
+	dib7000m_write_word(state, 908, clk_cfg1);
+	clk_cfg1 = (clk_cfg1 & 0xfff7) | (bw->pll_bypass << 3);
+	dib7000m_write_word(state, 908, clk_cfg1);
+
+	// smpl_cfg
+	dib7000m_write_word(state, 910, (1 << 12) | (2 << 10) | (bw->modulo << 8) | (bw->ADClkSrc << 7));
+
+	dib7000m_reset_pll_common(state, bw);
+}
+
+static int dib7000m_reset_gpio(struct dib7000m_state *st)
+{
+	/* reset the GPIOs */
+	dib7000m_write_word(st, 773, st->cfg.gpio_dir);
+	dib7000m_write_word(st, 774, st->cfg.gpio_val);
+
+	/* TODO 782 is P_gpio_od */
+
+	dib7000m_write_word(st, 775, st->cfg.gpio_pwm_pos);
+
+	dib7000m_write_word(st, 780, st->cfg.pwm_freq_div);
+	return 0;
+}
+
+static u16 dib7000m_defaults_common[] =
+
+{
+	// auto search configuration
+	3, 2,
+		0x0004,
+		0x1000,
+		0x0814,
+
+	12, 6,
+		0x001b,
+		0x7740,
+		0x005b,
+		0x8d80,
+		0x01c9,
+		0xc380,
+		0x0000,
+		0x0080,
+		0x0000,
+		0x0090,
+		0x0001,
+		0xd4c0,
+
+	1, 26,
+		0x6680, // P_corm_thres Lock algorithms configuration
+
+	1, 170,
+		0x0410, // P_palf_alpha_regul, P_palf_filter_freeze, P_palf_filter_on
+
+	8, 173,
+		0,
+		0,
+		0,
+		0,
+		0,
+		0,
+		0,
+		0,
+
+	1, 182,
+		8192, // P_fft_nb_to_cut
+
+	2, 195,
+		0x0ccd, // P_pha3_thres
+		0,      // P_cti_use_cpe, P_cti_use_prog
+
+	1, 205,
+		0x200f, // P_cspu_regul, P_cspu_win_cut
+
+	5, 214,
+		0x023d, // P_adp_regul_cnt
+		0x00a4, // P_adp_noise_cnt
+		0x00a4, // P_adp_regul_ext
+		0x7ff0, // P_adp_noise_ext
+		0x3ccc, // P_adp_fil
+
+	1, 226,
+		0, // P_2d_byp_ti_num
+
+	1, 255,
+		0x800, // P_equal_thres_wgn
+
+	1, 263,
+		0x0001,
+
+	1, 281,
+		0x0010, // P_fec_*
+
+	1, 294,
+		0x0062, // P_smo_mode, P_smo_rs_discard, P_smo_fifo_flush, P_smo_pid_parse, P_smo_error_discard
+
+	0
+};
+
+static u16 dib7000m_defaults[] =
+
+{
+	/* set ADC level to -16 */
+	11, 76,
+		(1 << 13) - 825 - 117,
+		(1 << 13) - 837 - 117,
+		(1 << 13) - 811 - 117,
+		(1 << 13) - 766 - 117,
+		(1 << 13) - 737 - 117,
+		(1 << 13) - 693 - 117,
+		(1 << 13) - 648 - 117,
+		(1 << 13) - 619 - 117,
+		(1 << 13) - 575 - 117,
+		(1 << 13) - 531 - 117,
+		(1 << 13) - 501 - 117,
+
+	// Tuner IO bank: max drive (14mA)
+	1, 912,
+		0x2c8a,
+
+	1, 1817,
+		1,
+
+	0,
+};
+
+static int dib7000m_demod_reset(struct dib7000m_state *state)
+{
+	dib7000m_set_power_mode(state, DIB7000M_POWER_ALL);
+
+	/* always leave the VBG voltage on - it consumes almost nothing but takes a long time to start */
+	dib7000m_set_adc_state(state, DIBX000_VBG_ENABLE);
+
+	/* restart all parts */
+	dib7000m_write_word(state,  898, 0xffff);
+	dib7000m_write_word(state,  899, 0xffff);
+	dib7000m_write_word(state,  900, 0xff0f);
+	dib7000m_write_word(state,  901, 0xfffc);
+
+	dib7000m_write_word(state,  898, 0);
+	dib7000m_write_word(state,  899, 0);
+	dib7000m_write_word(state,  900, 0);
+	dib7000m_write_word(state,  901, 0);
+
+	if (state->revision == 0x4000)
+		dib7000m_reset_pll(state);
+	else
+		dib7000mc_reset_pll(state);
+
+	if (dib7000m_reset_gpio(state) != 0)
+		dprintk( "GPIO reset was not successful.");
+
+	if (dib7000m_set_output_mode(state, OUTMODE_HIGH_Z) != 0)
+		dprintk( "OUTPUT_MODE could not be reset.");
+
+	/* unforce divstr regardless whether i2c enumeration was done or not */
+	dib7000m_write_word(state, 1794, dib7000m_read_word(state, 1794) & ~(1 << 1) );
+
+	dib7000m_set_bandwidth(state, 8000);
+
+	dib7000m_set_adc_state(state, DIBX000_SLOW_ADC_ON);
+	dib7000m_sad_calib(state);
+	dib7000m_set_adc_state(state, DIBX000_SLOW_ADC_OFF);
+
+	if (state->cfg.dvbt_mode)
+		dib7000m_write_word(state, 1796, 0x0); // select DVB-T output
+
+	if (state->cfg.mobile_mode)
+		dib7000m_write_word(state, 261 + state->reg_offs, 2);
+	else
+		dib7000m_write_word(state, 224 + state->reg_offs, 1);
+
+	// P_iqc_alpha_pha, P_iqc_alpha_amp, P_iqc_dcc_alpha, ...
+	if(state->cfg.tuner_is_baseband)
+		dib7000m_write_word(state, 36, 0x0755);
+	else
+		dib7000m_write_word(state, 36, 0x1f55);
+
+	// P_divclksel=3 P_divbitsel=1
+	if (state->revision == 0x4000)
+		dib7000m_write_word(state, 909, (3 << 10) | (1 << 6));
+	else
+		dib7000m_write_word(state, 909, (3 << 4) | 1);
+
+	dib7000m_write_tab(state, dib7000m_defaults_common);
+	dib7000m_write_tab(state, dib7000m_defaults);
+
+	dib7000m_set_power_mode(state, DIB7000M_POWER_INTERFACE_ONLY);
+
+	state->internal_clk = state->cfg.bw->internal;
+
+	return 0;
+}
+
+static void dib7000m_restart_agc(struct dib7000m_state *state)
+{
+	// P_restart_iqc & P_restart_agc
+	dib7000m_write_word(state, 898, 0x0c00);
+	dib7000m_write_word(state, 898, 0x0000);
+}
+
+static int dib7000m_agc_soft_split(struct dib7000m_state *state)
+{
+	u16 agc,split_offset;
+
+	if(!state->current_agc || !state->current_agc->perform_agc_softsplit || state->current_agc->split.max == 0)
+		return 0;
+
+	// n_agc_global
+	agc = dib7000m_read_word(state, 390);
+
+	if (agc > state->current_agc->split.min_thres)
+		split_offset = state->current_agc->split.min;
+	else if (agc < state->current_agc->split.max_thres)
+		split_offset = state->current_agc->split.max;
+	else
+		split_offset = state->current_agc->split.max *
+			(agc - state->current_agc->split.min_thres) /
+			(state->current_agc->split.max_thres - state->current_agc->split.min_thres);
+
+	dprintk( "AGC split_offset: %d",split_offset);
+
+	// P_agc_force_split and P_agc_split_offset
+	return dib7000m_write_word(state, 103, (dib7000m_read_word(state, 103) & 0xff00) | split_offset);
+}
+
+static int dib7000m_update_lna(struct dib7000m_state *state)
+{
+	u16 dyn_gain;
+
+	if (state->cfg.update_lna) {
+		// read dyn_gain here (because it is demod-dependent and not fe)
+		dyn_gain = dib7000m_read_word(state, 390);
+
+		if (state->cfg.update_lna(&state->demod,dyn_gain)) { // LNA has changed
+			dib7000m_restart_agc(state);
+			return 1;
+		}
+	}
+	return 0;
+}
+
+static int dib7000m_set_agc_config(struct dib7000m_state *state, u8 band)
+{
+	struct dibx000_agc_config *agc = NULL;
+	int i;
+	if (state->current_band == band && state->current_agc != NULL)
+		return 0;
+	state->current_band = band;
+
+	for (i = 0; i < state->cfg.agc_config_count; i++)
+		if (state->cfg.agc[i].band_caps & band) {
+			agc = &state->cfg.agc[i];
+			break;
+		}
+
+	if (agc == NULL) {
+		dprintk( "no valid AGC configuration found for band 0x%02x",band);
+		return -EINVAL;
+	}
+
+	state->current_agc = agc;
+
+	/* AGC */
+	dib7000m_write_word(state, 72 ,  agc->setup);
+	dib7000m_write_word(state, 73 ,  agc->inv_gain);
+	dib7000m_write_word(state, 74 ,  agc->time_stabiliz);
+	dib7000m_write_word(state, 97 , (agc->alpha_level << 12) | agc->thlock);
+
+	// Demod AGC loop configuration
+	dib7000m_write_word(state, 98, (agc->alpha_mant << 5) | agc->alpha_exp);
+	dib7000m_write_word(state, 99, (agc->beta_mant  << 6) | agc->beta_exp);
+
+	dprintk( "WBD: ref: %d, sel: %d, active: %d, alpha: %d",
+		state->wbd_ref != 0 ? state->wbd_ref : agc->wbd_ref, agc->wbd_sel, !agc->perform_agc_softsplit, agc->wbd_sel);
+
+	/* AGC continued */
+	if (state->wbd_ref != 0)
+		dib7000m_write_word(state, 102, state->wbd_ref);
+	else // use default
+		dib7000m_write_word(state, 102, agc->wbd_ref);
+
+	dib7000m_write_word(state, 103, (agc->wbd_alpha << 9) | (agc->perform_agc_softsplit << 8) );
+	dib7000m_write_word(state, 104,  agc->agc1_max);
+	dib7000m_write_word(state, 105,  agc->agc1_min);
+	dib7000m_write_word(state, 106,  agc->agc2_max);
+	dib7000m_write_word(state, 107,  agc->agc2_min);
+	dib7000m_write_word(state, 108, (agc->agc1_pt1 << 8) | agc->agc1_pt2 );
+	dib7000m_write_word(state, 109, (agc->agc1_slope1 << 8) | agc->agc1_slope2);
+	dib7000m_write_word(state, 110, (agc->agc2_pt1 << 8) | agc->agc2_pt2);
+	dib7000m_write_word(state, 111, (agc->agc2_slope1 << 8) | agc->agc2_slope2);
+
+	if (state->revision > 0x4000) { // settings for the MC
+		dib7000m_write_word(state, 71,   agc->agc1_pt3);
+//		dprintk( "929: %x %d %d",
+//			(dib7000m_read_word(state, 929) & 0xffe3) | (agc->wbd_inv << 4) | (agc->wbd_sel << 2), agc->wbd_inv, agc->wbd_sel);
+		dib7000m_write_word(state, 929, (dib7000m_read_word(state, 929) & 0xffe3) | (agc->wbd_inv << 4) | (agc->wbd_sel << 2));
+	} else {
+		// wrong default values
+		u16 b[9] = { 676, 696, 717, 737, 758, 778, 799, 819, 840 };
+		for (i = 0; i < 9; i++)
+			dib7000m_write_word(state, 88 + i, b[i]);
+	}
+	return 0;
+}
+
+static void dib7000m_update_timf(struct dib7000m_state *state)
+{
+	u32 timf = (dib7000m_read_word(state, 436) << 16) | dib7000m_read_word(state, 437);
+	state->timf = timf * 160 / (state->current_bandwidth / 50);
+	dib7000m_write_word(state, 23, (u16) (timf >> 16));
+	dib7000m_write_word(state, 24, (u16) (timf & 0xffff));
+	dprintk( "updated timf_frequency: %d (default: %d)",state->timf, state->timf_default);
+}
+
+static int dib7000m_agc_startup(struct dvb_frontend *demod)
+{
+	struct dtv_frontend_properties *ch = &demod->dtv_property_cache;
+	struct dib7000m_state *state = demod->demodulator_priv;
+	u16 cfg_72 = dib7000m_read_word(state, 72);
+	int ret = -1;
+	u8 *agc_state = &state->agc_state;
+	u8 agc_split;
+
+	switch (state->agc_state) {
+		case 0:
+			// set power-up level: interf+analog+AGC
+			dib7000m_set_power_mode(state, DIB7000M_POWER_INTERF_ANALOG_AGC);
+			dib7000m_set_adc_state(state, DIBX000_ADC_ON);
+
+			if (dib7000m_set_agc_config(state, BAND_OF_FREQUENCY(ch->frequency/1000)) != 0)
+				return -1;
+
+			ret = 7; /* ADC power up */
+			(*agc_state)++;
+			break;
+
+		case 1:
+			/* AGC initialization */
+			if (state->cfg.agc_control)
+				state->cfg.agc_control(&state->demod, 1);
+
+			dib7000m_write_word(state, 75, 32768);
+			if (!state->current_agc->perform_agc_softsplit) {
+				/* we are using the wbd - so slow AGC startup */
+				dib7000m_write_word(state, 103, 1 << 8); /* force 0 split on WBD and restart AGC */
+				(*agc_state)++;
+				ret = 5;
+			} else {
+				/* default AGC startup */
+				(*agc_state) = 4;
+				/* wait AGC rough lock time */
+				ret = 7;
+			}
+
+			dib7000m_restart_agc(state);
+			break;
+
+		case 2: /* fast split search path after 5sec */
+			dib7000m_write_word(state,  72, cfg_72 | (1 << 4)); /* freeze AGC loop */
+			dib7000m_write_word(state, 103, 2 << 9);            /* fast split search 0.25kHz */
+			(*agc_state)++;
+			ret = 14;
+			break;
+
+	case 3: /* split search ended */
+			agc_split = (u8)dib7000m_read_word(state, 392); /* store the split value for the next time */
+			dib7000m_write_word(state, 75, dib7000m_read_word(state, 390)); /* set AGC gain start value */
+
+			dib7000m_write_word(state, 72,  cfg_72 & ~(1 << 4));   /* std AGC loop */
+			dib7000m_write_word(state, 103, (state->current_agc->wbd_alpha << 9) | agc_split); /* standard split search */
+
+			dib7000m_restart_agc(state);
+
+			dprintk( "SPLIT %p: %hd", demod, agc_split);
+
+			(*agc_state)++;
+			ret = 5;
+			break;
+
+		case 4: /* LNA startup */
+			/* wait AGC accurate lock time */
+			ret = 7;
+
+			if (dib7000m_update_lna(state))
+				// wait only AGC rough lock time
+				ret = 5;
+			else
+				(*agc_state)++;
+			break;
+
+		case 5:
+			dib7000m_agc_soft_split(state);
+
+			if (state->cfg.agc_control)
+				state->cfg.agc_control(&state->demod, 0);
+
+			(*agc_state)++;
+			break;
+
+		default:
+			break;
+	}
+	return ret;
+}
+
+static void dib7000m_set_channel(struct dib7000m_state *state, struct dtv_frontend_properties *ch,
+				 u8 seq)
+{
+	u16 value, est[4];
+
+	dib7000m_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->bandwidth_hz));
+
+	/* nfft, guard, qam, alpha */
+	value = 0;
+	switch (ch->transmission_mode) {
+		case TRANSMISSION_MODE_2K: value |= (0 << 7); break;
+		case TRANSMISSION_MODE_4K: value |= (2 << 7); break;
+		default:
+		case TRANSMISSION_MODE_8K: value |= (1 << 7); break;
+	}
+	switch (ch->guard_interval) {
+		case GUARD_INTERVAL_1_32: value |= (0 << 5); break;
+		case GUARD_INTERVAL_1_16: value |= (1 << 5); break;
+		case GUARD_INTERVAL_1_4:  value |= (3 << 5); break;
+		default:
+		case GUARD_INTERVAL_1_8:  value |= (2 << 5); break;
+	}
+	switch (ch->modulation) {
+		case QPSK:  value |= (0 << 3); break;
+		case QAM_16: value |= (1 << 3); break;
+		default:
+		case QAM_64: value |= (2 << 3); break;
+	}
+	switch (HIERARCHY_1) {
+		case HIERARCHY_2: value |= 2; break;
+		case HIERARCHY_4: value |= 4; break;
+		default:
+		case HIERARCHY_1: value |= 1; break;
+	}
+	dib7000m_write_word(state, 0, value);
+	dib7000m_write_word(state, 5, (seq << 4));
+
+	/* P_dintl_native, P_dintlv_inv, P_hrch, P_code_rate, P_select_hp */
+	value = 0;
+	if (1 != 0)
+		value |= (1 << 6);
+	if (ch->hierarchy == 1)
+		value |= (1 << 4);
+	if (1 == 1)
+		value |= 1;
+	switch ((ch->hierarchy == 0 || 1 == 1) ? ch->code_rate_HP : ch->code_rate_LP) {
+		case FEC_2_3: value |= (2 << 1); break;
+		case FEC_3_4: value |= (3 << 1); break;
+		case FEC_5_6: value |= (5 << 1); break;
+		case FEC_7_8: value |= (7 << 1); break;
+		default:
+		case FEC_1_2: value |= (1 << 1); break;
+	}
+	dib7000m_write_word(state, 267 + state->reg_offs, value);
+
+	/* offset loop parameters */
+
+	/* P_timf_alpha = 6, P_corm_alpha=6, P_corm_thres=0x80 */
+	dib7000m_write_word(state, 26, (6 << 12) | (6 << 8) | 0x80);
+
+	/* P_ctrl_inh_cor=0, P_ctrl_alpha_cor=4, P_ctrl_inh_isi=1, P_ctrl_alpha_isi=3, P_ctrl_inh_cor4=1, P_ctrl_alpha_cor4=3 */
+	dib7000m_write_word(state, 29, (0 << 14) | (4 << 10) | (1 << 9) | (3 << 5) | (1 << 4) | (0x3));
+
+	/* P_ctrl_freeze_pha_shift=0, P_ctrl_pha_off_max=3 */
+	dib7000m_write_word(state, 32, (0 << 4) | 0x3);
+
+	/* P_ctrl_sfreq_inh=0, P_ctrl_sfreq_step=5 */
+	dib7000m_write_word(state, 33, (0 << 4) | 0x5);
+
+	/* P_dvsy_sync_wait */
+	switch (ch->transmission_mode) {
+		case TRANSMISSION_MODE_8K: value = 256; break;
+		case TRANSMISSION_MODE_4K: value = 128; break;
+		case TRANSMISSION_MODE_2K:
+		default: value = 64; break;
+	}
+	switch (ch->guard_interval) {
+		case GUARD_INTERVAL_1_16: value *= 2; break;
+		case GUARD_INTERVAL_1_8:  value *= 4; break;
+		case GUARD_INTERVAL_1_4:  value *= 8; break;
+		default:
+		case GUARD_INTERVAL_1_32: value *= 1; break;
+	}
+	state->div_sync_wait = (value * 3) / 2 + 32; // add 50% SFN margin + compensate for one DVSY-fifo TODO
+
+	/* deactive the possibility of diversity reception if extended interleave - not for 7000MC */
+	/* P_dvsy_sync_mode = 0, P_dvsy_sync_enable=1, P_dvcb_comb_mode=2 */
+	if (1 == 1 || state->revision > 0x4000)
+		state->div_force_off = 0;
+	else
+		state->div_force_off = 1;
+	dib7000m_set_diversity_in(&state->demod, state->div_state);
+
+	/* channel estimation fine configuration */
+	switch (ch->modulation) {
+		case QAM_64:
+			est[0] = 0x0148;       /* P_adp_regul_cnt 0.04 */
+			est[1] = 0xfff0;       /* P_adp_noise_cnt -0.002 */
+			est[2] = 0x00a4;       /* P_adp_regul_ext 0.02 */
+			est[3] = 0xfff8;       /* P_adp_noise_ext -0.001 */
+			break;
+		case QAM_16:
+			est[0] = 0x023d;       /* P_adp_regul_cnt 0.07 */
+			est[1] = 0xffdf;       /* P_adp_noise_cnt -0.004 */
+			est[2] = 0x00a4;       /* P_adp_regul_ext 0.02 */
+			est[3] = 0xfff0;       /* P_adp_noise_ext -0.002 */
+			break;
+		default:
+			est[0] = 0x099a;       /* P_adp_regul_cnt 0.3 */
+			est[1] = 0xffae;       /* P_adp_noise_cnt -0.01 */
+			est[2] = 0x0333;       /* P_adp_regul_ext 0.1 */
+			est[3] = 0xfff8;       /* P_adp_noise_ext -0.002 */
+			break;
+	}
+	for (value = 0; value < 4; value++)
+		dib7000m_write_word(state, 214 + value + state->reg_offs, est[value]);
+
+	// set power-up level: autosearch
+	dib7000m_set_power_mode(state, DIB7000M_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD);
+}
+
+static int dib7000m_autosearch_start(struct dvb_frontend *demod)
+{
+	struct dtv_frontend_properties *ch = &demod->dtv_property_cache;
+	struct dib7000m_state *state = demod->demodulator_priv;
+	struct dtv_frontend_properties schan;
+	int ret = 0;
+	u32 value, factor;
+
+	schan = *ch;
+
+	schan.modulation = QAM_64;
+	schan.guard_interval        = GUARD_INTERVAL_1_32;
+	schan.transmission_mode         = TRANSMISSION_MODE_8K;
+	schan.code_rate_HP = FEC_2_3;
+	schan.code_rate_LP = FEC_3_4;
+	schan.hierarchy    = 0;
+
+	dib7000m_set_channel(state, &schan, 7);
+
+	factor = BANDWIDTH_TO_KHZ(schan.bandwidth_hz);
+	if (factor >= 5000)
+		factor = 1;
+	else
+		factor = 6;
+
+	// always use the setting for 8MHz here lock_time for 7,6 MHz are longer
+	value = 30 * state->internal_clk * factor;
+	ret |= dib7000m_write_word(state, 6,  (u16) ((value >> 16) & 0xffff)); // lock0 wait time
+	ret |= dib7000m_write_word(state, 7,  (u16)  (value        & 0xffff)); // lock0 wait time
+	value = 100 * state->internal_clk * factor;
+	ret |= dib7000m_write_word(state, 8,  (u16) ((value >> 16) & 0xffff)); // lock1 wait time
+	ret |= dib7000m_write_word(state, 9,  (u16)  (value        & 0xffff)); // lock1 wait time
+	value = 500 * state->internal_clk * factor;
+	ret |= dib7000m_write_word(state, 10, (u16) ((value >> 16) & 0xffff)); // lock2 wait time
+	ret |= dib7000m_write_word(state, 11, (u16)  (value        & 0xffff)); // lock2 wait time
+
+	// start search
+	value = dib7000m_read_word(state, 0);
+	ret |= dib7000m_write_word(state, 0, (u16) (value | (1 << 9)));
+
+	/* clear n_irq_pending */
+	if (state->revision == 0x4000)
+		dib7000m_write_word(state, 1793, 0);
+	else
+		dib7000m_read_word(state, 537);
+
+	ret |= dib7000m_write_word(state, 0, (u16) value);
+
+	return ret;
+}
+
+static int dib7000m_autosearch_irq(struct dib7000m_state *state, u16 reg)
+{
+	u16 irq_pending = dib7000m_read_word(state, reg);
+
+	if (irq_pending & 0x1) { // failed
+		dprintk( "autosearch failed");
+		return 1;
+	}
+
+	if (irq_pending & 0x2) { // succeeded
+		dprintk( "autosearch succeeded");
+		return 2;
+	}
+	return 0; // still pending
+}
+
+static int dib7000m_autosearch_is_irq(struct dvb_frontend *demod)
+{
+	struct dib7000m_state *state = demod->demodulator_priv;
+	if (state->revision == 0x4000)
+		return dib7000m_autosearch_irq(state, 1793);
+	else
+		return dib7000m_autosearch_irq(state, 537);
+}
+
+static int dib7000m_tune(struct dvb_frontend *demod)
+{
+	struct dtv_frontend_properties *ch = &demod->dtv_property_cache;
+	struct dib7000m_state *state = demod->demodulator_priv;
+	int ret = 0;
+	u16 value;
+
+	// we are already tuned - just resuming from suspend
+	if (ch != NULL)
+		dib7000m_set_channel(state, ch, 0);
+	else
+		return -EINVAL;
+
+	// restart demod
+	ret |= dib7000m_write_word(state, 898, 0x4000);
+	ret |= dib7000m_write_word(state, 898, 0x0000);
+	msleep(45);
+
+	dib7000m_set_power_mode(state, DIB7000M_POWER_COR4_CRY_ESRAM_MOUT_NUD);
+	/* P_ctrl_inh_cor=0, P_ctrl_alpha_cor=4, P_ctrl_inh_isi=0, P_ctrl_alpha_isi=3, P_ctrl_inh_cor4=1, P_ctrl_alpha_cor4=3 */
+	ret |= dib7000m_write_word(state, 29, (0 << 14) | (4 << 10) | (0 << 9) | (3 << 5) | (1 << 4) | (0x3));
+
+	// never achieved a lock before - wait for timfreq to update
+	if (state->timf == 0)
+		msleep(200);
+
+	//dump_reg(state);
+	/* P_timf_alpha, P_corm_alpha=6, P_corm_thres=0x80 */
+	value = (6 << 8) | 0x80;
+	switch (ch->transmission_mode) {
+		case TRANSMISSION_MODE_2K: value |= (7 << 12); break;
+		case TRANSMISSION_MODE_4K: value |= (8 << 12); break;
+		default:
+		case TRANSMISSION_MODE_8K: value |= (9 << 12); break;
+	}
+	ret |= dib7000m_write_word(state, 26, value);
+
+	/* P_ctrl_freeze_pha_shift=0, P_ctrl_pha_off_max */
+	value = (0 << 4);
+	switch (ch->transmission_mode) {
+		case TRANSMISSION_MODE_2K: value |= 0x6; break;
+		case TRANSMISSION_MODE_4K: value |= 0x7; break;
+		default:
+		case TRANSMISSION_MODE_8K: value |= 0x8; break;
+	}
+	ret |= dib7000m_write_word(state, 32, value);
+
+	/* P_ctrl_sfreq_inh=0, P_ctrl_sfreq_step */
+	value = (0 << 4);
+	switch (ch->transmission_mode) {
+		case TRANSMISSION_MODE_2K: value |= 0x6; break;
+		case TRANSMISSION_MODE_4K: value |= 0x7; break;
+		default:
+		case TRANSMISSION_MODE_8K: value |= 0x8; break;
+	}
+	ret |= dib7000m_write_word(state, 33,  value);
+
+	// we achieved a lock - it's time to update the timf freq
+	if ((dib7000m_read_word(state, 535) >> 6)  & 0x1)
+		dib7000m_update_timf(state);
+
+	dib7000m_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->bandwidth_hz));
+	return ret;
+}
+
+static int dib7000m_wakeup(struct dvb_frontend *demod)
+{
+	struct dib7000m_state *state = demod->demodulator_priv;
+
+	dib7000m_set_power_mode(state, DIB7000M_POWER_ALL);
+
+	if (dib7000m_set_adc_state(state, DIBX000_SLOW_ADC_ON) != 0)
+		dprintk( "could not start Slow ADC");
+
+	return 0;
+}
+
+static int dib7000m_sleep(struct dvb_frontend *demod)
+{
+	struct dib7000m_state *st = demod->demodulator_priv;
+	dib7000m_set_output_mode(st, OUTMODE_HIGH_Z);
+	dib7000m_set_power_mode(st, DIB7000M_POWER_INTERFACE_ONLY);
+	return dib7000m_set_adc_state(st, DIBX000_SLOW_ADC_OFF) |
+		dib7000m_set_adc_state(st, DIBX000_ADC_OFF);
+}
+
+static int dib7000m_identify(struct dib7000m_state *state)
+{
+	u16 value;
+
+	if ((value = dib7000m_read_word(state, 896)) != 0x01b3) {
+		dprintk( "wrong Vendor ID (0x%x)",value);
+		return -EREMOTEIO;
+	}
+
+	state->revision = dib7000m_read_word(state, 897);
+	if (state->revision != 0x4000 &&
+		state->revision != 0x4001 &&
+		state->revision != 0x4002 &&
+		state->revision != 0x4003) {
+		dprintk( "wrong Device ID (0x%x)",value);
+		return -EREMOTEIO;
+	}
+
+	/* protect this driver to be used with 7000PC */
+	if (state->revision == 0x4000 && dib7000m_read_word(state, 769) == 0x4000) {
+		dprintk( "this driver does not work with DiB7000PC");
+		return -EREMOTEIO;
+	}
+
+	switch (state->revision) {
+		case 0x4000: dprintk( "found DiB7000MA/PA/MB/PB"); break;
+		case 0x4001: state->reg_offs = 1; dprintk( "found DiB7000HC"); break;
+		case 0x4002: state->reg_offs = 1; dprintk( "found DiB7000MC"); break;
+		case 0x4003: state->reg_offs = 1; dprintk( "found DiB9000"); break;
+	}
+
+	return 0;
+}
+
+
+static int dib7000m_get_frontend(struct dvb_frontend* fe)
+{
+	struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
+	struct dib7000m_state *state = fe->demodulator_priv;
+	u16 tps = dib7000m_read_word(state,480);
+
+	fep->inversion = INVERSION_AUTO;
+
+	fep->bandwidth_hz = BANDWIDTH_TO_HZ(state->current_bandwidth);
+
+	switch ((tps >> 8) & 0x3) {
+		case 0: fep->transmission_mode = TRANSMISSION_MODE_2K; break;
+		case 1: fep->transmission_mode = TRANSMISSION_MODE_8K; break;
+		/* case 2: fep->transmission_mode = TRANSMISSION_MODE_4K; break; */
+	}
+
+	switch (tps & 0x3) {
+		case 0: fep->guard_interval = GUARD_INTERVAL_1_32; break;
+		case 1: fep->guard_interval = GUARD_INTERVAL_1_16; break;
+		case 2: fep->guard_interval = GUARD_INTERVAL_1_8; break;
+		case 3: fep->guard_interval = GUARD_INTERVAL_1_4; break;
+	}
+
+	switch ((tps >> 14) & 0x3) {
+		case 0: fep->modulation = QPSK; break;
+		case 1: fep->modulation = QAM_16; break;
+		case 2:
+		default: fep->modulation = QAM_64; break;
+	}
+
+	/* as long as the frontend_param structure is fixed for hierarchical transmission I refuse to use it */
+	/* (tps >> 13) & 0x1 == hrch is used, (tps >> 10) & 0x7 == alpha */
+
+	fep->hierarchy = HIERARCHY_NONE;
+	switch ((tps >> 5) & 0x7) {
+		case 1: fep->code_rate_HP = FEC_1_2; break;
+		case 2: fep->code_rate_HP = FEC_2_3; break;
+		case 3: fep->code_rate_HP = FEC_3_4; break;
+		case 5: fep->code_rate_HP = FEC_5_6; break;
+		case 7:
+		default: fep->code_rate_HP = FEC_7_8; break;
+
+	}
+
+	switch ((tps >> 2) & 0x7) {
+		case 1: fep->code_rate_LP = FEC_1_2; break;
+		case 2: fep->code_rate_LP = FEC_2_3; break;
+		case 3: fep->code_rate_LP = FEC_3_4; break;
+		case 5: fep->code_rate_LP = FEC_5_6; break;
+		case 7:
+		default: fep->code_rate_LP = FEC_7_8; break;
+	}
+
+	/* native interleaver: (dib7000m_read_word(state, 481) >>  5) & 0x1 */
+
+	return 0;
+}
+
+static int dib7000m_set_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
+	struct dib7000m_state *state = fe->demodulator_priv;
+	int time, ret;
+
+	dib7000m_set_output_mode(state, OUTMODE_HIGH_Z);
+
+	dib7000m_set_bandwidth(state, BANDWIDTH_TO_KHZ(fep->bandwidth_hz));
+
+	if (fe->ops.tuner_ops.set_params)
+		fe->ops.tuner_ops.set_params(fe);
+
+	/* start up the AGC */
+	state->agc_state = 0;
+	do {
+		time = dib7000m_agc_startup(fe);
+		if (time != -1)
+			msleep(time);
+	} while (time != -1);
+
+	if (fep->transmission_mode == TRANSMISSION_MODE_AUTO ||
+		fep->guard_interval    == GUARD_INTERVAL_AUTO ||
+		fep->modulation        == QAM_AUTO ||
+		fep->code_rate_HP      == FEC_AUTO) {
+		int i = 800, found;
+
+		dib7000m_autosearch_start(fe);
+		do {
+			msleep(1);
+			found = dib7000m_autosearch_is_irq(fe);
+		} while (found == 0 && i--);
+
+		dprintk("autosearch returns: %d",found);
+		if (found == 0 || found == 1)
+			return 0; // no channel found
+
+		dib7000m_get_frontend(fe);
+	}
+
+	ret = dib7000m_tune(fe);
+
+	/* make this a config parameter */
+	dib7000m_set_output_mode(state, OUTMODE_MPEG2_FIFO);
+	return ret;
+}
+
+static int dib7000m_read_status(struct dvb_frontend *fe, fe_status_t *stat)
+{
+	struct dib7000m_state *state = fe->demodulator_priv;
+	u16 lock = dib7000m_read_word(state, 535);
+
+	*stat = 0;
+
+	if (lock & 0x8000)
+		*stat |= FE_HAS_SIGNAL;
+	if (lock & 0x3000)
+		*stat |= FE_HAS_CARRIER;
+	if (lock & 0x0100)
+		*stat |= FE_HAS_VITERBI;
+	if (lock & 0x0010)
+		*stat |= FE_HAS_SYNC;
+	if (lock & 0x0008)
+		*stat |= FE_HAS_LOCK;
+
+	return 0;
+}
+
+static int dib7000m_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+	struct dib7000m_state *state = fe->demodulator_priv;
+	*ber = (dib7000m_read_word(state, 526) << 16) | dib7000m_read_word(state, 527);
+	return 0;
+}
+
+static int dib7000m_read_unc_blocks(struct dvb_frontend *fe, u32 *unc)
+{
+	struct dib7000m_state *state = fe->demodulator_priv;
+	*unc = dib7000m_read_word(state, 534);
+	return 0;
+}
+
+static int dib7000m_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
+{
+	struct dib7000m_state *state = fe->demodulator_priv;
+	u16 val = dib7000m_read_word(state, 390);
+	*strength = 65535 - val;
+	return 0;
+}
+
+static int dib7000m_read_snr(struct dvb_frontend* fe, u16 *snr)
+{
+	*snr = 0x0000;
+	return 0;
+}
+
+static int dib7000m_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
+{
+	tune->min_delay_ms = 1000;
+	return 0;
+}
+
+static void dib7000m_release(struct dvb_frontend *demod)
+{
+	struct dib7000m_state *st = demod->demodulator_priv;
+	dibx000_exit_i2c_master(&st->i2c_master);
+	kfree(st);
+}
+
+struct i2c_adapter * dib7000m_get_i2c_master(struct dvb_frontend *demod, enum dibx000_i2c_interface intf, int gating)
+{
+	struct dib7000m_state *st = demod->demodulator_priv;
+	return dibx000_get_i2c_adapter(&st->i2c_master, intf, gating);
+}
+EXPORT_SYMBOL(dib7000m_get_i2c_master);
+
+int dib7000m_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
+{
+	struct dib7000m_state *state = fe->demodulator_priv;
+	u16 val = dib7000m_read_word(state, 294 + state->reg_offs) & 0xffef;
+	val |= (onoff & 0x1) << 4;
+	dprintk("PID filter enabled %d", onoff);
+	return dib7000m_write_word(state, 294 + state->reg_offs, val);
+}
+EXPORT_SYMBOL(dib7000m_pid_filter_ctrl);
+
+int dib7000m_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
+{
+	struct dib7000m_state *state = fe->demodulator_priv;
+	dprintk("PID filter: index %x, PID %d, OnOff %d", id, pid, onoff);
+	return dib7000m_write_word(state, 300 + state->reg_offs + id,
+			onoff ? (1 << 13) | pid : 0);
+}
+EXPORT_SYMBOL(dib7000m_pid_filter);
+
+#if 0
+/* used with some prototype boards */
+int dib7000m_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods,
+		u8 default_addr, struct dib7000m_config cfg[])
+{
+	struct dib7000m_state st = { .i2c_adap = i2c };
+	int k = 0;
+	u8 new_addr = 0;
+
+	for (k = no_of_demods-1; k >= 0; k--) {
+		st.cfg = cfg[k];
+
+		/* designated i2c address */
+		new_addr          = (0x40 + k) << 1;
+		st.i2c_addr = new_addr;
+		if (dib7000m_identify(&st) != 0) {
+			st.i2c_addr = default_addr;
+			if (dib7000m_identify(&st) != 0) {
+				dprintk("DiB7000M #%d: not identified", k);
+				return -EIO;
+			}
+		}
+
+		/* start diversity to pull_down div_str - just for i2c-enumeration */
+		dib7000m_set_output_mode(&st, OUTMODE_DIVERSITY);
+
+		dib7000m_write_word(&st, 1796, 0x0); // select DVB-T output
+
+		/* set new i2c address and force divstart */
+		dib7000m_write_word(&st, 1794, (new_addr << 2) | 0x2);
+
+		dprintk("IC %d initialized (to i2c_address 0x%x)", k, new_addr);
+	}
+
+	for (k = 0; k < no_of_demods; k++) {
+		st.cfg = cfg[k];
+		st.i2c_addr = (0x40 + k) << 1;
+
+		// unforce divstr
+		dib7000m_write_word(&st,1794, st.i2c_addr << 2);
+
+		/* deactivate div - it was just for i2c-enumeration */
+		dib7000m_set_output_mode(&st, OUTMODE_HIGH_Z);
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(dib7000m_i2c_enumeration);
+#endif
+
+static struct dvb_frontend_ops dib7000m_ops;
+struct dvb_frontend * dib7000m_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000m_config *cfg)
+{
+	struct dvb_frontend *demod;
+	struct dib7000m_state *st;
+	st = kzalloc(sizeof(struct dib7000m_state), GFP_KERNEL);
+	if (st == NULL)
+		return NULL;
+
+	memcpy(&st->cfg, cfg, sizeof(struct dib7000m_config));
+	st->i2c_adap = i2c_adap;
+	st->i2c_addr = i2c_addr;
+
+	demod                   = &st->demod;
+	demod->demodulator_priv = st;
+	memcpy(&st->demod.ops, &dib7000m_ops, sizeof(struct dvb_frontend_ops));
+	mutex_init(&st->i2c_buffer_lock);
+
+	st->timf_default = cfg->bw->timf;
+
+	if (dib7000m_identify(st) != 0)
+		goto error;
+
+	if (st->revision == 0x4000)
+		dibx000_init_i2c_master(&st->i2c_master, DIB7000, st->i2c_adap, st->i2c_addr);
+	else
+		dibx000_init_i2c_master(&st->i2c_master, DIB7000MC, st->i2c_adap, st->i2c_addr);
+
+	dib7000m_demod_reset(st);
+
+	return demod;
+
+error:
+	kfree(st);
+	return NULL;
+}
+EXPORT_SYMBOL(dib7000m_attach);
+
+static struct dvb_frontend_ops dib7000m_ops = {
+	.delsys = { SYS_DVBT },
+	.info = {
+		.name = "DiBcom 7000MA/MB/PA/PB/MC",
+		.frequency_min      = 44250000,
+		.frequency_max      = 867250000,
+		.frequency_stepsize = 62500,
+		.caps = FE_CAN_INVERSION_AUTO |
+			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_FEC_AUTO |
+			FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
+			FE_CAN_TRANSMISSION_MODE_AUTO |
+			FE_CAN_GUARD_INTERVAL_AUTO |
+			FE_CAN_RECOVER |
+			FE_CAN_HIERARCHY_AUTO,
+	},
+
+	.release              = dib7000m_release,
+
+	.init                 = dib7000m_wakeup,
+	.sleep                = dib7000m_sleep,
+
+	.set_frontend         = dib7000m_set_frontend,
+	.get_tune_settings    = dib7000m_fe_get_tune_settings,
+	.get_frontend         = dib7000m_get_frontend,
+
+	.read_status          = dib7000m_read_status,
+	.read_ber             = dib7000m_read_ber,
+	.read_signal_strength = dib7000m_read_signal_strength,
+	.read_snr             = dib7000m_read_snr,
+	.read_ucblocks        = dib7000m_read_unc_blocks,
+};
+
+MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
+MODULE_DESCRIPTION("Driver for the DiBcom 7000MA/MB/PA/PB/MC COFDM demodulator");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb-frontends/dib7000m.h b/drivers/media/dvb-frontends/dib7000m.h
new file mode 100644
index 0000000..81fcf22
--- /dev/null
+++ b/drivers/media/dvb-frontends/dib7000m.h
@@ -0,0 +1,90 @@
+#ifndef DIB7000M_H
+#define DIB7000M_H
+
+#include "dibx000_common.h"
+
+struct dib7000m_config {
+	u8 dvbt_mode;
+	u8 output_mpeg2_in_188_bytes;
+	u8 hostbus_diversity;
+	u8 tuner_is_baseband;
+	u8 mobile_mode;
+	int (*update_lna) (struct dvb_frontend *, u16 agc_global);
+
+	u8 agc_config_count;
+	struct dibx000_agc_config *agc;
+
+	struct dibx000_bandwidth_config *bw;
+
+#define DIB7000M_GPIO_DEFAULT_DIRECTIONS 0xffff
+	u16 gpio_dir;
+#define DIB7000M_GPIO_DEFAULT_VALUES     0x0000
+	u16 gpio_val;
+#define DIB7000M_GPIO_PWM_POS0(v)        ((v & 0xf) << 12)
+#define DIB7000M_GPIO_PWM_POS1(v)        ((v & 0xf) << 8 )
+#define DIB7000M_GPIO_PWM_POS2(v)        ((v & 0xf) << 4 )
+#define DIB7000M_GPIO_PWM_POS3(v)         (v & 0xf)
+#define DIB7000M_GPIO_DEFAULT_PWM_POS    0xffff
+	u16 gpio_pwm_pos;
+
+	u16 pwm_freq_div;
+
+	u8 quartz_direct;
+
+	u8 input_clk_is_div_2;
+
+	int (*agc_control) (struct dvb_frontend *, u8 before);
+};
+
+#define DEFAULT_DIB7000M_I2C_ADDRESS 18
+
+#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);
+extern int dib7000m_pid_filter(struct dvb_frontend *, u8 id, u16 pid, u8 onoff);
+extern int dib7000m_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff);
+#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;
+}
+static inline int dib7000m_pid_filter(struct dvb_frontend *fe, u8 id,
+						u16 pid, u8 onoff)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return -ENODEV;
+}
+
+static inline int dib7000m_pid_filter_ctrl(struct dvb_frontend *fe,
+						uint8_t onoff)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return -ENODEV;
+}
+#endif
+
+/* TODO
+extern INT dib7000m_set_gpio(struct dibDemod *demod, UCHAR num, UCHAR dir, UCHAR val);
+extern INT dib7000m_enable_vbg_voltage(struct dibDemod *demod);
+extern void dib7000m_set_hostbus_diversity(struct dibDemod *demod, UCHAR onoff);
+extern USHORT dib7000m_get_current_agc_global(struct dibDemod *demod);
+*/
+
+#endif
diff --git a/drivers/media/dvb-frontends/dib7000p.c b/drivers/media/dvb-frontends/dib7000p.c
new file mode 100644
index 0000000..3e1eefa
--- /dev/null
+++ b/drivers/media/dvb-frontends/dib7000p.c
@@ -0,0 +1,2457 @@
+/*
+ * Linux-DVB Driver for DiBcom's second generation DiB7000P (PC).
+ *
+ * Copyright (C) 2005-7 DiBcom (http://www.dibcom.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, version 2.
+ */
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+
+#include "dvb_math.h"
+#include "dvb_frontend.h"
+
+#include "dib7000p.h"
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
+
+static int buggy_sfn_workaround;
+module_param(buggy_sfn_workaround, int, 0644);
+MODULE_PARM_DESC(buggy_sfn_workaround, "Enable work-around for buggy SFNs (default: 0)");
+
+#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB7000P: "); printk(args); printk("\n"); } } while (0)
+
+struct i2c_device {
+	struct i2c_adapter *i2c_adap;
+	u8 i2c_addr;
+};
+
+struct dib7000p_state {
+	struct dvb_frontend demod;
+	struct dib7000p_config cfg;
+
+	u8 i2c_addr;
+	struct i2c_adapter *i2c_adap;
+
+	struct dibx000_i2c_master i2c_master;
+
+	u16 wbd_ref;
+
+	u8 current_band;
+	u32 current_bandwidth;
+	struct dibx000_agc_config *current_agc;
+	u32 timf;
+
+	u8 div_force_off:1;
+	u8 div_state:1;
+	u16 div_sync_wait;
+
+	u8 agc_state;
+
+	u16 gpio_dir;
+	u16 gpio_val;
+
+	u8 sfn_workaround_active:1;
+
+#define SOC7090 0x7090
+	u16 version;
+
+	u16 tuner_enable;
+	struct i2c_adapter dib7090_tuner_adap;
+
+	/* for the I2C transfer */
+	struct i2c_msg msg[2];
+	u8 i2c_write_buffer[4];
+	u8 i2c_read_buffer[2];
+	struct mutex i2c_buffer_lock;
+
+	u8 input_mode_mpeg;
+};
+
+enum dib7000p_power_mode {
+	DIB7000P_POWER_ALL = 0,
+	DIB7000P_POWER_ANALOG_ADC,
+	DIB7000P_POWER_INTERFACE_ONLY,
+};
+
+/* dib7090 specific fonctions */
+static int dib7090_set_output_mode(struct dvb_frontend *fe, int mode);
+static int dib7090_set_diversity_in(struct dvb_frontend *fe, int onoff);
+static void dib7090_setDibTxMux(struct dib7000p_state *state, int mode);
+static void dib7090_setHostBusMux(struct dib7000p_state *state, int mode);
+
+static u16 dib7000p_read_word(struct dib7000p_state *state, u16 reg)
+{
+	u16 ret;
+
+	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
+		dprintk("could not acquire lock");
+		return 0;
+	}
+
+	state->i2c_write_buffer[0] = reg >> 8;
+	state->i2c_write_buffer[1] = reg & 0xff;
+
+	memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
+	state->msg[0].addr = state->i2c_addr >> 1;
+	state->msg[0].flags = 0;
+	state->msg[0].buf = state->i2c_write_buffer;
+	state->msg[0].len = 2;
+	state->msg[1].addr = state->i2c_addr >> 1;
+	state->msg[1].flags = I2C_M_RD;
+	state->msg[1].buf = state->i2c_read_buffer;
+	state->msg[1].len = 2;
+
+	if (i2c_transfer(state->i2c_adap, state->msg, 2) != 2)
+		dprintk("i2c read error on %d", reg);
+
+	ret = (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
+	mutex_unlock(&state->i2c_buffer_lock);
+	return ret;
+}
+
+static int dib7000p_write_word(struct dib7000p_state *state, u16 reg, u16 val)
+{
+	int ret;
+
+	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
+		dprintk("could not acquire lock");
+		return -EINVAL;
+	}
+
+	state->i2c_write_buffer[0] = (reg >> 8) & 0xff;
+	state->i2c_write_buffer[1] = reg & 0xff;
+	state->i2c_write_buffer[2] = (val >> 8) & 0xff;
+	state->i2c_write_buffer[3] = val & 0xff;
+
+	memset(&state->msg[0], 0, sizeof(struct i2c_msg));
+	state->msg[0].addr = state->i2c_addr >> 1;
+	state->msg[0].flags = 0;
+	state->msg[0].buf = state->i2c_write_buffer;
+	state->msg[0].len = 4;
+
+	ret = (i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ?
+			-EREMOTEIO : 0);
+	mutex_unlock(&state->i2c_buffer_lock);
+	return ret;
+}
+
+static void dib7000p_write_tab(struct dib7000p_state *state, u16 * buf)
+{
+	u16 l = 0, r, *n;
+	n = buf;
+	l = *n++;
+	while (l) {
+		r = *n++;
+
+		do {
+			dib7000p_write_word(state, r, *n++);
+			r++;
+		} while (--l);
+		l = *n++;
+	}
+}
+
+static int dib7000p_set_output_mode(struct dib7000p_state *state, int mode)
+{
+	int ret = 0;
+	u16 outreg, fifo_threshold, smo_mode;
+
+	outreg = 0;
+	fifo_threshold = 1792;
+	smo_mode = (dib7000p_read_word(state, 235) & 0x0050) | (1 << 1);
+
+	dprintk("setting output mode for demod %p to %d", &state->demod, mode);
+
+	switch (mode) {
+	case OUTMODE_MPEG2_PAR_GATED_CLK:
+		outreg = (1 << 10);	/* 0x0400 */
+		break;
+	case OUTMODE_MPEG2_PAR_CONT_CLK:
+		outreg = (1 << 10) | (1 << 6);	/* 0x0440 */
+		break;
+	case OUTMODE_MPEG2_SERIAL:
+		outreg = (1 << 10) | (2 << 6) | (0 << 1);	/* 0x0480 */
+		break;
+	case OUTMODE_DIVERSITY:
+		if (state->cfg.hostbus_diversity)
+			outreg = (1 << 10) | (4 << 6);	/* 0x0500 */
+		else
+			outreg = (1 << 11);
+		break;
+	case OUTMODE_MPEG2_FIFO:
+		smo_mode |= (3 << 1);
+		fifo_threshold = 512;
+		outreg = (1 << 10) | (5 << 6);
+		break;
+	case OUTMODE_ANALOG_ADC:
+		outreg = (1 << 10) | (3 << 6);
+		break;
+	case OUTMODE_HIGH_Z:
+		outreg = 0;
+		break;
+	default:
+		dprintk("Unhandled output_mode passed to be set for demod %p", &state->demod);
+		break;
+	}
+
+	if (state->cfg.output_mpeg2_in_188_bytes)
+		smo_mode |= (1 << 5);
+
+	ret |= dib7000p_write_word(state, 235, smo_mode);
+	ret |= dib7000p_write_word(state, 236, fifo_threshold);	/* synchronous fread */
+	if (state->version != SOC7090)
+		ret |= dib7000p_write_word(state, 1286, outreg);	/* P_Div_active */
+
+	return ret;
+}
+
+static int dib7000p_set_diversity_in(struct dvb_frontend *demod, int onoff)
+{
+	struct dib7000p_state *state = demod->demodulator_priv;
+
+	if (state->div_force_off) {
+		dprintk("diversity combination deactivated - forced by COFDM parameters");
+		onoff = 0;
+		dib7000p_write_word(state, 207, 0);
+	} else
+		dib7000p_write_word(state, 207, (state->div_sync_wait << 4) | (1 << 2) | (2 << 0));
+
+	state->div_state = (u8) onoff;
+
+	if (onoff) {
+		dib7000p_write_word(state, 204, 6);
+		dib7000p_write_word(state, 205, 16);
+		/* P_dvsy_sync_mode = 0, P_dvsy_sync_enable=1, P_dvcb_comb_mode=2 */
+	} else {
+		dib7000p_write_word(state, 204, 1);
+		dib7000p_write_word(state, 205, 0);
+	}
+
+	return 0;
+}
+
+static int dib7000p_set_power_mode(struct dib7000p_state *state, enum dib7000p_power_mode mode)
+{
+	/* by default everything is powered off */
+	u16 reg_774 = 0x3fff, reg_775 = 0xffff, reg_776 = 0x0007, reg_899 = 0x0003, reg_1280 = (0xfe00) | (dib7000p_read_word(state, 1280) & 0x01ff);
+
+	/* now, depending on the requested mode, we power on */
+	switch (mode) {
+		/* power up everything in the demod */
+	case DIB7000P_POWER_ALL:
+		reg_774 = 0x0000;
+		reg_775 = 0x0000;
+		reg_776 = 0x0;
+		reg_899 = 0x0;
+		if (state->version == SOC7090)
+			reg_1280 &= 0x001f;
+		else
+			reg_1280 &= 0x01ff;
+		break;
+
+	case DIB7000P_POWER_ANALOG_ADC:
+		/* dem, cfg, iqc, sad, agc */
+		reg_774 &= ~((1 << 15) | (1 << 14) | (1 << 11) | (1 << 10) | (1 << 9));
+		/* nud */
+		reg_776 &= ~((1 << 0));
+		/* Dout */
+		if (state->version != SOC7090)
+			reg_1280 &= ~((1 << 11));
+		reg_1280 &= ~(1 << 6);
+		/* fall through wanted to enable the interfaces */
+
+		/* just leave power on the control-interfaces: GPIO and (I2C or SDIO) */
+	case DIB7000P_POWER_INTERFACE_ONLY:	/* TODO power up either SDIO or I2C */
+		if (state->version == SOC7090)
+			reg_1280 &= ~((1 << 7) | (1 << 5));
+		else
+			reg_1280 &= ~((1 << 14) | (1 << 13) | (1 << 12) | (1 << 10));
+		break;
+
+/* TODO following stuff is just converted from the dib7000-driver - check when is used what */
+	}
+
+	dib7000p_write_word(state, 774, reg_774);
+	dib7000p_write_word(state, 775, reg_775);
+	dib7000p_write_word(state, 776, reg_776);
+	dib7000p_write_word(state, 1280, reg_1280);
+	if (state->version != SOC7090)
+		dib7000p_write_word(state, 899, reg_899);
+
+	return 0;
+}
+
+static void dib7000p_set_adc_state(struct dib7000p_state *state, enum dibx000_adc_states no)
+{
+	u16 reg_908 = 0, reg_909 = 0;
+	u16 reg;
+
+	if (state->version != SOC7090) {
+		reg_908 = dib7000p_read_word(state, 908);
+		reg_909 = dib7000p_read_word(state, 909);
+	}
+
+	switch (no) {
+	case DIBX000_SLOW_ADC_ON:
+		if (state->version == SOC7090) {
+			reg = dib7000p_read_word(state, 1925);
+
+			dib7000p_write_word(state, 1925, reg | (1 << 4) | (1 << 2));	/* en_slowAdc = 1 & reset_sladc = 1 */
+
+			reg = dib7000p_read_word(state, 1925);	/* read acces to make it works... strange ... */
+			msleep(200);
+			dib7000p_write_word(state, 1925, reg & ~(1 << 4));	/* en_slowAdc = 1 & reset_sladc = 0 */
+
+			reg = dib7000p_read_word(state, 72) & ~((0x3 << 14) | (0x3 << 12));
+			dib7000p_write_word(state, 72, reg | (1 << 14) | (3 << 12) | 524);	/* ref = Vin1 => Vbg ; sel = Vin0 or Vin3 ; (Vin2 = Vcm) */
+		} else {
+			reg_909 |= (1 << 1) | (1 << 0);
+			dib7000p_write_word(state, 909, reg_909);
+			reg_909 &= ~(1 << 1);
+		}
+		break;
+
+	case DIBX000_SLOW_ADC_OFF:
+		if (state->version == SOC7090) {
+			reg = dib7000p_read_word(state, 1925);
+			dib7000p_write_word(state, 1925, (reg & ~(1 << 2)) | (1 << 4));	/* reset_sladc = 1 en_slowAdc = 0 */
+		} else
+			reg_909 |= (1 << 1) | (1 << 0);
+		break;
+
+	case DIBX000_ADC_ON:
+		reg_908 &= 0x0fff;
+		reg_909 &= 0x0003;
+		break;
+
+	case DIBX000_ADC_OFF:
+		reg_908 |= (1 << 14) | (1 << 13) | (1 << 12);
+		reg_909 |= (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2);
+		break;
+
+	case DIBX000_VBG_ENABLE:
+		reg_908 &= ~(1 << 15);
+		break;
+
+	case DIBX000_VBG_DISABLE:
+		reg_908 |= (1 << 15);
+		break;
+
+	default:
+		break;
+	}
+
+//	dprintk( "908: %x, 909: %x\n", reg_908, reg_909);
+
+	reg_909 |= (state->cfg.disable_sample_and_hold & 1) << 4;
+	reg_908 |= (state->cfg.enable_current_mirror & 1) << 7;
+
+	if (state->version != SOC7090) {
+		dib7000p_write_word(state, 908, reg_908);
+		dib7000p_write_word(state, 909, reg_909);
+	}
+}
+
+static int dib7000p_set_bandwidth(struct dib7000p_state *state, u32 bw)
+{
+	u32 timf;
+
+	// store the current bandwidth for later use
+	state->current_bandwidth = bw;
+
+	if (state->timf == 0) {
+		dprintk("using default timf");
+		timf = state->cfg.bw->timf;
+	} else {
+		dprintk("using updated timf");
+		timf = state->timf;
+	}
+
+	timf = timf * (bw / 50) / 160;
+
+	dib7000p_write_word(state, 23, (u16) ((timf >> 16) & 0xffff));
+	dib7000p_write_word(state, 24, (u16) ((timf) & 0xffff));
+
+	return 0;
+}
+
+static int dib7000p_sad_calib(struct dib7000p_state *state)
+{
+/* internal */
+	dib7000p_write_word(state, 73, (0 << 1) | (0 << 0));
+
+	if (state->version == SOC7090)
+		dib7000p_write_word(state, 74, 2048);
+	else
+		dib7000p_write_word(state, 74, 776);
+
+	/* do the calibration */
+	dib7000p_write_word(state, 73, (1 << 0));
+	dib7000p_write_word(state, 73, (0 << 0));
+
+	msleep(1);
+
+	return 0;
+}
+
+int dib7000p_set_wbd_ref(struct dvb_frontend *demod, u16 value)
+{
+	struct dib7000p_state *state = demod->demodulator_priv;
+	if (value > 4095)
+		value = 4095;
+	state->wbd_ref = value;
+	return dib7000p_write_word(state, 105, (dib7000p_read_word(state, 105) & 0xf000) | value);
+}
+EXPORT_SYMBOL(dib7000p_set_wbd_ref);
+
+int dib7000p_get_agc_values(struct dvb_frontend *fe,
+		u16 *agc_global, u16 *agc1, u16 *agc2, u16 *wbd)
+{
+	struct dib7000p_state *state = fe->demodulator_priv;
+
+	if (agc_global != NULL)
+		*agc_global = dib7000p_read_word(state, 394);
+	if (agc1 != NULL)
+		*agc1 = dib7000p_read_word(state, 392);
+	if (agc2 != NULL)
+		*agc2 = dib7000p_read_word(state, 393);
+	if (wbd != NULL)
+		*wbd = dib7000p_read_word(state, 397);
+
+	return 0;
+}
+EXPORT_SYMBOL(dib7000p_get_agc_values);
+
+static void dib7000p_reset_pll(struct dib7000p_state *state)
+{
+	struct dibx000_bandwidth_config *bw = &state->cfg.bw[0];
+	u16 clk_cfg0;
+
+	if (state->version == SOC7090) {
+		dib7000p_write_word(state, 1856, (!bw->pll_reset << 13) | (bw->pll_range << 12) | (bw->pll_ratio << 6) | (bw->pll_prediv));
+
+		while (((dib7000p_read_word(state, 1856) >> 15) & 0x1) != 1)
+			;
+
+		dib7000p_write_word(state, 1857, dib7000p_read_word(state, 1857) | (!bw->pll_bypass << 15));
+	} else {
+		/* force PLL bypass */
+		clk_cfg0 = (1 << 15) | ((bw->pll_ratio & 0x3f) << 9) |
+			(bw->modulo << 7) | (bw->ADClkSrc << 6) | (bw->IO_CLK_en_core << 5) | (bw->bypclk_div << 2) | (bw->enable_refdiv << 1) | (0 << 0);
+
+		dib7000p_write_word(state, 900, clk_cfg0);
+
+		/* P_pll_cfg */
+		dib7000p_write_word(state, 903, (bw->pll_prediv << 5) | (((bw->pll_ratio >> 6) & 0x3) << 3) | (bw->pll_range << 1) | bw->pll_reset);
+		clk_cfg0 = (bw->pll_bypass << 15) | (clk_cfg0 & 0x7fff);
+		dib7000p_write_word(state, 900, clk_cfg0);
+	}
+
+	dib7000p_write_word(state, 18, (u16) (((bw->internal * 1000) >> 16) & 0xffff));
+	dib7000p_write_word(state, 19, (u16) ((bw->internal * 1000) & 0xffff));
+	dib7000p_write_word(state, 21, (u16) ((bw->ifreq >> 16) & 0xffff));
+	dib7000p_write_word(state, 22, (u16) ((bw->ifreq) & 0xffff));
+
+	dib7000p_write_word(state, 72, bw->sad_cfg);
+}
+
+static u32 dib7000p_get_internal_freq(struct dib7000p_state *state)
+{
+	u32 internal = (u32) dib7000p_read_word(state, 18) << 16;
+	internal |= (u32) dib7000p_read_word(state, 19);
+	internal /= 1000;
+
+	return internal;
+}
+
+int dib7000p_update_pll(struct dvb_frontend *fe, struct dibx000_bandwidth_config *bw)
+{
+	struct dib7000p_state *state = fe->demodulator_priv;
+	u16 reg_1857, reg_1856 = dib7000p_read_word(state, 1856);
+	u8 loopdiv, prediv;
+	u32 internal, xtal;
+
+	/* get back old values */
+	prediv = reg_1856 & 0x3f;
+	loopdiv = (reg_1856 >> 6) & 0x3f;
+
+	if ((bw != NULL) && (bw->pll_prediv != prediv || bw->pll_ratio != loopdiv)) {
+		dprintk("Updating pll (prediv: old =  %d new = %d ; loopdiv : old = %d new = %d)", prediv, bw->pll_prediv, loopdiv, bw->pll_ratio);
+		reg_1856 &= 0xf000;
+		reg_1857 = dib7000p_read_word(state, 1857);
+		dib7000p_write_word(state, 1857, reg_1857 & ~(1 << 15));
+
+		dib7000p_write_word(state, 1856, reg_1856 | ((bw->pll_ratio & 0x3f) << 6) | (bw->pll_prediv & 0x3f));
+
+		/* write new system clk into P_sec_len */
+		internal = dib7000p_get_internal_freq(state);
+		xtal = (internal / loopdiv) * prediv;
+		internal = 1000 * (xtal / bw->pll_prediv) * bw->pll_ratio;	/* new internal */
+		dib7000p_write_word(state, 18, (u16) ((internal >> 16) & 0xffff));
+		dib7000p_write_word(state, 19, (u16) (internal & 0xffff));
+
+		dib7000p_write_word(state, 1857, reg_1857 | (1 << 15));
+
+		while (((dib7000p_read_word(state, 1856) >> 15) & 0x1) != 1)
+			dprintk("Waiting for PLL to lock");
+
+		return 0;
+	}
+	return -EIO;
+}
+EXPORT_SYMBOL(dib7000p_update_pll);
+
+static int dib7000p_reset_gpio(struct dib7000p_state *st)
+{
+	/* reset the GPIOs */
+	dprintk("gpio dir: %x: val: %x, pwm_pos: %x", st->gpio_dir, st->gpio_val, st->cfg.gpio_pwm_pos);
+
+	dib7000p_write_word(st, 1029, st->gpio_dir);
+	dib7000p_write_word(st, 1030, st->gpio_val);
+
+	/* TODO 1031 is P_gpio_od */
+
+	dib7000p_write_word(st, 1032, st->cfg.gpio_pwm_pos);
+
+	dib7000p_write_word(st, 1037, st->cfg.pwm_freq_div);
+	return 0;
+}
+
+static int dib7000p_cfg_gpio(struct dib7000p_state *st, u8 num, u8 dir, u8 val)
+{
+	st->gpio_dir = dib7000p_read_word(st, 1029);
+	st->gpio_dir &= ~(1 << num);	/* reset the direction bit */
+	st->gpio_dir |= (dir & 0x1) << num;	/* set the new direction */
+	dib7000p_write_word(st, 1029, st->gpio_dir);
+
+	st->gpio_val = dib7000p_read_word(st, 1030);
+	st->gpio_val &= ~(1 << num);	/* reset the direction bit */
+	st->gpio_val |= (val & 0x01) << num;	/* set the new value */
+	dib7000p_write_word(st, 1030, st->gpio_val);
+
+	return 0;
+}
+
+int dib7000p_set_gpio(struct dvb_frontend *demod, u8 num, u8 dir, u8 val)
+{
+	struct dib7000p_state *state = demod->demodulator_priv;
+	return dib7000p_cfg_gpio(state, num, dir, val);
+}
+EXPORT_SYMBOL(dib7000p_set_gpio);
+
+static u16 dib7000p_defaults[] = {
+	// auto search configuration
+	3, 2,
+	0x0004,
+	(1<<3)|(1<<11)|(1<<12)|(1<<13),
+	0x0814,			/* Equal Lock */
+
+	12, 6,
+	0x001b,
+	0x7740,
+	0x005b,
+	0x8d80,
+	0x01c9,
+	0xc380,
+	0x0000,
+	0x0080,
+	0x0000,
+	0x0090,
+	0x0001,
+	0xd4c0,
+
+	1, 26,
+	0x6680,
+
+	/* set ADC level to -16 */
+	11, 79,
+	(1 << 13) - 825 - 117,
+	(1 << 13) - 837 - 117,
+	(1 << 13) - 811 - 117,
+	(1 << 13) - 766 - 117,
+	(1 << 13) - 737 - 117,
+	(1 << 13) - 693 - 117,
+	(1 << 13) - 648 - 117,
+	(1 << 13) - 619 - 117,
+	(1 << 13) - 575 - 117,
+	(1 << 13) - 531 - 117,
+	(1 << 13) - 501 - 117,
+
+	1, 142,
+	0x0410,
+
+	/* disable power smoothing */
+	8, 145,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+
+	1, 154,
+	1 << 13,
+
+	1, 168,
+	0x0ccd,
+
+	1, 183,
+	0x200f,
+
+	1, 212,
+		0x169,
+
+	5, 187,
+	0x023d,
+	0x00a4,
+	0x00a4,
+	0x7ff0,
+	0x3ccc,
+
+	1, 198,
+	0x800,
+
+	1, 222,
+	0x0010,
+
+	1, 235,
+	0x0062,
+
+	0,
+};
+
+static int dib7000p_demod_reset(struct dib7000p_state *state)
+{
+	dib7000p_set_power_mode(state, DIB7000P_POWER_ALL);
+
+	if (state->version == SOC7090)
+		dibx000_reset_i2c_master(&state->i2c_master);
+
+	dib7000p_set_adc_state(state, DIBX000_VBG_ENABLE);
+
+	/* restart all parts */
+	dib7000p_write_word(state, 770, 0xffff);
+	dib7000p_write_word(state, 771, 0xffff);
+	dib7000p_write_word(state, 772, 0x001f);
+	dib7000p_write_word(state, 1280, 0x001f - ((1 << 4) | (1 << 3)));
+
+	dib7000p_write_word(state, 770, 0);
+	dib7000p_write_word(state, 771, 0);
+	dib7000p_write_word(state, 772, 0);
+	dib7000p_write_word(state, 1280, 0);
+
+	if (state->version != SOC7090) {
+		dib7000p_write_word(state,  898, 0x0003);
+		dib7000p_write_word(state,  898, 0);
+	}
+
+	/* default */
+	dib7000p_reset_pll(state);
+
+	if (dib7000p_reset_gpio(state) != 0)
+		dprintk("GPIO reset was not successful.");
+
+	if (state->version == SOC7090) {
+		dib7000p_write_word(state, 899, 0);
+
+		/* impulse noise */
+		dib7000p_write_word(state, 42, (1<<5) | 3); /* P_iqc_thsat_ipc = 1 ; P_iqc_win2 = 3 */
+		dib7000p_write_word(state, 43, 0x2d4); /*-300 fag P_iqc_dect_min = -280 */
+		dib7000p_write_word(state, 44, 300); /* 300 fag P_iqc_dect_min = +280 */
+		dib7000p_write_word(state, 273, (0<<6) | 30);
+	}
+	if (dib7000p_set_output_mode(state, OUTMODE_HIGH_Z) != 0)
+		dprintk("OUTPUT_MODE could not be reset.");
+
+	dib7000p_set_adc_state(state, DIBX000_SLOW_ADC_ON);
+	dib7000p_sad_calib(state);
+	dib7000p_set_adc_state(state, DIBX000_SLOW_ADC_OFF);
+
+	/* unforce divstr regardless whether i2c enumeration was done or not */
+	dib7000p_write_word(state, 1285, dib7000p_read_word(state, 1285) & ~(1 << 1));
+
+	dib7000p_set_bandwidth(state, 8000);
+
+	if (state->version == SOC7090) {
+		dib7000p_write_word(state, 36, 0x0755);/* P_iqc_impnc_on =1 & P_iqc_corr_inh = 1 for impulsive noise */
+	} else {
+		if (state->cfg.tuner_is_baseband)
+			dib7000p_write_word(state, 36, 0x0755);
+		else
+			dib7000p_write_word(state, 36, 0x1f55);
+	}
+
+	dib7000p_write_tab(state, dib7000p_defaults);
+	if (state->version != SOC7090) {
+		dib7000p_write_word(state, 901, 0x0006);
+		dib7000p_write_word(state, 902, (3 << 10) | (1 << 6));
+		dib7000p_write_word(state, 905, 0x2c8e);
+	}
+
+	dib7000p_set_power_mode(state, DIB7000P_POWER_INTERFACE_ONLY);
+
+	return 0;
+}
+
+static void dib7000p_pll_clk_cfg(struct dib7000p_state *state)
+{
+	u16 tmp = 0;
+	tmp = dib7000p_read_word(state, 903);
+	dib7000p_write_word(state, 903, (tmp | 0x1));
+	tmp = dib7000p_read_word(state, 900);
+	dib7000p_write_word(state, 900, (tmp & 0x7fff) | (1 << 6));
+}
+
+static void dib7000p_restart_agc(struct dib7000p_state *state)
+{
+	// P_restart_iqc & P_restart_agc
+	dib7000p_write_word(state, 770, (1 << 11) | (1 << 9));
+	dib7000p_write_word(state, 770, 0x0000);
+}
+
+static int dib7000p_update_lna(struct dib7000p_state *state)
+{
+	u16 dyn_gain;
+
+	if (state->cfg.update_lna) {
+		dyn_gain = dib7000p_read_word(state, 394);
+		if (state->cfg.update_lna(&state->demod, dyn_gain)) {
+			dib7000p_restart_agc(state);
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+static int dib7000p_set_agc_config(struct dib7000p_state *state, u8 band)
+{
+	struct dibx000_agc_config *agc = NULL;
+	int i;
+	if (state->current_band == band && state->current_agc != NULL)
+		return 0;
+	state->current_band = band;
+
+	for (i = 0; i < state->cfg.agc_config_count; i++)
+		if (state->cfg.agc[i].band_caps & band) {
+			agc = &state->cfg.agc[i];
+			break;
+		}
+
+	if (agc == NULL) {
+		dprintk("no valid AGC configuration found for band 0x%02x", band);
+		return -EINVAL;
+	}
+
+	state->current_agc = agc;
+
+	/* AGC */
+	dib7000p_write_word(state, 75, agc->setup);
+	dib7000p_write_word(state, 76, agc->inv_gain);
+	dib7000p_write_word(state, 77, agc->time_stabiliz);
+	dib7000p_write_word(state, 100, (agc->alpha_level << 12) | agc->thlock);
+
+	// Demod AGC loop configuration
+	dib7000p_write_word(state, 101, (agc->alpha_mant << 5) | agc->alpha_exp);
+	dib7000p_write_word(state, 102, (agc->beta_mant << 6) | agc->beta_exp);
+
+	/* AGC continued */
+	dprintk("WBD: ref: %d, sel: %d, active: %d, alpha: %d",
+		state->wbd_ref != 0 ? state->wbd_ref : agc->wbd_ref, agc->wbd_sel, !agc->perform_agc_softsplit, agc->wbd_sel);
+
+	if (state->wbd_ref != 0)
+		dib7000p_write_word(state, 105, (agc->wbd_inv << 12) | state->wbd_ref);
+	else
+		dib7000p_write_word(state, 105, (agc->wbd_inv << 12) | agc->wbd_ref);
+
+	dib7000p_write_word(state, 106, (agc->wbd_sel << 13) | (agc->wbd_alpha << 9) | (agc->perform_agc_softsplit << 8));
+
+	dib7000p_write_word(state, 107, agc->agc1_max);
+	dib7000p_write_word(state, 108, agc->agc1_min);
+	dib7000p_write_word(state, 109, agc->agc2_max);
+	dib7000p_write_word(state, 110, agc->agc2_min);
+	dib7000p_write_word(state, 111, (agc->agc1_pt1 << 8) | agc->agc1_pt2);
+	dib7000p_write_word(state, 112, agc->agc1_pt3);
+	dib7000p_write_word(state, 113, (agc->agc1_slope1 << 8) | agc->agc1_slope2);
+	dib7000p_write_word(state, 114, (agc->agc2_pt1 << 8) | agc->agc2_pt2);
+	dib7000p_write_word(state, 115, (agc->agc2_slope1 << 8) | agc->agc2_slope2);
+	return 0;
+}
+
+static void dib7000p_set_dds(struct dib7000p_state *state, s32 offset_khz)
+{
+	u32 internal = dib7000p_get_internal_freq(state);
+	s32 unit_khz_dds_val = 67108864 / (internal);	/* 2**26 / Fsampling is the unit 1KHz offset */
+	u32 abs_offset_khz = ABS(offset_khz);
+	u32 dds = state->cfg.bw->ifreq & 0x1ffffff;
+	u8 invert = !!(state->cfg.bw->ifreq & (1 << 25));
+
+	dprintk("setting a frequency offset of %dkHz internal freq = %d invert = %d", offset_khz, internal, invert);
+
+	if (offset_khz < 0)
+		unit_khz_dds_val *= -1;
+
+	/* IF tuner */
+	if (invert)
+		dds -= (abs_offset_khz * unit_khz_dds_val);	/* /100 because of /100 on the unit_khz_dds_val line calc for better accuracy */
+	else
+		dds += (abs_offset_khz * unit_khz_dds_val);
+
+	if (abs_offset_khz <= (internal / 2)) {	/* Max dds offset is the half of the demod freq */
+		dib7000p_write_word(state, 21, (u16) (((dds >> 16) & 0x1ff) | (0 << 10) | (invert << 9)));
+		dib7000p_write_word(state, 22, (u16) (dds & 0xffff));
+	}
+}
+
+static int dib7000p_agc_startup(struct dvb_frontend *demod)
+{
+	struct dtv_frontend_properties *ch = &demod->dtv_property_cache;
+	struct dib7000p_state *state = demod->demodulator_priv;
+	int ret = -1;
+	u8 *agc_state = &state->agc_state;
+	u8 agc_split;
+	u16 reg;
+	u32 upd_demod_gain_period = 0x1000;
+
+	switch (state->agc_state) {
+	case 0:
+		dib7000p_set_power_mode(state, DIB7000P_POWER_ALL);
+		if (state->version == SOC7090) {
+			reg = dib7000p_read_word(state, 0x79b) & 0xff00;
+			dib7000p_write_word(state, 0x79a, upd_demod_gain_period & 0xFFFF);	/* lsb */
+			dib7000p_write_word(state, 0x79b, reg | (1 << 14) | ((upd_demod_gain_period >> 16) & 0xFF));
+
+			/* enable adc i & q */
+			reg = dib7000p_read_word(state, 0x780);
+			dib7000p_write_word(state, 0x780, (reg | (0x3)) & (~(1 << 7)));
+		} else {
+			dib7000p_set_adc_state(state, DIBX000_ADC_ON);
+			dib7000p_pll_clk_cfg(state);
+		}
+
+		if (dib7000p_set_agc_config(state, BAND_OF_FREQUENCY(ch->frequency / 1000)) != 0)
+			return -1;
+
+		dib7000p_set_dds(state, 0);
+		ret = 7;
+		(*agc_state)++;
+		break;
+
+	case 1:
+		if (state->cfg.agc_control)
+			state->cfg.agc_control(&state->demod, 1);
+
+		dib7000p_write_word(state, 78, 32768);
+		if (!state->current_agc->perform_agc_softsplit) {
+			/* we are using the wbd - so slow AGC startup */
+			/* force 0 split on WBD and restart AGC */
+			dib7000p_write_word(state, 106, (state->current_agc->wbd_sel << 13) | (state->current_agc->wbd_alpha << 9) | (1 << 8));
+			(*agc_state)++;
+			ret = 5;
+		} else {
+			/* default AGC startup */
+			(*agc_state) = 4;
+			/* wait AGC rough lock time */
+			ret = 7;
+		}
+
+		dib7000p_restart_agc(state);
+		break;
+
+	case 2:		/* fast split search path after 5sec */
+		dib7000p_write_word(state, 75, state->current_agc->setup | (1 << 4));	/* freeze AGC loop */
+		dib7000p_write_word(state, 106, (state->current_agc->wbd_sel << 13) | (2 << 9) | (0 << 8));	/* fast split search 0.25kHz */
+		(*agc_state)++;
+		ret = 14;
+		break;
+
+	case 3:		/* split search ended */
+		agc_split = (u8) dib7000p_read_word(state, 396);	/* store the split value for the next time */
+		dib7000p_write_word(state, 78, dib7000p_read_word(state, 394));	/* set AGC gain start value */
+
+		dib7000p_write_word(state, 75, state->current_agc->setup);	/* std AGC loop */
+		dib7000p_write_word(state, 106, (state->current_agc->wbd_sel << 13) | (state->current_agc->wbd_alpha << 9) | agc_split);	/* standard split search */
+
+		dib7000p_restart_agc(state);
+
+		dprintk("SPLIT %p: %hd", demod, agc_split);
+
+		(*agc_state)++;
+		ret = 5;
+		break;
+
+	case 4:		/* LNA startup */
+		ret = 7;
+
+		if (dib7000p_update_lna(state))
+			ret = 5;
+		else
+			(*agc_state)++;
+		break;
+
+	case 5:
+		if (state->cfg.agc_control)
+			state->cfg.agc_control(&state->demod, 0);
+		(*agc_state)++;
+		break;
+	default:
+		break;
+	}
+	return ret;
+}
+
+static void dib7000p_update_timf(struct dib7000p_state *state)
+{
+	u32 timf = (dib7000p_read_word(state, 427) << 16) | dib7000p_read_word(state, 428);
+	state->timf = timf * 160 / (state->current_bandwidth / 50);
+	dib7000p_write_word(state, 23, (u16) (timf >> 16));
+	dib7000p_write_word(state, 24, (u16) (timf & 0xffff));
+	dprintk("updated timf_frequency: %d (default: %d)", state->timf, state->cfg.bw->timf);
+
+}
+
+u32 dib7000p_ctrl_timf(struct dvb_frontend *fe, u8 op, u32 timf)
+{
+	struct dib7000p_state *state = fe->demodulator_priv;
+	switch (op) {
+	case DEMOD_TIMF_SET:
+		state->timf = timf;
+		break;
+	case DEMOD_TIMF_UPDATE:
+		dib7000p_update_timf(state);
+		break;
+	case DEMOD_TIMF_GET:
+		break;
+	}
+	dib7000p_set_bandwidth(state, state->current_bandwidth);
+	return state->timf;
+}
+EXPORT_SYMBOL(dib7000p_ctrl_timf);
+
+static void dib7000p_set_channel(struct dib7000p_state *state,
+				 struct dtv_frontend_properties *ch, u8 seq)
+{
+	u16 value, est[4];
+
+	dib7000p_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->bandwidth_hz));
+
+	/* nfft, guard, qam, alpha */
+	value = 0;
+	switch (ch->transmission_mode) {
+	case TRANSMISSION_MODE_2K:
+		value |= (0 << 7);
+		break;
+	case TRANSMISSION_MODE_4K:
+		value |= (2 << 7);
+		break;
+	default:
+	case TRANSMISSION_MODE_8K:
+		value |= (1 << 7);
+		break;
+	}
+	switch (ch->guard_interval) {
+	case GUARD_INTERVAL_1_32:
+		value |= (0 << 5);
+		break;
+	case GUARD_INTERVAL_1_16:
+		value |= (1 << 5);
+		break;
+	case GUARD_INTERVAL_1_4:
+		value |= (3 << 5);
+		break;
+	default:
+	case GUARD_INTERVAL_1_8:
+		value |= (2 << 5);
+		break;
+	}
+	switch (ch->modulation) {
+	case QPSK:
+		value |= (0 << 3);
+		break;
+	case QAM_16:
+		value |= (1 << 3);
+		break;
+	default:
+	case QAM_64:
+		value |= (2 << 3);
+		break;
+	}
+	switch (HIERARCHY_1) {
+	case HIERARCHY_2:
+		value |= 2;
+		break;
+	case HIERARCHY_4:
+		value |= 4;
+		break;
+	default:
+	case HIERARCHY_1:
+		value |= 1;
+		break;
+	}
+	dib7000p_write_word(state, 0, value);
+	dib7000p_write_word(state, 5, (seq << 4) | 1);	/* do not force tps, search list 0 */
+
+	/* P_dintl_native, P_dintlv_inv, P_hrch, P_code_rate, P_select_hp */
+	value = 0;
+	if (1 != 0)
+		value |= (1 << 6);
+	if (ch->hierarchy == 1)
+		value |= (1 << 4);
+	if (1 == 1)
+		value |= 1;
+	switch ((ch->hierarchy == 0 || 1 == 1) ? ch->code_rate_HP : ch->code_rate_LP) {
+	case FEC_2_3:
+		value |= (2 << 1);
+		break;
+	case FEC_3_4:
+		value |= (3 << 1);
+		break;
+	case FEC_5_6:
+		value |= (5 << 1);
+		break;
+	case FEC_7_8:
+		value |= (7 << 1);
+		break;
+	default:
+	case FEC_1_2:
+		value |= (1 << 1);
+		break;
+	}
+	dib7000p_write_word(state, 208, value);
+
+	/* offset loop parameters */
+	dib7000p_write_word(state, 26, 0x6680);
+	dib7000p_write_word(state, 32, 0x0003);
+	dib7000p_write_word(state, 29, 0x1273);
+	dib7000p_write_word(state, 33, 0x0005);
+
+	/* P_dvsy_sync_wait */
+	switch (ch->transmission_mode) {
+	case TRANSMISSION_MODE_8K:
+		value = 256;
+		break;
+	case TRANSMISSION_MODE_4K:
+		value = 128;
+		break;
+	case TRANSMISSION_MODE_2K:
+	default:
+		value = 64;
+		break;
+	}
+	switch (ch->guard_interval) {
+	case GUARD_INTERVAL_1_16:
+		value *= 2;
+		break;
+	case GUARD_INTERVAL_1_8:
+		value *= 4;
+		break;
+	case GUARD_INTERVAL_1_4:
+		value *= 8;
+		break;
+	default:
+	case GUARD_INTERVAL_1_32:
+		value *= 1;
+		break;
+	}
+	if (state->cfg.diversity_delay == 0)
+		state->div_sync_wait = (value * 3) / 2 + 48;
+	else
+		state->div_sync_wait = (value * 3) / 2 + state->cfg.diversity_delay;
+
+	/* deactive the possibility of diversity reception if extended interleaver */
+	state->div_force_off = !1 && ch->transmission_mode != TRANSMISSION_MODE_8K;
+	dib7000p_set_diversity_in(&state->demod, state->div_state);
+
+	/* channel estimation fine configuration */
+	switch (ch->modulation) {
+	case QAM_64:
+		est[0] = 0x0148;	/* P_adp_regul_cnt 0.04 */
+		est[1] = 0xfff0;	/* P_adp_noise_cnt -0.002 */
+		est[2] = 0x00a4;	/* P_adp_regul_ext 0.02 */
+		est[3] = 0xfff8;	/* P_adp_noise_ext -0.001 */
+		break;
+	case QAM_16:
+		est[0] = 0x023d;	/* P_adp_regul_cnt 0.07 */
+		est[1] = 0xffdf;	/* P_adp_noise_cnt -0.004 */
+		est[2] = 0x00a4;	/* P_adp_regul_ext 0.02 */
+		est[3] = 0xfff0;	/* P_adp_noise_ext -0.002 */
+		break;
+	default:
+		est[0] = 0x099a;	/* P_adp_regul_cnt 0.3 */
+		est[1] = 0xffae;	/* P_adp_noise_cnt -0.01 */
+		est[2] = 0x0333;	/* P_adp_regul_ext 0.1 */
+		est[3] = 0xfff8;	/* P_adp_noise_ext -0.002 */
+		break;
+	}
+	for (value = 0; value < 4; value++)
+		dib7000p_write_word(state, 187 + value, est[value]);
+}
+
+static int dib7000p_autosearch_start(struct dvb_frontend *demod)
+{
+	struct dtv_frontend_properties *ch = &demod->dtv_property_cache;
+	struct dib7000p_state *state = demod->demodulator_priv;
+	struct dtv_frontend_properties schan;
+	u32 value, factor;
+	u32 internal = dib7000p_get_internal_freq(state);
+
+	schan = *ch;
+	schan.modulation = QAM_64;
+	schan.guard_interval = GUARD_INTERVAL_1_32;
+	schan.transmission_mode = TRANSMISSION_MODE_8K;
+	schan.code_rate_HP = FEC_2_3;
+	schan.code_rate_LP = FEC_3_4;
+	schan.hierarchy = 0;
+
+	dib7000p_set_channel(state, &schan, 7);
+
+	factor = BANDWIDTH_TO_KHZ(ch->bandwidth_hz);
+	if (factor >= 5000) {
+		if (state->version == SOC7090)
+			factor = 2;
+		else
+			factor = 1;
+	} else
+		factor = 6;
+
+	value = 30 * internal * factor;
+	dib7000p_write_word(state, 6, (u16) ((value >> 16) & 0xffff));
+	dib7000p_write_word(state, 7, (u16) (value & 0xffff));
+	value = 100 * internal * factor;
+	dib7000p_write_word(state, 8, (u16) ((value >> 16) & 0xffff));
+	dib7000p_write_word(state, 9, (u16) (value & 0xffff));
+	value = 500 * internal * factor;
+	dib7000p_write_word(state, 10, (u16) ((value >> 16) & 0xffff));
+	dib7000p_write_word(state, 11, (u16) (value & 0xffff));
+
+	value = dib7000p_read_word(state, 0);
+	dib7000p_write_word(state, 0, (u16) ((1 << 9) | value));
+	dib7000p_read_word(state, 1284);
+	dib7000p_write_word(state, 0, (u16) value);
+
+	return 0;
+}
+
+static int dib7000p_autosearch_is_irq(struct dvb_frontend *demod)
+{
+	struct dib7000p_state *state = demod->demodulator_priv;
+	u16 irq_pending = dib7000p_read_word(state, 1284);
+
+	if (irq_pending & 0x1)
+		return 1;
+
+	if (irq_pending & 0x2)
+		return 2;
+
+	return 0;
+}
+
+static void dib7000p_spur_protect(struct dib7000p_state *state, u32 rf_khz, u32 bw)
+{
+	static s16 notch[] = { 16143, 14402, 12238, 9713, 6902, 3888, 759, -2392 };
+	static u8 sine[] = { 0, 2, 3, 5, 6, 8, 9, 11, 13, 14, 16, 17, 19, 20, 22,
+		24, 25, 27, 28, 30, 31, 33, 34, 36, 38, 39, 41, 42, 44, 45, 47, 48, 50, 51,
+		53, 55, 56, 58, 59, 61, 62, 64, 65, 67, 68, 70, 71, 73, 74, 76, 77, 79, 80,
+		82, 83, 85, 86, 88, 89, 91, 92, 94, 95, 97, 98, 99, 101, 102, 104, 105,
+		107, 108, 109, 111, 112, 114, 115, 117, 118, 119, 121, 122, 123, 125, 126,
+		128, 129, 130, 132, 133, 134, 136, 137, 138, 140, 141, 142, 144, 145, 146,
+		147, 149, 150, 151, 152, 154, 155, 156, 157, 159, 160, 161, 162, 164, 165,
+		166, 167, 168, 170, 171, 172, 173, 174, 175, 177, 178, 179, 180, 181, 182,
+		183, 184, 185, 186, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198,
+		199, 200, 201, 202, 203, 204, 205, 206, 207, 207, 208, 209, 210, 211, 212,
+		213, 214, 215, 215, 216, 217, 218, 219, 220, 220, 221, 222, 223, 224, 224,
+		225, 226, 227, 227, 228, 229, 229, 230, 231, 231, 232, 233, 233, 234, 235,
+		235, 236, 237, 237, 238, 238, 239, 239, 240, 241, 241, 242, 242, 243, 243,
+		244, 244, 245, 245, 245, 246, 246, 247, 247, 248, 248, 248, 249, 249, 249,
+		250, 250, 250, 251, 251, 251, 252, 252, 252, 252, 253, 253, 253, 253, 254,
+		254, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+		255, 255, 255, 255, 255, 255
+	};
+
+	u32 xtal = state->cfg.bw->xtal_hz / 1000;
+	int f_rel = DIV_ROUND_CLOSEST(rf_khz, xtal) * xtal - rf_khz;
+	int k;
+	int coef_re[8], coef_im[8];
+	int bw_khz = bw;
+	u32 pha;
+
+	dprintk("relative position of the Spur: %dk (RF: %dk, XTAL: %dk)", f_rel, rf_khz, xtal);
+
+	if (f_rel < -bw_khz / 2 || f_rel > bw_khz / 2)
+		return;
+
+	bw_khz /= 100;
+
+	dib7000p_write_word(state, 142, 0x0610);
+
+	for (k = 0; k < 8; k++) {
+		pha = ((f_rel * (k + 1) * 112 * 80 / bw_khz) / 1000) & 0x3ff;
+
+		if (pha == 0) {
+			coef_re[k] = 256;
+			coef_im[k] = 0;
+		} else if (pha < 256) {
+			coef_re[k] = sine[256 - (pha & 0xff)];
+			coef_im[k] = sine[pha & 0xff];
+		} else if (pha == 256) {
+			coef_re[k] = 0;
+			coef_im[k] = 256;
+		} else if (pha < 512) {
+			coef_re[k] = -sine[pha & 0xff];
+			coef_im[k] = sine[256 - (pha & 0xff)];
+		} else if (pha == 512) {
+			coef_re[k] = -256;
+			coef_im[k] = 0;
+		} else if (pha < 768) {
+			coef_re[k] = -sine[256 - (pha & 0xff)];
+			coef_im[k] = -sine[pha & 0xff];
+		} else if (pha == 768) {
+			coef_re[k] = 0;
+			coef_im[k] = -256;
+		} else {
+			coef_re[k] = sine[pha & 0xff];
+			coef_im[k] = -sine[256 - (pha & 0xff)];
+		}
+
+		coef_re[k] *= notch[k];
+		coef_re[k] += (1 << 14);
+		if (coef_re[k] >= (1 << 24))
+			coef_re[k] = (1 << 24) - 1;
+		coef_re[k] /= (1 << 15);
+
+		coef_im[k] *= notch[k];
+		coef_im[k] += (1 << 14);
+		if (coef_im[k] >= (1 << 24))
+			coef_im[k] = (1 << 24) - 1;
+		coef_im[k] /= (1 << 15);
+
+		dprintk("PALF COEF: %d re: %d im: %d", k, coef_re[k], coef_im[k]);
+
+		dib7000p_write_word(state, 143, (0 << 14) | (k << 10) | (coef_re[k] & 0x3ff));
+		dib7000p_write_word(state, 144, coef_im[k] & 0x3ff);
+		dib7000p_write_word(state, 143, (1 << 14) | (k << 10) | (coef_re[k] & 0x3ff));
+	}
+	dib7000p_write_word(state, 143, 0);
+}
+
+static int dib7000p_tune(struct dvb_frontend *demod)
+{
+	struct dtv_frontend_properties *ch = &demod->dtv_property_cache;
+	struct dib7000p_state *state = demod->demodulator_priv;
+	u16 tmp = 0;
+
+	if (ch != NULL)
+		dib7000p_set_channel(state, ch, 0);
+	else
+		return -EINVAL;
+
+	// restart demod
+	dib7000p_write_word(state, 770, 0x4000);
+	dib7000p_write_word(state, 770, 0x0000);
+	msleep(45);
+
+	/* P_ctrl_inh_cor=0, P_ctrl_alpha_cor=4, P_ctrl_inh_isi=0, P_ctrl_alpha_isi=3, P_ctrl_inh_cor4=1, P_ctrl_alpha_cor4=3 */
+	tmp = (0 << 14) | (4 << 10) | (0 << 9) | (3 << 5) | (1 << 4) | (0x3);
+	if (state->sfn_workaround_active) {
+		dprintk("SFN workaround is active");
+		tmp |= (1 << 9);
+		dib7000p_write_word(state, 166, 0x4000);
+	} else {
+		dib7000p_write_word(state, 166, 0x0000);
+	}
+	dib7000p_write_word(state, 29, tmp);
+
+	// never achieved a lock with that bandwidth so far - wait for osc-freq to update
+	if (state->timf == 0)
+		msleep(200);
+
+	/* offset loop parameters */
+
+	/* P_timf_alpha, P_corm_alpha=6, P_corm_thres=0x80 */
+	tmp = (6 << 8) | 0x80;
+	switch (ch->transmission_mode) {
+	case TRANSMISSION_MODE_2K:
+		tmp |= (2 << 12);
+		break;
+	case TRANSMISSION_MODE_4K:
+		tmp |= (3 << 12);
+		break;
+	default:
+	case TRANSMISSION_MODE_8K:
+		tmp |= (4 << 12);
+		break;
+	}
+	dib7000p_write_word(state, 26, tmp);	/* timf_a(6xxx) */
+
+	/* P_ctrl_freeze_pha_shift=0, P_ctrl_pha_off_max */
+	tmp = (0 << 4);
+	switch (ch->transmission_mode) {
+	case TRANSMISSION_MODE_2K:
+		tmp |= 0x6;
+		break;
+	case TRANSMISSION_MODE_4K:
+		tmp |= 0x7;
+		break;
+	default:
+	case TRANSMISSION_MODE_8K:
+		tmp |= 0x8;
+		break;
+	}
+	dib7000p_write_word(state, 32, tmp);
+
+	/* P_ctrl_sfreq_inh=0, P_ctrl_sfreq_step */
+	tmp = (0 << 4);
+	switch (ch->transmission_mode) {
+	case TRANSMISSION_MODE_2K:
+		tmp |= 0x6;
+		break;
+	case TRANSMISSION_MODE_4K:
+		tmp |= 0x7;
+		break;
+	default:
+	case TRANSMISSION_MODE_8K:
+		tmp |= 0x8;
+		break;
+	}
+	dib7000p_write_word(state, 33, tmp);
+
+	tmp = dib7000p_read_word(state, 509);
+	if (!((tmp >> 6) & 0x1)) {
+		/* restart the fec */
+		tmp = dib7000p_read_word(state, 771);
+		dib7000p_write_word(state, 771, tmp | (1 << 1));
+		dib7000p_write_word(state, 771, tmp);
+		msleep(40);
+		tmp = dib7000p_read_word(state, 509);
+	}
+	// we achieved a lock - it's time to update the osc freq
+	if ((tmp >> 6) & 0x1) {
+		dib7000p_update_timf(state);
+		/* P_timf_alpha += 2 */
+		tmp = dib7000p_read_word(state, 26);
+		dib7000p_write_word(state, 26, (tmp & ~(0xf << 12)) | ((((tmp >> 12) & 0xf) + 5) << 12));
+	}
+
+	if (state->cfg.spur_protect)
+		dib7000p_spur_protect(state, ch->frequency / 1000, BANDWIDTH_TO_KHZ(ch->bandwidth_hz));
+
+	dib7000p_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->bandwidth_hz));
+	return 0;
+}
+
+static int dib7000p_wakeup(struct dvb_frontend *demod)
+{
+	struct dib7000p_state *state = demod->demodulator_priv;
+	dib7000p_set_power_mode(state, DIB7000P_POWER_ALL);
+	dib7000p_set_adc_state(state, DIBX000_SLOW_ADC_ON);
+	if (state->version == SOC7090)
+		dib7000p_sad_calib(state);
+	return 0;
+}
+
+static int dib7000p_sleep(struct dvb_frontend *demod)
+{
+	struct dib7000p_state *state = demod->demodulator_priv;
+	if (state->version == SOC7090)
+		return dib7000p_set_power_mode(state, DIB7000P_POWER_INTERFACE_ONLY);
+	return dib7000p_set_output_mode(state, OUTMODE_HIGH_Z) | dib7000p_set_power_mode(state, DIB7000P_POWER_INTERFACE_ONLY);
+}
+
+static int dib7000p_identify(struct dib7000p_state *st)
+{
+	u16 value;
+	dprintk("checking demod on I2C address: %d (%x)", st->i2c_addr, st->i2c_addr);
+
+	if ((value = dib7000p_read_word(st, 768)) != 0x01b3) {
+		dprintk("wrong Vendor ID (read=0x%x)", value);
+		return -EREMOTEIO;
+	}
+
+	if ((value = dib7000p_read_word(st, 769)) != 0x4000) {
+		dprintk("wrong Device ID (%x)", value);
+		return -EREMOTEIO;
+	}
+
+	return 0;
+}
+
+static int dib7000p_get_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
+	struct dib7000p_state *state = fe->demodulator_priv;
+	u16 tps = dib7000p_read_word(state, 463);
+
+	fep->inversion = INVERSION_AUTO;
+
+	fep->bandwidth_hz = BANDWIDTH_TO_HZ(state->current_bandwidth);
+
+	switch ((tps >> 8) & 0x3) {
+	case 0:
+		fep->transmission_mode = TRANSMISSION_MODE_2K;
+		break;
+	case 1:
+		fep->transmission_mode = TRANSMISSION_MODE_8K;
+		break;
+	/* case 2: fep->transmission_mode = TRANSMISSION_MODE_4K; break; */
+	}
+
+	switch (tps & 0x3) {
+	case 0:
+		fep->guard_interval = GUARD_INTERVAL_1_32;
+		break;
+	case 1:
+		fep->guard_interval = GUARD_INTERVAL_1_16;
+		break;
+	case 2:
+		fep->guard_interval = GUARD_INTERVAL_1_8;
+		break;
+	case 3:
+		fep->guard_interval = GUARD_INTERVAL_1_4;
+		break;
+	}
+
+	switch ((tps >> 14) & 0x3) {
+	case 0:
+		fep->modulation = QPSK;
+		break;
+	case 1:
+		fep->modulation = QAM_16;
+		break;
+	case 2:
+	default:
+		fep->modulation = QAM_64;
+		break;
+	}
+
+	/* as long as the frontend_param structure is fixed for hierarchical transmission I refuse to use it */
+	/* (tps >> 13) & 0x1 == hrch is used, (tps >> 10) & 0x7 == alpha */
+
+	fep->hierarchy = HIERARCHY_NONE;
+	switch ((tps >> 5) & 0x7) {
+	case 1:
+		fep->code_rate_HP = FEC_1_2;
+		break;
+	case 2:
+		fep->code_rate_HP = FEC_2_3;
+		break;
+	case 3:
+		fep->code_rate_HP = FEC_3_4;
+		break;
+	case 5:
+		fep->code_rate_HP = FEC_5_6;
+		break;
+	case 7:
+	default:
+		fep->code_rate_HP = FEC_7_8;
+		break;
+
+	}
+
+	switch ((tps >> 2) & 0x7) {
+	case 1:
+		fep->code_rate_LP = FEC_1_2;
+		break;
+	case 2:
+		fep->code_rate_LP = FEC_2_3;
+		break;
+	case 3:
+		fep->code_rate_LP = FEC_3_4;
+		break;
+	case 5:
+		fep->code_rate_LP = FEC_5_6;
+		break;
+	case 7:
+	default:
+		fep->code_rate_LP = FEC_7_8;
+		break;
+	}
+
+	/* native interleaver: (dib7000p_read_word(state, 464) >>  5) & 0x1 */
+
+	return 0;
+}
+
+static int dib7000p_set_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
+	struct dib7000p_state *state = fe->demodulator_priv;
+	int time, ret;
+
+	if (state->version == SOC7090)
+		dib7090_set_diversity_in(fe, 0);
+	else
+		dib7000p_set_output_mode(state, OUTMODE_HIGH_Z);
+
+	/* maybe the parameter has been changed */
+	state->sfn_workaround_active = buggy_sfn_workaround;
+
+	if (fe->ops.tuner_ops.set_params)
+		fe->ops.tuner_ops.set_params(fe);
+
+	/* start up the AGC */
+	state->agc_state = 0;
+	do {
+		time = dib7000p_agc_startup(fe);
+		if (time != -1)
+			msleep(time);
+	} while (time != -1);
+
+	if (fep->transmission_mode == TRANSMISSION_MODE_AUTO ||
+		fep->guard_interval == GUARD_INTERVAL_AUTO || fep->modulation == QAM_AUTO || fep->code_rate_HP == FEC_AUTO) {
+		int i = 800, found;
+
+		dib7000p_autosearch_start(fe);
+		do {
+			msleep(1);
+			found = dib7000p_autosearch_is_irq(fe);
+		} while (found == 0 && i--);
+
+		dprintk("autosearch returns: %d", found);
+		if (found == 0 || found == 1)
+			return 0;
+
+		dib7000p_get_frontend(fe);
+	}
+
+	ret = dib7000p_tune(fe);
+
+	/* make this a config parameter */
+	if (state->version == SOC7090) {
+		dib7090_set_output_mode(fe, state->cfg.output_mode);
+		if (state->cfg.enMpegOutput == 0) {
+			dib7090_setDibTxMux(state, MPEG_ON_DIBTX);
+			dib7090_setHostBusMux(state, DIBTX_ON_HOSTBUS);
+		}
+	} else
+		dib7000p_set_output_mode(state, state->cfg.output_mode);
+
+	return ret;
+}
+
+static int dib7000p_read_status(struct dvb_frontend *fe, fe_status_t * stat)
+{
+	struct dib7000p_state *state = fe->demodulator_priv;
+	u16 lock = dib7000p_read_word(state, 509);
+
+	*stat = 0;
+
+	if (lock & 0x8000)
+		*stat |= FE_HAS_SIGNAL;
+	if (lock & 0x3000)
+		*stat |= FE_HAS_CARRIER;
+	if (lock & 0x0100)
+		*stat |= FE_HAS_VITERBI;
+	if (lock & 0x0010)
+		*stat |= FE_HAS_SYNC;
+	if ((lock & 0x0038) == 0x38)
+		*stat |= FE_HAS_LOCK;
+
+	return 0;
+}
+
+static int dib7000p_read_ber(struct dvb_frontend *fe, u32 * ber)
+{
+	struct dib7000p_state *state = fe->demodulator_priv;
+	*ber = (dib7000p_read_word(state, 500) << 16) | dib7000p_read_word(state, 501);
+	return 0;
+}
+
+static int dib7000p_read_unc_blocks(struct dvb_frontend *fe, u32 * unc)
+{
+	struct dib7000p_state *state = fe->demodulator_priv;
+	*unc = dib7000p_read_word(state, 506);
+	return 0;
+}
+
+static int dib7000p_read_signal_strength(struct dvb_frontend *fe, u16 * strength)
+{
+	struct dib7000p_state *state = fe->demodulator_priv;
+	u16 val = dib7000p_read_word(state, 394);
+	*strength = 65535 - val;
+	return 0;
+}
+
+static int dib7000p_read_snr(struct dvb_frontend *fe, u16 * snr)
+{
+	struct dib7000p_state *state = fe->demodulator_priv;
+	u16 val;
+	s32 signal_mant, signal_exp, noise_mant, noise_exp;
+	u32 result = 0;
+
+	val = dib7000p_read_word(state, 479);
+	noise_mant = (val >> 4) & 0xff;
+	noise_exp = ((val & 0xf) << 2);
+	val = dib7000p_read_word(state, 480);
+	noise_exp += ((val >> 14) & 0x3);
+	if ((noise_exp & 0x20) != 0)
+		noise_exp -= 0x40;
+
+	signal_mant = (val >> 6) & 0xFF;
+	signal_exp = (val & 0x3F);
+	if ((signal_exp & 0x20) != 0)
+		signal_exp -= 0x40;
+
+	if (signal_mant != 0)
+		result = intlog10(2) * 10 * signal_exp + 10 * intlog10(signal_mant);
+	else
+		result = intlog10(2) * 10 * signal_exp - 100;
+
+	if (noise_mant != 0)
+		result -= intlog10(2) * 10 * noise_exp + 10 * intlog10(noise_mant);
+	else
+		result -= intlog10(2) * 10 * noise_exp - 100;
+
+	*snr = result / ((1 << 24) / 10);
+	return 0;
+}
+
+static int dib7000p_fe_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings *tune)
+{
+	tune->min_delay_ms = 1000;
+	return 0;
+}
+
+static void dib7000p_release(struct dvb_frontend *demod)
+{
+	struct dib7000p_state *st = demod->demodulator_priv;
+	dibx000_exit_i2c_master(&st->i2c_master);
+	i2c_del_adapter(&st->dib7090_tuner_adap);
+	kfree(st);
+}
+
+int dib7000pc_detection(struct i2c_adapter *i2c_adap)
+{
+	u8 *tx, *rx;
+	struct i2c_msg msg[2] = {
+		{.addr = 18 >> 1, .flags = 0, .len = 2},
+		{.addr = 18 >> 1, .flags = I2C_M_RD, .len = 2},
+	};
+	int ret = 0;
+
+	tx = kzalloc(2*sizeof(u8), GFP_KERNEL);
+	if (!tx)
+		return -ENOMEM;
+	rx = kzalloc(2*sizeof(u8), GFP_KERNEL);
+	if (!rx) {
+		ret = -ENOMEM;
+		goto rx_memory_error;
+	}
+
+	msg[0].buf = tx;
+	msg[1].buf = rx;
+
+	tx[0] = 0x03;
+	tx[1] = 0x00;
+
+	if (i2c_transfer(i2c_adap, msg, 2) == 2)
+		if (rx[0] == 0x01 && rx[1] == 0xb3) {
+			dprintk("-D-  DiB7000PC detected");
+			return 1;
+		}
+
+	msg[0].addr = msg[1].addr = 0x40;
+
+	if (i2c_transfer(i2c_adap, msg, 2) == 2)
+		if (rx[0] == 0x01 && rx[1] == 0xb3) {
+			dprintk("-D-  DiB7000PC detected");
+			return 1;
+		}
+
+	dprintk("-D-  DiB7000PC not detected");
+
+	kfree(rx);
+rx_memory_error:
+	kfree(tx);
+	return ret;
+}
+EXPORT_SYMBOL(dib7000pc_detection);
+
+struct i2c_adapter *dib7000p_get_i2c_master(struct dvb_frontend *demod, enum dibx000_i2c_interface intf, int gating)
+{
+	struct dib7000p_state *st = demod->demodulator_priv;
+	return dibx000_get_i2c_adapter(&st->i2c_master, intf, gating);
+}
+EXPORT_SYMBOL(dib7000p_get_i2c_master);
+
+int dib7000p_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
+{
+	struct dib7000p_state *state = fe->demodulator_priv;
+	u16 val = dib7000p_read_word(state, 235) & 0xffef;
+	val |= (onoff & 0x1) << 4;
+	dprintk("PID filter enabled %d", onoff);
+	return dib7000p_write_word(state, 235, val);
+}
+EXPORT_SYMBOL(dib7000p_pid_filter_ctrl);
+
+int dib7000p_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
+{
+	struct dib7000p_state *state = fe->demodulator_priv;
+	dprintk("PID filter: index %x, PID %d, OnOff %d", id, pid, onoff);
+	return dib7000p_write_word(state, 241 + id, onoff ? (1 << 13) | pid : 0);
+}
+EXPORT_SYMBOL(dib7000p_pid_filter);
+
+int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[])
+{
+	struct dib7000p_state *dpst;
+	int k = 0;
+	u8 new_addr = 0;
+
+	dpst = kzalloc(sizeof(struct dib7000p_state), GFP_KERNEL);
+	if (!dpst)
+		return -ENOMEM;
+
+	dpst->i2c_adap = i2c;
+	mutex_init(&dpst->i2c_buffer_lock);
+
+	for (k = no_of_demods - 1; k >= 0; k--) {
+		dpst->cfg = cfg[k];
+
+		/* designated i2c address */
+		if (cfg[k].default_i2c_addr != 0)
+			new_addr = cfg[k].default_i2c_addr + (k << 1);
+		else
+			new_addr = (0x40 + k) << 1;
+		dpst->i2c_addr = new_addr;
+		dib7000p_write_word(dpst, 1287, 0x0003);	/* sram lead in, rdy */
+		if (dib7000p_identify(dpst) != 0) {
+			dpst->i2c_addr = default_addr;
+			dib7000p_write_word(dpst, 1287, 0x0003);	/* sram lead in, rdy */
+			if (dib7000p_identify(dpst) != 0) {
+				dprintk("DiB7000P #%d: not identified\n", k);
+				kfree(dpst);
+				return -EIO;
+			}
+		}
+
+		/* start diversity to pull_down div_str - just for i2c-enumeration */
+		dib7000p_set_output_mode(dpst, OUTMODE_DIVERSITY);
+
+		/* set new i2c address and force divstart */
+		dib7000p_write_word(dpst, 1285, (new_addr << 2) | 0x2);
+
+		dprintk("IC %d initialized (to i2c_address 0x%x)", k, new_addr);
+	}
+
+	for (k = 0; k < no_of_demods; k++) {
+		dpst->cfg = cfg[k];
+		if (cfg[k].default_i2c_addr != 0)
+			dpst->i2c_addr = (cfg[k].default_i2c_addr + k) << 1;
+		else
+			dpst->i2c_addr = (0x40 + k) << 1;
+
+		// unforce divstr
+		dib7000p_write_word(dpst, 1285, dpst->i2c_addr << 2);
+
+		/* deactivate div - it was just for i2c-enumeration */
+		dib7000p_set_output_mode(dpst, OUTMODE_HIGH_Z);
+	}
+
+	kfree(dpst);
+	return 0;
+}
+EXPORT_SYMBOL(dib7000p_i2c_enumeration);
+
+static const s32 lut_1000ln_mant[] = {
+	6908, 6956, 7003, 7047, 7090, 7131, 7170, 7208, 7244, 7279, 7313, 7346, 7377, 7408, 7438, 7467, 7495, 7523, 7549, 7575, 7600
+};
+
+static s32 dib7000p_get_adc_power(struct dvb_frontend *fe)
+{
+	struct dib7000p_state *state = fe->demodulator_priv;
+	u32 tmp_val = 0, exp = 0, mant = 0;
+	s32 pow_i;
+	u16 buf[2];
+	u8 ix = 0;
+
+	buf[0] = dib7000p_read_word(state, 0x184);
+	buf[1] = dib7000p_read_word(state, 0x185);
+	pow_i = (buf[0] << 16) | buf[1];
+	dprintk("raw pow_i = %d", pow_i);
+
+	tmp_val = pow_i;
+	while (tmp_val >>= 1)
+		exp++;
+
+	mant = (pow_i * 1000 / (1 << exp));
+	dprintk(" mant = %d exp = %d", mant / 1000, exp);
+
+	ix = (u8) ((mant - 1000) / 100);	/* index of the LUT */
+	dprintk(" ix = %d", ix);
+
+	pow_i = (lut_1000ln_mant[ix] + 693 * (exp - 20) - 6908);
+	pow_i = (pow_i << 8) / 1000;
+	dprintk(" pow_i = %d", pow_i);
+
+	return pow_i;
+}
+
+static int map_addr_to_serpar_number(struct i2c_msg *msg)
+{
+	if ((msg->buf[0] <= 15))
+		msg->buf[0] -= 1;
+	else if (msg->buf[0] == 17)
+		msg->buf[0] = 15;
+	else if (msg->buf[0] == 16)
+		msg->buf[0] = 17;
+	else if (msg->buf[0] == 19)
+		msg->buf[0] = 16;
+	else if (msg->buf[0] >= 21 && msg->buf[0] <= 25)
+		msg->buf[0] -= 3;
+	else if (msg->buf[0] == 28)
+		msg->buf[0] = 23;
+	else
+		return -EINVAL;
+	return 0;
+}
+
+static int w7090p_tuner_write_serpar(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)
+{
+	struct dib7000p_state *state = i2c_get_adapdata(i2c_adap);
+	u8 n_overflow = 1;
+	u16 i = 1000;
+	u16 serpar_num = msg[0].buf[0];
+
+	while (n_overflow == 1 && i) {
+		n_overflow = (dib7000p_read_word(state, 1984) >> 1) & 0x1;
+		i--;
+		if (i == 0)
+			dprintk("Tuner ITF: write busy (overflow)");
+	}
+	dib7000p_write_word(state, 1985, (1 << 6) | (serpar_num & 0x3f));
+	dib7000p_write_word(state, 1986, (msg[0].buf[1] << 8) | msg[0].buf[2]);
+
+	return num;
+}
+
+static int w7090p_tuner_read_serpar(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)
+{
+	struct dib7000p_state *state = i2c_get_adapdata(i2c_adap);
+	u8 n_overflow = 1, n_empty = 1;
+	u16 i = 1000;
+	u16 serpar_num = msg[0].buf[0];
+	u16 read_word;
+
+	while (n_overflow == 1 && i) {
+		n_overflow = (dib7000p_read_word(state, 1984) >> 1) & 0x1;
+		i--;
+		if (i == 0)
+			dprintk("TunerITF: read busy (overflow)");
+	}
+	dib7000p_write_word(state, 1985, (0 << 6) | (serpar_num & 0x3f));
+
+	i = 1000;
+	while (n_empty == 1 && i) {
+		n_empty = dib7000p_read_word(state, 1984) & 0x1;
+		i--;
+		if (i == 0)
+			dprintk("TunerITF: read busy (empty)");
+	}
+	read_word = dib7000p_read_word(state, 1987);
+	msg[1].buf[0] = (read_word >> 8) & 0xff;
+	msg[1].buf[1] = (read_word) & 0xff;
+
+	return num;
+}
+
+static int w7090p_tuner_rw_serpar(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)
+{
+	if (map_addr_to_serpar_number(&msg[0]) == 0) {	/* else = Tuner regs to ignore : DIG_CFG, CTRL_RF_LT, PLL_CFG, PWM1_REG, ADCCLK, DIG_CFG_3; SLEEP_EN... */
+		if (num == 1) {	/* write */
+			return w7090p_tuner_write_serpar(i2c_adap, msg, 1);
+		} else {	/* read */
+			return w7090p_tuner_read_serpar(i2c_adap, msg, 2);
+		}
+	}
+	return num;
+}
+
+static int dib7090p_rw_on_apb(struct i2c_adapter *i2c_adap,
+		struct i2c_msg msg[], int num, u16 apb_address)
+{
+	struct dib7000p_state *state = i2c_get_adapdata(i2c_adap);
+	u16 word;
+
+	if (num == 1) {		/* write */
+		dib7000p_write_word(state, apb_address, ((msg[0].buf[1] << 8) | (msg[0].buf[2])));
+	} else {
+		word = dib7000p_read_word(state, apb_address);
+		msg[1].buf[0] = (word >> 8) & 0xff;
+		msg[1].buf[1] = (word) & 0xff;
+	}
+
+	return num;
+}
+
+static int dib7090_tuner_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)
+{
+	struct dib7000p_state *state = i2c_get_adapdata(i2c_adap);
+
+	u16 apb_address = 0, word;
+	int i = 0;
+	switch (msg[0].buf[0]) {
+	case 0x12:
+		apb_address = 1920;
+		break;
+	case 0x14:
+		apb_address = 1921;
+		break;
+	case 0x24:
+		apb_address = 1922;
+		break;
+	case 0x1a:
+		apb_address = 1923;
+		break;
+	case 0x22:
+		apb_address = 1924;
+		break;
+	case 0x33:
+		apb_address = 1926;
+		break;
+	case 0x34:
+		apb_address = 1927;
+		break;
+	case 0x35:
+		apb_address = 1928;
+		break;
+	case 0x36:
+		apb_address = 1929;
+		break;
+	case 0x37:
+		apb_address = 1930;
+		break;
+	case 0x38:
+		apb_address = 1931;
+		break;
+	case 0x39:
+		apb_address = 1932;
+		break;
+	case 0x2a:
+		apb_address = 1935;
+		break;
+	case 0x2b:
+		apb_address = 1936;
+		break;
+	case 0x2c:
+		apb_address = 1937;
+		break;
+	case 0x2d:
+		apb_address = 1938;
+		break;
+	case 0x2e:
+		apb_address = 1939;
+		break;
+	case 0x2f:
+		apb_address = 1940;
+		break;
+	case 0x30:
+		apb_address = 1941;
+		break;
+	case 0x31:
+		apb_address = 1942;
+		break;
+	case 0x32:
+		apb_address = 1943;
+		break;
+	case 0x3e:
+		apb_address = 1944;
+		break;
+	case 0x3f:
+		apb_address = 1945;
+		break;
+	case 0x40:
+		apb_address = 1948;
+		break;
+	case 0x25:
+		apb_address = 914;
+		break;
+	case 0x26:
+		apb_address = 915;
+		break;
+	case 0x27:
+		apb_address = 917;
+		break;
+	case 0x28:
+		apb_address = 916;
+		break;
+	case 0x1d:
+		i = ((dib7000p_read_word(state, 72) >> 12) & 0x3);
+		word = dib7000p_read_word(state, 384 + i);
+		msg[1].buf[0] = (word >> 8) & 0xff;
+		msg[1].buf[1] = (word) & 0xff;
+		return num;
+	case 0x1f:
+		if (num == 1) {	/* write */
+			word = (u16) ((msg[0].buf[1] << 8) | msg[0].buf[2]);
+			word &= 0x3;
+			word = (dib7000p_read_word(state, 72) & ~(3 << 12)) | (word << 12);
+			dib7000p_write_word(state, 72, word);	/* Set the proper input */
+			return num;
+		}
+	}
+
+	if (apb_address != 0)	/* R/W acces via APB */
+		return dib7090p_rw_on_apb(i2c_adap, msg, num, apb_address);
+	else			/* R/W access via SERPAR  */
+		return w7090p_tuner_rw_serpar(i2c_adap, msg, num);
+
+	return 0;
+}
+
+static u32 dib7000p_i2c_func(struct i2c_adapter *adapter)
+{
+	return I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm dib7090_tuner_xfer_algo = {
+	.master_xfer = dib7090_tuner_xfer,
+	.functionality = dib7000p_i2c_func,
+};
+
+struct i2c_adapter *dib7090_get_i2c_tuner(struct dvb_frontend *fe)
+{
+	struct dib7000p_state *st = fe->demodulator_priv;
+	return &st->dib7090_tuner_adap;
+}
+EXPORT_SYMBOL(dib7090_get_i2c_tuner);
+
+static int dib7090_host_bus_drive(struct dib7000p_state *state, u8 drive)
+{
+	u16 reg;
+
+	/* drive host bus 2, 3, 4 */
+	reg = dib7000p_read_word(state, 1798) & ~((0x7) | (0x7 << 6) | (0x7 << 12));
+	reg |= (drive << 12) | (drive << 6) | drive;
+	dib7000p_write_word(state, 1798, reg);
+
+	/* drive host bus 5,6 */
+	reg = dib7000p_read_word(state, 1799) & ~((0x7 << 2) | (0x7 << 8));
+	reg |= (drive << 8) | (drive << 2);
+	dib7000p_write_word(state, 1799, reg);
+
+	/* drive host bus 7, 8, 9 */
+	reg = dib7000p_read_word(state, 1800) & ~((0x7) | (0x7 << 6) | (0x7 << 12));
+	reg |= (drive << 12) | (drive << 6) | drive;
+	dib7000p_write_word(state, 1800, reg);
+
+	/* drive host bus 10, 11 */
+	reg = dib7000p_read_word(state, 1801) & ~((0x7 << 2) | (0x7 << 8));
+	reg |= (drive << 8) | (drive << 2);
+	dib7000p_write_word(state, 1801, reg);
+
+	/* drive host bus 12, 13, 14 */
+	reg = dib7000p_read_word(state, 1802) & ~((0x7) | (0x7 << 6) | (0x7 << 12));
+	reg |= (drive << 12) | (drive << 6) | drive;
+	dib7000p_write_word(state, 1802, reg);
+
+	return 0;
+}
+
+static u32 dib7090_calcSyncFreq(u32 P_Kin, u32 P_Kout, u32 insertExtSynchro, u32 syncSize)
+{
+	u32 quantif = 3;
+	u32 nom = (insertExtSynchro * P_Kin + syncSize);
+	u32 denom = P_Kout;
+	u32 syncFreq = ((nom << quantif) / denom);
+
+	if ((syncFreq & ((1 << quantif) - 1)) != 0)
+		syncFreq = (syncFreq >> quantif) + 1;
+	else
+		syncFreq = (syncFreq >> quantif);
+
+	if (syncFreq != 0)
+		syncFreq = syncFreq - 1;
+
+	return syncFreq;
+}
+
+static int dib7090_cfg_DibTx(struct dib7000p_state *state, u32 P_Kin, u32 P_Kout, u32 insertExtSynchro, u32 synchroMode, u32 syncWord, u32 syncSize)
+{
+	dprintk("Configure DibStream Tx");
+
+	dib7000p_write_word(state, 1615, 1);
+	dib7000p_write_word(state, 1603, P_Kin);
+	dib7000p_write_word(state, 1605, P_Kout);
+	dib7000p_write_word(state, 1606, insertExtSynchro);
+	dib7000p_write_word(state, 1608, synchroMode);
+	dib7000p_write_word(state, 1609, (syncWord >> 16) & 0xffff);
+	dib7000p_write_word(state, 1610, syncWord & 0xffff);
+	dib7000p_write_word(state, 1612, syncSize);
+	dib7000p_write_word(state, 1615, 0);
+
+	return 0;
+}
+
+static int dib7090_cfg_DibRx(struct dib7000p_state *state, u32 P_Kin, u32 P_Kout, u32 synchroMode, u32 insertExtSynchro, u32 syncWord, u32 syncSize,
+		u32 dataOutRate)
+{
+	u32 syncFreq;
+
+	dprintk("Configure DibStream Rx");
+	if ((P_Kin != 0) && (P_Kout != 0)) {
+		syncFreq = dib7090_calcSyncFreq(P_Kin, P_Kout, insertExtSynchro, syncSize);
+		dib7000p_write_word(state, 1542, syncFreq);
+	}
+	dib7000p_write_word(state, 1554, 1);
+	dib7000p_write_word(state, 1536, P_Kin);
+	dib7000p_write_word(state, 1537, P_Kout);
+	dib7000p_write_word(state, 1539, synchroMode);
+	dib7000p_write_word(state, 1540, (syncWord >> 16) & 0xffff);
+	dib7000p_write_word(state, 1541, syncWord & 0xffff);
+	dib7000p_write_word(state, 1543, syncSize);
+	dib7000p_write_word(state, 1544, dataOutRate);
+	dib7000p_write_word(state, 1554, 0);
+
+	return 0;
+}
+
+static void dib7090_enMpegMux(struct dib7000p_state *state, int onoff)
+{
+	u16 reg_1287 = dib7000p_read_word(state, 1287);
+
+	switch (onoff) {
+	case 1:
+			reg_1287 &= ~(1<<7);
+			break;
+	case 0:
+			reg_1287 |= (1<<7);
+			break;
+	}
+
+	dib7000p_write_word(state, 1287, reg_1287);
+}
+
+static void dib7090_configMpegMux(struct dib7000p_state *state,
+		u16 pulseWidth, u16 enSerialMode, u16 enSerialClkDiv2)
+{
+	dprintk("Enable Mpeg mux");
+
+	dib7090_enMpegMux(state, 0);
+
+	/* If the input mode is MPEG do not divide the serial clock */
+	if ((enSerialMode == 1) && (state->input_mode_mpeg == 1))
+		enSerialClkDiv2 = 0;
+
+	dib7000p_write_word(state, 1287, ((pulseWidth & 0x1f) << 2)
+			| ((enSerialMode & 0x1) << 1)
+			| (enSerialClkDiv2 & 0x1));
+
+	dib7090_enMpegMux(state, 1);
+}
+
+static void dib7090_setDibTxMux(struct dib7000p_state *state, int mode)
+{
+	u16 reg_1288 = dib7000p_read_word(state, 1288) & ~(0x7 << 7);
+
+	switch (mode) {
+	case MPEG_ON_DIBTX:
+			dprintk("SET MPEG ON DIBSTREAM TX");
+			dib7090_cfg_DibTx(state, 8, 5, 0, 0, 0, 0);
+			reg_1288 |= (1<<9);
+			break;
+	case DIV_ON_DIBTX:
+			dprintk("SET DIV_OUT ON DIBSTREAM TX");
+			dib7090_cfg_DibTx(state, 5, 5, 0, 0, 0, 0);
+			reg_1288 |= (1<<8);
+			break;
+	case ADC_ON_DIBTX:
+			dprintk("SET ADC_OUT ON DIBSTREAM TX");
+			dib7090_cfg_DibTx(state, 20, 5, 10, 0, 0, 0);
+			reg_1288 |= (1<<7);
+			break;
+	default:
+			break;
+	}
+	dib7000p_write_word(state, 1288, reg_1288);
+}
+
+static void dib7090_setHostBusMux(struct dib7000p_state *state, int mode)
+{
+	u16 reg_1288 = dib7000p_read_word(state, 1288) & ~(0x7 << 4);
+
+	switch (mode) {
+	case DEMOUT_ON_HOSTBUS:
+			dprintk("SET DEM OUT OLD INTERF ON HOST BUS");
+			dib7090_enMpegMux(state, 0);
+			reg_1288 |= (1<<6);
+			break;
+	case DIBTX_ON_HOSTBUS:
+			dprintk("SET DIBSTREAM TX ON HOST BUS");
+			dib7090_enMpegMux(state, 0);
+			reg_1288 |= (1<<5);
+			break;
+	case MPEG_ON_HOSTBUS:
+			dprintk("SET MPEG MUX ON HOST BUS");
+			reg_1288 |= (1<<4);
+			break;
+	default:
+			break;
+	}
+	dib7000p_write_word(state, 1288, reg_1288);
+}
+
+int dib7090_set_diversity_in(struct dvb_frontend *fe, int onoff)
+{
+	struct dib7000p_state *state = fe->demodulator_priv;
+	u16 reg_1287;
+
+	switch (onoff) {
+	case 0: /* only use the internal way - not the diversity input */
+			dprintk("%s mode OFF : by default Enable Mpeg INPUT", __func__);
+			dib7090_cfg_DibRx(state, 8, 5, 0, 0, 0, 8, 0);
+
+			/* Do not divide the serial clock of MPEG MUX */
+			/* in SERIAL MODE in case input mode MPEG is used */
+			reg_1287 = dib7000p_read_word(state, 1287);
+			/* enSerialClkDiv2 == 1 ? */
+			if ((reg_1287 & 0x1) == 1) {
+				/* force enSerialClkDiv2 = 0 */
+				reg_1287 &= ~0x1;
+				dib7000p_write_word(state, 1287, reg_1287);
+			}
+			state->input_mode_mpeg = 1;
+			break;
+	case 1: /* both ways */
+	case 2: /* only the diversity input */
+			dprintk("%s ON : Enable diversity INPUT", __func__);
+			dib7090_cfg_DibRx(state, 5, 5, 0, 0, 0, 0, 0);
+			state->input_mode_mpeg = 0;
+			break;
+	}
+
+	dib7000p_set_diversity_in(&state->demod, onoff);
+	return 0;
+}
+
+static int dib7090_set_output_mode(struct dvb_frontend *fe, int mode)
+{
+	struct dib7000p_state *state = fe->demodulator_priv;
+
+	u16 outreg, smo_mode, fifo_threshold;
+	u8 prefer_mpeg_mux_use = 1;
+	int ret = 0;
+
+	dib7090_host_bus_drive(state, 1);
+
+	fifo_threshold = 1792;
+	smo_mode = (dib7000p_read_word(state, 235) & 0x0050) | (1 << 1);
+	outreg = dib7000p_read_word(state, 1286) & ~((1 << 10) | (0x7 << 6) | (1 << 1));
+
+	switch (mode) {
+	case OUTMODE_HIGH_Z:
+		outreg = 0;
+		break;
+
+	case OUTMODE_MPEG2_SERIAL:
+		if (prefer_mpeg_mux_use) {
+			dprintk("setting output mode TS_SERIAL using Mpeg Mux");
+			dib7090_configMpegMux(state, 3, 1, 1);
+			dib7090_setHostBusMux(state, MPEG_ON_HOSTBUS);
+		} else {/* Use Smooth block */
+			dprintk("setting output mode TS_SERIAL using Smooth bloc");
+			dib7090_setHostBusMux(state, DEMOUT_ON_HOSTBUS);
+			outreg |= (2<<6) | (0 << 1);
+		}
+		break;
+
+	case OUTMODE_MPEG2_PAR_GATED_CLK:
+		if (prefer_mpeg_mux_use) {
+			dprintk("setting output mode TS_PARALLEL_GATED using Mpeg Mux");
+			dib7090_configMpegMux(state, 2, 0, 0);
+			dib7090_setHostBusMux(state, MPEG_ON_HOSTBUS);
+		} else { /* Use Smooth block */
+			dprintk("setting output mode TS_PARALLEL_GATED using Smooth block");
+			dib7090_setHostBusMux(state, DEMOUT_ON_HOSTBUS);
+			outreg |= (0<<6);
+		}
+		break;
+
+	case OUTMODE_MPEG2_PAR_CONT_CLK:	/* Using Smooth block only */
+		dprintk("setting output mode TS_PARALLEL_CONT using Smooth block");
+		dib7090_setHostBusMux(state, DEMOUT_ON_HOSTBUS);
+		outreg |= (1<<6);
+		break;
+
+	case OUTMODE_MPEG2_FIFO:	/* Using Smooth block because not supported by new Mpeg Mux bloc */
+		dprintk("setting output mode TS_FIFO using Smooth block");
+		dib7090_setHostBusMux(state, DEMOUT_ON_HOSTBUS);
+		outreg |= (5<<6);
+		smo_mode |= (3 << 1);
+		fifo_threshold = 512;
+		break;
+
+	case OUTMODE_DIVERSITY:
+		dprintk("setting output mode MODE_DIVERSITY");
+		dib7090_setDibTxMux(state, DIV_ON_DIBTX);
+		dib7090_setHostBusMux(state, DIBTX_ON_HOSTBUS);
+		break;
+
+	case OUTMODE_ANALOG_ADC:
+		dprintk("setting output mode MODE_ANALOG_ADC");
+		dib7090_setDibTxMux(state, ADC_ON_DIBTX);
+		dib7090_setHostBusMux(state, DIBTX_ON_HOSTBUS);
+		break;
+	}
+	if (mode != OUTMODE_HIGH_Z)
+		outreg |= (1 << 10);
+
+	if (state->cfg.output_mpeg2_in_188_bytes)
+		smo_mode |= (1 << 5);
+
+	ret |= dib7000p_write_word(state, 235, smo_mode);
+	ret |= dib7000p_write_word(state, 236, fifo_threshold);	/* synchronous fread */
+	ret |= dib7000p_write_word(state, 1286, outreg);
+
+	return ret;
+}
+
+int dib7090_tuner_sleep(struct dvb_frontend *fe, int onoff)
+{
+	struct dib7000p_state *state = fe->demodulator_priv;
+	u16 en_cur_state;
+
+	dprintk("sleep dib7090: %d", onoff);
+
+	en_cur_state = dib7000p_read_word(state, 1922);
+
+	if (en_cur_state > 0xff)
+		state->tuner_enable = en_cur_state;
+
+	if (onoff)
+		en_cur_state &= 0x00ff;
+	else {
+		if (state->tuner_enable != 0)
+			en_cur_state = state->tuner_enable;
+	}
+
+	dib7000p_write_word(state, 1922, en_cur_state);
+
+	return 0;
+}
+EXPORT_SYMBOL(dib7090_tuner_sleep);
+
+int dib7090_get_adc_power(struct dvb_frontend *fe)
+{
+	return dib7000p_get_adc_power(fe);
+}
+EXPORT_SYMBOL(dib7090_get_adc_power);
+
+int dib7090_slave_reset(struct dvb_frontend *fe)
+{
+	struct dib7000p_state *state = fe->demodulator_priv;
+	u16 reg;
+
+	reg = dib7000p_read_word(state, 1794);
+	dib7000p_write_word(state, 1794, reg | (4 << 12));
+
+	dib7000p_write_word(state, 1032, 0xffff);
+	return 0;
+}
+EXPORT_SYMBOL(dib7090_slave_reset);
+
+static struct dvb_frontend_ops dib7000p_ops;
+struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg)
+{
+	struct dvb_frontend *demod;
+	struct dib7000p_state *st;
+	st = kzalloc(sizeof(struct dib7000p_state), GFP_KERNEL);
+	if (st == NULL)
+		return NULL;
+
+	memcpy(&st->cfg, cfg, sizeof(struct dib7000p_config));
+	st->i2c_adap = i2c_adap;
+	st->i2c_addr = i2c_addr;
+	st->gpio_val = cfg->gpio_val;
+	st->gpio_dir = cfg->gpio_dir;
+
+	/* Ensure the output mode remains at the previous default if it's
+	 * not specifically set by the caller.
+	 */
+	if ((st->cfg.output_mode != OUTMODE_MPEG2_SERIAL) && (st->cfg.output_mode != OUTMODE_MPEG2_PAR_GATED_CLK))
+		st->cfg.output_mode = OUTMODE_MPEG2_FIFO;
+
+	demod = &st->demod;
+	demod->demodulator_priv = st;
+	memcpy(&st->demod.ops, &dib7000p_ops, sizeof(struct dvb_frontend_ops));
+	mutex_init(&st->i2c_buffer_lock);
+
+	dib7000p_write_word(st, 1287, 0x0003);	/* sram lead in, rdy */
+
+	if (dib7000p_identify(st) != 0)
+		goto error;
+
+	st->version = dib7000p_read_word(st, 897);
+
+	/* FIXME: make sure the dev.parent field is initialized, or else
+	   request_firmware() will hit an OOPS (this should be moved somewhere
+	   more common) */
+	st->i2c_master.gated_tuner_i2c_adap.dev.parent = i2c_adap->dev.parent;
+
+	dibx000_init_i2c_master(&st->i2c_master, DIB7000P, st->i2c_adap, st->i2c_addr);
+
+	/* init 7090 tuner adapter */
+	strncpy(st->dib7090_tuner_adap.name, "DiB7090 tuner interface", sizeof(st->dib7090_tuner_adap.name));
+	st->dib7090_tuner_adap.algo = &dib7090_tuner_xfer_algo;
+	st->dib7090_tuner_adap.algo_data = NULL;
+	st->dib7090_tuner_adap.dev.parent = st->i2c_adap->dev.parent;
+	i2c_set_adapdata(&st->dib7090_tuner_adap, st);
+	i2c_add_adapter(&st->dib7090_tuner_adap);
+
+	dib7000p_demod_reset(st);
+
+	if (st->version == SOC7090) {
+		dib7090_set_output_mode(demod, st->cfg.output_mode);
+		dib7090_set_diversity_in(demod, 0);
+	}
+
+	return demod;
+
+error:
+	kfree(st);
+	return NULL;
+}
+EXPORT_SYMBOL(dib7000p_attach);
+
+static struct dvb_frontend_ops dib7000p_ops = {
+	.delsys = { SYS_DVBT },
+	.info = {
+		 .name = "DiBcom 7000PC",
+		 .frequency_min = 44250000,
+		 .frequency_max = 867250000,
+		 .frequency_stepsize = 62500,
+		 .caps = FE_CAN_INVERSION_AUTO |
+		 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_FEC_AUTO |
+		 FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
+		 FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_RECOVER | FE_CAN_HIERARCHY_AUTO,
+		 },
+
+	.release = dib7000p_release,
+
+	.init = dib7000p_wakeup,
+	.sleep = dib7000p_sleep,
+
+	.set_frontend = dib7000p_set_frontend,
+	.get_tune_settings = dib7000p_fe_get_tune_settings,
+	.get_frontend = dib7000p_get_frontend,
+
+	.read_status = dib7000p_read_status,
+	.read_ber = dib7000p_read_ber,
+	.read_signal_strength = dib7000p_read_signal_strength,
+	.read_snr = dib7000p_read_snr,
+	.read_ucblocks = dib7000p_read_unc_blocks,
+};
+
+MODULE_AUTHOR("Olivier Grenie <ogrenie@dibcom.fr>");
+MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
+MODULE_DESCRIPTION("Driver for the DiBcom 7000PC COFDM demodulator");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb-frontends/dib7000p.h b/drivers/media/dvb-frontends/dib7000p.h
new file mode 100644
index 0000000..b61b03a
--- /dev/null
+++ b/drivers/media/dvb-frontends/dib7000p.h
@@ -0,0 +1,158 @@
+#ifndef DIB7000P_H
+#define DIB7000P_H
+
+#include "dibx000_common.h"
+
+struct dib7000p_config {
+	u8 output_mpeg2_in_188_bytes;
+	u8 hostbus_diversity;
+	u8 tuner_is_baseband;
+	int (*update_lna) (struct dvb_frontend *, u16 agc_global);
+
+	u8 agc_config_count;
+	struct dibx000_agc_config *agc;
+	struct dibx000_bandwidth_config *bw;
+
+#define DIB7000P_GPIO_DEFAULT_DIRECTIONS 0xffff
+	u16 gpio_dir;
+#define DIB7000P_GPIO_DEFAULT_VALUES     0x0000
+	u16 gpio_val;
+#define DIB7000P_GPIO_PWM_POS0(v)        ((v & 0xf) << 12)
+#define DIB7000P_GPIO_PWM_POS1(v)        ((v & 0xf) << 8 )
+#define DIB7000P_GPIO_PWM_POS2(v)        ((v & 0xf) << 4 )
+#define DIB7000P_GPIO_PWM_POS3(v)         (v & 0xf)
+#define DIB7000P_GPIO_DEFAULT_PWM_POS    0xffff
+	u16 gpio_pwm_pos;
+
+	u16 pwm_freq_div;
+
+	u8 quartz_direct;
+
+	u8 spur_protect;
+
+	int (*agc_control) (struct dvb_frontend *, u8 before);
+
+	u8 output_mode;
+	u8 disable_sample_and_hold:1;
+
+	u8 enable_current_mirror:1;
+	u16 diversity_delay;
+
+	u8 default_i2c_addr;
+	u8 enMpegOutput:1;
+};
+
+#define DEFAULT_DIB7000P_I2C_ADDRESS 18
+
+#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);
+extern struct i2c_adapter *dib7000p_get_i2c_master(struct dvb_frontend *, enum dibx000_i2c_interface, int);
+extern int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, 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);
+extern int dib7000p_pid_filter(struct dvb_frontend *, u8 id, u16 pid, u8 onoff);
+extern int dib7000p_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff);
+extern int dib7000p_update_pll(struct dvb_frontend *fe, struct dibx000_bandwidth_config *bw);
+extern u32 dib7000p_ctrl_timf(struct dvb_frontend *fe, u8 op, u32 timf);
+extern int dib7090_tuner_sleep(struct dvb_frontend *fe, int onoff);
+extern int dib7090_get_adc_power(struct dvb_frontend *fe);
+extern struct i2c_adapter *dib7090_get_i2c_tuner(struct dvb_frontend *fe);
+extern int dib7090_slave_reset(struct dvb_frontend *fe);
+extern int dib7000p_get_agc_values(struct dvb_frontend *fe,
+		u16 *agc_global, u16 *agc1, u16 *agc2, u16 *wbd);
+#else
+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;
+}
+
+static inline struct i2c_adapter *dib7000p_get_i2c_master(struct dvb_frontend *fe, 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[])
+{
+	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)
+{
+	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)
+{
+	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;
+}
+
+static inline int dib7000p_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return -ENODEV;
+}
+
+static inline int dib7000p_pid_filter_ctrl(struct dvb_frontend *fe, uint8_t onoff)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return -ENODEV;
+}
+
+static inline int dib7000p_update_pll(struct dvb_frontend *fe, struct dibx000_bandwidth_config *bw)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return -ENODEV;
+}
+
+static inline u32 dib7000p_ctrl_timf(struct dvb_frontend *fe, u8 op, u32 timf)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return 0;
+}
+
+static inline int dib7090_tuner_sleep(struct dvb_frontend *fe, int onoff)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return -ENODEV;
+}
+
+static inline int dib7090_get_adc_power(struct dvb_frontend *fe)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return -ENODEV;
+}
+
+static inline struct i2c_adapter *dib7090_get_i2c_tuner(struct dvb_frontend *fe)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+
+static inline int dib7090_slave_reset(struct dvb_frontend *fe)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return -ENODEV;
+}
+
+static inline int dib7000p_get_agc_values(struct dvb_frontend *fe,
+		u16 *agc_global, u16 *agc1, u16 *agc2, u16 *wbd)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return -ENODEV;
+}
+#endif
+
+#endif
diff --git a/drivers/media/dvb-frontends/dib8000.c b/drivers/media/dvb-frontends/dib8000.c
new file mode 100644
index 0000000..1f3bcb5
--- /dev/null
+++ b/drivers/media/dvb-frontends/dib8000.c
@@ -0,0 +1,3560 @@
+/*
+ * Linux-DVB Driver for DiBcom's DiB8000 chip (ISDB-T).
+ *
+ * Copyright (C) 2009 DiBcom (http://www.dibcom.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, version 2.
+ */
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+
+#include "dvb_math.h"
+
+#include "dvb_frontend.h"
+
+#include "dib8000.h"
+
+#define LAYER_ALL -1
+#define LAYER_A   1
+#define LAYER_B   2
+#define LAYER_C   3
+
+#define FE_CALLBACK_TIME_NEVER 0xffffffff
+#define MAX_NUMBER_OF_FRONTENDS 6
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
+
+#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB8000: "); printk(args); printk("\n"); } } while (0)
+
+#define FE_STATUS_TUNE_FAILED 0
+
+struct i2c_device {
+	struct i2c_adapter *adap;
+	u8 addr;
+	u8 *i2c_write_buffer;
+	u8 *i2c_read_buffer;
+	struct mutex *i2c_buffer_lock;
+};
+
+struct dib8000_state {
+	struct dib8000_config cfg;
+
+	struct i2c_device i2c;
+
+	struct dibx000_i2c_master i2c_master;
+
+	u16 wbd_ref;
+
+	u8 current_band;
+	u32 current_bandwidth;
+	struct dibx000_agc_config *current_agc;
+	u32 timf;
+	u32 timf_default;
+
+	u8 div_force_off:1;
+	u8 div_state:1;
+	u16 div_sync_wait;
+
+	u8 agc_state;
+	u8 differential_constellation;
+	u8 diversity_onoff;
+
+	s16 ber_monitored_layer;
+	u16 gpio_dir;
+	u16 gpio_val;
+
+	u16 revision;
+	u8 isdbt_cfg_loaded;
+	enum frontend_tune_state tune_state;
+	u32 status;
+
+	struct dvb_frontend *fe[MAX_NUMBER_OF_FRONTENDS];
+
+	/* for the I2C transfer */
+	struct i2c_msg msg[2];
+	u8 i2c_write_buffer[4];
+	u8 i2c_read_buffer[2];
+	struct mutex i2c_buffer_lock;
+	u8 input_mode_mpeg;
+
+	u16 tuner_enable;
+	struct i2c_adapter dib8096p_tuner_adap;
+};
+
+enum dib8000_power_mode {
+	DIB8000_POWER_ALL = 0,
+	DIB8000_POWER_INTERFACE_ONLY,
+};
+
+static u16 dib8000_i2c_read16(struct i2c_device *i2c, u16 reg)
+{
+	u16 ret;
+	struct i2c_msg msg[2] = {
+		{.addr = i2c->addr >> 1, .flags = 0, .len = 2},
+		{.addr = i2c->addr >> 1, .flags = I2C_M_RD, .len = 2},
+	};
+
+	if (mutex_lock_interruptible(i2c->i2c_buffer_lock) < 0) {
+		dprintk("could not acquire lock");
+		return 0;
+	}
+
+	msg[0].buf    = i2c->i2c_write_buffer;
+	msg[0].buf[0] = reg >> 8;
+	msg[0].buf[1] = reg & 0xff;
+	msg[1].buf    = i2c->i2c_read_buffer;
+
+	if (i2c_transfer(i2c->adap, msg, 2) != 2)
+		dprintk("i2c read error on %d", reg);
+
+	ret = (msg[1].buf[0] << 8) | msg[1].buf[1];
+	mutex_unlock(i2c->i2c_buffer_lock);
+	return ret;
+}
+
+static u16 dib8000_read_word(struct dib8000_state *state, u16 reg)
+{
+	u16 ret;
+
+	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
+		dprintk("could not acquire lock");
+		return 0;
+	}
+
+	state->i2c_write_buffer[0] = reg >> 8;
+	state->i2c_write_buffer[1] = reg & 0xff;
+
+	memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
+	state->msg[0].addr = state->i2c.addr >> 1;
+	state->msg[0].flags = 0;
+	state->msg[0].buf = state->i2c_write_buffer;
+	state->msg[0].len = 2;
+	state->msg[1].addr = state->i2c.addr >> 1;
+	state->msg[1].flags = I2C_M_RD;
+	state->msg[1].buf = state->i2c_read_buffer;
+	state->msg[1].len = 2;
+
+	if (i2c_transfer(state->i2c.adap, state->msg, 2) != 2)
+		dprintk("i2c read error on %d", reg);
+
+	ret = (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
+	mutex_unlock(&state->i2c_buffer_lock);
+
+	return ret;
+}
+
+static u32 dib8000_read32(struct dib8000_state *state, u16 reg)
+{
+	u16 rw[2];
+
+	rw[0] = dib8000_read_word(state, reg + 0);
+	rw[1] = dib8000_read_word(state, reg + 1);
+
+	return ((rw[0] << 16) | (rw[1]));
+}
+
+static int dib8000_i2c_write16(struct i2c_device *i2c, u16 reg, u16 val)
+{
+	struct i2c_msg msg = {.addr = i2c->addr >> 1, .flags = 0, .len = 4};
+	int ret = 0;
+
+	if (mutex_lock_interruptible(i2c->i2c_buffer_lock) < 0) {
+		dprintk("could not acquire lock");
+		return -EINVAL;
+	}
+
+	msg.buf    = i2c->i2c_write_buffer;
+	msg.buf[0] = (reg >> 8) & 0xff;
+	msg.buf[1] = reg & 0xff;
+	msg.buf[2] = (val >> 8) & 0xff;
+	msg.buf[3] = val & 0xff;
+
+	ret = i2c_transfer(i2c->adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
+	mutex_unlock(i2c->i2c_buffer_lock);
+
+	return ret;
+}
+
+static int dib8000_write_word(struct dib8000_state *state, u16 reg, u16 val)
+{
+	int ret;
+
+	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
+		dprintk("could not acquire lock");
+		return -EINVAL;
+	}
+
+	state->i2c_write_buffer[0] = (reg >> 8) & 0xff;
+	state->i2c_write_buffer[1] = reg & 0xff;
+	state->i2c_write_buffer[2] = (val >> 8) & 0xff;
+	state->i2c_write_buffer[3] = val & 0xff;
+
+	memset(&state->msg[0], 0, sizeof(struct i2c_msg));
+	state->msg[0].addr = state->i2c.addr >> 1;
+	state->msg[0].flags = 0;
+	state->msg[0].buf = state->i2c_write_buffer;
+	state->msg[0].len = 4;
+
+	ret = (i2c_transfer(state->i2c.adap, state->msg, 1) != 1 ?
+			-EREMOTEIO : 0);
+	mutex_unlock(&state->i2c_buffer_lock);
+
+	return ret;
+}
+
+static const s16 coeff_2k_sb_1seg_dqpsk[8] = {
+	(769 << 5) | 0x0a, (745 << 5) | 0x03, (595 << 5) | 0x0d, (769 << 5) | 0x0a, (920 << 5) | 0x09, (784 << 5) | 0x02, (519 << 5) | 0x0c,
+		(920 << 5) | 0x09
+};
+
+static const s16 coeff_2k_sb_1seg[8] = {
+	(692 << 5) | 0x0b, (683 << 5) | 0x01, (519 << 5) | 0x09, (692 << 5) | 0x0b, 0 | 0x1f, 0 | 0x1f, 0 | 0x1f, 0 | 0x1f
+};
+
+static const s16 coeff_2k_sb_3seg_0dqpsk_1dqpsk[8] = {
+	(832 << 5) | 0x10, (912 << 5) | 0x05, (900 << 5) | 0x12, (832 << 5) | 0x10, (-931 << 5) | 0x0f, (912 << 5) | 0x04, (807 << 5) | 0x11,
+		(-931 << 5) | 0x0f
+};
+
+static const s16 coeff_2k_sb_3seg_0dqpsk[8] = {
+	(622 << 5) | 0x0c, (941 << 5) | 0x04, (796 << 5) | 0x10, (622 << 5) | 0x0c, (982 << 5) | 0x0c, (519 << 5) | 0x02, (572 << 5) | 0x0e,
+		(982 << 5) | 0x0c
+};
+
+static const s16 coeff_2k_sb_3seg_1dqpsk[8] = {
+	(699 << 5) | 0x14, (607 << 5) | 0x04, (944 << 5) | 0x13, (699 << 5) | 0x14, (-720 << 5) | 0x0d, (640 << 5) | 0x03, (866 << 5) | 0x12,
+		(-720 << 5) | 0x0d
+};
+
+static const s16 coeff_2k_sb_3seg[8] = {
+	(664 << 5) | 0x0c, (925 << 5) | 0x03, (937 << 5) | 0x10, (664 << 5) | 0x0c, (-610 << 5) | 0x0a, (697 << 5) | 0x01, (836 << 5) | 0x0e,
+		(-610 << 5) | 0x0a
+};
+
+static const s16 coeff_4k_sb_1seg_dqpsk[8] = {
+	(-955 << 5) | 0x0e, (687 << 5) | 0x04, (818 << 5) | 0x10, (-955 << 5) | 0x0e, (-922 << 5) | 0x0d, (750 << 5) | 0x03, (665 << 5) | 0x0f,
+		(-922 << 5) | 0x0d
+};
+
+static const s16 coeff_4k_sb_1seg[8] = {
+	(638 << 5) | 0x0d, (683 << 5) | 0x02, (638 << 5) | 0x0d, (638 << 5) | 0x0d, (-655 << 5) | 0x0a, (517 << 5) | 0x00, (698 << 5) | 0x0d,
+		(-655 << 5) | 0x0a
+};
+
+static const s16 coeff_4k_sb_3seg_0dqpsk_1dqpsk[8] = {
+	(-707 << 5) | 0x14, (910 << 5) | 0x06, (889 << 5) | 0x16, (-707 << 5) | 0x14, (-958 << 5) | 0x13, (993 << 5) | 0x05, (523 << 5) | 0x14,
+		(-958 << 5) | 0x13
+};
+
+static const s16 coeff_4k_sb_3seg_0dqpsk[8] = {
+	(-723 << 5) | 0x13, (910 << 5) | 0x05, (777 << 5) | 0x14, (-723 << 5) | 0x13, (-568 << 5) | 0x0f, (547 << 5) | 0x03, (696 << 5) | 0x12,
+		(-568 << 5) | 0x0f
+};
+
+static const s16 coeff_4k_sb_3seg_1dqpsk[8] = {
+	(-940 << 5) | 0x15, (607 << 5) | 0x05, (915 << 5) | 0x16, (-940 << 5) | 0x15, (-848 << 5) | 0x13, (683 << 5) | 0x04, (543 << 5) | 0x14,
+		(-848 << 5) | 0x13
+};
+
+static const s16 coeff_4k_sb_3seg[8] = {
+	(612 << 5) | 0x12, (910 << 5) | 0x04, (864 << 5) | 0x14, (612 << 5) | 0x12, (-869 << 5) | 0x13, (683 << 5) | 0x02, (869 << 5) | 0x12,
+		(-869 << 5) | 0x13
+};
+
+static const s16 coeff_8k_sb_1seg_dqpsk[8] = {
+	(-835 << 5) | 0x12, (684 << 5) | 0x05, (735 << 5) | 0x14, (-835 << 5) | 0x12, (-598 << 5) | 0x10, (781 << 5) | 0x04, (739 << 5) | 0x13,
+		(-598 << 5) | 0x10
+};
+
+static const s16 coeff_8k_sb_1seg[8] = {
+	(673 << 5) | 0x0f, (683 << 5) | 0x03, (808 << 5) | 0x12, (673 << 5) | 0x0f, (585 << 5) | 0x0f, (512 << 5) | 0x01, (780 << 5) | 0x0f,
+		(585 << 5) | 0x0f
+};
+
+static const s16 coeff_8k_sb_3seg_0dqpsk_1dqpsk[8] = {
+	(863 << 5) | 0x17, (930 << 5) | 0x07, (878 << 5) | 0x19, (863 << 5) | 0x17, (0 << 5) | 0x14, (521 << 5) | 0x05, (980 << 5) | 0x18,
+		(0 << 5) | 0x14
+};
+
+static const s16 coeff_8k_sb_3seg_0dqpsk[8] = {
+	(-924 << 5) | 0x17, (910 << 5) | 0x06, (774 << 5) | 0x17, (-924 << 5) | 0x17, (-877 << 5) | 0x15, (565 << 5) | 0x04, (553 << 5) | 0x15,
+		(-877 << 5) | 0x15
+};
+
+static const s16 coeff_8k_sb_3seg_1dqpsk[8] = {
+	(-921 << 5) | 0x19, (607 << 5) | 0x06, (881 << 5) | 0x19, (-921 << 5) | 0x19, (-921 << 5) | 0x14, (713 << 5) | 0x05, (1018 << 5) | 0x18,
+		(-921 << 5) | 0x14
+};
+
+static const s16 coeff_8k_sb_3seg[8] = {
+	(514 << 5) | 0x14, (910 << 5) | 0x05, (861 << 5) | 0x17, (514 << 5) | 0x14, (690 << 5) | 0x14, (683 << 5) | 0x03, (662 << 5) | 0x15,
+		(690 << 5) | 0x14
+};
+
+static const s16 ana_fe_coeff_3seg[24] = {
+	81, 80, 78, 74, 68, 61, 54, 45, 37, 28, 19, 11, 4, 1022, 1017, 1013, 1010, 1008, 1008, 1008, 1008, 1010, 1014, 1017
+};
+
+static const s16 ana_fe_coeff_1seg[24] = {
+	249, 226, 164, 82, 5, 981, 970, 988, 1018, 20, 31, 26, 8, 1012, 1000, 1018, 1012, 8, 15, 14, 9, 3, 1017, 1003
+};
+
+static const s16 ana_fe_coeff_13seg[24] = {
+	396, 305, 105, -51, -77, -12, 41, 31, -11, -30, -11, 14, 15, -2, -13, -7, 5, 8, 1, -6, -7, -3, 0, 1
+};
+
+static u16 fft_to_mode(struct dib8000_state *state)
+{
+	u16 mode;
+	switch (state->fe[0]->dtv_property_cache.transmission_mode) {
+	case TRANSMISSION_MODE_2K:
+		mode = 1;
+		break;
+	case TRANSMISSION_MODE_4K:
+		mode = 2;
+		break;
+	default:
+	case TRANSMISSION_MODE_AUTO:
+	case TRANSMISSION_MODE_8K:
+		mode = 3;
+		break;
+	}
+	return mode;
+}
+
+static void dib8000_set_acquisition_mode(struct dib8000_state *state)
+{
+	u16 nud = dib8000_read_word(state, 298);
+	nud |= (1 << 3) | (1 << 0);
+	dprintk("acquisition mode activated");
+	dib8000_write_word(state, 298, nud);
+}
+static int dib8000_set_output_mode(struct dvb_frontend *fe, int mode)
+{
+	struct dib8000_state *state = fe->demodulator_priv;
+
+	u16 outreg, fifo_threshold, smo_mode, sram = 0x0205;	/* by default SDRAM deintlv is enabled */
+
+	outreg = 0;
+	fifo_threshold = 1792;
+	smo_mode = (dib8000_read_word(state, 299) & 0x0050) | (1 << 1);
+
+	dprintk("-I-	Setting output mode for demod %p to %d",
+			&state->fe[0], mode);
+
+	switch (mode) {
+	case OUTMODE_MPEG2_PAR_GATED_CLK:	// STBs with parallel gated clock
+		outreg = (1 << 10);	/* 0x0400 */
+		break;
+	case OUTMODE_MPEG2_PAR_CONT_CLK:	// STBs with parallel continues clock
+		outreg = (1 << 10) | (1 << 6);	/* 0x0440 */
+		break;
+	case OUTMODE_MPEG2_SERIAL:	// STBs with serial input
+		outreg = (1 << 10) | (2 << 6) | (0 << 1);	/* 0x0482 */
+		break;
+	case OUTMODE_DIVERSITY:
+		if (state->cfg.hostbus_diversity) {
+			outreg = (1 << 10) | (4 << 6);	/* 0x0500 */
+			sram &= 0xfdff;
+		} else
+			sram |= 0x0c00;
+		break;
+	case OUTMODE_MPEG2_FIFO:	// e.g. USB feeding
+		smo_mode |= (3 << 1);
+		fifo_threshold = 512;
+		outreg = (1 << 10) | (5 << 6);
+		break;
+	case OUTMODE_HIGH_Z:	// disable
+		outreg = 0;
+		break;
+
+	case OUTMODE_ANALOG_ADC:
+		outreg = (1 << 10) | (3 << 6);
+		dib8000_set_acquisition_mode(state);
+		break;
+
+	default:
+		dprintk("Unhandled output_mode passed to be set for demod %p",
+				&state->fe[0]);
+		return -EINVAL;
+	}
+
+	if (state->cfg.output_mpeg2_in_188_bytes)
+		smo_mode |= (1 << 5);
+
+	dib8000_write_word(state, 299, smo_mode);
+	dib8000_write_word(state, 300, fifo_threshold);	/* synchronous fread */
+	dib8000_write_word(state, 1286, outreg);
+	dib8000_write_word(state, 1291, sram);
+
+	return 0;
+}
+
+static int dib8000_set_diversity_in(struct dvb_frontend *fe, int onoff)
+{
+	struct dib8000_state *state = fe->demodulator_priv;
+	u16 sync_wait = dib8000_read_word(state, 273) & 0xfff0;
+
+	if (!state->differential_constellation) {
+		dib8000_write_word(state, 272, 1 << 9);	//dvsy_off_lmod4 = 1
+		dib8000_write_word(state, 273, sync_wait | (1 << 2) | 2);	// sync_enable = 1; comb_mode = 2
+	} else {
+		dib8000_write_word(state, 272, 0);	//dvsy_off_lmod4 = 0
+		dib8000_write_word(state, 273, sync_wait);	// sync_enable = 0; comb_mode = 0
+	}
+	state->diversity_onoff = onoff;
+
+	switch (onoff) {
+	case 0:		/* only use the internal way - not the diversity input */
+		dib8000_write_word(state, 270, 1);
+		dib8000_write_word(state, 271, 0);
+		break;
+	case 1:		/* both ways */
+		dib8000_write_word(state, 270, 6);
+		dib8000_write_word(state, 271, 6);
+		break;
+	case 2:		/* only the diversity input */
+		dib8000_write_word(state, 270, 0);
+		dib8000_write_word(state, 271, 1);
+		break;
+	}
+	return 0;
+}
+
+static void dib8000_set_power_mode(struct dib8000_state *state, enum dib8000_power_mode mode)
+{
+	/* by default everything is going to be powered off */
+	u16 reg_774 = 0x3fff, reg_775 = 0xffff, reg_776 = 0xffff,
+		reg_900 = (dib8000_read_word(state, 900) & 0xfffc) | 0x3,
+		reg_1280;
+
+	if (state->revision != 0x8090)
+		reg_1280 = (dib8000_read_word(state, 1280) & 0x00ff) | 0xff00;
+	else
+		reg_1280 = (dib8000_read_word(state, 1280) & 0x707f) | 0x8f80;
+
+	/* now, depending on the requested mode, we power on */
+	switch (mode) {
+		/* power up everything in the demod */
+	case DIB8000_POWER_ALL:
+		reg_774 = 0x0000;
+		reg_775 = 0x0000;
+		reg_776 = 0x0000;
+		reg_900 &= 0xfffc;
+		if (state->revision != 0x8090)
+			reg_1280 &= 0x00ff;
+		else
+			reg_1280 &= 0x707f;
+		break;
+	case DIB8000_POWER_INTERFACE_ONLY:
+		if (state->revision != 0x8090)
+			reg_1280 &= 0x00ff;
+		else
+			reg_1280 &= 0xfa7b;
+		break;
+	}
+
+	dprintk("powermode : 774 : %x ; 775 : %x; 776 : %x ; 900 : %x; 1280 : %x", reg_774, reg_775, reg_776, reg_900, reg_1280);
+	dib8000_write_word(state, 774, reg_774);
+	dib8000_write_word(state, 775, reg_775);
+	dib8000_write_word(state, 776, reg_776);
+	dib8000_write_word(state, 900, reg_900);
+	dib8000_write_word(state, 1280, reg_1280);
+}
+
+static int dib8000_init_sdram(struct dib8000_state *state)
+{
+	u16 reg = 0;
+	dprintk("Init sdram");
+
+	reg = dib8000_read_word(state, 274)&0xfff0;
+	/* P_dintlv_delay_ram = 7 because of MobileSdram */
+	dib8000_write_word(state, 274, reg | 0x7);
+
+	dib8000_write_word(state, 1803, (7<<2));
+
+	reg = dib8000_read_word(state, 1280);
+	/* force restart P_restart_sdram */
+	dib8000_write_word(state, 1280,  reg | (1<<2));
+
+	/* release restart P_restart_sdram */
+	dib8000_write_word(state, 1280,  reg);
+
+	return 0;
+}
+
+static int dib8000_set_adc_state(struct dib8000_state *state, enum dibx000_adc_states no)
+{
+	int ret = 0;
+	u16 reg, reg_907 = dib8000_read_word(state, 907);
+	u16 reg_908 = dib8000_read_word(state, 908);
+
+	switch (no) {
+	case DIBX000_SLOW_ADC_ON:
+		if (state->revision != 0x8090) {
+			reg_908 |= (1 << 1) | (1 << 0);
+			ret |= dib8000_write_word(state, 908, reg_908);
+			reg_908 &= ~(1 << 1);
+		} else {
+			reg = dib8000_read_word(state, 1925);
+			/* en_slowAdc = 1 & reset_sladc = 1 */
+			dib8000_write_word(state, 1925, reg |
+					(1<<4) | (1<<2));
+
+			/* read acces to make it works... strange ... */
+			reg = dib8000_read_word(state, 1925);
+			msleep(20);
+			/* en_slowAdc = 1 & reset_sladc = 0 */
+			dib8000_write_word(state, 1925, reg & ~(1<<4));
+
+			reg = dib8000_read_word(state, 921) & ~((0x3 << 14)
+					| (0x3 << 12));
+			/* ref = Vin1 => Vbg ; sel = Vin0 or Vin3 ;
+			   (Vin2 = Vcm) */
+			dib8000_write_word(state, 921, reg | (1 << 14)
+					| (3 << 12));
+		}
+		break;
+
+	case DIBX000_SLOW_ADC_OFF:
+		if (state->revision == 0x8090) {
+			reg = dib8000_read_word(state, 1925);
+			/* reset_sladc = 1 en_slowAdc = 0 */
+			dib8000_write_word(state, 1925,
+					(reg & ~(1<<2)) | (1<<4));
+		}
+		reg_908 |= (1 << 1) | (1 << 0);
+		break;
+
+	case DIBX000_ADC_ON:
+		reg_907 &= 0x0fff;
+		reg_908 &= 0x0003;
+		break;
+
+	case DIBX000_ADC_OFF:	// leave the VBG voltage on
+		reg_907 |= (1 << 14) | (1 << 13) | (1 << 12);
+		reg_908 |= (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2);
+		break;
+
+	case DIBX000_VBG_ENABLE:
+		reg_907 &= ~(1 << 15);
+		break;
+
+	case DIBX000_VBG_DISABLE:
+		reg_907 |= (1 << 15);
+		break;
+
+	default:
+		break;
+	}
+
+	ret |= dib8000_write_word(state, 907, reg_907);
+	ret |= dib8000_write_word(state, 908, reg_908);
+
+	return ret;
+}
+
+static int dib8000_set_bandwidth(struct dvb_frontend *fe, u32 bw)
+{
+	struct dib8000_state *state = fe->demodulator_priv;
+	u32 timf;
+
+	if (bw == 0)
+		bw = 6000;
+
+	if (state->timf == 0) {
+		dprintk("using default timf");
+		timf = state->timf_default;
+	} else {
+		dprintk("using updated timf");
+		timf = state->timf;
+	}
+
+	dib8000_write_word(state, 29, (u16) ((timf >> 16) & 0xffff));
+	dib8000_write_word(state, 30, (u16) ((timf) & 0xffff));
+
+	return 0;
+}
+
+static int dib8000_sad_calib(struct dib8000_state *state)
+{
+	if (state->revision == 0x8090) {
+		dprintk("%s: the sad calibration is not needed for the dib8096P",
+				__func__);
+		return 0;
+	}
+	/* internal */
+	dib8000_write_word(state, 923, (0 << 1) | (0 << 0));
+	dib8000_write_word(state, 924, 776);	// 0.625*3.3 / 4096
+
+	/* do the calibration */
+	dib8000_write_word(state, 923, (1 << 0));
+	dib8000_write_word(state, 923, (0 << 0));
+
+	msleep(1);
+	return 0;
+}
+
+int dib8000_set_wbd_ref(struct dvb_frontend *fe, u16 value)
+{
+	struct dib8000_state *state = fe->demodulator_priv;
+	if (value > 4095)
+		value = 4095;
+	state->wbd_ref = value;
+	return dib8000_write_word(state, 106, value);
+}
+
+EXPORT_SYMBOL(dib8000_set_wbd_ref);
+static void dib8000_reset_pll_common(struct dib8000_state *state, const struct dibx000_bandwidth_config *bw)
+{
+	dprintk("ifreq: %d %x, inversion: %d", bw->ifreq, bw->ifreq, bw->ifreq >> 25);
+	if (state->revision != 0x8090) {
+		dib8000_write_word(state, 23,
+				(u16) (((bw->internal * 1000) >> 16) & 0xffff));
+		dib8000_write_word(state, 24,
+				(u16) ((bw->internal * 1000) & 0xffff));
+	} else {
+		dib8000_write_word(state, 23, (u16) (((bw->internal / 2 * 1000) >> 16) & 0xffff));
+		dib8000_write_word(state, 24,
+				(u16) ((bw->internal  / 2 * 1000) & 0xffff));
+	}
+	dib8000_write_word(state, 27, (u16) ((bw->ifreq >> 16) & 0x01ff));
+	dib8000_write_word(state, 28, (u16) (bw->ifreq & 0xffff));
+	dib8000_write_word(state, 26, (u16) ((bw->ifreq >> 25) & 0x0003));
+
+	if (state->revision != 0x8090)
+		dib8000_write_word(state, 922, bw->sad_cfg);
+}
+
+static void dib8000_reset_pll(struct dib8000_state *state)
+{
+	const struct dibx000_bandwidth_config *pll = state->cfg.pll;
+	u16 clk_cfg1, reg;
+
+	if (state->revision != 0x8090) {
+		dib8000_write_word(state, 901,
+				(pll->pll_prediv << 8) | (pll->pll_ratio << 0));
+
+		clk_cfg1 = (1 << 10) | (0 << 9) | (pll->IO_CLK_en_core << 8) |
+			(pll->bypclk_div << 5) | (pll->enable_refdiv << 4) |
+			(1 << 3) | (pll->pll_range << 1) |
+			(pll->pll_reset << 0);
+
+		dib8000_write_word(state, 902, clk_cfg1);
+		clk_cfg1 = (clk_cfg1 & 0xfff7) | (pll->pll_bypass << 3);
+		dib8000_write_word(state, 902, clk_cfg1);
+
+		dprintk("clk_cfg1: 0x%04x", clk_cfg1);
+
+		/* smpl_cfg: P_refclksel=2, P_ensmplsel=1 nodivsmpl=1 */
+		if (state->cfg.pll->ADClkSrc == 0)
+			dib8000_write_word(state, 904,
+					(0 << 15) | (0 << 12) | (0 << 10) |
+					(pll->modulo << 8) |
+					(pll->ADClkSrc << 7) | (0 << 1));
+		else if (state->cfg.refclksel != 0)
+			dib8000_write_word(state, 904, (0 << 15) | (1 << 12) |
+					((state->cfg.refclksel & 0x3) << 10) |
+					(pll->modulo << 8) |
+					(pll->ADClkSrc << 7) | (0 << 1));
+		else
+			dib8000_write_word(state, 904, (0 << 15) | (1 << 12) |
+					(3 << 10) | (pll->modulo << 8) |
+					(pll->ADClkSrc << 7) | (0 << 1));
+	} else {
+		dib8000_write_word(state, 1856, (!pll->pll_reset<<13) |
+				(pll->pll_range<<12) | (pll->pll_ratio<<6) |
+				(pll->pll_prediv));
+
+		reg = dib8000_read_word(state, 1857);
+		dib8000_write_word(state, 1857, reg|(!pll->pll_bypass<<15));
+
+		reg = dib8000_read_word(state, 1858); /* Force clk out pll /2 */
+		dib8000_write_word(state, 1858, reg | 1);
+
+		dib8000_write_word(state, 904, (pll->modulo << 8));
+	}
+
+	dib8000_reset_pll_common(state, pll);
+}
+
+int dib8000_update_pll(struct dvb_frontend *fe,
+		struct dibx000_bandwidth_config *pll)
+{
+	struct dib8000_state *state = fe->demodulator_priv;
+	u16 reg_1857, reg_1856 = dib8000_read_word(state, 1856);
+	u8 loopdiv, prediv;
+	u32 internal, xtal;
+
+	/* get back old values */
+	prediv = reg_1856 & 0x3f;
+	loopdiv = (reg_1856 >> 6) & 0x3f;
+
+	if ((pll != NULL) && (pll->pll_prediv != prediv ||
+				pll->pll_ratio != loopdiv)) {
+		dprintk("Updating pll (prediv: old =  %d new = %d ; loopdiv : old = %d new = %d)", prediv, pll->pll_prediv, loopdiv, pll->pll_ratio);
+		reg_1856 &= 0xf000;
+		reg_1857 = dib8000_read_word(state, 1857);
+		/* disable PLL */
+		dib8000_write_word(state, 1857, reg_1857 & ~(1 << 15));
+
+		dib8000_write_word(state, 1856, reg_1856 |
+				((pll->pll_ratio & 0x3f) << 6) |
+				(pll->pll_prediv & 0x3f));
+
+		/* write new system clk into P_sec_len */
+		internal = dib8000_read32(state, 23) / 1000;
+		dprintk("Old Internal = %d", internal);
+		xtal = 2 * (internal / loopdiv) * prediv;
+		internal = 1000 * (xtal/pll->pll_prediv) * pll->pll_ratio;
+		dprintk("Xtal = %d , New Fmem = %d New Fdemod = %d, New Fsampling = %d", xtal, internal/1000, internal/2000, internal/8000);
+		dprintk("New Internal = %d", internal);
+
+		dib8000_write_word(state, 23,
+				(u16) (((internal / 2) >> 16) & 0xffff));
+		dib8000_write_word(state, 24, (u16) ((internal / 2) & 0xffff));
+		/* enable PLL */
+		dib8000_write_word(state, 1857, reg_1857 | (1 << 15));
+
+		while (((dib8000_read_word(state, 1856)>>15)&0x1) != 1)
+			dprintk("Waiting for PLL to lock");
+
+		/* verify */
+		reg_1856 = dib8000_read_word(state, 1856);
+		dprintk("PLL Updated with prediv = %d and loopdiv = %d",
+				reg_1856&0x3f, (reg_1856>>6)&0x3f);
+
+		return 0;
+	}
+	return -EINVAL;
+}
+EXPORT_SYMBOL(dib8000_update_pll);
+
+
+static int dib8000_reset_gpio(struct dib8000_state *st)
+{
+	/* reset the GPIOs */
+	dib8000_write_word(st, 1029, st->cfg.gpio_dir);
+	dib8000_write_word(st, 1030, st->cfg.gpio_val);
+
+	/* TODO 782 is P_gpio_od */
+
+	dib8000_write_word(st, 1032, st->cfg.gpio_pwm_pos);
+
+	dib8000_write_word(st, 1037, st->cfg.pwm_freq_div);
+	return 0;
+}
+
+static int dib8000_cfg_gpio(struct dib8000_state *st, u8 num, u8 dir, u8 val)
+{
+	st->cfg.gpio_dir = dib8000_read_word(st, 1029);
+	st->cfg.gpio_dir &= ~(1 << num);	/* reset the direction bit */
+	st->cfg.gpio_dir |= (dir & 0x1) << num;	/* set the new direction */
+	dib8000_write_word(st, 1029, st->cfg.gpio_dir);
+
+	st->cfg.gpio_val = dib8000_read_word(st, 1030);
+	st->cfg.gpio_val &= ~(1 << num);	/* reset the direction bit */
+	st->cfg.gpio_val |= (val & 0x01) << num;	/* set the new value */
+	dib8000_write_word(st, 1030, st->cfg.gpio_val);
+
+	dprintk("gpio dir: %x: gpio val: %x", st->cfg.gpio_dir, st->cfg.gpio_val);
+
+	return 0;
+}
+
+int dib8000_set_gpio(struct dvb_frontend *fe, u8 num, u8 dir, u8 val)
+{
+	struct dib8000_state *state = fe->demodulator_priv;
+	return dib8000_cfg_gpio(state, num, dir, val);
+}
+
+EXPORT_SYMBOL(dib8000_set_gpio);
+static const u16 dib8000_defaults[] = {
+	/* auto search configuration - lock0 by default waiting
+	 * for cpil_lock; lock1 cpil_lock; lock2 tmcc_sync_lock */
+	3, 7,
+	0x0004,
+	0x0400,
+	0x0814,
+
+	12, 11,
+	0x001b,
+	0x7740,
+	0x005b,
+	0x8d80,
+	0x01c9,
+	0xc380,
+	0x0000,
+	0x0080,
+	0x0000,
+	0x0090,
+	0x0001,
+	0xd4c0,
+
+	/*1, 32,
+		0x6680 // P_corm_thres Lock algorithms configuration */
+
+	11, 80,			/* set ADC level to -16 */
+	(1 << 13) - 825 - 117,
+	(1 << 13) - 837 - 117,
+	(1 << 13) - 811 - 117,
+	(1 << 13) - 766 - 117,
+	(1 << 13) - 737 - 117,
+	(1 << 13) - 693 - 117,
+	(1 << 13) - 648 - 117,
+	(1 << 13) - 619 - 117,
+	(1 << 13) - 575 - 117,
+	(1 << 13) - 531 - 117,
+	(1 << 13) - 501 - 117,
+
+	4, 108,
+	0,
+	0,
+	0,
+	0,
+
+	1, 175,
+	0x0410,
+	1, 179,
+	8192,			// P_fft_nb_to_cut
+
+	6, 181,
+	0x2800,			// P_coff_corthres_ ( 2k 4k 8k ) 0x2800
+	0x2800,
+	0x2800,
+	0x2800,			// P_coff_cpilthres_ ( 2k 4k 8k ) 0x2800
+	0x2800,
+	0x2800,
+
+	2, 193,
+	0x0666,			// P_pha3_thres
+	0x0000,			// P_cti_use_cpe, P_cti_use_prog
+
+	2, 205,
+	0x200f,			// P_cspu_regul, P_cspu_win_cut
+	0x000f,			// P_des_shift_work
+
+	5, 215,
+	0x023d,			// P_adp_regul_cnt
+	0x00a4,			// P_adp_noise_cnt
+	0x00a4,			// P_adp_regul_ext
+	0x7ff0,			// P_adp_noise_ext
+	0x3ccc,			// P_adp_fil
+
+	1, 230,
+	0x0000,			// P_2d_byp_ti_num
+
+	1, 263,
+	0x800,			//P_equal_thres_wgn
+
+	1, 268,
+	(2 << 9) | 39,		// P_equal_ctrl_synchro, P_equal_speedmode
+
+	1, 270,
+	0x0001,			// P_div_lock0_wait
+	1, 285,
+	0x0020,			//p_fec_
+	1, 299,
+	0x0062,			/* P_smo_mode, P_smo_rs_discard, P_smo_fifo_flush, P_smo_pid_parse, P_smo_error_discard */
+
+	1, 338,
+	(1 << 12) |		// P_ctrl_corm_thres4pre_freq_inh=1
+		(1 << 10) |
+		(0 << 9) |		/* P_ctrl_pre_freq_inh=0 */
+		(3 << 5) |		/* P_ctrl_pre_freq_step=3 */
+		(1 << 0),		/* P_pre_freq_win_len=1 */
+
+	0,
+};
+
+static u16 dib8000_identify(struct i2c_device *client)
+{
+	u16 value;
+
+	//because of glitches sometimes
+	value = dib8000_i2c_read16(client, 896);
+
+	if ((value = dib8000_i2c_read16(client, 896)) != 0x01b3) {
+		dprintk("wrong Vendor ID (read=0x%x)", value);
+		return 0;
+	}
+
+	value = dib8000_i2c_read16(client, 897);
+	if (value != 0x8000 && value != 0x8001 &&
+			value != 0x8002 && value != 0x8090) {
+		dprintk("wrong Device ID (%x)", value);
+		return 0;
+	}
+
+	switch (value) {
+	case 0x8000:
+		dprintk("found DiB8000A");
+		break;
+	case 0x8001:
+		dprintk("found DiB8000B");
+		break;
+	case 0x8002:
+		dprintk("found DiB8000C");
+		break;
+	case 0x8090:
+		dprintk("found DiB8096P");
+		break;
+	}
+	return value;
+}
+
+static int dib8000_reset(struct dvb_frontend *fe)
+{
+	struct dib8000_state *state = fe->demodulator_priv;
+
+	if ((state->revision = dib8000_identify(&state->i2c)) == 0)
+		return -EINVAL;
+
+	/* sram lead in, rdy */
+	if (state->revision != 0x8090)
+		dib8000_write_word(state, 1287, 0x0003);
+
+	if (state->revision == 0x8000)
+		dprintk("error : dib8000 MA not supported");
+
+	dibx000_reset_i2c_master(&state->i2c_master);
+
+	dib8000_set_power_mode(state, DIB8000_POWER_ALL);
+
+	/* always leave the VBG voltage on - it consumes almost nothing but takes a long time to start */
+	dib8000_set_adc_state(state, DIBX000_VBG_ENABLE);
+
+	/* restart all parts */
+	dib8000_write_word(state, 770, 0xffff);
+	dib8000_write_word(state, 771, 0xffff);
+	dib8000_write_word(state, 772, 0xfffc);
+	if (state->revision == 0x8090)
+		dib8000_write_word(state, 1280, 0x0045);
+	else
+		dib8000_write_word(state, 1280, 0x004d);
+	dib8000_write_word(state, 1281, 0x000c);
+
+	dib8000_write_word(state, 770, 0x0000);
+	dib8000_write_word(state, 771, 0x0000);
+	dib8000_write_word(state, 772, 0x0000);
+	dib8000_write_word(state, 898, 0x0004);	// sad
+	dib8000_write_word(state, 1280, 0x0000);
+	dib8000_write_word(state, 1281, 0x0000);
+
+	/* drives */
+	if (state->revision != 0x8090) {
+		if (state->cfg.drives)
+			dib8000_write_word(state, 906, state->cfg.drives);
+		else {
+			dprintk("using standard PAD-drive-settings, please adjust settings in config-struct to be optimal.");
+			/* min drive SDRAM - not optimal - adjust */
+			dib8000_write_word(state, 906, 0x2d98);
+		}
+	}
+
+	dib8000_reset_pll(state);
+	if (state->revision != 0x8090)
+		dib8000_write_word(state, 898, 0x0004);
+
+	if (dib8000_reset_gpio(state) != 0)
+		dprintk("GPIO reset was not successful.");
+
+	if ((state->revision != 0x8090) &&
+			(dib8000_set_output_mode(fe, OUTMODE_HIGH_Z) != 0))
+		dprintk("OUTPUT_MODE could not be resetted.");
+
+	state->current_agc = NULL;
+
+	// P_iqc_alpha_pha, P_iqc_alpha_amp, P_iqc_dcc_alpha, ...
+	/* P_iqc_ca2 = 0; P_iqc_impnc_on = 0; P_iqc_mode = 0; */
+	if (state->cfg.pll->ifreq == 0)
+		dib8000_write_word(state, 40, 0x0755);	/* P_iqc_corr_inh = 0 enable IQcorr block */
+	else
+		dib8000_write_word(state, 40, 0x1f55);	/* P_iqc_corr_inh = 1 disable IQcorr block */
+
+	{
+		u16 l = 0, r;
+		const u16 *n;
+		n = dib8000_defaults;
+		l = *n++;
+		while (l) {
+			r = *n++;
+			do {
+				dib8000_write_word(state, r, *n++);
+				r++;
+			} while (--l);
+			l = *n++;
+		}
+	}
+	if (state->revision != 0x8090)
+		dib8000_write_word(state, 903, (0 << 4) | 2);
+	state->isdbt_cfg_loaded = 0;
+
+	//div_cfg override for special configs
+	if (state->cfg.div_cfg != 0)
+		dib8000_write_word(state, 903, state->cfg.div_cfg);
+
+	/* unforce divstr regardless whether i2c enumeration was done or not */
+	dib8000_write_word(state, 1285, dib8000_read_word(state, 1285) & ~(1 << 1));
+
+	dib8000_set_bandwidth(fe, 6000);
+
+	dib8000_set_adc_state(state, DIBX000_SLOW_ADC_ON);
+	if (state->revision != 0x8090) {
+		dib8000_sad_calib(state);
+		dib8000_set_adc_state(state, DIBX000_SLOW_ADC_OFF);
+	}
+
+	dib8000_set_power_mode(state, DIB8000_POWER_INTERFACE_ONLY);
+
+	return 0;
+}
+
+static void dib8000_restart_agc(struct dib8000_state *state)
+{
+	// P_restart_iqc & P_restart_agc
+	dib8000_write_word(state, 770, 0x0a00);
+	dib8000_write_word(state, 770, 0x0000);
+}
+
+static int dib8000_update_lna(struct dib8000_state *state)
+{
+	u16 dyn_gain;
+
+	if (state->cfg.update_lna) {
+		// read dyn_gain here (because it is demod-dependent and not tuner)
+		dyn_gain = dib8000_read_word(state, 390);
+
+		if (state->cfg.update_lna(state->fe[0], dyn_gain)) {
+			dib8000_restart_agc(state);
+			return 1;
+		}
+	}
+	return 0;
+}
+
+static int dib8000_set_agc_config(struct dib8000_state *state, u8 band)
+{
+	struct dibx000_agc_config *agc = NULL;
+	int i;
+	u16 reg;
+
+	if (state->current_band == band && state->current_agc != NULL)
+		return 0;
+	state->current_band = band;
+
+	for (i = 0; i < state->cfg.agc_config_count; i++)
+		if (state->cfg.agc[i].band_caps & band) {
+			agc = &state->cfg.agc[i];
+			break;
+		}
+
+	if (agc == NULL) {
+		dprintk("no valid AGC configuration found for band 0x%02x", band);
+		return -EINVAL;
+	}
+
+	state->current_agc = agc;
+
+	/* AGC */
+	dib8000_write_word(state, 76, agc->setup);
+	dib8000_write_word(state, 77, agc->inv_gain);
+	dib8000_write_word(state, 78, agc->time_stabiliz);
+	dib8000_write_word(state, 101, (agc->alpha_level << 12) | agc->thlock);
+
+	// Demod AGC loop configuration
+	dib8000_write_word(state, 102, (agc->alpha_mant << 5) | agc->alpha_exp);
+	dib8000_write_word(state, 103, (agc->beta_mant << 6) | agc->beta_exp);
+
+	dprintk("WBD: ref: %d, sel: %d, active: %d, alpha: %d",
+		state->wbd_ref != 0 ? state->wbd_ref : agc->wbd_ref, agc->wbd_sel, !agc->perform_agc_softsplit, agc->wbd_sel);
+
+	/* AGC continued */
+	if (state->wbd_ref != 0)
+		dib8000_write_word(state, 106, state->wbd_ref);
+	else			// use default
+		dib8000_write_word(state, 106, agc->wbd_ref);
+
+	if (state->revision == 0x8090) {
+		reg = dib8000_read_word(state, 922) & (0x3 << 2);
+		dib8000_write_word(state, 922, reg | (agc->wbd_sel << 2));
+	}
+
+	dib8000_write_word(state, 107, (agc->wbd_alpha << 9) | (agc->perform_agc_softsplit << 8));
+	dib8000_write_word(state, 108, agc->agc1_max);
+	dib8000_write_word(state, 109, agc->agc1_min);
+	dib8000_write_word(state, 110, agc->agc2_max);
+	dib8000_write_word(state, 111, agc->agc2_min);
+	dib8000_write_word(state, 112, (agc->agc1_pt1 << 8) | agc->agc1_pt2);
+	dib8000_write_word(state, 113, (agc->agc1_slope1 << 8) | agc->agc1_slope2);
+	dib8000_write_word(state, 114, (agc->agc2_pt1 << 8) | agc->agc2_pt2);
+	dib8000_write_word(state, 115, (agc->agc2_slope1 << 8) | agc->agc2_slope2);
+
+	dib8000_write_word(state, 75, agc->agc1_pt3);
+	if (state->revision != 0x8090)
+		dib8000_write_word(state, 923,
+				(dib8000_read_word(state, 923) & 0xffe3) |
+				(agc->wbd_inv << 4) | (agc->wbd_sel << 2));
+
+	return 0;
+}
+
+void dib8000_pwm_agc_reset(struct dvb_frontend *fe)
+{
+	struct dib8000_state *state = fe->demodulator_priv;
+	dib8000_set_adc_state(state, DIBX000_ADC_ON);
+	dib8000_set_agc_config(state, (unsigned char)(BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency / 1000)));
+}
+EXPORT_SYMBOL(dib8000_pwm_agc_reset);
+
+static int dib8000_agc_soft_split(struct dib8000_state *state)
+{
+	u16 agc, split_offset;
+
+	if (!state->current_agc || !state->current_agc->perform_agc_softsplit || state->current_agc->split.max == 0)
+		return FE_CALLBACK_TIME_NEVER;
+
+	// n_agc_global
+	agc = dib8000_read_word(state, 390);
+
+	if (agc > state->current_agc->split.min_thres)
+		split_offset = state->current_agc->split.min;
+	else if (agc < state->current_agc->split.max_thres)
+		split_offset = state->current_agc->split.max;
+	else
+		split_offset = state->current_agc->split.max *
+			(agc - state->current_agc->split.min_thres) /
+			(state->current_agc->split.max_thres - state->current_agc->split.min_thres);
+
+	dprintk("AGC split_offset: %d", split_offset);
+
+	// P_agc_force_split and P_agc_split_offset
+	dib8000_write_word(state, 107, (dib8000_read_word(state, 107) & 0xff00) | split_offset);
+	return 5000;
+}
+
+static int dib8000_agc_startup(struct dvb_frontend *fe)
+{
+	struct dib8000_state *state = fe->demodulator_priv;
+	enum frontend_tune_state *tune_state = &state->tune_state;
+	int ret = 0;
+	u16 reg, upd_demod_gain_period = 0x8000;
+
+	switch (*tune_state) {
+	case CT_AGC_START:
+		// set power-up level: interf+analog+AGC
+
+		if (state->revision != 0x8090)
+			dib8000_set_adc_state(state, DIBX000_ADC_ON);
+		else {
+			dib8000_set_power_mode(state, DIB8000_POWER_ALL);
+
+			reg = dib8000_read_word(state, 1947)&0xff00;
+			dib8000_write_word(state, 1946,
+					upd_demod_gain_period & 0xFFFF);
+			/* bit 14 = enDemodGain */
+			dib8000_write_word(state, 1947, reg | (1<<14) |
+					((upd_demod_gain_period >> 16) & 0xFF));
+
+			/* enable adc i & q */
+			reg = dib8000_read_word(state, 1920);
+			dib8000_write_word(state, 1920, (reg | 0x3) &
+					(~(1 << 7)));
+		}
+
+		if (dib8000_set_agc_config(state, (unsigned char)(BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency / 1000))) != 0) {
+			*tune_state = CT_AGC_STOP;
+			state->status = FE_STATUS_TUNE_FAILED;
+			break;
+		}
+
+		ret = 70;
+		*tune_state = CT_AGC_STEP_0;
+		break;
+
+	case CT_AGC_STEP_0:
+		//AGC initialization
+		if (state->cfg.agc_control)
+			state->cfg.agc_control(fe, 1);
+
+		dib8000_restart_agc(state);
+
+		// wait AGC rough lock time
+		ret = 50;
+		*tune_state = CT_AGC_STEP_1;
+		break;
+
+	case CT_AGC_STEP_1:
+		// wait AGC accurate lock time
+		ret = 70;
+
+		if (dib8000_update_lna(state))
+			// wait only AGC rough lock time
+			ret = 50;
+		else
+			*tune_state = CT_AGC_STEP_2;
+		break;
+
+	case CT_AGC_STEP_2:
+		dib8000_agc_soft_split(state);
+
+		if (state->cfg.agc_control)
+			state->cfg.agc_control(fe, 0);
+
+		*tune_state = CT_AGC_STOP;
+		break;
+	default:
+		ret = dib8000_agc_soft_split(state);
+		break;
+	}
+	return ret;
+
+}
+
+static void dib8096p_host_bus_drive(struct dib8000_state *state, u8 drive)
+{
+	u16 reg;
+
+	drive &= 0x7;
+
+	/* drive host bus 2, 3, 4 */
+	reg = dib8000_read_word(state, 1798) &
+		~(0x7 | (0x7 << 6) | (0x7 << 12));
+	reg |= (drive<<12) | (drive<<6) | drive;
+	dib8000_write_word(state, 1798, reg);
+
+	/* drive host bus 5,6 */
+	reg = dib8000_read_word(state, 1799) & ~((0x7 << 2) | (0x7 << 8));
+	reg |= (drive<<8) | (drive<<2);
+	dib8000_write_word(state, 1799, reg);
+
+	/* drive host bus 7, 8, 9 */
+	reg = dib8000_read_word(state, 1800) &
+		~(0x7 | (0x7 << 6) | (0x7 << 12));
+	reg |= (drive<<12) | (drive<<6) | drive;
+	dib8000_write_word(state, 1800, reg);
+
+	/* drive host bus 10, 11 */
+	reg = dib8000_read_word(state, 1801) & ~((0x7 << 2) | (0x7 << 8));
+	reg |= (drive<<8) | (drive<<2);
+	dib8000_write_word(state, 1801, reg);
+
+	/* drive host bus 12, 13, 14 */
+	reg = dib8000_read_word(state, 1802) &
+		~(0x7 | (0x7 << 6) | (0x7 << 12));
+	reg |= (drive<<12) | (drive<<6) | drive;
+	dib8000_write_word(state, 1802, reg);
+}
+
+static u32 dib8096p_calcSyncFreq(u32 P_Kin, u32 P_Kout,
+		u32 insertExtSynchro, u32 syncSize)
+{
+	u32 quantif = 3;
+	u32 nom = (insertExtSynchro * P_Kin+syncSize);
+	u32 denom = P_Kout;
+	u32 syncFreq = ((nom << quantif) / denom);
+
+	if ((syncFreq & ((1 << quantif) - 1)) != 0)
+		syncFreq = (syncFreq >> quantif) + 1;
+	else
+		syncFreq = (syncFreq >> quantif);
+
+	if (syncFreq != 0)
+		syncFreq = syncFreq - 1;
+
+	return syncFreq;
+}
+
+static void dib8096p_cfg_DibTx(struct dib8000_state *state, u32 P_Kin,
+		u32 P_Kout, u32 insertExtSynchro, u32 synchroMode,
+		u32 syncWord, u32 syncSize)
+{
+	dprintk("Configure DibStream Tx");
+
+	dib8000_write_word(state, 1615, 1);
+	dib8000_write_word(state, 1603, P_Kin);
+	dib8000_write_word(state, 1605, P_Kout);
+	dib8000_write_word(state, 1606, insertExtSynchro);
+	dib8000_write_word(state, 1608, synchroMode);
+	dib8000_write_word(state, 1609, (syncWord >> 16) & 0xffff);
+	dib8000_write_word(state, 1610, syncWord & 0xffff);
+	dib8000_write_word(state, 1612, syncSize);
+	dib8000_write_word(state, 1615, 0);
+}
+
+static void dib8096p_cfg_DibRx(struct dib8000_state *state, u32 P_Kin,
+		u32 P_Kout, u32 synchroMode, u32 insertExtSynchro,
+		u32 syncWord, u32 syncSize, u32 dataOutRate)
+{
+	u32 syncFreq;
+
+	dprintk("Configure DibStream Rx synchroMode = %d", synchroMode);
+
+	if ((P_Kin != 0) && (P_Kout != 0)) {
+		syncFreq = dib8096p_calcSyncFreq(P_Kin, P_Kout,
+				insertExtSynchro, syncSize);
+		dib8000_write_word(state, 1542, syncFreq);
+	}
+
+	dib8000_write_word(state, 1554, 1);
+	dib8000_write_word(state, 1536, P_Kin);
+	dib8000_write_word(state, 1537, P_Kout);
+	dib8000_write_word(state, 1539, synchroMode);
+	dib8000_write_word(state, 1540, (syncWord >> 16) & 0xffff);
+	dib8000_write_word(state, 1541, syncWord & 0xffff);
+	dib8000_write_word(state, 1543, syncSize);
+	dib8000_write_word(state, 1544, dataOutRate);
+	dib8000_write_word(state, 1554, 0);
+}
+
+static void dib8096p_enMpegMux(struct dib8000_state *state, int onoff)
+{
+	u16 reg_1287;
+
+	reg_1287 = dib8000_read_word(state, 1287);
+
+	switch (onoff) {
+	case 1:
+			reg_1287 &= ~(1 << 8);
+			break;
+	case 0:
+			reg_1287 |= (1 << 8);
+			break;
+	}
+
+	dib8000_write_word(state, 1287, reg_1287);
+}
+
+static void dib8096p_configMpegMux(struct dib8000_state *state,
+		u16 pulseWidth, u16 enSerialMode, u16 enSerialClkDiv2)
+{
+	u16 reg_1287;
+
+	dprintk("Enable Mpeg mux");
+
+	dib8096p_enMpegMux(state, 0);
+
+	/* If the input mode is MPEG do not divide the serial clock */
+	if ((enSerialMode == 1) && (state->input_mode_mpeg == 1))
+		enSerialClkDiv2 = 0;
+
+	reg_1287 = ((pulseWidth & 0x1f) << 3) |
+		((enSerialMode & 0x1) << 2) | (enSerialClkDiv2 & 0x1);
+	dib8000_write_word(state, 1287, reg_1287);
+
+	dib8096p_enMpegMux(state, 1);
+}
+
+static void dib8096p_setDibTxMux(struct dib8000_state *state, int mode)
+{
+	u16 reg_1288 = dib8000_read_word(state, 1288) & ~(0x7 << 7);
+
+	switch (mode) {
+	case MPEG_ON_DIBTX:
+			dprintk("SET MPEG ON DIBSTREAM TX");
+			dib8096p_cfg_DibTx(state, 8, 5, 0, 0, 0, 0);
+			reg_1288 |= (1 << 9); break;
+	case DIV_ON_DIBTX:
+			dprintk("SET DIV_OUT ON DIBSTREAM TX");
+			dib8096p_cfg_DibTx(state, 5, 5, 0, 0, 0, 0);
+			reg_1288 |= (1 << 8); break;
+	case ADC_ON_DIBTX:
+			dprintk("SET ADC_OUT ON DIBSTREAM TX");
+			dib8096p_cfg_DibTx(state, 20, 5, 10, 0, 0, 0);
+			reg_1288 |= (1 << 7); break;
+	default:
+			break;
+	}
+	dib8000_write_word(state, 1288, reg_1288);
+}
+
+static void dib8096p_setHostBusMux(struct dib8000_state *state, int mode)
+{
+	u16 reg_1288 = dib8000_read_word(state, 1288) & ~(0x7 << 4);
+
+	switch (mode) {
+	case DEMOUT_ON_HOSTBUS:
+			dprintk("SET DEM OUT OLD INTERF ON HOST BUS");
+			dib8096p_enMpegMux(state, 0);
+			reg_1288 |= (1 << 6);
+			break;
+	case DIBTX_ON_HOSTBUS:
+			dprintk("SET DIBSTREAM TX ON HOST BUS");
+			dib8096p_enMpegMux(state, 0);
+			reg_1288 |= (1 << 5);
+			break;
+	case MPEG_ON_HOSTBUS:
+			dprintk("SET MPEG MUX ON HOST BUS");
+			reg_1288 |= (1 << 4);
+			break;
+	default:
+			break;
+	}
+	dib8000_write_word(state, 1288, reg_1288);
+}
+
+static int dib8096p_set_diversity_in(struct dvb_frontend *fe, int onoff)
+{
+	struct dib8000_state *state = fe->demodulator_priv;
+	u16 reg_1287;
+
+	switch (onoff) {
+	case 0: /* only use the internal way - not the diversity input */
+			dprintk("%s mode OFF : by default Enable Mpeg INPUT",
+					__func__);
+			/* outputRate = 8 */
+			dib8096p_cfg_DibRx(state, 8, 5, 0, 0, 0, 8, 0);
+
+			/* Do not divide the serial clock of MPEG MUX in
+			   SERIAL MODE in case input mode MPEG is used */
+			reg_1287 = dib8000_read_word(state, 1287);
+			/* enSerialClkDiv2 == 1 ? */
+			if ((reg_1287 & 0x1) == 1) {
+				/* force enSerialClkDiv2 = 0 */
+				reg_1287 &= ~0x1;
+				dib8000_write_word(state, 1287, reg_1287);
+			}
+			state->input_mode_mpeg = 1;
+			break;
+	case 1: /* both ways */
+	case 2: /* only the diversity input */
+			dprintk("%s ON : Enable diversity INPUT", __func__);
+			dib8096p_cfg_DibRx(state, 5, 5, 0, 0, 0, 0, 0);
+			state->input_mode_mpeg = 0;
+			break;
+	}
+
+	dib8000_set_diversity_in(state->fe[0], onoff);
+	return 0;
+}
+
+static int dib8096p_set_output_mode(struct dvb_frontend *fe, int mode)
+{
+	struct dib8000_state *state = fe->demodulator_priv;
+	u16 outreg, smo_mode, fifo_threshold;
+	u8 prefer_mpeg_mux_use = 1;
+	int ret = 0;
+
+	dib8096p_host_bus_drive(state, 1);
+
+	fifo_threshold = 1792;
+	smo_mode = (dib8000_read_word(state, 299) & 0x0050) | (1 << 1);
+	outreg   = dib8000_read_word(state, 1286) &
+		~((1 << 10) | (0x7 << 6) | (1 << 1));
+
+	switch (mode) {
+	case OUTMODE_HIGH_Z:
+			outreg = 0;
+			break;
+
+	case OUTMODE_MPEG2_SERIAL:
+			if (prefer_mpeg_mux_use) {
+				dprintk("dib8096P setting output mode TS_SERIAL using Mpeg Mux");
+				dib8096p_configMpegMux(state, 3, 1, 1);
+				dib8096p_setHostBusMux(state, MPEG_ON_HOSTBUS);
+			} else {/* Use Smooth block */
+				dprintk("dib8096P setting output mode TS_SERIAL using Smooth bloc");
+				dib8096p_setHostBusMux(state,
+						DEMOUT_ON_HOSTBUS);
+				outreg |= (2 << 6) | (0 << 1);
+			}
+			break;
+
+	case OUTMODE_MPEG2_PAR_GATED_CLK:
+			if (prefer_mpeg_mux_use) {
+				dprintk("dib8096P setting output mode TS_PARALLEL_GATED using Mpeg Mux");
+				dib8096p_configMpegMux(state, 2, 0, 0);
+				dib8096p_setHostBusMux(state, MPEG_ON_HOSTBUS);
+			} else { /* Use Smooth block */
+				dprintk("dib8096P setting output mode TS_PARALLEL_GATED using Smooth block");
+				dib8096p_setHostBusMux(state,
+						DEMOUT_ON_HOSTBUS);
+				outreg |= (0 << 6);
+			}
+			break;
+
+	case OUTMODE_MPEG2_PAR_CONT_CLK: /* Using Smooth block only */
+			dprintk("dib8096P setting output mode TS_PARALLEL_CONT using Smooth block");
+			dib8096p_setHostBusMux(state, DEMOUT_ON_HOSTBUS);
+			outreg |= (1 << 6);
+			break;
+
+	case OUTMODE_MPEG2_FIFO:
+			/* Using Smooth block because not supported
+			   by new Mpeg Mux bloc */
+			dprintk("dib8096P setting output mode TS_FIFO using Smooth block");
+			dib8096p_setHostBusMux(state, DEMOUT_ON_HOSTBUS);
+			outreg |= (5 << 6);
+			smo_mode |= (3 << 1);
+			fifo_threshold = 512;
+			break;
+
+	case OUTMODE_DIVERSITY:
+			dprintk("dib8096P setting output mode MODE_DIVERSITY");
+			dib8096p_setDibTxMux(state, DIV_ON_DIBTX);
+			dib8096p_setHostBusMux(state, DIBTX_ON_HOSTBUS);
+			break;
+
+	case OUTMODE_ANALOG_ADC:
+			dprintk("dib8096P setting output mode MODE_ANALOG_ADC");
+			dib8096p_setDibTxMux(state, ADC_ON_DIBTX);
+			dib8096p_setHostBusMux(state, DIBTX_ON_HOSTBUS);
+			break;
+	}
+
+	if (mode != OUTMODE_HIGH_Z)
+		outreg |= (1<<10);
+
+	dprintk("output_mpeg2_in_188_bytes = %d",
+			state->cfg.output_mpeg2_in_188_bytes);
+	if (state->cfg.output_mpeg2_in_188_bytes)
+		smo_mode |= (1 << 5);
+
+	ret |= dib8000_write_word(state, 299, smo_mode);
+	/* synchronous fread */
+	ret |= dib8000_write_word(state, 299 + 1, fifo_threshold);
+	ret |= dib8000_write_word(state, 1286, outreg);
+
+	return ret;
+}
+
+static int map_addr_to_serpar_number(struct i2c_msg *msg)
+{
+	if (msg->buf[0] <= 15)
+		msg->buf[0] -= 1;
+	else if (msg->buf[0] == 17)
+		msg->buf[0] = 15;
+	else if (msg->buf[0] == 16)
+		msg->buf[0] = 17;
+	else if (msg->buf[0] == 19)
+		msg->buf[0] = 16;
+	else if (msg->buf[0] >= 21 && msg->buf[0] <= 25)
+		msg->buf[0] -= 3;
+	else if (msg->buf[0] == 28)
+		msg->buf[0] = 23;
+	else if (msg->buf[0] == 99)
+		msg->buf[0] = 99;
+	else
+		return -EINVAL;
+	return 0;
+}
+
+static int dib8096p_tuner_write_serpar(struct i2c_adapter *i2c_adap,
+		struct i2c_msg msg[], int num)
+{
+	struct dib8000_state *state = i2c_get_adapdata(i2c_adap);
+	u8 n_overflow = 1;
+	u16 i = 1000;
+	u16 serpar_num = msg[0].buf[0];
+
+	while (n_overflow == 1 && i) {
+		n_overflow = (dib8000_read_word(state, 1984) >> 1) & 0x1;
+		i--;
+		if (i == 0)
+			dprintk("Tuner ITF: write busy (overflow)");
+	}
+	dib8000_write_word(state, 1985, (1 << 6) | (serpar_num & 0x3f));
+	dib8000_write_word(state, 1986, (msg[0].buf[1] << 8) | msg[0].buf[2]);
+
+	return num;
+}
+
+static int dib8096p_tuner_read_serpar(struct i2c_adapter *i2c_adap,
+		struct i2c_msg msg[], int num)
+{
+	struct dib8000_state *state = i2c_get_adapdata(i2c_adap);
+	u8 n_overflow = 1, n_empty = 1;
+	u16 i = 1000;
+	u16 serpar_num = msg[0].buf[0];
+	u16 read_word;
+
+	while (n_overflow == 1 && i) {
+		n_overflow = (dib8000_read_word(state, 1984) >> 1) & 0x1;
+		i--;
+		if (i == 0)
+			dprintk("TunerITF: read busy (overflow)");
+	}
+	dib8000_write_word(state, 1985, (0<<6) | (serpar_num&0x3f));
+
+	i = 1000;
+	while (n_empty == 1 && i) {
+		n_empty = dib8000_read_word(state, 1984)&0x1;
+		i--;
+		if (i == 0)
+			dprintk("TunerITF: read busy (empty)");
+	}
+
+	read_word = dib8000_read_word(state, 1987);
+	msg[1].buf[0] = (read_word >> 8) & 0xff;
+	msg[1].buf[1] = (read_word) & 0xff;
+
+	return num;
+}
+
+static int dib8096p_tuner_rw_serpar(struct i2c_adapter *i2c_adap,
+		struct i2c_msg msg[], int num)
+{
+	if (map_addr_to_serpar_number(&msg[0]) == 0) {
+		if (num == 1) /* write */
+			return dib8096p_tuner_write_serpar(i2c_adap, msg, 1);
+		else /* read */
+			return dib8096p_tuner_read_serpar(i2c_adap, msg, 2);
+	}
+	return num;
+}
+
+static int dib8096p_rw_on_apb(struct i2c_adapter *i2c_adap,
+		struct i2c_msg msg[], int num, u16 apb_address)
+{
+	struct dib8000_state *state = i2c_get_adapdata(i2c_adap);
+	u16 word;
+
+	if (num == 1) {		/* write */
+		dib8000_write_word(state, apb_address,
+				((msg[0].buf[1] << 8) | (msg[0].buf[2])));
+	} else {
+		word = dib8000_read_word(state, apb_address);
+		msg[1].buf[0] = (word >> 8) & 0xff;
+		msg[1].buf[1] = (word) & 0xff;
+	}
+	return num;
+}
+
+static int dib8096p_tuner_xfer(struct i2c_adapter *i2c_adap,
+		struct i2c_msg msg[], int num)
+{
+	struct dib8000_state *state = i2c_get_adapdata(i2c_adap);
+	u16 apb_address = 0, word;
+	int i = 0;
+
+	switch (msg[0].buf[0]) {
+	case 0x12:
+			apb_address = 1920;
+			break;
+	case 0x14:
+			apb_address = 1921;
+			break;
+	case 0x24:
+			apb_address = 1922;
+			break;
+	case 0x1a:
+			apb_address = 1923;
+			break;
+	case 0x22:
+			apb_address = 1924;
+			break;
+	case 0x33:
+			apb_address = 1926;
+			break;
+	case 0x34:
+			apb_address = 1927;
+			break;
+	case 0x35:
+			apb_address = 1928;
+			break;
+	case 0x36:
+			apb_address = 1929;
+			break;
+	case 0x37:
+			apb_address = 1930;
+			break;
+	case 0x38:
+			apb_address = 1931;
+			break;
+	case 0x39:
+			apb_address = 1932;
+			break;
+	case 0x2a:
+			apb_address = 1935;
+			break;
+	case 0x2b:
+			apb_address = 1936;
+			break;
+	case 0x2c:
+			apb_address = 1937;
+			break;
+	case 0x2d:
+			apb_address = 1938;
+			break;
+	case 0x2e:
+			apb_address = 1939;
+			break;
+	case 0x2f:
+			apb_address = 1940;
+			break;
+	case 0x30:
+			apb_address = 1941;
+			break;
+	case 0x31:
+			apb_address = 1942;
+			break;
+	case 0x32:
+			apb_address = 1943;
+			break;
+	case 0x3e:
+			apb_address = 1944;
+			break;
+	case 0x3f:
+			apb_address = 1945;
+			break;
+	case 0x40:
+			apb_address = 1948;
+			break;
+	case 0x25:
+			apb_address = 936;
+			break;
+	case 0x26:
+			apb_address = 937;
+			break;
+	case 0x27:
+			apb_address = 938;
+			break;
+	case 0x28:
+			apb_address = 939;
+			break;
+	case 0x1d:
+			/* get sad sel request */
+			i = ((dib8000_read_word(state, 921) >> 12)&0x3);
+			word = dib8000_read_word(state, 924+i);
+			msg[1].buf[0] = (word >> 8) & 0xff;
+			msg[1].buf[1] = (word) & 0xff;
+			return num;
+	case 0x1f:
+			if (num == 1) {	/* write */
+				word = (u16) ((msg[0].buf[1] << 8) |
+						msg[0].buf[2]);
+				/* in the VGAMODE Sel are located on bit 0/1 */
+				word &= 0x3;
+				word = (dib8000_read_word(state, 921) &
+						~(3<<12)) | (word<<12);
+				/* Set the proper input */
+				dib8000_write_word(state, 921, word);
+				return num;
+			}
+	}
+
+	if (apb_address != 0) /* R/W acces via APB */
+		return dib8096p_rw_on_apb(i2c_adap, msg, num, apb_address);
+	else  /* R/W access via SERPAR  */
+		return dib8096p_tuner_rw_serpar(i2c_adap, msg, num);
+
+	return 0;
+}
+
+static u32 dib8096p_i2c_func(struct i2c_adapter *adapter)
+{
+	return I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm dib8096p_tuner_xfer_algo = {
+	.master_xfer = dib8096p_tuner_xfer,
+	.functionality = dib8096p_i2c_func,
+};
+
+struct i2c_adapter *dib8096p_get_i2c_tuner(struct dvb_frontend *fe)
+{
+	struct dib8000_state *st = fe->demodulator_priv;
+	return &st->dib8096p_tuner_adap;
+}
+EXPORT_SYMBOL(dib8096p_get_i2c_tuner);
+
+int dib8096p_tuner_sleep(struct dvb_frontend *fe, int onoff)
+{
+	struct dib8000_state *state = fe->demodulator_priv;
+	u16 en_cur_state;
+
+	dprintk("sleep dib8096p: %d", onoff);
+
+	en_cur_state = dib8000_read_word(state, 1922);
+
+	/* LNAs and MIX are ON and therefore it is a valid configuration */
+	if (en_cur_state > 0xff)
+		state->tuner_enable = en_cur_state ;
+
+	if (onoff)
+		en_cur_state &= 0x00ff;
+	else {
+		if (state->tuner_enable != 0)
+			en_cur_state = state->tuner_enable;
+	}
+
+	dib8000_write_word(state, 1922, en_cur_state);
+
+	return 0;
+}
+EXPORT_SYMBOL(dib8096p_tuner_sleep);
+
+static const s32 lut_1000ln_mant[] =
+{
+	908, 7003, 7090, 7170, 7244, 7313, 7377, 7438, 7495, 7549, 7600
+};
+
+s32 dib8000_get_adc_power(struct dvb_frontend *fe, u8 mode)
+{
+	struct dib8000_state *state = fe->demodulator_priv;
+	u32 ix = 0, tmp_val = 0, exp = 0, mant = 0;
+	s32 val;
+
+	val = dib8000_read32(state, 384);
+	if (mode) {
+		tmp_val = val;
+		while (tmp_val >>= 1)
+			exp++;
+		mant = (val * 1000 / (1<<exp));
+		ix = (u8)((mant-1000)/100); /* index of the LUT */
+		val = (lut_1000ln_mant[ix] + 693*(exp-20) - 6908);
+		val = (val*256)/1000;
+	}
+	return val;
+}
+EXPORT_SYMBOL(dib8000_get_adc_power);
+
+int dib8090p_get_dc_power(struct dvb_frontend *fe, u8 IQ)
+{
+	struct dib8000_state *state = fe->demodulator_priv;
+	int val = 0;
+
+	switch (IQ) {
+	case 1:
+			val = dib8000_read_word(state, 403);
+			break;
+	case 0:
+			val = dib8000_read_word(state, 404);
+			break;
+	}
+	if (val  & 0x200)
+		val -= 1024;
+
+	return val;
+}
+EXPORT_SYMBOL(dib8090p_get_dc_power);
+
+static void dib8000_update_timf(struct dib8000_state *state)
+{
+	u32 timf = state->timf = dib8000_read32(state, 435);
+
+	dib8000_write_word(state, 29, (u16) (timf >> 16));
+	dib8000_write_word(state, 30, (u16) (timf & 0xffff));
+	dprintk("Updated timing frequency: %d (default: %d)", state->timf, state->timf_default);
+}
+
+u32 dib8000_ctrl_timf(struct dvb_frontend *fe, uint8_t op, uint32_t timf)
+{
+	struct dib8000_state *state = fe->demodulator_priv;
+
+	switch (op) {
+	case DEMOD_TIMF_SET:
+			state->timf = timf;
+			break;
+	case DEMOD_TIMF_UPDATE:
+			dib8000_update_timf(state);
+			break;
+	case DEMOD_TIMF_GET:
+			break;
+	}
+	dib8000_set_bandwidth(state->fe[0], 6000);
+
+	return state->timf;
+}
+EXPORT_SYMBOL(dib8000_ctrl_timf);
+
+static const u16 adc_target_16dB[11] = {
+	(1 << 13) - 825 - 117,
+	(1 << 13) - 837 - 117,
+	(1 << 13) - 811 - 117,
+	(1 << 13) - 766 - 117,
+	(1 << 13) - 737 - 117,
+	(1 << 13) - 693 - 117,
+	(1 << 13) - 648 - 117,
+	(1 << 13) - 619 - 117,
+	(1 << 13) - 575 - 117,
+	(1 << 13) - 531 - 117,
+	(1 << 13) - 501 - 117
+};
+static const u8 permu_seg[] = { 6, 5, 7, 4, 8, 3, 9, 2, 10, 1, 11, 0, 12 };
+
+static void dib8000_set_channel(struct dib8000_state *state, u8 seq, u8 autosearching)
+{
+	u16 mode, max_constellation, seg_diff_mask = 0, nbseg_diff = 0;
+	u8 guard, crate, constellation, timeI;
+	u16 i, coeff[4], P_cfr_left_edge = 0, P_cfr_right_edge = 0, seg_mask13 = 0x1fff;	// All 13 segments enabled
+	const s16 *ncoeff = NULL, *ana_fe;
+	u16 tmcc_pow = 0;
+	u16 coff_pow = 0x2800;
+	u16 init_prbs = 0xfff;
+	u16 ana_gain = 0;
+
+	if (state->revision == 0x8090)
+		dib8000_init_sdram(state);
+
+	if (state->ber_monitored_layer != LAYER_ALL)
+		dib8000_write_word(state, 285, (dib8000_read_word(state, 285) & 0x60) | state->ber_monitored_layer);
+	else
+		dib8000_write_word(state, 285, dib8000_read_word(state, 285) & 0x60);
+
+	i = dib8000_read_word(state, 26) & 1;	// P_dds_invspec
+	dib8000_write_word(state, 26, state->fe[0]->dtv_property_cache.inversion^i);
+
+	if (state->fe[0]->dtv_property_cache.isdbt_sb_mode) {
+		//compute new dds_freq for the seg and adjust prbs
+		int seg_offset =
+			state->fe[0]->dtv_property_cache.isdbt_sb_segment_idx -
+			(state->fe[0]->dtv_property_cache.isdbt_sb_segment_count / 2) -
+			(state->fe[0]->dtv_property_cache.isdbt_sb_segment_count % 2);
+		int clk = state->cfg.pll->internal;
+		u32 segtodds = ((u32) (430 << 23) / clk) << 3;	// segtodds = SegBW / Fclk * pow(2,26)
+		int dds_offset = seg_offset * segtodds;
+		int new_dds, sub_channel;
+		if ((state->fe[0]->dtv_property_cache.isdbt_sb_segment_count % 2) == 0)
+			dds_offset -= (int)(segtodds / 2);
+
+		if (state->cfg.pll->ifreq == 0) {
+			if ((state->fe[0]->dtv_property_cache.inversion ^ i) == 0) {
+				dib8000_write_word(state, 26, dib8000_read_word(state, 26) | 1);
+				new_dds = dds_offset;
+			} else
+				new_dds = dds_offset;
+
+			// We shift tuning frequency if the wanted segment is :
+			//  - the segment of center frequency with an odd total number of segments
+			//  - the segment to the left of center frequency with an even total number of segments
+			//  - the segment to the right of center frequency with an even total number of segments
+			if ((state->fe[0]->dtv_property_cache.delivery_system == SYS_ISDBT)
+				&& (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1)
+					&& (((state->fe[0]->dtv_property_cache.isdbt_sb_segment_count % 2)
+					  && (state->fe[0]->dtv_property_cache.isdbt_sb_segment_idx ==
+				  ((state->fe[0]->dtv_property_cache.isdbt_sb_segment_count / 2) + 1)))
+					 || (((state->fe[0]->dtv_property_cache.isdbt_sb_segment_count % 2) == 0)
+						 && (state->fe[0]->dtv_property_cache.isdbt_sb_segment_idx == (state->fe[0]->dtv_property_cache.isdbt_sb_segment_count / 2)))
+					 || (((state->fe[0]->dtv_property_cache.isdbt_sb_segment_count % 2) == 0)
+						 && (state->fe[0]->dtv_property_cache.isdbt_sb_segment_idx ==
+							 ((state->fe[0]->dtv_property_cache.isdbt_sb_segment_count / 2) + 1)))
+					)) {
+				new_dds -= ((u32) (850 << 22) / clk) << 4;	// new_dds = 850 (freq shift in KHz) / Fclk * pow(2,26)
+			}
+		} else {
+			if ((state->fe[0]->dtv_property_cache.inversion ^ i) == 0)
+				new_dds = state->cfg.pll->ifreq - dds_offset;
+			else
+				new_dds = state->cfg.pll->ifreq + dds_offset;
+		}
+		dib8000_write_word(state, 27, (u16) ((new_dds >> 16) & 0x01ff));
+		dib8000_write_word(state, 28, (u16) (new_dds & 0xffff));
+		if (state->fe[0]->dtv_property_cache.isdbt_sb_segment_count % 2)
+			sub_channel = ((state->fe[0]->dtv_property_cache.isdbt_sb_subchannel + (3 * seg_offset) + 1) % 41) / 3;
+		else
+			sub_channel = ((state->fe[0]->dtv_property_cache.isdbt_sb_subchannel + (3 * seg_offset)) % 41) / 3;
+		sub_channel -= 6;
+
+		if (state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_2K
+				|| state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_4K) {
+			dib8000_write_word(state, 219, dib8000_read_word(state, 219) | 0x1);	//adp_pass =1
+			dib8000_write_word(state, 190, dib8000_read_word(state, 190) | (0x1 << 14));	//pha3_force_pha_shift = 1
+		} else {
+			dib8000_write_word(state, 219, dib8000_read_word(state, 219) & 0xfffe);	//adp_pass =0
+			dib8000_write_word(state, 190, dib8000_read_word(state, 190) & 0xbfff);	//pha3_force_pha_shift = 0
+		}
+
+		switch (state->fe[0]->dtv_property_cache.transmission_mode) {
+		case TRANSMISSION_MODE_2K:
+			switch (sub_channel) {
+			case -6:
+				init_prbs = 0x0;
+				break;	// 41, 0, 1
+			case -5:
+				init_prbs = 0x423;
+				break;	// 02~04
+			case -4:
+				init_prbs = 0x9;
+				break;	// 05~07
+			case -3:
+				init_prbs = 0x5C7;
+				break;	// 08~10
+			case -2:
+				init_prbs = 0x7A6;
+				break;	// 11~13
+			case -1:
+				init_prbs = 0x3D8;
+				break;	// 14~16
+			case 0:
+				init_prbs = 0x527;
+				break;	// 17~19
+			case 1:
+				init_prbs = 0x7FF;
+				break;	// 20~22
+			case 2:
+				init_prbs = 0x79B;
+				break;	// 23~25
+			case 3:
+				init_prbs = 0x3D6;
+				break;	// 26~28
+			case 4:
+				init_prbs = 0x3A2;
+				break;	// 29~31
+			case 5:
+				init_prbs = 0x53B;
+				break;	// 32~34
+			case 6:
+				init_prbs = 0x2F4;
+				break;	// 35~37
+			default:
+			case 7:
+				init_prbs = 0x213;
+				break;	// 38~40
+			}
+			break;
+
+		case TRANSMISSION_MODE_4K:
+			switch (sub_channel) {
+			case -6:
+				init_prbs = 0x0;
+				break;	// 41, 0, 1
+			case -5:
+				init_prbs = 0x208;
+				break;	// 02~04
+			case -4:
+				init_prbs = 0xC3;
+				break;	// 05~07
+			case -3:
+				init_prbs = 0x7B9;
+				break;	// 08~10
+			case -2:
+				init_prbs = 0x423;
+				break;	// 11~13
+			case -1:
+				init_prbs = 0x5C7;
+				break;	// 14~16
+			case 0:
+				init_prbs = 0x3D8;
+				break;	// 17~19
+			case 1:
+				init_prbs = 0x7FF;
+				break;	// 20~22
+			case 2:
+				init_prbs = 0x3D6;
+				break;	// 23~25
+			case 3:
+				init_prbs = 0x53B;
+				break;	// 26~28
+			case 4:
+				init_prbs = 0x213;
+				break;	// 29~31
+			case 5:
+				init_prbs = 0x29;
+				break;	// 32~34
+			case 6:
+				init_prbs = 0xD0;
+				break;	// 35~37
+			default:
+			case 7:
+				init_prbs = 0x48E;
+				break;	// 38~40
+			}
+			break;
+
+		default:
+		case TRANSMISSION_MODE_8K:
+			switch (sub_channel) {
+			case -6:
+				init_prbs = 0x0;
+				break;	// 41, 0, 1
+			case -5:
+				init_prbs = 0x740;
+				break;	// 02~04
+			case -4:
+				init_prbs = 0x069;
+				break;	// 05~07
+			case -3:
+				init_prbs = 0x7DD;
+				break;	// 08~10
+			case -2:
+				init_prbs = 0x208;
+				break;	// 11~13
+			case -1:
+				init_prbs = 0x7B9;
+				break;	// 14~16
+			case 0:
+				init_prbs = 0x5C7;
+				break;	// 17~19
+			case 1:
+				init_prbs = 0x7FF;
+				break;	// 20~22
+			case 2:
+				init_prbs = 0x53B;
+				break;	// 23~25
+			case 3:
+				init_prbs = 0x29;
+				break;	// 26~28
+			case 4:
+				init_prbs = 0x48E;
+				break;	// 29~31
+			case 5:
+				init_prbs = 0x4C4;
+				break;	// 32~34
+			case 6:
+				init_prbs = 0x367;
+				break;	// 33~37
+			default:
+			case 7:
+				init_prbs = 0x684;
+				break;	// 38~40
+			}
+			break;
+		}
+	} else {
+		dib8000_write_word(state, 27, (u16) ((state->cfg.pll->ifreq >> 16) & 0x01ff));
+		dib8000_write_word(state, 28, (u16) (state->cfg.pll->ifreq & 0xffff));
+		dib8000_write_word(state, 26, (u16) ((state->cfg.pll->ifreq >> 25) & 0x0003));
+	}
+	/*P_mode == ?? */
+	dib8000_write_word(state, 10, (seq << 4));
+	//  dib8000_write_word(state, 287, (dib8000_read_word(state, 287) & 0xe000) | 0x1000);
+
+	switch (state->fe[0]->dtv_property_cache.guard_interval) {
+	case GUARD_INTERVAL_1_32:
+		guard = 0;
+		break;
+	case GUARD_INTERVAL_1_16:
+		guard = 1;
+		break;
+	case GUARD_INTERVAL_1_8:
+		guard = 2;
+		break;
+	case GUARD_INTERVAL_1_4:
+	default:
+		guard = 3;
+		break;
+	}
+
+	dib8000_write_word(state, 1, (init_prbs << 2) | (guard & 0x3));	// ADDR 1
+
+	max_constellation = DQPSK;
+	for (i = 0; i < 3; i++) {
+		switch (state->fe[0]->dtv_property_cache.layer[i].modulation) {
+		case DQPSK:
+			constellation = 0;
+			break;
+		case QPSK:
+			constellation = 1;
+			break;
+		case QAM_16:
+			constellation = 2;
+			break;
+		case QAM_64:
+		default:
+			constellation = 3;
+			break;
+		}
+
+		switch (state->fe[0]->dtv_property_cache.layer[i].fec) {
+		case FEC_1_2:
+			crate = 1;
+			break;
+		case FEC_2_3:
+			crate = 2;
+			break;
+		case FEC_3_4:
+			crate = 3;
+			break;
+		case FEC_5_6:
+			crate = 5;
+			break;
+		case FEC_7_8:
+		default:
+			crate = 7;
+			break;
+		}
+
+		if ((state->fe[0]->dtv_property_cache.layer[i].interleaving > 0) &&
+				((state->fe[0]->dtv_property_cache.layer[i].interleaving <= 3) ||
+				 (state->fe[0]->dtv_property_cache.layer[i].interleaving == 4 && state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1))
+			)
+			timeI = state->fe[0]->dtv_property_cache.layer[i].interleaving;
+		else
+			timeI = 0;
+		dib8000_write_word(state, 2 + i, (constellation << 10) | ((state->fe[0]->dtv_property_cache.layer[i].segment_count & 0xf) << 6) |
+					(crate << 3) | timeI);
+		if (state->fe[0]->dtv_property_cache.layer[i].segment_count > 0) {
+			switch (max_constellation) {
+			case DQPSK:
+			case QPSK:
+				if (state->fe[0]->dtv_property_cache.layer[i].modulation == QAM_16 ||
+					state->fe[0]->dtv_property_cache.layer[i].modulation == QAM_64)
+					max_constellation = state->fe[0]->dtv_property_cache.layer[i].modulation;
+				break;
+			case QAM_16:
+				if (state->fe[0]->dtv_property_cache.layer[i].modulation == QAM_64)
+					max_constellation = state->fe[0]->dtv_property_cache.layer[i].modulation;
+				break;
+			}
+		}
+	}
+
+	mode = fft_to_mode(state);
+
+	//dib8000_write_word(state, 5, 13); /*p_last_seg = 13*/
+
+	dib8000_write_word(state, 274, (dib8000_read_word(state, 274) & 0xffcf) |
+				((state->fe[0]->dtv_property_cache.isdbt_partial_reception & 1) << 5) | ((state->fe[0]->dtv_property_cache.
+												 isdbt_sb_mode & 1) << 4));
+
+	dprintk("mode = %d ; guard = %d", mode, state->fe[0]->dtv_property_cache.guard_interval);
+
+	/* signal optimization parameter */
+
+	if (state->fe[0]->dtv_property_cache.isdbt_partial_reception) {
+		seg_diff_mask = (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK) << permu_seg[0];
+		for (i = 1; i < 3; i++)
+			nbseg_diff +=
+				(state->fe[0]->dtv_property_cache.layer[i].modulation == DQPSK) * state->fe[0]->dtv_property_cache.layer[i].segment_count;
+		for (i = 0; i < nbseg_diff; i++)
+			seg_diff_mask |= 1 << permu_seg[i + 1];
+	} else {
+		for (i = 0; i < 3; i++)
+			nbseg_diff +=
+				(state->fe[0]->dtv_property_cache.layer[i].modulation == DQPSK) * state->fe[0]->dtv_property_cache.layer[i].segment_count;
+		for (i = 0; i < nbseg_diff; i++)
+			seg_diff_mask |= 1 << permu_seg[i];
+	}
+	dprintk("nbseg_diff = %X (%d)", seg_diff_mask, seg_diff_mask);
+
+	state->differential_constellation = (seg_diff_mask != 0);
+	if (state->revision != 0x8090)
+		dib8000_set_diversity_in(state->fe[0], state->diversity_onoff);
+	else
+		dib8096p_set_diversity_in(state->fe[0], state->diversity_onoff);
+
+	if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) {
+		if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 1)
+			seg_mask13 = 0x00E0;
+		else		// 1-segment
+			seg_mask13 = 0x0040;
+	} else
+		seg_mask13 = 0x1fff;
+
+	// WRITE: Mode & Diff mask
+	dib8000_write_word(state, 0, (mode << 13) | seg_diff_mask);
+
+	if ((seg_diff_mask) || (state->fe[0]->dtv_property_cache.isdbt_sb_mode))
+		dib8000_write_word(state, 268, (dib8000_read_word(state, 268) & 0xF9FF) | 0x0200);
+	else
+		dib8000_write_word(state, 268, (2 << 9) | 39);	//init value
+
+	// ---- SMALL ----
+	// P_small_seg_diff
+	dib8000_write_word(state, 352, seg_diff_mask);	// ADDR 352
+
+	dib8000_write_word(state, 353, seg_mask13);	// ADDR 353
+
+/*	// P_small_narrow_band=0, P_small_last_seg=13, P_small_offset_num_car=5 */
+
+	// ---- SMALL ----
+	if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) {
+		switch (state->fe[0]->dtv_property_cache.transmission_mode) {
+		case TRANSMISSION_MODE_2K:
+			if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) {
+				if (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK)
+					ncoeff = coeff_2k_sb_1seg_dqpsk;
+				else	// QPSK or QAM
+					ncoeff = coeff_2k_sb_1seg;
+			} else {	// 3-segments
+				if (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK) {
+					if (state->fe[0]->dtv_property_cache.layer[1].modulation == DQPSK)
+						ncoeff = coeff_2k_sb_3seg_0dqpsk_1dqpsk;
+					else	// QPSK or QAM on external segments
+						ncoeff = coeff_2k_sb_3seg_0dqpsk;
+				} else {	// QPSK or QAM on central segment
+					if (state->fe[0]->dtv_property_cache.layer[1].modulation == DQPSK)
+						ncoeff = coeff_2k_sb_3seg_1dqpsk;
+					else	// QPSK or QAM on external segments
+						ncoeff = coeff_2k_sb_3seg;
+				}
+			}
+			break;
+
+		case TRANSMISSION_MODE_4K:
+			if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) {
+				if (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK)
+					ncoeff = coeff_4k_sb_1seg_dqpsk;
+				else	// QPSK or QAM
+					ncoeff = coeff_4k_sb_1seg;
+			} else {	// 3-segments
+				if (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK) {
+					if (state->fe[0]->dtv_property_cache.layer[1].modulation == DQPSK) {
+						ncoeff = coeff_4k_sb_3seg_0dqpsk_1dqpsk;
+					} else {	// QPSK or QAM on external segments
+						ncoeff = coeff_4k_sb_3seg_0dqpsk;
+					}
+				} else {	// QPSK or QAM on central segment
+					if (state->fe[0]->dtv_property_cache.layer[1].modulation == DQPSK) {
+						ncoeff = coeff_4k_sb_3seg_1dqpsk;
+					} else	// QPSK or QAM on external segments
+						ncoeff = coeff_4k_sb_3seg;
+				}
+			}
+			break;
+
+		case TRANSMISSION_MODE_AUTO:
+		case TRANSMISSION_MODE_8K:
+		default:
+			if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) {
+				if (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK)
+					ncoeff = coeff_8k_sb_1seg_dqpsk;
+				else	// QPSK or QAM
+					ncoeff = coeff_8k_sb_1seg;
+			} else {	// 3-segments
+				if (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK) {
+					if (state->fe[0]->dtv_property_cache.layer[1].modulation == DQPSK) {
+						ncoeff = coeff_8k_sb_3seg_0dqpsk_1dqpsk;
+					} else {	// QPSK or QAM on external segments
+						ncoeff = coeff_8k_sb_3seg_0dqpsk;
+					}
+				} else {	// QPSK or QAM on central segment
+					if (state->fe[0]->dtv_property_cache.layer[1].modulation == DQPSK) {
+						ncoeff = coeff_8k_sb_3seg_1dqpsk;
+					} else	// QPSK or QAM on external segments
+						ncoeff = coeff_8k_sb_3seg;
+				}
+			}
+			break;
+		}
+		for (i = 0; i < 8; i++)
+			dib8000_write_word(state, 343 + i, ncoeff[i]);
+	}
+
+	// P_small_coef_ext_enable=ISDB-Tsb, P_small_narrow_band=ISDB-Tsb, P_small_last_seg=13, P_small_offset_num_car=5
+	dib8000_write_word(state, 351,
+				(state->fe[0]->dtv_property_cache.isdbt_sb_mode << 9) | (state->fe[0]->dtv_property_cache.isdbt_sb_mode << 8) | (13 << 4) | 5);
+
+	// ---- COFF ----
+	// Carloff, the most robust
+	if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) {
+
+		// P_coff_cpil_alpha=4, P_coff_inh=0, P_coff_cpil_winlen=64
+		// P_coff_narrow_band=1, P_coff_square_val=1, P_coff_one_seg=~partial_rcpt, P_coff_use_tmcc=1, P_coff_use_ac=1
+		dib8000_write_word(state, 187,
+					(4 << 12) | (0 << 11) | (63 << 5) | (0x3 << 3) | ((~state->fe[0]->dtv_property_cache.isdbt_partial_reception & 1) << 2)
+					| 0x3);
+
+/*		// P_small_coef_ext_enable = 1 */
+/*		dib8000_write_word(state, 351, dib8000_read_word(state, 351) | 0x200); */
+
+		if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) {
+
+			// P_coff_winlen=63, P_coff_thres_lock=15, P_coff_one_seg_width= (P_mode == 3) , P_coff_one_seg_sym= (P_mode-1)
+			if (mode == 3)
+				dib8000_write_word(state, 180, 0x1fcf | ((mode - 1) << 14));
+			else
+				dib8000_write_word(state, 180, 0x0fcf | ((mode - 1) << 14));
+			// P_ctrl_corm_thres4pre_freq_inh=1,P_ctrl_pre_freq_mode_sat=1,
+			// P_ctrl_pre_freq_inh=0, P_ctrl_pre_freq_step = 5, P_pre_freq_win_len=4
+			dib8000_write_word(state, 338, (1 << 12) | (1 << 10) | (0 << 9) | (5 << 5) | 4);
+			// P_ctrl_pre_freq_win_len=16, P_ctrl_pre_freq_thres_lockin=8
+			dib8000_write_word(state, 340, (16 << 6) | (8 << 0));
+			// P_ctrl_pre_freq_thres_lockout=6, P_small_use_tmcc/ac/cp=1
+			dib8000_write_word(state, 341, (6 << 3) | (1 << 2) | (1 << 1) | (1 << 0));
+
+			// P_coff_corthres_8k, 4k, 2k and P_coff_cpilthres_8k, 4k, 2k
+			dib8000_write_word(state, 181, 300);
+			dib8000_write_word(state, 182, 150);
+			dib8000_write_word(state, 183, 80);
+			dib8000_write_word(state, 184, 300);
+			dib8000_write_word(state, 185, 150);
+			dib8000_write_word(state, 186, 80);
+		} else {	// Sound Broadcasting mode 3 seg
+			// P_coff_one_seg_sym= 1, P_coff_one_seg_width= 1, P_coff_winlen=63, P_coff_thres_lock=15
+			/*	if (mode == 3) */
+			/*		dib8000_write_word(state, 180, 0x2fca | ((0) << 14)); */
+			/*	else */
+			/*		dib8000_write_word(state, 180, 0x2fca | ((1) << 14)); */
+			dib8000_write_word(state, 180, 0x1fcf | (1 << 14));
+
+			// P_ctrl_corm_thres4pre_freq_inh = 1, P_ctrl_pre_freq_mode_sat=1,
+			// P_ctrl_pre_freq_inh=0, P_ctrl_pre_freq_step = 4, P_pre_freq_win_len=4
+			dib8000_write_word(state, 338, (1 << 12) | (1 << 10) | (0 << 9) | (4 << 5) | 4);
+			// P_ctrl_pre_freq_win_len=16, P_ctrl_pre_freq_thres_lockin=8
+			dib8000_write_word(state, 340, (16 << 6) | (8 << 0));
+			//P_ctrl_pre_freq_thres_lockout=6, P_small_use_tmcc/ac/cp=1
+			dib8000_write_word(state, 341, (6 << 3) | (1 << 2) | (1 << 1) | (1 << 0));
+
+			// P_coff_corthres_8k, 4k, 2k and P_coff_cpilthres_8k, 4k, 2k
+			dib8000_write_word(state, 181, 350);
+			dib8000_write_word(state, 182, 300);
+			dib8000_write_word(state, 183, 250);
+			dib8000_write_word(state, 184, 350);
+			dib8000_write_word(state, 185, 300);
+			dib8000_write_word(state, 186, 250);
+		}
+
+	} else if (state->isdbt_cfg_loaded == 0) {	// if not Sound Broadcasting mode : put default values for 13 segments
+		dib8000_write_word(state, 180, (16 << 6) | 9);
+		dib8000_write_word(state, 187, (4 << 12) | (8 << 5) | 0x2);
+		coff_pow = 0x2800;
+		for (i = 0; i < 6; i++)
+			dib8000_write_word(state, 181 + i, coff_pow);
+
+		// P_ctrl_corm_thres4pre_freq_inh=1, P_ctrl_pre_freq_mode_sat=1,
+		// P_ctrl_pre_freq_mode_sat=1, P_ctrl_pre_freq_inh=0, P_ctrl_pre_freq_step = 3, P_pre_freq_win_len=1
+		dib8000_write_word(state, 338, (1 << 12) | (1 << 10) | (0 << 9) | (3 << 5) | 1);
+
+		// P_ctrl_pre_freq_win_len=8, P_ctrl_pre_freq_thres_lockin=6
+		dib8000_write_word(state, 340, (8 << 6) | (6 << 0));
+		// P_ctrl_pre_freq_thres_lockout=4, P_small_use_tmcc/ac/cp=1
+		dib8000_write_word(state, 341, (4 << 3) | (1 << 2) | (1 << 1) | (1 << 0));
+	}
+	// ---- FFT ----
+	if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1 && state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0)
+		dib8000_write_word(state, 178, 64);	// P_fft_powrange=64
+	else
+		dib8000_write_word(state, 178, 32);	// P_fft_powrange=32
+
+	/* make the cpil_coff_lock more robust but slower p_coff_winlen
+	 * 6bits; p_coff_thres_lock 6bits (for coff lock if needed)
+	 */
+	/* if ( ( nbseg_diff>0)&&(nbseg_diff<13))
+		dib8000_write_word(state, 187, (dib8000_read_word(state, 187) & 0xfffb) | (1 << 3)); */
+
+	dib8000_write_word(state, 189, ~seg_mask13 | seg_diff_mask);	/* P_lmod4_seg_inh       */
+	dib8000_write_word(state, 192, ~seg_mask13 | seg_diff_mask);	/* P_pha3_seg_inh        */
+	dib8000_write_word(state, 225, ~seg_mask13 | seg_diff_mask);	/* P_tac_seg_inh         */
+	if ((!state->fe[0]->dtv_property_cache.isdbt_sb_mode) && (state->cfg.pll->ifreq == 0))
+		dib8000_write_word(state, 266, ~seg_mask13 | seg_diff_mask | 0x40);	/* P_equal_noise_seg_inh */
+	else
+		dib8000_write_word(state, 266, ~seg_mask13 | seg_diff_mask);	/* P_equal_noise_seg_inh */
+	dib8000_write_word(state, 287, ~seg_mask13 | 0x1000);	/* P_tmcc_seg_inh        */
+	//dib8000_write_word(state, 288, ~seg_mask13 | seg_diff_mask); /* P_tmcc_seg_eq_inh */
+	if (!autosearching)
+		dib8000_write_word(state, 288, (~seg_mask13 | seg_diff_mask) & 0x1fff);	/* P_tmcc_seg_eq_inh */
+	else
+		dib8000_write_word(state, 288, 0x1fff);	//disable equalisation of the tmcc when autosearch to be able to find the DQPSK channels.
+	dprintk("287 = %X (%d)", ~seg_mask13 | 0x1000, ~seg_mask13 | 0x1000);
+
+	dib8000_write_word(state, 211, seg_mask13 & (~seg_diff_mask));	/* P_des_seg_enabled     */
+
+	/* offset loop parameters */
+	if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) {
+		if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0)
+			/* P_timf_alpha = (11-P_mode), P_corm_alpha=6, P_corm_thres=0x80 */
+			dib8000_write_word(state, 32, ((11 - mode) << 12) | (6 << 8) | 0x40);
+
+		else		// Sound Broadcasting mode 3 seg
+			/* P_timf_alpha = (10-P_mode), P_corm_alpha=6, P_corm_thres=0x80 */
+			dib8000_write_word(state, 32, ((10 - mode) << 12) | (6 << 8) | 0x60);
+	} else
+		// TODO in 13 seg, timf_alpha can always be the same or not ?
+		/* P_timf_alpha = (9-P_mode, P_corm_alpha=6, P_corm_thres=0x80 */
+		dib8000_write_word(state, 32, ((9 - mode) << 12) | (6 << 8) | 0x80);
+
+	if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) {
+		if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0)
+			/* P_ctrl_pha_off_max=3   P_ctrl_sfreq_inh =0  P_ctrl_sfreq_step = (11-P_mode)  */
+			dib8000_write_word(state, 37, (3 << 5) | (0 << 4) | (10 - mode));
+
+		else		// Sound Broadcasting mode 3 seg
+			/* P_ctrl_pha_off_max=3   P_ctrl_sfreq_inh =0  P_ctrl_sfreq_step = (10-P_mode)  */
+			dib8000_write_word(state, 37, (3 << 5) | (0 << 4) | (9 - mode));
+	} else
+		/* P_ctrl_pha_off_max=3   P_ctrl_sfreq_inh =0  P_ctrl_sfreq_step = 9  */
+		dib8000_write_word(state, 37, (3 << 5) | (0 << 4) | (8 - mode));
+
+	/* P_dvsy_sync_wait - reuse mode */
+	switch (state->fe[0]->dtv_property_cache.transmission_mode) {
+	case TRANSMISSION_MODE_8K:
+		mode = 256;
+		break;
+	case TRANSMISSION_MODE_4K:
+		mode = 128;
+		break;
+	default:
+	case TRANSMISSION_MODE_2K:
+		mode = 64;
+		break;
+	}
+	if (state->cfg.diversity_delay == 0)
+		mode = (mode * (1 << (guard)) * 3) / 2 + 48;	// add 50% SFN margin + compensate for one DVSY-fifo
+	else
+		mode = (mode * (1 << (guard)) * 3) / 2 + state->cfg.diversity_delay;	// add 50% SFN margin + compensate for DVSY-fifo
+	mode <<= 4;
+	dib8000_write_word(state, 273, (dib8000_read_word(state, 273) & 0x000f) | mode);
+
+	/* channel estimation fine configuration */
+	switch (max_constellation) {
+	case QAM_64:
+		ana_gain = 0x7;	// -1 : avoid def_est saturation when ADC target is -16dB
+		coeff[0] = 0x0148;	/* P_adp_regul_cnt 0.04 */
+		coeff[1] = 0xfff0;	/* P_adp_noise_cnt -0.002 */
+		coeff[2] = 0x00a4;	/* P_adp_regul_ext 0.02 */
+		coeff[3] = 0xfff8;	/* P_adp_noise_ext -0.001 */
+		//if (!state->cfg.hostbus_diversity) //if diversity, we should prehaps use the configuration of the max_constallation -1
+		break;
+	case QAM_16:
+		ana_gain = 0x7;	// -1 : avoid def_est saturation when ADC target is -16dB
+		coeff[0] = 0x023d;	/* P_adp_regul_cnt 0.07 */
+		coeff[1] = 0xffdf;	/* P_adp_noise_cnt -0.004 */
+		coeff[2] = 0x00a4;	/* P_adp_regul_ext 0.02 */
+		coeff[3] = 0xfff0;	/* P_adp_noise_ext -0.002 */
+		//if (!((state->cfg.hostbus_diversity) && (max_constellation == QAM_16)))
+		break;
+	default:
+		ana_gain = 0;	// 0 : goes along with ADC target at -22dB to keep good mobile performance and lock at sensitivity level
+		coeff[0] = 0x099a;	/* P_adp_regul_cnt 0.3 */
+		coeff[1] = 0xffae;	/* P_adp_noise_cnt -0.01 */
+		coeff[2] = 0x0333;	/* P_adp_regul_ext 0.1 */
+		coeff[3] = 0xfff8;	/* P_adp_noise_ext -0.002 */
+		break;
+	}
+	for (mode = 0; mode < 4; mode++)
+		dib8000_write_word(state, 215 + mode, coeff[mode]);
+
+	// update ana_gain depending on max constellation
+	dib8000_write_word(state, 116, ana_gain);
+	// update ADC target depending on ana_gain
+	if (ana_gain) {		// set -16dB ADC target for ana_gain=-1
+		for (i = 0; i < 10; i++)
+			dib8000_write_word(state, 80 + i, adc_target_16dB[i]);
+	} else {		// set -22dB ADC target for ana_gain=0
+		for (i = 0; i < 10; i++)
+			dib8000_write_word(state, 80 + i, adc_target_16dB[i] - 355);
+	}
+
+	// ---- ANA_FE ----
+	if (state->fe[0]->dtv_property_cache.isdbt_sb_mode) {
+		if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 1)
+			ana_fe = ana_fe_coeff_3seg;
+		else		// 1-segment
+			ana_fe = ana_fe_coeff_1seg;
+	} else
+		ana_fe = ana_fe_coeff_13seg;
+
+	if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1 || state->isdbt_cfg_loaded == 0)
+		for (mode = 0; mode < 24; mode++)
+			dib8000_write_word(state, 117 + mode, ana_fe[mode]);
+
+	// ---- CHAN_BLK ----
+	for (i = 0; i < 13; i++) {
+		if ((((~seg_diff_mask) >> i) & 1) == 1) {
+			P_cfr_left_edge += (1 << i) * ((i == 0) || ((((seg_mask13 & (~seg_diff_mask)) >> (i - 1)) & 1) == 0));
+			P_cfr_right_edge += (1 << i) * ((i == 12) || ((((seg_mask13 & (~seg_diff_mask)) >> (i + 1)) & 1) == 0));
+		}
+	}
+	dib8000_write_word(state, 222, P_cfr_left_edge);	// P_cfr_left_edge
+	dib8000_write_word(state, 223, P_cfr_right_edge);	// P_cfr_right_edge
+	// "P_cspu_left_edge"  not used => do not care
+	// "P_cspu_right_edge" not used => do not care
+
+	if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) {
+		dib8000_write_word(state, 228, 1);	// P_2d_mode_byp=1
+		dib8000_write_word(state, 205, dib8000_read_word(state, 205) & 0xfff0);	// P_cspu_win_cut = 0
+		if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0
+			&& state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_2K) {
+			//dib8000_write_word(state, 219, dib8000_read_word(state, 219) & 0xfffe); // P_adp_pass = 0
+			dib8000_write_word(state, 265, 15);	// P_equal_noise_sel = 15
+		}
+	} else if (state->isdbt_cfg_loaded == 0) {
+		dib8000_write_word(state, 228, 0);	// default value
+		dib8000_write_word(state, 265, 31);	// default value
+		dib8000_write_word(state, 205, 0x200f);	// init value
+	}
+	// ---- TMCC ----
+	for (i = 0; i < 3; i++)
+		tmcc_pow +=
+			(((state->fe[0]->dtv_property_cache.layer[i].modulation == DQPSK) * 4 + 1) * state->fe[0]->dtv_property_cache.layer[i].segment_count);
+	// Quantif of "P_tmcc_dec_thres_?k" is (0, 5+mode, 9);
+	// Threshold is set at 1/4 of max power.
+	tmcc_pow *= (1 << (9 - 2));
+
+	dib8000_write_word(state, 290, tmcc_pow);	// P_tmcc_dec_thres_2k
+	dib8000_write_word(state, 291, tmcc_pow);	// P_tmcc_dec_thres_4k
+	dib8000_write_word(state, 292, tmcc_pow);	// P_tmcc_dec_thres_8k
+	//dib8000_write_word(state, 287, (1 << 13) | 0x1000 );
+	// ---- PHA3 ----
+
+	if (state->isdbt_cfg_loaded == 0)
+		dib8000_write_word(state, 250, 3285);	/*p_2d_hspeed_thr0 */
+
+	if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1)
+		state->isdbt_cfg_loaded = 0;
+	else
+		state->isdbt_cfg_loaded = 1;
+
+}
+
+static int dib8000_autosearch_start(struct dvb_frontend *fe)
+{
+	u8 factor;
+	u32 value;
+	struct dib8000_state *state = fe->demodulator_priv;
+
+	int slist = 0;
+
+	state->fe[0]->dtv_property_cache.inversion = 0;
+	if (!state->fe[0]->dtv_property_cache.isdbt_sb_mode)
+		state->fe[0]->dtv_property_cache.layer[0].segment_count = 13;
+	state->fe[0]->dtv_property_cache.layer[0].modulation = QAM_64;
+	state->fe[0]->dtv_property_cache.layer[0].fec = FEC_2_3;
+	state->fe[0]->dtv_property_cache.layer[0].interleaving = 0;
+
+	//choose the right list, in sb, always do everything
+	if (state->fe[0]->dtv_property_cache.isdbt_sb_mode) {
+		state->fe[0]->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_8K;
+		state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_8;
+		slist = 7;
+		dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x9fff) | (1 << 13));
+	} else {
+		if (state->fe[0]->dtv_property_cache.guard_interval == GUARD_INTERVAL_AUTO) {
+			if (state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_AUTO) {
+				slist = 7;
+				dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x9fff) | (1 << 13));	// P_mode = 1 to have autosearch start ok with mode2
+			} else
+				slist = 3;
+		} else {
+			if (state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_AUTO) {
+				slist = 2;
+				dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x9fff) | (1 << 13));	// P_mode = 1
+			} else
+				slist = 0;
+		}
+
+		if (state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_AUTO)
+			state->fe[0]->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_8K;
+		if (state->fe[0]->dtv_property_cache.guard_interval == GUARD_INTERVAL_AUTO)
+			state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_8;
+
+		dprintk("using list for autosearch : %d", slist);
+		dib8000_set_channel(state, (unsigned char)slist, 1);
+		//dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x9fff) | (1 << 13));  // P_mode = 1
+
+		factor = 1;
+
+		//set lock_mask values
+		dib8000_write_word(state, 6, 0x4);
+		dib8000_write_word(state, 7, 0x8);
+		dib8000_write_word(state, 8, 0x1000);
+
+		//set lock_mask wait time values
+		value = 50 * state->cfg.pll->internal * factor;
+		dib8000_write_word(state, 11, (u16) ((value >> 16) & 0xffff));	// lock0 wait time
+		dib8000_write_word(state, 12, (u16) (value & 0xffff));	// lock0 wait time
+		value = 100 * state->cfg.pll->internal * factor;
+		dib8000_write_word(state, 13, (u16) ((value >> 16) & 0xffff));	// lock1 wait time
+		dib8000_write_word(state, 14, (u16) (value & 0xffff));	// lock1 wait time
+		value = 1000 * state->cfg.pll->internal * factor;
+		dib8000_write_word(state, 15, (u16) ((value >> 16) & 0xffff));	// lock2 wait time
+		dib8000_write_word(state, 16, (u16) (value & 0xffff));	// lock2 wait time
+
+		value = dib8000_read_word(state, 0);
+		dib8000_write_word(state, 0, (u16) ((1 << 15) | value));
+		dib8000_read_word(state, 1284);	// reset the INT. n_irq_pending
+		dib8000_write_word(state, 0, (u16) value);
+
+	}
+
+	return 0;
+}
+
+static int dib8000_autosearch_irq(struct dvb_frontend *fe)
+{
+	struct dib8000_state *state = fe->demodulator_priv;
+	u16 irq_pending = dib8000_read_word(state, 1284);
+
+	if (irq_pending & 0x1) {	// failed
+		dprintk("dib8000_autosearch_irq failed");
+		return 1;
+	}
+
+	if (irq_pending & 0x2) {	// succeeded
+		dprintk("dib8000_autosearch_irq succeeded");
+		return 2;
+	}
+
+	return 0;		// still pending
+}
+
+static int dib8000_tune(struct dvb_frontend *fe)
+{
+	struct dib8000_state *state = fe->demodulator_priv;
+	int ret = 0;
+	u16 lock, value, mode;
+
+	// we are already tuned - just resuming from suspend
+	if (state == NULL)
+		return -EINVAL;
+
+	mode = fft_to_mode(state);
+
+	dib8000_set_bandwidth(fe, state->fe[0]->dtv_property_cache.bandwidth_hz / 1000);
+	dib8000_set_channel(state, 0, 0);
+
+	// restart demod
+	ret |= dib8000_write_word(state, 770, 0x4000);
+	ret |= dib8000_write_word(state, 770, 0x0000);
+	msleep(45);
+
+	/* P_ctrl_inh_cor=0, P_ctrl_alpha_cor=4, P_ctrl_inh_isi=0, P_ctrl_alpha_isi=3 */
+	/*  ret |= dib8000_write_word(state, 29, (0 << 9) | (4 << 5) | (0 << 4) | (3 << 0) );  workaround inh_isi stays at 1 */
+
+	// never achieved a lock before - wait for timfreq to update
+	if (state->timf == 0) {
+		if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) {
+			if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0)
+				msleep(300);
+			else	// Sound Broadcasting mode 3 seg
+				msleep(500);
+		} else		// 13 seg
+			msleep(200);
+	}
+	if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) {
+		if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) {
+
+			/* P_timf_alpha = (13-P_mode) , P_corm_alpha=6, P_corm_thres=0x40  alpha to check on board */
+			dib8000_write_word(state, 32, ((13 - mode) << 12) | (6 << 8) | 0x40);
+			//dib8000_write_word(state, 32, (8 << 12) | (6 << 8) | 0x80);
+
+			/*  P_ctrl_sfreq_step= (12-P_mode)   P_ctrl_sfreq_inh =0     P_ctrl_pha_off_max  */
+			ret |= dib8000_write_word(state, 37, (12 - mode) | ((5 + mode) << 5));
+
+		} else {	// Sound Broadcasting mode 3 seg
+
+			/* P_timf_alpha = (12-P_mode) , P_corm_alpha=6, P_corm_thres=0x60  alpha to check on board */
+			dib8000_write_word(state, 32, ((12 - mode) << 12) | (6 << 8) | 0x60);
+
+			ret |= dib8000_write_word(state, 37, (11 - mode) | ((5 + mode) << 5));
+		}
+
+	} else {		// 13 seg
+		/* P_timf_alpha = 8 , P_corm_alpha=6, P_corm_thres=0x80  alpha to check on board */
+		dib8000_write_word(state, 32, ((11 - mode) << 12) | (6 << 8) | 0x80);
+
+		ret |= dib8000_write_word(state, 37, (10 - mode) | ((5 + mode) << 5));
+
+	}
+
+	// we achieved a coff_cpil_lock - it's time to update the timf
+	if (state->revision != 0x8090)
+		lock = dib8000_read_word(state, 568);
+	else
+		lock = dib8000_read_word(state, 570);
+	if ((lock >> 11) & 0x1)
+		dib8000_update_timf(state);
+
+	//now that tune is finished, lock0 should lock on fec_mpeg to output this lock on MP_LOCK. It's changed in autosearch start
+	dib8000_write_word(state, 6, 0x200);
+
+	if (state->revision == 0x8002) {
+		value = dib8000_read_word(state, 903);
+		dib8000_write_word(state, 903, value & ~(1 << 3));
+		msleep(1);
+		dib8000_write_word(state, 903, value | (1 << 3));
+	}
+
+	return ret;
+}
+
+static int dib8000_wakeup(struct dvb_frontend *fe)
+{
+	struct dib8000_state *state = fe->demodulator_priv;
+	u8 index_frontend;
+	int ret;
+
+	dib8000_set_power_mode(state, DIB8000_POWER_ALL);
+	dib8000_set_adc_state(state, DIBX000_ADC_ON);
+	if (dib8000_set_adc_state(state, DIBX000_SLOW_ADC_ON) != 0)
+		dprintk("could not start Slow ADC");
+
+	if (state->revision != 0x8090)
+		dib8000_sad_calib(state);
+
+	for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
+		ret = state->fe[index_frontend]->ops.init(state->fe[index_frontend]);
+		if (ret < 0)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int dib8000_sleep(struct dvb_frontend *fe)
+{
+	struct dib8000_state *state = fe->demodulator_priv;
+	u8 index_frontend;
+	int ret;
+
+	for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
+		ret = state->fe[index_frontend]->ops.sleep(state->fe[index_frontend]);
+		if (ret < 0)
+			return ret;
+	}
+
+	if (state->revision != 0x8090)
+		dib8000_set_output_mode(fe, OUTMODE_HIGH_Z);
+	dib8000_set_power_mode(state, DIB8000_POWER_INTERFACE_ONLY);
+	return dib8000_set_adc_state(state, DIBX000_SLOW_ADC_OFF) | dib8000_set_adc_state(state, DIBX000_ADC_OFF);
+}
+
+enum frontend_tune_state dib8000_get_tune_state(struct dvb_frontend *fe)
+{
+	struct dib8000_state *state = fe->demodulator_priv;
+	return state->tune_state;
+}
+EXPORT_SYMBOL(dib8000_get_tune_state);
+
+int dib8000_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state)
+{
+	struct dib8000_state *state = fe->demodulator_priv;
+	state->tune_state = tune_state;
+	return 0;
+}
+EXPORT_SYMBOL(dib8000_set_tune_state);
+
+static int dib8000_get_frontend(struct dvb_frontend *fe)
+{
+	struct dib8000_state *state = fe->demodulator_priv;
+	u16 i, val = 0;
+	fe_status_t stat;
+	u8 index_frontend, sub_index_frontend;
+
+	fe->dtv_property_cache.bandwidth_hz = 6000000;
+
+	for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
+		state->fe[index_frontend]->ops.read_status(state->fe[index_frontend], &stat);
+		if (stat&FE_HAS_SYNC) {
+			dprintk("TMCC lock on the slave%i", index_frontend);
+			/* synchronize the cache with the other frontends */
+			state->fe[index_frontend]->ops.get_frontend(state->fe[index_frontend]);
+			for (sub_index_frontend = 0; (sub_index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[sub_index_frontend] != NULL); sub_index_frontend++) {
+				if (sub_index_frontend != index_frontend) {
+					state->fe[sub_index_frontend]->dtv_property_cache.isdbt_sb_mode = state->fe[index_frontend]->dtv_property_cache.isdbt_sb_mode;
+					state->fe[sub_index_frontend]->dtv_property_cache.inversion = state->fe[index_frontend]->dtv_property_cache.inversion;
+					state->fe[sub_index_frontend]->dtv_property_cache.transmission_mode = state->fe[index_frontend]->dtv_property_cache.transmission_mode;
+					state->fe[sub_index_frontend]->dtv_property_cache.guard_interval = state->fe[index_frontend]->dtv_property_cache.guard_interval;
+					state->fe[sub_index_frontend]->dtv_property_cache.isdbt_partial_reception = state->fe[index_frontend]->dtv_property_cache.isdbt_partial_reception;
+					for (i = 0; i < 3; i++) {
+						state->fe[sub_index_frontend]->dtv_property_cache.layer[i].segment_count = state->fe[index_frontend]->dtv_property_cache.layer[i].segment_count;
+						state->fe[sub_index_frontend]->dtv_property_cache.layer[i].interleaving = state->fe[index_frontend]->dtv_property_cache.layer[i].interleaving;
+						state->fe[sub_index_frontend]->dtv_property_cache.layer[i].fec = state->fe[index_frontend]->dtv_property_cache.layer[i].fec;
+						state->fe[sub_index_frontend]->dtv_property_cache.layer[i].modulation = state->fe[index_frontend]->dtv_property_cache.layer[i].modulation;
+					}
+				}
+			}
+			return 0;
+		}
+	}
+
+	fe->dtv_property_cache.isdbt_sb_mode = dib8000_read_word(state, 508) & 0x1;
+
+	if (state->revision == 0x8090)
+		val = dib8000_read_word(state, 572);
+	else
+		val = dib8000_read_word(state, 570);
+	fe->dtv_property_cache.inversion = (val & 0x40) >> 6;
+	switch ((val & 0x30) >> 4) {
+	case 1:
+		fe->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_2K;
+		break;
+	case 3:
+	default:
+		fe->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_8K;
+		break;
+	}
+
+	switch (val & 0x3) {
+	case 0:
+		fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_32;
+		dprintk("dib8000_get_frontend GI = 1/32 ");
+		break;
+	case 1:
+		fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_16;
+		dprintk("dib8000_get_frontend GI = 1/16 ");
+		break;
+	case 2:
+		dprintk("dib8000_get_frontend GI = 1/8 ");
+		fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_8;
+		break;
+	case 3:
+		dprintk("dib8000_get_frontend GI = 1/4 ");
+		fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_4;
+		break;
+	}
+
+	val = dib8000_read_word(state, 505);
+	fe->dtv_property_cache.isdbt_partial_reception = val & 1;
+	dprintk("dib8000_get_frontend : partial_reception = %d ", fe->dtv_property_cache.isdbt_partial_reception);
+
+	for (i = 0; i < 3; i++) {
+		val = dib8000_read_word(state, 493 + i);
+		fe->dtv_property_cache.layer[i].segment_count = val & 0x0F;
+		dprintk("dib8000_get_frontend : Layer %d segments = %d ", i, fe->dtv_property_cache.layer[i].segment_count);
+
+		val = dib8000_read_word(state, 499 + i);
+		fe->dtv_property_cache.layer[i].interleaving = val & 0x3;
+		dprintk("dib8000_get_frontend : Layer %d time_intlv = %d ", i, fe->dtv_property_cache.layer[i].interleaving);
+
+		val = dib8000_read_word(state, 481 + i);
+		switch (val & 0x7) {
+		case 1:
+			fe->dtv_property_cache.layer[i].fec = FEC_1_2;
+			dprintk("dib8000_get_frontend : Layer %d Code Rate = 1/2 ", i);
+			break;
+		case 2:
+			fe->dtv_property_cache.layer[i].fec = FEC_2_3;
+			dprintk("dib8000_get_frontend : Layer %d Code Rate = 2/3 ", i);
+			break;
+		case 3:
+			fe->dtv_property_cache.layer[i].fec = FEC_3_4;
+			dprintk("dib8000_get_frontend : Layer %d Code Rate = 3/4 ", i);
+			break;
+		case 5:
+			fe->dtv_property_cache.layer[i].fec = FEC_5_6;
+			dprintk("dib8000_get_frontend : Layer %d Code Rate = 5/6 ", i);
+			break;
+		default:
+			fe->dtv_property_cache.layer[i].fec = FEC_7_8;
+			dprintk("dib8000_get_frontend : Layer %d Code Rate = 7/8 ", i);
+			break;
+		}
+
+		val = dib8000_read_word(state, 487 + i);
+		switch (val & 0x3) {
+		case 0:
+			dprintk("dib8000_get_frontend : Layer %d DQPSK ", i);
+			fe->dtv_property_cache.layer[i].modulation = DQPSK;
+			break;
+		case 1:
+			fe->dtv_property_cache.layer[i].modulation = QPSK;
+			dprintk("dib8000_get_frontend : Layer %d QPSK ", i);
+			break;
+		case 2:
+			fe->dtv_property_cache.layer[i].modulation = QAM_16;
+			dprintk("dib8000_get_frontend : Layer %d QAM16 ", i);
+			break;
+		case 3:
+		default:
+			dprintk("dib8000_get_frontend : Layer %d QAM64 ", i);
+			fe->dtv_property_cache.layer[i].modulation = QAM_64;
+			break;
+		}
+	}
+
+	/* synchronize the cache with the other frontends */
+	for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
+		state->fe[index_frontend]->dtv_property_cache.isdbt_sb_mode = fe->dtv_property_cache.isdbt_sb_mode;
+		state->fe[index_frontend]->dtv_property_cache.inversion = fe->dtv_property_cache.inversion;
+		state->fe[index_frontend]->dtv_property_cache.transmission_mode = fe->dtv_property_cache.transmission_mode;
+		state->fe[index_frontend]->dtv_property_cache.guard_interval = fe->dtv_property_cache.guard_interval;
+		state->fe[index_frontend]->dtv_property_cache.isdbt_partial_reception = fe->dtv_property_cache.isdbt_partial_reception;
+		for (i = 0; i < 3; i++) {
+			state->fe[index_frontend]->dtv_property_cache.layer[i].segment_count = fe->dtv_property_cache.layer[i].segment_count;
+			state->fe[index_frontend]->dtv_property_cache.layer[i].interleaving = fe->dtv_property_cache.layer[i].interleaving;
+			state->fe[index_frontend]->dtv_property_cache.layer[i].fec = fe->dtv_property_cache.layer[i].fec;
+			state->fe[index_frontend]->dtv_property_cache.layer[i].modulation = fe->dtv_property_cache.layer[i].modulation;
+		}
+	}
+	return 0;
+}
+
+static int dib8000_set_frontend(struct dvb_frontend *fe)
+{
+	struct dib8000_state *state = fe->demodulator_priv;
+	u8 nbr_pending, exit_condition, index_frontend;
+	s8 index_frontend_success = -1;
+	int time, ret;
+	int  time_slave = FE_CALLBACK_TIME_NEVER;
+
+	if (state->fe[0]->dtv_property_cache.frequency == 0) {
+		dprintk("dib8000: must at least specify frequency ");
+		return 0;
+	}
+
+	if (state->fe[0]->dtv_property_cache.bandwidth_hz == 0) {
+		dprintk("dib8000: no bandwidth specified, set to default ");
+		state->fe[0]->dtv_property_cache.bandwidth_hz = 6000000;
+	}
+
+	for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
+		/* synchronization of the cache */
+		state->fe[index_frontend]->dtv_property_cache.delivery_system = SYS_ISDBT;
+		memcpy(&state->fe[index_frontend]->dtv_property_cache, &fe->dtv_property_cache, sizeof(struct dtv_frontend_properties));
+
+		if (state->revision != 0x8090)
+			dib8000_set_output_mode(state->fe[index_frontend],
+					OUTMODE_HIGH_Z);
+		else
+			dib8096p_set_output_mode(state->fe[index_frontend],
+					OUTMODE_HIGH_Z);
+		if (state->fe[index_frontend]->ops.tuner_ops.set_params)
+			state->fe[index_frontend]->ops.tuner_ops.set_params(state->fe[index_frontend]);
+
+		dib8000_set_tune_state(state->fe[index_frontend], CT_AGC_START);
+	}
+
+	/* start up the AGC */
+	do {
+		time = dib8000_agc_startup(state->fe[0]);
+		for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
+			time_slave = dib8000_agc_startup(state->fe[index_frontend]);
+			if (time == FE_CALLBACK_TIME_NEVER)
+				time = time_slave;
+			else if ((time_slave != FE_CALLBACK_TIME_NEVER) && (time_slave > time))
+				time = time_slave;
+		}
+		if (time != FE_CALLBACK_TIME_NEVER)
+			msleep(time / 10);
+		else
+			break;
+		exit_condition = 1;
+		for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
+			if (dib8000_get_tune_state(state->fe[index_frontend]) != CT_AGC_STOP) {
+				exit_condition = 0;
+				break;
+			}
+		}
+	} while (exit_condition == 0);
+
+	for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++)
+		dib8000_set_tune_state(state->fe[index_frontend], CT_DEMOD_START);
+
+	if ((state->fe[0]->dtv_property_cache.delivery_system != SYS_ISDBT) ||
+			(state->fe[0]->dtv_property_cache.inversion == INVERSION_AUTO) ||
+			(state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_AUTO) ||
+			(state->fe[0]->dtv_property_cache.guard_interval == GUARD_INTERVAL_AUTO) ||
+			(((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (1 << 0)) != 0) &&
+			 (state->fe[0]->dtv_property_cache.layer[0].segment_count != 0xff) &&
+			 (state->fe[0]->dtv_property_cache.layer[0].segment_count != 0) &&
+			 ((state->fe[0]->dtv_property_cache.layer[0].modulation == QAM_AUTO) ||
+			  (state->fe[0]->dtv_property_cache.layer[0].fec == FEC_AUTO))) ||
+			(((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (1 << 1)) != 0) &&
+			 (state->fe[0]->dtv_property_cache.layer[1].segment_count != 0xff) &&
+			 (state->fe[0]->dtv_property_cache.layer[1].segment_count != 0) &&
+			 ((state->fe[0]->dtv_property_cache.layer[1].modulation == QAM_AUTO) ||
+			  (state->fe[0]->dtv_property_cache.layer[1].fec == FEC_AUTO))) ||
+			(((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (1 << 2)) != 0) &&
+			 (state->fe[0]->dtv_property_cache.layer[2].segment_count != 0xff) &&
+			 (state->fe[0]->dtv_property_cache.layer[2].segment_count != 0) &&
+			 ((state->fe[0]->dtv_property_cache.layer[2].modulation == QAM_AUTO) ||
+			  (state->fe[0]->dtv_property_cache.layer[2].fec == FEC_AUTO))) ||
+			(((state->fe[0]->dtv_property_cache.layer[0].segment_count == 0) ||
+			  ((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (1 << 0)) == 0)) &&
+			 ((state->fe[0]->dtv_property_cache.layer[1].segment_count == 0) ||
+			  ((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (2 << 0)) == 0)) &&
+			 ((state->fe[0]->dtv_property_cache.layer[2].segment_count == 0) || ((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (3 << 0)) == 0)))) {
+		int i = 100;
+		u8 found = 0;
+		u8 tune_failed = 0;
+
+		for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
+			dib8000_set_bandwidth(state->fe[index_frontend], fe->dtv_property_cache.bandwidth_hz / 1000);
+			dib8000_autosearch_start(state->fe[index_frontend]);
+		}
+
+		do {
+			msleep(20);
+			nbr_pending = 0;
+			exit_condition = 0; /* 0: tune pending; 1: tune failed; 2:tune success */
+			for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
+				if (((tune_failed >> index_frontend) & 0x1) == 0) {
+					found = dib8000_autosearch_irq(state->fe[index_frontend]);
+					switch (found) {
+					case 0: /* tune pending */
+						 nbr_pending++;
+						 break;
+					case 2:
+						 dprintk("autosearch succeed on the frontend%i", index_frontend);
+						 exit_condition = 2;
+						 index_frontend_success = index_frontend;
+						 break;
+					default:
+						 dprintk("unhandled autosearch result");
+					case 1:
+						 tune_failed |= (1 << index_frontend);
+						 dprintk("autosearch failed for the frontend%i", index_frontend);
+						 break;
+					}
+				}
+			}
+
+			/* if all tune are done and no success, exit: tune failed */
+			if ((nbr_pending == 0) && (exit_condition == 0))
+				exit_condition = 1;
+		} while ((exit_condition == 0) && i--);
+
+		if (exit_condition == 1) { /* tune failed */
+			dprintk("tune failed");
+			return 0;
+		}
+
+		dprintk("tune success on frontend%i", index_frontend_success);
+
+		dib8000_get_frontend(fe);
+	}
+
+	for (index_frontend = 0, ret = 0; (ret >= 0) && (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++)
+		ret = dib8000_tune(state->fe[index_frontend]);
+
+	/* set output mode and diversity input */
+	if (state->revision != 0x8090) {
+		dib8000_set_output_mode(state->fe[0], state->cfg.output_mode);
+		for (index_frontend = 1;
+				(index_frontend < MAX_NUMBER_OF_FRONTENDS) &&
+				(state->fe[index_frontend] != NULL);
+				index_frontend++) {
+			dib8000_set_output_mode(state->fe[index_frontend],
+					OUTMODE_DIVERSITY);
+			dib8000_set_diversity_in(state->fe[index_frontend-1], 1);
+		}
+
+		/* turn off the diversity of the last chip */
+		dib8000_set_diversity_in(state->fe[index_frontend-1], 0);
+	} else {
+		dib8096p_set_output_mode(state->fe[0], state->cfg.output_mode);
+		if (state->cfg.enMpegOutput == 0) {
+			dib8096p_setDibTxMux(state, MPEG_ON_DIBTX);
+			dib8096p_setHostBusMux(state, DIBTX_ON_HOSTBUS);
+		}
+		for (index_frontend = 1;
+				(index_frontend < MAX_NUMBER_OF_FRONTENDS) &&
+				(state->fe[index_frontend] != NULL);
+				index_frontend++) {
+			dib8096p_set_output_mode(state->fe[index_frontend],
+					OUTMODE_DIVERSITY);
+			dib8096p_set_diversity_in(state->fe[index_frontend-1], 1);
+		}
+
+		/* turn off the diversity of the last chip */
+		dib8096p_set_diversity_in(state->fe[index_frontend-1], 0);
+	}
+
+	return ret;
+}
+
+static u16 dib8000_read_lock(struct dvb_frontend *fe)
+{
+	struct dib8000_state *state = fe->demodulator_priv;
+
+	if (state->revision == 0x8090)
+		return dib8000_read_word(state, 570);
+	return dib8000_read_word(state, 568);
+}
+
+static int dib8000_read_status(struct dvb_frontend *fe, fe_status_t * stat)
+{
+	struct dib8000_state *state = fe->demodulator_priv;
+	u16 lock_slave = 0, lock;
+	u8 index_frontend;
+
+	if (state->revision == 0x8090)
+		lock = dib8000_read_word(state, 570);
+	else
+		lock = dib8000_read_word(state, 568);
+
+	for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++)
+		lock_slave |= dib8000_read_lock(state->fe[index_frontend]);
+
+	*stat = 0;
+
+	if (((lock >> 13) & 1) || ((lock_slave >> 13) & 1))
+		*stat |= FE_HAS_SIGNAL;
+
+	if (((lock >> 8) & 1) || ((lock_slave >> 8) & 1)) /* Equal */
+		*stat |= FE_HAS_CARRIER;
+
+	if ((((lock >> 1) & 0xf) == 0xf) || (((lock_slave >> 1) & 0xf) == 0xf)) /* TMCC_SYNC */
+		*stat |= FE_HAS_SYNC;
+
+	if ((((lock >> 12) & 1) || ((lock_slave >> 12) & 1)) && ((lock >> 5) & 7)) /* FEC MPEG */
+		*stat |= FE_HAS_LOCK;
+
+	if (((lock >> 12) & 1) || ((lock_slave >> 12) & 1)) {
+		lock = dib8000_read_word(state, 554); /* Viterbi Layer A */
+		if (lock & 0x01)
+			*stat |= FE_HAS_VITERBI;
+
+		lock = dib8000_read_word(state, 555); /* Viterbi Layer B */
+		if (lock & 0x01)
+			*stat |= FE_HAS_VITERBI;
+
+		lock = dib8000_read_word(state, 556); /* Viterbi Layer C */
+		if (lock & 0x01)
+			*stat |= FE_HAS_VITERBI;
+	}
+
+	return 0;
+}
+
+static int dib8000_read_ber(struct dvb_frontend *fe, u32 * ber)
+{
+	struct dib8000_state *state = fe->demodulator_priv;
+
+	/* 13 segments */
+	if (state->revision == 0x8090)
+		*ber = (dib8000_read_word(state, 562) << 16) |
+			dib8000_read_word(state, 563);
+	else
+		*ber = (dib8000_read_word(state, 560) << 16) |
+			dib8000_read_word(state, 561);
+	return 0;
+}
+
+static int dib8000_read_unc_blocks(struct dvb_frontend *fe, u32 * unc)
+{
+	struct dib8000_state *state = fe->demodulator_priv;
+
+	/* packet error on 13 seg */
+	if (state->revision == 0x8090)
+		*unc = dib8000_read_word(state, 567);
+	else
+		*unc = dib8000_read_word(state, 565);
+	return 0;
+}
+
+static int dib8000_read_signal_strength(struct dvb_frontend *fe, u16 * strength)
+{
+	struct dib8000_state *state = fe->demodulator_priv;
+	u8 index_frontend;
+	u16 val;
+
+	*strength = 0;
+	for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
+		state->fe[index_frontend]->ops.read_signal_strength(state->fe[index_frontend], &val);
+		if (val > 65535 - *strength)
+			*strength = 65535;
+		else
+			*strength += val;
+	}
+
+	val = 65535 - dib8000_read_word(state, 390);
+	if (val > 65535 - *strength)
+		*strength = 65535;
+	else
+		*strength += val;
+	return 0;
+}
+
+static u32 dib8000_get_snr(struct dvb_frontend *fe)
+{
+	struct dib8000_state *state = fe->demodulator_priv;
+	u32 n, s, exp;
+	u16 val;
+
+	if (state->revision != 0x8090)
+		val = dib8000_read_word(state, 542);
+	else
+		val = dib8000_read_word(state, 544);
+	n = (val >> 6) & 0xff;
+	exp = (val & 0x3f);
+	if ((exp & 0x20) != 0)
+		exp -= 0x40;
+	n <<= exp+16;
+
+	if (state->revision != 0x8090)
+		val = dib8000_read_word(state, 543);
+	else
+		val = dib8000_read_word(state, 545);
+	s = (val >> 6) & 0xff;
+	exp = (val & 0x3f);
+	if ((exp & 0x20) != 0)
+		exp -= 0x40;
+	s <<= exp+16;
+
+	if (n > 0) {
+		u32 t = (s/n) << 16;
+		return t + ((s << 16) - n*t) / n;
+	}
+	return 0xffffffff;
+}
+
+static int dib8000_read_snr(struct dvb_frontend *fe, u16 * snr)
+{
+	struct dib8000_state *state = fe->demodulator_priv;
+	u8 index_frontend;
+	u32 snr_master;
+
+	snr_master = dib8000_get_snr(fe);
+	for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++)
+		snr_master += dib8000_get_snr(state->fe[index_frontend]);
+
+	if ((snr_master >> 16) != 0) {
+		snr_master = 10*intlog10(snr_master>>16);
+		*snr = snr_master / ((1 << 24) / 10);
+	}
+	else
+		*snr = 0;
+
+	return 0;
+}
+
+int dib8000_set_slave_frontend(struct dvb_frontend *fe, struct dvb_frontend *fe_slave)
+{
+	struct dib8000_state *state = fe->demodulator_priv;
+	u8 index_frontend = 1;
+
+	while ((index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL))
+		index_frontend++;
+	if (index_frontend < MAX_NUMBER_OF_FRONTENDS) {
+		dprintk("set slave fe %p to index %i", fe_slave, index_frontend);
+		state->fe[index_frontend] = fe_slave;
+		return 0;
+	}
+
+	dprintk("too many slave frontend");
+	return -ENOMEM;
+}
+EXPORT_SYMBOL(dib8000_set_slave_frontend);
+
+int dib8000_remove_slave_frontend(struct dvb_frontend *fe)
+{
+	struct dib8000_state *state = fe->demodulator_priv;
+	u8 index_frontend = 1;
+
+	while ((index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL))
+		index_frontend++;
+	if (index_frontend != 1) {
+		dprintk("remove slave fe %p (index %i)", state->fe[index_frontend-1], index_frontend-1);
+		state->fe[index_frontend] = NULL;
+		return 0;
+	}
+
+	dprintk("no frontend to be removed");
+	return -ENODEV;
+}
+EXPORT_SYMBOL(dib8000_remove_slave_frontend);
+
+struct dvb_frontend *dib8000_get_slave_frontend(struct dvb_frontend *fe, int slave_index)
+{
+	struct dib8000_state *state = fe->demodulator_priv;
+
+	if (slave_index >= MAX_NUMBER_OF_FRONTENDS)
+		return NULL;
+	return state->fe[slave_index];
+}
+EXPORT_SYMBOL(dib8000_get_slave_frontend);
+
+
+int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods,
+		u8 default_addr, u8 first_addr, u8 is_dib8096p)
+{
+	int k = 0, ret = 0;
+	u8 new_addr = 0;
+	struct i2c_device client = {.adap = host };
+
+	client.i2c_write_buffer = kzalloc(4 * sizeof(u8), GFP_KERNEL);
+	if (!client.i2c_write_buffer) {
+		dprintk("%s: not enough memory", __func__);
+		return -ENOMEM;
+	}
+	client.i2c_read_buffer = kzalloc(4 * sizeof(u8), GFP_KERNEL);
+	if (!client.i2c_read_buffer) {
+		dprintk("%s: not enough memory", __func__);
+		ret = -ENOMEM;
+		goto error_memory_read;
+	}
+	client.i2c_buffer_lock = kzalloc(sizeof(struct mutex), GFP_KERNEL);
+	if (!client.i2c_buffer_lock) {
+		dprintk("%s: not enough memory", __func__);
+		ret = -ENOMEM;
+		goto error_memory_lock;
+	}
+	mutex_init(client.i2c_buffer_lock);
+
+	for (k = no_of_demods - 1; k >= 0; k--) {
+		/* designated i2c address */
+		new_addr = first_addr + (k << 1);
+
+		client.addr = new_addr;
+		if (!is_dib8096p)
+			dib8000_i2c_write16(&client, 1287, 0x0003);	/* sram lead in, rdy */
+		if (dib8000_identify(&client) == 0) {
+			/* sram lead in, rdy */
+			if (!is_dib8096p)
+				dib8000_i2c_write16(&client, 1287, 0x0003);
+			client.addr = default_addr;
+			if (dib8000_identify(&client) == 0) {
+				dprintk("#%d: not identified", k);
+				ret  = -EINVAL;
+				goto error;
+			}
+		}
+
+		/* start diversity to pull_down div_str - just for i2c-enumeration */
+		dib8000_i2c_write16(&client, 1286, (1 << 10) | (4 << 6));
+
+		/* set new i2c address and force divstart */
+		dib8000_i2c_write16(&client, 1285, (new_addr << 2) | 0x2);
+		client.addr = new_addr;
+		dib8000_identify(&client);
+
+		dprintk("IC %d initialized (to i2c_address 0x%x)", k, new_addr);
+	}
+
+	for (k = 0; k < no_of_demods; k++) {
+		new_addr = first_addr | (k << 1);
+		client.addr = new_addr;
+
+		// unforce divstr
+		dib8000_i2c_write16(&client, 1285, new_addr << 2);
+
+		/* deactivate div - it was just for i2c-enumeration */
+		dib8000_i2c_write16(&client, 1286, 0);
+	}
+
+error:
+	kfree(client.i2c_buffer_lock);
+error_memory_lock:
+	kfree(client.i2c_read_buffer);
+error_memory_read:
+	kfree(client.i2c_write_buffer);
+
+	return ret;
+}
+
+EXPORT_SYMBOL(dib8000_i2c_enumeration);
+static int dib8000_fe_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings *tune)
+{
+	tune->min_delay_ms = 1000;
+	tune->step_size = 0;
+	tune->max_drift = 0;
+	return 0;
+}
+
+static void dib8000_release(struct dvb_frontend *fe)
+{
+	struct dib8000_state *st = fe->demodulator_priv;
+	u8 index_frontend;
+
+	for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (st->fe[index_frontend] != NULL); index_frontend++)
+		dvb_frontend_detach(st->fe[index_frontend]);
+
+	dibx000_exit_i2c_master(&st->i2c_master);
+	i2c_del_adapter(&st->dib8096p_tuner_adap);
+	kfree(st->fe[0]);
+	kfree(st);
+}
+
+struct i2c_adapter *dib8000_get_i2c_master(struct dvb_frontend *fe, enum dibx000_i2c_interface intf, int gating)
+{
+	struct dib8000_state *st = fe->demodulator_priv;
+	return dibx000_get_i2c_adapter(&st->i2c_master, intf, gating);
+}
+
+EXPORT_SYMBOL(dib8000_get_i2c_master);
+
+int dib8000_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
+{
+	struct dib8000_state *st = fe->demodulator_priv;
+	u16 val = dib8000_read_word(st, 299) & 0xffef;
+	val |= (onoff & 0x1) << 4;
+
+	dprintk("pid filter enabled %d", onoff);
+	return dib8000_write_word(st, 299, val);
+}
+EXPORT_SYMBOL(dib8000_pid_filter_ctrl);
+
+int dib8000_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
+{
+	struct dib8000_state *st = fe->demodulator_priv;
+	dprintk("Index %x, PID %d, OnOff %d", id, pid, onoff);
+	return dib8000_write_word(st, 305 + id, onoff ? (1 << 13) | pid : 0);
+}
+EXPORT_SYMBOL(dib8000_pid_filter);
+
+static const struct dvb_frontend_ops dib8000_ops = {
+	.delsys = { SYS_ISDBT },
+	.info = {
+		 .name = "DiBcom 8000 ISDB-T",
+		 .frequency_min = 44250000,
+		 .frequency_max = 867250000,
+		 .frequency_stepsize = 62500,
+		 .caps = FE_CAN_INVERSION_AUTO |
+		 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_FEC_AUTO |
+		 FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
+		 FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_RECOVER | FE_CAN_HIERARCHY_AUTO,
+		 },
+
+	.release = dib8000_release,
+
+	.init = dib8000_wakeup,
+	.sleep = dib8000_sleep,
+
+	.set_frontend = dib8000_set_frontend,
+	.get_tune_settings = dib8000_fe_get_tune_settings,
+	.get_frontend = dib8000_get_frontend,
+
+	.read_status = dib8000_read_status,
+	.read_ber = dib8000_read_ber,
+	.read_signal_strength = dib8000_read_signal_strength,
+	.read_snr = dib8000_read_snr,
+	.read_ucblocks = dib8000_read_unc_blocks,
+};
+
+struct dvb_frontend *dib8000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib8000_config *cfg)
+{
+	struct dvb_frontend *fe;
+	struct dib8000_state *state;
+
+	dprintk("dib8000_attach");
+
+	state = kzalloc(sizeof(struct dib8000_state), GFP_KERNEL);
+	if (state == NULL)
+		return NULL;
+	fe = kzalloc(sizeof(struct dvb_frontend), GFP_KERNEL);
+	if (fe == NULL)
+		goto error;
+
+	memcpy(&state->cfg, cfg, sizeof(struct dib8000_config));
+	state->i2c.adap = i2c_adap;
+	state->i2c.addr = i2c_addr;
+	state->i2c.i2c_write_buffer = state->i2c_write_buffer;
+	state->i2c.i2c_read_buffer = state->i2c_read_buffer;
+	mutex_init(&state->i2c_buffer_lock);
+	state->i2c.i2c_buffer_lock = &state->i2c_buffer_lock;
+	state->gpio_val = cfg->gpio_val;
+	state->gpio_dir = cfg->gpio_dir;
+
+	/* Ensure the output mode remains at the previous default if it's
+	 * not specifically set by the caller.
+	 */
+	if ((state->cfg.output_mode != OUTMODE_MPEG2_SERIAL) && (state->cfg.output_mode != OUTMODE_MPEG2_PAR_GATED_CLK))
+		state->cfg.output_mode = OUTMODE_MPEG2_FIFO;
+
+	state->fe[0] = fe;
+	fe->demodulator_priv = state;
+	memcpy(&state->fe[0]->ops, &dib8000_ops, sizeof(struct dvb_frontend_ops));
+
+	state->timf_default = cfg->pll->timf;
+
+	if (dib8000_identify(&state->i2c) == 0)
+		goto error;
+
+	dibx000_init_i2c_master(&state->i2c_master, DIB8000, state->i2c.adap, state->i2c.addr);
+
+	/* init 8096p tuner adapter */
+	strncpy(state->dib8096p_tuner_adap.name, "DiB8096P tuner interface",
+			sizeof(state->dib8096p_tuner_adap.name));
+	state->dib8096p_tuner_adap.algo = &dib8096p_tuner_xfer_algo;
+	state->dib8096p_tuner_adap.algo_data = NULL;
+	state->dib8096p_tuner_adap.dev.parent = state->i2c.adap->dev.parent;
+	i2c_set_adapdata(&state->dib8096p_tuner_adap, state);
+	i2c_add_adapter(&state->dib8096p_tuner_adap);
+
+	dib8000_reset(fe);
+
+	dib8000_write_word(state, 285, (dib8000_read_word(state, 285) & ~0x60) | (3 << 5));	/* ber_rs_len = 3 */
+
+	return fe;
+
+ error:
+	kfree(state);
+	return NULL;
+}
+
+EXPORT_SYMBOL(dib8000_attach);
+
+MODULE_AUTHOR("Olivier Grenie <Olivier.Grenie@dibcom.fr, " "Patrick Boettcher <pboettcher@dibcom.fr>");
+MODULE_DESCRIPTION("Driver for the DiBcom 8000 ISDB-T demodulator");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb-frontends/dib8000.h b/drivers/media/dvb-frontends/dib8000.h
new file mode 100644
index 0000000..39591bb
--- /dev/null
+++ b/drivers/media/dvb-frontends/dib8000.h
@@ -0,0 +1,174 @@
+#ifndef DIB8000_H
+#define DIB8000_H
+
+#include "dibx000_common.h"
+
+struct dib8000_config {
+	u8 output_mpeg2_in_188_bytes;
+	u8 hostbus_diversity;
+	u8 tuner_is_baseband;
+	int (*update_lna) (struct dvb_frontend *, u16 agc_global);
+
+	u8 agc_config_count;
+	struct dibx000_agc_config *agc;
+	struct dibx000_bandwidth_config *pll;
+
+#define DIB8000_GPIO_DEFAULT_DIRECTIONS 0xffff
+	u16 gpio_dir;
+#define DIB8000_GPIO_DEFAULT_VALUES     0x0000
+	u16 gpio_val;
+#define DIB8000_GPIO_PWM_POS0(v)        ((v & 0xf) << 12)
+#define DIB8000_GPIO_PWM_POS1(v)        ((v & 0xf) << 8 )
+#define DIB8000_GPIO_PWM_POS2(v)        ((v & 0xf) << 4 )
+#define DIB8000_GPIO_PWM_POS3(v)         (v & 0xf)
+#define DIB8000_GPIO_DEFAULT_PWM_POS    0xffff
+	u16 gpio_pwm_pos;
+	u16 pwm_freq_div;
+
+	void (*agc_control) (struct dvb_frontend *, u8 before);
+
+	u16 drives;
+	u16 diversity_delay;
+	u8 div_cfg;
+	u8 output_mode;
+	u8 refclksel;
+	u8 enMpegOutput:1;
+};
+
+#define DEFAULT_DIB8000_I2C_ADDRESS 18
+
+#if defined(CONFIG_DVB_DIB8000) || (defined(CONFIG_DVB_DIB8000_MODULE) && defined(MODULE))
+extern struct dvb_frontend *dib8000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib8000_config *cfg);
+extern struct i2c_adapter *dib8000_get_i2c_master(struct dvb_frontend *, enum dibx000_i2c_interface, int);
+
+extern int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods,
+		u8 default_addr, u8 first_addr, u8 is_dib8096p);
+
+extern int dib8000_set_gpio(struct dvb_frontend *, u8 num, u8 dir, u8 val);
+extern int dib8000_set_wbd_ref(struct dvb_frontend *, u16 value);
+extern int dib8000_pid_filter_ctrl(struct dvb_frontend *, u8 onoff);
+extern int dib8000_pid_filter(struct dvb_frontend *, u8 id, u16 pid, u8 onoff);
+extern int dib8000_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state);
+extern enum frontend_tune_state dib8000_get_tune_state(struct dvb_frontend *fe);
+extern void dib8000_pwm_agc_reset(struct dvb_frontend *fe);
+extern s32 dib8000_get_adc_power(struct dvb_frontend *fe, u8 mode);
+extern struct i2c_adapter *dib8096p_get_i2c_tuner(struct dvb_frontend *fe);
+extern int dib8096p_tuner_sleep(struct dvb_frontend *fe, int onoff);
+extern int dib8090p_get_dc_power(struct dvb_frontend *fe, u8 IQ);
+extern u32 dib8000_ctrl_timf(struct dvb_frontend *fe,
+		uint8_t op, uint32_t timf);
+extern int dib8000_update_pll(struct dvb_frontend *fe,
+		struct dibx000_bandwidth_config *pll);
+extern int dib8000_set_slave_frontend(struct dvb_frontend *fe, struct dvb_frontend *fe_slave);
+extern int dib8000_remove_slave_frontend(struct dvb_frontend *fe);
+extern struct dvb_frontend *dib8000_get_slave_frontend(struct dvb_frontend *fe, int slave_index);
+#else
+static inline struct dvb_frontend *dib8000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib8000_config *cfg)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+
+static inline struct i2c_adapter *dib8000_get_i2c_master(struct dvb_frontend *fe, enum dibx000_i2c_interface i, int x)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+
+static inline int dib8000_i2c_enumeration(struct i2c_adapter *host,
+		int no_of_demods, u8 default_addr, u8 first_addr,
+		u8 is_dib8096p)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return -ENODEV;
+}
+
+static inline int dib8000_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 dib8000_set_wbd_ref(struct dvb_frontend *fe, u16 value)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return -ENODEV;
+}
+
+static inline int dib8000_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return -ENODEV;
+}
+
+static inline int dib8000_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return -ENODEV;
+}
+static inline int dib8000_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return -ENODEV;
+}
+static inline enum frontend_tune_state dib8000_get_tune_state(struct dvb_frontend *fe)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return CT_SHUTDOWN;
+}
+static inline void dib8000_pwm_agc_reset(struct dvb_frontend *fe)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+}
+static inline struct i2c_adapter *dib8096p_get_i2c_tuner(struct dvb_frontend *fe)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+static inline int dib8096p_tuner_sleep(struct dvb_frontend *fe, int onoff)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return 0;
+}
+static inline s32 dib8000_get_adc_power(struct dvb_frontend *fe, u8 mode)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return 0;
+}
+static inline int dib8090p_get_dc_power(struct dvb_frontend *fe, u8 IQ)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return 0;
+}
+static inline u32 dib8000_ctrl_timf(struct dvb_frontend *fe,
+		uint8_t op, uint32_t timf)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return 0;
+}
+static inline int dib8000_update_pll(struct dvb_frontend *fe,
+		struct dibx000_bandwidth_config *pll)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return -ENODEV;
+}
+static inline int dib8000_set_slave_frontend(struct dvb_frontend *fe, struct dvb_frontend *fe_slave)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return -ENODEV;
+}
+
+int dib8000_remove_slave_frontend(struct dvb_frontend *fe)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return -ENODEV;
+}
+
+static inline struct dvb_frontend *dib8000_get_slave_frontend(struct dvb_frontend *fe, int slave_index)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif
+
+#endif
diff --git a/drivers/media/dvb-frontends/dib9000.c b/drivers/media/dvb-frontends/dib9000.c
new file mode 100644
index 0000000..6201c59
--- /dev/null
+++ b/drivers/media/dvb-frontends/dib9000.c
@@ -0,0 +1,2590 @@
+/*
+ * Linux-DVB Driver for DiBcom's DiB9000 and demodulator-family.
+ *
+ * Copyright (C) 2005-10 DiBcom (http://www.dibcom.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, version 2.
+ */
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+
+#include "dvb_math.h"
+#include "dvb_frontend.h"
+
+#include "dib9000.h"
+#include "dibx000_common.h"
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
+
+#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB9000: "); printk(args); printk("\n"); } } while (0)
+#define MAX_NUMBER_OF_FRONTENDS 6
+
+struct i2c_device {
+	struct i2c_adapter *i2c_adap;
+	u8 i2c_addr;
+	u8 *i2c_read_buffer;
+	u8 *i2c_write_buffer;
+};
+
+struct dib9000_pid_ctrl {
+#define DIB9000_PID_FILTER_CTRL 0
+#define DIB9000_PID_FILTER      1
+	u8 cmd;
+	u8 id;
+	u16 pid;
+	u8 onoff;
+};
+
+struct dib9000_state {
+	struct i2c_device i2c;
+
+	struct dibx000_i2c_master i2c_master;
+	struct i2c_adapter tuner_adap;
+	struct i2c_adapter component_bus;
+
+	u16 revision;
+	u8 reg_offs;
+
+	enum frontend_tune_state tune_state;
+	u32 status;
+	struct dvb_frontend_parametersContext channel_status;
+
+	u8 fe_id;
+
+#define DIB9000_GPIO_DEFAULT_DIRECTIONS 0xffff
+	u16 gpio_dir;
+#define DIB9000_GPIO_DEFAULT_VALUES     0x0000
+	u16 gpio_val;
+#define DIB9000_GPIO_DEFAULT_PWM_POS    0xffff
+	u16 gpio_pwm_pos;
+
+	union {			/* common for all chips */
+		struct {
+			u8 mobile_mode:1;
+		} host;
+
+		struct {
+			struct dib9000_fe_memory_map {
+				u16 addr;
+				u16 size;
+			} fe_mm[18];
+			u8 memcmd;
+
+			struct mutex mbx_if_lock;	/* to protect read/write operations */
+			struct mutex mbx_lock;	/* to protect the whole mailbox handling */
+
+			struct mutex mem_lock;	/* to protect the memory accesses */
+			struct mutex mem_mbx_lock;	/* to protect the memory-based mailbox */
+
+#define MBX_MAX_WORDS (256 - 200 - 2)
+#define DIB9000_MSG_CACHE_SIZE 2
+			u16 message_cache[DIB9000_MSG_CACHE_SIZE][MBX_MAX_WORDS];
+			u8 fw_is_running;
+		} risc;
+	} platform;
+
+	union {			/* common for all platforms */
+		struct {
+			struct dib9000_config cfg;
+		} d9;
+	} chip;
+
+	struct dvb_frontend *fe[MAX_NUMBER_OF_FRONTENDS];
+	u16 component_bus_speed;
+
+	/* for the I2C transfer */
+	struct i2c_msg msg[2];
+	u8 i2c_write_buffer[255];
+	u8 i2c_read_buffer[255];
+	struct mutex demod_lock;
+	u8 get_frontend_internal;
+	struct dib9000_pid_ctrl pid_ctrl[10];
+	s8 pid_ctrl_index; /* -1: empty list; -2: do not use the list */
+};
+
+static const u32 fe_info[44] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0
+};
+
+enum dib9000_power_mode {
+	DIB9000_POWER_ALL = 0,
+
+	DIB9000_POWER_NO,
+	DIB9000_POWER_INTERF_ANALOG_AGC,
+	DIB9000_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD,
+	DIB9000_POWER_COR4_CRY_ESRAM_MOUT_NUD,
+	DIB9000_POWER_INTERFACE_ONLY,
+};
+
+enum dib9000_out_messages {
+	OUT_MSG_HBM_ACK,
+	OUT_MSG_HOST_BUF_FAIL,
+	OUT_MSG_REQ_VERSION,
+	OUT_MSG_BRIDGE_I2C_W,
+	OUT_MSG_BRIDGE_I2C_R,
+	OUT_MSG_BRIDGE_APB_W,
+	OUT_MSG_BRIDGE_APB_R,
+	OUT_MSG_SCAN_CHANNEL,
+	OUT_MSG_MONIT_DEMOD,
+	OUT_MSG_CONF_GPIO,
+	OUT_MSG_DEBUG_HELP,
+	OUT_MSG_SUBBAND_SEL,
+	OUT_MSG_ENABLE_TIME_SLICE,
+	OUT_MSG_FE_FW_DL,
+	OUT_MSG_FE_CHANNEL_SEARCH,
+	OUT_MSG_FE_CHANNEL_TUNE,
+	OUT_MSG_FE_SLEEP,
+	OUT_MSG_FE_SYNC,
+	OUT_MSG_CTL_MONIT,
+
+	OUT_MSG_CONF_SVC,
+	OUT_MSG_SET_HBM,
+	OUT_MSG_INIT_DEMOD,
+	OUT_MSG_ENABLE_DIVERSITY,
+	OUT_MSG_SET_OUTPUT_MODE,
+	OUT_MSG_SET_PRIORITARY_CHANNEL,
+	OUT_MSG_ACK_FRG,
+	OUT_MSG_INIT_PMU,
+};
+
+enum dib9000_in_messages {
+	IN_MSG_DATA,
+	IN_MSG_FRAME_INFO,
+	IN_MSG_CTL_MONIT,
+	IN_MSG_ACK_FREE_ITEM,
+	IN_MSG_DEBUG_BUF,
+	IN_MSG_MPE_MONITOR,
+	IN_MSG_RAWTS_MONITOR,
+	IN_MSG_END_BRIDGE_I2C_RW,
+	IN_MSG_END_BRIDGE_APB_RW,
+	IN_MSG_VERSION,
+	IN_MSG_END_OF_SCAN,
+	IN_MSG_MONIT_DEMOD,
+	IN_MSG_ERROR,
+	IN_MSG_FE_FW_DL_DONE,
+	IN_MSG_EVENT,
+	IN_MSG_ACK_CHANGE_SVC,
+	IN_MSG_HBM_PROF,
+};
+
+/* memory_access requests */
+#define FE_MM_W_CHANNEL                   0
+#define FE_MM_W_FE_INFO                   1
+#define FE_MM_RW_SYNC                     2
+
+#define FE_SYNC_CHANNEL          1
+#define FE_SYNC_W_GENERIC_MONIT	 2
+#define FE_SYNC_COMPONENT_ACCESS 3
+
+#define FE_MM_R_CHANNEL_SEARCH_STATE      3
+#define FE_MM_R_CHANNEL_UNION_CONTEXT     4
+#define FE_MM_R_FE_INFO                   5
+#define FE_MM_R_FE_MONITOR                6
+
+#define FE_MM_W_CHANNEL_HEAD              7
+#define FE_MM_W_CHANNEL_UNION             8
+#define FE_MM_W_CHANNEL_CONTEXT           9
+#define FE_MM_R_CHANNEL_UNION            10
+#define FE_MM_R_CHANNEL_CONTEXT          11
+#define FE_MM_R_CHANNEL_TUNE_STATE       12
+
+#define FE_MM_R_GENERIC_MONITORING_SIZE	 13
+#define FE_MM_W_GENERIC_MONITORING	     14
+#define FE_MM_R_GENERIC_MONITORING	     15
+
+#define FE_MM_W_COMPONENT_ACCESS         16
+#define FE_MM_RW_COMPONENT_ACCESS_BUFFER 17
+static int dib9000_risc_apb_access_read(struct dib9000_state *state, u32 address, u16 attribute, const u8 * tx, u32 txlen, u8 * b, u32 len);
+static int dib9000_risc_apb_access_write(struct dib9000_state *state, u32 address, u16 attribute, const u8 * b, u32 len);
+
+static u16 to_fw_output_mode(u16 mode)
+{
+	switch (mode) {
+	case OUTMODE_HIGH_Z:
+		return 0;
+	case OUTMODE_MPEG2_PAR_GATED_CLK:
+		return 4;
+	case OUTMODE_MPEG2_PAR_CONT_CLK:
+		return 8;
+	case OUTMODE_MPEG2_SERIAL:
+		return 16;
+	case OUTMODE_DIVERSITY:
+		return 128;
+	case OUTMODE_MPEG2_FIFO:
+		return 2;
+	case OUTMODE_ANALOG_ADC:
+		return 1;
+	default:
+		return 0;
+	}
+}
+
+static u16 dib9000_read16_attr(struct dib9000_state *state, u16 reg, u8 * b, u32 len, u16 attribute)
+{
+	u32 chunk_size = 126;
+	u32 l;
+	int ret;
+
+	if (state->platform.risc.fw_is_running && (reg < 1024))
+		return dib9000_risc_apb_access_read(state, reg, attribute, NULL, 0, b, len);
+
+	memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
+	state->msg[0].addr = state->i2c.i2c_addr >> 1;
+	state->msg[0].flags = 0;
+	state->msg[0].buf = state->i2c_write_buffer;
+	state->msg[0].len = 2;
+	state->msg[1].addr = state->i2c.i2c_addr >> 1;
+	state->msg[1].flags = I2C_M_RD;
+	state->msg[1].buf = b;
+	state->msg[1].len = len;
+
+	state->i2c_write_buffer[0] = reg >> 8;
+	state->i2c_write_buffer[1] = reg & 0xff;
+
+	if (attribute & DATA_BUS_ACCESS_MODE_8BIT)
+		state->i2c_write_buffer[0] |= (1 << 5);
+	if (attribute & DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT)
+		state->i2c_write_buffer[0] |= (1 << 4);
+
+	do {
+		l = len < chunk_size ? len : chunk_size;
+		state->msg[1].len = l;
+		state->msg[1].buf = b;
+		ret = i2c_transfer(state->i2c.i2c_adap, state->msg, 2) != 2 ? -EREMOTEIO : 0;
+		if (ret != 0) {
+			dprintk("i2c read error on %d", reg);
+			return -EREMOTEIO;
+		}
+
+		b += l;
+		len -= l;
+
+		if (!(attribute & DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT))
+			reg += l / 2;
+	} while ((ret == 0) && len);
+
+	return 0;
+}
+
+static u16 dib9000_i2c_read16(struct i2c_device *i2c, u16 reg)
+{
+	struct i2c_msg msg[2] = {
+		{.addr = i2c->i2c_addr >> 1, .flags = 0,
+			.buf = i2c->i2c_write_buffer, .len = 2},
+		{.addr = i2c->i2c_addr >> 1, .flags = I2C_M_RD,
+			.buf = i2c->i2c_read_buffer, .len = 2},
+	};
+
+	i2c->i2c_write_buffer[0] = reg >> 8;
+	i2c->i2c_write_buffer[1] = reg & 0xff;
+
+	if (i2c_transfer(i2c->i2c_adap, msg, 2) != 2) {
+		dprintk("read register %x error", reg);
+		return 0;
+	}
+
+	return (i2c->i2c_read_buffer[0] << 8) | i2c->i2c_read_buffer[1];
+}
+
+static inline u16 dib9000_read_word(struct dib9000_state *state, u16 reg)
+{
+	if (dib9000_read16_attr(state, reg, state->i2c_read_buffer, 2, 0) != 0)
+		return 0;
+	return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
+}
+
+static inline u16 dib9000_read_word_attr(struct dib9000_state *state, u16 reg, u16 attribute)
+{
+	if (dib9000_read16_attr(state, reg, state->i2c_read_buffer, 2,
+				attribute) != 0)
+		return 0;
+	return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
+}
+
+#define dib9000_read16_noinc_attr(state, reg, b, len, attribute) dib9000_read16_attr(state, reg, b, len, (attribute) | DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT)
+
+static u16 dib9000_write16_attr(struct dib9000_state *state, u16 reg, const u8 * buf, u32 len, u16 attribute)
+{
+	u32 chunk_size = 126;
+	u32 l;
+	int ret;
+
+	if (state->platform.risc.fw_is_running && (reg < 1024)) {
+		if (dib9000_risc_apb_access_write
+		    (state, reg, DATA_BUS_ACCESS_MODE_16BIT | DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT | attribute, buf, len) != 0)
+			return -EINVAL;
+		return 0;
+	}
+
+	memset(&state->msg[0], 0, sizeof(struct i2c_msg));
+	state->msg[0].addr = state->i2c.i2c_addr >> 1;
+	state->msg[0].flags = 0;
+	state->msg[0].buf = state->i2c_write_buffer;
+	state->msg[0].len = len + 2;
+
+	state->i2c_write_buffer[0] = (reg >> 8) & 0xff;
+	state->i2c_write_buffer[1] = (reg) & 0xff;
+
+	if (attribute & DATA_BUS_ACCESS_MODE_8BIT)
+		state->i2c_write_buffer[0] |= (1 << 5);
+	if (attribute & DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT)
+		state->i2c_write_buffer[0] |= (1 << 4);
+
+	do {
+		l = len < chunk_size ? len : chunk_size;
+		state->msg[0].len = l + 2;
+		memcpy(&state->i2c_write_buffer[2], buf, l);
+
+		ret = i2c_transfer(state->i2c.i2c_adap, state->msg, 1) != 1 ? -EREMOTEIO : 0;
+
+		buf += l;
+		len -= l;
+
+		if (!(attribute & DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT))
+			reg += l / 2;
+	} while ((ret == 0) && len);
+
+	return ret;
+}
+
+static int dib9000_i2c_write16(struct i2c_device *i2c, u16 reg, u16 val)
+{
+	struct i2c_msg msg = {
+		.addr = i2c->i2c_addr >> 1, .flags = 0,
+		.buf = i2c->i2c_write_buffer, .len = 4
+	};
+
+	i2c->i2c_write_buffer[0] = (reg >> 8) & 0xff;
+	i2c->i2c_write_buffer[1] = reg & 0xff;
+	i2c->i2c_write_buffer[2] = (val >> 8) & 0xff;
+	i2c->i2c_write_buffer[3] = val & 0xff;
+
+	return i2c_transfer(i2c->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
+}
+
+static inline int dib9000_write_word(struct dib9000_state *state, u16 reg, u16 val)
+{
+	u8 b[2] = { val >> 8, val & 0xff };
+	return dib9000_write16_attr(state, reg, b, 2, 0);
+}
+
+static inline int dib9000_write_word_attr(struct dib9000_state *state, u16 reg, u16 val, u16 attribute)
+{
+	u8 b[2] = { val >> 8, val & 0xff };
+	return dib9000_write16_attr(state, reg, b, 2, attribute);
+}
+
+#define dib9000_write(state, reg, buf, len) dib9000_write16_attr(state, reg, buf, len, 0)
+#define dib9000_write16_noinc(state, reg, buf, len) dib9000_write16_attr(state, reg, buf, len, DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT)
+#define dib9000_write16_noinc_attr(state, reg, buf, len, attribute) dib9000_write16_attr(state, reg, buf, len, DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT | (attribute))
+
+#define dib9000_mbx_send(state, id, data, len) dib9000_mbx_send_attr(state, id, data, len, 0)
+#define dib9000_mbx_get_message(state, id, msg, len) dib9000_mbx_get_message_attr(state, id, msg, len, 0)
+
+#define MAC_IRQ      (1 << 1)
+#define IRQ_POL_MSK  (1 << 4)
+
+#define dib9000_risc_mem_read_chunks(state, b, len) dib9000_read16_attr(state, 1063, b, len, DATA_BUS_ACCESS_MODE_8BIT | DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT)
+#define dib9000_risc_mem_write_chunks(state, buf, len) dib9000_write16_attr(state, 1063, buf, len, DATA_BUS_ACCESS_MODE_8BIT | DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT)
+
+static void dib9000_risc_mem_setup_cmd(struct dib9000_state *state, u32 addr, u32 len, u8 reading)
+{
+	u8 b[14] = { 0 };
+
+/*      dprintk("%d memcmd: %d %d %d\n", state->fe_id, addr, addr+len, len); */
+/*      b[0] = 0 << 7; */
+	b[1] = 1;
+
+/*      b[2] = 0; */
+/*      b[3] = 0; */
+	b[4] = (u8) (addr >> 8);
+	b[5] = (u8) (addr & 0xff);
+
+/*      b[10] = 0; */
+/*      b[11] = 0; */
+	b[12] = (u8) (addr >> 8);
+	b[13] = (u8) (addr & 0xff);
+
+	addr += len;
+/*      b[6] = 0; */
+/*      b[7] = 0; */
+	b[8] = (u8) (addr >> 8);
+	b[9] = (u8) (addr & 0xff);
+
+	dib9000_write(state, 1056, b, 14);
+	if (reading)
+		dib9000_write_word(state, 1056, (1 << 15) | 1);
+	state->platform.risc.memcmd = -1;	/* if it was called directly reset it - to force a future setup-call to set it */
+}
+
+static void dib9000_risc_mem_setup(struct dib9000_state *state, u8 cmd)
+{
+	struct dib9000_fe_memory_map *m = &state->platform.risc.fe_mm[cmd & 0x7f];
+	/* decide whether we need to "refresh" the memory controller */
+	if (state->platform.risc.memcmd == cmd &&	/* same command */
+	    !(cmd & 0x80 && m->size < 67))	/* and we do not want to read something with less than 67 bytes looping - working around a bug in the memory controller */
+		return;
+	dib9000_risc_mem_setup_cmd(state, m->addr, m->size, cmd & 0x80);
+	state->platform.risc.memcmd = cmd;
+}
+
+static int dib9000_risc_mem_read(struct dib9000_state *state, u8 cmd, u8 * b, u16 len)
+{
+	if (!state->platform.risc.fw_is_running)
+		return -EIO;
+
+	if (mutex_lock_interruptible(&state->platform.risc.mem_lock) < 0) {
+		dprintk("could not get the lock");
+		return -EINTR;
+	}
+	dib9000_risc_mem_setup(state, cmd | 0x80);
+	dib9000_risc_mem_read_chunks(state, b, len);
+	mutex_unlock(&state->platform.risc.mem_lock);
+	return 0;
+}
+
+static int dib9000_risc_mem_write(struct dib9000_state *state, u8 cmd, const u8 * b)
+{
+	struct dib9000_fe_memory_map *m = &state->platform.risc.fe_mm[cmd];
+	if (!state->platform.risc.fw_is_running)
+		return -EIO;
+
+	if (mutex_lock_interruptible(&state->platform.risc.mem_lock) < 0) {
+		dprintk("could not get the lock");
+		return -EINTR;
+	}
+	dib9000_risc_mem_setup(state, cmd);
+	dib9000_risc_mem_write_chunks(state, b, m->size);
+	mutex_unlock(&state->platform.risc.mem_lock);
+	return 0;
+}
+
+static int dib9000_firmware_download(struct dib9000_state *state, u8 risc_id, u16 key, const u8 * code, u32 len)
+{
+	u16 offs;
+
+	if (risc_id == 1)
+		offs = 16;
+	else
+		offs = 0;
+
+	/* config crtl reg */
+	dib9000_write_word(state, 1024 + offs, 0x000f);
+	dib9000_write_word(state, 1025 + offs, 0);
+	dib9000_write_word(state, 1031 + offs, key);
+
+	dprintk("going to download %dB of microcode", len);
+	if (dib9000_write16_noinc(state, 1026 + offs, (u8 *) code, (u16) len) != 0) {
+		dprintk("error while downloading microcode for RISC %c", 'A' + risc_id);
+		return -EIO;
+	}
+
+	dprintk("Microcode for RISC %c loaded", 'A' + risc_id);
+
+	return 0;
+}
+
+static int dib9000_mbx_host_init(struct dib9000_state *state, u8 risc_id)
+{
+	u16 mbox_offs;
+	u16 reset_reg;
+	u16 tries = 1000;
+
+	if (risc_id == 1)
+		mbox_offs = 16;
+	else
+		mbox_offs = 0;
+
+	/* Reset mailbox  */
+	dib9000_write_word(state, 1027 + mbox_offs, 0x8000);
+
+	/* Read reset status */
+	do {
+		reset_reg = dib9000_read_word(state, 1027 + mbox_offs);
+		msleep(100);
+	} while ((reset_reg & 0x8000) && --tries);
+
+	if (reset_reg & 0x8000) {
+		dprintk("MBX: init ERROR, no response from RISC %c", 'A' + risc_id);
+		return -EIO;
+	}
+	dprintk("MBX: initialized");
+	return 0;
+}
+
+#define MAX_MAILBOX_TRY 100
+static int dib9000_mbx_send_attr(struct dib9000_state *state, u8 id, u16 * data, u8 len, u16 attr)
+{
+	u8 *d, b[2];
+	u16 tmp;
+	u16 size;
+	u32 i;
+	int ret = 0;
+
+	if (!state->platform.risc.fw_is_running)
+		return -EINVAL;
+
+	if (mutex_lock_interruptible(&state->platform.risc.mbx_if_lock) < 0) {
+		dprintk("could not get the lock");
+		return -EINTR;
+	}
+	tmp = MAX_MAILBOX_TRY;
+	do {
+		size = dib9000_read_word_attr(state, 1043, attr) & 0xff;
+		if ((size + len + 1) > MBX_MAX_WORDS && --tmp) {
+			dprintk("MBX: RISC mbx full, retrying");
+			msleep(100);
+		} else
+			break;
+	} while (1);
+
+	/*dprintk( "MBX: size: %d", size); */
+
+	if (tmp == 0) {
+		ret = -EINVAL;
+		goto out;
+	}
+#ifdef DUMP_MSG
+	dprintk("--> %02x %d ", id, len + 1);
+	for (i = 0; i < len; i++)
+		dprintk("%04x ", data[i]);
+	dprintk("\n");
+#endif
+
+	/* byte-order conversion - works on big (where it is not necessary) or little endian */
+	d = (u8 *) data;
+	for (i = 0; i < len; i++) {
+		tmp = data[i];
+		*d++ = tmp >> 8;
+		*d++ = tmp & 0xff;
+	}
+
+	/* write msg */
+	b[0] = id;
+	b[1] = len + 1;
+	if (dib9000_write16_noinc_attr(state, 1045, b, 2, attr) != 0 || dib9000_write16_noinc_attr(state, 1045, (u8 *) data, len * 2, attr) != 0) {
+		ret = -EIO;
+		goto out;
+	}
+
+	/* update register nb_mes_in_RX */
+	ret = (u8) dib9000_write_word_attr(state, 1043, 1 << 14, attr);
+
+out:
+	mutex_unlock(&state->platform.risc.mbx_if_lock);
+
+	return ret;
+}
+
+static u8 dib9000_mbx_read(struct dib9000_state *state, u16 * data, u8 risc_id, u16 attr)
+{
+#ifdef DUMP_MSG
+	u16 *d = data;
+#endif
+
+	u16 tmp, i;
+	u8 size;
+	u8 mc_base;
+
+	if (!state->platform.risc.fw_is_running)
+		return 0;
+
+	if (mutex_lock_interruptible(&state->platform.risc.mbx_if_lock) < 0) {
+		dprintk("could not get the lock");
+		return 0;
+	}
+	if (risc_id == 1)
+		mc_base = 16;
+	else
+		mc_base = 0;
+
+	/* Length and type in the first word */
+	*data = dib9000_read_word_attr(state, 1029 + mc_base, attr);
+
+	size = *data & 0xff;
+	if (size <= MBX_MAX_WORDS) {
+		data++;
+		size--;		/* Initial word already read */
+
+		dib9000_read16_noinc_attr(state, 1029 + mc_base, (u8 *) data, size * 2, attr);
+
+		/* to word conversion */
+		for (i = 0; i < size; i++) {
+			tmp = *data;
+			*data = (tmp >> 8) | (tmp << 8);
+			data++;
+		}
+
+#ifdef DUMP_MSG
+		dprintk("<-- ");
+		for (i = 0; i < size + 1; i++)
+			dprintk("%04x ", d[i]);
+		dprintk("\n");
+#endif
+	} else {
+		dprintk("MBX: message is too big for message cache (%d), flushing message", size);
+		size--;		/* Initial word already read */
+		while (size--)
+			dib9000_read16_noinc_attr(state, 1029 + mc_base, (u8 *) data, 2, attr);
+	}
+	/* Update register nb_mes_in_TX */
+	dib9000_write_word_attr(state, 1028 + mc_base, 1 << 14, attr);
+
+	mutex_unlock(&state->platform.risc.mbx_if_lock);
+
+	return size + 1;
+}
+
+static int dib9000_risc_debug_buf(struct dib9000_state *state, u16 * data, u8 size)
+{
+	u32 ts = data[1] << 16 | data[0];
+	char *b = (char *)&data[2];
+
+	b[2 * (size - 2) - 1] = '\0';	/* Bullet proof the buffer */
+	if (*b == '~') {
+		b++;
+		dprintk(b);
+	} else
+		dprintk("RISC%d: %d.%04d %s", state->fe_id, ts / 10000, ts % 10000, *b ? b : "<emtpy>");
+	return 1;
+}
+
+static int dib9000_mbx_fetch_to_cache(struct dib9000_state *state, u16 attr)
+{
+	int i;
+	u8 size;
+	u16 *block;
+	/* find a free slot */
+	for (i = 0; i < DIB9000_MSG_CACHE_SIZE; i++) {
+		block = state->platform.risc.message_cache[i];
+		if (*block == 0) {
+			size = dib9000_mbx_read(state, block, 1, attr);
+
+/*                      dprintk( "MBX: fetched %04x message to cache", *block); */
+
+			switch (*block >> 8) {
+			case IN_MSG_DEBUG_BUF:
+				dib9000_risc_debug_buf(state, block + 1, size);	/* debug-messages are going to be printed right away */
+				*block = 0;	/* free the block */
+				break;
+#if 0
+			case IN_MSG_DATA:	/* FE-TRACE */
+				dib9000_risc_data_process(state, block + 1, size);
+				*block = 0;
+				break;
+#endif
+			default:
+				break;
+			}
+
+			return 1;
+		}
+	}
+	dprintk("MBX: no free cache-slot found for new message...");
+	return -1;
+}
+
+static u8 dib9000_mbx_count(struct dib9000_state *state, u8 risc_id, u16 attr)
+{
+	if (risc_id == 0)
+		return (u8) (dib9000_read_word_attr(state, 1028, attr) >> 10) & 0x1f;	/* 5 bit field */
+	else
+		return (u8) (dib9000_read_word_attr(state, 1044, attr) >> 8) & 0x7f;	/* 7 bit field */
+}
+
+static int dib9000_mbx_process(struct dib9000_state *state, u16 attr)
+{
+	int ret = 0;
+
+	if (!state->platform.risc.fw_is_running)
+		return -1;
+
+	if (mutex_lock_interruptible(&state->platform.risc.mbx_lock) < 0) {
+		dprintk("could not get the lock");
+		return -1;
+	}
+
+	if (dib9000_mbx_count(state, 1, attr))	/* 1=RiscB */
+		ret = dib9000_mbx_fetch_to_cache(state, attr);
+
+	dib9000_read_word_attr(state, 1229, attr);	/* Clear the IRQ */
+/*      if (tmp) */
+/*              dprintk( "cleared IRQ: %x", tmp); */
+	mutex_unlock(&state->platform.risc.mbx_lock);
+
+	return ret;
+}
+
+static int dib9000_mbx_get_message_attr(struct dib9000_state *state, u16 id, u16 * msg, u8 * size, u16 attr)
+{
+	u8 i;
+	u16 *block;
+	u16 timeout = 30;
+
+	*msg = 0;
+	do {
+		/* dib9000_mbx_get_from_cache(); */
+		for (i = 0; i < DIB9000_MSG_CACHE_SIZE; i++) {
+			block = state->platform.risc.message_cache[i];
+			if ((*block >> 8) == id) {
+				*size = (*block & 0xff) - 1;
+				memcpy(msg, block + 1, (*size) * 2);
+				*block = 0;	/* free the block */
+				i = 0;	/* signal that we found a message */
+				break;
+			}
+		}
+
+		if (i == 0)
+			break;
+
+		if (dib9000_mbx_process(state, attr) == -1)	/* try to fetch one message - if any */
+			return -1;
+
+	} while (--timeout);
+
+	if (timeout == 0) {
+		dprintk("waiting for message %d timed out", id);
+		return -1;
+	}
+
+	return i == 0;
+}
+
+static int dib9000_risc_check_version(struct dib9000_state *state)
+{
+	u8 r[4];
+	u8 size;
+	u16 fw_version = 0;
+
+	if (dib9000_mbx_send(state, OUT_MSG_REQ_VERSION, &fw_version, 1) != 0)
+		return -EIO;
+
+	if (dib9000_mbx_get_message(state, IN_MSG_VERSION, (u16 *) r, &size) < 0)
+		return -EIO;
+
+	fw_version = (r[0] << 8) | r[1];
+	dprintk("RISC: ver: %d.%02d (IC: %d)", fw_version >> 10, fw_version & 0x3ff, (r[2] << 8) | r[3]);
+
+	if ((fw_version >> 10) != 7)
+		return -EINVAL;
+
+	switch (fw_version & 0x3ff) {
+	case 11:
+	case 12:
+	case 14:
+	case 15:
+	case 16:
+	case 17:
+		break;
+	default:
+		dprintk("RISC: invalid firmware version");
+		return -EINVAL;
+	}
+
+	dprintk("RISC: valid firmware version");
+	return 0;
+}
+
+static int dib9000_fw_boot(struct dib9000_state *state, const u8 * codeA, u32 lenA, const u8 * codeB, u32 lenB)
+{
+	/* Reconfig pool mac ram */
+	dib9000_write_word(state, 1225, 0x02);	/* A: 8k C, 4 k D - B: 32k C 6 k D - IRAM 96k */
+	dib9000_write_word(state, 1226, 0x05);
+
+	/* Toggles IP crypto to Host APB interface. */
+	dib9000_write_word(state, 1542, 1);
+
+	/* Set jump and no jump in the dma box */
+	dib9000_write_word(state, 1074, 0);
+	dib9000_write_word(state, 1075, 0);
+
+	/* Set MAC as APB Master. */
+	dib9000_write_word(state, 1237, 0);
+
+	/* Reset the RISCs */
+	if (codeA != NULL)
+		dib9000_write_word(state, 1024, 2);
+	else
+		dib9000_write_word(state, 1024, 15);
+	if (codeB != NULL)
+		dib9000_write_word(state, 1040, 2);
+
+	if (codeA != NULL)
+		dib9000_firmware_download(state, 0, 0x1234, codeA, lenA);
+	if (codeB != NULL)
+		dib9000_firmware_download(state, 1, 0x1234, codeB, lenB);
+
+	/* Run the RISCs */
+	if (codeA != NULL)
+		dib9000_write_word(state, 1024, 0);
+	if (codeB != NULL)
+		dib9000_write_word(state, 1040, 0);
+
+	if (codeA != NULL)
+		if (dib9000_mbx_host_init(state, 0) != 0)
+			return -EIO;
+	if (codeB != NULL)
+		if (dib9000_mbx_host_init(state, 1) != 0)
+			return -EIO;
+
+	msleep(100);
+	state->platform.risc.fw_is_running = 1;
+
+	if (dib9000_risc_check_version(state) != 0)
+		return -EINVAL;
+
+	state->platform.risc.memcmd = 0xff;
+	return 0;
+}
+
+static u16 dib9000_identify(struct i2c_device *client)
+{
+	u16 value;
+
+	value = dib9000_i2c_read16(client, 896);
+	if (value != 0x01b3) {
+		dprintk("wrong Vendor ID (0x%x)", value);
+		return 0;
+	}
+
+	value = dib9000_i2c_read16(client, 897);
+	if (value != 0x4000 && value != 0x4001 && value != 0x4002 && value != 0x4003 && value != 0x4004 && value != 0x4005) {
+		dprintk("wrong Device ID (0x%x)", value);
+		return 0;
+	}
+
+	/* protect this driver to be used with 7000PC */
+	if (value == 0x4000 && dib9000_i2c_read16(client, 769) == 0x4000) {
+		dprintk("this driver does not work with DiB7000PC");
+		return 0;
+	}
+
+	switch (value) {
+	case 0x4000:
+		dprintk("found DiB7000MA/PA/MB/PB");
+		break;
+	case 0x4001:
+		dprintk("found DiB7000HC");
+		break;
+	case 0x4002:
+		dprintk("found DiB7000MC");
+		break;
+	case 0x4003:
+		dprintk("found DiB9000A");
+		break;
+	case 0x4004:
+		dprintk("found DiB9000H");
+		break;
+	case 0x4005:
+		dprintk("found DiB9000M");
+		break;
+	}
+
+	return value;
+}
+
+static void dib9000_set_power_mode(struct dib9000_state *state, enum dib9000_power_mode mode)
+{
+	/* by default everything is going to be powered off */
+	u16 reg_903 = 0x3fff, reg_904 = 0xffff, reg_905 = 0xffff, reg_906;
+	u8 offset;
+
+	if (state->revision == 0x4003 || state->revision == 0x4004 || state->revision == 0x4005)
+		offset = 1;
+	else
+		offset = 0;
+
+	reg_906 = dib9000_read_word(state, 906 + offset) | 0x3;	/* keep settings for RISC */
+
+	/* now, depending on the requested mode, we power on */
+	switch (mode) {
+		/* power up everything in the demod */
+	case DIB9000_POWER_ALL:
+		reg_903 = 0x0000;
+		reg_904 = 0x0000;
+		reg_905 = 0x0000;
+		reg_906 = 0x0000;
+		break;
+
+		/* just leave power on the control-interfaces: GPIO and (I2C or SDIO or SRAM) */
+	case DIB9000_POWER_INTERFACE_ONLY:	/* TODO power up either SDIO or I2C or SRAM */
+		reg_905 &= ~((1 << 7) | (1 << 6) | (1 << 5) | (1 << 2));
+		break;
+
+	case DIB9000_POWER_INTERF_ANALOG_AGC:
+		reg_903 &= ~((1 << 15) | (1 << 14) | (1 << 11) | (1 << 10));
+		reg_905 &= ~((1 << 7) | (1 << 6) | (1 << 5) | (1 << 4) | (1 << 2));
+		reg_906 &= ~((1 << 0));
+		break;
+
+	case DIB9000_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD:
+		reg_903 = 0x0000;
+		reg_904 = 0x801f;
+		reg_905 = 0x0000;
+		reg_906 &= ~((1 << 0));
+		break;
+
+	case DIB9000_POWER_COR4_CRY_ESRAM_MOUT_NUD:
+		reg_903 = 0x0000;
+		reg_904 = 0x8000;
+		reg_905 = 0x010b;
+		reg_906 &= ~((1 << 0));
+		break;
+	default:
+	case DIB9000_POWER_NO:
+		break;
+	}
+
+	/* always power down unused parts */
+	if (!state->platform.host.mobile_mode)
+		reg_904 |= (1 << 7) | (1 << 6) | (1 << 4) | (1 << 2) | (1 << 1);
+
+	/* P_sdio_select_clk = 0 on MC and after */
+	if (state->revision != 0x4000)
+		reg_906 <<= 1;
+
+	dib9000_write_word(state, 903 + offset, reg_903);
+	dib9000_write_word(state, 904 + offset, reg_904);
+	dib9000_write_word(state, 905 + offset, reg_905);
+	dib9000_write_word(state, 906 + offset, reg_906);
+}
+
+static int dib9000_fw_reset(struct dvb_frontend *fe)
+{
+	struct dib9000_state *state = fe->demodulator_priv;
+
+	dib9000_write_word(state, 1817, 0x0003);
+
+	dib9000_write_word(state, 1227, 1);
+	dib9000_write_word(state, 1227, 0);
+
+	switch ((state->revision = dib9000_identify(&state->i2c))) {
+	case 0x4003:
+	case 0x4004:
+	case 0x4005:
+		state->reg_offs = 1;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* reset the i2c-master to use the host interface */
+	dibx000_reset_i2c_master(&state->i2c_master);
+
+	dib9000_set_power_mode(state, DIB9000_POWER_ALL);
+
+	/* unforce divstr regardless whether i2c enumeration was done or not */
+	dib9000_write_word(state, 1794, dib9000_read_word(state, 1794) & ~(1 << 1));
+	dib9000_write_word(state, 1796, 0);
+	dib9000_write_word(state, 1805, 0x805);
+
+	/* restart all parts */
+	dib9000_write_word(state, 898, 0xffff);
+	dib9000_write_word(state, 899, 0xffff);
+	dib9000_write_word(state, 900, 0x0001);
+	dib9000_write_word(state, 901, 0xff19);
+	dib9000_write_word(state, 902, 0x003c);
+
+	dib9000_write_word(state, 898, 0);
+	dib9000_write_word(state, 899, 0);
+	dib9000_write_word(state, 900, 0);
+	dib9000_write_word(state, 901, 0);
+	dib9000_write_word(state, 902, 0);
+
+	dib9000_write_word(state, 911, state->chip.d9.cfg.if_drives);
+
+	dib9000_set_power_mode(state, DIB9000_POWER_INTERFACE_ONLY);
+
+	return 0;
+}
+
+static int dib9000_risc_apb_access_read(struct dib9000_state *state, u32 address, u16 attribute, const u8 * tx, u32 txlen, u8 * b, u32 len)
+{
+	u16 mb[10];
+	u8 i, s;
+
+	if (address >= 1024 || !state->platform.risc.fw_is_running)
+		return -EINVAL;
+
+	/* dprintk( "APB access thru rd fw %d %x", address, attribute); */
+
+	mb[0] = (u16) address;
+	mb[1] = len / 2;
+	dib9000_mbx_send_attr(state, OUT_MSG_BRIDGE_APB_R, mb, 2, attribute);
+	switch (dib9000_mbx_get_message_attr(state, IN_MSG_END_BRIDGE_APB_RW, mb, &s, attribute)) {
+	case 1:
+		s--;
+		for (i = 0; i < s; i++) {
+			b[i * 2] = (mb[i + 1] >> 8) & 0xff;
+			b[i * 2 + 1] = (mb[i + 1]) & 0xff;
+		}
+		return 0;
+	default:
+		return -EIO;
+	}
+	return -EIO;
+}
+
+static int dib9000_risc_apb_access_write(struct dib9000_state *state, u32 address, u16 attribute, const u8 * b, u32 len)
+{
+	u16 mb[10];
+	u8 s, i;
+
+	if (address >= 1024 || !state->platform.risc.fw_is_running)
+		return -EINVAL;
+
+	/* dprintk( "APB access thru wr fw %d %x", address, attribute); */
+
+	mb[0] = (unsigned short)address;
+	for (i = 0; i < len && i < 20; i += 2)
+		mb[1 + (i / 2)] = (b[i] << 8 | b[i + 1]);
+
+	dib9000_mbx_send_attr(state, OUT_MSG_BRIDGE_APB_W, mb, 1 + len / 2, attribute);
+	return dib9000_mbx_get_message_attr(state, IN_MSG_END_BRIDGE_APB_RW, mb, &s, attribute) == 1 ? 0 : -EINVAL;
+}
+
+static int dib9000_fw_memmbx_sync(struct dib9000_state *state, u8 i)
+{
+	u8 index_loop = 10;
+
+	if (!state->platform.risc.fw_is_running)
+		return 0;
+	dib9000_risc_mem_write(state, FE_MM_RW_SYNC, &i);
+	do {
+		dib9000_risc_mem_read(state, FE_MM_RW_SYNC, state->i2c_read_buffer, 1);
+	} while (state->i2c_read_buffer[0] && index_loop--);
+
+	if (index_loop > 0)
+		return 0;
+	return -EIO;
+}
+
+static int dib9000_fw_init(struct dib9000_state *state)
+{
+	struct dibGPIOFunction *f;
+	u16 b[40] = { 0 };
+	u8 i;
+	u8 size;
+
+	if (dib9000_fw_boot(state, NULL, 0, state->chip.d9.cfg.microcode_B_fe_buffer, state->chip.d9.cfg.microcode_B_fe_size) != 0)
+		return -EIO;
+
+	/* initialize the firmware */
+	for (i = 0; i < ARRAY_SIZE(state->chip.d9.cfg.gpio_function); i++) {
+		f = &state->chip.d9.cfg.gpio_function[i];
+		if (f->mask) {
+			switch (f->function) {
+			case BOARD_GPIO_FUNCTION_COMPONENT_ON:
+				b[0] = (u16) f->mask;
+				b[1] = (u16) f->direction;
+				b[2] = (u16) f->value;
+				break;
+			case BOARD_GPIO_FUNCTION_COMPONENT_OFF:
+				b[3] = (u16) f->mask;
+				b[4] = (u16) f->direction;
+				b[5] = (u16) f->value;
+				break;
+			}
+		}
+	}
+	if (dib9000_mbx_send(state, OUT_MSG_CONF_GPIO, b, 15) != 0)
+		return -EIO;
+
+	/* subband */
+	b[0] = state->chip.d9.cfg.subband.size;	/* type == 0 -> GPIO - PWM not yet supported */
+	for (i = 0; i < state->chip.d9.cfg.subband.size; i++) {
+		b[1 + i * 4] = state->chip.d9.cfg.subband.subband[i].f_mhz;
+		b[2 + i * 4] = (u16) state->chip.d9.cfg.subband.subband[i].gpio.mask;
+		b[3 + i * 4] = (u16) state->chip.d9.cfg.subband.subband[i].gpio.direction;
+		b[4 + i * 4] = (u16) state->chip.d9.cfg.subband.subband[i].gpio.value;
+	}
+	b[1 + i * 4] = 0;	/* fe_id */
+	if (dib9000_mbx_send(state, OUT_MSG_SUBBAND_SEL, b, 2 + 4 * i) != 0)
+		return -EIO;
+
+	/* 0 - id, 1 - no_of_frontends */
+	b[0] = (0 << 8) | 1;
+	/* 0 = i2c-address demod, 0 = tuner */
+	b[1] = (0 << 8) | (0);
+	b[2] = (u16) (((state->chip.d9.cfg.xtal_clock_khz * 1000) >> 16) & 0xffff);
+	b[3] = (u16) (((state->chip.d9.cfg.xtal_clock_khz * 1000)) & 0xffff);
+	b[4] = (u16) ((state->chip.d9.cfg.vcxo_timer >> 16) & 0xffff);
+	b[5] = (u16) ((state->chip.d9.cfg.vcxo_timer) & 0xffff);
+	b[6] = (u16) ((state->chip.d9.cfg.timing_frequency >> 16) & 0xffff);
+	b[7] = (u16) ((state->chip.d9.cfg.timing_frequency) & 0xffff);
+	b[29] = state->chip.d9.cfg.if_drives;
+	if (dib9000_mbx_send(state, OUT_MSG_INIT_DEMOD, b, ARRAY_SIZE(b)) != 0)
+		return -EIO;
+
+	if (dib9000_mbx_send(state, OUT_MSG_FE_FW_DL, NULL, 0) != 0)
+		return -EIO;
+
+	if (dib9000_mbx_get_message(state, IN_MSG_FE_FW_DL_DONE, b, &size) < 0)
+		return -EIO;
+
+	if (size > ARRAY_SIZE(b)) {
+		dprintk("error : firmware returned %dbytes needed but the used buffer has only %dbytes\n Firmware init ABORTED", size,
+			(int)ARRAY_SIZE(b));
+		return -EINVAL;
+	}
+
+	for (i = 0; i < size; i += 2) {
+		state->platform.risc.fe_mm[i / 2].addr = b[i + 0];
+		state->platform.risc.fe_mm[i / 2].size = b[i + 1];
+	}
+
+	return 0;
+}
+
+static void dib9000_fw_set_channel_head(struct dib9000_state *state)
+{
+	u8 b[9];
+	u32 freq = state->fe[0]->dtv_property_cache.frequency / 1000;
+	if (state->fe_id % 2)
+		freq += 101;
+
+	b[0] = (u8) ((freq >> 0) & 0xff);
+	b[1] = (u8) ((freq >> 8) & 0xff);
+	b[2] = (u8) ((freq >> 16) & 0xff);
+	b[3] = (u8) ((freq >> 24) & 0xff);
+	b[4] = (u8) ((state->fe[0]->dtv_property_cache.bandwidth_hz / 1000 >> 0) & 0xff);
+	b[5] = (u8) ((state->fe[0]->dtv_property_cache.bandwidth_hz / 1000 >> 8) & 0xff);
+	b[6] = (u8) ((state->fe[0]->dtv_property_cache.bandwidth_hz / 1000 >> 16) & 0xff);
+	b[7] = (u8) ((state->fe[0]->dtv_property_cache.bandwidth_hz / 1000 >> 24) & 0xff);
+	b[8] = 0x80;		/* do not wait for CELL ID when doing autosearch */
+	if (state->fe[0]->dtv_property_cache.delivery_system == SYS_DVBT)
+		b[8] |= 1;
+	dib9000_risc_mem_write(state, FE_MM_W_CHANNEL_HEAD, b);
+}
+
+static int dib9000_fw_get_channel(struct dvb_frontend *fe)
+{
+	struct dib9000_state *state = fe->demodulator_priv;
+	struct dibDVBTChannel {
+		s8 spectrum_inversion;
+
+		s8 nfft;
+		s8 guard;
+		s8 constellation;
+
+		s8 hrch;
+		s8 alpha;
+		s8 code_rate_hp;
+		s8 code_rate_lp;
+		s8 select_hp;
+
+		s8 intlv_native;
+	};
+	struct dibDVBTChannel *ch;
+	int ret = 0;
+
+	if (mutex_lock_interruptible(&state->platform.risc.mem_mbx_lock) < 0) {
+		dprintk("could not get the lock");
+		return -EINTR;
+	}
+	if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) {
+		ret = -EIO;
+		goto error;
+	}
+
+	dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_UNION,
+			state->i2c_read_buffer, sizeof(struct dibDVBTChannel));
+	ch = (struct dibDVBTChannel *)state->i2c_read_buffer;
+
+
+	switch (ch->spectrum_inversion & 0x7) {
+	case 1:
+		state->fe[0]->dtv_property_cache.inversion = INVERSION_ON;
+		break;
+	case 0:
+		state->fe[0]->dtv_property_cache.inversion = INVERSION_OFF;
+		break;
+	default:
+	case -1:
+		state->fe[0]->dtv_property_cache.inversion = INVERSION_AUTO;
+		break;
+	}
+	switch (ch->nfft) {
+	case 0:
+		state->fe[0]->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_2K;
+		break;
+	case 2:
+		state->fe[0]->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_4K;
+		break;
+	case 1:
+		state->fe[0]->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_8K;
+		break;
+	default:
+	case -1:
+		state->fe[0]->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_AUTO;
+		break;
+	}
+	switch (ch->guard) {
+	case 0:
+		state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_32;
+		break;
+	case 1:
+		state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_16;
+		break;
+	case 2:
+		state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_8;
+		break;
+	case 3:
+		state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_4;
+		break;
+	default:
+	case -1:
+		state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_AUTO;
+		break;
+	}
+	switch (ch->constellation) {
+	case 2:
+		state->fe[0]->dtv_property_cache.modulation = QAM_64;
+		break;
+	case 1:
+		state->fe[0]->dtv_property_cache.modulation = QAM_16;
+		break;
+	case 0:
+		state->fe[0]->dtv_property_cache.modulation = QPSK;
+		break;
+	default:
+	case -1:
+		state->fe[0]->dtv_property_cache.modulation = QAM_AUTO;
+		break;
+	}
+	switch (ch->hrch) {
+	case 0:
+		state->fe[0]->dtv_property_cache.hierarchy = HIERARCHY_NONE;
+		break;
+	case 1:
+		state->fe[0]->dtv_property_cache.hierarchy = HIERARCHY_1;
+		break;
+	default:
+	case -1:
+		state->fe[0]->dtv_property_cache.hierarchy = HIERARCHY_AUTO;
+		break;
+	}
+	switch (ch->code_rate_hp) {
+	case 1:
+		state->fe[0]->dtv_property_cache.code_rate_HP = FEC_1_2;
+		break;
+	case 2:
+		state->fe[0]->dtv_property_cache.code_rate_HP = FEC_2_3;
+		break;
+	case 3:
+		state->fe[0]->dtv_property_cache.code_rate_HP = FEC_3_4;
+		break;
+	case 5:
+		state->fe[0]->dtv_property_cache.code_rate_HP = FEC_5_6;
+		break;
+	case 7:
+		state->fe[0]->dtv_property_cache.code_rate_HP = FEC_7_8;
+		break;
+	default:
+	case -1:
+		state->fe[0]->dtv_property_cache.code_rate_HP = FEC_AUTO;
+		break;
+	}
+	switch (ch->code_rate_lp) {
+	case 1:
+		state->fe[0]->dtv_property_cache.code_rate_LP = FEC_1_2;
+		break;
+	case 2:
+		state->fe[0]->dtv_property_cache.code_rate_LP = FEC_2_3;
+		break;
+	case 3:
+		state->fe[0]->dtv_property_cache.code_rate_LP = FEC_3_4;
+		break;
+	case 5:
+		state->fe[0]->dtv_property_cache.code_rate_LP = FEC_5_6;
+		break;
+	case 7:
+		state->fe[0]->dtv_property_cache.code_rate_LP = FEC_7_8;
+		break;
+	default:
+	case -1:
+		state->fe[0]->dtv_property_cache.code_rate_LP = FEC_AUTO;
+		break;
+	}
+
+error:
+	mutex_unlock(&state->platform.risc.mem_mbx_lock);
+	return ret;
+}
+
+static int dib9000_fw_set_channel_union(struct dvb_frontend *fe)
+{
+	struct dib9000_state *state = fe->demodulator_priv;
+	struct dibDVBTChannel {
+		s8 spectrum_inversion;
+
+		s8 nfft;
+		s8 guard;
+		s8 constellation;
+
+		s8 hrch;
+		s8 alpha;
+		s8 code_rate_hp;
+		s8 code_rate_lp;
+		s8 select_hp;
+
+		s8 intlv_native;
+	};
+	struct dibDVBTChannel ch;
+
+	switch (state->fe[0]->dtv_property_cache.inversion) {
+	case INVERSION_ON:
+		ch.spectrum_inversion = 1;
+		break;
+	case INVERSION_OFF:
+		ch.spectrum_inversion = 0;
+		break;
+	default:
+	case INVERSION_AUTO:
+		ch.spectrum_inversion = -1;
+		break;
+	}
+	switch (state->fe[0]->dtv_property_cache.transmission_mode) {
+	case TRANSMISSION_MODE_2K:
+		ch.nfft = 0;
+		break;
+	case TRANSMISSION_MODE_4K:
+		ch.nfft = 2;
+		break;
+	case TRANSMISSION_MODE_8K:
+		ch.nfft = 1;
+		break;
+	default:
+	case TRANSMISSION_MODE_AUTO:
+		ch.nfft = 1;
+		break;
+	}
+	switch (state->fe[0]->dtv_property_cache.guard_interval) {
+	case GUARD_INTERVAL_1_32:
+		ch.guard = 0;
+		break;
+	case GUARD_INTERVAL_1_16:
+		ch.guard = 1;
+		break;
+	case GUARD_INTERVAL_1_8:
+		ch.guard = 2;
+		break;
+	case GUARD_INTERVAL_1_4:
+		ch.guard = 3;
+		break;
+	default:
+	case GUARD_INTERVAL_AUTO:
+		ch.guard = -1;
+		break;
+	}
+	switch (state->fe[0]->dtv_property_cache.modulation) {
+	case QAM_64:
+		ch.constellation = 2;
+		break;
+	case QAM_16:
+		ch.constellation = 1;
+		break;
+	case QPSK:
+		ch.constellation = 0;
+		break;
+	default:
+	case QAM_AUTO:
+		ch.constellation = -1;
+		break;
+	}
+	switch (state->fe[0]->dtv_property_cache.hierarchy) {
+	case HIERARCHY_NONE:
+		ch.hrch = 0;
+		break;
+	case HIERARCHY_1:
+	case HIERARCHY_2:
+	case HIERARCHY_4:
+		ch.hrch = 1;
+		break;
+	default:
+	case HIERARCHY_AUTO:
+		ch.hrch = -1;
+		break;
+	}
+	ch.alpha = 1;
+	switch (state->fe[0]->dtv_property_cache.code_rate_HP) {
+	case FEC_1_2:
+		ch.code_rate_hp = 1;
+		break;
+	case FEC_2_3:
+		ch.code_rate_hp = 2;
+		break;
+	case FEC_3_4:
+		ch.code_rate_hp = 3;
+		break;
+	case FEC_5_6:
+		ch.code_rate_hp = 5;
+		break;
+	case FEC_7_8:
+		ch.code_rate_hp = 7;
+		break;
+	default:
+	case FEC_AUTO:
+		ch.code_rate_hp = -1;
+		break;
+	}
+	switch (state->fe[0]->dtv_property_cache.code_rate_LP) {
+	case FEC_1_2:
+		ch.code_rate_lp = 1;
+		break;
+	case FEC_2_3:
+		ch.code_rate_lp = 2;
+		break;
+	case FEC_3_4:
+		ch.code_rate_lp = 3;
+		break;
+	case FEC_5_6:
+		ch.code_rate_lp = 5;
+		break;
+	case FEC_7_8:
+		ch.code_rate_lp = 7;
+		break;
+	default:
+	case FEC_AUTO:
+		ch.code_rate_lp = -1;
+		break;
+	}
+	ch.select_hp = 1;
+	ch.intlv_native = 1;
+
+	dib9000_risc_mem_write(state, FE_MM_W_CHANNEL_UNION, (u8 *) &ch);
+
+	return 0;
+}
+
+static int dib9000_fw_tune(struct dvb_frontend *fe)
+{
+	struct dib9000_state *state = fe->demodulator_priv;
+	int ret = 10, search = state->channel_status.status == CHANNEL_STATUS_PARAMETERS_UNKNOWN;
+	s8 i;
+
+	switch (state->tune_state) {
+	case CT_DEMOD_START:
+		dib9000_fw_set_channel_head(state);
+
+		/* write the channel context - a channel is initialized to 0, so it is OK */
+		dib9000_risc_mem_write(state, FE_MM_W_CHANNEL_CONTEXT, (u8 *) fe_info);
+		dib9000_risc_mem_write(state, FE_MM_W_FE_INFO, (u8 *) fe_info);
+
+		if (search)
+			dib9000_mbx_send(state, OUT_MSG_FE_CHANNEL_SEARCH, NULL, 0);
+		else {
+			dib9000_fw_set_channel_union(fe);
+			dib9000_mbx_send(state, OUT_MSG_FE_CHANNEL_TUNE, NULL, 0);
+		}
+		state->tune_state = CT_DEMOD_STEP_1;
+		break;
+	case CT_DEMOD_STEP_1:
+		if (search)
+			dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_SEARCH_STATE, state->i2c_read_buffer, 1);
+		else
+			dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_TUNE_STATE, state->i2c_read_buffer, 1);
+		i = (s8)state->i2c_read_buffer[0];
+		switch (i) {	/* something happened */
+		case 0:
+			break;
+		case -2:	/* tps locks are "slower" than MPEG locks -> even in autosearch data is OK here */
+			if (search)
+				state->status = FE_STATUS_DEMOD_SUCCESS;
+			else {
+				state->tune_state = CT_DEMOD_STOP;
+				state->status = FE_STATUS_LOCKED;
+			}
+			break;
+		default:
+			state->status = FE_STATUS_TUNE_FAILED;
+			state->tune_state = CT_DEMOD_STOP;
+			break;
+		}
+		break;
+	default:
+		ret = FE_CALLBACK_TIME_NEVER;
+		break;
+	}
+
+	return ret;
+}
+
+static int dib9000_fw_set_diversity_in(struct dvb_frontend *fe, int onoff)
+{
+	struct dib9000_state *state = fe->demodulator_priv;
+	u16 mode = (u16) onoff;
+	return dib9000_mbx_send(state, OUT_MSG_ENABLE_DIVERSITY, &mode, 1);
+}
+
+static int dib9000_fw_set_output_mode(struct dvb_frontend *fe, int mode)
+{
+	struct dib9000_state *state = fe->demodulator_priv;
+	u16 outreg, smo_mode;
+
+	dprintk("setting output mode for demod %p to %d", fe, mode);
+
+	switch (mode) {
+	case OUTMODE_MPEG2_PAR_GATED_CLK:
+		outreg = (1 << 10);	/* 0x0400 */
+		break;
+	case OUTMODE_MPEG2_PAR_CONT_CLK:
+		outreg = (1 << 10) | (1 << 6);	/* 0x0440 */
+		break;
+	case OUTMODE_MPEG2_SERIAL:
+		outreg = (1 << 10) | (2 << 6) | (0 << 1);	/* 0x0482 */
+		break;
+	case OUTMODE_DIVERSITY:
+		outreg = (1 << 10) | (4 << 6);	/* 0x0500 */
+		break;
+	case OUTMODE_MPEG2_FIFO:
+		outreg = (1 << 10) | (5 << 6);
+		break;
+	case OUTMODE_HIGH_Z:
+		outreg = 0;
+		break;
+	default:
+		dprintk("Unhandled output_mode passed to be set for demod %p", &state->fe[0]);
+		return -EINVAL;
+	}
+
+	dib9000_write_word(state, 1795, outreg);
+
+	switch (mode) {
+	case OUTMODE_MPEG2_PAR_GATED_CLK:
+	case OUTMODE_MPEG2_PAR_CONT_CLK:
+	case OUTMODE_MPEG2_SERIAL:
+	case OUTMODE_MPEG2_FIFO:
+		smo_mode = (dib9000_read_word(state, 295) & 0x0010) | (1 << 1);
+		if (state->chip.d9.cfg.output_mpeg2_in_188_bytes)
+			smo_mode |= (1 << 5);
+		dib9000_write_word(state, 295, smo_mode);
+		break;
+	}
+
+	outreg = to_fw_output_mode(mode);
+	return dib9000_mbx_send(state, OUT_MSG_SET_OUTPUT_MODE, &outreg, 1);
+}
+
+static int dib9000_tuner_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)
+{
+	struct dib9000_state *state = i2c_get_adapdata(i2c_adap);
+	u16 i, len, t, index_msg;
+
+	for (index_msg = 0; index_msg < num; index_msg++) {
+		if (msg[index_msg].flags & I2C_M_RD) {	/* read */
+			len = msg[index_msg].len;
+			if (len > 16)
+				len = 16;
+
+			if (dib9000_read_word(state, 790) != 0)
+				dprintk("TunerITF: read busy");
+
+			dib9000_write_word(state, 784, (u16) (msg[index_msg].addr));
+			dib9000_write_word(state, 787, (len / 2) - 1);
+			dib9000_write_word(state, 786, 1);	/* start read */
+
+			i = 1000;
+			while (dib9000_read_word(state, 790) != (len / 2) && i)
+				i--;
+
+			if (i == 0)
+				dprintk("TunerITF: read failed");
+
+			for (i = 0; i < len; i += 2) {
+				t = dib9000_read_word(state, 785);
+				msg[index_msg].buf[i] = (t >> 8) & 0xff;
+				msg[index_msg].buf[i + 1] = (t) & 0xff;
+			}
+			if (dib9000_read_word(state, 790) != 0)
+				dprintk("TunerITF: read more data than expected");
+		} else {
+			i = 1000;
+			while (dib9000_read_word(state, 789) && i)
+				i--;
+			if (i == 0)
+				dprintk("TunerITF: write busy");
+
+			len = msg[index_msg].len;
+			if (len > 16)
+				len = 16;
+
+			for (i = 0; i < len; i += 2)
+				dib9000_write_word(state, 785, (msg[index_msg].buf[i] << 8) | msg[index_msg].buf[i + 1]);
+			dib9000_write_word(state, 784, (u16) msg[index_msg].addr);
+			dib9000_write_word(state, 787, (len / 2) - 1);
+			dib9000_write_word(state, 786, 0);	/* start write */
+
+			i = 1000;
+			while (dib9000_read_word(state, 791) > 0 && i)
+				i--;
+			if (i == 0)
+				dprintk("TunerITF: write failed");
+		}
+	}
+	return num;
+}
+
+int dib9000_fw_set_component_bus_speed(struct dvb_frontend *fe, u16 speed)
+{
+	struct dib9000_state *state = fe->demodulator_priv;
+
+	state->component_bus_speed = speed;
+	return 0;
+}
+EXPORT_SYMBOL(dib9000_fw_set_component_bus_speed);
+
+static int dib9000_fw_component_bus_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)
+{
+	struct dib9000_state *state = i2c_get_adapdata(i2c_adap);
+	u8 type = 0;		/* I2C */
+	u8 port = DIBX000_I2C_INTERFACE_GPIO_3_4;
+	u16 scl = state->component_bus_speed;	/* SCL frequency */
+	struct dib9000_fe_memory_map *m = &state->platform.risc.fe_mm[FE_MM_RW_COMPONENT_ACCESS_BUFFER];
+	u8 p[13] = { 0 };
+
+	p[0] = type;
+	p[1] = port;
+	p[2] = msg[0].addr << 1;
+
+	p[3] = (u8) scl & 0xff;	/* scl */
+	p[4] = (u8) (scl >> 8);
+
+	p[7] = 0;
+	p[8] = 0;
+
+	p[9] = (u8) (msg[0].len);
+	p[10] = (u8) (msg[0].len >> 8);
+	if ((num > 1) && (msg[1].flags & I2C_M_RD)) {
+		p[11] = (u8) (msg[1].len);
+		p[12] = (u8) (msg[1].len >> 8);
+	} else {
+		p[11] = 0;
+		p[12] = 0;
+	}
+
+	if (mutex_lock_interruptible(&state->platform.risc.mem_mbx_lock) < 0) {
+		dprintk("could not get the lock");
+		return 0;
+	}
+
+	dib9000_risc_mem_write(state, FE_MM_W_COMPONENT_ACCESS, p);
+
+	{			/* write-part */
+		dib9000_risc_mem_setup_cmd(state, m->addr, msg[0].len, 0);
+		dib9000_risc_mem_write_chunks(state, msg[0].buf, msg[0].len);
+	}
+
+	/* do the transaction */
+	if (dib9000_fw_memmbx_sync(state, FE_SYNC_COMPONENT_ACCESS) < 0) {
+		mutex_unlock(&state->platform.risc.mem_mbx_lock);
+		return 0;
+	}
+
+	/* read back any possible result */
+	if ((num > 1) && (msg[1].flags & I2C_M_RD))
+		dib9000_risc_mem_read(state, FE_MM_RW_COMPONENT_ACCESS_BUFFER, msg[1].buf, msg[1].len);
+
+	mutex_unlock(&state->platform.risc.mem_mbx_lock);
+
+	return num;
+}
+
+static u32 dib9000_i2c_func(struct i2c_adapter *adapter)
+{
+	return I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm dib9000_tuner_algo = {
+	.master_xfer = dib9000_tuner_xfer,
+	.functionality = dib9000_i2c_func,
+};
+
+static struct i2c_algorithm dib9000_component_bus_algo = {
+	.master_xfer = dib9000_fw_component_bus_xfer,
+	.functionality = dib9000_i2c_func,
+};
+
+struct i2c_adapter *dib9000_get_tuner_interface(struct dvb_frontend *fe)
+{
+	struct dib9000_state *st = fe->demodulator_priv;
+	return &st->tuner_adap;
+}
+EXPORT_SYMBOL(dib9000_get_tuner_interface);
+
+struct i2c_adapter *dib9000_get_component_bus_interface(struct dvb_frontend *fe)
+{
+	struct dib9000_state *st = fe->demodulator_priv;
+	return &st->component_bus;
+}
+EXPORT_SYMBOL(dib9000_get_component_bus_interface);
+
+struct i2c_adapter *dib9000_get_i2c_master(struct dvb_frontend *fe, enum dibx000_i2c_interface intf, int gating)
+{
+	struct dib9000_state *st = fe->demodulator_priv;
+	return dibx000_get_i2c_adapter(&st->i2c_master, intf, gating);
+}
+EXPORT_SYMBOL(dib9000_get_i2c_master);
+
+int dib9000_set_i2c_adapter(struct dvb_frontend *fe, struct i2c_adapter *i2c)
+{
+	struct dib9000_state *st = fe->demodulator_priv;
+
+	st->i2c.i2c_adap = i2c;
+	return 0;
+}
+EXPORT_SYMBOL(dib9000_set_i2c_adapter);
+
+static int dib9000_cfg_gpio(struct dib9000_state *st, u8 num, u8 dir, u8 val)
+{
+	st->gpio_dir = dib9000_read_word(st, 773);
+	st->gpio_dir &= ~(1 << num);	/* reset the direction bit */
+	st->gpio_dir |= (dir & 0x1) << num;	/* set the new direction */
+	dib9000_write_word(st, 773, st->gpio_dir);
+
+	st->gpio_val = dib9000_read_word(st, 774);
+	st->gpio_val &= ~(1 << num);	/* reset the direction bit */
+	st->gpio_val |= (val & 0x01) << num;	/* set the new value */
+	dib9000_write_word(st, 774, st->gpio_val);
+
+	dprintk("gpio dir: %04x: gpio val: %04x", st->gpio_dir, st->gpio_val);
+
+	return 0;
+}
+
+int dib9000_set_gpio(struct dvb_frontend *fe, u8 num, u8 dir, u8 val)
+{
+	struct dib9000_state *state = fe->demodulator_priv;
+	return dib9000_cfg_gpio(state, num, dir, val);
+}
+EXPORT_SYMBOL(dib9000_set_gpio);
+
+int dib9000_fw_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
+{
+	struct dib9000_state *state = fe->demodulator_priv;
+	u16 val;
+	int ret;
+
+	if ((state->pid_ctrl_index != -2) && (state->pid_ctrl_index < 9)) {
+		/* postpone the pid filtering cmd */
+		dprintk("pid filter cmd postpone");
+		state->pid_ctrl_index++;
+		state->pid_ctrl[state->pid_ctrl_index].cmd = DIB9000_PID_FILTER_CTRL;
+		state->pid_ctrl[state->pid_ctrl_index].onoff = onoff;
+		return 0;
+	}
+
+	if (mutex_lock_interruptible(&state->demod_lock) < 0) {
+		dprintk("could not get the lock");
+		return -EINTR;
+	}
+
+	val = dib9000_read_word(state, 294 + 1) & 0xffef;
+	val |= (onoff & 0x1) << 4;
+
+	dprintk("PID filter enabled %d", onoff);
+	ret = dib9000_write_word(state, 294 + 1, val);
+	mutex_unlock(&state->demod_lock);
+	return ret;
+
+}
+EXPORT_SYMBOL(dib9000_fw_pid_filter_ctrl);
+
+int dib9000_fw_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
+{
+	struct dib9000_state *state = fe->demodulator_priv;
+	int ret;
+
+	if (state->pid_ctrl_index != -2) {
+		/* postpone the pid filtering cmd */
+		dprintk("pid filter postpone");
+		if (state->pid_ctrl_index < 9) {
+			state->pid_ctrl_index++;
+			state->pid_ctrl[state->pid_ctrl_index].cmd = DIB9000_PID_FILTER;
+			state->pid_ctrl[state->pid_ctrl_index].id = id;
+			state->pid_ctrl[state->pid_ctrl_index].pid = pid;
+			state->pid_ctrl[state->pid_ctrl_index].onoff = onoff;
+		} else
+			dprintk("can not add any more pid ctrl cmd");
+		return 0;
+	}
+
+	if (mutex_lock_interruptible(&state->demod_lock) < 0) {
+		dprintk("could not get the lock");
+		return -EINTR;
+	}
+	dprintk("Index %x, PID %d, OnOff %d", id, pid, onoff);
+	ret = dib9000_write_word(state, 300 + 1 + id,
+			onoff ? (1 << 13) | pid : 0);
+	mutex_unlock(&state->demod_lock);
+	return ret;
+}
+EXPORT_SYMBOL(dib9000_fw_pid_filter);
+
+int dib9000_firmware_post_pll_init(struct dvb_frontend *fe)
+{
+	struct dib9000_state *state = fe->demodulator_priv;
+	return dib9000_fw_init(state);
+}
+EXPORT_SYMBOL(dib9000_firmware_post_pll_init);
+
+static void dib9000_release(struct dvb_frontend *demod)
+{
+	struct dib9000_state *st = demod->demodulator_priv;
+	u8 index_frontend;
+
+	for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (st->fe[index_frontend] != NULL); index_frontend++)
+		dvb_frontend_detach(st->fe[index_frontend]);
+
+	dibx000_exit_i2c_master(&st->i2c_master);
+
+	i2c_del_adapter(&st->tuner_adap);
+	i2c_del_adapter(&st->component_bus);
+	kfree(st->fe[0]);
+	kfree(st);
+}
+
+static int dib9000_wakeup(struct dvb_frontend *fe)
+{
+	return 0;
+}
+
+static int dib9000_sleep(struct dvb_frontend *fe)
+{
+	struct dib9000_state *state = fe->demodulator_priv;
+	u8 index_frontend;
+	int ret = 0;
+
+	if (mutex_lock_interruptible(&state->demod_lock) < 0) {
+		dprintk("could not get the lock");
+		return -EINTR;
+	}
+	for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
+		ret = state->fe[index_frontend]->ops.sleep(state->fe[index_frontend]);
+		if (ret < 0)
+			goto error;
+	}
+	ret = dib9000_mbx_send(state, OUT_MSG_FE_SLEEP, NULL, 0);
+
+error:
+	mutex_unlock(&state->demod_lock);
+	return ret;
+}
+
+static int dib9000_fe_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings *tune)
+{
+	tune->min_delay_ms = 1000;
+	return 0;
+}
+
+static int dib9000_get_frontend(struct dvb_frontend *fe)
+{
+	struct dib9000_state *state = fe->demodulator_priv;
+	u8 index_frontend, sub_index_frontend;
+	fe_status_t stat;
+	int ret = 0;
+
+	if (state->get_frontend_internal == 0) {
+		if (mutex_lock_interruptible(&state->demod_lock) < 0) {
+			dprintk("could not get the lock");
+			return -EINTR;
+		}
+	}
+
+	for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
+		state->fe[index_frontend]->ops.read_status(state->fe[index_frontend], &stat);
+		if (stat & FE_HAS_SYNC) {
+			dprintk("TPS lock on the slave%i", index_frontend);
+
+			/* synchronize the cache with the other frontends */
+			state->fe[index_frontend]->ops.get_frontend(state->fe[index_frontend]);
+			for (sub_index_frontend = 0; (sub_index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[sub_index_frontend] != NULL);
+			     sub_index_frontend++) {
+				if (sub_index_frontend != index_frontend) {
+					state->fe[sub_index_frontend]->dtv_property_cache.modulation =
+					    state->fe[index_frontend]->dtv_property_cache.modulation;
+					state->fe[sub_index_frontend]->dtv_property_cache.inversion =
+					    state->fe[index_frontend]->dtv_property_cache.inversion;
+					state->fe[sub_index_frontend]->dtv_property_cache.transmission_mode =
+					    state->fe[index_frontend]->dtv_property_cache.transmission_mode;
+					state->fe[sub_index_frontend]->dtv_property_cache.guard_interval =
+					    state->fe[index_frontend]->dtv_property_cache.guard_interval;
+					state->fe[sub_index_frontend]->dtv_property_cache.hierarchy =
+					    state->fe[index_frontend]->dtv_property_cache.hierarchy;
+					state->fe[sub_index_frontend]->dtv_property_cache.code_rate_HP =
+					    state->fe[index_frontend]->dtv_property_cache.code_rate_HP;
+					state->fe[sub_index_frontend]->dtv_property_cache.code_rate_LP =
+					    state->fe[index_frontend]->dtv_property_cache.code_rate_LP;
+					state->fe[sub_index_frontend]->dtv_property_cache.rolloff =
+					    state->fe[index_frontend]->dtv_property_cache.rolloff;
+				}
+			}
+			ret = 0;
+			goto return_value;
+		}
+	}
+
+	/* get the channel from master chip */
+	ret = dib9000_fw_get_channel(fe);
+	if (ret != 0)
+		goto return_value;
+
+	/* synchronize the cache with the other frontends */
+	for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
+		state->fe[index_frontend]->dtv_property_cache.inversion = fe->dtv_property_cache.inversion;
+		state->fe[index_frontend]->dtv_property_cache.transmission_mode = fe->dtv_property_cache.transmission_mode;
+		state->fe[index_frontend]->dtv_property_cache.guard_interval = fe->dtv_property_cache.guard_interval;
+		state->fe[index_frontend]->dtv_property_cache.modulation = fe->dtv_property_cache.modulation;
+		state->fe[index_frontend]->dtv_property_cache.hierarchy = fe->dtv_property_cache.hierarchy;
+		state->fe[index_frontend]->dtv_property_cache.code_rate_HP = fe->dtv_property_cache.code_rate_HP;
+		state->fe[index_frontend]->dtv_property_cache.code_rate_LP = fe->dtv_property_cache.code_rate_LP;
+		state->fe[index_frontend]->dtv_property_cache.rolloff = fe->dtv_property_cache.rolloff;
+	}
+	ret = 0;
+
+return_value:
+	if (state->get_frontend_internal == 0)
+		mutex_unlock(&state->demod_lock);
+	return ret;
+}
+
+static int dib9000_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state)
+{
+	struct dib9000_state *state = fe->demodulator_priv;
+	state->tune_state = tune_state;
+	if (tune_state == CT_DEMOD_START)
+		state->status = FE_STATUS_TUNE_PENDING;
+
+	return 0;
+}
+
+static u32 dib9000_get_status(struct dvb_frontend *fe)
+{
+	struct dib9000_state *state = fe->demodulator_priv;
+	return state->status;
+}
+
+static int dib9000_set_channel_status(struct dvb_frontend *fe, struct dvb_frontend_parametersContext *channel_status)
+{
+	struct dib9000_state *state = fe->demodulator_priv;
+
+	memcpy(&state->channel_status, channel_status, sizeof(struct dvb_frontend_parametersContext));
+	return 0;
+}
+
+static int dib9000_set_frontend(struct dvb_frontend *fe)
+{
+	struct dib9000_state *state = fe->demodulator_priv;
+	int sleep_time, sleep_time_slave;
+	u32 frontend_status;
+	u8 nbr_pending, exit_condition, index_frontend, index_frontend_success;
+	struct dvb_frontend_parametersContext channel_status;
+
+	/* check that the correct parameters are set */
+	if (state->fe[0]->dtv_property_cache.frequency == 0) {
+		dprintk("dib9000: must specify frequency ");
+		return 0;
+	}
+
+	if (state->fe[0]->dtv_property_cache.bandwidth_hz == 0) {
+		dprintk("dib9000: must specify bandwidth ");
+		return 0;
+	}
+
+	state->pid_ctrl_index = -1; /* postpone the pid filtering cmd */
+	if (mutex_lock_interruptible(&state->demod_lock) < 0) {
+		dprintk("could not get the lock");
+		return 0;
+	}
+
+	fe->dtv_property_cache.delivery_system = SYS_DVBT;
+
+	/* set the master status */
+	if (state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_AUTO ||
+	    state->fe[0]->dtv_property_cache.guard_interval == GUARD_INTERVAL_AUTO ||
+	    state->fe[0]->dtv_property_cache.modulation == QAM_AUTO ||
+	    state->fe[0]->dtv_property_cache.code_rate_HP == FEC_AUTO) {
+		/* no channel specified, autosearch the channel */
+		state->channel_status.status = CHANNEL_STATUS_PARAMETERS_UNKNOWN;
+	} else
+		state->channel_status.status = CHANNEL_STATUS_PARAMETERS_SET;
+
+	/* set mode and status for the different frontends */
+	for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
+		dib9000_fw_set_diversity_in(state->fe[index_frontend], 1);
+
+		/* synchronization of the cache */
+		memcpy(&state->fe[index_frontend]->dtv_property_cache, &fe->dtv_property_cache, sizeof(struct dtv_frontend_properties));
+
+		state->fe[index_frontend]->dtv_property_cache.delivery_system = SYS_DVBT;
+		dib9000_fw_set_output_mode(state->fe[index_frontend], OUTMODE_HIGH_Z);
+
+		dib9000_set_channel_status(state->fe[index_frontend], &state->channel_status);
+		dib9000_set_tune_state(state->fe[index_frontend], CT_DEMOD_START);
+	}
+
+	/* actual tune */
+	exit_condition = 0;	/* 0: tune pending; 1: tune failed; 2:tune success */
+	index_frontend_success = 0;
+	do {
+		sleep_time = dib9000_fw_tune(state->fe[0]);
+		for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
+			sleep_time_slave = dib9000_fw_tune(state->fe[index_frontend]);
+			if (sleep_time == FE_CALLBACK_TIME_NEVER)
+				sleep_time = sleep_time_slave;
+			else if ((sleep_time_slave != FE_CALLBACK_TIME_NEVER) && (sleep_time_slave > sleep_time))
+				sleep_time = sleep_time_slave;
+		}
+		if (sleep_time != FE_CALLBACK_TIME_NEVER)
+			msleep(sleep_time / 10);
+		else
+			break;
+
+		nbr_pending = 0;
+		exit_condition = 0;
+		index_frontend_success = 0;
+		for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
+			frontend_status = -dib9000_get_status(state->fe[index_frontend]);
+			if (frontend_status > -FE_STATUS_TUNE_PENDING) {
+				exit_condition = 2;	/* tune success */
+				index_frontend_success = index_frontend;
+				break;
+			}
+			if (frontend_status == -FE_STATUS_TUNE_PENDING)
+				nbr_pending++;	/* some frontends are still tuning */
+		}
+		if ((exit_condition != 2) && (nbr_pending == 0))
+			exit_condition = 1;	/* if all tune are done and no success, exit: tune failed */
+
+	} while (exit_condition == 0);
+
+	/* check the tune result */
+	if (exit_condition == 1) {	/* tune failed */
+		dprintk("tune failed");
+		mutex_unlock(&state->demod_lock);
+		/* tune failed; put all the pid filtering cmd to junk */
+		state->pid_ctrl_index = -1;
+		return 0;
+	}
+
+	dprintk("tune success on frontend%i", index_frontend_success);
+
+	/* synchronize all the channel cache */
+	state->get_frontend_internal = 1;
+	dib9000_get_frontend(state->fe[0]);
+	state->get_frontend_internal = 0;
+
+	/* retune the other frontends with the found channel */
+	channel_status.status = CHANNEL_STATUS_PARAMETERS_SET;
+	for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
+		/* only retune the frontends which was not tuned success */
+		if (index_frontend != index_frontend_success) {
+			dib9000_set_channel_status(state->fe[index_frontend], &channel_status);
+			dib9000_set_tune_state(state->fe[index_frontend], CT_DEMOD_START);
+		}
+	}
+	do {
+		sleep_time = FE_CALLBACK_TIME_NEVER;
+		for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
+			if (index_frontend != index_frontend_success) {
+				sleep_time_slave = dib9000_fw_tune(state->fe[index_frontend]);
+				if (sleep_time == FE_CALLBACK_TIME_NEVER)
+					sleep_time = sleep_time_slave;
+				else if ((sleep_time_slave != FE_CALLBACK_TIME_NEVER) && (sleep_time_slave > sleep_time))
+					sleep_time = sleep_time_slave;
+			}
+		}
+		if (sleep_time != FE_CALLBACK_TIME_NEVER)
+			msleep(sleep_time / 10);
+		else
+			break;
+
+		nbr_pending = 0;
+		for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
+			if (index_frontend != index_frontend_success) {
+				frontend_status = -dib9000_get_status(state->fe[index_frontend]);
+				if ((index_frontend != index_frontend_success) && (frontend_status == -FE_STATUS_TUNE_PENDING))
+					nbr_pending++;	/* some frontends are still tuning */
+			}
+		}
+	} while (nbr_pending != 0);
+
+	/* set the output mode */
+	dib9000_fw_set_output_mode(state->fe[0], state->chip.d9.cfg.output_mode);
+	for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++)
+		dib9000_fw_set_output_mode(state->fe[index_frontend], OUTMODE_DIVERSITY);
+
+	/* turn off the diversity for the last frontend */
+	dib9000_fw_set_diversity_in(state->fe[index_frontend - 1], 0);
+
+	mutex_unlock(&state->demod_lock);
+	if (state->pid_ctrl_index >= 0) {
+		u8 index_pid_filter_cmd;
+		u8 pid_ctrl_index = state->pid_ctrl_index;
+
+		state->pid_ctrl_index = -2;
+		for (index_pid_filter_cmd = 0;
+				index_pid_filter_cmd <= pid_ctrl_index;
+				index_pid_filter_cmd++) {
+			if (state->pid_ctrl[index_pid_filter_cmd].cmd == DIB9000_PID_FILTER_CTRL)
+				dib9000_fw_pid_filter_ctrl(state->fe[0],
+						state->pid_ctrl[index_pid_filter_cmd].onoff);
+			else if (state->pid_ctrl[index_pid_filter_cmd].cmd == DIB9000_PID_FILTER)
+				dib9000_fw_pid_filter(state->fe[0],
+						state->pid_ctrl[index_pid_filter_cmd].id,
+						state->pid_ctrl[index_pid_filter_cmd].pid,
+						state->pid_ctrl[index_pid_filter_cmd].onoff);
+		}
+	}
+	/* do not postpone any more the pid filtering */
+	state->pid_ctrl_index = -2;
+
+	return 0;
+}
+
+static u16 dib9000_read_lock(struct dvb_frontend *fe)
+{
+	struct dib9000_state *state = fe->demodulator_priv;
+
+	return dib9000_read_word(state, 535);
+}
+
+static int dib9000_read_status(struct dvb_frontend *fe, fe_status_t * stat)
+{
+	struct dib9000_state *state = fe->demodulator_priv;
+	u8 index_frontend;
+	u16 lock = 0, lock_slave = 0;
+
+	if (mutex_lock_interruptible(&state->demod_lock) < 0) {
+		dprintk("could not get the lock");
+		return -EINTR;
+	}
+	for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++)
+		lock_slave |= dib9000_read_lock(state->fe[index_frontend]);
+
+	lock = dib9000_read_word(state, 535);
+
+	*stat = 0;
+
+	if ((lock & 0x8000) || (lock_slave & 0x8000))
+		*stat |= FE_HAS_SIGNAL;
+	if ((lock & 0x3000) || (lock_slave & 0x3000))
+		*stat |= FE_HAS_CARRIER;
+	if ((lock & 0x0100) || (lock_slave & 0x0100))
+		*stat |= FE_HAS_VITERBI;
+	if (((lock & 0x0038) == 0x38) || ((lock_slave & 0x0038) == 0x38))
+		*stat |= FE_HAS_SYNC;
+	if ((lock & 0x0008) || (lock_slave & 0x0008))
+		*stat |= FE_HAS_LOCK;
+
+	mutex_unlock(&state->demod_lock);
+
+	return 0;
+}
+
+static int dib9000_read_ber(struct dvb_frontend *fe, u32 * ber)
+{
+	struct dib9000_state *state = fe->demodulator_priv;
+	u16 *c;
+	int ret = 0;
+
+	if (mutex_lock_interruptible(&state->demod_lock) < 0) {
+		dprintk("could not get the lock");
+		return -EINTR;
+	}
+	if (mutex_lock_interruptible(&state->platform.risc.mem_mbx_lock) < 0) {
+		dprintk("could not get the lock");
+		ret = -EINTR;
+		goto error;
+	}
+	if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) {
+		mutex_unlock(&state->platform.risc.mem_mbx_lock);
+		ret = -EIO;
+		goto error;
+	}
+	dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR,
+			state->i2c_read_buffer, 16 * 2);
+	mutex_unlock(&state->platform.risc.mem_mbx_lock);
+
+	c = (u16 *)state->i2c_read_buffer;
+
+	*ber = c[10] << 16 | c[11];
+
+error:
+	mutex_unlock(&state->demod_lock);
+	return ret;
+}
+
+static int dib9000_read_signal_strength(struct dvb_frontend *fe, u16 * strength)
+{
+	struct dib9000_state *state = fe->demodulator_priv;
+	u8 index_frontend;
+	u16 *c = (u16 *)state->i2c_read_buffer;
+	u16 val;
+	int ret = 0;
+
+	if (mutex_lock_interruptible(&state->demod_lock) < 0) {
+		dprintk("could not get the lock");
+		return -EINTR;
+	}
+	*strength = 0;
+	for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
+		state->fe[index_frontend]->ops.read_signal_strength(state->fe[index_frontend], &val);
+		if (val > 65535 - *strength)
+			*strength = 65535;
+		else
+			*strength += val;
+	}
+
+	if (mutex_lock_interruptible(&state->platform.risc.mem_mbx_lock) < 0) {
+		dprintk("could not get the lock");
+		ret = -EINTR;
+		goto error;
+	}
+	if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) {
+		mutex_unlock(&state->platform.risc.mem_mbx_lock);
+		ret = -EIO;
+		goto error;
+	}
+	dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2);
+	mutex_unlock(&state->platform.risc.mem_mbx_lock);
+
+	val = 65535 - c[4];
+	if (val > 65535 - *strength)
+		*strength = 65535;
+	else
+		*strength += val;
+
+error:
+	mutex_unlock(&state->demod_lock);
+	return ret;
+}
+
+static u32 dib9000_get_snr(struct dvb_frontend *fe)
+{
+	struct dib9000_state *state = fe->demodulator_priv;
+	u16 *c = (u16 *)state->i2c_read_buffer;
+	u32 n, s, exp;
+	u16 val;
+
+	if (mutex_lock_interruptible(&state->platform.risc.mem_mbx_lock) < 0) {
+		dprintk("could not get the lock");
+		return 0;
+	}
+	if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) {
+		mutex_unlock(&state->platform.risc.mem_mbx_lock);
+		return 0;
+	}
+	dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2);
+	mutex_unlock(&state->platform.risc.mem_mbx_lock);
+
+	val = c[7];
+	n = (val >> 4) & 0xff;
+	exp = ((val & 0xf) << 2);
+	val = c[8];
+	exp += ((val >> 14) & 0x3);
+	if ((exp & 0x20) != 0)
+		exp -= 0x40;
+	n <<= exp + 16;
+
+	s = (val >> 6) & 0xFF;
+	exp = (val & 0x3F);
+	if ((exp & 0x20) != 0)
+		exp -= 0x40;
+	s <<= exp + 16;
+
+	if (n > 0) {
+		u32 t = (s / n) << 16;
+		return t + ((s << 16) - n * t) / n;
+	}
+	return 0xffffffff;
+}
+
+static int dib9000_read_snr(struct dvb_frontend *fe, u16 * snr)
+{
+	struct dib9000_state *state = fe->demodulator_priv;
+	u8 index_frontend;
+	u32 snr_master;
+
+	if (mutex_lock_interruptible(&state->demod_lock) < 0) {
+		dprintk("could not get the lock");
+		return -EINTR;
+	}
+	snr_master = dib9000_get_snr(fe);
+	for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++)
+		snr_master += dib9000_get_snr(state->fe[index_frontend]);
+
+	if ((snr_master >> 16) != 0) {
+		snr_master = 10 * intlog10(snr_master >> 16);
+		*snr = snr_master / ((1 << 24) / 10);
+	} else
+		*snr = 0;
+
+	mutex_unlock(&state->demod_lock);
+
+	return 0;
+}
+
+static int dib9000_read_unc_blocks(struct dvb_frontend *fe, u32 * unc)
+{
+	struct dib9000_state *state = fe->demodulator_priv;
+	u16 *c = (u16 *)state->i2c_read_buffer;
+	int ret = 0;
+
+	if (mutex_lock_interruptible(&state->demod_lock) < 0) {
+		dprintk("could not get the lock");
+		return -EINTR;
+	}
+	if (mutex_lock_interruptible(&state->platform.risc.mem_mbx_lock) < 0) {
+		dprintk("could not get the lock");
+		ret = -EINTR;
+		goto error;
+	}
+	if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) {
+		mutex_unlock(&state->platform.risc.mem_mbx_lock);
+		ret = -EIO;
+		goto error;
+	}
+	dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2);
+	mutex_unlock(&state->platform.risc.mem_mbx_lock);
+
+	*unc = c[12];
+
+error:
+	mutex_unlock(&state->demod_lock);
+	return ret;
+}
+
+int dib9000_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, u8 first_addr)
+{
+	int k = 0, ret = 0;
+	u8 new_addr = 0;
+	struct i2c_device client = {.i2c_adap = i2c };
+
+	client.i2c_write_buffer = kzalloc(4 * sizeof(u8), GFP_KERNEL);
+	if (!client.i2c_write_buffer) {
+		dprintk("%s: not enough memory", __func__);
+		return -ENOMEM;
+	}
+	client.i2c_read_buffer = kzalloc(4 * sizeof(u8), GFP_KERNEL);
+	if (!client.i2c_read_buffer) {
+		dprintk("%s: not enough memory", __func__);
+		ret = -ENOMEM;
+		goto error_memory;
+	}
+
+	client.i2c_addr = default_addr + 16;
+	dib9000_i2c_write16(&client, 1796, 0x0);
+
+	for (k = no_of_demods - 1; k >= 0; k--) {
+		/* designated i2c address */
+		new_addr = first_addr + (k << 1);
+		client.i2c_addr = default_addr;
+
+		dib9000_i2c_write16(&client, 1817, 3);
+		dib9000_i2c_write16(&client, 1796, 0);
+		dib9000_i2c_write16(&client, 1227, 1);
+		dib9000_i2c_write16(&client, 1227, 0);
+
+		client.i2c_addr = new_addr;
+		dib9000_i2c_write16(&client, 1817, 3);
+		dib9000_i2c_write16(&client, 1796, 0);
+		dib9000_i2c_write16(&client, 1227, 1);
+		dib9000_i2c_write16(&client, 1227, 0);
+
+		if (dib9000_identify(&client) == 0) {
+			client.i2c_addr = default_addr;
+			if (dib9000_identify(&client) == 0) {
+				dprintk("DiB9000 #%d: not identified", k);
+				ret = -EIO;
+				goto error;
+			}
+		}
+
+		dib9000_i2c_write16(&client, 1795, (1 << 10) | (4 << 6));
+		dib9000_i2c_write16(&client, 1794, (new_addr << 2) | 2);
+
+		dprintk("IC %d initialized (to i2c_address 0x%x)", k, new_addr);
+	}
+
+	for (k = 0; k < no_of_demods; k++) {
+		new_addr = first_addr | (k << 1);
+		client.i2c_addr = new_addr;
+
+		dib9000_i2c_write16(&client, 1794, (new_addr << 2));
+		dib9000_i2c_write16(&client, 1795, 0);
+	}
+
+error:
+	kfree(client.i2c_read_buffer);
+error_memory:
+	kfree(client.i2c_write_buffer);
+
+	return ret;
+}
+EXPORT_SYMBOL(dib9000_i2c_enumeration);
+
+int dib9000_set_slave_frontend(struct dvb_frontend *fe, struct dvb_frontend *fe_slave)
+{
+	struct dib9000_state *state = fe->demodulator_priv;
+	u8 index_frontend = 1;
+
+	while ((index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL))
+		index_frontend++;
+	if (index_frontend < MAX_NUMBER_OF_FRONTENDS) {
+		dprintk("set slave fe %p to index %i", fe_slave, index_frontend);
+		state->fe[index_frontend] = fe_slave;
+		return 0;
+	}
+
+	dprintk("too many slave frontend");
+	return -ENOMEM;
+}
+EXPORT_SYMBOL(dib9000_set_slave_frontend);
+
+int dib9000_remove_slave_frontend(struct dvb_frontend *fe)
+{
+	struct dib9000_state *state = fe->demodulator_priv;
+	u8 index_frontend = 1;
+
+	while ((index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL))
+		index_frontend++;
+	if (index_frontend != 1) {
+		dprintk("remove slave fe %p (index %i)", state->fe[index_frontend - 1], index_frontend - 1);
+		state->fe[index_frontend] = NULL;
+		return 0;
+	}
+
+	dprintk("no frontend to be removed");
+	return -ENODEV;
+}
+EXPORT_SYMBOL(dib9000_remove_slave_frontend);
+
+struct dvb_frontend *dib9000_get_slave_frontend(struct dvb_frontend *fe, int slave_index)
+{
+	struct dib9000_state *state = fe->demodulator_priv;
+
+	if (slave_index >= MAX_NUMBER_OF_FRONTENDS)
+		return NULL;
+	return state->fe[slave_index];
+}
+EXPORT_SYMBOL(dib9000_get_slave_frontend);
+
+static struct dvb_frontend_ops dib9000_ops;
+struct dvb_frontend *dib9000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, const struct dib9000_config *cfg)
+{
+	struct dvb_frontend *fe;
+	struct dib9000_state *st;
+	st = kzalloc(sizeof(struct dib9000_state), GFP_KERNEL);
+	if (st == NULL)
+		return NULL;
+	fe = kzalloc(sizeof(struct dvb_frontend), GFP_KERNEL);
+	if (fe == NULL) {
+		kfree(st);
+		return NULL;
+	}
+
+	memcpy(&st->chip.d9.cfg, cfg, sizeof(struct dib9000_config));
+	st->i2c.i2c_adap = i2c_adap;
+	st->i2c.i2c_addr = i2c_addr;
+	st->i2c.i2c_write_buffer = st->i2c_write_buffer;
+	st->i2c.i2c_read_buffer = st->i2c_read_buffer;
+
+	st->gpio_dir = DIB9000_GPIO_DEFAULT_DIRECTIONS;
+	st->gpio_val = DIB9000_GPIO_DEFAULT_VALUES;
+	st->gpio_pwm_pos = DIB9000_GPIO_DEFAULT_PWM_POS;
+
+	mutex_init(&st->platform.risc.mbx_if_lock);
+	mutex_init(&st->platform.risc.mbx_lock);
+	mutex_init(&st->platform.risc.mem_lock);
+	mutex_init(&st->platform.risc.mem_mbx_lock);
+	mutex_init(&st->demod_lock);
+	st->get_frontend_internal = 0;
+
+	st->pid_ctrl_index = -2;
+
+	st->fe[0] = fe;
+	fe->demodulator_priv = st;
+	memcpy(&st->fe[0]->ops, &dib9000_ops, sizeof(struct dvb_frontend_ops));
+
+	/* Ensure the output mode remains at the previous default if it's
+	 * not specifically set by the caller.
+	 */
+	if ((st->chip.d9.cfg.output_mode != OUTMODE_MPEG2_SERIAL) && (st->chip.d9.cfg.output_mode != OUTMODE_MPEG2_PAR_GATED_CLK))
+		st->chip.d9.cfg.output_mode = OUTMODE_MPEG2_FIFO;
+
+	if (dib9000_identify(&st->i2c) == 0)
+		goto error;
+
+	dibx000_init_i2c_master(&st->i2c_master, DIB7000MC, st->i2c.i2c_adap, st->i2c.i2c_addr);
+
+	st->tuner_adap.dev.parent = i2c_adap->dev.parent;
+	strncpy(st->tuner_adap.name, "DIB9000_FW TUNER ACCESS", sizeof(st->tuner_adap.name));
+	st->tuner_adap.algo = &dib9000_tuner_algo;
+	st->tuner_adap.algo_data = NULL;
+	i2c_set_adapdata(&st->tuner_adap, st);
+	if (i2c_add_adapter(&st->tuner_adap) < 0)
+		goto error;
+
+	st->component_bus.dev.parent = i2c_adap->dev.parent;
+	strncpy(st->component_bus.name, "DIB9000_FW COMPONENT BUS ACCESS", sizeof(st->component_bus.name));
+	st->component_bus.algo = &dib9000_component_bus_algo;
+	st->component_bus.algo_data = NULL;
+	st->component_bus_speed = 340;
+	i2c_set_adapdata(&st->component_bus, st);
+	if (i2c_add_adapter(&st->component_bus) < 0)
+		goto component_bus_add_error;
+
+	dib9000_fw_reset(fe);
+
+	return fe;
+
+component_bus_add_error:
+	i2c_del_adapter(&st->tuner_adap);
+error:
+	kfree(st);
+	return NULL;
+}
+EXPORT_SYMBOL(dib9000_attach);
+
+static struct dvb_frontend_ops dib9000_ops = {
+	.delsys = { SYS_DVBT },
+	.info = {
+		 .name = "DiBcom 9000",
+		 .frequency_min = 44250000,
+		 .frequency_max = 867250000,
+		 .frequency_stepsize = 62500,
+		 .caps = FE_CAN_INVERSION_AUTO |
+		 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_FEC_AUTO |
+		 FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
+		 FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_RECOVER | FE_CAN_HIERARCHY_AUTO,
+		 },
+
+	.release = dib9000_release,
+
+	.init = dib9000_wakeup,
+	.sleep = dib9000_sleep,
+
+	.set_frontend = dib9000_set_frontend,
+	.get_tune_settings = dib9000_fe_get_tune_settings,
+	.get_frontend = dib9000_get_frontend,
+
+	.read_status = dib9000_read_status,
+	.read_ber = dib9000_read_ber,
+	.read_signal_strength = dib9000_read_signal_strength,
+	.read_snr = dib9000_read_snr,
+	.read_ucblocks = dib9000_read_unc_blocks,
+};
+
+MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
+MODULE_AUTHOR("Olivier Grenie <ogrenie@dibcom.fr>");
+MODULE_DESCRIPTION("Driver for the DiBcom 9000 COFDM demodulator");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb-frontends/dib9000.h b/drivers/media/dvb-frontends/dib9000.h
new file mode 100644
index 0000000..b5781a4
--- /dev/null
+++ b/drivers/media/dvb-frontends/dib9000.h
@@ -0,0 +1,131 @@
+#ifndef DIB9000_H
+#define DIB9000_H
+
+#include "dibx000_common.h"
+
+struct dib9000_config {
+	u8 dvbt_mode;
+	u8 output_mpeg2_in_188_bytes;
+	u8 hostbus_diversity;
+	struct dibx000_bandwidth_config *bw;
+
+	u16 if_drives;
+
+	u32 timing_frequency;
+	u32 xtal_clock_khz;
+	u32 vcxo_timer;
+	u32 demod_clock_khz;
+
+	const u8 *microcode_B_fe_buffer;
+	u32 microcode_B_fe_size;
+
+	struct dibGPIOFunction gpio_function[2];
+	struct dibSubbandSelection subband;
+
+	u8 output_mode;
+};
+
+#define DEFAULT_DIB9000_I2C_ADDRESS 18
+
+#if defined(CONFIG_DVB_DIB9000) || (defined(CONFIG_DVB_DIB9000_MODULE) && defined(MODULE))
+extern struct dvb_frontend *dib9000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, const struct dib9000_config *cfg);
+extern int dib9000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 default_addr, u8 first_addr);
+extern struct i2c_adapter *dib9000_get_tuner_interface(struct dvb_frontend *fe);
+extern struct i2c_adapter *dib9000_get_i2c_master(struct dvb_frontend *fe, enum dibx000_i2c_interface intf, int gating);
+extern int dib9000_set_gpio(struct dvb_frontend *fe, u8 num, u8 dir, u8 val);
+extern int dib9000_fw_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff);
+extern int dib9000_fw_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff);
+extern int dib9000_firmware_post_pll_init(struct dvb_frontend *fe);
+extern int dib9000_set_slave_frontend(struct dvb_frontend *fe, struct dvb_frontend *fe_slave);
+extern int dib9000_remove_slave_frontend(struct dvb_frontend *fe);
+extern struct dvb_frontend *dib9000_get_slave_frontend(struct dvb_frontend *fe, int slave_index);
+extern struct i2c_adapter *dib9000_get_component_bus_interface(struct dvb_frontend *fe);
+extern int dib9000_set_i2c_adapter(struct dvb_frontend *fe, struct i2c_adapter *i2c);
+extern int dib9000_fw_set_component_bus_speed(struct dvb_frontend *fe, u16 speed);
+#else
+static inline struct dvb_frontend *dib9000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib9000_config *cfg)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+
+static inline struct i2c_adapter *dib9000_get_i2c_master(struct dvb_frontend *fe, enum dibx000_i2c_interface intf, int gating)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+
+static inline int dib9000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 default_addr, u8 first_addr)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return -ENODEV;
+}
+
+static inline struct i2c_adapter *dib9000_get_tuner_interface(struct dvb_frontend *fe)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+
+static inline int dib9000_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 dib9000_fw_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return -ENODEV;
+}
+
+static inline int dib9000_fw_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return -ENODEV;
+}
+
+static inline int dib9000_firmware_post_pll_init(struct dvb_frontend *fe)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return -ENODEV;
+}
+
+static inline int dib9000_set_slave_frontend(struct dvb_frontend *fe, struct dvb_frontend *fe_slave)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return -ENODEV;
+}
+
+int dib9000_remove_slave_frontend(struct dvb_frontend *fe)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return -ENODEV;
+}
+
+static inline struct dvb_frontend *dib9000_get_slave_frontend(struct dvb_frontend *fe, int slave_index)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+
+static inline struct i2c_adapter *dib9000_get_component_bus_interface(struct dvb_frontend *fe)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+
+static inline int dib9000_set_i2c_adapter(struct dvb_frontend *fe, struct i2c_adapter *i2c)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return -ENODEV;
+}
+
+static inline int dib9000_fw_set_component_bus_speed(struct dvb_frontend *fe, u16 speed)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return -ENODEV;
+}
+#endif
+
+#endif
diff --git a/drivers/media/dvb-frontends/dibx000_common.c b/drivers/media/dvb-frontends/dibx000_common.c
new file mode 100644
index 0000000..43be723
--- /dev/null
+++ b/drivers/media/dvb-frontends/dibx000_common.c
@@ -0,0 +1,515 @@
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+#include <linux/module.h>
+
+#include "dibx000_common.h"
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
+
+#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiBX000: "); printk(args); printk("\n"); } } while (0)
+
+static int dibx000_write_word(struct dibx000_i2c_master *mst, u16 reg, u16 val)
+{
+	int ret;
+
+	if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) {
+		dprintk("could not acquire lock");
+		return -EINVAL;
+	}
+
+	mst->i2c_write_buffer[0] = (reg >> 8) & 0xff;
+	mst->i2c_write_buffer[1] = reg & 0xff;
+	mst->i2c_write_buffer[2] = (val >> 8) & 0xff;
+	mst->i2c_write_buffer[3] = val & 0xff;
+
+	memset(mst->msg, 0, sizeof(struct i2c_msg));
+	mst->msg[0].addr = mst->i2c_addr;
+	mst->msg[0].flags = 0;
+	mst->msg[0].buf = mst->i2c_write_buffer;
+	mst->msg[0].len = 4;
+
+	ret = i2c_transfer(mst->i2c_adap, mst->msg, 1) != 1 ? -EREMOTEIO : 0;
+	mutex_unlock(&mst->i2c_buffer_lock);
+
+	return ret;
+}
+
+static u16 dibx000_read_word(struct dibx000_i2c_master *mst, u16 reg)
+{
+	u16 ret;
+
+	if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) {
+		dprintk("could not acquire lock");
+		return 0;
+	}
+
+	mst->i2c_write_buffer[0] = reg >> 8;
+	mst->i2c_write_buffer[1] = reg & 0xff;
+
+	memset(mst->msg, 0, 2 * sizeof(struct i2c_msg));
+	mst->msg[0].addr = mst->i2c_addr;
+	mst->msg[0].flags = 0;
+	mst->msg[0].buf = mst->i2c_write_buffer;
+	mst->msg[0].len = 2;
+	mst->msg[1].addr = mst->i2c_addr;
+	mst->msg[1].flags = I2C_M_RD;
+	mst->msg[1].buf = mst->i2c_read_buffer;
+	mst->msg[1].len = 2;
+
+	if (i2c_transfer(mst->i2c_adap, mst->msg, 2) != 2)
+		dprintk("i2c read error on %d", reg);
+
+	ret = (mst->i2c_read_buffer[0] << 8) | mst->i2c_read_buffer[1];
+	mutex_unlock(&mst->i2c_buffer_lock);
+
+	return ret;
+}
+
+static int dibx000_is_i2c_done(struct dibx000_i2c_master *mst)
+{
+	int i = 100;
+	u16 status;
+
+	while (((status = dibx000_read_word(mst, mst->base_reg + 2)) & 0x0100) == 0 && --i > 0)
+		;
+
+	/* i2c timed out */
+	if (i == 0)
+		return -EREMOTEIO;
+
+	/* no acknowledge */
+	if ((status & 0x0080) == 0)
+		return -EREMOTEIO;
+
+	return 0;
+}
+
+static int dibx000_master_i2c_write(struct dibx000_i2c_master *mst, struct i2c_msg *msg, u8 stop)
+{
+	u16 data;
+	u16 da;
+	u16 i;
+	u16 txlen = msg->len, len;
+	const u8 *b = msg->buf;
+
+	while (txlen) {
+		dibx000_read_word(mst, mst->base_reg + 2);
+
+		len = txlen > 8 ? 8 : txlen;
+		for (i = 0; i < len; i += 2) {
+			data = *b++ << 8;
+			if (i+1 < len)
+				data |= *b++;
+			dibx000_write_word(mst, mst->base_reg, data);
+		}
+		da = (((u8) (msg->addr))  << 9) |
+			(1           << 8) |
+			(1           << 7) |
+			(0           << 6) |
+			(0           << 5) |
+			((len & 0x7) << 2) |
+			(0           << 1) |
+			(0           << 0);
+
+		if (txlen == msg->len)
+			da |= 1 << 5; /* start */
+
+		if (txlen-len == 0 && stop)
+			da |= 1 << 6; /* stop */
+
+		dibx000_write_word(mst, mst->base_reg+1, da);
+
+		if (dibx000_is_i2c_done(mst) != 0)
+			return -EREMOTEIO;
+		txlen -= len;
+	}
+
+	return 0;
+}
+
+static int dibx000_master_i2c_read(struct dibx000_i2c_master *mst, struct i2c_msg *msg)
+{
+	u16 da;
+	u8 *b = msg->buf;
+	u16 rxlen = msg->len, len;
+
+	while (rxlen) {
+		len = rxlen > 8 ? 8 : rxlen;
+		da = (((u8) (msg->addr)) << 9) |
+			(1           << 8) |
+			(1           << 7) |
+			(0           << 6) |
+			(0           << 5) |
+			((len & 0x7) << 2) |
+			(1           << 1) |
+			(0           << 0);
+
+		if (rxlen == msg->len)
+			da |= 1 << 5; /* start */
+
+		if (rxlen-len == 0)
+			da |= 1 << 6; /* stop */
+		dibx000_write_word(mst, mst->base_reg+1, da);
+
+		if (dibx000_is_i2c_done(mst) != 0)
+			return -EREMOTEIO;
+
+		rxlen -= len;
+
+		while (len) {
+			da = dibx000_read_word(mst, mst->base_reg);
+			*b++ = (da >> 8) & 0xff;
+			len--;
+			if (len >= 1) {
+				*b++ =  da   & 0xff;
+				len--;
+			}
+		}
+	}
+
+	return 0;
+}
+
+int dibx000_i2c_set_speed(struct i2c_adapter *i2c_adap, u16 speed)
+{
+	struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap);
+
+	if (mst->device_rev < DIB7000MC && speed < 235)
+		speed = 235;
+	return dibx000_write_word(mst, mst->base_reg + 3, (u16)(60000 / speed));
+
+}
+EXPORT_SYMBOL(dibx000_i2c_set_speed);
+
+static u32 dibx000_i2c_func(struct i2c_adapter *adapter)
+{
+	return I2C_FUNC_I2C;
+}
+
+static int dibx000_i2c_select_interface(struct dibx000_i2c_master *mst,
+					enum dibx000_i2c_interface intf)
+{
+	if (mst->device_rev > DIB3000MC && mst->selected_interface != intf) {
+		dprintk("selecting interface: %d", intf);
+		mst->selected_interface = intf;
+		return dibx000_write_word(mst, mst->base_reg + 4, intf);
+	}
+	return 0;
+}
+
+static int dibx000_i2c_master_xfer_gpio12(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)
+{
+	struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap);
+	int msg_index;
+	int ret = 0;
+
+	dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_GPIO_1_2);
+	for (msg_index = 0; msg_index < num; msg_index++) {
+		if (msg[msg_index].flags & I2C_M_RD) {
+			ret = dibx000_master_i2c_read(mst, &msg[msg_index]);
+			if (ret != 0)
+				return 0;
+		} else {
+			ret = dibx000_master_i2c_write(mst, &msg[msg_index], 1);
+			if (ret != 0)
+				return 0;
+		}
+	}
+
+	return num;
+}
+
+static int dibx000_i2c_master_xfer_gpio34(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)
+{
+	struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap);
+	int msg_index;
+	int ret = 0;
+
+	dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_GPIO_3_4);
+	for (msg_index = 0; msg_index < num; msg_index++) {
+		if (msg[msg_index].flags & I2C_M_RD) {
+			ret = dibx000_master_i2c_read(mst, &msg[msg_index]);
+			if (ret != 0)
+				return 0;
+		} else {
+			ret = dibx000_master_i2c_write(mst, &msg[msg_index], 1);
+			if (ret != 0)
+				return 0;
+		}
+	}
+
+	return num;
+}
+
+static struct i2c_algorithm dibx000_i2c_master_gpio12_xfer_algo = {
+	.master_xfer = dibx000_i2c_master_xfer_gpio12,
+	.functionality = dibx000_i2c_func,
+};
+
+static struct i2c_algorithm dibx000_i2c_master_gpio34_xfer_algo = {
+	.master_xfer = dibx000_i2c_master_xfer_gpio34,
+	.functionality = dibx000_i2c_func,
+};
+
+static int dibx000_i2c_gate_ctrl(struct dibx000_i2c_master *mst, u8 tx[4],
+				 u8 addr, int onoff)
+{
+	u16 val;
+
+
+	if (onoff)
+		val = addr << 8;	// bit 7 = use master or not, if 0, the gate is open
+	else
+		val = 1 << 7;
+
+	if (mst->device_rev > DIB7000)
+		val <<= 1;
+
+	tx[0] = (((mst->base_reg + 1) >> 8) & 0xff);
+	tx[1] = ((mst->base_reg + 1) & 0xff);
+	tx[2] = val >> 8;
+	tx[3] = val & 0xff;
+
+	return 0;
+}
+
+static int dibx000_i2c_gated_gpio67_xfer(struct i2c_adapter *i2c_adap,
+					struct i2c_msg msg[], int num)
+{
+	struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap);
+	int ret;
+
+	if (num > 32) {
+		dprintk("%s: too much I2C message to be transmitted (%i).\
+				Maximum is 32", __func__, num);
+		return -ENOMEM;
+	}
+
+	dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_GPIO_6_7);
+
+	if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) {
+		dprintk("could not acquire lock");
+		return -EINVAL;
+	}
+
+	memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num));
+
+	/* open the gate */
+	dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[0], msg[0].addr, 1);
+	mst->msg[0].addr = mst->i2c_addr;
+	mst->msg[0].buf = &mst->i2c_write_buffer[0];
+	mst->msg[0].len = 4;
+
+	memcpy(&mst->msg[1], msg, sizeof(struct i2c_msg) * num);
+
+	/* close the gate */
+	dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[4], 0, 0);
+	mst->msg[num + 1].addr = mst->i2c_addr;
+	mst->msg[num + 1].buf = &mst->i2c_write_buffer[4];
+	mst->msg[num + 1].len = 4;
+
+	ret = (i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ?
+			num : -EIO);
+
+	mutex_unlock(&mst->i2c_buffer_lock);
+	return ret;
+}
+
+static struct i2c_algorithm dibx000_i2c_gated_gpio67_algo = {
+	.master_xfer = dibx000_i2c_gated_gpio67_xfer,
+	.functionality = dibx000_i2c_func,
+};
+
+static int dibx000_i2c_gated_tuner_xfer(struct i2c_adapter *i2c_adap,
+					struct i2c_msg msg[], int num)
+{
+	struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap);
+	int ret;
+
+	if (num > 32) {
+		dprintk("%s: too much I2C message to be transmitted (%i).\
+				Maximum is 32", __func__, num);
+		return -ENOMEM;
+	}
+
+	dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_TUNER);
+
+	if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) {
+		dprintk("could not acquire lock");
+		return -EINVAL;
+	}
+	memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num));
+
+	/* open the gate */
+	dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[0], msg[0].addr, 1);
+	mst->msg[0].addr = mst->i2c_addr;
+	mst->msg[0].buf = &mst->i2c_write_buffer[0];
+	mst->msg[0].len = 4;
+
+	memcpy(&mst->msg[1], msg, sizeof(struct i2c_msg) * num);
+
+	/* close the gate */
+	dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[4], 0, 0);
+	mst->msg[num + 1].addr = mst->i2c_addr;
+	mst->msg[num + 1].buf = &mst->i2c_write_buffer[4];
+	mst->msg[num + 1].len = 4;
+
+	ret = (i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ?
+			num : -EIO);
+	mutex_unlock(&mst->i2c_buffer_lock);
+	return ret;
+}
+
+static struct i2c_algorithm dibx000_i2c_gated_tuner_algo = {
+	.master_xfer = dibx000_i2c_gated_tuner_xfer,
+	.functionality = dibx000_i2c_func,
+};
+
+struct i2c_adapter *dibx000_get_i2c_adapter(struct dibx000_i2c_master *mst,
+						enum dibx000_i2c_interface intf,
+						int gating)
+{
+	struct i2c_adapter *i2c = NULL;
+
+	switch (intf) {
+	case DIBX000_I2C_INTERFACE_TUNER:
+		if (gating)
+			i2c = &mst->gated_tuner_i2c_adap;
+		break;
+	case DIBX000_I2C_INTERFACE_GPIO_1_2:
+		if (!gating)
+			i2c = &mst->master_i2c_adap_gpio12;
+		break;
+	case DIBX000_I2C_INTERFACE_GPIO_3_4:
+		if (!gating)
+			i2c = &mst->master_i2c_adap_gpio34;
+		break;
+	case DIBX000_I2C_INTERFACE_GPIO_6_7:
+		if (gating)
+			i2c = &mst->master_i2c_adap_gpio67;
+		break;
+	default:
+		printk(KERN_ERR "DiBX000: incorrect I2C interface selected\n");
+		break;
+	}
+
+	return i2c;
+}
+
+EXPORT_SYMBOL(dibx000_get_i2c_adapter);
+
+void dibx000_reset_i2c_master(struct dibx000_i2c_master *mst)
+{
+	/* initialize the i2c-master by closing the gate */
+	u8 tx[4];
+	struct i2c_msg m = {.addr = mst->i2c_addr,.buf = tx,.len = 4 };
+
+	dibx000_i2c_gate_ctrl(mst, tx, 0, 0);
+	i2c_transfer(mst->i2c_adap, &m, 1);
+	mst->selected_interface = 0xff;	// the first time force a select of the I2C
+	dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_TUNER);
+}
+
+EXPORT_SYMBOL(dibx000_reset_i2c_master);
+
+static int i2c_adapter_init(struct i2c_adapter *i2c_adap,
+				struct i2c_algorithm *algo, const char *name,
+				struct dibx000_i2c_master *mst)
+{
+	strncpy(i2c_adap->name, name, sizeof(i2c_adap->name));
+	i2c_adap->algo = algo;
+	i2c_adap->algo_data = NULL;
+	i2c_set_adapdata(i2c_adap, mst);
+	if (i2c_add_adapter(i2c_adap) < 0)
+		return -ENODEV;
+	return 0;
+}
+
+int dibx000_init_i2c_master(struct dibx000_i2c_master *mst, u16 device_rev,
+				struct i2c_adapter *i2c_adap, u8 i2c_addr)
+{
+	int ret;
+
+	mutex_init(&mst->i2c_buffer_lock);
+	if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) {
+		dprintk("could not acquire lock");
+		return -EINVAL;
+	}
+	memset(mst->msg, 0, sizeof(struct i2c_msg));
+	mst->msg[0].addr = i2c_addr >> 1;
+	mst->msg[0].flags = 0;
+	mst->msg[0].buf = mst->i2c_write_buffer;
+	mst->msg[0].len = 4;
+
+	mst->device_rev = device_rev;
+	mst->i2c_adap = i2c_adap;
+	mst->i2c_addr = i2c_addr >> 1;
+
+	if (device_rev == DIB7000P || device_rev == DIB8000)
+		mst->base_reg = 1024;
+	else
+		mst->base_reg = 768;
+
+	mst->gated_tuner_i2c_adap.dev.parent = mst->i2c_adap->dev.parent;
+	if (i2c_adapter_init
+			(&mst->gated_tuner_i2c_adap, &dibx000_i2c_gated_tuner_algo,
+			 "DiBX000 tuner I2C bus", mst) != 0)
+		printk(KERN_ERR
+				"DiBX000: could not initialize the tuner i2c_adapter\n");
+
+	mst->master_i2c_adap_gpio12.dev.parent = mst->i2c_adap->dev.parent;
+	if (i2c_adapter_init
+			(&mst->master_i2c_adap_gpio12, &dibx000_i2c_master_gpio12_xfer_algo,
+			 "DiBX000 master GPIO12 I2C bus", mst) != 0)
+		printk(KERN_ERR
+				"DiBX000: could not initialize the master i2c_adapter\n");
+
+	mst->master_i2c_adap_gpio34.dev.parent = mst->i2c_adap->dev.parent;
+	if (i2c_adapter_init
+			(&mst->master_i2c_adap_gpio34, &dibx000_i2c_master_gpio34_xfer_algo,
+			 "DiBX000 master GPIO34 I2C bus", mst) != 0)
+		printk(KERN_ERR
+				"DiBX000: could not initialize the master i2c_adapter\n");
+
+	mst->master_i2c_adap_gpio67.dev.parent = mst->i2c_adap->dev.parent;
+	if (i2c_adapter_init
+			(&mst->master_i2c_adap_gpio67, &dibx000_i2c_gated_gpio67_algo,
+			 "DiBX000 master GPIO67 I2C bus", mst) != 0)
+		printk(KERN_ERR
+				"DiBX000: could not initialize the master i2c_adapter\n");
+
+	/* initialize the i2c-master by closing the gate */
+	dibx000_i2c_gate_ctrl(mst, mst->i2c_write_buffer, 0, 0);
+
+	ret = (i2c_transfer(i2c_adap, mst->msg, 1) == 1);
+	mutex_unlock(&mst->i2c_buffer_lock);
+
+	return ret;
+}
+
+EXPORT_SYMBOL(dibx000_init_i2c_master);
+
+void dibx000_exit_i2c_master(struct dibx000_i2c_master *mst)
+{
+	i2c_del_adapter(&mst->gated_tuner_i2c_adap);
+	i2c_del_adapter(&mst->master_i2c_adap_gpio12);
+	i2c_del_adapter(&mst->master_i2c_adap_gpio34);
+	i2c_del_adapter(&mst->master_i2c_adap_gpio67);
+}
+EXPORT_SYMBOL(dibx000_exit_i2c_master);
+
+
+u32 systime(void)
+{
+	struct timespec t;
+
+	t = current_kernel_time();
+	return (t.tv_sec * 10000) + (t.tv_nsec / 100000);
+}
+EXPORT_SYMBOL(systime);
+
+MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
+MODULE_DESCRIPTION("Common function the DiBcom demodulator family");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb-frontends/dibx000_common.h b/drivers/media/dvb-frontends/dibx000_common.h
new file mode 100644
index 0000000..5f48488
--- /dev/null
+++ b/drivers/media/dvb-frontends/dibx000_common.h
@@ -0,0 +1,280 @@
+#ifndef DIBX000_COMMON_H
+#define DIBX000_COMMON_H
+
+enum dibx000_i2c_interface {
+	DIBX000_I2C_INTERFACE_TUNER = 0,
+	DIBX000_I2C_INTERFACE_GPIO_1_2 = 1,
+	DIBX000_I2C_INTERFACE_GPIO_3_4 = 2,
+	DIBX000_I2C_INTERFACE_GPIO_6_7 = 3
+};
+
+struct dibx000_i2c_master {
+#define DIB3000MC 1
+#define DIB7000   2
+#define DIB7000P  11
+#define DIB7000MC 12
+#define DIB8000   13
+	u16 device_rev;
+
+	enum dibx000_i2c_interface selected_interface;
+
+/*	struct i2c_adapter  tuner_i2c_adap; */
+	struct i2c_adapter gated_tuner_i2c_adap;
+	struct i2c_adapter master_i2c_adap_gpio12;
+	struct i2c_adapter master_i2c_adap_gpio34;
+	struct i2c_adapter master_i2c_adap_gpio67;
+
+	struct i2c_adapter *i2c_adap;
+	u8 i2c_addr;
+
+	u16 base_reg;
+
+	/* for the I2C transfer */
+	struct i2c_msg msg[34];
+	u8 i2c_write_buffer[8];
+	u8 i2c_read_buffer[2];
+	struct mutex i2c_buffer_lock;
+};
+
+extern int dibx000_init_i2c_master(struct dibx000_i2c_master *mst,
+					u16 device_rev, struct i2c_adapter *i2c_adap,
+					u8 i2c_addr);
+extern struct i2c_adapter *dibx000_get_i2c_adapter(struct dibx000_i2c_master
+							*mst,
+							enum dibx000_i2c_interface
+							intf, int gating);
+extern void dibx000_exit_i2c_master(struct dibx000_i2c_master *mst);
+extern void dibx000_reset_i2c_master(struct dibx000_i2c_master *mst);
+extern int dibx000_i2c_set_speed(struct i2c_adapter *i2c_adap, u16 speed);
+
+extern u32 systime(void);
+
+#define BAND_LBAND 0x01
+#define BAND_UHF   0x02
+#define BAND_VHF   0x04
+#define BAND_SBAND 0x08
+#define BAND_FM	   0x10
+#define BAND_CBAND 0x20
+
+#define BAND_OF_FREQUENCY(freq_kHz) ((freq_kHz) <= 170000 ? BAND_CBAND : \
+									(freq_kHz) <= 115000 ? BAND_FM : \
+									(freq_kHz) <= 250000 ? BAND_VHF : \
+									(freq_kHz) <= 863000 ? BAND_UHF : \
+									(freq_kHz) <= 2000000 ? BAND_LBAND : BAND_SBAND )
+
+struct dibx000_agc_config {
+	/* defines the capabilities of this AGC-setting - using the BAND_-defines */
+	u8 band_caps;
+
+	u16 setup;
+
+	u16 inv_gain;
+	u16 time_stabiliz;
+
+	u8 alpha_level;
+	u16 thlock;
+
+	u8 wbd_inv;
+	u16 wbd_ref;
+	u8 wbd_sel;
+	u8 wbd_alpha;
+
+	u16 agc1_max;
+	u16 agc1_min;
+	u16 agc2_max;
+	u16 agc2_min;
+
+	u8 agc1_pt1;
+	u8 agc1_pt2;
+	u8 agc1_pt3;
+
+	u8 agc1_slope1;
+	u8 agc1_slope2;
+
+	u8 agc2_pt1;
+	u8 agc2_pt2;
+
+	u8 agc2_slope1;
+	u8 agc2_slope2;
+
+	u8 alpha_mant;
+	u8 alpha_exp;
+
+	u8 beta_mant;
+	u8 beta_exp;
+
+	u8 perform_agc_softsplit;
+
+	struct {
+		u16 min;
+		u16 max;
+		u16 min_thres;
+		u16 max_thres;
+	} split;
+};
+
+struct dibx000_bandwidth_config {
+	u32 internal;
+	u32 sampling;
+
+	u8 pll_prediv;
+	u8 pll_ratio;
+	u8 pll_range;
+	u8 pll_reset;
+	u8 pll_bypass;
+
+	u8 enable_refdiv;
+	u8 bypclk_div;
+	u8 IO_CLK_en_core;
+	u8 ADClkSrc;
+	u8 modulo;
+
+	u16 sad_cfg;
+
+	u32 ifreq;
+	u32 timf;
+
+	u32 xtal_hz;
+};
+
+enum dibx000_adc_states {
+	DIBX000_SLOW_ADC_ON = 0,
+	DIBX000_SLOW_ADC_OFF,
+	DIBX000_ADC_ON,
+	DIBX000_ADC_OFF,
+	DIBX000_VBG_ENABLE,
+	DIBX000_VBG_DISABLE,
+};
+
+#define BANDWIDTH_TO_KHZ(v)	((v) / 1000)
+#define BANDWIDTH_TO_HZ(v)	((v) * 1000)
+
+/* Chip output mode. */
+#define OUTMODE_HIGH_Z              0
+#define OUTMODE_MPEG2_PAR_GATED_CLK 1
+#define OUTMODE_MPEG2_PAR_CONT_CLK  2
+#define OUTMODE_MPEG2_SERIAL        7
+#define OUTMODE_DIVERSITY           4
+#define OUTMODE_MPEG2_FIFO          5
+#define OUTMODE_ANALOG_ADC          6
+
+#define INPUT_MODE_OFF                0x11
+#define INPUT_MODE_DIVERSITY          0x12
+#define INPUT_MODE_MPEG               0x13
+
+enum frontend_tune_state {
+	CT_TUNER_START = 10,
+	CT_TUNER_STEP_0,
+	CT_TUNER_STEP_1,
+	CT_TUNER_STEP_2,
+	CT_TUNER_STEP_3,
+	CT_TUNER_STEP_4,
+	CT_TUNER_STEP_5,
+	CT_TUNER_STEP_6,
+	CT_TUNER_STEP_7,
+	CT_TUNER_STOP,
+
+	CT_AGC_START = 20,
+	CT_AGC_STEP_0,
+	CT_AGC_STEP_1,
+	CT_AGC_STEP_2,
+	CT_AGC_STEP_3,
+	CT_AGC_STEP_4,
+	CT_AGC_STOP,
+
+	CT_DEMOD_START = 30,
+	CT_DEMOD_STEP_1,
+	CT_DEMOD_STEP_2,
+	CT_DEMOD_STEP_3,
+	CT_DEMOD_STEP_4,
+	CT_DEMOD_STEP_5,
+	CT_DEMOD_STEP_6,
+	CT_DEMOD_STEP_7,
+	CT_DEMOD_STEP_8,
+	CT_DEMOD_STEP_9,
+	CT_DEMOD_STEP_10,
+	CT_DEMOD_SEARCH_NEXT = 41,
+	CT_DEMOD_STEP_LOCKED,
+	CT_DEMOD_STOP,
+
+	CT_DONE = 100,
+	CT_SHUTDOWN,
+
+};
+
+struct dvb_frontend_parametersContext {
+#define CHANNEL_STATUS_PARAMETERS_UNKNOWN   0x01
+#define CHANNEL_STATUS_PARAMETERS_SET       0x02
+	u8 status;
+	u32 tune_time_estimation[2];
+	s32 tps_available;
+	u16 tps[9];
+};
+
+#define FE_STATUS_TUNE_FAILED          0
+#define FE_STATUS_TUNE_TIMED_OUT      -1
+#define FE_STATUS_TUNE_TIME_TOO_SHORT -2
+#define FE_STATUS_TUNE_PENDING        -3
+#define FE_STATUS_STD_SUCCESS         -4
+#define FE_STATUS_FFT_SUCCESS         -5
+#define FE_STATUS_DEMOD_SUCCESS       -6
+#define FE_STATUS_LOCKED              -7
+#define FE_STATUS_DATA_LOCKED         -8
+
+#define FE_CALLBACK_TIME_NEVER 0xffffffff
+
+#define ABS(x) ((x < 0) ? (-x) : (x))
+
+#define DATA_BUS_ACCESS_MODE_8BIT                 0x01
+#define DATA_BUS_ACCESS_MODE_16BIT                0x02
+#define DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT 0x10
+
+struct dibGPIOFunction {
+#define BOARD_GPIO_COMPONENT_BUS_ADAPTER 1
+#define BOARD_GPIO_COMPONENT_DEMOD       2
+	u8 component;
+
+#define BOARD_GPIO_FUNCTION_BOARD_ON      1
+#define BOARD_GPIO_FUNCTION_BOARD_OFF     2
+#define BOARD_GPIO_FUNCTION_COMPONENT_ON  3
+#define BOARD_GPIO_FUNCTION_COMPONENT_OFF 4
+#define BOARD_GPIO_FUNCTION_SUBBAND_PWM   5
+#define BOARD_GPIO_FUNCTION_SUBBAND_GPIO   6
+	u8 function;
+
+/* mask, direction and value are used specify which GPIO to change GPIO0
+ * is LSB and possible GPIO31 is MSB.  The same bit-position as in the
+ * mask is used for the direction and the value. Direction == 1 is OUT,
+ * 0 == IN. For direction "OUT" value is either 1 or 0, for direction IN
+ * value has no meaning.
+ *
+ * In case of BOARD_GPIO_FUNCTION_PWM mask is giving the GPIO to be
+ * used to do the PWM. Direction gives the PWModulator to be used.
+ * Value gives the PWM value in device-dependent scale.
+ */
+	u32 mask;
+	u32 direction;
+	u32 value;
+};
+
+#define MAX_NB_SUBBANDS   8
+struct dibSubbandSelection {
+	u8  size; /* Actual number of subbands. */
+	struct {
+		u16 f_mhz;
+		struct dibGPIOFunction gpio;
+	} subband[MAX_NB_SUBBANDS];
+};
+
+#define DEMOD_TIMF_SET    0x00
+#define DEMOD_TIMF_GET    0x01
+#define DEMOD_TIMF_UPDATE 0x02
+
+#define MPEG_ON_DIBTX		1
+#define DIV_ON_DIBTX		2
+#define ADC_ON_DIBTX		3
+#define DEMOUT_ON_HOSTBUS	4
+#define DIBTX_ON_HOSTBUS	5
+#define MPEG_ON_HOSTBUS		6
+
+#endif
diff --git a/drivers/media/dvb-frontends/drxd.h b/drivers/media/dvb-frontends/drxd.h
new file mode 100644
index 0000000..216c8c3
--- /dev/null
+++ b/drivers/media/dvb-frontends/drxd.h
@@ -0,0 +1,73 @@
+/*
+ * drxd.h: DRXD DVB-T demodulator driver
+ *
+ * Copyright (C) 2005-2007 Micronas
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 only, as published by the Free Software Foundation.
+ *
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ */
+
+#ifndef _DRXD_H_
+#define _DRXD_H_
+
+#include <linux/types.h>
+#include <linux/i2c.h>
+
+struct drxd_config {
+	u8 index;
+
+	u8 pll_address;
+	u8 pll_type;
+#define DRXD_PLL_NONE     0
+#define DRXD_PLL_DTT7520X 1
+#define DRXD_PLL_MT3X0823 2
+
+	u32 clock;
+	u8 insert_rs_byte;
+
+	u8 demod_address;
+	u8 demoda_address;
+	u8 demod_revision;
+
+	/* If the tuner is not behind an i2c gate, be sure to flip this bit
+	   or else the i2c bus could get wedged */
+	u8 disable_i2c_gate_ctrl;
+
+	u32 IF;
+	 s16(*osc_deviation) (void *priv, s16 dev, int flag);
+};
+
+#if defined(CONFIG_DVB_DRXD) || \
+			(defined(CONFIG_DVB_DRXD_MODULE) && defined(MODULE))
+extern
+struct dvb_frontend *drxd_attach(const struct drxd_config *config,
+				 void *priv, struct i2c_adapter *i2c,
+				 struct device *dev);
+#else
+static inline
+struct dvb_frontend *drxd_attach(const struct drxd_config *config,
+				 void *priv, struct i2c_adapter *i2c,
+				 struct device *dev)
+{
+	printk(KERN_INFO "%s: not probed - driver disabled by Kconfig\n",
+	       __func__);
+	return NULL;
+}
+#endif
+
+extern int drxd_config_i2c(struct dvb_frontend *, int);
+#endif
diff --git a/drivers/media/dvb-frontends/drxd_firm.c b/drivers/media/dvb-frontends/drxd_firm.c
new file mode 100644
index 0000000..5418b0b
--- /dev/null
+++ b/drivers/media/dvb-frontends/drxd_firm.c
@@ -0,0 +1,929 @@
+/*
+ * drxd_firm.c : DRXD firmware tables
+ *
+ * Copyright (C) 2006-2007 Micronas
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 only, as published by the Free Software Foundation.
+ *
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ */
+
+/* TODO: generate this file with a script from a settings file */
+
+/* Contains A2 firmware version: 1.4.2
+ * Contains B1 firmware version: 3.3.33
+ * Contains settings from driver 1.4.23
+*/
+
+#include "drxd_firm.h"
+
+#define ADDRESS(x)     ((x) & 0xFF), (((x)>>8) & 0xFF), (((x)>>16) & 0xFF), (((x)>>24) & 0xFF)
+#define LENGTH(x)      ((x) & 0xFF), (((x)>>8) & 0xFF)
+
+/* Is written via block write, must be little endian */
+#define DATA16(x)      ((x) & 0xFF), (((x)>>8) & 0xFF)
+
+#define WRBLOCK(a, l) ADDRESS(a), LENGTH(l)
+#define WR16(a, d) ADDRESS(a), LENGTH(1), DATA16(d)
+
+#define END_OF_TABLE      0xFF, 0xFF, 0xFF, 0xFF
+
+/* HI firmware patches */
+
+#define HI_TR_FUNC_ADDR HI_IF_RAM_USR_BEGIN__A
+#define HI_TR_FUNC_SIZE 9	/* size of this function in instruction words */
+
+u8 DRXD_InitAtomicRead[] = {
+	WRBLOCK(HI_TR_FUNC_ADDR, HI_TR_FUNC_SIZE),
+	0x26, 0x00,		/* 0         -> ring.rdy;           */
+	0x60, 0x04,		/* r0rami.dt -> ring.xba;           */
+	0x61, 0x04,		/* r0rami.dt -> ring.xad;           */
+	0xE3, 0x07,		/* HI_RA_RAM_USR_BEGIN -> ring.iad; */
+	0x40, 0x00,		/* (long immediate)                 */
+	0x64, 0x04,		/* r0rami.dt -> ring.len;           */
+	0x65, 0x04,		/* r0rami.dt -> ring.ctl;           */
+	0x26, 0x00,		/* 0         -> ring.rdy;           */
+	0x38, 0x00,		/* 0         -> jumps.ad;           */
+	END_OF_TABLE
+};
+
+/* Pins D0 and D1 of the parallel MPEG output can be used
+   to set the I2C address of a device. */
+
+#define HI_RST_FUNC_ADDR (HI_IF_RAM_USR_BEGIN__A + HI_TR_FUNC_SIZE)
+#define HI_RST_FUNC_SIZE 54	/* size of this function in instruction words */
+
+/* D0 Version */
+u8 DRXD_HiI2cPatch_1[] = {
+	WRBLOCK(HI_RST_FUNC_ADDR, HI_RST_FUNC_SIZE),
+	0xC8, 0x07, 0x01, 0x00,	/* MASK      -> reg0.dt;                        */
+	0xE0, 0x07, 0x15, 0x02,	/* (EC__BLK << 6) + EC_OC_REG__BNK -> ring.xba; */
+	0xE1, 0x07, 0x12, 0x00,	/* EC_OC_REG_OC_MPG_SIO__A -> ring.xad;         */
+	0xA2, 0x00,		/* M_BNK_ID_DAT -> ring.iba;                    */
+	0x23, 0x00,		/* &data     -> ring.iad;                       */
+	0x24, 0x00,		/* 0         -> ring.len;                       */
+	0xA5, 0x02,		/* M_RC_CTR_SWAP | M_RC_CTR_READ -> ring.ctl;   */
+	0x26, 0x00,		/* 0         -> ring.rdy;                       */
+	0x42, 0x00,		/* &data+1   -> w0ram.ad;                       */
+	0xC0, 0x07, 0xFF, 0x0F,	/* -1        -> w0ram.dt;                       */
+	0x63, 0x00,		/* &data+1   -> ring.iad;                       */
+	0x65, 0x02,		/* M_RC_CTR_SWAP | M_RC_CTR_WRITE -> ring.ctl;  */
+	0x26, 0x00,		/* 0         -> ring.rdy;                       */
+	0xE1, 0x07, 0x38, 0x00,	/* EC_OC_REG_OCR_MPG_USR_DAT__A -> ring.xad;    */
+	0xA5, 0x02,		/* M_RC_CTR_SWAP | M_RC_CTR_READ -> ring.ctl;   */
+	0x26, 0x00,		/* 0         -> ring.rdy;                       */
+	0xE1, 0x07, 0x12, 0x00,	/* EC_OC_REG_OC_MPG_SIO__A -> ring.xad;         */
+	0x23, 0x00,		/* &data     -> ring.iad;                       */
+	0x65, 0x02,		/* M_RC_CTR_SWAP | M_RC_CTR_WRITE -> ring.ctl;  */
+	0x26, 0x00,		/* 0         -> ring.rdy;                       */
+	0x42, 0x00,		/* &data+1   -> w0ram.ad;                       */
+	0x0F, 0x04,		/* r0ram.dt  -> and.op;                         */
+	0x1C, 0x06,		/* reg0.dt   -> and.tr;                         */
+	0xCF, 0x04,		/* and.rs    -> add.op;                         */
+	0xD0, 0x07, 0x70, 0x00,	/* DEF_DEV_ID -> add.tr;                        */
+	0xD0, 0x04,		/* add.rs    -> add.tr;                         */
+	0xC8, 0x04,		/* add.rs    -> reg0.dt;                        */
+	0x60, 0x00,		/* reg0.dt   -> w0ram.dt;                       */
+	0xC2, 0x07, 0x10, 0x00,	/* SLV0_BASE -> w0rami.ad;                      */
+	0x01, 0x00,		/* 0         -> w0rami.dt;                      */
+	0x01, 0x06,		/* reg0.dt   -> w0rami.dt;                      */
+	0xC2, 0x07, 0x20, 0x00,	/* SLV1_BASE -> w0rami.ad;                      */
+	0x01, 0x00,		/* 0         -> w0rami.dt;                      */
+	0x01, 0x06,		/* reg0.dt   -> w0rami.dt;                      */
+	0xC2, 0x07, 0x30, 0x00,	/* CMD_BASE  -> w0rami.ad;                      */
+	0x01, 0x00,		/* 0         -> w0rami.dt;                      */
+	0x01, 0x00,		/* 0         -> w0rami.dt;                      */
+	0x01, 0x00,		/* 0         -> w0rami.dt;                      */
+	0x68, 0x00,		/* M_IC_SEL_PT1 -> i2c.sel;                     */
+	0x29, 0x00,		/* M_IC_CMD_RESET -> i2c.cmd;                   */
+	0x28, 0x00,		/* M_IC_SEL_PT0 -> i2c.sel;                     */
+	0x29, 0x00,		/* M_IC_CMD_RESET -> i2c.cmd;                   */
+	0xF8, 0x07, 0x2F, 0x00,	/* 0x2F      -> jumps.ad;                       */
+
+	WR16((B_HI_IF_RAM_TRP_BPT0__AX + ((2 * 0) + 1)),
+	     (u16) (HI_RST_FUNC_ADDR & 0x3FF)),
+	WR16((B_HI_IF_RAM_TRP_BPT0__AX + ((2 * 1) + 1)),
+	     (u16) (HI_RST_FUNC_ADDR & 0x3FF)),
+	WR16((B_HI_IF_RAM_TRP_BPT0__AX + ((2 * 2) + 1)),
+	     (u16) (HI_RST_FUNC_ADDR & 0x3FF)),
+	WR16((B_HI_IF_RAM_TRP_BPT0__AX + ((2 * 3) + 1)),
+	     (u16) (HI_RST_FUNC_ADDR & 0x3FF)),
+
+	/* Force quick and dirty reset */
+	WR16(B_HI_CT_REG_COMM_STATE__A, 0),
+	END_OF_TABLE
+};
+
+/* D0,D1 Version */
+u8 DRXD_HiI2cPatch_3[] = {
+	WRBLOCK(HI_RST_FUNC_ADDR, HI_RST_FUNC_SIZE),
+	0xC8, 0x07, 0x03, 0x00,	/* MASK      -> reg0.dt;                        */
+	0xE0, 0x07, 0x15, 0x02,	/* (EC__BLK << 6) + EC_OC_REG__BNK -> ring.xba; */
+	0xE1, 0x07, 0x12, 0x00,	/* EC_OC_REG_OC_MPG_SIO__A -> ring.xad;         */
+	0xA2, 0x00,		/* M_BNK_ID_DAT -> ring.iba;                    */
+	0x23, 0x00,		/* &data     -> ring.iad;                       */
+	0x24, 0x00,		/* 0         -> ring.len;                       */
+	0xA5, 0x02,		/* M_RC_CTR_SWAP | M_RC_CTR_READ -> ring.ctl;   */
+	0x26, 0x00,		/* 0         -> ring.rdy;                       */
+	0x42, 0x00,		/* &data+1   -> w0ram.ad;                       */
+	0xC0, 0x07, 0xFF, 0x0F,	/* -1        -> w0ram.dt;                       */
+	0x63, 0x00,		/* &data+1   -> ring.iad;                       */
+	0x65, 0x02,		/* M_RC_CTR_SWAP | M_RC_CTR_WRITE -> ring.ctl;  */
+	0x26, 0x00,		/* 0         -> ring.rdy;                       */
+	0xE1, 0x07, 0x38, 0x00,	/* EC_OC_REG_OCR_MPG_USR_DAT__A -> ring.xad;    */
+	0xA5, 0x02,		/* M_RC_CTR_SWAP | M_RC_CTR_READ -> ring.ctl;   */
+	0x26, 0x00,		/* 0         -> ring.rdy;                       */
+	0xE1, 0x07, 0x12, 0x00,	/* EC_OC_REG_OC_MPG_SIO__A -> ring.xad;         */
+	0x23, 0x00,		/* &data     -> ring.iad;                       */
+	0x65, 0x02,		/* M_RC_CTR_SWAP | M_RC_CTR_WRITE -> ring.ctl;  */
+	0x26, 0x00,		/* 0         -> ring.rdy;                       */
+	0x42, 0x00,		/* &data+1   -> w0ram.ad;                       */
+	0x0F, 0x04,		/* r0ram.dt  -> and.op;                         */
+	0x1C, 0x06,		/* reg0.dt   -> and.tr;                         */
+	0xCF, 0x04,		/* and.rs    -> add.op;                         */
+	0xD0, 0x07, 0x70, 0x00,	/* DEF_DEV_ID -> add.tr;                        */
+	0xD0, 0x04,		/* add.rs    -> add.tr;                         */
+	0xC8, 0x04,		/* add.rs    -> reg0.dt;                        */
+	0x60, 0x00,		/* reg0.dt   -> w0ram.dt;                       */
+	0xC2, 0x07, 0x10, 0x00,	/* SLV0_BASE -> w0rami.ad;                      */
+	0x01, 0x00,		/* 0         -> w0rami.dt;                      */
+	0x01, 0x06,		/* reg0.dt   -> w0rami.dt;                      */
+	0xC2, 0x07, 0x20, 0x00,	/* SLV1_BASE -> w0rami.ad;                      */
+	0x01, 0x00,		/* 0         -> w0rami.dt;                      */
+	0x01, 0x06,		/* reg0.dt   -> w0rami.dt;                      */
+	0xC2, 0x07, 0x30, 0x00,	/* CMD_BASE  -> w0rami.ad;                      */
+	0x01, 0x00,		/* 0         -> w0rami.dt;                      */
+	0x01, 0x00,		/* 0         -> w0rami.dt;                      */
+	0x01, 0x00,		/* 0         -> w0rami.dt;                      */
+	0x68, 0x00,		/* M_IC_SEL_PT1 -> i2c.sel;                     */
+	0x29, 0x00,		/* M_IC_CMD_RESET -> i2c.cmd;                   */
+	0x28, 0x00,		/* M_IC_SEL_PT0 -> i2c.sel;                     */
+	0x29, 0x00,		/* M_IC_CMD_RESET -> i2c.cmd;                   */
+	0xF8, 0x07, 0x2F, 0x00,	/* 0x2F      -> jumps.ad;                       */
+
+	WR16((B_HI_IF_RAM_TRP_BPT0__AX + ((2 * 0) + 1)),
+	     (u16) (HI_RST_FUNC_ADDR & 0x3FF)),
+	WR16((B_HI_IF_RAM_TRP_BPT0__AX + ((2 * 1) + 1)),
+	     (u16) (HI_RST_FUNC_ADDR & 0x3FF)),
+	WR16((B_HI_IF_RAM_TRP_BPT0__AX + ((2 * 2) + 1)),
+	     (u16) (HI_RST_FUNC_ADDR & 0x3FF)),
+	WR16((B_HI_IF_RAM_TRP_BPT0__AX + ((2 * 3) + 1)),
+	     (u16) (HI_RST_FUNC_ADDR & 0x3FF)),
+
+	/* Force quick and dirty reset */
+	WR16(B_HI_CT_REG_COMM_STATE__A, 0),
+	END_OF_TABLE
+};
+
+u8 DRXD_ResetCEFR[] = {
+	WRBLOCK(CE_REG_FR_TREAL00__A, 57),
+	0x52, 0x00,		/* CE_REG_FR_TREAL00__A */
+	0x00, 0x00,		/* CE_REG_FR_TIMAG00__A */
+	0x52, 0x00,		/* CE_REG_FR_TREAL01__A */
+	0x00, 0x00,		/* CE_REG_FR_TIMAG01__A */
+	0x52, 0x00,		/* CE_REG_FR_TREAL02__A */
+	0x00, 0x00,		/* CE_REG_FR_TIMAG02__A */
+	0x52, 0x00,		/* CE_REG_FR_TREAL03__A */
+	0x00, 0x00,		/* CE_REG_FR_TIMAG03__A */
+	0x52, 0x00,		/* CE_REG_FR_TREAL04__A */
+	0x00, 0x00,		/* CE_REG_FR_TIMAG04__A */
+	0x52, 0x00,		/* CE_REG_FR_TREAL05__A */
+	0x00, 0x00,		/* CE_REG_FR_TIMAG05__A */
+	0x52, 0x00,		/* CE_REG_FR_TREAL06__A */
+	0x00, 0x00,		/* CE_REG_FR_TIMAG06__A */
+	0x52, 0x00,		/* CE_REG_FR_TREAL07__A */
+	0x00, 0x00,		/* CE_REG_FR_TIMAG07__A */
+	0x52, 0x00,		/* CE_REG_FR_TREAL08__A */
+	0x00, 0x00,		/* CE_REG_FR_TIMAG08__A */
+	0x52, 0x00,		/* CE_REG_FR_TREAL09__A */
+	0x00, 0x00,		/* CE_REG_FR_TIMAG09__A */
+	0x52, 0x00,		/* CE_REG_FR_TREAL10__A */
+	0x00, 0x00,		/* CE_REG_FR_TIMAG10__A */
+	0x52, 0x00,		/* CE_REG_FR_TREAL11__A */
+	0x00, 0x00,		/* CE_REG_FR_TIMAG11__A */
+
+	0x52, 0x00,		/* CE_REG_FR_MID_TAP__A */
+
+	0x0B, 0x00,		/* CE_REG_FR_SQS_G00__A */
+	0x0B, 0x00,		/* CE_REG_FR_SQS_G01__A */
+	0x0B, 0x00,		/* CE_REG_FR_SQS_G02__A */
+	0x0B, 0x00,		/* CE_REG_FR_SQS_G03__A */
+	0x0B, 0x00,		/* CE_REG_FR_SQS_G04__A */
+	0x0B, 0x00,		/* CE_REG_FR_SQS_G05__A */
+	0x0B, 0x00,		/* CE_REG_FR_SQS_G06__A */
+	0x0B, 0x00,		/* CE_REG_FR_SQS_G07__A */
+	0x0B, 0x00,		/* CE_REG_FR_SQS_G08__A */
+	0x0B, 0x00,		/* CE_REG_FR_SQS_G09__A */
+	0x0B, 0x00,		/* CE_REG_FR_SQS_G10__A */
+	0x0B, 0x00,		/* CE_REG_FR_SQS_G11__A */
+	0x0B, 0x00,		/* CE_REG_FR_SQS_G12__A */
+
+	0xFF, 0x01,		/* CE_REG_FR_RIO_G00__A */
+	0x90, 0x01,		/* CE_REG_FR_RIO_G01__A */
+	0x0B, 0x01,		/* CE_REG_FR_RIO_G02__A */
+	0xC8, 0x00,		/* CE_REG_FR_RIO_G03__A */
+	0xA0, 0x00,		/* CE_REG_FR_RIO_G04__A */
+	0x85, 0x00,		/* CE_REG_FR_RIO_G05__A */
+	0x72, 0x00,		/* CE_REG_FR_RIO_G06__A */
+	0x64, 0x00,		/* CE_REG_FR_RIO_G07__A */
+	0x59, 0x00,		/* CE_REG_FR_RIO_G08__A */
+	0x50, 0x00,		/* CE_REG_FR_RIO_G09__A */
+	0x49, 0x00,		/* CE_REG_FR_RIO_G10__A */
+
+	0x10, 0x00,		/* CE_REG_FR_MODE__A     */
+	0x78, 0x00,		/* CE_REG_FR_SQS_TRH__A  */
+	0x00, 0x00,		/* CE_REG_FR_RIO_GAIN__A */
+	0x00, 0x02,		/* CE_REG_FR_BYPASS__A   */
+	0x0D, 0x00,		/* CE_REG_FR_PM_SET__A   */
+	0x07, 0x00,		/* CE_REG_FR_ERR_SH__A   */
+	0x04, 0x00,		/* CE_REG_FR_MAN_SH__A   */
+	0x06, 0x00,		/* CE_REG_FR_TAP_SH__A   */
+
+	END_OF_TABLE
+};
+
+u8 DRXD_InitFEA2_1[] = {
+	WRBLOCK(FE_AD_REG_PD__A, 3),
+	0x00, 0x00,		/* FE_AD_REG_PD__A          */
+	0x01, 0x00,		/* FE_AD_REG_INVEXT__A      */
+	0x00, 0x00,		/* FE_AD_REG_CLKNEG__A      */
+
+	WRBLOCK(FE_AG_REG_DCE_AUR_CNT__A, 2),
+	0x10, 0x00,		/* FE_AG_REG_DCE_AUR_CNT__A */
+	0x10, 0x00,		/* FE_AG_REG_DCE_RUR_CNT__A */
+
+	WRBLOCK(FE_AG_REG_ACE_AUR_CNT__A, 2),
+	0x0E, 0x00,		/* FE_AG_REG_ACE_AUR_CNT__A */
+	0x00, 0x00,		/* FE_AG_REG_ACE_RUR_CNT__A */
+
+	WRBLOCK(FE_AG_REG_EGC_FLA_RGN__A, 5),
+	0x04, 0x00,		/* FE_AG_REG_EGC_FLA_RGN__A */
+	0x1F, 0x00,		/* FE_AG_REG_EGC_SLO_RGN__A */
+	0x00, 0x00,		/* FE_AG_REG_EGC_JMP_PSN__A */
+	0x00, 0x00,		/* FE_AG_REG_EGC_FLA_INC__A */
+	0x00, 0x00,		/* FE_AG_REG_EGC_FLA_DEC__A */
+
+	WRBLOCK(FE_AG_REG_GC1_AGC_MAX__A, 2),
+	0xFF, 0x01,		/* FE_AG_REG_GC1_AGC_MAX__A */
+	0x00, 0xFE,		/* FE_AG_REG_GC1_AGC_MIN__A */
+
+	WRBLOCK(FE_AG_REG_IND_WIN__A, 29),
+	0x00, 0x00,		/* FE_AG_REG_IND_WIN__A     */
+	0x05, 0x00,		/* FE_AG_REG_IND_THD_LOL__A */
+	0x0F, 0x00,		/* FE_AG_REG_IND_THD_HIL__A */
+	0x00, 0x00,		/* FE_AG_REG_IND_DEL__A     don't care */
+	0x1E, 0x00,		/* FE_AG_REG_IND_PD1_WRI__A */
+	0x0C, 0x00,		/* FE_AG_REG_PDA_AUR_CNT__A */
+	0x00, 0x00,		/* FE_AG_REG_PDA_RUR_CNT__A */
+	0x00, 0x00,		/* FE_AG_REG_PDA_AVE_DAT__A don't care  */
+	0x00, 0x00,		/* FE_AG_REG_PDC_RUR_CNT__A */
+	0x01, 0x00,		/* FE_AG_REG_PDC_SET_LVL__A */
+	0x02, 0x00,		/* FE_AG_REG_PDC_FLA_RGN__A */
+	0x00, 0x00,		/* FE_AG_REG_PDC_JMP_PSN__A don't care  */
+	0xFF, 0xFF,		/* FE_AG_REG_PDC_FLA_STP__A */
+	0xFF, 0xFF,		/* FE_AG_REG_PDC_SLO_STP__A */
+	0x00, 0x1F,		/* FE_AG_REG_PDC_PD2_WRI__A don't care  */
+	0x00, 0x00,		/* FE_AG_REG_PDC_MAP_DAT__A don't care  */
+	0x02, 0x00,		/* FE_AG_REG_PDC_MAX__A     */
+	0x0C, 0x00,		/* FE_AG_REG_TGA_AUR_CNT__A */
+	0x00, 0x00,		/* FE_AG_REG_TGA_RUR_CNT__A */
+	0x00, 0x00,		/* FE_AG_REG_TGA_AVE_DAT__A don't care  */
+	0x00, 0x00,		/* FE_AG_REG_TGC_RUR_CNT__A */
+	0x22, 0x00,		/* FE_AG_REG_TGC_SET_LVL__A */
+	0x15, 0x00,		/* FE_AG_REG_TGC_FLA_RGN__A */
+	0x00, 0x00,		/* FE_AG_REG_TGC_JMP_PSN__A don't care  */
+	0x01, 0x00,		/* FE_AG_REG_TGC_FLA_STP__A */
+	0x0A, 0x00,		/* FE_AG_REG_TGC_SLO_STP__A */
+	0x00, 0x00,		/* FE_AG_REG_TGC_MAP_DAT__A don't care  */
+	0x10, 0x00,		/* FE_AG_REG_FGA_AUR_CNT__A */
+	0x10, 0x00,		/* FE_AG_REG_FGA_RUR_CNT__A */
+
+	WRBLOCK(FE_AG_REG_BGC_FGC_WRI__A, 2),
+	0x00, 0x00,		/* FE_AG_REG_BGC_FGC_WRI__A */
+	0x00, 0x00,		/* FE_AG_REG_BGC_CGC_WRI__A */
+
+	WRBLOCK(FE_FD_REG_SCL__A, 3),
+	0x05, 0x00,		/* FE_FD_REG_SCL__A         */
+	0x03, 0x00,		/* FE_FD_REG_MAX_LEV__A     */
+	0x05, 0x00,		/* FE_FD_REG_NR__A          */
+
+	WRBLOCK(FE_CF_REG_SCL__A, 5),
+	0x16, 0x00,		/* FE_CF_REG_SCL__A         */
+	0x04, 0x00,		/* FE_CF_REG_MAX_LEV__A     */
+	0x06, 0x00,		/* FE_CF_REG_NR__A          */
+	0x00, 0x00,		/* FE_CF_REG_IMP_VAL__A     */
+	0x01, 0x00,		/* FE_CF_REG_MEAS_VAL__A    */
+
+	WRBLOCK(FE_CU_REG_FRM_CNT_RST__A, 2),
+	0x00, 0x08,		/* FE_CU_REG_FRM_CNT_RST__A */
+	0x00, 0x00,		/* FE_CU_REG_FRM_CNT_STR__A */
+
+	END_OF_TABLE
+};
+
+   /* with PGA */
+/*   WR16COND( DRXD_WITH_PGA, FE_AG_REG_AG_PGA_MODE__A   , 0x0004), */
+   /* without PGA */
+/*   WR16COND( DRXD_WITHOUT_PGA, FE_AG_REG_AG_PGA_MODE__A   , 0x0001), */
+/*   WR16(FE_AG_REG_AG_AGC_SIO__A,  (extAttr -> FeAgRegAgAgcSio), 0x0000 );*/
+/*   WR16(FE_AG_REG_AG_PWD__A        ,(extAttr -> FeAgRegAgPwd), 0x0000 );*/
+
+u8 DRXD_InitFEA2_2[] = {
+	WR16(FE_AG_REG_CDR_RUR_CNT__A, 0x0010),
+	WR16(FE_AG_REG_FGM_WRI__A, 48),
+	/* Activate measurement, activate scale */
+	WR16(FE_FD_REG_MEAS_VAL__A, 0x0001),
+
+	WR16(FE_CU_REG_COMM_EXEC__A, 0x0001),
+	WR16(FE_CF_REG_COMM_EXEC__A, 0x0001),
+	WR16(FE_IF_REG_COMM_EXEC__A, 0x0001),
+	WR16(FE_FD_REG_COMM_EXEC__A, 0x0001),
+	WR16(FE_FS_REG_COMM_EXEC__A, 0x0001),
+	WR16(FE_AD_REG_COMM_EXEC__A, 0x0001),
+	WR16(FE_AG_REG_COMM_EXEC__A, 0x0001),
+	WR16(FE_AG_REG_AG_MODE_LOP__A, 0x895E),
+
+	END_OF_TABLE
+};
+
+u8 DRXD_InitFEB1_1[] = {
+	WR16(B_FE_AD_REG_PD__A, 0x0000),
+	WR16(B_FE_AD_REG_CLKNEG__A, 0x0000),
+	WR16(B_FE_AG_REG_BGC_FGC_WRI__A, 0x0000),
+	WR16(B_FE_AG_REG_BGC_CGC_WRI__A, 0x0000),
+	WR16(B_FE_AG_REG_AG_MODE_LOP__A, 0x000a),
+	WR16(B_FE_AG_REG_IND_PD1_WRI__A, 35),
+	WR16(B_FE_AG_REG_IND_WIN__A, 0),
+	WR16(B_FE_AG_REG_IND_THD_LOL__A, 8),
+	WR16(B_FE_AG_REG_IND_THD_HIL__A, 8),
+	WR16(B_FE_CF_REG_IMP_VAL__A, 1),
+	WR16(B_FE_AG_REG_EGC_FLA_RGN__A, 7),
+	END_OF_TABLE
+};
+
+	/* with PGA */
+/*      WR16(B_FE_AG_REG_AG_PGA_MODE__A   , 0x0000, 0x0000); */
+       /* without PGA */
+/*      WR16(B_FE_AG_REG_AG_PGA_MODE__A   ,
+	     B_FE_AG_REG_AG_PGA_MODE_PFN_PCN_AFY_REN, 0x0000);*/
+									     /*   WR16(B_FE_AG_REG_AG_AGC_SIO__A,(extAttr -> FeAgRegAgAgcSio), 0x0000 );*//*added HS 23-05-2005 */
+/*   WR16(B_FE_AG_REG_AG_PWD__A    ,(extAttr -> FeAgRegAgPwd), 0x0000 );*/
+
+u8 DRXD_InitFEB1_2[] = {
+	WR16(B_FE_COMM_EXEC__A, 0x0001),
+
+	/* RF-AGC setup */
+	WR16(B_FE_AG_REG_PDA_AUR_CNT__A, 0x0C),
+	WR16(B_FE_AG_REG_PDC_SET_LVL__A, 0x01),
+	WR16(B_FE_AG_REG_PDC_FLA_RGN__A, 0x02),
+	WR16(B_FE_AG_REG_PDC_FLA_STP__A, 0xFFFF),
+	WR16(B_FE_AG_REG_PDC_SLO_STP__A, 0xFFFF),
+	WR16(B_FE_AG_REG_PDC_MAX__A, 0x02),
+	WR16(B_FE_AG_REG_TGA_AUR_CNT__A, 0x0C),
+	WR16(B_FE_AG_REG_TGC_SET_LVL__A, 0x22),
+	WR16(B_FE_AG_REG_TGC_FLA_RGN__A, 0x15),
+	WR16(B_FE_AG_REG_TGC_FLA_STP__A, 0x01),
+	WR16(B_FE_AG_REG_TGC_SLO_STP__A, 0x0A),
+
+	WR16(B_FE_CU_REG_DIV_NFC_CLP__A, 0),
+	WR16(B_FE_CU_REG_CTR_NFC_OCR__A, 25000),
+	WR16(B_FE_CU_REG_CTR_NFC_ICR__A, 1),
+	END_OF_TABLE
+};
+
+u8 DRXD_InitCPA2[] = {
+	WRBLOCK(CP_REG_BR_SPL_OFFSET__A, 2),
+	0x07, 0x00,		/* CP_REG_BR_SPL_OFFSET__A  */
+	0x0A, 0x00,		/* CP_REG_BR_STR_DEL__A     */
+
+	WRBLOCK(CP_REG_RT_ANG_INC0__A, 4),
+	0x00, 0x00,		/* CP_REG_RT_ANG_INC0__A    */
+	0x00, 0x00,		/* CP_REG_RT_ANG_INC1__A    */
+	0x03, 0x00,		/* CP_REG_RT_DETECT_ENA__A  */
+	0x03, 0x00,		/* CP_REG_RT_DETECT_TRH__A  */
+
+	WRBLOCK(CP_REG_AC_NEXP_OFFS__A, 5),
+	0x32, 0x00,		/* CP_REG_AC_NEXP_OFFS__A   */
+	0x62, 0x00,		/* CP_REG_AC_AVER_POW__A    */
+	0x82, 0x00,		/* CP_REG_AC_MAX_POW__A     */
+	0x26, 0x00,		/* CP_REG_AC_WEIGHT_MAN__A  */
+	0x0F, 0x00,		/* CP_REG_AC_WEIGHT_EXP__A  */
+
+	WRBLOCK(CP_REG_AC_AMP_MODE__A, 2),
+	0x02, 0x00,		/* CP_REG_AC_AMP_MODE__A    */
+	0x01, 0x00,		/* CP_REG_AC_AMP_FIX__A     */
+
+	WR16(CP_REG_INTERVAL__A, 0x0005),
+	WR16(CP_REG_RT_EXP_MARG__A, 0x0004),
+	WR16(CP_REG_AC_ANG_MODE__A, 0x0003),
+
+	WR16(CP_REG_COMM_EXEC__A, 0x0001),
+	END_OF_TABLE
+};
+
+u8 DRXD_InitCPB1[] = {
+	WR16(B_CP_REG_BR_SPL_OFFSET__A, 0x0008),
+	WR16(B_CP_COMM_EXEC__A, 0x0001),
+	END_OF_TABLE
+};
+
+u8 DRXD_InitCEA2[] = {
+	WRBLOCK(CE_REG_AVG_POW__A, 4),
+	0x62, 0x00,		/* CE_REG_AVG_POW__A        */
+	0x78, 0x00,		/* CE_REG_MAX_POW__A        */
+	0x62, 0x00,		/* CE_REG_ATT__A            */
+	0x17, 0x00,		/* CE_REG_NRED__A           */
+
+	WRBLOCK(CE_REG_NE_ERR_SELECT__A, 2),
+	0x07, 0x00,		/* CE_REG_NE_ERR_SELECT__A  */
+	0xEB, 0xFF,		/* CE_REG_NE_TD_CAL__A      */
+
+	WRBLOCK(CE_REG_NE_MIXAVG__A, 2),
+	0x06, 0x00,		/* CE_REG_NE_MIXAVG__A      */
+	0x00, 0x00,		/* CE_REG_NE_NUPD_OFS__A    */
+
+	WRBLOCK(CE_REG_PE_NEXP_OFFS__A, 2),
+	0x00, 0x00,		/* CE_REG_PE_NEXP_OFFS__A   */
+	0x00, 0x00,		/* CE_REG_PE_TIMESHIFT__A   */
+
+	WRBLOCK(CE_REG_TP_A0_TAP_NEW__A, 3),
+	0x00, 0x01,		/* CE_REG_TP_A0_TAP_NEW__A       */
+	0x01, 0x00,		/* CE_REG_TP_A0_TAP_NEW_VALID__A */
+	0x0E, 0x00,		/* CE_REG_TP_A0_MU_LMS_STEP__A   */
+
+	WRBLOCK(CE_REG_TP_A1_TAP_NEW__A, 3),
+	0x00, 0x00,		/* CE_REG_TP_A1_TAP_NEW__A        */
+	0x01, 0x00,		/* CE_REG_TP_A1_TAP_NEW_VALID__A  */
+	0x0A, 0x00,		/* CE_REG_TP_A1_MU_LMS_STEP__A    */
+
+	WRBLOCK(CE_REG_FI_SHT_INCR__A, 2),
+	0x12, 0x00,		/* CE_REG_FI_SHT_INCR__A          */
+	0x0C, 0x00,		/* CE_REG_FI_EXP_NORM__A          */
+
+	WRBLOCK(CE_REG_IR_INPUTSEL__A, 3),
+	0x00, 0x00,		/* CE_REG_IR_INPUTSEL__A          */
+	0x00, 0x00,		/* CE_REG_IR_STARTPOS__A          */
+	0xFF, 0x00,		/* CE_REG_IR_NEXP_THRES__A        */
+
+	WR16(CE_REG_TI_NEXP_OFFS__A, 0x0000),
+
+	END_OF_TABLE
+};
+
+u8 DRXD_InitCEB1[] = {
+	WR16(B_CE_REG_TI_PHN_ENABLE__A, 0x0001),
+	WR16(B_CE_REG_FR_PM_SET__A, 0x000D),
+
+	END_OF_TABLE
+};
+
+u8 DRXD_InitEQA2[] = {
+	WRBLOCK(EQ_REG_OT_QNT_THRES0__A, 4),
+	0x1E, 0x00,		/* EQ_REG_OT_QNT_THRES0__A        */
+	0x1F, 0x00,		/* EQ_REG_OT_QNT_THRES1__A        */
+	0x06, 0x00,		/* EQ_REG_OT_CSI_STEP__A          */
+	0x02, 0x00,		/* EQ_REG_OT_CSI_OFFSET__A        */
+
+	WR16(EQ_REG_TD_REQ_SMB_CNT__A, 0x0200),
+	WR16(EQ_REG_IS_CLIP_EXP__A, 0x001F),
+	WR16(EQ_REG_SN_OFFSET__A, (u16) (-7)),
+	WR16(EQ_REG_RC_SEL_CAR__A, 0x0002),
+	WR16(EQ_REG_COMM_EXEC__A, 0x0001),
+	END_OF_TABLE
+};
+
+u8 DRXD_InitEQB1[] = {
+	WR16(B_EQ_REG_COMM_EXEC__A, 0x0001),
+	END_OF_TABLE
+};
+
+u8 DRXD_ResetECRAM[] = {
+	/* Reset packet sync bytes in EC_VD ram */
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (0 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (1 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (2 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (3 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (4 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (5 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (6 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (7 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (8 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (9 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (10 * 17), 0x0000),
+
+	/* Reset packet sync bytes in EC_RS ram */
+	WR16(EC_RS_EC_RAM__A, 0x0000),
+	WR16(EC_RS_EC_RAM__A + 204, 0x0000),
+	END_OF_TABLE
+};
+
+u8 DRXD_InitECA2[] = {
+	WRBLOCK(EC_SB_REG_CSI_HI__A, 6),
+	0x1F, 0x00,		/* EC_SB_REG_CSI_HI__A            */
+	0x1E, 0x00,		/* EC_SB_REG_CSI_LO__A            */
+	0x01, 0x00,		/* EC_SB_REG_SMB_TGL__A           */
+	0x7F, 0x00,		/* EC_SB_REG_SNR_HI__A            */
+	0x7F, 0x00,		/* EC_SB_REG_SNR_MID__A           */
+	0x7F, 0x00,		/* EC_SB_REG_SNR_LO__A            */
+
+	WRBLOCK(EC_RS_REG_REQ_PCK_CNT__A, 2),
+	0x00, 0x10,		/* EC_RS_REG_REQ_PCK_CNT__A       */
+	DATA16(EC_RS_REG_VAL_PCK),	/* EC_RS_REG_VAL__A               */
+
+	WRBLOCK(EC_OC_REG_TMD_TOP_MODE__A, 5),
+	0x03, 0x00,		/* EC_OC_REG_TMD_TOP_MODE__A      */
+	0xF4, 0x01,		/* EC_OC_REG_TMD_TOP_CNT__A       */
+	0xC0, 0x03,		/* EC_OC_REG_TMD_HIL_MAR__A       */
+	0x40, 0x00,		/* EC_OC_REG_TMD_LOL_MAR__A       */
+	0x03, 0x00,		/* EC_OC_REG_TMD_CUR_CNT__A       */
+
+	WRBLOCK(EC_OC_REG_AVR_ASH_CNT__A, 2),
+	0x06, 0x00,		/* EC_OC_REG_AVR_ASH_CNT__A       */
+	0x02, 0x00,		/* EC_OC_REG_AVR_BSH_CNT__A       */
+
+	WRBLOCK(EC_OC_REG_RCN_MODE__A, 7),
+	0x07, 0x00,		/* EC_OC_REG_RCN_MODE__A          */
+	0x00, 0x00,		/* EC_OC_REG_RCN_CRA_LOP__A       */
+	0xc0, 0x00,		/* EC_OC_REG_RCN_CRA_HIP__A       */
+	0x00, 0x10,		/* EC_OC_REG_RCN_CST_LOP__A       */
+	0x00, 0x00,		/* EC_OC_REG_RCN_CST_HIP__A       */
+	0xFF, 0x01,		/* EC_OC_REG_RCN_SET_LVL__A       */
+	0x0D, 0x00,		/* EC_OC_REG_RCN_GAI_LVL__A       */
+
+	WRBLOCK(EC_OC_REG_RCN_CLP_LOP__A, 2),
+	0x00, 0x00,		/* EC_OC_REG_RCN_CLP_LOP__A       */
+	0xC0, 0x00,		/* EC_OC_REG_RCN_CLP_HIP__A       */
+
+	WR16(EC_SB_REG_CSI_OFS__A, 0x0001),
+	WR16(EC_VD_REG_FORCE__A, 0x0002),
+	WR16(EC_VD_REG_REQ_SMB_CNT__A, 0x0001),
+	WR16(EC_VD_REG_RLK_ENA__A, 0x0001),
+	WR16(EC_OD_REG_SYNC__A, 0x0664),
+	WR16(EC_OC_REG_OC_MON_SIO__A, 0x0000),
+	WR16(EC_OC_REG_SNC_ISC_LVL__A, 0x0D0C),
+	/* Output zero on monitorbus pads, power saving */
+	WR16(EC_OC_REG_OCR_MON_UOS__A,
+	     (EC_OC_REG_OCR_MON_UOS_DAT_0_ENABLE |
+	      EC_OC_REG_OCR_MON_UOS_DAT_1_ENABLE |
+	      EC_OC_REG_OCR_MON_UOS_DAT_2_ENABLE |
+	      EC_OC_REG_OCR_MON_UOS_DAT_3_ENABLE |
+	      EC_OC_REG_OCR_MON_UOS_DAT_4_ENABLE |
+	      EC_OC_REG_OCR_MON_UOS_DAT_5_ENABLE |
+	      EC_OC_REG_OCR_MON_UOS_DAT_6_ENABLE |
+	      EC_OC_REG_OCR_MON_UOS_DAT_7_ENABLE |
+	      EC_OC_REG_OCR_MON_UOS_DAT_8_ENABLE |
+	      EC_OC_REG_OCR_MON_UOS_DAT_9_ENABLE |
+	      EC_OC_REG_OCR_MON_UOS_VAL_ENABLE |
+	      EC_OC_REG_OCR_MON_UOS_CLK_ENABLE)),
+	WR16(EC_OC_REG_OCR_MON_WRI__A,
+	     EC_OC_REG_OCR_MON_WRI_INIT),
+
+/*   CHK_ERROR(ResetECRAM(demod)); */
+	/* Reset packet sync bytes in EC_VD ram */
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (0 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (1 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (2 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (3 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (4 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (5 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (6 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (7 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (8 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (9 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (10 * 17), 0x0000),
+
+	/* Reset packet sync bytes in EC_RS ram */
+	WR16(EC_RS_EC_RAM__A, 0x0000),
+	WR16(EC_RS_EC_RAM__A + 204, 0x0000),
+
+	WR16(EC_SB_REG_COMM_EXEC__A, 0x0001),
+	WR16(EC_VD_REG_COMM_EXEC__A, 0x0001),
+	WR16(EC_OD_REG_COMM_EXEC__A, 0x0001),
+	WR16(EC_RS_REG_COMM_EXEC__A, 0x0001),
+	END_OF_TABLE
+};
+
+u8 DRXD_InitECB1[] = {
+	WR16(B_EC_SB_REG_CSI_OFS0__A, 0x0001),
+	WR16(B_EC_SB_REG_CSI_OFS1__A, 0x0001),
+	WR16(B_EC_SB_REG_CSI_OFS2__A, 0x0001),
+	WR16(B_EC_SB_REG_CSI_LO__A, 0x000c),
+	WR16(B_EC_SB_REG_CSI_HI__A, 0x0018),
+	WR16(B_EC_SB_REG_SNR_HI__A, 0x007f),
+	WR16(B_EC_SB_REG_SNR_MID__A, 0x007f),
+	WR16(B_EC_SB_REG_SNR_LO__A, 0x007f),
+
+	WR16(B_EC_OC_REG_DTO_CLKMODE__A, 0x0002),
+	WR16(B_EC_OC_REG_DTO_PER__A, 0x0006),
+	WR16(B_EC_OC_REG_DTO_BUR__A, 0x0001),
+	WR16(B_EC_OC_REG_RCR_CLKMODE__A, 0x0000),
+	WR16(B_EC_OC_REG_RCN_GAI_LVL__A, 0x000D),
+	WR16(B_EC_OC_REG_OC_MPG_SIO__A, 0x0000),
+
+	/* Needed because shadow registers do not have correct default value */
+	WR16(B_EC_OC_REG_RCN_CST_LOP__A, 0x1000),
+	WR16(B_EC_OC_REG_RCN_CST_HIP__A, 0x0000),
+	WR16(B_EC_OC_REG_RCN_CRA_LOP__A, 0x0000),
+	WR16(B_EC_OC_REG_RCN_CRA_HIP__A, 0x00C0),
+	WR16(B_EC_OC_REG_RCN_CLP_LOP__A, 0x0000),
+	WR16(B_EC_OC_REG_RCN_CLP_HIP__A, 0x00C0),
+	WR16(B_EC_OC_REG_DTO_INC_LOP__A, 0x0000),
+	WR16(B_EC_OC_REG_DTO_INC_HIP__A, 0x00C0),
+
+	WR16(B_EC_OD_REG_SYNC__A, 0x0664),
+	WR16(B_EC_RS_REG_REQ_PCK_CNT__A, 0x1000),
+
+/*   CHK_ERROR(ResetECRAM(demod)); */
+	/* Reset packet sync bytes in EC_VD ram */
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (0 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (1 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (2 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (3 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (4 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (5 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (6 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (7 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (8 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (9 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (10 * 17), 0x0000),
+
+	/* Reset packet sync bytes in EC_RS ram */
+	WR16(EC_RS_EC_RAM__A, 0x0000),
+	WR16(EC_RS_EC_RAM__A + 204, 0x0000),
+
+	WR16(B_EC_SB_REG_COMM_EXEC__A, 0x0001),
+	WR16(B_EC_VD_REG_COMM_EXEC__A, 0x0001),
+	WR16(B_EC_OD_REG_COMM_EXEC__A, 0x0001),
+	WR16(B_EC_RS_REG_COMM_EXEC__A, 0x0001),
+	END_OF_TABLE
+};
+
+u8 DRXD_ResetECA2[] = {
+
+	WR16(EC_OC_REG_COMM_EXEC__A, 0x0000),
+	WR16(EC_OD_REG_COMM_EXEC__A, 0x0000),
+
+	WRBLOCK(EC_OC_REG_TMD_TOP_MODE__A, 5),
+	0x03, 0x00,		/* EC_OC_REG_TMD_TOP_MODE__A      */
+	0xF4, 0x01,		/* EC_OC_REG_TMD_TOP_CNT__A       */
+	0xC0, 0x03,		/* EC_OC_REG_TMD_HIL_MAR__A       */
+	0x40, 0x00,		/* EC_OC_REG_TMD_LOL_MAR__A       */
+	0x03, 0x00,		/* EC_OC_REG_TMD_CUR_CNT__A       */
+
+	WRBLOCK(EC_OC_REG_AVR_ASH_CNT__A, 2),
+	0x06, 0x00,		/* EC_OC_REG_AVR_ASH_CNT__A       */
+	0x02, 0x00,		/* EC_OC_REG_AVR_BSH_CNT__A       */
+
+	WRBLOCK(EC_OC_REG_RCN_MODE__A, 7),
+	0x07, 0x00,		/* EC_OC_REG_RCN_MODE__A          */
+	0x00, 0x00,		/* EC_OC_REG_RCN_CRA_LOP__A       */
+	0xc0, 0x00,		/* EC_OC_REG_RCN_CRA_HIP__A       */
+	0x00, 0x10,		/* EC_OC_REG_RCN_CST_LOP__A       */
+	0x00, 0x00,		/* EC_OC_REG_RCN_CST_HIP__A       */
+	0xFF, 0x01,		/* EC_OC_REG_RCN_SET_LVL__A       */
+	0x0D, 0x00,		/* EC_OC_REG_RCN_GAI_LVL__A       */
+
+	WRBLOCK(EC_OC_REG_RCN_CLP_LOP__A, 2),
+	0x00, 0x00,		/* EC_OC_REG_RCN_CLP_LOP__A       */
+	0xC0, 0x00,		/* EC_OC_REG_RCN_CLP_HIP__A       */
+
+	WR16(EC_OD_REG_SYNC__A, 0x0664),
+	WR16(EC_OC_REG_OC_MON_SIO__A, 0x0000),
+	WR16(EC_OC_REG_SNC_ISC_LVL__A, 0x0D0C),
+	/* Output zero on monitorbus pads, power saving */
+	WR16(EC_OC_REG_OCR_MON_UOS__A,
+	     (EC_OC_REG_OCR_MON_UOS_DAT_0_ENABLE |
+	      EC_OC_REG_OCR_MON_UOS_DAT_1_ENABLE |
+	      EC_OC_REG_OCR_MON_UOS_DAT_2_ENABLE |
+	      EC_OC_REG_OCR_MON_UOS_DAT_3_ENABLE |
+	      EC_OC_REG_OCR_MON_UOS_DAT_4_ENABLE |
+	      EC_OC_REG_OCR_MON_UOS_DAT_5_ENABLE |
+	      EC_OC_REG_OCR_MON_UOS_DAT_6_ENABLE |
+	      EC_OC_REG_OCR_MON_UOS_DAT_7_ENABLE |
+	      EC_OC_REG_OCR_MON_UOS_DAT_8_ENABLE |
+	      EC_OC_REG_OCR_MON_UOS_DAT_9_ENABLE |
+	      EC_OC_REG_OCR_MON_UOS_VAL_ENABLE |
+	      EC_OC_REG_OCR_MON_UOS_CLK_ENABLE)),
+	WR16(EC_OC_REG_OCR_MON_WRI__A,
+	     EC_OC_REG_OCR_MON_WRI_INIT),
+
+/*   CHK_ERROR(ResetECRAM(demod)); */
+	/* Reset packet sync bytes in EC_VD ram */
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (0 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (1 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (2 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (3 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (4 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (5 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (6 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (7 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (8 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (9 * 17), 0x0000),
+	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (10 * 17), 0x0000),
+
+	/* Reset packet sync bytes in EC_RS ram */
+	WR16(EC_RS_EC_RAM__A, 0x0000),
+	WR16(EC_RS_EC_RAM__A + 204, 0x0000),
+
+	WR16(EC_OD_REG_COMM_EXEC__A, 0x0001),
+	END_OF_TABLE
+};
+
+u8 DRXD_InitSC[] = {
+	WR16(SC_COMM_EXEC__A, 0),
+	WR16(SC_COMM_STATE__A, 0),
+
+#ifdef COMPILE_FOR_QT
+	WR16(SC_RA_RAM_BE_OPT_DELAY__A, 0x100),
+#endif
+
+	/* SC is not started, this is done in SetChannels() */
+	END_OF_TABLE
+};
+
+/* Diversity settings */
+
+u8 DRXD_InitDiversityFront[] = {
+	/* Start demod ********* RF in , diversity out **************************** */
+	WR16(B_SC_RA_RAM_CONFIG__A, B_SC_RA_RAM_CONFIG_FR_ENABLE__M |
+	     B_SC_RA_RAM_CONFIG_FREQSCAN__M),
+
+	WR16(B_SC_RA_RAM_LC_ABS_2K__A, 0x7),
+	WR16(B_SC_RA_RAM_LC_ABS_8K__A, 0x7),
+	WR16(B_SC_RA_RAM_IR_COARSE_8K_LENGTH__A, IRLEN_COARSE_8K),
+	WR16(B_SC_RA_RAM_IR_COARSE_8K_FREQINC__A, 1 << (11 - IRLEN_COARSE_8K)),
+	WR16(B_SC_RA_RAM_IR_COARSE_8K_KAISINC__A, 1 << (17 - IRLEN_COARSE_8K)),
+	WR16(B_SC_RA_RAM_IR_FINE_8K_LENGTH__A, IRLEN_FINE_8K),
+	WR16(B_SC_RA_RAM_IR_FINE_8K_FREQINC__A, 1 << (11 - IRLEN_FINE_8K)),
+	WR16(B_SC_RA_RAM_IR_FINE_8K_KAISINC__A, 1 << (17 - IRLEN_FINE_8K)),
+
+	WR16(B_SC_RA_RAM_IR_COARSE_2K_LENGTH__A, IRLEN_COARSE_2K),
+	WR16(B_SC_RA_RAM_IR_COARSE_2K_FREQINC__A, 1 << (11 - IRLEN_COARSE_2K)),
+	WR16(B_SC_RA_RAM_IR_COARSE_2K_KAISINC__A, 1 << (17 - IRLEN_COARSE_2K)),
+	WR16(B_SC_RA_RAM_IR_FINE_2K_LENGTH__A, IRLEN_FINE_2K),
+	WR16(B_SC_RA_RAM_IR_FINE_2K_FREQINC__A, 1 << (11 - IRLEN_FINE_2K)),
+	WR16(B_SC_RA_RAM_IR_FINE_2K_KAISINC__A, 1 << (17 - IRLEN_FINE_2K)),
+
+	WR16(B_LC_RA_RAM_FILTER_CRMM_A__A, 7),
+	WR16(B_LC_RA_RAM_FILTER_CRMM_B__A, 4),
+	WR16(B_LC_RA_RAM_FILTER_SRMM_A__A, 7),
+	WR16(B_LC_RA_RAM_FILTER_SRMM_B__A, 4),
+	WR16(B_LC_RA_RAM_FILTER_SYM_SET__A, 500),
+
+	WR16(B_CC_REG_DIVERSITY__A, 0x0001),
+	WR16(B_EC_OC_REG_OC_MODE_HIP__A, 0x0010),
+	WR16(B_EQ_REG_RC_SEL_CAR__A, B_EQ_REG_RC_SEL_CAR_PASS_B_CE |
+	     B_EQ_REG_RC_SEL_CAR_LOCAL_B_CE | B_EQ_REG_RC_SEL_CAR_MEAS_B_CE),
+
+	/*    0x2a ), *//* CE to PASS mux */
+
+	END_OF_TABLE
+};
+
+u8 DRXD_InitDiversityEnd[] = {
+	/* End demod *********** combining RF in and diversity in, MPEG TS out **** */
+	/* disable near/far; switch on timing slave mode */
+	WR16(B_SC_RA_RAM_CONFIG__A, B_SC_RA_RAM_CONFIG_FR_ENABLE__M |
+	     B_SC_RA_RAM_CONFIG_FREQSCAN__M |
+	     B_SC_RA_RAM_CONFIG_DIV_ECHO_ENABLE__M |
+	     B_SC_RA_RAM_CONFIG_SLAVE__M |
+	     B_SC_RA_RAM_CONFIG_DIV_BLANK_ENABLE__M
+/* MV from CtrlDiversity */
+	    ),
+#ifdef DRXDDIV_SRMM_SLAVING
+	WR16(SC_RA_RAM_LC_ABS_2K__A, 0x3c7),
+	WR16(SC_RA_RAM_LC_ABS_8K__A, 0x3c7),
+#else
+	WR16(SC_RA_RAM_LC_ABS_2K__A, 0x7),
+	WR16(SC_RA_RAM_LC_ABS_8K__A, 0x7),
+#endif
+
+	WR16(B_SC_RA_RAM_IR_COARSE_8K_LENGTH__A, IRLEN_COARSE_8K),
+	WR16(B_SC_RA_RAM_IR_COARSE_8K_FREQINC__A, 1 << (11 - IRLEN_COARSE_8K)),
+	WR16(B_SC_RA_RAM_IR_COARSE_8K_KAISINC__A, 1 << (17 - IRLEN_COARSE_8K)),
+	WR16(B_SC_RA_RAM_IR_FINE_8K_LENGTH__A, IRLEN_FINE_8K),
+	WR16(B_SC_RA_RAM_IR_FINE_8K_FREQINC__A, 1 << (11 - IRLEN_FINE_8K)),
+	WR16(B_SC_RA_RAM_IR_FINE_8K_KAISINC__A, 1 << (17 - IRLEN_FINE_8K)),
+
+	WR16(B_SC_RA_RAM_IR_COARSE_2K_LENGTH__A, IRLEN_COARSE_2K),
+	WR16(B_SC_RA_RAM_IR_COARSE_2K_FREQINC__A, 1 << (11 - IRLEN_COARSE_2K)),
+	WR16(B_SC_RA_RAM_IR_COARSE_2K_KAISINC__A, 1 << (17 - IRLEN_COARSE_2K)),
+	WR16(B_SC_RA_RAM_IR_FINE_2K_LENGTH__A, IRLEN_FINE_2K),
+	WR16(B_SC_RA_RAM_IR_FINE_2K_FREQINC__A, 1 << (11 - IRLEN_FINE_2K)),
+	WR16(B_SC_RA_RAM_IR_FINE_2K_KAISINC__A, 1 << (17 - IRLEN_FINE_2K)),
+
+	WR16(B_LC_RA_RAM_FILTER_CRMM_A__A, 7),
+	WR16(B_LC_RA_RAM_FILTER_CRMM_B__A, 4),
+	WR16(B_LC_RA_RAM_FILTER_SRMM_A__A, 7),
+	WR16(B_LC_RA_RAM_FILTER_SRMM_B__A, 4),
+	WR16(B_LC_RA_RAM_FILTER_SYM_SET__A, 500),
+
+	WR16(B_CC_REG_DIVERSITY__A, 0x0001),
+	END_OF_TABLE
+};
+
+u8 DRXD_DisableDiversity[] = {
+	WR16(B_SC_RA_RAM_LC_ABS_2K__A, B_SC_RA_RAM_LC_ABS_2K__PRE),
+	WR16(B_SC_RA_RAM_LC_ABS_8K__A, B_SC_RA_RAM_LC_ABS_8K__PRE),
+	WR16(B_SC_RA_RAM_IR_COARSE_8K_LENGTH__A,
+	     B_SC_RA_RAM_IR_COARSE_8K_LENGTH__PRE),
+	WR16(B_SC_RA_RAM_IR_COARSE_8K_FREQINC__A,
+	     B_SC_RA_RAM_IR_COARSE_8K_FREQINC__PRE),
+	WR16(B_SC_RA_RAM_IR_COARSE_8K_KAISINC__A,
+	     B_SC_RA_RAM_IR_COARSE_8K_KAISINC__PRE),
+	WR16(B_SC_RA_RAM_IR_FINE_8K_LENGTH__A,
+	     B_SC_RA_RAM_IR_FINE_8K_LENGTH__PRE),
+	WR16(B_SC_RA_RAM_IR_FINE_8K_FREQINC__A,
+	     B_SC_RA_RAM_IR_FINE_8K_FREQINC__PRE),
+	WR16(B_SC_RA_RAM_IR_FINE_8K_KAISINC__A,
+	     B_SC_RA_RAM_IR_FINE_8K_KAISINC__PRE),
+
+	WR16(B_SC_RA_RAM_IR_COARSE_2K_LENGTH__A,
+	     B_SC_RA_RAM_IR_COARSE_2K_LENGTH__PRE),
+	WR16(B_SC_RA_RAM_IR_COARSE_2K_FREQINC__A,
+	     B_SC_RA_RAM_IR_COARSE_2K_FREQINC__PRE),
+	WR16(B_SC_RA_RAM_IR_COARSE_2K_KAISINC__A,
+	     B_SC_RA_RAM_IR_COARSE_2K_KAISINC__PRE),
+	WR16(B_SC_RA_RAM_IR_FINE_2K_LENGTH__A,
+	     B_SC_RA_RAM_IR_FINE_2K_LENGTH__PRE),
+	WR16(B_SC_RA_RAM_IR_FINE_2K_FREQINC__A,
+	     B_SC_RA_RAM_IR_FINE_2K_FREQINC__PRE),
+	WR16(B_SC_RA_RAM_IR_FINE_2K_KAISINC__A,
+	     B_SC_RA_RAM_IR_FINE_2K_KAISINC__PRE),
+
+	WR16(B_LC_RA_RAM_FILTER_CRMM_A__A, B_LC_RA_RAM_FILTER_CRMM_A__PRE),
+	WR16(B_LC_RA_RAM_FILTER_CRMM_B__A, B_LC_RA_RAM_FILTER_CRMM_B__PRE),
+	WR16(B_LC_RA_RAM_FILTER_SRMM_A__A, B_LC_RA_RAM_FILTER_SRMM_A__PRE),
+	WR16(B_LC_RA_RAM_FILTER_SRMM_B__A, B_LC_RA_RAM_FILTER_SRMM_B__PRE),
+	WR16(B_LC_RA_RAM_FILTER_SYM_SET__A, B_LC_RA_RAM_FILTER_SYM_SET__PRE),
+
+	WR16(B_CC_REG_DIVERSITY__A, 0x0000),
+	WR16(B_EQ_REG_RC_SEL_CAR__A, B_EQ_REG_RC_SEL_CAR_INIT),	/* combining disabled */
+
+	END_OF_TABLE
+};
+
+u8 DRXD_StartDiversityFront[] = {
+	/* Start demod, RF in and diversity out, no combining */
+	WR16(B_FE_CF_REG_IMP_VAL__A, 0x0),
+	WR16(B_FE_AD_REG_FDB_IN__A, 0x0),
+	WR16(B_FE_AD_REG_INVEXT__A, 0x0),
+	WR16(B_EQ_REG_COMM_MB__A, 0x12),	/* EQ to MB out */
+	WR16(B_EQ_REG_RC_SEL_CAR__A, B_EQ_REG_RC_SEL_CAR_PASS_B_CE |	/* CE to PASS mux */
+	     B_EQ_REG_RC_SEL_CAR_LOCAL_B_CE | B_EQ_REG_RC_SEL_CAR_MEAS_B_CE),
+
+	WR16(SC_RA_RAM_ECHO_SHIFT_LIM__A, 2),
+
+	END_OF_TABLE
+};
+
+u8 DRXD_StartDiversityEnd[] = {
+	/* End demod, combining RF in and diversity in, MPEG TS out */
+	WR16(B_FE_CF_REG_IMP_VAL__A, 0x0),	/* disable impulse noise cruncher */
+	WR16(B_FE_AD_REG_INVEXT__A, 0x0),	/* clock inversion (for sohard board) */
+	WR16(B_CP_REG_BR_STR_DEL__A, 10),	/* apperently no mb delay matching is best */
+
+	WR16(B_EQ_REG_RC_SEL_CAR__A, B_EQ_REG_RC_SEL_CAR_DIV_ON |	/* org = 0x81 combining enabled */
+	     B_EQ_REG_RC_SEL_CAR_MEAS_A_CC |
+	     B_EQ_REG_RC_SEL_CAR_PASS_A_CC | B_EQ_REG_RC_SEL_CAR_LOCAL_A_CC),
+
+	END_OF_TABLE
+};
+
+u8 DRXD_DiversityDelay8MHZ[] = {
+	WR16(B_SC_RA_RAM_DIVERSITY_DELAY_2K_32__A, 1150 - 50),
+	WR16(B_SC_RA_RAM_DIVERSITY_DELAY_2K_16__A, 1100 - 50),
+	WR16(B_SC_RA_RAM_DIVERSITY_DELAY_2K_8__A, 1000 - 50),
+	WR16(B_SC_RA_RAM_DIVERSITY_DELAY_2K_4__A, 800 - 50),
+	WR16(B_SC_RA_RAM_DIVERSITY_DELAY_8K_32__A, 5420 - 50),
+	WR16(B_SC_RA_RAM_DIVERSITY_DELAY_8K_16__A, 5200 - 50),
+	WR16(B_SC_RA_RAM_DIVERSITY_DELAY_8K_8__A, 4800 - 50),
+	WR16(B_SC_RA_RAM_DIVERSITY_DELAY_8K_4__A, 4000 - 50),
+	END_OF_TABLE
+};
+
+u8 DRXD_DiversityDelay6MHZ[] =	/* also used ok for 7 MHz */
+{
+	WR16(B_SC_RA_RAM_DIVERSITY_DELAY_2K_32__A, 1100 - 50),
+	WR16(B_SC_RA_RAM_DIVERSITY_DELAY_2K_16__A, 1000 - 50),
+	WR16(B_SC_RA_RAM_DIVERSITY_DELAY_2K_8__A, 900 - 50),
+	WR16(B_SC_RA_RAM_DIVERSITY_DELAY_2K_4__A, 600 - 50),
+	WR16(B_SC_RA_RAM_DIVERSITY_DELAY_8K_32__A, 5300 - 50),
+	WR16(B_SC_RA_RAM_DIVERSITY_DELAY_8K_16__A, 5000 - 50),
+	WR16(B_SC_RA_RAM_DIVERSITY_DELAY_8K_8__A, 4500 - 50),
+	WR16(B_SC_RA_RAM_DIVERSITY_DELAY_8K_4__A, 3500 - 50),
+	END_OF_TABLE
+};
diff --git a/drivers/media/dvb-frontends/drxd_firm.h b/drivers/media/dvb-frontends/drxd_firm.h
new file mode 100644
index 0000000..41597e8
--- /dev/null
+++ b/drivers/media/dvb-frontends/drxd_firm.h
@@ -0,0 +1,115 @@
+/*
+ * drxd_firm.h
+ *
+ * Copyright (C) 2006-2007 Micronas
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 only, as published by the Free Software Foundation.
+ *
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ */
+
+#ifndef _DRXD_FIRM_H_
+#define _DRXD_FIRM_H_
+
+#include <linux/types.h>
+#include "drxd_map_firm.h"
+
+#define VERSION_MAJOR 1
+#define VERSION_MINOR 4
+#define VERSION_PATCH 23
+
+#define HI_TR_FUNC_ADDR HI_IF_RAM_USR_BEGIN__A
+
+#define DRXD_MAX_RETRIES (1000)
+#define HI_I2C_DELAY     84
+#define HI_I2C_BRIDGE_DELAY   750
+
+#define EQ_TD_TPS_PWR_UNKNOWN          0x00C0	/* Unknown configurations */
+#define EQ_TD_TPS_PWR_QPSK             0x016a
+#define EQ_TD_TPS_PWR_QAM16_ALPHAN     0x0195
+#define EQ_TD_TPS_PWR_QAM16_ALPHA1     0x0195
+#define EQ_TD_TPS_PWR_QAM16_ALPHA2     0x011E
+#define EQ_TD_TPS_PWR_QAM16_ALPHA4     0x01CE
+#define EQ_TD_TPS_PWR_QAM64_ALPHAN     0x019F
+#define EQ_TD_TPS_PWR_QAM64_ALPHA1     0x019F
+#define EQ_TD_TPS_PWR_QAM64_ALPHA2     0x00F8
+#define EQ_TD_TPS_PWR_QAM64_ALPHA4     0x014D
+
+#define DRXD_DEF_AG_PWD_CONSUMER 0x000E
+#define DRXD_DEF_AG_PWD_PRO 0x0000
+#define DRXD_DEF_AG_AGC_SIO 0x0000
+
+#define DRXD_FE_CTRL_MAX 1023
+
+#define DRXD_OSCDEV_DO_SCAN  (16)
+
+#define DRXD_OSCDEV_DONT_SCAN  (0)
+
+#define DRXD_OSCDEV_STEP  (275)
+
+#define DRXD_SCAN_TIMEOUT    (650)
+
+#define DRXD_BANDWIDTH_8MHZ_IN_HZ  (0x8B8249L)
+#define DRXD_BANDWIDTH_7MHZ_IN_HZ  (0x7A1200L)
+#define DRXD_BANDWIDTH_6MHZ_IN_HZ  (0x68A1B6L)
+
+#define IRLEN_COARSE_8K       (10)
+#define IRLEN_FINE_8K         (10)
+#define IRLEN_COARSE_2K       (7)
+#define IRLEN_FINE_2K         (9)
+#define DIFF_INVALID          (511)
+#define DIFF_TARGET           (4)
+#define DIFF_MARGIN           (1)
+
+extern u8 DRXD_InitAtomicRead[];
+extern u8 DRXD_HiI2cPatch_1[];
+extern u8 DRXD_HiI2cPatch_3[];
+
+extern u8 DRXD_InitSC[];
+
+extern u8 DRXD_ResetCEFR[];
+extern u8 DRXD_InitFEA2_1[];
+extern u8 DRXD_InitFEA2_2[];
+extern u8 DRXD_InitCPA2[];
+extern u8 DRXD_InitCEA2[];
+extern u8 DRXD_InitEQA2[];
+extern u8 DRXD_InitECA2[];
+extern u8 DRXD_ResetECA2[];
+extern u8 DRXD_ResetECRAM[];
+
+extern u8 DRXD_A2_microcode[];
+extern u32 DRXD_A2_microcode_length;
+
+extern u8 DRXD_InitFEB1_1[];
+extern u8 DRXD_InitFEB1_2[];
+extern u8 DRXD_InitCPB1[];
+extern u8 DRXD_InitCEB1[];
+extern u8 DRXD_InitEQB1[];
+extern u8 DRXD_InitECB1[];
+
+extern u8 DRXD_InitDiversityFront[];
+extern u8 DRXD_InitDiversityEnd[];
+extern u8 DRXD_DisableDiversity[];
+extern u8 DRXD_StartDiversityFront[];
+extern u8 DRXD_StartDiversityEnd[];
+
+extern u8 DRXD_DiversityDelay8MHZ[];
+extern u8 DRXD_DiversityDelay6MHZ[];
+
+extern u8 DRXD_B1_microcode[];
+extern u32 DRXD_B1_microcode_length;
+
+#endif
diff --git a/drivers/media/dvb-frontends/drxd_hard.c b/drivers/media/dvb-frontends/drxd_hard.c
new file mode 100644
index 0000000..f380eb4
--- /dev/null
+++ b/drivers/media/dvb-frontends/drxd_hard.c
@@ -0,0 +1,2992 @@
+/*
+ * drxd_hard.c: DVB-T Demodulator Micronas DRX3975D-A2,DRX397xD-B1
+ *
+ * Copyright (C) 2003-2007 Micronas
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 only, as published by the Free Software Foundation.
+ *
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/firmware.h>
+#include <linux/i2c.h>
+#include <asm/div64.h>
+
+#include "dvb_frontend.h"
+#include "drxd.h"
+#include "drxd_firm.h"
+
+#define DRX_FW_FILENAME_A2 "drxd-a2-1.1.fw"
+#define DRX_FW_FILENAME_B1 "drxd-b1-1.1.fw"
+
+#define CHUNK_SIZE 48
+
+#define DRX_I2C_RMW           0x10
+#define DRX_I2C_BROADCAST     0x20
+#define DRX_I2C_CLEARCRC      0x80
+#define DRX_I2C_SINGLE_MASTER 0xC0
+#define DRX_I2C_MODEFLAGS     0xC0
+#define DRX_I2C_FLAGS         0xF0
+
+#ifndef SIZEOF_ARRAY
+#define SIZEOF_ARRAY(array) (sizeof((array))/sizeof((array)[0]))
+#endif
+
+#define DEFAULT_LOCK_TIMEOUT    1100
+
+#define DRX_CHANNEL_AUTO 0
+#define DRX_CHANNEL_HIGH 1
+#define DRX_CHANNEL_LOW  2
+
+#define DRX_LOCK_MPEG  1
+#define DRX_LOCK_FEC   2
+#define DRX_LOCK_DEMOD 4
+
+/****************************************************************************/
+
+enum CSCDState {
+	CSCD_INIT = 0,
+	CSCD_SET,
+	CSCD_SAVED
+};
+
+enum CDrxdState {
+	DRXD_UNINITIALIZED = 0,
+	DRXD_STOPPED,
+	DRXD_STARTED
+};
+
+enum AGC_CTRL_MODE {
+	AGC_CTRL_AUTO = 0,
+	AGC_CTRL_USER,
+	AGC_CTRL_OFF
+};
+
+enum OperationMode {
+	OM_Default,
+	OM_DVBT_Diversity_Front,
+	OM_DVBT_Diversity_End
+};
+
+struct SCfgAgc {
+	enum AGC_CTRL_MODE ctrlMode;
+	u16 outputLevel;	/* range [0, ... , 1023], 1/n of fullscale range */
+	u16 settleLevel;	/* range [0, ... , 1023], 1/n of fullscale range */
+	u16 minOutputLevel;	/* range [0, ... , 1023], 1/n of fullscale range */
+	u16 maxOutputLevel;	/* range [0, ... , 1023], 1/n of fullscale range */
+	u16 speed;		/* range [0, ... , 1023], 1/n of fullscale range */
+
+	u16 R1;
+	u16 R2;
+	u16 R3;
+};
+
+struct SNoiseCal {
+	int cpOpt;
+	short cpNexpOfs;
+	short tdCal2k;
+	short tdCal8k;
+};
+
+enum app_env {
+	APPENV_STATIC = 0,
+	APPENV_PORTABLE = 1,
+	APPENV_MOBILE = 2
+};
+
+enum EIFFilter {
+	IFFILTER_SAW = 0,
+	IFFILTER_DISCRETE = 1
+};
+
+struct drxd_state {
+	struct dvb_frontend frontend;
+	struct dvb_frontend_ops ops;
+	struct dtv_frontend_properties props;
+
+	const struct firmware *fw;
+	struct device *dev;
+
+	struct i2c_adapter *i2c;
+	void *priv;
+	struct drxd_config config;
+
+	int i2c_access;
+	int init_done;
+	struct mutex mutex;
+
+	u8 chip_adr;
+	u16 hi_cfg_timing_div;
+	u16 hi_cfg_bridge_delay;
+	u16 hi_cfg_wakeup_key;
+	u16 hi_cfg_ctrl;
+
+	u16 intermediate_freq;
+	u16 osc_clock_freq;
+
+	enum CSCDState cscd_state;
+	enum CDrxdState drxd_state;
+
+	u16 sys_clock_freq;
+	s16 osc_clock_deviation;
+	u16 expected_sys_clock_freq;
+
+	u16 insert_rs_byte;
+	u16 enable_parallel;
+
+	int operation_mode;
+
+	struct SCfgAgc if_agc_cfg;
+	struct SCfgAgc rf_agc_cfg;
+
+	struct SNoiseCal noise_cal;
+
+	u32 fe_fs_add_incr;
+	u32 org_fe_fs_add_incr;
+	u16 current_fe_if_incr;
+
+	u16 m_FeAgRegAgPwd;
+	u16 m_FeAgRegAgAgcSio;
+
+	u16 m_EcOcRegOcModeLop;
+	u16 m_EcOcRegSncSncLvl;
+	u8 *m_InitAtomicRead;
+	u8 *m_HiI2cPatch;
+
+	u8 *m_ResetCEFR;
+	u8 *m_InitFE_1;
+	u8 *m_InitFE_2;
+	u8 *m_InitCP;
+	u8 *m_InitCE;
+	u8 *m_InitEQ;
+	u8 *m_InitSC;
+	u8 *m_InitEC;
+	u8 *m_ResetECRAM;
+	u8 *m_InitDiversityFront;
+	u8 *m_InitDiversityEnd;
+	u8 *m_DisableDiversity;
+	u8 *m_StartDiversityFront;
+	u8 *m_StartDiversityEnd;
+
+	u8 *m_DiversityDelay8MHZ;
+	u8 *m_DiversityDelay6MHZ;
+
+	u8 *microcode;
+	u32 microcode_length;
+
+	int type_A;
+	int PGA;
+	int diversity;
+	int tuner_mirrors;
+
+	enum app_env app_env_default;
+	enum app_env app_env_diversity;
+
+};
+
+/****************************************************************************/
+/* I2C **********************************************************************/
+/****************************************************************************/
+
+static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 * data, int len)
+{
+	struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = data, .len = len };
+
+	if (i2c_transfer(adap, &msg, 1) != 1)
+		return -1;
+	return 0;
+}
+
+static int i2c_read(struct i2c_adapter *adap,
+		    u8 adr, u8 *msg, int len, u8 *answ, int alen)
+{
+	struct i2c_msg msgs[2] = {
+		{
+			.addr = adr, .flags = 0,
+			.buf = msg, .len = len
+		}, {
+			.addr = adr, .flags = I2C_M_RD,
+			.buf = answ, .len = alen
+		}
+	};
+	if (i2c_transfer(adap, msgs, 2) != 2)
+		return -1;
+	return 0;
+}
+
+static inline u32 MulDiv32(u32 a, u32 b, u32 c)
+{
+	u64 tmp64;
+
+	tmp64 = (u64)a * (u64)b;
+	do_div(tmp64, c);
+
+	return (u32) tmp64;
+}
+
+static int Read16(struct drxd_state *state, u32 reg, u16 *data, u8 flags)
+{
+	u8 adr = state->config.demod_address;
+	u8 mm1[4] = { reg & 0xff, (reg >> 16) & 0xff,
+		flags | ((reg >> 24) & 0xff), (reg >> 8) & 0xff
+	};
+	u8 mm2[2];
+	if (i2c_read(state->i2c, adr, mm1, 4, mm2, 2) < 0)
+		return -1;
+	if (data)
+		*data = mm2[0] | (mm2[1] << 8);
+	return mm2[0] | (mm2[1] << 8);
+}
+
+static int Read32(struct drxd_state *state, u32 reg, u32 *data, u8 flags)
+{
+	u8 adr = state->config.demod_address;
+	u8 mm1[4] = { reg & 0xff, (reg >> 16) & 0xff,
+		flags | ((reg >> 24) & 0xff), (reg >> 8) & 0xff
+	};
+	u8 mm2[4];
+
+	if (i2c_read(state->i2c, adr, mm1, 4, mm2, 4) < 0)
+		return -1;
+	if (data)
+		*data =
+		    mm2[0] | (mm2[1] << 8) | (mm2[2] << 16) | (mm2[3] << 24);
+	return 0;
+}
+
+static int Write16(struct drxd_state *state, u32 reg, u16 data, u8 flags)
+{
+	u8 adr = state->config.demod_address;
+	u8 mm[6] = { reg & 0xff, (reg >> 16) & 0xff,
+		flags | ((reg >> 24) & 0xff), (reg >> 8) & 0xff,
+		data & 0xff, (data >> 8) & 0xff
+	};
+
+	if (i2c_write(state->i2c, adr, mm, 6) < 0)
+		return -1;
+	return 0;
+}
+
+static int Write32(struct drxd_state *state, u32 reg, u32 data, u8 flags)
+{
+	u8 adr = state->config.demod_address;
+	u8 mm[8] = { reg & 0xff, (reg >> 16) & 0xff,
+		flags | ((reg >> 24) & 0xff), (reg >> 8) & 0xff,
+		data & 0xff, (data >> 8) & 0xff,
+		(data >> 16) & 0xff, (data >> 24) & 0xff
+	};
+
+	if (i2c_write(state->i2c, adr, mm, 8) < 0)
+		return -1;
+	return 0;
+}
+
+static int write_chunk(struct drxd_state *state,
+		       u32 reg, u8 *data, u32 len, u8 flags)
+{
+	u8 adr = state->config.demod_address;
+	u8 mm[CHUNK_SIZE + 4] = { reg & 0xff, (reg >> 16) & 0xff,
+		flags | ((reg >> 24) & 0xff), (reg >> 8) & 0xff
+	};
+	int i;
+
+	for (i = 0; i < len; i++)
+		mm[4 + i] = data[i];
+	if (i2c_write(state->i2c, adr, mm, 4 + len) < 0) {
+		printk(KERN_ERR "error in write_chunk\n");
+		return -1;
+	}
+	return 0;
+}
+
+static int WriteBlock(struct drxd_state *state,
+		      u32 Address, u16 BlockSize, u8 *pBlock, u8 Flags)
+{
+	while (BlockSize > 0) {
+		u16 Chunk = BlockSize > CHUNK_SIZE ? CHUNK_SIZE : BlockSize;
+
+		if (write_chunk(state, Address, pBlock, Chunk, Flags) < 0)
+			return -1;
+		pBlock += Chunk;
+		Address += (Chunk >> 1);
+		BlockSize -= Chunk;
+	}
+	return 0;
+}
+
+static int WriteTable(struct drxd_state *state, u8 * pTable)
+{
+	int status = 0;
+
+	if (pTable == NULL)
+		return 0;
+
+	while (!status) {
+		u16 Length;
+		u32 Address = pTable[0] | (pTable[1] << 8) |
+		    (pTable[2] << 16) | (pTable[3] << 24);
+
+		if (Address == 0xFFFFFFFF)
+			break;
+		pTable += sizeof(u32);
+
+		Length = pTable[0] | (pTable[1] << 8);
+		pTable += sizeof(u16);
+		if (!Length)
+			break;
+		status = WriteBlock(state, Address, Length * 2, pTable, 0);
+		pTable += (Length * 2);
+	}
+	return status;
+}
+
+/****************************************************************************/
+/****************************************************************************/
+/****************************************************************************/
+
+static int ResetCEFR(struct drxd_state *state)
+{
+	return WriteTable(state, state->m_ResetCEFR);
+}
+
+static int InitCP(struct drxd_state *state)
+{
+	return WriteTable(state, state->m_InitCP);
+}
+
+static int InitCE(struct drxd_state *state)
+{
+	int status;
+	enum app_env AppEnv = state->app_env_default;
+
+	do {
+		status = WriteTable(state, state->m_InitCE);
+		if (status < 0)
+			break;
+
+		if (state->operation_mode == OM_DVBT_Diversity_Front ||
+		    state->operation_mode == OM_DVBT_Diversity_End) {
+			AppEnv = state->app_env_diversity;
+		}
+		if (AppEnv == APPENV_STATIC) {
+			status = Write16(state, CE_REG_TAPSET__A, 0x0000, 0);
+			if (status < 0)
+				break;
+		} else if (AppEnv == APPENV_PORTABLE) {
+			status = Write16(state, CE_REG_TAPSET__A, 0x0001, 0);
+			if (status < 0)
+				break;
+		} else if (AppEnv == APPENV_MOBILE && state->type_A) {
+			status = Write16(state, CE_REG_TAPSET__A, 0x0002, 0);
+			if (status < 0)
+				break;
+		} else if (AppEnv == APPENV_MOBILE && !state->type_A) {
+			status = Write16(state, CE_REG_TAPSET__A, 0x0006, 0);
+			if (status < 0)
+				break;
+		}
+
+		/* start ce */
+		status = Write16(state, B_CE_REG_COMM_EXEC__A, 0x0001, 0);
+		if (status < 0)
+			break;
+	} while (0);
+	return status;
+}
+
+static int StopOC(struct drxd_state *state)
+{
+	int status = 0;
+	u16 ocSyncLvl = 0;
+	u16 ocModeLop = state->m_EcOcRegOcModeLop;
+	u16 dtoIncLop = 0;
+	u16 dtoIncHip = 0;
+
+	do {
+		/* Store output configuration */
+		status = Read16(state, EC_OC_REG_SNC_ISC_LVL__A, &ocSyncLvl, 0);
+		if (status < 0)
+			break;
+		/* CHK_ERROR(Read16(EC_OC_REG_OC_MODE_LOP__A, &ocModeLop)); */
+		state->m_EcOcRegSncSncLvl = ocSyncLvl;
+		/* m_EcOcRegOcModeLop = ocModeLop; */
+
+		/* Flush FIFO (byte-boundary) at fixed rate */
+		status = Read16(state, EC_OC_REG_RCN_MAP_LOP__A, &dtoIncLop, 0);
+		if (status < 0)
+			break;
+		status = Read16(state, EC_OC_REG_RCN_MAP_HIP__A, &dtoIncHip, 0);
+		if (status < 0)
+			break;
+		status = Write16(state, EC_OC_REG_DTO_INC_LOP__A, dtoIncLop, 0);
+		if (status < 0)
+			break;
+		status = Write16(state, EC_OC_REG_DTO_INC_HIP__A, dtoIncHip, 0);
+		if (status < 0)
+			break;
+		ocModeLop &= ~(EC_OC_REG_OC_MODE_LOP_DTO_CTR_SRC__M);
+		ocModeLop |= EC_OC_REG_OC_MODE_LOP_DTO_CTR_SRC_STATIC;
+		status = Write16(state, EC_OC_REG_OC_MODE_LOP__A, ocModeLop, 0);
+		if (status < 0)
+			break;
+		status = Write16(state, EC_OC_REG_COMM_EXEC__A, EC_OC_REG_COMM_EXEC_CTL_HOLD, 0);
+		if (status < 0)
+			break;
+
+		msleep(1);
+		/* Output pins to '0' */
+		status = Write16(state, EC_OC_REG_OCR_MPG_UOS__A, EC_OC_REG_OCR_MPG_UOS__M, 0);
+		if (status < 0)
+			break;
+
+		/* Force the OC out of sync */
+		ocSyncLvl &= ~(EC_OC_REG_SNC_ISC_LVL_OSC__M);
+		status = Write16(state, EC_OC_REG_SNC_ISC_LVL__A, ocSyncLvl, 0);
+		if (status < 0)
+			break;
+		ocModeLop &= ~(EC_OC_REG_OC_MODE_LOP_PAR_ENA__M);
+		ocModeLop |= EC_OC_REG_OC_MODE_LOP_PAR_ENA_ENABLE;
+		ocModeLop |= 0x2;	/* Magically-out-of-sync */
+		status = Write16(state, EC_OC_REG_OC_MODE_LOP__A, ocModeLop, 0);
+		if (status < 0)
+			break;
+		status = Write16(state, EC_OC_REG_COMM_INT_STA__A, 0x0, 0);
+		if (status < 0)
+			break;
+		status = Write16(state, EC_OC_REG_COMM_EXEC__A, EC_OC_REG_COMM_EXEC_CTL_ACTIVE, 0);
+		if (status < 0)
+			break;
+	} while (0);
+
+	return status;
+}
+
+static int StartOC(struct drxd_state *state)
+{
+	int status = 0;
+
+	do {
+		/* Stop OC */
+		status = Write16(state, EC_OC_REG_COMM_EXEC__A, EC_OC_REG_COMM_EXEC_CTL_HOLD, 0);
+		if (status < 0)
+			break;
+
+		/* Restore output configuration */
+		status = Write16(state, EC_OC_REG_SNC_ISC_LVL__A, state->m_EcOcRegSncSncLvl, 0);
+		if (status < 0)
+			break;
+		status = Write16(state, EC_OC_REG_OC_MODE_LOP__A, state->m_EcOcRegOcModeLop, 0);
+		if (status < 0)
+			break;
+
+		/* Output pins active again */
+		status = Write16(state, EC_OC_REG_OCR_MPG_UOS__A, EC_OC_REG_OCR_MPG_UOS_INIT, 0);
+		if (status < 0)
+			break;
+
+		/* Start OC */
+		status = Write16(state, EC_OC_REG_COMM_EXEC__A, EC_OC_REG_COMM_EXEC_CTL_ACTIVE, 0);
+		if (status < 0)
+			break;
+	} while (0);
+	return status;
+}
+
+static int InitEQ(struct drxd_state *state)
+{
+	return WriteTable(state, state->m_InitEQ);
+}
+
+static int InitEC(struct drxd_state *state)
+{
+	return WriteTable(state, state->m_InitEC);
+}
+
+static int InitSC(struct drxd_state *state)
+{
+	return WriteTable(state, state->m_InitSC);
+}
+
+static int InitAtomicRead(struct drxd_state *state)
+{
+	return WriteTable(state, state->m_InitAtomicRead);
+}
+
+static int CorrectSysClockDeviation(struct drxd_state *state);
+
+static int DRX_GetLockStatus(struct drxd_state *state, u32 * pLockStatus)
+{
+	u16 ScRaRamLock = 0;
+	const u16 mpeg_lock_mask = (SC_RA_RAM_LOCK_MPEG__M |
+				    SC_RA_RAM_LOCK_FEC__M |
+				    SC_RA_RAM_LOCK_DEMOD__M);
+	const u16 fec_lock_mask = (SC_RA_RAM_LOCK_FEC__M |
+				   SC_RA_RAM_LOCK_DEMOD__M);
+	const u16 demod_lock_mask = SC_RA_RAM_LOCK_DEMOD__M;
+
+	int status;
+
+	*pLockStatus = 0;
+
+	status = Read16(state, SC_RA_RAM_LOCK__A, &ScRaRamLock, 0x0000);
+	if (status < 0) {
+		printk(KERN_ERR "Can't read SC_RA_RAM_LOCK__A status = %08x\n", status);
+		return status;
+	}
+
+	if (state->drxd_state != DRXD_STARTED)
+		return 0;
+
+	if ((ScRaRamLock & mpeg_lock_mask) == mpeg_lock_mask) {
+		*pLockStatus |= DRX_LOCK_MPEG;
+		CorrectSysClockDeviation(state);
+	}
+
+	if ((ScRaRamLock & fec_lock_mask) == fec_lock_mask)
+		*pLockStatus |= DRX_LOCK_FEC;
+
+	if ((ScRaRamLock & demod_lock_mask) == demod_lock_mask)
+		*pLockStatus |= DRX_LOCK_DEMOD;
+	return 0;
+}
+
+/****************************************************************************/
+
+static int SetCfgIfAgc(struct drxd_state *state, struct SCfgAgc *cfg)
+{
+	int status;
+
+	if (cfg->outputLevel > DRXD_FE_CTRL_MAX)
+		return -1;
+
+	if (cfg->ctrlMode == AGC_CTRL_USER) {
+		do {
+			u16 FeAgRegPm1AgcWri;
+			u16 FeAgRegAgModeLop;
+
+			status = Read16(state, FE_AG_REG_AG_MODE_LOP__A, &FeAgRegAgModeLop, 0);
+			if (status < 0)
+				break;
+			FeAgRegAgModeLop &= (~FE_AG_REG_AG_MODE_LOP_MODE_4__M);
+			FeAgRegAgModeLop |= FE_AG_REG_AG_MODE_LOP_MODE_4_STATIC;
+			status = Write16(state, FE_AG_REG_AG_MODE_LOP__A, FeAgRegAgModeLop, 0);
+			if (status < 0)
+				break;
+
+			FeAgRegPm1AgcWri = (u16) (cfg->outputLevel &
+						  FE_AG_REG_PM1_AGC_WRI__M);
+			status = Write16(state, FE_AG_REG_PM1_AGC_WRI__A, FeAgRegPm1AgcWri, 0);
+			if (status < 0)
+				break;
+		} while (0);
+	} else if (cfg->ctrlMode == AGC_CTRL_AUTO) {
+		if (((cfg->maxOutputLevel) < (cfg->minOutputLevel)) ||
+		    ((cfg->maxOutputLevel) > DRXD_FE_CTRL_MAX) ||
+		    ((cfg->speed) > DRXD_FE_CTRL_MAX) ||
+		    ((cfg->settleLevel) > DRXD_FE_CTRL_MAX)
+		    )
+			return -1;
+		do {
+			u16 FeAgRegAgModeLop;
+			u16 FeAgRegEgcSetLvl;
+			u16 slope, offset;
+
+			/* == Mode == */
+
+			status = Read16(state, FE_AG_REG_AG_MODE_LOP__A, &FeAgRegAgModeLop, 0);
+			if (status < 0)
+				break;
+			FeAgRegAgModeLop &= (~FE_AG_REG_AG_MODE_LOP_MODE_4__M);
+			FeAgRegAgModeLop |=
+			    FE_AG_REG_AG_MODE_LOP_MODE_4_DYNAMIC;
+			status = Write16(state, FE_AG_REG_AG_MODE_LOP__A, FeAgRegAgModeLop, 0);
+			if (status < 0)
+				break;
+
+			/* == Settle level == */
+
+			FeAgRegEgcSetLvl = (u16) ((cfg->settleLevel >> 1) &
+						  FE_AG_REG_EGC_SET_LVL__M);
+			status = Write16(state, FE_AG_REG_EGC_SET_LVL__A, FeAgRegEgcSetLvl, 0);
+			if (status < 0)
+				break;
+
+			/* == Min/Max == */
+
+			slope = (u16) ((cfg->maxOutputLevel -
+					cfg->minOutputLevel) / 2);
+			offset = (u16) ((cfg->maxOutputLevel +
+					 cfg->minOutputLevel) / 2 - 511);
+
+			status = Write16(state, FE_AG_REG_GC1_AGC_RIC__A, slope, 0);
+			if (status < 0)
+				break;
+			status = Write16(state, FE_AG_REG_GC1_AGC_OFF__A, offset, 0);
+			if (status < 0)
+				break;
+
+			/* == Speed == */
+			{
+				const u16 maxRur = 8;
+				const u16 slowIncrDecLUT[] = { 3, 4, 4, 5, 6 };
+				const u16 fastIncrDecLUT[] = { 14, 15, 15, 16,
+					17, 18, 18, 19,
+					20, 21, 22, 23,
+					24, 26, 27, 28,
+					29, 31
+				};
+
+				u16 fineSteps = (DRXD_FE_CTRL_MAX + 1) /
+				    (maxRur + 1);
+				u16 fineSpeed = (u16) (cfg->speed -
+						       ((cfg->speed /
+							 fineSteps) *
+							fineSteps));
+				u16 invRurCount = (u16) (cfg->speed /
+							 fineSteps);
+				u16 rurCount;
+				if (invRurCount > maxRur) {
+					rurCount = 0;
+					fineSpeed += fineSteps;
+				} else {
+					rurCount = maxRur - invRurCount;
+				}
+
+				/*
+				   fastInc = default *
+				   (2^(fineSpeed/fineSteps))
+				   => range[default...2*default>
+				   slowInc = default *
+				   (2^(fineSpeed/fineSteps))
+				 */
+				{
+					u16 fastIncrDec =
+					    fastIncrDecLUT[fineSpeed /
+							   ((fineSteps /
+							     (14 + 1)) + 1)];
+					u16 slowIncrDec =
+					    slowIncrDecLUT[fineSpeed /
+							   (fineSteps /
+							    (3 + 1))];
+
+					status = Write16(state, FE_AG_REG_EGC_RUR_CNT__A, rurCount, 0);
+					if (status < 0)
+						break;
+					status = Write16(state, FE_AG_REG_EGC_FAS_INC__A, fastIncrDec, 0);
+					if (status < 0)
+						break;
+					status = Write16(state, FE_AG_REG_EGC_FAS_DEC__A, fastIncrDec, 0);
+					if (status < 0)
+						break;
+					status = Write16(state, FE_AG_REG_EGC_SLO_INC__A, slowIncrDec, 0);
+					if (status < 0)
+						break;
+					status = Write16(state, FE_AG_REG_EGC_SLO_DEC__A, slowIncrDec, 0);
+					if (status < 0)
+						break;
+				}
+			}
+		} while (0);
+
+	} else {
+		/* No OFF mode for IF control */
+		return -1;
+	}
+	return status;
+}
+
+static int SetCfgRfAgc(struct drxd_state *state, struct SCfgAgc *cfg)
+{
+	int status = 0;
+
+	if (cfg->outputLevel > DRXD_FE_CTRL_MAX)
+		return -1;
+
+	if (cfg->ctrlMode == AGC_CTRL_USER) {
+		do {
+			u16 AgModeLop = 0;
+			u16 level = (cfg->outputLevel);
+
+			if (level == DRXD_FE_CTRL_MAX)
+				level++;
+
+			status = Write16(state, FE_AG_REG_PM2_AGC_WRI__A, level, 0x0000);
+			if (status < 0)
+				break;
+
+			/*==== Mode ====*/
+
+			/* Powerdown PD2, WRI source */
+			state->m_FeAgRegAgPwd &= ~(FE_AG_REG_AG_PWD_PWD_PD2__M);
+			state->m_FeAgRegAgPwd |=
+			    FE_AG_REG_AG_PWD_PWD_PD2_DISABLE;
+			status = Write16(state, FE_AG_REG_AG_PWD__A, state->m_FeAgRegAgPwd, 0x0000);
+			if (status < 0)
+				break;
+
+			status = Read16(state, FE_AG_REG_AG_MODE_LOP__A, &AgModeLop, 0x0000);
+			if (status < 0)
+				break;
+			AgModeLop &= (~(FE_AG_REG_AG_MODE_LOP_MODE_5__M |
+					FE_AG_REG_AG_MODE_LOP_MODE_E__M));
+			AgModeLop |= (FE_AG_REG_AG_MODE_LOP_MODE_5_STATIC |
+				      FE_AG_REG_AG_MODE_LOP_MODE_E_STATIC);
+			status = Write16(state, FE_AG_REG_AG_MODE_LOP__A, AgModeLop, 0x0000);
+			if (status < 0)
+				break;
+
+			/* enable AGC2 pin */
+			{
+				u16 FeAgRegAgAgcSio = 0;
+				status = Read16(state, FE_AG_REG_AG_AGC_SIO__A, &FeAgRegAgAgcSio, 0x0000);
+				if (status < 0)
+					break;
+				FeAgRegAgAgcSio &=
+				    ~(FE_AG_REG_AG_AGC_SIO_AGC_SIO_2__M);
+				FeAgRegAgAgcSio |=
+				    FE_AG_REG_AG_AGC_SIO_AGC_SIO_2_OUTPUT;
+				status = Write16(state, FE_AG_REG_AG_AGC_SIO__A, FeAgRegAgAgcSio, 0x0000);
+				if (status < 0)
+					break;
+			}
+
+		} while (0);
+	} else if (cfg->ctrlMode == AGC_CTRL_AUTO) {
+		u16 AgModeLop = 0;
+
+		do {
+			u16 level;
+			/* Automatic control */
+			/* Powerup PD2, AGC2 as output, TGC source */
+			(state->m_FeAgRegAgPwd) &=
+			    ~(FE_AG_REG_AG_PWD_PWD_PD2__M);
+			(state->m_FeAgRegAgPwd) |=
+			    FE_AG_REG_AG_PWD_PWD_PD2_DISABLE;
+			status = Write16(state, FE_AG_REG_AG_PWD__A, (state->m_FeAgRegAgPwd), 0x0000);
+			if (status < 0)
+				break;
+
+			status = Read16(state, FE_AG_REG_AG_MODE_LOP__A, &AgModeLop, 0x0000);
+			if (status < 0)
+				break;
+			AgModeLop &= (~(FE_AG_REG_AG_MODE_LOP_MODE_5__M |
+					FE_AG_REG_AG_MODE_LOP_MODE_E__M));
+			AgModeLop |= (FE_AG_REG_AG_MODE_LOP_MODE_5_STATIC |
+				      FE_AG_REG_AG_MODE_LOP_MODE_E_DYNAMIC);
+			status = Write16(state, FE_AG_REG_AG_MODE_LOP__A, AgModeLop, 0x0000);
+			if (status < 0)
+				break;
+			/* Settle level */
+			level = (((cfg->settleLevel) >> 4) &
+				 FE_AG_REG_TGC_SET_LVL__M);
+			status = Write16(state, FE_AG_REG_TGC_SET_LVL__A, level, 0x0000);
+			if (status < 0)
+				break;
+
+			/* Min/max: don't care */
+
+			/* Speed: TODO */
+
+			/* enable AGC2 pin */
+			{
+				u16 FeAgRegAgAgcSio = 0;
+				status = Read16(state, FE_AG_REG_AG_AGC_SIO__A, &FeAgRegAgAgcSio, 0x0000);
+				if (status < 0)
+					break;
+				FeAgRegAgAgcSio &=
+				    ~(FE_AG_REG_AG_AGC_SIO_AGC_SIO_2__M);
+				FeAgRegAgAgcSio |=
+				    FE_AG_REG_AG_AGC_SIO_AGC_SIO_2_OUTPUT;
+				status = Write16(state, FE_AG_REG_AG_AGC_SIO__A, FeAgRegAgAgcSio, 0x0000);
+				if (status < 0)
+					break;
+			}
+
+		} while (0);
+	} else {
+		u16 AgModeLop = 0;
+
+		do {
+			/* No RF AGC control */
+			/* Powerdown PD2, AGC2 as output, WRI source */
+			(state->m_FeAgRegAgPwd) &=
+			    ~(FE_AG_REG_AG_PWD_PWD_PD2__M);
+			(state->m_FeAgRegAgPwd) |=
+			    FE_AG_REG_AG_PWD_PWD_PD2_ENABLE;
+			status = Write16(state, FE_AG_REG_AG_PWD__A, (state->m_FeAgRegAgPwd), 0x0000);
+			if (status < 0)
+				break;
+
+			status = Read16(state, FE_AG_REG_AG_MODE_LOP__A, &AgModeLop, 0x0000);
+			if (status < 0)
+				break;
+			AgModeLop &= (~(FE_AG_REG_AG_MODE_LOP_MODE_5__M |
+					FE_AG_REG_AG_MODE_LOP_MODE_E__M));
+			AgModeLop |= (FE_AG_REG_AG_MODE_LOP_MODE_5_STATIC |
+				      FE_AG_REG_AG_MODE_LOP_MODE_E_STATIC);
+			status = Write16(state, FE_AG_REG_AG_MODE_LOP__A, AgModeLop, 0x0000);
+			if (status < 0)
+				break;
+
+			/* set FeAgRegAgAgcSio AGC2 (RF) as input */
+			{
+				u16 FeAgRegAgAgcSio = 0;
+				status = Read16(state, FE_AG_REG_AG_AGC_SIO__A, &FeAgRegAgAgcSio, 0x0000);
+				if (status < 0)
+					break;
+				FeAgRegAgAgcSio &=
+				    ~(FE_AG_REG_AG_AGC_SIO_AGC_SIO_2__M);
+				FeAgRegAgAgcSio |=
+				    FE_AG_REG_AG_AGC_SIO_AGC_SIO_2_INPUT;
+				status = Write16(state, FE_AG_REG_AG_AGC_SIO__A, FeAgRegAgAgcSio, 0x0000);
+				if (status < 0)
+					break;
+			}
+		} while (0);
+	}
+	return status;
+}
+
+static int ReadIFAgc(struct drxd_state *state, u32 * pValue)
+{
+	int status = 0;
+
+	*pValue = 0;
+	if (state->if_agc_cfg.ctrlMode != AGC_CTRL_OFF) {
+		u16 Value;
+		status = Read16(state, FE_AG_REG_GC1_AGC_DAT__A, &Value, 0);
+		Value &= FE_AG_REG_GC1_AGC_DAT__M;
+		if (status >= 0) {
+			/*           3.3V
+			   |
+			   R1
+			   |
+			   Vin - R3 - * -- Vout
+			   |
+			   R2
+			   |
+			   GND
+			 */
+			u32 R1 = state->if_agc_cfg.R1;
+			u32 R2 = state->if_agc_cfg.R2;
+			u32 R3 = state->if_agc_cfg.R3;
+
+			u32 Vmax, Rpar, Vmin, Vout;
+
+			if (R2 == 0 && (R1 == 0 || R3 == 0))
+				return 0;
+
+			Vmax = (3300 * R2) / (R1 + R2);
+			Rpar = (R2 * R3) / (R3 + R2);
+			Vmin = (3300 * Rpar) / (R1 + Rpar);
+			Vout = Vmin + ((Vmax - Vmin) * Value) / 1024;
+
+			*pValue = Vout;
+		}
+	}
+	return status;
+}
+
+static int load_firmware(struct drxd_state *state, const char *fw_name)
+{
+	const struct firmware *fw;
+
+	if (request_firmware(&fw, fw_name, state->dev) < 0) {
+		printk(KERN_ERR "drxd: firmware load failure [%s]\n", fw_name);
+		return -EIO;
+	}
+
+	state->microcode = kmemdup(fw->data, fw->size, GFP_KERNEL);
+	if (state->microcode == NULL) {
+		release_firmware(fw);
+		printk(KERN_ERR "drxd: firmware load failure: no memory\n");
+		return -ENOMEM;
+	}
+
+	state->microcode_length = fw->size;
+	release_firmware(fw);
+	return 0;
+}
+
+static int DownloadMicrocode(struct drxd_state *state,
+			     const u8 *pMCImage, u32 Length)
+{
+	u8 *pSrc;
+	u32 Address;
+	u16 nBlocks;
+	u16 BlockSize;
+	u32 offset = 0;
+	int i, status = 0;
+
+	pSrc = (u8 *) pMCImage;
+	/* We're not using Flags */
+	/* Flags = (pSrc[0] << 8) | pSrc[1]; */
+	pSrc += sizeof(u16);
+	offset += sizeof(u16);
+	nBlocks = (pSrc[0] << 8) | pSrc[1];
+	pSrc += sizeof(u16);
+	offset += sizeof(u16);
+
+	for (i = 0; i < nBlocks; i++) {
+		Address = (pSrc[0] << 24) | (pSrc[1] << 16) |
+		    (pSrc[2] << 8) | pSrc[3];
+		pSrc += sizeof(u32);
+		offset += sizeof(u32);
+
+		BlockSize = ((pSrc[0] << 8) | pSrc[1]) * sizeof(u16);
+		pSrc += sizeof(u16);
+		offset += sizeof(u16);
+
+		/* We're not using Flags */
+		/* u16 Flags = (pSrc[0] << 8) | pSrc[1]; */
+		pSrc += sizeof(u16);
+		offset += sizeof(u16);
+
+		/* We're not using BlockCRC */
+		/* u16 BlockCRC = (pSrc[0] << 8) | pSrc[1]; */
+		pSrc += sizeof(u16);
+		offset += sizeof(u16);
+
+		status = WriteBlock(state, Address, BlockSize,
+				    pSrc, DRX_I2C_CLEARCRC);
+		if (status < 0)
+			break;
+		pSrc += BlockSize;
+		offset += BlockSize;
+	}
+
+	return status;
+}
+
+static int HI_Command(struct drxd_state *state, u16 cmd, u16 * pResult)
+{
+	u32 nrRetries = 0;
+	u16 waitCmd;
+	int status;
+
+	status = Write16(state, HI_RA_RAM_SRV_CMD__A, cmd, 0);
+	if (status < 0)
+		return status;
+
+	do {
+		nrRetries += 1;
+		if (nrRetries > DRXD_MAX_RETRIES) {
+			status = -1;
+			break;
+		};
+		status = Read16(state, HI_RA_RAM_SRV_CMD__A, &waitCmd, 0);
+	} while (waitCmd != 0);
+
+	if (status >= 0)
+		status = Read16(state, HI_RA_RAM_SRV_RES__A, pResult, 0);
+	return status;
+}
+
+static int HI_CfgCommand(struct drxd_state *state)
+{
+	int status = 0;
+
+	mutex_lock(&state->mutex);
+	Write16(state, HI_RA_RAM_SRV_CFG_KEY__A, HI_RA_RAM_SRV_RST_KEY_ACT, 0);
+	Write16(state, HI_RA_RAM_SRV_CFG_DIV__A, state->hi_cfg_timing_div, 0);
+	Write16(state, HI_RA_RAM_SRV_CFG_BDL__A, state->hi_cfg_bridge_delay, 0);
+	Write16(state, HI_RA_RAM_SRV_CFG_WUP__A, state->hi_cfg_wakeup_key, 0);
+	Write16(state, HI_RA_RAM_SRV_CFG_ACT__A, state->hi_cfg_ctrl, 0);
+
+	Write16(state, HI_RA_RAM_SRV_CFG_KEY__A, HI_RA_RAM_SRV_RST_KEY_ACT, 0);
+
+	if ((state->hi_cfg_ctrl & HI_RA_RAM_SRV_CFG_ACT_PWD_EXE) ==
+	    HI_RA_RAM_SRV_CFG_ACT_PWD_EXE)
+		status = Write16(state, HI_RA_RAM_SRV_CMD__A,
+				 HI_RA_RAM_SRV_CMD_CONFIG, 0);
+	else
+		status = HI_Command(state, HI_RA_RAM_SRV_CMD_CONFIG, 0);
+	mutex_unlock(&state->mutex);
+	return status;
+}
+
+static int InitHI(struct drxd_state *state)
+{
+	state->hi_cfg_wakeup_key = (state->chip_adr);
+	/* port/bridge/power down ctrl */
+	state->hi_cfg_ctrl = HI_RA_RAM_SRV_CFG_ACT_SLV0_ON;
+	return HI_CfgCommand(state);
+}
+
+static int HI_ResetCommand(struct drxd_state *state)
+{
+	int status;
+
+	mutex_lock(&state->mutex);
+	status = Write16(state, HI_RA_RAM_SRV_RST_KEY__A,
+			 HI_RA_RAM_SRV_RST_KEY_ACT, 0);
+	if (status == 0)
+		status = HI_Command(state, HI_RA_RAM_SRV_CMD_RESET, 0);
+	mutex_unlock(&state->mutex);
+	msleep(1);
+	return status;
+}
+
+static int DRX_ConfigureI2CBridge(struct drxd_state *state, int bEnableBridge)
+{
+	state->hi_cfg_ctrl &= (~HI_RA_RAM_SRV_CFG_ACT_BRD__M);
+	if (bEnableBridge)
+		state->hi_cfg_ctrl |= HI_RA_RAM_SRV_CFG_ACT_BRD_ON;
+	else
+		state->hi_cfg_ctrl |= HI_RA_RAM_SRV_CFG_ACT_BRD_OFF;
+
+	return HI_CfgCommand(state);
+}
+
+#define HI_TR_WRITE      0x9
+#define HI_TR_READ       0xA
+#define HI_TR_READ_WRITE 0xB
+#define HI_TR_BROADCAST  0x4
+
+#if 0
+static int AtomicReadBlock(struct drxd_state *state,
+			   u32 Addr, u16 DataSize, u8 *pData, u8 Flags)
+{
+	int status;
+	int i = 0;
+
+	/* Parameter check */
+	if ((!pData) || ((DataSize & 1) != 0))
+		return -1;
+
+	mutex_lock(&state->mutex);
+
+	do {
+		/* Instruct HI to read n bytes */
+		/* TODO use proper names forthese egisters */
+		status = Write16(state, HI_RA_RAM_SRV_CFG_KEY__A, (HI_TR_FUNC_ADDR & 0xFFFF), 0);
+		if (status < 0)
+			break;
+		status = Write16(state, HI_RA_RAM_SRV_CFG_DIV__A, (u16) (Addr >> 16), 0);
+		if (status < 0)
+			break;
+		status = Write16(state, HI_RA_RAM_SRV_CFG_BDL__A, (u16) (Addr & 0xFFFF), 0);
+		if (status < 0)
+			break;
+		status = Write16(state, HI_RA_RAM_SRV_CFG_WUP__A, (u16) ((DataSize / 2) - 1), 0);
+		if (status < 0)
+			break;
+		status = Write16(state, HI_RA_RAM_SRV_CFG_ACT__A, HI_TR_READ, 0);
+		if (status < 0)
+			break;
+
+		status = HI_Command(state, HI_RA_RAM_SRV_CMD_EXECUTE, 0);
+		if (status < 0)
+			break;
+
+	} while (0);
+
+	if (status >= 0) {
+		for (i = 0; i < (DataSize / 2); i += 1) {
+			u16 word;
+
+			status = Read16(state, (HI_RA_RAM_USR_BEGIN__A + i),
+					&word, 0);
+			if (status < 0)
+				break;
+			pData[2 * i] = (u8) (word & 0xFF);
+			pData[(2 * i) + 1] = (u8) (word >> 8);
+		}
+	}
+	mutex_unlock(&state->mutex);
+	return status;
+}
+
+static int AtomicReadReg32(struct drxd_state *state,
+			   u32 Addr, u32 *pData, u8 Flags)
+{
+	u8 buf[sizeof(u32)];
+	int status;
+
+	if (!pData)
+		return -1;
+	status = AtomicReadBlock(state, Addr, sizeof(u32), buf, Flags);
+	*pData = (((u32) buf[0]) << 0) +
+	    (((u32) buf[1]) << 8) +
+	    (((u32) buf[2]) << 16) + (((u32) buf[3]) << 24);
+	return status;
+}
+#endif
+
+static int StopAllProcessors(struct drxd_state *state)
+{
+	return Write16(state, HI_COMM_EXEC__A,
+		       SC_COMM_EXEC_CTL_STOP, DRX_I2C_BROADCAST);
+}
+
+static int EnableAndResetMB(struct drxd_state *state)
+{
+	if (state->type_A) {
+		/* disable? monitor bus observe @ EC_OC */
+		Write16(state, EC_OC_REG_OC_MON_SIO__A, 0x0000, 0x0000);
+	}
+
+	/* do inverse broadcast, followed by explicit write to HI */
+	Write16(state, HI_COMM_MB__A, 0x0000, DRX_I2C_BROADCAST);
+	Write16(state, HI_COMM_MB__A, 0x0000, 0x0000);
+	return 0;
+}
+
+static int InitCC(struct drxd_state *state)
+{
+	if (state->osc_clock_freq == 0 ||
+	    state->osc_clock_freq > 20000 ||
+	    (state->osc_clock_freq % 4000) != 0) {
+		printk(KERN_ERR "invalid osc frequency %d\n", state->osc_clock_freq);
+		return -1;
+	}
+
+	Write16(state, CC_REG_OSC_MODE__A, CC_REG_OSC_MODE_M20, 0);
+	Write16(state, CC_REG_PLL_MODE__A, CC_REG_PLL_MODE_BYPASS_PLL |
+		CC_REG_PLL_MODE_PUMP_CUR_12, 0);
+	Write16(state, CC_REG_REF_DIVIDE__A, state->osc_clock_freq / 4000, 0);
+	Write16(state, CC_REG_PWD_MODE__A, CC_REG_PWD_MODE_DOWN_PLL, 0);
+	Write16(state, CC_REG_UPDATE__A, CC_REG_UPDATE_KEY, 0);
+
+	return 0;
+}
+
+static int ResetECOD(struct drxd_state *state)
+{
+	int status = 0;
+
+	if (state->type_A)
+		status = Write16(state, EC_OD_REG_SYNC__A, 0x0664, 0);
+	else
+		status = Write16(state, B_EC_OD_REG_SYNC__A, 0x0664, 0);
+
+	if (!(status < 0))
+		status = WriteTable(state, state->m_ResetECRAM);
+	if (!(status < 0))
+		status = Write16(state, EC_OD_REG_COMM_EXEC__A, 0x0001, 0);
+	return status;
+}
+
+/* Configure PGA switch */
+
+static int SetCfgPga(struct drxd_state *state, int pgaSwitch)
+{
+	int status;
+	u16 AgModeLop = 0;
+	u16 AgModeHip = 0;
+	do {
+		if (pgaSwitch) {
+			/* PGA on */
+			/* fine gain */
+			status = Read16(state, B_FE_AG_REG_AG_MODE_LOP__A, &AgModeLop, 0x0000);
+			if (status < 0)
+				break;
+			AgModeLop &= (~(B_FE_AG_REG_AG_MODE_LOP_MODE_C__M));
+			AgModeLop |= B_FE_AG_REG_AG_MODE_LOP_MODE_C_DYNAMIC;
+			status = Write16(state, B_FE_AG_REG_AG_MODE_LOP__A, AgModeLop, 0x0000);
+			if (status < 0)
+				break;
+
+			/* coarse gain */
+			status = Read16(state, B_FE_AG_REG_AG_MODE_HIP__A, &AgModeHip, 0x0000);
+			if (status < 0)
+				break;
+			AgModeHip &= (~(B_FE_AG_REG_AG_MODE_HIP_MODE_J__M));
+			AgModeHip |= B_FE_AG_REG_AG_MODE_HIP_MODE_J_DYNAMIC;
+			status = Write16(state, B_FE_AG_REG_AG_MODE_HIP__A, AgModeHip, 0x0000);
+			if (status < 0)
+				break;
+
+			/* enable fine and coarse gain, enable AAF,
+			   no ext resistor */
+			status = Write16(state, B_FE_AG_REG_AG_PGA_MODE__A, B_FE_AG_REG_AG_PGA_MODE_PFY_PCY_AFY_REN, 0x0000);
+			if (status < 0)
+				break;
+		} else {
+			/* PGA off, bypass */
+
+			/* fine gain */
+			status = Read16(state, B_FE_AG_REG_AG_MODE_LOP__A, &AgModeLop, 0x0000);
+			if (status < 0)
+				break;
+			AgModeLop &= (~(B_FE_AG_REG_AG_MODE_LOP_MODE_C__M));
+			AgModeLop |= B_FE_AG_REG_AG_MODE_LOP_MODE_C_STATIC;
+			status = Write16(state, B_FE_AG_REG_AG_MODE_LOP__A, AgModeLop, 0x0000);
+			if (status < 0)
+				break;
+
+			/* coarse gain */
+			status = Read16(state, B_FE_AG_REG_AG_MODE_HIP__A, &AgModeHip, 0x0000);
+			if (status < 0)
+				break;
+			AgModeHip &= (~(B_FE_AG_REG_AG_MODE_HIP_MODE_J__M));
+			AgModeHip |= B_FE_AG_REG_AG_MODE_HIP_MODE_J_STATIC;
+			status = Write16(state, B_FE_AG_REG_AG_MODE_HIP__A, AgModeHip, 0x0000);
+			if (status < 0)
+				break;
+
+			/* disable fine and coarse gain, enable AAF,
+			   no ext resistor */
+			status = Write16(state, B_FE_AG_REG_AG_PGA_MODE__A, B_FE_AG_REG_AG_PGA_MODE_PFN_PCN_AFY_REN, 0x0000);
+			if (status < 0)
+				break;
+		}
+	} while (0);
+	return status;
+}
+
+static int InitFE(struct drxd_state *state)
+{
+	int status;
+
+	do {
+		status = WriteTable(state, state->m_InitFE_1);
+		if (status < 0)
+			break;
+
+		if (state->type_A) {
+			status = Write16(state, FE_AG_REG_AG_PGA_MODE__A,
+					 FE_AG_REG_AG_PGA_MODE_PFN_PCN_AFY_REN,
+					 0);
+		} else {
+			if (state->PGA)
+				status = SetCfgPga(state, 0);
+			else
+				status =
+				    Write16(state, B_FE_AG_REG_AG_PGA_MODE__A,
+					    B_FE_AG_REG_AG_PGA_MODE_PFN_PCN_AFY_REN,
+					    0);
+		}
+
+		if (status < 0)
+			break;
+		status = Write16(state, FE_AG_REG_AG_AGC_SIO__A, state->m_FeAgRegAgAgcSio, 0x0000);
+		if (status < 0)
+			break;
+		status = Write16(state, FE_AG_REG_AG_PWD__A, state->m_FeAgRegAgPwd, 0x0000);
+		if (status < 0)
+			break;
+
+		status = WriteTable(state, state->m_InitFE_2);
+		if (status < 0)
+			break;
+
+	} while (0);
+
+	return status;
+}
+
+static int InitFT(struct drxd_state *state)
+{
+	/*
+	   norm OFFSET,  MB says =2 voor 8K en =3 voor 2K waarschijnlijk
+	   SC stuff
+	 */
+	return Write16(state, FT_REG_COMM_EXEC__A, 0x0001, 0x0000);
+}
+
+static int SC_WaitForReady(struct drxd_state *state)
+{
+	u16 curCmd;
+	int i;
+
+	for (i = 0; i < DRXD_MAX_RETRIES; i += 1) {
+		int status = Read16(state, SC_RA_RAM_CMD__A, &curCmd, 0);
+		if (status == 0 || curCmd == 0)
+			return status;
+	}
+	return -1;
+}
+
+static int SC_SendCommand(struct drxd_state *state, u16 cmd)
+{
+	int status = 0;
+	u16 errCode;
+
+	Write16(state, SC_RA_RAM_CMD__A, cmd, 0);
+	SC_WaitForReady(state);
+
+	Read16(state, SC_RA_RAM_CMD_ADDR__A, &errCode, 0);
+
+	if (errCode == 0xFFFF) {
+		printk(KERN_ERR "Command Error\n");
+		status = -1;
+	}
+
+	return status;
+}
+
+static int SC_ProcStartCommand(struct drxd_state *state,
+			       u16 subCmd, u16 param0, u16 param1)
+{
+	int status = 0;
+	u16 scExec;
+
+	mutex_lock(&state->mutex);
+	do {
+		Read16(state, SC_COMM_EXEC__A, &scExec, 0);
+		if (scExec != 1) {
+			status = -1;
+			break;
+		}
+		SC_WaitForReady(state);
+		Write16(state, SC_RA_RAM_CMD_ADDR__A, subCmd, 0);
+		Write16(state, SC_RA_RAM_PARAM1__A, param1, 0);
+		Write16(state, SC_RA_RAM_PARAM0__A, param0, 0);
+
+		SC_SendCommand(state, SC_RA_RAM_CMD_PROC_START);
+	} while (0);
+	mutex_unlock(&state->mutex);
+	return status;
+}
+
+static int SC_SetPrefParamCommand(struct drxd_state *state,
+				  u16 subCmd, u16 param0, u16 param1)
+{
+	int status;
+
+	mutex_lock(&state->mutex);
+	do {
+		status = SC_WaitForReady(state);
+		if (status < 0)
+			break;
+		status = Write16(state, SC_RA_RAM_CMD_ADDR__A, subCmd, 0);
+		if (status < 0)
+			break;
+		status = Write16(state, SC_RA_RAM_PARAM1__A, param1, 0);
+		if (status < 0)
+			break;
+		status = Write16(state, SC_RA_RAM_PARAM0__A, param0, 0);
+		if (status < 0)
+			break;
+
+		status = SC_SendCommand(state, SC_RA_RAM_CMD_SET_PREF_PARAM);
+		if (status < 0)
+			break;
+	} while (0);
+	mutex_unlock(&state->mutex);
+	return status;
+}
+
+#if 0
+static int SC_GetOpParamCommand(struct drxd_state *state, u16 * result)
+{
+	int status = 0;
+
+	mutex_lock(&state->mutex);
+	do {
+		status = SC_WaitForReady(state);
+		if (status < 0)
+			break;
+		status = SC_SendCommand(state, SC_RA_RAM_CMD_GET_OP_PARAM);
+		if (status < 0)
+			break;
+		status = Read16(state, SC_RA_RAM_PARAM0__A, result, 0);
+		if (status < 0)
+			break;
+	} while (0);
+	mutex_unlock(&state->mutex);
+	return status;
+}
+#endif
+
+static int ConfigureMPEGOutput(struct drxd_state *state, int bEnableOutput)
+{
+	int status;
+
+	do {
+		u16 EcOcRegIprInvMpg = 0;
+		u16 EcOcRegOcModeLop = 0;
+		u16 EcOcRegOcModeHip = 0;
+		u16 EcOcRegOcMpgSio = 0;
+
+		/*CHK_ERROR(Read16(state, EC_OC_REG_OC_MODE_LOP__A, &EcOcRegOcModeLop, 0)); */
+
+		if (state->operation_mode == OM_DVBT_Diversity_Front) {
+			if (bEnableOutput) {
+				EcOcRegOcModeHip |=
+				    B_EC_OC_REG_OC_MODE_HIP_MPG_BUS_SRC_MONITOR;
+			} else
+				EcOcRegOcMpgSio |= EC_OC_REG_OC_MPG_SIO__M;
+			EcOcRegOcModeLop |=
+			    EC_OC_REG_OC_MODE_LOP_PAR_ENA_DISABLE;
+		} else {
+			EcOcRegOcModeLop = state->m_EcOcRegOcModeLop;
+
+			if (bEnableOutput)
+				EcOcRegOcMpgSio &= (~(EC_OC_REG_OC_MPG_SIO__M));
+			else
+				EcOcRegOcMpgSio |= EC_OC_REG_OC_MPG_SIO__M;
+
+			/* Don't Insert RS Byte */
+			if (state->insert_rs_byte) {
+				EcOcRegOcModeLop &=
+				    (~(EC_OC_REG_OC_MODE_LOP_PAR_ENA__M));
+				EcOcRegOcModeHip &=
+				    (~EC_OC_REG_OC_MODE_HIP_MPG_PAR_VAL__M);
+				EcOcRegOcModeHip |=
+				    EC_OC_REG_OC_MODE_HIP_MPG_PAR_VAL_ENABLE;
+			} else {
+				EcOcRegOcModeLop |=
+				    EC_OC_REG_OC_MODE_LOP_PAR_ENA_DISABLE;
+				EcOcRegOcModeHip &=
+				    (~EC_OC_REG_OC_MODE_HIP_MPG_PAR_VAL__M);
+				EcOcRegOcModeHip |=
+				    EC_OC_REG_OC_MODE_HIP_MPG_PAR_VAL_DISABLE;
+			}
+
+			/* Mode = Parallel */
+			if (state->enable_parallel)
+				EcOcRegOcModeLop &=
+				    (~(EC_OC_REG_OC_MODE_LOP_MPG_TRM_MDE__M));
+			else
+				EcOcRegOcModeLop |=
+				    EC_OC_REG_OC_MODE_LOP_MPG_TRM_MDE_SERIAL;
+		}
+		/* Invert Data */
+		/* EcOcRegIprInvMpg |= 0x00FF; */
+		EcOcRegIprInvMpg &= (~(0x00FF));
+
+		/* Invert Error ( we don't use the pin ) */
+		/*  EcOcRegIprInvMpg |= 0x0100; */
+		EcOcRegIprInvMpg &= (~(0x0100));
+
+		/* Invert Start ( we don't use the pin ) */
+		/* EcOcRegIprInvMpg |= 0x0200; */
+		EcOcRegIprInvMpg &= (~(0x0200));
+
+		/* Invert Valid ( we don't use the pin ) */
+		/* EcOcRegIprInvMpg |= 0x0400; */
+		EcOcRegIprInvMpg &= (~(0x0400));
+
+		/* Invert Clock */
+		/* EcOcRegIprInvMpg |= 0x0800; */
+		EcOcRegIprInvMpg &= (~(0x0800));
+
+		/* EcOcRegOcModeLop =0x05; */
+		status = Write16(state, EC_OC_REG_IPR_INV_MPG__A, EcOcRegIprInvMpg, 0);
+		if (status < 0)
+			break;
+		status = Write16(state, EC_OC_REG_OC_MODE_LOP__A, EcOcRegOcModeLop, 0);
+		if (status < 0)
+			break;
+		status = Write16(state, EC_OC_REG_OC_MODE_HIP__A, EcOcRegOcModeHip, 0x0000);
+		if (status < 0)
+			break;
+		status = Write16(state, EC_OC_REG_OC_MPG_SIO__A, EcOcRegOcMpgSio, 0);
+		if (status < 0)
+			break;
+	} while (0);
+	return status;
+}
+
+static int SetDeviceTypeId(struct drxd_state *state)
+{
+	int status = 0;
+	u16 deviceId = 0;
+
+	do {
+		status = Read16(state, CC_REG_JTAGID_L__A, &deviceId, 0);
+		if (status < 0)
+			break;
+		/* TODO: why twice? */
+		status = Read16(state, CC_REG_JTAGID_L__A, &deviceId, 0);
+		if (status < 0)
+			break;
+		printk(KERN_INFO "drxd: deviceId = %04x\n", deviceId);
+
+		state->type_A = 0;
+		state->PGA = 0;
+		state->diversity = 0;
+		if (deviceId == 0) {	/* on A2 only 3975 available */
+			state->type_A = 1;
+			printk(KERN_INFO "DRX3975D-A2\n");
+		} else {
+			deviceId >>= 12;
+			printk(KERN_INFO "DRX397%dD-B1\n", deviceId);
+			switch (deviceId) {
+			case 4:
+				state->diversity = 1;
+			case 3:
+			case 7:
+				state->PGA = 1;
+				break;
+			case 6:
+				state->diversity = 1;
+			case 5:
+			case 8:
+				break;
+			default:
+				status = -1;
+				break;
+			}
+		}
+	} while (0);
+
+	if (status < 0)
+		return status;
+
+	/* Init Table selection */
+	state->m_InitAtomicRead = DRXD_InitAtomicRead;
+	state->m_InitSC = DRXD_InitSC;
+	state->m_ResetECRAM = DRXD_ResetECRAM;
+	if (state->type_A) {
+		state->m_ResetCEFR = DRXD_ResetCEFR;
+		state->m_InitFE_1 = DRXD_InitFEA2_1;
+		state->m_InitFE_2 = DRXD_InitFEA2_2;
+		state->m_InitCP = DRXD_InitCPA2;
+		state->m_InitCE = DRXD_InitCEA2;
+		state->m_InitEQ = DRXD_InitEQA2;
+		state->m_InitEC = DRXD_InitECA2;
+		if (load_firmware(state, DRX_FW_FILENAME_A2))
+			return -EIO;
+	} else {
+		state->m_ResetCEFR = NULL;
+		state->m_InitFE_1 = DRXD_InitFEB1_1;
+		state->m_InitFE_2 = DRXD_InitFEB1_2;
+		state->m_InitCP = DRXD_InitCPB1;
+		state->m_InitCE = DRXD_InitCEB1;
+		state->m_InitEQ = DRXD_InitEQB1;
+		state->m_InitEC = DRXD_InitECB1;
+		if (load_firmware(state, DRX_FW_FILENAME_B1))
+			return -EIO;
+	}
+	if (state->diversity) {
+		state->m_InitDiversityFront = DRXD_InitDiversityFront;
+		state->m_InitDiversityEnd = DRXD_InitDiversityEnd;
+		state->m_DisableDiversity = DRXD_DisableDiversity;
+		state->m_StartDiversityFront = DRXD_StartDiversityFront;
+		state->m_StartDiversityEnd = DRXD_StartDiversityEnd;
+		state->m_DiversityDelay8MHZ = DRXD_DiversityDelay8MHZ;
+		state->m_DiversityDelay6MHZ = DRXD_DiversityDelay6MHZ;
+	} else {
+		state->m_InitDiversityFront = NULL;
+		state->m_InitDiversityEnd = NULL;
+		state->m_DisableDiversity = NULL;
+		state->m_StartDiversityFront = NULL;
+		state->m_StartDiversityEnd = NULL;
+		state->m_DiversityDelay8MHZ = NULL;
+		state->m_DiversityDelay6MHZ = NULL;
+	}
+
+	return status;
+}
+
+static int CorrectSysClockDeviation(struct drxd_state *state)
+{
+	int status;
+	s32 incr = 0;
+	s32 nomincr = 0;
+	u32 bandwidth = 0;
+	u32 sysClockInHz = 0;
+	u32 sysClockFreq = 0;	/* in kHz */
+	s16 oscClockDeviation;
+	s16 Diff;
+
+	do {
+		/* Retrieve bandwidth and incr, sanity check */
+
+		/* These accesses should be AtomicReadReg32, but that
+		   causes trouble (at least for diversity */
+		status = Read32(state, LC_RA_RAM_IFINCR_NOM_L__A, ((u32 *) &nomincr), 0);
+		if (status < 0)
+			break;
+		status = Read32(state, FE_IF_REG_INCR0__A, (u32 *) &incr, 0);
+		if (status < 0)
+			break;
+
+		if (state->type_A) {
+			if ((nomincr - incr < -500) || (nomincr - incr > 500))
+				break;
+		} else {
+			if ((nomincr - incr < -2000) || (nomincr - incr > 2000))
+				break;
+		}
+
+		switch (state->props.bandwidth_hz) {
+		case 8000000:
+			bandwidth = DRXD_BANDWIDTH_8MHZ_IN_HZ;
+			break;
+		case 7000000:
+			bandwidth = DRXD_BANDWIDTH_7MHZ_IN_HZ;
+			break;
+		case 6000000:
+			bandwidth = DRXD_BANDWIDTH_6MHZ_IN_HZ;
+			break;
+		default:
+			return -1;
+			break;
+		}
+
+		/* Compute new sysclock value
+		   sysClockFreq = (((incr + 2^23)*bandwidth)/2^21)/1000 */
+		incr += (1 << 23);
+		sysClockInHz = MulDiv32(incr, bandwidth, 1 << 21);
+		sysClockFreq = (u32) (sysClockInHz / 1000);
+		/* rounding */
+		if ((sysClockInHz % 1000) > 500)
+			sysClockFreq++;
+
+		/* Compute clock deviation in ppm */
+		oscClockDeviation = (u16) ((((s32) (sysClockFreq) -
+					     (s32)
+					     (state->expected_sys_clock_freq)) *
+					    1000000L) /
+					   (s32)
+					   (state->expected_sys_clock_freq));
+
+		Diff = oscClockDeviation - state->osc_clock_deviation;
+		/*printk(KERN_INFO "sysclockdiff=%d\n", Diff); */
+		if (Diff >= -200 && Diff <= 200) {
+			state->sys_clock_freq = (u16) sysClockFreq;
+			if (oscClockDeviation != state->osc_clock_deviation) {
+				if (state->config.osc_deviation) {
+					state->config.osc_deviation(state->priv,
+								    oscClockDeviation,
+								    1);
+					state->osc_clock_deviation =
+					    oscClockDeviation;
+				}
+			}
+			/* switch OFF SRMM scan in SC */
+			status = Write16(state, SC_RA_RAM_SAMPLE_RATE_COUNT__A, DRXD_OSCDEV_DONT_SCAN, 0);
+			if (status < 0)
+				break;
+			/* overrule FE_IF internal value for
+			   proper re-locking */
+			status = Write16(state, SC_RA_RAM_IF_SAVE__AX, state->current_fe_if_incr, 0);
+			if (status < 0)
+				break;
+			state->cscd_state = CSCD_SAVED;
+		}
+	} while (0);
+
+	return status;
+}
+
+static int DRX_Stop(struct drxd_state *state)
+{
+	int status;
+
+	if (state->drxd_state != DRXD_STARTED)
+		return 0;
+
+	do {
+		if (state->cscd_state != CSCD_SAVED) {
+			u32 lock;
+			status = DRX_GetLockStatus(state, &lock);
+			if (status < 0)
+				break;
+		}
+
+		status = StopOC(state);
+		if (status < 0)
+			break;
+
+		state->drxd_state = DRXD_STOPPED;
+
+		status = ConfigureMPEGOutput(state, 0);
+		if (status < 0)
+			break;
+
+		if (state->type_A) {
+			/* Stop relevant processors off the device */
+			status = Write16(state, EC_OD_REG_COMM_EXEC__A, 0x0000, 0x0000);
+			if (status < 0)
+				break;
+
+			status = Write16(state, SC_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0);
+			if (status < 0)
+				break;
+			status = Write16(state, LC_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0);
+			if (status < 0)
+				break;
+		} else {
+			/* Stop all processors except HI & CC & FE */
+			status = Write16(state, B_SC_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0);
+			if (status < 0)
+				break;
+			status = Write16(state, B_LC_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0);
+			if (status < 0)
+				break;
+			status = Write16(state, B_FT_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0);
+			if (status < 0)
+				break;
+			status = Write16(state, B_CP_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0);
+			if (status < 0)
+				break;
+			status = Write16(state, B_CE_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0);
+			if (status < 0)
+				break;
+			status = Write16(state, B_EQ_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0);
+			if (status < 0)
+				break;
+			status = Write16(state, EC_OD_REG_COMM_EXEC__A, 0x0000, 0);
+			if (status < 0)
+				break;
+		}
+
+	} while (0);
+	return status;
+}
+
+int SetOperationMode(struct drxd_state *state, int oMode)
+{
+	int status;
+
+	do {
+		if (state->drxd_state != DRXD_STOPPED) {
+			status = -1;
+			break;
+		}
+
+		if (oMode == state->operation_mode) {
+			status = 0;
+			break;
+		}
+
+		if (oMode != OM_Default && !state->diversity) {
+			status = -1;
+			break;
+		}
+
+		switch (oMode) {
+		case OM_DVBT_Diversity_Front:
+			status = WriteTable(state, state->m_InitDiversityFront);
+			break;
+		case OM_DVBT_Diversity_End:
+			status = WriteTable(state, state->m_InitDiversityEnd);
+			break;
+		case OM_Default:
+			/* We need to check how to
+			   get DRXD out of diversity */
+		default:
+			status = WriteTable(state, state->m_DisableDiversity);
+			break;
+		}
+	} while (0);
+
+	if (!status)
+		state->operation_mode = oMode;
+	return status;
+}
+
+static int StartDiversity(struct drxd_state *state)
+{
+	int status = 0;
+	u16 rcControl;
+
+	do {
+		if (state->operation_mode == OM_DVBT_Diversity_Front) {
+			status = WriteTable(state, state->m_StartDiversityFront);
+			if (status < 0)
+				break;
+		} else if (state->operation_mode == OM_DVBT_Diversity_End) {
+			status = WriteTable(state, state->m_StartDiversityEnd);
+			if (status < 0)
+				break;
+			if (state->props.bandwidth_hz == 8000000) {
+				status = WriteTable(state, state->m_DiversityDelay8MHZ);
+				if (status < 0)
+					break;
+			} else {
+				status = WriteTable(state, state->m_DiversityDelay6MHZ);
+				if (status < 0)
+					break;
+			}
+
+			status = Read16(state, B_EQ_REG_RC_SEL_CAR__A, &rcControl, 0);
+			if (status < 0)
+				break;
+			rcControl &= ~(B_EQ_REG_RC_SEL_CAR_FFTMODE__M);
+			rcControl |= B_EQ_REG_RC_SEL_CAR_DIV_ON |
+			    /*  combining enabled */
+			    B_EQ_REG_RC_SEL_CAR_MEAS_A_CC |
+			    B_EQ_REG_RC_SEL_CAR_PASS_A_CC |
+			    B_EQ_REG_RC_SEL_CAR_LOCAL_A_CC;
+			status = Write16(state, B_EQ_REG_RC_SEL_CAR__A, rcControl, 0);
+			if (status < 0)
+				break;
+		}
+	} while (0);
+	return status;
+}
+
+static int SetFrequencyShift(struct drxd_state *state,
+			     u32 offsetFreq, int channelMirrored)
+{
+	int negativeShift = (state->tuner_mirrors == channelMirrored);
+
+	/* Handle all mirroring
+	 *
+	 * Note: ADC mirroring (aliasing) is implictly handled by limiting
+	 * feFsRegAddInc to 28 bits below
+	 * (if the result before masking is more than 28 bits, this means
+	 *  that the ADC is mirroring.
+	 * The masking is in fact the aliasing of the ADC)
+	 *
+	 */
+
+	/* Compute register value, unsigned computation */
+	state->fe_fs_add_incr = MulDiv32(state->intermediate_freq +
+					 offsetFreq,
+					 1 << 28, state->sys_clock_freq);
+	/* Remove integer part */
+	state->fe_fs_add_incr &= 0x0FFFFFFFL;
+	if (negativeShift)
+		state->fe_fs_add_incr = ((1 << 28) - state->fe_fs_add_incr);
+
+	/* Save the frequency shift without tunerOffset compensation
+	   for CtrlGetChannel. */
+	state->org_fe_fs_add_incr = MulDiv32(state->intermediate_freq,
+					     1 << 28, state->sys_clock_freq);
+	/* Remove integer part */
+	state->org_fe_fs_add_incr &= 0x0FFFFFFFL;
+	if (negativeShift)
+		state->org_fe_fs_add_incr = ((1L << 28) -
+					     state->org_fe_fs_add_incr);
+
+	return Write32(state, FE_FS_REG_ADD_INC_LOP__A,
+		       state->fe_fs_add_incr, 0);
+}
+
+static int SetCfgNoiseCalibration(struct drxd_state *state,
+				  struct SNoiseCal *noiseCal)
+{
+	u16 beOptEna;
+	int status = 0;
+
+	do {
+		status = Read16(state, SC_RA_RAM_BE_OPT_ENA__A, &beOptEna, 0);
+		if (status < 0)
+			break;
+		if (noiseCal->cpOpt) {
+			beOptEna |= (1 << SC_RA_RAM_BE_OPT_ENA_CP_OPT);
+		} else {
+			beOptEna &= ~(1 << SC_RA_RAM_BE_OPT_ENA_CP_OPT);
+			status = Write16(state, CP_REG_AC_NEXP_OFFS__A, noiseCal->cpNexpOfs, 0);
+			if (status < 0)
+				break;
+		}
+		status = Write16(state, SC_RA_RAM_BE_OPT_ENA__A, beOptEna, 0);
+		if (status < 0)
+			break;
+
+		if (!state->type_A) {
+			status = Write16(state, B_SC_RA_RAM_CO_TD_CAL_2K__A, noiseCal->tdCal2k, 0);
+			if (status < 0)
+				break;
+			status = Write16(state, B_SC_RA_RAM_CO_TD_CAL_8K__A, noiseCal->tdCal8k, 0);
+			if (status < 0)
+				break;
+		}
+	} while (0);
+
+	return status;
+}
+
+static int DRX_Start(struct drxd_state *state, s32 off)
+{
+	struct dtv_frontend_properties *p = &state->props;
+	int status;
+
+	u16 transmissionParams = 0;
+	u16 operationMode = 0;
+	u16 qpskTdTpsPwr = 0;
+	u16 qam16TdTpsPwr = 0;
+	u16 qam64TdTpsPwr = 0;
+	u32 feIfIncr = 0;
+	u32 bandwidth = 0;
+	int mirrorFreqSpect;
+
+	u16 qpskSnCeGain = 0;
+	u16 qam16SnCeGain = 0;
+	u16 qam64SnCeGain = 0;
+	u16 qpskIsGainMan = 0;
+	u16 qam16IsGainMan = 0;
+	u16 qam64IsGainMan = 0;
+	u16 qpskIsGainExp = 0;
+	u16 qam16IsGainExp = 0;
+	u16 qam64IsGainExp = 0;
+	u16 bandwidthParam = 0;
+
+	if (off < 0)
+		off = (off - 500) / 1000;
+	else
+		off = (off + 500) / 1000;
+
+	do {
+		if (state->drxd_state != DRXD_STOPPED)
+			return -1;
+		status = ResetECOD(state);
+		if (status < 0)
+			break;
+		if (state->type_A) {
+			status = InitSC(state);
+			if (status < 0)
+				break;
+		} else {
+			status = InitFT(state);
+			if (status < 0)
+				break;
+			status = InitCP(state);
+			if (status < 0)
+				break;
+			status = InitCE(state);
+			if (status < 0)
+				break;
+			status = InitEQ(state);
+			if (status < 0)
+				break;
+			status = InitSC(state);
+			if (status < 0)
+				break;
+		}
+
+		/* Restore current IF & RF AGC settings */
+
+		status = SetCfgIfAgc(state, &state->if_agc_cfg);
+		if (status < 0)
+			break;
+		status = SetCfgRfAgc(state, &state->rf_agc_cfg);
+		if (status < 0)
+			break;
+
+		mirrorFreqSpect = (state->props.inversion == INVERSION_ON);
+
+		switch (p->transmission_mode) {
+		default:	/* Not set, detect it automatically */
+			operationMode |= SC_RA_RAM_OP_AUTO_MODE__M;
+			/* fall through , try first guess DRX_FFTMODE_8K */
+		case TRANSMISSION_MODE_8K:
+			transmissionParams |= SC_RA_RAM_OP_PARAM_MODE_8K;
+			if (state->type_A) {
+				status = Write16(state, EC_SB_REG_TR_MODE__A, EC_SB_REG_TR_MODE_8K, 0x0000);
+				if (status < 0)
+					break;
+				qpskSnCeGain = 99;
+				qam16SnCeGain = 83;
+				qam64SnCeGain = 67;
+			}
+			break;
+		case TRANSMISSION_MODE_2K:
+			transmissionParams |= SC_RA_RAM_OP_PARAM_MODE_2K;
+			if (state->type_A) {
+				status = Write16(state, EC_SB_REG_TR_MODE__A, EC_SB_REG_TR_MODE_2K, 0x0000);
+				if (status < 0)
+					break;
+				qpskSnCeGain = 97;
+				qam16SnCeGain = 71;
+				qam64SnCeGain = 65;
+			}
+			break;
+		}
+
+		switch (p->guard_interval) {
+		case GUARD_INTERVAL_1_4:
+			transmissionParams |= SC_RA_RAM_OP_PARAM_GUARD_4;
+			break;
+		case GUARD_INTERVAL_1_8:
+			transmissionParams |= SC_RA_RAM_OP_PARAM_GUARD_8;
+			break;
+		case GUARD_INTERVAL_1_16:
+			transmissionParams |= SC_RA_RAM_OP_PARAM_GUARD_16;
+			break;
+		case GUARD_INTERVAL_1_32:
+			transmissionParams |= SC_RA_RAM_OP_PARAM_GUARD_32;
+			break;
+		default:	/* Not set, detect it automatically */
+			operationMode |= SC_RA_RAM_OP_AUTO_GUARD__M;
+			/* try first guess 1/4 */
+			transmissionParams |= SC_RA_RAM_OP_PARAM_GUARD_4;
+			break;
+		}
+
+		switch (p->hierarchy) {
+		case HIERARCHY_1:
+			transmissionParams |= SC_RA_RAM_OP_PARAM_HIER_A1;
+			if (state->type_A) {
+				status = Write16(state, EQ_REG_OT_ALPHA__A, 0x0001, 0x0000);
+				if (status < 0)
+					break;
+				status = Write16(state, EC_SB_REG_ALPHA__A, 0x0001, 0x0000);
+				if (status < 0)
+					break;
+
+				qpskTdTpsPwr = EQ_TD_TPS_PWR_UNKNOWN;
+				qam16TdTpsPwr = EQ_TD_TPS_PWR_QAM16_ALPHA1;
+				qam64TdTpsPwr = EQ_TD_TPS_PWR_QAM64_ALPHA1;
+
+				qpskIsGainMan =
+				    SC_RA_RAM_EQ_IS_GAIN_UNKNOWN_MAN__PRE;
+				qam16IsGainMan =
+				    SC_RA_RAM_EQ_IS_GAIN_16QAM_MAN__PRE;
+				qam64IsGainMan =
+				    SC_RA_RAM_EQ_IS_GAIN_64QAM_MAN__PRE;
+
+				qpskIsGainExp =
+				    SC_RA_RAM_EQ_IS_GAIN_UNKNOWN_EXP__PRE;
+				qam16IsGainExp =
+				    SC_RA_RAM_EQ_IS_GAIN_16QAM_EXP__PRE;
+				qam64IsGainExp =
+				    SC_RA_RAM_EQ_IS_GAIN_64QAM_EXP__PRE;
+			}
+			break;
+
+		case HIERARCHY_2:
+			transmissionParams |= SC_RA_RAM_OP_PARAM_HIER_A2;
+			if (state->type_A) {
+				status = Write16(state, EQ_REG_OT_ALPHA__A, 0x0002, 0x0000);
+				if (status < 0)
+					break;
+				status = Write16(state, EC_SB_REG_ALPHA__A, 0x0002, 0x0000);
+				if (status < 0)
+					break;
+
+				qpskTdTpsPwr = EQ_TD_TPS_PWR_UNKNOWN;
+				qam16TdTpsPwr = EQ_TD_TPS_PWR_QAM16_ALPHA2;
+				qam64TdTpsPwr = EQ_TD_TPS_PWR_QAM64_ALPHA2;
+
+				qpskIsGainMan =
+				    SC_RA_RAM_EQ_IS_GAIN_UNKNOWN_MAN__PRE;
+				qam16IsGainMan =
+				    SC_RA_RAM_EQ_IS_GAIN_16QAM_A2_MAN__PRE;
+				qam64IsGainMan =
+				    SC_RA_RAM_EQ_IS_GAIN_64QAM_A2_MAN__PRE;
+
+				qpskIsGainExp =
+				    SC_RA_RAM_EQ_IS_GAIN_UNKNOWN_EXP__PRE;
+				qam16IsGainExp =
+				    SC_RA_RAM_EQ_IS_GAIN_16QAM_A2_EXP__PRE;
+				qam64IsGainExp =
+				    SC_RA_RAM_EQ_IS_GAIN_64QAM_A2_EXP__PRE;
+			}
+			break;
+		case HIERARCHY_4:
+			transmissionParams |= SC_RA_RAM_OP_PARAM_HIER_A4;
+			if (state->type_A) {
+				status = Write16(state, EQ_REG_OT_ALPHA__A, 0x0003, 0x0000);
+				if (status < 0)
+					break;
+				status = Write16(state, EC_SB_REG_ALPHA__A, 0x0003, 0x0000);
+				if (status < 0)
+					break;
+
+				qpskTdTpsPwr = EQ_TD_TPS_PWR_UNKNOWN;
+				qam16TdTpsPwr = EQ_TD_TPS_PWR_QAM16_ALPHA4;
+				qam64TdTpsPwr = EQ_TD_TPS_PWR_QAM64_ALPHA4;
+
+				qpskIsGainMan =
+				    SC_RA_RAM_EQ_IS_GAIN_UNKNOWN_MAN__PRE;
+				qam16IsGainMan =
+				    SC_RA_RAM_EQ_IS_GAIN_16QAM_A4_MAN__PRE;
+				qam64IsGainMan =
+				    SC_RA_RAM_EQ_IS_GAIN_64QAM_A4_MAN__PRE;
+
+				qpskIsGainExp =
+				    SC_RA_RAM_EQ_IS_GAIN_UNKNOWN_EXP__PRE;
+				qam16IsGainExp =
+				    SC_RA_RAM_EQ_IS_GAIN_16QAM_A4_EXP__PRE;
+				qam64IsGainExp =
+				    SC_RA_RAM_EQ_IS_GAIN_64QAM_A4_EXP__PRE;
+			}
+			break;
+		case HIERARCHY_AUTO:
+		default:
+			/* Not set, detect it automatically, start with none */
+			operationMode |= SC_RA_RAM_OP_AUTO_HIER__M;
+			transmissionParams |= SC_RA_RAM_OP_PARAM_HIER_NO;
+			if (state->type_A) {
+				status = Write16(state, EQ_REG_OT_ALPHA__A, 0x0000, 0x0000);
+				if (status < 0)
+					break;
+				status = Write16(state, EC_SB_REG_ALPHA__A, 0x0000, 0x0000);
+				if (status < 0)
+					break;
+
+				qpskTdTpsPwr = EQ_TD_TPS_PWR_QPSK;
+				qam16TdTpsPwr = EQ_TD_TPS_PWR_QAM16_ALPHAN;
+				qam64TdTpsPwr = EQ_TD_TPS_PWR_QAM64_ALPHAN;
+
+				qpskIsGainMan =
+				    SC_RA_RAM_EQ_IS_GAIN_QPSK_MAN__PRE;
+				qam16IsGainMan =
+				    SC_RA_RAM_EQ_IS_GAIN_16QAM_MAN__PRE;
+				qam64IsGainMan =
+				    SC_RA_RAM_EQ_IS_GAIN_64QAM_MAN__PRE;
+
+				qpskIsGainExp =
+				    SC_RA_RAM_EQ_IS_GAIN_QPSK_EXP__PRE;
+				qam16IsGainExp =
+				    SC_RA_RAM_EQ_IS_GAIN_16QAM_EXP__PRE;
+				qam64IsGainExp =
+				    SC_RA_RAM_EQ_IS_GAIN_64QAM_EXP__PRE;
+			}
+			break;
+		}
+		status = status;
+		if (status < 0)
+			break;
+
+		switch (p->modulation) {
+		default:
+			operationMode |= SC_RA_RAM_OP_AUTO_CONST__M;
+			/* fall through , try first guess
+			   DRX_CONSTELLATION_QAM64 */
+		case QAM_64:
+			transmissionParams |= SC_RA_RAM_OP_PARAM_CONST_QAM64;
+			if (state->type_A) {
+				status = Write16(state, EQ_REG_OT_CONST__A, 0x0002, 0x0000);
+				if (status < 0)
+					break;
+				status = Write16(state, EC_SB_REG_CONST__A, EC_SB_REG_CONST_64QAM, 0x0000);
+				if (status < 0)
+					break;
+				status = Write16(state, EC_SB_REG_SCALE_MSB__A, 0x0020, 0x0000);
+				if (status < 0)
+					break;
+				status = Write16(state, EC_SB_REG_SCALE_BIT2__A, 0x0008, 0x0000);
+				if (status < 0)
+					break;
+				status = Write16(state, EC_SB_REG_SCALE_LSB__A, 0x0002, 0x0000);
+				if (status < 0)
+					break;
+
+				status = Write16(state, EQ_REG_TD_TPS_PWR_OFS__A, qam64TdTpsPwr, 0x0000);
+				if (status < 0)
+					break;
+				status = Write16(state, EQ_REG_SN_CEGAIN__A, qam64SnCeGain, 0x0000);
+				if (status < 0)
+					break;
+				status = Write16(state, EQ_REG_IS_GAIN_MAN__A, qam64IsGainMan, 0x0000);
+				if (status < 0)
+					break;
+				status = Write16(state, EQ_REG_IS_GAIN_EXP__A, qam64IsGainExp, 0x0000);
+				if (status < 0)
+					break;
+			}
+			break;
+		case QPSK:
+			transmissionParams |= SC_RA_RAM_OP_PARAM_CONST_QPSK;
+			if (state->type_A) {
+				status = Write16(state, EQ_REG_OT_CONST__A, 0x0000, 0x0000);
+				if (status < 0)
+					break;
+				status = Write16(state, EC_SB_REG_CONST__A, EC_SB_REG_CONST_QPSK, 0x0000);
+				if (status < 0)
+					break;
+				status = Write16(state, EC_SB_REG_SCALE_MSB__A, 0x0010, 0x0000);
+				if (status < 0)
+					break;
+				status = Write16(state, EC_SB_REG_SCALE_BIT2__A, 0x0000, 0x0000);
+				if (status < 0)
+					break;
+				status = Write16(state, EC_SB_REG_SCALE_LSB__A, 0x0000, 0x0000);
+				if (status < 0)
+					break;
+
+				status = Write16(state, EQ_REG_TD_TPS_PWR_OFS__A, qpskTdTpsPwr, 0x0000);
+				if (status < 0)
+					break;
+				status = Write16(state, EQ_REG_SN_CEGAIN__A, qpskSnCeGain, 0x0000);
+				if (status < 0)
+					break;
+				status = Write16(state, EQ_REG_IS_GAIN_MAN__A, qpskIsGainMan, 0x0000);
+				if (status < 0)
+					break;
+				status = Write16(state, EQ_REG_IS_GAIN_EXP__A, qpskIsGainExp, 0x0000);
+				if (status < 0)
+					break;
+			}
+			break;
+
+		case QAM_16:
+			transmissionParams |= SC_RA_RAM_OP_PARAM_CONST_QAM16;
+			if (state->type_A) {
+				status = Write16(state, EQ_REG_OT_CONST__A, 0x0001, 0x0000);
+				if (status < 0)
+					break;
+				status = Write16(state, EC_SB_REG_CONST__A, EC_SB_REG_CONST_16QAM, 0x0000);
+				if (status < 0)
+					break;
+				status = Write16(state, EC_SB_REG_SCALE_MSB__A, 0x0010, 0x0000);
+				if (status < 0)
+					break;
+				status = Write16(state, EC_SB_REG_SCALE_BIT2__A, 0x0004, 0x0000);
+				if (status < 0)
+					break;
+				status = Write16(state, EC_SB_REG_SCALE_LSB__A, 0x0000, 0x0000);
+				if (status < 0)
+					break;
+
+				status = Write16(state, EQ_REG_TD_TPS_PWR_OFS__A, qam16TdTpsPwr, 0x0000);
+				if (status < 0)
+					break;
+				status = Write16(state, EQ_REG_SN_CEGAIN__A, qam16SnCeGain, 0x0000);
+				if (status < 0)
+					break;
+				status = Write16(state, EQ_REG_IS_GAIN_MAN__A, qam16IsGainMan, 0x0000);
+				if (status < 0)
+					break;
+				status = Write16(state, EQ_REG_IS_GAIN_EXP__A, qam16IsGainExp, 0x0000);
+				if (status < 0)
+					break;
+			}
+			break;
+
+		}
+		status = status;
+		if (status < 0)
+			break;
+
+		switch (DRX_CHANNEL_HIGH) {
+		default:
+		case DRX_CHANNEL_AUTO:
+		case DRX_CHANNEL_LOW:
+			transmissionParams |= SC_RA_RAM_OP_PARAM_PRIO_LO;
+			status = Write16(state, EC_SB_REG_PRIOR__A, EC_SB_REG_PRIOR_LO, 0x0000);
+			if (status < 0)
+				break;
+			break;
+		case DRX_CHANNEL_HIGH:
+			transmissionParams |= SC_RA_RAM_OP_PARAM_PRIO_HI;
+			status = Write16(state, EC_SB_REG_PRIOR__A, EC_SB_REG_PRIOR_HI, 0x0000);
+			if (status < 0)
+				break;
+			break;
+
+		}
+
+		switch (p->code_rate_HP) {
+		case FEC_1_2:
+			transmissionParams |= SC_RA_RAM_OP_PARAM_RATE_1_2;
+			if (state->type_A) {
+				status = Write16(state, EC_VD_REG_SET_CODERATE__A, EC_VD_REG_SET_CODERATE_C1_2, 0x0000);
+				if (status < 0)
+					break;
+			}
+			break;
+		default:
+			operationMode |= SC_RA_RAM_OP_AUTO_RATE__M;
+		case FEC_2_3:
+			transmissionParams |= SC_RA_RAM_OP_PARAM_RATE_2_3;
+			if (state->type_A) {
+				status = Write16(state, EC_VD_REG_SET_CODERATE__A, EC_VD_REG_SET_CODERATE_C2_3, 0x0000);
+				if (status < 0)
+					break;
+			}
+			break;
+		case FEC_3_4:
+			transmissionParams |= SC_RA_RAM_OP_PARAM_RATE_3_4;
+			if (state->type_A) {
+				status = Write16(state, EC_VD_REG_SET_CODERATE__A, EC_VD_REG_SET_CODERATE_C3_4, 0x0000);
+				if (status < 0)
+					break;
+			}
+			break;
+		case FEC_5_6:
+			transmissionParams |= SC_RA_RAM_OP_PARAM_RATE_5_6;
+			if (state->type_A) {
+				status = Write16(state, EC_VD_REG_SET_CODERATE__A, EC_VD_REG_SET_CODERATE_C5_6, 0x0000);
+				if (status < 0)
+					break;
+			}
+			break;
+		case FEC_7_8:
+			transmissionParams |= SC_RA_RAM_OP_PARAM_RATE_7_8;
+			if (state->type_A) {
+				status = Write16(state, EC_VD_REG_SET_CODERATE__A, EC_VD_REG_SET_CODERATE_C7_8, 0x0000);
+				if (status < 0)
+					break;
+			}
+			break;
+		}
+		status = status;
+		if (status < 0)
+			break;
+
+		/* First determine real bandwidth (Hz) */
+		/* Also set delay for impulse noise cruncher (only A2) */
+		/* Also set parameters for EC_OC fix, note
+		   EC_OC_REG_TMD_HIL_MAR is changed
+		   by SC for fix for some 8K,1/8 guard but is restored by
+		   InitEC and ResetEC
+		   functions */
+		switch (p->bandwidth_hz) {
+		case 0:
+			p->bandwidth_hz = 8000000;
+			/* fall through */
+		case 8000000:
+			/* (64/7)*(8/8)*1000000 */
+			bandwidth = DRXD_BANDWIDTH_8MHZ_IN_HZ;
+
+			bandwidthParam = 0;
+			status = Write16(state,
+					 FE_AG_REG_IND_DEL__A, 50, 0x0000);
+			break;
+		case 7000000:
+			/* (64/7)*(7/8)*1000000 */
+			bandwidth = DRXD_BANDWIDTH_7MHZ_IN_HZ;
+			bandwidthParam = 0x4807;	/*binary:0100 1000 0000 0111 */
+			status = Write16(state,
+					 FE_AG_REG_IND_DEL__A, 59, 0x0000);
+			break;
+		case 6000000:
+			/* (64/7)*(6/8)*1000000 */
+			bandwidth = DRXD_BANDWIDTH_6MHZ_IN_HZ;
+			bandwidthParam = 0x0F07;	/*binary: 0000 1111 0000 0111 */
+			status = Write16(state,
+					 FE_AG_REG_IND_DEL__A, 71, 0x0000);
+			break;
+		default:
+			status = -EINVAL;
+		}
+		if (status < 0)
+			break;
+
+		status = Write16(state, SC_RA_RAM_BAND__A, bandwidthParam, 0x0000);
+		if (status < 0)
+			break;
+
+		{
+			u16 sc_config;
+			status = Read16(state, SC_RA_RAM_CONFIG__A, &sc_config, 0);
+			if (status < 0)
+				break;
+
+			/* enable SLAVE mode in 2k 1/32 to
+			   prevent timing change glitches */
+			if ((p->transmission_mode == TRANSMISSION_MODE_2K) &&
+			    (p->guard_interval == GUARD_INTERVAL_1_32)) {
+				/* enable slave */
+				sc_config |= SC_RA_RAM_CONFIG_SLAVE__M;
+			} else {
+				/* disable slave */
+				sc_config &= ~SC_RA_RAM_CONFIG_SLAVE__M;
+			}
+			status = Write16(state, SC_RA_RAM_CONFIG__A, sc_config, 0);
+			if (status < 0)
+				break;
+		}
+
+		status = SetCfgNoiseCalibration(state, &state->noise_cal);
+		if (status < 0)
+			break;
+
+		if (state->cscd_state == CSCD_INIT) {
+			/* switch on SRMM scan in SC */
+			status = Write16(state, SC_RA_RAM_SAMPLE_RATE_COUNT__A, DRXD_OSCDEV_DO_SCAN, 0x0000);
+			if (status < 0)
+				break;
+/*            CHK_ERROR(Write16(SC_RA_RAM_SAMPLE_RATE_STEP__A, DRXD_OSCDEV_STEP, 0x0000));*/
+			state->cscd_state = CSCD_SET;
+		}
+
+		/* Now compute FE_IF_REG_INCR */
+		/*((( SysFreq/BandWidth)/2)/2) -1) * 2^23) =>
+		   ((SysFreq / BandWidth) * (2^21) ) - (2^23) */
+		feIfIncr = MulDiv32(state->sys_clock_freq * 1000,
+				    (1ULL << 21), bandwidth) - (1 << 23);
+		status = Write16(state, FE_IF_REG_INCR0__A, (u16) (feIfIncr & FE_IF_REG_INCR0__M), 0x0000);
+		if (status < 0)
+			break;
+		status = Write16(state, FE_IF_REG_INCR1__A, (u16) ((feIfIncr >> FE_IF_REG_INCR0__W) & FE_IF_REG_INCR1__M), 0x0000);
+		if (status < 0)
+			break;
+		/* Bandwidth setting done */
+
+		/* Mirror & frequency offset */
+		SetFrequencyShift(state, off, mirrorFreqSpect);
+
+		/* Start SC, write channel settings to SC */
+
+		/* Enable SC after setting all other parameters */
+		status = Write16(state, SC_COMM_STATE__A, 0, 0x0000);
+		if (status < 0)
+			break;
+		status = Write16(state, SC_COMM_EXEC__A, 1, 0x0000);
+		if (status < 0)
+			break;
+
+		/* Write SC parameter registers, operation mode */
+#if 1
+		operationMode = (SC_RA_RAM_OP_AUTO_MODE__M |
+				 SC_RA_RAM_OP_AUTO_GUARD__M |
+				 SC_RA_RAM_OP_AUTO_CONST__M |
+				 SC_RA_RAM_OP_AUTO_HIER__M |
+				 SC_RA_RAM_OP_AUTO_RATE__M);
+#endif
+		status = SC_SetPrefParamCommand(state, 0x0000, transmissionParams, operationMode);
+		if (status < 0)
+			break;
+
+		/* Start correct processes to get in lock */
+		status = SC_ProcStartCommand(state, SC_RA_RAM_PROC_LOCKTRACK, SC_RA_RAM_SW_EVENT_RUN_NMASK__M, SC_RA_RAM_LOCKTRACK_MIN);
+		if (status < 0)
+			break;
+
+		status = StartOC(state);
+		if (status < 0)
+			break;
+
+		if (state->operation_mode != OM_Default) {
+			status = StartDiversity(state);
+			if (status < 0)
+				break;
+		}
+
+		state->drxd_state = DRXD_STARTED;
+	} while (0);
+
+	return status;
+}
+
+static int CDRXD(struct drxd_state *state, u32 IntermediateFrequency)
+{
+	u32 ulRfAgcOutputLevel = 0xffffffff;
+	u32 ulRfAgcSettleLevel = 528;	/* Optimum value for MT2060 */
+	u32 ulRfAgcMinLevel = 0;	/* Currently unused */
+	u32 ulRfAgcMaxLevel = DRXD_FE_CTRL_MAX;	/* Currently unused */
+	u32 ulRfAgcSpeed = 0;	/* Currently unused */
+	u32 ulRfAgcMode = 0;	/*2;   Off */
+	u32 ulRfAgcR1 = 820;
+	u32 ulRfAgcR2 = 2200;
+	u32 ulRfAgcR3 = 150;
+	u32 ulIfAgcMode = 0;	/* Auto */
+	u32 ulIfAgcOutputLevel = 0xffffffff;
+	u32 ulIfAgcSettleLevel = 0xffffffff;
+	u32 ulIfAgcMinLevel = 0xffffffff;
+	u32 ulIfAgcMaxLevel = 0xffffffff;
+	u32 ulIfAgcSpeed = 0xffffffff;
+	u32 ulIfAgcR1 = 820;
+	u32 ulIfAgcR2 = 2200;
+	u32 ulIfAgcR3 = 150;
+	u32 ulClock = state->config.clock;
+	u32 ulSerialMode = 0;
+	u32 ulEcOcRegOcModeLop = 4;	/* Dynamic DTO source */
+	u32 ulHiI2cDelay = HI_I2C_DELAY;
+	u32 ulHiI2cBridgeDelay = HI_I2C_BRIDGE_DELAY;
+	u32 ulHiI2cPatch = 0;
+	u32 ulEnvironment = APPENV_PORTABLE;
+	u32 ulEnvironmentDiversity = APPENV_MOBILE;
+	u32 ulIFFilter = IFFILTER_SAW;
+
+	state->if_agc_cfg.ctrlMode = AGC_CTRL_AUTO;
+	state->if_agc_cfg.outputLevel = 0;
+	state->if_agc_cfg.settleLevel = 140;
+	state->if_agc_cfg.minOutputLevel = 0;
+	state->if_agc_cfg.maxOutputLevel = 1023;
+	state->if_agc_cfg.speed = 904;
+
+	if (ulIfAgcMode == 1 && ulIfAgcOutputLevel <= DRXD_FE_CTRL_MAX) {
+		state->if_agc_cfg.ctrlMode = AGC_CTRL_USER;
+		state->if_agc_cfg.outputLevel = (u16) (ulIfAgcOutputLevel);
+	}
+
+	if (ulIfAgcMode == 0 &&
+	    ulIfAgcSettleLevel <= DRXD_FE_CTRL_MAX &&
+	    ulIfAgcMinLevel <= DRXD_FE_CTRL_MAX &&
+	    ulIfAgcMaxLevel <= DRXD_FE_CTRL_MAX &&
+	    ulIfAgcSpeed <= DRXD_FE_CTRL_MAX) {
+		state->if_agc_cfg.ctrlMode = AGC_CTRL_AUTO;
+		state->if_agc_cfg.settleLevel = (u16) (ulIfAgcSettleLevel);
+		state->if_agc_cfg.minOutputLevel = (u16) (ulIfAgcMinLevel);
+		state->if_agc_cfg.maxOutputLevel = (u16) (ulIfAgcMaxLevel);
+		state->if_agc_cfg.speed = (u16) (ulIfAgcSpeed);
+	}
+
+	state->if_agc_cfg.R1 = (u16) (ulIfAgcR1);
+	state->if_agc_cfg.R2 = (u16) (ulIfAgcR2);
+	state->if_agc_cfg.R3 = (u16) (ulIfAgcR3);
+
+	state->rf_agc_cfg.R1 = (u16) (ulRfAgcR1);
+	state->rf_agc_cfg.R2 = (u16) (ulRfAgcR2);
+	state->rf_agc_cfg.R3 = (u16) (ulRfAgcR3);
+
+	state->rf_agc_cfg.ctrlMode = AGC_CTRL_AUTO;
+	/* rest of the RFAgcCfg structure currently unused */
+	if (ulRfAgcMode == 1 && ulRfAgcOutputLevel <= DRXD_FE_CTRL_MAX) {
+		state->rf_agc_cfg.ctrlMode = AGC_CTRL_USER;
+		state->rf_agc_cfg.outputLevel = (u16) (ulRfAgcOutputLevel);
+	}
+
+	if (ulRfAgcMode == 0 &&
+	    ulRfAgcSettleLevel <= DRXD_FE_CTRL_MAX &&
+	    ulRfAgcMinLevel <= DRXD_FE_CTRL_MAX &&
+	    ulRfAgcMaxLevel <= DRXD_FE_CTRL_MAX &&
+	    ulRfAgcSpeed <= DRXD_FE_CTRL_MAX) {
+		state->rf_agc_cfg.ctrlMode = AGC_CTRL_AUTO;
+		state->rf_agc_cfg.settleLevel = (u16) (ulRfAgcSettleLevel);
+		state->rf_agc_cfg.minOutputLevel = (u16) (ulRfAgcMinLevel);
+		state->rf_agc_cfg.maxOutputLevel = (u16) (ulRfAgcMaxLevel);
+		state->rf_agc_cfg.speed = (u16) (ulRfAgcSpeed);
+	}
+
+	if (ulRfAgcMode == 2)
+		state->rf_agc_cfg.ctrlMode = AGC_CTRL_OFF;
+
+	if (ulEnvironment <= 2)
+		state->app_env_default = (enum app_env)
+		    (ulEnvironment);
+	if (ulEnvironmentDiversity <= 2)
+		state->app_env_diversity = (enum app_env)
+		    (ulEnvironmentDiversity);
+
+	if (ulIFFilter == IFFILTER_DISCRETE) {
+		/* discrete filter */
+		state->noise_cal.cpOpt = 0;
+		state->noise_cal.cpNexpOfs = 40;
+		state->noise_cal.tdCal2k = -40;
+		state->noise_cal.tdCal8k = -24;
+	} else {
+		/* SAW filter */
+		state->noise_cal.cpOpt = 1;
+		state->noise_cal.cpNexpOfs = 0;
+		state->noise_cal.tdCal2k = -21;
+		state->noise_cal.tdCal8k = -24;
+	}
+	state->m_EcOcRegOcModeLop = (u16) (ulEcOcRegOcModeLop);
+
+	state->chip_adr = (state->config.demod_address << 1) | 1;
+	switch (ulHiI2cPatch) {
+	case 1:
+		state->m_HiI2cPatch = DRXD_HiI2cPatch_1;
+		break;
+	case 3:
+		state->m_HiI2cPatch = DRXD_HiI2cPatch_3;
+		break;
+	default:
+		state->m_HiI2cPatch = NULL;
+	}
+
+	/* modify tuner and clock attributes */
+	state->intermediate_freq = (u16) (IntermediateFrequency / 1000);
+	/* expected system clock frequency in kHz */
+	state->expected_sys_clock_freq = 48000;
+	/* real system clock frequency in kHz */
+	state->sys_clock_freq = 48000;
+	state->osc_clock_freq = (u16) ulClock;
+	state->osc_clock_deviation = 0;
+	state->cscd_state = CSCD_INIT;
+	state->drxd_state = DRXD_UNINITIALIZED;
+
+	state->PGA = 0;
+	state->type_A = 0;
+	state->tuner_mirrors = 0;
+
+	/* modify MPEG output attributes */
+	state->insert_rs_byte = state->config.insert_rs_byte;
+	state->enable_parallel = (ulSerialMode != 1);
+
+	/* Timing div, 250ns/Psys */
+	/* Timing div, = ( delay (nano seconds) * sysclk (kHz) )/ 1000 */
+
+	state->hi_cfg_timing_div = (u16) ((state->sys_clock_freq / 1000) *
+					  ulHiI2cDelay) / 1000;
+	/* Bridge delay, uses oscilator clock */
+	/* Delay = ( delay (nano seconds) * oscclk (kHz) )/ 1000 */
+	state->hi_cfg_bridge_delay = (u16) ((state->osc_clock_freq / 1000) *
+					    ulHiI2cBridgeDelay) / 1000;
+
+	state->m_FeAgRegAgPwd = DRXD_DEF_AG_PWD_CONSUMER;
+	/* state->m_FeAgRegAgPwd = DRXD_DEF_AG_PWD_PRO; */
+	state->m_FeAgRegAgAgcSio = DRXD_DEF_AG_AGC_SIO;
+	return 0;
+}
+
+int DRXD_init(struct drxd_state *state, const u8 * fw, u32 fw_size)
+{
+	int status = 0;
+	u32 driverVersion;
+
+	if (state->init_done)
+		return 0;
+
+	CDRXD(state, state->config.IF ? state->config.IF : 36000000);
+
+	do {
+		state->operation_mode = OM_Default;
+
+		status = SetDeviceTypeId(state);
+		if (status < 0)
+			break;
+
+		/* Apply I2c address patch to B1 */
+		if (!state->type_A && state->m_HiI2cPatch != NULL)
+			status = WriteTable(state, state->m_HiI2cPatch);
+			if (status < 0)
+				break;
+
+		if (state->type_A) {
+			/* HI firmware patch for UIO readout,
+			   avoid clearing of result register */
+			status = Write16(state, 0x43012D, 0x047f, 0);
+			if (status < 0)
+				break;
+		}
+
+		status = HI_ResetCommand(state);
+		if (status < 0)
+			break;
+
+		status = StopAllProcessors(state);
+		if (status < 0)
+			break;
+		status = InitCC(state);
+		if (status < 0)
+			break;
+
+		state->osc_clock_deviation = 0;
+
+		if (state->config.osc_deviation)
+			state->osc_clock_deviation =
+			    state->config.osc_deviation(state->priv, 0, 0);
+		{
+			/* Handle clock deviation */
+			s32 devB;
+			s32 devA = (s32) (state->osc_clock_deviation) *
+			    (s32) (state->expected_sys_clock_freq);
+			/* deviation in kHz */
+			s32 deviation = (devA / (1000000L));
+			/* rounding, signed */
+			if (devA > 0)
+				devB = (2);
+			else
+				devB = (-2);
+			if ((devB * (devA % 1000000L) > 1000000L)) {
+				/* add +1 or -1 */
+				deviation += (devB / 2);
+			}
+
+			state->sys_clock_freq =
+			    (u16) ((state->expected_sys_clock_freq) +
+				   deviation);
+		}
+		status = InitHI(state);
+		if (status < 0)
+			break;
+		status = InitAtomicRead(state);
+		if (status < 0)
+			break;
+
+		status = EnableAndResetMB(state);
+		if (status < 0)
+			break;
+		if (state->type_A)
+			status = ResetCEFR(state);
+			if (status < 0)
+				break;
+
+		if (fw) {
+			status = DownloadMicrocode(state, fw, fw_size);
+			if (status < 0)
+				break;
+		} else {
+			status = DownloadMicrocode(state, state->microcode, state->microcode_length);
+			if (status < 0)
+				break;
+		}
+
+		if (state->PGA) {
+			state->m_FeAgRegAgPwd = DRXD_DEF_AG_PWD_PRO;
+			SetCfgPga(state, 0);	/* PGA = 0 dB */
+		} else {
+			state->m_FeAgRegAgPwd = DRXD_DEF_AG_PWD_CONSUMER;
+		}
+
+		state->m_FeAgRegAgAgcSio = DRXD_DEF_AG_AGC_SIO;
+
+		status = InitFE(state);
+		if (status < 0)
+			break;
+		status = InitFT(state);
+		if (status < 0)
+			break;
+		status = InitCP(state);
+		if (status < 0)
+			break;
+		status = InitCE(state);
+		if (status < 0)
+			break;
+		status = InitEQ(state);
+		if (status < 0)
+			break;
+		status = InitEC(state);
+		if (status < 0)
+			break;
+		status = InitSC(state);
+		if (status < 0)
+			break;
+
+		status = SetCfgIfAgc(state, &state->if_agc_cfg);
+		if (status < 0)
+			break;
+		status = SetCfgRfAgc(state, &state->rf_agc_cfg);
+		if (status < 0)
+			break;
+
+		state->cscd_state = CSCD_INIT;
+		status = Write16(state, SC_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0);
+		if (status < 0)
+			break;
+		status = Write16(state, LC_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0);
+		if (status < 0)
+			break;
+
+		driverVersion = (((VERSION_MAJOR / 10) << 4) +
+				 (VERSION_MAJOR % 10)) << 24;
+		driverVersion += (((VERSION_MINOR / 10) << 4) +
+				  (VERSION_MINOR % 10)) << 16;
+		driverVersion += ((VERSION_PATCH / 1000) << 12) +
+		    ((VERSION_PATCH / 100) << 8) +
+		    ((VERSION_PATCH / 10) << 4) + (VERSION_PATCH % 10);
+
+		status = Write32(state, SC_RA_RAM_DRIVER_VERSION__AX, driverVersion, 0);
+		if (status < 0)
+			break;
+
+		status = StopOC(state);
+		if (status < 0)
+			break;
+
+		state->drxd_state = DRXD_STOPPED;
+		state->init_done = 1;
+		status = 0;
+	} while (0);
+	return status;
+}
+
+int DRXD_status(struct drxd_state *state, u32 * pLockStatus)
+{
+	DRX_GetLockStatus(state, pLockStatus);
+
+	/*if (*pLockStatus&DRX_LOCK_MPEG) */
+	if (*pLockStatus & DRX_LOCK_FEC) {
+		ConfigureMPEGOutput(state, 1);
+		/* Get status again, in case we have MPEG lock now */
+		/*DRX_GetLockStatus(state, pLockStatus); */
+	}
+
+	return 0;
+}
+
+/****************************************************************************/
+/****************************************************************************/
+/****************************************************************************/
+
+static int drxd_read_signal_strength(struct dvb_frontend *fe, u16 * strength)
+{
+	struct drxd_state *state = fe->demodulator_priv;
+	u32 value;
+	int res;
+
+	res = ReadIFAgc(state, &value);
+	if (res < 0)
+		*strength = 0;
+	else
+		*strength = 0xffff - (value << 4);
+	return 0;
+}
+
+static int drxd_read_status(struct dvb_frontend *fe, fe_status_t * status)
+{
+	struct drxd_state *state = fe->demodulator_priv;
+	u32 lock;
+
+	DRXD_status(state, &lock);
+	*status = 0;
+	/* No MPEG lock in V255 firmware, bug ? */
+#if 1
+	if (lock & DRX_LOCK_MPEG)
+		*status |= FE_HAS_LOCK;
+#else
+	if (lock & DRX_LOCK_FEC)
+		*status |= FE_HAS_LOCK;
+#endif
+	if (lock & DRX_LOCK_FEC)
+		*status |= FE_HAS_VITERBI | FE_HAS_SYNC;
+	if (lock & DRX_LOCK_DEMOD)
+		*status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
+
+	return 0;
+}
+
+static int drxd_init(struct dvb_frontend *fe)
+{
+	struct drxd_state *state = fe->demodulator_priv;
+	int err = 0;
+
+/*	if (request_firmware(&state->fw, "drxd.fw", state->dev)<0) */
+	return DRXD_init(state, 0, 0);
+
+	err = DRXD_init(state, state->fw->data, state->fw->size);
+	release_firmware(state->fw);
+	return err;
+}
+
+int drxd_config_i2c(struct dvb_frontend *fe, int onoff)
+{
+	struct drxd_state *state = fe->demodulator_priv;
+
+	if (state->config.disable_i2c_gate_ctrl == 1)
+		return 0;
+
+	return DRX_ConfigureI2CBridge(state, onoff);
+}
+EXPORT_SYMBOL(drxd_config_i2c);
+
+static int drxd_get_tune_settings(struct dvb_frontend *fe,
+				  struct dvb_frontend_tune_settings *sets)
+{
+	sets->min_delay_ms = 10000;
+	sets->max_drift = 0;
+	sets->step_size = 0;
+	return 0;
+}
+
+static int drxd_read_ber(struct dvb_frontend *fe, u32 * ber)
+{
+	*ber = 0;
+	return 0;
+}
+
+static int drxd_read_snr(struct dvb_frontend *fe, u16 * snr)
+{
+	*snr = 0;
+	return 0;
+}
+
+static int drxd_read_ucblocks(struct dvb_frontend *fe, u32 * ucblocks)
+{
+	*ucblocks = 0;
+	return 0;
+}
+
+static int drxd_sleep(struct dvb_frontend *fe)
+{
+	struct drxd_state *state = fe->demodulator_priv;
+
+	ConfigureMPEGOutput(state, 0);
+	return 0;
+}
+
+static int drxd_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+	return drxd_config_i2c(fe, enable);
+}
+
+static int drxd_set_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct drxd_state *state = fe->demodulator_priv;
+	s32 off = 0;
+
+	state->props = *p;
+	DRX_Stop(state);
+
+	if (fe->ops.tuner_ops.set_params) {
+		fe->ops.tuner_ops.set_params(fe);
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 0);
+	}
+
+	msleep(200);
+
+	return DRX_Start(state, off);
+}
+
+static void drxd_release(struct dvb_frontend *fe)
+{
+	struct drxd_state *state = fe->demodulator_priv;
+
+	kfree(state);
+}
+
+static struct dvb_frontend_ops drxd_ops = {
+	.delsys = { SYS_DVBT},
+	.info = {
+		 .name = "Micronas DRXD DVB-T",
+		 .frequency_min = 47125000,
+		 .frequency_max = 855250000,
+		 .frequency_stepsize = 166667,
+		 .frequency_tolerance = 0,
+		 .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_FEC_AUTO |
+		 FE_CAN_QAM_16 | FE_CAN_QAM_64 |
+		 FE_CAN_QAM_AUTO |
+		 FE_CAN_TRANSMISSION_MODE_AUTO |
+		 FE_CAN_GUARD_INTERVAL_AUTO |
+		 FE_CAN_HIERARCHY_AUTO | FE_CAN_RECOVER | FE_CAN_MUTE_TS},
+
+	.release = drxd_release,
+	.init = drxd_init,
+	.sleep = drxd_sleep,
+	.i2c_gate_ctrl = drxd_i2c_gate_ctrl,
+
+	.set_frontend = drxd_set_frontend,
+	.get_tune_settings = drxd_get_tune_settings,
+
+	.read_status = drxd_read_status,
+	.read_ber = drxd_read_ber,
+	.read_signal_strength = drxd_read_signal_strength,
+	.read_snr = drxd_read_snr,
+	.read_ucblocks = drxd_read_ucblocks,
+};
+
+struct dvb_frontend *drxd_attach(const struct drxd_config *config,
+				 void *priv, struct i2c_adapter *i2c,
+				 struct device *dev)
+{
+	struct drxd_state *state = NULL;
+
+	state = kmalloc(sizeof(struct drxd_state), GFP_KERNEL);
+	if (!state)
+		return NULL;
+	memset(state, 0, sizeof(*state));
+
+	memcpy(&state->ops, &drxd_ops, sizeof(struct dvb_frontend_ops));
+	state->dev = dev;
+	state->config = *config;
+	state->i2c = i2c;
+	state->priv = priv;
+
+	mutex_init(&state->mutex);
+
+	if (Read16(state, 0, 0, 0) < 0)
+		goto error;
+
+	memcpy(&state->frontend.ops, &drxd_ops,
+	       sizeof(struct dvb_frontend_ops));
+	state->frontend.demodulator_priv = state;
+	ConfigureMPEGOutput(state, 0);
+	return &state->frontend;
+
+error:
+	printk(KERN_ERR "drxd: not found\n");
+	kfree(state);
+	return NULL;
+}
+EXPORT_SYMBOL(drxd_attach);
+
+MODULE_DESCRIPTION("DRXD driver");
+MODULE_AUTHOR("Micronas");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb-frontends/drxd_map_firm.h b/drivers/media/dvb-frontends/drxd_map_firm.h
new file mode 100644
index 0000000..6bc553a
--- /dev/null
+++ b/drivers/media/dvb-frontends/drxd_map_firm.h
@@ -0,0 +1,1013 @@
+/*
+ * drx3973d_map_firm.h
+ *
+ * Copyright (C) 2006-2007 Micronas
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 only, as published by the Free Software Foundation.
+ *
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ */
+
+#ifndef __DRX3973D_MAP__H__
+#define __DRX3973D_MAP__H__
+
+/*
+ * Note: originally, this file contained 12000+ lines of data
+ * Probably a few lines for every firwmare assembler instruction. However,
+ * only a few defines were actually used. So, removed all uneeded lines.
+ * If ever needed, the other lines can be easily obtained via git history.
+ */
+
+#define HI_COMM_EXEC__A                                              0x400000
+#define HI_COMM_MB__A                                                0x400002
+#define HI_CT_REG_COMM_STATE__A                                      0x410001
+#define HI_RA_RAM_SRV_RES__A                                         0x420031
+#define HI_RA_RAM_SRV_CMD__A                                         0x420032
+#define   HI_RA_RAM_SRV_CMD_RESET                                    0x2
+#define   HI_RA_RAM_SRV_CMD_CONFIG                                   0x3
+#define   HI_RA_RAM_SRV_CMD_EXECUTE                                  0x6
+#define HI_RA_RAM_SRV_RST_KEY__A                                     0x420033
+#define   HI_RA_RAM_SRV_RST_KEY_ACT                                  0x3973
+#define HI_RA_RAM_SRV_CFG_KEY__A                                     0x420033
+#define HI_RA_RAM_SRV_CFG_DIV__A                                     0x420034
+#define HI_RA_RAM_SRV_CFG_BDL__A                                     0x420035
+#define HI_RA_RAM_SRV_CFG_WUP__A                                     0x420036
+#define HI_RA_RAM_SRV_CFG_ACT__A                                     0x420037
+#define     HI_RA_RAM_SRV_CFG_ACT_SLV0_ON                            0x1
+#define   HI_RA_RAM_SRV_CFG_ACT_BRD__M                               0x4
+#define     HI_RA_RAM_SRV_CFG_ACT_BRD_OFF                            0x0
+#define     HI_RA_RAM_SRV_CFG_ACT_BRD_ON                             0x4
+#define     HI_RA_RAM_SRV_CFG_ACT_PWD_EXE                            0x8
+#define HI_RA_RAM_USR_BEGIN__A                                       0x420040
+#define HI_IF_RAM_TRP_BPT0__AX                                       0x430000
+#define HI_IF_RAM_USR_BEGIN__A                                       0x430200
+#define SC_COMM_EXEC__A                                              0x800000
+#define     SC_COMM_EXEC_CTL_STOP                                    0x0
+#define SC_COMM_STATE__A                                             0x800001
+#define SC_RA_RAM_PARAM0__A                                          0x820040
+#define SC_RA_RAM_PARAM1__A                                          0x820041
+#define SC_RA_RAM_CMD_ADDR__A                                        0x820042
+#define SC_RA_RAM_CMD__A                                             0x820043
+#define   SC_RA_RAM_CMD_PROC_START                                   0x1
+#define   SC_RA_RAM_CMD_SET_PREF_PARAM                               0x3
+#define   SC_RA_RAM_CMD_GET_OP_PARAM                                 0x5
+#define   SC_RA_RAM_SW_EVENT_RUN_NMASK__M                            0x1
+#define   SC_RA_RAM_LOCKTRACK_MIN                                    0x1
+#define     SC_RA_RAM_OP_PARAM_MODE_2K                               0x0
+#define     SC_RA_RAM_OP_PARAM_MODE_8K                               0x1
+#define     SC_RA_RAM_OP_PARAM_GUARD_32                              0x0
+#define     SC_RA_RAM_OP_PARAM_GUARD_16                              0x4
+#define     SC_RA_RAM_OP_PARAM_GUARD_8                               0x8
+#define     SC_RA_RAM_OP_PARAM_GUARD_4                               0xC
+#define     SC_RA_RAM_OP_PARAM_CONST_QPSK                            0x0
+#define     SC_RA_RAM_OP_PARAM_CONST_QAM16                           0x10
+#define     SC_RA_RAM_OP_PARAM_CONST_QAM64                           0x20
+#define     SC_RA_RAM_OP_PARAM_HIER_NO                               0x0
+#define     SC_RA_RAM_OP_PARAM_HIER_A1                               0x40
+#define     SC_RA_RAM_OP_PARAM_HIER_A2                               0x80
+#define     SC_RA_RAM_OP_PARAM_HIER_A4                               0xC0
+#define     SC_RA_RAM_OP_PARAM_RATE_1_2                              0x0
+#define     SC_RA_RAM_OP_PARAM_RATE_2_3                              0x200
+#define     SC_RA_RAM_OP_PARAM_RATE_3_4                              0x400
+#define     SC_RA_RAM_OP_PARAM_RATE_5_6                              0x600
+#define     SC_RA_RAM_OP_PARAM_RATE_7_8                              0x800
+#define     SC_RA_RAM_OP_PARAM_PRIO_HI                               0x0
+#define     SC_RA_RAM_OP_PARAM_PRIO_LO                               0x1000
+#define   SC_RA_RAM_OP_AUTO_MODE__M                                  0x1
+#define   SC_RA_RAM_OP_AUTO_GUARD__M                                 0x2
+#define   SC_RA_RAM_OP_AUTO_CONST__M                                 0x4
+#define   SC_RA_RAM_OP_AUTO_HIER__M                                  0x8
+#define   SC_RA_RAM_OP_AUTO_RATE__M                                  0x10
+#define SC_RA_RAM_LOCK__A                                            0x82004B
+#define   SC_RA_RAM_LOCK_DEMOD__M                                    0x1
+#define   SC_RA_RAM_LOCK_FEC__M                                      0x2
+#define   SC_RA_RAM_LOCK_MPEG__M                                     0x4
+#define SC_RA_RAM_BE_OPT_ENA__A                                      0x82004C
+#define   SC_RA_RAM_BE_OPT_ENA_CP_OPT                                0x1
+#define SC_RA_RAM_BE_OPT_DELAY__A                                    0x82004D
+#define SC_RA_RAM_CONFIG__A                                          0x820050
+#define   SC_RA_RAM_CONFIG_FR_ENABLE__M                              0x4
+#define   SC_RA_RAM_CONFIG_FREQSCAN__M                               0x10
+#define   SC_RA_RAM_CONFIG_SLAVE__M                                  0x20
+#define SC_RA_RAM_IF_SAVE__AX                                        0x82008E
+#define SC_RA_RAM_IR_COARSE_2K_LENGTH__A                             0x8200D1
+#define SC_RA_RAM_IR_COARSE_2K_LENGTH__PRE                           0x9
+#define SC_RA_RAM_IR_COARSE_2K_FREQINC__A                            0x8200D2
+#define SC_RA_RAM_IR_COARSE_2K_FREQINC__PRE                          0x4
+#define SC_RA_RAM_IR_COARSE_2K_KAISINC__A                            0x8200D3
+#define SC_RA_RAM_IR_COARSE_2K_KAISINC__PRE                          0x100
+#define SC_RA_RAM_IR_COARSE_8K_LENGTH__A                             0x8200D4
+#define SC_RA_RAM_IR_COARSE_8K_LENGTH__PRE                           0x8
+#define SC_RA_RAM_IR_COARSE_8K_FREQINC__A                            0x8200D5
+#define SC_RA_RAM_IR_COARSE_8K_FREQINC__PRE                          0x8
+#define SC_RA_RAM_IR_COARSE_8K_KAISINC__A                            0x8200D6
+#define SC_RA_RAM_IR_COARSE_8K_KAISINC__PRE                          0x200
+#define SC_RA_RAM_IR_FINE_2K_LENGTH__A                               0x8200D7
+#define SC_RA_RAM_IR_FINE_2K_LENGTH__PRE                             0x9
+#define SC_RA_RAM_IR_FINE_2K_FREQINC__A                              0x8200D8
+#define SC_RA_RAM_IR_FINE_2K_FREQINC__PRE                            0x4
+#define SC_RA_RAM_IR_FINE_2K_KAISINC__A                              0x8200D9
+#define SC_RA_RAM_IR_FINE_2K_KAISINC__PRE                            0x100
+#define SC_RA_RAM_IR_FINE_8K_LENGTH__A                               0x8200DA
+#define SC_RA_RAM_IR_FINE_8K_LENGTH__PRE                             0xB
+#define SC_RA_RAM_IR_FINE_8K_FREQINC__A                              0x8200DB
+#define SC_RA_RAM_IR_FINE_8K_FREQINC__PRE                            0x1
+#define SC_RA_RAM_IR_FINE_8K_KAISINC__A                              0x8200DC
+#define SC_RA_RAM_IR_FINE_8K_KAISINC__PRE                            0x40
+#define SC_RA_RAM_ECHO_SHIFT_LIM__A                                  0x8200DD
+#define SC_RA_RAM_SAMPLE_RATE_COUNT__A                               0x8200E8
+#define SC_RA_RAM_SAMPLE_RATE_STEP__A                                0x8200E9
+#define SC_RA_RAM_BAND__A                                            0x8200EC
+#define SC_RA_RAM_LC_ABS_2K__A                                       0x8200F4
+#define SC_RA_RAM_LC_ABS_2K__PRE                                     0x1F
+#define SC_RA_RAM_LC_ABS_8K__A                                       0x8200F5
+#define SC_RA_RAM_LC_ABS_8K__PRE                                     0x1F
+#define SC_RA_RAM_EQ_IS_GAIN_UNKNOWN_MAN__PRE                        0x1D6
+#define SC_RA_RAM_EQ_IS_GAIN_UNKNOWN_EXP__PRE                        0x4
+#define SC_RA_RAM_EQ_IS_GAIN_QPSK_MAN__PRE                           0x1BB
+#define SC_RA_RAM_EQ_IS_GAIN_QPSK_EXP__PRE                           0x5
+#define SC_RA_RAM_EQ_IS_GAIN_16QAM_MAN__PRE                          0x1EF
+#define SC_RA_RAM_EQ_IS_GAIN_16QAM_EXP__PRE                          0x5
+#define SC_RA_RAM_EQ_IS_GAIN_16QAM_A2_MAN__PRE                       0x15E
+#define SC_RA_RAM_EQ_IS_GAIN_16QAM_A2_EXP__PRE                       0x5
+#define SC_RA_RAM_EQ_IS_GAIN_16QAM_A4_MAN__PRE                       0x11A
+#define SC_RA_RAM_EQ_IS_GAIN_16QAM_A4_EXP__PRE                       0x6
+#define SC_RA_RAM_EQ_IS_GAIN_64QAM_MAN__PRE                          0x1FB
+#define SC_RA_RAM_EQ_IS_GAIN_64QAM_EXP__PRE                          0x5
+#define SC_RA_RAM_EQ_IS_GAIN_64QAM_A2_MAN__PRE                       0x12F
+#define SC_RA_RAM_EQ_IS_GAIN_64QAM_A2_EXP__PRE                       0x5
+#define SC_RA_RAM_EQ_IS_GAIN_64QAM_A4_MAN__PRE                       0x197
+#define SC_RA_RAM_EQ_IS_GAIN_64QAM_A4_EXP__PRE                       0x5
+#define SC_RA_RAM_DRIVER_VERSION__AX                                 0x8201FE
+#define   SC_RA_RAM_PROC_LOCKTRACK                                   0x0
+#define FE_COMM_EXEC__A                                              0xC00000
+#define FE_AD_REG_COMM_EXEC__A                                       0xC10000
+#define FE_AD_REG_FDB_IN__A                                          0xC10012
+#define FE_AD_REG_PD__A                                              0xC10013
+#define FE_AD_REG_INVEXT__A                                          0xC10014
+#define FE_AD_REG_CLKNEG__A                                          0xC10015
+#define FE_AG_REG_COMM_EXEC__A                                       0xC20000
+#define FE_AG_REG_AG_MODE_LOP__A                                     0xC20010
+#define   FE_AG_REG_AG_MODE_LOP_MODE_4__M                            0x10
+#define     FE_AG_REG_AG_MODE_LOP_MODE_4_STATIC                      0x0
+#define     FE_AG_REG_AG_MODE_LOP_MODE_4_DYNAMIC                     0x10
+#define   FE_AG_REG_AG_MODE_LOP_MODE_5__M                            0x20
+#define     FE_AG_REG_AG_MODE_LOP_MODE_5_STATIC                      0x0
+#define   FE_AG_REG_AG_MODE_LOP_MODE_C__M                            0x1000
+#define     FE_AG_REG_AG_MODE_LOP_MODE_C_STATIC                      0x0
+#define     FE_AG_REG_AG_MODE_LOP_MODE_C_DYNAMIC                     0x1000
+#define   FE_AG_REG_AG_MODE_LOP_MODE_E__M                            0x4000
+#define     FE_AG_REG_AG_MODE_LOP_MODE_E_STATIC                      0x0
+#define     FE_AG_REG_AG_MODE_LOP_MODE_E_DYNAMIC                     0x4000
+#define FE_AG_REG_AG_MODE_HIP__A                                     0xC20011
+#define FE_AG_REG_AG_PGA_MODE__A                                     0xC20012
+#define   FE_AG_REG_AG_PGA_MODE_PFY_PCY_AFY_REN                      0x0
+#define   FE_AG_REG_AG_PGA_MODE_PFN_PCN_AFY_REN                      0x1
+#define FE_AG_REG_AG_AGC_SIO__A                                      0xC20013
+#define   FE_AG_REG_AG_AGC_SIO_AGC_SIO_2__M                          0x2
+#define     FE_AG_REG_AG_AGC_SIO_AGC_SIO_2_OUTPUT                    0x0
+#define     FE_AG_REG_AG_AGC_SIO_AGC_SIO_2_INPUT                     0x2
+#define FE_AG_REG_AG_PWD__A                                          0xC20015
+#define   FE_AG_REG_AG_PWD_PWD_PD2__M                                0x2
+#define     FE_AG_REG_AG_PWD_PWD_PD2_DISABLE                         0x0
+#define     FE_AG_REG_AG_PWD_PWD_PD2_ENABLE                          0x2
+#define FE_AG_REG_DCE_AUR_CNT__A                                     0xC20016
+#define FE_AG_REG_DCE_RUR_CNT__A                                     0xC20017
+#define FE_AG_REG_ACE_AUR_CNT__A                                     0xC2001A
+#define FE_AG_REG_ACE_RUR_CNT__A                                     0xC2001B
+#define FE_AG_REG_CDR_RUR_CNT__A                                     0xC20020
+#define FE_AG_REG_EGC_RUR_CNT__A                                     0xC20024
+#define FE_AG_REG_EGC_SET_LVL__A                                     0xC20025
+#define FE_AG_REG_EGC_SET_LVL__M                                     0x1FF
+#define FE_AG_REG_EGC_FLA_RGN__A                                     0xC20026
+#define FE_AG_REG_EGC_SLO_RGN__A                                     0xC20027
+#define FE_AG_REG_EGC_JMP_PSN__A                                     0xC20028
+#define FE_AG_REG_EGC_FLA_INC__A                                     0xC20029
+#define FE_AG_REG_EGC_FLA_DEC__A                                     0xC2002A
+#define FE_AG_REG_EGC_SLO_INC__A                                     0xC2002B
+#define FE_AG_REG_EGC_SLO_DEC__A                                     0xC2002C
+#define FE_AG_REG_EGC_FAS_INC__A                                     0xC2002D
+#define FE_AG_REG_EGC_FAS_DEC__A                                     0xC2002E
+#define FE_AG_REG_PM1_AGC_WRI__A                                     0xC20030
+#define FE_AG_REG_PM1_AGC_WRI__M                                     0x7FF
+#define FE_AG_REG_GC1_AGC_RIC__A                                     0xC20031
+#define FE_AG_REG_GC1_AGC_OFF__A                                     0xC20032
+#define FE_AG_REG_GC1_AGC_MAX__A                                     0xC20033
+#define FE_AG_REG_GC1_AGC_MIN__A                                     0xC20034
+#define FE_AG_REG_GC1_AGC_DAT__A                                     0xC20035
+#define FE_AG_REG_GC1_AGC_DAT__M                                     0x3FF
+#define FE_AG_REG_PM2_AGC_WRI__A                                     0xC20036
+#define FE_AG_REG_IND_WIN__A                                         0xC2003C
+#define FE_AG_REG_IND_THD_LOL__A                                     0xC2003D
+#define FE_AG_REG_IND_THD_HIL__A                                     0xC2003E
+#define FE_AG_REG_IND_DEL__A                                         0xC2003F
+#define FE_AG_REG_IND_PD1_WRI__A                                     0xC20040
+#define FE_AG_REG_PDA_AUR_CNT__A                                     0xC20041
+#define FE_AG_REG_PDA_RUR_CNT__A                                     0xC20042
+#define FE_AG_REG_PDA_AVE_DAT__A                                     0xC20043
+#define FE_AG_REG_PDC_RUR_CNT__A                                     0xC20044
+#define FE_AG_REG_PDC_SET_LVL__A                                     0xC20045
+#define FE_AG_REG_PDC_FLA_RGN__A                                     0xC20046
+#define FE_AG_REG_PDC_JMP_PSN__A                                     0xC20047
+#define FE_AG_REG_PDC_FLA_STP__A                                     0xC20048
+#define FE_AG_REG_PDC_SLO_STP__A                                     0xC20049
+#define FE_AG_REG_PDC_PD2_WRI__A                                     0xC2004A
+#define FE_AG_REG_PDC_MAP_DAT__A                                     0xC2004B
+#define FE_AG_REG_PDC_MAX__A                                         0xC2004C
+#define FE_AG_REG_TGA_AUR_CNT__A                                     0xC2004D
+#define FE_AG_REG_TGA_RUR_CNT__A                                     0xC2004E
+#define FE_AG_REG_TGA_AVE_DAT__A                                     0xC2004F
+#define FE_AG_REG_TGC_RUR_CNT__A                                     0xC20050
+#define FE_AG_REG_TGC_SET_LVL__A                                     0xC20051
+#define FE_AG_REG_TGC_SET_LVL__M                                     0x3F
+#define FE_AG_REG_TGC_FLA_RGN__A                                     0xC20052
+#define FE_AG_REG_TGC_JMP_PSN__A                                     0xC20053
+#define FE_AG_REG_TGC_FLA_STP__A                                     0xC20054
+#define FE_AG_REG_TGC_SLO_STP__A                                     0xC20055
+#define FE_AG_REG_TGC_MAP_DAT__A                                     0xC20056
+#define FE_AG_REG_FGA_AUR_CNT__A                                     0xC20057
+#define FE_AG_REG_FGA_RUR_CNT__A                                     0xC20058
+#define FE_AG_REG_FGM_WRI__A                                         0xC20061
+#define FE_AG_REG_BGC_FGC_WRI__A                                     0xC20068
+#define FE_AG_REG_BGC_CGC_WRI__A                                     0xC20069
+#define FE_FS_REG_COMM_EXEC__A                                       0xC30000
+#define FE_FS_REG_ADD_INC_LOP__A                                     0xC30010
+#define FE_FD_REG_COMM_EXEC__A                                       0xC40000
+#define FE_FD_REG_SCL__A                                             0xC40010
+#define FE_FD_REG_MAX_LEV__A                                         0xC40011
+#define FE_FD_REG_NR__A                                              0xC40012
+#define FE_FD_REG_MEAS_VAL__A                                        0xC40014
+#define FE_IF_REG_COMM_EXEC__A                                       0xC50000
+#define FE_IF_REG_INCR0__A                                           0xC50010
+#define FE_IF_REG_INCR0__W                                           16
+#define FE_IF_REG_INCR0__M                                           0xFFFF
+#define FE_IF_REG_INCR1__A                                           0xC50011
+#define FE_IF_REG_INCR1__M                                           0xFF
+#define FE_CF_REG_COMM_EXEC__A                                       0xC60000
+#define FE_CF_REG_SCL__A                                             0xC60010
+#define FE_CF_REG_MAX_LEV__A                                         0xC60011
+#define FE_CF_REG_NR__A                                              0xC60012
+#define FE_CF_REG_IMP_VAL__A                                         0xC60013
+#define FE_CF_REG_MEAS_VAL__A                                        0xC60014
+#define FE_CU_REG_COMM_EXEC__A                                       0xC70000
+#define FE_CU_REG_FRM_CNT_RST__A                                     0xC70011
+#define FE_CU_REG_FRM_CNT_STR__A                                     0xC70012
+#define FT_COMM_EXEC__A                                              0x1000000
+#define FT_REG_COMM_EXEC__A                                          0x1010000
+#define CP_COMM_EXEC__A                                              0x1400000
+#define CP_REG_COMM_EXEC__A                                          0x1410000
+#define CP_REG_INTERVAL__A                                           0x1410011
+#define CP_REG_BR_SPL_OFFSET__A                                      0x1410023
+#define CP_REG_BR_STR_DEL__A                                         0x1410024
+#define CP_REG_RT_ANG_INC0__A                                        0x1410030
+#define CP_REG_RT_ANG_INC1__A                                        0x1410031
+#define CP_REG_RT_DETECT_ENA__A                                      0x1410032
+#define CP_REG_RT_DETECT_TRH__A                                      0x1410033
+#define CP_REG_RT_EXP_MARG__A                                        0x141003E
+#define CP_REG_AC_NEXP_OFFS__A                                       0x1410040
+#define CP_REG_AC_AVER_POW__A                                        0x1410041
+#define CP_REG_AC_MAX_POW__A                                         0x1410042
+#define CP_REG_AC_WEIGHT_MAN__A                                      0x1410043
+#define CP_REG_AC_WEIGHT_EXP__A                                      0x1410044
+#define CP_REG_AC_AMP_MODE__A                                        0x1410047
+#define CP_REG_AC_AMP_FIX__A                                         0x1410048
+#define CP_REG_AC_ANG_MODE__A                                        0x141004A
+#define CE_COMM_EXEC__A                                              0x1800000
+#define CE_REG_COMM_EXEC__A                                          0x1810000
+#define CE_REG_TAPSET__A                                             0x1810011
+#define CE_REG_AVG_POW__A                                            0x1810012
+#define CE_REG_MAX_POW__A                                            0x1810013
+#define CE_REG_ATT__A                                                0x1810014
+#define CE_REG_NRED__A                                               0x1810015
+#define CE_REG_NE_ERR_SELECT__A                                      0x1810043
+#define CE_REG_NE_TD_CAL__A                                          0x1810044
+#define CE_REG_NE_MIXAVG__A                                          0x1810046
+#define CE_REG_NE_NUPD_OFS__A                                        0x1810047
+#define CE_REG_PE_NEXP_OFFS__A                                       0x1810050
+#define CE_REG_PE_TIMESHIFT__A                                       0x1810051
+#define CE_REG_TP_A0_TAP_NEW__A                                      0x1810064
+#define CE_REG_TP_A0_TAP_NEW_VALID__A                                0x1810065
+#define CE_REG_TP_A0_MU_LMS_STEP__A                                  0x1810066
+#define CE_REG_TP_A1_TAP_NEW__A                                      0x1810068
+#define CE_REG_TP_A1_TAP_NEW_VALID__A                                0x1810069
+#define CE_REG_TP_A1_MU_LMS_STEP__A                                  0x181006A
+#define CE_REG_TI_NEXP_OFFS__A                                       0x1810070
+#define CE_REG_FI_SHT_INCR__A                                        0x1810090
+#define CE_REG_FI_EXP_NORM__A                                        0x1810091
+#define CE_REG_IR_INPUTSEL__A                                        0x18100A0
+#define CE_REG_IR_STARTPOS__A                                        0x18100A1
+#define CE_REG_IR_NEXP_THRES__A                                      0x18100A2
+#define CE_REG_FR_TREAL00__A                                         0x1820010
+#define CE_REG_FR_TIMAG00__A                                         0x1820011
+#define CE_REG_FR_TREAL01__A                                         0x1820012
+#define CE_REG_FR_TIMAG01__A                                         0x1820013
+#define CE_REG_FR_TREAL02__A                                         0x1820014
+#define CE_REG_FR_TIMAG02__A                                         0x1820015
+#define CE_REG_FR_TREAL03__A                                         0x1820016
+#define CE_REG_FR_TIMAG03__A                                         0x1820017
+#define CE_REG_FR_TREAL04__A                                         0x1820018
+#define CE_REG_FR_TIMAG04__A                                         0x1820019
+#define CE_REG_FR_TREAL05__A                                         0x182001A
+#define CE_REG_FR_TIMAG05__A                                         0x182001B
+#define CE_REG_FR_TREAL06__A                                         0x182001C
+#define CE_REG_FR_TIMAG06__A                                         0x182001D
+#define CE_REG_FR_TREAL07__A                                         0x182001E
+#define CE_REG_FR_TIMAG07__A                                         0x182001F
+#define CE_REG_FR_TREAL08__A                                         0x1820020
+#define CE_REG_FR_TIMAG08__A                                         0x1820021
+#define CE_REG_FR_TREAL09__A                                         0x1820022
+#define CE_REG_FR_TIMAG09__A                                         0x1820023
+#define CE_REG_FR_TREAL10__A                                         0x1820024
+#define CE_REG_FR_TIMAG10__A                                         0x1820025
+#define CE_REG_FR_TREAL11__A                                         0x1820026
+#define CE_REG_FR_TIMAG11__A                                         0x1820027
+#define CE_REG_FR_MID_TAP__A                                         0x1820028
+#define CE_REG_FR_SQS_G00__A                                         0x1820029
+#define CE_REG_FR_SQS_G01__A                                         0x182002A
+#define CE_REG_FR_SQS_G02__A                                         0x182002B
+#define CE_REG_FR_SQS_G03__A                                         0x182002C
+#define CE_REG_FR_SQS_G04__A                                         0x182002D
+#define CE_REG_FR_SQS_G05__A                                         0x182002E
+#define CE_REG_FR_SQS_G06__A                                         0x182002F
+#define CE_REG_FR_SQS_G07__A                                         0x1820030
+#define CE_REG_FR_SQS_G08__A                                         0x1820031
+#define CE_REG_FR_SQS_G09__A                                         0x1820032
+#define CE_REG_FR_SQS_G10__A                                         0x1820033
+#define CE_REG_FR_SQS_G11__A                                         0x1820034
+#define CE_REG_FR_SQS_G12__A                                         0x1820035
+#define CE_REG_FR_RIO_G00__A                                         0x1820036
+#define CE_REG_FR_RIO_G01__A                                         0x1820037
+#define CE_REG_FR_RIO_G02__A                                         0x1820038
+#define CE_REG_FR_RIO_G03__A                                         0x1820039
+#define CE_REG_FR_RIO_G04__A                                         0x182003A
+#define CE_REG_FR_RIO_G05__A                                         0x182003B
+#define CE_REG_FR_RIO_G06__A                                         0x182003C
+#define CE_REG_FR_RIO_G07__A                                         0x182003D
+#define CE_REG_FR_RIO_G08__A                                         0x182003E
+#define CE_REG_FR_RIO_G09__A                                         0x182003F
+#define CE_REG_FR_RIO_G10__A                                         0x1820040
+#define CE_REG_FR_MODE__A                                            0x1820041
+#define CE_REG_FR_SQS_TRH__A                                         0x1820042
+#define CE_REG_FR_RIO_GAIN__A                                        0x1820043
+#define CE_REG_FR_BYPASS__A                                          0x1820044
+#define CE_REG_FR_PM_SET__A                                          0x1820045
+#define CE_REG_FR_ERR_SH__A                                          0x1820046
+#define CE_REG_FR_MAN_SH__A                                          0x1820047
+#define CE_REG_FR_TAP_SH__A                                          0x1820048
+#define EQ_COMM_EXEC__A                                              0x1C00000
+#define EQ_REG_COMM_EXEC__A                                          0x1C10000
+#define EQ_REG_COMM_MB__A                                            0x1C10002
+#define EQ_REG_IS_GAIN_MAN__A                                        0x1C10015
+#define EQ_REG_IS_GAIN_EXP__A                                        0x1C10016
+#define EQ_REG_IS_CLIP_EXP__A                                        0x1C10017
+#define EQ_REG_SN_CEGAIN__A                                          0x1C1002A
+#define EQ_REG_SN_OFFSET__A                                          0x1C1002B
+#define EQ_REG_RC_SEL_CAR__A                                         0x1C10032
+#define   EQ_REG_RC_SEL_CAR_INIT                                     0x0
+#define     EQ_REG_RC_SEL_CAR_DIV_ON                                 0x1
+#define     EQ_REG_RC_SEL_CAR_PASS_A_CC                              0x0
+#define     EQ_REG_RC_SEL_CAR_PASS_B_CE                              0x2
+#define     EQ_REG_RC_SEL_CAR_LOCAL_A_CC                             0x0
+#define     EQ_REG_RC_SEL_CAR_LOCAL_B_CE                             0x8
+#define     EQ_REG_RC_SEL_CAR_MEAS_A_CC                              0x0
+#define     EQ_REG_RC_SEL_CAR_MEAS_B_CE                              0x20
+#define EQ_REG_OT_CONST__A                                           0x1C10046
+#define EQ_REG_OT_ALPHA__A                                           0x1C10047
+#define EQ_REG_OT_QNT_THRES0__A                                      0x1C10048
+#define EQ_REG_OT_QNT_THRES1__A                                      0x1C10049
+#define EQ_REG_OT_CSI_STEP__A                                        0x1C1004A
+#define EQ_REG_OT_CSI_OFFSET__A                                      0x1C1004B
+#define EQ_REG_TD_REQ_SMB_CNT__A                                     0x1C10061
+#define EQ_REG_TD_TPS_PWR_OFS__A                                     0x1C10062
+#define EC_SB_REG_COMM_EXEC__A                                       0x2010000
+#define EC_SB_REG_TR_MODE__A                                         0x2010010
+#define   EC_SB_REG_TR_MODE_8K                                       0x0
+#define   EC_SB_REG_TR_MODE_2K                                       0x1
+#define EC_SB_REG_CONST__A                                           0x2010011
+#define   EC_SB_REG_CONST_QPSK                                       0x0
+#define   EC_SB_REG_CONST_16QAM                                      0x1
+#define   EC_SB_REG_CONST_64QAM                                      0x2
+#define EC_SB_REG_ALPHA__A                                           0x2010012
+#define EC_SB_REG_PRIOR__A                                           0x2010013
+#define   EC_SB_REG_PRIOR_HI                                         0x0
+#define   EC_SB_REG_PRIOR_LO                                         0x1
+#define EC_SB_REG_CSI_HI__A                                          0x2010014
+#define EC_SB_REG_CSI_LO__A                                          0x2010015
+#define EC_SB_REG_SMB_TGL__A                                         0x2010016
+#define EC_SB_REG_SNR_HI__A                                          0x2010017
+#define EC_SB_REG_SNR_MID__A                                         0x2010018
+#define EC_SB_REG_SNR_LO__A                                          0x2010019
+#define EC_SB_REG_SCALE_MSB__A                                       0x201001A
+#define EC_SB_REG_SCALE_BIT2__A                                      0x201001B
+#define EC_SB_REG_SCALE_LSB__A                                       0x201001C
+#define EC_SB_REG_CSI_OFS__A                                         0x201001D
+#define EC_VD_REG_COMM_EXEC__A                                       0x2090000
+#define EC_VD_REG_FORCE__A                                           0x2090010
+#define EC_VD_REG_SET_CODERATE__A                                    0x2090011
+#define   EC_VD_REG_SET_CODERATE_C1_2                                0x0
+#define   EC_VD_REG_SET_CODERATE_C2_3                                0x1
+#define   EC_VD_REG_SET_CODERATE_C3_4                                0x2
+#define   EC_VD_REG_SET_CODERATE_C5_6                                0x3
+#define   EC_VD_REG_SET_CODERATE_C7_8                                0x4
+#define EC_VD_REG_REQ_SMB_CNT__A                                     0x2090012
+#define EC_VD_REG_RLK_ENA__A                                         0x2090014
+#define EC_OD_REG_COMM_EXEC__A                                       0x2110000
+#define EC_OD_REG_SYNC__A                                            0x2110010
+#define EC_OD_DEINT_RAM__A                                           0x2120000
+#define EC_RS_REG_COMM_EXEC__A                                       0x2130000
+#define EC_RS_REG_REQ_PCK_CNT__A                                     0x2130010
+#define EC_RS_REG_VAL__A                                             0x2130011
+#define   EC_RS_REG_VAL_PCK                                          0x1
+#define EC_RS_EC_RAM__A                                              0x2140000
+#define EC_OC_REG_COMM_EXEC__A                                       0x2150000
+#define     EC_OC_REG_COMM_EXEC_CTL_ACTIVE                           0x1
+#define     EC_OC_REG_COMM_EXEC_CTL_HOLD                             0x2
+#define EC_OC_REG_COMM_INT_STA__A                                    0x2150007
+#define EC_OC_REG_OC_MODE_LOP__A                                     0x2150010
+#define   EC_OC_REG_OC_MODE_LOP_PAR_ENA__M                           0x1
+#define     EC_OC_REG_OC_MODE_LOP_PAR_ENA_ENABLE                     0x0
+#define     EC_OC_REG_OC_MODE_LOP_PAR_ENA_DISABLE                    0x1
+#define   EC_OC_REG_OC_MODE_LOP_DTO_CTR_SRC__M                       0x4
+#define     EC_OC_REG_OC_MODE_LOP_DTO_CTR_SRC_STATIC                 0x0
+#define   EC_OC_REG_OC_MODE_LOP_MPG_TRM_MDE__M                       0x80
+#define     EC_OC_REG_OC_MODE_LOP_MPG_TRM_MDE_SERIAL                 0x80
+#define EC_OC_REG_OC_MODE_HIP__A                                     0x2150011
+#define     EC_OC_REG_OC_MODE_HIP_MPG_BUS_SRC_MONITOR                0x10
+#define   EC_OC_REG_OC_MODE_HIP_MPG_PAR_VAL__M                       0x200
+#define     EC_OC_REG_OC_MODE_HIP_MPG_PAR_VAL_DISABLE                0x0
+#define     EC_OC_REG_OC_MODE_HIP_MPG_PAR_VAL_ENABLE                 0x200
+#define EC_OC_REG_OC_MPG_SIO__A                                      0x2150012
+#define EC_OC_REG_OC_MPG_SIO__M                                      0xFFF
+#define EC_OC_REG_OC_MON_SIO__A                                      0x2150013
+#define EC_OC_REG_DTO_INC_LOP__A                                     0x2150014
+#define EC_OC_REG_DTO_INC_HIP__A                                     0x2150015
+#define EC_OC_REG_SNC_ISC_LVL__A                                     0x2150016
+#define   EC_OC_REG_SNC_ISC_LVL_OSC__M                               0xF0
+#define EC_OC_REG_TMD_TOP_MODE__A                                    0x215001D
+#define EC_OC_REG_TMD_TOP_CNT__A                                     0x215001E
+#define EC_OC_REG_TMD_HIL_MAR__A                                     0x215001F
+#define EC_OC_REG_TMD_LOL_MAR__A                                     0x2150020
+#define EC_OC_REG_TMD_CUR_CNT__A                                     0x2150021
+#define EC_OC_REG_AVR_ASH_CNT__A                                     0x2150023
+#define EC_OC_REG_AVR_BSH_CNT__A                                     0x2150024
+#define EC_OC_REG_RCN_MODE__A                                        0x2150027
+#define EC_OC_REG_RCN_CRA_LOP__A                                     0x2150028
+#define EC_OC_REG_RCN_CRA_HIP__A                                     0x2150029
+#define EC_OC_REG_RCN_CST_LOP__A                                     0x215002A
+#define EC_OC_REG_RCN_CST_HIP__A                                     0x215002B
+#define EC_OC_REG_RCN_SET_LVL__A                                     0x215002C
+#define EC_OC_REG_RCN_GAI_LVL__A                                     0x215002D
+#define EC_OC_REG_RCN_CLP_LOP__A                                     0x2150032
+#define EC_OC_REG_RCN_CLP_HIP__A                                     0x2150033
+#define EC_OC_REG_RCN_MAP_LOP__A                                     0x2150034
+#define EC_OC_REG_RCN_MAP_HIP__A                                     0x2150035
+#define EC_OC_REG_OCR_MPG_UOS__A                                     0x2150036
+#define EC_OC_REG_OCR_MPG_UOS__M                                     0xFFF
+#define   EC_OC_REG_OCR_MPG_UOS_INIT                                 0x0
+#define EC_OC_REG_OCR_MPG_USR_DAT__A                                 0x2150038
+#define EC_OC_REG_OCR_MON_UOS__A                                     0x2150039
+#define     EC_OC_REG_OCR_MON_UOS_DAT_0_ENABLE                       0x1
+#define     EC_OC_REG_OCR_MON_UOS_DAT_1_ENABLE                       0x2
+#define     EC_OC_REG_OCR_MON_UOS_DAT_2_ENABLE                       0x4
+#define     EC_OC_REG_OCR_MON_UOS_DAT_3_ENABLE                       0x8
+#define     EC_OC_REG_OCR_MON_UOS_DAT_4_ENABLE                       0x10
+#define     EC_OC_REG_OCR_MON_UOS_DAT_5_ENABLE                       0x20
+#define     EC_OC_REG_OCR_MON_UOS_DAT_6_ENABLE                       0x40
+#define     EC_OC_REG_OCR_MON_UOS_DAT_7_ENABLE                       0x80
+#define     EC_OC_REG_OCR_MON_UOS_DAT_8_ENABLE                       0x100
+#define     EC_OC_REG_OCR_MON_UOS_DAT_9_ENABLE                       0x200
+#define     EC_OC_REG_OCR_MON_UOS_VAL_ENABLE                         0x400
+#define     EC_OC_REG_OCR_MON_UOS_CLK_ENABLE                         0x800
+#define EC_OC_REG_OCR_MON_WRI__A                                     0x215003A
+#define   EC_OC_REG_OCR_MON_WRI_INIT                                 0x0
+#define EC_OC_REG_IPR_INV_MPG__A                                     0x2150045
+#define CC_REG_OSC_MODE__A                                           0x2410010
+#define   CC_REG_OSC_MODE_M20                                        0x1
+#define CC_REG_PLL_MODE__A                                           0x2410011
+#define     CC_REG_PLL_MODE_BYPASS_PLL                               0x1
+#define     CC_REG_PLL_MODE_PUMP_CUR_12                              0x14
+#define CC_REG_REF_DIVIDE__A                                         0x2410012
+#define CC_REG_PWD_MODE__A                                           0x2410015
+#define   CC_REG_PWD_MODE_DOWN_PLL                                   0x2
+#define CC_REG_UPDATE__A                                             0x2410017
+#define   CC_REG_UPDATE_KEY                                          0x3973
+#define CC_REG_JTAGID_L__A                                           0x2410019
+#define LC_COMM_EXEC__A                                              0x2800000
+#define LC_RA_RAM_IFINCR_NOM_L__A                                    0x282000C
+#define LC_RA_RAM_FILTER_SYM_SET__A                                  0x282001A
+#define LC_RA_RAM_FILTER_SYM_SET__PRE                                0x3E8
+#define LC_RA_RAM_FILTER_CRMM_A__A                                   0x2820060
+#define LC_RA_RAM_FILTER_CRMM_A__PRE                                 0x4
+#define LC_RA_RAM_FILTER_CRMM_B__A                                   0x2820061
+#define LC_RA_RAM_FILTER_CRMM_B__PRE                                 0x1
+#define LC_RA_RAM_FILTER_SRMM_A__A                                   0x2820068
+#define LC_RA_RAM_FILTER_SRMM_A__PRE                                 0x4
+#define LC_RA_RAM_FILTER_SRMM_B__A                                   0x2820069
+#define LC_RA_RAM_FILTER_SRMM_B__PRE                                 0x1
+#define B_HI_COMM_EXEC__A                                            0x400000
+#define B_HI_COMM_MB__A                                              0x400002
+#define B_HI_CT_REG_COMM_STATE__A                                    0x410001
+#define B_HI_RA_RAM_SRV_RES__A                                       0x420031
+#define B_HI_RA_RAM_SRV_CMD__A                                       0x420032
+#define   B_HI_RA_RAM_SRV_CMD_RESET                                  0x2
+#define   B_HI_RA_RAM_SRV_CMD_CONFIG                                 0x3
+#define   B_HI_RA_RAM_SRV_CMD_EXECUTE                                0x6
+#define B_HI_RA_RAM_SRV_RST_KEY__A                                   0x420033
+#define   B_HI_RA_RAM_SRV_RST_KEY_ACT                                0x3973
+#define B_HI_RA_RAM_SRV_CFG_KEY__A                                   0x420033
+#define B_HI_RA_RAM_SRV_CFG_DIV__A                                   0x420034
+#define B_HI_RA_RAM_SRV_CFG_BDL__A                                   0x420035
+#define B_HI_RA_RAM_SRV_CFG_WUP__A                                   0x420036
+#define B_HI_RA_RAM_SRV_CFG_ACT__A                                   0x420037
+#define     B_HI_RA_RAM_SRV_CFG_ACT_SLV0_ON                          0x1
+#define   B_HI_RA_RAM_SRV_CFG_ACT_BRD__M                             0x4
+#define     B_HI_RA_RAM_SRV_CFG_ACT_BRD_OFF                          0x0
+#define     B_HI_RA_RAM_SRV_CFG_ACT_BRD_ON                           0x4
+#define     B_HI_RA_RAM_SRV_CFG_ACT_PWD_EXE                          0x8
+#define B_HI_RA_RAM_USR_BEGIN__A                                     0x420040
+#define B_HI_IF_RAM_TRP_BPT0__AX                                     0x430000
+#define B_HI_IF_RAM_USR_BEGIN__A                                     0x430200
+#define B_SC_COMM_EXEC__A                                            0x800000
+#define     B_SC_COMM_EXEC_CTL_STOP                                  0x0
+#define B_SC_COMM_STATE__A                                           0x800001
+#define B_SC_RA_RAM_PARAM0__A                                        0x820040
+#define B_SC_RA_RAM_PARAM1__A                                        0x820041
+#define B_SC_RA_RAM_CMD_ADDR__A                                      0x820042
+#define B_SC_RA_RAM_CMD__A                                           0x820043
+#define   B_SC_RA_RAM_CMD_PROC_START                                 0x1
+#define   B_SC_RA_RAM_CMD_SET_PREF_PARAM                             0x3
+#define   B_SC_RA_RAM_CMD_GET_OP_PARAM                               0x5
+#define   B_SC_RA_RAM_SW_EVENT_RUN_NMASK__M                          0x1
+#define   B_SC_RA_RAM_LOCKTRACK_MIN                                  0x1
+#define     B_SC_RA_RAM_OP_PARAM_MODE_2K                             0x0
+#define     B_SC_RA_RAM_OP_PARAM_MODE_8K                             0x1
+#define     B_SC_RA_RAM_OP_PARAM_GUARD_32                            0x0
+#define     B_SC_RA_RAM_OP_PARAM_GUARD_16                            0x4
+#define     B_SC_RA_RAM_OP_PARAM_GUARD_8                             0x8
+#define     B_SC_RA_RAM_OP_PARAM_GUARD_4                             0xC
+#define     B_SC_RA_RAM_OP_PARAM_CONST_QPSK                          0x0
+#define     B_SC_RA_RAM_OP_PARAM_CONST_QAM16                         0x10
+#define     B_SC_RA_RAM_OP_PARAM_CONST_QAM64                         0x20
+#define     B_SC_RA_RAM_OP_PARAM_HIER_NO                             0x0
+#define     B_SC_RA_RAM_OP_PARAM_HIER_A1                             0x40
+#define     B_SC_RA_RAM_OP_PARAM_HIER_A2                             0x80
+#define     B_SC_RA_RAM_OP_PARAM_HIER_A4                             0xC0
+#define     B_SC_RA_RAM_OP_PARAM_RATE_1_2                            0x0
+#define     B_SC_RA_RAM_OP_PARAM_RATE_2_3                            0x200
+#define     B_SC_RA_RAM_OP_PARAM_RATE_3_4                            0x400
+#define     B_SC_RA_RAM_OP_PARAM_RATE_5_6                            0x600
+#define     B_SC_RA_RAM_OP_PARAM_RATE_7_8                            0x800
+#define     B_SC_RA_RAM_OP_PARAM_PRIO_HI                             0x0
+#define     B_SC_RA_RAM_OP_PARAM_PRIO_LO                             0x1000
+#define   B_SC_RA_RAM_OP_AUTO_MODE__M                                0x1
+#define   B_SC_RA_RAM_OP_AUTO_GUARD__M                               0x2
+#define   B_SC_RA_RAM_OP_AUTO_CONST__M                               0x4
+#define   B_SC_RA_RAM_OP_AUTO_HIER__M                                0x8
+#define   B_SC_RA_RAM_OP_AUTO_RATE__M                                0x10
+#define B_SC_RA_RAM_LOCK__A                                          0x82004B
+#define   B_SC_RA_RAM_LOCK_DEMOD__M                                  0x1
+#define   B_SC_RA_RAM_LOCK_FEC__M                                    0x2
+#define   B_SC_RA_RAM_LOCK_MPEG__M                                   0x4
+#define B_SC_RA_RAM_BE_OPT_ENA__A                                    0x82004C
+#define   B_SC_RA_RAM_BE_OPT_ENA_CP_OPT                              0x1
+#define B_SC_RA_RAM_BE_OPT_DELAY__A                                  0x82004D
+#define B_SC_RA_RAM_CONFIG__A                                        0x820050
+#define   B_SC_RA_RAM_CONFIG_FR_ENABLE__M                            0x4
+#define   B_SC_RA_RAM_CONFIG_FREQSCAN__M                             0x10
+#define   B_SC_RA_RAM_CONFIG_SLAVE__M                                0x20
+#define   B_SC_RA_RAM_CONFIG_DIV_BLANK_ENABLE__M                     0x200
+#define   B_SC_RA_RAM_CONFIG_DIV_ECHO_ENABLE__M                      0x400
+#define B_SC_RA_RAM_CO_TD_CAL_2K__A                                  0x82005D
+#define B_SC_RA_RAM_CO_TD_CAL_8K__A                                  0x82005E
+#define B_SC_RA_RAM_IF_SAVE__AX                                      0x82008E
+#define B_SC_RA_RAM_DIVERSITY_DELAY_2K_32__A                         0x820098
+#define B_SC_RA_RAM_DIVERSITY_DELAY_2K_16__A                         0x820099
+#define B_SC_RA_RAM_DIVERSITY_DELAY_2K_8__A                          0x82009A
+#define B_SC_RA_RAM_DIVERSITY_DELAY_2K_4__A                          0x82009B
+#define B_SC_RA_RAM_DIVERSITY_DELAY_8K_32__A                         0x82009C
+#define B_SC_RA_RAM_DIVERSITY_DELAY_8K_16__A                         0x82009D
+#define B_SC_RA_RAM_DIVERSITY_DELAY_8K_8__A                          0x82009E
+#define B_SC_RA_RAM_DIVERSITY_DELAY_8K_4__A                          0x82009F
+#define B_SC_RA_RAM_IR_COARSE_2K_LENGTH__A                           0x8200D1
+#define B_SC_RA_RAM_IR_COARSE_2K_LENGTH__PRE                         0x9
+#define B_SC_RA_RAM_IR_COARSE_2K_FREQINC__A                          0x8200D2
+#define B_SC_RA_RAM_IR_COARSE_2K_FREQINC__PRE                        0x4
+#define B_SC_RA_RAM_IR_COARSE_2K_KAISINC__A                          0x8200D3
+#define B_SC_RA_RAM_IR_COARSE_2K_KAISINC__PRE                        0x100
+#define B_SC_RA_RAM_IR_COARSE_8K_LENGTH__A                           0x8200D4
+#define B_SC_RA_RAM_IR_COARSE_8K_LENGTH__PRE                         0x8
+#define B_SC_RA_RAM_IR_COARSE_8K_FREQINC__A                          0x8200D5
+#define B_SC_RA_RAM_IR_COARSE_8K_FREQINC__PRE                        0x8
+#define B_SC_RA_RAM_IR_COARSE_8K_KAISINC__A                          0x8200D6
+#define B_SC_RA_RAM_IR_COARSE_8K_KAISINC__PRE                        0x200
+#define B_SC_RA_RAM_IR_FINE_2K_LENGTH__A                             0x8200D7
+#define B_SC_RA_RAM_IR_FINE_2K_LENGTH__PRE                           0x9
+#define B_SC_RA_RAM_IR_FINE_2K_FREQINC__A                            0x8200D8
+#define B_SC_RA_RAM_IR_FINE_2K_FREQINC__PRE                          0x4
+#define B_SC_RA_RAM_IR_FINE_2K_KAISINC__A                            0x8200D9
+#define B_SC_RA_RAM_IR_FINE_2K_KAISINC__PRE                          0x100
+#define B_SC_RA_RAM_IR_FINE_8K_LENGTH__A                             0x8200DA
+#define B_SC_RA_RAM_IR_FINE_8K_LENGTH__PRE                           0xB
+#define B_SC_RA_RAM_IR_FINE_8K_FREQINC__A                            0x8200DB
+#define B_SC_RA_RAM_IR_FINE_8K_FREQINC__PRE                          0x1
+#define B_SC_RA_RAM_IR_FINE_8K_KAISINC__A                            0x8200DC
+#define B_SC_RA_RAM_IR_FINE_8K_KAISINC__PRE                          0x40
+#define B_SC_RA_RAM_ECHO_SHIFT_LIM__A                                0x8200DD
+#define B_SC_RA_RAM_SAMPLE_RATE_COUNT__A                             0x8200E8
+#define B_SC_RA_RAM_SAMPLE_RATE_STEP__A                              0x8200E9
+#define B_SC_RA_RAM_BAND__A                                          0x8200EC
+#define B_SC_RA_RAM_LC_ABS_2K__A                                     0x8200F4
+#define B_SC_RA_RAM_LC_ABS_2K__PRE                                   0x1F
+#define B_SC_RA_RAM_LC_ABS_8K__A                                     0x8200F5
+#define B_SC_RA_RAM_LC_ABS_8K__PRE                                   0x1F
+#define B_SC_RA_RAM_EQ_IS_GAIN_UNKNOWN_MAN__PRE                      0x100
+#define B_SC_RA_RAM_EQ_IS_GAIN_UNKNOWN_EXP__PRE                      0x4
+#define B_SC_RA_RAM_EQ_IS_GAIN_QPSK_MAN__PRE                         0x1E2
+#define B_SC_RA_RAM_EQ_IS_GAIN_QPSK_EXP__PRE                         0x4
+#define B_SC_RA_RAM_EQ_IS_GAIN_16QAM_MAN__PRE                        0x10D
+#define B_SC_RA_RAM_EQ_IS_GAIN_16QAM_EXP__PRE                        0x5
+#define B_SC_RA_RAM_EQ_IS_GAIN_16QAM_A2_MAN__PRE                     0x17D
+#define B_SC_RA_RAM_EQ_IS_GAIN_16QAM_A2_EXP__PRE                     0x4
+#define B_SC_RA_RAM_EQ_IS_GAIN_16QAM_A4_MAN__PRE                     0x133
+#define B_SC_RA_RAM_EQ_IS_GAIN_16QAM_A4_EXP__PRE                     0x5
+#define B_SC_RA_RAM_EQ_IS_GAIN_64QAM_MAN__PRE                        0x114
+#define B_SC_RA_RAM_EQ_IS_GAIN_64QAM_EXP__PRE                        0x5
+#define B_SC_RA_RAM_EQ_IS_GAIN_64QAM_A2_MAN__PRE                     0x14A
+#define B_SC_RA_RAM_EQ_IS_GAIN_64QAM_A2_EXP__PRE                     0x4
+#define B_SC_RA_RAM_EQ_IS_GAIN_64QAM_A4_MAN__PRE                     0x1BB
+#define B_SC_RA_RAM_EQ_IS_GAIN_64QAM_A4_EXP__PRE                     0x4
+#define B_SC_RA_RAM_DRIVER_VERSION__AX                               0x8201FE
+#define   B_SC_RA_RAM_PROC_LOCKTRACK                                 0x0
+#define B_FE_COMM_EXEC__A                                            0xC00000
+#define B_FE_AD_REG_COMM_EXEC__A                                     0xC10000
+#define B_FE_AD_REG_FDB_IN__A                                        0xC10012
+#define B_FE_AD_REG_PD__A                                            0xC10013
+#define B_FE_AD_REG_INVEXT__A                                        0xC10014
+#define B_FE_AD_REG_CLKNEG__A                                        0xC10015
+#define B_FE_AG_REG_COMM_EXEC__A                                     0xC20000
+#define B_FE_AG_REG_AG_MODE_LOP__A                                   0xC20010
+#define   B_FE_AG_REG_AG_MODE_LOP_MODE_4__M                          0x10
+#define     B_FE_AG_REG_AG_MODE_LOP_MODE_4_STATIC                    0x0
+#define     B_FE_AG_REG_AG_MODE_LOP_MODE_4_DYNAMIC                   0x10
+#define   B_FE_AG_REG_AG_MODE_LOP_MODE_5__M                          0x20
+#define     B_FE_AG_REG_AG_MODE_LOP_MODE_5_STATIC                    0x0
+#define   B_FE_AG_REG_AG_MODE_LOP_MODE_C__M                          0x1000
+#define     B_FE_AG_REG_AG_MODE_LOP_MODE_C_STATIC                    0x0
+#define     B_FE_AG_REG_AG_MODE_LOP_MODE_C_DYNAMIC                   0x1000
+#define   B_FE_AG_REG_AG_MODE_LOP_MODE_E__M                          0x4000
+#define     B_FE_AG_REG_AG_MODE_LOP_MODE_E_STATIC                    0x0
+#define     B_FE_AG_REG_AG_MODE_LOP_MODE_E_DYNAMIC                   0x4000
+#define B_FE_AG_REG_AG_MODE_HIP__A                                   0xC20011
+#define   B_FE_AG_REG_AG_MODE_HIP_MODE_J__M                          0x8
+#define     B_FE_AG_REG_AG_MODE_HIP_MODE_J_STATIC                    0x0
+#define     B_FE_AG_REG_AG_MODE_HIP_MODE_J_DYNAMIC                   0x8
+#define B_FE_AG_REG_AG_PGA_MODE__A                                   0xC20012
+#define   B_FE_AG_REG_AG_PGA_MODE_PFY_PCY_AFY_REN                    0x0
+#define   B_FE_AG_REG_AG_PGA_MODE_PFN_PCN_AFY_REN                    0x1
+#define B_FE_AG_REG_AG_AGC_SIO__A                                    0xC20013
+#define   B_FE_AG_REG_AG_AGC_SIO_AGC_SIO_2__M                        0x2
+#define     B_FE_AG_REG_AG_AGC_SIO_AGC_SIO_2_OUTPUT                  0x0
+#define     B_FE_AG_REG_AG_AGC_SIO_AGC_SIO_2_INPUT                   0x2
+#define B_FE_AG_REG_AG_PWD__A                                        0xC20015
+#define   B_FE_AG_REG_AG_PWD_PWD_PD2__M                              0x2
+#define     B_FE_AG_REG_AG_PWD_PWD_PD2_DISABLE                       0x0
+#define     B_FE_AG_REG_AG_PWD_PWD_PD2_ENABLE                        0x2
+#define B_FE_AG_REG_DCE_AUR_CNT__A                                   0xC20016
+#define B_FE_AG_REG_DCE_RUR_CNT__A                                   0xC20017
+#define B_FE_AG_REG_ACE_AUR_CNT__A                                   0xC2001A
+#define B_FE_AG_REG_ACE_RUR_CNT__A                                   0xC2001B
+#define B_FE_AG_REG_CDR_RUR_CNT__A                                   0xC20020
+#define B_FE_AG_REG_EGC_RUR_CNT__A                                   0xC20024
+#define B_FE_AG_REG_EGC_SET_LVL__A                                   0xC20025
+#define B_FE_AG_REG_EGC_SET_LVL__M                                   0x1FF
+#define B_FE_AG_REG_EGC_FLA_RGN__A                                   0xC20026
+#define B_FE_AG_REG_EGC_SLO_RGN__A                                   0xC20027
+#define B_FE_AG_REG_EGC_JMP_PSN__A                                   0xC20028
+#define B_FE_AG_REG_EGC_FLA_INC__A                                   0xC20029
+#define B_FE_AG_REG_EGC_FLA_DEC__A                                   0xC2002A
+#define B_FE_AG_REG_EGC_SLO_INC__A                                   0xC2002B
+#define B_FE_AG_REG_EGC_SLO_DEC__A                                   0xC2002C
+#define B_FE_AG_REG_EGC_FAS_INC__A                                   0xC2002D
+#define B_FE_AG_REG_EGC_FAS_DEC__A                                   0xC2002E
+#define B_FE_AG_REG_PM1_AGC_WRI__A                                   0xC20030
+#define B_FE_AG_REG_PM1_AGC_WRI__M                                   0x7FF
+#define B_FE_AG_REG_GC1_AGC_RIC__A                                   0xC20031
+#define B_FE_AG_REG_GC1_AGC_OFF__A                                   0xC20032
+#define B_FE_AG_REG_GC1_AGC_MAX__A                                   0xC20033
+#define B_FE_AG_REG_GC1_AGC_MIN__A                                   0xC20034
+#define B_FE_AG_REG_GC1_AGC_DAT__A                                   0xC20035
+#define B_FE_AG_REG_GC1_AGC_DAT__M                                   0x3FF
+#define B_FE_AG_REG_PM2_AGC_WRI__A                                   0xC20036
+#define B_FE_AG_REG_IND_WIN__A                                       0xC2003C
+#define B_FE_AG_REG_IND_THD_LOL__A                                   0xC2003D
+#define B_FE_AG_REG_IND_THD_HIL__A                                   0xC2003E
+#define B_FE_AG_REG_IND_DEL__A                                       0xC2003F
+#define B_FE_AG_REG_IND_PD1_WRI__A                                   0xC20040
+#define B_FE_AG_REG_PDA_AUR_CNT__A                                   0xC20041
+#define B_FE_AG_REG_PDA_RUR_CNT__A                                   0xC20042
+#define B_FE_AG_REG_PDA_AVE_DAT__A                                   0xC20043
+#define B_FE_AG_REG_PDC_RUR_CNT__A                                   0xC20044
+#define B_FE_AG_REG_PDC_SET_LVL__A                                   0xC20045
+#define B_FE_AG_REG_PDC_FLA_RGN__A                                   0xC20046
+#define B_FE_AG_REG_PDC_JMP_PSN__A                                   0xC20047
+#define B_FE_AG_REG_PDC_FLA_STP__A                                   0xC20048
+#define B_FE_AG_REG_PDC_SLO_STP__A                                   0xC20049
+#define B_FE_AG_REG_PDC_PD2_WRI__A                                   0xC2004A
+#define B_FE_AG_REG_PDC_MAP_DAT__A                                   0xC2004B
+#define B_FE_AG_REG_PDC_MAX__A                                       0xC2004C
+#define B_FE_AG_REG_TGA_AUR_CNT__A                                   0xC2004D
+#define B_FE_AG_REG_TGA_RUR_CNT__A                                   0xC2004E
+#define B_FE_AG_REG_TGA_AVE_DAT__A                                   0xC2004F
+#define B_FE_AG_REG_TGC_RUR_CNT__A                                   0xC20050
+#define B_FE_AG_REG_TGC_SET_LVL__A                                   0xC20051
+#define B_FE_AG_REG_TGC_SET_LVL__M                                   0x3F
+#define B_FE_AG_REG_TGC_FLA_RGN__A                                   0xC20052
+#define B_FE_AG_REG_TGC_JMP_PSN__A                                   0xC20053
+#define B_FE_AG_REG_TGC_FLA_STP__A                                   0xC20054
+#define B_FE_AG_REG_TGC_SLO_STP__A                                   0xC20055
+#define B_FE_AG_REG_TGC_MAP_DAT__A                                   0xC20056
+#define B_FE_AG_REG_FGM_WRI__A                                       0xC20061
+#define B_FE_AG_REG_BGC_FGC_WRI__A                                   0xC20068
+#define B_FE_AG_REG_BGC_CGC_WRI__A                                   0xC20069
+#define B_FE_FS_REG_COMM_EXEC__A                                     0xC30000
+#define B_FE_FS_REG_ADD_INC_LOP__A                                   0xC30010
+#define B_FE_FD_REG_COMM_EXEC__A                                     0xC40000
+#define B_FE_FD_REG_SCL__A                                           0xC40010
+#define B_FE_FD_REG_MAX_LEV__A                                       0xC40011
+#define B_FE_FD_REG_NR__A                                            0xC40012
+#define B_FE_FD_REG_MEAS_VAL__A                                      0xC40014
+#define B_FE_IF_REG_COMM_EXEC__A                                     0xC50000
+#define B_FE_IF_REG_INCR0__A                                         0xC50010
+#define B_FE_IF_REG_INCR0__W                                         16
+#define B_FE_IF_REG_INCR0__M                                         0xFFFF
+#define B_FE_IF_REG_INCR1__A                                         0xC50011
+#define B_FE_IF_REG_INCR1__M                                         0xFF
+#define B_FE_CF_REG_COMM_EXEC__A                                     0xC60000
+#define B_FE_CF_REG_SCL__A                                           0xC60010
+#define B_FE_CF_REG_MAX_LEV__A                                       0xC60011
+#define B_FE_CF_REG_NR__A                                            0xC60012
+#define B_FE_CF_REG_IMP_VAL__A                                       0xC60013
+#define B_FE_CF_REG_MEAS_VAL__A                                      0xC60014
+#define B_FE_CU_REG_COMM_EXEC__A                                     0xC70000
+#define B_FE_CU_REG_FRM_CNT_RST__A                                   0xC70011
+#define B_FE_CU_REG_FRM_CNT_STR__A                                   0xC70012
+#define B_FE_CU_REG_CTR_NFC_ICR__A                                   0xC70020
+#define B_FE_CU_REG_CTR_NFC_OCR__A                                   0xC70021
+#define B_FE_CU_REG_DIV_NFC_CLP__A                                   0xC70027
+#define B_FT_COMM_EXEC__A                                            0x1000000
+#define B_FT_REG_COMM_EXEC__A                                        0x1010000
+#define B_CP_COMM_EXEC__A                                            0x1400000
+#define B_CP_REG_COMM_EXEC__A                                        0x1410000
+#define B_CP_REG_INTERVAL__A                                         0x1410011
+#define B_CP_REG_BR_SPL_OFFSET__A                                    0x1410023
+#define B_CP_REG_BR_STR_DEL__A                                       0x1410024
+#define B_CP_REG_RT_ANG_INC0__A                                      0x1410030
+#define B_CP_REG_RT_ANG_INC1__A                                      0x1410031
+#define B_CP_REG_RT_DETECT_TRH__A                                    0x1410033
+#define B_CP_REG_AC_NEXP_OFFS__A                                     0x1410040
+#define B_CP_REG_AC_AVER_POW__A                                      0x1410041
+#define B_CP_REG_AC_MAX_POW__A                                       0x1410042
+#define B_CP_REG_AC_WEIGHT_MAN__A                                    0x1410043
+#define B_CP_REG_AC_WEIGHT_EXP__A                                    0x1410044
+#define B_CP_REG_AC_AMP_MODE__A                                      0x1410047
+#define B_CP_REG_AC_AMP_FIX__A                                       0x1410048
+#define B_CP_REG_AC_ANG_MODE__A                                      0x141004A
+#define B_CE_COMM_EXEC__A                                            0x1800000
+#define B_CE_REG_COMM_EXEC__A                                        0x1810000
+#define B_CE_REG_TAPSET__A                                           0x1810011
+#define B_CE_REG_AVG_POW__A                                          0x1810012
+#define B_CE_REG_MAX_POW__A                                          0x1810013
+#define B_CE_REG_ATT__A                                              0x1810014
+#define B_CE_REG_NRED__A                                             0x1810015
+#define B_CE_REG_NE_ERR_SELECT__A                                    0x1810043
+#define B_CE_REG_NE_TD_CAL__A                                        0x1810044
+#define B_CE_REG_NE_MIXAVG__A                                        0x1810046
+#define B_CE_REG_NE_NUPD_OFS__A                                      0x1810047
+#define B_CE_REG_PE_NEXP_OFFS__A                                     0x1810050
+#define B_CE_REG_PE_TIMESHIFT__A                                     0x1810051
+#define B_CE_REG_TP_A0_TAP_NEW__A                                    0x1810064
+#define B_CE_REG_TP_A0_TAP_NEW_VALID__A                              0x1810065
+#define B_CE_REG_TP_A0_MU_LMS_STEP__A                                0x1810066
+#define B_CE_REG_TP_A1_TAP_NEW__A                                    0x1810068
+#define B_CE_REG_TP_A1_TAP_NEW_VALID__A                              0x1810069
+#define B_CE_REG_TP_A1_MU_LMS_STEP__A                                0x181006A
+#define B_CE_REG_TI_PHN_ENABLE__A                                    0x1810073
+#define B_CE_REG_FI_SHT_INCR__A                                      0x1810090
+#define B_CE_REG_FI_EXP_NORM__A                                      0x1810091
+#define B_CE_REG_IR_INPUTSEL__A                                      0x18100A0
+#define B_CE_REG_IR_STARTPOS__A                                      0x18100A1
+#define B_CE_REG_IR_NEXP_THRES__A                                    0x18100A2
+#define B_CE_REG_FR_TREAL00__A                                       0x1820010
+#define B_CE_REG_FR_TIMAG00__A                                       0x1820011
+#define B_CE_REG_FR_TREAL01__A                                       0x1820012
+#define B_CE_REG_FR_TIMAG01__A                                       0x1820013
+#define B_CE_REG_FR_TREAL02__A                                       0x1820014
+#define B_CE_REG_FR_TIMAG02__A                                       0x1820015
+#define B_CE_REG_FR_TREAL03__A                                       0x1820016
+#define B_CE_REG_FR_TIMAG03__A                                       0x1820017
+#define B_CE_REG_FR_TREAL04__A                                       0x1820018
+#define B_CE_REG_FR_TIMAG04__A                                       0x1820019
+#define B_CE_REG_FR_TREAL05__A                                       0x182001A
+#define B_CE_REG_FR_TIMAG05__A                                       0x182001B
+#define B_CE_REG_FR_TREAL06__A                                       0x182001C
+#define B_CE_REG_FR_TIMAG06__A                                       0x182001D
+#define B_CE_REG_FR_TREAL07__A                                       0x182001E
+#define B_CE_REG_FR_TIMAG07__A                                       0x182001F
+#define B_CE_REG_FR_TREAL08__A                                       0x1820020
+#define B_CE_REG_FR_TIMAG08__A                                       0x1820021
+#define B_CE_REG_FR_TREAL09__A                                       0x1820022
+#define B_CE_REG_FR_TIMAG09__A                                       0x1820023
+#define B_CE_REG_FR_TREAL10__A                                       0x1820024
+#define B_CE_REG_FR_TIMAG10__A                                       0x1820025
+#define B_CE_REG_FR_TREAL11__A                                       0x1820026
+#define B_CE_REG_FR_TIMAG11__A                                       0x1820027
+#define B_CE_REG_FR_MID_TAP__A                                       0x1820028
+#define B_CE_REG_FR_SQS_G00__A                                       0x1820029
+#define B_CE_REG_FR_SQS_G01__A                                       0x182002A
+#define B_CE_REG_FR_SQS_G02__A                                       0x182002B
+#define B_CE_REG_FR_SQS_G03__A                                       0x182002C
+#define B_CE_REG_FR_SQS_G04__A                                       0x182002D
+#define B_CE_REG_FR_SQS_G05__A                                       0x182002E
+#define B_CE_REG_FR_SQS_G06__A                                       0x182002F
+#define B_CE_REG_FR_SQS_G07__A                                       0x1820030
+#define B_CE_REG_FR_SQS_G08__A                                       0x1820031
+#define B_CE_REG_FR_SQS_G09__A                                       0x1820032
+#define B_CE_REG_FR_SQS_G10__A                                       0x1820033
+#define B_CE_REG_FR_SQS_G11__A                                       0x1820034
+#define B_CE_REG_FR_SQS_G12__A                                       0x1820035
+#define B_CE_REG_FR_RIO_G00__A                                       0x1820036
+#define B_CE_REG_FR_RIO_G01__A                                       0x1820037
+#define B_CE_REG_FR_RIO_G02__A                                       0x1820038
+#define B_CE_REG_FR_RIO_G03__A                                       0x1820039
+#define B_CE_REG_FR_RIO_G04__A                                       0x182003A
+#define B_CE_REG_FR_RIO_G05__A                                       0x182003B
+#define B_CE_REG_FR_RIO_G06__A                                       0x182003C
+#define B_CE_REG_FR_RIO_G07__A                                       0x182003D
+#define B_CE_REG_FR_RIO_G08__A                                       0x182003E
+#define B_CE_REG_FR_RIO_G09__A                                       0x182003F
+#define B_CE_REG_FR_RIO_G10__A                                       0x1820040
+#define B_CE_REG_FR_MODE__A                                          0x1820041
+#define B_CE_REG_FR_SQS_TRH__A                                       0x1820042
+#define B_CE_REG_FR_RIO_GAIN__A                                      0x1820043
+#define B_CE_REG_FR_BYPASS__A                                        0x1820044
+#define B_CE_REG_FR_PM_SET__A                                        0x1820045
+#define B_CE_REG_FR_ERR_SH__A                                        0x1820046
+#define B_CE_REG_FR_MAN_SH__A                                        0x1820047
+#define B_CE_REG_FR_TAP_SH__A                                        0x1820048
+#define B_EQ_COMM_EXEC__A                                            0x1C00000
+#define B_EQ_REG_COMM_EXEC__A                                        0x1C10000
+#define B_EQ_REG_COMM_MB__A                                          0x1C10002
+#define B_EQ_REG_IS_GAIN_MAN__A                                      0x1C10015
+#define B_EQ_REG_IS_GAIN_EXP__A                                      0x1C10016
+#define B_EQ_REG_IS_CLIP_EXP__A                                      0x1C10017
+#define B_EQ_REG_SN_CEGAIN__A                                        0x1C1002A
+#define B_EQ_REG_SN_OFFSET__A                                        0x1C1002B
+#define B_EQ_REG_RC_SEL_CAR__A                                       0x1C10032
+#define   B_EQ_REG_RC_SEL_CAR_INIT                                   0x2
+#define     B_EQ_REG_RC_SEL_CAR_DIV_ON                               0x1
+#define     B_EQ_REG_RC_SEL_CAR_PASS_A_CC                            0x0
+#define     B_EQ_REG_RC_SEL_CAR_PASS_B_CE                            0x2
+#define     B_EQ_REG_RC_SEL_CAR_LOCAL_A_CC                           0x0
+#define     B_EQ_REG_RC_SEL_CAR_LOCAL_B_CE                           0x8
+#define     B_EQ_REG_RC_SEL_CAR_MEAS_A_CC                            0x0
+#define     B_EQ_REG_RC_SEL_CAR_MEAS_B_CE                            0x20
+#define   B_EQ_REG_RC_SEL_CAR_FFTMODE__M                             0x80
+#define B_EQ_REG_OT_CONST__A                                         0x1C10046
+#define B_EQ_REG_OT_ALPHA__A                                         0x1C10047
+#define B_EQ_REG_OT_QNT_THRES0__A                                    0x1C10048
+#define B_EQ_REG_OT_QNT_THRES1__A                                    0x1C10049
+#define B_EQ_REG_OT_CSI_STEP__A                                      0x1C1004A
+#define B_EQ_REG_OT_CSI_OFFSET__A                                    0x1C1004B
+#define B_EQ_REG_TD_REQ_SMB_CNT__A                                   0x1C10061
+#define B_EQ_REG_TD_TPS_PWR_OFS__A                                   0x1C10062
+#define B_EC_SB_REG_COMM_EXEC__A                                     0x2010000
+#define B_EC_SB_REG_TR_MODE__A                                       0x2010010
+#define   B_EC_SB_REG_TR_MODE_8K                                     0x0
+#define   B_EC_SB_REG_TR_MODE_2K                                     0x1
+#define B_EC_SB_REG_CONST__A                                         0x2010011
+#define   B_EC_SB_REG_CONST_QPSK                                     0x0
+#define   B_EC_SB_REG_CONST_16QAM                                    0x1
+#define   B_EC_SB_REG_CONST_64QAM                                    0x2
+#define B_EC_SB_REG_ALPHA__A                                         0x2010012
+#define B_EC_SB_REG_PRIOR__A                                         0x2010013
+#define   B_EC_SB_REG_PRIOR_HI                                       0x0
+#define   B_EC_SB_REG_PRIOR_LO                                       0x1
+#define B_EC_SB_REG_CSI_HI__A                                        0x2010014
+#define B_EC_SB_REG_CSI_LO__A                                        0x2010015
+#define B_EC_SB_REG_SMB_TGL__A                                       0x2010016
+#define B_EC_SB_REG_SNR_HI__A                                        0x2010017
+#define B_EC_SB_REG_SNR_MID__A                                       0x2010018
+#define B_EC_SB_REG_SNR_LO__A                                        0x2010019
+#define B_EC_SB_REG_SCALE_MSB__A                                     0x201001A
+#define B_EC_SB_REG_SCALE_BIT2__A                                    0x201001B
+#define B_EC_SB_REG_SCALE_LSB__A                                     0x201001C
+#define B_EC_SB_REG_CSI_OFS0__A                                      0x201001D
+#define B_EC_SB_REG_CSI_OFS1__A                                      0x201001E
+#define B_EC_SB_REG_CSI_OFS2__A                                      0x201001F
+#define B_EC_VD_REG_COMM_EXEC__A                                     0x2090000
+#define B_EC_VD_REG_FORCE__A                                         0x2090010
+#define B_EC_VD_REG_SET_CODERATE__A                                  0x2090011
+#define   B_EC_VD_REG_SET_CODERATE_C1_2                              0x0
+#define   B_EC_VD_REG_SET_CODERATE_C2_3                              0x1
+#define   B_EC_VD_REG_SET_CODERATE_C3_4                              0x2
+#define   B_EC_VD_REG_SET_CODERATE_C5_6                              0x3
+#define   B_EC_VD_REG_SET_CODERATE_C7_8                              0x4
+#define B_EC_VD_REG_REQ_SMB_CNT__A                                   0x2090012
+#define B_EC_VD_REG_RLK_ENA__A                                       0x2090014
+#define B_EC_OD_REG_COMM_EXEC__A                                     0x2110000
+#define B_EC_OD_REG_SYNC__A                                          0x2110664
+#define B_EC_OD_DEINT_RAM__A                                         0x2120000
+#define B_EC_RS_REG_COMM_EXEC__A                                     0x2130000
+#define B_EC_RS_REG_REQ_PCK_CNT__A                                   0x2130010
+#define B_EC_RS_REG_VAL__A                                           0x2130011
+#define   B_EC_RS_REG_VAL_PCK                                        0x1
+#define B_EC_RS_EC_RAM__A                                            0x2140000
+#define B_EC_OC_REG_COMM_EXEC__A                                     0x2150000
+#define     B_EC_OC_REG_COMM_EXEC_CTL_ACTIVE                         0x1
+#define     B_EC_OC_REG_COMM_EXEC_CTL_HOLD                           0x2
+#define B_EC_OC_REG_COMM_INT_STA__A                                  0x2150007
+#define B_EC_OC_REG_OC_MODE_LOP__A                                   0x2150010
+#define   B_EC_OC_REG_OC_MODE_LOP_PAR_ENA__M                         0x1
+#define     B_EC_OC_REG_OC_MODE_LOP_PAR_ENA_ENABLE                   0x0
+#define     B_EC_OC_REG_OC_MODE_LOP_PAR_ENA_DISABLE                  0x1
+#define   B_EC_OC_REG_OC_MODE_LOP_DTO_CTR_SRC__M                     0x4
+#define     B_EC_OC_REG_OC_MODE_LOP_DTO_CTR_SRC_STATIC               0x0
+#define   B_EC_OC_REG_OC_MODE_LOP_MPG_TRM_MDE__M                     0x80
+#define     B_EC_OC_REG_OC_MODE_LOP_MPG_TRM_MDE_SERIAL               0x80
+#define B_EC_OC_REG_OC_MODE_HIP__A                                   0x2150011
+#define     B_EC_OC_REG_OC_MODE_HIP_MPG_BUS_SRC_MONITOR              0x10
+#define   B_EC_OC_REG_OC_MODE_HIP_MPG_PAR_VAL__M                     0x200
+#define     B_EC_OC_REG_OC_MODE_HIP_MPG_PAR_VAL_DISABLE              0x0
+#define     B_EC_OC_REG_OC_MODE_HIP_MPG_PAR_VAL_ENABLE               0x200
+#define B_EC_OC_REG_OC_MPG_SIO__A                                    0x2150012
+#define B_EC_OC_REG_OC_MPG_SIO__M                                    0xFFF
+#define B_EC_OC_REG_DTO_INC_LOP__A                                   0x2150014
+#define B_EC_OC_REG_DTO_INC_HIP__A                                   0x2150015
+#define B_EC_OC_REG_SNC_ISC_LVL__A                                   0x2150016
+#define   B_EC_OC_REG_SNC_ISC_LVL_OSC__M                             0xF0
+#define B_EC_OC_REG_TMD_TOP_MODE__A                                  0x215001D
+#define B_EC_OC_REG_TMD_TOP_CNT__A                                   0x215001E
+#define B_EC_OC_REG_TMD_HIL_MAR__A                                   0x215001F
+#define B_EC_OC_REG_TMD_LOL_MAR__A                                   0x2150020
+#define B_EC_OC_REG_TMD_CUR_CNT__A                                   0x2150021
+#define B_EC_OC_REG_AVR_ASH_CNT__A                                   0x2150023
+#define B_EC_OC_REG_AVR_BSH_CNT__A                                   0x2150024
+#define B_EC_OC_REG_RCN_MODE__A                                      0x2150027
+#define B_EC_OC_REG_RCN_CRA_LOP__A                                   0x2150028
+#define B_EC_OC_REG_RCN_CRA_HIP__A                                   0x2150029
+#define B_EC_OC_REG_RCN_CST_LOP__A                                   0x215002A
+#define B_EC_OC_REG_RCN_CST_HIP__A                                   0x215002B
+#define B_EC_OC_REG_RCN_SET_LVL__A                                   0x215002C
+#define B_EC_OC_REG_RCN_GAI_LVL__A                                   0x215002D
+#define B_EC_OC_REG_RCN_CLP_LOP__A                                   0x2150032
+#define B_EC_OC_REG_RCN_CLP_HIP__A                                   0x2150033
+#define B_EC_OC_REG_RCN_MAP_LOP__A                                   0x2150034
+#define B_EC_OC_REG_RCN_MAP_HIP__A                                   0x2150035
+#define B_EC_OC_REG_OCR_MPG_UOS__A                                   0x2150036
+#define B_EC_OC_REG_OCR_MPG_UOS__M                                   0xFFF
+#define   B_EC_OC_REG_OCR_MPG_UOS_INIT                               0x0
+#define B_EC_OC_REG_OCR_MPG_USR_DAT__A                               0x2150038
+#define B_EC_OC_REG_IPR_INV_MPG__A                                   0x2150045
+#define B_EC_OC_REG_DTO_CLKMODE__A                                   0x2150047
+#define B_EC_OC_REG_DTO_PER__A                                       0x2150048
+#define B_EC_OC_REG_DTO_BUR__A                                       0x2150049
+#define B_EC_OC_REG_RCR_CLKMODE__A                                   0x215004A
+#define B_CC_REG_OSC_MODE__A                                         0x2410010
+#define   B_CC_REG_OSC_MODE_M20                                      0x1
+#define B_CC_REG_PLL_MODE__A                                         0x2410011
+#define     B_CC_REG_PLL_MODE_BYPASS_PLL                             0x1
+#define     B_CC_REG_PLL_MODE_PUMP_CUR_12                            0x14
+#define B_CC_REG_REF_DIVIDE__A                                       0x2410012
+#define B_CC_REG_PWD_MODE__A                                         0x2410015
+#define   B_CC_REG_PWD_MODE_DOWN_PLL                                 0x2
+#define B_CC_REG_UPDATE__A                                           0x2410017
+#define   B_CC_REG_UPDATE_KEY                                        0x3973
+#define B_CC_REG_JTAGID_L__A                                         0x2410019
+#define B_CC_REG_DIVERSITY__A                                        0x241001B
+#define B_LC_COMM_EXEC__A                                            0x2800000
+#define B_LC_RA_RAM_IFINCR_NOM_L__A                                  0x282000C
+#define B_LC_RA_RAM_FILTER_SYM_SET__A                                0x282001A
+#define B_LC_RA_RAM_FILTER_SYM_SET__PRE                              0x3E8
+#define B_LC_RA_RAM_FILTER_CRMM_A__A                                 0x2820060
+#define B_LC_RA_RAM_FILTER_CRMM_A__PRE                               0x4
+#define B_LC_RA_RAM_FILTER_CRMM_B__A                                 0x2820061
+#define B_LC_RA_RAM_FILTER_CRMM_B__PRE                               0x1
+#define B_LC_RA_RAM_FILTER_SRMM_A__A                                 0x2820068
+#define B_LC_RA_RAM_FILTER_SRMM_A__PRE                               0x4
+#define B_LC_RA_RAM_FILTER_SRMM_B__A                                 0x2820069
+#define B_LC_RA_RAM_FILTER_SRMM_B__PRE                               0x1
+
+#endif
diff --git a/drivers/media/dvb-frontends/drxk.h b/drivers/media/dvb-frontends/drxk.h
new file mode 100644
index 0000000..d615d7d
--- /dev/null
+++ b/drivers/media/dvb-frontends/drxk.h
@@ -0,0 +1,66 @@
+#ifndef _DRXK_H_
+#define _DRXK_H_
+
+#include <linux/types.h>
+#include <linux/i2c.h>
+
+/**
+ * struct drxk_config - Configure the initial parameters for DRX-K
+ *
+ * @adr:		I2C Address of the DRX-K
+ * @parallel_ts:	True means that the device uses parallel TS,
+ * 			Serial otherwise.
+ * @dynamic_clk:	True means that the clock will be dynamically
+ *			adjusted. Static clock otherwise.
+ * @enable_merr_cfg:	Enable SIO_PDR_PERR_CFG/SIO_PDR_MVAL_CFG.
+ * @single_master:	Device is on the single master mode
+ * @no_i2c_bridge:	Don't switch the I2C bridge to talk with tuner
+ * @antenna_gpio:	GPIO bit used to control the antenna
+ * @antenna_dvbt:	GPIO bit for changing antenna to DVB-C. A value of 1
+ *			means that 1=DVBC, 0 = DVBT. Zero means the opposite.
+ * @mpeg_out_clk_strength: DRXK Mpeg output clock drive strength.
+ * @microcode_name:	Name of the firmware file with the microcode
+ * @qam_demod_parameter_count:	The number of parameters used for the command
+ *				to set the demodulator parameters. All
+ *				firmwares are using the 2-parameter commmand.
+ *				An exception is the "drxk_a3.mc" firmware,
+ *				which uses the 4-parameter command.
+ *				A value of 0 (default) or lower indicates that
+ *				the correct number of parameters will be
+ *				automatically detected.
+ *
+ * On the *_gpio vars, bit 0 is UIO-1, bit 1 is UIO-2 and bit 2 is
+ * UIO-3.
+ */
+struct drxk_config {
+	u8	adr;
+	bool	single_master;
+	bool	no_i2c_bridge;
+	bool	parallel_ts;
+	bool	dynamic_clk;
+	bool	enable_merr_cfg;
+
+	bool	antenna_dvbt;
+	u16	antenna_gpio;
+
+	u8	mpeg_out_clk_strength;
+	int	chunk_size;
+
+	const char	*microcode_name;
+	int		 qam_demod_parameter_count;
+};
+
+#if defined(CONFIG_DVB_DRXK) || (defined(CONFIG_DVB_DRXK_MODULE) \
+        && defined(MODULE))
+extern struct dvb_frontend *drxk_attach(const struct drxk_config *config,
+					struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend *drxk_attach(const struct drxk_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/drxk_hard.c b/drivers/media/dvb-frontends/drxk_hard.c
new file mode 100644
index 0000000..1ab8154
--- /dev/null
+++ b/drivers/media/dvb-frontends/drxk_hard.c
@@ -0,0 +1,6637 @@
+/*
+ * drxk_hard: DRX-K DVB-C/T demodulator driver
+ *
+ * Copyright (C) 2010-2011 Digital Devices GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 only, as published by the Free Software Foundation.
+ *
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/firmware.h>
+#include <linux/i2c.h>
+#include <linux/hardirq.h>
+#include <asm/div64.h>
+
+#include "dvb_frontend.h"
+#include "drxk.h"
+#include "drxk_hard.h"
+
+static int PowerDownDVBT(struct drxk_state *state, bool setPowerMode);
+static int PowerDownQAM(struct drxk_state *state);
+static int SetDVBTStandard(struct drxk_state *state,
+			   enum OperationMode oMode);
+static int SetQAMStandard(struct drxk_state *state,
+			  enum OperationMode oMode);
+static int SetQAM(struct drxk_state *state, u16 IntermediateFreqkHz,
+		  s32 tunerFreqOffset);
+static int SetDVBTStandard(struct drxk_state *state,
+			   enum OperationMode oMode);
+static int DVBTStart(struct drxk_state *state);
+static int SetDVBT(struct drxk_state *state, u16 IntermediateFreqkHz,
+		   s32 tunerFreqOffset);
+static int GetQAMLockStatus(struct drxk_state *state, u32 *pLockStatus);
+static int GetDVBTLockStatus(struct drxk_state *state, u32 *pLockStatus);
+static int SwitchAntennaToQAM(struct drxk_state *state);
+static int SwitchAntennaToDVBT(struct drxk_state *state);
+
+static bool IsDVBT(struct drxk_state *state)
+{
+	return state->m_OperationMode == OM_DVBT;
+}
+
+static bool IsQAM(struct drxk_state *state)
+{
+	return state->m_OperationMode == OM_QAM_ITU_A ||
+	    state->m_OperationMode == OM_QAM_ITU_B ||
+	    state->m_OperationMode == OM_QAM_ITU_C;
+}
+
+bool IsA1WithPatchCode(struct drxk_state *state)
+{
+	return state->m_DRXK_A1_PATCH_CODE;
+}
+
+bool IsA1WithRomCode(struct drxk_state *state)
+{
+	return state->m_DRXK_A1_ROM_CODE;
+}
+
+#define NOA1ROM 0
+
+#define DRXDAP_FASI_SHORT_FORMAT(addr) (((addr) & 0xFC30FF80) == 0)
+#define DRXDAP_FASI_LONG_FORMAT(addr)  (((addr) & 0xFC30FF80) != 0)
+
+#define DEFAULT_MER_83  165
+#define DEFAULT_MER_93  250
+
+#ifndef DRXK_MPEG_SERIAL_OUTPUT_PIN_DRIVE_STRENGTH
+#define DRXK_MPEG_SERIAL_OUTPUT_PIN_DRIVE_STRENGTH (0x02)
+#endif
+
+#ifndef DRXK_MPEG_PARALLEL_OUTPUT_PIN_DRIVE_STRENGTH
+#define DRXK_MPEG_PARALLEL_OUTPUT_PIN_DRIVE_STRENGTH (0x03)
+#endif
+
+#define DEFAULT_DRXK_MPEG_LOCK_TIMEOUT 700
+#define DEFAULT_DRXK_DEMOD_LOCK_TIMEOUT 500
+
+#ifndef DRXK_KI_RAGC_ATV
+#define DRXK_KI_RAGC_ATV   4
+#endif
+#ifndef DRXK_KI_IAGC_ATV
+#define DRXK_KI_IAGC_ATV   6
+#endif
+#ifndef DRXK_KI_DAGC_ATV
+#define DRXK_KI_DAGC_ATV   7
+#endif
+
+#ifndef DRXK_KI_RAGC_QAM
+#define DRXK_KI_RAGC_QAM   3
+#endif
+#ifndef DRXK_KI_IAGC_QAM
+#define DRXK_KI_IAGC_QAM   4
+#endif
+#ifndef DRXK_KI_DAGC_QAM
+#define DRXK_KI_DAGC_QAM   7
+#endif
+#ifndef DRXK_KI_RAGC_DVBT
+#define DRXK_KI_RAGC_DVBT  (IsA1WithPatchCode(state) ? 3 : 2)
+#endif
+#ifndef DRXK_KI_IAGC_DVBT
+#define DRXK_KI_IAGC_DVBT  (IsA1WithPatchCode(state) ? 4 : 2)
+#endif
+#ifndef DRXK_KI_DAGC_DVBT
+#define DRXK_KI_DAGC_DVBT  (IsA1WithPatchCode(state) ? 10 : 7)
+#endif
+
+#ifndef DRXK_AGC_DAC_OFFSET
+#define DRXK_AGC_DAC_OFFSET (0x800)
+#endif
+
+#ifndef DRXK_BANDWIDTH_8MHZ_IN_HZ
+#define DRXK_BANDWIDTH_8MHZ_IN_HZ  (0x8B8249L)
+#endif
+
+#ifndef DRXK_BANDWIDTH_7MHZ_IN_HZ
+#define DRXK_BANDWIDTH_7MHZ_IN_HZ  (0x7A1200L)
+#endif
+
+#ifndef DRXK_BANDWIDTH_6MHZ_IN_HZ
+#define DRXK_BANDWIDTH_6MHZ_IN_HZ  (0x68A1B6L)
+#endif
+
+#ifndef DRXK_QAM_SYMBOLRATE_MAX
+#define DRXK_QAM_SYMBOLRATE_MAX         (7233000)
+#endif
+
+#define DRXK_BL_ROM_OFFSET_TAPS_DVBT    56
+#define DRXK_BL_ROM_OFFSET_TAPS_ITU_A   64
+#define DRXK_BL_ROM_OFFSET_TAPS_ITU_C   0x5FE0
+#define DRXK_BL_ROM_OFFSET_TAPS_BG      24
+#define DRXK_BL_ROM_OFFSET_TAPS_DKILLP  32
+#define DRXK_BL_ROM_OFFSET_TAPS_NTSC    40
+#define DRXK_BL_ROM_OFFSET_TAPS_FM      48
+#define DRXK_BL_ROM_OFFSET_UCODE        0
+
+#define DRXK_BLC_TIMEOUT                100
+
+#define DRXK_BLCC_NR_ELEMENTS_TAPS      2
+#define DRXK_BLCC_NR_ELEMENTS_UCODE     6
+
+#define DRXK_BLDC_NR_ELEMENTS_TAPS      28
+
+#ifndef DRXK_OFDM_NE_NOTCH_WIDTH
+#define DRXK_OFDM_NE_NOTCH_WIDTH             (4)
+#endif
+
+#define DRXK_QAM_SL_SIG_POWER_QAM16       (40960)
+#define DRXK_QAM_SL_SIG_POWER_QAM32       (20480)
+#define DRXK_QAM_SL_SIG_POWER_QAM64       (43008)
+#define DRXK_QAM_SL_SIG_POWER_QAM128      (20992)
+#define DRXK_QAM_SL_SIG_POWER_QAM256      (43520)
+
+static unsigned int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "enable debug messages");
+
+#define dprintk(level, fmt, arg...) do {			\
+if (debug >= level)						\
+	printk(KERN_DEBUG "drxk: %s" fmt, __func__, ## arg);	\
+} while (0)
+
+
+static inline u32 MulDiv32(u32 a, u32 b, u32 c)
+{
+	u64 tmp64;
+
+	tmp64 = (u64) a * (u64) b;
+	do_div(tmp64, c);
+
+	return (u32) tmp64;
+}
+
+inline u32 Frac28a(u32 a, u32 c)
+{
+	int i = 0;
+	u32 Q1 = 0;
+	u32 R0 = 0;
+
+	R0 = (a % c) << 4;	/* 32-28 == 4 shifts possible at max */
+	Q1 = a / c;		/* integer part, only the 4 least significant bits
+				   will be visible in the result */
+
+	/* division using radix 16, 7 nibbles in the result */
+	for (i = 0; i < 7; i++) {
+		Q1 = (Q1 << 4) | (R0 / c);
+		R0 = (R0 % c) << 4;
+	}
+	/* rounding */
+	if ((R0 >> 3) >= c)
+		Q1++;
+
+	return Q1;
+}
+
+static u32 Log10Times100(u32 x)
+{
+	static const u8 scale = 15;
+	static const u8 indexWidth = 5;
+	u8 i = 0;
+	u32 y = 0;
+	u32 d = 0;
+	u32 k = 0;
+	u32 r = 0;
+	/*
+	   log2lut[n] = (1<<scale) * 200 * log2(1.0 + ((1.0/(1<<INDEXWIDTH)) * n))
+	   0 <= n < ((1<<INDEXWIDTH)+1)
+	 */
+
+	static const u32 log2lut[] = {
+		0,		/* 0.000000 */
+		290941,		/* 290941.300628 */
+		573196,		/* 573196.476418 */
+		847269,		/* 847269.179851 */
+		1113620,	/* 1113620.489452 */
+		1372674,	/* 1372673.576986 */
+		1624818,	/* 1624817.752104 */
+		1870412,	/* 1870411.981536 */
+		2109788,	/* 2109787.962654 */
+		2343253,	/* 2343252.817465 */
+		2571091,	/* 2571091.461923 */
+		2793569,	/* 2793568.696416 */
+		3010931,	/* 3010931.055901 */
+		3223408,	/* 3223408.452106 */
+		3431216,	/* 3431215.635215 */
+		3634553,	/* 3634553.498355 */
+		3833610,	/* 3833610.244726 */
+		4028562,	/* 4028562.434393 */
+		4219576,	/* 4219575.925308 */
+		4406807,	/* 4406806.721144 */
+		4590402,	/* 4590401.736809 */
+		4770499,	/* 4770499.491025 */
+		4947231,	/* 4947230.734179 */
+		5120719,	/* 5120719.018555 */
+		5291081,	/* 5291081.217197 */
+		5458428,	/* 5458427.996830 */
+		5622864,	/* 5622864.249668 */
+		5784489,	/* 5784489.488298 */
+		5943398,	/* 5943398.207380 */
+		6099680,	/* 6099680.215452 */
+		6253421,	/* 6253420.939751 */
+		6404702,	/* 6404701.706649 */
+		6553600,	/* 6553600.000000 */
+	};
+
+
+	if (x == 0)
+		return 0;
+
+	/* Scale x (normalize) */
+	/* computing y in log(x/y) = log(x) - log(y) */
+	if ((x & ((0xffffffff) << (scale + 1))) == 0) {
+		for (k = scale; k > 0; k--) {
+			if (x & (((u32) 1) << scale))
+				break;
+			x <<= 1;
+		}
+	} else {
+		for (k = scale; k < 31; k++) {
+			if ((x & (((u32) (-1)) << (scale + 1))) == 0)
+				break;
+			x >>= 1;
+		}
+	}
+	/*
+	   Now x has binary point between bit[scale] and bit[scale-1]
+	   and 1.0 <= x < 2.0 */
+
+	/* correction for divison: log(x) = log(x/y)+log(y) */
+	y = k * ((((u32) 1) << scale) * 200);
+
+	/* remove integer part */
+	x &= ((((u32) 1) << scale) - 1);
+	/* get index */
+	i = (u8) (x >> (scale - indexWidth));
+	/* compute delta (x - a) */
+	d = x & ((((u32) 1) << (scale - indexWidth)) - 1);
+	/* compute log, multiplication (d* (..)) must be within range ! */
+	y += log2lut[i] +
+	    ((d * (log2lut[i + 1] - log2lut[i])) >> (scale - indexWidth));
+	/* Conver to log10() */
+	y /= 108853;		/* (log2(10) << scale) */
+	r = (y >> 1);
+	/* rounding */
+	if (y & ((u32) 1))
+		r++;
+	return r;
+}
+
+/****************************************************************************/
+/* I2C **********************************************************************/
+/****************************************************************************/
+
+static int drxk_i2c_lock(struct drxk_state *state)
+{
+	i2c_lock_adapter(state->i2c);
+	state->drxk_i2c_exclusive_lock = true;
+
+	return 0;
+}
+
+static void drxk_i2c_unlock(struct drxk_state *state)
+{
+	if (!state->drxk_i2c_exclusive_lock)
+		return;
+
+	i2c_unlock_adapter(state->i2c);
+	state->drxk_i2c_exclusive_lock = false;
+}
+
+static int drxk_i2c_transfer(struct drxk_state *state, struct i2c_msg *msgs,
+			     unsigned len)
+{
+	if (state->drxk_i2c_exclusive_lock)
+		return __i2c_transfer(state->i2c, msgs, len);
+	else
+		return i2c_transfer(state->i2c, msgs, len);
+}
+
+static int i2c_read1(struct drxk_state *state, u8 adr, u8 *val)
+{
+	struct i2c_msg msgs[1] = { {.addr = adr, .flags = I2C_M_RD,
+				    .buf = val, .len = 1}
+	};
+
+	return drxk_i2c_transfer(state, msgs, 1);
+}
+
+static int i2c_write(struct drxk_state *state, u8 adr, u8 *data, int len)
+{
+	int status;
+	struct i2c_msg msg = {
+	    .addr = adr, .flags = 0, .buf = data, .len = len };
+
+	dprintk(3, ":");
+	if (debug > 2) {
+		int i;
+		for (i = 0; i < len; i++)
+			printk(KERN_CONT " %02x", data[i]);
+		printk(KERN_CONT "\n");
+	}
+	status = drxk_i2c_transfer(state, &msg, 1);
+	if (status >= 0 && status != 1)
+		status = -EIO;
+
+	if (status < 0)
+		printk(KERN_ERR "drxk: i2c write error at addr 0x%02x\n", adr);
+
+	return status;
+}
+
+static int i2c_read(struct drxk_state *state,
+		    u8 adr, u8 *msg, int len, u8 *answ, int alen)
+{
+	int status;
+	struct i2c_msg msgs[2] = {
+		{.addr = adr, .flags = 0,
+				    .buf = msg, .len = len},
+		{.addr = adr, .flags = I2C_M_RD,
+		 .buf = answ, .len = alen}
+	};
+
+	status = drxk_i2c_transfer(state, msgs, 2);
+	if (status != 2) {
+		if (debug > 2)
+			printk(KERN_CONT ": ERROR!\n");
+		if (status >= 0)
+			status = -EIO;
+
+		printk(KERN_ERR "drxk: i2c read error at addr 0x%02x\n", adr);
+		return status;
+	}
+	if (debug > 2) {
+		int i;
+		dprintk(2, ": read from");
+		for (i = 0; i < len; i++)
+			printk(KERN_CONT " %02x", msg[i]);
+		printk(KERN_CONT ", value = ");
+		for (i = 0; i < alen; i++)
+			printk(KERN_CONT " %02x", answ[i]);
+		printk(KERN_CONT "\n");
+	}
+	return 0;
+}
+
+static int read16_flags(struct drxk_state *state, u32 reg, u16 *data, u8 flags)
+{
+	int status;
+	u8 adr = state->demod_address, mm1[4], mm2[2], len;
+
+	if (state->single_master)
+		flags |= 0xC0;
+
+	if (DRXDAP_FASI_LONG_FORMAT(reg) || (flags != 0)) {
+		mm1[0] = (((reg << 1) & 0xFF) | 0x01);
+		mm1[1] = ((reg >> 16) & 0xFF);
+		mm1[2] = ((reg >> 24) & 0xFF) | flags;
+		mm1[3] = ((reg >> 7) & 0xFF);
+		len = 4;
+	} else {
+		mm1[0] = ((reg << 1) & 0xFF);
+		mm1[1] = (((reg >> 16) & 0x0F) | ((reg >> 18) & 0xF0));
+		len = 2;
+	}
+	dprintk(2, "(0x%08x, 0x%02x)\n", reg, flags);
+	status = i2c_read(state, adr, mm1, len, mm2, 2);
+	if (status < 0)
+		return status;
+	if (data)
+		*data = mm2[0] | (mm2[1] << 8);
+
+	return 0;
+}
+
+static int read16(struct drxk_state *state, u32 reg, u16 *data)
+{
+	return read16_flags(state, reg, data, 0);
+}
+
+static int read32_flags(struct drxk_state *state, u32 reg, u32 *data, u8 flags)
+{
+	int status;
+	u8 adr = state->demod_address, mm1[4], mm2[4], len;
+
+	if (state->single_master)
+		flags |= 0xC0;
+
+	if (DRXDAP_FASI_LONG_FORMAT(reg) || (flags != 0)) {
+		mm1[0] = (((reg << 1) & 0xFF) | 0x01);
+		mm1[1] = ((reg >> 16) & 0xFF);
+		mm1[2] = ((reg >> 24) & 0xFF) | flags;
+		mm1[3] = ((reg >> 7) & 0xFF);
+		len = 4;
+	} else {
+		mm1[0] = ((reg << 1) & 0xFF);
+		mm1[1] = (((reg >> 16) & 0x0F) | ((reg >> 18) & 0xF0));
+		len = 2;
+	}
+	dprintk(2, "(0x%08x, 0x%02x)\n", reg, flags);
+	status = i2c_read(state, adr, mm1, len, mm2, 4);
+	if (status < 0)
+		return status;
+	if (data)
+		*data = mm2[0] | (mm2[1] << 8) |
+		    (mm2[2] << 16) | (mm2[3] << 24);
+
+	return 0;
+}
+
+static int read32(struct drxk_state *state, u32 reg, u32 *data)
+{
+	return read32_flags(state, reg, data, 0);
+}
+
+static int write16_flags(struct drxk_state *state, u32 reg, u16 data, u8 flags)
+{
+	u8 adr = state->demod_address, mm[6], len;
+
+	if (state->single_master)
+		flags |= 0xC0;
+	if (DRXDAP_FASI_LONG_FORMAT(reg) || (flags != 0)) {
+		mm[0] = (((reg << 1) & 0xFF) | 0x01);
+		mm[1] = ((reg >> 16) & 0xFF);
+		mm[2] = ((reg >> 24) & 0xFF) | flags;
+		mm[3] = ((reg >> 7) & 0xFF);
+		len = 4;
+	} else {
+		mm[0] = ((reg << 1) & 0xFF);
+		mm[1] = (((reg >> 16) & 0x0F) | ((reg >> 18) & 0xF0));
+		len = 2;
+	}
+	mm[len] = data & 0xff;
+	mm[len + 1] = (data >> 8) & 0xff;
+
+	dprintk(2, "(0x%08x, 0x%04x, 0x%02x)\n", reg, data, flags);
+	return i2c_write(state, adr, mm, len + 2);
+}
+
+static int write16(struct drxk_state *state, u32 reg, u16 data)
+{
+	return write16_flags(state, reg, data, 0);
+}
+
+static int write32_flags(struct drxk_state *state, u32 reg, u32 data, u8 flags)
+{
+	u8 adr = state->demod_address, mm[8], len;
+
+	if (state->single_master)
+		flags |= 0xC0;
+	if (DRXDAP_FASI_LONG_FORMAT(reg) || (flags != 0)) {
+		mm[0] = (((reg << 1) & 0xFF) | 0x01);
+		mm[1] = ((reg >> 16) & 0xFF);
+		mm[2] = ((reg >> 24) & 0xFF) | flags;
+		mm[3] = ((reg >> 7) & 0xFF);
+		len = 4;
+	} else {
+		mm[0] = ((reg << 1) & 0xFF);
+		mm[1] = (((reg >> 16) & 0x0F) | ((reg >> 18) & 0xF0));
+		len = 2;
+	}
+	mm[len] = data & 0xff;
+	mm[len + 1] = (data >> 8) & 0xff;
+	mm[len + 2] = (data >> 16) & 0xff;
+	mm[len + 3] = (data >> 24) & 0xff;
+	dprintk(2, "(0x%08x, 0x%08x, 0x%02x)\n", reg, data, flags);
+
+	return i2c_write(state, adr, mm, len + 4);
+}
+
+static int write32(struct drxk_state *state, u32 reg, u32 data)
+{
+	return write32_flags(state, reg, data, 0);
+}
+
+static int write_block(struct drxk_state *state, u32 Address,
+		      const int BlockSize, const u8 pBlock[])
+{
+	int status = 0, BlkSize = BlockSize;
+	u8 Flags = 0;
+
+	if (state->single_master)
+		Flags |= 0xC0;
+
+	while (BlkSize > 0) {
+		int Chunk = BlkSize > state->m_ChunkSize ?
+		    state->m_ChunkSize : BlkSize;
+		u8 *AdrBuf = &state->Chunk[0];
+		u32 AdrLength = 0;
+
+		if (DRXDAP_FASI_LONG_FORMAT(Address) || (Flags != 0)) {
+			AdrBuf[0] = (((Address << 1) & 0xFF) | 0x01);
+			AdrBuf[1] = ((Address >> 16) & 0xFF);
+			AdrBuf[2] = ((Address >> 24) & 0xFF);
+			AdrBuf[3] = ((Address >> 7) & 0xFF);
+			AdrBuf[2] |= Flags;
+			AdrLength = 4;
+			if (Chunk == state->m_ChunkSize)
+				Chunk -= 2;
+		} else {
+			AdrBuf[0] = ((Address << 1) & 0xFF);
+			AdrBuf[1] = (((Address >> 16) & 0x0F) |
+				     ((Address >> 18) & 0xF0));
+			AdrLength = 2;
+		}
+		memcpy(&state->Chunk[AdrLength], pBlock, Chunk);
+		dprintk(2, "(0x%08x, 0x%02x)\n", Address, Flags);
+		if (debug > 1) {
+			int i;
+			if (pBlock)
+				for (i = 0; i < Chunk; i++)
+					printk(KERN_CONT " %02x", pBlock[i]);
+			printk(KERN_CONT "\n");
+		}
+		status = i2c_write(state, state->demod_address,
+				   &state->Chunk[0], Chunk + AdrLength);
+		if (status < 0) {
+			printk(KERN_ERR "drxk: %s: i2c write error at addr 0x%02x\n",
+			       __func__, Address);
+			break;
+		}
+		pBlock += Chunk;
+		Address += (Chunk >> 1);
+		BlkSize -= Chunk;
+	}
+	return status;
+}
+
+#ifndef DRXK_MAX_RETRIES_POWERUP
+#define DRXK_MAX_RETRIES_POWERUP 20
+#endif
+
+int PowerUpDevice(struct drxk_state *state)
+{
+	int status;
+	u8 data = 0;
+	u16 retryCount = 0;
+
+	dprintk(1, "\n");
+
+	status = i2c_read1(state, state->demod_address, &data);
+	if (status < 0) {
+		do {
+			data = 0;
+			status = i2c_write(state, state->demod_address,
+					   &data, 1);
+			msleep(10);
+			retryCount++;
+			if (status < 0)
+				continue;
+			status = i2c_read1(state, state->demod_address,
+					   &data);
+		} while (status < 0 &&
+			 (retryCount < DRXK_MAX_RETRIES_POWERUP));
+		if (status < 0 && retryCount >= DRXK_MAX_RETRIES_POWERUP)
+			goto error;
+	}
+
+	/* Make sure all clk domains are active */
+	status = write16(state, SIO_CC_PWD_MODE__A, SIO_CC_PWD_MODE_LEVEL_NONE);
+	if (status < 0)
+		goto error;
+	status = write16(state, SIO_CC_UPDATE__A, SIO_CC_UPDATE_KEY);
+	if (status < 0)
+		goto error;
+	/* Enable pll lock tests */
+	status = write16(state, SIO_CC_PLL_LOCK__A, 1);
+	if (status < 0)
+		goto error;
+
+	state->m_currentPowerMode = DRX_POWER_UP;
+
+error:
+	if (status < 0)
+		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+
+	return status;
+}
+
+
+static int init_state(struct drxk_state *state)
+{
+	/*
+	 * FIXME: most (all?) of the values bellow should be moved into
+	 * struct drxk_config, as they are probably board-specific
+	 */
+	u32 ulVSBIfAgcMode = DRXK_AGC_CTRL_AUTO;
+	u32 ulVSBIfAgcOutputLevel = 0;
+	u32 ulVSBIfAgcMinLevel = 0;
+	u32 ulVSBIfAgcMaxLevel = 0x7FFF;
+	u32 ulVSBIfAgcSpeed = 3;
+
+	u32 ulVSBRfAgcMode = DRXK_AGC_CTRL_AUTO;
+	u32 ulVSBRfAgcOutputLevel = 0;
+	u32 ulVSBRfAgcMinLevel = 0;
+	u32 ulVSBRfAgcMaxLevel = 0x7FFF;
+	u32 ulVSBRfAgcSpeed = 3;
+	u32 ulVSBRfAgcTop = 9500;
+	u32 ulVSBRfAgcCutOffCurrent = 4000;
+
+	u32 ulATVIfAgcMode = DRXK_AGC_CTRL_AUTO;
+	u32 ulATVIfAgcOutputLevel = 0;
+	u32 ulATVIfAgcMinLevel = 0;
+	u32 ulATVIfAgcMaxLevel = 0;
+	u32 ulATVIfAgcSpeed = 3;
+
+	u32 ulATVRfAgcMode = DRXK_AGC_CTRL_OFF;
+	u32 ulATVRfAgcOutputLevel = 0;
+	u32 ulATVRfAgcMinLevel = 0;
+	u32 ulATVRfAgcMaxLevel = 0;
+	u32 ulATVRfAgcTop = 9500;
+	u32 ulATVRfAgcCutOffCurrent = 4000;
+	u32 ulATVRfAgcSpeed = 3;
+
+	u32 ulQual83 = DEFAULT_MER_83;
+	u32 ulQual93 = DEFAULT_MER_93;
+
+	u32 ulMpegLockTimeOut = DEFAULT_DRXK_MPEG_LOCK_TIMEOUT;
+	u32 ulDemodLockTimeOut = DEFAULT_DRXK_DEMOD_LOCK_TIMEOUT;
+
+	/* io_pad_cfg register (8 bit reg.) MSB bit is 1 (default value) */
+	/* io_pad_cfg_mode output mode is drive always */
+	/* io_pad_cfg_drive is set to power 2 (23 mA) */
+	u32 ulGPIOCfg = 0x0113;
+	u32 ulInvertTSClock = 0;
+	u32 ulTSDataStrength = DRXK_MPEG_SERIAL_OUTPUT_PIN_DRIVE_STRENGTH;
+	u32 ulDVBTBitrate = 50000000;
+	u32 ulDVBCBitrate = DRXK_QAM_SYMBOLRATE_MAX * 8;
+
+	u32 ulInsertRSByte = 0;
+
+	u32 ulRfMirror = 1;
+	u32 ulPowerDown = 0;
+
+	dprintk(1, "\n");
+
+	state->m_hasLNA = false;
+	state->m_hasDVBT = false;
+	state->m_hasDVBC = false;
+	state->m_hasATV = false;
+	state->m_hasOOB = false;
+	state->m_hasAudio = false;
+
+	if (!state->m_ChunkSize)
+		state->m_ChunkSize = 124;
+
+	state->m_oscClockFreq = 0;
+	state->m_smartAntInverted = false;
+	state->m_bPDownOpenBridge = false;
+
+	/* real system clock frequency in kHz */
+	state->m_sysClockFreq = 151875;
+	/* Timing div, 250ns/Psys */
+	/* Timing div, = (delay (nano seconds) * sysclk (kHz))/ 1000 */
+	state->m_HICfgTimingDiv = ((state->m_sysClockFreq / 1000) *
+				   HI_I2C_DELAY) / 1000;
+	/* Clipping */
+	if (state->m_HICfgTimingDiv > SIO_HI_RA_RAM_PAR_2_CFG_DIV__M)
+		state->m_HICfgTimingDiv = SIO_HI_RA_RAM_PAR_2_CFG_DIV__M;
+	state->m_HICfgWakeUpKey = (state->demod_address << 1);
+	/* port/bridge/power down ctrl */
+	state->m_HICfgCtrl = SIO_HI_RA_RAM_PAR_5_CFG_SLV0_SLAVE;
+
+	state->m_bPowerDown = (ulPowerDown != 0);
+
+	state->m_DRXK_A1_PATCH_CODE = false;
+	state->m_DRXK_A1_ROM_CODE = false;
+	state->m_DRXK_A2_ROM_CODE = false;
+	state->m_DRXK_A3_ROM_CODE = false;
+	state->m_DRXK_A2_PATCH_CODE = false;
+	state->m_DRXK_A3_PATCH_CODE = false;
+
+	/* Init AGC and PGA parameters */
+	/* VSB IF */
+	state->m_vsbIfAgcCfg.ctrlMode = (ulVSBIfAgcMode);
+	state->m_vsbIfAgcCfg.outputLevel = (ulVSBIfAgcOutputLevel);
+	state->m_vsbIfAgcCfg.minOutputLevel = (ulVSBIfAgcMinLevel);
+	state->m_vsbIfAgcCfg.maxOutputLevel = (ulVSBIfAgcMaxLevel);
+	state->m_vsbIfAgcCfg.speed = (ulVSBIfAgcSpeed);
+	state->m_vsbPgaCfg = 140;
+
+	/* VSB RF */
+	state->m_vsbRfAgcCfg.ctrlMode = (ulVSBRfAgcMode);
+	state->m_vsbRfAgcCfg.outputLevel = (ulVSBRfAgcOutputLevel);
+	state->m_vsbRfAgcCfg.minOutputLevel = (ulVSBRfAgcMinLevel);
+	state->m_vsbRfAgcCfg.maxOutputLevel = (ulVSBRfAgcMaxLevel);
+	state->m_vsbRfAgcCfg.speed = (ulVSBRfAgcSpeed);
+	state->m_vsbRfAgcCfg.top = (ulVSBRfAgcTop);
+	state->m_vsbRfAgcCfg.cutOffCurrent = (ulVSBRfAgcCutOffCurrent);
+	state->m_vsbPreSawCfg.reference = 0x07;
+	state->m_vsbPreSawCfg.usePreSaw = true;
+
+	state->m_Quality83percent = DEFAULT_MER_83;
+	state->m_Quality93percent = DEFAULT_MER_93;
+	if (ulQual93 <= 500 && ulQual83 < ulQual93) {
+		state->m_Quality83percent = ulQual83;
+		state->m_Quality93percent = ulQual93;
+	}
+
+	/* ATV IF */
+	state->m_atvIfAgcCfg.ctrlMode = (ulATVIfAgcMode);
+	state->m_atvIfAgcCfg.outputLevel = (ulATVIfAgcOutputLevel);
+	state->m_atvIfAgcCfg.minOutputLevel = (ulATVIfAgcMinLevel);
+	state->m_atvIfAgcCfg.maxOutputLevel = (ulATVIfAgcMaxLevel);
+	state->m_atvIfAgcCfg.speed = (ulATVIfAgcSpeed);
+
+	/* ATV RF */
+	state->m_atvRfAgcCfg.ctrlMode = (ulATVRfAgcMode);
+	state->m_atvRfAgcCfg.outputLevel = (ulATVRfAgcOutputLevel);
+	state->m_atvRfAgcCfg.minOutputLevel = (ulATVRfAgcMinLevel);
+	state->m_atvRfAgcCfg.maxOutputLevel = (ulATVRfAgcMaxLevel);
+	state->m_atvRfAgcCfg.speed = (ulATVRfAgcSpeed);
+	state->m_atvRfAgcCfg.top = (ulATVRfAgcTop);
+	state->m_atvRfAgcCfg.cutOffCurrent = (ulATVRfAgcCutOffCurrent);
+	state->m_atvPreSawCfg.reference = 0x04;
+	state->m_atvPreSawCfg.usePreSaw = true;
+
+
+	/* DVBT RF */
+	state->m_dvbtRfAgcCfg.ctrlMode = DRXK_AGC_CTRL_OFF;
+	state->m_dvbtRfAgcCfg.outputLevel = 0;
+	state->m_dvbtRfAgcCfg.minOutputLevel = 0;
+	state->m_dvbtRfAgcCfg.maxOutputLevel = 0xFFFF;
+	state->m_dvbtRfAgcCfg.top = 0x2100;
+	state->m_dvbtRfAgcCfg.cutOffCurrent = 4000;
+	state->m_dvbtRfAgcCfg.speed = 1;
+
+
+	/* DVBT IF */
+	state->m_dvbtIfAgcCfg.ctrlMode = DRXK_AGC_CTRL_AUTO;
+	state->m_dvbtIfAgcCfg.outputLevel = 0;
+	state->m_dvbtIfAgcCfg.minOutputLevel = 0;
+	state->m_dvbtIfAgcCfg.maxOutputLevel = 9000;
+	state->m_dvbtIfAgcCfg.top = 13424;
+	state->m_dvbtIfAgcCfg.cutOffCurrent = 0;
+	state->m_dvbtIfAgcCfg.speed = 3;
+	state->m_dvbtIfAgcCfg.FastClipCtrlDelay = 30;
+	state->m_dvbtIfAgcCfg.IngainTgtMax = 30000;
+	/* state->m_dvbtPgaCfg = 140; */
+
+	state->m_dvbtPreSawCfg.reference = 4;
+	state->m_dvbtPreSawCfg.usePreSaw = false;
+
+	/* QAM RF */
+	state->m_qamRfAgcCfg.ctrlMode = DRXK_AGC_CTRL_OFF;
+	state->m_qamRfAgcCfg.outputLevel = 0;
+	state->m_qamRfAgcCfg.minOutputLevel = 6023;
+	state->m_qamRfAgcCfg.maxOutputLevel = 27000;
+	state->m_qamRfAgcCfg.top = 0x2380;
+	state->m_qamRfAgcCfg.cutOffCurrent = 4000;
+	state->m_qamRfAgcCfg.speed = 3;
+
+	/* QAM IF */
+	state->m_qamIfAgcCfg.ctrlMode = DRXK_AGC_CTRL_AUTO;
+	state->m_qamIfAgcCfg.outputLevel = 0;
+	state->m_qamIfAgcCfg.minOutputLevel = 0;
+	state->m_qamIfAgcCfg.maxOutputLevel = 9000;
+	state->m_qamIfAgcCfg.top = 0x0511;
+	state->m_qamIfAgcCfg.cutOffCurrent = 0;
+	state->m_qamIfAgcCfg.speed = 3;
+	state->m_qamIfAgcCfg.IngainTgtMax = 5119;
+	state->m_qamIfAgcCfg.FastClipCtrlDelay = 50;
+
+	state->m_qamPgaCfg = 140;
+	state->m_qamPreSawCfg.reference = 4;
+	state->m_qamPreSawCfg.usePreSaw = false;
+
+	state->m_OperationMode = OM_NONE;
+	state->m_DrxkState = DRXK_UNINITIALIZED;
+
+	/* MPEG output configuration */
+	state->m_enableMPEGOutput = true;	/* If TRUE; enable MPEG ouput */
+	state->m_insertRSByte = false;	/* If TRUE; insert RS byte */
+	state->m_invertDATA = false;	/* If TRUE; invert DATA signals */
+	state->m_invertERR = false;	/* If TRUE; invert ERR signal */
+	state->m_invertSTR = false;	/* If TRUE; invert STR signals */
+	state->m_invertVAL = false;	/* If TRUE; invert VAL signals */
+	state->m_invertCLK = (ulInvertTSClock != 0);	/* If TRUE; invert CLK signals */
+
+	/* If TRUE; static MPEG clockrate will be used;
+	   otherwise clockrate will adapt to the bitrate of the TS */
+
+	state->m_DVBTBitrate = ulDVBTBitrate;
+	state->m_DVBCBitrate = ulDVBCBitrate;
+
+	state->m_TSDataStrength = (ulTSDataStrength & 0x07);
+
+	/* Maximum bitrate in b/s in case static clockrate is selected */
+	state->m_mpegTsStaticBitrate = 19392658;
+	state->m_disableTEIhandling = false;
+
+	if (ulInsertRSByte)
+		state->m_insertRSByte = true;
+
+	state->m_MpegLockTimeOut = DEFAULT_DRXK_MPEG_LOCK_TIMEOUT;
+	if (ulMpegLockTimeOut < 10000)
+		state->m_MpegLockTimeOut = ulMpegLockTimeOut;
+	state->m_DemodLockTimeOut = DEFAULT_DRXK_DEMOD_LOCK_TIMEOUT;
+	if (ulDemodLockTimeOut < 10000)
+		state->m_DemodLockTimeOut = ulDemodLockTimeOut;
+
+	/* QAM defaults */
+	state->m_Constellation = DRX_CONSTELLATION_AUTO;
+	state->m_qamInterleaveMode = DRXK_QAM_I12_J17;
+	state->m_fecRsPlen = 204 * 8;	/* fecRsPlen  annex A */
+	state->m_fecRsPrescale = 1;
+
+	state->m_sqiSpeed = DRXK_DVBT_SQI_SPEED_MEDIUM;
+	state->m_agcFastClipCtrlDelay = 0;
+
+	state->m_GPIOCfg = (ulGPIOCfg);
+
+	state->m_bPowerDown = false;
+	state->m_currentPowerMode = DRX_POWER_DOWN;
+
+	state->m_rfmirror = (ulRfMirror == 0);
+	state->m_IfAgcPol = false;
+	return 0;
+}
+
+static int DRXX_Open(struct drxk_state *state)
+{
+	int status = 0;
+	u32 jtag = 0;
+	u16 bid = 0;
+	u16 key = 0;
+
+	dprintk(1, "\n");
+	/* stop lock indicator process */
+	status = write16(state, SCU_RAM_GPIO__A, SCU_RAM_GPIO_HW_LOCK_IND_DISABLE);
+	if (status < 0)
+		goto error;
+	/* Check device id */
+	status = read16(state, SIO_TOP_COMM_KEY__A, &key);
+	if (status < 0)
+		goto error;
+	status = write16(state, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY);
+	if (status < 0)
+		goto error;
+	status = read32(state, SIO_TOP_JTAGID_LO__A, &jtag);
+	if (status < 0)
+		goto error;
+	status = read16(state, SIO_PDR_UIO_IN_HI__A, &bid);
+	if (status < 0)
+		goto error;
+	status = write16(state, SIO_TOP_COMM_KEY__A, key);
+error:
+	if (status < 0)
+		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+	return status;
+}
+
+static int GetDeviceCapabilities(struct drxk_state *state)
+{
+	u16 sioPdrOhwCfg = 0;
+	u32 sioTopJtagidLo = 0;
+	int status;
+	const char *spin = "";
+
+	dprintk(1, "\n");
+
+	/* driver 0.9.0 */
+	/* stop lock indicator process */
+	status = write16(state, SCU_RAM_GPIO__A, SCU_RAM_GPIO_HW_LOCK_IND_DISABLE);
+	if (status < 0)
+		goto error;
+	status = write16(state, SIO_TOP_COMM_KEY__A, 0xFABA);
+	if (status < 0)
+		goto error;
+	status = read16(state, SIO_PDR_OHW_CFG__A, &sioPdrOhwCfg);
+	if (status < 0)
+		goto error;
+	status = write16(state, SIO_TOP_COMM_KEY__A, 0x0000);
+	if (status < 0)
+		goto error;
+
+	switch ((sioPdrOhwCfg & SIO_PDR_OHW_CFG_FREF_SEL__M)) {
+	case 0:
+		/* ignore (bypass ?) */
+		break;
+	case 1:
+		/* 27 MHz */
+		state->m_oscClockFreq = 27000;
+		break;
+	case 2:
+		/* 20.25 MHz */
+		state->m_oscClockFreq = 20250;
+		break;
+	case 3:
+		/* 4 MHz */
+		state->m_oscClockFreq = 20250;
+		break;
+	default:
+		printk(KERN_ERR "drxk: Clock Frequency is unkonwn\n");
+		return -EINVAL;
+	}
+	/*
+		Determine device capabilities
+		Based on pinning v14
+		*/
+	status = read32(state, SIO_TOP_JTAGID_LO__A, &sioTopJtagidLo);
+	if (status < 0)
+		goto error;
+
+	printk(KERN_INFO "drxk: status = 0x%08x\n", sioTopJtagidLo);
+
+	/* driver 0.9.0 */
+	switch ((sioTopJtagidLo >> 29) & 0xF) {
+	case 0:
+		state->m_deviceSpin = DRXK_SPIN_A1;
+		spin = "A1";
+		break;
+	case 2:
+		state->m_deviceSpin = DRXK_SPIN_A2;
+		spin = "A2";
+		break;
+	case 3:
+		state->m_deviceSpin = DRXK_SPIN_A3;
+		spin = "A3";
+		break;
+	default:
+		state->m_deviceSpin = DRXK_SPIN_UNKNOWN;
+		status = -EINVAL;
+		printk(KERN_ERR "drxk: Spin %d unknown\n",
+		       (sioTopJtagidLo >> 29) & 0xF);
+		goto error2;
+	}
+	switch ((sioTopJtagidLo >> 12) & 0xFF) {
+	case 0x13:
+		/* typeId = DRX3913K_TYPE_ID */
+		state->m_hasLNA = false;
+		state->m_hasOOB = false;
+		state->m_hasATV = false;
+		state->m_hasAudio = false;
+		state->m_hasDVBT = true;
+		state->m_hasDVBC = true;
+		state->m_hasSAWSW = true;
+		state->m_hasGPIO2 = false;
+		state->m_hasGPIO1 = false;
+		state->m_hasIRQN = false;
+		break;
+	case 0x15:
+		/* typeId = DRX3915K_TYPE_ID */
+		state->m_hasLNA = false;
+		state->m_hasOOB = false;
+		state->m_hasATV = true;
+		state->m_hasAudio = false;
+		state->m_hasDVBT = true;
+		state->m_hasDVBC = false;
+		state->m_hasSAWSW = true;
+		state->m_hasGPIO2 = true;
+		state->m_hasGPIO1 = true;
+		state->m_hasIRQN = false;
+		break;
+	case 0x16:
+		/* typeId = DRX3916K_TYPE_ID */
+		state->m_hasLNA = false;
+		state->m_hasOOB = false;
+		state->m_hasATV = true;
+		state->m_hasAudio = false;
+		state->m_hasDVBT = true;
+		state->m_hasDVBC = false;
+		state->m_hasSAWSW = true;
+		state->m_hasGPIO2 = true;
+		state->m_hasGPIO1 = true;
+		state->m_hasIRQN = false;
+		break;
+	case 0x18:
+		/* typeId = DRX3918K_TYPE_ID */
+		state->m_hasLNA = false;
+		state->m_hasOOB = false;
+		state->m_hasATV = true;
+		state->m_hasAudio = true;
+		state->m_hasDVBT = true;
+		state->m_hasDVBC = false;
+		state->m_hasSAWSW = true;
+		state->m_hasGPIO2 = true;
+		state->m_hasGPIO1 = true;
+		state->m_hasIRQN = false;
+		break;
+	case 0x21:
+		/* typeId = DRX3921K_TYPE_ID */
+		state->m_hasLNA = false;
+		state->m_hasOOB = false;
+		state->m_hasATV = true;
+		state->m_hasAudio = true;
+		state->m_hasDVBT = true;
+		state->m_hasDVBC = true;
+		state->m_hasSAWSW = true;
+		state->m_hasGPIO2 = true;
+		state->m_hasGPIO1 = true;
+		state->m_hasIRQN = false;
+		break;
+	case 0x23:
+		/* typeId = DRX3923K_TYPE_ID */
+		state->m_hasLNA = false;
+		state->m_hasOOB = false;
+		state->m_hasATV = true;
+		state->m_hasAudio = true;
+		state->m_hasDVBT = true;
+		state->m_hasDVBC = true;
+		state->m_hasSAWSW = true;
+		state->m_hasGPIO2 = true;
+		state->m_hasGPIO1 = true;
+		state->m_hasIRQN = false;
+		break;
+	case 0x25:
+		/* typeId = DRX3925K_TYPE_ID */
+		state->m_hasLNA = false;
+		state->m_hasOOB = false;
+		state->m_hasATV = true;
+		state->m_hasAudio = true;
+		state->m_hasDVBT = true;
+		state->m_hasDVBC = true;
+		state->m_hasSAWSW = true;
+		state->m_hasGPIO2 = true;
+		state->m_hasGPIO1 = true;
+		state->m_hasIRQN = false;
+		break;
+	case 0x26:
+		/* typeId = DRX3926K_TYPE_ID */
+		state->m_hasLNA = false;
+		state->m_hasOOB = false;
+		state->m_hasATV = true;
+		state->m_hasAudio = false;
+		state->m_hasDVBT = true;
+		state->m_hasDVBC = true;
+		state->m_hasSAWSW = true;
+		state->m_hasGPIO2 = true;
+		state->m_hasGPIO1 = true;
+		state->m_hasIRQN = false;
+		break;
+	default:
+		printk(KERN_ERR "drxk: DeviceID 0x%02x not supported\n",
+			((sioTopJtagidLo >> 12) & 0xFF));
+		status = -EINVAL;
+		goto error2;
+	}
+
+	printk(KERN_INFO
+	       "drxk: detected a drx-39%02xk, spin %s, xtal %d.%03d MHz\n",
+	       ((sioTopJtagidLo >> 12) & 0xFF), spin,
+	       state->m_oscClockFreq / 1000,
+	       state->m_oscClockFreq % 1000);
+
+error:
+	if (status < 0)
+		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+
+error2:
+	return status;
+}
+
+static int HI_Command(struct drxk_state *state, u16 cmd, u16 *pResult)
+{
+	int status;
+	bool powerdown_cmd;
+
+	dprintk(1, "\n");
+
+	/* Write command */
+	status = write16(state, SIO_HI_RA_RAM_CMD__A, cmd);
+	if (status < 0)
+		goto error;
+	if (cmd == SIO_HI_RA_RAM_CMD_RESET)
+		msleep(1);
+
+	powerdown_cmd =
+	    (bool) ((cmd == SIO_HI_RA_RAM_CMD_CONFIG) &&
+		    ((state->m_HICfgCtrl) &
+		     SIO_HI_RA_RAM_PAR_5_CFG_SLEEP__M) ==
+		    SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ);
+	if (powerdown_cmd == false) {
+		/* Wait until command rdy */
+		u32 retryCount = 0;
+		u16 waitCmd;
+
+		do {
+			msleep(1);
+			retryCount += 1;
+			status = read16(state, SIO_HI_RA_RAM_CMD__A,
+					  &waitCmd);
+		} while ((status < 0) && (retryCount < DRXK_MAX_RETRIES)
+			 && (waitCmd != 0));
+		if (status < 0)
+			goto error;
+		status = read16(state, SIO_HI_RA_RAM_RES__A, pResult);
+	}
+error:
+	if (status < 0)
+		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+
+	return status;
+}
+
+static int HI_CfgCommand(struct drxk_state *state)
+{
+	int status;
+
+	dprintk(1, "\n");
+
+	mutex_lock(&state->mutex);
+
+	status = write16(state, SIO_HI_RA_RAM_PAR_6__A, state->m_HICfgTimeout);
+	if (status < 0)
+		goto error;
+	status = write16(state, SIO_HI_RA_RAM_PAR_5__A, state->m_HICfgCtrl);
+	if (status < 0)
+		goto error;
+	status = write16(state, SIO_HI_RA_RAM_PAR_4__A, state->m_HICfgWakeUpKey);
+	if (status < 0)
+		goto error;
+	status = write16(state, SIO_HI_RA_RAM_PAR_3__A, state->m_HICfgBridgeDelay);
+	if (status < 0)
+		goto error;
+	status = write16(state, SIO_HI_RA_RAM_PAR_2__A, state->m_HICfgTimingDiv);
+	if (status < 0)
+		goto error;
+	status = write16(state, SIO_HI_RA_RAM_PAR_1__A, SIO_HI_RA_RAM_PAR_1_PAR1_SEC_KEY);
+	if (status < 0)
+		goto error;
+	status = HI_Command(state, SIO_HI_RA_RAM_CMD_CONFIG, 0);
+	if (status < 0)
+		goto error;
+
+	state->m_HICfgCtrl &= ~SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ;
+error:
+	mutex_unlock(&state->mutex);
+	if (status < 0)
+		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+	return status;
+}
+
+static int InitHI(struct drxk_state *state)
+{
+	dprintk(1, "\n");
+
+	state->m_HICfgWakeUpKey = (state->demod_address << 1);
+	state->m_HICfgTimeout = 0x96FF;
+	/* port/bridge/power down ctrl */
+	state->m_HICfgCtrl = SIO_HI_RA_RAM_PAR_5_CFG_SLV0_SLAVE;
+
+	return HI_CfgCommand(state);
+}
+
+static int MPEGTSConfigurePins(struct drxk_state *state, bool mpegEnable)
+{
+	int status = -1;
+	u16 sioPdrMclkCfg = 0;
+	u16 sioPdrMdxCfg = 0;
+	u16 err_cfg = 0;
+
+	dprintk(1, ": mpeg %s, %s mode\n",
+		mpegEnable ? "enable" : "disable",
+		state->m_enableParallel ? "parallel" : "serial");
+
+	/* stop lock indicator process */
+	status = write16(state, SCU_RAM_GPIO__A, SCU_RAM_GPIO_HW_LOCK_IND_DISABLE);
+	if (status < 0)
+		goto error;
+
+	/*  MPEG TS pad configuration */
+	status = write16(state, SIO_TOP_COMM_KEY__A, 0xFABA);
+	if (status < 0)
+		goto error;
+
+	if (mpegEnable == false) {
+		/*  Set MPEG TS pads to inputmode */
+		status = write16(state, SIO_PDR_MSTRT_CFG__A, 0x0000);
+		if (status < 0)
+			goto error;
+		status = write16(state, SIO_PDR_MERR_CFG__A, 0x0000);
+		if (status < 0)
+			goto error;
+		status = write16(state, SIO_PDR_MCLK_CFG__A, 0x0000);
+		if (status < 0)
+			goto error;
+		status = write16(state, SIO_PDR_MVAL_CFG__A, 0x0000);
+		if (status < 0)
+			goto error;
+		status = write16(state, SIO_PDR_MD0_CFG__A, 0x0000);
+		if (status < 0)
+			goto error;
+		status = write16(state, SIO_PDR_MD1_CFG__A, 0x0000);
+		if (status < 0)
+			goto error;
+		status = write16(state, SIO_PDR_MD2_CFG__A, 0x0000);
+		if (status < 0)
+			goto error;
+		status = write16(state, SIO_PDR_MD3_CFG__A, 0x0000);
+		if (status < 0)
+			goto error;
+		status = write16(state, SIO_PDR_MD4_CFG__A, 0x0000);
+		if (status < 0)
+			goto error;
+		status = write16(state, SIO_PDR_MD5_CFG__A, 0x0000);
+		if (status < 0)
+			goto error;
+		status = write16(state, SIO_PDR_MD6_CFG__A, 0x0000);
+		if (status < 0)
+			goto error;
+		status = write16(state, SIO_PDR_MD7_CFG__A, 0x0000);
+		if (status < 0)
+			goto error;
+	} else {
+		/* Enable MPEG output */
+		sioPdrMdxCfg =
+			((state->m_TSDataStrength <<
+			SIO_PDR_MD0_CFG_DRIVE__B) | 0x0003);
+		sioPdrMclkCfg = ((state->m_TSClockkStrength <<
+					SIO_PDR_MCLK_CFG_DRIVE__B) |
+					0x0003);
+
+		status = write16(state, SIO_PDR_MSTRT_CFG__A, sioPdrMdxCfg);
+		if (status < 0)
+			goto error;
+
+		if (state->enable_merr_cfg)
+			err_cfg = sioPdrMdxCfg;
+
+		status = write16(state, SIO_PDR_MERR_CFG__A, err_cfg);
+		if (status < 0)
+			goto error;
+		status = write16(state, SIO_PDR_MVAL_CFG__A, err_cfg);
+		if (status < 0)
+			goto error;
+
+		if (state->m_enableParallel == true) {
+			/* paralel -> enable MD1 to MD7 */
+			status = write16(state, SIO_PDR_MD1_CFG__A, sioPdrMdxCfg);
+			if (status < 0)
+				goto error;
+			status = write16(state, SIO_PDR_MD2_CFG__A, sioPdrMdxCfg);
+			if (status < 0)
+				goto error;
+			status = write16(state, SIO_PDR_MD3_CFG__A, sioPdrMdxCfg);
+			if (status < 0)
+				goto error;
+			status = write16(state, SIO_PDR_MD4_CFG__A, sioPdrMdxCfg);
+			if (status < 0)
+				goto error;
+			status = write16(state, SIO_PDR_MD5_CFG__A, sioPdrMdxCfg);
+			if (status < 0)
+				goto error;
+			status = write16(state, SIO_PDR_MD6_CFG__A, sioPdrMdxCfg);
+			if (status < 0)
+				goto error;
+			status = write16(state, SIO_PDR_MD7_CFG__A, sioPdrMdxCfg);
+			if (status < 0)
+				goto error;
+		} else {
+			sioPdrMdxCfg = ((state->m_TSDataStrength <<
+						SIO_PDR_MD0_CFG_DRIVE__B)
+					| 0x0003);
+			/* serial -> disable MD1 to MD7 */
+			status = write16(state, SIO_PDR_MD1_CFG__A, 0x0000);
+			if (status < 0)
+				goto error;
+			status = write16(state, SIO_PDR_MD2_CFG__A, 0x0000);
+			if (status < 0)
+				goto error;
+			status = write16(state, SIO_PDR_MD3_CFG__A, 0x0000);
+			if (status < 0)
+				goto error;
+			status = write16(state, SIO_PDR_MD4_CFG__A, 0x0000);
+			if (status < 0)
+				goto error;
+			status = write16(state, SIO_PDR_MD5_CFG__A, 0x0000);
+			if (status < 0)
+				goto error;
+			status = write16(state, SIO_PDR_MD6_CFG__A, 0x0000);
+			if (status < 0)
+				goto error;
+			status = write16(state, SIO_PDR_MD7_CFG__A, 0x0000);
+			if (status < 0)
+				goto error;
+		}
+		status = write16(state, SIO_PDR_MCLK_CFG__A, sioPdrMclkCfg);
+		if (status < 0)
+			goto error;
+		status = write16(state, SIO_PDR_MD0_CFG__A, sioPdrMdxCfg);
+		if (status < 0)
+			goto error;
+	}
+	/*  Enable MB output over MPEG pads and ctl input */
+	status = write16(state, SIO_PDR_MON_CFG__A, 0x0000);
+	if (status < 0)
+		goto error;
+	/*  Write nomagic word to enable pdr reg write */
+	status = write16(state, SIO_TOP_COMM_KEY__A, 0x0000);
+error:
+	if (status < 0)
+		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+	return status;
+}
+
+static int MPEGTSDisable(struct drxk_state *state)
+{
+	dprintk(1, "\n");
+
+	return MPEGTSConfigurePins(state, false);
+}
+
+static int BLChainCmd(struct drxk_state *state,
+		      u16 romOffset, u16 nrOfElements, u32 timeOut)
+{
+	u16 blStatus = 0;
+	int status;
+	unsigned long end;
+
+	dprintk(1, "\n");
+	mutex_lock(&state->mutex);
+	status = write16(state, SIO_BL_MODE__A, SIO_BL_MODE_CHAIN);
+	if (status < 0)
+		goto error;
+	status = write16(state, SIO_BL_CHAIN_ADDR__A, romOffset);
+	if (status < 0)
+		goto error;
+	status = write16(state, SIO_BL_CHAIN_LEN__A, nrOfElements);
+	if (status < 0)
+		goto error;
+	status = write16(state, SIO_BL_ENABLE__A, SIO_BL_ENABLE_ON);
+	if (status < 0)
+		goto error;
+
+	end = jiffies + msecs_to_jiffies(timeOut);
+	do {
+		msleep(1);
+		status = read16(state, SIO_BL_STATUS__A, &blStatus);
+		if (status < 0)
+			goto error;
+	} while ((blStatus == 0x1) &&
+			((time_is_after_jiffies(end))));
+
+	if (blStatus == 0x1) {
+		printk(KERN_ERR "drxk: SIO not ready\n");
+		status = -EINVAL;
+		goto error2;
+	}
+error:
+	if (status < 0)
+		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+error2:
+	mutex_unlock(&state->mutex);
+	return status;
+}
+
+
+static int DownloadMicrocode(struct drxk_state *state,
+			     const u8 pMCImage[], u32 Length)
+{
+	const u8 *pSrc = pMCImage;
+	u32 Address;
+	u16 nBlocks;
+	u16 BlockSize;
+	u32 offset = 0;
+	u32 i;
+	int status = 0;
+
+	dprintk(1, "\n");
+
+	/* down the drain (we don't care about MAGIC_WORD) */
+#if 0
+	/* For future reference */
+	Drain = (pSrc[0] << 8) | pSrc[1];
+#endif
+	pSrc += sizeof(u16);
+	offset += sizeof(u16);
+	nBlocks = (pSrc[0] << 8) | pSrc[1];
+	pSrc += sizeof(u16);
+	offset += sizeof(u16);
+
+	for (i = 0; i < nBlocks; i += 1) {
+		Address = (pSrc[0] << 24) | (pSrc[1] << 16) |
+		    (pSrc[2] << 8) | pSrc[3];
+		pSrc += sizeof(u32);
+		offset += sizeof(u32);
+
+		BlockSize = ((pSrc[0] << 8) | pSrc[1]) * sizeof(u16);
+		pSrc += sizeof(u16);
+		offset += sizeof(u16);
+
+#if 0
+		/* For future reference */
+		Flags = (pSrc[0] << 8) | pSrc[1];
+#endif
+		pSrc += sizeof(u16);
+		offset += sizeof(u16);
+
+#if 0
+		/* For future reference */
+		BlockCRC = (pSrc[0] << 8) | pSrc[1];
+#endif
+		pSrc += sizeof(u16);
+		offset += sizeof(u16);
+
+		if (offset + BlockSize > Length) {
+			printk(KERN_ERR "drxk: Firmware is corrupted.\n");
+			return -EINVAL;
+		}
+
+		status = write_block(state, Address, BlockSize, pSrc);
+		if (status < 0) {
+			printk(KERN_ERR "drxk: Error %d while loading firmware\n", status);
+			break;
+		}
+		pSrc += BlockSize;
+		offset += BlockSize;
+	}
+	return status;
+}
+
+static int DVBTEnableOFDMTokenRing(struct drxk_state *state, bool enable)
+{
+	int status;
+	u16 data = 0;
+	u16 desiredCtrl = SIO_OFDM_SH_OFDM_RING_ENABLE_ON;
+	u16 desiredStatus = SIO_OFDM_SH_OFDM_RING_STATUS_ENABLED;
+	unsigned long end;
+
+	dprintk(1, "\n");
+
+	if (enable == false) {
+		desiredCtrl = SIO_OFDM_SH_OFDM_RING_ENABLE_OFF;
+		desiredStatus = SIO_OFDM_SH_OFDM_RING_STATUS_DOWN;
+	}
+
+	status = read16(state, SIO_OFDM_SH_OFDM_RING_STATUS__A, &data);
+	if (status >= 0 && data == desiredStatus) {
+		/* tokenring already has correct status */
+		return status;
+	}
+	/* Disable/enable dvbt tokenring bridge   */
+	status = write16(state, SIO_OFDM_SH_OFDM_RING_ENABLE__A, desiredCtrl);
+
+	end = jiffies + msecs_to_jiffies(DRXK_OFDM_TR_SHUTDOWN_TIMEOUT);
+	do {
+		status = read16(state, SIO_OFDM_SH_OFDM_RING_STATUS__A, &data);
+		if ((status >= 0 && data == desiredStatus) || time_is_after_jiffies(end))
+			break;
+		msleep(1);
+	} while (1);
+	if (data != desiredStatus) {
+		printk(KERN_ERR "drxk: SIO not ready\n");
+		return -EINVAL;
+	}
+	return status;
+}
+
+static int MPEGTSStop(struct drxk_state *state)
+{
+	int status = 0;
+	u16 fecOcSncMode = 0;
+	u16 fecOcIprMode = 0;
+
+	dprintk(1, "\n");
+
+	/* Gracefull shutdown (byte boundaries) */
+	status = read16(state, FEC_OC_SNC_MODE__A, &fecOcSncMode);
+	if (status < 0)
+		goto error;
+	fecOcSncMode |= FEC_OC_SNC_MODE_SHUTDOWN__M;
+	status = write16(state, FEC_OC_SNC_MODE__A, fecOcSncMode);
+	if (status < 0)
+		goto error;
+
+	/* Suppress MCLK during absence of data */
+	status = read16(state, FEC_OC_IPR_MODE__A, &fecOcIprMode);
+	if (status < 0)
+		goto error;
+	fecOcIprMode |= FEC_OC_IPR_MODE_MCLK_DIS_DAT_ABS__M;
+	status = write16(state, FEC_OC_IPR_MODE__A, fecOcIprMode);
+
+error:
+	if (status < 0)
+		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+
+	return status;
+}
+
+static int scu_command(struct drxk_state *state,
+		       u16 cmd, u8 parameterLen,
+		       u16 *parameter, u8 resultLen, u16 *result)
+{
+#if (SCU_RAM_PARAM_0__A - SCU_RAM_PARAM_15__A) != 15
+#error DRXK register mapping no longer compatible with this routine!
+#endif
+	u16 curCmd = 0;
+	int status = -EINVAL;
+	unsigned long end;
+	u8 buffer[34];
+	int cnt = 0, ii;
+	const char *p;
+	char errname[30];
+
+	dprintk(1, "\n");
+
+	if ((cmd == 0) || ((parameterLen > 0) && (parameter == NULL)) ||
+	    ((resultLen > 0) && (result == NULL))) {
+		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+		return status;
+	}
+
+	mutex_lock(&state->mutex);
+
+	/* assume that the command register is ready
+		since it is checked afterwards */
+	for (ii = parameterLen - 1; ii >= 0; ii -= 1) {
+		buffer[cnt++] = (parameter[ii] & 0xFF);
+		buffer[cnt++] = ((parameter[ii] >> 8) & 0xFF);
+	}
+	buffer[cnt++] = (cmd & 0xFF);
+	buffer[cnt++] = ((cmd >> 8) & 0xFF);
+
+	write_block(state, SCU_RAM_PARAM_0__A -
+			(parameterLen - 1), cnt, buffer);
+	/* Wait until SCU has processed command */
+	end = jiffies + msecs_to_jiffies(DRXK_MAX_WAITTIME);
+	do {
+		msleep(1);
+		status = read16(state, SCU_RAM_COMMAND__A, &curCmd);
+		if (status < 0)
+			goto error;
+	} while (!(curCmd == DRX_SCU_READY) && (time_is_after_jiffies(end)));
+	if (curCmd != DRX_SCU_READY) {
+		printk(KERN_ERR "drxk: SCU not ready\n");
+		status = -EIO;
+		goto error2;
+	}
+	/* read results */
+	if ((resultLen > 0) && (result != NULL)) {
+		s16 err;
+		int ii;
+
+		for (ii = resultLen - 1; ii >= 0; ii -= 1) {
+			status = read16(state, SCU_RAM_PARAM_0__A - ii, &result[ii]);
+			if (status < 0)
+				goto error;
+		}
+
+		/* Check if an error was reported by SCU */
+		err = (s16)result[0];
+		if (err >= 0)
+			goto error;
+
+		/* check for the known error codes */
+		switch (err) {
+		case SCU_RESULT_UNKCMD:
+			p = "SCU_RESULT_UNKCMD";
+			break;
+		case SCU_RESULT_UNKSTD:
+			p = "SCU_RESULT_UNKSTD";
+			break;
+		case SCU_RESULT_SIZE:
+			p = "SCU_RESULT_SIZE";
+			break;
+		case SCU_RESULT_INVPAR:
+			p = "SCU_RESULT_INVPAR";
+			break;
+		default: /* Other negative values are errors */
+			sprintf(errname, "ERROR: %d\n", err);
+			p = errname;
+		}
+		printk(KERN_ERR "drxk: %s while sending cmd 0x%04x with params:", p, cmd);
+		print_hex_dump_bytes("drxk: ", DUMP_PREFIX_NONE, buffer, cnt);
+		status = -EINVAL;
+		goto error2;
+	}
+
+error:
+	if (status < 0)
+		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+error2:
+	mutex_unlock(&state->mutex);
+	return status;
+}
+
+static int SetIqmAf(struct drxk_state *state, bool active)
+{
+	u16 data = 0;
+	int status;
+
+	dprintk(1, "\n");
+
+	/* Configure IQM */
+	status = read16(state, IQM_AF_STDBY__A, &data);
+	if (status < 0)
+		goto error;
+
+	if (!active) {
+		data |= (IQM_AF_STDBY_STDBY_ADC_STANDBY
+				| IQM_AF_STDBY_STDBY_AMP_STANDBY
+				| IQM_AF_STDBY_STDBY_PD_STANDBY
+				| IQM_AF_STDBY_STDBY_TAGC_IF_STANDBY
+				| IQM_AF_STDBY_STDBY_TAGC_RF_STANDBY);
+	} else {
+		data &= ((~IQM_AF_STDBY_STDBY_ADC_STANDBY)
+				& (~IQM_AF_STDBY_STDBY_AMP_STANDBY)
+				& (~IQM_AF_STDBY_STDBY_PD_STANDBY)
+				& (~IQM_AF_STDBY_STDBY_TAGC_IF_STANDBY)
+				& (~IQM_AF_STDBY_STDBY_TAGC_RF_STANDBY)
+			);
+	}
+	status = write16(state, IQM_AF_STDBY__A, data);
+
+error:
+	if (status < 0)
+		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+	return status;
+}
+
+static int CtrlPowerMode(struct drxk_state *state, enum DRXPowerMode *mode)
+{
+	int status = 0;
+	u16 sioCcPwdMode = 0;
+
+	dprintk(1, "\n");
+
+	/* Check arguments */
+	if (mode == NULL)
+		return -EINVAL;
+
+	switch (*mode) {
+	case DRX_POWER_UP:
+		sioCcPwdMode = SIO_CC_PWD_MODE_LEVEL_NONE;
+		break;
+	case DRXK_POWER_DOWN_OFDM:
+		sioCcPwdMode = SIO_CC_PWD_MODE_LEVEL_OFDM;
+		break;
+	case DRXK_POWER_DOWN_CORE:
+		sioCcPwdMode = SIO_CC_PWD_MODE_LEVEL_CLOCK;
+		break;
+	case DRXK_POWER_DOWN_PLL:
+		sioCcPwdMode = SIO_CC_PWD_MODE_LEVEL_PLL;
+		break;
+	case DRX_POWER_DOWN:
+		sioCcPwdMode = SIO_CC_PWD_MODE_LEVEL_OSC;
+		break;
+	default:
+		/* Unknow sleep mode */
+		return -EINVAL;
+	}
+
+	/* If already in requested power mode, do nothing */
+	if (state->m_currentPowerMode == *mode)
+		return 0;
+
+	/* For next steps make sure to start from DRX_POWER_UP mode */
+	if (state->m_currentPowerMode != DRX_POWER_UP) {
+		status = PowerUpDevice(state);
+		if (status < 0)
+			goto error;
+		status = DVBTEnableOFDMTokenRing(state, true);
+		if (status < 0)
+			goto error;
+	}
+
+	if (*mode == DRX_POWER_UP) {
+		/* Restore analog & pin configuartion */
+	} else {
+		/* Power down to requested mode */
+		/* Backup some register settings */
+		/* Set pins with possible pull-ups connected
+		   to them in input mode */
+		/* Analog power down */
+		/* ADC power down */
+		/* Power down device */
+		/* stop all comm_exec */
+		/* Stop and power down previous standard */
+		switch (state->m_OperationMode) {
+		case OM_DVBT:
+			status = MPEGTSStop(state);
+			if (status < 0)
+				goto error;
+			status = PowerDownDVBT(state, false);
+			if (status < 0)
+				goto error;
+			break;
+		case OM_QAM_ITU_A:
+		case OM_QAM_ITU_C:
+			status = MPEGTSStop(state);
+			if (status < 0)
+				goto error;
+			status = PowerDownQAM(state);
+			if (status < 0)
+				goto error;
+			break;
+		default:
+			break;
+		}
+		status = DVBTEnableOFDMTokenRing(state, false);
+		if (status < 0)
+			goto error;
+		status = write16(state, SIO_CC_PWD_MODE__A, sioCcPwdMode);
+		if (status < 0)
+			goto error;
+		status = write16(state, SIO_CC_UPDATE__A, SIO_CC_UPDATE_KEY);
+		if (status < 0)
+			goto error;
+
+		if (*mode != DRXK_POWER_DOWN_OFDM) {
+			state->m_HICfgCtrl |=
+				SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ;
+			status = HI_CfgCommand(state);
+			if (status < 0)
+				goto error;
+		}
+	}
+	state->m_currentPowerMode = *mode;
+
+error:
+	if (status < 0)
+		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+
+	return status;
+}
+
+static int PowerDownDVBT(struct drxk_state *state, bool setPowerMode)
+{
+	enum DRXPowerMode powerMode = DRXK_POWER_DOWN_OFDM;
+	u16 cmdResult = 0;
+	u16 data = 0;
+	int status;
+
+	dprintk(1, "\n");
+
+	status = read16(state, SCU_COMM_EXEC__A, &data);
+	if (status < 0)
+		goto error;
+	if (data == SCU_COMM_EXEC_ACTIVE) {
+		/* Send OFDM stop command */
+		status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM | SCU_RAM_COMMAND_CMD_DEMOD_STOP, 0, NULL, 1, &cmdResult);
+		if (status < 0)
+			goto error;
+		/* Send OFDM reset command */
+		status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM | SCU_RAM_COMMAND_CMD_DEMOD_RESET, 0, NULL, 1, &cmdResult);
+		if (status < 0)
+			goto error;
+	}
+
+	/* Reset datapath for OFDM, processors first */
+	status = write16(state, OFDM_SC_COMM_EXEC__A, OFDM_SC_COMM_EXEC_STOP);
+	if (status < 0)
+		goto error;
+	status = write16(state, OFDM_LC_COMM_EXEC__A, OFDM_LC_COMM_EXEC_STOP);
+	if (status < 0)
+		goto error;
+	status = write16(state, IQM_COMM_EXEC__A, IQM_COMM_EXEC_B_STOP);
+	if (status < 0)
+		goto error;
+
+	/* powerdown AFE                   */
+	status = SetIqmAf(state, false);
+	if (status < 0)
+		goto error;
+
+	/* powerdown to OFDM mode          */
+	if (setPowerMode) {
+		status = CtrlPowerMode(state, &powerMode);
+		if (status < 0)
+			goto error;
+	}
+error:
+	if (status < 0)
+		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+	return status;
+}
+
+static int SetOperationMode(struct drxk_state *state,
+			    enum OperationMode oMode)
+{
+	int status = 0;
+
+	dprintk(1, "\n");
+	/*
+	   Stop and power down previous standard
+	   TODO investigate total power down instead of partial
+	   power down depending on "previous" standard.
+	 */
+
+	/* disable HW lock indicator */
+	status = write16(state, SCU_RAM_GPIO__A, SCU_RAM_GPIO_HW_LOCK_IND_DISABLE);
+	if (status < 0)
+		goto error;
+
+	/* Device is already at the required mode */
+	if (state->m_OperationMode == oMode)
+		return 0;
+
+	switch (state->m_OperationMode) {
+		/* OM_NONE was added for start up */
+	case OM_NONE:
+		break;
+	case OM_DVBT:
+		status = MPEGTSStop(state);
+		if (status < 0)
+			goto error;
+		status = PowerDownDVBT(state, true);
+		if (status < 0)
+			goto error;
+		state->m_OperationMode = OM_NONE;
+		break;
+	case OM_QAM_ITU_A:	/* fallthrough */
+	case OM_QAM_ITU_C:
+		status = MPEGTSStop(state);
+		if (status < 0)
+			goto error;
+		status = PowerDownQAM(state);
+		if (status < 0)
+			goto error;
+		state->m_OperationMode = OM_NONE;
+		break;
+	case OM_QAM_ITU_B:
+	default:
+		status = -EINVAL;
+		goto error;
+	}
+
+	/*
+		Power up new standard
+		*/
+	switch (oMode) {
+	case OM_DVBT:
+		dprintk(1, ": DVB-T\n");
+		state->m_OperationMode = oMode;
+		status = SetDVBTStandard(state, oMode);
+		if (status < 0)
+			goto error;
+		break;
+	case OM_QAM_ITU_A:	/* fallthrough */
+	case OM_QAM_ITU_C:
+		dprintk(1, ": DVB-C Annex %c\n",
+			(state->m_OperationMode == OM_QAM_ITU_A) ? 'A' : 'C');
+		state->m_OperationMode = oMode;
+		status = SetQAMStandard(state, oMode);
+		if (status < 0)
+			goto error;
+		break;
+	case OM_QAM_ITU_B:
+	default:
+		status = -EINVAL;
+	}
+error:
+	if (status < 0)
+		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+	return status;
+}
+
+static int Start(struct drxk_state *state, s32 offsetFreq,
+		 s32 IntermediateFrequency)
+{
+	int status = -EINVAL;
+
+	u16 IFreqkHz;
+	s32 OffsetkHz = offsetFreq / 1000;
+
+	dprintk(1, "\n");
+	if (state->m_DrxkState != DRXK_STOPPED &&
+		state->m_DrxkState != DRXK_DTV_STARTED)
+		goto error;
+
+	state->m_bMirrorFreqSpect = (state->props.inversion == INVERSION_ON);
+
+	if (IntermediateFrequency < 0) {
+		state->m_bMirrorFreqSpect = !state->m_bMirrorFreqSpect;
+		IntermediateFrequency = -IntermediateFrequency;
+	}
+
+	switch (state->m_OperationMode) {
+	case OM_QAM_ITU_A:
+	case OM_QAM_ITU_C:
+		IFreqkHz = (IntermediateFrequency / 1000);
+		status = SetQAM(state, IFreqkHz, OffsetkHz);
+		if (status < 0)
+			goto error;
+		state->m_DrxkState = DRXK_DTV_STARTED;
+		break;
+	case OM_DVBT:
+		IFreqkHz = (IntermediateFrequency / 1000);
+		status = MPEGTSStop(state);
+		if (status < 0)
+			goto error;
+		status = SetDVBT(state, IFreqkHz, OffsetkHz);
+		if (status < 0)
+			goto error;
+		status = DVBTStart(state);
+		if (status < 0)
+			goto error;
+		state->m_DrxkState = DRXK_DTV_STARTED;
+		break;
+	default:
+		break;
+	}
+error:
+	if (status < 0)
+		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+	return status;
+}
+
+static int ShutDown(struct drxk_state *state)
+{
+	dprintk(1, "\n");
+
+	MPEGTSStop(state);
+	return 0;
+}
+
+static int GetLockStatus(struct drxk_state *state, u32 *pLockStatus,
+			 u32 Time)
+{
+	int status = -EINVAL;
+
+	dprintk(1, "\n");
+
+	if (pLockStatus == NULL)
+		goto error;
+
+	*pLockStatus = NOT_LOCKED;
+
+	/* define the SCU command code */
+	switch (state->m_OperationMode) {
+	case OM_QAM_ITU_A:
+	case OM_QAM_ITU_B:
+	case OM_QAM_ITU_C:
+		status = GetQAMLockStatus(state, pLockStatus);
+		break;
+	case OM_DVBT:
+		status = GetDVBTLockStatus(state, pLockStatus);
+		break;
+	default:
+		break;
+	}
+error:
+	if (status < 0)
+		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+	return status;
+}
+
+static int MPEGTSStart(struct drxk_state *state)
+{
+	int status;
+
+	u16 fecOcSncMode = 0;
+
+	/* Allow OC to sync again */
+	status = read16(state, FEC_OC_SNC_MODE__A, &fecOcSncMode);
+	if (status < 0)
+		goto error;
+	fecOcSncMode &= ~FEC_OC_SNC_MODE_SHUTDOWN__M;
+	status = write16(state, FEC_OC_SNC_MODE__A, fecOcSncMode);
+	if (status < 0)
+		goto error;
+	status = write16(state, FEC_OC_SNC_UNLOCK__A, 1);
+error:
+	if (status < 0)
+		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+	return status;
+}
+
+static int MPEGTSDtoInit(struct drxk_state *state)
+{
+	int status;
+
+	dprintk(1, "\n");
+
+	/* Rate integration settings */
+	status = write16(state, FEC_OC_RCN_CTL_STEP_LO__A, 0x0000);
+	if (status < 0)
+		goto error;
+	status = write16(state, FEC_OC_RCN_CTL_STEP_HI__A, 0x000C);
+	if (status < 0)
+		goto error;
+	status = write16(state, FEC_OC_RCN_GAIN__A, 0x000A);
+	if (status < 0)
+		goto error;
+	status = write16(state, FEC_OC_AVR_PARM_A__A, 0x0008);
+	if (status < 0)
+		goto error;
+	status = write16(state, FEC_OC_AVR_PARM_B__A, 0x0006);
+	if (status < 0)
+		goto error;
+	status = write16(state, FEC_OC_TMD_HI_MARGIN__A, 0x0680);
+	if (status < 0)
+		goto error;
+	status = write16(state, FEC_OC_TMD_LO_MARGIN__A, 0x0080);
+	if (status < 0)
+		goto error;
+	status = write16(state, FEC_OC_TMD_COUNT__A, 0x03F4);
+	if (status < 0)
+		goto error;
+
+	/* Additional configuration */
+	status = write16(state, FEC_OC_OCR_INVERT__A, 0);
+	if (status < 0)
+		goto error;
+	status = write16(state, FEC_OC_SNC_LWM__A, 2);
+	if (status < 0)
+		goto error;
+	status = write16(state, FEC_OC_SNC_HWM__A, 12);
+error:
+	if (status < 0)
+		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+
+	return status;
+}
+
+static int MPEGTSDtoSetup(struct drxk_state *state,
+			  enum OperationMode oMode)
+{
+	int status;
+
+	u16 fecOcRegMode = 0;	/* FEC_OC_MODE       register value */
+	u16 fecOcRegIprMode = 0;	/* FEC_OC_IPR_MODE   register value */
+	u16 fecOcDtoMode = 0;	/* FEC_OC_IPR_INVERT register value */
+	u16 fecOcFctMode = 0;	/* FEC_OC_IPR_INVERT register value */
+	u16 fecOcDtoPeriod = 2;	/* FEC_OC_IPR_INVERT register value */
+	u16 fecOcDtoBurstLen = 188;	/* FEC_OC_IPR_INVERT register value */
+	u32 fecOcRcnCtlRate = 0;	/* FEC_OC_IPR_INVERT register value */
+	u16 fecOcTmdMode = 0;
+	u16 fecOcTmdIntUpdRate = 0;
+	u32 maxBitRate = 0;
+	bool staticCLK = false;
+
+	dprintk(1, "\n");
+
+	/* Check insertion of the Reed-Solomon parity bytes */
+	status = read16(state, FEC_OC_MODE__A, &fecOcRegMode);
+	if (status < 0)
+		goto error;
+	status = read16(state, FEC_OC_IPR_MODE__A, &fecOcRegIprMode);
+	if (status < 0)
+		goto error;
+	fecOcRegMode &= (~FEC_OC_MODE_PARITY__M);
+	fecOcRegIprMode &= (~FEC_OC_IPR_MODE_MVAL_DIS_PAR__M);
+	if (state->m_insertRSByte == true) {
+		/* enable parity symbol forward */
+		fecOcRegMode |= FEC_OC_MODE_PARITY__M;
+		/* MVAL disable during parity bytes */
+		fecOcRegIprMode |= FEC_OC_IPR_MODE_MVAL_DIS_PAR__M;
+		/* TS burst length to 204 */
+		fecOcDtoBurstLen = 204;
+	}
+
+	/* Check serial or parrallel output */
+	fecOcRegIprMode &= (~(FEC_OC_IPR_MODE_SERIAL__M));
+	if (state->m_enableParallel == false) {
+		/* MPEG data output is serial -> set ipr_mode[0] */
+		fecOcRegIprMode |= FEC_OC_IPR_MODE_SERIAL__M;
+	}
+
+	switch (oMode) {
+	case OM_DVBT:
+		maxBitRate = state->m_DVBTBitrate;
+		fecOcTmdMode = 3;
+		fecOcRcnCtlRate = 0xC00000;
+		staticCLK = state->m_DVBTStaticCLK;
+		break;
+	case OM_QAM_ITU_A:	/* fallthrough */
+	case OM_QAM_ITU_C:
+		fecOcTmdMode = 0x0004;
+		fecOcRcnCtlRate = 0xD2B4EE;	/* good for >63 Mb/s */
+		maxBitRate = state->m_DVBCBitrate;
+		staticCLK = state->m_DVBCStaticCLK;
+		break;
+	default:
+		status = -EINVAL;
+	}		/* switch (standard) */
+	if (status < 0)
+		goto error;
+
+	/* Configure DTO's */
+	if (staticCLK) {
+		u32 bitRate = 0;
+
+		/* Rational DTO for MCLK source (static MCLK rate),
+			Dynamic DTO for optimal grouping
+			(avoid intra-packet gaps),
+			DTO offset enable to sync TS burst with MSTRT */
+		fecOcDtoMode = (FEC_OC_DTO_MODE_DYNAMIC__M |
+				FEC_OC_DTO_MODE_OFFSET_ENABLE__M);
+		fecOcFctMode = (FEC_OC_FCT_MODE_RAT_ENA__M |
+				FEC_OC_FCT_MODE_VIRT_ENA__M);
+
+		/* Check user defined bitrate */
+		bitRate = maxBitRate;
+		if (bitRate > 75900000UL) {	/* max is 75.9 Mb/s */
+			bitRate = 75900000UL;
+		}
+		/* Rational DTO period:
+			dto_period = (Fsys / bitrate) - 2
+
+			Result should be floored,
+			to make sure >= requested bitrate
+			*/
+		fecOcDtoPeriod = (u16) (((state->m_sysClockFreq)
+						* 1000) / bitRate);
+		if (fecOcDtoPeriod <= 2)
+			fecOcDtoPeriod = 0;
+		else
+			fecOcDtoPeriod -= 2;
+		fecOcTmdIntUpdRate = 8;
+	} else {
+		/* (commonAttr->staticCLK == false) => dynamic mode */
+		fecOcDtoMode = FEC_OC_DTO_MODE_DYNAMIC__M;
+		fecOcFctMode = FEC_OC_FCT_MODE__PRE;
+		fecOcTmdIntUpdRate = 5;
+	}
+
+	/* Write appropriate registers with requested configuration */
+	status = write16(state, FEC_OC_DTO_BURST_LEN__A, fecOcDtoBurstLen);
+	if (status < 0)
+		goto error;
+	status = write16(state, FEC_OC_DTO_PERIOD__A, fecOcDtoPeriod);
+	if (status < 0)
+		goto error;
+	status = write16(state, FEC_OC_DTO_MODE__A, fecOcDtoMode);
+	if (status < 0)
+		goto error;
+	status = write16(state, FEC_OC_FCT_MODE__A, fecOcFctMode);
+	if (status < 0)
+		goto error;
+	status = write16(state, FEC_OC_MODE__A, fecOcRegMode);
+	if (status < 0)
+		goto error;
+	status = write16(state, FEC_OC_IPR_MODE__A, fecOcRegIprMode);
+	if (status < 0)
+		goto error;
+
+	/* Rate integration settings */
+	status = write32(state, FEC_OC_RCN_CTL_RATE_LO__A, fecOcRcnCtlRate);
+	if (status < 0)
+		goto error;
+	status = write16(state, FEC_OC_TMD_INT_UPD_RATE__A, fecOcTmdIntUpdRate);
+	if (status < 0)
+		goto error;
+	status = write16(state, FEC_OC_TMD_MODE__A, fecOcTmdMode);
+error:
+	if (status < 0)
+		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+	return status;
+}
+
+static int MPEGTSConfigurePolarity(struct drxk_state *state)
+{
+	u16 fecOcRegIprInvert = 0;
+
+	/* Data mask for the output data byte */
+	u16 InvertDataMask =
+	    FEC_OC_IPR_INVERT_MD7__M | FEC_OC_IPR_INVERT_MD6__M |
+	    FEC_OC_IPR_INVERT_MD5__M | FEC_OC_IPR_INVERT_MD4__M |
+	    FEC_OC_IPR_INVERT_MD3__M | FEC_OC_IPR_INVERT_MD2__M |
+	    FEC_OC_IPR_INVERT_MD1__M | FEC_OC_IPR_INVERT_MD0__M;
+
+	dprintk(1, "\n");
+
+	/* Control selective inversion of output bits */
+	fecOcRegIprInvert &= (~(InvertDataMask));
+	if (state->m_invertDATA == true)
+		fecOcRegIprInvert |= InvertDataMask;
+	fecOcRegIprInvert &= (~(FEC_OC_IPR_INVERT_MERR__M));
+	if (state->m_invertERR == true)
+		fecOcRegIprInvert |= FEC_OC_IPR_INVERT_MERR__M;
+	fecOcRegIprInvert &= (~(FEC_OC_IPR_INVERT_MSTRT__M));
+	if (state->m_invertSTR == true)
+		fecOcRegIprInvert |= FEC_OC_IPR_INVERT_MSTRT__M;
+	fecOcRegIprInvert &= (~(FEC_OC_IPR_INVERT_MVAL__M));
+	if (state->m_invertVAL == true)
+		fecOcRegIprInvert |= FEC_OC_IPR_INVERT_MVAL__M;
+	fecOcRegIprInvert &= (~(FEC_OC_IPR_INVERT_MCLK__M));
+	if (state->m_invertCLK == true)
+		fecOcRegIprInvert |= FEC_OC_IPR_INVERT_MCLK__M;
+
+	return write16(state, FEC_OC_IPR_INVERT__A, fecOcRegIprInvert);
+}
+
+#define   SCU_RAM_AGC_KI_INV_RF_POL__M 0x4000
+
+static int SetAgcRf(struct drxk_state *state,
+		    struct SCfgAgc *pAgcCfg, bool isDTV)
+{
+	int status = -EINVAL;
+	u16 data = 0;
+	struct SCfgAgc *pIfAgcSettings;
+
+	dprintk(1, "\n");
+
+	if (pAgcCfg == NULL)
+		goto error;
+
+	switch (pAgcCfg->ctrlMode) {
+	case DRXK_AGC_CTRL_AUTO:
+		/* Enable RF AGC DAC */
+		status = read16(state, IQM_AF_STDBY__A, &data);
+		if (status < 0)
+			goto error;
+		data &= ~IQM_AF_STDBY_STDBY_TAGC_RF_STANDBY;
+		status = write16(state, IQM_AF_STDBY__A, data);
+		if (status < 0)
+			goto error;
+		status = read16(state, SCU_RAM_AGC_CONFIG__A, &data);
+		if (status < 0)
+			goto error;
+
+		/* Enable SCU RF AGC loop */
+		data &= ~SCU_RAM_AGC_CONFIG_DISABLE_RF_AGC__M;
+
+		/* Polarity */
+		if (state->m_RfAgcPol)
+			data |= SCU_RAM_AGC_CONFIG_INV_RF_POL__M;
+		else
+			data &= ~SCU_RAM_AGC_CONFIG_INV_RF_POL__M;
+		status = write16(state, SCU_RAM_AGC_CONFIG__A, data);
+		if (status < 0)
+			goto error;
+
+		/* Set speed (using complementary reduction value) */
+		status = read16(state, SCU_RAM_AGC_KI_RED__A, &data);
+		if (status < 0)
+			goto error;
+
+		data &= ~SCU_RAM_AGC_KI_RED_RAGC_RED__M;
+		data |= (~(pAgcCfg->speed <<
+				SCU_RAM_AGC_KI_RED_RAGC_RED__B)
+				& SCU_RAM_AGC_KI_RED_RAGC_RED__M);
+
+		status = write16(state, SCU_RAM_AGC_KI_RED__A, data);
+		if (status < 0)
+			goto error;
+
+		if (IsDVBT(state))
+			pIfAgcSettings = &state->m_dvbtIfAgcCfg;
+		else if (IsQAM(state))
+			pIfAgcSettings = &state->m_qamIfAgcCfg;
+		else
+			pIfAgcSettings = &state->m_atvIfAgcCfg;
+		if (pIfAgcSettings == NULL) {
+			status = -EINVAL;
+			goto error;
+		}
+
+		/* Set TOP, only if IF-AGC is in AUTO mode */
+		if (pIfAgcSettings->ctrlMode == DRXK_AGC_CTRL_AUTO)
+			status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, pAgcCfg->top);
+			if (status < 0)
+				goto error;
+
+		/* Cut-Off current */
+		status = write16(state, SCU_RAM_AGC_RF_IACCU_HI_CO__A, pAgcCfg->cutOffCurrent);
+		if (status < 0)
+			goto error;
+
+		/* Max. output level */
+		status = write16(state, SCU_RAM_AGC_RF_MAX__A, pAgcCfg->maxOutputLevel);
+		if (status < 0)
+			goto error;
+
+		break;
+
+	case DRXK_AGC_CTRL_USER:
+		/* Enable RF AGC DAC */
+		status = read16(state, IQM_AF_STDBY__A, &data);
+		if (status < 0)
+			goto error;
+		data &= ~IQM_AF_STDBY_STDBY_TAGC_RF_STANDBY;
+		status = write16(state, IQM_AF_STDBY__A, data);
+		if (status < 0)
+			goto error;
+
+		/* Disable SCU RF AGC loop */
+		status = read16(state, SCU_RAM_AGC_CONFIG__A, &data);
+		if (status < 0)
+			goto error;
+		data |= SCU_RAM_AGC_CONFIG_DISABLE_RF_AGC__M;
+		if (state->m_RfAgcPol)
+			data |= SCU_RAM_AGC_CONFIG_INV_RF_POL__M;
+		else
+			data &= ~SCU_RAM_AGC_CONFIG_INV_RF_POL__M;
+		status = write16(state, SCU_RAM_AGC_CONFIG__A, data);
+		if (status < 0)
+			goto error;
+
+		/* SCU c.o.c. to 0, enabling full control range */
+		status = write16(state, SCU_RAM_AGC_RF_IACCU_HI_CO__A, 0);
+		if (status < 0)
+			goto error;
+
+		/* Write value to output pin */
+		status = write16(state, SCU_RAM_AGC_RF_IACCU_HI__A, pAgcCfg->outputLevel);
+		if (status < 0)
+			goto error;
+		break;
+
+	case DRXK_AGC_CTRL_OFF:
+		/* Disable RF AGC DAC */
+		status = read16(state, IQM_AF_STDBY__A, &data);
+		if (status < 0)
+			goto error;
+		data |= IQM_AF_STDBY_STDBY_TAGC_RF_STANDBY;
+		status = write16(state, IQM_AF_STDBY__A, data);
+		if (status < 0)
+			goto error;
+
+		/* Disable SCU RF AGC loop */
+		status = read16(state, SCU_RAM_AGC_CONFIG__A, &data);
+		if (status < 0)
+			goto error;
+		data |= SCU_RAM_AGC_CONFIG_DISABLE_RF_AGC__M;
+		status = write16(state, SCU_RAM_AGC_CONFIG__A, data);
+		if (status < 0)
+			goto error;
+		break;
+
+	default:
+		status = -EINVAL;
+
+	}
+error:
+	if (status < 0)
+		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+	return status;
+}
+
+#define SCU_RAM_AGC_KI_INV_IF_POL__M 0x2000
+
+static int SetAgcIf(struct drxk_state *state,
+		    struct SCfgAgc *pAgcCfg, bool isDTV)
+{
+	u16 data = 0;
+	int status = 0;
+	struct SCfgAgc *pRfAgcSettings;
+
+	dprintk(1, "\n");
+
+	switch (pAgcCfg->ctrlMode) {
+	case DRXK_AGC_CTRL_AUTO:
+
+		/* Enable IF AGC DAC */
+		status = read16(state, IQM_AF_STDBY__A, &data);
+		if (status < 0)
+			goto error;
+		data &= ~IQM_AF_STDBY_STDBY_TAGC_IF_STANDBY;
+		status = write16(state, IQM_AF_STDBY__A, data);
+		if (status < 0)
+			goto error;
+
+		status = read16(state, SCU_RAM_AGC_CONFIG__A, &data);
+		if (status < 0)
+			goto error;
+
+		/* Enable SCU IF AGC loop */
+		data &= ~SCU_RAM_AGC_CONFIG_DISABLE_IF_AGC__M;
+
+		/* Polarity */
+		if (state->m_IfAgcPol)
+			data |= SCU_RAM_AGC_CONFIG_INV_IF_POL__M;
+		else
+			data &= ~SCU_RAM_AGC_CONFIG_INV_IF_POL__M;
+		status = write16(state, SCU_RAM_AGC_CONFIG__A, data);
+		if (status < 0)
+			goto error;
+
+		/* Set speed (using complementary reduction value) */
+		status = read16(state, SCU_RAM_AGC_KI_RED__A, &data);
+		if (status < 0)
+			goto error;
+		data &= ~SCU_RAM_AGC_KI_RED_IAGC_RED__M;
+		data |= (~(pAgcCfg->speed <<
+				SCU_RAM_AGC_KI_RED_IAGC_RED__B)
+				& SCU_RAM_AGC_KI_RED_IAGC_RED__M);
+
+		status = write16(state, SCU_RAM_AGC_KI_RED__A, data);
+		if (status < 0)
+			goto error;
+
+		if (IsQAM(state))
+			pRfAgcSettings = &state->m_qamRfAgcCfg;
+		else
+			pRfAgcSettings = &state->m_atvRfAgcCfg;
+		if (pRfAgcSettings == NULL)
+			return -1;
+		/* Restore TOP */
+		status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, pRfAgcSettings->top);
+		if (status < 0)
+			goto error;
+		break;
+
+	case DRXK_AGC_CTRL_USER:
+
+		/* Enable IF AGC DAC */
+		status = read16(state, IQM_AF_STDBY__A, &data);
+		if (status < 0)
+			goto error;
+		data &= ~IQM_AF_STDBY_STDBY_TAGC_IF_STANDBY;
+		status = write16(state, IQM_AF_STDBY__A, data);
+		if (status < 0)
+			goto error;
+
+		status = read16(state, SCU_RAM_AGC_CONFIG__A, &data);
+		if (status < 0)
+			goto error;
+
+		/* Disable SCU IF AGC loop */
+		data |= SCU_RAM_AGC_CONFIG_DISABLE_IF_AGC__M;
+
+		/* Polarity */
+		if (state->m_IfAgcPol)
+			data |= SCU_RAM_AGC_CONFIG_INV_IF_POL__M;
+		else
+			data &= ~SCU_RAM_AGC_CONFIG_INV_IF_POL__M;
+		status = write16(state, SCU_RAM_AGC_CONFIG__A, data);
+		if (status < 0)
+			goto error;
+
+		/* Write value to output pin */
+		status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, pAgcCfg->outputLevel);
+		if (status < 0)
+			goto error;
+		break;
+
+	case DRXK_AGC_CTRL_OFF:
+
+		/* Disable If AGC DAC */
+		status = read16(state, IQM_AF_STDBY__A, &data);
+		if (status < 0)
+			goto error;
+		data |= IQM_AF_STDBY_STDBY_TAGC_IF_STANDBY;
+		status = write16(state, IQM_AF_STDBY__A, data);
+		if (status < 0)
+			goto error;
+
+		/* Disable SCU IF AGC loop */
+		status = read16(state, SCU_RAM_AGC_CONFIG__A, &data);
+		if (status < 0)
+			goto error;
+		data |= SCU_RAM_AGC_CONFIG_DISABLE_IF_AGC__M;
+		status = write16(state, SCU_RAM_AGC_CONFIG__A, data);
+		if (status < 0)
+			goto error;
+		break;
+	}		/* switch (agcSettingsIf->ctrlMode) */
+
+	/* always set the top to support
+		configurations without if-loop */
+	status = write16(state, SCU_RAM_AGC_INGAIN_TGT_MIN__A, pAgcCfg->top);
+error:
+	if (status < 0)
+		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+	return status;
+}
+
+static int ReadIFAgc(struct drxk_state *state, u32 *pValue)
+{
+	u16 agcDacLvl;
+	int status;
+	u16 Level = 0;
+
+	dprintk(1, "\n");
+
+	status = read16(state, IQM_AF_AGC_IF__A, &agcDacLvl);
+	if (status < 0) {
+		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+		return status;
+	}
+
+	*pValue = 0;
+
+	if (agcDacLvl > DRXK_AGC_DAC_OFFSET)
+		Level = agcDacLvl - DRXK_AGC_DAC_OFFSET;
+	if (Level < 14000)
+		*pValue = (14000 - Level) / 4;
+	else
+		*pValue = 0;
+
+	return status;
+}
+
+static int GetQAMSignalToNoise(struct drxk_state *state,
+			       s32 *pSignalToNoise)
+{
+	int status = 0;
+	u16 qamSlErrPower = 0;	/* accum. error between
+					raw and sliced symbols */
+	u32 qamSlSigPower = 0;	/* used for MER, depends of
+					QAM modulation */
+	u32 qamSlMer = 0;	/* QAM MER */
+
+	dprintk(1, "\n");
+
+	/* MER calculation */
+
+	/* get the register value needed for MER */
+	status = read16(state, QAM_SL_ERR_POWER__A, &qamSlErrPower);
+	if (status < 0) {
+		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+		return -EINVAL;
+	}
+
+	switch (state->props.modulation) {
+	case QAM_16:
+		qamSlSigPower = DRXK_QAM_SL_SIG_POWER_QAM16 << 2;
+		break;
+	case QAM_32:
+		qamSlSigPower = DRXK_QAM_SL_SIG_POWER_QAM32 << 2;
+		break;
+	case QAM_64:
+		qamSlSigPower = DRXK_QAM_SL_SIG_POWER_QAM64 << 2;
+		break;
+	case QAM_128:
+		qamSlSigPower = DRXK_QAM_SL_SIG_POWER_QAM128 << 2;
+		break;
+	default:
+	case QAM_256:
+		qamSlSigPower = DRXK_QAM_SL_SIG_POWER_QAM256 << 2;
+		break;
+	}
+
+	if (qamSlErrPower > 0) {
+		qamSlMer = Log10Times100(qamSlSigPower) -
+			Log10Times100((u32) qamSlErrPower);
+	}
+	*pSignalToNoise = qamSlMer;
+
+	return status;
+}
+
+static int GetDVBTSignalToNoise(struct drxk_state *state,
+				s32 *pSignalToNoise)
+{
+	int status;
+	u16 regData = 0;
+	u32 EqRegTdSqrErrI = 0;
+	u32 EqRegTdSqrErrQ = 0;
+	u16 EqRegTdSqrErrExp = 0;
+	u16 EqRegTdTpsPwrOfs = 0;
+	u16 EqRegTdReqSmbCnt = 0;
+	u32 tpsCnt = 0;
+	u32 SqrErrIQ = 0;
+	u32 a = 0;
+	u32 b = 0;
+	u32 c = 0;
+	u32 iMER = 0;
+	u16 transmissionParams = 0;
+
+	dprintk(1, "\n");
+
+	status = read16(state, OFDM_EQ_TOP_TD_TPS_PWR_OFS__A, &EqRegTdTpsPwrOfs);
+	if (status < 0)
+		goto error;
+	status = read16(state, OFDM_EQ_TOP_TD_REQ_SMB_CNT__A, &EqRegTdReqSmbCnt);
+	if (status < 0)
+		goto error;
+	status = read16(state, OFDM_EQ_TOP_TD_SQR_ERR_EXP__A, &EqRegTdSqrErrExp);
+	if (status < 0)
+		goto error;
+	status = read16(state, OFDM_EQ_TOP_TD_SQR_ERR_I__A, &regData);
+	if (status < 0)
+		goto error;
+	/* Extend SQR_ERR_I operational range */
+	EqRegTdSqrErrI = (u32) regData;
+	if ((EqRegTdSqrErrExp > 11) &&
+		(EqRegTdSqrErrI < 0x00000FFFUL)) {
+		EqRegTdSqrErrI += 0x00010000UL;
+	}
+	status = read16(state, OFDM_EQ_TOP_TD_SQR_ERR_Q__A, &regData);
+	if (status < 0)
+		goto error;
+	/* Extend SQR_ERR_Q operational range */
+	EqRegTdSqrErrQ = (u32) regData;
+	if ((EqRegTdSqrErrExp > 11) &&
+		(EqRegTdSqrErrQ < 0x00000FFFUL))
+		EqRegTdSqrErrQ += 0x00010000UL;
+
+	status = read16(state, OFDM_SC_RA_RAM_OP_PARAM__A, &transmissionParams);
+	if (status < 0)
+		goto error;
+
+	/* Check input data for MER */
+
+	/* MER calculation (in 0.1 dB) without math.h */
+	if ((EqRegTdTpsPwrOfs == 0) || (EqRegTdReqSmbCnt == 0))
+		iMER = 0;
+	else if ((EqRegTdSqrErrI + EqRegTdSqrErrQ) == 0) {
+		/* No error at all, this must be the HW reset value
+			* Apparently no first measurement yet
+			* Set MER to 0.0 */
+		iMER = 0;
+	} else {
+		SqrErrIQ = (EqRegTdSqrErrI + EqRegTdSqrErrQ) <<
+			EqRegTdSqrErrExp;
+		if ((transmissionParams &
+			OFDM_SC_RA_RAM_OP_PARAM_MODE__M)
+			== OFDM_SC_RA_RAM_OP_PARAM_MODE_2K)
+			tpsCnt = 17;
+		else
+			tpsCnt = 68;
+
+		/* IMER = 100 * log10 (x)
+			where x = (EqRegTdTpsPwrOfs^2 *
+			EqRegTdReqSmbCnt * tpsCnt)/SqrErrIQ
+
+			=> IMER = a + b -c
+			where a = 100 * log10 (EqRegTdTpsPwrOfs^2)
+			b = 100 * log10 (EqRegTdReqSmbCnt * tpsCnt)
+			c = 100 * log10 (SqrErrIQ)
+			*/
+
+		/* log(x) x = 9bits * 9bits->18 bits  */
+		a = Log10Times100(EqRegTdTpsPwrOfs *
+					EqRegTdTpsPwrOfs);
+		/* log(x) x = 16bits * 7bits->23 bits  */
+		b = Log10Times100(EqRegTdReqSmbCnt * tpsCnt);
+		/* log(x) x = (16bits + 16bits) << 15 ->32 bits  */
+		c = Log10Times100(SqrErrIQ);
+
+		iMER = a + b;
+		/* No negative MER, clip to zero */
+		if (iMER > c)
+			iMER -= c;
+		else
+			iMER = 0;
+	}
+	*pSignalToNoise = iMER;
+
+error:
+	if (status < 0)
+		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+	return status;
+}
+
+static int GetSignalToNoise(struct drxk_state *state, s32 *pSignalToNoise)
+{
+	dprintk(1, "\n");
+
+	*pSignalToNoise = 0;
+	switch (state->m_OperationMode) {
+	case OM_DVBT:
+		return GetDVBTSignalToNoise(state, pSignalToNoise);
+	case OM_QAM_ITU_A:
+	case OM_QAM_ITU_C:
+		return GetQAMSignalToNoise(state, pSignalToNoise);
+	default:
+		break;
+	}
+	return 0;
+}
+
+#if 0
+static int GetDVBTQuality(struct drxk_state *state, s32 *pQuality)
+{
+	/* SNR Values for quasi errorfree reception rom Nordig 2.2 */
+	int status = 0;
+
+	dprintk(1, "\n");
+
+	static s32 QE_SN[] = {
+		51,		/* QPSK 1/2 */
+		69,		/* QPSK 2/3 */
+		79,		/* QPSK 3/4 */
+		89,		/* QPSK 5/6 */
+		97,		/* QPSK 7/8 */
+		108,		/* 16-QAM 1/2 */
+		131,		/* 16-QAM 2/3 */
+		146,		/* 16-QAM 3/4 */
+		156,		/* 16-QAM 5/6 */
+		160,		/* 16-QAM 7/8 */
+		165,		/* 64-QAM 1/2 */
+		187,		/* 64-QAM 2/3 */
+		202,		/* 64-QAM 3/4 */
+		216,		/* 64-QAM 5/6 */
+		225,		/* 64-QAM 7/8 */
+	};
+
+	*pQuality = 0;
+
+	do {
+		s32 SignalToNoise = 0;
+		u16 Constellation = 0;
+		u16 CodeRate = 0;
+		u32 SignalToNoiseRel;
+		u32 BERQuality;
+
+		status = GetDVBTSignalToNoise(state, &SignalToNoise);
+		if (status < 0)
+			break;
+		status = read16(state, OFDM_EQ_TOP_TD_TPS_CONST__A, &Constellation);
+		if (status < 0)
+			break;
+		Constellation &= OFDM_EQ_TOP_TD_TPS_CONST__M;
+
+		status = read16(state, OFDM_EQ_TOP_TD_TPS_CODE_HP__A, &CodeRate);
+		if (status < 0)
+			break;
+		CodeRate &= OFDM_EQ_TOP_TD_TPS_CODE_HP__M;
+
+		if (Constellation > OFDM_EQ_TOP_TD_TPS_CONST_64QAM ||
+		    CodeRate > OFDM_EQ_TOP_TD_TPS_CODE_LP_7_8)
+			break;
+		SignalToNoiseRel = SignalToNoise -
+		    QE_SN[Constellation * 5 + CodeRate];
+		BERQuality = 100;
+
+		if (SignalToNoiseRel < -70)
+			*pQuality = 0;
+		else if (SignalToNoiseRel < 30)
+			*pQuality = ((SignalToNoiseRel + 70) *
+				     BERQuality) / 100;
+		else
+			*pQuality = BERQuality;
+	} while (0);
+	return 0;
+};
+
+static int GetDVBCQuality(struct drxk_state *state, s32 *pQuality)
+{
+	int status = 0;
+	*pQuality = 0;
+
+	dprintk(1, "\n");
+
+	do {
+		u32 SignalToNoise = 0;
+		u32 BERQuality = 100;
+		u32 SignalToNoiseRel = 0;
+
+		status = GetQAMSignalToNoise(state, &SignalToNoise);
+		if (status < 0)
+			break;
+
+		switch (state->props.modulation) {
+		case QAM_16:
+			SignalToNoiseRel = SignalToNoise - 200;
+			break;
+		case QAM_32:
+			SignalToNoiseRel = SignalToNoise - 230;
+			break;	/* Not in NorDig */
+		case QAM_64:
+			SignalToNoiseRel = SignalToNoise - 260;
+			break;
+		case QAM_128:
+			SignalToNoiseRel = SignalToNoise - 290;
+			break;
+		default:
+		case QAM_256:
+			SignalToNoiseRel = SignalToNoise - 320;
+			break;
+		}
+
+		if (SignalToNoiseRel < -70)
+			*pQuality = 0;
+		else if (SignalToNoiseRel < 30)
+			*pQuality = ((SignalToNoiseRel + 70) *
+				     BERQuality) / 100;
+		else
+			*pQuality = BERQuality;
+	} while (0);
+
+	return status;
+}
+
+static int GetQuality(struct drxk_state *state, s32 *pQuality)
+{
+	dprintk(1, "\n");
+
+	switch (state->m_OperationMode) {
+	case OM_DVBT:
+		return GetDVBTQuality(state, pQuality);
+	case OM_QAM_ITU_A:
+		return GetDVBCQuality(state, pQuality);
+	default:
+		break;
+	}
+
+	return 0;
+}
+#endif
+
+/* Free data ram in SIO HI */
+#define SIO_HI_RA_RAM_USR_BEGIN__A 0x420040
+#define SIO_HI_RA_RAM_USR_END__A   0x420060
+
+#define DRXK_HI_ATOMIC_BUF_START (SIO_HI_RA_RAM_USR_BEGIN__A)
+#define DRXK_HI_ATOMIC_BUF_END   (SIO_HI_RA_RAM_USR_BEGIN__A + 7)
+#define DRXK_HI_ATOMIC_READ      SIO_HI_RA_RAM_PAR_3_ACP_RW_READ
+#define DRXK_HI_ATOMIC_WRITE     SIO_HI_RA_RAM_PAR_3_ACP_RW_WRITE
+
+#define DRXDAP_FASI_ADDR2BLOCK(addr)  (((addr) >> 22) & 0x3F)
+#define DRXDAP_FASI_ADDR2BANK(addr)   (((addr) >> 16) & 0x3F)
+#define DRXDAP_FASI_ADDR2OFFSET(addr) ((addr) & 0x7FFF)
+
+static int ConfigureI2CBridge(struct drxk_state *state, bool bEnableBridge)
+{
+	int status = -EINVAL;
+
+	dprintk(1, "\n");
+
+	if (state->m_DrxkState == DRXK_UNINITIALIZED)
+		return 0;
+	if (state->m_DrxkState == DRXK_POWERED_DOWN)
+		goto error;
+
+	if (state->no_i2c_bridge)
+		return 0;
+
+	status = write16(state, SIO_HI_RA_RAM_PAR_1__A, SIO_HI_RA_RAM_PAR_1_PAR1_SEC_KEY);
+	if (status < 0)
+		goto error;
+	if (bEnableBridge) {
+		status = write16(state, SIO_HI_RA_RAM_PAR_2__A, SIO_HI_RA_RAM_PAR_2_BRD_CFG_CLOSED);
+		if (status < 0)
+			goto error;
+	} else {
+		status = write16(state, SIO_HI_RA_RAM_PAR_2__A, SIO_HI_RA_RAM_PAR_2_BRD_CFG_OPEN);
+		if (status < 0)
+			goto error;
+	}
+
+	status = HI_Command(state, SIO_HI_RA_RAM_CMD_BRDCTRL, 0);
+
+error:
+	if (status < 0)
+		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+	return status;
+}
+
+static int SetPreSaw(struct drxk_state *state,
+		     struct SCfgPreSaw *pPreSawCfg)
+{
+	int status = -EINVAL;
+
+	dprintk(1, "\n");
+
+	if ((pPreSawCfg == NULL)
+	    || (pPreSawCfg->reference > IQM_AF_PDREF__M))
+		goto error;
+
+	status = write16(state, IQM_AF_PDREF__A, pPreSawCfg->reference);
+error:
+	if (status < 0)
+		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+	return status;
+}
+
+static int BLDirectCmd(struct drxk_state *state, u32 targetAddr,
+		       u16 romOffset, u16 nrOfElements, u32 timeOut)
+{
+	u16 blStatus = 0;
+	u16 offset = (u16) ((targetAddr >> 0) & 0x00FFFF);
+	u16 blockbank = (u16) ((targetAddr >> 16) & 0x000FFF);
+	int status;
+	unsigned long end;
+
+	dprintk(1, "\n");
+
+	mutex_lock(&state->mutex);
+	status = write16(state, SIO_BL_MODE__A, SIO_BL_MODE_DIRECT);
+	if (status < 0)
+		goto error;
+	status = write16(state, SIO_BL_TGT_HDR__A, blockbank);
+	if (status < 0)
+		goto error;
+	status = write16(state, SIO_BL_TGT_ADDR__A, offset);
+	if (status < 0)
+		goto error;
+	status = write16(state, SIO_BL_SRC_ADDR__A, romOffset);
+	if (status < 0)
+		goto error;
+	status = write16(state, SIO_BL_SRC_LEN__A, nrOfElements);
+	if (status < 0)
+		goto error;
+	status = write16(state, SIO_BL_ENABLE__A, SIO_BL_ENABLE_ON);
+	if (status < 0)
+		goto error;
+
+	end = jiffies + msecs_to_jiffies(timeOut);
+	do {
+		status = read16(state, SIO_BL_STATUS__A, &blStatus);
+		if (status < 0)
+			goto error;
+	} while ((blStatus == 0x1) && time_is_after_jiffies(end));
+	if (blStatus == 0x1) {
+		printk(KERN_ERR "drxk: SIO not ready\n");
+		status = -EINVAL;
+		goto error2;
+	}
+error:
+	if (status < 0)
+		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+error2:
+	mutex_unlock(&state->mutex);
+	return status;
+
+}
+
+static int ADCSyncMeasurement(struct drxk_state *state, u16 *count)
+{
+	u16 data = 0;
+	int status;
+
+	dprintk(1, "\n");
+
+	/* Start measurement */
+	status = write16(state, IQM_AF_COMM_EXEC__A, IQM_AF_COMM_EXEC_ACTIVE);
+	if (status < 0)
+		goto error;
+	status = write16(state, IQM_AF_START_LOCK__A, 1);
+	if (status < 0)
+		goto error;
+
+	*count = 0;
+	status = read16(state, IQM_AF_PHASE0__A, &data);
+	if (status < 0)
+		goto error;
+	if (data == 127)
+		*count = *count + 1;
+	status = read16(state, IQM_AF_PHASE1__A, &data);
+	if (status < 0)
+		goto error;
+	if (data == 127)
+		*count = *count + 1;
+	status = read16(state, IQM_AF_PHASE2__A, &data);
+	if (status < 0)
+		goto error;
+	if (data == 127)
+		*count = *count + 1;
+
+error:
+	if (status < 0)
+		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+	return status;
+}
+
+static int ADCSynchronization(struct drxk_state *state)
+{
+	u16 count = 0;
+	int status;
+
+	dprintk(1, "\n");
+
+	status = ADCSyncMeasurement(state, &count);
+	if (status < 0)
+		goto error;
+
+	if (count == 1) {
+		/* Try sampling on a diffrent edge */
+		u16 clkNeg = 0;
+
+		status = read16(state, IQM_AF_CLKNEG__A, &clkNeg);
+		if (status < 0)
+			goto error;
+		if ((clkNeg & IQM_AF_CLKNEG_CLKNEGDATA__M) ==
+			IQM_AF_CLKNEG_CLKNEGDATA_CLK_ADC_DATA_POS) {
+			clkNeg &= (~(IQM_AF_CLKNEG_CLKNEGDATA__M));
+			clkNeg |=
+				IQM_AF_CLKNEG_CLKNEGDATA_CLK_ADC_DATA_NEG;
+		} else {
+			clkNeg &= (~(IQM_AF_CLKNEG_CLKNEGDATA__M));
+			clkNeg |=
+				IQM_AF_CLKNEG_CLKNEGDATA_CLK_ADC_DATA_POS;
+		}
+		status = write16(state, IQM_AF_CLKNEG__A, clkNeg);
+		if (status < 0)
+			goto error;
+		status = ADCSyncMeasurement(state, &count);
+		if (status < 0)
+			goto error;
+	}
+
+	if (count < 2)
+		status = -EINVAL;
+error:
+	if (status < 0)
+		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+	return status;
+}
+
+static int SetFrequencyShifter(struct drxk_state *state,
+			       u16 intermediateFreqkHz,
+			       s32 tunerFreqOffset, bool isDTV)
+{
+	bool selectPosImage = false;
+	u32 rfFreqResidual = tunerFreqOffset;
+	u32 fmFrequencyShift = 0;
+	bool tunerMirror = !state->m_bMirrorFreqSpect;
+	u32 adcFreq;
+	bool adcFlip;
+	int status;
+	u32 ifFreqActual;
+	u32 samplingFrequency = (u32) (state->m_sysClockFreq / 3);
+	u32 frequencyShift;
+	bool imageToSelect;
+
+	dprintk(1, "\n");
+
+	/*
+	   Program frequency shifter
+	   No need to account for mirroring on RF
+	 */
+	if (isDTV) {
+		if ((state->m_OperationMode == OM_QAM_ITU_A) ||
+		    (state->m_OperationMode == OM_QAM_ITU_C) ||
+		    (state->m_OperationMode == OM_DVBT))
+			selectPosImage = true;
+		else
+			selectPosImage = false;
+	}
+	if (tunerMirror)
+		/* tuner doesn't mirror */
+		ifFreqActual = intermediateFreqkHz +
+		    rfFreqResidual + fmFrequencyShift;
+	else
+		/* tuner mirrors */
+		ifFreqActual = intermediateFreqkHz -
+		    rfFreqResidual - fmFrequencyShift;
+	if (ifFreqActual > samplingFrequency / 2) {
+		/* adc mirrors */
+		adcFreq = samplingFrequency - ifFreqActual;
+		adcFlip = true;
+	} else {
+		/* adc doesn't mirror */
+		adcFreq = ifFreqActual;
+		adcFlip = false;
+	}
+
+	frequencyShift = adcFreq;
+	imageToSelect = state->m_rfmirror ^ tunerMirror ^
+	    adcFlip ^ selectPosImage;
+	state->m_IqmFsRateOfs =
+	    Frac28a((frequencyShift), samplingFrequency);
+
+	if (imageToSelect)
+		state->m_IqmFsRateOfs = ~state->m_IqmFsRateOfs + 1;
+
+	/* Program frequency shifter with tuner offset compensation */
+	/* frequencyShift += tunerFreqOffset; TODO */
+	status = write32(state, IQM_FS_RATE_OFS_LO__A,
+			 state->m_IqmFsRateOfs);
+	if (status < 0)
+		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+	return status;
+}
+
+static int InitAGC(struct drxk_state *state, bool isDTV)
+{
+	u16 ingainTgt = 0;
+	u16 ingainTgtMin = 0;
+	u16 ingainTgtMax = 0;
+	u16 clpCyclen = 0;
+	u16 clpSumMin = 0;
+	u16 clpDirTo = 0;
+	u16 snsSumMin = 0;
+	u16 snsSumMax = 0;
+	u16 clpSumMax = 0;
+	u16 snsDirTo = 0;
+	u16 kiInnergainMin = 0;
+	u16 ifIaccuHiTgt = 0;
+	u16 ifIaccuHiTgtMin = 0;
+	u16 ifIaccuHiTgtMax = 0;
+	u16 data = 0;
+	u16 fastClpCtrlDelay = 0;
+	u16 clpCtrlMode = 0;
+	int status = 0;
+
+	dprintk(1, "\n");
+
+	/* Common settings */
+	snsSumMax = 1023;
+	ifIaccuHiTgtMin = 2047;
+	clpCyclen = 500;
+	clpSumMax = 1023;
+
+	/* AGCInit() not available for DVBT; init done in microcode */
+	if (!IsQAM(state)) {
+		printk(KERN_ERR "drxk: %s: mode %d is not DVB-C\n", __func__, state->m_OperationMode);
+		return -EINVAL;
+	}
+
+	/* FIXME: Analog TV AGC require different settings */
+
+	/* Standard specific settings */
+	clpSumMin = 8;
+	clpDirTo = (u16) -9;
+	clpCtrlMode = 0;
+	snsSumMin = 8;
+	snsDirTo = (u16) -9;
+	kiInnergainMin = (u16) -1030;
+	ifIaccuHiTgtMax = 0x2380;
+	ifIaccuHiTgt = 0x2380;
+	ingainTgtMin = 0x0511;
+	ingainTgt = 0x0511;
+	ingainTgtMax = 5119;
+	fastClpCtrlDelay = state->m_qamIfAgcCfg.FastClipCtrlDelay;
+
+	status = write16(state, SCU_RAM_AGC_FAST_CLP_CTRL_DELAY__A, fastClpCtrlDelay);
+	if (status < 0)
+		goto error;
+
+	status = write16(state, SCU_RAM_AGC_CLP_CTRL_MODE__A, clpCtrlMode);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_AGC_INGAIN_TGT__A, ingainTgt);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_AGC_INGAIN_TGT_MIN__A, ingainTgtMin);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_AGC_INGAIN_TGT_MAX__A, ingainTgtMax);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MIN__A, ifIaccuHiTgtMin);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, ifIaccuHiTgtMax);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_AGC_IF_IACCU_HI__A, 0);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_AGC_IF_IACCU_LO__A, 0);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_AGC_RF_IACCU_HI__A, 0);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_AGC_RF_IACCU_LO__A, 0);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_AGC_CLP_SUM_MAX__A, clpSumMax);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_AGC_SNS_SUM_MAX__A, snsSumMax);
+	if (status < 0)
+		goto error;
+
+	status = write16(state, SCU_RAM_AGC_KI_INNERGAIN_MIN__A, kiInnergainMin);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT__A, ifIaccuHiTgt);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_AGC_CLP_CYCLEN__A, clpCyclen);
+	if (status < 0)
+		goto error;
+
+	status = write16(state, SCU_RAM_AGC_RF_SNS_DEV_MAX__A, 1023);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_AGC_RF_SNS_DEV_MIN__A, (u16) -1023);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_AGC_FAST_SNS_CTRL_DELAY__A, 50);
+	if (status < 0)
+		goto error;
+
+	status = write16(state, SCU_RAM_AGC_KI_MAXMINGAIN_TH__A, 20);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_AGC_CLP_SUM_MIN__A, clpSumMin);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_AGC_SNS_SUM_MIN__A, snsSumMin);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_AGC_CLP_DIR_TO__A, clpDirTo);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_AGC_SNS_DIR_TO__A, snsDirTo);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_AGC_KI_MINGAIN__A, 0x7fff);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_AGC_KI_MAXGAIN__A, 0x0);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_AGC_KI_MIN__A, 0x0117);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_AGC_KI_MAX__A, 0x0657);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_AGC_CLP_SUM__A, 0);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_AGC_CLP_CYCCNT__A, 0);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_AGC_CLP_DIR_WD__A, 0);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_AGC_CLP_DIR_STP__A, 1);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_AGC_SNS_SUM__A, 0);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_AGC_SNS_CYCCNT__A, 0);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_AGC_SNS_DIR_WD__A, 0);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_AGC_SNS_DIR_STP__A, 1);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_AGC_SNS_CYCLEN__A, 500);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_AGC_KI_CYCLEN__A, 500);
+	if (status < 0)
+		goto error;
+
+	/* Initialize inner-loop KI gain factors */
+	status = read16(state, SCU_RAM_AGC_KI__A, &data);
+	if (status < 0)
+		goto error;
+
+	data = 0x0657;
+	data &= ~SCU_RAM_AGC_KI_RF__M;
+	data |= (DRXK_KI_RAGC_QAM << SCU_RAM_AGC_KI_RF__B);
+	data &= ~SCU_RAM_AGC_KI_IF__M;
+	data |= (DRXK_KI_IAGC_QAM << SCU_RAM_AGC_KI_IF__B);
+
+	status = write16(state, SCU_RAM_AGC_KI__A, data);
+error:
+	if (status < 0)
+		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+	return status;
+}
+
+static int DVBTQAMGetAccPktErr(struct drxk_state *state, u16 *packetErr)
+{
+	int status;
+
+	dprintk(1, "\n");
+	if (packetErr == NULL)
+		status = write16(state, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, 0);
+	else
+		status = read16(state, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, packetErr);
+	if (status < 0)
+		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+	return status;
+}
+
+static int DVBTScCommand(struct drxk_state *state,
+			 u16 cmd, u16 subcmd,
+			 u16 param0, u16 param1, u16 param2,
+			 u16 param3, u16 param4)
+{
+	u16 curCmd = 0;
+	u16 errCode = 0;
+	u16 retryCnt = 0;
+	u16 scExec = 0;
+	int status;
+
+	dprintk(1, "\n");
+	status = read16(state, OFDM_SC_COMM_EXEC__A, &scExec);
+	if (scExec != 1) {
+		/* SC is not running */
+		status = -EINVAL;
+	}
+	if (status < 0)
+		goto error;
+
+	/* Wait until sc is ready to receive command */
+	retryCnt = 0;
+	do {
+		msleep(1);
+		status = read16(state, OFDM_SC_RA_RAM_CMD__A, &curCmd);
+		retryCnt++;
+	} while ((curCmd != 0) && (retryCnt < DRXK_MAX_RETRIES));
+	if (retryCnt >= DRXK_MAX_RETRIES && (status < 0))
+		goto error;
+
+	/* Write sub-command */
+	switch (cmd) {
+		/* All commands using sub-cmd */
+	case OFDM_SC_RA_RAM_CMD_PROC_START:
+	case OFDM_SC_RA_RAM_CMD_SET_PREF_PARAM:
+	case OFDM_SC_RA_RAM_CMD_PROGRAM_PARAM:
+		status = write16(state, OFDM_SC_RA_RAM_CMD_ADDR__A, subcmd);
+		if (status < 0)
+			goto error;
+		break;
+	default:
+		/* Do nothing */
+		break;
+	}
+
+	/* Write needed parameters and the command */
+	switch (cmd) {
+		/* All commands using 5 parameters */
+		/* All commands using 4 parameters */
+		/* All commands using 3 parameters */
+		/* All commands using 2 parameters */
+	case OFDM_SC_RA_RAM_CMD_PROC_START:
+	case OFDM_SC_RA_RAM_CMD_SET_PREF_PARAM:
+	case OFDM_SC_RA_RAM_CMD_PROGRAM_PARAM:
+		status = write16(state, OFDM_SC_RA_RAM_PARAM1__A, param1);
+		/* All commands using 1 parameters */
+	case OFDM_SC_RA_RAM_CMD_SET_ECHO_TIMING:
+	case OFDM_SC_RA_RAM_CMD_USER_IO:
+		status = write16(state, OFDM_SC_RA_RAM_PARAM0__A, param0);
+		/* All commands using 0 parameters */
+	case OFDM_SC_RA_RAM_CMD_GET_OP_PARAM:
+	case OFDM_SC_RA_RAM_CMD_NULL:
+		/* Write command */
+		status = write16(state, OFDM_SC_RA_RAM_CMD__A, cmd);
+		break;
+	default:
+		/* Unknown command */
+		status = -EINVAL;
+	}
+	if (status < 0)
+		goto error;
+
+	/* Wait until sc is ready processing command */
+	retryCnt = 0;
+	do {
+		msleep(1);
+		status = read16(state, OFDM_SC_RA_RAM_CMD__A, &curCmd);
+		retryCnt++;
+	} while ((curCmd != 0) && (retryCnt < DRXK_MAX_RETRIES));
+	if (retryCnt >= DRXK_MAX_RETRIES && (status < 0))
+		goto error;
+
+	/* Check for illegal cmd */
+	status = read16(state, OFDM_SC_RA_RAM_CMD_ADDR__A, &errCode);
+	if (errCode == 0xFFFF) {
+		/* illegal command */
+		status = -EINVAL;
+	}
+	if (status < 0)
+		goto error;
+
+	/* Retreive results parameters from SC */
+	switch (cmd) {
+		/* All commands yielding 5 results */
+		/* All commands yielding 4 results */
+		/* All commands yielding 3 results */
+		/* All commands yielding 2 results */
+		/* All commands yielding 1 result */
+	case OFDM_SC_RA_RAM_CMD_USER_IO:
+	case OFDM_SC_RA_RAM_CMD_GET_OP_PARAM:
+		status = read16(state, OFDM_SC_RA_RAM_PARAM0__A, &(param0));
+		/* All commands yielding 0 results */
+	case OFDM_SC_RA_RAM_CMD_SET_ECHO_TIMING:
+	case OFDM_SC_RA_RAM_CMD_SET_TIMER:
+	case OFDM_SC_RA_RAM_CMD_PROC_START:
+	case OFDM_SC_RA_RAM_CMD_SET_PREF_PARAM:
+	case OFDM_SC_RA_RAM_CMD_PROGRAM_PARAM:
+	case OFDM_SC_RA_RAM_CMD_NULL:
+		break;
+	default:
+		/* Unknown command */
+		status = -EINVAL;
+		break;
+	}			/* switch (cmd->cmd) */
+error:
+	if (status < 0)
+		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+	return status;
+}
+
+static int PowerUpDVBT(struct drxk_state *state)
+{
+	enum DRXPowerMode powerMode = DRX_POWER_UP;
+	int status;
+
+	dprintk(1, "\n");
+	status = CtrlPowerMode(state, &powerMode);
+	if (status < 0)
+		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+	return status;
+}
+
+static int DVBTCtrlSetIncEnable(struct drxk_state *state, bool *enabled)
+{
+	int status;
+
+	dprintk(1, "\n");
+	if (*enabled == true)
+		status = write16(state, IQM_CF_BYPASSDET__A, 0);
+	else
+		status = write16(state, IQM_CF_BYPASSDET__A, 1);
+	if (status < 0)
+		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+	return status;
+}
+
+#define DEFAULT_FR_THRES_8K     4000
+static int DVBTCtrlSetFrEnable(struct drxk_state *state, bool *enabled)
+{
+
+	int status;
+
+	dprintk(1, "\n");
+	if (*enabled == true) {
+		/* write mask to 1 */
+		status = write16(state, OFDM_SC_RA_RAM_FR_THRES_8K__A,
+				   DEFAULT_FR_THRES_8K);
+	} else {
+		/* write mask to 0 */
+		status = write16(state, OFDM_SC_RA_RAM_FR_THRES_8K__A, 0);
+	}
+	if (status < 0)
+		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+
+	return status;
+}
+
+static int DVBTCtrlSetEchoThreshold(struct drxk_state *state,
+				    struct DRXKCfgDvbtEchoThres_t *echoThres)
+{
+	u16 data = 0;
+	int status;
+
+	dprintk(1, "\n");
+	status = read16(state, OFDM_SC_RA_RAM_ECHO_THRES__A, &data);
+	if (status < 0)
+		goto error;
+
+	switch (echoThres->fftMode) {
+	case DRX_FFTMODE_2K:
+		data &= ~OFDM_SC_RA_RAM_ECHO_THRES_2K__M;
+		data |= ((echoThres->threshold <<
+			OFDM_SC_RA_RAM_ECHO_THRES_2K__B)
+			& (OFDM_SC_RA_RAM_ECHO_THRES_2K__M));
+		break;
+	case DRX_FFTMODE_8K:
+		data &= ~OFDM_SC_RA_RAM_ECHO_THRES_8K__M;
+		data |= ((echoThres->threshold <<
+			OFDM_SC_RA_RAM_ECHO_THRES_8K__B)
+			& (OFDM_SC_RA_RAM_ECHO_THRES_8K__M));
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	status = write16(state, OFDM_SC_RA_RAM_ECHO_THRES__A, data);
+error:
+	if (status < 0)
+		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+	return status;
+}
+
+static int DVBTCtrlSetSqiSpeed(struct drxk_state *state,
+			       enum DRXKCfgDvbtSqiSpeed *speed)
+{
+	int status = -EINVAL;
+
+	dprintk(1, "\n");
+
+	switch (*speed) {
+	case DRXK_DVBT_SQI_SPEED_FAST:
+	case DRXK_DVBT_SQI_SPEED_MEDIUM:
+	case DRXK_DVBT_SQI_SPEED_SLOW:
+		break;
+	default:
+		goto error;
+	}
+	status = write16(state, SCU_RAM_FEC_PRE_RS_BER_FILTER_SH__A,
+			   (u16) *speed);
+error:
+	if (status < 0)
+		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+	return status;
+}
+
+/*============================================================================*/
+
+/**
+* \brief Activate DVBT specific presets
+* \param demod instance of demodulator.
+* \return DRXStatus_t.
+*
+* Called in DVBTSetStandard
+*
+*/
+static int DVBTActivatePresets(struct drxk_state *state)
+{
+	int status;
+	bool setincenable = false;
+	bool setfrenable = true;
+
+	struct DRXKCfgDvbtEchoThres_t echoThres2k = { 0, DRX_FFTMODE_2K };
+	struct DRXKCfgDvbtEchoThres_t echoThres8k = { 0, DRX_FFTMODE_8K };
+
+	dprintk(1, "\n");
+	status = DVBTCtrlSetIncEnable(state, &setincenable);
+	if (status < 0)
+		goto error;
+	status = DVBTCtrlSetFrEnable(state, &setfrenable);
+	if (status < 0)
+		goto error;
+	status = DVBTCtrlSetEchoThreshold(state, &echoThres2k);
+	if (status < 0)
+		goto error;
+	status = DVBTCtrlSetEchoThreshold(state, &echoThres8k);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_AGC_INGAIN_TGT_MAX__A, state->m_dvbtIfAgcCfg.IngainTgtMax);
+error:
+	if (status < 0)
+		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+	return status;
+}
+
+/*============================================================================*/
+
+/**
+* \brief Initialize channelswitch-independent settings for DVBT.
+* \param demod instance of demodulator.
+* \return DRXStatus_t.
+*
+* For ROM code channel filter taps are loaded from the bootloader. For microcode
+* the DVB-T taps from the drxk_filters.h are used.
+*/
+static int SetDVBTStandard(struct drxk_state *state,
+			   enum OperationMode oMode)
+{
+	u16 cmdResult = 0;
+	u16 data = 0;
+	int status;
+
+	dprintk(1, "\n");
+
+	PowerUpDVBT(state);
+	/* added antenna switch */
+	SwitchAntennaToDVBT(state);
+	/* send OFDM reset command */
+	status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM | SCU_RAM_COMMAND_CMD_DEMOD_RESET, 0, NULL, 1, &cmdResult);
+	if (status < 0)
+		goto error;
+
+	/* send OFDM setenv command */
+	status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM | SCU_RAM_COMMAND_CMD_DEMOD_SET_ENV, 0, NULL, 1, &cmdResult);
+	if (status < 0)
+		goto error;
+
+	/* reset datapath for OFDM, processors first */
+	status = write16(state, OFDM_SC_COMM_EXEC__A, OFDM_SC_COMM_EXEC_STOP);
+	if (status < 0)
+		goto error;
+	status = write16(state, OFDM_LC_COMM_EXEC__A, OFDM_LC_COMM_EXEC_STOP);
+	if (status < 0)
+		goto error;
+	status = write16(state, IQM_COMM_EXEC__A, IQM_COMM_EXEC_B_STOP);
+	if (status < 0)
+		goto error;
+
+	/* IQM setup */
+	/* synchronize on ofdstate->m_festart */
+	status = write16(state, IQM_AF_UPD_SEL__A, 1);
+	if (status < 0)
+		goto error;
+	/* window size for clipping ADC detection */
+	status = write16(state, IQM_AF_CLP_LEN__A, 0);
+	if (status < 0)
+		goto error;
+	/* window size for for sense pre-SAW detection */
+	status = write16(state, IQM_AF_SNS_LEN__A, 0);
+	if (status < 0)
+		goto error;
+	/* sense threshold for sense pre-SAW detection */
+	status = write16(state, IQM_AF_AMUX__A, IQM_AF_AMUX_SIGNAL2ADC);
+	if (status < 0)
+		goto error;
+	status = SetIqmAf(state, true);
+	if (status < 0)
+		goto error;
+
+	status = write16(state, IQM_AF_AGC_RF__A, 0);
+	if (status < 0)
+		goto error;
+
+	/* Impulse noise cruncher setup */
+	status = write16(state, IQM_AF_INC_LCT__A, 0);	/* crunch in IQM_CF */
+	if (status < 0)
+		goto error;
+	status = write16(state, IQM_CF_DET_LCT__A, 0);	/* detect in IQM_CF */
+	if (status < 0)
+		goto error;
+	status = write16(state, IQM_CF_WND_LEN__A, 3);	/* peak detector window length */
+	if (status < 0)
+		goto error;
+
+	status = write16(state, IQM_RC_STRETCH__A, 16);
+	if (status < 0)
+		goto error;
+	status = write16(state, IQM_CF_OUT_ENA__A, 0x4);	/* enable output 2 */
+	if (status < 0)
+		goto error;
+	status = write16(state, IQM_CF_DS_ENA__A, 0x4);	/* decimate output 2 */
+	if (status < 0)
+		goto error;
+	status = write16(state, IQM_CF_SCALE__A, 1600);
+	if (status < 0)
+		goto error;
+	status = write16(state, IQM_CF_SCALE_SH__A, 0);
+	if (status < 0)
+		goto error;
+
+	/* virtual clipping threshold for clipping ADC detection */
+	status = write16(state, IQM_AF_CLP_TH__A, 448);
+	if (status < 0)
+		goto error;
+	status = write16(state, IQM_CF_DATATH__A, 495);	/* crunching threshold */
+	if (status < 0)
+		goto error;
+
+	status = BLChainCmd(state, DRXK_BL_ROM_OFFSET_TAPS_DVBT, DRXK_BLCC_NR_ELEMENTS_TAPS, DRXK_BLC_TIMEOUT);
+	if (status < 0)
+		goto error;
+
+	status = write16(state, IQM_CF_PKDTH__A, 2);	/* peak detector threshold */
+	if (status < 0)
+		goto error;
+	status = write16(state, IQM_CF_POW_MEAS_LEN__A, 2);
+	if (status < 0)
+		goto error;
+	/* enable power measurement interrupt */
+	status = write16(state, IQM_CF_COMM_INT_MSK__A, 1);
+	if (status < 0)
+		goto error;
+	status = write16(state, IQM_COMM_EXEC__A, IQM_COMM_EXEC_B_ACTIVE);
+	if (status < 0)
+		goto error;
+
+	/* IQM will not be reset from here, sync ADC and update/init AGC */
+	status = ADCSynchronization(state);
+	if (status < 0)
+		goto error;
+	status = SetPreSaw(state, &state->m_dvbtPreSawCfg);
+	if (status < 0)
+		goto error;
+
+	/* Halt SCU to enable safe non-atomic accesses */
+	status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_HOLD);
+	if (status < 0)
+		goto error;
+
+	status = SetAgcRf(state, &state->m_dvbtRfAgcCfg, true);
+	if (status < 0)
+		goto error;
+	status = SetAgcIf(state, &state->m_dvbtIfAgcCfg, true);
+	if (status < 0)
+		goto error;
+
+	/* Set Noise Estimation notch width and enable DC fix */
+	status = read16(state, OFDM_SC_RA_RAM_CONFIG__A, &data);
+	if (status < 0)
+		goto error;
+	data |= OFDM_SC_RA_RAM_CONFIG_NE_FIX_ENABLE__M;
+	status = write16(state, OFDM_SC_RA_RAM_CONFIG__A, data);
+	if (status < 0)
+		goto error;
+
+	/* Activate SCU to enable SCU commands */
+	status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_ACTIVE);
+	if (status < 0)
+		goto error;
+
+	if (!state->m_DRXK_A3_ROM_CODE) {
+		/* AGCInit() is not done for DVBT, so set agcFastClipCtrlDelay  */
+		status = write16(state, SCU_RAM_AGC_FAST_CLP_CTRL_DELAY__A, state->m_dvbtIfAgcCfg.FastClipCtrlDelay);
+		if (status < 0)
+			goto error;
+	}
+
+	/* OFDM_SC setup */
+#ifdef COMPILE_FOR_NONRT
+	status = write16(state, OFDM_SC_RA_RAM_BE_OPT_DELAY__A, 1);
+	if (status < 0)
+		goto error;
+	status = write16(state, OFDM_SC_RA_RAM_BE_OPT_INIT_DELAY__A, 2);
+	if (status < 0)
+		goto error;
+#endif
+
+	/* FEC setup */
+	status = write16(state, FEC_DI_INPUT_CTL__A, 1);	/* OFDM input */
+	if (status < 0)
+		goto error;
+
+
+#ifdef COMPILE_FOR_NONRT
+	status = write16(state, FEC_RS_MEASUREMENT_PERIOD__A, 0x400);
+	if (status < 0)
+		goto error;
+#else
+	status = write16(state, FEC_RS_MEASUREMENT_PERIOD__A, 0x1000);
+	if (status < 0)
+		goto error;
+#endif
+	status = write16(state, FEC_RS_MEASUREMENT_PRESCALE__A, 0x0001);
+	if (status < 0)
+		goto error;
+
+	/* Setup MPEG bus */
+	status = MPEGTSDtoSetup(state, OM_DVBT);
+	if (status < 0)
+		goto error;
+	/* Set DVBT Presets */
+	status = DVBTActivatePresets(state);
+	if (status < 0)
+		goto error;
+
+error:
+	if (status < 0)
+		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+	return status;
+}
+
+/*============================================================================*/
+/**
+* \brief Start dvbt demodulating for channel.
+* \param demod instance of demodulator.
+* \return DRXStatus_t.
+*/
+static int DVBTStart(struct drxk_state *state)
+{
+	u16 param1;
+	int status;
+	/* DRXKOfdmScCmd_t scCmd; */
+
+	dprintk(1, "\n");
+	/* Start correct processes to get in lock */
+	/* DRXK: OFDM_SC_RA_RAM_PROC_LOCKTRACK is no longer in mapfile! */
+	param1 = OFDM_SC_RA_RAM_LOCKTRACK_MIN;
+	status = DVBTScCommand(state, OFDM_SC_RA_RAM_CMD_PROC_START, 0, OFDM_SC_RA_RAM_SW_EVENT_RUN_NMASK__M, param1, 0, 0, 0);
+	if (status < 0)
+		goto error;
+	/* Start FEC OC */
+	status = MPEGTSStart(state);
+	if (status < 0)
+		goto error;
+	status = write16(state, FEC_COMM_EXEC__A, FEC_COMM_EXEC_ACTIVE);
+	if (status < 0)
+		goto error;
+error:
+	if (status < 0)
+		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+	return status;
+}
+
+
+/*============================================================================*/
+
+/**
+* \brief Set up dvbt demodulator for channel.
+* \param demod instance of demodulator.
+* \return DRXStatus_t.
+* // original DVBTSetChannel()
+*/
+static int SetDVBT(struct drxk_state *state, u16 IntermediateFreqkHz,
+		   s32 tunerFreqOffset)
+{
+	u16 cmdResult = 0;
+	u16 transmissionParams = 0;
+	u16 operationMode = 0;
+	u32 iqmRcRateOfs = 0;
+	u32 bandwidth = 0;
+	u16 param1;
+	int status;
+
+	dprintk(1, "IF =%d, TFO = %d\n", IntermediateFreqkHz, tunerFreqOffset);
+
+	status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM | SCU_RAM_COMMAND_CMD_DEMOD_STOP, 0, NULL, 1, &cmdResult);
+	if (status < 0)
+		goto error;
+
+	/* Halt SCU to enable safe non-atomic accesses */
+	status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_HOLD);
+	if (status < 0)
+		goto error;
+
+	/* Stop processors */
+	status = write16(state, OFDM_SC_COMM_EXEC__A, OFDM_SC_COMM_EXEC_STOP);
+	if (status < 0)
+		goto error;
+	status = write16(state, OFDM_LC_COMM_EXEC__A, OFDM_LC_COMM_EXEC_STOP);
+	if (status < 0)
+		goto error;
+
+	/* Mandatory fix, always stop CP, required to set spl offset back to
+		hardware default (is set to 0 by ucode during pilot detection */
+	status = write16(state, OFDM_CP_COMM_EXEC__A, OFDM_CP_COMM_EXEC_STOP);
+	if (status < 0)
+		goto error;
+
+	/*== Write channel settings to device =====================================*/
+
+	/* mode */
+	switch (state->props.transmission_mode) {
+	case TRANSMISSION_MODE_AUTO:
+	default:
+		operationMode |= OFDM_SC_RA_RAM_OP_AUTO_MODE__M;
+		/* fall through , try first guess DRX_FFTMODE_8K */
+	case TRANSMISSION_MODE_8K:
+		transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_MODE_8K;
+		break;
+	case TRANSMISSION_MODE_2K:
+		transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_MODE_2K;
+		break;
+	}
+
+	/* guard */
+	switch (state->props.guard_interval) {
+	default:
+	case GUARD_INTERVAL_AUTO:
+		operationMode |= OFDM_SC_RA_RAM_OP_AUTO_GUARD__M;
+		/* fall through , try first guess DRX_GUARD_1DIV4 */
+	case GUARD_INTERVAL_1_4:
+		transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_4;
+		break;
+	case GUARD_INTERVAL_1_32:
+		transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_32;
+		break;
+	case GUARD_INTERVAL_1_16:
+		transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_16;
+		break;
+	case GUARD_INTERVAL_1_8:
+		transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_8;
+		break;
+	}
+
+	/* hierarchy */
+	switch (state->props.hierarchy) {
+	case HIERARCHY_AUTO:
+	case HIERARCHY_NONE:
+	default:
+		operationMode |= OFDM_SC_RA_RAM_OP_AUTO_HIER__M;
+		/* fall through , try first guess SC_RA_RAM_OP_PARAM_HIER_NO */
+		/* transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_HIER_NO; */
+		/* break; */
+	case HIERARCHY_1:
+		transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_HIER_A1;
+		break;
+	case HIERARCHY_2:
+		transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_HIER_A2;
+		break;
+	case HIERARCHY_4:
+		transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_HIER_A4;
+		break;
+	}
+
+
+	/* modulation */
+	switch (state->props.modulation) {
+	case QAM_AUTO:
+	default:
+		operationMode |= OFDM_SC_RA_RAM_OP_AUTO_CONST__M;
+		/* fall through , try first guess DRX_CONSTELLATION_QAM64 */
+	case QAM_64:
+		transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_CONST_QAM64;
+		break;
+	case QPSK:
+		transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_CONST_QPSK;
+		break;
+	case QAM_16:
+		transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_CONST_QAM16;
+		break;
+	}
+#if 0
+	/* No hierachical channels support in BDA */
+	/* Priority (only for hierarchical channels) */
+	switch (channel->priority) {
+	case DRX_PRIORITY_LOW:
+		transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_PRIO_LO;
+		WR16(devAddr, OFDM_EC_SB_PRIOR__A,
+			OFDM_EC_SB_PRIOR_LO);
+		break;
+	case DRX_PRIORITY_HIGH:
+		transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_PRIO_HI;
+		WR16(devAddr, OFDM_EC_SB_PRIOR__A,
+			OFDM_EC_SB_PRIOR_HI));
+		break;
+	case DRX_PRIORITY_UNKNOWN:	/* fall through */
+	default:
+		status = -EINVAL;
+		goto error;
+	}
+#else
+	/* Set Priorty high */
+	transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_PRIO_HI;
+	status = write16(state, OFDM_EC_SB_PRIOR__A, OFDM_EC_SB_PRIOR_HI);
+	if (status < 0)
+		goto error;
+#endif
+
+	/* coderate */
+	switch (state->props.code_rate_HP) {
+	case FEC_AUTO:
+	default:
+		operationMode |= OFDM_SC_RA_RAM_OP_AUTO_RATE__M;
+		/* fall through , try first guess DRX_CODERATE_2DIV3 */
+	case FEC_2_3:
+		transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_RATE_2_3;
+		break;
+	case FEC_1_2:
+		transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_RATE_1_2;
+		break;
+	case FEC_3_4:
+		transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_RATE_3_4;
+		break;
+	case FEC_5_6:
+		transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_RATE_5_6;
+		break;
+	case FEC_7_8:
+		transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_RATE_7_8;
+		break;
+	}
+
+	/* SAW filter selection: normaly not necesarry, but if wanted
+		the application can select a SAW filter via the driver by using UIOs */
+	/* First determine real bandwidth (Hz) */
+	/* Also set delay for impulse noise cruncher */
+	/* Also set parameters for EC_OC fix, note EC_OC_REG_TMD_HIL_MAR is changed
+		by SC for fix for some 8K,1/8 guard but is restored by InitEC and ResetEC
+		functions */
+	switch (state->props.bandwidth_hz) {
+	case 0:
+		state->props.bandwidth_hz = 8000000;
+		/* fall though */
+	case 8000000:
+		bandwidth = DRXK_BANDWIDTH_8MHZ_IN_HZ;
+		status = write16(state, OFDM_SC_RA_RAM_SRMM_FIX_FACT_8K__A, 3052);
+		if (status < 0)
+			goto error;
+		/* cochannel protection for PAL 8 MHz */
+		status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_LEFT__A, 7);
+		if (status < 0)
+			goto error;
+		status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_RIGHT__A, 7);
+		if (status < 0)
+			goto error;
+		status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_LEFT__A, 7);
+		if (status < 0)
+			goto error;
+		status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_RIGHT__A, 1);
+		if (status < 0)
+			goto error;
+		break;
+	case 7000000:
+		bandwidth = DRXK_BANDWIDTH_7MHZ_IN_HZ;
+		status = write16(state, OFDM_SC_RA_RAM_SRMM_FIX_FACT_8K__A, 3491);
+		if (status < 0)
+			goto error;
+		/* cochannel protection for PAL 7 MHz */
+		status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_LEFT__A, 8);
+		if (status < 0)
+			goto error;
+		status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_RIGHT__A, 8);
+		if (status < 0)
+			goto error;
+		status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_LEFT__A, 4);
+		if (status < 0)
+			goto error;
+		status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_RIGHT__A, 1);
+		if (status < 0)
+			goto error;
+		break;
+	case 6000000:
+		bandwidth = DRXK_BANDWIDTH_6MHZ_IN_HZ;
+		status = write16(state, OFDM_SC_RA_RAM_SRMM_FIX_FACT_8K__A, 4073);
+		if (status < 0)
+			goto error;
+		/* cochannel protection for NTSC 6 MHz */
+		status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_LEFT__A, 19);
+		if (status < 0)
+			goto error;
+		status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_RIGHT__A, 19);
+		if (status < 0)
+			goto error;
+		status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_LEFT__A, 14);
+		if (status < 0)
+			goto error;
+		status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_RIGHT__A, 1);
+		if (status < 0)
+			goto error;
+		break;
+	default:
+		status = -EINVAL;
+		goto error;
+	}
+
+	if (iqmRcRateOfs == 0) {
+		/* Now compute IQM_RC_RATE_OFS
+			(((SysFreq/BandWidth)/2)/2) -1) * 2^23)
+			=>
+			((SysFreq / BandWidth) * (2^21)) - (2^23)
+			*/
+		/* (SysFreq / BandWidth) * (2^28)  */
+		/* assert (MAX(sysClk)/MIN(bandwidth) < 16)
+			=> assert(MAX(sysClk) < 16*MIN(bandwidth))
+			=> assert(109714272 > 48000000) = true so Frac 28 can be used  */
+		iqmRcRateOfs = Frac28a((u32)
+					((state->m_sysClockFreq *
+						1000) / 3), bandwidth);
+		/* (SysFreq / BandWidth) * (2^21), rounding before truncating  */
+		if ((iqmRcRateOfs & 0x7fL) >= 0x40)
+			iqmRcRateOfs += 0x80L;
+		iqmRcRateOfs = iqmRcRateOfs >> 7;
+		/* ((SysFreq / BandWidth) * (2^21)) - (2^23)  */
+		iqmRcRateOfs = iqmRcRateOfs - (1 << 23);
+	}
+
+	iqmRcRateOfs &=
+		((((u32) IQM_RC_RATE_OFS_HI__M) <<
+		IQM_RC_RATE_OFS_LO__W) | IQM_RC_RATE_OFS_LO__M);
+	status = write32(state, IQM_RC_RATE_OFS_LO__A, iqmRcRateOfs);
+	if (status < 0)
+		goto error;
+
+	/* Bandwidth setting done */
+
+#if 0
+	status = DVBTSetFrequencyShift(demod, channel, tunerOffset);
+	if (status < 0)
+		goto error;
+#endif
+	status = SetFrequencyShifter(state, IntermediateFreqkHz, tunerFreqOffset, true);
+	if (status < 0)
+		goto error;
+
+	/*== Start SC, write channel settings to SC ===============================*/
+
+	/* Activate SCU to enable SCU commands */
+	status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_ACTIVE);
+	if (status < 0)
+		goto error;
+
+	/* Enable SC after setting all other parameters */
+	status = write16(state, OFDM_SC_COMM_STATE__A, 0);
+	if (status < 0)
+		goto error;
+	status = write16(state, OFDM_SC_COMM_EXEC__A, 1);
+	if (status < 0)
+		goto error;
+
+
+	status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM | SCU_RAM_COMMAND_CMD_DEMOD_START, 0, NULL, 1, &cmdResult);
+	if (status < 0)
+		goto error;
+
+	/* Write SC parameter registers, set all AUTO flags in operation mode */
+	param1 = (OFDM_SC_RA_RAM_OP_AUTO_MODE__M |
+			OFDM_SC_RA_RAM_OP_AUTO_GUARD__M |
+			OFDM_SC_RA_RAM_OP_AUTO_CONST__M |
+			OFDM_SC_RA_RAM_OP_AUTO_HIER__M |
+			OFDM_SC_RA_RAM_OP_AUTO_RATE__M);
+	status = DVBTScCommand(state, OFDM_SC_RA_RAM_CMD_SET_PREF_PARAM,
+				0, transmissionParams, param1, 0, 0, 0);
+	if (status < 0)
+		goto error;
+
+	if (!state->m_DRXK_A3_ROM_CODE)
+		status = DVBTCtrlSetSqiSpeed(state, &state->m_sqiSpeed);
+error:
+	if (status < 0)
+		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+
+	return status;
+}
+
+
+/*============================================================================*/
+
+/**
+* \brief Retreive lock status .
+* \param demod    Pointer to demodulator instance.
+* \param lockStat Pointer to lock status structure.
+* \return DRXStatus_t.
+*
+*/
+static int GetDVBTLockStatus(struct drxk_state *state, u32 *pLockStatus)
+{
+	int status;
+	const u16 mpeg_lock_mask = (OFDM_SC_RA_RAM_LOCK_MPEG__M |
+				    OFDM_SC_RA_RAM_LOCK_FEC__M);
+	const u16 fec_lock_mask = (OFDM_SC_RA_RAM_LOCK_FEC__M);
+	const u16 demod_lock_mask = OFDM_SC_RA_RAM_LOCK_DEMOD__M;
+
+	u16 ScRaRamLock = 0;
+	u16 ScCommExec = 0;
+
+	dprintk(1, "\n");
+
+	*pLockStatus = NOT_LOCKED;
+	/* driver 0.9.0 */
+	/* Check if SC is running */
+	status = read16(state, OFDM_SC_COMM_EXEC__A, &ScCommExec);
+	if (status < 0)
+		goto end;
+	if (ScCommExec == OFDM_SC_COMM_EXEC_STOP)
+		goto end;
+
+	status = read16(state, OFDM_SC_RA_RAM_LOCK__A, &ScRaRamLock);
+	if (status < 0)
+		goto end;
+
+	if ((ScRaRamLock & mpeg_lock_mask) == mpeg_lock_mask)
+		*pLockStatus = MPEG_LOCK;
+	else if ((ScRaRamLock & fec_lock_mask) == fec_lock_mask)
+		*pLockStatus = FEC_LOCK;
+	else if ((ScRaRamLock & demod_lock_mask) == demod_lock_mask)
+		*pLockStatus = DEMOD_LOCK;
+	else if (ScRaRamLock & OFDM_SC_RA_RAM_LOCK_NODVBT__M)
+		*pLockStatus = NEVER_LOCK;
+end:
+	if (status < 0)
+		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+
+	return status;
+}
+
+static int PowerUpQAM(struct drxk_state *state)
+{
+	enum DRXPowerMode powerMode = DRXK_POWER_DOWN_OFDM;
+	int status;
+
+	dprintk(1, "\n");
+	status = CtrlPowerMode(state, &powerMode);
+	if (status < 0)
+		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+
+	return status;
+}
+
+
+/** Power Down QAM */
+static int PowerDownQAM(struct drxk_state *state)
+{
+	u16 data = 0;
+	u16 cmdResult;
+	int status = 0;
+
+	dprintk(1, "\n");
+	status = read16(state, SCU_COMM_EXEC__A, &data);
+	if (status < 0)
+		goto error;
+	if (data == SCU_COMM_EXEC_ACTIVE) {
+		/*
+			STOP demodulator
+			QAM and HW blocks
+			*/
+		/* stop all comstate->m_exec */
+		status = write16(state, QAM_COMM_EXEC__A, QAM_COMM_EXEC_STOP);
+		if (status < 0)
+			goto error;
+		status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_STOP, 0, NULL, 1, &cmdResult);
+		if (status < 0)
+			goto error;
+	}
+	/* powerdown AFE                   */
+	status = SetIqmAf(state, false);
+
+error:
+	if (status < 0)
+		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+
+	return status;
+}
+
+/*============================================================================*/
+
+/**
+* \brief Setup of the QAM Measurement intervals for signal quality
+* \param demod instance of demod.
+* \param modulation current modulation.
+* \return DRXStatus_t.
+*
+*  NOTE:
+*  Take into account that for certain settings the errorcounters can overflow.
+*  The implementation does not check this.
+*
+*/
+static int SetQAMMeasurement(struct drxk_state *state,
+			     enum EDrxkConstellation modulation,
+			     u32 symbolRate)
+{
+	u32 fecBitsDesired = 0;	/* BER accounting period */
+	u32 fecRsPeriodTotal = 0;	/* Total period */
+	u16 fecRsPrescale = 0;	/* ReedSolomon Measurement Prescale */
+	u16 fecRsPeriod = 0;	/* Value for corresponding I2C register */
+	int status = 0;
+
+	dprintk(1, "\n");
+
+	fecRsPrescale = 1;
+	/* fecBitsDesired = symbolRate [kHz] *
+		FrameLenght [ms] *
+		(modulation + 1) *
+		SyncLoss (== 1) *
+		ViterbiLoss (==1)
+		*/
+	switch (modulation) {
+	case DRX_CONSTELLATION_QAM16:
+		fecBitsDesired = 4 * symbolRate;
+		break;
+	case DRX_CONSTELLATION_QAM32:
+		fecBitsDesired = 5 * symbolRate;
+		break;
+	case DRX_CONSTELLATION_QAM64:
+		fecBitsDesired = 6 * symbolRate;
+		break;
+	case DRX_CONSTELLATION_QAM128:
+		fecBitsDesired = 7 * symbolRate;
+		break;
+	case DRX_CONSTELLATION_QAM256:
+		fecBitsDesired = 8 * symbolRate;
+		break;
+	default:
+		status = -EINVAL;
+	}
+	if (status < 0)
+		goto error;
+
+	fecBitsDesired /= 1000;	/* symbolRate [Hz] -> symbolRate [kHz]  */
+	fecBitsDesired *= 500;	/* meas. period [ms] */
+
+	/* Annex A/C: bits/RsPeriod = 204 * 8 = 1632 */
+	/* fecRsPeriodTotal = fecBitsDesired / 1632 */
+	fecRsPeriodTotal = (fecBitsDesired / 1632UL) + 1;	/* roughly ceil */
+
+	/* fecRsPeriodTotal =  fecRsPrescale * fecRsPeriod  */
+	fecRsPrescale = 1 + (u16) (fecRsPeriodTotal >> 16);
+	if (fecRsPrescale == 0) {
+		/* Divide by zero (though impossible) */
+		status = -EINVAL;
+		if (status < 0)
+			goto error;
+	}
+	fecRsPeriod =
+		((u16) fecRsPeriodTotal +
+		(fecRsPrescale >> 1)) / fecRsPrescale;
+
+	/* write corresponding registers */
+	status = write16(state, FEC_RS_MEASUREMENT_PERIOD__A, fecRsPeriod);
+	if (status < 0)
+		goto error;
+	status = write16(state, FEC_RS_MEASUREMENT_PRESCALE__A, fecRsPrescale);
+	if (status < 0)
+		goto error;
+	status = write16(state, FEC_OC_SNC_FAIL_PERIOD__A, fecRsPeriod);
+error:
+	if (status < 0)
+		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+	return status;
+}
+
+static int SetQAM16(struct drxk_state *state)
+{
+	int status = 0;
+
+	dprintk(1, "\n");
+	/* QAM Equalizer Setup */
+	/* Equalizer */
+	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD0__A, 13517);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD1__A, 13517);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD2__A, 13517);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD3__A, 13517);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD4__A, 13517);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD5__A, 13517);
+	if (status < 0)
+		goto error;
+	/* Decision Feedback Equalizer */
+	status = write16(state, QAM_DQ_QUAL_FUN0__A, 2);
+	if (status < 0)
+		goto error;
+	status = write16(state, QAM_DQ_QUAL_FUN1__A, 2);
+	if (status < 0)
+		goto error;
+	status = write16(state, QAM_DQ_QUAL_FUN2__A, 2);
+	if (status < 0)
+		goto error;
+	status = write16(state, QAM_DQ_QUAL_FUN3__A, 2);
+	if (status < 0)
+		goto error;
+	status = write16(state, QAM_DQ_QUAL_FUN4__A, 2);
+	if (status < 0)
+		goto error;
+	status = write16(state, QAM_DQ_QUAL_FUN5__A, 0);
+	if (status < 0)
+		goto error;
+
+	status = write16(state, QAM_SY_SYNC_HWM__A, 5);
+	if (status < 0)
+		goto error;
+	status = write16(state, QAM_SY_SYNC_AWM__A, 4);
+	if (status < 0)
+		goto error;
+	status = write16(state, QAM_SY_SYNC_LWM__A, 3);
+	if (status < 0)
+		goto error;
+
+	/* QAM Slicer Settings */
+	status = write16(state, SCU_RAM_QAM_SL_SIG_POWER__A, DRXK_QAM_SL_SIG_POWER_QAM16);
+	if (status < 0)
+		goto error;
+
+	/* QAM Loop Controller Coeficients */
+	status = write16(state, SCU_RAM_QAM_LC_CA_FINE__A, 15);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_CA_COARSE__A, 40);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_EP_FINE__A, 12);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_EP_MEDIUM__A, 24);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_EP_COARSE__A, 24);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_EI_FINE__A, 12);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_EI_MEDIUM__A, 16);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_EI_COARSE__A, 16);
+	if (status < 0)
+		goto error;
+
+	status = write16(state, SCU_RAM_QAM_LC_CP_FINE__A, 5);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_CP_MEDIUM__A, 20);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_CP_COARSE__A, 80);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_CI_FINE__A, 5);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_CI_MEDIUM__A, 20);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_CI_COARSE__A, 50);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_CF_FINE__A, 16);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_CF_MEDIUM__A, 16);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_CF_COARSE__A, 32);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_CF1_FINE__A, 5);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_CF1_MEDIUM__A, 10);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_CF1_COARSE__A, 10);
+	if (status < 0)
+		goto error;
+
+
+	/* QAM State Machine (FSM) Thresholds */
+
+	status = write16(state, SCU_RAM_QAM_FSM_RTH__A, 140);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_FSM_FTH__A, 50);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_FSM_CTH__A, 95);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_FSM_PTH__A, 120);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_FSM_QTH__A, 230);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_FSM_MTH__A, 105);
+	if (status < 0)
+		goto error;
+
+	status = write16(state, SCU_RAM_QAM_FSM_RATE_LIM__A, 40);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_FSM_COUNT_LIM__A, 4);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_FSM_FREQ_LIM__A, 24);
+	if (status < 0)
+		goto error;
+
+
+	/* QAM FSM Tracking Parameters */
+
+	status = write16(state, SCU_RAM_QAM_FSM_MEDIAN_AV_MULT__A, (u16) 16);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_FSM_RADIUS_AV_LIMIT__A, (u16) 220);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET1__A, (u16) 25);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET2__A, (u16) 6);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET3__A, (u16) -24);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET4__A, (u16) -65);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16) -127);
+	if (status < 0)
+		goto error;
+
+error:
+	if (status < 0)
+		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+	return status;
+}
+
+/*============================================================================*/
+
+/**
+* \brief QAM32 specific setup
+* \param demod instance of demod.
+* \return DRXStatus_t.
+*/
+static int SetQAM32(struct drxk_state *state)
+{
+	int status = 0;
+
+	dprintk(1, "\n");
+
+	/* QAM Equalizer Setup */
+	/* Equalizer */
+	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD0__A, 6707);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD1__A, 6707);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD2__A, 6707);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD3__A, 6707);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD4__A, 6707);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD5__A, 6707);
+	if (status < 0)
+		goto error;
+
+	/* Decision Feedback Equalizer */
+	status = write16(state, QAM_DQ_QUAL_FUN0__A, 3);
+	if (status < 0)
+		goto error;
+	status = write16(state, QAM_DQ_QUAL_FUN1__A, 3);
+	if (status < 0)
+		goto error;
+	status = write16(state, QAM_DQ_QUAL_FUN2__A, 3);
+	if (status < 0)
+		goto error;
+	status = write16(state, QAM_DQ_QUAL_FUN3__A, 3);
+	if (status < 0)
+		goto error;
+	status = write16(state, QAM_DQ_QUAL_FUN4__A, 3);
+	if (status < 0)
+		goto error;
+	status = write16(state, QAM_DQ_QUAL_FUN5__A, 0);
+	if (status < 0)
+		goto error;
+
+	status = write16(state, QAM_SY_SYNC_HWM__A, 6);
+	if (status < 0)
+		goto error;
+	status = write16(state, QAM_SY_SYNC_AWM__A, 5);
+	if (status < 0)
+		goto error;
+	status = write16(state, QAM_SY_SYNC_LWM__A, 3);
+	if (status < 0)
+		goto error;
+
+	/* QAM Slicer Settings */
+
+	status = write16(state, SCU_RAM_QAM_SL_SIG_POWER__A, DRXK_QAM_SL_SIG_POWER_QAM32);
+	if (status < 0)
+		goto error;
+
+
+	/* QAM Loop Controller Coeficients */
+
+	status = write16(state, SCU_RAM_QAM_LC_CA_FINE__A, 15);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_CA_COARSE__A, 40);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_EP_FINE__A, 12);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_EP_MEDIUM__A, 24);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_EP_COARSE__A, 24);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_EI_FINE__A, 12);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_EI_MEDIUM__A, 16);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_EI_COARSE__A, 16);
+	if (status < 0)
+		goto error;
+
+	status = write16(state, SCU_RAM_QAM_LC_CP_FINE__A, 5);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_CP_MEDIUM__A, 20);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_CP_COARSE__A, 80);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_CI_FINE__A, 5);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_CI_MEDIUM__A, 20);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_CI_COARSE__A, 50);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_CF_FINE__A, 16);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_CF_MEDIUM__A, 16);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_CF_COARSE__A, 16);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_CF1_FINE__A, 5);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_CF1_MEDIUM__A, 10);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_CF1_COARSE__A, 0);
+	if (status < 0)
+		goto error;
+
+
+	/* QAM State Machine (FSM) Thresholds */
+
+	status = write16(state, SCU_RAM_QAM_FSM_RTH__A, 90);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_FSM_FTH__A, 50);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_FSM_CTH__A, 80);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_FSM_PTH__A, 100);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_FSM_QTH__A, 170);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_FSM_MTH__A, 100);
+	if (status < 0)
+		goto error;
+
+	status = write16(state, SCU_RAM_QAM_FSM_RATE_LIM__A, 40);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_FSM_COUNT_LIM__A, 4);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_FSM_FREQ_LIM__A, 10);
+	if (status < 0)
+		goto error;
+
+
+	/* QAM FSM Tracking Parameters */
+
+	status = write16(state, SCU_RAM_QAM_FSM_MEDIAN_AV_MULT__A, (u16) 12);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_FSM_RADIUS_AV_LIMIT__A, (u16) 140);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET1__A, (u16) -8);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET2__A, (u16) -16);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET3__A, (u16) -26);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET4__A, (u16) -56);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16) -86);
+error:
+	if (status < 0)
+		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+	return status;
+}
+
+/*============================================================================*/
+
+/**
+* \brief QAM64 specific setup
+* \param demod instance of demod.
+* \return DRXStatus_t.
+*/
+static int SetQAM64(struct drxk_state *state)
+{
+	int status = 0;
+
+	dprintk(1, "\n");
+	/* QAM Equalizer Setup */
+	/* Equalizer */
+	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD0__A, 13336);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD1__A, 12618);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD2__A, 11988);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD3__A, 13809);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD4__A, 13809);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD5__A, 15609);
+	if (status < 0)
+		goto error;
+
+	/* Decision Feedback Equalizer */
+	status = write16(state, QAM_DQ_QUAL_FUN0__A, 4);
+	if (status < 0)
+		goto error;
+	status = write16(state, QAM_DQ_QUAL_FUN1__A, 4);
+	if (status < 0)
+		goto error;
+	status = write16(state, QAM_DQ_QUAL_FUN2__A, 4);
+	if (status < 0)
+		goto error;
+	status = write16(state, QAM_DQ_QUAL_FUN3__A, 4);
+	if (status < 0)
+		goto error;
+	status = write16(state, QAM_DQ_QUAL_FUN4__A, 3);
+	if (status < 0)
+		goto error;
+	status = write16(state, QAM_DQ_QUAL_FUN5__A, 0);
+	if (status < 0)
+		goto error;
+
+	status = write16(state, QAM_SY_SYNC_HWM__A, 5);
+	if (status < 0)
+		goto error;
+	status = write16(state, QAM_SY_SYNC_AWM__A, 4);
+	if (status < 0)
+		goto error;
+	status = write16(state, QAM_SY_SYNC_LWM__A, 3);
+	if (status < 0)
+		goto error;
+
+	/* QAM Slicer Settings */
+	status = write16(state, SCU_RAM_QAM_SL_SIG_POWER__A, DRXK_QAM_SL_SIG_POWER_QAM64);
+	if (status < 0)
+		goto error;
+
+
+	/* QAM Loop Controller Coeficients */
+
+	status = write16(state, SCU_RAM_QAM_LC_CA_FINE__A, 15);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_CA_COARSE__A, 40);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_EP_FINE__A, 12);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_EP_MEDIUM__A, 24);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_EP_COARSE__A, 24);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_EI_FINE__A, 12);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_EI_MEDIUM__A, 16);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_EI_COARSE__A, 16);
+	if (status < 0)
+		goto error;
+
+	status = write16(state, SCU_RAM_QAM_LC_CP_FINE__A, 5);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_CP_MEDIUM__A, 30);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_CP_COARSE__A, 100);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_CI_FINE__A, 5);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_CI_MEDIUM__A, 30);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_CI_COARSE__A, 50);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_CF_FINE__A, 16);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_CF_MEDIUM__A, 25);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_CF_COARSE__A, 48);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_CF1_FINE__A, 5);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_CF1_MEDIUM__A, 10);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_CF1_COARSE__A, 10);
+	if (status < 0)
+		goto error;
+
+
+	/* QAM State Machine (FSM) Thresholds */
+
+	status = write16(state, SCU_RAM_QAM_FSM_RTH__A, 100);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_FSM_FTH__A, 60);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_FSM_CTH__A, 80);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_FSM_PTH__A, 110);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_FSM_QTH__A, 200);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_FSM_MTH__A, 95);
+	if (status < 0)
+		goto error;
+
+	status = write16(state, SCU_RAM_QAM_FSM_RATE_LIM__A, 40);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_FSM_COUNT_LIM__A, 4);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_FSM_FREQ_LIM__A, 15);
+	if (status < 0)
+		goto error;
+
+
+	/* QAM FSM Tracking Parameters */
+
+	status = write16(state, SCU_RAM_QAM_FSM_MEDIAN_AV_MULT__A, (u16) 12);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_FSM_RADIUS_AV_LIMIT__A, (u16) 141);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET1__A, (u16) 7);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET2__A, (u16) 0);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET3__A, (u16) -15);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET4__A, (u16) -45);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16) -80);
+error:
+	if (status < 0)
+		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+
+	return status;
+}
+
+/*============================================================================*/
+
+/**
+* \brief QAM128 specific setup
+* \param demod: instance of demod.
+* \return DRXStatus_t.
+*/
+static int SetQAM128(struct drxk_state *state)
+{
+	int status = 0;
+
+	dprintk(1, "\n");
+	/* QAM Equalizer Setup */
+	/* Equalizer */
+	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD0__A, 6564);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD1__A, 6598);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD2__A, 6394);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD3__A, 6409);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD4__A, 6656);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD5__A, 7238);
+	if (status < 0)
+		goto error;
+
+	/* Decision Feedback Equalizer */
+	status = write16(state, QAM_DQ_QUAL_FUN0__A, 6);
+	if (status < 0)
+		goto error;
+	status = write16(state, QAM_DQ_QUAL_FUN1__A, 6);
+	if (status < 0)
+		goto error;
+	status = write16(state, QAM_DQ_QUAL_FUN2__A, 6);
+	if (status < 0)
+		goto error;
+	status = write16(state, QAM_DQ_QUAL_FUN3__A, 6);
+	if (status < 0)
+		goto error;
+	status = write16(state, QAM_DQ_QUAL_FUN4__A, 5);
+	if (status < 0)
+		goto error;
+	status = write16(state, QAM_DQ_QUAL_FUN5__A, 0);
+	if (status < 0)
+		goto error;
+
+	status = write16(state, QAM_SY_SYNC_HWM__A, 6);
+	if (status < 0)
+		goto error;
+	status = write16(state, QAM_SY_SYNC_AWM__A, 5);
+	if (status < 0)
+		goto error;
+	status = write16(state, QAM_SY_SYNC_LWM__A, 3);
+	if (status < 0)
+		goto error;
+
+
+	/* QAM Slicer Settings */
+
+	status = write16(state, SCU_RAM_QAM_SL_SIG_POWER__A, DRXK_QAM_SL_SIG_POWER_QAM128);
+	if (status < 0)
+		goto error;
+
+
+	/* QAM Loop Controller Coeficients */
+
+	status = write16(state, SCU_RAM_QAM_LC_CA_FINE__A, 15);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_CA_COARSE__A, 40);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_EP_FINE__A, 12);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_EP_MEDIUM__A, 24);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_EP_COARSE__A, 24);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_EI_FINE__A, 12);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_EI_MEDIUM__A, 16);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_EI_COARSE__A, 16);
+	if (status < 0)
+		goto error;
+
+	status = write16(state, SCU_RAM_QAM_LC_CP_FINE__A, 5);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_CP_MEDIUM__A, 40);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_CP_COARSE__A, 120);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_CI_FINE__A, 5);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_CI_MEDIUM__A, 40);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_CI_COARSE__A, 60);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_CF_FINE__A, 16);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_CF_MEDIUM__A, 25);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_CF_COARSE__A, 64);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_CF1_FINE__A, 5);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_CF1_MEDIUM__A, 10);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_CF1_COARSE__A, 0);
+	if (status < 0)
+		goto error;
+
+
+	/* QAM State Machine (FSM) Thresholds */
+
+	status = write16(state, SCU_RAM_QAM_FSM_RTH__A, 50);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_FSM_FTH__A, 60);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_FSM_CTH__A, 80);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_FSM_PTH__A, 100);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_FSM_QTH__A, 140);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_FSM_MTH__A, 100);
+	if (status < 0)
+		goto error;
+
+	status = write16(state, SCU_RAM_QAM_FSM_RATE_LIM__A, 40);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_FSM_COUNT_LIM__A, 5);
+	if (status < 0)
+		goto error;
+
+	status = write16(state, SCU_RAM_QAM_FSM_FREQ_LIM__A, 12);
+	if (status < 0)
+		goto error;
+
+	/* QAM FSM Tracking Parameters */
+
+	status = write16(state, SCU_RAM_QAM_FSM_MEDIAN_AV_MULT__A, (u16) 8);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_FSM_RADIUS_AV_LIMIT__A, (u16) 65);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET1__A, (u16) 5);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET2__A, (u16) 3);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET3__A, (u16) -1);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET4__A, (u16) -12);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16) -23);
+error:
+	if (status < 0)
+		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+
+	return status;
+}
+
+/*============================================================================*/
+
+/**
+* \brief QAM256 specific setup
+* \param demod: instance of demod.
+* \return DRXStatus_t.
+*/
+static int SetQAM256(struct drxk_state *state)
+{
+	int status = 0;
+
+	dprintk(1, "\n");
+	/* QAM Equalizer Setup */
+	/* Equalizer */
+	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD0__A, 11502);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD1__A, 12084);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD2__A, 12543);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD3__A, 12931);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD4__A, 13629);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD5__A, 15385);
+	if (status < 0)
+		goto error;
+
+	/* Decision Feedback Equalizer */
+	status = write16(state, QAM_DQ_QUAL_FUN0__A, 8);
+	if (status < 0)
+		goto error;
+	status = write16(state, QAM_DQ_QUAL_FUN1__A, 8);
+	if (status < 0)
+		goto error;
+	status = write16(state, QAM_DQ_QUAL_FUN2__A, 8);
+	if (status < 0)
+		goto error;
+	status = write16(state, QAM_DQ_QUAL_FUN3__A, 8);
+	if (status < 0)
+		goto error;
+	status = write16(state, QAM_DQ_QUAL_FUN4__A, 6);
+	if (status < 0)
+		goto error;
+	status = write16(state, QAM_DQ_QUAL_FUN5__A, 0);
+	if (status < 0)
+		goto error;
+
+	status = write16(state, QAM_SY_SYNC_HWM__A, 5);
+	if (status < 0)
+		goto error;
+	status = write16(state, QAM_SY_SYNC_AWM__A, 4);
+	if (status < 0)
+		goto error;
+	status = write16(state, QAM_SY_SYNC_LWM__A, 3);
+	if (status < 0)
+		goto error;
+
+	/* QAM Slicer Settings */
+
+	status = write16(state, SCU_RAM_QAM_SL_SIG_POWER__A, DRXK_QAM_SL_SIG_POWER_QAM256);
+	if (status < 0)
+		goto error;
+
+
+	/* QAM Loop Controller Coeficients */
+
+	status = write16(state, SCU_RAM_QAM_LC_CA_FINE__A, 15);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_CA_COARSE__A, 40);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_EP_FINE__A, 12);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_EP_MEDIUM__A, 24);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_EP_COARSE__A, 24);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_EI_FINE__A, 12);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_EI_MEDIUM__A, 16);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_EI_COARSE__A, 16);
+	if (status < 0)
+		goto error;
+
+	status = write16(state, SCU_RAM_QAM_LC_CP_FINE__A, 5);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_CP_MEDIUM__A, 50);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_CP_COARSE__A, 250);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_CI_FINE__A, 5);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_CI_MEDIUM__A, 50);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_CI_COARSE__A, 125);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_CF_FINE__A, 16);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_CF_MEDIUM__A, 25);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_CF_COARSE__A, 48);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_CF1_FINE__A, 5);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_CF1_MEDIUM__A, 10);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_LC_CF1_COARSE__A, 10);
+	if (status < 0)
+		goto error;
+
+
+	/* QAM State Machine (FSM) Thresholds */
+
+	status = write16(state, SCU_RAM_QAM_FSM_RTH__A, 50);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_FSM_FTH__A, 60);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_FSM_CTH__A, 80);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_FSM_PTH__A, 100);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_FSM_QTH__A, 150);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_FSM_MTH__A, 110);
+	if (status < 0)
+		goto error;
+
+	status = write16(state, SCU_RAM_QAM_FSM_RATE_LIM__A, 40);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_FSM_COUNT_LIM__A, 4);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_FSM_FREQ_LIM__A, 12);
+	if (status < 0)
+		goto error;
+
+
+	/* QAM FSM Tracking Parameters */
+
+	status = write16(state, SCU_RAM_QAM_FSM_MEDIAN_AV_MULT__A, (u16) 8);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_FSM_RADIUS_AV_LIMIT__A, (u16) 74);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET1__A, (u16) 18);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET2__A, (u16) 13);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET3__A, (u16) 7);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET4__A, (u16) 0);
+	if (status < 0)
+		goto error;
+	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16) -8);
+error:
+	if (status < 0)
+		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+	return status;
+}
+
+
+/*============================================================================*/
+/**
+* \brief Reset QAM block.
+* \param demod:   instance of demod.
+* \param channel: pointer to channel data.
+* \return DRXStatus_t.
+*/
+static int QAMResetQAM(struct drxk_state *state)
+{
+	int status;
+	u16 cmdResult;
+
+	dprintk(1, "\n");
+	/* Stop QAM comstate->m_exec */
+	status = write16(state, QAM_COMM_EXEC__A, QAM_COMM_EXEC_STOP);
+	if (status < 0)
+		goto error;
+
+	status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_RESET, 0, NULL, 1, &cmdResult);
+error:
+	if (status < 0)
+		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+	return status;
+}
+
+/*============================================================================*/
+
+/**
+* \brief Set QAM symbolrate.
+* \param demod:   instance of demod.
+* \param channel: pointer to channel data.
+* \return DRXStatus_t.
+*/
+static int QAMSetSymbolrate(struct drxk_state *state)
+{
+	u32 adcFrequency = 0;
+	u32 symbFreq = 0;
+	u32 iqmRcRate = 0;
+	u16 ratesel = 0;
+	u32 lcSymbRate = 0;
+	int status;
+
+	dprintk(1, "\n");
+	/* Select & calculate correct IQM rate */
+	adcFrequency = (state->m_sysClockFreq * 1000) / 3;
+	ratesel = 0;
+	/* printk(KERN_DEBUG "drxk: SR %d\n", state->props.symbol_rate); */
+	if (state->props.symbol_rate <= 1188750)
+		ratesel = 3;
+	else if (state->props.symbol_rate <= 2377500)
+		ratesel = 2;
+	else if (state->props.symbol_rate <= 4755000)
+		ratesel = 1;
+	status = write16(state, IQM_FD_RATESEL__A, ratesel);
+	if (status < 0)
+		goto error;
+
+	/*
+		IqmRcRate = ((Fadc / (symbolrate * (4<<ratesel))) - 1) * (1<<23)
+		*/
+	symbFreq = state->props.symbol_rate * (1 << ratesel);
+	if (symbFreq == 0) {
+		/* Divide by zero */
+		status = -EINVAL;
+		goto error;
+	}
+	iqmRcRate = (adcFrequency / symbFreq) * (1 << 21) +
+		(Frac28a((adcFrequency % symbFreq), symbFreq) >> 7) -
+		(1 << 23);
+	status = write32(state, IQM_RC_RATE_OFS_LO__A, iqmRcRate);
+	if (status < 0)
+		goto error;
+	state->m_iqmRcRate = iqmRcRate;
+	/*
+		LcSymbFreq = round (.125 *  symbolrate / adcFreq * (1<<15))
+		*/
+	symbFreq = state->props.symbol_rate;
+	if (adcFrequency == 0) {
+		/* Divide by zero */
+		status = -EINVAL;
+		goto error;
+	}
+	lcSymbRate = (symbFreq / adcFrequency) * (1 << 12) +
+		(Frac28a((symbFreq % adcFrequency), adcFrequency) >>
+		16);
+	if (lcSymbRate > 511)
+		lcSymbRate = 511;
+	status = write16(state, QAM_LC_SYMBOL_FREQ__A, (u16) lcSymbRate);
+
+error:
+	if (status < 0)
+		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+	return status;
+}
+
+/*============================================================================*/
+
+/**
+* \brief Get QAM lock status.
+* \param demod:   instance of demod.
+* \param channel: pointer to channel data.
+* \return DRXStatus_t.
+*/
+
+static int GetQAMLockStatus(struct drxk_state *state, u32 *pLockStatus)
+{
+	int status;
+	u16 Result[2] = { 0, 0 };
+
+	dprintk(1, "\n");
+	*pLockStatus = NOT_LOCKED;
+	status = scu_command(state,
+			SCU_RAM_COMMAND_STANDARD_QAM |
+			SCU_RAM_COMMAND_CMD_DEMOD_GET_LOCK, 0, NULL, 2,
+			Result);
+	if (status < 0)
+		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+
+	if (Result[1] < SCU_RAM_QAM_LOCKED_LOCKED_DEMOD_LOCKED) {
+		/* 0x0000 NOT LOCKED */
+	} else if (Result[1] < SCU_RAM_QAM_LOCKED_LOCKED_LOCKED) {
+		/* 0x4000 DEMOD LOCKED */
+		*pLockStatus = DEMOD_LOCK;
+	} else if (Result[1] < SCU_RAM_QAM_LOCKED_LOCKED_NEVER_LOCK) {
+		/* 0x8000 DEMOD + FEC LOCKED (system lock) */
+		*pLockStatus = MPEG_LOCK;
+	} else {
+		/* 0xC000 NEVER LOCKED */
+		/* (system will never be able to lock to the signal) */
+		/* TODO: check this, intermediate & standard specific lock states are not
+		   taken into account here */
+		*pLockStatus = NEVER_LOCK;
+	}
+	return status;
+}
+
+#define QAM_MIRROR__M         0x03
+#define QAM_MIRROR_NORMAL     0x00
+#define QAM_MIRRORED          0x01
+#define QAM_MIRROR_AUTO_ON    0x02
+#define QAM_LOCKRANGE__M      0x10
+#define QAM_LOCKRANGE_NORMAL  0x10
+
+static int QAMDemodulatorCommand(struct drxk_state *state,
+				 int numberOfParameters)
+{
+	int status;
+	u16 cmdResult;
+	u16 setParamParameters[4] = { 0, 0, 0, 0 };
+
+	setParamParameters[0] = state->m_Constellation;	/* modulation     */
+	setParamParameters[1] = DRXK_QAM_I12_J17;	/* interleave mode   */
+
+	if (numberOfParameters == 2) {
+		u16 setEnvParameters[1] = { 0 };
+
+		if (state->m_OperationMode == OM_QAM_ITU_C)
+			setEnvParameters[0] = QAM_TOP_ANNEX_C;
+		else
+			setEnvParameters[0] = QAM_TOP_ANNEX_A;
+
+		status = scu_command(state,
+				     SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_SET_ENV,
+				     1, setEnvParameters, 1, &cmdResult);
+		if (status < 0)
+			goto error;
+
+		status = scu_command(state,
+				     SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_SET_PARAM,
+				     numberOfParameters, setParamParameters,
+				     1, &cmdResult);
+	} else if (numberOfParameters == 4) {
+		if (state->m_OperationMode == OM_QAM_ITU_C)
+			setParamParameters[2] = QAM_TOP_ANNEX_C;
+		else
+			setParamParameters[2] = QAM_TOP_ANNEX_A;
+
+		setParamParameters[3] |= (QAM_MIRROR_AUTO_ON);
+		/* Env parameters */
+		/* check for LOCKRANGE Extented */
+		/* setParamParameters[3] |= QAM_LOCKRANGE_NORMAL; */
+
+		status = scu_command(state,
+				     SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_SET_PARAM,
+				     numberOfParameters, setParamParameters,
+				     1, &cmdResult);
+	} else {
+		printk(KERN_WARNING "drxk: Unknown QAM demodulator parameter "
+			"count %d\n", numberOfParameters);
+	}
+
+error:
+	if (status < 0)
+		printk(KERN_WARNING "drxk: Warning %d on %s\n",
+		       status, __func__);
+	return status;
+}
+
+static int SetQAM(struct drxk_state *state, u16 IntermediateFreqkHz,
+		  s32 tunerFreqOffset)
+{
+	int status;
+	u16 cmdResult;
+	int qamDemodParamCount = state->qam_demod_parameter_count;
+
+	dprintk(1, "\n");
+	/*
+	 * STEP 1: reset demodulator
+	 *	resets FEC DI and FEC RS
+	 *	resets QAM block
+	 *	resets SCU variables
+	 */
+	status = write16(state, FEC_DI_COMM_EXEC__A, FEC_DI_COMM_EXEC_STOP);
+	if (status < 0)
+		goto error;
+	status = write16(state, FEC_RS_COMM_EXEC__A, FEC_RS_COMM_EXEC_STOP);
+	if (status < 0)
+		goto error;
+	status = QAMResetQAM(state);
+	if (status < 0)
+		goto error;
+
+	/*
+	 * STEP 2: configure demodulator
+	 *	-set params; resets IQM,QAM,FEC HW; initializes some
+	 *       SCU variables
+	 */
+	status = QAMSetSymbolrate(state);
+	if (status < 0)
+		goto error;
+
+	/* Set params */
+	switch (state->props.modulation) {
+	case QAM_256:
+		state->m_Constellation = DRX_CONSTELLATION_QAM256;
+		break;
+	case QAM_AUTO:
+	case QAM_64:
+		state->m_Constellation = DRX_CONSTELLATION_QAM64;
+		break;
+	case QAM_16:
+		state->m_Constellation = DRX_CONSTELLATION_QAM16;
+		break;
+	case QAM_32:
+		state->m_Constellation = DRX_CONSTELLATION_QAM32;
+		break;
+	case QAM_128:
+		state->m_Constellation = DRX_CONSTELLATION_QAM128;
+		break;
+	default:
+		status = -EINVAL;
+		break;
+	}
+	if (status < 0)
+		goto error;
+
+	/* Use the 4-parameter if it's requested or we're probing for
+	 * the correct command. */
+	if (state->qam_demod_parameter_count == 4
+		|| !state->qam_demod_parameter_count) {
+		qamDemodParamCount = 4;
+		status = QAMDemodulatorCommand(state, qamDemodParamCount);
+	}
+
+	/* Use the 2-parameter command if it was requested or if we're
+	 * probing for the correct command and the 4-parameter command
+	 * failed. */
+	if (state->qam_demod_parameter_count == 2
+		|| (!state->qam_demod_parameter_count && status < 0)) {
+		qamDemodParamCount = 2;
+		status = QAMDemodulatorCommand(state, qamDemodParamCount);
+	}
+
+	if (status < 0) {
+		dprintk(1, "Could not set demodulator parameters. Make "
+			"sure qam_demod_parameter_count (%d) is correct for "
+			"your firmware (%s).\n",
+			state->qam_demod_parameter_count,
+			state->microcode_name);
+		goto error;
+	} else if (!state->qam_demod_parameter_count) {
+		dprintk(1, "Auto-probing the correct QAM demodulator command "
+			"parameters was successful - using %d parameters.\n",
+			qamDemodParamCount);
+
+		/*
+		 * One of our commands was successful. We don't need to
+		 * auto-probe anymore, now that we got the correct command.
+		 */
+		state->qam_demod_parameter_count = qamDemodParamCount;
+	}
+
+	/*
+	 * STEP 3: enable the system in a mode where the ADC provides valid
+	 * signal setup modulation independent registers
+	 */
+#if 0
+	status = SetFrequency(channel, tunerFreqOffset));
+	if (status < 0)
+		goto error;
+#endif
+	status = SetFrequencyShifter(state, IntermediateFreqkHz, tunerFreqOffset, true);
+	if (status < 0)
+		goto error;
+
+	/* Setup BER measurement */
+	status = SetQAMMeasurement(state, state->m_Constellation, state->props.symbol_rate);
+	if (status < 0)
+		goto error;
+
+	/* Reset default values */
+	status = write16(state, IQM_CF_SCALE_SH__A, IQM_CF_SCALE_SH__PRE);
+	if (status < 0)
+		goto error;
+	status = write16(state, QAM_SY_TIMEOUT__A, QAM_SY_TIMEOUT__PRE);
+	if (status < 0)
+		goto error;
+
+	/* Reset default LC values */
+	status = write16(state, QAM_LC_RATE_LIMIT__A, 3);
+	if (status < 0)
+		goto error;
+	status = write16(state, QAM_LC_LPF_FACTORP__A, 4);
+	if (status < 0)
+		goto error;
+	status = write16(state, QAM_LC_LPF_FACTORI__A, 4);
+	if (status < 0)
+		goto error;
+	status = write16(state, QAM_LC_MODE__A, 7);
+	if (status < 0)
+		goto error;
+
+	status = write16(state, QAM_LC_QUAL_TAB0__A, 1);
+	if (status < 0)
+		goto error;
+	status = write16(state, QAM_LC_QUAL_TAB1__A, 1);
+	if (status < 0)
+		goto error;
+	status = write16(state, QAM_LC_QUAL_TAB2__A, 1);
+	if (status < 0)
+		goto error;
+	status = write16(state, QAM_LC_QUAL_TAB3__A, 1);
+	if (status < 0)
+		goto error;
+	status = write16(state, QAM_LC_QUAL_TAB4__A, 2);
+	if (status < 0)
+		goto error;
+	status = write16(state, QAM_LC_QUAL_TAB5__A, 2);
+	if (status < 0)
+		goto error;
+	status = write16(state, QAM_LC_QUAL_TAB6__A, 2);
+	if (status < 0)
+		goto error;
+	status = write16(state, QAM_LC_QUAL_TAB8__A, 2);
+	if (status < 0)
+		goto error;
+	status = write16(state, QAM_LC_QUAL_TAB9__A, 2);
+	if (status < 0)
+		goto error;
+	status = write16(state, QAM_LC_QUAL_TAB10__A, 2);
+	if (status < 0)
+		goto error;
+	status = write16(state, QAM_LC_QUAL_TAB12__A, 2);
+	if (status < 0)
+		goto error;
+	status = write16(state, QAM_LC_QUAL_TAB15__A, 3);
+	if (status < 0)
+		goto error;
+	status = write16(state, QAM_LC_QUAL_TAB16__A, 3);
+	if (status < 0)
+		goto error;
+	status = write16(state, QAM_LC_QUAL_TAB20__A, 4);
+	if (status < 0)
+		goto error;
+	status = write16(state, QAM_LC_QUAL_TAB25__A, 4);
+	if (status < 0)
+		goto error;
+
+	/* Mirroring, QAM-block starting point not inverted */
+	status = write16(state, QAM_SY_SP_INV__A, QAM_SY_SP_INV_SPECTRUM_INV_DIS);
+	if (status < 0)
+		goto error;
+
+	/* Halt SCU to enable safe non-atomic accesses */
+	status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_HOLD);
+	if (status < 0)
+		goto error;
+
+	/* STEP 4: modulation specific setup */
+	switch (state->props.modulation) {
+	case QAM_16:
+		status = SetQAM16(state);
+		break;
+	case QAM_32:
+		status = SetQAM32(state);
+		break;
+	case QAM_AUTO:
+	case QAM_64:
+		status = SetQAM64(state);
+		break;
+	case QAM_128:
+		status = SetQAM128(state);
+		break;
+	case QAM_256:
+		status = SetQAM256(state);
+		break;
+	default:
+		status = -EINVAL;
+		break;
+	}
+	if (status < 0)
+		goto error;
+
+	/* Activate SCU to enable SCU commands */
+	status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_ACTIVE);
+	if (status < 0)
+		goto error;
+
+	/* Re-configure MPEG output, requires knowledge of channel bitrate */
+	/* extAttr->currentChannel.modulation = channel->modulation; */
+	/* extAttr->currentChannel.symbolrate    = channel->symbolrate; */
+	status = MPEGTSDtoSetup(state, state->m_OperationMode);
+	if (status < 0)
+		goto error;
+
+	/* Start processes */
+	status = MPEGTSStart(state);
+	if (status < 0)
+		goto error;
+	status = write16(state, FEC_COMM_EXEC__A, FEC_COMM_EXEC_ACTIVE);
+	if (status < 0)
+		goto error;
+	status = write16(state, QAM_COMM_EXEC__A, QAM_COMM_EXEC_ACTIVE);
+	if (status < 0)
+		goto error;
+	status = write16(state, IQM_COMM_EXEC__A, IQM_COMM_EXEC_B_ACTIVE);
+	if (status < 0)
+		goto error;
+
+	/* STEP 5: start QAM demodulator (starts FEC, QAM and IQM HW) */
+	status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_START, 0, NULL, 1, &cmdResult);
+	if (status < 0)
+		goto error;
+
+	/* update global DRXK data container */
+/*?     extAttr->qamInterleaveMode = DRXK_QAM_I12_J17; */
+
+error:
+	if (status < 0)
+		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+	return status;
+}
+
+static int SetQAMStandard(struct drxk_state *state,
+			  enum OperationMode oMode)
+{
+	int status;
+#ifdef DRXK_QAM_TAPS
+#define DRXK_QAMA_TAPS_SELECT
+#include "drxk_filters.h"
+#undef DRXK_QAMA_TAPS_SELECT
+#endif
+
+	dprintk(1, "\n");
+
+	/* added antenna switch */
+	SwitchAntennaToQAM(state);
+
+	/* Ensure correct power-up mode */
+	status = PowerUpQAM(state);
+	if (status < 0)
+		goto error;
+	/* Reset QAM block */
+	status = QAMResetQAM(state);
+	if (status < 0)
+		goto error;
+
+	/* Setup IQM */
+
+	status = write16(state, IQM_COMM_EXEC__A, IQM_COMM_EXEC_B_STOP);
+	if (status < 0)
+		goto error;
+	status = write16(state, IQM_AF_AMUX__A, IQM_AF_AMUX_SIGNAL2ADC);
+	if (status < 0)
+		goto error;
+
+	/* Upload IQM Channel Filter settings by
+		boot loader from ROM table */
+	switch (oMode) {
+	case OM_QAM_ITU_A:
+		status = BLChainCmd(state, DRXK_BL_ROM_OFFSET_TAPS_ITU_A, DRXK_BLCC_NR_ELEMENTS_TAPS, DRXK_BLC_TIMEOUT);
+		break;
+	case OM_QAM_ITU_C:
+		status = BLDirectCmd(state, IQM_CF_TAP_RE0__A, DRXK_BL_ROM_OFFSET_TAPS_ITU_C, DRXK_BLDC_NR_ELEMENTS_TAPS, DRXK_BLC_TIMEOUT);
+		if (status < 0)
+			goto error;
+		status = BLDirectCmd(state, IQM_CF_TAP_IM0__A, DRXK_BL_ROM_OFFSET_TAPS_ITU_C, DRXK_BLDC_NR_ELEMENTS_TAPS, DRXK_BLC_TIMEOUT);
+		break;
+	default:
+		status = -EINVAL;
+	}
+	if (status < 0)
+		goto error;
+
+	status = write16(state, IQM_CF_OUT_ENA__A, (1 << IQM_CF_OUT_ENA_QAM__B));
+	if (status < 0)
+		goto error;
+	status = write16(state, IQM_CF_SYMMETRIC__A, 0);
+	if (status < 0)
+		goto error;
+	status = write16(state, IQM_CF_MIDTAP__A, ((1 << IQM_CF_MIDTAP_RE__B) | (1 << IQM_CF_MIDTAP_IM__B)));
+	if (status < 0)
+		goto error;
+
+	status = write16(state, IQM_RC_STRETCH__A, 21);
+	if (status < 0)
+		goto error;
+	status = write16(state, IQM_AF_CLP_LEN__A, 0);
+	if (status < 0)
+		goto error;
+	status = write16(state, IQM_AF_CLP_TH__A, 448);
+	if (status < 0)
+		goto error;
+	status = write16(state, IQM_AF_SNS_LEN__A, 0);
+	if (status < 0)
+		goto error;
+	status = write16(state, IQM_CF_POW_MEAS_LEN__A, 0);
+	if (status < 0)
+		goto error;
+
+	status = write16(state, IQM_FS_ADJ_SEL__A, 1);
+	if (status < 0)
+		goto error;
+	status = write16(state, IQM_RC_ADJ_SEL__A, 1);
+	if (status < 0)
+		goto error;
+	status = write16(state, IQM_CF_ADJ_SEL__A, 1);
+	if (status < 0)
+		goto error;
+	status = write16(state, IQM_AF_UPD_SEL__A, 0);
+	if (status < 0)
+		goto error;
+
+	/* IQM Impulse Noise Processing Unit */
+	status = write16(state, IQM_CF_CLP_VAL__A, 500);
+	if (status < 0)
+		goto error;
+	status = write16(state, IQM_CF_DATATH__A, 1000);
+	if (status < 0)
+		goto error;
+	status = write16(state, IQM_CF_BYPASSDET__A, 1);
+	if (status < 0)
+		goto error;
+	status = write16(state, IQM_CF_DET_LCT__A, 0);
+	if (status < 0)
+		goto error;
+	status = write16(state, IQM_CF_WND_LEN__A, 1);
+	if (status < 0)
+		goto error;
+	status = write16(state, IQM_CF_PKDTH__A, 1);
+	if (status < 0)
+		goto error;
+	status = write16(state, IQM_AF_INC_BYPASS__A, 1);
+	if (status < 0)
+		goto error;
+
+	/* turn on IQMAF. Must be done before setAgc**() */
+	status = SetIqmAf(state, true);
+	if (status < 0)
+		goto error;
+	status = write16(state, IQM_AF_START_LOCK__A, 0x01);
+	if (status < 0)
+		goto error;
+
+	/* IQM will not be reset from here, sync ADC and update/init AGC */
+	status = ADCSynchronization(state);
+	if (status < 0)
+		goto error;
+
+	/* Set the FSM step period */
+	status = write16(state, SCU_RAM_QAM_FSM_STEP_PERIOD__A, 2000);
+	if (status < 0)
+		goto error;
+
+	/* Halt SCU to enable safe non-atomic accesses */
+	status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_HOLD);
+	if (status < 0)
+		goto error;
+
+	/* No more resets of the IQM, current standard correctly set =>
+		now AGCs can be configured. */
+
+	status = InitAGC(state, true);
+	if (status < 0)
+		goto error;
+	status = SetPreSaw(state, &(state->m_qamPreSawCfg));
+	if (status < 0)
+		goto error;
+
+	/* Configure AGC's */
+	status = SetAgcRf(state, &(state->m_qamRfAgcCfg), true);
+	if (status < 0)
+		goto error;
+	status = SetAgcIf(state, &(state->m_qamIfAgcCfg), true);
+	if (status < 0)
+		goto error;
+
+	/* Activate SCU to enable SCU commands */
+	status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_ACTIVE);
+error:
+	if (status < 0)
+		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+	return status;
+}
+
+static int WriteGPIO(struct drxk_state *state)
+{
+	int status;
+	u16 value = 0;
+
+	dprintk(1, "\n");
+	/* stop lock indicator process */
+	status = write16(state, SCU_RAM_GPIO__A, SCU_RAM_GPIO_HW_LOCK_IND_DISABLE);
+	if (status < 0)
+		goto error;
+
+	/*  Write magic word to enable pdr reg write               */
+	status = write16(state, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY);
+	if (status < 0)
+		goto error;
+
+	if (state->m_hasSAWSW) {
+		if (state->UIO_mask & 0x0001) { /* UIO-1 */
+			/* write to io pad configuration register - output mode */
+			status = write16(state, SIO_PDR_SMA_TX_CFG__A, state->m_GPIOCfg);
+			if (status < 0)
+				goto error;
+
+			/* use corresponding bit in io data output registar */
+			status = read16(state, SIO_PDR_UIO_OUT_LO__A, &value);
+			if (status < 0)
+				goto error;
+			if ((state->m_GPIO & 0x0001) == 0)
+				value &= 0x7FFF;	/* write zero to 15th bit - 1st UIO */
+			else
+				value |= 0x8000;	/* write one to 15th bit - 1st UIO */
+			/* write back to io data output register */
+			status = write16(state, SIO_PDR_UIO_OUT_LO__A, value);
+			if (status < 0)
+				goto error;
+		}
+		if (state->UIO_mask & 0x0002) { /* UIO-2 */
+			/* write to io pad configuration register - output mode */
+			status = write16(state, SIO_PDR_SMA_RX_CFG__A, state->m_GPIOCfg);
+			if (status < 0)
+				goto error;
+
+			/* use corresponding bit in io data output registar */
+			status = read16(state, SIO_PDR_UIO_OUT_LO__A, &value);
+			if (status < 0)
+				goto error;
+			if ((state->m_GPIO & 0x0002) == 0)
+				value &= 0xBFFF;	/* write zero to 14th bit - 2st UIO */
+			else
+				value |= 0x4000;	/* write one to 14th bit - 2st UIO */
+			/* write back to io data output register */
+			status = write16(state, SIO_PDR_UIO_OUT_LO__A, value);
+			if (status < 0)
+				goto error;
+		}
+		if (state->UIO_mask & 0x0004) { /* UIO-3 */
+			/* write to io pad configuration register - output mode */
+			status = write16(state, SIO_PDR_GPIO_CFG__A, state->m_GPIOCfg);
+			if (status < 0)
+				goto error;
+
+			/* use corresponding bit in io data output registar */
+			status = read16(state, SIO_PDR_UIO_OUT_LO__A, &value);
+			if (status < 0)
+				goto error;
+			if ((state->m_GPIO & 0x0004) == 0)
+				value &= 0xFFFB;            /* write zero to 2nd bit - 3rd UIO */
+			else
+				value |= 0x0004;            /* write one to 2nd bit - 3rd UIO */
+			/* write back to io data output register */
+			status = write16(state, SIO_PDR_UIO_OUT_LO__A, value);
+			if (status < 0)
+				goto error;
+		}
+	}
+	/*  Write magic word to disable pdr reg write               */
+	status = write16(state, SIO_TOP_COMM_KEY__A, 0x0000);
+error:
+	if (status < 0)
+		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+	return status;
+}
+
+static int SwitchAntennaToQAM(struct drxk_state *state)
+{
+	int status = 0;
+	bool gpio_state;
+
+	dprintk(1, "\n");
+
+	if (!state->antenna_gpio)
+		return 0;
+
+	gpio_state = state->m_GPIO & state->antenna_gpio;
+
+	if (state->antenna_dvbt ^ gpio_state) {
+		/* Antenna is on DVB-T mode. Switch */
+		if (state->antenna_dvbt)
+			state->m_GPIO &= ~state->antenna_gpio;
+		else
+			state->m_GPIO |= state->antenna_gpio;
+		status = WriteGPIO(state);
+	}
+	if (status < 0)
+		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+	return status;
+}
+
+static int SwitchAntennaToDVBT(struct drxk_state *state)
+{
+	int status = 0;
+	bool gpio_state;
+
+	dprintk(1, "\n");
+
+	if (!state->antenna_gpio)
+		return 0;
+
+	gpio_state = state->m_GPIO & state->antenna_gpio;
+
+	if (!(state->antenna_dvbt ^ gpio_state)) {
+		/* Antenna is on DVB-C mode. Switch */
+		if (state->antenna_dvbt)
+			state->m_GPIO |= state->antenna_gpio;
+		else
+			state->m_GPIO &= ~state->antenna_gpio;
+		status = WriteGPIO(state);
+	}
+	if (status < 0)
+		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+	return status;
+}
+
+
+static int PowerDownDevice(struct drxk_state *state)
+{
+	/* Power down to requested mode */
+	/* Backup some register settings */
+	/* Set pins with possible pull-ups connected to them in input mode */
+	/* Analog power down */
+	/* ADC power down */
+	/* Power down device */
+	int status;
+
+	dprintk(1, "\n");
+	if (state->m_bPDownOpenBridge) {
+		/* Open I2C bridge before power down of DRXK */
+		status = ConfigureI2CBridge(state, true);
+		if (status < 0)
+			goto error;
+	}
+	/* driver 0.9.0 */
+	status = DVBTEnableOFDMTokenRing(state, false);
+	if (status < 0)
+		goto error;
+
+	status = write16(state, SIO_CC_PWD_MODE__A, SIO_CC_PWD_MODE_LEVEL_CLOCK);
+	if (status < 0)
+		goto error;
+	status = write16(state, SIO_CC_UPDATE__A, SIO_CC_UPDATE_KEY);
+	if (status < 0)
+		goto error;
+	state->m_HICfgCtrl |= SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ;
+	status = HI_CfgCommand(state);
+error:
+	if (status < 0)
+		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+
+	return status;
+}
+
+static int init_drxk(struct drxk_state *state)
+{
+	int status = 0, n = 0;
+	enum DRXPowerMode powerMode = DRXK_POWER_DOWN_OFDM;
+	u16 driverVersion;
+
+	dprintk(1, "\n");
+	if ((state->m_DrxkState == DRXK_UNINITIALIZED)) {
+		drxk_i2c_lock(state);
+		status = PowerUpDevice(state);
+		if (status < 0)
+			goto error;
+		status = DRXX_Open(state);
+		if (status < 0)
+			goto error;
+		/* Soft reset of OFDM-, sys- and osc-clockdomain */
+		status = write16(state, SIO_CC_SOFT_RST__A, SIO_CC_SOFT_RST_OFDM__M | SIO_CC_SOFT_RST_SYS__M | SIO_CC_SOFT_RST_OSC__M);
+		if (status < 0)
+			goto error;
+		status = write16(state, SIO_CC_UPDATE__A, SIO_CC_UPDATE_KEY);
+		if (status < 0)
+			goto error;
+		/* TODO is this needed, if yes how much delay in worst case scenario */
+		msleep(1);
+		state->m_DRXK_A3_PATCH_CODE = true;
+		status = GetDeviceCapabilities(state);
+		if (status < 0)
+			goto error;
+
+		/* Bridge delay, uses oscilator clock */
+		/* Delay = (delay (nano seconds) * oscclk (kHz))/ 1000 */
+		/* SDA brdige delay */
+		state->m_HICfgBridgeDelay =
+			(u16) ((state->m_oscClockFreq / 1000) *
+				HI_I2C_BRIDGE_DELAY) / 1000;
+		/* Clipping */
+		if (state->m_HICfgBridgeDelay >
+			SIO_HI_RA_RAM_PAR_3_CFG_DBL_SDA__M) {
+			state->m_HICfgBridgeDelay =
+				SIO_HI_RA_RAM_PAR_3_CFG_DBL_SDA__M;
+		}
+		/* SCL bridge delay, same as SDA for now */
+		state->m_HICfgBridgeDelay +=
+			state->m_HICfgBridgeDelay <<
+			SIO_HI_RA_RAM_PAR_3_CFG_DBL_SCL__B;
+
+		status = InitHI(state);
+		if (status < 0)
+			goto error;
+		/* disable various processes */
+#if NOA1ROM
+		if (!(state->m_DRXK_A1_ROM_CODE)
+			&& !(state->m_DRXK_A2_ROM_CODE))
+#endif
+		{
+			status = write16(state, SCU_RAM_GPIO__A, SCU_RAM_GPIO_HW_LOCK_IND_DISABLE);
+			if (status < 0)
+				goto error;
+		}
+
+		/* disable MPEG port */
+		status = MPEGTSDisable(state);
+		if (status < 0)
+			goto error;
+
+		/* Stop AUD and SCU */
+		status = write16(state, AUD_COMM_EXEC__A, AUD_COMM_EXEC_STOP);
+		if (status < 0)
+			goto error;
+		status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_STOP);
+		if (status < 0)
+			goto error;
+
+		/* enable token-ring bus through OFDM block for possible ucode upload */
+		status = write16(state, SIO_OFDM_SH_OFDM_RING_ENABLE__A, SIO_OFDM_SH_OFDM_RING_ENABLE_ON);
+		if (status < 0)
+			goto error;
+
+		/* include boot loader section */
+		status = write16(state, SIO_BL_COMM_EXEC__A, SIO_BL_COMM_EXEC_ACTIVE);
+		if (status < 0)
+			goto error;
+		status = BLChainCmd(state, 0, 6, 100);
+		if (status < 0)
+			goto error;
+
+		if (state->fw) {
+			status = DownloadMicrocode(state, state->fw->data,
+						   state->fw->size);
+			if (status < 0)
+				goto error;
+		}
+
+		/* disable token-ring bus through OFDM block for possible ucode upload */
+		status = write16(state, SIO_OFDM_SH_OFDM_RING_ENABLE__A, SIO_OFDM_SH_OFDM_RING_ENABLE_OFF);
+		if (status < 0)
+			goto error;
+
+		/* Run SCU for a little while to initialize microcode version numbers */
+		status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_ACTIVE);
+		if (status < 0)
+			goto error;
+		status = DRXX_Open(state);
+		if (status < 0)
+			goto error;
+		/* added for test */
+		msleep(30);
+
+		powerMode = DRXK_POWER_DOWN_OFDM;
+		status = CtrlPowerMode(state, &powerMode);
+		if (status < 0)
+			goto error;
+
+		/* Stamp driver version number in SCU data RAM in BCD code
+			Done to enable field application engineers to retreive drxdriver version
+			via I2C from SCU RAM.
+			Not using SCU command interface for SCU register access since no
+			microcode may be present.
+			*/
+		driverVersion =
+			(((DRXK_VERSION_MAJOR / 100) % 10) << 12) +
+			(((DRXK_VERSION_MAJOR / 10) % 10) << 8) +
+			((DRXK_VERSION_MAJOR % 10) << 4) +
+			(DRXK_VERSION_MINOR % 10);
+		status = write16(state, SCU_RAM_DRIVER_VER_HI__A, driverVersion);
+		if (status < 0)
+			goto error;
+		driverVersion =
+			(((DRXK_VERSION_PATCH / 1000) % 10) << 12) +
+			(((DRXK_VERSION_PATCH / 100) % 10) << 8) +
+			(((DRXK_VERSION_PATCH / 10) % 10) << 4) +
+			(DRXK_VERSION_PATCH % 10);
+		status = write16(state, SCU_RAM_DRIVER_VER_LO__A, driverVersion);
+		if (status < 0)
+			goto error;
+
+		printk(KERN_INFO "DRXK driver version %d.%d.%d\n",
+			DRXK_VERSION_MAJOR, DRXK_VERSION_MINOR,
+			DRXK_VERSION_PATCH);
+
+		/* Dirty fix of default values for ROM/PATCH microcode
+			Dirty because this fix makes it impossible to setup suitable values
+			before calling DRX_Open. This solution requires changes to RF AGC speed
+			to be done via the CTRL function after calling DRX_Open */
+
+		/* m_dvbtRfAgcCfg.speed = 3; */
+
+		/* Reset driver debug flags to 0 */
+		status = write16(state, SCU_RAM_DRIVER_DEBUG__A, 0);
+		if (status < 0)
+			goto error;
+		/* driver 0.9.0 */
+		/* Setup FEC OC:
+			NOTE: No more full FEC resets allowed afterwards!! */
+		status = write16(state, FEC_COMM_EXEC__A, FEC_COMM_EXEC_STOP);
+		if (status < 0)
+			goto error;
+		/* MPEGTS functions are still the same */
+		status = MPEGTSDtoInit(state);
+		if (status < 0)
+			goto error;
+		status = MPEGTSStop(state);
+		if (status < 0)
+			goto error;
+		status = MPEGTSConfigurePolarity(state);
+		if (status < 0)
+			goto error;
+		status = MPEGTSConfigurePins(state, state->m_enableMPEGOutput);
+		if (status < 0)
+			goto error;
+		/* added: configure GPIO */
+		status = WriteGPIO(state);
+		if (status < 0)
+			goto error;
+
+		state->m_DrxkState = DRXK_STOPPED;
+
+		if (state->m_bPowerDown) {
+			status = PowerDownDevice(state);
+			if (status < 0)
+				goto error;
+			state->m_DrxkState = DRXK_POWERED_DOWN;
+		} else
+			state->m_DrxkState = DRXK_STOPPED;
+
+		/* Initialize the supported delivery systems */
+		n = 0;
+		if (state->m_hasDVBC) {
+			state->frontend.ops.delsys[n++] = SYS_DVBC_ANNEX_A;
+			state->frontend.ops.delsys[n++] = SYS_DVBC_ANNEX_C;
+			strlcat(state->frontend.ops.info.name, " DVB-C",
+				sizeof(state->frontend.ops.info.name));
+		}
+		if (state->m_hasDVBT) {
+			state->frontend.ops.delsys[n++] = SYS_DVBT;
+			strlcat(state->frontend.ops.info.name, " DVB-T",
+				sizeof(state->frontend.ops.info.name));
+		}
+		drxk_i2c_unlock(state);
+	}
+error:
+	if (status < 0) {
+		state->m_DrxkState = DRXK_NO_DEV;
+		drxk_i2c_unlock(state);
+		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+	}
+
+	return status;
+}
+
+static void load_firmware_cb(const struct firmware *fw,
+			     void *context)
+{
+	struct drxk_state *state = context;
+
+	dprintk(1, ": %s\n", fw ? "firmware loaded" : "firmware not loaded");
+	if (!fw) {
+		printk(KERN_ERR
+		       "drxk: Could not load firmware file %s.\n",
+			state->microcode_name);
+		printk(KERN_INFO
+		       "drxk: Copy %s to your hotplug directory!\n",
+			state->microcode_name);
+		state->microcode_name = NULL;
+
+		/*
+		 * As firmware is now load asynchronous, it is not possible
+		 * anymore to fail at frontend attach. We might silently
+		 * return here, and hope that the driver won't crash.
+		 * We might also change all DVB callbacks to return -ENODEV
+		 * if the device is not initialized.
+		 * As the DRX-K devices have their own internal firmware,
+		 * let's just hope that it will match a firmware revision
+		 * compatible with this driver and proceed.
+		 */
+	}
+	state->fw = fw;
+
+	init_drxk(state);
+}
+
+static void drxk_release(struct dvb_frontend *fe)
+{
+	struct drxk_state *state = fe->demodulator_priv;
+
+	dprintk(1, "\n");
+	if (state->fw)
+		release_firmware(state->fw);
+
+	kfree(state);
+}
+
+static int drxk_sleep(struct dvb_frontend *fe)
+{
+	struct drxk_state *state = fe->demodulator_priv;
+
+	dprintk(1, "\n");
+
+	if (state->m_DrxkState == DRXK_NO_DEV)
+		return -ENODEV;
+	if (state->m_DrxkState == DRXK_UNINITIALIZED)
+		return 0;
+
+	ShutDown(state);
+	return 0;
+}
+
+static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+	struct drxk_state *state = fe->demodulator_priv;
+
+	dprintk(1, ": %s\n", enable ? "enable" : "disable");
+
+	if (state->m_DrxkState == DRXK_NO_DEV)
+		return -ENODEV;
+
+	return ConfigureI2CBridge(state, enable ? true : false);
+}
+
+static int drxk_set_parameters(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	u32 delsys  = p->delivery_system, old_delsys;
+	struct drxk_state *state = fe->demodulator_priv;
+	u32 IF;
+
+	dprintk(1, "\n");
+
+	if (state->m_DrxkState == DRXK_NO_DEV)
+		return -ENODEV;
+
+	if (state->m_DrxkState == DRXK_UNINITIALIZED)
+		return -EAGAIN;
+
+	if (!fe->ops.tuner_ops.get_if_frequency) {
+		printk(KERN_ERR
+		       "drxk: Error: get_if_frequency() not defined at tuner. Can't work without it!\n");
+		return -EINVAL;
+	}
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+	if (fe->ops.tuner_ops.set_params)
+		fe->ops.tuner_ops.set_params(fe);
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 0);
+
+	old_delsys = state->props.delivery_system;
+	state->props = *p;
+
+	if (old_delsys != delsys) {
+		ShutDown(state);
+		switch (delsys) {
+		case SYS_DVBC_ANNEX_A:
+		case SYS_DVBC_ANNEX_C:
+			if (!state->m_hasDVBC)
+				return -EINVAL;
+			state->m_itut_annex_c = (delsys == SYS_DVBC_ANNEX_C) ? true : false;
+			if (state->m_itut_annex_c)
+				SetOperationMode(state, OM_QAM_ITU_C);
+			else
+				SetOperationMode(state, OM_QAM_ITU_A);
+			break;
+		case SYS_DVBT:
+			if (!state->m_hasDVBT)
+				return -EINVAL;
+			SetOperationMode(state, OM_DVBT);
+			break;
+		default:
+			return -EINVAL;
+		}
+	}
+
+	fe->ops.tuner_ops.get_if_frequency(fe, &IF);
+	Start(state, 0, IF);
+
+	/* printk(KERN_DEBUG "drxk: %s IF=%d done\n", __func__, IF); */
+
+	return 0;
+}
+
+static int drxk_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+	struct drxk_state *state = fe->demodulator_priv;
+	u32 stat;
+
+	dprintk(1, "\n");
+
+	if (state->m_DrxkState == DRXK_NO_DEV)
+		return -ENODEV;
+	if (state->m_DrxkState == DRXK_UNINITIALIZED)
+		return -EAGAIN;
+
+	*status = 0;
+	GetLockStatus(state, &stat, 0);
+	if (stat == MPEG_LOCK)
+		*status |= 0x1f;
+	if (stat == FEC_LOCK)
+		*status |= 0x0f;
+	if (stat == DEMOD_LOCK)
+		*status |= 0x07;
+	return 0;
+}
+
+static int drxk_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+	struct drxk_state *state = fe->demodulator_priv;
+
+	dprintk(1, "\n");
+
+	if (state->m_DrxkState == DRXK_NO_DEV)
+		return -ENODEV;
+	if (state->m_DrxkState == DRXK_UNINITIALIZED)
+		return -EAGAIN;
+
+	*ber = 0;
+	return 0;
+}
+
+static int drxk_read_signal_strength(struct dvb_frontend *fe,
+				     u16 *strength)
+{
+	struct drxk_state *state = fe->demodulator_priv;
+	u32 val = 0;
+
+	dprintk(1, "\n");
+
+	if (state->m_DrxkState == DRXK_NO_DEV)
+		return -ENODEV;
+	if (state->m_DrxkState == DRXK_UNINITIALIZED)
+		return -EAGAIN;
+
+	ReadIFAgc(state, &val);
+	*strength = val & 0xffff;
+	return 0;
+}
+
+static int drxk_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+	struct drxk_state *state = fe->demodulator_priv;
+	s32 snr2;
+
+	dprintk(1, "\n");
+
+	if (state->m_DrxkState == DRXK_NO_DEV)
+		return -ENODEV;
+	if (state->m_DrxkState == DRXK_UNINITIALIZED)
+		return -EAGAIN;
+
+	GetSignalToNoise(state, &snr2);
+	*snr = snr2 & 0xffff;
+	return 0;
+}
+
+static int drxk_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+	struct drxk_state *state = fe->demodulator_priv;
+	u16 err;
+
+	dprintk(1, "\n");
+
+	if (state->m_DrxkState == DRXK_NO_DEV)
+		return -ENODEV;
+	if (state->m_DrxkState == DRXK_UNINITIALIZED)
+		return -EAGAIN;
+
+	DVBTQAMGetAccPktErr(state, &err);
+	*ucblocks = (u32) err;
+	return 0;
+}
+
+static int drxk_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings
+				    *sets)
+{
+	struct drxk_state *state = fe->demodulator_priv;
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+
+	dprintk(1, "\n");
+
+	if (state->m_DrxkState == DRXK_NO_DEV)
+		return -ENODEV;
+	if (state->m_DrxkState == DRXK_UNINITIALIZED)
+		return -EAGAIN;
+
+	switch (p->delivery_system) {
+	case SYS_DVBC_ANNEX_A:
+	case SYS_DVBC_ANNEX_C:
+	case SYS_DVBT:
+		sets->min_delay_ms = 3000;
+		sets->max_drift = 0;
+		sets->step_size = 0;
+		return 0;
+	default:
+		return -EINVAL;
+	}
+}
+
+static struct dvb_frontend_ops drxk_ops = {
+	/* .delsys will be filled dynamically */
+	.info = {
+		.name = "DRXK",
+		.frequency_min = 47000000,
+		.frequency_max = 865000000,
+		 /* For DVB-C */
+		.symbol_rate_min = 870000,
+		.symbol_rate_max = 11700000,
+		/* For DVB-T */
+		.frequency_stepsize = 166667,
+
+		.caps = FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 |
+			FE_CAN_QAM_128 | FE_CAN_QAM_256 | FE_CAN_FEC_AUTO |
+			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_MUTE_TS |
+			FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_RECOVER |
+			FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO
+	},
+
+	.release = drxk_release,
+	.sleep = drxk_sleep,
+	.i2c_gate_ctrl = drxk_gate_ctrl,
+
+	.set_frontend = drxk_set_parameters,
+	.get_tune_settings = drxk_get_tune_settings,
+
+	.read_status = drxk_read_status,
+	.read_ber = drxk_read_ber,
+	.read_signal_strength = drxk_read_signal_strength,
+	.read_snr = drxk_read_snr,
+	.read_ucblocks = drxk_read_ucblocks,
+};
+
+struct dvb_frontend *drxk_attach(const struct drxk_config *config,
+				 struct i2c_adapter *i2c)
+{
+	struct drxk_state *state = NULL;
+	u8 adr = config->adr;
+	int status;
+
+	dprintk(1, "\n");
+	state = kzalloc(sizeof(struct drxk_state), GFP_KERNEL);
+	if (!state)
+		return NULL;
+
+	state->i2c = i2c;
+	state->demod_address = adr;
+	state->single_master = config->single_master;
+	state->microcode_name = config->microcode_name;
+	state->qam_demod_parameter_count = config->qam_demod_parameter_count;
+	state->no_i2c_bridge = config->no_i2c_bridge;
+	state->antenna_gpio = config->antenna_gpio;
+	state->antenna_dvbt = config->antenna_dvbt;
+	state->m_ChunkSize = config->chunk_size;
+	state->enable_merr_cfg = config->enable_merr_cfg;
+
+	if (config->dynamic_clk) {
+		state->m_DVBTStaticCLK = 0;
+		state->m_DVBCStaticCLK = 0;
+	} else {
+		state->m_DVBTStaticCLK = 1;
+		state->m_DVBCStaticCLK = 1;
+	}
+
+
+	if (config->mpeg_out_clk_strength)
+		state->m_TSClockkStrength = config->mpeg_out_clk_strength & 0x07;
+	else
+		state->m_TSClockkStrength = 0x06;
+
+	if (config->parallel_ts)
+		state->m_enableParallel = true;
+	else
+		state->m_enableParallel = false;
+
+	/* NOTE: as more UIO bits will be used, add them to the mask */
+	state->UIO_mask = config->antenna_gpio;
+
+	/* Default gpio to DVB-C */
+	if (!state->antenna_dvbt && state->antenna_gpio)
+		state->m_GPIO |= state->antenna_gpio;
+	else
+		state->m_GPIO &= ~state->antenna_gpio;
+
+	mutex_init(&state->mutex);
+
+	memcpy(&state->frontend.ops, &drxk_ops, sizeof(drxk_ops));
+	state->frontend.demodulator_priv = state;
+
+	init_state(state);
+
+	/* Load firmware and initialize DRX-K */
+	if (state->microcode_name) {
+		status = request_firmware_nowait(THIS_MODULE, 1,
+					      state->microcode_name,
+					      state->i2c->dev.parent,
+					      GFP_KERNEL,
+					      state, load_firmware_cb);
+		if (status < 0) {
+			printk(KERN_ERR
+			"drxk: failed to request a firmware\n");
+			return NULL;
+		}
+	} else if (init_drxk(state) < 0)
+		goto error;
+
+	printk(KERN_INFO "drxk: frontend initialized.\n");
+	return &state->frontend;
+
+error:
+	printk(KERN_ERR "drxk: not found\n");
+	kfree(state);
+	return NULL;
+}
+EXPORT_SYMBOL(drxk_attach);
+
+MODULE_DESCRIPTION("DRX-K driver");
+MODULE_AUTHOR("Ralph Metzler");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb-frontends/drxk_hard.h b/drivers/media/dvb-frontends/drxk_hard.h
new file mode 100644
index 0000000..6bb9fc4
--- /dev/null
+++ b/drivers/media/dvb-frontends/drxk_hard.h
@@ -0,0 +1,364 @@
+#include "drxk_map.h"
+
+#define DRXK_VERSION_MAJOR 0
+#define DRXK_VERSION_MINOR 9
+#define DRXK_VERSION_PATCH 4300
+
+#define HI_I2C_DELAY        42
+#define HI_I2C_BRIDGE_DELAY 350
+#define DRXK_MAX_RETRIES    100
+
+#define DRIVER_4400 1
+
+#define DRXX_JTAGID   0x039210D9
+#define DRXX_J_JTAGID 0x239310D9
+#define DRXX_K_JTAGID 0x039210D9
+
+#define DRX_UNKNOWN     254
+#define DRX_AUTO        255
+
+#define DRX_SCU_READY   0
+#define DRXK_MAX_WAITTIME (200)
+#define SCU_RESULT_OK      0
+#define SCU_RESULT_SIZE   -4
+#define SCU_RESULT_INVPAR -3
+#define SCU_RESULT_UNKSTD -2
+#define SCU_RESULT_UNKCMD -1
+
+#ifndef DRXK_OFDM_TR_SHUTDOWN_TIMEOUT
+#define DRXK_OFDM_TR_SHUTDOWN_TIMEOUT (200)
+#endif
+
+#define DRXK_8VSB_MPEG_BIT_RATE     19392658UL  /*bps*/
+#define DRXK_DVBT_MPEG_BIT_RATE     32000000UL  /*bps*/
+#define DRXK_QAM16_MPEG_BIT_RATE    27000000UL  /*bps*/
+#define DRXK_QAM32_MPEG_BIT_RATE    33000000UL  /*bps*/
+#define DRXK_QAM64_MPEG_BIT_RATE    40000000UL  /*bps*/
+#define DRXK_QAM128_MPEG_BIT_RATE   46000000UL  /*bps*/
+#define DRXK_QAM256_MPEG_BIT_RATE   52000000UL  /*bps*/
+#define DRXK_MAX_MPEG_BIT_RATE      52000000UL  /*bps*/
+
+#define   IQM_CF_OUT_ENA_OFDM__M                                            0x4
+#define     IQM_FS_ADJ_SEL_B_QAM                                            0x1
+#define     IQM_FS_ADJ_SEL_B_OFF                                            0x0
+#define     IQM_FS_ADJ_SEL_B_VSB                                            0x2
+#define     IQM_RC_ADJ_SEL_B_OFF                                            0x0
+#define     IQM_RC_ADJ_SEL_B_QAM                                            0x1
+#define     IQM_RC_ADJ_SEL_B_VSB                                            0x2
+
+enum OperationMode {
+	OM_NONE,
+	OM_QAM_ITU_A,
+	OM_QAM_ITU_B,
+	OM_QAM_ITU_C,
+	OM_DVBT
+};
+
+enum DRXPowerMode {
+	DRX_POWER_UP = 0,
+	DRX_POWER_MODE_1,
+	DRX_POWER_MODE_2,
+	DRX_POWER_MODE_3,
+	DRX_POWER_MODE_4,
+	DRX_POWER_MODE_5,
+	DRX_POWER_MODE_6,
+	DRX_POWER_MODE_7,
+	DRX_POWER_MODE_8,
+
+	DRX_POWER_MODE_9,
+	DRX_POWER_MODE_10,
+	DRX_POWER_MODE_11,
+	DRX_POWER_MODE_12,
+	DRX_POWER_MODE_13,
+	DRX_POWER_MODE_14,
+	DRX_POWER_MODE_15,
+	DRX_POWER_MODE_16,
+	DRX_POWER_DOWN = 255
+};
+
+
+/** /brief Intermediate power mode for DRXK, power down OFDM clock domain */
+#ifndef DRXK_POWER_DOWN_OFDM
+#define DRXK_POWER_DOWN_OFDM        DRX_POWER_MODE_1
+#endif
+
+/** /brief Intermediate power mode for DRXK, power down core (sysclk) */
+#ifndef DRXK_POWER_DOWN_CORE
+#define DRXK_POWER_DOWN_CORE        DRX_POWER_MODE_9
+#endif
+
+/** /brief Intermediate power mode for DRXK, power down pll (only osc runs) */
+#ifndef DRXK_POWER_DOWN_PLL
+#define DRXK_POWER_DOWN_PLL         DRX_POWER_MODE_10
+#endif
+
+
+enum AGC_CTRL_MODE { DRXK_AGC_CTRL_AUTO = 0, DRXK_AGC_CTRL_USER, DRXK_AGC_CTRL_OFF };
+enum EDrxkState {
+	DRXK_UNINITIALIZED = 0,
+	DRXK_STOPPED,
+	DRXK_DTV_STARTED,
+	DRXK_ATV_STARTED,
+	DRXK_POWERED_DOWN,
+	DRXK_NO_DEV			/* If drxk init failed */
+};
+
+enum EDrxkCoefArrayIndex {
+	DRXK_COEF_IDX_MN = 0,
+	DRXK_COEF_IDX_FM    ,
+	DRXK_COEF_IDX_L     ,
+	DRXK_COEF_IDX_LP    ,
+	DRXK_COEF_IDX_BG    ,
+	DRXK_COEF_IDX_DK    ,
+	DRXK_COEF_IDX_I     ,
+	DRXK_COEF_IDX_MAX
+};
+enum EDrxkSifAttenuation {
+	DRXK_SIF_ATTENUATION_0DB,
+	DRXK_SIF_ATTENUATION_3DB,
+	DRXK_SIF_ATTENUATION_6DB,
+	DRXK_SIF_ATTENUATION_9DB
+};
+enum EDrxkConstellation {
+	DRX_CONSTELLATION_BPSK = 0,
+	DRX_CONSTELLATION_QPSK,
+	DRX_CONSTELLATION_PSK8,
+	DRX_CONSTELLATION_QAM16,
+	DRX_CONSTELLATION_QAM32,
+	DRX_CONSTELLATION_QAM64,
+	DRX_CONSTELLATION_QAM128,
+	DRX_CONSTELLATION_QAM256,
+	DRX_CONSTELLATION_QAM512,
+	DRX_CONSTELLATION_QAM1024,
+	DRX_CONSTELLATION_UNKNOWN = DRX_UNKNOWN,
+	DRX_CONSTELLATION_AUTO    = DRX_AUTO
+};
+enum EDrxkInterleaveMode {
+	DRXK_QAM_I12_J17    = 16,
+	DRXK_QAM_I_UNKNOWN  = DRX_UNKNOWN
+};
+enum {
+	DRXK_SPIN_A1 = 0,
+	DRXK_SPIN_A2,
+	DRXK_SPIN_A3,
+	DRXK_SPIN_UNKNOWN
+};
+
+enum DRXKCfgDvbtSqiSpeed {
+	DRXK_DVBT_SQI_SPEED_FAST = 0,
+	DRXK_DVBT_SQI_SPEED_MEDIUM,
+	DRXK_DVBT_SQI_SPEED_SLOW,
+	DRXK_DVBT_SQI_SPEED_UNKNOWN = DRX_UNKNOWN
+} ;
+
+enum DRXFftmode_t {
+	DRX_FFTMODE_2K = 0,
+	DRX_FFTMODE_4K,
+	DRX_FFTMODE_8K,
+	DRX_FFTMODE_UNKNOWN = DRX_UNKNOWN,
+	DRX_FFTMODE_AUTO    = DRX_AUTO
+};
+
+enum DRXMPEGStrWidth_t {
+	DRX_MPEG_STR_WIDTH_1,
+	DRX_MPEG_STR_WIDTH_8
+};
+
+enum DRXQamLockRange_t {
+	DRX_QAM_LOCKRANGE_NORMAL,
+	DRX_QAM_LOCKRANGE_EXTENDED
+};
+
+struct DRXKCfgDvbtEchoThres_t {
+	u16             threshold;
+	enum DRXFftmode_t      fftMode;
+} ;
+
+struct SCfgAgc {
+	enum AGC_CTRL_MODE     ctrlMode;        /* off, user, auto */
+	u16            outputLevel;     /* range dependent on AGC */
+	u16            minOutputLevel;  /* range dependent on AGC */
+	u16            maxOutputLevel;  /* range dependent on AGC */
+	u16            speed;           /* range dependent on AGC */
+	u16            top;             /* rf-agc take over point */
+	u16            cutOffCurrent;   /* rf-agc is accelerated if output current
+					   is below cut-off current */
+	u16            IngainTgtMax;
+	u16            FastClipCtrlDelay;
+};
+
+struct SCfgPreSaw {
+	u16        reference; /* pre SAW reference value, range 0 .. 31 */
+	bool          usePreSaw; /* TRUE algorithms must use pre SAW sense */
+};
+
+struct DRXKOfdmScCmd_t {
+	u16 cmd;        /**< Command number */
+	u16 subcmd;     /**< Sub-command parameter*/
+	u16 param0;     /**< General purpous param */
+	u16 param1;     /**< General purpous param */
+	u16 param2;     /**< General purpous param */
+	u16 param3;     /**< General purpous param */
+	u16 param4;     /**< General purpous param */
+};
+
+struct drxk_state {
+	struct dvb_frontend frontend;
+	struct dtv_frontend_properties props;
+	struct device *dev;
+
+	struct i2c_adapter *i2c;
+	u8     demod_address;
+	void  *priv;
+
+	struct mutex mutex;
+
+	u32    m_Instance;           /**< Channel 1,2,3 or 4 */
+
+	int    m_ChunkSize;
+	u8 Chunk[256];
+
+	bool   m_hasLNA;
+	bool   m_hasDVBT;
+	bool   m_hasDVBC;
+	bool   m_hasAudio;
+	bool   m_hasATV;
+	bool   m_hasOOB;
+	bool   m_hasSAWSW;         /**< TRUE if mat_tx is available */
+	bool   m_hasGPIO1;         /**< TRUE if mat_rx is available */
+	bool   m_hasGPIO2;         /**< TRUE if GPIO is available */
+	bool   m_hasIRQN;          /**< TRUE if IRQN is available */
+	u16    m_oscClockFreq;
+	u16    m_HICfgTimingDiv;
+	u16    m_HICfgBridgeDelay;
+	u16    m_HICfgWakeUpKey;
+	u16    m_HICfgTimeout;
+	u16    m_HICfgCtrl;
+	s32    m_sysClockFreq;      /**< system clock frequency in kHz */
+
+	enum EDrxkState    m_DrxkState;      /**< State of Drxk (init,stopped,started) */
+	enum OperationMode m_OperationMode;  /**< digital standards */
+	struct SCfgAgc     m_vsbRfAgcCfg;    /**< settings for VSB RF-AGC */
+	struct SCfgAgc     m_vsbIfAgcCfg;    /**< settings for VSB IF-AGC */
+	u16                m_vsbPgaCfg;      /**< settings for VSB PGA */
+	struct SCfgPreSaw  m_vsbPreSawCfg;   /**< settings for pre SAW sense */
+	s32    m_Quality83percent;  /**< MER level (*0.1 dB) for 83% quality indication */
+	s32    m_Quality93percent;  /**< MER level (*0.1 dB) for 93% quality indication */
+	bool   m_smartAntInverted;
+	bool   m_bDebugEnableBridge;
+	bool   m_bPDownOpenBridge;  /**< only open DRXK bridge before power-down once it has been accessed */
+	bool   m_bPowerDown;        /**< Power down when not used */
+
+	u32    m_IqmFsRateOfs;      /**< frequency shift as written to DRXK register (28bit fixpoint) */
+
+	bool   m_enableMPEGOutput;  /**< If TRUE, enable MPEG output */
+	bool   m_insertRSByte;      /**< If TRUE, insert RS byte */
+	bool   m_enableParallel;    /**< If TRUE, parallel out otherwise serial */
+	bool   m_invertDATA;        /**< If TRUE, invert DATA signals */
+	bool   m_invertERR;         /**< If TRUE, invert ERR signal */
+	bool   m_invertSTR;         /**< If TRUE, invert STR signals */
+	bool   m_invertVAL;         /**< If TRUE, invert VAL signals */
+	bool   m_invertCLK;         /**< If TRUE, invert CLK signals */
+	bool   m_DVBCStaticCLK;
+	bool   m_DVBTStaticCLK;     /**< If TRUE, static MPEG clockrate will
+					 be used, otherwise clockrate will
+					 adapt to the bitrate of the TS */
+	u32    m_DVBTBitrate;
+	u32    m_DVBCBitrate;
+
+	u8     m_TSDataStrength;
+	u8     m_TSClockkStrength;
+
+	bool   m_itut_annex_c;      /* If true, uses ITU-T DVB-C Annex C, instead of Annex A */
+
+	enum DRXMPEGStrWidth_t  m_widthSTR;    /**< MPEG start width */
+	u32    m_mpegTsStaticBitrate;          /**< Maximum bitrate in b/s in case
+						    static clockrate is selected */
+
+	/* LARGE_INTEGER   m_StartTime; */     /**< Contains the time of the last demod start */
+	s32    m_MpegLockTimeOut;      /**< WaitForLockStatus Timeout (counts from start time) */
+	s32    m_DemodLockTimeOut;     /**< WaitForLockStatus Timeout (counts from start time) */
+
+	bool   m_disableTEIhandling;
+
+	bool   m_RfAgcPol;
+	bool   m_IfAgcPol;
+
+	struct SCfgAgc    m_atvRfAgcCfg;  /**< settings for ATV RF-AGC */
+	struct SCfgAgc    m_atvIfAgcCfg;  /**< settings for ATV IF-AGC */
+	struct SCfgPreSaw m_atvPreSawCfg; /**< settings for ATV pre SAW sense */
+	bool              m_phaseCorrectionBypass;
+	s16               m_atvTopVidPeak;
+	u16               m_atvTopNoiseTh;
+	enum EDrxkSifAttenuation m_sifAttenuation;
+	bool              m_enableCVBSOutput;
+	bool              m_enableSIFOutput;
+	bool              m_bMirrorFreqSpect;
+	enum EDrxkConstellation  m_Constellation; /**< Constellation type of the channel */
+	u32               m_CurrSymbolRate;       /**< Current QAM symbol rate */
+	struct SCfgAgc    m_qamRfAgcCfg;          /**< settings for QAM RF-AGC */
+	struct SCfgAgc    m_qamIfAgcCfg;          /**< settings for QAM IF-AGC */
+	u16               m_qamPgaCfg;            /**< settings for QAM PGA */
+	struct SCfgPreSaw m_qamPreSawCfg;         /**< settings for QAM pre SAW sense */
+	enum EDrxkInterleaveMode m_qamInterleaveMode; /**< QAM Interleave mode */
+	u16               m_fecRsPlen;
+	u16               m_fecRsPrescale;
+
+	enum DRXKCfgDvbtSqiSpeed m_sqiSpeed;
+
+	u16               m_GPIO;
+	u16               m_GPIOCfg;
+
+	struct SCfgAgc    m_dvbtRfAgcCfg;     /**< settings for QAM RF-AGC */
+	struct SCfgAgc    m_dvbtIfAgcCfg;     /**< settings for QAM IF-AGC */
+	struct SCfgPreSaw m_dvbtPreSawCfg;    /**< settings for QAM pre SAW sense */
+
+	u16               m_agcFastClipCtrlDelay;
+	bool              m_adcCompPassed;
+	u16               m_adcCompCoef[64];
+	u16               m_adcState;
+
+	u8               *m_microcode;
+	int               m_microcode_length;
+	bool              m_DRXK_A1_PATCH_CODE;
+	bool              m_DRXK_A1_ROM_CODE;
+	bool              m_DRXK_A2_ROM_CODE;
+	bool              m_DRXK_A3_ROM_CODE;
+	bool              m_DRXK_A2_PATCH_CODE;
+	bool              m_DRXK_A3_PATCH_CODE;
+
+	bool              m_rfmirror;
+	u8                m_deviceSpin;
+	u32               m_iqmRcRate;
+
+	enum DRXPowerMode m_currentPowerMode;
+
+	/* when true, avoids other devices to use the I2C bus */
+	bool		  drxk_i2c_exclusive_lock;
+
+	/*
+	 * Configurable parameters at the driver. They stores the values found
+	 * at struct drxk_config.
+	 */
+
+	u16	UIO_mask;	/* Bits used by UIO */
+
+	bool	enable_merr_cfg;
+	bool	single_master;
+	bool	no_i2c_bridge;
+	bool	antenna_dvbt;
+	u16	antenna_gpio;
+
+	/* Firmware */
+	const char *microcode_name;
+	struct completion fw_wait_load;
+	const struct firmware *fw;
+	int qam_demod_parameter_count;
+};
+
+#define NEVER_LOCK 0
+#define NOT_LOCKED 1
+#define DEMOD_LOCK 2
+#define FEC_LOCK   3
+#define MPEG_LOCK  4
+
diff --git a/drivers/media/dvb-frontends/drxk_map.h b/drivers/media/dvb-frontends/drxk_map.h
new file mode 100644
index 0000000..23e16c1
--- /dev/null
+++ b/drivers/media/dvb-frontends/drxk_map.h
@@ -0,0 +1,451 @@
+#define  AUD_COMM_EXEC__A                                                  0x1000000
+#define    AUD_COMM_EXEC_STOP                                              0x0
+#define  FEC_COMM_EXEC__A                                                  0x1C00000
+#define    FEC_COMM_EXEC_STOP                                              0x0
+#define    FEC_COMM_EXEC_ACTIVE                                            0x1
+#define  FEC_DI_COMM_EXEC__A                                               0x1C20000
+#define    FEC_DI_COMM_EXEC_STOP                                           0x0
+#define  FEC_DI_INPUT_CTL__A                                               0x1C20016
+#define  FEC_RS_COMM_EXEC__A                                               0x1C30000
+#define    FEC_RS_COMM_EXEC_STOP                                           0x0
+#define  FEC_RS_MEASUREMENT_PERIOD__A                                      0x1C30012
+#define  FEC_RS_MEASUREMENT_PRESCALE__A                                    0x1C30013
+#define  FEC_OC_MODE__A                                                    0x1C40011
+#define    FEC_OC_MODE_PARITY__M                                           0x1
+#define  FEC_OC_DTO_MODE__A                                                0x1C40014
+#define    FEC_OC_DTO_MODE_DYNAMIC__M                                      0x1
+#define    FEC_OC_DTO_MODE_OFFSET_ENABLE__M                                0x4
+#define  FEC_OC_DTO_PERIOD__A                                              0x1C40015
+#define  FEC_OC_DTO_BURST_LEN__A                                           0x1C40018
+#define  FEC_OC_FCT_MODE__A                                                0x1C4001A
+#define  FEC_OC_FCT_MODE__PRE                                              0x0
+#define    FEC_OC_FCT_MODE_RAT_ENA__M                                      0x1
+#define    FEC_OC_FCT_MODE_VIRT_ENA__M                                     0x2
+#define  FEC_OC_TMD_MODE__A                                                0x1C4001E
+#define  FEC_OC_TMD_COUNT__A                                               0x1C4001F
+#define  FEC_OC_TMD_HI_MARGIN__A                                           0x1C40020
+#define  FEC_OC_TMD_LO_MARGIN__A                                           0x1C40021
+#define  FEC_OC_TMD_INT_UPD_RATE__A                                        0x1C40023
+#define  FEC_OC_AVR_PARM_A__A                                              0x1C40026
+#define  FEC_OC_AVR_PARM_B__A                                              0x1C40027
+#define  FEC_OC_RCN_GAIN__A                                                0x1C4002E
+#define  FEC_OC_RCN_CTL_RATE_LO__A                                         0x1C40030
+#define  FEC_OC_RCN_CTL_STEP_LO__A                                         0x1C40032
+#define  FEC_OC_RCN_CTL_STEP_HI__A                                         0x1C40033
+#define  FEC_OC_SNC_MODE__A                                                0x1C40040
+#define    FEC_OC_SNC_MODE_SHUTDOWN__M                                     0x10
+#define  FEC_OC_SNC_LWM__A                                                 0x1C40041
+#define  FEC_OC_SNC_HWM__A                                                 0x1C40042
+#define  FEC_OC_SNC_UNLOCK__A                                              0x1C40043
+#define  FEC_OC_SNC_FAIL_PERIOD__A                                         0x1C40046
+#define  FEC_OC_IPR_MODE__A                                                0x1C40048
+#define    FEC_OC_IPR_MODE_SERIAL__M                                       0x1
+#define    FEC_OC_IPR_MODE_MCLK_DIS_DAT_ABS__M                             0x4
+#define    FEC_OC_IPR_MODE_MVAL_DIS_PAR__M                                 0x10
+#define  FEC_OC_IPR_INVERT__A                                              0x1C40049
+#define    FEC_OC_IPR_INVERT_MD0__M                                        0x1
+#define    FEC_OC_IPR_INVERT_MD1__M                                        0x2
+#define    FEC_OC_IPR_INVERT_MD2__M                                        0x4
+#define    FEC_OC_IPR_INVERT_MD3__M                                        0x8
+#define    FEC_OC_IPR_INVERT_MD4__M                                        0x10
+#define    FEC_OC_IPR_INVERT_MD5__M                                        0x20
+#define    FEC_OC_IPR_INVERT_MD6__M                                        0x40
+#define    FEC_OC_IPR_INVERT_MD7__M                                        0x80
+#define    FEC_OC_IPR_INVERT_MERR__M                                       0x100
+#define    FEC_OC_IPR_INVERT_MSTRT__M                                      0x200
+#define    FEC_OC_IPR_INVERT_MVAL__M                                       0x400
+#define    FEC_OC_IPR_INVERT_MCLK__M                                       0x800
+#define  FEC_OC_OCR_INVERT__A                                              0x1C40052
+#define  IQM_COMM_EXEC__A                                                  0x1800000
+#define      IQM_COMM_EXEC_B_STOP                                          0x0
+#define      IQM_COMM_EXEC_B_ACTIVE                                        0x1
+#define  IQM_FS_RATE_OFS_LO__A                                             0x1820010
+#define  IQM_FS_ADJ_SEL__A                                                 0x1820014
+#define      IQM_FS_ADJ_SEL_B_OFF                                          0x0
+#define      IQM_FS_ADJ_SEL_B_QAM                                          0x1
+#define      IQM_FS_ADJ_SEL_B_VSB                                          0x2
+#define  IQM_FD_RATESEL__A                                                 0x1830010
+#define  IQM_RC_RATE_OFS_LO__A                                             0x1840010
+#define  IQM_RC_RATE_OFS_LO__W                                             16
+#define  IQM_RC_RATE_OFS_LO__M                                             0xFFFF
+#define  IQM_RC_RATE_OFS_HI__M                                             0xFF
+#define  IQM_RC_ADJ_SEL__A                                                 0x1840014
+#define      IQM_RC_ADJ_SEL_B_OFF                                          0x0
+#define      IQM_RC_ADJ_SEL_B_QAM                                          0x1
+#define      IQM_RC_ADJ_SEL_B_VSB                                          0x2
+#define  IQM_RC_STRETCH__A                                                 0x1840016
+#define  IQM_CF_COMM_INT_MSK__A                                            0x1860006
+#define  IQM_CF_SYMMETRIC__A                                               0x1860010
+#define  IQM_CF_MIDTAP__A                                                  0x1860011
+#define    IQM_CF_MIDTAP_RE__B                                             0
+#define    IQM_CF_MIDTAP_IM__B                                             1
+#define  IQM_CF_OUT_ENA__A                                                 0x1860012
+#define    IQM_CF_OUT_ENA_QAM__B                                           1
+#define    IQM_CF_OUT_ENA_OFDM__M                                          0x4
+#define  IQM_CF_ADJ_SEL__A                                                 0x1860013
+#define  IQM_CF_SCALE__A                                                   0x1860014
+#define  IQM_CF_SCALE_SH__A                                                0x1860015
+#define  IQM_CF_SCALE_SH__PRE                                              0x0
+#define  IQM_CF_POW_MEAS_LEN__A                                            0x1860017
+#define  IQM_CF_DS_ENA__A                                                  0x1860019
+#define  IQM_CF_TAP_RE0__A                                                 0x1860020
+#define  IQM_CF_TAP_IM0__A                                                 0x1860040
+#define  IQM_CF_CLP_VAL__A                                                 0x1860060
+#define  IQM_CF_DATATH__A                                                  0x1860061
+#define  IQM_CF_PKDTH__A                                                   0x1860062
+#define  IQM_CF_WND_LEN__A                                                 0x1860063
+#define  IQM_CF_DET_LCT__A                                                 0x1860064
+#define  IQM_CF_BYPASSDET__A                                               0x1860067
+#define  IQM_AF_COMM_EXEC__A                                               0x1870000
+#define    IQM_AF_COMM_EXEC_ACTIVE                                         0x1
+#define  IQM_AF_CLKNEG__A                                                  0x1870012
+#define    IQM_AF_CLKNEG_CLKNEGDATA__M                                     0x2
+#define      IQM_AF_CLKNEG_CLKNEGDATA_CLK_ADC_DATA_POS                     0x0
+#define      IQM_AF_CLKNEG_CLKNEGDATA_CLK_ADC_DATA_NEG                     0x2
+#define  IQM_AF_START_LOCK__A                                              0x187001B
+#define  IQM_AF_PHASE0__A                                                  0x187001C
+#define  IQM_AF_PHASE1__A                                                  0x187001D
+#define  IQM_AF_PHASE2__A                                                  0x187001E
+#define  IQM_AF_CLP_LEN__A                                                 0x1870023
+#define  IQM_AF_CLP_TH__A                                                  0x1870024
+#define  IQM_AF_SNS_LEN__A                                                 0x1870026
+#define  IQM_AF_AGC_IF__A                                                  0x1870028
+#define  IQM_AF_AGC_RF__A                                                  0x1870029
+#define  IQM_AF_PDREF__A                                                   0x187002B
+#define  IQM_AF_PDREF__M                                                   0x1F
+#define  IQM_AF_STDBY__A                                                   0x187002C
+#define      IQM_AF_STDBY_STDBY_ADC_STANDBY                                0x2
+#define      IQM_AF_STDBY_STDBY_AMP_STANDBY                                0x4
+#define      IQM_AF_STDBY_STDBY_PD_STANDBY                                 0x8
+#define      IQM_AF_STDBY_STDBY_TAGC_IF_STANDBY                            0x10
+#define      IQM_AF_STDBY_STDBY_TAGC_RF_STANDBY                            0x20
+#define  IQM_AF_AMUX__A                                                    0x187002D
+#define    IQM_AF_AMUX_SIGNAL2ADC                                          0x1
+#define  IQM_AF_UPD_SEL__A                                                 0x187002F
+#define  IQM_AF_INC_LCT__A                                                 0x1870034
+#define  IQM_AF_INC_BYPASS__A                                              0x1870036
+#define  OFDM_CP_COMM_EXEC__A                                              0x2800000
+#define    OFDM_CP_COMM_EXEC_STOP                                          0x0
+#define  OFDM_EC_SB_PRIOR__A                                               0x3410013
+#define    OFDM_EC_SB_PRIOR_HI                                             0x0
+#define    OFDM_EC_SB_PRIOR_LO                                             0x1
+#define  OFDM_EQ_TOP_TD_TPS_CONST__A                                       0x3010054
+#define  OFDM_EQ_TOP_TD_TPS_CONST__M                                       0x3
+#define    OFDM_EQ_TOP_TD_TPS_CONST_64QAM                                  0x2
+#define  OFDM_EQ_TOP_TD_TPS_CODE_HP__A                                     0x3010056
+#define  OFDM_EQ_TOP_TD_TPS_CODE_HP__M                                     0x7
+#define    OFDM_EQ_TOP_TD_TPS_CODE_LP_7_8                                  0x4
+#define  OFDM_EQ_TOP_TD_SQR_ERR_I__A                                       0x301005E
+#define  OFDM_EQ_TOP_TD_SQR_ERR_Q__A                                       0x301005F
+#define  OFDM_EQ_TOP_TD_SQR_ERR_EXP__A                                     0x3010060
+#define  OFDM_EQ_TOP_TD_REQ_SMB_CNT__A                                     0x3010061
+#define  OFDM_EQ_TOP_TD_TPS_PWR_OFS__A                                     0x3010062
+#define  OFDM_LC_COMM_EXEC__A                                              0x3800000
+#define    OFDM_LC_COMM_EXEC_STOP                                          0x0
+#define  OFDM_SC_COMM_EXEC__A                                              0x3C00000
+#define    OFDM_SC_COMM_EXEC_STOP                                          0x0
+#define  OFDM_SC_COMM_STATE__A                                             0x3C00001
+#define  OFDM_SC_RA_RAM_PARAM0__A                                          0x3C20040
+#define  OFDM_SC_RA_RAM_PARAM1__A                                          0x3C20041
+#define  OFDM_SC_RA_RAM_CMD_ADDR__A                                        0x3C20042
+#define  OFDM_SC_RA_RAM_CMD__A                                             0x3C20043
+#define    OFDM_SC_RA_RAM_CMD_NULL                                         0x0
+#define    OFDM_SC_RA_RAM_CMD_PROC_START                                   0x1
+#define    OFDM_SC_RA_RAM_CMD_SET_PREF_PARAM                               0x3
+#define    OFDM_SC_RA_RAM_CMD_PROGRAM_PARAM                                0x4
+#define    OFDM_SC_RA_RAM_CMD_GET_OP_PARAM                                 0x5
+#define    OFDM_SC_RA_RAM_CMD_USER_IO                                      0x6
+#define    OFDM_SC_RA_RAM_CMD_SET_TIMER                                    0x7
+#define    OFDM_SC_RA_RAM_CMD_SET_ECHO_TIMING                              0x8
+#define    OFDM_SC_RA_RAM_SW_EVENT_RUN_NMASK__M                            0x1
+#define    OFDM_SC_RA_RAM_LOCKTRACK_MIN                                    0x1
+#define  OFDM_SC_RA_RAM_OP_PARAM__A                                        0x3C20048
+#define    OFDM_SC_RA_RAM_OP_PARAM_MODE__M                                 0x3
+#define      OFDM_SC_RA_RAM_OP_PARAM_MODE_2K                               0x0
+#define      OFDM_SC_RA_RAM_OP_PARAM_MODE_8K                               0x1
+#define      OFDM_SC_RA_RAM_OP_PARAM_GUARD_32                              0x0
+#define      OFDM_SC_RA_RAM_OP_PARAM_GUARD_16                              0x4
+#define      OFDM_SC_RA_RAM_OP_PARAM_GUARD_8                               0x8
+#define      OFDM_SC_RA_RAM_OP_PARAM_GUARD_4                               0xC
+#define      OFDM_SC_RA_RAM_OP_PARAM_CONST_QPSK                            0x0
+#define      OFDM_SC_RA_RAM_OP_PARAM_CONST_QAM16                           0x10
+#define      OFDM_SC_RA_RAM_OP_PARAM_CONST_QAM64                           0x20
+#define      OFDM_SC_RA_RAM_OP_PARAM_HIER_NO                               0x0
+#define      OFDM_SC_RA_RAM_OP_PARAM_HIER_A1                               0x40
+#define      OFDM_SC_RA_RAM_OP_PARAM_HIER_A2                               0x80
+#define      OFDM_SC_RA_RAM_OP_PARAM_HIER_A4                               0xC0
+#define      OFDM_SC_RA_RAM_OP_PARAM_RATE_1_2                              0x0
+#define      OFDM_SC_RA_RAM_OP_PARAM_RATE_2_3                              0x200
+#define      OFDM_SC_RA_RAM_OP_PARAM_RATE_3_4                              0x400
+#define      OFDM_SC_RA_RAM_OP_PARAM_RATE_5_6                              0x600
+#define      OFDM_SC_RA_RAM_OP_PARAM_RATE_7_8                              0x800
+#define      OFDM_SC_RA_RAM_OP_PARAM_PRIO_HI                               0x0
+#define      OFDM_SC_RA_RAM_OP_PARAM_PRIO_LO                               0x1000
+#define    OFDM_SC_RA_RAM_OP_AUTO_MODE__M                                  0x1
+#define    OFDM_SC_RA_RAM_OP_AUTO_GUARD__M                                 0x2
+#define    OFDM_SC_RA_RAM_OP_AUTO_CONST__M                                 0x4
+#define    OFDM_SC_RA_RAM_OP_AUTO_HIER__M                                  0x8
+#define    OFDM_SC_RA_RAM_OP_AUTO_RATE__M                                  0x10
+#define  OFDM_SC_RA_RAM_LOCK__A                                            0x3C2004B
+#define    OFDM_SC_RA_RAM_LOCK_DEMOD__M                                    0x1
+#define    OFDM_SC_RA_RAM_LOCK_FEC__M                                      0x2
+#define    OFDM_SC_RA_RAM_LOCK_MPEG__M                                     0x4
+#define    OFDM_SC_RA_RAM_LOCK_NODVBT__M                                   0x8
+#define  OFDM_SC_RA_RAM_BE_OPT_DELAY__A                                    0x3C2004D
+#define  OFDM_SC_RA_RAM_BE_OPT_INIT_DELAY__A                               0x3C2004E
+#define  OFDM_SC_RA_RAM_ECHO_THRES__A                                      0x3C2004F
+#define    OFDM_SC_RA_RAM_ECHO_THRES_8K__B                                 0
+#define    OFDM_SC_RA_RAM_ECHO_THRES_8K__M                                 0xFF
+#define    OFDM_SC_RA_RAM_ECHO_THRES_2K__B                                 8
+#define    OFDM_SC_RA_RAM_ECHO_THRES_2K__M                                 0xFF00
+#define  OFDM_SC_RA_RAM_CONFIG__A                                          0x3C20050
+#define    OFDM_SC_RA_RAM_CONFIG_NE_FIX_ENABLE__M                          0x800
+#define  OFDM_SC_RA_RAM_FR_THRES_8K__A                                     0x3C2007D
+#define  OFDM_SC_RA_RAM_NI_INIT_2K_PER_LEFT__A                             0x3C200E0
+#define  OFDM_SC_RA_RAM_NI_INIT_2K_PER_RIGHT__A                            0x3C200E1
+#define  OFDM_SC_RA_RAM_NI_INIT_8K_PER_LEFT__A                             0x3C200E3
+#define  OFDM_SC_RA_RAM_NI_INIT_8K_PER_RIGHT__A                            0x3C200E4
+#define  OFDM_SC_RA_RAM_SRMM_FIX_FACT_8K__A                                0x3C200F8
+#define  QAM_COMM_EXEC__A                                                  0x1400000
+#define    QAM_COMM_EXEC_STOP                                              0x0
+#define    QAM_COMM_EXEC_ACTIVE                                            0x1
+#define    QAM_TOP_ANNEX_A                                                 0x0
+#define    QAM_TOP_ANNEX_C                                                 0x2
+#define  QAM_SL_ERR_POWER__A                                               0x1430017
+#define  QAM_DQ_QUAL_FUN0__A                                               0x1440018
+#define  QAM_DQ_QUAL_FUN1__A                                               0x1440019
+#define  QAM_DQ_QUAL_FUN2__A                                               0x144001A
+#define  QAM_DQ_QUAL_FUN3__A                                               0x144001B
+#define  QAM_DQ_QUAL_FUN4__A                                               0x144001C
+#define  QAM_DQ_QUAL_FUN5__A                                               0x144001D
+#define  QAM_LC_MODE__A                                                    0x1450010
+#define  QAM_LC_QUAL_TAB0__A                                               0x1450018
+#define  QAM_LC_QUAL_TAB1__A                                               0x1450019
+#define  QAM_LC_QUAL_TAB2__A                                               0x145001A
+#define  QAM_LC_QUAL_TAB3__A                                               0x145001B
+#define  QAM_LC_QUAL_TAB4__A                                               0x145001C
+#define  QAM_LC_QUAL_TAB5__A                                               0x145001D
+#define  QAM_LC_QUAL_TAB6__A                                               0x145001E
+#define  QAM_LC_QUAL_TAB8__A                                               0x145001F
+#define  QAM_LC_QUAL_TAB9__A                                               0x1450020
+#define  QAM_LC_QUAL_TAB10__A                                              0x1450021
+#define  QAM_LC_QUAL_TAB12__A                                              0x1450022
+#define  QAM_LC_QUAL_TAB15__A                                              0x1450023
+#define  QAM_LC_QUAL_TAB16__A                                              0x1450024
+#define  QAM_LC_QUAL_TAB20__A                                              0x1450025
+#define  QAM_LC_QUAL_TAB25__A                                              0x1450026
+#define  QAM_LC_LPF_FACTORP__A                                             0x1450028
+#define  QAM_LC_LPF_FACTORI__A                                             0x1450029
+#define  QAM_LC_RATE_LIMIT__A                                              0x145002A
+#define  QAM_LC_SYMBOL_FREQ__A                                             0x145002B
+#define  QAM_SY_TIMEOUT__A                                                 0x1470011
+#define  QAM_SY_TIMEOUT__PRE                                               0x3A98
+#define  QAM_SY_SYNC_LWM__A                                                0x1470012
+#define  QAM_SY_SYNC_AWM__A                                                0x1470013
+#define  QAM_SY_SYNC_HWM__A                                                0x1470014
+#define  QAM_SY_SP_INV__A                                                  0x1470017
+#define    QAM_SY_SP_INV_SPECTRUM_INV_DIS                                  0x0
+#define  SCU_COMM_EXEC__A                                                  0x800000
+#define    SCU_COMM_EXEC_STOP                                              0x0
+#define    SCU_COMM_EXEC_ACTIVE                                            0x1
+#define    SCU_COMM_EXEC_HOLD                                              0x2
+#define  SCU_RAM_DRIVER_DEBUG__A                                           0x831EBF
+#define  SCU_RAM_QAM_FSM_STEP_PERIOD__A                                    0x831EC4
+#define  SCU_RAM_GPIO__A                                                   0x831EC7
+#define      SCU_RAM_GPIO_HW_LOCK_IND_DISABLE                              0x0
+#define  SCU_RAM_AGC_CLP_CTRL_MODE__A                                      0x831EC8
+#define  SCU_RAM_FEC_ACCUM_PKT_FAILURES__A                                 0x831ECB
+#define  SCU_RAM_FEC_PRE_RS_BER_FILTER_SH__A                               0x831F05
+#define  SCU_RAM_AGC_FAST_SNS_CTRL_DELAY__A                                0x831F15
+#define  SCU_RAM_AGC_KI_CYCLEN__A                                          0x831F17
+#define  SCU_RAM_AGC_SNS_CYCLEN__A                                         0x831F18
+#define  SCU_RAM_AGC_RF_SNS_DEV_MAX__A                                     0x831F19
+#define  SCU_RAM_AGC_RF_SNS_DEV_MIN__A                                     0x831F1A
+#define  SCU_RAM_AGC_RF_MAX__A                                             0x831F1B
+#define  SCU_RAM_AGC_CONFIG__A                                             0x831F24
+#define    SCU_RAM_AGC_CONFIG_DISABLE_RF_AGC__M                            0x1
+#define    SCU_RAM_AGC_CONFIG_DISABLE_IF_AGC__M                            0x2
+#define    SCU_RAM_AGC_CONFIG_INV_IF_POL__M                                0x100
+#define    SCU_RAM_AGC_CONFIG_INV_RF_POL__M                                0x200
+#define  SCU_RAM_AGC_KI__A                                                 0x831F25
+#define    SCU_RAM_AGC_KI_RF__B                                            4
+#define    SCU_RAM_AGC_KI_RF__M                                            0xF0
+#define    SCU_RAM_AGC_KI_IF__B                                            8
+#define    SCU_RAM_AGC_KI_IF__M                                            0xF00
+#define  SCU_RAM_AGC_KI_RED__A                                             0x831F26
+#define    SCU_RAM_AGC_KI_RED_RAGC_RED__B                                  2
+#define    SCU_RAM_AGC_KI_RED_RAGC_RED__M                                  0xC
+#define    SCU_RAM_AGC_KI_RED_IAGC_RED__B                                  4
+#define    SCU_RAM_AGC_KI_RED_IAGC_RED__M                                  0x30
+#define  SCU_RAM_AGC_KI_INNERGAIN_MIN__A                                   0x831F27
+#define  SCU_RAM_AGC_KI_MINGAIN__A                                         0x831F28
+#define  SCU_RAM_AGC_KI_MAXGAIN__A                                         0x831F29
+#define  SCU_RAM_AGC_KI_MAXMINGAIN_TH__A                                   0x831F2A
+#define  SCU_RAM_AGC_KI_MIN__A                                             0x831F2B
+#define  SCU_RAM_AGC_KI_MAX__A                                             0x831F2C
+#define  SCU_RAM_AGC_CLP_SUM__A                                            0x831F2D
+#define  SCU_RAM_AGC_CLP_SUM_MIN__A                                        0x831F2E
+#define  SCU_RAM_AGC_CLP_SUM_MAX__A                                        0x831F2F
+#define  SCU_RAM_AGC_CLP_CYCLEN__A                                         0x831F30
+#define  SCU_RAM_AGC_CLP_CYCCNT__A                                         0x831F31
+#define  SCU_RAM_AGC_CLP_DIR_TO__A                                         0x831F32
+#define  SCU_RAM_AGC_CLP_DIR_WD__A                                         0x831F33
+#define  SCU_RAM_AGC_CLP_DIR_STP__A                                        0x831F34
+#define  SCU_RAM_AGC_SNS_SUM__A                                            0x831F35
+#define  SCU_RAM_AGC_SNS_SUM_MIN__A                                        0x831F36
+#define  SCU_RAM_AGC_SNS_SUM_MAX__A                                        0x831F37
+#define  SCU_RAM_AGC_SNS_CYCCNT__A                                         0x831F38
+#define  SCU_RAM_AGC_SNS_DIR_TO__A                                         0x831F39
+#define  SCU_RAM_AGC_SNS_DIR_WD__A                                         0x831F3A
+#define  SCU_RAM_AGC_SNS_DIR_STP__A                                        0x831F3B
+#define  SCU_RAM_AGC_INGAIN_TGT__A                                         0x831F3D
+#define  SCU_RAM_AGC_INGAIN_TGT_MIN__A                                     0x831F3E
+#define  SCU_RAM_AGC_INGAIN_TGT_MAX__A                                     0x831F3F
+#define  SCU_RAM_AGC_IF_IACCU_HI__A                                        0x831F40
+#define  SCU_RAM_AGC_IF_IACCU_LO__A                                        0x831F41
+#define  SCU_RAM_AGC_IF_IACCU_HI_TGT__A                                    0x831F42
+#define  SCU_RAM_AGC_IF_IACCU_HI_TGT_MIN__A                                0x831F43
+#define  SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A                                0x831F44
+#define  SCU_RAM_AGC_RF_IACCU_HI__A                                        0x831F45
+#define  SCU_RAM_AGC_RF_IACCU_LO__A                                        0x831F46
+#define  SCU_RAM_AGC_RF_IACCU_HI_CO__A                                     0x831F47
+#define  SCU_RAM_QAM_FSM_MEDIAN_AV_MULT__A                                 0x831F84
+#define  SCU_RAM_QAM_FSM_RADIUS_AV_LIMIT__A                                0x831F85
+#define  SCU_RAM_QAM_FSM_LCAVG_OFFSET1__A                                  0x831F86
+#define  SCU_RAM_QAM_FSM_LCAVG_OFFSET2__A                                  0x831F87
+#define  SCU_RAM_QAM_FSM_LCAVG_OFFSET3__A                                  0x831F88
+#define  SCU_RAM_QAM_FSM_LCAVG_OFFSET4__A                                  0x831F89
+#define  SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A                                  0x831F8A
+#define  SCU_RAM_QAM_FSM_RTH__A                                            0x831F8E
+#define  SCU_RAM_QAM_FSM_FTH__A                                            0x831F8F
+#define  SCU_RAM_QAM_FSM_PTH__A                                            0x831F90
+#define  SCU_RAM_QAM_FSM_MTH__A                                            0x831F91
+#define  SCU_RAM_QAM_FSM_CTH__A                                            0x831F92
+#define  SCU_RAM_QAM_FSM_QTH__A                                            0x831F93
+#define  SCU_RAM_QAM_FSM_RATE_LIM__A                                       0x831F94
+#define  SCU_RAM_QAM_FSM_FREQ_LIM__A                                       0x831F95
+#define  SCU_RAM_QAM_FSM_COUNT_LIM__A                                      0x831F96
+#define  SCU_RAM_QAM_LC_CA_COARSE__A                                       0x831F97
+#define  SCU_RAM_QAM_LC_CA_FINE__A                                         0x831F99
+#define  SCU_RAM_QAM_LC_CP_COARSE__A                                       0x831F9A
+#define  SCU_RAM_QAM_LC_CP_MEDIUM__A                                       0x831F9B
+#define  SCU_RAM_QAM_LC_CP_FINE__A                                         0x831F9C
+#define  SCU_RAM_QAM_LC_CI_COARSE__A                                       0x831F9D
+#define  SCU_RAM_QAM_LC_CI_MEDIUM__A                                       0x831F9E
+#define  SCU_RAM_QAM_LC_CI_FINE__A                                         0x831F9F
+#define  SCU_RAM_QAM_LC_EP_COARSE__A                                       0x831FA0
+#define  SCU_RAM_QAM_LC_EP_MEDIUM__A                                       0x831FA1
+#define  SCU_RAM_QAM_LC_EP_FINE__A                                         0x831FA2
+#define  SCU_RAM_QAM_LC_EI_COARSE__A                                       0x831FA3
+#define  SCU_RAM_QAM_LC_EI_MEDIUM__A                                       0x831FA4
+#define  SCU_RAM_QAM_LC_EI_FINE__A                                         0x831FA5
+#define  SCU_RAM_QAM_LC_CF_COARSE__A                                       0x831FA6
+#define  SCU_RAM_QAM_LC_CF_MEDIUM__A                                       0x831FA7
+#define  SCU_RAM_QAM_LC_CF_FINE__A                                         0x831FA8
+#define  SCU_RAM_QAM_LC_CF1_COARSE__A                                      0x831FA9
+#define  SCU_RAM_QAM_LC_CF1_MEDIUM__A                                      0x831FAA
+#define  SCU_RAM_QAM_LC_CF1_FINE__A                                        0x831FAB
+#define  SCU_RAM_QAM_SL_SIG_POWER__A                                       0x831FAC
+#define  SCU_RAM_QAM_EQ_CMA_RAD0__A                                        0x831FAD
+#define  SCU_RAM_QAM_EQ_CMA_RAD1__A                                        0x831FAE
+#define  SCU_RAM_QAM_EQ_CMA_RAD2__A                                        0x831FAF
+#define  SCU_RAM_QAM_EQ_CMA_RAD3__A                                        0x831FB0
+#define  SCU_RAM_QAM_EQ_CMA_RAD4__A                                        0x831FB1
+#define  SCU_RAM_QAM_EQ_CMA_RAD5__A                                        0x831FB2
+#define      SCU_RAM_QAM_LOCKED_LOCKED_DEMOD_LOCKED                        0x4000
+#define      SCU_RAM_QAM_LOCKED_LOCKED_LOCKED                              0x8000
+#define      SCU_RAM_QAM_LOCKED_LOCKED_NEVER_LOCK                          0xC000
+#define  SCU_RAM_AGC_FAST_CLP_CTRL_DELAY__A                                0x831FEA
+#define  SCU_RAM_DRIVER_VER_HI__A                                          0x831FEB
+#define  SCU_RAM_DRIVER_VER_LO__A                                          0x831FEC
+#define  SCU_RAM_PARAM_15__A                                               0x831FED
+#define  SCU_RAM_PARAM_0__A                                                0x831FFC
+#define  SCU_RAM_COMMAND__A                                                0x831FFD
+#define    SCU_RAM_COMMAND_CMD_DEMOD_RESET                                 0x1
+#define    SCU_RAM_COMMAND_CMD_DEMOD_SET_ENV                               0x2
+#define    SCU_RAM_COMMAND_CMD_DEMOD_SET_PARAM                             0x3
+#define    SCU_RAM_COMMAND_CMD_DEMOD_START                                 0x4
+#define    SCU_RAM_COMMAND_CMD_DEMOD_GET_LOCK                              0x5
+#define    SCU_RAM_COMMAND_CMD_DEMOD_STOP                                  0x9
+#define      SCU_RAM_COMMAND_STANDARD_QAM                                  0x200
+#define      SCU_RAM_COMMAND_STANDARD_OFDM                                 0x400
+#define  SIO_TOP_COMM_KEY__A                                               0x41000F
+#define    SIO_TOP_COMM_KEY_KEY                                            0xFABA
+#define  SIO_TOP_JTAGID_LO__A                                              0x410012
+#define  SIO_HI_RA_RAM_RES__A                                              0x420031
+#define  SIO_HI_RA_RAM_CMD__A                                              0x420032
+#define    SIO_HI_RA_RAM_CMD_RESET                                         0x2
+#define    SIO_HI_RA_RAM_CMD_CONFIG                                        0x3
+#define    SIO_HI_RA_RAM_CMD_BRDCTRL                                       0x7
+#define  SIO_HI_RA_RAM_PAR_1__A                                            0x420033
+#define      SIO_HI_RA_RAM_PAR_1_PAR1_SEC_KEY                              0x3945
+#define  SIO_HI_RA_RAM_PAR_2__A                                            0x420034
+#define    SIO_HI_RA_RAM_PAR_2_CFG_DIV__M                                  0x7F
+#define      SIO_HI_RA_RAM_PAR_2_BRD_CFG_OPEN                              0x0
+#define      SIO_HI_RA_RAM_PAR_2_BRD_CFG_CLOSED                            0x4
+#define  SIO_HI_RA_RAM_PAR_3__A                                            0x420035
+#define    SIO_HI_RA_RAM_PAR_3_CFG_DBL_SDA__M                              0x7F
+#define    SIO_HI_RA_RAM_PAR_3_CFG_DBL_SCL__B                              7
+#define      SIO_HI_RA_RAM_PAR_3_ACP_RW_READ                               0x0
+#define      SIO_HI_RA_RAM_PAR_3_ACP_RW_WRITE                              0x8
+#define  SIO_HI_RA_RAM_PAR_4__A                                            0x420036
+#define  SIO_HI_RA_RAM_PAR_5__A                                            0x420037
+#define      SIO_HI_RA_RAM_PAR_5_CFG_SLV0_SLAVE                            0x1
+#define    SIO_HI_RA_RAM_PAR_5_CFG_SLEEP__M                                0x8
+#define      SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ                             0x8
+#define  SIO_HI_RA_RAM_PAR_6__A                                            0x420038
+#define  SIO_CC_PLL_LOCK__A                                                0x450012
+#define  SIO_CC_PWD_MODE__A                                                0x450015
+#define      SIO_CC_PWD_MODE_LEVEL_NONE                                    0x0
+#define      SIO_CC_PWD_MODE_LEVEL_OFDM                                    0x1
+#define      SIO_CC_PWD_MODE_LEVEL_CLOCK                                   0x2
+#define      SIO_CC_PWD_MODE_LEVEL_PLL                                     0x3
+#define      SIO_CC_PWD_MODE_LEVEL_OSC                                     0x4
+#define  SIO_CC_SOFT_RST__A                                                0x450016
+#define    SIO_CC_SOFT_RST_OFDM__M                                         0x1
+#define    SIO_CC_SOFT_RST_SYS__M                                          0x2
+#define    SIO_CC_SOFT_RST_OSC__M                                          0x4
+#define  SIO_CC_UPDATE__A                                                  0x450017
+#define    SIO_CC_UPDATE_KEY                                               0xFABA
+#define  SIO_OFDM_SH_OFDM_RING_ENABLE__A                                   0x470010
+#define    SIO_OFDM_SH_OFDM_RING_ENABLE_OFF                                0x0
+#define    SIO_OFDM_SH_OFDM_RING_ENABLE_ON                                 0x1
+#define  SIO_OFDM_SH_OFDM_RING_STATUS__A                                   0x470012
+#define    SIO_OFDM_SH_OFDM_RING_STATUS_DOWN                               0x0
+#define    SIO_OFDM_SH_OFDM_RING_STATUS_ENABLED                            0x1
+#define  SIO_BL_COMM_EXEC__A                                               0x480000
+#define    SIO_BL_COMM_EXEC_ACTIVE                                         0x1
+#define  SIO_BL_STATUS__A                                                  0x480010
+#define  SIO_BL_MODE__A                                                    0x480011
+#define    SIO_BL_MODE_DIRECT                                              0x0
+#define    SIO_BL_MODE_CHAIN                                               0x1
+#define  SIO_BL_ENABLE__A                                                  0x480012
+#define    SIO_BL_ENABLE_ON                                                0x1
+#define  SIO_BL_TGT_HDR__A                                                 0x480014
+#define  SIO_BL_TGT_ADDR__A                                                0x480015
+#define  SIO_BL_SRC_ADDR__A                                                0x480016
+#define  SIO_BL_SRC_LEN__A                                                 0x480017
+#define  SIO_BL_CHAIN_ADDR__A                                              0x480018
+#define  SIO_BL_CHAIN_LEN__A                                               0x480019
+#define  SIO_PDR_MON_CFG__A                                                0x7F0010
+#define  SIO_PDR_UIO_IN_HI__A                                              0x7F0015
+#define  SIO_PDR_UIO_OUT_LO__A                                             0x7F0016
+#define  SIO_PDR_OHW_CFG__A                                                0x7F001F
+#define    SIO_PDR_OHW_CFG_FREF_SEL__M                                     0x3
+#define  SIO_PDR_GPIO_CFG__A                                               0x7F0021
+#define  SIO_PDR_MSTRT_CFG__A                                              0x7F0025
+#define  SIO_PDR_MERR_CFG__A                                               0x7F0026
+#define  SIO_PDR_MCLK_CFG__A                                               0x7F0028
+#define    SIO_PDR_MCLK_CFG_DRIVE__B                                       3
+#define  SIO_PDR_MVAL_CFG__A                                               0x7F0029
+#define  SIO_PDR_MD0_CFG__A                                                0x7F002A
+#define    SIO_PDR_MD0_CFG_DRIVE__B                                        3
+#define  SIO_PDR_MD1_CFG__A                                                0x7F002B
+#define  SIO_PDR_MD2_CFG__A                                                0x7F002C
+#define  SIO_PDR_MD3_CFG__A                                                0x7F002D
+#define  SIO_PDR_MD4_CFG__A                                                0x7F002F
+#define  SIO_PDR_MD5_CFG__A                                                0x7F0030
+#define  SIO_PDR_MD6_CFG__A                                                0x7F0031
+#define  SIO_PDR_MD7_CFG__A                                                0x7F0032
+#define  SIO_PDR_SMA_RX_CFG__A                                             0x7F0037
+#define  SIO_PDR_SMA_TX_CFG__A                                             0x7F0038
diff --git a/drivers/media/dvb-frontends/ds3000.c b/drivers/media/dvb-frontends/ds3000.c
new file mode 100644
index 0000000..4c8ac26
--- /dev/null
+++ b/drivers/media/dvb-frontends/ds3000.c
@@ -0,0 +1,1312 @@
+/*
+    Montage Technology DS3000/TS2020 - DVBS/S2 Demodulator/Tuner driver
+    Copyright (C) 2009 Konstantin Dimitrov <kosio.dimitrov@gmail.com>
+
+    Copyright (C) 2009 TurboSight.com
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/firmware.h>
+
+#include "dvb_frontend.h"
+#include "ds3000.h"
+
+static int debug;
+
+#define dprintk(args...) \
+	do { \
+		if (debug) \
+			printk(args); \
+	} while (0)
+
+/* as of March 2009 current DS3000 firmware version is 1.78 */
+/* DS3000 FW v1.78 MD5: a32d17910c4f370073f9346e71d34b80 */
+#define DS3000_DEFAULT_FIRMWARE "dvb-fe-ds3000.fw"
+
+#define DS3000_SAMPLE_RATE 96000 /* in kHz */
+#define DS3000_XTAL_FREQ   27000 /* in kHz */
+
+/* Register values to initialise the demod in DVB-S mode */
+static u8 ds3000_dvbs_init_tab[] = {
+	0x23, 0x05,
+	0x08, 0x03,
+	0x0c, 0x00,
+	0x21, 0x54,
+	0x25, 0x82,
+	0x27, 0x31,
+	0x30, 0x08,
+	0x31, 0x40,
+	0x32, 0x32,
+	0x33, 0x35,
+	0x35, 0xff,
+	0x3a, 0x00,
+	0x37, 0x10,
+	0x38, 0x10,
+	0x39, 0x02,
+	0x42, 0x60,
+	0x4a, 0x40,
+	0x4b, 0x04,
+	0x4d, 0x91,
+	0x5d, 0xc8,
+	0x50, 0x77,
+	0x51, 0x77,
+	0x52, 0x36,
+	0x53, 0x36,
+	0x56, 0x01,
+	0x63, 0x43,
+	0x64, 0x30,
+	0x65, 0x40,
+	0x68, 0x26,
+	0x69, 0x4c,
+	0x70, 0x20,
+	0x71, 0x70,
+	0x72, 0x04,
+	0x73, 0x00,
+	0x70, 0x40,
+	0x71, 0x70,
+	0x72, 0x04,
+	0x73, 0x00,
+	0x70, 0x60,
+	0x71, 0x70,
+	0x72, 0x04,
+	0x73, 0x00,
+	0x70, 0x80,
+	0x71, 0x70,
+	0x72, 0x04,
+	0x73, 0x00,
+	0x70, 0xa0,
+	0x71, 0x70,
+	0x72, 0x04,
+	0x73, 0x00,
+	0x70, 0x1f,
+	0x76, 0x00,
+	0x77, 0xd1,
+	0x78, 0x0c,
+	0x79, 0x80,
+	0x7f, 0x04,
+	0x7c, 0x00,
+	0x80, 0x86,
+	0x81, 0xa6,
+	0x85, 0x04,
+	0xcd, 0xf4,
+	0x90, 0x33,
+	0xa0, 0x44,
+	0xc0, 0x18,
+	0xc3, 0x10,
+	0xc4, 0x08,
+	0xc5, 0x80,
+	0xc6, 0x80,
+	0xc7, 0x0a,
+	0xc8, 0x1a,
+	0xc9, 0x80,
+	0xfe, 0x92,
+	0xe0, 0xf8,
+	0xe6, 0x8b,
+	0xd0, 0x40,
+	0xf8, 0x20,
+	0xfa, 0x0f,
+	0xfd, 0x20,
+	0xad, 0x20,
+	0xae, 0x07,
+	0xb8, 0x00,
+};
+
+/* Register values to initialise the demod in DVB-S2 mode */
+static u8 ds3000_dvbs2_init_tab[] = {
+	0x23, 0x0f,
+	0x08, 0x07,
+	0x0c, 0x00,
+	0x21, 0x54,
+	0x25, 0x82,
+	0x27, 0x31,
+	0x30, 0x08,
+	0x31, 0x32,
+	0x32, 0x32,
+	0x33, 0x35,
+	0x35, 0xff,
+	0x3a, 0x00,
+	0x37, 0x10,
+	0x38, 0x10,
+	0x39, 0x02,
+	0x42, 0x60,
+	0x4a, 0x80,
+	0x4b, 0x04,
+	0x4d, 0x81,
+	0x5d, 0x88,
+	0x50, 0x36,
+	0x51, 0x36,
+	0x52, 0x36,
+	0x53, 0x36,
+	0x63, 0x60,
+	0x64, 0x10,
+	0x65, 0x10,
+	0x68, 0x04,
+	0x69, 0x29,
+	0x70, 0x20,
+	0x71, 0x70,
+	0x72, 0x04,
+	0x73, 0x00,
+	0x70, 0x40,
+	0x71, 0x70,
+	0x72, 0x04,
+	0x73, 0x00,
+	0x70, 0x60,
+	0x71, 0x70,
+	0x72, 0x04,
+	0x73, 0x00,
+	0x70, 0x80,
+	0x71, 0x70,
+	0x72, 0x04,
+	0x73, 0x00,
+	0x70, 0xa0,
+	0x71, 0x70,
+	0x72, 0x04,
+	0x73, 0x00,
+	0x70, 0x1f,
+	0xa0, 0x44,
+	0xc0, 0x08,
+	0xc1, 0x10,
+	0xc2, 0x08,
+	0xc3, 0x10,
+	0xc4, 0x08,
+	0xc5, 0xf0,
+	0xc6, 0xf0,
+	0xc7, 0x0a,
+	0xc8, 0x1a,
+	0xc9, 0x80,
+	0xca, 0x23,
+	0xcb, 0x24,
+	0xce, 0x74,
+	0x90, 0x03,
+	0x76, 0x80,
+	0x77, 0x42,
+	0x78, 0x0a,
+	0x79, 0x80,
+	0xad, 0x40,
+	0xae, 0x07,
+	0x7f, 0xd4,
+	0x7c, 0x00,
+	0x80, 0xa8,
+	0x81, 0xda,
+	0x7c, 0x01,
+	0x80, 0xda,
+	0x81, 0xec,
+	0x7c, 0x02,
+	0x80, 0xca,
+	0x81, 0xeb,
+	0x7c, 0x03,
+	0x80, 0xba,
+	0x81, 0xdb,
+	0x85, 0x08,
+	0x86, 0x00,
+	0x87, 0x02,
+	0x89, 0x80,
+	0x8b, 0x44,
+	0x8c, 0xaa,
+	0x8a, 0x10,
+	0xba, 0x00,
+	0xf5, 0x04,
+	0xfe, 0x44,
+	0xd2, 0x32,
+	0xb8, 0x00,
+};
+
+struct ds3000_state {
+	struct i2c_adapter *i2c;
+	const struct ds3000_config *config;
+	struct dvb_frontend frontend;
+	u8 skip_fw_load;
+	/* previous uncorrected block counter for DVB-S2 */
+	u16 prevUCBS2;
+};
+
+static int ds3000_writereg(struct ds3000_state *state, int reg, int data)
+{
+	u8 buf[] = { reg, data };
+	struct i2c_msg msg = { .addr = state->config->demod_address,
+		.flags = 0, .buf = buf, .len = 2 };
+	int err;
+
+	dprintk("%s: write reg 0x%02x, value 0x%02x\n", __func__, reg, data);
+
+	err = i2c_transfer(state->i2c, &msg, 1);
+	if (err != 1) {
+		printk(KERN_ERR "%s: writereg error(err == %i, reg == 0x%02x,"
+			 " value == 0x%02x)\n", __func__, err, reg, data);
+		return -EREMOTEIO;
+	}
+
+	return 0;
+}
+
+static int ds3000_tuner_writereg(struct ds3000_state *state, int reg, int data)
+{
+	u8 buf[] = { reg, data };
+	struct i2c_msg msg = { .addr = 0x60,
+		.flags = 0, .buf = buf, .len = 2 };
+	int err;
+
+	dprintk("%s: write reg 0x%02x, value 0x%02x\n", __func__, reg, data);
+
+	ds3000_writereg(state, 0x03, 0x11);
+	err = i2c_transfer(state->i2c, &msg, 1);
+	if (err != 1) {
+		printk("%s: writereg error(err == %i, reg == 0x%02x,"
+			 " value == 0x%02x)\n", __func__, err, reg, data);
+		return -EREMOTEIO;
+	}
+
+	return 0;
+}
+
+/* I2C write for 8k firmware load */
+static int ds3000_writeFW(struct ds3000_state *state, int reg,
+				const u8 *data, u16 len)
+{
+	int i, ret = -EREMOTEIO;
+	struct i2c_msg msg;
+	u8 *buf;
+
+	buf = kmalloc(33, GFP_KERNEL);
+	if (buf == NULL) {
+		printk(KERN_ERR "Unable to kmalloc\n");
+		ret = -ENOMEM;
+		goto error;
+	}
+
+	*(buf) = reg;
+
+	msg.addr = state->config->demod_address;
+	msg.flags = 0;
+	msg.buf = buf;
+	msg.len = 33;
+
+	for (i = 0; i < len; i += 32) {
+		memcpy(buf + 1, data + i, 32);
+
+		dprintk("%s: write reg 0x%02x, len = %d\n", __func__, reg, len);
+
+		ret = i2c_transfer(state->i2c, &msg, 1);
+		if (ret != 1) {
+			printk(KERN_ERR "%s: write error(err == %i, "
+				"reg == 0x%02x\n", __func__, ret, reg);
+			ret = -EREMOTEIO;
+		}
+	}
+
+error:
+	kfree(buf);
+
+	return ret;
+}
+
+static int ds3000_readreg(struct ds3000_state *state, u8 reg)
+{
+	int ret;
+	u8 b0[] = { reg };
+	u8 b1[] = { 0 };
+	struct i2c_msg msg[] = {
+		{
+			.addr = state->config->demod_address,
+			.flags = 0,
+			.buf = b0,
+			.len = 1
+		}, {
+			.addr = state->config->demod_address,
+			.flags = I2C_M_RD,
+			.buf = b1,
+			.len = 1
+		}
+	};
+
+	ret = i2c_transfer(state->i2c, msg, 2);
+
+	if (ret != 2) {
+		printk(KERN_ERR "%s: reg=0x%x(error=%d)\n", __func__, reg, ret);
+		return ret;
+	}
+
+	dprintk("%s: read reg 0x%02x, value 0x%02x\n", __func__, reg, b1[0]);
+
+	return b1[0];
+}
+
+static int ds3000_tuner_readreg(struct ds3000_state *state, u8 reg)
+{
+	int ret;
+	u8 b0[] = { reg };
+	u8 b1[] = { 0 };
+	struct i2c_msg msg[] = {
+		{
+			.addr = 0x60,
+			.flags = 0,
+			.buf = b0,
+			.len = 1
+		}, {
+			.addr = 0x60,
+			.flags = I2C_M_RD,
+			.buf = b1,
+			.len = 1
+		}
+	};
+
+	ds3000_writereg(state, 0x03, 0x12);
+	ret = i2c_transfer(state->i2c, msg, 2);
+
+	if (ret != 2) {
+		printk(KERN_ERR "%s: reg=0x%x(error=%d)\n", __func__, reg, ret);
+		return ret;
+	}
+
+	dprintk("%s: read reg 0x%02x, value 0x%02x\n", __func__, reg, b1[0]);
+
+	return b1[0];
+}
+
+static int ds3000_load_firmware(struct dvb_frontend *fe,
+					const struct firmware *fw);
+
+static int ds3000_firmware_ondemand(struct dvb_frontend *fe)
+{
+	struct ds3000_state *state = fe->demodulator_priv;
+	const struct firmware *fw;
+	int ret = 0;
+
+	dprintk("%s()\n", __func__);
+
+	if (ds3000_readreg(state, 0xb2) <= 0)
+		return ret;
+
+	if (state->skip_fw_load)
+		return 0;
+	/* Load firmware */
+	/* request the firmware, this will block until someone uploads it */
+	printk(KERN_INFO "%s: Waiting for firmware upload (%s)...\n", __func__,
+				DS3000_DEFAULT_FIRMWARE);
+	ret = request_firmware(&fw, DS3000_DEFAULT_FIRMWARE,
+				state->i2c->dev.parent);
+	printk(KERN_INFO "%s: Waiting for firmware upload(2)...\n", __func__);
+	if (ret) {
+		printk(KERN_ERR "%s: No firmware uploaded (timeout or file not "
+				"found?)\n", __func__);
+		return ret;
+	}
+
+	/* Make sure we don't recurse back through here during loading */
+	state->skip_fw_load = 1;
+
+	ret = ds3000_load_firmware(fe, fw);
+	if (ret)
+		printk("%s: Writing firmware to device failed\n", __func__);
+
+	release_firmware(fw);
+
+	dprintk("%s: Firmware upload %s\n", __func__,
+			ret == 0 ? "complete" : "failed");
+
+	/* Ensure firmware is always loaded if required */
+	state->skip_fw_load = 0;
+
+	return ret;
+}
+
+static int ds3000_load_firmware(struct dvb_frontend *fe,
+					const struct firmware *fw)
+{
+	struct ds3000_state *state = fe->demodulator_priv;
+
+	dprintk("%s\n", __func__);
+	dprintk("Firmware is %zu bytes (%02x %02x .. %02x %02x)\n",
+			fw->size,
+			fw->data[0],
+			fw->data[1],
+			fw->data[fw->size - 2],
+			fw->data[fw->size - 1]);
+
+	/* Begin the firmware load process */
+	ds3000_writereg(state, 0xb2, 0x01);
+	/* write the entire firmware */
+	ds3000_writeFW(state, 0xb0, fw->data, fw->size);
+	ds3000_writereg(state, 0xb2, 0x00);
+
+	return 0;
+}
+
+static int ds3000_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+{
+	struct ds3000_state *state = fe->demodulator_priv;
+	u8 data;
+
+	dprintk("%s(%d)\n", __func__, voltage);
+
+	data = ds3000_readreg(state, 0xa2);
+	data |= 0x03; /* bit0 V/H, bit1 off/on */
+
+	switch (voltage) {
+	case SEC_VOLTAGE_18:
+		data &= ~0x03;
+		break;
+	case SEC_VOLTAGE_13:
+		data &= ~0x03;
+		data |= 0x01;
+		break;
+	case SEC_VOLTAGE_OFF:
+		break;
+	}
+
+	ds3000_writereg(state, 0xa2, data);
+
+	return 0;
+}
+
+static int ds3000_read_status(struct dvb_frontend *fe, fe_status_t* status)
+{
+	struct ds3000_state *state = fe->demodulator_priv;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	int lock;
+
+	*status = 0;
+
+	switch (c->delivery_system) {
+	case SYS_DVBS:
+		lock = ds3000_readreg(state, 0xd1);
+		if ((lock & 0x07) == 0x07)
+			*status = FE_HAS_SIGNAL | FE_HAS_CARRIER |
+				FE_HAS_VITERBI | FE_HAS_SYNC |
+				FE_HAS_LOCK;
+
+		break;
+	case SYS_DVBS2:
+		lock = ds3000_readreg(state, 0x0d);
+		if ((lock & 0x8f) == 0x8f)
+			*status = FE_HAS_SIGNAL | FE_HAS_CARRIER |
+				FE_HAS_VITERBI | FE_HAS_SYNC |
+				FE_HAS_LOCK;
+
+		break;
+	default:
+		return 1;
+	}
+
+	dprintk("%s: status = 0x%02x\n", __func__, lock);
+
+	return 0;
+}
+
+/* read DS3000 BER value */
+static int ds3000_read_ber(struct dvb_frontend *fe, u32* ber)
+{
+	struct ds3000_state *state = fe->demodulator_priv;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	u8 data;
+	u32 ber_reading, lpdc_frames;
+
+	dprintk("%s()\n", __func__);
+
+	switch (c->delivery_system) {
+	case SYS_DVBS:
+		/* set the number of bytes checked during
+		BER estimation */
+		ds3000_writereg(state, 0xf9, 0x04);
+		/* read BER estimation status */
+		data = ds3000_readreg(state, 0xf8);
+		/* check if BER estimation is ready */
+		if ((data & 0x10) == 0) {
+			/* this is the number of error bits,
+			to calculate the bit error rate
+			divide to 8388608 */
+			*ber = (ds3000_readreg(state, 0xf7) << 8) |
+				ds3000_readreg(state, 0xf6);
+			/* start counting error bits */
+			/* need to be set twice
+			otherwise it fails sometimes */
+			data |= 0x10;
+			ds3000_writereg(state, 0xf8, data);
+			ds3000_writereg(state, 0xf8, data);
+		} else
+			/* used to indicate that BER estimation
+			is not ready, i.e. BER is unknown */
+			*ber = 0xffffffff;
+		break;
+	case SYS_DVBS2:
+		/* read the number of LPDC decoded frames */
+		lpdc_frames = (ds3000_readreg(state, 0xd7) << 16) |
+				(ds3000_readreg(state, 0xd6) << 8) |
+				ds3000_readreg(state, 0xd5);
+		/* read the number of packets with bad CRC */
+		ber_reading = (ds3000_readreg(state, 0xf8) << 8) |
+				ds3000_readreg(state, 0xf7);
+		if (lpdc_frames > 750) {
+			/* clear LPDC frame counters */
+			ds3000_writereg(state, 0xd1, 0x01);
+			/* clear bad packets counter */
+			ds3000_writereg(state, 0xf9, 0x01);
+			/* enable bad packets counter */
+			ds3000_writereg(state, 0xf9, 0x00);
+			/* enable LPDC frame counters */
+			ds3000_writereg(state, 0xd1, 0x00);
+			*ber = ber_reading;
+		} else
+			/* used to indicate that BER estimation is not ready,
+			i.e. BER is unknown */
+			*ber = 0xffffffff;
+		break;
+	default:
+		return 1;
+	}
+
+	return 0;
+}
+
+/* read TS2020 signal strength */
+static int ds3000_read_signal_strength(struct dvb_frontend *fe,
+						u16 *signal_strength)
+{
+	struct ds3000_state *state = fe->demodulator_priv;
+	u16 sig_reading, sig_strength;
+	u8 rfgain, bbgain;
+
+	dprintk("%s()\n", __func__);
+
+	rfgain = ds3000_tuner_readreg(state, 0x3d) & 0x1f;
+	bbgain = ds3000_tuner_readreg(state, 0x21) & 0x1f;
+
+	if (rfgain > 15)
+		rfgain = 15;
+	if (bbgain > 13)
+		bbgain = 13;
+
+	sig_reading = rfgain * 2 + bbgain * 3;
+
+	sig_strength = 40 + (64 - sig_reading) * 50 / 64 ;
+
+	/* cook the value to be suitable for szap-s2 human readable output */
+	*signal_strength = sig_strength * 1000;
+
+	dprintk("%s: raw / cooked = 0x%04x / 0x%04x\n", __func__,
+			sig_reading, *signal_strength);
+
+	return 0;
+}
+
+/* calculate DS3000 snr value in dB */
+static int ds3000_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+	struct ds3000_state *state = fe->demodulator_priv;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	u8 snr_reading, snr_value;
+	u32 dvbs2_signal_reading, dvbs2_noise_reading, tmp;
+	static const u16 dvbs_snr_tab[] = { /* 20 x Table (rounded up) */
+		0x0000, 0x1b13, 0x2aea, 0x3627, 0x3ede, 0x45fe, 0x4c03,
+		0x513a, 0x55d4, 0x59f2, 0x5dab, 0x6111, 0x6431, 0x6717,
+		0x69c9, 0x6c4e, 0x6eac, 0x70e8, 0x7304, 0x7505
+	};
+	static const u16 dvbs2_snr_tab[] = { /* 80 x Table (rounded up) */
+		0x0000, 0x0bc2, 0x12a3, 0x1785, 0x1b4e, 0x1e65, 0x2103,
+		0x2347, 0x2546, 0x2710, 0x28ae, 0x2a28, 0x2b83, 0x2cc5,
+		0x2df1, 0x2f09, 0x3010, 0x3109, 0x31f4, 0x32d2, 0x33a6,
+		0x3470, 0x3531, 0x35ea, 0x369b, 0x3746, 0x37ea, 0x3888,
+		0x3920, 0x39b3, 0x3a42, 0x3acc, 0x3b51, 0x3bd3, 0x3c51,
+		0x3ccb, 0x3d42, 0x3db6, 0x3e27, 0x3e95, 0x3f00, 0x3f68,
+		0x3fcf, 0x4033, 0x4094, 0x40f4, 0x4151, 0x41ac, 0x4206,
+		0x425e, 0x42b4, 0x4308, 0x435b, 0x43ac, 0x43fc, 0x444a,
+		0x4497, 0x44e2, 0x452d, 0x4576, 0x45bd, 0x4604, 0x4649,
+		0x468e, 0x46d1, 0x4713, 0x4755, 0x4795, 0x47d4, 0x4813,
+		0x4851, 0x488d, 0x48c9, 0x4904, 0x493f, 0x4978, 0x49b1,
+		0x49e9, 0x4a20, 0x4a57
+	};
+
+	dprintk("%s()\n", __func__);
+
+	switch (c->delivery_system) {
+	case SYS_DVBS:
+		snr_reading = ds3000_readreg(state, 0xff);
+		snr_reading /= 8;
+		if (snr_reading == 0)
+			*snr = 0x0000;
+		else {
+			if (snr_reading > 20)
+				snr_reading = 20;
+			snr_value = dvbs_snr_tab[snr_reading - 1] * 10 / 23026;
+			/* cook the value to be suitable for szap-s2
+			human readable output */
+			*snr = snr_value * 8 * 655;
+		}
+		dprintk("%s: raw / cooked = 0x%02x / 0x%04x\n", __func__,
+				snr_reading, *snr);
+		break;
+	case SYS_DVBS2:
+		dvbs2_noise_reading = (ds3000_readreg(state, 0x8c) & 0x3f) +
+				(ds3000_readreg(state, 0x8d) << 4);
+		dvbs2_signal_reading = ds3000_readreg(state, 0x8e);
+		tmp = dvbs2_signal_reading * dvbs2_signal_reading >> 1;
+		if (tmp == 0) {
+			*snr = 0x0000;
+			return 0;
+		}
+		if (dvbs2_noise_reading == 0) {
+			snr_value = 0x0013;
+			/* cook the value to be suitable for szap-s2
+			human readable output */
+			*snr = 0xffff;
+			return 0;
+		}
+		if (tmp > dvbs2_noise_reading) {
+			snr_reading = tmp / dvbs2_noise_reading;
+			if (snr_reading > 80)
+				snr_reading = 80;
+			snr_value = dvbs2_snr_tab[snr_reading - 1] / 1000;
+			/* cook the value to be suitable for szap-s2
+			human readable output */
+			*snr = snr_value * 5 * 655;
+		} else {
+			snr_reading = dvbs2_noise_reading / tmp;
+			if (snr_reading > 80)
+				snr_reading = 80;
+			*snr = -(dvbs2_snr_tab[snr_reading] / 1000);
+		}
+		dprintk("%s: raw / cooked = 0x%02x / 0x%04x\n", __func__,
+				snr_reading, *snr);
+		break;
+	default:
+		return 1;
+	}
+
+	return 0;
+}
+
+/* read DS3000 uncorrected blocks */
+static int ds3000_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+	struct ds3000_state *state = fe->demodulator_priv;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	u8 data;
+	u16 _ucblocks;
+
+	dprintk("%s()\n", __func__);
+
+	switch (c->delivery_system) {
+	case SYS_DVBS:
+		*ucblocks = (ds3000_readreg(state, 0xf5) << 8) |
+				ds3000_readreg(state, 0xf4);
+		data = ds3000_readreg(state, 0xf8);
+		/* clear packet counters */
+		data &= ~0x20;
+		ds3000_writereg(state, 0xf8, data);
+		/* enable packet counters */
+		data |= 0x20;
+		ds3000_writereg(state, 0xf8, data);
+		break;
+	case SYS_DVBS2:
+		_ucblocks = (ds3000_readreg(state, 0xe2) << 8) |
+				ds3000_readreg(state, 0xe1);
+		if (_ucblocks > state->prevUCBS2)
+			*ucblocks = _ucblocks - state->prevUCBS2;
+		else
+			*ucblocks = state->prevUCBS2 - _ucblocks;
+		state->prevUCBS2 = _ucblocks;
+		break;
+	default:
+		return 1;
+	}
+
+	return 0;
+}
+
+static int ds3000_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
+{
+	struct ds3000_state *state = fe->demodulator_priv;
+	u8 data;
+
+	dprintk("%s(%d)\n", __func__, tone);
+	if ((tone != SEC_TONE_ON) && (tone != SEC_TONE_OFF)) {
+		printk(KERN_ERR "%s: Invalid, tone=%d\n", __func__, tone);
+		return -EINVAL;
+	}
+
+	data = ds3000_readreg(state, 0xa2);
+	data &= ~0xc0;
+	ds3000_writereg(state, 0xa2, data);
+
+	switch (tone) {
+	case SEC_TONE_ON:
+		dprintk("%s: setting tone on\n", __func__);
+		data = ds3000_readreg(state, 0xa1);
+		data &= ~0x43;
+		data |= 0x04;
+		ds3000_writereg(state, 0xa1, data);
+		break;
+	case SEC_TONE_OFF:
+		dprintk("%s: setting tone off\n", __func__);
+		data = ds3000_readreg(state, 0xa2);
+		data |= 0x80;
+		ds3000_writereg(state, 0xa2, data);
+		break;
+	}
+
+	return 0;
+}
+
+static int ds3000_send_diseqc_msg(struct dvb_frontend *fe,
+				struct dvb_diseqc_master_cmd *d)
+{
+	struct ds3000_state *state = fe->demodulator_priv;
+	int i;
+	u8 data;
+
+	/* Dump DiSEqC message */
+	dprintk("%s(", __func__);
+	for (i = 0 ; i < d->msg_len;) {
+		dprintk("0x%02x", d->msg[i]);
+		if (++i < d->msg_len)
+			dprintk(", ");
+	}
+
+	/* enable DiSEqC message send pin */
+	data = ds3000_readreg(state, 0xa2);
+	data &= ~0xc0;
+	ds3000_writereg(state, 0xa2, data);
+
+	/* DiSEqC message */
+	for (i = 0; i < d->msg_len; i++)
+		ds3000_writereg(state, 0xa3 + i, d->msg[i]);
+
+	data = ds3000_readreg(state, 0xa1);
+	/* clear DiSEqC message length and status,
+	enable DiSEqC message send */
+	data &= ~0xf8;
+	/* set DiSEqC mode, modulation active during 33 pulses,
+	set DiSEqC message length */
+	data |= ((d->msg_len - 1) << 3) | 0x07;
+	ds3000_writereg(state, 0xa1, data);
+
+	/* wait up to 150ms for DiSEqC transmission to complete */
+	for (i = 0; i < 15; i++) {
+		data = ds3000_readreg(state, 0xa1);
+		if ((data & 0x40) == 0)
+			break;
+		msleep(10);
+	}
+
+	/* DiSEqC timeout after 150ms */
+	if (i == 15) {
+		data = ds3000_readreg(state, 0xa1);
+		data &= ~0x80;
+		data |= 0x40;
+		ds3000_writereg(state, 0xa1, data);
+
+		data = ds3000_readreg(state, 0xa2);
+		data &= ~0xc0;
+		data |= 0x80;
+		ds3000_writereg(state, 0xa2, data);
+
+		return 1;
+	}
+
+	data = ds3000_readreg(state, 0xa2);
+	data &= ~0xc0;
+	data |= 0x80;
+	ds3000_writereg(state, 0xa2, data);
+
+	return 0;
+}
+
+/* Send DiSEqC burst */
+static int ds3000_diseqc_send_burst(struct dvb_frontend *fe,
+					fe_sec_mini_cmd_t burst)
+{
+	struct ds3000_state *state = fe->demodulator_priv;
+	int i;
+	u8 data;
+
+	dprintk("%s()\n", __func__);
+
+	data = ds3000_readreg(state, 0xa2);
+	data &= ~0xc0;
+	ds3000_writereg(state, 0xa2, data);
+
+	/* DiSEqC burst */
+	if (burst == SEC_MINI_A)
+		/* Unmodulated tone burst */
+		ds3000_writereg(state, 0xa1, 0x02);
+	else if (burst == SEC_MINI_B)
+		/* Modulated tone burst */
+		ds3000_writereg(state, 0xa1, 0x01);
+	else
+		return -EINVAL;
+
+	msleep(13);
+	for (i = 0; i < 5; i++) {
+		data = ds3000_readreg(state, 0xa1);
+		if ((data & 0x40) == 0)
+			break;
+		msleep(1);
+	}
+
+	if (i == 5) {
+		data = ds3000_readreg(state, 0xa1);
+		data &= ~0x80;
+		data |= 0x40;
+		ds3000_writereg(state, 0xa1, data);
+
+		data = ds3000_readreg(state, 0xa2);
+		data &= ~0xc0;
+		data |= 0x80;
+		ds3000_writereg(state, 0xa2, data);
+
+		return 1;
+	}
+
+	data = ds3000_readreg(state, 0xa2);
+	data &= ~0xc0;
+	data |= 0x80;
+	ds3000_writereg(state, 0xa2, data);
+
+	return 0;
+}
+
+static void ds3000_release(struct dvb_frontend *fe)
+{
+	struct ds3000_state *state = fe->demodulator_priv;
+	dprintk("%s\n", __func__);
+	kfree(state);
+}
+
+static struct dvb_frontend_ops ds3000_ops;
+
+struct dvb_frontend *ds3000_attach(const struct ds3000_config *config,
+				    struct i2c_adapter *i2c)
+{
+	struct ds3000_state *state = NULL;
+	int ret;
+
+	dprintk("%s\n", __func__);
+
+	/* allocate memory for the internal state */
+	state = kzalloc(sizeof(struct ds3000_state), GFP_KERNEL);
+	if (state == NULL) {
+		printk(KERN_ERR "Unable to kmalloc\n");
+		goto error2;
+	}
+
+	state->config = config;
+	state->i2c = i2c;
+	state->prevUCBS2 = 0;
+
+	/* check if the demod is present */
+	ret = ds3000_readreg(state, 0x00) & 0xfe;
+	if (ret != 0xe0) {
+		printk(KERN_ERR "Invalid probe, probably not a DS3000\n");
+		goto error3;
+	}
+
+	printk(KERN_INFO "DS3000 chip version: %d.%d attached.\n",
+			ds3000_readreg(state, 0x02),
+			ds3000_readreg(state, 0x01));
+
+	memcpy(&state->frontend.ops, &ds3000_ops,
+			sizeof(struct dvb_frontend_ops));
+	state->frontend.demodulator_priv = state;
+	return &state->frontend;
+
+error3:
+	kfree(state);
+error2:
+	return NULL;
+}
+EXPORT_SYMBOL(ds3000_attach);
+
+static int ds3000_set_carrier_offset(struct dvb_frontend *fe,
+					s32 carrier_offset_khz)
+{
+	struct ds3000_state *state = fe->demodulator_priv;
+	s32 tmp;
+
+	tmp = carrier_offset_khz;
+	tmp *= 65536;
+	tmp = (2 * tmp + DS3000_SAMPLE_RATE) / (2 * DS3000_SAMPLE_RATE);
+
+	if (tmp < 0)
+		tmp += 65536;
+
+	ds3000_writereg(state, 0x5f, tmp >> 8);
+	ds3000_writereg(state, 0x5e, tmp & 0xff);
+
+	return 0;
+}
+
+static int ds3000_set_frontend(struct dvb_frontend *fe)
+{
+	struct ds3000_state *state = fe->demodulator_priv;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+
+	int i;
+	fe_status_t status;
+	u8 mlpf, mlpf_new, mlpf_max, mlpf_min, nlpf, div4;
+	s32 offset_khz;
+	u16 value, ndiv;
+	u32 f3db;
+
+	dprintk("%s() ", __func__);
+
+	if (state->config->set_ts_params)
+		state->config->set_ts_params(fe, 0);
+	/* Tune */
+	/* unknown */
+	ds3000_tuner_writereg(state, 0x07, 0x02);
+	ds3000_tuner_writereg(state, 0x10, 0x00);
+	ds3000_tuner_writereg(state, 0x60, 0x79);
+	ds3000_tuner_writereg(state, 0x08, 0x01);
+	ds3000_tuner_writereg(state, 0x00, 0x01);
+	div4 = 0;
+
+	/* calculate and set freq divider */
+	if (c->frequency < 1146000) {
+		ds3000_tuner_writereg(state, 0x10, 0x11);
+		div4 = 1;
+		ndiv = ((c->frequency * (6 + 8) * 4) +
+				(DS3000_XTAL_FREQ / 2)) /
+				DS3000_XTAL_FREQ - 1024;
+	} else {
+		ds3000_tuner_writereg(state, 0x10, 0x01);
+		ndiv = ((c->frequency * (6 + 8) * 2) +
+				(DS3000_XTAL_FREQ / 2)) /
+				DS3000_XTAL_FREQ - 1024;
+	}
+
+	ds3000_tuner_writereg(state, 0x01, (ndiv & 0x0f00) >> 8);
+	ds3000_tuner_writereg(state, 0x02, ndiv & 0x00ff);
+
+	/* set pll */
+	ds3000_tuner_writereg(state, 0x03, 0x06);
+	ds3000_tuner_writereg(state, 0x51, 0x0f);
+	ds3000_tuner_writereg(state, 0x51, 0x1f);
+	ds3000_tuner_writereg(state, 0x50, 0x10);
+	ds3000_tuner_writereg(state, 0x50, 0x00);
+	msleep(5);
+
+	/* unknown */
+	ds3000_tuner_writereg(state, 0x51, 0x17);
+	ds3000_tuner_writereg(state, 0x51, 0x1f);
+	ds3000_tuner_writereg(state, 0x50, 0x08);
+	ds3000_tuner_writereg(state, 0x50, 0x00);
+	msleep(5);
+
+	value = ds3000_tuner_readreg(state, 0x3d);
+	value &= 0x0f;
+	if ((value > 4) && (value < 15)) {
+		value -= 3;
+		if (value < 4)
+			value = 4;
+		value = ((value << 3) | 0x01) & 0x79;
+	}
+
+	ds3000_tuner_writereg(state, 0x60, value);
+	ds3000_tuner_writereg(state, 0x51, 0x17);
+	ds3000_tuner_writereg(state, 0x51, 0x1f);
+	ds3000_tuner_writereg(state, 0x50, 0x08);
+	ds3000_tuner_writereg(state, 0x50, 0x00);
+
+	/* set low-pass filter period */
+	ds3000_tuner_writereg(state, 0x04, 0x2e);
+	ds3000_tuner_writereg(state, 0x51, 0x1b);
+	ds3000_tuner_writereg(state, 0x51, 0x1f);
+	ds3000_tuner_writereg(state, 0x50, 0x04);
+	ds3000_tuner_writereg(state, 0x50, 0x00);
+	msleep(5);
+
+	f3db = ((c->symbol_rate / 1000) << 2) / 5 + 2000;
+	if ((c->symbol_rate / 1000) < 5000)
+		f3db += 3000;
+	if (f3db < 7000)
+		f3db = 7000;
+	if (f3db > 40000)
+		f3db = 40000;
+
+	/* set low-pass filter baseband */
+	value = ds3000_tuner_readreg(state, 0x26);
+	mlpf = 0x2e * 207 / ((value << 1) + 151);
+	mlpf_max = mlpf * 135 / 100;
+	mlpf_min = mlpf * 78 / 100;
+	if (mlpf_max > 63)
+		mlpf_max = 63;
+
+	/* rounded to the closest integer */
+	nlpf = ((mlpf * f3db * 1000) + (2766 * DS3000_XTAL_FREQ / 2))
+			/ (2766 * DS3000_XTAL_FREQ);
+	if (nlpf > 23)
+		nlpf = 23;
+	if (nlpf < 1)
+		nlpf = 1;
+
+	/* rounded to the closest integer */
+	mlpf_new = ((DS3000_XTAL_FREQ * nlpf * 2766) +
+			(1000 * f3db / 2)) / (1000 * f3db);
+
+	if (mlpf_new < mlpf_min) {
+		nlpf++;
+		mlpf_new = ((DS3000_XTAL_FREQ * nlpf * 2766) +
+				(1000 * f3db / 2)) / (1000 * f3db);
+	}
+
+	if (mlpf_new > mlpf_max)
+		mlpf_new = mlpf_max;
+
+	ds3000_tuner_writereg(state, 0x04, mlpf_new);
+	ds3000_tuner_writereg(state, 0x06, nlpf);
+	ds3000_tuner_writereg(state, 0x51, 0x1b);
+	ds3000_tuner_writereg(state, 0x51, 0x1f);
+	ds3000_tuner_writereg(state, 0x50, 0x04);
+	ds3000_tuner_writereg(state, 0x50, 0x00);
+	msleep(5);
+
+	/* unknown */
+	ds3000_tuner_writereg(state, 0x51, 0x1e);
+	ds3000_tuner_writereg(state, 0x51, 0x1f);
+	ds3000_tuner_writereg(state, 0x50, 0x01);
+	ds3000_tuner_writereg(state, 0x50, 0x00);
+	msleep(60);
+
+	offset_khz = (ndiv - ndiv % 2 + 1024) * DS3000_XTAL_FREQ
+		/ (6 + 8) / (div4 + 1) / 2 - c->frequency;
+
+	/* ds3000 global reset */
+	ds3000_writereg(state, 0x07, 0x80);
+	ds3000_writereg(state, 0x07, 0x00);
+	/* ds3000 build-in uC reset */
+	ds3000_writereg(state, 0xb2, 0x01);
+	/* ds3000 software reset */
+	ds3000_writereg(state, 0x00, 0x01);
+
+	switch (c->delivery_system) {
+	case SYS_DVBS:
+		/* initialise the demod in DVB-S mode */
+		for (i = 0; i < sizeof(ds3000_dvbs_init_tab); i += 2)
+			ds3000_writereg(state,
+				ds3000_dvbs_init_tab[i],
+				ds3000_dvbs_init_tab[i + 1]);
+		value = ds3000_readreg(state, 0xfe);
+		value &= 0xc0;
+		value |= 0x1b;
+		ds3000_writereg(state, 0xfe, value);
+		break;
+	case SYS_DVBS2:
+		/* initialise the demod in DVB-S2 mode */
+		for (i = 0; i < sizeof(ds3000_dvbs2_init_tab); i += 2)
+			ds3000_writereg(state,
+				ds3000_dvbs2_init_tab[i],
+				ds3000_dvbs2_init_tab[i + 1]);
+		if (c->symbol_rate >= 30000000)
+			ds3000_writereg(state, 0xfe, 0x54);
+		else
+			ds3000_writereg(state, 0xfe, 0x98);
+		break;
+	default:
+		return 1;
+	}
+
+	/* enable 27MHz clock output */
+	ds3000_writereg(state, 0x29, 0x80);
+	/* enable ac coupling */
+	ds3000_writereg(state, 0x25, 0x8a);
+
+	/* enhance symbol rate performance */
+	if ((c->symbol_rate / 1000) <= 5000) {
+		value = 29777 / (c->symbol_rate / 1000) + 1;
+		if (value % 2 != 0)
+			value++;
+		ds3000_writereg(state, 0xc3, 0x0d);
+		ds3000_writereg(state, 0xc8, value);
+		ds3000_writereg(state, 0xc4, 0x10);
+		ds3000_writereg(state, 0xc7, 0x0e);
+	} else if ((c->symbol_rate / 1000) <= 10000) {
+		value = 92166 / (c->symbol_rate / 1000) + 1;
+		if (value % 2 != 0)
+			value++;
+		ds3000_writereg(state, 0xc3, 0x07);
+		ds3000_writereg(state, 0xc8, value);
+		ds3000_writereg(state, 0xc4, 0x09);
+		ds3000_writereg(state, 0xc7, 0x12);
+	} else if ((c->symbol_rate / 1000) <= 20000) {
+		value = 64516 / (c->symbol_rate / 1000) + 1;
+		ds3000_writereg(state, 0xc3, value);
+		ds3000_writereg(state, 0xc8, 0x0e);
+		ds3000_writereg(state, 0xc4, 0x07);
+		ds3000_writereg(state, 0xc7, 0x18);
+	} else {
+		value = 129032 / (c->symbol_rate / 1000) + 1;
+		ds3000_writereg(state, 0xc3, value);
+		ds3000_writereg(state, 0xc8, 0x0a);
+		ds3000_writereg(state, 0xc4, 0x05);
+		ds3000_writereg(state, 0xc7, 0x24);
+	}
+
+	/* normalized symbol rate rounded to the closest integer */
+	value = (((c->symbol_rate / 1000) << 16) +
+			(DS3000_SAMPLE_RATE / 2)) / DS3000_SAMPLE_RATE;
+	ds3000_writereg(state, 0x61, value & 0x00ff);
+	ds3000_writereg(state, 0x62, (value & 0xff00) >> 8);
+
+	/* co-channel interference cancellation disabled */
+	ds3000_writereg(state, 0x56, 0x00);
+
+	/* equalizer disabled */
+	ds3000_writereg(state, 0x76, 0x00);
+
+	/*ds3000_writereg(state, 0x08, 0x03);
+	ds3000_writereg(state, 0xfd, 0x22);
+	ds3000_writereg(state, 0x08, 0x07);
+	ds3000_writereg(state, 0xfd, 0x42);
+	ds3000_writereg(state, 0x08, 0x07);*/
+
+	if (state->config->ci_mode) {
+		switch (c->delivery_system) {
+		case SYS_DVBS:
+		default:
+			ds3000_writereg(state, 0xfd, 0x80);
+		break;
+		case SYS_DVBS2:
+			ds3000_writereg(state, 0xfd, 0x01);
+			break;
+		}
+	}
+
+	/* ds3000 out of software reset */
+	ds3000_writereg(state, 0x00, 0x00);
+	/* start ds3000 build-in uC */
+	ds3000_writereg(state, 0xb2, 0x00);
+
+	ds3000_set_carrier_offset(fe, offset_khz);
+
+	for (i = 0; i < 30 ; i++) {
+		ds3000_read_status(fe, &status);
+		if (status & FE_HAS_LOCK)
+			break;
+
+		msleep(10);
+	}
+
+	return 0;
+}
+
+static int ds3000_tune(struct dvb_frontend *fe,
+			bool re_tune,
+			unsigned int mode_flags,
+			unsigned int *delay,
+			fe_status_t *status)
+{
+	if (re_tune) {
+		int ret = ds3000_set_frontend(fe);
+		if (ret)
+			return ret;
+	}
+
+	*delay = HZ / 5;
+
+	return ds3000_read_status(fe, status);
+}
+
+static enum dvbfe_algo ds3000_get_algo(struct dvb_frontend *fe)
+{
+	dprintk("%s()\n", __func__);
+	return DVBFE_ALGO_HW;
+}
+
+/*
+ * Initialise or wake up device
+ *
+ * Power config will reset and load initial firmware if required
+ */
+static int ds3000_initfe(struct dvb_frontend *fe)
+{
+	struct ds3000_state *state = fe->demodulator_priv;
+	int ret;
+
+	dprintk("%s()\n", __func__);
+	/* hard reset */
+	ds3000_writereg(state, 0x08, 0x01 | ds3000_readreg(state, 0x08));
+	msleep(1);
+
+	/* TS2020 init */
+	ds3000_tuner_writereg(state, 0x42, 0x73);
+	ds3000_tuner_writereg(state, 0x05, 0x01);
+	ds3000_tuner_writereg(state, 0x62, 0xf5);
+	/* Load the firmware if required */
+	ret = ds3000_firmware_ondemand(fe);
+	if (ret != 0) {
+		printk(KERN_ERR "%s: Unable initialize firmware\n", __func__);
+		return ret;
+	}
+
+	return 0;
+}
+
+/* Put device to sleep */
+static int ds3000_sleep(struct dvb_frontend *fe)
+{
+	dprintk("%s()\n", __func__);
+	return 0;
+}
+
+static struct dvb_frontend_ops ds3000_ops = {
+	.delsys = { SYS_DVBS, SYS_DVBS2},
+	.info = {
+		.name = "Montage Technology DS3000/TS2020",
+		.frequency_min = 950000,
+		.frequency_max = 2150000,
+		.frequency_stepsize = 1011, /* kHz for QPSK frontends */
+		.frequency_tolerance = 5000,
+		.symbol_rate_min = 1000000,
+		.symbol_rate_max = 45000000,
+		.caps = FE_CAN_INVERSION_AUTO |
+			FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
+			FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
+			FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
+			FE_CAN_2G_MODULATION |
+			FE_CAN_QPSK | FE_CAN_RECOVER
+	},
+
+	.release = ds3000_release,
+
+	.init = ds3000_initfe,
+	.sleep = ds3000_sleep,
+	.read_status = ds3000_read_status,
+	.read_ber = ds3000_read_ber,
+	.read_signal_strength = ds3000_read_signal_strength,
+	.read_snr = ds3000_read_snr,
+	.read_ucblocks = ds3000_read_ucblocks,
+	.set_voltage = ds3000_set_voltage,
+	.set_tone = ds3000_set_tone,
+	.diseqc_send_master_cmd = ds3000_send_diseqc_msg,
+	.diseqc_send_burst = ds3000_diseqc_send_burst,
+	.get_frontend_algo = ds3000_get_algo,
+
+	.set_frontend = ds3000_set_frontend,
+	.tune = ds3000_tune,
+};
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)");
+
+MODULE_DESCRIPTION("DVB Frontend module for Montage Technology "
+			"DS3000/TS2020 hardware");
+MODULE_AUTHOR("Konstantin Dimitrov");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb-frontends/ds3000.h b/drivers/media/dvb-frontends/ds3000.h
new file mode 100644
index 0000000..1b73688
--- /dev/null
+++ b/drivers/media/dvb-frontends/ds3000.h
@@ -0,0 +1,48 @@
+/*
+    Montage Technology DS3000/TS2020 - DVBS/S2 Satellite demod/tuner driver
+    Copyright (C) 2009 Konstantin Dimitrov <kosio.dimitrov@gmail.com>
+
+    Copyright (C) 2009 TurboSight.com
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef DS3000_H
+#define DS3000_H
+
+#include <linux/dvb/frontend.h>
+
+struct ds3000_config {
+	/* the demodulator's i2c address */
+	u8 demod_address;
+	u8 ci_mode;
+	/* Set device param to start dma */
+	int (*set_ts_params)(struct dvb_frontend *fe, int is_punctured);
+};
+
+#if defined(CONFIG_DVB_DS3000) || \
+			(defined(CONFIG_DVB_DS3000_MODULE) && defined(MODULE))
+extern struct dvb_frontend *ds3000_attach(const struct ds3000_config *config,
+					struct i2c_adapter *i2c);
+#else
+static inline
+struct dvb_frontend *ds3000_attach(const struct ds3000_config *config,
+					struct i2c_adapter *i2c)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif /* CONFIG_DVB_DS3000 */
+#endif /* DS3000_H */
diff --git a/drivers/media/dvb-frontends/dvb-pll.c b/drivers/media/dvb-frontends/dvb-pll.c
new file mode 100644
index 0000000..6d8fe88
--- /dev/null
+++ b/drivers/media/dvb-frontends/dvb-pll.c
@@ -0,0 +1,820 @@
+/*
+ * descriptions + helper functions for simple dvb plls.
+ *
+ * (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the 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/slab.h>
+#include <linux/module.h>
+#include <linux/dvb/frontend.h>
+#include <asm/types.h>
+
+#include "dvb-pll.h"
+
+struct dvb_pll_priv {
+	/* pll number */
+	int nr;
+
+	/* i2c details */
+	int pll_i2c_address;
+	struct i2c_adapter *i2c;
+
+	/* the PLL descriptor */
+	struct dvb_pll_desc *pll_desc;
+
+	/* cached frequency/bandwidth */
+	u32 frequency;
+	u32 bandwidth;
+};
+
+#define DVB_PLL_MAX 64
+
+static unsigned int dvb_pll_devcount;
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "enable verbose debug messages");
+
+static unsigned int id[DVB_PLL_MAX] =
+	{ [ 0 ... (DVB_PLL_MAX-1) ] = DVB_PLL_UNDEFINED };
+module_param_array(id, int, NULL, 0644);
+MODULE_PARM_DESC(id, "force pll id to use (DEBUG ONLY)");
+
+/* ----------------------------------------------------------- */
+
+struct dvb_pll_desc {
+	char *name;
+	u32  min;
+	u32  max;
+	u32  iffreq;
+	void (*set)(struct dvb_frontend *fe, u8 *buf);
+	u8   *initdata;
+	u8   *initdata2;
+	u8   *sleepdata;
+	int  count;
+	struct {
+		u32 limit;
+		u32 stepsize;
+		u8  config;
+		u8  cb;
+	} entries[12];
+};
+
+/* ----------------------------------------------------------- */
+/* descriptions                                                */
+
+static struct dvb_pll_desc dvb_pll_thomson_dtt7579 = {
+	.name  = "Thomson dtt7579",
+	.min   = 177000000,
+	.max   = 858000000,
+	.iffreq= 36166667,
+	.sleepdata = (u8[]){ 2, 0xb4, 0x03 },
+	.count = 4,
+	.entries = {
+		{  443250000, 166667, 0xb4, 0x02 },
+		{  542000000, 166667, 0xb4, 0x08 },
+		{  771000000, 166667, 0xbc, 0x08 },
+		{  999999999, 166667, 0xf4, 0x08 },
+	},
+};
+
+static void thomson_dtt759x_bw(struct dvb_frontend *fe, u8 *buf)
+{
+	u32 bw = fe->dtv_property_cache.bandwidth_hz;
+	if (bw == 7000000)
+		buf[3] |= 0x10;
+}
+
+static struct dvb_pll_desc dvb_pll_thomson_dtt759x = {
+	.name  = "Thomson dtt759x",
+	.min   = 177000000,
+	.max   = 896000000,
+	.set   = thomson_dtt759x_bw,
+	.iffreq= 36166667,
+	.sleepdata = (u8[]){ 2, 0x84, 0x03 },
+	.count = 5,
+	.entries = {
+		{  264000000, 166667, 0xb4, 0x02 },
+		{  470000000, 166667, 0xbc, 0x02 },
+		{  735000000, 166667, 0xbc, 0x08 },
+		{  835000000, 166667, 0xf4, 0x08 },
+		{  999999999, 166667, 0xfc, 0x08 },
+	},
+};
+
+static void thomson_dtt7520x_bw(struct dvb_frontend *fe, u8 *buf)
+{
+	u32 bw = fe->dtv_property_cache.bandwidth_hz;
+	if (bw == 8000000)
+		buf[3] ^= 0x10;
+}
+
+static struct dvb_pll_desc dvb_pll_thomson_dtt7520x = {
+	.name  = "Thomson dtt7520x",
+	.min   = 185000000,
+	.max   = 900000000,
+	.set   = thomson_dtt7520x_bw,
+	.iffreq = 36166667,
+	.count = 7,
+	.entries = {
+		{  305000000, 166667, 0xb4, 0x12 },
+		{  405000000, 166667, 0xbc, 0x12 },
+		{  445000000, 166667, 0xbc, 0x12 },
+		{  465000000, 166667, 0xf4, 0x18 },
+		{  735000000, 166667, 0xfc, 0x18 },
+		{  835000000, 166667, 0xbc, 0x18 },
+		{  999999999, 166667, 0xfc, 0x18 },
+	},
+};
+
+static struct dvb_pll_desc dvb_pll_lg_z201 = {
+	.name  = "LG z201",
+	.min   = 174000000,
+	.max   = 862000000,
+	.iffreq= 36166667,
+	.sleepdata = (u8[]){ 2, 0xbc, 0x03 },
+	.count = 5,
+	.entries = {
+		{  157500000, 166667, 0xbc, 0x01 },
+		{  443250000, 166667, 0xbc, 0x02 },
+		{  542000000, 166667, 0xbc, 0x04 },
+		{  830000000, 166667, 0xf4, 0x04 },
+		{  999999999, 166667, 0xfc, 0x04 },
+	},
+};
+
+static struct dvb_pll_desc dvb_pll_unknown_1 = {
+	.name  = "unknown 1", /* used by dntv live dvb-t */
+	.min   = 174000000,
+	.max   = 862000000,
+	.iffreq= 36166667,
+	.count = 9,
+	.entries = {
+		{  150000000, 166667, 0xb4, 0x01 },
+		{  173000000, 166667, 0xbc, 0x01 },
+		{  250000000, 166667, 0xb4, 0x02 },
+		{  400000000, 166667, 0xbc, 0x02 },
+		{  420000000, 166667, 0xf4, 0x02 },
+		{  470000000, 166667, 0xfc, 0x02 },
+		{  600000000, 166667, 0xbc, 0x08 },
+		{  730000000, 166667, 0xf4, 0x08 },
+		{  999999999, 166667, 0xfc, 0x08 },
+	},
+};
+
+/* Infineon TUA6010XS
+ * used in Thomson Cable Tuner
+ */
+static struct dvb_pll_desc dvb_pll_tua6010xs = {
+	.name  = "Infineon TUA6010XS",
+	.min   =  44250000,
+	.max   = 858000000,
+	.iffreq= 36125000,
+	.count = 3,
+	.entries = {
+		{  115750000, 62500, 0x8e, 0x03 },
+		{  403250000, 62500, 0x8e, 0x06 },
+		{  999999999, 62500, 0x8e, 0x85 },
+	},
+};
+
+/* Panasonic env57h1xd5 (some Philips PLL ?) */
+static struct dvb_pll_desc dvb_pll_env57h1xd5 = {
+	.name  = "Panasonic ENV57H1XD5",
+	.min   =  44250000,
+	.max   = 858000000,
+	.iffreq= 36125000,
+	.count = 4,
+	.entries = {
+		{  153000000, 166667, 0xc2, 0x41 },
+		{  470000000, 166667, 0xc2, 0x42 },
+		{  526000000, 166667, 0xc2, 0x84 },
+		{  999999999, 166667, 0xc2, 0xa4 },
+	},
+};
+
+/* Philips TDA6650/TDA6651
+ * used in Panasonic ENV77H11D5
+ */
+static void tda665x_bw(struct dvb_frontend *fe, u8 *buf)
+{
+	u32 bw = fe->dtv_property_cache.bandwidth_hz;
+	if (bw == 8000000)
+		buf[3] |= 0x08;
+}
+
+static struct dvb_pll_desc dvb_pll_tda665x = {
+	.name  = "Philips TDA6650/TDA6651",
+	.min   =  44250000,
+	.max   = 858000000,
+	.set   = tda665x_bw,
+	.iffreq= 36166667,
+	.initdata = (u8[]){ 4, 0x0b, 0xf5, 0x85, 0xab },
+	.count = 12,
+	.entries = {
+		{   93834000, 166667, 0xca, 0x61 /* 011 0 0 0  01 */ },
+		{  123834000, 166667, 0xca, 0xa1 /* 101 0 0 0  01 */ },
+		{  161000000, 166667, 0xca, 0xa1 /* 101 0 0 0  01 */ },
+		{  163834000, 166667, 0xca, 0xc2 /* 110 0 0 0  10 */ },
+		{  253834000, 166667, 0xca, 0x62 /* 011 0 0 0  10 */ },
+		{  383834000, 166667, 0xca, 0xa2 /* 101 0 0 0  10 */ },
+		{  443834000, 166667, 0xca, 0xc2 /* 110 0 0 0  10 */ },
+		{  444000000, 166667, 0xca, 0xc4 /* 110 0 0 1  00 */ },
+		{  583834000, 166667, 0xca, 0x64 /* 011 0 0 1  00 */ },
+		{  793834000, 166667, 0xca, 0xa4 /* 101 0 0 1  00 */ },
+		{  444834000, 166667, 0xca, 0xc4 /* 110 0 0 1  00 */ },
+		{  861000000, 166667, 0xca, 0xe4 /* 111 0 0 1  00 */ },
+	}
+};
+
+/* Infineon TUA6034
+ * used in LG TDTP E102P
+ */
+static void tua6034_bw(struct dvb_frontend *fe, u8 *buf)
+{
+	u32 bw = fe->dtv_property_cache.bandwidth_hz;
+	if (bw == 7000000)
+		buf[3] |= 0x08;
+}
+
+static struct dvb_pll_desc dvb_pll_tua6034 = {
+	.name  = "Infineon TUA6034",
+	.min   =  44250000,
+	.max   = 858000000,
+	.iffreq= 36166667,
+	.count = 3,
+	.set   = tua6034_bw,
+	.entries = {
+		{  174500000, 62500, 0xce, 0x01 },
+		{  230000000, 62500, 0xce, 0x02 },
+		{  999999999, 62500, 0xce, 0x04 },
+	},
+};
+
+/* ALPS TDED4
+ * used in Nebula-Cards and USB boxes
+ */
+static void tded4_bw(struct dvb_frontend *fe, u8 *buf)
+{
+	u32 bw = fe->dtv_property_cache.bandwidth_hz;
+	if (bw == 8000000)
+		buf[3] |= 0x04;
+}
+
+static struct dvb_pll_desc dvb_pll_tded4 = {
+	.name = "ALPS TDED4",
+	.min = 47000000,
+	.max = 863000000,
+	.iffreq= 36166667,
+	.set   = tded4_bw,
+	.count = 4,
+	.entries = {
+		{ 153000000, 166667, 0x85, 0x01 },
+		{ 470000000, 166667, 0x85, 0x02 },
+		{ 823000000, 166667, 0x85, 0x08 },
+		{ 999999999, 166667, 0x85, 0x88 },
+	}
+};
+
+/* ALPS TDHU2
+ * used in AverTVHD MCE A180
+ */
+static struct dvb_pll_desc dvb_pll_tdhu2 = {
+	.name = "ALPS TDHU2",
+	.min = 54000000,
+	.max = 864000000,
+	.iffreq= 44000000,
+	.count = 4,
+	.entries = {
+		{ 162000000, 62500, 0x85, 0x01 },
+		{ 426000000, 62500, 0x85, 0x02 },
+		{ 782000000, 62500, 0x85, 0x08 },
+		{ 999999999, 62500, 0x85, 0x88 },
+	}
+};
+
+/* Samsung TBMV30111IN / TBMV30712IN1
+ * used in Air2PC ATSC - 2nd generation (nxt2002)
+ */
+static struct dvb_pll_desc dvb_pll_samsung_tbmv = {
+	.name = "Samsung TBMV30111IN / TBMV30712IN1",
+	.min = 54000000,
+	.max = 860000000,
+	.iffreq= 44000000,
+	.count = 6,
+	.entries = {
+		{ 172000000, 166667, 0xb4, 0x01 },
+		{ 214000000, 166667, 0xb4, 0x02 },
+		{ 467000000, 166667, 0xbc, 0x02 },
+		{ 721000000, 166667, 0xbc, 0x08 },
+		{ 841000000, 166667, 0xf4, 0x08 },
+		{ 999999999, 166667, 0xfc, 0x02 },
+	}
+};
+
+/*
+ * Philips SD1878 Tuner.
+ */
+static struct dvb_pll_desc dvb_pll_philips_sd1878_tda8261 = {
+	.name  = "Philips SD1878",
+	.min   =  950000,
+	.max   = 2150000,
+	.iffreq= 249, /* zero-IF, offset 249 is to round up */
+	.count = 4,
+	.entries = {
+		{ 1250000, 500, 0xc4, 0x00},
+		{ 1450000, 500, 0xc4, 0x40},
+		{ 2050000, 500, 0xc4, 0x80},
+		{ 2150000, 500, 0xc4, 0xc0},
+	},
+};
+
+static void opera1_bw(struct dvb_frontend *fe, u8 *buf)
+{
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	struct dvb_pll_priv *priv = fe->tuner_priv;
+	u32 b_w  = (c->symbol_rate * 27) / 32000;
+	struct i2c_msg msg = {
+		.addr = priv->pll_i2c_address,
+		.flags = 0,
+		.buf = buf,
+		.len = 4
+	};
+	int result;
+	u8 lpf;
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+
+	result = i2c_transfer(priv->i2c, &msg, 1);
+	if (result != 1)
+		printk(KERN_ERR "%s: i2c_transfer failed:%d",
+			__func__, result);
+
+	if (b_w <= 10000)
+		lpf = 0xc;
+	else if (b_w <= 12000)
+		lpf = 0x2;
+	else if (b_w <= 14000)
+		lpf = 0xa;
+	else if (b_w <= 16000)
+		lpf = 0x6;
+	else if (b_w <= 18000)
+		lpf = 0xe;
+	else if (b_w <= 20000)
+		lpf = 0x1;
+	else if (b_w <= 22000)
+		lpf = 0x9;
+	else if (b_w <= 24000)
+		lpf = 0x5;
+	else if (b_w <= 26000)
+		lpf = 0xd;
+	else if (b_w <= 28000)
+		lpf = 0x3;
+		else
+		lpf = 0xb;
+	buf[2] ^= 0x1c; /* Flip bits 3-5 */
+	/* Set lpf */
+	buf[2] |= ((lpf >> 2) & 0x3) << 3;
+	buf[3] |= (lpf & 0x3) << 2;
+
+	return;
+}
+
+static struct dvb_pll_desc dvb_pll_opera1 = {
+	.name  = "Opera Tuner",
+	.min   =  900000,
+	.max   = 2250000,
+	.initdata = (u8[]){ 4, 0x08, 0xe5, 0xe1, 0x00 },
+	.initdata2 = (u8[]){ 4, 0x08, 0xe5, 0xe5, 0x00 },
+	.iffreq= 0,
+	.set   = opera1_bw,
+	.count = 8,
+	.entries = {
+		{ 1064000, 500, 0xf9, 0xc2 },
+		{ 1169000, 500, 0xf9, 0xe2 },
+		{ 1299000, 500, 0xf9, 0x20 },
+		{ 1444000, 500, 0xf9, 0x40 },
+		{ 1606000, 500, 0xf9, 0x60 },
+		{ 1777000, 500, 0xf9, 0x80 },
+		{ 1941000, 500, 0xf9, 0xa0 },
+		{ 2250000, 500, 0xf9, 0xc0 },
+	}
+};
+
+static void samsung_dtos403ih102a_set(struct dvb_frontend *fe, u8 *buf)
+{
+	struct dvb_pll_priv *priv = fe->tuner_priv;
+	struct i2c_msg msg = {
+		.addr = priv->pll_i2c_address,
+		.flags = 0,
+		.buf = buf,
+		.len = 4
+	};
+	int result;
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+
+	result = i2c_transfer(priv->i2c, &msg, 1);
+	if (result != 1)
+		printk(KERN_ERR "%s: i2c_transfer failed:%d",
+			__func__, result);
+
+	buf[2] = 0x9e;
+	buf[3] = 0x90;
+
+	return;
+}
+
+/* unknown pll used in Samsung DTOS403IH102A DVB-C tuner */
+static struct dvb_pll_desc dvb_pll_samsung_dtos403ih102a = {
+	.name   = "Samsung DTOS403IH102A",
+	.min    =  44250000,
+	.max    = 858000000,
+	.iffreq =  36125000,
+	.count  = 8,
+	.set    = samsung_dtos403ih102a_set,
+	.entries = {
+		{ 135000000, 62500, 0xbe, 0x01 },
+		{ 177000000, 62500, 0xf6, 0x01 },
+		{ 370000000, 62500, 0xbe, 0x02 },
+		{ 450000000, 62500, 0xf6, 0x02 },
+		{ 466000000, 62500, 0xfe, 0x02 },
+		{ 538000000, 62500, 0xbe, 0x08 },
+		{ 826000000, 62500, 0xf6, 0x08 },
+		{ 999999999, 62500, 0xfe, 0x08 },
+	}
+};
+
+/* Samsung TDTC9251DH0 DVB-T NIM, as used on AirStar 2 */
+static struct dvb_pll_desc dvb_pll_samsung_tdtc9251dh0 = {
+	.name	= "Samsung TDTC9251DH0",
+	.min	=  48000000,
+	.max	= 863000000,
+	.iffreq	=  36166667,
+	.count	= 3,
+	.entries = {
+		{ 157500000, 166667, 0xcc, 0x09 },
+		{ 443000000, 166667, 0xcc, 0x0a },
+		{ 863000000, 166667, 0xcc, 0x08 },
+	}
+};
+
+/* Samsung TBDU18132 DVB-S NIM with TSA5059 PLL, used in SkyStar2 DVB-S 2.3 */
+static struct dvb_pll_desc dvb_pll_samsung_tbdu18132 = {
+	.name = "Samsung TBDU18132",
+	.min	=  950000,
+	.max	= 2150000, /* guesses */
+	.iffreq = 0,
+	.count = 2,
+	.entries = {
+		{ 1550000, 125, 0x84, 0x82 },
+		{ 4095937, 125, 0x84, 0x80 },
+	}
+	/* TSA5059 PLL has a 17 bit divisor rather than the 15 bits supported
+	 * by this driver.  The two extra bits are 0x60 in the third byte.  15
+	 * bits is enough for over 4 GHz, which is enough to cover the range
+	 * of this tuner.  We could use the additional divisor bits by adding
+	 * more entries, e.g.
+	 { 0x0ffff * 125 + 125/2, 125, 0x84 | 0x20, },
+	 { 0x17fff * 125 + 125/2, 125, 0x84 | 0x40, },
+	 { 0x1ffff * 125 + 125/2, 125, 0x84 | 0x60, }, */
+};
+
+/* Samsung TBMU24112 DVB-S NIM with SL1935 zero-IF tuner */
+static struct dvb_pll_desc dvb_pll_samsung_tbmu24112 = {
+	.name = "Samsung TBMU24112",
+	.min	=  950000,
+	.max	= 2150000, /* guesses */
+	.iffreq = 0,
+	.count = 2,
+	.entries = {
+		{ 1500000, 125, 0x84, 0x18 },
+		{ 9999999, 125, 0x84, 0x08 },
+	}
+};
+
+/* Alps TDEE4 DVB-C NIM, used on Cablestar 2 */
+/* byte 4 : 1  *   *   AGD R3  R2  R1  R0
+ * byte 5 : C1 *   RE  RTS BS4 BS3 BS2 BS1
+ * AGD = 1, R3 R2 R1 R0 = 0 1 0 1 => byte 4 = 1**10101 = 0x95
+ * Range(MHz)  C1 *  RE RTS BS4 BS3 BS2 BS1  Byte 5
+ *  47 - 153   0  *  0   0   0   0   0   1   0x01
+ * 153 - 430   0  *  0   0   0   0   1   0   0x02
+ * 430 - 822   0  *  0   0   1   0   0   0   0x08
+ * 822 - 862   1  *  0   0   1   0   0   0   0x88 */
+static struct dvb_pll_desc dvb_pll_alps_tdee4 = {
+	.name = "ALPS TDEE4",
+	.min	=  47000000,
+	.max	= 862000000,
+	.iffreq	=  36125000,
+	.count = 4,
+	.entries = {
+		{ 153000000, 62500, 0x95, 0x01 },
+		{ 430000000, 62500, 0x95, 0x02 },
+		{ 822000000, 62500, 0x95, 0x08 },
+		{ 999999999, 62500, 0x95, 0x88 },
+	}
+};
+
+/* ----------------------------------------------------------- */
+
+static struct dvb_pll_desc *pll_list[] = {
+	[DVB_PLL_UNDEFINED]              = NULL,
+	[DVB_PLL_THOMSON_DTT7579]        = &dvb_pll_thomson_dtt7579,
+	[DVB_PLL_THOMSON_DTT759X]        = &dvb_pll_thomson_dtt759x,
+	[DVB_PLL_THOMSON_DTT7520X]       = &dvb_pll_thomson_dtt7520x,
+	[DVB_PLL_LG_Z201]                = &dvb_pll_lg_z201,
+	[DVB_PLL_UNKNOWN_1]              = &dvb_pll_unknown_1,
+	[DVB_PLL_TUA6010XS]              = &dvb_pll_tua6010xs,
+	[DVB_PLL_ENV57H1XD5]             = &dvb_pll_env57h1xd5,
+	[DVB_PLL_TUA6034]                = &dvb_pll_tua6034,
+	[DVB_PLL_TDA665X]                = &dvb_pll_tda665x,
+	[DVB_PLL_TDED4]                  = &dvb_pll_tded4,
+	[DVB_PLL_TDEE4]                  = &dvb_pll_alps_tdee4,
+	[DVB_PLL_TDHU2]                  = &dvb_pll_tdhu2,
+	[DVB_PLL_SAMSUNG_TBMV]           = &dvb_pll_samsung_tbmv,
+	[DVB_PLL_PHILIPS_SD1878_TDA8261] = &dvb_pll_philips_sd1878_tda8261,
+	[DVB_PLL_OPERA1]                 = &dvb_pll_opera1,
+	[DVB_PLL_SAMSUNG_DTOS403IH102A]  = &dvb_pll_samsung_dtos403ih102a,
+	[DVB_PLL_SAMSUNG_TDTC9251DH0]    = &dvb_pll_samsung_tdtc9251dh0,
+	[DVB_PLL_SAMSUNG_TBDU18132]	 = &dvb_pll_samsung_tbdu18132,
+	[DVB_PLL_SAMSUNG_TBMU24112]      = &dvb_pll_samsung_tbmu24112,
+};
+
+/* ----------------------------------------------------------- */
+/* code                                                        */
+
+static int dvb_pll_configure(struct dvb_frontend *fe, u8 *buf,
+			     const u32 frequency)
+{
+	struct dvb_pll_priv *priv = fe->tuner_priv;
+	struct dvb_pll_desc *desc = priv->pll_desc;
+	u32 div;
+	int i;
+
+	if (frequency && (frequency < desc->min || frequency > desc->max))
+		return -EINVAL;
+
+	for (i = 0; i < desc->count; i++) {
+		if (frequency > desc->entries[i].limit)
+			continue;
+		break;
+	}
+
+	if (debug)
+		printk("pll: %s: freq=%d | i=%d/%d\n", desc->name,
+		       frequency, i, desc->count);
+	if (i == desc->count)
+		return -EINVAL;
+
+	div = (frequency + desc->iffreq +
+	       desc->entries[i].stepsize/2) / desc->entries[i].stepsize;
+	buf[0] = div >> 8;
+	buf[1] = div & 0xff;
+	buf[2] = desc->entries[i].config;
+	buf[3] = desc->entries[i].cb;
+
+	if (desc->set)
+		desc->set(fe, buf);
+
+	if (debug)
+		printk("pll: %s: div=%d | buf=0x%02x,0x%02x,0x%02x,0x%02x\n",
+		       desc->name, div, buf[0], buf[1], buf[2], buf[3]);
+
+	// calculate the frequency we set it to
+	return (div * desc->entries[i].stepsize) - desc->iffreq;
+}
+
+static int dvb_pll_release(struct dvb_frontend *fe)
+{
+	kfree(fe->tuner_priv);
+	fe->tuner_priv = NULL;
+	return 0;
+}
+
+static int dvb_pll_sleep(struct dvb_frontend *fe)
+{
+	struct dvb_pll_priv *priv = fe->tuner_priv;
+
+	if (priv->i2c == NULL)
+		return -EINVAL;
+
+	if (priv->pll_desc->sleepdata) {
+		struct i2c_msg msg = { .flags = 0,
+			.addr = priv->pll_i2c_address,
+			.buf = priv->pll_desc->sleepdata + 1,
+			.len = priv->pll_desc->sleepdata[0] };
+
+		int result;
+
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 1);
+		if ((result = i2c_transfer(priv->i2c, &msg, 1)) != 1) {
+			return result;
+		}
+		return 0;
+	}
+	/* Shouldn't be called when initdata is NULL, maybe BUG()? */
+	return -EINVAL;
+}
+
+static int dvb_pll_set_params(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	struct dvb_pll_priv *priv = fe->tuner_priv;
+	u8 buf[4];
+	struct i2c_msg msg =
+		{ .addr = priv->pll_i2c_address, .flags = 0,
+		  .buf = buf, .len = sizeof(buf) };
+	int result;
+	u32 frequency = 0;
+
+	if (priv->i2c == NULL)
+		return -EINVAL;
+
+	result = dvb_pll_configure(fe, buf, c->frequency);
+	if (result < 0)
+		return result;
+	else
+		frequency = result;
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+	if ((result = i2c_transfer(priv->i2c, &msg, 1)) != 1) {
+		return result;
+	}
+
+	priv->frequency = frequency;
+	priv->bandwidth = c->bandwidth_hz;
+
+	return 0;
+}
+
+static int dvb_pll_calc_regs(struct dvb_frontend *fe,
+			     u8 *buf, int buf_len)
+{
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	struct dvb_pll_priv *priv = fe->tuner_priv;
+	int result;
+	u32 frequency = 0;
+
+	if (buf_len < 5)
+		return -EINVAL;
+
+	result = dvb_pll_configure(fe, buf + 1, c->frequency);
+	if (result < 0)
+		return result;
+	else
+		frequency = result;
+
+	buf[0] = priv->pll_i2c_address;
+
+	priv->frequency = frequency;
+	priv->bandwidth = c->bandwidth_hz;
+
+	return 5;
+}
+
+static int dvb_pll_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+	struct dvb_pll_priv *priv = fe->tuner_priv;
+	*frequency = priv->frequency;
+	return 0;
+}
+
+static int dvb_pll_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
+{
+	struct dvb_pll_priv *priv = fe->tuner_priv;
+	*bandwidth = priv->bandwidth;
+	return 0;
+}
+
+static int dvb_pll_init(struct dvb_frontend *fe)
+{
+	struct dvb_pll_priv *priv = fe->tuner_priv;
+
+	if (priv->i2c == NULL)
+		return -EINVAL;
+
+	if (priv->pll_desc->initdata) {
+		struct i2c_msg msg = { .flags = 0,
+			.addr = priv->pll_i2c_address,
+			.buf = priv->pll_desc->initdata + 1,
+			.len = priv->pll_desc->initdata[0] };
+
+		int result;
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 1);
+		result = i2c_transfer(priv->i2c, &msg, 1);
+		if (result != 1)
+			return result;
+		if (priv->pll_desc->initdata2) {
+			msg.buf = priv->pll_desc->initdata2 + 1;
+			msg.len = priv->pll_desc->initdata2[0];
+			if (fe->ops.i2c_gate_ctrl)
+				fe->ops.i2c_gate_ctrl(fe, 1);
+			result = i2c_transfer(priv->i2c, &msg, 1);
+			if (result != 1)
+				return result;
+		}
+		return 0;
+	}
+	/* Shouldn't be called when initdata is NULL, maybe BUG()? */
+	return -EINVAL;
+}
+
+static struct dvb_tuner_ops dvb_pll_tuner_ops = {
+	.release = dvb_pll_release,
+	.sleep = dvb_pll_sleep,
+	.init = dvb_pll_init,
+	.set_params = dvb_pll_set_params,
+	.calc_regs = dvb_pll_calc_regs,
+	.get_frequency = dvb_pll_get_frequency,
+	.get_bandwidth = dvb_pll_get_bandwidth,
+};
+
+struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr,
+				    struct i2c_adapter *i2c,
+				    unsigned int pll_desc_id)
+{
+	u8 b1 [] = { 0 };
+	struct i2c_msg msg = { .addr = pll_addr, .flags = I2C_M_RD,
+			       .buf = b1, .len = 1 };
+	struct dvb_pll_priv *priv = NULL;
+	int ret;
+	struct dvb_pll_desc *desc;
+
+	if ((id[dvb_pll_devcount] > DVB_PLL_UNDEFINED) &&
+	    (id[dvb_pll_devcount] < ARRAY_SIZE(pll_list)))
+		pll_desc_id = id[dvb_pll_devcount];
+
+	BUG_ON(pll_desc_id < 1 || pll_desc_id >= ARRAY_SIZE(pll_list));
+
+	desc = pll_list[pll_desc_id];
+
+	if (i2c != NULL) {
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 1);
+
+		ret = i2c_transfer (i2c, &msg, 1);
+		if (ret != 1)
+			return NULL;
+		if (fe->ops.i2c_gate_ctrl)
+			     fe->ops.i2c_gate_ctrl(fe, 0);
+	}
+
+	priv = kzalloc(sizeof(struct dvb_pll_priv), GFP_KERNEL);
+	if (priv == NULL)
+		return NULL;
+
+	priv->pll_i2c_address = pll_addr;
+	priv->i2c = i2c;
+	priv->pll_desc = desc;
+	priv->nr = dvb_pll_devcount++;
+
+	memcpy(&fe->ops.tuner_ops, &dvb_pll_tuner_ops,
+	       sizeof(struct dvb_tuner_ops));
+
+	strncpy(fe->ops.tuner_ops.info.name, desc->name,
+		sizeof(fe->ops.tuner_ops.info.name));
+	fe->ops.tuner_ops.info.frequency_min = desc->min;
+	fe->ops.tuner_ops.info.frequency_max = desc->max;
+	if (!desc->initdata)
+		fe->ops.tuner_ops.init = NULL;
+	if (!desc->sleepdata)
+		fe->ops.tuner_ops.sleep = NULL;
+
+	fe->tuner_priv = priv;
+
+	if ((debug) || (id[priv->nr] == pll_desc_id)) {
+		printk("dvb-pll[%d]", priv->nr);
+		if (i2c != NULL)
+			printk(" %d-%04x", i2c_adapter_id(i2c), pll_addr);
+		printk(": id# %d (%s) attached, %s\n", pll_desc_id, desc->name,
+		       id[priv->nr] == pll_desc_id ?
+				"insmod option" : "autodetected");
+	}
+
+	return fe;
+}
+EXPORT_SYMBOL(dvb_pll_attach);
+
+MODULE_DESCRIPTION("dvb pll library");
+MODULE_AUTHOR("Gerd Knorr");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb-frontends/dvb-pll.h b/drivers/media/dvb-frontends/dvb-pll.h
new file mode 100644
index 0000000..4de754f
--- /dev/null
+++ b/drivers/media/dvb-frontends/dvb-pll.h
@@ -0,0 +1,57 @@
+/*
+ * descriptions + helper functions for simple dvb plls.
+ */
+
+#ifndef __DVB_PLL_H__
+#define __DVB_PLL_H__
+
+#include <linux/i2c.h>
+#include "dvb_frontend.h"
+
+#define DVB_PLL_UNDEFINED               0
+#define DVB_PLL_THOMSON_DTT7579         1
+#define DVB_PLL_THOMSON_DTT759X         2
+#define DVB_PLL_LG_Z201                 3
+#define DVB_PLL_UNKNOWN_1               4
+#define DVB_PLL_TUA6010XS               5
+#define DVB_PLL_ENV57H1XD5              6
+#define DVB_PLL_TUA6034                 7
+#define DVB_PLL_TDA665X                 8
+#define DVB_PLL_TDED4                   9
+#define DVB_PLL_TDHU2                  10
+#define DVB_PLL_SAMSUNG_TBMV           11
+#define DVB_PLL_PHILIPS_SD1878_TDA8261 12
+#define DVB_PLL_OPERA1                 13
+#define DVB_PLL_SAMSUNG_DTOS403IH102A  14
+#define DVB_PLL_SAMSUNG_TDTC9251DH0    15
+#define DVB_PLL_SAMSUNG_TBDU18132      16
+#define DVB_PLL_SAMSUNG_TBMU24112      17
+#define DVB_PLL_TDEE4		       18
+#define DVB_PLL_THOMSON_DTT7520X       19
+
+/**
+ * Attach a dvb-pll to the supplied frontend structure.
+ *
+ * @param fe Frontend to attach to.
+ * @param pll_addr i2c address of the PLL (if used).
+ * @param i2c i2c adapter to use (set to NULL if not used).
+ * @param pll_desc_id dvb_pll_desc to use.
+ * @return Frontend pointer on success, NULL on failure
+ */
+#if defined(CONFIG_DVB_PLL) || (defined(CONFIG_DVB_PLL_MODULE) && defined(MODULE))
+extern struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe,
+					   int pll_addr,
+					   struct i2c_adapter *i2c,
+					   unsigned int pll_desc_id);
+#else
+static inline struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe,
+					   int pll_addr,
+					   struct i2c_adapter *i2c,
+					   unsigned int pll_desc_id)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif
+
+#endif
diff --git a/drivers/media/dvb-frontends/dvb_dummy_fe.c b/drivers/media/dvb-frontends/dvb_dummy_fe.c
new file mode 100644
index 0000000..dcfc902
--- /dev/null
+++ b/drivers/media/dvb-frontends/dvb_dummy_fe.c
@@ -0,0 +1,276 @@
+/*
+ *  Driver for Dummy Frontend
+ *
+ *  Written by Emard <emard@softhome.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 program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You 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/init.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+
+#include "dvb_frontend.h"
+#include "dvb_dummy_fe.h"
+
+
+struct dvb_dummy_fe_state {
+	struct dvb_frontend frontend;
+};
+
+
+static int dvb_dummy_fe_read_status(struct dvb_frontend* fe, fe_status_t* status)
+{
+	*status = FE_HAS_SIGNAL
+		| FE_HAS_CARRIER
+		| FE_HAS_VITERBI
+		| FE_HAS_SYNC
+		| FE_HAS_LOCK;
+
+	return 0;
+}
+
+static int dvb_dummy_fe_read_ber(struct dvb_frontend* fe, u32* ber)
+{
+	*ber = 0;
+	return 0;
+}
+
+static int dvb_dummy_fe_read_signal_strength(struct dvb_frontend* fe, u16* strength)
+{
+	*strength = 0;
+	return 0;
+}
+
+static int dvb_dummy_fe_read_snr(struct dvb_frontend* fe, u16* snr)
+{
+	*snr = 0;
+	return 0;
+}
+
+static int dvb_dummy_fe_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
+{
+	*ucblocks = 0;
+	return 0;
+}
+
+/*
+ * Only needed if it actually reads something from the hardware
+ */
+static int dvb_dummy_fe_get_frontend(struct dvb_frontend *fe)
+{
+	return 0;
+}
+
+static int dvb_dummy_fe_set_frontend(struct dvb_frontend *fe)
+{
+	if (fe->ops.tuner_ops.set_params) {
+		fe->ops.tuner_ops.set_params(fe);
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 0);
+	}
+
+	return 0;
+}
+
+static int dvb_dummy_fe_sleep(struct dvb_frontend* fe)
+{
+	return 0;
+}
+
+static int dvb_dummy_fe_init(struct dvb_frontend* fe)
+{
+	return 0;
+}
+
+static int dvb_dummy_fe_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
+{
+	return 0;
+}
+
+static int dvb_dummy_fe_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
+{
+	return 0;
+}
+
+static void dvb_dummy_fe_release(struct dvb_frontend* fe)
+{
+	struct dvb_dummy_fe_state* state = fe->demodulator_priv;
+	kfree(state);
+}
+
+static struct dvb_frontend_ops dvb_dummy_fe_ofdm_ops;
+
+struct dvb_frontend* dvb_dummy_fe_ofdm_attach(void)
+{
+	struct dvb_dummy_fe_state* state = NULL;
+
+	/* allocate memory for the internal state */
+	state = kzalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL);
+	if (state == NULL) goto error;
+
+	/* create dvb_frontend */
+	memcpy(&state->frontend.ops, &dvb_dummy_fe_ofdm_ops, sizeof(struct dvb_frontend_ops));
+	state->frontend.demodulator_priv = state;
+	return &state->frontend;
+
+error:
+	kfree(state);
+	return NULL;
+}
+
+static struct dvb_frontend_ops dvb_dummy_fe_qpsk_ops;
+
+struct dvb_frontend *dvb_dummy_fe_qpsk_attach(void)
+{
+	struct dvb_dummy_fe_state* state = NULL;
+
+	/* allocate memory for the internal state */
+	state = kzalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL);
+	if (state == NULL) goto error;
+
+	/* create dvb_frontend */
+	memcpy(&state->frontend.ops, &dvb_dummy_fe_qpsk_ops, sizeof(struct dvb_frontend_ops));
+	state->frontend.demodulator_priv = state;
+	return &state->frontend;
+
+error:
+	kfree(state);
+	return NULL;
+}
+
+static struct dvb_frontend_ops dvb_dummy_fe_qam_ops;
+
+struct dvb_frontend *dvb_dummy_fe_qam_attach(void)
+{
+	struct dvb_dummy_fe_state* state = NULL;
+
+	/* allocate memory for the internal state */
+	state = kzalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL);
+	if (state == NULL) goto error;
+
+	/* create dvb_frontend */
+	memcpy(&state->frontend.ops, &dvb_dummy_fe_qam_ops, sizeof(struct dvb_frontend_ops));
+	state->frontend.demodulator_priv = state;
+	return &state->frontend;
+
+error:
+	kfree(state);
+	return NULL;
+}
+
+static struct dvb_frontend_ops dvb_dummy_fe_ofdm_ops = {
+	.delsys = { SYS_DVBT },
+	.info = {
+		.name			= "Dummy DVB-T",
+		.frequency_min		= 0,
+		.frequency_max		= 863250000,
+		.frequency_stepsize	= 62500,
+		.caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
+				FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
+				FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO |
+				FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
+				FE_CAN_TRANSMISSION_MODE_AUTO |
+				FE_CAN_GUARD_INTERVAL_AUTO |
+				FE_CAN_HIERARCHY_AUTO,
+	},
+
+	.release = dvb_dummy_fe_release,
+
+	.init = dvb_dummy_fe_init,
+	.sleep = dvb_dummy_fe_sleep,
+
+	.set_frontend = dvb_dummy_fe_set_frontend,
+	.get_frontend = dvb_dummy_fe_get_frontend,
+
+	.read_status = dvb_dummy_fe_read_status,
+	.read_ber = dvb_dummy_fe_read_ber,
+	.read_signal_strength = dvb_dummy_fe_read_signal_strength,
+	.read_snr = dvb_dummy_fe_read_snr,
+	.read_ucblocks = dvb_dummy_fe_read_ucblocks,
+};
+
+static struct dvb_frontend_ops dvb_dummy_fe_qam_ops = {
+	.delsys = { SYS_DVBC_ANNEX_A },
+	.info = {
+		.name			= "Dummy DVB-C",
+		.frequency_stepsize	= 62500,
+		.frequency_min		= 51000000,
+		.frequency_max		= 858000000,
+		.symbol_rate_min	= (57840000/2)/64,     /* SACLK/64 == (XIN/2)/64 */
+		.symbol_rate_max	= (57840000/2)/4,      /* SACLK/4 */
+		.caps = FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 |
+			FE_CAN_QAM_128 | FE_CAN_QAM_256 |
+			FE_CAN_FEC_AUTO | FE_CAN_INVERSION_AUTO
+	},
+
+	.release = dvb_dummy_fe_release,
+
+	.init = dvb_dummy_fe_init,
+	.sleep = dvb_dummy_fe_sleep,
+
+	.set_frontend = dvb_dummy_fe_set_frontend,
+	.get_frontend = dvb_dummy_fe_get_frontend,
+
+	.read_status = dvb_dummy_fe_read_status,
+	.read_ber = dvb_dummy_fe_read_ber,
+	.read_signal_strength = dvb_dummy_fe_read_signal_strength,
+	.read_snr = dvb_dummy_fe_read_snr,
+	.read_ucblocks = dvb_dummy_fe_read_ucblocks,
+};
+
+static struct dvb_frontend_ops dvb_dummy_fe_qpsk_ops = {
+	.delsys = { SYS_DVBS },
+	.info = {
+		.name			= "Dummy DVB-S",
+		.frequency_min		= 950000,
+		.frequency_max		= 2150000,
+		.frequency_stepsize	= 250,           /* kHz for QPSK frontends */
+		.frequency_tolerance	= 29500,
+		.symbol_rate_min	= 1000000,
+		.symbol_rate_max	= 45000000,
+		.caps = FE_CAN_INVERSION_AUTO |
+			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_FEC_AUTO |
+			FE_CAN_QPSK
+	},
+
+	.release = dvb_dummy_fe_release,
+
+	.init = dvb_dummy_fe_init,
+	.sleep = dvb_dummy_fe_sleep,
+
+	.set_frontend = dvb_dummy_fe_set_frontend,
+	.get_frontend = dvb_dummy_fe_get_frontend,
+
+	.read_status = dvb_dummy_fe_read_status,
+	.read_ber = dvb_dummy_fe_read_ber,
+	.read_signal_strength = dvb_dummy_fe_read_signal_strength,
+	.read_snr = dvb_dummy_fe_read_snr,
+	.read_ucblocks = dvb_dummy_fe_read_ucblocks,
+
+	.set_voltage = dvb_dummy_fe_set_voltage,
+	.set_tone = dvb_dummy_fe_set_tone,
+};
+
+MODULE_DESCRIPTION("DVB DUMMY Frontend");
+MODULE_AUTHOR("Emard");
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(dvb_dummy_fe_ofdm_attach);
+EXPORT_SYMBOL(dvb_dummy_fe_qam_attach);
+EXPORT_SYMBOL(dvb_dummy_fe_qpsk_attach);
diff --git a/drivers/media/dvb-frontends/dvb_dummy_fe.h b/drivers/media/dvb-frontends/dvb_dummy_fe.h
new file mode 100644
index 0000000..1fcb987
--- /dev/null
+++ b/drivers/media/dvb-frontends/dvb_dummy_fe.h
@@ -0,0 +1,51 @@
+/*
+ *  Driver for Dummy Frontend
+ *
+ *  Written by Emard <emard@softhome.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 program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You 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_DUMMY_FE_H
+#define DVB_DUMMY_FE_H
+
+#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/ec100.c b/drivers/media/dvb-frontends/ec100.c
new file mode 100644
index 0000000..9d42480
--- /dev/null
+++ b/drivers/media/dvb-frontends/ec100.c
@@ -0,0 +1,345 @@
+/*
+ * E3C EC100 demodulator driver
+ *
+ * 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 "dvb_frontend.h"
+#include "ec100.h"
+
+struct ec100_state {
+	struct i2c_adapter *i2c;
+	struct dvb_frontend frontend;
+	struct ec100_config config;
+
+	u16 ber;
+};
+
+/* write single register */
+static int ec100_write_reg(struct ec100_state *state, u8 reg, u8 val)
+{
+	int ret;
+	u8 buf[2] = {reg, val};
+	struct i2c_msg msg[1] = {
+		{
+			.addr = state->config.demod_address,
+			.flags = 0,
+			.len = sizeof(buf),
+			.buf = buf,
+		}
+	};
+
+	ret = i2c_transfer(state->i2c, msg, 1);
+	if (ret == 1) {
+		ret = 0;
+	} else {
+		dev_warn(&state->i2c->dev, "%s: i2c wr failed=%d reg=%02x\n",
+				KBUILD_MODNAME, ret, reg);
+		ret = -EREMOTEIO;
+	}
+
+	return ret;
+}
+
+/* read single register */
+static int ec100_read_reg(struct ec100_state *state, u8 reg, u8 *val)
+{
+	int ret;
+	struct i2c_msg msg[2] = {
+		{
+			.addr = state->config.demod_address,
+			.flags = 0,
+			.len = 1,
+			.buf = &reg
+		}, {
+			.addr = state->config.demod_address,
+			.flags = I2C_M_RD,
+			.len = 1,
+			.buf = val
+		}
+	};
+
+	ret = i2c_transfer(state->i2c, msg, 2);
+	if (ret == 2) {
+		ret = 0;
+	} else {
+		dev_warn(&state->i2c->dev, "%s: i2c rd failed=%d reg=%02x\n",
+				KBUILD_MODNAME, ret, reg);
+		ret = -EREMOTEIO;
+	}
+
+	return ret;
+}
+
+static int ec100_set_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	struct ec100_state *state = fe->demodulator_priv;
+	int ret;
+	u8 tmp, tmp2;
+
+	dev_dbg(&state->i2c->dev, "%s: frequency=%d bandwidth_hz=%d\n",
+			__func__, c->frequency, c->bandwidth_hz);
+
+	/* program tuner */
+	if (fe->ops.tuner_ops.set_params)
+		fe->ops.tuner_ops.set_params(fe);
+
+	ret = ec100_write_reg(state, 0x04, 0x06);
+	if (ret)
+		goto error;
+	ret = ec100_write_reg(state, 0x67, 0x58);
+	if (ret)
+		goto error;
+	ret = ec100_write_reg(state, 0x05, 0x18);
+	if (ret)
+		goto error;
+
+	/* reg/bw |   6  |   7  |   8
+	   -------+------+------+------
+	   A 0x1b | 0xa1 | 0xe7 | 0x2c
+	   A 0x1c | 0x55 | 0x63 | 0x72
+	   -------+------+------+------
+	   B 0x1b | 0xb7 | 0x00 | 0x49
+	   B 0x1c | 0x55 | 0x64 | 0x72 */
+
+	switch (c->bandwidth_hz) {
+	case 6000000:
+		tmp = 0xb7;
+		tmp2 = 0x55;
+		break;
+	case 7000000:
+		tmp = 0x00;
+		tmp2 = 0x64;
+		break;
+	case 8000000:
+	default:
+		tmp = 0x49;
+		tmp2 = 0x72;
+	}
+
+	ret = ec100_write_reg(state, 0x1b, tmp);
+	if (ret)
+		goto error;
+	ret = ec100_write_reg(state, 0x1c, tmp2);
+	if (ret)
+		goto error;
+
+	ret = ec100_write_reg(state, 0x0c, 0xbb); /* if freq */
+	if (ret)
+		goto error;
+	ret = ec100_write_reg(state, 0x0d, 0x31); /* if freq */
+	if (ret)
+		goto error;
+
+	ret = ec100_write_reg(state, 0x08, 0x24);
+	if (ret)
+		goto error;
+
+	ret = ec100_write_reg(state, 0x00, 0x00); /* go */
+	if (ret)
+		goto error;
+	ret = ec100_write_reg(state, 0x00, 0x20); /* go */
+	if (ret)
+		goto error;
+
+	return ret;
+error:
+	dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	return ret;
+}
+
+static int ec100_get_tune_settings(struct dvb_frontend *fe,
+	struct dvb_frontend_tune_settings *fesettings)
+{
+	fesettings->min_delay_ms = 300;
+	fesettings->step_size = 0;
+	fesettings->max_drift = 0;
+
+	return 0;
+}
+
+static int ec100_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+	struct ec100_state *state = fe->demodulator_priv;
+	int ret;
+	u8 tmp;
+	*status = 0;
+
+	ret = ec100_read_reg(state, 0x42, &tmp);
+	if (ret)
+		goto error;
+
+	if (tmp & 0x80) {
+		/* bit7 set - have lock */
+		*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI |
+			FE_HAS_SYNC | FE_HAS_LOCK;
+	} else {
+		ret = ec100_read_reg(state, 0x01, &tmp);
+		if (ret)
+			goto error;
+
+		if (tmp & 0x10) {
+			/* bit4 set - have signal */
+			*status |= FE_HAS_SIGNAL;
+			if (!(tmp & 0x01)) {
+				/* bit0 clear - have ~valid signal */
+				*status |= FE_HAS_CARRIER |  FE_HAS_VITERBI;
+			}
+		}
+	}
+
+	return ret;
+error:
+	dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	return ret;
+}
+
+static int ec100_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+	struct ec100_state *state = fe->demodulator_priv;
+	int ret;
+	u8 tmp, tmp2;
+	u16 ber2;
+
+	*ber = 0;
+
+	ret = ec100_read_reg(state, 0x65, &tmp);
+	if (ret)
+		goto error;
+	ret = ec100_read_reg(state, 0x66, &tmp2);
+	if (ret)
+		goto error;
+
+	ber2 = (tmp2 << 8) | tmp;
+
+	/* if counter overflow or clear */
+	if (ber2 < state->ber)
+		*ber = ber2;
+	else
+		*ber = ber2 - state->ber;
+
+	state->ber = ber2;
+
+	return ret;
+error:
+	dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	return ret;
+}
+
+static int ec100_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
+{
+	struct ec100_state *state = fe->demodulator_priv;
+	int ret;
+	u8 tmp;
+
+	ret = ec100_read_reg(state, 0x24, &tmp);
+	if (ret) {
+		*strength = 0;
+		goto error;
+	}
+
+	*strength = ((tmp << 8) | tmp);
+
+	return ret;
+error:
+	dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	return ret;
+}
+
+static int ec100_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+	*snr = 0;
+	return 0;
+}
+
+static int ec100_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+	*ucblocks = 0;
+	return 0;
+}
+
+static void ec100_release(struct dvb_frontend *fe)
+{
+	struct ec100_state *state = fe->demodulator_priv;
+	kfree(state);
+}
+
+static struct dvb_frontend_ops ec100_ops;
+
+struct dvb_frontend *ec100_attach(const struct ec100_config *config,
+	struct i2c_adapter *i2c)
+{
+	int ret;
+	struct ec100_state *state = NULL;
+	u8 tmp;
+
+	/* allocate memory for the internal state */
+	state = kzalloc(sizeof(struct ec100_state), GFP_KERNEL);
+	if (state == NULL)
+		goto error;
+
+	/* setup the state */
+	state->i2c = i2c;
+	memcpy(&state->config, config, sizeof(struct ec100_config));
+
+	/* check if the demod is there */
+	ret = ec100_read_reg(state, 0x33, &tmp);
+	if (ret || tmp != 0x0b)
+		goto error;
+
+	/* create dvb_frontend */
+	memcpy(&state->frontend.ops, &ec100_ops,
+		sizeof(struct dvb_frontend_ops));
+	state->frontend.demodulator_priv = state;
+
+	return &state->frontend;
+error:
+	kfree(state);
+	return NULL;
+}
+EXPORT_SYMBOL(ec100_attach);
+
+static struct dvb_frontend_ops ec100_ops = {
+	.delsys = { SYS_DVBT },
+	.info = {
+		.name = "E3C EC100 DVB-T",
+		.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_FEC_AUTO |
+			FE_CAN_QPSK | FE_CAN_QAM_16 |
+			FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
+			FE_CAN_TRANSMISSION_MODE_AUTO |
+			FE_CAN_GUARD_INTERVAL_AUTO |
+			FE_CAN_HIERARCHY_AUTO |
+			FE_CAN_MUTE_TS
+	},
+
+	.release = ec100_release,
+	.set_frontend = ec100_set_frontend,
+	.get_tune_settings = ec100_get_tune_settings,
+	.read_status = ec100_read_status,
+	.read_ber = ec100_read_ber,
+	.read_signal_strength = ec100_read_signal_strength,
+	.read_snr = ec100_read_snr,
+	.read_ucblocks = ec100_read_ucblocks,
+};
+
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
+MODULE_DESCRIPTION("E3C EC100 DVB-T demodulator driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb-frontends/ec100.h b/drivers/media/dvb-frontends/ec100.h
new file mode 100644
index 0000000..b847971
--- /dev/null
+++ b/drivers/media/dvb-frontends/ec100.h
@@ -0,0 +1,46 @@
+/*
+ * E3C EC100 demodulator driver
+ *
+ * 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 EC100_H
+#define EC100_H
+
+#include <linux/dvb/frontend.h>
+
+struct ec100_config {
+	/* demodulator's I2C address */
+	u8 demod_address;
+};
+
+
+#if defined(CONFIG_DVB_EC100) || \
+	(defined(CONFIG_DVB_EC100_MODULE) && defined(MODULE))
+extern struct dvb_frontend *ec100_attach(const struct ec100_config *config,
+	struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend *ec100_attach(
+	const struct ec100_config *config, struct i2c_adapter *i2c)
+{
+	pr_warn("%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif
+
+#endif /* EC100_H */
diff --git a/drivers/media/dvb-frontends/eds1547.h b/drivers/media/dvb-frontends/eds1547.h
new file mode 100644
index 0000000..c983f2f
--- /dev/null
+++ b/drivers/media/dvb-frontends/eds1547.h
@@ -0,0 +1,133 @@
+/* eds1547.h Earda EDS-1547 tuner support
+*
+* Copyright (C) 2008 Igor M. Liplianin (liplianin@me.by)
+*
+*	This program is free software; 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.
+*
+* see Documentation/dvb/README.dvb-usb for more information
+*/
+
+#ifndef EDS1547
+#define EDS1547
+
+static u8 stv0288_earda_inittab[] = {
+	0x01, 0x57,
+	0x02, 0x20,
+	0x03, 0x8e,
+	0x04, 0x8e,
+	0x05, 0x12,
+	0x06, 0x00,
+	0x07, 0x00,
+	0x09, 0x00,
+	0x0a, 0x04,
+	0x0b, 0x00,
+	0x0c, 0x00,
+	0x0d, 0x00,
+	0x0e, 0xd4,
+	0x0f, 0x30,
+	0x11, 0x44,
+	0x12, 0x03,
+	0x13, 0x48,
+	0x14, 0x84,
+	0x15, 0x45,
+	0x16, 0xb7,
+	0x17, 0x9c,
+	0x18, 0x00,
+	0x19, 0xa6,
+	0x1a, 0x88,
+	0x1b, 0x8f,
+	0x1c, 0xf0,
+	0x20, 0x0b,
+	0x21, 0x54,
+	0x22, 0x00,
+	0x23, 0x00,
+	0x2b, 0xff,
+	0x2c, 0xf7,
+	0x30, 0x00,
+	0x31, 0x1e,
+	0x32, 0x14,
+	0x33, 0x0f,
+	0x34, 0x09,
+	0x35, 0x0c,
+	0x36, 0x05,
+	0x37, 0x2f,
+	0x38, 0x16,
+	0x39, 0xbd,
+	0x3a, 0x00,
+	0x3b, 0x13,
+	0x3c, 0x11,
+	0x3d, 0x30,
+	0x40, 0x63,
+	0x41, 0x04,
+	0x42, 0x20,
+	0x43, 0x00,
+	0x44, 0x00,
+	0x45, 0x00,
+	0x46, 0x00,
+	0x47, 0x00,
+	0x4a, 0x00,
+	0x50, 0x10,
+	0x51, 0x36,
+	0x52, 0x09,
+	0x53, 0x94,
+	0x54, 0x62,
+	0x55, 0x29,
+	0x56, 0x64,
+	0x57, 0x2b,
+	0x58, 0x54,
+	0x59, 0x86,
+	0x5a, 0x00,
+	0x5b, 0x9b,
+	0x5c, 0x08,
+	0x5d, 0x7f,
+	0x5e, 0x00,
+	0x5f, 0xff,
+	0x70, 0x00,
+	0x71, 0x00,
+	0x72, 0x00,
+	0x74, 0x00,
+	0x75, 0x00,
+	0x76, 0x00,
+	0x81, 0x00,
+	0x82, 0x3f,
+	0x83, 0x3f,
+	0x84, 0x00,
+	0x85, 0x00,
+	0x88, 0x00,
+	0x89, 0x00,
+	0x8a, 0x00,
+	0x8b, 0x00,
+	0x8c, 0x00,
+	0x90, 0x00,
+	0x91, 0x00,
+	0x92, 0x00,
+	0x93, 0x00,
+	0x94, 0x1c,
+	0x97, 0x00,
+	0xa0, 0x48,
+	0xa1, 0x00,
+	0xb0, 0xb8,
+	0xb1, 0x3a,
+	0xb2, 0x10,
+	0xb3, 0x82,
+	0xb4, 0x80,
+	0xb5, 0x82,
+	0xb6, 0x82,
+	0xb7, 0x82,
+	0xb8, 0x20,
+	0xb9, 0x00,
+	0xf0, 0x00,
+	0xf1, 0x00,
+	0xf2, 0xc0,
+	0xff,0xff,
+};
+
+static struct stv0288_config earda_config = {
+	.demod_address = 0x68,
+	.min_delay_ms = 100,
+	.inittab = stv0288_earda_inittab,
+};
+
+#endif
diff --git a/drivers/media/dvb-frontends/hd29l2.c b/drivers/media/dvb-frontends/hd29l2.c
new file mode 100644
index 0000000..d7b9d54
--- /dev/null
+++ b/drivers/media/dvb-frontends/hd29l2.c
@@ -0,0 +1,866 @@
+/*
+ * HDIC HD29L2 DMB-TH demodulator driver
+ *
+ * Copyright (C) 2011 Metropolia University of Applied Sciences, Electria R&D
+ *
+ * Author: 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 "hd29l2_priv.h"
+
+/* write multiple registers */
+static int hd29l2_wr_regs(struct hd29l2_priv *priv, u8 reg, u8 *val, int len)
+{
+	int ret;
+	u8 buf[2 + len];
+	struct i2c_msg msg[1] = {
+		{
+			.addr = priv->cfg.i2c_addr,
+			.flags = 0,
+			.len = sizeof(buf),
+			.buf = buf,
+		}
+	};
+
+	buf[0] = 0x00;
+	buf[1] = reg;
+	memcpy(&buf[2], val, len);
+
+	ret = i2c_transfer(priv->i2c, msg, 1);
+	if (ret == 1) {
+		ret = 0;
+	} else {
+		dev_warn(&priv->i2c->dev,
+				"%s: i2c wr failed=%d reg=%02x len=%d\n",
+				KBUILD_MODNAME, ret, reg, len);
+		ret = -EREMOTEIO;
+	}
+
+	return ret;
+}
+
+/* read multiple registers */
+static int hd29l2_rd_regs(struct hd29l2_priv *priv, u8 reg, u8 *val, int len)
+{
+	int ret;
+	u8 buf[2] = { 0x00, reg };
+	struct i2c_msg msg[2] = {
+		{
+			.addr = priv->cfg.i2c_addr,
+			.flags = 0,
+			.len = 2,
+			.buf = buf,
+		}, {
+			.addr = priv->cfg.i2c_addr,
+			.flags = I2C_M_RD,
+			.len = len,
+			.buf = val,
+		}
+	};
+
+	ret = i2c_transfer(priv->i2c, msg, 2);
+	if (ret == 2) {
+		ret = 0;
+	} else {
+		dev_warn(&priv->i2c->dev,
+				"%s: i2c rd failed=%d reg=%02x len=%d\n",
+				KBUILD_MODNAME, ret, reg, len);
+		ret = -EREMOTEIO;
+	}
+
+	return ret;
+}
+
+/* write single register */
+static int hd29l2_wr_reg(struct hd29l2_priv *priv, u8 reg, u8 val)
+{
+	return hd29l2_wr_regs(priv, reg, &val, 1);
+}
+
+/* read single register */
+static int hd29l2_rd_reg(struct hd29l2_priv *priv, u8 reg, u8 *val)
+{
+	return hd29l2_rd_regs(priv, reg, val, 1);
+}
+
+/* write single register with mask */
+static int hd29l2_wr_reg_mask(struct hd29l2_priv *priv, u8 reg, u8 val, u8 mask)
+{
+	int ret;
+	u8 tmp;
+
+	/* no need for read if whole reg is written */
+	if (mask != 0xff) {
+		ret = hd29l2_rd_regs(priv, reg, &tmp, 1);
+		if (ret)
+			return ret;
+
+		val &= mask;
+		tmp &= ~mask;
+		val |= tmp;
+	}
+
+	return hd29l2_wr_regs(priv, reg, &val, 1);
+}
+
+/* read single register with mask */
+int hd29l2_rd_reg_mask(struct hd29l2_priv *priv, u8 reg, u8 *val, u8 mask)
+{
+	int ret, i;
+	u8 tmp;
+
+	ret = hd29l2_rd_regs(priv, reg, &tmp, 1);
+	if (ret)
+		return ret;
+
+	tmp &= mask;
+
+	/* find position of the first bit */
+	for (i = 0; i < 8; i++) {
+		if ((mask >> i) & 0x01)
+			break;
+	}
+	*val = tmp >> i;
+
+	return 0;
+}
+
+static int hd29l2_soft_reset(struct hd29l2_priv *priv)
+{
+	int ret;
+	u8 tmp;
+
+	ret = hd29l2_rd_reg(priv, 0x26, &tmp);
+	if (ret)
+		goto err;
+
+	ret = hd29l2_wr_reg(priv, 0x26, 0x0d);
+	if (ret)
+		goto err;
+
+	usleep_range(10000, 20000);
+
+	ret = hd29l2_wr_reg(priv, 0x26, tmp);
+	if (ret)
+		goto err;
+
+	return 0;
+err:
+	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	return ret;
+}
+
+static int hd29l2_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+	int ret, i;
+	struct hd29l2_priv *priv = fe->demodulator_priv;
+	u8 tmp;
+
+	dev_dbg(&priv->i2c->dev, "%s: enable=%d\n", __func__, enable);
+
+	/* set tuner address for demod */
+	if (!priv->tuner_i2c_addr_programmed && enable) {
+		/* no need to set tuner address every time, once is enough */
+		ret = hd29l2_wr_reg(priv, 0x9d, priv->cfg.tuner_i2c_addr << 1);
+		if (ret)
+			goto err;
+
+		priv->tuner_i2c_addr_programmed = true;
+	}
+
+	/* open / close gate */
+	ret = hd29l2_wr_reg(priv, 0x9f, enable);
+	if (ret)
+		goto err;
+
+	/* wait demod ready */
+	for (i = 10; i; i--) {
+		ret = hd29l2_rd_reg(priv, 0x9e, &tmp);
+		if (ret)
+			goto err;
+
+		if (tmp == enable)
+			break;
+
+		usleep_range(5000, 10000);
+	}
+
+	dev_dbg(&priv->i2c->dev, "%s: loop=%d\n", __func__, i);
+
+	return ret;
+err:
+	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	return ret;
+}
+
+static int hd29l2_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+	int ret;
+	struct hd29l2_priv *priv = fe->demodulator_priv;
+	u8 buf[2];
+
+	*status = 0;
+
+	ret = hd29l2_rd_reg(priv, 0x05, &buf[0]);
+	if (ret)
+		goto err;
+
+	if (buf[0] & 0x01) {
+		/* full lock */
+		*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI |
+			FE_HAS_SYNC | FE_HAS_LOCK;
+	} else {
+		ret = hd29l2_rd_reg(priv, 0x0d, &buf[1]);
+		if (ret)
+			goto err;
+
+		if ((buf[1] & 0xfe) == 0x78)
+			/* partial lock */
+			*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
+				FE_HAS_VITERBI | FE_HAS_SYNC;
+	}
+
+	priv->fe_status = *status;
+
+	return 0;
+err:
+	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	return ret;
+}
+
+static int hd29l2_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+	int ret;
+	struct hd29l2_priv *priv = fe->demodulator_priv;
+	u8 buf[2];
+	u16 tmp;
+
+	if (!(priv->fe_status & FE_HAS_LOCK)) {
+		*snr = 0;
+		ret = 0;
+		goto err;
+	}
+
+	ret = hd29l2_rd_regs(priv, 0x0b, buf, 2);
+	if (ret)
+		goto err;
+
+	tmp = (buf[0] << 8) | buf[1];
+
+	/* report SNR in dB * 10 */
+	#define LOG10_20736_24 72422627 /* log10(20736) << 24 */
+	if (tmp)
+		*snr = (LOG10_20736_24 - intlog10(tmp)) / ((1 << 24) / 100);
+	else
+		*snr = 0;
+
+	return 0;
+err:
+	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	return ret;
+}
+
+static int hd29l2_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
+{
+	int ret;
+	struct hd29l2_priv *priv = fe->demodulator_priv;
+	u8 buf[2];
+	u16 tmp;
+
+	*strength = 0;
+
+	ret = hd29l2_rd_regs(priv, 0xd5, buf, 2);
+	if (ret)
+		goto err;
+
+	tmp = buf[0] << 8 | buf[1];
+	tmp = ~tmp & 0x0fff;
+
+	/* scale value to 0x0000-0xffff from 0x0000-0x0fff */
+	*strength = tmp * 0xffff / 0x0fff;
+
+	return 0;
+err:
+	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	return ret;
+}
+
+static int hd29l2_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+	int ret;
+	struct hd29l2_priv *priv = fe->demodulator_priv;
+	u8 buf[2];
+
+	if (!(priv->fe_status & FE_HAS_SYNC)) {
+		*ber = 0;
+		ret = 0;
+		goto err;
+	}
+
+	ret = hd29l2_rd_regs(priv, 0xd9, buf, 2);
+	if (ret) {
+		*ber = 0;
+		goto err;
+	}
+
+	/* LDPC BER */
+	*ber = ((buf[0] & 0x0f) << 8) | buf[1];
+
+	return 0;
+err:
+	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	return ret;
+}
+
+static int hd29l2_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+	/* no way to read? */
+	*ucblocks = 0;
+	return 0;
+}
+
+static enum dvbfe_search hd29l2_search(struct dvb_frontend *fe)
+{
+	int ret, i;
+	struct hd29l2_priv *priv = fe->demodulator_priv;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	u8 tmp, buf[3];
+	u8 modulation, carrier, guard_interval, interleave, code_rate;
+	u64 num64;
+	u32 if_freq, if_ctl;
+	bool auto_mode;
+
+	dev_dbg(&priv->i2c->dev, "%s: delivery_system=%d frequency=%d " \
+			"bandwidth_hz=%d modulation=%d inversion=%d " \
+			"fec_inner=%d guard_interval=%d\n", __func__,
+			c->delivery_system, c->frequency, c->bandwidth_hz,
+			c->modulation, c->inversion, c->fec_inner,
+			c->guard_interval);
+
+	/* as for now we detect always params automatically */
+	auto_mode = true;
+
+	/* program tuner */
+	if (fe->ops.tuner_ops.set_params)
+		fe->ops.tuner_ops.set_params(fe);
+
+	/* get and program IF */
+	if (fe->ops.tuner_ops.get_if_frequency)
+		fe->ops.tuner_ops.get_if_frequency(fe, &if_freq);
+	else
+		if_freq = 0;
+
+	if (if_freq) {
+		/* normal IF */
+
+		/* calc IF control value */
+		num64 = if_freq;
+		num64 *= 0x800000;
+		num64 = div_u64(num64, HD29L2_XTAL);
+		num64 -= 0x800000;
+		if_ctl = num64;
+
+		tmp = 0xfc; /* tuner type normal */
+	} else {
+		/* zero IF */
+		if_ctl = 0;
+		tmp = 0xfe; /* tuner type Zero-IF */
+	}
+
+	buf[0] = ((if_ctl >>  0) & 0xff);
+	buf[1] = ((if_ctl >>  8) & 0xff);
+	buf[2] = ((if_ctl >> 16) & 0xff);
+
+	/* program IF control */
+	ret = hd29l2_wr_regs(priv, 0x14, buf, 3);
+	if (ret)
+		goto err;
+
+	/* program tuner type */
+	ret = hd29l2_wr_reg(priv, 0xab, tmp);
+	if (ret)
+		goto err;
+
+	dev_dbg(&priv->i2c->dev, "%s: if_freq=%d if_ctl=%x\n",
+			__func__, if_freq, if_ctl);
+
+	if (auto_mode) {
+		/*
+		 * use auto mode
+		 */
+
+		/* disable quick mode */
+		ret = hd29l2_wr_reg_mask(priv, 0xac, 0 << 7, 0x80);
+		if (ret)
+			goto err;
+
+		ret = hd29l2_wr_reg_mask(priv, 0x82, 1 << 1, 0x02);
+		if (ret)
+			goto err;
+
+		/* enable auto mode */
+		ret = hd29l2_wr_reg_mask(priv, 0x7d, 1 << 6, 0x40);
+		if (ret)
+			goto err;
+
+		ret = hd29l2_wr_reg_mask(priv, 0x81, 1 << 3, 0x08);
+		if (ret)
+			goto err;
+
+		/* soft reset */
+		ret = hd29l2_soft_reset(priv);
+		if (ret)
+			goto err;
+
+		/* detect modulation */
+		for (i = 30; i; i--) {
+			msleep(100);
+
+			ret = hd29l2_rd_reg(priv, 0x0d, &tmp);
+			if (ret)
+				goto err;
+
+			if ((((tmp & 0xf0) >= 0x10) &&
+				((tmp & 0x0f) == 0x08)) || (tmp >= 0x2c))
+				break;
+		}
+
+		dev_dbg(&priv->i2c->dev, "%s: loop=%d\n", __func__, i);
+
+		if (i == 0)
+			/* detection failed */
+			return DVBFE_ALGO_SEARCH_FAILED;
+
+		/* read modulation */
+		ret = hd29l2_rd_reg_mask(priv, 0x7d, &modulation, 0x07);
+		if (ret)
+			goto err;
+	} else {
+		/*
+		 * use manual mode
+		 */
+
+		modulation = HD29L2_QAM64;
+		carrier = HD29L2_CARRIER_MULTI;
+		guard_interval = HD29L2_PN945;
+		interleave = HD29L2_INTERLEAVER_420;
+		code_rate = HD29L2_CODE_RATE_08;
+
+		tmp = (code_rate << 3) | modulation;
+		ret = hd29l2_wr_reg_mask(priv, 0x7d, tmp, 0x5f);
+		if (ret)
+			goto err;
+
+		tmp = (carrier << 2) | guard_interval;
+		ret = hd29l2_wr_reg_mask(priv, 0x81, tmp, 0x0f);
+		if (ret)
+			goto err;
+
+		tmp = interleave;
+		ret = hd29l2_wr_reg_mask(priv, 0x82, tmp, 0x03);
+		if (ret)
+			goto err;
+	}
+
+	/* ensure modulation validy */
+	/* 0=QAM4_NR, 1=QAM4, 2=QAM16, 3=QAM32, 4=QAM64 */
+	if (modulation > (ARRAY_SIZE(reg_mod_vals_tab[0].val) - 1)) {
+		dev_dbg(&priv->i2c->dev, "%s: modulation=%d not valid\n",
+				__func__, modulation);
+		goto err;
+	}
+
+	/* program registers according to modulation */
+	for (i = 0; i < ARRAY_SIZE(reg_mod_vals_tab); i++) {
+		ret = hd29l2_wr_reg(priv, reg_mod_vals_tab[i].reg,
+			reg_mod_vals_tab[i].val[modulation]);
+		if (ret)
+			goto err;
+	}
+
+	/* read guard interval */
+	ret = hd29l2_rd_reg_mask(priv, 0x81, &guard_interval, 0x03);
+	if (ret)
+		goto err;
+
+	/* read carrier mode */
+	ret = hd29l2_rd_reg_mask(priv, 0x81, &carrier, 0x04);
+	if (ret)
+		goto err;
+
+	dev_dbg(&priv->i2c->dev,
+			"%s: modulation=%d guard_interval=%d carrier=%d\n",
+			__func__, modulation, guard_interval, carrier);
+
+	if ((carrier == HD29L2_CARRIER_MULTI) && (modulation == HD29L2_QAM64) &&
+		(guard_interval == HD29L2_PN945)) {
+		dev_dbg(&priv->i2c->dev, "%s: C=3780 && QAM64 && PN945\n",
+				__func__);
+
+		ret = hd29l2_wr_reg(priv, 0x42, 0x33);
+		if (ret)
+			goto err;
+
+		ret = hd29l2_wr_reg(priv, 0xdd, 0x01);
+		if (ret)
+			goto err;
+	}
+
+	usleep_range(10000, 20000);
+
+	/* soft reset */
+	ret = hd29l2_soft_reset(priv);
+	if (ret)
+		goto err;
+
+	/* wait demod lock */
+	for (i = 30; i; i--) {
+		msleep(100);
+
+		/* read lock bit */
+		ret = hd29l2_rd_reg_mask(priv, 0x05, &tmp, 0x01);
+		if (ret)
+			goto err;
+
+		if (tmp)
+			break;
+	}
+
+	dev_dbg(&priv->i2c->dev, "%s: loop=%d\n", __func__, i);
+
+	if (i == 0)
+		return DVBFE_ALGO_SEARCH_AGAIN;
+
+	return DVBFE_ALGO_SEARCH_SUCCESS;
+err:
+	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	return DVBFE_ALGO_SEARCH_ERROR;
+}
+
+static int hd29l2_get_frontend_algo(struct dvb_frontend *fe)
+{
+	return DVBFE_ALGO_CUSTOM;
+}
+
+static int hd29l2_get_frontend(struct dvb_frontend *fe)
+{
+	int ret;
+	struct hd29l2_priv *priv = fe->demodulator_priv;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	u8 buf[3];
+	u32 if_ctl;
+	char *str_constellation, *str_code_rate, *str_constellation_code_rate,
+		*str_guard_interval, *str_carrier, *str_guard_interval_carrier,
+		*str_interleave, *str_interleave_;
+
+	ret = hd29l2_rd_reg(priv, 0x7d, &buf[0]);
+	if (ret)
+		goto err;
+
+	ret = hd29l2_rd_regs(priv, 0x81, &buf[1], 2);
+	if (ret)
+		goto err;
+
+	/* constellation, 0x7d[2:0] */
+	switch ((buf[0] >> 0) & 0x07) {
+	case 0: /* QAM4NR */
+		str_constellation = "QAM4NR";
+		c->modulation = QAM_AUTO; /* FIXME */
+		break;
+	case 1: /* QAM4 */
+		str_constellation = "QAM4";
+		c->modulation = QPSK; /* FIXME */
+		break;
+	case 2:
+		str_constellation = "QAM16";
+		c->modulation = QAM_16;
+		break;
+	case 3:
+		str_constellation = "QAM32";
+		c->modulation = QAM_32;
+		break;
+	case 4:
+		str_constellation = "QAM64";
+		c->modulation = QAM_64;
+		break;
+	default:
+		str_constellation = "?";
+	}
+
+	/* LDPC code rate, 0x7d[4:3] */
+	switch ((buf[0] >> 3) & 0x03) {
+	case 0: /* 0.4 */
+		str_code_rate = "0.4";
+		c->fec_inner = FEC_AUTO; /* FIXME */
+		break;
+	case 1: /* 0.6 */
+		str_code_rate = "0.6";
+		c->fec_inner = FEC_3_5;
+		break;
+	case 2: /* 0.8 */
+		str_code_rate = "0.8";
+		c->fec_inner = FEC_4_5;
+		break;
+	default:
+		str_code_rate = "?";
+	}
+
+	/* constellation & code rate set, 0x7d[6] */
+	switch ((buf[0] >> 6) & 0x01) {
+	case 0:
+		str_constellation_code_rate = "manual";
+		break;
+	case 1:
+		str_constellation_code_rate = "auto";
+		break;
+	default:
+		str_constellation_code_rate = "?";
+	}
+
+	/* frame header, 0x81[1:0] */
+	switch ((buf[1] >> 0) & 0x03) {
+	case 0: /* PN945 */
+		str_guard_interval = "PN945";
+		c->guard_interval = GUARD_INTERVAL_AUTO; /* FIXME */
+		break;
+	case 1: /* PN595 */
+		str_guard_interval = "PN595";
+		c->guard_interval = GUARD_INTERVAL_AUTO; /* FIXME */
+		break;
+	case 2: /* PN420 */
+		str_guard_interval = "PN420";
+		c->guard_interval = GUARD_INTERVAL_AUTO; /* FIXME */
+		break;
+	default:
+		str_guard_interval = "?";
+	}
+
+	/* carrier, 0x81[2] */
+	switch ((buf[1] >> 2) & 0x01) {
+	case 0:
+		str_carrier = "C=1";
+		break;
+	case 1:
+		str_carrier = "C=3780";
+		break;
+	default:
+		str_carrier = "?";
+	}
+
+	/* frame header & carrier set, 0x81[3] */
+	switch ((buf[1] >> 3) & 0x01) {
+	case 0:
+		str_guard_interval_carrier = "manual";
+		break;
+	case 1:
+		str_guard_interval_carrier = "auto";
+		break;
+	default:
+		str_guard_interval_carrier = "?";
+	}
+
+	/* interleave, 0x82[0] */
+	switch ((buf[2] >> 0) & 0x01) {
+	case 0:
+		str_interleave = "M=720";
+		break;
+	case 1:
+		str_interleave = "M=240";
+		break;
+	default:
+		str_interleave = "?";
+	}
+
+	/* interleave set, 0x82[1] */
+	switch ((buf[2] >> 1) & 0x01) {
+	case 0:
+		str_interleave_ = "manual";
+		break;
+	case 1:
+		str_interleave_ = "auto";
+		break;
+	default:
+		str_interleave_ = "?";
+	}
+
+	/*
+	 * We can read out current detected NCO and use that value next
+	 * time instead of calculating new value from targed IF.
+	 * I think it will not effect receiver sensitivity but gaining lock
+	 * after tune could be easier...
+	 */
+	ret = hd29l2_rd_regs(priv, 0xb1, &buf[0], 3);
+	if (ret)
+		goto err;
+
+	if_ctl = (buf[0] << 16) | ((buf[1] - 7) << 8) | buf[2];
+
+	dev_dbg(&priv->i2c->dev, "%s: %s %s %s | %s %s %s | %s %s | NCO=%06x\n",
+			__func__, str_constellation, str_code_rate,
+			str_constellation_code_rate, str_guard_interval,
+			str_carrier, str_guard_interval_carrier, str_interleave,
+			str_interleave_, if_ctl);
+	return 0;
+err:
+	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	return ret;
+}
+
+static int hd29l2_init(struct dvb_frontend *fe)
+{
+	int ret, i;
+	struct hd29l2_priv *priv = fe->demodulator_priv;
+	u8 tmp;
+	static const struct reg_val tab[] = {
+		{ 0x3a, 0x06 },
+		{ 0x3b, 0x03 },
+		{ 0x3c, 0x04 },
+		{ 0xaf, 0x06 },
+		{ 0xb0, 0x1b },
+		{ 0x80, 0x64 },
+		{ 0x10, 0x38 },
+	};
+
+	dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
+
+	/* reset demod */
+	/* it is recommended to HW reset chip using RST_N pin */
+	if (fe->callback) {
+		ret = fe->callback(fe, DVB_FRONTEND_COMPONENT_DEMOD, 0, 0);
+		if (ret)
+			goto err;
+
+		/* reprogramming needed because HW reset clears registers */
+		priv->tuner_i2c_addr_programmed = false;
+	}
+
+	/* init */
+	for (i = 0; i < ARRAY_SIZE(tab); i++) {
+		ret = hd29l2_wr_reg(priv, tab[i].reg, tab[i].val);
+		if (ret)
+			goto err;
+	}
+
+	/* TS params */
+	ret = hd29l2_rd_reg(priv, 0x36, &tmp);
+	if (ret)
+		goto err;
+
+	tmp &= 0x1b;
+	tmp |= priv->cfg.ts_mode;
+	ret = hd29l2_wr_reg(priv, 0x36, tmp);
+	if (ret)
+		goto err;
+
+	ret = hd29l2_rd_reg(priv, 0x31, &tmp);
+	tmp &= 0xef;
+
+	if (!(priv->cfg.ts_mode >> 7))
+		/* set b4 for serial TS */
+		tmp |= 0x10;
+
+	ret = hd29l2_wr_reg(priv, 0x31, tmp);
+	if (ret)
+		goto err;
+
+	return ret;
+err:
+	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	return ret;
+}
+
+static void hd29l2_release(struct dvb_frontend *fe)
+{
+	struct hd29l2_priv *priv = fe->demodulator_priv;
+	kfree(priv);
+}
+
+static struct dvb_frontend_ops hd29l2_ops;
+
+struct dvb_frontend *hd29l2_attach(const struct hd29l2_config *config,
+	struct i2c_adapter *i2c)
+{
+	int ret;
+	struct hd29l2_priv *priv = NULL;
+	u8 tmp;
+
+	/* allocate memory for the internal state */
+	priv = kzalloc(sizeof(struct hd29l2_priv), GFP_KERNEL);
+	if (priv == NULL)
+		goto err;
+
+	/* setup the state */
+	priv->i2c = i2c;
+	memcpy(&priv->cfg, config, sizeof(struct hd29l2_config));
+
+
+	/* check if the demod is there */
+	ret = hd29l2_rd_reg(priv, 0x00, &tmp);
+	if (ret)
+		goto err;
+
+	/* create dvb_frontend */
+	memcpy(&priv->fe.ops, &hd29l2_ops, sizeof(struct dvb_frontend_ops));
+	priv->fe.demodulator_priv = priv;
+
+	return &priv->fe;
+err:
+	kfree(priv);
+	return NULL;
+}
+EXPORT_SYMBOL(hd29l2_attach);
+
+static struct dvb_frontend_ops hd29l2_ops = {
+	.delsys = { SYS_DVBT },
+	.info = {
+		.name = "HDIC HD29L2 DMB-TH",
+		.frequency_min = 474000000,
+		.frequency_max = 858000000,
+		.frequency_stepsize = 10000,
+		.caps = FE_CAN_FEC_AUTO |
+			FE_CAN_QPSK |
+			FE_CAN_QAM_16 |
+			FE_CAN_QAM_32 |
+			FE_CAN_QAM_64 |
+			FE_CAN_QAM_AUTO |
+			FE_CAN_TRANSMISSION_MODE_AUTO |
+			FE_CAN_BANDWIDTH_AUTO |
+			FE_CAN_GUARD_INTERVAL_AUTO |
+			FE_CAN_HIERARCHY_AUTO |
+			FE_CAN_RECOVER
+	},
+
+	.release = hd29l2_release,
+
+	.init = hd29l2_init,
+
+	.get_frontend_algo = hd29l2_get_frontend_algo,
+	.search = hd29l2_search,
+	.get_frontend = hd29l2_get_frontend,
+
+	.read_status = hd29l2_read_status,
+	.read_snr = hd29l2_read_snr,
+	.read_signal_strength = hd29l2_read_signal_strength,
+	.read_ber = hd29l2_read_ber,
+	.read_ucblocks = hd29l2_read_ucblocks,
+
+	.i2c_gate_ctrl = hd29l2_i2c_gate_ctrl,
+};
+
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
+MODULE_DESCRIPTION("HDIC HD29L2 DMB-TH demodulator driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb-frontends/hd29l2.h b/drivers/media/dvb-frontends/hd29l2.h
new file mode 100644
index 0000000..4ad00d7
--- /dev/null
+++ b/drivers/media/dvb-frontends/hd29l2.h
@@ -0,0 +1,66 @@
+/*
+ * HDIC HD29L2 DMB-TH demodulator driver
+ *
+ * Copyright (C) 2011 Metropolia University of Applied Sciences, Electria R&D
+ *
+ * Author: 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 HD29L2_H
+#define HD29L2_H
+
+#include <linux/dvb/frontend.h>
+
+struct hd29l2_config {
+	/*
+	 * demodulator I2C address
+	 */
+	u8 i2c_addr;
+
+	/*
+	 * tuner I2C address
+	 * only needed when tuner is behind demod I2C-gate
+	 */
+	u8 tuner_i2c_addr;
+
+	/*
+	 * TS settings
+	 */
+#define HD29L2_TS_SERIAL            0x00
+#define HD29L2_TS_PARALLEL          0x80
+#define HD29L2_TS_CLK_NORMAL        0x40
+#define HD29L2_TS_CLK_INVERTED      0x00
+#define HD29L2_TS_CLK_GATED         0x20
+#define HD29L2_TS_CLK_FREE          0x00
+	u8 ts_mode;
+};
+
+
+#if defined(CONFIG_DVB_HD29L2) || \
+	(defined(CONFIG_DVB_HD29L2_MODULE) && defined(MODULE))
+extern struct dvb_frontend *hd29l2_attach(const struct hd29l2_config *config,
+	struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend *hd29l2_attach(
+const struct hd29l2_config *config, struct i2c_adapter *i2c)
+{
+	pr_warn("%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif
+
+#endif /* HD29L2_H */
diff --git a/drivers/media/dvb-frontends/hd29l2_priv.h b/drivers/media/dvb-frontends/hd29l2_priv.h
new file mode 100644
index 0000000..4d571a2
--- /dev/null
+++ b/drivers/media/dvb-frontends/hd29l2_priv.h
@@ -0,0 +1,301 @@
+/*
+ * HDIC HD29L2 DMB-TH demodulator driver
+ *
+ * Copyright (C) 2011 Metropolia University of Applied Sciences, Electria R&D
+ *
+ * Author: 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 HD29L2_PRIV
+#define HD29L2_PRIV
+
+#include <linux/dvb/version.h>
+#include "dvb_frontend.h"
+#include "dvb_math.h"
+#include "hd29l2.h"
+
+#define HD29L2_XTAL 30400000 /* Hz */
+
+
+#define HD29L2_QAM4NR 0x00
+#define HD29L2_QAM4   0x01
+#define HD29L2_QAM16  0x02
+#define HD29L2_QAM32  0x03
+#define HD29L2_QAM64  0x04
+
+#define HD29L2_CODE_RATE_04 0x00
+#define HD29L2_CODE_RATE_06 0x08
+#define HD29L2_CODE_RATE_08 0x10
+
+#define HD29L2_PN945 0x00
+#define HD29L2_PN595 0x01
+#define HD29L2_PN420 0x02
+
+#define HD29L2_CARRIER_SINGLE 0x00
+#define HD29L2_CARRIER_MULTI  0x01
+
+#define HD29L2_INTERLEAVER_720 0x00
+#define HD29L2_INTERLEAVER_420 0x01
+
+struct reg_val {
+	u8 reg;
+	u8 val;
+};
+
+struct reg_mod_vals {
+	u8 reg;
+	u8 val[5];
+};
+
+struct hd29l2_priv {
+	struct i2c_adapter *i2c;
+	struct dvb_frontend fe;
+	struct hd29l2_config cfg;
+	u8 tuner_i2c_addr_programmed:1;
+
+	fe_status_t fe_status;
+};
+
+static const struct reg_mod_vals reg_mod_vals_tab[] = {
+	/* REG, QAM4NR, QAM4,QAM16,QAM32,QAM64 */
+	{ 0x01, { 0x10, 0x10, 0x10, 0x10, 0x10 } },
+	{ 0x02, { 0x07, 0x07, 0x07, 0x07, 0x07 } },
+	{ 0x03, { 0x10, 0x10, 0x10, 0x10, 0x10 } },
+	{ 0x04, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+	{ 0x05, { 0x61, 0x60, 0x60, 0x61, 0x60 } },
+	{ 0x06, { 0xff, 0xff, 0xff, 0xff, 0xff } },
+	{ 0x07, { 0xff, 0xff, 0xff, 0xff, 0xff } },
+	{ 0x08, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+	{ 0x09, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+	{ 0x0a, { 0x15, 0x15, 0x03, 0x03, 0x03 } },
+	{ 0x0d, { 0x78, 0x78, 0x88, 0x78, 0x78 } },
+	{ 0x0e, { 0xa0, 0x90, 0xa0, 0xa0, 0xa0 } },
+	{ 0x0f, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+	{ 0x10, { 0xa0, 0xa0, 0x58, 0x38, 0x38 } },
+	{ 0x11, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+	{ 0x12, { 0x5a, 0x5a, 0x5a, 0x5a, 0x5a } },
+	{ 0x13, { 0xa2, 0xa2, 0xa2, 0xa2, 0xa2 } },
+	{ 0x17, { 0x40, 0x40, 0x40, 0x40, 0x40 } },
+	{ 0x18, { 0x21, 0x21, 0x42, 0x52, 0x42 } },
+	{ 0x19, { 0x21, 0x21, 0x62, 0x72, 0x62 } },
+	{ 0x1a, { 0x32, 0x43, 0xa9, 0xb9, 0xa9 } },
+	{ 0x1b, { 0x32, 0x43, 0xb9, 0xd8, 0xb9 } },
+	{ 0x1c, { 0x02, 0x02, 0x03, 0x02, 0x03 } },
+	{ 0x1d, { 0x0c, 0x0c, 0x01, 0x02, 0x02 } },
+	{ 0x1e, { 0x02, 0x02, 0x02, 0x01, 0x02 } },
+	{ 0x1f, { 0x02, 0x02, 0x01, 0x02, 0x04 } },
+	{ 0x20, { 0x01, 0x02, 0x01, 0x01, 0x01 } },
+	{ 0x21, { 0x08, 0x08, 0x0a, 0x0a, 0x0a } },
+	{ 0x22, { 0x06, 0x06, 0x04, 0x05, 0x05 } },
+	{ 0x23, { 0x06, 0x06, 0x05, 0x03, 0x05 } },
+	{ 0x24, { 0x08, 0x08, 0x05, 0x07, 0x07 } },
+	{ 0x25, { 0x16, 0x10, 0x10, 0x0a, 0x10 } },
+	{ 0x26, { 0x14, 0x14, 0x04, 0x04, 0x04 } },
+	{ 0x27, { 0x58, 0x58, 0x58, 0x5c, 0x58 } },
+	{ 0x28, { 0x0a, 0x0a, 0x0a, 0x0a, 0x0a } },
+	{ 0x29, { 0x0a, 0x0a, 0x0a, 0x0a, 0x0a } },
+	{ 0x2a, { 0x08, 0x0a, 0x08, 0x08, 0x08 } },
+	{ 0x2b, { 0x08, 0x08, 0x08, 0x08, 0x08 } },
+	{ 0x2c, { 0x06, 0x06, 0x06, 0x06, 0x06 } },
+	{ 0x2d, { 0x05, 0x06, 0x06, 0x06, 0x06 } },
+	{ 0x2e, { 0x21, 0x21, 0x21, 0x21, 0x21 } },
+	{ 0x2f, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+	{ 0x30, { 0x14, 0x14, 0x14, 0x14, 0x14 } },
+	{ 0x33, { 0xb7, 0xb7, 0xb7, 0xb7, 0xb7 } },
+	{ 0x34, { 0x81, 0x81, 0x81, 0x81, 0x81 } },
+	{ 0x35, { 0x80, 0x80, 0x80, 0x80, 0x80 } },
+	{ 0x37, { 0x70, 0x70, 0x70, 0x70, 0x70 } },
+	{ 0x38, { 0x04, 0x04, 0x02, 0x02, 0x02 } },
+	{ 0x39, { 0x07, 0x07, 0x05, 0x05, 0x05 } },
+	{ 0x3a, { 0x06, 0x06, 0x06, 0x06, 0x06 } },
+	{ 0x3b, { 0x03, 0x03, 0x03, 0x03, 0x03 } },
+	{ 0x3c, { 0x07, 0x06, 0x04, 0x04, 0x04 } },
+	{ 0x3d, { 0xf0, 0xf0, 0xf0, 0xf0, 0x80 } },
+	{ 0x3e, { 0x60, 0x60, 0x60, 0x60, 0xff } },
+	{ 0x3f, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+	{ 0x40, { 0x5b, 0x5b, 0x5b, 0x57, 0x50 } },
+	{ 0x41, { 0x30, 0x30, 0x30, 0x30, 0x18 } },
+	{ 0x42, { 0x20, 0x20, 0x20, 0x00, 0x30 } },
+	{ 0x43, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+	{ 0x44, { 0x3f, 0x3f, 0x3f, 0x3f, 0x3f } },
+	{ 0x45, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+	{ 0x46, { 0x0a, 0x0a, 0x0a, 0x0a, 0x0a } },
+	{ 0x47, { 0x00, 0x00, 0x95, 0x00, 0x95 } },
+	{ 0x48, { 0xc0, 0xc0, 0xc0, 0xc0, 0xc0 } },
+	{ 0x49, { 0xc0, 0xc0, 0xc0, 0xc0, 0xc0 } },
+	{ 0x4a, { 0x40, 0x40, 0x33, 0x11, 0x11 } },
+	{ 0x4b, { 0x40, 0x40, 0x00, 0x00, 0x00 } },
+	{ 0x4c, { 0x40, 0x40, 0x99, 0x11, 0x11 } },
+	{ 0x4d, { 0x40, 0x40, 0x00, 0x00, 0x00 } },
+	{ 0x4e, { 0x40, 0x40, 0x66, 0x77, 0x77 } },
+	{ 0x4f, { 0x40, 0x40, 0x00, 0x00, 0x00 } },
+	{ 0x50, { 0x40, 0x40, 0x88, 0x33, 0x11 } },
+	{ 0x51, { 0x40, 0x40, 0x00, 0x00, 0x00 } },
+	{ 0x52, { 0x40, 0x40, 0x88, 0x02, 0x02 } },
+	{ 0x53, { 0x40, 0x40, 0x00, 0x02, 0x02 } },
+	{ 0x54, { 0x00, 0x00, 0x88, 0x33, 0x33 } },
+	{ 0x55, { 0x40, 0x40, 0x00, 0x00, 0x00 } },
+	{ 0x56, { 0x00, 0x00, 0x00, 0x0b, 0x00 } },
+	{ 0x57, { 0x40, 0x40, 0x0a, 0x0b, 0x0a } },
+	{ 0x58, { 0xaa, 0x00, 0x00, 0x00, 0x00 } },
+	{ 0x59, { 0x7a, 0x40, 0x02, 0x02, 0x02 } },
+	{ 0x5a, { 0x18, 0x18, 0x01, 0x01, 0x01 } },
+	{ 0x5b, { 0x18, 0x18, 0x01, 0x01, 0x01 } },
+	{ 0x5c, { 0x18, 0x18, 0x01, 0x01, 0x01 } },
+	{ 0x5d, { 0x18, 0x18, 0x01, 0x01, 0x01 } },
+	{ 0x5e, { 0xc0, 0xc0, 0xc0, 0xff, 0xc0 } },
+	{ 0x5f, { 0xc0, 0xc0, 0xc0, 0xff, 0xc0 } },
+	{ 0x60, { 0x40, 0x40, 0x00, 0x30, 0x30 } },
+	{ 0x61, { 0x40, 0x40, 0x10, 0x30, 0x30 } },
+	{ 0x62, { 0x40, 0x40, 0x00, 0x30, 0x30 } },
+	{ 0x63, { 0x40, 0x40, 0x05, 0x30, 0x30 } },
+	{ 0x64, { 0x40, 0x40, 0x06, 0x00, 0x30 } },
+	{ 0x65, { 0x40, 0x40, 0x06, 0x08, 0x30 } },
+	{ 0x66, { 0x40, 0x40, 0x00, 0x00, 0x20 } },
+	{ 0x67, { 0x40, 0x40, 0x01, 0x04, 0x20 } },
+	{ 0x68, { 0x00, 0x00, 0x30, 0x00, 0x20 } },
+	{ 0x69, { 0xa0, 0xa0, 0x00, 0x08, 0x20 } },
+	{ 0x6a, { 0x00, 0x00, 0x30, 0x00, 0x25 } },
+	{ 0x6b, { 0xa0, 0xa0, 0x00, 0x06, 0x25 } },
+	{ 0x6c, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+	{ 0x6d, { 0xa0, 0x60, 0x0c, 0x03, 0x0c } },
+	{ 0x6e, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+	{ 0x6f, { 0xa0, 0x60, 0x04, 0x01, 0x04 } },
+	{ 0x70, { 0x58, 0x58, 0xaa, 0xaa, 0xaa } },
+	{ 0x71, { 0x58, 0x58, 0xaa, 0xaa, 0xaa } },
+	{ 0x72, { 0x58, 0x58, 0xff, 0xff, 0xff } },
+	{ 0x73, { 0x58, 0x58, 0xff, 0xff, 0xff } },
+	{ 0x74, { 0x06, 0x06, 0x09, 0x05, 0x05 } },
+	{ 0x75, { 0x06, 0x06, 0x0a, 0x10, 0x10 } },
+	{ 0x76, { 0x10, 0x10, 0x06, 0x0a, 0x0a } },
+	{ 0x77, { 0x12, 0x18, 0x28, 0x10, 0x28 } },
+	{ 0x78, { 0xf8, 0xf8, 0xf8, 0xf8, 0xf8 } },
+	{ 0x79, { 0x15, 0x15, 0x03, 0x03, 0x03 } },
+	{ 0x7a, { 0x02, 0x02, 0x01, 0x04, 0x03 } },
+	{ 0x7b, { 0x01, 0x02, 0x03, 0x03, 0x03 } },
+	{ 0x7c, { 0x28, 0x28, 0x28, 0x28, 0x28 } },
+	{ 0x7f, { 0x25, 0x92, 0x5f, 0x17, 0x2d } },
+	{ 0x80, { 0x64, 0x64, 0x64, 0x74, 0x64 } },
+	{ 0x83, { 0x06, 0x03, 0x04, 0x04, 0x04 } },
+	{ 0x84, { 0xff, 0xff, 0xff, 0xff, 0xff } },
+	{ 0x85, { 0x05, 0x05, 0x05, 0x05, 0x05 } },
+	{ 0x86, { 0x00, 0x00, 0x11, 0x11, 0x11 } },
+	{ 0x87, { 0x03, 0x03, 0x03, 0x03, 0x03 } },
+	{ 0x88, { 0x09, 0x09, 0x09, 0x09, 0x09 } },
+	{ 0x89, { 0x20, 0x20, 0x30, 0x20, 0x20 } },
+	{ 0x8a, { 0x03, 0x03, 0x02, 0x03, 0x02 } },
+	{ 0x8b, { 0x00, 0x07, 0x09, 0x00, 0x09 } },
+	{ 0x8c, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+	{ 0x8d, { 0x4f, 0x4f, 0x4f, 0x3f, 0x4f } },
+	{ 0x8e, { 0xf0, 0xf0, 0x60, 0xf0, 0xa0 } },
+	{ 0x8f, { 0xe8, 0xe8, 0xe8, 0xe8, 0xe8 } },
+	{ 0x90, { 0x10, 0x10, 0x10, 0x10, 0x10 } },
+	{ 0x91, { 0x40, 0x40, 0x70, 0x70, 0x10 } },
+	{ 0x92, { 0x00, 0x00, 0x00, 0x00, 0x04 } },
+	{ 0x93, { 0x60, 0x60, 0x60, 0x60, 0x60 } },
+	{ 0x94, { 0x00, 0x00, 0x00, 0x00, 0x03 } },
+	{ 0x95, { 0x09, 0x09, 0x47, 0x47, 0x47 } },
+	{ 0x96, { 0x80, 0xa0, 0xa0, 0x40, 0xa0 } },
+	{ 0x97, { 0x60, 0x60, 0x60, 0x60, 0x60 } },
+	{ 0x98, { 0x50, 0x50, 0x50, 0x30, 0x50 } },
+	{ 0x99, { 0x10, 0x10, 0x10, 0x10, 0x10 } },
+	{ 0x9a, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+	{ 0x9b, { 0x40, 0x40, 0x40, 0x30, 0x40 } },
+	{ 0x9c, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+	{ 0xa0, { 0xf0, 0xf0, 0xf0, 0xf0, 0xf0 } },
+	{ 0xa1, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+	{ 0xa2, { 0x30, 0x30, 0x00, 0x30, 0x00 } },
+	{ 0xa3, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+	{ 0xa4, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+	{ 0xa5, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+	{ 0xa6, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+	{ 0xa7, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+	{ 0xa8, { 0x77, 0x77, 0x77, 0x77, 0x77 } },
+	{ 0xa9, { 0x02, 0x02, 0x02, 0x02, 0x02 } },
+	{ 0xaa, { 0x40, 0x40, 0x40, 0x40, 0x40 } },
+	{ 0xac, { 0x1f, 0x1f, 0x1f, 0x1f, 0x1f } },
+	{ 0xad, { 0x14, 0x14, 0x14, 0x14, 0x14 } },
+	{ 0xae, { 0x78, 0x78, 0x78, 0x78, 0x78 } },
+	{ 0xaf, { 0x06, 0x06, 0x06, 0x06, 0x07 } },
+	{ 0xb0, { 0x1b, 0x1b, 0x1b, 0x19, 0x1b } },
+	{ 0xb1, { 0x18, 0x17, 0x17, 0x18, 0x17 } },
+	{ 0xb2, { 0x35, 0x82, 0x82, 0x38, 0x82 } },
+	{ 0xb3, { 0xb6, 0xce, 0xc7, 0x5c, 0xb0 } },
+	{ 0xb4, { 0x3f, 0x3e, 0x3e, 0x3f, 0x3e } },
+	{ 0xb5, { 0x70, 0x58, 0x50, 0x68, 0x50 } },
+	{ 0xb6, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+	{ 0xb7, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+	{ 0xb8, { 0x03, 0x03, 0x01, 0x01, 0x01 } },
+	{ 0xb9, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+	{ 0xba, { 0x06, 0x06, 0x0a, 0x05, 0x0a } },
+	{ 0xbb, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+	{ 0xbc, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+	{ 0xbd, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+	{ 0xbe, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+	{ 0xbf, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+	{ 0xc0, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+	{ 0xc1, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+	{ 0xc2, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+	{ 0xc3, { 0x00, 0x00, 0x88, 0x66, 0x88 } },
+	{ 0xc4, { 0x10, 0x10, 0x00, 0x00, 0x00 } },
+	{ 0xc5, { 0x00, 0x00, 0x44, 0x60, 0x44 } },
+	{ 0xc6, { 0x10, 0x0a, 0x00, 0x00, 0x00 } },
+	{ 0xc7, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+	{ 0xc8, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+	{ 0xc9, { 0x90, 0x04, 0x00, 0x00, 0x00 } },
+	{ 0xca, { 0x90, 0x08, 0x01, 0x01, 0x01 } },
+	{ 0xcb, { 0xa0, 0x04, 0x00, 0x44, 0x00 } },
+	{ 0xcc, { 0xa0, 0x10, 0x03, 0x00, 0x03 } },
+	{ 0xcd, { 0x06, 0x06, 0x06, 0x05, 0x06 } },
+	{ 0xce, { 0x05, 0x05, 0x01, 0x01, 0x01 } },
+	{ 0xcf, { 0x40, 0x20, 0x18, 0x18, 0x18 } },
+	{ 0xd0, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+	{ 0xd1, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+	{ 0xd2, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+	{ 0xd3, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+	{ 0xd4, { 0x05, 0x05, 0x05, 0x05, 0x05 } },
+	{ 0xd5, { 0x05, 0x05, 0x05, 0x03, 0x05 } },
+	{ 0xd6, { 0xac, 0x22, 0xca, 0x8f, 0xca } },
+	{ 0xd7, { 0x20, 0x20, 0x20, 0x20, 0x20 } },
+	{ 0xd8, { 0x01, 0x01, 0x01, 0x01, 0x01 } },
+	{ 0xd9, { 0x00, 0x00, 0x0f, 0x00, 0x0f } },
+	{ 0xda, { 0x00, 0xff, 0xff, 0x0e, 0xff } },
+	{ 0xdb, { 0x0a, 0x0a, 0x0a, 0x0a, 0x0a } },
+	{ 0xdc, { 0x0a, 0x0a, 0x0a, 0x0a, 0x0a } },
+	{ 0xdd, { 0x05, 0x05, 0x05, 0x05, 0x05 } },
+	{ 0xde, { 0x0a, 0x0a, 0x0a, 0x0a, 0x0a } },
+	{ 0xdf, { 0x42, 0x42, 0x44, 0x44, 0x04 } },
+	{ 0xe0, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+	{ 0xe1, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+	{ 0xe2, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+	{ 0xe3, { 0x00, 0x00, 0x26, 0x06, 0x26 } },
+	{ 0xe4, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+	{ 0xe5, { 0x01, 0x0a, 0x01, 0x01, 0x01 } },
+	{ 0xe6, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+	{ 0xe7, { 0x08, 0x08, 0x08, 0x08, 0x08 } },
+	{ 0xe8, { 0x63, 0x63, 0x63, 0x63, 0x63 } },
+	{ 0xe9, { 0x59, 0x59, 0x59, 0x59, 0x59 } },
+	{ 0xea, { 0x80, 0x80, 0x20, 0x80, 0x80 } },
+	{ 0xeb, { 0x37, 0x37, 0x78, 0x37, 0x77 } },
+	{ 0xec, { 0x1f, 0x1f, 0x25, 0x25, 0x25 } },
+	{ 0xed, { 0x0a, 0x0a, 0x0a, 0x0a, 0x0a } },
+	{ 0xee, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+	{ 0xef, { 0x70, 0x70, 0x58, 0x38, 0x58 } },
+	{ 0xf0, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
+};
+
+#endif /* HD29L2_PRIV */
diff --git a/drivers/media/dvb-frontends/isl6405.c b/drivers/media/dvb-frontends/isl6405.c
new file mode 100644
index 0000000..33d33f4
--- /dev/null
+++ b/drivers/media/dvb-frontends/isl6405.c
@@ -0,0 +1,164 @@
+/*
+ * isl6405.c - driver for dual lnb supply and control ic ISL6405
+ *
+ * Copyright (C) 2008 Hartmut Hackmann
+ * Copyright (C) 2006 Oliver Endriss
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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.
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ *
+ *
+ * the project's page is at http://www.linuxtv.org
+ */
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+
+#include "dvb_frontend.h"
+#include "isl6405.h"
+
+struct isl6405 {
+	u8			config;
+	u8			override_or;
+	u8			override_and;
+	struct i2c_adapter	*i2c;
+	u8			i2c_addr;
+};
+
+static int isl6405_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+{
+	struct isl6405 *isl6405 = (struct isl6405 *) fe->sec_priv;
+	struct i2c_msg msg = {	.addr = isl6405->i2c_addr, .flags = 0,
+				.buf = &isl6405->config,
+				.len = sizeof(isl6405->config) };
+
+	if (isl6405->override_or & 0x80) {
+		isl6405->config &= ~(ISL6405_VSEL2 | ISL6405_EN2);
+		switch (voltage) {
+		case SEC_VOLTAGE_OFF:
+			break;
+		case SEC_VOLTAGE_13:
+			isl6405->config |= ISL6405_EN2;
+			break;
+		case SEC_VOLTAGE_18:
+			isl6405->config |= (ISL6405_EN2 | ISL6405_VSEL2);
+			break;
+		default:
+			return -EINVAL;
+		}
+	} else {
+		isl6405->config &= ~(ISL6405_VSEL1 | ISL6405_EN1);
+		switch (voltage) {
+		case SEC_VOLTAGE_OFF:
+			break;
+		case SEC_VOLTAGE_13:
+			isl6405->config |= ISL6405_EN1;
+			break;
+		case SEC_VOLTAGE_18:
+			isl6405->config |= (ISL6405_EN1 | ISL6405_VSEL1);
+			break;
+		default:
+			return -EINVAL;
+		};
+	}
+	isl6405->config |= isl6405->override_or;
+	isl6405->config &= isl6405->override_and;
+
+	return (i2c_transfer(isl6405->i2c, &msg, 1) == 1) ? 0 : -EIO;
+}
+
+static int isl6405_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
+{
+	struct isl6405 *isl6405 = (struct isl6405 *) fe->sec_priv;
+	struct i2c_msg msg = {	.addr = isl6405->i2c_addr, .flags = 0,
+				.buf = &isl6405->config,
+				.len = sizeof(isl6405->config) };
+
+	if (isl6405->override_or & 0x80) {
+		if (arg)
+			isl6405->config |= ISL6405_LLC2;
+		else
+			isl6405->config &= ~ISL6405_LLC2;
+	} else {
+		if (arg)
+			isl6405->config |= ISL6405_LLC1;
+		else
+			isl6405->config &= ~ISL6405_LLC1;
+	}
+	isl6405->config |= isl6405->override_or;
+	isl6405->config &= isl6405->override_and;
+
+	return (i2c_transfer(isl6405->i2c, &msg, 1) == 1) ? 0 : -EIO;
+}
+
+static void isl6405_release(struct dvb_frontend *fe)
+{
+	/* power off */
+	isl6405_set_voltage(fe, SEC_VOLTAGE_OFF);
+
+	/* free */
+	kfree(fe->sec_priv);
+	fe->sec_priv = NULL;
+}
+
+struct dvb_frontend *isl6405_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c,
+				    u8 i2c_addr, u8 override_set, u8 override_clear)
+{
+	struct isl6405 *isl6405 = kmalloc(sizeof(struct isl6405), GFP_KERNEL);
+	if (!isl6405)
+		return NULL;
+
+	/* default configuration */
+	if (override_set & 0x80)
+		isl6405->config = ISL6405_ISEL2;
+	else
+		isl6405->config = ISL6405_ISEL1;
+	isl6405->i2c = i2c;
+	isl6405->i2c_addr = i2c_addr;
+	fe->sec_priv = isl6405;
+
+	/* bits which should be forced to '1' */
+	isl6405->override_or = override_set;
+
+	/* bits which should be forced to '0' */
+	isl6405->override_and = ~override_clear;
+
+	/* detect if it is present or not */
+	if (isl6405_set_voltage(fe, SEC_VOLTAGE_OFF)) {
+		kfree(isl6405);
+		fe->sec_priv = NULL;
+		return NULL;
+	}
+
+	/* install release callback */
+	fe->ops.release_sec = isl6405_release;
+
+	/* override frontend ops */
+	fe->ops.set_voltage = isl6405_set_voltage;
+	fe->ops.enable_high_lnb_voltage = isl6405_enable_high_lnb_voltage;
+
+	return fe;
+}
+EXPORT_SYMBOL(isl6405_attach);
+
+MODULE_DESCRIPTION("Driver for lnb supply and control ic isl6405");
+MODULE_AUTHOR("Hartmut Hackmann & Oliver Endriss");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb-frontends/isl6405.h b/drivers/media/dvb-frontends/isl6405.h
new file mode 100644
index 0000000..1c793d3
--- /dev/null
+++ b/drivers/media/dvb-frontends/isl6405.h
@@ -0,0 +1,74 @@
+/*
+ * isl6405.h - driver for dual lnb supply and control ic ISL6405
+ *
+ * Copyright (C) 2008 Hartmut Hackmann
+ * Copyright (C) 2006 Oliver Endriss
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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.
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ *
+ *
+ * the project's page is at http://www.linuxtv.org
+ */
+
+#ifndef _ISL6405_H
+#define _ISL6405_H
+
+#include <linux/dvb/frontend.h>
+
+/* system register bits */
+
+/* this bit selects register (control) 1 or 2
+   note that the bit maps are different */
+
+#define ISL6405_SR	0x80
+
+/* SR = 0 */
+#define ISL6405_OLF1	0x01
+#define ISL6405_EN1	0x02
+#define ISL6405_VSEL1	0x04
+#define ISL6405_LLC1	0x08
+#define ISL6405_ENT1	0x10
+#define ISL6405_ISEL1	0x20
+#define ISL6405_DCL	0x40
+
+/* SR = 1 */
+#define ISL6405_OLF2	0x01
+#define ISL6405_OTF	0x02
+#define ISL6405_EN2	0x04
+#define ISL6405_VSEL2	0x08
+#define ISL6405_LLC2	0x10
+#define ISL6405_ENT2	0x20
+#define ISL6405_ISEL2	0x40
+
+#if defined(CONFIG_DVB_ISL6405) || (defined(CONFIG_DVB_ISL6405_MODULE) && defined(MODULE))
+/* override_set and override_clear control which system register bits (above)
+ * to always set & clear
+ */
+extern struct dvb_frontend *isl6405_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c,
+					   u8 i2c_addr, u8 override_set, u8 override_clear);
+#else
+static inline struct dvb_frontend *isl6405_attach(struct dvb_frontend *fe,
+						  struct i2c_adapter *i2c, u8 i2c_addr,
+						  u8 override_set, u8 override_clear)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif /* CONFIG_DVB_ISL6405 */
+
+#endif
diff --git a/drivers/media/dvb-frontends/isl6421.c b/drivers/media/dvb-frontends/isl6421.c
new file mode 100644
index 0000000..684c8ec
--- /dev/null
+++ b/drivers/media/dvb-frontends/isl6421.c
@@ -0,0 +1,141 @@
+/*
+ * isl6421.h - driver for lnb supply and control ic ISL6421
+ *
+ * Copyright (C) 2006 Andrew de Quincey
+ * Copyright (C) 2006 Oliver Endriss
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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.
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ *
+ *
+ * the project's page is at http://www.linuxtv.org
+ */
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+
+#include "dvb_frontend.h"
+#include "isl6421.h"
+
+struct isl6421 {
+	u8			config;
+	u8			override_or;
+	u8			override_and;
+	struct i2c_adapter	*i2c;
+	u8			i2c_addr;
+};
+
+static int isl6421_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+{
+	struct isl6421 *isl6421 = (struct isl6421 *) fe->sec_priv;
+	struct i2c_msg msg = {	.addr = isl6421->i2c_addr, .flags = 0,
+				.buf = &isl6421->config,
+				.len = sizeof(isl6421->config) };
+
+	isl6421->config &= ~(ISL6421_VSEL1 | ISL6421_EN1);
+
+	switch(voltage) {
+	case SEC_VOLTAGE_OFF:
+		break;
+	case SEC_VOLTAGE_13:
+		isl6421->config |= ISL6421_EN1;
+		break;
+	case SEC_VOLTAGE_18:
+		isl6421->config |= (ISL6421_EN1 | ISL6421_VSEL1);
+		break;
+	default:
+		return -EINVAL;
+	};
+
+	isl6421->config |= isl6421->override_or;
+	isl6421->config &= isl6421->override_and;
+
+	return (i2c_transfer(isl6421->i2c, &msg, 1) == 1) ? 0 : -EIO;
+}
+
+static int isl6421_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
+{
+	struct isl6421 *isl6421 = (struct isl6421 *) fe->sec_priv;
+	struct i2c_msg msg = {	.addr = isl6421->i2c_addr, .flags = 0,
+				.buf = &isl6421->config,
+				.len = sizeof(isl6421->config) };
+
+	if (arg)
+		isl6421->config |= ISL6421_LLC1;
+	else
+		isl6421->config &= ~ISL6421_LLC1;
+
+	isl6421->config |= isl6421->override_or;
+	isl6421->config &= isl6421->override_and;
+
+	return (i2c_transfer(isl6421->i2c, &msg, 1) == 1) ? 0 : -EIO;
+}
+
+static void isl6421_release(struct dvb_frontend *fe)
+{
+	/* power off */
+	isl6421_set_voltage(fe, SEC_VOLTAGE_OFF);
+
+	/* free */
+	kfree(fe->sec_priv);
+	fe->sec_priv = NULL;
+}
+
+struct dvb_frontend *isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr,
+		   u8 override_set, u8 override_clear)
+{
+	struct isl6421 *isl6421 = kmalloc(sizeof(struct isl6421), GFP_KERNEL);
+	if (!isl6421)
+		return NULL;
+
+	/* default configuration */
+	isl6421->config = ISL6421_ISEL1;
+	isl6421->i2c = i2c;
+	isl6421->i2c_addr = i2c_addr;
+	fe->sec_priv = isl6421;
+
+	/* bits which should be forced to '1' */
+	isl6421->override_or = override_set;
+
+	/* bits which should be forced to '0' */
+	isl6421->override_and = ~override_clear;
+
+	/* detect if it is present or not */
+	if (isl6421_set_voltage(fe, SEC_VOLTAGE_OFF)) {
+		kfree(isl6421);
+		fe->sec_priv = NULL;
+		return NULL;
+	}
+
+	/* install release callback */
+	fe->ops.release_sec = isl6421_release;
+
+	/* override frontend ops */
+	fe->ops.set_voltage = isl6421_set_voltage;
+	fe->ops.enable_high_lnb_voltage = isl6421_enable_high_lnb_voltage;
+
+	return fe;
+}
+EXPORT_SYMBOL(isl6421_attach);
+
+MODULE_DESCRIPTION("Driver for lnb supply and control ic isl6421");
+MODULE_AUTHOR("Andrew de Quincey & Oliver Endriss");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb-frontends/isl6421.h b/drivers/media/dvb-frontends/isl6421.h
new file mode 100644
index 0000000..47e4518
--- /dev/null
+++ b/drivers/media/dvb-frontends/isl6421.h
@@ -0,0 +1,55 @@
+/*
+ * isl6421.h - driver for lnb supply and control ic ISL6421
+ *
+ * Copyright (C) 2006 Andrew de Quincey
+ * Copyright (C) 2006 Oliver Endriss
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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.
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ *
+ *
+ * the project's page is at http://www.linuxtv.org
+ */
+
+#ifndef _ISL6421_H
+#define _ISL6421_H
+
+#include <linux/dvb/frontend.h>
+
+/* system register bits */
+#define ISL6421_OLF1	0x01
+#define ISL6421_EN1	0x02
+#define ISL6421_VSEL1	0x04
+#define ISL6421_LLC1	0x08
+#define ISL6421_ENT1	0x10
+#define ISL6421_ISEL1	0x20
+#define ISL6421_DCL	0x40
+
+#if defined(CONFIG_DVB_ISL6421) || (defined(CONFIG_DVB_ISL6421_MODULE) && defined(MODULE))
+/* override_set and override_clear control which system register bits (above) to always set & clear */
+extern struct dvb_frontend *isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr,
+			  u8 override_set, u8 override_clear);
+#else
+static inline struct dvb_frontend *isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr,
+						  u8 override_set, u8 override_clear)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif // CONFIG_DVB_ISL6421
+
+#endif
diff --git a/drivers/media/dvb-frontends/isl6423.c b/drivers/media/dvb-frontends/isl6423.c
new file mode 100644
index 0000000..dca5beb
--- /dev/null
+++ b/drivers/media/dvb-frontends/isl6423.c
@@ -0,0 +1,308 @@
+/*
+	Intersil ISL6423 SEC and LNB Power supply controller
+
+	Copyright (C) Manu Abraham <abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+
+#include "dvb_frontend.h"
+#include "isl6423.h"
+
+static unsigned int verbose;
+module_param(verbose, int, 0644);
+MODULE_PARM_DESC(verbose, "Set Verbosity level");
+
+#define FE_ERROR				0
+#define FE_NOTICE				1
+#define FE_INFO					2
+#define FE_DEBUG				3
+#define FE_DEBUGREG				4
+
+#define dprintk(__y, __z, format, arg...) do {						\
+	if (__z) {									\
+		if	((verbose > FE_ERROR) && (verbose > __y))			\
+			printk(KERN_ERR "%s: " format "\n", __func__ , ##arg);		\
+		else if	((verbose > FE_NOTICE) && (verbose > __y))			\
+			printk(KERN_NOTICE "%s: " format "\n", __func__ , ##arg);	\
+		else if ((verbose > FE_INFO) && (verbose > __y))			\
+			printk(KERN_INFO "%s: " format "\n", __func__ , ##arg);		\
+		else if ((verbose > FE_DEBUG) && (verbose > __y))			\
+			printk(KERN_DEBUG "%s: " format "\n", __func__ , ##arg);	\
+	} else {									\
+		if (verbose > __y)							\
+			printk(format, ##arg);						\
+	}										\
+} while (0)
+
+struct isl6423_dev {
+	const struct isl6423_config	*config;
+	struct i2c_adapter		*i2c;
+
+	u8 reg_3;
+	u8 reg_4;
+
+	unsigned int verbose;
+};
+
+static int isl6423_write(struct isl6423_dev *isl6423, u8 reg)
+{
+	struct i2c_adapter *i2c = isl6423->i2c;
+	u8 addr			= isl6423->config->addr;
+	int err = 0;
+
+	struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = &reg, .len = 1 };
+
+	dprintk(FE_DEBUG, 1, "write reg %02X", reg);
+	err = i2c_transfer(i2c, &msg, 1);
+	if (err < 0)
+		goto exit;
+	return 0;
+
+exit:
+	dprintk(FE_ERROR, 1, "I/O error <%d>", err);
+	return err;
+}
+
+static int isl6423_set_modulation(struct dvb_frontend *fe)
+{
+	struct isl6423_dev *isl6423		= (struct isl6423_dev *) fe->sec_priv;
+	const struct isl6423_config *config	= isl6423->config;
+	int err = 0;
+	u8 reg_2 = 0;
+
+	reg_2 = 0x01 << 5;
+
+	if (config->mod_extern)
+		reg_2 |= (1 << 3);
+	else
+		reg_2 |= (1 << 4);
+
+	err = isl6423_write(isl6423, reg_2);
+	if (err < 0)
+		goto exit;
+	return 0;
+
+exit:
+	dprintk(FE_ERROR, 1, "I/O error <%d>", err);
+	return err;
+}
+
+static int isl6423_voltage_boost(struct dvb_frontend *fe, long arg)
+{
+	struct isl6423_dev *isl6423 = (struct isl6423_dev *) fe->sec_priv;
+	u8 reg_3 = isl6423->reg_3;
+	u8 reg_4 = isl6423->reg_4;
+	int err = 0;
+
+	if (arg) {
+		/* EN = 1, VSPEN = 1, VBOT = 1 */
+		reg_4 |= (1 << 4);
+		reg_4 |= 0x1;
+		reg_3 |= (1 << 3);
+	} else {
+		/* EN = 1, VSPEN = 1, VBOT = 0 */
+		reg_4 |= (1 << 4);
+		reg_4 &= ~0x1;
+		reg_3 |= (1 << 3);
+	}
+	err = isl6423_write(isl6423, reg_3);
+	if (err < 0)
+		goto exit;
+
+	err = isl6423_write(isl6423, reg_4);
+	if (err < 0)
+		goto exit;
+
+	isl6423->reg_3 = reg_3;
+	isl6423->reg_4 = reg_4;
+
+	return 0;
+exit:
+	dprintk(FE_ERROR, 1, "I/O error <%d>", err);
+	return err;
+}
+
+
+static int isl6423_set_voltage(struct dvb_frontend *fe,
+			       enum fe_sec_voltage voltage)
+{
+	struct isl6423_dev *isl6423 = (struct isl6423_dev *) fe->sec_priv;
+	u8 reg_3 = isl6423->reg_3;
+	u8 reg_4 = isl6423->reg_4;
+	int err = 0;
+
+	switch (voltage) {
+	case SEC_VOLTAGE_OFF:
+		/* EN = 0 */
+		reg_4 &= ~(1 << 4);
+		break;
+
+	case SEC_VOLTAGE_13:
+		/* EN = 1, VSPEN = 1, VTOP = 0, VBOT = 0 */
+		reg_4 |= (1 << 4);
+		reg_4 &= ~0x3;
+		reg_3 |= (1 << 3);
+		break;
+
+	case SEC_VOLTAGE_18:
+		/* EN = 1, VSPEN = 1, VTOP = 1, VBOT = 0 */
+		reg_4 |= (1 << 4);
+		reg_4 |=  0x2;
+		reg_4 &= ~0x1;
+		reg_3 |= (1 << 3);
+		break;
+
+	default:
+		break;
+	}
+	err = isl6423_write(isl6423, reg_3);
+	if (err < 0)
+		goto exit;
+
+	err = isl6423_write(isl6423, reg_4);
+	if (err < 0)
+		goto exit;
+
+	isl6423->reg_3 = reg_3;
+	isl6423->reg_4 = reg_4;
+
+	return 0;
+exit:
+	dprintk(FE_ERROR, 1, "I/O error <%d>", err);
+	return err;
+}
+
+static int isl6423_set_current(struct dvb_frontend *fe)
+{
+	struct isl6423_dev *isl6423		= (struct isl6423_dev *) fe->sec_priv;
+	u8 reg_3 = isl6423->reg_3;
+	const struct isl6423_config *config	= isl6423->config;
+	int err = 0;
+
+	switch (config->current_max) {
+	case SEC_CURRENT_275m:
+		/* 275mA */
+		/* ISELH = 0, ISELL = 0 */
+		reg_3 &= ~0x3;
+		break;
+
+	case SEC_CURRENT_515m:
+		/* 515mA */
+		/* ISELH = 0, ISELL = 1 */
+		reg_3 &= ~0x2;
+		reg_3 |=  0x1;
+		break;
+
+	case SEC_CURRENT_635m:
+		/* 635mA */
+		/* ISELH = 1, ISELL = 0 */
+		reg_3 &= ~0x1;
+		reg_3 |=  0x2;
+		break;
+
+	case SEC_CURRENT_800m:
+		/* 800mA */
+		/* ISELH = 1, ISELL = 1 */
+		reg_3 |= 0x3;
+		break;
+	}
+
+	err = isl6423_write(isl6423, reg_3);
+	if (err < 0)
+		goto exit;
+
+	switch (config->curlim) {
+	case SEC_CURRENT_LIM_ON:
+		/* DCL = 0 */
+		reg_3 &= ~0x10;
+		break;
+
+	case SEC_CURRENT_LIM_OFF:
+		/* DCL = 1 */
+		reg_3 |= 0x10;
+		break;
+	}
+
+	err = isl6423_write(isl6423, reg_3);
+	if (err < 0)
+		goto exit;
+
+	isl6423->reg_3 = reg_3;
+
+	return 0;
+exit:
+	dprintk(FE_ERROR, 1, "I/O error <%d>", err);
+	return err;
+}
+
+static void isl6423_release(struct dvb_frontend *fe)
+{
+	isl6423_set_voltage(fe, SEC_VOLTAGE_OFF);
+
+	kfree(fe->sec_priv);
+	fe->sec_priv = NULL;
+}
+
+struct dvb_frontend *isl6423_attach(struct dvb_frontend *fe,
+				    struct i2c_adapter *i2c,
+				    const struct isl6423_config *config)
+{
+	struct isl6423_dev *isl6423;
+
+	isl6423 = kzalloc(sizeof(struct isl6423_dev), GFP_KERNEL);
+	if (!isl6423)
+		return NULL;
+
+	isl6423->config	= config;
+	isl6423->i2c	= i2c;
+	fe->sec_priv	= isl6423;
+
+	/* SR3H = 0, SR3M = 1, SR3L = 0 */
+	isl6423->reg_3 = 0x02 << 5;
+	/* SR4H = 0, SR4M = 1, SR4L = 1 */
+	isl6423->reg_4 = 0x03 << 5;
+
+	if (isl6423_set_current(fe))
+		goto exit;
+
+	if (isl6423_set_modulation(fe))
+		goto exit;
+
+	fe->ops.release_sec		= isl6423_release;
+	fe->ops.set_voltage		= isl6423_set_voltage;
+	fe->ops.enable_high_lnb_voltage = isl6423_voltage_boost;
+	isl6423->verbose		= verbose;
+
+	return fe;
+
+exit:
+	kfree(isl6423);
+	fe->sec_priv = NULL;
+	return NULL;
+}
+EXPORT_SYMBOL(isl6423_attach);
+
+MODULE_DESCRIPTION("ISL6423 SEC");
+MODULE_AUTHOR("Manu Abraham");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb-frontends/isl6423.h b/drivers/media/dvb-frontends/isl6423.h
new file mode 100644
index 0000000..e1a37fb
--- /dev/null
+++ b/drivers/media/dvb-frontends/isl6423.h
@@ -0,0 +1,63 @@
+/*
+	Intersil ISL6423 SEC and LNB Power supply controller
+
+	Copyright (C) Manu Abraham <abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __ISL_6423_H
+#define __ISL_6423_H
+
+#include <linux/dvb/frontend.h>
+
+enum isl6423_current {
+	SEC_CURRENT_275m = 0,
+	SEC_CURRENT_515m,
+	SEC_CURRENT_635m,
+	SEC_CURRENT_800m,
+};
+
+enum isl6423_curlim {
+	SEC_CURRENT_LIM_ON = 1,
+	SEC_CURRENT_LIM_OFF
+};
+
+struct isl6423_config {
+	enum isl6423_current current_max;
+	enum isl6423_curlim curlim;
+	u8 addr;
+	u8 mod_extern;
+};
+
+#if defined(CONFIG_DVB_ISL6423) || (defined(CONFIG_DVB_ISL6423_MODULE) && defined(MODULE))
+
+
+extern struct dvb_frontend *isl6423_attach(struct dvb_frontend *fe,
+					   struct i2c_adapter *i2c,
+					   const struct isl6423_config *config);
+
+#else
+static inline struct dvb_frontend *isl6423_attach(struct dvb_frontend *fe,
+						  struct i2c_adapter *i2c,
+						  const struct isl6423_config *config)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+
+#endif /* CONFIG_DVB_ISL6423 */
+
+#endif /* __ISL_6423_H */
diff --git a/drivers/media/dvb-frontends/it913x-fe-priv.h b/drivers/media/dvb-frontends/it913x-fe-priv.h
new file mode 100644
index 0000000..eb6fd8a
--- /dev/null
+++ b/drivers/media/dvb-frontends/it913x-fe-priv.h
@@ -0,0 +1,1051 @@
+
+struct it913xset {	u32 pro;
+			u32 address;
+			u8 reg[15];
+			u8 count;
+};
+
+struct adctable {	u32 adcFrequency;
+			u32 bandwidth;
+			u32 coeff_1_2048;
+			u32 coeff_1_4096;
+			u32 coeff_1_8191;
+			u32 coeff_1_8192;
+			u32 coeff_1_8193;
+			u32 coeff_2_2k;
+			u32 coeff_2_4k;
+			u32 coeff_2_8k;
+			u16 bfsfcw_fftinx_ratio;
+			u16 fftinx_bfsfcw_ratio;
+};
+
+/* clock and coeff tables only table 3 is used with IT9137*/
+/* TODO other tables relate AF9035 may be removed */
+static struct adctable tab1[] = {
+	{	20156250, 6000000,
+		0x02b8ba6e, 0x015c5d37, 0x00ae340d, 0x00ae2e9b, 0x00ae292a,
+		0x015c5d37, 0x00ae2e9b, 0x0057174e, 0x02f1, 0x015c	},
+	{	20156250, 7000000,
+		0x032cd980, 0x01966cc0, 0x00cb3cba, 0x00cb3660, 0x00cb3007,
+		0x01966cc0, 0x00cb3660, 0x00659b30, 0x0285, 0x0196	},
+	{	20156250, 8000000,
+		0x03a0f893, 0x01d07c49, 0x00e84567, 0x00e83e25, 0x00e836e3,
+		0x01d07c49, 0x00e83e25, 0x00741f12, 0x0234, 0x01d0	},
+	{	20156250, 5000000,
+		0x02449b5c, 0x01224dae, 0x00912b60, 0x009126d7, 0x0091224e,
+		0x01224dae, 0x009126d7, 0x0048936b, 0x0387, 0x0122	}
+};
+
+static struct adctable tab2[] = {
+	{	20187500, 6000000,
+		0x02b7a654, 0x015bd32a, 0x00adef04, 0x00ade995, 0x00ade426,
+		0x015bd32a, 0x00ade995, 0x0056f4ca, 0x02f2, 0x015c	},
+	{	20187500, 7000000,
+		0x032b9761, 0x0195cbb1, 0x00caec30, 0x00cae5d8, 0x00cadf81,
+		0x0195cbb1, 0x00cae5d8, 0x006572ec, 0x0286, 0x0196	},
+	{	20187500, 8000000,
+		0x039f886f, 0x01cfc438, 0x00e7e95b, 0x00e7e21c, 0x00e7dadd,
+		0x01cfc438, 0x00e7e21c, 0x0073f10e, 0x0235, 0x01d0	},
+	{	20187500, 5000000,
+		0x0243b546, 0x0121daa3, 0x0090f1d9, 0x0090ed51, 0x0090e8ca,
+		0x0121daa3, 0x0090ed51, 0x004876a9, 0x0388, 0x0122	}
+
+};
+
+static struct adctable tab3[] = {
+	{	20250000, 6000000,
+		0x02b580ad, 0x015ac057, 0x00ad6597, 0x00ad602b, 0x00ad5ac1,
+		0x015ac057, 0x00ad602b, 0x0056b016, 0x02f4, 0x015b	},
+	{	20250000, 7000000,
+		0x03291620, 0x01948b10, 0x00ca4bda, 0x00ca4588, 0x00ca3f36,
+		0x01948b10, 0x00ca4588, 0x006522c4, 0x0288, 0x0195	},
+	{	20250000, 8000000,
+		0x039cab92, 0x01ce55c9, 0x00e7321e, 0x00e72ae4, 0x00e723ab,
+		0x01ce55c9, 0x00e72ae4, 0x00739572, 0x0237, 0x01ce	},
+	{	20250000, 5000000,
+		0x0241eb3b, 0x0120f59e, 0x00907f53, 0x00907acf, 0x0090764b,
+		0x0120f59e, 0x00907acf, 0x00483d67, 0x038b, 0x0121	}
+
+};
+
+static struct adctable tab4[] = {
+	{	20583333, 6000000,
+		0x02aa4598, 0x015522cc, 0x00aa96bb, 0x00aa9166, 0x00aa8c12,
+		0x015522cc, 0x00aa9166, 0x005548b3, 0x0300, 0x0155	},
+	{	20583333, 7000000,
+		0x031bfbdc, 0x018dfdee, 0x00c7052f, 0x00c6fef7, 0x00c6f8bf,
+		0x018dfdee, 0x00c6fef7, 0x00637f7b, 0x0293, 0x018e	},
+	{	20583333, 8000000,
+		0x038db21f, 0x01c6d910, 0x00e373a3, 0x00e36c88, 0x00e3656d,
+		0x01c6d910, 0x00e36c88, 0x0071b644, 0x0240, 0x01c7	},
+	{	20583333, 5000000,
+		0x02388f54, 0x011c47aa, 0x008e2846, 0x008e23d5, 0x008e1f64,
+		0x011c47aa, 0x008e23d5, 0x004711ea, 0x039a, 0x011c	}
+
+};
+
+static struct adctable tab5[] = {
+	{	20416667, 6000000,
+		0x02afd765, 0x0157ebb3, 0x00abfb39, 0x00abf5d9, 0x00abf07a,
+		0x0157ebb3, 0x00abf5d9, 0x0055faed, 0x02fa, 0x0158	},
+	{	20416667, 7000000,
+		0x03227b4b, 0x01913da6, 0x00c8a518, 0x00c89ed3, 0x00c8988e,
+		0x01913da6, 0x00c89ed3, 0x00644f69, 0x028d, 0x0191	},
+	{	20416667, 8000000,
+		0x03951f32, 0x01ca8f99, 0x00e54ef7, 0x00e547cc, 0x00e540a2,
+		0x01ca8f99, 0x00e547cc, 0x0072a3e6, 0x023c, 0x01cb	},
+	{	20416667, 5000000,
+		0x023d337f, 0x011e99c0, 0x008f515a, 0x008f4ce0, 0x008f4865,
+		0x011e99c0, 0x008f4ce0, 0x0047a670, 0x0393, 0x011f	}
+
+};
+
+static struct adctable tab6[] = {
+	{	20480000, 6000000,
+		0x02adb6db, 0x0156db6e, 0x00ab7312, 0x00ab6db7, 0x00ab685c,
+		0x0156db6e, 0x00ab6db7, 0x0055b6db, 0x02fd, 0x0157	},
+	{	20480000, 7000000,
+		0x03200000, 0x01900000, 0x00c80640, 0x00c80000, 0x00c7f9c0,
+		0x01900000, 0x00c80000, 0x00640000, 0x028f, 0x0190	},
+	{	20480000, 8000000,
+		0x03924925, 0x01c92492, 0x00e4996e, 0x00e49249, 0x00e48b25,
+		0x01c92492, 0x00e49249, 0x00724925, 0x023d, 0x01c9	},
+	{	20480000, 5000000,
+		0x023b6db7, 0x011db6db, 0x008edfe5, 0x008edb6e, 0x008ed6f7,
+		0x011db6db, 0x008edb6e, 0x00476db7, 0x0396, 0x011e	}
+};
+
+static struct adctable tab7[] = {
+	{	20500000, 6000000,
+		0x02ad0b99, 0x015685cc, 0x00ab4840, 0x00ab42e6, 0x00ab3d8c,
+		0x015685cc, 0x00ab42e6, 0x0055a173, 0x02fd, 0x0157	},
+	{	20500000, 7000000,
+		0x031f3832, 0x018f9c19, 0x00c7d44b, 0x00c7ce0c, 0x00c7c7ce,
+		0x018f9c19, 0x00c7ce0c, 0x0063e706, 0x0290, 0x0190	},
+	{	20500000, 8000000,
+		0x039164cb, 0x01c8b266, 0x00e46056, 0x00e45933, 0x00e45210,
+		0x01c8b266, 0x00e45933, 0x00722c99, 0x023e, 0x01c9	},
+	{	20500000, 5000000,
+		0x023adeff, 0x011d6f80, 0x008ebc36, 0x008eb7c0, 0x008eb34a,
+		0x011d6f80, 0x008eb7c0, 0x00475be0, 0x0396, 0x011d	}
+
+};
+
+static struct adctable tab8[] = {
+	{	20625000, 6000000,
+		0x02a8e4bd, 0x0154725e, 0x00aa3e81, 0x00aa392f, 0x00aa33de,
+		0x0154725e, 0x00aa392f, 0x00551c98, 0x0302, 0x0154	},
+	{	20625000, 7000000,
+		0x031a6032, 0x018d3019, 0x00c69e41, 0x00c6980c, 0x00c691d8,
+		0x018d3019, 0x00c6980c, 0x00634c06, 0x0294, 0x018d	},
+	{	20625000, 8000000,
+		0x038bdba6, 0x01c5edd3, 0x00e2fe02, 0x00e2f6ea, 0x00e2efd2,
+		0x01c5edd3, 0x00e2f6ea, 0x00717b75, 0x0242, 0x01c6	},
+	{	20625000, 5000000,
+		0x02376948, 0x011bb4a4, 0x008ddec1, 0x008dda52, 0x008dd5e3,
+		0x011bb4a4, 0x008dda52, 0x0046ed29, 0x039c, 0x011c	}
+
+};
+
+struct table {
+		u32 xtal;
+		struct adctable *table;
+};
+
+static struct table fe_clockTable[] = {
+		{12000000, tab3},	/* 12.00MHz */
+		{20480000, tab6},	/* 20.48MHz */
+		{36000000, tab3},	/* 36.00MHz */
+		{30000000, tab1},	/* 30.00MHz */
+		{26000000, tab4},	/* 26.00MHz */
+		{28000000, tab5},	/* 28.00MHz */
+		{32000000, tab7},	/* 32.00MHz */
+		{34000000, tab2},	/* 34.00MHz */
+		{24000000, tab1},	/* 24.00MHz */
+		{22000000, tab8},	/* 22.00MHz */
+};
+
+/* fe get */
+fe_code_rate_t fe_code[] = {
+	FEC_1_2,
+	FEC_2_3,
+	FEC_3_4,
+	FEC_5_6,
+	FEC_7_8,
+	FEC_NONE,
+};
+
+fe_guard_interval_t fe_gi[] = {
+	GUARD_INTERVAL_1_32,
+	GUARD_INTERVAL_1_16,
+	GUARD_INTERVAL_1_8,
+	GUARD_INTERVAL_1_4,
+};
+
+fe_hierarchy_t fe_hi[] = {
+	HIERARCHY_NONE,
+	HIERARCHY_1,
+	HIERARCHY_2,
+	HIERARCHY_4,
+};
+
+fe_transmit_mode_t fe_mode[] = {
+	TRANSMISSION_MODE_2K,
+	TRANSMISSION_MODE_8K,
+	TRANSMISSION_MODE_4K,
+};
+
+fe_modulation_t fe_con[] = {
+	QPSK,
+	QAM_16,
+	QAM_64,
+};
+
+enum {
+	PRIORITY_HIGH = 0,	/* High-priority stream */
+	PRIORITY_LOW,	/* Low-priority stream */
+};
+
+/* Standard demodulator functions */
+static struct it913xset set_solo_fe[] = {
+	{PRO_LINK, GPIOH5_EN, {0x01}, 0x01},
+	{PRO_LINK, GPIOH5_ON, {0x01}, 0x01},
+	{PRO_LINK, GPIOH5_O, {0x00}, 0x01},
+	{PRO_LINK, GPIOH5_O, {0x01}, 0x01},
+	{PRO_LINK, DVBT_INTEN, {0x04}, 0x01},
+	{PRO_LINK, DVBT_ENABLE, {0x05}, 0x01},
+	{PRO_DMOD, MP2IF_MPEG_PAR_MODE, {0x00}, 0x01},
+	{PRO_LINK, HOSTB_MPEG_SER_MODE, {0x00}, 0x01},
+	{PRO_LINK, HOSTB_MPEG_PAR_MODE, {0x00}, 0x01},
+	{PRO_DMOD, DCA_UPPER_CHIP, {0x00}, 0x01},
+	{PRO_LINK, HOSTB_DCA_UPPER, {0x00}, 0x01},
+	{PRO_DMOD, DCA_LOWER_CHIP, {0x00}, 0x01},
+	{PRO_LINK, HOSTB_DCA_LOWER, {0x00}, 0x01},
+	{PRO_DMOD, DCA_PLATCH, {0x00}, 0x01},
+	{PRO_DMOD, DCA_FPGA_LATCH, {0x00}, 0x01},
+	{PRO_DMOD, DCA_STAND_ALONE, {0x01}, 0x01},
+	{PRO_DMOD, DCA_ENABLE, {0x00}, 0x01},
+	{PRO_DMOD, MP2IF_MPEG_PAR_MODE, {0x00}, 0x01},
+	{PRO_DMOD, BFS_FCW, {0x00, 0x00, 0x00}, 0x03},
+	{0xff, 0x0000, {0x00}, 0x00}, /* Terminating Entry */
+};
+
+
+static struct it913xset init_1[] = {
+	{PRO_LINK, LOCK3_OUT, {0x01}, 0x01},
+	{PRO_LINK, PADMISCDRSR, {0x01}, 0x01},
+	{PRO_LINK, PADMISCDR2, {0x00}, 0x01},
+	{PRO_DMOD, 0xec57, {0x00, 0x00}, 0x02},
+	{PRO_LINK, PADMISCDR4, {0x00}, 0x01}, /* Power up */
+	{PRO_LINK, PADMISCDR8, {0x00}, 0x01},
+	{0xff, 0x0000, {0x00}, 0x00} /* Terminating Entry */
+};
+
+
+/* Version 1 types */
+static struct it913xset it9135_v1[] = {
+	{PRO_DMOD, 0x0051, {0x01}, 0x01},
+	{PRO_DMOD, 0x0070, {0x0a}, 0x01},
+	{PRO_DMOD, 0x007e, {0x04}, 0x01},
+	{PRO_DMOD, 0x0081, {0x0a}, 0x01},
+	{PRO_DMOD, 0x008a, {0x01}, 0x01},
+	{PRO_DMOD, 0x008e, {0x01}, 0x01},
+	{PRO_DMOD, 0x0092, {0x06}, 0x01},
+	{PRO_DMOD, 0x0099, {0x01}, 0x01},
+	{PRO_DMOD, 0x009f, {0xe1}, 0x01},
+	{PRO_DMOD, 0x00a0, {0xcf}, 0x01},
+	{PRO_DMOD, 0x00a3, {0x01}, 0x01},
+	{PRO_DMOD, 0x00a5, {0x01}, 0x01},
+	{PRO_DMOD, 0x00a6, {0x01}, 0x01},
+	{PRO_DMOD, 0x00a9, {0x00}, 0x01},
+	{PRO_DMOD, 0x00aa, {0x01}, 0x01},
+	{PRO_DMOD, 0x00b0, {0x01}, 0x01},
+	{PRO_DMOD, 0x00c2, {0x05}, 0x01},
+	{PRO_DMOD, 0x00c6, {0x19}, 0x01},
+	{PRO_DMOD, 0xf000, {0x0f}, 0x01},
+	{PRO_DMOD, 0xf016, {0x10}, 0x01},
+	{PRO_DMOD, 0xf017, {0x04}, 0x01},
+	{PRO_DMOD, 0xf018, {0x05}, 0x01},
+	{PRO_DMOD, 0xf019, {0x04}, 0x01},
+	{PRO_DMOD, 0xf01a, {0x05}, 0x01},
+	{PRO_DMOD, 0xf021, {0x03}, 0x01},
+	{PRO_DMOD, 0xf022, {0x0a}, 0x01},
+	{PRO_DMOD, 0xf023, {0x0a}, 0x01},
+	{PRO_DMOD, 0xf02b, {0x00}, 0x01},
+	{PRO_DMOD, 0xf02c, {0x01}, 0x01},
+	{PRO_DMOD, 0xf064, {0x03}, 0x01},
+	{PRO_DMOD, 0xf065, {0xf9}, 0x01},
+	{PRO_DMOD, 0xf066, {0x03}, 0x01},
+	{PRO_DMOD, 0xf067, {0x01}, 0x01},
+	{PRO_DMOD, 0xf06f, {0xe0}, 0x01},
+	{PRO_DMOD, 0xf070, {0x03}, 0x01},
+	{PRO_DMOD, 0xf072, {0x0f}, 0x01},
+	{PRO_DMOD, 0xf073, {0x03}, 0x01},
+	{PRO_DMOD, 0xf078, {0x00}, 0x01},
+	{PRO_DMOD, 0xf087, {0x00}, 0x01},
+	{PRO_DMOD, 0xf09b, {0x3f}, 0x01},
+	{PRO_DMOD, 0xf09c, {0x00}, 0x01},
+	{PRO_DMOD, 0xf09d, {0x20}, 0x01},
+	{PRO_DMOD, 0xf09e, {0x00}, 0x01},
+	{PRO_DMOD, 0xf09f, {0x0c}, 0x01},
+	{PRO_DMOD, 0xf0a0, {0x00}, 0x01},
+	{PRO_DMOD, 0xf130, {0x04}, 0x01},
+	{PRO_DMOD, 0xf132, {0x04}, 0x01},
+	{PRO_DMOD, 0xf144, {0x1a}, 0x01},
+	{PRO_DMOD, 0xf146, {0x00}, 0x01},
+	{PRO_DMOD, 0xf14a, {0x01}, 0x01},
+	{PRO_DMOD, 0xf14c, {0x00}, 0x01},
+	{PRO_DMOD, 0xf14d, {0x00}, 0x01},
+	{PRO_DMOD, 0xf14f, {0x04}, 0x01},
+	{PRO_DMOD, 0xf158, {0x7f}, 0x01},
+	{PRO_DMOD, 0xf15a, {0x00}, 0x01},
+	{PRO_DMOD, 0xf15b, {0x08}, 0x01},
+	{PRO_DMOD, 0xf15d, {0x03}, 0x01},
+	{PRO_DMOD, 0xf15e, {0x05}, 0x01},
+	{PRO_DMOD, 0xf163, {0x05}, 0x01},
+	{PRO_DMOD, 0xf166, {0x01}, 0x01},
+	{PRO_DMOD, 0xf167, {0x40}, 0x01},
+	{PRO_DMOD, 0xf168, {0x0f}, 0x01},
+	{PRO_DMOD, 0xf17a, {0x00}, 0x01},
+	{PRO_DMOD, 0xf17b, {0x00}, 0x01},
+	{PRO_DMOD, 0xf183, {0x01}, 0x01},
+	{PRO_DMOD, 0xf19d, {0x40}, 0x01},
+	{PRO_DMOD, 0xf1bc, {0x36}, 0x01},
+	{PRO_DMOD, 0xf1bd, {0x00}, 0x01},
+	{PRO_DMOD, 0xf1cb, {0xa0}, 0x01},
+	{PRO_DMOD, 0xf1cc, {0x01}, 0x01},
+	{PRO_DMOD, 0xf204, {0x10}, 0x01},
+	{PRO_DMOD, 0xf214, {0x00}, 0x01},
+	{PRO_DMOD, 0xf40e, {0x0a}, 0x01},
+	{PRO_DMOD, 0xf40f, {0x40}, 0x01},
+	{PRO_DMOD, 0xf410, {0x08}, 0x01},
+	{PRO_DMOD, 0xf55f, {0x0a}, 0x01},
+	{PRO_DMOD, 0xf561, {0x15}, 0x01},
+	{PRO_DMOD, 0xf562, {0x20}, 0x01},
+	{PRO_DMOD, 0xf5df, {0xfb}, 0x01},
+	{PRO_DMOD, 0xf5e0, {0x00}, 0x01},
+	{PRO_DMOD, 0xf5e3, {0x09}, 0x01},
+	{PRO_DMOD, 0xf5e4, {0x01}, 0x01},
+	{PRO_DMOD, 0xf5e5, {0x01}, 0x01},
+	{PRO_DMOD, 0xf5f8, {0x01}, 0x01},
+	{PRO_DMOD, 0xf5fd, {0x01}, 0x01},
+	{PRO_DMOD, 0xf600, {0x05}, 0x01},
+	{PRO_DMOD, 0xf601, {0x08}, 0x01},
+	{PRO_DMOD, 0xf602, {0x0b}, 0x01},
+	{PRO_DMOD, 0xf603, {0x0e}, 0x01},
+	{PRO_DMOD, 0xf604, {0x11}, 0x01},
+	{PRO_DMOD, 0xf605, {0x14}, 0x01},
+	{PRO_DMOD, 0xf606, {0x17}, 0x01},
+	{PRO_DMOD, 0xf607, {0x1f}, 0x01},
+	{PRO_DMOD, 0xf60e, {0x00}, 0x01},
+	{PRO_DMOD, 0xf60f, {0x04}, 0x01},
+	{PRO_DMOD, 0xf610, {0x32}, 0x01},
+	{PRO_DMOD, 0xf611, {0x10}, 0x01},
+	{PRO_DMOD, 0xf707, {0xfc}, 0x01},
+	{PRO_DMOD, 0xf708, {0x00}, 0x01},
+	{PRO_DMOD, 0xf709, {0x37}, 0x01},
+	{PRO_DMOD, 0xf70a, {0x00}, 0x01},
+	{PRO_DMOD, 0xf78b, {0x01}, 0x01},
+	{PRO_DMOD, 0xf80f, {0x40}, 0x01},
+	{PRO_DMOD, 0xf810, {0x54}, 0x01},
+	{PRO_DMOD, 0xf811, {0x5a}, 0x01},
+	{PRO_DMOD, 0xf905, {0x01}, 0x01},
+	{PRO_DMOD, 0xfb06, {0x03}, 0x01},
+	{PRO_DMOD, 0xfd8b, {0x00}, 0x01},
+	{0xff, 0x0000, {0x00}, 0x00} /* Terminating Entry */
+};
+
+static struct it913xset it9135_38[] = {
+	{PRO_DMOD, 0x0043, {0x00}, 0x01},
+	{PRO_DMOD, 0x0046, {0x38}, 0x01},
+	{PRO_DMOD, 0x0051, {0x01}, 0x01},
+	{PRO_DMOD, 0x005f, {0x00, 0x00}, 0x02},
+	{PRO_DMOD, 0x0068, {0x0a}, 0x01},
+	{PRO_DMOD, 0x0070, {0x0a, 0x05, 0x02}, 0x03},
+	{PRO_DMOD, 0x0075, {0x8c, 0x8c, 0x8c, 0xc8, 0x01}, 0x05},
+	{PRO_DMOD, 0x007e, {0x04, 0x00}, 0x02},
+	{PRO_DMOD, 0x0081, {	0x0a, 0x12, 0x02, 0x0a, 0x03, 0xc8, 0xb8,
+				0xd0, 0xc3, 0x01}, 0x0a},
+	{PRO_DMOD, 0x008e, {0x01}, 0x01},
+	{PRO_DMOD, 0x0092, {0x06, 0x00, 0x00, 0x00, 0x00}, 0x05},
+	{PRO_DMOD, 0x0099, {0x01}, 0x01},
+	{PRO_DMOD, 0x009b, {0x3c, 0x28}, 0x02},
+	{PRO_DMOD, 0x009f, {0xe1, 0xcf}, 0x02},
+	{PRO_DMOD, 0x00a3, {0x01, 0x5a, 0x01, 0x01}, 0x04},
+	{PRO_DMOD, 0x00a9, {0x00, 0x01}, 0x02},
+	{PRO_DMOD, 0x00b0, {0x01}, 0x01},
+	{PRO_DMOD, 0x00b3, {0x02, 0x32}, 0x02},
+	{PRO_DMOD, 0x00b6, {0x14}, 0x01},
+	{PRO_DMOD, 0x00c0, {0x11, 0x00, 0x05}, 0x03},
+	{PRO_DMOD, 0x00c4, {0x00}, 0x01},
+	{PRO_DMOD, 0x00c6, {0x19, 0x00}, 0x02},
+	{PRO_DMOD, 0x00cc, {0x2e, 0x51, 0x33}, 0x03},
+	{PRO_DMOD, 0x00f3, {0x05, 0x8c, 0x8c}, 0x03},
+	{PRO_DMOD, 0x00f8, {0x03, 0x06, 0x06}, 0x03},
+	{PRO_DMOD, 0x00fc, {	0x02, 0x02, 0x02, 0x09, 0x50, 0x7b, 0x77,
+				0x00, 0x02, 0xc8, 0x05, 0x7b}, 0x0c},
+	{PRO_DMOD, 0x0109, {0x02}, 0x01},
+	{PRO_DMOD, 0x0115, {0x0a, 0x03, 0x02, 0x80}, 0x04},
+	{PRO_DMOD, 0x011a, {0xc8, 0x7b, 0x8a, 0xa0}, 0x04},
+	{PRO_DMOD, 0x0122, {0x02, 0x18, 0xc3}, 0x03},
+	{PRO_DMOD, 0x0127, {0x00, 0x07}, 0x02},
+	{PRO_DMOD, 0x012a, {0x53, 0x51, 0x4e, 0x43}, 0x04},
+	{PRO_DMOD, 0x0137, {0x01, 0x00, 0x07, 0x00, 0x06}, 0x05},
+	{PRO_DMOD, 0x013d, {0x00, 0x01, 0x5b, 0xc8, 0x59}, 0x05},
+	{PRO_DMOD, 0xf000, {0x0f}, 0x01},
+	{PRO_DMOD, 0xf016, {0x10, 0x04, 0x05, 0x04, 0x05}, 0x05},
+	{PRO_DMOD, 0xf01f, {0x8c, 0x00, 0x03, 0x0a, 0x0a}, 0x05},
+	{PRO_DMOD, 0xf029, {0x8c, 0x00, 0x00, 0x01}, 0x04},
+	{PRO_DMOD, 0xf064, {0x03, 0xf9, 0x03, 0x01}, 0x04},
+	{PRO_DMOD, 0xf06f, {0xe0, 0x03}, 0x02},
+	{PRO_DMOD, 0xf072, {0x0f, 0x03}, 0x02},
+	{PRO_DMOD, 0xf077, {0x01, 0x00}, 0x02},
+	{PRO_DMOD, 0xf085, {0x00, 0x02, 0x00}, 0x03},
+	{PRO_DMOD, 0xf09b, {0x3f, 0x00, 0x20, 0x00, 0x0c, 0x00}, 0x06},
+	{PRO_DMOD, 0xf130, {0x04}, 0x01},
+	{PRO_DMOD, 0xf132, {0x04}, 0x01},
+	{PRO_DMOD, 0xf144, {0x1a}, 0x01},
+	{PRO_DMOD, 0xf146, {0x00}, 0x01},
+	{PRO_DMOD, 0xf14a, {0x01}, 0x01},
+	{PRO_DMOD, 0xf14c, {0x00, 0x00}, 0x02},
+	{PRO_DMOD, 0xf14f, {0x04}, 0x01},
+	{PRO_DMOD, 0xf158, {0x7f}, 0x01},
+	{PRO_DMOD, 0xf15a, {0x00, 0x08}, 0x02},
+	{PRO_DMOD, 0xf15d, {0x03, 0x05}, 0x02},
+	{PRO_DMOD, 0xf163, {0x05}, 0x01},
+	{PRO_DMOD, 0xf166, {0x01, 0x40, 0x0f}, 0x03},
+	{PRO_DMOD, 0xf17a, {0x00, 0x00}, 0x02},
+	{PRO_DMOD, 0xf183, {0x01}, 0x01},
+	{PRO_DMOD, 0xf19d, {0x40}, 0x01},
+	{PRO_DMOD, 0xf1bc, {0x36, 0x00}, 0x02},
+	{PRO_DMOD, 0xf1cb, {0xa0, 0x01}, 0x02},
+	{PRO_DMOD, 0xf204, {0x10}, 0x01},
+	{PRO_DMOD, 0xf214, {0x00}, 0x01},
+	{PRO_DMOD, 0xf24c, {0x88, 0x95, 0x9a, 0x90}, 0x04},
+	{PRO_DMOD, 0xf25a, {0x07, 0xe8, 0x03, 0xb0, 0x04}, 0x05},
+	{PRO_DMOD, 0xf270, {0x01, 0x02, 0x01, 0x02}, 0x04},
+	{PRO_DMOD, 0xf40e, {0x0a, 0x40, 0x08}, 0x03},
+	{PRO_DMOD, 0xf55f, {0x0a}, 0x01},
+	{PRO_DMOD, 0xf561, {0x15, 0x20}, 0x02},
+	{PRO_DMOD, 0xf5df, {0xfb, 0x00}, 0x02},
+	{PRO_DMOD, 0xf5e3, {0x09, 0x01, 0x01}, 0x03},
+	{PRO_DMOD, 0xf5f8, {0x01}, 0x01},
+	{PRO_DMOD, 0xf5fd, {0x01}, 0x01},
+	{PRO_DMOD, 0xf600, {	0x05, 0x08, 0x0b, 0x0e, 0x11, 0x14, 0x17,
+				0x1f}, 0x08},
+	{PRO_DMOD, 0xf60e, {0x00, 0x04, 0x32, 0x10}, 0x04},
+	{PRO_DMOD, 0xf707, {0xfc, 0x00, 0x37, 0x00}, 0x04},
+	{PRO_DMOD, 0xf78b, {0x01}, 0x01},
+	{PRO_DMOD, 0xf80f, {0x40, 0x54, 0x5a}, 0x03},
+	{PRO_DMOD, 0xf905, {0x01}, 0x01},
+	{PRO_DMOD, 0xfb06, {0x03}, 0x01},
+	{PRO_DMOD, 0xfd8b, {0x00}, 0x01},
+	{0xff, 0x0000, {0x00}, 0x00} /* Terminating Entry */
+};
+
+static struct it913xset it9135_51[] = {
+	{PRO_DMOD, 0x0043, {0x00}, 0x01},
+	{PRO_DMOD, 0x0046, {0x51}, 0x01},
+	{PRO_DMOD, 0x0051, {0x01}, 0x01},
+	{PRO_DMOD, 0x005f, {0x00, 0x00}, 0x02},
+	{PRO_DMOD, 0x0068, {0x0a}, 0x01},
+	{PRO_DMOD, 0x0070, {0x0a, 0x06, 0x02}, 0x03},
+	{PRO_DMOD, 0x0075, {0x8c, 0x8c, 0x8c, 0xc8, 0x01}, 0x05},
+	{PRO_DMOD, 0x007e, {0x04, 0x00}, 0x02},
+	{PRO_DMOD, 0x0081, {	0x0a, 0x12, 0x02, 0x0a, 0x03, 0xc0, 0x96,
+				0xcf, 0xc3, 0x01}, 0x0a},
+	{PRO_DMOD, 0x008e, {0x01}, 0x01},
+	{PRO_DMOD, 0x0092, {0x06, 0x00, 0x00, 0x00, 0x00}, 0x05},
+	{PRO_DMOD, 0x0099, {0x01}, 0x01},
+	{PRO_DMOD, 0x009b, {0x3c, 0x28}, 0x02},
+	{PRO_DMOD, 0x009f, {0xe1, 0xcf}, 0x02},
+	{PRO_DMOD, 0x00a3, {0x01, 0x5a, 0x01, 0x01}, 0x04},
+	{PRO_DMOD, 0x00a9, {0x00, 0x01}, 0x02},
+	{PRO_DMOD, 0x00b0, {0x01}, 0x01},
+	{PRO_DMOD, 0x00b3, {0x02, 0x3c}, 0x02},
+	{PRO_DMOD, 0x00b6, {0x14}, 0x01},
+	{PRO_DMOD, 0x00c0, {0x11, 0x00, 0x05}, 0x03},
+	{PRO_DMOD, 0x00c4, {0x00}, 0x01},
+	{PRO_DMOD, 0x00c6, {0x19, 0x00}, 0x02},
+	{PRO_DMOD, 0x00cc, {0x2e, 0x51, 0x33}, 0x03},
+	{PRO_DMOD, 0x00f3, {0x05, 0x8c, 0x8c}, 0x03},
+	{PRO_DMOD, 0x00f8, {0x03, 0x06, 0x06}, 0x03},
+	{PRO_DMOD, 0x00fc, {	0x03, 0x02, 0x02, 0x09, 0x50, 0x7a, 0x77,
+				0x01, 0x02, 0xb0, 0x02, 0x7a}, 0x0c},
+	{PRO_DMOD, 0x0109, {0x02}, 0x01},
+	{PRO_DMOD, 0x0115, {0x0a, 0x03, 0x02, 0x80}, 0x04},
+	{PRO_DMOD, 0x011a, {0xc0, 0x7a, 0xac, 0x8c}, 0x04},
+	{PRO_DMOD, 0x0122, {0x02, 0x70, 0xa4}, 0x03},
+	{PRO_DMOD, 0x0127, {0x00, 0x07}, 0x02},
+	{PRO_DMOD, 0x012a, {0x53, 0x51, 0x4e, 0x43}, 0x04},
+	{PRO_DMOD, 0x0137, {0x01, 0x00, 0x07, 0x00, 0x06}, 0x05},
+	{PRO_DMOD, 0x013d, {0x00, 0x01, 0x5b, 0xc0, 0x59}, 0x05},
+	{PRO_DMOD, 0xf000, {0x0f}, 0x01},
+	{PRO_DMOD, 0xf016, {0x10, 0x04, 0x05, 0x04, 0x05}, 0x05},
+	{PRO_DMOD, 0xf01f, {0x8c, 0x00, 0x03, 0x0a, 0x0a}, 0x05},
+	{PRO_DMOD, 0xf029, {0x8c, 0x00, 0x00, 0x01}, 0x04},
+	{PRO_DMOD, 0xf064, {0x03, 0xf9, 0x03, 0x01}, 0x04},
+	{PRO_DMOD, 0xf06f, {0xe0, 0x03}, 0x02},
+	{PRO_DMOD, 0xf072, {0x0f, 0x03}, 0x02},
+	{PRO_DMOD, 0xf077, {0x01, 0x00}, 0x02},
+	{PRO_DMOD, 0xf085, {0xc0, 0x01, 0x00}, 0x03},
+	{PRO_DMOD, 0xf09b, {0x3f, 0x00, 0x20, 0x00, 0x0c, 0x00}, 0x06},
+	{PRO_DMOD, 0xf130, {0x04}, 0x01},
+	{PRO_DMOD, 0xf132, {0x04}, 0x01},
+	{PRO_DMOD, 0xf144, {0x1a}, 0x01},
+	{PRO_DMOD, 0xf146, {0x00}, 0x01},
+	{PRO_DMOD, 0xf14a, {0x01}, 0x01},
+	{PRO_DMOD, 0xf14c, {0x00, 0x00}, 0x02},
+	{PRO_DMOD, 0xf14f, {0x04}, 0x01},
+	{PRO_DMOD, 0xf158, {0x7f}, 0x01},
+	{PRO_DMOD, 0xf15a, {0x00, 0x08}, 0x02},
+	{PRO_DMOD, 0xf15d, {0x03, 0x05}, 0x02},
+	{PRO_DMOD, 0xf163, {0x05}, 0x01},
+	{PRO_DMOD, 0xf166, {0x01, 0x40, 0x0f}, 0x03},
+	{PRO_DMOD, 0xf17a, {0x00, 0x00}, 0x02},
+	{PRO_DMOD, 0xf183, {0x01}, 0x01},
+	{PRO_DMOD, 0xf19d, {0x40}, 0x01},
+	{PRO_DMOD, 0xf1bc, {0x36, 0x00}, 0x02},
+	{PRO_DMOD, 0xf1cb, {0xa0, 0x01}, 0x02},
+	{PRO_DMOD, 0xf204, {0x10}, 0x01},
+	{PRO_DMOD, 0xf214, {0x00}, 0x01},
+	{PRO_DMOD, 0xf24c, {0x88, 0x95, 0x9a, 0x90}, 0x04},
+	{PRO_DMOD, 0xf25a, {0x07, 0xe8, 0x03, 0xb0, 0x04}, 0x05},
+	{PRO_DMOD, 0xf270, {0x01, 0x02, 0x01, 0x02}, 0x04},
+	{PRO_DMOD, 0xf40e, {0x0a, 0x40, 0x08}, 0x03},
+	{PRO_DMOD, 0xf55f, {0x0a}, 0x01},
+	{PRO_DMOD, 0xf561, {0x15, 0x20}, 0x02},
+	{PRO_DMOD, 0xf5df, {0xfb, 0x00}, 0x02},
+	{PRO_DMOD, 0xf5e3, {0x09, 0x01, 0x01}, 0x03},
+	{PRO_DMOD, 0xf5f8, {0x01}, 0x01},
+	{PRO_DMOD, 0xf5fd, {0x01}, 0x01},
+	{PRO_DMOD, 0xf600, {	0x05, 0x08, 0x0b, 0x0e, 0x11, 0x14, 0x17,
+				0x1f}, 0x08},
+	{PRO_DMOD, 0xf60e, {0x00, 0x04, 0x32, 0x10}, 0x04},
+	{PRO_DMOD, 0xf707, {0xfc, 0x00, 0x37, 0x00}, 0x04},
+	{PRO_DMOD, 0xf78b, {0x01}, 0x01},
+	{PRO_DMOD, 0xf80f, {0x40, 0x54, 0x5a}, 0x03},
+	{PRO_DMOD, 0xf905, {0x01}, 0x01},
+	{PRO_DMOD, 0xfb06, {0x03}, 0x01},
+	{PRO_DMOD, 0xfd8b, {0x00}, 0x01},
+	{0xff, 0x0000, {0x00}, 0x00} /* Terminating Entry */
+};
+
+static struct it913xset it9135_52[] = {
+	{PRO_DMOD, 0x0043, {0x00}, 0x01},
+	{PRO_DMOD, 0x0046, {0x52}, 0x01},
+	{PRO_DMOD, 0x0051, {0x01}, 0x01},
+	{PRO_DMOD, 0x005f, {0x00, 0x00}, 0x02},
+	{PRO_DMOD, 0x0068, {0x10}, 0x01},
+	{PRO_DMOD, 0x0070, {0x0a, 0x05, 0x02}, 0x03},
+	{PRO_DMOD, 0x0075, {0x8c, 0x8c, 0x8c, 0xa0, 0x01}, 0x05},
+	{PRO_DMOD, 0x007e, {0x04, 0x00}, 0x02},
+	{PRO_DMOD, 0x0081, {	0x0a, 0x12, 0x03, 0x0a, 0x03, 0xb3, 0x97,
+				0xc0, 0x9e, 0x01}, 0x0a},
+	{PRO_DMOD, 0x008e, {0x01}, 0x01},
+	{PRO_DMOD, 0x0092, {0x06, 0x00, 0x00, 0x00, 0x00}, 0x05},
+	{PRO_DMOD, 0x0099, {0x01}, 0x01},
+	{PRO_DMOD, 0x009b, {0x3c, 0x28}, 0x02},
+	{PRO_DMOD, 0x009f, {0xe1, 0xcf}, 0x02},
+	{PRO_DMOD, 0x00a3, {0x01, 0x5c, 0x01, 0x01}, 0x04},
+	{PRO_DMOD, 0x00a9, {0x00, 0x01}, 0x02},
+	{PRO_DMOD, 0x00b0, {0x01}, 0x01},
+	{PRO_DMOD, 0x00b3, {0x02, 0x3c}, 0x02},
+	{PRO_DMOD, 0x00b6, {0x14}, 0x01},
+	{PRO_DMOD, 0x00c0, {0x11, 0x00, 0x05}, 0x03},
+	{PRO_DMOD, 0x00c4, {0x00}, 0x01},
+	{PRO_DMOD, 0x00c6, {0x19, 0x00}, 0x02},
+	{PRO_DMOD, 0x00cc, {0x2e, 0x51, 0x33}, 0x03},
+	{PRO_DMOD, 0x00f3, {0x05, 0x91, 0x8c}, 0x03},
+	{PRO_DMOD, 0x00f8, {0x03, 0x06, 0x06}, 0x03},
+	{PRO_DMOD, 0x00fc, {	0x03, 0x02, 0x02, 0x09, 0x50, 0x74, 0x77,
+				0x02, 0x02, 0xae, 0x02, 0x6e}, 0x0c},
+	{PRO_DMOD, 0x0109, {0x02}, 0x01},
+	{PRO_DMOD, 0x0115, {0x0a, 0x03, 0x02, 0x80}, 0x04},
+	{PRO_DMOD, 0x011a, {0xcd, 0x62, 0xa4, 0x8c}, 0x04},
+	{PRO_DMOD, 0x0122, {0x03, 0x18, 0x9e}, 0x03},
+	{PRO_DMOD, 0x0127, {0x00, 0x07}, 0x02},
+	{PRO_DMOD, 0x012a, {0x53, 0x51, 0x4e, 0x43}, 0x04},
+	{PRO_DMOD, 0x0137, {0x00, 0x00, 0x07, 0x00, 0x06}, 0x05},
+	{PRO_DMOD, 0x013d, {0x00, 0x01, 0x5b, 0xb6, 0x59}, 0x05},
+	{PRO_DMOD, 0xf000, {0x0f}, 0x01},
+	{PRO_DMOD, 0xf016, {0x10, 0x04, 0x05, 0x04, 0x05}, 0x05},
+	{PRO_DMOD, 0xf01f, {0x8c, 0x00, 0x03, 0x0a, 0x0a}, 0x05},
+	{PRO_DMOD, 0xf029, {0x8c, 0x00, 0x00, 0x01}, 0x04},
+	{PRO_DMOD, 0xf064, {0x03, 0xf9, 0x03, 0x01}, 0x04},
+	{PRO_DMOD, 0xf06f, {0xe0, 0x03}, 0x02},
+	{PRO_DMOD, 0xf072, {0x0f, 0x03}, 0x02},
+	{PRO_DMOD, 0xf077, {0x01, 0x00}, 0x02},
+	{PRO_DMOD, 0xf085, {0xc0, 0x01, 0x00}, 0x03},
+	{PRO_DMOD, 0xf09b, {0x3f, 0x00, 0x20, 0x00, 0x0c, 0x00}, 0x06},
+	{PRO_DMOD, 0xf130, {0x04}, 0x01},
+	{PRO_DMOD, 0xf132, {0x04}, 0x01},
+	{PRO_DMOD, 0xf144, {0x1a}, 0x01},
+	{PRO_DMOD, 0xf146, {0x00}, 0x01},
+	{PRO_DMOD, 0xf14a, {0x01}, 0x01},
+	{PRO_DMOD, 0xf14c, {0x00, 0x00}, 0x02},
+	{PRO_DMOD, 0xf14f, {0x04}, 0x01},
+	{PRO_DMOD, 0xf158, {0x7f}, 0x01},
+	{PRO_DMOD, 0xf15a, {0x00, 0x08}, 0x02},
+	{PRO_DMOD, 0xf15d, {0x03, 0x05}, 0x02},
+	{PRO_DMOD, 0xf163, {0x05}, 0x01},
+	{PRO_DMOD, 0xf166, {0x01, 0x40, 0x0f}, 0x03},
+	{PRO_DMOD, 0xf17a, {0x00, 0x00}, 0x02},
+	{PRO_DMOD, 0xf183, {0x01}, 0x01},
+	{PRO_DMOD, 0xf19d, {0x40}, 0x01},
+	{PRO_DMOD, 0xf1bc, {0x36, 0x00}, 0x02},
+	{PRO_DMOD, 0xf1cb, {0xa0, 0x01}, 0x02},
+	{PRO_DMOD, 0xf204, {0x10}, 0x01},
+	{PRO_DMOD, 0xf214, {0x00}, 0x01},
+	{PRO_DMOD, 0xf24c, {0x88, 0x95, 0x9a, 0x90}, 0x04},
+	{PRO_DMOD, 0xf25a, {0x07, 0xe8, 0x03, 0xb0, 0x04}, 0x05},
+	{PRO_DMOD, 0xf270, {0x01, 0x02, 0x01, 0x02}, 0x04},
+	{PRO_DMOD, 0xf40e, {0x0a, 0x40, 0x08}, 0x03},
+	{PRO_DMOD, 0xf55f, {0x0a}, 0x01},
+	{PRO_DMOD, 0xf561, {0x15, 0x20}, 0x02},
+	{PRO_DMOD, 0xf5df, {0xfb, 0x00}, 0x02},
+	{PRO_DMOD, 0xf5e3, {0x09, 0x01, 0x01}, 0x03},
+	{PRO_DMOD, 0xf5f8, {0x01}, 0x01},
+	{PRO_DMOD, 0xf5fd, {0x01}, 0x01},
+	{PRO_DMOD, 0xf600, {0x05, 0x08, 0x0b, 0x0e, 0x11, 0x14, 0x17,
+				0x1f}, 0x08},
+	{PRO_DMOD, 0xf60e, {0x00, 0x04, 0x32, 0x10}, 0x04},
+	{PRO_DMOD, 0xf707, {0xfc, 0x00, 0x37, 0x00}, 0x04},
+	{PRO_DMOD, 0xf78b, {0x01}, 0x01},
+	{PRO_DMOD, 0xf80f, {0x40, 0x54, 0x5a}, 0x03},
+	{PRO_DMOD, 0xf905, {0x01}, 0x01},
+	{PRO_DMOD, 0xfb06, {0x03}, 0x01},
+	{PRO_DMOD, 0xfd8b, {0x00}, 0x01},
+	{0xff, 0x0000, {0x00}, 0x00} /* Terminating Entry */
+};
+
+/* Version 2 types */
+static struct it913xset it9135_v2[] = {
+	{PRO_DMOD, 0x0051, {0x01}, 0x01},
+	{PRO_DMOD, 0x0070, {0x0a}, 0x01},
+	{PRO_DMOD, 0x007e, {0x04}, 0x01},
+	{PRO_DMOD, 0x0081, {0x0a}, 0x01},
+	{PRO_DMOD, 0x008a, {0x01}, 0x01},
+	{PRO_DMOD, 0x008e, {0x01}, 0x01},
+	{PRO_DMOD, 0x0092, {0x06}, 0x01},
+	{PRO_DMOD, 0x0099, {0x01}, 0x01},
+	{PRO_DMOD, 0x009f, {0xe1}, 0x01},
+	{PRO_DMOD, 0x00a0, {0xcf}, 0x01},
+	{PRO_DMOD, 0x00a3, {0x01}, 0x01},
+	{PRO_DMOD, 0x00a5, {0x01}, 0x01},
+	{PRO_DMOD, 0x00a6, {0x01}, 0x01},
+	{PRO_DMOD, 0x00a9, {0x00}, 0x01},
+	{PRO_DMOD, 0x00aa, {0x01}, 0x01},
+	{PRO_DMOD, 0x00b0, {0x01}, 0x01},
+	{PRO_DMOD, 0x00c2, {0x05}, 0x01},
+	{PRO_DMOD, 0x00c6, {0x19}, 0x01},
+	{PRO_DMOD, 0xf000, {0x0f}, 0x01},
+	{PRO_DMOD, 0xf02b, {0x00}, 0x01},
+	{PRO_DMOD, 0xf064, {0x03}, 0x01},
+	{PRO_DMOD, 0xf065, {0xf9}, 0x01},
+	{PRO_DMOD, 0xf066, {0x03}, 0x01},
+	{PRO_DMOD, 0xf067, {0x01}, 0x01},
+	{PRO_DMOD, 0xf06f, {0xe0}, 0x01},
+	{PRO_DMOD, 0xf070, {0x03}, 0x01},
+	{PRO_DMOD, 0xf072, {0x0f}, 0x01},
+	{PRO_DMOD, 0xf073, {0x03}, 0x01},
+	{PRO_DMOD, 0xf078, {0x00}, 0x01},
+	{PRO_DMOD, 0xf087, {0x00}, 0x01},
+	{PRO_DMOD, 0xf09b, {0x3f}, 0x01},
+	{PRO_DMOD, 0xf09c, {0x00}, 0x01},
+	{PRO_DMOD, 0xf09d, {0x20}, 0x01},
+	{PRO_DMOD, 0xf09e, {0x00}, 0x01},
+	{PRO_DMOD, 0xf09f, {0x0c}, 0x01},
+	{PRO_DMOD, 0xf0a0, {0x00}, 0x01},
+	{PRO_DMOD, 0xf130, {0x04}, 0x01},
+	{PRO_DMOD, 0xf132, {0x04}, 0x01},
+	{PRO_DMOD, 0xf144, {0x1a}, 0x01},
+	{PRO_DMOD, 0xf146, {0x00}, 0x01},
+	{PRO_DMOD, 0xf14a, {0x01}, 0x01},
+	{PRO_DMOD, 0xf14c, {0x00}, 0x01},
+	{PRO_DMOD, 0xf14d, {0x00}, 0x01},
+	{PRO_DMOD, 0xf14f, {0x04}, 0x01},
+	{PRO_DMOD, 0xf158, {0x7f}, 0x01},
+	{PRO_DMOD, 0xf15a, {0x00}, 0x01},
+	{PRO_DMOD, 0xf15b, {0x08}, 0x01},
+	{PRO_DMOD, 0xf15d, {0x03}, 0x01},
+	{PRO_DMOD, 0xf15e, {0x05}, 0x01},
+	{PRO_DMOD, 0xf163, {0x05}, 0x01},
+	{PRO_DMOD, 0xf166, {0x01}, 0x01},
+	{PRO_DMOD, 0xf167, {0x40}, 0x01},
+	{PRO_DMOD, 0xf168, {0x0f}, 0x01},
+	{PRO_DMOD, 0xf17a, {0x00}, 0x01},
+	{PRO_DMOD, 0xf17b, {0x00}, 0x01},
+	{PRO_DMOD, 0xf183, {0x01}, 0x01},
+	{PRO_DMOD, 0xf19d, {0x40}, 0x01},
+	{PRO_DMOD, 0xf1bc, {0x36}, 0x01},
+	{PRO_DMOD, 0xf1bd, {0x00}, 0x01},
+	{PRO_DMOD, 0xf1cb, {0xa0}, 0x01},
+	{PRO_DMOD, 0xf1cc, {0x01}, 0x01},
+	{PRO_DMOD, 0xf204, {0x10}, 0x01},
+	{PRO_DMOD, 0xf214, {0x00}, 0x01},
+	{PRO_DMOD, 0xf40e, {0x0a}, 0x01},
+	{PRO_DMOD, 0xf40f, {0x40}, 0x01},
+	{PRO_DMOD, 0xf410, {0x08}, 0x01},
+	{PRO_DMOD, 0xf55f, {0x0a}, 0x01},
+	{PRO_DMOD, 0xf561, {0x15}, 0x01},
+	{PRO_DMOD, 0xf562, {0x20}, 0x01},
+	{PRO_DMOD, 0xf5e3, {0x09}, 0x01},
+	{PRO_DMOD, 0xf5e4, {0x01}, 0x01},
+	{PRO_DMOD, 0xf5e5, {0x01}, 0x01},
+	{PRO_DMOD, 0xf600, {0x05}, 0x01},
+	{PRO_DMOD, 0xf601, {0x08}, 0x01},
+	{PRO_DMOD, 0xf602, {0x0b}, 0x01},
+	{PRO_DMOD, 0xf603, {0x0e}, 0x01},
+	{PRO_DMOD, 0xf604, {0x11}, 0x01},
+	{PRO_DMOD, 0xf605, {0x14}, 0x01},
+	{PRO_DMOD, 0xf606, {0x17}, 0x01},
+	{PRO_DMOD, 0xf607, {0x1f}, 0x01},
+	{PRO_DMOD, 0xf60e, {0x00}, 0x01},
+	{PRO_DMOD, 0xf60f, {0x04}, 0x01},
+	{PRO_DMOD, 0xf610, {0x32}, 0x01},
+	{PRO_DMOD, 0xf611, {0x10}, 0x01},
+	{PRO_DMOD, 0xf707, {0xfc}, 0x01},
+	{PRO_DMOD, 0xf708, {0x00}, 0x01},
+	{PRO_DMOD, 0xf709, {0x37}, 0x01},
+	{PRO_DMOD, 0xf70a, {0x00}, 0x01},
+	{PRO_DMOD, 0xf78b, {0x01}, 0x01},
+	{PRO_DMOD, 0xf80f, {0x40}, 0x01},
+	{PRO_DMOD, 0xf810, {0x54}, 0x01},
+	{PRO_DMOD, 0xf811, {0x5a}, 0x01},
+	{PRO_DMOD, 0xf905, {0x01}, 0x01},
+	{PRO_DMOD, 0xfb06, {0x03}, 0x01},
+	{PRO_DMOD, 0xfd8b, {0x00}, 0x01},
+	{0xff, 0x0000, {0x00}, 0x00} /* Terminating Entry */
+};
+
+static struct it913xset it9135_60[] = {
+	{PRO_DMOD, 0x0043, {0x00}, 0x01},
+	{PRO_DMOD, 0x0046, {0x60}, 0x01},
+	{PRO_DMOD, 0x0051, {0x01}, 0x01},
+	{PRO_DMOD, 0x005f, {0x00, 0x00}, 0x02},
+	{PRO_DMOD, 0x0068, {0x0a}, 0x01},
+	{PRO_DMOD, 0x006a, {0x03}, 0x01},
+	{PRO_DMOD, 0x0070, {0x0a, 0x05, 0x02}, 0x03},
+	{PRO_DMOD, 0x0075, {0x8c, 0x8c, 0x8c, 0x8c, 0x01}, 0x05},
+	{PRO_DMOD, 0x007e, {0x04}, 0x01},
+	{PRO_DMOD, 0x0081, {0x0a, 0x12}, 0x02},
+	{PRO_DMOD, 0x0084, {0x0a, 0x33, 0xbe, 0xa0, 0xc6, 0xb6, 0x01}, 0x07},
+	{PRO_DMOD, 0x008e, {0x01}, 0x01},
+	{PRO_DMOD, 0x0092, {0x06, 0x00, 0x00, 0x00, 0x00}, 0x05},
+	{PRO_DMOD, 0x0099, {0x01}, 0x01},
+	{PRO_DMOD, 0x009b, {0x3c, 0x28}, 0x02},
+	{PRO_DMOD, 0x009f, {0xe1, 0xcf}, 0x02},
+	{PRO_DMOD, 0x00a3, {0x01, 0x5a, 0x01, 0x01}, 0x04},
+	{PRO_DMOD, 0x00a9, {0x00, 0x01}, 0x02},
+	{PRO_DMOD, 0x00b0, {0x01}, 0x01},
+	{PRO_DMOD, 0x00b3, {0x02, 0x3a}, 0x02},
+	{PRO_DMOD, 0x00b6, {0x14}, 0x01},
+	{PRO_DMOD, 0x00c0, {0x11, 0x00, 0x05, 0x01, 0x00}, 0x05},
+	{PRO_DMOD, 0x00c6, {0x19, 0x00}, 0x02},
+	{PRO_DMOD, 0x00cb, {0x32, 0x2c, 0x4f, 0x30}, 0x04},
+	{PRO_DMOD, 0x00f3, {0x05, 0xa0, 0x8c}, 0x03},
+	{PRO_DMOD, 0x00f8, {0x03, 0x06, 0x06}, 0x03},
+	{PRO_DMOD, 0x00fc, {	0x03, 0x03, 0x02, 0x0a, 0x50, 0x7b, 0x8c,
+				0x00, 0x02, 0xbe, 0x00}, 0x0b},
+	{PRO_DMOD, 0x0109, {0x02}, 0x01},
+	{PRO_DMOD, 0x0115, {0x0a, 0x03}, 0x02},
+	{PRO_DMOD, 0x011a, {0xbe}, 0x01},
+	{PRO_DMOD, 0x0124, {0xae}, 0x01},
+	{PRO_DMOD, 0x0127, {0x00}, 0x01},
+	{PRO_DMOD, 0x012a, {0x56, 0x50, 0x47, 0x42}, 0x04},
+	{PRO_DMOD, 0x0137, {0x00}, 0x01},
+	{PRO_DMOD, 0x013b, {0x08}, 0x01},
+	{PRO_DMOD, 0x013f, {0x5b}, 0x01},
+	{PRO_DMOD, 0x0141, {	0x59, 0xf9, 0x19, 0x19, 0x8c, 0x8c, 0x8c,
+				0x6e, 0x8c, 0x50, 0x8c, 0x8c, 0xac, 0xc6,
+				0x33}, 0x0f},
+	{PRO_DMOD, 0x0151, {0x28}, 0x01},
+	{PRO_DMOD, 0x0153, {0xbc}, 0x01},
+	{PRO_DMOD, 0x0178, {0x09}, 0x01},
+	{PRO_DMOD, 0x0181, {0x94, 0x6e}, 0x02},
+	{PRO_DMOD, 0x0185, {0x24}, 0x01},
+	{PRO_DMOD, 0x0187, {0x00, 0x00, 0xbe, 0x02, 0x80}, 0x05},
+	{PRO_DMOD, 0xed02, {0xff}, 0x01},
+	{PRO_DMOD, 0xee42, {0xff}, 0x01},
+	{PRO_DMOD, 0xee82, {0xff}, 0x01},
+	{PRO_DMOD, 0xf000, {0x0f}, 0x01},
+	{PRO_DMOD, 0xf01f, {0x8c, 0x00}, 0x02},
+	{PRO_DMOD, 0xf029, {0x8c, 0x00, 0x00}, 0x03},
+	{PRO_DMOD, 0xf064, {0x03, 0xf9, 0x03, 0x01}, 0x04},
+	{PRO_DMOD, 0xf06f, {0xe0, 0x03}, 0x02},
+	{PRO_DMOD, 0xf072, {0x0f, 0x03}, 0x02},
+	{PRO_DMOD, 0xf077, {0x01, 0x00}, 0x02},
+	{PRO_DMOD, 0xf087, {0x00}, 0x01},
+	{PRO_DMOD, 0xf09b, {0x3f, 0x00, 0x20, 0x00, 0x0c, 0x00}, 0x06},
+	{PRO_DMOD, 0xf130, {0x04}, 0x01},
+	{PRO_DMOD, 0xf132, {0x04}, 0x01},
+	{PRO_DMOD, 0xf144, {0x1a}, 0x01},
+	{PRO_DMOD, 0xf146, {0x00}, 0x01},
+	{PRO_DMOD, 0xf14a, {0x01}, 0x01},
+	{PRO_DMOD, 0xf14c, {0x00, 0x00}, 0x02},
+	{PRO_DMOD, 0xf14f, {0x04}, 0x01},
+	{PRO_DMOD, 0xf158, {0x7f}, 0x01},
+	{PRO_DMOD, 0xf15a, {0x00, 0x08}, 0x02},
+	{PRO_DMOD, 0xf15d, {0x03, 0x05}, 0x02},
+	{PRO_DMOD, 0xf163, {0x05}, 0x01},
+	{PRO_DMOD, 0xf166, {0x01, 0x40, 0x0f}, 0x03},
+	{PRO_DMOD, 0xf17a, {0x00, 0x00}, 0x02},
+	{PRO_DMOD, 0xf183, {0x01}, 0x01},
+	{PRO_DMOD, 0xf19d, {0x40}, 0x01},
+	{PRO_DMOD, 0xf1bc, {0x36, 0x00}, 0x02},
+	{PRO_DMOD, 0xf1cb, {0xa0, 0x01}, 0x02},
+	{PRO_DMOD, 0xf204, {0x10}, 0x01},
+	{PRO_DMOD, 0xf214, {0x00}, 0x01},
+	{PRO_DMOD, 0xf24c, {0x88, 0x95, 0x9a, 0x90}, 0x04},
+	{PRO_DMOD, 0xf25a, {0x07, 0xe8, 0x03, 0xb0, 0x04}, 0x05},
+	{PRO_DMOD, 0xf270, {0x01, 0x02, 0x01, 0x02}, 0x04},
+	{PRO_DMOD, 0xf40e, {0x0a, 0x40, 0x08}, 0x03},
+	{PRO_DMOD, 0xf55f, {0x0a}, 0x01},
+	{PRO_DMOD, 0xf561, {0x15, 0x20}, 0x02},
+	{PRO_DMOD, 0xf5e3, {0x09, 0x01, 0x01}, 0x03},
+	{PRO_DMOD, 0xf600, {0x05, 0x08, 0x0b, 0x0e, 0x11, 0x14, 0x17
+		, 0x1f}, 0x08},
+	{PRO_DMOD, 0xf60e, {0x00, 0x04, 0x32, 0x10}, 0x04},
+	{PRO_DMOD, 0xf707, {0xfc, 0x00, 0x37, 0x00}, 0x04},
+	{PRO_DMOD, 0xf78b, {0x01}, 0x01},
+	{PRO_DMOD, 0xf80f, {0x40, 0x54, 0x5a}, 0x03},
+	{PRO_DMOD, 0xf905, {0x01}, 0x01},
+	{PRO_DMOD, 0xfb06, {0x03}, 0x01},
+	{PRO_DMOD, 0xfd8b, {0x00}, 0x01},
+	{0xff, 0x0000, {0x00}, 0x00} /* Terminating Entry */
+};
+
+static struct it913xset it9135_61[] = {
+	{PRO_DMOD, 0x0043, {0x00}, 0x01},
+	{PRO_DMOD, 0x0046, {0x61}, 0x01},
+	{PRO_DMOD, 0x0051, {0x01}, 0x01},
+	{PRO_DMOD, 0x005f, {0x00, 0x00}, 0x02},
+	{PRO_DMOD, 0x0068, {0x06}, 0x01},
+	{PRO_DMOD, 0x006a, {0x03}, 0x01},
+	{PRO_DMOD, 0x0070, {0x0a, 0x05, 0x02}, 0x03},
+	{PRO_DMOD, 0x0075, {0x8c, 0x8c, 0x8c, 0x90, 0x01}, 0x05},
+	{PRO_DMOD, 0x007e, {0x04}, 0x01},
+	{PRO_DMOD, 0x0081, {0x0a, 0x12}, 0x02},
+	{PRO_DMOD, 0x0084, {0x0a, 0x33, 0xbc, 0x9c, 0xcc, 0xa8, 0x01}, 0x07},
+	{PRO_DMOD, 0x008e, {0x01}, 0x01},
+	{PRO_DMOD, 0x0092, {0x06, 0x00, 0x00, 0x00, 0x00}, 0x05},
+	{PRO_DMOD, 0x0099, {0x01}, 0x01},
+	{PRO_DMOD, 0x009b, {0x3c, 0x28}, 0x02},
+	{PRO_DMOD, 0x009f, {0xe1, 0xcf}, 0x02},
+	{PRO_DMOD, 0x00a3, {0x01, 0x5c, 0x01, 0x01}, 0x04},
+	{PRO_DMOD, 0x00a9, {0x00, 0x01}, 0x02},
+	{PRO_DMOD, 0x00b0, {0x01}, 0x01},
+	{PRO_DMOD, 0x00b3, {0x02, 0x3a}, 0x02},
+	{PRO_DMOD, 0x00b6, {0x14}, 0x01},
+	{PRO_DMOD, 0x00c0, {0x11, 0x00, 0x05, 0x01, 0x00}, 0x05},
+	{PRO_DMOD, 0x00c6, {0x19, 0x00}, 0x02},
+	{PRO_DMOD, 0x00cb, {0x32, 0x2c, 0x4f, 0x30}, 0x04},
+	{PRO_DMOD, 0x00f3, {0x05, 0xa0, 0x8c}, 0x03},
+	{PRO_DMOD, 0x00f8, {0x03, 0x06, 0x06}, 0x03},
+	{PRO_DMOD, 0x00fc, {	0x03, 0x03, 0x02, 0x08, 0x50, 0x7b, 0x8c,
+				0x01, 0x02, 0xc8, 0x00}, 0x0b},
+	{PRO_DMOD, 0x0109, {0x02}, 0x01},
+	{PRO_DMOD, 0x0115, {0x0a, 0x03}, 0x02},
+	{PRO_DMOD, 0x011a, {0xc6}, 0x01},
+	{PRO_DMOD, 0x0124, {0xa8}, 0x01},
+	{PRO_DMOD, 0x0127, {0x00}, 0x01},
+	{PRO_DMOD, 0x012a, {0x59, 0x50, 0x47, 0x42}, 0x04},
+	{PRO_DMOD, 0x0137, {0x00}, 0x01},
+	{PRO_DMOD, 0x013b, {0x05}, 0x01},
+	{PRO_DMOD, 0x013f, {0x5b}, 0x01},
+	{PRO_DMOD, 0x0141, {	0x59, 0xf9, 0x59, 0x59, 0x8c, 0x8c, 0x8c,
+				0x7b, 0x8c, 0x50, 0x8c, 0x8c, 0xa8, 0xc6,
+				0x33}, 0x0f},
+	{PRO_DMOD, 0x0151, {0x28}, 0x01},
+	{PRO_DMOD, 0x0153, {0xcc}, 0x01},
+	{PRO_DMOD, 0x0178, {0x09}, 0x01},
+	{PRO_DMOD, 0x0181, {0x9c, 0x76}, 0x02},
+	{PRO_DMOD, 0x0185, {0x28}, 0x01},
+	{PRO_DMOD, 0x0187, {0x01, 0x00, 0xaa, 0x02, 0x80}, 0x05},
+	{PRO_DMOD, 0xed02, {0xff}, 0x01},
+	{PRO_DMOD, 0xee42, {0xff}, 0x01},
+	{PRO_DMOD, 0xee82, {0xff}, 0x01},
+	{PRO_DMOD, 0xf000, {0x0f}, 0x01},
+	{PRO_DMOD, 0xf01f, {0x8c, 0x00}, 0x02},
+	{PRO_DMOD, 0xf029, {0x8c, 0x00, 0x00}, 0x03},
+	{PRO_DMOD, 0xf064, {0x03, 0xf9, 0x03, 0x01}, 0x04},
+	{PRO_DMOD, 0xf06f, {0xe0, 0x03}, 0x02},
+	{PRO_DMOD, 0xf072, {0x0f, 0x03}, 0x02},
+	{PRO_DMOD, 0xf077, {0x01, 0x00}, 0x02},
+	{PRO_DMOD, 0xf087, {0x00}, 0x01},
+	{PRO_DMOD, 0xf09b, {0x3f, 0x00, 0x20, 0x00, 0x0c, 0x00}, 0x06},
+	{PRO_DMOD, 0xf130, {0x04}, 0x01},
+	{PRO_DMOD, 0xf132, {0x04}, 0x01},
+	{PRO_DMOD, 0xf144, {0x1a}, 0x01},
+	{PRO_DMOD, 0xf146, {0x00}, 0x01},
+	{PRO_DMOD, 0xf14a, {0x01}, 0x01},
+	{PRO_DMOD, 0xf14c, {0x00, 0x00}, 0x02},
+	{PRO_DMOD, 0xf14f, {0x04}, 0x01},
+	{PRO_DMOD, 0xf158, {0x7f}, 0x01},
+	{PRO_DMOD, 0xf15a, {0x00, 0x08}, 0x02},
+	{PRO_DMOD, 0xf15d, {0x03, 0x05}, 0x02},
+	{PRO_DMOD, 0xf163, {0x05}, 0x01},
+	{PRO_DMOD, 0xf166, {0x01, 0x40, 0x0f}, 0x03},
+	{PRO_DMOD, 0xf17a, {0x00, 0x00}, 0x02},
+	{PRO_DMOD, 0xf183, {0x01}, 0x01},
+	{PRO_DMOD, 0xf19d, {0x40}, 0x01},
+	{PRO_DMOD, 0xf1bc, {0x36, 0x00}, 0x02},
+	{PRO_DMOD, 0xf1cb, {0xa0, 0x01}, 0x02},
+	{PRO_DMOD, 0xf204, {0x10}, 0x01},
+	{PRO_DMOD, 0xf214, {0x00}, 0x01},
+	{PRO_DMOD, 0xf24c, {0x88, 0x95, 0x9a, 0x90}, 0x04},
+	{PRO_DMOD, 0xf25a, {0x07, 0xe8, 0x03, 0xb0, 0x04}, 0x05},
+	{PRO_DMOD, 0xf270, {0x01, 0x02, 0x01, 0x02}, 0x04},
+	{PRO_DMOD, 0xf40e, {0x0a, 0x40, 0x08}, 0x03},
+	{PRO_DMOD, 0xf55f, {0x0a}, 0x01},
+	{PRO_DMOD, 0xf561, {0x15, 0x20}, 0x02},
+	{PRO_DMOD, 0xf5e3, {0x09, 0x01, 0x01}, 0x03},
+	{PRO_DMOD, 0xf600, {	0x05, 0x08, 0x0b, 0x0e, 0x11, 0x14, 0x17,
+				0x1f}, 0x08},
+	{PRO_DMOD, 0xf60e, {0x00, 0x04, 0x32, 0x10}, 0x04},
+	{PRO_DMOD, 0xf707, {0xfc, 0x00, 0x37, 0x00}, 0x04},
+	{PRO_DMOD, 0xf78b, {0x01}, 0x01},
+	{PRO_DMOD, 0xf80f, {0x40, 0x54, 0x5a}, 0x03},
+	{PRO_DMOD, 0xf905, {0x01}, 0x01},
+	{PRO_DMOD, 0xfb06, {0x03}, 0x01},
+	{PRO_DMOD, 0xfd8b, {0x00}, 0x01},
+	{0xff, 0x0000, {0x00}, 0x00} /* Terminating Entry */
+};
+
+static struct it913xset it9135_62[] = {
+	{PRO_DMOD, 0x0043, {0x00}, 0x01},
+	{PRO_DMOD, 0x0046, {0x62}, 0x01},
+	{PRO_DMOD, 0x0051, {0x01}, 0x01},
+	{PRO_DMOD, 0x005f, {0x00, 0x00}, 0x02},
+	{PRO_DMOD, 0x0068, {0x0a}, 0x01},
+	{PRO_DMOD, 0x006a, {0x03}, 0x01},
+	{PRO_DMOD, 0x0070, {0x0a, 0x05, 0x02}, 0x03},
+	{PRO_DMOD, 0x0075, {0x8c, 0x8c, 0x8c, 0x8c, 0x01}, 0x05},
+	{PRO_DMOD, 0x007e, {0x04}, 0x01},
+	{PRO_DMOD, 0x0081, {0x0a, 0x12}, 0x02},
+	{PRO_DMOD, 0x0084, {	0x0a, 0x33, 0xb8, 0x9c, 0xb2, 0xa6, 0x01},
+				0x07},
+	{PRO_DMOD, 0x008e, {0x01}, 0x01},
+	{PRO_DMOD, 0x0092, {0x06, 0x00, 0x00, 0x00, 0x00}, 0x05},
+	{PRO_DMOD, 0x0099, {0x01}, 0x01},
+	{PRO_DMOD, 0x009b, {0x3c, 0x28}, 0x02},
+	{PRO_DMOD, 0x009f, {0xe1, 0xcf}, 0x02},
+	{PRO_DMOD, 0x00a3, {0x01, 0x5a, 0x01, 0x01}, 0x04},
+	{PRO_DMOD, 0x00a9, {0x00, 0x01}, 0x02},
+	{PRO_DMOD, 0x00b0, {0x01}, 0x01},
+	{PRO_DMOD, 0x00b3, {0x02, 0x3a}, 0x02},
+	{PRO_DMOD, 0x00b6, {0x14}, 0x01},
+	{PRO_DMOD, 0x00c0, {0x11, 0x00, 0x05, 0x01, 0x00}, 0x05},
+	{PRO_DMOD, 0x00c6, {0x19, 0x00}, 0x02},
+	{PRO_DMOD, 0x00cb, {0x32, 0x2c, 0x4f, 0x30}, 0x04},
+	{PRO_DMOD, 0x00f3, {0x05, 0x8c, 0x8c}, 0x03},
+	{PRO_DMOD, 0x00f8, {0x03, 0x06, 0x06}, 0x03},
+	{PRO_DMOD, 0x00fc, {	0x02, 0x03, 0x02, 0x09, 0x50, 0x6e, 0x8c,
+				0x02, 0x02, 0xc2, 0x00}, 0x0b},
+	{PRO_DMOD, 0x0109, {0x02}, 0x01},
+	{PRO_DMOD, 0x0115, {0x0a, 0x03}, 0x02},
+	{PRO_DMOD, 0x011a, {0xb8}, 0x01},
+	{PRO_DMOD, 0x0124, {0xa8}, 0x01},
+	{PRO_DMOD, 0x0127, {0x00}, 0x01},
+	{PRO_DMOD, 0x012a, {0x53, 0x51, 0x4e, 0x43}, 0x04},
+	{PRO_DMOD, 0x0137, {0x00}, 0x01},
+	{PRO_DMOD, 0x013b, {0x05}, 0x01},
+	{PRO_DMOD, 0x013f, {0x5b}, 0x01},
+	{PRO_DMOD, 0x0141, {	0x59, 0xf9, 0x59, 0x19, 0x8c, 0x8c, 0x8c,
+				0x7b, 0x8c, 0x50, 0x70, 0x8c, 0x96, 0xd0,
+				0x33}, 0x0f},
+	{PRO_DMOD, 0x0151, {0x28}, 0x01},
+	{PRO_DMOD, 0x0153, {0xb2}, 0x01},
+	{PRO_DMOD, 0x0178, {0x09}, 0x01},
+	{PRO_DMOD, 0x0181, {0x9c, 0x6e}, 0x02},
+	{PRO_DMOD, 0x0185, {0x24}, 0x01},
+	{PRO_DMOD, 0x0187, {0x00, 0x00, 0xb8, 0x02, 0x80}, 0x05},
+	{PRO_DMOD, 0xed02, {0xff}, 0x01},
+	{PRO_DMOD, 0xee42, {0xff}, 0x01},
+	{PRO_DMOD, 0xee82, {0xff}, 0x01},
+	{PRO_DMOD, 0xf000, {0x0f}, 0x01},
+	{PRO_DMOD, 0xf01f, {0x8c, 0x00}, 0x02},
+	{PRO_DMOD, 0xf029, {0x8c, 0x00, 0x00}, 0x03},
+	{PRO_DMOD, 0xf064, {0x03, 0xf9, 0x03, 0x01}, 0x04},
+	{PRO_DMOD, 0xf06f, {0xe0, 0x03}, 0x02},
+	{PRO_DMOD, 0xf072, {0x0f, 0x03}, 0x02},
+	{PRO_DMOD, 0xf077, {0x01, 0x00}, 0x02},
+	{PRO_DMOD, 0xf087, {0x00}, 0x01},
+	{PRO_DMOD, 0xf09b, {0x3f, 0x00, 0x20, 0x00, 0x0c, 0x00}, 0x06},
+	{PRO_DMOD, 0xf130, {0x04}, 0x01},
+	{PRO_DMOD, 0xf132, {0x04}, 0x01},
+	{PRO_DMOD, 0xf144, {0x1a}, 0x01},
+	{PRO_DMOD, 0xf146, {0x00}, 0x01},
+	{PRO_DMOD, 0xf14a, {0x01}, 0x01},
+	{PRO_DMOD, 0xf14c, {0x00, 0x00}, 0x02},
+	{PRO_DMOD, 0xf14f, {0x04}, 0x01},
+	{PRO_DMOD, 0xf158, {0x7f}, 0x01},
+	{PRO_DMOD, 0xf15a, {0x00, 0x08}, 0x02},
+	{PRO_DMOD, 0xf15d, {0x03, 0x05}, 0x02},
+	{PRO_DMOD, 0xf163, {0x05}, 0x01},
+	{PRO_DMOD, 0xf166, {0x01, 0x40, 0x0f}, 0x03},
+	{PRO_DMOD, 0xf17a, {0x00, 0x00}, 0x02},
+	{PRO_DMOD, 0xf183, {0x01}, 0x01},
+	{PRO_DMOD, 0xf19d, {0x40}, 0x01},
+	{PRO_DMOD, 0xf1bc, {0x36, 0x00}, 0x02},
+	{PRO_DMOD, 0xf1cb, {0xa0, 0x01}, 0x02},
+	{PRO_DMOD, 0xf204, {0x10}, 0x01},
+	{PRO_DMOD, 0xf214, {0x00}, 0x01},
+	{PRO_DMOD, 0xf24c, {0x88, 0x95, 0x9a, 0x90}, 0x04},
+	{PRO_DMOD, 0xf25a, {0x07, 0xe8, 0x03, 0xb0, 0x04}, 0x05},
+	{PRO_DMOD, 0xf270, {0x01, 0x02, 0x01, 0x02}, 0x04},
+	{PRO_DMOD, 0xf40e, {0x0a, 0x40, 0x08}, 0x03},
+	{PRO_DMOD, 0xf55f, {0x0a}, 0x01},
+	{PRO_DMOD, 0xf561, {0x15, 0x20}, 0x02},
+	{PRO_DMOD, 0xf5e3, {0x09, 0x01, 0x01}, 0x03},
+	{PRO_DMOD, 0xf600, {	0x05, 0x08, 0x0b, 0x0e, 0x11, 0x14, 0x17,
+				0x1f}, 0x08},
+	{PRO_DMOD, 0xf60e, {0x00, 0x04, 0x32, 0x10}, 0x04},
+	{PRO_DMOD, 0xf707, {0xfc, 0x00, 0x37, 0x00}, 0x04},
+	{PRO_DMOD, 0xf78b, {0x01}, 0x01},
+	{PRO_DMOD, 0xf80f, {0x40, 0x54, 0x5a}, 0x03},
+	{PRO_DMOD, 0xf905, {0x01}, 0x01},
+	{PRO_DMOD, 0xfb06, {0x03}, 0x01},
+	{PRO_DMOD, 0xfd8b, {0x00}, 0x01},
+	{0xff, 0x0000, {0x00}, 0x00} /* Terminating Entry */
+};
+
+/* Tuner setting scripts (still keeping it9137) */
+static struct it913xset it9137_tuner_off[] = {
+	{PRO_DMOD, 0xfba8, {0x01}, 0x01}, /* Tuner Clock Off  */
+	{PRO_DMOD, 0xec40, {0x00}, 0x01}, /* Power Down Tuner */
+	{PRO_DMOD, 0xec02, {0x3f, 0x1f, 0x3f, 0x3f}, 0x04},
+	{PRO_DMOD, 0xec06, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+				0x00, 0x00, 0x00, 0x00}, 0x0c},
+	{PRO_DMOD, 0xec12, {0x00, 0x00, 0x00, 0x00}, 0x04},
+	{PRO_DMOD, 0xec17, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+				0x00}, 0x09},
+	{PRO_DMOD, 0xec22, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+				0x00, 0x00}, 0x0a},
+	{PRO_DMOD, 0xec20, {0x00}, 0x01},
+	{PRO_DMOD, 0xec3f, {0x01}, 0x01},
+	{0xff, 0x0000, {0x00}, 0x00}, /* Terminating Entry */
+};
+
+static struct it913xset set_it9135_template[] = {
+	{PRO_DMOD, 0xee06, {0x00}, 0x01},
+	{PRO_DMOD, 0xec56, {0x00}, 0x01},
+	{PRO_DMOD, 0xec4c, {0x00}, 0x01},
+	{PRO_DMOD, 0xec4d, {0x00}, 0x01},
+	{PRO_DMOD, 0xec4e, {0x00}, 0x01},
+	{PRO_DMOD, 0x011e, {0x00}, 0x01}, /* Older Devices */
+	{PRO_DMOD, 0x011f, {0x00}, 0x01},
+	{0xff, 0x0000, {0x00}, 0x00}, /* Terminating Entry */
+};
+
+static struct it913xset set_it9137_template[] = {
+	{PRO_DMOD, 0xee06, {0x00}, 0x01},
+	{PRO_DMOD, 0xec56, {0x00}, 0x01},
+	{PRO_DMOD, 0xec4c, {0x00}, 0x01},
+	{PRO_DMOD, 0xec4d, {0x00}, 0x01},
+	{PRO_DMOD, 0xec4e, {0x00}, 0x01},
+	{PRO_DMOD, 0xec4f, {0x00}, 0x01},
+	{PRO_DMOD, 0xec50, {0x00}, 0x01},
+	{0xff, 0x0000, {0x00}, 0x00}, /* Terminating Entry */
+};
diff --git a/drivers/media/dvb-frontends/it913x-fe.c b/drivers/media/dvb-frontends/it913x-fe.c
new file mode 100644
index 0000000..6e1c6eb
--- /dev/null
+++ b/drivers/media/dvb-frontends/it913x-fe.c
@@ -0,0 +1,1045 @@
+/*
+ *  Driver for it913x-fe Frontend
+ *
+ *  with support for on chip it9137 integral tuner
+ *
+ *  Copyright (C) 2011 Malcolm Priestley (tvboxspy@gmail.com)
+ *  IT9137 Copyright (C) ITE Tech Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.=
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#include "dvb_frontend.h"
+#include "it913x-fe.h"
+#include "it913x-fe-priv.h"
+
+static int it913x_debug;
+
+module_param_named(debug, it913x_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able)).");
+
+#define dprintk(level, args...) do { \
+	if (level & it913x_debug) \
+		printk(KERN_DEBUG "it913x-fe: " args); \
+} while (0)
+
+#define deb_info(args...)  dprintk(0x01, args)
+#define debug_data_snipet(level, name, p) \
+	  dprintk(level, name" (%02x%02x%02x%02x%02x%02x%02x%02x)", \
+		*p, *(p+1), *(p+2), *(p+3), *(p+4), \
+			*(p+5), *(p+6), *(p+7));
+#define info(format, arg...) \
+	printk(KERN_INFO "it913x-fe: " format "\n" , ## arg)
+
+struct it913x_fe_state {
+	struct dvb_frontend frontend;
+	struct i2c_adapter *i2c_adap;
+	struct ite_config *config;
+	u8 i2c_addr;
+	u32 frequency;
+	fe_modulation_t constellation;
+	fe_transmit_mode_t transmission_mode;
+	u8 priority;
+	u32 crystalFrequency;
+	u32 adcFrequency;
+	u8 tuner_type;
+	struct adctable *table;
+	fe_status_t it913x_status;
+	u16 tun_xtal;
+	u8 tun_fdiv;
+	u8 tun_clk_mode;
+	u32 tun_fn_min;
+	u32 ucblocks;
+};
+
+static int it913x_read_reg(struct it913x_fe_state *state,
+		u32 reg, u8 *data, u8 count)
+{
+	int ret;
+	u8 pro = PRO_DMOD; /* All reads from demodulator */
+	u8 b[4];
+	struct i2c_msg msg[2] = {
+		{ .addr = state->i2c_addr + (pro << 1), .flags = 0,
+			.buf = b, .len = sizeof(b) },
+		{ .addr = state->i2c_addr + (pro << 1), .flags = I2C_M_RD,
+			.buf = data, .len = count }
+	};
+	b[0] = (u8) reg >> 24;
+	b[1] = (u8)(reg >> 16) & 0xff;
+	b[2] = (u8)(reg >> 8) & 0xff;
+	b[3] = (u8) reg & 0xff;
+
+	ret = i2c_transfer(state->i2c_adap, msg, 2);
+
+	return ret;
+}
+
+static int it913x_read_reg_u8(struct it913x_fe_state *state, u32 reg)
+{
+	int ret;
+	u8 b[1];
+	ret = it913x_read_reg(state, reg, &b[0], sizeof(b));
+	return (ret < 0) ? -ENODEV : b[0];
+}
+
+static int it913x_write(struct it913x_fe_state *state,
+		u8 pro, u32 reg, u8 buf[], u8 count)
+{
+	u8 b[256];
+	struct i2c_msg msg[1] = {
+		{ .addr = state->i2c_addr + (pro << 1), .flags = 0,
+		  .buf = b, .len = count + 4 }
+	};
+	int ret;
+
+	b[0] = (u8) reg >> 24;
+	b[1] = (u8)(reg >> 16) & 0xff;
+	b[2] = (u8)(reg >> 8) & 0xff;
+	b[3] = (u8) reg & 0xff;
+	memcpy(&b[4], buf, count);
+
+	ret = i2c_transfer(state->i2c_adap, msg, 1);
+
+	if (ret < 0)
+		return -EIO;
+
+	return 0;
+}
+
+static int it913x_write_reg(struct it913x_fe_state *state,
+		u8 pro, u32 reg, u32 data)
+{
+	int ret;
+	u8 b[4];
+	u8 s;
+
+	b[0] = data >> 24;
+	b[1] = (data >> 16) & 0xff;
+	b[2] = (data >> 8) & 0xff;
+	b[3] = data & 0xff;
+	/* expand write as needed */
+	if (data < 0x100)
+		s = 3;
+	else if (data < 0x1000)
+		s = 2;
+	else if (data < 0x100000)
+		s = 1;
+	else
+		s = 0;
+
+	ret = it913x_write(state, pro, reg, &b[s], sizeof(b) - s);
+
+	return ret;
+}
+
+static int it913x_fe_script_loader(struct it913x_fe_state *state,
+		struct it913xset *loadscript)
+{
+	int ret, i;
+	if (loadscript == NULL)
+		return -EINVAL;
+
+	for (i = 0; i < 1000; ++i) {
+		if (loadscript[i].pro == 0xff)
+			break;
+		ret = it913x_write(state, loadscript[i].pro,
+			loadscript[i].address,
+			loadscript[i].reg, loadscript[i].count);
+		if (ret < 0)
+			return -ENODEV;
+	}
+	return 0;
+}
+
+static int it913x_init_tuner(struct it913x_fe_state *state)
+{
+	int ret, i, reg;
+	u8 val, nv_val;
+	u8 nv[] = {48, 32, 24, 16, 12, 8, 6, 4, 2};
+	u8 b[2];
+
+	reg = it913x_read_reg_u8(state, 0xec86);
+	switch (reg) {
+	case 0:
+		state->tun_clk_mode = reg;
+		state->tun_xtal = 2000;
+		state->tun_fdiv = 3;
+		val = 16;
+		break;
+	case -ENODEV:
+		return -ENODEV;
+	case 1:
+	default:
+		state->tun_clk_mode = reg;
+		state->tun_xtal = 640;
+		state->tun_fdiv = 1;
+		val = 6;
+		break;
+	}
+
+	reg = it913x_read_reg_u8(state, 0xed03);
+
+	if (reg < 0)
+		return -ENODEV;
+	else if (reg < ARRAY_SIZE(nv))
+		nv_val = nv[reg];
+	else
+		nv_val = 2;
+
+	for (i = 0; i < 50; i++) {
+		ret = it913x_read_reg(state, 0xed23, &b[0], sizeof(b));
+		reg = (b[1] << 8) + b[0];
+		if (reg > 0)
+			break;
+		if (ret < 0)
+			return -ENODEV;
+		udelay(2000);
+	}
+	state->tun_fn_min = state->tun_xtal * reg;
+	state->tun_fn_min /= (state->tun_fdiv * nv_val);
+	deb_info("Tuner fn_min %d", state->tun_fn_min);
+
+	if (state->config->chip_ver > 1)
+		msleep(50);
+	else {
+		for (i = 0; i < 50; i++) {
+			reg = it913x_read_reg_u8(state, 0xec82);
+			if (reg > 0)
+				break;
+			if (reg < 0)
+				return -ENODEV;
+			udelay(2000);
+		}
+	}
+
+	return it913x_write_reg(state, PRO_DMOD, 0xed81, val);
+}
+
+static int it9137_set_tuner(struct it913x_fe_state *state,
+		u32 bandwidth, u32 frequency_m)
+{
+	struct it913xset *set_tuner = set_it9137_template;
+	int ret, reg;
+	u32 frequency = frequency_m / 1000;
+	u32 freq, temp_f, tmp;
+	u16 iqik_m_cal;
+	u16 n_div;
+	u8 n;
+	u8 l_band;
+	u8 lna_band;
+	u8 bw;
+
+	if (state->config->firmware_ver == 1)
+		set_tuner = set_it9135_template;
+	else
+		set_tuner = set_it9137_template;
+
+	deb_info("Tuner Frequency %d Bandwidth %d", frequency, bandwidth);
+
+	if (frequency >= 51000 && frequency <= 440000) {
+		l_band = 0;
+		lna_band = 0;
+	} else if (frequency > 440000 && frequency <= 484000) {
+		l_band = 1;
+		lna_band = 1;
+	} else if (frequency > 484000 && frequency <= 533000) {
+		l_band = 1;
+		lna_band = 2;
+	} else if (frequency > 533000 && frequency <= 587000) {
+		l_band = 1;
+		lna_band = 3;
+	} else if (frequency > 587000 && frequency <= 645000) {
+		l_band = 1;
+		lna_band = 4;
+	} else if (frequency > 645000 && frequency <= 710000) {
+		l_band = 1;
+		lna_band = 5;
+	} else if (frequency > 710000 && frequency <= 782000) {
+		l_band = 1;
+		lna_band = 6;
+	} else if (frequency > 782000 && frequency <= 860000) {
+		l_band = 1;
+		lna_band = 7;
+	} else if (frequency > 1450000 && frequency <= 1492000) {
+		l_band = 1;
+		lna_band = 0;
+	} else if (frequency > 1660000 && frequency <= 1685000) {
+		l_band = 1;
+		lna_band = 1;
+	} else
+		return -EINVAL;
+	set_tuner[0].reg[0] = lna_band;
+
+	switch (bandwidth) {
+	case 5000000:
+		bw = 0;
+		break;
+	case 6000000:
+		bw = 2;
+		break;
+	case 7000000:
+		bw = 4;
+		break;
+	default:
+	case 8000000:
+		bw = 6;
+		break;
+	}
+
+	set_tuner[1].reg[0] = bw;
+	set_tuner[2].reg[0] = 0xa0 | (l_band << 3);
+
+	if (frequency > 53000 && frequency <= 74000) {
+		n_div = 48;
+		n = 0;
+	} else if (frequency > 74000 && frequency <= 111000) {
+		n_div = 32;
+		n = 1;
+	} else if (frequency > 111000 && frequency <= 148000) {
+		n_div = 24;
+		n = 2;
+	} else if (frequency > 148000 && frequency <= 222000) {
+		n_div = 16;
+		n = 3;
+	} else if (frequency > 222000 && frequency <= 296000) {
+		n_div = 12;
+		n = 4;
+	} else if (frequency > 296000 && frequency <= 445000) {
+		n_div = 8;
+		n = 5;
+	} else if (frequency > 445000 && frequency <= state->tun_fn_min) {
+		n_div = 6;
+		n = 6;
+	} else if (frequency > state->tun_fn_min && frequency <= 950000) {
+		n_div = 4;
+		n = 7;
+	} else if (frequency > 1450000 && frequency <= 1680000) {
+		n_div = 2;
+		n = 0;
+	} else
+		return -EINVAL;
+
+	reg = it913x_read_reg_u8(state, 0xed81);
+	iqik_m_cal = (u16)reg * n_div;
+
+	if (reg < 0x20) {
+		if (state->tun_clk_mode == 0)
+			iqik_m_cal = (iqik_m_cal * 9) >> 5;
+		else
+			iqik_m_cal >>= 1;
+	} else {
+		iqik_m_cal = 0x40 - iqik_m_cal;
+		if (state->tun_clk_mode == 0)
+			iqik_m_cal = ~((iqik_m_cal * 9) >> 5);
+		else
+			iqik_m_cal = ~(iqik_m_cal >> 1);
+	}
+
+	temp_f = frequency * (u32)n_div * (u32)state->tun_fdiv;
+	freq = temp_f / state->tun_xtal;
+	tmp = freq * state->tun_xtal;
+
+	if ((temp_f - tmp) >= (state->tun_xtal >> 1))
+		freq++;
+
+	freq += (u32) n << 13;
+	/* Frequency OMEGA_IQIK_M_CAL_MID*/
+	temp_f = freq + (u32)iqik_m_cal;
+
+	set_tuner[3].reg[0] =  temp_f & 0xff;
+	set_tuner[4].reg[0] =  (temp_f >> 8) & 0xff;
+
+	deb_info("High Frequency = %04x", temp_f);
+
+	/* Lower frequency */
+	set_tuner[5].reg[0] =  freq & 0xff;
+	set_tuner[6].reg[0] =  (freq >> 8) & 0xff;
+
+	deb_info("low Frequency = %04x", freq);
+
+	ret = it913x_fe_script_loader(state, set_tuner);
+
+	return (ret < 0) ? -ENODEV : 0;
+}
+
+static int it913x_fe_select_bw(struct it913x_fe_state *state,
+			u32 bandwidth, u32 adcFrequency)
+{
+	int ret, i;
+	u8 buffer[256];
+	u32 coeff[8];
+	u16 bfsfcw_fftinx_ratio;
+	u16 fftinx_bfsfcw_ratio;
+	u8 count;
+	u8 bw;
+	u8 adcmultiplier;
+
+	deb_info("Bandwidth %d Adc %d", bandwidth, adcFrequency);
+
+	switch (bandwidth) {
+	case 5000000:
+		bw = 3;
+		break;
+	case 6000000:
+		bw = 0;
+		break;
+	case 7000000:
+		bw = 1;
+		break;
+	default:
+	case 8000000:
+		bw = 2;
+		break;
+	}
+	ret = it913x_write_reg(state, PRO_DMOD, REG_BW, bw);
+
+	if (state->table == NULL)
+		return -EINVAL;
+
+	/* In write order */
+	coeff[0] = state->table[bw].coeff_1_2048;
+	coeff[1] = state->table[bw].coeff_2_2k;
+	coeff[2] = state->table[bw].coeff_1_8191;
+	coeff[3] = state->table[bw].coeff_1_8192;
+	coeff[4] = state->table[bw].coeff_1_8193;
+	coeff[5] = state->table[bw].coeff_2_8k;
+	coeff[6] = state->table[bw].coeff_1_4096;
+	coeff[7] = state->table[bw].coeff_2_4k;
+	bfsfcw_fftinx_ratio = state->table[bw].bfsfcw_fftinx_ratio;
+	fftinx_bfsfcw_ratio = state->table[bw].fftinx_bfsfcw_ratio;
+
+	/* ADC multiplier */
+	ret = it913x_read_reg_u8(state, ADC_X_2);
+	if (ret < 0)
+		return -EINVAL;
+
+	adcmultiplier = ret;
+
+	count = 0;
+
+	/*  Build Buffer for COEFF Registers */
+	for (i = 0; i < 8; i++) {
+		if (adcmultiplier == 1)
+			coeff[i] /= 2;
+		buffer[count++] = (coeff[i] >> 24) & 0x3;
+		buffer[count++] = (coeff[i] >> 16) & 0xff;
+		buffer[count++] = (coeff[i] >> 8) & 0xff;
+		buffer[count++] = coeff[i] & 0xff;
+	}
+
+	/* bfsfcw_fftinx_ratio register 0x21-0x22 */
+	buffer[count++] = bfsfcw_fftinx_ratio & 0xff;
+	buffer[count++] = (bfsfcw_fftinx_ratio >> 8) & 0xff;
+	/* fftinx_bfsfcw_ratio register 0x23-0x24 */
+	buffer[count++] = fftinx_bfsfcw_ratio & 0xff;
+	buffer[count++] = (fftinx_bfsfcw_ratio >> 8) & 0xff;
+	/* start at COEFF_1_2048 and write through to fftinx_bfsfcw_ratio*/
+	ret = it913x_write(state, PRO_DMOD, COEFF_1_2048, buffer, count);
+
+	for (i = 0; i < 42; i += 8)
+		debug_data_snipet(0x1, "Buffer", &buffer[i]);
+
+	return ret;
+}
+
+
+
+static int it913x_fe_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+	struct it913x_fe_state *state = fe->demodulator_priv;
+	int ret, i;
+	fe_status_t old_status = state->it913x_status;
+	*status = 0;
+
+	if (state->it913x_status == 0) {
+		ret = it913x_read_reg_u8(state, EMPTY_CHANNEL_STATUS);
+		if (ret == 0x1) {
+			*status |= FE_HAS_SIGNAL;
+			for (i = 0; i < 40; i++) {
+				ret = it913x_read_reg_u8(state, MP2IF_SYNC_LK);
+				if (ret == 0x1)
+					break;
+				msleep(25);
+			}
+			if (ret == 0x1)
+				*status |= FE_HAS_CARRIER
+					| FE_HAS_VITERBI
+					| FE_HAS_SYNC;
+			state->it913x_status = *status;
+		}
+	}
+
+	if (state->it913x_status & FE_HAS_SYNC) {
+		ret = it913x_read_reg_u8(state, TPSD_LOCK);
+		if (ret == 0x1)
+			*status |= FE_HAS_LOCK
+				| state->it913x_status;
+		else
+			state->it913x_status = 0;
+		if (old_status != state->it913x_status)
+			ret = it913x_write_reg(state, PRO_LINK, GPIOH3_O, ret);
+	}
+
+	return 0;
+}
+
+/* FEC values based on fe_code_rate_t non supported values 0*/
+int it913x_qpsk_pval[] = {0, -93, -91, -90, 0, -89, -88};
+int it913x_16qam_pval[] = {0, -87, -85, -84, 0, -83, -82};
+int it913x_64qam_pval[] = {0, -82, -80, -78, 0, -77, -76};
+
+static int it913x_get_signal_strength(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct it913x_fe_state *state = fe->demodulator_priv;
+	u8 code_rate;
+	int ret, temp;
+	u8 lna_gain_os;
+
+	ret = it913x_read_reg_u8(state, VAR_P_INBAND);
+	if (ret < 0)
+		return ret;
+
+	/* VHF/UHF gain offset */
+	if (state->frequency < 300000000)
+		lna_gain_os = 7;
+	else
+		lna_gain_os = 14;
+
+	temp = (ret - 100) - lna_gain_os;
+
+	if (state->priority == PRIORITY_HIGH)
+		code_rate = p->code_rate_HP;
+	else
+		code_rate = p->code_rate_LP;
+
+	if (code_rate >= ARRAY_SIZE(it913x_qpsk_pval))
+		return -EINVAL;
+
+	deb_info("Reg VAR_P_INBAND:%d Calc Offset Value:%d", ret, temp);
+
+	/* Apply FEC offset values*/
+	switch (p->modulation) {
+	case QPSK:
+		temp -= it913x_qpsk_pval[code_rate];
+		break;
+	case QAM_16:
+		temp -= it913x_16qam_pval[code_rate];
+		break;
+	case QAM_64:
+		temp -= it913x_64qam_pval[code_rate];
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (temp < -15)
+		ret = 0;
+	else if ((-15 <= temp) && (temp < 0))
+		ret = (2 * (temp + 15)) / 3;
+	else if ((0 <= temp) && (temp < 20))
+		ret = 4 * temp + 10;
+	else if ((20 <= temp) && (temp < 35))
+		ret = (2 * (temp - 20)) / 3 + 90;
+	else if (temp >= 35)
+		ret = 100;
+
+	deb_info("Signal Strength :%d", ret);
+
+	return ret;
+}
+
+static int it913x_fe_read_signal_strength(struct dvb_frontend *fe,
+		u16 *strength)
+{
+	struct it913x_fe_state *state = fe->demodulator_priv;
+	int ret = 0;
+	if (state->config->read_slevel) {
+		if (state->it913x_status & FE_HAS_SIGNAL)
+			ret = it913x_read_reg_u8(state, SIGNAL_LEVEL);
+	} else
+		ret = it913x_get_signal_strength(fe);
+
+	if (ret >= 0)
+		*strength = (u16)((u32)ret * 0xffff / 0x64);
+
+	return (ret < 0) ? -ENODEV : 0;
+}
+
+static int it913x_fe_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+	struct it913x_fe_state *state = fe->demodulator_priv;
+	int ret;
+	u8 reg[3];
+	u32 snr_val, snr_min, snr_max;
+	u32 temp;
+
+	ret = it913x_read_reg(state, 0x2c, reg, sizeof(reg));
+
+	snr_val = (u32)(reg[2] << 16) | (reg[1] << 8) | reg[0];
+
+	ret |= it913x_read_reg(state, 0xf78b, reg, 1);
+	if (reg[0])
+		snr_val /= reg[0];
+
+	if (state->transmission_mode == TRANSMISSION_MODE_2K)
+		snr_val *= 4;
+	else if (state->transmission_mode == TRANSMISSION_MODE_4K)
+		snr_val *= 2;
+
+	if (state->constellation == QPSK) {
+		snr_min = 0xb4711;
+		snr_max = 0x191451;
+	} else if (state->constellation == QAM_16) {
+		snr_min = 0x4f0d5;
+		snr_max = 0xc7925;
+	} else if (state->constellation == QAM_64) {
+		snr_min = 0x256d0;
+		snr_max = 0x626be;
+	} else
+		return -EINVAL;
+
+	if (snr_val < snr_min)
+		*snr = 0;
+	else if (snr_val < snr_max) {
+		temp = (snr_val - snr_min) >> 5;
+		temp *= 0xffff;
+		temp /= (snr_max - snr_min) >> 5;
+		*snr = (u16)temp;
+	} else
+		*snr = 0xffff;
+
+	return (ret < 0) ? -ENODEV : 0;
+}
+
+static int it913x_fe_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+	struct it913x_fe_state *state = fe->demodulator_priv;
+	u8 reg[5];
+	/* Read Aborted Packets and Pre-Viterbi error rate 5 bytes */
+	it913x_read_reg(state, RSD_ABORT_PKT_LSB, reg, sizeof(reg));
+	state->ucblocks += (u32)(reg[1] << 8) | reg[0];
+	*ber = (u32)(reg[4] << 16) | (reg[3] << 8) | reg[2];
+	return 0;
+}
+
+static int it913x_fe_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+	struct it913x_fe_state *state = fe->demodulator_priv;
+	int ret;
+	u8 reg[2];
+	/* Aborted Packets */
+	ret = it913x_read_reg(state, RSD_ABORT_PKT_LSB, reg, sizeof(reg));
+	state->ucblocks += (u32)(reg[1] << 8) | reg[0];
+	*ucblocks = state->ucblocks;
+	return ret;
+}
+
+static int it913x_fe_get_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct it913x_fe_state *state = fe->demodulator_priv;
+	u8 reg[8];
+
+	it913x_read_reg(state, REG_TPSD_TX_MODE, reg, sizeof(reg));
+
+	if (reg[3] < 3)
+		p->modulation = fe_con[reg[3]];
+
+	if (reg[0] < 3)
+		p->transmission_mode = fe_mode[reg[0]];
+
+	if (reg[1] < 4)
+		p->guard_interval = fe_gi[reg[1]];
+
+	if (reg[2] < 4)
+		p->hierarchy = fe_hi[reg[2]];
+
+	state->priority = reg[5];
+
+	p->code_rate_HP = (reg[6] < 6) ? fe_code[reg[6]] : FEC_NONE;
+	p->code_rate_LP = (reg[7] < 6) ? fe_code[reg[7]] : FEC_NONE;
+
+	/* Update internal state to reflect the autodetected props */
+	state->constellation = p->modulation;
+	state->transmission_mode = p->transmission_mode;
+
+	return 0;
+}
+
+static int it913x_fe_set_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct it913x_fe_state *state = fe->demodulator_priv;
+	int i;
+	u8 empty_ch, last_ch;
+
+	state->it913x_status = 0;
+
+	/* Set bw*/
+	it913x_fe_select_bw(state, p->bandwidth_hz,
+		state->adcFrequency);
+
+	/* Training Mode Off */
+	it913x_write_reg(state, PRO_LINK, TRAINING_MODE, 0x0);
+
+	/* Clear Empty Channel */
+	it913x_write_reg(state, PRO_DMOD, EMPTY_CHANNEL_STATUS, 0x0);
+
+	/* Clear bits */
+	it913x_write_reg(state, PRO_DMOD, MP2IF_SYNC_LK, 0x0);
+	/* LED on */
+	it913x_write_reg(state, PRO_LINK, GPIOH3_O, 0x1);
+	/* Select Band*/
+	if ((p->frequency >= 51000000) && (p->frequency <= 230000000))
+		i = 0;
+	else if ((p->frequency >= 350000000) && (p->frequency <= 900000000))
+			i = 1;
+	else if ((p->frequency >= 1450000000) && (p->frequency <= 1680000000))
+			i = 2;
+	else
+		return -EOPNOTSUPP;
+
+	it913x_write_reg(state, PRO_DMOD, FREE_BAND, i);
+
+	deb_info("Frontend Set Tuner Type %02x", state->tuner_type);
+	switch (state->tuner_type) {
+	case IT9135_38:
+	case IT9135_51:
+	case IT9135_52:
+	case IT9135_60:
+	case IT9135_61:
+	case IT9135_62:
+		it9137_set_tuner(state,
+			p->bandwidth_hz, p->frequency);
+		break;
+	default:
+		if (fe->ops.tuner_ops.set_params) {
+			fe->ops.tuner_ops.set_params(fe);
+			if (fe->ops.i2c_gate_ctrl)
+				fe->ops.i2c_gate_ctrl(fe, 0);
+		}
+		break;
+	}
+	/* LED off */
+	it913x_write_reg(state, PRO_LINK, GPIOH3_O, 0x0);
+	/* Trigger ofsm */
+	it913x_write_reg(state, PRO_DMOD, TRIGGER_OFSM, 0x0);
+	last_ch = 2;
+	for (i = 0; i < 40; ++i) {
+		empty_ch = it913x_read_reg_u8(state, EMPTY_CHANNEL_STATUS);
+		if (last_ch == 1 && empty_ch == 1)
+			break;
+		if (last_ch == 2 && empty_ch == 2)
+			return 0;
+		last_ch = empty_ch;
+		msleep(25);
+	}
+	for (i = 0; i < 40; ++i) {
+		if (it913x_read_reg_u8(state, D_TPSD_LOCK) == 1)
+			break;
+		msleep(25);
+	}
+
+	state->frequency = p->frequency;
+	return 0;
+}
+
+static int it913x_fe_suspend(struct it913x_fe_state *state)
+{
+	int ret, i;
+	u8 b;
+
+	ret = it913x_write_reg(state, PRO_DMOD, SUSPEND_FLAG, 0x1);
+
+	ret |= it913x_write_reg(state, PRO_DMOD, TRIGGER_OFSM, 0x0);
+
+	for (i = 0; i < 128; i++) {
+		ret = it913x_read_reg(state, SUSPEND_FLAG, &b, 1);
+		if (ret < 0)
+			return -ENODEV;
+		if (b == 0)
+			break;
+
+	}
+
+	ret |= it913x_write_reg(state, PRO_DMOD, AFE_MEM0, 0x8);
+	/* Turn LED off */
+	ret |= it913x_write_reg(state, PRO_LINK, GPIOH3_O, 0x0);
+
+	ret |= it913x_fe_script_loader(state, it9137_tuner_off);
+
+	return (ret < 0) ? -ENODEV : 0;
+}
+
+/* Power sequence */
+/* Power Up	Tuner on -> Frontend suspend off -> Tuner clk on */
+/* Power Down	Frontend suspend on -> Tuner clk off -> Tuner off */
+
+static int it913x_fe_sleep(struct dvb_frontend *fe)
+{
+	struct it913x_fe_state *state = fe->demodulator_priv;
+	return it913x_fe_suspend(state);
+}
+
+static u32 compute_div(u32 a, u32 b, u32 x)
+{
+	u32 res = 0;
+	u32 c = 0;
+	u32 i = 0;
+
+	if (a > b) {
+		c = a / b;
+		a = a - c * b;
+	}
+
+	for (i = 0; i < x; i++) {
+		if (a >= b) {
+			res += 1;
+			a -= b;
+		}
+		a <<= 1;
+		res <<= 1;
+	}
+
+	res = (c << x) + res;
+
+	return res;
+}
+
+static int it913x_fe_start(struct it913x_fe_state *state)
+{
+	struct it913xset *set_lna;
+	struct it913xset *set_mode;
+	int ret;
+	u8 adf = (state->config->adf & 0xf);
+	u32 adc, xtal;
+	u8 b[4];
+
+	if (state->config->chip_ver == 1)
+		ret = it913x_init_tuner(state);
+
+	info("ADF table value	:%02x", adf);
+
+	if (adf < 10) {
+		state->crystalFrequency = fe_clockTable[adf].xtal ;
+		state->table = fe_clockTable[adf].table;
+		state->adcFrequency = state->table->adcFrequency;
+
+		adc = compute_div(state->adcFrequency, 1000000ul, 19ul);
+		xtal = compute_div(state->crystalFrequency, 1000000ul, 19ul);
+
+	} else
+		return -EINVAL;
+
+	/* Set LED indicator on GPIOH3 */
+	ret = it913x_write_reg(state, PRO_LINK, GPIOH3_EN, 0x1);
+	ret |= it913x_write_reg(state, PRO_LINK, GPIOH3_ON, 0x1);
+	ret |= it913x_write_reg(state, PRO_LINK, GPIOH3_O, 0x1);
+
+	ret |= it913x_write_reg(state, PRO_LINK, 0xf641, state->tuner_type);
+	ret |= it913x_write_reg(state, PRO_DMOD, 0xf5ca, 0x01);
+	ret |= it913x_write_reg(state, PRO_DMOD, 0xf715, 0x01);
+
+	b[0] = xtal & 0xff;
+	b[1] = (xtal >> 8) & 0xff;
+	b[2] = (xtal >> 16) & 0xff;
+	b[3] = (xtal >> 24);
+	ret |= it913x_write(state, PRO_DMOD, XTAL_CLK, b , 4);
+
+	b[0] = adc & 0xff;
+	b[1] = (adc >> 8) & 0xff;
+	b[2] = (adc >> 16) & 0xff;
+	ret |= it913x_write(state, PRO_DMOD, ADC_FREQ, b, 3);
+
+	if (state->config->adc_x2)
+		ret |= it913x_write_reg(state, PRO_DMOD, ADC_X_2, 0x01);
+	b[0] = 0;
+	b[1] = 0;
+	b[2] = 0;
+	ret |= it913x_write(state, PRO_DMOD, 0x0029, b, 3);
+
+	info("Crystal Frequency :%d Adc Frequency :%d ADC X2: %02x",
+		state->crystalFrequency, state->adcFrequency,
+			state->config->adc_x2);
+	deb_info("Xtal value :%04x Adc value :%04x", xtal, adc);
+
+	if (ret < 0)
+		return -ENODEV;
+
+	/* v1 or v2 tuner script */
+	if (state->config->chip_ver > 1)
+		ret = it913x_fe_script_loader(state, it9135_v2);
+	else
+		ret = it913x_fe_script_loader(state, it9135_v1);
+	if (ret < 0)
+		return ret;
+
+	/* LNA Scripts */
+	switch (state->tuner_type) {
+	case IT9135_51:
+		set_lna = it9135_51;
+		break;
+	case IT9135_52:
+		set_lna = it9135_52;
+		break;
+	case IT9135_60:
+		set_lna = it9135_60;
+		break;
+	case IT9135_61:
+		set_lna = it9135_61;
+		break;
+	case IT9135_62:
+		set_lna = it9135_62;
+		break;
+	case IT9135_38:
+	default:
+		set_lna = it9135_38;
+	}
+	info("Tuner LNA type :%02x", state->tuner_type);
+
+	ret = it913x_fe_script_loader(state, set_lna);
+	if (ret < 0)
+		return ret;
+
+	if (state->config->chip_ver == 2) {
+		ret = it913x_write_reg(state, PRO_DMOD, TRIGGER_OFSM, 0x1);
+		ret |= it913x_write_reg(state, PRO_LINK, PADODPU, 0x0);
+		ret |= it913x_write_reg(state, PRO_LINK, AGC_O_D, 0x0);
+		ret |= it913x_init_tuner(state);
+	}
+	if (ret < 0)
+		return -ENODEV;
+
+	/* Always solo frontend */
+	set_mode = set_solo_fe;
+	ret |= it913x_fe_script_loader(state, set_mode);
+
+	ret |= it913x_fe_suspend(state);
+	return (ret < 0) ? -ENODEV : 0;
+}
+
+static int it913x_fe_init(struct dvb_frontend *fe)
+{
+	struct it913x_fe_state *state = fe->demodulator_priv;
+	int ret = 0;
+	/* Power Up Tuner - common all versions */
+	ret = it913x_write_reg(state, PRO_DMOD, 0xec40, 0x1);
+
+	ret |= it913x_fe_script_loader(state, init_1);
+
+	ret |= it913x_write_reg(state, PRO_DMOD, AFE_MEM0, 0x0);
+
+	ret |= it913x_write_reg(state, PRO_DMOD, 0xfba8, 0x0);
+
+	return (ret < 0) ? -ENODEV : 0;
+}
+
+static void it913x_fe_release(struct dvb_frontend *fe)
+{
+	struct it913x_fe_state *state = fe->demodulator_priv;
+	kfree(state);
+}
+
+static struct dvb_frontend_ops it913x_fe_ofdm_ops;
+
+struct dvb_frontend *it913x_fe_attach(struct i2c_adapter *i2c_adap,
+		u8 i2c_addr, struct ite_config *config)
+{
+	struct it913x_fe_state *state = NULL;
+	int ret;
+
+	/* allocate memory for the internal state */
+	state = kzalloc(sizeof(struct it913x_fe_state), GFP_KERNEL);
+	if (state == NULL)
+		return NULL;
+	if (config == NULL)
+		goto error;
+
+	state->i2c_adap = i2c_adap;
+	state->i2c_addr = i2c_addr;
+	state->config = config;
+
+	switch (state->config->tuner_id_0) {
+	case IT9135_51:
+	case IT9135_52:
+	case IT9135_60:
+	case IT9135_61:
+	case IT9135_62:
+		state->tuner_type = state->config->tuner_id_0;
+		break;
+	default:
+	case IT9135_38:
+		state->tuner_type = IT9135_38;
+	}
+
+	ret = it913x_fe_start(state);
+	if (ret < 0)
+		goto error;
+
+
+	/* create dvb_frontend */
+	memcpy(&state->frontend.ops, &it913x_fe_ofdm_ops,
+			sizeof(struct dvb_frontend_ops));
+	state->frontend.demodulator_priv = state;
+
+	return &state->frontend;
+error:
+	kfree(state);
+	return NULL;
+}
+EXPORT_SYMBOL(it913x_fe_attach);
+
+static struct dvb_frontend_ops it913x_fe_ofdm_ops = {
+	.delsys = { SYS_DVBT },
+	.info = {
+		.name			= "it913x-fe DVB-T",
+		.frequency_min		= 51000000,
+		.frequency_max		= 1680000000,
+		.frequency_stepsize	= 62500,
+		.caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
+			FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
+			FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO |
+			FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
+			FE_CAN_TRANSMISSION_MODE_AUTO |
+			FE_CAN_GUARD_INTERVAL_AUTO |
+			FE_CAN_HIERARCHY_AUTO,
+	},
+
+	.release = it913x_fe_release,
+
+	.init = it913x_fe_init,
+	.sleep = it913x_fe_sleep,
+
+	.set_frontend = it913x_fe_set_frontend,
+	.get_frontend = it913x_fe_get_frontend,
+
+	.read_status = it913x_fe_read_status,
+	.read_signal_strength = it913x_fe_read_signal_strength,
+	.read_snr = it913x_fe_read_snr,
+	.read_ber = it913x_fe_read_ber,
+	.read_ucblocks = it913x_fe_read_ucblocks,
+};
+
+MODULE_DESCRIPTION("it913x Frontend and it9137 tuner");
+MODULE_AUTHOR("Malcolm Priestley tvboxspy@gmail.com");
+MODULE_VERSION("1.15");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb-frontends/it913x-fe.h b/drivers/media/dvb-frontends/it913x-fe.h
new file mode 100644
index 0000000..07fa459
--- /dev/null
+++ b/drivers/media/dvb-frontends/it913x-fe.h
@@ -0,0 +1,237 @@
+/*
+ *  Driver for it913x Frontend
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the 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 IT913X_FE_H
+#define IT913X_FE_H
+
+#include <linux/dvb/frontend.h>
+#include "dvb_frontend.h"
+
+struct ite_config {
+	u8 chip_ver;
+	u16 chip_type;
+	u32 firmware;
+	u8 firmware_ver;
+	u8 adc_x2;
+	u8 tuner_id_0;
+	u8 tuner_id_1;
+	u8 dual_mode;
+	u8 adf;
+	/* option to read SIGNAL_LEVEL */
+	u8 read_slevel;
+};
+
+#if defined(CONFIG_DVB_IT913X_FE) || (defined(CONFIG_DVB_IT913X_FE_MODULE) && \
+defined(MODULE))
+extern struct dvb_frontend *it913x_fe_attach(struct i2c_adapter *i2c_adap,
+			u8 i2c_addr, struct ite_config *config);
+#else
+static inline struct dvb_frontend *it913x_fe_attach(
+		struct i2c_adapter *i2c_adap,
+			u8 i2c_addr, struct ite_config *config)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif /* CONFIG_IT913X_FE */
+#define I2C_BASE_ADDR		0x10
+#define DEV_0			0x0
+#define DEV_1			0x10
+#define PRO_LINK		0x0
+#define PRO_DMOD		0x1
+#define DEV_0_DMOD		(PRO_DMOD << 0x7)
+#define DEV_1_DMOD		(DEV_0_DMOD | DEV_1)
+#define CHIP2_I2C_ADDR		0x3a
+
+#define AFE_MEM0		0xfb24
+
+#define MP2_SW_RST		0xf99d
+#define MP2IF2_SW_RST		0xf9a4
+
+#define	PADODPU			0xd827
+#define THIRDODPU		0xd828
+#define AGC_O_D			0xd829
+
+#define EP0_TX_EN		0xdd11
+#define EP0_TX_NAK		0xdd13
+#define EP4_TX_LEN_LSB		0xdd88
+#define EP4_TX_LEN_MSB		0xdd89
+#define EP4_MAX_PKT		0xdd0c
+#define EP5_TX_LEN_LSB		0xdd8a
+#define EP5_TX_LEN_MSB		0xdd8b
+#define EP5_MAX_PKT		0xdd0d
+
+#define IO_MUX_POWER_CLK	0xd800
+#define CLK_O_EN		0xd81a
+#define I2C_CLK			0xf103
+#define I2C_CLK_100		0x7
+#define I2C_CLK_400		0x1a
+
+#define D_TPSD_LOCK		0xf5a9
+#define MP2IF2_EN		0xf9a3
+#define MP2IF_SERIAL		0xf985
+#define TSIS_ENABLE		0xf9cd
+#define MP2IF2_HALF_PSB		0xf9a5
+#define MP2IF_STOP_EN		0xf9b5
+#define MPEG_FULL_SPEED		0xf990
+#define TOP_HOSTB_SER_MODE	0xd91c
+
+#define PID_RST			0xf992
+#define PID_EN			0xf993
+#define PID_INX_EN		0xf994
+#define PID_INX			0xf995
+#define PID_LSB			0xf996
+#define PID_MSB			0xf997
+
+#define MP2IF_MPEG_PAR_MODE	0xf986
+#define DCA_UPPER_CHIP		0xf731
+#define DCA_LOWER_CHIP		0xf732
+#define DCA_PLATCH		0xf730
+#define DCA_FPGA_LATCH		0xf778
+#define DCA_STAND_ALONE		0xf73c
+#define DCA_ENABLE		0xf776
+
+#define DVBT_INTEN		0xf41f
+#define DVBT_ENABLE		0xf41a
+#define HOSTB_DCA_LOWER		0xd91f
+#define HOSTB_MPEG_PAR_MODE	0xd91b
+#define HOSTB_MPEG_SER_MODE	0xd91c
+#define HOSTB_MPEG_SER_DO7	0xd91d
+#define HOSTB_DCA_UPPER		0xd91e
+#define PADMISCDR2		0xd830
+#define PADMISCDR4		0xd831
+#define PADMISCDR8		0xd832
+#define PADMISCDRSR		0xd833
+#define LOCK3_OUT		0xd8fd
+
+#define GPIOH1_O		0xd8af
+#define GPIOH1_EN		0xd8b0
+#define GPIOH1_ON		0xd8b1
+#define GPIOH3_O		0xd8b3
+#define GPIOH3_EN		0xd8b4
+#define GPIOH3_ON		0xd8b5
+#define GPIOH5_O		0xd8bb
+#define GPIOH5_EN		0xd8bc
+#define GPIOH5_ON		0xd8bd
+
+#define AFE_MEM0		0xfb24
+
+#define REG_TPSD_TX_MODE	0xf900
+#define REG_TPSD_GI		0xf901
+#define REG_TPSD_HIER		0xf902
+#define REG_TPSD_CONST		0xf903
+#define REG_BW			0xf904
+#define REG_PRIV		0xf905
+#define REG_TPSD_HP_CODE	0xf906
+#define REG_TPSD_LP_CODE	0xf907
+
+#define MP2IF_SYNC_LK		0xf999
+#define ADC_FREQ		0xf1cd
+
+#define TRIGGER_OFSM		0x0000
+/* COEFF Registers start at 0x0001 to 0x0020 */
+#define COEFF_1_2048		0x0001
+#define XTAL_CLK		0x0025
+#define BFS_FCW			0x0029
+
+/* Error Regs */
+#define RSD_ABORT_PKT_LSB	0x0032
+#define RSD_ABORT_PKT_MSB	0x0033
+#define RSD_BIT_ERR_0_7		0x0034
+#define RSD_BIT_ERR_8_15	0x0035
+#define RSD_BIT_ERR_23_16	0x0036
+#define RSD_BIT_COUNT_LSB	0x0037
+#define RSD_BIT_COUNT_MSB	0x0038
+
+#define TPSD_LOCK		0x003c
+#define TRAINING_MODE		0x0040
+#define ADC_X_2			0x0045
+#define TUNER_ID		0x0046
+#define EMPTY_CHANNEL_STATUS	0x0047
+#define SIGNAL_LEVEL		0x0048
+#define SIGNAL_QUALITY		0x0049
+#define EST_SIGNAL_LEVEL	0x004a
+#define FREE_BAND		0x004b
+#define SUSPEND_FLAG		0x004c
+#define VAR_P_INBAND		0x00f7
+
+/* Build in tuner types */
+#define IT9137 0x38
+#define IT9135_38 0x38
+#define IT9135_51 0x51
+#define IT9135_52 0x52
+#define IT9135_60 0x60
+#define IT9135_61 0x61
+#define IT9135_62 0x62
+
+enum {
+	CMD_DEMOD_READ = 0,
+	CMD_DEMOD_WRITE,
+	CMD_TUNER_READ,
+	CMD_TUNER_WRITE,
+	CMD_REG_EEPROM_READ,
+	CMD_REG_EEPROM_WRITE,
+	CMD_DATA_READ,
+	CMD_VAR_READ = 8,
+	CMD_VAR_WRITE,
+	CMD_PLATFORM_GET,
+	CMD_PLATFORM_SET,
+	CMD_IP_CACHE,
+	CMD_IP_ADD,
+	CMD_IP_REMOVE,
+	CMD_PID_ADD,
+	CMD_PID_REMOVE,
+	CMD_SIPSI_GET,
+	CMD_SIPSI_MPE_RESET,
+	CMD_H_PID_ADD = 0x15,
+	CMD_H_PID_REMOVE,
+	CMD_ABORT,
+	CMD_IR_GET,
+	CMD_IR_SET,
+	CMD_FW_DOWNLOAD = 0x21,
+	CMD_QUERYINFO,
+	CMD_BOOT,
+	CMD_FW_DOWNLOAD_BEGIN,
+	CMD_FW_DOWNLOAD_END,
+	CMD_RUN_CODE,
+	CMD_SCATTER_READ = 0x28,
+	CMD_SCATTER_WRITE,
+	CMD_GENERIC_READ,
+	CMD_GENERIC_WRITE
+};
+
+enum {
+	READ_LONG,
+	WRITE_LONG,
+	READ_SHORT,
+	WRITE_SHORT,
+	READ_DATA,
+	WRITE_DATA,
+	WRITE_CMD,
+};
+
+enum {
+	IT9135_AUTO = 0,
+	IT9137_FW,
+	IT9135_V1_FW,
+	IT9135_V2_FW,
+};
+
+#endif /* IT913X_FE_H */
diff --git a/drivers/media/dvb-frontends/itd1000.c b/drivers/media/dvb-frontends/itd1000.c
new file mode 100644
index 0000000..3164575
--- /dev/null
+++ b/drivers/media/dvb-frontends/itd1000.c
@@ -0,0 +1,399 @@
+/*
+ *  Driver for the Integrant ITD1000 "Zero-IF Tuner IC for Direct Broadcast Satellite"
+ *
+ *  Copyright (c) 2007-8 Patrick Boettcher <pb@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/module.h>
+#include <linux/moduleparam.h>
+#include <linux/delay.h>
+#include <linux/dvb/frontend.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+
+#include "dvb_frontend.h"
+
+#include "itd1000.h"
+#include "itd1000_priv.h"
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
+
+#define itd_dbg(args...)  do { \
+	if (debug) { \
+		printk(KERN_DEBUG   "ITD1000: " args);\
+	} \
+} while (0)
+
+#define itd_warn(args...) do { \
+	printk(KERN_WARNING "ITD1000: " args); \
+} while (0)
+
+#define itd_info(args...) do { \
+	printk(KERN_INFO    "ITD1000: " args); \
+} while (0)
+
+/* don't write more than one byte with flexcop behind */
+static int itd1000_write_regs(struct itd1000_state *state, u8 reg, u8 v[], u8 len)
+{
+	u8 buf[1+len];
+	struct i2c_msg msg = {
+		.addr = state->cfg->i2c_address, .flags = 0, .buf = buf, .len = len+1
+	};
+	buf[0] = reg;
+	memcpy(&buf[1], v, len);
+
+	/* itd_dbg("wr %02x: %02x\n", reg, v[0]); */
+
+	if (i2c_transfer(state->i2c, &msg, 1) != 1) {
+		printk(KERN_WARNING "itd1000 I2C write failed\n");
+		return -EREMOTEIO;
+	}
+	return 0;
+}
+
+static int itd1000_read_reg(struct itd1000_state *state, u8 reg)
+{
+	u8 val;
+	struct i2c_msg msg[2] = {
+		{ .addr = state->cfg->i2c_address, .flags = 0,        .buf = &reg, .len = 1 },
+		{ .addr = state->cfg->i2c_address, .flags = I2C_M_RD, .buf = &val, .len = 1 },
+	};
+
+	/* ugly flexcop workaround */
+	itd1000_write_regs(state, (reg - 1) & 0xff, &state->shadow[(reg - 1) & 0xff], 1);
+
+	if (i2c_transfer(state->i2c, msg, 2) != 2) {
+		itd_warn("itd1000 I2C read failed\n");
+		return -EREMOTEIO;
+	}
+	return val;
+}
+
+static inline int itd1000_write_reg(struct itd1000_state *state, u8 r, u8 v)
+{
+	int ret = itd1000_write_regs(state, r, &v, 1);
+	state->shadow[r] = v;
+	return ret;
+}
+
+
+static struct {
+	u32 symbol_rate;
+	u8  pgaext  : 4; /* PLLFH */
+	u8  bbgvmin : 4; /* BBGVMIN */
+} itd1000_lpf_pga[] = {
+	{        0, 0x8, 0x3 },
+	{  5200000, 0x8, 0x3 },
+	{ 12200000, 0x4, 0x3 },
+	{ 15400000, 0x2, 0x3 },
+	{ 19800000, 0x2, 0x3 },
+	{ 21500000, 0x2, 0x3 },
+	{ 24500000, 0x2, 0x3 },
+	{ 28400000, 0x2, 0x3 },
+	{ 33400000, 0x2, 0x3 },
+	{ 34400000, 0x1, 0x4 },
+	{ 34400000, 0x1, 0x4 },
+	{ 38400000, 0x1, 0x4 },
+	{ 38400000, 0x1, 0x4 },
+	{ 40400000, 0x1, 0x4 },
+	{ 45400000, 0x1, 0x4 },
+};
+
+static void itd1000_set_lpf_bw(struct itd1000_state *state, u32 symbol_rate)
+{
+	u8 i;
+	u8 con1    = itd1000_read_reg(state, CON1)    & 0xfd;
+	u8 pllfh   = itd1000_read_reg(state, PLLFH)   & 0x0f;
+	u8 bbgvmin = itd1000_read_reg(state, BBGVMIN) & 0xf0;
+	u8 bw      = itd1000_read_reg(state, BW)      & 0xf0;
+
+	itd_dbg("symbol_rate = %d\n", symbol_rate);
+
+	/* not sure what is that ? - starting to download the table */
+	itd1000_write_reg(state, CON1, con1 | (1 << 1));
+
+	for (i = 0; i < ARRAY_SIZE(itd1000_lpf_pga); i++)
+		if (symbol_rate < itd1000_lpf_pga[i].symbol_rate) {
+			itd_dbg("symrate: index: %d pgaext: %x, bbgvmin: %x\n", i, itd1000_lpf_pga[i].pgaext, itd1000_lpf_pga[i].bbgvmin);
+			itd1000_write_reg(state, PLLFH,   pllfh | (itd1000_lpf_pga[i].pgaext << 4));
+			itd1000_write_reg(state, BBGVMIN, bbgvmin | (itd1000_lpf_pga[i].bbgvmin));
+			itd1000_write_reg(state, BW,      bw | (i & 0x0f));
+			break;
+		}
+
+	itd1000_write_reg(state, CON1, con1 | (0 << 1));
+}
+
+static struct {
+	u8 vcorg;
+	u32 fmax_rg;
+} itd1000_vcorg[] = {
+	{  1,  920000 },
+	{  2,  971000 },
+	{  3, 1031000 },
+	{  4, 1091000 },
+	{  5, 1171000 },
+	{  6, 1281000 },
+	{  7, 1381000 },
+	{  8,  500000 },	/* this is intentional. */
+	{  9, 1451000 },
+	{ 10, 1531000 },
+	{ 11, 1631000 },
+	{ 12, 1741000 },
+	{ 13, 1891000 },
+	{ 14, 2071000 },
+	{ 15, 2250000 },
+};
+
+static void itd1000_set_vco(struct itd1000_state *state, u32 freq_khz)
+{
+	u8 i;
+	u8 gvbb_i2c     = itd1000_read_reg(state, GVBB_I2C) & 0xbf;
+	u8 vco_chp1_i2c = itd1000_read_reg(state, VCO_CHP1_I2C) & 0x0f;
+	u8 adcout;
+
+	/* reserved bit again (reset ?) */
+	itd1000_write_reg(state, GVBB_I2C, gvbb_i2c | (1 << 6));
+
+	for (i = 0; i < ARRAY_SIZE(itd1000_vcorg); i++) {
+		if (freq_khz < itd1000_vcorg[i].fmax_rg) {
+			itd1000_write_reg(state, VCO_CHP1_I2C, vco_chp1_i2c | (itd1000_vcorg[i].vcorg << 4));
+			msleep(1);
+
+			adcout = itd1000_read_reg(state, PLLLOCK) & 0x0f;
+
+			itd_dbg("VCO: %dkHz: %d -> ADCOUT: %d %02x\n", freq_khz, itd1000_vcorg[i].vcorg, adcout, vco_chp1_i2c);
+
+			if (adcout > 13) {
+				if (!(itd1000_vcorg[i].vcorg == 7 || itd1000_vcorg[i].vcorg == 15))
+					itd1000_write_reg(state, VCO_CHP1_I2C, vco_chp1_i2c | ((itd1000_vcorg[i].vcorg + 1) << 4));
+			} else if (adcout < 2) {
+				if (!(itd1000_vcorg[i].vcorg == 1 || itd1000_vcorg[i].vcorg == 9))
+					itd1000_write_reg(state, VCO_CHP1_I2C, vco_chp1_i2c | ((itd1000_vcorg[i].vcorg - 1) << 4));
+			}
+			break;
+		}
+	}
+}
+
+static const struct {
+	u32 freq;
+	u8 values[10]; /* RFTR, RFST1 - RFST9 */
+} itd1000_fre_values[] = {
+	{ 1075000, { 0x59, 0x1d, 0x1c, 0x17, 0x16, 0x0f, 0x0e, 0x0c, 0x0b, 0x0a } },
+	{ 1250000, { 0x89, 0x1e, 0x1d, 0x17, 0x15, 0x0f, 0x0e, 0x0c, 0x0b, 0x0a } },
+	{ 1450000, { 0x89, 0x1e, 0x1d, 0x17, 0x15, 0x0f, 0x0e, 0x0c, 0x0b, 0x0a } },
+	{ 1650000, { 0x69, 0x1e, 0x1d, 0x17, 0x15, 0x0f, 0x0e, 0x0c, 0x0b, 0x0a } },
+	{ 1750000, { 0x69, 0x1e, 0x17, 0x15, 0x14, 0x0f, 0x0e, 0x0c, 0x0b, 0x0a } },
+	{ 1850000, { 0x69, 0x1d, 0x17, 0x16, 0x14, 0x0f, 0x0e, 0x0d, 0x0b, 0x0a } },
+	{ 1900000, { 0x69, 0x1d, 0x17, 0x15, 0x14, 0x0f, 0x0e, 0x0d, 0x0b, 0x0a } },
+	{ 1950000, { 0x69, 0x1d, 0x17, 0x16, 0x14, 0x13, 0x0e, 0x0d, 0x0b, 0x0a } },
+	{ 2050000, { 0x69, 0x1e, 0x1d, 0x17, 0x16, 0x14, 0x13, 0x0e, 0x0b, 0x0a } },
+	{ 2150000, { 0x69, 0x1d, 0x1c, 0x17, 0x15, 0x14, 0x13, 0x0f, 0x0e, 0x0b } }
+};
+
+
+#define FREF 16
+
+static void itd1000_set_lo(struct itd1000_state *state, u32 freq_khz)
+{
+	int i, j;
+	u32 plln, pllf;
+	u64 tmp;
+
+	plln = (freq_khz * 1000) / 2 / FREF;
+
+	/* Compute the factional part times 1000 */
+	tmp  = plln % 1000000;
+	plln /= 1000000;
+
+	tmp *= 1048576;
+	do_div(tmp, 1000000);
+	pllf = (u32) tmp;
+
+	state->frequency = ((plln * 1000) + (pllf * 1000)/1048576) * 2*FREF;
+	itd_dbg("frequency: %dkHz (wanted) %dkHz (set), PLLF = %d, PLLN = %d\n", freq_khz, state->frequency, pllf, plln);
+
+	itd1000_write_reg(state, PLLNH, 0x80); /* PLLNH */;
+	itd1000_write_reg(state, PLLNL, plln & 0xff);
+	itd1000_write_reg(state, PLLFH, (itd1000_read_reg(state, PLLFH) & 0xf0) | ((pllf >> 16) & 0x0f));
+	itd1000_write_reg(state, PLLFM, (pllf >> 8) & 0xff);
+	itd1000_write_reg(state, PLLFL, (pllf >> 0) & 0xff);
+
+	for (i = 0; i < ARRAY_SIZE(itd1000_fre_values); i++) {
+		if (freq_khz <= itd1000_fre_values[i].freq) {
+			itd_dbg("fre_values: %d\n", i);
+			itd1000_write_reg(state, RFTR, itd1000_fre_values[i].values[0]);
+			for (j = 0; j < 9; j++)
+				itd1000_write_reg(state, RFST1+j, itd1000_fre_values[i].values[j+1]);
+			break;
+		}
+	}
+
+	itd1000_set_vco(state, freq_khz);
+}
+
+static int itd1000_set_parameters(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	struct itd1000_state *state = fe->tuner_priv;
+	u8 pllcon1;
+
+	itd1000_set_lo(state, c->frequency);
+	itd1000_set_lpf_bw(state, c->symbol_rate);
+
+	pllcon1 = itd1000_read_reg(state, PLLCON1) & 0x7f;
+	itd1000_write_reg(state, PLLCON1, pllcon1 | (1 << 7));
+	itd1000_write_reg(state, PLLCON1, pllcon1);
+
+	return 0;
+}
+
+static int itd1000_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+	struct itd1000_state *state = fe->tuner_priv;
+	*frequency = state->frequency;
+	return 0;
+}
+
+static int itd1000_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
+{
+	return 0;
+}
+
+static u8 itd1000_init_tab[][2] = {
+	{ PLLCON1,       0x65 }, /* Register does not change */
+	{ PLLNH,         0x80 }, /* Bits [7:6] do not change */
+	{ RESERVED_0X6D, 0x3b },
+	{ VCO_CHP2_I2C,  0x12 },
+	{ 0x72,          0xf9 }, /* No such regsister defined */
+	{ RESERVED_0X73, 0xff },
+	{ RESERVED_0X74, 0xb2 },
+	{ RESERVED_0X75, 0xc7 },
+	{ EXTGVBBRF,     0xf0 },
+	{ DIVAGCCK,      0x80 },
+	{ BBTR,          0xa0 },
+	{ RESERVED_0X7E, 0x4f },
+	{ 0x82,          0x88 }, /* No such regsister defined */
+	{ 0x83,          0x80 }, /* No such regsister defined */
+	{ 0x84,          0x80 }, /* No such regsister defined */
+	{ RESERVED_0X85, 0x74 },
+	{ RESERVED_0X86, 0xff },
+	{ RESERVED_0X88, 0x02 },
+	{ RESERVED_0X89, 0x16 },
+	{ RFST0,         0x1f },
+	{ RESERVED_0X94, 0x66 },
+	{ RESERVED_0X95, 0x66 },
+	{ RESERVED_0X96, 0x77 },
+	{ RESERVED_0X97, 0x99 },
+	{ RESERVED_0X98, 0xff },
+	{ RESERVED_0X99, 0xfc },
+	{ RESERVED_0X9A, 0xba },
+	{ RESERVED_0X9B, 0xaa },
+};
+
+static u8 itd1000_reinit_tab[][2] = {
+	{ VCO_CHP1_I2C, 0x8a },
+	{ BW,           0x87 },
+	{ GVBB_I2C,     0x03 },
+	{ BBGVMIN,      0x03 },
+	{ CON1,         0x2e },
+};
+
+
+static int itd1000_init(struct dvb_frontend *fe)
+{
+	struct itd1000_state *state = fe->tuner_priv;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(itd1000_init_tab); i++)
+		itd1000_write_reg(state, itd1000_init_tab[i][0], itd1000_init_tab[i][1]);
+
+	for (i = 0; i < ARRAY_SIZE(itd1000_reinit_tab); i++)
+		itd1000_write_reg(state, itd1000_reinit_tab[i][0], itd1000_reinit_tab[i][1]);
+
+	return 0;
+}
+
+static int itd1000_sleep(struct dvb_frontend *fe)
+{
+	return 0;
+}
+
+static int itd1000_release(struct dvb_frontend *fe)
+{
+	kfree(fe->tuner_priv);
+	fe->tuner_priv = NULL;
+	return 0;
+}
+
+static const struct dvb_tuner_ops itd1000_tuner_ops = {
+	.info = {
+		.name           = "Integrant ITD1000",
+		.frequency_min  = 950000,
+		.frequency_max  = 2150000,
+		.frequency_step = 125,     /* kHz for QPSK frontends */
+	},
+
+	.release       = itd1000_release,
+
+	.init          = itd1000_init,
+	.sleep         = itd1000_sleep,
+
+	.set_params    = itd1000_set_parameters,
+	.get_frequency = itd1000_get_frequency,
+	.get_bandwidth = itd1000_get_bandwidth
+};
+
+
+struct dvb_frontend *itd1000_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct itd1000_config *cfg)
+{
+	struct itd1000_state *state = NULL;
+	u8 i = 0;
+
+	state = kzalloc(sizeof(struct itd1000_state), GFP_KERNEL);
+	if (state == NULL)
+		return NULL;
+
+	state->cfg = cfg;
+	state->i2c = i2c;
+
+	i = itd1000_read_reg(state, 0);
+	if (i != 0) {
+		kfree(state);
+		return NULL;
+	}
+	itd_info("successfully identified (ID: %d)\n", i);
+
+	memset(state->shadow, 0xff, sizeof(state->shadow));
+	for (i = 0x65; i < 0x9c; i++)
+		state->shadow[i] = itd1000_read_reg(state, i);
+
+	memcpy(&fe->ops.tuner_ops, &itd1000_tuner_ops, sizeof(struct dvb_tuner_ops));
+
+	fe->tuner_priv = state;
+
+	return fe;
+}
+EXPORT_SYMBOL(itd1000_attach);
+
+MODULE_AUTHOR("Patrick Boettcher <pb@linuxtv.org>");
+MODULE_DESCRIPTION("Integrant ITD1000 driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb-frontends/itd1000.h b/drivers/media/dvb-frontends/itd1000.h
new file mode 100644
index 0000000..5e18df0
--- /dev/null
+++ b/drivers/media/dvb-frontends/itd1000.h
@@ -0,0 +1,42 @@
+/*
+ *  Driver for the Integrant ITD1000 "Zero-IF Tuner IC for Direct Broadcast Satellite"
+ *
+ *  Copyright (c) 2007 Patrick Boettcher <pb@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 ITD1000_H
+#define ITD1000_H
+
+struct dvb_frontend;
+struct i2c_adapter;
+
+struct itd1000_config {
+	u8 i2c_address;
+};
+
+#if defined(CONFIG_DVB_TUNER_ITD1000) || (defined(CONFIG_DVB_TUNER_ITD1000_MODULE) && defined(MODULE))
+extern struct dvb_frontend *itd1000_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct itd1000_config *cfg);
+#else
+static inline struct dvb_frontend *itd1000_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct itd1000_config *cfg)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif
+
+#endif
diff --git a/drivers/media/dvb-frontends/itd1000_priv.h b/drivers/media/dvb-frontends/itd1000_priv.h
new file mode 100644
index 0000000..08ca851
--- /dev/null
+++ b/drivers/media/dvb-frontends/itd1000_priv.h
@@ -0,0 +1,88 @@
+/*
+ *  Driver for the Integrant ITD1000 "Zero-IF Tuner IC for Direct Broadcast Satellite"
+ *
+ *  Copyright (c) 2007 Patrick Boettcher <pb@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 ITD1000_PRIV_H
+#define ITD1000_PRIV_H
+
+struct itd1000_state {
+	struct itd1000_config *cfg;
+	struct i2c_adapter    *i2c;
+
+	u32 frequency; /* contains the value resulting from the LO-setting */
+
+	/* ugly workaround for flexcop's incapable i2c-controller
+	 * FIXME, if possible
+	 */
+	u8 shadow[256];
+};
+
+enum itd1000_register {
+	VCO_CHP1 = 0x65,
+	VCO_CHP2,
+	PLLCON1,
+	PLLNH,
+	PLLNL,
+	PLLFH,
+	PLLFM,
+	PLLFL,
+	RESERVED_0X6D,
+	PLLLOCK,
+	VCO_CHP2_I2C,
+	VCO_CHP1_I2C,
+	BW,
+	RESERVED_0X73 = 0x73,
+	RESERVED_0X74,
+	RESERVED_0X75,
+	GVBB,
+	GVRF,
+	GVBB_I2C,
+	EXTGVBBRF,
+	DIVAGCCK,
+	BBTR,
+	RFTR,
+	BBGVMIN,
+	RESERVED_0X7E,
+	RESERVED_0X85 = 0x85,
+	RESERVED_0X86,
+	CON1,
+	RESERVED_0X88,
+	RESERVED_0X89,
+	RFST0,
+	RFST1,
+	RFST2,
+	RFST3,
+	RFST4,
+	RFST5,
+	RFST6,
+	RFST7,
+	RFST8,
+	RFST9,
+	RESERVED_0X94,
+	RESERVED_0X95,
+	RESERVED_0X96,
+	RESERVED_0X97,
+	RESERVED_0X98,
+	RESERVED_0X99,
+	RESERVED_0X9A,
+	RESERVED_0X9B,
+};
+
+#endif
diff --git a/drivers/media/dvb-frontends/ix2505v.c b/drivers/media/dvb-frontends/ix2505v.c
new file mode 100644
index 0000000..bc5a820
--- /dev/null
+++ b/drivers/media/dvb-frontends/ix2505v.c
@@ -0,0 +1,325 @@
+/**
+ * Driver for Sharp IX2505V (marked B0017) DVB-S silicon tuner
+ *
+ * Copyright (C) 2010 Malcolm Priestley
+ *
+ * This program is free software; you can 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.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/dvb/frontend.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#include "ix2505v.h"
+
+static int ix2505v_debug;
+#define dprintk(level, args...) do { \
+	if (ix2505v_debug & level) \
+		printk(KERN_DEBUG "ix2505v: " args); \
+} while (0)
+
+#define deb_info(args...)  dprintk(0x01, args)
+#define deb_i2c(args...)  dprintk(0x02, args)
+
+struct ix2505v_state {
+	struct i2c_adapter *i2c;
+	const struct ix2505v_config *config;
+	u32 frequency;
+};
+
+/**
+ *  Data read format of the Sharp IX2505V B0017
+ *
+ *  byte1:   1   |   1   |   0   |   0   |   0   |  MA1  |  MA0  |  1
+ *  byte2:  POR  |   FL  |  RD2  |  RD1  |  RD0  |   X   |   X   |  X
+ *
+ *  byte1 = address
+ *  byte2;
+ *	POR = Power on Reset (VCC H=<2.2v L=>2.2v)
+ *	FL  = Phase Lock (H=lock L=unlock)
+ *	RD0-2 = Reserved internal operations
+ *
+ * Only POR can be used to check the tuner is present
+ *
+ * Caution: after byte2 the I2C reverts to write mode continuing to read
+ *          may corrupt tuning data.
+ *
+ */
+
+static int ix2505v_read_status_reg(struct ix2505v_state *state)
+{
+	u8 addr = state->config->tuner_address;
+	u8 b2[] = {0};
+	int ret;
+
+	struct i2c_msg msg[1] = {
+		{ .addr = addr, .flags = I2C_M_RD, .buf = b2, .len = 1 }
+	};
+
+	ret = i2c_transfer(state->i2c, msg, 1);
+	deb_i2c("Read %s ", __func__);
+
+	return (ret == 1) ? (int) b2[0] : -1;
+}
+
+static int ix2505v_write(struct ix2505v_state *state, u8 buf[], u8 count)
+{
+	struct i2c_msg msg[1] = {
+		{ .addr = state->config->tuner_address, .flags = 0,
+		  .buf = buf, .len = count },
+	};
+
+	int ret;
+
+	ret = i2c_transfer(state->i2c, msg, 1);
+
+	if (ret != 1) {
+		deb_i2c("%s: i2c error, ret=%d\n", __func__, ret);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int ix2505v_release(struct dvb_frontend *fe)
+{
+	struct ix2505v_state *state = fe->tuner_priv;
+
+	fe->tuner_priv = NULL;
+	kfree(state);
+
+	return 0;
+}
+
+/**
+ *  Data write format of the Sharp IX2505V B0017
+ *
+ *  byte1:   1   |   1   |   0   |   0   |   0   | 0(MA1)| 0(MA0)|  0
+ *  byte2:   0   |  BG1  |  BG2  |   N8  |   N7  |   N6  |  N5   |  N4
+ *  byte3:   N3  |   N2  |   N1  |   A5  |   A4  |   A3  |   A2  |  A1
+ *  byte4:   1   | 1(C1) | 1(C0) |  PD5  |  PD4  |   TM  | 0(RTS)| 1(REF)
+ *  byte5:   BA2 |   BA1 |  BA0  |  PSC  |  PD3  |PD2/TS2|DIV/TS1|PD0/TS0
+ *
+ *  byte1 = address
+ *
+ *  Write order
+ *  1) byte1 -> byte2 -> byte3 -> byte4 -> byte5
+ *  2) byte1 -> byte4 -> byte5 -> byte2 -> byte3
+ *  3) byte1 -> byte2 -> byte3 -> byte4
+ *  4) byte1 -> byte4 -> byte5 -> byte2
+ *  5) byte1 -> byte2 -> byte3
+ *  6) byte1 -> byte4 -> byte5
+ *  7) byte1 -> byte2
+ *  8) byte1 -> byte4
+ *
+ *  Recommended Setup
+ *  1 -> 8 -> 6
+ */
+
+static int ix2505v_set_params(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	struct ix2505v_state *state = fe->tuner_priv;
+	u32 frequency = c->frequency;
+	u32 b_w  = (c->symbol_rate * 27) / 32000;
+	u32 div_factor, N , A, x;
+	int ret = 0, len;
+	u8 gain, cc, ref, psc, local_osc, lpf;
+	u8 data[4] = {0};
+
+	if ((frequency < fe->ops.info.frequency_min)
+	||  (frequency > fe->ops.info.frequency_max))
+		return -EINVAL;
+
+	if (state->config->tuner_gain)
+		gain = (state->config->tuner_gain < 4)
+			? state->config->tuner_gain : 0;
+	else
+		gain = 0x0;
+
+	if (state->config->tuner_chargepump)
+		cc = state->config->tuner_chargepump;
+	else
+		cc = 0x3;
+
+	ref = 8; /* REF =1 */
+	psc = 32; /* PSC = 0 */
+
+	div_factor = (frequency * ref) / 40; /* local osc = 4Mhz */
+	x = div_factor / psc;
+	N = x/100;
+	A = ((x - (N * 100)) * psc) / 100;
+
+	data[0] = ((gain & 0x3) << 5) | (N >> 3);
+	data[1] = (N << 5) | (A & 0x1f);
+	data[2] = 0x81 | ((cc & 0x3) << 5) ; /*PD5,PD4 & TM = 0|C1,C0|REF=1*/
+
+	deb_info("Frq=%d x=%d N=%d A=%d\n", frequency, x, N, A);
+
+	if (frequency <= 1065000)
+		local_osc = (6 << 5) | 2;
+	else if (frequency <= 1170000)
+		local_osc = (7 << 5) | 2;
+	else if (frequency <= 1300000)
+		local_osc = (1 << 5);
+	else if (frequency <= 1445000)
+		local_osc = (2 << 5);
+	else if (frequency <= 1607000)
+		local_osc = (3 << 5);
+	else if (frequency <= 1778000)
+		local_osc = (4 << 5);
+	else if (frequency <= 1942000)
+		local_osc = (5 << 5);
+	else		/*frequency up to 2150000*/
+		local_osc = (6 << 5);
+
+	data[3] = local_osc; /* all other bits set 0 */
+
+	if (b_w <= 10000)
+		lpf = 0xc;
+	else if (b_w <= 12000)
+		lpf = 0x2;
+	else if (b_w <= 14000)
+		lpf = 0xa;
+	else if (b_w <= 16000)
+		lpf = 0x6;
+	else if (b_w <= 18000)
+		lpf = 0xe;
+	else if (b_w <= 20000)
+		lpf = 0x1;
+	else if (b_w <= 22000)
+		lpf = 0x9;
+	else if (b_w <= 24000)
+		lpf = 0x5;
+	else if (b_w <= 26000)
+		lpf = 0xd;
+	else if (b_w <= 28000)
+		lpf = 0x3;
+		else
+		lpf = 0xb;
+
+	deb_info("Osc=%x b_w=%x lpf=%x\n", local_osc, b_w, lpf);
+	deb_info("Data 0=[%x%x%x%x]\n", data[0], data[1], data[2], data[3]);
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+
+	len = sizeof(data);
+	ret |= ix2505v_write(state, data, len);
+
+	data[2] |= 0x4; /* set TM = 1 other bits same */
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+
+	len = 1;
+	ret |= ix2505v_write(state, &data[2], len); /* write byte 4 only */
+
+	msleep(10);
+
+	data[2] |= ((lpf >> 2) & 0x3) << 3; /* lpf */
+	data[3] |= (lpf & 0x3) << 2;
+
+	deb_info("Data 2=[%x%x]\n", data[2], data[3]);
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+
+	len = 2;
+	ret |= ix2505v_write(state, &data[2], len); /* write byte 4 & 5 */
+
+	if (state->config->min_delay_ms)
+		msleep(state->config->min_delay_ms);
+
+	state->frequency = frequency;
+
+	return ret;
+}
+
+static int ix2505v_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+	struct ix2505v_state *state = fe->tuner_priv;
+
+	*frequency = state->frequency;
+
+	return 0;
+}
+
+static struct dvb_tuner_ops ix2505v_tuner_ops = {
+	.info = {
+		.name = "Sharp IX2505V (B0017)",
+		.frequency_min = 950000,
+		.frequency_max = 2175000
+	},
+	.release = ix2505v_release,
+	.set_params = ix2505v_set_params,
+	.get_frequency = ix2505v_get_frequency,
+};
+
+struct dvb_frontend *ix2505v_attach(struct dvb_frontend *fe,
+				    const struct ix2505v_config *config,
+				    struct i2c_adapter *i2c)
+{
+	struct ix2505v_state *state = NULL;
+	int ret;
+
+	if (NULL == config) {
+		deb_i2c("%s: no config ", __func__);
+		goto error;
+	}
+
+	state = kzalloc(sizeof(struct ix2505v_state), GFP_KERNEL);
+	if (NULL == state)
+		return NULL;
+
+	state->config = config;
+	state->i2c = i2c;
+
+	if (state->config->tuner_write_only) {
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 1);
+
+		ret = ix2505v_read_status_reg(state);
+
+		if (ret & 0x80) {
+			deb_i2c("%s: No IX2505V found\n", __func__);
+			goto error;
+		}
+
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 0);
+	}
+
+	fe->tuner_priv = state;
+
+	memcpy(&fe->ops.tuner_ops, &ix2505v_tuner_ops,
+		sizeof(struct dvb_tuner_ops));
+	deb_i2c("%s: initialization (%s addr=0x%02x) ok\n",
+		__func__, fe->ops.tuner_ops.info.name, config->tuner_address);
+
+	return fe;
+
+error:
+	kfree(state);
+	return NULL;
+}
+EXPORT_SYMBOL(ix2505v_attach);
+
+module_param_named(debug, ix2505v_debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+MODULE_DESCRIPTION("DVB IX2505V tuner driver");
+MODULE_AUTHOR("Malcolm Priestley");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb-frontends/ix2505v.h b/drivers/media/dvb-frontends/ix2505v.h
new file mode 100644
index 0000000..67e89d6
--- /dev/null
+++ b/drivers/media/dvb-frontends/ix2505v.h
@@ -0,0 +1,64 @@
+/**
+ * Driver for Sharp IX2505V (marked B0017) DVB-S silicon tuner
+ *
+ * Copyright (C) 2010 Malcolm Priestley
+ *
+ * This program is free software; you can 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_IX2505V_H
+#define DVB_IX2505V_H
+
+#include <linux/i2c.h>
+#include "dvb_frontend.h"
+
+/**
+ * Attach a ix2505v tuner to the supplied frontend structure.
+ *
+ * @param fe Frontend to attach to.
+ * @param config ix2505v_config structure
+ * @return FE pointer on success, NULL on failure.
+ */
+
+struct ix2505v_config {
+	u8 tuner_address;
+
+	/*Baseband AMP gain control 0/1=0dB(default) 2=-2bB 3=-4dB */
+	u8 tuner_gain;
+
+	/*Charge pump output +/- 0=120 1=260 2=555 3=1200(default) */
+	u8 tuner_chargepump;
+
+	/* delay after tune */
+	int min_delay_ms;
+
+	/* disables reads*/
+	u8 tuner_write_only;
+
+};
+
+#if defined(CONFIG_DVB_IX2505V) || \
+	(defined(CONFIG_DVB_IX2505V_MODULE) && defined(MODULE))
+extern struct dvb_frontend *ix2505v_attach(struct dvb_frontend *fe,
+	const struct ix2505v_config *config, struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend *ix2505v_attach(struct dvb_frontend *fe,
+	const struct ix2505v_config *config, struct i2c_adapter *i2c)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif
+
+#endif /* DVB_IX2505V_H */
diff --git a/drivers/media/dvb-frontends/l64781.c b/drivers/media/dvb-frontends/l64781.c
new file mode 100644
index 0000000..36fcf55
--- /dev/null
+++ b/drivers/media/dvb-frontends/l64781.c
@@ -0,0 +1,609 @@
+/*
+    driver for LSI L64781 COFDM demodulator
+
+    Copyright (C) 2001 Holger Waechtler for Convergence Integrated Media GmbH
+		       Marko Kohtala <marko.kohtala@luukku.com>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include "dvb_frontend.h"
+#include "l64781.h"
+
+
+struct l64781_state {
+	struct i2c_adapter* i2c;
+	const struct l64781_config* config;
+	struct dvb_frontend frontend;
+
+	/* private demodulator data */
+	unsigned int first:1;
+};
+
+#define dprintk(args...) \
+	do { \
+		if (debug) printk(KERN_DEBUG "l64781: " args); \
+	} while (0)
+
+static int debug;
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+
+
+static int l64781_writereg (struct l64781_state* state, u8 reg, u8 data)
+{
+	int ret;
+	u8 buf [] = { reg, data };
+	struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 };
+
+	if ((ret = i2c_transfer(state->i2c, &msg, 1)) != 1)
+		dprintk ("%s: write_reg error (reg == %02x) = %02x!\n",
+			 __func__, reg, ret);
+
+	return (ret != 1) ? -1 : 0;
+}
+
+static int l64781_readreg (struct l64781_state* state, u8 reg)
+{
+	int ret;
+	u8 b0 [] = { reg };
+	u8 b1 [] = { 0 };
+	struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 },
+			   { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } };
+
+	ret = i2c_transfer(state->i2c, msg, 2);
+
+	if (ret != 2) return ret;
+
+	return b1[0];
+}
+
+static void apply_tps (struct l64781_state* state)
+{
+	l64781_writereg (state, 0x2a, 0x00);
+	l64781_writereg (state, 0x2a, 0x01);
+
+	/* This here is a little bit questionable because it enables
+	   the automatic update of TPS registers. I think we'd need to
+	   handle the IRQ from FE to update some other registers as
+	   well, or at least implement some magic to tuning to correct
+	   to the TPS received from transmission. */
+	l64781_writereg (state, 0x2a, 0x02);
+}
+
+
+static void reset_afc (struct l64781_state* state)
+{
+	/* Set AFC stall for the AFC_INIT_FRQ setting, TIM_STALL for
+	   timing offset */
+	l64781_writereg (state, 0x07, 0x9e); /* stall AFC */
+	l64781_writereg (state, 0x08, 0);    /* AFC INIT FREQ */
+	l64781_writereg (state, 0x09, 0);
+	l64781_writereg (state, 0x0a, 0);
+	l64781_writereg (state, 0x07, 0x8e);
+	l64781_writereg (state, 0x0e, 0);    /* AGC gain to zero in beginning */
+	l64781_writereg (state, 0x11, 0x80); /* stall TIM */
+	l64781_writereg (state, 0x10, 0);    /* TIM_OFFSET_LSB */
+	l64781_writereg (state, 0x12, 0);
+	l64781_writereg (state, 0x13, 0);
+	l64781_writereg (state, 0x11, 0x00);
+}
+
+static int reset_and_configure (struct l64781_state* state)
+{
+	u8 buf [] = { 0x06 };
+	struct i2c_msg msg = { .addr = 0x00, .flags = 0, .buf = buf, .len = 1 };
+	// NOTE: this is correct in writing to address 0x00
+
+	return (i2c_transfer(state->i2c, &msg, 1) == 1) ? 0 : -ENODEV;
+}
+
+static int apply_frontend_param(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct l64781_state* state = fe->demodulator_priv;
+	/* The coderates for FEC_NONE, FEC_4_5 and FEC_FEC_6_7 are arbitrary */
+	static const u8 fec_tab[] = { 7, 0, 1, 2, 9, 3, 10, 4 };
+	/* QPSK, QAM_16, QAM_64 */
+	static const u8 qam_tab [] = { 2, 4, 0, 6 };
+	static const u8 guard_tab [] = { 1, 2, 4, 8 };
+	/* The Grundig 29504-401.04 Tuner comes with 18.432MHz crystal. */
+	static const u32 ppm = 8000;
+	u32 ddfs_offset_fixed;
+/*	u32 ddfs_offset_variable = 0x6000-((1000000UL+ppm)/ */
+/*			bw_tab[p->bandWidth]<<10)/15625; */
+	u32 init_freq;
+	u32 spi_bias;
+	u8 val0x04;
+	u8 val0x05;
+	u8 val0x06;
+	int bw;
+
+	switch (p->bandwidth_hz) {
+	case 8000000:
+		bw = 8;
+		break;
+	case 7000000:
+		bw = 7;
+		break;
+	case 6000000:
+		bw = 6;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (fe->ops.tuner_ops.set_params) {
+		fe->ops.tuner_ops.set_params(fe);
+		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+	}
+
+	if (p->inversion != INVERSION_ON &&
+	    p->inversion != INVERSION_OFF)
+		return -EINVAL;
+
+	if (p->code_rate_HP != FEC_1_2 && p->code_rate_HP != FEC_2_3 &&
+	    p->code_rate_HP != FEC_3_4 && p->code_rate_HP != FEC_5_6 &&
+	    p->code_rate_HP != FEC_7_8)
+		return -EINVAL;
+
+	if (p->hierarchy != HIERARCHY_NONE &&
+	    (p->code_rate_LP != FEC_1_2 && p->code_rate_LP != FEC_2_3 &&
+	     p->code_rate_LP != FEC_3_4 && p->code_rate_LP != FEC_5_6 &&
+	     p->code_rate_LP != FEC_7_8))
+		return -EINVAL;
+
+	if (p->modulation != QPSK && p->modulation != QAM_16 &&
+	    p->modulation != QAM_64)
+		return -EINVAL;
+
+	if (p->transmission_mode != TRANSMISSION_MODE_2K &&
+	    p->transmission_mode != TRANSMISSION_MODE_8K)
+		return -EINVAL;
+
+	if (p->guard_interval < GUARD_INTERVAL_1_32 ||
+	    p->guard_interval > GUARD_INTERVAL_1_4)
+		return -EINVAL;
+
+	if (p->hierarchy < HIERARCHY_NONE ||
+	    p->hierarchy > HIERARCHY_4)
+		return -EINVAL;
+
+	ddfs_offset_fixed = 0x4000-(ppm<<16)/bw/1000000;
+
+	/* This works up to 20000 ppm, it overflows if too large ppm! */
+	init_freq = (((8UL<<25) + (8UL<<19) / 25*ppm / (15625/25)) /
+			bw & 0xFFFFFF);
+
+	/* SPI bias calculation is slightly modified to fit in 32bit */
+	/* will work for high ppm only... */
+	spi_bias = 378 * (1 << 10);
+	spi_bias *= 16;
+	spi_bias *= bw;
+	spi_bias *= qam_tab[p->modulation];
+	spi_bias /= p->code_rate_HP + 1;
+	spi_bias /= (guard_tab[p->guard_interval] + 32);
+	spi_bias *= 1000;
+	spi_bias /= 1000 + ppm/1000;
+	spi_bias *= p->code_rate_HP;
+
+	val0x04 = (p->transmission_mode << 2) | p->guard_interval;
+	val0x05 = fec_tab[p->code_rate_HP];
+
+	if (p->hierarchy != HIERARCHY_NONE)
+		val0x05 |= (p->code_rate_LP - FEC_1_2) << 3;
+
+	val0x06 = (p->hierarchy << 2) | p->modulation;
+
+	l64781_writereg (state, 0x04, val0x04);
+	l64781_writereg (state, 0x05, val0x05);
+	l64781_writereg (state, 0x06, val0x06);
+
+	reset_afc (state);
+
+	/* Technical manual section 2.6.1, TIM_IIR_GAIN optimal values */
+	l64781_writereg (state, 0x15,
+			 p->transmission_mode == TRANSMISSION_MODE_2K ? 1 : 3);
+	l64781_writereg (state, 0x16, init_freq & 0xff);
+	l64781_writereg (state, 0x17, (init_freq >> 8) & 0xff);
+	l64781_writereg (state, 0x18, (init_freq >> 16) & 0xff);
+
+	l64781_writereg (state, 0x1b, spi_bias & 0xff);
+	l64781_writereg (state, 0x1c, (spi_bias >> 8) & 0xff);
+	l64781_writereg (state, 0x1d, ((spi_bias >> 16) & 0x7f) |
+		(p->inversion == INVERSION_ON ? 0x80 : 0x00));
+
+	l64781_writereg (state, 0x22, ddfs_offset_fixed & 0xff);
+	l64781_writereg (state, 0x23, (ddfs_offset_fixed >> 8) & 0x3f);
+
+	l64781_readreg (state, 0x00);  /*  clear interrupt registers... */
+	l64781_readreg (state, 0x01);  /*  dto. */
+
+	apply_tps (state);
+
+	return 0;
+}
+
+static int get_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct l64781_state* state = fe->demodulator_priv;
+	int tmp;
+
+
+	tmp = l64781_readreg(state, 0x04);
+	switch(tmp & 3) {
+	case 0:
+		p->guard_interval = GUARD_INTERVAL_1_32;
+		break;
+	case 1:
+		p->guard_interval = GUARD_INTERVAL_1_16;
+		break;
+	case 2:
+		p->guard_interval = GUARD_INTERVAL_1_8;
+		break;
+	case 3:
+		p->guard_interval = GUARD_INTERVAL_1_4;
+		break;
+	}
+	switch((tmp >> 2) & 3) {
+	case 0:
+		p->transmission_mode = TRANSMISSION_MODE_2K;
+		break;
+	case 1:
+		p->transmission_mode = TRANSMISSION_MODE_8K;
+		break;
+	default:
+		printk(KERN_WARNING "Unexpected value for transmission_mode\n");
+	}
+
+	tmp = l64781_readreg(state, 0x05);
+	switch(tmp & 7) {
+	case 0:
+		p->code_rate_HP = FEC_1_2;
+		break;
+	case 1:
+		p->code_rate_HP = FEC_2_3;
+		break;
+	case 2:
+		p->code_rate_HP = FEC_3_4;
+		break;
+	case 3:
+		p->code_rate_HP = FEC_5_6;
+		break;
+	case 4:
+		p->code_rate_HP = FEC_7_8;
+		break;
+	default:
+		printk("Unexpected value for code_rate_HP\n");
+	}
+	switch((tmp >> 3) & 7) {
+	case 0:
+		p->code_rate_LP = FEC_1_2;
+		break;
+	case 1:
+		p->code_rate_LP = FEC_2_3;
+		break;
+	case 2:
+		p->code_rate_LP = FEC_3_4;
+		break;
+	case 3:
+		p->code_rate_LP = FEC_5_6;
+		break;
+	case 4:
+		p->code_rate_LP = FEC_7_8;
+		break;
+	default:
+		printk("Unexpected value for code_rate_LP\n");
+	}
+
+	tmp = l64781_readreg(state, 0x06);
+	switch(tmp & 3) {
+	case 0:
+		p->modulation = QPSK;
+		break;
+	case 1:
+		p->modulation = QAM_16;
+		break;
+	case 2:
+		p->modulation = QAM_64;
+		break;
+	default:
+		printk(KERN_WARNING "Unexpected value for modulation\n");
+	}
+	switch((tmp >> 2) & 7) {
+	case 0:
+		p->hierarchy = HIERARCHY_NONE;
+		break;
+	case 1:
+		p->hierarchy = HIERARCHY_1;
+		break;
+	case 2:
+		p->hierarchy = HIERARCHY_2;
+		break;
+	case 3:
+		p->hierarchy = HIERARCHY_4;
+		break;
+	default:
+		printk("Unexpected value for hierarchy\n");
+	}
+
+
+	tmp = l64781_readreg (state, 0x1d);
+	p->inversion = (tmp & 0x80) ? INVERSION_ON : INVERSION_OFF;
+
+	tmp = (int) (l64781_readreg (state, 0x08) |
+		     (l64781_readreg (state, 0x09) << 8) |
+		     (l64781_readreg (state, 0x0a) << 16));
+	p->frequency += tmp;
+
+	return 0;
+}
+
+static int l64781_read_status(struct dvb_frontend* fe, fe_status_t* status)
+{
+	struct l64781_state* state = fe->demodulator_priv;
+	int sync = l64781_readreg (state, 0x32);
+	int gain = l64781_readreg (state, 0x0e);
+
+	l64781_readreg (state, 0x00);  /*  clear interrupt registers... */
+	l64781_readreg (state, 0x01);  /*  dto. */
+
+	*status = 0;
+
+	if (gain > 5)
+		*status |= FE_HAS_SIGNAL;
+
+	if (sync & 0x02) /* VCXO locked, this criteria should be ok */
+		*status |= FE_HAS_CARRIER;
+
+	if (sync & 0x20)
+		*status |= FE_HAS_VITERBI;
+
+	if (sync & 0x40)
+		*status |= FE_HAS_SYNC;
+
+	if (sync == 0x7f)
+		*status |= FE_HAS_LOCK;
+
+	return 0;
+}
+
+static int l64781_read_ber(struct dvb_frontend* fe, u32* ber)
+{
+	struct l64781_state* state = fe->demodulator_priv;
+
+	/*   XXX FIXME: set up counting period (reg 0x26...0x28)
+	 */
+	*ber = l64781_readreg (state, 0x39)
+	    | (l64781_readreg (state, 0x3a) << 8);
+
+	return 0;
+}
+
+static int l64781_read_signal_strength(struct dvb_frontend* fe, u16* signal_strength)
+{
+	struct l64781_state* state = fe->demodulator_priv;
+
+	u8 gain = l64781_readreg (state, 0x0e);
+	*signal_strength = (gain << 8) | gain;
+
+	return 0;
+}
+
+static int l64781_read_snr(struct dvb_frontend* fe, u16* snr)
+{
+	struct l64781_state* state = fe->demodulator_priv;
+
+	u8 avg_quality = 0xff - l64781_readreg (state, 0x33);
+	*snr = (avg_quality << 8) | avg_quality; /* not exact, but...*/
+
+	return 0;
+}
+
+static int l64781_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
+{
+	struct l64781_state* state = fe->demodulator_priv;
+
+	*ucblocks = l64781_readreg (state, 0x37)
+	   | (l64781_readreg (state, 0x38) << 8);
+
+	return 0;
+}
+
+static int l64781_sleep(struct dvb_frontend* fe)
+{
+	struct l64781_state* state = fe->demodulator_priv;
+
+	/* Power down */
+	return l64781_writereg (state, 0x3e, 0x5a);
+}
+
+static int l64781_init(struct dvb_frontend* fe)
+{
+	struct l64781_state* state = fe->demodulator_priv;
+
+	reset_and_configure (state);
+
+	/* Power up */
+	l64781_writereg (state, 0x3e, 0xa5);
+
+	/* Reset hard */
+	l64781_writereg (state, 0x2a, 0x04);
+	l64781_writereg (state, 0x2a, 0x00);
+
+	/* Set tuner specific things */
+	/* AFC_POL, set also in reset_afc */
+	l64781_writereg (state, 0x07, 0x8e);
+
+	/* Use internal ADC */
+	l64781_writereg (state, 0x0b, 0x81);
+
+	/* AGC loop gain, and polarity is positive */
+	l64781_writereg (state, 0x0c, 0x84);
+
+	/* Internal ADC outputs two's complement */
+	l64781_writereg (state, 0x0d, 0x8c);
+
+	/* With ppm=8000, it seems the DTR_SENSITIVITY will result in
+	   value of 2 with all possible bandwidths and guard
+	   intervals, which is the initial value anyway. */
+	/*l64781_writereg (state, 0x19, 0x92);*/
+
+	/* Everything is two's complement, soft bit and CSI_OUT too */
+	l64781_writereg (state, 0x1e, 0x09);
+
+	/* delay a bit after first init attempt */
+	if (state->first) {
+		state->first = 0;
+		msleep(200);
+	}
+
+	return 0;
+}
+
+static int l64781_get_tune_settings(struct dvb_frontend* fe,
+				    struct dvb_frontend_tune_settings* fesettings)
+{
+	fesettings->min_delay_ms = 4000;
+	fesettings->step_size = 0;
+	fesettings->max_drift = 0;
+	return 0;
+}
+
+static void l64781_release(struct dvb_frontend* fe)
+{
+	struct l64781_state* state = fe->demodulator_priv;
+	kfree(state);
+}
+
+static struct dvb_frontend_ops l64781_ops;
+
+struct dvb_frontend* l64781_attach(const struct l64781_config* config,
+				   struct i2c_adapter* i2c)
+{
+	struct l64781_state* state = NULL;
+	int reg0x3e = -1;
+	u8 b0 [] = { 0x1a };
+	u8 b1 [] = { 0x00 };
+	struct i2c_msg msg [] = { { .addr = config->demod_address, .flags = 0, .buf = b0, .len = 1 },
+			   { .addr = config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } };
+
+	/* allocate memory for the internal state */
+	state = kzalloc(sizeof(struct l64781_state), GFP_KERNEL);
+	if (state == NULL) goto error;
+
+	/* setup the state */
+	state->config = config;
+	state->i2c = i2c;
+	state->first = 1;
+
+	/**
+	 *  the L64781 won't show up before we send the reset_and_configure()
+	 *  broadcast. If nothing responds there is no L64781 on the bus...
+	 */
+	if (reset_and_configure(state) < 0) {
+		dprintk("No response to reset and configure broadcast...\n");
+		goto error;
+	}
+
+	/* The chip always responds to reads */
+	if (i2c_transfer(state->i2c, msg, 2) != 2) {
+		dprintk("No response to read on I2C bus\n");
+		goto error;
+	}
+
+	/* Save current register contents for bailout */
+	reg0x3e = l64781_readreg(state, 0x3e);
+
+	/* Reading the POWER_DOWN register always returns 0 */
+	if (reg0x3e != 0) {
+		dprintk("Device doesn't look like L64781\n");
+		goto error;
+	}
+
+	/* Turn the chip off */
+	l64781_writereg (state, 0x3e, 0x5a);
+
+	/* Responds to all reads with 0 */
+	if (l64781_readreg(state, 0x1a) != 0) {
+		dprintk("Read 1 returned unexpcted value\n");
+		goto error;
+	}
+
+	/* Turn the chip on */
+	l64781_writereg (state, 0x3e, 0xa5);
+
+	/* Responds with register default value */
+	if (l64781_readreg(state, 0x1a) != 0xa1) {
+		dprintk("Read 2 returned unexpcted value\n");
+		goto error;
+	}
+
+	/* create dvb_frontend */
+	memcpy(&state->frontend.ops, &l64781_ops, sizeof(struct dvb_frontend_ops));
+	state->frontend.demodulator_priv = state;
+	return &state->frontend;
+
+error:
+	if (reg0x3e >= 0)
+		l64781_writereg (state, 0x3e, reg0x3e);  /* restore reg 0x3e */
+	kfree(state);
+	return NULL;
+}
+
+static struct dvb_frontend_ops l64781_ops = {
+	.delsys = { SYS_DVBT },
+	.info = {
+		.name = "LSI L64781 DVB-T",
+	/*	.frequency_min = ???,*/
+	/*	.frequency_max = ???,*/
+		.frequency_stepsize = 166666,
+	/*      .frequency_tolerance = ???,*/
+	/*      .symbol_rate_tolerance = ???,*/
+		.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_QAM_16 | FE_CAN_QAM_64 |
+		      FE_CAN_MUTE_TS
+	},
+
+	.release = l64781_release,
+
+	.init = l64781_init,
+	.sleep = l64781_sleep,
+
+	.set_frontend = apply_frontend_param,
+	.get_frontend = get_frontend,
+	.get_tune_settings = l64781_get_tune_settings,
+
+	.read_status = l64781_read_status,
+	.read_ber = l64781_read_ber,
+	.read_signal_strength = l64781_read_signal_strength,
+	.read_snr = l64781_read_snr,
+	.read_ucblocks = l64781_read_ucblocks,
+};
+
+MODULE_DESCRIPTION("LSI L64781 DVB-T Demodulator driver");
+MODULE_AUTHOR("Holger Waechtler, Marko Kohtala");
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(l64781_attach);
diff --git a/drivers/media/dvb-frontends/l64781.h b/drivers/media/dvb-frontends/l64781.h
new file mode 100644
index 0000000..1305a9e
--- /dev/null
+++ b/drivers/media/dvb-frontends/l64781.h
@@ -0,0 +1,46 @@
+/*
+    driver for LSI L64781 COFDM demodulator
+
+    Copyright (C) 2001 Holger Waechtler for Convergence Integrated Media GmbH
+		       Marko Kohtala <marko.kohtala@luukku.com>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef L64781_H
+#define L64781_H
+
+#include <linux/dvb/frontend.h>
+
+struct l64781_config
+{
+	/* the demodulator's i2c address */
+	u8 demod_address;
+};
+
+#if defined(CONFIG_DVB_L64781) || (defined(CONFIG_DVB_L64781_MODULE) && defined(MODULE))
+extern struct dvb_frontend* l64781_attach(const struct l64781_config* config,
+					  struct i2c_adapter* i2c);
+#else
+static inline struct dvb_frontend* l64781_attach(const struct l64781_config* config,
+					  struct i2c_adapter* i2c)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif // CONFIG_DVB_L64781
+
+#endif // L64781_H
diff --git a/drivers/media/dvb-frontends/lg2160.c b/drivers/media/dvb-frontends/lg2160.c
new file mode 100644
index 0000000..cc11260
--- /dev/null
+++ b/drivers/media/dvb-frontends/lg2160.c
@@ -0,0 +1,1468 @@
+/*
+ *    Support for LG2160 - ATSC/MH
+ *
+ *    Copyright (C) 2010 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/jiffies.h>
+#include <linux/dvb/frontend.h>
+#include "lg2160.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 "lg2160: " 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 lg216x_state {
+	struct i2c_adapter *i2c_adap;
+	const struct lg2160_config *cfg;
+
+	struct dvb_frontend frontend;
+
+	u32 current_frequency;
+	u8 parade_id;
+	u8 fic_ver;
+	unsigned int last_reset;
+};
+
+/* ------------------------------------------------------------------------ */
+
+static int lg216x_write_reg(struct lg216x_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 lg216x_read_reg(struct lg216x_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;
+}
+
+struct lg216x_reg {
+	u16 reg;
+	u8 val;
+};
+
+static int lg216x_write_regs(struct lg216x_state *state,
+			     struct lg216x_reg *regs, int len)
+{
+	int i, ret;
+
+	lg_reg("writing %d registers...\n", len);
+
+	for (i = 0; i < len; i++) {
+		ret = lg216x_write_reg(state, regs[i].reg, regs[i].val);
+		if (lg_fail(ret))
+			return ret;
+	}
+	return 0;
+}
+
+static int lg216x_set_reg_bit(struct lg216x_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 = lg216x_read_reg(state, reg, &val);
+	if (lg_fail(ret))
+		goto fail;
+
+	val &= ~(1 << bit);
+	val |= (onoff & 1) << bit;
+
+	ret = lg216x_write_reg(state, reg, val);
+	lg_fail(ret);
+fail:
+	return ret;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int lg216x_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+	struct lg216x_state *state = fe->demodulator_priv;
+	int ret;
+
+	if (state->cfg->deny_i2c_rptr)
+		return 0;
+
+	lg_dbg("(%d)\n", enable);
+
+	ret = lg216x_set_reg_bit(state, 0x0000, 0, enable ? 0 : 1);
+
+	msleep(1);
+
+	return ret;
+}
+
+static int lg216x_soft_reset(struct lg216x_state *state)
+{
+	int ret;
+
+	lg_dbg("\n");
+
+	ret = lg216x_write_reg(state, 0x0002, 0x00);
+	if (lg_fail(ret))
+		goto fail;
+
+	msleep(20);
+	ret = lg216x_write_reg(state, 0x0002, 0x01);
+	if (lg_fail(ret))
+		goto fail;
+
+	state->last_reset = jiffies_to_msecs(jiffies);
+fail:
+	return ret;
+}
+
+static int lg216x_initialize(struct lg216x_state *state)
+{
+	int ret;
+
+	static struct lg216x_reg lg2160_init[] = {
+#if 0
+		{ .reg = 0x0015, .val = 0xe6 },
+#else
+		{ .reg = 0x0015, .val = 0xf7 },
+		{ .reg = 0x001b, .val = 0x52 },
+		{ .reg = 0x0208, .val = 0x00 },
+		{ .reg = 0x0209, .val = 0x82 },
+		{ .reg = 0x0210, .val = 0xf9 },
+		{ .reg = 0x020a, .val = 0x00 },
+		{ .reg = 0x020b, .val = 0x82 },
+		{ .reg = 0x020d, .val = 0x28 },
+		{ .reg = 0x020f, .val = 0x14 },
+#endif
+	};
+
+	static struct lg216x_reg lg2161_init[] = {
+		{ .reg = 0x0000, .val = 0x41 },
+		{ .reg = 0x0001, .val = 0xfb },
+		{ .reg = 0x0216, .val = 0x00 },
+		{ .reg = 0x0219, .val = 0x00 },
+		{ .reg = 0x021b, .val = 0x55 },
+		{ .reg = 0x0606, .val = 0x0a },
+	};
+
+	switch (state->cfg->lg_chip) {
+	case LG2160:
+		ret = lg216x_write_regs(state,
+					lg2160_init, ARRAY_SIZE(lg2160_init));
+		break;
+	case LG2161:
+		ret = lg216x_write_regs(state,
+					lg2161_init, ARRAY_SIZE(lg2161_init));
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+	if (lg_fail(ret))
+		goto fail;
+
+	ret = lg216x_soft_reset(state);
+	lg_fail(ret);
+fail:
+	return ret;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int lg216x_set_if(struct lg216x_state *state)
+{
+	u8 val;
+	int ret;
+
+	lg_dbg("%d KHz\n", state->cfg->if_khz);
+
+	ret = lg216x_read_reg(state, 0x0132, &val);
+	if (lg_fail(ret))
+		goto fail;
+
+	val &= 0xfb;
+	val |= (0 == state->cfg->if_khz) ? 0x04 : 0x00;
+
+	ret = lg216x_write_reg(state, 0x0132, val);
+	lg_fail(ret);
+
+	/* if NOT zero IF, 6 MHz is the default */
+fail:
+	return ret;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int lg2160_agc_fix(struct lg216x_state *state,
+			  int if_agc_fix, int rf_agc_fix)
+{
+	u8 val;
+	int ret;
+
+	ret = lg216x_read_reg(state, 0x0100, &val);
+	if (lg_fail(ret))
+		goto fail;
+
+	val &= 0xf3;
+	val |= (if_agc_fix) ? 0x08 : 0x00;
+	val |= (rf_agc_fix) ? 0x04 : 0x00;
+
+	ret = lg216x_write_reg(state, 0x0100, val);
+	lg_fail(ret);
+fail:
+	return ret;
+}
+
+#if 0
+static int lg2160_agc_freeze(struct lg216x_state *state,
+			     int if_agc_freeze, int rf_agc_freeze)
+{
+	u8 val;
+	int ret;
+
+	ret = lg216x_read_reg(state, 0x0100, &val);
+	if (lg_fail(ret))
+		goto fail;
+
+	val &= 0xcf;
+	val |= (if_agc_freeze) ? 0x20 : 0x00;
+	val |= (rf_agc_freeze) ? 0x10 : 0x00;
+
+	ret = lg216x_write_reg(state, 0x0100, val);
+	lg_fail(ret);
+fail:
+	return ret;
+}
+#endif
+
+static int lg2160_agc_polarity(struct lg216x_state *state,
+			       int if_agc_polarity, int rf_agc_polarity)
+{
+	u8 val;
+	int ret;
+
+	ret = lg216x_read_reg(state, 0x0100, &val);
+	if (lg_fail(ret))
+		goto fail;
+
+	val &= 0xfc;
+	val |= (if_agc_polarity) ? 0x02 : 0x00;
+	val |= (rf_agc_polarity) ? 0x01 : 0x00;
+
+	ret = lg216x_write_reg(state, 0x0100, val);
+	lg_fail(ret);
+fail:
+	return ret;
+}
+
+static int lg2160_tuner_pwr_save_polarity(struct lg216x_state *state,
+					  int polarity)
+{
+	u8 val;
+	int ret;
+
+	ret = lg216x_read_reg(state, 0x0008, &val);
+	if (lg_fail(ret))
+		goto fail;
+
+	val &= 0xfe;
+	val |= (polarity) ? 0x01 : 0x00;
+
+	ret = lg216x_write_reg(state, 0x0008, val);
+	lg_fail(ret);
+fail:
+	return ret;
+}
+
+static int lg2160_spectrum_polarity(struct lg216x_state *state,
+				    int inverted)
+{
+	u8 val;
+	int ret;
+
+	ret = lg216x_read_reg(state, 0x0132, &val);
+	if (lg_fail(ret))
+		goto fail;
+
+	val &= 0xfd;
+	val |= (inverted) ? 0x02 : 0x00;
+
+	ret = lg216x_write_reg(state, 0x0132, val);
+	lg_fail(ret);
+fail:
+	return lg216x_soft_reset(state);
+}
+
+static int lg2160_tuner_pwr_save(struct lg216x_state *state, int onoff)
+{
+	u8 val;
+	int ret;
+
+	ret = lg216x_read_reg(state, 0x0007, &val);
+	if (lg_fail(ret))
+		goto fail;
+
+	val &= 0xbf;
+	val |= (onoff) ? 0x40 : 0x00;
+
+	ret = lg216x_write_reg(state, 0x0007, val);
+	lg_fail(ret);
+fail:
+	return ret;
+}
+
+static int lg216x_set_parade(struct lg216x_state *state, int id)
+{
+	int ret;
+
+	ret = lg216x_write_reg(state, 0x013e, id & 0x7f);
+	if (lg_fail(ret))
+		goto fail;
+
+	state->parade_id = id & 0x7f;
+fail:
+	return ret;
+}
+
+static int lg216x_set_ensemble(struct lg216x_state *state, int id)
+{
+	int ret;
+	u16 reg;
+	u8 val;
+
+	switch (state->cfg->lg_chip) {
+	case LG2160:
+		reg = 0x0400;
+		break;
+	case LG2161:
+	default:
+		reg = 0x0500;
+		break;
+	}
+
+	ret = lg216x_read_reg(state, reg, &val);
+	if (lg_fail(ret))
+		goto fail;
+
+	val &= 0xfe;
+	val |= (id) ? 0x01 : 0x00;
+
+	ret = lg216x_write_reg(state, reg, val);
+	lg_fail(ret);
+fail:
+	return ret;
+}
+
+static int lg2160_set_spi_clock(struct lg216x_state *state)
+{
+	u8 val;
+	int ret;
+
+	ret = lg216x_read_reg(state, 0x0014, &val);
+	if (lg_fail(ret))
+		goto fail;
+
+	val &= 0xf3;
+	val |= (state->cfg->spi_clock << 2);
+
+	ret = lg216x_write_reg(state, 0x0014, val);
+	lg_fail(ret);
+fail:
+	return ret;
+}
+
+static int lg2161_set_output_interface(struct lg216x_state *state)
+{
+	u8 val;
+	int ret;
+
+	ret = lg216x_read_reg(state, 0x0014, &val);
+	if (lg_fail(ret))
+		goto fail;
+
+	val &= ~0x07;
+	val |= state->cfg->output_if; /* FIXME: needs sanity check */
+
+	ret = lg216x_write_reg(state, 0x0014, val);
+	lg_fail(ret);
+fail:
+	return ret;
+}
+
+static int lg216x_enable_fic(struct lg216x_state *state, int onoff)
+{
+	int ret;
+
+	ret = lg216x_write_reg(state, 0x0017, 0x23);
+	if (lg_fail(ret))
+		goto fail;
+
+	ret = lg216x_write_reg(state, 0x0016, 0xfc);
+	if (lg_fail(ret))
+		goto fail;
+
+	switch (state->cfg->lg_chip) {
+	case LG2160:
+		ret = lg216x_write_reg(state, 0x0016,
+				       0xfc | ((onoff) ? 0x02 : 0x00));
+		break;
+	case LG2161:
+		ret = lg216x_write_reg(state, 0x0016, (onoff) ? 0x10 : 0x00);
+		break;
+	}
+	if (lg_fail(ret))
+		goto fail;
+
+	ret = lg216x_initialize(state);
+	if (lg_fail(ret))
+		goto fail;
+
+	if (onoff) {
+		ret = lg216x_write_reg(state, 0x0017, 0x03);
+		lg_fail(ret);
+	}
+fail:
+	return ret;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int lg216x_get_fic_version(struct lg216x_state *state, u8 *ficver)
+{
+	u8 val;
+	int ret;
+
+	*ficver = 0xff; /* invalid value */
+
+	ret = lg216x_read_reg(state, 0x0128, &val);
+	if (lg_fail(ret))
+		goto fail;
+
+	*ficver = (val >> 3) & 0x1f;
+fail:
+	return ret;
+}
+
+#if 0
+static int lg2160_get_parade_id(struct lg216x_state *state, u8 *id)
+{
+	u8 val;
+	int ret;
+
+	*id = 0xff; /* invalid value */
+
+	ret = lg216x_read_reg(state, 0x0123, &val);
+	if (lg_fail(ret))
+		goto fail;
+
+	*id = val & 0x7f;
+fail:
+	return ret;
+}
+#endif
+
+static int lg216x_get_nog(struct lg216x_state *state, u8 *nog)
+{
+	u8 val;
+	int ret;
+
+	*nog = 0xff; /* invalid value */
+
+	ret = lg216x_read_reg(state, 0x0124, &val);
+	if (lg_fail(ret))
+		goto fail;
+
+	*nog = ((val >> 4) & 0x07) + 1;
+fail:
+	return ret;
+}
+
+static int lg216x_get_tnog(struct lg216x_state *state, u8 *tnog)
+{
+	u8 val;
+	int ret;
+
+	*tnog = 0xff; /* invalid value */
+
+	ret = lg216x_read_reg(state, 0x0125, &val);
+	if (lg_fail(ret))
+		goto fail;
+
+	*tnog = val & 0x1f;
+fail:
+	return ret;
+}
+
+static int lg216x_get_sgn(struct lg216x_state *state, u8 *sgn)
+{
+	u8 val;
+	int ret;
+
+	*sgn = 0xff; /* invalid value */
+
+	ret = lg216x_read_reg(state, 0x0124, &val);
+	if (lg_fail(ret))
+		goto fail;
+
+	*sgn = val & 0x0f;
+fail:
+	return ret;
+}
+
+static int lg216x_get_prc(struct lg216x_state *state, u8 *prc)
+{
+	u8 val;
+	int ret;
+
+	*prc = 0xff; /* invalid value */
+
+	ret = lg216x_read_reg(state, 0x0125, &val);
+	if (lg_fail(ret))
+		goto fail;
+
+	*prc = ((val >> 5) & 0x07) + 1;
+fail:
+	return ret;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int lg216x_get_rs_frame_mode(struct lg216x_state *state,
+				    enum atscmh_rs_frame_mode *rs_framemode)
+{
+	u8 val;
+	int ret;
+
+	switch (state->cfg->lg_chip) {
+	case LG2160:
+		ret = lg216x_read_reg(state, 0x0410, &val);
+		break;
+	case LG2161:
+		ret = lg216x_read_reg(state, 0x0513, &val);
+		break;
+	default:
+		ret = -EINVAL;
+	}
+	if (lg_fail(ret))
+		goto fail;
+
+	switch ((val >> 4) & 0x03) {
+#if 1
+	default:
+#endif
+	case 0x00:
+		*rs_framemode = ATSCMH_RSFRAME_PRI_ONLY;
+		break;
+	case 0x01:
+		*rs_framemode = ATSCMH_RSFRAME_PRI_SEC;
+		break;
+#if 0
+	default:
+		*rs_framemode = ATSCMH_RSFRAME_RES;
+		break;
+#endif
+	}
+fail:
+	return ret;
+}
+
+static
+int lg216x_get_rs_frame_ensemble(struct lg216x_state *state,
+				 enum atscmh_rs_frame_ensemble *rs_frame_ens)
+{
+	u8 val;
+	int ret;
+
+	switch (state->cfg->lg_chip) {
+	case LG2160:
+		ret = lg216x_read_reg(state, 0x0400, &val);
+		break;
+	case LG2161:
+		ret = lg216x_read_reg(state, 0x0500, &val);
+		break;
+	default:
+		ret = -EINVAL;
+	}
+	if (lg_fail(ret))
+		goto fail;
+
+	val &= 0x01;
+	*rs_frame_ens = (enum atscmh_rs_frame_ensemble) val;
+fail:
+	return ret;
+}
+
+static int lg216x_get_rs_code_mode(struct lg216x_state *state,
+				   enum atscmh_rs_code_mode *rs_code_pri,
+				   enum atscmh_rs_code_mode *rs_code_sec)
+{
+	u8 val;
+	int ret;
+
+	switch (state->cfg->lg_chip) {
+	case LG2160:
+		ret = lg216x_read_reg(state, 0x0410, &val);
+		break;
+	case LG2161:
+		ret = lg216x_read_reg(state, 0x0513, &val);
+		break;
+	default:
+		ret = -EINVAL;
+	}
+	if (lg_fail(ret))
+		goto fail;
+
+	*rs_code_pri = (enum atscmh_rs_code_mode) ((val >> 2) & 0x03);
+	*rs_code_sec = (enum atscmh_rs_code_mode) (val & 0x03);
+fail:
+	return ret;
+}
+
+static int lg216x_get_sccc_block_mode(struct lg216x_state *state,
+				      enum atscmh_sccc_block_mode *sccc_block)
+{
+	u8 val;
+	int ret;
+
+	switch (state->cfg->lg_chip) {
+	case LG2160:
+		ret = lg216x_read_reg(state, 0x0315, &val);
+		break;
+	case LG2161:
+		ret = lg216x_read_reg(state, 0x0511, &val);
+		break;
+	default:
+		ret = -EINVAL;
+	}
+	if (lg_fail(ret))
+		goto fail;
+
+	switch (val & 0x03) {
+	case 0x00:
+		*sccc_block = ATSCMH_SCCC_BLK_SEP;
+		break;
+	case 0x01:
+		*sccc_block = ATSCMH_SCCC_BLK_COMB;
+		break;
+	default:
+		*sccc_block = ATSCMH_SCCC_BLK_RES;
+		break;
+	}
+fail:
+	return ret;
+}
+
+static int lg216x_get_sccc_code_mode(struct lg216x_state *state,
+				     enum atscmh_sccc_code_mode *mode_a,
+				     enum atscmh_sccc_code_mode *mode_b,
+				     enum atscmh_sccc_code_mode *mode_c,
+				     enum atscmh_sccc_code_mode *mode_d)
+{
+	u8 val;
+	int ret;
+
+	switch (state->cfg->lg_chip) {
+	case LG2160:
+		ret = lg216x_read_reg(state, 0x0316, &val);
+		break;
+	case LG2161:
+		ret = lg216x_read_reg(state, 0x0512, &val);
+		break;
+	default:
+		ret = -EINVAL;
+	}
+	if (lg_fail(ret))
+		goto fail;
+
+	switch ((val >> 6) & 0x03) {
+	case 0x00:
+		*mode_a = ATSCMH_SCCC_CODE_HLF;
+		break;
+	case 0x01:
+		*mode_a = ATSCMH_SCCC_CODE_QTR;
+		break;
+	default:
+		*mode_a = ATSCMH_SCCC_CODE_RES;
+		break;
+	}
+
+	switch ((val >> 4) & 0x03) {
+	case 0x00:
+		*mode_b = ATSCMH_SCCC_CODE_HLF;
+		break;
+	case 0x01:
+		*mode_b = ATSCMH_SCCC_CODE_QTR;
+		break;
+	default:
+		*mode_b = ATSCMH_SCCC_CODE_RES;
+		break;
+	}
+
+	switch ((val >> 2) & 0x03) {
+	case 0x00:
+		*mode_c = ATSCMH_SCCC_CODE_HLF;
+		break;
+	case 0x01:
+		*mode_c = ATSCMH_SCCC_CODE_QTR;
+		break;
+	default:
+		*mode_c = ATSCMH_SCCC_CODE_RES;
+		break;
+	}
+
+	switch (val & 0x03) {
+	case 0x00:
+		*mode_d = ATSCMH_SCCC_CODE_HLF;
+		break;
+	case 0x01:
+		*mode_d = ATSCMH_SCCC_CODE_QTR;
+		break;
+	default:
+		*mode_d = ATSCMH_SCCC_CODE_RES;
+		break;
+	}
+fail:
+	return ret;
+}
+
+/* ------------------------------------------------------------------------ */
+
+#if 0
+static int lg216x_read_fic_err_count(struct lg216x_state *state, u8 *err)
+{
+	u8 fic_err;
+	int ret;
+
+	*err = 0;
+
+	switch (state->cfg->lg_chip) {
+	case LG2160:
+		ret = lg216x_read_reg(state, 0x0012, &fic_err);
+		break;
+	case LG2161:
+		ret = lg216x_read_reg(state, 0x001e, &fic_err);
+		break;
+	}
+	if (lg_fail(ret))
+		goto fail;
+
+	*err = fic_err;
+fail:
+	return ret;
+}
+
+static int lg2160_read_crc_err_count(struct lg216x_state *state, u16 *err)
+{
+	u8 crc_err1, crc_err2;
+	int ret;
+
+	*err = 0;
+
+	ret = lg216x_read_reg(state, 0x0411, &crc_err1);
+	if (lg_fail(ret))
+		goto fail;
+
+	ret = lg216x_read_reg(state, 0x0412, &crc_err2);
+	if (lg_fail(ret))
+		goto fail;
+
+	*err = (u16)(((crc_err2 & 0x0f) << 8) | crc_err1);
+fail:
+	return ret;
+}
+
+static int lg2161_read_crc_err_count(struct lg216x_state *state, u16 *err)
+{
+	u8 crc_err;
+	int ret;
+
+	*err = 0;
+
+	ret = lg216x_read_reg(state, 0x0612, &crc_err);
+	if (lg_fail(ret))
+		goto fail;
+
+	*err = (u16)crc_err;
+fail:
+	return ret;
+}
+
+static int lg216x_read_crc_err_count(struct lg216x_state *state, u16 *err)
+{
+	int ret;
+	switch (state->cfg->lg_chip) {
+	case LG2160:
+		ret = lg2160_read_crc_err_count(state, err);
+		break;
+	case LG2161:
+		ret = lg2161_read_crc_err_count(state, err);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+	return ret;
+}
+
+static int lg2160_read_rs_err_count(struct lg216x_state *state, u16 *err)
+{
+	u8 rs_err1, rs_err2;
+	int ret;
+
+	*err = 0;
+
+	ret = lg216x_read_reg(state, 0x0413, &rs_err1);
+	if (lg_fail(ret))
+		goto fail;
+
+	ret = lg216x_read_reg(state, 0x0414, &rs_err2);
+	if (lg_fail(ret))
+		goto fail;
+
+	*err = (u16)(((rs_err2 & 0x0f) << 8) | rs_err1);
+fail:
+	return ret;
+}
+
+static int lg2161_read_rs_err_count(struct lg216x_state *state, u16 *err)
+{
+	u8 rs_err1, rs_err2;
+	int ret;
+
+	*err = 0;
+
+	ret = lg216x_read_reg(state, 0x0613, &rs_err1);
+	if (lg_fail(ret))
+		goto fail;
+
+	ret = lg216x_read_reg(state, 0x0614, &rs_err2);
+	if (lg_fail(ret))
+		goto fail;
+
+	*err = (u16)((rs_err1 << 8) | rs_err2);
+fail:
+	return ret;
+}
+
+static int lg216x_read_rs_err_count(struct lg216x_state *state, u16 *err)
+{
+	int ret;
+	switch (state->cfg->lg_chip) {
+	case LG2160:
+		ret = lg2160_read_rs_err_count(state, err);
+		break;
+	case LG2161:
+		ret = lg2161_read_rs_err_count(state, err);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+	return ret;
+}
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+static int lg216x_get_frontend(struct dvb_frontend *fe)
+{
+	struct lg216x_state *state = fe->demodulator_priv;
+	int ret;
+
+	lg_dbg("\n");
+
+	fe->dtv_property_cache.modulation = VSB_8;
+	fe->dtv_property_cache.frequency = state->current_frequency;
+	fe->dtv_property_cache.delivery_system = SYS_ATSCMH;
+
+	ret = lg216x_get_fic_version(state,
+				     &fe->dtv_property_cache.atscmh_fic_ver);
+	if (lg_fail(ret))
+		goto fail;
+	if (state->fic_ver != fe->dtv_property_cache.atscmh_fic_ver) {
+		state->fic_ver = fe->dtv_property_cache.atscmh_fic_ver;
+
+#if 0
+		ret = lg2160_get_parade_id(state,
+				&fe->dtv_property_cache.atscmh_parade_id);
+		if (lg_fail(ret))
+			goto fail;
+/* #else */
+		fe->dtv_property_cache.atscmh_parade_id = state->parade_id;
+#endif
+		ret = lg216x_get_nog(state,
+				     &fe->dtv_property_cache.atscmh_nog);
+		if (lg_fail(ret))
+			goto fail;
+		ret = lg216x_get_tnog(state,
+				      &fe->dtv_property_cache.atscmh_tnog);
+		if (lg_fail(ret))
+			goto fail;
+		ret = lg216x_get_sgn(state,
+				     &fe->dtv_property_cache.atscmh_sgn);
+		if (lg_fail(ret))
+			goto fail;
+		ret = lg216x_get_prc(state,
+				     &fe->dtv_property_cache.atscmh_prc);
+		if (lg_fail(ret))
+			goto fail;
+
+		ret = lg216x_get_rs_frame_mode(state,
+			(enum atscmh_rs_frame_mode *)
+			&fe->dtv_property_cache.atscmh_rs_frame_mode);
+		if (lg_fail(ret))
+			goto fail;
+		ret = lg216x_get_rs_frame_ensemble(state,
+			(enum atscmh_rs_frame_ensemble *)
+			&fe->dtv_property_cache.atscmh_rs_frame_ensemble);
+		if (lg_fail(ret))
+			goto fail;
+		ret = lg216x_get_rs_code_mode(state,
+			(enum atscmh_rs_code_mode *)
+			&fe->dtv_property_cache.atscmh_rs_code_mode_pri,
+			(enum atscmh_rs_code_mode *)
+			&fe->dtv_property_cache.atscmh_rs_code_mode_sec);
+		if (lg_fail(ret))
+			goto fail;
+		ret = lg216x_get_sccc_block_mode(state,
+			(enum atscmh_sccc_block_mode *)
+			&fe->dtv_property_cache.atscmh_sccc_block_mode);
+		if (lg_fail(ret))
+			goto fail;
+		ret = lg216x_get_sccc_code_mode(state,
+			(enum atscmh_sccc_code_mode *)
+			&fe->dtv_property_cache.atscmh_sccc_code_mode_a,
+			(enum atscmh_sccc_code_mode *)
+			&fe->dtv_property_cache.atscmh_sccc_code_mode_b,
+			(enum atscmh_sccc_code_mode *)
+			&fe->dtv_property_cache.atscmh_sccc_code_mode_c,
+			(enum atscmh_sccc_code_mode *)
+			&fe->dtv_property_cache.atscmh_sccc_code_mode_d);
+		if (lg_fail(ret))
+			goto fail;
+	}
+#if 0
+	ret = lg216x_read_fic_err_count(state,
+				(u8 *)&fe->dtv_property_cache.atscmh_fic_err);
+	if (lg_fail(ret))
+		goto fail;
+	ret = lg216x_read_crc_err_count(state,
+				&fe->dtv_property_cache.atscmh_crc_err);
+	if (lg_fail(ret))
+		goto fail;
+	ret = lg216x_read_rs_err_count(state,
+				&fe->dtv_property_cache.atscmh_rs_err);
+	if (lg_fail(ret))
+		goto fail;
+
+	switch (state->cfg->lg_chip) {
+	case LG2160:
+		if (((fe->dtv_property_cache.atscmh_rs_err >= 240) &&
+		     (fe->dtv_property_cache.atscmh_crc_err >= 240)) &&
+		    ((jiffies_to_msecs(jiffies) - state->last_reset) > 6000))
+			ret = lg216x_soft_reset(state);
+		break;
+	case LG2161:
+		/* no fix needed here (as far as we know) */
+		ret = 0;
+		break;
+	}
+	lg_fail(ret);
+#endif
+fail:
+	return ret;
+}
+
+static int lg216x_get_property(struct dvb_frontend *fe,
+			       struct dtv_property *tvp)
+{
+	return (DTV_ATSCMH_FIC_VER == tvp->cmd) ?
+		lg216x_get_frontend(fe) : 0;
+}
+
+
+static int lg2160_set_frontend(struct dvb_frontend *fe)
+{
+	struct lg216x_state *state = fe->demodulator_priv;
+	int ret;
+
+	lg_dbg("(%d)\n", fe->dtv_property_cache.frequency);
+
+	if (fe->ops.tuner_ops.set_params) {
+		ret = fe->ops.tuner_ops.set_params(fe);
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 0);
+		if (lg_fail(ret))
+			goto fail;
+		state->current_frequency = fe->dtv_property_cache.frequency;
+	}
+
+	ret = lg2160_agc_fix(state, 0, 0);
+	if (lg_fail(ret))
+		goto fail;
+	ret = lg2160_agc_polarity(state, 0, 0);
+	if (lg_fail(ret))
+		goto fail;
+	ret = lg2160_tuner_pwr_save_polarity(state, 1);
+	if (lg_fail(ret))
+		goto fail;
+	ret = lg216x_set_if(state);
+	if (lg_fail(ret))
+		goto fail;
+	ret = lg2160_spectrum_polarity(state, state->cfg->spectral_inversion);
+	if (lg_fail(ret))
+		goto fail;
+
+	/* be tuned before this point */
+	ret = lg216x_soft_reset(state);
+	if (lg_fail(ret))
+		goto fail;
+
+	ret = lg2160_tuner_pwr_save(state, 0);
+	if (lg_fail(ret))
+		goto fail;
+
+	switch (state->cfg->lg_chip) {
+	case LG2160:
+		ret = lg2160_set_spi_clock(state);
+		if (lg_fail(ret))
+			goto fail;
+		break;
+	case LG2161:
+		ret = lg2161_set_output_interface(state);
+		if (lg_fail(ret))
+			goto fail;
+		break;
+	}
+
+	ret = lg216x_set_parade(state, fe->dtv_property_cache.atscmh_parade_id);
+	if (lg_fail(ret))
+		goto fail;
+
+	ret = lg216x_set_ensemble(state,
+			fe->dtv_property_cache.atscmh_rs_frame_ensemble);
+	if (lg_fail(ret))
+		goto fail;
+
+	ret = lg216x_initialize(state);
+	if (lg_fail(ret))
+		goto fail;
+
+	ret = lg216x_enable_fic(state, 1);
+	lg_fail(ret);
+
+	lg216x_get_frontend(fe);
+fail:
+	return ret;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int lg2160_read_lock_status(struct lg216x_state *state,
+				   int *acq_lock, int *sync_lock)
+{
+	u8 val;
+	int ret;
+
+	*acq_lock = 0;
+	*sync_lock = 0;
+
+	ret = lg216x_read_reg(state, 0x011b, &val);
+	if (lg_fail(ret))
+		goto fail;
+
+	*sync_lock = (val & 0x20) ? 0 : 1;
+	*acq_lock  = (val & 0x40) ? 0 : 1;
+fail:
+	return ret;
+}
+
+#ifdef USE_LG2161_LOCK_BITS
+static int lg2161_read_lock_status(struct lg216x_state *state,
+				   int *acq_lock, int *sync_lock)
+{
+	u8 val;
+	int ret;
+
+	*acq_lock = 0;
+	*sync_lock = 0;
+
+	ret = lg216x_read_reg(state, 0x0304, &val);
+	if (lg_fail(ret))
+		goto fail;
+
+	*sync_lock = (val & 0x80) ? 0 : 1;
+
+	ret = lg216x_read_reg(state, 0x011b, &val);
+	if (lg_fail(ret))
+		goto fail;
+
+	*acq_lock  = (val & 0x40) ? 0 : 1;
+fail:
+	return ret;
+}
+#endif
+
+static int lg216x_read_lock_status(struct lg216x_state *state,
+				   int *acq_lock, int *sync_lock)
+{
+#ifdef USE_LG2161_LOCK_BITS
+	int ret;
+	switch (state->cfg->lg_chip) {
+	case LG2160:
+		ret = lg2160_read_lock_status(state, acq_lock, sync_lock);
+		break;
+	case LG2161:
+		ret = lg2161_read_lock_status(state, acq_lock, sync_lock);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+	return ret;
+#else
+	return lg2160_read_lock_status(state, acq_lock, sync_lock);
+#endif
+}
+
+static int lg216x_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+	struct lg216x_state *state = fe->demodulator_priv;
+	int ret, acq_lock, sync_lock;
+
+	*status = 0;
+
+	ret = lg216x_read_lock_status(state, &acq_lock, &sync_lock);
+	if (lg_fail(ret))
+		goto fail;
+
+	lg_dbg("%s%s\n",
+	       acq_lock  ? "SIGNALEXIST " : "",
+	       sync_lock ? "SYNCLOCK"     : "");
+
+	if (acq_lock)
+		*status |= FE_HAS_SIGNAL;
+	if (sync_lock)
+		*status |= FE_HAS_SYNC;
+
+	if (*status)
+		*status |= FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_LOCK;
+
+fail:
+	return ret;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int lg2160_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+	struct lg216x_state *state = fe->demodulator_priv;
+	u8 snr1, snr2;
+	int ret;
+
+	*snr = 0;
+
+	ret = lg216x_read_reg(state, 0x0202, &snr1);
+	if (lg_fail(ret))
+		goto fail;
+
+	ret = lg216x_read_reg(state, 0x0203, &snr2);
+	if (lg_fail(ret))
+		goto fail;
+
+	if ((snr1 == 0xba) || (snr2 == 0xdf))
+		*snr = 0;
+	else
+#if 1
+	*snr =  ((snr1 >> 4) * 100) + ((snr1 & 0x0f) * 10) + (snr2 >> 4);
+#else /* BCD */
+	*snr =  (snr2 | (snr1 << 8));
+#endif
+fail:
+	return ret;
+}
+
+static int lg2161_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+	struct lg216x_state *state = fe->demodulator_priv;
+	u8 snr1, snr2;
+	int ret;
+
+	*snr = 0;
+
+	ret = lg216x_read_reg(state, 0x0302, &snr1);
+	if (lg_fail(ret))
+		goto fail;
+
+	ret = lg216x_read_reg(state, 0x0303, &snr2);
+	if (lg_fail(ret))
+		goto fail;
+
+	if ((snr1 == 0xba) || (snr2 == 0xfd))
+		*snr = 0;
+	else
+
+	*snr =  ((snr1 >> 4) * 100) + ((snr1 & 0x0f) * 10) + (snr2 & 0x0f);
+fail:
+	return ret;
+}
+
+static int lg216x_read_signal_strength(struct dvb_frontend *fe,
+				       u16 *strength)
+{
+#if 0
+	/* 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 lg216x_state *state = fe->demodulator_priv;
+	u16 snr;
+	int ret;
+#endif
+	*strength = 0;
+#if 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;
+#else
+	return 0;
+#endif
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int lg216x_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+#if 0
+	struct lg216x_state *state = fe->demodulator_priv;
+	int ret;
+
+	ret = lg216x_read_rs_err_count(state,
+				       &fe->dtv_property_cache.atscmh_rs_err);
+	if (lg_fail(ret))
+		goto fail;
+
+	*ucblocks = fe->dtv_property_cache.atscmh_rs_err;
+fail:
+#else
+	*ucblocks = 0;
+#endif
+	return 0;
+}
+
+static int lg216x_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 lg216x_release(struct dvb_frontend *fe)
+{
+	struct lg216x_state *state = fe->demodulator_priv;
+	lg_dbg("\n");
+	kfree(state);
+}
+
+static struct dvb_frontend_ops lg2160_ops = {
+	.delsys = { SYS_ATSCMH },
+	.info = {
+		.name = "LG Electronics LG2160 ATSC/MH Frontend",
+		.frequency_min      = 54000000,
+		.frequency_max      = 858000000,
+		.frequency_stepsize = 62500,
+	},
+	.i2c_gate_ctrl        = lg216x_i2c_gate_ctrl,
+#if 0
+	.init                 = lg216x_init,
+	.sleep                = lg216x_sleep,
+#endif
+	.get_property         = lg216x_get_property,
+
+	.set_frontend         = lg2160_set_frontend,
+	.get_frontend         = lg216x_get_frontend,
+	.get_tune_settings    = lg216x_get_tune_settings,
+	.read_status          = lg216x_read_status,
+#if 0
+	.read_ber             = lg216x_read_ber,
+#endif
+	.read_signal_strength = lg216x_read_signal_strength,
+	.read_snr             = lg2160_read_snr,
+	.read_ucblocks        = lg216x_read_ucblocks,
+	.release              = lg216x_release,
+};
+
+static struct dvb_frontend_ops lg2161_ops = {
+	.delsys = { SYS_ATSCMH },
+	.info = {
+		.name = "LG Electronics LG2161 ATSC/MH Frontend",
+		.frequency_min      = 54000000,
+		.frequency_max      = 858000000,
+		.frequency_stepsize = 62500,
+	},
+	.i2c_gate_ctrl        = lg216x_i2c_gate_ctrl,
+#if 0
+	.init                 = lg216x_init,
+	.sleep                = lg216x_sleep,
+#endif
+	.get_property         = lg216x_get_property,
+
+	.set_frontend         = lg2160_set_frontend,
+	.get_frontend         = lg216x_get_frontend,
+	.get_tune_settings    = lg216x_get_tune_settings,
+	.read_status          = lg216x_read_status,
+#if 0
+	.read_ber             = lg216x_read_ber,
+#endif
+	.read_signal_strength = lg216x_read_signal_strength,
+	.read_snr             = lg2161_read_snr,
+	.read_ucblocks        = lg216x_read_ucblocks,
+	.release              = lg216x_release,
+};
+
+struct dvb_frontend *lg2160_attach(const struct lg2160_config *config,
+				   struct i2c_adapter *i2c_adap)
+{
+	struct lg216x_state *state = NULL;
+
+	lg_dbg("(%d-%04x)\n",
+	       i2c_adap ? i2c_adapter_id(i2c_adap) : 0,
+	       config ? config->i2c_addr : 0);
+
+	state = kzalloc(sizeof(struct lg216x_state), GFP_KERNEL);
+	if (state == NULL)
+		goto fail;
+
+	state->cfg = config;
+	state->i2c_adap = i2c_adap;
+	state->fic_ver = 0xff;
+	state->parade_id = 0xff;
+
+	switch (config->lg_chip) {
+	default:
+		lg_warn("invalid chip requested, defaulting to LG2160");
+		/* fall-thru */
+	case LG2160:
+		memcpy(&state->frontend.ops, &lg2160_ops,
+		       sizeof(struct dvb_frontend_ops));
+		break;
+	case LG2161:
+		memcpy(&state->frontend.ops, &lg2161_ops,
+		       sizeof(struct dvb_frontend_ops));
+		break;
+	}
+
+	state->frontend.demodulator_priv = state;
+	state->current_frequency = -1;
+	/* parade 1 by default */
+	state->frontend.dtv_property_cache.atscmh_parade_id = 1;
+
+	return &state->frontend;
+fail:
+	lg_warn("unable to detect LG216x hardware\n");
+	kfree(state);
+	return NULL;
+}
+EXPORT_SYMBOL(lg2160_attach);
+
+MODULE_DESCRIPTION("LG Electronics LG216x ATSC/MH Demodulator Driver");
+MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("0.3");
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/dvb-frontends/lg2160.h b/drivers/media/dvb-frontends/lg2160.h
new file mode 100644
index 0000000..9e2c0f4
--- /dev/null
+++ b/drivers/media/dvb-frontends/lg2160.h
@@ -0,0 +1,84 @@
+/*
+ *    Support for LG2160 - ATSC/MH
+ *
+ *    Copyright (C) 2010 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 _LG2160_H_
+#define _LG2160_H_
+
+#include <linux/i2c.h>
+#include "dvb_frontend.h"
+
+enum lg_chip_type {
+	LG2160 = 0,
+	LG2161 = 1,
+};
+
+#define LG2161_1019 LG2161
+#define LG2161_1040 LG2161
+
+enum lg2160_spi_clock {
+	LG2160_SPI_3_125_MHZ = 0,
+	LG2160_SPI_6_25_MHZ = 1,
+	LG2160_SPI_12_5_MHZ = 2,
+};
+
+#if 0
+enum lg2161_oif {
+	LG2161_OIF_EBI2_SLA  = 1,
+	LG2161_OIF_SDIO_SLA  = 2,
+	LG2161_OIF_SPI_SLA   = 3,
+	LG2161_OIF_SPI_MAS   = 4,
+	LG2161_OIF_SERIAL_TS = 7,
+};
+#endif
+
+struct lg2160_config {
+	u8 i2c_addr;
+
+	/* user defined IF frequency in KHz */
+	u16 if_khz;
+
+	/* disable i2c repeater - 0:repeater enabled 1:repeater disabled */
+	int deny_i2c_rptr:1;
+
+	/* spectral inversion - 0:disabled 1:enabled */
+	int spectral_inversion:1;
+
+	unsigned int output_if;
+	enum lg2160_spi_clock spi_clock;
+	enum lg_chip_type lg_chip;
+};
+
+#if defined(CONFIG_DVB_LG2160) || (defined(CONFIG_DVB_LG2160_MODULE) && \
+				     defined(MODULE))
+extern
+struct dvb_frontend *lg2160_attach(const struct lg2160_config *config,
+				     struct i2c_adapter *i2c_adap);
+#else
+static inline
+struct dvb_frontend *lg2160_attach(const struct lg2160_config *config,
+				     struct i2c_adapter *i2c_adap)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif /* CONFIG_DVB_LG2160 */
+
+#endif /* _LG2160_H_ */
diff --git a/drivers/media/dvb-frontends/lgdt3305.c b/drivers/media/dvb-frontends/lgdt3305.c
new file mode 100644
index 0000000..1d2c473
--- /dev/null
+++ b/drivers/media/dvb-frontends/lgdt3305.c
@@ -0,0 +1,1222 @@
+/*
+ *    Support for LG Electronics LGDT3304 and LGDT3305 - VSB/QAM
+ *
+ *    Copyright (C) 2008, 2009, 2010 Michael Krufky <mkrufky@linuxtv.org>
+ *
+ *    LGDT3304 support by Jarod Wilson <jarod@redhat.com>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <asm/div64.h>
+#include <linux/dvb/frontend.h>
+#include <linux/slab.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;
+};
+
+/* ------------------------------------------------------------------------ */
+
+/* FIXME: verify & document the LGDT3304 registers */
+
+#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 dtv_frontend_properties *p)
+{
+	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 (p->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 dtv_frontend_properties *p)
+{
+	int val;
+
+	switch (p->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 dtv_frontend_properties *p)
+{
+	u16 agc_ref;
+
+	switch (p->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 dtv_frontend_properties *p)
+{
+	u16 ifbw, rfbw, agcdelay;
+
+	switch (p->modulation) {
+	case VSB_8:
+		agcdelay = 0x04c0;
+		rfbw     = 0x8000;
+		ifbw     = 0x8000;
+		break;
+	case QAM_64:
+	case QAM_256:
+		agcdelay = 0x046b;
+		rfbw     = 0x8889;
+		/* FIXME: investigate optimal ifbw & rfbw values for the
+		 *        DT3304 and re-write this switch..case block */
+		if (state->cfg->demod_chip == LGDT3304)
+			ifbw = 0x6666;
+		else /* (state->cfg->demod_chip == LGDT3305) */
+			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 dtv_frontend_properties *p)
+{
+	int lockdten, acqen;
+
+	switch (p->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 */
+	switch (state->cfg->demod_chip) {
+	case LGDT3304:
+		lgdt3305_write_reg(state, 0x0314, 0xe1 | lockdten << 1);
+		lgdt3305_set_reg_bit(state, 0x030e, 2, acqen);
+		break;
+	case LGDT3305:
+		lgdt3305_write_reg(state, LGDT3305_AGC_CTRL_4, 0xe1 | lockdten << 1);
+		lgdt3305_set_reg_bit(state, LGDT3305_AGC_CTRL_1, 2, acqen);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return lgdt3305_rfagc_loop(state, p);
+}
+
+static int lgdt3305_set_agc_power_ref(struct lgdt3305_state *state,
+				      struct dtv_frontend_properties *p)
+{
+	u16 usref = 0;
+
+	switch (p->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 dtv_frontend_properties *p,
+				       int inversion)
+{
+	int ret;
+
+	lg_dbg("(%d)\n", inversion);
+
+	switch (p->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 dtv_frontend_properties *p)
+{
+	u16 if_freq_khz;
+	u8 nco1, nco2, nco3, nco4;
+	u64 nco;
+
+	switch (p->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;
+
+	switch (p->modulation) {
+	case VSB_8:
+		nco <<= 24;
+		do_div(nco, 625);
+		break;
+	case QAM_64:
+	case QAM_256:
+		nco <<= 28;
+		do_div(nco, 625);
+		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 lgdt3304_init_data[] = {
+		{ .reg = LGDT3305_GEN_CTRL_1,           .val = 0x03, },
+		{ .reg = 0x000d,                        .val = 0x02, },
+		{ .reg = 0x000e,                        .val = 0x02, },
+		{ .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 = 0xf9, },
+		{ .reg = 0x0112,                        .val = 0x17, },
+		{ .reg = 0x0113,                        .val = 0x15, },
+		{ .reg = 0x0114,                        .val = 0x18, },
+		{ .reg = 0x0115,                        .val = 0xff, },
+		{ .reg = 0x0116,                        .val = 0x3c, },
+		{ .reg = 0x0214,                        .val = 0x67, },
+		{ .reg = 0x0424,                        .val = 0x8d, },
+		{ .reg = 0x0427,                        .val = 0x12, },
+		{ .reg = 0x0428,                        .val = 0x4f, },
+		{ .reg = LGDT3305_IFBW_1,               .val = 0x80, },
+		{ .reg = LGDT3305_IFBW_2,               .val = 0x00, },
+		{ .reg = 0x030a,                        .val = 0x08, },
+		{ .reg = 0x030b,                        .val = 0x9b, },
+		{ .reg = 0x030d,                        .val = 0x00, },
+		{ .reg = 0x030e,                        .val = 0x1c, },
+		{ .reg = 0x0314,                        .val = 0xe1, },
+		{ .reg = 0x000d,                        .val = 0x82, },
+		{ .reg = LGDT3305_TP_CTRL_1,            .val = 0x5b, },
+		{ .reg = LGDT3305_TP_CTRL_1,            .val = 0x5b, },
+	};
+
+	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");
+
+	switch (state->cfg->demod_chip) {
+	case LGDT3304:
+		ret = lgdt3305_write_regs(state, lgdt3304_init_data,
+					  ARRAY_SIZE(lgdt3304_init_data));
+		break;
+	case LGDT3305:
+		ret = lgdt3305_write_regs(state, lgdt3305_init_data,
+					  ARRAY_SIZE(lgdt3305_init_data));
+		break;
+	default:
+		ret = -EINVAL;
+	}
+	if (lg_fail(ret))
+		goto fail;
+
+	ret = lgdt3305_soft_reset(state);
+fail:
+	return ret;
+}
+
+static int lgdt3304_set_parameters(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct lgdt3305_state *state = fe->demodulator_priv;
+	int ret;
+
+	lg_dbg("(%d, %d)\n", p->frequency, p->modulation);
+
+	if (fe->ops.tuner_ops.set_params) {
+		ret = fe->ops.tuner_ops.set_params(fe);
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 0);
+		if (lg_fail(ret))
+			goto fail;
+		state->current_frequency = p->frequency;
+	}
+
+	ret = lgdt3305_set_modulation(state, p);
+	if (lg_fail(ret))
+		goto fail;
+
+	ret = lgdt3305_passband_digital_agc(state, p);
+	if (lg_fail(ret))
+		goto fail;
+
+	ret = lgdt3305_agc_setup(state, p);
+	if (lg_fail(ret))
+		goto fail;
+
+	/* reg 0x030d is 3304-only... seen in vsb and qam usbsnoops... */
+	switch (p->modulation) {
+	case VSB_8:
+		lgdt3305_write_reg(state, 0x030d, 0x00);
+		lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_1, 0x4f);
+		lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_2, 0x0c);
+		lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_3, 0xac);
+		lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_4, 0xba);
+		break;
+	case QAM_64:
+	case QAM_256:
+		lgdt3305_write_reg(state, 0x030d, 0x14);
+		ret = lgdt3305_set_if(state, p);
+		if (lg_fail(ret))
+			goto fail;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+
+	ret = lgdt3305_spectral_inversion(state, p,
+					  state->cfg->spectral_inversion
+					  ? 1 : 0);
+	if (lg_fail(ret))
+		goto fail;
+
+	state->current_modulation = p->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_set_parameters(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct lgdt3305_state *state = fe->demodulator_priv;
+	int ret;
+
+	lg_dbg("(%d, %d)\n", p->frequency, p->modulation);
+
+	if (fe->ops.tuner_ops.set_params) {
+		ret = fe->ops.tuner_ops.set_params(fe);
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 0);
+		if (lg_fail(ret))
+			goto fail;
+		state->current_frequency = p->frequency;
+	}
+
+	ret = lgdt3305_set_modulation(state, p);
+	if (lg_fail(ret))
+		goto fail;
+
+	ret = lgdt3305_passband_digital_agc(state, p);
+	if (lg_fail(ret))
+		goto fail;
+	ret = lgdt3305_set_agc_power_ref(state, p);
+	if (lg_fail(ret))
+		goto fail;
+	ret = lgdt3305_agc_setup(state, p);
+	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, p);
+	if (lg_fail(ret))
+		goto fail;
+	ret = lgdt3305_spectral_inversion(state, p,
+					  state->cfg->spectral_inversion
+					  ? 1 : 0);
+	if (lg_fail(ret))
+		goto fail;
+
+	ret = lgdt3305_set_filter_extension(state, p);
+	if (lg_fail(ret))
+		goto fail;
+
+	state->current_modulation = p->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 dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct lgdt3305_state *state = fe->demodulator_priv;
+
+	lg_dbg("\n");
+
+	p->modulation = state->current_modulation;
+	p->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:
+		/* signal bit is unreliable on the DT3304 in QAM mode */
+		if (((LGDT3304 == state->cfg->demod_chip)) && (cr_lock))
+			*status |= FE_HAS_SIGNAL;
+
+		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 lgdt3304_ops;
+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;
+
+	switch (config->demod_chip) {
+	case LGDT3304:
+		memcpy(&state->frontend.ops, &lgdt3304_ops,
+		       sizeof(struct dvb_frontend_ops));
+		break;
+	case LGDT3305:
+		memcpy(&state->frontend.ops, &lgdt3305_ops,
+		       sizeof(struct dvb_frontend_ops));
+		break;
+	default:
+		goto fail;
+	}
+	state->frontend.demodulator_priv = state;
+
+	/* verify that we're talking to a lg dt3304/5 */
+	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 %s hardware\n",
+		config->demod_chip ? "LGDT3304" : "LGDT3305");
+	kfree(state);
+	return NULL;
+}
+EXPORT_SYMBOL(lgdt3305_attach);
+
+static struct dvb_frontend_ops lgdt3304_ops = {
+	.delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
+	.info = {
+		.name = "LG Electronics LGDT3304 VSB/QAM Frontend",
+		.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,
+	.set_frontend         = lgdt3304_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,
+};
+
+static struct dvb_frontend_ops lgdt3305_ops = {
+	.delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
+	.info = {
+		.name = "LG Electronics LGDT3305 VSB/QAM Frontend",
+		.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 LGDT3304/5 ATSC/QAM-B Demodulator Driver");
+MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("0.2");
+
+/*
+ * 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..02172ec
--- /dev/null
+++ b/drivers/media/dvb-frontends/lgdt3305.h
@@ -0,0 +1,91 @@
+/*
+ *    Support for LG Electronics LGDT3304 and LGDT3305 - VSB/QAM
+ *
+ *    Copyright (C) 2008, 2009, 2010 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,
+};
+
+enum lgdt_demod_chip_type {
+	LGDT3305 = 0,
+	LGDT3304 = 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 */
+	unsigned int deny_i2c_rptr:1;
+
+	/* spectral inversion - 0:disabled 1:enabled */
+	unsigned int spectral_inversion:1;
+
+	/* use RF AGC loop - 0:disabled 1:enabled */
+	unsigned 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;
+	enum lgdt_demod_chip_type demod_chip;
+};
+
+#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/lgdt330x.c b/drivers/media/dvb-frontends/lgdt330x.c
new file mode 100644
index 0000000..e046622
--- /dev/null
+++ b/drivers/media/dvb-frontends/lgdt330x.c
@@ -0,0 +1,831 @@
+/*
+ *    Support for LGDT3302 and LGDT3303 - VSB/QAM
+ *
+ *    Copyright (C) 2005 Wilson Michaels <wilsonmichaels@earthlink.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 program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You 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.
+ *
+ */
+
+/*
+ *                      NOTES ABOUT THIS DRIVER
+ *
+ * This Linux driver supports:
+ *   DViCO FusionHDTV 3 Gold-Q
+ *   DViCO FusionHDTV 3 Gold-T
+ *   DViCO FusionHDTV 5 Gold
+ *   DViCO FusionHDTV 5 Lite
+ *   DViCO FusionHDTV 5 USB Gold
+ *   Air2PC/AirStar 2 ATSC 3rd generation (HD5000)
+ *   pcHDTV HD5500
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <asm/byteorder.h>
+
+#include "dvb_frontend.h"
+#include "dvb_math.h"
+#include "lgdt330x_priv.h"
+#include "lgdt330x.h"
+
+/* Use Equalizer Mean Squared Error instead of Phaser Tracker MSE */
+/* #define USE_EQMSE */
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug,"Turn on/off lgdt330x frontend debugging (default:off).");
+#define dprintk(args...) \
+do { \
+if (debug) printk(KERN_DEBUG "lgdt330x: " args); \
+} while (0)
+
+struct lgdt330x_state
+{
+	struct i2c_adapter* i2c;
+
+	/* Configuration settings */
+	const struct lgdt330x_config* config;
+
+	struct dvb_frontend frontend;
+
+	/* Demodulator private data */
+	fe_modulation_t current_modulation;
+	u32 snr; /* Result of last SNR calculation */
+
+	/* Tuner private data */
+	u32 current_frequency;
+};
+
+static int i2c_write_demod_bytes (struct lgdt330x_state* state,
+				  u8 *buf, /* data bytes to send */
+				  int len  /* number of bytes to send */ )
+{
+	struct i2c_msg msg =
+		{ .addr = state->config->demod_address,
+		  .flags = 0,
+		  .buf = buf,
+		  .len = 2 };
+	int i;
+	int err;
+
+	for (i=0; i<len-1; i+=2){
+		if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
+			printk(KERN_WARNING "lgdt330x: %s error (addr %02x <- %02x, err = %i)\n", __func__, msg.buf[0], msg.buf[1], err);
+			if (err < 0)
+				return err;
+			else
+				return -EREMOTEIO;
+		}
+		msg.buf += 2;
+	}
+	return 0;
+}
+
+/*
+ * This routine writes the register (reg) to the demod bus
+ * then reads the data returned for (len) bytes.
+ */
+
+static int i2c_read_demod_bytes(struct lgdt330x_state *state,
+				enum I2C_REG reg, u8 *buf, int len)
+{
+	u8 wr [] = { reg };
+	struct i2c_msg msg [] = {
+		{ .addr = state->config->demod_address,
+		  .flags = 0, .buf = wr,  .len = 1 },
+		{ .addr = state->config->demod_address,
+		  .flags = I2C_M_RD, .buf = buf, .len = len },
+	};
+	int ret;
+	ret = i2c_transfer(state->i2c, msg, 2);
+	if (ret != 2) {
+		printk(KERN_WARNING "lgdt330x: %s: addr 0x%02x select 0x%02x error (ret == %i)\n", __func__, state->config->demod_address, reg, ret);
+		if (ret >= 0)
+			ret = -EIO;
+	} else {
+		ret = 0;
+	}
+	return ret;
+}
+
+/* Software reset */
+static int lgdt3302_SwReset(struct lgdt330x_state* state)
+{
+	u8 ret;
+	u8 reset[] = {
+		IRQ_MASK,
+		0x00 /* bit 6 is active low software reset
+		      *	bits 5-0 are 1 to mask interrupts */
+	};
+
+	ret = i2c_write_demod_bytes(state,
+				    reset, sizeof(reset));
+	if (ret == 0) {
+
+		/* force reset high (inactive) and unmask interrupts */
+		reset[1] = 0x7f;
+		ret = i2c_write_demod_bytes(state,
+					    reset, sizeof(reset));
+	}
+	return ret;
+}
+
+static int lgdt3303_SwReset(struct lgdt330x_state* state)
+{
+	u8 ret;
+	u8 reset[] = {
+		0x02,
+		0x00 /* bit 0 is active low software reset */
+	};
+
+	ret = i2c_write_demod_bytes(state,
+				    reset, sizeof(reset));
+	if (ret == 0) {
+
+		/* force reset high (inactive) */
+		reset[1] = 0x01;
+		ret = i2c_write_demod_bytes(state,
+					    reset, sizeof(reset));
+	}
+	return ret;
+}
+
+static int lgdt330x_SwReset(struct lgdt330x_state* state)
+{
+	switch (state->config->demod_chip) {
+	case LGDT3302:
+		return lgdt3302_SwReset(state);
+	case LGDT3303:
+		return lgdt3303_SwReset(state);
+	default:
+		return -ENODEV;
+	}
+}
+
+static int lgdt330x_init(struct dvb_frontend* fe)
+{
+	/* Hardware reset is done using gpio[0] of cx23880x chip.
+	 * I'd like to do it here, but don't know how to find chip address.
+	 * cx88-cards.c arranges for the reset bit to be inactive (high).
+	 * Maybe there needs to be a callable function in cx88-core or
+	 * the caller of this function needs to do it. */
+
+	/*
+	 * Array of byte pairs <address, value>
+	 * to initialize each different chip
+	 */
+	static u8 lgdt3302_init_data[] = {
+		/* Use 50MHz parameter values from spec sheet since xtal is 50 */
+		/* Change the value of NCOCTFV[25:0] of carrier
+		   recovery center frequency register */
+		VSB_CARRIER_FREQ0, 0x00,
+		VSB_CARRIER_FREQ1, 0x87,
+		VSB_CARRIER_FREQ2, 0x8e,
+		VSB_CARRIER_FREQ3, 0x01,
+		/* Change the TPCLK pin polarity
+		   data is valid on falling clock */
+		DEMUX_CONTROL, 0xfb,
+		/* Change the value of IFBW[11:0] of
+		   AGC IF/RF loop filter bandwidth register */
+		AGC_RF_BANDWIDTH0, 0x40,
+		AGC_RF_BANDWIDTH1, 0x93,
+		AGC_RF_BANDWIDTH2, 0x00,
+		/* Change the value of bit 6, 'nINAGCBY' and
+		   'NSSEL[1:0] of ACG function control register 2 */
+		AGC_FUNC_CTRL2, 0xc6,
+		/* Change the value of bit 6 'RFFIX'
+		   of AGC function control register 3 */
+		AGC_FUNC_CTRL3, 0x40,
+		/* Set the value of 'INLVTHD' register 0x2a/0x2c
+		   to 0x7fe */
+		AGC_DELAY0, 0x07,
+		AGC_DELAY2, 0xfe,
+		/* Change the value of IAGCBW[15:8]
+		   of inner AGC loop filter bandwidth */
+		AGC_LOOP_BANDWIDTH0, 0x08,
+		AGC_LOOP_BANDWIDTH1, 0x9a
+	};
+
+	static u8 lgdt3303_init_data[] = {
+		0x4c, 0x14
+	};
+
+	static u8 flip_1_lgdt3303_init_data[] = {
+		0x4c, 0x14,
+		0x87, 0xf3
+	};
+
+	static u8 flip_2_lgdt3303_init_data[] = {
+		0x4c, 0x14,
+		0x87, 0xda
+	};
+
+	struct lgdt330x_state* state = fe->demodulator_priv;
+	char  *chip_name;
+	int    err;
+
+	switch (state->config->demod_chip) {
+	case LGDT3302:
+		chip_name = "LGDT3302";
+		err = i2c_write_demod_bytes(state, lgdt3302_init_data,
+					    sizeof(lgdt3302_init_data));
+		break;
+	case LGDT3303:
+		chip_name = "LGDT3303";
+		switch (state->config->clock_polarity_flip) {
+		case 2:
+			err = i2c_write_demod_bytes(state,
+					flip_2_lgdt3303_init_data,
+					sizeof(flip_2_lgdt3303_init_data));
+			break;
+		case 1:
+			err = i2c_write_demod_bytes(state,
+					flip_1_lgdt3303_init_data,
+					sizeof(flip_1_lgdt3303_init_data));
+			break;
+		case 0:
+		default:
+			err = i2c_write_demod_bytes(state, lgdt3303_init_data,
+						    sizeof(lgdt3303_init_data));
+		}
+		break;
+	default:
+		chip_name = "undefined";
+		printk (KERN_WARNING "Only LGDT3302 and LGDT3303 are supported chips.\n");
+		err = -ENODEV;
+	}
+	dprintk("%s entered as %s\n", __func__, chip_name);
+	if (err < 0)
+		return err;
+	return lgdt330x_SwReset(state);
+}
+
+static int lgdt330x_read_ber(struct dvb_frontend* fe, u32* ber)
+{
+	*ber = 0; /* Not supplied by the demod chips */
+	return 0;
+}
+
+static int lgdt330x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
+{
+	struct lgdt330x_state* state = fe->demodulator_priv;
+	int err;
+	u8 buf[2];
+
+	*ucblocks = 0;
+
+	switch (state->config->demod_chip) {
+	case LGDT3302:
+		err = i2c_read_demod_bytes(state, LGDT3302_PACKET_ERR_COUNTER1,
+					   buf, sizeof(buf));
+		break;
+	case LGDT3303:
+		err = i2c_read_demod_bytes(state, LGDT3303_PACKET_ERR_COUNTER1,
+					   buf, sizeof(buf));
+		break;
+	default:
+		printk(KERN_WARNING
+		       "Only LGDT3302 and LGDT3303 are supported chips.\n");
+		err = -ENODEV;
+	}
+	if (err < 0)
+		return err;
+
+	*ucblocks = (buf[0] << 8) | buf[1];
+	return 0;
+}
+
+static int lgdt330x_set_parameters(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	/*
+	 * Array of byte pairs <address, value>
+	 * to initialize 8VSB for lgdt3303 chip 50 MHz IF
+	 */
+	static u8 lgdt3303_8vsb_44_data[] = {
+		0x04, 0x00,
+		0x0d, 0x40,
+		0x0e, 0x87,
+		0x0f, 0x8e,
+		0x10, 0x01,
+		0x47, 0x8b };
+
+	/*
+	 * Array of byte pairs <address, value>
+	 * to initialize QAM for lgdt3303 chip
+	 */
+	static u8 lgdt3303_qam_data[] = {
+		0x04, 0x00,
+		0x0d, 0x00,
+		0x0e, 0x00,
+		0x0f, 0x00,
+		0x10, 0x00,
+		0x51, 0x63,
+		0x47, 0x66,
+		0x48, 0x66,
+		0x4d, 0x1a,
+		0x49, 0x08,
+		0x4a, 0x9b };
+
+	struct lgdt330x_state* state = fe->demodulator_priv;
+
+	static u8 top_ctrl_cfg[]   = { TOP_CONTROL, 0x03 };
+
+	int err = 0;
+	/* Change only if we are actually changing the modulation */
+	if (state->current_modulation != p->modulation) {
+		switch (p->modulation) {
+		case VSB_8:
+			dprintk("%s: VSB_8 MODE\n", __func__);
+
+			/* Select VSB mode */
+			top_ctrl_cfg[1] = 0x03;
+
+			/* Select ANT connector if supported by card */
+			if (state->config->pll_rf_set)
+				state->config->pll_rf_set(fe, 1);
+
+			if (state->config->demod_chip == LGDT3303) {
+				err = i2c_write_demod_bytes(state, lgdt3303_8vsb_44_data,
+							    sizeof(lgdt3303_8vsb_44_data));
+			}
+			break;
+
+		case QAM_64:
+			dprintk("%s: QAM_64 MODE\n", __func__);
+
+			/* Select QAM_64 mode */
+			top_ctrl_cfg[1] = 0x00;
+
+			/* Select CABLE connector if supported by card */
+			if (state->config->pll_rf_set)
+				state->config->pll_rf_set(fe, 0);
+
+			if (state->config->demod_chip == LGDT3303) {
+				err = i2c_write_demod_bytes(state, lgdt3303_qam_data,
+											sizeof(lgdt3303_qam_data));
+			}
+			break;
+
+		case QAM_256:
+			dprintk("%s: QAM_256 MODE\n", __func__);
+
+			/* Select QAM_256 mode */
+			top_ctrl_cfg[1] = 0x01;
+
+			/* Select CABLE connector if supported by card */
+			if (state->config->pll_rf_set)
+				state->config->pll_rf_set(fe, 0);
+
+			if (state->config->demod_chip == LGDT3303) {
+				err = i2c_write_demod_bytes(state, lgdt3303_qam_data,
+											sizeof(lgdt3303_qam_data));
+			}
+			break;
+		default:
+			printk(KERN_WARNING "lgdt330x: %s: Modulation type(%d) UNSUPPORTED\n", __func__, p->modulation);
+			return -1;
+		}
+		if (err < 0)
+			printk(KERN_WARNING "lgdt330x: %s: error blasting "
+			       "bytes to lgdt3303 for modulation type(%d)\n",
+			       __func__, p->modulation);
+
+		/*
+		 * select serial or parallel MPEG harware interface
+		 * Serial:   0x04 for LGDT3302 or 0x40 for LGDT3303
+		 * Parallel: 0x00
+		 */
+		top_ctrl_cfg[1] |= state->config->serial_mpeg;
+
+		/* Select the requested mode */
+		i2c_write_demod_bytes(state, top_ctrl_cfg,
+				      sizeof(top_ctrl_cfg));
+		if (state->config->set_ts_params)
+			state->config->set_ts_params(fe, 0);
+		state->current_modulation = p->modulation;
+	}
+
+	/* Tune to the specified frequency */
+	if (fe->ops.tuner_ops.set_params) {
+		fe->ops.tuner_ops.set_params(fe);
+		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+	}
+
+	/* Keep track of the new frequency */
+	/* FIXME this is the wrong way to do this...           */
+	/* The tuner is shared with the video4linux analog API */
+	state->current_frequency = p->frequency;
+
+	lgdt330x_SwReset(state);
+	return 0;
+}
+
+static int lgdt330x_get_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct lgdt330x_state *state = fe->demodulator_priv;
+	p->frequency = state->current_frequency;
+	return 0;
+}
+
+static int lgdt3302_read_status(struct dvb_frontend* fe, fe_status_t* status)
+{
+	struct lgdt330x_state* state = fe->demodulator_priv;
+	u8 buf[3];
+
+	*status = 0; /* Reset status result */
+
+	/* AGC status register */
+	i2c_read_demod_bytes(state, AGC_STATUS, buf, 1);
+	dprintk("%s: AGC_STATUS = 0x%02x\n", __func__, buf[0]);
+	if ((buf[0] & 0x0c) == 0x8){
+		/* Test signal does not exist flag */
+		/* as well as the AGC lock flag.   */
+		*status |= FE_HAS_SIGNAL;
+	}
+
+	/*
+	 * You must set the Mask bits to 1 in the IRQ_MASK in order
+	 * to see that status bit in the IRQ_STATUS register.
+	 * This is done in SwReset();
+	 */
+	/* signal status */
+	i2c_read_demod_bytes(state, TOP_CONTROL, buf, sizeof(buf));
+	dprintk("%s: TOP_CONTROL = 0x%02x, IRO_MASK = 0x%02x, IRQ_STATUS = 0x%02x\n", __func__, buf[0], buf[1], buf[2]);
+
+
+	/* sync status */
+	if ((buf[2] & 0x03) == 0x01) {
+		*status |= FE_HAS_SYNC;
+	}
+
+	/* FEC error status */
+	if ((buf[2] & 0x0c) == 0x08) {
+		*status |= FE_HAS_LOCK;
+		*status |= FE_HAS_VITERBI;
+	}
+
+	/* Carrier Recovery Lock Status Register */
+	i2c_read_demod_bytes(state, CARRIER_LOCK, buf, 1);
+	dprintk("%s: CARRIER_LOCK = 0x%02x\n", __func__, buf[0]);
+	switch (state->current_modulation) {
+	case QAM_256:
+	case QAM_64:
+		/* Need to understand why there are 3 lock levels here */
+		if ((buf[0] & 0x07) == 0x07)
+			*status |= FE_HAS_CARRIER;
+		break;
+	case VSB_8:
+		if ((buf[0] & 0x80) == 0x80)
+			*status |= FE_HAS_CARRIER;
+		break;
+	default:
+		printk(KERN_WARNING "lgdt330x: %s: Modulation set to unsupported value\n", __func__);
+	}
+
+	return 0;
+}
+
+static int lgdt3303_read_status(struct dvb_frontend* fe, fe_status_t* status)
+{
+	struct lgdt330x_state* state = fe->demodulator_priv;
+	int err;
+	u8 buf[3];
+
+	*status = 0; /* Reset status result */
+
+	/* lgdt3303 AGC status register */
+	err = i2c_read_demod_bytes(state, 0x58, buf, 1);
+	if (err < 0)
+		return err;
+
+	dprintk("%s: AGC_STATUS = 0x%02x\n", __func__, buf[0]);
+	if ((buf[0] & 0x21) == 0x01){
+		/* Test input signal does not exist flag */
+		/* as well as the AGC lock flag.   */
+		*status |= FE_HAS_SIGNAL;
+	}
+
+	/* Carrier Recovery Lock Status Register */
+	i2c_read_demod_bytes(state, CARRIER_LOCK, buf, 1);
+	dprintk("%s: CARRIER_LOCK = 0x%02x\n", __func__, buf[0]);
+	switch (state->current_modulation) {
+	case QAM_256:
+	case QAM_64:
+		/* Need to understand why there are 3 lock levels here */
+		if ((buf[0] & 0x07) == 0x07)
+			*status |= FE_HAS_CARRIER;
+		else
+			break;
+		i2c_read_demod_bytes(state, 0x8a, buf, 1);
+		if ((buf[0] & 0x04) == 0x04)
+			*status |= FE_HAS_SYNC;
+		if ((buf[0] & 0x01) == 0x01)
+			*status |= FE_HAS_LOCK;
+		if ((buf[0] & 0x08) == 0x08)
+			*status |= FE_HAS_VITERBI;
+		break;
+	case VSB_8:
+		if ((buf[0] & 0x80) == 0x80)
+			*status |= FE_HAS_CARRIER;
+		else
+			break;
+		i2c_read_demod_bytes(state, 0x38, buf, 1);
+		if ((buf[0] & 0x02) == 0x00)
+			*status |= FE_HAS_SYNC;
+		if ((buf[0] & 0x01) == 0x01) {
+			*status |= FE_HAS_LOCK;
+			*status |= FE_HAS_VITERBI;
+		}
+		break;
+	default:
+		printk(KERN_WARNING "lgdt330x: %s: Modulation set to unsupported value\n", __func__);
+	}
+	return 0;
+}
+
+/* Calculate SNR estimation (scaled by 2^24)
+
+   8-VSB SNR equations from LGDT3302 and LGDT3303 datasheets, QAM
+   equations from LGDT3303 datasheet.  VSB is the same between the '02
+   and '03, so maybe QAM is too?  Perhaps someone with a newer datasheet
+   that has QAM information could verify?
+
+   For 8-VSB: (two ways, take your pick)
+   LGDT3302:
+     SNR_EQ = 10 * log10(25 * 24^2 / EQ_MSE)
+   LGDT3303:
+     SNR_EQ = 10 * log10(25 * 32^2 / EQ_MSE)
+   LGDT3302 & LGDT3303:
+     SNR_PT = 10 * log10(25 * 32^2 / PT_MSE)  (we use this one)
+   For 64-QAM:
+     SNR    = 10 * log10( 688128   / MSEQAM)
+   For 256-QAM:
+     SNR    = 10 * log10( 696320   / MSEQAM)
+
+   We re-write the snr equation as:
+     SNR * 2^24 = 10*(c - intlog10(MSE))
+   Where for 256-QAM, c = log10(696320) * 2^24, and so on. */
+
+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 lgdt3302_read_snr(struct dvb_frontend* fe, u16* snr)
+{
+	struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv;
+	u8 buf[5];	/* read data buffer */
+	u32 noise;	/* noise value */
+	u32 c;		/* per-modulation SNR calculation constant */
+
+	switch(state->current_modulation) {
+	case VSB_8:
+		i2c_read_demod_bytes(state, LGDT3302_EQPH_ERR0, buf, 5);
+#ifdef USE_EQMSE
+		/* Use Equalizer Mean-Square Error Register */
+		/* SNR for ranges from -15.61 to +41.58 */
+		noise = ((buf[0] & 7) << 16) | (buf[1] << 8) | buf[2];
+		c = 69765745; /* log10(25*24^2)*2^24 */
+#else
+		/* Use Phase Tracker Mean-Square Error Register */
+		/* SNR for ranges from -13.11 to +44.08 */
+		noise = ((buf[0] & 7<<3) << 13) | (buf[3] << 8) | buf[4];
+		c = 73957994; /* log10(25*32^2)*2^24 */
+#endif
+		break;
+	case QAM_64:
+	case QAM_256:
+		i2c_read_demod_bytes(state, CARRIER_MSEQAM1, buf, 2);
+		noise = ((buf[0] & 3) << 8) | buf[1];
+		c = state->current_modulation == QAM_64 ? 97939837 : 98026066;
+		/* log10(688128)*2^24 and log10(696320)*2^24 */
+		break;
+	default:
+		printk(KERN_ERR "lgdt330x: %s: Modulation set to unsupported value\n",
+		       __func__);
+		return -EREMOTEIO; /* return -EDRIVER_IS_GIBBERED; */
+	}
+
+	state->snr = calculate_snr(noise, c);
+	*snr = (state->snr) >> 16; /* Convert from 8.24 fixed-point to 8.8 */
+
+	dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __func__, noise,
+		state->snr >> 24, (((state->snr>>8) & 0xffff) * 100) >> 16);
+
+	return 0;
+}
+
+static int lgdt3303_read_snr(struct dvb_frontend* fe, u16* snr)
+{
+	struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv;
+	u8 buf[5];	/* read data buffer */
+	u32 noise;	/* noise value */
+	u32 c;		/* per-modulation SNR calculation constant */
+
+	switch(state->current_modulation) {
+	case VSB_8:
+		i2c_read_demod_bytes(state, LGDT3303_EQPH_ERR0, buf, 5);
+#ifdef USE_EQMSE
+		/* Use Equalizer Mean-Square Error Register */
+		/* SNR for ranges from -16.12 to +44.08 */
+		noise = ((buf[0] & 0x78) << 13) | (buf[1] << 8) | buf[2];
+		c = 73957994; /* log10(25*32^2)*2^24 */
+#else
+		/* Use Phase Tracker Mean-Square Error Register */
+		/* SNR for ranges from -13.11 to +44.08 */
+		noise = ((buf[0] & 7) << 16) | (buf[3] << 8) | buf[4];
+		c = 73957994; /* log10(25*32^2)*2^24 */
+#endif
+		break;
+	case QAM_64:
+	case QAM_256:
+		i2c_read_demod_bytes(state, CARRIER_MSEQAM1, buf, 2);
+		noise = (buf[0] << 8) | buf[1];
+		c = state->current_modulation == QAM_64 ? 97939837 : 98026066;
+		/* log10(688128)*2^24 and log10(696320)*2^24 */
+		break;
+	default:
+		printk(KERN_ERR "lgdt330x: %s: Modulation set to unsupported value\n",
+		       __func__);
+		return -EREMOTEIO; /* return -EDRIVER_IS_GIBBERED; */
+	}
+
+	state->snr = calculate_snr(noise, c);
+	*snr = (state->snr) >> 16; /* Convert from 8.24 fixed-point to 8.8 */
+
+	dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __func__, noise,
+		state->snr >> 24, (((state->snr >> 8) & 0xffff) * 100) >> 16);
+
+	return 0;
+}
+
+static int lgdt330x_read_signal_strength(struct dvb_frontend* fe, u16* strength)
+{
+	/* 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 lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv;
+	u16 snr;
+	int ret;
+
+	ret = fe->ops.read_snr(fe, &snr);
+	if (ret != 0)
+		return ret;
+	/* 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;
+
+	return 0;
+}
+
+static int lgdt330x_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fe_tune_settings)
+{
+	/* I have no idea about this - it may not be needed */
+	fe_tune_settings->min_delay_ms = 500;
+	fe_tune_settings->step_size = 0;
+	fe_tune_settings->max_drift = 0;
+	return 0;
+}
+
+static void lgdt330x_release(struct dvb_frontend* fe)
+{
+	struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv;
+	kfree(state);
+}
+
+static struct dvb_frontend_ops lgdt3302_ops;
+static struct dvb_frontend_ops lgdt3303_ops;
+
+struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config,
+				     struct i2c_adapter* i2c)
+{
+	struct lgdt330x_state* state = NULL;
+	u8 buf[1];
+
+	/* Allocate memory for the internal state */
+	state = kzalloc(sizeof(struct lgdt330x_state), GFP_KERNEL);
+	if (state == NULL)
+		goto error;
+
+	/* Setup the state */
+	state->config = config;
+	state->i2c = i2c;
+
+	/* Create dvb_frontend */
+	switch (config->demod_chip) {
+	case LGDT3302:
+		memcpy(&state->frontend.ops, &lgdt3302_ops, sizeof(struct dvb_frontend_ops));
+		break;
+	case LGDT3303:
+		memcpy(&state->frontend.ops, &lgdt3303_ops, sizeof(struct dvb_frontend_ops));
+		break;
+	default:
+		goto error;
+	}
+	state->frontend.demodulator_priv = state;
+
+	/* Verify communication with demod chip */
+	if (i2c_read_demod_bytes(state, 2, buf, 1))
+		goto error;
+
+	state->current_frequency = -1;
+	state->current_modulation = -1;
+
+	return &state->frontend;
+
+error:
+	kfree(state);
+	dprintk("%s: ERROR\n",__func__);
+	return NULL;
+}
+
+static struct dvb_frontend_ops lgdt3302_ops = {
+	.delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
+	.info = {
+		.name= "LG Electronics LGDT3302 VSB/QAM Frontend",
+		.frequency_min= 54000000,
+		.frequency_max= 858000000,
+		.frequency_stepsize= 62500,
+		.symbol_rate_min    = 5056941,	/* QAM 64 */
+		.symbol_rate_max    = 10762000,	/* VSB 8  */
+		.caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
+	},
+	.init                 = lgdt330x_init,
+	.set_frontend         = lgdt330x_set_parameters,
+	.get_frontend         = lgdt330x_get_frontend,
+	.get_tune_settings    = lgdt330x_get_tune_settings,
+	.read_status          = lgdt3302_read_status,
+	.read_ber             = lgdt330x_read_ber,
+	.read_signal_strength = lgdt330x_read_signal_strength,
+	.read_snr             = lgdt3302_read_snr,
+	.read_ucblocks        = lgdt330x_read_ucblocks,
+	.release              = lgdt330x_release,
+};
+
+static struct dvb_frontend_ops lgdt3303_ops = {
+	.delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
+	.info = {
+		.name= "LG Electronics LGDT3303 VSB/QAM Frontend",
+		.frequency_min= 54000000,
+		.frequency_max= 858000000,
+		.frequency_stepsize= 62500,
+		.symbol_rate_min    = 5056941,	/* QAM 64 */
+		.symbol_rate_max    = 10762000,	/* VSB 8  */
+		.caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
+	},
+	.init                 = lgdt330x_init,
+	.set_frontend         = lgdt330x_set_parameters,
+	.get_frontend         = lgdt330x_get_frontend,
+	.get_tune_settings    = lgdt330x_get_tune_settings,
+	.read_status          = lgdt3303_read_status,
+	.read_ber             = lgdt330x_read_ber,
+	.read_signal_strength = lgdt330x_read_signal_strength,
+	.read_snr             = lgdt3303_read_snr,
+	.read_ucblocks        = lgdt330x_read_ucblocks,
+	.release              = lgdt330x_release,
+};
+
+MODULE_DESCRIPTION("LGDT330X (ATSC 8VSB & ITU-T J.83 AnnexB 64/256 QAM) Demodulator Driver");
+MODULE_AUTHOR("Wilson Michaels");
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(lgdt330x_attach);
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/dvb-frontends/lgdt330x.h b/drivers/media/dvb-frontends/lgdt330x.h
new file mode 100644
index 0000000..9012504
--- /dev/null
+++ b/drivers/media/dvb-frontends/lgdt330x.h
@@ -0,0 +1,73 @@
+/*
+ *    Support for LGDT3302 and LGDT3303 - VSB/QAM
+ *
+ *    Copyright (C) 2005 Wilson Michaels <wilsonmichaels@earthlink.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 program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You 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 LGDT330X_H
+#define LGDT330X_H
+
+#include <linux/dvb/frontend.h>
+
+typedef enum lg_chip_t {
+		UNDEFINED,
+		LGDT3302,
+		LGDT3303
+}lg_chip_type;
+
+struct lgdt330x_config
+{
+	/* The demodulator's i2c address */
+	u8 demod_address;
+
+	/* LG demodulator chip LGDT3302 or LGDT3303 */
+	lg_chip_type demod_chip;
+
+	/* MPEG hardware interface - 0:parallel 1:serial */
+	int serial_mpeg;
+
+	/* PLL interface */
+	int (*pll_rf_set) (struct dvb_frontend* fe, int index);
+
+	/* Need to set device param for start_dma */
+	int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured);
+
+	/* Flip the polarity of the mpeg data transfer clock using alternate init data
+	 * This option applies ONLY to LGDT3303 - 0:disabled (default) 1:enabled */
+	int clock_polarity_flip;
+};
+
+#if defined(CONFIG_DVB_LGDT330X) || (defined(CONFIG_DVB_LGDT330X_MODULE) && defined(MODULE))
+extern struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config,
+					    struct i2c_adapter* i2c);
+#else
+static inline struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config,
+					    struct i2c_adapter* i2c)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif // CONFIG_DVB_LGDT330X
+
+#endif /* LGDT330X_H */
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/dvb-frontends/lgdt330x_priv.h b/drivers/media/dvb-frontends/lgdt330x_priv.h
new file mode 100644
index 0000000..38c7669
--- /dev/null
+++ b/drivers/media/dvb-frontends/lgdt330x_priv.h
@@ -0,0 +1,77 @@
+/*
+ *    Support for LGDT3302 and LGDT3303 - VSB/QAM
+ *
+ *    Copyright (C) 2005 Wilson Michaels <wilsonmichaels@earthlink.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 program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You 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 _LGDT330X_PRIV_
+#define _LGDT330X_PRIV_
+
+/* i2c control register addresses */
+enum I2C_REG {
+	TOP_CONTROL= 0x00,
+	IRQ_MASK= 0x01,
+	IRQ_STATUS= 0x02,
+	VSB_CARRIER_FREQ0= 0x16,
+	VSB_CARRIER_FREQ1= 0x17,
+	VSB_CARRIER_FREQ2= 0x18,
+	VSB_CARRIER_FREQ3= 0x19,
+	CARRIER_MSEQAM1= 0x1a,
+	CARRIER_MSEQAM2= 0x1b,
+	CARRIER_LOCK= 0x1c,
+	TIMING_RECOVERY= 0x1d,
+	AGC_DELAY0= 0x2a,
+	AGC_DELAY1= 0x2b,
+	AGC_DELAY2= 0x2c,
+	AGC_RF_BANDWIDTH0= 0x2d,
+	AGC_RF_BANDWIDTH1= 0x2e,
+	AGC_RF_BANDWIDTH2= 0x2f,
+	AGC_LOOP_BANDWIDTH0= 0x30,
+	AGC_LOOP_BANDWIDTH1= 0x31,
+	AGC_FUNC_CTRL1= 0x32,
+	AGC_FUNC_CTRL2= 0x33,
+	AGC_FUNC_CTRL3= 0x34,
+	AGC_RFIF_ACC0= 0x39,
+	AGC_RFIF_ACC1= 0x3a,
+	AGC_RFIF_ACC2= 0x3b,
+	AGC_STATUS= 0x3f,
+	SYNC_STATUS_VSB= 0x43,
+	DEMUX_CONTROL= 0x66,
+	LGDT3302_EQPH_ERR0= 0x47,
+	LGDT3302_EQ_ERR1= 0x48,
+	LGDT3302_EQ_ERR2= 0x49,
+	LGDT3302_PH_ERR1= 0x4a,
+	LGDT3302_PH_ERR2= 0x4b,
+	LGDT3302_PACKET_ERR_COUNTER1= 0x6a,
+	LGDT3302_PACKET_ERR_COUNTER2= 0x6b,
+	LGDT3303_EQPH_ERR0= 0x6e,
+	LGDT3303_EQ_ERR1= 0x6f,
+	LGDT3303_EQ_ERR2= 0x70,
+	LGDT3303_PH_ERR1= 0x71,
+	LGDT3303_PH_ERR2= 0x72,
+	LGDT3303_PACKET_ERR_COUNTER1= 0x8b,
+	LGDT3303_PACKET_ERR_COUNTER2= 0x8c,
+};
+
+#endif /* _LGDT330X_PRIV_ */
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/dvb-frontends/lgs8gl5.c b/drivers/media/dvb-frontends/lgs8gl5.c
new file mode 100644
index 0000000..416cce3
--- /dev/null
+++ b/drivers/media/dvb-frontends/lgs8gl5.c
@@ -0,0 +1,453 @@
+/*
+    Legend Silicon LGS-8GL5 DMB-TH OFDM demodulator driver
+
+    Copyright (C) 2008 Sirius International (Hong Kong) Limited
+	Timothy Lee <timothy.lee@siriushk.com>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include "dvb_frontend.h"
+#include "lgs8gl5.h"
+
+
+#define REG_RESET		0x02
+#define REG_RESET_OFF			0x01
+#define REG_03			0x03
+#define REG_04			0x04
+#define REG_07			0x07
+#define REG_09			0x09
+#define REG_0A			0x0a
+#define REG_0B			0x0b
+#define REG_0C			0x0c
+#define REG_37			0x37
+#define REG_STRENGTH		0x4b
+#define REG_STRENGTH_MASK		0x7f
+#define REG_STRENGTH_CARRIER		0x80
+#define REG_INVERSION		0x7c
+#define REG_INVERSION_ON		0x80
+#define REG_7D			0x7d
+#define REG_7E			0x7e
+#define REG_A2			0xa2
+#define REG_STATUS		0xa4
+#define REG_STATUS_SYNC		0x04
+#define REG_STATUS_LOCK		0x01
+
+
+struct lgs8gl5_state {
+	struct i2c_adapter *i2c;
+	const struct lgs8gl5_config *config;
+	struct dvb_frontend frontend;
+};
+
+
+static int debug;
+#define dprintk(args...) \
+	do { \
+		if (debug) \
+			printk(KERN_DEBUG "lgs8gl5: " args); \
+	} while (0)
+
+
+/* Writes into demod's register */
+static int
+lgs8gl5_write_reg(struct lgs8gl5_state *state, u8 reg, u8 data)
+{
+	int ret;
+	u8 buf[] = {reg, data};
+	struct i2c_msg msg = {
+		.addr  = state->config->demod_address,
+		.flags = 0,
+		.buf   = buf,
+		.len   = 2
+	};
+
+	ret = i2c_transfer(state->i2c, &msg, 1);
+	if (ret != 1)
+		dprintk("%s: error (reg=0x%02x, val=0x%02x, ret=%i)\n",
+			__func__, reg, data, ret);
+	return (ret != 1) ? -1 : 0;
+}
+
+
+/* Reads from demod's register */
+static int
+lgs8gl5_read_reg(struct lgs8gl5_state *state, u8 reg)
+{
+	int ret;
+	u8 b0[] = {reg};
+	u8 b1[] = {0};
+	struct i2c_msg msg[2] = {
+		{
+			.addr  = state->config->demod_address,
+			.flags = 0,
+			.buf   = b0,
+			.len   = 1
+		},
+		{
+			.addr  = state->config->demod_address,
+			.flags = I2C_M_RD,
+			.buf   = b1,
+			.len   = 1
+		}
+	};
+
+	ret = i2c_transfer(state->i2c, msg, 2);
+	if (ret != 2)
+		return -EIO;
+
+	return b1[0];
+}
+
+
+static int
+lgs8gl5_update_reg(struct lgs8gl5_state *state, u8 reg, u8 data)
+{
+	lgs8gl5_read_reg(state, reg);
+	lgs8gl5_write_reg(state, reg, data);
+	return 0;
+}
+
+
+/* Writes into alternate device's register */
+/* TODO:  Find out what that device is for! */
+static int
+lgs8gl5_update_alt_reg(struct lgs8gl5_state *state, u8 reg, u8 data)
+{
+	int ret;
+	u8 b0[] = {reg};
+	u8 b1[] = {0};
+	u8 b2[] = {reg, data};
+	struct i2c_msg msg[3] = {
+		{
+			.addr  = state->config->demod_address + 2,
+			.flags = 0,
+			.buf   = b0,
+			.len   = 1
+		},
+		{
+			.addr  = state->config->demod_address + 2,
+			.flags = I2C_M_RD,
+			.buf   = b1,
+			.len   = 1
+		},
+		{
+			.addr  = state->config->demod_address + 2,
+			.flags = 0,
+			.buf   = b2,
+			.len   = 2
+		},
+	};
+
+	ret = i2c_transfer(state->i2c, msg, 3);
+	return (ret != 3) ? -1 : 0;
+}
+
+
+static void
+lgs8gl5_soft_reset(struct lgs8gl5_state *state)
+{
+	u8 val;
+
+	dprintk("%s\n", __func__);
+
+	val = lgs8gl5_read_reg(state, REG_RESET);
+	lgs8gl5_write_reg(state, REG_RESET, val & ~REG_RESET_OFF);
+	lgs8gl5_write_reg(state, REG_RESET, val | REG_RESET_OFF);
+	msleep(5);
+}
+
+
+/* Starts demodulation */
+static void
+lgs8gl5_start_demod(struct lgs8gl5_state *state)
+{
+	u8  val;
+	int n;
+
+	dprintk("%s\n", __func__);
+
+	lgs8gl5_update_alt_reg(state, 0xc2, 0x28);
+	lgs8gl5_soft_reset(state);
+	lgs8gl5_update_reg(state, REG_07, 0x10);
+	lgs8gl5_update_reg(state, REG_07, 0x10);
+	lgs8gl5_write_reg(state, REG_09, 0x0e);
+	lgs8gl5_write_reg(state, REG_0A, 0xe5);
+	lgs8gl5_write_reg(state, REG_0B, 0x35);
+	lgs8gl5_write_reg(state, REG_0C, 0x30);
+
+	lgs8gl5_update_reg(state, REG_03, 0x00);
+	lgs8gl5_update_reg(state, REG_7E, 0x01);
+	lgs8gl5_update_alt_reg(state, 0xc5, 0x00);
+	lgs8gl5_update_reg(state, REG_04, 0x02);
+	lgs8gl5_update_reg(state, REG_37, 0x01);
+	lgs8gl5_soft_reset(state);
+
+	/* Wait for carrier */
+	for (n = 0;  n < 10;  n++) {
+		val = lgs8gl5_read_reg(state, REG_STRENGTH);
+		dprintk("Wait for carrier[%d] 0x%02X\n", n, val);
+		if (val & REG_STRENGTH_CARRIER)
+			break;
+		msleep(4);
+	}
+	if (!(val & REG_STRENGTH_CARRIER))
+		return;
+
+	/* Wait for lock */
+	for (n = 0;  n < 20;  n++) {
+		val = lgs8gl5_read_reg(state, REG_STATUS);
+		dprintk("Wait for lock[%d] 0x%02X\n", n, val);
+		if (val & REG_STATUS_LOCK)
+			break;
+		msleep(12);
+	}
+	if (!(val & REG_STATUS_LOCK))
+		return;
+
+	lgs8gl5_write_reg(state, REG_7D, lgs8gl5_read_reg(state, REG_A2));
+	lgs8gl5_soft_reset(state);
+}
+
+
+static int
+lgs8gl5_init(struct dvb_frontend *fe)
+{
+	struct lgs8gl5_state *state = fe->demodulator_priv;
+
+	dprintk("%s\n", __func__);
+
+	lgs8gl5_update_alt_reg(state, 0xc2, 0x28);
+	lgs8gl5_soft_reset(state);
+	lgs8gl5_update_reg(state, REG_07, 0x10);
+	lgs8gl5_update_reg(state, REG_07, 0x10);
+	lgs8gl5_write_reg(state, REG_09, 0x0e);
+	lgs8gl5_write_reg(state, REG_0A, 0xe5);
+	lgs8gl5_write_reg(state, REG_0B, 0x35);
+	lgs8gl5_write_reg(state, REG_0C, 0x30);
+
+	return 0;
+}
+
+
+static int
+lgs8gl5_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+	struct lgs8gl5_state *state = fe->demodulator_priv;
+	u8 level = lgs8gl5_read_reg(state, REG_STRENGTH);
+	u8 flags = lgs8gl5_read_reg(state, REG_STATUS);
+
+	*status = 0;
+
+	if ((level & REG_STRENGTH_MASK) > 0)
+		*status |= FE_HAS_SIGNAL;
+	if (level & REG_STRENGTH_CARRIER)
+		*status |= FE_HAS_CARRIER;
+	if (flags & REG_STATUS_SYNC)
+		*status |= FE_HAS_SYNC;
+	if (flags & REG_STATUS_LOCK)
+		*status |= FE_HAS_LOCK;
+
+	return 0;
+}
+
+
+static int
+lgs8gl5_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+	*ber = 0;
+
+	return 0;
+}
+
+
+static int
+lgs8gl5_read_signal_strength(struct dvb_frontend *fe, u16 *signal_strength)
+{
+	struct lgs8gl5_state *state = fe->demodulator_priv;
+	u8 level = lgs8gl5_read_reg(state, REG_STRENGTH);
+	*signal_strength = (level & REG_STRENGTH_MASK) << 8;
+
+	return 0;
+}
+
+
+static int
+lgs8gl5_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+	struct lgs8gl5_state *state = fe->demodulator_priv;
+	u8 level = lgs8gl5_read_reg(state, REG_STRENGTH);
+	*snr = (level & REG_STRENGTH_MASK) << 8;
+
+	return 0;
+}
+
+
+static int
+lgs8gl5_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+	*ucblocks = 0;
+
+	return 0;
+}
+
+
+static int
+lgs8gl5_set_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct lgs8gl5_state *state = fe->demodulator_priv;
+
+	dprintk("%s\n", __func__);
+
+	if (p->bandwidth_hz != 8000000)
+		return -EINVAL;
+
+	if (fe->ops.tuner_ops.set_params) {
+		fe->ops.tuner_ops.set_params(fe);
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 0);
+	}
+
+	/* lgs8gl5_set_inversion(state, p->inversion); */
+
+	lgs8gl5_start_demod(state);
+
+	return 0;
+}
+
+
+static int
+lgs8gl5_get_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct lgs8gl5_state *state = fe->demodulator_priv;
+	u8 inv = lgs8gl5_read_reg(state, REG_INVERSION);
+
+	p->inversion = (inv & REG_INVERSION_ON) ? INVERSION_ON : INVERSION_OFF;
+
+	p->code_rate_HP = FEC_1_2;
+	p->code_rate_LP = FEC_7_8;
+	p->guard_interval = GUARD_INTERVAL_1_32;
+	p->transmission_mode = TRANSMISSION_MODE_2K;
+	p->modulation = QAM_64;
+	p->hierarchy = HIERARCHY_NONE;
+	p->bandwidth_hz = 8000000;
+
+	return 0;
+}
+
+
+static int
+lgs8gl5_get_tune_settings(struct dvb_frontend *fe,
+		struct dvb_frontend_tune_settings *fesettings)
+{
+	fesettings->min_delay_ms = 240;
+	fesettings->step_size    = 0;
+	fesettings->max_drift    = 0;
+	return 0;
+}
+
+
+static void
+lgs8gl5_release(struct dvb_frontend *fe)
+{
+	struct lgs8gl5_state *state = fe->demodulator_priv;
+	kfree(state);
+}
+
+
+static struct dvb_frontend_ops lgs8gl5_ops;
+
+
+struct dvb_frontend*
+lgs8gl5_attach(const struct lgs8gl5_config *config, struct i2c_adapter *i2c)
+{
+	struct lgs8gl5_state *state = NULL;
+
+	dprintk("%s\n", __func__);
+
+	/* Allocate memory for the internal state */
+	state = kzalloc(sizeof(struct lgs8gl5_state), GFP_KERNEL);
+	if (state == NULL)
+		goto error;
+
+	/* Setup the state */
+	state->config = config;
+	state->i2c    = i2c;
+
+	/* Check if the demod is there */
+	if (lgs8gl5_read_reg(state, REG_RESET) < 0)
+		goto error;
+
+	/* Create dvb_frontend */
+	memcpy(&state->frontend.ops, &lgs8gl5_ops,
+		sizeof(struct dvb_frontend_ops));
+	state->frontend.demodulator_priv = state;
+	return &state->frontend;
+
+error:
+	kfree(state);
+	return NULL;
+}
+EXPORT_SYMBOL(lgs8gl5_attach);
+
+
+static struct dvb_frontend_ops lgs8gl5_ops = {
+	.delsys = { SYS_DTMB },
+	.info = {
+		.name			= "Legend Silicon LGS-8GL5 DMB-TH",
+		.frequency_min		= 474000000,
+		.frequency_max		= 858000000,
+		.frequency_stepsize	= 10000,
+		.frequency_tolerance	= 0,
+		.caps = FE_CAN_FEC_AUTO |
+			FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_32 |
+			FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
+			FE_CAN_TRANSMISSION_MODE_AUTO |
+			FE_CAN_BANDWIDTH_AUTO |
+			FE_CAN_GUARD_INTERVAL_AUTO |
+			FE_CAN_HIERARCHY_AUTO |
+			FE_CAN_RECOVER
+	},
+
+	.release = lgs8gl5_release,
+
+	.init = lgs8gl5_init,
+
+	.set_frontend = lgs8gl5_set_frontend,
+	.get_frontend = lgs8gl5_get_frontend,
+	.get_tune_settings = lgs8gl5_get_tune_settings,
+
+	.read_status = lgs8gl5_read_status,
+	.read_ber = lgs8gl5_read_ber,
+	.read_signal_strength = lgs8gl5_read_signal_strength,
+	.read_snr = lgs8gl5_read_snr,
+	.read_ucblocks = lgs8gl5_read_ucblocks,
+};
+
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+
+MODULE_DESCRIPTION("Legend Silicon LGS-8GL5 DMB-TH Demodulator driver");
+MODULE_AUTHOR("Timothy Lee");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb-frontends/lgs8gl5.h b/drivers/media/dvb-frontends/lgs8gl5.h
new file mode 100644
index 0000000..d1417678
--- /dev/null
+++ b/drivers/media/dvb-frontends/lgs8gl5.h
@@ -0,0 +1,45 @@
+/*
+    Legend Silicon LGS-8GL5 DMB-TH OFDM demodulator driver
+
+    Copyright (C) 2008 Sirius International (Hong Kong) Limited
+	Timothy Lee <timothy.lee@siriushk.com>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef LGS8GL5_H
+#define LGS8GL5_H
+
+#include <linux/dvb/frontend.h>
+
+struct lgs8gl5_config {
+	/* the demodulator's i2c address */
+	u8 demod_address;
+};
+
+#if defined(CONFIG_DVB_LGS8GL5) || \
+	(defined(CONFIG_DVB_LGS8GL5_MODULE) && defined(MODULE))
+extern struct dvb_frontend *lgs8gl5_attach(
+	const struct lgs8gl5_config *config, struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend *lgs8gl5_attach(
+	const struct lgs8gl5_config *config, struct i2c_adapter *i2c) {
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif /* CONFIG_DVB_LGS8GL5 */
+
+#endif /* LGS8GL5_H */
diff --git a/drivers/media/dvb-frontends/lgs8gxx.c b/drivers/media/dvb-frontends/lgs8gxx.c
new file mode 100644
index 0000000..3c92f36
--- /dev/null
+++ b/drivers/media/dvb-frontends/lgs8gxx.c
@@ -0,0 +1,1075 @@
+/*
+ *    Support for Legend Silicon GB20600 (a.k.a DMB-TH) demodulator
+ *    LGS8913, LGS8GL5, LGS8G75
+ *    experimental support LGS8G42, LGS8G52
+ *
+ *    Copyright (C) 2007-2009 David T.L. Wong <davidtlwong@gmail.com>
+ *    Copyright (C) 2008 Sirius International (Hong Kong) Limited
+ *    Timothy Lee <timothy.lee@siriushk.com> (for initial work on LGS8GL5)
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the 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 <asm/div64.h>
+#include <linux/firmware.h>
+
+#include "dvb_frontend.h"
+
+#include "lgs8gxx.h"
+#include "lgs8gxx_priv.h"
+
+#define dprintk(args...) \
+	do { \
+		if (debug) \
+			printk(KERN_DEBUG "lgs8gxx: " args); \
+	} while (0)
+
+static int debug;
+static int fake_signal_str = 1;
+
+#define LGS8GXX_FIRMWARE "lgs8g75.fw"
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+
+module_param(fake_signal_str, int, 0644);
+MODULE_PARM_DESC(fake_signal_str, "fake signal strength for LGS8913."
+"Signal strength calculation is slow.(default:on).");
+
+/* LGS8GXX internal helper functions */
+
+static int lgs8gxx_write_reg(struct lgs8gxx_state *priv, u8 reg, u8 data)
+{
+	int ret;
+	u8 buf[] = { reg, data };
+	struct i2c_msg msg = { .flags = 0, .buf = buf, .len = 2 };
+
+	msg.addr = priv->config->demod_address;
+	if (priv->config->prod != LGS8GXX_PROD_LGS8G75 && reg >= 0xC0)
+		msg.addr += 0x02;
+
+	if (debug >= 2)
+		dprintk("%s: reg=0x%02X, data=0x%02X\n", __func__, reg, data);
+
+	ret = i2c_transfer(priv->i2c, &msg, 1);
+
+	if (ret != 1)
+		dprintk("%s: error reg=0x%x, data=0x%x, ret=%i\n",
+			__func__, reg, data, ret);
+
+	return (ret != 1) ? -1 : 0;
+}
+
+static int lgs8gxx_read_reg(struct lgs8gxx_state *priv, u8 reg, u8 *p_data)
+{
+	int ret;
+	u8 dev_addr;
+
+	u8 b0[] = { reg };
+	u8 b1[] = { 0 };
+	struct i2c_msg msg[] = {
+		{ .flags = 0, .buf = b0, .len = 1 },
+		{ .flags = I2C_M_RD, .buf = b1, .len = 1 },
+	};
+
+	dev_addr = priv->config->demod_address;
+	if (priv->config->prod != LGS8GXX_PROD_LGS8G75 && reg >= 0xC0)
+		dev_addr += 0x02;
+	msg[1].addr =  msg[0].addr = dev_addr;
+
+	ret = i2c_transfer(priv->i2c, msg, 2);
+	if (ret != 2) {
+		dprintk("%s: error reg=0x%x, ret=%i\n", __func__, reg, ret);
+		return -1;
+	}
+
+	*p_data = b1[0];
+	if (debug >= 2)
+		dprintk("%s: reg=0x%02X, data=0x%02X\n", __func__, reg, b1[0]);
+	return 0;
+}
+
+static int lgs8gxx_soft_reset(struct lgs8gxx_state *priv)
+{
+	lgs8gxx_write_reg(priv, 0x02, 0x00);
+	msleep(1);
+	lgs8gxx_write_reg(priv, 0x02, 0x01);
+	msleep(100);
+
+	return 0;
+}
+
+static int wait_reg_mask(struct lgs8gxx_state *priv, u8 reg, u8 mask,
+	u8 val, u8 delay, u8 tries)
+{
+	u8 t;
+	int i;
+
+	for (i = 0; i < tries; i++) {
+		lgs8gxx_read_reg(priv, reg, &t);
+
+		if ((t & mask) == val)
+			return 0;
+		msleep(delay);
+	}
+
+	return 1;
+}
+
+static int lgs8gxx_set_ad_mode(struct lgs8gxx_state *priv)
+{
+	const struct lgs8gxx_config *config = priv->config;
+	u8 if_conf;
+
+	if_conf = 0x10; /* AGC output on, RF_AGC output off; */
+
+	if_conf |=
+		((config->ext_adc) ? 0x80 : 0x00) |
+		((config->if_neg_center) ? 0x04 : 0x00) |
+		((config->if_freq == 0) ? 0x08 : 0x00) | /* Baseband */
+		((config->adc_signed) ? 0x02 : 0x00) |
+		((config->if_neg_edge) ? 0x01 : 0x00);
+
+	if (config->ext_adc &&
+		(config->prod == LGS8GXX_PROD_LGS8G52)) {
+		lgs8gxx_write_reg(priv, 0xBA, 0x40);
+	}
+
+	lgs8gxx_write_reg(priv, 0x07, if_conf);
+
+	return 0;
+}
+
+static int lgs8gxx_set_if_freq(struct lgs8gxx_state *priv, u32 freq /*in kHz*/)
+{
+	u64 val;
+	u32 v32;
+	u32 if_clk;
+
+	if_clk = priv->config->if_clk_freq;
+
+	val = freq;
+	if (freq != 0) {
+		val <<= 32;
+		if (if_clk != 0)
+			do_div(val, if_clk);
+		v32 = val & 0xFFFFFFFF;
+		dprintk("Set IF Freq to %dkHz\n", freq);
+	} else {
+		v32 = 0;
+		dprintk("Set IF Freq to baseband\n");
+	}
+	dprintk("AFC_INIT_FREQ = 0x%08X\n", v32);
+
+	if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
+		lgs8gxx_write_reg(priv, 0x08, 0xFF & (v32));
+		lgs8gxx_write_reg(priv, 0x09, 0xFF & (v32 >> 8));
+		lgs8gxx_write_reg(priv, 0x0A, 0xFF & (v32 >> 16));
+		lgs8gxx_write_reg(priv, 0x0B, 0xFF & (v32 >> 24));
+	} else {
+		lgs8gxx_write_reg(priv, 0x09, 0xFF & (v32));
+		lgs8gxx_write_reg(priv, 0x0A, 0xFF & (v32 >> 8));
+		lgs8gxx_write_reg(priv, 0x0B, 0xFF & (v32 >> 16));
+		lgs8gxx_write_reg(priv, 0x0C, 0xFF & (v32 >> 24));
+	}
+
+	return 0;
+}
+
+static int lgs8gxx_get_afc_phase(struct lgs8gxx_state *priv)
+{
+	u64 val;
+	u32 v32 = 0;
+	u8 reg_addr, t;
+	int i;
+
+	if (priv->config->prod == LGS8GXX_PROD_LGS8G75)
+		reg_addr = 0x23;
+	else
+		reg_addr = 0x48;
+
+	for (i = 0; i < 4; i++) {
+		lgs8gxx_read_reg(priv, reg_addr, &t);
+		v32 <<= 8;
+		v32 |= t;
+		reg_addr--;
+	}
+
+	val = v32;
+	val *= priv->config->if_clk_freq;
+	val >>= 32;
+	dprintk("AFC = %u kHz\n", (u32)val);
+	return 0;
+}
+
+static int lgs8gxx_set_mode_auto(struct lgs8gxx_state *priv)
+{
+	u8 t;
+	u8 prod = priv->config->prod;
+
+	if (prod == LGS8GXX_PROD_LGS8913)
+		lgs8gxx_write_reg(priv, 0xC6, 0x01);
+
+	if (prod == LGS8GXX_PROD_LGS8G75) {
+		lgs8gxx_read_reg(priv, 0x0C, &t);
+		t &= (~0x04);
+		lgs8gxx_write_reg(priv, 0x0C, t | 0x80);
+		lgs8gxx_write_reg(priv, 0x39, 0x00);
+		lgs8gxx_write_reg(priv, 0x3D, 0x04);
+	} else if (prod == LGS8GXX_PROD_LGS8913 ||
+		prod == LGS8GXX_PROD_LGS8GL5 ||
+		prod == LGS8GXX_PROD_LGS8G42 ||
+		prod == LGS8GXX_PROD_LGS8G52 ||
+		prod == LGS8GXX_PROD_LGS8G54) {
+		lgs8gxx_read_reg(priv, 0x7E, &t);
+		lgs8gxx_write_reg(priv, 0x7E, t | 0x01);
+
+		/* clear FEC self reset */
+		lgs8gxx_read_reg(priv, 0xC5, &t);
+		lgs8gxx_write_reg(priv, 0xC5, t & 0xE0);
+	}
+
+	if (prod == LGS8GXX_PROD_LGS8913) {
+		/* FEC auto detect */
+		lgs8gxx_write_reg(priv, 0xC1, 0x03);
+
+		lgs8gxx_read_reg(priv, 0x7C, &t);
+		t = (t & 0x8C) | 0x03;
+		lgs8gxx_write_reg(priv, 0x7C, t);
+
+		/* BER test mode */
+		lgs8gxx_read_reg(priv, 0xC3, &t);
+		t = (t & 0xEF) |  0x10;
+		lgs8gxx_write_reg(priv, 0xC3, t);
+	}
+
+	if (priv->config->prod == LGS8GXX_PROD_LGS8G52)
+		lgs8gxx_write_reg(priv, 0xD9, 0x40);
+
+	return 0;
+}
+
+static int lgs8gxx_set_mode_manual(struct lgs8gxx_state *priv)
+{
+	u8 t;
+
+	if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
+		u8 t2;
+		lgs8gxx_read_reg(priv, 0x0C, &t);
+		t &= (~0x80);
+		lgs8gxx_write_reg(priv, 0x0C, t);
+
+		lgs8gxx_read_reg(priv, 0x0C, &t);
+		lgs8gxx_read_reg(priv, 0x19, &t2);
+
+		if (((t&0x03) == 0x01) && (t2&0x01)) {
+			lgs8gxx_write_reg(priv, 0x6E, 0x05);
+			lgs8gxx_write_reg(priv, 0x39, 0x02);
+			lgs8gxx_write_reg(priv, 0x39, 0x03);
+			lgs8gxx_write_reg(priv, 0x3D, 0x05);
+			lgs8gxx_write_reg(priv, 0x3E, 0x28);
+			lgs8gxx_write_reg(priv, 0x53, 0x80);
+		} else {
+			lgs8gxx_write_reg(priv, 0x6E, 0x3F);
+			lgs8gxx_write_reg(priv, 0x39, 0x00);
+			lgs8gxx_write_reg(priv, 0x3D, 0x04);
+		}
+
+		lgs8gxx_soft_reset(priv);
+		return 0;
+	}
+
+	/* turn off auto-detect; manual settings */
+	lgs8gxx_write_reg(priv, 0x7E, 0);
+	if (priv->config->prod == LGS8GXX_PROD_LGS8913)
+		lgs8gxx_write_reg(priv, 0xC1, 0);
+
+	lgs8gxx_read_reg(priv, 0xC5, &t);
+	t = (t & 0xE0) | 0x06;
+	lgs8gxx_write_reg(priv, 0xC5, t);
+
+	lgs8gxx_soft_reset(priv);
+
+	return 0;
+}
+
+static int lgs8gxx_is_locked(struct lgs8gxx_state *priv, u8 *locked)
+{
+	int ret = 0;
+	u8 t;
+
+	if (priv->config->prod == LGS8GXX_PROD_LGS8G75)
+		ret = lgs8gxx_read_reg(priv, 0x13, &t);
+	else
+		ret = lgs8gxx_read_reg(priv, 0x4B, &t);
+	if (ret != 0)
+		return ret;
+
+	if (priv->config->prod == LGS8GXX_PROD_LGS8G75)
+		*locked = ((t & 0x80) == 0x80) ? 1 : 0;
+	else
+		*locked = ((t & 0xC0) == 0xC0) ? 1 : 0;
+	return 0;
+}
+
+/* Wait for Code Acquisition Lock */
+static int lgs8gxx_wait_ca_lock(struct lgs8gxx_state *priv, u8 *locked)
+{
+	int ret = 0;
+	u8 reg, mask, val;
+
+	if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
+		reg = 0x13;
+		mask = 0x80;
+		val = 0x80;
+	} else {
+		reg = 0x4B;
+		mask = 0xC0;
+		val = 0xC0;
+	}
+
+	ret = wait_reg_mask(priv, reg, mask, val, 50, 40);
+	*locked = (ret == 0) ? 1 : 0;
+
+	return 0;
+}
+
+static int lgs8gxx_is_autodetect_finished(struct lgs8gxx_state *priv,
+					  u8 *finished)
+{
+	int ret = 0;
+	u8 reg, mask, val;
+
+	if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
+		reg = 0x1f;
+		mask = 0xC0;
+		val = 0x80;
+	} else {
+		reg = 0xA4;
+		mask = 0x03;
+		val = 0x01;
+	}
+
+	ret = wait_reg_mask(priv, reg, mask, val, 10, 20);
+	*finished = (ret == 0) ? 1 : 0;
+
+	return 0;
+}
+
+static int lgs8gxx_autolock_gi(struct lgs8gxx_state *priv, u8 gi, u8 cpn,
+	u8 *locked)
+{
+	int err = 0;
+	u8 ad_fini = 0;
+	u8 t1, t2;
+
+	if (gi == GI_945)
+		dprintk("try GI 945\n");
+	else if (gi == GI_595)
+		dprintk("try GI 595\n");
+	else if (gi == GI_420)
+		dprintk("try GI 420\n");
+	if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
+		lgs8gxx_read_reg(priv, 0x0C, &t1);
+		lgs8gxx_read_reg(priv, 0x18, &t2);
+		t1 &= ~(GI_MASK);
+		t1 |= gi;
+		t2 &= 0xFE;
+		t2 |= cpn ? 0x01 : 0x00;
+		lgs8gxx_write_reg(priv, 0x0C, t1);
+		lgs8gxx_write_reg(priv, 0x18, t2);
+	} else {
+		lgs8gxx_write_reg(priv, 0x04, gi);
+	}
+	lgs8gxx_soft_reset(priv);
+	err = lgs8gxx_wait_ca_lock(priv, locked);
+	if (err || !(*locked))
+		return err;
+	err = lgs8gxx_is_autodetect_finished(priv, &ad_fini);
+	if (err != 0)
+		return err;
+	if (ad_fini) {
+		dprintk("auto detect finished\n");
+	} else
+		*locked = 0;
+
+	return 0;
+}
+
+static int lgs8gxx_auto_detect(struct lgs8gxx_state *priv,
+			       u8 *detected_param, u8 *gi)
+{
+	int i, j;
+	int err = 0;
+	u8 locked = 0, tmp_gi;
+
+	dprintk("%s\n", __func__);
+
+	lgs8gxx_set_mode_auto(priv);
+	if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
+		lgs8gxx_write_reg(priv, 0x67, 0xAA);
+		lgs8gxx_write_reg(priv, 0x6E, 0x3F);
+	} else {
+		/* Guard Interval */
+		lgs8gxx_write_reg(priv, 0x03, 00);
+	}
+
+	for (i = 0; i < 2; i++) {
+		for (j = 0; j < 2; j++) {
+			tmp_gi = GI_945;
+			err = lgs8gxx_autolock_gi(priv, GI_945, j, &locked);
+			if (err)
+				goto out;
+			if (locked)
+				goto locked;
+		}
+		for (j = 0; j < 2; j++) {
+			tmp_gi = GI_420;
+			err = lgs8gxx_autolock_gi(priv, GI_420, j, &locked);
+			if (err)
+				goto out;
+			if (locked)
+				goto locked;
+		}
+		tmp_gi = GI_595;
+		err = lgs8gxx_autolock_gi(priv, GI_595, 1, &locked);
+		if (err)
+			goto out;
+		if (locked)
+			goto locked;
+	}
+
+locked:
+	if ((err == 0) && (locked == 1)) {
+		u8 t;
+
+		if (priv->config->prod != LGS8GXX_PROD_LGS8G75) {
+			lgs8gxx_read_reg(priv, 0xA2, &t);
+			*detected_param = t;
+		} else {
+			lgs8gxx_read_reg(priv, 0x1F, &t);
+			*detected_param = t & 0x3F;
+		}
+
+		if (tmp_gi == GI_945)
+			dprintk("GI 945 locked\n");
+		else if (tmp_gi == GI_595)
+			dprintk("GI 595 locked\n");
+		else if (tmp_gi == GI_420)
+			dprintk("GI 420 locked\n");
+		*gi = tmp_gi;
+	}
+	if (!locked)
+		err = -1;
+
+out:
+	return err;
+}
+
+static void lgs8gxx_auto_lock(struct lgs8gxx_state *priv)
+{
+	s8 err;
+	u8 gi = 0x2;
+	u8 detected_param = 0;
+
+	err = lgs8gxx_auto_detect(priv, &detected_param, &gi);
+
+	if (err != 0) {
+		dprintk("lgs8gxx_auto_detect failed\n");
+	} else
+		dprintk("detected param = 0x%02X\n", detected_param);
+
+	/* Apply detected parameters */
+	if (priv->config->prod == LGS8GXX_PROD_LGS8913) {
+		u8 inter_leave_len = detected_param & TIM_MASK ;
+		/* Fix 8913 time interleaver detection bug */
+		inter_leave_len = (inter_leave_len == TIM_MIDDLE) ? 0x60 : 0x40;
+		detected_param &= CF_MASK | SC_MASK  | LGS_FEC_MASK;
+		detected_param |= inter_leave_len;
+	}
+	if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
+		u8 t;
+		lgs8gxx_read_reg(priv, 0x19, &t);
+		t &= 0x81;
+		t |= detected_param << 1;
+		lgs8gxx_write_reg(priv, 0x19, t);
+	} else {
+		lgs8gxx_write_reg(priv, 0x7D, detected_param);
+		if (priv->config->prod == LGS8GXX_PROD_LGS8913)
+			lgs8gxx_write_reg(priv, 0xC0, detected_param);
+	}
+	/* lgs8gxx_soft_reset(priv); */
+
+	/* Enter manual mode */
+	lgs8gxx_set_mode_manual(priv);
+
+	switch (gi) {
+	case GI_945:
+		priv->curr_gi = 945; break;
+	case GI_595:
+		priv->curr_gi = 595; break;
+	case GI_420:
+		priv->curr_gi = 420; break;
+	default:
+		priv->curr_gi = 945; break;
+	}
+}
+
+static int lgs8gxx_set_mpeg_mode(struct lgs8gxx_state *priv,
+	u8 serial, u8 clk_pol, u8 clk_gated)
+{
+	int ret = 0;
+	u8 t, reg_addr;
+
+	reg_addr = (priv->config->prod == LGS8GXX_PROD_LGS8G75) ? 0x30 : 0xC2;
+	ret = lgs8gxx_read_reg(priv, reg_addr, &t);
+	if (ret != 0)
+		return ret;
+
+	t &= 0xF8;
+	t |= serial ? TS_SERIAL : TS_PARALLEL;
+	t |= clk_pol ? TS_CLK_INVERTED : TS_CLK_NORMAL;
+	t |= clk_gated ? TS_CLK_GATED : TS_CLK_FREERUN;
+
+	ret = lgs8gxx_write_reg(priv, reg_addr, t);
+	if (ret != 0)
+		return ret;
+
+	return 0;
+}
+
+/* A/D input peak-to-peak voltage range */
+static int lgs8g75_set_adc_vpp(struct lgs8gxx_state *priv,
+	u8 sel)
+{
+	u8 r26 = 0x73, r27 = 0x90;
+
+	if (priv->config->prod != LGS8GXX_PROD_LGS8G75)
+		return 0;
+
+	r26 |= (sel & 0x01) << 7;
+	r27 |= (sel & 0x02) >> 1;
+	lgs8gxx_write_reg(priv, 0x26, r26);
+	lgs8gxx_write_reg(priv, 0x27, r27);
+
+	return 0;
+}
+
+/* LGS8913 demod frontend functions */
+
+static int lgs8913_init(struct lgs8gxx_state *priv)
+{
+	u8 t;
+
+	/* LGS8913 specific */
+	lgs8gxx_write_reg(priv, 0xc1, 0x3);
+
+	lgs8gxx_read_reg(priv, 0x7c, &t);
+	lgs8gxx_write_reg(priv, 0x7c, (t&0x8c) | 0x3);
+
+	/* LGS8913 specific */
+	lgs8gxx_read_reg(priv, 0xc3, &t);
+	lgs8gxx_write_reg(priv, 0xc3, t&0x10);
+
+
+	return 0;
+}
+
+static int lgs8g75_init_data(struct lgs8gxx_state *priv)
+{
+	const struct firmware *fw;
+	int rc;
+	int i;
+
+	rc = request_firmware(&fw, LGS8GXX_FIRMWARE, &priv->i2c->dev);
+	if (rc)
+		return rc;
+
+	lgs8gxx_write_reg(priv, 0xC6, 0x40);
+
+	lgs8gxx_write_reg(priv, 0x3D, 0x04);
+	lgs8gxx_write_reg(priv, 0x39, 0x00);
+
+	lgs8gxx_write_reg(priv, 0x3A, 0x00);
+	lgs8gxx_write_reg(priv, 0x38, 0x00);
+	lgs8gxx_write_reg(priv, 0x3B, 0x00);
+	lgs8gxx_write_reg(priv, 0x38, 0x00);
+
+	for (i = 0; i < fw->size; i++) {
+		lgs8gxx_write_reg(priv, 0x38, 0x00);
+		lgs8gxx_write_reg(priv, 0x3A, (u8)(i&0xff));
+		lgs8gxx_write_reg(priv, 0x3B, (u8)(i>>8));
+		lgs8gxx_write_reg(priv, 0x3C, fw->data[i]);
+	}
+
+	lgs8gxx_write_reg(priv, 0x38, 0x00);
+
+	release_firmware(fw);
+	return 0;
+}
+
+static int lgs8gxx_init(struct dvb_frontend *fe)
+{
+	struct lgs8gxx_state *priv =
+		(struct lgs8gxx_state *)fe->demodulator_priv;
+	const struct lgs8gxx_config *config = priv->config;
+	u8 data = 0;
+	s8 err;
+	dprintk("%s\n", __func__);
+
+	lgs8gxx_read_reg(priv, 0, &data);
+	dprintk("reg 0 = 0x%02X\n", data);
+
+	if (config->prod == LGS8GXX_PROD_LGS8G75)
+		lgs8g75_set_adc_vpp(priv, config->adc_vpp);
+
+	/* Setup MPEG output format */
+	err = lgs8gxx_set_mpeg_mode(priv, config->serial_ts,
+				    config->ts_clk_pol,
+				    config->ts_clk_gated);
+	if (err != 0)
+		return -EIO;
+
+	if (config->prod == LGS8GXX_PROD_LGS8913)
+		lgs8913_init(priv);
+	lgs8gxx_set_if_freq(priv, priv->config->if_freq);
+	lgs8gxx_set_ad_mode(priv);
+
+	return 0;
+}
+
+static void lgs8gxx_release(struct dvb_frontend *fe)
+{
+	struct lgs8gxx_state *state = fe->demodulator_priv;
+	dprintk("%s\n", __func__);
+
+	kfree(state);
+}
+
+
+static int lgs8gxx_write(struct dvb_frontend *fe, const u8 buf[], int len)
+{
+	struct lgs8gxx_state *priv = fe->demodulator_priv;
+
+	if (len != 2)
+		return -EINVAL;
+
+	return lgs8gxx_write_reg(priv, buf[0], buf[1]);
+}
+
+static int lgs8gxx_set_fe(struct dvb_frontend *fe)
+{
+
+	struct lgs8gxx_state *priv = fe->demodulator_priv;
+
+	dprintk("%s\n", __func__);
+
+	/* set frequency */
+	if (fe->ops.tuner_ops.set_params) {
+		fe->ops.tuner_ops.set_params(fe);
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 0);
+	}
+
+	/* start auto lock */
+	lgs8gxx_auto_lock(priv);
+
+	msleep(10);
+
+	return 0;
+}
+
+static int lgs8gxx_get_fe(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *fe_params = &fe->dtv_property_cache;
+	dprintk("%s\n", __func__);
+
+	/* TODO: get real readings from device */
+	/* inversion status */
+	fe_params->inversion = INVERSION_OFF;
+
+	/* bandwidth */
+	fe_params->bandwidth_hz = 8000000;
+
+	fe_params->code_rate_HP = FEC_AUTO;
+	fe_params->code_rate_LP = FEC_AUTO;
+
+	fe_params->modulation = QAM_AUTO;
+
+	/* transmission mode */
+	fe_params->transmission_mode = TRANSMISSION_MODE_AUTO;
+
+	/* guard interval */
+	fe_params->guard_interval = GUARD_INTERVAL_AUTO;
+
+	/* hierarchy */
+	fe_params->hierarchy = HIERARCHY_NONE;
+
+	return 0;
+}
+
+static
+int lgs8gxx_get_tune_settings(struct dvb_frontend *fe,
+			      struct dvb_frontend_tune_settings *fesettings)
+{
+	/* FIXME: copy from tda1004x.c */
+	fesettings->min_delay_ms = 800;
+	fesettings->step_size = 0;
+	fesettings->max_drift = 0;
+	return 0;
+}
+
+static int lgs8gxx_read_status(struct dvb_frontend *fe, fe_status_t *fe_status)
+{
+	struct lgs8gxx_state *priv = fe->demodulator_priv;
+	s8 ret;
+	u8 t, locked = 0;
+
+	dprintk("%s\n", __func__);
+	*fe_status = 0;
+
+	lgs8gxx_get_afc_phase(priv);
+	lgs8gxx_is_locked(priv, &locked);
+	if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
+		if (locked)
+			*fe_status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
+				FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
+		return 0;
+	}
+
+	ret = lgs8gxx_read_reg(priv, 0x4B, &t);
+	if (ret != 0)
+		return -EIO;
+
+	dprintk("Reg 0x4B: 0x%02X\n", t);
+
+	*fe_status = 0;
+	if (priv->config->prod == LGS8GXX_PROD_LGS8913) {
+		if ((t & 0x40) == 0x40)
+			*fe_status |= FE_HAS_SIGNAL | FE_HAS_CARRIER;
+		if ((t & 0x80) == 0x80)
+			*fe_status |= FE_HAS_VITERBI | FE_HAS_SYNC |
+				FE_HAS_LOCK;
+	} else {
+		if ((t & 0x80) == 0x80)
+			*fe_status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
+				FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
+	}
+
+	/* success */
+	dprintk("%s: fe_status=0x%x\n", __func__, *fe_status);
+	return 0;
+}
+
+static int lgs8gxx_read_signal_agc(struct lgs8gxx_state *priv, u16 *signal)
+{
+	u16 v;
+	u8 agc_lvl[2], cat;
+
+	dprintk("%s()\n", __func__);
+	lgs8gxx_read_reg(priv, 0x3F, &agc_lvl[0]);
+	lgs8gxx_read_reg(priv, 0x3E, &agc_lvl[1]);
+
+	v = agc_lvl[0];
+	v <<= 8;
+	v |= agc_lvl[1];
+
+	dprintk("agc_lvl: 0x%04X\n", v);
+
+	if (v < 0x100)
+		cat = 0;
+	else if (v < 0x190)
+		cat = 5;
+	else if (v < 0x2A8)
+		cat = 4;
+	else if (v < 0x381)
+		cat = 3;
+	else if (v < 0x400)
+		cat = 2;
+	else if (v == 0x400)
+		cat = 1;
+	else
+		cat = 0;
+
+	*signal = cat * 65535 / 5;
+
+	return 0;
+}
+
+static int lgs8913_read_signal_strength(struct lgs8gxx_state *priv, u16 *signal)
+{
+	u8 t; s8 ret;
+	s16 max_strength = 0;
+	u8 str;
+	u16 i, gi = priv->curr_gi;
+
+	dprintk("%s\n", __func__);
+
+	ret = lgs8gxx_read_reg(priv, 0x4B, &t);
+	if (ret != 0)
+		return -EIO;
+
+	if (fake_signal_str) {
+		if ((t & 0xC0) == 0xC0) {
+			dprintk("Fake signal strength\n");
+			*signal = 0x7FFF;
+		} else
+			*signal = 0;
+		return 0;
+	}
+
+	dprintk("gi = %d\n", gi);
+	for (i = 0; i < gi; i++) {
+
+		if ((i & 0xFF) == 0)
+			lgs8gxx_write_reg(priv, 0x84, 0x03 & (i >> 8));
+		lgs8gxx_write_reg(priv, 0x83, i & 0xFF);
+
+		lgs8gxx_read_reg(priv, 0x94, &str);
+		if (max_strength < str)
+			max_strength = str;
+	}
+
+	*signal = max_strength;
+	dprintk("%s: signal=0x%02X\n", __func__, *signal);
+
+	lgs8gxx_read_reg(priv, 0x95, &t);
+	dprintk("%s: AVG Noise=0x%02X\n", __func__, t);
+
+	return 0;
+}
+
+static int lgs8g75_read_signal_strength(struct lgs8gxx_state *priv, u16 *signal)
+{
+	u8 t;
+	s16 v = 0;
+
+	dprintk("%s\n", __func__);
+
+	lgs8gxx_read_reg(priv, 0xB1, &t);
+	v |= t;
+	v <<= 8;
+	lgs8gxx_read_reg(priv, 0xB0, &t);
+	v |= t;
+
+	*signal = v;
+	dprintk("%s: signal=0x%02X\n", __func__, *signal);
+
+	return 0;
+}
+
+static int lgs8gxx_read_signal_strength(struct dvb_frontend *fe, u16 *signal)
+{
+	struct lgs8gxx_state *priv = fe->demodulator_priv;
+
+	if (priv->config->prod == LGS8GXX_PROD_LGS8913)
+		return lgs8913_read_signal_strength(priv, signal);
+	else if (priv->config->prod == LGS8GXX_PROD_LGS8G75)
+		return lgs8g75_read_signal_strength(priv, signal);
+	else
+		return lgs8gxx_read_signal_agc(priv, signal);
+}
+
+static int lgs8gxx_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+	struct lgs8gxx_state *priv = fe->demodulator_priv;
+	u8 t;
+	*snr = 0;
+
+	if (priv->config->prod == LGS8GXX_PROD_LGS8G75)
+		lgs8gxx_read_reg(priv, 0x34, &t);
+	else
+		lgs8gxx_read_reg(priv, 0x95, &t);
+	dprintk("AVG Noise=0x%02X\n", t);
+	*snr = 256 - t;
+	*snr <<= 8;
+	dprintk("snr=0x%x\n", *snr);
+
+	return 0;
+}
+
+static int lgs8gxx_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+	*ucblocks = 0;
+	dprintk("%s: ucblocks=0x%x\n", __func__, *ucblocks);
+	return 0;
+}
+
+static void packet_counter_start(struct lgs8gxx_state *priv)
+{
+	u8 orig, t;
+
+	if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
+		lgs8gxx_read_reg(priv, 0x30, &orig);
+		orig &= 0xE7;
+		t = orig | 0x10;
+		lgs8gxx_write_reg(priv, 0x30, t);
+		t = orig | 0x18;
+		lgs8gxx_write_reg(priv, 0x30, t);
+		t = orig | 0x10;
+		lgs8gxx_write_reg(priv, 0x30, t);
+	} else {
+		lgs8gxx_write_reg(priv, 0xC6, 0x01);
+		lgs8gxx_write_reg(priv, 0xC6, 0x41);
+		lgs8gxx_write_reg(priv, 0xC6, 0x01);
+	}
+}
+
+static void packet_counter_stop(struct lgs8gxx_state *priv)
+{
+	u8 t;
+
+	if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
+		lgs8gxx_read_reg(priv, 0x30, &t);
+		t &= 0xE7;
+		lgs8gxx_write_reg(priv, 0x30, t);
+	} else {
+		lgs8gxx_write_reg(priv, 0xC6, 0x81);
+	}
+}
+
+static int lgs8gxx_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+	struct lgs8gxx_state *priv = fe->demodulator_priv;
+	u8 reg_err, reg_total, t;
+	u32 total_cnt = 0, err_cnt = 0;
+	int i;
+
+	dprintk("%s\n", __func__);
+
+	packet_counter_start(priv);
+	msleep(200);
+	packet_counter_stop(priv);
+
+	if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
+		reg_total = 0x28; reg_err = 0x2C;
+	} else {
+		reg_total = 0xD0; reg_err = 0xD4;
+	}
+
+	for (i = 0; i < 4; i++) {
+		total_cnt <<= 8;
+		lgs8gxx_read_reg(priv, reg_total+3-i, &t);
+		total_cnt |= t;
+	}
+	for (i = 0; i < 4; i++) {
+		err_cnt <<= 8;
+		lgs8gxx_read_reg(priv, reg_err+3-i, &t);
+		err_cnt |= t;
+	}
+	dprintk("error=%d total=%d\n", err_cnt, total_cnt);
+
+	if (total_cnt == 0)
+		*ber = 0;
+	else
+		*ber = err_cnt * 100 / total_cnt;
+
+	dprintk("%s: ber=0x%x\n", __func__, *ber);
+	return 0;
+}
+
+static int lgs8gxx_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+	struct lgs8gxx_state *priv = fe->demodulator_priv;
+
+	if (priv->config->tuner_address == 0)
+		return 0;
+	if (enable) {
+		u8 v = 0x80 | priv->config->tuner_address;
+		return lgs8gxx_write_reg(priv, 0x01, v);
+	}
+	return lgs8gxx_write_reg(priv, 0x01, 0);
+}
+
+static struct dvb_frontend_ops lgs8gxx_ops = {
+	.delsys = { SYS_DTMB },
+	.info = {
+		.name = "Legend Silicon LGS8913/LGS8GXX DMB-TH",
+		.frequency_min = 474000000,
+		.frequency_max = 858000000,
+		.frequency_stepsize = 10000,
+		.caps =
+			FE_CAN_FEC_AUTO |
+			FE_CAN_QAM_AUTO |
+			FE_CAN_TRANSMISSION_MODE_AUTO |
+			FE_CAN_GUARD_INTERVAL_AUTO
+	},
+
+	.release = lgs8gxx_release,
+
+	.init = lgs8gxx_init,
+	.write = lgs8gxx_write,
+	.i2c_gate_ctrl = lgs8gxx_i2c_gate_ctrl,
+
+	.set_frontend = lgs8gxx_set_fe,
+	.get_frontend = lgs8gxx_get_fe,
+	.get_tune_settings = lgs8gxx_get_tune_settings,
+
+	.read_status = lgs8gxx_read_status,
+	.read_ber = lgs8gxx_read_ber,
+	.read_signal_strength = lgs8gxx_read_signal_strength,
+	.read_snr = lgs8gxx_read_snr,
+	.read_ucblocks = lgs8gxx_read_ucblocks,
+};
+
+struct dvb_frontend *lgs8gxx_attach(const struct lgs8gxx_config *config,
+	struct i2c_adapter *i2c)
+{
+	struct lgs8gxx_state *priv = NULL;
+	u8 data = 0;
+
+	dprintk("%s()\n", __func__);
+
+	if (config == NULL || i2c == NULL)
+		return NULL;
+
+	priv = kzalloc(sizeof(struct lgs8gxx_state), GFP_KERNEL);
+	if (priv == NULL)
+		goto error_out;
+
+	priv->config = config;
+	priv->i2c = i2c;
+
+	/* check if the demod is there */
+	if (lgs8gxx_read_reg(priv, 0, &data) != 0) {
+		dprintk("%s lgs8gxx not found at i2c addr 0x%02X\n",
+			__func__, priv->config->demod_address);
+		goto error_out;
+	}
+
+	lgs8gxx_read_reg(priv, 1, &data);
+
+	memcpy(&priv->frontend.ops, &lgs8gxx_ops,
+	       sizeof(struct dvb_frontend_ops));
+	priv->frontend.demodulator_priv = priv;
+
+	if (config->prod == LGS8GXX_PROD_LGS8G75)
+		lgs8g75_init_data(priv);
+
+	return &priv->frontend;
+
+error_out:
+	dprintk("%s() error_out\n", __func__);
+	kfree(priv);
+	return NULL;
+
+}
+EXPORT_SYMBOL(lgs8gxx_attach);
+
+MODULE_DESCRIPTION("Legend Silicon LGS8913/LGS8GXX DMB-TH demodulator driver");
+MODULE_AUTHOR("David T. L. Wong <davidtlwong@gmail.com>");
+MODULE_LICENSE("GPL");
+MODULE_FIRMWARE(LGS8GXX_FIRMWARE);
diff --git a/drivers/media/dvb-frontends/lgs8gxx.h b/drivers/media/dvb-frontends/lgs8gxx.h
new file mode 100644
index 0000000..33c3c5e
--- /dev/null
+++ b/drivers/media/dvb-frontends/lgs8gxx.h
@@ -0,0 +1,95 @@
+/*
+ *    Support for Legend Silicon GB20600 (a.k.a DMB-TH) demodulator
+ *    LGS8913, LGS8GL5, LGS8G75
+ *    experimental support LGS8G42, LGS8G52
+ *
+ *    Copyright (C) 2007-2009 David T.L. Wong <davidtlwong@gmail.com>
+ *    Copyright (C) 2008 Sirius International (Hong Kong) Limited
+ *    Timothy Lee <timothy.lee@siriushk.com> (for initial work on LGS8GL5)
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the 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 __LGS8GXX_H__
+#define __LGS8GXX_H__
+
+#include <linux/dvb/frontend.h>
+#include <linux/i2c.h>
+
+#define LGS8GXX_PROD_LGS8913 0
+#define LGS8GXX_PROD_LGS8GL5 1
+#define LGS8GXX_PROD_LGS8G42 3
+#define LGS8GXX_PROD_LGS8G52 4
+#define LGS8GXX_PROD_LGS8G54 5
+#define LGS8GXX_PROD_LGS8G75 6
+
+struct lgs8gxx_config {
+
+	/* product type */
+	u8 prod;
+
+	/* the demodulator's i2c address */
+	u8 demod_address;
+
+	/* parallel or serial transport stream */
+	u8 serial_ts;
+
+	/* transport stream polarity*/
+	u8 ts_clk_pol;
+
+	/* transport stream clock gated by ts_valid */
+	u8 ts_clk_gated;
+
+	/* A/D Clock frequency */
+	u32 if_clk_freq; /* in kHz */
+
+	/* IF frequency */
+	u32 if_freq; /* in kHz */
+
+	/*Use External ADC*/
+	u8 ext_adc;
+
+	/*External ADC output two's complement*/
+	u8 adc_signed;
+
+	/*Sample IF data at falling edge of IF_CLK*/
+	u8 if_neg_edge;
+
+	/*IF use Negative center frequency*/
+	u8 if_neg_center;
+
+	/*8G75 internal ADC input range selection*/
+	/*0: 0.8Vpp, 1: 1.0Vpp, 2: 1.6Vpp, 3: 2.0Vpp*/
+	u8 adc_vpp;
+
+	/* slave address and configuration of the tuner */
+	u8 tuner_address;
+};
+
+#if defined(CONFIG_DVB_LGS8GXX) || \
+	(defined(CONFIG_DVB_LGS8GXX_MODULE) && defined(MODULE))
+extern struct dvb_frontend *lgs8gxx_attach(const struct lgs8gxx_config *config,
+					   struct i2c_adapter *i2c);
+#else
+static inline
+struct dvb_frontend *lgs8gxx_attach(const struct lgs8gxx_config *config,
+				    struct i2c_adapter *i2c) {
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif /* CONFIG_DVB_LGS8GXX */
+
+#endif /* __LGS8GXX_H__ */
diff --git a/drivers/media/dvb-frontends/lgs8gxx_priv.h b/drivers/media/dvb-frontends/lgs8gxx_priv.h
new file mode 100644
index 0000000..8ef376f
--- /dev/null
+++ b/drivers/media/dvb-frontends/lgs8gxx_priv.h
@@ -0,0 +1,70 @@
+/*
+ *    Support for Legend Silicon GB20600 (a.k.a DMB-TH) demodulator
+ *    LGS8913, LGS8GL5, LGS8G75
+ *    experimental support LGS8G42, LGS8G52
+ *
+ *    Copyright (C) 2007-2009 David T.L. Wong <davidtlwong@gmail.com>
+ *    Copyright (C) 2008 Sirius International (Hong Kong) Limited
+ *    Timothy Lee <timothy.lee@siriushk.com> (for initial work on LGS8GL5)
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the 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 LGS8913_PRIV_H
+#define LGS8913_PRIV_H
+
+struct lgs8gxx_state {
+	struct i2c_adapter *i2c;
+	/* configuration settings */
+	const struct lgs8gxx_config *config;
+	struct dvb_frontend frontend;
+	u16 curr_gi; /* current guard interval */
+};
+
+#define SC_MASK		0x1C	/* Sub-Carrier Modulation Mask */
+#define SC_QAM64	0x10	/* 64QAM modulation */
+#define SC_QAM32	0x0C	/* 32QAM modulation */
+#define SC_QAM16	0x08	/* 16QAM modulation */
+#define SC_QAM4NR	0x04	/* 4QAM-NR modulation */
+#define SC_QAM4		0x00	/* 4QAM modulation */
+
+#define LGS_FEC_MASK	0x03	/* FEC Rate Mask */
+#define LGS_FEC_0_4	0x00	/* FEC Rate 0.4 */
+#define LGS_FEC_0_6	0x01	/* FEC Rate 0.6 */
+#define LGS_FEC_0_8	0x02	/* FEC Rate 0.8 */
+
+#define TIM_MASK	  0x20	/* Time Interleave Length Mask */
+#define TIM_LONG	  0x20	/* Time Interleave Length = 720 */
+#define TIM_MIDDLE     0x00   /* Time Interleave Length = 240 */
+
+#define CF_MASK	0x80	/* Control Frame Mask */
+#define CF_EN	0x80	/* Control Frame On */
+
+#define GI_MASK	0x03	/* Guard Interval Mask */
+#define GI_420	0x00	/* 1/9 Guard Interval */
+#define GI_595	0x01	/* */
+#define GI_945	0x02	/* 1/4 Guard Interval */
+
+
+#define TS_PARALLEL	0x00	/* Parallel TS Output a.k.a. SPI */
+#define TS_SERIAL	0x01	/* Serial TS Output a.k.a. SSI */
+#define TS_CLK_NORMAL		0x00	/* MPEG Clock Normal */
+#define TS_CLK_INVERTED		0x02	/* MPEG Clock Inverted */
+#define TS_CLK_GATED		0x00	/* MPEG clock gated */
+#define TS_CLK_FREERUN		0x04	/* MPEG clock free running*/
+
+
+#endif
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
new file mode 100644
index 0000000..1343725
--- /dev/null
+++ b/drivers/media/dvb-frontends/lnbp21.c
@@ -0,0 +1,188 @@
+/*
+ * lnbp21.c - driver for lnb supply and control ic lnbp21
+ *
+ * Copyright (C) 2006, 2009 Oliver Endriss <o.endriss@gmx.de>
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ *
+ *
+ * the project's page is at http://www.linuxtv.org
+ */
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+
+#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)
+{
+	struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->sec_priv;
+	struct i2c_msg msg = {	.addr = lnbp21->i2c_addr, .flags = 0,
+				.buf = &lnbp21->config,
+				.len = sizeof(lnbp21->config) };
+
+	lnbp21->config &= ~(LNBP21_VSEL | LNBP21_EN);
+
+	switch(voltage) {
+	case SEC_VOLTAGE_OFF:
+		break;
+	case SEC_VOLTAGE_13:
+		lnbp21->config |= LNBP21_EN;
+		break;
+	case SEC_VOLTAGE_18:
+		lnbp21->config |= (LNBP21_EN | LNBP21_VSEL);
+		break;
+	default:
+		return -EINVAL;
+	};
+
+	lnbp21->config |= lnbp21->override_or;
+	lnbp21->config &= lnbp21->override_and;
+
+	return (i2c_transfer(lnbp21->i2c, &msg, 1) == 1) ? 0 : -EIO;
+}
+
+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 = lnbp21->i2c_addr, .flags = 0,
+				.buf = &lnbp21->config,
+				.len = sizeof(lnbp21->config) };
+
+	if (arg)
+		lnbp21->config |= LNBP21_LLC;
+	else
+		lnbp21->config &= ~LNBP21_LLC;
+
+	lnbp21->config |= lnbp21->override_or;
+	lnbp21->config &= lnbp21->override_and;
+
+	return (i2c_transfer(lnbp21->i2c, &msg, 1) == 1) ? 0 : -EIO;
+}
+
+static int lnbp21_set_tone(struct dvb_frontend *fe,
+				fe_sec_tone_mode_t tone)
+{
+	struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->sec_priv;
+	struct i2c_msg msg = {	.addr = lnbp21->i2c_addr, .flags = 0,
+				.buf = &lnbp21->config,
+				.len = sizeof(lnbp21->config) };
+
+	switch (tone) {
+	case SEC_TONE_OFF:
+		lnbp21->config &= ~LNBP21_TEN;
+		break;
+	case SEC_TONE_ON:
+		lnbp21->config |= LNBP21_TEN;
+		break;
+	default:
+		return -EINVAL;
+	};
+
+	lnbp21->config |= lnbp21->override_or;
+	lnbp21->config &= lnbp21->override_and;
+
+	return (i2c_transfer(lnbp21->i2c, &msg, 1) == 1) ? 0 : -EIO;
+}
+
+static void lnbp21_release(struct dvb_frontend *fe)
+{
+	/* LNBP power off */
+	lnbp21_set_voltage(fe, SEC_VOLTAGE_OFF);
+
+	/* free data */
+	kfree(fe->sec_priv);
+	fe->sec_priv = NULL;
+}
+
+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 = config;
+	lnbp21->i2c = i2c;
+	lnbp21->i2c_addr = i2c_addr;
+	fe->sec_priv = lnbp21;
+
+	/* bits which should be forced to '1' */
+	lnbp21->override_or = override_set;
+
+	/* bits which should be forced to '0' */
+	lnbp21->override_and = ~override_clear;
+
+	/* detect if it is present or not */
+	if (lnbp21_set_voltage(fe, SEC_VOLTAGE_OFF)) {
+		kfree(lnbp21);
+		return NULL;
+	}
+
+	/* install release callback */
+	fe->ops.release_sec = lnbp21_release;
+
+	/* override frontend ops */
+	fe->ops.set_voltage = lnbp21_set_voltage;
+	fe->ops.enable_high_lnb_voltage = lnbp21_enable_high_lnb_voltage;
+	if (!(override_clear & LNBH24_TEN)) /*22kHz logic controlled by demod*/
+		fe->ops.set_tone = lnbp21_set_tone;
+	printk(KERN_INFO "LNBx2x attached on addr=%x\n", 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, 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
new file mode 100644
index 0000000..fcdf1c6
--- /dev/null
+++ b/drivers/media/dvb-frontends/lnbp21.h
@@ -0,0 +1,75 @@
+/*
+ * lnbp21.h - driver for lnb supply and control ic lnbp21
+ *
+ * Copyright (C) 2006 Oliver Endriss
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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.
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ *
+ *
+ * the project's page is at http://www.linuxtv.org
+ */
+
+#ifndef _LNBP21_H
+#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);
+#else
+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
+
+#endif
diff --git a/drivers/media/dvb-frontends/lnbp22.c b/drivers/media/dvb-frontends/lnbp22.c
new file mode 100644
index 0000000..84ad039
--- /dev/null
+++ b/drivers/media/dvb-frontends/lnbp22.c
@@ -0,0 +1,148 @@
+/*
+ * lnbp22.h - driver for lnb supply and control ic lnbp22
+ *
+ * Copyright (C) 2006 Dominik Kuhlen
+ * Based on lnbp21 driver
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ *
+ *
+ * the project's page is at http://www.linuxtv.org
+ */
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+
+#include "dvb_frontend.h"
+#include "lnbp22.h"
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
+
+
+#define dprintk(lvl, arg...) if (debug >= (lvl)) printk(arg)
+
+struct lnbp22 {
+	u8		    config[4];
+	struct i2c_adapter *i2c;
+};
+
+static int lnbp22_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+{
+	struct lnbp22 *lnbp22 = (struct lnbp22 *)fe->sec_priv;
+	struct i2c_msg msg = {
+		.addr = 0x08,
+		.flags = 0,
+		.buf = (char *)&lnbp22->config,
+		.len = sizeof(lnbp22->config),
+	};
+
+	dprintk(1, "%s: %d (18V=%d 13V=%d)\n", __func__, voltage,
+	       SEC_VOLTAGE_18, SEC_VOLTAGE_13);
+
+	lnbp22->config[3] = 0x60; /* Power down */
+	switch (voltage) {
+	case SEC_VOLTAGE_OFF:
+		break;
+	case SEC_VOLTAGE_13:
+		lnbp22->config[3] |= LNBP22_EN;
+		break;
+	case SEC_VOLTAGE_18:
+		lnbp22->config[3] |= (LNBP22_EN | LNBP22_VSEL);
+		break;
+	default:
+		return -EINVAL;
+	};
+
+	dprintk(1, "%s: 0x%02x)\n", __func__, lnbp22->config[3]);
+	return (i2c_transfer(lnbp22->i2c, &msg, 1) == 1) ? 0 : -EIO;
+}
+
+static int lnbp22_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
+{
+	struct lnbp22 *lnbp22 = (struct lnbp22 *) fe->sec_priv;
+	struct i2c_msg msg = {
+		.addr = 0x08,
+		.flags = 0,
+		.buf = (char *)&lnbp22->config,
+		.len = sizeof(lnbp22->config),
+	};
+
+	dprintk(1, "%s: %d\n", __func__, (int)arg);
+	if (arg)
+		lnbp22->config[3] |= LNBP22_LLC;
+	else
+		lnbp22->config[3] &= ~LNBP22_LLC;
+
+	return (i2c_transfer(lnbp22->i2c, &msg, 1) == 1) ? 0 : -EIO;
+}
+
+static void lnbp22_release(struct dvb_frontend *fe)
+{
+	dprintk(1, "%s\n", __func__);
+	/* LNBP power off */
+	lnbp22_set_voltage(fe, SEC_VOLTAGE_OFF);
+
+	/* free data */
+	kfree(fe->sec_priv);
+	fe->sec_priv = NULL;
+}
+
+struct dvb_frontend *lnbp22_attach(struct dvb_frontend *fe,
+					struct i2c_adapter *i2c)
+{
+	struct lnbp22 *lnbp22 = kmalloc(sizeof(struct lnbp22), GFP_KERNEL);
+	if (!lnbp22)
+		return NULL;
+
+	/* default configuration */
+	lnbp22->config[0] = 0x00; /* ? */
+	lnbp22->config[1] = 0x28; /* ? */
+	lnbp22->config[2] = 0x48; /* ? */
+	lnbp22->config[3] = 0x60; /* Power down */
+	lnbp22->i2c = i2c;
+	fe->sec_priv = lnbp22;
+
+	/* detect if it is present or not */
+	if (lnbp22_set_voltage(fe, SEC_VOLTAGE_OFF)) {
+		dprintk(0, "%s LNBP22 not found\n", __func__);
+		kfree(lnbp22);
+		fe->sec_priv = NULL;
+		return NULL;
+	}
+
+	/* install release callback */
+	fe->ops.release_sec = lnbp22_release;
+
+	/* override frontend ops */
+	fe->ops.set_voltage = lnbp22_set_voltage;
+	fe->ops.enable_high_lnb_voltage = lnbp22_enable_high_lnb_voltage;
+
+	return fe;
+}
+EXPORT_SYMBOL(lnbp22_attach);
+
+MODULE_DESCRIPTION("Driver for lnb supply and control ic lnbp22");
+MODULE_AUTHOR("Dominik Kuhlen");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb-frontends/lnbp22.h b/drivers/media/dvb-frontends/lnbp22.h
new file mode 100644
index 0000000..63e2dec
--- /dev/null
+++ b/drivers/media/dvb-frontends/lnbp22.h
@@ -0,0 +1,57 @@
+/*
+ * lnbp22.h - driver for lnb supply and control ic lnbp22
+ *
+ * Copyright (C) 2006 Dominik Kuhlen
+ * Based on lnbp21.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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ *
+ *
+ * the project's page is at http://www.linuxtv.org
+ */
+
+#ifndef _LNBP22_H
+#define _LNBP22_H
+
+/* Enable */
+#define LNBP22_EN	  0x10
+/* Voltage selection */
+#define LNBP22_VSEL	0x02
+/* Plus 1 Volt Bit */
+#define LNBP22_LLC	0x01
+
+#include <linux/dvb/frontend.h>
+
+#if defined(CONFIG_DVB_LNBP22) || \
+		(defined(CONFIG_DVB_LNBP22_MODULE) && defined(MODULE))
+/*
+ * override_set and override_clear control which system register bits (above)
+ * to always set & clear
+ */
+extern struct dvb_frontend *lnbp22_attach(struct dvb_frontend *fe,
+						struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend *lnbp22_attach(struct dvb_frontend *fe,
+						struct i2c_adapter *i2c)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif /* CONFIG_DVB_LNBP22 */
+
+#endif /* _LNBP22_H */
diff --git a/drivers/media/dvb-frontends/m88rs2000.c b/drivers/media/dvb-frontends/m88rs2000.c
new file mode 100644
index 0000000..633815e
--- /dev/null
+++ b/drivers/media/dvb-frontends/m88rs2000.c
@@ -0,0 +1,919 @@
+/*
+	Driver for M88RS2000 demodulator and tuner
+
+	Copyright (C) 2012 Malcolm Priestley (tvboxspy@gmail.com)
+	Beta Driver
+
+	Include various calculation code from DS3000 driver.
+	Copyright (C) 2009 Konstantin Dimitrov.
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the 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/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/jiffies.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+
+#include "dvb_frontend.h"
+#include "m88rs2000.h"
+
+struct m88rs2000_state {
+	struct i2c_adapter *i2c;
+	const struct m88rs2000_config *config;
+	struct dvb_frontend frontend;
+	u8 no_lock_count;
+	u32 tuner_frequency;
+	u32 symbol_rate;
+	fe_code_rate_t fec_inner;
+	u8 tuner_level;
+	int errmode;
+};
+
+static int m88rs2000_debug;
+
+module_param_named(debug, m88rs2000_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able)).");
+
+#define dprintk(level, args...) do { \
+	if (level & m88rs2000_debug) \
+		printk(KERN_DEBUG "m88rs2000-fe: " args); \
+} while (0)
+
+#define deb_info(args...)  dprintk(0x01, args)
+#define info(format, arg...) \
+	printk(KERN_INFO "m88rs2000-fe: " format "\n" , ## arg)
+
+static int m88rs2000_writereg(struct m88rs2000_state *state, u8 tuner,
+	u8 reg, u8 data)
+{
+	int ret;
+	u8 addr = (tuner == 0) ? state->config->tuner_addr :
+		state->config->demod_addr;
+	u8 buf[] = { reg, data };
+	struct i2c_msg msg = {
+		.addr = addr,
+		.flags = 0,
+		.buf = buf,
+		.len = 2
+	};
+
+	ret = i2c_transfer(state->i2c, &msg, 1);
+
+	if (ret != 1)
+		deb_info("%s: writereg error (reg == 0x%02x, val == 0x%02x, "
+			"ret == %i)\n", __func__, reg, data, ret);
+
+	return (ret != 1) ? -EREMOTEIO : 0;
+}
+
+static int m88rs2000_demod_write(struct m88rs2000_state *state, u8 reg, u8 data)
+{
+	return m88rs2000_writereg(state, 1, reg, data);
+}
+
+static int m88rs2000_tuner_write(struct m88rs2000_state *state, u8 reg, u8 data)
+{
+	m88rs2000_demod_write(state, 0x81, 0x84);
+	udelay(10);
+	return m88rs2000_writereg(state, 0, reg, data);
+
+}
+
+static int m88rs2000_write(struct dvb_frontend *fe, const u8 buf[], int len)
+{
+	struct m88rs2000_state *state = fe->demodulator_priv;
+
+	if (len != 2)
+		return -EINVAL;
+
+	return m88rs2000_writereg(state, 1, buf[0], buf[1]);
+}
+
+static u8 m88rs2000_readreg(struct m88rs2000_state *state, u8 tuner, u8 reg)
+{
+	int ret;
+	u8 b0[] = { reg };
+	u8 b1[] = { 0 };
+	u8 addr = (tuner == 0) ? state->config->tuner_addr :
+		state->config->demod_addr;
+	struct i2c_msg msg[] = {
+		{
+			.addr = addr,
+			.flags = 0,
+			.buf = b0,
+			.len = 1
+		}, {
+			.addr = addr,
+			.flags = I2C_M_RD,
+			.buf = b1,
+			.len = 1
+		}
+	};
+
+	ret = i2c_transfer(state->i2c, msg, 2);
+
+	if (ret != 2)
+		deb_info("%s: readreg error (reg == 0x%02x, ret == %i)\n",
+				__func__, reg, ret);
+
+	return b1[0];
+}
+
+static u8 m88rs2000_demod_read(struct m88rs2000_state *state, u8 reg)
+{
+	return m88rs2000_readreg(state, 1, reg);
+}
+
+static u8 m88rs2000_tuner_read(struct m88rs2000_state *state, u8 reg)
+{
+	m88rs2000_demod_write(state, 0x81, 0x85);
+	udelay(10);
+	return m88rs2000_readreg(state, 0, reg);
+}
+
+static int m88rs2000_set_symbolrate(struct dvb_frontend *fe, u32 srate)
+{
+	struct m88rs2000_state *state = fe->demodulator_priv;
+	int ret;
+	u32 temp;
+	u8 b[3];
+
+	if ((srate < 1000000) || (srate > 45000000))
+		return -EINVAL;
+
+	temp = srate / 1000;
+	temp *= 11831;
+	temp /= 68;
+	temp -= 3;
+
+	b[0] = (u8) (temp >> 16) & 0xff;
+	b[1] = (u8) (temp >> 8) & 0xff;
+	b[2] = (u8) temp & 0xff;
+	ret = m88rs2000_demod_write(state, 0x93, b[2]);
+	ret |= m88rs2000_demod_write(state, 0x94, b[1]);
+	ret |= m88rs2000_demod_write(state, 0x95, b[0]);
+
+	deb_info("m88rs2000: m88rs2000_set_symbolrate\n");
+	return ret;
+}
+
+static int m88rs2000_send_diseqc_msg(struct dvb_frontend *fe,
+				    struct dvb_diseqc_master_cmd *m)
+{
+	struct m88rs2000_state *state = fe->demodulator_priv;
+
+	int i;
+	u8 reg;
+	deb_info("%s\n", __func__);
+	m88rs2000_demod_write(state, 0x9a, 0x30);
+	reg = m88rs2000_demod_read(state, 0xb2);
+	reg &= 0x3f;
+	m88rs2000_demod_write(state, 0xb2, reg);
+	for (i = 0; i <  m->msg_len; i++)
+		m88rs2000_demod_write(state, 0xb3 + i, m->msg[i]);
+
+	reg = m88rs2000_demod_read(state, 0xb1);
+	reg &= 0x87;
+	reg |= ((m->msg_len - 1) << 3) | 0x07;
+	reg &= 0x7f;
+	m88rs2000_demod_write(state, 0xb1, reg);
+
+	for (i = 0; i < 15; i++) {
+		if ((m88rs2000_demod_read(state, 0xb1) & 0x40) == 0x0)
+			break;
+		msleep(20);
+	}
+
+	reg = m88rs2000_demod_read(state, 0xb1);
+	if ((reg & 0x40) > 0x0) {
+		reg &= 0x7f;
+		reg |= 0x40;
+		m88rs2000_demod_write(state, 0xb1, reg);
+	}
+
+	reg = m88rs2000_demod_read(state, 0xb2);
+	reg &= 0x3f;
+	reg |= 0x80;
+	m88rs2000_demod_write(state, 0xb2, reg);
+	m88rs2000_demod_write(state, 0x9a, 0xb0);
+
+
+	return 0;
+}
+
+static int m88rs2000_send_diseqc_burst(struct dvb_frontend *fe,
+						fe_sec_mini_cmd_t burst)
+{
+	struct m88rs2000_state *state = fe->demodulator_priv;
+	u8 reg0, reg1;
+	deb_info("%s\n", __func__);
+	m88rs2000_demod_write(state, 0x9a, 0x30);
+	msleep(50);
+	reg0 = m88rs2000_demod_read(state, 0xb1);
+	reg1 = m88rs2000_demod_read(state, 0xb2);
+	/* TODO complete this section */
+	m88rs2000_demod_write(state, 0xb2, reg1);
+	m88rs2000_demod_write(state, 0xb1, reg0);
+	m88rs2000_demod_write(state, 0x9a, 0xb0);
+
+	return 0;
+}
+
+static int m88rs2000_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
+{
+	struct m88rs2000_state *state = fe->demodulator_priv;
+	u8 reg0, reg1;
+	m88rs2000_demod_write(state, 0x9a, 0x30);
+	reg0 = m88rs2000_demod_read(state, 0xb1);
+	reg1 = m88rs2000_demod_read(state, 0xb2);
+
+	reg1 &= 0x3f;
+
+	switch (tone) {
+	case SEC_TONE_ON:
+		reg0 |= 0x4;
+		reg0 &= 0xbc;
+		break;
+	case SEC_TONE_OFF:
+		reg1 |= 0x80;
+		break;
+	default:
+		break;
+	}
+	m88rs2000_demod_write(state, 0xb2, reg1);
+	m88rs2000_demod_write(state, 0xb1, reg0);
+	m88rs2000_demod_write(state, 0x9a, 0xb0);
+	return 0;
+}
+
+struct inittab {
+	u8 cmd;
+	u8 reg;
+	u8 val;
+};
+
+struct inittab m88rs2000_setup[] = {
+	{DEMOD_WRITE, 0x9a, 0x30},
+	{DEMOD_WRITE, 0x00, 0x01},
+	{WRITE_DELAY, 0x19, 0x00},
+	{DEMOD_WRITE, 0x00, 0x00},
+	{DEMOD_WRITE, 0x9a, 0xb0},
+	{DEMOD_WRITE, 0x81, 0xc1},
+	{TUNER_WRITE, 0x42, 0x73},
+	{TUNER_WRITE, 0x05, 0x07},
+	{TUNER_WRITE, 0x20, 0x27},
+	{TUNER_WRITE, 0x07, 0x02},
+	{TUNER_WRITE, 0x11, 0xff},
+	{TUNER_WRITE, 0x60, 0xf9},
+	{TUNER_WRITE, 0x08, 0x01},
+	{TUNER_WRITE, 0x00, 0x41},
+	{DEMOD_WRITE, 0x81, 0x81},
+	{DEMOD_WRITE, 0x86, 0xc6},
+	{DEMOD_WRITE, 0x9a, 0x30},
+	{DEMOD_WRITE, 0xf0, 0x22},
+	{DEMOD_WRITE, 0xf1, 0xbf},
+	{DEMOD_WRITE, 0xb0, 0x45},
+	{DEMOD_WRITE, 0xb2, 0x01}, /* set voltage pin always set 1*/
+	{DEMOD_WRITE, 0x9a, 0xb0},
+	{0xff, 0xaa, 0xff}
+};
+
+struct inittab m88rs2000_shutdown[] = {
+	{DEMOD_WRITE, 0x9a, 0x30},
+	{DEMOD_WRITE, 0xb0, 0x00},
+	{DEMOD_WRITE, 0xf1, 0x89},
+	{DEMOD_WRITE, 0x00, 0x01},
+	{DEMOD_WRITE, 0x9a, 0xb0},
+	{TUNER_WRITE, 0x00, 0x40},
+	{DEMOD_WRITE, 0x81, 0x81},
+	{0xff, 0xaa, 0xff}
+};
+
+struct inittab tuner_reset[] = {
+	{TUNER_WRITE, 0x42, 0x73},
+	{TUNER_WRITE, 0x05, 0x07},
+	{TUNER_WRITE, 0x20, 0x27},
+	{TUNER_WRITE, 0x07, 0x02},
+	{TUNER_WRITE, 0x11, 0xff},
+	{TUNER_WRITE, 0x60, 0xf9},
+	{TUNER_WRITE, 0x08, 0x01},
+	{TUNER_WRITE, 0x00, 0x41},
+	{0xff, 0xaa, 0xff}
+};
+
+struct inittab fe_reset[] = {
+	{DEMOD_WRITE, 0x00, 0x01},
+	{DEMOD_WRITE, 0xf1, 0xbf},
+	{DEMOD_WRITE, 0x00, 0x01},
+	{DEMOD_WRITE, 0x20, 0x81},
+	{DEMOD_WRITE, 0x21, 0x80},
+	{DEMOD_WRITE, 0x10, 0x33},
+	{DEMOD_WRITE, 0x11, 0x44},
+	{DEMOD_WRITE, 0x12, 0x07},
+	{DEMOD_WRITE, 0x18, 0x20},
+	{DEMOD_WRITE, 0x28, 0x04},
+	{DEMOD_WRITE, 0x29, 0x8e},
+	{DEMOD_WRITE, 0x3b, 0xff},
+	{DEMOD_WRITE, 0x32, 0x10},
+	{DEMOD_WRITE, 0x33, 0x02},
+	{DEMOD_WRITE, 0x34, 0x30},
+	{DEMOD_WRITE, 0x35, 0xff},
+	{DEMOD_WRITE, 0x38, 0x50},
+	{DEMOD_WRITE, 0x39, 0x68},
+	{DEMOD_WRITE, 0x3c, 0x7f},
+	{DEMOD_WRITE, 0x3d, 0x0f},
+	{DEMOD_WRITE, 0x45, 0x20},
+	{DEMOD_WRITE, 0x46, 0x24},
+	{DEMOD_WRITE, 0x47, 0x7c},
+	{DEMOD_WRITE, 0x48, 0x16},
+	{DEMOD_WRITE, 0x49, 0x04},
+	{DEMOD_WRITE, 0x4a, 0x01},
+	{DEMOD_WRITE, 0x4b, 0x78},
+	{DEMOD_WRITE, 0X4d, 0xd2},
+	{DEMOD_WRITE, 0x4e, 0x6d},
+	{DEMOD_WRITE, 0x50, 0x30},
+	{DEMOD_WRITE, 0x51, 0x30},
+	{DEMOD_WRITE, 0x54, 0x7b},
+	{DEMOD_WRITE, 0x56, 0x09},
+	{DEMOD_WRITE, 0x58, 0x59},
+	{DEMOD_WRITE, 0x59, 0x37},
+	{DEMOD_WRITE, 0x63, 0xfa},
+	{0xff, 0xaa, 0xff}
+};
+
+struct inittab fe_trigger[] = {
+	{DEMOD_WRITE, 0x97, 0x04},
+	{DEMOD_WRITE, 0x99, 0x77},
+	{DEMOD_WRITE, 0x9b, 0x64},
+	{DEMOD_WRITE, 0x9e, 0x00},
+	{DEMOD_WRITE, 0x9f, 0xf8},
+	{DEMOD_WRITE, 0xa0, 0x20},
+	{DEMOD_WRITE, 0xa1, 0xe0},
+	{DEMOD_WRITE, 0xa3, 0x38},
+	{DEMOD_WRITE, 0x98, 0xff},
+	{DEMOD_WRITE, 0xc0, 0x0f},
+	{DEMOD_WRITE, 0x89, 0x01},
+	{DEMOD_WRITE, 0x00, 0x00},
+	{WRITE_DELAY, 0x0a, 0x00},
+	{DEMOD_WRITE, 0x00, 0x01},
+	{DEMOD_WRITE, 0x00, 0x00},
+	{DEMOD_WRITE, 0x9a, 0xb0},
+	{0xff, 0xaa, 0xff}
+};
+
+static int m88rs2000_tab_set(struct m88rs2000_state *state,
+		struct inittab *tab)
+{
+	int ret = 0;
+	u8 i;
+	if (tab == NULL)
+		return -EINVAL;
+
+	for (i = 0; i < 255; i++) {
+		switch (tab[i].cmd) {
+		case 0x01:
+			ret = m88rs2000_demod_write(state, tab[i].reg,
+				tab[i].val);
+			break;
+		case 0x02:
+			ret = m88rs2000_tuner_write(state, tab[i].reg,
+				tab[i].val);
+			break;
+		case 0x10:
+			if (tab[i].reg > 0)
+				mdelay(tab[i].reg);
+			break;
+		case 0xff:
+			if (tab[i].reg == 0xaa && tab[i].val == 0xff)
+				return 0;
+		case 0x00:
+			break;
+		default:
+			return -EINVAL;
+		}
+		if (ret < 0)
+			return -ENODEV;
+	}
+	return 0;
+}
+
+static int m88rs2000_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t volt)
+{
+	struct m88rs2000_state *state = fe->demodulator_priv;
+	u8 data;
+
+	data = m88rs2000_demod_read(state, 0xb2);
+	data |= 0x03; /* bit0 V/H, bit1 off/on */
+
+	switch (volt) {
+	case SEC_VOLTAGE_18:
+		data &= ~0x03;
+		break;
+	case SEC_VOLTAGE_13:
+		data &= ~0x03;
+		data |= 0x01;
+		break;
+	case SEC_VOLTAGE_OFF:
+		break;
+	}
+
+	m88rs2000_demod_write(state, 0xb2, data);
+
+	return 0;
+}
+
+static int m88rs2000_startup(struct m88rs2000_state *state)
+{
+	int ret = 0;
+	u8 reg;
+
+	reg = m88rs2000_tuner_read(state, 0x00);
+	if ((reg & 0x40) == 0)
+		ret = -ENODEV;
+
+	return ret;
+}
+
+static int m88rs2000_init(struct dvb_frontend *fe)
+{
+	struct m88rs2000_state *state = fe->demodulator_priv;
+	int ret;
+
+	deb_info("m88rs2000: init chip\n");
+	/* Setup frontend from shutdown/cold */
+	ret = m88rs2000_tab_set(state, m88rs2000_setup);
+
+	return ret;
+}
+
+static int m88rs2000_sleep(struct dvb_frontend *fe)
+{
+	struct m88rs2000_state *state = fe->demodulator_priv;
+	int ret;
+	/* Shutdown the frondend */
+	ret = m88rs2000_tab_set(state, m88rs2000_shutdown);
+	return ret;
+}
+
+static int m88rs2000_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+	struct m88rs2000_state *state = fe->demodulator_priv;
+	u8 reg = m88rs2000_demod_read(state, 0x8c);
+
+	*status = 0;
+
+	if ((reg & 0x7) == 0x7) {
+		*status = FE_HAS_CARRIER | FE_HAS_SIGNAL | FE_HAS_VITERBI
+			| FE_HAS_SYNC | FE_HAS_LOCK;
+		if (state->config->set_ts_params)
+			state->config->set_ts_params(fe, CALL_IS_READ);
+	}
+	return 0;
+}
+
+/* Extact code for these unknown but lmedm04 driver uses interupt callbacks */
+
+static int m88rs2000_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+	deb_info("m88rs2000_read_ber %d\n", *ber);
+	*ber = 0;
+	return 0;
+}
+
+static int m88rs2000_read_signal_strength(struct dvb_frontend *fe,
+	u16 *strength)
+{
+	*strength = 0;
+	return 0;
+}
+
+static int m88rs2000_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+	deb_info("m88rs2000_read_snr %d\n", *snr);
+	*snr = 0;
+	return 0;
+}
+
+static int m88rs2000_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+	deb_info("m88rs2000_read_ber %d\n", *ucblocks);
+	*ucblocks = 0;
+	return 0;
+}
+
+static int m88rs2000_tuner_gate_ctrl(struct m88rs2000_state *state, u8 offset)
+{
+	int ret;
+	ret = m88rs2000_tuner_write(state, 0x51, 0x1f - offset);
+	ret |= m88rs2000_tuner_write(state, 0x51, 0x1f);
+	ret |= m88rs2000_tuner_write(state, 0x50, offset);
+	ret |= m88rs2000_tuner_write(state, 0x50, 0x00);
+	msleep(20);
+	return ret;
+}
+
+static int m88rs2000_set_tuner_rf(struct dvb_frontend *fe)
+{
+	struct m88rs2000_state *state = fe->demodulator_priv;
+	int reg;
+	reg = m88rs2000_tuner_read(state, 0x3d);
+	reg &= 0x7f;
+	if (reg < 0x16)
+		reg = 0xa1;
+	else if (reg == 0x16)
+		reg = 0x99;
+	else
+		reg = 0xf9;
+
+	m88rs2000_tuner_write(state, 0x60, reg);
+	reg = m88rs2000_tuner_gate_ctrl(state, 0x08);
+
+	if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 0);
+	return reg;
+}
+
+static int m88rs2000_set_tuner(struct dvb_frontend *fe, u16 *offset)
+{
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	struct m88rs2000_state *state = fe->demodulator_priv;
+	int ret;
+	u32 frequency = c->frequency;
+	s32 offset_khz;
+	s32 tmp;
+	u32 symbol_rate = (c->symbol_rate / 1000);
+	u32 f3db, gdiv28;
+	u16 value, ndiv, lpf_coeff;
+	u8 lpf_mxdiv, mlpf_max, mlpf_min, nlpf;
+	u8 lo = 0x01, div4 = 0x0;
+
+	/* Reset Tuner */
+	ret = m88rs2000_tab_set(state, tuner_reset);
+
+	/* Calculate frequency divider */
+	if (frequency < 1060000) {
+		lo |= 0x10;
+		div4 = 0x1;
+		ndiv = (frequency * 14 * 4) / FE_CRYSTAL_KHZ;
+	} else
+		ndiv = (frequency * 14 * 2) / FE_CRYSTAL_KHZ;
+	ndiv = ndiv + ndiv % 2;
+	ndiv = ndiv - 1024;
+
+	ret = m88rs2000_tuner_write(state, 0x10, 0x80 | lo);
+
+	/* Set frequency divider */
+	ret |= m88rs2000_tuner_write(state, 0x01, (ndiv >> 8) & 0xf);
+	ret |= m88rs2000_tuner_write(state, 0x02, ndiv & 0xff);
+
+	ret |= m88rs2000_tuner_write(state, 0x03, 0x06);
+	ret |= m88rs2000_tuner_gate_ctrl(state, 0x10);
+	if (ret < 0)
+		return -ENODEV;
+
+	/* Tuner Frequency Range */
+	ret = m88rs2000_tuner_write(state, 0x10, lo);
+
+	ret |= m88rs2000_tuner_gate_ctrl(state, 0x08);
+
+	/* Tuner RF */
+	ret |= m88rs2000_set_tuner_rf(fe);
+
+	gdiv28 = (FE_CRYSTAL_KHZ / 1000 * 1694 + 500) / 1000;
+	ret |= m88rs2000_tuner_write(state, 0x04, gdiv28 & 0xff);
+	ret |= m88rs2000_tuner_gate_ctrl(state, 0x04);
+	if (ret < 0)
+		return -ENODEV;
+
+	value = m88rs2000_tuner_read(state, 0x26);
+
+	f3db = (symbol_rate * 135) / 200 + 2000;
+	f3db += FREQ_OFFSET_LOW_SYM_RATE;
+	if (f3db < 7000)
+		f3db = 7000;
+	if (f3db > 40000)
+		f3db = 40000;
+
+	gdiv28 = gdiv28 * 207 / (value * 2 + 151);
+	mlpf_max = gdiv28 * 135 / 100;
+	mlpf_min = gdiv28 * 78 / 100;
+	if (mlpf_max > 63)
+		mlpf_max = 63;
+
+	lpf_coeff = 2766;
+
+	nlpf = (f3db * gdiv28 * 2 / lpf_coeff /
+		(FE_CRYSTAL_KHZ / 1000)  + 1) / 2;
+	if (nlpf > 23)
+		nlpf = 23;
+	if (nlpf < 1)
+		nlpf = 1;
+
+	lpf_mxdiv = (nlpf * (FE_CRYSTAL_KHZ / 1000)
+		* lpf_coeff * 2  / f3db + 1) / 2;
+
+	if (lpf_mxdiv < mlpf_min) {
+		nlpf++;
+		lpf_mxdiv = (nlpf * (FE_CRYSTAL_KHZ / 1000)
+			* lpf_coeff * 2  / f3db + 1) / 2;
+	}
+
+	if (lpf_mxdiv > mlpf_max)
+		lpf_mxdiv = mlpf_max;
+
+	ret = m88rs2000_tuner_write(state, 0x04, lpf_mxdiv);
+	ret |= m88rs2000_tuner_write(state, 0x06, nlpf);
+
+	ret |= m88rs2000_tuner_gate_ctrl(state, 0x04);
+
+	ret |= m88rs2000_tuner_gate_ctrl(state, 0x01);
+
+	msleep(80);
+	/* calculate offset assuming 96000kHz*/
+	offset_khz = (ndiv - ndiv % 2 + 1024) * FE_CRYSTAL_KHZ
+		/ 14 / (div4 + 1) / 2;
+
+	offset_khz -= frequency;
+
+	tmp = offset_khz;
+	tmp *= 65536;
+
+	tmp = (2 * tmp + 96000) / (2 * 96000);
+	if (tmp < 0)
+		tmp += 65536;
+
+	*offset = tmp & 0xffff;
+
+	if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 0);
+
+	return (ret < 0) ? -EINVAL : 0;
+}
+
+static int m88rs2000_set_fec(struct m88rs2000_state *state,
+		fe_code_rate_t fec)
+{
+	u16 fec_set;
+	switch (fec) {
+	/* This is not confirmed kept for reference */
+/*	case FEC_1_2:
+		fec_set = 0x88;
+		break;
+	case FEC_2_3:
+		fec_set = 0x68;
+		break;
+	case FEC_3_4:
+		fec_set = 0x48;
+		break;
+	case FEC_5_6:
+		fec_set = 0x28;
+		break;
+	case FEC_7_8:
+		fec_set = 0x18;
+		break; */
+	case FEC_AUTO:
+	default:
+		fec_set = 0x08;
+	}
+	m88rs2000_demod_write(state, 0x76, fec_set);
+
+	return 0;
+}
+
+
+static fe_code_rate_t m88rs2000_get_fec(struct m88rs2000_state *state)
+{
+	u8 reg;
+	m88rs2000_demod_write(state, 0x9a, 0x30);
+	reg = m88rs2000_demod_read(state, 0x76);
+	m88rs2000_demod_write(state, 0x9a, 0xb0);
+
+	switch (reg) {
+	case 0x88:
+		return FEC_1_2;
+	case 0x68:
+		return FEC_2_3;
+	case 0x48:
+		return FEC_3_4;
+	case 0x28:
+		return FEC_5_6;
+	case 0x18:
+		return FEC_7_8;
+	case 0x08:
+	default:
+		break;
+	}
+
+	return FEC_AUTO;
+}
+
+static int m88rs2000_set_frontend(struct dvb_frontend *fe)
+{
+	struct m88rs2000_state *state = fe->demodulator_priv;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	fe_status_t status;
+	int i, ret;
+	u16 offset = 0;
+	u8 reg;
+
+	state->no_lock_count = 0;
+
+	if (c->delivery_system != SYS_DVBS) {
+			deb_info("%s: unsupported delivery "
+				"system selected (%d)\n",
+				__func__, c->delivery_system);
+			return -EOPNOTSUPP;
+	}
+
+	/* Set Tuner */
+	ret = m88rs2000_set_tuner(fe, &offset);
+	if (ret < 0)
+		return -ENODEV;
+
+	ret = m88rs2000_demod_write(state, 0x9a, 0x30);
+	/* Unknown usually 0xc6 sometimes 0xc1 */
+	reg = m88rs2000_demod_read(state, 0x86);
+	ret |= m88rs2000_demod_write(state, 0x86, reg);
+	/* Offset lower nibble always 0 */
+	ret |= m88rs2000_demod_write(state, 0x9c, (offset >> 8));
+	ret |= m88rs2000_demod_write(state, 0x9d, offset & 0xf0);
+
+
+	/* Reset Demod */
+	ret = m88rs2000_tab_set(state, fe_reset);
+	if (ret < 0)
+		return -ENODEV;
+
+	/* Unknown */
+	reg = m88rs2000_demod_read(state, 0x70);
+	ret = m88rs2000_demod_write(state, 0x70, reg);
+
+	/* Set FEC */
+	ret |= m88rs2000_set_fec(state, c->fec_inner);
+	ret |= m88rs2000_demod_write(state, 0x85, 0x1);
+	ret |= m88rs2000_demod_write(state, 0x8a, 0xbf);
+	ret |= m88rs2000_demod_write(state, 0x8d, 0x1e);
+	ret |= m88rs2000_demod_write(state, 0x90, 0xf1);
+	ret |= m88rs2000_demod_write(state, 0x91, 0x08);
+
+	if (ret < 0)
+		return -ENODEV;
+
+	/* Set Symbol Rate */
+	ret = m88rs2000_set_symbolrate(fe, c->symbol_rate);
+	if (ret < 0)
+		return -ENODEV;
+
+	/* Set up Demod */
+	ret = m88rs2000_tab_set(state, fe_trigger);
+	if (ret < 0)
+		return -ENODEV;
+
+	for (i = 0; i < 25; i++) {
+		reg = m88rs2000_demod_read(state, 0x8c);
+		if ((reg & 0x7) == 0x7) {
+			status = FE_HAS_LOCK;
+			break;
+		}
+		state->no_lock_count++;
+		if (state->no_lock_count == 15) {
+			reg = m88rs2000_demod_read(state, 0x70);
+			reg ^= 0x4;
+			m88rs2000_demod_write(state, 0x70, reg);
+			state->no_lock_count = 0;
+		}
+		if (state->no_lock_count == 20)
+			m88rs2000_set_tuner_rf(fe);
+		msleep(20);
+	}
+
+	if (status & FE_HAS_LOCK) {
+		state->fec_inner = m88rs2000_get_fec(state);
+		/* Uknown suspect SNR level */
+		reg = m88rs2000_demod_read(state, 0x65);
+	}
+
+	state->tuner_frequency = c->frequency;
+	state->symbol_rate = c->symbol_rate;
+	return 0;
+}
+
+static int m88rs2000_get_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	struct m88rs2000_state *state = fe->demodulator_priv;
+	c->fec_inner = state->fec_inner;
+	c->frequency = state->tuner_frequency;
+	c->symbol_rate = state->symbol_rate;
+	return 0;
+}
+
+static int m88rs2000_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+	struct m88rs2000_state *state = fe->demodulator_priv;
+
+	if (enable)
+		m88rs2000_demod_write(state, 0x81, 0x84);
+	else
+		m88rs2000_demod_write(state, 0x81, 0x81);
+	udelay(10);
+	return 0;
+}
+
+static void m88rs2000_release(struct dvb_frontend *fe)
+{
+	struct m88rs2000_state *state = fe->demodulator_priv;
+	kfree(state);
+}
+
+static struct dvb_frontend_ops m88rs2000_ops = {
+	.delsys = { SYS_DVBS },
+	.info = {
+		.name			= "M88RS2000 DVB-S",
+		.frequency_min		= 950000,
+		.frequency_max		= 2150000,
+		.frequency_stepsize	= 1000,	 /* kHz for QPSK frontends */
+		.frequency_tolerance	= 5000,
+		.symbol_rate_min	= 1000000,
+		.symbol_rate_max	= 45000000,
+		.symbol_rate_tolerance	= 500,	/* ppm */
+		.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_FEC_AUTO
+	},
+
+	.release = m88rs2000_release,
+	.init = m88rs2000_init,
+	.sleep = m88rs2000_sleep,
+	.write = m88rs2000_write,
+	.i2c_gate_ctrl = m88rs2000_i2c_gate_ctrl,
+	.read_status = m88rs2000_read_status,
+	.read_ber = m88rs2000_read_ber,
+	.read_signal_strength = m88rs2000_read_signal_strength,
+	.read_snr = m88rs2000_read_snr,
+	.read_ucblocks = m88rs2000_read_ucblocks,
+	.diseqc_send_master_cmd = m88rs2000_send_diseqc_msg,
+	.diseqc_send_burst = m88rs2000_send_diseqc_burst,
+	.set_tone = m88rs2000_set_tone,
+	.set_voltage = m88rs2000_set_voltage,
+
+	.set_frontend = m88rs2000_set_frontend,
+	.get_frontend = m88rs2000_get_frontend,
+};
+
+struct dvb_frontend *m88rs2000_attach(const struct m88rs2000_config *config,
+				    struct i2c_adapter *i2c)
+{
+	struct m88rs2000_state *state = NULL;
+
+	/* allocate memory for the internal state */
+	state = kzalloc(sizeof(struct m88rs2000_state), GFP_KERNEL);
+	if (state == NULL)
+		goto error;
+
+	/* setup the state */
+	state->config = config;
+	state->i2c = i2c;
+	state->tuner_frequency = 0;
+	state->symbol_rate = 0;
+	state->fec_inner = 0;
+
+	if (m88rs2000_startup(state) < 0)
+		goto error;
+
+	/* create dvb_frontend */
+	memcpy(&state->frontend.ops, &m88rs2000_ops,
+			sizeof(struct dvb_frontend_ops));
+	state->frontend.demodulator_priv = state;
+	return &state->frontend;
+
+error:
+	kfree(state);
+
+	return NULL;
+}
+EXPORT_SYMBOL(m88rs2000_attach);
+
+MODULE_DESCRIPTION("M88RS2000 DVB-S Demodulator driver");
+MODULE_AUTHOR("Malcolm Priestley tvboxspy@gmail.com");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("1.13");
+
diff --git a/drivers/media/dvb-frontends/m88rs2000.h b/drivers/media/dvb-frontends/m88rs2000.h
new file mode 100644
index 0000000..59acdb6
--- /dev/null
+++ b/drivers/media/dvb-frontends/m88rs2000.h
@@ -0,0 +1,66 @@
+/*
+	Driver for M88RS2000 demodulator
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the 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 M88RS2000_H
+#define M88RS2000_H
+
+#include <linux/dvb/frontend.h>
+#include "dvb_frontend.h"
+
+struct m88rs2000_config {
+	/* Demodulator i2c address */
+	u8 demod_addr;
+	/* Tuner address */
+	u8 tuner_addr;
+
+	u8 *inittab;
+
+	/* minimum delay before retuning */
+	int min_delay_ms;
+
+	int (*set_ts_params)(struct dvb_frontend *, int);
+};
+
+enum {
+	CALL_IS_SET_FRONTEND = 0x0,
+	CALL_IS_READ,
+};
+
+#if defined(CONFIG_DVB_M88RS2000) || (defined(CONFIG_DVB_M88RS2000_MODULE) && \
+							defined(MODULE))
+extern struct dvb_frontend *m88rs2000_attach(
+	const struct m88rs2000_config *config, struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend *m88rs2000_attach(
+	const struct m88rs2000_config *config, struct i2c_adapter *i2c)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif /* CONFIG_DVB_M88RS2000 */
+
+#define FE_CRYSTAL_KHZ 27000
+#define FREQ_OFFSET_LOW_SYM_RATE 3000
+
+enum {
+	DEMOD_WRITE = 0x1,
+	TUNER_WRITE,
+	WRITE_DELAY = 0x10,
+};
+#endif /* M88RS2000_H */
diff --git a/drivers/media/dvb-frontends/mb86a16.c b/drivers/media/dvb-frontends/mb86a16.c
new file mode 100644
index 0000000..9ae40ab
--- /dev/null
+++ b/drivers/media/dvb-frontends/mb86a16.c
@@ -0,0 +1,1878 @@
+/*
+	Fujitsu MB86A16 DVB-S/DSS DC Receiver driver
+
+	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/slab.h>
+
+#include "dvb_frontend.h"
+#include "mb86a16.h"
+#include "mb86a16_priv.h"
+
+unsigned int verbose = 5;
+module_param(verbose, int, 0644);
+
+#define ABS(x)		((x) < 0 ? (-x) : (x))
+
+struct mb86a16_state {
+	struct i2c_adapter		*i2c_adap;
+	const struct mb86a16_config	*config;
+	struct dvb_frontend		frontend;
+
+	/* tuning parameters */
+	int				frequency;
+	int				srate;
+
+	/* Internal stuff */
+	int				master_clk;
+	int				deci;
+	int				csel;
+	int				rsel;
+};
+
+#define MB86A16_ERROR		0
+#define MB86A16_NOTICE		1
+#define MB86A16_INFO		2
+#define MB86A16_DEBUG		3
+
+#define dprintk(x, y, z, format, arg...) do {						\
+	if (z) {									\
+		if	((x > MB86A16_ERROR) && (x > y))				\
+			printk(KERN_ERR "%s: " format "\n", __func__, ##arg);		\
+		else if ((x > MB86A16_NOTICE) && (x > y))				\
+			printk(KERN_NOTICE "%s: " format "\n", __func__, ##arg);	\
+		else if ((x > MB86A16_INFO) && (x > y))					\
+			printk(KERN_INFO "%s: " format "\n", __func__, ##arg);		\
+		else if ((x > MB86A16_DEBUG) && (x > y))				\
+			printk(KERN_DEBUG "%s: " format "\n", __func__, ##arg);		\
+	} else {									\
+		if (x > y)								\
+			printk(format, ##arg);						\
+	}										\
+} while (0)
+
+#define TRACE_IN	dprintk(verbose, MB86A16_DEBUG, 1, "-->()")
+#define TRACE_OUT	dprintk(verbose, MB86A16_DEBUG, 1, "()-->")
+
+static int mb86a16_write(struct mb86a16_state *state, u8 reg, u8 val)
+{
+	int ret;
+	u8 buf[] = { reg, val };
+
+	struct i2c_msg msg = {
+		.addr = state->config->demod_address,
+		.flags = 0,
+		.buf = buf,
+		.len = 2
+	};
+
+	dprintk(verbose, MB86A16_DEBUG, 1,
+		"writing to [0x%02x],Reg[0x%02x],Data[0x%02x]",
+		state->config->demod_address, buf[0], buf[1]);
+
+	ret = i2c_transfer(state->i2c_adap, &msg, 1);
+
+	return (ret != 1) ? -EREMOTEIO : 0;
+}
+
+static int mb86a16_read(struct mb86a16_state *state, u8 reg, u8 *val)
+{
+	int ret;
+	u8 b0[] = { reg };
+	u8 b1[] = { 0 };
+
+	struct i2c_msg msg[] = {
+		{
+			.addr = state->config->demod_address,
+			.flags = 0,
+			.buf = b0,
+			.len = 1
+		}, {
+			.addr = state->config->demod_address,
+			.flags = I2C_M_RD,
+			.buf = b1,
+			.len = 1
+		}
+	};
+	ret = i2c_transfer(state->i2c_adap, msg, 2);
+	if (ret != 2) {
+		dprintk(verbose, MB86A16_ERROR, 1, "read error(reg=0x%02x, ret=0x%i)",
+			reg, ret);
+
+		return -EREMOTEIO;
+	}
+	*val = b1[0];
+
+	return ret;
+}
+
+static int CNTM_set(struct mb86a16_state *state,
+		    unsigned char timint1,
+		    unsigned char timint2,
+		    unsigned char cnext)
+{
+	unsigned char val;
+
+	val = (timint1 << 4) | (timint2 << 2) | cnext;
+	if (mb86a16_write(state, MB86A16_CNTMR, val) < 0)
+		goto err;
+
+	return 0;
+
+err:
+	dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+	return -EREMOTEIO;
+}
+
+static int smrt_set(struct mb86a16_state *state, int rate)
+{
+	int tmp ;
+	int m ;
+	unsigned char STOFS0, STOFS1;
+
+	m = 1 << state->deci;
+	tmp = (8192 * state->master_clk - 2 * m * rate * 8192 + state->master_clk / 2) / state->master_clk;
+
+	STOFS0 = tmp & 0x0ff;
+	STOFS1 = (tmp & 0xf00) >> 8;
+
+	if (mb86a16_write(state, MB86A16_SRATE1, (state->deci << 2) |
+				       (state->csel << 1) |
+					state->rsel) < 0)
+		goto err;
+	if (mb86a16_write(state, MB86A16_SRATE2, STOFS0) < 0)
+		goto err;
+	if (mb86a16_write(state, MB86A16_SRATE3, STOFS1) < 0)
+		goto err;
+
+	return 0;
+err:
+	dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+	return -1;
+}
+
+static int srst(struct mb86a16_state *state)
+{
+	if (mb86a16_write(state, MB86A16_RESET, 0x04) < 0)
+		goto err;
+
+	return 0;
+err:
+	dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+	return -EREMOTEIO;
+
+}
+
+static int afcex_data_set(struct mb86a16_state *state,
+			  unsigned char AFCEX_L,
+			  unsigned char AFCEX_H)
+{
+	if (mb86a16_write(state, MB86A16_AFCEXL, AFCEX_L) < 0)
+		goto err;
+	if (mb86a16_write(state, MB86A16_AFCEXH, AFCEX_H) < 0)
+		goto err;
+
+	return 0;
+err:
+	dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+
+	return -1;
+}
+
+static int afcofs_data_set(struct mb86a16_state *state,
+			   unsigned char AFCEX_L,
+			   unsigned char AFCEX_H)
+{
+	if (mb86a16_write(state, 0x58, AFCEX_L) < 0)
+		goto err;
+	if (mb86a16_write(state, 0x59, AFCEX_H) < 0)
+		goto err;
+
+	return 0;
+err:
+	dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+	return -EREMOTEIO;
+}
+
+static int stlp_set(struct mb86a16_state *state,
+		    unsigned char STRAS,
+		    unsigned char STRBS)
+{
+	if (mb86a16_write(state, MB86A16_STRFILTCOEF1, (STRBS << 3) | (STRAS)) < 0)
+		goto err;
+
+	return 0;
+err:
+	dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+	return -EREMOTEIO;
+}
+
+static int Vi_set(struct mb86a16_state *state, unsigned char ETH, unsigned char VIA)
+{
+	if (mb86a16_write(state, MB86A16_VISET2, 0x04) < 0)
+		goto err;
+	if (mb86a16_write(state, MB86A16_VISET3, 0xf5) < 0)
+		goto err;
+
+	return 0;
+err:
+	dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+	return -EREMOTEIO;
+}
+
+static int initial_set(struct mb86a16_state *state)
+{
+	if (stlp_set(state, 5, 7))
+		goto err;
+
+	udelay(100);
+	if (afcex_data_set(state, 0, 0))
+		goto err;
+
+	udelay(100);
+	if (afcofs_data_set(state, 0, 0))
+		goto err;
+
+	udelay(100);
+	if (mb86a16_write(state, MB86A16_CRLFILTCOEF1, 0x16) < 0)
+		goto err;
+	if (mb86a16_write(state, 0x2f, 0x21) < 0)
+		goto err;
+	if (mb86a16_write(state, MB86A16_VIMAG, 0x38) < 0)
+		goto err;
+	if (mb86a16_write(state, MB86A16_FAGCS1, 0x00) < 0)
+		goto err;
+	if (mb86a16_write(state, MB86A16_FAGCS2, 0x1c) < 0)
+		goto err;
+	if (mb86a16_write(state, MB86A16_FAGCS3, 0x20) < 0)
+		goto err;
+	if (mb86a16_write(state, MB86A16_FAGCS4, 0x1e) < 0)
+		goto err;
+	if (mb86a16_write(state, MB86A16_FAGCS5, 0x23) < 0)
+		goto err;
+	if (mb86a16_write(state, 0x54, 0xff) < 0)
+		goto err;
+	if (mb86a16_write(state, MB86A16_TSOUT, 0x00) < 0)
+		goto err;
+
+	return 0;
+
+err:
+	dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+	return -EREMOTEIO;
+}
+
+static int S01T_set(struct mb86a16_state *state,
+		    unsigned char s1t,
+		    unsigned s0t)
+{
+	if (mb86a16_write(state, 0x33, (s1t << 3) | s0t) < 0)
+		goto err;
+
+	return 0;
+err:
+	dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+	return -EREMOTEIO;
+}
+
+
+static int EN_set(struct mb86a16_state *state,
+		  int cren,
+		  int afcen)
+{
+	unsigned char val;
+
+	val = 0x7a | (cren << 7) | (afcen << 2);
+	if (mb86a16_write(state, 0x49, val) < 0)
+		goto err;
+
+	return 0;
+err:
+	dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+	return -EREMOTEIO;
+}
+
+static int AFCEXEN_set(struct mb86a16_state *state,
+		       int afcexen,
+		       int smrt)
+{
+	unsigned char AFCA ;
+
+	if (smrt > 18875)
+		AFCA = 4;
+	else if (smrt > 9375)
+		AFCA = 3;
+	else if (smrt > 2250)
+		AFCA = 2;
+	else
+		AFCA = 1;
+
+	if (mb86a16_write(state, 0x2a, 0x02 | (afcexen << 5) | (AFCA << 2)) < 0)
+		goto err;
+
+	return 0;
+
+err:
+	dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+	return -EREMOTEIO;
+}
+
+static int DAGC_data_set(struct mb86a16_state *state,
+			 unsigned char DAGCA,
+			 unsigned char DAGCW)
+{
+	if (mb86a16_write(state, 0x2d, (DAGCA << 3) | DAGCW) < 0)
+		goto err;
+
+	return 0;
+
+err:
+	dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+	return -EREMOTEIO;
+}
+
+static void smrt_info_get(struct mb86a16_state *state, int rate)
+{
+	if (rate >= 37501) {
+		state->deci = 0; state->csel = 0; state->rsel = 0;
+	} else if (rate >= 30001) {
+		state->deci = 0; state->csel = 0; state->rsel = 1;
+	} else if (rate >= 26251) {
+		state->deci = 0; state->csel = 1; state->rsel = 0;
+	} else if (rate >= 22501) {
+		state->deci = 0; state->csel = 1; state->rsel = 1;
+	} else if (rate >= 18751) {
+		state->deci = 1; state->csel = 0; state->rsel = 0;
+	} else if (rate >= 15001) {
+		state->deci = 1; state->csel = 0; state->rsel = 1;
+	} else if (rate >= 13126) {
+		state->deci = 1; state->csel = 1; state->rsel = 0;
+	} else if (rate >= 11251) {
+		state->deci = 1; state->csel = 1; state->rsel = 1;
+	} else if (rate >= 9376) {
+		state->deci = 2; state->csel = 0; state->rsel = 0;
+	} else if (rate >= 7501) {
+		state->deci = 2; state->csel = 0; state->rsel = 1;
+	} else if (rate >= 6563) {
+		state->deci = 2; state->csel = 1; state->rsel = 0;
+	} else if (rate >= 5626) {
+		state->deci = 2; state->csel = 1; state->rsel = 1;
+	} else if (rate >= 4688) {
+		state->deci = 3; state->csel = 0; state->rsel = 0;
+	} else if (rate >= 3751) {
+		state->deci = 3; state->csel = 0; state->rsel = 1;
+	} else if (rate >= 3282) {
+		state->deci = 3; state->csel = 1; state->rsel = 0;
+	} else if (rate >= 2814) {
+		state->deci = 3; state->csel = 1; state->rsel = 1;
+	} else if (rate >= 2344) {
+		state->deci = 4; state->csel = 0; state->rsel = 0;
+	} else if (rate >= 1876) {
+		state->deci = 4; state->csel = 0; state->rsel = 1;
+	} else if (rate >= 1641) {
+		state->deci = 4; state->csel = 1; state->rsel = 0;
+	} else if (rate >= 1407) {
+		state->deci = 4; state->csel = 1; state->rsel = 1;
+	} else if (rate >= 1172) {
+		state->deci = 5; state->csel = 0; state->rsel = 0;
+	} else if (rate >=  939) {
+		state->deci = 5; state->csel = 0; state->rsel = 1;
+	} else if (rate >=  821) {
+		state->deci = 5; state->csel = 1; state->rsel = 0;
+	} else {
+		state->deci = 5; state->csel = 1; state->rsel = 1;
+	}
+
+	if (state->csel == 0)
+		state->master_clk = 92000;
+	else
+		state->master_clk = 61333;
+
+}
+
+static int signal_det(struct mb86a16_state *state,
+		      int smrt,
+		      unsigned char *SIG)
+{
+
+	int ret ;
+	int smrtd ;
+	int wait_sym ;
+
+	u32 wait_t;
+	unsigned char S[3] ;
+	int i ;
+
+	if (*SIG > 45) {
+		if (CNTM_set(state, 2, 1, 2) < 0) {
+			dprintk(verbose, MB86A16_ERROR, 1, "CNTM set Error");
+			return -1;
+		}
+		wait_sym = 40000;
+	} else {
+		if (CNTM_set(state, 3, 1, 2) < 0) {
+			dprintk(verbose, MB86A16_ERROR, 1, "CNTM set Error");
+			return -1;
+		}
+		wait_sym = 80000;
+	}
+	for (i = 0; i < 3; i++) {
+		if (i == 0)
+			smrtd = smrt * 98 / 100;
+		else if (i == 1)
+			smrtd = smrt;
+		else
+			smrtd = smrt * 102 / 100;
+		smrt_info_get(state, smrtd);
+		smrt_set(state, smrtd);
+		srst(state);
+		wait_t = (wait_sym + 99 * smrtd / 100) / smrtd;
+		if (wait_t == 0)
+			wait_t = 1;
+		msleep_interruptible(10);
+		if (mb86a16_read(state, 0x37, &(S[i])) != 2) {
+			dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+			return -EREMOTEIO;
+		}
+	}
+	if ((S[1] > S[0] * 112 / 100) &&
+	    (S[1] > S[2] * 112 / 100)) {
+
+		ret = 1;
+	} else {
+		ret = 0;
+	}
+	*SIG = S[1];
+
+	if (CNTM_set(state, 0, 1, 2) < 0) {
+		dprintk(verbose, MB86A16_ERROR, 1, "CNTM set Error");
+		return -1;
+	}
+
+	return ret;
+}
+
+static int rf_val_set(struct mb86a16_state *state,
+		      int f,
+		      int smrt,
+		      unsigned char R)
+{
+	unsigned char C, F, B;
+	int M;
+	unsigned char rf_val[5];
+	int ack = -1;
+
+	if (smrt > 37750)
+		C = 1;
+	else if (smrt > 18875)
+		C = 2;
+	else if (smrt > 5500)
+		C = 3;
+	else
+		C = 4;
+
+	if (smrt > 30500)
+		F = 3;
+	else if (smrt > 9375)
+		F = 1;
+	else if (smrt > 4625)
+		F = 0;
+	else
+		F = 2;
+
+	if (f < 1060)
+		B = 0;
+	else if (f < 1175)
+		B = 1;
+	else if (f < 1305)
+		B = 2;
+	else if (f < 1435)
+		B = 3;
+	else if (f < 1570)
+		B = 4;
+	else if (f < 1715)
+		B = 5;
+	else if (f < 1845)
+		B = 6;
+	else if (f < 1980)
+		B = 7;
+	else if (f < 2080)
+		B = 8;
+	else
+		B = 9;
+
+	M = f * (1 << R) / 2;
+
+	rf_val[0] = 0x01 | (C << 3) | (F << 1);
+	rf_val[1] = (R << 5) | ((M & 0x1f000) >> 12);
+	rf_val[2] = (M & 0x00ff0) >> 4;
+	rf_val[3] = ((M & 0x0000f) << 4) | B;
+
+	/* Frequency Set */
+	if (mb86a16_write(state, 0x21, rf_val[0]) < 0)
+		ack = 0;
+	if (mb86a16_write(state, 0x22, rf_val[1]) < 0)
+		ack = 0;
+	if (mb86a16_write(state, 0x23, rf_val[2]) < 0)
+		ack = 0;
+	if (mb86a16_write(state, 0x24, rf_val[3]) < 0)
+		ack = 0;
+	if (mb86a16_write(state, 0x25, 0x01) < 0)
+		ack = 0;
+	if (ack == 0) {
+		dprintk(verbose, MB86A16_ERROR, 1, "RF Setup - I2C transfer error");
+		return -EREMOTEIO;
+	}
+
+	return 0;
+}
+
+static int afcerr_chk(struct mb86a16_state *state)
+{
+	unsigned char AFCM_L, AFCM_H ;
+	int AFCM ;
+	int afcm, afcerr ;
+
+	if (mb86a16_read(state, 0x0e, &AFCM_L) != 2)
+		goto err;
+	if (mb86a16_read(state, 0x0f, &AFCM_H) != 2)
+		goto err;
+
+	AFCM = (AFCM_H << 8) + AFCM_L;
+
+	if (AFCM > 2048)
+		afcm = AFCM - 4096;
+	else
+		afcm = AFCM;
+	afcerr = afcm * state->master_clk / 8192;
+
+	return afcerr;
+
+err:
+	dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+	return -EREMOTEIO;
+}
+
+static int dagcm_val_get(struct mb86a16_state *state)
+{
+	int DAGCM;
+	unsigned char DAGCM_H, DAGCM_L;
+
+	if (mb86a16_read(state, 0x45, &DAGCM_L) != 2)
+		goto err;
+	if (mb86a16_read(state, 0x46, &DAGCM_H) != 2)
+		goto err;
+
+	DAGCM = (DAGCM_H << 8) + DAGCM_L;
+
+	return DAGCM;
+
+err:
+	dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+	return -EREMOTEIO;
+}
+
+static int mb86a16_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+	u8 stat, stat2;
+	struct mb86a16_state *state = fe->demodulator_priv;
+
+	*status = 0;
+
+	if (mb86a16_read(state, MB86A16_SIG1, &stat) != 2)
+		goto err;
+	if (mb86a16_read(state, MB86A16_SIG2, &stat2) != 2)
+		goto err;
+	if ((stat > 25) && (stat2 > 25))
+		*status |= FE_HAS_SIGNAL;
+	if ((stat > 45) && (stat2 > 45))
+		*status |= FE_HAS_CARRIER;
+
+	if (mb86a16_read(state, MB86A16_STATUS, &stat) != 2)
+		goto err;
+
+	if (stat & 0x01)
+		*status |= FE_HAS_SYNC;
+	if (stat & 0x01)
+		*status |= FE_HAS_VITERBI;
+
+	if (mb86a16_read(state, MB86A16_FRAMESYNC, &stat) != 2)
+		goto err;
+
+	if ((stat & 0x0f) && (*status & FE_HAS_VITERBI))
+		*status |= FE_HAS_LOCK;
+
+	return 0;
+
+err:
+	dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+	return -EREMOTEIO;
+}
+
+static int sync_chk(struct mb86a16_state *state,
+		    unsigned char *VIRM)
+{
+	unsigned char val;
+	int sync;
+
+	if (mb86a16_read(state, 0x0d, &val) != 2)
+		goto err;
+
+	dprintk(verbose, MB86A16_INFO, 1, "Status = %02x,", val);
+	sync = val & 0x01;
+	*VIRM = (val & 0x1c) >> 2;
+
+	return sync;
+err:
+	dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+	return -EREMOTEIO;
+
+}
+
+static int freqerr_chk(struct mb86a16_state *state,
+		       int fTP,
+		       int smrt,
+		       int unit)
+{
+	unsigned char CRM, AFCML, AFCMH;
+	unsigned char temp1, temp2, temp3;
+	int crm, afcm, AFCM;
+	int crrerr, afcerr;		/* kHz */
+	int frqerr;			/* MHz */
+	int afcen, afcexen = 0;
+	int R, M, fOSC, fOSC_OFS;
+
+	if (mb86a16_read(state, 0x43, &CRM) != 2)
+		goto err;
+
+	if (CRM > 127)
+		crm = CRM - 256;
+	else
+		crm = CRM;
+
+	crrerr = smrt * crm / 256;
+	if (mb86a16_read(state, 0x49, &temp1) != 2)
+		goto err;
+
+	afcen = (temp1 & 0x04) >> 2;
+	if (afcen == 0) {
+		if (mb86a16_read(state, 0x2a, &temp1) != 2)
+			goto err;
+		afcexen = (temp1 & 0x20) >> 5;
+	}
+
+	if (afcen == 1) {
+		if (mb86a16_read(state, 0x0e, &AFCML) != 2)
+			goto err;
+		if (mb86a16_read(state, 0x0f, &AFCMH) != 2)
+			goto err;
+	} else if (afcexen == 1) {
+		if (mb86a16_read(state, 0x2b, &AFCML) != 2)
+			goto err;
+		if (mb86a16_read(state, 0x2c, &AFCMH) != 2)
+			goto err;
+	}
+	if ((afcen == 1) || (afcexen == 1)) {
+		smrt_info_get(state, smrt);
+		AFCM = ((AFCMH & 0x01) << 8) + AFCML;
+		if (AFCM > 255)
+			afcm = AFCM - 512;
+		else
+			afcm = AFCM;
+
+		afcerr = afcm * state->master_clk / 8192;
+	} else
+		afcerr = 0;
+
+	if (mb86a16_read(state, 0x22, &temp1) != 2)
+		goto err;
+	if (mb86a16_read(state, 0x23, &temp2) != 2)
+		goto err;
+	if (mb86a16_read(state, 0x24, &temp3) != 2)
+		goto err;
+
+	R = (temp1 & 0xe0) >> 5;
+	M = ((temp1 & 0x1f) << 12) + (temp2 << 4) + (temp3 >> 4);
+	if (R == 0)
+		fOSC = 2 * M;
+	else
+		fOSC = M;
+
+	fOSC_OFS = fOSC - fTP;
+
+	if (unit == 0) {	/* MHz */
+		if (crrerr + afcerr + fOSC_OFS * 1000 >= 0)
+			frqerr = (crrerr + afcerr + fOSC_OFS * 1000 + 500) / 1000;
+		else
+			frqerr = (crrerr + afcerr + fOSC_OFS * 1000 - 500) / 1000;
+	} else {	/* kHz */
+		frqerr = crrerr + afcerr + fOSC_OFS * 1000;
+	}
+
+	return frqerr;
+err:
+	dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+	return -EREMOTEIO;
+}
+
+static unsigned char vco_dev_get(struct mb86a16_state *state, int smrt)
+{
+	unsigned char R;
+
+	if (smrt > 9375)
+		R = 0;
+	else
+		R = 1;
+
+	return R;
+}
+
+static void swp_info_get(struct mb86a16_state *state,
+			 int fOSC_start,
+			 int smrt,
+			 int v, int R,
+			 int swp_ofs,
+			 int *fOSC,
+			 int *afcex_freq,
+			 unsigned char *AFCEX_L,
+			 unsigned char *AFCEX_H)
+{
+	int AFCEX ;
+	int crnt_swp_freq ;
+
+	crnt_swp_freq = fOSC_start * 1000 + v * swp_ofs;
+
+	if (R == 0)
+		*fOSC = (crnt_swp_freq + 1000) / 2000 * 2;
+	else
+		*fOSC = (crnt_swp_freq + 500) / 1000;
+
+	if (*fOSC >= crnt_swp_freq)
+		*afcex_freq = *fOSC * 1000 - crnt_swp_freq;
+	else
+		*afcex_freq = crnt_swp_freq - *fOSC * 1000;
+
+	AFCEX = *afcex_freq * 8192 / state->master_clk;
+	*AFCEX_L =  AFCEX & 0x00ff;
+	*AFCEX_H = (AFCEX & 0x0f00) >> 8;
+}
+
+
+static int swp_freq_calcuation(struct mb86a16_state *state, int i, int v, int *V,  int vmax, int vmin,
+			       int SIGMIN, int fOSC, int afcex_freq, int swp_ofs, unsigned char *SIG1)
+{
+	int swp_freq ;
+
+	if ((i % 2 == 1) && (v <= vmax)) {
+		/* positive v (case 1) */
+		if ((v - 1 == vmin)				&&
+		    (*(V + 30 + v) >= 0)			&&
+		    (*(V + 30 + v - 1) >= 0)			&&
+		    (*(V + 30 + v - 1) > *(V + 30 + v))		&&
+		    (*(V + 30 + v - 1) > SIGMIN)) {
+
+			swp_freq = fOSC * 1000 + afcex_freq - swp_ofs;
+			*SIG1 = *(V + 30 + v - 1);
+		} else if ((v == vmax)				&&
+			   (*(V + 30 + v) >= 0)			&&
+			   (*(V + 30 + v - 1) >= 0)		&&
+			   (*(V + 30 + v) > *(V + 30 + v - 1))	&&
+			   (*(V + 30 + v) > SIGMIN)) {
+			/* (case 2) */
+			swp_freq = fOSC * 1000 + afcex_freq;
+			*SIG1 = *(V + 30 + v);
+		} else if ((*(V + 30 + v) > 0)			&&
+			   (*(V + 30 + v - 1) > 0)		&&
+			   (*(V + 30 + v - 2) > 0)		&&
+			   (*(V + 30 + v - 3) > 0)		&&
+			   (*(V + 30 + v - 1) > *(V + 30 + v))	&&
+			   (*(V + 30 + v - 2) > *(V + 30 + v - 3)) &&
+			   ((*(V + 30 + v - 1) > SIGMIN)	||
+			   (*(V + 30 + v - 2) > SIGMIN))) {
+			/* (case 3) */
+			if (*(V + 30 + v - 1) >= *(V + 30 + v - 2)) {
+				swp_freq = fOSC * 1000 + afcex_freq - swp_ofs;
+				*SIG1 = *(V + 30 + v - 1);
+			} else {
+				swp_freq = fOSC * 1000 + afcex_freq - swp_ofs * 2;
+				*SIG1 = *(V + 30 + v - 2);
+			}
+		} else if ((v == vmax)				&&
+			   (*(V + 30 + v) >= 0)			&&
+			   (*(V + 30 + v - 1) >= 0)		&&
+			   (*(V + 30 + v - 2) >= 0)		&&
+			   (*(V + 30 + v) > *(V + 30 + v - 2))	&&
+			   (*(V + 30 + v - 1) > *(V + 30 + v - 2)) &&
+			   ((*(V + 30 + v) > SIGMIN)		||
+			   (*(V + 30 + v - 1) > SIGMIN))) {
+			/* (case 4) */
+			if (*(V + 30 + v) >= *(V + 30 + v - 1)) {
+				swp_freq = fOSC * 1000 + afcex_freq;
+				*SIG1 = *(V + 30 + v);
+			} else {
+				swp_freq = fOSC * 1000 + afcex_freq - swp_ofs;
+				*SIG1 = *(V + 30 + v - 1);
+			}
+		} else  {
+			swp_freq = -1 ;
+		}
+	} else if ((i % 2 == 0) && (v >= vmin)) {
+		/* Negative v (case 1) */
+		if ((*(V + 30 + v) > 0)				&&
+		    (*(V + 30 + v + 1) > 0)			&&
+		    (*(V + 30 + v + 2) > 0)			&&
+		    (*(V + 30 + v + 1) > *(V + 30 + v))		&&
+		    (*(V + 30 + v + 1) > *(V + 30 + v + 2))	&&
+		    (*(V + 30 + v + 1) > SIGMIN)) {
+
+			swp_freq = fOSC * 1000 + afcex_freq + swp_ofs;
+			*SIG1 = *(V + 30 + v + 1);
+		} else if ((v + 1 == vmax)			&&
+			   (*(V + 30 + v) >= 0)			&&
+			   (*(V + 30 + v + 1) >= 0)		&&
+			   (*(V + 30 + v + 1) > *(V + 30 + v))	&&
+			   (*(V + 30 + v + 1) > SIGMIN)) {
+			/* (case 2) */
+			swp_freq = fOSC * 1000 + afcex_freq + swp_ofs;
+			*SIG1 = *(V + 30 + v);
+		} else if ((v == vmin)				&&
+			   (*(V + 30 + v) > 0)			&&
+			   (*(V + 30 + v + 1) > 0)		&&
+			   (*(V + 30 + v + 2) > 0)		&&
+			   (*(V + 30 + v) > *(V + 30 + v + 1))	&&
+			   (*(V + 30 + v) > *(V + 30 + v + 2))	&&
+			   (*(V + 30 + v) > SIGMIN)) {
+			/* (case 3) */
+			swp_freq = fOSC * 1000 + afcex_freq;
+			*SIG1 = *(V + 30 + v);
+		} else if ((*(V + 30 + v) >= 0)			&&
+			   (*(V + 30 + v + 1) >= 0)		&&
+			   (*(V + 30 + v + 2) >= 0)		&&
+			   (*(V + 30 + v + 3) >= 0)		&&
+			   (*(V + 30 + v + 1) > *(V + 30 + v))	&&
+			   (*(V + 30 + v + 2) > *(V + 30 + v + 3)) &&
+			   ((*(V + 30 + v + 1) > SIGMIN)	||
+			    (*(V + 30 + v + 2) > SIGMIN))) {
+			/* (case 4) */
+			if (*(V + 30 + v + 1) >= *(V + 30 + v + 2)) {
+				swp_freq = fOSC * 1000 + afcex_freq + swp_ofs;
+				*SIG1 = *(V + 30 + v + 1);
+			} else {
+				swp_freq = fOSC * 1000 + afcex_freq + swp_ofs * 2;
+				*SIG1 = *(V + 30 + v + 2);
+			}
+		} else if ((*(V + 30 + v) >= 0)			&&
+			   (*(V + 30 + v + 1) >= 0)		&&
+			   (*(V + 30 + v + 2) >= 0)		&&
+			   (*(V + 30 + v + 3) >= 0)		&&
+			   (*(V + 30 + v) > *(V + 30 + v + 2))	&&
+			   (*(V + 30 + v + 1) > *(V + 30 + v + 2)) &&
+			   (*(V + 30 + v) > *(V + 30 + v + 3))	&&
+			   (*(V + 30 + v + 1) > *(V + 30 + v + 3)) &&
+			   ((*(V + 30 + v) > SIGMIN)		||
+			    (*(V + 30 + v + 1) > SIGMIN))) {
+			/* (case 5) */
+			if (*(V + 30 + v) >= *(V + 30 + v + 1)) {
+				swp_freq = fOSC * 1000 + afcex_freq;
+				*SIG1 = *(V + 30 + v);
+			} else {
+				swp_freq = fOSC * 1000 + afcex_freq + swp_ofs;
+				*SIG1 = *(V + 30 + v + 1);
+			}
+		} else if ((v + 2 == vmin)			&&
+			   (*(V + 30 + v) >= 0)			&&
+			   (*(V + 30 + v + 1) >= 0)		&&
+			   (*(V + 30 + v + 2) >= 0)		&&
+			   (*(V + 30 + v + 1) > *(V + 30 + v))	&&
+			   (*(V + 30 + v + 2) > *(V + 30 + v))	&&
+			   ((*(V + 30 + v + 1) > SIGMIN)	||
+			    (*(V + 30 + v + 2) > SIGMIN))) {
+			/* (case 6) */
+			if (*(V + 30 + v + 1) >= *(V + 30 + v + 2)) {
+				swp_freq = fOSC * 1000 + afcex_freq + swp_ofs;
+				*SIG1 = *(V + 30 + v + 1);
+			} else {
+				swp_freq = fOSC * 1000 + afcex_freq + swp_ofs * 2;
+				*SIG1 = *(V + 30 + v + 2);
+			}
+		} else if ((vmax == 0) && (vmin == 0) && (*(V + 30 + v) > SIGMIN)) {
+			swp_freq = fOSC * 1000;
+			*SIG1 = *(V + 30 + v);
+		} else
+			swp_freq = -1;
+	} else
+		swp_freq = -1;
+
+	return swp_freq;
+}
+
+static void swp_info_get2(struct mb86a16_state *state,
+			  int smrt,
+			  int R,
+			  int swp_freq,
+			  int *afcex_freq,
+			  int *fOSC,
+			  unsigned char *AFCEX_L,
+			  unsigned char *AFCEX_H)
+{
+	int AFCEX ;
+
+	if (R == 0)
+		*fOSC = (swp_freq + 1000) / 2000 * 2;
+	else
+		*fOSC = (swp_freq + 500) / 1000;
+
+	if (*fOSC >= swp_freq)
+		*afcex_freq = *fOSC * 1000 - swp_freq;
+	else
+		*afcex_freq = swp_freq - *fOSC * 1000;
+
+	AFCEX = *afcex_freq * 8192 / state->master_clk;
+	*AFCEX_L =  AFCEX & 0x00ff;
+	*AFCEX_H = (AFCEX & 0x0f00) >> 8;
+}
+
+static void afcex_info_get(struct mb86a16_state *state,
+			   int afcex_freq,
+			   unsigned char *AFCEX_L,
+			   unsigned char *AFCEX_H)
+{
+	int AFCEX ;
+
+	AFCEX = afcex_freq * 8192 / state->master_clk;
+	*AFCEX_L =  AFCEX & 0x00ff;
+	*AFCEX_H = (AFCEX & 0x0f00) >> 8;
+}
+
+static int SEQ_set(struct mb86a16_state *state, unsigned char loop)
+{
+	/* SLOCK0 = 0 */
+	if (mb86a16_write(state, 0x32, 0x02 | (loop << 2)) < 0) {
+		dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+		return -EREMOTEIO;
+	}
+
+	return 0;
+}
+
+static int iq_vt_set(struct mb86a16_state *state, unsigned char IQINV)
+{
+	/* Viterbi Rate, IQ Settings */
+	if (mb86a16_write(state, 0x06, 0xdf | (IQINV << 5)) < 0) {
+		dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+		return -EREMOTEIO;
+	}
+
+	return 0;
+}
+
+static int FEC_srst(struct mb86a16_state *state)
+{
+	if (mb86a16_write(state, MB86A16_RESET, 0x02) < 0) {
+		dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+		return -EREMOTEIO;
+	}
+
+	return 0;
+}
+
+static int S2T_set(struct mb86a16_state *state, unsigned char S2T)
+{
+	if (mb86a16_write(state, 0x34, 0x70 | S2T) < 0) {
+		dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+		return -EREMOTEIO;
+	}
+
+	return 0;
+}
+
+static int S45T_set(struct mb86a16_state *state, unsigned char S4T, unsigned char S5T)
+{
+	if (mb86a16_write(state, 0x35, 0x00 | (S5T << 4) | S4T) < 0) {
+		dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+		return -EREMOTEIO;
+	}
+
+	return 0;
+}
+
+
+static int mb86a16_set_fe(struct mb86a16_state *state)
+{
+	u8 agcval, cnmval;
+
+	int i, j;
+	int fOSC = 0;
+	int fOSC_start = 0;
+	int wait_t;
+	int fcp;
+	int swp_ofs;
+	int V[60];
+	u8 SIG1MIN;
+
+	unsigned char CREN, AFCEN, AFCEXEN;
+	unsigned char SIG1;
+	unsigned char TIMINT1, TIMINT2, TIMEXT;
+	unsigned char S0T, S1T;
+	unsigned char S2T;
+/*	unsigned char S2T, S3T; */
+	unsigned char S4T, S5T;
+	unsigned char AFCEX_L, AFCEX_H;
+	unsigned char R;
+	unsigned char VIRM;
+	unsigned char ETH, VIA;
+	unsigned char junk;
+
+	int loop;
+	int ftemp;
+	int v, vmax, vmin;
+	int vmax_his, vmin_his;
+	int swp_freq, prev_swp_freq[20];
+	int prev_freq_num;
+	int signal_dupl;
+	int afcex_freq;
+	int signal;
+	int afcerr;
+	int temp_freq, delta_freq;
+	int dagcm[4];
+	int smrt_d;
+/*	int freq_err; */
+	int n;
+	int ret = -1;
+	int sync;
+
+	dprintk(verbose, MB86A16_INFO, 1, "freq=%d Mhz, symbrt=%d Ksps", state->frequency, state->srate);
+
+	fcp = 3000;
+	swp_ofs = state->srate / 4;
+
+	for (i = 0; i < 60; i++)
+		V[i] = -1;
+
+	for (i = 0; i < 20; i++)
+		prev_swp_freq[i] = 0;
+
+	SIG1MIN = 25;
+
+	for (n = 0; ((n < 3) && (ret == -1)); n++) {
+		SEQ_set(state, 0);
+		iq_vt_set(state, 0);
+
+		CREN = 0;
+		AFCEN = 0;
+		AFCEXEN = 1;
+		TIMINT1 = 0;
+		TIMINT2 = 1;
+		TIMEXT = 2;
+		S1T = 0;
+		S0T = 0;
+
+		if (initial_set(state) < 0) {
+			dprintk(verbose, MB86A16_ERROR, 1, "initial set failed");
+			return -1;
+		}
+		if (DAGC_data_set(state, 3, 2) < 0) {
+			dprintk(verbose, MB86A16_ERROR, 1, "DAGC data set error");
+			return -1;
+		}
+		if (EN_set(state, CREN, AFCEN) < 0) {
+			dprintk(verbose, MB86A16_ERROR, 1, "EN set error");
+			return -1; /* (0, 0) */
+		}
+		if (AFCEXEN_set(state, AFCEXEN, state->srate) < 0) {
+			dprintk(verbose, MB86A16_ERROR, 1, "AFCEXEN set error");
+			return -1; /* (1, smrt) = (1, symbolrate) */
+		}
+		if (CNTM_set(state, TIMINT1, TIMINT2, TIMEXT) < 0) {
+			dprintk(verbose, MB86A16_ERROR, 1, "CNTM set error");
+			return -1; /* (0, 1, 2) */
+		}
+		if (S01T_set(state, S1T, S0T) < 0) {
+			dprintk(verbose, MB86A16_ERROR, 1, "S01T set error");
+			return -1; /* (0, 0) */
+		}
+		smrt_info_get(state, state->srate);
+		if (smrt_set(state, state->srate) < 0) {
+			dprintk(verbose, MB86A16_ERROR, 1, "smrt info get error");
+			return -1;
+		}
+
+		R = vco_dev_get(state, state->srate);
+		if (R == 1)
+			fOSC_start = state->frequency;
+
+		else if (R == 0) {
+			if (state->frequency % 2 == 0) {
+				fOSC_start = state->frequency;
+			} else {
+				fOSC_start = state->frequency + 1;
+				if (fOSC_start > 2150)
+					fOSC_start = state->frequency - 1;
+			}
+		}
+		loop = 1;
+		ftemp = fOSC_start * 1000;
+		vmax = 0 ;
+		while (loop == 1) {
+			ftemp = ftemp + swp_ofs;
+			vmax++;
+
+			/* Upper bound */
+			if (ftemp > 2150000) {
+				loop = 0;
+				vmax--;
+			} else {
+				if ((ftemp == 2150000) ||
+				    (ftemp - state->frequency * 1000 >= fcp + state->srate / 4))
+					loop = 0;
+			}
+		}
+
+		loop = 1;
+		ftemp = fOSC_start * 1000;
+		vmin = 0 ;
+		while (loop == 1) {
+			ftemp = ftemp - swp_ofs;
+			vmin--;
+
+			/* Lower bound */
+			if (ftemp < 950000) {
+				loop = 0;
+				vmin++;
+			} else {
+				if ((ftemp == 950000) ||
+				    (state->frequency * 1000 - ftemp >= fcp + state->srate / 4))
+					loop = 0;
+			}
+		}
+
+		wait_t = (8000 + state->srate / 2) / state->srate;
+		if (wait_t == 0)
+			wait_t = 1;
+
+		i = 0;
+		j = 0;
+		prev_freq_num = 0;
+		loop = 1;
+		signal = 0;
+		vmax_his = 0;
+		vmin_his = 0;
+		v = 0;
+
+		while (loop == 1) {
+			swp_info_get(state, fOSC_start, state->srate,
+				     v, R, swp_ofs, &fOSC,
+				     &afcex_freq, &AFCEX_L, &AFCEX_H);
+
+			udelay(100);
+			if (rf_val_set(state, fOSC, state->srate, R) < 0) {
+				dprintk(verbose, MB86A16_ERROR, 1, "rf val set error");
+				return -1;
+			}
+			udelay(100);
+			if (afcex_data_set(state, AFCEX_L, AFCEX_H) < 0) {
+				dprintk(verbose, MB86A16_ERROR, 1, "afcex data set error");
+				return -1;
+			}
+			if (srst(state) < 0) {
+				dprintk(verbose, MB86A16_ERROR, 1, "srst error");
+				return -1;
+			}
+			msleep_interruptible(wait_t);
+
+			if (mb86a16_read(state, 0x37, &SIG1) != 2) {
+				dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+				return -1;
+			}
+			V[30 + v] = SIG1 ;
+			swp_freq = swp_freq_calcuation(state, i, v, V, vmax, vmin,
+						      SIG1MIN, fOSC, afcex_freq,
+						      swp_ofs, &SIG1);	/* changed */
+
+			signal_dupl = 0;
+			for (j = 0; j < prev_freq_num; j++) {
+				if ((ABS(prev_swp_freq[j] - swp_freq)) < (swp_ofs * 3 / 2)) {
+					signal_dupl = 1;
+					dprintk(verbose, MB86A16_INFO, 1, "Probably Duplicate Signal, j = %d", j);
+				}
+			}
+			if ((signal_dupl == 0) && (swp_freq > 0) && (ABS(swp_freq - state->frequency * 1000) < fcp + state->srate / 6)) {
+				dprintk(verbose, MB86A16_DEBUG, 1, "------ Signal detect ------ [swp_freq=[%07d, srate=%05d]]", swp_freq, state->srate);
+				prev_swp_freq[prev_freq_num] = swp_freq;
+				prev_freq_num++;
+				swp_info_get2(state, state->srate, R, swp_freq,
+					      &afcex_freq, &fOSC,
+					      &AFCEX_L, &AFCEX_H);
+
+				if (rf_val_set(state, fOSC, state->srate, R) < 0) {
+					dprintk(verbose, MB86A16_ERROR, 1, "rf val set error");
+					return -1;
+				}
+				if (afcex_data_set(state, AFCEX_L, AFCEX_H) < 0) {
+					dprintk(verbose, MB86A16_ERROR, 1, "afcex data set error");
+					return -1;
+				}
+				signal = signal_det(state, state->srate, &SIG1);
+				if (signal == 1) {
+					dprintk(verbose, MB86A16_ERROR, 1, "***** Signal Found *****");
+					loop = 0;
+				} else {
+					dprintk(verbose, MB86A16_ERROR, 1, "!!!!! No signal !!!!!, try again...");
+					smrt_info_get(state, state->srate);
+					if (smrt_set(state, state->srate) < 0) {
+						dprintk(verbose, MB86A16_ERROR, 1, "smrt set error");
+						return -1;
+					}
+				}
+			}
+			if (v > vmax)
+				vmax_his = 1 ;
+			if (v < vmin)
+				vmin_his = 1 ;
+			i++;
+
+			if ((i % 2 == 1) && (vmax_his == 1))
+				i++;
+			if ((i % 2 == 0) && (vmin_his == 1))
+				i++;
+
+			if (i % 2 == 1)
+				v = (i + 1) / 2;
+			else
+				v = -i / 2;
+
+			if ((vmax_his == 1) && (vmin_his == 1))
+				loop = 0 ;
+		}
+
+		if (signal == 1) {
+			dprintk(verbose, MB86A16_INFO, 1, " Start Freq Error Check");
+			S1T = 7 ;
+			S0T = 1 ;
+			CREN = 0 ;
+			AFCEN = 1 ;
+			AFCEXEN = 0 ;
+
+			if (S01T_set(state, S1T, S0T) < 0) {
+				dprintk(verbose, MB86A16_ERROR, 1, "S01T set error");
+				return -1;
+			}
+			smrt_info_get(state, state->srate);
+			if (smrt_set(state, state->srate) < 0) {
+				dprintk(verbose, MB86A16_ERROR, 1, "smrt set error");
+				return -1;
+			}
+			if (EN_set(state, CREN, AFCEN) < 0) {
+				dprintk(verbose, MB86A16_ERROR, 1, "EN set error");
+				return -1;
+			}
+			if (AFCEXEN_set(state, AFCEXEN, state->srate) < 0) {
+				dprintk(verbose, MB86A16_ERROR, 1, "AFCEXEN set error");
+				return -1;
+			}
+			afcex_info_get(state, afcex_freq, &AFCEX_L, &AFCEX_H);
+			if (afcofs_data_set(state, AFCEX_L, AFCEX_H) < 0) {
+				dprintk(verbose, MB86A16_ERROR, 1, "AFCOFS data set error");
+				return -1;
+			}
+			if (srst(state) < 0) {
+				dprintk(verbose, MB86A16_ERROR, 1, "srst error");
+				return -1;
+			}
+			/* delay 4~200 */
+			wait_t = 200000 / state->master_clk + 200000 / state->srate;
+			msleep(wait_t);
+			afcerr = afcerr_chk(state);
+			if (afcerr == -1)
+				return -1;
+
+			swp_freq = fOSC * 1000 + afcerr ;
+			AFCEXEN = 1 ;
+			if (state->srate >= 1500)
+				smrt_d = state->srate / 3;
+			else
+				smrt_d = state->srate / 2;
+			smrt_info_get(state, smrt_d);
+			if (smrt_set(state, smrt_d) < 0) {
+				dprintk(verbose, MB86A16_ERROR, 1, "smrt set error");
+				return -1;
+			}
+			if (AFCEXEN_set(state, AFCEXEN, smrt_d) < 0) {
+				dprintk(verbose, MB86A16_ERROR, 1, "AFCEXEN set error");
+				return -1;
+			}
+			R = vco_dev_get(state, smrt_d);
+			if (DAGC_data_set(state, 2, 0) < 0) {
+				dprintk(verbose, MB86A16_ERROR, 1, "DAGC data set error");
+				return -1;
+			}
+			for (i = 0; i < 3; i++) {
+				temp_freq = swp_freq + (i - 1) * state->srate / 8;
+				swp_info_get2(state, smrt_d, R, temp_freq, &afcex_freq, &fOSC, &AFCEX_L, &AFCEX_H);
+				if (rf_val_set(state, fOSC, smrt_d, R) < 0) {
+					dprintk(verbose, MB86A16_ERROR, 1, "rf val set error");
+					return -1;
+				}
+				if (afcex_data_set(state, AFCEX_L, AFCEX_H) < 0) {
+					dprintk(verbose, MB86A16_ERROR, 1, "afcex data set error");
+					return -1;
+				}
+				wait_t = 200000 / state->master_clk + 40000 / smrt_d;
+				msleep(wait_t);
+				dagcm[i] = dagcm_val_get(state);
+			}
+			if ((dagcm[0] > dagcm[1]) &&
+			    (dagcm[0] > dagcm[2]) &&
+			    (dagcm[0] - dagcm[1] > 2 * (dagcm[2] - dagcm[1]))) {
+
+				temp_freq = swp_freq - 2 * state->srate / 8;
+				swp_info_get2(state, smrt_d, R, temp_freq, &afcex_freq, &fOSC, &AFCEX_L, &AFCEX_H);
+				if (rf_val_set(state, fOSC, smrt_d, R) < 0) {
+					dprintk(verbose, MB86A16_ERROR, 1, "rf val set error");
+					return -1;
+				}
+				if (afcex_data_set(state, AFCEX_L, AFCEX_H) < 0) {
+					dprintk(verbose, MB86A16_ERROR, 1, "afcex data set");
+					return -1;
+				}
+				wait_t = 200000 / state->master_clk + 40000 / smrt_d;
+				msleep(wait_t);
+				dagcm[3] = dagcm_val_get(state);
+				if (dagcm[3] > dagcm[1])
+					delta_freq = (dagcm[2] - dagcm[0] + dagcm[1] - dagcm[3]) * state->srate / 300;
+				else
+					delta_freq = 0;
+			} else if ((dagcm[2] > dagcm[1]) &&
+				   (dagcm[2] > dagcm[0]) &&
+				   (dagcm[2] - dagcm[1] > 2 * (dagcm[0] - dagcm[1]))) {
+
+				temp_freq = swp_freq + 2 * state->srate / 8;
+				swp_info_get2(state, smrt_d, R, temp_freq, &afcex_freq, &fOSC, &AFCEX_L, &AFCEX_H);
+				if (rf_val_set(state, fOSC, smrt_d, R) < 0) {
+					dprintk(verbose, MB86A16_ERROR, 1, "rf val set");
+					return -1;
+				}
+				if (afcex_data_set(state, AFCEX_L, AFCEX_H) < 0) {
+					dprintk(verbose, MB86A16_ERROR, 1, "afcex data set");
+					return -1;
+				}
+				wait_t = 200000 / state->master_clk + 40000 / smrt_d;
+				msleep(wait_t);
+				dagcm[3] = dagcm_val_get(state);
+				if (dagcm[3] > dagcm[1])
+					delta_freq = (dagcm[2] - dagcm[0] + dagcm[3] - dagcm[1]) * state->srate / 300;
+				else
+					delta_freq = 0 ;
+
+			} else {
+				delta_freq = 0 ;
+			}
+			dprintk(verbose, MB86A16_INFO, 1, "SWEEP Frequency = %d", swp_freq);
+			swp_freq += delta_freq;
+			dprintk(verbose, MB86A16_INFO, 1, "Adjusting .., DELTA Freq = %d, SWEEP Freq=%d", delta_freq, swp_freq);
+			if (ABS(state->frequency * 1000 - swp_freq) > 3800) {
+				dprintk(verbose, MB86A16_INFO, 1, "NO  --  SIGNAL !");
+			} else {
+
+				S1T = 0;
+				S0T = 3;
+				CREN = 1;
+				AFCEN = 0;
+				AFCEXEN = 1;
+
+				if (S01T_set(state, S1T, S0T) < 0) {
+					dprintk(verbose, MB86A16_ERROR, 1, "S01T set error");
+					return -1;
+				}
+				if (DAGC_data_set(state, 0, 0) < 0) {
+					dprintk(verbose, MB86A16_ERROR, 1, "DAGC data set error");
+					return -1;
+				}
+				R = vco_dev_get(state, state->srate);
+				smrt_info_get(state, state->srate);
+				if (smrt_set(state, state->srate) < 0) {
+					dprintk(verbose, MB86A16_ERROR, 1, "smrt set error");
+					return -1;
+				}
+				if (EN_set(state, CREN, AFCEN) < 0) {
+					dprintk(verbose, MB86A16_ERROR, 1, "EN set error");
+					return -1;
+				}
+				if (AFCEXEN_set(state, AFCEXEN, state->srate) < 0) {
+					dprintk(verbose, MB86A16_ERROR, 1, "AFCEXEN set error");
+					return -1;
+				}
+				swp_info_get2(state, state->srate, R, swp_freq, &afcex_freq, &fOSC, &AFCEX_L, &AFCEX_H);
+				if (rf_val_set(state, fOSC, state->srate, R) < 0) {
+					dprintk(verbose, MB86A16_ERROR, 1, "rf val set error");
+					return -1;
+				}
+				if (afcex_data_set(state, AFCEX_L, AFCEX_H) < 0) {
+					dprintk(verbose, MB86A16_ERROR, 1, "afcex data set error");
+					return -1;
+				}
+				if (srst(state) < 0) {
+					dprintk(verbose, MB86A16_ERROR, 1, "srst error");
+					return -1;
+				}
+				wait_t = 7 + (10000 + state->srate / 2) / state->srate;
+				if (wait_t == 0)
+					wait_t = 1;
+				msleep_interruptible(wait_t);
+				if (mb86a16_read(state, 0x37, &SIG1) != 2) {
+					dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+					return -EREMOTEIO;
+				}
+
+				if (SIG1 > 110) {
+					S2T = 4; S4T = 1; S5T = 6; ETH = 4; VIA = 6;
+					wait_t = 7 + (917504 + state->srate / 2) / state->srate;
+				} else if (SIG1 > 105) {
+					S2T = 4; S4T = 2; S5T = 8; ETH = 7; VIA = 2;
+					wait_t = 7 + (1048576 + state->srate / 2) / state->srate;
+				} else if (SIG1 > 85) {
+					S2T = 5; S4T = 2; S5T = 8; ETH = 7; VIA = 2;
+					wait_t = 7 + (1310720 + state->srate / 2) / state->srate;
+				} else if (SIG1 > 65) {
+					S2T = 6; S4T = 2; S5T = 8; ETH = 7; VIA = 2;
+					wait_t = 7 + (1572864 + state->srate / 2) / state->srate;
+				} else {
+					S2T = 7; S4T = 2; S5T = 8; ETH = 7; VIA = 2;
+					wait_t = 7 + (2097152 + state->srate / 2) / state->srate;
+				}
+				wait_t *= 2; /* FOS */
+				S2T_set(state, S2T);
+				S45T_set(state, S4T, S5T);
+				Vi_set(state, ETH, VIA);
+				srst(state);
+				msleep_interruptible(wait_t);
+				sync = sync_chk(state, &VIRM);
+				dprintk(verbose, MB86A16_INFO, 1, "-------- Viterbi=[%d] SYNC=[%d] ---------", VIRM, sync);
+				if (VIRM) {
+					if (VIRM == 4) {
+						/* 5/6 */
+						if (SIG1 > 110)
+							wait_t = (786432 + state->srate / 2) / state->srate;
+						else
+							wait_t = (1572864 + state->srate / 2) / state->srate;
+						if (state->srate < 5000)
+							/* FIXME ! , should be a long wait ! */
+							msleep_interruptible(wait_t);
+						else
+							msleep_interruptible(wait_t);
+
+						if (sync_chk(state, &junk) == 0) {
+							iq_vt_set(state, 1);
+							FEC_srst(state);
+						}
+					}
+					/* 1/2, 2/3, 3/4, 7/8 */
+					if (SIG1 > 110)
+						wait_t = (786432 + state->srate / 2) / state->srate;
+					else
+						wait_t = (1572864 + state->srate / 2) / state->srate;
+					msleep_interruptible(wait_t);
+					SEQ_set(state, 1);
+				} else {
+					dprintk(verbose, MB86A16_INFO, 1, "NO  -- SYNC");
+					SEQ_set(state, 1);
+					ret = -1;
+				}
+			}
+		} else {
+			dprintk(verbose, MB86A16_INFO, 1, "NO  -- SIGNAL");
+			ret = -1;
+		}
+
+		sync = sync_chk(state, &junk);
+		if (sync) {
+			dprintk(verbose, MB86A16_INFO, 1, "******* SYNC *******");
+			freqerr_chk(state, state->frequency, state->srate, 1);
+			ret = 0;
+			break;
+		}
+	}
+
+	mb86a16_read(state, 0x15, &agcval);
+	mb86a16_read(state, 0x26, &cnmval);
+	dprintk(verbose, MB86A16_INFO, 1, "AGC = %02x CNM = %02x", agcval, cnmval);
+
+	return ret;
+}
+
+static int mb86a16_send_diseqc_msg(struct dvb_frontend *fe,
+				   struct dvb_diseqc_master_cmd *cmd)
+{
+	struct mb86a16_state *state = fe->demodulator_priv;
+	int i;
+	u8 regs;
+
+	if (mb86a16_write(state, MB86A16_DCC1, MB86A16_DCC1_DISTA) < 0)
+		goto err;
+	if (mb86a16_write(state, MB86A16_DCCOUT, 0x00) < 0)
+		goto err;
+	if (mb86a16_write(state, MB86A16_TONEOUT2, 0x04) < 0)
+		goto err;
+
+	regs = 0x18;
+
+	if (cmd->msg_len > 5 || cmd->msg_len < 4)
+		return -EINVAL;
+
+	for (i = 0; i < cmd->msg_len; i++) {
+		if (mb86a16_write(state, regs, cmd->msg[i]) < 0)
+			goto err;
+
+		regs++;
+	}
+	i += 0x90;
+
+	msleep_interruptible(10);
+
+	if (mb86a16_write(state, MB86A16_DCC1, i) < 0)
+		goto err;
+	if (mb86a16_write(state, MB86A16_DCCOUT, MB86A16_DCCOUT_DISEN) < 0)
+		goto err;
+
+	return 0;
+
+err:
+	dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+	return -EREMOTEIO;
+}
+
+static int mb86a16_send_diseqc_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t burst)
+{
+	struct mb86a16_state *state = fe->demodulator_priv;
+
+	switch (burst) {
+	case SEC_MINI_A:
+		if (mb86a16_write(state, MB86A16_DCC1, MB86A16_DCC1_DISTA |
+						       MB86A16_DCC1_TBEN  |
+						       MB86A16_DCC1_TBO) < 0)
+			goto err;
+		if (mb86a16_write(state, MB86A16_DCCOUT, MB86A16_DCCOUT_DISEN) < 0)
+			goto err;
+		break;
+	case SEC_MINI_B:
+		if (mb86a16_write(state, MB86A16_DCC1, MB86A16_DCC1_DISTA |
+						       MB86A16_DCC1_TBEN) < 0)
+			goto err;
+		if (mb86a16_write(state, MB86A16_DCCOUT, MB86A16_DCCOUT_DISEN) < 0)
+			goto err;
+		break;
+	}
+
+	return 0;
+err:
+	dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+	return -EREMOTEIO;
+}
+
+static int mb86a16_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
+{
+	struct mb86a16_state *state = fe->demodulator_priv;
+
+	switch (tone) {
+	case SEC_TONE_ON:
+		if (mb86a16_write(state, MB86A16_TONEOUT2, 0x00) < 0)
+			goto err;
+		if (mb86a16_write(state, MB86A16_DCC1, MB86A16_DCC1_DISTA |
+						       MB86A16_DCC1_CTOE) < 0)
+
+			goto err;
+		if (mb86a16_write(state, MB86A16_DCCOUT, MB86A16_DCCOUT_DISEN) < 0)
+			goto err;
+		break;
+	case SEC_TONE_OFF:
+		if (mb86a16_write(state, MB86A16_TONEOUT2, 0x04) < 0)
+			goto err;
+		if (mb86a16_write(state, MB86A16_DCC1, MB86A16_DCC1_DISTA) < 0)
+			goto err;
+		if (mb86a16_write(state, MB86A16_DCCOUT, 0x00) < 0)
+			goto err;
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+
+err:
+	dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+	return -EREMOTEIO;
+}
+
+static enum dvbfe_search mb86a16_search(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct mb86a16_state *state = fe->demodulator_priv;
+
+	state->frequency = p->frequency / 1000;
+	state->srate = p->symbol_rate / 1000;
+
+	if (!mb86a16_set_fe(state)) {
+		dprintk(verbose, MB86A16_ERROR, 1, "Successfully acquired LOCK");
+		return DVBFE_ALGO_SEARCH_SUCCESS;
+	}
+
+	dprintk(verbose, MB86A16_ERROR, 1, "Lock acquisition failed!");
+	return DVBFE_ALGO_SEARCH_FAILED;
+}
+
+static void mb86a16_release(struct dvb_frontend *fe)
+{
+	struct mb86a16_state *state = fe->demodulator_priv;
+	kfree(state);
+}
+
+static int mb86a16_init(struct dvb_frontend *fe)
+{
+	return 0;
+}
+
+static int mb86a16_sleep(struct dvb_frontend *fe)
+{
+	return 0;
+}
+
+static int mb86a16_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+	u8 ber_mon, ber_tab, ber_lsb, ber_mid, ber_msb, ber_tim, ber_rst;
+	u32 timer;
+
+	struct mb86a16_state *state = fe->demodulator_priv;
+
+	*ber = 0;
+	if (mb86a16_read(state, MB86A16_BERMON, &ber_mon) != 2)
+		goto err;
+	if (mb86a16_read(state, MB86A16_BERTAB, &ber_tab) != 2)
+		goto err;
+	if (mb86a16_read(state, MB86A16_BERLSB, &ber_lsb) != 2)
+		goto err;
+	if (mb86a16_read(state, MB86A16_BERMID, &ber_mid) != 2)
+		goto err;
+	if (mb86a16_read(state, MB86A16_BERMSB, &ber_msb) != 2)
+		goto err;
+	/* BER monitor invalid when BER_EN = 0	*/
+	if (ber_mon & 0x04) {
+		/* coarse, fast calculation	*/
+		*ber = ber_tab & 0x1f;
+		dprintk(verbose, MB86A16_DEBUG, 1, "BER coarse=[0x%02x]", *ber);
+		if (ber_mon & 0x01) {
+			/*
+			 * BER_SEL = 1, The monitored BER is the estimated
+			 * value with a Reed-Solomon decoder error amount at
+			 * the deinterleaver output.
+			 * monitored BER is expressed as a 20 bit output in total
+			 */
+			ber_rst = ber_mon >> 3;
+			*ber = (((ber_msb << 8) | ber_mid) << 8) | ber_lsb;
+			if (ber_rst == 0)
+				timer =  12500000;
+			if (ber_rst == 1)
+				timer =  25000000;
+			if (ber_rst == 2)
+				timer =  50000000;
+			if (ber_rst == 3)
+				timer = 100000000;
+
+			*ber /= timer;
+			dprintk(verbose, MB86A16_DEBUG, 1, "BER fine=[0x%02x]", *ber);
+		} else {
+			/*
+			 * BER_SEL = 0, The monitored BER is the estimated
+			 * value with a Viterbi decoder error amount at the
+			 * QPSK demodulator output.
+			 * monitored BER is expressed as a 24 bit output in total
+			 */
+			ber_tim = ber_mon >> 1;
+			*ber = (((ber_msb << 8) | ber_mid) << 8) | ber_lsb;
+			if (ber_tim == 0)
+				timer = 16;
+			if (ber_tim == 1)
+				timer = 24;
+
+			*ber /= 2 ^ timer;
+			dprintk(verbose, MB86A16_DEBUG, 1, "BER fine=[0x%02x]", *ber);
+		}
+	}
+	return 0;
+err:
+	dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+	return -EREMOTEIO;
+}
+
+static int mb86a16_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
+{
+	u8 agcm = 0;
+	struct mb86a16_state *state = fe->demodulator_priv;
+
+	*strength = 0;
+	if (mb86a16_read(state, MB86A16_AGCM, &agcm) != 2) {
+		dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+		return -EREMOTEIO;
+	}
+
+	*strength = ((0xff - agcm) * 100) / 256;
+	dprintk(verbose, MB86A16_DEBUG, 1, "Signal strength=[%d %%]", (u8) *strength);
+	*strength = (0xffff - 0xff) + agcm;
+
+	return 0;
+}
+
+struct cnr {
+	u8 cn_reg;
+	u8 cn_val;
+};
+
+static const struct cnr cnr_tab[] = {
+	{  35,  2 },
+	{  40,  3 },
+	{  50,  4 },
+	{  60,  5 },
+	{  70,  6 },
+	{  80,  7 },
+	{  92,  8 },
+	{ 103,  9 },
+	{ 115, 10 },
+	{ 138, 12 },
+	{ 162, 15 },
+	{ 180, 18 },
+	{ 185, 19 },
+	{ 189, 20 },
+	{ 195, 22 },
+	{ 199, 24 },
+	{ 201, 25 },
+	{ 202, 26 },
+	{ 203, 27 },
+	{ 205, 28 },
+	{ 208, 30 }
+};
+
+static int mb86a16_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+	struct mb86a16_state *state = fe->demodulator_priv;
+	int i = 0;
+	int low_tide = 2, high_tide = 30, q_level;
+	u8  cn;
+
+	*snr = 0;
+	if (mb86a16_read(state, 0x26, &cn) != 2) {
+		dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+		return -EREMOTEIO;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(cnr_tab); i++) {
+		if (cn < cnr_tab[i].cn_reg) {
+			*snr = cnr_tab[i].cn_val;
+			break;
+		}
+	}
+	q_level = (*snr * 100) / (high_tide - low_tide);
+	dprintk(verbose, MB86A16_ERROR, 1, "SNR (Quality) = [%d dB], Level=%d %%", *snr, q_level);
+	*snr = (0xffff - 0xff) + *snr;
+
+	return 0;
+}
+
+static int mb86a16_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+	u8 dist;
+	struct mb86a16_state *state = fe->demodulator_priv;
+
+	if (mb86a16_read(state, MB86A16_DISTMON, &dist) != 2) {
+		dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+		return -EREMOTEIO;
+	}
+	*ucblocks = dist;
+
+	return 0;
+}
+
+static enum dvbfe_algo mb86a16_frontend_algo(struct dvb_frontend *fe)
+{
+	return DVBFE_ALGO_CUSTOM;
+}
+
+static struct dvb_frontend_ops mb86a16_ops = {
+	.delsys = { SYS_DVBS },
+	.info = {
+		.name			= "Fujitsu MB86A16 DVB-S",
+		.frequency_min		= 950000,
+		.frequency_max		= 2150000,
+		.frequency_stepsize	= 3000,
+		.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_FEC_AUTO
+	},
+	.release			= mb86a16_release,
+
+	.get_frontend_algo		= mb86a16_frontend_algo,
+	.search				= mb86a16_search,
+	.init				= mb86a16_init,
+	.sleep				= mb86a16_sleep,
+	.read_status			= mb86a16_read_status,
+
+	.read_ber			= mb86a16_read_ber,
+	.read_signal_strength		= mb86a16_read_signal_strength,
+	.read_snr			= mb86a16_read_snr,
+	.read_ucblocks			= mb86a16_read_ucblocks,
+
+	.diseqc_send_master_cmd		= mb86a16_send_diseqc_msg,
+	.diseqc_send_burst		= mb86a16_send_diseqc_burst,
+	.set_tone			= mb86a16_set_tone,
+};
+
+struct dvb_frontend *mb86a16_attach(const struct mb86a16_config *config,
+				    struct i2c_adapter *i2c_adap)
+{
+	u8 dev_id = 0;
+	struct mb86a16_state *state = NULL;
+
+	state = kmalloc(sizeof(struct mb86a16_state), GFP_KERNEL);
+	if (state == NULL)
+		goto error;
+
+	state->config = config;
+	state->i2c_adap = i2c_adap;
+
+	mb86a16_read(state, 0x7f, &dev_id);
+	if (dev_id != 0xfe)
+		goto error;
+
+	memcpy(&state->frontend.ops, &mb86a16_ops, sizeof(struct dvb_frontend_ops));
+	state->frontend.demodulator_priv = state;
+	state->frontend.ops.set_voltage = state->config->set_voltage;
+
+	return &state->frontend;
+error:
+	kfree(state);
+	return NULL;
+}
+EXPORT_SYMBOL(mb86a16_attach);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Manu Abraham");
diff --git a/drivers/media/dvb-frontends/mb86a16.h b/drivers/media/dvb-frontends/mb86a16.h
new file mode 100644
index 0000000..6ea8c37
--- /dev/null
+++ b/drivers/media/dvb-frontends/mb86a16.h
@@ -0,0 +1,52 @@
+/*
+	Fujitsu MB86A16 DVB-S/DSS DC Receiver driver
+
+	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __MB86A16_H
+#define __MB86A16_H
+
+#include <linux/dvb/frontend.h>
+#include "dvb_frontend.h"
+
+
+struct mb86a16_config {
+	u8 demod_address;
+
+	int (*set_voltage)(struct dvb_frontend *fe, fe_sec_voltage_t voltage);
+};
+
+
+
+#if defined(CONFIG_DVB_MB86A16) || (defined(CONFIG_DVB_MB86A16_MODULE) && defined(MODULE))
+
+extern struct dvb_frontend *mb86a16_attach(const struct mb86a16_config *config,
+					   struct i2c_adapter *i2c_adap);
+
+#else
+
+static inline struct dvb_frontend *mb86a16_attach(const struct mb86a16_config *config,
+					   struct i2c_adapter *i2c_adap)
+{
+	printk(KERN_WARNING "%s: Driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+
+#endif /* CONFIG_DVB_MB86A16 */
+
+#endif /* __MB86A16_H */
diff --git a/drivers/media/dvb-frontends/mb86a16_priv.h b/drivers/media/dvb-frontends/mb86a16_priv.h
new file mode 100644
index 0000000..360a35a
--- /dev/null
+++ b/drivers/media/dvb-frontends/mb86a16_priv.h
@@ -0,0 +1,151 @@
+/*
+	Fujitsu MB86A16 DVB-S/DSS DC Receiver driver
+
+	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __MB86A16_PRIV_H
+#define __MB86A16_PRIV_H
+
+#define MB86A16_TSOUT		0x00
+#define MB86A16_TSOUT_HIZSEL	(0x01 << 5)
+#define MB86A16_TSOUT_HIZCNTI	(0x01 << 4)
+#define MB86A16_TSOUT_MODE	(0x01 << 3)
+#define MB86A16_TSOUT_ORDER	(0x01 << 2)
+#define MB86A16_TSOUT_ERROR	(0x01 << 1)
+#define Mb86A16_TSOUT_EDGE	(0x01 << 0)
+
+#define MB86A16_FEC		0x01
+#define MB86A16_FEC_FSYNC	(0x01 << 5)
+#define MB86A16_FEC_PCKB8	(0x01 << 4)
+#define MB86A16_FEC_DVDS	(0x01 << 3)
+#define MB86A16_FEC_EREN	(0x01 << 2)
+#define Mb86A16_FEC_RSEN	(0x01 << 1)
+#define MB86A16_FEC_DIEN	(0x01 << 0)
+
+#define MB86A16_AGC		0x02
+#define MB86A16_AGC_AGMD	(0x01 << 6)
+#define MB86A16_AGC_AGCW	(0x0f << 2)
+#define MB86A16_AGC_AGCP	(0x01 << 1)
+#define MB86A16_AGC_AGCR	(0x01 << 0)
+
+#define MB86A16_SRATE1		0x03
+#define MB86A16_SRATE1_DECI	(0x07 << 2)
+#define MB86A16_SRATE1_CSEL	(0x01 << 1)
+#define MB86A16_SRATE1_RSEL	(0x01 << 0)
+
+#define MB86A16_SRATE2		0x04
+#define MB86A16_SRATE2_STOFSL	(0xff << 0)
+
+#define MB86A16_SRATE3		0x05
+#define MB86A16_SRATE2_STOFSH	(0xff << 0)
+
+#define MB86A16_VITERBI		0x06
+#define MB86A16_FRAMESYNC	0x07
+#define MB86A16_CRLFILTCOEF1	0x08
+#define MB86A16_CRLFILTCOEF2	0x09
+#define MB86A16_STRFILTCOEF1	0x0a
+#define MB86A16_STRFILTCOEF2	0x0b
+#define MB86A16_RESET		0x0c
+#define MB86A16_STATUS		0x0d
+#define MB86A16_AFCML		0x0e
+#define MB86A16_AFCMH		0x0f
+#define MB86A16_BERMON		0x10
+#define MB86A16_BERTAB		0x11
+#define MB86A16_BERLSB		0x12
+#define MB86A16_BERMID		0x13
+#define MB86A16_BERMSB		0x14
+#define MB86A16_AGCM		0x15
+
+#define MB86A16_DCC1		0x16
+#define MB86A16_DCC1_DISTA	(0x01 << 7)
+#define MB86A16_DCC1_PRTY	(0x01 << 6)
+#define MB86A16_DCC1_CTOE	(0x01 << 5)
+#define MB86A16_DCC1_TBEN	(0x01 << 4)
+#define MB86A16_DCC1_TBO	(0x01 << 3)
+#define MB86A16_DCC1_NUM	(0x07 << 0)
+
+#define MB86A16_DCC2		0x17
+#define MB86A16_DCC2_DCBST	(0x01 << 0)
+
+#define MB86A16_DCC3		0x18
+#define MB86A16_DCC3_CODE0	(0xff << 0)
+
+#define MB86A16_DCC4		0x19
+#define MB86A16_DCC4_CODE1	(0xff << 0)
+
+#define MB86A16_DCC5		0x1a
+#define MB86A16_DCC5_CODE2	(0xff << 0)
+
+#define MB86A16_DCC6		0x1b
+#define MB86A16_DCC6_CODE3	(0xff << 0)
+
+#define MB86A16_DCC7		0x1c
+#define MB86A16_DCC7_CODE4	(0xff << 0)
+
+#define MB86A16_DCC8		0x1d
+#define MB86A16_DCC8_CODE5	(0xff << 0)
+
+#define MB86A16_DCCOUT		0x1e
+#define MB86A16_DCCOUT_DISEN	(0x01 << 0)
+
+#define MB86A16_TONEOUT1	0x1f
+#define MB86A16_TONE_TDIVL	(0xff << 0)
+
+#define MB86A16_TONEOUT2	0x20
+#define MB86A16_TONE_TMD	(0x03 << 2)
+#define MB86A16_TONE_TDIVH	(0x03 << 0)
+
+#define MB86A16_FREQ1		0x21
+#define MB86A16_FREQ2		0x22
+#define MB86A16_FREQ3		0x23
+#define MB86A16_FREQ4		0x24
+#define MB86A16_FREQSET		0x25
+#define MB86A16_CNM		0x26
+#define MB86A16_PORT0		0x27
+#define MB86A16_PORT1		0x28
+#define MB86A16_DRCFILT		0x29
+#define MB86A16_AFC		0x2a
+#define MB86A16_AFCEXL		0x2b
+#define MB86A16_AFCEXH		0x2c
+#define MB86A16_DAGC		0x2d
+#define MB86A16_SEQMODE		0x32
+#define MB86A16_S0S1T		0x33
+#define MB86A16_S2S3T		0x34
+#define MB86A16_S4S5T		0x35
+#define MB86A16_CNTMR		0x36
+#define MB86A16_SIG1		0x37
+#define MB86A16_SIG2		0x38
+#define MB86A16_VIMAG		0x39
+#define MB86A16_VISET1		0x3a
+#define MB86A16_VISET2		0x3b
+#define MB86A16_VISET3		0x3c
+#define MB86A16_FAGCS1		0x3d
+#define MB86A16_FAGCS2		0x3e
+#define MB86A16_FAGCS3		0x3f
+#define MB86A16_FAGCS4		0x40
+#define MB86A16_FAGCS5		0x41
+#define MB86A16_FAGCS6		0x42
+#define MB86A16_CRM		0x43
+#define MB86A16_STRM		0x44
+#define MB86A16_DAGCML		0x45
+#define MB86A16_DAGCMH		0x46
+#define MB86A16_QPSKTST		0x49
+#define MB86A16_DISTMON		0x52
+#define MB86A16_VERSION		0x7f
+
+#endif /* __MB86A16_PRIV_H */
diff --git a/drivers/media/dvb-frontends/mb86a20s.c b/drivers/media/dvb-frontends/mb86a20s.c
new file mode 100644
index 0000000..fade566
--- /dev/null
+++ b/drivers/media/dvb-frontends/mb86a20s.c
@@ -0,0 +1,701 @@
+/*
+ *   Fujitu mb86a20s ISDB-T/ISDB-Tsb Module driver
+ *
+ *   Copyright (C) 2010 Mauro Carvalho Chehab <mchehab@redhat.com>
+ *   Copyright (C) 2009-2010 Douglas Landgraf <dougsland@redhat.com>
+ *
+ *   FIXME: Need to port to DVB v5.2 API
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License as
+ *   published by the Free Software Foundation version 2.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *   General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <asm/div64.h>
+
+#include "dvb_frontend.h"
+#include "mb86a20s.h"
+
+static int debug = 1;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)");
+
+#define rc(args...)  do {						\
+	printk(KERN_ERR  "mb86a20s: " args);				\
+} while (0)
+
+#define dprintk(args...)						\
+	do {								\
+		if (debug) {						\
+			printk(KERN_DEBUG "mb86a20s: %s: ", __func__);	\
+			printk(args);					\
+		}							\
+	} while (0)
+
+struct mb86a20s_state {
+	struct i2c_adapter *i2c;
+	const struct mb86a20s_config *config;
+
+	struct dvb_frontend frontend;
+
+	bool need_init;
+};
+
+struct regdata {
+	u8 reg;
+	u8 data;
+};
+
+/*
+ * Initialization sequence: Use whatevere default values that PV SBTVD
+ * does on its initialisation, obtained via USB snoop
+ */
+static struct regdata mb86a20s_init[] = {
+	{ 0x70, 0x0f },
+	{ 0x70, 0xff },
+	{ 0x08, 0x01 },
+	{ 0x09, 0x3e },
+	{ 0x50, 0xd1 }, { 0x51, 0x22 },
+	{ 0x39, 0x01 },
+	{ 0x71, 0x00 },
+	{ 0x28, 0x2a }, { 0x29, 0x00 }, { 0x2a, 0xff }, { 0x2b, 0x80 },
+	{ 0x28, 0x20 }, { 0x29, 0x33 }, { 0x2a, 0xdf }, { 0x2b, 0xa9 },
+	{ 0x28, 0x22 }, { 0x29, 0x00 }, { 0x2a, 0x1f }, { 0x2b, 0xf0 },
+	{ 0x3b, 0x21 },
+	{ 0x3c, 0x3a },
+	{ 0x01, 0x0d },
+	{ 0x04, 0x08 }, { 0x05, 0x05 },
+	{ 0x04, 0x0e }, { 0x05, 0x00 },
+	{ 0x04, 0x0f }, { 0x05, 0x14 },
+	{ 0x04, 0x0b }, { 0x05, 0x8c },
+	{ 0x04, 0x00 }, { 0x05, 0x00 },
+	{ 0x04, 0x01 }, { 0x05, 0x07 },
+	{ 0x04, 0x02 }, { 0x05, 0x0f },
+	{ 0x04, 0x03 }, { 0x05, 0xa0 },
+	{ 0x04, 0x09 }, { 0x05, 0x00 },
+	{ 0x04, 0x0a }, { 0x05, 0xff },
+	{ 0x04, 0x27 }, { 0x05, 0x64 },
+	{ 0x04, 0x28 }, { 0x05, 0x00 },
+	{ 0x04, 0x1e }, { 0x05, 0xff },
+	{ 0x04, 0x29 }, { 0x05, 0x0a },
+	{ 0x04, 0x32 }, { 0x05, 0x0a },
+	{ 0x04, 0x14 }, { 0x05, 0x02 },
+	{ 0x04, 0x04 }, { 0x05, 0x00 },
+	{ 0x04, 0x05 }, { 0x05, 0x22 },
+	{ 0x04, 0x06 }, { 0x05, 0x0e },
+	{ 0x04, 0x07 }, { 0x05, 0xd8 },
+	{ 0x04, 0x12 }, { 0x05, 0x00 },
+	{ 0x04, 0x13 }, { 0x05, 0xff },
+	{ 0x04, 0x15 }, { 0x05, 0x4e },
+	{ 0x04, 0x16 }, { 0x05, 0x20 },
+	{ 0x52, 0x01 },
+	{ 0x50, 0xa7 }, { 0x51, 0xff },
+	{ 0x50, 0xa8 }, { 0x51, 0xff },
+	{ 0x50, 0xa9 }, { 0x51, 0xff },
+	{ 0x50, 0xaa }, { 0x51, 0xff },
+	{ 0x50, 0xab }, { 0x51, 0xff },
+	{ 0x50, 0xac }, { 0x51, 0xff },
+	{ 0x50, 0xad }, { 0x51, 0xff },
+	{ 0x50, 0xae }, { 0x51, 0xff },
+	{ 0x50, 0xaf }, { 0x51, 0xff },
+	{ 0x5e, 0x07 },
+	{ 0x50, 0xdc }, { 0x51, 0x01 },
+	{ 0x50, 0xdd }, { 0x51, 0xf4 },
+	{ 0x50, 0xde }, { 0x51, 0x01 },
+	{ 0x50, 0xdf }, { 0x51, 0xf4 },
+	{ 0x50, 0xe0 }, { 0x51, 0x01 },
+	{ 0x50, 0xe1 }, { 0x51, 0xf4 },
+	{ 0x50, 0xb0 }, { 0x51, 0x07 },
+	{ 0x50, 0xb2 }, { 0x51, 0xff },
+	{ 0x50, 0xb3 }, { 0x51, 0xff },
+	{ 0x50, 0xb4 }, { 0x51, 0xff },
+	{ 0x50, 0xb5 }, { 0x51, 0xff },
+	{ 0x50, 0xb6 }, { 0x51, 0xff },
+	{ 0x50, 0xb7 }, { 0x51, 0xff },
+	{ 0x50, 0x50 }, { 0x51, 0x02 },
+	{ 0x50, 0x51 }, { 0x51, 0x04 },
+	{ 0x45, 0x04 },
+	{ 0x48, 0x04 },
+	{ 0x50, 0xd5 }, { 0x51, 0x01 },		/* Serial */
+	{ 0x50, 0xd6 }, { 0x51, 0x1f },
+	{ 0x50, 0xd2 }, { 0x51, 0x03 },
+	{ 0x50, 0xd7 }, { 0x51, 0x3f },
+	{ 0x28, 0x74 }, { 0x29, 0x00 }, { 0x28, 0x74 }, { 0x29, 0x40 },
+	{ 0x28, 0x46 }, { 0x29, 0x2c }, { 0x28, 0x46 }, { 0x29, 0x0c },
+	{ 0x04, 0x40 }, { 0x05, 0x01 },
+	{ 0x28, 0x00 }, { 0x29, 0x10 },
+	{ 0x28, 0x05 }, { 0x29, 0x02 },
+	{ 0x1c, 0x01 },
+	{ 0x28, 0x06 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x03 },
+	{ 0x28, 0x07 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x0d },
+	{ 0x28, 0x08 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x02 },
+	{ 0x28, 0x09 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x01 },
+	{ 0x28, 0x0a }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x21 },
+	{ 0x28, 0x0b }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x29 },
+	{ 0x28, 0x0c }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x16 },
+	{ 0x28, 0x0d }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x31 },
+	{ 0x28, 0x0e }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x0e },
+	{ 0x28, 0x0f }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x4e },
+	{ 0x28, 0x10 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x46 },
+	{ 0x28, 0x11 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x0f },
+	{ 0x28, 0x12 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x56 },
+	{ 0x28, 0x13 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x35 },
+	{ 0x28, 0x14 }, { 0x29, 0x00 }, { 0x2a, 0x01 }, { 0x2b, 0xbe },
+	{ 0x28, 0x15 }, { 0x29, 0x00 }, { 0x2a, 0x01 }, { 0x2b, 0x84 },
+	{ 0x28, 0x16 }, { 0x29, 0x00 }, { 0x2a, 0x03 }, { 0x2b, 0xee },
+	{ 0x28, 0x17 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x98 },
+	{ 0x28, 0x18 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x9f },
+	{ 0x28, 0x19 }, { 0x29, 0x00 }, { 0x2a, 0x07 }, { 0x2b, 0xb2 },
+	{ 0x28, 0x1a }, { 0x29, 0x00 }, { 0x2a, 0x06 }, { 0x2b, 0xc2 },
+	{ 0x28, 0x1b }, { 0x29, 0x00 }, { 0x2a, 0x07 }, { 0x2b, 0x4a },
+	{ 0x28, 0x1c }, { 0x29, 0x00 }, { 0x2a, 0x01 }, { 0x2b, 0xbc },
+	{ 0x28, 0x1d }, { 0x29, 0x00 }, { 0x2a, 0x04 }, { 0x2b, 0xba },
+	{ 0x28, 0x1e }, { 0x29, 0x00 }, { 0x2a, 0x06 }, { 0x2b, 0x14 },
+	{ 0x50, 0x1e }, { 0x51, 0x5d },
+	{ 0x50, 0x22 }, { 0x51, 0x00 },
+	{ 0x50, 0x23 }, { 0x51, 0xc8 },
+	{ 0x50, 0x24 }, { 0x51, 0x00 },
+	{ 0x50, 0x25 }, { 0x51, 0xf0 },
+	{ 0x50, 0x26 }, { 0x51, 0x00 },
+	{ 0x50, 0x27 }, { 0x51, 0xc3 },
+	{ 0x50, 0x39 }, { 0x51, 0x02 },
+	{ 0x28, 0x6a }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x00 },
+	{ 0xd0, 0x00 },
+};
+
+static struct regdata mb86a20s_reset_reception[] = {
+	{ 0x70, 0xf0 },
+	{ 0x70, 0xff },
+	{ 0x08, 0x01 },
+	{ 0x08, 0x00 },
+};
+
+static int mb86a20s_i2c_writereg(struct mb86a20s_state *state,
+			     u8 i2c_addr, int reg, int data)
+{
+	u8 buf[] = { reg, data };
+	struct i2c_msg msg = {
+		.addr = i2c_addr, .flags = 0, .buf = buf, .len = 2
+	};
+	int rc;
+
+	rc = i2c_transfer(state->i2c, &msg, 1);
+	if (rc != 1) {
+		printk("%s: writereg error (rc == %i, reg == 0x%02x,"
+			 " data == 0x%02x)\n", __func__, rc, reg, data);
+		return rc;
+	}
+
+	return 0;
+}
+
+static int mb86a20s_i2c_writeregdata(struct mb86a20s_state *state,
+				     u8 i2c_addr, struct regdata *rd, int size)
+{
+	int i, rc;
+
+	for (i = 0; i < size; i++) {
+		rc = mb86a20s_i2c_writereg(state, i2c_addr, rd[i].reg,
+					   rd[i].data);
+		if (rc < 0)
+			return rc;
+	}
+	return 0;
+}
+
+static int mb86a20s_i2c_readreg(struct mb86a20s_state *state,
+				u8 i2c_addr, u8 reg)
+{
+	u8 val;
+	int rc;
+	struct i2c_msg msg[] = {
+		{ .addr = i2c_addr, .flags = 0, .buf = &reg, .len = 1 },
+		{ .addr = i2c_addr, .flags = I2C_M_RD, .buf = &val, .len = 1 }
+	};
+
+	rc = i2c_transfer(state->i2c, msg, 2);
+
+	if (rc != 2) {
+		rc("%s: reg=0x%x (error=%d)\n", __func__, reg, rc);
+		return rc;
+	}
+
+	return val;
+}
+
+#define mb86a20s_readreg(state, reg) \
+	mb86a20s_i2c_readreg(state, state->config->demod_address, reg)
+#define mb86a20s_writereg(state, reg, val) \
+	mb86a20s_i2c_writereg(state, state->config->demod_address, reg, val)
+#define mb86a20s_writeregdata(state, regdata) \
+	mb86a20s_i2c_writeregdata(state, state->config->demod_address, \
+	regdata, ARRAY_SIZE(regdata))
+
+static int mb86a20s_initfe(struct dvb_frontend *fe)
+{
+	struct mb86a20s_state *state = fe->demodulator_priv;
+	int rc;
+	u8  regD5 = 1;
+
+	dprintk("\n");
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 0);
+
+	/* Initialize the frontend */
+	rc = mb86a20s_writeregdata(state, mb86a20s_init);
+	if (rc < 0)
+		goto err;
+
+	if (!state->config->is_serial) {
+		regD5 &= ~1;
+
+		rc = mb86a20s_writereg(state, 0x50, 0xd5);
+		if (rc < 0)
+			goto err;
+		rc = mb86a20s_writereg(state, 0x51, regD5);
+		if (rc < 0)
+			goto err;
+	}
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+
+err:
+	if (rc < 0) {
+		state->need_init = true;
+		printk(KERN_INFO "mb86a20s: Init failed. Will try again later\n");
+	} else {
+		state->need_init = false;
+		dprintk("Initialization succeeded.\n");
+	}
+	return rc;
+}
+
+static int mb86a20s_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
+{
+	struct mb86a20s_state *state = fe->demodulator_priv;
+	unsigned rf_max, rf_min, rf;
+	u8	 val;
+
+	dprintk("\n");
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 0);
+
+	/* Does a binary search to get RF strength */
+	rf_max = 0xfff;
+	rf_min = 0;
+	do {
+		rf = (rf_max + rf_min) / 2;
+		mb86a20s_writereg(state, 0x04, 0x1f);
+		mb86a20s_writereg(state, 0x05, rf >> 8);
+		mb86a20s_writereg(state, 0x04, 0x20);
+		mb86a20s_writereg(state, 0x04, rf);
+
+		val = mb86a20s_readreg(state, 0x02);
+		if (val & 0x08)
+			rf_min = (rf_max + rf_min) / 2;
+		else
+			rf_max = (rf_max + rf_min) / 2;
+		if (rf_max - rf_min < 4) {
+			*strength = (((rf_max + rf_min) / 2) * 65535) / 4095;
+			break;
+		}
+	} while (1);
+
+	dprintk("signal strength = %d\n", *strength);
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+
+	return 0;
+}
+
+static int mb86a20s_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+	struct mb86a20s_state *state = fe->demodulator_priv;
+	u8 val;
+
+	dprintk("\n");
+	*status = 0;
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 0);
+	val = mb86a20s_readreg(state, 0x0a) & 0xf;
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+
+	if (val >= 2)
+		*status |= FE_HAS_SIGNAL;
+
+	if (val >= 4)
+		*status |= FE_HAS_CARRIER;
+
+	if (val >= 5)
+		*status |= FE_HAS_VITERBI;
+
+	if (val >= 7)
+		*status |= FE_HAS_SYNC;
+
+	if (val >= 8)				/* Maybe 9? */
+		*status |= FE_HAS_LOCK;
+
+	dprintk("val = %d, status = 0x%02x\n", val, *status);
+
+	return 0;
+}
+
+static int mb86a20s_set_frontend(struct dvb_frontend *fe)
+{
+	struct mb86a20s_state *state = fe->demodulator_priv;
+	int rc;
+#if 0
+	/*
+	 * FIXME: Properly implement the set frontend properties
+	 */
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+#endif
+
+	dprintk("\n");
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+	dprintk("Calling tuner set parameters\n");
+	fe->ops.tuner_ops.set_params(fe);
+
+	/*
+	 * Make it more reliable: if, for some reason, the initial
+	 * device initialization doesn't happen, initialize it when
+	 * a SBTVD parameters are adjusted.
+	 *
+	 * Unfortunately, due to a hard to track bug at tda829x/tda18271,
+	 * the agc callback logic is not called during DVB attach time,
+	 * causing mb86a20s to not be initialized with Kworld SBTVD.
+	 * So, this hack is needed, in order to make Kworld SBTVD to work.
+	 */
+	if (state->need_init)
+		mb86a20s_initfe(fe);
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 0);
+	rc = mb86a20s_writeregdata(state, mb86a20s_reset_reception);
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+
+	return rc;
+}
+
+static int mb86a20s_get_modulation(struct mb86a20s_state *state,
+				   unsigned layer)
+{
+	int rc;
+	static unsigned char reg[] = {
+		[0] = 0x86,	/* Layer A */
+		[1] = 0x8a,	/* Layer B */
+		[2] = 0x8e,	/* Layer C */
+	};
+
+	if (layer >= ARRAY_SIZE(reg))
+		return -EINVAL;
+	rc = mb86a20s_writereg(state, 0x6d, reg[layer]);
+	if (rc < 0)
+		return rc;
+	rc = mb86a20s_readreg(state, 0x6e);
+	if (rc < 0)
+		return rc;
+	switch ((rc & 0x70) >> 4) {
+	case 0:
+		return DQPSK;
+	case 1:
+		return QPSK;
+	case 2:
+		return QAM_16;
+	case 3:
+		return QAM_64;
+	default:
+		return QAM_AUTO;
+	}
+}
+
+static int mb86a20s_get_fec(struct mb86a20s_state *state,
+			    unsigned layer)
+{
+	int rc;
+
+	static unsigned char reg[] = {
+		[0] = 0x87,	/* Layer A */
+		[1] = 0x8b,	/* Layer B */
+		[2] = 0x8f,	/* Layer C */
+	};
+
+	if (layer >= ARRAY_SIZE(reg))
+		return -EINVAL;
+	rc = mb86a20s_writereg(state, 0x6d, reg[layer]);
+	if (rc < 0)
+		return rc;
+	rc = mb86a20s_readreg(state, 0x6e);
+	if (rc < 0)
+		return rc;
+	switch (rc) {
+	case 0:
+		return FEC_1_2;
+	case 1:
+		return FEC_2_3;
+	case 2:
+		return FEC_3_4;
+	case 3:
+		return FEC_5_6;
+	case 4:
+		return FEC_7_8;
+	default:
+		return FEC_AUTO;
+	}
+}
+
+static int mb86a20s_get_interleaving(struct mb86a20s_state *state,
+				     unsigned layer)
+{
+	int rc;
+
+	static unsigned char reg[] = {
+		[0] = 0x88,	/* Layer A */
+		[1] = 0x8c,	/* Layer B */
+		[2] = 0x90,	/* Layer C */
+	};
+
+	if (layer >= ARRAY_SIZE(reg))
+		return -EINVAL;
+	rc = mb86a20s_writereg(state, 0x6d, reg[layer]);
+	if (rc < 0)
+		return rc;
+	rc = mb86a20s_readreg(state, 0x6e);
+	if (rc < 0)
+		return rc;
+	if (rc > 3)
+		return -EINVAL;	/* Not used */
+	return rc;
+}
+
+static int mb86a20s_get_segment_count(struct mb86a20s_state *state,
+				      unsigned layer)
+{
+	int rc, count;
+
+	static unsigned char reg[] = {
+		[0] = 0x89,	/* Layer A */
+		[1] = 0x8d,	/* Layer B */
+		[2] = 0x91,	/* Layer C */
+	};
+
+	if (layer >= ARRAY_SIZE(reg))
+		return -EINVAL;
+	rc = mb86a20s_writereg(state, 0x6d, reg[layer]);
+	if (rc < 0)
+		return rc;
+	rc = mb86a20s_readreg(state, 0x6e);
+	if (rc < 0)
+		return rc;
+	count = (rc >> 4) & 0x0f;
+
+	return count;
+}
+
+static int mb86a20s_get_frontend(struct dvb_frontend *fe)
+{
+	struct mb86a20s_state *state = fe->demodulator_priv;
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	int i, rc;
+
+	/* Fixed parameters */
+	p->delivery_system = SYS_ISDBT;
+	p->bandwidth_hz = 6000000;
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 0);
+
+	/* Check for partial reception */
+	rc = mb86a20s_writereg(state, 0x6d, 0x85);
+	if (rc >= 0)
+		rc = mb86a20s_readreg(state, 0x6e);
+	if (rc >= 0)
+		p->isdbt_partial_reception = (rc & 0x10) ? 1 : 0;
+
+	/* Get per-layer data */
+	p->isdbt_layer_enabled = 0;
+	for (i = 0; i < 3; i++) {
+		rc = mb86a20s_get_segment_count(state, i);
+			if (rc >= 0 && rc < 14)
+				p->layer[i].segment_count = rc;
+		if (rc == 0x0f)
+			continue;
+		p->isdbt_layer_enabled |= 1 << i;
+		rc = mb86a20s_get_modulation(state, i);
+			if (rc >= 0)
+				p->layer[i].modulation = rc;
+		rc = mb86a20s_get_fec(state, i);
+			if (rc >= 0)
+				p->layer[i].fec = rc;
+		rc = mb86a20s_get_interleaving(state, i);
+			if (rc >= 0)
+				p->layer[i].interleaving = rc;
+	}
+
+	p->isdbt_sb_mode = 0;
+	rc = mb86a20s_writereg(state, 0x6d, 0x84);
+	if ((rc >= 0) && ((rc & 0x60) == 0x20)) {
+		p->isdbt_sb_mode = 1;
+		/* At least, one segment should exist */
+		if (!p->isdbt_sb_segment_count)
+			p->isdbt_sb_segment_count = 1;
+	} else
+		p->isdbt_sb_segment_count = 0;
+
+	/* Get transmission mode and guard interval */
+	p->transmission_mode = TRANSMISSION_MODE_AUTO;
+	p->guard_interval = GUARD_INTERVAL_AUTO;
+	rc = mb86a20s_readreg(state, 0x07);
+	if (rc >= 0) {
+		if ((rc & 0x60) == 0x20) {
+			switch (rc & 0x0c >> 2) {
+			case 0:
+				p->transmission_mode = TRANSMISSION_MODE_2K;
+				break;
+			case 1:
+				p->transmission_mode = TRANSMISSION_MODE_4K;
+				break;
+			case 2:
+				p->transmission_mode = TRANSMISSION_MODE_8K;
+				break;
+			}
+		}
+		if (!(rc & 0x10)) {
+			switch (rc & 0x3) {
+			case 0:
+				p->guard_interval = GUARD_INTERVAL_1_4;
+				break;
+			case 1:
+				p->guard_interval = GUARD_INTERVAL_1_8;
+				break;
+			case 2:
+				p->guard_interval = GUARD_INTERVAL_1_16;
+				break;
+			}
+		}
+	}
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+
+	return 0;
+}
+
+static int mb86a20s_tune(struct dvb_frontend *fe,
+			bool re_tune,
+			unsigned int mode_flags,
+			unsigned int *delay,
+			fe_status_t *status)
+{
+	int rc = 0;
+
+	dprintk("\n");
+
+	if (re_tune)
+		rc = mb86a20s_set_frontend(fe);
+
+	if (!(mode_flags & FE_TUNE_MODE_ONESHOT))
+		mb86a20s_read_status(fe, status);
+
+	return rc;
+}
+
+static void mb86a20s_release(struct dvb_frontend *fe)
+{
+	struct mb86a20s_state *state = fe->demodulator_priv;
+
+	dprintk("\n");
+
+	kfree(state);
+}
+
+static struct dvb_frontend_ops mb86a20s_ops;
+
+struct dvb_frontend *mb86a20s_attach(const struct mb86a20s_config *config,
+				    struct i2c_adapter *i2c)
+{
+	u8	rev;
+
+	/* allocate memory for the internal state */
+	struct mb86a20s_state *state =
+		kzalloc(sizeof(struct mb86a20s_state), GFP_KERNEL);
+
+	dprintk("\n");
+	if (state == NULL) {
+		rc("Unable to kzalloc\n");
+		goto error;
+	}
+
+	/* setup the state */
+	state->config = config;
+	state->i2c = i2c;
+
+	/* create dvb_frontend */
+	memcpy(&state->frontend.ops, &mb86a20s_ops,
+		sizeof(struct dvb_frontend_ops));
+	state->frontend.demodulator_priv = state;
+
+	/* Check if it is a mb86a20s frontend */
+	rev = mb86a20s_readreg(state, 0);
+
+	if (rev == 0x13) {
+		printk(KERN_INFO "Detected a Fujitsu mb86a20s frontend\n");
+	} else {
+		printk(KERN_ERR "Frontend revision %d is unknown - aborting.\n",
+		       rev);
+		goto error;
+	}
+
+	return &state->frontend;
+
+error:
+	kfree(state);
+	return NULL;
+}
+EXPORT_SYMBOL(mb86a20s_attach);
+
+static struct dvb_frontend_ops mb86a20s_ops = {
+	.delsys = { SYS_ISDBT },
+	/* Use dib8000 values per default */
+	.info = {
+		.name = "Fujitsu mb86A20s",
+		.caps = FE_CAN_INVERSION_AUTO | FE_CAN_RECOVER |
+			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_FEC_AUTO |
+			FE_CAN_QPSK     | FE_CAN_QAM_16  | FE_CAN_QAM_64 |
+			FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_QAM_AUTO |
+			FE_CAN_GUARD_INTERVAL_AUTO    | FE_CAN_HIERARCHY_AUTO,
+		/* Actually, those values depend on the used tuner */
+		.frequency_min = 45000000,
+		.frequency_max = 864000000,
+		.frequency_stepsize = 62500,
+	},
+
+	.release = mb86a20s_release,
+
+	.init = mb86a20s_initfe,
+	.set_frontend = mb86a20s_set_frontend,
+	.get_frontend = mb86a20s_get_frontend,
+	.read_status = mb86a20s_read_status,
+	.read_signal_strength = mb86a20s_read_signal_strength,
+	.tune = mb86a20s_tune,
+};
+
+MODULE_DESCRIPTION("DVB Frontend module for Fujitsu mb86A20s hardware");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb-frontends/mb86a20s.h b/drivers/media/dvb-frontends/mb86a20s.h
new file mode 100644
index 0000000..bf22e77
--- /dev/null
+++ b/drivers/media/dvb-frontends/mb86a20s.h
@@ -0,0 +1,52 @@
+/*
+ *   Fujitsu mb86a20s driver
+ *
+ *   Copyright (C) 2010 Mauro Carvalho Chehab <mchehab@redhat.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 version 2.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *   General Public License for more details.
+ */
+
+#ifndef MB86A20S_H
+#define MB86A20S_H
+
+#include <linux/dvb/frontend.h>
+
+/**
+ * struct mb86a20s_config - Define the per-device attributes of the frontend
+ *
+ * @demod_address:	the demodulator's i2c address
+ */
+
+struct mb86a20s_config {
+	u8 demod_address;
+	bool is_serial;
+};
+
+#if defined(CONFIG_DVB_MB86A20S) || (defined(CONFIG_DVB_MB86A20S_MODULE) \
+	&& defined(MODULE))
+extern struct dvb_frontend *mb86a20s_attach(const struct mb86a20s_config *config,
+					   struct i2c_adapter *i2c);
+extern struct i2c_adapter *mb86a20s_get_tuner_i2c_adapter(struct dvb_frontend *);
+#else
+static inline struct dvb_frontend *mb86a20s_attach(
+	const struct mb86a20s_config *config, struct i2c_adapter *i2c)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+static struct i2c_adapter *
+	mb86a20s_get_tuner_i2c_adapter(struct dvb_frontend *fe)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif
+
+#endif /* MB86A20S */
diff --git a/drivers/media/dvb-frontends/mt312.c b/drivers/media/dvb-frontends/mt312.c
new file mode 100644
index 0000000..e20bf13
--- /dev/null
+++ b/drivers/media/dvb-frontends/mt312.c
@@ -0,0 +1,839 @@
+/*
+    Driver for Zarlink VP310/MT312/ZL10313 Satellite Channel Decoder
+
+    Copyright (C) 2003 Andreas Oberritter <obi@linuxtv.org>
+    Copyright (C) 2008 Matthias Schwarzott <zzam@gentoo.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.
+
+    References:
+    http://products.zarlink.com/product_profiles/MT312.htm
+    http://products.zarlink.com/product_profiles/SL1935.htm
+*/
+
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+
+#include "dvb_frontend.h"
+#include "mt312_priv.h"
+#include "mt312.h"
+
+
+struct mt312_state {
+	struct i2c_adapter *i2c;
+	/* configuration settings */
+	const struct mt312_config *config;
+	struct dvb_frontend frontend;
+
+	u8 id;
+	unsigned long xtal;
+	u8 freq_mult;
+};
+
+static int debug;
+#define dprintk(args...) \
+	do { \
+		if (debug) \
+			printk(KERN_DEBUG "mt312: " args); \
+	} while (0)
+
+#define MT312_PLL_CLK		10000000UL	/* 10 MHz */
+#define MT312_PLL_CLK_10_111	10111000UL	/* 10.111 MHz */
+
+static int mt312_read(struct mt312_state *state, const enum mt312_reg_addr reg,
+		      u8 *buf, const size_t count)
+{
+	int ret;
+	struct i2c_msg msg[2];
+	u8 regbuf[1] = { reg };
+
+	msg[0].addr = state->config->demod_address;
+	msg[0].flags = 0;
+	msg[0].buf = regbuf;
+	msg[0].len = 1;
+	msg[1].addr = state->config->demod_address;
+	msg[1].flags = I2C_M_RD;
+	msg[1].buf = buf;
+	msg[1].len = count;
+
+	ret = i2c_transfer(state->i2c, msg, 2);
+
+	if (ret != 2) {
+		printk(KERN_DEBUG "%s: ret == %d\n", __func__, ret);
+		return -EREMOTEIO;
+	}
+
+	if (debug) {
+		int i;
+		dprintk("R(%d):", reg & 0x7f);
+		for (i = 0; i < count; i++)
+			printk(KERN_CONT " %02x", buf[i]);
+		printk("\n");
+	}
+
+	return 0;
+}
+
+static int mt312_write(struct mt312_state *state, const enum mt312_reg_addr reg,
+		       const u8 *src, const size_t count)
+{
+	int ret;
+	u8 buf[count + 1];
+	struct i2c_msg msg;
+
+	if (debug) {
+		int i;
+		dprintk("W(%d):", reg & 0x7f);
+		for (i = 0; i < count; i++)
+			printk(KERN_CONT " %02x", src[i]);
+		printk("\n");
+	}
+
+	buf[0] = reg;
+	memcpy(&buf[1], src, count);
+
+	msg.addr = state->config->demod_address;
+	msg.flags = 0;
+	msg.buf = buf;
+	msg.len = count + 1;
+
+	ret = i2c_transfer(state->i2c, &msg, 1);
+
+	if (ret != 1) {
+		dprintk("%s: ret == %d\n", __func__, ret);
+		return -EREMOTEIO;
+	}
+
+	return 0;
+}
+
+static inline int mt312_readreg(struct mt312_state *state,
+				const enum mt312_reg_addr reg, u8 *val)
+{
+	return mt312_read(state, reg, val, 1);
+}
+
+static inline int mt312_writereg(struct mt312_state *state,
+				 const enum mt312_reg_addr reg, const u8 val)
+{
+	return mt312_write(state, reg, &val, 1);
+}
+
+static inline u32 mt312_div(u32 a, u32 b)
+{
+	return (a + (b / 2)) / b;
+}
+
+static int mt312_reset(struct mt312_state *state, const u8 full)
+{
+	return mt312_writereg(state, RESET, full ? 0x80 : 0x40);
+}
+
+static int mt312_get_inversion(struct mt312_state *state,
+			       fe_spectral_inversion_t *i)
+{
+	int ret;
+	u8 vit_mode;
+
+	ret = mt312_readreg(state, VIT_MODE, &vit_mode);
+	if (ret < 0)
+		return ret;
+
+	if (vit_mode & 0x80)	/* auto inversion was used */
+		*i = (vit_mode & 0x40) ? INVERSION_ON : INVERSION_OFF;
+
+	return 0;
+}
+
+static int mt312_get_symbol_rate(struct mt312_state *state, u32 *sr)
+{
+	int ret;
+	u8 sym_rate_h;
+	u8 dec_ratio;
+	u16 sym_rat_op;
+	u16 monitor;
+	u8 buf[2];
+
+	ret = mt312_readreg(state, SYM_RATE_H, &sym_rate_h);
+	if (ret < 0)
+		return ret;
+
+	if (sym_rate_h & 0x80) {
+		/* symbol rate search was used */
+		ret = mt312_writereg(state, MON_CTRL, 0x03);
+		if (ret < 0)
+			return ret;
+
+		ret = mt312_read(state, MONITOR_H, buf, sizeof(buf));
+		if (ret < 0)
+			return ret;
+
+		monitor = (buf[0] << 8) | buf[1];
+
+		dprintk("sr(auto) = %u\n",
+		       mt312_div(monitor * 15625, 4));
+	} else {
+		ret = mt312_writereg(state, MON_CTRL, 0x05);
+		if (ret < 0)
+			return ret;
+
+		ret = mt312_read(state, MONITOR_H, buf, sizeof(buf));
+		if (ret < 0)
+			return ret;
+
+		dec_ratio = ((buf[0] >> 5) & 0x07) * 32;
+
+		ret = mt312_read(state, SYM_RAT_OP_H, buf, sizeof(buf));
+		if (ret < 0)
+			return ret;
+
+		sym_rat_op = (buf[0] << 8) | buf[1];
+
+		dprintk("sym_rat_op=%d dec_ratio=%d\n",
+		       sym_rat_op, dec_ratio);
+		dprintk("*sr(manual) = %lu\n",
+		       (((state->xtal * 8192) / (sym_rat_op + 8192)) *
+			2) - dec_ratio);
+	}
+
+	return 0;
+}
+
+static int mt312_get_code_rate(struct mt312_state *state, fe_code_rate_t *cr)
+{
+	const fe_code_rate_t fec_tab[8] =
+	    { FEC_1_2, FEC_2_3, FEC_3_4, FEC_5_6, FEC_6_7, FEC_7_8,
+		FEC_AUTO, FEC_AUTO };
+
+	int ret;
+	u8 fec_status;
+
+	ret = mt312_readreg(state, FEC_STATUS, &fec_status);
+	if (ret < 0)
+		return ret;
+
+	*cr = fec_tab[(fec_status >> 4) & 0x07];
+
+	return 0;
+}
+
+static int mt312_initfe(struct dvb_frontend *fe)
+{
+	struct mt312_state *state = fe->demodulator_priv;
+	int ret;
+	u8 buf[2];
+
+	/* wake up */
+	ret = mt312_writereg(state, CONFIG,
+			(state->freq_mult == 6 ? 0x88 : 0x8c));
+	if (ret < 0)
+		return ret;
+
+	/* wait at least 150 usec */
+	udelay(150);
+
+	/* full reset */
+	ret = mt312_reset(state, 1);
+	if (ret < 0)
+		return ret;
+
+/* Per datasheet, write correct values. 09/28/03 ACCJr.
+ * If we don't do this, we won't get FE_HAS_VITERBI in the VP310. */
+	{
+		u8 buf_def[8] = { 0x14, 0x12, 0x03, 0x02,
+				  0x01, 0x00, 0x00, 0x00 };
+
+		ret = mt312_write(state, VIT_SETUP, buf_def, sizeof(buf_def));
+		if (ret < 0)
+			return ret;
+	}
+
+	switch (state->id) {
+	case ID_ZL10313:
+		/* enable ADC */
+		ret = mt312_writereg(state, GPP_CTRL, 0x80);
+		if (ret < 0)
+			return ret;
+
+		/* configure ZL10313 for optimal ADC performance */
+		buf[0] = 0x80;
+		buf[1] = 0xB0;
+		ret = mt312_write(state, HW_CTRL, buf, 2);
+		if (ret < 0)
+			return ret;
+
+		/* enable MPEG output and ADCs */
+		ret = mt312_writereg(state, HW_CTRL, 0x00);
+		if (ret < 0)
+			return ret;
+
+		ret = mt312_writereg(state, MPEG_CTRL, 0x00);
+		if (ret < 0)
+			return ret;
+
+		break;
+	}
+
+	/* SYS_CLK */
+	buf[0] = mt312_div(state->xtal * state->freq_mult * 2, 1000000);
+
+	/* DISEQC_RATIO */
+	buf[1] = mt312_div(state->xtal, 22000 * 4);
+
+	ret = mt312_write(state, SYS_CLK, buf, sizeof(buf));
+	if (ret < 0)
+		return ret;
+
+	ret = mt312_writereg(state, SNR_THS_HIGH, 0x32);
+	if (ret < 0)
+		return ret;
+
+	/* different MOCLK polarity */
+	switch (state->id) {
+	case ID_ZL10313:
+		buf[0] = 0x33;
+		break;
+	default:
+		buf[0] = 0x53;
+		break;
+	}
+
+	ret = mt312_writereg(state, OP_CTRL, buf[0]);
+	if (ret < 0)
+		return ret;
+
+	/* TS_SW_LIM */
+	buf[0] = 0x8c;
+	buf[1] = 0x98;
+
+	ret = mt312_write(state, TS_SW_LIM_L, buf, sizeof(buf));
+	if (ret < 0)
+		return ret;
+
+	ret = mt312_writereg(state, CS_SW_LIM, 0x69);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int mt312_send_master_cmd(struct dvb_frontend *fe,
+				 struct dvb_diseqc_master_cmd *c)
+{
+	struct mt312_state *state = fe->demodulator_priv;
+	int ret;
+	u8 diseqc_mode;
+
+	if ((c->msg_len == 0) || (c->msg_len > sizeof(c->msg)))
+		return -EINVAL;
+
+	ret = mt312_readreg(state, DISEQC_MODE, &diseqc_mode);
+	if (ret < 0)
+		return ret;
+
+	ret = mt312_write(state, (0x80 | DISEQC_INSTR), c->msg, c->msg_len);
+	if (ret < 0)
+		return ret;
+
+	ret = mt312_writereg(state, DISEQC_MODE,
+			     (diseqc_mode & 0x40) | ((c->msg_len - 1) << 3)
+			     | 0x04);
+	if (ret < 0)
+		return ret;
+
+	/* is there a better way to wait for message to be transmitted */
+	msleep(100);
+
+	/* set DISEQC_MODE[2:0] to zero if a return message is expected */
+	if (c->msg[0] & 0x02) {
+		ret = mt312_writereg(state, DISEQC_MODE, (diseqc_mode & 0x40));
+		if (ret < 0)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int mt312_send_burst(struct dvb_frontend *fe, const fe_sec_mini_cmd_t c)
+{
+	struct mt312_state *state = fe->demodulator_priv;
+	const u8 mini_tab[2] = { 0x02, 0x03 };
+
+	int ret;
+	u8 diseqc_mode;
+
+	if (c > SEC_MINI_B)
+		return -EINVAL;
+
+	ret = mt312_readreg(state, DISEQC_MODE, &diseqc_mode);
+	if (ret < 0)
+		return ret;
+
+	ret = mt312_writereg(state, DISEQC_MODE,
+			     (diseqc_mode & 0x40) | mini_tab[c]);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int mt312_set_tone(struct dvb_frontend *fe, const fe_sec_tone_mode_t t)
+{
+	struct mt312_state *state = fe->demodulator_priv;
+	const u8 tone_tab[2] = { 0x01, 0x00 };
+
+	int ret;
+	u8 diseqc_mode;
+
+	if (t > SEC_TONE_OFF)
+		return -EINVAL;
+
+	ret = mt312_readreg(state, DISEQC_MODE, &diseqc_mode);
+	if (ret < 0)
+		return ret;
+
+	ret = mt312_writereg(state, DISEQC_MODE,
+			     (diseqc_mode & 0x40) | tone_tab[t]);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int mt312_set_voltage(struct dvb_frontend *fe, const fe_sec_voltage_t v)
+{
+	struct mt312_state *state = fe->demodulator_priv;
+	const u8 volt_tab[3] = { 0x00, 0x40, 0x00 };
+	u8 val;
+
+	if (v > SEC_VOLTAGE_OFF)
+		return -EINVAL;
+
+	val = volt_tab[v];
+	if (state->config->voltage_inverted)
+		val ^= 0x40;
+
+	return mt312_writereg(state, DISEQC_MODE, val);
+}
+
+static int mt312_read_status(struct dvb_frontend *fe, fe_status_t *s)
+{
+	struct mt312_state *state = fe->demodulator_priv;
+	int ret;
+	u8 status[3];
+
+	*s = 0;
+
+	ret = mt312_read(state, QPSK_STAT_H, status, sizeof(status));
+	if (ret < 0)
+		return ret;
+
+	dprintk("QPSK_STAT_H: 0x%02x, QPSK_STAT_L: 0x%02x,"
+		" FEC_STATUS: 0x%02x\n", status[0], status[1], status[2]);
+
+	if (status[0] & 0xc0)
+		*s |= FE_HAS_SIGNAL;	/* signal noise ratio */
+	if (status[0] & 0x04)
+		*s |= FE_HAS_CARRIER;	/* qpsk carrier lock */
+	if (status[2] & 0x02)
+		*s |= FE_HAS_VITERBI;	/* viterbi lock */
+	if (status[2] & 0x04)
+		*s |= FE_HAS_SYNC;	/* byte align lock */
+	if (status[0] & 0x01)
+		*s |= FE_HAS_LOCK;	/* qpsk lock */
+
+	return 0;
+}
+
+static int mt312_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+	struct mt312_state *state = fe->demodulator_priv;
+	int ret;
+	u8 buf[3];
+
+	ret = mt312_read(state, RS_BERCNT_H, buf, 3);
+	if (ret < 0)
+		return ret;
+
+	*ber = ((buf[0] << 16) | (buf[1] << 8) | buf[2]) * 64;
+
+	return 0;
+}
+
+static int mt312_read_signal_strength(struct dvb_frontend *fe,
+				      u16 *signal_strength)
+{
+	struct mt312_state *state = fe->demodulator_priv;
+	int ret;
+	u8 buf[3];
+	u16 agc;
+	s16 err_db;
+
+	ret = mt312_read(state, AGC_H, buf, sizeof(buf));
+	if (ret < 0)
+		return ret;
+
+	agc = (buf[0] << 6) | (buf[1] >> 2);
+	err_db = (s16) (((buf[1] & 0x03) << 14) | buf[2] << 6) >> 6;
+
+	*signal_strength = agc;
+
+	dprintk("agc=%08x err_db=%hd\n", agc, err_db);
+
+	return 0;
+}
+
+static int mt312_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+	struct mt312_state *state = fe->demodulator_priv;
+	int ret;
+	u8 buf[2];
+
+	ret = mt312_read(state, M_SNR_H, buf, sizeof(buf));
+	if (ret < 0)
+		return ret;
+
+	*snr = 0xFFFF - ((((buf[0] & 0x7f) << 8) | buf[1]) << 1);
+
+	return 0;
+}
+
+static int mt312_read_ucblocks(struct dvb_frontend *fe, u32 *ubc)
+{
+	struct mt312_state *state = fe->demodulator_priv;
+	int ret;
+	u8 buf[2];
+
+	ret = mt312_read(state, RS_UBC_H, buf, sizeof(buf));
+	if (ret < 0)
+		return ret;
+
+	*ubc = (buf[0] << 8) | buf[1];
+
+	return 0;
+}
+
+static int mt312_set_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct mt312_state *state = fe->demodulator_priv;
+	int ret;
+	u8 buf[5], config_val;
+	u16 sr;
+
+	const u8 fec_tab[10] =
+	    { 0x00, 0x01, 0x02, 0x04, 0x3f, 0x08, 0x10, 0x20, 0x3f, 0x3f };
+	const u8 inv_tab[3] = { 0x00, 0x40, 0x80 };
+
+	dprintk("%s: Freq %d\n", __func__, p->frequency);
+
+	if ((p->frequency < fe->ops.info.frequency_min)
+	    || (p->frequency > fe->ops.info.frequency_max))
+		return -EINVAL;
+
+	if ((p->inversion < INVERSION_OFF)
+	    || (p->inversion > INVERSION_ON))
+		return -EINVAL;
+
+	if ((p->symbol_rate < fe->ops.info.symbol_rate_min)
+	    || (p->symbol_rate > fe->ops.info.symbol_rate_max))
+		return -EINVAL;
+
+	if ((p->fec_inner < FEC_NONE)
+	    || (p->fec_inner > FEC_AUTO))
+		return -EINVAL;
+
+	if ((p->fec_inner == FEC_4_5)
+	    || (p->fec_inner == FEC_8_9))
+		return -EINVAL;
+
+	switch (state->id) {
+	case ID_VP310:
+	/* For now we will do this only for the VP310.
+	 * It should be better for the mt312 as well,
+	 * but tuning will be slower. ACCJr 09/29/03
+	 */
+		ret = mt312_readreg(state, CONFIG, &config_val);
+		if (ret < 0)
+			return ret;
+		if (p->symbol_rate >= 30000000) {
+			/* Note that 30MS/s should use 90MHz */
+			if (state->freq_mult == 6) {
+				/* We are running 60MHz */
+				state->freq_mult = 9;
+				ret = mt312_initfe(fe);
+				if (ret < 0)
+					return ret;
+			}
+		} else {
+			if (state->freq_mult == 9) {
+				/* We are running 90MHz */
+				state->freq_mult = 6;
+				ret = mt312_initfe(fe);
+				if (ret < 0)
+					return ret;
+			}
+		}
+		break;
+
+	case ID_MT312:
+	case ID_ZL10313:
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	if (fe->ops.tuner_ops.set_params) {
+		fe->ops.tuner_ops.set_params(fe);
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 0);
+	}
+
+	/* sr = (u16)(sr * 256.0 / 1000000.0) */
+	sr = mt312_div(p->symbol_rate * 4, 15625);
+
+	/* SYM_RATE */
+	buf[0] = (sr >> 8) & 0x3f;
+	buf[1] = (sr >> 0) & 0xff;
+
+	/* VIT_MODE */
+	buf[2] = inv_tab[p->inversion] | fec_tab[p->fec_inner];
+
+	/* QPSK_CTRL */
+	buf[3] = 0x40;		/* swap I and Q before QPSK demodulation */
+
+	if (p->symbol_rate < 10000000)
+		buf[3] |= 0x04;	/* use afc mode */
+
+	/* GO */
+	buf[4] = 0x01;
+
+	ret = mt312_write(state, SYM_RATE_H, buf, sizeof(buf));
+	if (ret < 0)
+		return ret;
+
+	mt312_reset(state, 0);
+
+	return 0;
+}
+
+static int mt312_get_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct mt312_state *state = fe->demodulator_priv;
+	int ret;
+
+	ret = mt312_get_inversion(state, &p->inversion);
+	if (ret < 0)
+		return ret;
+
+	ret = mt312_get_symbol_rate(state, &p->symbol_rate);
+	if (ret < 0)
+		return ret;
+
+	ret = mt312_get_code_rate(state, &p->fec_inner);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int mt312_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+	struct mt312_state *state = fe->demodulator_priv;
+
+	u8 val = 0x00;
+	int ret;
+
+	switch (state->id) {
+	case ID_ZL10313:
+		ret = mt312_readreg(state, GPP_CTRL, &val);
+		if (ret < 0)
+			goto error;
+
+		/* preserve this bit to not accidentally shutdown ADC */
+		val &= 0x80;
+		break;
+	}
+
+	if (enable)
+		val |= 0x40;
+	else
+		val &= ~0x40;
+
+	ret = mt312_writereg(state, GPP_CTRL, val);
+
+error:
+	return ret;
+}
+
+static int mt312_sleep(struct dvb_frontend *fe)
+{
+	struct mt312_state *state = fe->demodulator_priv;
+	int ret;
+	u8 config;
+
+	/* reset all registers to defaults */
+	ret = mt312_reset(state, 1);
+	if (ret < 0)
+		return ret;
+
+	if (state->id == ID_ZL10313) {
+		/* reset ADC */
+		ret = mt312_writereg(state, GPP_CTRL, 0x00);
+		if (ret < 0)
+			return ret;
+
+		/* full shutdown of ADCs, mpeg bus tristated */
+		ret = mt312_writereg(state, HW_CTRL, 0x0d);
+		if (ret < 0)
+			return ret;
+	}
+
+	ret = mt312_readreg(state, CONFIG, &config);
+	if (ret < 0)
+		return ret;
+
+	/* enter standby */
+	ret = mt312_writereg(state, CONFIG, config & 0x7f);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int mt312_get_tune_settings(struct dvb_frontend *fe,
+		struct dvb_frontend_tune_settings *fesettings)
+{
+	fesettings->min_delay_ms = 50;
+	fesettings->step_size = 0;
+	fesettings->max_drift = 0;
+	return 0;
+}
+
+static void mt312_release(struct dvb_frontend *fe)
+{
+	struct mt312_state *state = fe->demodulator_priv;
+	kfree(state);
+}
+
+#define MT312_SYS_CLK		90000000UL	/* 90 MHz */
+static struct dvb_frontend_ops mt312_ops = {
+	.delsys = { SYS_DVBS },
+	.info = {
+		.name = "Zarlink ???? DVB-S",
+		.frequency_min = 950000,
+		.frequency_max = 2150000,
+		/* FIXME: adjust freq to real used xtal */
+		.frequency_stepsize = (MT312_PLL_CLK / 1000) / 128,
+		.symbol_rate_min = MT312_SYS_CLK / 128, /* FIXME as above */
+		.symbol_rate_max = MT312_SYS_CLK / 2,
+		.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_FEC_AUTO | FE_CAN_QPSK | FE_CAN_MUTE_TS |
+		    FE_CAN_RECOVER
+	},
+
+	.release = mt312_release,
+
+	.init = mt312_initfe,
+	.sleep = mt312_sleep,
+	.i2c_gate_ctrl = mt312_i2c_gate_ctrl,
+
+	.set_frontend = mt312_set_frontend,
+	.get_frontend = mt312_get_frontend,
+	.get_tune_settings = mt312_get_tune_settings,
+
+	.read_status = mt312_read_status,
+	.read_ber = mt312_read_ber,
+	.read_signal_strength = mt312_read_signal_strength,
+	.read_snr = mt312_read_snr,
+	.read_ucblocks = mt312_read_ucblocks,
+
+	.diseqc_send_master_cmd = mt312_send_master_cmd,
+	.diseqc_send_burst = mt312_send_burst,
+	.set_tone = mt312_set_tone,
+	.set_voltage = mt312_set_voltage,
+};
+
+struct dvb_frontend *mt312_attach(const struct mt312_config *config,
+					struct i2c_adapter *i2c)
+{
+	struct mt312_state *state = NULL;
+
+	/* allocate memory for the internal state */
+	state = kzalloc(sizeof(struct mt312_state), GFP_KERNEL);
+	if (state == NULL)
+		goto error;
+
+	/* setup the state */
+	state->config = config;
+	state->i2c = i2c;
+
+	/* check if the demod is there */
+	if (mt312_readreg(state, ID, &state->id) < 0)
+		goto error;
+
+	/* create dvb_frontend */
+	memcpy(&state->frontend.ops, &mt312_ops,
+		sizeof(struct dvb_frontend_ops));
+	state->frontend.demodulator_priv = state;
+
+	switch (state->id) {
+	case ID_VP310:
+		strcpy(state->frontend.ops.info.name, "Zarlink VP310 DVB-S");
+		state->xtal = MT312_PLL_CLK;
+		state->freq_mult = 9;
+		break;
+	case ID_MT312:
+		strcpy(state->frontend.ops.info.name, "Zarlink MT312 DVB-S");
+		state->xtal = MT312_PLL_CLK;
+		state->freq_mult = 6;
+		break;
+	case ID_ZL10313:
+		strcpy(state->frontend.ops.info.name, "Zarlink ZL10313 DVB-S");
+		state->xtal = MT312_PLL_CLK_10_111;
+		state->freq_mult = 9;
+		break;
+	default:
+		printk(KERN_WARNING "Only Zarlink VP310/MT312/ZL10313"
+			" are supported chips.\n");
+		goto error;
+	}
+
+	return &state->frontend;
+
+error:
+	kfree(state);
+	return NULL;
+}
+EXPORT_SYMBOL(mt312_attach);
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+
+MODULE_DESCRIPTION("Zarlink VP310/MT312/ZL10313 DVB-S Demodulator driver");
+MODULE_AUTHOR("Andreas Oberritter <obi@linuxtv.org>");
+MODULE_AUTHOR("Matthias Schwarzott <zzam@gentoo.org>");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/media/dvb-frontends/mt312.h b/drivers/media/dvb-frontends/mt312.h
new file mode 100644
index 0000000..29e3bb5
--- /dev/null
+++ b/drivers/media/dvb-frontends/mt312.h
@@ -0,0 +1,51 @@
+/*
+    Driver for Zarlink MT312 Satellite Channel Decoder
+
+    Copyright (C) 2003 Andreas Oberritter <obi@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.
+
+    References:
+    http://products.zarlink.com/product_profiles/MT312.htm
+    http://products.zarlink.com/product_profiles/SL1935.htm
+*/
+
+#ifndef MT312_H
+#define MT312_H
+
+#include <linux/dvb/frontend.h>
+
+struct mt312_config {
+	/* the demodulator's i2c address */
+	u8 demod_address;
+
+	/* inverted voltage setting */
+	unsigned int voltage_inverted:1;
+};
+
+#if defined(CONFIG_DVB_MT312) || (defined(CONFIG_DVB_MT312_MODULE) && defined(MODULE))
+struct dvb_frontend *mt312_attach(const struct mt312_config *config,
+					struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend *mt312_attach(
+	const struct mt312_config *config, struct i2c_adapter *i2c)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif /* CONFIG_DVB_MT312 */
+
+#endif /* MT312_H */
diff --git a/drivers/media/dvb-frontends/mt312_priv.h b/drivers/media/dvb-frontends/mt312_priv.h
new file mode 100644
index 0000000..a3959f9
--- /dev/null
+++ b/drivers/media/dvb-frontends/mt312_priv.h
@@ -0,0 +1,165 @@
+/*
+    Driver for Zarlink MT312 QPSK Frontend
+
+    Copyright (C) 2003 Andreas Oberritter <obi@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 _DVB_FRONTENDS_MT312_PRIV
+#define _DVB_FRONTENDS_MT312_PRIV
+
+enum mt312_reg_addr {
+	QPSK_INT_H = 0,
+	QPSK_INT_M = 1,
+	QPSK_INT_L = 2,
+	FEC_INT = 3,
+	QPSK_STAT_H = 4,
+	QPSK_STAT_L = 5,
+	FEC_STATUS = 6,
+	LNB_FREQ_H = 7,
+	LNB_FREQ_L = 8,
+	M_SNR_H = 9,
+	M_SNR_L = 10,
+	VIT_ERRCNT_H = 11,
+	VIT_ERRCNT_M = 12,
+	VIT_ERRCNT_L = 13,
+	RS_BERCNT_H = 14,
+	RS_BERCNT_M = 15,
+	RS_BERCNT_L = 16,
+	RS_UBC_H = 17,
+	RS_UBC_L = 18,
+	SIG_LEVEL = 19,
+	GPP_CTRL = 20,
+	RESET = 21,
+	DISEQC_MODE = 22,
+	SYM_RATE_H = 23,
+	SYM_RATE_L = 24,
+	VIT_MODE = 25,
+	QPSK_CTRL = 26,
+	GO = 27,
+	IE_QPSK_H = 28,
+	IE_QPSK_M = 29,
+	IE_QPSK_L = 30,
+	IE_FEC = 31,
+	QPSK_STAT_EN = 32,
+	FEC_STAT_EN = 33,
+	SYS_CLK = 34,
+	DISEQC_RATIO = 35,
+	DISEQC_INSTR = 36,
+	FR_LIM = 37,
+	FR_OFF = 38,
+	AGC_CTRL = 39,
+	AGC_INIT = 40,
+	AGC_REF = 41,
+	AGC_MAX = 42,
+	AGC_MIN = 43,
+	AGC_LK_TH = 44,
+	TS_AGC_LK_TH = 45,
+	AGC_PWR_SET = 46,
+	QPSK_MISC = 47,
+	SNR_THS_LOW = 48,
+	SNR_THS_HIGH = 49,
+	TS_SW_RATE = 50,
+	TS_SW_LIM_L = 51,
+	TS_SW_LIM_H = 52,
+	CS_SW_RATE_1 = 53,
+	CS_SW_RATE_2 = 54,
+	CS_SW_RATE_3 = 55,
+	CS_SW_RATE_4 = 56,
+	CS_SW_LIM = 57,
+	TS_LPK = 58,
+	TS_LPK_M = 59,
+	TS_LPK_L = 60,
+	CS_KPROP_H = 61,
+	CS_KPROP_L = 62,
+	CS_KINT_H = 63,
+	CS_KINT_L = 64,
+	QPSK_SCALE = 65,
+	TLD_OUTCLK_TH = 66,
+	TLD_INCLK_TH = 67,
+	FLD_TH = 68,
+	PLD_OUTLK3 = 69,
+	PLD_OUTLK2 = 70,
+	PLD_OUTLK1 = 71,
+	PLD_OUTLK0 = 72,
+	PLD_INLK3 = 73,
+	PLD_INLK2 = 74,
+	PLD_INLK1 = 75,
+	PLD_INLK0 = 76,
+	PLD_ACC_TIME = 77,
+	SWEEP_PAR = 78,
+	STARTUP_TIME = 79,
+	LOSSLOCK_TH = 80,
+	FEC_LOCK_TM = 81,
+	LOSSLOCK_TM = 82,
+	VIT_ERRPER_H = 83,
+	VIT_ERRPER_M = 84,
+	VIT_ERRPER_L = 85,
+	HW_CTRL = 84,	/* ZL10313 only */
+	MPEG_CTRL = 85,	/* ZL10313 only */
+	VIT_SETUP = 86,
+	VIT_REF0 = 87,
+	VIT_REF1 = 88,
+	VIT_REF2 = 89,
+	VIT_REF3 = 90,
+	VIT_REF4 = 91,
+	VIT_REF5 = 92,
+	VIT_REF6 = 93,
+	VIT_MAXERR = 94,
+	BA_SETUPT = 95,
+	OP_CTRL = 96,
+	FEC_SETUP = 97,
+	PROG_SYNC = 98,
+	AFC_SEAR_TH = 99,
+	CSACC_DIF_TH = 100,
+	QPSK_LK_CT = 101,
+	QPSK_ST_CT = 102,
+	MON_CTRL = 103,
+	QPSK_RESET = 104,
+	QPSK_TST_CT = 105,
+	QPSK_TST_ST = 106,
+	TEST_R = 107,
+	AGC_H = 108,
+	AGC_M = 109,
+	AGC_L = 110,
+	FREQ_ERR1_H = 111,
+	FREQ_ERR1_M = 112,
+	FREQ_ERR1_L = 113,
+	FREQ_ERR2_H = 114,
+	FREQ_ERR2_L = 115,
+	SYM_RAT_OP_H = 116,
+	SYM_RAT_OP_L = 117,
+	DESEQC2_INT = 118,
+	DISEQC2_STAT = 119,
+	DISEQC2_FIFO = 120,
+	DISEQC2_CTRL1 = 121,
+	DISEQC2_CTRL2 = 122,
+	MONITOR_H = 123,
+	MONITOR_L = 124,
+	TEST_MODE = 125,
+	ID = 126,
+	CONFIG = 127
+};
+
+enum mt312_model_id {
+	ID_VP310 = 1,
+	ID_MT312 = 3,
+	ID_ZL10313 = 5,
+};
+
+#endif				/* DVB_FRONTENDS_MT312_PRIV */
diff --git a/drivers/media/dvb-frontends/mt352.c b/drivers/media/dvb-frontends/mt352.c
new file mode 100644
index 0000000..2c3b50e
--- /dev/null
+++ b/drivers/media/dvb-frontends/mt352.c
@@ -0,0 +1,610 @@
+/*
+ *  Driver for Zarlink DVB-T MT352 demodulator
+ *
+ *  Written by Holger Waechtler <holger@qanu.de>
+ *	 and Daniel Mack <daniel@qanu.de>
+ *
+ *  AVerMedia AVerTV DVB-T 771 support by
+ *       Wolfram Joost <dbox2@frokaschwei.de>
+ *
+ *  Support for Samsung TDTC9251DH01C(M) tuner
+ *  Copyright (C) 2004 Antonio Mancuso <antonio.mancuso@digitaltelevision.it>
+ *                     Amauri  Celani  <acelani@essegi.net>
+ *
+ *  DVICO FusionHDTV DVB-T1 and DVICO FusionHDTV DVB-T Lite support by
+ *       Christopher Pascoe <c.pascoe@itee.uq.edu.au>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You 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/init.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+
+#include "dvb_frontend.h"
+#include "mt352_priv.h"
+#include "mt352.h"
+
+struct mt352_state {
+	struct i2c_adapter* i2c;
+	struct dvb_frontend frontend;
+
+	/* configuration settings */
+	struct mt352_config config;
+};
+
+static int debug;
+#define dprintk(args...) \
+	do { \
+		if (debug) printk(KERN_DEBUG "mt352: " args); \
+	} while (0)
+
+static int mt352_single_write(struct dvb_frontend *fe, u8 reg, u8 val)
+{
+	struct mt352_state* state = fe->demodulator_priv;
+	u8 buf[2] = { reg, val };
+	struct i2c_msg msg = { .addr = state->config.demod_address, .flags = 0,
+			       .buf = buf, .len = 2 };
+	int err = i2c_transfer(state->i2c, &msg, 1);
+	if (err != 1) {
+		printk("mt352_write() to reg %x failed (err = %d)!\n", reg, err);
+		return err;
+	}
+	return 0;
+}
+
+static int _mt352_write(struct dvb_frontend* fe, const u8 ibuf[], int ilen)
+{
+	int err,i;
+	for (i=0; i < ilen-1; i++)
+		if ((err = mt352_single_write(fe,ibuf[0]+i,ibuf[i+1])))
+			return err;
+
+	return 0;
+}
+
+static int mt352_read_register(struct mt352_state* state, u8 reg)
+{
+	int ret;
+	u8 b0 [] = { reg };
+	u8 b1 [] = { 0 };
+	struct i2c_msg msg [] = { { .addr = state->config.demod_address,
+				    .flags = 0,
+				    .buf = b0, .len = 1 },
+				  { .addr = state->config.demod_address,
+				    .flags = I2C_M_RD,
+				    .buf = b1, .len = 1 } };
+
+	ret = i2c_transfer(state->i2c, msg, 2);
+
+	if (ret != 2) {
+		printk("%s: readreg error (reg=%d, ret==%i)\n",
+		       __func__, reg, ret);
+		return ret;
+	}
+
+	return b1[0];
+}
+
+static int mt352_sleep(struct dvb_frontend* fe)
+{
+	static u8 mt352_softdown[] = { CLOCK_CTL, 0x20, 0x08 };
+
+	_mt352_write(fe, mt352_softdown, sizeof(mt352_softdown));
+	return 0;
+}
+
+static void mt352_calc_nominal_rate(struct mt352_state* state,
+				    u32 bandwidth,
+				    unsigned char *buf)
+{
+	u32 adc_clock = 20480; /* 20.340 MHz */
+	u32 bw,value;
+
+	switch (bandwidth) {
+	case 6000000:
+		bw = 6;
+		break;
+	case 7000000:
+		bw = 7;
+		break;
+	case 8000000:
+	default:
+		bw = 8;
+		break;
+	}
+	if (state->config.adc_clock)
+		adc_clock = state->config.adc_clock;
+
+	value = 64 * bw * (1<<16) / (7 * 8);
+	value = value * 1000 / adc_clock;
+	dprintk("%s: bw %d, adc_clock %d => 0x%x\n",
+		__func__, bw, adc_clock, value);
+	buf[0] = msb(value);
+	buf[1] = lsb(value);
+}
+
+static void mt352_calc_input_freq(struct mt352_state* state,
+				  unsigned char *buf)
+{
+	int adc_clock = 20480; /* 20.480000 MHz */
+	int if2       = 36167; /* 36.166667 MHz */
+	int ife,value;
+
+	if (state->config.adc_clock)
+		adc_clock = state->config.adc_clock;
+	if (state->config.if2)
+		if2 = state->config.if2;
+
+	if (adc_clock >= if2 * 2)
+		ife = if2;
+	else {
+		ife = adc_clock - (if2 % adc_clock);
+		if (ife > adc_clock / 2)
+			ife = adc_clock - ife;
+	}
+	value = -16374 * ife / adc_clock;
+	dprintk("%s: if2 %d, ife %d, adc_clock %d => %d / 0x%x\n",
+		__func__, if2, ife, adc_clock, value, value & 0x3fff);
+	buf[0] = msb(value);
+	buf[1] = lsb(value);
+}
+
+static int mt352_set_parameters(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *op = &fe->dtv_property_cache;
+	struct mt352_state* state = fe->demodulator_priv;
+	unsigned char buf[13];
+	static unsigned char tuner_go[] = { 0x5d, 0x01 };
+	static unsigned char fsm_go[]   = { 0x5e, 0x01 };
+	unsigned int tps = 0;
+
+	switch (op->code_rate_HP) {
+		case FEC_2_3:
+			tps |= (1 << 7);
+			break;
+		case FEC_3_4:
+			tps |= (2 << 7);
+			break;
+		case FEC_5_6:
+			tps |= (3 << 7);
+			break;
+		case FEC_7_8:
+			tps |= (4 << 7);
+			break;
+		case FEC_1_2:
+		case FEC_AUTO:
+			break;
+		default:
+			return -EINVAL;
+	}
+
+	switch (op->code_rate_LP) {
+		case FEC_2_3:
+			tps |= (1 << 4);
+			break;
+		case FEC_3_4:
+			tps |= (2 << 4);
+			break;
+		case FEC_5_6:
+			tps |= (3 << 4);
+			break;
+		case FEC_7_8:
+			tps |= (4 << 4);
+			break;
+		case FEC_1_2:
+		case FEC_AUTO:
+			break;
+		case FEC_NONE:
+			if (op->hierarchy == HIERARCHY_AUTO ||
+			    op->hierarchy == HIERARCHY_NONE)
+				break;
+		default:
+			return -EINVAL;
+	}
+
+	switch (op->modulation) {
+		case QPSK:
+			break;
+		case QAM_AUTO:
+		case QAM_16:
+			tps |= (1 << 13);
+			break;
+		case QAM_64:
+			tps |= (2 << 13);
+			break;
+		default:
+			return -EINVAL;
+	}
+
+	switch (op->transmission_mode) {
+		case TRANSMISSION_MODE_2K:
+		case TRANSMISSION_MODE_AUTO:
+			break;
+		case TRANSMISSION_MODE_8K:
+			tps |= (1 << 0);
+			break;
+		default:
+			return -EINVAL;
+	}
+
+	switch (op->guard_interval) {
+		case GUARD_INTERVAL_1_32:
+		case GUARD_INTERVAL_AUTO:
+			break;
+		case GUARD_INTERVAL_1_16:
+			tps |= (1 << 2);
+			break;
+		case GUARD_INTERVAL_1_8:
+			tps |= (2 << 2);
+			break;
+		case GUARD_INTERVAL_1_4:
+			tps |= (3 << 2);
+			break;
+		default:
+			return -EINVAL;
+	}
+
+	switch (op->hierarchy) {
+		case HIERARCHY_AUTO:
+		case HIERARCHY_NONE:
+			break;
+		case HIERARCHY_1:
+			tps |= (1 << 10);
+			break;
+		case HIERARCHY_2:
+			tps |= (2 << 10);
+			break;
+		case HIERARCHY_4:
+			tps |= (3 << 10);
+			break;
+		default:
+			return -EINVAL;
+	}
+
+
+	buf[0] = TPS_GIVEN_1; /* TPS_GIVEN_1 and following registers */
+
+	buf[1] = msb(tps);      /* TPS_GIVEN_(1|0) */
+	buf[2] = lsb(tps);
+
+	buf[3] = 0x50;  // old
+//	buf[3] = 0xf4;  // pinnacle
+
+	mt352_calc_nominal_rate(state, op->bandwidth_hz, buf+4);
+	mt352_calc_input_freq(state, buf+6);
+
+	if (state->config.no_tuner) {
+		if (fe->ops.tuner_ops.set_params) {
+			fe->ops.tuner_ops.set_params(fe);
+			if (fe->ops.i2c_gate_ctrl)
+				fe->ops.i2c_gate_ctrl(fe, 0);
+		}
+
+		_mt352_write(fe, buf, 8);
+		_mt352_write(fe, fsm_go, 2);
+	} else {
+		if (fe->ops.tuner_ops.calc_regs) {
+			fe->ops.tuner_ops.calc_regs(fe, buf+8, 5);
+			buf[8] <<= 1;
+			_mt352_write(fe, buf, sizeof(buf));
+			_mt352_write(fe, tuner_go, 2);
+		}
+	}
+
+	return 0;
+}
+
+static int mt352_get_parameters(struct dvb_frontend* fe)
+{
+	struct dtv_frontend_properties *op = &fe->dtv_property_cache;
+	struct mt352_state* state = fe->demodulator_priv;
+	u16 tps;
+	u16 div;
+	u8 trl;
+	static const u8 tps_fec_to_api[8] =
+	{
+		FEC_1_2,
+		FEC_2_3,
+		FEC_3_4,
+		FEC_5_6,
+		FEC_7_8,
+		FEC_AUTO,
+		FEC_AUTO,
+		FEC_AUTO
+	};
+
+	if ( (mt352_read_register(state,0x00) & 0xC0) != 0xC0 )
+		return -EINVAL;
+
+	/* Use TPS_RECEIVED-registers, not the TPS_CURRENT-registers because
+	 * the mt352 sometimes works with the wrong parameters
+	 */
+	tps = (mt352_read_register(state, TPS_RECEIVED_1) << 8) | mt352_read_register(state, TPS_RECEIVED_0);
+	div = (mt352_read_register(state, CHAN_START_1) << 8) | mt352_read_register(state, CHAN_START_0);
+	trl = mt352_read_register(state, TRL_NOMINAL_RATE_1);
+
+	op->code_rate_HP = tps_fec_to_api[(tps >> 7) & 7];
+	op->code_rate_LP = tps_fec_to_api[(tps >> 4) & 7];
+
+	switch ( (tps >> 13) & 3)
+	{
+		case 0:
+			op->modulation = QPSK;
+			break;
+		case 1:
+			op->modulation = QAM_16;
+			break;
+		case 2:
+			op->modulation = QAM_64;
+			break;
+		default:
+			op->modulation = QAM_AUTO;
+			break;
+	}
+
+	op->transmission_mode = (tps & 0x01) ? TRANSMISSION_MODE_8K : TRANSMISSION_MODE_2K;
+
+	switch ( (tps >> 2) & 3)
+	{
+		case 0:
+			op->guard_interval = GUARD_INTERVAL_1_32;
+			break;
+		case 1:
+			op->guard_interval = GUARD_INTERVAL_1_16;
+			break;
+		case 2:
+			op->guard_interval = GUARD_INTERVAL_1_8;
+			break;
+		case 3:
+			op->guard_interval = GUARD_INTERVAL_1_4;
+			break;
+		default:
+			op->guard_interval = GUARD_INTERVAL_AUTO;
+			break;
+	}
+
+	switch ( (tps >> 10) & 7)
+	{
+		case 0:
+			op->hierarchy = HIERARCHY_NONE;
+			break;
+		case 1:
+			op->hierarchy = HIERARCHY_1;
+			break;
+		case 2:
+			op->hierarchy = HIERARCHY_2;
+			break;
+		case 3:
+			op->hierarchy = HIERARCHY_4;
+			break;
+		default:
+			op->hierarchy = HIERARCHY_AUTO;
+			break;
+	}
+
+	op->frequency = (500 * (div - IF_FREQUENCYx6)) / 3 * 1000;
+
+	if (trl == 0x72)
+		op->bandwidth_hz = 8000000;
+	else if (trl == 0x64)
+		op->bandwidth_hz = 7000000;
+	else
+		op->bandwidth_hz = 6000000;
+
+
+	if (mt352_read_register(state, STATUS_2) & 0x02)
+		op->inversion = INVERSION_OFF;
+	else
+		op->inversion = INVERSION_ON;
+
+	return 0;
+}
+
+static int mt352_read_status(struct dvb_frontend* fe, fe_status_t* status)
+{
+	struct mt352_state* state = fe->demodulator_priv;
+	int s0, s1, s3;
+
+	/* FIXME:
+	 *
+	 * The MT352 design manual from Zarlink states (page 46-47):
+	 *
+	 * Notes about the TUNER_GO register:
+	 *
+	 * If the Read_Tuner_Byte (bit-1) is activated, then the tuner status
+	 * byte is copied from the tuner to the STATUS_3 register and
+	 * completion of the read operation is indicated by bit-5 of the
+	 * INTERRUPT_3 register.
+	 */
+
+	if ((s0 = mt352_read_register(state, STATUS_0)) < 0)
+		return -EREMOTEIO;
+	if ((s1 = mt352_read_register(state, STATUS_1)) < 0)
+		return -EREMOTEIO;
+	if ((s3 = mt352_read_register(state, STATUS_3)) < 0)
+		return -EREMOTEIO;
+
+	*status = 0;
+	if (s0 & (1 << 4))
+		*status |= FE_HAS_CARRIER;
+	if (s0 & (1 << 1))
+		*status |= FE_HAS_VITERBI;
+	if (s0 & (1 << 5))
+		*status |= FE_HAS_LOCK;
+	if (s1 & (1 << 1))
+		*status |= FE_HAS_SYNC;
+	if (s3 & (1 << 6))
+		*status |= FE_HAS_SIGNAL;
+
+	if ((*status & (FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC)) !=
+		      (FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC))
+		*status &= ~FE_HAS_LOCK;
+
+	return 0;
+}
+
+static int mt352_read_ber(struct dvb_frontend* fe, u32* ber)
+{
+	struct mt352_state* state = fe->demodulator_priv;
+
+	*ber = (mt352_read_register (state, RS_ERR_CNT_2) << 16) |
+	       (mt352_read_register (state, RS_ERR_CNT_1) << 8) |
+	       (mt352_read_register (state, RS_ERR_CNT_0));
+
+	return 0;
+}
+
+static int mt352_read_signal_strength(struct dvb_frontend* fe, u16* strength)
+{
+	struct mt352_state* state = fe->demodulator_priv;
+
+	/* align the 12 bit AGC gain with the most significant bits */
+	u16 signal = ((mt352_read_register(state, AGC_GAIN_1) & 0x0f) << 12) |
+		(mt352_read_register(state, AGC_GAIN_0) << 4);
+
+	/* inverse of gain is signal strength */
+	*strength = ~signal;
+	return 0;
+}
+
+static int mt352_read_snr(struct dvb_frontend* fe, u16* snr)
+{
+	struct mt352_state* state = fe->demodulator_priv;
+
+	u8 _snr = mt352_read_register (state, SNR);
+	*snr = (_snr << 8) | _snr;
+
+	return 0;
+}
+
+static int mt352_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
+{
+	struct mt352_state* state = fe->demodulator_priv;
+
+	*ucblocks = (mt352_read_register (state,  RS_UBC_1) << 8) |
+		    (mt352_read_register (state,  RS_UBC_0));
+
+	return 0;
+}
+
+static int mt352_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fe_tune_settings)
+{
+	fe_tune_settings->min_delay_ms = 800;
+	fe_tune_settings->step_size = 0;
+	fe_tune_settings->max_drift = 0;
+
+	return 0;
+}
+
+static int mt352_init(struct dvb_frontend* fe)
+{
+	struct mt352_state* state = fe->demodulator_priv;
+
+	static u8 mt352_reset_attach [] = { RESET, 0xC0 };
+
+	dprintk("%s: hello\n",__func__);
+
+	if ((mt352_read_register(state, CLOCK_CTL) & 0x10) == 0 ||
+	    (mt352_read_register(state, CONFIG) & 0x20) == 0) {
+
+		/* Do a "hard" reset */
+		_mt352_write(fe, mt352_reset_attach, sizeof(mt352_reset_attach));
+		return state->config.demod_init(fe);
+	}
+
+	return 0;
+}
+
+static void mt352_release(struct dvb_frontend* fe)
+{
+	struct mt352_state* state = fe->demodulator_priv;
+	kfree(state);
+}
+
+static struct dvb_frontend_ops mt352_ops;
+
+struct dvb_frontend* mt352_attach(const struct mt352_config* config,
+				  struct i2c_adapter* i2c)
+{
+	struct mt352_state* state = NULL;
+
+	/* allocate memory for the internal state */
+	state = kzalloc(sizeof(struct mt352_state), GFP_KERNEL);
+	if (state == NULL) goto error;
+
+	/* setup the state */
+	state->i2c = i2c;
+	memcpy(&state->config,config,sizeof(struct mt352_config));
+
+	/* check if the demod is there */
+	if (mt352_read_register(state, CHIP_ID) != ID_MT352) goto error;
+
+	/* create dvb_frontend */
+	memcpy(&state->frontend.ops, &mt352_ops, sizeof(struct dvb_frontend_ops));
+	state->frontend.demodulator_priv = state;
+	return &state->frontend;
+
+error:
+	kfree(state);
+	return NULL;
+}
+
+static struct dvb_frontend_ops mt352_ops = {
+	.delsys = { SYS_DVBT },
+	.info = {
+		.name			= "Zarlink MT352 DVB-T",
+		.frequency_min		= 174000000,
+		.frequency_max		= 862000000,
+		.frequency_stepsize	= 166667,
+		.frequency_tolerance	= 0,
+		.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_FEC_AUTO |
+			FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
+			FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |
+			FE_CAN_HIERARCHY_AUTO | FE_CAN_RECOVER |
+			FE_CAN_MUTE_TS
+	},
+
+	.release = mt352_release,
+
+	.init = mt352_init,
+	.sleep = mt352_sleep,
+	.write = _mt352_write,
+
+	.set_frontend = mt352_set_parameters,
+	.get_frontend = mt352_get_parameters,
+	.get_tune_settings = mt352_get_tune_settings,
+
+	.read_status = mt352_read_status,
+	.read_ber = mt352_read_ber,
+	.read_signal_strength = mt352_read_signal_strength,
+	.read_snr = mt352_read_snr,
+	.read_ucblocks = mt352_read_ucblocks,
+};
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+
+MODULE_DESCRIPTION("Zarlink MT352 DVB-T Demodulator driver");
+MODULE_AUTHOR("Holger Waechtler, Daniel Mack, Antonio Mancuso");
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(mt352_attach);
diff --git a/drivers/media/dvb-frontends/mt352.h b/drivers/media/dvb-frontends/mt352.h
new file mode 100644
index 0000000..ca2562d
--- /dev/null
+++ b/drivers/media/dvb-frontends/mt352.h
@@ -0,0 +1,73 @@
+/*
+ *  Driver for Zarlink DVB-T MT352 demodulator
+ *
+ *  Written by Holger Waechtler <holger@qanu.de>
+ *	 and Daniel Mack <daniel@qanu.de>
+ *
+ *  AVerMedia AVerTV DVB-T 771 support by
+ *       Wolfram Joost <dbox2@frokaschwei.de>
+ *
+ *  Support for Samsung TDTC9251DH01C(M) tuner
+ *  Copyright (C) 2004 Antonio Mancuso <antonio.mancuso@digitaltelevision.it>
+ *                     Amauri  Celani  <acelani@essegi.net>
+ *
+ *  DVICO FusionHDTV DVB-T1 and DVICO FusionHDTV DVB-T Lite support by
+ *       Christopher Pascoe <c.pascoe@itee.uq.edu.au>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You 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 MT352_H
+#define MT352_H
+
+#include <linux/dvb/frontend.h>
+
+struct mt352_config
+{
+	/* the demodulator's i2c address */
+	u8 demod_address;
+
+	/* frequencies in kHz */
+	int adc_clock;  // default: 20480
+	int if2;        // default: 36166
+
+	/* set if no pll is connected to the secondary i2c bus */
+	int no_tuner;
+
+	/* Initialise the demodulator and PLL. Cannot be NULL */
+	int (*demod_init)(struct dvb_frontend* fe);
+};
+
+#if defined(CONFIG_DVB_MT352) || (defined(CONFIG_DVB_MT352_MODULE) && defined(MODULE))
+extern struct dvb_frontend* mt352_attach(const struct mt352_config* config,
+					 struct i2c_adapter* i2c);
+#else
+static inline struct dvb_frontend* mt352_attach(const struct mt352_config* config,
+					 struct i2c_adapter* i2c)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif // CONFIG_DVB_MT352
+
+static inline int mt352_write(struct dvb_frontend *fe, const u8 buf[], int len) {
+	int r = 0;
+	if (fe->ops.write)
+		r = fe->ops.write(fe, buf, len);
+	return r;
+}
+
+#endif // MT352_H
diff --git a/drivers/media/dvb-frontends/mt352_priv.h b/drivers/media/dvb-frontends/mt352_priv.h
new file mode 100644
index 0000000..44ad0d4
--- /dev/null
+++ b/drivers/media/dvb-frontends/mt352_priv.h
@@ -0,0 +1,127 @@
+/*
+ *  Driver for Zarlink DVB-T MT352 demodulator
+ *
+ *  Written by Holger Waechtler <holger@qanu.de>
+ *	 and Daniel Mack <daniel@qanu.de>
+ *
+ *  AVerMedia AVerTV DVB-T 771 support by
+ *       Wolfram Joost <dbox2@frokaschwei.de>
+ *
+ *  Support for Samsung TDTC9251DH01C(M) tuner
+ *  Copyright (C) 2004 Antonio Mancuso <antonio.mancuso@digitaltelevision.it>
+ *                     Amauri  Celani  <acelani@essegi.net>
+ *
+ *  DVICO FusionHDTV DVB-T1 and DVICO FusionHDTV DVB-T Lite support by
+ *       Christopher Pascoe <c.pascoe@itee.uq.edu.au>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You 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 _MT352_PRIV_
+#define _MT352_PRIV_
+
+#define ID_MT352        0x13
+
+#define msb(x) (((x) >> 8) & 0xff)
+#define lsb(x) ((x) & 0xff)
+
+enum mt352_reg_addr {
+	STATUS_0           = 0x00,
+	STATUS_1           = 0x01,
+	STATUS_2           = 0x02,
+	STATUS_3           = 0x03,
+	STATUS_4           = 0x04,
+	INTERRUPT_0        = 0x05,
+	INTERRUPT_1        = 0x06,
+	INTERRUPT_2        = 0x07,
+	INTERRUPT_3        = 0x08,
+	SNR                = 0x09,
+	VIT_ERR_CNT_2      = 0x0A,
+	VIT_ERR_CNT_1      = 0x0B,
+	VIT_ERR_CNT_0      = 0x0C,
+	RS_ERR_CNT_2       = 0x0D,
+	RS_ERR_CNT_1       = 0x0E,
+	RS_ERR_CNT_0       = 0x0F,
+	RS_UBC_1           = 0x10,
+	RS_UBC_0           = 0x11,
+	AGC_GAIN_3         = 0x12,
+	AGC_GAIN_2         = 0x13,
+	AGC_GAIN_1         = 0x14,
+	AGC_GAIN_0         = 0x15,
+	FREQ_OFFSET_2      = 0x17,
+	FREQ_OFFSET_1      = 0x18,
+	FREQ_OFFSET_0      = 0x19,
+	TIMING_OFFSET_1    = 0x1A,
+	TIMING_OFFSET_0    = 0x1B,
+	CHAN_FREQ_1        = 0x1C,
+	CHAN_FREQ_0        = 0x1D,
+	TPS_RECEIVED_1     = 0x1E,
+	TPS_RECEIVED_0     = 0x1F,
+	TPS_CURRENT_1      = 0x20,
+	TPS_CURRENT_0      = 0x21,
+	TPS_CELL_ID_1      = 0x22,
+	TPS_CELL_ID_0      = 0x23,
+	TPS_MISC_DATA_2    = 0x24,
+	TPS_MISC_DATA_1    = 0x25,
+	TPS_MISC_DATA_0    = 0x26,
+	RESET              = 0x50,
+	TPS_GIVEN_1        = 0x51,
+	TPS_GIVEN_0        = 0x52,
+	ACQ_CTL            = 0x53,
+	TRL_NOMINAL_RATE_1 = 0x54,
+	TRL_NOMINAL_RATE_0 = 0x55,
+	INPUT_FREQ_1       = 0x56,
+	INPUT_FREQ_0       = 0x57,
+	TUNER_ADDR         = 0x58,
+	CHAN_START_1       = 0x59,
+	CHAN_START_0       = 0x5A,
+	CONT_1             = 0x5B,
+	CONT_0             = 0x5C,
+	TUNER_GO           = 0x5D,
+	STATUS_EN_0        = 0x5F,
+	STATUS_EN_1        = 0x60,
+	INTERRUPT_EN_0     = 0x61,
+	INTERRUPT_EN_1     = 0x62,
+	INTERRUPT_EN_2     = 0x63,
+	INTERRUPT_EN_3     = 0x64,
+	AGC_TARGET         = 0x67,
+	AGC_CTL            = 0x68,
+	CAPT_RANGE         = 0x75,
+	SNR_SELECT_1       = 0x79,
+	SNR_SELECT_0       = 0x7A,
+	RS_ERR_PER_1       = 0x7C,
+	RS_ERR_PER_0       = 0x7D,
+	CHIP_ID            = 0x7F,
+	CHAN_STOP_1        = 0x80,
+	CHAN_STOP_0        = 0x81,
+	CHAN_STEP_1        = 0x82,
+	CHAN_STEP_0        = 0x83,
+	FEC_LOCK_TIME      = 0x85,
+	OFDM_LOCK_TIME     = 0x86,
+	ACQ_DELAY          = 0x87,
+	SCAN_CTL           = 0x88,
+	CLOCK_CTL          = 0x89,
+	CONFIG             = 0x8A,
+	MCLK_RATIO         = 0x8B,
+	GPP_CTL            = 0x8C,
+	ADC_CTL_1          = 0x8E,
+	ADC_CTL_0          = 0x8F
+};
+
+/* here we assume 1/6MHz == 166.66kHz stepsize */
+#define IF_FREQUENCYx6 217    /* 6 * 36.16666666667MHz */
+
+#endif                          /* _MT352_PRIV_ */
diff --git a/drivers/media/dvb-frontends/nxt200x.c b/drivers/media/dvb-frontends/nxt200x.c
new file mode 100644
index 0000000..8e28894
--- /dev/null
+++ b/drivers/media/dvb-frontends/nxt200x.c
@@ -0,0 +1,1242 @@
+/*
+ *    Support for NXT2002 and NXT2004 - VSB/QAM
+ *
+ *    Copyright (C) 2005 Kirk Lapray <kirk.lapray@gmail.com>
+ *    Copyright (C) 2006 Michael Krufky <mkrufky@m1k.net>
+ *    based on nxt2002 by Taylor Jacob <rtjacob@earthlink.net>
+ *    and nxt2004 by Jean-Francois Thibert <jeanfrancois@sagetv.com>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+*/
+
+/*
+ *                      NOTES ABOUT THIS DRIVER
+ *
+ * This Linux driver supports:
+ *   B2C2/BBTI Technisat Air2PC - ATSC (NXT2002)
+ *   AverTVHD MCE A180 (NXT2004)
+ *   ATI HDTV Wonder (NXT2004)
+ *
+ * This driver needs external firmware. Please use the command
+ * "<kerneldir>/Documentation/dvb/get_dvb_firmware nxt2002" or
+ * "<kerneldir>/Documentation/dvb/get_dvb_firmware nxt2004" to
+ * download/extract the appropriate firmware, and then copy it to
+ * /usr/lib/hotplug/firmware/ or /lib/firmware/
+ * (depending on configuration of firmware hotplug).
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#define NXT2002_DEFAULT_FIRMWARE "dvb-fe-nxt2002.fw"
+#define NXT2004_DEFAULT_FIRMWARE "dvb-fe-nxt2004.fw"
+#define CRC_CCIT_MASK 0x1021
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+
+#include "dvb_frontend.h"
+#include "nxt200x.h"
+
+struct nxt200x_state {
+
+	struct i2c_adapter* i2c;
+	const struct nxt200x_config* config;
+	struct dvb_frontend frontend;
+
+	/* demodulator private data */
+	nxt_chip_type demod_chip;
+	u8 initialised:1;
+};
+
+static int debug;
+#define dprintk(args...)	do { if (debug) pr_debug(args); } while (0)
+
+static int i2c_writebytes (struct nxt200x_state* state, u8 addr, u8 *buf, u8 len)
+{
+	int err;
+	struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = buf, .len = len };
+
+	if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
+		pr_warn("%s: i2c write error (addr 0x%02x, err == %i)\n",
+			__func__, addr, err);
+		return -EREMOTEIO;
+	}
+	return 0;
+}
+
+static int i2c_readbytes(struct nxt200x_state *state, u8 addr, u8 *buf, u8 len)
+{
+	int err;
+	struct i2c_msg msg = { .addr = addr, .flags = I2C_M_RD, .buf = buf, .len = len };
+
+	if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
+		pr_warn("%s: i2c read error (addr 0x%02x, err == %i)\n",
+			__func__, addr, err);
+		return -EREMOTEIO;
+	}
+	return 0;
+}
+
+static int nxt200x_writebytes (struct nxt200x_state* state, u8 reg,
+			       const u8 *buf, u8 len)
+{
+	u8 buf2 [len+1];
+	int err;
+	struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf2, .len = len + 1 };
+
+	buf2[0] = reg;
+	memcpy(&buf2[1], buf, len);
+
+	if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
+		pr_warn("%s: i2c write error (addr 0x%02x, err == %i)\n",
+			__func__, state->config->demod_address, err);
+		return -EREMOTEIO;
+	}
+	return 0;
+}
+
+static int nxt200x_readbytes(struct nxt200x_state *state, u8 reg, u8 *buf, u8 len)
+{
+	u8 reg2 [] = { reg };
+
+	struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = reg2, .len = 1 },
+			{ .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = buf, .len = len } };
+
+	int err;
+
+	if ((err = i2c_transfer (state->i2c, msg, 2)) != 2) {
+		pr_warn("%s: i2c read error (addr 0x%02x, err == %i)\n",
+			__func__, state->config->demod_address, err);
+		return -EREMOTEIO;
+	}
+	return 0;
+}
+
+static u16 nxt200x_crc(u16 crc, u8 c)
+{
+	u8 i;
+	u16 input = (u16) c & 0xFF;
+
+	input<<=8;
+	for(i=0; i<8; i++) {
+		if((crc^input) & 0x8000)
+			crc=(crc<<1)^CRC_CCIT_MASK;
+		else
+			crc<<=1;
+		input<<=1;
+	}
+	return crc;
+}
+
+static int nxt200x_writereg_multibyte (struct nxt200x_state* state, u8 reg, u8* data, u8 len)
+{
+	u8 attr, len2, buf;
+	dprintk("%s\n", __func__);
+
+	/* set mutli register register */
+	nxt200x_writebytes(state, 0x35, &reg, 1);
+
+	/* send the actual data */
+	nxt200x_writebytes(state, 0x36, data, len);
+
+	switch (state->demod_chip) {
+		case NXT2002:
+			len2 = len;
+			buf = 0x02;
+			break;
+		case NXT2004:
+			/* probably not right, but gives correct values */
+			attr = 0x02;
+			if (reg & 0x80) {
+				attr = attr << 1;
+				if (reg & 0x04)
+					attr = attr >> 1;
+			}
+			/* set write bit */
+			len2 = ((attr << 4) | 0x10) | len;
+			buf = 0x80;
+			break;
+		default:
+			return -EINVAL;
+			break;
+	}
+
+	/* set multi register length */
+	nxt200x_writebytes(state, 0x34, &len2, 1);
+
+	/* toggle the multireg write bit */
+	nxt200x_writebytes(state, 0x21, &buf, 1);
+
+	nxt200x_readbytes(state, 0x21, &buf, 1);
+
+	switch (state->demod_chip) {
+		case NXT2002:
+			if ((buf & 0x02) == 0)
+				return 0;
+			break;
+		case NXT2004:
+			if (buf == 0)
+				return 0;
+			break;
+		default:
+			return -EINVAL;
+			break;
+	}
+
+	pr_warn("Error writing multireg register 0x%02X\n", reg);
+
+	return 0;
+}
+
+static int nxt200x_readreg_multibyte (struct nxt200x_state* state, u8 reg, u8* data, u8 len)
+{
+	int i;
+	u8 buf, len2, attr;
+	dprintk("%s\n", __func__);
+
+	/* set mutli register register */
+	nxt200x_writebytes(state, 0x35, &reg, 1);
+
+	switch (state->demod_chip) {
+		case NXT2002:
+			/* set multi register length */
+			len2 = len & 0x80;
+			nxt200x_writebytes(state, 0x34, &len2, 1);
+
+			/* read the actual data */
+			nxt200x_readbytes(state, reg, data, len);
+			return 0;
+			break;
+		case NXT2004:
+			/* probably not right, but gives correct values */
+			attr = 0x02;
+			if (reg & 0x80) {
+				attr = attr << 1;
+				if (reg & 0x04)
+					attr = attr >> 1;
+			}
+
+			/* set multi register length */
+			len2 = (attr << 4) | len;
+			nxt200x_writebytes(state, 0x34, &len2, 1);
+
+			/* toggle the multireg bit*/
+			buf = 0x80;
+			nxt200x_writebytes(state, 0x21, &buf, 1);
+
+			/* read the actual data */
+			for(i = 0; i < len; i++) {
+				nxt200x_readbytes(state, 0x36 + i, &data[i], 1);
+			}
+			return 0;
+			break;
+		default:
+			return -EINVAL;
+			break;
+	}
+}
+
+static void nxt200x_microcontroller_stop (struct nxt200x_state* state)
+{
+	u8 buf, stopval, counter = 0;
+	dprintk("%s\n", __func__);
+
+	/* set correct stop value */
+	switch (state->demod_chip) {
+		case NXT2002:
+			stopval = 0x40;
+			break;
+		case NXT2004:
+			stopval = 0x10;
+			break;
+		default:
+			stopval = 0;
+			break;
+	}
+
+	buf = 0x80;
+	nxt200x_writebytes(state, 0x22, &buf, 1);
+
+	while (counter < 20) {
+		nxt200x_readbytes(state, 0x31, &buf, 1);
+		if (buf & stopval)
+			return;
+		msleep(10);
+		counter++;
+	}
+
+	pr_warn("Timeout waiting for nxt200x to stop. This is ok after "
+		"firmware upload.\n");
+	return;
+}
+
+static void nxt200x_microcontroller_start (struct nxt200x_state* state)
+{
+	u8 buf;
+	dprintk("%s\n", __func__);
+
+	buf = 0x00;
+	nxt200x_writebytes(state, 0x22, &buf, 1);
+}
+
+static void nxt2004_microcontroller_init (struct nxt200x_state* state)
+{
+	u8 buf[9];
+	u8 counter = 0;
+	dprintk("%s\n", __func__);
+
+	buf[0] = 0x00;
+	nxt200x_writebytes(state, 0x2b, buf, 1);
+	buf[0] = 0x70;
+	nxt200x_writebytes(state, 0x34, buf, 1);
+	buf[0] = 0x04;
+	nxt200x_writebytes(state, 0x35, buf, 1);
+	buf[0] = 0x01; buf[1] = 0x23; buf[2] = 0x45; buf[3] = 0x67; buf[4] = 0x89;
+	buf[5] = 0xAB; buf[6] = 0xCD; buf[7] = 0xEF; buf[8] = 0xC0;
+	nxt200x_writebytes(state, 0x36, buf, 9);
+	buf[0] = 0x80;
+	nxt200x_writebytes(state, 0x21, buf, 1);
+
+	while (counter < 20) {
+		nxt200x_readbytes(state, 0x21, buf, 1);
+		if (buf[0] == 0)
+			return;
+		msleep(10);
+		counter++;
+	}
+
+	pr_warn("Timeout waiting for nxt2004 to init.\n");
+
+	return;
+}
+
+static int nxt200x_writetuner (struct nxt200x_state* state, u8* data)
+{
+	u8 buf, count = 0;
+
+	dprintk("%s\n", __func__);
+
+	dprintk("Tuner Bytes: %*ph\n", 4, data + 1);
+
+	/* if NXT2004, write directly to tuner. if NXT2002, write through NXT chip.
+	 * direct write is required for Philips TUV1236D and ALPS TDHU2 */
+	switch (state->demod_chip) {
+		case NXT2004:
+			if (i2c_writebytes(state, data[0], data+1, 4))
+				pr_warn("error writing to tuner\n");
+			/* wait until we have a lock */
+			while (count < 20) {
+				i2c_readbytes(state, data[0], &buf, 1);
+				if (buf & 0x40)
+					return 0;
+				msleep(100);
+				count++;
+			}
+			pr_warn("timeout waiting for tuner lock\n");
+			break;
+		case NXT2002:
+			/* set the i2c transfer speed to the tuner */
+			buf = 0x03;
+			nxt200x_writebytes(state, 0x20, &buf, 1);
+
+			/* setup to transfer 4 bytes via i2c */
+			buf = 0x04;
+			nxt200x_writebytes(state, 0x34, &buf, 1);
+
+			/* write actual tuner bytes */
+			nxt200x_writebytes(state, 0x36, data+1, 4);
+
+			/* set tuner i2c address */
+			buf = data[0] << 1;
+			nxt200x_writebytes(state, 0x35, &buf, 1);
+
+			/* write UC Opmode to begin transfer */
+			buf = 0x80;
+			nxt200x_writebytes(state, 0x21, &buf, 1);
+
+			while (count < 20) {
+				nxt200x_readbytes(state, 0x21, &buf, 1);
+				if ((buf & 0x80)== 0x00)
+					return 0;
+				msleep(100);
+				count++;
+			}
+			pr_warn("timeout error writing to tuner\n");
+			break;
+		default:
+			return -EINVAL;
+			break;
+	}
+	return 0;
+}
+
+static void nxt200x_agc_reset(struct nxt200x_state* state)
+{
+	u8 buf;
+	dprintk("%s\n", __func__);
+
+	switch (state->demod_chip) {
+		case NXT2002:
+			buf = 0x08;
+			nxt200x_writebytes(state, 0x08, &buf, 1);
+			buf = 0x00;
+			nxt200x_writebytes(state, 0x08, &buf, 1);
+			break;
+		case NXT2004:
+			nxt200x_readreg_multibyte(state, 0x08, &buf, 1);
+			buf = 0x08;
+			nxt200x_writereg_multibyte(state, 0x08, &buf, 1);
+			buf = 0x00;
+			nxt200x_writereg_multibyte(state, 0x08, &buf, 1);
+			break;
+		default:
+			break;
+	}
+	return;
+}
+
+static int nxt2002_load_firmware (struct dvb_frontend* fe, const struct firmware *fw)
+{
+
+	struct nxt200x_state* state = fe->demodulator_priv;
+	u8 buf[3], written = 0, chunkpos = 0;
+	u16 rambase, position, crc = 0;
+
+	dprintk("%s\n", __func__);
+	dprintk("Firmware is %zu bytes\n", fw->size);
+
+	/* Get the RAM base for this nxt2002 */
+	nxt200x_readbytes(state, 0x10, buf, 1);
+
+	if (buf[0] & 0x10)
+		rambase = 0x1000;
+	else
+		rambase = 0x0000;
+
+	dprintk("rambase on this nxt2002 is %04X\n", rambase);
+
+	/* Hold the micro in reset while loading firmware */
+	buf[0] = 0x80;
+	nxt200x_writebytes(state, 0x2B, buf, 1);
+
+	for (position = 0; position < fw->size; position++) {
+		if (written == 0) {
+			crc = 0;
+			chunkpos = 0x28;
+			buf[0] = ((rambase + position) >> 8);
+			buf[1] = (rambase + position) & 0xFF;
+			buf[2] = 0x81;
+			/* write starting address */
+			nxt200x_writebytes(state, 0x29, buf, 3);
+		}
+		written++;
+		chunkpos++;
+
+		if ((written % 4) == 0)
+			nxt200x_writebytes(state, chunkpos, &fw->data[position-3], 4);
+
+		crc = nxt200x_crc(crc, fw->data[position]);
+
+		if ((written == 255) || (position+1 == fw->size)) {
+			/* write remaining bytes of firmware */
+			nxt200x_writebytes(state, chunkpos+4-(written %4),
+				&fw->data[position-(written %4) + 1],
+				written %4);
+			buf[0] = crc << 8;
+			buf[1] = crc & 0xFF;
+
+			/* write crc */
+			nxt200x_writebytes(state, 0x2C, buf, 2);
+
+			/* do a read to stop things */
+			nxt200x_readbytes(state, 0x2A, buf, 1);
+
+			/* set transfer mode to complete */
+			buf[0] = 0x80;
+			nxt200x_writebytes(state, 0x2B, buf, 1);
+
+			written = 0;
+		}
+	}
+
+	return 0;
+};
+
+static int nxt2004_load_firmware (struct dvb_frontend* fe, const struct firmware *fw)
+{
+
+	struct nxt200x_state* state = fe->demodulator_priv;
+	u8 buf[3];
+	u16 rambase, position, crc=0;
+
+	dprintk("%s\n", __func__);
+	dprintk("Firmware is %zu bytes\n", fw->size);
+
+	/* set rambase */
+	rambase = 0x1000;
+
+	/* hold the micro in reset while loading firmware */
+	buf[0] = 0x80;
+	nxt200x_writebytes(state, 0x2B, buf,1);
+
+	/* calculate firmware CRC */
+	for (position = 0; position < fw->size; position++) {
+		crc = nxt200x_crc(crc, fw->data[position]);
+	}
+
+	buf[0] = rambase >> 8;
+	buf[1] = rambase & 0xFF;
+	buf[2] = 0x81;
+	/* write starting address */
+	nxt200x_writebytes(state,0x29,buf,3);
+
+	for (position = 0; position < fw->size;) {
+		nxt200x_writebytes(state, 0x2C, &fw->data[position],
+			fw->size-position > 255 ? 255 : fw->size-position);
+		position += (fw->size-position > 255 ? 255 : fw->size-position);
+	}
+	buf[0] = crc >> 8;
+	buf[1] = crc & 0xFF;
+
+	dprintk("firmware crc is 0x%02X 0x%02X\n", buf[0], buf[1]);
+
+	/* write crc */
+	nxt200x_writebytes(state, 0x2C, buf,2);
+
+	/* do a read to stop things */
+	nxt200x_readbytes(state, 0x2C, buf, 1);
+
+	/* set transfer mode to complete */
+	buf[0] = 0x80;
+	nxt200x_writebytes(state, 0x2B, buf,1);
+
+	return 0;
+};
+
+static int nxt200x_setup_frontend_parameters(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct nxt200x_state* state = fe->demodulator_priv;
+	u8 buf[5];
+
+	/* stop the micro first */
+	nxt200x_microcontroller_stop(state);
+
+	if (state->demod_chip == NXT2004) {
+		/* make sure demod is set to digital */
+		buf[0] = 0x04;
+		nxt200x_writebytes(state, 0x14, buf, 1);
+		buf[0] = 0x00;
+		nxt200x_writebytes(state, 0x17, buf, 1);
+	}
+
+	/* set additional params */
+	switch (p->modulation) {
+		case QAM_64:
+		case QAM_256:
+			/* Set punctured clock for QAM */
+			/* This is just a guess since I am unable to test it */
+			if (state->config->set_ts_params)
+				state->config->set_ts_params(fe, 1);
+			break;
+		case VSB_8:
+			/* Set non-punctured clock for VSB */
+			if (state->config->set_ts_params)
+				state->config->set_ts_params(fe, 0);
+			break;
+		default:
+			return -EINVAL;
+			break;
+	}
+
+	if (fe->ops.tuner_ops.calc_regs) {
+		/* get tuning information */
+		fe->ops.tuner_ops.calc_regs(fe, buf, 5);
+
+		/* write frequency information */
+		nxt200x_writetuner(state, buf);
+	}
+
+	/* reset the agc now that tuning has been completed */
+	nxt200x_agc_reset(state);
+
+	/* set target power level */
+	switch (p->modulation) {
+		case QAM_64:
+		case QAM_256:
+			buf[0] = 0x74;
+			break;
+		case VSB_8:
+			buf[0] = 0x70;
+			break;
+		default:
+			return -EINVAL;
+			break;
+	}
+	nxt200x_writebytes(state, 0x42, buf, 1);
+
+	/* configure sdm */
+	switch (state->demod_chip) {
+		case NXT2002:
+			buf[0] = 0x87;
+			break;
+		case NXT2004:
+			buf[0] = 0x07;
+			break;
+		default:
+			return -EINVAL;
+			break;
+	}
+	nxt200x_writebytes(state, 0x57, buf, 1);
+
+	/* write sdm1 input */
+	buf[0] = 0x10;
+	buf[1] = 0x00;
+	switch (state->demod_chip) {
+		case NXT2002:
+			nxt200x_writereg_multibyte(state, 0x58, buf, 2);
+			break;
+		case NXT2004:
+			nxt200x_writebytes(state, 0x58, buf, 2);
+			break;
+		default:
+			return -EINVAL;
+			break;
+	}
+
+	/* write sdmx input */
+	switch (p->modulation) {
+		case QAM_64:
+				buf[0] = 0x68;
+				break;
+		case QAM_256:
+				buf[0] = 0x64;
+				break;
+		case VSB_8:
+				buf[0] = 0x60;
+				break;
+		default:
+				return -EINVAL;
+				break;
+	}
+	buf[1] = 0x00;
+	switch (state->demod_chip) {
+		case NXT2002:
+			nxt200x_writereg_multibyte(state, 0x5C, buf, 2);
+			break;
+		case NXT2004:
+			nxt200x_writebytes(state, 0x5C, buf, 2);
+			break;
+		default:
+			return -EINVAL;
+			break;
+	}
+
+	/* write adc power lpf fc */
+	buf[0] = 0x05;
+	nxt200x_writebytes(state, 0x43, buf, 1);
+
+	if (state->demod_chip == NXT2004) {
+		/* write ??? */
+		buf[0] = 0x00;
+		buf[1] = 0x00;
+		nxt200x_writebytes(state, 0x46, buf, 2);
+	}
+
+	/* write accumulator2 input */
+	buf[0] = 0x80;
+	buf[1] = 0x00;
+	switch (state->demod_chip) {
+		case NXT2002:
+			nxt200x_writereg_multibyte(state, 0x4B, buf, 2);
+			break;
+		case NXT2004:
+			nxt200x_writebytes(state, 0x4B, buf, 2);
+			break;
+		default:
+			return -EINVAL;
+			break;
+	}
+
+	/* write kg1 */
+	buf[0] = 0x00;
+	nxt200x_writebytes(state, 0x4D, buf, 1);
+
+	/* write sdm12 lpf fc */
+	buf[0] = 0x44;
+	nxt200x_writebytes(state, 0x55, buf, 1);
+
+	/* write agc control reg */
+	buf[0] = 0x04;
+	nxt200x_writebytes(state, 0x41, buf, 1);
+
+	if (state->demod_chip == NXT2004) {
+		nxt200x_readreg_multibyte(state, 0x80, buf, 1);
+		buf[0] = 0x24;
+		nxt200x_writereg_multibyte(state, 0x80, buf, 1);
+
+		/* soft reset? */
+		nxt200x_readreg_multibyte(state, 0x08, buf, 1);
+		buf[0] = 0x10;
+		nxt200x_writereg_multibyte(state, 0x08, buf, 1);
+		nxt200x_readreg_multibyte(state, 0x08, buf, 1);
+		buf[0] = 0x00;
+		nxt200x_writereg_multibyte(state, 0x08, buf, 1);
+
+		nxt200x_readreg_multibyte(state, 0x80, buf, 1);
+		buf[0] = 0x04;
+		nxt200x_writereg_multibyte(state, 0x80, buf, 1);
+		buf[0] = 0x00;
+		nxt200x_writereg_multibyte(state, 0x81, buf, 1);
+		buf[0] = 0x80; buf[1] = 0x00; buf[2] = 0x00;
+		nxt200x_writereg_multibyte(state, 0x82, buf, 3);
+		nxt200x_readreg_multibyte(state, 0x88, buf, 1);
+		buf[0] = 0x11;
+		nxt200x_writereg_multibyte(state, 0x88, buf, 1);
+		nxt200x_readreg_multibyte(state, 0x80, buf, 1);
+		buf[0] = 0x44;
+		nxt200x_writereg_multibyte(state, 0x80, buf, 1);
+	}
+
+	/* write agc ucgp0 */
+	switch (p->modulation) {
+		case QAM_64:
+				buf[0] = 0x02;
+				break;
+		case QAM_256:
+				buf[0] = 0x03;
+				break;
+		case VSB_8:
+				buf[0] = 0x00;
+				break;
+		default:
+				return -EINVAL;
+				break;
+	}
+	nxt200x_writebytes(state, 0x30, buf, 1);
+
+	/* write agc control reg */
+	buf[0] = 0x00;
+	nxt200x_writebytes(state, 0x41, buf, 1);
+
+	/* write accumulator2 input */
+	buf[0] = 0x80;
+	buf[1] = 0x00;
+	switch (state->demod_chip) {
+		case NXT2002:
+			nxt200x_writereg_multibyte(state, 0x49, buf, 2);
+			nxt200x_writereg_multibyte(state, 0x4B, buf, 2);
+			break;
+		case NXT2004:
+			nxt200x_writebytes(state, 0x49, buf, 2);
+			nxt200x_writebytes(state, 0x4B, buf, 2);
+			break;
+		default:
+			return -EINVAL;
+			break;
+	}
+
+	/* write agc control reg */
+	buf[0] = 0x04;
+	nxt200x_writebytes(state, 0x41, buf, 1);
+
+	nxt200x_microcontroller_start(state);
+
+	if (state->demod_chip == NXT2004) {
+		nxt2004_microcontroller_init(state);
+
+		/* ???? */
+		buf[0] = 0xF0;
+		buf[1] = 0x00;
+		nxt200x_writebytes(state, 0x5C, buf, 2);
+	}
+
+	/* adjacent channel detection should be done here, but I don't
+	have any stations with this need so I cannot test it */
+
+	return 0;
+}
+
+static int nxt200x_read_status(struct dvb_frontend* fe, fe_status_t* status)
+{
+	struct nxt200x_state* state = fe->demodulator_priv;
+	u8 lock;
+	nxt200x_readbytes(state, 0x31, &lock, 1);
+
+	*status = 0;
+	if (lock & 0x20) {
+		*status |= FE_HAS_SIGNAL;
+		*status |= FE_HAS_CARRIER;
+		*status |= FE_HAS_VITERBI;
+		*status |= FE_HAS_SYNC;
+		*status |= FE_HAS_LOCK;
+	}
+	return 0;
+}
+
+static int nxt200x_read_ber(struct dvb_frontend* fe, u32* ber)
+{
+	struct nxt200x_state* state = fe->demodulator_priv;
+	u8 b[3];
+
+	nxt200x_readreg_multibyte(state, 0xE6, b, 3);
+
+	*ber = ((b[0] << 8) + b[1]) * 8;
+
+	return 0;
+}
+
+static int nxt200x_read_signal_strength(struct dvb_frontend* fe, u16* strength)
+{
+	struct nxt200x_state* state = fe->demodulator_priv;
+	u8 b[2];
+	u16 temp = 0;
+
+	/* setup to read cluster variance */
+	b[0] = 0x00;
+	nxt200x_writebytes(state, 0xA1, b, 1);
+
+	/* get multreg val */
+	nxt200x_readreg_multibyte(state, 0xA6, b, 2);
+
+	temp = (b[0] << 8) | b[1];
+	*strength = ((0x7FFF - temp) & 0x0FFF) * 16;
+
+	return 0;
+}
+
+static int nxt200x_read_snr(struct dvb_frontend* fe, u16* snr)
+{
+
+	struct nxt200x_state* state = fe->demodulator_priv;
+	u8 b[2];
+	u16 temp = 0, temp2;
+	u32 snrdb = 0;
+
+	/* setup to read cluster variance */
+	b[0] = 0x00;
+	nxt200x_writebytes(state, 0xA1, b, 1);
+
+	/* get multreg val from 0xA6 */
+	nxt200x_readreg_multibyte(state, 0xA6, b, 2);
+
+	temp = (b[0] << 8) | b[1];
+	temp2 = 0x7FFF - temp;
+
+	/* snr will be in db */
+	if (temp2 > 0x7F00)
+		snrdb = 1000*24 + ( 1000*(30-24) * ( temp2 - 0x7F00 ) / ( 0x7FFF - 0x7F00 ) );
+	else if (temp2 > 0x7EC0)
+		snrdb = 1000*18 + ( 1000*(24-18) * ( temp2 - 0x7EC0 ) / ( 0x7F00 - 0x7EC0 ) );
+	else if (temp2 > 0x7C00)
+		snrdb = 1000*12 + ( 1000*(18-12) * ( temp2 - 0x7C00 ) / ( 0x7EC0 - 0x7C00 ) );
+	else
+		snrdb = 1000*0 + ( 1000*(12-0) * ( temp2 - 0 ) / ( 0x7C00 - 0 ) );
+
+	/* the value reported back from the frontend will be FFFF=32db 0000=0db */
+	*snr = snrdb * (0xFFFF/32000);
+
+	return 0;
+}
+
+static int nxt200x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
+{
+	struct nxt200x_state* state = fe->demodulator_priv;
+	u8 b[3];
+
+	nxt200x_readreg_multibyte(state, 0xE6, b, 3);
+	*ucblocks = b[2];
+
+	return 0;
+}
+
+static int nxt200x_sleep(struct dvb_frontend* fe)
+{
+	return 0;
+}
+
+static int nxt2002_init(struct dvb_frontend* fe)
+{
+	struct nxt200x_state* state = fe->demodulator_priv;
+	const struct firmware *fw;
+	int ret;
+	u8 buf[2];
+
+	/* request the firmware, this will block until someone uploads it */
+	pr_debug("%s: Waiting for firmware upload (%s)...\n",
+		 __func__, NXT2002_DEFAULT_FIRMWARE);
+	ret = request_firmware(&fw, NXT2002_DEFAULT_FIRMWARE,
+			       state->i2c->dev.parent);
+	pr_debug("%s: Waiting for firmware upload(2)...\n", __func__);
+	if (ret) {
+		pr_err("%s: No firmware uploaded (timeout or file not found?)"
+		       "\n", __func__);
+		return ret;
+	}
+
+	ret = nxt2002_load_firmware(fe, fw);
+	release_firmware(fw);
+	if (ret) {
+		pr_err("%s: Writing firmware to device failed\n", __func__);
+		return ret;
+	}
+	pr_info("%s: Firmware upload complete\n", __func__);
+
+	/* Put the micro into reset */
+	nxt200x_microcontroller_stop(state);
+
+	/* ensure transfer is complete */
+	buf[0]=0x00;
+	nxt200x_writebytes(state, 0x2B, buf, 1);
+
+	/* Put the micro into reset for real this time */
+	nxt200x_microcontroller_stop(state);
+
+	/* soft reset everything (agc,frontend,eq,fec)*/
+	buf[0] = 0x0F;
+	nxt200x_writebytes(state, 0x08, buf, 1);
+	buf[0] = 0x00;
+	nxt200x_writebytes(state, 0x08, buf, 1);
+
+	/* write agc sdm configure */
+	buf[0] = 0xF1;
+	nxt200x_writebytes(state, 0x57, buf, 1);
+
+	/* write mod output format */
+	buf[0] = 0x20;
+	nxt200x_writebytes(state, 0x09, buf, 1);
+
+	/* write fec mpeg mode */
+	buf[0] = 0x7E;
+	buf[1] = 0x00;
+	nxt200x_writebytes(state, 0xE9, buf, 2);
+
+	/* write mux selection */
+	buf[0] = 0x00;
+	nxt200x_writebytes(state, 0xCC, buf, 1);
+
+	return 0;
+}
+
+static int nxt2004_init(struct dvb_frontend* fe)
+{
+	struct nxt200x_state* state = fe->demodulator_priv;
+	const struct firmware *fw;
+	int ret;
+	u8 buf[3];
+
+	/* ??? */
+	buf[0]=0x00;
+	nxt200x_writebytes(state, 0x1E, buf, 1);
+
+	/* request the firmware, this will block until someone uploads it */
+	pr_debug("%s: Waiting for firmware upload (%s)...\n",
+		 __func__, NXT2004_DEFAULT_FIRMWARE);
+	ret = request_firmware(&fw, NXT2004_DEFAULT_FIRMWARE,
+			       state->i2c->dev.parent);
+	pr_debug("%s: Waiting for firmware upload(2)...\n", __func__);
+	if (ret) {
+		pr_err("%s: No firmware uploaded (timeout or file not found?)"
+		       "\n", __func__);
+		return ret;
+	}
+
+	ret = nxt2004_load_firmware(fe, fw);
+	release_firmware(fw);
+	if (ret) {
+		pr_err("%s: Writing firmware to device failed\n", __func__);
+		return ret;
+	}
+	pr_info("%s: Firmware upload complete\n", __func__);
+
+	/* ensure transfer is complete */
+	buf[0] = 0x01;
+	nxt200x_writebytes(state, 0x19, buf, 1);
+
+	nxt2004_microcontroller_init(state);
+	nxt200x_microcontroller_stop(state);
+	nxt200x_microcontroller_stop(state);
+	nxt2004_microcontroller_init(state);
+	nxt200x_microcontroller_stop(state);
+
+	/* soft reset everything (agc,frontend,eq,fec)*/
+	buf[0] = 0xFF;
+	nxt200x_writereg_multibyte(state, 0x08, buf, 1);
+	buf[0] = 0x00;
+	nxt200x_writereg_multibyte(state, 0x08, buf, 1);
+
+	/* write agc sdm configure */
+	buf[0] = 0xD7;
+	nxt200x_writebytes(state, 0x57, buf, 1);
+
+	/* ???*/
+	buf[0] = 0x07;
+	buf[1] = 0xfe;
+	nxt200x_writebytes(state, 0x35, buf, 2);
+	buf[0] = 0x12;
+	nxt200x_writebytes(state, 0x34, buf, 1);
+	buf[0] = 0x80;
+	nxt200x_writebytes(state, 0x21, buf, 1);
+
+	/* ???*/
+	buf[0] = 0x21;
+	nxt200x_writebytes(state, 0x0A, buf, 1);
+
+	/* ???*/
+	buf[0] = 0x01;
+	nxt200x_writereg_multibyte(state, 0x80, buf, 1);
+
+	/* write fec mpeg mode */
+	buf[0] = 0x7E;
+	buf[1] = 0x00;
+	nxt200x_writebytes(state, 0xE9, buf, 2);
+
+	/* write mux selection */
+	buf[0] = 0x00;
+	nxt200x_writebytes(state, 0xCC, buf, 1);
+
+	/* ???*/
+	nxt200x_readreg_multibyte(state, 0x80, buf, 1);
+	buf[0] = 0x00;
+	nxt200x_writereg_multibyte(state, 0x80, buf, 1);
+
+	/* soft reset? */
+	nxt200x_readreg_multibyte(state, 0x08, buf, 1);
+	buf[0] = 0x10;
+	nxt200x_writereg_multibyte(state, 0x08, buf, 1);
+	nxt200x_readreg_multibyte(state, 0x08, buf, 1);
+	buf[0] = 0x00;
+	nxt200x_writereg_multibyte(state, 0x08, buf, 1);
+
+	/* ???*/
+	nxt200x_readreg_multibyte(state, 0x80, buf, 1);
+	buf[0] = 0x01;
+	nxt200x_writereg_multibyte(state, 0x80, buf, 1);
+	buf[0] = 0x70;
+	nxt200x_writereg_multibyte(state, 0x81, buf, 1);
+	buf[0] = 0x31; buf[1] = 0x5E; buf[2] = 0x66;
+	nxt200x_writereg_multibyte(state, 0x82, buf, 3);
+
+	nxt200x_readreg_multibyte(state, 0x88, buf, 1);
+	buf[0] = 0x11;
+	nxt200x_writereg_multibyte(state, 0x88, buf, 1);
+	nxt200x_readreg_multibyte(state, 0x80, buf, 1);
+	buf[0] = 0x40;
+	nxt200x_writereg_multibyte(state, 0x80, buf, 1);
+
+	nxt200x_readbytes(state, 0x10, buf, 1);
+	buf[0] = 0x10;
+	nxt200x_writebytes(state, 0x10, buf, 1);
+	nxt200x_readbytes(state, 0x0A, buf, 1);
+	buf[0] = 0x21;
+	nxt200x_writebytes(state, 0x0A, buf, 1);
+
+	nxt2004_microcontroller_init(state);
+
+	buf[0] = 0x21;
+	nxt200x_writebytes(state, 0x0A, buf, 1);
+	buf[0] = 0x7E;
+	nxt200x_writebytes(state, 0xE9, buf, 1);
+	buf[0] = 0x00;
+	nxt200x_writebytes(state, 0xEA, buf, 1);
+
+	nxt200x_readreg_multibyte(state, 0x80, buf, 1);
+	buf[0] = 0x00;
+	nxt200x_writereg_multibyte(state, 0x80, buf, 1);
+	nxt200x_readreg_multibyte(state, 0x80, buf, 1);
+	buf[0] = 0x00;
+	nxt200x_writereg_multibyte(state, 0x80, buf, 1);
+
+	/* soft reset? */
+	nxt200x_readreg_multibyte(state, 0x08, buf, 1);
+	buf[0] = 0x10;
+	nxt200x_writereg_multibyte(state, 0x08, buf, 1);
+	nxt200x_readreg_multibyte(state, 0x08, buf, 1);
+	buf[0] = 0x00;
+	nxt200x_writereg_multibyte(state, 0x08, buf, 1);
+
+	nxt200x_readreg_multibyte(state, 0x80, buf, 1);
+	buf[0] = 0x04;
+	nxt200x_writereg_multibyte(state, 0x80, buf, 1);
+	buf[0] = 0x00;
+	nxt200x_writereg_multibyte(state, 0x81, buf, 1);
+	buf[0] = 0x80; buf[1] = 0x00; buf[2] = 0x00;
+	nxt200x_writereg_multibyte(state, 0x82, buf, 3);
+
+	nxt200x_readreg_multibyte(state, 0x88, buf, 1);
+	buf[0] = 0x11;
+	nxt200x_writereg_multibyte(state, 0x88, buf, 1);
+
+	nxt200x_readreg_multibyte(state, 0x80, buf, 1);
+	buf[0] = 0x44;
+	nxt200x_writereg_multibyte(state, 0x80, buf, 1);
+
+	/* initialize tuner */
+	nxt200x_readbytes(state, 0x10, buf, 1);
+	buf[0] = 0x12;
+	nxt200x_writebytes(state, 0x10, buf, 1);
+	buf[0] = 0x04;
+	nxt200x_writebytes(state, 0x13, buf, 1);
+	buf[0] = 0x00;
+	nxt200x_writebytes(state, 0x16, buf, 1);
+	buf[0] = 0x04;
+	nxt200x_writebytes(state, 0x14, buf, 1);
+	buf[0] = 0x00;
+	nxt200x_writebytes(state, 0x14, buf, 1);
+	nxt200x_writebytes(state, 0x17, buf, 1);
+	nxt200x_writebytes(state, 0x14, buf, 1);
+	nxt200x_writebytes(state, 0x17, buf, 1);
+
+	return 0;
+}
+
+static int nxt200x_init(struct dvb_frontend* fe)
+{
+	struct nxt200x_state* state = fe->demodulator_priv;
+	int ret = 0;
+
+	if (!state->initialised) {
+		switch (state->demod_chip) {
+			case NXT2002:
+				ret = nxt2002_init(fe);
+				break;
+			case NXT2004:
+				ret = nxt2004_init(fe);
+				break;
+			default:
+				return -EINVAL;
+				break;
+		}
+		state->initialised = 1;
+	}
+	return ret;
+}
+
+static int nxt200x_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings)
+{
+	fesettings->min_delay_ms = 500;
+	fesettings->step_size = 0;
+	fesettings->max_drift = 0;
+	return 0;
+}
+
+static void nxt200x_release(struct dvb_frontend* fe)
+{
+	struct nxt200x_state* state = fe->demodulator_priv;
+	kfree(state);
+}
+
+static struct dvb_frontend_ops nxt200x_ops;
+
+struct dvb_frontend* nxt200x_attach(const struct nxt200x_config* config,
+				   struct i2c_adapter* i2c)
+{
+	struct nxt200x_state* state = NULL;
+	u8 buf [] = {0,0,0,0,0};
+
+	/* allocate memory for the internal state */
+	state = kzalloc(sizeof(struct nxt200x_state), GFP_KERNEL);
+	if (state == NULL)
+		goto error;
+
+	/* setup the state */
+	state->config = config;
+	state->i2c = i2c;
+	state->initialised = 0;
+
+	/* read card id */
+	nxt200x_readbytes(state, 0x00, buf, 5);
+	dprintk("NXT info: %*ph\n", 5, buf);
+
+	/* set demod chip */
+	switch (buf[0]) {
+		case 0x04:
+			state->demod_chip = NXT2002;
+			pr_info("NXT2002 Detected\n");
+			break;
+		case 0x05:
+			state->demod_chip = NXT2004;
+			pr_info("NXT2004 Detected\n");
+			break;
+		default:
+			goto error;
+	}
+
+	/* make sure demod chip is supported */
+	switch (state->demod_chip) {
+		case NXT2002:
+			if (buf[0] != 0x04) goto error;		/* device id */
+			if (buf[1] != 0x02) goto error;		/* fab id */
+			if (buf[2] != 0x11) goto error;		/* month */
+			if (buf[3] != 0x20) goto error;		/* year msb */
+			if (buf[4] != 0x00) goto error;		/* year lsb */
+			break;
+		case NXT2004:
+			if (buf[0] != 0x05) goto error;		/* device id */
+			break;
+		default:
+			goto error;
+	}
+
+	/* create dvb_frontend */
+	memcpy(&state->frontend.ops, &nxt200x_ops, sizeof(struct dvb_frontend_ops));
+	state->frontend.demodulator_priv = state;
+	return &state->frontend;
+
+error:
+	kfree(state);
+	pr_err("Unknown/Unsupported NXT chip: %*ph\n", 5, buf);
+	return NULL;
+}
+
+static struct dvb_frontend_ops nxt200x_ops = {
+	.delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
+	.info = {
+		.name = "Nextwave NXT200X VSB/QAM frontend",
+		.frequency_min =  54000000,
+		.frequency_max = 860000000,
+		.frequency_stepsize = 166666,	/* stepsize is just a guess */
+		.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_FEC_AUTO |
+			FE_CAN_8VSB | FE_CAN_QAM_64 | FE_CAN_QAM_256
+	},
+
+	.release = nxt200x_release,
+
+	.init = nxt200x_init,
+	.sleep = nxt200x_sleep,
+
+	.set_frontend = nxt200x_setup_frontend_parameters,
+	.get_tune_settings = nxt200x_get_tune_settings,
+
+	.read_status = nxt200x_read_status,
+	.read_ber = nxt200x_read_ber,
+	.read_signal_strength = nxt200x_read_signal_strength,
+	.read_snr = nxt200x_read_snr,
+	.read_ucblocks = nxt200x_read_ucblocks,
+};
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+
+MODULE_DESCRIPTION("NXT200X (ATSC 8VSB & ITU-T J.83 AnnexB 64/256 QAM) Demodulator Driver");
+MODULE_AUTHOR("Kirk Lapray, Michael Krufky, Jean-Francois Thibert, and Taylor Jacob");
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(nxt200x_attach);
+
diff --git a/drivers/media/dvb-frontends/nxt200x.h b/drivers/media/dvb-frontends/nxt200x.h
new file mode 100644
index 0000000..f3c8458
--- /dev/null
+++ b/drivers/media/dvb-frontends/nxt200x.h
@@ -0,0 +1,63 @@
+/*
+ *    Support for NXT2002 and NXT2004 - VSB/QAM
+ *
+ *    Copyright (C) 2005 Kirk Lapray (kirk.lapray@gmail.com)
+ *    based on nxt2002 by Taylor Jacob <rtjacob@earthlink.net>
+ *    and nxt2004 by Jean-Francois Thibert (jeanfrancois@sagetv.com)
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+*/
+
+#ifndef NXT200X_H
+#define NXT200X_H
+
+#include <linux/dvb/frontend.h>
+#include <linux/firmware.h>
+
+typedef enum nxt_chip_t {
+		NXTUNDEFINED,
+		NXT2002,
+		NXT2004
+}nxt_chip_type;
+
+struct nxt200x_config
+{
+	/* the demodulator's i2c address */
+	u8 demod_address;
+
+	/* need to set device param for start_dma */
+	int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured);
+};
+
+#if defined(CONFIG_DVB_NXT200X) || (defined(CONFIG_DVB_NXT200X_MODULE) && defined(MODULE))
+extern struct dvb_frontend* nxt200x_attach(const struct nxt200x_config* config,
+					   struct i2c_adapter* i2c);
+#else
+static inline struct dvb_frontend* nxt200x_attach(const struct nxt200x_config* config,
+					   struct i2c_adapter* i2c)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif // CONFIG_DVB_NXT200X
+
+#endif /* NXT200X_H */
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/dvb-frontends/nxt6000.c b/drivers/media/dvb-frontends/nxt6000.c
new file mode 100644
index 0000000..90ae6c7
--- /dev/null
+++ b/drivers/media/dvb-frontends/nxt6000.c
@@ -0,0 +1,616 @@
+/*
+	NxtWave Communications - NXT6000 demodulator driver
+
+    Copyright (C) 2002-2003 Florian Schirmer <jolt@tuxbox.org>
+    Copyright (C) 2003 Paul Andreassen <paul@andreassen.com.au>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You 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/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+
+#include "dvb_frontend.h"
+#include "nxt6000_priv.h"
+#include "nxt6000.h"
+
+
+
+struct nxt6000_state {
+	struct i2c_adapter* i2c;
+	/* configuration settings */
+	const struct nxt6000_config* config;
+	struct dvb_frontend frontend;
+};
+
+static int debug;
+#define dprintk if (debug) printk
+
+static int nxt6000_writereg(struct nxt6000_state* state, u8 reg, u8 data)
+{
+	u8 buf[] = { reg, data };
+	struct i2c_msg msg = {.addr = state->config->demod_address,.flags = 0,.buf = buf,.len = 2 };
+	int ret;
+
+	if ((ret = i2c_transfer(state->i2c, &msg, 1)) != 1)
+		dprintk("nxt6000: nxt6000_write error (reg: 0x%02X, data: 0x%02X, ret: %d)\n", reg, data, ret);
+
+	return (ret != 1) ? -EIO : 0;
+}
+
+static u8 nxt6000_readreg(struct nxt6000_state* state, u8 reg)
+{
+	int ret;
+	u8 b0[] = { reg };
+	u8 b1[] = { 0 };
+	struct i2c_msg msgs[] = {
+		{.addr = state->config->demod_address,.flags = 0,.buf = b0,.len = 1},
+		{.addr = state->config->demod_address,.flags = I2C_M_RD,.buf = b1,.len = 1}
+	};
+
+	ret = i2c_transfer(state->i2c, msgs, 2);
+
+	if (ret != 2)
+		dprintk("nxt6000: nxt6000_read error (reg: 0x%02X, ret: %d)\n", reg, ret);
+
+	return b1[0];
+}
+
+static void nxt6000_reset(struct nxt6000_state* state)
+{
+	u8 val;
+
+	val = nxt6000_readreg(state, OFDM_COR_CTL);
+
+	nxt6000_writereg(state, OFDM_COR_CTL, val & ~COREACT);
+	nxt6000_writereg(state, OFDM_COR_CTL, val | COREACT);
+}
+
+static int nxt6000_set_bandwidth(struct nxt6000_state *state, u32 bandwidth)
+{
+	u16 nominal_rate;
+	int result;
+
+	switch (bandwidth) {
+	case 6000000:
+		nominal_rate = 0x55B7;
+		break;
+
+	case 7000000:
+		nominal_rate = 0x6400;
+		break;
+
+	case 8000000:
+		nominal_rate = 0x7249;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	if ((result = nxt6000_writereg(state, OFDM_TRL_NOMINALRATE_1, nominal_rate & 0xFF)) < 0)
+		return result;
+
+	return nxt6000_writereg(state, OFDM_TRL_NOMINALRATE_2, (nominal_rate >> 8) & 0xFF);
+}
+
+static int nxt6000_set_guard_interval(struct nxt6000_state* state, fe_guard_interval_t guard_interval)
+{
+	switch (guard_interval) {
+
+	case GUARD_INTERVAL_1_32:
+		return nxt6000_writereg(state, OFDM_COR_MODEGUARD, 0x00 | (nxt6000_readreg(state, OFDM_COR_MODEGUARD) & ~0x03));
+
+	case GUARD_INTERVAL_1_16:
+		return nxt6000_writereg(state, OFDM_COR_MODEGUARD, 0x01 | (nxt6000_readreg(state, OFDM_COR_MODEGUARD) & ~0x03));
+
+	case GUARD_INTERVAL_AUTO:
+	case GUARD_INTERVAL_1_8:
+		return nxt6000_writereg(state, OFDM_COR_MODEGUARD, 0x02 | (nxt6000_readreg(state, OFDM_COR_MODEGUARD) & ~0x03));
+
+	case GUARD_INTERVAL_1_4:
+		return nxt6000_writereg(state, OFDM_COR_MODEGUARD, 0x03 | (nxt6000_readreg(state, OFDM_COR_MODEGUARD) & ~0x03));
+
+	default:
+		return -EINVAL;
+	}
+}
+
+static int nxt6000_set_inversion(struct nxt6000_state* state, fe_spectral_inversion_t inversion)
+{
+	switch (inversion) {
+
+	case INVERSION_OFF:
+		return nxt6000_writereg(state, OFDM_ITB_CTL, 0x00);
+
+	case INVERSION_ON:
+		return nxt6000_writereg(state, OFDM_ITB_CTL, ITBINV);
+
+	default:
+		return -EINVAL;
+
+	}
+}
+
+static int nxt6000_set_transmission_mode(struct nxt6000_state* state, fe_transmit_mode_t transmission_mode)
+{
+	int result;
+
+	switch (transmission_mode) {
+
+	case TRANSMISSION_MODE_2K:
+		if ((result = nxt6000_writereg(state, EN_DMD_RACQ, 0x00 | (nxt6000_readreg(state, EN_DMD_RACQ) & ~0x03))) < 0)
+			return result;
+
+		return nxt6000_writereg(state, OFDM_COR_MODEGUARD, (0x00 << 2) | (nxt6000_readreg(state, OFDM_COR_MODEGUARD) & ~0x04));
+
+	case TRANSMISSION_MODE_8K:
+	case TRANSMISSION_MODE_AUTO:
+		if ((result = nxt6000_writereg(state, EN_DMD_RACQ, 0x02 | (nxt6000_readreg(state, EN_DMD_RACQ) & ~0x03))) < 0)
+			return result;
+
+		return nxt6000_writereg(state, OFDM_COR_MODEGUARD, (0x01 << 2) | (nxt6000_readreg(state, OFDM_COR_MODEGUARD) & ~0x04));
+
+	default:
+		return -EINVAL;
+
+	}
+}
+
+static void nxt6000_setup(struct dvb_frontend* fe)
+{
+	struct nxt6000_state* state = fe->demodulator_priv;
+
+	nxt6000_writereg(state, RS_COR_SYNC_PARAM, SYNC_PARAM);
+	nxt6000_writereg(state, BER_CTRL, /*(1 << 2) | */ (0x01 << 1) | 0x01);
+	nxt6000_writereg(state, VIT_BERTIME_2, 0x00);  // BER Timer = 0x000200 * 256 = 131072 bits
+	nxt6000_writereg(state, VIT_BERTIME_1, 0x02);  //
+	nxt6000_writereg(state, VIT_BERTIME_0, 0x00);  //
+	nxt6000_writereg(state, VIT_COR_INTEN, 0x98); // Enable BER interrupts
+	nxt6000_writereg(state, VIT_COR_CTL, 0x82);   // Enable BER measurement
+	nxt6000_writereg(state, VIT_COR_CTL, VIT_COR_RESYNC | 0x02 );
+	nxt6000_writereg(state, OFDM_COR_CTL, (0x01 << 5) | (nxt6000_readreg(state, OFDM_COR_CTL) & 0x0F));
+	nxt6000_writereg(state, OFDM_COR_MODEGUARD, FORCEMODE8K | 0x02);
+	nxt6000_writereg(state, OFDM_AGC_CTL, AGCLAST | INITIAL_AGC_BW);
+	nxt6000_writereg(state, OFDM_ITB_FREQ_1, 0x06);
+	nxt6000_writereg(state, OFDM_ITB_FREQ_2, 0x31);
+	nxt6000_writereg(state, OFDM_CAS_CTL, (0x01 << 7) | (0x02 << 3) | 0x04);
+	nxt6000_writereg(state, CAS_FREQ, 0xBB);	/* CHECKME */
+	nxt6000_writereg(state, OFDM_SYR_CTL, 1 << 2);
+	nxt6000_writereg(state, OFDM_PPM_CTL_1, PPM256);
+	nxt6000_writereg(state, OFDM_TRL_NOMINALRATE_1, 0x49);
+	nxt6000_writereg(state, OFDM_TRL_NOMINALRATE_2, 0x72);
+	nxt6000_writereg(state, ANALOG_CONTROL_0, 1 << 5);
+	nxt6000_writereg(state, EN_DMD_RACQ, (1 << 7) | (3 << 4) | 2);
+	nxt6000_writereg(state, DIAG_CONFIG, TB_SET);
+
+	if (state->config->clock_inversion)
+		nxt6000_writereg(state, SUB_DIAG_MODE_SEL, CLKINVERSION);
+	else
+		nxt6000_writereg(state, SUB_DIAG_MODE_SEL, 0);
+
+	nxt6000_writereg(state, TS_FORMAT, 0);
+}
+
+static void nxt6000_dump_status(struct nxt6000_state *state)
+{
+	u8 val;
+
+/*
+	printk("RS_COR_STAT: 0x%02X\n", nxt6000_readreg(fe, RS_COR_STAT));
+	printk("VIT_SYNC_STATUS: 0x%02X\n", nxt6000_readreg(fe, VIT_SYNC_STATUS));
+	printk("OFDM_COR_STAT: 0x%02X\n", nxt6000_readreg(fe, OFDM_COR_STAT));
+	printk("OFDM_SYR_STAT: 0x%02X\n", nxt6000_readreg(fe, OFDM_SYR_STAT));
+	printk("OFDM_TPS_RCVD_1: 0x%02X\n", nxt6000_readreg(fe, OFDM_TPS_RCVD_1));
+	printk("OFDM_TPS_RCVD_2: 0x%02X\n", nxt6000_readreg(fe, OFDM_TPS_RCVD_2));
+	printk("OFDM_TPS_RCVD_3: 0x%02X\n", nxt6000_readreg(fe, OFDM_TPS_RCVD_3));
+	printk("OFDM_TPS_RCVD_4: 0x%02X\n", nxt6000_readreg(fe, OFDM_TPS_RCVD_4));
+	printk("OFDM_TPS_RESERVED_1: 0x%02X\n", nxt6000_readreg(fe, OFDM_TPS_RESERVED_1));
+	printk("OFDM_TPS_RESERVED_2: 0x%02X\n", nxt6000_readreg(fe, OFDM_TPS_RESERVED_2));
+*/
+	printk("NXT6000 status:");
+
+	val = nxt6000_readreg(state, RS_COR_STAT);
+
+	printk(" DATA DESCR LOCK: %d,", val & 0x01);
+	printk(" DATA SYNC LOCK: %d,", (val >> 1) & 0x01);
+
+	val = nxt6000_readreg(state, VIT_SYNC_STATUS);
+
+	printk(" VITERBI LOCK: %d,", (val >> 7) & 0x01);
+
+	switch ((val >> 4) & 0x07) {
+
+	case 0x00:
+		printk(" VITERBI CODERATE: 1/2,");
+		break;
+
+	case 0x01:
+		printk(" VITERBI CODERATE: 2/3,");
+		break;
+
+	case 0x02:
+		printk(" VITERBI CODERATE: 3/4,");
+		break;
+
+	case 0x03:
+		printk(" VITERBI CODERATE: 5/6,");
+		break;
+
+	case 0x04:
+		printk(" VITERBI CODERATE: 7/8,");
+		break;
+
+	default:
+		printk(" VITERBI CODERATE: Reserved,");
+
+	}
+
+	val = nxt6000_readreg(state, OFDM_COR_STAT);
+
+	printk(" CHCTrack: %d,", (val >> 7) & 0x01);
+	printk(" TPSLock: %d,", (val >> 6) & 0x01);
+	printk(" SYRLock: %d,", (val >> 5) & 0x01);
+	printk(" AGCLock: %d,", (val >> 4) & 0x01);
+
+	switch (val & 0x0F) {
+
+	case 0x00:
+		printk(" CoreState: IDLE,");
+		break;
+
+	case 0x02:
+		printk(" CoreState: WAIT_AGC,");
+		break;
+
+	case 0x03:
+		printk(" CoreState: WAIT_SYR,");
+		break;
+
+	case 0x04:
+		printk(" CoreState: WAIT_PPM,");
+		break;
+
+	case 0x01:
+		printk(" CoreState: WAIT_TRL,");
+		break;
+
+	case 0x05:
+		printk(" CoreState: WAIT_TPS,");
+		break;
+
+	case 0x06:
+		printk(" CoreState: MONITOR_TPS,");
+		break;
+
+	default:
+		printk(" CoreState: Reserved,");
+
+	}
+
+	val = nxt6000_readreg(state, OFDM_SYR_STAT);
+
+	printk(" SYRLock: %d,", (val >> 4) & 0x01);
+	printk(" SYRMode: %s,", (val >> 2) & 0x01 ? "8K" : "2K");
+
+	switch ((val >> 4) & 0x03) {
+
+	case 0x00:
+		printk(" SYRGuard: 1/32,");
+		break;
+
+	case 0x01:
+		printk(" SYRGuard: 1/16,");
+		break;
+
+	case 0x02:
+		printk(" SYRGuard: 1/8,");
+		break;
+
+	case 0x03:
+		printk(" SYRGuard: 1/4,");
+		break;
+	}
+
+	val = nxt6000_readreg(state, OFDM_TPS_RCVD_3);
+
+	switch ((val >> 4) & 0x07) {
+
+	case 0x00:
+		printk(" TPSLP: 1/2,");
+		break;
+
+	case 0x01:
+		printk(" TPSLP: 2/3,");
+		break;
+
+	case 0x02:
+		printk(" TPSLP: 3/4,");
+		break;
+
+	case 0x03:
+		printk(" TPSLP: 5/6,");
+		break;
+
+	case 0x04:
+		printk(" TPSLP: 7/8,");
+		break;
+
+	default:
+		printk(" TPSLP: Reserved,");
+
+	}
+
+	switch (val & 0x07) {
+
+	case 0x00:
+		printk(" TPSHP: 1/2,");
+		break;
+
+	case 0x01:
+		printk(" TPSHP: 2/3,");
+		break;
+
+	case 0x02:
+		printk(" TPSHP: 3/4,");
+		break;
+
+	case 0x03:
+		printk(" TPSHP: 5/6,");
+		break;
+
+	case 0x04:
+		printk(" TPSHP: 7/8,");
+		break;
+
+	default:
+		printk(" TPSHP: Reserved,");
+
+	}
+
+	val = nxt6000_readreg(state, OFDM_TPS_RCVD_4);
+
+	printk(" TPSMode: %s,", val & 0x01 ? "8K" : "2K");
+
+	switch ((val >> 4) & 0x03) {
+
+	case 0x00:
+		printk(" TPSGuard: 1/32,");
+		break;
+
+	case 0x01:
+		printk(" TPSGuard: 1/16,");
+		break;
+
+	case 0x02:
+		printk(" TPSGuard: 1/8,");
+		break;
+
+	case 0x03:
+		printk(" TPSGuard: 1/4,");
+		break;
+
+	}
+
+	/* Strange magic required to gain access to RF_AGC_STATUS */
+	nxt6000_readreg(state, RF_AGC_VAL_1);
+	val = nxt6000_readreg(state, RF_AGC_STATUS);
+	val = nxt6000_readreg(state, RF_AGC_STATUS);
+
+	printk(" RF AGC LOCK: %d,", (val >> 4) & 0x01);
+	printk("\n");
+}
+
+static int nxt6000_read_status(struct dvb_frontend* fe, fe_status_t* status)
+{
+	u8 core_status;
+	struct nxt6000_state* state = fe->demodulator_priv;
+
+	*status = 0;
+
+	core_status = nxt6000_readreg(state, OFDM_COR_STAT);
+
+	if (core_status & AGCLOCKED)
+		*status |= FE_HAS_SIGNAL;
+
+	if (nxt6000_readreg(state, OFDM_SYR_STAT) & GI14_SYR_LOCK)
+		*status |= FE_HAS_CARRIER;
+
+	if (nxt6000_readreg(state, VIT_SYNC_STATUS) & VITINSYNC)
+		*status |= FE_HAS_VITERBI;
+
+	if (nxt6000_readreg(state, RS_COR_STAT) & RSCORESTATUS)
+		*status |= FE_HAS_SYNC;
+
+	if ((core_status & TPSLOCKED) && (*status == (FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC)))
+		*status |= FE_HAS_LOCK;
+
+	if (debug)
+		nxt6000_dump_status(state);
+
+	return 0;
+}
+
+static int nxt6000_init(struct dvb_frontend* fe)
+{
+	struct nxt6000_state* state = fe->demodulator_priv;
+
+	nxt6000_reset(state);
+	nxt6000_setup(fe);
+
+	return 0;
+}
+
+static int nxt6000_set_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct nxt6000_state* state = fe->demodulator_priv;
+	int result;
+
+	if (fe->ops.tuner_ops.set_params) {
+		fe->ops.tuner_ops.set_params(fe);
+		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+	}
+
+	result = nxt6000_set_bandwidth(state, p->bandwidth_hz);
+	if (result < 0)
+		return result;
+
+	result = nxt6000_set_guard_interval(state, p->guard_interval);
+	if (result < 0)
+		return result;
+
+	result = nxt6000_set_transmission_mode(state, p->transmission_mode);
+	if (result < 0)
+		return result;
+
+	result = nxt6000_set_inversion(state, p->inversion);
+	if (result < 0)
+		return result;
+
+	msleep(500);
+	return 0;
+}
+
+static void nxt6000_release(struct dvb_frontend* fe)
+{
+	struct nxt6000_state* state = fe->demodulator_priv;
+	kfree(state);
+}
+
+static int nxt6000_read_snr(struct dvb_frontend* fe, u16* snr)
+{
+	struct nxt6000_state* state = fe->demodulator_priv;
+
+	*snr = nxt6000_readreg( state, OFDM_CHC_SNR) / 8;
+
+	return 0;
+}
+
+static int nxt6000_read_ber(struct dvb_frontend* fe, u32* ber)
+{
+	struct nxt6000_state* state = fe->demodulator_priv;
+
+	nxt6000_writereg( state, VIT_COR_INTSTAT, 0x18 );
+
+	*ber = (nxt6000_readreg( state, VIT_BER_1 ) << 8 ) |
+		nxt6000_readreg( state, VIT_BER_0 );
+
+	nxt6000_writereg( state, VIT_COR_INTSTAT, 0x18); // Clear BER Done interrupts
+
+	return 0;
+}
+
+static int nxt6000_read_signal_strength(struct dvb_frontend* fe, u16* signal_strength)
+{
+	struct nxt6000_state* state = fe->demodulator_priv;
+
+	*signal_strength = (short) (511 -
+		(nxt6000_readreg(state, AGC_GAIN_1) +
+		((nxt6000_readreg(state, AGC_GAIN_2) & 0x03) << 8)));
+
+	return 0;
+}
+
+static int nxt6000_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
+{
+	tune->min_delay_ms = 500;
+	return 0;
+}
+
+static int nxt6000_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+{
+	struct nxt6000_state* state = fe->demodulator_priv;
+
+	if (enable) {
+		return nxt6000_writereg(state, ENABLE_TUNER_IIC, 0x01);
+	} else {
+		return nxt6000_writereg(state, ENABLE_TUNER_IIC, 0x00);
+	}
+}
+
+static struct dvb_frontend_ops nxt6000_ops;
+
+struct dvb_frontend* nxt6000_attach(const struct nxt6000_config* config,
+				    struct i2c_adapter* i2c)
+{
+	struct nxt6000_state* state = NULL;
+
+	/* allocate memory for the internal state */
+	state = kzalloc(sizeof(struct nxt6000_state), GFP_KERNEL);
+	if (state == NULL) goto error;
+
+	/* setup the state */
+	state->config = config;
+	state->i2c = i2c;
+
+	/* check if the demod is there */
+	if (nxt6000_readreg(state, OFDM_MSC_REV) != NXT6000ASICDEVICE) goto error;
+
+	/* create dvb_frontend */
+	memcpy(&state->frontend.ops, &nxt6000_ops, sizeof(struct dvb_frontend_ops));
+	state->frontend.demodulator_priv = state;
+	return &state->frontend;
+
+error:
+	kfree(state);
+	return NULL;
+}
+
+static struct dvb_frontend_ops nxt6000_ops = {
+	.delsys = { SYS_DVBT },
+	.info = {
+		.name = "NxtWave NXT6000 DVB-T",
+		.frequency_min = 0,
+		.frequency_max = 863250000,
+		.frequency_stepsize = 62500,
+		/*.frequency_tolerance = *//* FIXME: 12% of SR */
+		.symbol_rate_min = 0,	/* FIXME */
+		.symbol_rate_max = 9360000,	/* FIXME */
+		.symbol_rate_tolerance = 4000,
+		.caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
+			FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
+			FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO |
+			FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
+			FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |
+			FE_CAN_HIERARCHY_AUTO,
+	},
+
+	.release = nxt6000_release,
+
+	.init = nxt6000_init,
+	.i2c_gate_ctrl = nxt6000_i2c_gate_ctrl,
+
+	.get_tune_settings = nxt6000_fe_get_tune_settings,
+
+	.set_frontend = nxt6000_set_frontend,
+
+	.read_status = nxt6000_read_status,
+	.read_ber = nxt6000_read_ber,
+	.read_signal_strength = nxt6000_read_signal_strength,
+	.read_snr = nxt6000_read_snr,
+};
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+
+MODULE_DESCRIPTION("NxtWave NXT6000 DVB-T demodulator driver");
+MODULE_AUTHOR("Florian Schirmer");
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(nxt6000_attach);
diff --git a/drivers/media/dvb-frontends/nxt6000.h b/drivers/media/dvb-frontends/nxt6000.h
new file mode 100644
index 0000000..878eb38
--- /dev/null
+++ b/drivers/media/dvb-frontends/nxt6000.h
@@ -0,0 +1,48 @@
+/*
+	NxtWave Communications - NXT6000 demodulator driver
+
+    Copyright (C) 2002-2003 Florian Schirmer <jolt@tuxbox.org>
+    Copyright (C) 2003 Paul Andreassen <paul@andreassen.com.au>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You 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 NXT6000_H
+#define NXT6000_H
+
+#include <linux/dvb/frontend.h>
+
+struct nxt6000_config
+{
+	/* the demodulator's i2c address */
+	u8 demod_address;
+
+	/* should clock inversion be used? */
+	u8 clock_inversion:1;
+};
+
+#if defined(CONFIG_DVB_NXT6000) || (defined(CONFIG_DVB_NXT6000_MODULE) && defined(MODULE))
+extern struct dvb_frontend* nxt6000_attach(const struct nxt6000_config* config,
+					   struct i2c_adapter* i2c);
+#else
+static inline struct dvb_frontend* nxt6000_attach(const struct nxt6000_config* config,
+					   struct i2c_adapter* i2c)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif // CONFIG_DVB_NXT6000
+
+#endif // NXT6000_H
diff --git a/drivers/media/dvb-frontends/nxt6000_priv.h b/drivers/media/dvb-frontends/nxt6000_priv.h
new file mode 100644
index 0000000..0422e58
--- /dev/null
+++ b/drivers/media/dvb-frontends/nxt6000_priv.h
@@ -0,0 +1,286 @@
+/*
+ * Public Include File for DRV6000 users
+ * (ie. NxtWave Communications - NXT6000 demodulator driver)
+ *
+ * Copyright (C) 2001 NxtWave Communications, Inc.
+ *
+ */
+
+/*  Nxt6000 Register Addresses and Bit Masks */
+
+/* Maximum Register Number */
+#define MAXNXT6000REG          (0x9A)
+
+/* 0x1B A_VIT_BER_0  aka 0x3A */
+#define A_VIT_BER_0            (0x1B)
+
+/* 0x1D A_VIT_BER_TIMER_0 aka 0x38 */
+#define A_VIT_BER_TIMER_0      (0x1D)
+
+/* 0x21 RS_COR_STAT */
+#define RS_COR_STAT            (0x21)
+#define RSCORESTATUS           (0x03)
+
+/* 0x22 RS_COR_INTEN */
+#define RS_COR_INTEN           (0x22)
+
+/* 0x23 RS_COR_INSTAT */
+#define RS_COR_INSTAT          (0x23)
+#define INSTAT_ERROR           (0x04)
+#define LOCK_LOSS_BITS         (0x03)
+
+/* 0x24 RS_COR_SYNC_PARAM */
+#define RS_COR_SYNC_PARAM      (0x24)
+#define SYNC_PARAM             (0x03)
+
+/* 0x25 BER_CTRL */
+#define BER_CTRL               (0x25)
+#define BER_ENABLE             (0x02)
+#define BER_RESET              (0x01)
+
+/* 0x26 BER_PAY */
+#define BER_PAY                (0x26)
+
+/* 0x27 BER_PKT_L */
+#define BER_PKT_L              (0x27)
+#define BER_PKTOVERFLOW        (0x80)
+
+/* 0x30 VIT_COR_CTL */
+#define VIT_COR_CTL            (0x30)
+#define BER_CONTROL            (0x02)
+#define VIT_COR_MASK           (0x82)
+#define VIT_COR_RESYNC         (0x80)
+
+
+/* 0x32 VIT_SYNC_STATUS */
+#define VIT_SYNC_STATUS        (0x32)
+#define VITINSYNC              (0x80)
+
+/* 0x33 VIT_COR_INTEN */
+#define VIT_COR_INTEN          (0x33)
+#define GLOBAL_ENABLE          (0x80)
+
+/* 0x34 VIT_COR_INTSTAT */
+#define VIT_COR_INTSTAT        (0x34)
+#define BER_DONE               (0x08)
+#define BER_OVERFLOW           (0x10)
+
+/* 0x38 VIT_BERTIME_2 */
+#define VIT_BERTIME_2      (0x38)
+
+/* 0x39 VIT_BERTIME_1 */
+#define VIT_BERTIME_1      (0x39)
+
+/* 0x3A VIT_BERTIME_0 */
+#define VIT_BERTIME_0      (0x3a)
+
+			     /* 0x38 OFDM_BERTimer *//* Use the alias registers */
+#define A_VIT_BER_TIMER_0      (0x1D)
+
+			     /* 0x3A VIT_BER_TIMER_0 *//* Use the alias registers */
+#define A_VIT_BER_0            (0x1B)
+
+/* 0x3B VIT_BER_1 */
+#define VIT_BER_1              (0x3b)
+
+/* 0x3C VIT_BER_0 */
+#define VIT_BER_0              (0x3c)
+
+/* 0x40 OFDM_COR_CTL */
+#define OFDM_COR_CTL           (0x40)
+#define COREACT                (0x20)
+#define HOLDSM                 (0x10)
+#define WAIT_AGC               (0x02)
+#define WAIT_SYR               (0x03)
+
+/* 0x41 OFDM_COR_STAT */
+#define OFDM_COR_STAT          (0x41)
+#define COR_STATUS             (0x0F)
+#define MONITOR_TPS            (0x06)
+#define TPSLOCKED              (0x40)
+#define AGCLOCKED              (0x10)
+
+/* 0x42 OFDM_COR_INTEN */
+#define OFDM_COR_INTEN         (0x42)
+#define TPSRCVBAD              (0x04)
+#define TPSRCVCHANGED         (0x02)
+#define TPSRCVUPDATE           (0x01)
+
+/* 0x43 OFDM_COR_INSTAT */
+#define OFDM_COR_INSTAT        (0x43)
+
+/* 0x44 OFDM_COR_MODEGUARD */
+#define OFDM_COR_MODEGUARD     (0x44)
+#define FORCEMODE              (0x08)
+#define FORCEMODE8K			   (0x04)
+
+/* 0x45 OFDM_AGC_CTL */
+#define OFDM_AGC_CTL           (0x45)
+#define INITIAL_AGC_BW		   (0x08)
+#define AGCNEG                 (0x02)
+#define AGCLAST				   (0x10)
+
+/* 0x48 OFDM_AGC_TARGET */
+#define OFDM_AGC_TARGET		   (0x48)
+#define OFDM_AGC_TARGET_DEFAULT (0x28)
+#define OFDM_AGC_TARGET_IMPULSE (0x38)
+
+/* 0x49 OFDM_AGC_GAIN_1 */
+#define OFDM_AGC_GAIN_1        (0x49)
+
+/* 0x4B OFDM_ITB_CTL */
+#define OFDM_ITB_CTL           (0x4B)
+#define ITBINV                 (0x01)
+
+/* 0x49 AGC_GAIN_1 */
+#define AGC_GAIN_1             (0x49)
+
+/* 0x4A AGC_GAIN_2 */
+#define AGC_GAIN_2             (0x4A)
+
+/* 0x4C OFDM_ITB_FREQ_1 */
+#define OFDM_ITB_FREQ_1        (0x4C)
+
+/* 0x4D OFDM_ITB_FREQ_2 */
+#define OFDM_ITB_FREQ_2        (0x4D)
+
+/* 0x4E  OFDM_CAS_CTL */
+#define OFDM_CAS_CTL           (0x4E)
+#define ACSDIS                 (0x40)
+#define CCSEN                  (0x80)
+
+/* 0x4F CAS_FREQ */
+#define CAS_FREQ               (0x4F)
+
+/* 0x51 OFDM_SYR_CTL */
+#define OFDM_SYR_CTL           (0x51)
+#define SIXTH_ENABLE           (0x80)
+#define SYR_TRACKING_DISABLE   (0x01)
+
+/* 0x52 OFDM_SYR_STAT */
+#define OFDM_SYR_STAT		   (0x52)
+#define GI14_2K_SYR_LOCK	   (0x13)
+#define GI14_8K_SYR_LOCK	   (0x17)
+#define GI14_SYR_LOCK		   (0x10)
+
+/* 0x55 OFDM_SYR_OFFSET_1 */
+#define OFDM_SYR_OFFSET_1      (0x55)
+
+/* 0x56 OFDM_SYR_OFFSET_2 */
+#define OFDM_SYR_OFFSET_2      (0x56)
+
+/* 0x58 OFDM_SCR_CTL */
+#define OFDM_SCR_CTL           (0x58)
+#define SYR_ADJ_DECAY_MASK     (0x70)
+#define SYR_ADJ_DECAY          (0x30)
+
+/* 0x59 OFDM_PPM_CTL_1 */
+#define OFDM_PPM_CTL_1         (0x59)
+#define PPMMAX_MASK            (0x30)
+#define PPM256				   (0x30)
+
+/* 0x5B OFDM_TRL_NOMINALRATE_1 */
+#define OFDM_TRL_NOMINALRATE_1 (0x5B)
+
+/* 0x5C OFDM_TRL_NOMINALRATE_2 */
+#define OFDM_TRL_NOMINALRATE_2 (0x5C)
+
+/* 0x5D OFDM_TRL_TIME_1 */
+#define OFDM_TRL_TIME_1        (0x5D)
+
+/* 0x60 OFDM_CRL_FREQ_1 */
+#define OFDM_CRL_FREQ_1        (0x60)
+
+/* 0x63 OFDM_CHC_CTL_1 */
+#define OFDM_CHC_CTL_1         (0x63)
+#define MANMEAN1               (0xF0);
+#define CHCFIR                 (0x01)
+
+/* 0x64 OFDM_CHC_SNR */
+#define OFDM_CHC_SNR           (0x64)
+
+/* 0x65 OFDM_BDI_CTL */
+#define OFDM_BDI_CTL           (0x65)
+#define LP_SELECT              (0x02)
+
+/* 0x67 OFDM_TPS_RCVD_1 */
+#define OFDM_TPS_RCVD_1        (0x67)
+#define TPSFRAME               (0x03)
+
+/* 0x68 OFDM_TPS_RCVD_2 */
+#define OFDM_TPS_RCVD_2        (0x68)
+
+/* 0x69 OFDM_TPS_RCVD_3 */
+#define OFDM_TPS_RCVD_3        (0x69)
+
+/* 0x6A OFDM_TPS_RCVD_4 */
+#define OFDM_TPS_RCVD_4        (0x6A)
+
+/* 0x6B OFDM_TPS_RESERVED_1 */
+#define OFDM_TPS_RESERVED_1    (0x6B)
+
+/* 0x6C OFDM_TPS_RESERVED_2 */
+#define OFDM_TPS_RESERVED_2    (0x6C)
+
+/* 0x73 OFDM_MSC_REV */
+#define OFDM_MSC_REV           (0x73)
+
+/* 0x76 OFDM_SNR_CARRIER_2 */
+#define OFDM_SNR_CARRIER_2     (0x76)
+#define MEAN_MASK              (0x80)
+#define MEANBIT                (0x80)
+
+/* 0x80 ANALOG_CONTROL_0 */
+#define ANALOG_CONTROL_0       (0x80)
+#define POWER_DOWN_ADC         (0x40)
+
+/* 0x81 ENABLE_TUNER_IIC */
+#define ENABLE_TUNER_IIC       (0x81)
+#define ENABLE_TUNER_BIT       (0x01)
+
+/* 0x82 EN_DMD_RACQ */
+#define EN_DMD_RACQ            (0x82)
+#define EN_DMD_RACQ_REG_VAL    (0x81)
+#define EN_DMD_RACQ_REG_VAL_14 (0x01)
+
+/* 0x84 SNR_COMMAND */
+#define SNR_COMMAND            (0x84)
+#define SNRStat                (0x80)
+
+/* 0x85 SNRCARRIERNUMBER_LSB */
+#define SNRCARRIERNUMBER_LSB   (0x85)
+
+/* 0x87 SNRMINTHRESHOLD_LSB */
+#define SNRMINTHRESHOLD_LSB    (0x87)
+
+/* 0x89 SNR_PER_CARRIER_LSB */
+#define SNR_PER_CARRIER_LSB    (0x89)
+
+/* 0x8B SNRBELOWTHRESHOLD_LSB */
+#define SNRBELOWTHRESHOLD_LSB  (0x8B)
+
+/* 0x91 RF_AGC_VAL_1 */
+#define RF_AGC_VAL_1           (0x91)
+
+/* 0x92 RF_AGC_STATUS */
+#define RF_AGC_STATUS          (0x92)
+
+/* 0x98 DIAG_CONFIG */
+#define DIAG_CONFIG            (0x98)
+#define DIAG_MASK              (0x70)
+#define TB_SET                 (0x10)
+#define TRAN_SELECT            (0x07)
+#define SERIAL_SELECT          (0x01)
+
+/* 0x99 SUB_DIAG_MODE_SEL */
+#define SUB_DIAG_MODE_SEL      (0x99)
+#define CLKINVERSION           (0x01)
+
+/* 0x9A TS_FORMAT */
+#define TS_FORMAT              (0x9A)
+#define ERROR_SENSE            (0x08)
+#define VALID_SENSE            (0x04)
+#define SYNC_SENSE             (0x02)
+#define GATED_CLOCK            (0x01)
+
+#define NXT6000ASICDEVICE      (0x0b)
diff --git a/drivers/media/dvb-frontends/or51132.c b/drivers/media/dvb-frontends/or51132.c
new file mode 100644
index 0000000..5ef9218
--- /dev/null
+++ b/drivers/media/dvb-frontends/or51132.c
@@ -0,0 +1,631 @@
+/*
+ *    Support for OR51132 (pcHDTV HD-3000) - VSB/QAM
+ *
+ *
+ *    Copyright (C) 2007 Trent Piepho <xyzzy@speakeasy.org>
+ *
+ *    Copyright (C) 2005 Kirk Lapray <kirk_lapray@bigfoot.com>
+ *
+ *    Based on code from Jack Kelliher (kelliher@xmission.com)
+ *                           Copyright (C) 2002 & pcHDTV, inc.
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+*/
+
+/*
+ * This driver needs two external firmware files. Please copy
+ * "dvb-fe-or51132-vsb.fw" and "dvb-fe-or51132-qam.fw" to
+ * /usr/lib/hotplug/firmware/ or /lib/firmware/
+ * (depending on configuration of firmware hotplug).
+ */
+#define OR51132_VSB_FIRMWARE "dvb-fe-or51132-vsb.fw"
+#define OR51132_QAM_FIRMWARE "dvb-fe-or51132-qam.fw"
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <asm/byteorder.h>
+
+#include "dvb_math.h"
+#include "dvb_frontend.h"
+#include "or51132.h"
+
+static int debug;
+#define dprintk(args...) \
+	do { \
+		if (debug) printk(KERN_DEBUG "or51132: " args); \
+	} while (0)
+
+
+struct or51132_state
+{
+	struct i2c_adapter* i2c;
+
+	/* Configuration settings */
+	const struct or51132_config* config;
+
+	struct dvb_frontend frontend;
+
+	/* Demodulator private data */
+	fe_modulation_t current_modulation;
+	u32 snr; /* Result of last SNR calculation */
+
+	/* Tuner private data */
+	u32 current_frequency;
+};
+
+
+/* Write buffer to demod */
+static int or51132_writebuf(struct or51132_state *state, const u8 *buf, int len)
+{
+	int err;
+	struct i2c_msg msg = { .addr = state->config->demod_address,
+			       .flags = 0, .buf = (u8*)buf, .len = len };
+
+	/* msleep(20); */ /* doesn't appear to be necessary */
+	if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
+		printk(KERN_WARNING "or51132: I2C write (addr 0x%02x len %d) error: %d\n",
+		       msg.addr, msg.len, err);
+		return -EREMOTEIO;
+	}
+	return 0;
+}
+
+/* Write constant bytes, e.g. or51132_writebytes(state, 0x04, 0x42, 0x00);
+   Less code and more efficient that loading a buffer on the stack with
+   the bytes to send and then calling or51132_writebuf() on that. */
+#define or51132_writebytes(state, data...)  \
+	({ static const u8 _data[] = {data}; \
+	or51132_writebuf(state, _data, sizeof(_data)); })
+
+/* Read data from demod into buffer.  Returns 0 on success. */
+static int or51132_readbuf(struct or51132_state *state, u8 *buf, int len)
+{
+	int err;
+	struct i2c_msg msg = { .addr = state->config->demod_address,
+			       .flags = I2C_M_RD, .buf = buf, .len = len };
+
+	/* msleep(20); */ /* doesn't appear to be necessary */
+	if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
+		printk(KERN_WARNING "or51132: I2C read (addr 0x%02x len %d) error: %d\n",
+		       msg.addr, msg.len, err);
+		return -EREMOTEIO;
+	}
+	return 0;
+}
+
+/* Reads a 16-bit demod register.  Returns <0 on error. */
+static int or51132_readreg(struct or51132_state *state, u8 reg)
+{
+	u8 buf[2] = { 0x04, reg };
+	struct i2c_msg msg[2] = {
+		{.addr = state->config->demod_address, .flags = 0,
+		 .buf = buf, .len = 2 },
+		{.addr = state->config->demod_address, .flags = I2C_M_RD,
+		 .buf = buf, .len = 2 }};
+	int err;
+
+	if ((err = i2c_transfer(state->i2c, msg, 2)) != 2) {
+		printk(KERN_WARNING "or51132: I2C error reading register %d: %d\n",
+		       reg, err);
+		return -EREMOTEIO;
+	}
+	return buf[0] | (buf[1] << 8);
+}
+
+static int or51132_load_firmware (struct dvb_frontend* fe, const struct firmware *fw)
+{
+	struct or51132_state* state = fe->demodulator_priv;
+	static const u8 run_buf[] = {0x7F,0x01};
+	u8 rec_buf[8];
+	u32 firmwareAsize, firmwareBsize;
+	int i,ret;
+
+	dprintk("Firmware is %Zd bytes\n",fw->size);
+
+	/* Get size of firmware A and B */
+	firmwareAsize = le32_to_cpu(*((__le32*)fw->data));
+	dprintk("FirmwareA is %i bytes\n",firmwareAsize);
+	firmwareBsize = le32_to_cpu(*((__le32*)(fw->data+4)));
+	dprintk("FirmwareB is %i bytes\n",firmwareBsize);
+
+	/* Upload firmware */
+	if ((ret = or51132_writebuf(state, &fw->data[8], firmwareAsize))) {
+		printk(KERN_WARNING "or51132: load_firmware error 1\n");
+		return ret;
+	}
+	if ((ret = or51132_writebuf(state, &fw->data[8+firmwareAsize],
+				    firmwareBsize))) {
+		printk(KERN_WARNING "or51132: load_firmware error 2\n");
+		return ret;
+	}
+
+	if ((ret = or51132_writebuf(state, run_buf, 2))) {
+		printk(KERN_WARNING "or51132: load_firmware error 3\n");
+		return ret;
+	}
+	if ((ret = or51132_writebuf(state, run_buf, 2))) {
+		printk(KERN_WARNING "or51132: load_firmware error 4\n");
+		return ret;
+	}
+
+	/* 50ms for operation to begin */
+	msleep(50);
+
+	/* Read back ucode version to besure we loaded correctly and are really up and running */
+	/* Get uCode version */
+	if ((ret = or51132_writebytes(state, 0x10, 0x10, 0x00))) {
+		printk(KERN_WARNING "or51132: load_firmware error a\n");
+		return ret;
+	}
+	if ((ret = or51132_writebytes(state, 0x04, 0x17))) {
+		printk(KERN_WARNING "or51132: load_firmware error b\n");
+		return ret;
+	}
+	if ((ret = or51132_writebytes(state, 0x00, 0x00))) {
+		printk(KERN_WARNING "or51132: load_firmware error c\n");
+		return ret;
+	}
+	for (i=0;i<4;i++) {
+		/* Once upon a time, this command might have had something
+		   to do with getting the firmware version, but it's
+		   not used anymore:
+		   {0x04,0x00,0x30,0x00,i+1} */
+		/* Read 8 bytes, two bytes at a time */
+		if ((ret = or51132_readbuf(state, &rec_buf[i*2], 2))) {
+			printk(KERN_WARNING
+			       "or51132: load_firmware error d - %d\n",i);
+			return ret;
+		}
+	}
+
+	printk(KERN_WARNING
+	       "or51132: Version: %02X%02X%02X%02X-%02X%02X%02X%02X (%02X%01X-%01X-%02X%01X-%01X)\n",
+	       rec_buf[1],rec_buf[0],rec_buf[3],rec_buf[2],
+	       rec_buf[5],rec_buf[4],rec_buf[7],rec_buf[6],
+	       rec_buf[3],rec_buf[2]>>4,rec_buf[2]&0x0f,
+	       rec_buf[5],rec_buf[4]>>4,rec_buf[4]&0x0f);
+
+	if ((ret = or51132_writebytes(state, 0x10, 0x00, 0x00))) {
+		printk(KERN_WARNING "or51132: load_firmware error e\n");
+		return ret;
+	}
+	return 0;
+};
+
+static int or51132_init(struct dvb_frontend* fe)
+{
+	return 0;
+}
+
+static int or51132_read_ber(struct dvb_frontend* fe, u32* ber)
+{
+	*ber = 0;
+	return 0;
+}
+
+static int or51132_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
+{
+	*ucblocks = 0;
+	return 0;
+}
+
+static int or51132_sleep(struct dvb_frontend* fe)
+{
+	return 0;
+}
+
+static int or51132_setmode(struct dvb_frontend* fe)
+{
+	struct or51132_state* state = fe->demodulator_priv;
+	u8 cmd_buf1[3] = {0x04, 0x01, 0x5f};
+	u8 cmd_buf2[3] = {0x1c, 0x00, 0 };
+
+	dprintk("setmode %d\n",(int)state->current_modulation);
+
+	switch (state->current_modulation) {
+	case VSB_8:
+		/* Auto CH, Auto NTSC rej, MPEGser, MPEG2tr, phase noise-high */
+		cmd_buf1[2] = 0x50;
+		/* REC MODE inv IF spectrum, Normal */
+		cmd_buf2[1] = 0x03;
+		/* Channel MODE ATSC/VSB8 */
+		cmd_buf2[2] = 0x06;
+		break;
+	/* All QAM modes are:
+	   Auto-deinterleave; MPEGser, MPEG2tr, phase noise-high
+	   REC MODE Normal Carrier Lock */
+	case QAM_AUTO:
+		/* Channel MODE Auto QAM64/256 */
+		cmd_buf2[2] = 0x4f;
+		break;
+	case QAM_256:
+		/* Channel MODE QAM256 */
+		cmd_buf2[2] = 0x45;
+		break;
+	case QAM_64:
+		/* Channel MODE QAM64 */
+		cmd_buf2[2] = 0x43;
+		break;
+	default:
+		printk(KERN_WARNING
+		       "or51132: setmode: Modulation set to unsupported value (%d)\n",
+		       state->current_modulation);
+		return -EINVAL;
+	}
+
+	/* Set Receiver 1 register */
+	if (or51132_writebuf(state, cmd_buf1, 3)) {
+		printk(KERN_WARNING "or51132: set_mode error 1\n");
+		return -EREMOTEIO;
+	}
+	dprintk("set #1 to %02x\n", cmd_buf1[2]);
+
+	/* Set operation mode in Receiver 6 register */
+	if (or51132_writebuf(state, cmd_buf2, 3)) {
+		printk(KERN_WARNING "or51132: set_mode error 2\n");
+		return -EREMOTEIO;
+	}
+	dprintk("set #6 to 0x%02x%02x\n", cmd_buf2[1], cmd_buf2[2]);
+
+	return 0;
+}
+
+/* Some modulations use the same firmware.  This classifies modulations
+   by the firmware they use. */
+#define MOD_FWCLASS_UNKNOWN	0
+#define MOD_FWCLASS_VSB		1
+#define MOD_FWCLASS_QAM		2
+static int modulation_fw_class(fe_modulation_t modulation)
+{
+	switch(modulation) {
+	case VSB_8:
+		return MOD_FWCLASS_VSB;
+	case QAM_AUTO:
+	case QAM_64:
+	case QAM_256:
+		return MOD_FWCLASS_QAM;
+	default:
+		return MOD_FWCLASS_UNKNOWN;
+	}
+}
+
+static int or51132_set_parameters(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	int ret;
+	struct or51132_state* state = fe->demodulator_priv;
+	const struct firmware *fw;
+	const char *fwname;
+	int clock_mode;
+
+	/* Upload new firmware only if we need a different one */
+	if (modulation_fw_class(state->current_modulation) !=
+	    modulation_fw_class(p->modulation)) {
+		switch (modulation_fw_class(p->modulation)) {
+		case MOD_FWCLASS_VSB:
+			dprintk("set_parameters VSB MODE\n");
+			fwname = OR51132_VSB_FIRMWARE;
+
+			/* Set non-punctured clock for VSB */
+			clock_mode = 0;
+			break;
+		case MOD_FWCLASS_QAM:
+			dprintk("set_parameters QAM MODE\n");
+			fwname = OR51132_QAM_FIRMWARE;
+
+			/* Set punctured clock for QAM */
+			clock_mode = 1;
+			break;
+		default:
+			printk("or51132: Modulation type(%d) UNSUPPORTED\n",
+			       p->modulation);
+			return -1;
+		}
+		printk("or51132: Waiting for firmware upload(%s)...\n",
+		       fwname);
+		ret = request_firmware(&fw, fwname, state->i2c->dev.parent);
+		if (ret) {
+			printk(KERN_WARNING "or51132: No firmware up"
+			       "loaded(timeout or file not found?)\n");
+			return ret;
+		}
+		ret = or51132_load_firmware(fe, fw);
+		release_firmware(fw);
+		if (ret) {
+			printk(KERN_WARNING "or51132: Writing firmware to "
+			       "device failed!\n");
+			return ret;
+		}
+		printk("or51132: Firmware upload complete.\n");
+		state->config->set_ts_params(fe, clock_mode);
+	}
+	/* Change only if we are actually changing the modulation */
+	if (state->current_modulation != p->modulation) {
+		state->current_modulation = p->modulation;
+		or51132_setmode(fe);
+	}
+
+	if (fe->ops.tuner_ops.set_params) {
+		fe->ops.tuner_ops.set_params(fe);
+		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+	}
+
+	/* Set to current mode */
+	or51132_setmode(fe);
+
+	/* Update current frequency */
+	state->current_frequency = p->frequency;
+	return 0;
+}
+
+static int or51132_get_parameters(struct dvb_frontend* fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct or51132_state* state = fe->demodulator_priv;
+	int status;
+	int retry = 1;
+
+start:
+	/* Receiver Status */
+	if ((status = or51132_readreg(state, 0x00)) < 0) {
+		printk(KERN_WARNING "or51132: get_parameters: error reading receiver status\n");
+		return -EREMOTEIO;
+	}
+	switch(status&0xff) {
+	case 0x06:
+		p->modulation = VSB_8;
+		break;
+	case 0x43:
+		p->modulation = QAM_64;
+		break;
+	case 0x45:
+		p->modulation = QAM_256;
+		break;
+	default:
+		if (retry--)
+			goto start;
+		printk(KERN_WARNING "or51132: unknown status 0x%02x\n",
+		       status&0xff);
+		return -EREMOTEIO;
+	}
+
+	/* FIXME: Read frequency from frontend, take AFC into account */
+	p->frequency = state->current_frequency;
+
+	/* FIXME: How to read inversion setting? Receiver 6 register? */
+	p->inversion = INVERSION_AUTO;
+
+	return 0;
+}
+
+static int or51132_read_status(struct dvb_frontend* fe, fe_status_t* status)
+{
+	struct or51132_state* state = fe->demodulator_priv;
+	int reg;
+
+	/* Receiver Status */
+	if ((reg = or51132_readreg(state, 0x00)) < 0) {
+		printk(KERN_WARNING "or51132: read_status: error reading receiver status: %d\n", reg);
+		*status = 0;
+		return -EREMOTEIO;
+	}
+	dprintk("%s: read_status %04x\n", __func__, reg);
+
+	if (reg & 0x0100) /* Receiver Lock */
+		*status = FE_HAS_SIGNAL|FE_HAS_CARRIER|FE_HAS_VITERBI|
+			  FE_HAS_SYNC|FE_HAS_LOCK;
+	else
+		*status = 0;
+	return 0;
+}
+
+/* Calculate SNR estimation (scaled by 2^24)
+
+   8-VSB SNR and QAM equations from Oren datasheets
+
+   For 8-VSB:
+     SNR[dB] = 10 * log10(897152044.8282 / MSE^2 ) - K
+
+     Where K = 0 if NTSC rejection filter is OFF; and
+	   K = 3 if NTSC rejection filter is ON
+
+   For QAM64:
+     SNR[dB] = 10 * log10(897152044.8282 / MSE^2 )
+
+   For QAM256:
+     SNR[dB] = 10 * log10(907832426.314266  / MSE^2 )
+
+   We re-write the snr equation as:
+     SNR * 2^24 = 10*(c - 2*intlog10(MSE))
+   Where for QAM256, c = log10(907832426.314266) * 2^24
+   and for 8-VSB and QAM64, c = log10(897152044.8282) * 2^24 */
+
+static u32 calculate_snr(u32 mse, u32 c)
+{
+	if (mse == 0) /* No signal */
+		return 0;
+
+	mse = 2*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 or51132_read_snr(struct dvb_frontend* fe, u16* snr)
+{
+	struct or51132_state* state = fe->demodulator_priv;
+	int noise, reg;
+	u32 c, usK = 0;
+	int retry = 1;
+
+start:
+	/* SNR after Equalizer */
+	noise = or51132_readreg(state, 0x02);
+	if (noise < 0) {
+		printk(KERN_WARNING "or51132: read_snr: error reading equalizer\n");
+		return -EREMOTEIO;
+	}
+	dprintk("read_snr noise (%d)\n", noise);
+
+	/* Read status, contains modulation type for QAM_AUTO and
+	   NTSC filter for VSB */
+	reg = or51132_readreg(state, 0x00);
+	if (reg < 0) {
+		printk(KERN_WARNING "or51132: read_snr: error reading receiver status\n");
+		return -EREMOTEIO;
+	}
+
+	switch (reg&0xff) {
+	case 0x06:
+		if (reg & 0x1000) usK = 3 << 24;
+		/* Fall through to QAM64 case */
+	case 0x43:
+		c = 150204167;
+		break;
+	case 0x45:
+		c = 150290396;
+		break;
+	default:
+		printk(KERN_WARNING "or51132: unknown status 0x%02x\n", reg&0xff);
+		if (retry--) goto start;
+		return -EREMOTEIO;
+	}
+	dprintk("%s: modulation %02x, NTSC rej O%s\n", __func__,
+		reg&0xff, reg&0x1000?"n":"ff");
+
+	/* Calculate SNR using noise, c, and NTSC rejection correction */
+	state->snr = calculate_snr(noise, c) - usK;
+	*snr = (state->snr) >> 16;
+
+	dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __func__, noise,
+		state->snr >> 24, (((state->snr>>8) & 0xffff) * 100) >> 16);
+
+	return 0;
+}
+
+static int or51132_read_signal_strength(struct dvb_frontend* fe, u16* strength)
+{
+	/* 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 or51132_state* state = (struct or51132_state*) fe->demodulator_priv;
+	u16 snr;
+	int ret;
+
+	ret = fe->ops.read_snr(fe, &snr);
+	if (ret != 0)
+		return ret;
+	/* 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;
+
+	return 0;
+}
+
+static int or51132_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fe_tune_settings)
+{
+	fe_tune_settings->min_delay_ms = 500;
+	fe_tune_settings->step_size = 0;
+	fe_tune_settings->max_drift = 0;
+
+	return 0;
+}
+
+static void or51132_release(struct dvb_frontend* fe)
+{
+	struct or51132_state* state = fe->demodulator_priv;
+	kfree(state);
+}
+
+static struct dvb_frontend_ops or51132_ops;
+
+struct dvb_frontend* or51132_attach(const struct or51132_config* config,
+				    struct i2c_adapter* i2c)
+{
+	struct or51132_state* state = NULL;
+
+	/* Allocate memory for the internal state */
+	state = kzalloc(sizeof(struct or51132_state), GFP_KERNEL);
+	if (state == NULL)
+		return NULL;
+
+	/* Setup the state */
+	state->config = config;
+	state->i2c = i2c;
+	state->current_frequency = -1;
+	state->current_modulation = -1;
+
+	/* Create dvb_frontend */
+	memcpy(&state->frontend.ops, &or51132_ops, sizeof(struct dvb_frontend_ops));
+	state->frontend.demodulator_priv = state;
+	return &state->frontend;
+}
+
+static struct dvb_frontend_ops or51132_ops = {
+	.delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
+	.info = {
+		.name			= "Oren OR51132 VSB/QAM Frontend",
+		.frequency_min		= 44000000,
+		.frequency_max		= 958000000,
+		.frequency_stepsize	= 166666,
+		.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_FEC_AUTO |
+			FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_QAM_AUTO |
+			FE_CAN_8VSB
+	},
+
+	.release = or51132_release,
+
+	.init = or51132_init,
+	.sleep = or51132_sleep,
+
+	.set_frontend = or51132_set_parameters,
+	.get_frontend = or51132_get_parameters,
+	.get_tune_settings = or51132_get_tune_settings,
+
+	.read_status = or51132_read_status,
+	.read_ber = or51132_read_ber,
+	.read_signal_strength = or51132_read_signal_strength,
+	.read_snr = or51132_read_snr,
+	.read_ucblocks = or51132_read_ucblocks,
+};
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+
+MODULE_DESCRIPTION("OR51132 ATSC [pcHDTV HD-3000] (8VSB & ITU J83 AnnexB FEC QAM64/256) Demodulator Driver");
+MODULE_AUTHOR("Kirk Lapray");
+MODULE_AUTHOR("Trent Piepho");
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(or51132_attach);
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/dvb-frontends/or51132.h b/drivers/media/dvb-frontends/or51132.h
new file mode 100644
index 0000000..1b8e04d
--- /dev/null
+++ b/drivers/media/dvb-frontends/or51132.h
@@ -0,0 +1,55 @@
+/*
+ *    Support for OR51132 (pcHDTV HD-3000) - VSB/QAM
+ *
+ *    Copyright (C) 2005 Kirk Lapray <kirk_lapray@bigfoot.com>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+*/
+
+#ifndef OR51132_H
+#define OR51132_H
+
+#include <linux/firmware.h>
+#include <linux/dvb/frontend.h>
+
+struct or51132_config
+{
+	/* The demodulator's i2c address */
+	u8 demod_address;
+
+	/* Need to set device param for start_dma */
+	int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured);
+};
+
+#if defined(CONFIG_DVB_OR51132) || (defined(CONFIG_DVB_OR51132_MODULE) && defined(MODULE))
+extern struct dvb_frontend* or51132_attach(const struct or51132_config* config,
+					   struct i2c_adapter* i2c);
+#else
+static inline struct dvb_frontend* or51132_attach(const struct or51132_config* config,
+					   struct i2c_adapter* i2c)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif // CONFIG_DVB_OR51132
+
+#endif // OR51132_H
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/dvb-frontends/or51211.c b/drivers/media/dvb-frontends/or51211.c
new file mode 100644
index 0000000..c625b57
--- /dev/null
+++ b/drivers/media/dvb-frontends/or51211.c
@@ -0,0 +1,581 @@
+/*
+ *    Support for OR51211 (pcHDTV HD-2000) - VSB
+ *
+ *    Copyright (C) 2005 Kirk Lapray <kirk_lapray@bigfoot.com>
+ *
+ *    Based on code from Jack Kelliher (kelliher@xmission.com)
+ *                           Copyright (C) 2002 & pcHDTV, inc.
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+*/
+
+/*
+ * This driver needs external firmware. Please use the command
+ * "<kerneldir>/Documentation/dvb/get_dvb_firmware or51211" to
+ * download/extract it, and then copy it to /usr/lib/hotplug/firmware
+ * or /lib/firmware (depending on configuration of firmware hotplug).
+ */
+#define OR51211_DEFAULT_FIRMWARE "dvb-fe-or51211.fw"
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/firmware.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <asm/byteorder.h>
+
+#include "dvb_math.h"
+#include "dvb_frontend.h"
+#include "or51211.h"
+
+static int debug;
+#define dprintk(args...) \
+	do { \
+		if (debug) printk(KERN_DEBUG "or51211: " args); \
+	} while (0)
+
+static u8 run_buf[] = {0x7f,0x01};
+static u8 cmd_buf[] = {0x04,0x01,0x50,0x80,0x06}; // ATSC
+
+struct or51211_state {
+
+	struct i2c_adapter* i2c;
+
+	/* Configuration settings */
+	const struct or51211_config* config;
+
+	struct dvb_frontend frontend;
+	struct bt878* bt;
+
+	/* Demodulator private data */
+	u8 initialized:1;
+	u32 snr; /* Result of last SNR claculation */
+
+	/* Tuner private data */
+	u32 current_frequency;
+};
+
+static int i2c_writebytes (struct or51211_state* state, u8 reg, const u8 *buf,
+			   int len)
+{
+	int err;
+	struct i2c_msg msg;
+	msg.addr	= reg;
+	msg.flags	= 0;
+	msg.len		= len;
+	msg.buf		= (u8 *)buf;
+
+	if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
+		printk(KERN_WARNING "or51211: i2c_writebytes error "
+		       "(addr %02x, err == %i)\n", reg, err);
+		return -EREMOTEIO;
+	}
+
+	return 0;
+}
+
+static int i2c_readbytes(struct or51211_state *state, u8 reg, u8 *buf, int len)
+{
+	int err;
+	struct i2c_msg msg;
+	msg.addr	= reg;
+	msg.flags	= I2C_M_RD;
+	msg.len		= len;
+	msg.buf		= buf;
+
+	if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
+		printk(KERN_WARNING "or51211: i2c_readbytes error "
+		       "(addr %02x, err == %i)\n", reg, err);
+		return -EREMOTEIO;
+	}
+
+	return 0;
+}
+
+static int or51211_load_firmware (struct dvb_frontend* fe,
+				  const struct firmware *fw)
+{
+	struct or51211_state* state = fe->demodulator_priv;
+	u8 tudata[585];
+	int i;
+
+	dprintk("Firmware is %zd bytes\n",fw->size);
+
+	/* Get eprom data */
+	tudata[0] = 17;
+	if (i2c_writebytes(state,0x50,tudata,1)) {
+		printk(KERN_WARNING "or51211:load_firmware error eprom addr\n");
+		return -1;
+	}
+	if (i2c_readbytes(state,0x50,&tudata[145],192)) {
+		printk(KERN_WARNING "or51211: load_firmware error eprom\n");
+		return -1;
+	}
+
+	/* Create firmware buffer */
+	for (i = 0; i < 145; i++)
+		tudata[i] = fw->data[i];
+
+	for (i = 0; i < 248; i++)
+		tudata[i+337] = fw->data[145+i];
+
+	state->config->reset(fe);
+
+	if (i2c_writebytes(state,state->config->demod_address,tudata,585)) {
+		printk(KERN_WARNING "or51211: load_firmware error 1\n");
+		return -1;
+	}
+	msleep(1);
+
+	if (i2c_writebytes(state,state->config->demod_address,
+			   &fw->data[393],8125)) {
+		printk(KERN_WARNING "or51211: load_firmware error 2\n");
+		return -1;
+	}
+	msleep(1);
+
+	if (i2c_writebytes(state,state->config->demod_address,run_buf,2)) {
+		printk(KERN_WARNING "or51211: load_firmware error 3\n");
+		return -1;
+	}
+
+	/* Wait at least 5 msec */
+	msleep(10);
+	if (i2c_writebytes(state,state->config->demod_address,run_buf,2)) {
+		printk(KERN_WARNING "or51211: load_firmware error 4\n");
+		return -1;
+	}
+	msleep(10);
+
+	printk("or51211: Done.\n");
+	return 0;
+};
+
+static int or51211_setmode(struct dvb_frontend* fe, int mode)
+{
+	struct or51211_state* state = fe->demodulator_priv;
+	u8 rec_buf[14];
+
+	state->config->setmode(fe, mode);
+
+	if (i2c_writebytes(state,state->config->demod_address,run_buf,2)) {
+		printk(KERN_WARNING "or51211: setmode error 1\n");
+		return -1;
+	}
+
+	/* Wait at least 5 msec */
+	msleep(10);
+	if (i2c_writebytes(state,state->config->demod_address,run_buf,2)) {
+		printk(KERN_WARNING "or51211: setmode error 2\n");
+		return -1;
+	}
+
+	msleep(10);
+
+	/* Set operation mode in Receiver 1 register;
+	 * type 1:
+	 * data 0x50h  Automatic sets receiver channel conditions
+	 *             Automatic NTSC rejection filter
+	 *             Enable  MPEG serial data output
+	 *             MPEG2tr
+	 *             High tuner phase noise
+	 *             normal +/-150kHz Carrier acquisition range
+	 */
+	if (i2c_writebytes(state,state->config->demod_address,cmd_buf,3)) {
+		printk(KERN_WARNING "or51211: setmode error 3\n");
+		return -1;
+	}
+
+	rec_buf[0] = 0x04;
+	rec_buf[1] = 0x00;
+	rec_buf[2] = 0x03;
+	rec_buf[3] = 0x00;
+	msleep(20);
+	if (i2c_writebytes(state,state->config->demod_address,rec_buf,3)) {
+		printk(KERN_WARNING "or51211: setmode error 5\n");
+	}
+	msleep(3);
+	if (i2c_readbytes(state,state->config->demod_address,&rec_buf[10],2)) {
+		printk(KERN_WARNING "or51211: setmode error 6");
+		return -1;
+	}
+	dprintk("setmode rec status %02x %02x\n",rec_buf[10],rec_buf[11]);
+
+	return 0;
+}
+
+static int or51211_set_parameters(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct or51211_state* state = fe->demodulator_priv;
+
+	/* Change only if we are actually changing the channel */
+	if (state->current_frequency != p->frequency) {
+		if (fe->ops.tuner_ops.set_params) {
+			fe->ops.tuner_ops.set_params(fe);
+			if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+		}
+
+		/* Set to ATSC mode */
+		or51211_setmode(fe,0);
+
+		/* Update current frequency */
+		state->current_frequency = p->frequency;
+	}
+	return 0;
+}
+
+static int or51211_read_status(struct dvb_frontend* fe, fe_status_t* status)
+{
+	struct or51211_state* state = fe->demodulator_priv;
+	unsigned char rec_buf[2];
+	unsigned char snd_buf[] = {0x04,0x00,0x03,0x00};
+	*status = 0;
+
+	/* Receiver Status */
+	if (i2c_writebytes(state,state->config->demod_address,snd_buf,3)) {
+		printk(KERN_WARNING "or51132: read_status write error\n");
+		return -1;
+	}
+	msleep(3);
+	if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) {
+		printk(KERN_WARNING "or51132: read_status read error\n");
+		return -1;
+	}
+	dprintk("read_status %x %x\n",rec_buf[0],rec_buf[1]);
+
+	if (rec_buf[0] &  0x01) { /* Receiver Lock */
+		*status |= FE_HAS_SIGNAL;
+		*status |= FE_HAS_CARRIER;
+		*status |= FE_HAS_VITERBI;
+		*status |= FE_HAS_SYNC;
+		*status |= FE_HAS_LOCK;
+	}
+	return 0;
+}
+
+/* Calculate SNR estimation (scaled by 2^24)
+
+   8-VSB SNR equation from Oren datasheets
+
+   For 8-VSB:
+     SNR[dB] = 10 * log10(219037.9454 / MSE^2 )
+
+   We re-write the snr equation as:
+     SNR * 2^24 = 10*(c - 2*intlog10(MSE))
+   Where for 8-VSB, c = log10(219037.9454) * 2^24 */
+
+static u32 calculate_snr(u32 mse, u32 c)
+{
+	if (mse == 0) /* No signal */
+		return 0;
+
+	mse = 2*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 or51211_read_snr(struct dvb_frontend* fe, u16* snr)
+{
+	struct or51211_state* state = fe->demodulator_priv;
+	u8 rec_buf[2];
+	u8 snd_buf[3];
+
+	/* SNR after Equalizer */
+	snd_buf[0] = 0x04;
+	snd_buf[1] = 0x00;
+	snd_buf[2] = 0x04;
+
+	if (i2c_writebytes(state,state->config->demod_address,snd_buf,3)) {
+		printk(KERN_WARNING "%s: error writing snr reg\n",
+		       __func__);
+		return -1;
+	}
+	if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) {
+		printk(KERN_WARNING "%s: read_status read error\n",
+		       __func__);
+		return -1;
+	}
+
+	state->snr = calculate_snr(rec_buf[0], 89599047);
+	*snr = (state->snr) >> 16;
+
+	dprintk("%s: noise = 0x%02x, snr = %d.%02d dB\n", __func__, rec_buf[0],
+		state->snr >> 24, (((state->snr>>8) & 0xffff) * 100) >> 16);
+
+	return 0;
+}
+
+static int or51211_read_signal_strength(struct dvb_frontend* fe, u16* strength)
+{
+	/* 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 or51211_state* state = (struct or51211_state*)fe->demodulator_priv;
+	u16 snr;
+	int ret;
+
+	ret = fe->ops.read_snr(fe, &snr);
+	if (ret != 0)
+		return ret;
+	/* 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;
+
+	return 0;
+}
+
+static int or51211_read_ber(struct dvb_frontend* fe, u32* ber)
+{
+	*ber = -ENOSYS;
+	return 0;
+}
+
+static int or51211_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
+{
+	*ucblocks = -ENOSYS;
+	return 0;
+}
+
+static int or51211_sleep(struct dvb_frontend* fe)
+{
+	return 0;
+}
+
+static int or51211_init(struct dvb_frontend* fe)
+{
+	struct or51211_state* state = fe->demodulator_priv;
+	const struct or51211_config* config = state->config;
+	const struct firmware* fw;
+	unsigned char get_ver_buf[] = {0x04,0x00,0x30,0x00,0x00};
+	unsigned char rec_buf[14];
+	int ret,i;
+
+	if (!state->initialized) {
+		/* Request the firmware, this will block until it uploads */
+		printk(KERN_INFO "or51211: Waiting for firmware upload "
+		       "(%s)...\n", OR51211_DEFAULT_FIRMWARE);
+		ret = config->request_firmware(fe, &fw,
+					       OR51211_DEFAULT_FIRMWARE);
+		printk(KERN_INFO "or51211:Got Hotplug firmware\n");
+		if (ret) {
+			printk(KERN_WARNING "or51211: No firmware uploaded "
+			       "(timeout or file not found?)\n");
+			return ret;
+		}
+
+		ret = or51211_load_firmware(fe, fw);
+		release_firmware(fw);
+		if (ret) {
+			printk(KERN_WARNING "or51211: Writing firmware to "
+			       "device failed!\n");
+			return ret;
+		}
+		printk(KERN_INFO "or51211: Firmware upload complete.\n");
+
+		/* Set operation mode in Receiver 1 register;
+		 * type 1:
+		 * data 0x50h  Automatic sets receiver channel conditions
+		 *             Automatic NTSC rejection filter
+		 *             Enable  MPEG serial data output
+		 *             MPEG2tr
+		 *             High tuner phase noise
+		 *             normal +/-150kHz Carrier acquisition range
+		 */
+		if (i2c_writebytes(state,state->config->demod_address,
+				   cmd_buf,3)) {
+			printk(KERN_WARNING "or51211: Load DVR Error 5\n");
+			return -1;
+		}
+
+		/* Read back ucode version to besure we loaded correctly */
+		/* and are really up and running */
+		rec_buf[0] = 0x04;
+		rec_buf[1] = 0x00;
+		rec_buf[2] = 0x03;
+		rec_buf[3] = 0x00;
+		msleep(30);
+		if (i2c_writebytes(state,state->config->demod_address,
+				   rec_buf,3)) {
+			printk(KERN_WARNING "or51211: Load DVR Error A\n");
+			return -1;
+		}
+		msleep(3);
+		if (i2c_readbytes(state,state->config->demod_address,
+				  &rec_buf[10],2)) {
+			printk(KERN_WARNING "or51211: Load DVR Error B\n");
+			return -1;
+		}
+
+		rec_buf[0] = 0x04;
+		rec_buf[1] = 0x00;
+		rec_buf[2] = 0x01;
+		rec_buf[3] = 0x00;
+		msleep(20);
+		if (i2c_writebytes(state,state->config->demod_address,
+				   rec_buf,3)) {
+			printk(KERN_WARNING "or51211: Load DVR Error C\n");
+			return -1;
+		}
+		msleep(3);
+		if (i2c_readbytes(state,state->config->demod_address,
+				  &rec_buf[12],2)) {
+			printk(KERN_WARNING "or51211: Load DVR Error D\n");
+			return -1;
+		}
+
+		for (i = 0; i < 8; i++)
+			rec_buf[i]=0xed;
+
+		for (i = 0; i < 5; i++) {
+			msleep(30);
+			get_ver_buf[4] = i+1;
+			if (i2c_writebytes(state,state->config->demod_address,
+					   get_ver_buf,5)) {
+				printk(KERN_WARNING "or51211:Load DVR Error 6"
+				       " - %d\n",i);
+				return -1;
+			}
+			msleep(3);
+
+			if (i2c_readbytes(state,state->config->demod_address,
+					  &rec_buf[i*2],2)) {
+				printk(KERN_WARNING "or51211:Load DVR Error 7"
+				       " - %d\n",i);
+				return -1;
+			}
+			/* If we didn't receive the right index, try again */
+			if ((int)rec_buf[i*2+1]!=i+1){
+			  i--;
+			}
+		}
+		dprintk("read_fwbits %x %x %x %x %x %x %x %x %x %x\n",
+			rec_buf[0], rec_buf[1], rec_buf[2], rec_buf[3],
+			rec_buf[4], rec_buf[5], rec_buf[6], rec_buf[7],
+			rec_buf[8], rec_buf[9]);
+
+		printk(KERN_INFO "or51211: ver TU%02x%02x%02x VSB mode %02x"
+		       " Status %02x\n",
+		       rec_buf[2], rec_buf[4],rec_buf[6],
+		       rec_buf[12],rec_buf[10]);
+
+		rec_buf[0] = 0x04;
+		rec_buf[1] = 0x00;
+		rec_buf[2] = 0x03;
+		rec_buf[3] = 0x00;
+		msleep(20);
+		if (i2c_writebytes(state,state->config->demod_address,
+				   rec_buf,3)) {
+			printk(KERN_WARNING "or51211: Load DVR Error 8\n");
+			return -1;
+		}
+		msleep(20);
+		if (i2c_readbytes(state,state->config->demod_address,
+				  &rec_buf[8],2)) {
+			printk(KERN_WARNING "or51211: Load DVR Error 9\n");
+			return -1;
+		}
+		state->initialized = 1;
+	}
+
+	return 0;
+}
+
+static int or51211_get_tune_settings(struct dvb_frontend* fe,
+				     struct dvb_frontend_tune_settings* fesettings)
+{
+	fesettings->min_delay_ms = 500;
+	fesettings->step_size = 0;
+	fesettings->max_drift = 0;
+	return 0;
+}
+
+static void or51211_release(struct dvb_frontend* fe)
+{
+	struct or51211_state* state = fe->demodulator_priv;
+	state->config->sleep(fe);
+	kfree(state);
+}
+
+static struct dvb_frontend_ops or51211_ops;
+
+struct dvb_frontend* or51211_attach(const struct or51211_config* config,
+				    struct i2c_adapter* i2c)
+{
+	struct or51211_state* state = NULL;
+
+	/* Allocate memory for the internal state */
+	state = kzalloc(sizeof(struct or51211_state), GFP_KERNEL);
+	if (state == NULL)
+		return NULL;
+
+	/* Setup the state */
+	state->config = config;
+	state->i2c = i2c;
+	state->initialized = 0;
+	state->current_frequency = 0;
+
+	/* Create dvb_frontend */
+	memcpy(&state->frontend.ops, &or51211_ops, sizeof(struct dvb_frontend_ops));
+	state->frontend.demodulator_priv = state;
+	return &state->frontend;
+}
+
+static struct dvb_frontend_ops or51211_ops = {
+	.delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
+	.info = {
+		.name               = "Oren OR51211 VSB Frontend",
+		.frequency_min      = 44000000,
+		.frequency_max      = 958000000,
+		.frequency_stepsize = 166666,
+		.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_FEC_AUTO |
+			FE_CAN_8VSB
+	},
+
+	.release = or51211_release,
+
+	.init = or51211_init,
+	.sleep = or51211_sleep,
+
+	.set_frontend = or51211_set_parameters,
+	.get_tune_settings = or51211_get_tune_settings,
+
+	.read_status = or51211_read_status,
+	.read_ber = or51211_read_ber,
+	.read_signal_strength = or51211_read_signal_strength,
+	.read_snr = or51211_read_snr,
+	.read_ucblocks = or51211_read_ucblocks,
+};
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+
+MODULE_DESCRIPTION("Oren OR51211 VSB [pcHDTV HD-2000] Demodulator Driver");
+MODULE_AUTHOR("Kirk Lapray");
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(or51211_attach);
+
diff --git a/drivers/media/dvb-frontends/or51211.h b/drivers/media/dvb-frontends/or51211.h
new file mode 100644
index 0000000..3ce0508
--- /dev/null
+++ b/drivers/media/dvb-frontends/or51211.h
@@ -0,0 +1,53 @@
+/*
+ *    Support for OR51211 (pcHDTV HD-2000) - VSB
+ *
+ *    Copyright (C) 2005 Kirk Lapray <kirk_lapray@bigfoot.com>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+*/
+
+#ifndef OR51211_H
+#define OR51211_H
+
+#include <linux/dvb/frontend.h>
+#include <linux/firmware.h>
+
+struct or51211_config
+{
+	/* The demodulator's i2c address */
+	u8 demod_address;
+
+	/* Request firmware for device */
+	int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name);
+	void (*setmode)(struct dvb_frontend * fe, int mode);
+	void (*reset)(struct dvb_frontend * fe);
+	void (*sleep)(struct dvb_frontend * fe);
+};
+
+#if defined(CONFIG_DVB_OR51211) || (defined(CONFIG_DVB_OR51211_MODULE) && defined(MODULE))
+extern struct dvb_frontend* or51211_attach(const struct or51211_config* config,
+					   struct i2c_adapter* i2c);
+#else
+static inline struct dvb_frontend* or51211_attach(const struct or51211_config* config,
+					   struct i2c_adapter* i2c)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif // CONFIG_DVB_OR51211
+
+#endif // OR51211_H
+
diff --git a/drivers/media/dvb-frontends/rtl2830.c b/drivers/media/dvb-frontends/rtl2830.c
new file mode 100644
index 0000000..b0f6ec0
--- /dev/null
+++ b/drivers/media/dvb-frontends/rtl2830.c
@@ -0,0 +1,761 @@
+/*
+ * Realtek RTL2830 DVB-T demodulator driver
+ *
+ * Copyright (C) 2011 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.,
+ *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+
+/*
+ * Driver implements own I2C-adapter for tuner I2C access. That's since chip
+ * have unusual I2C-gate control which closes gate automatically after each
+ * I2C transfer. Using own I2C adapter we can workaround that.
+ */
+
+#include "rtl2830_priv.h"
+
+/* write multiple hardware registers */
+static int rtl2830_wr(struct rtl2830_priv *priv, u8 reg, const u8 *val, int len)
+{
+	int ret;
+	u8 buf[1+len];
+	struct i2c_msg msg[1] = {
+		{
+			.addr = priv->cfg.i2c_addr,
+			.flags = 0,
+			.len = 1+len,
+			.buf = buf,
+		}
+	};
+
+	buf[0] = reg;
+	memcpy(&buf[1], val, len);
+
+	ret = i2c_transfer(priv->i2c, msg, 1);
+	if (ret == 1) {
+		ret = 0;
+	} else {
+		dev_warn(&priv->i2c->dev, "%s: i2c wr failed=%d reg=%02x " \
+				"len=%d\n", KBUILD_MODNAME, ret, reg, len);
+		ret = -EREMOTEIO;
+	}
+	return ret;
+}
+
+/* read multiple hardware registers */
+static int rtl2830_rd(struct rtl2830_priv *priv, u8 reg, u8 *val, int len)
+{
+	int ret;
+	struct i2c_msg msg[2] = {
+		{
+			.addr = priv->cfg.i2c_addr,
+			.flags = 0,
+			.len = 1,
+			.buf = &reg,
+		}, {
+			.addr = priv->cfg.i2c_addr,
+			.flags = I2C_M_RD,
+			.len = len,
+			.buf = val,
+		}
+	};
+
+	ret = i2c_transfer(priv->i2c, msg, 2);
+	if (ret == 2) {
+		ret = 0;
+	} else {
+		dev_warn(&priv->i2c->dev, "%s: i2c rd failed=%d reg=%02x " \
+				"len=%d\n", KBUILD_MODNAME, ret, reg, len);
+		ret = -EREMOTEIO;
+	}
+	return ret;
+}
+
+/* write multiple registers */
+static int rtl2830_wr_regs(struct rtl2830_priv *priv, u16 reg, const u8 *val,
+		int len)
+{
+	int ret;
+	u8 reg2 = (reg >> 0) & 0xff;
+	u8 page = (reg >> 8) & 0xff;
+
+	/* switch bank if needed */
+	if (page != priv->page) {
+		ret = rtl2830_wr(priv, 0x00, &page, 1);
+		if (ret)
+			return ret;
+
+		priv->page = page;
+	}
+
+	return rtl2830_wr(priv, reg2, val, len);
+}
+
+/* read multiple registers */
+static int rtl2830_rd_regs(struct rtl2830_priv *priv, u16 reg, u8 *val, int len)
+{
+	int ret;
+	u8 reg2 = (reg >> 0) & 0xff;
+	u8 page = (reg >> 8) & 0xff;
+
+	/* switch bank if needed */
+	if (page != priv->page) {
+		ret = rtl2830_wr(priv, 0x00, &page, 1);
+		if (ret)
+			return ret;
+
+		priv->page = page;
+	}
+
+	return rtl2830_rd(priv, reg2, val, len);
+}
+
+/* read single register */
+static int rtl2830_rd_reg(struct rtl2830_priv *priv, u16 reg, u8 *val)
+{
+	return rtl2830_rd_regs(priv, reg, val, 1);
+}
+
+/* write single register with mask */
+int rtl2830_wr_reg_mask(struct rtl2830_priv *priv, u16 reg, u8 val, u8 mask)
+{
+	int ret;
+	u8 tmp;
+
+	/* no need for read if whole reg is written */
+	if (mask != 0xff) {
+		ret = rtl2830_rd_regs(priv, reg, &tmp, 1);
+		if (ret)
+			return ret;
+
+		val &= mask;
+		tmp &= ~mask;
+		val |= tmp;
+	}
+
+	return rtl2830_wr_regs(priv, reg, &val, 1);
+}
+
+/* read single register with mask */
+int rtl2830_rd_reg_mask(struct rtl2830_priv *priv, u16 reg, u8 *val, u8 mask)
+{
+	int ret, i;
+	u8 tmp;
+
+	ret = rtl2830_rd_regs(priv, reg, &tmp, 1);
+	if (ret)
+		return ret;
+
+	tmp &= mask;
+
+	/* find position of the first bit */
+	for (i = 0; i < 8; i++) {
+		if ((mask >> i) & 0x01)
+			break;
+	}
+	*val = tmp >> i;
+
+	return 0;
+}
+
+static int rtl2830_init(struct dvb_frontend *fe)
+{
+	struct rtl2830_priv *priv = fe->demodulator_priv;
+	int ret, i;
+	struct rtl2830_reg_val_mask tab[] = {
+		{ 0x00d, 0x01, 0x03 },
+		{ 0x00d, 0x10, 0x10 },
+		{ 0x104, 0x00, 0x1e },
+		{ 0x105, 0x80, 0x80 },
+		{ 0x110, 0x02, 0x03 },
+		{ 0x110, 0x08, 0x0c },
+		{ 0x17b, 0x00, 0x40 },
+		{ 0x17d, 0x05, 0x0f },
+		{ 0x17d, 0x50, 0xf0 },
+		{ 0x18c, 0x08, 0x0f },
+		{ 0x18d, 0x00, 0xc0 },
+		{ 0x188, 0x05, 0x0f },
+		{ 0x189, 0x00, 0xfc },
+		{ 0x2d5, 0x02, 0x02 },
+		{ 0x2f1, 0x02, 0x06 },
+		{ 0x2f1, 0x20, 0xf8 },
+		{ 0x16d, 0x00, 0x01 },
+		{ 0x1a6, 0x00, 0x80 },
+		{ 0x106, priv->cfg.vtop, 0x3f },
+		{ 0x107, priv->cfg.krf, 0x3f },
+		{ 0x112, 0x28, 0xff },
+		{ 0x103, priv->cfg.agc_targ_val, 0xff },
+		{ 0x00a, 0x02, 0x07 },
+		{ 0x140, 0x0c, 0x3c },
+		{ 0x140, 0x40, 0xc0 },
+		{ 0x15b, 0x05, 0x07 },
+		{ 0x15b, 0x28, 0x38 },
+		{ 0x15c, 0x05, 0x07 },
+		{ 0x15c, 0x28, 0x38 },
+		{ 0x115, priv->cfg.spec_inv, 0x01 },
+		{ 0x16f, 0x01, 0x07 },
+		{ 0x170, 0x18, 0x38 },
+		{ 0x172, 0x0f, 0x0f },
+		{ 0x173, 0x08, 0x38 },
+		{ 0x175, 0x01, 0x07 },
+		{ 0x176, 0x00, 0xc0 },
+	};
+
+	for (i = 0; i < ARRAY_SIZE(tab); i++) {
+		ret = rtl2830_wr_reg_mask(priv, tab[i].reg, tab[i].val,
+			tab[i].mask);
+		if (ret)
+			goto err;
+	}
+
+	ret = rtl2830_wr_regs(priv, 0x18f, "\x28\x00", 2);
+	if (ret)
+		goto err;
+
+	ret = rtl2830_wr_regs(priv, 0x195,
+		"\x04\x06\x0a\x12\x0a\x12\x1e\x28", 8);
+	if (ret)
+		goto err;
+
+	/* TODO: spec init */
+
+	/* soft reset */
+	ret = rtl2830_wr_reg_mask(priv, 0x101, 0x04, 0x04);
+	if (ret)
+		goto err;
+
+	ret = rtl2830_wr_reg_mask(priv, 0x101, 0x00, 0x04);
+	if (ret)
+		goto err;
+
+	priv->sleeping = false;
+
+	return ret;
+err:
+	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	return ret;
+}
+
+static int rtl2830_sleep(struct dvb_frontend *fe)
+{
+	struct rtl2830_priv *priv = fe->demodulator_priv;
+	priv->sleeping = true;
+	return 0;
+}
+
+int rtl2830_get_tune_settings(struct dvb_frontend *fe,
+	struct dvb_frontend_tune_settings *s)
+{
+	s->min_delay_ms = 500;
+	s->step_size = fe->ops.info.frequency_stepsize * 2;
+	s->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1;
+
+	return 0;
+}
+
+static int rtl2830_set_frontend(struct dvb_frontend *fe)
+{
+	struct rtl2830_priv *priv = fe->demodulator_priv;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	int ret, i;
+	u64 num;
+	u8 buf[3], tmp;
+	u32 if_ctl, if_frequency;
+	static const u8 bw_params1[3][34] = {
+		{
+		0x1f, 0xf0, 0x1f, 0xf0, 0x1f, 0xfa, 0x00, 0x17, 0x00, 0x41,
+		0x00, 0x64, 0x00, 0x67, 0x00, 0x38, 0x1f, 0xde, 0x1f, 0x7a,
+		0x1f, 0x47, 0x1f, 0x7c, 0x00, 0x30, 0x01, 0x4b, 0x02, 0x82,
+		0x03, 0x73, 0x03, 0xcf, /* 6 MHz */
+		}, {
+		0x1f, 0xfa, 0x1f, 0xda, 0x1f, 0xc1, 0x1f, 0xb3, 0x1f, 0xca,
+		0x00, 0x07, 0x00, 0x4d, 0x00, 0x6d, 0x00, 0x40, 0x1f, 0xca,
+		0x1f, 0x4d, 0x1f, 0x2a, 0x1f, 0xb2, 0x00, 0xec, 0x02, 0x7e,
+		0x03, 0xd0, 0x04, 0x53, /* 7 MHz */
+		}, {
+		0x00, 0x10, 0x00, 0x0e, 0x1f, 0xf7, 0x1f, 0xc9, 0x1f, 0xa0,
+		0x1f, 0xa6, 0x1f, 0xec, 0x00, 0x4e, 0x00, 0x7d, 0x00, 0x3a,
+		0x1f, 0x98, 0x1f, 0x10, 0x1f, 0x40, 0x00, 0x75, 0x02, 0x5f,
+		0x04, 0x24, 0x04, 0xdb, /* 8 MHz */
+		},
+	};
+	static const u8 bw_params2[3][6] = {
+		{0xc3, 0x0c, 0x44, 0x33, 0x33, 0x30}, /* 6 MHz */
+		{0xb8, 0xe3, 0x93, 0x99, 0x99, 0x98}, /* 7 MHz */
+		{0xae, 0xba, 0xf3, 0x26, 0x66, 0x64}, /* 8 MHz */
+	};
+
+	dev_dbg(&priv->i2c->dev,
+			"%s: frequency=%d bandwidth_hz=%d inversion=%d\n",
+			__func__, c->frequency, c->bandwidth_hz, c->inversion);
+
+	/* program tuner */
+	if (fe->ops.tuner_ops.set_params)
+		fe->ops.tuner_ops.set_params(fe);
+
+	switch (c->bandwidth_hz) {
+	case 6000000:
+		i = 0;
+		break;
+	case 7000000:
+		i = 1;
+		break;
+	case 8000000:
+		i = 2;
+		break;
+	default:
+		dev_dbg(&priv->i2c->dev, "%s: invalid bandwidth\n", __func__);
+		return -EINVAL;
+	}
+
+	ret = rtl2830_wr_reg_mask(priv, 0x008, i << 1, 0x06);
+	if (ret)
+		goto err;
+
+	/* program if frequency */
+	if (fe->ops.tuner_ops.get_if_frequency)
+		ret = fe->ops.tuner_ops.get_if_frequency(fe, &if_frequency);
+	else
+		ret = -EINVAL;
+
+	if (ret < 0)
+		goto err;
+
+	num = if_frequency % priv->cfg.xtal;
+	num *= 0x400000;
+	num = div_u64(num, priv->cfg.xtal);
+	num = -num;
+	if_ctl = num & 0x3fffff;
+	dev_dbg(&priv->i2c->dev, "%s: if_frequency=%d if_ctl=%08x\n",
+			__func__, if_frequency, if_ctl);
+
+	ret = rtl2830_rd_reg_mask(priv, 0x119, &tmp, 0xc0); /* b[7:6] */
+	if (ret)
+		goto err;
+
+	buf[0] = tmp << 6;
+	buf[0] |= (if_ctl >> 16) & 0x3f;
+	buf[1] = (if_ctl >>  8) & 0xff;
+	buf[2] = (if_ctl >>  0) & 0xff;
+
+	ret = rtl2830_wr_regs(priv, 0x119, buf, 3);
+	if (ret)
+		goto err;
+
+	/* 1/2 split I2C write */
+	ret = rtl2830_wr_regs(priv, 0x11c, &bw_params1[i][0], 17);
+	if (ret)
+		goto err;
+
+	/* 2/2 split I2C write */
+	ret = rtl2830_wr_regs(priv, 0x12d, &bw_params1[i][17], 17);
+	if (ret)
+		goto err;
+
+	ret = rtl2830_wr_regs(priv, 0x19d, bw_params2[i], 6);
+	if (ret)
+		goto err;
+
+	return ret;
+err:
+	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	return ret;
+}
+
+static int rtl2830_get_frontend(struct dvb_frontend *fe)
+{
+	struct rtl2830_priv *priv = fe->demodulator_priv;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	int ret;
+	u8 buf[3];
+
+	if (priv->sleeping)
+		return 0;
+
+	ret = rtl2830_rd_regs(priv, 0x33c, buf, 2);
+	if (ret)
+		goto err;
+
+	ret = rtl2830_rd_reg(priv, 0x351, &buf[2]);
+	if (ret)
+		goto err;
+
+	dev_dbg(&priv->i2c->dev, "%s: TPS=%*ph\n", __func__, 3, buf);
+
+	switch ((buf[0] >> 2) & 3) {
+	case 0:
+		c->modulation = QPSK;
+		break;
+	case 1:
+		c->modulation = QAM_16;
+		break;
+	case 2:
+		c->modulation = QAM_64;
+		break;
+	}
+
+	switch ((buf[2] >> 2) & 1) {
+	case 0:
+		c->transmission_mode = TRANSMISSION_MODE_2K;
+		break;
+	case 1:
+		c->transmission_mode = TRANSMISSION_MODE_8K;
+	}
+
+	switch ((buf[2] >> 0) & 3) {
+	case 0:
+		c->guard_interval = GUARD_INTERVAL_1_32;
+		break;
+	case 1:
+		c->guard_interval = GUARD_INTERVAL_1_16;
+		break;
+	case 2:
+		c->guard_interval = GUARD_INTERVAL_1_8;
+		break;
+	case 3:
+		c->guard_interval = GUARD_INTERVAL_1_4;
+		break;
+	}
+
+	switch ((buf[0] >> 4) & 7) {
+	case 0:
+		c->hierarchy = HIERARCHY_NONE;
+		break;
+	case 1:
+		c->hierarchy = HIERARCHY_1;
+		break;
+	case 2:
+		c->hierarchy = HIERARCHY_2;
+		break;
+	case 3:
+		c->hierarchy = HIERARCHY_4;
+		break;
+	}
+
+	switch ((buf[1] >> 3) & 7) {
+	case 0:
+		c->code_rate_HP = FEC_1_2;
+		break;
+	case 1:
+		c->code_rate_HP = FEC_2_3;
+		break;
+	case 2:
+		c->code_rate_HP = FEC_3_4;
+		break;
+	case 3:
+		c->code_rate_HP = FEC_5_6;
+		break;
+	case 4:
+		c->code_rate_HP = FEC_7_8;
+		break;
+	}
+
+	switch ((buf[1] >> 0) & 7) {
+	case 0:
+		c->code_rate_LP = FEC_1_2;
+		break;
+	case 1:
+		c->code_rate_LP = FEC_2_3;
+		break;
+	case 2:
+		c->code_rate_LP = FEC_3_4;
+		break;
+	case 3:
+		c->code_rate_LP = FEC_5_6;
+		break;
+	case 4:
+		c->code_rate_LP = FEC_7_8;
+		break;
+	}
+
+	return 0;
+err:
+	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	return ret;
+}
+
+static int rtl2830_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+	struct rtl2830_priv *priv = fe->demodulator_priv;
+	int ret;
+	u8 tmp;
+	*status = 0;
+
+	if (priv->sleeping)
+		return 0;
+
+	ret = rtl2830_rd_reg_mask(priv, 0x351, &tmp, 0x78); /* [6:3] */
+	if (ret)
+		goto err;
+
+	if (tmp == 11) {
+		*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
+			FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
+	} else if (tmp == 10) {
+		*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
+			FE_HAS_VITERBI;
+	}
+
+	return ret;
+err:
+	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	return ret;
+}
+
+static int rtl2830_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+	struct rtl2830_priv *priv = fe->demodulator_priv;
+	int ret, hierarchy, constellation;
+	u8 buf[2], tmp;
+	u16 tmp16;
+#define CONSTELLATION_NUM 3
+#define HIERARCHY_NUM 4
+	static const u32 snr_constant[CONSTELLATION_NUM][HIERARCHY_NUM] = {
+		{ 70705899, 70705899, 70705899, 70705899 },
+		{ 82433173, 82433173, 87483115, 94445660 },
+		{ 92888734, 92888734, 95487525, 99770748 },
+	};
+
+	if (priv->sleeping)
+		return 0;
+
+	/* reports SNR in resolution of 0.1 dB */
+
+	ret = rtl2830_rd_reg(priv, 0x33c, &tmp);
+	if (ret)
+		goto err;
+
+	constellation = (tmp >> 2) & 0x03; /* [3:2] */
+	if (constellation > CONSTELLATION_NUM - 1)
+		goto err;
+
+	hierarchy = (tmp >> 4) & 0x07; /* [6:4] */
+	if (hierarchy > HIERARCHY_NUM - 1)
+		goto err;
+
+	ret = rtl2830_rd_regs(priv, 0x40c, buf, 2);
+	if (ret)
+		goto err;
+
+	tmp16 = buf[0] << 8 | buf[1];
+
+	if (tmp16)
+		*snr = (snr_constant[constellation][hierarchy] -
+				intlog10(tmp16)) / ((1 << 24) / 100);
+	else
+		*snr = 0;
+
+	return 0;
+err:
+	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	return ret;
+}
+
+static int rtl2830_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+	struct rtl2830_priv *priv = fe->demodulator_priv;
+	int ret;
+	u8 buf[2];
+
+	if (priv->sleeping)
+		return 0;
+
+	ret = rtl2830_rd_regs(priv, 0x34e, buf, 2);
+	if (ret)
+		goto err;
+
+	*ber = buf[0] << 8 | buf[1];
+
+	return 0;
+err:
+	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	return ret;
+}
+
+static int rtl2830_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+	*ucblocks = 0;
+	return 0;
+}
+
+static int rtl2830_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
+{
+	struct rtl2830_priv *priv = fe->demodulator_priv;
+	int ret;
+	u8 buf[2];
+	u16 if_agc_raw, if_agc;
+
+	if (priv->sleeping)
+		return 0;
+
+	ret = rtl2830_rd_regs(priv, 0x359, buf, 2);
+	if (ret)
+		goto err;
+
+	if_agc_raw = (buf[0] << 8 | buf[1]) & 0x3fff;
+
+	if (if_agc_raw & (1 << 9))
+		if_agc = -(~(if_agc_raw - 1) & 0x1ff);
+	else
+		if_agc = if_agc_raw;
+
+	*strength = (u8) (55 - if_agc / 182);
+	*strength |= *strength << 8;
+
+	return 0;
+err:
+	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	return ret;
+}
+
+static struct dvb_frontend_ops rtl2830_ops;
+
+static u32 rtl2830_tuner_i2c_func(struct i2c_adapter *adapter)
+{
+	return I2C_FUNC_I2C;
+}
+
+static int rtl2830_tuner_i2c_xfer(struct i2c_adapter *i2c_adap,
+	struct i2c_msg msg[], int num)
+{
+	struct rtl2830_priv *priv = i2c_get_adapdata(i2c_adap);
+	int ret;
+
+	/* open i2c-gate */
+	ret = rtl2830_wr_reg_mask(priv, 0x101, 0x08, 0x08);
+	if (ret)
+		goto err;
+
+	ret = i2c_transfer(priv->i2c, msg, num);
+	if (ret < 0)
+		dev_warn(&priv->i2c->dev, "%s: tuner i2c failed=%d\n",
+			KBUILD_MODNAME, ret);
+
+	return ret;
+err:
+	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	return ret;
+}
+
+static struct i2c_algorithm rtl2830_tuner_i2c_algo = {
+	.master_xfer   = rtl2830_tuner_i2c_xfer,
+	.functionality = rtl2830_tuner_i2c_func,
+};
+
+struct i2c_adapter *rtl2830_get_tuner_i2c_adapter(struct dvb_frontend *fe)
+{
+	struct rtl2830_priv *priv = fe->demodulator_priv;
+	return &priv->tuner_i2c_adapter;
+}
+EXPORT_SYMBOL(rtl2830_get_tuner_i2c_adapter);
+
+static void rtl2830_release(struct dvb_frontend *fe)
+{
+	struct rtl2830_priv *priv = fe->demodulator_priv;
+
+	i2c_del_adapter(&priv->tuner_i2c_adapter);
+	kfree(priv);
+}
+
+struct dvb_frontend *rtl2830_attach(const struct rtl2830_config *cfg,
+	struct i2c_adapter *i2c)
+{
+	struct rtl2830_priv *priv = NULL;
+	int ret = 0;
+	u8 tmp;
+
+	/* allocate memory for the internal state */
+	priv = kzalloc(sizeof(struct rtl2830_priv), GFP_KERNEL);
+	if (priv == NULL)
+		goto err;
+
+	/* setup the priv */
+	priv->i2c = i2c;
+	memcpy(&priv->cfg, cfg, sizeof(struct rtl2830_config));
+
+	/* check if the demod is there */
+	ret = rtl2830_rd_reg(priv, 0x000, &tmp);
+	if (ret)
+		goto err;
+
+	/* create dvb_frontend */
+	memcpy(&priv->fe.ops, &rtl2830_ops, sizeof(struct dvb_frontend_ops));
+	priv->fe.demodulator_priv = priv;
+
+	/* create tuner i2c adapter */
+	strlcpy(priv->tuner_i2c_adapter.name, "RTL2830 tuner I2C adapter",
+		sizeof(priv->tuner_i2c_adapter.name));
+	priv->tuner_i2c_adapter.algo = &rtl2830_tuner_i2c_algo;
+	priv->tuner_i2c_adapter.algo_data = NULL;
+	i2c_set_adapdata(&priv->tuner_i2c_adapter, priv);
+	if (i2c_add_adapter(&priv->tuner_i2c_adapter) < 0) {
+		dev_err(&i2c->dev,
+				"%s: tuner i2c bus could not be initialized\n",
+				KBUILD_MODNAME);
+		goto err;
+	}
+
+	priv->sleeping = true;
+
+	return &priv->fe;
+err:
+	dev_dbg(&i2c->dev, "%s: failed=%d\n", __func__, ret);
+	kfree(priv);
+	return NULL;
+}
+EXPORT_SYMBOL(rtl2830_attach);
+
+static struct dvb_frontend_ops rtl2830_ops = {
+	.delsys = { SYS_DVBT },
+	.info = {
+		.name = "Realtek RTL2830 (DVB-T)",
+		.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_FEC_AUTO |
+			FE_CAN_QPSK |
+			FE_CAN_QAM_16 |
+			FE_CAN_QAM_64 |
+			FE_CAN_QAM_AUTO |
+			FE_CAN_TRANSMISSION_MODE_AUTO |
+			FE_CAN_GUARD_INTERVAL_AUTO |
+			FE_CAN_HIERARCHY_AUTO |
+			FE_CAN_RECOVER |
+			FE_CAN_MUTE_TS
+	},
+
+	.release = rtl2830_release,
+
+	.init = rtl2830_init,
+	.sleep = rtl2830_sleep,
+
+	.get_tune_settings = rtl2830_get_tune_settings,
+
+	.set_frontend = rtl2830_set_frontend,
+	.get_frontend = rtl2830_get_frontend,
+
+	.read_status = rtl2830_read_status,
+	.read_snr = rtl2830_read_snr,
+	.read_ber = rtl2830_read_ber,
+	.read_ucblocks = rtl2830_read_ucblocks,
+	.read_signal_strength = rtl2830_read_signal_strength,
+};
+
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
+MODULE_DESCRIPTION("Realtek RTL2830 DVB-T demodulator driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb-frontends/rtl2830.h b/drivers/media/dvb-frontends/rtl2830.h
new file mode 100644
index 0000000..f4349a1
--- /dev/null
+++ b/drivers/media/dvb-frontends/rtl2830.h
@@ -0,0 +1,90 @@
+/*
+ * Realtek RTL2830 DVB-T demodulator driver
+ *
+ * Copyright (C) 2011 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.,
+ *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef RTL2830_H
+#define RTL2830_H
+
+#include <linux/dvb/frontend.h>
+
+struct rtl2830_config {
+	/*
+	 * Demodulator I2C address.
+	 */
+	u8 i2c_addr;
+
+	/*
+	 * Xtal frequency.
+	 * Hz
+	 * 4000000, 16000000, 25000000, 28800000
+	 */
+	u32 xtal;
+
+	/*
+	 * TS output mode.
+	 */
+	u8 ts_mode;
+
+	/*
+	 * Spectrum inversion.
+	 */
+	bool spec_inv;
+
+	/*
+	 */
+	u8 vtop;
+
+	/*
+	 */
+	u8 krf;
+
+	/*
+	 */
+	u8 agc_targ_val;
+};
+
+#if defined(CONFIG_DVB_RTL2830) || \
+	(defined(CONFIG_DVB_RTL2830_MODULE) && defined(MODULE))
+extern struct dvb_frontend *rtl2830_attach(
+	const struct rtl2830_config *config,
+	struct i2c_adapter *i2c
+);
+
+extern struct i2c_adapter *rtl2830_get_tuner_i2c_adapter(
+	struct dvb_frontend *fe
+);
+#else
+static inline struct dvb_frontend *rtl2830_attach(
+	const struct rtl2830_config *config,
+	struct i2c_adapter *i2c
+)
+{
+	pr_warn("%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+
+static inline struct i2c_adapter *rtl2830_get_tuner_i2c_adapter(
+	struct dvb_frontend *fe
+)
+{
+	return NULL;
+}
+#endif
+
+#endif /* RTL2830_H */
diff --git a/drivers/media/dvb-frontends/rtl2830_priv.h b/drivers/media/dvb-frontends/rtl2830_priv.h
new file mode 100644
index 0000000..fab10ec
--- /dev/null
+++ b/drivers/media/dvb-frontends/rtl2830_priv.h
@@ -0,0 +1,45 @@
+/*
+ * Realtek RTL2830 DVB-T demodulator driver
+ *
+ * Copyright (C) 2011 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.,
+ *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef RTL2830_PRIV_H
+#define RTL2830_PRIV_H
+
+#include "dvb_frontend.h"
+#include "dvb_math.h"
+#include "rtl2830.h"
+
+struct rtl2830_priv {
+	struct i2c_adapter *i2c;
+	struct dvb_frontend fe;
+	struct rtl2830_config cfg;
+	struct i2c_adapter tuner_i2c_adapter;
+
+	bool sleeping;
+
+	u8 page; /* active register page */
+};
+
+struct rtl2830_reg_val_mask {
+	u16 reg;
+	u8  val;
+	u8  mask;
+};
+
+#endif /* RTL2830_PRIV_H */
diff --git a/drivers/media/dvb-frontends/rtl2832.c b/drivers/media/dvb-frontends/rtl2832.c
new file mode 100644
index 0000000..aaf0c29
--- /dev/null
+++ b/drivers/media/dvb-frontends/rtl2832.c
@@ -0,0 +1,928 @@
+/*
+ * Realtek RTL2832 DVB-T demodulator driver
+ *
+ * Copyright (C) 2012 Thomas Mair <thomas.mair86@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 "rtl2832_priv.h"
+#include "dvb_math.h"
+#include <linux/bitops.h>
+
+int rtl2832_debug;
+module_param_named(debug, rtl2832_debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+
+#define REG_MASK(b) (BIT(b + 1) - 1)
+
+static const struct rtl2832_reg_entry registers[] = {
+	[DVBT_SOFT_RST]		= {0x1, 0x1,   2, 2},
+	[DVBT_IIC_REPEAT]	= {0x1, 0x1,   3, 3},
+	[DVBT_TR_WAIT_MIN_8K]	= {0x1, 0x88, 11, 2},
+	[DVBT_RSD_BER_FAIL_VAL]	= {0x1, 0x8f, 15, 0},
+	[DVBT_EN_BK_TRK]	= {0x1, 0xa6,  7, 7},
+	[DVBT_AD_EN_REG]	= {0x0, 0x8,   7, 7},
+	[DVBT_AD_EN_REG1]	= {0x0, 0x8,   6, 6},
+	[DVBT_EN_BBIN]		= {0x1, 0xb1,  0, 0},
+	[DVBT_MGD_THD0]		= {0x1, 0x95,  7, 0},
+	[DVBT_MGD_THD1]		= {0x1, 0x96,  7, 0},
+	[DVBT_MGD_THD2]		= {0x1, 0x97,  7, 0},
+	[DVBT_MGD_THD3]		= {0x1, 0x98,  7, 0},
+	[DVBT_MGD_THD4]		= {0x1, 0x99,  7, 0},
+	[DVBT_MGD_THD5]		= {0x1, 0x9a,  7, 0},
+	[DVBT_MGD_THD6]		= {0x1, 0x9b,  7, 0},
+	[DVBT_MGD_THD7]		= {0x1, 0x9c,  7, 0},
+	[DVBT_EN_CACQ_NOTCH]	= {0x1, 0x61,  4, 4},
+	[DVBT_AD_AV_REF]	= {0x0, 0x9,   6, 0},
+	[DVBT_REG_PI]		= {0x0, 0xa,   2, 0},
+	[DVBT_PIP_ON]		= {0x0, 0x21,  3, 3},
+	[DVBT_SCALE1_B92]	= {0x2, 0x92,  7, 0},
+	[DVBT_SCALE1_B93]	= {0x2, 0x93,  7, 0},
+	[DVBT_SCALE1_BA7]	= {0x2, 0xa7,  7, 0},
+	[DVBT_SCALE1_BA9]	= {0x2, 0xa9,  7, 0},
+	[DVBT_SCALE1_BAA]	= {0x2, 0xaa,  7, 0},
+	[DVBT_SCALE1_BAB]	= {0x2, 0xab,  7, 0},
+	[DVBT_SCALE1_BAC]	= {0x2, 0xac,  7, 0},
+	[DVBT_SCALE1_BB0]	= {0x2, 0xb0,  7, 0},
+	[DVBT_SCALE1_BB1]	= {0x2, 0xb1,  7, 0},
+	[DVBT_KB_P1]		= {0x1, 0x64,  3, 1},
+	[DVBT_KB_P2]		= {0x1, 0x64,  6, 4},
+	[DVBT_KB_P3]		= {0x1, 0x65,  2, 0},
+	[DVBT_OPT_ADC_IQ]	= {0x0, 0x6,   5, 4},
+	[DVBT_AD_AVI]		= {0x0, 0x9,   1, 0},
+	[DVBT_AD_AVQ]		= {0x0, 0x9,   3, 2},
+	[DVBT_K1_CR_STEP12]	= {0x2, 0xad,  9, 4},
+	[DVBT_TRK_KS_P2]	= {0x1, 0x6f,  2, 0},
+	[DVBT_TRK_KS_I2]	= {0x1, 0x70,  5, 3},
+	[DVBT_TR_THD_SET2]	= {0x1, 0x72,  3, 0},
+	[DVBT_TRK_KC_P2]	= {0x1, 0x73,  5, 3},
+	[DVBT_TRK_KC_I2]	= {0x1, 0x75,  2, 0},
+	[DVBT_CR_THD_SET2]	= {0x1, 0x76,  7, 6},
+	[DVBT_PSET_IFFREQ]	= {0x1, 0x19, 21, 0},
+	[DVBT_SPEC_INV]		= {0x1, 0x15,  0, 0},
+	[DVBT_RSAMP_RATIO]	= {0x1, 0x9f, 27, 2},
+	[DVBT_CFREQ_OFF_RATIO]	= {0x1, 0x9d, 23, 4},
+	[DVBT_FSM_STAGE]	= {0x3, 0x51,  6, 3},
+	[DVBT_RX_CONSTEL]	= {0x3, 0x3c,  3, 2},
+	[DVBT_RX_HIER]		= {0x3, 0x3c,  6, 4},
+	[DVBT_RX_C_RATE_LP]	= {0x3, 0x3d,  2, 0},
+	[DVBT_RX_C_RATE_HP]	= {0x3, 0x3d,  5, 3},
+	[DVBT_GI_IDX]		= {0x3, 0x51,  1, 0},
+	[DVBT_FFT_MODE_IDX]	= {0x3, 0x51,  2, 2},
+	[DVBT_RSD_BER_EST]	= {0x3, 0x4e, 15, 0},
+	[DVBT_CE_EST_EVM]	= {0x4, 0xc,  15, 0},
+	[DVBT_RF_AGC_VAL]	= {0x3, 0x5b, 13, 0},
+	[DVBT_IF_AGC_VAL]	= {0x3, 0x59, 13, 0},
+	[DVBT_DAGC_VAL]		= {0x3, 0x5,   7, 0},
+	[DVBT_SFREQ_OFF]	= {0x3, 0x18, 13, 0},
+	[DVBT_CFREQ_OFF]	= {0x3, 0x5f, 17, 0},
+	[DVBT_POLAR_RF_AGC]	= {0x0, 0xe,   1, 1},
+	[DVBT_POLAR_IF_AGC]	= {0x0, 0xe,   0, 0},
+	[DVBT_AAGC_HOLD]	= {0x1, 0x4,   5, 5},
+	[DVBT_EN_RF_AGC]	= {0x1, 0x4,   6, 6},
+	[DVBT_EN_IF_AGC]	= {0x1, 0x4,   7, 7},
+	[DVBT_IF_AGC_MIN]	= {0x1, 0x8,   7, 0},
+	[DVBT_IF_AGC_MAX]	= {0x1, 0x9,   7, 0},
+	[DVBT_RF_AGC_MIN]	= {0x1, 0xa,   7, 0},
+	[DVBT_RF_AGC_MAX]	= {0x1, 0xb,   7, 0},
+	[DVBT_IF_AGC_MAN]	= {0x1, 0xc,   6, 6},
+	[DVBT_IF_AGC_MAN_VAL]	= {0x1, 0xc,  13, 0},
+	[DVBT_RF_AGC_MAN]	= {0x1, 0xe,   6, 6},
+	[DVBT_RF_AGC_MAN_VAL]	= {0x1, 0xe,  13, 0},
+	[DVBT_DAGC_TRG_VAL]	= {0x1, 0x12,  7, 0},
+	[DVBT_AGC_TARG_VAL_0]	= {0x1, 0x2,   0, 0},
+	[DVBT_AGC_TARG_VAL_8_1]	= {0x1, 0x3,   7, 0},
+	[DVBT_AAGC_LOOP_GAIN]	= {0x1, 0xc7,  5, 1},
+	[DVBT_LOOP_GAIN2_3_0]	= {0x1, 0x4,   4, 1},
+	[DVBT_LOOP_GAIN2_4]	= {0x1, 0x5,   7, 7},
+	[DVBT_LOOP_GAIN3]	= {0x1, 0xc8,  4, 0},
+	[DVBT_VTOP1]		= {0x1, 0x6,   5, 0},
+	[DVBT_VTOP2]		= {0x1, 0xc9,  5, 0},
+	[DVBT_VTOP3]		= {0x1, 0xca,  5, 0},
+	[DVBT_KRF1]		= {0x1, 0xcb,  7, 0},
+	[DVBT_KRF2]		= {0x1, 0x7,   7, 0},
+	[DVBT_KRF3]		= {0x1, 0xcd,  7, 0},
+	[DVBT_KRF4]		= {0x1, 0xce,  7, 0},
+	[DVBT_EN_GI_PGA]	= {0x1, 0xe5,  0, 0},
+	[DVBT_THD_LOCK_UP]	= {0x1, 0xd9,  8, 0},
+	[DVBT_THD_LOCK_DW]	= {0x1, 0xdb,  8, 0},
+	[DVBT_THD_UP1]		= {0x1, 0xdd,  7, 0},
+	[DVBT_THD_DW1]		= {0x1, 0xde,  7, 0},
+	[DVBT_INTER_CNT_LEN]	= {0x1, 0xd8,  3, 0},
+	[DVBT_GI_PGA_STATE]	= {0x1, 0xe6,  3, 3},
+	[DVBT_EN_AGC_PGA]	= {0x1, 0xd7,  0, 0},
+	[DVBT_CKOUTPAR]		= {0x1, 0x7b,  5, 5},
+	[DVBT_CKOUT_PWR]	= {0x1, 0x7b,  6, 6},
+	[DVBT_SYNC_DUR]		= {0x1, 0x7b,  7, 7},
+	[DVBT_ERR_DUR]		= {0x1, 0x7c,  0, 0},
+	[DVBT_SYNC_LVL]		= {0x1, 0x7c,  1, 1},
+	[DVBT_ERR_LVL]		= {0x1, 0x7c,  2, 2},
+	[DVBT_VAL_LVL]		= {0x1, 0x7c,  3, 3},
+	[DVBT_SERIAL]		= {0x1, 0x7c,  4, 4},
+	[DVBT_SER_LSB]		= {0x1, 0x7c,  5, 5},
+	[DVBT_CDIV_PH0]		= {0x1, 0x7d,  3, 0},
+	[DVBT_CDIV_PH1]		= {0x1, 0x7d,  7, 4},
+	[DVBT_MPEG_IO_OPT_2_2]	= {0x0, 0x6,   7, 7},
+	[DVBT_MPEG_IO_OPT_1_0]	= {0x0, 0x7,   7, 6},
+	[DVBT_CKOUTPAR_PIP]	= {0x0, 0xb7,  4, 4},
+	[DVBT_CKOUT_PWR_PIP]	= {0x0, 0xb7,  3, 3},
+	[DVBT_SYNC_LVL_PIP]	= {0x0, 0xb7,  2, 2},
+	[DVBT_ERR_LVL_PIP]	= {0x0, 0xb7,  1, 1},
+	[DVBT_VAL_LVL_PIP]	= {0x0, 0xb7,  0, 0},
+	[DVBT_CKOUTPAR_PID]	= {0x0, 0xb9,  4, 4},
+	[DVBT_CKOUT_PWR_PID]	= {0x0, 0xb9,  3, 3},
+	[DVBT_SYNC_LVL_PID]	= {0x0, 0xb9,  2, 2},
+	[DVBT_ERR_LVL_PID]	= {0x0, 0xb9,  1, 1},
+	[DVBT_VAL_LVL_PID]	= {0x0, 0xb9,  0, 0},
+	[DVBT_SM_PASS]		= {0x1, 0x93, 11, 0},
+	[DVBT_AD7_SETTING]	= {0x0, 0x11, 15, 0},
+	[DVBT_RSSI_R]		= {0x3, 0x1,   6, 0},
+	[DVBT_ACI_DET_IND]	= {0x3, 0x12,  0, 0},
+	[DVBT_REG_MON]		= {0x0, 0xd,   1, 0},
+	[DVBT_REG_MONSEL]	= {0x0, 0xd,   2, 2},
+	[DVBT_REG_GPE]		= {0x0, 0xd,   7, 7},
+	[DVBT_REG_GPO]		= {0x0, 0x10,  0, 0},
+	[DVBT_REG_4MSEL]	= {0x0, 0x13,  0, 0},
+};
+
+/* write multiple hardware registers */
+static int rtl2832_wr(struct rtl2832_priv *priv, u8 reg, u8 *val, int len)
+{
+	int ret;
+	u8 buf[1+len];
+	struct i2c_msg msg[1] = {
+		{
+			.addr = priv->cfg.i2c_addr,
+			.flags = 0,
+			.len = 1+len,
+			.buf = buf,
+		}
+	};
+
+	buf[0] = reg;
+	memcpy(&buf[1], val, len);
+
+	ret = i2c_transfer(priv->i2c, msg, 1);
+	if (ret == 1) {
+		ret = 0;
+	} else {
+		dev_warn(&priv->i2c->dev, "%s: i2c wr failed=%d reg=%02x " \
+				"len=%d\n", KBUILD_MODNAME, ret, reg, len);
+		ret = -EREMOTEIO;
+	}
+	return ret;
+}
+
+/* read multiple hardware registers */
+static int rtl2832_rd(struct rtl2832_priv *priv, u8 reg, u8 *val, int len)
+{
+	int ret;
+	struct i2c_msg msg[2] = {
+		{
+			.addr = priv->cfg.i2c_addr,
+			.flags = 0,
+			.len = 1,
+			.buf = &reg,
+		}, {
+			.addr = priv->cfg.i2c_addr,
+			.flags = I2C_M_RD,
+			.len = len,
+			.buf = val,
+		}
+	};
+
+	ret = i2c_transfer(priv->i2c, msg, 2);
+	if (ret == 2) {
+		ret = 0;
+	} else {
+		dev_warn(&priv->i2c->dev, "%s: i2c rd failed=%d reg=%02x " \
+				"len=%d\n", KBUILD_MODNAME, ret, reg, len);
+		ret = -EREMOTEIO;
+	}
+	return ret;
+}
+
+/* write multiple registers */
+static int rtl2832_wr_regs(struct rtl2832_priv *priv, u8 reg, u8 page, u8 *val,
+	int len)
+{
+	int ret;
+
+	/* switch bank if needed */
+	if (page != priv->page) {
+		ret = rtl2832_wr(priv, 0x00, &page, 1);
+		if (ret)
+			return ret;
+
+		priv->page = page;
+}
+
+return rtl2832_wr(priv, reg, val, len);
+}
+
+/* read multiple registers */
+static int rtl2832_rd_regs(struct rtl2832_priv *priv, u8 reg, u8 page, u8 *val,
+	int len)
+{
+	int ret;
+
+	/* switch bank if needed */
+	if (page != priv->page) {
+		ret = rtl2832_wr(priv, 0x00, &page, 1);
+		if (ret)
+			return ret;
+
+		priv->page = page;
+	}
+
+	return rtl2832_rd(priv, reg, val, len);
+}
+
+#if 0 /* currently not used */
+/* write single register */
+static int rtl2832_wr_reg(struct rtl2832_priv *priv, u8 reg, u8 page, u8 val)
+{
+	return rtl2832_wr_regs(priv, reg, page, &val, 1);
+}
+#endif
+
+/* read single register */
+static int rtl2832_rd_reg(struct rtl2832_priv *priv, u8 reg, u8 page, u8 *val)
+{
+	return rtl2832_rd_regs(priv, reg, page, val, 1);
+}
+
+int rtl2832_rd_demod_reg(struct rtl2832_priv *priv, int reg, u32 *val)
+{
+	int ret;
+
+	u8 reg_start_addr;
+	u8 msb, lsb;
+	u8 page;
+	u8 reading[4];
+	u32 reading_tmp;
+	int i;
+
+	u8 len;
+	u32 mask;
+
+	reg_start_addr = registers[reg].start_address;
+	msb = registers[reg].msb;
+	lsb = registers[reg].lsb;
+	page = registers[reg].page;
+
+	len = (msb >> 3) + 1;
+	mask = REG_MASK(msb - lsb);
+
+	ret = rtl2832_rd_regs(priv, reg_start_addr, page, &reading[0], len);
+	if (ret)
+		goto err;
+
+	reading_tmp = 0;
+	for (i = 0; i < len; i++)
+		reading_tmp |= reading[i] << ((len - 1 - i) * 8);
+
+	*val = (reading_tmp >> lsb) & mask;
+
+	return ret;
+
+err:
+	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	return ret;
+
+}
+
+int rtl2832_wr_demod_reg(struct rtl2832_priv *priv, int reg, u32 val)
+{
+	int ret, i;
+	u8 len;
+	u8 reg_start_addr;
+	u8 msb, lsb;
+	u8 page;
+	u32 mask;
+
+
+	u8 reading[4];
+	u8 writing[4];
+	u32 reading_tmp;
+	u32 writing_tmp;
+
+
+	reg_start_addr = registers[reg].start_address;
+	msb = registers[reg].msb;
+	lsb = registers[reg].lsb;
+	page = registers[reg].page;
+
+	len = (msb >> 3) + 1;
+	mask = REG_MASK(msb - lsb);
+
+
+	ret = rtl2832_rd_regs(priv, reg_start_addr, page, &reading[0], len);
+	if (ret)
+		goto err;
+
+	reading_tmp = 0;
+	for (i = 0; i < len; i++)
+		reading_tmp |= reading[i] << ((len - 1 - i) * 8);
+
+	writing_tmp = reading_tmp & ~(mask << lsb);
+	writing_tmp |= ((val & mask) << lsb);
+
+
+	for (i = 0; i < len; i++)
+		writing[i] = (writing_tmp >> ((len - 1 - i) * 8)) & 0xff;
+
+	ret = rtl2832_wr_regs(priv, reg_start_addr, page, &writing[0], len);
+	if (ret)
+		goto err;
+
+	return ret;
+
+err:
+	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	return ret;
+
+}
+
+static int rtl2832_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+	int ret;
+	struct rtl2832_priv *priv = fe->demodulator_priv;
+
+	dev_dbg(&priv->i2c->dev, "%s: enable=%d\n", __func__, enable);
+
+	/* gate already open or close */
+	if (priv->i2c_gate_state == enable)
+		return 0;
+
+	ret = rtl2832_wr_demod_reg(priv, DVBT_IIC_REPEAT, (enable ? 0x1 : 0x0));
+	if (ret)
+		goto err;
+
+	priv->i2c_gate_state = enable;
+
+	return ret;
+err:
+	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	return ret;
+}
+
+static int rtl2832_init(struct dvb_frontend *fe)
+{
+	struct rtl2832_priv *priv = fe->demodulator_priv;
+	int i, ret, len;
+	u8 en_bbin;
+	u64 pset_iffreq;
+	const struct rtl2832_reg_value *init;
+
+	/* initialization values for the demodulator registers */
+	struct rtl2832_reg_value rtl2832_initial_regs[] = {
+		{DVBT_AD_EN_REG,		0x1},
+		{DVBT_AD_EN_REG1,		0x1},
+		{DVBT_RSD_BER_FAIL_VAL,		0x2800},
+		{DVBT_MGD_THD0,			0x10},
+		{DVBT_MGD_THD1,			0x20},
+		{DVBT_MGD_THD2,			0x20},
+		{DVBT_MGD_THD3,			0x40},
+		{DVBT_MGD_THD4,			0x22},
+		{DVBT_MGD_THD5,			0x32},
+		{DVBT_MGD_THD6,			0x37},
+		{DVBT_MGD_THD7,			0x39},
+		{DVBT_EN_BK_TRK,		0x0},
+		{DVBT_EN_CACQ_NOTCH,		0x0},
+		{DVBT_AD_AV_REF,		0x2a},
+		{DVBT_REG_PI,			0x6},
+		{DVBT_PIP_ON,			0x0},
+		{DVBT_CDIV_PH0,			0x8},
+		{DVBT_CDIV_PH1,			0x8},
+		{DVBT_SCALE1_B92,		0x4},
+		{DVBT_SCALE1_B93,		0xb0},
+		{DVBT_SCALE1_BA7,		0x78},
+		{DVBT_SCALE1_BA9,		0x28},
+		{DVBT_SCALE1_BAA,		0x59},
+		{DVBT_SCALE1_BAB,		0x83},
+		{DVBT_SCALE1_BAC,		0xd4},
+		{DVBT_SCALE1_BB0,		0x65},
+		{DVBT_SCALE1_BB1,		0x43},
+		{DVBT_KB_P1,			0x1},
+		{DVBT_KB_P2,			0x4},
+		{DVBT_KB_P3,			0x7},
+		{DVBT_K1_CR_STEP12,		0xa},
+		{DVBT_REG_GPE,			0x1},
+		{DVBT_SERIAL,			0x0},
+		{DVBT_CDIV_PH0,			0x9},
+		{DVBT_CDIV_PH1,			0x9},
+		{DVBT_MPEG_IO_OPT_2_2,		0x0},
+		{DVBT_MPEG_IO_OPT_1_0,		0x0},
+		{DVBT_TRK_KS_P2,		0x4},
+		{DVBT_TRK_KS_I2,		0x7},
+		{DVBT_TR_THD_SET2,		0x6},
+		{DVBT_TRK_KC_I2,		0x5},
+		{DVBT_CR_THD_SET2,		0x1},
+		{DVBT_SPEC_INV,			0x0},
+	};
+
+	dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
+
+	en_bbin = (priv->cfg.if_dvbt == 0 ? 0x1 : 0x0);
+
+	/*
+	* PSET_IFFREQ = - floor((IfFreqHz % CrystalFreqHz) * pow(2, 22)
+	*		/ CrystalFreqHz)
+	*/
+	pset_iffreq = priv->cfg.if_dvbt % priv->cfg.xtal;
+	pset_iffreq *= 0x400000;
+	pset_iffreq = div_u64(pset_iffreq, priv->cfg.xtal);
+	pset_iffreq = pset_iffreq & 0x3fffff;
+
+	for (i = 0; i < ARRAY_SIZE(rtl2832_initial_regs); i++) {
+		ret = rtl2832_wr_demod_reg(priv, rtl2832_initial_regs[i].reg,
+			rtl2832_initial_regs[i].value);
+		if (ret)
+			goto err;
+	}
+
+	/* load tuner specific settings */
+	dev_dbg(&priv->i2c->dev, "%s: load settings for tuner=%02x\n",
+			__func__, priv->cfg.tuner);
+	switch (priv->cfg.tuner) {
+	case RTL2832_TUNER_FC0012:
+	case RTL2832_TUNER_FC0013:
+		len = ARRAY_SIZE(rtl2832_tuner_init_fc0012);
+		init = rtl2832_tuner_init_fc0012;
+		break;
+	case RTL2832_TUNER_TUA9001:
+		len = ARRAY_SIZE(rtl2832_tuner_init_tua9001);
+		init = rtl2832_tuner_init_tua9001;
+		break;
+	default:
+		ret = -EINVAL;
+		goto err;
+	}
+
+	for (i = 0; i < len; i++) {
+		ret = rtl2832_wr_demod_reg(priv, init[i].reg, init[i].value);
+		if (ret)
+			goto err;
+	}
+
+	/* if frequency settings */
+	ret = rtl2832_wr_demod_reg(priv, DVBT_EN_BBIN, en_bbin);
+		if (ret)
+			goto err;
+
+	ret = rtl2832_wr_demod_reg(priv, DVBT_PSET_IFFREQ, pset_iffreq);
+		if (ret)
+			goto err;
+
+	priv->sleeping = false;
+
+	return ret;
+
+err:
+	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	return ret;
+}
+
+static int rtl2832_sleep(struct dvb_frontend *fe)
+{
+	struct rtl2832_priv *priv = fe->demodulator_priv;
+
+	dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
+	priv->sleeping = true;
+	return 0;
+}
+
+int rtl2832_get_tune_settings(struct dvb_frontend *fe,
+	struct dvb_frontend_tune_settings *s)
+{
+	struct rtl2832_priv *priv = fe->demodulator_priv;
+
+	dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
+	s->min_delay_ms = 1000;
+	s->step_size = fe->ops.info.frequency_stepsize * 2;
+	s->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1;
+	return 0;
+}
+
+static int rtl2832_set_frontend(struct dvb_frontend *fe)
+{
+	struct rtl2832_priv *priv = fe->demodulator_priv;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	int ret, i, j;
+	u64 bw_mode, num, num2;
+	u32 resamp_ratio, cfreq_off_ratio;
+	static u8 bw_params[3][32] = {
+	/* 6 MHz bandwidth */
+		{
+		0xf5, 0xff, 0x15, 0x38, 0x5d, 0x6d, 0x52, 0x07, 0xfa, 0x2f,
+		0x53, 0xf5, 0x3f, 0xca, 0x0b, 0x91, 0xea, 0x30, 0x63, 0xb2,
+		0x13, 0xda, 0x0b, 0xc4, 0x18, 0x7e, 0x16, 0x66, 0x08, 0x67,
+		0x19, 0xe0,
+		},
+
+	/*  7 MHz bandwidth */
+		{
+		0xe7, 0xcc, 0xb5, 0xba, 0xe8, 0x2f, 0x67, 0x61, 0x00, 0xaf,
+		0x86, 0xf2, 0xbf, 0x59, 0x04, 0x11, 0xb6, 0x33, 0xa4, 0x30,
+		0x15, 0x10, 0x0a, 0x42, 0x18, 0xf8, 0x17, 0xd9, 0x07, 0x22,
+		0x19, 0x10,
+		},
+
+	/*  8 MHz bandwidth */
+		{
+		0x09, 0xf6, 0xd2, 0xa7, 0x9a, 0xc9, 0x27, 0x77, 0x06, 0xbf,
+		0xec, 0xf4, 0x4f, 0x0b, 0xfc, 0x01, 0x63, 0x35, 0x54, 0xa7,
+		0x16, 0x66, 0x08, 0xb4, 0x19, 0x6e, 0x19, 0x65, 0x05, 0xc8,
+		0x19, 0xe0,
+		},
+	};
+
+
+	dev_dbg(&priv->i2c->dev, "%s: frequency=%d bandwidth_hz=%d " \
+			"inversion=%d\n", __func__, c->frequency,
+			c->bandwidth_hz, c->inversion);
+
+	/* program tuner */
+	if (fe->ops.tuner_ops.set_params)
+		fe->ops.tuner_ops.set_params(fe);
+
+	switch (c->bandwidth_hz) {
+	case 6000000:
+		i = 0;
+		bw_mode = 48000000;
+		break;
+	case 7000000:
+		i = 1;
+		bw_mode = 56000000;
+		break;
+	case 8000000:
+		i = 2;
+		bw_mode = 64000000;
+		break;
+	default:
+		dev_dbg(&priv->i2c->dev, "%s: invalid bandwidth\n", __func__);
+		return -EINVAL;
+	}
+
+	for (j = 0; j < sizeof(bw_params[0]); j++) {
+		ret = rtl2832_wr_regs(priv, 0x1c+j, 1, &bw_params[i][j], 1);
+		if (ret)
+			goto err;
+	}
+
+	/* calculate and set resample ratio
+	* RSAMP_RATIO = floor(CrystalFreqHz * 7 * pow(2, 22)
+	*	/ ConstWithBandwidthMode)
+	*/
+	num = priv->cfg.xtal * 7;
+	num *= 0x400000;
+	num = div_u64(num, bw_mode);
+	resamp_ratio =  num & 0x3ffffff;
+	ret = rtl2832_wr_demod_reg(priv, DVBT_RSAMP_RATIO, resamp_ratio);
+	if (ret)
+		goto err;
+
+	/* calculate and set cfreq off ratio
+	* CFREQ_OFF_RATIO = - floor(ConstWithBandwidthMode * pow(2, 20)
+	*	/ (CrystalFreqHz * 7))
+	*/
+	num = bw_mode << 20;
+	num2 = priv->cfg.xtal * 7;
+	num = div_u64(num, num2);
+	num = -num;
+	cfreq_off_ratio = num & 0xfffff;
+	ret = rtl2832_wr_demod_reg(priv, DVBT_CFREQ_OFF_RATIO, cfreq_off_ratio);
+	if (ret)
+		goto err;
+
+
+	/* soft reset */
+	ret = rtl2832_wr_demod_reg(priv, DVBT_SOFT_RST, 0x1);
+	if (ret)
+		goto err;
+
+	ret = rtl2832_wr_demod_reg(priv, DVBT_SOFT_RST, 0x0);
+	if (ret)
+		goto err;
+
+	return ret;
+err:
+	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	return ret;
+}
+
+static int rtl2832_get_frontend(struct dvb_frontend *fe)
+{
+	struct rtl2832_priv *priv = fe->demodulator_priv;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	int ret;
+	u8 buf[3];
+
+	if (priv->sleeping)
+		return 0;
+
+	ret = rtl2832_rd_regs(priv, 0x3c, 3, buf, 2);
+	if (ret)
+		goto err;
+
+	ret = rtl2832_rd_reg(priv, 0x51, 3, &buf[2]);
+	if (ret)
+		goto err;
+
+	dev_dbg(&priv->i2c->dev, "%s: TPS=%*ph\n", __func__, 3, buf);
+
+	switch ((buf[0] >> 2) & 3) {
+	case 0:
+		c->modulation = QPSK;
+		break;
+	case 1:
+		c->modulation = QAM_16;
+		break;
+	case 2:
+		c->modulation = QAM_64;
+		break;
+	}
+
+	switch ((buf[2] >> 2) & 1) {
+	case 0:
+		c->transmission_mode = TRANSMISSION_MODE_2K;
+		break;
+	case 1:
+		c->transmission_mode = TRANSMISSION_MODE_8K;
+	}
+
+	switch ((buf[2] >> 0) & 3) {
+	case 0:
+		c->guard_interval = GUARD_INTERVAL_1_32;
+		break;
+	case 1:
+		c->guard_interval = GUARD_INTERVAL_1_16;
+		break;
+	case 2:
+		c->guard_interval = GUARD_INTERVAL_1_8;
+		break;
+	case 3:
+		c->guard_interval = GUARD_INTERVAL_1_4;
+		break;
+	}
+
+	switch ((buf[0] >> 4) & 7) {
+	case 0:
+		c->hierarchy = HIERARCHY_NONE;
+		break;
+	case 1:
+		c->hierarchy = HIERARCHY_1;
+		break;
+	case 2:
+		c->hierarchy = HIERARCHY_2;
+		break;
+	case 3:
+		c->hierarchy = HIERARCHY_4;
+		break;
+	}
+
+	switch ((buf[1] >> 3) & 7) {
+	case 0:
+		c->code_rate_HP = FEC_1_2;
+		break;
+	case 1:
+		c->code_rate_HP = FEC_2_3;
+		break;
+	case 2:
+		c->code_rate_HP = FEC_3_4;
+		break;
+	case 3:
+		c->code_rate_HP = FEC_5_6;
+		break;
+	case 4:
+		c->code_rate_HP = FEC_7_8;
+		break;
+	}
+
+	switch ((buf[1] >> 0) & 7) {
+	case 0:
+		c->code_rate_LP = FEC_1_2;
+		break;
+	case 1:
+		c->code_rate_LP = FEC_2_3;
+		break;
+	case 2:
+		c->code_rate_LP = FEC_3_4;
+		break;
+	case 3:
+		c->code_rate_LP = FEC_5_6;
+		break;
+	case 4:
+		c->code_rate_LP = FEC_7_8;
+		break;
+	}
+
+	return 0;
+err:
+	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	return ret;
+}
+
+static int rtl2832_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+	struct rtl2832_priv *priv = fe->demodulator_priv;
+	int ret;
+	u32 tmp;
+	*status = 0;
+
+	dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
+	if (priv->sleeping)
+		return 0;
+
+	ret = rtl2832_rd_demod_reg(priv, DVBT_FSM_STAGE, &tmp);
+	if (ret)
+		goto err;
+
+	if (tmp == 11) {
+		*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
+				FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
+	}
+	/* TODO find out if this is also true for rtl2832? */
+	/*else if (tmp == 10) {
+		*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
+				FE_HAS_VITERBI;
+	}*/
+
+	return ret;
+err:
+	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	return ret;
+}
+
+static int rtl2832_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+	struct rtl2832_priv *priv = fe->demodulator_priv;
+	int ret, hierarchy, constellation;
+	u8 buf[2], tmp;
+	u16 tmp16;
+#define CONSTELLATION_NUM 3
+#define HIERARCHY_NUM 4
+	static const u32 snr_constant[CONSTELLATION_NUM][HIERARCHY_NUM] = {
+		{ 85387325, 85387325, 85387325, 85387325 },
+		{ 86676178, 86676178, 87167949, 87795660 },
+		{ 87659938, 87659938, 87885178, 88241743 },
+	};
+
+	/* reports SNR in resolution of 0.1 dB */
+
+	ret = rtl2832_rd_reg(priv, 0x3c, 3, &tmp);
+	if (ret)
+		goto err;
+
+	constellation = (tmp >> 2) & 0x03; /* [3:2] */
+	if (constellation > CONSTELLATION_NUM - 1)
+		goto err;
+
+	hierarchy = (tmp >> 4) & 0x07; /* [6:4] */
+	if (hierarchy > HIERARCHY_NUM - 1)
+		goto err;
+
+	ret = rtl2832_rd_regs(priv, 0x0c, 4, buf, 2);
+	if (ret)
+		goto err;
+
+	tmp16 = buf[0] << 8 | buf[1];
+
+	if (tmp16)
+		*snr = (snr_constant[constellation][hierarchy] -
+				intlog10(tmp16)) / ((1 << 24) / 100);
+	else
+		*snr = 0;
+
+	return 0;
+err:
+	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	return ret;
+}
+
+static int rtl2832_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+	struct rtl2832_priv *priv = fe->demodulator_priv;
+	int ret;
+	u8 buf[2];
+
+	ret = rtl2832_rd_regs(priv, 0x4e, 3, buf, 2);
+	if (ret)
+		goto err;
+
+	*ber = buf[0] << 8 | buf[1];
+
+	return 0;
+err:
+	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	return ret;
+}
+
+static struct dvb_frontend_ops rtl2832_ops;
+
+static void rtl2832_release(struct dvb_frontend *fe)
+{
+	struct rtl2832_priv *priv = fe->demodulator_priv;
+
+	dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
+	kfree(priv);
+}
+
+struct dvb_frontend *rtl2832_attach(const struct rtl2832_config *cfg,
+	struct i2c_adapter *i2c)
+{
+	struct rtl2832_priv *priv = NULL;
+	int ret = 0;
+	u8 tmp;
+
+	dev_dbg(&i2c->dev, "%s:\n", __func__);
+
+	/* allocate memory for the internal state */
+	priv = kzalloc(sizeof(struct rtl2832_priv), GFP_KERNEL);
+	if (priv == NULL)
+		goto err;
+
+	/* setup the priv */
+	priv->i2c = i2c;
+	priv->tuner = cfg->tuner;
+	memcpy(&priv->cfg, cfg, sizeof(struct rtl2832_config));
+
+	/* check if the demod is there */
+	ret = rtl2832_rd_reg(priv, 0x00, 0x0, &tmp);
+	if (ret)
+		goto err;
+
+	/* create dvb_frontend */
+	memcpy(&priv->fe.ops, &rtl2832_ops, sizeof(struct dvb_frontend_ops));
+	priv->fe.demodulator_priv = priv;
+
+	/* TODO implement sleep mode */
+	priv->sleeping = true;
+
+	return &priv->fe;
+err:
+	dev_dbg(&i2c->dev, "%s: failed=%d\n", __func__, ret);
+	kfree(priv);
+	return NULL;
+}
+EXPORT_SYMBOL(rtl2832_attach);
+
+static struct dvb_frontend_ops rtl2832_ops = {
+	.delsys = { SYS_DVBT },
+	.info = {
+		.name = "Realtek RTL2832 (DVB-T)",
+		.frequency_min	  = 174000000,
+		.frequency_max	  = 862000000,
+		.frequency_stepsize = 166667,
+		.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_FEC_AUTO |
+			FE_CAN_QPSK |
+			FE_CAN_QAM_16 |
+			FE_CAN_QAM_64 |
+			FE_CAN_QAM_AUTO |
+			FE_CAN_TRANSMISSION_MODE_AUTO |
+			FE_CAN_GUARD_INTERVAL_AUTO |
+			FE_CAN_HIERARCHY_AUTO |
+			FE_CAN_RECOVER |
+			FE_CAN_MUTE_TS
+	 },
+
+	.release = rtl2832_release,
+
+	.init = rtl2832_init,
+	.sleep = rtl2832_sleep,
+
+	.get_tune_settings = rtl2832_get_tune_settings,
+
+	.set_frontend = rtl2832_set_frontend,
+	.get_frontend = rtl2832_get_frontend,
+
+	.read_status = rtl2832_read_status,
+	.read_snr = rtl2832_read_snr,
+	.read_ber = rtl2832_read_ber,
+
+	.i2c_gate_ctrl = rtl2832_i2c_gate_ctrl,
+};
+
+MODULE_AUTHOR("Thomas Mair <mair.thomas86@gmail.com>");
+MODULE_DESCRIPTION("Realtek RTL2832 DVB-T demodulator driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("0.5");
diff --git a/drivers/media/dvb-frontends/rtl2832.h b/drivers/media/dvb-frontends/rtl2832.h
new file mode 100644
index 0000000..c4a6118
--- /dev/null
+++ b/drivers/media/dvb-frontends/rtl2832.h
@@ -0,0 +1,74 @@
+/*
+ * Realtek RTL2832 DVB-T demodulator driver
+ *
+ * Copyright (C) 2012 Thomas Mair <thomas.mair86@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.
+ */
+
+#ifndef RTL2832_H
+#define RTL2832_H
+
+#include <linux/dvb/frontend.h>
+
+struct rtl2832_config {
+	/*
+	 * Demodulator I2C address.
+	 */
+	u8 i2c_addr;
+
+	/*
+	 * Xtal frequency.
+	 * Hz
+	 * 4000000, 16000000, 25000000, 28800000
+	 */
+	u32 xtal;
+
+	/*
+	 * IFs for all used modes.
+	 * Hz
+	 * 4570000, 4571429, 36000000, 36125000, 36166667, 44000000
+	 */
+	u32 if_dvbt;
+
+	/*
+	 * tuner
+	 * XXX: This must be keep sync with dvb_usb_rtl28xxu demod driver.
+	 */
+#define RTL2832_TUNER_TUA9001   0x24
+#define RTL2832_TUNER_FC0012    0x26
+#define RTL2832_TUNER_FC0013    0x29
+	u8 tuner;
+};
+
+#if defined(CONFIG_DVB_RTL2832) || \
+	(defined(CONFIG_DVB_RTL2832_MODULE) && defined(MODULE))
+extern struct dvb_frontend *rtl2832_attach(
+	const struct rtl2832_config *cfg,
+	struct i2c_adapter *i2c
+);
+#else
+static inline struct dvb_frontend *rtl2832_attach(
+	const struct rtl2832_config *config,
+	struct i2c_adapter *i2c
+)
+{
+	pr_warn("%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif
+
+
+#endif /* RTL2832_H */
diff --git a/drivers/media/dvb-frontends/rtl2832_priv.h b/drivers/media/dvb-frontends/rtl2832_priv.h
new file mode 100644
index 0000000..5e68955
--- /dev/null
+++ b/drivers/media/dvb-frontends/rtl2832_priv.h
@@ -0,0 +1,305 @@
+/*
+ * Realtek RTL2832 DVB-T demodulator driver
+ *
+ * Copyright (C) 2012 Thomas Mair <thomas.mair86@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.
+ */
+
+#ifndef RTL2832_PRIV_H
+#define RTL2832_PRIV_H
+
+#include "dvb_frontend.h"
+#include "rtl2832.h"
+
+struct rtl2832_priv {
+	struct i2c_adapter *i2c;
+	struct dvb_frontend fe;
+	struct rtl2832_config cfg;
+
+	bool i2c_gate_state;
+	bool sleeping;
+
+	u8 tuner;
+	u8 page; /* active register page */
+};
+
+struct rtl2832_reg_entry {
+	u8 page;
+	u8 start_address;
+	u8 msb;
+	u8 lsb;
+};
+
+struct rtl2832_reg_value {
+	int reg;
+	u32 value;
+};
+
+
+/* Demod register bit names */
+enum DVBT_REG_BIT_NAME {
+	DVBT_SOFT_RST,
+	DVBT_IIC_REPEAT,
+	DVBT_TR_WAIT_MIN_8K,
+	DVBT_RSD_BER_FAIL_VAL,
+	DVBT_EN_BK_TRK,
+	DVBT_REG_PI,
+	DVBT_REG_PFREQ_1_0,
+	DVBT_PD_DA8,
+	DVBT_LOCK_TH,
+	DVBT_BER_PASS_SCAL,
+	DVBT_CE_FFSM_BYPASS,
+	DVBT_ALPHAIIR_N,
+	DVBT_ALPHAIIR_DIF,
+	DVBT_EN_TRK_SPAN,
+	DVBT_LOCK_TH_LEN,
+	DVBT_CCI_THRE,
+	DVBT_CCI_MON_SCAL,
+	DVBT_CCI_M0,
+	DVBT_CCI_M1,
+	DVBT_CCI_M2,
+	DVBT_CCI_M3,
+	DVBT_SPEC_INIT_0,
+	DVBT_SPEC_INIT_1,
+	DVBT_SPEC_INIT_2,
+	DVBT_AD_EN_REG,
+	DVBT_AD_EN_REG1,
+	DVBT_EN_BBIN,
+	DVBT_MGD_THD0,
+	DVBT_MGD_THD1,
+	DVBT_MGD_THD2,
+	DVBT_MGD_THD3,
+	DVBT_MGD_THD4,
+	DVBT_MGD_THD5,
+	DVBT_MGD_THD6,
+	DVBT_MGD_THD7,
+	DVBT_EN_CACQ_NOTCH,
+	DVBT_AD_AV_REF,
+	DVBT_PIP_ON,
+	DVBT_SCALE1_B92,
+	DVBT_SCALE1_B93,
+	DVBT_SCALE1_BA7,
+	DVBT_SCALE1_BA9,
+	DVBT_SCALE1_BAA,
+	DVBT_SCALE1_BAB,
+	DVBT_SCALE1_BAC,
+	DVBT_SCALE1_BB0,
+	DVBT_SCALE1_BB1,
+	DVBT_KB_P1,
+	DVBT_KB_P2,
+	DVBT_KB_P3,
+	DVBT_OPT_ADC_IQ,
+	DVBT_AD_AVI,
+	DVBT_AD_AVQ,
+	DVBT_K1_CR_STEP12,
+	DVBT_TRK_KS_P2,
+	DVBT_TRK_KS_I2,
+	DVBT_TR_THD_SET2,
+	DVBT_TRK_KC_P2,
+	DVBT_TRK_KC_I2,
+	DVBT_CR_THD_SET2,
+	DVBT_PSET_IFFREQ,
+	DVBT_SPEC_INV,
+	DVBT_BW_INDEX,
+	DVBT_RSAMP_RATIO,
+	DVBT_CFREQ_OFF_RATIO,
+	DVBT_FSM_STAGE,
+	DVBT_RX_CONSTEL,
+	DVBT_RX_HIER,
+	DVBT_RX_C_RATE_LP,
+	DVBT_RX_C_RATE_HP,
+	DVBT_GI_IDX,
+	DVBT_FFT_MODE_IDX,
+	DVBT_RSD_BER_EST,
+	DVBT_CE_EST_EVM,
+	DVBT_RF_AGC_VAL,
+	DVBT_IF_AGC_VAL,
+	DVBT_DAGC_VAL,
+	DVBT_SFREQ_OFF,
+	DVBT_CFREQ_OFF,
+	DVBT_POLAR_RF_AGC,
+	DVBT_POLAR_IF_AGC,
+	DVBT_AAGC_HOLD,
+	DVBT_EN_RF_AGC,
+	DVBT_EN_IF_AGC,
+	DVBT_IF_AGC_MIN,
+	DVBT_IF_AGC_MAX,
+	DVBT_RF_AGC_MIN,
+	DVBT_RF_AGC_MAX,
+	DVBT_IF_AGC_MAN,
+	DVBT_IF_AGC_MAN_VAL,
+	DVBT_RF_AGC_MAN,
+	DVBT_RF_AGC_MAN_VAL,
+	DVBT_DAGC_TRG_VAL,
+	DVBT_AGC_TARG_VAL,
+	DVBT_LOOP_GAIN_3_0,
+	DVBT_LOOP_GAIN_4,
+	DVBT_VTOP,
+	DVBT_KRF,
+	DVBT_AGC_TARG_VAL_0,
+	DVBT_AGC_TARG_VAL_8_1,
+	DVBT_AAGC_LOOP_GAIN,
+	DVBT_LOOP_GAIN2_3_0,
+	DVBT_LOOP_GAIN2_4,
+	DVBT_LOOP_GAIN3,
+	DVBT_VTOP1,
+	DVBT_VTOP2,
+	DVBT_VTOP3,
+	DVBT_KRF1,
+	DVBT_KRF2,
+	DVBT_KRF3,
+	DVBT_KRF4,
+	DVBT_EN_GI_PGA,
+	DVBT_THD_LOCK_UP,
+	DVBT_THD_LOCK_DW,
+	DVBT_THD_UP1,
+	DVBT_THD_DW1,
+	DVBT_INTER_CNT_LEN,
+	DVBT_GI_PGA_STATE,
+	DVBT_EN_AGC_PGA,
+	DVBT_CKOUTPAR,
+	DVBT_CKOUT_PWR,
+	DVBT_SYNC_DUR,
+	DVBT_ERR_DUR,
+	DVBT_SYNC_LVL,
+	DVBT_ERR_LVL,
+	DVBT_VAL_LVL,
+	DVBT_SERIAL,
+	DVBT_SER_LSB,
+	DVBT_CDIV_PH0,
+	DVBT_CDIV_PH1,
+	DVBT_MPEG_IO_OPT_2_2,
+	DVBT_MPEG_IO_OPT_1_0,
+	DVBT_CKOUTPAR_PIP,
+	DVBT_CKOUT_PWR_PIP,
+	DVBT_SYNC_LVL_PIP,
+	DVBT_ERR_LVL_PIP,
+	DVBT_VAL_LVL_PIP,
+	DVBT_CKOUTPAR_PID,
+	DVBT_CKOUT_PWR_PID,
+	DVBT_SYNC_LVL_PID,
+	DVBT_ERR_LVL_PID,
+	DVBT_VAL_LVL_PID,
+	DVBT_SM_PASS,
+	DVBT_UPDATE_REG_2,
+	DVBT_BTHD_P3,
+	DVBT_BTHD_D3,
+	DVBT_FUNC4_REG0,
+	DVBT_FUNC4_REG1,
+	DVBT_FUNC4_REG2,
+	DVBT_FUNC4_REG3,
+	DVBT_FUNC4_REG4,
+	DVBT_FUNC4_REG5,
+	DVBT_FUNC4_REG6,
+	DVBT_FUNC4_REG7,
+	DVBT_FUNC4_REG8,
+	DVBT_FUNC4_REG9,
+	DVBT_FUNC4_REG10,
+	DVBT_FUNC5_REG0,
+	DVBT_FUNC5_REG1,
+	DVBT_FUNC5_REG2,
+	DVBT_FUNC5_REG3,
+	DVBT_FUNC5_REG4,
+	DVBT_FUNC5_REG5,
+	DVBT_FUNC5_REG6,
+	DVBT_FUNC5_REG7,
+	DVBT_FUNC5_REG8,
+	DVBT_FUNC5_REG9,
+	DVBT_FUNC5_REG10,
+	DVBT_FUNC5_REG11,
+	DVBT_FUNC5_REG12,
+	DVBT_FUNC5_REG13,
+	DVBT_FUNC5_REG14,
+	DVBT_FUNC5_REG15,
+	DVBT_FUNC5_REG16,
+	DVBT_FUNC5_REG17,
+	DVBT_FUNC5_REG18,
+	DVBT_AD7_SETTING,
+	DVBT_RSSI_R,
+	DVBT_ACI_DET_IND,
+	DVBT_REG_MON,
+	DVBT_REG_MONSEL,
+	DVBT_REG_GPE,
+	DVBT_REG_GPO,
+	DVBT_REG_4MSEL,
+	DVBT_TEST_REG_1,
+	DVBT_TEST_REG_2,
+	DVBT_TEST_REG_3,
+	DVBT_TEST_REG_4,
+	DVBT_REG_BIT_NAME_ITEM_TERMINATOR,
+};
+
+static const struct rtl2832_reg_value rtl2832_tuner_init_tua9001[] = {
+	{DVBT_DAGC_TRG_VAL,             0x39},
+	{DVBT_AGC_TARG_VAL_0,            0x0},
+	{DVBT_AGC_TARG_VAL_8_1,         0x5a},
+	{DVBT_AAGC_LOOP_GAIN,           0x16},
+	{DVBT_LOOP_GAIN2_3_0,            0x6},
+	{DVBT_LOOP_GAIN2_4,              0x1},
+	{DVBT_LOOP_GAIN3,               0x16},
+	{DVBT_VTOP1,                    0x35},
+	{DVBT_VTOP2,                    0x21},
+	{DVBT_VTOP3,                    0x21},
+	{DVBT_KRF1,                      0x0},
+	{DVBT_KRF2,                     0x40},
+	{DVBT_KRF3,                     0x10},
+	{DVBT_KRF4,                     0x10},
+	{DVBT_IF_AGC_MIN,               0x80},
+	{DVBT_IF_AGC_MAX,               0x7f},
+	{DVBT_RF_AGC_MIN,               0x9c},
+	{DVBT_RF_AGC_MAX,               0x7f},
+	{DVBT_POLAR_RF_AGC,              0x0},
+	{DVBT_POLAR_IF_AGC,              0x0},
+	{DVBT_AD7_SETTING,            0xe9f4},
+	{DVBT_OPT_ADC_IQ,                0x1},
+	{DVBT_AD_AVI,                    0x0},
+	{DVBT_AD_AVQ,                    0x0},
+};
+
+static const struct rtl2832_reg_value rtl2832_tuner_init_fc0012[] = {
+	{DVBT_DAGC_TRG_VAL,             0x5a},
+	{DVBT_AGC_TARG_VAL_0,            0x0},
+	{DVBT_AGC_TARG_VAL_8_1,         0x5a},
+	{DVBT_AAGC_LOOP_GAIN,           0x16},
+	{DVBT_LOOP_GAIN2_3_0,            0x6},
+	{DVBT_LOOP_GAIN2_4,              0x1},
+	{DVBT_LOOP_GAIN3,               0x16},
+	{DVBT_VTOP1,                    0x35},
+	{DVBT_VTOP2,                    0x21},
+	{DVBT_VTOP3,                    0x21},
+	{DVBT_KRF1,                      0x0},
+	{DVBT_KRF2,                     0x40},
+	{DVBT_KRF3,                     0x10},
+	{DVBT_KRF4,                     0x10},
+	{DVBT_IF_AGC_MIN,               0x80},
+	{DVBT_IF_AGC_MAX,               0x7f},
+	{DVBT_RF_AGC_MIN,               0x80},
+	{DVBT_RF_AGC_MAX,               0x7f},
+	{DVBT_POLAR_RF_AGC,              0x0},
+	{DVBT_POLAR_IF_AGC,              0x0},
+	{DVBT_AD7_SETTING,            0xe9bf},
+	{DVBT_EN_GI_PGA,                 0x0},
+	{DVBT_THD_LOCK_UP,               0x0},
+	{DVBT_THD_LOCK_DW,               0x0},
+	{DVBT_THD_UP1,                  0x11},
+	{DVBT_THD_DW1,                  0xef},
+	{DVBT_INTER_CNT_LEN,             0xc},
+	{DVBT_GI_PGA_STATE,              0x0},
+	{DVBT_EN_AGC_PGA,                0x1},
+	{DVBT_IF_AGC_MAN,                0x0},
+};
+
+#endif /* RTL2832_PRIV_H */
diff --git a/drivers/media/dvb-frontends/s5h1409.c b/drivers/media/dvb-frontends/s5h1409.c
new file mode 100644
index 0000000..f71b062
--- /dev/null
+++ b/drivers/media/dvb-frontends/s5h1409.c
@@ -0,0 +1,1029 @@
+/*
+    Samsung S5H1409 VSB/QAM demodulator driver
+
+    Copyright (C) 2006 Steven Toth <stoth@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/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include "dvb_frontend.h"
+#include "s5h1409.h"
+
+struct s5h1409_state {
+
+	struct i2c_adapter *i2c;
+
+	/* configuration settings */
+	const struct s5h1409_config *config;
+
+	struct dvb_frontend frontend;
+
+	/* previous uncorrected block counter */
+	fe_modulation_t current_modulation;
+
+	u32 current_frequency;
+	int if_freq;
+
+	u32 is_qam_locked;
+
+	/* QAM tuning state goes through the following state transitions */
+#define QAM_STATE_UNTUNED 0
+#define QAM_STATE_TUNING_STARTED 1
+#define QAM_STATE_INTERLEAVE_SET 2
+#define QAM_STATE_QAM_OPTIMIZED_L1 3
+#define QAM_STATE_QAM_OPTIMIZED_L2 4
+#define QAM_STATE_QAM_OPTIMIZED_L3 5
+	u8  qam_state;
+};
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Enable verbose debug messages");
+
+#define dprintk	if (debug) printk
+
+/* Register values to initialise the demod, this will set VSB by default */
+static struct init_tab {
+	u8	reg;
+	u16	data;
+} init_tab[] = {
+	{ 0x00, 0x0071, },
+	{ 0x01, 0x3213, },
+	{ 0x09, 0x0025, },
+	{ 0x1c, 0x001d, },
+	{ 0x1f, 0x002d, },
+	{ 0x20, 0x001d, },
+	{ 0x22, 0x0022, },
+	{ 0x23, 0x0020, },
+	{ 0x29, 0x110f, },
+	{ 0x2a, 0x10b4, },
+	{ 0x2b, 0x10ae, },
+	{ 0x2c, 0x0031, },
+	{ 0x31, 0x010d, },
+	{ 0x32, 0x0100, },
+	{ 0x44, 0x0510, },
+	{ 0x54, 0x0104, },
+	{ 0x58, 0x2222, },
+	{ 0x59, 0x1162, },
+	{ 0x5a, 0x3211, },
+	{ 0x5d, 0x0370, },
+	{ 0x5e, 0x0296, },
+	{ 0x61, 0x0010, },
+	{ 0x63, 0x4a00, },
+	{ 0x65, 0x0800, },
+	{ 0x71, 0x0003, },
+	{ 0x72, 0x0470, },
+	{ 0x81, 0x0002, },
+	{ 0x82, 0x0600, },
+	{ 0x86, 0x0002, },
+	{ 0x8a, 0x2c38, },
+	{ 0x8b, 0x2a37, },
+	{ 0x92, 0x302f, },
+	{ 0x93, 0x3332, },
+	{ 0x96, 0x000c, },
+	{ 0x99, 0x0101, },
+	{ 0x9c, 0x2e37, },
+	{ 0x9d, 0x2c37, },
+	{ 0x9e, 0x2c37, },
+	{ 0xab, 0x0100, },
+	{ 0xac, 0x1003, },
+	{ 0xad, 0x103f, },
+	{ 0xe2, 0x0100, },
+	{ 0xe3, 0x1000, },
+	{ 0x28, 0x1010, },
+	{ 0xb1, 0x000e, },
+};
+
+/* VSB SNR lookup table */
+static struct vsb_snr_tab {
+	u16	val;
+	u16	data;
+} vsb_snr_tab[] = {
+	{  924, 300, },
+	{  923, 300, },
+	{  918, 295, },
+	{  915, 290, },
+	{  911, 285, },
+	{  906, 280, },
+	{  901, 275, },
+	{  896, 270, },
+	{  891, 265, },
+	{  885, 260, },
+	{  879, 255, },
+	{  873, 250, },
+	{  864, 245, },
+	{  858, 240, },
+	{  850, 235, },
+	{  841, 230, },
+	{  832, 225, },
+	{  823, 220, },
+	{  812, 215, },
+	{  802, 210, },
+	{  788, 205, },
+	{  778, 200, },
+	{  767, 195, },
+	{  753, 190, },
+	{  740, 185, },
+	{  725, 180, },
+	{  707, 175, },
+	{  689, 170, },
+	{  671, 165, },
+	{  656, 160, },
+	{  637, 155, },
+	{  616, 150, },
+	{  542, 145, },
+	{  519, 140, },
+	{  507, 135, },
+	{  497, 130, },
+	{  492, 125, },
+	{  474, 120, },
+	{  300, 111, },
+	{    0,   0, },
+};
+
+/* QAM64 SNR lookup table */
+static struct qam64_snr_tab {
+	u16	val;
+	u16	data;
+} qam64_snr_tab[] = {
+	{    1,   0, },
+	{   12, 300, },
+	{   15, 290, },
+	{   18, 280, },
+	{   22, 270, },
+	{   23, 268, },
+	{   24, 266, },
+	{   25, 264, },
+	{   27, 262, },
+	{   28, 260, },
+	{   29, 258, },
+	{   30, 256, },
+	{   32, 254, },
+	{   33, 252, },
+	{   34, 250, },
+	{   35, 249, },
+	{   36, 248, },
+	{   37, 247, },
+	{   38, 246, },
+	{   39, 245, },
+	{   40, 244, },
+	{   41, 243, },
+	{   42, 241, },
+	{   43, 240, },
+	{   44, 239, },
+	{   45, 238, },
+	{   46, 237, },
+	{   47, 236, },
+	{   48, 235, },
+	{   49, 234, },
+	{   50, 233, },
+	{   51, 232, },
+	{   52, 231, },
+	{   53, 230, },
+	{   55, 229, },
+	{   56, 228, },
+	{   57, 227, },
+	{   58, 226, },
+	{   59, 225, },
+	{   60, 224, },
+	{   62, 223, },
+	{   63, 222, },
+	{   65, 221, },
+	{   66, 220, },
+	{   68, 219, },
+	{   69, 218, },
+	{   70, 217, },
+	{   72, 216, },
+	{   73, 215, },
+	{   75, 214, },
+	{   76, 213, },
+	{   78, 212, },
+	{   80, 211, },
+	{   81, 210, },
+	{   83, 209, },
+	{   84, 208, },
+	{   85, 207, },
+	{   87, 206, },
+	{   89, 205, },
+	{   91, 204, },
+	{   93, 203, },
+	{   95, 202, },
+	{   96, 201, },
+	{  104, 200, },
+	{  255,   0, },
+};
+
+/* QAM256 SNR lookup table */
+static struct qam256_snr_tab {
+	u16	val;
+	u16	data;
+} qam256_snr_tab[] = {
+	{    1,   0, },
+	{   12, 400, },
+	{   13, 390, },
+	{   15, 380, },
+	{   17, 360, },
+	{   19, 350, },
+	{   22, 348, },
+	{   23, 346, },
+	{   24, 344, },
+	{   25, 342, },
+	{   26, 340, },
+	{   27, 336, },
+	{   28, 334, },
+	{   29, 332, },
+	{   30, 330, },
+	{   31, 328, },
+	{   32, 326, },
+	{   33, 325, },
+	{   34, 322, },
+	{   35, 320, },
+	{   37, 318, },
+	{   39, 316, },
+	{   40, 314, },
+	{   41, 312, },
+	{   42, 310, },
+	{   43, 308, },
+	{   46, 306, },
+	{   47, 304, },
+	{   49, 302, },
+	{   51, 300, },
+	{   53, 298, },
+	{   54, 297, },
+	{   55, 296, },
+	{   56, 295, },
+	{   57, 294, },
+	{   59, 293, },
+	{   60, 292, },
+	{   61, 291, },
+	{   63, 290, },
+	{   64, 289, },
+	{   65, 288, },
+	{   66, 287, },
+	{   68, 286, },
+	{   69, 285, },
+	{   71, 284, },
+	{   72, 283, },
+	{   74, 282, },
+	{   75, 281, },
+	{   76, 280, },
+	{   77, 279, },
+	{   78, 278, },
+	{   81, 277, },
+	{   83, 276, },
+	{   84, 275, },
+	{   86, 274, },
+	{   87, 273, },
+	{   89, 272, },
+	{   90, 271, },
+	{   92, 270, },
+	{   93, 269, },
+	{   95, 268, },
+	{   96, 267, },
+	{   98, 266, },
+	{  100, 265, },
+	{  102, 264, },
+	{  104, 263, },
+	{  105, 262, },
+	{  106, 261, },
+	{  110, 260, },
+	{  255,   0, },
+};
+
+/* 8 bit registers, 16 bit values */
+static int s5h1409_writereg(struct s5h1409_state *state, u8 reg, u16 data)
+{
+	int ret;
+	u8 buf[] = { reg, data >> 8,  data & 0xff };
+
+	struct i2c_msg msg = { .addr = state->config->demod_address,
+			       .flags = 0, .buf = buf, .len = 3 };
+
+	ret = i2c_transfer(state->i2c, &msg, 1);
+
+	if (ret != 1)
+		printk(KERN_ERR "%s: error (reg == 0x%02x, val == 0x%04x, "
+		       "ret == %i)\n", __func__, reg, data, ret);
+
+	return (ret != 1) ? -1 : 0;
+}
+
+static u16 s5h1409_readreg(struct s5h1409_state *state, u8 reg)
+{
+	int ret;
+	u8 b0[] = { reg };
+	u8 b1[] = { 0, 0 };
+
+	struct i2c_msg msg[] = {
+		{ .addr = state->config->demod_address, .flags = 0,
+		  .buf = b0, .len = 1 },
+		{ .addr = state->config->demod_address, .flags = I2C_M_RD,
+		  .buf = b1, .len = 2 } };
+
+	ret = i2c_transfer(state->i2c, msg, 2);
+
+	if (ret != 2)
+		printk("%s: readreg error (ret == %i)\n", __func__, ret);
+	return (b1[0] << 8) | b1[1];
+}
+
+static int s5h1409_softreset(struct dvb_frontend *fe)
+{
+	struct s5h1409_state *state = fe->demodulator_priv;
+
+	dprintk("%s()\n", __func__);
+
+	s5h1409_writereg(state, 0xf5, 0);
+	s5h1409_writereg(state, 0xf5, 1);
+	state->is_qam_locked = 0;
+	state->qam_state = QAM_STATE_UNTUNED;
+	return 0;
+}
+
+#define S5H1409_VSB_IF_FREQ 5380
+#define S5H1409_QAM_IF_FREQ (state->config->qam_if)
+
+static int s5h1409_set_if_freq(struct dvb_frontend *fe, int KHz)
+{
+	struct s5h1409_state *state = fe->demodulator_priv;
+
+	dprintk("%s(%d KHz)\n", __func__, KHz);
+
+	switch (KHz) {
+	case 4000:
+		s5h1409_writereg(state, 0x87, 0x014b);
+		s5h1409_writereg(state, 0x88, 0x0cb5);
+		s5h1409_writereg(state, 0x89, 0x03e2);
+		break;
+	case 5380:
+	case 44000:
+	default:
+		s5h1409_writereg(state, 0x87, 0x01be);
+		s5h1409_writereg(state, 0x88, 0x0436);
+		s5h1409_writereg(state, 0x89, 0x054d);
+		break;
+	}
+	state->if_freq = KHz;
+
+	return 0;
+}
+
+static int s5h1409_set_spectralinversion(struct dvb_frontend *fe, int inverted)
+{
+	struct s5h1409_state *state = fe->demodulator_priv;
+
+	dprintk("%s(%d)\n", __func__, inverted);
+
+	if (inverted == 1)
+		return s5h1409_writereg(state, 0x1b, 0x1101); /* Inverted */
+	else
+		return s5h1409_writereg(state, 0x1b, 0x0110); /* Normal */
+}
+
+static int s5h1409_enable_modulation(struct dvb_frontend *fe,
+				     fe_modulation_t m)
+{
+	struct s5h1409_state *state = fe->demodulator_priv;
+
+	dprintk("%s(0x%08x)\n", __func__, m);
+
+	switch (m) {
+	case VSB_8:
+		dprintk("%s() VSB_8\n", __func__);
+		if (state->if_freq != S5H1409_VSB_IF_FREQ)
+			s5h1409_set_if_freq(fe, S5H1409_VSB_IF_FREQ);
+		s5h1409_writereg(state, 0xf4, 0);
+		break;
+	case QAM_64:
+	case QAM_256:
+	case QAM_AUTO:
+		dprintk("%s() QAM_AUTO (64/256)\n", __func__);
+		if (state->if_freq != S5H1409_QAM_IF_FREQ)
+			s5h1409_set_if_freq(fe, S5H1409_QAM_IF_FREQ);
+		s5h1409_writereg(state, 0xf4, 1);
+		s5h1409_writereg(state, 0x85, 0x110);
+		break;
+	default:
+		dprintk("%s() Invalid modulation\n", __func__);
+		return -EINVAL;
+	}
+
+	state->current_modulation = m;
+	s5h1409_softreset(fe);
+
+	return 0;
+}
+
+static int s5h1409_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+	struct s5h1409_state *state = fe->demodulator_priv;
+
+	dprintk("%s(%d)\n", __func__, enable);
+
+	if (enable)
+		return s5h1409_writereg(state, 0xf3, 1);
+	else
+		return s5h1409_writereg(state, 0xf3, 0);
+}
+
+static int s5h1409_set_gpio(struct dvb_frontend *fe, int enable)
+{
+	struct s5h1409_state *state = fe->demodulator_priv;
+
+	dprintk("%s(%d)\n", __func__, enable);
+
+	if (enable)
+		return s5h1409_writereg(state, 0xe3,
+			s5h1409_readreg(state, 0xe3) | 0x1100);
+	else
+		return s5h1409_writereg(state, 0xe3,
+			s5h1409_readreg(state, 0xe3) & 0xfeff);
+}
+
+static int s5h1409_sleep(struct dvb_frontend *fe, int enable)
+{
+	struct s5h1409_state *state = fe->demodulator_priv;
+
+	dprintk("%s(%d)\n", __func__, enable);
+
+	return s5h1409_writereg(state, 0xf2, enable);
+}
+
+static int s5h1409_register_reset(struct dvb_frontend *fe)
+{
+	struct s5h1409_state *state = fe->demodulator_priv;
+
+	dprintk("%s()\n", __func__);
+
+	return s5h1409_writereg(state, 0xfa, 0);
+}
+
+static void s5h1409_set_qam_amhum_mode(struct dvb_frontend *fe)
+{
+	struct s5h1409_state *state = fe->demodulator_priv;
+	u16 reg;
+
+	if (state->qam_state < QAM_STATE_INTERLEAVE_SET) {
+		/* We should not perform amhum optimization until
+		   the interleave mode has been configured */
+		return;
+	}
+
+	if (state->qam_state == QAM_STATE_QAM_OPTIMIZED_L3) {
+		/* We've already reached the maximum optimization level, so
+		   dont bother banging on the status registers */
+		return;
+	}
+
+	/* QAM EQ lock check */
+	reg = s5h1409_readreg(state, 0xf0);
+
+	if ((reg >> 13) & 0x1) {
+		reg &= 0xff;
+
+		s5h1409_writereg(state, 0x96, 0x000c);
+		if (reg < 0x68) {
+			if (state->qam_state < QAM_STATE_QAM_OPTIMIZED_L3) {
+				dprintk("%s() setting QAM state to OPT_L3\n",
+					__func__);
+				s5h1409_writereg(state, 0x93, 0x3130);
+				s5h1409_writereg(state, 0x9e, 0x2836);
+				state->qam_state = QAM_STATE_QAM_OPTIMIZED_L3;
+			}
+		} else {
+			if (state->qam_state < QAM_STATE_QAM_OPTIMIZED_L2) {
+				dprintk("%s() setting QAM state to OPT_L2\n",
+					__func__);
+				s5h1409_writereg(state, 0x93, 0x3332);
+				s5h1409_writereg(state, 0x9e, 0x2c37);
+				state->qam_state = QAM_STATE_QAM_OPTIMIZED_L2;
+			}
+		}
+
+	} else {
+		if (state->qam_state < QAM_STATE_QAM_OPTIMIZED_L1) {
+			dprintk("%s() setting QAM state to OPT_L1\n", __func__);
+			s5h1409_writereg(state, 0x96, 0x0008);
+			s5h1409_writereg(state, 0x93, 0x3332);
+			s5h1409_writereg(state, 0x9e, 0x2c37);
+			state->qam_state = QAM_STATE_QAM_OPTIMIZED_L1;
+		}
+	}
+}
+
+static void s5h1409_set_qam_amhum_mode_legacy(struct dvb_frontend *fe)
+{
+	struct s5h1409_state *state = fe->demodulator_priv;
+	u16 reg;
+
+	if (state->is_qam_locked)
+		return;
+
+	/* QAM EQ lock check */
+	reg = s5h1409_readreg(state, 0xf0);
+
+	if ((reg >> 13) & 0x1) {
+
+		state->is_qam_locked = 1;
+		reg &= 0xff;
+
+		s5h1409_writereg(state, 0x96, 0x00c);
+		if ((reg < 0x38) || (reg > 0x68)) {
+			s5h1409_writereg(state, 0x93, 0x3332);
+			s5h1409_writereg(state, 0x9e, 0x2c37);
+		} else {
+			s5h1409_writereg(state, 0x93, 0x3130);
+			s5h1409_writereg(state, 0x9e, 0x2836);
+		}
+
+	} else {
+		s5h1409_writereg(state, 0x96, 0x0008);
+		s5h1409_writereg(state, 0x93, 0x3332);
+		s5h1409_writereg(state, 0x9e, 0x2c37);
+	}
+}
+
+static void s5h1409_set_qam_interleave_mode(struct dvb_frontend *fe)
+{
+	struct s5h1409_state *state = fe->demodulator_priv;
+	u16 reg, reg1, reg2;
+
+	if (state->qam_state >= QAM_STATE_INTERLEAVE_SET) {
+		/* We've done the optimization already */
+		return;
+	}
+
+	reg = s5h1409_readreg(state, 0xf1);
+
+	/* Master lock */
+	if ((reg >> 15) & 0x1) {
+		if (state->qam_state == QAM_STATE_UNTUNED ||
+		    state->qam_state == QAM_STATE_TUNING_STARTED) {
+			dprintk("%s() setting QAM state to INTERLEAVE_SET\n",
+				__func__);
+			reg1 = s5h1409_readreg(state, 0xb2);
+			reg2 = s5h1409_readreg(state, 0xad);
+
+			s5h1409_writereg(state, 0x96, 0x0020);
+			s5h1409_writereg(state, 0xad,
+				(((reg1 & 0xf000) >> 4) | (reg2 & 0xf0ff)));
+			state->qam_state = QAM_STATE_INTERLEAVE_SET;
+		}
+	} else {
+		if (state->qam_state == QAM_STATE_UNTUNED) {
+			dprintk("%s() setting QAM state to TUNING_STARTED\n",
+				__func__);
+			s5h1409_writereg(state, 0x96, 0x08);
+			s5h1409_writereg(state, 0xab,
+				s5h1409_readreg(state, 0xab) | 0x1001);
+			state->qam_state = QAM_STATE_TUNING_STARTED;
+		}
+	}
+}
+
+static void s5h1409_set_qam_interleave_mode_legacy(struct dvb_frontend *fe)
+{
+	struct s5h1409_state *state = fe->demodulator_priv;
+	u16 reg, reg1, reg2;
+
+	reg = s5h1409_readreg(state, 0xf1);
+
+	/* Master lock */
+	if ((reg >> 15) & 0x1) {
+		if (state->qam_state != 2) {
+			state->qam_state = 2;
+			reg1 = s5h1409_readreg(state, 0xb2);
+			reg2 = s5h1409_readreg(state, 0xad);
+
+			s5h1409_writereg(state, 0x96, 0x20);
+			s5h1409_writereg(state, 0xad,
+				(((reg1 & 0xf000) >> 4) | (reg2 & 0xf0ff)));
+			s5h1409_writereg(state, 0xab,
+				s5h1409_readreg(state, 0xab) & 0xeffe);
+		}
+	} else {
+		if (state->qam_state != 1) {
+			state->qam_state = 1;
+			s5h1409_writereg(state, 0x96, 0x08);
+			s5h1409_writereg(state, 0xab,
+				s5h1409_readreg(state, 0xab) | 0x1001);
+		}
+	}
+}
+
+/* Talk to the demod, set the FEC, GUARD, QAM settings etc */
+static int s5h1409_set_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct s5h1409_state *state = fe->demodulator_priv;
+
+	dprintk("%s(frequency=%d)\n", __func__, p->frequency);
+
+	s5h1409_softreset(fe);
+
+	state->current_frequency = p->frequency;
+
+	s5h1409_enable_modulation(fe, p->modulation);
+
+	if (fe->ops.tuner_ops.set_params) {
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 1);
+		fe->ops.tuner_ops.set_params(fe);
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 0);
+	}
+
+	/* Issue a reset to the demod so it knows to resync against the
+	   newly tuned frequency */
+	s5h1409_softreset(fe);
+
+	/* Optimize the demod for QAM */
+	if (state->current_modulation != VSB_8) {
+		/* This almost certainly applies to all boards, but for now
+		   only do it for the HVR-1600.  Once the other boards are
+		   tested, the "legacy" versions can just go away */
+		if (state->config->hvr1600_opt == S5H1409_HVR1600_OPTIMIZE) {
+			s5h1409_set_qam_interleave_mode(fe);
+			s5h1409_set_qam_amhum_mode(fe);
+		} else {
+			s5h1409_set_qam_amhum_mode_legacy(fe);
+			s5h1409_set_qam_interleave_mode_legacy(fe);
+		}
+	}
+
+	return 0;
+}
+
+static int s5h1409_set_mpeg_timing(struct dvb_frontend *fe, int mode)
+{
+	struct s5h1409_state *state = fe->demodulator_priv;
+	u16 val;
+
+	dprintk("%s(%d)\n", __func__, mode);
+
+	val = s5h1409_readreg(state, 0xac) & 0xcfff;
+	switch (mode) {
+	case S5H1409_MPEGTIMING_CONTINOUS_INVERTING_CLOCK:
+		val |= 0x0000;
+		break;
+	case S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK:
+		dprintk("%s(%d) Mode1 or Defaulting\n", __func__, mode);
+		val |= 0x1000;
+		break;
+	case S5H1409_MPEGTIMING_NONCONTINOUS_INVERTING_CLOCK:
+		val |= 0x2000;
+		break;
+	case S5H1409_MPEGTIMING_NONCONTINOUS_NONINVERTING_CLOCK:
+		val |= 0x3000;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* Configure MPEG Signal Timing charactistics */
+	return s5h1409_writereg(state, 0xac, val);
+}
+
+/* Reset the demod hardware and reset all of the configuration registers
+   to a default state. */
+static int s5h1409_init(struct dvb_frontend *fe)
+{
+	int i;
+
+	struct s5h1409_state *state = fe->demodulator_priv;
+	dprintk("%s()\n", __func__);
+
+	s5h1409_sleep(fe, 0);
+	s5h1409_register_reset(fe);
+
+	for (i = 0; i < ARRAY_SIZE(init_tab); i++)
+		s5h1409_writereg(state, init_tab[i].reg, init_tab[i].data);
+
+	/* The datasheet says that after initialisation, VSB is default */
+	state->current_modulation = VSB_8;
+
+	/* Optimize for the HVR-1600 if appropriate.  Note that some of these
+	   may get folded into the generic case after testing with other
+	   devices */
+	if (state->config->hvr1600_opt == S5H1409_HVR1600_OPTIMIZE) {
+		/* VSB AGC REF */
+		s5h1409_writereg(state, 0x09, 0x0050);
+
+		/* Unknown but Windows driver does it... */
+		s5h1409_writereg(state, 0x21, 0x0001);
+		s5h1409_writereg(state, 0x50, 0x030e);
+
+		/* QAM AGC REF */
+		s5h1409_writereg(state, 0x82, 0x0800);
+	}
+
+	if (state->config->output_mode == S5H1409_SERIAL_OUTPUT)
+		s5h1409_writereg(state, 0xab,
+			s5h1409_readreg(state, 0xab) | 0x100); /* Serial */
+	else
+		s5h1409_writereg(state, 0xab,
+			s5h1409_readreg(state, 0xab) & 0xfeff); /* Parallel */
+
+	s5h1409_set_spectralinversion(fe, state->config->inversion);
+	s5h1409_set_if_freq(fe, state->if_freq);
+	s5h1409_set_gpio(fe, state->config->gpio);
+	s5h1409_set_mpeg_timing(fe, state->config->mpeg_timing);
+	s5h1409_softreset(fe);
+
+	/* Note: Leaving the I2C gate closed. */
+	s5h1409_i2c_gate_ctrl(fe, 0);
+
+	return 0;
+}
+
+static int s5h1409_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+	struct s5h1409_state *state = fe->demodulator_priv;
+	u16 reg;
+	u32 tuner_status = 0;
+
+	*status = 0;
+
+	/* Optimize the demod for QAM */
+	if (state->current_modulation != VSB_8) {
+		/* This almost certainly applies to all boards, but for now
+		   only do it for the HVR-1600.  Once the other boards are
+		   tested, the "legacy" versions can just go away */
+		if (state->config->hvr1600_opt == S5H1409_HVR1600_OPTIMIZE) {
+			s5h1409_set_qam_interleave_mode(fe);
+			s5h1409_set_qam_amhum_mode(fe);
+		}
+	}
+
+	/* Get the demodulator status */
+	reg = s5h1409_readreg(state, 0xf1);
+	if (reg & 0x1000)
+		*status |= FE_HAS_VITERBI;
+	if (reg & 0x8000)
+		*status |= FE_HAS_LOCK | FE_HAS_SYNC;
+
+	switch (state->config->status_mode) {
+	case S5H1409_DEMODLOCKING:
+		if (*status & FE_HAS_VITERBI)
+			*status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
+		break;
+	case S5H1409_TUNERLOCKING:
+		/* Get the tuner status */
+		if (fe->ops.tuner_ops.get_status) {
+			if (fe->ops.i2c_gate_ctrl)
+				fe->ops.i2c_gate_ctrl(fe, 1);
+
+			fe->ops.tuner_ops.get_status(fe, &tuner_status);
+
+			if (fe->ops.i2c_gate_ctrl)
+				fe->ops.i2c_gate_ctrl(fe, 0);
+		}
+		if (tuner_status)
+			*status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
+		break;
+	}
+
+	dprintk("%s() status 0x%08x\n", __func__, *status);
+
+	return 0;
+}
+
+static int s5h1409_qam256_lookup_snr(struct dvb_frontend *fe, u16 *snr, u16 v)
+{
+	int i, ret = -EINVAL;
+	dprintk("%s()\n", __func__);
+
+	for (i = 0; i < ARRAY_SIZE(qam256_snr_tab); i++) {
+		if (v < qam256_snr_tab[i].val) {
+			*snr = qam256_snr_tab[i].data;
+			ret = 0;
+			break;
+		}
+	}
+	return ret;
+}
+
+static int s5h1409_qam64_lookup_snr(struct dvb_frontend *fe, u16 *snr, u16 v)
+{
+	int i, ret = -EINVAL;
+	dprintk("%s()\n", __func__);
+
+	for (i = 0; i < ARRAY_SIZE(qam64_snr_tab); i++) {
+		if (v < qam64_snr_tab[i].val) {
+			*snr = qam64_snr_tab[i].data;
+			ret = 0;
+			break;
+		}
+	}
+	return ret;
+}
+
+static int s5h1409_vsb_lookup_snr(struct dvb_frontend *fe, u16 *snr, u16 v)
+{
+	int i, ret = -EINVAL;
+	dprintk("%s()\n", __func__);
+
+	for (i = 0; i < ARRAY_SIZE(vsb_snr_tab); i++) {
+		if (v > vsb_snr_tab[i].val) {
+			*snr = vsb_snr_tab[i].data;
+			ret = 0;
+			break;
+		}
+	}
+	dprintk("%s() snr=%d\n", __func__, *snr);
+	return ret;
+}
+
+static int s5h1409_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+	struct s5h1409_state *state = fe->demodulator_priv;
+	u16 reg;
+	dprintk("%s()\n", __func__);
+
+	switch (state->current_modulation) {
+	case QAM_64:
+		reg = s5h1409_readreg(state, 0xf0) & 0xff;
+		return s5h1409_qam64_lookup_snr(fe, snr, reg);
+	case QAM_256:
+		reg = s5h1409_readreg(state, 0xf0) & 0xff;
+		return s5h1409_qam256_lookup_snr(fe, snr, reg);
+	case VSB_8:
+		reg = s5h1409_readreg(state, 0xf1) & 0x3ff;
+		return s5h1409_vsb_lookup_snr(fe, snr, reg);
+	default:
+		break;
+	}
+
+	return -EINVAL;
+}
+
+static int s5h1409_read_signal_strength(struct dvb_frontend *fe,
+					u16 *signal_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%
+	 */
+	u16 snr;
+	u32 tmp;
+	int ret = s5h1409_read_snr(fe, &snr);
+
+	*signal_strength = 0;
+
+	if (0 == ret) {
+		/* The following calculation method was chosen
+		 * purely for the sake of code re-use from the
+		 * other demod drivers that use this method */
+
+		/* Convert from SNR in dB * 10 to 8.24 fixed-point */
+		tmp = (snr * ((1 << 24) / 10));
+
+		/* Convert from 8.24 fixed-point to
+		 * scale the range 0 - 35*2^24 into 0 - 65535*/
+		if (tmp >= 8960 * 0x10000)
+			*signal_strength = 0xffff;
+		else
+			*signal_strength = tmp / 8960;
+	}
+
+	return ret;
+}
+
+static int s5h1409_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+	struct s5h1409_state *state = fe->demodulator_priv;
+
+	*ucblocks = s5h1409_readreg(state, 0xb5);
+
+	return 0;
+}
+
+static int s5h1409_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+	return s5h1409_read_ucblocks(fe, ber);
+}
+
+static int s5h1409_get_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct s5h1409_state *state = fe->demodulator_priv;
+
+	p->frequency = state->current_frequency;
+	p->modulation = state->current_modulation;
+
+	return 0;
+}
+
+static int s5h1409_get_tune_settings(struct dvb_frontend *fe,
+				     struct dvb_frontend_tune_settings *tune)
+{
+	tune->min_delay_ms = 1000;
+	return 0;
+}
+
+static void s5h1409_release(struct dvb_frontend *fe)
+{
+	struct s5h1409_state *state = fe->demodulator_priv;
+	kfree(state);
+}
+
+static struct dvb_frontend_ops s5h1409_ops;
+
+struct dvb_frontend *s5h1409_attach(const struct s5h1409_config *config,
+				    struct i2c_adapter *i2c)
+{
+	struct s5h1409_state *state = NULL;
+	u16 reg;
+
+	/* allocate memory for the internal state */
+	state = kzalloc(sizeof(struct s5h1409_state), GFP_KERNEL);
+	if (state == NULL)
+		goto error;
+
+	/* setup the state */
+	state->config = config;
+	state->i2c = i2c;
+	state->current_modulation = 0;
+	state->if_freq = S5H1409_VSB_IF_FREQ;
+
+	/* check if the demod exists */
+	reg = s5h1409_readreg(state, 0x04);
+	if ((reg != 0x0066) && (reg != 0x007f))
+		goto error;
+
+	/* create dvb_frontend */
+	memcpy(&state->frontend.ops, &s5h1409_ops,
+	       sizeof(struct dvb_frontend_ops));
+	state->frontend.demodulator_priv = state;
+
+	if (s5h1409_init(&state->frontend) != 0) {
+		printk(KERN_ERR "%s: Failed to initialize correctly\n",
+			__func__);
+		goto error;
+	}
+
+	/* Note: Leaving the I2C gate open here. */
+	s5h1409_i2c_gate_ctrl(&state->frontend, 1);
+
+	return &state->frontend;
+
+error:
+	kfree(state);
+	return NULL;
+}
+EXPORT_SYMBOL(s5h1409_attach);
+
+static struct dvb_frontend_ops s5h1409_ops = {
+	.delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
+	.info = {
+		.name			= "Samsung S5H1409 QAM/8VSB Frontend",
+		.frequency_min		= 54000000,
+		.frequency_max		= 858000000,
+		.frequency_stepsize	= 62500,
+		.caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
+	},
+
+	.init                 = s5h1409_init,
+	.i2c_gate_ctrl        = s5h1409_i2c_gate_ctrl,
+	.set_frontend         = s5h1409_set_frontend,
+	.get_frontend         = s5h1409_get_frontend,
+	.get_tune_settings    = s5h1409_get_tune_settings,
+	.read_status          = s5h1409_read_status,
+	.read_ber             = s5h1409_read_ber,
+	.read_signal_strength = s5h1409_read_signal_strength,
+	.read_snr             = s5h1409_read_snr,
+	.read_ucblocks        = s5h1409_read_ucblocks,
+	.release              = s5h1409_release,
+};
+
+MODULE_DESCRIPTION("Samsung S5H1409 QAM-B/ATSC Demodulator driver");
+MODULE_AUTHOR("Steven Toth");
+MODULE_LICENSE("GPL");
+
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ */
diff --git a/drivers/media/dvb-frontends/s5h1409.h b/drivers/media/dvb-frontends/s5h1409.h
new file mode 100644
index 0000000..91f2ebd
--- /dev/null
+++ b/drivers/media/dvb-frontends/s5h1409.h
@@ -0,0 +1,88 @@
+/*
+    Samsung S5H1409 VSB/QAM demodulator driver
+
+    Copyright (C) 2006 Steven Toth <stoth@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 __S5H1409_H__
+#define __S5H1409_H__
+
+#include <linux/dvb/frontend.h>
+
+struct s5h1409_config {
+	/* the demodulator's i2c address */
+	u8 demod_address;
+
+	/* serial/parallel output */
+#define S5H1409_PARALLEL_OUTPUT 0
+#define S5H1409_SERIAL_OUTPUT   1
+	u8 output_mode;
+
+	/* GPIO Setting */
+#define S5H1409_GPIO_OFF 0
+#define S5H1409_GPIO_ON  1
+	u8 gpio;
+
+	/* IF Freq for QAM in KHz, VSB is hardcoded to 5380 */
+	u16 qam_if;
+
+	/* Spectral Inversion */
+#define S5H1409_INVERSION_OFF 0
+#define S5H1409_INVERSION_ON  1
+	u8 inversion;
+
+	/* Return lock status based on tuner lock, or demod lock */
+#define S5H1409_TUNERLOCKING 0
+#define S5H1409_DEMODLOCKING 1
+	u8 status_mode;
+
+	/* MPEG signal timing */
+#define S5H1409_MPEGTIMING_CONTINOUS_INVERTING_CLOCK       0
+#define S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK    1
+#define S5H1409_MPEGTIMING_NONCONTINOUS_INVERTING_CLOCK    2
+#define S5H1409_MPEGTIMING_NONCONTINOUS_NONINVERTING_CLOCK 3
+	u16 mpeg_timing;
+
+	/* HVR-1600 optimizations (to better work with MXL5005s)
+	   Note: some of these are likely to be folded into the generic driver
+	   after being regression tested with other boards */
+#define S5H1409_HVR1600_NOOPTIMIZE 0
+#define S5H1409_HVR1600_OPTIMIZE   1
+	u8 hvr1600_opt;
+};
+
+#if defined(CONFIG_DVB_S5H1409) || (defined(CONFIG_DVB_S5H1409_MODULE) \
+	&& defined(MODULE))
+extern struct dvb_frontend *s5h1409_attach(const struct s5h1409_config *config,
+					   struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend *s5h1409_attach(
+	const struct s5h1409_config *config,
+	struct i2c_adapter *i2c)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif /* CONFIG_DVB_S5H1409 */
+
+#endif /* __S5H1409_H__ */
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ */
diff --git a/drivers/media/dvb-frontends/s5h1411.c b/drivers/media/dvb-frontends/s5h1411.c
new file mode 100644
index 0000000..6cc4b7a
--- /dev/null
+++ b/drivers/media/dvb-frontends/s5h1411.c
@@ -0,0 +1,951 @@
+/*
+    Samsung S5H1411 VSB/QAM demodulator driver
+
+    Copyright (C) 2008 Steven Toth <stoth@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/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include "dvb_frontend.h"
+#include "s5h1411.h"
+
+struct s5h1411_state {
+
+	struct i2c_adapter *i2c;
+
+	/* configuration settings */
+	const struct s5h1411_config *config;
+
+	struct dvb_frontend frontend;
+
+	fe_modulation_t current_modulation;
+	unsigned int first_tune:1;
+
+	u32 current_frequency;
+	int if_freq;
+
+	u8 inversion;
+};
+
+static int debug;
+
+#define dprintk(arg...) do {	\
+	if (debug)		\
+		printk(arg);	\
+	} while (0)
+
+/* Register values to initialise the demod, defaults to VSB */
+static struct init_tab {
+	u8	addr;
+	u8	reg;
+	u16	data;
+} init_tab[] = {
+	{ S5H1411_I2C_TOP_ADDR, 0x00, 0x0071, },
+	{ S5H1411_I2C_TOP_ADDR, 0x08, 0x0047, },
+	{ S5H1411_I2C_TOP_ADDR, 0x1c, 0x0400, },
+	{ S5H1411_I2C_TOP_ADDR, 0x1e, 0x0370, },
+	{ S5H1411_I2C_TOP_ADDR, 0x1f, 0x342c, },
+	{ S5H1411_I2C_TOP_ADDR, 0x24, 0x0231, },
+	{ S5H1411_I2C_TOP_ADDR, 0x25, 0x1011, },
+	{ S5H1411_I2C_TOP_ADDR, 0x26, 0x0f07, },
+	{ S5H1411_I2C_TOP_ADDR, 0x27, 0x0f04, },
+	{ S5H1411_I2C_TOP_ADDR, 0x28, 0x070f, },
+	{ S5H1411_I2C_TOP_ADDR, 0x29, 0x2820, },
+	{ S5H1411_I2C_TOP_ADDR, 0x2a, 0x102e, },
+	{ S5H1411_I2C_TOP_ADDR, 0x2b, 0x0220, },
+	{ S5H1411_I2C_TOP_ADDR, 0x2e, 0x0d0e, },
+	{ S5H1411_I2C_TOP_ADDR, 0x2f, 0x1013, },
+	{ S5H1411_I2C_TOP_ADDR, 0x31, 0x171b, },
+	{ S5H1411_I2C_TOP_ADDR, 0x32, 0x0e0f, },
+	{ S5H1411_I2C_TOP_ADDR, 0x33, 0x0f10, },
+	{ S5H1411_I2C_TOP_ADDR, 0x34, 0x170e, },
+	{ S5H1411_I2C_TOP_ADDR, 0x35, 0x4b10, },
+	{ S5H1411_I2C_TOP_ADDR, 0x36, 0x0f17, },
+	{ S5H1411_I2C_TOP_ADDR, 0x3c, 0x1577, },
+	{ S5H1411_I2C_TOP_ADDR, 0x3d, 0x081a, },
+	{ S5H1411_I2C_TOP_ADDR, 0x3e, 0x77ee, },
+	{ S5H1411_I2C_TOP_ADDR, 0x40, 0x1e09, },
+	{ S5H1411_I2C_TOP_ADDR, 0x41, 0x0f0c, },
+	{ S5H1411_I2C_TOP_ADDR, 0x42, 0x1f10, },
+	{ S5H1411_I2C_TOP_ADDR, 0x4d, 0x0509, },
+	{ S5H1411_I2C_TOP_ADDR, 0x4e, 0x0a00, },
+	{ S5H1411_I2C_TOP_ADDR, 0x50, 0x0000, },
+	{ S5H1411_I2C_TOP_ADDR, 0x5b, 0x0000, },
+	{ S5H1411_I2C_TOP_ADDR, 0x5c, 0x0008, },
+	{ S5H1411_I2C_TOP_ADDR, 0x57, 0x1101, },
+	{ S5H1411_I2C_TOP_ADDR, 0x65, 0x007c, },
+	{ S5H1411_I2C_TOP_ADDR, 0x68, 0x0512, },
+	{ S5H1411_I2C_TOP_ADDR, 0x69, 0x0258, },
+	{ S5H1411_I2C_TOP_ADDR, 0x70, 0x0004, },
+	{ S5H1411_I2C_TOP_ADDR, 0x71, 0x0007, },
+	{ S5H1411_I2C_TOP_ADDR, 0x76, 0x00a9, },
+	{ S5H1411_I2C_TOP_ADDR, 0x78, 0x3141, },
+	{ S5H1411_I2C_TOP_ADDR, 0x7a, 0x3141, },
+	{ S5H1411_I2C_TOP_ADDR, 0xb3, 0x8003, },
+	{ S5H1411_I2C_TOP_ADDR, 0xb5, 0xa6bb, },
+	{ S5H1411_I2C_TOP_ADDR, 0xb6, 0x0609, },
+	{ S5H1411_I2C_TOP_ADDR, 0xb7, 0x2f06, },
+	{ S5H1411_I2C_TOP_ADDR, 0xb8, 0x003f, },
+	{ S5H1411_I2C_TOP_ADDR, 0xb9, 0x2700, },
+	{ S5H1411_I2C_TOP_ADDR, 0xba, 0xfac8, },
+	{ S5H1411_I2C_TOP_ADDR, 0xbe, 0x1003, },
+	{ S5H1411_I2C_TOP_ADDR, 0xbf, 0x103f, },
+	{ S5H1411_I2C_TOP_ADDR, 0xce, 0x2000, },
+	{ S5H1411_I2C_TOP_ADDR, 0xcf, 0x0800, },
+	{ S5H1411_I2C_TOP_ADDR, 0xd0, 0x0800, },
+	{ S5H1411_I2C_TOP_ADDR, 0xd1, 0x0400, },
+	{ S5H1411_I2C_TOP_ADDR, 0xd2, 0x0800, },
+	{ S5H1411_I2C_TOP_ADDR, 0xd3, 0x2000, },
+	{ S5H1411_I2C_TOP_ADDR, 0xd4, 0x3000, },
+	{ S5H1411_I2C_TOP_ADDR, 0xdb, 0x4a9b, },
+	{ S5H1411_I2C_TOP_ADDR, 0xdc, 0x1000, },
+	{ S5H1411_I2C_TOP_ADDR, 0xde, 0x0001, },
+	{ S5H1411_I2C_TOP_ADDR, 0xdf, 0x0000, },
+	{ S5H1411_I2C_TOP_ADDR, 0xe3, 0x0301, },
+	{ S5H1411_I2C_QAM_ADDR, 0xf3, 0x0000, },
+	{ S5H1411_I2C_QAM_ADDR, 0xf3, 0x0001, },
+	{ S5H1411_I2C_QAM_ADDR, 0x08, 0x0600, },
+	{ S5H1411_I2C_QAM_ADDR, 0x18, 0x4201, },
+	{ S5H1411_I2C_QAM_ADDR, 0x1e, 0x6476, },
+	{ S5H1411_I2C_QAM_ADDR, 0x21, 0x0830, },
+	{ S5H1411_I2C_QAM_ADDR, 0x0c, 0x5679, },
+	{ S5H1411_I2C_QAM_ADDR, 0x0d, 0x579b, },
+	{ S5H1411_I2C_QAM_ADDR, 0x24, 0x0102, },
+	{ S5H1411_I2C_QAM_ADDR, 0x31, 0x7488, },
+	{ S5H1411_I2C_QAM_ADDR, 0x32, 0x0a08, },
+	{ S5H1411_I2C_QAM_ADDR, 0x3d, 0x8689, },
+	{ S5H1411_I2C_QAM_ADDR, 0x49, 0x0048, },
+	{ S5H1411_I2C_QAM_ADDR, 0x57, 0x2012, },
+	{ S5H1411_I2C_QAM_ADDR, 0x5d, 0x7676, },
+	{ S5H1411_I2C_QAM_ADDR, 0x04, 0x0400, },
+	{ S5H1411_I2C_QAM_ADDR, 0x58, 0x00c0, },
+	{ S5H1411_I2C_QAM_ADDR, 0x5b, 0x0100, },
+};
+
+/* VSB SNR lookup table */
+static struct vsb_snr_tab {
+	u16	val;
+	u16	data;
+} vsb_snr_tab[] = {
+	{  0x39f, 300, },
+	{  0x39b, 295, },
+	{  0x397, 290, },
+	{  0x394, 285, },
+	{  0x38f, 280, },
+	{  0x38b, 275, },
+	{  0x387, 270, },
+	{  0x382, 265, },
+	{  0x37d, 260, },
+	{  0x377, 255, },
+	{  0x370, 250, },
+	{  0x36a, 245, },
+	{  0x364, 240, },
+	{  0x35b, 235, },
+	{  0x353, 230, },
+	{  0x349, 225, },
+	{  0x340, 320, },
+	{  0x337, 215, },
+	{  0x327, 210, },
+	{  0x31b, 205, },
+	{  0x310, 200, },
+	{  0x302, 195, },
+	{  0x2f3, 190, },
+	{  0x2e4, 185, },
+	{  0x2d7, 180, },
+	{  0x2cd, 175, },
+	{  0x2bb, 170, },
+	{  0x2a9, 165, },
+	{  0x29e, 160, },
+	{  0x284, 155, },
+	{  0x27a, 150, },
+	{  0x260, 145, },
+	{  0x23a, 140, },
+	{  0x224, 135, },
+	{  0x213, 130, },
+	{  0x204, 125, },
+	{  0x1fe, 120, },
+	{      0,   0, },
+};
+
+/* QAM64 SNR lookup table */
+static struct qam64_snr_tab {
+	u16	val;
+	u16	data;
+} qam64_snr_tab[] = {
+	{  0x0001,   0, },
+	{  0x0af0, 300, },
+	{  0x0d80, 290, },
+	{  0x10a0, 280, },
+	{  0x14b5, 270, },
+	{  0x1590, 268, },
+	{  0x1680, 266, },
+	{  0x17b0, 264, },
+	{  0x18c0, 262, },
+	{  0x19b0, 260, },
+	{  0x1ad0, 258, },
+	{  0x1d00, 256, },
+	{  0x1da0, 254, },
+	{  0x1ef0, 252, },
+	{  0x2050, 250, },
+	{  0x20f0, 249, },
+	{  0x21d0, 248, },
+	{  0x22b0, 247, },
+	{  0x23a0, 246, },
+	{  0x2470, 245, },
+	{  0x24f0, 244, },
+	{  0x25a0, 243, },
+	{  0x26c0, 242, },
+	{  0x27b0, 241, },
+	{  0x28d0, 240, },
+	{  0x29b0, 239, },
+	{  0x2ad0, 238, },
+	{  0x2ba0, 237, },
+	{  0x2c80, 236, },
+	{  0x2d20, 235, },
+	{  0x2e00, 234, },
+	{  0x2f10, 233, },
+	{  0x3050, 232, },
+	{  0x3190, 231, },
+	{  0x3300, 230, },
+	{  0x3340, 229, },
+	{  0x3200, 228, },
+	{  0x3550, 227, },
+	{  0x3610, 226, },
+	{  0x3600, 225, },
+	{  0x3700, 224, },
+	{  0x3800, 223, },
+	{  0x3920, 222, },
+	{  0x3a20, 221, },
+	{  0x3b30, 220, },
+	{  0x3d00, 219, },
+	{  0x3e00, 218, },
+	{  0x4000, 217, },
+	{  0x4100, 216, },
+	{  0x4300, 215, },
+	{  0x4400, 214, },
+	{  0x4600, 213, },
+	{  0x4700, 212, },
+	{  0x4800, 211, },
+	{  0x4a00, 210, },
+	{  0x4b00, 209, },
+	{  0x4d00, 208, },
+	{  0x4f00, 207, },
+	{  0x5050, 206, },
+	{  0x5200, 205, },
+	{  0x53c0, 204, },
+	{  0x5450, 203, },
+	{  0x5650, 202, },
+	{  0x5820, 201, },
+	{  0x6000, 200, },
+	{  0xffff,   0, },
+};
+
+/* QAM256 SNR lookup table */
+static struct qam256_snr_tab {
+	u16	val;
+	u16	data;
+} qam256_snr_tab[] = {
+	{  0x0001,   0, },
+	{  0x0970, 400, },
+	{  0x0a90, 390, },
+	{  0x0b90, 380, },
+	{  0x0d90, 370, },
+	{  0x0ff0, 360, },
+	{  0x1240, 350, },
+	{  0x1345, 348, },
+	{  0x13c0, 346, },
+	{  0x14c0, 344, },
+	{  0x1500, 342, },
+	{  0x1610, 340, },
+	{  0x1700, 338, },
+	{  0x1800, 336, },
+	{  0x18b0, 334, },
+	{  0x1900, 332, },
+	{  0x1ab0, 330, },
+	{  0x1bc0, 328, },
+	{  0x1cb0, 326, },
+	{  0x1db0, 324, },
+	{  0x1eb0, 322, },
+	{  0x2030, 320, },
+	{  0x2200, 318, },
+	{  0x2280, 316, },
+	{  0x2410, 314, },
+	{  0x25b0, 312, },
+	{  0x27a0, 310, },
+	{  0x2840, 308, },
+	{  0x29d0, 306, },
+	{  0x2b10, 304, },
+	{  0x2d30, 302, },
+	{  0x2f20, 300, },
+	{  0x30c0, 298, },
+	{  0x3260, 297, },
+	{  0x32c0, 296, },
+	{  0x3300, 295, },
+	{  0x33b0, 294, },
+	{  0x34b0, 293, },
+	{  0x35a0, 292, },
+	{  0x3650, 291, },
+	{  0x3800, 290, },
+	{  0x3900, 289, },
+	{  0x3a50, 288, },
+	{  0x3b30, 287, },
+	{  0x3cb0, 286, },
+	{  0x3e20, 285, },
+	{  0x3fa0, 284, },
+	{  0x40a0, 283, },
+	{  0x41c0, 282, },
+	{  0x42f0, 281, },
+	{  0x44a0, 280, },
+	{  0x4600, 279, },
+	{  0x47b0, 278, },
+	{  0x4900, 277, },
+	{  0x4a00, 276, },
+	{  0x4ba0, 275, },
+	{  0x4d00, 274, },
+	{  0x4f00, 273, },
+	{  0x5000, 272, },
+	{  0x51f0, 272, },
+	{  0x53a0, 270, },
+	{  0x5520, 269, },
+	{  0x5700, 268, },
+	{  0x5800, 267, },
+	{  0x5a00, 266, },
+	{  0x5c00, 265, },
+	{  0x5d00, 264, },
+	{  0x5f00, 263, },
+	{  0x6000, 262, },
+	{  0x6200, 261, },
+	{  0x6400, 260, },
+	{  0xffff,   0, },
+};
+
+/* 8 bit registers, 16 bit values */
+static int s5h1411_writereg(struct s5h1411_state *state,
+	u8 addr, u8 reg, u16 data)
+{
+	int ret;
+	u8 buf[] = { reg, data >> 8,  data & 0xff };
+
+	struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = buf, .len = 3 };
+
+	ret = i2c_transfer(state->i2c, &msg, 1);
+
+	if (ret != 1)
+		printk(KERN_ERR "%s: writereg error 0x%02x 0x%02x 0x%04x, "
+		       "ret == %i)\n", __func__, addr, reg, data, ret);
+
+	return (ret != 1) ? -1 : 0;
+}
+
+static u16 s5h1411_readreg(struct s5h1411_state *state, u8 addr, u8 reg)
+{
+	int ret;
+	u8 b0[] = { reg };
+	u8 b1[] = { 0, 0 };
+
+	struct i2c_msg msg[] = {
+		{ .addr = addr, .flags = 0, .buf = b0, .len = 1 },
+		{ .addr = addr, .flags = I2C_M_RD, .buf = b1, .len = 2 } };
+
+	ret = i2c_transfer(state->i2c, msg, 2);
+
+	if (ret != 2)
+		printk(KERN_ERR "%s: readreg error (ret == %i)\n",
+			__func__, ret);
+	return (b1[0] << 8) | b1[1];
+}
+
+static int s5h1411_softreset(struct dvb_frontend *fe)
+{
+	struct s5h1411_state *state = fe->demodulator_priv;
+
+	dprintk("%s()\n", __func__);
+
+	s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf7, 0);
+	s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf7, 1);
+	return 0;
+}
+
+static int s5h1411_set_if_freq(struct dvb_frontend *fe, int KHz)
+{
+	struct s5h1411_state *state = fe->demodulator_priv;
+
+	dprintk("%s(%d KHz)\n", __func__, KHz);
+
+	switch (KHz) {
+	case 3250:
+		s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x38, 0x10d5);
+		s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x39, 0x5342);
+		s5h1411_writereg(state, S5H1411_I2C_QAM_ADDR, 0x2c, 0x10d9);
+		break;
+	case 3500:
+		s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x38, 0x1225);
+		s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x39, 0x1e96);
+		s5h1411_writereg(state, S5H1411_I2C_QAM_ADDR, 0x2c, 0x1225);
+		break;
+	case 4000:
+		s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x38, 0x14bc);
+		s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x39, 0xb53e);
+		s5h1411_writereg(state, S5H1411_I2C_QAM_ADDR, 0x2c, 0x14bd);
+		break;
+	default:
+		dprintk("%s(%d KHz) Invalid, defaulting to 5380\n",
+			__func__, KHz);
+		/* no break, need to continue */
+	case 5380:
+	case 44000:
+		s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x38, 0x1be4);
+		s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x39, 0x3655);
+		s5h1411_writereg(state, S5H1411_I2C_QAM_ADDR, 0x2c, 0x1be4);
+		break;
+	}
+
+	state->if_freq = KHz;
+
+	return 0;
+}
+
+static int s5h1411_set_mpeg_timing(struct dvb_frontend *fe, int mode)
+{
+	struct s5h1411_state *state = fe->demodulator_priv;
+	u16 val;
+
+	dprintk("%s(%d)\n", __func__, mode);
+
+	val = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xbe) & 0xcfff;
+	switch (mode) {
+	case S5H1411_MPEGTIMING_CONTINOUS_INVERTING_CLOCK:
+		val |= 0x0000;
+		break;
+	case S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK:
+		dprintk("%s(%d) Mode1 or Defaulting\n", __func__, mode);
+		val |= 0x1000;
+		break;
+	case S5H1411_MPEGTIMING_NONCONTINOUS_INVERTING_CLOCK:
+		val |= 0x2000;
+		break;
+	case S5H1411_MPEGTIMING_NONCONTINOUS_NONINVERTING_CLOCK:
+		val |= 0x3000;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* Configure MPEG Signal Timing charactistics */
+	return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xbe, val);
+}
+
+static int s5h1411_set_spectralinversion(struct dvb_frontend *fe, int inversion)
+{
+	struct s5h1411_state *state = fe->demodulator_priv;
+	u16 val;
+
+	dprintk("%s(%d)\n", __func__, inversion);
+	val = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0x24) & ~0x1000;
+
+	if (inversion == 1)
+		val |= 0x1000; /* Inverted */
+
+	state->inversion = inversion;
+	return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x24, val);
+}
+
+static int s5h1411_set_serialmode(struct dvb_frontend *fe, int serial)
+{
+	struct s5h1411_state *state = fe->demodulator_priv;
+	u16 val;
+
+	dprintk("%s(%d)\n", __func__, serial);
+	val = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xbd) & ~0x100;
+
+	if (serial == 1)
+		val |= 0x100;
+
+	return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xbd, val);
+}
+
+static int s5h1411_enable_modulation(struct dvb_frontend *fe,
+				     fe_modulation_t m)
+{
+	struct s5h1411_state *state = fe->demodulator_priv;
+
+	dprintk("%s(0x%08x)\n", __func__, m);
+
+	if ((state->first_tune == 0) && (m == state->current_modulation)) {
+		dprintk("%s() Already at desired modulation.  Skipping...\n",
+			__func__);
+		return 0;
+	}
+
+	switch (m) {
+	case VSB_8:
+		dprintk("%s() VSB_8\n", __func__);
+		s5h1411_set_if_freq(fe, state->config->vsb_if);
+		s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x00, 0x71);
+		s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf6, 0x00);
+		s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xcd, 0xf1);
+		break;
+	case QAM_64:
+	case QAM_256:
+	case QAM_AUTO:
+		dprintk("%s() QAM_AUTO (64/256)\n", __func__);
+		s5h1411_set_if_freq(fe, state->config->qam_if);
+		s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x00, 0x0171);
+		s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf6, 0x0001);
+		s5h1411_writereg(state, S5H1411_I2C_QAM_ADDR, 0x16, 0x1101);
+		s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xcd, 0x00f0);
+		break;
+	default:
+		dprintk("%s() Invalid modulation\n", __func__);
+		return -EINVAL;
+	}
+
+	state->current_modulation = m;
+	state->first_tune = 0;
+	s5h1411_softreset(fe);
+
+	return 0;
+}
+
+static int s5h1411_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+	struct s5h1411_state *state = fe->demodulator_priv;
+
+	dprintk("%s(%d)\n", __func__, enable);
+
+	if (enable)
+		return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf5, 1);
+	else
+		return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf5, 0);
+}
+
+static int s5h1411_set_gpio(struct dvb_frontend *fe, int enable)
+{
+	struct s5h1411_state *state = fe->demodulator_priv;
+	u16 val;
+
+	dprintk("%s(%d)\n", __func__, enable);
+
+	val = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xe0) & ~0x02;
+
+	if (enable)
+		return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xe0,
+				val | 0x02);
+	else
+		return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xe0, val);
+}
+
+static int s5h1411_set_powerstate(struct dvb_frontend *fe, int enable)
+{
+	struct s5h1411_state *state = fe->demodulator_priv;
+
+	dprintk("%s(%d)\n", __func__, enable);
+
+	if (enable)
+		s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf4, 1);
+	else {
+		s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf4, 0);
+		s5h1411_softreset(fe);
+	}
+
+	return 0;
+}
+
+static int s5h1411_sleep(struct dvb_frontend *fe)
+{
+	return s5h1411_set_powerstate(fe, 1);
+}
+
+static int s5h1411_register_reset(struct dvb_frontend *fe)
+{
+	struct s5h1411_state *state = fe->demodulator_priv;
+
+	dprintk("%s()\n", __func__);
+
+	return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf3, 0);
+}
+
+/* Talk to the demod, set the FEC, GUARD, QAM settings etc */
+static int s5h1411_set_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct s5h1411_state *state = fe->demodulator_priv;
+
+	dprintk("%s(frequency=%d)\n", __func__, p->frequency);
+
+	s5h1411_softreset(fe);
+
+	state->current_frequency = p->frequency;
+
+	s5h1411_enable_modulation(fe, p->modulation);
+
+	if (fe->ops.tuner_ops.set_params) {
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 1);
+
+		fe->ops.tuner_ops.set_params(fe);
+
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 0);
+	}
+
+	/* Issue a reset to the demod so it knows to resync against the
+	   newly tuned frequency */
+	s5h1411_softreset(fe);
+
+	return 0;
+}
+
+/* Reset the demod hardware and reset all of the configuration registers
+   to a default state. */
+static int s5h1411_init(struct dvb_frontend *fe)
+{
+	struct s5h1411_state *state = fe->demodulator_priv;
+	int i;
+
+	dprintk("%s()\n", __func__);
+
+	s5h1411_set_powerstate(fe, 0);
+	s5h1411_register_reset(fe);
+
+	for (i = 0; i < ARRAY_SIZE(init_tab); i++)
+		s5h1411_writereg(state, init_tab[i].addr,
+			init_tab[i].reg,
+			init_tab[i].data);
+
+	/* The datasheet says that after initialisation, VSB is default */
+	state->current_modulation = VSB_8;
+
+	/* Although the datasheet says it's in VSB, empirical evidence
+	   shows problems getting lock on the first tuning request.  Make
+	   sure we call enable_modulation the first time around */
+	state->first_tune = 1;
+
+	if (state->config->output_mode == S5H1411_SERIAL_OUTPUT)
+		/* Serial */
+		s5h1411_set_serialmode(fe, 1);
+	else
+		/* Parallel */
+		s5h1411_set_serialmode(fe, 0);
+
+	s5h1411_set_spectralinversion(fe, state->config->inversion);
+	s5h1411_set_if_freq(fe, state->config->vsb_if);
+	s5h1411_set_gpio(fe, state->config->gpio);
+	s5h1411_set_mpeg_timing(fe, state->config->mpeg_timing);
+	s5h1411_softreset(fe);
+
+	/* Note: Leaving the I2C gate closed. */
+	s5h1411_i2c_gate_ctrl(fe, 0);
+
+	return 0;
+}
+
+static int s5h1411_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+	struct s5h1411_state *state = fe->demodulator_priv;
+	u16 reg;
+	u32 tuner_status = 0;
+
+	*status = 0;
+
+	/* Register F2 bit 15 = Master Lock, removed */
+
+	switch (state->current_modulation) {
+	case QAM_64:
+	case QAM_256:
+		reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xf0);
+		if (reg & 0x10) /* QAM FEC Lock */
+			*status |= FE_HAS_SYNC | FE_HAS_LOCK;
+		if (reg & 0x100) /* QAM EQ Lock */
+			*status |= FE_HAS_VITERBI | FE_HAS_CARRIER | FE_HAS_SIGNAL;
+
+		break;
+	case VSB_8:
+		reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xf2);
+		if (reg & 0x1000) /* FEC Lock */
+			*status |= FE_HAS_SYNC | FE_HAS_LOCK;
+		if (reg & 0x2000) /* EQ Lock */
+			*status |= FE_HAS_VITERBI | FE_HAS_CARRIER | FE_HAS_SIGNAL;
+
+		reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0x53);
+		if (reg & 0x1) /* AFC Lock */
+			*status |= FE_HAS_SIGNAL;
+
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (state->config->status_mode) {
+	case S5H1411_DEMODLOCKING:
+		if (*status & FE_HAS_VITERBI)
+			*status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
+		break;
+	case S5H1411_TUNERLOCKING:
+		/* Get the tuner status */
+		if (fe->ops.tuner_ops.get_status) {
+			if (fe->ops.i2c_gate_ctrl)
+				fe->ops.i2c_gate_ctrl(fe, 1);
+
+			fe->ops.tuner_ops.get_status(fe, &tuner_status);
+
+			if (fe->ops.i2c_gate_ctrl)
+				fe->ops.i2c_gate_ctrl(fe, 0);
+		}
+		if (tuner_status)
+			*status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
+		break;
+	}
+
+	dprintk("%s() status 0x%08x\n", __func__, *status);
+
+	return 0;
+}
+
+static int s5h1411_qam256_lookup_snr(struct dvb_frontend *fe, u16 *snr, u16 v)
+{
+	int i, ret = -EINVAL;
+	dprintk("%s()\n", __func__);
+
+	for (i = 0; i < ARRAY_SIZE(qam256_snr_tab); i++) {
+		if (v < qam256_snr_tab[i].val) {
+			*snr = qam256_snr_tab[i].data;
+			ret = 0;
+			break;
+		}
+	}
+	return ret;
+}
+
+static int s5h1411_qam64_lookup_snr(struct dvb_frontend *fe, u16 *snr, u16 v)
+{
+	int i, ret = -EINVAL;
+	dprintk("%s()\n", __func__);
+
+	for (i = 0; i < ARRAY_SIZE(qam64_snr_tab); i++) {
+		if (v < qam64_snr_tab[i].val) {
+			*snr = qam64_snr_tab[i].data;
+			ret = 0;
+			break;
+		}
+	}
+	return ret;
+}
+
+static int s5h1411_vsb_lookup_snr(struct dvb_frontend *fe, u16 *snr, u16 v)
+{
+	int i, ret = -EINVAL;
+	dprintk("%s()\n", __func__);
+
+	for (i = 0; i < ARRAY_SIZE(vsb_snr_tab); i++) {
+		if (v > vsb_snr_tab[i].val) {
+			*snr = vsb_snr_tab[i].data;
+			ret = 0;
+			break;
+		}
+	}
+	dprintk("%s() snr=%d\n", __func__, *snr);
+	return ret;
+}
+
+static int s5h1411_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+	struct s5h1411_state *state = fe->demodulator_priv;
+	u16 reg;
+	dprintk("%s()\n", __func__);
+
+	switch (state->current_modulation) {
+	case QAM_64:
+		reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xf1);
+		return s5h1411_qam64_lookup_snr(fe, snr, reg);
+	case QAM_256:
+		reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xf1);
+		return s5h1411_qam256_lookup_snr(fe, snr, reg);
+	case VSB_8:
+		reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR,
+			0xf2) & 0x3ff;
+		return s5h1411_vsb_lookup_snr(fe, snr, reg);
+	default:
+		break;
+	}
+
+	return -EINVAL;
+}
+
+static int s5h1411_read_signal_strength(struct dvb_frontend *fe,
+	u16 *signal_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%
+	 */
+	u16 snr;
+	u32 tmp;
+	int ret = s5h1411_read_snr(fe, &snr);
+
+	*signal_strength = 0;
+
+	if (0 == ret) {
+		/* The following calculation method was chosen
+		 * purely for the sake of code re-use from the
+		 * other demod drivers that use this method */
+
+		/* Convert from SNR in dB * 10 to 8.24 fixed-point */
+		tmp = (snr * ((1 << 24) / 10));
+
+		/* Convert from 8.24 fixed-point to
+		 * scale the range 0 - 35*2^24 into 0 - 65535*/
+		if (tmp >= 8960 * 0x10000)
+			*signal_strength = 0xffff;
+		else
+			*signal_strength = tmp / 8960;
+	}
+
+	return ret;
+}
+
+static int s5h1411_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+	struct s5h1411_state *state = fe->demodulator_priv;
+
+	*ucblocks = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xc9);
+
+	return 0;
+}
+
+static int s5h1411_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+	return s5h1411_read_ucblocks(fe, ber);
+}
+
+static int s5h1411_get_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct s5h1411_state *state = fe->demodulator_priv;
+
+	p->frequency = state->current_frequency;
+	p->modulation = state->current_modulation;
+
+	return 0;
+}
+
+static int s5h1411_get_tune_settings(struct dvb_frontend *fe,
+				     struct dvb_frontend_tune_settings *tune)
+{
+	tune->min_delay_ms = 1000;
+	return 0;
+}
+
+static void s5h1411_release(struct dvb_frontend *fe)
+{
+	struct s5h1411_state *state = fe->demodulator_priv;
+	kfree(state);
+}
+
+static struct dvb_frontend_ops s5h1411_ops;
+
+struct dvb_frontend *s5h1411_attach(const struct s5h1411_config *config,
+				    struct i2c_adapter *i2c)
+{
+	struct s5h1411_state *state = NULL;
+	u16 reg;
+
+	/* allocate memory for the internal state */
+	state = kzalloc(sizeof(struct s5h1411_state), GFP_KERNEL);
+	if (state == NULL)
+		goto error;
+
+	/* setup the state */
+	state->config = config;
+	state->i2c = i2c;
+	state->current_modulation = VSB_8;
+	state->inversion = state->config->inversion;
+
+	/* check if the demod exists */
+	reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0x05);
+	if (reg != 0x0066)
+		goto error;
+
+	/* create dvb_frontend */
+	memcpy(&state->frontend.ops, &s5h1411_ops,
+	       sizeof(struct dvb_frontend_ops));
+
+	state->frontend.demodulator_priv = state;
+
+	if (s5h1411_init(&state->frontend) != 0) {
+		printk(KERN_ERR "%s: Failed to initialize correctly\n",
+			__func__);
+		goto error;
+	}
+
+	/* Note: Leaving the I2C gate open here. */
+	s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf5, 1);
+
+	/* Put the device into low-power mode until first use */
+	s5h1411_set_powerstate(&state->frontend, 1);
+
+	return &state->frontend;
+
+error:
+	kfree(state);
+	return NULL;
+}
+EXPORT_SYMBOL(s5h1411_attach);
+
+static struct dvb_frontend_ops s5h1411_ops = {
+	.delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
+	.info = {
+		.name			= "Samsung S5H1411 QAM/8VSB Frontend",
+		.frequency_min		= 54000000,
+		.frequency_max		= 858000000,
+		.frequency_stepsize	= 62500,
+		.caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
+	},
+
+	.init                 = s5h1411_init,
+	.sleep                = s5h1411_sleep,
+	.i2c_gate_ctrl        = s5h1411_i2c_gate_ctrl,
+	.set_frontend         = s5h1411_set_frontend,
+	.get_frontend         = s5h1411_get_frontend,
+	.get_tune_settings    = s5h1411_get_tune_settings,
+	.read_status          = s5h1411_read_status,
+	.read_ber             = s5h1411_read_ber,
+	.read_signal_strength = s5h1411_read_signal_strength,
+	.read_snr             = s5h1411_read_snr,
+	.read_ucblocks        = s5h1411_read_ucblocks,
+	.release              = s5h1411_release,
+};
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Enable verbose debug messages");
+
+MODULE_DESCRIPTION("Samsung S5H1411 QAM-B/ATSC Demodulator driver");
+MODULE_AUTHOR("Steven Toth");
+MODULE_LICENSE("GPL");
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ */
diff --git a/drivers/media/dvb-frontends/s5h1411.h b/drivers/media/dvb-frontends/s5h1411.h
new file mode 100644
index 0000000..45ec0f8
--- /dev/null
+++ b/drivers/media/dvb-frontends/s5h1411.h
@@ -0,0 +1,90 @@
+/*
+    Samsung S5H1411 VSB/QAM demodulator driver
+
+    Copyright (C) 2008 Steven Toth <stoth@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 __S5H1411_H__
+#define __S5H1411_H__
+
+#include <linux/dvb/frontend.h>
+
+#define S5H1411_I2C_TOP_ADDR (0x32 >> 1)
+#define S5H1411_I2C_QAM_ADDR (0x34 >> 1)
+
+struct s5h1411_config {
+
+	/* serial/parallel output */
+#define S5H1411_PARALLEL_OUTPUT 0
+#define S5H1411_SERIAL_OUTPUT   1
+	u8 output_mode;
+
+	/* GPIO Setting */
+#define S5H1411_GPIO_OFF 0
+#define S5H1411_GPIO_ON  1
+	u8 gpio;
+
+	/* MPEG signal timing */
+#define S5H1411_MPEGTIMING_CONTINOUS_INVERTING_CLOCK       0
+#define S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK    1
+#define S5H1411_MPEGTIMING_NONCONTINOUS_INVERTING_CLOCK    2
+#define S5H1411_MPEGTIMING_NONCONTINOUS_NONINVERTING_CLOCK 3
+	u16 mpeg_timing;
+
+	/* IF Freq for QAM and VSB in KHz */
+#define S5H1411_IF_3250  3250
+#define S5H1411_IF_3500  3500
+#define S5H1411_IF_4000  4000
+#define S5H1411_IF_5380  5380
+#define S5H1411_IF_44000 44000
+#define S5H1411_VSB_IF_DEFAULT S5H1411_IF_44000
+#define S5H1411_QAM_IF_DEFAULT S5H1411_IF_44000
+	u16 qam_if;
+	u16 vsb_if;
+
+	/* Spectral Inversion */
+#define S5H1411_INVERSION_OFF 0
+#define S5H1411_INVERSION_ON  1
+	u8 inversion;
+
+	/* Return lock status based on tuner lock, or demod lock */
+#define S5H1411_TUNERLOCKING 0
+#define S5H1411_DEMODLOCKING 1
+	u8 status_mode;
+};
+
+#if defined(CONFIG_DVB_S5H1411) || \
+	(defined(CONFIG_DVB_S5H1411_MODULE) && defined(MODULE))
+extern struct dvb_frontend *s5h1411_attach(const struct s5h1411_config *config,
+					   struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend *s5h1411_attach(
+	const struct s5h1411_config *config,
+	struct i2c_adapter *i2c)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif /* CONFIG_DVB_S5H1411 */
+
+#endif /* __S5H1411_H__ */
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ */
diff --git a/drivers/media/dvb-frontends/s5h1420.c b/drivers/media/dvb-frontends/s5h1420.c
new file mode 100644
index 0000000..e2fec9e
--- /dev/null
+++ b/drivers/media/dvb-frontends/s5h1420.c
@@ -0,0 +1,960 @@
+/*
+ * Driver for
+ *    Samsung S5H1420 and
+ *    PnpNetwork PN1010 QPSK Demodulator
+ *
+ * Copyright (C) 2005 Andrew de Quincey <adq_dvb@lidskialf.net>
+ * Copyright (C) 2005-8 Patrick Boettcher <pb@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/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/jiffies.h>
+#include <asm/div64.h>
+
+#include <linux/i2c.h>
+
+
+#include "dvb_frontend.h"
+#include "s5h1420.h"
+#include "s5h1420_priv.h"
+
+#define TONE_FREQ 22000
+
+struct s5h1420_state {
+	struct i2c_adapter* i2c;
+	const struct s5h1420_config* config;
+
+	struct dvb_frontend frontend;
+	struct i2c_adapter tuner_i2c_adapter;
+
+	u8 CON_1_val;
+
+	u8 postlocked:1;
+	u32 fclk;
+	u32 tunedfreq;
+	fe_code_rate_t fec_inner;
+	u32 symbol_rate;
+
+	/* FIXME: ugly workaround for flexcop's incapable i2c-controller
+	 * it does not support repeated-start, workaround: write addr-1
+	 * and then read
+	 */
+	u8 shadow[256];
+};
+
+static u32 s5h1420_getsymbolrate(struct s5h1420_state* state);
+static int s5h1420_get_tune_settings(struct dvb_frontend* fe,
+				     struct dvb_frontend_tune_settings* fesettings);
+
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "enable debugging");
+
+#define dprintk(x...) do { \
+	if (debug) \
+		printk(KERN_DEBUG "S5H1420: " x); \
+} while (0)
+
+static u8 s5h1420_readreg(struct s5h1420_state *state, u8 reg)
+{
+	int ret;
+	u8 b[2];
+	struct i2c_msg msg[] = {
+		{ .addr = state->config->demod_address, .flags = 0, .buf = b, .len = 2 },
+		{ .addr = state->config->demod_address, .flags = 0, .buf = &reg, .len = 1 },
+		{ .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b, .len = 1 },
+	};
+
+	b[0] = (reg - 1) & 0xff;
+	b[1] = state->shadow[(reg - 1) & 0xff];
+
+	if (state->config->repeated_start_workaround) {
+		ret = i2c_transfer(state->i2c, msg, 3);
+		if (ret != 3)
+			return ret;
+	} else {
+		ret = i2c_transfer(state->i2c, &msg[1], 1);
+		if (ret != 1)
+			return ret;
+		ret = i2c_transfer(state->i2c, &msg[2], 1);
+		if (ret != 1)
+			return ret;
+	}
+
+	/* dprintk("rd(%02x): %02x %02x\n", state->config->demod_address, reg, b[0]); */
+
+	return b[0];
+}
+
+static int s5h1420_writereg (struct s5h1420_state* state, u8 reg, u8 data)
+{
+	u8 buf[] = { reg, data };
+	struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 };
+	int err;
+
+	/* dprintk("wr(%02x): %02x %02x\n", state->config->demod_address, reg, data); */
+	err = i2c_transfer(state->i2c, &msg, 1);
+	if (err != 1) {
+		dprintk("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __func__, err, reg, data);
+		return -EREMOTEIO;
+	}
+	state->shadow[reg] = data;
+
+	return 0;
+}
+
+static int s5h1420_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltage)
+{
+	struct s5h1420_state* state = fe->demodulator_priv;
+
+	dprintk("enter %s\n", __func__);
+
+	switch(voltage) {
+	case SEC_VOLTAGE_13:
+		s5h1420_writereg(state, 0x3c,
+				 (s5h1420_readreg(state, 0x3c) & 0xfe) | 0x02);
+		break;
+
+	case SEC_VOLTAGE_18:
+		s5h1420_writereg(state, 0x3c, s5h1420_readreg(state, 0x3c) | 0x03);
+		break;
+
+	case SEC_VOLTAGE_OFF:
+		s5h1420_writereg(state, 0x3c, s5h1420_readreg(state, 0x3c) & 0xfd);
+		break;
+	}
+
+	dprintk("leave %s\n", __func__);
+	return 0;
+}
+
+static int s5h1420_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
+{
+	struct s5h1420_state* state = fe->demodulator_priv;
+
+	dprintk("enter %s\n", __func__);
+	switch(tone) {
+	case SEC_TONE_ON:
+		s5h1420_writereg(state, 0x3b,
+				 (s5h1420_readreg(state, 0x3b) & 0x74) | 0x08);
+		break;
+
+	case SEC_TONE_OFF:
+		s5h1420_writereg(state, 0x3b,
+				 (s5h1420_readreg(state, 0x3b) & 0x74) | 0x01);
+		break;
+	}
+	dprintk("leave %s\n", __func__);
+
+	return 0;
+}
+
+static int s5h1420_send_master_cmd (struct dvb_frontend* fe,
+				    struct dvb_diseqc_master_cmd* cmd)
+{
+	struct s5h1420_state* state = fe->demodulator_priv;
+	u8 val;
+	int i;
+	unsigned long timeout;
+	int result = 0;
+
+	dprintk("enter %s\n", __func__);
+	if (cmd->msg_len > 8)
+		return -EINVAL;
+
+	/* setup for DISEQC */
+	val = s5h1420_readreg(state, 0x3b);
+	s5h1420_writereg(state, 0x3b, 0x02);
+	msleep(15);
+
+	/* write the DISEQC command bytes */
+	for(i=0; i< cmd->msg_len; i++) {
+		s5h1420_writereg(state, 0x3d + i, cmd->msg[i]);
+	}
+
+	/* kick off transmission */
+	s5h1420_writereg(state, 0x3b, s5h1420_readreg(state, 0x3b) |
+				      ((cmd->msg_len-1) << 4) | 0x08);
+
+	/* wait for transmission to complete */
+	timeout = jiffies + ((100*HZ) / 1000);
+	while(time_before(jiffies, timeout)) {
+		if (!(s5h1420_readreg(state, 0x3b) & 0x08))
+			break;
+
+		msleep(5);
+	}
+	if (time_after(jiffies, timeout))
+		result = -ETIMEDOUT;
+
+	/* restore original settings */
+	s5h1420_writereg(state, 0x3b, val);
+	msleep(15);
+	dprintk("leave %s\n", __func__);
+	return result;
+}
+
+static int s5h1420_recv_slave_reply (struct dvb_frontend* fe,
+				     struct dvb_diseqc_slave_reply* reply)
+{
+	struct s5h1420_state* state = fe->demodulator_priv;
+	u8 val;
+	int i;
+	int length;
+	unsigned long timeout;
+	int result = 0;
+
+	/* setup for DISEQC receive */
+	val = s5h1420_readreg(state, 0x3b);
+	s5h1420_writereg(state, 0x3b, 0x82); /* FIXME: guess - do we need to set DIS_RDY(0x08) in receive mode? */
+	msleep(15);
+
+	/* wait for reception to complete */
+	timeout = jiffies + ((reply->timeout*HZ) / 1000);
+	while(time_before(jiffies, timeout)) {
+		if (!(s5h1420_readreg(state, 0x3b) & 0x80)) /* FIXME: do we test DIS_RDY(0x08) or RCV_EN(0x80)? */
+			break;
+
+		msleep(5);
+	}
+	if (time_after(jiffies, timeout)) {
+		result = -ETIMEDOUT;
+		goto exit;
+	}
+
+	/* check error flag - FIXME: not sure what this does - docs do not describe
+	 * beyond "error flag for diseqc receive data :( */
+	if (s5h1420_readreg(state, 0x49)) {
+		result = -EIO;
+		goto exit;
+	}
+
+	/* check length */
+	length = (s5h1420_readreg(state, 0x3b) & 0x70) >> 4;
+	if (length > sizeof(reply->msg)) {
+		result = -EOVERFLOW;
+		goto exit;
+	}
+	reply->msg_len = length;
+
+	/* extract data */
+	for(i=0; i< length; i++) {
+		reply->msg[i] = s5h1420_readreg(state, 0x3d + i);
+	}
+
+exit:
+	/* restore original settings */
+	s5h1420_writereg(state, 0x3b, val);
+	msleep(15);
+	return result;
+}
+
+static int s5h1420_send_burst (struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd)
+{
+	struct s5h1420_state* state = fe->demodulator_priv;
+	u8 val;
+	int result = 0;
+	unsigned long timeout;
+
+	/* setup for tone burst */
+	val = s5h1420_readreg(state, 0x3b);
+	s5h1420_writereg(state, 0x3b, (s5h1420_readreg(state, 0x3b) & 0x70) | 0x01);
+
+	/* set value for B position if requested */
+	if (minicmd == SEC_MINI_B) {
+		s5h1420_writereg(state, 0x3b, s5h1420_readreg(state, 0x3b) | 0x04);
+	}
+	msleep(15);
+
+	/* start transmission */
+	s5h1420_writereg(state, 0x3b, s5h1420_readreg(state, 0x3b) | 0x08);
+
+	/* wait for transmission to complete */
+	timeout = jiffies + ((100*HZ) / 1000);
+	while(time_before(jiffies, timeout)) {
+		if (!(s5h1420_readreg(state, 0x3b) & 0x08))
+			break;
+
+		msleep(5);
+	}
+	if (time_after(jiffies, timeout))
+		result = -ETIMEDOUT;
+
+	/* restore original settings */
+	s5h1420_writereg(state, 0x3b, val);
+	msleep(15);
+	return result;
+}
+
+static fe_status_t s5h1420_get_status_bits(struct s5h1420_state* state)
+{
+	u8 val;
+	fe_status_t status = 0;
+
+	val = s5h1420_readreg(state, 0x14);
+	if (val & 0x02)
+		status |=  FE_HAS_SIGNAL;
+	if (val & 0x01)
+		status |=  FE_HAS_CARRIER;
+	val = s5h1420_readreg(state, 0x36);
+	if (val & 0x01)
+		status |=  FE_HAS_VITERBI;
+	if (val & 0x20)
+		status |=  FE_HAS_SYNC;
+	if (status == (FE_HAS_SIGNAL|FE_HAS_CARRIER|FE_HAS_VITERBI|FE_HAS_SYNC))
+		status |=  FE_HAS_LOCK;
+
+	return status;
+}
+
+static int s5h1420_read_status(struct dvb_frontend* fe, fe_status_t* status)
+{
+	struct s5h1420_state* state = fe->demodulator_priv;
+	u8 val;
+
+	dprintk("enter %s\n", __func__);
+
+	if (status == NULL)
+		return -EINVAL;
+
+	/* determine lock state */
+	*status = s5h1420_get_status_bits(state);
+
+	/* fix for FEC 5/6 inversion issue - if it doesn't quite lock, invert
+	the inversion, wait a bit and check again */
+	if (*status == (FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI)) {
+		val = s5h1420_readreg(state, Vit10);
+		if ((val & 0x07) == 0x03) {
+			if (val & 0x08)
+				s5h1420_writereg(state, Vit09, 0x13);
+			else
+				s5h1420_writereg(state, Vit09, 0x1b);
+
+			/* wait a bit then update lock status */
+			mdelay(200);
+			*status = s5h1420_get_status_bits(state);
+		}
+	}
+
+	/* perform post lock setup */
+	if ((*status & FE_HAS_LOCK) && !state->postlocked) {
+
+		/* calculate the data rate */
+		u32 tmp = s5h1420_getsymbolrate(state);
+		switch (s5h1420_readreg(state, Vit10) & 0x07) {
+		case 0: tmp = (tmp * 2 * 1) / 2; break;
+		case 1: tmp = (tmp * 2 * 2) / 3; break;
+		case 2: tmp = (tmp * 2 * 3) / 4; break;
+		case 3: tmp = (tmp * 2 * 5) / 6; break;
+		case 4: tmp = (tmp * 2 * 6) / 7; break;
+		case 5: tmp = (tmp * 2 * 7) / 8; break;
+		}
+
+		if (tmp == 0) {
+			printk(KERN_ERR "s5h1420: avoided division by 0\n");
+			tmp = 1;
+		}
+		tmp = state->fclk / tmp;
+
+
+		/* set the MPEG_CLK_INTL for the calculated data rate */
+		if (tmp < 2)
+			val = 0x00;
+		else if (tmp < 5)
+			val = 0x01;
+		else if (tmp < 9)
+			val = 0x02;
+		else if (tmp < 13)
+			val = 0x03;
+		else if (tmp < 17)
+			val = 0x04;
+		else if (tmp < 25)
+			val = 0x05;
+		else if (tmp < 33)
+			val = 0x06;
+		else
+			val = 0x07;
+		dprintk("for MPEG_CLK_INTL %d %x\n", tmp, val);
+
+		s5h1420_writereg(state, FEC01, 0x18);
+		s5h1420_writereg(state, FEC01, 0x10);
+		s5h1420_writereg(state, FEC01, val);
+
+		/* Enable "MPEG_Out" */
+		val = s5h1420_readreg(state, Mpeg02);
+		s5h1420_writereg(state, Mpeg02, val | (1 << 6));
+
+		/* kicker disable */
+		val = s5h1420_readreg(state, QPSK01) & 0x7f;
+		s5h1420_writereg(state, QPSK01, val);
+
+		/* DC freeze TODO it was never activated by default or it can stay activated */
+
+		if (s5h1420_getsymbolrate(state) >= 20000000) {
+			s5h1420_writereg(state, Loop04, 0x8a);
+			s5h1420_writereg(state, Loop05, 0x6a);
+		} else {
+			s5h1420_writereg(state, Loop04, 0x58);
+			s5h1420_writereg(state, Loop05, 0x27);
+		}
+
+		/* post-lock processing has been done! */
+		state->postlocked = 1;
+	}
+
+	dprintk("leave %s\n", __func__);
+
+	return 0;
+}
+
+static int s5h1420_read_ber(struct dvb_frontend* fe, u32* ber)
+{
+	struct s5h1420_state* state = fe->demodulator_priv;
+
+	s5h1420_writereg(state, 0x46, 0x1d);
+	mdelay(25);
+
+	*ber = (s5h1420_readreg(state, 0x48) << 8) | s5h1420_readreg(state, 0x47);
+
+	return 0;
+}
+
+static int s5h1420_read_signal_strength(struct dvb_frontend* fe, u16* strength)
+{
+	struct s5h1420_state* state = fe->demodulator_priv;
+
+	u8 val = s5h1420_readreg(state, 0x15);
+
+	*strength =  (u16) ((val << 8) | val);
+
+	return 0;
+}
+
+static int s5h1420_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
+{
+	struct s5h1420_state* state = fe->demodulator_priv;
+
+	s5h1420_writereg(state, 0x46, 0x1f);
+	mdelay(25);
+
+	*ucblocks = (s5h1420_readreg(state, 0x48) << 8) | s5h1420_readreg(state, 0x47);
+
+	return 0;
+}
+
+static void s5h1420_reset(struct s5h1420_state* state)
+{
+	dprintk("%s\n", __func__);
+	s5h1420_writereg (state, 0x01, 0x08);
+	s5h1420_writereg (state, 0x01, 0x00);
+	udelay(10);
+}
+
+static void s5h1420_setsymbolrate(struct s5h1420_state* state,
+				  struct dtv_frontend_properties *p)
+{
+	u8 v;
+	u64 val;
+
+	dprintk("enter %s\n", __func__);
+
+	val = ((u64) p->symbol_rate / 1000ULL) * (1ULL<<24);
+	if (p->symbol_rate < 29000000)
+		val *= 2;
+	do_div(val, (state->fclk / 1000));
+
+	dprintk("symbol rate register: %06llx\n", (unsigned long long)val);
+
+	v = s5h1420_readreg(state, Loop01);
+	s5h1420_writereg(state, Loop01, v & 0x7f);
+	s5h1420_writereg(state, Tnco01, val >> 16);
+	s5h1420_writereg(state, Tnco02, val >> 8);
+	s5h1420_writereg(state, Tnco03, val & 0xff);
+	s5h1420_writereg(state, Loop01,  v | 0x80);
+	dprintk("leave %s\n", __func__);
+}
+
+static u32 s5h1420_getsymbolrate(struct s5h1420_state* state)
+{
+	return state->symbol_rate;
+}
+
+static void s5h1420_setfreqoffset(struct s5h1420_state* state, int freqoffset)
+{
+	int val;
+	u8 v;
+
+	dprintk("enter %s\n", __func__);
+
+	/* remember freqoffset is in kHz, but the chip wants the offset in Hz, so
+	 * divide fclk by 1000000 to get the correct value. */
+	val = -(int) ((freqoffset * (1<<24)) / (state->fclk / 1000000));
+
+	dprintk("phase rotator/freqoffset: %d %06x\n", freqoffset, val);
+
+	v = s5h1420_readreg(state, Loop01);
+	s5h1420_writereg(state, Loop01, v & 0xbf);
+	s5h1420_writereg(state, Pnco01, val >> 16);
+	s5h1420_writereg(state, Pnco02, val >> 8);
+	s5h1420_writereg(state, Pnco03, val & 0xff);
+	s5h1420_writereg(state, Loop01, v | 0x40);
+	dprintk("leave %s\n", __func__);
+}
+
+static int s5h1420_getfreqoffset(struct s5h1420_state* state)
+{
+	int val;
+
+	s5h1420_writereg(state, 0x06, s5h1420_readreg(state, 0x06) | 0x08);
+	val  = s5h1420_readreg(state, 0x0e) << 16;
+	val |= s5h1420_readreg(state, 0x0f) << 8;
+	val |= s5h1420_readreg(state, 0x10);
+	s5h1420_writereg(state, 0x06, s5h1420_readreg(state, 0x06) & 0xf7);
+
+	if (val & 0x800000)
+		val |= 0xff000000;
+
+	/* remember freqoffset is in kHz, but the chip wants the offset in Hz, so
+	 * divide fclk by 1000000 to get the correct value. */
+	val = (((-val) * (state->fclk/1000000)) / (1<<24));
+
+	return val;
+}
+
+static void s5h1420_setfec_inversion(struct s5h1420_state* state,
+				     struct dtv_frontend_properties *p)
+{
+	u8 inversion = 0;
+	u8 vit08, vit09;
+
+	dprintk("enter %s\n", __func__);
+
+	if (p->inversion == INVERSION_OFF)
+		inversion = state->config->invert ? 0x08 : 0;
+	else if (p->inversion == INVERSION_ON)
+		inversion = state->config->invert ? 0 : 0x08;
+
+	if ((p->fec_inner == FEC_AUTO) || (p->inversion == INVERSION_AUTO)) {
+		vit08 = 0x3f;
+		vit09 = 0;
+	} else {
+		switch (p->fec_inner) {
+		case FEC_1_2:
+			vit08 = 0x01; vit09 = 0x10;
+			break;
+
+		case FEC_2_3:
+			vit08 = 0x02; vit09 = 0x11;
+			break;
+
+		case FEC_3_4:
+			vit08 = 0x04; vit09 = 0x12;
+			break;
+
+		case FEC_5_6:
+			vit08 = 0x08; vit09 = 0x13;
+			break;
+
+		case FEC_6_7:
+			vit08 = 0x10; vit09 = 0x14;
+			break;
+
+		case FEC_7_8:
+			vit08 = 0x20; vit09 = 0x15;
+			break;
+
+		default:
+			return;
+		}
+	}
+	vit09 |= inversion;
+	dprintk("fec: %02x %02x\n", vit08, vit09);
+	s5h1420_writereg(state, Vit08, vit08);
+	s5h1420_writereg(state, Vit09, vit09);
+	dprintk("leave %s\n", __func__);
+}
+
+static fe_code_rate_t s5h1420_getfec(struct s5h1420_state* state)
+{
+	switch(s5h1420_readreg(state, 0x32) & 0x07) {
+	case 0:
+		return FEC_1_2;
+
+	case 1:
+		return FEC_2_3;
+
+	case 2:
+		return FEC_3_4;
+
+	case 3:
+		return FEC_5_6;
+
+	case 4:
+		return FEC_6_7;
+
+	case 5:
+		return FEC_7_8;
+	}
+
+	return FEC_NONE;
+}
+
+static fe_spectral_inversion_t s5h1420_getinversion(struct s5h1420_state* state)
+{
+	if (s5h1420_readreg(state, 0x32) & 0x08)
+		return INVERSION_ON;
+
+	return INVERSION_OFF;
+}
+
+static int s5h1420_set_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct s5h1420_state* state = fe->demodulator_priv;
+	int frequency_delta;
+	struct dvb_frontend_tune_settings fesettings;
+
+	dprintk("enter %s\n", __func__);
+
+	/* check if we should do a fast-tune */
+	s5h1420_get_tune_settings(fe, &fesettings);
+	frequency_delta = p->frequency - state->tunedfreq;
+	if ((frequency_delta > -fesettings.max_drift) &&
+			(frequency_delta < fesettings.max_drift) &&
+			(frequency_delta != 0) &&
+			(state->fec_inner == p->fec_inner) &&
+			(state->symbol_rate == p->symbol_rate)) {
+
+		if (fe->ops.tuner_ops.set_params) {
+			fe->ops.tuner_ops.set_params(fe);
+			if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+		}
+		if (fe->ops.tuner_ops.get_frequency) {
+			u32 tmp;
+			fe->ops.tuner_ops.get_frequency(fe, &tmp);
+			if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+			s5h1420_setfreqoffset(state, p->frequency - tmp);
+		} else {
+			s5h1420_setfreqoffset(state, 0);
+		}
+		dprintk("simple tune\n");
+		return 0;
+	}
+	dprintk("tuning demod\n");
+
+	/* first of all, software reset */
+	s5h1420_reset(state);
+
+	/* set s5h1420 fclk PLL according to desired symbol rate */
+	if (p->symbol_rate > 33000000)
+		state->fclk = 80000000;
+	else if (p->symbol_rate > 28500000)
+		state->fclk = 59000000;
+	else if (p->symbol_rate > 25000000)
+		state->fclk = 86000000;
+	else if (p->symbol_rate > 1900000)
+		state->fclk = 88000000;
+	else
+		state->fclk = 44000000;
+
+	dprintk("pll01: %d, ToneFreq: %d\n", state->fclk/1000000 - 8, (state->fclk + (TONE_FREQ * 32) - 1) / (TONE_FREQ * 32));
+	s5h1420_writereg(state, PLL01, state->fclk/1000000 - 8);
+	s5h1420_writereg(state, PLL02, 0x40);
+	s5h1420_writereg(state, DiS01, (state->fclk + (TONE_FREQ * 32) - 1) / (TONE_FREQ * 32));
+
+	/* TODO DC offset removal, config parameter ? */
+	if (p->symbol_rate > 29000000)
+		s5h1420_writereg(state, QPSK01, 0xae | 0x10);
+	else
+		s5h1420_writereg(state, QPSK01, 0xac | 0x10);
+
+	/* set misc registers */
+	s5h1420_writereg(state, CON_1, 0x00);
+	s5h1420_writereg(state, QPSK02, 0x00);
+	s5h1420_writereg(state, Pre01, 0xb0);
+
+	s5h1420_writereg(state, Loop01, 0xF0);
+	s5h1420_writereg(state, Loop02, 0x2a); /* e7 for s5h1420 */
+	s5h1420_writereg(state, Loop03, 0x79); /* 78 for s5h1420 */
+	if (p->symbol_rate > 20000000)
+		s5h1420_writereg(state, Loop04, 0x79);
+	else
+		s5h1420_writereg(state, Loop04, 0x58);
+	s5h1420_writereg(state, Loop05, 0x6b);
+
+	if (p->symbol_rate >= 8000000)
+		s5h1420_writereg(state, Post01, (0 << 6) | 0x10);
+	else if (p->symbol_rate >= 4000000)
+		s5h1420_writereg(state, Post01, (1 << 6) | 0x10);
+	else
+		s5h1420_writereg(state, Post01, (3 << 6) | 0x10);
+
+	s5h1420_writereg(state, Monitor12, 0x00); /* unfreeze DC compensation */
+
+	s5h1420_writereg(state, Sync01, 0x33);
+	s5h1420_writereg(state, Mpeg01, state->config->cdclk_polarity);
+	s5h1420_writereg(state, Mpeg02, 0x3d); /* Parallel output more, disabled -> enabled later */
+	s5h1420_writereg(state, Err01, 0x03); /* 0x1d for s5h1420 */
+
+	s5h1420_writereg(state, Vit06, 0x6e); /* 0x8e for s5h1420 */
+	s5h1420_writereg(state, DiS03, 0x00);
+	s5h1420_writereg(state, Rf01, 0x61); /* Tuner i2c address - for the gate controller */
+
+	/* set tuner PLL */
+	if (fe->ops.tuner_ops.set_params) {
+		fe->ops.tuner_ops.set_params(fe);
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 0);
+		s5h1420_setfreqoffset(state, 0);
+	}
+
+	/* set the reset of the parameters */
+	s5h1420_setsymbolrate(state, p);
+	s5h1420_setfec_inversion(state, p);
+
+	/* start QPSK */
+	s5h1420_writereg(state, QPSK01, s5h1420_readreg(state, QPSK01) | 1);
+
+	state->fec_inner = p->fec_inner;
+	state->symbol_rate = p->symbol_rate;
+	state->postlocked = 0;
+	state->tunedfreq = p->frequency;
+
+	dprintk("leave %s\n", __func__);
+	return 0;
+}
+
+static int s5h1420_get_frontend(struct dvb_frontend* fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct s5h1420_state* state = fe->demodulator_priv;
+
+	p->frequency = state->tunedfreq + s5h1420_getfreqoffset(state);
+	p->inversion = s5h1420_getinversion(state);
+	p->symbol_rate = s5h1420_getsymbolrate(state);
+	p->fec_inner = s5h1420_getfec(state);
+
+	return 0;
+}
+
+static int s5h1420_get_tune_settings(struct dvb_frontend* fe,
+				     struct dvb_frontend_tune_settings* fesettings)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	if (p->symbol_rate > 20000000) {
+		fesettings->min_delay_ms = 50;
+		fesettings->step_size = 2000;
+		fesettings->max_drift = 8000;
+	} else if (p->symbol_rate > 12000000) {
+		fesettings->min_delay_ms = 100;
+		fesettings->step_size = 1500;
+		fesettings->max_drift = 9000;
+	} else if (p->symbol_rate > 8000000) {
+		fesettings->min_delay_ms = 100;
+		fesettings->step_size = 1000;
+		fesettings->max_drift = 8000;
+	} else if (p->symbol_rate > 4000000) {
+		fesettings->min_delay_ms = 100;
+		fesettings->step_size = 500;
+		fesettings->max_drift = 7000;
+	} else if (p->symbol_rate > 2000000) {
+		fesettings->min_delay_ms = 200;
+		fesettings->step_size = (p->symbol_rate / 8000);
+		fesettings->max_drift = 14 * fesettings->step_size;
+	} else {
+		fesettings->min_delay_ms = 200;
+		fesettings->step_size = (p->symbol_rate / 8000);
+		fesettings->max_drift = 18 * fesettings->step_size;
+	}
+
+	return 0;
+}
+
+static int s5h1420_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+{
+	struct s5h1420_state* state = fe->demodulator_priv;
+
+	if (enable)
+		return s5h1420_writereg(state, 0x02, state->CON_1_val | 1);
+	else
+		return s5h1420_writereg(state, 0x02, state->CON_1_val & 0xfe);
+}
+
+static int s5h1420_init (struct dvb_frontend* fe)
+{
+	struct s5h1420_state* state = fe->demodulator_priv;
+
+	/* disable power down and do reset */
+	state->CON_1_val = state->config->serial_mpeg << 4;
+	s5h1420_writereg(state, 0x02, state->CON_1_val);
+	msleep(10);
+	s5h1420_reset(state);
+
+	return 0;
+}
+
+static int s5h1420_sleep(struct dvb_frontend* fe)
+{
+	struct s5h1420_state* state = fe->demodulator_priv;
+	state->CON_1_val = 0x12;
+	return s5h1420_writereg(state, 0x02, state->CON_1_val);
+}
+
+static void s5h1420_release(struct dvb_frontend* fe)
+{
+	struct s5h1420_state* state = fe->demodulator_priv;
+	i2c_del_adapter(&state->tuner_i2c_adapter);
+	kfree(state);
+}
+
+static u32 s5h1420_tuner_i2c_func(struct i2c_adapter *adapter)
+{
+	return I2C_FUNC_I2C;
+}
+
+static int s5h1420_tuner_i2c_tuner_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)
+{
+	struct s5h1420_state *state = i2c_get_adapdata(i2c_adap);
+	struct i2c_msg m[1 + num];
+	u8 tx_open[2] = { CON_1, state->CON_1_val | 1 }; /* repeater stops once there was a stop condition */
+
+	memset(m, 0, sizeof(struct i2c_msg) * (1 + num));
+
+	m[0].addr = state->config->demod_address;
+	m[0].buf  = tx_open;
+	m[0].len  = 2;
+
+	memcpy(&m[1], msg, sizeof(struct i2c_msg) * num);
+
+	return i2c_transfer(state->i2c, m, 1+num) == 1 + num ? num : -EIO;
+}
+
+static struct i2c_algorithm s5h1420_tuner_i2c_algo = {
+	.master_xfer   = s5h1420_tuner_i2c_tuner_xfer,
+	.functionality = s5h1420_tuner_i2c_func,
+};
+
+struct i2c_adapter *s5h1420_get_tuner_i2c_adapter(struct dvb_frontend *fe)
+{
+	struct s5h1420_state *state = fe->demodulator_priv;
+	return &state->tuner_i2c_adapter;
+}
+EXPORT_SYMBOL(s5h1420_get_tuner_i2c_adapter);
+
+static struct dvb_frontend_ops s5h1420_ops;
+
+struct dvb_frontend *s5h1420_attach(const struct s5h1420_config *config,
+				    struct i2c_adapter *i2c)
+{
+	/* allocate memory for the internal state */
+	struct s5h1420_state *state = kzalloc(sizeof(struct s5h1420_state), GFP_KERNEL);
+	u8 i;
+
+	if (state == NULL)
+		goto error;
+
+	/* setup the state */
+	state->config = config;
+	state->i2c = i2c;
+	state->postlocked = 0;
+	state->fclk = 88000000;
+	state->tunedfreq = 0;
+	state->fec_inner = FEC_NONE;
+	state->symbol_rate = 0;
+
+	/* check if the demod is there + identify it */
+	i = s5h1420_readreg(state, ID01);
+	if (i != 0x03)
+		goto error;
+
+	memset(state->shadow, 0xff, sizeof(state->shadow));
+
+	for (i = 0; i < 0x50; i++)
+		state->shadow[i] = s5h1420_readreg(state, i);
+
+	/* create dvb_frontend */
+	memcpy(&state->frontend.ops, &s5h1420_ops, sizeof(struct dvb_frontend_ops));
+	state->frontend.demodulator_priv = state;
+
+	/* create tuner i2c adapter */
+	strlcpy(state->tuner_i2c_adapter.name, "S5H1420-PN1010 tuner I2C bus",
+		sizeof(state->tuner_i2c_adapter.name));
+	state->tuner_i2c_adapter.algo      = &s5h1420_tuner_i2c_algo;
+	state->tuner_i2c_adapter.algo_data = NULL;
+	i2c_set_adapdata(&state->tuner_i2c_adapter, state);
+	if (i2c_add_adapter(&state->tuner_i2c_adapter) < 0) {
+		printk(KERN_ERR "S5H1420/PN1010: tuner i2c bus could not be initialized\n");
+		goto error;
+	}
+
+	return &state->frontend;
+
+error:
+	kfree(state);
+	return NULL;
+}
+EXPORT_SYMBOL(s5h1420_attach);
+
+static struct dvb_frontend_ops s5h1420_ops = {
+	.delsys = { SYS_DVBS },
+	.info = {
+		.name     = "Samsung S5H1420/PnpNetwork PN1010 DVB-S",
+		.frequency_min    = 950000,
+		.frequency_max    = 2150000,
+		.frequency_stepsize = 125,     /* kHz for QPSK frontends */
+		.frequency_tolerance  = 29500,
+		.symbol_rate_min  = 1000000,
+		.symbol_rate_max  = 45000000,
+		/*  .symbol_rate_tolerance  = ???,*/
+		.caps = FE_CAN_INVERSION_AUTO |
+		FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
+		FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
+		FE_CAN_QPSK
+	},
+
+	.release = s5h1420_release,
+
+	.init = s5h1420_init,
+	.sleep = s5h1420_sleep,
+	.i2c_gate_ctrl = s5h1420_i2c_gate_ctrl,
+
+	.set_frontend = s5h1420_set_frontend,
+	.get_frontend = s5h1420_get_frontend,
+	.get_tune_settings = s5h1420_get_tune_settings,
+
+	.read_status = s5h1420_read_status,
+	.read_ber = s5h1420_read_ber,
+	.read_signal_strength = s5h1420_read_signal_strength,
+	.read_ucblocks = s5h1420_read_ucblocks,
+
+	.diseqc_send_master_cmd = s5h1420_send_master_cmd,
+	.diseqc_recv_slave_reply = s5h1420_recv_slave_reply,
+	.diseqc_send_burst = s5h1420_send_burst,
+	.set_tone = s5h1420_set_tone,
+	.set_voltage = s5h1420_set_voltage,
+};
+
+MODULE_DESCRIPTION("Samsung S5H1420/PnpNetwork PN1010 DVB-S Demodulator driver");
+MODULE_AUTHOR("Andrew de Quincey, Patrick Boettcher");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb-frontends/s5h1420.h b/drivers/media/dvb-frontends/s5h1420.h
new file mode 100644
index 0000000..ff30813
--- /dev/null
+++ b/drivers/media/dvb-frontends/s5h1420.h
@@ -0,0 +1,61 @@
+/*
+ * Driver for
+ *    Samsung S5H1420 and
+ *    PnpNetwork PN1010 QPSK Demodulator
+ *
+ * Copyright (C) 2005 Andrew de Quincey <adq_dvb@lidskialf.net>
+ * Copyright (C) 2005-8 Patrick Boettcher <pb@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 S5H1420_H
+#define S5H1420_H
+
+#include <linux/dvb/frontend.h>
+
+struct s5h1420_config
+{
+	/* the demodulator's i2c address */
+	u8 demod_address;
+
+	/* does the inversion require inversion? */
+	u8 invert:1;
+
+	u8 repeated_start_workaround:1;
+	u8 cdclk_polarity:1; /* 1 == falling edge, 0 == raising edge */
+
+	u8 serial_mpeg:1;
+};
+
+#if defined(CONFIG_DVB_S5H1420) || (defined(CONFIG_DVB_S5H1420_MODULE) && defined(MODULE))
+extern struct dvb_frontend *s5h1420_attach(const struct s5h1420_config *config,
+	     struct i2c_adapter *i2c);
+extern struct i2c_adapter *s5h1420_get_tuner_i2c_adapter(struct dvb_frontend *fe);
+#else
+static inline struct dvb_frontend *s5h1420_attach(const struct s5h1420_config *config,
+					   struct i2c_adapter *i2c)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+
+static inline struct i2c_adapter *s5h1420_get_tuner_i2c_adapter(struct dvb_frontend *fe)
+{
+	return NULL;
+}
+#endif // CONFIG_DVB_S5H1420
+
+#endif // S5H1420_H
diff --git a/drivers/media/dvb-frontends/s5h1420_priv.h b/drivers/media/dvb-frontends/s5h1420_priv.h
new file mode 100644
index 0000000..d9c58d2
--- /dev/null
+++ b/drivers/media/dvb-frontends/s5h1420_priv.h
@@ -0,0 +1,102 @@
+/*
+ * Driver for
+ *    Samsung S5H1420 and
+ *    PnpNetwork PN1010 QPSK Demodulator
+ *
+ * Copyright (C) 2005 Andrew de Quincey <adq_dvb@lidskialf.net>
+ * Copyright (C) 2005 Patrick Boettcher <pb@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 S5H1420_PRIV
+#define S5H1420_PRIV
+
+#include <asm/types.h>
+
+enum s5h1420_register {
+	ID01      = 0x00,
+	CON_0     = 0x01,
+	CON_1     = 0x02,
+	PLL01     = 0x03,
+	PLL02     = 0x04,
+	QPSK01    = 0x05,
+	QPSK02    = 0x06,
+	Pre01     = 0x07,
+	Post01    = 0x08,
+	Loop01    = 0x09,
+	Loop02    = 0x0a,
+	Loop03    = 0x0b,
+	Loop04    = 0x0c,
+	Loop05    = 0x0d,
+	Pnco01    = 0x0e,
+	Pnco02    = 0x0f,
+	Pnco03    = 0x10,
+	Tnco01    = 0x11,
+	Tnco02    = 0x12,
+	Tnco03    = 0x13,
+	Monitor01 = 0x14,
+	Monitor02 = 0x15,
+	Monitor03 = 0x16,
+	Monitor04 = 0x17,
+	Monitor05 = 0x18,
+	Monitor06 = 0x19,
+	Monitor07 = 0x1a,
+	Monitor12 = 0x1f,
+
+	FEC01     = 0x22,
+	Soft01    = 0x23,
+	Soft02    = 0x24,
+	Soft03    = 0x25,
+	Soft04    = 0x26,
+	Soft05    = 0x27,
+	Soft06    = 0x28,
+	Vit01     = 0x29,
+	Vit02     = 0x2a,
+	Vit03     = 0x2b,
+	Vit04     = 0x2c,
+	Vit05     = 0x2d,
+	Vit06     = 0x2e,
+	Vit07     = 0x2f,
+	Vit08     = 0x30,
+	Vit09     = 0x31,
+	Vit10     = 0x32,
+	Vit11     = 0x33,
+	Vit12     = 0x34,
+	Sync01    = 0x35,
+	Sync02    = 0x36,
+	Rs01      = 0x37,
+	Mpeg01    = 0x38,
+	Mpeg02    = 0x39,
+	DiS01     = 0x3a,
+	DiS02     = 0x3b,
+	DiS03     = 0x3c,
+	DiS04     = 0x3d,
+	DiS05     = 0x3e,
+	DiS06     = 0x3f,
+	DiS07     = 0x40,
+	DiS08     = 0x41,
+	DiS09     = 0x42,
+	DiS10     = 0x43,
+	DiS11     = 0x44,
+	Rf01      = 0x45,
+	Err01     = 0x46,
+	Err02     = 0x47,
+	Err03     = 0x48,
+	Err04     = 0x49,
+};
+
+
+#endif
diff --git a/drivers/media/dvb-frontends/s5h1432.c b/drivers/media/dvb-frontends/s5h1432.c
new file mode 100644
index 0000000..8352ce1
--- /dev/null
+++ b/drivers/media/dvb-frontends/s5h1432.c
@@ -0,0 +1,407 @@
+/*
+ *  Samsung s5h1432 DVB-T demodulator driver
+ *
+ *  Copyright (C) 2009 Bill Liu <Bill.Liu@Conexant.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include "dvb_frontend.h"
+#include "s5h1432.h"
+
+struct s5h1432_state {
+
+	struct i2c_adapter *i2c;
+
+	/* configuration settings */
+	const struct s5h1432_config *config;
+
+	struct dvb_frontend frontend;
+
+	fe_modulation_t current_modulation;
+	unsigned int first_tune:1;
+
+	u32 current_frequency;
+	int if_freq;
+
+	u8 inversion;
+};
+
+static int debug;
+
+#define dprintk(arg...) do {	\
+	if (debug)		\
+		printk(arg);	\
+	} while (0)
+
+static int s5h1432_writereg(struct s5h1432_state *state,
+			    u8 addr, u8 reg, u8 data)
+{
+	int ret;
+	u8 buf[] = { reg, data };
+
+	struct i2c_msg msg = {.addr = addr, .flags = 0, .buf = buf, .len = 2 };
+
+	ret = i2c_transfer(state->i2c, &msg, 1);
+
+	if (ret != 1)
+		printk(KERN_ERR "%s: writereg error 0x%02x 0x%02x 0x%04x, "
+		       "ret == %i)\n", __func__, addr, reg, data, ret);
+
+	return (ret != 1) ? -1 : 0;
+}
+
+static u8 s5h1432_readreg(struct s5h1432_state *state, u8 addr, u8 reg)
+{
+	int ret;
+	u8 b0[] = { reg };
+	u8 b1[] = { 0 };
+
+	struct i2c_msg msg[] = {
+		{.addr = addr, .flags = 0, .buf = b0, .len = 1},
+		{.addr = addr, .flags = I2C_M_RD, .buf = b1, .len = 1}
+	};
+
+	ret = i2c_transfer(state->i2c, msg, 2);
+
+	if (ret != 2)
+		printk(KERN_ERR "%s: readreg error (ret == %i)\n",
+		       __func__, ret);
+	return b1[0];
+}
+
+static int s5h1432_sleep(struct dvb_frontend *fe)
+{
+	return 0;
+}
+
+static int s5h1432_set_channel_bandwidth(struct dvb_frontend *fe,
+					 u32 bandwidth)
+{
+	struct s5h1432_state *state = fe->demodulator_priv;
+
+	u8 reg = 0;
+
+	/* Register [0x2E] bit 3:2 : 8MHz = 0; 7MHz = 1; 6MHz = 2 */
+	reg = s5h1432_readreg(state, S5H1432_I2C_TOP_ADDR, 0x2E);
+	reg &= ~(0x0C);
+	switch (bandwidth) {
+	case 6:
+		reg |= 0x08;
+		break;
+	case 7:
+		reg |= 0x04;
+		break;
+	case 8:
+		reg |= 0x00;
+		break;
+	default:
+		return 0;
+	}
+	s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x2E, reg);
+	return 1;
+}
+
+static int s5h1432_set_IF(struct dvb_frontend *fe, u32 ifFreqHz)
+{
+	struct s5h1432_state *state = fe->demodulator_priv;
+
+	switch (ifFreqHz) {
+	case TAIWAN_HI_IF_FREQ_44_MHZ:
+		s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe4, 0x55);
+		s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe5, 0x55);
+		s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe7, 0x15);
+		break;
+	case EUROPE_HI_IF_FREQ_36_MHZ:
+		s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe4, 0x00);
+		s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe5, 0x00);
+		s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe7, 0x40);
+		break;
+	case IF_FREQ_6_MHZ:
+		s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe4, 0x00);
+		s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe5, 0x00);
+		s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe7, 0xe0);
+		break;
+	case IF_FREQ_3point3_MHZ:
+		s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe4, 0x66);
+		s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe5, 0x66);
+		s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe7, 0xEE);
+		break;
+	case IF_FREQ_3point5_MHZ:
+		s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe4, 0x55);
+		s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe5, 0x55);
+		s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe7, 0xED);
+		break;
+	case IF_FREQ_4_MHZ:
+		s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe4, 0xAA);
+		s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe5, 0xAA);
+		s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe7, 0xEA);
+		break;
+	default:
+		{
+			u32 value = 0;
+			value = (u32) (((48000 - (ifFreqHz / 1000)) * 512 *
+					(u32) 32768) / (48 * 1000));
+			printk(KERN_INFO
+			       "Default IFFreq %d :reg value = 0x%x\n",
+			       ifFreqHz, value);
+			s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe4,
+					 (u8) value & 0xFF);
+			s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe5,
+					 (u8) (value >> 8) & 0xFF);
+			s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe7,
+					 (u8) (value >> 16) & 0xFF);
+			break;
+		}
+
+	}
+
+	return 1;
+}
+
+/* Talk to the demod, set the FEC, GUARD, QAM settings etc */
+static int s5h1432_set_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	u32 dvb_bandwidth = 8;
+	struct s5h1432_state *state = fe->demodulator_priv;
+
+	if (p->frequency == state->current_frequency) {
+		/*current_frequency = p->frequency; */
+		/*state->current_frequency = p->frequency; */
+	} else {
+		fe->ops.tuner_ops.set_params(fe);
+		msleep(300);
+		s5h1432_set_channel_bandwidth(fe, dvb_bandwidth);
+		switch (p->bandwidth_hz) {
+		case 6000000:
+			dvb_bandwidth = 6;
+			s5h1432_set_IF(fe, IF_FREQ_4_MHZ);
+			break;
+		case 7000000:
+			dvb_bandwidth = 7;
+			s5h1432_set_IF(fe, IF_FREQ_4_MHZ);
+			break;
+		case 8000000:
+			dvb_bandwidth = 8;
+			s5h1432_set_IF(fe, IF_FREQ_4_MHZ);
+			break;
+		default:
+			return 0;
+		}
+		/*fe->ops.tuner_ops.set_params(fe); */
+/*Soft Reset chip*/
+		msleep(30);
+		s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x09, 0x1a);
+		msleep(30);
+		s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x09, 0x1b);
+
+		s5h1432_set_channel_bandwidth(fe, dvb_bandwidth);
+		switch (p->bandwidth_hz) {
+		case 6000000:
+			dvb_bandwidth = 6;
+			s5h1432_set_IF(fe, IF_FREQ_4_MHZ);
+			break;
+		case 7000000:
+			dvb_bandwidth = 7;
+			s5h1432_set_IF(fe, IF_FREQ_4_MHZ);
+			break;
+		case 8000000:
+			dvb_bandwidth = 8;
+			s5h1432_set_IF(fe, IF_FREQ_4_MHZ);
+			break;
+		default:
+			return 0;
+		}
+		/*fe->ops.tuner_ops.set_params(fe); */
+		/*Soft Reset chip*/
+		msleep(30);
+		s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x09, 0x1a);
+		msleep(30);
+		s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x09, 0x1b);
+
+	}
+
+	state->current_frequency = p->frequency;
+
+	return 0;
+}
+
+static int s5h1432_init(struct dvb_frontend *fe)
+{
+	struct s5h1432_state *state = fe->demodulator_priv;
+
+	u8 reg = 0;
+	state->current_frequency = 0;
+	printk(KERN_INFO " s5h1432_init().\n");
+
+	/*Set VSB mode as default, this also does a soft reset */
+	/*Initialize registers */
+
+	s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x04, 0xa8);
+	s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x05, 0x01);
+	s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x07, 0x70);
+	s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x19, 0x80);
+	s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x1b, 0x9D);
+	s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x1c, 0x30);
+	s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x1d, 0x20);
+	s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x1e, 0x1B);
+	s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x2e, 0x40);
+	s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x42, 0x84);
+	s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x50, 0x5a);
+	s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x5a, 0xd3);
+	s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x68, 0x50);
+	s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xb8, 0x3c);
+	s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xc4, 0x10);
+	s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xcc, 0x9c);
+	s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xDA, 0x00);
+	s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe1, 0x94);
+	/* s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xf4, 0xa1); */
+	s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xf9, 0x00);
+
+	/*For NXP tuner*/
+
+	/*Set 3.3MHz as default IF frequency */
+	s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe4, 0x66);
+	s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe5, 0x66);
+	s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe7, 0xEE);
+	/* Set reg 0x1E to get the full dynamic range */
+	s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x1e, 0x31);
+
+	/* Mode setting in demod */
+	reg = s5h1432_readreg(state, S5H1432_I2C_TOP_ADDR, 0x42);
+	reg |= 0x80;
+	s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x42, reg);
+	/* Serial mode */
+
+	/* Soft Reset chip */
+
+	s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x09, 0x1a);
+	msleep(30);
+	s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x09, 0x1b);
+
+
+	return 0;
+}
+
+static int s5h1432_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+	return 0;
+}
+
+static int s5h1432_read_signal_strength(struct dvb_frontend *fe,
+					u16 *signal_strength)
+{
+	return 0;
+}
+
+static int s5h1432_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+	return 0;
+}
+
+static int s5h1432_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+
+	return 0;
+}
+
+static int s5h1432_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+	return 0;
+}
+
+static int s5h1432_get_tune_settings(struct dvb_frontend *fe,
+				     struct dvb_frontend_tune_settings *tune)
+{
+	return 0;
+}
+
+static void s5h1432_release(struct dvb_frontend *fe)
+{
+	struct s5h1432_state *state = fe->demodulator_priv;
+	kfree(state);
+}
+
+static struct dvb_frontend_ops s5h1432_ops;
+
+struct dvb_frontend *s5h1432_attach(const struct s5h1432_config *config,
+				    struct i2c_adapter *i2c)
+{
+	struct s5h1432_state *state = NULL;
+
+	printk(KERN_INFO " Enter s5h1432_attach(). attach success!\n");
+	/* allocate memory for the internal state */
+	state = kmalloc(sizeof(struct s5h1432_state), GFP_KERNEL);
+	if (state == NULL)
+		goto error;
+
+	/* setup the state */
+	state->config = config;
+	state->i2c = i2c;
+	state->current_modulation = QAM_16;
+	state->inversion = state->config->inversion;
+
+	/* create dvb_frontend */
+	memcpy(&state->frontend.ops, &s5h1432_ops,
+	       sizeof(struct dvb_frontend_ops));
+
+	state->frontend.demodulator_priv = state;
+
+	return &state->frontend;
+
+error:
+	kfree(state);
+	return NULL;
+}
+EXPORT_SYMBOL(s5h1432_attach);
+
+static struct dvb_frontend_ops s5h1432_ops = {
+	.delsys = { SYS_DVBT },
+	.info = {
+		 .name = "Samsung s5h1432 DVB-T Frontend",
+		 .frequency_min = 177000000,
+		 .frequency_max = 858000000,
+		 .frequency_stepsize = 166666,
+		 .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_FEC_AUTO |
+		 FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
+		 FE_CAN_HIERARCHY_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |
+		 FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_RECOVER},
+
+	.init = s5h1432_init,
+	.sleep = s5h1432_sleep,
+	.set_frontend = s5h1432_set_frontend,
+	.get_tune_settings = s5h1432_get_tune_settings,
+	.read_status = s5h1432_read_status,
+	.read_ber = s5h1432_read_ber,
+	.read_signal_strength = s5h1432_read_signal_strength,
+	.read_snr = s5h1432_read_snr,
+	.read_ucblocks = s5h1432_read_ucblocks,
+	.release = s5h1432_release,
+};
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Enable verbose debug messages");
+
+MODULE_DESCRIPTION("Samsung s5h1432 DVB-T Demodulator driver");
+MODULE_AUTHOR("Bill Liu");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb-frontends/s5h1432.h b/drivers/media/dvb-frontends/s5h1432.h
new file mode 100644
index 0000000..b57438c
--- /dev/null
+++ b/drivers/media/dvb-frontends/s5h1432.h
@@ -0,0 +1,91 @@
+/*
+ *  Samsung s5h1432 VSB/QAM demodulator driver
+ *
+ *  Copyright (C) 2009 Bill Liu <Bill.Liu@Conexant.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifndef __S5H1432_H__
+#define __S5H1432_H__
+
+#include <linux/dvb/frontend.h>
+
+#define S5H1432_I2C_TOP_ADDR (0x02 >> 1)
+
+#define TAIWAN_HI_IF_FREQ_44_MHZ 44000000
+#define EUROPE_HI_IF_FREQ_36_MHZ 36000000
+#define IF_FREQ_6_MHZ             6000000
+#define IF_FREQ_3point3_MHZ       3300000
+#define IF_FREQ_3point5_MHZ       3500000
+#define IF_FREQ_4_MHZ             4000000
+
+struct s5h1432_config {
+
+	/* serial/parallel output */
+#define S5H1432_PARALLEL_OUTPUT 0
+#define S5H1432_SERIAL_OUTPUT   1
+	u8 output_mode;
+
+	/* GPIO Setting */
+#define S5H1432_GPIO_OFF 0
+#define S5H1432_GPIO_ON  1
+	u8 gpio;
+
+	/* MPEG signal timing */
+#define S5H1432_MPEGTIMING_CONTINOUS_INVERTING_CLOCK       0
+#define S5H1432_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK    1
+#define S5H1432_MPEGTIMING_NONCONTINOUS_INVERTING_CLOCK    2
+#define S5H1432_MPEGTIMING_NONCONTINOUS_NONINVERTING_CLOCK 3
+	u16 mpeg_timing;
+
+	/* IF Freq for QAM and VSB in KHz */
+#define S5H1432_IF_3250  3250
+#define S5H1432_IF_3500  3500
+#define S5H1432_IF_4000  4000
+#define S5H1432_IF_5380  5380
+#define S5H1432_IF_44000 44000
+#define S5H1432_VSB_IF_DEFAULT s5h1432_IF_44000
+#define S5H1432_QAM_IF_DEFAULT s5h1432_IF_44000
+	u16 qam_if;
+	u16 vsb_if;
+
+	/* Spectral Inversion */
+#define S5H1432_INVERSION_OFF 0
+#define S5H1432_INVERSION_ON  1
+	u8 inversion;
+
+	/* Return lock status based on tuner lock, or demod lock */
+#define S5H1432_TUNERLOCKING 0
+#define S5H1432_DEMODLOCKING 1
+	u8 status_mode;
+};
+
+#if defined(CONFIG_DVB_S5H1432) || \
+	(defined(CONFIG_DVB_S5H1432_MODULE) && defined(MODULE))
+extern struct dvb_frontend *s5h1432_attach(const struct s5h1432_config *config,
+					   struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend *s5h1432_attach(const struct s5h1432_config
+						  *config,
+						  struct i2c_adapter *i2c)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif /* CONFIG_DVB_s5h1432 */
+
+#endif /* __s5h1432_H__ */
diff --git a/drivers/media/dvb-frontends/s921.c b/drivers/media/dvb-frontends/s921.c
new file mode 100644
index 0000000..cd2288c
--- /dev/null
+++ b/drivers/media/dvb-frontends/s921.c
@@ -0,0 +1,549 @@
+/*
+ *   Sharp VA3A5JZ921 One Seg Broadcast Module driver
+ *   This device is labeled as just S. 921 at the top of the frontend can
+ *
+ *   Copyright (C) 2009-2010 Mauro Carvalho Chehab <mchehab@redhat.com>
+ *   Copyright (C) 2009-2010 Douglas Landgraf <dougsland@redhat.com>
+ *
+ *   Developed for Leadership SBTVD 1seg device sold in Brazil
+ *
+ *   Frontend module based on cx24123 driver, getting some info from
+ *	the old s921 driver.
+ *
+ *   FIXME: Need to port to DVB v5.2 API
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License as
+ *   published by the Free Software Foundation version 2.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *   General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <asm/div64.h>
+
+#include "dvb_frontend.h"
+#include "s921.h"
+
+static int debug = 1;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)");
+
+#define rc(args...)  do {						\
+	printk(KERN_ERR  "s921: " args);				\
+} while (0)
+
+#define dprintk(args...)						\
+	do {								\
+		if (debug) {						\
+			printk(KERN_DEBUG "s921: %s: ", __func__);	\
+			printk(args);					\
+		}							\
+	} while (0)
+
+struct s921_state {
+	struct i2c_adapter *i2c;
+	const struct s921_config *config;
+
+	struct dvb_frontend frontend;
+
+	/* The Demod can't easily provide these, we cache them */
+	u32 currentfreq;
+};
+
+/*
+ * Various tuner defaults need to be established for a given frequency kHz.
+ * fixme: The bounds on the bands do not match the doc in real life.
+ * fixme: Some of them have been moved, other might need adjustment.
+ */
+static struct s921_bandselect_val {
+	u32 freq_low;
+	u8  band_reg;
+} s921_bandselect[] = {
+	{         0, 0x7b },
+	{ 485140000, 0x5b },
+	{ 515140000, 0x3b },
+	{ 545140000, 0x1b },
+	{ 599140000, 0xfb },
+	{ 623140000, 0xdb },
+	{ 659140000, 0xbb },
+	{ 713140000, 0x9b },
+};
+
+struct regdata {
+	u8 reg;
+	u8 data;
+};
+
+static struct regdata s921_init[] = {
+	{ 0x01, 0x80 },		/* Probably, a reset sequence */
+	{ 0x01, 0x40 },
+	{ 0x01, 0x80 },
+	{ 0x01, 0x40 },
+
+	{ 0x02, 0x00 },
+	{ 0x03, 0x40 },
+	{ 0x04, 0x01 },
+	{ 0x05, 0x00 },
+	{ 0x06, 0x00 },
+	{ 0x07, 0x00 },
+	{ 0x08, 0x00 },
+	{ 0x09, 0x00 },
+	{ 0x0a, 0x00 },
+	{ 0x0b, 0x5a },
+	{ 0x0c, 0x00 },
+	{ 0x0d, 0x00 },
+	{ 0x0f, 0x00 },
+	{ 0x13, 0x1b },
+	{ 0x14, 0x80 },
+	{ 0x15, 0x40 },
+	{ 0x17, 0x70 },
+	{ 0x18, 0x01 },
+	{ 0x19, 0x12 },
+	{ 0x1a, 0x01 },
+	{ 0x1b, 0x12 },
+	{ 0x1c, 0xa0 },
+	{ 0x1d, 0x00 },
+	{ 0x1e, 0x0a },
+	{ 0x1f, 0x08 },
+	{ 0x20, 0x40 },
+	{ 0x21, 0xff },
+	{ 0x22, 0x4c },
+	{ 0x23, 0x4e },
+	{ 0x24, 0x4c },
+	{ 0x25, 0x00 },
+	{ 0x26, 0x00 },
+	{ 0x27, 0xf4 },
+	{ 0x28, 0x60 },
+	{ 0x29, 0x88 },
+	{ 0x2a, 0x40 },
+	{ 0x2b, 0x40 },
+	{ 0x2c, 0xff },
+	{ 0x2d, 0x00 },
+	{ 0x2e, 0xff },
+	{ 0x2f, 0x00 },
+	{ 0x30, 0x20 },
+	{ 0x31, 0x06 },
+	{ 0x32, 0x0c },
+	{ 0x34, 0x0f },
+	{ 0x37, 0xfe },
+	{ 0x38, 0x00 },
+	{ 0x39, 0x63 },
+	{ 0x3a, 0x10 },
+	{ 0x3b, 0x10 },
+	{ 0x47, 0x00 },
+	{ 0x49, 0xe5 },
+	{ 0x4b, 0x00 },
+	{ 0x50, 0xc0 },
+	{ 0x52, 0x20 },
+	{ 0x54, 0x5a },
+	{ 0x55, 0x5b },
+	{ 0x56, 0x40 },
+	{ 0x57, 0x70 },
+	{ 0x5c, 0x50 },
+	{ 0x5d, 0x00 },
+	{ 0x62, 0x17 },
+	{ 0x63, 0x2f },
+	{ 0x64, 0x6f },
+	{ 0x68, 0x00 },
+	{ 0x69, 0x89 },
+	{ 0x6a, 0x00 },
+	{ 0x6b, 0x00 },
+	{ 0x6c, 0x00 },
+	{ 0x6d, 0x00 },
+	{ 0x6e, 0x00 },
+	{ 0x70, 0x10 },
+	{ 0x71, 0x00 },
+	{ 0x75, 0x00 },
+	{ 0x76, 0x30 },
+	{ 0x77, 0x01 },
+	{ 0xaf, 0x00 },
+	{ 0xb0, 0xa0 },
+	{ 0xb2, 0x3d },
+	{ 0xb3, 0x25 },
+	{ 0xb4, 0x8b },
+	{ 0xb5, 0x4b },
+	{ 0xb6, 0x3f },
+	{ 0xb7, 0xff },
+	{ 0xb8, 0xff },
+	{ 0xb9, 0xfc },
+	{ 0xba, 0x00 },
+	{ 0xbb, 0x00 },
+	{ 0xbc, 0x00 },
+	{ 0xd0, 0x30 },
+	{ 0xe4, 0x84 },
+	{ 0xf0, 0x48 },
+	{ 0xf1, 0x19 },
+	{ 0xf2, 0x5a },
+	{ 0xf3, 0x8e },
+	{ 0xf4, 0x2d },
+	{ 0xf5, 0x07 },
+	{ 0xf6, 0x5a },
+	{ 0xf7, 0xba },
+	{ 0xf8, 0xd7 },
+};
+
+static struct regdata s921_prefreq[] = {
+	{ 0x47, 0x60 },
+	{ 0x68, 0x00 },
+	{ 0x69, 0x89 },
+	{ 0xf0, 0x48 },
+	{ 0xf1, 0x19 },
+};
+
+static struct regdata s921_postfreq[] = {
+	{ 0xf5, 0xae },
+	{ 0xf6, 0xb7 },
+	{ 0xf7, 0xba },
+	{ 0xf8, 0xd7 },
+	{ 0x68, 0x0a },
+	{ 0x69, 0x09 },
+};
+
+static int s921_i2c_writereg(struct s921_state *state,
+			     u8 i2c_addr, int reg, int data)
+{
+	u8 buf[] = { reg, data };
+	struct i2c_msg msg = {
+		.addr = i2c_addr, .flags = 0, .buf = buf, .len = 2
+	};
+	int rc;
+
+	rc = i2c_transfer(state->i2c, &msg, 1);
+	if (rc != 1) {
+		printk("%s: writereg rcor(rc == %i, reg == 0x%02x,"
+			 " data == 0x%02x)\n", __func__, rc, reg, data);
+		return rc;
+	}
+
+	return 0;
+}
+
+static int s921_i2c_writeregdata(struct s921_state *state, u8 i2c_addr,
+				 struct regdata *rd, int size)
+{
+	int i, rc;
+
+	for (i = 0; i < size; i++) {
+		rc = s921_i2c_writereg(state, i2c_addr, rd[i].reg, rd[i].data);
+		if (rc < 0)
+			return rc;
+	}
+	return 0;
+}
+
+static int s921_i2c_readreg(struct s921_state *state, u8 i2c_addr, u8 reg)
+{
+	u8 val;
+	int rc;
+	struct i2c_msg msg[] = {
+		{ .addr = i2c_addr, .flags = 0, .buf = &reg, .len = 1 },
+		{ .addr = i2c_addr, .flags = I2C_M_RD, .buf = &val, .len = 1 }
+	};
+
+	rc = i2c_transfer(state->i2c, msg, 2);
+
+	if (rc != 2) {
+		rc("%s: reg=0x%x (rcor=%d)\n", __func__, reg, rc);
+		return rc;
+	}
+
+	return val;
+}
+
+#define s921_readreg(state, reg) \
+	s921_i2c_readreg(state, state->config->demod_address, reg)
+#define s921_writereg(state, reg, val) \
+	s921_i2c_writereg(state, state->config->demod_address, reg, val)
+#define s921_writeregdata(state, regdata) \
+	s921_i2c_writeregdata(state, state->config->demod_address, \
+	regdata, ARRAY_SIZE(regdata))
+
+static int s921_pll_tune(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct s921_state *state = fe->demodulator_priv;
+	int band, rc, i;
+	unsigned long f_offset;
+	u8 f_switch;
+	u64 offset;
+
+	dprintk("frequency=%i\n", p->frequency);
+
+	for (band = 0; band < ARRAY_SIZE(s921_bandselect); band++)
+		if (p->frequency < s921_bandselect[band].freq_low)
+			break;
+	band--;
+
+	if (band < 0) {
+		rc("%s: frequency out of range\n", __func__);
+		return -EINVAL;
+	}
+
+	f_switch = s921_bandselect[band].band_reg;
+
+	offset = ((u64)p->frequency) * 258;
+	do_div(offset, 6000000);
+	f_offset = ((unsigned long)offset) + 2321;
+
+	rc = s921_writeregdata(state, s921_prefreq);
+	if (rc < 0)
+		return rc;
+
+	rc = s921_writereg(state, 0xf2, (f_offset >> 8) & 0xff);
+	if (rc < 0)
+		return rc;
+
+	rc = s921_writereg(state, 0xf3, f_offset & 0xff);
+	if (rc < 0)
+		return rc;
+
+	rc = s921_writereg(state, 0xf4, f_switch);
+	if (rc < 0)
+		return rc;
+
+	rc = s921_writeregdata(state, s921_postfreq);
+	if (rc < 0)
+		return rc;
+
+	for (i = 0 ; i < 6; i++) {
+		rc = s921_readreg(state, 0x80);
+		dprintk("status 0x80: %02x\n", rc);
+	}
+	rc = s921_writereg(state, 0x01, 0x40);
+	if (rc < 0)
+		return rc;
+
+	rc = s921_readreg(state, 0x01);
+	dprintk("status 0x01: %02x\n", rc);
+
+	rc = s921_readreg(state, 0x80);
+	dprintk("status 0x80: %02x\n", rc);
+
+	rc = s921_readreg(state, 0x80);
+	dprintk("status 0x80: %02x\n", rc);
+
+	rc = s921_readreg(state, 0x32);
+	dprintk("status 0x32: %02x\n", rc);
+
+	dprintk("pll tune band=%d, pll=%d\n", f_switch, (int)f_offset);
+
+	return 0;
+}
+
+static int s921_initfe(struct dvb_frontend *fe)
+{
+	struct s921_state *state = fe->demodulator_priv;
+	int rc;
+
+	dprintk("\n");
+
+	rc = s921_writeregdata(state, s921_init);
+	if (rc < 0)
+		return rc;
+
+	return 0;
+}
+
+static int s921_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+	struct s921_state *state = fe->demodulator_priv;
+	int regstatus, rc;
+
+	*status = 0;
+
+	rc = s921_readreg(state, 0x81);
+	if (rc < 0)
+		return rc;
+
+	regstatus = rc << 8;
+
+	rc = s921_readreg(state, 0x82);
+	if (rc < 0)
+		return rc;
+
+	regstatus |= rc;
+
+	dprintk("status = %04x\n", regstatus);
+
+	/* Full Sync - We don't know what each bit means on regs 0x81/0x82 */
+	if ((regstatus & 0xff) == 0x40) {
+		*status = FE_HAS_SIGNAL  |
+			  FE_HAS_CARRIER |
+			  FE_HAS_VITERBI |
+			  FE_HAS_SYNC    |
+			  FE_HAS_LOCK;
+	} else if (regstatus & 0x40) {
+		/* This is close to Full Sync, but not enough to get useful info */
+		*status = FE_HAS_SIGNAL  |
+			  FE_HAS_CARRIER |
+			  FE_HAS_VITERBI |
+			  FE_HAS_SYNC;
+	}
+
+	return 0;
+}
+
+static int s921_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
+{
+	fe_status_t	status;
+	struct s921_state *state = fe->demodulator_priv;
+	int rc;
+
+	/* FIXME: Use the proper register for it... 0x80? */
+	rc = s921_read_status(fe, &status);
+	if (rc < 0)
+		return rc;
+
+	*strength = (status & FE_HAS_LOCK) ? 0xffff : 0;
+
+	dprintk("strength = 0x%04x\n", *strength);
+
+	rc = s921_readreg(state, 0x01);
+	dprintk("status 0x01: %02x\n", rc);
+
+	rc = s921_readreg(state, 0x80);
+	dprintk("status 0x80: %02x\n", rc);
+
+	rc = s921_readreg(state, 0x32);
+	dprintk("status 0x32: %02x\n", rc);
+
+	return 0;
+}
+
+static int s921_set_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct s921_state *state = fe->demodulator_priv;
+	int rc;
+
+	dprintk("\n");
+
+	/* FIXME: We don't know how to use non-auto mode */
+
+	rc = s921_pll_tune(fe);
+	if (rc < 0)
+		return rc;
+
+	state->currentfreq = p->frequency;
+
+	return 0;
+}
+
+static int s921_get_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct s921_state *state = fe->demodulator_priv;
+
+	/* FIXME: Probably it is possible to get it from regs f1 and f2 */
+	p->frequency = state->currentfreq;
+	p->delivery_system = SYS_ISDBT;
+
+	return 0;
+}
+
+static int s921_tune(struct dvb_frontend *fe,
+			bool re_tune,
+			unsigned int mode_flags,
+			unsigned int *delay,
+			fe_status_t *status)
+{
+	int rc = 0;
+
+	dprintk("\n");
+
+	if (re_tune)
+		rc = s921_set_frontend(fe);
+
+	if (!(mode_flags & FE_TUNE_MODE_ONESHOT))
+		s921_read_status(fe, status);
+
+	return rc;
+}
+
+static int s921_get_algo(struct dvb_frontend *fe)
+{
+	return 1; /* FE_ALGO_HW */
+}
+
+static void s921_release(struct dvb_frontend *fe)
+{
+	struct s921_state *state = fe->demodulator_priv;
+
+	dprintk("\n");
+	kfree(state);
+}
+
+static struct dvb_frontend_ops s921_ops;
+
+struct dvb_frontend *s921_attach(const struct s921_config *config,
+				    struct i2c_adapter *i2c)
+{
+	/* allocate memory for the internal state */
+	struct s921_state *state =
+		kzalloc(sizeof(struct s921_state), GFP_KERNEL);
+
+	dprintk("\n");
+	if (state == NULL) {
+		rc("Unable to kzalloc\n");
+		goto rcor;
+	}
+
+	/* setup the state */
+	state->config = config;
+	state->i2c = i2c;
+
+	/* create dvb_frontend */
+	memcpy(&state->frontend.ops, &s921_ops,
+		sizeof(struct dvb_frontend_ops));
+	state->frontend.demodulator_priv = state;
+
+	return &state->frontend;
+
+rcor:
+	kfree(state);
+
+	return NULL;
+}
+EXPORT_SYMBOL(s921_attach);
+
+static struct dvb_frontend_ops s921_ops = {
+	.delsys = { SYS_ISDBT },
+	/* Use dib8000 values per default */
+	.info = {
+		.name = "Sharp S921",
+		.frequency_min = 470000000,
+		/*
+		 * Max should be 770MHz instead, according with Sharp docs,
+		 * but Leadership doc says it works up to 806 MHz. This is
+		 * required to get channel 69, used in Brazil
+		 */
+		.frequency_max = 806000000,
+		.frequency_tolerance = 0,
+		 .caps = FE_CAN_INVERSION_AUTO |
+			 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_FEC_AUTO |
+			 FE_CAN_QPSK     | FE_CAN_QAM_16 | FE_CAN_QAM_64 |
+			 FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO |
+			 FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_RECOVER |
+			 FE_CAN_HIERARCHY_AUTO,
+	},
+
+	.release = s921_release,
+
+	.init = s921_initfe,
+	.set_frontend = s921_set_frontend,
+	.get_frontend = s921_get_frontend,
+	.read_status = s921_read_status,
+	.read_signal_strength = s921_read_signal_strength,
+	.tune = s921_tune,
+	.get_frontend_algo = s921_get_algo,
+};
+
+MODULE_DESCRIPTION("DVB Frontend module for Sharp S921 hardware");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
+MODULE_AUTHOR("Douglas Landgraf <dougsland@redhat.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb-frontends/s921.h b/drivers/media/dvb-frontends/s921.h
new file mode 100644
index 0000000..f220d82
--- /dev/null
+++ b/drivers/media/dvb-frontends/s921.h
@@ -0,0 +1,47 @@
+/*
+ *   Sharp s921 driver
+ *
+ *   Copyright (C) 2009 Mauro Carvalho Chehab <mchehab@redhat.com>
+ *   Copyright (C) 2009 Douglas Landgraf <dougsland@redhat.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 version 2.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *   General Public License for more details.
+ */
+
+#ifndef S921_H
+#define S921_H
+
+#include <linux/dvb/frontend.h>
+
+struct s921_config {
+	/* the demodulator's i2c address */
+	u8 demod_address;
+};
+
+#if defined(CONFIG_DVB_S921) || (defined(CONFIG_DVB_S921_MODULE) \
+	&& defined(MODULE))
+extern struct dvb_frontend *s921_attach(const struct s921_config *config,
+					   struct i2c_adapter *i2c);
+extern struct i2c_adapter *s921_get_tuner_i2c_adapter(struct dvb_frontend *);
+#else
+static inline struct dvb_frontend *s921_attach(
+	const struct s921_config *config, struct i2c_adapter *i2c)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+static struct i2c_adapter *
+	s921_get_tuner_i2c_adapter(struct dvb_frontend *fe)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif
+
+#endif /* S921_H */
diff --git a/drivers/media/dvb-frontends/si21xx.c b/drivers/media/dvb-frontends/si21xx.c
new file mode 100644
index 0000000..a68a648
--- /dev/null
+++ b/drivers/media/dvb-frontends/si21xx.c
@@ -0,0 +1,951 @@
+/* DVB compliant Linux driver for the DVB-S si2109/2110 demodulator
+*
+* Copyright (C) 2008 Igor M. Liplianin (liplianin@me.by)
+*
+*	This program is free software; you can redistribute it and/or modify
+*	it under the terms of the 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/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <asm/div64.h>
+
+#include "dvb_frontend.h"
+#include "si21xx.h"
+
+#define	REVISION_REG			0x00
+#define	SYSTEM_MODE_REG			0x01
+#define	TS_CTRL_REG_1			0x02
+#define	TS_CTRL_REG_2			0x03
+#define	PIN_CTRL_REG_1			0x04
+#define	PIN_CTRL_REG_2			0x05
+#define	LOCK_STATUS_REG_1		0x0f
+#define	LOCK_STATUS_REG_2		0x10
+#define	ACQ_STATUS_REG			0x11
+#define	ACQ_CTRL_REG_1			0x13
+#define	ACQ_CTRL_REG_2			0x14
+#define	PLL_DIVISOR_REG			0x15
+#define	COARSE_TUNE_REG			0x16
+#define	FINE_TUNE_REG_L			0x17
+#define	FINE_TUNE_REG_H			0x18
+
+#define	ANALOG_AGC_POWER_LEVEL_REG	0x28
+#define	CFO_ESTIMATOR_CTRL_REG_1	0x29
+#define	CFO_ESTIMATOR_CTRL_REG_2	0x2a
+#define	CFO_ESTIMATOR_CTRL_REG_3	0x2b
+
+#define	SYM_RATE_ESTIMATE_REG_L		0x31
+#define	SYM_RATE_ESTIMATE_REG_M		0x32
+#define	SYM_RATE_ESTIMATE_REG_H		0x33
+
+#define	CFO_ESTIMATOR_OFFSET_REG_L	0x36
+#define	CFO_ESTIMATOR_OFFSET_REG_H	0x37
+#define	CFO_ERROR_REG_L			0x38
+#define	CFO_ERROR_REG_H			0x39
+#define	SYM_RATE_ESTIMATOR_CTRL_REG	0x3a
+
+#define	SYM_RATE_REG_L			0x3f
+#define	SYM_RATE_REG_M			0x40
+#define	SYM_RATE_REG_H			0x41
+#define	SYM_RATE_ESTIMATOR_MAXIMUM_REG	0x42
+#define	SYM_RATE_ESTIMATOR_MINIMUM_REG	0x43
+
+#define	C_N_ESTIMATOR_CTRL_REG		0x7c
+#define	C_N_ESTIMATOR_THRSHLD_REG	0x7d
+#define	C_N_ESTIMATOR_LEVEL_REG_L	0x7e
+#define	C_N_ESTIMATOR_LEVEL_REG_H	0x7f
+
+#define	BLIND_SCAN_CTRL_REG		0x80
+
+#define	LSA_CTRL_REG_1			0x8D
+#define	SPCTRM_TILT_CORR_THRSHLD_REG	0x8f
+#define	ONE_DB_BNDWDTH_THRSHLD_REG	0x90
+#define	TWO_DB_BNDWDTH_THRSHLD_REG	0x91
+#define	THREE_DB_BNDWDTH_THRSHLD_REG	0x92
+#define	INBAND_POWER_THRSHLD_REG	0x93
+#define	REF_NOISE_LVL_MRGN_THRSHLD_REG	0x94
+
+#define	VIT_SRCH_CTRL_REG_1		0xa0
+#define	VIT_SRCH_CTRL_REG_2		0xa1
+#define	VIT_SRCH_CTRL_REG_3		0xa2
+#define	VIT_SRCH_STATUS_REG		0xa3
+#define	VITERBI_BER_COUNT_REG_L		0xab
+#define	REED_SOLOMON_CTRL_REG		0xb0
+#define	REED_SOLOMON_ERROR_COUNT_REG_L	0xb1
+#define	PRBS_CTRL_REG			0xb5
+
+#define	LNB_CTRL_REG_1			0xc0
+#define	LNB_CTRL_REG_2			0xc1
+#define	LNB_CTRL_REG_3			0xc2
+#define	LNB_CTRL_REG_4			0xc3
+#define	LNB_CTRL_STATUS_REG		0xc4
+#define	LNB_FIFO_REGS_0			0xc5
+#define	LNB_FIFO_REGS_1			0xc6
+#define	LNB_FIFO_REGS_2			0xc7
+#define	LNB_FIFO_REGS_3			0xc8
+#define	LNB_FIFO_REGS_4			0xc9
+#define	LNB_FIFO_REGS_5			0xca
+#define	LNB_SUPPLY_CTRL_REG_1		0xcb
+#define	LNB_SUPPLY_CTRL_REG_2		0xcc
+#define	LNB_SUPPLY_CTRL_REG_3		0xcd
+#define	LNB_SUPPLY_CTRL_REG_4		0xce
+#define	LNB_SUPPLY_STATUS_REG		0xcf
+
+#define FAIL	-1
+#define PASS	0
+
+#define ALLOWABLE_FS_COUNT	10
+#define STATUS_BER		0
+#define STATUS_UCBLOCKS		1
+
+static int debug;
+#define dprintk(args...) \
+	do { \
+		if (debug) \
+			printk(KERN_DEBUG "si21xx: " args); \
+	} while (0)
+
+enum {
+	ACTIVE_HIGH,
+	ACTIVE_LOW
+};
+enum {
+	BYTE_WIDE,
+	BIT_WIDE
+};
+enum {
+	CLK_GAPPED_MODE,
+	CLK_CONTINUOUS_MODE
+};
+enum {
+	RISING_EDGE,
+	FALLING_EDGE
+};
+enum {
+	MSB_FIRST,
+	LSB_FIRST
+};
+enum {
+	SERIAL,
+	PARALLEL
+};
+
+struct si21xx_state {
+	struct i2c_adapter *i2c;
+	const struct si21xx_config *config;
+	struct dvb_frontend frontend;
+	u8 initialised:1;
+	int errmode;
+	int fs;			/*Sampling rate of the ADC in MHz*/
+};
+
+/*	register default initialization */
+static u8 serit_sp1511lhb_inittab[] = {
+	0x01, 0x28,	/* set i2c_inc_disable */
+	0x20, 0x03,
+	0x27, 0x20,
+	0xe0, 0x45,
+	0xe1, 0x08,
+	0xfe, 0x01,
+	0x01, 0x28,
+	0x89, 0x09,
+	0x04, 0x80,
+	0x05, 0x01,
+	0x06, 0x00,
+	0x20, 0x03,
+	0x24, 0x88,
+	0x29, 0x09,
+	0x2a, 0x0f,
+	0x2c, 0x10,
+	0x2d, 0x19,
+	0x2e, 0x08,
+	0x2f, 0x10,
+	0x30, 0x19,
+	0x34, 0x20,
+	0x35, 0x03,
+	0x45, 0x02,
+	0x46, 0x45,
+	0x47, 0xd0,
+	0x48, 0x00,
+	0x49, 0x40,
+	0x4a, 0x03,
+	0x4c, 0xfd,
+	0x4f, 0x2e,
+	0x50, 0x2e,
+	0x51, 0x10,
+	0x52, 0x10,
+	0x56, 0x92,
+	0x59, 0x00,
+	0x5a, 0x2d,
+	0x5b, 0x33,
+	0x5c, 0x1f,
+	0x5f, 0x76,
+	0x62, 0xc0,
+	0x63, 0xc0,
+	0x64, 0xf3,
+	0x65, 0xf3,
+	0x79, 0x40,
+	0x6a, 0x40,
+	0x6b, 0x0a,
+	0x6c, 0x80,
+	0x6d, 0x27,
+	0x71, 0x06,
+	0x75, 0x60,
+	0x78, 0x00,
+	0x79, 0xb5,
+	0x7c, 0x05,
+	0x7d, 0x1a,
+	0x87, 0x55,
+	0x88, 0x72,
+	0x8f, 0x08,
+	0x90, 0xe0,
+	0x94, 0x40,
+	0xa0, 0x3f,
+	0xa1, 0xc0,
+	0xa4, 0xcc,
+	0xa5, 0x66,
+	0xa6, 0x66,
+	0xa7, 0x7b,
+	0xa8, 0x7b,
+	0xa9, 0x7b,
+	0xaa, 0x9a,
+	0xed, 0x04,
+	0xad, 0x00,
+	0xae, 0x03,
+	0xcc, 0xab,
+	0x01, 0x08,
+	0xff, 0xff
+};
+
+/*	low level read/writes */
+static int si21_writeregs(struct si21xx_state *state, u8 reg1,
+							u8 *data, int len)
+{
+	int ret;
+	u8 buf[60];/* = { reg1, data };*/
+	struct i2c_msg msg = {
+				.addr = state->config->demod_address,
+				.flags = 0,
+				.buf = buf,
+				.len = len + 1
+	};
+
+	msg.buf[0] =  reg1;
+	memcpy(msg.buf + 1, data, len);
+
+	ret = i2c_transfer(state->i2c, &msg, 1);
+
+	if (ret != 1)
+		dprintk("%s: writereg error (reg1 == 0x%02x, data == 0x%02x, "
+			"ret == %i)\n", __func__, reg1, data[0], ret);
+
+	return (ret != 1) ? -EREMOTEIO : 0;
+}
+
+static int si21_writereg(struct si21xx_state *state, u8 reg, u8 data)
+{
+	int ret;
+	u8 buf[] = { reg, data };
+	struct i2c_msg msg = {
+				.addr = state->config->demod_address,
+				.flags = 0,
+				.buf = buf,
+				.len = 2
+	};
+
+	ret = i2c_transfer(state->i2c, &msg, 1);
+
+	if (ret != 1)
+		dprintk("%s: writereg error (reg == 0x%02x, data == 0x%02x, "
+			"ret == %i)\n", __func__, reg, data, ret);
+
+	return (ret != 1) ? -EREMOTEIO : 0;
+}
+
+static int si21_write(struct dvb_frontend *fe, const u8 buf[], int len)
+{
+	struct si21xx_state *state = fe->demodulator_priv;
+
+	if (len != 2)
+		return -EINVAL;
+
+	return si21_writereg(state, buf[0], buf[1]);
+}
+
+static u8 si21_readreg(struct si21xx_state *state, u8 reg)
+{
+	int ret;
+	u8 b0[] = { reg };
+	u8 b1[] = { 0 };
+	struct i2c_msg msg[] = {
+		{
+			.addr = state->config->demod_address,
+			.flags = 0,
+			.buf = b0,
+			.len = 1
+		}, {
+			.addr = state->config->demod_address,
+			.flags = I2C_M_RD,
+			.buf = b1,
+			.len = 1
+		}
+	};
+
+	ret = i2c_transfer(state->i2c, msg, 2);
+
+	if (ret != 2)
+		dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n",
+			__func__, reg, ret);
+
+	return b1[0];
+}
+
+static int si21_readregs(struct si21xx_state *state, u8 reg1, u8 *b, u8 len)
+{
+	int ret;
+	struct i2c_msg msg[] = {
+		{
+			.addr = state->config->demod_address,
+			.flags = 0,
+			.buf = &reg1,
+			.len = 1
+		}, {
+			.addr = state->config->demod_address,
+			.flags = I2C_M_RD,
+			.buf = b,
+			.len = len
+		}
+	};
+
+	ret = i2c_transfer(state->i2c, msg, 2);
+
+	if (ret != 2)
+		dprintk("%s: readreg error (ret == %i)\n", __func__, ret);
+
+	return ret == 2 ? 0 : -1;
+}
+
+static int si21xx_wait_diseqc_idle(struct si21xx_state *state, int timeout)
+{
+	unsigned long start = jiffies;
+
+	dprintk("%s\n", __func__);
+
+	while ((si21_readreg(state, LNB_CTRL_REG_1) & 0x8) == 8) {
+		if (jiffies - start > timeout) {
+			dprintk("%s: timeout!!\n", __func__);
+			return -ETIMEDOUT;
+		}
+		msleep(10);
+	};
+
+	return 0;
+}
+
+static int si21xx_set_symbolrate(struct dvb_frontend *fe, u32 srate)
+{
+	struct si21xx_state *state = fe->demodulator_priv;
+	u32 sym_rate, data_rate;
+	int i;
+	u8 sym_rate_bytes[3];
+
+	dprintk("%s : srate = %i\n", __func__ , srate);
+
+	if ((srate < 1000000) || (srate > 45000000))
+		return -EINVAL;
+
+	data_rate = srate;
+	sym_rate = 0;
+
+	for (i = 0; i < 4; ++i) {
+		sym_rate /= 100;
+		sym_rate = sym_rate + ((data_rate % 100) * 0x800000) /
+								state->fs;
+		data_rate /= 100;
+	}
+	for (i = 0; i < 3; ++i)
+		sym_rate_bytes[i] = (u8)((sym_rate >> (i * 8)) & 0xff);
+
+	si21_writeregs(state, SYM_RATE_REG_L, sym_rate_bytes, 0x03);
+
+	return 0;
+}
+
+static int si21xx_send_diseqc_msg(struct dvb_frontend *fe,
+					struct dvb_diseqc_master_cmd *m)
+{
+	struct si21xx_state *state = fe->demodulator_priv;
+	u8 lnb_status;
+	u8 LNB_CTRL_1;
+	int status;
+
+	dprintk("%s\n", __func__);
+
+	status = PASS;
+	LNB_CTRL_1 = 0;
+
+	status |= si21_readregs(state, LNB_CTRL_STATUS_REG, &lnb_status, 0x01);
+	status |= si21_readregs(state, LNB_CTRL_REG_1, &lnb_status, 0x01);
+
+	/*fill the FIFO*/
+	status |= si21_writeregs(state, LNB_FIFO_REGS_0, m->msg, m->msg_len);
+
+	LNB_CTRL_1 = (lnb_status & 0x70);
+	LNB_CTRL_1 |= m->msg_len;
+
+	LNB_CTRL_1 |= 0x80;	/* begin LNB signaling */
+
+	status |= si21_writeregs(state, LNB_CTRL_REG_1, &LNB_CTRL_1, 0x01);
+
+	return status;
+}
+
+static int si21xx_send_diseqc_burst(struct dvb_frontend *fe,
+						fe_sec_mini_cmd_t burst)
+{
+	struct si21xx_state *state = fe->demodulator_priv;
+	u8 val;
+
+	dprintk("%s\n", __func__);
+
+	if (si21xx_wait_diseqc_idle(state, 100) < 0)
+		return -ETIMEDOUT;
+
+	val = (0x80 | si21_readreg(state, 0xc1));
+	if (si21_writereg(state, LNB_CTRL_REG_1,
+			burst == SEC_MINI_A ? (val & ~0x10) : (val | 0x10)))
+		return -EREMOTEIO;
+
+	if (si21xx_wait_diseqc_idle(state, 100) < 0)
+		return -ETIMEDOUT;
+
+	if (si21_writereg(state, LNB_CTRL_REG_1, val))
+		return -EREMOTEIO;
+
+	return 0;
+}
+/*	30.06.2008 */
+static int si21xx_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
+{
+	struct si21xx_state *state = fe->demodulator_priv;
+	u8 val;
+
+	dprintk("%s\n", __func__);
+	val = (0x80 | si21_readreg(state, LNB_CTRL_REG_1));
+
+	switch (tone) {
+	case SEC_TONE_ON:
+		return si21_writereg(state, LNB_CTRL_REG_1, val | 0x20);
+
+	case SEC_TONE_OFF:
+		return si21_writereg(state, LNB_CTRL_REG_1, (val & ~0x20));
+
+	default:
+		return -EINVAL;
+	}
+}
+
+static int si21xx_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t volt)
+{
+	struct si21xx_state *state = fe->demodulator_priv;
+
+	u8 val;
+	dprintk("%s: %s\n", __func__,
+		volt == SEC_VOLTAGE_13 ? "SEC_VOLTAGE_13" :
+		volt == SEC_VOLTAGE_18 ? "SEC_VOLTAGE_18" : "??");
+
+
+	val = (0x80 | si21_readreg(state, LNB_CTRL_REG_1));
+
+	switch (volt) {
+	case SEC_VOLTAGE_18:
+		return si21_writereg(state, LNB_CTRL_REG_1, val | 0x40);
+		break;
+	case SEC_VOLTAGE_13:
+		return si21_writereg(state, LNB_CTRL_REG_1, (val & ~0x40));
+		break;
+	default:
+		return -EINVAL;
+	};
+}
+
+static int si21xx_init(struct dvb_frontend *fe)
+{
+	struct si21xx_state *state = fe->demodulator_priv;
+	int i;
+	int status = 0;
+	u8 reg1;
+	u8 val;
+	u8 reg2[2];
+
+	dprintk("%s\n", __func__);
+
+	for (i = 0; ; i += 2) {
+		reg1 = serit_sp1511lhb_inittab[i];
+		val = serit_sp1511lhb_inittab[i+1];
+		if (reg1 == 0xff && val == 0xff)
+			break;
+		si21_writeregs(state, reg1, &val, 1);
+	}
+
+	/*DVB QPSK SYSTEM MODE REG*/
+	reg1 = 0x08;
+	si21_writeregs(state, SYSTEM_MODE_REG, &reg1, 0x01);
+
+	/*transport stream config*/
+	/*
+	mode = PARALLEL;
+	sdata_form = LSB_FIRST;
+	clk_edge = FALLING_EDGE;
+	clk_mode = CLK_GAPPED_MODE;
+	strt_len = BYTE_WIDE;
+	sync_pol = ACTIVE_HIGH;
+	val_pol = ACTIVE_HIGH;
+	err_pol = ACTIVE_HIGH;
+	sclk_rate = 0x00;
+	parity = 0x00 ;
+	data_delay = 0x00;
+	clk_delay = 0x00;
+	pclk_smooth = 0x00;
+	*/
+	reg2[0] =
+		PARALLEL + (LSB_FIRST << 1)
+		+ (FALLING_EDGE << 2) + (CLK_GAPPED_MODE << 3)
+		+ (BYTE_WIDE << 4) + (ACTIVE_HIGH << 5)
+		+ (ACTIVE_HIGH << 6) + (ACTIVE_HIGH << 7);
+
+	reg2[1] = 0;
+	/*	sclk_rate + (parity << 2)
+		+ (data_delay << 3) + (clk_delay << 4)
+		+ (pclk_smooth << 5);
+	*/
+	status |= si21_writeregs(state, TS_CTRL_REG_1, reg2, 0x02);
+	if (status != 0)
+		dprintk(" %s : TS Set Error\n", __func__);
+
+	return 0;
+
+}
+
+static int si21_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+	struct si21xx_state *state = fe->demodulator_priv;
+	u8 regs_read[2];
+	u8 reg_read;
+	u8 i;
+	u8 lock;
+	u8 signal = si21_readreg(state, ANALOG_AGC_POWER_LEVEL_REG);
+
+	si21_readregs(state, LOCK_STATUS_REG_1, regs_read, 0x02);
+	reg_read = 0;
+
+	for (i = 0; i < 7; ++i)
+		reg_read |= ((regs_read[0] >> i) & 0x01) << (6 - i);
+
+	lock = ((reg_read & 0x7f) | (regs_read[1] & 0x80));
+
+	dprintk("%s : FE_READ_STATUS : VSTATUS: 0x%02x\n", __func__, lock);
+	*status = 0;
+
+	if (signal > 10)
+		*status |= FE_HAS_SIGNAL;
+
+	if (lock & 0x2)
+		*status |= FE_HAS_CARRIER;
+
+	if (lock & 0x20)
+		*status |= FE_HAS_VITERBI;
+
+	if (lock & 0x40)
+		*status |= FE_HAS_SYNC;
+
+	if ((lock & 0x7b) == 0x7b)
+		*status |= FE_HAS_LOCK;
+
+	return 0;
+}
+
+static int si21_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
+{
+	struct si21xx_state *state = fe->demodulator_priv;
+
+	/*status = si21_readreg(state, ANALOG_AGC_POWER_LEVEL_REG,
+						(u8*)agclevel, 0x01);*/
+
+	u16 signal = (3 * si21_readreg(state, 0x27) *
+					si21_readreg(state, 0x28));
+
+	dprintk("%s : AGCPWR: 0x%02x%02x, signal=0x%04x\n", __func__,
+		si21_readreg(state, 0x27),
+		si21_readreg(state, 0x28), (int) signal);
+
+	signal  <<= 4;
+	*strength = signal;
+
+	return 0;
+}
+
+static int si21_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+	struct si21xx_state *state = fe->demodulator_priv;
+
+	dprintk("%s\n", __func__);
+
+	if (state->errmode != STATUS_BER)
+		return 0;
+
+	*ber = (si21_readreg(state, 0x1d) << 8) |
+				si21_readreg(state, 0x1e);
+
+	return 0;
+}
+
+static int si21_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+	struct si21xx_state *state = fe->demodulator_priv;
+
+	s32 xsnr = 0xffff - ((si21_readreg(state, 0x24) << 8) |
+					si21_readreg(state, 0x25));
+	xsnr = 3 * (xsnr - 0xa100);
+	*snr = (xsnr > 0xffff) ? 0xffff : (xsnr < 0) ? 0 : xsnr;
+
+	dprintk("%s\n", __func__);
+
+	return 0;
+}
+
+static int si21_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+	struct si21xx_state *state = fe->demodulator_priv;
+
+	dprintk("%s\n", __func__);
+
+	if (state->errmode != STATUS_UCBLOCKS)
+		*ucblocks = 0;
+	else
+		*ucblocks = (si21_readreg(state, 0x1d) << 8) |
+					si21_readreg(state, 0x1e);
+
+	return 0;
+}
+
+/*	initiates a channel acquisition sequence
+	using the specified symbol rate and code rate */
+static int si21xx_setacquire(struct dvb_frontend *fe, int symbrate,
+						fe_code_rate_t crate)
+{
+
+	struct si21xx_state *state = fe->demodulator_priv;
+	u8 coderates[] = {
+				0x0, 0x01, 0x02, 0x04, 0x00,
+				0x8, 0x10, 0x20, 0x00, 0x3f
+	};
+
+	u8 coderate_ptr;
+	int status;
+	u8 start_acq = 0x80;
+	u8 reg, regs[3];
+
+	dprintk("%s\n", __func__);
+
+	status = PASS;
+	coderate_ptr = coderates[crate];
+
+	si21xx_set_symbolrate(fe, symbrate);
+
+	/* write code rates to use in the Viterbi search */
+	status |= si21_writeregs(state,
+				VIT_SRCH_CTRL_REG_1,
+				&coderate_ptr, 0x01);
+
+	/* clear acq_start bit */
+	status |= si21_readregs(state, ACQ_CTRL_REG_2, &reg, 0x01);
+	reg &= ~start_acq;
+	status |= si21_writeregs(state, ACQ_CTRL_REG_2, &reg, 0x01);
+
+	/* use new Carrier Frequency Offset Estimator (QuickLock) */
+	regs[0] = 0xCB;
+	regs[1] = 0x40;
+	regs[2] = 0xCB;
+
+	status |= si21_writeregs(state,
+				TWO_DB_BNDWDTH_THRSHLD_REG,
+				&regs[0], 0x03);
+	reg = 0x56;
+	status |= si21_writeregs(state,
+				LSA_CTRL_REG_1, &reg, 1);
+	reg = 0x05;
+	status |= si21_writeregs(state,
+				BLIND_SCAN_CTRL_REG, &reg, 1);
+	/* start automatic acq */
+	status |= si21_writeregs(state,
+				ACQ_CTRL_REG_2, &start_acq, 0x01);
+
+	return status;
+}
+
+static int si21xx_set_frontend(struct dvb_frontend *fe)
+{
+	struct si21xx_state *state = fe->demodulator_priv;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+
+	/* freq		Channel carrier frequency in KHz (i.e. 1550000 KHz)
+	 datarate	Channel symbol rate in Sps (i.e. 22500000 Sps)*/
+
+	/* in MHz */
+	unsigned char coarse_tune_freq;
+	int fine_tune_freq;
+	unsigned char sample_rate = 0;
+	/* boolean */
+	bool inband_interferer_ind;
+
+	/* INTERMEDIATE VALUES */
+	int icoarse_tune_freq; /* MHz */
+	int ifine_tune_freq; /* MHz */
+	unsigned int band_high;
+	unsigned int band_low;
+	unsigned int x1;
+	unsigned int x2;
+	int i;
+	bool inband_interferer_div2[ALLOWABLE_FS_COUNT];
+	bool inband_interferer_div4[ALLOWABLE_FS_COUNT];
+	int status;
+
+	/* allowable sample rates for ADC in MHz */
+	int afs[ALLOWABLE_FS_COUNT] = { 200, 192, 193, 194, 195,
+					196, 204, 205, 206, 207
+	};
+	/* in MHz */
+	int if_limit_high;
+	int if_limit_low;
+	int lnb_lo;
+	int lnb_uncertanity;
+
+	int rf_freq;
+	int data_rate;
+	unsigned char regs[4];
+
+	dprintk("%s : FE_SET_FRONTEND\n", __func__);
+
+	if (c->delivery_system != SYS_DVBS) {
+			dprintk("%s: unsupported delivery system selected (%d)\n",
+				__func__, c->delivery_system);
+			return -EOPNOTSUPP;
+	}
+
+	for (i = 0; i < ALLOWABLE_FS_COUNT; ++i)
+		inband_interferer_div2[i] = inband_interferer_div4[i] = false;
+
+	if_limit_high = -700000;
+	if_limit_low = -100000;
+	/* in MHz */
+	lnb_lo = 0;
+	lnb_uncertanity = 0;
+
+	rf_freq = 10 * c->frequency ;
+	data_rate = c->symbol_rate / 100;
+
+	status = PASS;
+
+	band_low = (rf_freq - lnb_lo) - ((lnb_uncertanity * 200)
+					+ (data_rate * 135)) / 200;
+
+	band_high = (rf_freq - lnb_lo) + ((lnb_uncertanity * 200)
+					+ (data_rate * 135)) / 200;
+
+
+	icoarse_tune_freq = 100000 *
+				(((rf_freq - lnb_lo) -
+					(if_limit_low + if_limit_high) / 2)
+								/ 100000);
+
+	ifine_tune_freq = (rf_freq - lnb_lo) - icoarse_tune_freq ;
+
+	for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) {
+		x1 = ((rf_freq - lnb_lo) / (afs[i] * 2500)) *
+					(afs[i] * 2500) + afs[i] * 2500;
+
+		x2 = ((rf_freq - lnb_lo) / (afs[i] * 2500)) *
+							(afs[i] * 2500);
+
+		if (((band_low < x1) && (x1 < band_high)) ||
+					((band_low < x2) && (x2 < band_high)))
+					inband_interferer_div4[i] = true;
+
+	}
+
+	for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) {
+		x1 = ((rf_freq - lnb_lo) / (afs[i] * 5000)) *
+					(afs[i] * 5000) + afs[i] * 5000;
+
+		x2 = ((rf_freq - lnb_lo) / (afs[i] * 5000)) *
+					(afs[i] * 5000);
+
+		if (((band_low < x1) && (x1 < band_high)) ||
+					((band_low < x2) && (x2 < band_high)))
+					inband_interferer_div2[i] = true;
+	}
+
+	inband_interferer_ind = true;
+	for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) {
+		if (inband_interferer_div2[i] || inband_interferer_div4[i]) {
+			inband_interferer_ind = false;
+			break;
+		}
+	}
+
+	if (inband_interferer_ind) {
+		for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) {
+			if (!inband_interferer_div2[i]) {
+				sample_rate = (u8) afs[i];
+				break;
+			}
+		}
+	} else {
+		for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) {
+			if ((inband_interferer_div2[i] ||
+			     !inband_interferer_div4[i])) {
+				sample_rate = (u8) afs[i];
+				break;
+			}
+		}
+
+	}
+
+	if (sample_rate > 207 || sample_rate < 192)
+		sample_rate = 200;
+
+	fine_tune_freq = ((0x4000 * (ifine_tune_freq / 10)) /
+					((sample_rate) * 1000));
+
+	coarse_tune_freq = (u8)(icoarse_tune_freq / 100000);
+
+	regs[0] = sample_rate;
+	regs[1] = coarse_tune_freq;
+	regs[2] = fine_tune_freq & 0xFF;
+	regs[3] = fine_tune_freq >> 8 & 0xFF;
+
+	status |= si21_writeregs(state, PLL_DIVISOR_REG, &regs[0], 0x04);
+
+	state->fs = sample_rate;/*ADC MHz*/
+	si21xx_setacquire(fe, c->symbol_rate, c->fec_inner);
+
+	return 0;
+}
+
+static int si21xx_sleep(struct dvb_frontend *fe)
+{
+	struct si21xx_state *state = fe->demodulator_priv;
+	u8 regdata;
+
+	dprintk("%s\n", __func__);
+
+	si21_readregs(state, SYSTEM_MODE_REG, &regdata, 0x01);
+	regdata |= 1 << 6;
+	si21_writeregs(state, SYSTEM_MODE_REG, &regdata, 0x01);
+	state->initialised = 0;
+
+	return 0;
+}
+
+static void si21xx_release(struct dvb_frontend *fe)
+{
+	struct si21xx_state *state = fe->demodulator_priv;
+
+	dprintk("%s\n", __func__);
+
+	kfree(state);
+}
+
+static struct dvb_frontend_ops si21xx_ops = {
+	.delsys = { SYS_DVBS },
+	.info = {
+		.name			= "SL SI21XX DVB-S",
+		.frequency_min		= 950000,
+		.frequency_max		= 2150000,
+		.frequency_stepsize	= 125,	 /* kHz for QPSK frontends */
+		.frequency_tolerance	= 0,
+		.symbol_rate_min	= 1000000,
+		.symbol_rate_max	= 45000000,
+		.symbol_rate_tolerance	= 500,	/* ppm */
+		.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_FEC_AUTO
+	},
+
+	.release = si21xx_release,
+	.init = si21xx_init,
+	.sleep = si21xx_sleep,
+	.write = si21_write,
+	.read_status = si21_read_status,
+	.read_ber = si21_read_ber,
+	.read_signal_strength = si21_read_signal_strength,
+	.read_snr = si21_read_snr,
+	.read_ucblocks = si21_read_ucblocks,
+	.diseqc_send_master_cmd = si21xx_send_diseqc_msg,
+	.diseqc_send_burst = si21xx_send_diseqc_burst,
+	.set_tone = si21xx_set_tone,
+	.set_voltage = si21xx_set_voltage,
+
+	.set_frontend = si21xx_set_frontend,
+};
+
+struct dvb_frontend *si21xx_attach(const struct si21xx_config *config,
+						struct i2c_adapter *i2c)
+{
+	struct si21xx_state *state = NULL;
+	int id;
+
+	dprintk("%s\n", __func__);
+
+	/* allocate memory for the internal state */
+	state = kzalloc(sizeof(struct si21xx_state), GFP_KERNEL);
+	if (state == NULL)
+		goto error;
+
+	/* setup the state */
+	state->config = config;
+	state->i2c = i2c;
+	state->initialised = 0;
+	state->errmode = STATUS_BER;
+
+	/* check if the demod is there */
+	id = si21_readreg(state, SYSTEM_MODE_REG);
+	si21_writereg(state, SYSTEM_MODE_REG, id | 0x40); /* standby off */
+	msleep(200);
+	id = si21_readreg(state, 0x00);
+
+	/* register 0x00 contains:
+		0x34 for SI2107
+		0x24 for SI2108
+		0x14 for SI2109
+		0x04 for SI2110
+	*/
+	if (id != 0x04 && id != 0x14)
+		goto error;
+
+	/* create dvb_frontend */
+	memcpy(&state->frontend.ops, &si21xx_ops,
+					sizeof(struct dvb_frontend_ops));
+	state->frontend.demodulator_priv = state;
+	return &state->frontend;
+
+error:
+	kfree(state);
+	return NULL;
+}
+EXPORT_SYMBOL(si21xx_attach);
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+
+MODULE_DESCRIPTION("SL SI21XX DVB Demodulator driver");
+MODULE_AUTHOR("Igor M. Liplianin");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb-frontends/si21xx.h b/drivers/media/dvb-frontends/si21xx.h
new file mode 100644
index 0000000..141b5b8
--- /dev/null
+++ b/drivers/media/dvb-frontends/si21xx.h
@@ -0,0 +1,37 @@
+#ifndef SI21XX_H
+#define SI21XX_H
+
+#include <linux/dvb/frontend.h>
+#include "dvb_frontend.h"
+
+struct si21xx_config {
+	/* the demodulator's i2c address */
+	u8 demod_address;
+
+	/* minimum delay before retuning */
+	int min_delay_ms;
+};
+
+#if defined(CONFIG_DVB_SI21XX) || \
+		(defined(CONFIG_DVB_SI21XX_MODULE) && defined(MODULE))
+extern struct dvb_frontend *si21xx_attach(const struct si21xx_config *config,
+						struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend *si21xx_attach(
+		const struct si21xx_config *config, struct i2c_adapter *i2c)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif
+
+static inline int si21xx_writeregister(struct dvb_frontend *fe, u8 reg, u8 val)
+{
+	int r = 0;
+	u8 buf[] = {reg, val};
+	if (fe->ops.write)
+		r = fe->ops.write(fe, buf, 2);
+	return r;
+}
+
+#endif
diff --git a/drivers/media/dvb-frontends/sp8870.c b/drivers/media/dvb-frontends/sp8870.c
new file mode 100644
index 0000000..e37274c
--- /dev/null
+++ b/drivers/media/dvb-frontends/sp8870.c
@@ -0,0 +1,620 @@
+/*
+    Driver for Spase SP8870 demodulator
+
+    Copyright (C) 1999 Juergen Peitz
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the 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.
+
+*/
+/*
+ * This driver needs external firmware. Please use the command
+ * "<kerneldir>/Documentation/dvb/get_dvb_firmware alps_tdlb7" to
+ * download/extract it, and then copy it to /usr/lib/hotplug/firmware
+ * or /lib/firmware (depending on configuration of firmware hotplug).
+ */
+#define SP8870_DEFAULT_FIRMWARE "dvb-fe-sp8870.fw"
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/firmware.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+
+#include "dvb_frontend.h"
+#include "sp8870.h"
+
+
+struct sp8870_state {
+
+	struct i2c_adapter* i2c;
+
+	const struct sp8870_config* config;
+
+	struct dvb_frontend frontend;
+
+	/* demodulator private data */
+	u8 initialised:1;
+};
+
+static int debug;
+#define dprintk(args...) \
+	do { \
+		if (debug) printk(KERN_DEBUG "sp8870: " args); \
+	} while (0)
+
+/* firmware size for sp8870 */
+#define SP8870_FIRMWARE_SIZE 16382
+
+/* starting point for firmware in file 'Sc_main.mc' */
+#define SP8870_FIRMWARE_OFFSET 0x0A
+
+static int sp8870_writereg (struct sp8870_state* state, u16 reg, u16 data)
+{
+	u8 buf [] = { reg >> 8, reg & 0xff, data >> 8, data & 0xff };
+	struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 4 };
+	int err;
+
+	if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
+		dprintk ("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __func__, err, reg, data);
+		return -EREMOTEIO;
+	}
+
+	return 0;
+}
+
+static int sp8870_readreg (struct sp8870_state* state, u16 reg)
+{
+	int ret;
+	u8 b0 [] = { reg >> 8 , reg & 0xff };
+	u8 b1 [] = { 0, 0 };
+	struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 2 },
+			   { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 2 } };
+
+	ret = i2c_transfer (state->i2c, msg, 2);
+
+	if (ret != 2) {
+		dprintk("%s: readreg error (ret == %i)\n", __func__, ret);
+		return -1;
+	}
+
+	return (b1[0] << 8 | b1[1]);
+}
+
+static int sp8870_firmware_upload (struct sp8870_state* state, const struct firmware *fw)
+{
+	struct i2c_msg msg;
+	const char *fw_buf = fw->data;
+	int fw_pos;
+	u8 tx_buf[255];
+	int tx_len;
+	int err = 0;
+
+	dprintk ("%s: ...\n", __func__);
+
+	if (fw->size < SP8870_FIRMWARE_SIZE + SP8870_FIRMWARE_OFFSET)
+		return -EINVAL;
+
+	// system controller stop
+	sp8870_writereg(state, 0x0F00, 0x0000);
+
+	// instruction RAM register hiword
+	sp8870_writereg(state, 0x8F08, ((SP8870_FIRMWARE_SIZE / 2) & 0xFFFF));
+
+	// instruction RAM MWR
+	sp8870_writereg(state, 0x8F0A, ((SP8870_FIRMWARE_SIZE / 2) >> 16));
+
+	// do firmware upload
+	fw_pos = SP8870_FIRMWARE_OFFSET;
+	while (fw_pos < SP8870_FIRMWARE_SIZE + SP8870_FIRMWARE_OFFSET){
+		tx_len = (fw_pos <= SP8870_FIRMWARE_SIZE + SP8870_FIRMWARE_OFFSET - 252) ? 252 : SP8870_FIRMWARE_SIZE + SP8870_FIRMWARE_OFFSET - fw_pos;
+		// write register 0xCF0A
+		tx_buf[0] = 0xCF;
+		tx_buf[1] = 0x0A;
+		memcpy(&tx_buf[2], fw_buf + fw_pos, tx_len);
+		msg.addr = state->config->demod_address;
+		msg.flags = 0;
+		msg.buf = tx_buf;
+		msg.len = tx_len + 2;
+		if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
+			printk("%s: firmware upload failed!\n", __func__);
+			printk ("%s: i2c error (err == %i)\n", __func__, err);
+			return err;
+		}
+		fw_pos += tx_len;
+	}
+
+	dprintk ("%s: done!\n", __func__);
+	return 0;
+};
+
+static void sp8870_microcontroller_stop (struct sp8870_state* state)
+{
+	sp8870_writereg(state, 0x0F08, 0x000);
+	sp8870_writereg(state, 0x0F09, 0x000);
+
+	// microcontroller STOP
+	sp8870_writereg(state, 0x0F00, 0x000);
+}
+
+static void sp8870_microcontroller_start (struct sp8870_state* state)
+{
+	sp8870_writereg(state, 0x0F08, 0x000);
+	sp8870_writereg(state, 0x0F09, 0x000);
+
+	// microcontroller START
+	sp8870_writereg(state, 0x0F00, 0x001);
+	// not documented but if we don't read 0x0D01 out here
+	// we don't get a correct data valid signal
+	sp8870_readreg(state, 0x0D01);
+}
+
+static int sp8870_read_data_valid_signal(struct sp8870_state* state)
+{
+	return (sp8870_readreg(state, 0x0D02) > 0);
+}
+
+static int configure_reg0xc05 (struct dtv_frontend_properties *p, u16 *reg0xc05)
+{
+	int known_parameters = 1;
+
+	*reg0xc05 = 0x000;
+
+	switch (p->modulation) {
+	case QPSK:
+		break;
+	case QAM_16:
+		*reg0xc05 |= (1 << 10);
+		break;
+	case QAM_64:
+		*reg0xc05 |= (2 << 10);
+		break;
+	case QAM_AUTO:
+		known_parameters = 0;
+		break;
+	default:
+		return -EINVAL;
+	};
+
+	switch (p->hierarchy) {
+	case HIERARCHY_NONE:
+		break;
+	case HIERARCHY_1:
+		*reg0xc05 |= (1 << 7);
+		break;
+	case HIERARCHY_2:
+		*reg0xc05 |= (2 << 7);
+		break;
+	case HIERARCHY_4:
+		*reg0xc05 |= (3 << 7);
+		break;
+	case HIERARCHY_AUTO:
+		known_parameters = 0;
+		break;
+	default:
+		return -EINVAL;
+	};
+
+	switch (p->code_rate_HP) {
+	case FEC_1_2:
+		break;
+	case FEC_2_3:
+		*reg0xc05 |= (1 << 3);
+		break;
+	case FEC_3_4:
+		*reg0xc05 |= (2 << 3);
+		break;
+	case FEC_5_6:
+		*reg0xc05 |= (3 << 3);
+		break;
+	case FEC_7_8:
+		*reg0xc05 |= (4 << 3);
+		break;
+	case FEC_AUTO:
+		known_parameters = 0;
+		break;
+	default:
+		return -EINVAL;
+	};
+
+	if (known_parameters)
+		*reg0xc05 |= (2 << 1);	/* use specified parameters */
+	else
+		*reg0xc05 |= (1 << 1);	/* enable autoprobing */
+
+	return 0;
+}
+
+static int sp8870_wake_up(struct sp8870_state* state)
+{
+	// enable TS output and interface pins
+	return sp8870_writereg(state, 0xC18, 0x00D);
+}
+
+static int sp8870_set_frontend_parameters(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct sp8870_state* state = fe->demodulator_priv;
+	int  err;
+	u16 reg0xc05;
+
+	if ((err = configure_reg0xc05(p, &reg0xc05)))
+		return err;
+
+	// system controller stop
+	sp8870_microcontroller_stop(state);
+
+	// set tuner parameters
+	if (fe->ops.tuner_ops.set_params) {
+		fe->ops.tuner_ops.set_params(fe);
+		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+	}
+
+	// sample rate correction bit [23..17]
+	sp8870_writereg(state, 0x0319, 0x000A);
+
+	// sample rate correction bit [16..0]
+	sp8870_writereg(state, 0x031A, 0x0AAB);
+
+	// integer carrier offset
+	sp8870_writereg(state, 0x0309, 0x0400);
+
+	// fractional carrier offset
+	sp8870_writereg(state, 0x030A, 0x0000);
+
+	// filter for 6/7/8 Mhz channel
+	if (p->bandwidth_hz == 6000000)
+		sp8870_writereg(state, 0x0311, 0x0002);
+	else if (p->bandwidth_hz == 7000000)
+		sp8870_writereg(state, 0x0311, 0x0001);
+	else
+		sp8870_writereg(state, 0x0311, 0x0000);
+
+	// scan order: 2k first = 0x0000, 8k first = 0x0001
+	if (p->transmission_mode == TRANSMISSION_MODE_2K)
+		sp8870_writereg(state, 0x0338, 0x0000);
+	else
+		sp8870_writereg(state, 0x0338, 0x0001);
+
+	sp8870_writereg(state, 0xc05, reg0xc05);
+
+	// read status reg in order to clear pending irqs
+	sp8870_readreg(state, 0x200);
+
+	// system controller start
+	sp8870_microcontroller_start(state);
+
+	return 0;
+}
+
+static int sp8870_init (struct dvb_frontend* fe)
+{
+	struct sp8870_state* state = fe->demodulator_priv;
+	const struct firmware *fw = NULL;
+
+	sp8870_wake_up(state);
+	if (state->initialised) return 0;
+	state->initialised = 1;
+
+	dprintk ("%s\n", __func__);
+
+
+	/* request the firmware, this will block until someone uploads it */
+	printk("sp8870: waiting for firmware upload (%s)...\n", SP8870_DEFAULT_FIRMWARE);
+	if (state->config->request_firmware(fe, &fw, SP8870_DEFAULT_FIRMWARE)) {
+		printk("sp8870: no firmware upload (timeout or file not found?)\n");
+		return -EIO;
+	}
+
+	if (sp8870_firmware_upload(state, fw)) {
+		printk("sp8870: writing firmware to device failed\n");
+		release_firmware(fw);
+		return -EIO;
+	}
+	release_firmware(fw);
+	printk("sp8870: firmware upload complete\n");
+
+	/* enable TS output and interface pins */
+	sp8870_writereg(state, 0xc18, 0x00d);
+
+	// system controller stop
+	sp8870_microcontroller_stop(state);
+
+	// ADC mode
+	sp8870_writereg(state, 0x0301, 0x0003);
+
+	// Reed Solomon parity bytes passed to output
+	sp8870_writereg(state, 0x0C13, 0x0001);
+
+	// MPEG clock is suppressed if no valid data
+	sp8870_writereg(state, 0x0C14, 0x0001);
+
+	/* bit 0x010: enable data valid signal */
+	sp8870_writereg(state, 0x0D00, 0x010);
+	sp8870_writereg(state, 0x0D01, 0x000);
+
+	return 0;
+}
+
+static int sp8870_read_status (struct dvb_frontend* fe, fe_status_t * fe_status)
+{
+	struct sp8870_state* state = fe->demodulator_priv;
+	int status;
+	int signal;
+
+	*fe_status = 0;
+
+	status = sp8870_readreg (state, 0x0200);
+	if (status < 0)
+		return -EIO;
+
+	signal = sp8870_readreg (state, 0x0303);
+	if (signal < 0)
+		return -EIO;
+
+	if (signal > 0x0F)
+		*fe_status |= FE_HAS_SIGNAL;
+	if (status & 0x08)
+		*fe_status |= FE_HAS_SYNC;
+	if (status & 0x04)
+		*fe_status |= FE_HAS_LOCK | FE_HAS_CARRIER | FE_HAS_VITERBI;
+
+	return 0;
+}
+
+static int sp8870_read_ber (struct dvb_frontend* fe, u32 * ber)
+{
+	struct sp8870_state* state = fe->demodulator_priv;
+	int ret;
+	u32 tmp;
+
+	*ber = 0;
+
+	ret = sp8870_readreg(state, 0xC08);
+	if (ret < 0)
+		return -EIO;
+
+	tmp = ret & 0x3F;
+
+	ret = sp8870_readreg(state, 0xC07);
+	if (ret < 0)
+		return -EIO;
+
+	 tmp = ret << 6;
+
+	if (tmp >= 0x3FFF0)
+		tmp = ~0;
+
+	*ber = tmp;
+
+	return 0;
+}
+
+static int sp8870_read_signal_strength(struct dvb_frontend* fe,  u16 * signal)
+{
+	struct sp8870_state* state = fe->demodulator_priv;
+	int ret;
+	u16 tmp;
+
+	*signal = 0;
+
+	ret = sp8870_readreg (state, 0x306);
+	if (ret < 0)
+		return -EIO;
+
+	tmp = ret << 8;
+
+	ret = sp8870_readreg (state, 0x303);
+	if (ret < 0)
+		return -EIO;
+
+	tmp |= ret;
+
+	if (tmp)
+		*signal = 0xFFFF - tmp;
+
+	return 0;
+}
+
+static int sp8870_read_uncorrected_blocks (struct dvb_frontend* fe, u32* ublocks)
+{
+	struct sp8870_state* state = fe->demodulator_priv;
+	int ret;
+
+	*ublocks = 0;
+
+	ret = sp8870_readreg(state, 0xC0C);
+	if (ret < 0)
+		return -EIO;
+
+	if (ret == 0xFFFF)
+		ret = ~0;
+
+	*ublocks = ret;
+
+	return 0;
+}
+
+/* number of trials to recover from lockup */
+#define MAXTRIALS 5
+/* maximum checks for data valid signal */
+#define MAXCHECKS 100
+
+/* only for debugging: counter for detected lockups */
+static int lockups;
+/* only for debugging: counter for channel switches */
+static int switches;
+
+static int sp8870_set_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct sp8870_state* state = fe->demodulator_priv;
+
+	/*
+	    The firmware of the sp8870 sometimes locks up after setting frontend parameters.
+	    We try to detect this by checking the data valid signal.
+	    If it is not set after MAXCHECKS we try to recover the lockup by setting
+	    the frontend parameters again.
+	*/
+
+	int err = 0;
+	int valid = 0;
+	int trials = 0;
+	int check_count = 0;
+
+	dprintk("%s: frequency = %i\n", __func__, p->frequency);
+
+	for (trials = 1; trials <= MAXTRIALS; trials++) {
+
+		err = sp8870_set_frontend_parameters(fe);
+		if (err)
+			return err;
+
+		for (check_count = 0; check_count < MAXCHECKS; check_count++) {
+//			valid = ((sp8870_readreg(i2c, 0x0200) & 4) == 0);
+			valid = sp8870_read_data_valid_signal(state);
+			if (valid) {
+				dprintk("%s: delay = %i usec\n",
+					__func__, check_count * 10);
+				break;
+			}
+			udelay(10);
+		}
+		if (valid)
+			break;
+	}
+
+	if (!valid) {
+		printk("%s: firmware crash!!!!!!\n", __func__);
+		return -EIO;
+	}
+
+	if (debug) {
+		if (valid) {
+			if (trials > 1) {
+				printk("%s: firmware lockup!!!\n", __func__);
+				printk("%s: recovered after %i trial(s))\n",  __func__, trials - 1);
+				lockups++;
+			}
+		}
+		switches++;
+		printk("%s: switches = %i lockups = %i\n", __func__, switches, lockups);
+	}
+
+	return 0;
+}
+
+static int sp8870_sleep(struct dvb_frontend* fe)
+{
+	struct sp8870_state* state = fe->demodulator_priv;
+
+	// tristate TS output and disable interface pins
+	return sp8870_writereg(state, 0xC18, 0x000);
+}
+
+static int sp8870_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings)
+{
+	fesettings->min_delay_ms = 350;
+	fesettings->step_size = 0;
+	fesettings->max_drift = 0;
+	return 0;
+}
+
+static int sp8870_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+{
+	struct sp8870_state* state = fe->demodulator_priv;
+
+	if (enable) {
+		return sp8870_writereg(state, 0x206, 0x001);
+	} else {
+		return sp8870_writereg(state, 0x206, 0x000);
+	}
+}
+
+static void sp8870_release(struct dvb_frontend* fe)
+{
+	struct sp8870_state* state = fe->demodulator_priv;
+	kfree(state);
+}
+
+static struct dvb_frontend_ops sp8870_ops;
+
+struct dvb_frontend* sp8870_attach(const struct sp8870_config* config,
+				   struct i2c_adapter* i2c)
+{
+	struct sp8870_state* state = NULL;
+
+	/* allocate memory for the internal state */
+	state = kzalloc(sizeof(struct sp8870_state), GFP_KERNEL);
+	if (state == NULL) goto error;
+
+	/* setup the state */
+	state->config = config;
+	state->i2c = i2c;
+	state->initialised = 0;
+
+	/* check if the demod is there */
+	if (sp8870_readreg(state, 0x0200) < 0) goto error;
+
+	/* create dvb_frontend */
+	memcpy(&state->frontend.ops, &sp8870_ops, sizeof(struct dvb_frontend_ops));
+	state->frontend.demodulator_priv = state;
+	return &state->frontend;
+
+error:
+	kfree(state);
+	return NULL;
+}
+
+static struct dvb_frontend_ops sp8870_ops = {
+	.delsys = { SYS_DVBT },
+	.info = {
+		.name			= "Spase SP8870 DVB-T",
+		.frequency_min		= 470000000,
+		.frequency_max		= 860000000,
+		.frequency_stepsize	= 166666,
+		.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_FEC_AUTO |
+					  FE_CAN_QPSK | FE_CAN_QAM_16 |
+					  FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
+					  FE_CAN_HIERARCHY_AUTO |  FE_CAN_RECOVER
+	},
+
+	.release = sp8870_release,
+
+	.init = sp8870_init,
+	.sleep = sp8870_sleep,
+	.i2c_gate_ctrl = sp8870_i2c_gate_ctrl,
+
+	.set_frontend = sp8870_set_frontend,
+	.get_tune_settings = sp8870_get_tune_settings,
+
+	.read_status = sp8870_read_status,
+	.read_ber = sp8870_read_ber,
+	.read_signal_strength = sp8870_read_signal_strength,
+	.read_ucblocks = sp8870_read_uncorrected_blocks,
+};
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+
+MODULE_DESCRIPTION("Spase SP8870 DVB-T Demodulator driver");
+MODULE_AUTHOR("Juergen Peitz");
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(sp8870_attach);
diff --git a/drivers/media/dvb-frontends/sp8870.h b/drivers/media/dvb-frontends/sp8870.h
new file mode 100644
index 0000000..a764a79
--- /dev/null
+++ b/drivers/media/dvb-frontends/sp8870.h
@@ -0,0 +1,50 @@
+/*
+    Driver for Spase SP8870 demodulator
+
+    Copyright (C) 1999 Juergen Peitz
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the 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 SP8870_H
+#define SP8870_H
+
+#include <linux/dvb/frontend.h>
+#include <linux/firmware.h>
+
+struct sp8870_config
+{
+	/* the demodulator's i2c address */
+	u8 demod_address;
+
+	/* request firmware for device */
+	int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name);
+};
+
+#if defined(CONFIG_DVB_SP8870) || (defined(CONFIG_DVB_SP8870_MODULE) && defined(MODULE))
+extern struct dvb_frontend* sp8870_attach(const struct sp8870_config* config,
+					  struct i2c_adapter* i2c);
+#else
+static inline struct dvb_frontend* sp8870_attach(const struct sp8870_config* config,
+					  struct i2c_adapter* i2c)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif // CONFIG_DVB_SP8870
+
+#endif // SP8870_H
diff --git a/drivers/media/dvb-frontends/sp887x.c b/drivers/media/dvb-frontends/sp887x.c
new file mode 100644
index 0000000..f4096cc
--- /dev/null
+++ b/drivers/media/dvb-frontends/sp887x.c
@@ -0,0 +1,629 @@
+/*
+   Driver for the Spase sp887x demodulator
+*/
+
+/*
+ * This driver needs external firmware. Please use the command
+ * "<kerneldir>/Documentation/dvb/get_dvb_firmware sp887x" to
+ * download/extract it, and then copy it to /usr/lib/hotplug/firmware
+ * or /lib/firmware (depending on configuration of firmware hotplug).
+ */
+#define SP887X_DEFAULT_FIRMWARE "dvb-fe-sp887x.fw"
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/firmware.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+
+#include "dvb_frontend.h"
+#include "sp887x.h"
+
+
+struct sp887x_state {
+	struct i2c_adapter* i2c;
+	const struct sp887x_config* config;
+	struct dvb_frontend frontend;
+
+	/* demodulator private data */
+	u8 initialised:1;
+};
+
+static int debug;
+#define dprintk(args...) \
+	do { \
+		if (debug) printk(KERN_DEBUG "sp887x: " args); \
+	} while (0)
+
+static int i2c_writebytes (struct sp887x_state* state, u8 *buf, u8 len)
+{
+	struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = len };
+	int err;
+
+	if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
+		printk ("%s: i2c write error (addr %02x, err == %i)\n",
+			__func__, state->config->demod_address, err);
+		return -EREMOTEIO;
+	}
+
+	return 0;
+}
+
+static int sp887x_writereg (struct sp887x_state* state, u16 reg, u16 data)
+{
+	u8 b0 [] = { reg >> 8 , reg & 0xff, data >> 8, data & 0xff };
+	struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 4 };
+	int ret;
+
+	if ((ret = i2c_transfer(state->i2c, &msg, 1)) != 1) {
+		/**
+		 *  in case of soft reset we ignore ACK errors...
+		 */
+		if (!(reg == 0xf1a && data == 0x000 &&
+			(ret == -EREMOTEIO || ret == -EFAULT)))
+		{
+			printk("%s: writereg error "
+			       "(reg %03x, data %03x, ret == %i)\n",
+			       __func__, reg & 0xffff, data & 0xffff, ret);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static int sp887x_readreg (struct sp887x_state* state, u16 reg)
+{
+	u8 b0 [] = { reg >> 8 , reg & 0xff };
+	u8 b1 [2];
+	int ret;
+	struct i2c_msg msg[] = {{ .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 2 },
+			 { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 2 }};
+
+	if ((ret = i2c_transfer(state->i2c, msg, 2)) != 2) {
+		printk("%s: readreg error (ret == %i)\n", __func__, ret);
+		return -1;
+	}
+
+	return (((b1[0] << 8) | b1[1]) & 0xfff);
+}
+
+static void sp887x_microcontroller_stop (struct sp887x_state* state)
+{
+	dprintk("%s\n", __func__);
+	sp887x_writereg(state, 0xf08, 0x000);
+	sp887x_writereg(state, 0xf09, 0x000);
+
+	/* microcontroller STOP */
+	sp887x_writereg(state, 0xf00, 0x000);
+}
+
+static void sp887x_microcontroller_start (struct sp887x_state* state)
+{
+	dprintk("%s\n", __func__);
+	sp887x_writereg(state, 0xf08, 0x000);
+	sp887x_writereg(state, 0xf09, 0x000);
+
+	/* microcontroller START */
+	sp887x_writereg(state, 0xf00, 0x001);
+}
+
+static void sp887x_setup_agc (struct sp887x_state* state)
+{
+	/* setup AGC parameters */
+	dprintk("%s\n", __func__);
+	sp887x_writereg(state, 0x33c, 0x054);
+	sp887x_writereg(state, 0x33b, 0x04c);
+	sp887x_writereg(state, 0x328, 0x000);
+	sp887x_writereg(state, 0x327, 0x005);
+	sp887x_writereg(state, 0x326, 0x001);
+	sp887x_writereg(state, 0x325, 0x001);
+	sp887x_writereg(state, 0x324, 0x001);
+	sp887x_writereg(state, 0x318, 0x050);
+	sp887x_writereg(state, 0x317, 0x3fe);
+	sp887x_writereg(state, 0x316, 0x001);
+	sp887x_writereg(state, 0x313, 0x005);
+	sp887x_writereg(state, 0x312, 0x002);
+	sp887x_writereg(state, 0x306, 0x000);
+	sp887x_writereg(state, 0x303, 0x000);
+}
+
+#define BLOCKSIZE 30
+#define FW_SIZE 0x4000
+/**
+ *  load firmware and setup MPEG interface...
+ */
+static int sp887x_initial_setup (struct dvb_frontend* fe, const struct firmware *fw)
+{
+	struct sp887x_state* state = fe->demodulator_priv;
+	u8 buf [BLOCKSIZE+2];
+	int i;
+	int fw_size = fw->size;
+	const unsigned char *mem = fw->data;
+
+	dprintk("%s\n", __func__);
+
+	/* ignore the first 10 bytes, then we expect 0x4000 bytes of firmware */
+	if (fw_size < FW_SIZE+10)
+		return -ENODEV;
+
+	mem = fw->data + 10;
+
+	/* soft reset */
+	sp887x_writereg(state, 0xf1a, 0x000);
+
+	sp887x_microcontroller_stop (state);
+
+	printk ("%s: firmware upload... ", __func__);
+
+	/* setup write pointer to -1 (end of memory) */
+	/* bit 0x8000 in address is set to enable 13bit mode */
+	sp887x_writereg(state, 0x8f08, 0x1fff);
+
+	/* dummy write (wrap around to start of memory) */
+	sp887x_writereg(state, 0x8f0a, 0x0000);
+
+	for (i = 0; i < FW_SIZE; i += BLOCKSIZE) {
+		int c = BLOCKSIZE;
+		int err;
+
+		if (i+c > FW_SIZE)
+			c = FW_SIZE - i;
+
+		/* bit 0x8000 in address is set to enable 13bit mode */
+		/* bit 0x4000 enables multibyte read/write transfers */
+		/* write register is 0xf0a */
+		buf[0] = 0xcf;
+		buf[1] = 0x0a;
+
+		memcpy(&buf[2], mem + i, c);
+
+		if ((err = i2c_writebytes (state, buf, c+2)) < 0) {
+			printk ("failed.\n");
+			printk ("%s: i2c error (err == %i)\n", __func__, err);
+			return err;
+		}
+	}
+
+	/* don't write RS bytes between packets */
+	sp887x_writereg(state, 0xc13, 0x001);
+
+	/* suppress clock if (!data_valid) */
+	sp887x_writereg(state, 0xc14, 0x000);
+
+	/* setup MPEG interface... */
+	sp887x_writereg(state, 0xc1a, 0x872);
+	sp887x_writereg(state, 0xc1b, 0x001);
+	sp887x_writereg(state, 0xc1c, 0x000); /* parallel mode (serial mode == 1) */
+	sp887x_writereg(state, 0xc1a, 0x871);
+
+	/* ADC mode, 2 for MT8872, 3 for SP8870/SP8871 */
+	sp887x_writereg(state, 0x301, 0x002);
+
+	sp887x_setup_agc(state);
+
+	/* bit 0x010: enable data valid signal */
+	sp887x_writereg(state, 0xd00, 0x010);
+	sp887x_writereg(state, 0x0d1, 0x000);
+	return 0;
+};
+
+static int configure_reg0xc05(struct dtv_frontend_properties *p, u16 *reg0xc05)
+{
+	int known_parameters = 1;
+
+	*reg0xc05 = 0x000;
+
+	switch (p->modulation) {
+	case QPSK:
+		break;
+	case QAM_16:
+		*reg0xc05 |= (1 << 10);
+		break;
+	case QAM_64:
+		*reg0xc05 |= (2 << 10);
+		break;
+	case QAM_AUTO:
+		known_parameters = 0;
+		break;
+	default:
+		return -EINVAL;
+	};
+
+	switch (p->hierarchy) {
+	case HIERARCHY_NONE:
+		break;
+	case HIERARCHY_1:
+		*reg0xc05 |= (1 << 7);
+		break;
+	case HIERARCHY_2:
+		*reg0xc05 |= (2 << 7);
+		break;
+	case HIERARCHY_4:
+		*reg0xc05 |= (3 << 7);
+		break;
+	case HIERARCHY_AUTO:
+		known_parameters = 0;
+		break;
+	default:
+		return -EINVAL;
+	};
+
+	switch (p->code_rate_HP) {
+	case FEC_1_2:
+		break;
+	case FEC_2_3:
+		*reg0xc05 |= (1 << 3);
+		break;
+	case FEC_3_4:
+		*reg0xc05 |= (2 << 3);
+		break;
+	case FEC_5_6:
+		*reg0xc05 |= (3 << 3);
+		break;
+	case FEC_7_8:
+		*reg0xc05 |= (4 << 3);
+		break;
+	case FEC_AUTO:
+		known_parameters = 0;
+		break;
+	default:
+		return -EINVAL;
+	};
+
+	if (known_parameters)
+		*reg0xc05 |= (2 << 1);	/* use specified parameters */
+	else
+		*reg0xc05 |= (1 << 1);	/* enable autoprobing */
+
+	return 0;
+}
+
+/**
+ *  estimates division of two 24bit numbers,
+ *  derived from the ves1820/stv0299 driver code
+ */
+static void divide (int n, int d, int *quotient_i, int *quotient_f)
+{
+	unsigned int q, r;
+
+	r = (n % d) << 8;
+	q = (r / d);
+
+	if (quotient_i)
+		*quotient_i = q;
+
+	if (quotient_f) {
+		r = (r % d) << 8;
+		q = (q << 8) | (r / d);
+		r = (r % d) << 8;
+		*quotient_f = (q << 8) | (r / d);
+	}
+}
+
+static void sp887x_correct_offsets (struct sp887x_state* state,
+				    struct dtv_frontend_properties *p,
+				    int actual_freq)
+{
+	static const u32 srate_correction [] = { 1879617, 4544878, 8098561 };
+	int bw_index;
+	int freq_offset = actual_freq - p->frequency;
+	int sysclock = 61003; //[kHz]
+	int ifreq = 36000000;
+	int freq;
+	int frequency_shift;
+
+	switch (p->bandwidth_hz) {
+	default:
+	case 8000000:
+		bw_index = 0;
+		break;
+	case 7000000:
+		bw_index = 1;
+		break;
+	case 6000000:
+		bw_index = 2;
+		break;
+	}
+
+	if (p->inversion == INVERSION_ON)
+		freq = ifreq - freq_offset;
+	else
+		freq = ifreq + freq_offset;
+
+	divide(freq / 333, sysclock, NULL, &frequency_shift);
+
+	if (p->inversion == INVERSION_ON)
+		frequency_shift = -frequency_shift;
+
+	/* sample rate correction */
+	sp887x_writereg(state, 0x319, srate_correction[bw_index] >> 12);
+	sp887x_writereg(state, 0x31a, srate_correction[bw_index] & 0xfff);
+
+	/* carrier offset correction */
+	sp887x_writereg(state, 0x309, frequency_shift >> 12);
+	sp887x_writereg(state, 0x30a, frequency_shift & 0xfff);
+}
+
+static int sp887x_setup_frontend_parameters(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct sp887x_state* state = fe->demodulator_priv;
+	unsigned actual_freq;
+	int err;
+	u16 val, reg0xc05;
+
+	if (p->bandwidth_hz != 8000000 &&
+	    p->bandwidth_hz != 7000000 &&
+	    p->bandwidth_hz != 6000000)
+		return -EINVAL;
+
+	if ((err = configure_reg0xc05(p, &reg0xc05)))
+		return err;
+
+	sp887x_microcontroller_stop(state);
+
+	/* setup the PLL */
+	if (fe->ops.tuner_ops.set_params) {
+		fe->ops.tuner_ops.set_params(fe);
+		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+	}
+	if (fe->ops.tuner_ops.get_frequency) {
+		fe->ops.tuner_ops.get_frequency(fe, &actual_freq);
+		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+	} else {
+		actual_freq = p->frequency;
+	}
+
+	/* read status reg in order to clear <pending irqs */
+	sp887x_readreg(state, 0x200);
+
+	sp887x_correct_offsets(state, p, actual_freq);
+
+	/* filter for 6/7/8 Mhz channel */
+	if (p->bandwidth_hz == 6000000)
+		val = 2;
+	else if (p->bandwidth_hz == 7000000)
+		val = 1;
+	else
+		val = 0;
+
+	sp887x_writereg(state, 0x311, val);
+
+	/* scan order: 2k first = 0, 8k first = 1 */
+	if (p->transmission_mode == TRANSMISSION_MODE_2K)
+		sp887x_writereg(state, 0x338, 0x000);
+	else
+		sp887x_writereg(state, 0x338, 0x001);
+
+	sp887x_writereg(state, 0xc05, reg0xc05);
+
+	if (p->bandwidth_hz == 6000000)
+		val = 2 << 3;
+	else if (p->bandwidth_hz == 7000000)
+		val = 3 << 3;
+	else
+		val = 0 << 3;
+
+	/* enable OFDM and SAW bits as lock indicators in sync register 0xf17,
+	 * optimize algorithm for given bandwidth...
+	 */
+	sp887x_writereg(state, 0xf14, 0x160 | val);
+	sp887x_writereg(state, 0xf15, 0x000);
+
+	sp887x_microcontroller_start(state);
+	return 0;
+}
+
+static int sp887x_read_status(struct dvb_frontend* fe, fe_status_t* status)
+{
+	struct sp887x_state* state = fe->demodulator_priv;
+	u16 snr12 = sp887x_readreg(state, 0xf16);
+	u16 sync0x200 = sp887x_readreg(state, 0x200);
+	u16 sync0xf17 = sp887x_readreg(state, 0xf17);
+
+	*status = 0;
+
+	if (snr12 > 0x00f)
+		*status |= FE_HAS_SIGNAL;
+
+	//if (sync0x200 & 0x004)
+	//	*status |= FE_HAS_SYNC | FE_HAS_CARRIER;
+
+	//if (sync0x200 & 0x008)
+	//	*status |= FE_HAS_VITERBI;
+
+	if ((sync0xf17 & 0x00f) == 0x002) {
+		*status |= FE_HAS_LOCK;
+		*status |= FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_CARRIER;
+	}
+
+	if (sync0x200 & 0x001) {	/* tuner adjustment requested...*/
+		int steps = (sync0x200 >> 4) & 0x00f;
+		if (steps & 0x008)
+			steps = -steps;
+		dprintk("sp887x: implement tuner adjustment (%+i steps)!!\n",
+		       steps);
+	}
+
+	return 0;
+}
+
+static int sp887x_read_ber(struct dvb_frontend* fe, u32* ber)
+{
+	struct sp887x_state* state = fe->demodulator_priv;
+
+	*ber = (sp887x_readreg(state, 0xc08) & 0x3f) |
+	       (sp887x_readreg(state, 0xc07) << 6);
+	sp887x_writereg(state, 0xc08, 0x000);
+	sp887x_writereg(state, 0xc07, 0x000);
+	if (*ber >= 0x3fff0)
+		*ber = ~0;
+
+	return 0;
+}
+
+static int sp887x_read_signal_strength(struct dvb_frontend* fe, u16* strength)
+{
+	struct sp887x_state* state = fe->demodulator_priv;
+
+	u16 snr12 = sp887x_readreg(state, 0xf16);
+	u32 signal = 3 * (snr12 << 4);
+	*strength = (signal < 0xffff) ? signal : 0xffff;
+
+	return 0;
+}
+
+static int sp887x_read_snr(struct dvb_frontend* fe, u16* snr)
+{
+	struct sp887x_state* state = fe->demodulator_priv;
+
+	u16 snr12 = sp887x_readreg(state, 0xf16);
+	*snr = (snr12 << 4) | (snr12 >> 8);
+
+	return 0;
+}
+
+static int sp887x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
+{
+	struct sp887x_state* state = fe->demodulator_priv;
+
+	*ucblocks = sp887x_readreg(state, 0xc0c);
+	if (*ucblocks == 0xfff)
+		*ucblocks = ~0;
+
+	return 0;
+}
+
+static int sp887x_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+{
+	struct sp887x_state* state = fe->demodulator_priv;
+
+	if (enable) {
+		return sp887x_writereg(state, 0x206, 0x001);
+	} else {
+		return sp887x_writereg(state, 0x206, 0x000);
+	}
+}
+
+static int sp887x_sleep(struct dvb_frontend* fe)
+{
+	struct sp887x_state* state = fe->demodulator_priv;
+
+	/* tristate TS output and disable interface pins */
+	sp887x_writereg(state, 0xc18, 0x000);
+
+	return 0;
+}
+
+static int sp887x_init(struct dvb_frontend* fe)
+{
+	struct sp887x_state* state = fe->demodulator_priv;
+	const struct firmware *fw = NULL;
+	int ret;
+
+	if (!state->initialised) {
+		/* request the firmware, this will block until someone uploads it */
+		printk("sp887x: waiting for firmware upload (%s)...\n", SP887X_DEFAULT_FIRMWARE);
+		ret = state->config->request_firmware(fe, &fw, SP887X_DEFAULT_FIRMWARE);
+		if (ret) {
+			printk("sp887x: no firmware upload (timeout or file not found?)\n");
+			return ret;
+		}
+
+		ret = sp887x_initial_setup(fe, fw);
+		release_firmware(fw);
+		if (ret) {
+			printk("sp887x: writing firmware to device failed\n");
+			return ret;
+		}
+		printk("sp887x: firmware upload complete\n");
+		state->initialised = 1;
+	}
+
+	/* enable TS output and interface pins */
+	sp887x_writereg(state, 0xc18, 0x00d);
+
+	return 0;
+}
+
+static int sp887x_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings)
+{
+	fesettings->min_delay_ms = 350;
+	fesettings->step_size = 166666*2;
+	fesettings->max_drift = (166666*2)+1;
+	return 0;
+}
+
+static void sp887x_release(struct dvb_frontend* fe)
+{
+	struct sp887x_state* state = fe->demodulator_priv;
+	kfree(state);
+}
+
+static struct dvb_frontend_ops sp887x_ops;
+
+struct dvb_frontend* sp887x_attach(const struct sp887x_config* config,
+				   struct i2c_adapter* i2c)
+{
+	struct sp887x_state* state = NULL;
+
+	/* allocate memory for the internal state */
+	state = kzalloc(sizeof(struct sp887x_state), GFP_KERNEL);
+	if (state == NULL) goto error;
+
+	/* setup the state */
+	state->config = config;
+	state->i2c = i2c;
+	state->initialised = 0;
+
+	/* check if the demod is there */
+	if (sp887x_readreg(state, 0x0200) < 0) goto error;
+
+	/* create dvb_frontend */
+	memcpy(&state->frontend.ops, &sp887x_ops, sizeof(struct dvb_frontend_ops));
+	state->frontend.demodulator_priv = state;
+	return &state->frontend;
+
+error:
+	kfree(state);
+	return NULL;
+}
+
+static struct dvb_frontend_ops sp887x_ops = {
+	.delsys = { SYS_DVBT },
+	.info = {
+		.name = "Spase SP887x DVB-T",
+		.frequency_min =  50500000,
+		.frequency_max = 858000000,
+		.frequency_stepsize = 166666,
+		.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_FEC_AUTO |
+			FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 |
+			FE_CAN_RECOVER
+	},
+
+	.release = sp887x_release,
+
+	.init = sp887x_init,
+	.sleep = sp887x_sleep,
+	.i2c_gate_ctrl = sp887x_i2c_gate_ctrl,
+
+	.set_frontend = sp887x_setup_frontend_parameters,
+	.get_tune_settings = sp887x_get_tune_settings,
+
+	.read_status = sp887x_read_status,
+	.read_ber = sp887x_read_ber,
+	.read_signal_strength = sp887x_read_signal_strength,
+	.read_snr = sp887x_read_snr,
+	.read_ucblocks = sp887x_read_ucblocks,
+};
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+
+MODULE_DESCRIPTION("Spase sp887x DVB-T demodulator driver");
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(sp887x_attach);
diff --git a/drivers/media/dvb-frontends/sp887x.h b/drivers/media/dvb-frontends/sp887x.h
new file mode 100644
index 0000000..04eff6e
--- /dev/null
+++ b/drivers/media/dvb-frontends/sp887x.h
@@ -0,0 +1,32 @@
+/*
+   Driver for the Spase sp887x demodulator
+*/
+
+#ifndef SP887X_H
+#define SP887X_H
+
+#include <linux/dvb/frontend.h>
+#include <linux/firmware.h>
+
+struct sp887x_config
+{
+	/* the demodulator's i2c address */
+	u8 demod_address;
+
+	/* request firmware for device */
+	int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name);
+};
+
+#if defined(CONFIG_DVB_SP887X) || (defined(CONFIG_DVB_SP887X_MODULE) && defined(MODULE))
+extern struct dvb_frontend* sp887x_attach(const struct sp887x_config* config,
+					  struct i2c_adapter* i2c);
+#else
+static inline struct dvb_frontend* sp887x_attach(const struct sp887x_config* config,
+					  struct i2c_adapter* i2c)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif // CONFIG_DVB_SP887X
+
+#endif // SP887X_H
diff --git a/drivers/media/dvb-frontends/stb0899_algo.c b/drivers/media/dvb-frontends/stb0899_algo.c
new file mode 100644
index 0000000..117a569
--- /dev/null
+++ b/drivers/media/dvb-frontends/stb0899_algo.c
@@ -0,0 +1,1525 @@
+/*
+	STB0899 Multistandard Frontend driver
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	Copyright (C) ST Microelectronics
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the 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 "stb0899_drv.h"
+#include "stb0899_priv.h"
+#include "stb0899_reg.h"
+
+static inline u32 stb0899_do_div(u64 n, u32 d)
+{
+	/* wrap do_div() for ease of use */
+
+	do_div(n, d);
+	return n;
+}
+
+#if 0
+/* These functions are currently unused */
+/*
+ * stb0899_calc_srate
+ * Compute symbol rate
+ */
+static u32 stb0899_calc_srate(u32 master_clk, u8 *sfr)
+{
+	u64 tmp;
+
+	/* srate = (SFR * master_clk) >> 20 */
+
+	/* sfr is of size 20 bit, stored with an offset of 4 bit */
+	tmp = (((u32)sfr[0]) << 16) | (((u32)sfr[1]) << 8) | sfr[2];
+	tmp &= ~0xf;
+	tmp *= master_clk;
+	tmp >>= 24;
+
+	return tmp;
+}
+
+/*
+ * stb0899_get_srate
+ * Get the current symbol rate
+ */
+static u32 stb0899_get_srate(struct stb0899_state *state)
+{
+	struct stb0899_internal *internal = &state->internal;
+	u8 sfr[3];
+
+	stb0899_read_regs(state, STB0899_SFRH, sfr, 3);
+
+	return stb0899_calc_srate(internal->master_clk, sfr);
+}
+#endif
+
+/*
+ * stb0899_set_srate
+ * Set symbol frequency
+ * MasterClock: master clock frequency (hz)
+ * SymbolRate: symbol rate (bauds)
+ * return symbol frequency
+ */
+static u32 stb0899_set_srate(struct stb0899_state *state, u32 master_clk, u32 srate)
+{
+	u32 tmp;
+	u8 sfr[3];
+
+	dprintk(state->verbose, FE_DEBUG, 1, "-->");
+	/*
+	 * in order to have the maximum precision, the symbol rate entered into
+	 * the chip is computed as the closest value of the "true value".
+	 * In this purpose, the symbol rate value is rounded (1 is added on the bit
+	 * below the LSB )
+	 *
+	 * srate = (SFR * master_clk) >> 20
+	 *      <=>
+	 *   SFR = srate << 20 / master_clk
+	 *
+	 * rounded:
+	 *   SFR = (srate << 21 + master_clk) / (2 * master_clk)
+	 *
+	 * stored as 20 bit number with an offset of 4 bit:
+	 *   sfr = SFR << 4;
+	 */
+
+	tmp = stb0899_do_div((((u64)srate) << 21) + master_clk, 2 * master_clk);
+	tmp <<= 4;
+
+	sfr[0] = tmp >> 16;
+	sfr[1] = tmp >>  8;
+	sfr[2] = tmp;
+
+	stb0899_write_regs(state, STB0899_SFRH, sfr, 3);
+
+	return srate;
+}
+
+/*
+ * stb0899_calc_derot_time
+ * Compute the amount of time needed by the derotator to lock
+ * SymbolRate: Symbol rate
+ * return: derotator time constant (ms)
+ */
+static long stb0899_calc_derot_time(long srate)
+{
+	if (srate > 0)
+		return (100000 / (srate / 1000));
+	else
+		return 0;
+}
+
+/*
+ * stb0899_carr_width
+ * Compute the width of the carrier
+ * return: width of carrier (kHz or Mhz)
+ */
+long stb0899_carr_width(struct stb0899_state *state)
+{
+	struct stb0899_internal *internal = &state->internal;
+
+	return (internal->srate + (internal->srate * internal->rolloff) / 100);
+}
+
+/*
+ * stb0899_first_subrange
+ * Compute the first subrange of the search
+ */
+static void stb0899_first_subrange(struct stb0899_state *state)
+{
+	struct stb0899_internal *internal	= &state->internal;
+	struct stb0899_params *params		= &state->params;
+	struct stb0899_config *config		=  state->config;
+
+	int range = 0;
+	u32 bandwidth = 0;
+
+	if (config->tuner_get_bandwidth) {
+		stb0899_i2c_gate_ctrl(&state->frontend, 1);
+		config->tuner_get_bandwidth(&state->frontend, &bandwidth);
+		stb0899_i2c_gate_ctrl(&state->frontend, 0);
+		range = bandwidth - stb0899_carr_width(state) / 2;
+	}
+
+	if (range > 0)
+		internal->sub_range = min(internal->srch_range, range);
+	else
+		internal->sub_range = 0;
+
+	internal->freq = params->freq;
+	internal->tuner_offst = 0L;
+	internal->sub_dir = 1;
+}
+
+/*
+ * stb0899_check_tmg
+ * check for timing lock
+ * internal.Ttiming: time to wait for loop lock
+ */
+static enum stb0899_status stb0899_check_tmg(struct stb0899_state *state)
+{
+	struct stb0899_internal *internal = &state->internal;
+	int lock;
+	u8 reg;
+	s8 timing;
+
+	msleep(internal->t_derot);
+
+	stb0899_write_reg(state, STB0899_RTF, 0xf2);
+	reg = stb0899_read_reg(state, STB0899_TLIR);
+	lock = STB0899_GETFIELD(TLIR_TMG_LOCK_IND, reg);
+	timing = stb0899_read_reg(state, STB0899_RTF);
+
+	if (lock >= 42) {
+		if ((lock > 48) && (abs(timing) >= 110)) {
+			internal->status = ANALOGCARRIER;
+			dprintk(state->verbose, FE_DEBUG, 1, "-->ANALOG Carrier !");
+		} else {
+			internal->status = TIMINGOK;
+			dprintk(state->verbose, FE_DEBUG, 1, "------->TIMING OK !");
+		}
+	} else {
+		internal->status = NOTIMING;
+		dprintk(state->verbose, FE_DEBUG, 1, "-->NO TIMING !");
+	}
+	return internal->status;
+}
+
+/*
+ * stb0899_search_tmg
+ * perform a fs/2 zig-zag to find timing
+ */
+static enum stb0899_status stb0899_search_tmg(struct stb0899_state *state)
+{
+	struct stb0899_internal *internal = &state->internal;
+	struct stb0899_params *params = &state->params;
+
+	short int derot_step, derot_freq = 0, derot_limit, next_loop = 3;
+	int index = 0;
+	u8 cfr[2];
+
+	internal->status = NOTIMING;
+
+	/* timing loop computation & symbol rate optimisation	*/
+	derot_limit = (internal->sub_range / 2L) / internal->mclk;
+	derot_step = (params->srate / 2L) / internal->mclk;
+
+	while ((stb0899_check_tmg(state) != TIMINGOK) && next_loop) {
+		index++;
+		derot_freq += index * internal->direction * derot_step;	/* next derot zig zag position	*/
+
+		if (abs(derot_freq) > derot_limit)
+			next_loop--;
+
+		if (next_loop) {
+			STB0899_SETFIELD_VAL(CFRM, cfr[0], MSB(state->config->inversion * derot_freq));
+			STB0899_SETFIELD_VAL(CFRL, cfr[1], LSB(state->config->inversion * derot_freq));
+			stb0899_write_regs(state, STB0899_CFRM, cfr, 2); /* derotator frequency		*/
+		}
+		internal->direction = -internal->direction;	/* Change zigzag direction		*/
+	}
+
+	if (internal->status == TIMINGOK) {
+		stb0899_read_regs(state, STB0899_CFRM, cfr, 2); /* get derotator frequency		*/
+		internal->derot_freq = state->config->inversion * MAKEWORD16(cfr[0], cfr[1]);
+		dprintk(state->verbose, FE_DEBUG, 1, "------->TIMING OK ! Derot Freq = %d", internal->derot_freq);
+	}
+
+	return internal->status;
+}
+
+/*
+ * stb0899_check_carrier
+ * Check for carrier found
+ */
+static enum stb0899_status stb0899_check_carrier(struct stb0899_state *state)
+{
+	struct stb0899_internal *internal = &state->internal;
+	u8 reg;
+
+	msleep(internal->t_derot); /* wait for derotator ok	*/
+
+	reg = stb0899_read_reg(state, STB0899_CFD);
+	STB0899_SETFIELD_VAL(CFD_ON, reg, 1);
+	stb0899_write_reg(state, STB0899_CFD, reg);
+
+	reg = stb0899_read_reg(state, STB0899_DSTATUS);
+	dprintk(state->verbose, FE_DEBUG, 1, "--------------------> STB0899_DSTATUS=[0x%02x]", reg);
+	if (STB0899_GETFIELD(CARRIER_FOUND, reg)) {
+		internal->status = CARRIEROK;
+		dprintk(state->verbose, FE_DEBUG, 1, "-------------> CARRIEROK !");
+	} else {
+		internal->status = NOCARRIER;
+		dprintk(state->verbose, FE_DEBUG, 1, "-------------> NOCARRIER !");
+	}
+
+	return internal->status;
+}
+
+/*
+ * stb0899_search_carrier
+ * Search for a QPSK carrier with the derotator
+ */
+static enum stb0899_status stb0899_search_carrier(struct stb0899_state *state)
+{
+	struct stb0899_internal *internal = &state->internal;
+
+	short int derot_freq = 0, last_derot_freq = 0, derot_limit, next_loop = 3;
+	int index = 0;
+	u8 cfr[2];
+	u8 reg;
+
+	internal->status = NOCARRIER;
+	derot_limit = (internal->sub_range / 2L) / internal->mclk;
+	derot_freq = internal->derot_freq;
+
+	reg = stb0899_read_reg(state, STB0899_CFD);
+	STB0899_SETFIELD_VAL(CFD_ON, reg, 1);
+	stb0899_write_reg(state, STB0899_CFD, reg);
+
+	do {
+		dprintk(state->verbose, FE_DEBUG, 1, "Derot Freq=%d, mclk=%d", derot_freq, internal->mclk);
+		if (stb0899_check_carrier(state) == NOCARRIER) {
+			index++;
+			last_derot_freq = derot_freq;
+			derot_freq += index * internal->direction * internal->derot_step; /* next zig zag derotator position */
+
+			if(abs(derot_freq) > derot_limit)
+				next_loop--;
+
+			if (next_loop) {
+				reg = stb0899_read_reg(state, STB0899_CFD);
+				STB0899_SETFIELD_VAL(CFD_ON, reg, 1);
+				stb0899_write_reg(state, STB0899_CFD, reg);
+
+				STB0899_SETFIELD_VAL(CFRM, cfr[0], MSB(state->config->inversion * derot_freq));
+				STB0899_SETFIELD_VAL(CFRL, cfr[1], LSB(state->config->inversion * derot_freq));
+				stb0899_write_regs(state, STB0899_CFRM, cfr, 2); /* derotator frequency	*/
+			}
+		}
+
+		internal->direction = -internal->direction; /* Change zigzag direction */
+	} while ((internal->status != CARRIEROK) && next_loop);
+
+	if (internal->status == CARRIEROK) {
+		stb0899_read_regs(state, STB0899_CFRM, cfr, 2); /* get derotator frequency */
+		internal->derot_freq = state->config->inversion * MAKEWORD16(cfr[0], cfr[1]);
+		dprintk(state->verbose, FE_DEBUG, 1, "----> CARRIER OK !, Derot Freq=%d", internal->derot_freq);
+	} else {
+		internal->derot_freq = last_derot_freq;
+	}
+
+	return internal->status;
+}
+
+/*
+ * stb0899_check_data
+ * Check for data found
+ */
+static enum stb0899_status stb0899_check_data(struct stb0899_state *state)
+{
+	struct stb0899_internal *internal = &state->internal;
+	struct stb0899_params *params = &state->params;
+
+	int lock = 0, index = 0, dataTime = 500, loop;
+	u8 reg;
+
+	internal->status = NODATA;
+
+	/* RESET FEC	*/
+	reg = stb0899_read_reg(state, STB0899_TSTRES);
+	STB0899_SETFIELD_VAL(FRESACS, reg, 1);
+	stb0899_write_reg(state, STB0899_TSTRES, reg);
+	msleep(1);
+	reg = stb0899_read_reg(state, STB0899_TSTRES);
+	STB0899_SETFIELD_VAL(FRESACS, reg, 0);
+	stb0899_write_reg(state, STB0899_TSTRES, reg);
+
+	if (params->srate <= 2000000)
+		dataTime = 2000;
+	else if (params->srate <= 5000000)
+		dataTime = 1500;
+	else if (params->srate <= 15000000)
+		dataTime = 1000;
+	else
+		dataTime = 500;
+
+	/* clear previous failed END_LOOPVIT */
+	stb0899_read_reg(state, STB0899_VSTATUS);
+
+	stb0899_write_reg(state, STB0899_DSTATUS2, 0x00); /* force search loop	*/
+	while (1) {
+		/* WARNING! VIT LOCKED has to be tested before VIT_END_LOOOP	*/
+		reg = stb0899_read_reg(state, STB0899_VSTATUS);
+		lock = STB0899_GETFIELD(VSTATUS_LOCKEDVIT, reg);
+		loop = STB0899_GETFIELD(VSTATUS_END_LOOPVIT, reg);
+
+		if (lock || loop || (index > dataTime))
+			break;
+		index++;
+	}
+
+	if (lock) {	/* DATA LOCK indicator	*/
+		internal->status = DATAOK;
+		dprintk(state->verbose, FE_DEBUG, 1, "-----------------> DATA OK !");
+	}
+
+	return internal->status;
+}
+
+/*
+ * stb0899_search_data
+ * Search for a QPSK carrier with the derotator
+ */
+static enum stb0899_status stb0899_search_data(struct stb0899_state *state)
+{
+	short int derot_freq, derot_step, derot_limit, next_loop = 3;
+	u8 cfr[2];
+	u8 reg;
+	int index = 1;
+
+	struct stb0899_internal *internal = &state->internal;
+	struct stb0899_params *params = &state->params;
+
+	derot_step = (params->srate / 4L) / internal->mclk;
+	derot_limit = (internal->sub_range / 2L) / internal->mclk;
+	derot_freq = internal->derot_freq;
+
+	do {
+		if ((internal->status != CARRIEROK) || (stb0899_check_data(state) != DATAOK)) {
+
+			derot_freq += index * internal->direction * derot_step;	/* next zig zag derotator position */
+			if (abs(derot_freq) > derot_limit)
+				next_loop--;
+
+			if (next_loop) {
+				dprintk(state->verbose, FE_DEBUG, 1, "Derot freq=%d, mclk=%d", derot_freq, internal->mclk);
+				reg = stb0899_read_reg(state, STB0899_CFD);
+				STB0899_SETFIELD_VAL(CFD_ON, reg, 1);
+				stb0899_write_reg(state, STB0899_CFD, reg);
+
+				STB0899_SETFIELD_VAL(CFRM, cfr[0], MSB(state->config->inversion * derot_freq));
+				STB0899_SETFIELD_VAL(CFRL, cfr[1], LSB(state->config->inversion * derot_freq));
+				stb0899_write_regs(state, STB0899_CFRM, cfr, 2); /* derotator frequency	*/
+
+				stb0899_check_carrier(state);
+				index++;
+			}
+		}
+		internal->direction = -internal->direction; /* change zig zag direction */
+	} while ((internal->status != DATAOK) && next_loop);
+
+	if (internal->status == DATAOK) {
+		stb0899_read_regs(state, STB0899_CFRM, cfr, 2); /* get derotator frequency */
+		internal->derot_freq = state->config->inversion * MAKEWORD16(cfr[0], cfr[1]);
+		dprintk(state->verbose, FE_DEBUG, 1, "------> DATAOK ! Derot Freq=%d", internal->derot_freq);
+	}
+
+	return internal->status;
+}
+
+/*
+ * stb0899_check_range
+ * check if the found frequency is in the correct range
+ */
+static enum stb0899_status stb0899_check_range(struct stb0899_state *state)
+{
+	struct stb0899_internal *internal = &state->internal;
+	struct stb0899_params *params = &state->params;
+
+	int range_offst, tp_freq;
+
+	range_offst = internal->srch_range / 2000;
+	tp_freq = internal->freq + (internal->derot_freq * internal->mclk) / 1000;
+
+	if ((tp_freq >= params->freq - range_offst) && (tp_freq <= params->freq + range_offst)) {
+		internal->status = RANGEOK;
+		dprintk(state->verbose, FE_DEBUG, 1, "----> RANGEOK !");
+	} else {
+		internal->status = OUTOFRANGE;
+		dprintk(state->verbose, FE_DEBUG, 1, "----> OUT OF RANGE !");
+	}
+
+	return internal->status;
+}
+
+/*
+ * NextSubRange
+ * Compute the next subrange of the search
+ */
+static void next_sub_range(struct stb0899_state *state)
+{
+	struct stb0899_internal *internal = &state->internal;
+	struct stb0899_params *params = &state->params;
+
+	long old_sub_range;
+
+	if (internal->sub_dir > 0) {
+		old_sub_range = internal->sub_range;
+		internal->sub_range = min((internal->srch_range / 2) -
+					  (internal->tuner_offst + internal->sub_range / 2),
+					   internal->sub_range);
+
+		if (internal->sub_range < 0)
+			internal->sub_range = 0;
+
+		internal->tuner_offst += (old_sub_range + internal->sub_range) / 2;
+	}
+
+	internal->freq = params->freq + (internal->sub_dir * internal->tuner_offst) / 1000;
+	internal->sub_dir = -internal->sub_dir;
+}
+
+/*
+ * stb0899_dvbs_algo
+ * Search for a signal, timing, carrier and data for a
+ * given frequency in a given range
+ */
+enum stb0899_status stb0899_dvbs_algo(struct stb0899_state *state)
+{
+	struct stb0899_params *params		= &state->params;
+	struct stb0899_internal *internal	= &state->internal;
+	struct stb0899_config *config		= state->config;
+
+	u8 bclc, reg;
+	u8 cfr[2];
+	u8 eq_const[10];
+	s32 clnI = 3;
+	u32 bandwidth = 0;
+
+	/* BETA values rated @ 99MHz	*/
+	s32 betaTab[5][4] = {
+	       /*  5   10   20   30MBps */
+		{ 37,  34,  32,  31 }, /* QPSK 1/2	*/
+		{ 37,  35,  33,  31 }, /* QPSK 2/3	*/
+		{ 37,  35,  33,  31 }, /* QPSK 3/4	*/
+		{ 37,  36,  33,	 32 }, /* QPSK 5/6	*/
+		{ 37,  36,  33,	 32 }  /* QPSK 7/8	*/
+	};
+
+	internal->direction = 1;
+
+	stb0899_set_srate(state, internal->master_clk, params->srate);
+	/* Carrier loop optimization versus symbol rate for acquisition*/
+	if (params->srate <= 5000000) {
+		stb0899_write_reg(state, STB0899_ACLC, 0x89);
+		bclc = stb0899_read_reg(state, STB0899_BCLC);
+		STB0899_SETFIELD_VAL(BETA, bclc, 0x1c);
+		stb0899_write_reg(state, STB0899_BCLC, bclc);
+		clnI = 0;
+	} else if (params->srate <= 15000000) {
+		stb0899_write_reg(state, STB0899_ACLC, 0xc9);
+		bclc = stb0899_read_reg(state, STB0899_BCLC);
+		STB0899_SETFIELD_VAL(BETA, bclc, 0x22);
+		stb0899_write_reg(state, STB0899_BCLC, bclc);
+		clnI = 1;
+	} else if(params->srate <= 25000000) {
+		stb0899_write_reg(state, STB0899_ACLC, 0x89);
+		bclc = stb0899_read_reg(state, STB0899_BCLC);
+		STB0899_SETFIELD_VAL(BETA, bclc, 0x27);
+		stb0899_write_reg(state, STB0899_BCLC, bclc);
+		clnI = 2;
+	} else {
+		stb0899_write_reg(state, STB0899_ACLC, 0xc8);
+		bclc = stb0899_read_reg(state, STB0899_BCLC);
+		STB0899_SETFIELD_VAL(BETA, bclc, 0x29);
+		stb0899_write_reg(state, STB0899_BCLC, bclc);
+		clnI = 3;
+	}
+
+	dprintk(state->verbose, FE_DEBUG, 1, "Set the timing loop to acquisition");
+	/* Set the timing loop to acquisition	*/
+	stb0899_write_reg(state, STB0899_RTC, 0x46);
+	stb0899_write_reg(state, STB0899_CFD, 0xee);
+
+	/* !! WARNING !!
+	 * Do not read any status variables while acquisition,
+	 * If any needed, read before the acquisition starts
+	 * querying status while acquiring causes the
+	 * acquisition to go bad and hence no locks.
+	 */
+	dprintk(state->verbose, FE_DEBUG, 1, "Derot Percent=%d Srate=%d mclk=%d",
+		internal->derot_percent, params->srate, internal->mclk);
+
+	/* Initial calculations	*/
+	internal->derot_step = internal->derot_percent * (params->srate / 1000L) / internal->mclk; /* DerotStep/1000 * Fsymbol	*/
+	internal->t_derot = stb0899_calc_derot_time(params->srate);
+	internal->t_data = 500;
+
+	dprintk(state->verbose, FE_DEBUG, 1, "RESET stream merger");
+	/* RESET Stream merger	*/
+	reg = stb0899_read_reg(state, STB0899_TSTRES);
+	STB0899_SETFIELD_VAL(FRESRS, reg, 1);
+	stb0899_write_reg(state, STB0899_TSTRES, reg);
+
+	/*
+	 * Set KDIVIDER to an intermediate value between
+	 * 1/2 and 7/8 for acquisition
+	 */
+	reg = stb0899_read_reg(state, STB0899_DEMAPVIT);
+	STB0899_SETFIELD_VAL(DEMAPVIT_KDIVIDER, reg, 60);
+	stb0899_write_reg(state, STB0899_DEMAPVIT, reg);
+
+	stb0899_write_reg(state, STB0899_EQON, 0x01); /* Equalizer OFF while acquiring */
+	stb0899_write_reg(state, STB0899_VITSYNC, 0x19);
+
+	stb0899_first_subrange(state);
+	do {
+		/* Initialisations */
+		cfr[0] = cfr[1] = 0;
+		stb0899_write_regs(state, STB0899_CFRM, cfr, 2); /* RESET derotator frequency	*/
+
+		stb0899_write_reg(state, STB0899_RTF, 0);
+		reg = stb0899_read_reg(state, STB0899_CFD);
+		STB0899_SETFIELD_VAL(CFD_ON, reg, 1);
+		stb0899_write_reg(state, STB0899_CFD, reg);
+
+		internal->derot_freq = 0;
+		internal->status = NOAGC1;
+
+		/* enable tuner I/O */
+		stb0899_i2c_gate_ctrl(&state->frontend, 1);
+
+		/* Move tuner to frequency */
+		dprintk(state->verbose, FE_DEBUG, 1, "Tuner set frequency");
+		if (state->config->tuner_set_frequency)
+			state->config->tuner_set_frequency(&state->frontend, internal->freq);
+
+		if (state->config->tuner_get_frequency)
+			state->config->tuner_get_frequency(&state->frontend, &internal->freq);
+
+		msleep(internal->t_agc1 + internal->t_agc2 + internal->t_derot); /* AGC1, AGC2 and timing loop	*/
+		dprintk(state->verbose, FE_DEBUG, 1, "current derot freq=%d", internal->derot_freq);
+		internal->status = AGC1OK;
+
+		/* There is signal in the band	*/
+		if (config->tuner_get_bandwidth)
+			config->tuner_get_bandwidth(&state->frontend, &bandwidth);
+
+		/* disable tuner I/O */
+		stb0899_i2c_gate_ctrl(&state->frontend, 0);
+
+		if (params->srate <= bandwidth / 2)
+			stb0899_search_tmg(state); /* For low rates (SCPC)	*/
+		else
+			stb0899_check_tmg(state); /* For high rates (MCPC)	*/
+
+		if (internal->status == TIMINGOK) {
+			dprintk(state->verbose, FE_DEBUG, 1,
+				"TIMING OK ! Derot freq=%d, mclk=%d",
+				internal->derot_freq, internal->mclk);
+
+			if (stb0899_search_carrier(state) == CARRIEROK) {	/* Search for carrier	*/
+				dprintk(state->verbose, FE_DEBUG, 1,
+					"CARRIER OK ! Derot freq=%d, mclk=%d",
+					internal->derot_freq, internal->mclk);
+
+				if (stb0899_search_data(state) == DATAOK) {	/* Check for data	*/
+					dprintk(state->verbose, FE_DEBUG, 1,
+						"DATA OK ! Derot freq=%d, mclk=%d",
+						internal->derot_freq, internal->mclk);
+
+					if (stb0899_check_range(state) == RANGEOK) {
+						dprintk(state->verbose, FE_DEBUG, 1,
+							"RANGE OK ! derot freq=%d, mclk=%d",
+							internal->derot_freq, internal->mclk);
+
+						internal->freq = params->freq + ((internal->derot_freq * internal->mclk) / 1000);
+						reg = stb0899_read_reg(state, STB0899_PLPARM);
+						internal->fecrate = STB0899_GETFIELD(VITCURPUN, reg);
+						dprintk(state->verbose, FE_DEBUG, 1,
+							"freq=%d, internal resultant freq=%d",
+							params->freq, internal->freq);
+
+						dprintk(state->verbose, FE_DEBUG, 1,
+							"internal puncture rate=%d",
+							internal->fecrate);
+					}
+				}
+			}
+		}
+		if (internal->status != RANGEOK)
+			next_sub_range(state);
+
+	} while (internal->sub_range && internal->status != RANGEOK);
+
+	/* Set the timing loop to tracking	*/
+	stb0899_write_reg(state, STB0899_RTC, 0x33);
+	stb0899_write_reg(state, STB0899_CFD, 0xf7);
+	/* if locked and range ok, set Kdiv	*/
+	if (internal->status == RANGEOK) {
+		dprintk(state->verbose, FE_DEBUG, 1, "Locked & Range OK !");
+		stb0899_write_reg(state, STB0899_EQON, 0x41);		/* Equalizer OFF while acquiring	*/
+		stb0899_write_reg(state, STB0899_VITSYNC, 0x39);	/* SN to b'11 for acquisition		*/
+
+		/*
+		 * Carrier loop optimization versus
+		 * symbol Rate/Puncture Rate for Tracking
+		 */
+		reg = stb0899_read_reg(state, STB0899_BCLC);
+		switch (internal->fecrate) {
+		case STB0899_FEC_1_2:		/* 13	*/
+			stb0899_write_reg(state, STB0899_DEMAPVIT, 0x1a);
+			STB0899_SETFIELD_VAL(BETA, reg, betaTab[0][clnI]);
+			stb0899_write_reg(state, STB0899_BCLC, reg);
+			break;
+		case STB0899_FEC_2_3:		/* 18	*/
+			stb0899_write_reg(state, STB0899_DEMAPVIT, 44);
+			STB0899_SETFIELD_VAL(BETA, reg, betaTab[1][clnI]);
+			stb0899_write_reg(state, STB0899_BCLC, reg);
+			break;
+		case STB0899_FEC_3_4:		/* 21	*/
+			stb0899_write_reg(state, STB0899_DEMAPVIT, 60);
+			STB0899_SETFIELD_VAL(BETA, reg, betaTab[2][clnI]);
+			stb0899_write_reg(state, STB0899_BCLC, reg);
+			break;
+		case STB0899_FEC_5_6:		/* 24	*/
+			stb0899_write_reg(state, STB0899_DEMAPVIT, 75);
+			STB0899_SETFIELD_VAL(BETA, reg, betaTab[3][clnI]);
+			stb0899_write_reg(state, STB0899_BCLC, reg);
+			break;
+		case STB0899_FEC_6_7:		/* 25	*/
+			stb0899_write_reg(state, STB0899_DEMAPVIT, 88);
+			stb0899_write_reg(state, STB0899_ACLC, 0x88);
+			stb0899_write_reg(state, STB0899_BCLC, 0x9a);
+			break;
+		case STB0899_FEC_7_8:		/* 26	*/
+			stb0899_write_reg(state, STB0899_DEMAPVIT, 94);
+			STB0899_SETFIELD_VAL(BETA, reg, betaTab[4][clnI]);
+			stb0899_write_reg(state, STB0899_BCLC, reg);
+			break;
+		default:
+			dprintk(state->verbose, FE_DEBUG, 1, "Unsupported Puncture Rate");
+			break;
+		}
+		/* release stream merger RESET	*/
+		reg = stb0899_read_reg(state, STB0899_TSTRES);
+		STB0899_SETFIELD_VAL(FRESRS, reg, 0);
+		stb0899_write_reg(state, STB0899_TSTRES, reg);
+
+		/* disable carrier detector	*/
+		reg = stb0899_read_reg(state, STB0899_CFD);
+		STB0899_SETFIELD_VAL(CFD_ON, reg, 0);
+		stb0899_write_reg(state, STB0899_CFD, reg);
+
+		stb0899_read_regs(state, STB0899_EQUAI1, eq_const, 10);
+	}
+
+	return internal->status;
+}
+
+/*
+ * stb0899_dvbs2_config_uwp
+ * Configure UWP state machine
+ */
+static void stb0899_dvbs2_config_uwp(struct stb0899_state *state)
+{
+	struct stb0899_internal *internal = &state->internal;
+	struct stb0899_config *config = state->config;
+	u32 uwp1, uwp2, uwp3, reg;
+
+	uwp1 = STB0899_READ_S2REG(STB0899_S2DEMOD, UWP_CNTRL1);
+	uwp2 = STB0899_READ_S2REG(STB0899_S2DEMOD, UWP_CNTRL2);
+	uwp3 = STB0899_READ_S2REG(STB0899_S2DEMOD, UWP_CNTRL3);
+
+	STB0899_SETFIELD_VAL(UWP_ESN0_AVE, uwp1, config->esno_ave);
+	STB0899_SETFIELD_VAL(UWP_ESN0_QUANT, uwp1, config->esno_quant);
+	STB0899_SETFIELD_VAL(UWP_TH_SOF, uwp1, config->uwp_threshold_sof);
+
+	STB0899_SETFIELD_VAL(FE_COARSE_TRK, uwp2, internal->av_frame_coarse);
+	STB0899_SETFIELD_VAL(FE_FINE_TRK, uwp2, internal->av_frame_fine);
+	STB0899_SETFIELD_VAL(UWP_MISS_TH, uwp2, config->miss_threshold);
+
+	STB0899_SETFIELD_VAL(UWP_TH_ACQ, uwp3, config->uwp_threshold_acq);
+	STB0899_SETFIELD_VAL(UWP_TH_TRACK, uwp3, config->uwp_threshold_track);
+
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_UWP_CNTRL1, STB0899_OFF0_UWP_CNTRL1, uwp1);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_UWP_CNTRL2, STB0899_OFF0_UWP_CNTRL2, uwp2);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_UWP_CNTRL3, STB0899_OFF0_UWP_CNTRL3, uwp3);
+
+	reg = STB0899_READ_S2REG(STB0899_S2DEMOD, SOF_SRCH_TO);
+	STB0899_SETFIELD_VAL(SOF_SEARCH_TIMEOUT, reg, config->sof_search_timeout);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_SOF_SRCH_TO, STB0899_OFF0_SOF_SRCH_TO, reg);
+}
+
+/*
+ * stb0899_dvbs2_config_csm_auto
+ * Set CSM to AUTO mode
+ */
+static void stb0899_dvbs2_config_csm_auto(struct stb0899_state *state)
+{
+	u32 reg;
+
+	reg = STB0899_READ_S2REG(STB0899_S2DEMOD, CSM_CNTRL1);
+	STB0899_SETFIELD_VAL(CSM_AUTO_PARAM, reg, 1);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CSM_CNTRL1, STB0899_OFF0_CSM_CNTRL1, reg);
+}
+
+static long Log2Int(int number)
+{
+	int i;
+
+	i = 0;
+	while ((1 << i) <= abs(number))
+		i++;
+
+	if (number == 0)
+		i = 1;
+
+	return i - 1;
+}
+
+/*
+ * stb0899_dvbs2_calc_srate
+ * compute BTR_NOM_FREQ for the symbol rate
+ */
+static u32 stb0899_dvbs2_calc_srate(struct stb0899_state *state)
+{
+	struct stb0899_internal *internal	= &state->internal;
+	struct stb0899_config *config		= state->config;
+
+	u32 dec_ratio, dec_rate, decim, remain, intval, btr_nom_freq;
+	u32 master_clk, srate;
+
+	dec_ratio = (internal->master_clk * 2) / (5 * internal->srate);
+	dec_ratio = (dec_ratio == 0) ? 1 : dec_ratio;
+	dec_rate = Log2Int(dec_ratio);
+	decim = 1 << dec_rate;
+	master_clk = internal->master_clk / 1000;
+	srate = internal->srate / 1000;
+
+	if (decim <= 4) {
+		intval = (decim * (1 << (config->btr_nco_bits - 1))) / master_clk;
+		remain = (decim * (1 << (config->btr_nco_bits - 1))) % master_clk;
+	} else {
+		intval = (1 << (config->btr_nco_bits - 1)) / (master_clk / 100) * decim / 100;
+		remain = (decim * (1 << (config->btr_nco_bits - 1))) % master_clk;
+	}
+	btr_nom_freq = (intval * srate) + ((remain * srate) / master_clk);
+
+	return btr_nom_freq;
+}
+
+/*
+ * stb0899_dvbs2_calc_dev
+ * compute the correction to be applied to symbol rate
+ */
+static u32 stb0899_dvbs2_calc_dev(struct stb0899_state *state)
+{
+	struct stb0899_internal *internal = &state->internal;
+	u32 dec_ratio, correction, master_clk, srate;
+
+	dec_ratio = (internal->master_clk * 2) / (5 * internal->srate);
+	dec_ratio = (dec_ratio == 0) ? 1 : dec_ratio;
+
+	master_clk = internal->master_clk / 1000;	/* for integer Caculation*/
+	srate = internal->srate / 1000;	/* for integer Caculation*/
+	correction = (512 * master_clk) / (2 * dec_ratio * srate);
+
+	return	correction;
+}
+
+/*
+ * stb0899_dvbs2_set_srate
+ * Set DVBS2 symbol rate
+ */
+static void stb0899_dvbs2_set_srate(struct stb0899_state *state)
+{
+	struct stb0899_internal *internal = &state->internal;
+
+	u32 dec_ratio, dec_rate, win_sel, decim, f_sym, btr_nom_freq;
+	u32 correction, freq_adj, band_lim, decim_cntrl, reg;
+	u8 anti_alias;
+
+	/*set decimation to 1*/
+	dec_ratio = (internal->master_clk * 2) / (5 * internal->srate);
+	dec_ratio = (dec_ratio == 0) ? 1 : dec_ratio;
+	dec_rate = Log2Int(dec_ratio);
+
+	win_sel = 0;
+	if (dec_rate >= 5)
+		win_sel = dec_rate - 4;
+
+	decim = (1 << dec_rate);
+	/* (FSamp/Fsymbol *100) for integer Caculation */
+	f_sym = internal->master_clk / ((decim * internal->srate) / 1000);
+
+	if (f_sym <= 2250)	/* don't band limit signal going into btr block*/
+		band_lim = 1;
+	else
+		band_lim = 0;	/* band limit signal going into btr block*/
+
+	decim_cntrl = ((win_sel << 3) & 0x18) + ((band_lim << 5) & 0x20) + (dec_rate & 0x7);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_DECIM_CNTRL, STB0899_OFF0_DECIM_CNTRL, decim_cntrl);
+
+	if (f_sym <= 3450)
+		anti_alias = 0;
+	else if (f_sym <= 4250)
+		anti_alias = 1;
+	else
+		anti_alias = 2;
+
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_ANTI_ALIAS_SEL, STB0899_OFF0_ANTI_ALIAS_SEL, anti_alias);
+	btr_nom_freq = stb0899_dvbs2_calc_srate(state);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_BTR_NOM_FREQ, STB0899_OFF0_BTR_NOM_FREQ, btr_nom_freq);
+
+	correction = stb0899_dvbs2_calc_dev(state);
+	reg = STB0899_READ_S2REG(STB0899_S2DEMOD, BTR_CNTRL);
+	STB0899_SETFIELD_VAL(BTR_FREQ_CORR, reg, correction);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_BTR_CNTRL, STB0899_OFF0_BTR_CNTRL, reg);
+
+	/* scale UWP+CSM frequency to sample rate*/
+	freq_adj =  internal->srate / (internal->master_clk / 4096);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_FREQ_ADJ_SCALE, STB0899_OFF0_FREQ_ADJ_SCALE, freq_adj);
+}
+
+/*
+ * stb0899_dvbs2_set_btr_loopbw
+ * set bit timing loop bandwidth as a percentage of the symbol rate
+ */
+static void stb0899_dvbs2_set_btr_loopbw(struct stb0899_state *state)
+{
+	struct stb0899_internal *internal	= &state->internal;
+	struct stb0899_config *config		= state->config;
+
+	u32 sym_peak = 23, zeta = 707, loopbw_percent = 60;
+	s32 dec_ratio, dec_rate, k_btr1_rshft, k_btr1, k_btr0_rshft;
+	s32 k_btr0, k_btr2_rshft, k_direct_shift, k_indirect_shift;
+	u32 decim, K, wn, k_direct, k_indirect;
+	u32 reg;
+
+	dec_ratio = (internal->master_clk * 2) / (5 * internal->srate);
+	dec_ratio = (dec_ratio == 0) ? 1 : dec_ratio;
+	dec_rate = Log2Int(dec_ratio);
+	decim = (1 << dec_rate);
+
+	sym_peak *= 576000;
+	K = (1 << config->btr_nco_bits) / (internal->master_clk / 1000);
+	K *= (internal->srate / 1000000) * decim; /*k=k 10^-8*/
+
+	if (K != 0) {
+		K = sym_peak / K;
+		wn = (4 * zeta * zeta) + 1000000;
+		wn = (2 * (loopbw_percent * 1000) * 40 * zeta) /wn;  /*wn =wn 10^-8*/
+
+		k_indirect = (wn * wn) / K;
+		k_indirect = k_indirect;	  /*kindirect = kindirect 10^-6*/
+		k_direct   = (2 * wn * zeta) / K;	/*kDirect = kDirect 10^-2*/
+		k_direct  *= 100;
+
+		k_direct_shift = Log2Int(k_direct) - Log2Int(10000) - 2;
+		k_btr1_rshft = (-1 * k_direct_shift) + config->btr_gain_shift_offset;
+		k_btr1 = k_direct / (1 << k_direct_shift);
+		k_btr1 /= 10000;
+
+		k_indirect_shift = Log2Int(k_indirect + 15) - 20 /*- 2*/;
+		k_btr0_rshft = (-1 * k_indirect_shift) + config->btr_gain_shift_offset;
+		k_btr0 = k_indirect * (1 << (-k_indirect_shift));
+		k_btr0 /= 1000000;
+
+		k_btr2_rshft = 0;
+		if (k_btr0_rshft > 15) {
+			k_btr2_rshft = k_btr0_rshft - 15;
+			k_btr0_rshft = 15;
+		}
+		reg = STB0899_READ_S2REG(STB0899_S2DEMOD, BTR_LOOP_GAIN);
+		STB0899_SETFIELD_VAL(KBTR0_RSHFT, reg, k_btr0_rshft);
+		STB0899_SETFIELD_VAL(KBTR0, reg, k_btr0);
+		STB0899_SETFIELD_VAL(KBTR1_RSHFT, reg, k_btr1_rshft);
+		STB0899_SETFIELD_VAL(KBTR1, reg, k_btr1);
+		STB0899_SETFIELD_VAL(KBTR2_RSHFT, reg, k_btr2_rshft);
+		stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_BTR_LOOP_GAIN, STB0899_OFF0_BTR_LOOP_GAIN, reg);
+	} else
+		stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_BTR_LOOP_GAIN, STB0899_OFF0_BTR_LOOP_GAIN, 0xc4c4f);
+}
+
+/*
+ * stb0899_dvbs2_set_carr_freq
+ * set nominal frequency for carrier search
+ */
+static void stb0899_dvbs2_set_carr_freq(struct stb0899_state *state, s32 carr_freq, u32 master_clk)
+{
+	struct stb0899_config *config = state->config;
+	s32 crl_nom_freq;
+	u32 reg;
+
+	crl_nom_freq = (1 << config->crl_nco_bits) / master_clk;
+	crl_nom_freq *= carr_freq;
+	reg = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_NOM_FREQ);
+	STB0899_SETFIELD_VAL(CRL_NOM_FREQ, reg, crl_nom_freq);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CRL_NOM_FREQ, STB0899_OFF0_CRL_NOM_FREQ, reg);
+}
+
+/*
+ * stb0899_dvbs2_init_calc
+ * Initialize DVBS2 UWP, CSM, carrier and timing loops
+ */
+static void stb0899_dvbs2_init_calc(struct stb0899_state *state)
+{
+	struct stb0899_internal *internal = &state->internal;
+	s32 steps, step_size;
+	u32 range, reg;
+
+	/* config uwp and csm */
+	stb0899_dvbs2_config_uwp(state);
+	stb0899_dvbs2_config_csm_auto(state);
+
+	/* initialize BTR	*/
+	stb0899_dvbs2_set_srate(state);
+	stb0899_dvbs2_set_btr_loopbw(state);
+
+	if (internal->srate / 1000000 >= 15)
+		step_size = (1 << 17) / 5;
+	else if (internal->srate / 1000000 >= 10)
+		step_size = (1 << 17) / 7;
+	else if (internal->srate / 1000000 >= 5)
+		step_size = (1 << 17) / 10;
+	else
+		step_size = (1 << 17) / 4;
+
+	range = internal->srch_range / 1000000;
+	steps = (10 * range * (1 << 17)) / (step_size * (internal->srate / 1000000));
+	steps = (steps + 6) / 10;
+	steps = (steps == 0) ? 1 : steps;
+	if (steps % 2 == 0)
+		stb0899_dvbs2_set_carr_freq(state, internal->center_freq -
+					   (internal->step_size * (internal->srate / 20000000)),
+					   (internal->master_clk) / 1000000);
+	else
+		stb0899_dvbs2_set_carr_freq(state, internal->center_freq, (internal->master_clk) / 1000000);
+
+	/*Set Carrier Search params (zigzag, num steps and freq step size*/
+	reg = STB0899_READ_S2REG(STB0899_S2DEMOD, ACQ_CNTRL2);
+	STB0899_SETFIELD_VAL(ZIGZAG, reg, 1);
+	STB0899_SETFIELD_VAL(NUM_STEPS, reg, steps);
+	STB0899_SETFIELD_VAL(FREQ_STEPSIZE, reg, step_size);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_ACQ_CNTRL2, STB0899_OFF0_ACQ_CNTRL2, reg);
+}
+
+/*
+ * stb0899_dvbs2_btr_init
+ * initialize the timing loop
+ */
+static void stb0899_dvbs2_btr_init(struct stb0899_state *state)
+{
+	u32 reg;
+
+	/* set enable BTR loopback	*/
+	reg = STB0899_READ_S2REG(STB0899_S2DEMOD, BTR_CNTRL);
+	STB0899_SETFIELD_VAL(INTRP_PHS_SENSE, reg, 1);
+	STB0899_SETFIELD_VAL(BTR_ERR_ENA, reg, 1);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_BTR_CNTRL, STB0899_OFF0_BTR_CNTRL, reg);
+
+	/* fix btr freq accum at 0	*/
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_BTR_FREQ_INIT, STB0899_OFF0_BTR_FREQ_INIT, 0x10000000);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_BTR_FREQ_INIT, STB0899_OFF0_BTR_FREQ_INIT, 0x00000000);
+
+	/* fix btr freq accum at 0	*/
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_BTR_PHS_INIT, STB0899_OFF0_BTR_PHS_INIT, 0x10000000);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_BTR_PHS_INIT, STB0899_OFF0_BTR_PHS_INIT, 0x00000000);
+}
+
+/*
+ * stb0899_dvbs2_reacquire
+ * trigger a DVB-S2 acquisition
+ */
+static void stb0899_dvbs2_reacquire(struct stb0899_state *state)
+{
+	u32 reg = 0;
+
+	/* demod soft reset	*/
+	STB0899_SETFIELD_VAL(DVBS2_RESET, reg, 1);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_RESET_CNTRL, STB0899_OFF0_RESET_CNTRL, reg);
+
+	/*Reset Timing Loop	*/
+	stb0899_dvbs2_btr_init(state);
+
+	/* reset Carrier loop	*/
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CRL_FREQ_INIT, STB0899_OFF0_CRL_FREQ_INIT, (1 << 30));
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CRL_FREQ_INIT, STB0899_OFF0_CRL_FREQ_INIT, 0);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CRL_LOOP_GAIN, STB0899_OFF0_CRL_LOOP_GAIN, 0);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CRL_PHS_INIT, STB0899_OFF0_CRL_PHS_INIT, (1 << 30));
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CRL_PHS_INIT, STB0899_OFF0_CRL_PHS_INIT, 0);
+
+	/*release demod soft reset	*/
+	reg = 0;
+	STB0899_SETFIELD_VAL(DVBS2_RESET, reg, 0);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_RESET_CNTRL, STB0899_OFF0_RESET_CNTRL, reg);
+
+	/* start acquisition process	*/
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_ACQUIRE_TRIG, STB0899_OFF0_ACQUIRE_TRIG, 1);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_LOCK_LOST, STB0899_OFF0_LOCK_LOST, 0);
+
+	/* equalizer Init	*/
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_EQUALIZER_INIT, STB0899_OFF0_EQUALIZER_INIT, 1);
+
+	/*Start equilizer	*/
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_EQUALIZER_INIT, STB0899_OFF0_EQUALIZER_INIT, 0);
+
+	reg = STB0899_READ_S2REG(STB0899_S2DEMOD, EQ_CNTRL);
+	STB0899_SETFIELD_VAL(EQ_SHIFT, reg, 0);
+	STB0899_SETFIELD_VAL(EQ_DISABLE_UPDATE, reg, 0);
+	STB0899_SETFIELD_VAL(EQ_DELAY, reg, 0x05);
+	STB0899_SETFIELD_VAL(EQ_ADAPT_MODE, reg, 0x01);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_EQ_CNTRL, STB0899_OFF0_EQ_CNTRL, reg);
+
+	/* RESET Packet delineator	*/
+	stb0899_write_reg(state, STB0899_PDELCTRL, 0x4a);
+}
+
+/*
+ * stb0899_dvbs2_get_dmd_status
+ * get DVB-S2 Demod LOCK status
+ */
+static enum stb0899_status stb0899_dvbs2_get_dmd_status(struct stb0899_state *state, int timeout)
+{
+	int time = -10, lock = 0, uwp, csm;
+	u32 reg;
+
+	do {
+		reg = STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_STATUS);
+		dprintk(state->verbose, FE_DEBUG, 1, "DMD_STATUS=[0x%02x]", reg);
+		if (STB0899_GETFIELD(IF_AGC_LOCK, reg))
+			dprintk(state->verbose, FE_DEBUG, 1, "------------->IF AGC LOCKED !");
+		reg = STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_STAT2);
+		dprintk(state->verbose, FE_DEBUG, 1, "----------->DMD STAT2=[0x%02x]", reg);
+		uwp = STB0899_GETFIELD(UWP_LOCK, reg);
+		csm = STB0899_GETFIELD(CSM_LOCK, reg);
+		if (uwp && csm)
+			lock = 1;
+
+		time += 10;
+		msleep(10);
+
+	} while ((!lock) && (time <= timeout));
+
+	if (lock) {
+		dprintk(state->verbose, FE_DEBUG, 1, "----------------> DVB-S2 LOCK !");
+		return DVBS2_DEMOD_LOCK;
+	} else {
+		return DVBS2_DEMOD_NOLOCK;
+	}
+}
+
+/*
+ * stb0899_dvbs2_get_data_lock
+ * get FEC status
+ */
+static int stb0899_dvbs2_get_data_lock(struct stb0899_state *state, int timeout)
+{
+	int time = 0, lock = 0;
+	u8 reg;
+
+	while ((!lock) && (time < timeout)) {
+		reg = stb0899_read_reg(state, STB0899_CFGPDELSTATUS1);
+		dprintk(state->verbose, FE_DEBUG, 1, "---------> CFGPDELSTATUS=[0x%02x]", reg);
+		lock = STB0899_GETFIELD(CFGPDELSTATUS_LOCK, reg);
+		time++;
+	}
+
+	return lock;
+}
+
+/*
+ * stb0899_dvbs2_get_fec_status
+ * get DVB-S2 FEC LOCK status
+ */
+static enum stb0899_status stb0899_dvbs2_get_fec_status(struct stb0899_state *state, int timeout)
+{
+	int time = 0, Locked;
+
+	do {
+		Locked = stb0899_dvbs2_get_data_lock(state, 1);
+		time++;
+		msleep(1);
+
+	} while ((!Locked) && (time < timeout));
+
+	if (Locked) {
+		dprintk(state->verbose, FE_DEBUG, 1, "---------->DVB-S2 FEC LOCK !");
+		return DVBS2_FEC_LOCK;
+	} else {
+		return DVBS2_FEC_NOLOCK;
+	}
+}
+
+
+/*
+ * stb0899_dvbs2_init_csm
+ * set parameters for manual mode
+ */
+static void stb0899_dvbs2_init_csm(struct stb0899_state *state, int pilots, enum stb0899_modcod modcod)
+{
+	struct stb0899_internal *internal = &state->internal;
+
+	s32 dvt_tbl = 1, two_pass = 0, agc_gain = 6, agc_shift = 0, loop_shift = 0, phs_diff_thr = 0x80;
+	s32 gamma_acq, gamma_rho_acq, gamma_trk, gamma_rho_trk, lock_count_thr;
+	u32 csm1, csm2, csm3, csm4;
+
+	if (((internal->master_clk / internal->srate) <= 4) && (modcod <= 11) && (pilots == 1)) {
+		switch (modcod) {
+		case STB0899_QPSK_12:
+			gamma_acq		= 25;
+			gamma_rho_acq		= 2700;
+			gamma_trk		= 12;
+			gamma_rho_trk		= 180;
+			lock_count_thr		= 8;
+			break;
+		case STB0899_QPSK_35:
+			gamma_acq		= 38;
+			gamma_rho_acq		= 7182;
+			gamma_trk		= 14;
+			gamma_rho_trk		= 308;
+			lock_count_thr		= 8;
+			break;
+		case STB0899_QPSK_23:
+			gamma_acq		= 42;
+			gamma_rho_acq		= 9408;
+			gamma_trk		= 17;
+			gamma_rho_trk		= 476;
+			lock_count_thr		= 8;
+			break;
+		case STB0899_QPSK_34:
+			gamma_acq		= 53;
+			gamma_rho_acq		= 16642;
+			gamma_trk		= 19;
+			gamma_rho_trk		= 646;
+			lock_count_thr		= 8;
+			break;
+		case STB0899_QPSK_45:
+			gamma_acq		= 53;
+			gamma_rho_acq		= 17119;
+			gamma_trk		= 22;
+			gamma_rho_trk		= 880;
+			lock_count_thr		= 8;
+			break;
+		case STB0899_QPSK_56:
+			gamma_acq		= 55;
+			gamma_rho_acq		= 19250;
+			gamma_trk		= 23;
+			gamma_rho_trk		= 989;
+			lock_count_thr		= 8;
+			break;
+		case STB0899_QPSK_89:
+			gamma_acq		= 60;
+			gamma_rho_acq		= 24240;
+			gamma_trk		= 24;
+			gamma_rho_trk		= 1176;
+			lock_count_thr		= 8;
+			break;
+		case STB0899_QPSK_910:
+			gamma_acq		= 66;
+			gamma_rho_acq		= 29634;
+			gamma_trk		= 24;
+			gamma_rho_trk		= 1176;
+			lock_count_thr		= 8;
+			break;
+		default:
+			gamma_acq		= 66;
+			gamma_rho_acq		= 29634;
+			gamma_trk		= 24;
+			gamma_rho_trk		= 1176;
+			lock_count_thr		= 8;
+			break;
+		}
+
+		csm1 = STB0899_READ_S2REG(STB0899_S2DEMOD, CSM_CNTRL1);
+		STB0899_SETFIELD_VAL(CSM_AUTO_PARAM, csm1, 0);
+		stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CSM_CNTRL1, STB0899_OFF0_CSM_CNTRL1, csm1);
+
+		csm1 = STB0899_READ_S2REG(STB0899_S2DEMOD, CSM_CNTRL1);
+		csm2 = STB0899_READ_S2REG(STB0899_S2DEMOD, CSM_CNTRL2);
+		csm3 = STB0899_READ_S2REG(STB0899_S2DEMOD, CSM_CNTRL3);
+		csm4 = STB0899_READ_S2REG(STB0899_S2DEMOD, CSM_CNTRL4);
+
+		STB0899_SETFIELD_VAL(CSM_DVT_TABLE, csm1, dvt_tbl);
+		STB0899_SETFIELD_VAL(CSM_TWO_PASS, csm1, two_pass);
+		STB0899_SETFIELD_VAL(CSM_AGC_GAIN, csm1, agc_gain);
+		STB0899_SETFIELD_VAL(CSM_AGC_SHIFT, csm1, agc_shift);
+		STB0899_SETFIELD_VAL(FE_LOOP_SHIFT, csm1, loop_shift);
+		STB0899_SETFIELD_VAL(CSM_GAMMA_ACQ, csm2, gamma_acq);
+		STB0899_SETFIELD_VAL(CSM_GAMMA_RHOACQ, csm2, gamma_rho_acq);
+		STB0899_SETFIELD_VAL(CSM_GAMMA_TRACK, csm3, gamma_trk);
+		STB0899_SETFIELD_VAL(CSM_GAMMA_RHOTRACK, csm3, gamma_rho_trk);
+		STB0899_SETFIELD_VAL(CSM_LOCKCOUNT_THRESH, csm4, lock_count_thr);
+		STB0899_SETFIELD_VAL(CSM_PHASEDIFF_THRESH, csm4, phs_diff_thr);
+
+		stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CSM_CNTRL1, STB0899_OFF0_CSM_CNTRL1, csm1);
+		stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CSM_CNTRL2, STB0899_OFF0_CSM_CNTRL2, csm2);
+		stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CSM_CNTRL3, STB0899_OFF0_CSM_CNTRL3, csm3);
+		stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CSM_CNTRL4, STB0899_OFF0_CSM_CNTRL4, csm4);
+	}
+}
+
+/*
+ * stb0899_dvbs2_get_srate
+ * get DVB-S2 Symbol Rate
+ */
+static u32 stb0899_dvbs2_get_srate(struct stb0899_state *state)
+{
+	struct stb0899_internal *internal = &state->internal;
+	struct stb0899_config *config = state->config;
+
+	u32 bTrNomFreq, srate, decimRate, intval1, intval2, reg;
+	int div1, div2, rem1, rem2;
+
+	div1 = config->btr_nco_bits / 2;
+	div2 = config->btr_nco_bits - div1 - 1;
+
+	bTrNomFreq = STB0899_READ_S2REG(STB0899_S2DEMOD, BTR_NOM_FREQ);
+
+	reg = STB0899_READ_S2REG(STB0899_S2DEMOD, DECIM_CNTRL);
+	decimRate = STB0899_GETFIELD(DECIM_RATE, reg);
+	decimRate = (1 << decimRate);
+
+	intval1 = internal->master_clk / (1 << div1);
+	intval2 = bTrNomFreq / (1 << div2);
+
+	rem1 = internal->master_clk % (1 << div1);
+	rem2 = bTrNomFreq % (1 << div2);
+	/* only for integer calculation	*/
+	srate = (intval1 * intval2) + ((intval1 * rem2) / (1 << div2)) + ((intval2 * rem1) / (1 << div1));
+	srate /= decimRate;	/*symbrate = (btrnomfreq_register_val*MasterClock)/2^(27+decim_rate_field) */
+
+	return	srate;
+}
+
+/*
+ * stb0899_dvbs2_algo
+ * Search for signal, timing, carrier and data for a given
+ * frequency in a given range
+ */
+enum stb0899_status stb0899_dvbs2_algo(struct stb0899_state *state)
+{
+	struct stb0899_internal *internal = &state->internal;
+	enum stb0899_modcod modcod;
+
+	s32 offsetfreq, searchTime, FecLockTime, pilots, iqSpectrum;
+	int i = 0;
+	u32 reg, csm1;
+
+	if (internal->srate <= 2000000) {
+		searchTime	= 5000;	/* 5000 ms max time to lock UWP and CSM, SYMB <= 2Mbs		*/
+		FecLockTime	= 350;	/* 350  ms max time to lock FEC, SYMB <= 2Mbs			*/
+	} else if (internal->srate <= 5000000) {
+		searchTime	= 2500;	/* 2500 ms max time to lock UWP and CSM, 2Mbs < SYMB <= 5Mbs	*/
+		FecLockTime	= 170;	/* 170  ms max time to lock FEC, 2Mbs< SYMB <= 5Mbs		*/
+	} else if (internal->srate <= 10000000) {
+		searchTime	= 1500;	/* 1500 ms max time to lock UWP and CSM, 5Mbs <SYMB <= 10Mbs	*/
+		FecLockTime	= 80;	/* 80  ms max time to lock FEC, 5Mbs< SYMB <= 10Mbs		*/
+	} else if (internal->srate <= 15000000) {
+		searchTime	= 500;	/* 500 ms max time to lock UWP and CSM, 10Mbs <SYMB <= 15Mbs	*/
+		FecLockTime	= 50;	/* 50  ms max time to lock FEC, 10Mbs< SYMB <= 15Mbs		*/
+	} else if (internal->srate <= 20000000) {
+		searchTime	= 300;	/* 300 ms max time to lock UWP and CSM, 15Mbs < SYMB <= 20Mbs	*/
+		FecLockTime	= 30;	/* 50  ms max time to lock FEC, 15Mbs< SYMB <= 20Mbs		*/
+	} else if (internal->srate <= 25000000) {
+		searchTime	= 250;	/* 250 ms max time to lock UWP and CSM, 20 Mbs < SYMB <= 25Mbs	*/
+		FecLockTime	= 25;	/* 25 ms max time to lock FEC, 20Mbs< SYMB <= 25Mbs		*/
+	} else {
+		searchTime	= 150;	/* 150 ms max time to lock UWP and CSM, SYMB > 25Mbs		*/
+		FecLockTime	= 20;	/* 20 ms max time to lock FEC, 20Mbs< SYMB <= 25Mbs		*/
+	}
+
+	/* Maintain Stream Merger in reset during acquisition	*/
+	reg = stb0899_read_reg(state, STB0899_TSTRES);
+	STB0899_SETFIELD_VAL(FRESRS, reg, 1);
+	stb0899_write_reg(state, STB0899_TSTRES, reg);
+
+	/* enable tuner I/O */
+	stb0899_i2c_gate_ctrl(&state->frontend, 1);
+
+	/* Move tuner to frequency	*/
+	if (state->config->tuner_set_frequency)
+		state->config->tuner_set_frequency(&state->frontend, internal->freq);
+	if (state->config->tuner_get_frequency)
+		state->config->tuner_get_frequency(&state->frontend, &internal->freq);
+
+	/* disable tuner I/O */
+	stb0899_i2c_gate_ctrl(&state->frontend, 0);
+
+	/* Set IF AGC to acquisition	*/
+	reg = STB0899_READ_S2REG(STB0899_S2DEMOD, IF_AGC_CNTRL);
+	STB0899_SETFIELD_VAL(IF_LOOP_GAIN, reg,  4);
+	STB0899_SETFIELD_VAL(IF_AGC_REF, reg, 32);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_IF_AGC_CNTRL, STB0899_OFF0_IF_AGC_CNTRL, reg);
+
+	reg = STB0899_READ_S2REG(STB0899_S2DEMOD, IF_AGC_CNTRL2);
+	STB0899_SETFIELD_VAL(IF_AGC_DUMP_PER, reg, 0);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_IF_AGC_CNTRL2, STB0899_OFF0_IF_AGC_CNTRL2, reg);
+
+	/* Initialisation	*/
+	stb0899_dvbs2_init_calc(state);
+
+	reg = STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_CNTRL2);
+	switch (internal->inversion) {
+	case IQ_SWAP_OFF:
+		STB0899_SETFIELD_VAL(SPECTRUM_INVERT, reg, 0);
+		break;
+	case IQ_SWAP_ON:
+		STB0899_SETFIELD_VAL(SPECTRUM_INVERT, reg, 1);
+		break;
+	case IQ_SWAP_AUTO:	/* use last successful search first	*/
+		STB0899_SETFIELD_VAL(SPECTRUM_INVERT, reg, 1);
+		break;
+	}
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_DMD_CNTRL2, STB0899_OFF0_DMD_CNTRL2, reg);
+	stb0899_dvbs2_reacquire(state);
+
+	/* Wait for demod lock (UWP and CSM)	*/
+	internal->status = stb0899_dvbs2_get_dmd_status(state, searchTime);
+
+	if (internal->status == DVBS2_DEMOD_LOCK) {
+		dprintk(state->verbose, FE_DEBUG, 1, "------------> DVB-S2 DEMOD LOCK !");
+		i = 0;
+		/* Demod Locked, check FEC status	*/
+		internal->status = stb0899_dvbs2_get_fec_status(state, FecLockTime);
+
+		/*If false lock (UWP and CSM Locked but no FEC) try 3 time max*/
+		while ((internal->status != DVBS2_FEC_LOCK) && (i < 3)) {
+			/*	Read the frequency offset*/
+			offsetfreq = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_FREQ);
+
+			/* Set the Nominal frequency to the found frequency offset for the next reacquire*/
+			reg = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_NOM_FREQ);
+			STB0899_SETFIELD_VAL(CRL_NOM_FREQ, reg, offsetfreq);
+			stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CRL_NOM_FREQ, STB0899_OFF0_CRL_NOM_FREQ, reg);
+			stb0899_dvbs2_reacquire(state);
+			internal->status = stb0899_dvbs2_get_fec_status(state, searchTime);
+			i++;
+		}
+	}
+
+	if (internal->status != DVBS2_FEC_LOCK) {
+		if (internal->inversion == IQ_SWAP_AUTO) {
+			reg = STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_CNTRL2);
+			iqSpectrum = STB0899_GETFIELD(SPECTRUM_INVERT, reg);
+			/* IQ Spectrum Inversion	*/
+			STB0899_SETFIELD_VAL(SPECTRUM_INVERT, reg, !iqSpectrum);
+			stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_DMD_CNTRL2, STB0899_OFF0_DMD_CNTRL2, reg);
+			/* start acquistion process	*/
+			stb0899_dvbs2_reacquire(state);
+
+			/* Wait for demod lock (UWP and CSM)	*/
+			internal->status = stb0899_dvbs2_get_dmd_status(state, searchTime);
+			if (internal->status == DVBS2_DEMOD_LOCK) {
+				i = 0;
+				/* Demod Locked, check FEC	*/
+				internal->status = stb0899_dvbs2_get_fec_status(state, FecLockTime);
+				/*try thrice for false locks, (UWP and CSM Locked but no FEC)	*/
+				while ((internal->status != DVBS2_FEC_LOCK) && (i < 3)) {
+					/*	Read the frequency offset*/
+					offsetfreq = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_FREQ);
+
+					/* Set the Nominal frequency to the found frequency offset for the next reacquire*/
+					reg = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_NOM_FREQ);
+					STB0899_SETFIELD_VAL(CRL_NOM_FREQ, reg, offsetfreq);
+					stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CRL_NOM_FREQ, STB0899_OFF0_CRL_NOM_FREQ, reg);
+
+					stb0899_dvbs2_reacquire(state);
+					internal->status = stb0899_dvbs2_get_fec_status(state, searchTime);
+					i++;
+				}
+			}
+/*
+			if (pParams->DVBS2State == FE_DVBS2_FEC_LOCKED)
+				pParams->IQLocked = !iqSpectrum;
+*/
+		}
+	}
+	if (internal->status == DVBS2_FEC_LOCK) {
+		dprintk(state->verbose, FE_DEBUG, 1, "----------------> DVB-S2 FEC Lock !");
+		reg = STB0899_READ_S2REG(STB0899_S2DEMOD, UWP_STAT2);
+		modcod = STB0899_GETFIELD(UWP_DECODE_MOD, reg) >> 2;
+		pilots = STB0899_GETFIELD(UWP_DECODE_MOD, reg) & 0x01;
+
+		if ((((10 * internal->master_clk) / (internal->srate / 10)) <= 410) &&
+		      (INRANGE(STB0899_QPSK_23, modcod, STB0899_QPSK_910)) &&
+		      (pilots == 1)) {
+
+			stb0899_dvbs2_init_csm(state, pilots, modcod);
+			/* Wait for UWP,CSM and data LOCK 20ms max	*/
+			internal->status = stb0899_dvbs2_get_fec_status(state, FecLockTime);
+
+			i = 0;
+			while ((internal->status != DVBS2_FEC_LOCK) && (i < 3)) {
+				csm1 = STB0899_READ_S2REG(STB0899_S2DEMOD, CSM_CNTRL1);
+				STB0899_SETFIELD_VAL(CSM_TWO_PASS, csm1, 1);
+				stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CSM_CNTRL1, STB0899_OFF0_CSM_CNTRL1, csm1);
+				csm1 = STB0899_READ_S2REG(STB0899_S2DEMOD, CSM_CNTRL1);
+				STB0899_SETFIELD_VAL(CSM_TWO_PASS, csm1, 0);
+				stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CSM_CNTRL1, STB0899_OFF0_CSM_CNTRL1, csm1);
+
+				internal->status = stb0899_dvbs2_get_fec_status(state, FecLockTime);
+				i++;
+			}
+		}
+
+		if ((((10 * internal->master_clk) / (internal->srate / 10)) <= 410) &&
+		      (INRANGE(STB0899_QPSK_12, modcod, STB0899_QPSK_35)) &&
+		      (pilots == 1)) {
+
+			/* Equalizer Disable update	 */
+			reg = STB0899_READ_S2REG(STB0899_S2DEMOD, EQ_CNTRL);
+			STB0899_SETFIELD_VAL(EQ_DISABLE_UPDATE, reg, 1);
+			stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_EQ_CNTRL, STB0899_OFF0_EQ_CNTRL, reg);
+		}
+
+		/* slow down the Equalizer once locked	*/
+		reg = STB0899_READ_S2REG(STB0899_S2DEMOD, EQ_CNTRL);
+		STB0899_SETFIELD_VAL(EQ_SHIFT, reg, 0x02);
+		stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_EQ_CNTRL, STB0899_OFF0_EQ_CNTRL, reg);
+
+		/* Store signal parameters	*/
+		offsetfreq = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_FREQ);
+
+		offsetfreq = offsetfreq / ((1 << 30) / 1000);
+		offsetfreq *= (internal->master_clk / 1000000);
+		reg = STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_CNTRL2);
+		if (STB0899_GETFIELD(SPECTRUM_INVERT, reg))
+			offsetfreq *= -1;
+
+		internal->freq = internal->freq - offsetfreq;
+		internal->srate = stb0899_dvbs2_get_srate(state);
+
+		reg = STB0899_READ_S2REG(STB0899_S2DEMOD, UWP_STAT2);
+		internal->modcod = STB0899_GETFIELD(UWP_DECODE_MOD, reg) >> 2;
+		internal->pilots = STB0899_GETFIELD(UWP_DECODE_MOD, reg) & 0x01;
+		internal->frame_length = (STB0899_GETFIELD(UWP_DECODE_MOD, reg) >> 1) & 0x01;
+
+		 /* Set IF AGC to tracking	*/
+		reg = STB0899_READ_S2REG(STB0899_S2DEMOD, IF_AGC_CNTRL);
+		STB0899_SETFIELD_VAL(IF_LOOP_GAIN, reg,  3);
+
+		/* if QPSK 1/2,QPSK 3/5 or QPSK 2/3 set IF AGC reference to 16 otherwise 32*/
+		if (INRANGE(STB0899_QPSK_12, internal->modcod, STB0899_QPSK_23))
+			STB0899_SETFIELD_VAL(IF_AGC_REF, reg, 16);
+
+		stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_IF_AGC_CNTRL, STB0899_OFF0_IF_AGC_CNTRL, reg);
+
+		reg = STB0899_READ_S2REG(STB0899_S2DEMOD, IF_AGC_CNTRL2);
+		STB0899_SETFIELD_VAL(IF_AGC_DUMP_PER, reg, 7);
+		stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_IF_AGC_CNTRL2, STB0899_OFF0_IF_AGC_CNTRL2, reg);
+	}
+
+	/* Release Stream Merger Reset		*/
+	reg = stb0899_read_reg(state, STB0899_TSTRES);
+	STB0899_SETFIELD_VAL(FRESRS, reg, 0);
+	stb0899_write_reg(state, STB0899_TSTRES, reg);
+
+	return internal->status;
+}
diff --git a/drivers/media/dvb-frontends/stb0899_cfg.h b/drivers/media/dvb-frontends/stb0899_cfg.h
new file mode 100644
index 0000000..0867906
--- /dev/null
+++ b/drivers/media/dvb-frontends/stb0899_cfg.h
@@ -0,0 +1,287 @@
+/*
+	STB0899 Multistandard Frontend driver
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	Copyright (C) ST Microelectronics
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the 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 __STB0899_CFG_H
+#define __STB0899_CFG_H
+
+static const struct stb0899_s2_reg  stb0899_s2_init_2[] = {
+
+	{ STB0899_OFF0_DMD_STATUS	, STB0899_BASE_DMD_STATUS	, 0x00000103 },	/* DMDSTATUS	*/
+	{ STB0899_OFF0_CRL_FREQ		, STB0899_BASE_CRL_FREQ		, 0x3ed1da56 },	/* CRLFREQ	*/
+	{ STB0899_OFF0_BTR_FREQ		, STB0899_BASE_BTR_FREQ		, 0x00004000 },	/* BTRFREQ	*/
+	{ STB0899_OFF0_IF_AGC_GAIN	, STB0899_BASE_IF_AGC_GAIN	, 0x00002ade },	/* IFAGCGAIN	*/
+	{ STB0899_OFF0_BB_AGC_GAIN	, STB0899_BASE_BB_AGC_GAIN	, 0x000001bc },	/* BBAGCGAIN	*/
+	{ STB0899_OFF0_DC_OFFSET	, STB0899_BASE_DC_OFFSET	, 0x00000200 },	/* DCOFFSET	*/
+	{ STB0899_OFF0_DMD_CNTRL	, STB0899_BASE_DMD_CNTRL	, 0x0000000f },	/* DMDCNTRL	*/
+
+	{ STB0899_OFF0_IF_AGC_CNTRL	, STB0899_BASE_IF_AGC_CNTRL	, 0x03fb4a20 },	/* IFAGCCNTRL	*/
+	{ STB0899_OFF0_BB_AGC_CNTRL	, STB0899_BASE_BB_AGC_CNTRL	, 0x00200c97 },	/* BBAGCCNTRL	*/
+
+	{ STB0899_OFF0_CRL_CNTRL	, STB0899_BASE_CRL_CNTRL	, 0x00000016 },	/* CRLCNTRL	*/
+	{ STB0899_OFF0_CRL_PHS_INIT	, STB0899_BASE_CRL_PHS_INIT	, 0x00000000 },	/* CRLPHSINIT	*/
+	{ STB0899_OFF0_CRL_FREQ_INIT	, STB0899_BASE_CRL_FREQ_INIT	, 0x00000000 },	/* CRLFREQINIT	*/
+	{ STB0899_OFF0_CRL_LOOP_GAIN	, STB0899_BASE_CRL_LOOP_GAIN	, 0x00000000 },	/* CRLLOOPGAIN	*/
+	{ STB0899_OFF0_CRL_NOM_FREQ	, STB0899_BASE_CRL_NOM_FREQ	, 0x3ed097b6 },	/* CRLNOMFREQ	*/
+	{ STB0899_OFF0_CRL_SWP_RATE	, STB0899_BASE_CRL_SWP_RATE	, 0x00000000 },	/* CRLSWPRATE	*/
+	{ STB0899_OFF0_CRL_MAX_SWP	, STB0899_BASE_CRL_MAX_SWP	, 0x00000000 },	/* CRLMAXSWP	*/
+	{ STB0899_OFF0_CRL_LK_CNTRL	, STB0899_BASE_CRL_LK_CNTRL	, 0x0f6cdc01 },	/* CRLLKCNTRL	*/
+	{ STB0899_OFF0_DECIM_CNTRL	, STB0899_BASE_DECIM_CNTRL	, 0x00000000 },	/* DECIMCNTRL	*/
+	{ STB0899_OFF0_BTR_CNTRL	, STB0899_BASE_BTR_CNTRL	, 0x00003993 },	/* BTRCNTRL	*/
+	{ STB0899_OFF0_BTR_LOOP_GAIN	, STB0899_BASE_BTR_LOOP_GAIN	, 0x000d3c6f },	/* BTRLOOPGAIN	*/
+	{ STB0899_OFF0_BTR_PHS_INIT	, STB0899_BASE_BTR_PHS_INIT	, 0x00000000 },	/* BTRPHSINIT	*/
+	{ STB0899_OFF0_BTR_FREQ_INIT	, STB0899_BASE_BTR_FREQ_INIT	, 0x00000000 },	/* BTRFREQINIT	*/
+	{ STB0899_OFF0_BTR_NOM_FREQ	, STB0899_BASE_BTR_NOM_FREQ	, 0x0238e38e },	/* BTRNOMFREQ	*/
+	{ STB0899_OFF0_BTR_LK_CNTRL	, STB0899_BASE_BTR_LK_CNTRL	, 0x00000000 },	/* BTRLKCNTRL	*/
+	{ STB0899_OFF0_DECN_CNTRL	, STB0899_BASE_DECN_CNTRL	, 0x00000000 },	/* DECNCNTRL	*/
+	{ STB0899_OFF0_TP_CNTRL		, STB0899_BASE_TP_CNTRL		, 0x00000000 },	/* TPCNTRL	*/
+	{ STB0899_OFF0_TP_BUF_STATUS	, STB0899_BASE_TP_BUF_STATUS	, 0x00000000 },	/* TPBUFSTATUS	*/
+	{ STB0899_OFF0_DC_ESTIM		, STB0899_BASE_DC_ESTIM		, 0x00000000 },	/* DCESTIM	*/
+	{ STB0899_OFF0_FLL_CNTRL	, STB0899_BASE_FLL_CNTRL	, 0x00000000 },	/* FLLCNTRL	*/
+	{ STB0899_OFF0_FLL_FREQ_WD	, STB0899_BASE_FLL_FREQ_WD	, 0x40070000 },	/* FLLFREQWD	*/
+	{ STB0899_OFF0_ANTI_ALIAS_SEL	, STB0899_BASE_ANTI_ALIAS_SEL	, 0x00000001 },	/* ANTIALIASSEL */
+	{ STB0899_OFF0_RRC_ALPHA	, STB0899_BASE_RRC_ALPHA	, 0x00000002 },	/* RRCALPHA	*/
+	{ STB0899_OFF0_DC_ADAPT_LSHFT	, STB0899_BASE_DC_ADAPT_LSHFT	, 0x00000000 },	/* DCADAPTISHFT */
+	{ STB0899_OFF0_IMB_OFFSET	, STB0899_BASE_IMB_OFFSET	, 0x0000fe01 },	/* IMBOFFSET	*/
+	{ STB0899_OFF0_IMB_ESTIMATE	, STB0899_BASE_IMB_ESTIMATE	, 0x00000000 },	/* IMBESTIMATE	*/
+	{ STB0899_OFF0_IMB_CNTRL	, STB0899_BASE_IMB_CNTRL	, 0x00000001 },	/* IMBCNTRL	*/
+	{ STB0899_OFF0_IF_AGC_CNTRL2	, STB0899_BASE_IF_AGC_CNTRL2	, 0x00005007 },	/* IFAGCCNTRL2	*/
+	{ STB0899_OFF0_DMD_CNTRL2	, STB0899_BASE_DMD_CNTRL2	, 0x00000002 },	/* DMDCNTRL2	*/
+	{ STB0899_OFF0_TP_BUFFER	, STB0899_BASE_TP_BUFFER	, 0x00000000 },	/* TPBUFFER	*/
+	{ STB0899_OFF0_TP_BUFFER1	, STB0899_BASE_TP_BUFFER1	, 0x00000000 },	/* TPBUFFER1	*/
+	{ STB0899_OFF0_TP_BUFFER2	, STB0899_BASE_TP_BUFFER2	, 0x00000000 },	/* TPBUFFER2	*/
+	{ STB0899_OFF0_TP_BUFFER3	, STB0899_BASE_TP_BUFFER3	, 0x00000000 },	/* TPBUFFER3	*/
+	{ STB0899_OFF0_TP_BUFFER4	, STB0899_BASE_TP_BUFFER4	, 0x00000000 },	/* TPBUFFER4	*/
+	{ STB0899_OFF0_TP_BUFFER5	, STB0899_BASE_TP_BUFFER5	, 0x00000000 },	/* TPBUFFER5	*/
+	{ STB0899_OFF0_TP_BUFFER6	, STB0899_BASE_TP_BUFFER6	, 0x00000000 },	/* TPBUFFER6	*/
+	{ STB0899_OFF0_TP_BUFFER7	, STB0899_BASE_TP_BUFFER7	, 0x00000000 },	/* TPBUFFER7	*/
+	{ STB0899_OFF0_TP_BUFFER8	, STB0899_BASE_TP_BUFFER8	, 0x00000000 },	/* TPBUFFER8	*/
+	{ STB0899_OFF0_TP_BUFFER9	, STB0899_BASE_TP_BUFFER9	, 0x00000000 },	/* TPBUFFER9	*/
+	{ STB0899_OFF0_TP_BUFFER10	, STB0899_BASE_TP_BUFFER10	, 0x00000000 },	/* TPBUFFER10	*/
+	{ STB0899_OFF0_TP_BUFFER11	, STB0899_BASE_TP_BUFFER11	, 0x00000000 },	/* TPBUFFER11	*/
+	{ STB0899_OFF0_TP_BUFFER12	, STB0899_BASE_TP_BUFFER12	, 0x00000000 },	/* TPBUFFER12	*/
+	{ STB0899_OFF0_TP_BUFFER13	, STB0899_BASE_TP_BUFFER13	, 0x00000000 },	/* TPBUFFER13	*/
+	{ STB0899_OFF0_TP_BUFFER14	, STB0899_BASE_TP_BUFFER14	, 0x00000000 },	/* TPBUFFER14	*/
+	{ STB0899_OFF0_TP_BUFFER15	, STB0899_BASE_TP_BUFFER15	, 0x00000000 },	/* TPBUFFER15	*/
+	{ STB0899_OFF0_TP_BUFFER16	, STB0899_BASE_TP_BUFFER16	, 0x0000ff00 },	/* TPBUFFER16	*/
+	{ STB0899_OFF0_TP_BUFFER17	, STB0899_BASE_TP_BUFFER17	, 0x00000100 },	/* TPBUFFER17	*/
+	{ STB0899_OFF0_TP_BUFFER18	, STB0899_BASE_TP_BUFFER18	, 0x0000fe01 },	/* TPBUFFER18	*/
+	{ STB0899_OFF0_TP_BUFFER19	, STB0899_BASE_TP_BUFFER19	, 0x000004fe },	/* TPBUFFER19	*/
+	{ STB0899_OFF0_TP_BUFFER20	, STB0899_BASE_TP_BUFFER20	, 0x0000cfe7 },	/* TPBUFFER20	*/
+	{ STB0899_OFF0_TP_BUFFER21	, STB0899_BASE_TP_BUFFER21	, 0x0000bec6 },	/* TPBUFFER21	*/
+	{ STB0899_OFF0_TP_BUFFER22	, STB0899_BASE_TP_BUFFER22	, 0x0000c2bf },	/* TPBUFFER22	*/
+	{ STB0899_OFF0_TP_BUFFER23	, STB0899_BASE_TP_BUFFER23	, 0x0000c1c1 },	/* TPBUFFER23	*/
+	{ STB0899_OFF0_TP_BUFFER24	, STB0899_BASE_TP_BUFFER24	, 0x0000c1c1 },	/* TPBUFFER24	*/
+	{ STB0899_OFF0_TP_BUFFER25	, STB0899_BASE_TP_BUFFER25	, 0x0000c1c1 },	/* TPBUFFER25	*/
+	{ STB0899_OFF0_TP_BUFFER26	, STB0899_BASE_TP_BUFFER26	, 0x0000c1c1 },	/* TPBUFFER26	*/
+	{ STB0899_OFF0_TP_BUFFER27	, STB0899_BASE_TP_BUFFER27	, 0x0000c1c0 },	/* TPBUFFER27	*/
+	{ STB0899_OFF0_TP_BUFFER28	, STB0899_BASE_TP_BUFFER28	, 0x0000c0c0 },	/* TPBUFFER28	*/
+	{ STB0899_OFF0_TP_BUFFER29	, STB0899_BASE_TP_BUFFER29	, 0x0000c1c1 },	/* TPBUFFER29	*/
+	{ STB0899_OFF0_TP_BUFFER30	, STB0899_BASE_TP_BUFFER30	, 0x0000c1c1 },	/* TPBUFFER30	*/
+	{ STB0899_OFF0_TP_BUFFER31	, STB0899_BASE_TP_BUFFER31	, 0x0000c0c1 },	/* TPBUFFER31	*/
+	{ STB0899_OFF0_TP_BUFFER32	, STB0899_BASE_TP_BUFFER32	, 0x0000c0c1 },	/* TPBUFFER32	*/
+	{ STB0899_OFF0_TP_BUFFER33	, STB0899_BASE_TP_BUFFER33	, 0x0000c1c1 },	/* TPBUFFER33	*/
+	{ STB0899_OFF0_TP_BUFFER34	, STB0899_BASE_TP_BUFFER34	, 0x0000c1c1 },	/* TPBUFFER34	*/
+	{ STB0899_OFF0_TP_BUFFER35	, STB0899_BASE_TP_BUFFER35	, 0x0000c0c1 },	/* TPBUFFER35	*/
+	{ STB0899_OFF0_TP_BUFFER36	, STB0899_BASE_TP_BUFFER36	, 0x0000c1c1 },	/* TPBUFFER36	*/
+	{ STB0899_OFF0_TP_BUFFER37	, STB0899_BASE_TP_BUFFER37	, 0x0000c0c1 },	/* TPBUFFER37	*/
+	{ STB0899_OFF0_TP_BUFFER38	, STB0899_BASE_TP_BUFFER38	, 0x0000c1c1 },	/* TPBUFFER38	*/
+	{ STB0899_OFF0_TP_BUFFER39	, STB0899_BASE_TP_BUFFER39	, 0x0000c0c0 },	/* TPBUFFER39	*/
+	{ STB0899_OFF0_TP_BUFFER40	, STB0899_BASE_TP_BUFFER40	, 0x0000c1c0 },	/* TPBUFFER40	*/
+	{ STB0899_OFF0_TP_BUFFER41	, STB0899_BASE_TP_BUFFER41	, 0x0000c1c1 },	/* TPBUFFER41	*/
+	{ STB0899_OFF0_TP_BUFFER42	, STB0899_BASE_TP_BUFFER42	, 0x0000c0c0 },	/* TPBUFFER42	*/
+	{ STB0899_OFF0_TP_BUFFER43	, STB0899_BASE_TP_BUFFER43	, 0x0000c1c0 },	/* TPBUFFER43	*/
+	{ STB0899_OFF0_TP_BUFFER44	, STB0899_BASE_TP_BUFFER44	, 0x0000c0c1 },	/* TPBUFFER44	*/
+	{ STB0899_OFF0_TP_BUFFER45	, STB0899_BASE_TP_BUFFER45	, 0x0000c1be },	/* TPBUFFER45	*/
+	{ STB0899_OFF0_TP_BUFFER46	, STB0899_BASE_TP_BUFFER46	, 0x0000c1c9 },	/* TPBUFFER46	*/
+	{ STB0899_OFF0_TP_BUFFER47	, STB0899_BASE_TP_BUFFER47	, 0x0000c0da },	/* TPBUFFER47	*/
+	{ STB0899_OFF0_TP_BUFFER48	, STB0899_BASE_TP_BUFFER48	, 0x0000c0ba },	/* TPBUFFER48	*/
+	{ STB0899_OFF0_TP_BUFFER49	, STB0899_BASE_TP_BUFFER49	, 0x0000c1c4 },	/* TPBUFFER49	*/
+	{ STB0899_OFF0_TP_BUFFER50	, STB0899_BASE_TP_BUFFER50	, 0x0000c1bf },	/* TPBUFFER50	*/
+	{ STB0899_OFF0_TP_BUFFER51	, STB0899_BASE_TP_BUFFER51	, 0x0000c0c1 },	/* TPBUFFER51	*/
+	{ STB0899_OFF0_TP_BUFFER52	, STB0899_BASE_TP_BUFFER52	, 0x0000c1c0 },	/* TPBUFFER52	*/
+	{ STB0899_OFF0_TP_BUFFER53	, STB0899_BASE_TP_BUFFER53	, 0x0000c0c1 },	/* TPBUFFER53	*/
+	{ STB0899_OFF0_TP_BUFFER54	, STB0899_BASE_TP_BUFFER54	, 0x0000c1c1 },	/* TPBUFFER54	*/
+	{ STB0899_OFF0_TP_BUFFER55	, STB0899_BASE_TP_BUFFER55	, 0x0000c1c1 },	/* TPBUFFER55	*/
+	{ STB0899_OFF0_TP_BUFFER56	, STB0899_BASE_TP_BUFFER56	, 0x0000c1c1 },	/* TPBUFFER56	*/
+	{ STB0899_OFF0_TP_BUFFER57	, STB0899_BASE_TP_BUFFER57	, 0x0000c1c1 },	/* TPBUFFER57	*/
+	{ STB0899_OFF0_TP_BUFFER58	, STB0899_BASE_TP_BUFFER58	, 0x0000c1c1 },	/* TPBUFFER58	*/
+	{ STB0899_OFF0_TP_BUFFER59	, STB0899_BASE_TP_BUFFER59	, 0x0000c1c1 },	/* TPBUFFER59	*/
+	{ STB0899_OFF0_TP_BUFFER60	, STB0899_BASE_TP_BUFFER60	, 0x0000c1c1 },	/* TPBUFFER60	*/
+	{ STB0899_OFF0_TP_BUFFER61	, STB0899_BASE_TP_BUFFER61	, 0x0000c1c1 },	/* TPBUFFER61	*/
+	{ STB0899_OFF0_TP_BUFFER62	, STB0899_BASE_TP_BUFFER62	, 0x0000c1c1 },	/* TPBUFFER62	*/
+	{ STB0899_OFF0_TP_BUFFER63	, STB0899_BASE_TP_BUFFER63	, 0x0000c1c0 },	/* TPBUFFER63	*/
+	{ STB0899_OFF0_RESET_CNTRL	, STB0899_BASE_RESET_CNTRL	, 0x00000001 },	/* RESETCNTRL	*/
+	{ STB0899_OFF0_ACM_ENABLE	, STB0899_BASE_ACM_ENABLE	, 0x00005654 },	/* ACMENABLE	*/
+	{ STB0899_OFF0_DESCR_CNTRL	, STB0899_BASE_DESCR_CNTRL	, 0x00000000 },	/* DESCRCNTRL	*/
+	{ STB0899_OFF0_CSM_CNTRL1	, STB0899_BASE_CSM_CNTRL1	, 0x00020019 },	/* CSMCNTRL1	*/
+	{ STB0899_OFF0_CSM_CNTRL2	, STB0899_BASE_CSM_CNTRL2	, 0x004b3237 },	/* CSMCNTRL2	*/
+	{ STB0899_OFF0_CSM_CNTRL3	, STB0899_BASE_CSM_CNTRL3	, 0x0003dd17 },	/* CSMCNTRL3	*/
+	{ STB0899_OFF0_CSM_CNTRL4	, STB0899_BASE_CSM_CNTRL4	, 0x00008008 },	/* CSMCNTRL4	*/
+	{ STB0899_OFF0_UWP_CNTRL1	, STB0899_BASE_UWP_CNTRL1	, 0x002a3106 },	/* UWPCNTRL1	*/
+	{ STB0899_OFF0_UWP_CNTRL2	, STB0899_BASE_UWP_CNTRL2	, 0x0006140a },	/* UWPCNTRL2	*/
+	{ STB0899_OFF0_UWP_STAT1	, STB0899_BASE_UWP_STAT1	, 0x00008000 },	/* UWPSTAT1	*/
+	{ STB0899_OFF0_UWP_STAT2	, STB0899_BASE_UWP_STAT2	, 0x00000000 },	/* UWPSTAT2	*/
+	{ STB0899_OFF0_DMD_STAT2	, STB0899_BASE_DMD_STAT2	, 0x00000000 },	/* DMDSTAT2	*/
+	{ STB0899_OFF0_FREQ_ADJ_SCALE	, STB0899_BASE_FREQ_ADJ_SCALE	, 0x00000471 },	/* FREQADJSCALE */
+	{ STB0899_OFF0_UWP_CNTRL3	, STB0899_BASE_UWP_CNTRL3	, 0x017b0465 },	/* UWPCNTRL3	*/
+	{ STB0899_OFF0_SYM_CLK_SEL	, STB0899_BASE_SYM_CLK_SEL	, 0x00000002 },	/* SYMCLKSEL	*/
+	{ STB0899_OFF0_SOF_SRCH_TO	, STB0899_BASE_SOF_SRCH_TO	, 0x00196464 },	/* SOFSRCHTO	*/
+	{ STB0899_OFF0_ACQ_CNTRL1	, STB0899_BASE_ACQ_CNTRL1	, 0x00000603 },	/* ACQCNTRL1	*/
+	{ STB0899_OFF0_ACQ_CNTRL2	, STB0899_BASE_ACQ_CNTRL2	, 0x02046666 },	/* ACQCNTRL2	*/
+	{ STB0899_OFF0_ACQ_CNTRL3	, STB0899_BASE_ACQ_CNTRL3	, 0x10046583 },	/* ACQCNTRL3	*/
+	{ STB0899_OFF0_FE_SETTLE	, STB0899_BASE_FE_SETTLE	, 0x00010404 },	/* FESETTLE	*/
+	{ STB0899_OFF0_AC_DWELL		, STB0899_BASE_AC_DWELL		, 0x0002aa8a },	/* ACDWELL	*/
+	{ STB0899_OFF0_ACQUIRE_TRIG	, STB0899_BASE_ACQUIRE_TRIG	, 0x00000000 },	/* ACQUIRETRIG	*/
+	{ STB0899_OFF0_LOCK_LOST	, STB0899_BASE_LOCK_LOST	, 0x00000001 },	/* LOCKLOST	*/
+	{ STB0899_OFF0_ACQ_STAT1	, STB0899_BASE_ACQ_STAT1	, 0x00000500 },	/* ACQSTAT1	*/
+	{ STB0899_OFF0_ACQ_TIMEOUT	, STB0899_BASE_ACQ_TIMEOUT	, 0x0028a0a0 },	/* ACQTIMEOUT	*/
+	{ STB0899_OFF0_ACQ_TIME		, STB0899_BASE_ACQ_TIME		, 0x00000000 },	/* ACQTIME	*/
+	{ STB0899_OFF0_FINAL_AGC_CNTRL	, STB0899_BASE_FINAL_AGC_CNTRL	, 0x00800c17 },	/* FINALAGCCNTRL*/
+	{ STB0899_OFF0_FINAL_AGC_GAIN	, STB0899_BASE_FINAL_AGC_GAIN	, 0x00000000 },	/* FINALAGCCGAIN*/
+	{ STB0899_OFF0_EQUALIZER_INIT	, STB0899_BASE_EQUALIZER_INIT	, 0x00000000 },	/* EQUILIZERINIT*/
+	{ STB0899_OFF0_EQ_CNTRL		, STB0899_BASE_EQ_CNTRL		, 0x00054802 },	/* EQCNTL	*/
+	{ STB0899_OFF0_EQ_I_INIT_COEFF_0, STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000000 },	/* EQIINITCOEFF0 */
+	{ STB0899_OFF1_EQ_I_INIT_COEFF_1, STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000000 },	/* EQIINITCOEFF1 */
+	{ STB0899_OFF2_EQ_I_INIT_COEFF_2, STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000000 },	/* EQIINITCOEFF2 */
+	{ STB0899_OFF3_EQ_I_INIT_COEFF_3, STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000000 },	/* EQIINITCOEFF3 */
+	{ STB0899_OFF4_EQ_I_INIT_COEFF_4, STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000000 },	/* EQIINITCOEFF4 */
+	{ STB0899_OFF5_EQ_I_INIT_COEFF_5, STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000400 },	/* EQIINITCOEFF5 */
+	{ STB0899_OFF6_EQ_I_INIT_COEFF_6, STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000000 },	/* EQIINITCOEFF6 */
+	{ STB0899_OFF7_EQ_I_INIT_COEFF_7, STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000000 },	/* EQIINITCOEFF7 */
+	{ STB0899_OFF8_EQ_I_INIT_COEFF_8, STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000000 },	/* EQIINITCOEFF8 */
+	{ STB0899_OFF9_EQ_I_INIT_COEFF_9, STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000000 },	/* EQIINITCOEFF9 */
+	{ STB0899_OFFa_EQ_I_INIT_COEFF_10,STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000000 },	/* EQIINITCOEFF10*/
+	{ STB0899_OFF0_EQ_Q_INIT_COEFF_0, STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 },	/* EQQINITCOEFF0 */
+	{ STB0899_OFF1_EQ_Q_INIT_COEFF_1, STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 },	/* EQQINITCOEFF1 */
+	{ STB0899_OFF2_EQ_Q_INIT_COEFF_2, STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 },	/* EQQINITCOEFF2 */
+	{ STB0899_OFF3_EQ_Q_INIT_COEFF_3, STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 },	/* EQQINITCOEFF3 */
+	{ STB0899_OFF4_EQ_Q_INIT_COEFF_4, STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 },	/* EQQINITCOEFF4 */
+	{ STB0899_OFF5_EQ_Q_INIT_COEFF_5, STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 },	/* EQQINITCOEFF5 */
+	{ STB0899_OFF6_EQ_Q_INIT_COEFF_6, STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 },	/* EQQINITCOEFF6 */
+	{ STB0899_OFF7_EQ_Q_INIT_COEFF_7, STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 },	/* EQQINITCOEFF7 */
+	{ STB0899_OFF8_EQ_Q_INIT_COEFF_8, STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 },	/* EQQINITCOEFF8 */
+	{ STB0899_OFF9_EQ_Q_INIT_COEFF_9, STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 },	/* EQQINITCOEFF9 */
+	{ STB0899_OFFa_EQ_Q_INIT_COEFF_10,STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 },	/* EQQINITCOEFF10*/
+	{ STB0899_OFF0_EQ_I_OUT_COEFF_0	, STB0899_BASE_EQ_I_OUT_COEFF_N	, 0x00000000 }, /* EQICOEFFSOUT0 */
+	{ STB0899_OFF1_EQ_I_OUT_COEFF_1	, STB0899_BASE_EQ_I_OUT_COEFF_N	, 0x00000000 }, /* EQICOEFFSOUT1 */
+	{ STB0899_OFF2_EQ_I_OUT_COEFF_2	, STB0899_BASE_EQ_I_OUT_COEFF_N	, 0x00000000 }, /* EQICOEFFSOUT2 */
+	{ STB0899_OFF3_EQ_I_OUT_COEFF_3	, STB0899_BASE_EQ_I_OUT_COEFF_N	, 0x00000000 }, /* EQICOEFFSOUT3 */
+	{ STB0899_OFF4_EQ_I_OUT_COEFF_4	, STB0899_BASE_EQ_I_OUT_COEFF_N	, 0x00000000 }, /* EQICOEFFSOUT4 */
+	{ STB0899_OFF5_EQ_I_OUT_COEFF_5	, STB0899_BASE_EQ_I_OUT_COEFF_N	, 0x00000000 }, /* EQICOEFFSOUT5 */
+	{ STB0899_OFF6_EQ_I_OUT_COEFF_6	, STB0899_BASE_EQ_I_OUT_COEFF_N	, 0x00000000 }, /* EQICOEFFSOUT6 */
+	{ STB0899_OFF7_EQ_I_OUT_COEFF_7	, STB0899_BASE_EQ_I_OUT_COEFF_N	, 0x00000000 }, /* EQICOEFFSOUT7 */
+	{ STB0899_OFF8_EQ_I_OUT_COEFF_8	, STB0899_BASE_EQ_I_OUT_COEFF_N	, 0x00000000 }, /* EQICOEFFSOUT8 */
+	{ STB0899_OFF9_EQ_I_OUT_COEFF_9	, STB0899_BASE_EQ_I_OUT_COEFF_N	, 0x00000000 }, /* EQICOEFFSOUT9 */
+	{ STB0899_OFFa_EQ_I_OUT_COEFF_10,STB0899_BASE_EQ_I_OUT_COEFF_N	, 0x00000000 }, /* EQICOEFFSOUT10*/
+	{ STB0899_OFF0_EQ_Q_OUT_COEFF_0	, STB0899_BASE_EQ_Q_OUT_COEFF_N	, 0x00000000 },	/* EQQCOEFFSOUT0 */
+	{ STB0899_OFF1_EQ_Q_OUT_COEFF_1	, STB0899_BASE_EQ_Q_OUT_COEFF_N	, 0x00000000 },	/* EQQCOEFFSOUT1 */
+	{ STB0899_OFF2_EQ_Q_OUT_COEFF_2	, STB0899_BASE_EQ_Q_OUT_COEFF_N	, 0x00000000 },	/* EQQCOEFFSOUT2 */
+	{ STB0899_OFF3_EQ_Q_OUT_COEFF_3	, STB0899_BASE_EQ_Q_OUT_COEFF_N	, 0x00000000 },	/* EQQCOEFFSOUT3 */
+	{ STB0899_OFF4_EQ_Q_OUT_COEFF_4	, STB0899_BASE_EQ_Q_OUT_COEFF_N	, 0x00000000 },	/* EQQCOEFFSOUT4 */
+	{ STB0899_OFF5_EQ_Q_OUT_COEFF_5	, STB0899_BASE_EQ_Q_OUT_COEFF_N	, 0x00000000 },	/* EQQCOEFFSOUT5 */
+	{ STB0899_OFF6_EQ_Q_OUT_COEFF_6 , STB0899_BASE_EQ_Q_OUT_COEFF_N	, 0x00000000 },	/* EQQCOEFFSOUT6 */
+	{ STB0899_OFF7_EQ_Q_OUT_COEFF_7	, STB0899_BASE_EQ_Q_OUT_COEFF_N	, 0x00000000 },	/* EQQCOEFFSOUT7 */
+	{ STB0899_OFF8_EQ_Q_OUT_COEFF_8	, STB0899_BASE_EQ_Q_OUT_COEFF_N	, 0x00000000 },	/* EQQCOEFFSOUT8 */
+	{ STB0899_OFF9_EQ_Q_OUT_COEFF_9	, STB0899_BASE_EQ_Q_OUT_COEFF_N	, 0x00000000 },	/* EQQCOEFFSOUT9 */
+	{ STB0899_OFFa_EQ_Q_OUT_COEFF_10, STB0899_BASE_EQ_Q_OUT_COEFF_N	, 0x00000000 },	/* EQQCOEFFSOUT10*/
+	{ 0xffff			, 0xffffffff			, 0xffffffff },
+};
+static const struct stb0899_s2_reg stb0899_s2_init_4[] = {
+	{ STB0899_OFF0_BLOCK_LNGTH	, STB0899_BASE_BLOCK_LNGTH	, 0x00000008 },	/* BLOCKLNGTH	*/
+	{ STB0899_OFF0_ROW_STR		, STB0899_BASE_ROW_STR		, 0x000000b4 },	/* ROWSTR	*/
+	{ STB0899_OFF0_BN_END_ADDR	, STB0899_BASE_BN_END_ADDR	, 0x000004b5 },	/* BNANDADDR	*/
+	{ STB0899_OFF0_CN_END_ADDR	, STB0899_BASE_CN_END_ADDR	, 0x00000b4b },	/* CNANDADDR	*/
+	{ STB0899_OFF0_INFO_LENGTH	, STB0899_BASE_INFO_LENGTH	, 0x00000078 },	/* INFOLENGTH	*/
+	{ STB0899_OFF0_BOT_ADDR		, STB0899_BASE_BOT_ADDR		, 0x000001e0 },	/* BOT_ADDR	*/
+	{ STB0899_OFF0_BCH_BLK_LN	, STB0899_BASE_BCH_BLK_LN	, 0x0000a8c0 },	/* BCHBLKLN	*/
+	{ STB0899_OFF0_BCH_T		, STB0899_BASE_BCH_T		, 0x0000000c },	/* BCHT		*/
+	{ STB0899_OFF0_CNFG_MODE	, STB0899_BASE_CNFG_MODE	, 0x00000001 },	/* CNFGMODE	*/
+	{ STB0899_OFF0_LDPC_STAT	, STB0899_BASE_LDPC_STAT	, 0x0000000d },	/* LDPCSTAT	*/
+	{ STB0899_OFF0_ITER_SCALE	, STB0899_BASE_ITER_SCALE	, 0x00000040 },	/* ITERSCALE	*/
+	{ STB0899_OFF0_INPUT_MODE	, STB0899_BASE_INPUT_MODE	, 0x00000000 },	/* INPUTMODE	*/
+	{ STB0899_OFF0_LDPCDECRST	, STB0899_BASE_LDPCDECRST	, 0x00000000 },	/* LDPCDECRST	*/
+	{ STB0899_OFF0_CLK_PER_BYTE_RW	, STB0899_BASE_CLK_PER_BYTE_RW	, 0x00000008 },	/* CLKPERBYTE	*/
+	{ STB0899_OFF0_BCH_ERRORS	, STB0899_BASE_BCH_ERRORS	, 0x00000000 },	/* BCHERRORS	*/
+	{ STB0899_OFF0_LDPC_ERRORS	, STB0899_BASE_LDPC_ERRORS	, 0x00000000 },	/* LDPCERRORS	*/
+	{ STB0899_OFF0_BCH_MODE		, STB0899_BASE_BCH_MODE		, 0x00000000 },	/* BCHMODE	*/
+	{ STB0899_OFF0_ERR_ACC_PER	, STB0899_BASE_ERR_ACC_PER	, 0x00000008 },	/* ERRACCPER	*/
+	{ STB0899_OFF0_BCH_ERR_ACC	, STB0899_BASE_BCH_ERR_ACC	, 0x00000000 },	/* BCHERRACC	*/
+	{ STB0899_OFF0_FEC_TP_SEL	, STB0899_BASE_FEC_TP_SEL	, 0x00000000 },	/* FECTPSEL	*/
+	{ 0xffff			, 0xffffffff			, 0xffffffff },
+};
+
+static const struct stb0899_s1_reg stb0899_s1_init_5[] = {
+	{ STB0899_TSTCK		, 0x00 },
+	{ STB0899_TSTRES	, 0x00 },
+	{ STB0899_TSTOUT	, 0x00 },
+	{ STB0899_TSTIN		, 0x00 },
+	{ STB0899_TSTSYS	, 0x00 },
+	{ STB0899_TSTCHIP	, 0x00 },
+	{ STB0899_TSTFREE	, 0x00 },
+	{ STB0899_TSTI2C	, 0x00 },
+	{ STB0899_BITSPEEDM	, 0x00 },
+	{ STB0899_BITSPEEDL	, 0x00 },
+	{ STB0899_TBUSBIT	, 0x00 },
+	{ STB0899_TSTDIS	, 0x00 },
+	{ STB0899_TSTDISRX	, 0x00 },
+	{ STB0899_TSTJETON	, 0x00 },
+	{ STB0899_TSTDCADJ	, 0x00 },
+	{ STB0899_TSTAGC1	, 0x00 },
+	{ STB0899_TSTAGC1N	, 0x00 },
+	{ STB0899_TSTPOLYPH	, 0x00 },
+	{ STB0899_TSTR		, 0x00 },
+	{ STB0899_TSTAGC2	, 0x00 },
+	{ STB0899_TSTCTL1	, 0x00 },
+	{ STB0899_TSTCTL2	, 0x00 },
+	{ STB0899_TSTCTL3	, 0x00 },
+	{ STB0899_TSTDEMAP	, 0x00 },
+	{ STB0899_TSTDEMAP2	, 0x00 },
+	{ STB0899_TSTDEMMON	, 0x00 },
+	{ STB0899_TSTRATE	, 0x00 },
+	{ STB0899_TSTSELOUT	, 0x00 },
+	{ STB0899_TSYNC		, 0x00 },
+	{ STB0899_TSTERR	, 0x00 },
+	{ STB0899_TSTRAM1	, 0x00 },
+	{ STB0899_TSTVSELOUT	, 0x00 },
+	{ STB0899_TSTFORCEIN	, 0x00 },
+	{ STB0899_TSTRS1	, 0x00 },
+	{ STB0899_TSTRS2	, 0x00 },
+	{ STB0899_TSTRS3	, 0x00 },
+	{ STB0899_GHOSTREG	, 0x81 },
+	{ 0xffff		, 0xff },
+};
+
+#define STB0899_DVBS2_ESNO_AVE			3
+#define STB0899_DVBS2_ESNO_QUANT		32
+#define STB0899_DVBS2_AVFRAMES_COARSE		10
+#define STB0899_DVBS2_AVFRAMES_FINE		20
+#define STB0899_DVBS2_MISS_THRESHOLD		6
+#define STB0899_DVBS2_UWP_THRESHOLD_ACQ		1125
+#define STB0899_DVBS2_UWP_THRESHOLD_TRACK	758
+#define STB0899_DVBS2_UWP_THRESHOLD_SOF		1350
+#define STB0899_DVBS2_SOF_SEARCH_TIMEOUT	1664100
+
+#define STB0899_DVBS2_BTR_NCO_BITS		28
+#define STB0899_DVBS2_BTR_GAIN_SHIFT_OFFSET	15
+#define STB0899_DVBS2_CRL_NCO_BITS		30
+#define STB0899_DVBS2_LDPC_MAX_ITER		70
+
+#endif //__STB0899_CFG_H
diff --git a/drivers/media/dvb-frontends/stb0899_drv.c b/drivers/media/dvb-frontends/stb0899_drv.c
new file mode 100644
index 0000000..79e29de
--- /dev/null
+++ b/drivers/media/dvb-frontends/stb0899_drv.c
@@ -0,0 +1,1652 @@
+/*
+	STB0899 Multistandard Frontend driver
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	Copyright (C) ST Microelectronics
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the 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/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+
+#include <linux/dvb/frontend.h>
+#include "dvb_frontend.h"
+
+#include "stb0899_drv.h"
+#include "stb0899_priv.h"
+#include "stb0899_reg.h"
+
+static unsigned int verbose = 0;//1;
+module_param(verbose, int, 0644);
+
+/* C/N in dB/10, NIRM/NIRL */
+static const struct stb0899_tab stb0899_cn_tab[] = {
+	{ 200,	2600 },
+	{ 190,	2700 },
+	{ 180,	2860 },
+	{ 170,	3020 },
+	{ 160,	3210 },
+	{ 150,	3440 },
+	{ 140,	3710 },
+	{ 130,	4010 },
+	{ 120,	4360 },
+	{ 110,	4740 },
+	{ 100,	5190 },
+	{ 90,	5670 },
+	{ 80,	6200 },
+	{ 70,	6770 },
+	{ 60,	7360 },
+	{ 50,	7970 },
+	{ 40,	8250 },
+	{ 30,	9000 },
+	{ 20,	9450 },
+	{ 15,	9600 },
+};
+
+/* DVB-S AGCIQ_VALUE vs. signal level in dBm/10.
+ * As measured, connected to a modulator.
+ * -8.0 to -50.0 dBm directly connected,
+ * -52.0 to -74.8 with extra attenuation.
+ * Cut-off to AGCIQ_VALUE = 0x80 below -74.8dBm.
+ * Crude linear extrapolation below -84.8dBm and above -8.0dBm.
+ */
+static const struct stb0899_tab stb0899_dvbsrf_tab[] = {
+	{ -750,	-128 },
+	{ -748,	 -94 },
+	{ -745,	 -92 },
+	{ -735,	 -90 },
+	{ -720,	 -87 },
+	{ -670,	 -77 },
+	{ -640,	 -70 },
+	{ -610,	 -62 },
+	{ -600,	 -60 },
+	{ -590,	 -56 },
+	{ -560,	 -41 },
+	{ -540,	 -25 },
+	{ -530,	 -17 },
+	{ -520,	 -11 },
+	{ -500,	   1 },
+	{ -490,	   6 },
+	{ -480,	  10 },
+	{ -440,	  22 },
+	{ -420,	  27 },
+	{ -400,	  31 },
+	{ -380,	  34 },
+	{ -340,	  40 },
+	{ -320,	  43 },
+	{ -280,	  48 },
+	{ -250,	  52 },
+	{ -230,	  55 },
+	{ -180,	  61 },
+	{ -140,	  66 },
+	{  -90,	  73 },
+	{  -80,	  74 },
+	{  500,	 127 }
+};
+
+/* DVB-S2 IF_AGC_GAIN vs. signal level in dBm/10.
+ * As measured, connected to a modulator.
+ * -8.0 to -50.1 dBm directly connected,
+ * -53.0 to -76.6 with extra attenuation.
+ * Cut-off to IF_AGC_GAIN = 0x3fff below -76.6dBm.
+ * Crude linear extrapolation below -76.6dBm and above -8.0dBm.
+ */
+static const struct stb0899_tab stb0899_dvbs2rf_tab[] = {
+	{  700,	    0 },
+	{  -80,	 3217 },
+	{ -150,	 3893 },
+	{ -190,	 4217 },
+	{ -240,	 4621 },
+	{ -280,	 4945 },
+	{ -320,	 5273 },
+	{ -350,	 5545 },
+	{ -370,	 5741 },
+	{ -410,	 6147 },
+	{ -450,	 6671 },
+	{ -490,	 7413 },
+	{ -501,	 7665 },
+	{ -530,	 8767 },
+	{ -560,	10219 },
+	{ -580,	10939 },
+	{ -590,	11518 },
+	{ -600,	11723 },
+	{ -650,	12659 },
+	{ -690,	13219 },
+	{ -730,	13645 },
+	{ -750,	13909 },
+	{ -766,	14153 },
+	{ -950,	16383 }
+};
+
+/* DVB-S2 Es/N0 quant in dB/100 vs read value * 100*/
+static struct stb0899_tab stb0899_quant_tab[] = {
+	{    0,	    0 },
+	{    0,	  100 },
+	{  600,	  200 },
+	{  950,	  299 },
+	{ 1200,	  398 },
+	{ 1400,	  501 },
+	{ 1560,	  603 },
+	{ 1690,	  700 },
+	{ 1810,	  804 },
+	{ 1910,	  902 },
+	{ 2000,	 1000 },
+	{ 2080,	 1096 },
+	{ 2160,	 1202 },
+	{ 2230,	 1303 },
+	{ 2350,	 1496 },
+	{ 2410,	 1603 },
+	{ 2460,	 1698 },
+	{ 2510,	 1799 },
+	{ 2600,	 1995 },
+	{ 2650,	 2113 },
+	{ 2690,  2213 },
+	{ 2720,	 2291 },
+	{ 2760,	 2399 },
+	{ 2800,	 2512 },
+	{ 2860,	 2692 },
+	{ 2930,	 2917 },
+	{ 2960,	 3020 },
+	{ 3010,	 3199 },
+	{ 3040,	 3311 },
+	{ 3060,	 3388 },
+	{ 3120,	 3631 },
+	{ 3190,	 3936 },
+	{ 3400,	 5012 },
+	{ 3610,	 6383 },
+	{ 3800,	 7943 },
+	{ 4210,	12735 },
+	{ 4500,	17783 },
+	{ 4690,	22131 },
+	{ 4810,	25410 }
+};
+
+/* DVB-S2 Es/N0 estimate in dB/100 vs read value */
+static struct stb0899_tab stb0899_est_tab[] = {
+	{    0,	     0 },
+	{    0,	     1 },
+	{  301,	     2 },
+	{ 1204,	    16 },
+	{ 1806,	    64 },
+	{ 2408,	   256 },
+	{ 2709,	   512 },
+	{ 3010,	  1023 },
+	{ 3311,	  2046 },
+	{ 3612,	  4093 },
+	{ 3823,	  6653 },
+	{ 3913,	  8185 },
+	{ 4010,	 10233 },
+	{ 4107,	 12794 },
+	{ 4214,	 16368 },
+	{ 4266,	 18450 },
+	{ 4311,	 20464 },
+	{ 4353,	 22542 },
+	{ 4391,	 24604 },
+	{ 4425,	 26607 },
+	{ 4457,	 28642 },
+	{ 4487,	 30690 },
+	{ 4515,	 32734 },
+	{ 4612,	 40926 },
+	{ 4692,	 49204 },
+	{ 4816,	 65464 },
+	{ 4913,	 81846 },
+	{ 4993,	 98401 },
+	{ 5060,	114815 },
+	{ 5118,	131220 },
+	{ 5200,	158489 },
+	{ 5300,	199526 },
+	{ 5400,	251189 },
+	{ 5500,	316228 },
+	{ 5600,	398107 },
+	{ 5720,	524807 },
+	{ 5721,	526017 },
+};
+
+static int _stb0899_read_reg(struct stb0899_state *state, unsigned int reg)
+{
+	int ret;
+
+	u8 b0[] = { reg >> 8, reg & 0xff };
+	u8 buf;
+
+	struct i2c_msg msg[] = {
+		{
+			.addr	= state->config->demod_address,
+			.flags	= 0,
+			.buf	= b0,
+			.len	= 2
+		},{
+			.addr	= state->config->demod_address,
+			.flags	= I2C_M_RD,
+			.buf	= &buf,
+			.len	= 1
+		}
+	};
+
+	ret = i2c_transfer(state->i2c, msg, 2);
+	if (ret != 2) {
+		if (ret != -ERESTARTSYS)
+			dprintk(state->verbose, FE_ERROR, 1,
+				"Read error, Reg=[0x%02x], Status=%d",
+				reg, ret);
+
+		return ret < 0 ? ret : -EREMOTEIO;
+	}
+	if (unlikely(*state->verbose >= FE_DEBUGREG))
+		dprintk(state->verbose, FE_ERROR, 1, "Reg=[0x%02x], data=%02x",
+			reg, buf);
+
+	return (unsigned int)buf;
+}
+
+int stb0899_read_reg(struct stb0899_state *state, unsigned int reg)
+{
+	int result;
+
+	result = _stb0899_read_reg(state, reg);
+	/*
+	 * Bug ID 9:
+	 * access to 0xf2xx/0xf6xx
+	 * must be followed by read from 0xf2ff/0xf6ff.
+	 */
+	if ((reg != 0xf2ff) && (reg != 0xf6ff) &&
+	    (((reg & 0xff00) == 0xf200) || ((reg & 0xff00) == 0xf600)))
+		_stb0899_read_reg(state, (reg | 0x00ff));
+
+	return result;
+}
+
+u32 _stb0899_read_s2reg(struct stb0899_state *state,
+			u32 stb0899_i2cdev,
+			u32 stb0899_base_addr,
+			u16 stb0899_reg_offset)
+{
+	int status;
+	u32 data;
+	u8 buf[7] = { 0 };
+	u16 tmpaddr;
+
+	u8 buf_0[] = {
+		GETBYTE(stb0899_i2cdev, BYTE1),		/* 0xf3	S2 Base Address (MSB)	*/
+		GETBYTE(stb0899_i2cdev, BYTE0),		/* 0xfc	S2 Base Address (LSB)	*/
+		GETBYTE(stb0899_base_addr, BYTE0),	/* 0x00	Base Address (LSB)	*/
+		GETBYTE(stb0899_base_addr, BYTE1),	/* 0x04	Base Address (LSB)	*/
+		GETBYTE(stb0899_base_addr, BYTE2),	/* 0x00	Base Address (MSB)	*/
+		GETBYTE(stb0899_base_addr, BYTE3),	/* 0x00	Base Address (MSB)	*/
+	};
+	u8 buf_1[] = {
+		0x00,	/* 0xf3	Reg Offset	*/
+		0x00,	/* 0x44	Reg Offset	*/
+	};
+
+	struct i2c_msg msg_0 = {
+		.addr	= state->config->demod_address,
+		.flags	= 0,
+		.buf	= buf_0,
+		.len	= 6
+	};
+
+	struct i2c_msg msg_1 = {
+		.addr	= state->config->demod_address,
+		.flags	= 0,
+		.buf	= buf_1,
+		.len	= 2
+	};
+
+	struct i2c_msg msg_r = {
+		.addr	= state->config->demod_address,
+		.flags	= I2C_M_RD,
+		.buf	= buf,
+		.len	= 4
+	};
+
+	tmpaddr = stb0899_reg_offset & 0xff00;
+	if (!(stb0899_reg_offset & 0x8))
+		tmpaddr = stb0899_reg_offset | 0x20;
+
+	buf_1[0] = GETBYTE(tmpaddr, BYTE1);
+	buf_1[1] = GETBYTE(tmpaddr, BYTE0);
+
+	status = i2c_transfer(state->i2c, &msg_0, 1);
+	if (status < 1) {
+		if (status != -ERESTARTSYS)
+			printk(KERN_ERR "%s ERR(1), Device=[0x%04x], Base address=[0x%08x], Offset=[0x%04x], Status=%d\n",
+			       __func__, stb0899_i2cdev, stb0899_base_addr, stb0899_reg_offset, status);
+
+		goto err;
+	}
+
+	/* Dummy	*/
+	status = i2c_transfer(state->i2c, &msg_1, 1);
+	if (status < 1)
+		goto err;
+
+	status = i2c_transfer(state->i2c, &msg_r, 1);
+	if (status < 1)
+		goto err;
+
+	buf_1[0] = GETBYTE(stb0899_reg_offset, BYTE1);
+	buf_1[1] = GETBYTE(stb0899_reg_offset, BYTE0);
+
+	/* Actual	*/
+	status = i2c_transfer(state->i2c, &msg_1, 1);
+	if (status < 1) {
+		if (status != -ERESTARTSYS)
+			printk(KERN_ERR "%s ERR(2), Device=[0x%04x], Base address=[0x%08x], Offset=[0x%04x], Status=%d\n",
+			       __func__, stb0899_i2cdev, stb0899_base_addr, stb0899_reg_offset, status);
+		goto err;
+	}
+
+	status = i2c_transfer(state->i2c, &msg_r, 1);
+	if (status < 1) {
+		if (status != -ERESTARTSYS)
+			printk(KERN_ERR "%s ERR(3), Device=[0x%04x], Base address=[0x%08x], Offset=[0x%04x], Status=%d\n",
+			       __func__, stb0899_i2cdev, stb0899_base_addr, stb0899_reg_offset, status);
+		return status < 0 ? status : -EREMOTEIO;
+	}
+
+	data = MAKEWORD32(buf[3], buf[2], buf[1], buf[0]);
+	if (unlikely(*state->verbose >= FE_DEBUGREG))
+		printk(KERN_DEBUG "%s Device=[0x%04x], Base address=[0x%08x], Offset=[0x%04x], Data=[0x%08x]\n",
+		       __func__, stb0899_i2cdev, stb0899_base_addr, stb0899_reg_offset, data);
+
+	return data;
+
+err:
+	return status < 0 ? status : -EREMOTEIO;
+}
+
+int stb0899_write_s2reg(struct stb0899_state *state,
+			u32 stb0899_i2cdev,
+			u32 stb0899_base_addr,
+			u16 stb0899_reg_offset,
+			u32 stb0899_data)
+{
+	int status;
+
+	/* Base Address Setup	*/
+	u8 buf_0[] = {
+		GETBYTE(stb0899_i2cdev, BYTE1),		/* 0xf3	S2 Base Address (MSB)	*/
+		GETBYTE(stb0899_i2cdev, BYTE0),		/* 0xfc	S2 Base Address (LSB)	*/
+		GETBYTE(stb0899_base_addr, BYTE0),	/* 0x00	Base Address (LSB)	*/
+		GETBYTE(stb0899_base_addr, BYTE1),	/* 0x04	Base Address (LSB)	*/
+		GETBYTE(stb0899_base_addr, BYTE2),	/* 0x00	Base Address (MSB)	*/
+		GETBYTE(stb0899_base_addr, BYTE3),	/* 0x00	Base Address (MSB)	*/
+	};
+	u8 buf_1[] = {
+		0x00,	/* 0xf3	Reg Offset	*/
+		0x00,	/* 0x44	Reg Offset	*/
+		0x00,	/* data			*/
+		0x00,	/* data			*/
+		0x00,	/* data			*/
+		0x00,	/* data			*/
+	};
+
+	struct i2c_msg msg_0 = {
+		.addr	= state->config->demod_address,
+		.flags	= 0,
+		.buf	= buf_0,
+		.len	= 6
+	};
+
+	struct i2c_msg msg_1 = {
+		.addr	= state->config->demod_address,
+		.flags	= 0,
+		.buf	= buf_1,
+		.len	= 6
+	};
+
+	buf_1[0] = GETBYTE(stb0899_reg_offset, BYTE1);
+	buf_1[1] = GETBYTE(stb0899_reg_offset, BYTE0);
+	buf_1[2] = GETBYTE(stb0899_data, BYTE0);
+	buf_1[3] = GETBYTE(stb0899_data, BYTE1);
+	buf_1[4] = GETBYTE(stb0899_data, BYTE2);
+	buf_1[5] = GETBYTE(stb0899_data, BYTE3);
+
+	if (unlikely(*state->verbose >= FE_DEBUGREG))
+		printk(KERN_DEBUG "%s Device=[0x%04x], Base Address=[0x%08x], Offset=[0x%04x], Data=[0x%08x]\n",
+		       __func__, stb0899_i2cdev, stb0899_base_addr, stb0899_reg_offset, stb0899_data);
+
+	status = i2c_transfer(state->i2c, &msg_0, 1);
+	if (unlikely(status < 1)) {
+		if (status != -ERESTARTSYS)
+			printk(KERN_ERR "%s ERR (1), Device=[0x%04x], Base Address=[0x%08x], Offset=[0x%04x], Data=[0x%08x], status=%d\n",
+			       __func__, stb0899_i2cdev, stb0899_base_addr, stb0899_reg_offset, stb0899_data, status);
+		goto err;
+	}
+	status = i2c_transfer(state->i2c, &msg_1, 1);
+	if (unlikely(status < 1)) {
+		if (status != -ERESTARTSYS)
+			printk(KERN_ERR "%s ERR (2), Device=[0x%04x], Base Address=[0x%08x], Offset=[0x%04x], Data=[0x%08x], status=%d\n",
+			       __func__, stb0899_i2cdev, stb0899_base_addr, stb0899_reg_offset, stb0899_data, status);
+
+		return status < 0 ? status : -EREMOTEIO;
+	}
+
+	return 0;
+
+err:
+	return status < 0 ? status : -EREMOTEIO;
+}
+
+int stb0899_read_regs(struct stb0899_state *state, unsigned int reg, u8 *buf, u32 count)
+{
+	int status;
+
+	u8 b0[] = { reg >> 8, reg & 0xff };
+
+	struct i2c_msg msg[] = {
+		{
+			.addr	= state->config->demod_address,
+			.flags	= 0,
+			.buf	= b0,
+			.len	= 2
+		},{
+			.addr	= state->config->demod_address,
+			.flags	= I2C_M_RD,
+			.buf	= buf,
+			.len	= count
+		}
+	};
+
+	status = i2c_transfer(state->i2c, msg, 2);
+	if (status != 2) {
+		if (status != -ERESTARTSYS)
+			printk(KERN_ERR "%s Read error, Reg=[0x%04x], Count=%u, Status=%d\n",
+			       __func__, reg, count, status);
+		goto err;
+	}
+	/*
+	 * Bug ID 9:
+	 * access to 0xf2xx/0xf6xx
+	 * must be followed by read from 0xf2ff/0xf6ff.
+	 */
+	if ((reg != 0xf2ff) && (reg != 0xf6ff) &&
+	    (((reg & 0xff00) == 0xf200) || ((reg & 0xff00) == 0xf600)))
+		_stb0899_read_reg(state, (reg | 0x00ff));
+
+	if (unlikely(*state->verbose >= FE_DEBUGREG)) {
+		int i;
+
+		printk(KERN_DEBUG "%s [0x%04x]:", __func__, reg);
+		for (i = 0; i < count; i++) {
+			printk(" %02x", buf[i]);
+		}
+		printk("\n");
+	}
+
+	return 0;
+err:
+	return status < 0 ? status : -EREMOTEIO;
+}
+
+int stb0899_write_regs(struct stb0899_state *state, unsigned int reg, u8 *data, u32 count)
+{
+	int ret;
+	u8 buf[2 + count];
+	struct i2c_msg i2c_msg = {
+		.addr	= state->config->demod_address,
+		.flags	= 0,
+		.buf	= buf,
+		.len	= 2 + count
+	};
+
+	buf[0] = reg >> 8;
+	buf[1] = reg & 0xff;
+	memcpy(&buf[2], data, count);
+
+	if (unlikely(*state->verbose >= FE_DEBUGREG)) {
+		int i;
+
+		printk(KERN_DEBUG "%s [0x%04x]:", __func__, reg);
+		for (i = 0; i < count; i++)
+			printk(" %02x", data[i]);
+		printk("\n");
+	}
+	ret = i2c_transfer(state->i2c, &i2c_msg, 1);
+
+	/*
+	 * Bug ID 9:
+	 * access to 0xf2xx/0xf6xx
+	 * must be followed by read from 0xf2ff/0xf6ff.
+	 */
+	if ((((reg & 0xff00) == 0xf200) || ((reg & 0xff00) == 0xf600)))
+		stb0899_read_reg(state, (reg | 0x00ff));
+
+	if (ret != 1) {
+		if (ret != -ERESTARTSYS)
+			dprintk(state->verbose, FE_ERROR, 1, "Reg=[0x%04x], Data=[0x%02x ...], Count=%u, Status=%d",
+				reg, data[0], count, ret);
+		return ret < 0 ? ret : -EREMOTEIO;
+	}
+
+	return 0;
+}
+
+int stb0899_write_reg(struct stb0899_state *state, unsigned int reg, u8 data)
+{
+	return stb0899_write_regs(state, reg, &data, 1);
+}
+
+/*
+ * stb0899_get_mclk
+ * Get STB0899 master clock frequency
+ * ExtClk: external clock frequency (Hz)
+ */
+static u32 stb0899_get_mclk(struct stb0899_state *state)
+{
+	u32 mclk = 0, div = 0;
+
+	div = stb0899_read_reg(state, STB0899_NCOARSE);
+	mclk = (div + 1) * state->config->xtal_freq / 6;
+	dprintk(state->verbose, FE_DEBUG, 1, "div=%d, mclk=%d", div, mclk);
+
+	return mclk;
+}
+
+/*
+ * stb0899_set_mclk
+ * Set STB0899 master Clock frequency
+ * Mclk: demodulator master clock
+ * ExtClk: external clock frequency (Hz)
+ */
+static void stb0899_set_mclk(struct stb0899_state *state, u32 Mclk)
+{
+	struct stb0899_internal *internal = &state->internal;
+	u8 mdiv = 0;
+
+	dprintk(state->verbose, FE_DEBUG, 1, "state->config=%p", state->config);
+	mdiv = ((6 * Mclk) / state->config->xtal_freq) - 1;
+	dprintk(state->verbose, FE_DEBUG, 1, "mdiv=%d", mdiv);
+
+	stb0899_write_reg(state, STB0899_NCOARSE, mdiv);
+	internal->master_clk = stb0899_get_mclk(state);
+
+	dprintk(state->verbose, FE_DEBUG, 1, "MasterCLOCK=%d", internal->master_clk);
+}
+
+static int stb0899_postproc(struct stb0899_state *state, u8 ctl, int enable)
+{
+	struct stb0899_config *config		= state->config;
+	const struct stb0899_postproc *postproc	= config->postproc;
+
+	/* post process event */
+	if (postproc) {
+		if (enable) {
+			if (postproc[ctl].level == STB0899_GPIOPULLUP)
+				stb0899_write_reg(state, postproc[ctl].gpio, 0x02);
+			else
+				stb0899_write_reg(state, postproc[ctl].gpio, 0x82);
+		} else {
+			if (postproc[ctl].level == STB0899_GPIOPULLUP)
+				stb0899_write_reg(state, postproc[ctl].gpio, 0x82);
+			else
+				stb0899_write_reg(state, postproc[ctl].gpio, 0x02);
+		}
+	}
+	return 0;
+}
+
+static void stb0899_release(struct dvb_frontend *fe)
+{
+	struct stb0899_state *state = fe->demodulator_priv;
+
+	dprintk(state->verbose, FE_DEBUG, 1, "Release Frontend");
+	/* post process event */
+	stb0899_postproc(state, STB0899_POSTPROC_GPIO_POWER, 0);
+	kfree(state);
+}
+
+/*
+ * stb0899_get_alpha
+ * return: rolloff
+ */
+static int stb0899_get_alpha(struct stb0899_state *state)
+{
+	u8 mode_coeff;
+
+	mode_coeff = stb0899_read_reg(state, STB0899_DEMOD);
+
+	if (STB0899_GETFIELD(MODECOEFF, mode_coeff) == 1)
+		return 20;
+	else
+		return 35;
+}
+
+/*
+ * stb0899_init_calc
+ */
+static void stb0899_init_calc(struct stb0899_state *state)
+{
+	struct stb0899_internal *internal = &state->internal;
+	int master_clk;
+	u8 agc[2];
+	u32 reg;
+
+	/* Read registers (in burst mode)	*/
+	stb0899_read_regs(state, STB0899_AGC1REF, agc, 2); /* AGC1R and AGC2O	*/
+
+	/* Initial calculations	*/
+	master_clk			= stb0899_get_mclk(state);
+	internal->t_agc1		= 0;
+	internal->t_agc2		= 0;
+	internal->master_clk		= master_clk;
+	internal->mclk			= master_clk / 65536L;
+	internal->rolloff		= stb0899_get_alpha(state);
+
+	/* DVBS2 Initial calculations	*/
+	/* Set AGC value to the middle	*/
+	internal->agc_gain		= 8154;
+	reg = STB0899_READ_S2REG(STB0899_S2DEMOD, IF_AGC_CNTRL);
+	STB0899_SETFIELD_VAL(IF_GAIN_INIT, reg, internal->agc_gain);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_IF_AGC_CNTRL, STB0899_OFF0_IF_AGC_CNTRL, reg);
+
+	reg = STB0899_READ_S2REG(STB0899_S2DEMOD, RRC_ALPHA);
+	internal->rrc_alpha		= STB0899_GETFIELD(RRC_ALPHA, reg);
+
+	internal->center_freq		= 0;
+	internal->av_frame_coarse	= 10;
+	internal->av_frame_fine		= 20;
+	internal->step_size		= 2;
+/*
+	if ((pParams->SpectralInv == FE_IQ_NORMAL) || (pParams->SpectralInv == FE_IQ_AUTO))
+		pParams->IQLocked = 0;
+	else
+		pParams->IQLocked = 1;
+*/
+}
+
+static int stb0899_wait_diseqc_fifo_empty(struct stb0899_state *state, int timeout)
+{
+	u8 reg = 0;
+	unsigned long start = jiffies;
+
+	while (1) {
+		reg = stb0899_read_reg(state, STB0899_DISSTATUS);
+		if (!STB0899_GETFIELD(FIFOFULL, reg))
+			break;
+		if ((jiffies - start) > timeout) {
+			dprintk(state->verbose, FE_ERROR, 1, "timed out !!");
+			return -ETIMEDOUT;
+		}
+	}
+
+	return 0;
+}
+
+static int stb0899_send_diseqc_msg(struct dvb_frontend *fe, struct dvb_diseqc_master_cmd *cmd)
+{
+	struct stb0899_state *state = fe->demodulator_priv;
+	u8 reg, i;
+
+	if (cmd->msg_len > 8)
+		return -EINVAL;
+
+	/* enable FIFO precharge	*/
+	reg = stb0899_read_reg(state, STB0899_DISCNTRL1);
+	STB0899_SETFIELD_VAL(DISPRECHARGE, reg, 1);
+	stb0899_write_reg(state, STB0899_DISCNTRL1, reg);
+	for (i = 0; i < cmd->msg_len; i++) {
+		/* wait for FIFO empty	*/
+		if (stb0899_wait_diseqc_fifo_empty(state, 100) < 0)
+			return -ETIMEDOUT;
+
+		stb0899_write_reg(state, STB0899_DISFIFO, cmd->msg[i]);
+	}
+	reg = stb0899_read_reg(state, STB0899_DISCNTRL1);
+	STB0899_SETFIELD_VAL(DISPRECHARGE, reg, 0);
+	stb0899_write_reg(state, STB0899_DISCNTRL1, reg);
+	msleep(100);
+	return 0;
+}
+
+static int stb0899_wait_diseqc_rxidle(struct stb0899_state *state, int timeout)
+{
+	u8 reg = 0;
+	unsigned long start = jiffies;
+
+	while (!STB0899_GETFIELD(RXEND, reg)) {
+		reg = stb0899_read_reg(state, STB0899_DISRX_ST0);
+		if (jiffies - start > timeout) {
+			dprintk(state->verbose, FE_ERROR, 1, "timed out!!");
+			return -ETIMEDOUT;
+		}
+		msleep(10);
+	}
+
+	return 0;
+}
+
+static int stb0899_recv_slave_reply(struct dvb_frontend *fe, struct dvb_diseqc_slave_reply *reply)
+{
+	struct stb0899_state *state = fe->demodulator_priv;
+	u8 reg, length = 0, i;
+	int result;
+
+	if (stb0899_wait_diseqc_rxidle(state, 100) < 0)
+		return -ETIMEDOUT;
+
+	reg = stb0899_read_reg(state, STB0899_DISRX_ST0);
+	if (STB0899_GETFIELD(RXEND, reg)) {
+
+		reg = stb0899_read_reg(state, STB0899_DISRX_ST1);
+		length = STB0899_GETFIELD(FIFOBYTENBR, reg);
+
+		if (length > sizeof (reply->msg)) {
+			result = -EOVERFLOW;
+			goto exit;
+		}
+		reply->msg_len = length;
+
+		/* extract data */
+		for (i = 0; i < length; i++)
+			reply->msg[i] = stb0899_read_reg(state, STB0899_DISFIFO);
+	}
+
+	return 0;
+exit:
+
+	return result;
+}
+
+static int stb0899_wait_diseqc_txidle(struct stb0899_state *state, int timeout)
+{
+	u8 reg = 0;
+	unsigned long start = jiffies;
+
+	while (!STB0899_GETFIELD(TXIDLE, reg)) {
+		reg = stb0899_read_reg(state, STB0899_DISSTATUS);
+		if (jiffies - start > timeout) {
+			dprintk(state->verbose, FE_ERROR, 1, "timed out!!");
+			return -ETIMEDOUT;
+		}
+		msleep(10);
+	}
+	return 0;
+}
+
+static int stb0899_send_diseqc_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t burst)
+{
+	struct stb0899_state *state = fe->demodulator_priv;
+	u8 reg, old_state;
+
+	/* wait for diseqc idle	*/
+	if (stb0899_wait_diseqc_txidle(state, 100) < 0)
+		return -ETIMEDOUT;
+
+	reg = stb0899_read_reg(state, STB0899_DISCNTRL1);
+	old_state = reg;
+	/* set to burst mode	*/
+	STB0899_SETFIELD_VAL(DISEQCMODE, reg, 0x03);
+	STB0899_SETFIELD_VAL(DISPRECHARGE, reg, 0x01);
+	stb0899_write_reg(state, STB0899_DISCNTRL1, reg);
+	switch (burst) {
+	case SEC_MINI_A:
+		/* unmodulated	*/
+		stb0899_write_reg(state, STB0899_DISFIFO, 0x00);
+		break;
+	case SEC_MINI_B:
+		/* modulated	*/
+		stb0899_write_reg(state, STB0899_DISFIFO, 0xff);
+		break;
+	}
+	reg = stb0899_read_reg(state, STB0899_DISCNTRL1);
+	STB0899_SETFIELD_VAL(DISPRECHARGE, reg, 0x00);
+	stb0899_write_reg(state, STB0899_DISCNTRL1, reg);
+	/* wait for diseqc idle	*/
+	if (stb0899_wait_diseqc_txidle(state, 100) < 0)
+		return -ETIMEDOUT;
+
+	/* restore state	*/
+	stb0899_write_reg(state, STB0899_DISCNTRL1, old_state);
+
+	return 0;
+}
+
+static int stb0899_diseqc_init(struct stb0899_state *state)
+{
+/*
+	struct dvb_diseqc_slave_reply rx_data;
+*/
+	u8 f22_tx, reg;
+
+	u32 mclk, tx_freq = 22000;/* count = 0, i; */
+	reg = stb0899_read_reg(state, STB0899_DISCNTRL2);
+	STB0899_SETFIELD_VAL(ONECHIP_TRX, reg, 0);
+	stb0899_write_reg(state, STB0899_DISCNTRL2, reg);
+
+	/* disable Tx spy	*/
+	reg = stb0899_read_reg(state, STB0899_DISCNTRL1);
+	STB0899_SETFIELD_VAL(DISEQCRESET, reg, 1);
+	stb0899_write_reg(state, STB0899_DISCNTRL1, reg);
+
+	reg = stb0899_read_reg(state, STB0899_DISCNTRL1);
+	STB0899_SETFIELD_VAL(DISEQCRESET, reg, 0);
+	stb0899_write_reg(state, STB0899_DISCNTRL1, reg);
+
+	mclk = stb0899_get_mclk(state);
+	f22_tx = mclk / (tx_freq * 32);
+	stb0899_write_reg(state, STB0899_DISF22, f22_tx); /* DiSEqC Tx freq	*/
+	state->rx_freq = 20000;
+
+	return 0;
+}
+
+static int stb0899_sleep(struct dvb_frontend *fe)
+{
+	struct stb0899_state *state = fe->demodulator_priv;
+/*
+	u8 reg;
+*/
+	dprintk(state->verbose, FE_DEBUG, 1, "Going to Sleep .. (Really tired .. :-))");
+	/* post process event */
+	stb0899_postproc(state, STB0899_POSTPROC_GPIO_POWER, 0);
+
+	return 0;
+}
+
+static int stb0899_wakeup(struct dvb_frontend *fe)
+{
+	int rc;
+	struct stb0899_state *state = fe->demodulator_priv;
+
+	if ((rc = stb0899_write_reg(state, STB0899_SYNTCTRL, STB0899_SELOSCI)))
+		return rc;
+	/* Activate all clocks; DVB-S2 registers are inaccessible otherwise. */
+	if ((rc = stb0899_write_reg(state, STB0899_STOPCLK1, 0x00)))
+		return rc;
+	if ((rc = stb0899_write_reg(state, STB0899_STOPCLK2, 0x00)))
+		return rc;
+
+	/* post process event */
+	stb0899_postproc(state, STB0899_POSTPROC_GPIO_POWER, 1);
+
+	return 0;
+}
+
+static int stb0899_init(struct dvb_frontend *fe)
+{
+	int i;
+	struct stb0899_state *state = fe->demodulator_priv;
+	struct stb0899_config *config = state->config;
+
+	dprintk(state->verbose, FE_DEBUG, 1, "Initializing STB0899 ... ");
+
+	/* init device		*/
+	dprintk(state->verbose, FE_DEBUG, 1, "init device");
+	for (i = 0; config->init_dev[i].address != 0xffff; i++)
+		stb0899_write_reg(state, config->init_dev[i].address, config->init_dev[i].data);
+
+	dprintk(state->verbose, FE_DEBUG, 1, "init S2 demod");
+	/* init S2 demod	*/
+	for (i = 0; config->init_s2_demod[i].offset != 0xffff; i++)
+		stb0899_write_s2reg(state, STB0899_S2DEMOD,
+				    config->init_s2_demod[i].base_address,
+				    config->init_s2_demod[i].offset,
+				    config->init_s2_demod[i].data);
+
+	dprintk(state->verbose, FE_DEBUG, 1, "init S1 demod");
+	/* init S1 demod	*/
+	for (i = 0; config->init_s1_demod[i].address != 0xffff; i++)
+		stb0899_write_reg(state, config->init_s1_demod[i].address, config->init_s1_demod[i].data);
+
+	dprintk(state->verbose, FE_DEBUG, 1, "init S2 FEC");
+	/* init S2 fec		*/
+	for (i = 0; config->init_s2_fec[i].offset != 0xffff; i++)
+		stb0899_write_s2reg(state, STB0899_S2FEC,
+				    config->init_s2_fec[i].base_address,
+				    config->init_s2_fec[i].offset,
+				    config->init_s2_fec[i].data);
+
+	dprintk(state->verbose, FE_DEBUG, 1, "init TST");
+	/* init test		*/
+	for (i = 0; config->init_tst[i].address != 0xffff; i++)
+		stb0899_write_reg(state, config->init_tst[i].address, config->init_tst[i].data);
+
+	stb0899_init_calc(state);
+	stb0899_diseqc_init(state);
+
+	return 0;
+}
+
+static int stb0899_table_lookup(const struct stb0899_tab *tab, int max, int val)
+{
+	int res = 0;
+	int min = 0, med;
+
+	if (val < tab[min].read)
+		res = tab[min].real;
+	else if (val >= tab[max].read)
+		res = tab[max].real;
+	else {
+		while ((max - min) > 1) {
+			med = (max + min) / 2;
+			if (val >= tab[min].read && val < tab[med].read)
+				max = med;
+			else
+				min = med;
+		}
+		res = ((val - tab[min].read) *
+		       (tab[max].real - tab[min].real) /
+		       (tab[max].read - tab[min].read)) +
+			tab[min].real;
+	}
+
+	return res;
+}
+
+static int stb0899_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
+{
+	struct stb0899_state *state		= fe->demodulator_priv;
+	struct stb0899_internal *internal	= &state->internal;
+
+	int val;
+	u32 reg;
+	*strength = 0;
+	switch (state->delsys) {
+	case SYS_DVBS:
+	case SYS_DSS:
+		if (internal->lock) {
+			reg  = stb0899_read_reg(state, STB0899_VSTATUS);
+			if (STB0899_GETFIELD(VSTATUS_LOCKEDVIT, reg)) {
+
+				reg = stb0899_read_reg(state, STB0899_AGCIQIN);
+				val = (s32)(s8)STB0899_GETFIELD(AGCIQVALUE, reg);
+
+				*strength = stb0899_table_lookup(stb0899_dvbsrf_tab, ARRAY_SIZE(stb0899_dvbsrf_tab) - 1, val);
+				*strength += 750;
+				dprintk(state->verbose, FE_DEBUG, 1, "AGCIQVALUE = 0x%02x, C = %d * 0.1 dBm",
+					val & 0xff, *strength);
+			}
+		}
+		break;
+	case SYS_DVBS2:
+		if (internal->lock) {
+			reg = STB0899_READ_S2REG(STB0899_S2DEMOD, IF_AGC_GAIN);
+			val = STB0899_GETFIELD(IF_AGC_GAIN, reg);
+
+			*strength = stb0899_table_lookup(stb0899_dvbs2rf_tab, ARRAY_SIZE(stb0899_dvbs2rf_tab) - 1, val);
+			*strength += 950;
+			dprintk(state->verbose, FE_DEBUG, 1, "IF_AGC_GAIN = 0x%04x, C = %d * 0.1 dBm",
+				val & 0x3fff, *strength);
+		}
+		break;
+	default:
+		dprintk(state->verbose, FE_DEBUG, 1, "Unsupported delivery system");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int stb0899_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+	struct stb0899_state *state		= fe->demodulator_priv;
+	struct stb0899_internal *internal	= &state->internal;
+
+	unsigned int val, quant, quantn = -1, est, estn = -1;
+	u8 buf[2];
+	u32 reg;
+
+	*snr = 0;
+	reg  = stb0899_read_reg(state, STB0899_VSTATUS);
+	switch (state->delsys) {
+	case SYS_DVBS:
+	case SYS_DSS:
+		if (internal->lock) {
+			if (STB0899_GETFIELD(VSTATUS_LOCKEDVIT, reg)) {
+
+				stb0899_read_regs(state, STB0899_NIRM, buf, 2);
+				val = MAKEWORD16(buf[0], buf[1]);
+
+				*snr = stb0899_table_lookup(stb0899_cn_tab, ARRAY_SIZE(stb0899_cn_tab) - 1, val);
+				dprintk(state->verbose, FE_DEBUG, 1, "NIR = 0x%02x%02x = %u, C/N = %d * 0.1 dBm\n",
+					buf[0], buf[1], val, *snr);
+			}
+		}
+		break;
+	case SYS_DVBS2:
+		if (internal->lock) {
+			reg = STB0899_READ_S2REG(STB0899_S2DEMOD, UWP_CNTRL1);
+			quant = STB0899_GETFIELD(UWP_ESN0_QUANT, reg);
+			reg = STB0899_READ_S2REG(STB0899_S2DEMOD, UWP_STAT2);
+			est = STB0899_GETFIELD(ESN0_EST, reg);
+			if (est == 1)
+				val = 301; /* C/N = 30.1 dB */
+			else if (est == 2)
+				val = 270; /* C/N = 27.0 dB */
+			else {
+				/* quantn = 100 * log(quant^2) */
+				quantn = stb0899_table_lookup(stb0899_quant_tab, ARRAY_SIZE(stb0899_quant_tab) - 1, quant * 100);
+				/* estn = 100 * log(est) */
+				estn = stb0899_table_lookup(stb0899_est_tab, ARRAY_SIZE(stb0899_est_tab) - 1, est);
+				/* snr(dBm/10) = -10*(log(est)-log(quant^2)) => snr(dBm/10) = (100*log(quant^2)-100*log(est))/10 */
+				val = (quantn - estn) / 10;
+			}
+			*snr = val;
+			dprintk(state->verbose, FE_DEBUG, 1, "Es/N0 quant = %d (%d) estimate = %u (%d), C/N = %d * 0.1 dBm",
+				quant, quantn, est, estn, val);
+		}
+		break;
+	default:
+		dprintk(state->verbose, FE_DEBUG, 1, "Unsupported delivery system");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int stb0899_read_status(struct dvb_frontend *fe, enum fe_status *status)
+{
+	struct stb0899_state *state		= fe->demodulator_priv;
+	struct stb0899_internal *internal	= &state->internal;
+	u8 reg;
+	*status = 0;
+
+	switch (state->delsys) {
+	case SYS_DVBS:
+	case SYS_DSS:
+		dprintk(state->verbose, FE_DEBUG, 1, "Delivery system DVB-S/DSS");
+		if (internal->lock) {
+			reg  = stb0899_read_reg(state, STB0899_VSTATUS);
+			if (STB0899_GETFIELD(VSTATUS_LOCKEDVIT, reg)) {
+				dprintk(state->verbose, FE_DEBUG, 1, "--------> FE_HAS_CARRIER | FE_HAS_LOCK");
+				*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_LOCK;
+
+				reg = stb0899_read_reg(state, STB0899_PLPARM);
+				if (STB0899_GETFIELD(VITCURPUN, reg)) {
+					dprintk(state->verbose, FE_DEBUG, 1, "--------> FE_HAS_VITERBI | FE_HAS_SYNC");
+					*status |= FE_HAS_VITERBI | FE_HAS_SYNC;
+					/* post process event */
+					stb0899_postproc(state, STB0899_POSTPROC_GPIO_LOCK, 1);
+				}
+			}
+		}
+		break;
+	case SYS_DVBS2:
+		dprintk(state->verbose, FE_DEBUG, 1, "Delivery system DVB-S2");
+		if (internal->lock) {
+			reg = STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_STAT2);
+			if (STB0899_GETFIELD(UWP_LOCK, reg) && STB0899_GETFIELD(CSM_LOCK, reg)) {
+				*status |= FE_HAS_CARRIER;
+				dprintk(state->verbose, FE_DEBUG, 1,
+					"UWP & CSM Lock ! ---> DVB-S2 FE_HAS_CARRIER");
+
+				reg = stb0899_read_reg(state, STB0899_CFGPDELSTATUS1);
+				if (STB0899_GETFIELD(CFGPDELSTATUS_LOCK, reg)) {
+					*status |= FE_HAS_LOCK;
+					dprintk(state->verbose, FE_DEBUG, 1,
+						"Packet Delineator Locked ! -----> DVB-S2 FE_HAS_LOCK");
+
+				}
+				if (STB0899_GETFIELD(CONTINUOUS_STREAM, reg)) {
+					*status |= FE_HAS_VITERBI;
+					dprintk(state->verbose, FE_DEBUG, 1,
+						"Packet Delineator found VITERBI ! -----> DVB-S2 FE_HAS_VITERBI");
+				}
+				if (STB0899_GETFIELD(ACCEPTED_STREAM, reg)) {
+					*status |= FE_HAS_SYNC;
+					dprintk(state->verbose, FE_DEBUG, 1,
+						"Packet Delineator found SYNC ! -----> DVB-S2 FE_HAS_SYNC");
+					/* post process event */
+					stb0899_postproc(state, STB0899_POSTPROC_GPIO_LOCK, 1);
+				}
+			}
+		}
+		break;
+	default:
+		dprintk(state->verbose, FE_DEBUG, 1, "Unsupported delivery system");
+		return -EINVAL;
+	}
+	return 0;
+}
+
+/*
+ * stb0899_get_error
+ * viterbi error for DVB-S/DSS
+ * packet error for DVB-S2
+ * Bit Error Rate or Packet Error Rate * 10 ^ 7
+ */
+static int stb0899_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+	struct stb0899_state *state		= fe->demodulator_priv;
+	struct stb0899_internal *internal	= &state->internal;
+
+	u8  lsb, msb;
+
+	*ber = 0;
+
+	switch (state->delsys) {
+	case SYS_DVBS:
+	case SYS_DSS:
+		if (internal->lock) {
+			lsb = stb0899_read_reg(state, STB0899_ECNT1L);
+			msb = stb0899_read_reg(state, STB0899_ECNT1M);
+			*ber = MAKEWORD16(msb, lsb);
+			/* Viterbi Check	*/
+			if (STB0899_GETFIELD(VSTATUS_PRFVIT, internal->v_status)) {
+				/* Error Rate		*/
+				*ber *= 9766;
+				/* ber = ber * 10 ^ 7	*/
+				*ber /= (-1 + (1 << (2 * STB0899_GETFIELD(NOE, internal->err_ctrl))));
+				*ber /= 8;
+			}
+		}
+		break;
+	case SYS_DVBS2:
+		if (internal->lock) {
+			lsb = stb0899_read_reg(state, STB0899_ECNT1L);
+			msb = stb0899_read_reg(state, STB0899_ECNT1M);
+			*ber = MAKEWORD16(msb, lsb);
+			/* ber = ber * 10 ^ 7	*/
+			*ber *= 10000000;
+			*ber /= (-1 + (1 << (4 + 2 * STB0899_GETFIELD(NOE, internal->err_ctrl))));
+		}
+		break;
+	default:
+		dprintk(state->verbose, FE_DEBUG, 1, "Unsupported delivery system");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int stb0899_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+{
+	struct stb0899_state *state = fe->demodulator_priv;
+
+	switch (voltage) {
+	case SEC_VOLTAGE_13:
+		stb0899_write_reg(state, STB0899_GPIO00CFG, 0x82);
+		stb0899_write_reg(state, STB0899_GPIO01CFG, 0x02);
+		stb0899_write_reg(state, STB0899_GPIO02CFG, 0x00);
+		break;
+	case SEC_VOLTAGE_18:
+		stb0899_write_reg(state, STB0899_GPIO00CFG, 0x02);
+		stb0899_write_reg(state, STB0899_GPIO01CFG, 0x02);
+		stb0899_write_reg(state, STB0899_GPIO02CFG, 0x82);
+		break;
+	case SEC_VOLTAGE_OFF:
+		stb0899_write_reg(state, STB0899_GPIO00CFG, 0x82);
+		stb0899_write_reg(state, STB0899_GPIO01CFG, 0x82);
+		stb0899_write_reg(state, STB0899_GPIO02CFG, 0x82);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int stb0899_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
+{
+	struct stb0899_state *state = fe->demodulator_priv;
+	struct stb0899_internal *internal = &state->internal;
+
+	u8 div, reg;
+
+	/* wait for diseqc idle	*/
+	if (stb0899_wait_diseqc_txidle(state, 100) < 0)
+		return -ETIMEDOUT;
+
+	switch (tone) {
+	case SEC_TONE_ON:
+		div = (internal->master_clk / 100) / 5632;
+		div = (div + 5) / 10;
+		stb0899_write_reg(state, STB0899_DISEQCOCFG, 0x66);
+		reg = stb0899_read_reg(state, STB0899_ACRPRESC);
+		STB0899_SETFIELD_VAL(ACRPRESC, reg, 0x03);
+		stb0899_write_reg(state, STB0899_ACRPRESC, reg);
+		stb0899_write_reg(state, STB0899_ACRDIV1, div);
+		break;
+	case SEC_TONE_OFF:
+		stb0899_write_reg(state, STB0899_DISEQCOCFG, 0x20);
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+int stb0899_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+	int i2c_stat;
+	struct stb0899_state *state = fe->demodulator_priv;
+
+	i2c_stat = stb0899_read_reg(state, STB0899_I2CRPT);
+	if (i2c_stat < 0)
+		goto err;
+
+	if (enable) {
+		dprintk(state->verbose, FE_DEBUG, 1, "Enabling I2C Repeater ...");
+		i2c_stat |=  STB0899_I2CTON;
+		if (stb0899_write_reg(state, STB0899_I2CRPT, i2c_stat) < 0)
+			goto err;
+	} else {
+		dprintk(state->verbose, FE_DEBUG, 1, "Disabling I2C Repeater ...");
+		i2c_stat &= ~STB0899_I2CTON;
+		if (stb0899_write_reg(state, STB0899_I2CRPT, i2c_stat) < 0)
+			goto err;
+	}
+	return 0;
+err:
+	dprintk(state->verbose, FE_ERROR, 1, "I2C Repeater control failed");
+	return -EREMOTEIO;
+}
+
+
+static inline void CONVERT32(u32 x, char *str)
+{
+	*str++	= (x >> 24) & 0xff;
+	*str++	= (x >> 16) & 0xff;
+	*str++	= (x >>  8) & 0xff;
+	*str++	= (x >>  0) & 0xff;
+	*str	= '\0';
+}
+
+int stb0899_get_dev_id(struct stb0899_state *state)
+{
+	u8 chip_id, release;
+	u16 id;
+	u32 demod_ver = 0, fec_ver = 0;
+	char demod_str[5] = { 0 };
+	char fec_str[5] = { 0 };
+
+	id = stb0899_read_reg(state, STB0899_DEV_ID);
+	dprintk(state->verbose, FE_DEBUG, 1, "ID reg=[0x%02x]", id);
+	chip_id = STB0899_GETFIELD(CHIP_ID, id);
+	release = STB0899_GETFIELD(CHIP_REL, id);
+
+	dprintk(state->verbose, FE_ERROR, 1, "Device ID=[%d], Release=[%d]",
+		chip_id, release);
+
+	CONVERT32(STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_CORE_ID), (char *)&demod_str);
+
+	demod_ver = STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_VERSION_ID);
+	dprintk(state->verbose, FE_ERROR, 1, "Demodulator Core ID=[%s], Version=[%d]", (char *) &demod_str, demod_ver);
+	CONVERT32(STB0899_READ_S2REG(STB0899_S2FEC, FEC_CORE_ID_REG), (char *)&fec_str);
+	fec_ver = STB0899_READ_S2REG(STB0899_S2FEC, FEC_VER_ID_REG);
+	if (! (chip_id > 0)) {
+		dprintk(state->verbose, FE_ERROR, 1, "couldn't find a STB 0899");
+
+		return -ENODEV;
+	}
+	dprintk(state->verbose, FE_ERROR, 1, "FEC Core ID=[%s], Version=[%d]", (char*) &fec_str, fec_ver);
+
+	return 0;
+}
+
+static void stb0899_set_delivery(struct stb0899_state *state)
+{
+	u8 reg;
+	u8 stop_clk[2];
+
+	stop_clk[0] = stb0899_read_reg(state, STB0899_STOPCLK1);
+	stop_clk[1] = stb0899_read_reg(state, STB0899_STOPCLK2);
+
+	switch (state->delsys) {
+	case SYS_DVBS:
+		dprintk(state->verbose, FE_DEBUG, 1, "Delivery System -- DVB-S");
+		/* FECM/Viterbi ON	*/
+		reg = stb0899_read_reg(state, STB0899_FECM);
+		STB0899_SETFIELD_VAL(FECM_RSVD0, reg, 0);
+		STB0899_SETFIELD_VAL(FECM_VITERBI_ON, reg, 1);
+		stb0899_write_reg(state, STB0899_FECM, reg);
+
+		stb0899_write_reg(state, STB0899_RSULC, 0xb1);
+		stb0899_write_reg(state, STB0899_TSULC, 0x40);
+		stb0899_write_reg(state, STB0899_RSLLC, 0x42);
+		stb0899_write_reg(state, STB0899_TSLPL, 0x12);
+
+		reg = stb0899_read_reg(state, STB0899_TSTRES);
+		STB0899_SETFIELD_VAL(FRESLDPC, reg, 1);
+		stb0899_write_reg(state, STB0899_TSTRES, reg);
+
+		STB0899_SETFIELD_VAL(STOP_CHK8PSK, stop_clk[0], 1);
+		STB0899_SETFIELD_VAL(STOP_CKFEC108, stop_clk[0], 1);
+		STB0899_SETFIELD_VAL(STOP_CKFEC216, stop_clk[0], 1);
+
+		STB0899_SETFIELD_VAL(STOP_CKPKDLIN108, stop_clk[1], 1);
+		STB0899_SETFIELD_VAL(STOP_CKPKDLIN216, stop_clk[1], 1);
+
+		STB0899_SETFIELD_VAL(STOP_CKINTBUF216, stop_clk[0], 1);
+		STB0899_SETFIELD_VAL(STOP_CKCORE216, stop_clk[0], 0);
+
+		STB0899_SETFIELD_VAL(STOP_CKS2DMD108, stop_clk[1], 1);
+		break;
+	case SYS_DVBS2:
+		/* FECM/Viterbi OFF	*/
+		reg = stb0899_read_reg(state, STB0899_FECM);
+		STB0899_SETFIELD_VAL(FECM_RSVD0, reg, 0);
+		STB0899_SETFIELD_VAL(FECM_VITERBI_ON, reg, 0);
+		stb0899_write_reg(state, STB0899_FECM, reg);
+
+		stb0899_write_reg(state, STB0899_RSULC, 0xb1);
+		stb0899_write_reg(state, STB0899_TSULC, 0x42);
+		stb0899_write_reg(state, STB0899_RSLLC, 0x40);
+		stb0899_write_reg(state, STB0899_TSLPL, 0x02);
+
+		reg = stb0899_read_reg(state, STB0899_TSTRES);
+		STB0899_SETFIELD_VAL(FRESLDPC, reg, 0);
+		stb0899_write_reg(state, STB0899_TSTRES, reg);
+
+		STB0899_SETFIELD_VAL(STOP_CHK8PSK, stop_clk[0], 1);
+		STB0899_SETFIELD_VAL(STOP_CKFEC108, stop_clk[0], 0);
+		STB0899_SETFIELD_VAL(STOP_CKFEC216, stop_clk[0], 0);
+
+		STB0899_SETFIELD_VAL(STOP_CKPKDLIN108, stop_clk[1], 0);
+		STB0899_SETFIELD_VAL(STOP_CKPKDLIN216, stop_clk[1], 0);
+
+		STB0899_SETFIELD_VAL(STOP_CKINTBUF216, stop_clk[0], 0);
+		STB0899_SETFIELD_VAL(STOP_CKCORE216, stop_clk[0], 0);
+
+		STB0899_SETFIELD_VAL(STOP_CKS2DMD108, stop_clk[1], 0);
+		break;
+	case SYS_DSS:
+		/* FECM/Viterbi ON	*/
+		reg = stb0899_read_reg(state, STB0899_FECM);
+		STB0899_SETFIELD_VAL(FECM_RSVD0, reg, 1);
+		STB0899_SETFIELD_VAL(FECM_VITERBI_ON, reg, 1);
+		stb0899_write_reg(state, STB0899_FECM, reg);
+
+		stb0899_write_reg(state, STB0899_RSULC, 0xa1);
+		stb0899_write_reg(state, STB0899_TSULC, 0x61);
+		stb0899_write_reg(state, STB0899_RSLLC, 0x42);
+
+		reg = stb0899_read_reg(state, STB0899_TSTRES);
+		STB0899_SETFIELD_VAL(FRESLDPC, reg, 1);
+		stb0899_write_reg(state, STB0899_TSTRES, reg);
+
+		STB0899_SETFIELD_VAL(STOP_CHK8PSK, stop_clk[0], 1);
+		STB0899_SETFIELD_VAL(STOP_CKFEC108, stop_clk[0], 1);
+		STB0899_SETFIELD_VAL(STOP_CKFEC216, stop_clk[0], 1);
+
+		STB0899_SETFIELD_VAL(STOP_CKPKDLIN108, stop_clk[1], 1);
+		STB0899_SETFIELD_VAL(STOP_CKPKDLIN216, stop_clk[1], 1);
+
+		STB0899_SETFIELD_VAL(STOP_CKCORE216, stop_clk[0], 0);
+
+		STB0899_SETFIELD_VAL(STOP_CKS2DMD108, stop_clk[1], 1);
+		break;
+	default:
+		dprintk(state->verbose, FE_ERROR, 1, "Unsupported delivery system");
+		break;
+	}
+	STB0899_SETFIELD_VAL(STOP_CKADCI108, stop_clk[0], 0);
+	stb0899_write_regs(state, STB0899_STOPCLK1, stop_clk, 2);
+}
+
+/*
+ * stb0899_set_iterations
+ * set the LDPC iteration scale function
+ */
+static void stb0899_set_iterations(struct stb0899_state *state)
+{
+	struct stb0899_internal *internal = &state->internal;
+	struct stb0899_config *config = state->config;
+
+	s32 iter_scale;
+	u32 reg;
+
+	iter_scale = 17 * (internal->master_clk / 1000);
+	iter_scale += 410000;
+	iter_scale /= (internal->srate / 1000000);
+	iter_scale /= 1000;
+
+	if (iter_scale > config->ldpc_max_iter)
+		iter_scale = config->ldpc_max_iter;
+
+	reg = STB0899_READ_S2REG(STB0899_S2FEC, MAX_ITER);
+	STB0899_SETFIELD_VAL(MAX_ITERATIONS, reg, iter_scale);
+	stb0899_write_s2reg(state, STB0899_S2FEC, STB0899_BASE_MAX_ITER, STB0899_OFF0_MAX_ITER, reg);
+}
+
+static enum dvbfe_search stb0899_search(struct dvb_frontend *fe)
+{
+	struct stb0899_state *state = fe->demodulator_priv;
+	struct stb0899_params *i_params = &state->params;
+	struct stb0899_internal *internal = &state->internal;
+	struct stb0899_config *config = state->config;
+	struct dtv_frontend_properties *props = &fe->dtv_property_cache;
+
+	u32 SearchRange, gain;
+
+	i_params->freq	= props->frequency;
+	i_params->srate = props->symbol_rate;
+	state->delsys = props->delivery_system;
+	dprintk(state->verbose, FE_DEBUG, 1, "delivery system=%d", state->delsys);
+
+	SearchRange = 10000000;
+	dprintk(state->verbose, FE_DEBUG, 1, "Frequency=%d, Srate=%d", i_params->freq, i_params->srate);
+	/* checking Search Range is meaningless for a fixed 3 Mhz			*/
+	if (INRANGE(i_params->srate, 1000000, 45000000)) {
+		dprintk(state->verbose, FE_DEBUG, 1, "Parameters IN RANGE");
+		stb0899_set_delivery(state);
+
+		if (state->config->tuner_set_rfsiggain) {
+			if (internal->srate > 15000000)
+				gain =  8; /* 15Mb < srate < 45Mb, gain = 8dB	*/
+			else if (internal->srate > 5000000)
+				gain = 12; /*  5Mb < srate < 15Mb, gain = 12dB	*/
+			else
+				gain = 14; /*  1Mb < srate <  5Mb, gain = 14db	*/
+			state->config->tuner_set_rfsiggain(fe, gain);
+		}
+
+		if (i_params->srate <= 5000000)
+			stb0899_set_mclk(state, config->lo_clk);
+		else
+			stb0899_set_mclk(state, config->hi_clk);
+
+		switch (state->delsys) {
+		case SYS_DVBS:
+		case SYS_DSS:
+			dprintk(state->verbose, FE_DEBUG, 1, "DVB-S delivery system");
+			internal->freq	= i_params->freq;
+			internal->srate	= i_params->srate;
+			/*
+			 * search = user search range +
+			 *	    500Khz +
+			 *	    2 * Tuner_step_size +
+			 *	    10% of the symbol rate
+			 */
+			internal->srch_range	= SearchRange + 1500000 + (i_params->srate / 5);
+			internal->derot_percent	= 30;
+
+			/* What to do for tuners having no bandwidth setup ?	*/
+			/* enable tuner I/O */
+			stb0899_i2c_gate_ctrl(&state->frontend, 1);
+
+			if (state->config->tuner_set_bandwidth)
+				state->config->tuner_set_bandwidth(fe, (13 * (stb0899_carr_width(state) + SearchRange)) / 10);
+			if (state->config->tuner_get_bandwidth)
+				state->config->tuner_get_bandwidth(fe, &internal->tuner_bw);
+
+			/* disable tuner I/O */
+			stb0899_i2c_gate_ctrl(&state->frontend, 0);
+
+			/* Set DVB-S1 AGC		*/
+			stb0899_write_reg(state, STB0899_AGCRFCFG, 0x11);
+
+			/* Run the search algorithm	*/
+			dprintk(state->verbose, FE_DEBUG, 1, "running DVB-S search algo ..");
+			if (stb0899_dvbs_algo(state)	== RANGEOK) {
+				internal->lock		= 1;
+				dprintk(state->verbose, FE_DEBUG, 1,
+					"-------------------------------------> DVB-S LOCK !");
+
+//				stb0899_write_reg(state, STB0899_ERRCTRL1, 0x3d); /* Viterbi Errors	*/
+//				internal->v_status = stb0899_read_reg(state, STB0899_VSTATUS);
+//				internal->err_ctrl = stb0899_read_reg(state, STB0899_ERRCTRL1);
+//				dprintk(state->verbose, FE_DEBUG, 1, "VSTATUS=0x%02x", internal->v_status);
+//				dprintk(state->verbose, FE_DEBUG, 1, "ERR_CTRL=0x%02x", internal->err_ctrl);
+
+				return DVBFE_ALGO_SEARCH_SUCCESS;
+			} else {
+				internal->lock		= 0;
+
+				return DVBFE_ALGO_SEARCH_FAILED;
+			}
+			break;
+		case SYS_DVBS2:
+			internal->freq			= i_params->freq;
+			internal->srate			= i_params->srate;
+			internal->srch_range		= SearchRange;
+
+			/* enable tuner I/O */
+			stb0899_i2c_gate_ctrl(&state->frontend, 1);
+
+			if (state->config->tuner_set_bandwidth)
+				state->config->tuner_set_bandwidth(fe, (stb0899_carr_width(state) + SearchRange));
+			if (state->config->tuner_get_bandwidth)
+				state->config->tuner_get_bandwidth(fe, &internal->tuner_bw);
+
+			/* disable tuner I/O */
+			stb0899_i2c_gate_ctrl(&state->frontend, 0);
+
+//			pParams->SpectralInv		= pSearch->IQ_Inversion;
+
+			/* Set DVB-S2 AGC		*/
+			stb0899_write_reg(state, STB0899_AGCRFCFG, 0x1c);
+
+			/* Set IterScale =f(MCLK,SYMB)	*/
+			stb0899_set_iterations(state);
+
+			/* Run the search algorithm	*/
+			dprintk(state->verbose, FE_DEBUG, 1, "running DVB-S2 search algo ..");
+			if (stb0899_dvbs2_algo(state)	== DVBS2_FEC_LOCK) {
+				internal->lock		= 1;
+				dprintk(state->verbose, FE_DEBUG, 1,
+					"-------------------------------------> DVB-S2 LOCK !");
+
+//				stb0899_write_reg(state, STB0899_ERRCTRL1, 0xb6); /* Packet Errors	*/
+//				internal->v_status = stb0899_read_reg(state, STB0899_VSTATUS);
+//				internal->err_ctrl = stb0899_read_reg(state, STB0899_ERRCTRL1);
+
+				return DVBFE_ALGO_SEARCH_SUCCESS;
+			} else {
+				internal->lock		= 0;
+
+				return DVBFE_ALGO_SEARCH_FAILED;
+			}
+			break;
+		default:
+			dprintk(state->verbose, FE_ERROR, 1, "Unsupported delivery system");
+			return DVBFE_ALGO_SEARCH_INVALID;
+		}
+	}
+
+	return DVBFE_ALGO_SEARCH_ERROR;
+}
+
+static int stb0899_get_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct stb0899_state *state		= fe->demodulator_priv;
+	struct stb0899_internal *internal	= &state->internal;
+
+	dprintk(state->verbose, FE_DEBUG, 1, "Get params");
+	p->symbol_rate = internal->srate;
+	p->frequency = internal->freq;
+
+	return 0;
+}
+
+static enum dvbfe_algo stb0899_frontend_algo(struct dvb_frontend *fe)
+{
+	return DVBFE_ALGO_CUSTOM;
+}
+
+static struct dvb_frontend_ops stb0899_ops = {
+	.delsys = { SYS_DVBS, SYS_DVBS2, SYS_DSS },
+	.info = {
+		.name 			= "STB0899 Multistandard",
+		.frequency_min		= 950000,
+		.frequency_max 		= 2150000,
+		.frequency_stepsize	= 0,
+		.frequency_tolerance	= 0,
+		.symbol_rate_min 	=  5000000,
+		.symbol_rate_max 	= 45000000,
+
+		.caps 			= FE_CAN_INVERSION_AUTO	|
+					  FE_CAN_FEC_AUTO	|
+					  FE_CAN_2G_MODULATION	|
+					  FE_CAN_QPSK
+	},
+
+	.release			= stb0899_release,
+	.init				= stb0899_init,
+	.sleep				= stb0899_sleep,
+//	.wakeup				= stb0899_wakeup,
+
+	.i2c_gate_ctrl			= stb0899_i2c_gate_ctrl,
+
+	.get_frontend_algo		= stb0899_frontend_algo,
+	.search				= stb0899_search,
+	.get_frontend                   = stb0899_get_frontend,
+
+
+	.read_status			= stb0899_read_status,
+	.read_snr			= stb0899_read_snr,
+	.read_signal_strength		= stb0899_read_signal_strength,
+	.read_ber			= stb0899_read_ber,
+
+	.set_voltage			= stb0899_set_voltage,
+	.set_tone			= stb0899_set_tone,
+
+	.diseqc_send_master_cmd		= stb0899_send_diseqc_msg,
+	.diseqc_recv_slave_reply	= stb0899_recv_slave_reply,
+	.diseqc_send_burst		= stb0899_send_diseqc_burst,
+};
+
+struct dvb_frontend *stb0899_attach(struct stb0899_config *config, struct i2c_adapter *i2c)
+{
+	struct stb0899_state *state = NULL;
+	enum stb0899_inversion inversion;
+
+	state = kzalloc(sizeof (struct stb0899_state), GFP_KERNEL);
+	if (state == NULL)
+		goto error;
+
+	inversion				= config->inversion;
+	state->verbose				= &verbose;
+	state->config				= config;
+	state->i2c				= i2c;
+	state->frontend.ops			= stb0899_ops;
+	state->frontend.demodulator_priv	= state;
+	state->internal.inversion		= inversion;
+
+	stb0899_wakeup(&state->frontend);
+	if (stb0899_get_dev_id(state) == -ENODEV) {
+		printk("%s: Exiting .. !\n", __func__);
+		goto error;
+	}
+
+	printk("%s: Attaching STB0899 \n", __func__);
+	return &state->frontend;
+
+error:
+	kfree(state);
+	return NULL;
+}
+EXPORT_SYMBOL(stb0899_attach);
+MODULE_PARM_DESC(verbose, "Set Verbosity level");
+MODULE_AUTHOR("Manu Abraham");
+MODULE_DESCRIPTION("STB0899 Multi-Std frontend");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb-frontends/stb0899_drv.h b/drivers/media/dvb-frontends/stb0899_drv.h
new file mode 100644
index 0000000..98b200c
--- /dev/null
+++ b/drivers/media/dvb-frontends/stb0899_drv.h
@@ -0,0 +1,162 @@
+/*
+	STB0899 Multistandard Frontend driver
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	Copyright (C) ST Microelectronics
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the 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 __STB0899_DRV_H
+#define __STB0899_DRV_H
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include "dvb_frontend.h"
+
+#define STB0899_TSMODE_SERIAL		1
+#define STB0899_CLKPOL_FALLING		2
+#define STB0899_CLKNULL_PARITY		3
+#define STB0899_SYNC_FORCED		4
+#define STB0899_FECMODE_DSS		5
+
+struct stb0899_s1_reg {
+	u16	address;
+	u8	data;
+};
+
+struct stb0899_s2_reg {
+	u16	offset;
+	u32	base_address;
+	u32	data;
+};
+
+enum stb0899_inversion {
+	IQ_SWAP_OFF	= 0,
+	IQ_SWAP_ON,
+	IQ_SWAP_AUTO
+};
+
+#define STB0899_GPIO00				0xf140
+#define STB0899_GPIO01				0xf141
+#define STB0899_GPIO02				0xf142
+#define STB0899_GPIO03				0xf143
+#define STB0899_GPIO04				0xf144
+#define STB0899_GPIO05				0xf145
+#define STB0899_GPIO06				0xf146
+#define STB0899_GPIO07				0xf147
+#define STB0899_GPIO08				0xf148
+#define STB0899_GPIO09				0xf149
+#define STB0899_GPIO10				0xf14a
+#define STB0899_GPIO11				0xf14b
+#define STB0899_GPIO12				0xf14c
+#define STB0899_GPIO13				0xf14d
+#define STB0899_GPIO14				0xf14e
+#define STB0899_GPIO15				0xf14f
+#define STB0899_GPIO16				0xf150
+#define STB0899_GPIO17				0xf151
+#define STB0899_GPIO18				0xf152
+#define STB0899_GPIO19				0xf153
+#define STB0899_GPIO20				0xf154
+
+#define STB0899_GPIOPULLUP			0x01 /* Output device is connected to Vdd */
+#define STB0899_GPIOPULLDN			0x00 /* Output device is connected to Vss */
+
+#define STB0899_POSTPROC_GPIO_POWER		0x00
+#define STB0899_POSTPROC_GPIO_LOCK		0x01
+
+/*
+ * Post process output configuration control
+ * 1. POWER ON/OFF		(index 0)
+ * 2. FE_HAS_LOCK/LOCK_LOSS	(index 1)
+ *
+ * @gpio 	= one of the above listed GPIO's
+ * @level	= output state: pulled up or low
+ */
+struct stb0899_postproc {
+	u16	gpio;
+	u8	level;
+};
+
+struct stb0899_config {
+	const struct stb0899_s1_reg	*init_dev;
+	const struct stb0899_s2_reg	*init_s2_demod;
+	const struct stb0899_s1_reg	*init_s1_demod;
+	const struct stb0899_s2_reg	*init_s2_fec;
+	const struct stb0899_s1_reg	*init_tst;
+
+	const struct stb0899_postproc	*postproc;
+
+	enum stb0899_inversion		inversion;
+
+	u32	xtal_freq;
+
+	u8	demod_address;
+	u8	ts_output_mode;
+	u8	block_sync_mode;
+	u8	ts_pfbit_toggle;
+
+	u8	clock_polarity;
+	u8	data_clk_parity;
+	u8	fec_mode;
+	u8	data_output_ctl;
+	u8	data_fifo_mode;
+	u8	out_rate_comp;
+	u8	i2c_repeater;
+//	int	inversion;
+	int	lo_clk;
+	int	hi_clk;
+
+	u32	esno_ave;
+	u32	esno_quant;
+	u32	avframes_coarse;
+	u32	avframes_fine;
+	u32	miss_threshold;
+	u32	uwp_threshold_acq;
+	u32	uwp_threshold_track;
+	u32	uwp_threshold_sof;
+	u32	sof_search_timeout;
+
+	u32	btr_nco_bits;
+	u32	btr_gain_shift_offset;
+	u32	crl_nco_bits;
+	u32	ldpc_max_iter;
+
+	int (*tuner_set_frequency)(struct dvb_frontend *fe, u32 frequency);
+	int (*tuner_get_frequency)(struct dvb_frontend *fe, u32 *frequency);
+	int (*tuner_set_bandwidth)(struct dvb_frontend *fe, u32 bandwidth);
+	int (*tuner_get_bandwidth)(struct dvb_frontend *fe, u32 *bandwidth);
+	int (*tuner_set_rfsiggain)(struct dvb_frontend *fe, u32 rf_gain);
+};
+
+#if defined(CONFIG_DVB_STB0899) || (defined(CONFIG_DVB_STB0899_MODULE) && defined(MODULE))
+
+extern struct dvb_frontend *stb0899_attach(struct stb0899_config *config,
+					   struct i2c_adapter *i2c);
+
+#else
+
+static inline struct dvb_frontend *stb0899_attach(struct stb0899_config *config,
+						  struct i2c_adapter *i2c)
+{
+	printk(KERN_WARNING "%s: Driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+
+#endif //CONFIG_DVB_STB0899
+
+
+#endif
diff --git a/drivers/media/dvb-frontends/stb0899_priv.h b/drivers/media/dvb-frontends/stb0899_priv.h
new file mode 100644
index 0000000..82395b9
--- /dev/null
+++ b/drivers/media/dvb-frontends/stb0899_priv.h
@@ -0,0 +1,263 @@
+/*
+	STB0899 Multistandard Frontend driver
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	Copyright (C) ST Microelectronics
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the 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 __STB0899_PRIV_H
+#define __STB0899_PRIV_H
+
+#include "dvb_frontend.h"
+#include "stb0899_drv.h"
+
+#define FE_ERROR				0
+#define FE_NOTICE				1
+#define FE_INFO					2
+#define FE_DEBUG				3
+#define FE_DEBUGREG				4
+
+#define dprintk(x, y, z, format, arg...) do {						\
+	if (z) {									\
+		if	((*x > FE_ERROR) && (*x > y))					\
+			printk(KERN_ERR "%s: " format "\n", __func__ , ##arg);		\
+		else if	((*x > FE_NOTICE) && (*x > y))					\
+			printk(KERN_NOTICE "%s: " format "\n", __func__ , ##arg);	\
+		else if ((*x > FE_INFO) && (*x > y))					\
+			printk(KERN_INFO "%s: " format "\n", __func__ , ##arg);		\
+		else if ((*x > FE_DEBUG) && (*x > y))					\
+			printk(KERN_DEBUG "%s: " format "\n", __func__ , ##arg);	\
+	} else {									\
+		if (*x > y)								\
+			printk(format, ##arg);						\
+	}										\
+} while(0)
+
+#define INRANGE(val, x, y)			(((x <= val) && (val <= y)) ||		\
+						 ((y <= val) && (val <= x)) ? 1 : 0)
+
+#define BYTE0					0
+#define BYTE1					8
+#define BYTE2					16
+#define BYTE3					24
+
+#define GETBYTE(x, y)				(((x) >> (y)) & 0xff)
+#define MAKEWORD32(a, b, c, d)			(((a) << 24) | ((b) << 16) | ((c) << 8) | (d))
+#define MAKEWORD16(a, b)			(((a) << 8) | (b))
+
+#define LSB(x)					((x & 0xff))
+#define MSB(y)					((y >> 8) & 0xff)
+
+
+#define STB0899_GETFIELD(bitf, val)		((val >> STB0899_OFFST_##bitf) & ((1 << STB0899_WIDTH_##bitf) - 1))
+
+
+#define STB0899_SETFIELD(mask, val, width, offset)      (mask & (~(((1 << width) - 1) <<	\
+							 offset))) | ((val &			\
+							 ((1 << width) - 1)) << offset)
+
+#define STB0899_SETFIELD_VAL(bitf, mask, val)	(mask = (mask & (~(((1 << STB0899_WIDTH_##bitf) - 1) <<\
+							 STB0899_OFFST_##bitf))) | \
+							 (val << STB0899_OFFST_##bitf))
+
+
+enum stb0899_status {
+	NOAGC1	= 0,
+	AGC1OK,
+	NOTIMING,
+	ANALOGCARRIER,
+	TIMINGOK,
+	NOAGC2,
+	AGC2OK,
+	NOCARRIER,
+	CARRIEROK,
+	NODATA,
+	FALSELOCK,
+	DATAOK,
+	OUTOFRANGE,
+	RANGEOK,
+	DVBS2_DEMOD_LOCK,
+	DVBS2_DEMOD_NOLOCK,
+	DVBS2_FEC_LOCK,
+	DVBS2_FEC_NOLOCK
+};
+
+enum stb0899_modcod {
+	STB0899_DUMMY_PLF,
+	STB0899_QPSK_14,
+	STB0899_QPSK_13,
+	STB0899_QPSK_25,
+	STB0899_QPSK_12,
+	STB0899_QPSK_35,
+	STB0899_QPSK_23,
+	STB0899_QPSK_34,
+	STB0899_QPSK_45,
+	STB0899_QPSK_56,
+	STB0899_QPSK_89,
+	STB0899_QPSK_910,
+	STB0899_8PSK_35,
+	STB0899_8PSK_23,
+	STB0899_8PSK_34,
+	STB0899_8PSK_56,
+	STB0899_8PSK_89,
+	STB0899_8PSK_910,
+	STB0899_16APSK_23,
+	STB0899_16APSK_34,
+	STB0899_16APSK_45,
+	STB0899_16APSK_56,
+	STB0899_16APSK_89,
+	STB0899_16APSK_910,
+	STB0899_32APSK_34,
+	STB0899_32APSK_45,
+	STB0899_32APSK_56,
+	STB0899_32APSK_89,
+	STB0899_32APSK_910
+};
+
+enum stb0899_frame {
+	STB0899_LONG_FRAME,
+	STB0899_SHORT_FRAME
+};
+
+enum stb0899_alpha {
+	RRC_20,
+	RRC_25,
+	RRC_35
+};
+
+struct stb0899_tab {
+	s32 real;
+	s32 read;
+};
+
+enum stb0899_fec {
+	STB0899_FEC_1_2			= 13,
+	STB0899_FEC_2_3			= 18,
+	STB0899_FEC_3_4			= 21,
+	STB0899_FEC_5_6			= 24,
+	STB0899_FEC_6_7			= 25,
+	STB0899_FEC_7_8			= 26
+};
+
+struct stb0899_params {
+	u32	freq;					/* Frequency	*/
+	u32	srate;					/* Symbol rate	*/
+	enum fe_code_rate fecrate;
+};
+
+struct stb0899_internal {
+	u32			master_clk;
+	u32			freq;			/* Demod internal Frequency		*/
+	u32			srate;			/* Demod internal Symbol rate		*/
+	enum stb0899_fec	fecrate;		/* Demod internal FEC rate		*/
+	s32			srch_range;		/* Demod internal Search Range		*/
+	s32			sub_range;		/* Demod current sub range (Hz)		*/
+	s32			tuner_step;		/* Tuner step (Hz)			*/
+	s32			tuner_offst;		/* Relative offset to carrier (Hz)	*/
+	u32			tuner_bw;		/* Current bandwidth of the tuner (Hz)	*/
+
+	s32			mclk;			/* Masterclock Divider factor (binary)	*/
+	s32			rolloff;		/* Current RollOff of the filter (x100)	*/
+
+	s16			derot_freq;		/* Current derotator frequency (Hz)	*/
+	s16			derot_percent;
+
+	s16			direction;		/* Current derotator search direction	*/
+	s16			derot_step;		/* Derotator step (binary value)	*/
+	s16			t_derot;		/* Derotator time constant (ms)		*/
+	s16			t_data;			/* Data recovery time constant (ms)	*/
+	s16			sub_dir;		/* Direction of the next sub range	*/
+
+	s16			t_agc1;			/* Agc1 time constant (ms)		*/
+	s16			t_agc2;			/* Agc2 time constant (ms)		*/
+
+	u32			lock;			/* Demod internal lock state		*/
+	enum stb0899_status	status;			/* Demod internal status		*/
+
+	/* DVB-S2 */
+	s32			agc_gain;		/* RF AGC Gain				*/
+	s32			center_freq;		/* Nominal carrier frequency		*/
+	s32			av_frame_coarse;	/* Coarse carrier freq search frames	*/
+	s32			av_frame_fine;		/* Fine carrier freq search frames	*/
+
+	s16			step_size;		/* Carrier frequency search step size	*/
+
+	enum stb0899_alpha	rrc_alpha;
+	enum stb0899_inversion	inversion;
+	enum stb0899_modcod	modcod;
+	u8			pilots;			/* Pilots found				*/
+
+	enum stb0899_frame	frame_length;
+	u8			v_status;		/* VSTATUS				*/
+	u8			err_ctrl;		/* ERRCTRLn				*/
+};
+
+struct stb0899_state {
+	struct i2c_adapter		*i2c;
+	struct stb0899_config		*config;
+	struct dvb_frontend		frontend;
+
+	u32				*verbose;	/* Cached module verbosity level	*/
+
+	struct stb0899_internal		internal;	/* Device internal parameters		*/
+
+	/*	cached params from API	*/
+	enum fe_delivery_system		delsys;
+	struct stb0899_params		params;
+
+	u32				rx_freq;	/* DiSEqC 2.0 receiver freq		*/
+	struct mutex			search_lock;
+};
+/* stb0899.c		*/
+extern int stb0899_read_reg(struct stb0899_state *state,
+			    unsigned int reg);
+
+extern u32 _stb0899_read_s2reg(struct stb0899_state *state,
+			       u32 stb0899_i2cdev,
+			       u32 stb0899_base_addr,
+			       u16 stb0899_reg_offset);
+
+extern int stb0899_read_regs(struct stb0899_state *state,
+			     unsigned int reg, u8 *buf,
+			     u32 count);
+
+extern int stb0899_write_regs(struct stb0899_state *state,
+			      unsigned int reg, u8 *data,
+			      u32 count);
+
+extern int stb0899_write_reg(struct stb0899_state *state,
+			     unsigned int reg,
+			     u8 data);
+
+extern int stb0899_write_s2reg(struct stb0899_state *state,
+			       u32 stb0899_i2cdev,
+			       u32 stb0899_base_addr,
+			       u16 stb0899_reg_offset,
+			       u32 stb0899_data);
+
+extern int stb0899_i2c_gate_ctrl(struct dvb_frontend *fe, int enable);
+
+
+#define STB0899_READ_S2REG(DEVICE, REG) 	(_stb0899_read_s2reg(state, DEVICE, STB0899_BASE_##REG, STB0899_OFF0_##REG))
+//#define STB0899_WRITE_S2REG(DEVICE, REG, DATA)	(_stb0899_write_s2reg(state, DEVICE, STB0899_BASE_##REG, STB0899_OFF0_##REG, DATA))
+
+/* stb0899_algo.c	*/
+extern enum stb0899_status stb0899_dvbs_algo(struct stb0899_state *state);
+extern enum stb0899_status stb0899_dvbs2_algo(struct stb0899_state *state);
+extern long stb0899_carr_width(struct stb0899_state *state);
+
+#endif //__STB0899_PRIV_H
diff --git a/drivers/media/dvb-frontends/stb0899_reg.h b/drivers/media/dvb-frontends/stb0899_reg.h
new file mode 100644
index 0000000..ba1ed56
--- /dev/null
+++ b/drivers/media/dvb-frontends/stb0899_reg.h
@@ -0,0 +1,2027 @@
+/*
+	STB0899 Multistandard Frontend driver
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	Copyright (C) ST Microelectronics
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the 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 __STB0899_REG_H
+#define __STB0899_REG_H
+
+/*	S1	*/
+#define STB0899_DEV_ID				0xf000
+#define STB0899_CHIP_ID				(0x0f << 4)
+#define STB0899_OFFST_CHIP_ID			4
+#define STB0899_WIDTH_CHIP_ID			4
+#define STB0899_CHIP_REL			(0x0f << 0)
+#define STB0899_OFFST_CHIP_REL			0
+#define STB0899_WIDTH_CHIP_REL			4
+
+#define STB0899_DEMOD				0xf40e
+#define STB0899_MODECOEFF			(0x01 << 0)
+#define STB0899_OFFST_MODECOEFF			0
+#define STB0899_WIDTH_MODECOEFF			1
+
+#define STB0899_RCOMPC				0xf410
+#define STB0899_AGC1CN				0xf412
+#define STB0899_AGC1REF				0xf413
+#define STB0899_RTC				0xf417
+#define STB0899_TMGCFG				0xf418
+#define STB0899_AGC2REF				0xf419
+#define STB0899_TLSR				0xf41a
+
+#define STB0899_CFD				0xf41b
+#define STB0899_CFD_ON				(0x01 << 7)
+#define STB0899_OFFST_CFD_ON			7
+#define STB0899_WIDTH_CFD_ON			1
+
+#define STB0899_ACLC				0xf41c
+
+#define STB0899_BCLC				0xf41d
+#define STB0899_OFFST_ALGO			6
+#define STB0899_WIDTH_ALGO_QPSK2		2
+#define STB0899_ALGO_QPSK2			(2 << 6)
+#define STB0899_ALGO_QPSK1			(1 << 6)
+#define STB0899_ALGO_BPSK			(0 << 6)
+#define STB0899_OFFST_BETA			0
+#define STB0899_WIDTH_BETA			6
+
+#define STB0899_EQON				0xf41e
+#define STB0899_LDT				0xf41f
+#define STB0899_LDT2				0xf420
+#define STB0899_EQUALREF			0xf425
+#define STB0899_TMGRAMP				0xf426
+#define STB0899_TMGTHD				0xf427
+#define STB0899_IDCCOMP				0xf428
+#define STB0899_QDCCOMP				0xf429
+#define STB0899_POWERI				0xf42a
+#define STB0899_POWERQ				0xf42b
+#define STB0899_RCOMP				0xf42c
+
+#define STB0899_AGCIQIN				0xf42e
+#define STB0899_AGCIQVALUE			(0xff << 0)
+#define STB0899_OFFST_AGCIQVALUE		0
+#define STB0899_WIDTH_AGCIQVALUE		8
+
+#define STB0899_AGC2I1				0xf436
+#define STB0899_AGC2I2				0xf437
+
+#define STB0899_TLIR				0xf438
+#define STB0899_TLIR_TMG_LOCK_IND		(0xff << 0)
+#define STB0899_OFFST_TLIR_TMG_LOCK_IND		0
+#define STB0899_WIDTH_TLIR_TMG_LOCK_IND		8
+
+#define STB0899_RTF				0xf439
+#define STB0899_RTF_TIMING_LOOP_FREQ		(0xff << 0)
+#define STB0899_OFFST_RTF_TIMING_LOOP_FREQ	0
+#define STB0899_WIDTH_RTF_TIMING_LOOP_FREQ	8
+
+#define STB0899_DSTATUS				0xf43a
+#define STB0899_CARRIER_FOUND			(0x01 << 7)
+#define STB0899_OFFST_CARRIER_FOUND		7
+#define STB0899_WIDTH_CARRIER_FOUND		1
+#define STB0899_TMG_LOCK			(0x01 << 6)
+#define STB0899_OFFST_TMG_LOCK			6
+#define STB0899_WIDTH_TMG_LOCK			1
+#define STB0899_DEMOD_LOCK			(0x01 << 5)
+#define STB0899_OFFST_DEMOD_LOCK		5
+#define STB0899_WIDTH_DEMOD_LOCK		1
+#define STB0899_TMG_AUTO			(0x01 << 4)
+#define STB0899_OFFST_TMG_AUTO			4
+#define STB0899_WIDTH_TMG_AUTO			1
+#define STB0899_END_MAIN			(0x01 << 3)
+#define STB0899_OFFST_END_MAIN			3
+#define STB0899_WIDTH_END_MAIN			1
+
+#define STB0899_LDI				0xf43b
+#define STB0899_OFFST_LDI			0
+#define STB0899_WIDTH_LDI			8
+
+#define STB0899_CFRM				0xf43e
+#define STB0899_OFFST_CFRM			0
+#define STB0899_WIDTH_CFRM			8
+
+#define STB0899_CFRL				0xf43f
+#define STB0899_OFFST_CFRL			0
+#define STB0899_WIDTH_CFRL			8
+
+#define STB0899_NIRM				0xf440
+#define STB0899_OFFST_NIRM			0
+#define STB0899_WIDTH_NIRM			8
+
+#define STB0899_NIRL				0xf441
+#define STB0899_OFFST_NIRL			0
+#define STB0899_WIDTH_NIRL			8
+
+#define STB0899_ISYMB				0xf444
+#define STB0899_QSYMB				0xf445
+
+#define STB0899_SFRH				0xf446
+#define STB0899_OFFST_SFRH			0
+#define STB0899_WIDTH_SFRH			8
+
+#define STB0899_SFRM				0xf447
+#define STB0899_OFFST_SFRM			0
+#define STB0899_WIDTH_SFRM			8
+
+#define STB0899_SFRL				0xf448
+#define STB0899_OFFST_SFRL			4
+#define STB0899_WIDTH_SFRL			4
+
+#define STB0899_SFRUPH				0xf44c
+#define STB0899_SFRUPM				0xf44d
+#define STB0899_SFRUPL				0xf44e
+
+#define STB0899_EQUAI1				0xf4e0
+#define STB0899_EQUAQ1				0xf4e1
+#define STB0899_EQUAI2				0xf4e2
+#define STB0899_EQUAQ2				0xf4e3
+#define STB0899_EQUAI3				0xf4e4
+#define STB0899_EQUAQ3				0xf4e5
+#define STB0899_EQUAI4				0xf4e6
+#define STB0899_EQUAQ4				0xf4e7
+#define STB0899_EQUAI5				0xf4e8
+#define STB0899_EQUAQ5				0xf4e9
+
+#define STB0899_DSTATUS2			0xf50c
+#define STB0899_DS2_TMG_AUTOSRCH		(0x01 << 7)
+#define STB8999_OFFST_DS2_TMG_AUTOSRCH		7
+#define STB0899_WIDTH_DS2_TMG_AUTOSRCH		1
+#define STB0899_DS2_END_MAINLOOP		(0x01 << 6)
+#define STB0899_OFFST_DS2_END_MAINLOOP		6
+#define STB0899_WIDTH_DS2_END_MAINLOOP		1
+#define STB0899_DS2_CFSYNC			(0x01 << 5)
+#define STB0899_OFFST_DS2_CFSYNC		5
+#define STB0899_WIDTH_DS2_CFSYNC		1
+#define STB0899_DS2_TMGLOCK			(0x01 << 4)
+#define STB0899_OFFST_DS2_TMGLOCK		4
+#define STB0899_WIDTH_DS2_TMGLOCK		1
+#define STB0899_DS2_DEMODWAIT			(0x01 << 3)
+#define STB0899_OFFST_DS2_DEMODWAIT		3
+#define STB0899_WIDTH_DS2_DEMODWAIT		1
+#define STB0899_DS2_FECON			(0x01 << 1)
+#define STB0899_OFFST_DS2_FECON			1
+#define STB0899_WIDTH_DS2_FECON			1
+
+/*	S1 FEC	*/
+#define STB0899_VSTATUS				0xf50d
+#define STB0899_VSTATUS_VITERBI_ON		(0x01 << 7)
+#define STB0899_OFFST_VSTATUS_VITERBI_ON	7
+#define STB0899_WIDTH_VSTATUS_VITERBI_ON	1
+#define STB0899_VSTATUS_END_LOOPVIT		(0x01 << 6)
+#define STB0899_OFFST_VSTATUS_END_LOOPVIT	6
+#define STB0899_WIDTH_VSTATUS_END_LOOPVIT	1
+#define STB0899_VSTATUS_PRFVIT			(0x01 << 4)
+#define STB0899_OFFST_VSTATUS_PRFVIT		4
+#define STB0899_WIDTH_VSTATUS_PRFVIT		1
+#define STB0899_VSTATUS_LOCKEDVIT		(0x01 << 3)
+#define STB0899_OFFST_VSTATUS_LOCKEDVIT		3
+#define STB0899_WIDTH_VSTATUS_LOCKEDVIT		1
+
+#define STB0899_VERROR				0xf50f
+
+#define STB0899_IQSWAP				0xf523
+#define STB0899_SYM				(0x01 << 3)
+#define STB0899_OFFST_SYM			3
+#define STB0899_WIDTH_SYM			1
+
+#define STB0899_FECAUTO1			0xf530
+#define STB0899_DSSSRCH				(0x01 << 3)
+#define STB0899_OFFST_DSSSRCH			3
+#define STB0899_WIDTH_DSSSRCH			1
+#define STB0899_SYMSRCH				(0x01 << 2)
+#define STB0899_OFFST_SYMSRCH			2
+#define STB0899_WIDTH_SYMSRCH			1
+#define STB0899_QPSKSRCH			(0x01 << 1)
+#define STB0899_OFFST_QPSKSRCH			1
+#define STB0899_WIDTH_QPSKSRCH			1
+#define STB0899_BPSKSRCH			(0x01 << 0)
+#define STB0899_OFFST_BPSKSRCH			0
+#define STB0899_WIDTH_BPSKSRCH			1
+
+#define STB0899_FECM				0xf533
+#define STB0899_FECM_NOT_DVB			(0x01 << 7)
+#define STB0899_OFFST_FECM_NOT_DVB		7
+#define STB0899_WIDTH_FECM_NOT_DVB		1
+#define STB0899_FECM_RSVD1			(0x07 << 4)
+#define STB0899_OFFST_FECM_RSVD1		4
+#define STB0899_WIDTH_FECM_RSVD1		3
+#define STB0899_FECM_VITERBI_ON			(0x01 << 3)
+#define STB0899_OFFST_FECM_VITERBI_ON		3
+#define STB0899_WIDTH_FECM_VITERBI_ON		1
+#define STB0899_FECM_RSVD0			(0x01 << 2)
+#define STB0899_OFFST_FECM_RSVD0		2
+#define STB0899_WIDTH_FECM_RSVD0		1
+#define STB0899_FECM_SYNCDIS			(0x01 << 1)
+#define STB0899_OFFST_FECM_SYNCDIS		1
+#define STB0899_WIDTH_FECM_SYNCDIS		1
+#define STB0899_FECM_SYMI			(0x01 << 0)
+#define STB0899_OFFST_FECM_SYMI			0
+#define STB0899_WIDTH_FECM_SYMI			1
+
+#define STB0899_VTH12				0xf534
+#define STB0899_VTH23				0xf535
+#define STB0899_VTH34				0xf536
+#define STB0899_VTH56				0xf537
+#define STB0899_VTH67				0xf538
+#define STB0899_VTH78				0xf539
+
+#define STB0899_PRVIT				0xf53c
+#define STB0899_PR_7_8				(0x01 << 5)
+#define STB0899_OFFST_PR_7_8			5
+#define STB0899_WIDTH_PR_7_8			1
+#define STB0899_PR_6_7				(0x01 << 4)
+#define STB0899_OFFST_PR_6_7			4
+#define STB0899_WIDTH_PR_6_7			1
+#define STB0899_PR_5_6				(0x01 << 3)
+#define STB0899_OFFST_PR_5_6			3
+#define STB0899_WIDTH_PR_5_6			1
+#define STB0899_PR_3_4				(0x01 << 2)
+#define STB0899_OFFST_PR_3_4			2
+#define STB0899_WIDTH_PR_3_4			1
+#define STB0899_PR_2_3				(0x01 << 1)
+#define STB0899_OFFST_PR_2_3			1
+#define STB0899_WIDTH_PR_2_3			1
+#define STB0899_PR_1_2				(0x01 << 0)
+#define STB0899_OFFST_PR_1_2			0
+#define STB0899_WIDTH_PR_1_2			1
+
+#define STB0899_VITSYNC				0xf53d
+#define STB0899_AM				(0x01 << 7)
+#define STB0899_OFFST_AM			7
+#define STB0899_WIDTH_AM			1
+#define STB0899_FREEZE				(0x01 << 6)
+#define STB0899_OFFST_FREEZE			6
+#define STB0899_WIDTH_FREEZE			1
+#define STB0899_SN_65536			(0x03 << 4)
+#define STB0899_OFFST_SN_65536			4
+#define STB0899_WIDTH_SN_65536			2
+#define STB0899_SN_16384			(0x01 << 5)
+#define STB0899_OFFST_SN_16384			5
+#define STB0899_WIDTH_SN_16384			1
+#define STB0899_SN_4096				(0x01 << 4)
+#define STB0899_OFFST_SN_4096			4
+#define STB0899_WIDTH_SN_4096			1
+#define STB0899_SN_1024				(0x00 << 4)
+#define STB0899_OFFST_SN_1024			4
+#define STB0899_WIDTH_SN_1024			0
+#define STB0899_TO_128				(0x03 << 2)
+#define STB0899_OFFST_TO_128			2
+#define STB0899_WIDTH_TO_128			2
+#define STB0899_TO_64				(0x01 << 3)
+#define STB0899_OFFST_TO_64			3
+#define STB0899_WIDTH_TO_64			1
+#define STB0899_TO_32				(0x01 << 2)
+#define STB0899_OFFST_TO_32			2
+#define STB0899_WIDTH_TO_32			1
+#define STB0899_TO_16				(0x00 << 2)
+#define STB0899_OFFST_TO_16			2
+#define STB0899_WIDTH_TO_16			0
+#define STB0899_HYST_128			(0x03 << 1)
+#define STB0899_OFFST_HYST_128			1
+#define STB0899_WIDTH_HYST_128			2
+#define STB0899_HYST_64				(0x01 << 1)
+#define STB0899_OFFST_HYST_64			1
+#define STB0899_WIDTH_HYST_64			1
+#define STB0899_HYST_32				(0x01 << 0)
+#define STB0899_OFFST_HYST_32			0
+#define STB0899_WIDTH_HYST_32			1
+#define STB0899_HYST_16				(0x00 << 0)
+#define STB0899_OFFST_HYST_16			0
+#define STB0899_WIDTH_HYST_16			0
+
+#define STB0899_RSULC				0xf548
+#define STB0899_ULDIL_ON			(0x01 << 7)
+#define STB0899_OFFST_ULDIL_ON			7
+#define STB0899_WIDTH_ULDIL_ON			1
+#define STB0899_ULAUTO_ON			(0x01 << 6)
+#define STB0899_OFFST_ULAUTO_ON			6
+#define STB0899_WIDTH_ULAUTO_ON			1
+#define STB0899_ULRS_ON				(0x01 << 5)
+#define STB0899_OFFST_ULRS_ON			5
+#define STB0899_WIDTH_ULRS_ON			1
+#define STB0899_ULDESCRAM_ON			(0x01 << 4)
+#define STB0899_OFFST_ULDESCRAM_ON		4
+#define STB0899_WIDTH_ULDESCRAM_ON		1
+#define STB0899_UL_DISABLE			(0x01 << 2)
+#define STB0899_OFFST_UL_DISABLE		2
+#define STB0899_WIDTH_UL_DISABLE		1
+#define STB0899_NOFTHRESHOLD			(0x01 << 0)
+#define STB0899_OFFST_NOFTHRESHOLD		0
+#define STB0899_WIDTH_NOFTHRESHOLD		1
+
+#define STB0899_RSLLC				0xf54a
+#define STB0899_DEMAPVIT			0xf583
+#define STB0899_DEMAPVIT_RSVD			(0x01 << 7)
+#define STB0899_OFFST_DEMAPVIT_RSVD		7
+#define STB0899_WIDTH_DEMAPVIT_RSVD		1
+#define STB0899_DEMAPVIT_KDIVIDER		(0x7f << 0)
+#define STB0899_OFFST_DEMAPVIT_KDIVIDER		0
+#define STB0899_WIDTH_DEMAPVIT_KDIVIDER		7
+
+#define STB0899_PLPARM				0xf58c
+#define STB0899_VITMAPPING			(0x07 << 5)
+#define STB0899_OFFST_VITMAPPING		5
+#define STB0899_WIDTH_VITMAPPING		3
+#define STB0899_VITMAPPING_BPSK			(0x01 << 5)
+#define STB0899_OFFST_VITMAPPING_BPSK		5
+#define STB0899_WIDTH_VITMAPPING_BPSK		1
+#define STB0899_VITMAPPING_QPSK			(0x00 << 5)
+#define STB0899_OFFST_VITMAPPING_QPSK		5
+#define STB0899_WIDTH_VITMAPPING_QPSK		0
+#define STB0899_VITCURPUN			(0x1f << 0)
+#define STB0899_OFFST_VITCURPUN			0
+#define STB0899_WIDTH_VITCURPUN			5
+#define STB0899_VITCURPUN_1_2			(0x0d << 0)
+#define STB0899_VITCURPUN_2_3			(0x12 << 0)
+#define STB0899_VITCURPUN_3_4			(0x15 << 0)
+#define STB0899_VITCURPUN_5_6			(0x18 << 0)
+#define STB0899_VITCURPUN_6_7			(0x19 << 0)
+#define STB0899_VITCURPUN_7_8			(0x1a << 0)
+
+/*	S2 DEMOD	*/
+#define STB0899_OFF0_DMD_STATUS			0xf300
+#define STB0899_BASE_DMD_STATUS			0x00000000
+#define STB0899_IF_AGC_LOCK			(0x01 << 8)
+#define STB0899_OFFST_IF_AGC_LOCK		0
+#define STB0899_WIDTH_IF_AGC_LOCK		1
+
+#define STB0899_OFF0_CRL_FREQ			0xf304
+#define STB0899_BASE_CRL_FREQ			0x00000000
+#define STB0899_CARR_FREQ			(0x3fffffff << 0)
+#define STB0899_OFFST_CARR_FREQ			0
+#define STB0899_WIDTH_CARR_FREQ			30
+
+#define STB0899_OFF0_BTR_FREQ			0xf308
+#define STB0899_BASE_BTR_FREQ			0x00000000
+#define STB0899_BTR_FREQ			(0xfffffff << 0)
+#define STB0899_OFFST_BTR_FREQ			0
+#define STB0899_WIDTH_BTR_FREQ			28
+
+#define STB0899_OFF0_IF_AGC_GAIN		0xf30c
+#define STB0899_BASE_IF_AGC_GAIN		0x00000000
+#define STB0899_IF_AGC_GAIN			(0x3fff < 0)
+#define STB0899_OFFST_IF_AGC_GAIN		0
+#define STB0899_WIDTH_IF_AGC_GAIN		14
+
+#define STB0899_OFF0_BB_AGC_GAIN		0xf310
+#define STB0899_BASE_BB_AGC_GAIN		0x00000000
+#define STB0899_BB_AGC_GAIN			(0x3fff < 0)
+#define STB0899_OFFST_BB_AGC_GAIN		0
+#define STB0899_WIDTH_BB_AGC_GAIN		14
+
+#define STB0899_OFF0_DC_OFFSET			0xf314
+#define STB0899_BASE_DC_OFFSET			0x00000000
+#define STB0899_I				(0xff < 8)
+#define STB0899_OFFST_I				8
+#define STB0899_WIDTH_I				8
+#define STB0899_Q				(0xff < 0)
+#define STB0899_OFFST_Q				8
+#define STB0899_WIDTH_Q				8
+
+#define STB0899_OFF0_DMD_CNTRL			0xf31c
+#define STB0899_BASE_DMD_CNTRL			0x00000000
+#define STB0899_ADC0_PINS1IN			(0x01 << 6)
+#define STB0899_OFFST_ADC0_PINS1IN              6
+#define STB0899_WIDTH_ADC0_PINS1IN              1
+#define STB0899_IN2COMP1_OFFBIN0		(0x01 << 3)
+#define STB0899_OFFST_IN2COMP1_OFFBIN0          3
+#define STB0899_WIDTH_IN2COMP1_OFFBIN0          1
+#define STB0899_DC_COMP				(0x01 << 2)
+#define STB0899_OFFST_DC_COMP			2
+#define STB0899_WIDTH_DC_COMP			1
+#define STB0899_MODMODE				(0x03 << 0)
+#define STB0899_OFFST_MODMODE			0
+#define STB0899_WIDTH_MODMODE			2
+
+#define STB0899_OFF0_IF_AGC_CNTRL		0xf320
+#define STB0899_BASE_IF_AGC_CNTRL		0x00000000
+#define STB0899_IF_GAIN_INIT			(0x3fff << 13)
+#define STB0899_OFFST_IF_GAIN_INIT		13
+#define STB0899_WIDTH_IF_GAIN_INIT		14
+#define STB0899_IF_GAIN_SENSE			(0x01 << 12)
+#define STB0899_OFFST_IF_GAIN_SENSE		12
+#define STB0899_WIDTH_IF_GAIN_SENSE		1
+#define STB0899_IF_LOOP_GAIN			(0x0f << 8)
+#define STB0899_OFFST_IF_LOOP_GAIN		8
+#define STB0899_WIDTH_IF_LOOP_GAIN		4
+#define STB0899_IF_LD_GAIN_INIT			(0x01 << 7)
+#define STB0899_OFFST_IF_LD_GAIN_INIT		7
+#define STB0899_WIDTH_IF_LD_GAIN_INIT		1
+#define STB0899_IF_AGC_REF			(0x7f << 0)
+#define STB0899_OFFST_IF_AGC_REF		0
+#define STB0899_WIDTH_IF_AGC_REF		7
+
+#define STB0899_OFF0_BB_AGC_CNTRL		0xf324
+#define STB0899_BASE_BB_AGC_CNTRL		0x00000000
+#define STB0899_BB_GAIN_INIT			(0x3fff << 12)
+#define STB0899_OFFST_BB_GAIN_INIT		12
+#define STB0899_WIDTH_BB_GAIN_INIT		14
+#define STB0899_BB_LOOP_GAIN			(0x0f << 8)
+#define STB0899_OFFST_BB_LOOP_GAIN		8
+#define STB0899_WIDTH_BB_LOOP_GAIN		4
+#define STB0899_BB_LD_GAIN_INIT			(0x01 << 7)
+#define STB0899_OFFST_BB_LD_GAIN_INIT		7
+#define STB0899_WIDTH_BB_LD_GAIN_INIT		1
+#define STB0899_BB_AGC_REF			(0x7f << 0)
+#define STB0899_OFFST_BB_AGC_REF		0
+#define STB0899_WIDTH_BB_AGC_REF		7
+
+#define STB0899_OFF0_CRL_CNTRL			0xf328
+#define STB0899_BASE_CRL_CNTRL			0x00000000
+#define STB0899_CRL_LOCK_CLEAR			(0x01 << 5)
+#define STB0899_OFFST_CRL_LOCK_CLEAR		5
+#define STB0899_WIDTH_CRL_LOCK_CLEAR		1
+#define STB0899_CRL_SWPR_CLEAR			(0x01 << 4)
+#define STB0899_OFFST_CRL_SWPR_CLEAR		4
+#define STB0899_WIDTH_CRL_SWPR_CLEAR		1
+#define STB0899_CRL_SWP_ENA			(0x01 << 3)
+#define STB0899_OFFST_CRL_SWP_ENA		3
+#define STB0899_WIDTH_CRL_SWP_ENA		1
+#define STB0899_CRL_DET_SEL			(0x01 << 2)
+#define STB0899_OFFST_CRL_DET_SEL		2
+#define STB0899_WIDTH_CRL_DET_SEL		1
+#define STB0899_CRL_SENSE			(0x01 << 1)
+#define STB0899_OFFST_CRL_SENSE			1
+#define STB0899_WIDTH_CRL_SENSE			1
+#define STB0899_CRL_PHSERR_CLEAR		(0x01 << 0)
+#define STB0899_OFFST_CRL_PHSERR_CLEAR		0
+#define STB0899_WIDTH_CRL_PHSERR_CLEAR		1
+
+#define STB0899_OFF0_CRL_PHS_INIT		0xf32c
+#define STB0899_BASE_CRL_PHS_INIT		0x00000000
+#define STB0899_CRL_PHS_INIT_31			(0x1 << 30)
+#define STB0899_OFFST_CRL_PHS_INIT_31		30
+#define STB0899_WIDTH_CRL_PHS_INIT_31		1
+#define STB0899_CRL_LD_INIT_PHASE		(0x1 << 24)
+#define STB0899_OFFST_CRL_LD_INIT_PHASE		24
+#define STB0899_WIDTH_CRL_LD_INIT_PHASE		1
+#define STB0899_CRL_INIT_PHASE			(0xffffff << 0)
+#define STB0899_OFFST_CRL_INIT_PHASE		0
+#define STB0899_WIDTH_CRL_INIT_PHASE		24
+
+#define STB0899_OFF0_CRL_FREQ_INIT		0xf330
+#define STB0899_BASE_CRL_FREQ_INIT		0x00000000
+#define STB0899_CRL_FREQ_INIT_31		(0x1 << 30)
+#define STB0899_OFFST_CRL_FREQ_INIT_31		30
+#define STB0899_WIDTH_CRL_FREQ_INIT_31		1
+#define STB0899_CRL_LD_FREQ_INIT		(0x1 << 24)
+#define STB0899_OFFST_CRL_LD_FREQ_INIT		24
+#define STB0899_WIDTH_CRL_LD_FREQ_INIT		1
+#define STB0899_CRL_FREQ_INIT			(0xffffff << 0)
+#define STB0899_OFFST_CRL_FREQ_INIT		0
+#define STB0899_WIDTH_CRL_FREQ_INIT		24
+
+#define STB0899_OFF0_CRL_LOOP_GAIN		0xf334
+#define STB0899_BASE_CRL_LOOP_GAIN		0x00000000
+#define STB0899_KCRL2_RSHFT			(0xf << 16)
+#define STB0899_OFFST_KCRL2_RSHFT		16
+#define STB0899_WIDTH_KCRL2_RSHFT		4
+#define STB0899_KCRL1				(0xf << 12)
+#define STB0899_OFFST_KCRL1			12
+#define STB0899_WIDTH_KCRL1			4
+#define STB0899_KCRL1_RSHFT			(0xf << 8)
+#define STB0899_OFFST_KCRL1_RSHFT		8
+#define STB0899_WIDTH_KCRL1_RSHFT		4
+#define STB0899_KCRL0				(0xf << 4)
+#define STB0899_OFFST_KCRL0			4
+#define STB0899_WIDTH_KCRL0			4
+#define STB0899_KCRL0_RSHFT			(0xf << 0)
+#define STB0899_OFFST_KCRL0_RSHFT		0
+#define STB0899_WIDTH_KCRL0_RSHFT		4
+
+#define STB0899_OFF0_CRL_NOM_FREQ		0xf338
+#define STB0899_BASE_CRL_NOM_FREQ		0x00000000
+#define STB0899_CRL_NOM_FREQ			(0x3fffffff << 0)
+#define STB0899_OFFST_CRL_NOM_FREQ		0
+#define STB0899_WIDTH_CRL_NOM_FREQ		30
+
+#define STB0899_OFF0_CRL_SWP_RATE		0xf33c
+#define STB0899_BASE_CRL_SWP_RATE		0x00000000
+#define STB0899_CRL_SWP_RATE			(0x3fffffff << 0)
+#define STB0899_OFFST_CRL_SWP_RATE		0
+#define STB0899_WIDTH_CRL_SWP_RATE		30
+
+#define STB0899_OFF0_CRL_MAX_SWP		0xf340
+#define STB0899_BASE_CRL_MAX_SWP		0x00000000
+#define STB0899_CRL_MAX_SWP			(0x3fffffff << 0)
+#define STB0899_OFFST_CRL_MAX_SWP		0
+#define STB0899_WIDTH_CRL_MAX_SWP		30
+
+#define STB0899_OFF0_CRL_LK_CNTRL		0xf344
+#define STB0899_BASE_CRL_LK_CNTRL		0x00000000
+
+#define STB0899_OFF0_DECIM_CNTRL		0xf348
+#define STB0899_BASE_DECIM_CNTRL		0x00000000
+#define STB0899_BAND_LIMIT_B			(0x01 << 5)
+#define STB0899_OFFST_BAND_LIMIT_B		5
+#define STB0899_WIDTH_BAND_LIMIT_B		1
+#define STB0899_WIN_SEL				(0x03 << 3)
+#define STB0899_OFFST_WIN_SEL			3
+#define STB0899_WIDTH_WIN_SEL			2
+#define STB0899_DECIM_RATE			(0x07 << 0)
+#define STB0899_OFFST_DECIM_RATE		0
+#define STB0899_WIDTH_DECIM_RATE		3
+
+#define STB0899_OFF0_BTR_CNTRL			0xf34c
+#define STB0899_BASE_BTR_CNTRL			0x00000000
+#define STB0899_BTR_FREQ_CORR			(0x7ff << 4)
+#define STB0899_OFFST_BTR_FREQ_CORR		4
+#define STB0899_WIDTH_BTR_FREQ_CORR		11
+#define STB0899_BTR_CLR_LOCK			(0x01 << 3)
+#define STB0899_OFFST_BTR_CLR_LOCK		3
+#define STB0899_WIDTH_BTR_CLR_LOCK		1
+#define STB0899_BTR_SENSE			(0x01 << 2)
+#define STB0899_OFFST_BTR_SENSE			2
+#define STB0899_WIDTH_BTR_SENSE			1
+#define STB0899_BTR_ERR_ENA			(0x01 << 1)
+#define STB0899_OFFST_BTR_ERR_ENA		1
+#define STB0899_WIDTH_BTR_ERR_ENA		1
+#define STB0899_INTRP_PHS_SENSE			(0x01 << 0)
+#define STB0899_OFFST_INTRP_PHS_SENSE		0
+#define STB0899_WIDTH_INTRP_PHS_SENSE		1
+
+#define STB0899_OFF0_BTR_LOOP_GAIN		0xf350
+#define STB0899_BASE_BTR_LOOP_GAIN		0x00000000
+#define STB0899_KBTR2_RSHFT			(0x0f << 16)
+#define STB0899_OFFST_KBTR2_RSHFT		16
+#define STB0899_WIDTH_KBTR2_RSHFT		4
+#define STB0899_KBTR1				(0x0f << 12)
+#define STB0899_OFFST_KBTR1			12
+#define STB0899_WIDTH_KBTR1			4
+#define STB0899_KBTR1_RSHFT			(0x0f << 8)
+#define STB0899_OFFST_KBTR1_RSHFT		8
+#define STB0899_WIDTH_KBTR1_RSHFT		4
+#define STB0899_KBTR0				(0x0f << 4)
+#define STB0899_OFFST_KBTR0			4
+#define STB0899_WIDTH_KBTR0			4
+#define STB0899_KBTR0_RSHFT			(0x0f << 0)
+#define STB0899_OFFST_KBTR0_RSHFT		0
+#define STB0899_WIDTH_KBTR0_RSHFT		4
+
+#define STB0899_OFF0_BTR_PHS_INIT		0xf354
+#define STB0899_BASE_BTR_PHS_INIT		0x00000000
+#define STB0899_BTR_LD_PHASE_INIT		(0x01 << 28)
+#define STB0899_OFFST_BTR_LD_PHASE_INIT		28
+#define STB0899_WIDTH_BTR_LD_PHASE_INIT		1
+#define STB0899_BTR_INIT_PHASE			(0xfffffff << 0)
+#define STB0899_OFFST_BTR_INIT_PHASE		0
+#define STB0899_WIDTH_BTR_INIT_PHASE		28
+
+#define STB0899_OFF0_BTR_FREQ_INIT		0xf358
+#define STB0899_BASE_BTR_FREQ_INIT		0x00000000
+#define STB0899_BTR_LD_FREQ_INIT		(1 << 28)
+#define STB0899_OFFST_BTR_LD_FREQ_INIT		28
+#define STB0899_WIDTH_BTR_LD_FREQ_INIT		1
+#define STB0899_BTR_FREQ_INIT			(0xfffffff << 0)
+#define STB0899_OFFST_BTR_FREQ_INIT		0
+#define STB0899_WIDTH_BTR_FREQ_INIT		28
+
+#define STB0899_OFF0_BTR_NOM_FREQ		0xf35c
+#define STB0899_BASE_BTR_NOM_FREQ		0x00000000
+#define STB0899_BTR_NOM_FREQ			(0xfffffff << 0)
+#define STB0899_OFFST_BTR_NOM_FREQ		0
+#define STB0899_WIDTH_BTR_NOM_FREQ		28
+
+#define STB0899_OFF0_BTR_LK_CNTRL		0xf360
+#define STB0899_BASE_BTR_LK_CNTRL		0x00000000
+#define STB0899_BTR_MIN_ENERGY			(0x0f << 24)
+#define STB0899_OFFST_BTR_MIN_ENERGY		24
+#define STB0899_WIDTH_BTR_MIN_ENERGY		4
+#define STB0899_BTR_LOCK_TH_LO			(0xff << 16)
+#define STB0899_OFFST_BTR_LOCK_TH_LO		16
+#define STB0899_WIDTH_BTR_LOCK_TH_LO		8
+#define STB0899_BTR_LOCK_TH_HI			(0xff << 8)
+#define STB0899_OFFST_BTR_LOCK_TH_HI		8
+#define STB0899_WIDTH_BTR_LOCK_TH_HI		8
+#define STB0899_BTR_LOCK_GAIN			(0x03 << 6)
+#define STB0899_OFFST_BTR_LOCK_GAIN		6
+#define STB0899_WIDTH_BTR_LOCK_GAIN		2
+#define STB0899_BTR_LOCK_LEAK			(0x3f << 0)
+#define STB0899_OFFST_BTR_LOCK_LEAK		0
+#define STB0899_WIDTH_BTR_LOCK_LEAK		6
+
+#define STB0899_OFF0_DECN_CNTRL			0xf364
+#define STB0899_BASE_DECN_CNTRL			0x00000000
+
+#define STB0899_OFF0_TP_CNTRL			0xf368
+#define STB0899_BASE_TP_CNTRL			0x00000000
+
+#define STB0899_OFF0_TP_BUF_STATUS		0xf36c
+#define STB0899_BASE_TP_BUF_STATUS		0x00000000
+#define STB0899_TP_BUFFER_FULL                  (1 << 0)
+
+#define STB0899_OFF0_DC_ESTIM			0xf37c
+#define STB0899_BASE_DC_ESTIM			0x0000
+#define STB0899_I_DC_ESTIMATE			(0xff << 8)
+#define STB0899_OFFST_I_DC_ESTIMATE		8
+#define STB0899_WIDTH_I_DC_ESTIMATE		8
+#define STB0899_Q_DC_ESTIMATE			(0xff << 0)
+#define STB0899_OFFST_Q_DC_ESTIMATE		0
+#define STB0899_WIDTH_Q_DC_ESTIMATE		8
+
+#define STB0899_OFF0_FLL_CNTRL			0xf310
+#define STB0899_BASE_FLL_CNTRL			0x00000020
+#define STB0899_CRL_FLL_ACC			(0x01 << 4)
+#define STB0899_OFFST_CRL_FLL_ACC		4
+#define STB0899_WIDTH_CRL_FLL_ACC		1
+#define STB0899_FLL_AVG_PERIOD			(0x0f << 0)
+#define STB0899_OFFST_FLL_AVG_PERIOD		0
+#define STB0899_WIDTH_FLL_AVG_PERIOD		4
+
+#define STB0899_OFF0_FLL_FREQ_WD		0xf314
+#define STB0899_BASE_FLL_FREQ_WD		0x00000020
+#define STB0899_FLL_FREQ_WD			(0xffffffff << 0)
+#define STB0899_OFFST_FLL_FREQ_WD		0
+#define STB0899_WIDTH_FLL_FREQ_WD		32
+
+#define STB0899_OFF0_ANTI_ALIAS_SEL		0xf358
+#define STB0899_BASE_ANTI_ALIAS_SEL		0x00000020
+#define STB0899_ANTI_ALIAS_SELB			(0x03 << 0)
+#define STB0899_OFFST_ANTI_ALIAS_SELB		0
+#define STB0899_WIDTH_ANTI_ALIAS_SELB		2
+
+#define STB0899_OFF0_RRC_ALPHA			0xf35c
+#define STB0899_BASE_RRC_ALPHA			0x00000020
+#define STB0899_RRC_ALPHA			(0x03 << 0)
+#define STB0899_OFFST_RRC_ALPHA			0
+#define STB0899_WIDTH_RRC_ALPHA			2
+
+#define STB0899_OFF0_DC_ADAPT_LSHFT		0xf360
+#define STB0899_BASE_DC_ADAPT_LSHFT		0x00000020
+#define STB0899_DC_ADAPT_LSHFT			(0x077 << 0)
+#define STB0899_OFFST_DC_ADAPT_LSHFT		0
+#define STB0899_WIDTH_DC_ADAPT_LSHFT		3
+
+#define STB0899_OFF0_IMB_OFFSET			0xf364
+#define STB0899_BASE_IMB_OFFSET			0x00000020
+#define STB0899_PHS_IMB_COMP			(0xff << 8)
+#define STB0899_OFFST_PHS_IMB_COMP		8
+#define STB0899_WIDTH_PHS_IMB_COMP		8
+#define STB0899_AMPL_IMB_COMP			(0xff << 0)
+#define STB0899_OFFST_AMPL_IMB_COMP		0
+#define STB0899_WIDTH_AMPL_IMB_COMP		8
+
+#define STB0899_OFF0_IMB_ESTIMATE		0xf368
+#define STB0899_BASE_IMB_ESTIMATE		0x00000020
+#define STB0899_PHS_IMB_ESTIMATE		(0xff << 8)
+#define STB0899_OFFST_PHS_IMB_ESTIMATE		8
+#define STB0899_WIDTH_PHS_IMB_ESTIMATE		8
+#define STB0899_AMPL_IMB_ESTIMATE		(0xff << 0)
+#define STB0899_OFFST_AMPL_IMB_ESTIMATE		0
+#define STB0899_WIDTH_AMPL_IMB_ESTIMATE		8
+
+#define STB0899_OFF0_IMB_CNTRL			0xf36c
+#define STB0899_BASE_IMB_CNTRL			0x00000020
+#define STB0899_PHS_ADAPT_LSHFT			(0x07 << 4)
+#define STB0899_OFFST_PHS_ADAPT_LSHFT		4
+#define STB0899_WIDTH_PHS_ADAPT_LSHFT		3
+#define STB0899_AMPL_ADAPT_LSHFT		(0x07 << 1)
+#define STB0899_OFFST_AMPL_ADAPT_LSHFT		1
+#define STB0899_WIDTH_AMPL_ADAPT_LSHFT		3
+#define STB0899_IMB_COMP			(0x01 << 0)
+#define STB0899_OFFST_IMB_COMP			0
+#define STB0899_WIDTH_IMB_COMP			1
+
+#define STB0899_OFF0_IF_AGC_CNTRL2		0xf374
+#define STB0899_BASE_IF_AGC_CNTRL2		0x00000020
+#define STB0899_IF_AGC_LOCK_TH			(0xff << 11)
+#define STB0899_OFFST_IF_AGC_LOCK_TH		11
+#define STB0899_WIDTH_IF_AGC_LOCK_TH		8
+#define STB0899_IF_AGC_SD_DIV			(0xff << 3)
+#define STB0899_OFFST_IF_AGC_SD_DIV		3
+#define STB0899_WIDTH_IF_AGC_SD_DIV		8
+#define STB0899_IF_AGC_DUMP_PER			(0x07 << 0)
+#define STB0899_OFFST_IF_AGC_DUMP_PER		0
+#define STB0899_WIDTH_IF_AGC_DUMP_PER		3
+
+#define STB0899_OFF0_DMD_CNTRL2			0xf378
+#define STB0899_BASE_DMD_CNTRL2			0x00000020
+#define STB0899_SPECTRUM_INVERT			(0x01 << 2)
+#define STB0899_OFFST_SPECTRUM_INVERT		2
+#define STB0899_WIDTH_SPECTRUM_INVERT		1
+#define STB0899_AGC_MODE			(0x01 << 1)
+#define STB0899_OFFST_AGC_MODE			1
+#define STB0899_WIDTH_AGC_MODE			1
+#define STB0899_CRL_FREQ_ADJ			(0x01 << 0)
+#define STB0899_OFFST_CRL_FREQ_ADJ		0
+#define STB0899_WIDTH_CRL_FREQ_ADJ		1
+
+#define STB0899_OFF0_TP_BUFFER			0xf300
+#define STB0899_BASE_TP_BUFFER			0x00000040
+#define STB0899_TP_BUFFER_IN			(0xffff << 0)
+#define STB0899_OFFST_TP_BUFFER_IN		0
+#define STB0899_WIDTH_TP_BUFFER_IN		16
+
+#define STB0899_OFF0_TP_BUFFER1			0xf304
+#define STB0899_BASE_TP_BUFFER1			0x00000040
+#define STB0899_OFF0_TP_BUFFER2			0xf308
+#define STB0899_BASE_TP_BUFFER2			0x00000040
+#define STB0899_OFF0_TP_BUFFER3			0xf30c
+#define STB0899_BASE_TP_BUFFER3			0x00000040
+#define STB0899_OFF0_TP_BUFFER4			0xf310
+#define STB0899_BASE_TP_BUFFER4			0x00000040
+#define STB0899_OFF0_TP_BUFFER5			0xf314
+#define STB0899_BASE_TP_BUFFER5			0x00000040
+#define STB0899_OFF0_TP_BUFFER6			0xf318
+#define STB0899_BASE_TP_BUFFER6			0x00000040
+#define STB0899_OFF0_TP_BUFFER7			0xf31c
+#define STB0899_BASE_TP_BUFFER7			0x00000040
+#define STB0899_OFF0_TP_BUFFER8			0xf320
+#define STB0899_BASE_TP_BUFFER8			0x00000040
+#define STB0899_OFF0_TP_BUFFER9			0xf324
+#define STB0899_BASE_TP_BUFFER9			0x00000040
+#define STB0899_OFF0_TP_BUFFER10		0xf328
+#define STB0899_BASE_TP_BUFFER10		0x00000040
+#define STB0899_OFF0_TP_BUFFER11		0xf32c
+#define STB0899_BASE_TP_BUFFER11		0x00000040
+#define STB0899_OFF0_TP_BUFFER12		0xf330
+#define STB0899_BASE_TP_BUFFER12		0x00000040
+#define STB0899_OFF0_TP_BUFFER13		0xf334
+#define STB0899_BASE_TP_BUFFER13		0x00000040
+#define STB0899_OFF0_TP_BUFFER14		0xf338
+#define STB0899_BASE_TP_BUFFER14		0x00000040
+#define STB0899_OFF0_TP_BUFFER15		0xf33c
+#define STB0899_BASE_TP_BUFFER15		0x00000040
+#define STB0899_OFF0_TP_BUFFER16		0xf340
+#define STB0899_BASE_TP_BUFFER16		0x00000040
+#define STB0899_OFF0_TP_BUFFER17		0xf344
+#define STB0899_BASE_TP_BUFFER17		0x00000040
+#define STB0899_OFF0_TP_BUFFER18		0xf348
+#define STB0899_BASE_TP_BUFFER18		0x00000040
+#define STB0899_OFF0_TP_BUFFER19		0xf34c
+#define STB0899_BASE_TP_BUFFER19		0x00000040
+#define STB0899_OFF0_TP_BUFFER20		0xf350
+#define STB0899_BASE_TP_BUFFER20		0x00000040
+#define STB0899_OFF0_TP_BUFFER21		0xf354
+#define STB0899_BASE_TP_BUFFER21		0x00000040
+#define STB0899_OFF0_TP_BUFFER22		0xf358
+#define STB0899_BASE_TP_BUFFER22		0x00000040
+#define STB0899_OFF0_TP_BUFFER23		0xf35c
+#define STB0899_BASE_TP_BUFFER23		0x00000040
+#define STB0899_OFF0_TP_BUFFER24		0xf360
+#define STB0899_BASE_TP_BUFFER24		0x00000040
+#define STB0899_OFF0_TP_BUFFER25		0xf364
+#define STB0899_BASE_TP_BUFFER25		0x00000040
+#define STB0899_OFF0_TP_BUFFER26		0xf368
+#define STB0899_BASE_TP_BUFFER26		0x00000040
+#define STB0899_OFF0_TP_BUFFER27		0xf36c
+#define STB0899_BASE_TP_BUFFER27		0x00000040
+#define STB0899_OFF0_TP_BUFFER28		0xf370
+#define STB0899_BASE_TP_BUFFER28		0x00000040
+#define STB0899_OFF0_TP_BUFFER29		0xf374
+#define STB0899_BASE_TP_BUFFER29		0x00000040
+#define STB0899_OFF0_TP_BUFFER30		0xf378
+#define STB0899_BASE_TP_BUFFER30		0x00000040
+#define STB0899_OFF0_TP_BUFFER31		0xf37c
+#define STB0899_BASE_TP_BUFFER31		0x00000040
+#define STB0899_OFF0_TP_BUFFER32		0xf300
+#define STB0899_BASE_TP_BUFFER32		0x00000060
+#define STB0899_OFF0_TP_BUFFER33		0xf304
+#define STB0899_BASE_TP_BUFFER33		0x00000060
+#define STB0899_OFF0_TP_BUFFER34		0xf308
+#define STB0899_BASE_TP_BUFFER34		0x00000060
+#define STB0899_OFF0_TP_BUFFER35		0xf30c
+#define STB0899_BASE_TP_BUFFER35		0x00000060
+#define STB0899_OFF0_TP_BUFFER36		0xf310
+#define STB0899_BASE_TP_BUFFER36		0x00000060
+#define STB0899_OFF0_TP_BUFFER37		0xf314
+#define STB0899_BASE_TP_BUFFER37		0x00000060
+#define STB0899_OFF0_TP_BUFFER38		0xf318
+#define STB0899_BASE_TP_BUFFER38		0x00000060
+#define STB0899_OFF0_TP_BUFFER39		0xf31c
+#define STB0899_BASE_TP_BUFFER39		0x00000060
+#define STB0899_OFF0_TP_BUFFER40		0xf320
+#define STB0899_BASE_TP_BUFFER40		0x00000060
+#define STB0899_OFF0_TP_BUFFER41		0xf324
+#define STB0899_BASE_TP_BUFFER41		0x00000060
+#define STB0899_OFF0_TP_BUFFER42		0xf328
+#define STB0899_BASE_TP_BUFFER42		0x00000060
+#define STB0899_OFF0_TP_BUFFER43		0xf32c
+#define STB0899_BASE_TP_BUFFER43		0x00000060
+#define STB0899_OFF0_TP_BUFFER44		0xf330
+#define STB0899_BASE_TP_BUFFER44		0x00000060
+#define STB0899_OFF0_TP_BUFFER45		0xf334
+#define STB0899_BASE_TP_BUFFER45		0x00000060
+#define STB0899_OFF0_TP_BUFFER46		0xf338
+#define STB0899_BASE_TP_BUFFER46		0x00000060
+#define STB0899_OFF0_TP_BUFFER47		0xf33c
+#define STB0899_BASE_TP_BUFFER47		0x00000060
+#define STB0899_OFF0_TP_BUFFER48		0xf340
+#define STB0899_BASE_TP_BUFFER48		0x00000060
+#define STB0899_OFF0_TP_BUFFER49		0xf344
+#define STB0899_BASE_TP_BUFFER49		0x00000060
+#define STB0899_OFF0_TP_BUFFER50		0xf348
+#define STB0899_BASE_TP_BUFFER50		0x00000060
+#define STB0899_OFF0_TP_BUFFER51		0xf34c
+#define STB0899_BASE_TP_BUFFER51		0x00000060
+#define STB0899_OFF0_TP_BUFFER52		0xf350
+#define STB0899_BASE_TP_BUFFER52		0x00000060
+#define STB0899_OFF0_TP_BUFFER53		0xf354
+#define STB0899_BASE_TP_BUFFER53		0x00000060
+#define STB0899_OFF0_TP_BUFFER54		0xf358
+#define STB0899_BASE_TP_BUFFER54		0x00000060
+#define STB0899_OFF0_TP_BUFFER55		0xf35c
+#define STB0899_BASE_TP_BUFFER55		0x00000060
+#define STB0899_OFF0_TP_BUFFER56		0xf360
+#define STB0899_BASE_TP_BUFFER56		0x00000060
+#define STB0899_OFF0_TP_BUFFER57		0xf364
+#define STB0899_BASE_TP_BUFFER57		0x00000060
+#define STB0899_OFF0_TP_BUFFER58		0xf368
+#define STB0899_BASE_TP_BUFFER58		0x00000060
+#define STB0899_OFF0_TP_BUFFER59		0xf36c
+#define STB0899_BASE_TP_BUFFER59		0x00000060
+#define STB0899_OFF0_TP_BUFFER60		0xf370
+#define STB0899_BASE_TP_BUFFER60		0x00000060
+#define STB0899_OFF0_TP_BUFFER61		0xf374
+#define STB0899_BASE_TP_BUFFER61		0x00000060
+#define STB0899_OFF0_TP_BUFFER62		0xf378
+#define STB0899_BASE_TP_BUFFER62		0x00000060
+#define STB0899_OFF0_TP_BUFFER63		0xf37c
+#define STB0899_BASE_TP_BUFFER63		0x00000060
+
+#define STB0899_OFF0_RESET_CNTRL		0xf300
+#define STB0899_BASE_RESET_CNTRL		0x00000400
+#define STB0899_DVBS2_RESET			(0x01 << 0)
+#define STB0899_OFFST_DVBS2_RESET		0
+#define STB0899_WIDTH_DVBS2_RESET		1
+
+#define STB0899_OFF0_ACM_ENABLE			0xf304
+#define STB0899_BASE_ACM_ENABLE			0x00000400
+#define STB0899_ACM_ENABLE			1
+
+#define STB0899_OFF0_DESCR_CNTRL		0xf30c
+#define STB0899_BASE_DESCR_CNTRL		0x00000400
+#define STB0899_OFFST_DESCR_CNTRL               0
+#define STB0899_WIDTH_DESCR_CNTRL               16
+
+#define STB0899_OFF0_UWP_CNTRL1			0xf320
+#define STB0899_BASE_UWP_CNTRL1			0x00000400
+#define STB0899_UWP_TH_SOF			(0x7fff << 11)
+#define STB0899_OFFST_UWP_TH_SOF		11
+#define STB0899_WIDTH_UWP_TH_SOF		15
+#define STB0899_UWP_ESN0_QUANT			(0xff << 3)
+#define STB0899_OFFST_UWP_ESN0_QUANT		3
+#define STB0899_WIDTH_UWP_ESN0_QUANT		8
+#define STB0899_UWP_ESN0_AVE			(0x03 << 1)
+#define STB0899_OFFST_UWP_ESN0_AVE		1
+#define STB0899_WIDTH_UWP_ESN0_AVE		2
+#define STB0899_UWP_START			(0x01 << 0)
+#define STB0899_OFFST_UWP_START			0
+#define STB0899_WIDTH_UWP_START			1
+
+#define STB0899_OFF0_UWP_CNTRL2			0xf324
+#define STB0899_BASE_UWP_CNTRL2			0x00000400
+#define STB0899_UWP_MISS_TH			(0xff << 16)
+#define STB0899_OFFST_UWP_MISS_TH		16
+#define STB0899_WIDTH_UWP_MISS_TH		8
+#define STB0899_FE_FINE_TRK			(0xff << 8)
+#define STB0899_OFFST_FE_FINE_TRK		8
+#define STB0899_WIDTH_FE_FINE_TRK		8
+#define STB0899_FE_COARSE_TRK			(0xff << 0)
+#define STB0899_OFFST_FE_COARSE_TRK		0
+#define STB0899_WIDTH_FE_COARSE_TRK		8
+
+#define STB0899_OFF0_UWP_STAT1			0xf328
+#define STB0899_BASE_UWP_STAT1			0x00000400
+#define STB0899_UWP_STATE			(0x03ff << 15)
+#define STB0899_OFFST_UWP_STATE			15
+#define STB0899_WIDTH_UWP_STATE			10
+#define STB0899_UW_MAX_PEAK			(0x7fff << 0)
+#define STB0899_OFFST_UW_MAX_PEAK		0
+#define STB0899_WIDTH_UW_MAX_PEAK		15
+
+#define STB0899_OFF0_UWP_STAT2			0xf32c
+#define STB0899_BASE_UWP_STAT2			0x00000400
+#define STB0899_ESNO_EST			(0x07ffff << 7)
+#define STB0899_OFFST_ESN0_EST			7
+#define STB0899_WIDTH_ESN0_EST			19
+#define STB0899_UWP_DECODE_MOD			(0x7f << 0)
+#define STB0899_OFFST_UWP_DECODE_MOD		0
+#define STB0899_WIDTH_UWP_DECODE_MOD		7
+
+#define STB0899_OFF0_DMD_CORE_ID		0xf334
+#define STB0899_BASE_DMD_CORE_ID		0x00000400
+#define STB0899_CORE_ID				(0xffffffff << 0)
+#define STB0899_OFFST_CORE_ID			0
+#define STB0899_WIDTH_CORE_ID			32
+
+#define STB0899_OFF0_DMD_VERSION_ID		0xf33c
+#define STB0899_BASE_DMD_VERSION_ID		0x00000400
+#define STB0899_VERSION_ID			(0xff << 0)
+#define STB0899_OFFST_VERSION_ID		0
+#define STB0899_WIDTH_VERSION_ID		8
+
+#define STB0899_OFF0_DMD_STAT2			0xf340
+#define STB0899_BASE_DMD_STAT2			0x00000400
+#define STB0899_CSM_LOCK			(0x01 << 1)
+#define STB0899_OFFST_CSM_LOCK			1
+#define STB0899_WIDTH_CSM_LOCK			1
+#define STB0899_UWP_LOCK			(0x01 << 0)
+#define STB0899_OFFST_UWP_LOCK			0
+#define STB0899_WIDTH_UWP_LOCK			1
+
+#define STB0899_OFF0_FREQ_ADJ_SCALE		0xf344
+#define STB0899_BASE_FREQ_ADJ_SCALE		0x00000400
+#define STB0899_FREQ_ADJ_SCALE			(0x0fff << 0)
+#define STB0899_OFFST_FREQ_ADJ_SCALE		0
+#define STB0899_WIDTH_FREQ_ADJ_SCALE		12
+
+#define STB0899_OFF0_UWP_CNTRL3			0xf34c
+#define STB0899_BASE_UWP_CNTRL3			0x00000400
+#define STB0899_UWP_TH_TRACK			(0x7fff << 15)
+#define STB0899_OFFST_UWP_TH_TRACK		15
+#define STB0899_WIDTH_UWP_TH_TRACK		15
+#define STB0899_UWP_TH_ACQ			(0x7fff << 0)
+#define STB0899_OFFST_UWP_TH_ACQ		0
+#define STB0899_WIDTH_UWP_TH_ACQ		15
+
+#define STB0899_OFF0_SYM_CLK_SEL		0xf350
+#define STB0899_BASE_SYM_CLK_SEL		0x00000400
+#define STB0899_SYM_CLK_SEL			(0x03 << 0)
+#define STB0899_OFFST_SYM_CLK_SEL		0
+#define STB0899_WIDTH_SYM_CLK_SEL		2
+
+#define STB0899_OFF0_SOF_SRCH_TO		0xf354
+#define STB0899_BASE_SOF_SRCH_TO		0x00000400
+#define STB0899_SOF_SEARCH_TIMEOUT		(0x3fffff << 0)
+#define STB0899_OFFST_SOF_SEARCH_TIMEOUT	0
+#define STB0899_WIDTH_SOF_SEARCH_TIMEOUT	22
+
+#define STB0899_OFF0_ACQ_CNTRL1			0xf358
+#define STB0899_BASE_ACQ_CNTRL1			0x00000400
+#define STB0899_FE_FINE_ACQ			(0xff << 8)
+#define STB0899_OFFST_FE_FINE_ACQ		8
+#define STB0899_WIDTH_FE_FINE_ACQ		8
+#define STB0899_FE_COARSE_ACQ			(0xff << 0)
+#define STB0899_OFFST_FE_COARSE_ACQ		0
+#define STB0899_WIDTH_FE_COARSE_ACQ		8
+
+#define STB0899_OFF0_ACQ_CNTRL2			0xf35c
+#define STB0899_BASE_ACQ_CNTRL2			0x00000400
+#define STB0899_ZIGZAG				(0x01 << 25)
+#define STB0899_OFFST_ZIGZAG			25
+#define STB0899_WIDTH_ZIGZAG			1
+#define STB0899_NUM_STEPS			(0xff << 17)
+#define STB0899_OFFST_NUM_STEPS			17
+#define STB0899_WIDTH_NUM_STEPS			8
+#define STB0899_FREQ_STEPSIZE			(0x1ffff << 0)
+#define STB0899_OFFST_FREQ_STEPSIZE		0
+#define STB0899_WIDTH_FREQ_STEPSIZE		17
+
+#define STB0899_OFF0_ACQ_CNTRL3			0xf360
+#define STB0899_BASE_ACQ_CNTRL3			0x00000400
+#define STB0899_THRESHOLD_SCL			(0x3f << 23)
+#define STB0899_OFFST_THRESHOLD_SCL		23
+#define STB0899_WIDTH_THRESHOLD_SCL		6
+#define STB0899_UWP_TH_SRCH			(0x7fff << 8)
+#define STB0899_OFFST_UWP_TH_SRCH		8
+#define STB0899_WIDTH_UWP_TH_SRCH		15
+#define STB0899_AUTO_REACQUIRE			(0x01 << 7)
+#define STB0899_OFFST_AUTO_REACQUIRE		7
+#define STB0899_WIDTH_AUTO_REACQUIRE		1
+#define STB0899_TRACK_LOCK_SEL			(0x01 << 6)
+#define STB0899_OFFST_TRACK_LOCK_SEL		6
+#define STB0899_WIDTH_TRACK_LOCK_SEL		1
+#define STB0899_ACQ_SEARCH_MODE			(0x03 << 4)
+#define STB0899_OFFST_ACQ_SEARCH_MODE		4
+#define STB0899_WIDTH_ACQ_SEARCH_MODE		2
+#define STB0899_CONFIRM_FRAMES			(0x0f << 0)
+#define STB0899_OFFST_CONFIRM_FRAMES		0
+#define STB0899_WIDTH_CONFIRM_FRAMES		4
+
+#define STB0899_OFF0_FE_SETTLE			0xf364
+#define STB0899_BASE_FE_SETTLE			0x00000400
+#define STB0899_SETTLING_TIME			(0x3fffff << 0)
+#define STB0899_OFFST_SETTLING_TIME		0
+#define STB0899_WIDTH_SETTLING_TIME		22
+
+#define STB0899_OFF0_AC_DWELL			0xf368
+#define STB0899_BASE_AC_DWELL			0x00000400
+#define STB0899_DWELL_TIME			(0x3fffff << 0)
+#define STB0899_OFFST_DWELL_TIME		0
+#define STB0899_WIDTH_DWELL_TIME		22
+
+#define STB0899_OFF0_ACQUIRE_TRIG		0xf36c
+#define STB0899_BASE_ACQUIRE_TRIG		0x00000400
+#define STB0899_ACQUIRE				(0x01 << 0)
+#define STB0899_OFFST_ACQUIRE			0
+#define STB0899_WIDTH_ACQUIRE			1
+
+#define STB0899_OFF0_LOCK_LOST			0xf370
+#define STB0899_BASE_LOCK_LOST			0x00000400
+#define STB0899_LOCK_LOST			(0x01 << 0)
+#define STB0899_OFFST_LOCK_LOST			0
+#define STB0899_WIDTH_LOCK_LOST			1
+
+#define STB0899_OFF0_ACQ_STAT1			0xf374
+#define STB0899_BASE_ACQ_STAT1			0x00000400
+#define STB0899_STEP_FREQ			(0x1fffff << 11)
+#define STB0899_OFFST_STEP_FREQ			11
+#define STB0899_WIDTH_STEP_FREQ			21
+#define STB0899_ACQ_STATE			(0x07 << 8)
+#define STB0899_OFFST_ACQ_STATE			8
+#define STB0899_WIDTH_ACQ_STATE			3
+#define STB0899_UW_DETECT_COUNT			(0xff << 0)
+#define STB0899_OFFST_UW_DETECT_COUNT		0
+#define STB0899_WIDTH_UW_DETECT_COUNT		8
+
+#define STB0899_OFF0_ACQ_TIMEOUT		0xf378
+#define STB0899_BASE_ACQ_TIMEOUT		0x00000400
+#define STB0899_ACQ_TIMEOUT			(0x3fffff << 0)
+#define STB0899_OFFST_ACQ_TIMEOUT		0
+#define STB0899_WIDTH_ACQ_TIMEOUT		22
+
+#define STB0899_OFF0_ACQ_TIME			0xf37c
+#define STB0899_BASE_ACQ_TIME			0x00000400
+#define STB0899_ACQ_TIME_SYM			(0xffffff << 0)
+#define STB0899_OFFST_ACQ_TIME_SYM		0
+#define STB0899_WIDTH_ACQ_TIME_SYM		24
+
+#define STB0899_OFF0_FINAL_AGC_CNTRL		0xf308
+#define STB0899_BASE_FINAL_AGC_CNTRL		0x00000440
+#define STB0899_FINAL_GAIN_INIT			(0x3fff << 12)
+#define STB0899_OFFST_FINAL_GAIN_INIT		12
+#define STB0899_WIDTH_FINAL_GAIN_INIT		14
+#define STB0899_FINAL_LOOP_GAIN			(0x0f << 8)
+#define STB0899_OFFST_FINAL_LOOP_GAIN		8
+#define STB0899_WIDTH_FINAL_LOOP_GAIN		4
+#define STB0899_FINAL_LD_GAIN_INIT		(0x01 << 7)
+#define STB0899_OFFST_FINAL_LD_GAIN_INIT	7
+#define STB0899_WIDTH_FINAL_LD_GAIN_INIT	1
+#define STB0899_FINAL_AGC_REF			(0x7f << 0)
+#define STB0899_OFFST_FINAL_AGC_REF		0
+#define STB0899_WIDTH_FINAL_AGC_REF		7
+
+#define STB0899_OFF0_FINAL_AGC_GAIN		0xf30c
+#define STB0899_BASE_FINAL_AGC_GAIN		0x00000440
+#define STB0899_FINAL_AGC_GAIN			(0x3fff << 0)
+#define STB0899_OFFST_FINAL_AGC_GAIN		0
+#define STB0899_WIDTH_FINAL_AGC_GAIN		14
+
+#define STB0899_OFF0_EQUALIZER_INIT		0xf310
+#define STB0899_BASE_EQUALIZER_INIT		0x00000440
+#define STB0899_EQ_SRST				(0x01 << 1)
+#define STB0899_OFFST_EQ_SRST			1
+#define STB0899_WIDTH_EQ_SRST			1
+#define STB0899_EQ_INIT				(0x01 << 0)
+#define STB0899_OFFST_EQ_INIT			0
+#define STB0899_WIDTH_EQ_INIT			1
+
+#define STB0899_OFF0_EQ_CNTRL			0xf314
+#define STB0899_BASE_EQ_CNTRL			0x00000440
+#define STB0899_EQ_ADAPT_MODE			(0x01 << 18)
+#define STB0899_OFFST_EQ_ADAPT_MODE		18
+#define STB0899_WIDTH_EQ_ADAPT_MODE		1
+#define STB0899_EQ_DELAY			(0x0f << 14)
+#define STB0899_OFFST_EQ_DELAY			14
+#define STB0899_WIDTH_EQ_DELAY			4
+#define STB0899_EQ_QUANT_LEVEL			(0xff << 6)
+#define STB0899_OFFST_EQ_QUANT_LEVEL		6
+#define STB0899_WIDTH_EQ_QUANT_LEVEL		8
+#define STB0899_EQ_DISABLE_UPDATE		(0x01 << 5)
+#define STB0899_OFFST_EQ_DISABLE_UPDATE		5
+#define STB0899_WIDTH_EQ_DISABLE_UPDATE		1
+#define STB0899_EQ_BYPASS			(0x01 << 4)
+#define STB0899_OFFST_EQ_BYPASS			4
+#define STB0899_WIDTH_EQ_BYPASS			1
+#define STB0899_EQ_SHIFT			(0x0f << 0)
+#define STB0899_OFFST_EQ_SHIFT			0
+#define STB0899_WIDTH_EQ_SHIFT			4
+
+#define STB0899_OFF0_EQ_I_INIT_COEFF_0		0xf320
+#define STB0899_OFF1_EQ_I_INIT_COEFF_1		0xf324
+#define STB0899_OFF2_EQ_I_INIT_COEFF_2		0xf328
+#define STB0899_OFF3_EQ_I_INIT_COEFF_3		0xf32c
+#define STB0899_OFF4_EQ_I_INIT_COEFF_4		0xf330
+#define STB0899_OFF5_EQ_I_INIT_COEFF_5		0xf334
+#define STB0899_OFF6_EQ_I_INIT_COEFF_6		0xf338
+#define STB0899_OFF7_EQ_I_INIT_COEFF_7		0xf33c
+#define STB0899_OFF8_EQ_I_INIT_COEFF_8		0xf340
+#define STB0899_OFF9_EQ_I_INIT_COEFF_9		0xf344
+#define STB0899_OFFa_EQ_I_INIT_COEFF_10		0xf348
+#define STB0899_BASE_EQ_I_INIT_COEFF_N		0x00000440
+#define STB0899_EQ_I_INIT_COEFF_N		(0x0fff << 0)
+#define STB0899_OFFST_EQ_I_INIT_COEFF_N		0
+#define STB0899_WIDTH_EQ_I_INIT_COEFF_N		12
+
+#define STB0899_OFF0_EQ_Q_INIT_COEFF_0		0xf350
+#define STB0899_OFF1_EQ_Q_INIT_COEFF_1		0xf354
+#define STB0899_OFF2_EQ_Q_INIT_COEFF_2		0xf358
+#define STB0899_OFF3_EQ_Q_INIT_COEFF_3		0xf35c
+#define STB0899_OFF4_EQ_Q_INIT_COEFF_4		0xf360
+#define STB0899_OFF5_EQ_Q_INIT_COEFF_5		0xf364
+#define STB0899_OFF6_EQ_Q_INIT_COEFF_6		0xf368
+#define STB0899_OFF7_EQ_Q_INIT_COEFF_7		0xf36c
+#define STB0899_OFF8_EQ_Q_INIT_COEFF_8		0xf370
+#define STB0899_OFF9_EQ_Q_INIT_COEFF_9		0xf374
+#define STB0899_OFFa_EQ_Q_INIT_COEFF_10		0xf378
+#define STB0899_BASE_EQ_Q_INIT_COEFF_N		0x00000440
+#define STB0899_EQ_Q_INIT_COEFF_N		(0x0fff << 0)
+#define STB0899_OFFST_EQ_Q_INIT_COEFF_N		0
+#define STB0899_WIDTH_EQ_Q_INIT_COEFF_N		12
+
+#define STB0899_OFF0_EQ_I_OUT_COEFF_0		0xf300
+#define STB0899_OFF1_EQ_I_OUT_COEFF_1		0xf304
+#define STB0899_OFF2_EQ_I_OUT_COEFF_2		0xf308
+#define STB0899_OFF3_EQ_I_OUT_COEFF_3		0xf30c
+#define STB0899_OFF4_EQ_I_OUT_COEFF_4		0xf310
+#define STB0899_OFF5_EQ_I_OUT_COEFF_5		0xf314
+#define STB0899_OFF6_EQ_I_OUT_COEFF_6		0xf318
+#define STB0899_OFF7_EQ_I_OUT_COEFF_7		0xf31c
+#define STB0899_OFF8_EQ_I_OUT_COEFF_8		0xf320
+#define STB0899_OFF9_EQ_I_OUT_COEFF_9		0xf324
+#define STB0899_OFFa_EQ_I_OUT_COEFF_10		0xf328
+#define STB0899_BASE_EQ_I_OUT_COEFF_N		0x00000460
+#define STB0899_EQ_I_OUT_COEFF_N		(0x0fff << 0)
+#define STB0899_OFFST_EQ_I_OUT_COEFF_N		0
+#define STB0899_WIDTH_EQ_I_OUT_COEFF_N		12
+
+#define STB0899_OFF0_EQ_Q_OUT_COEFF_0		0xf330
+#define STB0899_OFF1_EQ_Q_OUT_COEFF_1		0xf334
+#define STB0899_OFF2_EQ_Q_OUT_COEFF_2		0xf338
+#define STB0899_OFF3_EQ_Q_OUT_COEFF_3		0xf33c
+#define STB0899_OFF4_EQ_Q_OUT_COEFF_4		0xf340
+#define STB0899_OFF5_EQ_Q_OUT_COEFF_5		0xf344
+#define STB0899_OFF6_EQ_Q_OUT_COEFF_6		0xf348
+#define STB0899_OFF7_EQ_Q_OUT_COEFF_7		0xf34c
+#define STB0899_OFF8_EQ_Q_OUT_COEFF_8		0xf350
+#define STB0899_OFF9_EQ_Q_OUT_COEFF_9		0xf354
+#define STB0899_OFFa_EQ_Q_OUT_COEFF_10		0xf358
+#define STB0899_BASE_EQ_Q_OUT_COEFF_N		0x00000460
+#define STB0899_EQ_Q_OUT_COEFF_N		(0x0fff << 0)
+#define STB0899_OFFST_EQ_Q_OUT_COEFF_N		0
+#define STB0899_WIDTH_EQ_Q_OUT_COEFF_N		12
+
+/*	S2 FEC	*/
+#define STB0899_OFF0_BLOCK_LNGTH		0xfa04
+#define STB0899_BASE_BLOCK_LNGTH		0x00000000
+#define STB0899_BLOCK_LENGTH			(0xff << 0)
+#define STB0899_OFFST_BLOCK_LENGTH		0
+#define STB0899_WIDTH_BLOCK_LENGTH		8
+
+#define STB0899_OFF0_ROW_STR			0xfa08
+#define STB0899_BASE_ROW_STR			0x00000000
+#define STB0899_ROW_STRIDE			(0xff << 0)
+#define STB0899_OFFST_ROW_STRIDE		0
+#define STB0899_WIDTH_ROW_STRIDE		8
+
+#define STB0899_OFF0_MAX_ITER			0xfa0c
+#define STB0899_BASE_MAX_ITER			0x00000000
+#define STB0899_MAX_ITERATIONS			(0xff << 0)
+#define STB0899_OFFST_MAX_ITERATIONS		0
+#define STB0899_WIDTH_MAX_ITERATIONS		8
+
+#define STB0899_OFF0_BN_END_ADDR		0xfa10
+#define STB0899_BASE_BN_END_ADDR		0x00000000
+#define STB0899_BN_END_ADDR			(0x0fff << 0)
+#define STB0899_OFFST_BN_END_ADDR		0
+#define STB0899_WIDTH_BN_END_ADDR		12
+
+#define STB0899_OFF0_CN_END_ADDR		0xfa14
+#define STB0899_BASE_CN_END_ADDR		0x00000000
+#define STB0899_CN_END_ADDR			(0x0fff << 0)
+#define STB0899_OFFST_CN_END_ADDR		0
+#define STB0899_WIDTH_CN_END_ADDR		12
+
+#define STB0899_OFF0_INFO_LENGTH		0xfa1c
+#define STB0899_BASE_INFO_LENGTH		0x00000000
+#define STB0899_INFO_LENGTH			(0xff << 0)
+#define STB0899_OFFST_INFO_LENGTH		0
+#define STB0899_WIDTH_INFO_LENGTH		8
+
+#define STB0899_OFF0_BOT_ADDR			0xfa20
+#define STB0899_BASE_BOT_ADDR			0x00000000
+#define STB0899_BOTTOM_BASE_ADDR		(0x03ff << 0)
+#define STB0899_OFFST_BOTTOM_BASE_ADDR		0
+#define STB0899_WIDTH_BOTTOM_BASE_ADDR		10
+
+#define STB0899_OFF0_BCH_BLK_LN			0xfa24
+#define STB0899_BASE_BCH_BLK_LN			0x00000000
+#define STB0899_BCH_BLOCK_LENGTH		(0xffff << 0)
+#define STB0899_OFFST_BCH_BLOCK_LENGTH		0
+#define STB0899_WIDTH_BCH_BLOCK_LENGTH		16
+
+#define STB0899_OFF0_BCH_T			0xfa28
+#define STB0899_BASE_BCH_T			0x00000000
+#define STB0899_BCH_T				(0x0f << 0)
+#define STB0899_OFFST_BCH_T			0
+#define STB0899_WIDTH_BCH_T			4
+
+#define STB0899_OFF0_CNFG_MODE			0xfa00
+#define STB0899_BASE_CNFG_MODE			0x00000800
+#define STB0899_MODCOD				(0x1f << 2)
+#define STB0899_OFFST_MODCOD			2
+#define STB0899_WIDTH_MODCOD			5
+#define STB0899_MODCOD_SEL			(0x01 << 1)
+#define STB0899_OFFST_MODCOD_SEL		1
+#define STB0899_WIDTH_MODCOD_SEL		1
+#define STB0899_CONFIG_MODE			(0x01 << 0)
+#define STB0899_OFFST_CONFIG_MODE		0
+#define STB0899_WIDTH_CONFIG_MODE		1
+
+#define STB0899_OFF0_LDPC_STAT			0xfa04
+#define STB0899_BASE_LDPC_STAT			0x00000800
+#define STB0899_ITERATION			(0xff << 3)
+#define STB0899_OFFST_ITERATION			3
+#define STB0899_WIDTH_ITERATION			8
+#define STB0899_LDPC_DEC_STATE			(0x07 << 0)
+#define STB0899_OFFST_LDPC_DEC_STATE		0
+#define STB0899_WIDTH_LDPC_DEC_STATE		3
+
+#define STB0899_OFF0_ITER_SCALE			0xfa08
+#define STB0899_BASE_ITER_SCALE			0x00000800
+#define STB0899_ITERATION_SCALE			(0xff << 0)
+#define STB0899_OFFST_ITERATION_SCALE		0
+#define STB0899_WIDTH_ITERATION_SCALE		8
+
+#define STB0899_OFF0_INPUT_MODE			0xfa0c
+#define STB0899_BASE_INPUT_MODE			0x00000800
+#define STB0899_SD_BLOCK1_STREAM0		(0x01 << 0)
+#define STB0899_OFFST_SD_BLOCK1_STREAM0		0
+#define STB0899_WIDTH_SD_BLOCK1_STREAM0		1
+
+#define STB0899_OFF0_LDPCDECRST			0xfa10
+#define STB0899_BASE_LDPCDECRST			0x00000800
+#define STB0899_LDPC_DEC_RST			(0x01 << 0)
+#define STB0899_OFFST_LDPC_DEC_RST		0
+#define STB0899_WIDTH_LDPC_DEC_RST		1
+
+#define STB0899_OFF0_CLK_PER_BYTE_RW		0xfa14
+#define STB0899_BASE_CLK_PER_BYTE_RW		0x00000800
+#define STB0899_CLKS_PER_BYTE			(0x0f << 0)
+#define STB0899_OFFST_CLKS_PER_BYTE		0
+#define STB0899_WIDTH_CLKS_PER_BYTE		5
+
+#define STB0899_OFF0_BCH_ERRORS			0xfa18
+#define STB0899_BASE_BCH_ERRORS			0x00000800
+#define STB0899_BCH_ERRORS			(0x0f << 0)
+#define STB0899_OFFST_BCH_ERRORS		0
+#define STB0899_WIDTH_BCH_ERRORS		4
+
+#define STB0899_OFF0_LDPC_ERRORS		0xfa1c
+#define STB0899_BASE_LDPC_ERRORS		0x00000800
+#define STB0899_LDPC_ERRORS			(0xffff << 0)
+#define STB0899_OFFST_LDPC_ERRORS		0
+#define STB0899_WIDTH_LDPC_ERRORS		16
+
+#define STB0899_OFF0_BCH_MODE			0xfa20
+#define STB0899_BASE_BCH_MODE			0x00000800
+#define STB0899_BCH_CORRECT_N			(0x01 << 1)
+#define STB0899_OFFST_BCH_CORRECT_N		1
+#define STB0899_WIDTH_BCH_CORRECT_N		1
+#define STB0899_FULL_BYPASS			(0x01 << 0)
+#define STB0899_OFFST_FULL_BYPASS		0
+#define STB0899_WIDTH_FULL_BYPASS		1
+
+#define STB0899_OFF0_ERR_ACC_PER		0xfa24
+#define STB0899_BASE_ERR_ACC_PER		0x00000800
+#define STB0899_BCH_ERR_ACC_PERIOD		(0x0f << 0)
+#define STB0899_OFFST_BCH_ERR_ACC_PERIOD	0
+#define STB0899_WIDTH_BCH_ERR_ACC_PERIOD	4
+
+#define STB0899_OFF0_BCH_ERR_ACC		0xfa28
+#define STB0899_BASE_BCH_ERR_ACC		0x00000800
+#define STB0899_BCH_ERR_ACCUM			(0xff << 0)
+#define STB0899_OFFST_BCH_ERR_ACCUM		0
+#define STB0899_WIDTH_BCH_ERR_ACCUM		8
+
+#define STB0899_OFF0_FEC_CORE_ID_REG		0xfa2c
+#define STB0899_BASE_FEC_CORE_ID_REG		0x00000800
+#define STB0899_FEC_CORE_ID			(0xffffffff << 0)
+#define STB0899_OFFST_FEC_CORE_ID		0
+#define STB0899_WIDTH_FEC_CORE_ID		32
+
+#define STB0899_OFF0_FEC_VER_ID_REG		0xfa34
+#define STB0899_BASE_FEC_VER_ID_REG		0x00000800
+#define STB0899_FEC_VER_ID			(0xff << 0)
+#define STB0899_OFFST_FEC_VER_ID		0
+#define STB0899_WIDTH_FEC_VER_ID		8
+
+#define STB0899_OFF0_FEC_TP_SEL			0xfa38
+#define STB0899_BASE_FEC_TP_SEL			0x00000800
+
+#define STB0899_OFF0_CSM_CNTRL1			0xf310
+#define STB0899_BASE_CSM_CNTRL1			0x00000400
+#define STB0899_CSM_FORCE_FREQLOCK		(0x01 << 19)
+#define STB0899_OFFST_CSM_FORCE_FREQLOCK	19
+#define STB0899_WIDTH_CSM_FORCE_FREQLOCK	1
+#define STB0899_CSM_FREQ_LOCKSTATE		(0x01 << 18)
+#define STB0899_OFFST_CSM_FREQ_LOCKSTATE	18
+#define STB0899_WIDTH_CSM_FREQ_LOCKSTATE	1
+#define STB0899_CSM_AUTO_PARAM			(0x01 << 17)
+#define STB0899_OFFST_CSM_AUTO_PARAM		17
+#define STB0899_WIDTH_CSM_AUTO_PARAM		1
+#define STB0899_FE_LOOP_SHIFT			(0x07 << 14)
+#define STB0899_OFFST_FE_LOOP_SHIFT		14
+#define STB0899_WIDTH_FE_LOOP_SHIFT		3
+#define STB0899_CSM_AGC_SHIFT			(0x07 << 11)
+#define STB0899_OFFST_CSM_AGC_SHIFT		11
+#define STB0899_WIDTH_CSM_AGC_SHIFT		3
+#define STB0899_CSM_AGC_GAIN			(0x1ff << 2)
+#define STB0899_OFFST_CSM_AGC_GAIN		2
+#define STB0899_WIDTH_CSM_AGC_GAIN		9
+#define STB0899_CSM_TWO_PASS			(0x01 << 1)
+#define STB0899_OFFST_CSM_TWO_PASS		1
+#define STB0899_WIDTH_CSM_TWO_PASS		1
+#define STB0899_CSM_DVT_TABLE			(0x01 << 0)
+#define STB0899_OFFST_CSM_DVT_TABLE		0
+#define STB0899_WIDTH_CSM_DVT_TABLE		1
+
+#define STB0899_OFF0_CSM_CNTRL2			0xf314
+#define STB0899_BASE_CSM_CNTRL2			0x00000400
+#define STB0899_CSM_GAMMA_RHO_ACQ		(0x1ff << 9)
+#define STB0899_OFFST_CSM_GAMMA_RHOACQ		9
+#define STB0899_WIDTH_CSM_GAMMA_RHOACQ		9
+#define STB0899_CSM_GAMMA_ACQ			(0x1ff << 0)
+#define STB0899_OFFST_CSM_GAMMA_ACQ		0
+#define STB0899_WIDTH_CSM_GAMMA_ACQ		9
+
+#define STB0899_OFF0_CSM_CNTRL3			0xf318
+#define STB0899_BASE_CSM_CNTRL3			0x00000400
+#define STB0899_CSM_GAMMA_RHO_TRACK		(0x1ff << 9)
+#define STB0899_OFFST_CSM_GAMMA_RHOTRACK	9
+#define STB0899_WIDTH_CSM_GAMMA_RHOTRACK	9
+#define STB0899_CSM_GAMMA_TRACK			(0x1ff << 0)
+#define STB0899_OFFST_CSM_GAMMA_TRACK		0
+#define STB0899_WIDTH_CSM_GAMMA_TRACK		9
+
+#define STB0899_OFF0_CSM_CNTRL4			0xf31c
+#define STB0899_BASE_CSM_CNTRL4			0x00000400
+#define STB0899_CSM_PHASEDIFF_THRESH		(0x0f << 8)
+#define STB0899_OFFST_CSM_PHASEDIFF_THRESH	8
+#define STB0899_WIDTH_CSM_PHASEDIFF_THRESH	4
+#define STB0899_CSM_LOCKCOUNT_THRESH		(0xff << 0)
+#define STB0899_OFFST_CSM_LOCKCOUNT_THRESH	0
+#define STB0899_WIDTH_CSM_LOCKCOUNT_THRESH	8
+
+/*	Check on chapter 8 page 42	*/
+#define STB0899_ERRCTRL1			0xf574
+#define STB0899_ERRCTRL2			0xf575
+#define STB0899_ERRCTRL3			0xf576
+#define STB0899_ERR_SRC_S1			(0x1f << 3)
+#define STB0899_OFFST_ERR_SRC_S1		3
+#define STB0899_WIDTH_ERR_SRC_S1		5
+#define STB0899_ERR_SRC_S2			(0x0f << 0)
+#define STB0899_OFFST_ERR_SRC_S2		0
+#define STB0899_WIDTH_ERR_SRC_S2		4
+#define STB0899_NOE				(0x07 << 0)
+#define STB0899_OFFST_NOE			0
+#define STB0899_WIDTH_NOE			3
+
+#define STB0899_ECNT1M				0xf524
+#define STB0899_ECNT1L				0xf525
+#define STB0899_ECNT2M				0xf526
+#define STB0899_ECNT2L				0xf527
+#define STB0899_ECNT3M				0xf528
+#define STB0899_ECNT3L				0xf529
+
+#define STB0899_DMONMSK1			0xf57b
+#define STB0899_DMONMSK1_WAIT_1STEP		(1 << 7)
+#define STB0899_DMONMSK1_FREE_14		(1 << 6)
+#define STB0899_DMONMSK1_AVRGVIT_CALC		(1 << 5)
+#define STB0899_DMONMSK1_FREE_12		(1 << 4)
+#define STB0899_DMONMSK1_FREE_11		(1 << 3)
+#define STB0899_DMONMSK1_B0DIV_CALC		(1 << 2)
+#define STB0899_DMONMSK1_KDIVB1_CALC		(1 << 1)
+#define STB0899_DMONMSK1_KDIVB2_CALC		(1 << 0)
+
+#define STB0899_DMONMSK0			0xf57c
+#define STB0899_DMONMSK0_SMOTTH_CALC		(1 << 7)
+#define STB0899_DMONMSK0_FREE_6			(1 << 6)
+#define STB0899_DMONMSK0_SIGPOWER_CALC		(1 << 5)
+#define STB0899_DMONMSK0_QSEUIL_CALC		(1 << 4)
+#define STB0899_DMONMSK0_FREE_3			(1 << 3)
+#define STB0899_DMONMSK0_FREE_2			(1 << 2)
+#define STB0899_DMONMSK0_KVDIVB1_CALC		(1 << 1)
+#define STB0899_DMONMSK0_KVDIVB2_CALC		(1 << 0)
+
+#define STB0899_TSULC				0xf549
+#define STB0899_ULNOSYNCBYTES			(0x01 << 7)
+#define STB0899_OFFST_ULNOSYNCBYTES		7
+#define STB0899_WIDTH_ULNOSYNCBYTES		1
+#define STB0899_ULPARITY_ON			(0x01 << 6)
+#define STB0899_OFFST_ULPARITY_ON		6
+#define STB0899_WIDTH_ULPARITY_ON		1
+#define STB0899_ULSYNCOUTRS			(0x01 << 5)
+#define STB0899_OFFST_ULSYNCOUTRS		5
+#define STB0899_WIDTH_ULSYNCOUTRS		1
+#define STB0899_ULDSS_PACKETS			(0x01 << 0)
+#define STB0899_OFFST_ULDSS_PACKETS		0
+#define STB0899_WIDTH_ULDSS_PACKETS		1
+
+#define STB0899_TSLPL				0xf54b
+#define STB0899_LLDVBS2_MODE			(0x01 << 4)
+#define STB0899_OFFST_LLDVBS2_MODE		4
+#define STB0899_WIDTH_LLDVBS2_MODE		1
+#define STB0899_LLISSYI_ON			(0x01 << 3)
+#define STB0899_OFFST_LLISSYI_ON		3
+#define STB0899_WIDTH_LLISSYI_ON		1
+#define STB0899_LLNPD_ON			(0x01 << 2)
+#define STB0899_OFFST_LLNPD_ON			2
+#define STB0899_WIDTH_LLNPD_ON			1
+#define STB0899_LLCRC8_ON			(0x01 << 1)
+#define STB0899_OFFST_LLCRC8_ON			1
+#define STB0899_WIDTH_LLCRC8_ON			1
+
+#define STB0899_TSCFGH				0xf54c
+#define STB0899_OUTRS_PS			(0x01 << 6)
+#define STB0899_OFFST_OUTRS_PS			6
+#define STB0899_WIDTH_OUTRS_PS			1
+#define STB0899_SYNCBYTE			(0x01 << 5)
+#define STB0899_OFFST_SYNCBYTE			5
+#define STB0899_WIDTH_SYNCBYTE			1
+#define STB0899_PFBIT				(0x01 << 4)
+#define STB0899_OFFST_PFBIT			4
+#define STB0899_WIDTH_PFBIT			1
+#define STB0899_ERR_BIT				(0x01 << 3)
+#define STB0899_OFFST_ERR_BIT			3
+#define STB0899_WIDTH_ERR_BIT			1
+#define STB0899_MPEG				(0x01 << 2)
+#define STB0899_OFFST_MPEG			2
+#define STB0899_WIDTH_MPEG			1
+#define STB0899_CLK_POL				(0x01 << 1)
+#define STB0899_OFFST_CLK_POL			1
+#define STB0899_WIDTH_CLK_POL			1
+#define STB0899_FORCE0				(0x01 << 0)
+#define STB0899_OFFST_FORCE0			0
+#define STB0899_WIDTH_FORCE0			1
+
+#define STB0899_TSCFGM				0xf54d
+#define STB0899_LLPRIORITY			(0x01 << 3)
+#define STB0899_OFFST_LLPRIORIY			3
+#define STB0899_WIDTH_LLPRIORITY		1
+#define STB0899_EN188				(0x01 << 2)
+#define STB0899_OFFST_EN188			2
+#define STB0899_WIDTH_EN188			1
+
+#define STB0899_TSCFGL				0xf54e
+#define STB0899_DEL_ERRPCK			(0x01 << 7)
+#define STB0899_OFFST_DEL_ERRPCK		7
+#define STB0899_WIDTH_DEL_ERRPCK		1
+#define STB0899_ERRFLAGSTD			(0x01 << 5)
+#define STB0899_OFFST_ERRFLAGSTD		5
+#define STB0899_WIDTH_ERRFLAGSTD		1
+#define STB0899_MPEGERR				(0x01 << 4)
+#define STB0899_OFFST_MPEGERR			4
+#define STB0899_WIDTH_MPEGERR			1
+#define STB0899_BCH_CHK				(0x01 << 3)
+#define STB0899_OFFST_BCH_CHK			5
+#define STB0899_WIDTH_BCH_CHK			1
+#define STB0899_CRC8CHK				(0x01 << 2)
+#define STB0899_OFFST_CRC8CHK			2
+#define STB0899_WIDTH_CRC8CHK			1
+#define STB0899_SPEC_INFO			(0x01 << 1)
+#define STB0899_OFFST_SPEC_INFO			1
+#define STB0899_WIDTH_SPEC_INFO			1
+#define STB0899_LOW_PRIO_CLK			(0x01 << 0)
+#define STB0899_OFFST_LOW_PRIO_CLK		0
+#define STB0899_WIDTH_LOW_PRIO_CLK		1
+#define STB0899_ERROR_NORM			(0x00 << 0)
+#define STB0899_OFFST_ERROR_NORM		0
+#define STB0899_WIDTH_ERROR_NORM		0
+
+#define STB0899_TSOUT				0xf54f
+#define STB0899_RSSYNCDEL			0xf550
+#define STB0899_TSINHDELH			0xf551
+#define STB0899_TSINHDELM			0xf552
+#define STB0899_TSINHDELL			0xf553
+#define STB0899_TSLLSTKM			0xf55a
+#define STB0899_TSLLSTKL			0xf55b
+#define STB0899_TSULSTKM			0xf55c
+#define STB0899_TSULSTKL			0xf55d
+#define STB0899_TSSTATUS			0xf561
+
+#define STB0899_PDELCTRL			0xf600
+#define STB0899_INVERT_RES			(0x01 << 7)
+#define STB0899_OFFST_INVERT_RES		7
+#define STB0899_WIDTH_INVERT_RES		1
+#define STB0899_FORCE_ACCEPTED			(0x01 << 6)
+#define STB0899_OFFST_FORCE_ACCEPTED		6
+#define STB0899_WIDTH_FORCE_ACCEPTED		1
+#define STB0899_FILTER_EN			(0x01 << 5)
+#define STB0899_OFFST_FILTER_EN			5
+#define STB0899_WIDTH_FILTER_EN			1
+#define STB0899_LOCKFALL_THRESH			(0x01 << 4)
+#define STB0899_OFFST_LOCKFALL_THRESH		4
+#define STB0899_WIDTH_LOCKFALL_THRESH		1
+#define STB0899_HYST_EN				(0x01 << 3)
+#define STB0899_OFFST_HYST_EN			3
+#define STB0899_WIDTH_HYST_EN			1
+#define STB0899_HYST_SWRST			(0x01 << 2)
+#define STB0899_OFFST_HYST_SWRST		2
+#define STB0899_WIDTH_HYST_SWRST		1
+#define STB0899_ALGO_EN				(0x01 << 1)
+#define STB0899_OFFST_ALGO_EN			1
+#define STB0899_WIDTH_ALGO_EN			1
+#define STB0899_ALGO_SWRST			(0x01 << 0)
+#define STB0899_OFFST_ALGO_SWRST		0
+#define STB0899_WIDTH_ALGO_SWRST		1
+
+#define STB0899_PDELCTRL2			0xf601
+#define STB0899_BBHCTRL1			0xf602
+#define STB0899_BBHCTRL2			0xf603
+#define STB0899_HYSTTHRESH			0xf604
+
+#define STB0899_MATCSTM				0xf605
+#define STB0899_MATCSTL				0xf606
+#define STB0899_UPLCSTM				0xf607
+#define STB0899_UPLCSTL				0xf608
+#define STB0899_DFLCSTM				0xf609
+#define STB0899_DFLCSTL				0xf60a
+#define STB0899_SYNCCST				0xf60b
+#define STB0899_SYNCDCSTM			0xf60c
+#define STB0899_SYNCDCSTL			0xf60d
+#define STB0899_ISI_ENTRY			0xf60e
+#define STB0899_ISI_BIT_EN			0xf60f
+#define STB0899_MATSTRM				0xf610
+#define STB0899_MATSTRL				0xf611
+#define STB0899_UPLSTRM				0xf612
+#define STB0899_UPLSTRL				0xf613
+#define STB0899_DFLSTRM				0xf614
+#define STB0899_DFLSTRL				0xf615
+#define STB0899_SYNCSTR				0xf616
+#define STB0899_SYNCDSTRM			0xf617
+#define STB0899_SYNCDSTRL			0xf618
+
+#define STB0899_CFGPDELSTATUS1			0xf619
+#define STB0899_BADDFL				(0x01 << 6)
+#define STB0899_OFFST_BADDFL			6
+#define STB0899_WIDTH_BADDFL			1
+#define STB0899_CONTINUOUS_STREAM		(0x01 << 5)
+#define STB0899_OFFST_CONTINUOUS_STREAM		5
+#define STB0899_WIDTH_CONTINUOUS_STREAM		1
+#define STB0899_ACCEPTED_STREAM			(0x01 << 4)
+#define STB0899_OFFST_ACCEPTED_STREAM		4
+#define STB0899_WIDTH_ACCEPTED_STREAM		1
+#define STB0899_BCH_ERRFLAG			(0x01 << 3)
+#define STB0899_OFFST_BCH_ERRFLAG		3
+#define STB0899_WIDTH_BCH_ERRFLAG		1
+#define STB0899_CRCRES				(0x01 << 2)
+#define STB0899_OFFST_CRCRES			2
+#define STB0899_WIDTH_CRCRES			1
+#define STB0899_CFGPDELSTATUS_LOCK		(0x01 << 1)
+#define STB0899_OFFST_CFGPDELSTATUS_LOCK	1
+#define STB0899_WIDTH_CFGPDELSTATUS_LOCK	1
+#define STB0899_1STLOCK				(0x01 << 0)
+#define STB0899_OFFST_1STLOCK			0
+#define STB0899_WIDTH_1STLOCK			1
+
+#define STB0899_CFGPDELSTATUS2			0xf61a
+#define STB0899_BBFERRORM			0xf61b
+#define STB0899_BBFERRORL			0xf61c
+#define STB0899_UPKTERRORM			0xf61d
+#define STB0899_UPKTERRORL			0xf61e
+
+#define STB0899_TSTCK				0xff10
+
+#define STB0899_TSTRES				0xff11
+#define STB0899_FRESLDPC			(0x01 << 7)
+#define STB0899_OFFST_FRESLDPC			7
+#define STB0899_WIDTH_FRESLDPC			1
+#define STB0899_FRESRS				(0x01 << 6)
+#define STB0899_OFFST_FRESRS			6
+#define STB0899_WIDTH_FRESRS			1
+#define STB0899_FRESVIT				(0x01 << 5)
+#define STB0899_OFFST_FRESVIT			5
+#define STB0899_WIDTH_FRESVIT			1
+#define STB0899_FRESMAS1_2			(0x01 << 4)
+#define STB0899_OFFST_FRESMAS1_2		4
+#define STB0899_WIDTH_FRESMAS1_2		1
+#define STB0899_FRESACS				(0x01 << 3)
+#define STB0899_OFFST_FRESACS			3
+#define STB0899_WIDTH_FRESACS			1
+#define STB0899_FRESSYM				(0x01 << 2)
+#define STB0899_OFFST_FRESSYM			2
+#define STB0899_WIDTH_FRESSYM			1
+#define STB0899_FRESMAS				(0x01 << 1)
+#define STB0899_OFFST_FRESMAS			1
+#define STB0899_WIDTH_FRESMAS			1
+#define STB0899_FRESINT				(0x01 << 0)
+#define STB0899_OFFST_FRESINIT			0
+#define STB0899_WIDTH_FRESINIT			1
+
+#define STB0899_TSTOUT				0xff12
+#define STB0899_EN_SIGNATURE			(0x01 << 7)
+#define STB0899_OFFST_EN_SIGNATURE		7
+#define STB0899_WIDTH_EN_SIGNATURE		1
+#define STB0899_BCLK_CLK			(0x01 << 6)
+#define STB0899_OFFST_BCLK_CLK			6
+#define STB0899_WIDTH_BCLK_CLK			1
+#define STB0899_SGNL_OUT			(0x01 << 5)
+#define STB0899_OFFST_SGNL_OUT			5
+#define STB0899_WIDTH_SGNL_OUT			1
+#define STB0899_TS				(0x01 << 4)
+#define STB0899_OFFST_TS			4
+#define STB0899_WIDTH_TS			1
+#define STB0899_CTEST				(0x01 << 0)
+#define STB0899_OFFST_CTEST			0
+#define STB0899_WIDTH_CTEST			1
+
+#define STB0899_TSTIN				0xff13
+#define STB0899_TEST_IN				(0x01 << 7)
+#define STB0899_OFFST_TEST_IN			7
+#define STB0899_WIDTH_TEST_IN			1
+#define STB0899_EN_ADC				(0x01 << 6)
+#define STB0899_OFFST_EN_ADC			6
+#define STB0899_WIDTH_ENADC			1
+#define STB0899_SGN_ADC				(0x01 << 5)
+#define STB0899_OFFST_SGN_ADC			5
+#define STB0899_WIDTH_SGN_ADC			1
+#define STB0899_BCLK_IN				(0x01 << 4)
+#define STB0899_OFFST_BCLK_IN			4
+#define STB0899_WIDTH_BCLK_IN			1
+#define STB0899_JETONIN_MODE			(0x01 << 3)
+#define STB0899_OFFST_JETONIN_MODE		3
+#define STB0899_WIDTH_JETONIN_MODE		1
+#define STB0899_BCLK_VALUE			(0x01 << 2)
+#define STB0899_OFFST_BCLK_VALUE		2
+#define STB0899_WIDTH_BCLK_VALUE		1
+#define STB0899_SGNRST_T12			(0x01 << 1)
+#define STB0899_OFFST_SGNRST_T12		1
+#define STB0899_WIDTH_SGNRST_T12		1
+#define STB0899_LOWSP_ENAX			(0x01 << 0)
+#define STB0899_OFFST_LOWSP_ENAX		0
+#define STB0899_WIDTH_LOWSP_ENAX		1
+
+#define STB0899_TSTSYS				0xff14
+#define STB0899_TSTCHIP				0xff15
+#define STB0899_TSTFREE				0xff16
+#define STB0899_TSTI2C				0xff17
+#define STB0899_BITSPEEDM			0xff1c
+#define STB0899_BITSPEEDL			0xff1d
+#define STB0899_TBUSBIT				0xff1e
+#define STB0899_TSTDIS				0xff24
+#define STB0899_TSTDISRX			0xff25
+#define STB0899_TSTJETON			0xff28
+#define STB0899_TSTDCADJ			0xff40
+#define STB0899_TSTAGC1				0xff41
+#define STB0899_TSTAGC1N			0xff42
+#define STB0899_TSTPOLYPH			0xff48
+#define STB0899_TSTR				0xff49
+#define STB0899_TSTAGC2				0xff4a
+#define STB0899_TSTCTL1				0xff4b
+#define STB0899_TSTCTL2				0xff4c
+#define STB0899_TSTCTL3				0xff4d
+#define STB0899_TSTDEMAP			0xff50
+#define STB0899_TSTDEMAP2			0xff51
+#define STB0899_TSTDEMMON			0xff52
+#define STB0899_TSTRATE				0xff53
+#define STB0899_TSTSELOUT			0xff54
+#define STB0899_TSYNC				0xff55
+#define STB0899_TSTERR				0xff56
+#define STB0899_TSTRAM1				0xff58
+#define STB0899_TSTVSELOUT			0xff59
+#define STB0899_TSTFORCEIN			0xff5a
+#define STB0899_TSTRS1				0xff5c
+#define STB0899_TSTRS2				0xff5d
+#define STB0899_TSTRS3				0xff53
+
+#define STB0899_INTBUFSTATUS			0xf200
+#define STB0899_INTBUFCTRL			0xf201
+#define STB0899_PCKLENUL			0xf55e
+#define STB0899_PCKLENLL			0xf55f
+#define STB0899_RSPCKLEN			0xf560
+
+/*	2 registers	*/
+#define STB0899_SYNCDCST			0xf60c
+
+/*	DiSEqC	*/
+#define STB0899_DISCNTRL1			0xf0a0
+#define STB0899_TIMOFF				(0x01 << 7)
+#define STB0899_OFFST_TIMOFF			7
+#define STB0899_WIDTH_TIMOFF			1
+#define STB0899_DISEQCRESET			(0x01 << 6)
+#define STB0899_OFFST_DISEQCRESET		6
+#define STB0899_WIDTH_DISEQCRESET		1
+#define STB0899_TIMCMD				(0x03 << 4)
+#define STB0899_OFFST_TIMCMD			4
+#define STB0899_WIDTH_TIMCMD			2
+#define STB0899_DISPRECHARGE			(0x01 << 2)
+#define STB0899_OFFST_DISPRECHARGE		2
+#define STB0899_WIDTH_DISPRECHARGE		1
+#define STB0899_DISEQCMODE			(0x03 << 0)
+#define STB0899_OFFST_DISEQCMODE		0
+#define STB0899_WIDTH_DISEQCMODE		2
+
+#define STB0899_DISCNTRL2			0xf0a1
+#define STB0899_RECEIVER_ON			(0x01 << 7)
+#define STB0899_OFFST_RECEIVER_ON		7
+#define STB0899_WIDTH_RECEIVER_ON		1
+#define STB0899_IGNO_SHORT_22K			(0x01 << 6)
+#define STB0899_OFFST_IGNO_SHORT_22K		6
+#define STB0899_WIDTH_IGNO_SHORT_22K		1
+#define STB0899_ONECHIP_TRX			(0x01 << 5)
+#define STB0899_OFFST_ONECHIP_TRX		5
+#define STB0899_WIDTH_ONECHIP_TRX		1
+#define STB0899_EXT_ENVELOP			(0x01 << 4)
+#define STB0899_OFFST_EXT_ENVELOP		4
+#define STB0899_WIDTH_EXT_ENVELOP		1
+#define STB0899_PIN_SELECT			(0x03 << 2)
+#define STB0899_OFFST_PIN_SELCT			2
+#define STB0899_WIDTH_PIN_SELCT			2
+#define STB0899_IRQ_RXEND			(0x01 << 1)
+#define STB0899_OFFST_IRQ_RXEND			1
+#define STB0899_WIDTH_IRQ_RXEND			1
+#define STB0899_IRQ_4NBYTES			(0x01 << 0)
+#define STB0899_OFFST_IRQ_4NBYTES		0
+#define STB0899_WIDTH_IRQ_4NBYTES		1
+
+#define STB0899_DISRX_ST0			0xf0a4
+#define STB0899_RXEND				(0x01 << 7)
+#define STB0899_OFFST_RXEND			7
+#define STB0899_WIDTH_RXEND			1
+#define STB0899_RXACTIVE			(0x01 << 6)
+#define STB0899_OFFST_RXACTIVE			6
+#define STB0899_WIDTH_RXACTIVE			1
+#define STB0899_SHORT22K			(0x01 << 5)
+#define STB0899_OFFST_SHORT22K			5
+#define STB0899_WIDTH_SHORT22K			1
+#define STB0899_CONTTONE			(0x01 << 4)
+#define STB0899_OFFST_CONTTONE			4
+#define STB0899_WIDTH_CONTONE			1
+#define STB0899_4BFIFOREDY			(0x01 << 3)
+#define STB0899_OFFST_4BFIFOREDY		3
+#define STB0899_WIDTH_4BFIFOREDY		1
+#define STB0899_FIFOEMPTY			(0x01 << 2)
+#define STB0899_OFFST_FIFOEMPTY			2
+#define STB0899_WIDTH_FIFOEMPTY			1
+#define STB0899_ABORTTRX			(0x01 << 0)
+#define STB0899_OFFST_ABORTTRX			0
+#define STB0899_WIDTH_ABORTTRX			1
+
+#define STB0899_DISRX_ST1			0xf0a5
+#define STB0899_RXFAIL				(0x01 << 7)
+#define STB0899_OFFST_RXFAIL			7
+#define STB0899_WIDTH_RXFAIL			1
+#define STB0899_FIFOPFAIL			(0x01 << 6)
+#define STB0899_OFFST_FIFOPFAIL			6
+#define STB0899_WIDTH_FIFOPFAIL			1
+#define STB0899_RXNONBYTES			(0x01 << 5)
+#define STB0899_OFFST_RXNONBYTES		5
+#define STB0899_WIDTH_RXNONBYTES		1
+#define STB0899_FIFOOVF				(0x01 << 4)
+#define STB0899_OFFST_FIFOOVF			4
+#define STB0899_WIDTH_FIFOOVF			1
+#define STB0899_FIFOBYTENBR			(0x0f << 0)
+#define STB0899_OFFST_FIFOBYTENBR		0
+#define STB0899_WIDTH_FIFOBYTENBR		4
+
+#define STB0899_DISPARITY			0xf0a6
+
+#define STB0899_DISFIFO				0xf0a7
+
+#define STB0899_DISSTATUS			0xf0a8
+#define STB0899_FIFOFULL			(0x01 << 6)
+#define STB0899_OFFST_FIFOFULL			6
+#define STB0899_WIDTH_FIFOFULL			1
+#define STB0899_TXIDLE				(0x01 << 5)
+#define STB0899_OFFST_TXIDLE			5
+#define STB0899_WIDTH_TXIDLE			1
+#define STB0899_GAPBURST			(0x01 << 4)
+#define STB0899_OFFST_GAPBURST			4
+#define STB0899_WIDTH_GAPBURST			1
+#define STB0899_TXFIFOBYTES			(0x0f << 0)
+#define STB0899_OFFST_TXFIFOBYTES		0
+#define STB0899_WIDTH_TXFIFOBYTES		4
+#define STB0899_DISF22				0xf0a9
+
+#define STB0899_DISF22RX			0xf0aa
+
+/*	General Purpose	*/
+#define STB0899_SYSREG				0xf101
+#define STB0899_ACRPRESC			0xf110
+#define STB0899_OFFST_RSVD2			7
+#define STB0899_WIDTH_RSVD2			1
+#define STB0899_OFFST_ACRPRESC			4
+#define STB0899_WIDTH_ACRPRESC			3
+#define STB0899_OFFST_RSVD1			3
+#define STB0899_WIDTH_RSVD1			1
+#define STB0899_OFFST_ACRPRESC2			0
+#define STB0899_WIDTH_ACRPRESC2			3
+
+#define STB0899_ACRDIV1				0xf111
+#define STB0899_ACRDIV2				0xf112
+#define STB0899_DACR1				0xf113
+#define STB0899_DACR2				0xf114
+#define STB0899_OUTCFG				0xf11c
+#define STB0899_MODECFG				0xf11d
+#define STB0899_NCOARSE				0xf1b3
+
+#define STB0899_SYNTCTRL			0xf1b6
+#define STB0899_STANDBY				(0x01 << 7)
+#define STB0899_OFFST_STANDBY			7
+#define STB0899_WIDTH_STANDBY			1
+#define STB0899_BYPASSPLL			(0x01 << 6)
+#define STB0899_OFFST_BYPASSPLL			6
+#define STB0899_WIDTH_BYPASSPLL			1
+#define STB0899_SEL1XRATIO			(0x01 << 5)
+#define STB0899_OFFST_SEL1XRATIO		5
+#define STB0899_WIDTH_SEL1XRATIO		1
+#define STB0899_SELOSCI				(0x01 << 1)
+#define STB0899_OFFST_SELOSCI			1
+#define STB0899_WIDTH_SELOSCI			1
+
+#define STB0899_FILTCTRL			0xf1b7
+#define STB0899_SYSCTRL				0xf1b8
+
+#define STB0899_STOPCLK1			0xf1c2
+#define STB0899_STOP_CKINTBUF108		(0x01 << 7)
+#define STB0899_OFFST_STOP_CKINTBUF108		7
+#define STB0899_WIDTH_STOP_CKINTBUF108		1
+#define STB0899_STOP_CKINTBUF216		(0x01 << 6)
+#define STB0899_OFFST_STOP_CKINTBUF216		6
+#define STB0899_WIDTH_STOP_CKINTBUF216		1
+#define STB0899_STOP_CHK8PSK			(0x01 << 5)
+#define STB0899_OFFST_STOP_CHK8PSK		5
+#define STB0899_WIDTH_STOP_CHK8PSK		1
+#define STB0899_STOP_CKFEC108			(0x01 << 4)
+#define STB0899_OFFST_STOP_CKFEC108		4
+#define STB0899_WIDTH_STOP_CKFEC108		1
+#define STB0899_STOP_CKFEC216			(0x01 << 3)
+#define STB0899_OFFST_STOP_CKFEC216		3
+#define STB0899_WIDTH_STOP_CKFEC216		1
+#define STB0899_STOP_CKCORE216			(0x01 << 2)
+#define STB0899_OFFST_STOP_CKCORE216		2
+#define STB0899_WIDTH_STOP_CKCORE216		1
+#define STB0899_STOP_CKADCI108			(0x01 << 1)
+#define STB0899_OFFST_STOP_CKADCI108		1
+#define STB0899_WIDTH_STOP_CKADCI108		1
+#define STB0899_STOP_INVCKADCI108		(0x01 << 0)
+#define STB0899_OFFST_STOP_INVCKADCI108		0
+#define STB0899_WIDTH_STOP_INVCKADCI108		1
+
+#define STB0899_STOPCLK2			0xf1c3
+#define STB0899_STOP_CKS2DMD108			(0x01 << 2)
+#define STB0899_OFFST_STOP_CKS2DMD108		2
+#define STB0899_WIDTH_STOP_CKS2DMD108		1
+#define STB0899_STOP_CKPKDLIN108		(0x01 << 1)
+#define STB0899_OFFST_STOP_CKPKDLIN108		1
+#define STB0899_WIDTH_STOP_CKPKDLIN108		1
+#define STB0899_STOP_CKPKDLIN216		(0x01 << 0)
+#define STB0899_OFFST_STOP_CKPKDLIN216		0
+#define STB0899_WIDTH_STOP_CKPKDLIN216		1
+
+#define STB0899_TSTTNR1				0xf1e0
+#define STB0899_BYPASS_ADC			(0x01 << 7)
+#define STB0899_OFFST_BYPASS_ADC		7
+#define STB0899_WIDTH_BYPASS_ADC		1
+#define STB0899_INVADCICKOUT			(0x01 << 6)
+#define STB0899_OFFST_INVADCICKOUT		6
+#define STB0899_WIDTH_INVADCICKOUT		1
+#define STB0899_ADCTEST_VOLTAGE			(0x03 << 4)
+#define STB0899_OFFST_ADCTEST_VOLTAGE		4
+#define STB0899_WIDTH_ADCTEST_VOLTAGE		1
+#define STB0899_ADC_RESET			(0x01 << 3)
+#define STB0899_OFFST_ADC_RESET			3
+#define STB0899_WIDTH_ADC_RESET			1
+#define STB0899_TSTTNR1_2			(0x01 << 2)
+#define STB0899_OFFST_TSTTNR1_2			2
+#define STB0899_WIDTH_TSTTNR1_2			1
+#define STB0899_ADCPON				(0x01 << 1)
+#define STB0899_OFFST_ADCPON			1
+#define STB0899_WIDTH_ADCPON			1
+#define STB0899_ADCIN_MODE			(0x01 << 0)
+#define STB0899_OFFST_ADCIN_MODE		0
+#define STB0899_WIDTH_ADCIN_MODE		1
+
+#define STB0899_TSTTNR2				0xf1e1
+#define STB0899_TSTTNR2_7			(0x01 << 7)
+#define STB0899_OFFST_TSTTNR2_7			7
+#define STB0899_WIDTH_TSTTNR2_7			1
+#define STB0899_NOT_DISRX_WIRED			(0x01 << 6)
+#define STB0899_OFFST_NOT_DISRX_WIRED		6
+#define STB0899_WIDTH_NOT_DISRX_WIRED		1
+#define STB0899_DISEQC_DCURRENT			(0x01 << 5)
+#define STB0899_OFFST_DISEQC_DCURRENT		5
+#define STB0899_WIDTH_DISEQC_DCURRENT		1
+#define STB0899_DISEQC_ZCURRENT			(0x01 << 4)
+#define STB0899_OFFST_DISEQC_ZCURRENT		4
+#define STB0899_WIDTH_DISEQC_ZCURRENT		1
+#define STB0899_DISEQC_SINC_SOURCE		(0x03 << 2)
+#define STB0899_OFFST_DISEQC_SINC_SOURCE	2
+#define STB0899_WIDTH_DISEQC_SINC_SOURCE	2
+#define STB0899_SELIQSRC			(0x03 << 0)
+#define STB0899_OFFST_SELIQSRC			0
+#define STB0899_WIDTH_SELIQSRC			2
+
+#define STB0899_TSTTNR3				0xf1e2
+
+#define STB0899_I2CCFG				0xf129
+#define STB0899_I2CCFGRSVD			(0x0f << 4)
+#define STB0899_OFFST_I2CCFGRSVD		4
+#define STB0899_WIDTH_I2CCFGRSVD		4
+#define STB0899_I2CFASTMODE			(0x01 << 3)
+#define STB0899_OFFST_I2CFASTMODE		3
+#define STB0899_WIDTH_I2CFASTMODE		1
+#define STB0899_STATUSWR			(0x01 << 2)
+#define STB0899_OFFST_STATUSWR			2
+#define STB0899_WIDTH_STATUSWR			1
+#define STB0899_I2CADDRINC			(0x03 << 0)
+#define STB0899_OFFST_I2CADDRINC		0
+#define STB0899_WIDTH_I2CADDRINC		2
+
+#define STB0899_I2CRPT				0xf12a
+#define STB0899_I2CTON				(0x01 << 7)
+#define STB0899_OFFST_I2CTON			7
+#define STB0899_WIDTH_I2CTON			1
+#define STB0899_ENARPTLEVEL			(0x01 << 6)
+#define STB0899_OFFST_ENARPTLEVEL		6
+#define STB0899_WIDTH_ENARPTLEVEL		2
+#define STB0899_SCLTDELAY			(0x01 << 3)
+#define STB0899_OFFST_SCLTDELAY			3
+#define STB0899_WIDTH_SCLTDELAY			1
+#define STB0899_STOPENA				(0x01 << 2)
+#define STB0899_OFFST_STOPENA			2
+#define STB0899_WIDTH_STOPENA			1
+#define STB0899_STOPSDAT2SDA			(0x01 << 1)
+#define STB0899_OFFST_STOPSDAT2SDA		1
+#define STB0899_WIDTH_STOPSDAT2SDA		1
+
+#define STB0899_IOPVALUE8			0xf136
+#define STB0899_IOPVALUE7			0xf137
+#define STB0899_IOPVALUE6			0xf138
+#define STB0899_IOPVALUE5			0xf139
+#define STB0899_IOPVALUE4			0xf13a
+#define STB0899_IOPVALUE3			0xf13b
+#define STB0899_IOPVALUE2			0xf13c
+#define STB0899_IOPVALUE1			0xf13d
+#define STB0899_IOPVALUE0			0xf13e
+
+#define STB0899_GPIO00CFG			0xf140
+
+#define STB0899_GPIO01CFG			0xf141
+#define STB0899_GPIO02CFG			0xf142
+#define STB0899_GPIO03CFG			0xf143
+#define STB0899_GPIO04CFG			0xf144
+#define STB0899_GPIO05CFG			0xf145
+#define STB0899_GPIO06CFG			0xf146
+#define STB0899_GPIO07CFG			0xf147
+#define STB0899_GPIO08CFG			0xf148
+#define STB0899_GPIO09CFG			0xf149
+#define STB0899_GPIO10CFG			0xf14a
+#define STB0899_GPIO11CFG			0xf14b
+#define STB0899_GPIO12CFG			0xf14c
+#define STB0899_GPIO13CFG			0xf14d
+#define STB0899_GPIO14CFG			0xf14e
+#define STB0899_GPIO15CFG			0xf14f
+#define STB0899_GPIO16CFG			0xf150
+#define STB0899_GPIO17CFG			0xf151
+#define STB0899_GPIO18CFG			0xf152
+#define STB0899_GPIO19CFG			0xf153
+#define STB0899_GPIO20CFG			0xf154
+
+#define STB0899_SDATCFG				0xf155
+#define STB0899_SCLTCFG				0xf156
+#define STB0899_AGCRFCFG			0xf157
+#define STB0899_GPIO22				0xf158	/* AGCBB2CFG	*/
+#define STB0899_GPIO21				0xf159  /* AGCBB1CFG	*/
+#define STB0899_DIRCLKCFG			0xf15a
+#define STB0899_CLKOUT27CFG			0xf15b
+#define STB0899_STDBYCFG			0xf15c
+#define STB0899_CS0CFG				0xf15d
+#define STB0899_CS1CFG				0xf15e
+#define STB0899_DISEQCOCFG			0xf15f
+
+#define STB0899_GPIO32CFG			0xf160
+#define STB0899_GPIO33CFG			0xf161
+#define STB0899_GPIO34CFG			0xf162
+#define STB0899_GPIO35CFG			0xf163
+#define STB0899_GPIO36CFG			0xf164
+#define STB0899_GPIO37CFG			0xf165
+#define STB0899_GPIO38CFG			0xf166
+#define STB0899_GPIO39CFG			0xf167
+
+#define STB0899_IRQSTATUS_3			0xf120
+#define STB0899_IRQSTATUS_2			0xf121
+#define STB0899_IRQSTATUS_1			0xf122
+#define STB0899_IRQSTATUS_0			0xf123
+
+#define STB0899_IRQMSK_3			0xf124
+#define STB0899_IRQMSK_2			0xf125
+#define STB0899_IRQMSK_1			0xf126
+#define STB0899_IRQMSK_0			0xf127
+
+#define STB0899_IRQCFG				0xf128
+
+#define STB0899_GHOSTREG			0xf000
+
+#define STB0899_S2DEMOD				0xf3fc
+#define STB0899_S2FEC				0xfafc
+
+
+#endif
diff --git a/drivers/media/dvb-frontends/stb6000.c b/drivers/media/dvb-frontends/stb6000.c
new file mode 100644
index 0000000..a0c3c52
--- /dev/null
+++ b/drivers/media/dvb-frontends/stb6000.c
@@ -0,0 +1,256 @@
+  /*
+     Driver for ST STB6000 DVBS Silicon tuner
+
+     Copyright (C) 2008 Igor M. Liplianin (liplianin@me.by)
+
+     This program is free software; you can redistribute it and/or modify
+     it under the terms of the 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/slab.h>
+#include <linux/module.h>
+#include <linux/dvb/frontend.h>
+#include <asm/types.h>
+
+#include "stb6000.h"
+
+static int debug;
+#define dprintk(args...) \
+	do { \
+		if (debug) \
+			printk(KERN_DEBUG "stb6000: " args); \
+	} while (0)
+
+struct stb6000_priv {
+	/* i2c details */
+	int i2c_address;
+	struct i2c_adapter *i2c;
+	u32 frequency;
+};
+
+static int stb6000_release(struct dvb_frontend *fe)
+{
+	kfree(fe->tuner_priv);
+	fe->tuner_priv = NULL;
+	return 0;
+}
+
+static int stb6000_sleep(struct dvb_frontend *fe)
+{
+	struct stb6000_priv *priv = fe->tuner_priv;
+	int ret;
+	u8 buf[] = { 10, 0 };
+	struct i2c_msg msg = {
+		.addr = priv->i2c_address,
+		.flags = 0,
+		.buf = buf,
+		.len = 2
+	};
+
+	dprintk("%s:\n", __func__);
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+
+	ret = i2c_transfer(priv->i2c, &msg, 1);
+	if (ret != 1)
+		dprintk("%s: i2c error\n", __func__);
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 0);
+
+	return (ret == 1) ? 0 : ret;
+}
+
+static int stb6000_set_params(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct stb6000_priv *priv = fe->tuner_priv;
+	unsigned int n, m;
+	int ret;
+	u32 freq_mhz;
+	int bandwidth;
+	u8 buf[12];
+	struct i2c_msg msg = {
+		.addr = priv->i2c_address,
+		.flags = 0,
+		.buf = buf,
+		.len = 12
+	};
+
+	dprintk("%s:\n", __func__);
+
+	freq_mhz = p->frequency / 1000;
+	bandwidth = p->symbol_rate / 1000000;
+
+	if (bandwidth > 31)
+		bandwidth = 31;
+
+	if ((freq_mhz > 949) && (freq_mhz < 2151)) {
+		buf[0] = 0x01;
+		buf[1] = 0xac;
+		if (freq_mhz < 1950)
+			buf[1] = 0xaa;
+		if (freq_mhz < 1800)
+			buf[1] = 0xa8;
+		if (freq_mhz < 1650)
+			buf[1] = 0xa6;
+		if (freq_mhz < 1530)
+			buf[1] = 0xa5;
+		if (freq_mhz < 1470)
+			buf[1] = 0xa4;
+		if (freq_mhz < 1370)
+			buf[1] = 0xa2;
+		if (freq_mhz < 1300)
+			buf[1] = 0xa1;
+		if (freq_mhz < 1200)
+			buf[1] = 0xa0;
+		if (freq_mhz < 1075)
+			buf[1] = 0xbc;
+		if (freq_mhz < 1000)
+			buf[1] = 0xba;
+		if (freq_mhz < 1075) {
+			n = freq_mhz / 8; /* vco=lo*4 */
+			m = 2;
+		} else {
+			n = freq_mhz / 16; /* vco=lo*2 */
+			m = 1;
+		}
+		buf[2] = n >> 1;
+		buf[3] = (unsigned char)(((n & 1) << 7) |
+					(m * freq_mhz - n * 16) | 0x60);
+		buf[4] = 0x04;
+		buf[5] = 0x0e;
+
+		buf[6] = (unsigned char)(bandwidth);
+
+		buf[7] = 0xd8;
+		buf[8] = 0xd0;
+		buf[9] = 0x50;
+		buf[10] = 0xeb;
+		buf[11] = 0x4f;
+
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 1);
+
+		ret = i2c_transfer(priv->i2c, &msg, 1);
+		if (ret != 1)
+			dprintk("%s: i2c error\n", __func__);
+
+		udelay(10);
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 0);
+
+		buf[0] = 0x07;
+		buf[1] = 0xdf;
+		buf[2] = 0xd0;
+		buf[3] = 0x50;
+		buf[4] = 0xfb;
+		msg.len = 5;
+
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 1);
+
+		ret = i2c_transfer(priv->i2c, &msg, 1);
+		if (ret != 1)
+			dprintk("%s: i2c error\n", __func__);
+
+		udelay(10);
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 0);
+
+		priv->frequency = freq_mhz * 1000;
+
+		return (ret == 1) ? 0 : ret;
+	}
+	return -1;
+}
+
+static int stb6000_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+	struct stb6000_priv *priv = fe->tuner_priv;
+	*frequency = priv->frequency;
+	return 0;
+}
+
+static struct dvb_tuner_ops stb6000_tuner_ops = {
+	.info = {
+		.name = "ST STB6000",
+		.frequency_min = 950000,
+		.frequency_max = 2150000
+	},
+	.release = stb6000_release,
+	.sleep = stb6000_sleep,
+	.set_params = stb6000_set_params,
+	.get_frequency = stb6000_get_frequency,
+};
+
+struct dvb_frontend *stb6000_attach(struct dvb_frontend *fe, int addr,
+						struct i2c_adapter *i2c)
+{
+	struct stb6000_priv *priv = NULL;
+	u8 b0[] = { 0 };
+	u8 b1[] = { 0, 0 };
+	struct i2c_msg msg[2] = {
+		{
+			.addr = addr,
+			.flags = 0,
+			.buf = b0,
+			.len = 0
+		}, {
+			.addr = addr,
+			.flags = I2C_M_RD,
+			.buf = b1,
+			.len = 2
+		}
+	};
+	int ret;
+
+	dprintk("%s:\n", __func__);
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+
+	/* is some i2c device here ? */
+	ret = i2c_transfer(i2c, msg, 2);
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 0);
+
+	if (ret != 2)
+		return NULL;
+
+	priv = kzalloc(sizeof(struct stb6000_priv), GFP_KERNEL);
+	if (priv == NULL)
+		return NULL;
+
+	priv->i2c_address = addr;
+	priv->i2c = i2c;
+
+	memcpy(&fe->ops.tuner_ops, &stb6000_tuner_ops,
+				sizeof(struct dvb_tuner_ops));
+
+	fe->tuner_priv = priv;
+
+	return fe;
+}
+EXPORT_SYMBOL(stb6000_attach);
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+
+MODULE_DESCRIPTION("DVB STB6000 driver");
+MODULE_AUTHOR("Igor M. Liplianin <liplianin@me.by>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb-frontends/stb6000.h b/drivers/media/dvb-frontends/stb6000.h
new file mode 100644
index 0000000..7be479c
--- /dev/null
+++ b/drivers/media/dvb-frontends/stb6000.h
@@ -0,0 +1,51 @@
+  /*
+     Driver for ST stb6000 DVBS Silicon tuner
+
+     Copyright (C) 2008 Igor M. Liplianin (liplianin@me.by)
+
+     This program is free software; you can redistribute it and/or modify
+     it under the terms of the 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_STB6000_H__
+#define __DVB_STB6000_H__
+
+#include <linux/i2c.h>
+#include "dvb_frontend.h"
+
+/**
+ * Attach a stb6000 tuner to the supplied frontend structure.
+ *
+ * @param fe Frontend to attach to.
+ * @param addr i2c address of the tuner.
+ * @param i2c i2c adapter to use.
+ * @return FE pointer on success, NULL on failure.
+ */
+#if defined(CONFIG_DVB_STB6000) || (defined(CONFIG_DVB_STB6000_MODULE) \
+							&& defined(MODULE))
+extern struct dvb_frontend *stb6000_attach(struct dvb_frontend *fe, int addr,
+					   struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend *stb6000_attach(struct dvb_frontend *fe,
+						  int addr,
+						  struct i2c_adapter *i2c)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif /* CONFIG_DVB_STB6000 */
+
+#endif /* __DVB_STB6000_H__ */
diff --git a/drivers/media/dvb-frontends/stb6100.c b/drivers/media/dvb-frontends/stb6100.c
new file mode 100644
index 0000000..2e93e65
--- /dev/null
+++ b/drivers/media/dvb-frontends/stb6100.c
@@ -0,0 +1,611 @@
+/*
+	STB6100 Silicon Tuner
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	Copyright (C) ST Microelectronics
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the 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/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+
+#include "dvb_frontend.h"
+#include "stb6100.h"
+
+static unsigned int verbose;
+module_param(verbose, int, 0644);
+
+
+#define FE_ERROR		0
+#define FE_NOTICE		1
+#define FE_INFO			2
+#define FE_DEBUG		3
+
+#define dprintk(x, y, z, format, arg...) do {						\
+	if (z) {									\
+		if	((x > FE_ERROR) && (x > y))					\
+			printk(KERN_ERR "%s: " format "\n", __func__ , ##arg);		\
+		else if	((x > FE_NOTICE) && (x > y))					\
+			printk(KERN_NOTICE "%s: " format "\n", __func__ , ##arg);	\
+		else if ((x > FE_INFO) && (x > y))					\
+			printk(KERN_INFO "%s: " format "\n", __func__ , ##arg);		\
+		else if ((x > FE_DEBUG) && (x > y))					\
+			printk(KERN_DEBUG "%s: " format "\n", __func__ , ##arg);	\
+	} else {									\
+		if (x > y)								\
+			printk(format, ##arg);						\
+	}										\
+} while (0)
+
+struct stb6100_lkup {
+	u32 val_low;
+	u32 val_high;
+	u8   reg;
+};
+
+static int stb6100_release(struct dvb_frontend *fe);
+
+static const struct stb6100_lkup lkup[] = {
+	{       0,  950000, 0x0a },
+	{  950000, 1000000, 0x0a },
+	{ 1000000, 1075000, 0x0c },
+	{ 1075000, 1200000, 0x00 },
+	{ 1200000, 1300000, 0x01 },
+	{ 1300000, 1370000, 0x02 },
+	{ 1370000, 1470000, 0x04 },
+	{ 1470000, 1530000, 0x05 },
+	{ 1530000, 1650000, 0x06 },
+	{ 1650000, 1800000, 0x08 },
+	{ 1800000, 1950000, 0x0a },
+	{ 1950000, 2150000, 0x0c },
+	{ 2150000, 9999999, 0x0c },
+	{       0,       0, 0x00 }
+};
+
+/* Register names for easy debugging.	*/
+static const char *stb6100_regnames[] = {
+	[STB6100_LD]		= "LD",
+	[STB6100_VCO]		= "VCO",
+	[STB6100_NI]		= "NI",
+	[STB6100_NF_LSB]	= "NF",
+	[STB6100_K]		= "K",
+	[STB6100_G]		= "G",
+	[STB6100_F]		= "F",
+	[STB6100_DLB]		= "DLB",
+	[STB6100_TEST1]		= "TEST1",
+	[STB6100_FCCK]		= "FCCK",
+	[STB6100_LPEN]		= "LPEN",
+	[STB6100_TEST3]		= "TEST3",
+};
+
+/* Template for normalisation, i.e. setting unused or undocumented
+ * bits as required according to the documentation.
+ */
+struct stb6100_regmask {
+	u8 mask;
+	u8 set;
+};
+
+static const struct stb6100_regmask stb6100_template[] = {
+	[STB6100_LD]		= { 0xff, 0x00 },
+	[STB6100_VCO]		= { 0xff, 0x00 },
+	[STB6100_NI]		= { 0xff, 0x00 },
+	[STB6100_NF_LSB]	= { 0xff, 0x00 },
+	[STB6100_K]		= { 0xc7, 0x38 },
+	[STB6100_G]		= { 0xef, 0x10 },
+	[STB6100_F]		= { 0x1f, 0xc0 },
+	[STB6100_DLB]		= { 0x38, 0xc4 },
+	[STB6100_TEST1]		= { 0x00, 0x8f },
+	[STB6100_FCCK]		= { 0x40, 0x0d },
+	[STB6100_LPEN]		= { 0xf0, 0x0b },
+	[STB6100_TEST3]		= { 0x00, 0xde },
+};
+
+/*
+ * Currently unused. Some boards might need it in the future
+ */
+static inline void stb6100_normalise_regs(u8 regs[])
+{
+	int i;
+
+	for (i = 0; i < STB6100_NUMREGS; i++)
+		regs[i] = (regs[i] & stb6100_template[i].mask) | stb6100_template[i].set;
+}
+
+static int stb6100_read_regs(struct stb6100_state *state, u8 regs[])
+{
+	int rc;
+	struct i2c_msg msg = {
+		.addr	= state->config->tuner_address,
+		.flags	= I2C_M_RD,
+		.buf	= regs,
+		.len	= STB6100_NUMREGS
+	};
+
+	rc = i2c_transfer(state->i2c, &msg, 1);
+	if (unlikely(rc != 1)) {
+		dprintk(verbose, FE_ERROR, 1, "Read (0x%x) err, rc=[%d]",
+			state->config->tuner_address, rc);
+
+		return -EREMOTEIO;
+	}
+	if (unlikely(verbose > FE_DEBUG)) {
+		int i;
+
+		dprintk(verbose, FE_DEBUG, 1, "    Read from 0x%02x", state->config->tuner_address);
+		for (i = 0; i < STB6100_NUMREGS; i++)
+			dprintk(verbose, FE_DEBUG, 1, "        %s: 0x%02x", stb6100_regnames[i], regs[i]);
+	}
+	return 0;
+}
+
+static int stb6100_read_reg(struct stb6100_state *state, u8 reg)
+{
+	u8 regs[STB6100_NUMREGS];
+
+	struct i2c_msg msg = {
+		.addr	= state->config->tuner_address + reg,
+		.flags	= I2C_M_RD,
+		.buf	= regs,
+		.len	= 1
+	};
+
+	i2c_transfer(state->i2c, &msg, 1);
+
+	if (unlikely(reg >= STB6100_NUMREGS)) {
+		dprintk(verbose, FE_ERROR, 1, "Invalid register offset 0x%x", reg);
+		return -EINVAL;
+	}
+	if (unlikely(verbose > FE_DEBUG)) {
+		dprintk(verbose, FE_DEBUG, 1, "    Read from 0x%02x", state->config->tuner_address);
+		dprintk(verbose, FE_DEBUG, 1, "        %s: 0x%02x", stb6100_regnames[reg], regs[0]);
+	}
+
+	return (unsigned int)regs[0];
+}
+
+static int stb6100_write_reg_range(struct stb6100_state *state, u8 buf[], int start, int len)
+{
+	int rc;
+	u8 cmdbuf[len + 1];
+	struct i2c_msg msg = {
+		.addr	= state->config->tuner_address,
+		.flags	= 0,
+		.buf	= cmdbuf,
+		.len	= len + 1
+	};
+
+	if (unlikely(start < 1 || start + len > STB6100_NUMREGS)) {
+		dprintk(verbose, FE_ERROR, 1, "Invalid register range %d:%d",
+			start, len);
+		return -EINVAL;
+	}
+	memcpy(&cmdbuf[1], buf, len);
+	cmdbuf[0] = start;
+
+	if (unlikely(verbose > FE_DEBUG)) {
+		int i;
+
+		dprintk(verbose, FE_DEBUG, 1, "    Write @ 0x%02x: [%d:%d]", state->config->tuner_address, start, len);
+		for (i = 0; i < len; i++)
+			dprintk(verbose, FE_DEBUG, 1, "        %s: 0x%02x", stb6100_regnames[start + i], buf[i]);
+	}
+	rc = i2c_transfer(state->i2c, &msg, 1);
+	if (unlikely(rc != 1)) {
+		dprintk(verbose, FE_ERROR, 1, "(0x%x) write err [%d:%d], rc=[%d]",
+			(unsigned int)state->config->tuner_address, start, len,	rc);
+		return -EREMOTEIO;
+	}
+	return 0;
+}
+
+static int stb6100_write_reg(struct stb6100_state *state, u8 reg, u8 data)
+{
+	if (unlikely(reg >= STB6100_NUMREGS)) {
+		dprintk(verbose, FE_ERROR, 1, "Invalid register offset 0x%x", reg);
+		return -EREMOTEIO;
+	}
+	data = (data & stb6100_template[reg].mask) | stb6100_template[reg].set;
+	return stb6100_write_reg_range(state, &data, reg, 1);
+}
+
+
+static int stb6100_get_status(struct dvb_frontend *fe, u32 *status)
+{
+	int rc;
+	struct stb6100_state *state = fe->tuner_priv;
+
+	rc = stb6100_read_reg(state, STB6100_LD);
+	if (rc < 0) {
+		dprintk(verbose, FE_ERROR, 1, "%s failed", __func__);
+		return rc;
+	}
+	return (rc & STB6100_LD_LOCK) ? TUNER_STATUS_LOCKED : 0;
+}
+
+static int stb6100_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
+{
+	int rc;
+	u8 f;
+	struct stb6100_state *state = fe->tuner_priv;
+
+	rc = stb6100_read_reg(state, STB6100_F);
+	if (rc < 0)
+		return rc;
+	f = rc & STB6100_F_F;
+
+	state->status.bandwidth = (f + 5) * 2000;	/* x2 for ZIF	*/
+
+	*bandwidth = state->bandwidth = state->status.bandwidth * 1000;
+	dprintk(verbose, FE_DEBUG, 1, "bandwidth = %u Hz", state->bandwidth);
+	return 0;
+}
+
+static int stb6100_set_bandwidth(struct dvb_frontend *fe, u32 bandwidth)
+{
+	u32 tmp;
+	int rc;
+	struct stb6100_state *state = fe->tuner_priv;
+
+	dprintk(verbose, FE_DEBUG, 1, "set bandwidth to %u Hz", bandwidth);
+
+	bandwidth /= 2; /* ZIF */
+
+	if (bandwidth >= 36000000)	/* F[4:0] BW/2 max =31+5=36 mhz for F=31	*/
+		tmp = 31;
+	else if (bandwidth <= 5000000)	/* bw/2 min = 5Mhz for F=0			*/
+		tmp = 0;
+	else				/* if 5 < bw/2 < 36				*/
+		tmp = (bandwidth + 500000) / 1000000 - 5;
+
+	/* Turn on LPF bandwidth setting clock control,
+	 * set bandwidth, wait 10ms, turn off.
+	 */
+	rc = stb6100_write_reg(state, STB6100_FCCK, 0x0d | STB6100_FCCK_FCCK);
+	if (rc < 0)
+		return rc;
+	rc = stb6100_write_reg(state, STB6100_F, 0xc0 | tmp);
+	if (rc < 0)
+		return rc;
+
+	msleep(5);  /*  This is dangerous as another (related) thread may start */
+
+	rc = stb6100_write_reg(state, STB6100_FCCK, 0x0d);
+	if (rc < 0)
+		return rc;
+
+	msleep(10);  /*  This is dangerous as another (related) thread may start */
+
+	return 0;
+}
+
+static int stb6100_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+	int rc;
+	u32 nint, nfrac, fvco;
+	int psd2, odiv;
+	struct stb6100_state *state = fe->tuner_priv;
+	u8 regs[STB6100_NUMREGS];
+
+	rc = stb6100_read_regs(state, regs);
+	if (rc < 0)
+		return rc;
+
+	odiv = (regs[STB6100_VCO] & STB6100_VCO_ODIV) >> STB6100_VCO_ODIV_SHIFT;
+	psd2 = (regs[STB6100_K] & STB6100_K_PSD2) >> STB6100_K_PSD2_SHIFT;
+	nint = regs[STB6100_NI];
+	nfrac = ((regs[STB6100_K] & STB6100_K_NF_MSB) << 8) | regs[STB6100_NF_LSB];
+	fvco = (nfrac * state->reference >> (9 - psd2)) + (nint * state->reference << psd2);
+	*frequency = state->frequency = fvco >> (odiv + 1);
+
+	dprintk(verbose, FE_DEBUG, 1,
+		"frequency = %u kHz, odiv = %u, psd2 = %u, fxtal = %u kHz, fvco = %u kHz, N(I) = %u, N(F) = %u",
+		state->frequency, odiv, psd2, state->reference,	fvco, nint, nfrac);
+	return 0;
+}
+
+
+static int stb6100_set_frequency(struct dvb_frontend *fe, u32 frequency)
+{
+	int rc;
+	const struct stb6100_lkup *ptr;
+	struct stb6100_state *state = fe->tuner_priv;
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+
+	u32 srate = 0, fvco, nint, nfrac;
+	u8 regs[STB6100_NUMREGS];
+	u8 g, psd2, odiv;
+
+	dprintk(verbose, FE_DEBUG, 1, "Version 2010-8-14 13:51");
+
+	if (fe->ops.get_frontend) {
+		dprintk(verbose, FE_DEBUG, 1, "Get frontend parameters");
+		fe->ops.get_frontend(fe);
+	}
+	srate = p->symbol_rate;
+
+	/* Set up tuner cleanly, LPF calibration on */
+	rc = stb6100_write_reg(state, STB6100_FCCK, 0x4d | STB6100_FCCK_FCCK);
+	if (rc < 0)
+		return rc;  /* allow LPF calibration */
+
+	/* PLL Loop disabled, bias on, VCO on, synth on */
+	regs[STB6100_LPEN] = 0xeb;
+	rc = stb6100_write_reg(state, STB6100_LPEN, regs[STB6100_LPEN]);
+	if (rc < 0)
+		return rc;
+
+	/* Program the registers with their data values */
+
+	/* VCO divide ratio (LO divide ratio, VCO prescaler enable).	*/
+	if (frequency <= 1075000)
+		odiv = 1;
+	else
+		odiv = 0;
+
+	/* VCO enabled, search clock off as per LL3.7, 3.4.1 */
+	regs[STB6100_VCO] = 0xe0 | (odiv << STB6100_VCO_ODIV_SHIFT);
+
+	/* OSM	*/
+	for (ptr = lkup;
+	     (ptr->val_high != 0) && !CHKRANGE(frequency, ptr->val_low, ptr->val_high);
+	     ptr++);
+
+	if (ptr->val_high == 0) {
+		printk(KERN_ERR "%s: frequency out of range: %u kHz\n", __func__, frequency);
+		return -EINVAL;
+	}
+	regs[STB6100_VCO] = (regs[STB6100_VCO] & ~STB6100_VCO_OSM) | ptr->reg;
+	rc = stb6100_write_reg(state, STB6100_VCO, regs[STB6100_VCO]);
+	if (rc < 0)
+		return rc;
+
+	if ((frequency > 1075000) && (frequency <= 1325000))
+		psd2 = 0;
+	else
+		psd2 = 1;
+	/* F(VCO) = F(LO) * (ODIV == 0 ? 2 : 4)			*/
+	fvco = frequency << (1 + odiv);
+	/* N(I) = floor(f(VCO) / (f(XTAL) * (PSD2 ? 2 : 1)))	*/
+	nint = fvco / (state->reference << psd2);
+	/* N(F) = round(f(VCO) / f(XTAL) * (PSD2 ? 2 : 1) - N(I)) * 2 ^ 9	*/
+	nfrac = DIV_ROUND_CLOSEST((fvco - (nint * state->reference << psd2))
+					 << (9 - psd2), state->reference);
+
+	/* NI */
+	regs[STB6100_NI] = nint;
+	rc = stb6100_write_reg(state, STB6100_NI, regs[STB6100_NI]);
+	if (rc < 0)
+		return rc;
+
+	/* NF */
+	regs[STB6100_NF_LSB] = nfrac;
+	rc = stb6100_write_reg(state, STB6100_NF_LSB, regs[STB6100_NF_LSB]);
+	if (rc < 0)
+		return rc;
+
+	/* K */
+	regs[STB6100_K] = (0x38 & ~STB6100_K_PSD2) | (psd2 << STB6100_K_PSD2_SHIFT);
+	regs[STB6100_K] = (regs[STB6100_K] & ~STB6100_K_NF_MSB) | ((nfrac >> 8) & STB6100_K_NF_MSB);
+	rc = stb6100_write_reg(state, STB6100_K, regs[STB6100_K]);
+	if (rc < 0)
+		return rc;
+
+	/* G Baseband gain. */
+	if (srate >= 15000000)
+		g = 9;  /*  +4 dB */
+	else if (srate >= 5000000)
+		g = 11; /*  +8 dB */
+	else
+		g = 14; /* +14 dB */
+
+	regs[STB6100_G] = (0x10 & ~STB6100_G_G) | g;
+	regs[STB6100_G] &= ~STB6100_G_GCT; /* mask GCT */
+	regs[STB6100_G] |= (1 << 5); /* 2Vp-p Mode */
+	rc = stb6100_write_reg(state, STB6100_G, regs[STB6100_G]);
+	if (rc < 0)
+		return rc;
+
+	/* F we don't write as it is set up in BW set */
+
+	/* DLB set DC servo loop BW to 160Hz (LLA 3.8 / 2.1) */
+	regs[STB6100_DLB] = 0xcc;
+	rc = stb6100_write_reg(state, STB6100_DLB, regs[STB6100_DLB]);
+	if (rc < 0)
+		return rc;
+
+	dprintk(verbose, FE_DEBUG, 1,
+		"frequency = %u, srate = %u, g = %u, odiv = %u, psd2 = %u, fxtal = %u, osm = %u, fvco = %u, N(I) = %u, N(F) = %u",
+		frequency, srate, (unsigned int)g, (unsigned int)odiv,
+		(unsigned int)psd2, state->reference,
+		ptr->reg, fvco, nint, nfrac);
+
+	/* Set up the test registers */
+	regs[STB6100_TEST1] = 0x8f;
+	rc = stb6100_write_reg(state, STB6100_TEST1, regs[STB6100_TEST1]);
+	if (rc < 0)
+		return rc;
+	regs[STB6100_TEST3] = 0xde;
+	rc = stb6100_write_reg(state, STB6100_TEST3, regs[STB6100_TEST3]);
+	if (rc < 0)
+		return rc;
+
+	/* Bring up tuner according to LLA 3.7 3.4.1, step 2 */
+	regs[STB6100_LPEN] = 0xfb; /* PLL Loop enabled, bias on, VCO on, synth on */
+	rc = stb6100_write_reg(state, STB6100_LPEN, regs[STB6100_LPEN]);
+	if (rc < 0)
+		return rc;
+
+	msleep(2);
+
+	/* Bring up tuner according to LLA 3.7 3.4.1, step 3 */
+	regs[STB6100_VCO] &= ~STB6100_VCO_OCK;		/* VCO fast search		*/
+	rc = stb6100_write_reg(state, STB6100_VCO, regs[STB6100_VCO]);
+	if (rc < 0)
+		return rc;
+
+	msleep(10);  /*  This is dangerous as another (related) thread may start */ /* wait for LO to lock */
+
+	regs[STB6100_VCO] &= ~STB6100_VCO_OSCH;		/* vco search disabled		*/
+	regs[STB6100_VCO] |= STB6100_VCO_OCK;		/* search clock off		*/
+	rc = stb6100_write_reg(state, STB6100_VCO, regs[STB6100_VCO]);
+	if (rc < 0)
+		return rc;
+
+	rc = stb6100_write_reg(state, STB6100_FCCK, 0x0d);
+	if (rc < 0)
+		return rc;  /* Stop LPF calibration */
+
+	msleep(10);  /*  This is dangerous as another (related) thread may start */
+		     /* wait for stabilisation, (should not be necessary)		*/
+	return 0;
+}
+
+static int stb6100_sleep(struct dvb_frontend *fe)
+{
+	/* TODO: power down	*/
+	return 0;
+}
+
+static int stb6100_init(struct dvb_frontend *fe)
+{
+	struct stb6100_state *state = fe->tuner_priv;
+	struct tuner_state *status = &state->status;
+
+	status->tunerstep	= 125000;
+	status->ifreq		= 0;
+	status->refclock	= 27000000;	/* Hz	*/
+	status->iqsense		= 1;
+	status->bandwidth	= 36000;	/* kHz	*/
+	state->bandwidth	= status->bandwidth * 1000;	/* Hz	*/
+	state->reference	= status->refclock / 1000;	/* kHz	*/
+
+	/* Set default bandwidth. Modified, PN 13-May-10	*/
+	return 0;
+}
+
+static int stb6100_get_state(struct dvb_frontend *fe,
+			     enum tuner_param param,
+			     struct tuner_state *state)
+{
+	switch (param) {
+	case DVBFE_TUNER_FREQUENCY:
+		stb6100_get_frequency(fe, &state->frequency);
+		break;
+	case DVBFE_TUNER_TUNERSTEP:
+		break;
+	case DVBFE_TUNER_IFFREQ:
+		break;
+	case DVBFE_TUNER_BANDWIDTH:
+		stb6100_get_bandwidth(fe, &state->bandwidth);
+		break;
+	case DVBFE_TUNER_REFCLOCK:
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static int stb6100_set_state(struct dvb_frontend *fe,
+			     enum tuner_param param,
+			     struct tuner_state *state)
+{
+	struct stb6100_state *tstate = fe->tuner_priv;
+
+	switch (param) {
+	case DVBFE_TUNER_FREQUENCY:
+		stb6100_set_frequency(fe, state->frequency);
+		tstate->frequency = state->frequency;
+		break;
+	case DVBFE_TUNER_TUNERSTEP:
+		break;
+	case DVBFE_TUNER_IFFREQ:
+		break;
+	case DVBFE_TUNER_BANDWIDTH:
+		stb6100_set_bandwidth(fe, state->bandwidth);
+		tstate->bandwidth = state->bandwidth;
+		break;
+	case DVBFE_TUNER_REFCLOCK:
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static struct dvb_tuner_ops stb6100_ops = {
+	.info = {
+		.name			= "STB6100 Silicon Tuner",
+		.frequency_min		= 950000,
+		.frequency_max		= 2150000,
+		.frequency_step		= 0,
+	},
+
+	.init		= stb6100_init,
+	.sleep          = stb6100_sleep,
+	.get_status	= stb6100_get_status,
+	.get_state	= stb6100_get_state,
+	.set_state	= stb6100_set_state,
+	.release	= stb6100_release
+};
+
+struct dvb_frontend *stb6100_attach(struct dvb_frontend *fe,
+				    const struct stb6100_config *config,
+				    struct i2c_adapter *i2c)
+{
+	struct stb6100_state *state = NULL;
+
+	state = kzalloc(sizeof (struct stb6100_state), GFP_KERNEL);
+	if (state == NULL)
+		goto error;
+
+	state->config		= config;
+	state->i2c		= i2c;
+	state->frontend		= fe;
+	state->reference	= config->refclock / 1000; /* kHz */
+	fe->tuner_priv		= state;
+	fe->ops.tuner_ops	= stb6100_ops;
+
+	printk("%s: Attaching STB6100 \n", __func__);
+	return fe;
+
+error:
+	kfree(state);
+	return NULL;
+}
+
+static int stb6100_release(struct dvb_frontend *fe)
+{
+	struct stb6100_state *state = fe->tuner_priv;
+
+	fe->tuner_priv = NULL;
+	kfree(state);
+
+	return 0;
+}
+
+EXPORT_SYMBOL(stb6100_attach);
+MODULE_PARM_DESC(verbose, "Set Verbosity level");
+
+MODULE_AUTHOR("Manu Abraham");
+MODULE_DESCRIPTION("STB6100 Silicon tuner");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb-frontends/stb6100.h b/drivers/media/dvb-frontends/stb6100.h
new file mode 100644
index 0000000..2ab0966
--- /dev/null
+++ b/drivers/media/dvb-frontends/stb6100.h
@@ -0,0 +1,115 @@
+/*
+	STB6100 Silicon Tuner
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	Copyright (C) ST Microelectronics
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the 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 __STB_6100_REG_H
+#define __STB_6100_REG_H
+
+#include <linux/dvb/frontend.h>
+#include "dvb_frontend.h"
+
+#define STB6100_LD			0x00
+#define STB6100_LD_LOCK			(1 << 0)
+
+#define STB6100_VCO			0x01
+#define STB6100_VCO_OSCH		(0x01 << 7)
+#define STB6100_VCO_OSCH_SHIFT		7
+#define STB6100_VCO_OCK			(0x03 << 5)
+#define STB6100_VCO_OCK_SHIFT		5
+#define STB6100_VCO_ODIV		(0x01 << 4)
+#define STB6100_VCO_ODIV_SHIFT		4
+#define STB6100_VCO_OSM			(0x0f << 0)
+
+#define STB6100_NI			0x02
+#define STB6100_NF_LSB			0x03
+
+#define STB6100_K			0x04
+#define STB6100_K_PSD2			(0x01 << 2)
+#define STB6100_K_PSD2_SHIFT            2
+#define STB6100_K_NF_MSB		(0x03 << 0)
+
+#define STB6100_G			0x05
+#define STB6100_G_G			(0x0f << 0)
+#define STB6100_G_GCT			(0x07 << 5)
+
+#define STB6100_F			0x06
+#define STB6100_F_F			(0x1f << 0)
+
+#define STB6100_DLB			0x07
+
+#define STB6100_TEST1			0x08
+
+#define STB6100_FCCK			0x09
+#define STB6100_FCCK_FCCK		(0x01 << 6)
+
+#define STB6100_LPEN			0x0a
+#define STB6100_LPEN_LPEN		(0x01 << 4)
+#define STB6100_LPEN_SYNP		(0x01 << 5)
+#define STB6100_LPEN_OSCP		(0x01 << 6)
+#define STB6100_LPEN_BEN		(0x01 << 7)
+
+#define STB6100_TEST3			0x0b
+
+#define STB6100_NUMREGS                 0x0c
+
+
+#define INRANGE(val, x, y)		(((x <= val) && (val <= y)) ||		\
+					 ((y <= val) && (val <= x)) ? 1 : 0)
+
+#define CHKRANGE(val, x, y)		(((val >= x) && (val < y)) ? 1 : 0)
+
+struct stb6100_config {
+	u8	tuner_address;
+	u32	refclock;
+};
+
+struct stb6100_state {
+	struct i2c_adapter *i2c;
+
+	const struct stb6100_config	*config;
+	struct dvb_tuner_ops		ops;
+	struct dvb_frontend		*frontend;
+	struct tuner_state		status;
+
+	u32 frequency;
+	u32 srate;
+	u32 bandwidth;
+	u32 reference;
+};
+
+#if defined(CONFIG_DVB_STB6100) || (defined(CONFIG_DVB_STB6100_MODULE) && defined(MODULE))
+
+extern struct dvb_frontend *stb6100_attach(struct dvb_frontend *fe,
+					   const struct stb6100_config *config,
+					   struct i2c_adapter *i2c);
+
+#else
+
+static inline struct dvb_frontend *stb6100_attach(struct dvb_frontend *fe,
+						  const struct stb6100_config *config,
+						  struct i2c_adapter *i2c)
+{
+	printk(KERN_WARNING "%s: Driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+
+#endif //CONFIG_DVB_STB6100
+
+#endif
diff --git a/drivers/media/dvb-frontends/stb6100_cfg.h b/drivers/media/dvb-frontends/stb6100_cfg.h
new file mode 100644
index 0000000..6314d18
--- /dev/null
+++ b/drivers/media/dvb-frontends/stb6100_cfg.h
@@ -0,0 +1,104 @@
+/*
+	STB6100 Silicon Tuner
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	Copyright (C) ST Microelectronics
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the 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.
+*/
+
+static int stb6100_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+	struct dvb_frontend_ops	*frontend_ops = NULL;
+	struct dvb_tuner_ops	*tuner_ops = NULL;
+	struct tuner_state	t_state;
+	int err = 0;
+
+	if (&fe->ops)
+		frontend_ops = &fe->ops;
+	if (&frontend_ops->tuner_ops)
+		tuner_ops = &frontend_ops->tuner_ops;
+	if (tuner_ops->get_state) {
+		if ((err = tuner_ops->get_state(fe, DVBFE_TUNER_FREQUENCY, &t_state)) < 0) {
+			printk("%s: Invalid parameter\n", __func__);
+			return err;
+		}
+		*frequency = t_state.frequency;
+	}
+	return 0;
+}
+
+static int stb6100_set_frequency(struct dvb_frontend *fe, u32 frequency)
+{
+	struct dvb_frontend_ops	*frontend_ops = NULL;
+	struct dvb_tuner_ops	*tuner_ops = NULL;
+	struct tuner_state	t_state;
+	int err = 0;
+
+	t_state.frequency = frequency;
+	if (&fe->ops)
+		frontend_ops = &fe->ops;
+	if (&frontend_ops->tuner_ops)
+		tuner_ops = &frontend_ops->tuner_ops;
+	if (tuner_ops->set_state) {
+		if ((err = tuner_ops->set_state(fe, DVBFE_TUNER_FREQUENCY, &t_state)) < 0) {
+			printk("%s: Invalid parameter\n", __func__);
+			return err;
+		}
+	}
+	return 0;
+}
+
+static int stb6100_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
+{
+	struct dvb_frontend_ops	*frontend_ops = &fe->ops;
+	struct dvb_tuner_ops	*tuner_ops = &frontend_ops->tuner_ops;
+	struct tuner_state	t_state;
+	int err = 0;
+
+	if (&fe->ops)
+		frontend_ops = &fe->ops;
+	if (&frontend_ops->tuner_ops)
+		tuner_ops = &frontend_ops->tuner_ops;
+	if (tuner_ops->get_state) {
+		if ((err = tuner_ops->get_state(fe, DVBFE_TUNER_BANDWIDTH, &t_state)) < 0) {
+			printk("%s: Invalid parameter\n", __func__);
+			return err;
+		}
+		*bandwidth = t_state.bandwidth;
+	}
+	return 0;
+}
+
+static int stb6100_set_bandwidth(struct dvb_frontend *fe, u32 bandwidth)
+{
+	struct dvb_frontend_ops	*frontend_ops = NULL;
+	struct dvb_tuner_ops	*tuner_ops = NULL;
+	struct tuner_state	t_state;
+	int err = 0;
+
+	t_state.bandwidth = bandwidth;
+	if (&fe->ops)
+		frontend_ops = &fe->ops;
+	if (&frontend_ops->tuner_ops)
+		tuner_ops = &frontend_ops->tuner_ops;
+	if (tuner_ops->set_state) {
+		if ((err = tuner_ops->set_state(fe, DVBFE_TUNER_BANDWIDTH, &t_state)) < 0) {
+			printk("%s: Invalid parameter\n", __func__);
+			return err;
+		}
+	}
+	return 0;
+}
diff --git a/drivers/media/dvb-frontends/stb6100_proc.h b/drivers/media/dvb-frontends/stb6100_proc.h
new file mode 100644
index 0000000..112163a
--- /dev/null
+++ b/drivers/media/dvb-frontends/stb6100_proc.h
@@ -0,0 +1,138 @@
+/*
+	STB6100 Silicon Tuner wrapper
+	Copyright (C)2009 Igor M. Liplianin (liplianin@me.by)
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the 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.
+*/
+
+static int stb6100_get_freq(struct dvb_frontend *fe, u32 *frequency)
+{
+	struct dvb_frontend_ops	*frontend_ops = NULL;
+	struct dvb_tuner_ops	*tuner_ops = NULL;
+	struct tuner_state	state;
+	int err = 0;
+
+	if (&fe->ops)
+		frontend_ops = &fe->ops;
+	if (&frontend_ops->tuner_ops)
+		tuner_ops = &frontend_ops->tuner_ops;
+	if (tuner_ops->get_state) {
+		if (frontend_ops->i2c_gate_ctrl)
+			frontend_ops->i2c_gate_ctrl(fe, 1);
+
+		err = tuner_ops->get_state(fe, DVBFE_TUNER_FREQUENCY, &state);
+		if (err < 0) {
+			printk(KERN_ERR "%s: Invalid parameter\n", __func__);
+			return err;
+		}
+
+		if (frontend_ops->i2c_gate_ctrl)
+			frontend_ops->i2c_gate_ctrl(fe, 0);
+
+		*frequency = state.frequency;
+	}
+
+	return 0;
+}
+
+static int stb6100_set_freq(struct dvb_frontend *fe, u32 frequency)
+{
+	struct dvb_frontend_ops	*frontend_ops = NULL;
+	struct dvb_tuner_ops	*tuner_ops = NULL;
+	struct tuner_state	state;
+	int err = 0;
+
+	state.frequency = frequency;
+	if (&fe->ops)
+		frontend_ops = &fe->ops;
+	if (&frontend_ops->tuner_ops)
+		tuner_ops = &frontend_ops->tuner_ops;
+	if (tuner_ops->set_state) {
+		if (frontend_ops->i2c_gate_ctrl)
+			frontend_ops->i2c_gate_ctrl(fe, 1);
+
+		err = tuner_ops->set_state(fe, DVBFE_TUNER_FREQUENCY, &state);
+		if (err < 0) {
+			printk(KERN_ERR "%s: Invalid parameter\n", __func__);
+			return err;
+		}
+
+		if (frontend_ops->i2c_gate_ctrl)
+			frontend_ops->i2c_gate_ctrl(fe, 0);
+
+	}
+
+	return 0;
+}
+
+static int stb6100_get_bandw(struct dvb_frontend *fe, u32 *bandwidth)
+{
+	struct dvb_frontend_ops	*frontend_ops = NULL;
+	struct dvb_tuner_ops	*tuner_ops = NULL;
+	struct tuner_state	state;
+	int err = 0;
+
+	if (&fe->ops)
+		frontend_ops = &fe->ops;
+	if (&frontend_ops->tuner_ops)
+		tuner_ops = &frontend_ops->tuner_ops;
+	if (tuner_ops->get_state) {
+		if (frontend_ops->i2c_gate_ctrl)
+			frontend_ops->i2c_gate_ctrl(fe, 1);
+
+		err = tuner_ops->get_state(fe, DVBFE_TUNER_BANDWIDTH, &state);
+		if (err < 0) {
+			printk(KERN_ERR "%s: Invalid parameter\n", __func__);
+			return err;
+		}
+
+		if (frontend_ops->i2c_gate_ctrl)
+			frontend_ops->i2c_gate_ctrl(fe, 0);
+
+		*bandwidth = state.bandwidth;
+	}
+
+	return 0;
+}
+
+static int stb6100_set_bandw(struct dvb_frontend *fe, u32 bandwidth)
+{
+	struct dvb_frontend_ops	*frontend_ops = NULL;
+	struct dvb_tuner_ops	*tuner_ops = NULL;
+	struct tuner_state	state;
+	int err = 0;
+
+	state.bandwidth = bandwidth;
+	if (&fe->ops)
+		frontend_ops = &fe->ops;
+	if (&frontend_ops->tuner_ops)
+		tuner_ops = &frontend_ops->tuner_ops;
+	if (tuner_ops->set_state) {
+		if (frontend_ops->i2c_gate_ctrl)
+			frontend_ops->i2c_gate_ctrl(fe, 1);
+
+		err = tuner_ops->set_state(fe, DVBFE_TUNER_BANDWIDTH, &state);
+		if (err < 0) {
+			printk(KERN_ERR "%s: Invalid parameter\n", __func__);
+			return err;
+		}
+
+		if (frontend_ops->i2c_gate_ctrl)
+			frontend_ops->i2c_gate_ctrl(fe, 0);
+
+	}
+
+	return 0;
+}
diff --git a/drivers/media/dvb-frontends/stv0288.c b/drivers/media/dvb-frontends/stv0288.c
new file mode 100644
index 0000000..632b251
--- /dev/null
+++ b/drivers/media/dvb-frontends/stv0288.c
@@ -0,0 +1,626 @@
+/*
+	Driver for ST STV0288 demodulator
+	Copyright (C) 2006 Georg Acher, BayCom GmbH, acher (at) baycom (dot) de
+		for Reel Multimedia
+	Copyright (C) 2008 TurboSight.com, Bob Liu <bob@turbosight.com>
+	Copyright (C) 2008 Igor M. Liplianin <liplianin@me.by>
+		Removed stb6000 specific tuner code and revised some
+		procedures.
+	2010-09-01 Josef Pavlik <josef@pavlik.it>
+		Fixed diseqc_msg, diseqc_burst and set_tone problems
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the 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/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <asm/div64.h>
+
+#include "dvb_frontend.h"
+#include "stv0288.h"
+
+struct stv0288_state {
+	struct i2c_adapter *i2c;
+	const struct stv0288_config *config;
+	struct dvb_frontend frontend;
+
+	u8 initialised:1;
+	u32 tuner_frequency;
+	u32 symbol_rate;
+	fe_code_rate_t fec_inner;
+	int errmode;
+};
+
+#define STATUS_BER 0
+#define STATUS_UCBLOCKS 1
+
+static int debug;
+static int debug_legacy_dish_switch;
+#define dprintk(args...) \
+	do { \
+		if (debug) \
+			printk(KERN_DEBUG "stv0288: " args); \
+	} while (0)
+
+
+static int stv0288_writeregI(struct stv0288_state *state, u8 reg, u8 data)
+{
+	int ret;
+	u8 buf[] = { reg, data };
+	struct i2c_msg msg = {
+		.addr = state->config->demod_address,
+		.flags = 0,
+		.buf = buf,
+		.len = 2
+	};
+
+	ret = i2c_transfer(state->i2c, &msg, 1);
+
+	if (ret != 1)
+		dprintk("%s: writereg error (reg == 0x%02x, val == 0x%02x, "
+			"ret == %i)\n", __func__, reg, data, ret);
+
+	return (ret != 1) ? -EREMOTEIO : 0;
+}
+
+static int stv0288_write(struct dvb_frontend *fe, const u8 buf[], int len)
+{
+	struct stv0288_state *state = fe->demodulator_priv;
+
+	if (len != 2)
+		return -EINVAL;
+
+	return stv0288_writeregI(state, buf[0], buf[1]);
+}
+
+static u8 stv0288_readreg(struct stv0288_state *state, u8 reg)
+{
+	int ret;
+	u8 b0[] = { reg };
+	u8 b1[] = { 0 };
+	struct i2c_msg msg[] = {
+		{
+			.addr = state->config->demod_address,
+			.flags = 0,
+			.buf = b0,
+			.len = 1
+		}, {
+			.addr = state->config->demod_address,
+			.flags = I2C_M_RD,
+			.buf = b1,
+			.len = 1
+		}
+	};
+
+	ret = i2c_transfer(state->i2c, msg, 2);
+
+	if (ret != 2)
+		dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n",
+				__func__, reg, ret);
+
+	return b1[0];
+}
+
+static int stv0288_set_symbolrate(struct dvb_frontend *fe, u32 srate)
+{
+	struct stv0288_state *state = fe->demodulator_priv;
+	unsigned int temp;
+	unsigned char b[3];
+
+	if ((srate < 1000000) || (srate > 45000000))
+		return -EINVAL;
+
+	stv0288_writeregI(state, 0x22, 0);
+	stv0288_writeregI(state, 0x23, 0);
+	stv0288_writeregI(state, 0x2b, 0xff);
+	stv0288_writeregI(state, 0x2c, 0xf7);
+
+	temp = (unsigned int)srate / 1000;
+
+		temp = temp * 32768;
+		temp = temp / 25;
+		temp = temp / 125;
+		b[0] = (unsigned char)((temp >> 12) & 0xff);
+		b[1] = (unsigned char)((temp >> 4) & 0xff);
+		b[2] = (unsigned char)((temp << 4) & 0xf0);
+		stv0288_writeregI(state, 0x28, 0x80); /* SFRH */
+		stv0288_writeregI(state, 0x29, 0); /* SFRM */
+		stv0288_writeregI(state, 0x2a, 0); /* SFRL */
+
+		stv0288_writeregI(state, 0x28, b[0]);
+		stv0288_writeregI(state, 0x29, b[1]);
+		stv0288_writeregI(state, 0x2a, b[2]);
+		dprintk("stv0288: stv0288_set_symbolrate\n");
+
+	return 0;
+}
+
+static int stv0288_send_diseqc_msg(struct dvb_frontend *fe,
+				    struct dvb_diseqc_master_cmd *m)
+{
+	struct stv0288_state *state = fe->demodulator_priv;
+
+	int i;
+
+	dprintk("%s\n", __func__);
+
+	stv0288_writeregI(state, 0x09, 0);
+	msleep(30);
+	stv0288_writeregI(state, 0x05, 0x12);/* modulated mode, single shot */
+
+	for (i = 0; i < m->msg_len; i++) {
+		if (stv0288_writeregI(state, 0x06, m->msg[i]))
+			return -EREMOTEIO;
+	}
+	msleep(m->msg_len*12);
+	return 0;
+}
+
+static int stv0288_send_diseqc_burst(struct dvb_frontend *fe,
+						fe_sec_mini_cmd_t burst)
+{
+	struct stv0288_state *state = fe->demodulator_priv;
+
+	dprintk("%s\n", __func__);
+
+	if (stv0288_writeregI(state, 0x05, 0x03))/* burst mode, single shot */
+		return -EREMOTEIO;
+
+	if (stv0288_writeregI(state, 0x06, burst == SEC_MINI_A ? 0x00 : 0xff))
+		return -EREMOTEIO;
+
+	msleep(15);
+	if (stv0288_writeregI(state, 0x05, 0x12))
+		return -EREMOTEIO;
+
+	return 0;
+}
+
+static int stv0288_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
+{
+	struct stv0288_state *state = fe->demodulator_priv;
+
+	switch (tone) {
+	case SEC_TONE_ON:
+		if (stv0288_writeregI(state, 0x05, 0x10))/* cont carrier */
+			return -EREMOTEIO;
+	break;
+
+	case SEC_TONE_OFF:
+		if (stv0288_writeregI(state, 0x05, 0x12))/* burst mode off*/
+			return -EREMOTEIO;
+	break;
+
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static u8 stv0288_inittab[] = {
+	0x01, 0x15,
+	0x02, 0x20,
+	0x09, 0x0,
+	0x0a, 0x4,
+	0x0b, 0x0,
+	0x0c, 0x0,
+	0x0d, 0x0,
+	0x0e, 0xd4,
+	0x0f, 0x30,
+	0x11, 0x80,
+	0x12, 0x03,
+	0x13, 0x48,
+	0x14, 0x84,
+	0x15, 0x45,
+	0x16, 0xb7,
+	0x17, 0x9c,
+	0x18, 0x0,
+	0x19, 0xa6,
+	0x1a, 0x88,
+	0x1b, 0x8f,
+	0x1c, 0xf0,
+	0x20, 0x0b,
+	0x21, 0x54,
+	0x22, 0x0,
+	0x23, 0x0,
+	0x2b, 0xff,
+	0x2c, 0xf7,
+	0x30, 0x0,
+	0x31, 0x1e,
+	0x32, 0x14,
+	0x33, 0x0f,
+	0x34, 0x09,
+	0x35, 0x0c,
+	0x36, 0x05,
+	0x37, 0x2f,
+	0x38, 0x16,
+	0x39, 0xbe,
+	0x3a, 0x0,
+	0x3b, 0x13,
+	0x3c, 0x11,
+	0x3d, 0x30,
+	0x40, 0x63,
+	0x41, 0x04,
+	0x42, 0x20,
+	0x43, 0x00,
+	0x44, 0x00,
+	0x45, 0x00,
+	0x46, 0x00,
+	0x47, 0x00,
+	0x4a, 0x00,
+	0x50, 0x10,
+	0x51, 0x38,
+	0x52, 0x21,
+	0x58, 0x54,
+	0x59, 0x86,
+	0x5a, 0x0,
+	0x5b, 0x9b,
+	0x5c, 0x08,
+	0x5d, 0x7f,
+	0x5e, 0x0,
+	0x5f, 0xff,
+	0x70, 0x0,
+	0x71, 0x0,
+	0x72, 0x0,
+	0x74, 0x0,
+	0x75, 0x0,
+	0x76, 0x0,
+	0x81, 0x0,
+	0x82, 0x3f,
+	0x83, 0x3f,
+	0x84, 0x0,
+	0x85, 0x0,
+	0x88, 0x0,
+	0x89, 0x0,
+	0x8a, 0x0,
+	0x8b, 0x0,
+	0x8c, 0x0,
+	0x90, 0x0,
+	0x91, 0x0,
+	0x92, 0x0,
+	0x93, 0x0,
+	0x94, 0x1c,
+	0x97, 0x0,
+	0xa0, 0x48,
+	0xa1, 0x0,
+	0xb0, 0xb8,
+	0xb1, 0x3a,
+	0xb2, 0x10,
+	0xb3, 0x82,
+	0xb4, 0x80,
+	0xb5, 0x82,
+	0xb6, 0x82,
+	0xb7, 0x82,
+	0xb8, 0x20,
+	0xb9, 0x0,
+	0xf0, 0x0,
+	0xf1, 0x0,
+	0xf2, 0xc0,
+	0x51, 0x36,
+	0x52, 0x09,
+	0x53, 0x94,
+	0x54, 0x62,
+	0x55, 0x29,
+	0x56, 0x64,
+	0x57, 0x2b,
+	0xff, 0xff,
+};
+
+static int stv0288_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t volt)
+{
+	dprintk("%s: %s\n", __func__,
+		volt == SEC_VOLTAGE_13 ? "SEC_VOLTAGE_13" :
+		volt == SEC_VOLTAGE_18 ? "SEC_VOLTAGE_18" : "??");
+
+	return 0;
+}
+
+static int stv0288_init(struct dvb_frontend *fe)
+{
+	struct stv0288_state *state = fe->demodulator_priv;
+	int i;
+	u8 reg;
+	u8 val;
+
+	dprintk("stv0288: init chip\n");
+	stv0288_writeregI(state, 0x41, 0x04);
+	msleep(50);
+
+	/* we have default inittab */
+	if (state->config->inittab == NULL) {
+		for (i = 0; !(stv0288_inittab[i] == 0xff &&
+				stv0288_inittab[i + 1] == 0xff); i += 2)
+			stv0288_writeregI(state, stv0288_inittab[i],
+					stv0288_inittab[i + 1]);
+	} else {
+		for (i = 0; ; i += 2)  {
+			reg = state->config->inittab[i];
+			val = state->config->inittab[i+1];
+			if (reg == 0xff && val == 0xff)
+				break;
+			stv0288_writeregI(state, reg, val);
+		}
+	}
+	return 0;
+}
+
+static int stv0288_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+	struct stv0288_state *state = fe->demodulator_priv;
+
+	u8 sync = stv0288_readreg(state, 0x24);
+	if (sync == 255)
+		sync = 0;
+
+	dprintk("%s : FE_READ_STATUS : VSTATUS: 0x%02x\n", __func__, sync);
+
+	*status = 0;
+	if (sync & 0x80)
+		*status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
+	if (sync & 0x10)
+		*status |= FE_HAS_VITERBI;
+	if (sync & 0x08) {
+		*status |= FE_HAS_LOCK;
+		dprintk("stv0288 has locked\n");
+	}
+
+	return 0;
+}
+
+static int stv0288_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+	struct stv0288_state *state = fe->demodulator_priv;
+
+	if (state->errmode != STATUS_BER)
+		return 0;
+	*ber = (stv0288_readreg(state, 0x26) << 8) |
+					stv0288_readreg(state, 0x27);
+	dprintk("stv0288_read_ber %d\n", *ber);
+
+	return 0;
+}
+
+
+static int stv0288_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
+{
+	struct stv0288_state *state = fe->demodulator_priv;
+
+	s32 signal =  0xffff - ((stv0288_readreg(state, 0x10) << 8));
+
+
+	signal = signal * 5 / 4;
+	*strength = (signal > 0xffff) ? 0xffff : (signal < 0) ? 0 : signal;
+	dprintk("stv0288_read_signal_strength %d\n", *strength);
+
+	return 0;
+}
+static int stv0288_sleep(struct dvb_frontend *fe)
+{
+	struct stv0288_state *state = fe->demodulator_priv;
+
+	stv0288_writeregI(state, 0x41, 0x84);
+	state->initialised = 0;
+
+	return 0;
+}
+static int stv0288_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+	struct stv0288_state *state = fe->demodulator_priv;
+
+	s32 xsnr = 0xffff - ((stv0288_readreg(state, 0x2d) << 8)
+			   | stv0288_readreg(state, 0x2e));
+	xsnr = 3 * (xsnr - 0xa100);
+	*snr = (xsnr > 0xffff) ? 0xffff : (xsnr < 0) ? 0 : xsnr;
+	dprintk("stv0288_read_snr %d\n", *snr);
+
+	return 0;
+}
+
+static int stv0288_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+	struct stv0288_state *state = fe->demodulator_priv;
+
+	if (state->errmode != STATUS_BER)
+		return 0;
+	*ucblocks = (stv0288_readreg(state, 0x26) << 8) |
+					stv0288_readreg(state, 0x27);
+	dprintk("stv0288_read_ber %d\n", *ucblocks);
+
+	return 0;
+}
+
+static int stv0288_set_property(struct dvb_frontend *fe, struct dtv_property *p)
+{
+	dprintk("%s(..)\n", __func__);
+	return 0;
+}
+
+static int stv0288_set_frontend(struct dvb_frontend *fe)
+{
+	struct stv0288_state *state = fe->demodulator_priv;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+
+	char tm;
+	unsigned char tda[3];
+	u8 reg, time_out = 0;
+
+	dprintk("%s : FE_SET_FRONTEND\n", __func__);
+
+	if (c->delivery_system != SYS_DVBS) {
+			dprintk("%s: unsupported delivery "
+				"system selected (%d)\n",
+				__func__, c->delivery_system);
+			return -EOPNOTSUPP;
+	}
+
+	if (state->config->set_ts_params)
+		state->config->set_ts_params(fe, 0);
+
+	/* only frequency & symbol_rate are used for tuner*/
+	if (fe->ops.tuner_ops.set_params) {
+		fe->ops.tuner_ops.set_params(fe);
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 0);
+	}
+
+	udelay(10);
+	stv0288_set_symbolrate(fe, c->symbol_rate);
+	/* Carrier lock control register */
+	stv0288_writeregI(state, 0x15, 0xc5);
+
+	tda[2] = 0x0; /* CFRL */
+	for (tm = -9; tm < 7;) {
+		/* Viterbi status */
+		reg = stv0288_readreg(state, 0x24);
+		if (reg & 0x8)
+				break;
+		if (reg & 0x80) {
+			time_out++;
+			if (time_out > 10)
+				break;
+			tda[2] += 40;
+			if (tda[2] < 40)
+				tm++;
+		} else {
+			tm++;
+			tda[2] = 0;
+			time_out = 0;
+		}
+		tda[1] = (unsigned char)tm;
+		stv0288_writeregI(state, 0x2b, tda[1]);
+		stv0288_writeregI(state, 0x2c, tda[2]);
+		msleep(30);
+	}
+	state->tuner_frequency = c->frequency;
+	state->fec_inner = FEC_AUTO;
+	state->symbol_rate = c->symbol_rate;
+
+	return 0;
+}
+
+static int stv0288_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+	struct stv0288_state *state = fe->demodulator_priv;
+
+	if (enable)
+		stv0288_writeregI(state, 0x01, 0xb5);
+	else
+		stv0288_writeregI(state, 0x01, 0x35);
+
+	udelay(1);
+
+	return 0;
+}
+
+static void stv0288_release(struct dvb_frontend *fe)
+{
+	struct stv0288_state *state = fe->demodulator_priv;
+	kfree(state);
+}
+
+static struct dvb_frontend_ops stv0288_ops = {
+	.delsys = { SYS_DVBS },
+	.info = {
+		.name			= "ST STV0288 DVB-S",
+		.frequency_min		= 950000,
+		.frequency_max		= 2150000,
+		.frequency_stepsize	= 1000,	 /* kHz for QPSK frontends */
+		.frequency_tolerance	= 0,
+		.symbol_rate_min	= 1000000,
+		.symbol_rate_max	= 45000000,
+		.symbol_rate_tolerance	= 500,	/* ppm */
+		.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_FEC_AUTO
+	},
+
+	.release = stv0288_release,
+	.init = stv0288_init,
+	.sleep = stv0288_sleep,
+	.write = stv0288_write,
+	.i2c_gate_ctrl = stv0288_i2c_gate_ctrl,
+	.read_status = stv0288_read_status,
+	.read_ber = stv0288_read_ber,
+	.read_signal_strength = stv0288_read_signal_strength,
+	.read_snr = stv0288_read_snr,
+	.read_ucblocks = stv0288_read_ucblocks,
+	.diseqc_send_master_cmd = stv0288_send_diseqc_msg,
+	.diseqc_send_burst = stv0288_send_diseqc_burst,
+	.set_tone = stv0288_set_tone,
+	.set_voltage = stv0288_set_voltage,
+
+	.set_property = stv0288_set_property,
+	.set_frontend = stv0288_set_frontend,
+};
+
+struct dvb_frontend *stv0288_attach(const struct stv0288_config *config,
+				    struct i2c_adapter *i2c)
+{
+	struct stv0288_state *state = NULL;
+	int id;
+
+	/* allocate memory for the internal state */
+	state = kzalloc(sizeof(struct stv0288_state), GFP_KERNEL);
+	if (state == NULL)
+		goto error;
+
+	/* setup the state */
+	state->config = config;
+	state->i2c = i2c;
+	state->initialised = 0;
+	state->tuner_frequency = 0;
+	state->symbol_rate = 0;
+	state->fec_inner = 0;
+	state->errmode = STATUS_BER;
+
+	stv0288_writeregI(state, 0x41, 0x04);
+	msleep(200);
+	id = stv0288_readreg(state, 0x00);
+	dprintk("stv0288 id %x\n", id);
+
+	/* register 0x00 contains 0x11 for STV0288  */
+	if (id != 0x11)
+		goto error;
+
+	/* create dvb_frontend */
+	memcpy(&state->frontend.ops, &stv0288_ops,
+			sizeof(struct dvb_frontend_ops));
+	state->frontend.demodulator_priv = state;
+	return &state->frontend;
+
+error:
+	kfree(state);
+
+	return NULL;
+}
+EXPORT_SYMBOL(stv0288_attach);
+
+module_param(debug_legacy_dish_switch, int, 0444);
+MODULE_PARM_DESC(debug_legacy_dish_switch,
+		"Enable timing analysis for Dish Network legacy switches");
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+
+MODULE_DESCRIPTION("ST STV0288 DVB Demodulator driver");
+MODULE_AUTHOR("Georg Acher, Bob Liu, Igor liplianin");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/media/dvb-frontends/stv0288.h b/drivers/media/dvb-frontends/stv0288.h
new file mode 100644
index 0000000..f2b53db
--- /dev/null
+++ b/drivers/media/dvb-frontends/stv0288.h
@@ -0,0 +1,67 @@
+/*
+	Driver for ST STV0288 demodulator
+
+	Copyright (C) 2006 Georg Acher, BayCom GmbH, acher (at) baycom (dot) de
+		for Reel Multimedia
+	Copyright (C) 2008 TurboSight.com, <bob@turbosight.com>
+	Copyright (C) 2008 Igor M. Liplianin <liplianin@me.by>
+		Removed stb6000 specific tuner code and revised some
+		procedures.
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the 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 STV0288_H
+#define STV0288_H
+
+#include <linux/dvb/frontend.h>
+#include "dvb_frontend.h"
+
+struct stv0288_config {
+	/* the demodulator's i2c address */
+	u8 demod_address;
+
+	u8* inittab;
+
+	/* minimum delay before retuning */
+	int min_delay_ms;
+
+	int (*set_ts_params)(struct dvb_frontend *fe, int is_punctured);
+};
+
+#if defined(CONFIG_DVB_STV0288) || (defined(CONFIG_DVB_STV0288_MODULE) && \
+							defined(MODULE))
+extern struct dvb_frontend *stv0288_attach(const struct stv0288_config *config,
+					   struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend *stv0288_attach(const struct stv0288_config *config,
+					   struct i2c_adapter *i2c)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif /* CONFIG_DVB_STV0288 */
+
+static inline int stv0288_writereg(struct dvb_frontend *fe, u8 reg, u8 val)
+{
+	int r = 0;
+	u8 buf[] = { reg, val };
+	if (fe->ops.write)
+		r = fe->ops.write(fe, buf, 2);
+	return r;
+}
+
+#endif /* STV0288_H */
diff --git a/drivers/media/dvb-frontends/stv0297.c b/drivers/media/dvb-frontends/stv0297.c
new file mode 100644
index 0000000..d40f226
--- /dev/null
+++ b/drivers/media/dvb-frontends/stv0297.c
@@ -0,0 +1,722 @@
+/*
+    Driver for STV0297 demodulator
+
+    Copyright (C) 2004 Andrew de Quincey <adq_dvb@lidskialf.net>
+    Copyright (C) 2003-2004 Dennis Noermann <dennis.noermann@noernet.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/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/jiffies.h>
+#include <linux/slab.h>
+
+#include "dvb_frontend.h"
+#include "stv0297.h"
+
+struct stv0297_state {
+	struct i2c_adapter *i2c;
+	const struct stv0297_config *config;
+	struct dvb_frontend frontend;
+
+	unsigned long last_ber;
+	unsigned long base_freq;
+};
+
+#if 1
+#define dprintk(x...) printk(x)
+#else
+#define dprintk(x...)
+#endif
+
+#define STV0297_CLOCK_KHZ   28900
+
+
+static int stv0297_writereg(struct stv0297_state *state, u8 reg, u8 data)
+{
+	int ret;
+	u8 buf[] = { reg, data };
+	struct i2c_msg msg = {.addr = state->config->demod_address,.flags = 0,.buf = buf,.len = 2 };
+
+	ret = i2c_transfer(state->i2c, &msg, 1);
+
+	if (ret != 1)
+		dprintk("%s: writereg error (reg == 0x%02x, val == 0x%02x, "
+			"ret == %i)\n", __func__, reg, data, ret);
+
+	return (ret != 1) ? -1 : 0;
+}
+
+static int stv0297_readreg(struct stv0297_state *state, u8 reg)
+{
+	int ret;
+	u8 b0[] = { reg };
+	u8 b1[] = { 0 };
+	struct i2c_msg msg[] = { {.addr = state->config->demod_address,.flags = 0,.buf = b0,.len = 1},
+				 {.addr = state->config->demod_address,.flags = I2C_M_RD,.buf = b1,.len = 1}
+			       };
+
+	// this device needs a STOP between the register and data
+	if (state->config->stop_during_read) {
+		if ((ret = i2c_transfer(state->i2c, &msg[0], 1)) != 1) {
+			dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __func__, reg, ret);
+			return -1;
+		}
+		if ((ret = i2c_transfer(state->i2c, &msg[1], 1)) != 1) {
+			dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __func__, reg, ret);
+			return -1;
+		}
+	} else {
+		if ((ret = i2c_transfer(state->i2c, msg, 2)) != 2) {
+			dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __func__, reg, ret);
+			return -1;
+		}
+	}
+
+	return b1[0];
+}
+
+static int stv0297_writereg_mask(struct stv0297_state *state, u8 reg, u8 mask, u8 data)
+{
+	int val;
+
+	val = stv0297_readreg(state, reg);
+	val &= ~mask;
+	val |= (data & mask);
+	stv0297_writereg(state, reg, val);
+
+	return 0;
+}
+
+static int stv0297_readregs(struct stv0297_state *state, u8 reg1, u8 * b, u8 len)
+{
+	int ret;
+	struct i2c_msg msg[] = { {.addr = state->config->demod_address,.flags = 0,.buf =
+				  &reg1,.len = 1},
+	{.addr = state->config->demod_address,.flags = I2C_M_RD,.buf = b,.len = len}
+	};
+
+	// this device needs a STOP between the register and data
+	if (state->config->stop_during_read) {
+		if ((ret = i2c_transfer(state->i2c, &msg[0], 1)) != 1) {
+			dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __func__, reg1, ret);
+			return -1;
+		}
+		if ((ret = i2c_transfer(state->i2c, &msg[1], 1)) != 1) {
+			dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __func__, reg1, ret);
+			return -1;
+		}
+	} else {
+		if ((ret = i2c_transfer(state->i2c, msg, 2)) != 2) {
+			dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __func__, reg1, ret);
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
+static u32 stv0297_get_symbolrate(struct stv0297_state *state)
+{
+	u64 tmp;
+
+	tmp = stv0297_readreg(state, 0x55);
+	tmp |= stv0297_readreg(state, 0x56) << 8;
+	tmp |= stv0297_readreg(state, 0x57) << 16;
+	tmp |= stv0297_readreg(state, 0x58) << 24;
+
+	tmp *= STV0297_CLOCK_KHZ;
+	tmp >>= 32;
+
+	return (u32) tmp;
+}
+
+static void stv0297_set_symbolrate(struct stv0297_state *state, u32 srate)
+{
+	long tmp;
+
+	tmp = 131072L * srate;	/* 131072 = 2^17  */
+	tmp = tmp / (STV0297_CLOCK_KHZ / 4);	/* 1/4 = 2^-2 */
+	tmp = tmp * 8192L;	/* 8192 = 2^13 */
+
+	stv0297_writereg(state, 0x55, (unsigned char) (tmp & 0xFF));
+	stv0297_writereg(state, 0x56, (unsigned char) (tmp >> 8));
+	stv0297_writereg(state, 0x57, (unsigned char) (tmp >> 16));
+	stv0297_writereg(state, 0x58, (unsigned char) (tmp >> 24));
+}
+
+static void stv0297_set_sweeprate(struct stv0297_state *state, short fshift, long symrate)
+{
+	long tmp;
+
+	tmp = (long) fshift *262144L;	/* 262144 = 2*18 */
+	tmp /= symrate;
+	tmp *= 1024;		/* 1024 = 2*10   */
+
+	// adjust
+	if (tmp >= 0) {
+		tmp += 500000;
+	} else {
+		tmp -= 500000;
+	}
+	tmp /= 1000000;
+
+	stv0297_writereg(state, 0x60, tmp & 0xFF);
+	stv0297_writereg_mask(state, 0x69, 0xF0, (tmp >> 4) & 0xf0);
+}
+
+static void stv0297_set_carrieroffset(struct stv0297_state *state, long offset)
+{
+	long tmp;
+
+	/* symrate is hardcoded to 10000 */
+	tmp = offset * 26844L;	/* (2**28)/10000 */
+	if (tmp < 0)
+		tmp += 0x10000000;
+	tmp &= 0x0FFFFFFF;
+
+	stv0297_writereg(state, 0x66, (unsigned char) (tmp & 0xFF));
+	stv0297_writereg(state, 0x67, (unsigned char) (tmp >> 8));
+	stv0297_writereg(state, 0x68, (unsigned char) (tmp >> 16));
+	stv0297_writereg_mask(state, 0x69, 0x0F, (tmp >> 24) & 0x0f);
+}
+
+/*
+static long stv0297_get_carrieroffset(struct stv0297_state *state)
+{
+	s64 tmp;
+
+	stv0297_writereg(state, 0x6B, 0x00);
+
+	tmp = stv0297_readreg(state, 0x66);
+	tmp |= (stv0297_readreg(state, 0x67) << 8);
+	tmp |= (stv0297_readreg(state, 0x68) << 16);
+	tmp |= (stv0297_readreg(state, 0x69) & 0x0F) << 24;
+
+	tmp *= stv0297_get_symbolrate(state);
+	tmp >>= 28;
+
+	return (s32) tmp;
+}
+*/
+
+static void stv0297_set_initialdemodfreq(struct stv0297_state *state, long freq)
+{
+	s32 tmp;
+
+	if (freq > 10000)
+		freq -= STV0297_CLOCK_KHZ;
+
+	tmp = (STV0297_CLOCK_KHZ * 1000) / (1 << 16);
+	tmp = (freq * 1000) / tmp;
+	if (tmp > 0xffff)
+		tmp = 0xffff;
+
+	stv0297_writereg_mask(state, 0x25, 0x80, 0x80);
+	stv0297_writereg(state, 0x21, tmp >> 8);
+	stv0297_writereg(state, 0x20, tmp);
+}
+
+static int stv0297_set_qam(struct stv0297_state *state, fe_modulation_t modulation)
+{
+	int val = 0;
+
+	switch (modulation) {
+	case QAM_16:
+		val = 0;
+		break;
+
+	case QAM_32:
+		val = 1;
+		break;
+
+	case QAM_64:
+		val = 4;
+		break;
+
+	case QAM_128:
+		val = 2;
+		break;
+
+	case QAM_256:
+		val = 3;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	stv0297_writereg_mask(state, 0x00, 0x70, val << 4);
+
+	return 0;
+}
+
+static int stv0297_set_inversion(struct stv0297_state *state, fe_spectral_inversion_t inversion)
+{
+	int val = 0;
+
+	switch (inversion) {
+	case INVERSION_OFF:
+		val = 0;
+		break;
+
+	case INVERSION_ON:
+		val = 1;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	stv0297_writereg_mask(state, 0x83, 0x08, val << 3);
+
+	return 0;
+}
+
+static int stv0297_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+	struct stv0297_state *state = fe->demodulator_priv;
+
+	if (enable) {
+		stv0297_writereg(state, 0x87, 0x78);
+		stv0297_writereg(state, 0x86, 0xc8);
+	}
+
+	return 0;
+}
+
+static int stv0297_init(struct dvb_frontend *fe)
+{
+	struct stv0297_state *state = fe->demodulator_priv;
+	int i;
+
+	/* load init table */
+	for (i=0; !(state->config->inittab[i] == 0xff && state->config->inittab[i+1] == 0xff); i+=2)
+		stv0297_writereg(state, state->config->inittab[i], state->config->inittab[i+1]);
+	msleep(200);
+
+	state->last_ber = 0;
+
+	return 0;
+}
+
+static int stv0297_sleep(struct dvb_frontend *fe)
+{
+	struct stv0297_state *state = fe->demodulator_priv;
+
+	stv0297_writereg_mask(state, 0x80, 1, 1);
+
+	return 0;
+}
+
+static int stv0297_read_status(struct dvb_frontend *fe, fe_status_t * status)
+{
+	struct stv0297_state *state = fe->demodulator_priv;
+
+	u8 sync = stv0297_readreg(state, 0xDF);
+
+	*status = 0;
+	if (sync & 0x80)
+		*status |=
+			FE_HAS_SYNC | FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_LOCK;
+	return 0;
+}
+
+static int stv0297_read_ber(struct dvb_frontend *fe, u32 * ber)
+{
+	struct stv0297_state *state = fe->demodulator_priv;
+	u8 BER[3];
+
+	stv0297_readregs(state, 0xA0, BER, 3);
+	if (!(BER[0] & 0x80)) {
+		state->last_ber = BER[2] << 8 | BER[1];
+		stv0297_writereg_mask(state, 0xA0, 0x80, 0x80);
+	}
+
+	*ber = state->last_ber;
+
+	return 0;
+}
+
+
+static int stv0297_read_signal_strength(struct dvb_frontend *fe, u16 * strength)
+{
+	struct stv0297_state *state = fe->demodulator_priv;
+	u8 STRENGTH[3];
+	u16 tmp;
+
+	stv0297_readregs(state, 0x41, STRENGTH, 3);
+	tmp = (STRENGTH[1] & 0x03) << 8 | STRENGTH[0];
+	if (STRENGTH[2] & 0x20) {
+		if (tmp < 0x200)
+			tmp = 0;
+		else
+			tmp = tmp - 0x200;
+	} else {
+		if (tmp > 0x1ff)
+			tmp = 0;
+		else
+			tmp = 0x1ff - tmp;
+	}
+	*strength = (tmp << 7) | (tmp >> 2);
+	return 0;
+}
+
+static int stv0297_read_snr(struct dvb_frontend *fe, u16 * snr)
+{
+	struct stv0297_state *state = fe->demodulator_priv;
+	u8 SNR[2];
+
+	stv0297_readregs(state, 0x07, SNR, 2);
+	*snr = SNR[1] << 8 | SNR[0];
+
+	return 0;
+}
+
+static int stv0297_read_ucblocks(struct dvb_frontend *fe, u32 * ucblocks)
+{
+	struct stv0297_state *state = fe->demodulator_priv;
+
+	stv0297_writereg_mask(state, 0xDF, 0x03, 0x03); /* freeze the counters */
+
+	*ucblocks = (stv0297_readreg(state, 0xD5) << 8)
+		| stv0297_readreg(state, 0xD4);
+
+	stv0297_writereg_mask(state, 0xDF, 0x03, 0x02); /* clear the counters */
+	stv0297_writereg_mask(state, 0xDF, 0x03, 0x01); /* re-enable the counters */
+
+	return 0;
+}
+
+static int stv0297_set_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct stv0297_state *state = fe->demodulator_priv;
+	int u_threshold;
+	int initial_u;
+	int blind_u;
+	int delay;
+	int sweeprate;
+	int carrieroffset;
+	unsigned long timeout;
+	fe_spectral_inversion_t inversion;
+
+	switch (p->modulation) {
+	case QAM_16:
+	case QAM_32:
+	case QAM_64:
+		delay = 100;
+		sweeprate = 1000;
+		break;
+
+	case QAM_128:
+	case QAM_256:
+		delay = 200;
+		sweeprate = 500;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	// determine inversion dependent parameters
+	inversion = p->inversion;
+	if (state->config->invert)
+		inversion = (inversion == INVERSION_ON) ? INVERSION_OFF : INVERSION_ON;
+	carrieroffset = -330;
+	switch (inversion) {
+	case INVERSION_OFF:
+		break;
+
+	case INVERSION_ON:
+		sweeprate = -sweeprate;
+		carrieroffset = -carrieroffset;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	stv0297_init(fe);
+	if (fe->ops.tuner_ops.set_params) {
+		fe->ops.tuner_ops.set_params(fe);
+		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+	}
+
+	/* clear software interrupts */
+	stv0297_writereg(state, 0x82, 0x0);
+
+	/* set initial demodulation frequency */
+	stv0297_set_initialdemodfreq(state, 7250);
+
+	/* setup AGC */
+	stv0297_writereg_mask(state, 0x43, 0x10, 0x00);
+	stv0297_writereg(state, 0x41, 0x00);
+	stv0297_writereg_mask(state, 0x42, 0x03, 0x01);
+	stv0297_writereg_mask(state, 0x36, 0x60, 0x00);
+	stv0297_writereg_mask(state, 0x36, 0x18, 0x00);
+	stv0297_writereg_mask(state, 0x71, 0x80, 0x80);
+	stv0297_writereg(state, 0x72, 0x00);
+	stv0297_writereg(state, 0x73, 0x00);
+	stv0297_writereg_mask(state, 0x74, 0x0F, 0x00);
+	stv0297_writereg_mask(state, 0x43, 0x08, 0x00);
+	stv0297_writereg_mask(state, 0x71, 0x80, 0x00);
+
+	/* setup STL */
+	stv0297_writereg_mask(state, 0x5a, 0x20, 0x20);
+	stv0297_writereg_mask(state, 0x5b, 0x02, 0x02);
+	stv0297_writereg_mask(state, 0x5b, 0x02, 0x00);
+	stv0297_writereg_mask(state, 0x5b, 0x01, 0x00);
+	stv0297_writereg_mask(state, 0x5a, 0x40, 0x40);
+
+	/* disable frequency sweep */
+	stv0297_writereg_mask(state, 0x6a, 0x01, 0x00);
+
+	/* reset deinterleaver */
+	stv0297_writereg_mask(state, 0x81, 0x01, 0x01);
+	stv0297_writereg_mask(state, 0x81, 0x01, 0x00);
+
+	/* ??? */
+	stv0297_writereg_mask(state, 0x83, 0x20, 0x20);
+	stv0297_writereg_mask(state, 0x83, 0x20, 0x00);
+
+	/* reset equaliser */
+	u_threshold = stv0297_readreg(state, 0x00) & 0xf;
+	initial_u = stv0297_readreg(state, 0x01) >> 4;
+	blind_u = stv0297_readreg(state, 0x01) & 0xf;
+	stv0297_writereg_mask(state, 0x84, 0x01, 0x01);
+	stv0297_writereg_mask(state, 0x84, 0x01, 0x00);
+	stv0297_writereg_mask(state, 0x00, 0x0f, u_threshold);
+	stv0297_writereg_mask(state, 0x01, 0xf0, initial_u << 4);
+	stv0297_writereg_mask(state, 0x01, 0x0f, blind_u);
+
+	/* data comes from internal A/D */
+	stv0297_writereg_mask(state, 0x87, 0x80, 0x00);
+
+	/* clear phase registers */
+	stv0297_writereg(state, 0x63, 0x00);
+	stv0297_writereg(state, 0x64, 0x00);
+	stv0297_writereg(state, 0x65, 0x00);
+	stv0297_writereg(state, 0x66, 0x00);
+	stv0297_writereg(state, 0x67, 0x00);
+	stv0297_writereg(state, 0x68, 0x00);
+	stv0297_writereg_mask(state, 0x69, 0x0f, 0x00);
+
+	/* set parameters */
+	stv0297_set_qam(state, p->modulation);
+	stv0297_set_symbolrate(state, p->symbol_rate / 1000);
+	stv0297_set_sweeprate(state, sweeprate, p->symbol_rate / 1000);
+	stv0297_set_carrieroffset(state, carrieroffset);
+	stv0297_set_inversion(state, inversion);
+
+	/* kick off lock */
+	/* Disable corner detection for higher QAMs */
+	if (p->modulation == QAM_128 ||
+		p->modulation == QAM_256)
+		stv0297_writereg_mask(state, 0x88, 0x08, 0x00);
+	else
+		stv0297_writereg_mask(state, 0x88, 0x08, 0x08);
+
+	stv0297_writereg_mask(state, 0x5a, 0x20, 0x00);
+	stv0297_writereg_mask(state, 0x6a, 0x01, 0x01);
+	stv0297_writereg_mask(state, 0x43, 0x40, 0x40);
+	stv0297_writereg_mask(state, 0x5b, 0x30, 0x00);
+	stv0297_writereg_mask(state, 0x03, 0x0c, 0x0c);
+	stv0297_writereg_mask(state, 0x03, 0x03, 0x03);
+	stv0297_writereg_mask(state, 0x43, 0x10, 0x10);
+
+	/* wait for WGAGC lock */
+	timeout = jiffies + msecs_to_jiffies(2000);
+	while (time_before(jiffies, timeout)) {
+		msleep(10);
+		if (stv0297_readreg(state, 0x43) & 0x08)
+			break;
+	}
+	if (time_after(jiffies, timeout)) {
+		goto timeout;
+	}
+	msleep(20);
+
+	/* wait for equaliser partial convergence */
+	timeout = jiffies + msecs_to_jiffies(500);
+	while (time_before(jiffies, timeout)) {
+		msleep(10);
+
+		if (stv0297_readreg(state, 0x82) & 0x04) {
+			break;
+		}
+	}
+	if (time_after(jiffies, timeout)) {
+		goto timeout;
+	}
+
+	/* wait for equaliser full convergence */
+	timeout = jiffies + msecs_to_jiffies(delay);
+	while (time_before(jiffies, timeout)) {
+		msleep(10);
+
+		if (stv0297_readreg(state, 0x82) & 0x08) {
+			break;
+		}
+	}
+	if (time_after(jiffies, timeout)) {
+		goto timeout;
+	}
+
+	/* disable sweep */
+	stv0297_writereg_mask(state, 0x6a, 1, 0);
+	stv0297_writereg_mask(state, 0x88, 8, 0);
+
+	/* wait for main lock */
+	timeout = jiffies + msecs_to_jiffies(20);
+	while (time_before(jiffies, timeout)) {
+		msleep(10);
+
+		if (stv0297_readreg(state, 0xDF) & 0x80) {
+			break;
+		}
+	}
+	if (time_after(jiffies, timeout)) {
+		goto timeout;
+	}
+	msleep(100);
+
+	/* is it still locked after that delay? */
+	if (!(stv0297_readreg(state, 0xDF) & 0x80)) {
+		goto timeout;
+	}
+
+	/* success!! */
+	stv0297_writereg_mask(state, 0x5a, 0x40, 0x00);
+	state->base_freq = p->frequency;
+	return 0;
+
+timeout:
+	stv0297_writereg_mask(state, 0x6a, 0x01, 0x00);
+	return 0;
+}
+
+static int stv0297_get_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct stv0297_state *state = fe->demodulator_priv;
+	int reg_00, reg_83;
+
+	reg_00 = stv0297_readreg(state, 0x00);
+	reg_83 = stv0297_readreg(state, 0x83);
+
+	p->frequency = state->base_freq;
+	p->inversion = (reg_83 & 0x08) ? INVERSION_ON : INVERSION_OFF;
+	if (state->config->invert)
+		p->inversion = (p->inversion == INVERSION_ON) ? INVERSION_OFF : INVERSION_ON;
+	p->symbol_rate = stv0297_get_symbolrate(state) * 1000;
+	p->fec_inner = FEC_NONE;
+
+	switch ((reg_00 >> 4) & 0x7) {
+	case 0:
+		p->modulation = QAM_16;
+		break;
+	case 1:
+		p->modulation = QAM_32;
+		break;
+	case 2:
+		p->modulation = QAM_128;
+		break;
+	case 3:
+		p->modulation = QAM_256;
+		break;
+	case 4:
+		p->modulation = QAM_64;
+		break;
+	}
+
+	return 0;
+}
+
+static void stv0297_release(struct dvb_frontend *fe)
+{
+	struct stv0297_state *state = fe->demodulator_priv;
+	kfree(state);
+}
+
+static struct dvb_frontend_ops stv0297_ops;
+
+struct dvb_frontend *stv0297_attach(const struct stv0297_config *config,
+				    struct i2c_adapter *i2c)
+{
+	struct stv0297_state *state = NULL;
+
+	/* allocate memory for the internal state */
+	state = kzalloc(sizeof(struct stv0297_state), GFP_KERNEL);
+	if (state == NULL)
+		goto error;
+
+	/* setup the state */
+	state->config = config;
+	state->i2c = i2c;
+	state->last_ber = 0;
+	state->base_freq = 0;
+
+	/* check if the demod is there */
+	if ((stv0297_readreg(state, 0x80) & 0x70) != 0x20)
+		goto error;
+
+	/* create dvb_frontend */
+	memcpy(&state->frontend.ops, &stv0297_ops, sizeof(struct dvb_frontend_ops));
+	state->frontend.demodulator_priv = state;
+	return &state->frontend;
+
+error:
+	kfree(state);
+	return NULL;
+}
+
+static struct dvb_frontend_ops stv0297_ops = {
+	.delsys = { SYS_DVBC_ANNEX_A },
+	.info = {
+		 .name = "ST STV0297 DVB-C",
+		 .frequency_min = 47000000,
+		 .frequency_max = 862000000,
+		 .frequency_stepsize = 62500,
+		 .symbol_rate_min = 870000,
+		 .symbol_rate_max = 11700000,
+		 .caps = FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 |
+		 FE_CAN_QAM_128 | FE_CAN_QAM_256 | FE_CAN_FEC_AUTO},
+
+	.release = stv0297_release,
+
+	.init = stv0297_init,
+	.sleep = stv0297_sleep,
+	.i2c_gate_ctrl = stv0297_i2c_gate_ctrl,
+
+	.set_frontend = stv0297_set_frontend,
+	.get_frontend = stv0297_get_frontend,
+
+	.read_status = stv0297_read_status,
+	.read_ber = stv0297_read_ber,
+	.read_signal_strength = stv0297_read_signal_strength,
+	.read_snr = stv0297_read_snr,
+	.read_ucblocks = stv0297_read_ucblocks,
+};
+
+MODULE_DESCRIPTION("ST STV0297 DVB-C Demodulator driver");
+MODULE_AUTHOR("Dennis Noermann and Andrew de Quincey");
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(stv0297_attach);
diff --git a/drivers/media/dvb-frontends/stv0297.h b/drivers/media/dvb-frontends/stv0297.h
new file mode 100644
index 0000000..3f8f946
--- /dev/null
+++ b/drivers/media/dvb-frontends/stv0297.h
@@ -0,0 +1,57 @@
+/*
+    Driver for STV0297 demodulator
+
+    Copyright (C) 2003-2004 Dennis Noermann <dennis.noermann@noernet.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 STV0297_H
+#define STV0297_H
+
+#include <linux/dvb/frontend.h>
+#include "dvb_frontend.h"
+
+struct stv0297_config
+{
+	/* the demodulator's i2c address */
+	u8 demod_address;
+
+	/* inittab - array of pairs of values.
+	* First of each pair is the register, second is the value.
+	* List should be terminated with an 0xff, 0xff pair.
+	*/
+	u8* inittab;
+
+	/* does the "inversion" need inverted? */
+	u8 invert:1;
+
+	/* set to 1 if the device requires an i2c STOP during reading */
+	u8 stop_during_read:1;
+};
+
+#if defined(CONFIG_DVB_STV0297) || (defined(CONFIG_DVB_STV0297_MODULE) && defined(MODULE))
+extern struct dvb_frontend* stv0297_attach(const struct stv0297_config* config,
+					   struct i2c_adapter* i2c);
+#else
+static inline struct dvb_frontend* stv0297_attach(const struct stv0297_config* config,
+					   struct i2c_adapter* i2c)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif // CONFIG_DVB_STV0297
+
+#endif // STV0297_H
diff --git a/drivers/media/dvb-frontends/stv0299.c b/drivers/media/dvb-frontends/stv0299.c
new file mode 100644
index 0000000..057b5f8
--- /dev/null
+++ b/drivers/media/dvb-frontends/stv0299.c
@@ -0,0 +1,762 @@
+/*
+    Driver for ST STV0299 demodulator
+
+    Copyright (C) 2001-2002 Convergence Integrated Media GmbH
+	<ralph@convergence.de>,
+	<holger@convergence.de>,
+	<js@convergence.de>
+
+
+    Philips SU1278/SH
+
+    Copyright (C) 2002 by Peter Schildmann <peter.schildmann@web.de>
+
+
+    LG TDQF-S001F
+
+    Copyright (C) 2002 Felix Domke <tmbinc@elitedvb.net>
+		     & Andreas Oberritter <obi@linuxtv.org>
+
+
+    Support for Samsung TBMU24112IMB used on Technisat SkyStar2 rev. 2.6B
+
+    Copyright (C) 2003 Vadim Catana <skystar@moldova.cc>:
+
+    Support for Philips SU1278 on Technotrend hardware
+
+    Copyright (C) 2004 Andrew de Quincey <adq_dvb@lidskialf.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 program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You 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/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <asm/div64.h>
+
+#include "dvb_frontend.h"
+#include "stv0299.h"
+
+struct stv0299_state {
+	struct i2c_adapter* i2c;
+	const struct stv0299_config* config;
+	struct dvb_frontend frontend;
+
+	u8 initialised:1;
+	u32 tuner_frequency;
+	u32 symbol_rate;
+	fe_code_rate_t fec_inner;
+	int errmode;
+	u32 ucblocks;
+	u8 mcr_reg;
+};
+
+#define STATUS_BER 0
+#define STATUS_UCBLOCKS 1
+
+static int debug;
+static int debug_legacy_dish_switch;
+#define dprintk(args...) \
+	do { \
+		if (debug) printk(KERN_DEBUG "stv0299: " args); \
+	} while (0)
+
+
+static int stv0299_writeregI (struct stv0299_state* state, u8 reg, u8 data)
+{
+	int ret;
+	u8 buf [] = { reg, data };
+	struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 };
+
+	ret = i2c_transfer (state->i2c, &msg, 1);
+
+	if (ret != 1)
+		dprintk("%s: writereg error (reg == 0x%02x, val == 0x%02x, "
+			"ret == %i)\n", __func__, reg, data, ret);
+
+	return (ret != 1) ? -EREMOTEIO : 0;
+}
+
+static int stv0299_write(struct dvb_frontend* fe, const u8 buf[], int len)
+{
+	struct stv0299_state* state = fe->demodulator_priv;
+
+	if (len != 2)
+		return -EINVAL;
+
+	return stv0299_writeregI(state, buf[0], buf[1]);
+}
+
+static u8 stv0299_readreg (struct stv0299_state* state, u8 reg)
+{
+	int ret;
+	u8 b0 [] = { reg };
+	u8 b1 [] = { 0 };
+	struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 },
+			   { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } };
+
+	ret = i2c_transfer (state->i2c, msg, 2);
+
+	if (ret != 2)
+		dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n",
+				__func__, reg, ret);
+
+	return b1[0];
+}
+
+static int stv0299_readregs (struct stv0299_state* state, u8 reg1, u8 *b, u8 len)
+{
+	int ret;
+	struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = &reg1, .len = 1 },
+			   { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b, .len = len } };
+
+	ret = i2c_transfer (state->i2c, msg, 2);
+
+	if (ret != 2)
+		dprintk("%s: readreg error (ret == %i)\n", __func__, ret);
+
+	return ret == 2 ? 0 : ret;
+}
+
+static int stv0299_set_FEC (struct stv0299_state* state, fe_code_rate_t fec)
+{
+	dprintk ("%s\n", __func__);
+
+	switch (fec) {
+	case FEC_AUTO:
+	{
+		return stv0299_writeregI (state, 0x31, 0x1f);
+	}
+	case FEC_1_2:
+	{
+		return stv0299_writeregI (state, 0x31, 0x01);
+	}
+	case FEC_2_3:
+	{
+		return stv0299_writeregI (state, 0x31, 0x02);
+	}
+	case FEC_3_4:
+	{
+		return stv0299_writeregI (state, 0x31, 0x04);
+	}
+	case FEC_5_6:
+	{
+		return stv0299_writeregI (state, 0x31, 0x08);
+	}
+	case FEC_7_8:
+	{
+		return stv0299_writeregI (state, 0x31, 0x10);
+	}
+	default:
+	{
+		return -EINVAL;
+	}
+    }
+}
+
+static fe_code_rate_t stv0299_get_fec (struct stv0299_state* state)
+{
+	static fe_code_rate_t fec_tab [] = { FEC_2_3, FEC_3_4, FEC_5_6,
+					     FEC_7_8, FEC_1_2 };
+	u8 index;
+
+	dprintk ("%s\n", __func__);
+
+	index = stv0299_readreg (state, 0x1b);
+	index &= 0x7;
+
+	if (index > 4)
+		return FEC_AUTO;
+
+	return fec_tab [index];
+}
+
+static int stv0299_wait_diseqc_fifo (struct stv0299_state* state, int timeout)
+{
+	unsigned long start = jiffies;
+
+	dprintk ("%s\n", __func__);
+
+	while (stv0299_readreg(state, 0x0a) & 1) {
+		if (jiffies - start > timeout) {
+			dprintk ("%s: timeout!!\n", __func__);
+			return -ETIMEDOUT;
+		}
+		msleep(10);
+	};
+
+	return 0;
+}
+
+static int stv0299_wait_diseqc_idle (struct stv0299_state* state, int timeout)
+{
+	unsigned long start = jiffies;
+
+	dprintk ("%s\n", __func__);
+
+	while ((stv0299_readreg(state, 0x0a) & 3) != 2 ) {
+		if (jiffies - start > timeout) {
+			dprintk ("%s: timeout!!\n", __func__);
+			return -ETIMEDOUT;
+		}
+		msleep(10);
+	};
+
+	return 0;
+}
+
+static int stv0299_set_symbolrate (struct dvb_frontend* fe, u32 srate)
+{
+	struct stv0299_state* state = fe->demodulator_priv;
+	u64 big = srate;
+	u32 ratio;
+
+	// check rate is within limits
+	if ((srate < 1000000) || (srate > 45000000)) return -EINVAL;
+
+	// calculate value to program
+	big = big << 20;
+	big += (state->config->mclk-1); // round correctly
+	do_div(big, state->config->mclk);
+	ratio = big << 4;
+
+	return state->config->set_symbol_rate(fe, srate, ratio);
+}
+
+static int stv0299_get_symbolrate (struct stv0299_state* state)
+{
+	u32 Mclk = state->config->mclk / 4096L;
+	u32 srate;
+	s32 offset;
+	u8 sfr[3];
+	s8 rtf;
+
+	dprintk ("%s\n", __func__);
+
+	stv0299_readregs (state, 0x1f, sfr, 3);
+	stv0299_readregs (state, 0x1a, (u8 *)&rtf, 1);
+
+	srate = (sfr[0] << 8) | sfr[1];
+	srate *= Mclk;
+	srate /= 16;
+	srate += (sfr[2] >> 4) * Mclk / 256;
+	offset = (s32) rtf * (srate / 4096L);
+	offset /= 128;
+
+	dprintk ("%s : srate = %i\n", __func__, srate);
+	dprintk ("%s : ofset = %i\n", __func__, offset);
+
+	srate += offset;
+
+	srate += 1000;
+	srate /= 2000;
+	srate *= 2000;
+
+	return srate;
+}
+
+static int stv0299_send_diseqc_msg (struct dvb_frontend* fe,
+				    struct dvb_diseqc_master_cmd *m)
+{
+	struct stv0299_state* state = fe->demodulator_priv;
+	u8 val;
+	int i;
+
+	dprintk ("%s\n", __func__);
+
+	if (stv0299_wait_diseqc_idle (state, 100) < 0)
+		return -ETIMEDOUT;
+
+	val = stv0299_readreg (state, 0x08);
+
+	if (stv0299_writeregI (state, 0x08, (val & ~0x7) | 0x6))  /* DiSEqC mode */
+		return -EREMOTEIO;
+
+	for (i=0; i<m->msg_len; i++) {
+		if (stv0299_wait_diseqc_fifo (state, 100) < 0)
+			return -ETIMEDOUT;
+
+		if (stv0299_writeregI (state, 0x09, m->msg[i]))
+			return -EREMOTEIO;
+	}
+
+	if (stv0299_wait_diseqc_idle (state, 100) < 0)
+		return -ETIMEDOUT;
+
+	return 0;
+}
+
+static int stv0299_send_diseqc_burst (struct dvb_frontend* fe, fe_sec_mini_cmd_t burst)
+{
+	struct stv0299_state* state = fe->demodulator_priv;
+	u8 val;
+
+	dprintk ("%s\n", __func__);
+
+	if (stv0299_wait_diseqc_idle (state, 100) < 0)
+		return -ETIMEDOUT;
+
+	val = stv0299_readreg (state, 0x08);
+
+	if (stv0299_writeregI (state, 0x08, (val & ~0x7) | 0x2))	/* burst mode */
+		return -EREMOTEIO;
+
+	if (stv0299_writeregI (state, 0x09, burst == SEC_MINI_A ? 0x00 : 0xff))
+		return -EREMOTEIO;
+
+	if (stv0299_wait_diseqc_idle (state, 100) < 0)
+		return -ETIMEDOUT;
+
+	if (stv0299_writeregI (state, 0x08, val))
+		return -EREMOTEIO;
+
+	return 0;
+}
+
+static int stv0299_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
+{
+	struct stv0299_state* state = fe->demodulator_priv;
+	u8 val;
+
+	if (stv0299_wait_diseqc_idle (state, 100) < 0)
+		return -ETIMEDOUT;
+
+	val = stv0299_readreg (state, 0x08);
+
+	switch (tone) {
+	case SEC_TONE_ON:
+		return stv0299_writeregI (state, 0x08, val | 0x3);
+
+	case SEC_TONE_OFF:
+		return stv0299_writeregI (state, 0x08, (val & ~0x3) | 0x02);
+
+	default:
+		return -EINVAL;
+	}
+}
+
+static int stv0299_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltage)
+{
+	struct stv0299_state* state = fe->demodulator_priv;
+	u8 reg0x08;
+	u8 reg0x0c;
+
+	dprintk("%s: %s\n", __func__,
+		voltage == SEC_VOLTAGE_13 ? "SEC_VOLTAGE_13" :
+		voltage == SEC_VOLTAGE_18 ? "SEC_VOLTAGE_18" : "??");
+
+	reg0x08 = stv0299_readreg (state, 0x08);
+	reg0x0c = stv0299_readreg (state, 0x0c);
+
+	/**
+	 *  H/V switching over OP0, OP1 and OP2 are LNB power enable bits
+	 */
+	reg0x0c &= 0x0f;
+	reg0x08 = (reg0x08 & 0x3f) | (state->config->lock_output << 6);
+
+	switch (voltage) {
+	case SEC_VOLTAGE_13:
+		if (state->config->volt13_op0_op1 == STV0299_VOLT13_OP0)
+			reg0x0c |= 0x10; /* OP1 off, OP0 on */
+		else
+			reg0x0c |= 0x40; /* OP1 on, OP0 off */
+		break;
+	case SEC_VOLTAGE_18:
+		reg0x0c |= 0x50; /* OP1 on, OP0 on */
+		break;
+	case SEC_VOLTAGE_OFF:
+		/* LNB power off! */
+		reg0x08 = 0x00;
+		reg0x0c = 0x00;
+		break;
+	default:
+		return -EINVAL;
+	};
+
+	if (state->config->op0_off)
+		reg0x0c &= ~0x10;
+
+	stv0299_writeregI(state, 0x08, reg0x08);
+	return stv0299_writeregI(state, 0x0c, reg0x0c);
+}
+
+static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, unsigned long cmd)
+{
+	struct stv0299_state* state = fe->demodulator_priv;
+	u8 reg0x08;
+	u8 reg0x0c;
+	u8 lv_mask = 0x40;
+	u8 last = 1;
+	int i;
+	struct timeval nexttime;
+	struct timeval tv[10];
+
+	reg0x08 = stv0299_readreg (state, 0x08);
+	reg0x0c = stv0299_readreg (state, 0x0c);
+	reg0x0c &= 0x0f;
+	stv0299_writeregI (state, 0x08, (reg0x08 & 0x3f) | (state->config->lock_output << 6));
+	if (state->config->volt13_op0_op1 == STV0299_VOLT13_OP0)
+		lv_mask = 0x10;
+
+	cmd = cmd << 1;
+	if (debug_legacy_dish_switch)
+		printk ("%s switch command: 0x%04lx\n",__func__, cmd);
+
+	do_gettimeofday (&nexttime);
+	if (debug_legacy_dish_switch)
+		memcpy (&tv[0], &nexttime, sizeof (struct timeval));
+	stv0299_writeregI (state, 0x0c, reg0x0c | 0x50); /* set LNB to 18V */
+
+	dvb_frontend_sleep_until(&nexttime, 32000);
+
+	for (i=0; i<9; i++) {
+		if (debug_legacy_dish_switch)
+			do_gettimeofday (&tv[i+1]);
+		if((cmd & 0x01) != last) {
+			/* set voltage to (last ? 13V : 18V) */
+			stv0299_writeregI (state, 0x0c, reg0x0c | (last ? lv_mask : 0x50));
+			last = (last) ? 0 : 1;
+		}
+
+		cmd = cmd >> 1;
+
+		if (i != 8)
+			dvb_frontend_sleep_until(&nexttime, 8000);
+	}
+	if (debug_legacy_dish_switch) {
+		printk ("%s(%d): switch delay (should be 32k followed by all 8k\n",
+			__func__, fe->dvb->num);
+		for (i = 1; i < 10; i++)
+			printk ("%d: %d\n", i, timeval_usec_diff(tv[i-1] , tv[i]));
+	}
+
+	return 0;
+}
+
+static int stv0299_init (struct dvb_frontend* fe)
+{
+	struct stv0299_state* state = fe->demodulator_priv;
+	int i;
+	u8 reg;
+	u8 val;
+
+	dprintk("stv0299: init chip\n");
+
+	stv0299_writeregI(state, 0x02, 0x30 | state->mcr_reg);
+	msleep(50);
+
+	for (i = 0; ; i += 2)  {
+		reg = state->config->inittab[i];
+		val = state->config->inittab[i+1];
+		if (reg == 0xff && val == 0xff)
+			break;
+		if (reg == 0x0c && state->config->op0_off)
+			val &= ~0x10;
+		if (reg == 0x2)
+			state->mcr_reg = val & 0xf;
+		stv0299_writeregI(state, reg, val);
+	}
+
+	return 0;
+}
+
+static int stv0299_read_status(struct dvb_frontend* fe, fe_status_t* status)
+{
+	struct stv0299_state* state = fe->demodulator_priv;
+
+	u8 signal = 0xff - stv0299_readreg (state, 0x18);
+	u8 sync = stv0299_readreg (state, 0x1b);
+
+	dprintk ("%s : FE_READ_STATUS : VSTATUS: 0x%02x\n", __func__, sync);
+	*status = 0;
+
+	if (signal > 10)
+		*status |= FE_HAS_SIGNAL;
+
+	if (sync & 0x80)
+		*status |= FE_HAS_CARRIER;
+
+	if (sync & 0x10)
+		*status |= FE_HAS_VITERBI;
+
+	if (sync & 0x08)
+		*status |= FE_HAS_SYNC;
+
+	if ((sync & 0x98) == 0x98)
+		*status |= FE_HAS_LOCK;
+
+	return 0;
+}
+
+static int stv0299_read_ber(struct dvb_frontend* fe, u32* ber)
+{
+	struct stv0299_state* state = fe->demodulator_priv;
+
+	if (state->errmode != STATUS_BER)
+		return -ENOSYS;
+
+	*ber = stv0299_readreg(state, 0x1e) | (stv0299_readreg(state, 0x1d) << 8);
+
+	return 0;
+}
+
+static int stv0299_read_signal_strength(struct dvb_frontend* fe, u16* strength)
+{
+	struct stv0299_state* state = fe->demodulator_priv;
+
+	s32 signal =  0xffff - ((stv0299_readreg (state, 0x18) << 8)
+			       | stv0299_readreg (state, 0x19));
+
+	dprintk ("%s : FE_READ_SIGNAL_STRENGTH : AGC2I: 0x%02x%02x, signal=0x%04x\n", __func__,
+		 stv0299_readreg (state, 0x18),
+		 stv0299_readreg (state, 0x19), (int) signal);
+
+	signal = signal * 5 / 4;
+	*strength = (signal > 0xffff) ? 0xffff : (signal < 0) ? 0 : signal;
+
+	return 0;
+}
+
+static int stv0299_read_snr(struct dvb_frontend* fe, u16* snr)
+{
+	struct stv0299_state* state = fe->demodulator_priv;
+
+	s32 xsnr = 0xffff - ((stv0299_readreg (state, 0x24) << 8)
+			   | stv0299_readreg (state, 0x25));
+	xsnr = 3 * (xsnr - 0xa100);
+	*snr = (xsnr > 0xffff) ? 0xffff : (xsnr < 0) ? 0 : xsnr;
+
+	return 0;
+}
+
+static int stv0299_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
+{
+	struct stv0299_state* state = fe->demodulator_priv;
+
+	if (state->errmode != STATUS_UCBLOCKS)
+		return -ENOSYS;
+
+	state->ucblocks += stv0299_readreg(state, 0x1e);
+	state->ucblocks += (stv0299_readreg(state, 0x1d) << 8);
+	*ucblocks = state->ucblocks;
+
+	return 0;
+}
+
+static int stv0299_set_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct stv0299_state* state = fe->demodulator_priv;
+	int invval = 0;
+
+	dprintk ("%s : FE_SET_FRONTEND\n", __func__);
+	if (state->config->set_ts_params)
+		state->config->set_ts_params(fe, 0);
+
+	// set the inversion
+	if (p->inversion == INVERSION_OFF) invval = 0;
+	else if (p->inversion == INVERSION_ON) invval = 1;
+	else {
+		printk("stv0299 does not support auto-inversion\n");
+		return -EINVAL;
+	}
+	if (state->config->invert) invval = (~invval) & 1;
+	stv0299_writeregI(state, 0x0c, (stv0299_readreg(state, 0x0c) & 0xfe) | invval);
+
+	if (fe->ops.tuner_ops.set_params) {
+		fe->ops.tuner_ops.set_params(fe);
+		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+	}
+
+	stv0299_set_FEC(state, p->fec_inner);
+	stv0299_set_symbolrate(fe, p->symbol_rate);
+	stv0299_writeregI(state, 0x22, 0x00);
+	stv0299_writeregI(state, 0x23, 0x00);
+
+	state->tuner_frequency = p->frequency;
+	state->fec_inner = p->fec_inner;
+	state->symbol_rate = p->symbol_rate;
+
+	return 0;
+}
+
+static int stv0299_get_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct stv0299_state* state = fe->demodulator_priv;
+	s32 derot_freq;
+	int invval;
+
+	derot_freq = (s32)(s16) ((stv0299_readreg (state, 0x22) << 8)
+				| stv0299_readreg (state, 0x23));
+
+	derot_freq *= (state->config->mclk >> 16);
+	derot_freq += 500;
+	derot_freq /= 1000;
+
+	p->frequency += derot_freq;
+
+	invval = stv0299_readreg (state, 0x0c) & 1;
+	if (state->config->invert) invval = (~invval) & 1;
+	p->inversion = invval ? INVERSION_ON : INVERSION_OFF;
+
+	p->fec_inner = stv0299_get_fec(state);
+	p->symbol_rate = stv0299_get_symbolrate(state);
+
+	return 0;
+}
+
+static int stv0299_sleep(struct dvb_frontend* fe)
+{
+	struct stv0299_state* state = fe->demodulator_priv;
+
+	stv0299_writeregI(state, 0x02, 0xb0 | state->mcr_reg);
+	state->initialised = 0;
+
+	return 0;
+}
+
+static int stv0299_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+{
+	struct stv0299_state* state = fe->demodulator_priv;
+
+	if (enable) {
+		stv0299_writeregI(state, 0x05, 0xb5);
+	} else {
+		stv0299_writeregI(state, 0x05, 0x35);
+	}
+	udelay(1);
+	return 0;
+}
+
+static int stv0299_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings)
+{
+	struct stv0299_state* state = fe->demodulator_priv;
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+
+	fesettings->min_delay_ms = state->config->min_delay_ms;
+	if (p->symbol_rate < 10000000) {
+		fesettings->step_size = p->symbol_rate / 32000;
+		fesettings->max_drift = 5000;
+	} else {
+		fesettings->step_size = p->symbol_rate / 16000;
+		fesettings->max_drift = p->symbol_rate / 2000;
+	}
+	return 0;
+}
+
+static void stv0299_release(struct dvb_frontend* fe)
+{
+	struct stv0299_state* state = fe->demodulator_priv;
+	kfree(state);
+}
+
+static struct dvb_frontend_ops stv0299_ops;
+
+struct dvb_frontend* stv0299_attach(const struct stv0299_config* config,
+				    struct i2c_adapter* i2c)
+{
+	struct stv0299_state* state = NULL;
+	int id;
+
+	/* allocate memory for the internal state */
+	state = kzalloc(sizeof(struct stv0299_state), GFP_KERNEL);
+	if (state == NULL) goto error;
+
+	/* setup the state */
+	state->config = config;
+	state->i2c = i2c;
+	state->initialised = 0;
+	state->tuner_frequency = 0;
+	state->symbol_rate = 0;
+	state->fec_inner = 0;
+	state->errmode = STATUS_BER;
+
+	/* check if the demod is there */
+	stv0299_writeregI(state, 0x02, 0x30); /* standby off */
+	msleep(200);
+	id = stv0299_readreg(state, 0x00);
+
+	/* register 0x00 contains 0xa1 for STV0299 and STV0299B */
+	/* register 0x00 might contain 0x80 when returning from standby */
+	if (id != 0xa1 && id != 0x80) goto error;
+
+	/* create dvb_frontend */
+	memcpy(&state->frontend.ops, &stv0299_ops, sizeof(struct dvb_frontend_ops));
+	state->frontend.demodulator_priv = state;
+	return &state->frontend;
+
+error:
+	kfree(state);
+	return NULL;
+}
+
+static struct dvb_frontend_ops stv0299_ops = {
+	.delsys = { SYS_DVBS },
+	.info = {
+		.name			= "ST STV0299 DVB-S",
+		.frequency_min		= 950000,
+		.frequency_max		= 2150000,
+		.frequency_stepsize	= 125,	 /* kHz for QPSK frontends */
+		.frequency_tolerance	= 0,
+		.symbol_rate_min	= 1000000,
+		.symbol_rate_max	= 45000000,
+		.symbol_rate_tolerance	= 500,	/* ppm */
+		.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_FEC_AUTO
+	},
+
+	.release = stv0299_release,
+
+	.init = stv0299_init,
+	.sleep = stv0299_sleep,
+	.write = stv0299_write,
+	.i2c_gate_ctrl = stv0299_i2c_gate_ctrl,
+
+	.set_frontend = stv0299_set_frontend,
+	.get_frontend = stv0299_get_frontend,
+	.get_tune_settings = stv0299_get_tune_settings,
+
+	.read_status = stv0299_read_status,
+	.read_ber = stv0299_read_ber,
+	.read_signal_strength = stv0299_read_signal_strength,
+	.read_snr = stv0299_read_snr,
+	.read_ucblocks = stv0299_read_ucblocks,
+
+	.diseqc_send_master_cmd = stv0299_send_diseqc_msg,
+	.diseqc_send_burst = stv0299_send_diseqc_burst,
+	.set_tone = stv0299_set_tone,
+	.set_voltage = stv0299_set_voltage,
+	.dishnetwork_send_legacy_command = stv0299_send_legacy_dish_cmd,
+};
+
+module_param(debug_legacy_dish_switch, int, 0444);
+MODULE_PARM_DESC(debug_legacy_dish_switch, "Enable timing analysis for Dish Network legacy switches");
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+
+MODULE_DESCRIPTION("ST STV0299 DVB Demodulator driver");
+MODULE_AUTHOR("Ralph Metzler, Holger Waechtler, Peter Schildmann, Felix Domke, "
+	      "Andreas Oberritter, Andrew de Quincey, Kenneth Aafly");
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(stv0299_attach);
diff --git a/drivers/media/dvb-frontends/stv0299.h b/drivers/media/dvb-frontends/stv0299.h
new file mode 100644
index 0000000..ba219b7
--- /dev/null
+++ b/drivers/media/dvb-frontends/stv0299.h
@@ -0,0 +1,118 @@
+/*
+    Driver for ST STV0299 demodulator
+
+    Copyright (C) 2001-2002 Convergence Integrated Media GmbH
+	<ralph@convergence.de>,
+	<holger@convergence.de>,
+	<js@convergence.de>
+
+
+    Philips SU1278/SH
+
+    Copyright (C) 2002 by Peter Schildmann <peter.schildmann@web.de>
+
+
+    LG TDQF-S001F
+
+    Copyright (C) 2002 Felix Domke <tmbinc@elitedvb.net>
+		     & Andreas Oberritter <obi@linuxtv.org>
+
+
+    Support for Samsung TBMU24112IMB used on Technisat SkyStar2 rev. 2.6B
+
+    Copyright (C) 2003 Vadim Catana <skystar@moldova.cc>:
+
+    Support for Philips SU1278 on Technotrend hardware
+
+    Copyright (C) 2004 Andrew de Quincey <adq_dvb@lidskialf.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 program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You 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 STV0299_H
+#define STV0299_H
+
+#include <linux/dvb/frontend.h>
+#include "dvb_frontend.h"
+
+#define STV0299_LOCKOUTPUT_0  0
+#define STV0299_LOCKOUTPUT_1  1
+#define STV0299_LOCKOUTPUT_CF 2
+#define STV0299_LOCKOUTPUT_LK 3
+
+#define STV0299_VOLT13_OP0 0
+#define STV0299_VOLT13_OP1 1
+
+struct stv0299_config
+{
+	/* the demodulator's i2c address */
+	u8 demod_address;
+
+	/* inittab - array of pairs of values.
+	 * First of each pair is the register, second is the value.
+	 * List should be terminated with an 0xff, 0xff pair.
+	 */
+	const u8* inittab;
+
+	/* master clock to use */
+	u32 mclk;
+
+	/* does the inversion require inversion? */
+	u8 invert:1;
+
+	/* Skip reinitialisation? */
+	u8 skip_reinit:1;
+
+	/* LOCK OUTPUT setting */
+	u8 lock_output:2;
+
+	/* Is 13v controlled by OP0 or OP1? */
+	u8 volt13_op0_op1:1;
+
+	/* Turn-off OP0? */
+	u8 op0_off:1;
+
+	/* minimum delay before retuning */
+	int min_delay_ms;
+
+	/* Set the symbol rate */
+	int (*set_symbol_rate)(struct dvb_frontend *fe, u32 srate, u32 ratio);
+
+	/* Set device param to start dma */
+	int (*set_ts_params)(struct dvb_frontend *fe, int is_punctured);
+};
+
+#if defined(CONFIG_DVB_STV0299) || (defined(CONFIG_DVB_STV0299_MODULE) && defined(MODULE))
+extern struct dvb_frontend *stv0299_attach(const struct stv0299_config *config,
+					   struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend *stv0299_attach(const struct stv0299_config *config,
+					   struct i2c_adapter *i2c)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif // CONFIG_DVB_STV0299
+
+static inline int stv0299_writereg(struct dvb_frontend *fe, u8 reg, u8 val) {
+	int r = 0;
+	u8 buf[] = {reg, val};
+	if (fe->ops.write)
+		r = fe->ops.write(fe, buf, 2);
+	return r;
+}
+
+#endif // STV0299_H
diff --git a/drivers/media/dvb-frontends/stv0367.c b/drivers/media/dvb-frontends/stv0367.c
new file mode 100644
index 0000000..2a8aaeb
--- /dev/null
+++ b/drivers/media/dvb-frontends/stv0367.c
@@ -0,0 +1,3450 @@
+/*
+ * stv0367.c
+ *
+ * Driver for ST STV0367 DVB-T & DVB-C demodulator IC.
+ *
+ * Copyright (C) ST Microelectronics.
+ * Copyright (C) 2010,2011 NetUP Inc.
+ * Copyright (C) 2010,2011 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 "stv0367.h"
+#include "stv0367_regs.h"
+#include "stv0367_priv.h"
+
+static int stvdebug;
+module_param_named(debug, stvdebug, int, 0644);
+
+static int i2cdebug;
+module_param_named(i2c_debug, i2cdebug, int, 0644);
+
+#define dprintk(args...) \
+	do { \
+		if (stvdebug) \
+			printk(KERN_DEBUG args); \
+	} while (0)
+	/* DVB-C */
+
+struct stv0367cab_state {
+	enum stv0367_cab_signal_type	state;
+	u32	mclk;
+	u32	adc_clk;
+	s32	search_range;
+	s32	derot_offset;
+	/* results */
+	int locked;			/* channel found		*/
+	u32 freq_khz;			/* found frequency (in kHz)	*/
+	u32 symbol_rate;		/* found symbol rate (in Bds)	*/
+	enum stv0367cab_mod modulation;	/* modulation			*/
+	fe_spectral_inversion_t	spect_inv; /* Spectrum Inversion	*/
+};
+
+struct stv0367ter_state {
+	/* DVB-T */
+	enum stv0367_ter_signal_type state;
+	enum stv0367_ter_if_iq_mode if_iq_mode;
+	enum stv0367_ter_mode mode;/* mode 2K or 8K */
+	fe_guard_interval_t guard;
+	enum stv0367_ter_hierarchy hierarchy;
+	u32 frequency;
+	fe_spectral_inversion_t  sense; /*  current search spectrum */
+	u8  force; /* force mode/guard */
+	u8  bw; /* channel width 6, 7 or 8 in MHz */
+	u8  pBW; /* channel width used during previous lock */
+	u32 pBER;
+	u32 pPER;
+	u32 ucblocks;
+	s8  echo_pos; /* echo position */
+	u8  first_lock;
+	u8  unlock_counter;
+	u32 agc_val;
+};
+
+struct stv0367_state {
+	struct dvb_frontend fe;
+	struct i2c_adapter *i2c;
+	/* config settings */
+	const struct stv0367_config *config;
+	u8 chip_id;
+	/* DVB-C */
+	struct stv0367cab_state *cab_state;
+	/* DVB-T */
+	struct stv0367ter_state *ter_state;
+};
+
+struct st_register {
+	u16	addr;
+	u8	value;
+};
+
+/* values for STV4100 XTAL=30M int clk=53.125M*/
+static struct st_register def0367ter[STV0367TER_NBREGS] = {
+	{R367TER_ID,		0x60},
+	{R367TER_I2CRPT,	0xa0},
+	/* {R367TER_I2CRPT,	0x22},*/
+	{R367TER_TOPCTRL,	0x00},/* for xc5000; was 0x02 */
+	{R367TER_IOCFG0,	0x40},
+	{R367TER_DAC0R,		0x00},
+	{R367TER_IOCFG1,	0x00},
+	{R367TER_DAC1R,		0x00},
+	{R367TER_IOCFG2,	0x62},
+	{R367TER_SDFR,		0x00},
+	{R367TER_STATUS,	0xf8},
+	{R367TER_AUX_CLK,	0x0a},
+	{R367TER_FREESYS1,	0x00},
+	{R367TER_FREESYS2,	0x00},
+	{R367TER_FREESYS3,	0x00},
+	{R367TER_GPIO_CFG,	0x55},
+	{R367TER_GPIO_CMD,	0x00},
+	{R367TER_AGC2MAX,	0xff},
+	{R367TER_AGC2MIN,	0x00},
+	{R367TER_AGC1MAX,	0xff},
+	{R367TER_AGC1MIN,	0x00},
+	{R367TER_AGCR,		0xbc},
+	{R367TER_AGC2TH,	0x00},
+	{R367TER_AGC12C,	0x00},
+	{R367TER_AGCCTRL1,	0x85},
+	{R367TER_AGCCTRL2,	0x1f},
+	{R367TER_AGC1VAL1,	0x00},
+	{R367TER_AGC1VAL2,	0x00},
+	{R367TER_AGC2VAL1,	0x6f},
+	{R367TER_AGC2VAL2,	0x05},
+	{R367TER_AGC2PGA,	0x00},
+	{R367TER_OVF_RATE1,	0x00},
+	{R367TER_OVF_RATE2,	0x00},
+	{R367TER_GAIN_SRC1,	0xaa},/* for xc5000; was 0x2b */
+	{R367TER_GAIN_SRC2,	0xd6},/* for xc5000; was 0x04 */
+	{R367TER_INC_DEROT1,	0x55},
+	{R367TER_INC_DEROT2,	0x55},
+	{R367TER_PPM_CPAMP_DIR,	0x2c},
+	{R367TER_PPM_CPAMP_INV,	0x00},
+	{R367TER_FREESTFE_1,	0x00},
+	{R367TER_FREESTFE_2,	0x1c},
+	{R367TER_DCOFFSET,	0x00},
+	{R367TER_EN_PROCESS,	0x05},
+	{R367TER_SDI_SMOOTHER,	0x80},
+	{R367TER_FE_LOOP_OPEN,	0x1c},
+	{R367TER_FREQOFF1,	0x00},
+	{R367TER_FREQOFF2,	0x00},
+	{R367TER_FREQOFF3,	0x00},
+	{R367TER_TIMOFF1,	0x00},
+	{R367TER_TIMOFF2,	0x00},
+	{R367TER_EPQ,		0x02},
+	{R367TER_EPQAUTO,	0x01},
+	{R367TER_SYR_UPDATE,	0xf5},
+	{R367TER_CHPFREE,	0x00},
+	{R367TER_PPM_STATE_MAC,	0x23},
+	{R367TER_INR_THRESHOLD,	0xff},
+	{R367TER_EPQ_TPS_ID_CELL, 0xf9},
+	{R367TER_EPQ_CFG,	0x00},
+	{R367TER_EPQ_STATUS,	0x01},
+	{R367TER_AUTORELOCK,	0x81},
+	{R367TER_BER_THR_VMSB,	0x00},
+	{R367TER_BER_THR_MSB,	0x00},
+	{R367TER_BER_THR_LSB,	0x00},
+	{R367TER_CCD,		0x83},
+	{R367TER_SPECTR_CFG,	0x00},
+	{R367TER_CHC_DUMMY,	0x18},
+	{R367TER_INC_CTL,	0x88},
+	{R367TER_INCTHRES_COR1,	0xb4},
+	{R367TER_INCTHRES_COR2,	0x96},
+	{R367TER_INCTHRES_DET1,	0x0e},
+	{R367TER_INCTHRES_DET2,	0x11},
+	{R367TER_IIR_CELLNB,	0x8d},
+	{R367TER_IIRCX_COEFF1_MSB, 0x00},
+	{R367TER_IIRCX_COEFF1_LSB, 0x00},
+	{R367TER_IIRCX_COEFF2_MSB, 0x09},
+	{R367TER_IIRCX_COEFF2_LSB, 0x18},
+	{R367TER_IIRCX_COEFF3_MSB, 0x14},
+	{R367TER_IIRCX_COEFF3_LSB, 0x9c},
+	{R367TER_IIRCX_COEFF4_MSB, 0x00},
+	{R367TER_IIRCX_COEFF4_LSB, 0x00},
+	{R367TER_IIRCX_COEFF5_MSB, 0x36},
+	{R367TER_IIRCX_COEFF5_LSB, 0x42},
+	{R367TER_FEPATH_CFG,	0x00},
+	{R367TER_PMC1_FUNC,	0x65},
+	{R367TER_PMC1_FOR,	0x00},
+	{R367TER_PMC2_FUNC,	0x00},
+	{R367TER_STATUS_ERR_DA,	0xe0},
+	{R367TER_DIG_AGC_R,	0xfe},
+	{R367TER_COMAGC_TARMSB,	0x0b},
+	{R367TER_COM_AGC_TAR_ENMODE, 0x41},
+	{R367TER_COM_AGC_CFG,	0x3e},
+	{R367TER_COM_AGC_GAIN1, 0x39},
+	{R367TER_AUT_AGC_TARGETMSB, 0x0b},
+	{R367TER_LOCK_DET_MSB,	0x01},
+	{R367TER_AGCTAR_LOCK_LSBS, 0x40},
+	{R367TER_AUT_GAIN_EN,	0xf4},
+	{R367TER_AUT_CFG,	0xf0},
+	{R367TER_LOCKN,		0x23},
+	{R367TER_INT_X_3,	0x00},
+	{R367TER_INT_X_2,	0x03},
+	{R367TER_INT_X_1,	0x8d},
+	{R367TER_INT_X_0,	0xa0},
+	{R367TER_MIN_ERRX_MSB,	0x00},
+	{R367TER_COR_CTL,	0x23},
+	{R367TER_COR_STAT,	0xf6},
+	{R367TER_COR_INTEN,	0x00},
+	{R367TER_COR_INTSTAT,	0x3f},
+	{R367TER_COR_MODEGUARD,	0x03},
+	{R367TER_AGC_CTL,	0x08},
+	{R367TER_AGC_MANUAL1,	0x00},
+	{R367TER_AGC_MANUAL2,	0x00},
+	{R367TER_AGC_TARG,	0x16},
+	{R367TER_AGC_GAIN1,	0x53},
+	{R367TER_AGC_GAIN2,	0x1d},
+	{R367TER_RESERVED_1,	0x00},
+	{R367TER_RESERVED_2,	0x00},
+	{R367TER_RESERVED_3,	0x00},
+	{R367TER_CAS_CTL,	0x44},
+	{R367TER_CAS_FREQ,	0xb3},
+	{R367TER_CAS_DAGCGAIN,	0x12},
+	{R367TER_SYR_CTL,	0x04},
+	{R367TER_SYR_STAT,	0x10},
+	{R367TER_SYR_NCO1,	0x00},
+	{R367TER_SYR_NCO2,	0x00},
+	{R367TER_SYR_OFFSET1,	0x00},
+	{R367TER_SYR_OFFSET2,	0x00},
+	{R367TER_FFT_CTL,	0x00},
+	{R367TER_SCR_CTL,	0x70},
+	{R367TER_PPM_CTL1,	0xf8},
+	{R367TER_TRL_CTL,	0x14},/* for xc5000; was 0xac */
+	{R367TER_TRL_NOMRATE1,	0xae},/* for xc5000; was 0x1e */
+	{R367TER_TRL_NOMRATE2,	0x56},/* for xc5000; was 0x58 */
+	{R367TER_TRL_TIME1,	0x1d},
+	{R367TER_TRL_TIME2,	0xfc},
+	{R367TER_CRL_CTL,	0x24},
+	{R367TER_CRL_FREQ1,	0xad},
+	{R367TER_CRL_FREQ2,	0x9d},
+	{R367TER_CRL_FREQ3,	0xff},
+	{R367TER_CHC_CTL,	0x01},
+	{R367TER_CHC_SNR,	0xf0},
+	{R367TER_BDI_CTL,	0x00},
+	{R367TER_DMP_CTL,	0x00},
+	{R367TER_TPS_RCVD1,	0x30},
+	{R367TER_TPS_RCVD2,	0x02},
+	{R367TER_TPS_RCVD3,	0x01},
+	{R367TER_TPS_RCVD4,	0x00},
+	{R367TER_TPS_ID_CELL1,	0x00},
+	{R367TER_TPS_ID_CELL2,	0x00},
+	{R367TER_TPS_RCVD5_SET1, 0x02},
+	{R367TER_TPS_SET2,	0x02},
+	{R367TER_TPS_SET3,	0x01},
+	{R367TER_TPS_CTL,	0x00},
+	{R367TER_CTL_FFTOSNUM,	0x34},
+	{R367TER_TESTSELECT,	0x09},
+	{R367TER_MSC_REV,	0x0a},
+	{R367TER_PIR_CTL,	0x00},
+	{R367TER_SNR_CARRIER1,	0xa1},
+	{R367TER_SNR_CARRIER2,	0x9a},
+	{R367TER_PPM_CPAMP,	0x2c},
+	{R367TER_TSM_AP0,	0x00},
+	{R367TER_TSM_AP1,	0x00},
+	{R367TER_TSM_AP2 ,	0x00},
+	{R367TER_TSM_AP3,	0x00},
+	{R367TER_TSM_AP4,	0x00},
+	{R367TER_TSM_AP5,	0x00},
+	{R367TER_TSM_AP6,	0x00},
+	{R367TER_TSM_AP7,	0x00},
+	{R367TER_TSTRES,	0x00},
+	{R367TER_ANACTRL,	0x0D},/* PLL stoped, restart at init!!! */
+	{R367TER_TSTBUS,	0x00},
+	{R367TER_TSTRATE,	0x00},
+	{R367TER_CONSTMODE,	0x01},
+	{R367TER_CONSTCARR1,	0x00},
+	{R367TER_CONSTCARR2,	0x00},
+	{R367TER_ICONSTEL,	0x0a},
+	{R367TER_QCONSTEL,	0x15},
+	{R367TER_TSTBISTRES0,	0x00},
+	{R367TER_TSTBISTRES1,	0x00},
+	{R367TER_TSTBISTRES2,	0x28},
+	{R367TER_TSTBISTRES3,	0x00},
+	{R367TER_RF_AGC1,	0xff},
+	{R367TER_RF_AGC2,	0x83},
+	{R367TER_ANADIGCTRL,	0x19},
+	{R367TER_PLLMDIV,	0x01},/* for xc5000; was 0x0c */
+	{R367TER_PLLNDIV,	0x06},/* for xc5000; was 0x55 */
+	{R367TER_PLLSETUP,	0x18},
+	{R367TER_DUAL_AD12,	0x0C},/* for xc5000 AGC voltage 1.6V */
+	{R367TER_TSTBIST,	0x00},
+	{R367TER_PAD_COMP_CTRL,	0x00},
+	{R367TER_PAD_COMP_WR,	0x00},
+	{R367TER_PAD_COMP_RD,	0xe0},
+	{R367TER_SYR_TARGET_FFTADJT_MSB, 0x00},
+	{R367TER_SYR_TARGET_FFTADJT_LSB, 0x00},
+	{R367TER_SYR_TARGET_CHCADJT_MSB, 0x00},
+	{R367TER_SYR_TARGET_CHCADJT_LSB, 0x00},
+	{R367TER_SYR_FLAG,	0x00},
+	{R367TER_CRL_TARGET1,	0x00},
+	{R367TER_CRL_TARGET2,	0x00},
+	{R367TER_CRL_TARGET3,	0x00},
+	{R367TER_CRL_TARGET4,	0x00},
+	{R367TER_CRL_FLAG,	0x00},
+	{R367TER_TRL_TARGET1,	0x00},
+	{R367TER_TRL_TARGET2,	0x00},
+	{R367TER_TRL_CHC,	0x00},
+	{R367TER_CHC_SNR_TARG,	0x00},
+	{R367TER_TOP_TRACK,	0x00},
+	{R367TER_TRACKER_FREE1,	0x00},
+	{R367TER_ERROR_CRL1,	0x00},
+	{R367TER_ERROR_CRL2,	0x00},
+	{R367TER_ERROR_CRL3,	0x00},
+	{R367TER_ERROR_CRL4,	0x00},
+	{R367TER_DEC_NCO1,	0x2c},
+	{R367TER_DEC_NCO2,	0x0f},
+	{R367TER_DEC_NCO3,	0x20},
+	{R367TER_SNR,		0xf1},
+	{R367TER_SYR_FFTADJ1,	0x00},
+	{R367TER_SYR_FFTADJ2,	0x00},
+	{R367TER_SYR_CHCADJ1,	0x00},
+	{R367TER_SYR_CHCADJ2,	0x00},
+	{R367TER_SYR_OFF,	0x00},
+	{R367TER_PPM_OFFSET1,	0x00},
+	{R367TER_PPM_OFFSET2,	0x03},
+	{R367TER_TRACKER_FREE2,	0x00},
+	{R367TER_DEBG_LT10,	0x00},
+	{R367TER_DEBG_LT11,	0x00},
+	{R367TER_DEBG_LT12,	0x00},
+	{R367TER_DEBG_LT13,	0x00},
+	{R367TER_DEBG_LT14,	0x00},
+	{R367TER_DEBG_LT15,	0x00},
+	{R367TER_DEBG_LT16,	0x00},
+	{R367TER_DEBG_LT17,	0x00},
+	{R367TER_DEBG_LT18,	0x00},
+	{R367TER_DEBG_LT19,	0x00},
+	{R367TER_DEBG_LT1A,	0x00},
+	{R367TER_DEBG_LT1B,	0x00},
+	{R367TER_DEBG_LT1C,	0x00},
+	{R367TER_DEBG_LT1D,	0x00},
+	{R367TER_DEBG_LT1E,	0x00},
+	{R367TER_DEBG_LT1F,	0x00},
+	{R367TER_RCCFGH,	0x00},
+	{R367TER_RCCFGM,	0x00},
+	{R367TER_RCCFGL,	0x00},
+	{R367TER_RCINSDELH,	0x00},
+	{R367TER_RCINSDELM,	0x00},
+	{R367TER_RCINSDELL,	0x00},
+	{R367TER_RCSTATUS,	0x00},
+	{R367TER_RCSPEED,	0x6f},
+	{R367TER_RCDEBUGM,	0xe7},
+	{R367TER_RCDEBUGL,	0x9b},
+	{R367TER_RCOBSCFG,	0x00},
+	{R367TER_RCOBSM,	0x00},
+	{R367TER_RCOBSL,	0x00},
+	{R367TER_RCFECSPY,	0x00},
+	{R367TER_RCFSPYCFG,	0x00},
+	{R367TER_RCFSPYDATA,	0x00},
+	{R367TER_RCFSPYOUT,	0x00},
+	{R367TER_RCFSTATUS,	0x00},
+	{R367TER_RCFGOODPACK,	0x00},
+	{R367TER_RCFPACKCNT,	0x00},
+	{R367TER_RCFSPYMISC,	0x00},
+	{R367TER_RCFBERCPT4,	0x00},
+	{R367TER_RCFBERCPT3,	0x00},
+	{R367TER_RCFBERCPT2,	0x00},
+	{R367TER_RCFBERCPT1,	0x00},
+	{R367TER_RCFBERCPT0,	0x00},
+	{R367TER_RCFBERERR2,	0x00},
+	{R367TER_RCFBERERR1,	0x00},
+	{R367TER_RCFBERERR0,	0x00},
+	{R367TER_RCFSTATESM,	0x00},
+	{R367TER_RCFSTATESL,	0x00},
+	{R367TER_RCFSPYBER,	0x00},
+	{R367TER_RCFSPYDISTM,	0x00},
+	{R367TER_RCFSPYDISTL,	0x00},
+	{R367TER_RCFSPYOBS7,	0x00},
+	{R367TER_RCFSPYOBS6,	0x00},
+	{R367TER_RCFSPYOBS5,	0x00},
+	{R367TER_RCFSPYOBS4,	0x00},
+	{R367TER_RCFSPYOBS3,	0x00},
+	{R367TER_RCFSPYOBS2,	0x00},
+	{R367TER_RCFSPYOBS1,	0x00},
+	{R367TER_RCFSPYOBS0,	0x00},
+	{R367TER_TSGENERAL,	0x00},
+	{R367TER_RC1SPEED,	0x6f},
+	{R367TER_TSGSTATUS,	0x18},
+	{R367TER_FECM,		0x01},
+	{R367TER_VTH12,		0xff},
+	{R367TER_VTH23,		0xa1},
+	{R367TER_VTH34,		0x64},
+	{R367TER_VTH56,		0x40},
+	{R367TER_VTH67,		0x00},
+	{R367TER_VTH78,		0x2c},
+	{R367TER_VITCURPUN,	0x12},
+	{R367TER_VERROR,	0x01},
+	{R367TER_PRVIT,		0x3f},
+	{R367TER_VAVSRVIT,	0x00},
+	{R367TER_VSTATUSVIT,	0xbd},
+	{R367TER_VTHINUSE,	0xa1},
+	{R367TER_KDIV12,	0x20},
+	{R367TER_KDIV23,	0x40},
+	{R367TER_KDIV34,	0x20},
+	{R367TER_KDIV56,	0x30},
+	{R367TER_KDIV67,	0x00},
+	{R367TER_KDIV78,	0x30},
+	{R367TER_SIGPOWER,	0x54},
+	{R367TER_DEMAPVIT,	0x40},
+	{R367TER_VITSCALE,	0x00},
+	{R367TER_FFEC1PRG,	0x00},
+	{R367TER_FVITCURPUN,	0x12},
+	{R367TER_FVERROR,	0x01},
+	{R367TER_FVSTATUSVIT,	0xbd},
+	{R367TER_DEBUG_LT1,	0x00},
+	{R367TER_DEBUG_LT2,	0x00},
+	{R367TER_DEBUG_LT3,	0x00},
+	{R367TER_TSTSFMET,	0x00},
+	{R367TER_SELOUT,	0x00},
+	{R367TER_TSYNC,		0x00},
+	{R367TER_TSTERR,	0x00},
+	{R367TER_TSFSYNC,	0x00},
+	{R367TER_TSTSFERR,	0x00},
+	{R367TER_TSTTSSF1,	0x01},
+	{R367TER_TSTTSSF2,	0x1f},
+	{R367TER_TSTTSSF3,	0x00},
+	{R367TER_TSTTS1,	0x00},
+	{R367TER_TSTTS2,	0x1f},
+	{R367TER_TSTTS3,	0x01},
+	{R367TER_TSTTS4,	0x00},
+	{R367TER_TSTTSRC,	0x00},
+	{R367TER_TSTTSRS,	0x00},
+	{R367TER_TSSTATEM,	0xb0},
+	{R367TER_TSSTATEL,	0x40},
+	{R367TER_TSCFGH,	0xC0},
+	{R367TER_TSCFGM,	0xc0},/* for xc5000; was 0x00 */
+	{R367TER_TSCFGL,	0x20},
+	{R367TER_TSSYNC,	0x00},
+	{R367TER_TSINSDELH,	0x00},
+	{R367TER_TSINSDELM,	0x00},
+	{R367TER_TSINSDELL,	0x00},
+	{R367TER_TSDIVN,	0x03},
+	{R367TER_TSDIVPM,	0x00},
+	{R367TER_TSDIVPL,	0x00},
+	{R367TER_TSDIVQM,	0x00},
+	{R367TER_TSDIVQL,	0x00},
+	{R367TER_TSDILSTKM,	0x00},
+	{R367TER_TSDILSTKL,	0x00},
+	{R367TER_TSSPEED,	0x40},/* for xc5000; was 0x6f */
+	{R367TER_TSSTATUS,	0x81},
+	{R367TER_TSSTATUS2,	0x6a},
+	{R367TER_TSBITRATEM,	0x0f},
+	{R367TER_TSBITRATEL,	0xc6},
+	{R367TER_TSPACKLENM,	0x00},
+	{R367TER_TSPACKLENL,	0xfc},
+	{R367TER_TSBLOCLENM,	0x0a},
+	{R367TER_TSBLOCLENL,	0x80},
+	{R367TER_TSDLYH,	0x90},
+	{R367TER_TSDLYM,	0x68},
+	{R367TER_TSDLYL,	0x01},
+	{R367TER_TSNPDAV,	0x00},
+	{R367TER_TSBUFSTATH,	0x00},
+	{R367TER_TSBUFSTATM,	0x00},
+	{R367TER_TSBUFSTATL,	0x00},
+	{R367TER_TSDEBUGM,	0xcf},
+	{R367TER_TSDEBUGL,	0x1e},
+	{R367TER_TSDLYSETH,	0x00},
+	{R367TER_TSDLYSETM,	0x68},
+	{R367TER_TSDLYSETL,	0x00},
+	{R367TER_TSOBSCFG,	0x00},
+	{R367TER_TSOBSM,	0x47},
+	{R367TER_TSOBSL,	0x1f},
+	{R367TER_ERRCTRL1,	0x95},
+	{R367TER_ERRCNT1H,	0x80},
+	{R367TER_ERRCNT1M,	0x00},
+	{R367TER_ERRCNT1L,	0x00},
+	{R367TER_ERRCTRL2,	0x95},
+	{R367TER_ERRCNT2H,	0x00},
+	{R367TER_ERRCNT2M,	0x00},
+	{R367TER_ERRCNT2L,	0x00},
+	{R367TER_FECSPY,	0x88},
+	{R367TER_FSPYCFG,	0x2c},
+	{R367TER_FSPYDATA,	0x3a},
+	{R367TER_FSPYOUT,	0x06},
+	{R367TER_FSTATUS,	0x61},
+	{R367TER_FGOODPACK,	0xff},
+	{R367TER_FPACKCNT,	0xff},
+	{R367TER_FSPYMISC,	0x66},
+	{R367TER_FBERCPT4,	0x00},
+	{R367TER_FBERCPT3,	0x00},
+	{R367TER_FBERCPT2,	0x36},
+	{R367TER_FBERCPT1,	0x36},
+	{R367TER_FBERCPT0,	0x14},
+	{R367TER_FBERERR2,	0x00},
+	{R367TER_FBERERR1,	0x03},
+	{R367TER_FBERERR0,	0x28},
+	{R367TER_FSTATESM,	0x00},
+	{R367TER_FSTATESL,	0x02},
+	{R367TER_FSPYBER,	0x00},
+	{R367TER_FSPYDISTM,	0x01},
+	{R367TER_FSPYDISTL,	0x9f},
+	{R367TER_FSPYOBS7,	0xc9},
+	{R367TER_FSPYOBS6,	0x99},
+	{R367TER_FSPYOBS5,	0x08},
+	{R367TER_FSPYOBS4,	0xec},
+	{R367TER_FSPYOBS3,	0x01},
+	{R367TER_FSPYOBS2,	0x0f},
+	{R367TER_FSPYOBS1,	0xf5},
+	{R367TER_FSPYOBS0,	0x08},
+	{R367TER_SFDEMAP,	0x40},
+	{R367TER_SFERROR,	0x00},
+	{R367TER_SFAVSR,	0x30},
+	{R367TER_SFECSTATUS,	0xcc},
+	{R367TER_SFKDIV12,	0x20},
+	{R367TER_SFKDIV23,	0x40},
+	{R367TER_SFKDIV34,	0x20},
+	{R367TER_SFKDIV56,	0x20},
+	{R367TER_SFKDIV67,	0x00},
+	{R367TER_SFKDIV78,	0x20},
+	{R367TER_SFDILSTKM,	0x00},
+	{R367TER_SFDILSTKL,	0x00},
+	{R367TER_SFSTATUS,	0xb5},
+	{R367TER_SFDLYH,	0x90},
+	{R367TER_SFDLYM,	0x60},
+	{R367TER_SFDLYL,	0x01},
+	{R367TER_SFDLYSETH,	0xc0},
+	{R367TER_SFDLYSETM,	0x60},
+	{R367TER_SFDLYSETL,	0x00},
+	{R367TER_SFOBSCFG,	0x00},
+	{R367TER_SFOBSM,	0x47},
+	{R367TER_SFOBSL,	0x05},
+	{R367TER_SFECINFO,	0x40},
+	{R367TER_SFERRCTRL,	0x74},
+	{R367TER_SFERRCNTH,	0x80},
+	{R367TER_SFERRCNTM ,	0x00},
+	{R367TER_SFERRCNTL,	0x00},
+	{R367TER_SYMBRATEM,	0x2f},
+	{R367TER_SYMBRATEL,	0x50},
+	{R367TER_SYMBSTATUS,	0x7f},
+	{R367TER_SYMBCFG,	0x00},
+	{R367TER_SYMBFIFOM,	0xf4},
+	{R367TER_SYMBFIFOL,	0x0d},
+	{R367TER_SYMBOFFSM,	0xf0},
+	{R367TER_SYMBOFFSL,	0x2d},
+	{R367TER_DEBUG_LT4,	0x00},
+	{R367TER_DEBUG_LT5,	0x00},
+	{R367TER_DEBUG_LT6,	0x00},
+	{R367TER_DEBUG_LT7,	0x00},
+	{R367TER_DEBUG_LT8,	0x00},
+	{R367TER_DEBUG_LT9,	0x00},
+};
+
+#define RF_LOOKUP_TABLE_SIZE  31
+#define RF_LOOKUP_TABLE2_SIZE 16
+/* RF Level (for RF AGC->AGC1) Lookup Table, depends on the board and tuner.*/
+s32 stv0367cab_RF_LookUp1[RF_LOOKUP_TABLE_SIZE][RF_LOOKUP_TABLE_SIZE] = {
+	{/*AGC1*/
+		48, 50, 51, 53, 54, 56, 57, 58, 60, 61, 62, 63,
+		64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75,
+		76, 77, 78, 80, 83, 85, 88,
+	}, {/*RF(dbm)*/
+		22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
+		34, 35, 36, 37, 38, 39, 41, 42, 43, 44, 46, 47,
+		49, 50, 52, 53, 54, 55, 56,
+	}
+};
+/* RF Level (for IF AGC->AGC2) Lookup Table, depends on the board and tuner.*/
+s32 stv0367cab_RF_LookUp2[RF_LOOKUP_TABLE2_SIZE][RF_LOOKUP_TABLE2_SIZE] = {
+	{/*AGC2*/
+		28, 29, 31, 32, 34, 35, 36, 37,
+		38, 39, 40, 41, 42, 43, 44, 45,
+	}, {/*RF(dbm)*/
+		57, 58, 59, 60, 61, 62, 63, 64,
+		65, 66, 67, 68, 69, 70, 71, 72,
+	}
+};
+
+static struct st_register def0367cab[STV0367CAB_NBREGS] = {
+	{R367CAB_ID,		0x60},
+	{R367CAB_I2CRPT,	0xa0},
+	/*{R367CAB_I2CRPT,	0x22},*/
+	{R367CAB_TOPCTRL,	0x10},
+	{R367CAB_IOCFG0,	0x80},
+	{R367CAB_DAC0R,		0x00},
+	{R367CAB_IOCFG1,	0x00},
+	{R367CAB_DAC1R,		0x00},
+	{R367CAB_IOCFG2,	0x00},
+	{R367CAB_SDFR,		0x00},
+	{R367CAB_AUX_CLK,	0x00},
+	{R367CAB_FREESYS1,	0x00},
+	{R367CAB_FREESYS2,	0x00},
+	{R367CAB_FREESYS3,	0x00},
+	{R367CAB_GPIO_CFG,	0x55},
+	{R367CAB_GPIO_CMD,	0x01},
+	{R367CAB_TSTRES,	0x00},
+	{R367CAB_ANACTRL,	0x0d},/* was 0x00 need to check - I.M.L.*/
+	{R367CAB_TSTBUS,	0x00},
+	{R367CAB_RF_AGC1,	0xea},
+	{R367CAB_RF_AGC2,	0x82},
+	{R367CAB_ANADIGCTRL,	0x0b},
+	{R367CAB_PLLMDIV,	0x01},
+	{R367CAB_PLLNDIV,	0x08},
+	{R367CAB_PLLSETUP,	0x18},
+	{R367CAB_DUAL_AD12,	0x0C}, /* for xc5000 AGC voltage 1.6V */
+	{R367CAB_TSTBIST,	0x00},
+	{R367CAB_CTRL_1,	0x00},
+	{R367CAB_CTRL_2,	0x03},
+	{R367CAB_IT_STATUS1,	0x2b},
+	{R367CAB_IT_STATUS2,	0x08},
+	{R367CAB_IT_EN1,	0x00},
+	{R367CAB_IT_EN2,	0x00},
+	{R367CAB_CTRL_STATUS,	0x04},
+	{R367CAB_TEST_CTL,	0x00},
+	{R367CAB_AGC_CTL,	0x73},
+	{R367CAB_AGC_IF_CFG,	0x50},
+	{R367CAB_AGC_RF_CFG,	0x00},
+	{R367CAB_AGC_PWM_CFG,	0x03},
+	{R367CAB_AGC_PWR_REF_L,	0x5a},
+	{R367CAB_AGC_PWR_REF_H,	0x00},
+	{R367CAB_AGC_RF_TH_L,	0xff},
+	{R367CAB_AGC_RF_TH_H,	0x07},
+	{R367CAB_AGC_IF_LTH_L,	0x00},
+	{R367CAB_AGC_IF_LTH_H,	0x08},
+	{R367CAB_AGC_IF_HTH_L,	0xff},
+	{R367CAB_AGC_IF_HTH_H,	0x07},
+	{R367CAB_AGC_PWR_RD_L,	0xa0},
+	{R367CAB_AGC_PWR_RD_M,	0xe9},
+	{R367CAB_AGC_PWR_RD_H,	0x03},
+	{R367CAB_AGC_PWM_IFCMD_L,	0xe4},
+	{R367CAB_AGC_PWM_IFCMD_H,	0x00},
+	{R367CAB_AGC_PWM_RFCMD_L,	0xff},
+	{R367CAB_AGC_PWM_RFCMD_H,	0x07},
+	{R367CAB_IQDEM_CFG,	0x01},
+	{R367CAB_MIX_NCO_LL,	0x22},
+	{R367CAB_MIX_NCO_HL,	0x96},
+	{R367CAB_MIX_NCO_HH,	0x55},
+	{R367CAB_SRC_NCO_LL,	0xff},
+	{R367CAB_SRC_NCO_LH,	0x0c},
+	{R367CAB_SRC_NCO_HL,	0xf5},
+	{R367CAB_SRC_NCO_HH,	0x20},
+	{R367CAB_IQDEM_GAIN_SRC_L,	0x06},
+	{R367CAB_IQDEM_GAIN_SRC_H,	0x01},
+	{R367CAB_IQDEM_DCRM_CFG_LL,	0xfe},
+	{R367CAB_IQDEM_DCRM_CFG_LH,	0xff},
+	{R367CAB_IQDEM_DCRM_CFG_HL,	0x0f},
+	{R367CAB_IQDEM_DCRM_CFG_HH,	0x00},
+	{R367CAB_IQDEM_ADJ_COEFF0,	0x34},
+	{R367CAB_IQDEM_ADJ_COEFF1,	0xae},
+	{R367CAB_IQDEM_ADJ_COEFF2,	0x46},
+	{R367CAB_IQDEM_ADJ_COEFF3,	0x77},
+	{R367CAB_IQDEM_ADJ_COEFF4,	0x96},
+	{R367CAB_IQDEM_ADJ_COEFF5,	0x69},
+	{R367CAB_IQDEM_ADJ_COEFF6,	0xc7},
+	{R367CAB_IQDEM_ADJ_COEFF7,	0x01},
+	{R367CAB_IQDEM_ADJ_EN,	0x04},
+	{R367CAB_IQDEM_ADJ_AGC_REF,	0x94},
+	{R367CAB_ALLPASSFILT1,	0xc9},
+	{R367CAB_ALLPASSFILT2,	0x2d},
+	{R367CAB_ALLPASSFILT3,	0xa3},
+	{R367CAB_ALLPASSFILT4,	0xfb},
+	{R367CAB_ALLPASSFILT5,	0xf6},
+	{R367CAB_ALLPASSFILT6,	0x45},
+	{R367CAB_ALLPASSFILT7,	0x6f},
+	{R367CAB_ALLPASSFILT8,	0x7e},
+	{R367CAB_ALLPASSFILT9,	0x05},
+	{R367CAB_ALLPASSFILT10,	0x0a},
+	{R367CAB_ALLPASSFILT11,	0x51},
+	{R367CAB_TRL_AGC_CFG,	0x20},
+	{R367CAB_TRL_LPF_CFG,	0x28},
+	{R367CAB_TRL_LPF_ACQ_GAIN,	0x44},
+	{R367CAB_TRL_LPF_TRK_GAIN,	0x22},
+	{R367CAB_TRL_LPF_OUT_GAIN,	0x03},
+	{R367CAB_TRL_LOCKDET_LTH,	0x04},
+	{R367CAB_TRL_LOCKDET_HTH,	0x11},
+	{R367CAB_TRL_LOCKDET_TRGVAL,	0x20},
+	{R367CAB_IQ_QAM,	0x01},
+	{R367CAB_FSM_STATE,	0xa0},
+	{R367CAB_FSM_CTL,	0x08},
+	{R367CAB_FSM_STS,	0x0c},
+	{R367CAB_FSM_SNR0_HTH,	0x00},
+	{R367CAB_FSM_SNR1_HTH,	0x00},
+	{R367CAB_FSM_SNR2_HTH,	0x23},/* 0x00 */
+	{R367CAB_FSM_SNR0_LTH,	0x00},
+	{R367CAB_FSM_SNR1_LTH,	0x00},
+	{R367CAB_FSM_EQA1_HTH,	0x00},
+	{R367CAB_FSM_TEMPO,	0x32},
+	{R367CAB_FSM_CONFIG,	0x03},
+	{R367CAB_EQU_I_TESTTAP_L,	0x11},
+	{R367CAB_EQU_I_TESTTAP_M,	0x00},
+	{R367CAB_EQU_I_TESTTAP_H,	0x00},
+	{R367CAB_EQU_TESTAP_CFG,	0x00},
+	{R367CAB_EQU_Q_TESTTAP_L,	0xff},
+	{R367CAB_EQU_Q_TESTTAP_M,	0x00},
+	{R367CAB_EQU_Q_TESTTAP_H,	0x00},
+	{R367CAB_EQU_TAP_CTRL,	0x00},
+	{R367CAB_EQU_CTR_CRL_CONTROL_L,	0x11},
+	{R367CAB_EQU_CTR_CRL_CONTROL_H,	0x05},
+	{R367CAB_EQU_CTR_HIPOW_L,	0x00},
+	{R367CAB_EQU_CTR_HIPOW_H,	0x00},
+	{R367CAB_EQU_I_EQU_LO,	0xef},
+	{R367CAB_EQU_I_EQU_HI,	0x00},
+	{R367CAB_EQU_Q_EQU_LO,	0xee},
+	{R367CAB_EQU_Q_EQU_HI,	0x00},
+	{R367CAB_EQU_MAPPER,	0xc5},
+	{R367CAB_EQU_SWEEP_RATE,	0x80},
+	{R367CAB_EQU_SNR_LO,	0x64},
+	{R367CAB_EQU_SNR_HI,	0x03},
+	{R367CAB_EQU_GAMMA_LO,	0x00},
+	{R367CAB_EQU_GAMMA_HI,	0x00},
+	{R367CAB_EQU_ERR_GAIN,	0x36},
+	{R367CAB_EQU_RADIUS,	0xaa},
+	{R367CAB_EQU_FFE_MAINTAP,	0x00},
+	{R367CAB_EQU_FFE_LEAKAGE,	0x63},
+	{R367CAB_EQU_FFE_MAINTAP_POS,	0xdf},
+	{R367CAB_EQU_GAIN_WIDE,	0x88},
+	{R367CAB_EQU_GAIN_NARROW,	0x41},
+	{R367CAB_EQU_CTR_LPF_GAIN,	0xd1},
+	{R367CAB_EQU_CRL_LPF_GAIN,	0xa7},
+	{R367CAB_EQU_GLOBAL_GAIN,	0x06},
+	{R367CAB_EQU_CRL_LD_SEN,	0x85},
+	{R367CAB_EQU_CRL_LD_VAL,	0xe2},
+	{R367CAB_EQU_CRL_TFR,	0x20},
+	{R367CAB_EQU_CRL_BISTH_LO,	0x00},
+	{R367CAB_EQU_CRL_BISTH_HI,	0x00},
+	{R367CAB_EQU_SWEEP_RANGE_LO,	0x00},
+	{R367CAB_EQU_SWEEP_RANGE_HI,	0x00},
+	{R367CAB_EQU_CRL_LIMITER,	0x40},
+	{R367CAB_EQU_MODULUS_MAP,	0x90},
+	{R367CAB_EQU_PNT_GAIN,	0xa7},
+	{R367CAB_FEC_AC_CTR_0,	0x16},
+	{R367CAB_FEC_AC_CTR_1,	0x0b},
+	{R367CAB_FEC_AC_CTR_2,	0x88},
+	{R367CAB_FEC_AC_CTR_3,	0x02},
+	{R367CAB_FEC_STATUS,	0x12},
+	{R367CAB_RS_COUNTER_0,	0x7d},
+	{R367CAB_RS_COUNTER_1,	0xd0},
+	{R367CAB_RS_COUNTER_2,	0x19},
+	{R367CAB_RS_COUNTER_3,	0x0b},
+	{R367CAB_RS_COUNTER_4,	0xa3},
+	{R367CAB_RS_COUNTER_5,	0x00},
+	{R367CAB_BERT_0,	0x01},
+	{R367CAB_BERT_1,	0x25},
+	{R367CAB_BERT_2,	0x41},
+	{R367CAB_BERT_3,	0x39},
+	{R367CAB_OUTFORMAT_0,	0xc2},
+	{R367CAB_OUTFORMAT_1,	0x22},
+	{R367CAB_SMOOTHER_2,	0x28},
+	{R367CAB_TSMF_CTRL_0,	0x01},
+	{R367CAB_TSMF_CTRL_1,	0xc6},
+	{R367CAB_TSMF_CTRL_3,	0x43},
+	{R367CAB_TS_ON_ID_0,	0x00},
+	{R367CAB_TS_ON_ID_1,	0x00},
+	{R367CAB_TS_ON_ID_2,	0x00},
+	{R367CAB_TS_ON_ID_3,	0x00},
+	{R367CAB_RE_STATUS_0,	0x00},
+	{R367CAB_RE_STATUS_1,	0x00},
+	{R367CAB_RE_STATUS_2,	0x00},
+	{R367CAB_RE_STATUS_3,	0x00},
+	{R367CAB_TS_STATUS_0,	0x00},
+	{R367CAB_TS_STATUS_1,	0x00},
+	{R367CAB_TS_STATUS_2,	0xa0},
+	{R367CAB_TS_STATUS_3,	0x00},
+	{R367CAB_T_O_ID_0,	0x00},
+	{R367CAB_T_O_ID_1,	0x00},
+	{R367CAB_T_O_ID_2,	0x00},
+	{R367CAB_T_O_ID_3,	0x00},
+};
+
+static
+int stv0367_writeregs(struct stv0367_state *state, u16 reg, u8 *data, int len)
+{
+	u8 buf[len + 2];
+	struct i2c_msg msg = {
+		.addr = state->config->demod_address,
+		.flags = 0,
+		.buf = buf,
+		.len = len + 2
+	};
+	int ret;
+
+	buf[0] = MSB(reg);
+	buf[1] = LSB(reg);
+	memcpy(buf + 2, data, len);
+
+	if (i2cdebug)
+		printk(KERN_DEBUG "%s: %02x: %02x\n", __func__, reg, buf[2]);
+
+	ret = i2c_transfer(state->i2c, &msg, 1);
+	if (ret != 1)
+		printk(KERN_ERR "%s: i2c write error!\n", __func__);
+
+	return (ret != 1) ? -EREMOTEIO : 0;
+}
+
+static int stv0367_writereg(struct stv0367_state *state, u16 reg, u8 data)
+{
+	return stv0367_writeregs(state, reg, &data, 1);
+}
+
+static u8 stv0367_readreg(struct stv0367_state *state, u16 reg)
+{
+	u8 b0[] = { 0, 0 };
+	u8 b1[] = { 0 };
+	struct i2c_msg msg[] = {
+		{
+			.addr = state->config->demod_address,
+			.flags = 0,
+			.buf = b0,
+			.len = 2
+		}, {
+			.addr = state->config->demod_address,
+			.flags = I2C_M_RD,
+			.buf = b1,
+			.len = 1
+		}
+	};
+	int ret;
+
+	b0[0] = MSB(reg);
+	b0[1] = LSB(reg);
+
+	ret = i2c_transfer(state->i2c, msg, 2);
+	if (ret != 2)
+		printk(KERN_ERR "%s: i2c read error\n", __func__);
+
+	if (i2cdebug)
+		printk(KERN_DEBUG "%s: %02x: %02x\n", __func__, reg, b1[0]);
+
+	return b1[0];
+}
+
+static 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);
+}
+
+static void stv0367_writebits(struct stv0367_state *state, u32 label, u8 val)
+{
+	u8 reg, mask, pos;
+
+	reg = stv0367_readreg(state, (label >> 16) & 0xffff);
+	extract_mask_pos(label, &mask, &pos);
+
+	val = mask & (val << pos);
+
+	reg = (reg & (~mask)) | val;
+	stv0367_writereg(state, (label >> 16) & 0xffff, reg);
+
+}
+
+static void stv0367_setbits(u8 *reg, u32 label, u8 val)
+{
+	u8 mask, pos;
+
+	extract_mask_pos(label, &mask, &pos);
+
+	val = mask & (val << pos);
+
+	(*reg) = ((*reg) & (~mask)) | val;
+}
+
+static u8 stv0367_readbits(struct stv0367_state *state, u32 label)
+{
+	u8 val = 0xff;
+	u8 mask, pos;
+
+	extract_mask_pos(label, &mask, &pos);
+
+	val = stv0367_readreg(state, label >> 16);
+	val = (val & mask) >> pos;
+
+	return val;
+}
+
+u8 stv0367_getbits(u8 reg, u32 label)
+{
+	u8 mask, pos;
+
+	extract_mask_pos(label, &mask, &pos);
+
+	return (reg & mask) >> pos;
+}
+
+static int stv0367ter_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+	struct stv0367_state *state = fe->demodulator_priv;
+	u8 tmp = stv0367_readreg(state, R367TER_I2CRPT);
+
+	dprintk("%s:\n", __func__);
+
+	if (enable) {
+		stv0367_setbits(&tmp, F367TER_STOP_ENABLE, 0);
+		stv0367_setbits(&tmp, F367TER_I2CT_ON, 1);
+	} else {
+		stv0367_setbits(&tmp, F367TER_STOP_ENABLE, 1);
+		stv0367_setbits(&tmp, F367TER_I2CT_ON, 0);
+	}
+
+	stv0367_writereg(state, R367TER_I2CRPT, tmp);
+
+	return 0;
+}
+
+static u32 stv0367_get_tuner_freq(struct dvb_frontend *fe)
+{
+	struct dvb_frontend_ops	*frontend_ops = NULL;
+	struct dvb_tuner_ops	*tuner_ops = NULL;
+	u32 freq = 0;
+	int err = 0;
+
+	dprintk("%s:\n", __func__);
+
+
+	if (&fe->ops)
+		frontend_ops = &fe->ops;
+	if (&frontend_ops->tuner_ops)
+		tuner_ops = &frontend_ops->tuner_ops;
+	if (tuner_ops->get_frequency) {
+		err = tuner_ops->get_frequency(fe, &freq);
+		if (err < 0) {
+			printk(KERN_ERR "%s: Invalid parameter\n", __func__);
+			return err;
+		}
+
+		dprintk("%s: frequency=%d\n", __func__, freq);
+
+	} else
+		return -1;
+
+	return freq;
+}
+
+static u16 CellsCoeffs_8MHz_367cofdm[3][6][5] = {
+	{
+		{0x10EF, 0xE205, 0x10EF, 0xCE49, 0x6DA7}, /* CELL 1 COEFFS 27M*/
+		{0x2151, 0xc557, 0x2151, 0xc705, 0x6f93}, /* CELL 2 COEFFS */
+		{0x2503, 0xc000, 0x2503, 0xc375, 0x7194}, /* CELL 3 COEFFS */
+		{0x20E9, 0xca94, 0x20e9, 0xc153, 0x7194}, /* CELL 4 COEFFS */
+		{0x06EF, 0xF852, 0x06EF, 0xC057, 0x7207}, /* CELL 5 COEFFS */
+		{0x0000, 0x0ECC, 0x0ECC, 0x0000, 0x3647} /* CELL 6 COEFFS */
+	}, {
+		{0x10A0, 0xE2AF, 0x10A1, 0xCE76, 0x6D6D}, /* CELL 1 COEFFS 25M*/
+		{0x20DC, 0xC676, 0x20D9, 0xC80A, 0x6F29},
+		{0x2532, 0xC000, 0x251D, 0xC391, 0x706F},
+		{0x1F7A, 0xCD2B, 0x2032, 0xC15E, 0x711F},
+		{0x0698, 0xFA5E, 0x0568, 0xC059, 0x7193},
+		{0x0000, 0x0918, 0x149C, 0x0000, 0x3642} /* CELL 6 COEFFS */
+	}, {
+		{0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, /* 30M */
+		{0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
+		{0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
+		{0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
+		{0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
+		{0x0000, 0x0000, 0x0000, 0x0000, 0x0000}
+	}
+};
+
+static u16 CellsCoeffs_7MHz_367cofdm[3][6][5] = {
+	{
+		{0x12CA, 0xDDAF, 0x12CA, 0xCCEB, 0x6FB1}, /* CELL 1 COEFFS 27M*/
+		{0x2329, 0xC000, 0x2329, 0xC6B0, 0x725F}, /* CELL 2 COEFFS */
+		{0x2394, 0xC000, 0x2394, 0xC2C7, 0x7410}, /* CELL 3 COEFFS */
+		{0x251C, 0xC000, 0x251C, 0xC103, 0x74D9}, /* CELL 4 COEFFS */
+		{0x0804, 0xF546, 0x0804, 0xC040, 0x7544}, /* CELL 5 COEFFS */
+		{0x0000, 0x0CD9, 0x0CD9, 0x0000, 0x370A} /* CELL 6 COEFFS */
+	}, {
+		{0x1285, 0xDE47, 0x1285, 0xCD17, 0x6F76}, /*25M*/
+		{0x234C, 0xC000, 0x2348, 0xC6DA, 0x7206},
+		{0x23B4, 0xC000, 0x23AC, 0xC2DB, 0x73B3},
+		{0x253D, 0xC000, 0x25B6, 0xC10B, 0x747F},
+		{0x0721, 0xF79C, 0x065F, 0xC041, 0x74EB},
+		{0x0000, 0x08FA, 0x1162, 0x0000, 0x36FF}
+	}, {
+		{0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, /* 30M */
+		{0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
+		{0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
+		{0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
+		{0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
+		{0x0000, 0x0000, 0x0000, 0x0000, 0x0000}
+	}
+};
+
+static u16 CellsCoeffs_6MHz_367cofdm[3][6][5] = {
+	{
+		{0x1699, 0xD5B8, 0x1699, 0xCBC3, 0x713B}, /* CELL 1 COEFFS 27M*/
+		{0x2245, 0xC000, 0x2245, 0xC568, 0x74D5}, /* CELL 2 COEFFS */
+		{0x227F, 0xC000, 0x227F, 0xC1FC, 0x76C6}, /* CELL 3 COEFFS */
+		{0x235E, 0xC000, 0x235E, 0xC0A7, 0x778A}, /* CELL 4 COEFFS */
+		{0x0ECB, 0xEA0B, 0x0ECB, 0xC027, 0x77DD}, /* CELL 5 COEFFS */
+		{0x0000, 0x0B68, 0x0B68, 0x0000, 0xC89A}, /* CELL 6 COEFFS */
+	}, {
+		{0x1655, 0xD64E, 0x1658, 0xCBEF, 0x70FE}, /*25M*/
+		{0x225E, 0xC000, 0x2256, 0xC589, 0x7489},
+		{0x2293, 0xC000, 0x2295, 0xC209, 0x767E},
+		{0x2377, 0xC000, 0x23AA, 0xC0AB, 0x7746},
+		{0x0DC7, 0xEBC8, 0x0D07, 0xC027, 0x7799},
+		{0x0000, 0x0888, 0x0E9C, 0x0000, 0x3757}
+
+	}, {
+		{0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, /* 30M */
+		{0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
+		{0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
+		{0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
+		{0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
+		{0x0000, 0x0000, 0x0000, 0x0000, 0x0000}
+	}
+};
+
+static u32 stv0367ter_get_mclk(struct stv0367_state *state, u32 ExtClk_Hz)
+{
+	u32 mclk_Hz = 0; /* master clock frequency (Hz) */
+	u32 m, n, p;
+
+	dprintk("%s:\n", __func__);
+
+	if (stv0367_readbits(state, F367TER_BYPASS_PLLXN) == 0) {
+		n = (u32)stv0367_readbits(state, F367TER_PLL_NDIV);
+		if (n == 0)
+			n = n + 1;
+
+		m = (u32)stv0367_readbits(state, F367TER_PLL_MDIV);
+		if (m == 0)
+			m = m + 1;
+
+		p = (u32)stv0367_readbits(state, F367TER_PLL_PDIV);
+		if (p > 5)
+			p = 5;
+
+		mclk_Hz = ((ExtClk_Hz / 2) * n) / (m * (1 << p));
+
+		dprintk("N=%d M=%d P=%d mclk_Hz=%d ExtClk_Hz=%d\n",
+				n, m, p, mclk_Hz, ExtClk_Hz);
+	} else
+		mclk_Hz = ExtClk_Hz;
+
+	dprintk("%s: mclk_Hz=%d\n", __func__, mclk_Hz);
+
+	return mclk_Hz;
+}
+
+static int stv0367ter_filt_coeff_init(struct stv0367_state *state,
+				u16 CellsCoeffs[3][6][5], u32 DemodXtal)
+{
+	int i, j, k, freq;
+
+	dprintk("%s:\n", __func__);
+
+	freq = stv0367ter_get_mclk(state, DemodXtal);
+
+	if (freq == 53125000)
+		k = 1; /* equivalent to Xtal 25M on 362*/
+	else if (freq == 54000000)
+		k = 0; /* equivalent to Xtal 27M on 362*/
+	else if (freq == 52500000)
+		k = 2; /* equivalent to Xtal 30M on 362*/
+	else
+		return 0;
+
+	for (i = 1; i <= 6; i++) {
+		stv0367_writebits(state, F367TER_IIR_CELL_NB, i - 1);
+
+		for (j = 1; j <= 5; j++) {
+			stv0367_writereg(state,
+				(R367TER_IIRCX_COEFF1_MSB + 2 * (j - 1)),
+				MSB(CellsCoeffs[k][i-1][j-1]));
+			stv0367_writereg(state,
+				(R367TER_IIRCX_COEFF1_LSB + 2 * (j - 1)),
+				LSB(CellsCoeffs[k][i-1][j-1]));
+		}
+	}
+
+	return 1;
+
+}
+
+static void stv0367ter_agc_iir_lock_detect_set(struct stv0367_state *state)
+{
+	dprintk("%s:\n", __func__);
+
+	stv0367_writebits(state, F367TER_LOCK_DETECT_LSB, 0x00);
+
+	/* Lock detect 1 */
+	stv0367_writebits(state, F367TER_LOCK_DETECT_CHOICE, 0x00);
+	stv0367_writebits(state, F367TER_LOCK_DETECT_MSB, 0x06);
+	stv0367_writebits(state, F367TER_AUT_AGC_TARGET_LSB, 0x04);
+
+	/* Lock detect 2 */
+	stv0367_writebits(state, F367TER_LOCK_DETECT_CHOICE, 0x01);
+	stv0367_writebits(state, F367TER_LOCK_DETECT_MSB, 0x06);
+	stv0367_writebits(state, F367TER_AUT_AGC_TARGET_LSB, 0x04);
+
+	/* Lock detect 3 */
+	stv0367_writebits(state, F367TER_LOCK_DETECT_CHOICE, 0x02);
+	stv0367_writebits(state, F367TER_LOCK_DETECT_MSB, 0x01);
+	stv0367_writebits(state, F367TER_AUT_AGC_TARGET_LSB, 0x00);
+
+	/* Lock detect 4 */
+	stv0367_writebits(state, F367TER_LOCK_DETECT_CHOICE, 0x03);
+	stv0367_writebits(state, F367TER_LOCK_DETECT_MSB, 0x01);
+	stv0367_writebits(state, F367TER_AUT_AGC_TARGET_LSB, 0x00);
+
+}
+
+static int stv0367_iir_filt_init(struct stv0367_state *state, u8 Bandwidth,
+							u32 DemodXtalValue)
+{
+	dprintk("%s:\n", __func__);
+
+	stv0367_writebits(state, F367TER_NRST_IIR, 0);
+
+	switch (Bandwidth) {
+	case 6:
+		if (!stv0367ter_filt_coeff_init(state,
+				CellsCoeffs_6MHz_367cofdm,
+				DemodXtalValue))
+			return 0;
+		break;
+	case 7:
+		if (!stv0367ter_filt_coeff_init(state,
+				CellsCoeffs_7MHz_367cofdm,
+				DemodXtalValue))
+			return 0;
+		break;
+	case 8:
+		if (!stv0367ter_filt_coeff_init(state,
+				CellsCoeffs_8MHz_367cofdm,
+				DemodXtalValue))
+			return 0;
+		break;
+	default:
+		return 0;
+	}
+
+	stv0367_writebits(state, F367TER_NRST_IIR, 1);
+
+	return 1;
+}
+
+static void stv0367ter_agc_iir_rst(struct stv0367_state *state)
+{
+
+	u8 com_n;
+
+	dprintk("%s:\n", __func__);
+
+	com_n = stv0367_readbits(state, F367TER_COM_N);
+
+	stv0367_writebits(state, F367TER_COM_N, 0x07);
+
+	stv0367_writebits(state, F367TER_COM_SOFT_RSTN, 0x00);
+	stv0367_writebits(state, F367TER_COM_AGC_ON, 0x00);
+
+	stv0367_writebits(state, F367TER_COM_SOFT_RSTN, 0x01);
+	stv0367_writebits(state, F367TER_COM_AGC_ON, 0x01);
+
+	stv0367_writebits(state, F367TER_COM_N, com_n);
+
+}
+
+static int stv0367ter_duration(s32 mode, int tempo1, int tempo2, int tempo3)
+{
+	int local_tempo = 0;
+	switch (mode) {
+	case 0:
+		local_tempo = tempo1;
+		break;
+	case 1:
+		local_tempo = tempo2;
+		break ;
+
+	case 2:
+		local_tempo = tempo3;
+		break;
+
+	default:
+		break;
+	}
+	/*	msleep(local_tempo);  */
+	return local_tempo;
+}
+
+static enum
+stv0367_ter_signal_type stv0367ter_check_syr(struct stv0367_state *state)
+{
+	int wd = 100;
+	unsigned short int SYR_var;
+	s32 SYRStatus;
+
+	dprintk("%s:\n", __func__);
+
+	SYR_var = stv0367_readbits(state, F367TER_SYR_LOCK);
+
+	while ((!SYR_var) && (wd > 0)) {
+		usleep_range(2000, 3000);
+		wd -= 2;
+		SYR_var = stv0367_readbits(state, F367TER_SYR_LOCK);
+	}
+
+	if (!SYR_var)
+		SYRStatus = FE_TER_NOSYMBOL;
+	else
+		SYRStatus =  FE_TER_SYMBOLOK;
+
+	dprintk("stv0367ter_check_syr SYRStatus %s\n",
+				SYR_var == 0 ? "No Symbol" : "OK");
+
+	return SYRStatus;
+}
+
+static enum
+stv0367_ter_signal_type stv0367ter_check_cpamp(struct stv0367_state *state,
+								s32 FFTmode)
+{
+
+	s32  CPAMPvalue = 0, CPAMPStatus, CPAMPMin;
+	int wd = 0;
+
+	dprintk("%s:\n", __func__);
+
+	switch (FFTmode) {
+	case 0: /*2k mode*/
+		CPAMPMin = 20;
+		wd = 10;
+		break;
+	case 1: /*8k mode*/
+		CPAMPMin = 80;
+		wd = 55;
+		break;
+	case 2: /*4k mode*/
+		CPAMPMin = 40;
+		wd = 30;
+		break;
+	default:
+		CPAMPMin = 0xffff;  /*drives to NOCPAMP	*/
+		break;
+	}
+
+	dprintk("%s: CPAMPMin=%d wd=%d\n", __func__, CPAMPMin, wd);
+
+	CPAMPvalue = stv0367_readbits(state, F367TER_PPM_CPAMP_DIRECT);
+	while ((CPAMPvalue < CPAMPMin) && (wd > 0)) {
+		usleep_range(1000, 2000);
+		wd -= 1;
+		CPAMPvalue = stv0367_readbits(state, F367TER_PPM_CPAMP_DIRECT);
+		/*dprintk("CPAMPvalue= %d at wd=%d\n",CPAMPvalue,wd); */
+	}
+	dprintk("******last CPAMPvalue= %d at wd=%d\n", CPAMPvalue, wd);
+	if (CPAMPvalue < CPAMPMin) {
+		CPAMPStatus = FE_TER_NOCPAMP;
+		printk(KERN_ERR "CPAMP failed\n");
+	} else {
+		printk(KERN_ERR "CPAMP OK !\n");
+		CPAMPStatus = FE_TER_CPAMPOK;
+	}
+
+	return CPAMPStatus;
+}
+
+enum
+stv0367_ter_signal_type stv0367ter_lock_algo(struct stv0367_state *state)
+{
+	enum stv0367_ter_signal_type ret_flag;
+	short int wd, tempo;
+	u8 try, u_var1 = 0, u_var2 = 0, u_var3 = 0, u_var4 = 0, mode, guard;
+	u8 tmp, tmp2;
+
+	dprintk("%s:\n", __func__);
+
+	if (state == NULL)
+		return FE_TER_SWNOK;
+
+	try = 0;
+	do {
+		ret_flag = FE_TER_LOCKOK;
+
+		stv0367_writebits(state, F367TER_CORE_ACTIVE, 0);
+
+		if (state->config->if_iq_mode != 0)
+			stv0367_writebits(state, F367TER_COM_N, 0x07);
+
+		stv0367_writebits(state, F367TER_GUARD, 3);/* suggest 2k 1/4 */
+		stv0367_writebits(state, F367TER_MODE, 0);
+		stv0367_writebits(state, F367TER_SYR_TR_DIS, 0);
+		usleep_range(5000, 10000);
+
+		stv0367_writebits(state, F367TER_CORE_ACTIVE, 1);
+
+
+		if (stv0367ter_check_syr(state) == FE_TER_NOSYMBOL)
+			return FE_TER_NOSYMBOL;
+		else { /*
+			if chip locked on wrong mode first try,
+			it must lock correctly second try */
+			mode = stv0367_readbits(state, F367TER_SYR_MODE);
+			if (stv0367ter_check_cpamp(state, mode) ==
+							FE_TER_NOCPAMP) {
+				if (try == 0)
+					ret_flag = FE_TER_NOCPAMP;
+
+			}
+		}
+
+		try++;
+	} while ((try < 10) && (ret_flag != FE_TER_LOCKOK));
+
+	tmp  = stv0367_readreg(state, R367TER_SYR_STAT);
+	tmp2 = stv0367_readreg(state, R367TER_STATUS);
+	dprintk("state=%p\n", state);
+	dprintk("LOCK OK! mode=%d SYR_STAT=0x%x R367TER_STATUS=0x%x\n",
+							mode, tmp, tmp2);
+
+	tmp  = stv0367_readreg(state, R367TER_PRVIT);
+	tmp2 = stv0367_readreg(state, R367TER_I2CRPT);
+	dprintk("PRVIT=0x%x I2CRPT=0x%x\n", tmp, tmp2);
+
+	tmp  = stv0367_readreg(state, R367TER_GAIN_SRC1);
+	dprintk("GAIN_SRC1=0x%x\n", tmp);
+
+	if ((mode != 0) && (mode != 1) && (mode != 2))
+		return FE_TER_SWNOK;
+
+	/*guard=stv0367_readbits(state,F367TER_SYR_GUARD); */
+
+	/*suppress EPQ auto for SYR_GARD 1/16 or 1/32
+	and set channel predictor in automatic */
+#if 0
+	switch (guard) {
+
+	case 0:
+	case 1:
+		stv0367_writebits(state, F367TER_AUTO_LE_EN, 0);
+		stv0367_writereg(state, R367TER_CHC_CTL, 0x01);
+		break;
+	case 2:
+	case 3:
+		stv0367_writebits(state, F367TER_AUTO_LE_EN, 1);
+		stv0367_writereg(state, R367TER_CHC_CTL, 0x11);
+		break;
+
+	default:
+		return FE_TER_SWNOK;
+	}
+#endif
+
+	/*reset fec an reedsolo FOR 367 only*/
+	stv0367_writebits(state, F367TER_RST_SFEC, 1);
+	stv0367_writebits(state, F367TER_RST_REEDSOLO, 1);
+	usleep_range(1000, 2000);
+	stv0367_writebits(state, F367TER_RST_SFEC, 0);
+	stv0367_writebits(state, F367TER_RST_REEDSOLO, 0);
+
+	u_var1 = stv0367_readbits(state, F367TER_LK);
+	u_var2 = stv0367_readbits(state, F367TER_PRF);
+	u_var3 = stv0367_readbits(state, F367TER_TPS_LOCK);
+	/*	u_var4=stv0367_readbits(state,F367TER_TSFIFO_LINEOK); */
+
+	wd = stv0367ter_duration(mode, 125, 500, 250);
+	tempo = stv0367ter_duration(mode, 4, 16, 8);
+
+	/*while ( ((!u_var1)||(!u_var2)||(!u_var3)||(!u_var4))  && (wd>=0)) */
+	while (((!u_var1) || (!u_var2) || (!u_var3)) && (wd >= 0)) {
+		usleep_range(1000 * tempo, 1000 * (tempo + 1));
+		wd -= tempo;
+		u_var1 = stv0367_readbits(state, F367TER_LK);
+		u_var2 = stv0367_readbits(state, F367TER_PRF);
+		u_var3 = stv0367_readbits(state, F367TER_TPS_LOCK);
+		/*u_var4=stv0367_readbits(state, F367TER_TSFIFO_LINEOK); */
+	}
+
+	if (!u_var1)
+		return FE_TER_NOLOCK;
+
+
+	if (!u_var2)
+		return FE_TER_NOPRFOUND;
+
+	if (!u_var3)
+		return FE_TER_NOTPS;
+
+	guard = stv0367_readbits(state, F367TER_SYR_GUARD);
+	stv0367_writereg(state, R367TER_CHC_CTL, 0x11);
+	switch (guard) {
+	case 0:
+	case 1:
+		stv0367_writebits(state, F367TER_AUTO_LE_EN, 0);
+		/*stv0367_writereg(state,R367TER_CHC_CTL, 0x1);*/
+		stv0367_writebits(state, F367TER_SYR_FILTER, 0);
+		break;
+	case 2:
+	case 3:
+		stv0367_writebits(state, F367TER_AUTO_LE_EN, 1);
+		/*stv0367_writereg(state,R367TER_CHC_CTL, 0x11);*/
+		stv0367_writebits(state, F367TER_SYR_FILTER, 1);
+		break;
+
+	default:
+		return FE_TER_SWNOK;
+	}
+
+	/* apply Sfec workaround if 8K 64QAM CR!=1/2*/
+	if ((stv0367_readbits(state, F367TER_TPS_CONST) == 2) &&
+			(mode == 1) &&
+			(stv0367_readbits(state, F367TER_TPS_HPCODE) != 0)) {
+		stv0367_writereg(state, R367TER_SFDLYSETH, 0xc0);
+		stv0367_writereg(state, R367TER_SFDLYSETM, 0x60);
+		stv0367_writereg(state, R367TER_SFDLYSETL, 0x0);
+	} else
+		stv0367_writereg(state, R367TER_SFDLYSETH, 0x0);
+
+	wd = stv0367ter_duration(mode, 125, 500, 250);
+	u_var4 = stv0367_readbits(state, F367TER_TSFIFO_LINEOK);
+
+	while ((!u_var4) && (wd >= 0)) {
+		usleep_range(1000 * tempo, 1000 * (tempo + 1));
+		wd -= tempo;
+		u_var4 = stv0367_readbits(state, F367TER_TSFIFO_LINEOK);
+	}
+
+	if (!u_var4)
+		return FE_TER_NOLOCK;
+
+	/* for 367 leave COM_N at 0x7 for IQ_mode*/
+	/*if(ter_state->if_iq_mode!=FE_TER_NORMAL_IF_TUNER) {
+		tempo=0;
+		while ((stv0367_readbits(state,F367TER_COM_USEGAINTRK)!=1) &&
+		(stv0367_readbits(state,F367TER_COM_AGCLOCK)!=1)&&(tempo<100)) {
+			ChipWaitOrAbort(state,1);
+			tempo+=1;
+		}
+
+		stv0367_writebits(state,F367TER_COM_N,0x17);
+	} */
+
+	stv0367_writebits(state, F367TER_SYR_TR_DIS, 1);
+
+	dprintk("FE_TER_LOCKOK !!!\n");
+
+	return	FE_TER_LOCKOK;
+
+}
+
+static void stv0367ter_set_ts_mode(struct stv0367_state *state,
+					enum stv0367_ts_mode PathTS)
+{
+
+	dprintk("%s:\n", __func__);
+
+	if (state == NULL)
+		return;
+
+	stv0367_writebits(state, F367TER_TS_DIS, 0);
+	switch (PathTS) {
+	default:
+		/*for removing warning :default we can assume in parallel mode*/
+	case STV0367_PARALLEL_PUNCT_CLOCK:
+		stv0367_writebits(state, F367TER_TSFIFO_SERIAL, 0);
+		stv0367_writebits(state, F367TER_TSFIFO_DVBCI, 0);
+		break;
+	case STV0367_SERIAL_PUNCT_CLOCK:
+		stv0367_writebits(state, F367TER_TSFIFO_SERIAL, 1);
+		stv0367_writebits(state, F367TER_TSFIFO_DVBCI, 1);
+		break;
+	}
+}
+
+static void stv0367ter_set_clk_pol(struct stv0367_state *state,
+					enum stv0367_clk_pol clock)
+{
+
+	dprintk("%s:\n", __func__);
+
+	if (state == NULL)
+		return;
+
+	switch (clock) {
+	case STV0367_RISINGEDGE_CLOCK:
+		stv0367_writebits(state, F367TER_TS_BYTE_CLK_INV, 1);
+		break;
+	case STV0367_FALLINGEDGE_CLOCK:
+		stv0367_writebits(state, F367TER_TS_BYTE_CLK_INV, 0);
+		break;
+		/*case FE_TER_CLOCK_POLARITY_DEFAULT:*/
+	default:
+		stv0367_writebits(state, F367TER_TS_BYTE_CLK_INV, 0);
+		break;
+	}
+}
+
+#if 0
+static void stv0367ter_core_sw(struct stv0367_state *state)
+{
+
+	dprintk("%s:\n", __func__);
+
+	stv0367_writebits(state, F367TER_CORE_ACTIVE, 0);
+	stv0367_writebits(state, F367TER_CORE_ACTIVE, 1);
+	msleep(350);
+}
+#endif
+static int stv0367ter_standby(struct dvb_frontend *fe, u8 standby_on)
+{
+	struct stv0367_state *state = fe->demodulator_priv;
+
+	dprintk("%s:\n", __func__);
+
+	if (standby_on) {
+		stv0367_writebits(state, F367TER_STDBY, 1);
+		stv0367_writebits(state, F367TER_STDBY_FEC, 1);
+		stv0367_writebits(state, F367TER_STDBY_CORE, 1);
+	} else {
+		stv0367_writebits(state, F367TER_STDBY, 0);
+		stv0367_writebits(state, F367TER_STDBY_FEC, 0);
+		stv0367_writebits(state, F367TER_STDBY_CORE, 0);
+	}
+
+	return 0;
+}
+
+static int stv0367ter_sleep(struct dvb_frontend *fe)
+{
+	return stv0367ter_standby(fe, 1);
+}
+
+int stv0367ter_init(struct dvb_frontend *fe)
+{
+	struct stv0367_state *state = fe->demodulator_priv;
+	struct stv0367ter_state *ter_state = state->ter_state;
+	int i;
+
+	dprintk("%s:\n", __func__);
+
+	ter_state->pBER = 0;
+
+	for (i = 0; i < STV0367TER_NBREGS; i++)
+		stv0367_writereg(state, def0367ter[i].addr,
+					def0367ter[i].value);
+
+	switch (state->config->xtal) {
+		/*set internal freq to 53.125MHz */
+	case 25000000:
+		stv0367_writereg(state, R367TER_PLLMDIV, 0xa);
+		stv0367_writereg(state, R367TER_PLLNDIV, 0x55);
+		stv0367_writereg(state, R367TER_PLLSETUP, 0x18);
+		break;
+	default:
+	case 27000000:
+		dprintk("FE_STV0367TER_SetCLKgen for 27Mhz\n");
+		stv0367_writereg(state, R367TER_PLLMDIV, 0x1);
+		stv0367_writereg(state, R367TER_PLLNDIV, 0x8);
+		stv0367_writereg(state, R367TER_PLLSETUP, 0x18);
+		break;
+	case 30000000:
+		stv0367_writereg(state, R367TER_PLLMDIV, 0xc);
+		stv0367_writereg(state, R367TER_PLLNDIV, 0x55);
+		stv0367_writereg(state, R367TER_PLLSETUP, 0x18);
+		break;
+	}
+
+	stv0367_writereg(state, R367TER_I2CRPT, 0xa0);
+	stv0367_writereg(state, R367TER_ANACTRL, 0x00);
+
+	/*Set TS1 and TS2 to serial or parallel mode */
+	stv0367ter_set_ts_mode(state, state->config->ts_mode);
+	stv0367ter_set_clk_pol(state, state->config->clk_pol);
+
+	state->chip_id = stv0367_readreg(state, R367TER_ID);
+	ter_state->first_lock = 0;
+	ter_state->unlock_counter = 2;
+
+	return 0;
+}
+
+static int stv0367ter_algo(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct stv0367_state *state = fe->demodulator_priv;
+	struct stv0367ter_state *ter_state = state->ter_state;
+	int offset = 0, tempo = 0;
+	u8 u_var;
+	u8 /*constell,*/ counter;
+	s8 step;
+	s32 timing_offset = 0;
+	u32 trl_nomrate = 0, InternalFreq = 0, temp = 0;
+
+	dprintk("%s:\n", __func__);
+
+	ter_state->frequency = p->frequency;
+	ter_state->force = FE_TER_FORCENONE
+			+ stv0367_readbits(state, F367TER_FORCE) * 2;
+	ter_state->if_iq_mode = state->config->if_iq_mode;
+	switch (state->config->if_iq_mode) {
+	case FE_TER_NORMAL_IF_TUNER:  /* Normal IF mode */
+		dprintk("ALGO: FE_TER_NORMAL_IF_TUNER selected\n");
+		stv0367_writebits(state, F367TER_TUNER_BB, 0);
+		stv0367_writebits(state, F367TER_LONGPATH_IF, 0);
+		stv0367_writebits(state, F367TER_DEMUX_SWAP, 0);
+		break;
+	case FE_TER_LONGPATH_IF_TUNER:  /* Long IF mode */
+		dprintk("ALGO: FE_TER_LONGPATH_IF_TUNER selected\n");
+		stv0367_writebits(state, F367TER_TUNER_BB, 0);
+		stv0367_writebits(state, F367TER_LONGPATH_IF, 1);
+		stv0367_writebits(state, F367TER_DEMUX_SWAP, 1);
+		break;
+	case FE_TER_IQ_TUNER:  /* IQ mode */
+		dprintk("ALGO: FE_TER_IQ_TUNER selected\n");
+		stv0367_writebits(state, F367TER_TUNER_BB, 1);
+		stv0367_writebits(state, F367TER_PPM_INVSEL, 0);
+		break;
+	default:
+		printk(KERN_ERR "ALGO: wrong TUNER type selected\n");
+		return -EINVAL;
+	}
+
+	usleep_range(5000, 7000);
+
+	switch (p->inversion) {
+	case INVERSION_AUTO:
+	default:
+		dprintk("%s: inversion AUTO\n", __func__);
+		if (ter_state->if_iq_mode == FE_TER_IQ_TUNER)
+			stv0367_writebits(state, F367TER_IQ_INVERT,
+						ter_state->sense);
+		else
+			stv0367_writebits(state, F367TER_INV_SPECTR,
+						ter_state->sense);
+
+		break;
+	case INVERSION_ON:
+	case INVERSION_OFF:
+		if (ter_state->if_iq_mode == FE_TER_IQ_TUNER)
+			stv0367_writebits(state, F367TER_IQ_INVERT,
+						p->inversion);
+		else
+			stv0367_writebits(state, F367TER_INV_SPECTR,
+						p->inversion);
+
+		break;
+	}
+
+	if ((ter_state->if_iq_mode != FE_TER_NORMAL_IF_TUNER) &&
+				(ter_state->pBW != ter_state->bw)) {
+		stv0367ter_agc_iir_lock_detect_set(state);
+
+		/*set fine agc target to 180 for LPIF or IQ mode*/
+		/* set Q_AGCTarget */
+		stv0367_writebits(state, F367TER_SEL_IQNTAR, 1);
+		stv0367_writebits(state, F367TER_AUT_AGC_TARGET_MSB, 0xB);
+		/*stv0367_writebits(state,AUT_AGC_TARGET_LSB,0x04); */
+
+		/* set Q_AGCTarget */
+		stv0367_writebits(state, F367TER_SEL_IQNTAR, 0);
+		stv0367_writebits(state, F367TER_AUT_AGC_TARGET_MSB, 0xB);
+		/*stv0367_writebits(state,AUT_AGC_TARGET_LSB,0x04); */
+
+		if (!stv0367_iir_filt_init(state, ter_state->bw,
+						state->config->xtal))
+			return -EINVAL;
+		/*set IIR filter once for 6,7 or 8MHz BW*/
+		ter_state->pBW = ter_state->bw;
+
+		stv0367ter_agc_iir_rst(state);
+	}
+
+	if (ter_state->hierarchy == FE_TER_HIER_LOW_PRIO)
+		stv0367_writebits(state, F367TER_BDI_LPSEL, 0x01);
+	else
+		stv0367_writebits(state, F367TER_BDI_LPSEL, 0x00);
+
+	InternalFreq = stv0367ter_get_mclk(state, state->config->xtal) / 1000;
+	temp = (int)
+		((((ter_state->bw * 64 * (1 << 15) * 100)
+						/ (InternalFreq)) * 10) / 7);
+
+	stv0367_writebits(state, F367TER_TRL_NOMRATE_LSB, temp % 2);
+	temp = temp / 2;
+	stv0367_writebits(state, F367TER_TRL_NOMRATE_HI, temp / 256);
+	stv0367_writebits(state, F367TER_TRL_NOMRATE_LO, temp % 256);
+
+	temp = stv0367_readbits(state, F367TER_TRL_NOMRATE_HI) * 512 +
+			stv0367_readbits(state, F367TER_TRL_NOMRATE_LO) * 2 +
+			stv0367_readbits(state, F367TER_TRL_NOMRATE_LSB);
+	temp = (int)(((1 << 17) * ter_state->bw * 1000) / (7 * (InternalFreq)));
+	stv0367_writebits(state, F367TER_GAIN_SRC_HI, temp / 256);
+	stv0367_writebits(state, F367TER_GAIN_SRC_LO, temp % 256);
+	temp = stv0367_readbits(state, F367TER_GAIN_SRC_HI) * 256 +
+			stv0367_readbits(state, F367TER_GAIN_SRC_LO);
+
+	temp = (int)
+		((InternalFreq - state->config->if_khz) * (1 << 16)
+							/ (InternalFreq));
+
+	dprintk("DEROT temp=0x%x\n", temp);
+	stv0367_writebits(state, F367TER_INC_DEROT_HI, temp / 256);
+	stv0367_writebits(state, F367TER_INC_DEROT_LO, temp % 256);
+
+	ter_state->echo_pos = 0;
+	ter_state->ucblocks = 0; /* liplianin */
+	ter_state->pBER = 0; /* liplianin */
+	stv0367_writebits(state, F367TER_LONG_ECHO, ter_state->echo_pos);
+
+	if (stv0367ter_lock_algo(state) != FE_TER_LOCKOK)
+		return 0;
+
+	ter_state->state = FE_TER_LOCKOK;
+
+	ter_state->mode = stv0367_readbits(state, F367TER_SYR_MODE);
+	ter_state->guard = stv0367_readbits(state, F367TER_SYR_GUARD);
+
+	ter_state->first_lock = 1; /* we know sense now :) */
+
+	ter_state->agc_val =
+			(stv0367_readbits(state, F367TER_AGC1_VAL_LO) << 16) +
+			(stv0367_readbits(state, F367TER_AGC1_VAL_HI) << 24) +
+			stv0367_readbits(state, F367TER_AGC2_VAL_LO) +
+			(stv0367_readbits(state, F367TER_AGC2_VAL_HI) << 8);
+
+	/* Carrier offset calculation */
+	stv0367_writebits(state, F367TER_FREEZE, 1);
+	offset = (stv0367_readbits(state, F367TER_CRL_FOFFSET_VHI) << 16) ;
+	offset += (stv0367_readbits(state, F367TER_CRL_FOFFSET_HI) << 8);
+	offset += (stv0367_readbits(state, F367TER_CRL_FOFFSET_LO));
+	stv0367_writebits(state, F367TER_FREEZE, 0);
+	if (offset > 8388607)
+		offset -= 16777216;
+
+	offset = offset * 2 / 16384;
+
+	if (ter_state->mode == FE_TER_MODE_2K)
+		offset = (offset * 4464) / 1000;/*** 1 FFT BIN=4.464khz***/
+	else if (ter_state->mode == FE_TER_MODE_4K)
+		offset = (offset * 223) / 100;/*** 1 FFT BIN=2.23khz***/
+	else  if (ter_state->mode == FE_TER_MODE_8K)
+		offset = (offset * 111) / 100;/*** 1 FFT BIN=1.1khz***/
+
+	if (stv0367_readbits(state, F367TER_PPM_INVSEL) == 1) {
+		if ((stv0367_readbits(state, F367TER_INV_SPECTR) ==
+				(stv0367_readbits(state,
+					F367TER_STATUS_INV_SPECRUM) == 1)))
+			offset = offset * -1;
+	}
+
+	if (ter_state->bw == 6)
+		offset = (offset * 6) / 8;
+	else if (ter_state->bw == 7)
+		offset = (offset * 7) / 8;
+
+	ter_state->frequency += offset;
+
+	tempo = 10;  /* exit even if timing_offset stays null */
+	while ((timing_offset == 0) && (tempo > 0)) {
+		usleep_range(10000, 20000);	/*was 20ms  */
+		/* fine tuning of timing offset if required */
+		timing_offset = stv0367_readbits(state, F367TER_TRL_TOFFSET_LO)
+				+ 256 * stv0367_readbits(state,
+							F367TER_TRL_TOFFSET_HI);
+		if (timing_offset >= 32768)
+			timing_offset -= 65536;
+		trl_nomrate = (512 * stv0367_readbits(state,
+							F367TER_TRL_NOMRATE_HI)
+			+ stv0367_readbits(state, F367TER_TRL_NOMRATE_LO) * 2
+			+ stv0367_readbits(state, F367TER_TRL_NOMRATE_LSB));
+
+		timing_offset = ((signed)(1000000 / trl_nomrate) *
+							timing_offset) / 2048;
+		tempo--;
+	}
+
+	if (timing_offset <= 0) {
+		timing_offset = (timing_offset - 11) / 22;
+		step = -1;
+	} else {
+		timing_offset = (timing_offset + 11) / 22;
+		step = 1;
+	}
+
+	for (counter = 0; counter < abs(timing_offset); counter++) {
+		trl_nomrate += step;
+		stv0367_writebits(state, F367TER_TRL_NOMRATE_LSB,
+						trl_nomrate % 2);
+		stv0367_writebits(state, F367TER_TRL_NOMRATE_LO,
+						trl_nomrate / 2);
+		usleep_range(1000, 2000);
+	}
+
+	usleep_range(5000, 6000);
+	/* unlocks could happen in case of trl centring big step,
+	then a core off/on restarts demod */
+	u_var = stv0367_readbits(state, F367TER_LK);
+
+	if (!u_var) {
+		stv0367_writebits(state, F367TER_CORE_ACTIVE, 0);
+		msleep(20);
+		stv0367_writebits(state, F367TER_CORE_ACTIVE, 1);
+	}
+
+	return 0;
+}
+
+static int stv0367ter_set_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct stv0367_state *state = fe->demodulator_priv;
+	struct stv0367ter_state *ter_state = state->ter_state;
+
+	/*u8 trials[2]; */
+	s8 num_trials, index;
+	u8 SenseTrials[] = { INVERSION_ON, INVERSION_OFF };
+
+	stv0367ter_init(fe);
+
+	if (fe->ops.tuner_ops.set_params) {
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 1);
+		fe->ops.tuner_ops.set_params(fe);
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 0);
+	}
+
+	switch (p->transmission_mode) {
+	default:
+	case TRANSMISSION_MODE_AUTO:
+	case TRANSMISSION_MODE_2K:
+		ter_state->mode = FE_TER_MODE_2K;
+		break;
+/*	case TRANSMISSION_MODE_4K:
+		pLook.mode = FE_TER_MODE_4K;
+		break;*/
+	case TRANSMISSION_MODE_8K:
+		ter_state->mode = FE_TER_MODE_8K;
+		break;
+	}
+
+	switch (p->guard_interval) {
+	default:
+	case GUARD_INTERVAL_1_32:
+	case GUARD_INTERVAL_1_16:
+	case GUARD_INTERVAL_1_8:
+	case GUARD_INTERVAL_1_4:
+		ter_state->guard = p->guard_interval;
+		break;
+	case GUARD_INTERVAL_AUTO:
+		ter_state->guard = GUARD_INTERVAL_1_32;
+		break;
+	}
+
+	switch (p->bandwidth_hz) {
+	case 6000000:
+		ter_state->bw = FE_TER_CHAN_BW_6M;
+		break;
+	case 7000000:
+		ter_state->bw = FE_TER_CHAN_BW_7M;
+		break;
+	case 8000000:
+	default:
+		ter_state->bw = FE_TER_CHAN_BW_8M;
+	}
+
+	ter_state->hierarchy = FE_TER_HIER_NONE;
+
+	switch (p->inversion) {
+	case INVERSION_OFF:
+	case INVERSION_ON:
+		num_trials = 1;
+		break;
+	default:
+		num_trials = 2;
+		if (ter_state->first_lock)
+			num_trials = 1;
+		break;
+	}
+
+	ter_state->state = FE_TER_NOLOCK;
+	index = 0;
+
+	while (((index) < num_trials) && (ter_state->state != FE_TER_LOCKOK)) {
+		if (!ter_state->first_lock) {
+			if (p->inversion == INVERSION_AUTO)
+				ter_state->sense = SenseTrials[index];
+
+		}
+		stv0367ter_algo(fe);
+
+		if ((ter_state->state == FE_TER_LOCKOK) &&
+				(p->inversion == INVERSION_AUTO) &&
+								(index == 1)) {
+			/* invert spectrum sense */
+			SenseTrials[index] = SenseTrials[0];
+			SenseTrials[(index + 1) % 2] = (SenseTrials[1] + 1) % 2;
+		}
+
+		index++;
+	}
+
+	return 0;
+}
+
+static int stv0367ter_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+	struct stv0367_state *state = fe->demodulator_priv;
+	struct stv0367ter_state *ter_state = state->ter_state;
+	u32 errs = 0;
+
+	/*wait for counting completion*/
+	if (stv0367_readbits(state, F367TER_SFERRC_OLDVALUE) == 0) {
+		errs =
+			((u32)stv0367_readbits(state, F367TER_ERR_CNT1)
+			* (1 << 16))
+			+ ((u32)stv0367_readbits(state, F367TER_ERR_CNT1_HI)
+			* (1 << 8))
+			+ ((u32)stv0367_readbits(state, F367TER_ERR_CNT1_LO));
+		ter_state->ucblocks = errs;
+	}
+
+	(*ucblocks) = ter_state->ucblocks;
+
+	return 0;
+}
+
+static int stv0367ter_get_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct stv0367_state *state = fe->demodulator_priv;
+	struct stv0367ter_state *ter_state = state->ter_state;
+
+	int error = 0;
+	enum stv0367_ter_mode mode;
+	int constell = 0,/* snr = 0,*/ Data = 0;
+
+	p->frequency = stv0367_get_tuner_freq(fe);
+	if ((int)p->frequency < 0)
+		p->frequency = -p->frequency;
+
+	constell = stv0367_readbits(state, F367TER_TPS_CONST);
+	if (constell == 0)
+		p->modulation = QPSK;
+	else if (constell == 1)
+		p->modulation = QAM_16;
+	else
+		p->modulation = QAM_64;
+
+	p->inversion = stv0367_readbits(state, F367TER_INV_SPECTR);
+
+	/* Get the Hierarchical mode */
+	Data = stv0367_readbits(state, F367TER_TPS_HIERMODE);
+
+	switch (Data) {
+	case 0:
+		p->hierarchy = HIERARCHY_NONE;
+		break;
+	case 1:
+		p->hierarchy = HIERARCHY_1;
+		break;
+	case 2:
+		p->hierarchy = HIERARCHY_2;
+		break;
+	case 3:
+		p->hierarchy = HIERARCHY_4;
+		break;
+	default:
+		p->hierarchy = HIERARCHY_AUTO;
+		break; /* error */
+	}
+
+	/* Get the FEC Rate */
+	if (ter_state->hierarchy == FE_TER_HIER_LOW_PRIO)
+		Data = stv0367_readbits(state, F367TER_TPS_LPCODE);
+	else
+		Data = stv0367_readbits(state, F367TER_TPS_HPCODE);
+
+	switch (Data) {
+	case 0:
+		p->code_rate_HP = FEC_1_2;
+		break;
+	case 1:
+		p->code_rate_HP = FEC_2_3;
+		break;
+	case 2:
+		p->code_rate_HP = FEC_3_4;
+		break;
+	case 3:
+		p->code_rate_HP = FEC_5_6;
+		break;
+	case 4:
+		p->code_rate_HP = FEC_7_8;
+		break;
+	default:
+		p->code_rate_HP = FEC_AUTO;
+		break; /* error */
+	}
+
+	mode = stv0367_readbits(state, F367TER_SYR_MODE);
+
+	switch (mode) {
+	case FE_TER_MODE_2K:
+		p->transmission_mode = TRANSMISSION_MODE_2K;
+		break;
+/*	case FE_TER_MODE_4K:
+		p->transmission_mode = TRANSMISSION_MODE_4K;
+		break;*/
+	case FE_TER_MODE_8K:
+		p->transmission_mode = TRANSMISSION_MODE_8K;
+		break;
+	default:
+		p->transmission_mode = TRANSMISSION_MODE_AUTO;
+	}
+
+	p->guard_interval = stv0367_readbits(state, F367TER_SYR_GUARD);
+
+	return error;
+}
+
+static int stv0367ter_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+	struct stv0367_state *state = fe->demodulator_priv;
+	u32 snru32 = 0;
+	int cpt = 0;
+	u8 cut = stv0367_readbits(state, F367TER_IDENTIFICATIONREG);
+
+	while (cpt < 10) {
+		usleep_range(2000, 3000);
+		if (cut == 0x50) /*cut 1.0 cut 1.1*/
+			snru32 += stv0367_readbits(state, F367TER_CHCSNR) / 4;
+		else /*cu2.0*/
+			snru32 += 125 * stv0367_readbits(state, F367TER_CHCSNR);
+
+		cpt++;
+	}
+
+	snru32 /= 10;/*average on 10 values*/
+
+	*snr = snru32 / 1000;
+
+	return 0;
+}
+
+#if 0
+static int stv0367ter_status(struct dvb_frontend *fe)
+{
+
+	struct stv0367_state *state = fe->demodulator_priv;
+	struct stv0367ter_state *ter_state = state->ter_state;
+	int locked = FALSE;
+
+	locked = (stv0367_readbits(state, F367TER_LK));
+	if (!locked)
+		ter_state->unlock_counter += 1;
+	else
+		ter_state->unlock_counter = 0;
+
+	if (ter_state->unlock_counter > 2) {
+		if (!stv0367_readbits(state, F367TER_TPS_LOCK) ||
+				(!stv0367_readbits(state, F367TER_LK))) {
+			stv0367_writebits(state, F367TER_CORE_ACTIVE, 0);
+			usleep_range(2000, 3000);
+			stv0367_writebits(state, F367TER_CORE_ACTIVE, 1);
+			msleep(350);
+			locked = (stv0367_readbits(state, F367TER_TPS_LOCK)) &&
+					(stv0367_readbits(state, F367TER_LK));
+		}
+
+	}
+
+	return locked;
+}
+#endif
+static int stv0367ter_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+	struct stv0367_state *state = fe->demodulator_priv;
+
+	dprintk("%s:\n", __func__);
+
+	*status = 0;
+
+	if (stv0367_readbits(state, F367TER_LK)) {
+		*status |= FE_HAS_LOCK;
+		dprintk("%s: stv0367 has locked\n", __func__);
+	}
+
+	return 0;
+}
+
+static int stv0367ter_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+	struct stv0367_state *state = fe->demodulator_priv;
+	struct stv0367ter_state *ter_state = state->ter_state;
+	u32 Errors = 0, tber = 0, temporary = 0;
+	int abc = 0, def = 0;
+
+
+	/*wait for counting completion*/
+	if (stv0367_readbits(state, F367TER_SFERRC_OLDVALUE) == 0)
+		Errors = ((u32)stv0367_readbits(state, F367TER_SFEC_ERR_CNT)
+			* (1 << 16))
+			+ ((u32)stv0367_readbits(state, F367TER_SFEC_ERR_CNT_HI)
+			* (1 << 8))
+			+ ((u32)stv0367_readbits(state,
+						F367TER_SFEC_ERR_CNT_LO));
+	/*measurement not completed, load previous value*/
+	else {
+		tber = ter_state->pBER;
+		return 0;
+	}
+
+	abc = stv0367_readbits(state, F367TER_SFEC_ERR_SOURCE);
+	def = stv0367_readbits(state, F367TER_SFEC_NUM_EVENT);
+
+	if (Errors == 0) {
+		tber = 0;
+	} else if (abc == 0x7) {
+		if (Errors <= 4) {
+			temporary = (Errors * 1000000000) / (8 * (1 << 14));
+			temporary =  temporary;
+		} else if (Errors <= 42) {
+			temporary = (Errors * 100000000) / (8 * (1 << 14));
+			temporary = temporary * 10;
+		} else if (Errors <= 429) {
+			temporary = (Errors * 10000000) / (8 * (1 << 14));
+			temporary = temporary * 100;
+		} else if (Errors <= 4294) {
+			temporary = (Errors * 1000000) / (8 * (1 << 14));
+			temporary = temporary * 1000;
+		} else if (Errors <= 42949) {
+			temporary = (Errors * 100000) / (8 * (1 << 14));
+			temporary = temporary * 10000;
+		} else if (Errors <= 429496) {
+			temporary = (Errors * 10000) / (8 * (1 << 14));
+			temporary = temporary * 100000;
+		} else { /*if (Errors<4294967) 2^22 max error*/
+			temporary = (Errors * 1000) / (8 * (1 << 14));
+			temporary = temporary * 100000;	/* still to *10 */
+		}
+
+		/* Byte error*/
+		if (def == 2)
+			/*tber=Errors/(8*(1 <<14));*/
+			tber = temporary;
+		else if (def == 3)
+			/*tber=Errors/(8*(1 <<16));*/
+			tber = temporary / 4;
+		else if (def == 4)
+			/*tber=Errors/(8*(1 <<18));*/
+			tber = temporary / 16;
+		else if (def == 5)
+			/*tber=Errors/(8*(1 <<20));*/
+			tber = temporary / 64;
+		else if (def == 6)
+			/*tber=Errors/(8*(1 <<22));*/
+			tber = temporary / 256;
+		else
+			/* should not pass here*/
+			tber = 0;
+
+		if ((Errors < 4294967) && (Errors > 429496))
+			tber *= 10;
+
+	}
+
+	/* save actual value */
+	ter_state->pBER = tber;
+
+	(*ber) = tber;
+
+	return 0;
+}
+#if 0
+static u32 stv0367ter_get_per(struct stv0367_state *state)
+{
+	struct stv0367ter_state *ter_state = state->ter_state;
+	u32 Errors = 0, Per = 0, temporary = 0;
+	int abc = 0, def = 0, cpt = 0;
+
+	while (((stv0367_readbits(state, F367TER_SFERRC_OLDVALUE) == 1) &&
+			(cpt < 400)) || ((Errors == 0) && (cpt < 400))) {
+		usleep_range(1000, 2000);
+		Errors = ((u32)stv0367_readbits(state, F367TER_ERR_CNT1)
+			* (1 << 16))
+			+ ((u32)stv0367_readbits(state, F367TER_ERR_CNT1_HI)
+			* (1 << 8))
+			+ ((u32)stv0367_readbits(state, F367TER_ERR_CNT1_LO));
+		cpt++;
+	}
+	abc = stv0367_readbits(state, F367TER_ERR_SRC1);
+	def = stv0367_readbits(state, F367TER_NUM_EVT1);
+
+	if (Errors == 0)
+		Per = 0;
+	else if (abc == 0x9) {
+		if (Errors <= 4) {
+			temporary = (Errors * 1000000000) / (8 * (1 << 8));
+			temporary =  temporary;
+		} else if (Errors <= 42) {
+			temporary = (Errors * 100000000) / (8 * (1 << 8));
+			temporary = temporary * 10;
+		} else if (Errors <= 429) {
+			temporary = (Errors * 10000000) / (8 * (1 << 8));
+			temporary = temporary * 100;
+		} else if (Errors <= 4294) {
+			temporary = (Errors * 1000000) / (8 * (1 << 8));
+			temporary = temporary * 1000;
+		} else if (Errors <= 42949) {
+			temporary = (Errors * 100000) / (8 * (1 << 8));
+			temporary = temporary * 10000;
+		} else { /*if(Errors<=429496)  2^16 errors max*/
+			temporary = (Errors * 10000) / (8 * (1 << 8));
+			temporary = temporary * 100000;
+		}
+
+		/* pkt error*/
+		if (def == 2)
+			/*Per=Errors/(1 << 8);*/
+			Per = temporary;
+		else if (def == 3)
+			/*Per=Errors/(1 << 10);*/
+			Per = temporary / 4;
+		else if (def == 4)
+			/*Per=Errors/(1 << 12);*/
+			Per = temporary / 16;
+		else if (def == 5)
+			/*Per=Errors/(1 << 14);*/
+			Per = temporary / 64;
+		else if (def == 6)
+			/*Per=Errors/(1 << 16);*/
+			Per = temporary / 256;
+		else
+			Per = 0;
+
+	}
+	/* save actual value */
+	ter_state->pPER = Per;
+
+	return Per;
+}
+#endif
+static int stv0367_get_tune_settings(struct dvb_frontend *fe,
+					struct dvb_frontend_tune_settings
+					*fe_tune_settings)
+{
+	fe_tune_settings->min_delay_ms = 1000;
+	fe_tune_settings->step_size = 0;
+	fe_tune_settings->max_drift = 0;
+
+	return 0;
+}
+
+static void stv0367_release(struct dvb_frontend *fe)
+{
+	struct stv0367_state *state = fe->demodulator_priv;
+
+	kfree(state->ter_state);
+	kfree(state->cab_state);
+	kfree(state);
+}
+
+static struct dvb_frontend_ops stv0367ter_ops = {
+	.delsys = { SYS_DVBT },
+	.info = {
+		.name			= "ST STV0367 DVB-T",
+		.frequency_min		= 47000000,
+		.frequency_max		= 862000000,
+		.frequency_stepsize	= 15625,
+		.frequency_tolerance	= 0,
+		.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_FEC_AUTO |
+			FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 |
+			FE_CAN_QAM_128 | FE_CAN_QAM_256 | FE_CAN_QAM_AUTO |
+			FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_RECOVER |
+			FE_CAN_INVERSION_AUTO |
+			FE_CAN_MUTE_TS
+	},
+	.release = stv0367_release,
+	.init = stv0367ter_init,
+	.sleep = stv0367ter_sleep,
+	.i2c_gate_ctrl = stv0367ter_gate_ctrl,
+	.set_frontend = stv0367ter_set_frontend,
+	.get_frontend = stv0367ter_get_frontend,
+	.get_tune_settings = stv0367_get_tune_settings,
+	.read_status = stv0367ter_read_status,
+	.read_ber = stv0367ter_read_ber,/* too slow */
+/*	.read_signal_strength = stv0367_read_signal_strength,*/
+	.read_snr = stv0367ter_read_snr,
+	.read_ucblocks = stv0367ter_read_ucblocks,
+};
+
+struct dvb_frontend *stv0367ter_attach(const struct stv0367_config *config,
+				   struct i2c_adapter *i2c)
+{
+	struct stv0367_state *state = NULL;
+	struct stv0367ter_state *ter_state = NULL;
+
+	/* allocate memory for the internal state */
+	state = kzalloc(sizeof(struct stv0367_state), GFP_KERNEL);
+	if (state == NULL)
+		goto error;
+	ter_state = kzalloc(sizeof(struct stv0367ter_state), GFP_KERNEL);
+	if (ter_state == NULL)
+		goto error;
+
+	/* setup the state */
+	state->i2c = i2c;
+	state->config = config;
+	state->ter_state = ter_state;
+	state->fe.ops = stv0367ter_ops;
+	state->fe.demodulator_priv = state;
+	state->chip_id = stv0367_readreg(state, 0xf000);
+
+	dprintk("%s: chip_id = 0x%x\n", __func__, state->chip_id);
+
+	/* check if the demod is there */
+	if ((state->chip_id != 0x50) && (state->chip_id != 0x60))
+		goto error;
+
+	return &state->fe;
+
+error:
+	kfree(ter_state);
+	kfree(state);
+	return NULL;
+}
+EXPORT_SYMBOL(stv0367ter_attach);
+
+static int stv0367cab_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+	struct stv0367_state *state = fe->demodulator_priv;
+
+	dprintk("%s:\n", __func__);
+
+	stv0367_writebits(state, F367CAB_I2CT_ON, (enable > 0) ? 1 : 0);
+
+	return 0;
+}
+
+static u32 stv0367cab_get_mclk(struct dvb_frontend *fe, u32 ExtClk_Hz)
+{
+	struct stv0367_state *state = fe->demodulator_priv;
+	u32 mclk_Hz = 0;/* master clock frequency (Hz) */
+	u32 M, N, P;
+
+
+	if (stv0367_readbits(state, F367CAB_BYPASS_PLLXN) == 0) {
+		N = (u32)stv0367_readbits(state, F367CAB_PLL_NDIV);
+		if (N == 0)
+			N = N + 1;
+
+		M = (u32)stv0367_readbits(state, F367CAB_PLL_MDIV);
+		if (M == 0)
+			M = M + 1;
+
+		P = (u32)stv0367_readbits(state, F367CAB_PLL_PDIV);
+
+		if (P > 5)
+			P = 5;
+
+		mclk_Hz = ((ExtClk_Hz / 2) * N) / (M * (1 << P));
+		dprintk("stv0367cab_get_mclk BYPASS_PLLXN mclk_Hz=%d\n",
+								mclk_Hz);
+	} else
+		mclk_Hz = ExtClk_Hz;
+
+	dprintk("stv0367cab_get_mclk final mclk_Hz=%d\n", mclk_Hz);
+
+	return mclk_Hz;
+}
+
+static u32 stv0367cab_get_adc_freq(struct dvb_frontend *fe, u32 ExtClk_Hz)
+{
+	u32 ADCClk_Hz = ExtClk_Hz;
+
+	ADCClk_Hz = stv0367cab_get_mclk(fe, ExtClk_Hz);
+
+	return ADCClk_Hz;
+}
+
+enum stv0367cab_mod stv0367cab_SetQamSize(struct stv0367_state *state,
+					u32 SymbolRate,
+					enum stv0367cab_mod QAMSize)
+{
+	/* Set QAM size */
+	stv0367_writebits(state, F367CAB_QAM_MODE, QAMSize);
+
+	/* Set Registers settings specific to the QAM size */
+	switch (QAMSize) {
+	case FE_CAB_MOD_QAM4:
+		stv0367_writereg(state, R367CAB_IQDEM_ADJ_AGC_REF, 0x00);
+		break;
+	case FE_CAB_MOD_QAM16:
+		stv0367_writereg(state, R367CAB_AGC_PWR_REF_L, 0x64);
+		stv0367_writereg(state, R367CAB_IQDEM_ADJ_AGC_REF, 0x00);
+		stv0367_writereg(state, R367CAB_FSM_STATE, 0x90);
+		stv0367_writereg(state, R367CAB_EQU_CTR_LPF_GAIN, 0xc1);
+		stv0367_writereg(state, R367CAB_EQU_CRL_LPF_GAIN, 0xa7);
+		stv0367_writereg(state, R367CAB_EQU_CRL_LD_SEN, 0x95);
+		stv0367_writereg(state, R367CAB_EQU_CRL_LIMITER, 0x40);
+		stv0367_writereg(state, R367CAB_EQU_PNT_GAIN, 0x8a);
+		break;
+	case FE_CAB_MOD_QAM32:
+		stv0367_writereg(state, R367CAB_IQDEM_ADJ_AGC_REF, 0x00);
+		stv0367_writereg(state, R367CAB_AGC_PWR_REF_L, 0x6e);
+		stv0367_writereg(state, R367CAB_FSM_STATE, 0xb0);
+		stv0367_writereg(state, R367CAB_EQU_CTR_LPF_GAIN, 0xc1);
+		stv0367_writereg(state, R367CAB_EQU_CRL_LPF_GAIN, 0xb7);
+		stv0367_writereg(state, R367CAB_EQU_CRL_LD_SEN, 0x9d);
+		stv0367_writereg(state, R367CAB_EQU_CRL_LIMITER, 0x7f);
+		stv0367_writereg(state, R367CAB_EQU_PNT_GAIN, 0xa7);
+		break;
+	case FE_CAB_MOD_QAM64:
+		stv0367_writereg(state, R367CAB_IQDEM_ADJ_AGC_REF, 0x82);
+		stv0367_writereg(state, R367CAB_AGC_PWR_REF_L, 0x5a);
+		if (SymbolRate > 45000000) {
+			stv0367_writereg(state, R367CAB_FSM_STATE, 0xb0);
+			stv0367_writereg(state, R367CAB_EQU_CTR_LPF_GAIN, 0xc1);
+			stv0367_writereg(state, R367CAB_EQU_CRL_LPF_GAIN, 0xa5);
+		} else if (SymbolRate > 25000000) {
+			stv0367_writereg(state, R367CAB_FSM_STATE, 0xa0);
+			stv0367_writereg(state, R367CAB_EQU_CTR_LPF_GAIN, 0xc1);
+			stv0367_writereg(state, R367CAB_EQU_CRL_LPF_GAIN, 0xa6);
+		} else {
+			stv0367_writereg(state, R367CAB_FSM_STATE, 0xa0);
+			stv0367_writereg(state, R367CAB_EQU_CTR_LPF_GAIN, 0xd1);
+			stv0367_writereg(state, R367CAB_EQU_CRL_LPF_GAIN, 0xa7);
+		}
+		stv0367_writereg(state, R367CAB_EQU_CRL_LD_SEN, 0x95);
+		stv0367_writereg(state, R367CAB_EQU_CRL_LIMITER, 0x40);
+		stv0367_writereg(state, R367CAB_EQU_PNT_GAIN, 0x99);
+		break;
+	case FE_CAB_MOD_QAM128:
+		stv0367_writereg(state, R367CAB_IQDEM_ADJ_AGC_REF, 0x00);
+		stv0367_writereg(state, R367CAB_AGC_PWR_REF_L, 0x76);
+		stv0367_writereg(state, R367CAB_FSM_STATE, 0x90);
+		stv0367_writereg(state, R367CAB_EQU_CTR_LPF_GAIN, 0xb1);
+		if (SymbolRate > 45000000)
+			stv0367_writereg(state, R367CAB_EQU_CRL_LPF_GAIN, 0xa7);
+		else if (SymbolRate > 25000000)
+			stv0367_writereg(state, R367CAB_EQU_CRL_LPF_GAIN, 0xa6);
+		else
+			stv0367_writereg(state, R367CAB_EQU_CRL_LPF_GAIN, 0x97);
+
+		stv0367_writereg(state, R367CAB_EQU_CRL_LD_SEN, 0x8e);
+		stv0367_writereg(state, R367CAB_EQU_CRL_LIMITER, 0x7f);
+		stv0367_writereg(state, R367CAB_EQU_PNT_GAIN, 0xa7);
+		break;
+	case FE_CAB_MOD_QAM256:
+		stv0367_writereg(state, R367CAB_IQDEM_ADJ_AGC_REF, 0x94);
+		stv0367_writereg(state, R367CAB_AGC_PWR_REF_L, 0x5a);
+		stv0367_writereg(state, R367CAB_FSM_STATE, 0xa0);
+		if (SymbolRate > 45000000)
+			stv0367_writereg(state, R367CAB_EQU_CTR_LPF_GAIN, 0xc1);
+		else if (SymbolRate > 25000000)
+			stv0367_writereg(state, R367CAB_EQU_CTR_LPF_GAIN, 0xc1);
+		else
+			stv0367_writereg(state, R367CAB_EQU_CTR_LPF_GAIN, 0xd1);
+
+		stv0367_writereg(state, R367CAB_EQU_CRL_LPF_GAIN, 0xa7);
+		stv0367_writereg(state, R367CAB_EQU_CRL_LD_SEN, 0x85);
+		stv0367_writereg(state, R367CAB_EQU_CRL_LIMITER, 0x40);
+		stv0367_writereg(state, R367CAB_EQU_PNT_GAIN, 0xa7);
+		break;
+	case FE_CAB_MOD_QAM512:
+		stv0367_writereg(state, R367CAB_IQDEM_ADJ_AGC_REF, 0x00);
+		break;
+	case FE_CAB_MOD_QAM1024:
+		stv0367_writereg(state, R367CAB_IQDEM_ADJ_AGC_REF, 0x00);
+		break;
+	default:
+		break;
+	}
+
+	return QAMSize;
+}
+
+static u32 stv0367cab_set_derot_freq(struct stv0367_state *state,
+					u32 adc_hz, s32 derot_hz)
+{
+	u32 sampled_if = 0;
+	u32 adc_khz;
+
+	adc_khz = adc_hz / 1000;
+
+	dprintk("%s: adc_hz=%d derot_hz=%d\n", __func__, adc_hz, derot_hz);
+
+	if (adc_khz != 0) {
+		if (derot_hz < 1000000)
+			derot_hz = adc_hz / 4; /* ZIF operation */
+		if (derot_hz > adc_hz)
+			derot_hz = derot_hz - adc_hz;
+		sampled_if = (u32)derot_hz / 1000;
+		sampled_if *= 32768;
+		sampled_if /= adc_khz;
+		sampled_if *= 256;
+	}
+
+	if (sampled_if > 8388607)
+		sampled_if = 8388607;
+
+	dprintk("%s: sampled_if=0x%x\n", __func__, sampled_if);
+
+	stv0367_writereg(state, R367CAB_MIX_NCO_LL, sampled_if);
+	stv0367_writereg(state, R367CAB_MIX_NCO_HL, (sampled_if >> 8));
+	stv0367_writebits(state, F367CAB_MIX_NCO_INC_HH, (sampled_if >> 16));
+
+	return derot_hz;
+}
+
+static u32 stv0367cab_get_derot_freq(struct stv0367_state *state, u32 adc_hz)
+{
+	u32 sampled_if;
+
+	sampled_if = stv0367_readbits(state, F367CAB_MIX_NCO_INC_LL) +
+			(stv0367_readbits(state, F367CAB_MIX_NCO_INC_HL) << 8) +
+			(stv0367_readbits(state, F367CAB_MIX_NCO_INC_HH) << 16);
+
+	sampled_if /= 256;
+	sampled_if *= (adc_hz / 1000);
+	sampled_if += 1;
+	sampled_if /= 32768;
+
+	return sampled_if;
+}
+
+static u32 stv0367cab_set_srate(struct stv0367_state *state, u32 adc_hz,
+			u32 mclk_hz, u32 SymbolRate,
+			enum stv0367cab_mod QAMSize)
+{
+	u32 QamSizeCorr = 0;
+	u32 u32_tmp = 0, u32_tmp1 = 0;
+	u32 adp_khz;
+
+	dprintk("%s:\n", __func__);
+
+	/* Set Correction factor of SRC gain */
+	switch (QAMSize) {
+	case FE_CAB_MOD_QAM4:
+		QamSizeCorr = 1110;
+		break;
+	case FE_CAB_MOD_QAM16:
+		QamSizeCorr = 1032;
+		break;
+	case FE_CAB_MOD_QAM32:
+		QamSizeCorr =  954;
+		break;
+	case FE_CAB_MOD_QAM64:
+		QamSizeCorr =  983;
+		break;
+	case FE_CAB_MOD_QAM128:
+		QamSizeCorr =  957;
+		break;
+	case FE_CAB_MOD_QAM256:
+		QamSizeCorr =  948;
+		break;
+	case FE_CAB_MOD_QAM512:
+		QamSizeCorr =    0;
+		break;
+	case FE_CAB_MOD_QAM1024:
+		QamSizeCorr =  944;
+		break;
+	default:
+		break;
+	}
+
+	/* Transfer ratio calculation */
+	if (adc_hz != 0) {
+		u32_tmp = 256 * SymbolRate;
+		u32_tmp = u32_tmp / adc_hz;
+	}
+	stv0367_writereg(state, R367CAB_EQU_CRL_TFR, (u8)u32_tmp);
+
+	/* Symbol rate and SRC gain calculation */
+	adp_khz = (mclk_hz >> 1) / 1000;/* TRL works at half the system clock */
+	if (adp_khz != 0) {
+		u32_tmp = SymbolRate;
+		u32_tmp1 = SymbolRate;
+
+		if (u32_tmp < 2097152) { /* 2097152 = 2^21 */
+			/* Symbol rate calculation */
+			u32_tmp *= 2048; /* 2048 = 2^11 */
+			u32_tmp = u32_tmp / adp_khz;
+			u32_tmp = u32_tmp * 16384; /* 16384 = 2^14 */
+			u32_tmp /= 125 ; /* 125 = 1000/2^3 */
+			u32_tmp = u32_tmp * 8; /* 8 = 2^3 */
+
+			/* SRC Gain Calculation */
+			u32_tmp1 *= 2048; /* *2*2^10 */
+			u32_tmp1 /= 439; /* *2/878 */
+			u32_tmp1 *= 256; /* *2^8 */
+			u32_tmp1 = u32_tmp1 / adp_khz; /* /(AdpClk in kHz) */
+			u32_tmp1 *= QamSizeCorr * 9; /* *1000*corr factor */
+			u32_tmp1 = u32_tmp1 / 10000000;
+
+		} else if (u32_tmp < 4194304) { /* 4194304 = 2**22 */
+			/* Symbol rate calculation */
+			u32_tmp *= 1024 ; /* 1024 = 2**10 */
+			u32_tmp = u32_tmp / adp_khz;
+			u32_tmp = u32_tmp * 16384; /* 16384 = 2**14 */
+			u32_tmp /= 125 ; /* 125 = 1000/2**3 */
+			u32_tmp = u32_tmp * 16; /* 16 = 2**4 */
+
+			/* SRC Gain Calculation */
+			u32_tmp1 *= 1024; /* *2*2^9 */
+			u32_tmp1 /= 439; /* *2/878 */
+			u32_tmp1 *= 256; /* *2^8 */
+			u32_tmp1 = u32_tmp1 / adp_khz; /* /(AdpClk in kHz)*/
+			u32_tmp1 *= QamSizeCorr * 9; /* *1000*corr factor */
+			u32_tmp1 = u32_tmp1 / 5000000;
+		} else if (u32_tmp < 8388607) { /* 8388607 = 2**23 */
+			/* Symbol rate calculation */
+			u32_tmp *= 512 ; /* 512 = 2**9 */
+			u32_tmp = u32_tmp / adp_khz;
+			u32_tmp = u32_tmp * 16384; /* 16384 = 2**14 */
+			u32_tmp /= 125 ; /* 125 = 1000/2**3 */
+			u32_tmp = u32_tmp * 32; /* 32 = 2**5 */
+
+			/* SRC Gain Calculation */
+			u32_tmp1 *= 512; /* *2*2^8 */
+			u32_tmp1 /= 439; /* *2/878 */
+			u32_tmp1 *= 256; /* *2^8 */
+			u32_tmp1 = u32_tmp1 / adp_khz; /* /(AdpClk in kHz) */
+			u32_tmp1 *= QamSizeCorr * 9; /* *1000*corr factor */
+			u32_tmp1 = u32_tmp1 / 2500000;
+		} else {
+			/* Symbol rate calculation */
+			u32_tmp *= 256 ; /* 256 = 2**8 */
+			u32_tmp = u32_tmp / adp_khz;
+			u32_tmp = u32_tmp * 16384; /* 16384 = 2**13 */
+			u32_tmp /= 125 ; /* 125 = 1000/2**3 */
+			u32_tmp = u32_tmp * 64; /* 64 = 2**6 */
+
+			/* SRC Gain Calculation */
+			u32_tmp1 *= 256; /* 2*2^7 */
+			u32_tmp1 /= 439; /* *2/878 */
+			u32_tmp1 *= 256; /* *2^8 */
+			u32_tmp1 = u32_tmp1 / adp_khz; /* /(AdpClk in kHz) */
+			u32_tmp1 *= QamSizeCorr * 9; /* *1000*corr factor */
+			u32_tmp1 = u32_tmp1 / 1250000;
+		}
+	}
+#if 0
+	/* Filters' coefficients are calculated and written
+	into registers only if the filters are enabled */
+	if (stv0367_readbits(state, F367CAB_ADJ_EN)) {
+		stv0367cab_SetIirAdjacentcoefficient(state, mclk_hz,
+								SymbolRate);
+		/* AllPass filter must be enabled
+		when the adjacents filter is used */
+		stv0367_writebits(state, F367CAB_ALLPASSFILT_EN, 1);
+		stv0367cab_SetAllPasscoefficient(state, mclk_hz, SymbolRate);
+	} else
+		/* AllPass filter must be disabled
+		when the adjacents filter is not used */
+#endif
+	stv0367_writebits(state, F367CAB_ALLPASSFILT_EN, 0);
+
+	stv0367_writereg(state, R367CAB_SRC_NCO_LL, u32_tmp);
+	stv0367_writereg(state, R367CAB_SRC_NCO_LH, (u32_tmp >> 8));
+	stv0367_writereg(state, R367CAB_SRC_NCO_HL, (u32_tmp >> 16));
+	stv0367_writereg(state, R367CAB_SRC_NCO_HH, (u32_tmp >> 24));
+
+	stv0367_writereg(state, R367CAB_IQDEM_GAIN_SRC_L, u32_tmp1 & 0x00ff);
+	stv0367_writebits(state, F367CAB_GAIN_SRC_HI, (u32_tmp1 >> 8) & 0x00ff);
+
+	return SymbolRate ;
+}
+
+static u32 stv0367cab_GetSymbolRate(struct stv0367_state *state, u32 mclk_hz)
+{
+	u32 regsym;
+	u32 adp_khz;
+
+	regsym = stv0367_readreg(state, R367CAB_SRC_NCO_LL) +
+		(stv0367_readreg(state, R367CAB_SRC_NCO_LH) << 8) +
+		(stv0367_readreg(state, R367CAB_SRC_NCO_HL) << 16) +
+		(stv0367_readreg(state, R367CAB_SRC_NCO_HH) << 24);
+
+	adp_khz = (mclk_hz >> 1) / 1000;/* TRL works at half the system clock */
+
+	if (regsym < 134217728) {		/* 134217728L = 2**27*/
+		regsym = regsym * 32;		/* 32 = 2**5 */
+		regsym = regsym / 32768;	/* 32768L = 2**15 */
+		regsym = adp_khz * regsym;	/* AdpClk in kHz */
+		regsym = regsym / 128;		/* 128 = 2**7 */
+		regsym *= 125 ;			/* 125 = 1000/2**3 */
+		regsym /= 2048 ;		/* 2048 = 2**11	*/
+	} else if (regsym < 268435456) {	/* 268435456L = 2**28 */
+		regsym = regsym * 16;		/* 16 = 2**4 */
+		regsym = regsym / 32768;	/* 32768L = 2**15 */
+		regsym = adp_khz * regsym;	/* AdpClk in kHz */
+		regsym = regsym / 128;		/* 128 = 2**7 */
+		regsym *= 125 ;			/* 125 = 1000/2**3*/
+		regsym /= 1024 ;		/* 256 = 2**10*/
+	} else if (regsym < 536870912) {	/* 536870912L = 2**29*/
+		regsym = regsym * 8;		/* 8 = 2**3 */
+		regsym = regsym / 32768;	/* 32768L = 2**15 */
+		regsym = adp_khz * regsym;	/* AdpClk in kHz */
+		regsym = regsym / 128;		/* 128 = 2**7 */
+		regsym *= 125 ;			/* 125 = 1000/2**3 */
+		regsym /= 512 ;			/* 128 = 2**9 */
+	} else {
+		regsym = regsym * 4;		/* 4 = 2**2 */
+		regsym = regsym / 32768;	/* 32768L = 2**15 */
+		regsym = adp_khz * regsym;	/* AdpClk in kHz */
+		regsym = regsym / 128;		/* 128 = 2**7 */
+		regsym *= 125 ;			/* 125 = 1000/2**3 */
+		regsym /= 256 ;			/* 64 = 2**8 */
+	}
+
+	return regsym;
+}
+
+static int stv0367cab_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+	struct stv0367_state *state = fe->demodulator_priv;
+
+	dprintk("%s:\n", __func__);
+
+	*status = 0;
+
+	if (stv0367_readbits(state, F367CAB_QAMFEC_LOCK)) {
+		*status |= FE_HAS_LOCK;
+		dprintk("%s: stv0367 has locked\n", __func__);
+	}
+
+	return 0;
+}
+
+static int stv0367cab_standby(struct dvb_frontend *fe, u8 standby_on)
+{
+	struct stv0367_state *state = fe->demodulator_priv;
+
+	dprintk("%s:\n", __func__);
+
+	if (standby_on) {
+		stv0367_writebits(state, F367CAB_BYPASS_PLLXN, 0x03);
+		stv0367_writebits(state, F367CAB_STDBY_PLLXN, 0x01);
+		stv0367_writebits(state, F367CAB_STDBY, 1);
+		stv0367_writebits(state, F367CAB_STDBY_CORE, 1);
+		stv0367_writebits(state, F367CAB_EN_BUFFER_I, 0);
+		stv0367_writebits(state, F367CAB_EN_BUFFER_Q, 0);
+		stv0367_writebits(state, F367CAB_POFFQ, 1);
+		stv0367_writebits(state, F367CAB_POFFI, 1);
+	} else {
+		stv0367_writebits(state, F367CAB_STDBY_PLLXN, 0x00);
+		stv0367_writebits(state, F367CAB_BYPASS_PLLXN, 0x00);
+		stv0367_writebits(state, F367CAB_STDBY, 0);
+		stv0367_writebits(state, F367CAB_STDBY_CORE, 0);
+		stv0367_writebits(state, F367CAB_EN_BUFFER_I, 1);
+		stv0367_writebits(state, F367CAB_EN_BUFFER_Q, 1);
+		stv0367_writebits(state, F367CAB_POFFQ, 0);
+		stv0367_writebits(state, F367CAB_POFFI, 0);
+	}
+
+	return 0;
+}
+
+static int stv0367cab_sleep(struct dvb_frontend *fe)
+{
+	return stv0367cab_standby(fe, 1);
+}
+
+int stv0367cab_init(struct dvb_frontend *fe)
+{
+	struct stv0367_state *state = fe->demodulator_priv;
+	struct stv0367cab_state *cab_state = state->cab_state;
+	int i;
+
+	dprintk("%s:\n", __func__);
+
+	for (i = 0; i < STV0367CAB_NBREGS; i++)
+		stv0367_writereg(state, def0367cab[i].addr,
+						def0367cab[i].value);
+
+	switch (state->config->ts_mode) {
+	case STV0367_DVBCI_CLOCK:
+		dprintk("Setting TSMode = STV0367_DVBCI_CLOCK\n");
+		stv0367_writebits(state, F367CAB_OUTFORMAT, 0x03);
+		break;
+	case STV0367_SERIAL_PUNCT_CLOCK:
+	case STV0367_SERIAL_CONT_CLOCK:
+		stv0367_writebits(state, F367CAB_OUTFORMAT, 0x01);
+		break;
+	case STV0367_PARALLEL_PUNCT_CLOCK:
+	case STV0367_OUTPUTMODE_DEFAULT:
+		stv0367_writebits(state, F367CAB_OUTFORMAT, 0x00);
+		break;
+	}
+
+	switch (state->config->clk_pol) {
+	case STV0367_RISINGEDGE_CLOCK:
+		stv0367_writebits(state, F367CAB_CLK_POLARITY, 0x00);
+		break;
+	case STV0367_FALLINGEDGE_CLOCK:
+	case STV0367_CLOCKPOLARITY_DEFAULT:
+		stv0367_writebits(state, F367CAB_CLK_POLARITY, 0x01);
+		break;
+	}
+
+	stv0367_writebits(state, F367CAB_SYNC_STRIP, 0x00);
+
+	stv0367_writebits(state, F367CAB_CT_NBST, 0x01);
+
+	stv0367_writebits(state, F367CAB_TS_SWAP, 0x01);
+
+	stv0367_writebits(state, F367CAB_FIFO_BYPASS, 0x00);
+
+	stv0367_writereg(state, R367CAB_ANACTRL, 0x00);/*PLL enabled and used */
+
+	cab_state->mclk = stv0367cab_get_mclk(fe, state->config->xtal);
+	cab_state->adc_clk = stv0367cab_get_adc_freq(fe, state->config->xtal);
+
+	return 0;
+}
+static
+enum stv0367_cab_signal_type stv0367cab_algo(struct stv0367_state *state,
+					     struct dtv_frontend_properties *p)
+{
+	struct stv0367cab_state *cab_state = state->cab_state;
+	enum stv0367_cab_signal_type signalType = FE_CAB_NOAGC;
+	u32	QAMFEC_Lock, QAM_Lock, u32_tmp,
+		LockTime, TRLTimeOut, AGCTimeOut, CRLSymbols,
+		CRLTimeOut, EQLTimeOut, DemodTimeOut, FECTimeOut;
+	u8	TrackAGCAccum;
+	s32	tmp;
+
+	dprintk("%s:\n", __func__);
+
+	/* Timeouts calculation */
+	/* A max lock time of 25 ms is allowed for delayed AGC */
+	AGCTimeOut = 25;
+	/* 100000 symbols needed by the TRL as a maximum value */
+	TRLTimeOut = 100000000 / p->symbol_rate;
+	/* CRLSymbols is the needed number of symbols to achieve a lock
+	   within [-4%, +4%] of the symbol rate.
+	   CRL timeout is calculated
+	   for a lock within [-search_range, +search_range].
+	   EQL timeout can be changed depending on
+	   the micro-reflections we want to handle.
+	   A characterization must be performed
+	   with these echoes to get new timeout values.
+	*/
+	switch (p->modulation) {
+	case QAM_16:
+		CRLSymbols = 150000;
+		EQLTimeOut = 100;
+		break;
+	case QAM_32:
+		CRLSymbols = 250000;
+		EQLTimeOut = 100;
+		break;
+	case QAM_64:
+		CRLSymbols = 200000;
+		EQLTimeOut = 100;
+		break;
+	case QAM_128:
+		CRLSymbols = 250000;
+		EQLTimeOut = 100;
+		break;
+	case QAM_256:
+		CRLSymbols = 250000;
+		EQLTimeOut = 100;
+		break;
+	default:
+		CRLSymbols = 200000;
+		EQLTimeOut = 100;
+		break;
+	}
+#if 0
+	if (pIntParams->search_range < 0) {
+		CRLTimeOut = (25 * CRLSymbols *
+				(-pIntParams->search_range / 1000)) /
+					(pIntParams->symbol_rate / 1000);
+	} else
+#endif
+	CRLTimeOut = (25 * CRLSymbols * (cab_state->search_range / 1000)) /
+					(p->symbol_rate / 1000);
+
+	CRLTimeOut = (1000 * CRLTimeOut) / p->symbol_rate;
+	/* Timeouts below 50ms are coerced */
+	if (CRLTimeOut < 50)
+		CRLTimeOut = 50;
+	/* A maximum of 100 TS packets is needed to get FEC lock even in case
+	the spectrum inversion needs to be changed.
+	   This is equal to 20 ms in case of the lowest symbol rate of 0.87Msps
+	*/
+	FECTimeOut = 20;
+	DemodTimeOut = AGCTimeOut + TRLTimeOut + CRLTimeOut + EQLTimeOut;
+
+	dprintk("%s: DemodTimeOut=%d\n", __func__, DemodTimeOut);
+
+	/* Reset the TRL to ensure nothing starts until the
+	   AGC is stable which ensures a better lock time
+	*/
+	stv0367_writereg(state, R367CAB_CTRL_1, 0x04);
+	/* Set AGC accumulation time to minimum and lock threshold to maximum
+	in order to speed up the AGC lock */
+	TrackAGCAccum = stv0367_readbits(state, F367CAB_AGC_ACCUMRSTSEL);
+	stv0367_writebits(state, F367CAB_AGC_ACCUMRSTSEL, 0x0);
+	/* Modulus Mapper is disabled */
+	stv0367_writebits(state, F367CAB_MODULUSMAP_EN, 0);
+	/* Disable the sweep function */
+	stv0367_writebits(state, F367CAB_SWEEP_EN, 0);
+	/* The sweep function is never used, Sweep rate must be set to 0 */
+	/* Set the derotator frequency in Hz */
+	stv0367cab_set_derot_freq(state, cab_state->adc_clk,
+		(1000 * (s32)state->config->if_khz + cab_state->derot_offset));
+	/* Disable the Allpass Filter when the symbol rate is out of range */
+	if ((p->symbol_rate > 10800000) | (p->symbol_rate < 1800000)) {
+		stv0367_writebits(state, F367CAB_ADJ_EN, 0);
+		stv0367_writebits(state, F367CAB_ALLPASSFILT_EN, 0);
+	}
+#if 0
+	/* Check if the tuner is locked */
+	tuner_lock = stv0367cab_tuner_get_status(fe);
+	if (tuner_lock == 0)
+		return FE_367CAB_NOTUNER;
+#endif
+	/* Relase the TRL to start demodulator acquisition */
+	/* Wait for QAM lock */
+	LockTime = 0;
+	stv0367_writereg(state, R367CAB_CTRL_1, 0x00);
+	do {
+		QAM_Lock = stv0367_readbits(state, F367CAB_FSM_STATUS);
+		if ((LockTime >= (DemodTimeOut - EQLTimeOut)) &&
+							(QAM_Lock == 0x04))
+			/*
+			 * We don't wait longer, the frequency/phase offset
+			 * must be too big
+			 */
+			LockTime = DemodTimeOut;
+		else if ((LockTime >= (AGCTimeOut + TRLTimeOut)) &&
+							(QAM_Lock == 0x02))
+			/*
+			 * We don't wait longer, either there is no signal or
+			 * it is not the right symbol rate or it is an analog
+			 * carrier
+			 */
+		{
+			LockTime = DemodTimeOut;
+			u32_tmp = stv0367_readbits(state,
+						F367CAB_AGC_PWR_WORD_LO) +
+					(stv0367_readbits(state,
+						F367CAB_AGC_PWR_WORD_ME) << 8) +
+					(stv0367_readbits(state,
+						F367CAB_AGC_PWR_WORD_HI) << 16);
+			if (u32_tmp >= 131072)
+				u32_tmp = 262144 - u32_tmp;
+			u32_tmp = u32_tmp / (1 << (11 - stv0367_readbits(state,
+							F367CAB_AGC_IF_BWSEL)));
+
+			if (u32_tmp < stv0367_readbits(state,
+						F367CAB_AGC_PWRREF_LO) +
+					256 * stv0367_readbits(state,
+						F367CAB_AGC_PWRREF_HI) - 10)
+				QAM_Lock = 0x0f;
+		} else {
+			usleep_range(10000, 20000);
+			LockTime += 10;
+		}
+		dprintk("QAM_Lock=0x%x LockTime=%d\n", QAM_Lock, LockTime);
+		tmp = stv0367_readreg(state, R367CAB_IT_STATUS1);
+
+		dprintk("R367CAB_IT_STATUS1=0x%x\n", tmp);
+
+	} while (((QAM_Lock != 0x0c) && (QAM_Lock != 0x0b)) &&
+						(LockTime < DemodTimeOut));
+
+	dprintk("QAM_Lock=0x%x\n", QAM_Lock);
+
+	tmp = stv0367_readreg(state, R367CAB_IT_STATUS1);
+	dprintk("R367CAB_IT_STATUS1=0x%x\n", tmp);
+	tmp = stv0367_readreg(state, R367CAB_IT_STATUS2);
+	dprintk("R367CAB_IT_STATUS2=0x%x\n", tmp);
+
+	tmp  = stv0367cab_get_derot_freq(state, cab_state->adc_clk);
+	dprintk("stv0367cab_get_derot_freq=0x%x\n", tmp);
+
+	if ((QAM_Lock == 0x0c) || (QAM_Lock == 0x0b)) {
+		/* Wait for FEC lock */
+		LockTime = 0;
+		do {
+			usleep_range(5000, 7000);
+			LockTime += 5;
+			QAMFEC_Lock = stv0367_readbits(state,
+							F367CAB_QAMFEC_LOCK);
+		} while (!QAMFEC_Lock && (LockTime < FECTimeOut));
+	} else
+		QAMFEC_Lock = 0;
+
+	if (QAMFEC_Lock) {
+		signalType = FE_CAB_DATAOK;
+		cab_state->modulation = p->modulation;
+		cab_state->spect_inv = stv0367_readbits(state,
+							F367CAB_QUAD_INV);
+#if 0
+/* not clear for me */
+		if (state->config->if_khz != 0) {
+			if (state->config->if_khz > cab_state->adc_clk / 1000) {
+				cab_state->freq_khz =
+					FE_Cab_TunerGetFrequency(pIntParams->hTuner)
+				- stv0367cab_get_derot_freq(state, cab_state->adc_clk)
+				- cab_state->adc_clk / 1000 + state->config->if_khz;
+			} else {
+				cab_state->freq_khz =
+						FE_Cab_TunerGetFrequency(pIntParams->hTuner)
+						- stv0367cab_get_derot_freq(state, cab_state->adc_clk)
+										+ state->config->if_khz;
+			}
+		} else {
+			cab_state->freq_khz =
+				FE_Cab_TunerGetFrequency(pIntParams->hTuner) +
+				stv0367cab_get_derot_freq(state,
+							cab_state->adc_clk) -
+				cab_state->adc_clk / 4000;
+		}
+#endif
+		cab_state->symbol_rate = stv0367cab_GetSymbolRate(state,
+							cab_state->mclk);
+		cab_state->locked = 1;
+
+		/* stv0367_setbits(state, F367CAB_AGC_ACCUMRSTSEL,7);*/
+	} else {
+		switch (QAM_Lock) {
+		case 1:
+			signalType = FE_CAB_NOAGC;
+			break;
+		case 2:
+			signalType = FE_CAB_NOTIMING;
+			break;
+		case 3:
+			signalType = FE_CAB_TIMINGOK;
+			break;
+		case 4:
+			signalType = FE_CAB_NOCARRIER;
+			break;
+		case 5:
+			signalType = FE_CAB_CARRIEROK;
+			break;
+		case 7:
+			signalType = FE_CAB_NOBLIND;
+			break;
+		case 8:
+			signalType = FE_CAB_BLINDOK;
+			break;
+		case 10:
+			signalType = FE_CAB_NODEMOD;
+			break;
+		case 11:
+			signalType = FE_CAB_DEMODOK;
+			break;
+		case 12:
+			signalType = FE_CAB_DEMODOK;
+			break;
+		case 13:
+			signalType = FE_CAB_NODEMOD;
+			break;
+		case 14:
+			signalType = FE_CAB_NOBLIND;
+			break;
+		case 15:
+			signalType = FE_CAB_NOSIGNAL;
+			break;
+		default:
+			break;
+		}
+
+	}
+
+	/* Set the AGC control values to tracking values */
+	stv0367_writebits(state, F367CAB_AGC_ACCUMRSTSEL, TrackAGCAccum);
+	return signalType;
+}
+
+static int stv0367cab_set_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct stv0367_state *state = fe->demodulator_priv;
+	struct stv0367cab_state *cab_state = state->cab_state;
+	enum stv0367cab_mod QAMSize = 0;
+
+	dprintk("%s: freq = %d, srate = %d\n", __func__,
+					p->frequency, p->symbol_rate);
+
+	cab_state->derot_offset = 0;
+
+	switch (p->modulation) {
+	case QAM_16:
+		QAMSize = FE_CAB_MOD_QAM16;
+		break;
+	case QAM_32:
+		QAMSize = FE_CAB_MOD_QAM32;
+		break;
+	case QAM_64:
+		QAMSize = FE_CAB_MOD_QAM64;
+		break;
+	case QAM_128:
+		QAMSize = FE_CAB_MOD_QAM128;
+		break;
+	case QAM_256:
+		QAMSize = FE_CAB_MOD_QAM256;
+		break;
+	default:
+		break;
+	}
+
+	stv0367cab_init(fe);
+
+	/* Tuner Frequency Setting */
+	if (fe->ops.tuner_ops.set_params) {
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 1);
+		fe->ops.tuner_ops.set_params(fe);
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 0);
+	}
+
+	stv0367cab_SetQamSize(
+			state,
+			p->symbol_rate,
+			QAMSize);
+
+	stv0367cab_set_srate(state,
+			cab_state->adc_clk,
+			cab_state->mclk,
+			p->symbol_rate,
+			QAMSize);
+	/* Search algorithm launch, [-1.1*RangeOffset, +1.1*RangeOffset] scan */
+	cab_state->state = stv0367cab_algo(state, p);
+	return 0;
+}
+
+static int stv0367cab_get_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct stv0367_state *state = fe->demodulator_priv;
+	struct stv0367cab_state *cab_state = state->cab_state;
+
+	enum stv0367cab_mod QAMSize;
+
+	dprintk("%s:\n", __func__);
+
+	p->symbol_rate = stv0367cab_GetSymbolRate(state, cab_state->mclk);
+
+	QAMSize = stv0367_readbits(state, F367CAB_QAM_MODE);
+	switch (QAMSize) {
+	case FE_CAB_MOD_QAM16:
+		p->modulation = QAM_16;
+		break;
+	case FE_CAB_MOD_QAM32:
+		p->modulation = QAM_32;
+		break;
+	case FE_CAB_MOD_QAM64:
+		p->modulation = QAM_64;
+		break;
+	case FE_CAB_MOD_QAM128:
+		p->modulation = QAM_128;
+		break;
+	case QAM_256:
+		p->modulation = QAM_256;
+		break;
+	default:
+		break;
+	}
+
+	p->frequency = stv0367_get_tuner_freq(fe);
+
+	dprintk("%s: tuner frequency = %d\n", __func__, p->frequency);
+
+	if (state->config->if_khz == 0) {
+		p->frequency +=
+			(stv0367cab_get_derot_freq(state, cab_state->adc_clk) -
+			cab_state->adc_clk / 4000);
+		return 0;
+	}
+
+	if (state->config->if_khz > cab_state->adc_clk / 1000)
+		p->frequency += (state->config->if_khz
+			- stv0367cab_get_derot_freq(state, cab_state->adc_clk)
+			- cab_state->adc_clk / 1000);
+	else
+		p->frequency += (state->config->if_khz
+			- stv0367cab_get_derot_freq(state, cab_state->adc_clk));
+
+	return 0;
+}
+
+#if 0
+void stv0367cab_GetErrorCount(state, enum stv0367cab_mod QAMSize,
+			u32 symbol_rate, FE_367qam_Monitor *Monitor_results)
+{
+	stv0367cab_OptimiseNByteAndGetBER(state, QAMSize, symbol_rate, Monitor_results);
+	stv0367cab_GetPacketsCount(state, Monitor_results);
+
+	return;
+}
+
+static int stv0367cab_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+	struct stv0367_state *state = fe->demodulator_priv;
+
+	return 0;
+}
+#endif
+static s32 stv0367cab_get_rf_lvl(struct stv0367_state *state)
+{
+	s32 rfLevel = 0;
+	s32 RfAgcPwm = 0, IfAgcPwm = 0;
+	u8 i;
+
+	stv0367_writebits(state, F367CAB_STDBY_ADCGP, 0x0);
+
+	RfAgcPwm =
+		(stv0367_readbits(state, F367CAB_RF_AGC1_LEVEL_LO) & 0x03) +
+		(stv0367_readbits(state, F367CAB_RF_AGC1_LEVEL_HI) << 2);
+	RfAgcPwm = 100 * RfAgcPwm / 1023;
+
+	IfAgcPwm =
+		stv0367_readbits(state, F367CAB_AGC_IF_PWMCMD_LO) +
+		(stv0367_readbits(state, F367CAB_AGC_IF_PWMCMD_HI) << 8);
+	if (IfAgcPwm >= 2048)
+		IfAgcPwm -= 2048;
+	else
+		IfAgcPwm += 2048;
+
+	IfAgcPwm = 100 * IfAgcPwm / 4095;
+
+	/* For DTT75467 on NIM */
+	if (RfAgcPwm < 90  && IfAgcPwm < 28) {
+		for (i = 0; i < RF_LOOKUP_TABLE_SIZE; i++) {
+			if (RfAgcPwm <= stv0367cab_RF_LookUp1[0][i]) {
+				rfLevel = (-1) * stv0367cab_RF_LookUp1[1][i];
+				break;
+			}
+		}
+		if (i == RF_LOOKUP_TABLE_SIZE)
+			rfLevel = -56;
+	} else { /*if IF AGC>10*/
+		for (i = 0; i < RF_LOOKUP_TABLE2_SIZE; i++) {
+			if (IfAgcPwm <= stv0367cab_RF_LookUp2[0][i]) {
+				rfLevel = (-1) * stv0367cab_RF_LookUp2[1][i];
+				break;
+			}
+		}
+		if (i == RF_LOOKUP_TABLE2_SIZE)
+			rfLevel = -72;
+	}
+	return rfLevel;
+}
+
+static int stv0367cab_read_strength(struct dvb_frontend *fe, u16 *strength)
+{
+	struct stv0367_state *state = fe->demodulator_priv;
+
+	s32 signal =  stv0367cab_get_rf_lvl(state);
+
+	dprintk("%s: signal=%d dBm\n", __func__, signal);
+
+	if (signal <= -72)
+		*strength = 65535;
+	else
+		*strength = (22 + signal) * (-1311);
+
+	dprintk("%s: strength=%d\n", __func__, (*strength));
+
+	return 0;
+}
+
+static int stv0367cab_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+	struct stv0367_state *state = fe->demodulator_priv;
+	u32 noisepercentage;
+	enum stv0367cab_mod QAMSize;
+	u32 regval = 0, temp = 0;
+	int power, i;
+
+	QAMSize = stv0367_readbits(state, F367CAB_QAM_MODE);
+	switch (QAMSize) {
+	case FE_CAB_MOD_QAM4:
+		power = 21904;
+		break;
+	case FE_CAB_MOD_QAM16:
+		power = 20480;
+		break;
+	case FE_CAB_MOD_QAM32:
+		power = 23040;
+		break;
+	case FE_CAB_MOD_QAM64:
+		power = 21504;
+		break;
+	case FE_CAB_MOD_QAM128:
+		power = 23616;
+		break;
+	case FE_CAB_MOD_QAM256:
+		power = 21760;
+		break;
+	case FE_CAB_MOD_QAM512:
+		power = 1;
+		break;
+	case FE_CAB_MOD_QAM1024:
+		power = 21280;
+		break;
+	default:
+		power = 1;
+		break;
+	}
+
+	for (i = 0; i < 10; i++) {
+		regval += (stv0367_readbits(state, F367CAB_SNR_LO)
+			+ 256 * stv0367_readbits(state, F367CAB_SNR_HI));
+	}
+
+	regval /= 10; /*for average over 10 times in for loop above*/
+	if (regval != 0) {
+		temp = power
+			* (1 << (3 + stv0367_readbits(state, F367CAB_SNR_PER)));
+		temp /= regval;
+	}
+
+	/* table values, not needed to calculate logarithms */
+	if (temp >= 5012)
+		noisepercentage = 100;
+	else if (temp >= 3981)
+		noisepercentage = 93;
+	else if (temp >= 3162)
+		noisepercentage = 86;
+	else if (temp >= 2512)
+		noisepercentage = 79;
+	else if (temp >= 1995)
+		noisepercentage = 72;
+	else if (temp >= 1585)
+		noisepercentage = 65;
+	else if (temp >= 1259)
+		noisepercentage = 58;
+	else if (temp >= 1000)
+		noisepercentage = 50;
+	else if (temp >= 794)
+		noisepercentage = 43;
+	else if (temp >= 501)
+		noisepercentage = 36;
+	else if (temp >= 316)
+		noisepercentage = 29;
+	else if (temp >= 200)
+		noisepercentage = 22;
+	else if (temp >= 158)
+		noisepercentage = 14;
+	else if (temp >= 126)
+		noisepercentage = 7;
+	else
+		noisepercentage = 0;
+
+	dprintk("%s: noisepercentage=%d\n", __func__, noisepercentage);
+
+	*snr = (noisepercentage * 65535) / 100;
+
+	return 0;
+}
+
+static int stv0367cab_read_ucblcks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+	struct stv0367_state *state = fe->demodulator_priv;
+	int corrected, tscount;
+
+	*ucblocks = (stv0367_readreg(state, R367CAB_RS_COUNTER_5) << 8)
+			| stv0367_readreg(state, R367CAB_RS_COUNTER_4);
+	corrected = (stv0367_readreg(state, R367CAB_RS_COUNTER_3) << 8)
+			| stv0367_readreg(state, R367CAB_RS_COUNTER_2);
+	tscount = (stv0367_readreg(state, R367CAB_RS_COUNTER_2) << 8)
+			| stv0367_readreg(state, R367CAB_RS_COUNTER_1);
+
+	dprintk("%s: uncorrected blocks=%d corrected blocks=%d tscount=%d\n",
+				__func__, *ucblocks, corrected, tscount);
+
+	return 0;
+};
+
+static struct dvb_frontend_ops stv0367cab_ops = {
+	.delsys = { SYS_DVBC_ANNEX_A },
+	.info = {
+		.name = "ST STV0367 DVB-C",
+		.frequency_min = 47000000,
+		.frequency_max = 862000000,
+		.frequency_stepsize = 62500,
+		.symbol_rate_min = 870000,
+		.symbol_rate_max = 11700000,
+		.caps = 0x400 |/* FE_CAN_QAM_4 */
+			FE_CAN_QAM_16 | FE_CAN_QAM_32  |
+			FE_CAN_QAM_64 | FE_CAN_QAM_128 |
+			FE_CAN_QAM_256 | FE_CAN_FEC_AUTO
+	},
+	.release				= stv0367_release,
+	.init					= stv0367cab_init,
+	.sleep					= stv0367cab_sleep,
+	.i2c_gate_ctrl				= stv0367cab_gate_ctrl,
+	.set_frontend				= stv0367cab_set_frontend,
+	.get_frontend				= stv0367cab_get_frontend,
+	.read_status				= stv0367cab_read_status,
+/*	.read_ber				= stv0367cab_read_ber, */
+	.read_signal_strength			= stv0367cab_read_strength,
+	.read_snr				= stv0367cab_read_snr,
+	.read_ucblocks				= stv0367cab_read_ucblcks,
+	.get_tune_settings			= stv0367_get_tune_settings,
+};
+
+struct dvb_frontend *stv0367cab_attach(const struct stv0367_config *config,
+				   struct i2c_adapter *i2c)
+{
+	struct stv0367_state *state = NULL;
+	struct stv0367cab_state *cab_state = NULL;
+
+	/* allocate memory for the internal state */
+	state = kzalloc(sizeof(struct stv0367_state), GFP_KERNEL);
+	if (state == NULL)
+		goto error;
+	cab_state = kzalloc(sizeof(struct stv0367cab_state), GFP_KERNEL);
+	if (cab_state == NULL)
+		goto error;
+
+	/* setup the state */
+	state->i2c = i2c;
+	state->config = config;
+	cab_state->search_range = 280000;
+	state->cab_state = cab_state;
+	state->fe.ops = stv0367cab_ops;
+	state->fe.demodulator_priv = state;
+	state->chip_id = stv0367_readreg(state, 0xf000);
+
+	dprintk("%s: chip_id = 0x%x\n", __func__, state->chip_id);
+
+	/* check if the demod is there */
+	if ((state->chip_id != 0x50) && (state->chip_id != 0x60))
+		goto error;
+
+	return &state->fe;
+
+error:
+	kfree(cab_state);
+	kfree(state);
+	return NULL;
+}
+EXPORT_SYMBOL(stv0367cab_attach);
+
+MODULE_PARM_DESC(debug, "Set debug");
+MODULE_PARM_DESC(i2c_debug, "Set i2c debug");
+
+MODULE_AUTHOR("Igor M. Liplianin");
+MODULE_DESCRIPTION("ST STV0367 DVB-C/T demodulator driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb-frontends/stv0367.h b/drivers/media/dvb-frontends/stv0367.h
new file mode 100644
index 0000000..93cc4a5
--- /dev/null
+++ b/drivers/media/dvb-frontends/stv0367.h
@@ -0,0 +1,66 @@
+/*
+ * stv0367.h
+ *
+ * Driver for ST STV0367 DVB-T & DVB-C demodulator IC.
+ *
+ * Copyright (C) ST Microelectronics.
+ * Copyright (C) 2010,2011 NetUP Inc.
+ * Copyright (C) 2010,2011 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 STV0367_H
+#define STV0367_H
+
+#include <linux/dvb/frontend.h>
+#include "dvb_frontend.h"
+
+struct stv0367_config {
+	u8 demod_address;
+	u32 xtal;
+	u32 if_khz;/*4500*/
+	int if_iq_mode;
+	int ts_mode;
+	int clk_pol;
+};
+
+#if defined(CONFIG_DVB_STV0367) || (defined(CONFIG_DVB_STV0367_MODULE) \
+							&& defined(MODULE))
+extern struct
+dvb_frontend *stv0367ter_attach(const struct stv0367_config *config,
+					struct i2c_adapter *i2c);
+extern struct
+dvb_frontend *stv0367cab_attach(const struct stv0367_config *config,
+					struct i2c_adapter *i2c);
+#else
+static inline struct
+dvb_frontend *stv0367ter_attach(const struct stv0367_config *config,
+					struct i2c_adapter *i2c)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+static inline struct
+dvb_frontend *stv0367cab_attach(const struct stv0367_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/stv0367_priv.h b/drivers/media/dvb-frontends/stv0367_priv.h
new file mode 100644
index 0000000..995db06
--- /dev/null
+++ b/drivers/media/dvb-frontends/stv0367_priv.h
@@ -0,0 +1,212 @@
+/*
+ * stv0367_priv.h
+ *
+ * Driver for ST STV0367 DVB-T & DVB-C demodulator IC.
+ *
+ * Copyright (C) ST Microelectronics.
+ * Copyright (C) 2010,2011 NetUP Inc.
+ * Copyright (C) 2010,2011 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.
+ */
+/* Common driver error constants */
+
+#ifndef STV0367_PRIV_H
+#define STV0367_PRIV_H
+
+#ifndef TRUE
+    #define TRUE (1 == 1)
+#endif
+#ifndef FALSE
+    #define FALSE (!TRUE)
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+/* MACRO definitions */
+#define ABS(X) ((X) < 0 ? (-1 * (X)) : (X))
+#define MAX(X, Y) ((X) >= (Y) ? (X) : (Y))
+#define MIN(X, Y) ((X) <= (Y) ? (X) : (Y))
+#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)
+#define MMSB(Y)(((Y) >> 16) & 0xff)
+
+enum stv0367_ter_signal_type {
+	FE_TER_NOAGC = 0,
+	FE_TER_AGCOK = 5,
+	FE_TER_NOTPS = 6,
+	FE_TER_TPSOK = 7,
+	FE_TER_NOSYMBOL = 8,
+	FE_TER_BAD_CPQ = 9,
+	FE_TER_PRFOUNDOK = 10,
+	FE_TER_NOPRFOUND = 11,
+	FE_TER_LOCKOK = 12,
+	FE_TER_NOLOCK = 13,
+	FE_TER_SYMBOLOK = 15,
+	FE_TER_CPAMPOK = 16,
+	FE_TER_NOCPAMP = 17,
+	FE_TER_SWNOK = 18
+};
+
+enum stv0367_ts_mode {
+	STV0367_OUTPUTMODE_DEFAULT,
+	STV0367_SERIAL_PUNCT_CLOCK,
+	STV0367_SERIAL_CONT_CLOCK,
+	STV0367_PARALLEL_PUNCT_CLOCK,
+	STV0367_DVBCI_CLOCK
+};
+
+enum stv0367_clk_pol {
+	STV0367_CLOCKPOLARITY_DEFAULT,
+	STV0367_RISINGEDGE_CLOCK,
+	STV0367_FALLINGEDGE_CLOCK
+};
+
+enum stv0367_ter_bw {
+	FE_TER_CHAN_BW_6M = 6,
+	FE_TER_CHAN_BW_7M = 7,
+	FE_TER_CHAN_BW_8M = 8
+};
+
+#if 0
+enum FE_TER_Rate_TPS {
+	FE_TER_TPS_1_2 = 0,
+	FE_TER_TPS_2_3 = 1,
+	FE_TER_TPS_3_4 = 2,
+	FE_TER_TPS_5_6 = 3,
+	FE_TER_TPS_7_8 = 4
+};
+#endif
+
+enum stv0367_ter_mode {
+	FE_TER_MODE_2K,
+	FE_TER_MODE_8K,
+	FE_TER_MODE_4K
+};
+#if 0
+enum FE_TER_Hierarchy_Alpha {
+	FE_TER_HIER_ALPHA_NONE,	/* Regular modulation */
+	FE_TER_HIER_ALPHA_1,	/* Hierarchical modulation a = 1*/
+	FE_TER_HIER_ALPHA_2,	/* Hierarchical modulation a = 2*/
+	FE_TER_HIER_ALPHA_4	/* Hierarchical modulation a = 4*/
+};
+#endif
+enum stv0367_ter_hierarchy {
+	FE_TER_HIER_NONE,	/*Hierarchy None*/
+	FE_TER_HIER_LOW_PRIO,	/*Hierarchy : Low Priority*/
+	FE_TER_HIER_HIGH_PRIO,	/*Hierarchy : High Priority*/
+	FE_TER_HIER_PRIO_ANY	/*Hierarchy  :Any*/
+};
+
+#if 0
+enum fe_stv0367_ter_spec {
+	FE_TER_INVERSION_NONE = 0,
+	FE_TER_INVERSION = 1,
+	FE_TER_INVERSION_AUTO = 2,
+	FE_TER_INVERSION_UNK  = 4
+};
+#endif
+
+enum stv0367_ter_if_iq_mode {
+	FE_TER_NORMAL_IF_TUNER = 0,
+	FE_TER_LONGPATH_IF_TUNER = 1,
+	FE_TER_IQ_TUNER = 2
+
+};
+
+#if 0
+enum FE_TER_FECRate {
+	FE_TER_FEC_NONE = 0x00,	/* no FEC rate specified */
+	FE_TER_FEC_ALL = 0xFF,	 /* Logical OR of all FECs */
+	FE_TER_FEC_1_2 = 1,
+	FE_TER_FEC_2_3 = (1 << 1),
+	FE_TER_FEC_3_4 = (1 << 2),
+	FE_TER_FEC_4_5 = (1 << 3),
+	FE_TER_FEC_5_6 = (1 << 4),
+	FE_TER_FEC_6_7 = (1 << 5),
+	FE_TER_FEC_7_8 = (1 << 6),
+	FE_TER_FEC_8_9 = (1 << 7)
+};
+
+enum FE_TER_Rate {
+	FE_TER_FE_1_2 = 0,
+	FE_TER_FE_2_3 = 1,
+	FE_TER_FE_3_4 = 2,
+	FE_TER_FE_5_6 = 3,
+	FE_TER_FE_6_7 = 4,
+	FE_TER_FE_7_8 = 5
+};
+#endif
+
+enum stv0367_ter_force {
+	FE_TER_FORCENONE = 0,
+	FE_TER_FORCE_M_G = 1
+};
+
+enum  stv0367cab_mod {
+	FE_CAB_MOD_QAM4,
+	FE_CAB_MOD_QAM16,
+	FE_CAB_MOD_QAM32,
+	FE_CAB_MOD_QAM64,
+	FE_CAB_MOD_QAM128,
+	FE_CAB_MOD_QAM256,
+	FE_CAB_MOD_QAM512,
+	FE_CAB_MOD_QAM1024
+};
+#if 0
+enum {
+	FE_CAB_FEC_A = 1,	/* J83 Annex A */
+	FE_CAB_FEC_B = (1 << 1),/* J83 Annex B */
+	FE_CAB_FEC_C = (1 << 2)	/* J83 Annex C */
+} FE_CAB_FECType_t;
+#endif
+struct stv0367_cab_signal_info {
+	int locked;
+	u32 frequency; /* kHz */
+	u32 symbol_rate; /* Mbds */
+	enum stv0367cab_mod modulation;
+	fe_spectral_inversion_t spect_inv;
+	s32 Power_dBmx10;	/* Power of the RF signal (dBm x 10) */
+	u32	CN_dBx10;	/* Carrier to noise ratio (dB x 10) */
+	u32	BER;		/* Bit error rate (x 10000000)	*/
+};
+
+enum stv0367_cab_signal_type {
+	FE_CAB_NOTUNER,
+	FE_CAB_NOAGC,
+	FE_CAB_NOSIGNAL,
+	FE_CAB_NOTIMING,
+	FE_CAB_TIMINGOK,
+	FE_CAB_NOCARRIER,
+	FE_CAB_CARRIEROK,
+	FE_CAB_NOBLIND,
+	FE_CAB_BLINDOK,
+	FE_CAB_NODEMOD,
+	FE_CAB_DEMODOK,
+	FE_CAB_DATAOK
+};
+
+#endif
diff --git a/drivers/media/dvb-frontends/stv0367_regs.h b/drivers/media/dvb-frontends/stv0367_regs.h
new file mode 100644
index 0000000..a96fbdc
--- /dev/null
+++ b/drivers/media/dvb-frontends/stv0367_regs.h
@@ -0,0 +1,3614 @@
+/*
+ * stv0367_regs.h
+ *
+ * Driver for ST STV0367 DVB-T & DVB-C demodulator IC.
+ *
+ * Copyright (C) ST Microelectronics.
+ * Copyright (C) 2010,2011 NetUP Inc.
+ * Copyright (C) 2010,2011 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 STV0367_REGS_H
+#define STV0367_REGS_H
+
+/* ID */
+#define	R367TER_ID	0xf000
+#define	F367TER_IDENTIFICATIONREG	0xf00000ff
+
+/* I2CRPT */
+#define	R367TER_I2CRPT	0xf001
+#define	F367TER_I2CT_ON	0xf0010080
+#define	F367TER_ENARPT_LEVEL	0xf0010070
+#define	F367TER_SCLT_DELAY	0xf0010008
+#define	F367TER_SCLT_NOD	0xf0010004
+#define	F367TER_STOP_ENABLE	0xf0010002
+#define	F367TER_SDAT_NOD	0xf0010001
+
+/* TOPCTRL */
+#define	R367TER_TOPCTRL	0xf002
+#define	F367TER_STDBY	0xf0020080
+#define	F367TER_STDBY_FEC	0xf0020040
+#define	F367TER_STDBY_CORE	0xf0020020
+#define	F367TER_QAM_COFDM	0xf0020010
+#define	F367TER_TS_DIS	0xf0020008
+#define	F367TER_DIR_CLK_216	0xf0020004
+#define	F367TER_TUNER_BB	0xf0020002
+#define	F367TER_DVBT_H	0xf0020001
+
+/* IOCFG0 */
+#define	R367TER_IOCFG0	0xf003
+#define	F367TER_OP0_SD	0xf0030080
+#define	F367TER_OP0_VAL	0xf0030040
+#define	F367TER_OP0_OD	0xf0030020
+#define	F367TER_OP0_INV	0xf0030010
+#define	F367TER_OP0_DACVALUE_HI	0xf003000f
+
+/* DAc0R */
+#define	R367TER_DAC0R	0xf004
+#define	F367TER_OP0_DACVALUE_LO	0xf00400ff
+
+/* IOCFG1 */
+#define	R367TER_IOCFG1	0xf005
+#define	F367TER_IP0	0xf0050040
+#define	F367TER_OP1_OD	0xf0050020
+#define	F367TER_OP1_INV	0xf0050010
+#define	F367TER_OP1_DACVALUE_HI	0xf005000f
+
+/* DAC1R */
+#define	R367TER_DAC1R	0xf006
+#define	F367TER_OP1_DACVALUE_LO	0xf00600ff
+
+/* IOCFG2 */
+#define	R367TER_IOCFG2	0xf007
+#define	F367TER_OP2_LOCK_CONF	0xf00700e0
+#define	F367TER_OP2_OD	0xf0070010
+#define	F367TER_OP2_VAL	0xf0070008
+#define	F367TER_OP1_LOCK_CONF	0xf0070007
+
+/* SDFR */
+#define	R367TER_SDFR	0xf008
+#define	F367TER_OP0_FREQ	0xf00800f0
+#define	F367TER_OP1_FREQ	0xf008000f
+
+/* STATUS */
+#define	R367TER_STATUS	0xf009
+#define	F367TER_TPS_LOCK	0xf0090080
+#define	F367TER_SYR_LOCK	0xf0090040
+#define	F367TER_AGC_LOCK	0xf0090020
+#define	F367TER_PRF	0xf0090010
+#define	F367TER_LK	0xf0090008
+#define	F367TER_PR	0xf0090007
+
+/* AUX_CLK */
+#define	R367TER_AUX_CLK	0xf00a
+#define	F367TER_AUXFEC_CTL	0xf00a00c0
+#define	F367TER_DIS_CKX4	0xf00a0020
+#define	F367TER_CKSEL	0xf00a0018
+#define	F367TER_CKDIV_PROG	0xf00a0006
+#define	F367TER_AUXCLK_ENA	0xf00a0001
+
+/* FREESYS1 */
+#define	R367TER_FREESYS1	0xf00b
+#define	F367TER_FREE_SYS1	0xf00b00ff
+
+/* FREESYS2 */
+#define	R367TER_FREESYS2	0xf00c
+#define	F367TER_FREE_SYS2	0xf00c00ff
+
+/* FREESYS3 */
+#define	R367TER_FREESYS3	0xf00d
+#define	F367TER_FREE_SYS3	0xf00d00ff
+
+/* GPIO_CFG */
+#define	R367TER_GPIO_CFG	0xf00e
+#define	F367TER_GPIO7_NOD	0xf00e0080
+#define	F367TER_GPIO7_CFG	0xf00e0040
+#define	F367TER_GPIO6_NOD	0xf00e0020
+#define	F367TER_GPIO6_CFG	0xf00e0010
+#define	F367TER_GPIO5_NOD	0xf00e0008
+#define	F367TER_GPIO5_CFG	0xf00e0004
+#define	F367TER_GPIO4_NOD	0xf00e0002
+#define	F367TER_GPIO4_CFG	0xf00e0001
+
+/* GPIO_CMD */
+#define	R367TER_GPIO_CMD	0xf00f
+#define	F367TER_GPIO7_VAL	0xf00f0008
+#define	F367TER_GPIO6_VAL	0xf00f0004
+#define	F367TER_GPIO5_VAL	0xf00f0002
+#define	F367TER_GPIO4_VAL	0xf00f0001
+
+/* AGC2MAX */
+#define	R367TER_AGC2MAX	0xf010
+#define	F367TER_AGC2_MAX	0xf01000ff
+
+/* AGC2MIN */
+#define	R367TER_AGC2MIN	0xf011
+#define	F367TER_AGC2_MIN	0xf01100ff
+
+/* AGC1MAX */
+#define	R367TER_AGC1MAX	0xf012
+#define	F367TER_AGC1_MAX	0xf01200ff
+
+/* AGC1MIN */
+#define	R367TER_AGC1MIN	0xf013
+#define	F367TER_AGC1_MIN	0xf01300ff
+
+/* AGCR */
+#define	R367TER_AGCR	0xf014
+#define	F367TER_RATIO_A	0xf01400e0
+#define	F367TER_RATIO_B	0xf0140018
+#define	F367TER_RATIO_C	0xf0140007
+
+/* AGC2TH */
+#define	R367TER_AGC2TH	0xf015
+#define	F367TER_AGC2_THRES	0xf01500ff
+
+/* AGC12c */
+#define	R367TER_AGC12C	0xf016
+#define	F367TER_AGC1_IV	0xf0160080
+#define	F367TER_AGC1_OD	0xf0160040
+#define	F367TER_AGC1_LOAD	0xf0160020
+#define	F367TER_AGC2_IV	0xf0160010
+#define	F367TER_AGC2_OD	0xf0160008
+#define	F367TER_AGC2_LOAD	0xf0160004
+#define	F367TER_AGC12_MODE	0xf0160003
+
+/* AGCCTRL1 */
+#define	R367TER_AGCCTRL1	0xf017
+#define	F367TER_DAGC_ON	0xf0170080
+#define	F367TER_INVERT_AGC12	0xf0170040
+#define	F367TER_AGC1_MODE	0xf0170008
+#define	F367TER_AGC2_MODE	0xf0170007
+
+/* AGCCTRL2 */
+#define	R367TER_AGCCTRL2	0xf018
+#define	F367TER_FRZ2_CTRL	0xf0180060
+#define	F367TER_FRZ1_CTRL	0xf0180018
+#define	F367TER_TIME_CST	0xf0180007
+
+/* AGC1VAL1 */
+#define	R367TER_AGC1VAL1	0xf019
+#define	F367TER_AGC1_VAL_LO	0xf01900ff
+
+/* AGC1VAL2 */
+#define	R367TER_AGC1VAL2	0xf01a
+#define	F367TER_AGC1_VAL_HI	0xf01a000f
+
+/* AGC2VAL1 */
+#define	R367TER_AGC2VAL1	0xf01b
+#define	F367TER_AGC2_VAL_LO	0xf01b00ff
+
+/* AGC2VAL2 */
+#define	R367TER_AGC2VAL2	0xf01c
+#define	F367TER_AGC2_VAL_HI	0xf01c000f
+
+/* AGC2PGA */
+#define	R367TER_AGC2PGA	0xf01d
+#define	F367TER_AGC2_PGA	0xf01d00ff
+
+/* OVF_RATE1 */
+#define	R367TER_OVF_RATE1	0xf01e
+#define	F367TER_OVF_RATE_HI	0xf01e000f
+
+/* OVF_RATE2 */
+#define	R367TER_OVF_RATE2	0xf01f
+#define	F367TER_OVF_RATE_LO	0xf01f00ff
+
+/* GAIN_SRC1 */
+#define	R367TER_GAIN_SRC1	0xf020
+#define	F367TER_INV_SPECTR	0xf0200080
+#define	F367TER_IQ_INVERT	0xf0200040
+#define	F367TER_INR_BYPASS	0xf0200020
+#define	F367TER_STATUS_INV_SPECRUM	0xf0200010
+#define	F367TER_GAIN_SRC_HI	0xf020000f
+
+/* GAIN_SRC2 */
+#define	R367TER_GAIN_SRC2	0xf021
+#define	F367TER_GAIN_SRC_LO	0xf02100ff
+
+/* INC_DEROT1 */
+#define	R367TER_INC_DEROT1	0xf022
+#define	F367TER_INC_DEROT_HI	0xf02200ff
+
+/* INC_DEROT2 */
+#define	R367TER_INC_DEROT2	0xf023
+#define	F367TER_INC_DEROT_LO	0xf02300ff
+
+/* PPM_CPAMP_DIR */
+#define	R367TER_PPM_CPAMP_DIR	0xf024
+#define	F367TER_PPM_CPAMP_DIRECT	0xf02400ff
+
+/* PPM_CPAMP_INV */
+#define	R367TER_PPM_CPAMP_INV	0xf025
+#define	F367TER_PPM_CPAMP_INVER	0xf02500ff
+
+/* FREESTFE_1 */
+#define	R367TER_FREESTFE_1	0xf026
+#define	F367TER_SYMBOL_NUMBER_INC	0xf02600c0
+#define	F367TER_SEL_LSB	0xf0260004
+#define	F367TER_AVERAGE_ON	0xf0260002
+#define	F367TER_DC_ADJ	0xf0260001
+
+/* FREESTFE_2 */
+#define	R367TER_FREESTFE_2	0xf027
+#define	F367TER_SEL_SRCOUT	0xf02700c0
+#define	F367TER_SEL_SYRTHR	0xf027001f
+
+/* DCOFFSET */
+#define	R367TER_DCOFFSET	0xf028
+#define	F367TER_SELECT_I_Q	0xf0280080
+#define	F367TER_DC_OFFSET	0xf028007f
+
+/* EN_PROCESS */
+#define	R367TER_EN_PROCESS	0xf029
+#define	F367TER_FREE	0xf02900f0
+#define	F367TER_ENAB_MANUAL	0xf0290001
+
+/* SDI_SMOOTHER */
+#define	R367TER_SDI_SMOOTHER	0xf02a
+#define	F367TER_DIS_SMOOTH	0xf02a0080
+#define	F367TER_SDI_INC_SMOOTHER	0xf02a007f
+
+/* FE_LOOP_OPEN */
+#define	R367TER_FE_LOOP_OPEN	0xf02b
+#define	F367TER_TRL_LOOP_OP	0xf02b0002
+#define	F367TER_CRL_LOOP_OP	0xf02b0001
+
+/* FREQOFF1 */
+#define	R367TER_FREQOFF1	0xf02c
+#define	F367TER_FREQ_OFFSET_LOOP_OPEN_VHI	0xf02c00ff
+
+/* FREQOFF2 */
+#define	R367TER_FREQOFF2	0xf02d
+#define	F367TER_FREQ_OFFSET_LOOP_OPEN_HI	0xf02d00ff
+
+/* FREQOFF3 */
+#define	R367TER_FREQOFF3	0xf02e
+#define	F367TER_FREQ_OFFSET_LOOP_OPEN_LO	0xf02e00ff
+
+/* TIMOFF1 */
+#define	R367TER_TIMOFF1	0xf02f
+#define	F367TER_TIM_OFFSET_LOOP_OPEN_HI	0xf02f00ff
+
+/* TIMOFF2 */
+#define	R367TER_TIMOFF2	0xf030
+#define	F367TER_TIM_OFFSET_LOOP_OPEN_LO	0xf03000ff
+
+/* EPQ */
+#define	R367TER_EPQ	0xf031
+#define	F367TER_EPQ1	0xf03100ff
+
+/* EPQAUTO */
+#define	R367TER_EPQAUTO	0xf032
+#define	F367TER_EPQ2	0xf03200ff
+
+/* SYR_UPDATE */
+#define	R367TER_SYR_UPDATE	0xf033
+#define	F367TER_SYR_PROTV	0xf0330080
+#define	F367TER_SYR_PROTV_GAIN	0xf0330060
+#define	F367TER_SYR_FILTER	0xf0330010
+#define	F367TER_SYR_TRACK_THRES	0xf033000c
+
+/* CHPFREE */
+#define	R367TER_CHPFREE	0xf034
+#define	F367TER_CHP_FREE	0xf03400ff
+
+/* PPM_STATE_MAC */
+#define	R367TER_PPM_STATE_MAC	0xf035
+#define	F367TER_PPM_STATE_MACHINE_DECODER	0xf035003f
+
+/* INR_THRESHOLD */
+#define	R367TER_INR_THRESHOLD	0xf036
+#define	F367TER_INR_THRESH	0xf03600ff
+
+/* EPQ_TPS_ID_CELL */
+#define	R367TER_EPQ_TPS_ID_CELL	0xf037
+#define	F367TER_ENABLE_LGTH_TO_CF	0xf0370080
+#define	F367TER_DIS_TPS_RSVD	0xf0370040
+#define	F367TER_DIS_BCH	0xf0370020
+#define	F367TER_DIS_ID_CEL	0xf0370010
+#define	F367TER_TPS_ADJUST_SYM	0xf037000f
+
+/* EPQ_CFG */
+#define	R367TER_EPQ_CFG	0xf038
+#define	F367TER_EPQ_RANGE	0xf0380002
+#define	F367TER_EPQ_SOFT	0xf0380001
+
+/* EPQ_STATUS */
+#define	R367TER_EPQ_STATUS	0xf039
+#define	F367TER_SLOPE_INC	0xf03900fc
+#define	F367TER_TPS_FIELD	0xf0390003
+
+/* AUTORELOCK */
+#define	R367TER_AUTORELOCK	0xf03a
+#define	F367TER_BYPASS_BER_TEMPO	0xf03a0080
+#define	F367TER_BER_TEMPO	0xf03a0070
+#define	F367TER_BYPASS_COFDM_TEMPO	0xf03a0008
+#define	F367TER_COFDM_TEMPO	0xf03a0007
+
+/* BER_THR_VMSB */
+#define	R367TER_BER_THR_VMSB	0xf03b
+#define	F367TER_BER_THRESHOLD_HI	0xf03b00ff
+
+/* BER_THR_MSB */
+#define	R367TER_BER_THR_MSB	0xf03c
+#define	F367TER_BER_THRESHOLD_MID	0xf03c00ff
+
+/* BER_THR_LSB */
+#define	R367TER_BER_THR_LSB	0xf03d
+#define	F367TER_BER_THRESHOLD_LO	0xf03d00ff
+
+/* CCD */
+#define	R367TER_CCD	0xf03e
+#define	F367TER_CCD_DETECTED	0xf03e0080
+#define	F367TER_CCD_RESET	0xf03e0040
+#define	F367TER_CCD_THRESHOLD	0xf03e000f
+
+/* SPECTR_CFG */
+#define	R367TER_SPECTR_CFG	0xf03f
+#define	F367TER_SPECT_CFG	0xf03f0003
+
+/* CONSTMU_MSB */
+#define	R367TER_CONSTMU_MSB	0xf040
+#define	F367TER_CONSTMU_FREEZE	0xf0400080
+#define	F367TER_CONSTNU_FORCE_EN	0xf0400040
+#define	F367TER_CONST_MU_MSB	0xf040003f
+
+/* CONSTMU_LSB */
+#define	R367TER_CONSTMU_LSB	0xf041
+#define	F367TER_CONST_MU_LSB	0xf04100ff
+
+/* CONSTMU_MAX_MSB */
+#define	R367TER_CONSTMU_MAX_MSB	0xf042
+#define	F367TER_CONST_MU_MAX_MSB	0xf042003f
+
+/* CONSTMU_MAX_LSB */
+#define	R367TER_CONSTMU_MAX_LSB	0xf043
+#define	F367TER_CONST_MU_MAX_LSB	0xf04300ff
+
+/* ALPHANOISE */
+#define	R367TER_ALPHANOISE	0xf044
+#define	F367TER_USE_ALLFILTER	0xf0440080
+#define	F367TER_INTER_ON	0xf0440040
+#define	F367TER_ALPHA_NOISE	0xf044001f
+
+/* MAXGP_MSB */
+#define	R367TER_MAXGP_MSB	0xf045
+#define	F367TER_MUFILTER_LENGTH	0xf04500f0
+#define	F367TER_MAX_GP_MSB	0xf045000f
+
+/* MAXGP_LSB */
+#define	R367TER_MAXGP_LSB	0xf046
+#define	F367TER_MAX_GP_LSB	0xf04600ff
+
+/* ALPHAMSB */
+#define	R367TER_ALPHAMSB	0xf047
+#define	F367TER_CHC_DATARATE	0xf04700c0
+#define	F367TER_ALPHA_MSB	0xf047003f
+
+/* ALPHALSB */
+#define	R367TER_ALPHALSB	0xf048
+#define	F367TER_ALPHA_LSB	0xf04800ff
+
+/* PILOT_ACCU */
+#define	R367TER_PILOT_ACCU	0xf049
+#define	F367TER_USE_SCAT4ADDAPT	0xf0490080
+#define	F367TER_PILOT_ACC	0xf049001f
+
+/* PILOTMU_ACCU */
+#define	R367TER_PILOTMU_ACCU	0xf04a
+#define	F367TER_DISCARD_BAD_SP	0xf04a0080
+#define	F367TER_DISCARD_BAD_CP	0xf04a0040
+#define	F367TER_PILOT_MU_ACCU	0xf04a001f
+
+/* FILT_CHANNEL_EST */
+#define	R367TER_FILT_CHANNEL_EST	0xf04b
+#define	F367TER_USE_FILT_PILOT	0xf04b0080
+#define	F367TER_FILT_CHANNEL	0xf04b007f
+
+/* ALPHA_NOPISE_FREQ */
+#define	R367TER_ALPHA_NOPISE_FREQ	0xf04c
+#define	F367TER_NOISE_FREQ_FILT	0xf04c0040
+#define	F367TER_ALPHA_NOISE_FREQ	0xf04c003f
+
+/* RATIO_PILOT */
+#define	R367TER_RATIO_PILOT	0xf04d
+#define	F367TER_RATIO_MEAN_SP	0xf04d00f0
+#define	F367TER_RATIO_MEAN_CP	0xf04d000f
+
+/* CHC_CTL */
+#define	R367TER_CHC_CTL	0xf04e
+#define	F367TER_TRACK_EN	0xf04e0080
+#define	F367TER_NOISE_NORM_EN	0xf04e0040
+#define	F367TER_FORCE_CHC_RESET	0xf04e0020
+#define	F367TER_SHORT_TIME	0xf04e0010
+#define	F367TER_FORCE_STATE_EN	0xf04e0008
+#define	F367TER_FORCE_STATE	0xf04e0007
+
+/* EPQ_ADJUST */
+#define	R367TER_EPQ_ADJUST	0xf04f
+#define	F367TER_ADJUST_SCAT_IND	0xf04f00c0
+#define	F367TER_ONE_SYMBOL	0xf04f0010
+#define	F367TER_EPQ_DECAY	0xf04f000e
+#define	F367TER_HOLD_SLOPE	0xf04f0001
+
+/* EPQ_THRES */
+#define	R367TER_EPQ_THRES	0xf050
+#define	F367TER_EPQ_THR	0xf05000ff
+
+/* OMEGA_CTL */
+#define	R367TER_OMEGA_CTL	0xf051
+#define	F367TER_OMEGA_RST	0xf0510080
+#define	F367TER_FREEZE_OMEGA	0xf0510040
+#define	F367TER_OMEGA_SEL	0xf051003f
+
+/* GP_CTL */
+#define	R367TER_GP_CTL	0xf052
+#define	F367TER_CHC_STATE	0xf05200e0
+#define	F367TER_FREEZE_GP	0xf0520010
+#define	F367TER_GP_SEL	0xf052000f
+
+/* MUMSB */
+#define	R367TER_MUMSB	0xf053
+#define	F367TER_MU_MSB	0xf053007f
+
+/* MULSB */
+#define	R367TER_MULSB	0xf054
+#define	F367TER_MU_LSB	0xf05400ff
+
+/* GPMSB */
+#define	R367TER_GPMSB	0xf055
+#define	F367TER_CSI_THRESHOLD	0xf05500e0
+#define	F367TER_GP_MSB	0xf055000f
+
+/* GPLSB */
+#define	R367TER_GPLSB	0xf056
+#define	F367TER_GP_LSB	0xf05600ff
+
+/* OMEGAMSB */
+#define	R367TER_OMEGAMSB	0xf057
+#define	F367TER_OMEGA_MSB	0xf057007f
+
+/* OMEGALSB */
+#define	R367TER_OMEGALSB	0xf058
+#define	F367TER_OMEGA_LSB	0xf05800ff
+
+/* SCAT_NB */
+#define	R367TER_SCAT_NB	0xf059
+#define	F367TER_CHC_TEST	0xf05900f8
+#define	F367TER_SCAT_NUMB	0xf0590003
+
+/* CHC_DUMMY */
+#define	R367TER_CHC_DUMMY	0xf05a
+#define	F367TER_CHC_DUM	0xf05a00ff
+
+/* INC_CTL */
+#define	R367TER_INC_CTL	0xf05b
+#define	F367TER_INC_BYPASS	0xf05b0080
+#define	F367TER_INC_NDEPTH	0xf05b000c
+#define	F367TER_INC_MADEPTH	0xf05b0003
+
+/* INCTHRES_COR1 */
+#define	R367TER_INCTHRES_COR1	0xf05c
+#define	F367TER_INC_THRES_COR1	0xf05c00ff
+
+/* INCTHRES_COR2 */
+#define	R367TER_INCTHRES_COR2	0xf05d
+#define	F367TER_INC_THRES_COR2	0xf05d00ff
+
+/* INCTHRES_DET1 */
+#define	R367TER_INCTHRES_DET1	0xf05e
+#define	F367TER_INC_THRES_DET1	0xf05e003f
+
+/* INCTHRES_DET2 */
+#define	R367TER_INCTHRES_DET2	0xf05f
+#define	F367TER_INC_THRES_DET2	0xf05f003f
+
+/* IIR_CELLNB */
+#define	R367TER_IIR_CELLNB	0xf060
+#define	F367TER_NRST_IIR	0xf0600080
+#define	F367TER_IIR_CELL_NB	0xf0600007
+
+/* IIRCX_COEFF1_MSB */
+#define	R367TER_IIRCX_COEFF1_MSB	0xf061
+#define	F367TER_IIR_CX_COEFF1_MSB	0xf06100ff
+
+/* IIRCX_COEFF1_LSB */
+#define	R367TER_IIRCX_COEFF1_LSB	0xf062
+#define	F367TER_IIR_CX_COEFF1_LSB	0xf06200ff
+
+/* IIRCX_COEFF2_MSB */
+#define	R367TER_IIRCX_COEFF2_MSB	0xf063
+#define	F367TER_IIR_CX_COEFF2_MSB	0xf06300ff
+
+/* IIRCX_COEFF2_LSB */
+#define	R367TER_IIRCX_COEFF2_LSB	0xf064
+#define	F367TER_IIR_CX_COEFF2_LSB	0xf06400ff
+
+/* IIRCX_COEFF3_MSB */
+#define	R367TER_IIRCX_COEFF3_MSB	0xf065
+#define	F367TER_IIR_CX_COEFF3_MSB	0xf06500ff
+
+/* IIRCX_COEFF3_LSB */
+#define	R367TER_IIRCX_COEFF3_LSB	0xf066
+#define	F367TER_IIR_CX_COEFF3_LSB	0xf06600ff
+
+/* IIRCX_COEFF4_MSB */
+#define	R367TER_IIRCX_COEFF4_MSB	0xf067
+#define	F367TER_IIR_CX_COEFF4_MSB	0xf06700ff
+
+/* IIRCX_COEFF4_LSB */
+#define	R367TER_IIRCX_COEFF4_LSB	0xf068
+#define	F367TER_IIR_CX_COEFF4_LSB	0xf06800ff
+
+/* IIRCX_COEFF5_MSB */
+#define	R367TER_IIRCX_COEFF5_MSB	0xf069
+#define	F367TER_IIR_CX_COEFF5_MSB	0xf06900ff
+
+/* IIRCX_COEFF5_LSB */
+#define	R367TER_IIRCX_COEFF5_LSB	0xf06a
+#define	F367TER_IIR_CX_COEFF5_LSB	0xf06a00ff
+
+/* FEPATH_CFG */
+#define	R367TER_FEPATH_CFG	0xf06b
+#define	F367TER_DEMUX_SWAP	0xf06b0004
+#define	F367TER_DIGAGC_SWAP	0xf06b0002
+#define	F367TER_LONGPATH_IF	0xf06b0001
+
+/* PMC1_FUNC */
+#define	R367TER_PMC1_FUNC	0xf06c
+#define	F367TER_SOFT_RSTN	0xf06c0080
+#define	F367TER_PMC1_AVERAGE_TIME	0xf06c0078
+#define	F367TER_PMC1_WAIT_TIME	0xf06c0006
+#define	F367TER_PMC1_2N_SEL	0xf06c0001
+
+/* PMC1_FOR */
+#define	R367TER_PMC1_FOR	0xf06d
+#define	F367TER_PMC1_FORCE	0xf06d0080
+#define	F367TER_PMC1_FORCE_VALUE	0xf06d007c
+
+/* PMC2_FUNC */
+#define	R367TER_PMC2_FUNC	0xf06e
+#define	F367TER_PMC2_SOFT_STN	0xf06e0080
+#define	F367TER_PMC2_ACCU_TIME	0xf06e0070
+#define	F367TER_PMC2_CMDP_MN	0xf06e0008
+#define	F367TER_PMC2_SWAP	0xf06e0004
+
+/* STATUS_ERR_DA */
+#define	R367TER_STATUS_ERR_DA	0xf06f
+#define	F367TER_COM_USEGAINTRK	0xf06f0080
+#define	F367TER_COM_AGCLOCK	0xf06f0040
+#define	F367TER_AUT_AGCLOCK	0xf06f0020
+#define	F367TER_MIN_ERR_X_LSB	0xf06f000f
+
+/* DIG_AGC_R */
+#define	R367TER_DIG_AGC_R	0xf070
+#define	F367TER_COM_SOFT_RSTN	0xf0700080
+#define	F367TER_COM_AGC_ON	0xf0700040
+#define	F367TER_COM_EARLY	0xf0700020
+#define	F367TER_AUT_SOFT_RESETN	0xf0700010
+#define	F367TER_AUT_AGC_ON	0xf0700008
+#define	F367TER_AUT_EARLY	0xf0700004
+#define	F367TER_AUT_ROT_EN	0xf0700002
+#define	F367TER_LOCK_SOFT_RESETN	0xf0700001
+
+/* COMAGC_TARMSB */
+#define	R367TER_COMAGC_TARMSB	0xf071
+#define	F367TER_COM_AGC_TARGET_MSB	0xf07100ff
+
+/* COM_AGC_TAR_ENMODE */
+#define	R367TER_COM_AGC_TAR_ENMODE	0xf072
+#define	F367TER_COM_AGC_TARGET_LSB	0xf07200f0
+#define	F367TER_COM_ENMODE	0xf072000f
+
+/* COM_AGC_CFG */
+#define	R367TER_COM_AGC_CFG	0xf073
+#define	F367TER_COM_N	0xf07300f8
+#define	F367TER_COM_STABMODE	0xf0730006
+#define	F367TER_ERR_SEL	0xf0730001
+
+/* COM_AGC_GAIN1 */
+#define	R367TER_COM_AGC_GAIN1	0xf074
+#define	F367TER_COM_GAIN1aCK	0xf07400f0
+#define	F367TER_COM_GAIN1TRK	0xf074000f
+
+/* AUT_AGC_TARGETMSB */
+#define	R367TER_AUT_AGC_TARGETMSB	0xf075
+#define	F367TER_AUT_AGC_TARGET_MSB	0xf07500ff
+
+/* LOCK_DET_MSB */
+#define	R367TER_LOCK_DET_MSB	0xf076
+#define	F367TER_LOCK_DETECT_MSB	0xf07600ff
+
+/* AGCTAR_LOCK_LSBS */
+#define	R367TER_AGCTAR_LOCK_LSBS	0xf077
+#define	F367TER_AUT_AGC_TARGET_LSB	0xf07700f0
+#define	F367TER_LOCK_DETECT_LSB	0xf077000f
+
+/* AUT_GAIN_EN */
+#define	R367TER_AUT_GAIN_EN	0xf078
+#define	F367TER_AUT_ENMODE	0xf07800f0
+#define	F367TER_AUT_GAIN2	0xf078000f
+
+/* AUT_CFG */
+#define	R367TER_AUT_CFG	0xf079
+#define	F367TER_AUT_N	0xf07900f8
+#define	F367TER_INT_CHOICE	0xf0790006
+#define	F367TER_INT_LOAD	0xf0790001
+
+/* LOCKN */
+#define	R367TER_LOCKN	0xf07a
+#define	F367TER_LOCK_N	0xf07a00f8
+#define	F367TER_SEL_IQNTAR	0xf07a0004
+#define	F367TER_LOCK_DETECT_CHOICE	0xf07a0003
+
+/* INT_X_3 */
+#define	R367TER_INT_X_3	0xf07b
+#define	F367TER_INT_X3	0xf07b00ff
+
+/* INT_X_2 */
+#define	R367TER_INT_X_2	0xf07c
+#define	F367TER_INT_X2	0xf07c00ff
+
+/* INT_X_1 */
+#define	R367TER_INT_X_1	0xf07d
+#define	F367TER_INT_X1	0xf07d00ff
+
+/* INT_X_0 */
+#define	R367TER_INT_X_0	0xf07e
+#define	F367TER_INT_X0	0xf07e00ff
+
+/* MIN_ERRX_MSB */
+#define	R367TER_MIN_ERRX_MSB	0xf07f
+#define	F367TER_MIN_ERR_X_MSB	0xf07f00ff
+
+/* COR_CTL */
+#define	R367TER_COR_CTL	0xf080
+#define	F367TER_CORE_ACTIVE	0xf0800020
+#define	F367TER_HOLD	0xf0800010
+#define	F367TER_CORE_STATE_CTL	0xf080000f
+
+/* COR_STAT */
+#define	R367TER_COR_STAT	0xf081
+#define	F367TER_SCATT_LOCKED	0xf0810080
+#define	F367TER_TPS_LOCKED	0xf0810040
+#define	F367TER_SYR_LOCKED_COR	0xf0810020
+#define	F367TER_AGC_LOCKED_STAT	0xf0810010
+#define	F367TER_CORE_STATE_STAT	0xf081000f
+
+/* COR_INTEN */
+#define	R367TER_COR_INTEN	0xf082
+#define	F367TER_INTEN	0xf0820080
+#define	F367TER_INTEN_SYR	0xf0820020
+#define	F367TER_INTEN_FFT	0xf0820010
+#define	F367TER_INTEN_AGC	0xf0820008
+#define	F367TER_INTEN_TPS1	0xf0820004
+#define	F367TER_INTEN_TPS2	0xf0820002
+#define	F367TER_INTEN_TPS3	0xf0820001
+
+/* COR_INTSTAT */
+#define	R367TER_COR_INTSTAT	0xf083
+#define	F367TER_INTSTAT_SYR	0xf0830020
+#define	F367TER_INTSTAT_FFT	0xf0830010
+#define	F367TER_INTSAT_AGC	0xf0830008
+#define	F367TER_INTSTAT_TPS1	0xf0830004
+#define	F367TER_INTSTAT_TPS2	0xf0830002
+#define	F367TER_INTSTAT_TPS3	0xf0830001
+
+/* COR_MODEGUARD */
+#define	R367TER_COR_MODEGUARD	0xf084
+#define	F367TER_FORCE	0xf0840010
+#define	F367TER_MODE	0xf084000c
+#define	F367TER_GUARD	0xf0840003
+
+/* AGC_CTL */
+#define	R367TER_AGC_CTL	0xf085
+#define	F367TER_AGC_TIMING_FACTOR	0xf08500e0
+#define	F367TER_AGC_LAST	0xf0850010
+#define	F367TER_AGC_GAIN	0xf085000c
+#define	F367TER_AGC_NEG	0xf0850002
+#define	F367TER_AGC_SET	0xf0850001
+
+/* AGC_MANUAL1 */
+#define	R367TER_AGC_MANUAL1	0xf086
+#define	F367TER_AGC_VAL_LO	0xf08600ff
+
+/* AGC_MANUAL2 */
+#define	R367TER_AGC_MANUAL2	0xf087
+#define	F367TER_AGC_VAL_HI	0xf087000f
+
+/* AGC_TARG */
+#define	R367TER_AGC_TARG	0xf088
+#define	F367TER_AGC_TARGET	0xf08800ff
+
+/* AGC_GAIN1 */
+#define	R367TER_AGC_GAIN1	0xf089
+#define	F367TER_AGC_GAIN_LO	0xf08900ff
+
+/* AGC_GAIN2 */
+#define	R367TER_AGC_GAIN2	0xf08a
+#define	F367TER_AGC_LOCKED_GAIN2	0xf08a0010
+#define	F367TER_AGC_GAIN_HI	0xf08a000f
+
+/* RESERVED_1 */
+#define	R367TER_RESERVED_1	0xf08b
+#define	F367TER_RESERVED1	0xf08b00ff
+
+/* RESERVED_2 */
+#define	R367TER_RESERVED_2	0xf08c
+#define	F367TER_RESERVED2	0xf08c00ff
+
+/* RESERVED_3 */
+#define	R367TER_RESERVED_3	0xf08d
+#define	F367TER_RESERVED3	0xf08d00ff
+
+/* CAS_CTL */
+#define	R367TER_CAS_CTL	0xf08e
+#define	F367TER_CCS_ENABLE	0xf08e0080
+#define	F367TER_ACS_DISABLE	0xf08e0040
+#define	F367TER_DAGC_DIS	0xf08e0020
+#define	F367TER_DAGC_GAIN	0xf08e0018
+#define	F367TER_CCSMU	0xf08e0007
+
+/* CAS_FREQ */
+#define	R367TER_CAS_FREQ	0xf08f
+#define	F367TER_CCS_FREQ	0xf08f00ff
+
+/* CAS_DAGCGAIN */
+#define	R367TER_CAS_DAGCGAIN	0xf090
+#define	F367TER_CAS_DAGC_GAIN	0xf09000ff
+
+/* SYR_CTL */
+#define	R367TER_SYR_CTL	0xf091
+#define	F367TER_SICTH_ENABLE	0xf0910080
+#define	F367TER_LONG_ECHO	0xf0910078
+#define	F367TER_AUTO_LE_EN	0xf0910004
+#define	F367TER_SYR_BYPASS	0xf0910002
+#define	F367TER_SYR_TR_DIS	0xf0910001
+
+/* SYR_STAT */
+#define	R367TER_SYR_STAT	0xf092
+#define	F367TER_SYR_LOCKED_STAT	0xf0920010
+#define	F367TER_SYR_MODE	0xf092000c
+#define	F367TER_SYR_GUARD	0xf0920003
+
+/* SYR_NCO1 */
+#define	R367TER_SYR_NCO1	0xf093
+#define	F367TER_SYR_NCO_LO	0xf09300ff
+
+/* SYR_NCO2 */
+#define	R367TER_SYR_NCO2	0xf094
+#define	F367TER_SYR_NCO_HI	0xf094003f
+
+/* SYR_OFFSET1 */
+#define	R367TER_SYR_OFFSET1	0xf095
+#define	F367TER_SYR_OFFSET_LO	0xf09500ff
+
+/* SYR_OFFSET2 */
+#define	R367TER_SYR_OFFSET2	0xf096
+#define	F367TER_SYR_OFFSET_HI	0xf096003f
+
+/* FFT_CTL */
+#define	R367TER_FFT_CTL	0xf097
+#define	F367TER_SHIFT_FFT_TRIG	0xf0970018
+#define	F367TER_FFT_TRIGGER	0xf0970004
+#define	F367TER_FFT_MANUAL	0xf0970002
+#define	F367TER_IFFT_MODE	0xf0970001
+
+/* SCR_CTL */
+#define	R367TER_SCR_CTL	0xf098
+#define	F367TER_SYRADJDECAY	0xf0980070
+#define	F367TER_SCR_CPEDIS	0xf0980002
+#define	F367TER_SCR_DIS	0xf0980001
+
+/* PPM_CTL1 */
+#define	R367TER_PPM_CTL1	0xf099
+#define	F367TER_PPM_MAXFREQ	0xf0990030
+#define	F367TER_PPM_MAXTIM	0xf0990008
+#define	F367TER_PPM_INVSEL	0xf0990004
+#define	F367TER_PPM_SCATDIS	0xf0990002
+#define	F367TER_PPM_BYP	0xf0990001
+
+/* TRL_CTL */
+#define	R367TER_TRL_CTL	0xf09a
+#define	F367TER_TRL_NOMRATE_LSB	0xf09a0080
+#define	F367TER_TRL_GAIN_FACTOR	0xf09a0078
+#define	F367TER_TRL_LOOPGAIN	0xf09a0007
+
+/* TRL_NOMRATE1 */
+#define	R367TER_TRL_NOMRATE1	0xf09b
+#define	F367TER_TRL_NOMRATE_LO	0xf09b00ff
+
+/* TRL_NOMRATE2 */
+#define	R367TER_TRL_NOMRATE2	0xf09c
+#define	F367TER_TRL_NOMRATE_HI	0xf09c00ff
+
+/* TRL_TIME1 */
+#define	R367TER_TRL_TIME1	0xf09d
+#define	F367TER_TRL_TOFFSET_LO	0xf09d00ff
+
+/* TRL_TIME2 */
+#define	R367TER_TRL_TIME2	0xf09e
+#define	F367TER_TRL_TOFFSET_HI	0xf09e00ff
+
+/* CRL_CTL */
+#define	R367TER_CRL_CTL	0xf09f
+#define	F367TER_CRL_DIS	0xf09f0080
+#define	F367TER_CRL_GAIN_FACTOR	0xf09f0078
+#define	F367TER_CRL_LOOPGAIN	0xf09f0007
+
+/* CRL_FREQ1 */
+#define	R367TER_CRL_FREQ1	0xf0a0
+#define	F367TER_CRL_FOFFSET_LO	0xf0a000ff
+
+/* CRL_FREQ2 */
+#define	R367TER_CRL_FREQ2	0xf0a1
+#define	F367TER_CRL_FOFFSET_HI	0xf0a100ff
+
+/* CRL_FREQ3 */
+#define	R367TER_CRL_FREQ3	0xf0a2
+#define	F367TER_CRL_FOFFSET_VHI	0xf0a200ff
+
+/* TPS_SFRAME_CTL */
+#define	R367TER_TPS_SFRAME_CTL	0xf0a3
+#define	F367TER_TPS_SFRAME_SYNC	0xf0a30001
+
+/* CHC_SNR */
+#define	R367TER_CHC_SNR	0xf0a4
+#define	F367TER_CHCSNR	0xf0a400ff
+
+/* BDI_CTL */
+#define	R367TER_BDI_CTL	0xf0a5
+#define	F367TER_BDI_LPSEL	0xf0a50002
+#define	F367TER_BDI_SERIAL	0xf0a50001
+
+/* DMP_CTL */
+#define	R367TER_DMP_CTL	0xf0a6
+#define	F367TER_DMP_SCALING_FACTOR	0xf0a6001e
+#define	F367TER_DMP_SDDIS	0xf0a60001
+
+/* TPS_RCVD1 */
+#define	R367TER_TPS_RCVD1	0xf0a7
+#define	F367TER_TPS_CHANGE	0xf0a70040
+#define	F367TER_BCH_OK	0xf0a70020
+#define	F367TER_TPS_SYNC	0xf0a70010
+#define	F367TER_TPS_FRAME	0xf0a70003
+
+/* TPS_RCVD2 */
+#define	R367TER_TPS_RCVD2	0xf0a8
+#define	F367TER_TPS_HIERMODE	0xf0a80070
+#define	F367TER_TPS_CONST	0xf0a80003
+
+/* TPS_RCVD3 */
+#define	R367TER_TPS_RCVD3	0xf0a9
+#define	F367TER_TPS_LPCODE	0xf0a90070
+#define	F367TER_TPS_HPCODE	0xf0a90007
+
+/* TPS_RCVD4 */
+#define	R367TER_TPS_RCVD4	0xf0aa
+#define	F367TER_TPS_GUARD	0xf0aa0030
+#define	F367TER_TPS_MODE	0xf0aa0003
+
+/* TPS_ID_CELL1 */
+#define	R367TER_TPS_ID_CELL1	0xf0ab
+#define	F367TER_TPS_ID_CELL_LO	0xf0ab00ff
+
+/* TPS_ID_CELL2 */
+#define	R367TER_TPS_ID_CELL2	0xf0ac
+#define	F367TER_TPS_ID_CELL_HI	0xf0ac00ff
+
+/* TPS_RCVD5_SET1 */
+#define	R367TER_TPS_RCVD5_SET1	0xf0ad
+#define	F367TER_TPS_NA	0xf0ad00fC
+#define	F367TER_TPS_SETFRAME	0xf0ad0003
+
+/* TPS_SET2 */
+#define	R367TER_TPS_SET2	0xf0ae
+#define	F367TER_TPS_SETHIERMODE	0xf0ae0070
+#define	F367TER_TPS_SETCONST	0xf0ae0003
+
+/* TPS_SET3 */
+#define	R367TER_TPS_SET3	0xf0af
+#define	F367TER_TPS_SETLPCODE	0xf0af0070
+#define	F367TER_TPS_SETHPCODE	0xf0af0007
+
+/* TPS_CTL */
+#define	R367TER_TPS_CTL	0xf0b0
+#define	F367TER_TPS_IMM	0xf0b00004
+#define	F367TER_TPS_BCHDIS	0xf0b00002
+#define	F367TER_TPS_UPDDIS	0xf0b00001
+
+/* CTL_FFTOSNUM */
+#define	R367TER_CTL_FFTOSNUM	0xf0b1
+#define	F367TER_SYMBOL_NUMBER	0xf0b1007f
+
+/* TESTSELECT */
+#define	R367TER_TESTSELECT	0xf0b2
+#define	F367TER_TEST_SELECT	0xf0b2001f
+
+/* MSC_REV */
+#define	R367TER_MSC_REV	0xf0b3
+#define	F367TER_REV_NUMBER	0xf0b300ff
+
+/* PIR_CTL */
+#define	R367TER_PIR_CTL	0xf0b4
+#define	F367TER_FREEZE	0xf0b40001
+
+/* SNR_CARRIER1 */
+#define	R367TER_SNR_CARRIER1	0xf0b5
+#define	F367TER_SNR_CARRIER_LO	0xf0b500ff
+
+/* SNR_CARRIER2 */
+#define	R367TER_SNR_CARRIER2	0xf0b6
+#define	F367TER_MEAN	0xf0b600c0
+#define	F367TER_SNR_CARRIER_HI	0xf0b6001f
+
+/* PPM_CPAMP */
+#define	R367TER_PPM_CPAMP	0xf0b7
+#define	F367TER_PPM_CPC	0xf0b700ff
+
+/* TSM_AP0 */
+#define	R367TER_TSM_AP0	0xf0b8
+#define	F367TER_ADDRESS_BYTE_0	0xf0b800ff
+
+/* TSM_AP1 */
+#define	R367TER_TSM_AP1	0xf0b9
+#define	F367TER_ADDRESS_BYTE_1	0xf0b900ff
+
+/* TSM_AP2 */
+#define	R367TER_TSM_AP2	0xf0bA
+#define	F367TER_DATA_BYTE_0	0xf0ba00ff
+
+/* TSM_AP3 */
+#define	R367TER_TSM_AP3	0xf0bB
+#define	F367TER_DATA_BYTE_1	0xf0bb00ff
+
+/* TSM_AP4 */
+#define	R367TER_TSM_AP4	0xf0bC
+#define	F367TER_DATA_BYTE_2	0xf0bc00ff
+
+/* TSM_AP5 */
+#define	R367TER_TSM_AP5	0xf0bD
+#define	F367TER_DATA_BYTE_3	0xf0bd00ff
+
+/* TSM_AP6 */
+#define	R367TER_TSM_AP6	0xf0bE
+#define	F367TER_TSM_AP_6	0xf0be00ff
+
+/* TSM_AP7 */
+#define	R367TER_TSM_AP7	0xf0bF
+#define	F367TER_MEM_SELECT_BYTE	0xf0bf00ff
+
+/* TSTRES */
+#define	R367TER_TSTRES	0xf0c0
+#define	F367TER_FRES_DISPLAY	0xf0c00080
+#define	F367TER_FRES_FIFO_AD	0xf0c00020
+#define	F367TER_FRESRS	0xf0c00010
+#define	F367TER_FRESACS	0xf0c00008
+#define	F367TER_FRESFEC	0xf0c00004
+#define	F367TER_FRES_PRIF	0xf0c00002
+#define	F367TER_FRESCORE	0xf0c00001
+
+/* ANACTRL */
+#define	R367TER_ANACTRL	0xf0c1
+#define	F367TER_BYPASS_XTAL	0xf0c10040
+#define	F367TER_BYPASS_PLLXN	0xf0c1000c
+#define	F367TER_DIS_PAD_OSC	0xf0c10002
+#define	F367TER_STDBY_PLLXN	0xf0c10001
+
+/* TSTBUS */
+#define	R367TER_TSTBUS	0xf0c2
+#define	F367TER_TS_BYTE_CLK_INV	0xf0c20080
+#define	F367TER_CFG_IP	0xf0c20070
+#define	F367TER_CFG_TST	0xf0c2000f
+
+/* TSTRATE */
+#define	R367TER_TSTRATE	0xf0c6
+#define	F367TER_FORCEPHA	0xf0c60080
+#define	F367TER_FNEWPHA	0xf0c60010
+#define	F367TER_FROT90	0xf0c60008
+#define	F367TER_FR	0xf0c60007
+
+/* CONSTMODE */
+#define	R367TER_CONSTMODE	0xf0cb
+#define	F367TER_TST_PRIF	0xf0cb00e0
+#define	F367TER_CAR_TYPE	0xf0cb0018
+#define	F367TER_CONST_MODE	0xf0cb0003
+
+/* CONSTCARR1 */
+#define	R367TER_CONSTCARR1	0xf0cc
+#define	F367TER_CONST_CARR_LO	0xf0cc00ff
+
+/* CONSTCARR2 */
+#define	R367TER_CONSTCARR2	0xf0cd
+#define	F367TER_CONST_CARR_HI	0xf0cd001f
+
+/* ICONSTEL */
+#define	R367TER_ICONSTEL	0xf0ce
+#define	F367TER_PICONSTEL	0xf0ce00ff
+
+/* QCONSTEL */
+#define	R367TER_QCONSTEL	0xf0cf
+#define	F367TER_PQCONSTEL	0xf0cf00ff
+
+/* TSTBISTRES0 */
+#define	R367TER_TSTBISTRES0	0xf0d0
+#define	F367TER_BEND_PPM	0xf0d00080
+#define	F367TER_BBAD_PPM	0xf0d00040
+#define	F367TER_BEND_FFTW	0xf0d00020
+#define	F367TER_BBAD_FFTW	0xf0d00010
+#define	F367TER_BEND_FFT_BUF	0xf0d00008
+#define	F367TER_BBAD_FFT_BUF	0xf0d00004
+#define	F367TER_BEND_SYR	0xf0d00002
+#define	F367TER_BBAD_SYR	0xf0d00001
+
+/* TSTBISTRES1 */
+#define	R367TER_TSTBISTRES1	0xf0d1
+#define	F367TER_BEND_CHC_CP	0xf0d10080
+#define	F367TER_BBAD_CHC_CP	0xf0d10040
+#define	F367TER_BEND_CHCI	0xf0d10020
+#define	F367TER_BBAD_CHCI	0xf0d10010
+#define	F367TER_BEND_BDI	0xf0d10008
+#define	F367TER_BBAD_BDI	0xf0d10004
+#define	F367TER_BEND_SDI	0xf0d10002
+#define	F367TER_BBAD_SDI	0xf0d10001
+
+/* TSTBISTRES2 */
+#define	R367TER_TSTBISTRES2	0xf0d2
+#define	F367TER_BEND_CHC_INC	0xf0d20080
+#define	F367TER_BBAD_CHC_INC	0xf0d20040
+#define	F367TER_BEND_CHC_SPP	0xf0d20020
+#define	F367TER_BBAD_CHC_SPP	0xf0d20010
+#define	F367TER_BEND_CHC_CPP	0xf0d20008
+#define	F367TER_BBAD_CHC_CPP	0xf0d20004
+#define	F367TER_BEND_CHC_SP	0xf0d20002
+#define	F367TER_BBAD_CHC_SP	0xf0d20001
+
+/* TSTBISTRES3 */
+#define	R367TER_TSTBISTRES3	0xf0d3
+#define	F367TER_BEND_QAM	0xf0d30080
+#define	F367TER_BBAD_QAM	0xf0d30040
+#define	F367TER_BEND_SFEC_VIT	0xf0d30020
+#define	F367TER_BBAD_SFEC_VIT	0xf0d30010
+#define	F367TER_BEND_SFEC_DLINE	0xf0d30008
+#define	F367TER_BBAD_SFEC_DLINE	0xf0d30004
+#define	F367TER_BEND_SFEC_HW	0xf0d30002
+#define	F367TER_BBAD_SFEC_HW	0xf0d30001
+
+/* RF_AGC1 */
+#define	R367TER_RF_AGC1	0xf0d4
+#define	F367TER_RF_AGC1_LEVEL_HI	0xf0d400ff
+
+/* RF_AGC2 */
+#define	R367TER_RF_AGC2	0xf0d5
+#define	F367TER_REF_ADGP	0xf0d50080
+#define	F367TER_STDBY_ADCGP	0xf0d50020
+#define	F367TER_CHANNEL_SEL	0xf0d5001c
+#define	F367TER_RF_AGC1_LEVEL_LO	0xf0d50003
+
+/* ANADIGCTRL */
+#define	R367TER_ANADIGCTRL	0xf0d7
+#define	F367TER_SEL_CLKDEM	0xf0d70020
+#define	F367TER_EN_BUFFER_Q	0xf0d70010
+#define	F367TER_EN_BUFFER_I	0xf0d70008
+#define	F367TER_ADC_RIS_EGDE	0xf0d70004
+#define	F367TER_SGN_ADC	0xf0d70002
+#define	F367TER_SEL_AD12_SYNC	0xf0d70001
+
+/* PLLMDIV */
+#define	R367TER_PLLMDIV	0xf0d8
+#define	F367TER_PLL_MDIV	0xf0d800ff
+
+/* PLLNDIV */
+#define	R367TER_PLLNDIV	0xf0d9
+#define	F367TER_PLL_NDIV	0xf0d900ff
+
+/* PLLSETUP */
+#define	R367TER_PLLSETUP	0xf0dA
+#define	F367TER_PLL_PDIV	0xf0da0070
+#define	F367TER_PLL_KDIV	0xf0da000f
+
+/* DUAL_AD12 */
+#define	R367TER_DUAL_AD12	0xf0dB
+#define	F367TER_FS20M	0xf0db0020
+#define	F367TER_FS50M	0xf0db0010
+#define	F367TER_INMODe0	0xf0db0008
+#define	F367TER_POFFQ	0xf0db0004
+#define	F367TER_POFFI	0xf0db0002
+#define	F367TER_INMODE1	0xf0db0001
+
+/* TSTBIST */
+#define	R367TER_TSTBIST	0xf0dC
+#define	F367TER_TST_BYP_CLK	0xf0dc0080
+#define	F367TER_TST_GCLKENA_STD	0xf0dc0040
+#define	F367TER_TST_GCLKENA	0xf0dc0020
+#define	F367TER_TST_MEMBIST	0xf0dc001f
+
+/* PAD_COMP_CTRL */
+#define	R367TER_PAD_COMP_CTRL	0xf0dD
+#define	F367TER_COMPTQ	0xf0dd0010
+#define	F367TER_COMPEN	0xf0dd0008
+#define	F367TER_FREEZE2	0xf0dd0004
+#define	F367TER_SLEEP_INHBT	0xf0dd0002
+#define	F367TER_CHIP_SLEEP	0xf0dd0001
+
+/* PAD_COMP_WR */
+#define	R367TER_PAD_COMP_WR	0xf0de
+#define	F367TER_WR_ASRC	0xf0de007f
+
+/* PAD_COMP_RD */
+#define	R367TER_PAD_COMP_RD	0xf0df
+#define	F367TER_COMPOK	0xf0df0080
+#define	F367TER_RD_ASRC	0xf0df007f
+
+/* SYR_TARGET_FFTADJT_MSB */
+#define	R367TER_SYR_TARGET_FFTADJT_MSB	0xf100
+#define	F367TER_SYR_START	0xf1000080
+#define	F367TER_SYR_TARGET_FFTADJ_HI	0xf100000f
+
+/* SYR_TARGET_FFTADJT_LSB */
+#define	R367TER_SYR_TARGET_FFTADJT_LSB	0xf101
+#define	F367TER_SYR_TARGET_FFTADJ_LO	0xf10100ff
+
+/* SYR_TARGET_CHCADJT_MSB */
+#define	R367TER_SYR_TARGET_CHCADJT_MSB	0xf102
+#define	F367TER_SYR_TARGET_CHCADJ_HI	0xf102000f
+
+/* SYR_TARGET_CHCADJT_LSB */
+#define	R367TER_SYR_TARGET_CHCADJT_LSB	0xf103
+#define	F367TER_SYR_TARGET_CHCADJ_LO	0xf10300ff
+
+/* SYR_FLAG */
+#define	R367TER_SYR_FLAG	0xf104
+#define	F367TER_TRIG_FLG1	0xf1040080
+#define	F367TER_TRIG_FLG0	0xf1040040
+#define	F367TER_FFT_FLG1	0xf1040008
+#define	F367TER_FFT_FLG0	0xf1040004
+#define	F367TER_CHC_FLG1	0xf1040002
+#define	F367TER_CHC_FLG0	0xf1040001
+
+/* CRL_TARGET1 */
+#define	R367TER_CRL_TARGET1	0xf105
+#define	F367TER_CRL_START	0xf1050080
+#define	F367TER_CRL_TARGET_VHI	0xf105000f
+
+/* CRL_TARGET2 */
+#define	R367TER_CRL_TARGET2	0xf106
+#define	F367TER_CRL_TARGET_HI	0xf10600ff
+
+/* CRL_TARGET3 */
+#define	R367TER_CRL_TARGET3	0xf107
+#define	F367TER_CRL_TARGET_LO	0xf10700ff
+
+/* CRL_TARGET4 */
+#define	R367TER_CRL_TARGET4	0xf108
+#define	F367TER_CRL_TARGET_VLO	0xf10800ff
+
+/* CRL_FLAG */
+#define	R367TER_CRL_FLAG	0xf109
+#define	F367TER_CRL_FLAG1	0xf1090002
+#define	F367TER_CRL_FLAG0	0xf1090001
+
+/* TRL_TARGET1 */
+#define	R367TER_TRL_TARGET1	0xf10a
+#define	F367TER_TRL_TARGET_HI	0xf10a00ff
+
+/* TRL_TARGET2 */
+#define	R367TER_TRL_TARGET2	0xf10b
+#define	F367TER_TRL_TARGET_LO	0xf10b00ff
+
+/* TRL_CHC */
+#define	R367TER_TRL_CHC	0xf10c
+#define	F367TER_TRL_START	0xf10c0080
+#define	F367TER_CHC_START	0xf10c0040
+#define	F367TER_TRL_FLAG1	0xf10c0002
+#define	F367TER_TRL_FLAG0	0xf10c0001
+
+/* CHC_SNR_TARG */
+#define	R367TER_CHC_SNR_TARG	0xf10d
+#define	F367TER_CHC_SNR_TARGET	0xf10d00ff
+
+/* TOP_TRACK */
+#define	R367TER_TOP_TRACK	0xf10e
+#define	F367TER_TOP_START	0xf10e0080
+#define	F367TER_FIRST_FLAG	0xf10e0070
+#define	F367TER_TOP_FLAG1	0xf10e0008
+#define	F367TER_TOP_FLAG0	0xf10e0004
+#define	F367TER_CHC_FLAG1	0xf10e0002
+#define	F367TER_CHC_FLAG0	0xf10e0001
+
+/* TRACKER_FREE1 */
+#define	R367TER_TRACKER_FREE1	0xf10f
+#define	F367TER_TRACKER_FREE_1	0xf10f00ff
+
+/* ERROR_CRL1 */
+#define	R367TER_ERROR_CRL1	0xf110
+#define	F367TER_ERROR_CRL_VHI	0xf11000ff
+
+/* ERROR_CRL2 */
+#define	R367TER_ERROR_CRL2	0xf111
+#define	F367TER_ERROR_CRL_HI	0xf11100ff
+
+/* ERROR_CRL3 */
+#define	R367TER_ERROR_CRL3	0xf112
+#define	F367TER_ERROR_CRL_LOI	0xf11200ff
+
+/* ERROR_CRL4 */
+#define	R367TER_ERROR_CRL4	0xf113
+#define	F367TER_ERROR_CRL_VLO	0xf11300ff
+
+/* DEC_NCO1 */
+#define	R367TER_DEC_NCO1	0xf114
+#define	F367TER_DEC_NCO_VHI	0xf11400ff
+
+/* DEC_NCO2 */
+#define	R367TER_DEC_NCO2	0xf115
+#define	F367TER_DEC_NCO_HI	0xf11500ff
+
+/* DEC_NCO3 */
+#define	R367TER_DEC_NCO3	0xf116
+#define	F367TER_DEC_NCO_LO	0xf11600ff
+
+/* SNR */
+#define	R367TER_SNR	0xf117
+#define	F367TER_SNRATIO	0xf11700ff
+
+/* SYR_FFTADJ1 */
+#define	R367TER_SYR_FFTADJ1	0xf118
+#define	F367TER_SYR_FFTADJ_HI	0xf11800ff
+
+/* SYR_FFTADJ2 */
+#define	R367TER_SYR_FFTADJ2	0xf119
+#define	F367TER_SYR_FFTADJ_LO	0xf11900ff
+
+/* SYR_CHCADJ1 */
+#define	R367TER_SYR_CHCADJ1	0xf11a
+#define	F367TER_SYR_CHCADJ_HI	0xf11a00ff
+
+/* SYR_CHCADJ2 */
+#define	R367TER_SYR_CHCADJ2	0xf11b
+#define	F367TER_SYR_CHCADJ_LO	0xf11b00ff
+
+/* SYR_OFF */
+#define	R367TER_SYR_OFF	0xf11c
+#define	F367TER_SYR_OFFSET	0xf11c00ff
+
+/* PPM_OFFSET1 */
+#define	R367TER_PPM_OFFSET1	0xf11d
+#define	F367TER_PPM_OFFSET_HI	0xf11d00ff
+
+/* PPM_OFFSET2 */
+#define	R367TER_PPM_OFFSET2	0xf11e
+#define	F367TER_PPM_OFFSET_LO	0xf11e00ff
+
+/* TRACKER_FREE2 */
+#define	R367TER_TRACKER_FREE2	0xf11f
+#define	F367TER_TRACKER_FREE_2	0xf11f00ff
+
+/* DEBG_LT10 */
+#define	R367TER_DEBG_LT10	0xf120
+#define	F367TER_DEBUG_LT10	0xf12000ff
+
+/* DEBG_LT11 */
+#define	R367TER_DEBG_LT11	0xf121
+#define	F367TER_DEBUG_LT11	0xf12100ff
+
+/* DEBG_LT12 */
+#define	R367TER_DEBG_LT12	0xf122
+#define	F367TER_DEBUG_LT12	0xf12200ff
+
+/* DEBG_LT13 */
+#define	R367TER_DEBG_LT13	0xf123
+#define	F367TER_DEBUG_LT13	0xf12300ff
+
+/* DEBG_LT14 */
+#define	R367TER_DEBG_LT14	0xf124
+#define	F367TER_DEBUG_LT14	0xf12400ff
+
+/* DEBG_LT15 */
+#define	R367TER_DEBG_LT15	0xf125
+#define	F367TER_DEBUG_LT15	0xf12500ff
+
+/* DEBG_LT16 */
+#define	R367TER_DEBG_LT16	0xf126
+#define	F367TER_DEBUG_LT16	0xf12600ff
+
+/* DEBG_LT17 */
+#define	R367TER_DEBG_LT17	0xf127
+#define	F367TER_DEBUG_LT17	0xf12700ff
+
+/* DEBG_LT18 */
+#define	R367TER_DEBG_LT18	0xf128
+#define	F367TER_DEBUG_LT18	0xf12800ff
+
+/* DEBG_LT19 */
+#define	R367TER_DEBG_LT19	0xf129
+#define	F367TER_DEBUG_LT19	0xf12900ff
+
+/* DEBG_LT1a */
+#define	R367TER_DEBG_LT1A	0xf12a
+#define	F367TER_DEBUG_LT1A	0xf12a00ff
+
+/* DEBG_LT1b */
+#define	R367TER_DEBG_LT1B	0xf12b
+#define	F367TER_DEBUG_LT1B	0xf12b00ff
+
+/* DEBG_LT1c */
+#define	R367TER_DEBG_LT1C	0xf12c
+#define	F367TER_DEBUG_LT1C	0xf12c00ff
+
+/* DEBG_LT1D */
+#define	R367TER_DEBG_LT1D	0xf12d
+#define	F367TER_DEBUG_LT1D	0xf12d00ff
+
+/* DEBG_LT1E */
+#define	R367TER_DEBG_LT1E	0xf12e
+#define	F367TER_DEBUG_LT1E	0xf12e00ff
+
+/* DEBG_LT1F */
+#define	R367TER_DEBG_LT1F	0xf12f
+#define	F367TER_DEBUG_LT1F	0xf12f00ff
+
+/* RCCFGH */
+#define	R367TER_RCCFGH	0xf200
+#define	F367TER_TSRCFIFO_DVBCI	0xf2000080
+#define	F367TER_TSRCFIFO_SERIAL	0xf2000040
+#define	F367TER_TSRCFIFO_DISABLE	0xf2000020
+#define	F367TER_TSFIFO_2TORC	0xf2000010
+#define	F367TER_TSRCFIFO_HSGNLOUT	0xf2000008
+#define	F367TER_TSRCFIFO_ERRMODE	0xf2000006
+#define	F367TER_RCCFGH_0	0xf2000001
+
+/* RCCFGM */
+#define	R367TER_RCCFGM	0xf201
+#define	F367TER_TSRCFIFO_MANSPEED	0xf20100c0
+#define	F367TER_TSRCFIFO_PERMDATA	0xf2010020
+#define	F367TER_TSRCFIFO_NONEWSGNL	0xf2010010
+#define	F367TER_RCBYTE_OVERSAMPLING	0xf201000e
+#define	F367TER_TSRCFIFO_INVDATA	0xf2010001
+
+/* RCCFGL */
+#define	R367TER_RCCFGL	0xf202
+#define	F367TER_TSRCFIFO_BCLKDEL1cK	0xf20200c0
+#define	F367TER_RCCFGL_5	0xf2020020
+#define	F367TER_TSRCFIFO_DUTY50	0xf2020010
+#define	F367TER_TSRCFIFO_NSGNL2dATA	0xf2020008
+#define	F367TER_TSRCFIFO_DISSERMUX	0xf2020004
+#define	F367TER_RCCFGL_1	0xf2020002
+#define	F367TER_TSRCFIFO_STOPCKDIS	0xf2020001
+
+/* RCINSDELH */
+#define	R367TER_RCINSDELH	0xf203
+#define	F367TER_TSRCDEL_SYNCBYTE	0xf2030080
+#define	F367TER_TSRCDEL_XXHEADER	0xf2030040
+#define	F367TER_TSRCDEL_BBHEADER	0xf2030020
+#define	F367TER_TSRCDEL_DATAFIELD	0xf2030010
+#define	F367TER_TSRCINSDEL_ISCR	0xf2030008
+#define	F367TER_TSRCINSDEL_NPD	0xf2030004
+#define	F367TER_TSRCINSDEL_RSPARITY	0xf2030002
+#define	F367TER_TSRCINSDEL_CRC8	0xf2030001
+
+/* RCINSDELM */
+#define	R367TER_RCINSDELM	0xf204
+#define	F367TER_TSRCINS_BBPADDING	0xf2040080
+#define	F367TER_TSRCINS_BCHFEC	0xf2040040
+#define	F367TER_TSRCINS_LDPCFEC	0xf2040020
+#define	F367TER_TSRCINS_EMODCOD	0xf2040010
+#define	F367TER_TSRCINS_TOKEN	0xf2040008
+#define	F367TER_TSRCINS_XXXERR	0xf2040004
+#define	F367TER_TSRCINS_MATYPE	0xf2040002
+#define	F367TER_TSRCINS_UPL	0xf2040001
+
+/* RCINSDELL */
+#define	R367TER_RCINSDELL	0xf205
+#define	F367TER_TSRCINS_DFL	0xf2050080
+#define	F367TER_TSRCINS_SYNCD	0xf2050040
+#define	F367TER_TSRCINS_BLOCLEN	0xf2050020
+#define	F367TER_TSRCINS_SIGPCOUNT	0xf2050010
+#define	F367TER_TSRCINS_FIFO	0xf2050008
+#define	F367TER_TSRCINS_REALPACK	0xf2050004
+#define	F367TER_TSRCINS_TSCONFIG	0xf2050002
+#define	F367TER_TSRCINS_LATENCY	0xf2050001
+
+/* RCSTATUS */
+#define	R367TER_RCSTATUS	0xf206
+#define	F367TER_TSRCFIFO_LINEOK	0xf2060080
+#define	F367TER_TSRCFIFO_ERROR	0xf2060040
+#define	F367TER_TSRCFIFO_DATA7	0xf2060020
+#define	F367TER_RCSTATUS_4	0xf2060010
+#define	F367TER_TSRCFIFO_DEMODSEL	0xf2060008
+#define	F367TER_TSRC1FIFOSPEED_STORE	0xf2060004
+#define	F367TER_RCSTATUS_1	0xf2060002
+#define	F367TER_TSRCSERIAL_IMPOSSIBLE	0xf2060001
+
+/* RCSPEED */
+#define	R367TER_RCSPEED	0xf207
+#define	F367TER_TSRCFIFO_OUTSPEED	0xf20700ff
+
+/* RCDEBUGM */
+#define	R367TER_RCDEBUGM	0xf208
+#define	F367TER_SD_UNSYNC	0xf2080080
+#define	F367TER_ULFLOCK_DETECTM	0xf2080040
+#define	F367TER_SUL_SELECTOS	0xf2080020
+#define	F367TER_DILUL_NOSCRBLE	0xf2080010
+#define	F367TER_NUL_SCRB	0xf2080008
+#define	F367TER_UL_SCRB	0xf2080004
+#define	F367TER_SCRAULBAD	0xf2080002
+#define	F367TER_SCRAUL_UNSYNC	0xf2080001
+
+/* RCDEBUGL */
+#define	R367TER_RCDEBUGL	0xf209
+#define	F367TER_RS_ERR	0xf2090080
+#define	F367TER_LLFLOCK_DETECTM	0xf2090040
+#define	F367TER_NOT_SUL_SELECTOS	0xf2090020
+#define	F367TER_DILLL_NOSCRBLE	0xf2090010
+#define	F367TER_NLL_SCRB	0xf2090008
+#define	F367TER_LL_SCRB	0xf2090004
+#define	F367TER_SCRALLBAD	0xf2090002
+#define	F367TER_SCRALL_UNSYNC	0xf2090001
+
+/* RCOBSCFG */
+#define	R367TER_RCOBSCFG	0xf20a
+#define	F367TER_TSRCFIFO_OBSCFG	0xf20a00ff
+
+/* RCOBSM */
+#define	R367TER_RCOBSM	0xf20b
+#define	F367TER_TSRCFIFO_OBSDATA_HI	0xf20b00ff
+
+/* RCOBSL */
+#define	R367TER_RCOBSL	0xf20c
+#define	F367TER_TSRCFIFO_OBSDATA_LO	0xf20c00ff
+
+/* RCFECSPY */
+#define	R367TER_RCFECSPY	0xf210
+#define	F367TER_SPYRC_ENABLE	0xf2100080
+#define	F367TER_RCNO_SYNCBYTE	0xf2100040
+#define	F367TER_RCSERIAL_MODE	0xf2100020
+#define	F367TER_RCUNUSUAL_PACKET	0xf2100010
+#define	F367TER_BERRCMETER_DATAMODE	0xf210000c
+#define	F367TER_BERRCMETER_LMODE	0xf2100002
+#define	F367TER_BERRCMETER_RESET	0xf2100001
+
+/* RCFSPYCFG */
+#define	R367TER_RCFSPYCFG	0xf211
+#define	F367TER_FECSPYRC_INPUT	0xf21100c0
+#define	F367TER_RCRST_ON_ERROR	0xf2110020
+#define	F367TER_RCONE_SHOT	0xf2110010
+#define	F367TER_RCI2C_MODE	0xf211000c
+#define	F367TER_SPYRC_HSTERESIS	0xf2110003
+
+/* RCFSPYDATA */
+#define	R367TER_RCFSPYDATA	0xf212
+#define	F367TER_SPYRC_STUFFING	0xf2120080
+#define	F367TER_RCNOERR_PKTJITTER	0xf2120040
+#define	F367TER_SPYRC_CNULLPKT	0xf2120020
+#define	F367TER_SPYRC_OUTDATA_MODE	0xf212001f
+
+/* RCFSPYOUT */
+#define	R367TER_RCFSPYOUT	0xf213
+#define	F367TER_FSPYRC_DIRECT	0xf2130080
+#define	F367TER_RCFSPYOUT_6	0xf2130040
+#define	F367TER_SPYRC_OUTDATA_BUS	0xf2130038
+#define	F367TER_RCSTUFF_MODE	0xf2130007
+
+/* RCFSTATUS */
+#define	R367TER_RCFSTATUS	0xf214
+#define	F367TER_SPYRC_ENDSIM	0xf2140080
+#define	F367TER_RCVALID_SIM	0xf2140040
+#define	F367TER_RCFOUND_SIGNAL	0xf2140020
+#define	F367TER_RCDSS_SYNCBYTE	0xf2140010
+#define	F367TER_RCRESULT_STATE	0xf214000f
+
+/* RCFGOODPACK */
+#define	R367TER_RCFGOODPACK	0xf215
+#define	F367TER_RCGOOD_PACKET	0xf21500ff
+
+/* RCFPACKCNT */
+#define	R367TER_RCFPACKCNT	0xf216
+#define	F367TER_RCPACKET_COUNTER	0xf21600ff
+
+/* RCFSPYMISC */
+#define	R367TER_RCFSPYMISC	0xf217
+#define	F367TER_RCLABEL_COUNTER	0xf21700ff
+
+/* RCFBERCPT4 */
+#define	R367TER_RCFBERCPT4	0xf218
+#define	F367TER_FBERRCMETER_CPT_MMMMSB	0xf21800ff
+
+/* RCFBERCPT3 */
+#define	R367TER_RCFBERCPT3	0xf219
+#define	F367TER_FBERRCMETER_CPT_MMMSB	0xf21900ff
+
+/* RCFBERCPT2 */
+#define	R367TER_RCFBERCPT2	0xf21a
+#define	F367TER_FBERRCMETER_CPT_MMSB	0xf21a00ff
+
+/* RCFBERCPT1 */
+#define	R367TER_RCFBERCPT1	0xf21b
+#define	F367TER_FBERRCMETER_CPT_MSB	0xf21b00ff
+
+/* RCFBERCPT0 */
+#define	R367TER_RCFBERCPT0	0xf21c
+#define	F367TER_FBERRCMETER_CPT_LSB	0xf21c00ff
+
+/* RCFBERERR2 */
+#define	R367TER_RCFBERERR2	0xf21d
+#define	F367TER_FBERRCMETER_ERR_HI	0xf21d00ff
+
+/* RCFBERERR1 */
+#define	R367TER_RCFBERERR1	0xf21e
+#define	F367TER_FBERRCMETER_ERR	0xf21e00ff
+
+/* RCFBERERR0 */
+#define	R367TER_RCFBERERR0	0xf21f
+#define	F367TER_FBERRCMETER_ERR_LO	0xf21f00ff
+
+/* RCFSTATESM */
+#define	R367TER_RCFSTATESM	0xf220
+#define	F367TER_RCRSTATE_F	0xf2200080
+#define	F367TER_RCRSTATE_E	0xf2200040
+#define	F367TER_RCRSTATE_D	0xf2200020
+#define	F367TER_RCRSTATE_C	0xf2200010
+#define	F367TER_RCRSTATE_B	0xf2200008
+#define	F367TER_RCRSTATE_A	0xf2200004
+#define	F367TER_RCRSTATE_9	0xf2200002
+#define	F367TER_RCRSTATE_8	0xf2200001
+
+/* RCFSTATESL */
+#define	R367TER_RCFSTATESL	0xf221
+#define	F367TER_RCRSTATE_7	0xf2210080
+#define	F367TER_RCRSTATE_6	0xf2210040
+#define	F367TER_RCRSTATE_5	0xf2210020
+#define	F367TER_RCRSTATE_4	0xf2210010
+#define	F367TER_RCRSTATE_3	0xf2210008
+#define	F367TER_RCRSTATE_2	0xf2210004
+#define	F367TER_RCRSTATE_1	0xf2210002
+#define	F367TER_RCRSTATE_0	0xf2210001
+
+/* RCFSPYBER */
+#define	R367TER_RCFSPYBER	0xf222
+#define	F367TER_RCFSPYBER_7	0xf2220080
+#define	F367TER_SPYRCOBS_XORREAD	0xf2220040
+#define	F367TER_FSPYRCBER_OBSMODE	0xf2220020
+#define	F367TER_FSPYRCBER_SYNCBYT	0xf2220010
+#define	F367TER_FSPYRCBER_UNSYNC	0xf2220008
+#define	F367TER_FSPYRCBER_CTIME	0xf2220007
+
+/* RCFSPYDISTM */
+#define	R367TER_RCFSPYDISTM	0xf223
+#define	F367TER_RCPKTTIME_DISTANCE_HI	0xf22300ff
+
+/* RCFSPYDISTL */
+#define	R367TER_RCFSPYDISTL	0xf224
+#define	F367TER_RCPKTTIME_DISTANCE_LO	0xf22400ff
+
+/* RCFSPYOBS7 */
+#define	R367TER_RCFSPYOBS7	0xf228
+#define	F367TER_RCSPYOBS_SPYFAIL	0xf2280080
+#define	F367TER_RCSPYOBS_SPYFAIL1	0xf2280040
+#define	F367TER_RCSPYOBS_ERROR	0xf2280020
+#define	F367TER_RCSPYOBS_STROUT	0xf2280010
+#define	F367TER_RCSPYOBS_RESULTSTATE1	0xf228000f
+
+/* RCFSPYOBS6 */
+#define	R367TER_RCFSPYOBS6	0xf229
+#define	F367TER_RCSPYOBS_RESULTSTATe0	0xf22900f0
+#define	F367TER_RCSPYOBS_RESULTSTATEM1	0xf229000f
+
+/* RCFSPYOBS5 */
+#define	R367TER_RCFSPYOBS5	0xf22a
+#define	F367TER_RCSPYOBS_BYTEOFPACKET1	0xf22a00ff
+
+/* RCFSPYOBS4 */
+#define	R367TER_RCFSPYOBS4	0xf22b
+#define	F367TER_RCSPYOBS_BYTEVALUE1	0xf22b00ff
+
+/* RCFSPYOBS3 */
+#define	R367TER_RCFSPYOBS3	0xf22c
+#define	F367TER_RCSPYOBS_DATA1	0xf22c00ff
+
+/* RCFSPYOBS2 */
+#define	R367TER_RCFSPYOBS2	0xf22d
+#define	F367TER_RCSPYOBS_DATa0	0xf22d00ff
+
+/* RCFSPYOBS1 */
+#define	R367TER_RCFSPYOBS1	0xf22e
+#define	F367TER_RCSPYOBS_DATAM1	0xf22e00ff
+
+/* RCFSPYOBS0 */
+#define	R367TER_RCFSPYOBS0	0xf22f
+#define	F367TER_RCSPYOBS_DATAM2	0xf22f00ff
+
+/* TSGENERAL */
+#define	R367TER_TSGENERAL	0xf230
+#define	F367TER_TSGENERAL_7	0xf2300080
+#define	F367TER_TSGENERAL_6	0xf2300040
+#define	F367TER_TSFIFO_BCLK1aLL	0xf2300020
+#define	F367TER_TSGENERAL_4	0xf2300010
+#define	F367TER_MUXSTREAM_OUTMODE	0xf2300008
+#define	F367TER_TSFIFO_PERMPARAL	0xf2300006
+#define	F367TER_RST_REEDSOLO	0xf2300001
+
+/* RC1SPEED */
+#define	R367TER_RC1SPEED	0xf231
+#define	F367TER_TSRCFIFO1_OUTSPEED	0xf23100ff
+
+/* TSGSTATUS */
+#define	R367TER_TSGSTATUS	0xf232
+#define	F367TER_TSGSTATUS_7	0xf2320080
+#define	F367TER_TSGSTATUS_6	0xf2320040
+#define	F367TER_RSMEM_FULL	0xf2320020
+#define	F367TER_RS_MULTCALC	0xf2320010
+#define	F367TER_RSIN_OVERTIME	0xf2320008
+#define	F367TER_TSFIFO3_DEMODSEL	0xf2320004
+#define	F367TER_TSFIFO2_DEMODSEL	0xf2320002
+#define	F367TER_TSFIFO1_DEMODSEL	0xf2320001
+
+
+/* FECM */
+#define	R367TER_FECM	0xf233
+#define	F367TER_DSS_DVB	0xf2330080
+#define	F367TER_DEMOD_BYPASS	0xf2330040
+#define	F367TER_CMP_SLOWMODE	0xf2330020
+#define	F367TER_DSS_SRCH	0xf2330010
+#define	F367TER_FECM_3	0xf2330008
+#define	F367TER_DIFF_MODEVIT	0xf2330004
+#define	F367TER_SYNCVIT	0xf2330002
+#define	F367TER_I2CSYM	0xf2330001
+
+/* VTH12 */
+#define	R367TER_VTH12	0xf234
+#define	F367TER_VTH_12	0xf23400ff
+
+/* VTH23 */
+#define	R367TER_VTH23	0xf235
+#define	F367TER_VTH_23	0xf23500ff
+
+/* VTH34 */
+#define	R367TER_VTH34	0xf236
+#define	F367TER_VTH_34	0xf23600ff
+
+/* VTH56 */
+#define	R367TER_VTH56	0xf237
+#define	F367TER_VTH_56	0xf23700ff
+
+/* VTH67 */
+#define	R367TER_VTH67	0xf238
+#define	F367TER_VTH_67	0xf23800ff
+
+/* VTH78 */
+#define	R367TER_VTH78	0xf239
+#define	F367TER_VTH_78	0xf23900ff
+
+/* VITCURPUN */
+#define	R367TER_VITCURPUN	0xf23a
+#define	F367TER_VIT_MAPPING	0xf23a00e0
+#define	F367TER_VIT_CURPUN	0xf23a001f
+
+/* VERROR */
+#define	R367TER_VERROR	0xf23b
+#define	F367TER_REGERR_VIT	0xf23b00ff
+
+/* PRVIT */
+#define	R367TER_PRVIT	0xf23c
+#define	F367TER_PRVIT_7	0xf23c0080
+#define	F367TER_DIS_VTHLOCK	0xf23c0040
+#define	F367TER_E7_8VIT	0xf23c0020
+#define	F367TER_E6_7VIT	0xf23c0010
+#define	F367TER_E5_6VIT	0xf23c0008
+#define	F367TER_E3_4VIT	0xf23c0004
+#define	F367TER_E2_3VIT	0xf23c0002
+#define	F367TER_E1_2VIT	0xf23c0001
+
+/* VAVSRVIT */
+#define	R367TER_VAVSRVIT	0xf23d
+#define	F367TER_AMVIT	0xf23d0080
+#define	F367TER_FROZENVIT	0xf23d0040
+#define	F367TER_SNVIT	0xf23d0030
+#define	F367TER_TOVVIT	0xf23d000c
+#define	F367TER_HYPVIT	0xf23d0003
+
+/* VSTATUSVIT */
+#define	R367TER_VSTATUSVIT	0xf23e
+#define	F367TER_VITERBI_ON	0xf23e0080
+#define	F367TER_END_LOOPVIT	0xf23e0040
+#define	F367TER_VITERBI_DEPRF	0xf23e0020
+#define	F367TER_PRFVIT	0xf23e0010
+#define	F367TER_LOCKEDVIT	0xf23e0008
+#define	F367TER_VITERBI_DELOCK	0xf23e0004
+#define	F367TER_VIT_DEMODSEL	0xf23e0002
+#define	F367TER_VITERBI_COMPOUT	0xf23e0001
+
+/* VTHINUSE */
+#define	R367TER_VTHINUSE	0xf23f
+#define	F367TER_VIT_INUSE	0xf23f00ff
+
+/* KDIV12 */
+#define	R367TER_KDIV12	0xf240
+#define	F367TER_KDIV12_MANUAL	0xf2400080
+#define	F367TER_K_DIVIDER_12	0xf240007f
+
+/* KDIV23 */
+#define	R367TER_KDIV23	0xf241
+#define	F367TER_KDIV23_MANUAL	0xf2410080
+#define	F367TER_K_DIVIDER_23	0xf241007f
+
+/* KDIV34 */
+#define	R367TER_KDIV34	0xf242
+#define	F367TER_KDIV34_MANUAL	0xf2420080
+#define	F367TER_K_DIVIDER_34	0xf242007f
+
+/* KDIV56 */
+#define	R367TER_KDIV56	0xf243
+#define	F367TER_KDIV56_MANUAL	0xf2430080
+#define	F367TER_K_DIVIDER_56	0xf243007f
+
+/* KDIV67 */
+#define	R367TER_KDIV67	0xf244
+#define	F367TER_KDIV67_MANUAL	0xf2440080
+#define	F367TER_K_DIVIDER_67	0xf244007f
+
+/* KDIV78 */
+#define	R367TER_KDIV78	0xf245
+#define	F367TER_KDIV78_MANUAL	0xf2450080
+#define	F367TER_K_DIVIDER_78	0xf245007f
+
+/* SIGPOWER */
+#define	R367TER_SIGPOWER	0xf246
+#define	F367TER_SIGPOWER_MANUAL	0xf2460080
+#define	F367TER_SIG_POWER	0xf246007f
+
+/* DEMAPVIT */
+#define	R367TER_DEMAPVIT	0xf247
+#define	F367TER_DEMAPVIT_7	0xf2470080
+#define	F367TER_K_DIVIDER_VIT	0xf247007f
+
+/* VITSCALE */
+#define	R367TER_VITSCALE	0xf248
+#define	F367TER_NVTH_NOSRANGE	0xf2480080
+#define	F367TER_VERROR_MAXMODE	0xf2480040
+#define	F367TER_KDIV_MODE	0xf2480030
+#define	F367TER_NSLOWSN_LOCKED	0xf2480008
+#define	F367TER_DELOCK_PRFLOSS	0xf2480004
+#define	F367TER_DIS_RSFLOCK	0xf2480002
+#define	F367TER_VITSCALE_0	0xf2480001
+
+/* FFEC1PRG */
+#define	R367TER_FFEC1PRG	0xf249
+#define	F367TER_FDSS_DVB	0xf2490080
+#define	F367TER_FDSS_SRCH	0xf2490040
+#define	F367TER_FFECPROG_5	0xf2490020
+#define	F367TER_FFECPROG_4	0xf2490010
+#define	F367TER_FFECPROG_3	0xf2490008
+#define	F367TER_FFECPROG_2	0xf2490004
+#define	F367TER_FTS1_DISABLE	0xf2490002
+#define	F367TER_FTS2_DISABLE	0xf2490001
+
+/* FVITCURPUN */
+#define	R367TER_FVITCURPUN	0xf24a
+#define	F367TER_FVIT_MAPPING	0xf24a00e0
+#define	F367TER_FVIT_CURPUN	0xf24a001f
+
+/* FVERROR */
+#define	R367TER_FVERROR	0xf24b
+#define	F367TER_FREGERR_VIT	0xf24b00ff
+
+/* FVSTATUSVIT */
+#define	R367TER_FVSTATUSVIT	0xf24c
+#define	F367TER_FVITERBI_ON	0xf24c0080
+#define	F367TER_F1END_LOOPVIT	0xf24c0040
+#define	F367TER_FVITERBI_DEPRF	0xf24c0020
+#define	F367TER_FPRFVIT	0xf24c0010
+#define	F367TER_FLOCKEDVIT	0xf24c0008
+#define	F367TER_FVITERBI_DELOCK	0xf24c0004
+#define	F367TER_FVIT_DEMODSEL	0xf24c0002
+#define	F367TER_FVITERBI_COMPOUT	0xf24c0001
+
+/* DEBUG_LT1 */
+#define	R367TER_DEBUG_LT1	0xf24d
+#define	F367TER_DBG_LT1	0xf24d00ff
+
+/* DEBUG_LT2 */
+#define	R367TER_DEBUG_LT2	0xf24e
+#define	F367TER_DBG_LT2	0xf24e00ff
+
+/* DEBUG_LT3 */
+#define	R367TER_DEBUG_LT3	0xf24f
+#define	F367TER_DBG_LT3	0xf24f00ff
+
+/*	TSTSFMET */
+#define	R367TER_TSTSFMET	0xf250
+#define F367TER_TSTSFEC_METRIQUES	0xf25000ff
+
+/*	SELOUT */
+#define	R367TER_SELOUT	0xf252
+#define	F367TER_EN_SYNC	0xf2520080
+#define	F367TER_EN_TBUSDEMAP	0xf2520040
+#define	F367TER_SELOUT_5	0xf2520020
+#define	F367TER_SELOUT_4	0xf2520010
+#define	F367TER_TSTSYNCHRO_MODE	0xf2520002
+
+/*	TSYNC */
+#define R367TER_TSYNC	0xf253
+#define F367TER_CURPUN_INCMODE	0xf2530080
+#define F367TER_CERR_TSTMODE	0xf2530040
+#define F367TER_SHIFTSOF_MODE	0xf2530030
+#define F367TER_SLOWPHA_MODE	0xf2530008
+#define F367TER_PXX_BYPALL	0xf2530004
+#define F367TER_FROTA45_FIRST	0xf2530002
+#define F367TER_TST_BCHERROR	0xf2530001
+
+/*	TSTERR */
+#define R367TER_TSTERR	0xf254
+#define F367TER_TST_LONGPKT	0xf2540080
+#define F367TER_TST_ISSYION	0xf2540040
+#define F367TER_TST_NPDON	0xf2540020
+#define F367TER_TSTERR_4	0xf2540010
+#define F367TER_TRACEBACK_MODE	0xf2540008
+#define F367TER_TST_RSPARITY	0xf2540004
+#define F367TER_METRIQUE_MODE	0xf2540003
+
+/*	TSFSYNC */
+#define R367TER_TSFSYNC	0xf255
+#define F367TER_EN_SFECSYNC	0xf2550080
+#define F367TER_EN_SFECDEMAP	0xf2550040
+#define F367TER_SFCERR_TSTMODE	0xf2550020
+#define F367TER_SFECPXX_BYPALL	0xf2550010
+#define F367TER_SFECTSTSYNCHRO_MODE 0xf255000f
+
+/*	TSTSFERR */
+#define R367TER_TSTSFERR	0xf256
+#define F367TER_TSTSTERR_7	0xf2560080
+#define F367TER_TSTSTERR_6	0xf2560040
+#define F367TER_TSTSTERR_5	0xf2560020
+#define F367TER_TSTSTERR_4	0xf2560010
+#define F367TER_SFECTRACEBACK_MODE	0xf2560008
+#define F367TER_SFEC_NCONVPROG	0xf2560004
+#define F367TER_SFECMETRIQUE_MODE	0xf2560003
+
+/*	TSTTSSF1 */
+#define R367TER_TSTTSSF1	0xf258
+#define F367TER_TSTERSSF	0xf2580080
+#define F367TER_TSTTSSFEN	0xf2580040
+#define F367TER_SFEC_OUTMODE	0xf2580030
+#define F367TER_XLSF_NOFTHRESHOLD  0xf2580008
+#define F367TER_TSTTSSF_STACKSEL	0xf2580007
+
+/*	TSTTSSF2 */
+#define R367TER_TSTTSSF2	0xf259
+#define F367TER_DILSF_DBBHEADER	0xf2590080
+#define F367TER_TSTTSSF_DISBUG	0xf2590040
+#define F367TER_TSTTSSF_NOBADSTART	0xf2590020
+#define F367TER_TSTTSSF_SELECT	0xf259001f
+
+/*	TSTTSSF3 */
+#define R367TER_TSTTSSF3	0xf25a
+#define F367TER_TSTTSSF3_7	0xf25a0080
+#define F367TER_TSTTSSF3_6	0xf25a0040
+#define F367TER_TSTTSSF3_5	0xf25a0020
+#define F367TER_TSTTSSF3_4	0xf25a0010
+#define F367TER_TSTTSSF3_3	0xf25a0008
+#define F367TER_TSTTSSF3_2	0xf25a0004
+#define F367TER_TSTTSSF3_1	0xf25a0002
+#define F367TER_DISSF_CLKENABLE	0xf25a0001
+
+/*	TSTTS1 */
+#define R367TER_TSTTS1	0xf25c
+#define F367TER_TSTERS	0xf25c0080
+#define F367TER_TSFIFO_DSSSYNCB	0xf25c0040
+#define F367TER_TSTTS_FSPYBEFRS	0xf25c0020
+#define F367TER_NFORCE_SYNCBYTE	0xf25c0010
+#define F367TER_XL_NOFTHRESHOLD	0xf25c0008
+#define F367TER_TSTTS_FRFORCEPKT	0xf25c0004
+#define F367TER_DESCR_NOTAUTO	0xf25c0002
+#define F367TER_TSTTSEN	0xf25c0001
+
+/*	TSTTS2 */
+#define R367TER_TSTTS2	0xf25d
+#define F367TER_DIL_DBBHEADER	0xf25d0080
+#define F367TER_TSTTS_NOBADXXX	0xf25d0040
+#define F367TER_TSFIFO_DELSPEEDUP	0xf25d0020
+#define F367TER_TSTTS_SELECT	0xf25d001f
+
+/*	TSTTS3 */
+#define R367TER_TSTTS3	0xf25e
+#define F367TER_TSTTS_NOPKTGAIN	0xf25e0080
+#define F367TER_TSTTS_NOPKTENE	0xf25e0040
+#define F367TER_TSTTS_ISOLATION	0xf25e0020
+#define F367TER_TSTTS_DISBUG	0xf25e0010
+#define F367TER_TSTTS_NOBADSTART	0xf25e0008
+#define F367TER_TSTTS_STACKSEL	0xf25e0007
+
+/*	TSTTS4 */
+#define R367TER_TSTTS4	0xf25f
+#define F367TER_TSTTS4_7	0xf25f0080
+#define F367TER_TSTTS4_6	0xf25f0040
+#define F367TER_TSTTS4_5	0xf25f0020
+#define F367TER_TSTTS_DISDSTATE	0xf25f0010
+#define F367TER_TSTTS_FASTNOSYNC	0xf25f0008
+#define F367TER_EXT_FECSPYIN	0xf25f0004
+#define F367TER_TSTTS_NODPZERO	0xf25f0002
+#define F367TER_TSTTS_NODIV3	0xf25f0001
+
+/*	TSTTSRC */
+#define R367TER_TSTTSRC	0xf26c
+#define F367TER_TSTTSRC_7	0xf26c0080
+#define F367TER_TSRCFIFO_DSSSYNCB	0xf26c0040
+#define F367TER_TSRCFIFO_DPUNACTIVE	0xf26c0020
+#define F367TER_TSRCFIFO_DELSPEEDUP	0xf26c0010
+#define F367TER_TSTTSRC_NODIV3	0xf26c0008
+#define F367TER_TSTTSRC_FRFORCEPKT	0xf26c0004
+#define F367TER_SAT25_SDDORIGINE	0xf26c0002
+#define F367TER_TSTTSRC_INACTIVE	0xf26c0001
+
+/*	TSTTSRS */
+#define R367TER_TSTTSRS	0xf26d
+#define F367TER_TSTTSRS_7	0xf26d0080
+#define F367TER_TSTTSRS_6	0xf26d0040
+#define F367TER_TSTTSRS_5	0xf26d0020
+#define F367TER_TSTTSRS_4	0xf26d0010
+#define F367TER_TSTTSRS_3	0xf26d0008
+#define F367TER_TSTTSRS_2	0xf26d0004
+#define F367TER_TSTRS_DISRS2	0xf26d0002
+#define F367TER_TSTRS_DISRS1	0xf26d0001
+
+/* TSSTATEM */
+#define	R367TER_TSSTATEM	0xf270
+#define	F367TER_TSDIL_ON	0xf2700080
+#define	F367TER_TSSKIPRS_ON	0xf2700040
+#define	F367TER_TSRS_ON	0xf2700020
+#define	F367TER_TSDESCRAMB_ON	0xf2700010
+#define	F367TER_TSFRAME_MODE	0xf2700008
+#define	F367TER_TS_DISABLE	0xf2700004
+#define	F367TER_TSACM_MODE	0xf2700002
+#define	F367TER_TSOUT_NOSYNC	0xf2700001
+
+/* TSSTATEL */
+#define	R367TER_TSSTATEL	0xf271
+#define	F367TER_TSNOSYNCBYTE	0xf2710080
+#define	F367TER_TSPARITY_ON	0xf2710040
+#define	F367TER_TSSYNCOUTRS_ON	0xf2710020
+#define	F367TER_TSDVBS2_MODE	0xf2710010
+#define	F367TER_TSISSYI_ON	0xf2710008
+#define	F367TER_TSNPD_ON	0xf2710004
+#define	F367TER_TSCRC8_ON	0xf2710002
+#define	F367TER_TSDSS_PACKET	0xf2710001
+
+/* TSCFGH */
+#define	R367TER_TSCFGH	0xf272
+#define	F367TER_TSFIFO_DVBCI	0xf2720080
+#define	F367TER_TSFIFO_SERIAL	0xf2720040
+#define	F367TER_TSFIFO_TEIUPDATE	0xf2720020
+#define	F367TER_TSFIFO_DUTY50	0xf2720010
+#define	F367TER_TSFIFO_HSGNLOUT	0xf2720008
+#define	F367TER_TSFIFO_ERRMODE	0xf2720006
+#define	F367TER_RST_HWARE	0xf2720001
+
+/* TSCFGM */
+#define	R367TER_TSCFGM	0xf273
+#define	F367TER_TSFIFO_MANSPEED	0xf27300c0
+#define	F367TER_TSFIFO_PERMDATA	0xf2730020
+#define	F367TER_TSFIFO_NONEWSGNL	0xf2730010
+#define	F367TER_TSFIFO_BITSPEED	0xf2730008
+#define	F367TER_NPD_SPECDVBS2	0xf2730004
+#define	F367TER_TSFIFO_STOPCKDIS	0xf2730002
+#define	F367TER_TSFIFO_INVDATA	0xf2730001
+
+/* TSCFGL */
+#define	R367TER_TSCFGL	0xf274
+#define	F367TER_TSFIFO_BCLKDEL1cK	0xf27400c0
+#define	F367TER_BCHERROR_MODE	0xf2740030
+#define	F367TER_TSFIFO_NSGNL2dATA	0xf2740008
+#define	F367TER_TSFIFO_EMBINDVB	0xf2740004
+#define	F367TER_TSFIFO_DPUNACT	0xf2740002
+#define	F367TER_TSFIFO_NPDOFF	0xf2740001
+
+/* TSSYNC */
+#define	R367TER_TSSYNC	0xf275
+#define	F367TER_TSFIFO_PERMUTE	0xf2750080
+#define	F367TER_TSFIFO_FISCR3B	0xf2750060
+#define	F367TER_TSFIFO_SYNCMODE	0xf2750018
+#define	F367TER_TSFIFO_SYNCSEL	0xf2750007
+
+/* TSINSDELH */
+#define	R367TER_TSINSDELH	0xf276
+#define	F367TER_TSDEL_SYNCBYTE	0xf2760080
+#define	F367TER_TSDEL_XXHEADER	0xf2760040
+#define	F367TER_TSDEL_BBHEADER	0xf2760020
+#define	F367TER_TSDEL_DATAFIELD	0xf2760010
+#define	F367TER_TSINSDEL_ISCR	0xf2760008
+#define	F367TER_TSINSDEL_NPD	0xf2760004
+#define	F367TER_TSINSDEL_RSPARITY	0xf2760002
+#define	F367TER_TSINSDEL_CRC8	0xf2760001
+
+/* TSINSDELM */
+#define	R367TER_TSINSDELM	0xf277
+#define	F367TER_TSINS_BBPADDING	0xf2770080
+#define	F367TER_TSINS_BCHFEC	0xf2770040
+#define	F367TER_TSINS_LDPCFEC	0xf2770020
+#define	F367TER_TSINS_EMODCOD	0xf2770010
+#define	F367TER_TSINS_TOKEN	0xf2770008
+#define	F367TER_TSINS_XXXERR	0xf2770004
+#define	F367TER_TSINS_MATYPE	0xf2770002
+#define	F367TER_TSINS_UPL	0xf2770001
+
+/* TSINSDELL */
+#define	R367TER_TSINSDELL	0xf278
+#define	F367TER_TSINS_DFL	0xf2780080
+#define	F367TER_TSINS_SYNCD	0xf2780040
+#define	F367TER_TSINS_BLOCLEN	0xf2780020
+#define	F367TER_TSINS_SIGPCOUNT	0xf2780010
+#define	F367TER_TSINS_FIFO	0xf2780008
+#define	F367TER_TSINS_REALPACK	0xf2780004
+#define	F367TER_TSINS_TSCONFIG	0xf2780002
+#define	F367TER_TSINS_LATENCY	0xf2780001
+
+/* TSDIVN */
+#define	R367TER_TSDIVN	0xf279
+#define	F367TER_TSFIFO_LOWSPEED	0xf2790080
+#define	F367TER_BYTE_OVERSAMPLING	0xf2790070
+#define	F367TER_TSMANUAL_PACKETNBR	0xf279000f
+
+/* TSDIVPM */
+#define	R367TER_TSDIVPM	0xf27a
+#define	F367TER_TSMANUAL_P_HI	0xf27a00ff
+
+/* TSDIVPL */
+#define	R367TER_TSDIVPL	0xf27b
+#define	F367TER_TSMANUAL_P_LO	0xf27b00ff
+
+/* TSDIVQM */
+#define	R367TER_TSDIVQM	0xf27c
+#define	F367TER_TSMANUAL_Q_HI	0xf27c00ff
+
+/* TSDIVQL */
+#define	R367TER_TSDIVQL	0xf27d
+#define	F367TER_TSMANUAL_Q_LO	0xf27d00ff
+
+/* TSDILSTKM */
+#define	R367TER_TSDILSTKM	0xf27e
+#define	F367TER_TSFIFO_DILSTK_HI	0xf27e00ff
+
+/* TSDILSTKL */
+#define	R367TER_TSDILSTKL	0xf27f
+#define	F367TER_TSFIFO_DILSTK_LO	0xf27f00ff
+
+/* TSSPEED */
+#define	R367TER_TSSPEED	0xf280
+#define	F367TER_TSFIFO_OUTSPEED	0xf28000ff
+
+/* TSSTATUS */
+#define	R367TER_TSSTATUS	0xf281
+#define	F367TER_TSFIFO_LINEOK	0xf2810080
+#define	F367TER_TSFIFO_ERROR	0xf2810040
+#define	F367TER_TSFIFO_DATA7	0xf2810020
+#define	F367TER_TSFIFO_NOSYNC	0xf2810010
+#define	F367TER_ISCR_INITIALIZED	0xf2810008
+#define	F367TER_ISCR_UPDATED	0xf2810004
+#define	F367TER_SOFFIFO_UNREGUL	0xf2810002
+#define	F367TER_DIL_READY	0xf2810001
+
+/* TSSTATUS2 */
+#define	R367TER_TSSTATUS2	0xf282
+#define	F367TER_TSFIFO_DEMODSEL	0xf2820080
+#define	F367TER_TSFIFOSPEED_STORE	0xf2820040
+#define	F367TER_DILXX_RESET	0xf2820020
+#define	F367TER_TSSERIAL_IMPOSSIBLE	0xf2820010
+#define	F367TER_TSFIFO_UNDERSPEED	0xf2820008
+#define	F367TER_BITSPEED_EVENT	0xf2820004
+#define	F367TER_UL_SCRAMBDETECT	0xf2820002
+#define	F367TER_ULDTV67_FALSELOCK	0xf2820001
+
+/* TSBITRATEM */
+#define	R367TER_TSBITRATEM	0xf283
+#define	F367TER_TSFIFO_BITRATE_HI	0xf28300ff
+
+/* TSBITRATEL */
+#define	R367TER_TSBITRATEL	0xf284
+#define	F367TER_TSFIFO_BITRATE_LO	0xf28400ff
+
+/* TSPACKLENM */
+#define	R367TER_TSPACKLENM	0xf285
+#define	F367TER_TSFIFO_PACKCPT	0xf28500e0
+#define	F367TER_DIL_RPLEN_HI	0xf285001f
+
+/* TSPACKLENL */
+#define	R367TER_TSPACKLENL	0xf286
+#define	F367TER_DIL_RPLEN_LO	0xf28600ff
+
+/* TSBLOCLENM */
+#define	R367TER_TSBLOCLENM	0xf287
+#define	F367TER_TSFIFO_PFLEN_HI	0xf28700ff
+
+/* TSBLOCLENL */
+#define	R367TER_TSBLOCLENL	0xf288
+#define	F367TER_TSFIFO_PFLEN_LO	0xf28800ff
+
+/* TSDLYH */
+#define	R367TER_TSDLYH	0xf289
+#define	F367TER_SOFFIFO_TSTIMEVALID	0xf2890080
+#define	F367TER_SOFFIFO_SPEEDUP	0xf2890040
+#define	F367TER_SOFFIFO_STOP	0xf2890020
+#define	F367TER_SOFFIFO_REGULATED	0xf2890010
+#define	F367TER_SOFFIFO_REALSBOFF_HI	0xf289000f
+
+/* TSDLYM */
+#define	R367TER_TSDLYM	0xf28a
+#define	F367TER_SOFFIFO_REALSBOFF_MED	0xf28a00ff
+
+/* TSDLYL */
+#define	R367TER_TSDLYL	0xf28b
+#define	F367TER_SOFFIFO_REALSBOFF_LO	0xf28b00ff
+
+/* TSNPDAV */
+#define	R367TER_TSNPDAV	0xf28c
+#define	F367TER_TSNPD_AVERAGE	0xf28c00ff
+
+/* TSBUFSTATH */
+#define	R367TER_TSBUFSTATH	0xf28d
+#define	F367TER_TSISCR_3BYTES	0xf28d0080
+#define	F367TER_TSISCR_NEWDATA	0xf28d0040
+#define	F367TER_TSISCR_BUFSTAT_HI	0xf28d003f
+
+/* TSBUFSTATM */
+#define	R367TER_TSBUFSTATM	0xf28e
+#define	F367TER_TSISCR_BUFSTAT_MED	0xf28e00ff
+
+/* TSBUFSTATL */
+#define	R367TER_TSBUFSTATL	0xf28f
+#define	F367TER_TSISCR_BUFSTAT_LO	0xf28f00ff
+
+/* TSDEBUGM */
+#define	R367TER_TSDEBUGM	0xf290
+#define	F367TER_TSFIFO_ILLPACKET	0xf2900080
+#define	F367TER_DIL_NOSYNC	0xf2900040
+#define	F367TER_DIL_ISCR	0xf2900020
+#define	F367TER_DILOUT_BSYNCB	0xf2900010
+#define	F367TER_TSFIFO_EMPTYPKT	0xf2900008
+#define	F367TER_TSFIFO_EMPTYRD	0xf2900004
+#define	F367TER_SOFFIFO_STOPM	0xf2900002
+#define	F367TER_SOFFIFO_SPEEDUPM	0xf2900001
+
+/* TSDEBUGL */
+#define	R367TER_TSDEBUGL	0xf291
+#define	F367TER_TSFIFO_PACKLENFAIL	0xf2910080
+#define	F367TER_TSFIFO_SYNCBFAIL	0xf2910040
+#define	F367TER_TSFIFO_VITLIBRE	0xf2910020
+#define	F367TER_TSFIFO_BOOSTSPEEDM	0xf2910010
+#define	F367TER_TSFIFO_UNDERSPEEDM	0xf2910008
+#define	F367TER_TSFIFO_ERROR_EVNT	0xf2910004
+#define	F367TER_TSFIFO_FULL	0xf2910002
+#define	F367TER_TSFIFO_OVERFLOWM	0xf2910001
+
+/* TSDLYSETH */
+#define	R367TER_TSDLYSETH	0xf292
+#define	F367TER_SOFFIFO_OFFSET	0xf29200e0
+#define	F367TER_SOFFIFO_SYMBOFFSET_HI	0xf292001f
+
+/* TSDLYSETM */
+#define	R367TER_TSDLYSETM	0xf293
+#define	F367TER_SOFFIFO_SYMBOFFSET_MED	0xf29300ff
+
+/* TSDLYSETL */
+#define	R367TER_TSDLYSETL	0xf294
+#define	F367TER_SOFFIFO_SYMBOFFSET_LO	0xf29400ff
+
+/* TSOBSCFG */
+#define	R367TER_TSOBSCFG	0xf295
+#define	F367TER_TSFIFO_OBSCFG	0xf29500ff
+
+/* TSOBSM */
+#define	R367TER_TSOBSM	0xf296
+#define	F367TER_TSFIFO_OBSDATA_HI	0xf29600ff
+
+/* TSOBSL */
+#define	R367TER_TSOBSL	0xf297
+#define	F367TER_TSFIFO_OBSDATA_LO	0xf29700ff
+
+/* ERRCTRL1 */
+#define	R367TER_ERRCTRL1	0xf298
+#define	F367TER_ERR_SRC1	0xf29800f0
+#define	F367TER_ERRCTRL1_3	0xf2980008
+#define	F367TER_NUM_EVT1	0xf2980007
+
+/* ERRCNT1H */
+#define	R367TER_ERRCNT1H	0xf299
+#define	F367TER_ERRCNT1_OLDVALUE	0xf2990080
+#define	F367TER_ERR_CNT1	0xf299007f
+
+/* ERRCNT1M */
+#define	R367TER_ERRCNT1M	0xf29a
+#define	F367TER_ERR_CNT1_HI	0xf29a00ff
+
+/* ERRCNT1L */
+#define	R367TER_ERRCNT1L	0xf29b
+#define	F367TER_ERR_CNT1_LO	0xf29b00ff
+
+/* ERRCTRL2 */
+#define	R367TER_ERRCTRL2	0xf29c
+#define	F367TER_ERR_SRC2	0xf29c00f0
+#define	F367TER_ERRCTRL2_3	0xf29c0008
+#define	F367TER_NUM_EVT2	0xf29c0007
+
+/* ERRCNT2H */
+#define	R367TER_ERRCNT2H	0xf29d
+#define	F367TER_ERRCNT2_OLDVALUE	0xf29d0080
+#define	F367TER_ERR_CNT2_HI	0xf29d007f
+
+/* ERRCNT2M */
+#define	R367TER_ERRCNT2M	0xf29e
+#define	F367TER_ERR_CNT2_MED	0xf29e00ff
+
+/* ERRCNT2L */
+#define	R367TER_ERRCNT2L	0xf29f
+#define	F367TER_ERR_CNT2_LO	0xf29f00ff
+
+/* FECSPY */
+#define	R367TER_FECSPY	0xf2a0
+#define	F367TER_SPY_ENABLE	0xf2a00080
+#define	F367TER_NO_SYNCBYTE	0xf2a00040
+#define	F367TER_SERIAL_MODE	0xf2a00020
+#define	F367TER_UNUSUAL_PACKET	0xf2a00010
+#define	F367TER_BERMETER_DATAMODE	0xf2a0000c
+#define	F367TER_BERMETER_LMODE	0xf2a00002
+#define	F367TER_BERMETER_RESET	0xf2a00001
+
+/* FSPYCFG */
+#define	R367TER_FSPYCFG	0xf2a1
+#define	F367TER_FECSPY_INPUT	0xf2a100c0
+#define	F367TER_RST_ON_ERROR	0xf2a10020
+#define	F367TER_ONE_SHOT	0xf2a10010
+#define	F367TER_I2C_MOD	0xf2a1000c
+#define	F367TER_SPY_HYSTERESIS	0xf2a10003
+
+/* FSPYDATA */
+#define	R367TER_FSPYDATA	0xf2a2
+#define	F367TER_SPY_STUFFING	0xf2a20080
+#define	F367TER_NOERROR_PKTJITTER	0xf2a20040
+#define	F367TER_SPY_CNULLPKT	0xf2a20020
+#define	F367TER_SPY_OUTDATA_MODE	0xf2a2001f
+
+/* FSPYOUT */
+#define	R367TER_FSPYOUT	0xf2a3
+#define	F367TER_FSPY_DIRECT	0xf2a30080
+#define	F367TER_FSPYOUT_6	0xf2a30040
+#define	F367TER_SPY_OUTDATA_BUS	0xf2a30038
+#define	F367TER_STUFF_MODE	0xf2a30007
+
+/* FSTATUS */
+#define	R367TER_FSTATUS	0xf2a4
+#define	F367TER_SPY_ENDSIM	0xf2a40080
+#define	F367TER_VALID_SIM	0xf2a40040
+#define	F367TER_FOUND_SIGNAL	0xf2a40020
+#define	F367TER_DSS_SYNCBYTE	0xf2a40010
+#define	F367TER_RESULT_STATE	0xf2a4000f
+
+/* FGOODPACK */
+#define	R367TER_FGOODPACK	0xf2a5
+#define	F367TER_FGOOD_PACKET	0xf2a500ff
+
+/* FPACKCNT */
+#define	R367TER_FPACKCNT	0xf2a6
+#define	F367TER_FPACKET_COUNTER	0xf2a600ff
+
+/* FSPYMISC */
+#define	R367TER_FSPYMISC	0xf2a7
+#define	F367TER_FLABEL_COUNTER	0xf2a700ff
+
+/* FBERCPT4 */
+#define	R367TER_FBERCPT4	0xf2a8
+#define	F367TER_FBERMETER_CPT5	0xf2a800ff
+
+/* FBERCPT3 */
+#define	R367TER_FBERCPT3	0xf2a9
+#define	F367TER_FBERMETER_CPT4	0xf2a900ff
+
+/* FBERCPT2 */
+#define	R367TER_FBERCPT2	0xf2aa
+#define	F367TER_FBERMETER_CPT3	0xf2aa00ff
+
+/* FBERCPT1 */
+#define	R367TER_FBERCPT1	0xf2ab
+#define	F367TER_FBERMETER_CPT2	0xf2ab00ff
+
+/* FBERCPT0 */
+#define	R367TER_FBERCPT0	0xf2ac
+#define	F367TER_FBERMETER_CPT1	0xf2ac00ff
+
+/* FBERERR2 */
+#define	R367TER_FBERERR2	0xf2ad
+#define	F367TER_FBERMETER_ERR_HI	0xf2ad00ff
+
+/* FBERERR1 */
+#define	R367TER_FBERERR1	0xf2ae
+#define	F367TER_FBERMETER_ERR_MED	0xf2ae00ff
+
+/* FBERERR0 */
+#define	R367TER_FBERERR0	0xf2af
+#define	F367TER_FBERMETER_ERR_LO	0xf2af00ff
+
+/* FSTATESM */
+#define	R367TER_FSTATESM	0xf2b0
+#define	F367TER_RSTATE_F	0xf2b00080
+#define	F367TER_RSTATE_E	0xf2b00040
+#define	F367TER_RSTATE_D	0xf2b00020
+#define	F367TER_RSTATE_C	0xf2b00010
+#define	F367TER_RSTATE_B	0xf2b00008
+#define	F367TER_RSTATE_A	0xf2b00004
+#define	F367TER_RSTATE_9	0xf2b00002
+#define	F367TER_RSTATE_8	0xf2b00001
+
+/* FSTATESL */
+#define	R367TER_FSTATESL	0xf2b1
+#define	F367TER_RSTATE_7	0xf2b10080
+#define	F367TER_RSTATE_6	0xf2b10040
+#define	F367TER_RSTATE_5	0xf2b10020
+#define	F367TER_RSTATE_4	0xf2b10010
+#define	F367TER_RSTATE_3	0xf2b10008
+#define	F367TER_RSTATE_2	0xf2b10004
+#define	F367TER_RSTATE_1	0xf2b10002
+#define	F367TER_RSTATE_0	0xf2b10001
+
+/* FSPYBER */
+#define	R367TER_FSPYBER	0xf2b2
+#define	F367TER_FSPYBER_7	0xf2b20080
+#define	F367TER_FSPYOBS_XORREAD	0xf2b20040
+#define	F367TER_FSPYBER_OBSMODE	0xf2b20020
+#define	F367TER_FSPYBER_SYNCBYTE	0xf2b20010
+#define	F367TER_FSPYBER_UNSYNC	0xf2b20008
+#define	F367TER_FSPYBER_CTIME	0xf2b20007
+
+/* FSPYDISTM */
+#define	R367TER_FSPYDISTM	0xf2b3
+#define	F367TER_PKTTIME_DISTANCE_HI	0xf2b300ff
+
+/* FSPYDISTL */
+#define	R367TER_FSPYDISTL	0xf2b4
+#define	F367TER_PKTTIME_DISTANCE_LO	0xf2b400ff
+
+/* FSPYOBS7 */
+#define	R367TER_FSPYOBS7	0xf2b8
+#define	F367TER_FSPYOBS_SPYFAIL	0xf2b80080
+#define	F367TER_FSPYOBS_SPYFAIL1	0xf2b80040
+#define	F367TER_FSPYOBS_ERROR	0xf2b80020
+#define	F367TER_FSPYOBS_STROUT	0xf2b80010
+#define	F367TER_FSPYOBS_RESULTSTATE1	0xf2b8000f
+
+/* FSPYOBS6 */
+#define	R367TER_FSPYOBS6	0xf2b9
+#define	F367TER_FSPYOBS_RESULTSTATe0	0xf2b900f0
+#define	F367TER_FSPYOBS_RESULTSTATEM1	0xf2b9000f
+
+/* FSPYOBS5 */
+#define	R367TER_FSPYOBS5	0xf2ba
+#define	F367TER_FSPYOBS_BYTEOFPACKET1	0xf2ba00ff
+
+/* FSPYOBS4 */
+#define	R367TER_FSPYOBS4	0xf2bb
+#define	F367TER_FSPYOBS_BYTEVALUE1	0xf2bb00ff
+
+/* FSPYOBS3 */
+#define	R367TER_FSPYOBS3	0xf2bc
+#define	F367TER_FSPYOBS_DATA1	0xf2bc00ff
+
+/* FSPYOBS2 */
+#define	R367TER_FSPYOBS2	0xf2bd
+#define	F367TER_FSPYOBS_DATa0	0xf2bd00ff
+
+/* FSPYOBS1 */
+#define	R367TER_FSPYOBS1	0xf2be
+#define	F367TER_FSPYOBS_DATAM1	0xf2be00ff
+
+/* FSPYOBS0 */
+#define	R367TER_FSPYOBS0	0xf2bf
+#define	F367TER_FSPYOBS_DATAM2	0xf2bf00ff
+
+/* SFDEMAP */
+#define	R367TER_SFDEMAP	0xf2c0
+#define	F367TER_SFDEMAP_7	0xf2c00080
+#define	F367TER_SFEC_K_DIVIDER_VIT	0xf2c0007f
+
+/* SFERROR */
+#define	R367TER_SFERROR	0xf2c1
+#define	F367TER_SFEC_REGERR_VIT	0xf2c100ff
+
+/* SFAVSR */
+#define	R367TER_SFAVSR	0xf2c2
+#define	F367TER_SFEC_SUMERRORS	0xf2c20080
+#define	F367TER_SERROR_MAXMODE	0xf2c20040
+#define	F367TER_SN_SFEC	0xf2c20030
+#define	F367TER_KDIV_MODE_SFEC	0xf2c2000c
+#define	F367TER_SFAVSR_1	0xf2c20002
+#define	F367TER_SFAVSR_0	0xf2c20001
+
+/* SFECSTATUS */
+#define	R367TER_SFECSTATUS	0xf2c3
+#define	F367TER_SFEC_ON	0xf2c30080
+#define	F367TER_SFSTATUS_6	0xf2c30040
+#define	F367TER_SFSTATUS_5	0xf2c30020
+#define	F367TER_SFSTATUS_4	0xf2c30010
+#define	F367TER_LOCKEDSFEC	0xf2c30008
+#define	F367TER_SFEC_DELOCK	0xf2c30004
+#define	F367TER_SFEC_DEMODSEL1	0xf2c30002
+#define	F367TER_SFEC_OVFON	0xf2c30001
+
+/* SFKDIV12 */
+#define	R367TER_SFKDIV12	0xf2c4
+#define	F367TER_SFECKDIV12_MAN	0xf2c40080
+#define	F367TER_SFEC_K_DIVIDER_12	0xf2c4007f
+
+/* SFKDIV23 */
+#define	R367TER_SFKDIV23	0xf2c5
+#define	F367TER_SFECKDIV23_MAN	0xf2c50080
+#define	F367TER_SFEC_K_DIVIDER_23	0xf2c5007f
+
+/* SFKDIV34 */
+#define	R367TER_SFKDIV34	0xf2c6
+#define	F367TER_SFECKDIV34_MAN	0xf2c60080
+#define	F367TER_SFEC_K_DIVIDER_34	0xf2c6007f
+
+/* SFKDIV56 */
+#define	R367TER_SFKDIV56	0xf2c7
+#define	F367TER_SFECKDIV56_MAN	0xf2c70080
+#define	F367TER_SFEC_K_DIVIDER_56	0xf2c7007f
+
+/* SFKDIV67 */
+#define	R367TER_SFKDIV67	0xf2c8
+#define	F367TER_SFECKDIV67_MAN	0xf2c80080
+#define	F367TER_SFEC_K_DIVIDER_67	0xf2c8007f
+
+/* SFKDIV78 */
+#define	R367TER_SFKDIV78	0xf2c9
+#define	F367TER_SFECKDIV78_MAN	0xf2c90080
+#define	F367TER_SFEC_K_DIVIDER_78	0xf2c9007f
+
+/* SFDILSTKM */
+#define	R367TER_SFDILSTKM	0xf2ca
+#define	F367TER_SFEC_PACKCPT	0xf2ca00e0
+#define	F367TER_SFEC_DILSTK_HI	0xf2ca001f
+
+/* SFDILSTKL */
+#define	R367TER_SFDILSTKL	0xf2cb
+#define	F367TER_SFEC_DILSTK_LO	0xf2cb00ff
+
+/* SFSTATUS */
+#define	R367TER_SFSTATUS	0xf2cc
+#define	F367TER_SFEC_LINEOK	0xf2cc0080
+#define	F367TER_SFEC_ERROR	0xf2cc0040
+#define	F367TER_SFEC_DATA7	0xf2cc0020
+#define	F367TER_SFEC_OVERFLOW	0xf2cc0010
+#define	F367TER_SFEC_DEMODSEL2	0xf2cc0008
+#define	F367TER_SFEC_NOSYNC	0xf2cc0004
+#define	F367TER_SFEC_UNREGULA	0xf2cc0002
+#define	F367TER_SFEC_READY	0xf2cc0001
+
+/* SFDLYH */
+#define	R367TER_SFDLYH	0xf2cd
+#define	F367TER_SFEC_TSTIMEVALID	0xf2cd0080
+#define	F367TER_SFEC_SPEEDUP	0xf2cd0040
+#define	F367TER_SFEC_STOP	0xf2cd0020
+#define	F367TER_SFEC_REGULATED	0xf2cd0010
+#define	F367TER_SFEC_REALSYMBOFFSET	0xf2cd000f
+
+/* SFDLYM */
+#define	R367TER_SFDLYM	0xf2ce
+#define	F367TER_SFEC_REALSYMBOFFSET_HI	0xf2ce00ff
+
+/* SFDLYL */
+#define	R367TER_SFDLYL	0xf2cf
+#define	F367TER_SFEC_REALSYMBOFFSET_LO	0xf2cf00ff
+
+/* SFDLYSETH */
+#define	R367TER_SFDLYSETH	0xf2d0
+#define	F367TER_SFEC_OFFSET	0xf2d000e0
+#define	F367TER_SFECDLYSETH_4	0xf2d00010
+#define	F367TER_RST_SFEC	0xf2d00008
+#define	F367TER_SFECDLYSETH_2	0xf2d00004
+#define	F367TER_SFEC_DISABLE	0xf2d00002
+#define	F367TER_SFEC_UNREGUL	0xf2d00001
+
+/* SFDLYSETM */
+#define	R367TER_SFDLYSETM	0xf2d1
+#define	F367TER_SFECDLYSETM_7	0xf2d10080
+#define	F367TER_SFEC_SYMBOFFSET_HI	0xf2d1007f
+
+/* SFDLYSETL */
+#define	R367TER_SFDLYSETL	0xf2d2
+#define	F367TER_SFEC_SYMBOFFSET_LO	0xf2d200ff
+
+/* SFOBSCFG */
+#define	R367TER_SFOBSCFG	0xf2d3
+#define	F367TER_SFEC_OBSCFG	0xf2d300ff
+
+/* SFOBSM */
+#define	R367TER_SFOBSM	0xf2d4
+#define	F367TER_SFEC_OBSDATA_HI	0xf2d400ff
+
+/* SFOBSL */
+#define	R367TER_SFOBSL	0xf2d5
+#define	F367TER_SFEC_OBSDATA_LO	0xf2d500ff
+
+/* SFECINFO */
+#define	R367TER_SFECINFO	0xf2d6
+#define	F367TER_SFECINFO_7	0xf2d60080
+#define	F367TER_SFEC_SYNCDLSB	0xf2d60070
+#define	F367TER_SFCE_S1cPHASE	0xf2d6000f
+
+/* SFERRCTRL */
+#define	R367TER_SFERRCTRL	0xf2d8
+#define	F367TER_SFEC_ERR_SOURCE	0xf2d800f0
+#define	F367TER_SFERRCTRL_3	0xf2d80008
+#define	F367TER_SFEC_NUM_EVENT	0xf2d80007
+
+/* SFERRCNTH */
+#define	R367TER_SFERRCNTH	0xf2d9
+#define	F367TER_SFERRC_OLDVALUE	0xf2d90080
+#define	F367TER_SFEC_ERR_CNT	0xf2d9007f
+
+/* SFERRCNTM */
+#define	R367TER_SFERRCNTM	0xf2da
+#define	F367TER_SFEC_ERR_CNT_HI	0xf2da00ff
+
+/* SFERRCNTL */
+#define	R367TER_SFERRCNTL	0xf2db
+#define	F367TER_SFEC_ERR_CNT_LO	0xf2db00ff
+
+/* SYMBRATEM */
+#define	R367TER_SYMBRATEM	0xf2e0
+#define	F367TER_DEFGEN_SYMBRATE_HI	0xf2e000ff
+
+/* SYMBRATEL */
+#define	R367TER_SYMBRATEL	0xf2e1
+#define	F367TER_DEFGEN_SYMBRATE_LO	0xf2e100ff
+
+/* SYMBSTATUS */
+#define	R367TER_SYMBSTATUS	0xf2e2
+#define	F367TER_SYMBDLINE2_OFF	0xf2e20080
+#define	F367TER_SDDL_REINIT1	0xf2e20040
+#define	F367TER_SDD_REINIT1	0xf2e20020
+#define	F367TER_TOKENID_ERROR	0xf2e20010
+#define	F367TER_SYMBRATE_OVERFLOW	0xf2e20008
+#define	F367TER_SYMBRATE_UNDERFLOW	0xf2e20004
+#define	F367TER_TOKENID_RSTEVENT	0xf2e20002
+#define	F367TER_TOKENID_RESET1	0xf2e20001
+
+/* SYMBCFG */
+#define	R367TER_SYMBCFG	0xf2e3
+#define	F367TER_SYMBCFG_7	0xf2e30080
+#define	F367TER_SYMBCFG_6	0xf2e30040
+#define	F367TER_SYMBCFG_5	0xf2e30020
+#define	F367TER_SYMBCFG_4	0xf2e30010
+#define	F367TER_SYMRATE_FSPEED	0xf2e3000c
+#define	F367TER_SYMRATE_SSPEED	0xf2e30003
+
+/* SYMBFIFOM */
+#define	R367TER_SYMBFIFOM	0xf2e4
+#define	F367TER_SYMBFIFOM_7	0xf2e40080
+#define	F367TER_SYMBFIFOM_6	0xf2e40040
+#define	F367TER_DEFGEN_SYMFIFO_HI	0xf2e4003f
+
+/* SYMBFIFOL */
+#define	R367TER_SYMBFIFOL	0xf2e5
+#define	F367TER_DEFGEN_SYMFIFO_LO	0xf2e500ff
+
+/* SYMBOFFSM */
+#define	R367TER_SYMBOFFSM	0xf2e6
+#define	F367TER_TOKENID_RESET2	0xf2e60080
+#define	F367TER_SDDL_REINIT2	0xf2e60040
+#define	F367TER_SDD_REINIT2	0xf2e60020
+#define	F367TER_SYMBOFFSM_4	0xf2e60010
+#define	F367TER_SYMBOFFSM_3	0xf2e60008
+#define	F367TER_DEFGEN_SYMBOFFSET_HI	0xf2e60007
+
+/* SYMBOFFSL */
+#define	R367TER_SYMBOFFSL	0xf2e7
+#define	F367TER_DEFGEN_SYMBOFFSET_LO	0xf2e700ff
+
+/* DEBUG_LT4 */
+#define	R367TER_DEBUG_LT4	0xf400
+#define	F367TER_F_DEBUG_LT4	0xf40000ff
+
+/* DEBUG_LT5 */
+#define	R367TER_DEBUG_LT5	0xf401
+#define	F367TER_F_DEBUG_LT5	0xf40100ff
+
+/* DEBUG_LT6 */
+#define	R367TER_DEBUG_LT6	0xf402
+#define	F367TER_F_DEBUG_LT6	0xf40200ff
+
+/* DEBUG_LT7 */
+#define	R367TER_DEBUG_LT7	0xf403
+#define	F367TER_F_DEBUG_LT7	0xf40300ff
+
+/* DEBUG_LT8 */
+#define	R367TER_DEBUG_LT8	0xf404
+#define	F367TER_F_DEBUG_LT8	0xf40400ff
+
+/* DEBUG_LT9 */
+#define	R367TER_DEBUG_LT9	0xf405
+#define	F367TER_F_DEBUG_LT9	0xf40500ff
+
+#define STV0367TER_NBREGS	445
+
+/* ID */
+#define	R367CAB_ID	0xf000
+#define	F367CAB_IDENTIFICATIONREGISTER	0xf00000ff
+
+/* I2CRPT */
+#define	R367CAB_I2CRPT	0xf001
+#define	F367CAB_I2CT_ON	0xf0010080
+#define	F367CAB_ENARPT_LEVEL	0xf0010070
+#define	F367CAB_SCLT_DELAY	0xf0010008
+#define	F367CAB_SCLT_NOD	0xf0010004
+#define	F367CAB_STOP_ENABLE	0xf0010002
+#define	F367CAB_SDAT_NOD	0xf0010001
+
+/* TOPCTRL */
+#define	R367CAB_TOPCTRL	0xf002
+#define	F367CAB_STDBY	0xf0020080
+#define	F367CAB_STDBY_CORE	0xf0020020
+#define	F367CAB_QAM_COFDM	0xf0020010
+#define	F367CAB_TS_DIS	0xf0020008
+#define	F367CAB_DIR_CLK_216	0xf0020004
+
+/* IOCFG0 */
+#define	R367CAB_IOCFG0	0xf003
+#define	F367CAB_OP0_SD	0xf0030080
+#define	F367CAB_OP0_VAL	0xf0030040
+#define	F367CAB_OP0_OD	0xf0030020
+#define	F367CAB_OP0_INV	0xf0030010
+#define	F367CAB_OP0_DACVALUE_HI	0xf003000f
+
+/* DAc0R */
+#define	R367CAB_DAC0R	0xf004
+#define	F367CAB_OP0_DACVALUE_LO	0xf00400ff
+
+/* IOCFG1 */
+#define	R367CAB_IOCFG1	0xf005
+#define	F367CAB_IP0	0xf0050040
+#define	F367CAB_OP1_OD	0xf0050020
+#define	F367CAB_OP1_INV	0xf0050010
+#define	F367CAB_OP1_DACVALUE_HI	0xf005000f
+
+/* DAC1R */
+#define	R367CAB_DAC1R	0xf006
+#define	F367CAB_OP1_DACVALUE_LO	0xf00600ff
+
+/* IOCFG2 */
+#define	R367CAB_IOCFG2	0xf007
+#define	F367CAB_OP2_LOCK_CONF	0xf00700e0
+#define	F367CAB_OP2_OD	0xf0070010
+#define	F367CAB_OP2_VAL	0xf0070008
+#define	F367CAB_OP1_LOCK_CONF	0xf0070007
+
+/* SDFR */
+#define	R367CAB_SDFR	0xf008
+#define	F367CAB_OP0_FREQ	0xf00800f0
+#define	F367CAB_OP1_FREQ	0xf008000f
+
+/* AUX_CLK */
+#define	R367CAB_AUX_CLK	0xf00a
+#define	F367CAB_AUXFEC_CTL	0xf00a00c0
+#define	F367CAB_DIS_CKX4	0xf00a0020
+#define	F367CAB_CKSEL	0xf00a0018
+#define	F367CAB_CKDIV_PROG	0xf00a0006
+#define	F367CAB_AUXCLK_ENA	0xf00a0001
+
+/* FREESYS1 */
+#define	R367CAB_FREESYS1	0xf00b
+#define	F367CAB_FREESYS_1	0xf00b00ff
+
+/* FREESYS2 */
+#define	R367CAB_FREESYS2	0xf00c
+#define	F367CAB_FREESYS_2	0xf00c00ff
+
+/* FREESYS3 */
+#define	R367CAB_FREESYS3	0xf00d
+#define	F367CAB_FREESYS_3	0xf00d00ff
+
+/* GPIO_CFG */
+#define	R367CAB_GPIO_CFG	0xf00e
+#define	F367CAB_GPIO7_OD	0xf00e0080
+#define	F367CAB_GPIO7_CFG	0xf00e0040
+#define	F367CAB_GPIO6_OD	0xf00e0020
+#define	F367CAB_GPIO6_CFG	0xf00e0010
+#define	F367CAB_GPIO5_OD	0xf00e0008
+#define	F367CAB_GPIO5_CFG	0xf00e0004
+#define	F367CAB_GPIO4_OD	0xf00e0002
+#define	F367CAB_GPIO4_CFG	0xf00e0001
+
+/* GPIO_CMD */
+#define	R367CAB_GPIO_CMD	0xf00f
+#define	F367CAB_GPIO7_VAL	0xf00f0008
+#define	F367CAB_GPIO6_VAL	0xf00f0004
+#define	F367CAB_GPIO5_VAL	0xf00f0002
+#define	F367CAB_GPIO4_VAL	0xf00f0001
+
+/* TSTRES */
+#define	R367CAB_TSTRES	0xf0c0
+#define	F367CAB_FRES_DISPLAY	0xf0c00080
+#define	F367CAB_FRES_FIFO_AD	0xf0c00020
+#define	F367CAB_FRESRS	0xf0c00010
+#define	F367CAB_FRESACS	0xf0c00008
+#define	F367CAB_FRESFEC	0xf0c00004
+#define	F367CAB_FRES_PRIF	0xf0c00002
+#define	F367CAB_FRESCORE	0xf0c00001
+
+/* ANACTRL */
+#define	R367CAB_ANACTRL	0xf0c1
+#define	F367CAB_BYPASS_XTAL	0xf0c10040
+#define	F367CAB_BYPASS_PLLXN	0xf0c1000c
+#define	F367CAB_DIS_PAD_OSC	0xf0c10002
+#define	F367CAB_STDBY_PLLXN	0xf0c10001
+
+/* TSTBUS */
+#define	R367CAB_TSTBUS	0xf0c2
+#define	F367CAB_TS_BYTE_CLK_INV	0xf0c20080
+#define	F367CAB_CFG_IP	0xf0c20070
+#define	F367CAB_CFG_TST	0xf0c2000f
+
+/* RF_AGC1 */
+#define	R367CAB_RF_AGC1	0xf0d4
+#define	F367CAB_RF_AGC1_LEVEL_HI	0xf0d400ff
+
+/* RF_AGC2 */
+#define	R367CAB_RF_AGC2	0xf0d5
+#define	F367CAB_REF_ADGP	0xf0d50080
+#define	F367CAB_STDBY_ADCGP	0xf0d50020
+#define	F367CAB_RF_AGC1_LEVEL_LO	0xf0d50003
+
+/* ANADIGCTRL */
+#define	R367CAB_ANADIGCTRL	0xf0d7
+#define	F367CAB_SEL_CLKDEM	0xf0d70020
+#define	F367CAB_EN_BUFFER_Q	0xf0d70010
+#define	F367CAB_EN_BUFFER_I	0xf0d70008
+#define	F367CAB_ADC_RIS_EGDE	0xf0d70004
+#define	F367CAB_SGN_ADC	0xf0d70002
+#define	F367CAB_SEL_AD12_SYNC	0xf0d70001
+
+/* PLLMDIV */
+#define	R367CAB_PLLMDIV	0xf0d8
+#define	F367CAB_PLL_MDIV	0xf0d800ff
+
+/* PLLNDIV */
+#define	R367CAB_PLLNDIV	0xf0d9
+#define	F367CAB_PLL_NDIV	0xf0d900ff
+
+/* PLLSETUP */
+#define	R367CAB_PLLSETUP	0xf0da
+#define	F367CAB_PLL_PDIV	0xf0da0070
+#define	F367CAB_PLL_KDIV	0xf0da000f
+
+/* DUAL_AD12 */
+#define	R367CAB_DUAL_AD12	0xf0db
+#define	F367CAB_FS20M	0xf0db0020
+#define	F367CAB_FS50M	0xf0db0010
+#define	F367CAB_INMODe0	0xf0db0008
+#define	F367CAB_POFFQ	0xf0db0004
+#define	F367CAB_POFFI	0xf0db0002
+#define	F367CAB_INMODE1	0xf0db0001
+
+/* TSTBIST */
+#define	R367CAB_TSTBIST	0xf0dc
+#define	F367CAB_TST_BYP_CLK	0xf0dc0080
+#define	F367CAB_TST_GCLKENA_STD	0xf0dc0040
+#define	F367CAB_TST_GCLKENA	0xf0dc0020
+#define	F367CAB_TST_MEMBIST	0xf0dc001f
+
+/* CTRL_1 */
+#define	R367CAB_CTRL_1	0xf402
+#define	F367CAB_SOFT_RST	0xf4020080
+#define	F367CAB_EQU_RST	0xf4020008
+#define	F367CAB_CRL_RST	0xf4020004
+#define	F367CAB_TRL_RST	0xf4020002
+#define	F367CAB_AGC_RST	0xf4020001
+
+/* CTRL_2 */
+#define	R367CAB_CTRL_2	0xf403
+#define	F367CAB_DEINT_RST	0xf4030008
+#define	F367CAB_RS_RST	0xf4030004
+
+/* IT_STATUS1 */
+#define	R367CAB_IT_STATUS1	0xf408
+#define	F367CAB_SWEEP_OUT	0xf4080080
+#define	F367CAB_FSM_CRL	0xf4080040
+#define	F367CAB_CRL_LOCK	0xf4080020
+#define	F367CAB_MFSM	0xf4080010
+#define	F367CAB_TRL_LOCK	0xf4080008
+#define	F367CAB_TRL_AGC_LIMIT	0xf4080004
+#define	F367CAB_ADJ_AGC_LOCK	0xf4080002
+#define	F367CAB_AGC_QAM_LOCK	0xf4080001
+
+/* IT_STATUS2 */
+#define	R367CAB_IT_STATUS2	0xf409
+#define	F367CAB_TSMF_CNT	0xf4090080
+#define	F367CAB_TSMF_EOF	0xf4090040
+#define	F367CAB_TSMF_RDY	0xf4090020
+#define	F367CAB_FEC_NOCORR	0xf4090010
+#define	F367CAB_SYNCSTATE	0xf4090008
+#define	F367CAB_DEINT_LOCK	0xf4090004
+#define	F367CAB_FADDING_FRZ	0xf4090002
+#define	F367CAB_TAPMON_ALARM	0xf4090001
+
+/* IT_EN1 */
+#define	R367CAB_IT_EN1	0xf40a
+#define	F367CAB_SWEEP_OUTE	0xf40a0080
+#define	F367CAB_FSM_CRLE	0xf40a0040
+#define	F367CAB_CRL_LOCKE	0xf40a0020
+#define	F367CAB_MFSME	0xf40a0010
+#define	F367CAB_TRL_LOCKE	0xf40a0008
+#define	F367CAB_TRL_AGC_LIMITE	0xf40a0004
+#define	F367CAB_ADJ_AGC_LOCKE	0xf40a0002
+#define	F367CAB_AGC_LOCKE	0xf40a0001
+
+/* IT_EN2 */
+#define	R367CAB_IT_EN2	0xf40b
+#define	F367CAB_TSMF_CNTE	0xf40b0080
+#define	F367CAB_TSMF_EOFE	0xf40b0040
+#define	F367CAB_TSMF_RDYE	0xf40b0020
+#define	F367CAB_FEC_NOCORRE	0xf40b0010
+#define	F367CAB_SYNCSTATEE	0xf40b0008
+#define	F367CAB_DEINT_LOCKE	0xf40b0004
+#define	F367CAB_FADDING_FRZE	0xf40b0002
+#define	F367CAB_TAPMON_ALARME	0xf40b0001
+
+/* CTRL_STATUS */
+#define	R367CAB_CTRL_STATUS	0xf40c
+#define	F367CAB_QAMFEC_LOCK	0xf40c0004
+#define	F367CAB_TSMF_LOCK	0xf40c0002
+#define	F367CAB_TSMF_ERROR	0xf40c0001
+
+/* TEST_CTL */
+#define	R367CAB_TEST_CTL	0xf40f
+#define	F367CAB_TST_BLK_SEL	0xf40f0060
+#define	F367CAB_TST_BUS_SEL	0xf40f001f
+
+/* AGC_CTL */
+#define	R367CAB_AGC_CTL	0xf410
+#define	F367CAB_AGC_LCK_TH	0xf41000f0
+#define	F367CAB_AGC_ACCUMRSTSEL	0xf4100007
+
+/* AGC_IF_CFG */
+#define	R367CAB_AGC_IF_CFG	0xf411
+#define	F367CAB_AGC_IF_BWSEL	0xf41100f0
+#define	F367CAB_AGC_IF_FREEZE	0xf4110002
+
+/* AGC_RF_CFG */
+#define	R367CAB_AGC_RF_CFG	0xf412
+#define	F367CAB_AGC_RF_BWSEL	0xf4120070
+#define	F367CAB_AGC_RF_FREEZE	0xf4120002
+
+/* AGC_PWM_CFG */
+#define	R367CAB_AGC_PWM_CFG	0xf413
+#define	F367CAB_AGC_RF_PWM_TST	0xf4130080
+#define	F367CAB_AGC_RF_PWM_INV	0xf4130040
+#define	F367CAB_AGC_IF_PWM_TST	0xf4130008
+#define	F367CAB_AGC_IF_PWM_INV	0xf4130004
+#define	F367CAB_AGC_PWM_CLKDIV	0xf4130003
+
+/* AGC_PWR_REF_L */
+#define	R367CAB_AGC_PWR_REF_L	0xf414
+#define	F367CAB_AGC_PWRREF_LO	0xf41400ff
+
+/* AGC_PWR_REF_H */
+#define	R367CAB_AGC_PWR_REF_H	0xf415
+#define	F367CAB_AGC_PWRREF_HI	0xf4150003
+
+/* AGC_RF_TH_L */
+#define	R367CAB_AGC_RF_TH_L	0xf416
+#define	F367CAB_AGC_RF_TH_LO	0xf41600ff
+
+/* AGC_RF_TH_H */
+#define	R367CAB_AGC_RF_TH_H	0xf417
+#define	F367CAB_AGC_RF_TH_HI	0xf417000f
+
+/* AGC_IF_LTH_L */
+#define	R367CAB_AGC_IF_LTH_L	0xf418
+#define	F367CAB_AGC_IF_THLO_LO	0xf41800ff
+
+/* AGC_IF_LTH_H */
+#define	R367CAB_AGC_IF_LTH_H	0xf419
+#define	F367CAB_AGC_IF_THLO_HI	0xf419000f
+
+/* AGC_IF_HTH_L */
+#define	R367CAB_AGC_IF_HTH_L	0xf41a
+#define	F367CAB_AGC_IF_THHI_LO	0xf41a00ff
+
+/* AGC_IF_HTH_H */
+#define	R367CAB_AGC_IF_HTH_H	0xf41b
+#define	F367CAB_AGC_IF_THHI_HI	0xf41b000f
+
+/* AGC_PWR_RD_L */
+#define	R367CAB_AGC_PWR_RD_L	0xf41c
+#define	F367CAB_AGC_PWR_WORD_LO	0xf41c00ff
+
+/* AGC_PWR_RD_M */
+#define	R367CAB_AGC_PWR_RD_M	0xf41d
+#define	F367CAB_AGC_PWR_WORD_ME	0xf41d00ff
+
+/* AGC_PWR_RD_H */
+#define	R367CAB_AGC_PWR_RD_H	0xf41e
+#define	F367CAB_AGC_PWR_WORD_HI	0xf41e0003
+
+/* AGC_PWM_IFCMD_L */
+#define	R367CAB_AGC_PWM_IFCMD_L	0xf420
+#define	F367CAB_AGC_IF_PWMCMD_LO	0xf42000ff
+
+/* AGC_PWM_IFCMD_H */
+#define	R367CAB_AGC_PWM_IFCMD_H	0xf421
+#define	F367CAB_AGC_IF_PWMCMD_HI	0xf421000f
+
+/* AGC_PWM_RFCMD_L */
+#define	R367CAB_AGC_PWM_RFCMD_L	0xf422
+#define	F367CAB_AGC_RF_PWMCMD_LO	0xf42200ff
+
+/* AGC_PWM_RFCMD_H */
+#define	R367CAB_AGC_PWM_RFCMD_H	0xf423
+#define	F367CAB_AGC_RF_PWMCMD_HI	0xf423000f
+
+/* IQDEM_CFG */
+#define	R367CAB_IQDEM_CFG	0xf424
+#define	F367CAB_IQDEM_CLK_SEL	0xf4240004
+#define	F367CAB_IQDEM_INVIQ	0xf4240002
+#define	F367CAB_IQDEM_A2dTYPE	0xf4240001
+
+/* MIX_NCO_LL */
+#define	R367CAB_MIX_NCO_LL	0xf425
+#define	F367CAB_MIX_NCO_INC_LL	0xf42500ff
+
+/* MIX_NCO_HL */
+#define	R367CAB_MIX_NCO_HL	0xf426
+#define	F367CAB_MIX_NCO_INC_HL	0xf42600ff
+
+/* MIX_NCO_HH */
+#define	R367CAB_MIX_NCO_HH	0xf427
+#define	F367CAB_MIX_NCO_INVCNST	0xf4270080
+#define	F367CAB_MIX_NCO_INC_HH	0xf427007f
+
+/* SRC_NCO_LL */
+#define	R367CAB_SRC_NCO_LL	0xf428
+#define	F367CAB_SRC_NCO_INC_LL	0xf42800ff
+
+/* SRC_NCO_LH */
+#define	R367CAB_SRC_NCO_LH	0xf429
+#define	F367CAB_SRC_NCO_INC_LH	0xf42900ff
+
+/* SRC_NCO_HL */
+#define	R367CAB_SRC_NCO_HL	0xf42a
+#define	F367CAB_SRC_NCO_INC_HL	0xf42a00ff
+
+/* SRC_NCO_HH */
+#define	R367CAB_SRC_NCO_HH	0xf42b
+#define	F367CAB_SRC_NCO_INC_HH	0xf42b007f
+
+/* IQDEM_GAIN_SRC_L */
+#define	R367CAB_IQDEM_GAIN_SRC_L	0xf42c
+#define	F367CAB_GAIN_SRC_LO	0xf42c00ff
+
+/* IQDEM_GAIN_SRC_H */
+#define	R367CAB_IQDEM_GAIN_SRC_H	0xf42d
+#define	F367CAB_GAIN_SRC_HI	0xf42d0003
+
+/* IQDEM_DCRM_CFG_LL */
+#define	R367CAB_IQDEM_DCRM_CFG_LL	0xf430
+#define	F367CAB_DCRM0_DCIN_L	0xf43000ff
+
+/* IQDEM_DCRM_CFG_LH */
+#define	R367CAB_IQDEM_DCRM_CFG_LH	0xf431
+#define	F367CAB_DCRM1_I_DCIN_L	0xf43100fc
+#define	F367CAB_DCRM0_DCIN_H	0xf4310003
+
+/* IQDEM_DCRM_CFG_HL */
+#define	R367CAB_IQDEM_DCRM_CFG_HL	0xf432
+#define	F367CAB_DCRM1_Q_DCIN_L	0xf43200f0
+#define	F367CAB_DCRM1_I_DCIN_H	0xf432000f
+
+/* IQDEM_DCRM_CFG_HH */
+#define	R367CAB_IQDEM_DCRM_CFG_HH	0xf433
+#define	F367CAB_DCRM1_FRZ	0xf4330080
+#define	F367CAB_DCRM0_FRZ	0xf4330040
+#define	F367CAB_DCRM1_Q_DCIN_H	0xf433003f
+
+/* IQDEM_ADJ_COEFf0 */
+#define	R367CAB_IQDEM_ADJ_COEFF0	0xf434
+#define	F367CAB_ADJIIR_COEFF10_L	0xf43400ff
+
+/* IQDEM_ADJ_COEFF1 */
+#define	R367CAB_IQDEM_ADJ_COEFF1	0xf435
+#define	F367CAB_ADJIIR_COEFF11_L	0xf43500fc
+#define	F367CAB_ADJIIR_COEFF10_H	0xf4350003
+
+/* IQDEM_ADJ_COEFF2 */
+#define	R367CAB_IQDEM_ADJ_COEFF2	0xf436
+#define	F367CAB_ADJIIR_COEFF12_L	0xf43600f0
+#define	F367CAB_ADJIIR_COEFF11_H	0xf436000f
+
+/* IQDEM_ADJ_COEFF3 */
+#define	R367CAB_IQDEM_ADJ_COEFF3	0xf437
+#define	F367CAB_ADJIIR_COEFF20_L	0xf43700c0
+#define	F367CAB_ADJIIR_COEFF12_H	0xf437003f
+
+/* IQDEM_ADJ_COEFF4 */
+#define	R367CAB_IQDEM_ADJ_COEFF4	0xf438
+#define	F367CAB_ADJIIR_COEFF20_H	0xf43800ff
+
+/* IQDEM_ADJ_COEFF5 */
+#define	R367CAB_IQDEM_ADJ_COEFF5	0xf439
+#define	F367CAB_ADJIIR_COEFF21_L	0xf43900ff
+
+/* IQDEM_ADJ_COEFF6 */
+#define	R367CAB_IQDEM_ADJ_COEFF6	0xf43a
+#define	F367CAB_ADJIIR_COEFF22_L	0xf43a00fc
+#define	F367CAB_ADJIIR_COEFF21_H	0xf43a0003
+
+/* IQDEM_ADJ_COEFF7 */
+#define	R367CAB_IQDEM_ADJ_COEFF7	0xf43b
+#define	F367CAB_ADJIIR_COEFF22_H	0xf43b000f
+
+/* IQDEM_ADJ_EN */
+#define	R367CAB_IQDEM_ADJ_EN	0xf43c
+#define	F367CAB_ALLPASSFILT_EN	0xf43c0008
+#define	F367CAB_ADJ_AGC_EN	0xf43c0004
+#define	F367CAB_ADJ_COEFF_FRZ	0xf43c0002
+#define	F367CAB_ADJ_EN	0xf43c0001
+
+/* IQDEM_ADJ_AGC_REF */
+#define	R367CAB_IQDEM_ADJ_AGC_REF	0xf43d
+#define	F367CAB_ADJ_AGC_REF	0xf43d00ff
+
+/* ALLPASSFILT1 */
+#define	R367CAB_ALLPASSFILT1	0xf440
+#define	F367CAB_ALLPASSFILT_COEFF1_LO	0xf44000ff
+
+/* ALLPASSFILT2 */
+#define	R367CAB_ALLPASSFILT2	0xf441
+#define	F367CAB_ALLPASSFILT_COEFF1_ME	0xf44100ff
+
+/* ALLPASSFILT3 */
+#define	R367CAB_ALLPASSFILT3	0xf442
+#define	F367CAB_ALLPASSFILT_COEFF2_LO	0xf44200c0
+#define	F367CAB_ALLPASSFILT_COEFF1_HI	0xf442003f
+
+/* ALLPASSFILT4 */
+#define	R367CAB_ALLPASSFILT4	0xf443
+#define	F367CAB_ALLPASSFILT_COEFF2_MEL	0xf44300ff
+
+/* ALLPASSFILT5 */
+#define	R367CAB_ALLPASSFILT5	0xf444
+#define	F367CAB_ALLPASSFILT_COEFF2_MEH	0xf44400ff
+
+/* ALLPASSFILT6 */
+#define	R367CAB_ALLPASSFILT6	0xf445
+#define	F367CAB_ALLPASSFILT_COEFF3_LO	0xf44500f0
+#define	F367CAB_ALLPASSFILT_COEFF2_HI	0xf445000f
+
+/* ALLPASSFILT7 */
+#define	R367CAB_ALLPASSFILT7	0xf446
+#define	F367CAB_ALLPASSFILT_COEFF3_MEL	0xf44600ff
+
+/* ALLPASSFILT8 */
+#define	R367CAB_ALLPASSFILT8	0xf447
+#define	F367CAB_ALLPASSFILT_COEFF3_MEH	0xf44700ff
+
+/* ALLPASSFILT9 */
+#define	R367CAB_ALLPASSFILT9	0xf448
+#define	F367CAB_ALLPASSFILT_COEFF4_LO	0xf44800fc
+#define	F367CAB_ALLPASSFILT_COEFF3_HI	0xf4480003
+
+/* ALLPASSFILT10 */
+#define	R367CAB_ALLPASSFILT10	0xf449
+#define	F367CAB_ALLPASSFILT_COEFF4_ME	0xf44900ff
+
+/* ALLPASSFILT11 */
+#define	R367CAB_ALLPASSFILT11	0xf44a
+#define	F367CAB_ALLPASSFILT_COEFF4_HI	0xf44a00ff
+
+/* TRL_AGC_CFG */
+#define	R367CAB_TRL_AGC_CFG	0xf450
+#define	F367CAB_TRL_AGC_FREEZE	0xf4500080
+#define	F367CAB_TRL_AGC_REF	0xf450007f
+
+/* TRL_LPF_CFG */
+#define	R367CAB_TRL_LPF_CFG	0xf454
+#define	F367CAB_NYQPOINT_INV	0xf4540040
+#define	F367CAB_TRL_SHIFT	0xf4540030
+#define	F367CAB_NYQ_COEFF_SEL	0xf454000c
+#define	F367CAB_TRL_LPF_FREEZE	0xf4540002
+#define	F367CAB_TRL_LPF_CRT	0xf4540001
+
+/* TRL_LPF_ACQ_GAIN */
+#define	R367CAB_TRL_LPF_ACQ_GAIN	0xf455
+#define	F367CAB_TRL_GDIR_ACQ	0xf4550070
+#define	F367CAB_TRL_GINT_ACQ	0xf4550007
+
+/* TRL_LPF_TRK_GAIN */
+#define	R367CAB_TRL_LPF_TRK_GAIN	0xf456
+#define	F367CAB_TRL_GDIR_TRK	0xf4560070
+#define	F367CAB_TRL_GINT_TRK	0xf4560007
+
+/* TRL_LPF_OUT_GAIN */
+#define	R367CAB_TRL_LPF_OUT_GAIN	0xf457
+#define	F367CAB_TRL_GAIN_OUT	0xf4570007
+
+/* TRL_LOCKDET_LTH */
+#define	R367CAB_TRL_LOCKDET_LTH	0xf458
+#define	F367CAB_TRL_LCK_THLO	0xf4580007
+
+/* TRL_LOCKDET_HTH */
+#define	R367CAB_TRL_LOCKDET_HTH	0xf459
+#define	F367CAB_TRL_LCK_THHI	0xf45900ff
+
+/* TRL_LOCKDET_TRGVAL */
+#define	R367CAB_TRL_LOCKDET_TRGVAL	0xf45a
+#define	F367CAB_TRL_LCK_TRG	0xf45a00ff
+
+/* IQ_QAM */
+#define	R367CAB_IQ_QAM	0xf45c
+#define	F367CAB_IQ_INPUT	0xf45c0008
+#define	F367CAB_DETECT_MODE	0xf45c0007
+
+/* FSM_STATE */
+#define	R367CAB_FSM_STATE	0xf460
+#define	F367CAB_CRL_DFE	0xf4600080
+#define	F367CAB_DFE_START	0xf4600040
+#define	F367CAB_CTRLG_START	0xf4600030
+#define	F367CAB_FSM_FORCESTATE	0xf460000f
+
+/* FSM_CTL */
+#define	R367CAB_FSM_CTL	0xf461
+#define	F367CAB_FEC2_EN	0xf4610040
+#define	F367CAB_SIT_EN	0xf4610020
+#define	F367CAB_TRL_AHEAD	0xf4610010
+#define	F367CAB_TRL2_EN	0xf4610008
+#define	F367CAB_FSM_EQA1_EN	0xf4610004
+#define	F367CAB_FSM_BKP_DIS	0xf4610002
+#define	F367CAB_FSM_FORCE_EN	0xf4610001
+
+/* FSM_STS */
+#define	R367CAB_FSM_STS	0xf462
+#define	F367CAB_FSM_STATUS	0xf462000f
+
+/* FSM_SNR0_HTH */
+#define	R367CAB_FSM_SNR0_HTH	0xf463
+#define	F367CAB_SNR0_HTH	0xf46300ff
+
+/* FSM_SNR1_HTH */
+#define	R367CAB_FSM_SNR1_HTH	0xf464
+#define	F367CAB_SNR1_HTH	0xf46400ff
+
+/* FSM_SNR2_HTH */
+#define	R367CAB_FSM_SNR2_HTH	0xf465
+#define	F367CAB_SNR2_HTH	0xf46500ff
+
+/* FSM_SNR0_LTH */
+#define	R367CAB_FSM_SNR0_LTH	0xf466
+#define	F367CAB_SNR0_LTH	0xf46600ff
+
+/* FSM_SNR1_LTH */
+#define	R367CAB_FSM_SNR1_LTH	0xf467
+#define	F367CAB_SNR1_LTH	0xf46700ff
+
+/* FSM_EQA1_HTH */
+#define	R367CAB_FSM_EQA1_HTH	0xf468
+#define	F367CAB_SNR3_HTH_LO	0xf46800f0
+#define	F367CAB_EQA1_HTH	0xf468000f
+
+/* FSM_TEMPO */
+#define	R367CAB_FSM_TEMPO	0xf469
+#define	F367CAB_SIT	0xf46900c0
+#define	F367CAB_WST	0xf4690038
+#define	F367CAB_ELT	0xf4690006
+#define	F367CAB_SNR3_HTH_HI	0xf4690001
+
+/* FSM_CONFIG */
+#define	R367CAB_FSM_CONFIG	0xf46a
+#define	F367CAB_FEC2_DFEOFF	0xf46a0004
+#define	F367CAB_PRIT_STATE	0xf46a0002
+#define	F367CAB_MODMAP_STATE	0xf46a0001
+
+/* EQU_I_TESTTAP_L */
+#define	R367CAB_EQU_I_TESTTAP_L	0xf474
+#define	F367CAB_I_TEST_TAP_L	0xf47400ff
+
+/* EQU_I_TESTTAP_M */
+#define	R367CAB_EQU_I_TESTTAP_M	0xf475
+#define	F367CAB_I_TEST_TAP_M	0xf47500ff
+
+/* EQU_I_TESTTAP_H */
+#define	R367CAB_EQU_I_TESTTAP_H	0xf476
+#define	F367CAB_I_TEST_TAP_H	0xf476001f
+
+/* EQU_TESTAP_CFG */
+#define	R367CAB_EQU_TESTAP_CFG	0xf477
+#define	F367CAB_TEST_FFE_DFE_SEL	0xf4770040
+#define	F367CAB_TEST_TAP_SELECT	0xf477003f
+
+/* EQU_Q_TESTTAP_L */
+#define	R367CAB_EQU_Q_TESTTAP_L	0xf478
+#define	F367CAB_Q_TEST_TAP_L	0xf47800ff
+
+/* EQU_Q_TESTTAP_M */
+#define	R367CAB_EQU_Q_TESTTAP_M	0xf479
+#define	F367CAB_Q_TEST_TAP_M	0xf47900ff
+
+/* EQU_Q_TESTTAP_H */
+#define	R367CAB_EQU_Q_TESTTAP_H	0xf47a
+#define	F367CAB_Q_TEST_TAP_H	0xf47a001f
+
+/* EQU_TAP_CTRL */
+#define	R367CAB_EQU_TAP_CTRL	0xf47b
+#define	F367CAB_MTAP_FRZ	0xf47b0010
+#define	F367CAB_PRE_FREEZE	0xf47b0008
+#define	F367CAB_DFE_TAPMON_EN	0xf47b0004
+#define	F367CAB_FFE_TAPMON_EN	0xf47b0002
+#define	F367CAB_MTAP_ONLY	0xf47b0001
+
+/* EQU_CTR_CRL_CONTROL_L */
+#define	R367CAB_EQU_CTR_CRL_CONTROL_L	0xf47c
+#define	F367CAB_EQU_CTR_CRL_CONTROL_LO	0xf47c00ff
+
+/* EQU_CTR_CRL_CONTROL_H */
+#define	R367CAB_EQU_CTR_CRL_CONTROL_H	0xf47d
+#define	F367CAB_EQU_CTR_CRL_CONTROL_HI	0xf47d00ff
+
+/* EQU_CTR_HIPOW_L */
+#define	R367CAB_EQU_CTR_HIPOW_L	0xf47e
+#define	F367CAB_CTR_HIPOW_L	0xf47e00ff
+
+/* EQU_CTR_HIPOW_H */
+#define	R367CAB_EQU_CTR_HIPOW_H	0xf47f
+#define	F367CAB_CTR_HIPOW_H	0xf47f00ff
+
+/* EQU_I_EQU_LO */
+#define	R367CAB_EQU_I_EQU_LO	0xf480
+#define	F367CAB_EQU_I_EQU_L	0xf48000ff
+
+/* EQU_I_EQU_HI */
+#define	R367CAB_EQU_I_EQU_HI	0xf481
+#define	F367CAB_EQU_I_EQU_H	0xf4810003
+
+/* EQU_Q_EQU_LO */
+#define	R367CAB_EQU_Q_EQU_LO	0xf482
+#define	F367CAB_EQU_Q_EQU_L	0xf48200ff
+
+/* EQU_Q_EQU_HI */
+#define	R367CAB_EQU_Q_EQU_HI	0xf483
+#define	F367CAB_EQU_Q_EQU_H	0xf4830003
+
+/* EQU_MAPPER */
+#define	R367CAB_EQU_MAPPER	0xf484
+#define	F367CAB_QUAD_AUTO	0xf4840080
+#define	F367CAB_QUAD_INV	0xf4840040
+#define	F367CAB_QAM_MODE	0xf4840007
+
+/* EQU_SWEEP_RATE */
+#define	R367CAB_EQU_SWEEP_RATE	0xf485
+#define	F367CAB_SNR_PER	0xf48500c0
+#define	F367CAB_SWEEP_RATE	0xf485003f
+
+/* EQU_SNR_LO */
+#define	R367CAB_EQU_SNR_LO	0xf486
+#define	F367CAB_SNR_LO	0xf48600ff
+
+/* EQU_SNR_HI */
+#define	R367CAB_EQU_SNR_HI	0xf487
+#define	F367CAB_SNR_HI	0xf48700ff
+
+/* EQU_GAMMA_LO */
+#define	R367CAB_EQU_GAMMA_LO	0xf488
+#define	F367CAB_GAMMA_LO	0xf48800ff
+
+/* EQU_GAMMA_HI */
+#define	R367CAB_EQU_GAMMA_HI	0xf489
+#define	F367CAB_GAMMA_ME	0xf48900ff
+
+/* EQU_ERR_GAIN */
+#define	R367CAB_EQU_ERR_GAIN	0xf48a
+#define	F367CAB_EQA1MU	0xf48a0070
+#define	F367CAB_CRL2MU	0xf48a000e
+#define	F367CAB_GAMMA_HI	0xf48a0001
+
+/* EQU_RADIUS */
+#define	R367CAB_EQU_RADIUS	0xf48b
+#define	F367CAB_RADIUS	0xf48b00ff
+
+/* EQU_FFE_MAINTAP */
+#define	R367CAB_EQU_FFE_MAINTAP	0xf48c
+#define	F367CAB_FFE_MAINTAP_INIT	0xf48c00ff
+
+/* EQU_FFE_LEAKAGE */
+#define	R367CAB_EQU_FFE_LEAKAGE	0xf48e
+#define	F367CAB_LEAK_PER	0xf48e00f0
+#define	F367CAB_EQU_OUTSEL	0xf48e0002
+#define	F367CAB_PNT2dFE	0xf48e0001
+
+/* EQU_FFE_MAINTAP_POS */
+#define	R367CAB_EQU_FFE_MAINTAP_POS	0xf48f
+#define	F367CAB_FFE_LEAK_EN	0xf48f0080
+#define	F367CAB_DFE_LEAK_EN	0xf48f0040
+#define	F367CAB_FFE_MAINTAP_POS	0xf48f003f
+
+/* EQU_GAIN_WIDE */
+#define	R367CAB_EQU_GAIN_WIDE	0xf490
+#define	F367CAB_DFE_GAIN_WIDE	0xf49000f0
+#define	F367CAB_FFE_GAIN_WIDE	0xf490000f
+
+/* EQU_GAIN_NARROW */
+#define	R367CAB_EQU_GAIN_NARROW	0xf491
+#define	F367CAB_DFE_GAIN_NARROW	0xf49100f0
+#define	F367CAB_FFE_GAIN_NARROW	0xf491000f
+
+/* EQU_CTR_LPF_GAIN */
+#define	R367CAB_EQU_CTR_LPF_GAIN	0xf492
+#define	F367CAB_CTR_GTO	0xf4920080
+#define	F367CAB_CTR_GDIR	0xf4920070
+#define	F367CAB_SWEEP_EN	0xf4920008
+#define	F367CAB_CTR_GINT	0xf4920007
+
+/* EQU_CRL_LPF_GAIN */
+#define	R367CAB_EQU_CRL_LPF_GAIN	0xf493
+#define	F367CAB_CRL_GTO	0xf4930080
+#define	F367CAB_CRL_GDIR	0xf4930070
+#define	F367CAB_SWEEP_DIR	0xf4930008
+#define	F367CAB_CRL_GINT	0xf4930007
+
+/* EQU_GLOBAL_GAIN */
+#define	R367CAB_EQU_GLOBAL_GAIN	0xf494
+#define	F367CAB_CRL_GAIN	0xf49400f8
+#define	F367CAB_CTR_INC_GAIN	0xf4940004
+#define	F367CAB_CTR_FRAC	0xf4940003
+
+/* EQU_CRL_LD_SEN */
+#define	R367CAB_EQU_CRL_LD_SEN	0xf495
+#define	F367CAB_CTR_BADPOINT_EN	0xf4950080
+#define	F367CAB_CTR_GAIN	0xf4950070
+#define	F367CAB_LIMANEN	0xf4950008
+#define	F367CAB_CRL_LD_SEN	0xf4950007
+
+/* EQU_CRL_LD_VAL */
+#define	R367CAB_EQU_CRL_LD_VAL	0xf496
+#define	F367CAB_CRL_BISTH_LIMIT	0xf4960080
+#define	F367CAB_CARE_EN	0xf4960040
+#define	F367CAB_CRL_LD_PER	0xf4960030
+#define	F367CAB_CRL_LD_WST	0xf496000c
+#define	F367CAB_CRL_LD_TFS	0xf4960003
+
+/* EQU_CRL_TFR */
+#define	R367CAB_EQU_CRL_TFR	0xf497
+#define	F367CAB_CRL_LD_TFR	0xf49700ff
+
+/* EQU_CRL_BISTH_LO */
+#define	R367CAB_EQU_CRL_BISTH_LO	0xf498
+#define	F367CAB_CRL_BISTH_LO	0xf49800ff
+
+/* EQU_CRL_BISTH_HI */
+#define	R367CAB_EQU_CRL_BISTH_HI	0xf499
+#define	F367CAB_CRL_BISTH_HI	0xf49900ff
+
+/* EQU_SWEEP_RANGE_LO */
+#define	R367CAB_EQU_SWEEP_RANGE_LO	0xf49a
+#define	F367CAB_SWEEP_RANGE_LO	0xf49a00ff
+
+/* EQU_SWEEP_RANGE_HI */
+#define	R367CAB_EQU_SWEEP_RANGE_HI	0xf49b
+#define	F367CAB_SWEEP_RANGE_HI	0xf49b00ff
+
+/* EQU_CRL_LIMITER */
+#define	R367CAB_EQU_CRL_LIMITER	0xf49c
+#define	F367CAB_BISECTOR_EN	0xf49c0080
+#define	F367CAB_PHEST128_EN	0xf49c0040
+#define	F367CAB_CRL_LIM	0xf49c003f
+
+/* EQU_MODULUS_MAP */
+#define	R367CAB_EQU_MODULUS_MAP	0xf49d
+#define	F367CAB_PNT_DEPTH	0xf49d00e0
+#define	F367CAB_MODULUS_CMP	0xf49d001f
+
+/* EQU_PNT_GAIN */
+#define	R367CAB_EQU_PNT_GAIN	0xf49e
+#define	F367CAB_PNT_EN	0xf49e0080
+#define	F367CAB_MODULUSMAP_EN	0xf49e0040
+#define	F367CAB_PNT_GAIN	0xf49e003f
+
+/* FEC_AC_CTR_0 */
+#define	R367CAB_FEC_AC_CTR_0	0xf4a8
+#define	F367CAB_BE_BYPASS	0xf4a80020
+#define	F367CAB_REFRESH47	0xf4a80010
+#define	F367CAB_CT_NBST	0xf4a80008
+#define	F367CAB_TEI_ENA	0xf4a80004
+#define	F367CAB_DS_ENA	0xf4a80002
+#define	F367CAB_TSMF_EN	0xf4a80001
+
+/* FEC_AC_CTR_1 */
+#define	R367CAB_FEC_AC_CTR_1	0xf4a9
+#define	F367CAB_DEINT_DEPTH	0xf4a900ff
+
+/* FEC_AC_CTR_2 */
+#define	R367CAB_FEC_AC_CTR_2	0xf4aa
+#define	F367CAB_DEINT_M	0xf4aa00f8
+#define	F367CAB_DIS_UNLOCK	0xf4aa0004
+#define	F367CAB_DESCR_MODE	0xf4aa0003
+
+/* FEC_AC_CTR_3 */
+#define	R367CAB_FEC_AC_CTR_3	0xf4ab
+#define	F367CAB_DI_UNLOCK	0xf4ab0080
+#define	F367CAB_DI_FREEZE	0xf4ab0040
+#define	F367CAB_MISMATCH	0xf4ab0030
+#define	F367CAB_ACQ_MODE	0xf4ab000c
+#define	F367CAB_TRK_MODE	0xf4ab0003
+
+/* FEC_STATUS */
+#define	R367CAB_FEC_STATUS	0xf4ac
+#define	F367CAB_DEINT_SMCNTR	0xf4ac00e0
+#define	F367CAB_DEINT_SYNCSTATE	0xf4ac0018
+#define	F367CAB_DEINT_SYNLOST	0xf4ac0004
+#define	F367CAB_DESCR_SYNCSTATE	0xf4ac0002
+
+/* RS_COUNTER_0 */
+#define	R367CAB_RS_COUNTER_0	0xf4ae
+#define	F367CAB_BK_CT_L	0xf4ae00ff
+
+/* RS_COUNTER_1 */
+#define	R367CAB_RS_COUNTER_1	0xf4af
+#define	F367CAB_BK_CT_H	0xf4af00ff
+
+/* RS_COUNTER_2 */
+#define	R367CAB_RS_COUNTER_2	0xf4b0
+#define	F367CAB_CORR_CT_L	0xf4b000ff
+
+/* RS_COUNTER_3 */
+#define	R367CAB_RS_COUNTER_3	0xf4b1
+#define	F367CAB_CORR_CT_H	0xf4b100ff
+
+/* RS_COUNTER_4 */
+#define	R367CAB_RS_COUNTER_4	0xf4b2
+#define	F367CAB_UNCORR_CT_L	0xf4b200ff
+
+/* RS_COUNTER_5 */
+#define	R367CAB_RS_COUNTER_5	0xf4b3
+#define	F367CAB_UNCORR_CT_H	0xf4b300ff
+
+/* BERT_0 */
+#define	R367CAB_BERT_0	0xf4b4
+#define	F367CAB_RS_NOCORR	0xf4b40004
+#define	F367CAB_CT_HOLD	0xf4b40002
+#define	F367CAB_CT_CLEAR	0xf4b40001
+
+/* BERT_1 */
+#define	R367CAB_BERT_1	0xf4b5
+#define	F367CAB_BERT_ON	0xf4b50020
+#define	F367CAB_BERT_ERR_SRC	0xf4b50010
+#define	F367CAB_BERT_ERR_MODE	0xf4b50008
+#define	F367CAB_BERT_NBYTE	0xf4b50007
+
+/* BERT_2 */
+#define	R367CAB_BERT_2	0xf4b6
+#define	F367CAB_BERT_ERRCOUNT_L	0xf4b600ff
+
+/* BERT_3 */
+#define	R367CAB_BERT_3	0xf4b7
+#define	F367CAB_BERT_ERRCOUNT_H	0xf4b700ff
+
+/* OUTFORMAT_0 */
+#define	R367CAB_OUTFORMAT_0	0xf4b8
+#define	F367CAB_CLK_POLARITY	0xf4b80080
+#define	F367CAB_FEC_TYPE	0xf4b80040
+#define	F367CAB_SYNC_STRIP	0xf4b80008
+#define	F367CAB_TS_SWAP	0xf4b80004
+#define	F367CAB_OUTFORMAT	0xf4b80003
+
+/* OUTFORMAT_1 */
+#define	R367CAB_OUTFORMAT_1	0xf4b9
+#define	F367CAB_CI_DIVRANGE	0xf4b900ff
+
+/* SMOOTHER_2 */
+#define	R367CAB_SMOOTHER_2	0xf4be
+#define	F367CAB_FIFO_BYPASS	0xf4be0020
+
+/* TSMF_CTRL_0 */
+#define	R367CAB_TSMF_CTRL_0	0xf4c0
+#define	F367CAB_TS_NUMBER	0xf4c0001e
+#define	F367CAB_SEL_MODE	0xf4c00001
+
+/* TSMF_CTRL_1 */
+#define	R367CAB_TSMF_CTRL_1	0xf4c1
+#define	F367CAB_CHECK_ERROR_BIT	0xf4c10080
+#define	F367CAB_CHCK_F_SYNC	0xf4c10040
+#define	F367CAB_H_MODE	0xf4c10008
+#define	F367CAB_D_V_MODE	0xf4c10004
+#define	F367CAB_MODE	0xf4c10003
+
+/* TSMF_CTRL_3 */
+#define	R367CAB_TSMF_CTRL_3	0xf4c3
+#define	F367CAB_SYNC_IN_COUNT	0xf4c300f0
+#define	F367CAB_SYNC_OUT_COUNT	0xf4c3000f
+
+/* TS_ON_ID_0 */
+#define	R367CAB_TS_ON_ID_0	0xf4c4
+#define	F367CAB_TS_ID_L	0xf4c400ff
+
+/* TS_ON_ID_1 */
+#define	R367CAB_TS_ON_ID_1	0xf4c5
+#define	F367CAB_TS_ID_H	0xf4c500ff
+
+/* TS_ON_ID_2 */
+#define	R367CAB_TS_ON_ID_2	0xf4c6
+#define	F367CAB_ON_ID_L	0xf4c600ff
+
+/* TS_ON_ID_3 */
+#define	R367CAB_TS_ON_ID_3	0xf4c7
+#define	F367CAB_ON_ID_H	0xf4c700ff
+
+/* RE_STATUS_0 */
+#define	R367CAB_RE_STATUS_0	0xf4c8
+#define	F367CAB_RECEIVE_STATUS_L	0xf4c800ff
+
+/* RE_STATUS_1 */
+#define	R367CAB_RE_STATUS_1	0xf4c9
+#define	F367CAB_RECEIVE_STATUS_LH	0xf4c900ff
+
+/* RE_STATUS_2 */
+#define	R367CAB_RE_STATUS_2	0xf4ca
+#define	F367CAB_RECEIVE_STATUS_HL	0xf4ca00ff
+
+/* RE_STATUS_3 */
+#define	R367CAB_RE_STATUS_3	0xf4cb
+#define	F367CAB_RECEIVE_STATUS_HH	0xf4cb003f
+
+/* TS_STATUS_0 */
+#define	R367CAB_TS_STATUS_0	0xf4cc
+#define	F367CAB_TS_STATUS_L	0xf4cc00ff
+
+/* TS_STATUS_1 */
+#define	R367CAB_TS_STATUS_1	0xf4cd
+#define	F367CAB_TS_STATUS_H	0xf4cd007f
+
+/* TS_STATUS_2 */
+#define	R367CAB_TS_STATUS_2	0xf4ce
+#define	F367CAB_ERROR	0xf4ce0080
+#define	F367CAB_EMERGENCY	0xf4ce0040
+#define	F367CAB_CRE_TS	0xf4ce0030
+#define	F367CAB_VER	0xf4ce000e
+#define	F367CAB_M_LOCK	0xf4ce0001
+
+/* TS_STATUS_3 */
+#define	R367CAB_TS_STATUS_3	0xf4cf
+#define	F367CAB_UPDATE_READY	0xf4cf0080
+#define	F367CAB_END_FRAME_HEADER	0xf4cf0040
+#define	F367CAB_CONTCNT	0xf4cf0020
+#define	F367CAB_TS_IDENTIFIER_SEL	0xf4cf000f
+
+/* T_O_ID_0 */
+#define	R367CAB_T_O_ID_0	0xf4d0
+#define	F367CAB_ON_ID_I_L	0xf4d000ff
+
+/* T_O_ID_1 */
+#define	R367CAB_T_O_ID_1	0xf4d1
+#define	F367CAB_ON_ID_I_H	0xf4d100ff
+
+/* T_O_ID_2 */
+#define	R367CAB_T_O_ID_2	0xf4d2
+#define	F367CAB_TS_ID_I_L	0xf4d200ff
+
+/* T_O_ID_3 */
+#define	R367CAB_T_O_ID_3	0xf4d3
+#define	F367CAB_TS_ID_I_H	0xf4d300ff
+
+#define STV0367CAB_NBREGS	187
+
+#endif
diff --git a/drivers/media/dvb-frontends/stv0900.h b/drivers/media/dvb-frontends/stv0900.h
new file mode 100644
index 0000000..91c7ee8
--- /dev/null
+++ b/drivers/media/dvb-frontends/stv0900.h
@@ -0,0 +1,74 @@
+/*
+ * 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_reg {
+	u16 addr;
+	u8  val;
+};
+
+struct stv0900_config {
+	u8 demod_address;
+	u8 demod_mode;
+	u32 xtal;
+	u8 clkmode;/* 0 for CLKI,  2 for XTALI */
+
+	u8 diseqc_mode;
+
+	u8 path1_mode;
+	u8 path2_mode;
+	struct stv0900_reg *ts_config_regs;
+	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;
+	u8 tun1_type;/* for now 3 for stb6100 auto, else - software */
+	u8 tun2_type;
+	/* Set device param to start dma */
+	int (*set_ts_params)(struct dvb_frontend *fe, int is_punctured);
+	/* Hook for Lock LED */
+	void (*set_lock_led)(struct dvb_frontend *fe, int offon);
+};
+
+#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..7f1bada
--- /dev/null
+++ b/drivers/media/dvb-frontends/stv0900_core.c
@@ -0,0 +1,1959 @@
+/*
+ * 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"
+
+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 *intp, u16 reg_addr,
+								u8 reg_data)
+{
+	u8 data[3];
+	int ret;
+	struct i2c_msg i2cmsg = {
+		.addr  = intp->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(intp->i2c_adap, &i2cmsg, 1);
+	if (ret != 1)
+		dprintk("%s: i2c error %d\n", __func__, ret);
+}
+
+u8 stv0900_read_reg(struct stv0900_internal *intp, u16 reg)
+{
+	int ret;
+	u8 b0[] = { MSB(reg), LSB(reg) };
+	u8 buf = 0;
+	struct i2c_msg msg[] = {
+		{
+			.addr	= intp->i2c_addr,
+			.flags	= 0,
+			.buf = b0,
+			.len = 2,
+		}, {
+			.addr	= intp->i2c_addr,
+			.flags	= I2C_M_RD,
+			.buf = &buf,
+			.len = 1,
+		},
+	};
+
+	ret = i2c_transfer(intp->i2c_adap, msg, 2);
+	if (ret != 2)
+		dprintk("%s: i2c error %d, reg[0x%02x]\n",
+				__func__, ret, reg);
+
+	return buf;
+}
+
+static 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 *intp, u32 label, u8 val)
+{
+	u8 reg, mask, pos;
+
+	reg = stv0900_read_reg(intp, (label >> 16) & 0xffff);
+	extract_mask_pos(label, &mask, &pos);
+
+	val = mask & (val << pos);
+
+	reg = (reg & (~mask)) | val;
+	stv0900_write_reg(intp, (label >> 16) & 0xffff, reg);
+
+}
+
+u8 stv0900_get_bits(struct stv0900_internal *intp, u32 label)
+{
+	u8 val = 0xff;
+	u8 mask, pos;
+
+	extract_mask_pos(label, &mask, &pos);
+
+	val = stv0900_read_reg(intp, label >> 16);
+	val = (val & mask) >> pos;
+
+	return val;
+}
+
+static enum fe_stv0900_error stv0900_initialize(struct stv0900_internal *intp)
+{
+	s32 i;
+
+	if (intp == NULL)
+		return STV0900_INVALID_HANDLE;
+
+	intp->chip_id = stv0900_read_reg(intp, R0900_MID);
+
+	if (intp->errs != STV0900_NO_ERROR)
+		return intp->errs;
+
+	/*Startup sequence*/
+	stv0900_write_reg(intp, R0900_P1_DMDISTATE, 0x5c);
+	stv0900_write_reg(intp, R0900_P2_DMDISTATE, 0x5c);
+	msleep(3);
+	stv0900_write_reg(intp, R0900_P1_TNRCFG, 0x6c);
+	stv0900_write_reg(intp, R0900_P2_TNRCFG, 0x6f);
+	stv0900_write_reg(intp, R0900_P1_I2CRPT, 0x20);
+	stv0900_write_reg(intp, R0900_P2_I2CRPT, 0x20);
+	stv0900_write_reg(intp, R0900_NCOARSE, 0x13);
+	msleep(3);
+	stv0900_write_reg(intp, R0900_I2CCFG, 0x08);
+
+	switch (intp->clkmode) {
+	case 0:
+	case 2:
+		stv0900_write_reg(intp, R0900_SYNTCTRL, 0x20
+				| intp->clkmode);
+		break;
+	default:
+		/* preserve SELOSCI bit */
+		i = 0x02 & stv0900_read_reg(intp, R0900_SYNTCTRL);
+		stv0900_write_reg(intp, R0900_SYNTCTRL, 0x20 | i);
+		break;
+	}
+
+	msleep(3);
+	for (i = 0; i < 181; i++)
+		stv0900_write_reg(intp, STV0900_InitVal[i][0],
+				STV0900_InitVal[i][1]);
+
+	if (stv0900_read_reg(intp, R0900_MID) >= 0x20) {
+		stv0900_write_reg(intp, R0900_TSGENERAL, 0x0c);
+		for (i = 0; i < 32; i++)
+			stv0900_write_reg(intp, STV0900_Cut20_AddOnVal[i][0],
+					STV0900_Cut20_AddOnVal[i][1]);
+	}
+
+	stv0900_write_reg(intp, R0900_P1_FSPYCFG, 0x6c);
+	stv0900_write_reg(intp, R0900_P2_FSPYCFG, 0x6c);
+
+	stv0900_write_reg(intp, R0900_P1_PDELCTRL2, 0x01);
+	stv0900_write_reg(intp, R0900_P2_PDELCTRL2, 0x21);
+
+	stv0900_write_reg(intp, R0900_P1_PDELCTRL3, 0x20);
+	stv0900_write_reg(intp, R0900_P2_PDELCTRL3, 0x20);
+
+	stv0900_write_reg(intp, R0900_TSTRES0, 0x80);
+	stv0900_write_reg(intp, R0900_TSTRES0, 0x00);
+
+	return STV0900_NO_ERROR;
+}
+
+static u32 stv0900_get_mclk_freq(struct stv0900_internal *intp, u32 ext_clk)
+{
+	u32 mclk = 90000000, div = 0, ad_div = 0;
+
+	div = stv0900_get_bits(intp, F0900_M_DIV);
+	ad_div = ((stv0900_get_bits(intp, F0900_SELX1RATIO) == 1) ? 4 : 6);
+
+	mclk = (div + 1) * ext_clk / ad_div;
+
+	dprintk("%s: Calculated Mclk = %d\n", __func__, mclk);
+
+	return mclk;
+}
+
+static enum fe_stv0900_error stv0900_set_mclk(struct stv0900_internal *intp, u32 mclk)
+{
+	u32 m_div, clk_sel;
+
+	dprintk("%s: Mclk set to %d, Quartz = %d\n", __func__, mclk,
+			intp->quartz);
+
+	if (intp == NULL)
+		return STV0900_INVALID_HANDLE;
+
+	if (intp->errs)
+		return STV0900_I2C_ERROR;
+
+	clk_sel = ((stv0900_get_bits(intp, F0900_SELX1RATIO) == 1) ? 4 : 6);
+	m_div = ((clk_sel * mclk) / intp->quartz) - 1;
+	stv0900_write_bits(intp, F0900_M_DIV, m_div);
+	intp->mclk = stv0900_get_mclk_freq(intp,
+					intp->quartz);
+
+	/*Set the DiseqC frequency to 22KHz */
+	/*
+		Formula:
+		DiseqC_TX_Freq= MasterClock/(32*F22TX_Reg)
+		DiseqC_RX_Freq= MasterClock/(32*F22RX_Reg)
+	*/
+	m_div = intp->mclk / 704000;
+	stv0900_write_reg(intp, R0900_P1_F22TX, m_div);
+	stv0900_write_reg(intp, R0900_P1_F22RX, m_div);
+
+	stv0900_write_reg(intp, R0900_P2_F22TX, m_div);
+	stv0900_write_reg(intp, R0900_P2_F22RX, m_div);
+
+	if ((intp->errs))
+		return STV0900_I2C_ERROR;
+
+	return STV0900_NO_ERROR;
+}
+
+static u32 stv0900_get_err_count(struct stv0900_internal *intp, int cntr,
+					enum fe_stv0900_demod_num demod)
+{
+	u32 lsb, msb, hsb, err_val;
+
+	switch (cntr) {
+	case 0:
+	default:
+		hsb = stv0900_get_bits(intp, ERR_CNT12);
+		msb = stv0900_get_bits(intp, ERR_CNT11);
+		lsb = stv0900_get_bits(intp, ERR_CNT10);
+		break;
+	case 1:
+		hsb = stv0900_get_bits(intp, ERR_CNT22);
+		msb = stv0900_get_bits(intp, ERR_CNT21);
+		lsb = stv0900_get_bits(intp, ERR_CNT20);
+		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 *intp = state->internal;
+	enum fe_stv0900_demod_num demod = state->demod;
+
+	stv0900_write_bits(intp, I2CT_ON, enable);
+
+	return 0;
+}
+
+static void stv0900_set_ts_parallel_serial(struct stv0900_internal *intp,
+					enum fe_stv0900_clock_type path1_ts,
+					enum fe_stv0900_clock_type path2_ts)
+{
+
+	dprintk("%s\n", __func__);
+
+	if (intp->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(intp, R0900_TSGENERAL,
+							0x00);
+				break;
+			case STV0900_PARALLEL_PUNCT_CLOCK:
+			case STV0900_DVBCI_CLOCK:
+				stv0900_write_reg(intp, R0900_TSGENERAL,
+							0x06);
+				stv0900_write_bits(intp,
+						F0900_P1_TSFIFO_MANSPEED, 3);
+				stv0900_write_bits(intp,
+						F0900_P2_TSFIFO_MANSPEED, 0);
+				stv0900_write_reg(intp,
+						R0900_P1_TSSPEED, 0x14);
+				stv0900_write_reg(intp,
+						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(intp,
+						R0900_TSGENERAL, 0x0C);
+				break;
+			case STV0900_PARALLEL_PUNCT_CLOCK:
+			case STV0900_DVBCI_CLOCK:
+				stv0900_write_reg(intp,
+						R0900_TSGENERAL, 0x0A);
+				dprintk("%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(intp, R0900_TSGENERAL1X,
+							0x10);
+				break;
+			case STV0900_PARALLEL_PUNCT_CLOCK:
+			case STV0900_DVBCI_CLOCK:
+				stv0900_write_reg(intp, R0900_TSGENERAL1X,
+							0x16);
+				stv0900_write_bits(intp,
+						F0900_P1_TSFIFO_MANSPEED, 3);
+				stv0900_write_bits(intp,
+						F0900_P2_TSFIFO_MANSPEED, 0);
+				stv0900_write_reg(intp, R0900_P1_TSSPEED,
+							0x14);
+				stv0900_write_reg(intp, 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(intp, R0900_TSGENERAL1X,
+							0x14);
+				break;
+			case STV0900_PARALLEL_PUNCT_CLOCK:
+			case STV0900_DVBCI_CLOCK:
+				stv0900_write_reg(intp, R0900_TSGENERAL1X,
+							0x12);
+				dprintk("%s: 0x12\n", __func__);
+				break;
+			}
+
+			break;
+		}
+	}
+
+	switch (path1_ts) {
+	case STV0900_PARALLEL_PUNCT_CLOCK:
+		stv0900_write_bits(intp, F0900_P1_TSFIFO_SERIAL, 0x00);
+		stv0900_write_bits(intp, F0900_P1_TSFIFO_DVBCI, 0x00);
+		break;
+	case STV0900_DVBCI_CLOCK:
+		stv0900_write_bits(intp, F0900_P1_TSFIFO_SERIAL, 0x00);
+		stv0900_write_bits(intp, F0900_P1_TSFIFO_DVBCI, 0x01);
+		break;
+	case STV0900_SERIAL_PUNCT_CLOCK:
+		stv0900_write_bits(intp, F0900_P1_TSFIFO_SERIAL, 0x01);
+		stv0900_write_bits(intp, F0900_P1_TSFIFO_DVBCI, 0x00);
+		break;
+	case STV0900_SERIAL_CONT_CLOCK:
+		stv0900_write_bits(intp, F0900_P1_TSFIFO_SERIAL, 0x01);
+		stv0900_write_bits(intp, F0900_P1_TSFIFO_DVBCI, 0x01);
+		break;
+	default:
+		break;
+	}
+
+	switch (path2_ts) {
+	case STV0900_PARALLEL_PUNCT_CLOCK:
+		stv0900_write_bits(intp, F0900_P2_TSFIFO_SERIAL, 0x00);
+		stv0900_write_bits(intp, F0900_P2_TSFIFO_DVBCI, 0x00);
+		break;
+	case STV0900_DVBCI_CLOCK:
+		stv0900_write_bits(intp, F0900_P2_TSFIFO_SERIAL, 0x00);
+		stv0900_write_bits(intp, F0900_P2_TSFIFO_DVBCI, 0x01);
+		break;
+	case STV0900_SERIAL_PUNCT_CLOCK:
+		stv0900_write_bits(intp, F0900_P2_TSFIFO_SERIAL, 0x01);
+		stv0900_write_bits(intp, F0900_P2_TSFIFO_DVBCI, 0x00);
+		break;
+	case STV0900_SERIAL_CONT_CLOCK:
+		stv0900_write_bits(intp, F0900_P2_TSFIFO_SERIAL, 0x01);
+		stv0900_write_bits(intp, F0900_P2_TSFIFO_DVBCI, 0x01);
+		break;
+	default:
+		break;
+	}
+
+	stv0900_write_bits(intp, F0900_P2_RST_HWARE, 1);
+	stv0900_write_bits(intp, F0900_P2_RST_HWARE, 0);
+	stv0900_write_bits(intp, F0900_P1_RST_HWARE, 1);
+	stv0900_write_bits(intp, 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);
+
+	}
+}
+
+u32 stv0900_get_freq_auto(struct stv0900_internal *intp, int demod)
+{
+	u32 freq, round;
+	/*	Formulat :
+	Tuner_Frequency(MHz)	= Regs / 64
+	Tuner_granularity(MHz)	= Regs / 2048
+	real_Tuner_Frequency	= Tuner_Frequency(MHz) - Tuner_granularity(MHz)
+	*/
+	freq = (stv0900_get_bits(intp, TUN_RFFREQ2) << 10) +
+		(stv0900_get_bits(intp, TUN_RFFREQ1) << 2) +
+		stv0900_get_bits(intp, TUN_RFFREQ0);
+
+	freq = (freq * 1000) / 64;
+
+	round = (stv0900_get_bits(intp, TUN_RFRESTE1) >> 2) +
+		stv0900_get_bits(intp, TUN_RFRESTE0);
+
+	round = (round * 1000) / 2048;
+
+	return freq + round;
+}
+
+void stv0900_set_tuner_auto(struct stv0900_internal *intp, u32 Frequency,
+						u32 Bandwidth, int demod)
+{
+	u32 tunerFrequency;
+	/* Formulat:
+	Tuner_frequency_reg= Frequency(MHz)*64
+	*/
+	tunerFrequency = (Frequency * 64) / 1000;
+
+	stv0900_write_bits(intp, TUN_RFFREQ2, (tunerFrequency >> 10));
+	stv0900_write_bits(intp, TUN_RFFREQ1, (tunerFrequency >> 2) & 0xff);
+	stv0900_write_bits(intp, TUN_RFFREQ0, (tunerFrequency & 0x03));
+	/* Low Pass Filter = BW /2 (MHz)*/
+	stv0900_write_bits(intp, TUN_BW, Bandwidth / 2000000);
+	/* Tuner Write trig */
+	stv0900_write_reg(intp, TNRLD, 1);
+}
+
+static s32 stv0900_get_rf_level(struct stv0900_internal *intp,
+				const struct stv0900_table *lookup,
+				enum fe_stv0900_demod_num demod)
+{
+	s32 agc_gain = 0,
+		imin,
+		imax,
+		i,
+		rf_lvl = 0;
+
+	dprintk("%s\n", __func__);
+
+	if ((lookup == NULL) || (lookup->size <= 0))
+		return 0;
+
+	agc_gain = MAKEWORD(stv0900_get_bits(intp, AGCIQ_VALUE1),
+				stv0900_get_bits(intp, AGCIQ_VALUE0));
+
+	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;
+		rf_lvl *= (lookup->table[imax].realval -
+				lookup->table[imin].realval);
+		rf_lvl /= (lookup->table[imax].regval -
+				lookup->table[imin].regval);
+		rf_lvl += 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("%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);
+
+	rflevel = (rflevel + 100) * (65535 / 70);
+	if (rflevel < 0)
+		rflevel = 0;
+
+	if (rflevel > 65535)
+		rflevel = 65535;
+
+	*strength = rflevel;
+
+	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 *intp = state->internal;
+	enum fe_stv0900_demod_num demod = state->demod;
+
+	s32	c_n = -100,
+		regval,
+		imin,
+		imax,
+		i,
+		noise_field1,
+		noise_field0;
+
+	dprintk("%s\n", __func__);
+
+	if (stv0900_get_standard(fe, demod) == STV0900_DVBS2_STANDARD) {
+		noise_field1 = NOSPLHT_NORMED1;
+		noise_field0 = NOSPLHT_NORMED0;
+	} else {
+		noise_field1 = NOSDATAT_NORMED1;
+		noise_field0 = NOSDATAT_NORMED0;
+	}
+
+	if (stv0900_get_bits(intp, LOCK_DEFINITIF)) {
+		if ((lookup != NULL) && lookup->size) {
+			regval = 0;
+			msleep(5);
+			for (i = 0; i < 16; i++) {
+				regval += MAKEWORD(stv0900_get_bits(intp,
+								noise_field1),
+						stv0900_get_bits(intp,
+								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_ucblocks(struct dvb_frontend *fe, u32 * ucblocks)
+{
+	struct stv0900_state *state = fe->demodulator_priv;
+	struct stv0900_internal *intp = state->internal;
+	enum fe_stv0900_demod_num demod = state->demod;
+	u8 err_val1, err_val0;
+	u32 header_err_val = 0;
+
+	*ucblocks = 0x0;
+	if (stv0900_get_standard(fe, demod) == STV0900_DVBS2_STANDARD) {
+		/* DVB-S2 delineator errors count */
+
+		/* retreiving number for errnous headers */
+		err_val1 = stv0900_read_reg(intp, BBFCRCKO1);
+		err_val0 = stv0900_read_reg(intp, BBFCRCKO0);
+		header_err_val = (err_val1 << 8) | err_val0;
+
+		/* retreiving number for errnous packets */
+		err_val1 = stv0900_read_reg(intp, UPCRCKO1);
+		err_val0 = stv0900_read_reg(intp, UPCRCKO0);
+		*ucblocks = (err_val1 << 8) | err_val0;
+		*ucblocks += header_err_val;
+	}
+
+	return 0;
+}
+
+static int stv0900_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+	s32 snrlcl = stv0900_carr_get_quality(fe,
+			(const struct stv0900_table *)&stv0900_s2_cn);
+	snrlcl = (snrlcl + 30) * 384;
+	if (snrlcl < 0)
+		snrlcl = 0;
+
+	if (snrlcl > 65535)
+		snrlcl = 65535;
+
+	*snr = snrlcl;
+
+	return 0;
+}
+
+static u32 stv0900_get_ber(struct stv0900_internal *intp,
+				enum fe_stv0900_demod_num demod)
+{
+	u32 ber = 10000000, i;
+	s32 demod_state;
+
+	demod_state = stv0900_get_bits(intp, HEADER_MODE);
+
+	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(intp, 0, demod);
+		}
+
+		ber /= 5;
+		if (stv0900_get_bits(intp, PRFVIT)) {
+			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(intp, 0, demod);
+		}
+
+		ber /= 5;
+		if (stv0900_get_bits(intp, PKTDELIN_LOCK)) {
+			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 *intp,
+			enum fe_stv0900_demod_num demod, s32 time_out)
+{
+	s32 timer = 0,
+		lock = 0;
+
+	enum fe_stv0900_search_state	dmd_state;
+
+	while ((timer < time_out) && (lock == 0)) {
+		dmd_state = stv0900_get_bits(intp, HEADER_MODE);
+		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(intp, LOCK_DEFINITIF);
+			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 *intp,
+				enum fe_stv0900_demod_num demod)
+{
+	s32 regflist,
+	i;
+
+	dprintk("%s\n", __func__);
+
+	regflist = MODCODLST0;
+
+	for (i = 0; i < 16; i++)
+		stv0900_write_reg(intp, regflist + i, 0xff);
+}
+
+void stv0900_activate_s2_modcod(struct stv0900_internal *intp,
+				enum fe_stv0900_demod_num demod)
+{
+	u32 matype,
+		mod_code,
+		fmod,
+		reg_index,
+		field_index;
+
+	dprintk("%s\n", __func__);
+
+	if (intp->chip_id <= 0x11) {
+		msleep(5);
+
+		mod_code = stv0900_read_reg(intp, PLHMODCOD);
+		matype = mod_code & 0x3;
+		mod_code = (mod_code & 0x7f) >> 2;
+
+		reg_index = MODCODLSTF - mod_code / 2;
+		field_index = mod_code % 2;
+
+		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(intp, reg_index,
+							0xf0 | fmod);
+			else
+				stv0900_write_reg(intp, reg_index,
+							(fmod << 4) | 0xf);
+		}
+
+	} else if (intp->chip_id >= 0x12) {
+		for (reg_index = 0; reg_index < 7; reg_index++)
+			stv0900_write_reg(intp, MODCODLST0 + reg_index, 0xff);
+
+		stv0900_write_reg(intp, MODCODLSTE, 0xff);
+		stv0900_write_reg(intp, MODCODLSTF, 0xcf);
+		for (reg_index = 0; reg_index < 8; reg_index++)
+			stv0900_write_reg(intp, MODCODLST7 + reg_index, 0xcc);
+
+
+	}
+}
+
+void stv0900_activate_s2_modcod_single(struct stv0900_internal *intp,
+					enum fe_stv0900_demod_num demod)
+{
+	u32 reg_index;
+
+	dprintk("%s\n", __func__);
+
+	stv0900_write_reg(intp, MODCODLST0, 0xff);
+	stv0900_write_reg(intp, MODCODLST1, 0xf0);
+	stv0900_write_reg(intp, MODCODLSTF, 0x0f);
+	for (reg_index = 0; reg_index < 13; reg_index++)
+		stv0900_write_reg(intp, MODCODLST2 + reg_index, 0);
+
+}
+
+static enum dvbfe_algo stv0900_frontend_algo(struct dvb_frontend *fe)
+{
+	return DVBFE_ALGO_CUSTOM;
+}
+
+void stv0900_start_search(struct stv0900_internal *intp,
+				enum fe_stv0900_demod_num demod)
+{
+	u32 freq;
+	s16 freq_s16 ;
+
+	stv0900_write_bits(intp, DEMOD_MODE, 0x1f);
+	if (intp->chip_id == 0x10)
+		stv0900_write_reg(intp, CORRELEXP, 0xaa);
+
+	if (intp->chip_id < 0x20)
+		stv0900_write_reg(intp, CARHDR, 0x55);
+
+	if (intp->chip_id <= 0x20) {
+		if (intp->symbol_rate[0] <= 5000000) {
+			stv0900_write_reg(intp, CARCFG, 0x44);
+			stv0900_write_reg(intp, CFRUP1, 0x0f);
+			stv0900_write_reg(intp, CFRUP0, 0xff);
+			stv0900_write_reg(intp, CFRLOW1, 0xf0);
+			stv0900_write_reg(intp, CFRLOW0, 0x00);
+			stv0900_write_reg(intp, RTCS2, 0x68);
+		} else {
+			stv0900_write_reg(intp, CARCFG, 0xc4);
+			stv0900_write_reg(intp, RTCS2, 0x44);
+		}
+
+	} else { /*cut 3.0 above*/
+		if (intp->symbol_rate[demod] <= 5000000)
+			stv0900_write_reg(intp, RTCS2, 0x68);
+		else
+			stv0900_write_reg(intp, RTCS2, 0x44);
+
+		stv0900_write_reg(intp, CARCFG, 0x46);
+		if (intp->srch_algo[demod] == STV0900_WARM_START) {
+			freq = 1000 << 16;
+			freq /= (intp->mclk / 1000);
+			freq_s16 = (s16)freq;
+		} else {
+			freq = (intp->srch_range[demod] / 2000);
+			if (intp->symbol_rate[demod] <= 5000000)
+				freq += 80;
+			else
+				freq += 600;
+
+			freq = freq << 16;
+			freq /= (intp->mclk / 1000);
+			freq_s16 = (s16)freq;
+		}
+
+		stv0900_write_bits(intp, CFR_UP1, MSB(freq_s16));
+		stv0900_write_bits(intp, CFR_UP0, LSB(freq_s16));
+		freq_s16 *= (-1);
+		stv0900_write_bits(intp, CFR_LOW1, MSB(freq_s16));
+		stv0900_write_bits(intp, CFR_LOW0, LSB(freq_s16));
+	}
+
+	stv0900_write_reg(intp, CFRINIT1, 0);
+	stv0900_write_reg(intp, CFRINIT0, 0);
+
+	if (intp->chip_id >= 0x20) {
+		stv0900_write_reg(intp, EQUALCFG, 0x41);
+		stv0900_write_reg(intp, FFECFG, 0x41);
+
+		if ((intp->srch_standard[demod] == STV0900_SEARCH_DVBS1) ||
+			(intp->srch_standard[demod] == STV0900_SEARCH_DSS) ||
+			(intp->srch_standard[demod] == STV0900_AUTO_SEARCH)) {
+			stv0900_write_reg(intp, VITSCALE,
+								0x82);
+			stv0900_write_reg(intp, VAVSRVIT, 0x0);
+		}
+	}
+
+	stv0900_write_reg(intp, SFRSTEP, 0x00);
+	stv0900_write_reg(intp, TMGTHRISE, 0xe0);
+	stv0900_write_reg(intp, TMGTHFALL, 0xc0);
+	stv0900_write_bits(intp, SCAN_ENABLE, 0);
+	stv0900_write_bits(intp, CFR_AUTOSCAN, 0);
+	stv0900_write_bits(intp, S1S2_SEQUENTIAL, 0);
+	stv0900_write_reg(intp, RTC, 0x88);
+	if (intp->chip_id >= 0x20) {
+		if (intp->symbol_rate[demod] < 2000000) {
+			if (intp->chip_id <= 0x20)
+				stv0900_write_reg(intp, CARFREQ, 0x39);
+			else  /*cut 3.0*/
+				stv0900_write_reg(intp, CARFREQ, 0x89);
+
+			stv0900_write_reg(intp, CARHDR, 0x40);
+		} else if (intp->symbol_rate[demod] < 10000000) {
+			stv0900_write_reg(intp, CARFREQ, 0x4c);
+			stv0900_write_reg(intp, CARHDR, 0x20);
+		} else {
+			stv0900_write_reg(intp, CARFREQ, 0x4b);
+			stv0900_write_reg(intp, CARHDR, 0x20);
+		}
+
+	} else {
+		if (intp->symbol_rate[demod] < 10000000)
+			stv0900_write_reg(intp, CARFREQ, 0xef);
+		else
+			stv0900_write_reg(intp, CARFREQ, 0xed);
+	}
+
+	switch (intp->srch_algo[demod]) {
+	case STV0900_WARM_START:
+		stv0900_write_reg(intp, DMDISTATE, 0x1f);
+		stv0900_write_reg(intp, DMDISTATE, 0x18);
+		break;
+	case STV0900_COLD_START:
+		stv0900_write_reg(intp, DMDISTATE, 0x1f);
+		stv0900_write_reg(intp, DMDISTATE, 0x15);
+		break;
+	default:
+		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 *cls2, *cllqs2, *cllas2;
+
+	dprintk("%s\n", __func__);
+
+	if (chip_id <= 0x12) {
+		cls2 = FE_STV0900_S2CarLoop;
+		cllqs2 = FE_STV0900_S2LowQPCarLoopCut30;
+		cllas2 = FE_STV0900_S2APSKCarLoopCut30;
+	} else if (chip_id == 0x20) {
+		cls2 = FE_STV0900_S2CarLoopCut20;
+		cllqs2 = FE_STV0900_S2LowQPCarLoopCut20;
+		cllas2 = FE_STV0900_S2APSKCarLoopCut20;
+	} else {
+		cls2 = FE_STV0900_S2CarLoopCut30;
+		cllqs2 = FE_STV0900_S2LowQPCarLoopCut30;
+		cllas2 = FE_STV0900_S2APSKCarLoopCut30;
+	}
+
+	if (modcode < STV0900_QPSK_12) {
+		i = 0;
+		while ((i < 3) && (modcode != cllqs2[i].modcode))
+			i++;
+
+		if (i >= 3)
+			i = 2;
+	} else {
+		i = 0;
+		while ((i < 14) && (modcode != cls2[i].modcode))
+			i++;
+
+		if (i >= 14) {
+			i = 0;
+			while ((i < 11) && (modcode != cllas2[i].modcode))
+				i++;
+
+			if (i >= 11)
+				i = 10;
+		}
+	}
+
+	if (modcode <= STV0900_QPSK_25) {
+		if (pilot) {
+			if (srate <= 3000000)
+				aclc_value = cllqs2[i].car_loop_pilots_on_2;
+			else if (srate <= 7000000)
+				aclc_value = cllqs2[i].car_loop_pilots_on_5;
+			else if (srate <= 15000000)
+				aclc_value = cllqs2[i].car_loop_pilots_on_10;
+			else if (srate <= 25000000)
+				aclc_value = cllqs2[i].car_loop_pilots_on_20;
+			else
+				aclc_value = cllqs2[i].car_loop_pilots_on_30;
+		} else {
+			if (srate <= 3000000)
+				aclc_value = cllqs2[i].car_loop_pilots_off_2;
+			else if (srate <= 7000000)
+				aclc_value = cllqs2[i].car_loop_pilots_off_5;
+			else if (srate <= 15000000)
+				aclc_value = cllqs2[i].car_loop_pilots_off_10;
+			else if (srate <= 25000000)
+				aclc_value = cllqs2[i].car_loop_pilots_off_20;
+			else
+				aclc_value = cllqs2[i].car_loop_pilots_off_30;
+		}
+
+	} else if (modcode <= STV0900_8PSK_910) {
+		if (pilot) {
+			if (srate <= 3000000)
+				aclc_value = cls2[i].car_loop_pilots_on_2;
+			else if (srate <= 7000000)
+				aclc_value = cls2[i].car_loop_pilots_on_5;
+			else if (srate <= 15000000)
+				aclc_value = cls2[i].car_loop_pilots_on_10;
+			else if (srate <= 25000000)
+				aclc_value = cls2[i].car_loop_pilots_on_20;
+			else
+				aclc_value = cls2[i].car_loop_pilots_on_30;
+		} else {
+			if (srate <= 3000000)
+				aclc_value = cls2[i].car_loop_pilots_off_2;
+			else if (srate <= 7000000)
+				aclc_value = cls2[i].car_loop_pilots_off_5;
+			else if (srate <= 15000000)
+				aclc_value = cls2[i].car_loop_pilots_off_10;
+			else if (srate <= 25000000)
+				aclc_value = cls2[i].car_loop_pilots_off_20;
+			else
+				aclc_value = cls2[i].car_loop_pilots_off_30;
+		}
+
+	} else {
+		if (srate <= 3000000)
+			aclc_value = cllas2[i].car_loop_pilots_on_2;
+		else if (srate <= 7000000)
+			aclc_value = cllas2[i].car_loop_pilots_on_5;
+		else if (srate <= 15000000)
+			aclc_value = cllas2[i].car_loop_pilots_on_10;
+		else if (srate <= 25000000)
+			aclc_value = cllas2[i].car_loop_pilots_on_20;
+		else
+			aclc_value = cllas2[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)
+{
+	const struct stv0900_short_frames_car_loop_optim *s2scl;
+	const struct stv0900_short_frames_car_loop_optim_vs_mod *s2sclc30;
+	s32 mod_index = 0;
+	u8 aclc_value = 0x0b;
+
+	dprintk("%s\n", __func__);
+
+	s2scl = FE_STV0900_S2ShortCarLoop;
+	s2sclc30 = FE_STV0900_S2ShortCarLoopCut30;
+
+	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;
+	}
+
+	if (chip_id >= 0x30) {
+		if (srate <= 3000000)
+			aclc_value = s2sclc30[mod_index].car_loop_2;
+		else if (srate <= 7000000)
+			aclc_value = s2sclc30[mod_index].car_loop_5;
+		else if (srate <= 15000000)
+			aclc_value = s2sclc30[mod_index].car_loop_10;
+		else if (srate <= 25000000)
+			aclc_value = s2sclc30[mod_index].car_loop_20;
+		else
+			aclc_value = s2sclc30[mod_index].car_loop_30;
+
+	} else if (chip_id >= 0x20) {
+		if (srate <= 3000000)
+			aclc_value = s2scl[mod_index].car_loop_cut20_2;
+		else if (srate <= 7000000)
+			aclc_value = s2scl[mod_index].car_loop_cut20_5;
+		else if (srate <= 15000000)
+			aclc_value = s2scl[mod_index].car_loop_cut20_10;
+		else if (srate <= 25000000)
+			aclc_value = s2scl[mod_index].car_loop_cut20_20;
+		else
+			aclc_value = s2scl[mod_index].car_loop_cut20_30;
+
+	} else {
+		if (srate <= 3000000)
+			aclc_value = s2scl[mod_index].car_loop_cut12_2;
+		else if (srate <= 7000000)
+			aclc_value = s2scl[mod_index].car_loop_cut12_5;
+		else if (srate <= 15000000)
+			aclc_value = s2scl[mod_index].car_loop_cut12_10;
+		else if (srate <= 25000000)
+			aclc_value = s2scl[mod_index].car_loop_cut12_20;
+		else
+			aclc_value = s2scl[mod_index].car_loop_cut12_30;
+
+	}
+
+	return aclc_value;
+}
+
+static
+enum fe_stv0900_error stv0900_st_dvbs2_single(struct stv0900_internal *intp,
+					enum fe_stv0900_demod_mode LDPC_Mode,
+					enum fe_stv0900_demod_num demod)
+{
+	enum fe_stv0900_error error = STV0900_NO_ERROR;
+	s32 reg_ind;
+
+	dprintk("%s\n", __func__);
+
+	switch (LDPC_Mode) {
+	case STV0900_DUAL:
+	default:
+		if ((intp->demod_mode != STV0900_DUAL)
+			|| (stv0900_get_bits(intp, F0900_DDEMOD) != 1)) {
+			stv0900_write_reg(intp, R0900_GENCFG, 0x1d);
+
+			intp->demod_mode = STV0900_DUAL;
+
+			stv0900_write_bits(intp, F0900_FRESFEC, 1);
+			stv0900_write_bits(intp, F0900_FRESFEC, 0);
+
+			for (reg_ind = 0; reg_ind < 7; reg_ind++)
+				stv0900_write_reg(intp,
+						R0900_P1_MODCODLST0 + reg_ind,
+						0xff);
+			for (reg_ind = 0; reg_ind < 8; reg_ind++)
+				stv0900_write_reg(intp,
+						R0900_P1_MODCODLST7 + reg_ind,
+						0xcc);
+
+			stv0900_write_reg(intp, R0900_P1_MODCODLSTE, 0xff);
+			stv0900_write_reg(intp, R0900_P1_MODCODLSTF, 0xcf);
+
+			for (reg_ind = 0; reg_ind < 7; reg_ind++)
+				stv0900_write_reg(intp,
+						R0900_P2_MODCODLST0 + reg_ind,
+						0xff);
+			for (reg_ind = 0; reg_ind < 8; reg_ind++)
+				stv0900_write_reg(intp,
+						R0900_P2_MODCODLST7 + reg_ind,
+						0xcc);
+
+			stv0900_write_reg(intp, R0900_P2_MODCODLSTE, 0xff);
+			stv0900_write_reg(intp, R0900_P2_MODCODLSTF, 0xcf);
+		}
+
+		break;
+	case STV0900_SINGLE:
+		if (demod == STV0900_DEMOD_2) {
+			stv0900_stop_all_s2_modcod(intp, STV0900_DEMOD_1);
+			stv0900_activate_s2_modcod_single(intp,
+							STV0900_DEMOD_2);
+			stv0900_write_reg(intp, R0900_GENCFG, 0x06);
+		} else {
+			stv0900_stop_all_s2_modcod(intp, STV0900_DEMOD_2);
+			stv0900_activate_s2_modcod_single(intp,
+							STV0900_DEMOD_1);
+			stv0900_write_reg(intp, R0900_GENCFG, 0x04);
+		}
+
+		intp->demod_mode = STV0900_SINGLE;
+
+		stv0900_write_bits(intp, F0900_FRESFEC, 1);
+		stv0900_write_bits(intp, F0900_FRESFEC, 0);
+		stv0900_write_bits(intp, F0900_P1_ALGOSWRST, 1);
+		stv0900_write_bits(intp, F0900_P1_ALGOSWRST, 0);
+		stv0900_write_bits(intp, F0900_P2_ALGOSWRST, 1);
+		stv0900_write_bits(intp, 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;
+	struct stv0900_internal *intp = NULL;
+	int selosci, i;
+
+	struct stv0900_inode *temp_int = find_inode(state->i2c_adap,
+						state->config->demod_address);
+
+	dprintk("%s\n", __func__);
+
+	if ((temp_int != NULL) && (p_init->demod_mode == STV0900_DUAL)) {
+		state->internal = temp_int->internal;
+		(state->internal->dmds_used)++;
+		dprintk("%s: Find Internal Structure!\n", __func__);
+		return STV0900_NO_ERROR;
+	} else {
+		state->internal = kmalloc(sizeof(struct stv0900_internal),
+								GFP_KERNEL);
+		if (state->internal == NULL)
+			return STV0900_INVALID_HANDLE;
+		temp_int = append_internal(state->internal);
+		if (temp_int == NULL) {
+			kfree(state->internal);
+			state->internal = NULL;
+			return STV0900_INVALID_HANDLE;
+		}
+		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("%s: Create New Internal Structure!\n", __func__);
+	}
+
+	if (state->internal == NULL) {
+		error = STV0900_INVALID_HANDLE;
+		return error;
+	}
+
+	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;
+
+		return error;
+	}
+
+	intp = state->internal;
+
+	intp->demod_mode = p_init->demod_mode;
+	stv0900_st_dvbs2_single(intp, intp->demod_mode,	STV0900_DEMOD_1);
+	intp->chip_id = stv0900_read_reg(intp, R0900_MID);
+	intp->rolloff = p_init->rolloff;
+	intp->quartz = p_init->dmd_ref_clk;
+
+	stv0900_write_bits(intp, F0900_P1_ROLLOFF_CONTROL, p_init->rolloff);
+	stv0900_write_bits(intp, F0900_P2_ROLLOFF_CONTROL, p_init->rolloff);
+
+	intp->ts_config = p_init->ts_config;
+	if (intp->ts_config == NULL)
+		stv0900_set_ts_parallel_serial(intp,
+				p_init->path1_ts_clock,
+				p_init->path2_ts_clock);
+	else {
+		for (i = 0; intp->ts_config[i].addr != 0xffff; i++)
+			stv0900_write_reg(intp,
+					intp->ts_config[i].addr,
+					intp->ts_config[i].val);
+
+		stv0900_write_bits(intp, F0900_P2_RST_HWARE, 1);
+		stv0900_write_bits(intp, F0900_P2_RST_HWARE, 0);
+		stv0900_write_bits(intp, F0900_P1_RST_HWARE, 1);
+		stv0900_write_bits(intp, F0900_P1_RST_HWARE, 0);
+	}
+
+	intp->tuner_type[0] = p_init->tuner1_type;
+	intp->tuner_type[1] = p_init->tuner2_type;
+	/* tuner init */
+	switch (p_init->tuner1_type) {
+	case 3: /*FE_AUTO_STB6100:*/
+		stv0900_write_reg(intp, R0900_P1_TNRCFG, 0x3c);
+		stv0900_write_reg(intp, R0900_P1_TNRCFG2, 0x86);
+		stv0900_write_reg(intp, R0900_P1_TNRCFG3, 0x18);
+		stv0900_write_reg(intp, R0900_P1_TNRXTAL, 27); /* 27MHz */
+		stv0900_write_reg(intp, R0900_P1_TNRSTEPS, 0x05);
+		stv0900_write_reg(intp, R0900_P1_TNRGAIN, 0x17);
+		stv0900_write_reg(intp, R0900_P1_TNRADJ, 0x1f);
+		stv0900_write_reg(intp, R0900_P1_TNRCTL2, 0x0);
+		stv0900_write_bits(intp, F0900_P1_TUN_TYPE, 3);
+		break;
+	/* case FE_SW_TUNER: */
+	default:
+		stv0900_write_bits(intp, F0900_P1_TUN_TYPE, 6);
+		break;
+	}
+
+	stv0900_write_bits(intp, F0900_P1_TUN_MADDRESS, p_init->tun1_maddress);
+	switch (p_init->tuner1_adc) {
+	case 1:
+		stv0900_write_reg(intp, R0900_TSTTNR1, 0x26);
+		break;
+	default:
+		break;
+	}
+
+	stv0900_write_reg(intp, R0900_P1_TNRLD, 1); /* hw tuner */
+
+	/* tuner init */
+	switch (p_init->tuner2_type) {
+	case 3: /*FE_AUTO_STB6100:*/
+		stv0900_write_reg(intp, R0900_P2_TNRCFG, 0x3c);
+		stv0900_write_reg(intp, R0900_P2_TNRCFG2, 0x86);
+		stv0900_write_reg(intp, R0900_P2_TNRCFG3, 0x18);
+		stv0900_write_reg(intp, R0900_P2_TNRXTAL, 27); /* 27MHz */
+		stv0900_write_reg(intp, R0900_P2_TNRSTEPS, 0x05);
+		stv0900_write_reg(intp, R0900_P2_TNRGAIN, 0x17);
+		stv0900_write_reg(intp, R0900_P2_TNRADJ, 0x1f);
+		stv0900_write_reg(intp, R0900_P2_TNRCTL2, 0x0);
+		stv0900_write_bits(intp, F0900_P2_TUN_TYPE, 3);
+		break;
+	/* case FE_SW_TUNER: */
+	default:
+		stv0900_write_bits(intp, F0900_P2_TUN_TYPE, 6);
+		break;
+	}
+
+	stv0900_write_bits(intp, F0900_P2_TUN_MADDRESS, p_init->tun2_maddress);
+	switch (p_init->tuner2_adc) {
+	case 1:
+		stv0900_write_reg(intp, R0900_TSTTNR3, 0x26);
+		break;
+	default:
+		break;
+	}
+
+	stv0900_write_reg(intp, R0900_P2_TNRLD, 1); /* hw tuner */
+
+	stv0900_write_bits(intp, F0900_P1_TUN_IQSWAP, p_init->tun1_iq_inv);
+	stv0900_write_bits(intp, F0900_P2_TUN_IQSWAP, p_init->tun2_iq_inv);
+	stv0900_set_mclk(intp, 135000000);
+	msleep(3);
+
+	switch (intp->clkmode) {
+	case 0:
+	case 2:
+		stv0900_write_reg(intp, R0900_SYNTCTRL, 0x20 | intp->clkmode);
+		break;
+	default:
+		selosci = 0x02 & stv0900_read_reg(intp, R0900_SYNTCTRL);
+		stv0900_write_reg(intp, R0900_SYNTCTRL, 0x20 | selosci);
+		break;
+	}
+	msleep(3);
+
+	intp->mclk = stv0900_get_mclk_freq(intp, intp->quartz);
+	if (intp->errs)
+		error = STV0900_I2C_ERROR;
+
+	return error;
+}
+
+static int stv0900_status(struct stv0900_internal *intp,
+					enum fe_stv0900_demod_num demod)
+{
+	enum fe_stv0900_search_state demod_state;
+	int locked = FALSE;
+	u8 tsbitrate0_val, tsbitrate1_val;
+	s32 bitrate;
+
+	demod_state = stv0900_get_bits(intp, HEADER_MODE);
+	switch (demod_state) {
+	case STV0900_SEARCH:
+	case STV0900_PLH_DETECTED:
+	default:
+		locked = FALSE;
+		break;
+	case STV0900_DVBS2_FOUND:
+		locked = stv0900_get_bits(intp, LOCK_DEFINITIF) &&
+				stv0900_get_bits(intp, PKTDELIN_LOCK) &&
+				stv0900_get_bits(intp, TSFIFO_LINEOK);
+		break;
+	case STV0900_DVBS_FOUND:
+		locked = stv0900_get_bits(intp, LOCK_DEFINITIF) &&
+				stv0900_get_bits(intp, LOCKEDVIT) &&
+				stv0900_get_bits(intp, TSFIFO_LINEOK);
+		break;
+	}
+
+	dprintk("%s: locked = %d\n", __func__, locked);
+
+	if (stvdebug) {
+		/* Print TS bitrate */
+		tsbitrate0_val = stv0900_read_reg(intp, TSBITRATE0);
+		tsbitrate1_val = stv0900_read_reg(intp, TSBITRATE1);
+		/* Formula Bit rate = Mclk * px_tsfifo_bitrate / 16384 */
+		bitrate = (stv0900_get_mclk_freq(intp, intp->quartz)/1000000)
+			* (tsbitrate1_val << 8 | tsbitrate0_val);
+		bitrate /= 16384;
+		dprintk("TS bitrate = %d Mbit/sec \n", bitrate);
+	};
+
+	return locked;
+}
+
+static enum dvbfe_search stv0900_search(struct dvb_frontend *fe)
+{
+	struct stv0900_state *state = fe->demodulator_priv;
+	struct stv0900_internal *intp = state->internal;
+	enum fe_stv0900_demod_num demod = state->demod;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+
+	struct stv0900_search_params p_search;
+	struct stv0900_signal_info p_result = intp->result[demod];
+
+	enum fe_stv0900_error error = STV0900_NO_ERROR;
+
+	dprintk("%s: ", __func__);
+
+	if (!(INRANGE(100000, c->symbol_rate, 70000000)))
+		return DVBFE_ALGO_SEARCH_FAILED;
+
+	if (state->config->set_ts_params)
+		state->config->set_ts_params(fe, 0);
+
+	p_result.locked = FALSE;
+	p_search.path = 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;
+	/* Speeds up DVB-S searching */
+	if (c->delivery_system == SYS_DVBS)
+		p_search.standard = STV0900_SEARCH_DVBS1;
+
+	intp->srch_standard[demod] = p_search.standard;
+	intp->symbol_rate[demod] = p_search.symbol_rate;
+	intp->srch_range[demod] = p_search.search_range;
+	intp->freq[demod] = p_search.frequency;
+	intp->srch_algo[demod] = p_search.search_algo;
+	intp->srch_iq_inv[demod] = p_search.iq_inversion;
+	intp->fec[demod] = p_search.fec;
+	if ((stv0900_algo(fe) == STV0900_RANGEOK) &&
+				(intp->errs == STV0900_NO_ERROR)) {
+		p_result.locked = intp->result[demod].locked;
+		p_result.standard = intp->result[demod].standard;
+		p_result.frequency = intp->result[demod].frequency;
+		p_result.symbol_rate = intp->result[demod].symbol_rate;
+		p_result.fec = intp->result[demod].fec;
+		p_result.modcode = intp->result[demod].modcode;
+		p_result.pilot = intp->result[demod].pilot;
+		p_result.frame_len = intp->result[demod].frame_len;
+		p_result.spectrum = intp->result[demod].spectrum;
+		p_result.rolloff = intp->result[demod].rolloff;
+		p_result.modulation = intp->result[demod].modulation;
+	} else {
+		p_result.locked = FALSE;
+		switch (intp->err[demod]) {
+		case STV0900_I2C_ERROR:
+			error = STV0900_I2C_ERROR;
+			break;
+		case STV0900_NO_ERROR:
+		default:
+			error = STV0900_SEARCH_FAILED;
+			break;
+		}
+	}
+
+	if ((p_result.locked == TRUE) && (error == STV0900_NO_ERROR)) {
+		dprintk("Search Success\n");
+		return DVBFE_ALGO_SEARCH_SUCCESS;
+	} else {
+		dprintk("Search Fail\n");
+		return DVBFE_ALGO_SEARCH_FAILED;
+	}
+
+}
+
+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;
+		if (state->config->set_lock_led)
+			state->config->set_lock_led(fe, 1);
+	} else {
+		*status = 0;
+		if (state->config->set_lock_led)
+			state->config->set_lock_led(fe, 0);
+		dprintk("DEMOD LOCK FAIL\n");
+	}
+
+	return 0;
+}
+
+static int stv0900_stop_ts(struct dvb_frontend *fe, int stop_ts)
+{
+
+	struct stv0900_state *state = fe->demodulator_priv;
+	struct stv0900_internal *intp = state->internal;
+	enum fe_stv0900_demod_num demod = state->demod;
+
+	if (stop_ts == TRUE)
+		stv0900_write_bits(intp, RST_HWARE, 1);
+	else
+		stv0900_write_bits(intp, RST_HWARE, 0);
+
+	return 0;
+}
+
+static int stv0900_diseqc_init(struct dvb_frontend *fe)
+{
+	struct stv0900_state *state = fe->demodulator_priv;
+	struct stv0900_internal *intp = state->internal;
+	enum fe_stv0900_demod_num demod = state->demod;
+
+	stv0900_write_bits(intp, DISTX_MODE, state->config->diseqc_mode);
+	stv0900_write_bits(intp, DISEQC_RESET, 1);
+	stv0900_write_bits(intp, DISEQC_RESET, 0);
+
+	return 0;
+}
+
+static int stv0900_init(struct dvb_frontend *fe)
+{
+	dprintk("%s\n", __func__);
+
+	stv0900_stop_ts(fe, 1);
+	stv0900_diseqc_init(fe);
+
+	return 0;
+}
+
+static int stv0900_diseqc_send(struct stv0900_internal *intp , u8 *data,
+				u32 NbData, enum fe_stv0900_demod_num demod)
+{
+	s32 i = 0;
+
+	stv0900_write_bits(intp, DIS_PRECHARGE, 1);
+	while (i < NbData) {
+		while (stv0900_get_bits(intp, FIFO_FULL))
+			;/* checkpatch complains */
+		stv0900_write_reg(intp, DISTXDATA, data[i]);
+		i++;
+	}
+
+	stv0900_write_bits(intp, DIS_PRECHARGE, 0);
+	i = 0;
+	while ((stv0900_get_bits(intp, TX_IDLE) != 1) && (i < 10)) {
+		msleep(10);
+		i++;
+	}
+
+	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 *intp = state->internal;
+	enum fe_stv0900_demod_num demod = state->demod;
+	u8 data;
+
+
+	switch (burst) {
+	case SEC_MINI_A:
+		stv0900_write_bits(intp, DISTX_MODE, 3);/* Unmodulated */
+		data = 0x00;
+		stv0900_diseqc_send(intp, &data, 1, state->demod);
+		break;
+	case SEC_MINI_B:
+		stv0900_write_bits(intp, DISTX_MODE, 2);/* Modulated */
+		data = 0xff;
+		stv0900_diseqc_send(intp, &data, 1, state->demod);
+		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 *intp = state->internal;
+	enum fe_stv0900_demod_num demod = state->demod;
+	s32 i = 0;
+
+	reply->msg_len = 0;
+
+	while ((stv0900_get_bits(intp, RX_END) != 1) && (i < 10)) {
+		msleep(10);
+		i++;
+	}
+
+	if (stv0900_get_bits(intp, RX_END)) {
+		reply->msg_len = stv0900_get_bits(intp, FIFO_BYTENBR);
+
+		for (i = 0; i < reply->msg_len; i++)
+			reply->msg[i] = stv0900_read_reg(intp, DISRXDATA);
+	}
+
+	return 0;
+}
+
+static int stv0900_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t toneoff)
+{
+	struct stv0900_state *state = fe->demodulator_priv;
+	struct stv0900_internal *intp = state->internal;
+	enum fe_stv0900_demod_num demod = state->demod;
+
+	dprintk("%s: %s\n", __func__, ((toneoff == 0) ? "On" : "Off"));
+
+	switch (toneoff) {
+	case SEC_TONE_ON:
+		/*Set the DiseqC mode to 22Khz _continues_ tone*/
+		stv0900_write_bits(intp, DISTX_MODE, 0);
+		stv0900_write_bits(intp, DISEQC_RESET, 1);
+		/*release DiseqC reset to enable the 22KHz tone*/
+		stv0900_write_bits(intp, DISEQC_RESET, 0);
+		break;
+	case SEC_TONE_OFF:
+		/*return diseqc mode to config->diseqc_mode.
+		Usually it's without _continues_ tone */
+		stv0900_write_bits(intp, DISTX_MODE,
+				state->config->diseqc_mode);
+		/*maintain the DiseqC reset to disable the 22KHz tone*/
+		stv0900_write_bits(intp, DISEQC_RESET, 1);
+		stv0900_write_bits(intp, DISEQC_RESET, 0);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void stv0900_release(struct dvb_frontend *fe)
+{
+	struct stv0900_state *state = fe->demodulator_priv;
+
+	dprintk("%s\n", __func__);
+
+	if (state->config->set_lock_led)
+		state->config->set_lock_led(fe, 0);
+
+	if ((--(state->internal->dmds_used)) <= 0) {
+
+		dprintk("%s: Actually removing\n", __func__);
+
+		remove_inode(state->internal);
+		kfree(state->internal);
+	}
+
+	kfree(state);
+}
+
+static int stv0900_sleep(struct dvb_frontend *fe)
+{
+	struct stv0900_state *state = fe->demodulator_priv;
+
+	dprintk("%s\n", __func__);
+
+	if (state->config->set_lock_led)
+		state->config->set_lock_led(fe, 0);
+
+	return 0;
+}
+
+static int stv0900_get_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct stv0900_state *state = fe->demodulator_priv;
+	struct stv0900_internal *intp = state->internal;
+	enum fe_stv0900_demod_num demod = state->demod;
+	struct stv0900_signal_info p_result = intp->result[demod];
+
+	p->frequency = p_result.locked ? p_result.frequency : 0;
+	p->symbol_rate = p_result.locked ? p_result.symbol_rate : 0;
+	return 0;
+}
+
+static struct dvb_frontend_ops stv0900_ops = {
+	.delsys = { SYS_DVBS, SYS_DVBS2, SYS_DSS },
+	.info = {
+		.name			= "STV0900 frontend",
+		.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                   = stv0900_get_frontend,
+	.sleep				= stv0900_sleep,
+	.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,
+	.search				= stv0900_search,
+	.read_status			= stv0900_read_status,
+	.read_ber			= stv0900_read_ber,
+	.read_signal_strength		= stv0900_read_signal_strength,
+	.read_snr			= stv0900_read_snr,
+	.read_ucblocks                  = stv0900_read_ucblocks,
+};
+
+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		= config->demod_mode;
+		init_params.rolloff		= STV0900_35;
+		init_params.path1_ts_clock	= config->path1_mode;
+		init_params.tun1_maddress	= config->tun1_maddress;
+		init_params.tun1_iq_inv		= STV0900_IQ_NORMAL;
+		init_params.tuner1_adc		= config->tun1_adc;
+		init_params.tuner1_type		= config->tun1_type;
+		init_params.path2_ts_clock	= config->path2_mode;
+		init_params.ts_config		= config->ts_config_regs;
+		init_params.tun2_maddress	= config->tun2_maddress;
+		init_params.tuner2_adc		= config->tun2_adc;
+		init_params.tuner2_type		= config->tun2_type;
+		init_params.tun2_iq_inv		= 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..b684df9
--- /dev/null
+++ b/drivers/media/dvb-frontends/stv0900_init.h
@@ -0,0 +1,584 @@
+/*
+ * 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 */
+
+};
+
+struct stv0900_short_frames_car_loop_optim_vs_mod {
+	enum fe_stv0900_modulation modulation;
+	u8 car_loop_2;	  /* SR<3msps      */
+	u8 car_loop_5;	  /* 3<SR<=7msps   */
+	u8 car_loop_10;   /* 7<SR<=15msps  */
+	u8 car_loop_20;   /* 10<SR<=25msps */
+	u8 car_loop_30;   /* 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		2Mcut1.2 2Mcut2.0 5Mcut1.2 5Mcut2.0 10Mcut1.2
+			10Mcut2.0 20Mcut1.2 20M_cut2.0 30Mcut1.2 30Mcut2.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 struct stv0900_car_loop_optim FE_STV0900_S2CarLoopCut30[14] = {
+	/*Modcod		2MPon 	2MPoff	5MPon 	5MPoff	10MPon
+				10MPoff	20MPon 	20MPoff	30MPon 	30MPoff	*/
+	{ STV0900_QPSK_12,	0x3C,	0x2C,	0x0C,	0x2C,	0x1B,
+				0x2C,	0x1B,	0x1C,	0x0B, 	0x3B },
+	{ STV0900_QPSK_35,	0x0D,	0x0D,	0x0C,	0x0D,	0x1B,
+				0x3C,	0x1B,	0x1C,	0x0B,	0x3B },
+	{ STV0900_QPSK_23,	0x1D,	0x0D,	0x0C,	0x1D,	0x2B,
+				0x3C,	0x1B,	0x1C,	0x0B,	0x3B },
+	{ STV0900_QPSK_34,	0x1D,	0x1D,	0x0C,	0x1D,	0x2B,
+				0x3C,	0x1B,	0x1C,	0x0B,	0x3B },
+	{ STV0900_QPSK_45,	0x2D,	0x1D,	0x1C,	0x1D,	0x2B,
+				0x3C,	0x2B,	0x0C,	0x1B,	0x3B },
+	{ STV0900_QPSK_56,	0x2D,	0x1D,	0x1C,	0x1D,	0x2B,
+				0x3C,	0x2B,	0x0C,	0x1B,	0x3B },
+	{ STV0900_QPSK_89,	0x3D,	0x2D,	0x1C,	0x1D,	0x3B,
+				0x3C,	0x2B,	0x0C,	0x1B,	0x3B },
+	{ STV0900_QPSK_910,	0x3D,	0x2D,	0x1C,	0x1D,	0x3B,
+				0x3C,	0x2B,	0x0C,	0x1B,	0x3B },
+	{ STV0900_8PSK_35,	0x39,	0x19,	0x39,	0x19,	0x19,
+				0x19,	0x19,	0x19,	0x09,	0x19 },
+	{ STV0900_8PSK_23,	0x2A,	0x39,	0x1A,	0x0A,	0x39,
+				0x0A,	0x29,	0x39,	0x29,	0x0A },
+	{ STV0900_8PSK_34,	0x0B,	0x3A,	0x0B,	0x0B,	0x3A,
+				0x1B,	0x1A,	0x0B,	0x1A,	0x3A },
+	{ STV0900_8PSK_56,	0x0C,	0x1B,	0x3B,	0x2B,	0x1B,
+				0x3B,	0x3A,	0x3B,	0x3A,	0x1B },
+	{ STV0900_8PSK_89,	0x2C,	0x2C,	0x2C,	0x1C,	0x2B,
+				0x0C,	0x0B,	0x3B,	0x0B,	0x1B },
+	{ STV0900_8PSK_910,	0x2C,	0x3C,	0x2C,	0x1C,	0x3B,
+				0x1C,	0x0B,	0x3B,	0x0B,	0x1B }
+};
+
+static	const
+struct stv0900_car_loop_optim FE_STV0900_S2APSKCarLoopCut30[11] = {
+	/*Modcod		2MPon 	2MPoff	5MPon 	5MPoff	10MPon
+				10MPoff	20MPon 	20MPoff	30MPon 	30MPoff	*/
+	{ STV0900_16APSK_23,	0x0A,	0x0A,	0x0A,	0x0A,	0x1A,
+				0x0A,	0x3A,	0x0A,	0x2A,	0x0A },
+	{ STV0900_16APSK_34,	0x0A,	0x0A,	0x0A,	0x0A,	0x0B,
+				0x0A,	0x3B,	0x0A,	0x1B,	0x0A },
+	{ STV0900_16APSK_45,	0x0A,	0x0A,	0x0A,	0x0A,	0x1B,
+				0x0A,	0x3B,	0x0A,	0x2B,	0x0A },
+	{ STV0900_16APSK_56,	0x0A,	0x0A,	0x0A,	0x0A,	0x1B,
+				0x0A,	0x3B,	0x0A,	0x2B,	0x0A },
+	{ STV0900_16APSK_89,	0x0A,	0x0A,	0x0A,	0x0A,	0x2B,
+				0x0A,	0x0C,	0x0A,	0x3B,	0x0A },
+	{ STV0900_16APSK_910,	0x0A,	0x0A,	0x0A,	0x0A,	0x2B,
+				0x0A,	0x0C,	0x0A,	0x3B,	0x0A },
+	{ STV0900_32APSK_34,	0x0A,	0x0A,	0x0A,	0x0A,	0x0A,
+				0x0A,	0x0A,	0x0A,	0x0A,	0x0A },
+	{ STV0900_32APSK_45,	0x0A,	0x0A,	0x0A,	0x0A,	0x0A,
+				0x0A,	0x0A,	0x0A,	0x0A,	0x0A },
+	{ STV0900_32APSK_56,	0x0A,	0x0A,	0x0A,	0x0A,	0x0A,
+				0x0A,	0x0A,	0x0A,	0x0A,	0x0A },
+	{ STV0900_32APSK_89,	0x0A,	0x0A,	0x0A,	0x0A,	0x0A,
+				0x0A,	0x0A,	0x0A,	0x0A,	0x0A },
+	{ STV0900_32APSK_910,	0x0A,	0x0A,	0x0A,	0x0A,	0x0A,
+				0x0A,	0x0A,	0x0A,	0x0A,	0x0A }
+};
+
+static	const
+struct stv0900_car_loop_optim FE_STV0900_S2LowQPCarLoopCut30[3] = {
+	/*Modcod		2MPon 	2MPoff	5MPon 	5MPoff	10MPon
+				10MPoff	20MPon 	20MPoff	30MPon 	30MPoff*/
+	{ STV0900_QPSK_14,	0x0C,	0x3C,	0x0B,	0x3C,	0x2A,
+				0x2C,	0x2A,	0x1C,	0x3A,	0x3B },
+	{ STV0900_QPSK_13,	0x0C,	0x3C,	0x0B,	0x3C,	0x2A,
+				0x2C,	0x3A,	0x0C,	0x3A,	0x2B },
+	{ STV0900_QPSK_25,	0x1C,	0x3C,	0x1B,	0x3C,	0x3A,
+				0x1C,	0x3A,	0x3B,	0x3A,	0x2B }
+};
+
+static	const struct stv0900_short_frames_car_loop_optim_vs_mod
+FE_STV0900_S2ShortCarLoopCut30[4] = {
+	/*Mod		2Mcut3.0 5Mcut3.0 10Mcut3.0 20Mcut3.0 30Mcut3.0*/
+	{ STV0900_QPSK,		0x2C,	0x2B,	0x0B,	0x0B,	0x3A },
+	{ STV0900_8PSK,		0x3B,	0x0B,	0x2A,	0x0A,	0x39 },
+	{ STV0900_16APSK,	0x1B,	0x1B,	0x1B,	0x3A,	0x2A },
+	{ STV0900_32APSK,	0x1B,	0x1B,	0x1B,	0x3A,	0x2A },
+
+};
+
+static const u16 STV0900_InitVal[181][2] = {
+	{ R0900_OUTCFG		, 0x00	},
+	{ 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_RCCFG2		, 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..e0ea74c
--- /dev/null
+++ b/drivers/media/dvb-frontends/stv0900_priv.h
@@ -0,0 +1,408 @@
+/*
+ * 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 dprintk(args...) \
+	do { \
+		if (stvdebug) \
+			printk(KERN_DEBUG args); \
+	} while (0)
+
+#define STV0900_MAXLOOKUPSIZE 500
+#define STV0900_BLIND_SEARCH_AGC2_TH 700
+#define STV0900_BLIND_SEARCH_AGC2_TH_CUT30 1400
+#define IQPOWER_THRESHOLD  30
+
+/* 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;/* Reference,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;
+	int 	tuner1_type;
+
+	/* IQ from the tuner1 to the demod */
+	enum stv0900_iq_inversion	tun1_iq_inv;
+	enum fe_stv0900_clock_type	path2_ts_clock;
+
+	u8	tun2_maddress;
+	int	tuner2_adc;
+	int	tuner2_type;
+
+	/* IQ from the tuner2 to the demod */
+	enum stv0900_iq_inversion	tun2_iq_inv;
+	struct stv0900_reg		*ts_config;
+};
+
+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_len;
+	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;
+
+	/*Demods */
+	s32	freq[2];
+	s32	bw[2];
+	s32	symbol_rate[2];
+	s32	srch_range[2];
+	/* for software/auto tuner */
+	int	tuner_type[2];
+
+	/* algorithm for search Blind, Cold or Warm*/
+	enum fe_stv0900_search_algo	srch_algo[2];
+	/* search standard: Auto, DVBS1/DSS only or DVBS2 only*/
+	enum fe_stv0900_search_standard	srch_standard[2];
+	/* inversion search : auto, auto norma first, normal or inverted */
+	enum fe_stv0900_search_iq	srch_iq_inv[2];
+	enum fe_stv0900_modcode		modcode[2];
+	enum fe_stv0900_modulation	modulation[2];
+	enum fe_stv0900_fec		fec[2];
+
+	struct stv0900_signal_info	result[2];
+	enum fe_stv0900_error		err[2];
+
+
+	struct i2c_adapter	*i2c_adap;
+	u8			i2c_addr;
+	u8			clkmode;/* 0 for CLKI, 2 for XTALI */
+	u8			chip_id;
+	struct stv0900_reg	*ts_config;
+	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 int stvdebug;
+
+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_modcod(struct stv0900_internal *i_params,
+				enum fe_stv0900_demod_num demod);
+
+extern void stv0900_activate_s2_modcod_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);
+
+extern u32
+stv0900_get_freq_auto(struct stv0900_internal *intp, int demod);
+
+extern void
+stv0900_set_tuner_auto(struct stv0900_internal *intp, u32 Frequency,
+						u32 Bandwidth, int 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..731afe9
--- /dev/null
+++ b/drivers/media/dvb-frontends/stv0900_reg.h
@@ -0,0 +1,3981 @@
+/*
+ * 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
+
+extern s32 shiftx(s32 x, int demod, s32 shift);
+
+#define REGx(x) shiftx(x, demod, 0x200)
+#define FLDx(x) shiftx(x, demod, 0x2000000)
+
+/*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_OUTSERRS1_HZ 0xf11c0040
+#define F0900_OUTSERRS2_HZ 0xf11c0020
+#define F0900_OUTSERRS3_HZ 0xf11c0010
+#define F0900_OUTPARRS3_HZ 0xf11c0008
+
+/*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_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_I2C_FASTMODE 0xf1290008
+#define F0900_I2CADDR_INC 0xf1290003
+
+/*P1_I2CRPT*/
+#define R0900_P1_I2CRPT 0xf12a
+#define I2CRPT shiftx(R0900_P1_I2CRPT, demod, -1)
+#define F0900_P1_I2CT_ON 0xf12a0080
+#define I2CT_ON shiftx(F0900_P1_I2CT_ON, demod, -0x10000)
+#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
+
+/*IOPVALUE6*/
+#define R0900_IOPVALUE6 0xf138
+#define F0900_VSCL 0xf1380004
+#define F0900_VSDA 0xf1380002
+#define F0900_VDATA3_0 0xf1380001
+
+/*IOPVALUE5*/
+#define R0900_IOPVALUE5 0xf139
+#define F0900_VDATA3_1 0xf1390080
+#define F0900_VDATA3_2 0xf1390040
+#define F0900_VDATA3_3 0xf1390020
+#define F0900_VDATA3_4 0xf1390010
+#define F0900_VDATA3_5 0xf1390008
+#define F0900_VDATA3_6 0xf1390004
+#define F0900_VDATA3_7 0xf1390002
+#define F0900_VCLKOUT3 0xf1390001
+
+/*IOPVALUE4*/
+#define R0900_IOPVALUE4 0xf13a
+#define F0900_VSTROUT3 0xf13a0080
+#define F0900_VDPN3 0xf13a0040
+#define F0900_VERROR3 0xf13a0020
+#define F0900_VDATA2_7 0xf13a0010
+#define F0900_VCLKOUT2 0xf13a0008
+#define F0900_VSTROUT2 0xf13a0004
+#define F0900_VDPN2 0xf13a0002
+#define F0900_VERROR2 0xf13a0001
+
+/*IOPVALUE3*/
+#define R0900_IOPVALUE3 0xf13b
+#define F0900_VDATA1_7 0xf13b0080
+#define F0900_VCLKOUT1 0xf13b0040
+#define F0900_VSTROUT1 0xf13b0020
+#define F0900_VDPN1 0xf13b0010
+#define F0900_VERROR1 0xf13b0008
+#define F0900_VCLKOUT27 0xf13b0004
+#define F0900_VDISEQCOUT2 0xf13b0002
+#define F0900_VSCLT2 0xf13b0001
+
+/*IOPVALUE2*/
+#define R0900_IOPVALUE2 0xf13c
+#define F0900_VSDAT2 0xf13c0080
+#define F0900_VAGCRF2 0xf13c0040
+#define F0900_VDISEQCOUT1 0xf13c0020
+#define F0900_VSCLT1 0xf13c0010
+#define F0900_VSDAT1 0xf13c0008
+#define F0900_VAGCRF1 0xf13c0004
+#define F0900_VDIRCLK 0xf13c0002
+#define F0900_VSTDBY 0xf13c0001
+
+/*IOPVALUE1*/
+#define R0900_IOPVALUE1 0xf13d
+#define F0900_VCS1 0xf13d0080
+#define F0900_VCS0 0xf13d0040
+#define F0900_VGPIO13 0xf13d0020
+#define F0900_VGPIO12 0xf13d0010
+#define F0900_VGPIO11 0xf13d0008
+#define F0900_VGPIO10 0xf13d0004
+#define F0900_VGPIO9 0xf13d0002
+#define F0900_VGPIO8 0xf13d0001
+
+/*IOPVALUE0*/
+#define R0900_IOPVALUE0 0xf13e
+#define F0900_VGPIO7 0xf13e0080
+#define F0900_VGPIO6 0xf13e0040
+#define F0900_VGPIO5 0xf13e0020
+#define F0900_VGPIO4 0xf13e0010
+#define F0900_VGPIO3 0xf13e0008
+#define F0900_VGPIO2 0xf13e0004
+#define F0900_VGPIO1 0xf13e0002
+#define F0900_VCLKI2 0xf13e0001
+
+/*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
+
+/*STRSTATUS1*/
+#define R0900_STRSTATUS1 0xf16a
+#define F0900_STRSTATUS_SEL2 0xf16a00f0
+#define F0900_STRSTATUS_SEL1 0xf16a000f
+
+/*STRSTATUS2*/
+#define R0900_STRSTATUS2 0xf16b
+#define F0900_STRSTATUS_SEL4 0xf16b00f0
+#define F0900_STRSTATUS_SEL3 0xf16b000f
+
+/*STRSTATUS3*/
+#define R0900_STRSTATUS3 0xf16c
+#define F0900_STRSTATUS_SEL6 0xf16c00f0
+#define F0900_STRSTATUS_SEL5 0xf16c000f
+
+/*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_SELECT0 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_PRESC 0xf19c0007
+
+/*P2_ACRDIV*/
+#define R0900_P2_ACRDIV 0xf19d
+#define F0900_P2_ACR_DIV 0xf19d00ff
+
+/*P1_DISTXCTL*/
+#define R0900_P1_DISTXCTL 0xf1a0
+#define DISTXCTL shiftx(R0900_P1_DISTXCTL, demod, 0x10)
+#define F0900_P1_TIM_OFF 0xf1a00080
+#define F0900_P1_DISEQC_RESET 0xf1a00040
+#define DISEQC_RESET shiftx(F0900_P1_DISEQC_RESET, demod, 0x100000)
+#define F0900_P1_TIM_CMD 0xf1a00030
+#define F0900_P1_DIS_PRECHARGE 0xf1a00008
+#define DIS_PRECHARGE shiftx(F0900_P1_DIS_PRECHARGE, demod, 0x100000)
+#define F0900_P1_DISTX_MODE 0xf1a00007
+#define DISTX_MODE shiftx(F0900_P1_DISTX_MODE, demod, 0x100000)
+
+/*P1_DISRXCTL*/
+#define R0900_P1_DISRXCTL 0xf1a1
+#define DISRXCTL shiftx(R0900_P1_DISRXCTL, demod, 0x10)
+#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_SELECT0 0xf1a1000c
+#define F0900_P1_IRQ_RXEND 0xf1a10002
+#define F0900_P1_IRQ_4NBYTES 0xf1a10001
+
+/*P1_DISRX_ST0*/
+#define R0900_P1_DISRX_ST0 0xf1a4
+#define DISRX_ST0 shiftx(R0900_P1_DISRX_ST0, demod, 0x10)
+#define F0900_P1_RX_END 0xf1a40080
+#define RX_END shiftx(F0900_P1_RX_END, demod, 0x100000)
+#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 DISRX_ST1 shiftx(R0900_P1_DISRX_ST1, demod, 0x10)
+#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
+#define FIFO_BYTENBR shiftx(F0900_P1_FIFO_BYTENBR, demod, 0x100000)
+
+/*P1_DISRXDATA*/
+#define R0900_P1_DISRXDATA 0xf1a6
+#define DISRXDATA shiftx(R0900_P1_DISRXDATA, demod, 0x10)
+#define F0900_P1_DISRX_DATA 0xf1a600ff
+
+/*P1_DISTXDATA*/
+#define R0900_P1_DISTXDATA 0xf1a7
+#define DISTXDATA shiftx(R0900_P1_DISTXDATA, demod, 0x10)
+#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 FIFO_FULL shiftx(F0900_P1_FIFO_FULL, demod, 0x100000)
+#define F0900_P1_TX_IDLE 0xf1a80020
+#define TX_IDLE shiftx(F0900_P1_TX_IDLE, demod, 0x100000)
+#define F0900_P1_GAP_BURST 0xf1a80010
+#define F0900_P1_TXFIFO_BYTES 0xf1a8000f
+
+/*P1_F22TX*/
+#define R0900_P1_F22TX 0xf1a9
+#define F22TX shiftx(R0900_P1_F22TX, demod, 0x10)
+#define F0900_P1_F22_REG 0xf1a900ff
+
+/*P1_F22RX*/
+#define R0900_P1_F22RX 0xf1aa
+#define F22RX shiftx(R0900_P1_F22RX, demod, 0x10)
+#define F0900_P1_F22RX_REG 0xf1aa00ff
+
+/*P1_ACRPRESC*/
+#define R0900_P1_ACRPRESC 0xf1ac
+#define ACRPRESC shiftx(R0900_P1_ACRPRESC, demod, 0x10)
+#define F0900_P1_ACR_PRESC 0xf1ac0007
+
+/*P1_ACRDIV*/
+#define R0900_P1_ACRDIV 0xf1ad
+#define ACRDIV shiftx(R0900_P1_ACRDIV, demod, 0x10)
+#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_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_SEL_FSKCKDIV 0xf1b70004
+#define F0900_INV_CLKFSK 0xf1b70002
+#define F0900_BYPASS_APPLI 0xf1b70001
+
+/*PLLSTAT*/
+#define R0900_PLLSTAT 0xf1b8
+#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 STOP_CLKVIT shiftx(F0900_STOP_CLKVIT1, demod, -2)
+#define F0900_STOP_CLKTS 0xf1c30001
+
+/*TSTTNR0*/
+#define R0900_TSTTNR0 0xf1df
+#define F0900_SEL_FSK 0xf1df0080
+#define F0900_FSK_PON 0xf1df0004
+
+/*TSTTNR1*/
+#define R0900_TSTTNR1 0xf1e0
+#define F0900_ADC1_PON 0xf1e00002
+#define F0900_ADC1_INMODE 0xf1e00001
+
+/*TSTTNR2*/
+#define R0900_TSTTNR2 0xf1e1
+#define F0900_DISEQC1_PON 0xf1e10020
+
+/*TSTTNR3*/
+#define R0900_TSTTNR3 0xf1e2
+#define F0900_ADC2_PON 0xf1e20002
+#define F0900_ADC2_INMODE 0xf1e20001
+
+/*TSTTNR4*/
+#define R0900_TSTTNR4 0xf1e3
+#define F0900_DISEQC2_PON 0xf1e30020
+
+/*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
+
+/*P2_AGC1CN*/
+#define R0900_P2_AGC1CN 0xf206
+#define F0900_P2_AGC1_LOCKED 0xf2060080
+#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_MANUALS2_ROLLOFF 0xf2100080
+#define F0900_P2_SPECINV_CONTROL 0xf2100030
+#define F0900_P2_FORCE_ENASAMP 0xf2100008
+#define F0900_P2_MANUALSX_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_LOCK_DEFINITIF 0xf2120008
+#define F0900_P2_OVADC_DETECT 0xf2120001
+
+/*P2_DSTATUS2*/
+#define R0900_P2_DSTATUS2 0xf213
+#define F0900_P2_DEMOD_DELOCK 0xf2130080
+#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_SCAN_ENABLE 0xf2140010
+#define F0900_P2_CFR_AUTOSCAN 0xf2140008
+#define F0900_P2_TUN_RNG 0xf2140003
+
+/*P2_DMDCFG2*/
+#define R0900_P2_DMDCFG2 0xf215
+#define F0900_P2_S1S2_SEQUENTIAL 0xf2150040
+#define F0900_P2_INFINITE_RELOCK 0xf2150010
+
+/*P2_DMDISTATE*/
+#define R0900_P2_DMDISTATE 0xf216
+#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_HEADER_MODE 0xf21b0060
+
+/*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_DEMOD_CFGMODE 0xf21d0060
+
+/*P2_DMDCFG3*/
+#define R0900_P2_DMDCFG3 0xf21e
+#define F0900_P2_NOSTOP_FIFOFULL 0xf21e0008
+
+/*P2_DMDCFG4*/
+#define R0900_P2_DMDCFG4 0xf21f
+#define F0900_P2_TUNER_NRELAUNCH 0xf21f0008
+
+/*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_DMDREG*/
+#define R0900_P2_DMDREG 0xf225
+#define F0900_P2_DECIM_PLFRAMES 0xf2250001
+
+/*P2_AGC2O*/
+#define R0900_P2_AGC2O 0xf22c
+#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_AGC1_ADJUSTED 0xf22e007f
+
+/*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_ROTAON 0xf2380004
+#define F0900_P2_PH_DET_ALGO 0xf2380003
+
+/*P2_ACLC*/
+#define R0900_P2_ACLC 0xf239
+#define F0900_P2_CAR_ALPHA_MANT 0xf2390030
+#define F0900_P2_CAR_ALPHA_EXP 0xf239000f
+
+/*P2_BCLC*/
+#define R0900_P2_BCLC 0xf23a
+#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_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 0xf24a003f
+
+/*P2_CFRINC0*/
+#define R0900_P2_CFRINC0 0xf24b
+#define F0900_P2_CFR_INC0 0xf24b00f8
+
+/*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_DO_TIMING_CORR 0xf2500010
+#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_SFRRATIO_FINE 0xf25a0001
+
+/*P2_KREFTMG2*/
+#define R0900_P2_KREFTMG2 0xf25b
+#define F0900_P2_KREF_TMG2 0xf25b00ff
+
+/*P2_SFRINIT1*/
+#define R0900_P2_SFRINIT1 0xf25e
+#define F0900_P2_SFR_INIT1 0xf25e007f
+
+/*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
+
+/*P2_EQUALCFG*/
+#define R0900_P2_EQUALCFG 0xf26f
+#define F0900_P2_EQUAL_ON 0xf26f0040
+#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_CARRIER3_DISABLE 0xf2900040
+#define F0900_P2_ROTA2ON 0xf2900004
+#define F0900_P2_PH_DET_ALGO2 0xf2900003
+
+/*P2_CFR2CFR1*/
+#define R0900_P2_CFR2CFR1 0xf291
+#define F0900_P2_CFR2TOCFR1_DVBS1 0xf29100c0
+#define F0900_P2_EN_S2CAR2CENTER 0xf2910020
+#define F0900_P2_DIS_BCHERRCFR2 0xf2910010
+#define F0900_P2_CFR2TOCFR1_BETA 0xf2910007
+
+/*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_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_8_ALPH_M 0xf2980030
+#define F0900_P2_CAR2S2_8_ALPH_E 0xf298000f
+
+/*P2_ACLC2S216A*/
+#define R0900_P2_ACLC2S216A 0xf299
+#define F0900_P2_DIS_C3STOPA2 0xf2990080
+#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_CAR2S2_Q_BETA_M 0xf29c0030
+#define F0900_P2_CAR2S2_Q_BETA_E 0xf29c000f
+
+/*P2_BCLC2S28*/
+#define R0900_P2_BCLC2S28 0xf29d
+#define F0900_P2_CAR2S2_8_BETA_M 0xf29d0030
+#define F0900_P2_CAR2S2_8_BETA_E 0xf29d000f
+
+/*P2_BCLC2S216A*/
+#define R0900_P2_BCLC2S216A 0xf29e
+
+/*P2_BCLC2S232A*/
+#define R0900_P2_BCLC2S232A 0xf29f
+
+/*P2_PLROOT2*/
+#define R0900_P2_PLROOT2 0xf2ac
+#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
+
+/*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
+
+/*P2_GAUSSR0*/
+#define R0900_P2_GAUSSR0 0xf2c0
+#define F0900_P2_EN_CCIMODE 0xf2c00080
+#define F0900_P2_R0_GAUSSIEN 0xf2c0007f
+
+/*P2_CCIR0*/
+#define R0900_P2_CCIR0 0xf2c1
+#define F0900_P2_CCIDETECT_PLHONLY 0xf2c10080
+#define F0900_P2_R0_CCI 0xf2c1007f
+
+/*P2_CCIQUANT*/
+#define R0900_P2_CCIQUANT 0xf2c2
+#define F0900_P2_CCI_BETA 0xf2c200e0
+#define F0900_P2_CCI_QUANT 0xf2c2001f
+
+/*P2_CCITHRES*/
+#define R0900_P2_CCITHRES 0xf2c3
+#define F0900_P2_CCI_THRESHOLD 0xf2c300ff
+
+/*P2_CCIACC*/
+#define R0900_P2_CCIACC 0xf2c4
+#define F0900_P2_CCI_VALUE 0xf2c400ff
+
+/*P2_DMDRESCFG*/
+#define R0900_P2_DMDRESCFG 0xf2c6
+#define F0900_P2_DMDRES_RESET 0xf2c60080
+#define F0900_P2_DMDRES_STRALL 0xf2c60008
+#define F0900_P2_DMDRES_NEWONLY 0xf2c60004
+#define F0900_P2_DMDRES_NOSTORE 0xf2c60002
+
+/*P2_DMDRESADR*/
+#define R0900_P2_DMDRESADR 0xf2c7
+#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_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_DIS_BWCALC 0xf2e10004
+#define F0900_P2_SHORT_WAITSTATES 0xf2e10002
+
+/*P2_TNRXTAL*/
+#define R0900_P2_TNRXTAL 0xf2e4
+#define F0900_P2_TUN_XTALFREQ 0xf2e4001f
+
+/*P2_TNRSTEPS*/
+#define R0900_P2_TNRSTEPS 0xf2e7
+#define F0900_P2_TUNER_BW0P125 0xf2e70080
+#define F0900_P2_BWINC_OFFSET 0xf2e70170
+#define F0900_P2_SOFTSTEP_RNG 0xf2e70008
+#define F0900_P2_TUN_BWOFFSET 0xf2e70007
+
+/*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_CALTIME 0xf2ec0040
+
+/*P2_TNRCTL2*/
+#define R0900_P2_TNRCTL2 0xf2ed
+#define F0900_P2_STB61X0_RCCKOFF 0xf2ed0080
+#define F0900_P2_STB61X0_ICP_SDOFF 0xf2ed0040
+#define F0900_P2_STB61X0_DCLOOPOFF 0xf2ed0020
+#define F0900_P2_STB61X0_REFOUTSEL 0xf2ed0010
+#define F0900_P2_STB61X0_CALOFF 0xf2ed0008
+#define F0900_P2_STB6XX0_LPT_BEN 0xf2ed0004
+#define F0900_P2_STB6XX0_RX_OSCP 0xf2ed0002
+#define F0900_P2_STB6XX0_SYN 0xf2ed0001
+
+/*P2_TNRCFG3*/
+#define R0900_P2_TNRCFG3 0xf2ee
+#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_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_NCO2MAX1*/
+#define R0900_P2_NCO2MAX1 0xf314
+#define F0900_P2_TETA2_MAXVABS1 0xf31400ff
+
+/*P2_NCO2MAX0*/
+#define R0900_P2_NCO2MAX0 0xf315
+#define F0900_P2_TETA2_MAXVABS0 0xf31500ff
+
+/*P2_NCO2FR1*/
+#define R0900_P2_NCO2FR1 0xf316
+#define F0900_P2_NCO2FINAL_ANGLE1 0xf31600ff
+
+/*P2_NCO2FR0*/
+#define R0900_P2_NCO2FR0 0xf317
+#define F0900_P2_NCO2FINAL_ANGLE0 0xf31700ff
+
+/*P2_CFR2AVRGE1*/
+#define R0900_P2_CFR2AVRGE1 0xf318
+#define F0900_P2_I2C_CFR2AVERAGE1 0xf31800ff
+
+/*P2_CFR2AVRGE0*/
+#define R0900_P2_CFR2AVRGE0 0xf319
+#define F0900_P2_I2C_CFR2AVERAGE0 0xf31900ff
+
+/*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_NSLOWSN_LOCKED 0xf3320008
+#define F0900_P2_DIS_RSFLOCK 0xf3320002
+
+/*P2_FECM*/
+#define R0900_P2_FECM 0xf333
+#define F0900_P2_DSS_DVB 0xf3330080
+#define F0900_P2_DSS_SRCH 0xf3330010
+#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_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_PRFVIT 0xf33e0010
+#define F0900_P2_LOCKEDVIT 0xf33e0008
+
+/*P2_VTHINUSE*/
+#define R0900_P2_VTHINUSE 0xf33f
+#define F0900_P2_VIT_INUSE 0xf33f00ff
+
+/*P2_KDIV12*/
+#define R0900_P2_KDIV12 0xf340
+#define F0900_P2_K_DIVIDER_12 0xf340007f
+
+/*P2_KDIV23*/
+#define R0900_P2_KDIV23 0xf341
+#define F0900_P2_K_DIVIDER_23 0xf341007f
+
+/*P2_KDIV34*/
+#define R0900_P2_KDIV34 0xf342
+#define F0900_P2_K_DIVIDER_34 0xf342007f
+
+/*P2_KDIV56*/
+#define R0900_P2_KDIV56 0xf343
+#define F0900_P2_K_DIVIDER_56 0xf343007f
+
+/*P2_KDIV67*/
+#define R0900_P2_KDIV67 0xf344
+#define F0900_P2_K_DIVIDER_67 0xf344007f
+
+/*P2_KDIV78*/
+#define R0900_P2_KDIV78 0xf345
+#define F0900_P2_K_DIVIDER_78 0xf345007f
+
+/*P2_PDELCTRL1*/
+#define R0900_P2_PDELCTRL1 0xf350
+#define F0900_P2_INV_MISMASK 0xf3500080
+#define F0900_P2_FILTER_EN 0xf3500020
+#define F0900_P2_EN_MIS00 0xf3500002
+#define F0900_P2_ALGOSWRST 0xf3500001
+
+/*P2_PDELCTRL2*/
+#define R0900_P2_PDELCTRL2 0xf351
+#define F0900_P2_RESET_UPKO_COUNT 0xf3510040
+#define F0900_P2_FRAME_MODE 0xf3510002
+#define F0900_P2_NOBCHERRFLG_USE 0xf3510001
+
+/*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_PKTDELIN_LOCK 0xf3690002
+#define F0900_P2_FIRST_LOCK 0xf3690001
+
+/*P2_PDELSTATUS2*/
+#define R0900_P2_PDELSTATUS2 0xf36a
+#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_PDELCTRL3*/
+#define R0900_P2_PDELCTRL3 0xf36f
+#define F0900_P2_PKTDEL_CONTFAIL 0xf36f0080
+#define F0900_P2_NOFIFO_BCHERR 0xf36f0020
+
+/*P2_TSSTATEM*/
+#define R0900_P2_TSSTATEM 0xf370
+#define F0900_P2_TSDIL_ON 0xf3700080
+#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_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_DPUNACT 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_BITSPEED 0xf3740003
+
+/*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_TSDIVN*/
+#define R0900_P2_TSDIVN 0xf379
+#define F0900_P2_TSFIFO_SPEEDMODE 0xf37900c0
+
+/*P2_TSCFG4*/
+#define R0900_P2_TSCFG4 0xf37a
+#define F0900_P2_TSFIFO_TSSPEEDMODE 0xf37a00c0
+
+/*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_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_SCRAMBDETECT 0xf3820002
+
+/*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_BERMETER_DATAMODE 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_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_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_FSPYBER_SYNCBYTE 0xf3b20010
+#define F0900_P2_FSPYBER_UNSYNC 0xf3b20008
+#define F0900_P2_FSPYBER_CTIME 0xf3b20007
+
+/*P1_IQCONST*/
+#define R0900_P1_IQCONST 0xf400
+#define IQCONST REGx(R0900_P1_IQCONST)
+#define F0900_P1_CONSTEL_SELECT 0xf4000060
+#define F0900_P1_IQSYMB_SEL 0xf400001f
+
+/*P1_NOSCFG*/
+#define R0900_P1_NOSCFG 0xf401
+#define NOSCFG REGx(R0900_P1_NOSCFG)
+#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 ISYMB REGx(R0900_P1_ISYMB)
+#define F0900_P1_I_SYMBOL 0xf40201ff
+
+/*P1_QSYMB*/
+#define R0900_P1_QSYMB 0xf403
+#define QSYMB REGx(R0900_P1_QSYMB)
+#define F0900_P1_Q_SYMBOL 0xf40301ff
+
+/*P1_AGC1CFG*/
+#define R0900_P1_AGC1CFG 0xf404
+#define AGC1CFG REGx(R0900_P1_AGC1CFG)
+#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
+
+/*P1_AGC1CN*/
+#define R0900_P1_AGC1CN 0xf406
+#define AGC1CN REGx(R0900_P1_AGC1CN)
+#define F0900_P1_AGC1_LOCKED 0xf4060080
+#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 AGC1REF REGx(R0900_P1_AGC1REF)
+#define F0900_P1_AGCIQ_REF 0xf40700ff
+
+/*P1_IDCCOMP*/
+#define R0900_P1_IDCCOMP 0xf408
+#define IDCCOMP REGx(R0900_P1_IDCCOMP)
+#define F0900_P1_IAVERAGE_ADJ 0xf40801ff
+
+/*P1_QDCCOMP*/
+#define R0900_P1_QDCCOMP 0xf409
+#define QDCCOMP REGx(R0900_P1_QDCCOMP)
+#define F0900_P1_QAVERAGE_ADJ 0xf40901ff
+
+/*P1_POWERI*/
+#define R0900_P1_POWERI 0xf40a
+#define POWERI REGx(R0900_P1_POWERI)
+#define F0900_P1_POWER_I 0xf40a00ff
+#define POWER_I FLDx(F0900_P1_POWER_I)
+
+/*P1_POWERQ*/
+#define R0900_P1_POWERQ 0xf40b
+#define POWERQ REGx(R0900_P1_POWERQ)
+#define F0900_P1_POWER_Q 0xf40b00ff
+#define POWER_Q FLDx(F0900_P1_POWER_Q)
+
+/*P1_AGC1AMM*/
+#define R0900_P1_AGC1AMM 0xf40c
+#define AGC1AMM REGx(R0900_P1_AGC1AMM)
+#define F0900_P1_AMM_VALUE 0xf40c00ff
+
+/*P1_AGC1QUAD*/
+#define R0900_P1_AGC1QUAD 0xf40d
+#define AGC1QUAD REGx(R0900_P1_AGC1QUAD)
+#define F0900_P1_QUAD_VALUE 0xf40d01ff
+
+/*P1_AGCIQIN1*/
+#define R0900_P1_AGCIQIN1 0xf40e
+#define AGCIQIN1 REGx(R0900_P1_AGCIQIN1)
+#define F0900_P1_AGCIQ_VALUE1 0xf40e00ff
+#define AGCIQ_VALUE1 FLDx(F0900_P1_AGCIQ_VALUE1)
+
+/*P1_AGCIQIN0*/
+#define R0900_P1_AGCIQIN0 0xf40f
+#define AGCIQIN0 REGx(R0900_P1_AGCIQIN0)
+#define F0900_P1_AGCIQ_VALUE0 0xf40f00ff
+#define AGCIQ_VALUE0 FLDx(F0900_P1_AGCIQ_VALUE0)
+
+/*P1_DEMOD*/
+#define R0900_P1_DEMOD 0xf410
+#define DEMOD REGx(R0900_P1_DEMOD)
+#define F0900_P1_MANUALS2_ROLLOFF 0xf4100080
+#define MANUALS2_ROLLOFF FLDx(F0900_P1_MANUALS2_ROLLOFF)
+
+#define F0900_P1_SPECINV_CONTROL 0xf4100030
+#define SPECINV_CONTROL FLDx(F0900_P1_SPECINV_CONTROL)
+#define F0900_P1_FORCE_ENASAMP 0xf4100008
+#define F0900_P1_MANUALSX_ROLLOFF 0xf4100004
+#define MANUALSX_ROLLOFF FLDx(F0900_P1_MANUALSX_ROLLOFF)
+#define F0900_P1_ROLLOFF_CONTROL 0xf4100003
+#define ROLLOFF_CONTROL FLDx(F0900_P1_ROLLOFF_CONTROL)
+
+/*P1_DMDMODCOD*/
+#define R0900_P1_DMDMODCOD 0xf411
+#define DMDMODCOD REGx(R0900_P1_DMDMODCOD)
+#define F0900_P1_MANUAL_MODCOD 0xf4110080
+#define F0900_P1_DEMOD_MODCOD 0xf411007c
+#define DEMOD_MODCOD FLDx(F0900_P1_DEMOD_MODCOD)
+#define F0900_P1_DEMOD_TYPE 0xf4110003
+#define DEMOD_TYPE FLDx(F0900_P1_DEMOD_TYPE)
+
+/*P1_DSTATUS*/
+#define R0900_P1_DSTATUS 0xf412
+#define DSTATUS REGx(R0900_P1_DSTATUS)
+#define F0900_P1_CAR_LOCK 0xf4120080
+#define F0900_P1_TMGLOCK_QUALITY 0xf4120060
+#define TMGLOCK_QUALITY FLDx(F0900_P1_TMGLOCK_QUALITY)
+#define F0900_P1_LOCK_DEFINITIF 0xf4120008
+#define LOCK_DEFINITIF FLDx(F0900_P1_LOCK_DEFINITIF)
+#define F0900_P1_OVADC_DETECT 0xf4120001
+
+/*P1_DSTATUS2*/
+#define R0900_P1_DSTATUS2 0xf413
+#define DSTATUS2 REGx(R0900_P1_DSTATUS2)
+#define F0900_P1_DEMOD_DELOCK 0xf4130080
+#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 DMDCFGMD REGx(R0900_P1_DMDCFGMD)
+#define F0900_P1_DVBS2_ENABLE 0xf4140080
+#define DVBS2_ENABLE FLDx(F0900_P1_DVBS2_ENABLE)
+#define F0900_P1_DVBS1_ENABLE 0xf4140040
+#define DVBS1_ENABLE FLDx(F0900_P1_DVBS1_ENABLE)
+#define F0900_P1_SCAN_ENABLE 0xf4140010
+#define SCAN_ENABLE FLDx(F0900_P1_SCAN_ENABLE)
+#define F0900_P1_CFR_AUTOSCAN 0xf4140008
+#define CFR_AUTOSCAN FLDx(F0900_P1_CFR_AUTOSCAN)
+#define F0900_P1_TUN_RNG 0xf4140003
+
+/*P1_DMDCFG2*/
+#define R0900_P1_DMDCFG2 0xf415
+#define DMDCFG2 REGx(R0900_P1_DMDCFG2)
+#define F0900_P1_S1S2_SEQUENTIAL 0xf4150040
+#define S1S2_SEQUENTIAL FLDx(F0900_P1_S1S2_SEQUENTIAL)
+#define F0900_P1_INFINITE_RELOCK 0xf4150010
+
+/*P1_DMDISTATE*/
+#define R0900_P1_DMDISTATE 0xf416
+#define DMDISTATE REGx(R0900_P1_DMDISTATE)
+#define F0900_P1_I2C_DEMOD_MODE 0xf416001f
+#define DEMOD_MODE FLDx(F0900_P1_I2C_DEMOD_MODE)
+
+/*P1_DMDT0M*/
+#define R0900_P1_DMDT0M 0xf417
+#define DMDT0M REGx(R0900_P1_DMDT0M)
+#define F0900_P1_DMDT0_MIN 0xf41700ff
+
+/*P1_DMDSTATE*/
+#define R0900_P1_DMDSTATE 0xf41b
+#define DMDSTATE REGx(R0900_P1_DMDSTATE)
+#define F0900_P1_HEADER_MODE 0xf41b0060
+#define HEADER_MODE FLDx(F0900_P1_HEADER_MODE)
+
+/*P1_DMDFLYW*/
+#define R0900_P1_DMDFLYW 0xf41c
+#define DMDFLYW REGx(R0900_P1_DMDFLYW)
+#define F0900_P1_I2C_IRQVAL 0xf41c00f0
+#define F0900_P1_FLYWHEEL_CPT 0xf41c000f
+#define FLYWHEEL_CPT FLDx(F0900_P1_FLYWHEEL_CPT)
+
+/*P1_DSTATUS3*/
+#define R0900_P1_DSTATUS3 0xf41d
+#define DSTATUS3 REGx(R0900_P1_DSTATUS3)
+#define F0900_P1_DEMOD_CFGMODE 0xf41d0060
+
+/*P1_DMDCFG3*/
+#define R0900_P1_DMDCFG3 0xf41e
+#define DMDCFG3 REGx(R0900_P1_DMDCFG3)
+#define F0900_P1_NOSTOP_FIFOFULL 0xf41e0008
+
+/*P1_DMDCFG4*/
+#define R0900_P1_DMDCFG4 0xf41f
+#define DMDCFG4 REGx(R0900_P1_DMDCFG4)
+#define F0900_P1_TUNER_NRELAUNCH 0xf41f0008
+
+/*P1_CORRELMANT*/
+#define R0900_P1_CORRELMANT 0xf420
+#define CORRELMANT REGx(R0900_P1_CORRELMANT)
+#define F0900_P1_CORREL_MANT 0xf42000ff
+
+/*P1_CORRELABS*/
+#define R0900_P1_CORRELABS 0xf421
+#define CORRELABS REGx(R0900_P1_CORRELABS)
+#define F0900_P1_CORREL_ABS 0xf42100ff
+
+/*P1_CORRELEXP*/
+#define R0900_P1_CORRELEXP 0xf422
+#define CORRELEXP REGx(R0900_P1_CORRELEXP)
+#define F0900_P1_CORREL_ABSEXP 0xf42200f0
+#define F0900_P1_CORREL_EXP 0xf422000f
+
+/*P1_PLHMODCOD*/
+#define R0900_P1_PLHMODCOD 0xf424
+#define PLHMODCOD REGx(R0900_P1_PLHMODCOD)
+#define F0900_P1_SPECINV_DEMOD 0xf4240080
+#define SPECINV_DEMOD FLDx(F0900_P1_SPECINV_DEMOD)
+#define F0900_P1_PLH_MODCOD 0xf424007c
+#define F0900_P1_PLH_TYPE 0xf4240003
+
+/*P1_DMDREG*/
+#define R0900_P1_DMDREG 0xf425
+#define DMDREG REGx(R0900_P1_DMDREG)
+#define F0900_P1_DECIM_PLFRAMES 0xf4250001
+
+/*P1_AGC2O*/
+#define R0900_P1_AGC2O 0xf42c
+#define AGC2O REGx(R0900_P1_AGC2O)
+#define F0900_P1_AGC2_COEF 0xf42c0007
+
+/*P1_AGC2REF*/
+#define R0900_P1_AGC2REF 0xf42d
+#define AGC2REF REGx(R0900_P1_AGC2REF)
+#define F0900_P1_AGC2_REF 0xf42d00ff
+
+/*P1_AGC1ADJ*/
+#define R0900_P1_AGC1ADJ 0xf42e
+#define AGC1ADJ REGx(R0900_P1_AGC1ADJ)
+#define F0900_P1_AGC1_ADJUSTED 0xf42e007f
+
+/*P1_AGC2I1*/
+#define R0900_P1_AGC2I1 0xf436
+#define AGC2I1 REGx(R0900_P1_AGC2I1)
+#define F0900_P1_AGC2_INTEGRATOR1 0xf43600ff
+
+/*P1_AGC2I0*/
+#define R0900_P1_AGC2I0 0xf437
+#define AGC2I0 REGx(R0900_P1_AGC2I0)
+#define F0900_P1_AGC2_INTEGRATOR0 0xf43700ff
+
+/*P1_CARCFG*/
+#define R0900_P1_CARCFG 0xf438
+#define CARCFG REGx(R0900_P1_CARCFG)
+#define F0900_P1_CFRUPLOW_AUTO 0xf4380080
+#define F0900_P1_CFRUPLOW_TEST 0xf4380040
+#define F0900_P1_ROTAON 0xf4380004
+#define F0900_P1_PH_DET_ALGO 0xf4380003
+
+/*P1_ACLC*/
+#define R0900_P1_ACLC 0xf439
+#define ACLC REGx(R0900_P1_ACLC)
+#define F0900_P1_CAR_ALPHA_MANT 0xf4390030
+#define F0900_P1_CAR_ALPHA_EXP 0xf439000f
+
+/*P1_BCLC*/
+#define R0900_P1_BCLC 0xf43a
+#define BCLC REGx(R0900_P1_BCLC)
+#define F0900_P1_CAR_BETA_MANT 0xf43a0030
+#define F0900_P1_CAR_BETA_EXP 0xf43a000f
+
+/*P1_CARFREQ*/
+#define R0900_P1_CARFREQ 0xf43d
+#define CARFREQ REGx(R0900_P1_CARFREQ)
+#define F0900_P1_KC_COARSE_EXP 0xf43d00f0
+#define F0900_P1_BETA_FREQ 0xf43d000f
+
+/*P1_CARHDR*/
+#define R0900_P1_CARHDR 0xf43e
+#define CARHDR REGx(R0900_P1_CARHDR)
+#define F0900_P1_K_FREQ_HDR 0xf43e00ff
+
+/*P1_LDT*/
+#define R0900_P1_LDT 0xf43f
+#define LDT REGx(R0900_P1_LDT)
+#define F0900_P1_CARLOCK_THRES 0xf43f01ff
+
+/*P1_LDT2*/
+#define R0900_P1_LDT2 0xf440
+#define LDT2 REGx(R0900_P1_LDT2)
+#define F0900_P1_CARLOCK_THRES2 0xf44001ff
+
+/*P1_CFRICFG*/
+#define R0900_P1_CFRICFG 0xf441
+#define CFRICFG REGx(R0900_P1_CFRICFG)
+#define F0900_P1_NEG_CFRSTEP 0xf4410001
+
+/*P1_CFRUP1*/
+#define R0900_P1_CFRUP1 0xf442
+#define CFRUP1 REGx(R0900_P1_CFRUP1)
+#define F0900_P1_CFR_UP1 0xf44201ff
+#define CFR_UP1 FLDx(F0900_P1_CFR_UP1)
+
+/*P1_CFRUP0*/
+#define R0900_P1_CFRUP0 0xf443
+#define CFRUP0 REGx(R0900_P1_CFRUP0)
+#define F0900_P1_CFR_UP0 0xf44300ff
+#define CFR_UP0 FLDx(F0900_P1_CFR_UP0)
+
+/*P1_CFRLOW1*/
+#define R0900_P1_CFRLOW1 0xf446
+#define CFRLOW1 REGx(R0900_P1_CFRLOW1)
+#define F0900_P1_CFR_LOW1 0xf44601ff
+#define CFR_LOW1 FLDx(F0900_P1_CFR_LOW1)
+
+/*P1_CFRLOW0*/
+#define R0900_P1_CFRLOW0 0xf447
+#define CFRLOW0 REGx(R0900_P1_CFRLOW0)
+#define F0900_P1_CFR_LOW0 0xf44700ff
+#define CFR_LOW0 FLDx(F0900_P1_CFR_LOW0)
+
+/*P1_CFRINIT1*/
+#define R0900_P1_CFRINIT1 0xf448
+#define CFRINIT1 REGx(R0900_P1_CFRINIT1)
+#define F0900_P1_CFR_INIT1 0xf44801ff
+#define CFR_INIT1 FLDx(F0900_P1_CFR_INIT1)
+
+/*P1_CFRINIT0*/
+#define R0900_P1_CFRINIT0 0xf449
+#define CFRINIT0 REGx(R0900_P1_CFRINIT0)
+#define F0900_P1_CFR_INIT0 0xf44900ff
+#define CFR_INIT0 FLDx(F0900_P1_CFR_INIT0)
+
+/*P1_CFRINC1*/
+#define R0900_P1_CFRINC1 0xf44a
+#define CFRINC1 REGx(R0900_P1_CFRINC1)
+#define F0900_P1_MANUAL_CFRINC 0xf44a0080
+#define F0900_P1_CFR_INC1 0xf44a003f
+
+/*P1_CFRINC0*/
+#define R0900_P1_CFRINC0 0xf44b
+#define CFRINC0 REGx(R0900_P1_CFRINC0)
+#define F0900_P1_CFR_INC0 0xf44b00f8
+
+/*P1_CFR2*/
+#define R0900_P1_CFR2 0xf44c
+#define CFR2 REGx(R0900_P1_CFR2)
+#define F0900_P1_CAR_FREQ2 0xf44c01ff
+#define CAR_FREQ2 FLDx(F0900_P1_CAR_FREQ2)
+
+/*P1_CFR1*/
+#define R0900_P1_CFR1 0xf44d
+#define CFR1 REGx(R0900_P1_CFR1)
+#define F0900_P1_CAR_FREQ1 0xf44d00ff
+#define CAR_FREQ1 FLDx(F0900_P1_CAR_FREQ1)
+
+/*P1_CFR0*/
+#define R0900_P1_CFR0 0xf44e
+#define CFR0 REGx(R0900_P1_CFR0)
+#define F0900_P1_CAR_FREQ0 0xf44e00ff
+#define CAR_FREQ0 FLDx(F0900_P1_CAR_FREQ0)
+
+/*P1_LDI*/
+#define R0900_P1_LDI 0xf44f
+#define LDI REGx(R0900_P1_LDI)
+#define F0900_P1_LOCK_DET_INTEGR 0xf44f01ff
+
+/*P1_TMGCFG*/
+#define R0900_P1_TMGCFG 0xf450
+#define TMGCFG REGx(R0900_P1_TMGCFG)
+#define F0900_P1_TMGLOCK_BETA 0xf45000c0
+#define F0900_P1_DO_TIMING_CORR 0xf4500010
+#define F0900_P1_TMG_MINFREQ 0xf4500003
+
+/*P1_RTC*/
+#define R0900_P1_RTC 0xf451
+#define RTC REGx(R0900_P1_RTC)
+#define F0900_P1_TMGALPHA_EXP 0xf45100f0
+#define F0900_P1_TMGBETA_EXP 0xf451000f
+
+/*P1_RTCS2*/
+#define R0900_P1_RTCS2 0xf452
+#define RTCS2 REGx(R0900_P1_RTCS2)
+#define F0900_P1_TMGALPHAS2_EXP 0xf45200f0
+#define F0900_P1_TMGBETAS2_EXP 0xf452000f
+
+/*P1_TMGTHRISE*/
+#define R0900_P1_TMGTHRISE 0xf453
+#define TMGTHRISE REGx(R0900_P1_TMGTHRISE)
+#define F0900_P1_TMGLOCK_THRISE 0xf45300ff
+
+/*P1_TMGTHFALL*/
+#define R0900_P1_TMGTHFALL 0xf454
+#define TMGTHFALL REGx(R0900_P1_TMGTHFALL)
+#define F0900_P1_TMGLOCK_THFALL 0xf45400ff
+
+/*P1_SFRUPRATIO*/
+#define R0900_P1_SFRUPRATIO 0xf455
+#define SFRUPRATIO REGx(R0900_P1_SFRUPRATIO)
+#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 KREFTMG REGx(R0900_P1_KREFTMG)
+#define F0900_P1_KREF_TMG 0xf45800ff
+
+/*P1_SFRSTEP*/
+#define R0900_P1_SFRSTEP 0xf459
+#define SFRSTEP REGx(R0900_P1_SFRSTEP)
+#define F0900_P1_SFR_SCANSTEP 0xf45900f0
+#define F0900_P1_SFR_CENTERSTEP 0xf459000f
+
+/*P1_TMGCFG2*/
+#define R0900_P1_TMGCFG2 0xf45a
+#define TMGCFG2 REGx(R0900_P1_TMGCFG2)
+#define F0900_P1_SFRRATIO_FINE 0xf45a0001
+
+/*P1_KREFTMG2*/
+#define R0900_P1_KREFTMG2 0xf45b
+#define KREFTMG2 REGx(R0900_P1_KREFTMG2)
+#define F0900_P1_KREF_TMG2 0xf45b00ff
+
+/*P1_SFRINIT1*/
+#define R0900_P1_SFRINIT1 0xf45e
+#define SFRINIT1 REGx(R0900_P1_SFRINIT1)
+#define F0900_P1_SFR_INIT1 0xf45e007f
+
+/*P1_SFRINIT0*/
+#define R0900_P1_SFRINIT0 0xf45f
+#define SFRINIT0 REGx(R0900_P1_SFRINIT0)
+#define F0900_P1_SFR_INIT0 0xf45f00ff
+
+/*P1_SFRUP1*/
+#define R0900_P1_SFRUP1 0xf460
+#define SFRUP1 REGx(R0900_P1_SFRUP1)
+#define F0900_P1_AUTO_GUP 0xf4600080
+#define AUTO_GUP FLDx(F0900_P1_AUTO_GUP)
+#define F0900_P1_SYMB_FREQ_UP1 0xf460007f
+
+/*P1_SFRUP0*/
+#define R0900_P1_SFRUP0 0xf461
+#define SFRUP0 REGx(R0900_P1_SFRUP0)
+#define F0900_P1_SYMB_FREQ_UP0 0xf46100ff
+
+/*P1_SFRLOW1*/
+#define R0900_P1_SFRLOW1 0xf462
+#define SFRLOW1 REGx(R0900_P1_SFRLOW1)
+#define F0900_P1_AUTO_GLOW 0xf4620080
+#define AUTO_GLOW FLDx(F0900_P1_AUTO_GLOW)
+#define F0900_P1_SYMB_FREQ_LOW1 0xf462007f
+
+/*P1_SFRLOW0*/
+#define R0900_P1_SFRLOW0 0xf463
+#define SFRLOW0 REGx(R0900_P1_SFRLOW0)
+#define F0900_P1_SYMB_FREQ_LOW0 0xf46300ff
+
+/*P1_SFR3*/
+#define R0900_P1_SFR3 0xf464
+#define SFR3 REGx(R0900_P1_SFR3)
+#define F0900_P1_SYMB_FREQ3 0xf46400ff
+#define SYMB_FREQ3 FLDx(F0900_P1_SYMB_FREQ3)
+
+/*P1_SFR2*/
+#define R0900_P1_SFR2 0xf465
+#define SFR2 REGx(R0900_P1_SFR2)
+#define F0900_P1_SYMB_FREQ2 0xf46500ff
+#define SYMB_FREQ2 FLDx(F0900_P1_SYMB_FREQ2)
+
+/*P1_SFR1*/
+#define R0900_P1_SFR1 0xf466
+#define SFR1 REGx(R0900_P1_SFR1)
+#define F0900_P1_SYMB_FREQ1 0xf46600ff
+#define SYMB_FREQ1 FLDx(F0900_P1_SYMB_FREQ1)
+
+/*P1_SFR0*/
+#define R0900_P1_SFR0 0xf467
+#define SFR0 REGx(R0900_P1_SFR0)
+#define F0900_P1_SYMB_FREQ0 0xf46700ff
+#define SYMB_FREQ0 FLDx(F0900_P1_SYMB_FREQ0)
+
+/*P1_TMGREG2*/
+#define R0900_P1_TMGREG2 0xf468
+#define TMGREG2 REGx(R0900_P1_TMGREG2)
+#define F0900_P1_TMGREG2 0xf46800ff
+
+/*P1_TMGREG1*/
+#define R0900_P1_TMGREG1 0xf469
+#define TMGREG1 REGx(R0900_P1_TMGREG1)
+#define F0900_P1_TMGREG1 0xf46900ff
+
+/*P1_TMGREG0*/
+#define R0900_P1_TMGREG0 0xf46a
+#define TMGREG0 REGx(R0900_P1_TMGREG0)
+#define F0900_P1_TMGREG0 0xf46a00ff
+
+/*P1_TMGLOCK1*/
+#define R0900_P1_TMGLOCK1 0xf46b
+#define TMGLOCK1 REGx(R0900_P1_TMGLOCK1)
+#define F0900_P1_TMGLOCK_LEVEL1 0xf46b01ff
+
+/*P1_TMGLOCK0*/
+#define R0900_P1_TMGLOCK0 0xf46c
+#define TMGLOCK0 REGx(R0900_P1_TMGLOCK0)
+#define F0900_P1_TMGLOCK_LEVEL0 0xf46c00ff
+
+/*P1_TMGOBS*/
+#define R0900_P1_TMGOBS 0xf46d
+#define TMGOBS REGx(R0900_P1_TMGOBS)
+#define F0900_P1_ROLLOFF_STATUS 0xf46d00c0
+#define ROLLOFF_STATUS FLDx(F0900_P1_ROLLOFF_STATUS)
+
+/*P1_EQUALCFG*/
+#define R0900_P1_EQUALCFG 0xf46f
+#define EQUALCFG REGx(R0900_P1_EQUALCFG)
+#define F0900_P1_EQUAL_ON 0xf46f0040
+#define F0900_P1_MU_EQUALDFE 0xf46f0007
+
+/*P1_EQUAI1*/
+#define R0900_P1_EQUAI1 0xf470
+#define EQUAI1 REGx(R0900_P1_EQUAI1)
+#define F0900_P1_EQUA_ACCI1 0xf47001ff
+
+/*P1_EQUAQ1*/
+#define R0900_P1_EQUAQ1 0xf471
+#define EQUAQ1 REGx(R0900_P1_EQUAQ1)
+#define F0900_P1_EQUA_ACCQ1 0xf47101ff
+
+/*P1_EQUAI2*/
+#define R0900_P1_EQUAI2 0xf472
+#define EQUAI2 REGx(R0900_P1_EQUAI2)
+#define F0900_P1_EQUA_ACCI2 0xf47201ff
+
+/*P1_EQUAQ2*/
+#define R0900_P1_EQUAQ2 0xf473
+#define EQUAQ2 REGx(R0900_P1_EQUAQ2)
+#define F0900_P1_EQUA_ACCQ2 0xf47301ff
+
+/*P1_EQUAI3*/
+#define R0900_P1_EQUAI3 0xf474
+#define EQUAI3 REGx(R0900_P1_EQUAI3)
+#define F0900_P1_EQUA_ACCI3 0xf47401ff
+
+/*P1_EQUAQ3*/
+#define R0900_P1_EQUAQ3 0xf475
+#define EQUAQ3 REGx(R0900_P1_EQUAQ3)
+#define F0900_P1_EQUA_ACCQ3 0xf47501ff
+
+/*P1_EQUAI4*/
+#define R0900_P1_EQUAI4 0xf476
+#define EQUAI4 REGx(R0900_P1_EQUAI4)
+#define F0900_P1_EQUA_ACCI4 0xf47601ff
+
+/*P1_EQUAQ4*/
+#define R0900_P1_EQUAQ4 0xf477
+#define EQUAQ4 REGx(R0900_P1_EQUAQ4)
+#define F0900_P1_EQUA_ACCQ4 0xf47701ff
+
+/*P1_EQUAI5*/
+#define R0900_P1_EQUAI5 0xf478
+#define EQUAI5 REGx(R0900_P1_EQUAI5)
+#define F0900_P1_EQUA_ACCI5 0xf47801ff
+
+/*P1_EQUAQ5*/
+#define R0900_P1_EQUAQ5 0xf479
+#define EQUAQ5 REGx(R0900_P1_EQUAQ5)
+#define F0900_P1_EQUA_ACCQ5 0xf47901ff
+
+/*P1_EQUAI6*/
+#define R0900_P1_EQUAI6 0xf47a
+#define EQUAI6 REGx(R0900_P1_EQUAI6)
+#define F0900_P1_EQUA_ACCI6 0xf47a01ff
+
+/*P1_EQUAQ6*/
+#define R0900_P1_EQUAQ6 0xf47b
+#define EQUAQ6 REGx(R0900_P1_EQUAQ6)
+#define F0900_P1_EQUA_ACCQ6 0xf47b01ff
+
+/*P1_EQUAI7*/
+#define R0900_P1_EQUAI7 0xf47c
+#define EQUAI7 REGx(R0900_P1_EQUAI7)
+#define F0900_P1_EQUA_ACCI7 0xf47c01ff
+
+/*P1_EQUAQ7*/
+#define R0900_P1_EQUAQ7 0xf47d
+#define EQUAQ7 REGx(R0900_P1_EQUAQ7)
+#define F0900_P1_EQUA_ACCQ7 0xf47d01ff
+
+/*P1_EQUAI8*/
+#define R0900_P1_EQUAI8 0xf47e
+#define EQUAI8 REGx(R0900_P1_EQUAI8)
+#define F0900_P1_EQUA_ACCI8 0xf47e01ff
+
+/*P1_EQUAQ8*/
+#define R0900_P1_EQUAQ8 0xf47f
+#define EQUAQ8 REGx(R0900_P1_EQUAQ8)
+#define F0900_P1_EQUA_ACCQ8 0xf47f01ff
+
+/*P1_NNOSDATAT1*/
+#define R0900_P1_NNOSDATAT1 0xf480
+#define NNOSDATAT1 REGx(R0900_P1_NNOSDATAT1)
+#define F0900_P1_NOSDATAT_NORMED1 0xf48000ff
+#define NOSDATAT_NORMED1 FLDx(F0900_P1_NOSDATAT_NORMED1)
+
+/*P1_NNOSDATAT0*/
+#define R0900_P1_NNOSDATAT0 0xf481
+#define NNOSDATAT0 REGx(R0900_P1_NNOSDATAT0)
+#define F0900_P1_NOSDATAT_NORMED0 0xf48100ff
+#define NOSDATAT_NORMED0 FLDx(F0900_P1_NOSDATAT_NORMED0)
+
+/*P1_NNOSDATA1*/
+#define R0900_P1_NNOSDATA1 0xf482
+#define NNOSDATA1 REGx(R0900_P1_NNOSDATA1)
+#define F0900_P1_NOSDATA_NORMED1 0xf48200ff
+
+/*P1_NNOSDATA0*/
+#define R0900_P1_NNOSDATA0 0xf483
+#define NNOSDATA0 REGx(R0900_P1_NNOSDATA0)
+#define F0900_P1_NOSDATA_NORMED0 0xf48300ff
+
+/*P1_NNOSPLHT1*/
+#define R0900_P1_NNOSPLHT1 0xf484
+#define NNOSPLHT1 REGx(R0900_P1_NNOSPLHT1)
+#define F0900_P1_NOSPLHT_NORMED1 0xf48400ff
+#define NOSPLHT_NORMED1 FLDx(F0900_P1_NOSPLHT_NORMED1)
+
+/*P1_NNOSPLHT0*/
+#define R0900_P1_NNOSPLHT0 0xf485
+#define NNOSPLHT0 REGx(R0900_P1_NNOSPLHT0)
+#define F0900_P1_NOSPLHT_NORMED0 0xf48500ff
+#define NOSPLHT_NORMED0 FLDx(F0900_P1_NOSPLHT_NORMED0)
+
+/*P1_NNOSPLH1*/
+#define R0900_P1_NNOSPLH1 0xf486
+#define NNOSPLH1 REGx(R0900_P1_NNOSPLH1)
+#define F0900_P1_NOSPLH_NORMED1 0xf48600ff
+
+/*P1_NNOSPLH0*/
+#define R0900_P1_NNOSPLH0 0xf487
+#define NNOSPLH0 REGx(R0900_P1_NNOSPLH0)
+#define F0900_P1_NOSPLH_NORMED0 0xf48700ff
+
+/*P1_NOSDATAT1*/
+#define R0900_P1_NOSDATAT1 0xf488
+#define NOSDATAT1 REGx(R0900_P1_NOSDATAT1)
+#define F0900_P1_NOSDATAT_UNNORMED1 0xf48800ff
+
+/*P1_NOSDATAT0*/
+#define R0900_P1_NOSDATAT0 0xf489
+#define NOSDATAT0 REGx(R0900_P1_NOSDATAT0)
+#define F0900_P1_NOSDATAT_UNNORMED0 0xf48900ff
+
+/*P1_NOSDATA1*/
+#define R0900_P1_NOSDATA1 0xf48a
+#define NOSDATA1 REGx(R0900_P1_NOSDATA1)
+#define F0900_P1_NOSDATA_UNNORMED1 0xf48a00ff
+
+/*P1_NOSDATA0*/
+#define R0900_P1_NOSDATA0 0xf48b
+#define NOSDATA0 REGx(R0900_P1_NOSDATA0)
+#define F0900_P1_NOSDATA_UNNORMED0 0xf48b00ff
+
+/*P1_NOSPLHT1*/
+#define R0900_P1_NOSPLHT1 0xf48c
+#define NOSPLHT1 REGx(R0900_P1_NOSPLHT1)
+#define F0900_P1_NOSPLHT_UNNORMED1 0xf48c00ff
+
+/*P1_NOSPLHT0*/
+#define R0900_P1_NOSPLHT0 0xf48d
+#define NOSPLHT0 REGx(R0900_P1_NOSPLHT0)
+#define F0900_P1_NOSPLHT_UNNORMED0 0xf48d00ff
+
+/*P1_NOSPLH1*/
+#define R0900_P1_NOSPLH1 0xf48e
+#define NOSPLH1 REGx(R0900_P1_NOSPLH1)
+#define F0900_P1_NOSPLH_UNNORMED1 0xf48e00ff
+
+/*P1_NOSPLH0*/
+#define R0900_P1_NOSPLH0 0xf48f
+#define NOSPLH0 REGx(R0900_P1_NOSPLH0)
+#define F0900_P1_NOSPLH_UNNORMED0 0xf48f00ff
+
+/*P1_CAR2CFG*/
+#define R0900_P1_CAR2CFG 0xf490
+#define CAR2CFG REGx(R0900_P1_CAR2CFG)
+#define F0900_P1_CARRIER3_DISABLE 0xf4900040
+#define F0900_P1_ROTA2ON 0xf4900004
+#define F0900_P1_PH_DET_ALGO2 0xf4900003
+
+/*P1_CFR2CFR1*/
+#define R0900_P1_CFR2CFR1 0xf491
+#define CFR2CFR1 REGx(R0900_P1_CFR2CFR1)
+#define F0900_P1_CFR2TOCFR1_DVBS1 0xf49100c0
+#define F0900_P1_EN_S2CAR2CENTER 0xf4910020
+#define F0900_P1_DIS_BCHERRCFR2 0xf4910010
+#define F0900_P1_CFR2TOCFR1_BETA 0xf4910007
+
+/*P1_CFR22*/
+#define R0900_P1_CFR22 0xf493
+#define CFR22 REGx(R0900_P1_CFR22)
+#define F0900_P1_CAR2_FREQ2 0xf49301ff
+
+/*P1_CFR21*/
+#define R0900_P1_CFR21 0xf494
+#define CFR21 REGx(R0900_P1_CFR21)
+#define F0900_P1_CAR2_FREQ1 0xf49400ff
+
+/*P1_CFR20*/
+#define R0900_P1_CFR20 0xf495
+#define CFR20 REGx(R0900_P1_CFR20)
+#define F0900_P1_CAR2_FREQ0 0xf49500ff
+
+/*P1_ACLC2S2Q*/
+#define R0900_P1_ACLC2S2Q 0xf497
+#define ACLC2S2Q REGx(R0900_P1_ACLC2S2Q)
+#define F0900_P1_ENAB_SPSKSYMB 0xf4970080
+#define F0900_P1_CAR2S2_Q_ALPH_M 0xf4970030
+#define F0900_P1_CAR2S2_Q_ALPH_E 0xf497000f
+
+/*P1_ACLC2S28*/
+#define R0900_P1_ACLC2S28 0xf498
+#define ACLC2S28 REGx(R0900_P1_ACLC2S28)
+#define F0900_P1_OLDI3Q_MODE 0xf4980080
+#define F0900_P1_CAR2S2_8_ALPH_M 0xf4980030
+#define F0900_P1_CAR2S2_8_ALPH_E 0xf498000f
+
+/*P1_ACLC2S216A*/
+#define R0900_P1_ACLC2S216A 0xf499
+#define ACLC2S216A REGx(R0900_P1_ACLC2S216A)
+#define F0900_P1_DIS_C3STOPA2 0xf4990080
+#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 ACLC2S232A REGx(R0900_P1_ACLC2S232A)
+#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 BCLC2S2Q REGx(R0900_P1_BCLC2S2Q)
+#define F0900_P1_CAR2S2_Q_BETA_M 0xf49c0030
+#define F0900_P1_CAR2S2_Q_BETA_E 0xf49c000f
+
+/*P1_BCLC2S28*/
+#define R0900_P1_BCLC2S28 0xf49d
+#define BCLC2S28 REGx(R0900_P1_BCLC2S28)
+#define F0900_P1_CAR2S2_8_BETA_M 0xf49d0030
+#define F0900_P1_CAR2S2_8_BETA_E 0xf49d000f
+
+/*P1_BCLC2S216A*/
+#define R0900_P1_BCLC2S216A 0xf49e
+#define BCLC2S216A REGx(R0900_P1_BCLC2S216A)
+
+/*P1_BCLC2S232A*/
+#define R0900_P1_BCLC2S232A 0xf49f
+#define BCLC2S232A REGx(R0900_P1_BCLC2S232A)
+
+/*P1_PLROOT2*/
+#define R0900_P1_PLROOT2 0xf4ac
+#define PLROOT2 REGx(R0900_P1_PLROOT2)
+#define F0900_P1_PLSCRAMB_MODE 0xf4ac000c
+#define F0900_P1_PLSCRAMB_ROOT2 0xf4ac0003
+
+/*P1_PLROOT1*/
+#define R0900_P1_PLROOT1 0xf4ad
+#define PLROOT1 REGx(R0900_P1_PLROOT1)
+#define F0900_P1_PLSCRAMB_ROOT1 0xf4ad00ff
+
+/*P1_PLROOT0*/
+#define R0900_P1_PLROOT0 0xf4ae
+#define PLROOT0 REGx(R0900_P1_PLROOT0)
+#define F0900_P1_PLSCRAMB_ROOT0 0xf4ae00ff
+
+/*P1_MODCODLST0*/
+#define R0900_P1_MODCODLST0 0xf4b0
+#define MODCODLST0 REGx(R0900_P1_MODCODLST0)
+
+/*P1_MODCODLST1*/
+#define R0900_P1_MODCODLST1 0xf4b1
+#define MODCODLST1 REGx(R0900_P1_MODCODLST1)
+#define F0900_P1_DIS_MODCOD29 0xf4b100f0
+#define F0900_P1_DIS_32PSK_9_10 0xf4b1000f
+
+/*P1_MODCODLST2*/
+#define R0900_P1_MODCODLST2 0xf4b2
+#define MODCODLST2 REGx(R0900_P1_MODCODLST2)
+#define F0900_P1_DIS_32PSK_8_9 0xf4b200f0
+#define F0900_P1_DIS_32PSK_5_6 0xf4b2000f
+
+/*P1_MODCODLST3*/
+#define R0900_P1_MODCODLST3 0xf4b3
+#define MODCODLST3 REGx(R0900_P1_MODCODLST3)
+#define F0900_P1_DIS_32PSK_4_5 0xf4b300f0
+#define F0900_P1_DIS_32PSK_3_4 0xf4b3000f
+
+/*P1_MODCODLST4*/
+#define R0900_P1_MODCODLST4 0xf4b4
+#define MODCODLST4 REGx(R0900_P1_MODCODLST4)
+#define F0900_P1_DIS_16PSK_9_10 0xf4b400f0
+#define F0900_P1_DIS_16PSK_8_9 0xf4b4000f
+
+/*P1_MODCODLST5*/
+#define R0900_P1_MODCODLST5 0xf4b5
+#define MODCODLST5 REGx(R0900_P1_MODCODLST5)
+#define F0900_P1_DIS_16PSK_5_6 0xf4b500f0
+#define F0900_P1_DIS_16PSK_4_5 0xf4b5000f
+
+/*P1_MODCODLST6*/
+#define R0900_P1_MODCODLST6 0xf4b6
+#define MODCODLST6 REGx(R0900_P1_MODCODLST6)
+#define F0900_P1_DIS_16PSK_3_4 0xf4b600f0
+#define F0900_P1_DIS_16PSK_2_3 0xf4b6000f
+
+/*P1_MODCODLST7*/
+#define R0900_P1_MODCODLST7 0xf4b7
+#define MODCODLST7 REGx(R0900_P1_MODCODLST7)
+#define F0900_P1_DIS_8P_9_10 0xf4b700f0
+#define F0900_P1_DIS_8P_8_9 0xf4b7000f
+
+/*P1_MODCODLST8*/
+#define R0900_P1_MODCODLST8 0xf4b8
+#define MODCODLST8 REGx(R0900_P1_MODCODLST8)
+#define F0900_P1_DIS_8P_5_6 0xf4b800f0
+#define F0900_P1_DIS_8P_3_4 0xf4b8000f
+
+/*P1_MODCODLST9*/
+#define R0900_P1_MODCODLST9 0xf4b9
+#define MODCODLST9 REGx(R0900_P1_MODCODLST9)
+#define F0900_P1_DIS_8P_2_3 0xf4b900f0
+#define F0900_P1_DIS_8P_3_5 0xf4b9000f
+
+/*P1_MODCODLSTA*/
+#define R0900_P1_MODCODLSTA 0xf4ba
+#define MODCODLSTA REGx(R0900_P1_MODCODLSTA)
+#define F0900_P1_DIS_QP_9_10 0xf4ba00f0
+#define F0900_P1_DIS_QP_8_9 0xf4ba000f
+
+/*P1_MODCODLSTB*/
+#define R0900_P1_MODCODLSTB 0xf4bb
+#define MODCODLSTB REGx(R0900_P1_MODCODLSTB)
+#define F0900_P1_DIS_QP_5_6 0xf4bb00f0
+#define F0900_P1_DIS_QP_4_5 0xf4bb000f
+
+/*P1_MODCODLSTC*/
+#define R0900_P1_MODCODLSTC 0xf4bc
+#define MODCODLSTC REGx(R0900_P1_MODCODLSTC)
+#define F0900_P1_DIS_QP_3_4 0xf4bc00f0
+#define F0900_P1_DIS_QP_2_3 0xf4bc000f
+
+/*P1_MODCODLSTD*/
+#define R0900_P1_MODCODLSTD 0xf4bd
+#define MODCODLSTD REGx(R0900_P1_MODCODLSTD)
+#define F0900_P1_DIS_QP_3_5 0xf4bd00f0
+#define F0900_P1_DIS_QP_1_2 0xf4bd000f
+
+/*P1_MODCODLSTE*/
+#define R0900_P1_MODCODLSTE 0xf4be
+#define MODCODLSTE REGx(R0900_P1_MODCODLSTE)
+#define F0900_P1_DIS_QP_2_5 0xf4be00f0
+#define F0900_P1_DIS_QP_1_3 0xf4be000f
+
+/*P1_MODCODLSTF*/
+#define R0900_P1_MODCODLSTF 0xf4bf
+#define MODCODLSTF REGx(R0900_P1_MODCODLSTF)
+#define F0900_P1_DIS_QP_1_4 0xf4bf00f0
+
+/*P1_GAUSSR0*/
+#define R0900_P1_GAUSSR0 0xf4c0
+#define GAUSSR0 REGx(R0900_P1_GAUSSR0)
+#define F0900_P1_EN_CCIMODE 0xf4c00080
+#define F0900_P1_R0_GAUSSIEN 0xf4c0007f
+
+/*P1_CCIR0*/
+#define R0900_P1_CCIR0 0xf4c1
+#define CCIR0 REGx(R0900_P1_CCIR0)
+#define F0900_P1_CCIDETECT_PLHONLY 0xf4c10080
+#define F0900_P1_R0_CCI 0xf4c1007f
+
+/*P1_CCIQUANT*/
+#define R0900_P1_CCIQUANT 0xf4c2
+#define CCIQUANT REGx(R0900_P1_CCIQUANT)
+#define F0900_P1_CCI_BETA 0xf4c200e0
+#define F0900_P1_CCI_QUANT 0xf4c2001f
+
+/*P1_CCITHRES*/
+#define R0900_P1_CCITHRES 0xf4c3
+#define CCITHRES REGx(R0900_P1_CCITHRES)
+#define F0900_P1_CCI_THRESHOLD 0xf4c300ff
+
+/*P1_CCIACC*/
+#define R0900_P1_CCIACC 0xf4c4
+#define CCIACC REGx(R0900_P1_CCIACC)
+#define F0900_P1_CCI_VALUE 0xf4c400ff
+
+/*P1_DMDRESCFG*/
+#define R0900_P1_DMDRESCFG 0xf4c6
+#define DMDRESCFG REGx(R0900_P1_DMDRESCFG)
+#define F0900_P1_DMDRES_RESET 0xf4c60080
+#define F0900_P1_DMDRES_STRALL 0xf4c60008
+#define F0900_P1_DMDRES_NEWONLY 0xf4c60004
+#define F0900_P1_DMDRES_NOSTORE 0xf4c60002
+
+/*P1_DMDRESADR*/
+#define R0900_P1_DMDRESADR 0xf4c7
+#define DMDRESADR REGx(R0900_P1_DMDRESADR)
+#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 FFEI1 REGx(R0900_P1_FFEI1)
+#define F0900_P1_FFE_ACCI1 0xf4d001ff
+
+/*P1_FFEQ1*/
+#define R0900_P1_FFEQ1 0xf4d1
+#define FFEQ1 REGx(R0900_P1_FFEQ1)
+#define F0900_P1_FFE_ACCQ1 0xf4d101ff
+
+/*P1_FFEI2*/
+#define R0900_P1_FFEI2 0xf4d2
+#define FFEI2 REGx(R0900_P1_FFEI2)
+#define F0900_P1_FFE_ACCI2 0xf4d201ff
+
+/*P1_FFEQ2*/
+#define R0900_P1_FFEQ2 0xf4d3
+#define FFEQ2 REGx(R0900_P1_FFEQ2)
+#define F0900_P1_FFE_ACCQ2 0xf4d301ff
+
+/*P1_FFEI3*/
+#define R0900_P1_FFEI3 0xf4d4
+#define FFEI3 REGx(R0900_P1_FFEI3)
+#define F0900_P1_FFE_ACCI3 0xf4d401ff
+
+/*P1_FFEQ3*/
+#define R0900_P1_FFEQ3 0xf4d5
+#define FFEQ3 REGx(R0900_P1_FFEQ3)
+#define F0900_P1_FFE_ACCQ3 0xf4d501ff
+
+/*P1_FFEI4*/
+#define R0900_P1_FFEI4 0xf4d6
+#define FFEI4 REGx(R0900_P1_FFEI4)
+#define F0900_P1_FFE_ACCI4 0xf4d601ff
+
+/*P1_FFEQ4*/
+#define R0900_P1_FFEQ4 0xf4d7
+#define FFEQ4 REGx(R0900_P1_FFEQ4)
+#define F0900_P1_FFE_ACCQ4 0xf4d701ff
+
+/*P1_FFECFG*/
+#define R0900_P1_FFECFG 0xf4d8
+#define FFECFG REGx(R0900_P1_FFECFG)
+#define F0900_P1_EQUALFFE_ON 0xf4d80040
+#define F0900_P1_MU_EQUALFFE 0xf4d80007
+
+/*P1_TNRCFG*/
+#define R0900_P1_TNRCFG 0xf4e0
+#define TNRCFG REGx(R0900_P1_TNRCFG)
+#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 TNRCFG2 REGx(R0900_P1_TNRCFG2)
+#define F0900_P1_TUN_IQSWAP 0xf4e10080
+#define F0900_P1_DIS_BWCALC 0xf4e10004
+#define F0900_P1_SHORT_WAITSTATES 0xf4e10002
+
+/*P1_TNRXTAL*/
+#define R0900_P1_TNRXTAL 0xf4e4
+#define TNRXTAL REGx(R0900_P1_TNRXTAL)
+#define F0900_P1_TUN_XTALFREQ 0xf4e4001f
+
+/*P1_TNRSTEPS*/
+#define R0900_P1_TNRSTEPS 0xf4e7
+#define TNRSTEPS REGx(R0900_P1_TNRSTEPS)
+#define F0900_P1_TUNER_BW0P125 0xf4e70080
+#define F0900_P1_BWINC_OFFSET 0xf4e70170
+#define F0900_P1_SOFTSTEP_RNG 0xf4e70008
+#define F0900_P1_TUN_BWOFFSET 0xf4e70007
+
+/*P1_TNRGAIN*/
+#define R0900_P1_TNRGAIN 0xf4e8
+#define TNRGAIN REGx(R0900_P1_TNRGAIN)
+#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 TNRRF1 REGx(R0900_P1_TNRRF1)
+#define F0900_P1_TUN_RFFREQ2 0xf4e900ff
+#define TUN_RFFREQ2 FLDx(F0900_P1_TUN_RFFREQ2)
+
+/*P1_TNRRF0*/
+#define R0900_P1_TNRRF0 0xf4ea
+#define TNRRF0 REGx(R0900_P1_TNRRF0)
+#define F0900_P1_TUN_RFFREQ1 0xf4ea00ff
+#define TUN_RFFREQ1 FLDx(F0900_P1_TUN_RFFREQ1)
+
+/*P1_TNRBW*/
+#define R0900_P1_TNRBW 0xf4eb
+#define TNRBW REGx(R0900_P1_TNRBW)
+#define F0900_P1_TUN_RFFREQ0 0xf4eb00c0
+#define TUN_RFFREQ0 FLDx(F0900_P1_TUN_RFFREQ0)
+#define F0900_P1_TUN_BW 0xf4eb003f
+#define TUN_BW FLDx(F0900_P1_TUN_BW)
+
+/*P1_TNRADJ*/
+#define R0900_P1_TNRADJ 0xf4ec
+#define TNRADJ REGx(R0900_P1_TNRADJ)
+#define F0900_P1_STB61X0_CALTIME 0xf4ec0040
+
+/*P1_TNRCTL2*/
+#define R0900_P1_TNRCTL2 0xf4ed
+#define TNRCTL2 REGx(R0900_P1_TNRCTL2)
+#define F0900_P1_STB61X0_RCCKOFF 0xf4ed0080
+#define F0900_P1_STB61X0_ICP_SDOFF 0xf4ed0040
+#define F0900_P1_STB61X0_DCLOOPOFF 0xf4ed0020
+#define F0900_P1_STB61X0_REFOUTSEL 0xf4ed0010
+#define F0900_P1_STB61X0_CALOFF 0xf4ed0008
+#define F0900_P1_STB6XX0_LPT_BEN 0xf4ed0004
+#define F0900_P1_STB6XX0_RX_OSCP 0xf4ed0002
+#define F0900_P1_STB6XX0_SYN 0xf4ed0001
+
+/*P1_TNRCFG3*/
+#define R0900_P1_TNRCFG3 0xf4ee
+#define TNRCFG3 REGx(R0900_P1_TNRCFG3)
+#define F0900_P1_TUN_PLLFREQ 0xf4ee001c
+#define F0900_P1_TUN_I2CFREQ_MODE 0xf4ee0003
+
+/*P1_TNRLAUNCH*/
+#define R0900_P1_TNRLAUNCH 0xf4f0
+#define TNRLAUNCH REGx(R0900_P1_TNRLAUNCH)
+
+/*P1_TNRLD*/
+#define R0900_P1_TNRLD 0xf4f0
+#define TNRLD REGx(R0900_P1_TNRLD)
+#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 TNROBSL REGx(R0900_P1_TNROBSL)
+#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
+#define TUN_RFRESTE1 FLDx(F0900_P1_TUN_RFRESTE1)
+
+/*P1_TNRRESTE*/
+#define R0900_P1_TNRRESTE 0xf4f7
+#define TNRRESTE REGx(R0900_P1_TNRRESTE)
+#define F0900_P1_TUN_RFRESTE0 0xf4f700ff
+#define TUN_RFRESTE0 FLDx(F0900_P1_TUN_RFRESTE0)
+
+/*P1_SMAPCOEF7*/
+#define R0900_P1_SMAPCOEF7 0xf500
+#define SMAPCOEF7 REGx(R0900_P1_SMAPCOEF7)
+#define F0900_P1_DIS_QSCALE 0xf5000080
+#define F0900_P1_SMAPCOEF_Q_LLR12 0xf500017f
+
+/*P1_SMAPCOEF6*/
+#define R0900_P1_SMAPCOEF6 0xf501
+#define SMAPCOEF6 REGx(R0900_P1_SMAPCOEF6)
+#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 SMAPCOEF5 REGx(R0900_P1_SMAPCOEF5)
+#define F0900_P1_DIS_8SCALE 0xf5020080
+#define F0900_P1_SMAPCOEF_8P_LLR23 0xf502017f
+
+/*P1_NCO2MAX1*/
+#define R0900_P1_NCO2MAX1 0xf514
+#define NCO2MAX1 REGx(R0900_P1_NCO2MAX1)
+#define F0900_P1_TETA2_MAXVABS1 0xf51400ff
+
+/*P1_NCO2MAX0*/
+#define R0900_P1_NCO2MAX0 0xf515
+#define NCO2MAX0 REGx(R0900_P1_NCO2MAX0)
+#define F0900_P1_TETA2_MAXVABS0 0xf51500ff
+
+/*P1_NCO2FR1*/
+#define R0900_P1_NCO2FR1 0xf516
+#define NCO2FR1 REGx(R0900_P1_NCO2FR1)
+#define F0900_P1_NCO2FINAL_ANGLE1 0xf51600ff
+
+/*P1_NCO2FR0*/
+#define R0900_P1_NCO2FR0 0xf517
+#define NCO2FR0 REGx(R0900_P1_NCO2FR0)
+#define F0900_P1_NCO2FINAL_ANGLE0 0xf51700ff
+
+/*P1_CFR2AVRGE1*/
+#define R0900_P1_CFR2AVRGE1 0xf518
+#define CFR2AVRGE1 REGx(R0900_P1_CFR2AVRGE1)
+#define F0900_P1_I2C_CFR2AVERAGE1 0xf51800ff
+
+/*P1_CFR2AVRGE0*/
+#define R0900_P1_CFR2AVRGE0 0xf519
+#define CFR2AVRGE0 REGx(R0900_P1_CFR2AVRGE0)
+#define F0900_P1_I2C_CFR2AVERAGE0 0xf51900ff
+
+/*P1_DMDPLHSTAT*/
+#define R0900_P1_DMDPLHSTAT 0xf520
+#define DMDPLHSTAT REGx(R0900_P1_DMDPLHSTAT)
+#define F0900_P1_PLH_STATISTIC 0xf52000ff
+
+/*P1_LOCKTIME3*/
+#define R0900_P1_LOCKTIME3 0xf522
+#define LOCKTIME3 REGx(R0900_P1_LOCKTIME3)
+#define F0900_P1_DEMOD_LOCKTIME3 0xf52200ff
+
+/*P1_LOCKTIME2*/
+#define R0900_P1_LOCKTIME2 0xf523
+#define LOCKTIME2 REGx(R0900_P1_LOCKTIME2)
+#define F0900_P1_DEMOD_LOCKTIME2 0xf52300ff
+
+/*P1_LOCKTIME1*/
+#define R0900_P1_LOCKTIME1 0xf524
+#define LOCKTIME1 REGx(R0900_P1_LOCKTIME1)
+#define F0900_P1_DEMOD_LOCKTIME1 0xf52400ff
+
+/*P1_LOCKTIME0*/
+#define R0900_P1_LOCKTIME0 0xf525
+#define LOCKTIME0 REGx(R0900_P1_LOCKTIME0)
+#define F0900_P1_DEMOD_LOCKTIME0 0xf52500ff
+
+/*P1_VITSCALE*/
+#define R0900_P1_VITSCALE 0xf532
+#define VITSCALE REGx(R0900_P1_VITSCALE)
+#define F0900_P1_NVTH_NOSRANGE 0xf5320080
+#define F0900_P1_VERROR_MAXMODE 0xf5320040
+#define F0900_P1_NSLOWSN_LOCKED 0xf5320008
+#define F0900_P1_DIS_RSFLOCK 0xf5320002
+
+/*P1_FECM*/
+#define R0900_P1_FECM 0xf533
+#define FECM REGx(R0900_P1_FECM)
+#define F0900_P1_DSS_DVB 0xf5330080
+#define DSS_DVB FLDx(F0900_P1_DSS_DVB)
+#define F0900_P1_DSS_SRCH 0xf5330010
+#define F0900_P1_SYNCVIT 0xf5330002
+#define F0900_P1_IQINV 0xf5330001
+#define IQINV FLDx(F0900_P1_IQINV)
+
+/*P1_VTH12*/
+#define R0900_P1_VTH12 0xf534
+#define VTH12 REGx(R0900_P1_VTH12)
+#define F0900_P1_VTH12 0xf53400ff
+
+/*P1_VTH23*/
+#define R0900_P1_VTH23 0xf535
+#define VTH23 REGx(R0900_P1_VTH23)
+#define F0900_P1_VTH23 0xf53500ff
+
+/*P1_VTH34*/
+#define R0900_P1_VTH34 0xf536
+#define VTH34 REGx(R0900_P1_VTH34)
+#define F0900_P1_VTH34 0xf53600ff
+
+/*P1_VTH56*/
+#define R0900_P1_VTH56 0xf537
+#define VTH56 REGx(R0900_P1_VTH56)
+#define F0900_P1_VTH56 0xf53700ff
+
+/*P1_VTH67*/
+#define R0900_P1_VTH67 0xf538
+#define VTH67 REGx(R0900_P1_VTH67)
+#define F0900_P1_VTH67 0xf53800ff
+
+/*P1_VTH78*/
+#define R0900_P1_VTH78 0xf539
+#define VTH78 REGx(R0900_P1_VTH78)
+#define F0900_P1_VTH78 0xf53900ff
+
+/*P1_VITCURPUN*/
+#define R0900_P1_VITCURPUN 0xf53a
+#define VITCURPUN REGx(R0900_P1_VITCURPUN)
+#define F0900_P1_VIT_CURPUN 0xf53a001f
+#define VIT_CURPUN FLDx(F0900_P1_VIT_CURPUN)
+
+/*P1_VERROR*/
+#define R0900_P1_VERROR 0xf53b
+#define VERROR REGx(R0900_P1_VERROR)
+#define F0900_P1_REGERR_VIT 0xf53b00ff
+
+/*P1_PRVIT*/
+#define R0900_P1_PRVIT 0xf53c
+#define PRVIT REGx(R0900_P1_PRVIT)
+#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 VAVSRVIT REGx(R0900_P1_VAVSRVIT)
+#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 VSTATUSVIT REGx(R0900_P1_VSTATUSVIT)
+#define F0900_P1_PRFVIT 0xf53e0010
+#define PRFVIT FLDx(F0900_P1_PRFVIT)
+#define F0900_P1_LOCKEDVIT 0xf53e0008
+#define LOCKEDVIT FLDx(F0900_P1_LOCKEDVIT)
+
+/*P1_VTHINUSE*/
+#define R0900_P1_VTHINUSE 0xf53f
+#define VTHINUSE REGx(R0900_P1_VTHINUSE)
+#define F0900_P1_VIT_INUSE 0xf53f00ff
+
+/*P1_KDIV12*/
+#define R0900_P1_KDIV12 0xf540
+#define KDIV12 REGx(R0900_P1_KDIV12)
+#define F0900_P1_K_DIVIDER_12 0xf540007f
+
+/*P1_KDIV23*/
+#define R0900_P1_KDIV23 0xf541
+#define KDIV23 REGx(R0900_P1_KDIV23)
+#define F0900_P1_K_DIVIDER_23 0xf541007f
+
+/*P1_KDIV34*/
+#define R0900_P1_KDIV34 0xf542
+#define KDIV34 REGx(R0900_P1_KDIV34)
+#define F0900_P1_K_DIVIDER_34 0xf542007f
+
+/*P1_KDIV56*/
+#define R0900_P1_KDIV56 0xf543
+#define KDIV56 REGx(R0900_P1_KDIV56)
+#define F0900_P1_K_DIVIDER_56 0xf543007f
+
+/*P1_KDIV67*/
+#define R0900_P1_KDIV67 0xf544
+#define KDIV67 REGx(R0900_P1_KDIV67)
+#define F0900_P1_K_DIVIDER_67 0xf544007f
+
+/*P1_KDIV78*/
+#define R0900_P1_KDIV78 0xf545
+#define KDIV78 REGx(R0900_P1_KDIV78)
+#define F0900_P1_K_DIVIDER_78 0xf545007f
+
+/*P1_PDELCTRL1*/
+#define R0900_P1_PDELCTRL1 0xf550
+#define PDELCTRL1 REGx(R0900_P1_PDELCTRL1)
+#define F0900_P1_INV_MISMASK 0xf5500080
+#define F0900_P1_FILTER_EN 0xf5500020
+#define F0900_P1_EN_MIS00 0xf5500002
+#define F0900_P1_ALGOSWRST 0xf5500001
+#define ALGOSWRST FLDx(F0900_P1_ALGOSWRST)
+
+/*P1_PDELCTRL2*/
+#define R0900_P1_PDELCTRL2 0xf551
+#define PDELCTRL2 REGx(R0900_P1_PDELCTRL2)
+#define F0900_P1_RESET_UPKO_COUNT 0xf5510040
+#define RESET_UPKO_COUNT FLDx(F0900_P1_RESET_UPKO_COUNT)
+#define F0900_P1_FRAME_MODE 0xf5510002
+#define F0900_P1_NOBCHERRFLG_USE 0xf5510001
+
+/*P1_HYSTTHRESH*/
+#define R0900_P1_HYSTTHRESH 0xf554
+#define HYSTTHRESH REGx(R0900_P1_HYSTTHRESH)
+#define F0900_P1_UNLCK_THRESH 0xf55400f0
+#define F0900_P1_DELIN_LCK_THRESH 0xf554000f
+
+/*P1_ISIENTRY*/
+#define R0900_P1_ISIENTRY 0xf55e
+#define ISIENTRY REGx(R0900_P1_ISIENTRY)
+#define F0900_P1_ISI_ENTRY 0xf55e00ff
+
+/*P1_ISIBITENA*/
+#define R0900_P1_ISIBITENA 0xf55f
+#define ISIBITENA REGx(R0900_P1_ISIBITENA)
+#define F0900_P1_ISI_BIT_EN 0xf55f00ff
+
+/*P1_MATSTR1*/
+#define R0900_P1_MATSTR1 0xf560
+#define MATSTR1 REGx(R0900_P1_MATSTR1)
+#define F0900_P1_MATYPE_CURRENT1 0xf56000ff
+
+/*P1_MATSTR0*/
+#define R0900_P1_MATSTR0 0xf561
+#define MATSTR0 REGx(R0900_P1_MATSTR0)
+#define F0900_P1_MATYPE_CURRENT0 0xf56100ff
+
+/*P1_UPLSTR1*/
+#define R0900_P1_UPLSTR1 0xf562
+#define UPLSTR1 REGx(R0900_P1_UPLSTR1)
+#define F0900_P1_UPL_CURRENT1 0xf56200ff
+
+/*P1_UPLSTR0*/
+#define R0900_P1_UPLSTR0 0xf563
+#define UPLSTR0 REGx(R0900_P1_UPLSTR0)
+#define F0900_P1_UPL_CURRENT0 0xf56300ff
+
+/*P1_DFLSTR1*/
+#define R0900_P1_DFLSTR1 0xf564
+#define DFLSTR1 REGx(R0900_P1_DFLSTR1)
+#define F0900_P1_DFL_CURRENT1 0xf56400ff
+
+/*P1_DFLSTR0*/
+#define R0900_P1_DFLSTR0 0xf565
+#define DFLSTR0 REGx(R0900_P1_DFLSTR0)
+#define F0900_P1_DFL_CURRENT0 0xf56500ff
+
+/*P1_SYNCSTR*/
+#define R0900_P1_SYNCSTR 0xf566
+#define SYNCSTR REGx(R0900_P1_SYNCSTR)
+#define F0900_P1_SYNC_CURRENT 0xf56600ff
+
+/*P1_SYNCDSTR1*/
+#define R0900_P1_SYNCDSTR1 0xf567
+#define SYNCDSTR1 REGx(R0900_P1_SYNCDSTR1)
+#define F0900_P1_SYNCD_CURRENT1 0xf56700ff
+
+/*P1_SYNCDSTR0*/
+#define R0900_P1_SYNCDSTR0 0xf568
+#define SYNCDSTR0 REGx(R0900_P1_SYNCDSTR0)
+#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_PKTDELIN_LOCK 0xf5690002
+#define PKTDELIN_LOCK FLDx(F0900_P1_PKTDELIN_LOCK)
+#define F0900_P1_FIRST_LOCK 0xf5690001
+
+/*P1_PDELSTATUS2*/
+#define R0900_P1_PDELSTATUS2 0xf56a
+#define F0900_P1_FRAME_MODCOD 0xf56a007c
+#define F0900_P1_FRAME_TYPE 0xf56a0003
+
+/*P1_BBFCRCKO1*/
+#define R0900_P1_BBFCRCKO1 0xf56b
+#define BBFCRCKO1 REGx(R0900_P1_BBFCRCKO1)
+#define F0900_P1_BBHCRC_KOCNT1 0xf56b00ff
+
+/*P1_BBFCRCKO0*/
+#define R0900_P1_BBFCRCKO0 0xf56c
+#define BBFCRCKO0 REGx(R0900_P1_BBFCRCKO0)
+#define F0900_P1_BBHCRC_KOCNT0 0xf56c00ff
+
+/*P1_UPCRCKO1*/
+#define R0900_P1_UPCRCKO1 0xf56d
+#define UPCRCKO1 REGx(R0900_P1_UPCRCKO1)
+#define F0900_P1_PKTCRC_KOCNT1 0xf56d00ff
+
+/*P1_UPCRCKO0*/
+#define R0900_P1_UPCRCKO0 0xf56e
+#define UPCRCKO0 REGx(R0900_P1_UPCRCKO0)
+#define F0900_P1_PKTCRC_KOCNT0 0xf56e00ff
+
+/*P1_PDELCTRL3*/
+#define R0900_P1_PDELCTRL3 0xf56f
+#define PDELCTRL3 REGx(R0900_P1_PDELCTRL3)
+#define F0900_P1_PKTDEL_CONTFAIL 0xf56f0080
+#define F0900_P1_NOFIFO_BCHERR 0xf56f0020
+
+/*P1_TSSTATEM*/
+#define R0900_P1_TSSTATEM 0xf570
+#define TSSTATEM REGx(R0900_P1_TSSTATEM)
+#define F0900_P1_TSDIL_ON 0xf5700080
+#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_TSOUT_NOSYNC 0xf5700001
+
+/*P1_TSCFGH*/
+#define R0900_P1_TSCFGH 0xf572
+#define TSCFGH REGx(R0900_P1_TSCFGH)
+#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
+#define RST_HWARE FLDx(F0900_P1_RST_HWARE)
+
+/*P1_TSCFGM*/
+#define R0900_P1_TSCFGM 0xf573
+#define TSCFGM REGx(R0900_P1_TSCFGM)
+#define F0900_P1_TSFIFO_MANSPEED 0xf57300c0
+#define F0900_P1_TSFIFO_PERMDATA 0xf5730020
+#define F0900_P1_TSFIFO_DPUNACT 0xf5730002
+#define F0900_P1_TSFIFO_INVDATA 0xf5730001
+
+/*P1_TSCFGL*/
+#define R0900_P1_TSCFGL 0xf574
+#define TSCFGL REGx(R0900_P1_TSCFGL)
+#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_BITSPEED 0xf5740003
+
+/*P1_TSINSDELH*/
+#define R0900_P1_TSINSDELH 0xf576
+#define TSINSDELH REGx(R0900_P1_TSINSDELH)
+#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_TSDIVN*/
+#define R0900_P1_TSDIVN 0xf579
+#define TSDIVN REGx(R0900_P1_TSDIVN)
+#define F0900_P1_TSFIFO_SPEEDMODE 0xf57900c0
+
+/*P1_TSCFG4*/
+#define R0900_P1_TSCFG4 0xf57a
+#define TSCFG4 REGx(R0900_P1_TSCFG4)
+#define F0900_P1_TSFIFO_TSSPEEDMODE 0xf57a00c0
+
+/*P1_TSSPEED*/
+#define R0900_P1_TSSPEED 0xf580
+#define TSSPEED REGx(R0900_P1_TSSPEED)
+#define F0900_P1_TSFIFO_OUTSPEED 0xf58000ff
+
+/*P1_TSSTATUS*/
+#define R0900_P1_TSSTATUS 0xf581
+#define TSSTATUS REGx(R0900_P1_TSSTATUS)
+#define F0900_P1_TSFIFO_LINEOK 0xf5810080
+#define TSFIFO_LINEOK FLDx(F0900_P1_TSFIFO_LINEOK)
+#define F0900_P1_TSFIFO_ERROR 0xf5810040
+#define F0900_P1_DIL_READY 0xf5810001
+
+/*P1_TSSTATUS2*/
+#define R0900_P1_TSSTATUS2 0xf582
+#define TSSTATUS2 REGx(R0900_P1_TSSTATUS2)
+#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_SCRAMBDETECT 0xf5820002
+
+/*P1_TSBITRATE1*/
+#define R0900_P1_TSBITRATE1 0xf583
+#define TSBITRATE1 REGx(R0900_P1_TSBITRATE1)
+#define F0900_P1_TSFIFO_BITRATE1 0xf58300ff
+
+/*P1_TSBITRATE0*/
+#define R0900_P1_TSBITRATE0 0xf584
+#define TSBITRATE0 REGx(R0900_P1_TSBITRATE0)
+#define F0900_P1_TSFIFO_BITRATE0 0xf58400ff
+
+/*P1_ERRCTRL1*/
+#define R0900_P1_ERRCTRL1 0xf598
+#define ERRCTRL1 REGx(R0900_P1_ERRCTRL1)
+#define F0900_P1_ERR_SOURCE1 0xf59800f0
+#define F0900_P1_NUM_EVENT1 0xf5980007
+
+/*P1_ERRCNT12*/
+#define R0900_P1_ERRCNT12 0xf599
+#define ERRCNT12 REGx(R0900_P1_ERRCNT12)
+#define F0900_P1_ERRCNT1_OLDVALUE 0xf5990080
+#define F0900_P1_ERR_CNT12 0xf599007f
+#define ERR_CNT12 FLDx(F0900_P1_ERR_CNT12)
+
+/*P1_ERRCNT11*/
+#define R0900_P1_ERRCNT11 0xf59a
+#define ERRCNT11 REGx(R0900_P1_ERRCNT11)
+#define F0900_P1_ERR_CNT11 0xf59a00ff
+#define ERR_CNT11 FLDx(F0900_P1_ERR_CNT11)
+
+/*P1_ERRCNT10*/
+#define R0900_P1_ERRCNT10 0xf59b
+#define ERRCNT10 REGx(R0900_P1_ERRCNT10)
+#define F0900_P1_ERR_CNT10 0xf59b00ff
+#define ERR_CNT10 FLDx(F0900_P1_ERR_CNT10)
+
+/*P1_ERRCTRL2*/
+#define R0900_P1_ERRCTRL2 0xf59c
+#define ERRCTRL2 REGx(R0900_P1_ERRCTRL2)
+#define F0900_P1_ERR_SOURCE2 0xf59c00f0
+#define F0900_P1_NUM_EVENT2 0xf59c0007
+
+/*P1_ERRCNT22*/
+#define R0900_P1_ERRCNT22 0xf59d
+#define ERRCNT22 REGx(R0900_P1_ERRCNT22)
+#define F0900_P1_ERRCNT2_OLDVALUE 0xf59d0080
+#define F0900_P1_ERR_CNT22 0xf59d007f
+#define ERR_CNT22 FLDx(F0900_P1_ERR_CNT22)
+
+/*P1_ERRCNT21*/
+#define R0900_P1_ERRCNT21 0xf59e
+#define ERRCNT21 REGx(R0900_P1_ERRCNT21)
+#define F0900_P1_ERR_CNT21 0xf59e00ff
+#define ERR_CNT21 FLDx(F0900_P1_ERR_CNT21)
+
+/*P1_ERRCNT20*/
+#define R0900_P1_ERRCNT20 0xf59f
+#define ERRCNT20 REGx(R0900_P1_ERRCNT20)
+#define F0900_P1_ERR_CNT20 0xf59f00ff
+#define ERR_CNT20 FLDx(F0900_P1_ERR_CNT20)
+
+/*P1_FECSPY*/
+#define R0900_P1_FECSPY 0xf5a0
+#define FECSPY REGx(R0900_P1_FECSPY)
+#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_BERMETER_DATAMODE 0xf5a00008
+#define F0900_P1_BERMETER_LMODE 0xf5a00002
+#define F0900_P1_BERMETER_RESET 0xf5a00001
+
+/*P1_FSPYCFG*/
+#define R0900_P1_FSPYCFG 0xf5a1
+#define FSPYCFG REGx(R0900_P1_FSPYCFG)
+#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 FSPYDATA REGx(R0900_P1_FSPYDATA)
+#define F0900_P1_SPY_STUFFING 0xf5a20080
+#define F0900_P1_SPY_CNULLPKT 0xf5a20020
+#define F0900_P1_SPY_OUTDATA_MODE 0xf5a2001f
+
+/*P1_FSPYOUT*/
+#define R0900_P1_FSPYOUT 0xf5a3
+#define FSPYOUT REGx(R0900_P1_FSPYOUT)
+#define F0900_P1_FSPY_DIRECT 0xf5a30080
+#define F0900_P1_STUFF_MODE 0xf5a30007
+
+/*P1_FSTATUS*/
+#define R0900_P1_FSTATUS 0xf5a4
+#define FSTATUS REGx(R0900_P1_FSTATUS)
+#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 FBERCPT4 REGx(R0900_P1_FBERCPT4)
+#define F0900_P1_FBERMETER_CPT4 0xf5a800ff
+
+/*P1_FBERCPT3*/
+#define R0900_P1_FBERCPT3 0xf5a9
+#define FBERCPT3 REGx(R0900_P1_FBERCPT3)
+#define F0900_P1_FBERMETER_CPT3 0xf5a900ff
+
+/*P1_FBERCPT2*/
+#define R0900_P1_FBERCPT2 0xf5aa
+#define FBERCPT2 REGx(R0900_P1_FBERCPT2)
+#define F0900_P1_FBERMETER_CPT2 0xf5aa00ff
+
+/*P1_FBERCPT1*/
+#define R0900_P1_FBERCPT1 0xf5ab
+#define FBERCPT1 REGx(R0900_P1_FBERCPT1)
+#define F0900_P1_FBERMETER_CPT1 0xf5ab00ff
+
+/*P1_FBERCPT0*/
+#define R0900_P1_FBERCPT0 0xf5ac
+#define FBERCPT0 REGx(R0900_P1_FBERCPT0)
+#define F0900_P1_FBERMETER_CPT0 0xf5ac00ff
+
+/*P1_FBERERR2*/
+#define R0900_P1_FBERERR2 0xf5ad
+#define FBERERR2 REGx(R0900_P1_FBERERR2)
+#define F0900_P1_FBERMETER_ERR2 0xf5ad00ff
+
+/*P1_FBERERR1*/
+#define R0900_P1_FBERERR1 0xf5ae
+#define FBERERR1 REGx(R0900_P1_FBERERR1)
+#define F0900_P1_FBERMETER_ERR1 0xf5ae00ff
+
+/*P1_FBERERR0*/
+#define R0900_P1_FBERERR0 0xf5af
+#define FBERERR0 REGx(R0900_P1_FBERERR0)
+#define F0900_P1_FBERMETER_ERR0 0xf5af00ff
+
+/*P1_FSPYBER*/
+#define R0900_P1_FSPYBER 0xf5b2
+#define FSPYBER REGx(R0900_P1_FSPYBER)
+#define F0900_P1_FSPYBER_SYNCBYTE 0xf5b20010
+#define F0900_P1_FSPYBER_UNSYNC 0xf5b20008
+#define F0900_P1_FSPYBER_CTIME 0xf5b20007
+
+/*RCCFG2*/
+#define R0900_RCCFG2 0xf600
+
+/*TSGENERAL*/
+#define R0900_TSGENERAL 0xf630
+#define F0900_TSFIFO_DISTS2PAR 0xf6300040
+#define F0900_MUXSTREAM_OUTMODE 0xf6300008
+#define F0900_TSFIFO_PERMPARAL 0xf6300006
+
+/*TSGENERAL1X*/
+#define R0900_TSGENERAL1X 0xf670
+
+/*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_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
+
+/*P2_TCTL4*/
+#define R0900_P2_TCTL4 0xff28
+#define F0900_P2_PN4_SELECT 0xff280020
+
+/*P1_TCTL4*/
+#define R0900_P1_TCTL4 0xff48
+#define TCTL4 shiftx(R0900_P1_TCTL4, demod, 0x20)
+#define F0900_P1_PN4_SELECT 0xff480020
+
+/*P2_TSTDISRX*/
+#define R0900_P2_TSTDISRX 0xff65
+#define F0900_P2_PIN_SELECT1 0xff650008
+
+/*P1_TSTDISRX*/
+#define R0900_P1_TSTDISRX 0xff67
+#define TSTDISRX shiftx(R0900_P1_TSTDISRX, demod, 2)
+#define F0900_P1_PIN_SELECT1 0xff670008
+#define PIN_SELECT1 shiftx(F0900_P1_PIN_SELECT1, demod, 0x20000)
+
+#define STV0900_NBREGS 723
+#define STV0900_NBFIELDS 1420
+
+#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..4af2078
--- /dev/null
+++ b/drivers/media/dvb-frontends/stv0900_sw.c
@@ -0,0 +1,2032 @@
+/*
+ * 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"
+
+s32 shiftx(s32 x, int demod, s32 shift)
+{
+	if (demod == 1)
+		return x - shift;
+
+	return x;
+}
+
+int stv0900_check_signal_presence(struct stv0900_internal *intp,
+					enum fe_stv0900_demod_num demod)
+{
+	s32	carr_offset,
+		agc2_integr,
+		max_carrier;
+
+	int no_signal = FALSE;
+
+	carr_offset = (stv0900_read_reg(intp, CFR2) << 8)
+					| stv0900_read_reg(intp, CFR1);
+	carr_offset = ge2comp(carr_offset, 16);
+	agc2_integr = (stv0900_read_reg(intp, AGC2I1) << 8)
+					| stv0900_read_reg(intp, AGC2I0);
+	max_carrier = intp->srch_range[demod] / 1000;
+
+	max_carrier += (max_carrier / 10);
+	max_carrier = 65536 * (max_carrier / 2);
+	max_carrier /= intp->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;
+
+	return no_signal;
+}
+
+static void stv0900_get_sw_loop_params(struct stv0900_internal *intp,
+				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;
+
+	srate = intp->symbol_rate[demod];
+	max_carrier = intp->srch_range[demod] / 1000;
+	max_carrier += max_carrier / 10;
+	standard = intp->srch_standard[demod];
+
+	max_carrier = 65536 * (max_carrier / 2);
+	max_carrier /= intp->mclk / 1000;
+
+	if (max_carrier > 0x4000)
+		max_carrier = 0x4000;
+
+	freq_inc = srate;
+	freq_inc /= intp->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 *intp,
+				s32 FreqIncr, s32 Timeout, int zigzag,
+				s32 MaxStep, enum fe_stv0900_demod_num demod)
+{
+	int	no_signal,
+		lock = FALSE;
+	s32	stepCpt,
+		freqOffset,
+		max_carrier;
+
+	max_carrier = intp->srch_range[demod] / 1000;
+	max_carrier += (max_carrier / 10);
+
+	max_carrier = 65536 * (max_carrier / 2);
+	max_carrier /= intp->mclk / 1000;
+
+	if (max_carrier > 0x4000)
+		max_carrier = 0x4000;
+
+	if (zigzag == TRUE)
+		freqOffset = 0;
+	else
+		freqOffset = -max_carrier + FreqIncr;
+
+	stepCpt = 0;
+
+	do {
+		stv0900_write_reg(intp, DMDISTATE, 0x1c);
+		stv0900_write_reg(intp, CFRINIT1, (freqOffset / 256) & 0xff);
+		stv0900_write_reg(intp, CFRINIT0, freqOffset & 0xff);
+		stv0900_write_reg(intp, DMDISTATE, 0x18);
+		stv0900_write_bits(intp, ALGOSWRST, 1);
+
+		if (intp->chip_id == 0x12) {
+			stv0900_write_bits(intp, RST_HWARE, 1);
+			stv0900_write_bits(intp, RST_HWARE, 0);
+		}
+
+		if (zigzag == TRUE) {
+			if (freqOffset >= 0)
+				freqOffset = -freqOffset - 2 * FreqIncr;
+			else
+				freqOffset = -freqOffset;
+		} else
+			freqOffset += + 2 * FreqIncr;
+
+		stepCpt++;
+		lock = stv0900_get_demod_lock(intp, demod, Timeout);
+		no_signal = stv0900_check_signal_presence(intp, demod);
+
+	} while ((lock == FALSE)
+			&& (no_signal == FALSE)
+			&& ((freqOffset - FreqIncr) <  max_carrier)
+			&& ((freqOffset + FreqIncr) > -max_carrier)
+			&& (stepCpt < MaxStep));
+
+	stv0900_write_bits(intp, ALGOSWRST, 0);
+
+	return lock;
+}
+
+static int stv0900_sw_algo(struct stv0900_internal *intp,
+				enum fe_stv0900_demod_num demod)
+{
+	int	lock = FALSE,
+		no_signal,
+		zigzag;
+	s32	s2fw,
+		fqc_inc,
+		sft_stp_tout,
+		trial_cntr,
+		max_steps;
+
+	stv0900_get_sw_loop_params(intp, &fqc_inc, &sft_stp_tout,
+					&max_steps, demod);
+	switch (intp->srch_standard[demod]) {
+	case STV0900_SEARCH_DVBS1:
+	case STV0900_SEARCH_DSS:
+		if (intp->chip_id >= 0x20)
+			stv0900_write_reg(intp, CARFREQ, 0x3b);
+		else
+			stv0900_write_reg(intp, CARFREQ, 0xef);
+
+		stv0900_write_reg(intp, DMDCFGMD, 0x49);
+		zigzag = FALSE;
+		break;
+	case STV0900_SEARCH_DVBS2:
+		if (intp->chip_id >= 0x20)
+			stv0900_write_reg(intp, CORRELABS, 0x79);
+		else
+			stv0900_write_reg(intp, CORRELABS, 0x68);
+
+		stv0900_write_reg(intp, DMDCFGMD, 0x89);
+
+		zigzag = TRUE;
+		break;
+	case STV0900_AUTO_SEARCH:
+	default:
+		if (intp->chip_id >= 0x20) {
+			stv0900_write_reg(intp, CARFREQ, 0x3b);
+			stv0900_write_reg(intp, CORRELABS, 0x79);
+		} else {
+			stv0900_write_reg(intp, CARFREQ, 0xef);
+			stv0900_write_reg(intp, CORRELABS, 0x68);
+		}
+
+		stv0900_write_reg(intp, DMDCFGMD, 0xc9);
+		zigzag = FALSE;
+		break;
+	}
+
+	trial_cntr = 0;
+	do {
+		lock = stv0900_search_carr_sw_loop(intp,
+						fqc_inc,
+						sft_stp_tout,
+						zigzag,
+						max_steps,
+						demod);
+		no_signal = stv0900_check_signal_presence(intp, demod);
+		trial_cntr++;
+		if ((lock == TRUE)
+				|| (no_signal == TRUE)
+				|| (trial_cntr == 2)) {
+
+			if (intp->chip_id >= 0x20) {
+				stv0900_write_reg(intp, CARFREQ, 0x49);
+				stv0900_write_reg(intp, CORRELABS, 0x9e);
+			} else {
+				stv0900_write_reg(intp, CARFREQ, 0xed);
+				stv0900_write_reg(intp, CORRELABS, 0x88);
+			}
+
+			if ((stv0900_get_bits(intp, HEADER_MODE) ==
+						STV0900_DVBS2_FOUND) &&
+							(lock == TRUE)) {
+				msleep(sft_stp_tout);
+				s2fw = stv0900_get_bits(intp, FLYWHEEL_CPT);
+
+				if (s2fw < 0xd) {
+					msleep(sft_stp_tout);
+					s2fw = stv0900_get_bits(intp,
+								FLYWHEEL_CPT);
+				}
+
+				if (s2fw < 0xd) {
+					lock = FALSE;
+
+					if (trial_cntr < 2) {
+						if (intp->chip_id >= 0x20)
+							stv0900_write_reg(intp,
+								CORRELABS,
+								0x79);
+						else
+							stv0900_write_reg(intp,
+								CORRELABS,
+								0x68);
+
+						stv0900_write_reg(intp,
+								DMDCFGMD,
+								0x89);
+					}
+				}
+			}
+		}
+
+	} while ((lock == FALSE)
+		&& (trial_cntr < 2)
+		&& (no_signal == FALSE));
+
+	return lock;
+}
+
+static u32 stv0900_get_symbol_rate(struct stv0900_internal *intp,
+					u32 mclk,
+					enum fe_stv0900_demod_num demod)
+{
+	s32	rem1, rem2, intval1, intval2, srate;
+
+	srate = (stv0900_get_bits(intp, SYMB_FREQ3) << 24) +
+		(stv0900_get_bits(intp, SYMB_FREQ2) << 16) +
+		(stv0900_get_bits(intp, SYMB_FREQ1) << 8) +
+		(stv0900_get_bits(intp, SYMB_FREQ0));
+	dprintk("lock: srate=%d r0=0x%x r1=0x%x r2=0x%x r3=0x%x \n",
+		srate, stv0900_get_bits(intp, SYMB_FREQ0),
+		stv0900_get_bits(intp, SYMB_FREQ1),
+		stv0900_get_bits(intp, SYMB_FREQ2),
+		stv0900_get_bits(intp, SYMB_FREQ3));
+
+	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 *intp,
+					u32 mclk, u32 srate,
+					enum fe_stv0900_demod_num demod)
+{
+	u32 symb;
+
+	dprintk("%s: Mclk %d, SR %d, Dmd %d\n", __func__, mclk,
+							srate, demod);
+
+	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(intp, SFRINIT1, (symb >> 8) & 0x7f);
+	stv0900_write_reg(intp, SFRINIT1 + 1, (symb & 0xff));
+}
+
+static void stv0900_set_max_symbol_rate(struct stv0900_internal *intp,
+					u32 mclk, u32 srate,
+					enum fe_stv0900_demod_num demod)
+{
+	u32 symb;
+
+	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(intp, SFRUP1, (symb >> 8) & 0x7f);
+		stv0900_write_reg(intp, SFRUP1 + 1, (symb & 0xff));
+	} else {
+		stv0900_write_reg(intp, SFRUP1, 0x7f);
+		stv0900_write_reg(intp, SFRUP1 + 1, 0xff);
+	}
+}
+
+static void stv0900_set_min_symbol_rate(struct stv0900_internal *intp,
+					u32 mclk, u32 srate,
+					enum fe_stv0900_demod_num demod)
+{
+	u32	symb;
+
+	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(intp, SFRLOW1, (symb >> 8) & 0xff);
+	stv0900_write_reg(intp, SFRLOW1 + 1, (symb & 0xff));
+}
+
+static s32 stv0900_get_timing_offst(struct stv0900_internal *intp,
+					u32 srate,
+					enum fe_stv0900_demod_num demod)
+{
+	s32 timingoffset;
+
+
+	timingoffset = (stv0900_read_reg(intp, TMGREG2) << 16) +
+		       (stv0900_read_reg(intp, TMGREG2 + 1) << 8) +
+		       (stv0900_read_reg(intp, TMGREG2 + 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 *intp,
+					enum fe_stv0900_demod_num demod)
+{
+	s32 rolloff;
+
+	if (intp->chip_id == 0x10) {
+		stv0900_write_bits(intp, MANUALSX_ROLLOFF, 1);
+		rolloff = stv0900_read_reg(intp, MATSTR1) & 0x03;
+		stv0900_write_bits(intp, ROLLOFF_CONTROL, rolloff);
+	} else if (intp->chip_id <= 0x20)
+		stv0900_write_bits(intp, MANUALSX_ROLLOFF, 0);
+	else /* cut 3.0 */
+		stv0900_write_bits(intp, MANUALS2_ROLLOFF, 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 *intp,
+				enum fe_stv0900_demod_num demod)
+{
+	int timingLock = FALSE;
+	s32	i,
+		timingcpt = 0;
+	u8	car_freq,
+		tmg_th_high,
+		tmg_th_low;
+
+	car_freq = stv0900_read_reg(intp, CARFREQ);
+	tmg_th_high = stv0900_read_reg(intp, TMGTHRISE);
+	tmg_th_low = stv0900_read_reg(intp, TMGTHFALL);
+	stv0900_write_reg(intp, TMGTHRISE, 0x20);
+	stv0900_write_reg(intp, TMGTHFALL, 0x0);
+	stv0900_write_bits(intp, CFR_AUTOSCAN, 0);
+	stv0900_write_reg(intp, RTC, 0x80);
+	stv0900_write_reg(intp, RTCS2, 0x40);
+	stv0900_write_reg(intp, CARFREQ, 0x0);
+	stv0900_write_reg(intp, CFRINIT1, 0x0);
+	stv0900_write_reg(intp, CFRINIT0, 0x0);
+	stv0900_write_reg(intp, AGC2REF, 0x65);
+	stv0900_write_reg(intp, DMDISTATE, 0x18);
+	msleep(7);
+
+	for (i = 0; i < 10; i++) {
+		if (stv0900_get_bits(intp, TMGLOCK_QUALITY) >= 2)
+			timingcpt++;
+
+		msleep(1);
+	}
+
+	if (timingcpt >= 3)
+		timingLock = TRUE;
+
+	stv0900_write_reg(intp, AGC2REF, 0x38);
+	stv0900_write_reg(intp, RTC, 0x88);
+	stv0900_write_reg(intp, RTCS2, 0x68);
+	stv0900_write_reg(intp, CARFREQ, car_freq);
+	stv0900_write_reg(intp, TMGTHRISE, tmg_th_high);
+	stv0900_write_reg(intp, TMGTHFALL, tmg_th_low);
+
+	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 *intp = state->internal;
+	enum fe_stv0900_demod_num demod = state->demod;
+	int	lock = FALSE,
+		d = demod;
+	s32	srate,
+		search_range,
+		locktimeout,
+		currier_step,
+		nb_steps,
+		current_step,
+		direction,
+		tuner_freq,
+		timeout,
+		freq;
+
+	srate = intp->symbol_rate[d];
+	search_range = intp->srch_range[d];
+
+	if (srate >= 10000000)
+		locktimeout = demod_timeout / 3;
+	else
+		locktimeout = demod_timeout / 2;
+
+	lock = stv0900_get_demod_lock(intp, d, locktimeout);
+
+	if (lock != FALSE)
+		return lock;
+
+	if (srate >= 10000000) {
+		if (stv0900_check_timing_lock(intp, d) == TRUE) {
+			stv0900_write_reg(intp, DMDISTATE, 0x1f);
+			stv0900_write_reg(intp, DMDISTATE, 0x15);
+			lock = stv0900_get_demod_lock(intp, d, demod_timeout);
+		} else
+			lock = FALSE;
+
+		return lock;
+	}
+
+	if (intp->chip_id <= 0x20) {
+		if (srate <= 1000000)
+			currier_step = 500;
+		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;
+
+		if (srate >= 2000000) {
+			timeout = (demod_timeout / 3);
+			if (timeout > 1000)
+				timeout = 1000;
+		} else
+			timeout = (demod_timeout / 2);
+	} else {
+		/*cut 3.0 */
+		currier_step = srate / 4000;
+		timeout = (demod_timeout * 3) / 4;
+	}
+
+	nb_steps = ((search_range / 1000) / currier_step);
+
+	if ((nb_steps % 2) != 0)
+		nb_steps += 1;
+
+	if (nb_steps <= 0)
+		nb_steps = 2;
+	else if (nb_steps > 12)
+		nb_steps = 12;
+
+	current_step = 1;
+	direction = 1;
+
+	if (intp->chip_id <= 0x20) {
+		tuner_freq = intp->freq[d];
+		intp->bw[d] = stv0900_carrier_width(intp->symbol_rate[d],
+				intp->rolloff) + intp->symbol_rate[d];
+	} else
+		tuner_freq = 0;
+
+	while ((current_step <= nb_steps) && (lock == FALSE)) {
+		if (direction > 0)
+			tuner_freq += (current_step * currier_step);
+		else
+			tuner_freq -= (current_step * currier_step);
+
+		if (intp->chip_id <= 0x20) {
+			if (intp->tuner_type[d] == 3)
+				stv0900_set_tuner_auto(intp, tuner_freq,
+						intp->bw[d], demod);
+			else
+				stv0900_set_tuner(fe, tuner_freq, intp->bw[d]);
+
+			stv0900_write_reg(intp, DMDISTATE, 0x1c);
+			stv0900_write_reg(intp, CFRINIT1, 0);
+			stv0900_write_reg(intp, CFRINIT0, 0);
+			stv0900_write_reg(intp, DMDISTATE, 0x1f);
+			stv0900_write_reg(intp, DMDISTATE, 0x15);
+		} else {
+			stv0900_write_reg(intp, DMDISTATE, 0x1c);
+			freq = (tuner_freq * 65536) / (intp->mclk / 1000);
+			stv0900_write_bits(intp, CFR_INIT1, MSB(freq));
+			stv0900_write_bits(intp, CFR_INIT0, LSB(freq));
+			stv0900_write_reg(intp, DMDISTATE, 0x1f);
+			stv0900_write_reg(intp, DMDISTATE, 0x05);
+		}
+
+		lock = stv0900_get_demod_lock(intp, d, timeout);
+		direction *= -1;
+		current_step++;
+	}
+
+	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 *intp,
+					enum fe_stv0900_demod_num demod)
+{
+
+	s32 vth_reg = VTH12;
+
+	dprintk("%s\n", __func__);
+
+	stv0900_write_reg(intp, vth_reg++, 0xd0);
+	stv0900_write_reg(intp, vth_reg++, 0x7d);
+	stv0900_write_reg(intp, vth_reg++, 0x53);
+	stv0900_write_reg(intp, vth_reg++, 0x2f);
+	stv0900_write_reg(intp, vth_reg++, 0x24);
+	stv0900_write_reg(intp, vth_reg++, 0x1f);
+}
+
+static void stv0900_set_viterbi_standard(struct stv0900_internal *intp,
+				   enum fe_stv0900_search_standard standard,
+				   enum fe_stv0900_fec fec,
+				   enum fe_stv0900_demod_num demod)
+{
+	dprintk("%s: ViterbiStandard = ", __func__);
+
+	switch (standard) {
+	case STV0900_AUTO_SEARCH:
+		dprintk("Auto\n");
+		stv0900_write_reg(intp, FECM, 0x10);
+		stv0900_write_reg(intp, PRVIT, 0x3f);
+		break;
+	case STV0900_SEARCH_DVBS1:
+		dprintk("DVBS1\n");
+		stv0900_write_reg(intp, FECM, 0x00);
+		switch (fec) {
+		case STV0900_FEC_UNKNOWN:
+		default:
+			stv0900_write_reg(intp, PRVIT, 0x2f);
+			break;
+		case STV0900_FEC_1_2:
+			stv0900_write_reg(intp, PRVIT, 0x01);
+			break;
+		case STV0900_FEC_2_3:
+			stv0900_write_reg(intp, PRVIT, 0x02);
+			break;
+		case STV0900_FEC_3_4:
+			stv0900_write_reg(intp, PRVIT, 0x04);
+			break;
+		case STV0900_FEC_5_6:
+			stv0900_write_reg(intp, PRVIT, 0x08);
+			break;
+		case STV0900_FEC_7_8:
+			stv0900_write_reg(intp, PRVIT, 0x20);
+			break;
+		}
+
+		break;
+	case STV0900_SEARCH_DSS:
+		dprintk("DSS\n");
+		stv0900_write_reg(intp, FECM, 0x80);
+		switch (fec) {
+		case STV0900_FEC_UNKNOWN:
+		default:
+			stv0900_write_reg(intp, PRVIT, 0x13);
+			break;
+		case STV0900_FEC_1_2:
+			stv0900_write_reg(intp, PRVIT, 0x01);
+			break;
+		case STV0900_FEC_2_3:
+			stv0900_write_reg(intp, PRVIT, 0x02);
+			break;
+		case STV0900_FEC_6_7:
+			stv0900_write_reg(intp, PRVIT, 0x10);
+			break;
+		}
+		break;
+	default:
+		break;
+	}
+}
+
+static enum fe_stv0900_fec stv0900_get_vit_fec(struct stv0900_internal *intp,
+						enum fe_stv0900_demod_num demod)
+{
+	enum fe_stv0900_fec prate;
+	s32 rate_fld = stv0900_get_bits(intp, VIT_CURPUN);
+
+	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 void stv0900_set_dvbs1_track_car_loop(struct stv0900_internal *intp,
+					enum fe_stv0900_demod_num demod,
+					u32 srate)
+{
+	if (intp->chip_id >= 0x30) {
+		if (srate >= 15000000) {
+			stv0900_write_reg(intp, ACLC, 0x2b);
+			stv0900_write_reg(intp, BCLC, 0x1a);
+		} else if ((srate >= 7000000) && (15000000 > srate)) {
+			stv0900_write_reg(intp, ACLC, 0x0c);
+			stv0900_write_reg(intp, BCLC, 0x1b);
+		} else if (srate < 7000000) {
+			stv0900_write_reg(intp, ACLC, 0x2c);
+			stv0900_write_reg(intp, BCLC, 0x1c);
+		}
+
+	} else { /*cut 2.0 and 1.x*/
+		stv0900_write_reg(intp, ACLC, 0x1a);
+		stv0900_write_reg(intp, BCLC, 0x09);
+	}
+
+}
+
+static void stv0900_track_optimization(struct dvb_frontend *fe)
+{
+	struct stv0900_state *state = fe->demodulator_priv;
+	struct stv0900_internal *intp = state->internal;
+	enum fe_stv0900_demod_num demod = state->demod;
+
+	s32	srate,
+		pilots,
+		aclc,
+		freq1,
+		freq0,
+		i = 0,
+		timed,
+		timef,
+		blind_tun_sw = 0,
+		modulation;
+
+	enum fe_stv0900_modcode foundModcod;
+
+	dprintk("%s\n", __func__);
+
+	srate = stv0900_get_symbol_rate(intp, intp->mclk, demod);
+	srate += stv0900_get_timing_offst(intp, srate, demod);
+
+	switch (intp->result[demod].standard) {
+	case STV0900_DVBS1_STANDARD:
+	case STV0900_DSS_STANDARD:
+		dprintk("%s: found DVB-S or DSS\n", __func__);
+		if (intp->srch_standard[demod] == STV0900_AUTO_SEARCH) {
+			stv0900_write_bits(intp, DVBS1_ENABLE, 1);
+			stv0900_write_bits(intp, DVBS2_ENABLE, 0);
+		}
+
+		stv0900_write_bits(intp, ROLLOFF_CONTROL, intp->rolloff);
+		stv0900_write_bits(intp, MANUALSX_ROLLOFF, 1);
+
+		if (intp->chip_id < 0x30) {
+			stv0900_write_reg(intp, ERRCTRL1, 0x75);
+			break;
+		}
+
+		if (stv0900_get_vit_fec(intp, demod) == STV0900_FEC_1_2) {
+			stv0900_write_reg(intp, GAUSSR0, 0x98);
+			stv0900_write_reg(intp, CCIR0, 0x18);
+		} else {
+			stv0900_write_reg(intp, GAUSSR0, 0x18);
+			stv0900_write_reg(intp, CCIR0, 0x18);
+		}
+
+		stv0900_write_reg(intp, ERRCTRL1, 0x75);
+		break;
+	case STV0900_DVBS2_STANDARD:
+		dprintk("%s: found DVB-S2\n", __func__);
+		stv0900_write_bits(intp, DVBS1_ENABLE, 0);
+		stv0900_write_bits(intp, DVBS2_ENABLE, 1);
+		stv0900_write_reg(intp, ACLC, 0);
+		stv0900_write_reg(intp, BCLC, 0);
+		if (intp->result[demod].frame_len == STV0900_LONG_FRAME) {
+			foundModcod = stv0900_get_bits(intp, DEMOD_MODCOD);
+			pilots = stv0900_get_bits(intp, DEMOD_TYPE) & 0x01;
+			aclc = stv0900_get_optim_carr_loop(srate,
+							foundModcod,
+							pilots,
+							intp->chip_id);
+			if (foundModcod <= STV0900_QPSK_910)
+				stv0900_write_reg(intp, ACLC2S2Q, aclc);
+			else if (foundModcod <= STV0900_8PSK_910) {
+				stv0900_write_reg(intp, ACLC2S2Q, 0x2a);
+				stv0900_write_reg(intp, ACLC2S28, aclc);
+			}
+
+			if ((intp->demod_mode == STV0900_SINGLE) &&
+					(foundModcod > STV0900_8PSK_910)) {
+				if (foundModcod <= STV0900_16APSK_910) {
+					stv0900_write_reg(intp, ACLC2S2Q, 0x2a);
+					stv0900_write_reg(intp, ACLC2S216A,
+									aclc);
+				} else if (foundModcod <= STV0900_32APSK_910) {
+					stv0900_write_reg(intp, ACLC2S2Q, 0x2a);
+					stv0900_write_reg(intp,	ACLC2S232A,
+									aclc);
+				}
+			}
+
+		} else {
+			modulation = intp->result[demod].modulation;
+			aclc = stv0900_get_optim_short_carr_loop(srate,
+					modulation, intp->chip_id);
+			if (modulation == STV0900_QPSK)
+				stv0900_write_reg(intp, ACLC2S2Q, aclc);
+			else if (modulation == STV0900_8PSK) {
+				stv0900_write_reg(intp, ACLC2S2Q, 0x2a);
+				stv0900_write_reg(intp, ACLC2S28, aclc);
+			} else if (modulation == STV0900_16APSK) {
+				stv0900_write_reg(intp, ACLC2S2Q, 0x2a);
+				stv0900_write_reg(intp, ACLC2S216A, aclc);
+			} else if (modulation == STV0900_32APSK) {
+				stv0900_write_reg(intp, ACLC2S2Q, 0x2a);
+				stv0900_write_reg(intp, ACLC2S232A, aclc);
+			}
+
+		}
+
+		if (intp->chip_id <= 0x11) {
+			if (intp->demod_mode != STV0900_SINGLE)
+				stv0900_activate_s2_modcod(intp, demod);
+
+		}
+
+		stv0900_write_reg(intp, ERRCTRL1, 0x67);
+		break;
+	case STV0900_UNKNOWN_STANDARD:
+	default:
+		dprintk("%s: found unknown standard\n", __func__);
+		stv0900_write_bits(intp, DVBS1_ENABLE, 1);
+		stv0900_write_bits(intp, DVBS2_ENABLE, 1);
+		break;
+	}
+
+	freq1 = stv0900_read_reg(intp, CFR2);
+	freq0 = stv0900_read_reg(intp, CFR1);
+	if (intp->srch_algo[demod] == STV0900_BLIND_SEARCH) {
+		stv0900_write_reg(intp, SFRSTEP, 0x00);
+		stv0900_write_bits(intp, SCAN_ENABLE, 0);
+		stv0900_write_bits(intp, CFR_AUTOSCAN, 0);
+		stv0900_write_reg(intp, TMGCFG2, 0xc1);
+		stv0900_set_symbol_rate(intp, intp->mclk, srate, demod);
+		blind_tun_sw = 1;
+		if (intp->result[demod].standard != STV0900_DVBS2_STANDARD)
+			stv0900_set_dvbs1_track_car_loop(intp, demod, srate);
+
+	}
+
+	if (intp->chip_id >= 0x20) {
+		if ((intp->srch_standard[demod] == STV0900_SEARCH_DVBS1) ||
+				(intp->srch_standard[demod] ==
+							STV0900_SEARCH_DSS) ||
+				(intp->srch_standard[demod] ==
+							STV0900_AUTO_SEARCH)) {
+			stv0900_write_reg(intp, VAVSRVIT, 0x0a);
+			stv0900_write_reg(intp, VITSCALE, 0x0);
+		}
+	}
+
+	if (intp->chip_id < 0x20)
+		stv0900_write_reg(intp, CARHDR, 0x08);
+
+	if (intp->chip_id == 0x10)
+		stv0900_write_reg(intp, CORRELEXP, 0x0a);
+
+	stv0900_write_reg(intp, AGC2REF, 0x38);
+
+	if ((intp->chip_id >= 0x20) ||
+			(blind_tun_sw == 1) ||
+			(intp->symbol_rate[demod] < 10000000)) {
+		stv0900_write_reg(intp, CFRINIT1, freq1);
+		stv0900_write_reg(intp, CFRINIT0, freq0);
+		intp->bw[demod] = stv0900_carrier_width(srate,
+					intp->rolloff) + 10000000;
+
+		if ((intp->chip_id >= 0x20) || (blind_tun_sw == 1)) {
+			if (intp->srch_algo[demod] != STV0900_WARM_START) {
+				if (intp->tuner_type[demod] == 3)
+					stv0900_set_tuner_auto(intp,
+							intp->freq[demod],
+							intp->bw[demod],
+							demod);
+				else
+					stv0900_set_bandwidth(fe,
+							intp->bw[demod]);
+			}
+		}
+
+		if ((intp->srch_algo[demod] == STV0900_BLIND_SEARCH) ||
+				(intp->symbol_rate[demod] < 10000000))
+			msleep(50);
+		else
+			msleep(5);
+
+		stv0900_get_lock_timeout(&timed, &timef, srate,
+						STV0900_WARM_START);
+
+		if (stv0900_get_demod_lock(intp, demod, timed / 2) == FALSE) {
+			stv0900_write_reg(intp, DMDISTATE, 0x1f);
+			stv0900_write_reg(intp, CFRINIT1, freq1);
+			stv0900_write_reg(intp, CFRINIT0, freq0);
+			stv0900_write_reg(intp, DMDISTATE, 0x18);
+			i = 0;
+			while ((stv0900_get_demod_lock(intp,
+							demod,
+							timed / 2) == FALSE) &&
+						(i <= 2)) {
+				stv0900_write_reg(intp, DMDISTATE, 0x1f);
+				stv0900_write_reg(intp, CFRINIT1, freq1);
+				stv0900_write_reg(intp, CFRINIT0, freq0);
+				stv0900_write_reg(intp, DMDISTATE, 0x18);
+				i++;
+			}
+		}
+
+	}
+
+	if (intp->chip_id >= 0x20)
+		stv0900_write_reg(intp, CARFREQ, 0x49);
+
+	if ((intp->result[demod].standard == STV0900_DVBS1_STANDARD) ||
+			(intp->result[demod].standard == STV0900_DSS_STANDARD))
+		stv0900_set_viterbi_tracq(intp, demod);
+
+}
+
+static int stv0900_get_fec_lock(struct stv0900_internal *intp,
+				enum fe_stv0900_demod_num demod, s32 time_out)
+{
+	s32 timer = 0, lock = 0;
+
+	enum fe_stv0900_search_state dmd_state;
+
+	dprintk("%s\n", __func__);
+
+	dmd_state = stv0900_get_bits(intp, HEADER_MODE);
+
+	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(intp, PKTDELIN_LOCK);
+			break;
+		case STV0900_DVBS_FOUND:
+			lock = stv0900_get_bits(intp, LOCKEDVIT);
+			break;
+		}
+
+		if (lock == 0) {
+			msleep(10);
+			timer += 10;
+		}
+	}
+
+	if (lock)
+		dprintk("%s: DEMOD FEC LOCK OK\n", __func__);
+	else
+		dprintk("%s: DEMOD FEC LOCK FAIL\n", __func__);
+
+	return lock;
+}
+
+static int stv0900_wait_for_lock(struct stv0900_internal *intp,
+				enum fe_stv0900_demod_num demod,
+				s32 dmd_timeout, s32 fec_timeout)
+{
+
+	s32 timer = 0, lock = 0;
+
+	dprintk("%s\n", __func__);
+
+	lock = stv0900_get_demod_lock(intp, demod, dmd_timeout);
+
+	if (lock)
+		lock = lock && stv0900_get_fec_lock(intp, demod, fec_timeout);
+
+	if (lock) {
+		lock = 0;
+
+		dprintk("%s: Timer = %d, time_out = %d\n",
+				__func__, timer, fec_timeout);
+
+		while ((timer < fec_timeout) && (lock == 0)) {
+			lock = stv0900_get_bits(intp, TSFIFO_LINEOK);
+			msleep(1);
+			timer++;
+		}
+	}
+
+	if (lock)
+		dprintk("%s: DEMOD LOCK OK\n", __func__);
+	else
+		dprintk("%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 *intp = state->internal;
+	enum fe_stv0900_tracking_standard fnd_standard;
+
+	int hdr_mode = stv0900_get_bits(intp, HEADER_MODE);
+
+	switch (hdr_mode) {
+	case 2:
+		fnd_standard = STV0900_DVBS2_STANDARD;
+		break;
+	case 3:
+		if (stv0900_get_bits(intp, DSS_DVB) == 1)
+			fnd_standard = STV0900_DSS_STANDARD;
+		else
+			fnd_standard = STV0900_DVBS1_STANDARD;
+
+		break;
+	default:
+		fnd_standard = STV0900_UNKNOWN_STANDARD;
+	}
+
+	dprintk("%s: standard %d\n", __func__, fnd_standard);
+
+	return fnd_standard;
+}
+
+static s32 stv0900_get_carr_freq(struct stv0900_internal *intp, u32 mclk,
+					enum fe_stv0900_demod_num demod)
+{
+	s32	derot,
+		rem1,
+		rem2,
+		intval1,
+		intval2;
+
+	derot = (stv0900_get_bits(intp, CAR_FREQ2) << 16) +
+		(stv0900_get_bits(intp, CAR_FREQ1) << 8) +
+		(stv0900_get_bits(intp, CAR_FREQ0));
+
+	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 freq = 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, &freq)) < 0)
+			dprintk("%s: Invalid parameter\n", __func__);
+		else
+			dprintk("%s: Frequency=%d\n", __func__, freq);
+
+	}
+
+	return freq;
+}
+
+static enum
+fe_stv0900_signal_type stv0900_get_signal_params(struct dvb_frontend *fe)
+{
+	struct stv0900_state *state = fe->demodulator_priv;
+	struct stv0900_internal *intp = state->internal;
+	enum fe_stv0900_demod_num demod = state->demod;
+	enum fe_stv0900_signal_type range = STV0900_OUTOFRANGE;
+	struct stv0900_signal_info *result = &intp->result[demod];
+	s32	offsetFreq,
+		srate_offset;
+	int	i = 0,
+		d = demod;
+
+	u8 timing;
+
+	msleep(5);
+	if (intp->srch_algo[d] == STV0900_BLIND_SEARCH) {
+		timing = stv0900_read_reg(intp, TMGREG2);
+		i = 0;
+		stv0900_write_reg(intp, SFRSTEP, 0x5c);
+
+		while ((i <= 50) && (timing != 0) && (timing != 0xff)) {
+			timing = stv0900_read_reg(intp, TMGREG2);
+			msleep(5);
+			i += 5;
+		}
+	}
+
+	result->standard = stv0900_get_standard(fe, d);
+	if (intp->tuner_type[demod] == 3)
+		result->frequency = stv0900_get_freq_auto(intp, d);
+	else
+		result->frequency = stv0900_get_tuner_freq(fe);
+
+	offsetFreq = stv0900_get_carr_freq(intp, intp->mclk, d) / 1000;
+	result->frequency += offsetFreq;
+	result->symbol_rate = stv0900_get_symbol_rate(intp, intp->mclk, d);
+	srate_offset = stv0900_get_timing_offst(intp, result->symbol_rate, d);
+	result->symbol_rate += srate_offset;
+	result->fec = stv0900_get_vit_fec(intp, d);
+	result->modcode = stv0900_get_bits(intp, DEMOD_MODCOD);
+	result->pilot = stv0900_get_bits(intp, DEMOD_TYPE) & 0x01;
+	result->frame_len = ((u32)stv0900_get_bits(intp, DEMOD_TYPE)) >> 1;
+	result->rolloff = stv0900_get_bits(intp, ROLLOFF_STATUS);
+
+	dprintk("%s: modcode=0x%x \n", __func__, result->modcode);
+
+	switch (result->standard) {
+	case STV0900_DVBS2_STANDARD:
+		result->spectrum = stv0900_get_bits(intp, SPECINV_DEMOD);
+		if (result->modcode <= STV0900_QPSK_910)
+			result->modulation = STV0900_QPSK;
+		else if (result->modcode <= STV0900_8PSK_910)
+			result->modulation = STV0900_8PSK;
+		else if (result->modcode <= STV0900_16APSK_910)
+			result->modulation = STV0900_16APSK;
+		else if (result->modcode <= STV0900_32APSK_910)
+			result->modulation = STV0900_32APSK;
+		else
+			result->modulation = STV0900_UNKNOWN;
+		break;
+	case STV0900_DVBS1_STANDARD:
+	case STV0900_DSS_STANDARD:
+		result->spectrum = stv0900_get_bits(intp, IQINV);
+		result->modulation = STV0900_QPSK;
+		break;
+	default:
+		break;
+	}
+
+	if ((intp->srch_algo[d] == STV0900_BLIND_SEARCH) ||
+				(intp->symbol_rate[d] < 10000000)) {
+		offsetFreq = result->frequency - intp->freq[d];
+		if (intp->tuner_type[demod] == 3)
+			intp->freq[d] = stv0900_get_freq_auto(intp, d);
+		else
+			intp->freq[d] = stv0900_get_tuner_freq(fe);
+
+		if (ABS(offsetFreq) <= ((intp->srch_range[d] / 2000) + 500))
+			range = STV0900_RANGEOK;
+		else if (ABS(offsetFreq) <=
+				(stv0900_carrier_width(result->symbol_rate,
+						result->rolloff) / 2000))
+			range = STV0900_RANGEOK;
+
+	} else if (ABS(offsetFreq) <= ((intp->srch_range[d] / 2000) + 500))
+		range = STV0900_RANGEOK;
+
+	dprintk("%s: range %d\n", __func__, range);
+
+	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 *intp = state->internal;
+	enum fe_stv0900_demod_num demod = state->demod;
+	enum fe_stv0900_signal_type signal_type = STV0900_NODATA;
+
+	s32	srate,
+		demod_timeout,
+		fec_timeout,
+		freq1,
+		freq0;
+
+	intp->result[demod].locked = FALSE;
+
+	if (stv0900_get_bits(intp, HEADER_MODE) == STV0900_DVBS_FOUND) {
+		srate = stv0900_get_symbol_rate(intp, intp->mclk, demod);
+		srate += stv0900_get_timing_offst(intp, srate, demod);
+		if (intp->srch_algo[demod] == STV0900_BLIND_SEARCH)
+			stv0900_set_symbol_rate(intp, intp->mclk, srate, demod);
+
+		stv0900_get_lock_timeout(&demod_timeout, &fec_timeout,
+					srate, STV0900_WARM_START);
+		freq1 = stv0900_read_reg(intp, CFR2);
+		freq0 = stv0900_read_reg(intp, CFR1);
+		stv0900_write_bits(intp, CFR_AUTOSCAN, 0);
+		stv0900_write_bits(intp, SPECINV_CONTROL,
+					STV0900_IQ_FORCE_SWAPPED);
+		stv0900_write_reg(intp, DMDISTATE, 0x1c);
+		stv0900_write_reg(intp, CFRINIT1, freq1);
+		stv0900_write_reg(intp, CFRINIT0, freq0);
+		stv0900_write_reg(intp, DMDISTATE, 0x18);
+		if (stv0900_wait_for_lock(intp, demod,
+				demod_timeout, fec_timeout) == TRUE) {
+			intp->result[demod].locked = TRUE;
+			signal_type = stv0900_get_signal_params(fe);
+			stv0900_track_optimization(fe);
+		} else {
+			stv0900_write_bits(intp, SPECINV_CONTROL,
+					STV0900_IQ_FORCE_NORMAL);
+			stv0900_write_reg(intp, DMDISTATE, 0x1c);
+			stv0900_write_reg(intp, CFRINIT1, freq1);
+			stv0900_write_reg(intp, CFRINIT0, freq0);
+			stv0900_write_reg(intp, DMDISTATE, 0x18);
+			if (stv0900_wait_for_lock(intp, demod,
+					demod_timeout, fec_timeout) == TRUE) {
+				intp->result[demod].locked = TRUE;
+				signal_type = stv0900_get_signal_params(fe);
+				stv0900_track_optimization(fe);
+			}
+
+		}
+
+	} else
+		intp->result[demod].locked = FALSE;
+
+	return signal_type;
+}
+
+static u16 stv0900_blind_check_agc2_min_level(struct stv0900_internal *intp,
+					enum fe_stv0900_demod_num demod)
+{
+	u32 minagc2level = 0xffff,
+		agc2level,
+		init_freq, freq_step;
+
+	s32 i, j, nb_steps, direction;
+
+	dprintk("%s\n", __func__);
+
+	stv0900_write_reg(intp, AGC2REF, 0x38);
+	stv0900_write_bits(intp, SCAN_ENABLE, 0);
+	stv0900_write_bits(intp, CFR_AUTOSCAN, 0);
+
+	stv0900_write_bits(intp, AUTO_GUP, 1);
+	stv0900_write_bits(intp, AUTO_GLOW, 1);
+
+	stv0900_write_reg(intp, DMDT0M, 0x0);
+
+	stv0900_set_symbol_rate(intp, intp->mclk, 1000000, demod);
+	nb_steps = -1 + (intp->srch_range[demod] / 1000000);
+	nb_steps /= 2;
+	nb_steps = (2 * nb_steps) + 1;
+
+	if (nb_steps < 0)
+		nb_steps = 1;
+
+	direction = 1;
+
+	freq_step = (1000000 << 8) / (intp->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(intp, DMDISTATE, 0x5C);
+		stv0900_write_reg(intp, CFRINIT1, (init_freq >> 8) & 0xff);
+		stv0900_write_reg(intp, CFRINIT0, init_freq  & 0xff);
+		stv0900_write_reg(intp, DMDISTATE, 0x58);
+		msleep(10);
+		agc2level = 0;
+
+		for (j = 0; j < 10; j++)
+			agc2level += (stv0900_read_reg(intp, AGC2I1) << 8)
+					| stv0900_read_reg(intp, AGC2I0);
+
+		agc2level /= 10;
+
+		if (agc2level < minagc2level)
+			minagc2level = agc2level;
+
+	}
+
+	return (u16)minagc2level;
+}
+
+static u32 stv0900_search_srate_coarse(struct dvb_frontend *fe)
+{
+	struct stv0900_state *state = fe->demodulator_priv;
+	struct stv0900_internal *intp = state->internal;
+	enum fe_stv0900_demod_num demod = state->demod;
+	int timing_lck = FALSE;
+	s32 i, timingcpt = 0,
+		direction = 1,
+		nb_steps,
+		current_step = 0,
+		tuner_freq;
+	u32 agc2_th,
+		coarse_srate = 0,
+		agc2_integr = 0,
+		currier_step = 1200;
+
+	if (intp->chip_id >= 0x30)
+		agc2_th = 0x2e00;
+	else
+		agc2_th = 0x1f00;
+
+	stv0900_write_bits(intp, DEMOD_MODE, 0x1f);
+	stv0900_write_reg(intp, TMGCFG, 0x12);
+	stv0900_write_reg(intp, TMGTHRISE, 0xf0);
+	stv0900_write_reg(intp, TMGTHFALL, 0xe0);
+	stv0900_write_bits(intp, SCAN_ENABLE, 1);
+	stv0900_write_bits(intp, CFR_AUTOSCAN, 1);
+	stv0900_write_reg(intp, SFRUP1, 0x83);
+	stv0900_write_reg(intp, SFRUP0, 0xc0);
+	stv0900_write_reg(intp, SFRLOW1, 0x82);
+	stv0900_write_reg(intp, SFRLOW0, 0xa0);
+	stv0900_write_reg(intp, DMDT0M, 0x0);
+	stv0900_write_reg(intp, AGC2REF, 0x50);
+
+	if (intp->chip_id >= 0x30) {
+		stv0900_write_reg(intp, CARFREQ, 0x99);
+		stv0900_write_reg(intp, SFRSTEP, 0x98);
+	} else if (intp->chip_id >= 0x20) {
+		stv0900_write_reg(intp, CARFREQ, 0x6a);
+		stv0900_write_reg(intp, SFRSTEP, 0x95);
+	} else {
+		stv0900_write_reg(intp, CARFREQ, 0xed);
+		stv0900_write_reg(intp, SFRSTEP, 0x73);
+	}
+
+	if (intp->symbol_rate[demod] <= 2000000)
+		currier_step = 1000;
+	else if (intp->symbol_rate[demod] <= 5000000)
+		currier_step = 2000;
+	else if (intp->symbol_rate[demod] <= 12000000)
+		currier_step = 3000;
+	else
+			currier_step = 5000;
+
+	nb_steps = -1 + ((intp->srch_range[demod] / 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 = (intp->srch_range[demod] / 1000) / 10;
+	}
+
+	current_step = 0;
+	direction = 1;
+
+	tuner_freq = intp->freq[demod];
+
+	while ((timing_lck == FALSE) && (current_step < nb_steps)) {
+		stv0900_write_reg(intp, DMDISTATE, 0x5f);
+		stv0900_write_bits(intp, DEMOD_MODE, 0);
+
+		msleep(50);
+
+		for (i = 0; i < 10; i++) {
+			if (stv0900_get_bits(intp, TMGLOCK_QUALITY) >= 2)
+				timingcpt++;
+
+			agc2_integr += (stv0900_read_reg(intp, AGC2I1) << 8) |
+					stv0900_read_reg(intp, AGC2I0);
+		}
+
+		agc2_integr /= 10;
+		coarse_srate = stv0900_get_symbol_rate(intp, intp->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 < agc2_th) &&
+				(coarse_srate < 55000000) &&
+				(coarse_srate > 850000))
+			timing_lck = TRUE;
+		else if (current_step < nb_steps) {
+			if (direction > 0)
+				tuner_freq += (current_step * currier_step);
+			else
+				tuner_freq -= (current_step * currier_step);
+
+			if (intp->tuner_type[demod] == 3)
+				stv0900_set_tuner_auto(intp, tuner_freq,
+						intp->bw[demod], demod);
+			else
+				stv0900_set_tuner(fe, tuner_freq,
+						intp->bw[demod]);
+		}
+	}
+
+	if (timing_lck == FALSE)
+		coarse_srate = 0;
+	else
+		coarse_srate = stv0900_get_symbol_rate(intp, intp->mclk, demod);
+
+	return coarse_srate;
+}
+
+static u32 stv0900_search_srate_fine(struct dvb_frontend *fe)
+{
+	struct stv0900_state *state = fe->demodulator_priv;
+	struct stv0900_internal *intp = state->internal;
+	enum fe_stv0900_demod_num demod = state->demod;
+	u32	coarse_srate,
+		coarse_freq,
+		symb,
+		symbmax,
+		symbmin,
+		symbcomp;
+
+	coarse_srate = stv0900_get_symbol_rate(intp, intp->mclk, demod);
+
+	if (coarse_srate > 3000000) {
+		symbmax = 13 * (coarse_srate / 10);
+		symbmax = (symbmax / 1000) * 65536;
+		symbmax /= (intp->mclk / 1000);
+
+		symbmin = 10 * (coarse_srate / 13);
+		symbmin = (symbmin / 1000)*65536;
+		symbmin /= (intp->mclk / 1000);
+
+		symb = (coarse_srate / 1000) * 65536;
+		symb /= (intp->mclk / 1000);
+	} else {
+		symbmax = 13 * (coarse_srate / 10);
+		symbmax = (symbmax / 100) * 65536;
+		symbmax /= (intp->mclk / 100);
+
+		symbmin = 10 * (coarse_srate / 14);
+		symbmin = (symbmin / 100) * 65536;
+		symbmin /= (intp->mclk / 100);
+
+		symb = (coarse_srate / 100) * 65536;
+		symb /= (intp->mclk / 100);
+	}
+
+	symbcomp = 13 * (coarse_srate / 10);
+		coarse_freq = (stv0900_read_reg(intp, CFR2) << 8)
+					| stv0900_read_reg(intp, CFR1);
+
+	if (symbcomp < intp->symbol_rate[demod])
+		coarse_srate = 0;
+	else {
+		stv0900_write_reg(intp, DMDISTATE, 0x1f);
+		stv0900_write_reg(intp, TMGCFG2, 0xc1);
+		stv0900_write_reg(intp, TMGTHRISE, 0x20);
+		stv0900_write_reg(intp, TMGTHFALL, 0x00);
+		stv0900_write_reg(intp, TMGCFG, 0xd2);
+		stv0900_write_bits(intp, CFR_AUTOSCAN, 0);
+		stv0900_write_reg(intp, AGC2REF, 0x38);
+
+		if (intp->chip_id >= 0x30)
+			stv0900_write_reg(intp, CARFREQ, 0x79);
+		else if (intp->chip_id >= 0x20)
+			stv0900_write_reg(intp, CARFREQ, 0x49);
+		else
+			stv0900_write_reg(intp, CARFREQ, 0xed);
+
+		stv0900_write_reg(intp, SFRUP1, (symbmax >> 8) & 0x7f);
+		stv0900_write_reg(intp, SFRUP0, (symbmax & 0xff));
+
+		stv0900_write_reg(intp, SFRLOW1, (symbmin >> 8) & 0x7f);
+		stv0900_write_reg(intp, SFRLOW0, (symbmin & 0xff));
+
+		stv0900_write_reg(intp, SFRINIT1, (symb >> 8) & 0xff);
+		stv0900_write_reg(intp, SFRINIT0, (symb & 0xff));
+
+		stv0900_write_reg(intp, DMDT0M, 0x20);
+		stv0900_write_reg(intp, CFRINIT1, (coarse_freq >> 8) & 0xff);
+		stv0900_write_reg(intp, CFRINIT0, coarse_freq  & 0xff);
+		stv0900_write_reg(intp, DMDISTATE, 0x15);
+	}
+
+	return coarse_srate;
+}
+
+static int stv0900_blind_search_algo(struct dvb_frontend *fe)
+{
+	struct stv0900_state *state = fe->demodulator_priv;
+	struct stv0900_internal *intp = 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,
+		agc2_th;
+	int	lock = FALSE,
+		coarse_fail = FALSE;
+	s32	demod_timeout = 500,
+		fec_timeout = 50,
+		fail_cpt,
+		i,
+		agc2_overflow;
+	u16	agc2_int;
+	u8	dstatus2;
+
+	dprintk("%s\n", __func__);
+
+	if (intp->chip_id < 0x20) {
+		k_ref_tmg_max = 233;
+		k_ref_tmg_min = 143;
+	} else {
+		k_ref_tmg_max = 110;
+		k_ref_tmg_min = 10;
+	}
+
+	if (intp->chip_id <= 0x20)
+		agc2_th = STV0900_BLIND_SEARCH_AGC2_TH;
+	else
+		agc2_th = STV0900_BLIND_SEARCH_AGC2_TH_CUT30;
+
+	agc2_int = stv0900_blind_check_agc2_min_level(intp, demod);
+
+	dprintk("%s agc2_int=%d agc2_th=%d \n", __func__, agc2_int, agc2_th);
+	if (agc2_int > agc2_th)
+		return FALSE;
+
+	if (intp->chip_id == 0x10)
+		stv0900_write_reg(intp, CORRELEXP, 0xaa);
+
+	if (intp->chip_id < 0x20)
+		stv0900_write_reg(intp, CARHDR, 0x55);
+	else
+		stv0900_write_reg(intp, CARHDR, 0x20);
+
+	if (intp->chip_id <= 0x20)
+		stv0900_write_reg(intp, CARCFG, 0xc4);
+	else
+		stv0900_write_reg(intp, CARCFG, 0x6);
+
+	stv0900_write_reg(intp, RTCS2, 0x44);
+
+	if (intp->chip_id >= 0x20) {
+		stv0900_write_reg(intp, EQUALCFG, 0x41);
+		stv0900_write_reg(intp, FFECFG, 0x41);
+		stv0900_write_reg(intp, VITSCALE, 0x82);
+		stv0900_write_reg(intp, VAVSRVIT, 0x0);
+	}
+
+	k_ref_tmg = k_ref_tmg_max;
+
+	do {
+		stv0900_write_reg(intp, KREFTMG, 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(intp,
+							demod,
+							demod_timeout);
+			} else
+				lock = FALSE;
+		} else {
+			fail_cpt = 0;
+			agc2_overflow = 0;
+
+			for (i = 0; i < 10; i++) {
+				agc2_int = (stv0900_read_reg(intp, AGC2I1) << 8)
+					| stv0900_read_reg(intp, AGC2I0);
+
+				if (agc2_int >= 0xff00)
+					agc2_overflow++;
+
+				dstatus2 = stv0900_read_reg(intp, DSTATUS2);
+
+				if (((dstatus2 & 0x1) == 0x1) &&
+						((dstatus2 >> 7) == 1))
+					fail_cpt++;
+			}
+
+			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 *intp,
+					enum fe_stv0900_demod_num demod)
+{
+	s32 vth_reg = VTH12;
+
+	dprintk("%s\n", __func__);
+
+	stv0900_write_reg(intp, vth_reg++, 0x96);
+	stv0900_write_reg(intp, vth_reg++, 0x64);
+	stv0900_write_reg(intp, vth_reg++, 0x36);
+	stv0900_write_reg(intp, vth_reg++, 0x23);
+	stv0900_write_reg(intp, vth_reg++, 0x1e);
+	stv0900_write_reg(intp, vth_reg++, 0x19);
+}
+
+static void stv0900_set_search_standard(struct stv0900_internal *intp,
+					enum fe_stv0900_demod_num demod)
+{
+
+	dprintk("%s\n", __func__);
+
+	switch (intp->srch_standard[demod]) {
+	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 (intp->srch_standard[demod]) {
+	case STV0900_SEARCH_DVBS1:
+	case STV0900_SEARCH_DSS:
+		stv0900_write_bits(intp, DVBS1_ENABLE, 1);
+		stv0900_write_bits(intp, DVBS2_ENABLE, 0);
+		stv0900_write_bits(intp, STOP_CLKVIT, 0);
+		stv0900_set_dvbs1_track_car_loop(intp,
+						demod,
+						intp->symbol_rate[demod]);
+		stv0900_write_reg(intp, CAR2CFG, 0x22);
+
+		stv0900_set_viterbi_acq(intp, demod);
+		stv0900_set_viterbi_standard(intp,
+					intp->srch_standard[demod],
+					intp->fec[demod], demod);
+
+		break;
+	case STV0900_SEARCH_DVBS2:
+		stv0900_write_bits(intp, DVBS1_ENABLE, 0);
+		stv0900_write_bits(intp, DVBS2_ENABLE, 1);
+		stv0900_write_bits(intp, STOP_CLKVIT, 1);
+		stv0900_write_reg(intp, ACLC, 0x1a);
+		stv0900_write_reg(intp, BCLC, 0x09);
+		if (intp->chip_id <= 0x20) /*cut 1.x and 2.0*/
+			stv0900_write_reg(intp, CAR2CFG, 0x26);
+		else
+			stv0900_write_reg(intp, CAR2CFG, 0x66);
+
+		if (intp->demod_mode != STV0900_SINGLE) {
+			if (intp->chip_id <= 0x11)
+				stv0900_stop_all_s2_modcod(intp, demod);
+			else
+				stv0900_activate_s2_modcod(intp, demod);
+
+		} else
+			stv0900_activate_s2_modcod_single(intp, demod);
+
+		stv0900_set_viterbi_tracq(intp, demod);
+
+		break;
+	case STV0900_AUTO_SEARCH:
+	default:
+		stv0900_write_bits(intp, DVBS1_ENABLE, 1);
+		stv0900_write_bits(intp, DVBS2_ENABLE, 1);
+		stv0900_write_bits(intp, STOP_CLKVIT, 0);
+		stv0900_write_reg(intp, ACLC, 0x1a);
+		stv0900_write_reg(intp, BCLC, 0x09);
+		stv0900_set_dvbs1_track_car_loop(intp,
+						demod,
+						intp->symbol_rate[demod]);
+		if (intp->chip_id <= 0x20) /*cut 1.x and 2.0*/
+			stv0900_write_reg(intp, CAR2CFG, 0x26);
+		else
+			stv0900_write_reg(intp, CAR2CFG, 0x66);
+
+		if (intp->demod_mode != STV0900_SINGLE) {
+			if (intp->chip_id <= 0x11)
+				stv0900_stop_all_s2_modcod(intp, demod);
+			else
+				stv0900_activate_s2_modcod(intp, demod);
+
+		} else
+			stv0900_activate_s2_modcod_single(intp, demod);
+
+		stv0900_set_viterbi_tracq(intp, demod);
+		stv0900_set_viterbi_standard(intp,
+						intp->srch_standard[demod],
+						intp->fec[demod], demod);
+
+		break;
+	}
+}
+
+enum fe_stv0900_signal_type stv0900_algo(struct dvb_frontend *fe)
+{
+	struct stv0900_state *state = fe->demodulator_priv;
+	struct stv0900_internal *intp = state->internal;
+	enum fe_stv0900_demod_num demod = state->demod;
+
+	s32 demod_timeout = 500, fec_timeout = 50;
+	s32 aq_power, agc1_power, i;
+
+	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("%s\n", __func__);
+
+	algo = intp->srch_algo[demod];
+	stv0900_write_bits(intp, RST_HWARE, 1);
+	stv0900_write_reg(intp, DMDISTATE, 0x5c);
+	if (intp->chip_id >= 0x20) {
+		if (intp->symbol_rate[demod] > 5000000)
+			stv0900_write_reg(intp, CORRELABS, 0x9e);
+		else
+			stv0900_write_reg(intp, CORRELABS, 0x82);
+	} else
+		stv0900_write_reg(intp, CORRELABS, 0x88);
+
+	stv0900_get_lock_timeout(&demod_timeout, &fec_timeout,
+				intp->symbol_rate[demod],
+				intp->srch_algo[demod]);
+
+	if (intp->srch_algo[demod] == STV0900_BLIND_SEARCH) {
+		intp->bw[demod] = 2 * 36000000;
+
+		stv0900_write_reg(intp, TMGCFG2, 0xc0);
+		stv0900_write_reg(intp, CORRELMANT, 0x70);
+
+		stv0900_set_symbol_rate(intp, intp->mclk, 1000000, demod);
+	} else {
+		stv0900_write_reg(intp, DMDT0M, 0x20);
+		stv0900_write_reg(intp, TMGCFG, 0xd2);
+
+		if (intp->symbol_rate[demod] < 2000000)
+			stv0900_write_reg(intp, CORRELMANT, 0x63);
+		else
+			stv0900_write_reg(intp, CORRELMANT, 0x70);
+
+		stv0900_write_reg(intp, AGC2REF, 0x38);
+
+		intp->bw[demod] =
+				stv0900_carrier_width(intp->symbol_rate[demod],
+								intp->rolloff);
+		if (intp->chip_id >= 0x20) {
+			stv0900_write_reg(intp, KREFTMG, 0x5a);
+
+			if (intp->srch_algo[demod] == STV0900_COLD_START) {
+				intp->bw[demod] += 10000000;
+				intp->bw[demod] *= 15;
+				intp->bw[demod] /= 10;
+			} else if (intp->srch_algo[demod] == STV0900_WARM_START)
+				intp->bw[demod] += 10000000;
+
+		} else {
+			stv0900_write_reg(intp, KREFTMG, 0xc1);
+			intp->bw[demod] += 10000000;
+			intp->bw[demod] *= 15;
+			intp->bw[demod] /= 10;
+		}
+
+		stv0900_write_reg(intp, TMGCFG2, 0xc1);
+
+		stv0900_set_symbol_rate(intp, intp->mclk,
+					intp->symbol_rate[demod], demod);
+		stv0900_set_max_symbol_rate(intp, intp->mclk,
+					intp->symbol_rate[demod], demod);
+		stv0900_set_min_symbol_rate(intp, intp->mclk,
+					intp->symbol_rate[demod], demod);
+		if (intp->symbol_rate[demod] >= 10000000)
+			low_sr = FALSE;
+		else
+			low_sr = TRUE;
+
+	}
+
+	if (intp->tuner_type[demod] == 3)
+		stv0900_set_tuner_auto(intp, intp->freq[demod],
+				intp->bw[demod], demod);
+	else
+		stv0900_set_tuner(fe, intp->freq[demod], intp->bw[demod]);
+
+	agc1_power = MAKEWORD(stv0900_get_bits(intp, AGCIQ_VALUE1),
+				stv0900_get_bits(intp, AGCIQ_VALUE0));
+
+	aq_power = 0;
+
+	if (agc1_power == 0) {
+		for (i = 0; i < 5; i++)
+			aq_power += (stv0900_get_bits(intp, POWER_I) +
+					stv0900_get_bits(intp, POWER_Q)) / 2;
+
+		aq_power /= 5;
+	}
+
+	if ((agc1_power == 0) && (aq_power < IQPOWER_THRESHOLD)) {
+		intp->result[demod].locked = FALSE;
+		signal_type = STV0900_NOAGC1;
+		dprintk("%s: NO AGC1, POWERI, POWERQ\n", __func__);
+	} else {
+		stv0900_write_bits(intp, SPECINV_CONTROL,
+					intp->srch_iq_inv[demod]);
+		if (intp->chip_id <= 0x20) /*cut 2.0*/
+			stv0900_write_bits(intp, MANUALSX_ROLLOFF, 1);
+		else /*cut 3.0*/
+			stv0900_write_bits(intp, MANUALS2_ROLLOFF, 1);
+
+		stv0900_set_search_standard(intp, demod);
+
+		if (intp->srch_algo[demod] != STV0900_BLIND_SEARCH)
+			stv0900_start_search(intp, demod);
+	}
+
+	if (signal_type == STV0900_NOAGC1)
+		return signal_type;
+
+	if (intp->chip_id == 0x12) {
+		stv0900_write_bits(intp, RST_HWARE, 0);
+		msleep(3);
+		stv0900_write_bits(intp, RST_HWARE, 1);
+		stv0900_write_bits(intp, RST_HWARE, 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(intp, demod, demod_timeout);
+
+	if ((lock == FALSE) && (algo == STV0900_COLD_START)) {
+		if (low_sr == FALSE) {
+			if (stv0900_check_timing_lock(intp, demod) == TRUE)
+				lock = stv0900_sw_algo(intp, demod);
+		}
+	}
+
+	if (lock == TRUE)
+		signal_type = stv0900_get_signal_params(fe);
+
+	if ((lock == TRUE) && (signal_type == STV0900_RANGEOK)) {
+		stv0900_track_optimization(fe);
+		if (intp->chip_id <= 0x11) {
+			if ((stv0900_get_standard(fe, 0) ==
+						STV0900_DVBS1_STANDARD) &&
+			   (stv0900_get_standard(fe, 1) ==
+						STV0900_DVBS1_STANDARD)) {
+				msleep(20);
+				stv0900_write_bits(intp, RST_HWARE, 0);
+			} else {
+				stv0900_write_bits(intp, RST_HWARE, 0);
+				msleep(3);
+				stv0900_write_bits(intp, RST_HWARE, 1);
+				stv0900_write_bits(intp, RST_HWARE, 0);
+			}
+
+		} else if (intp->chip_id >= 0x20) {
+			stv0900_write_bits(intp, RST_HWARE, 0);
+			msleep(3);
+			stv0900_write_bits(intp, RST_HWARE, 1);
+			stv0900_write_bits(intp, RST_HWARE, 0);
+		}
+
+		if (stv0900_wait_for_lock(intp, demod,
+					fec_timeout, fec_timeout) == TRUE) {
+			lock = TRUE;
+			intp->result[demod].locked = TRUE;
+			if (intp->result[demod].standard ==
+						STV0900_DVBS2_STANDARD) {
+				stv0900_set_dvbs2_rolloff(intp, demod);
+				stv0900_write_bits(intp, RESET_UPKO_COUNT, 1);
+				stv0900_write_bits(intp, RESET_UPKO_COUNT, 0);
+				stv0900_write_reg(intp, ERRCTRL1, 0x67);
+			} else {
+				stv0900_write_reg(intp, ERRCTRL1, 0x75);
+			}
+
+			stv0900_write_reg(intp, FBERCPT4, 0);
+			stv0900_write_reg(intp, ERRCTRL2, 0xc1);
+		} else {
+			lock = FALSE;
+			signal_type = STV0900_NODATA;
+			no_signal = stv0900_check_signal_presence(intp, demod);
+
+				intp->result[demod].locked = FALSE;
+		}
+	}
+
+	if ((signal_type != STV0900_NODATA) || (no_signal != FALSE))
+		return signal_type;
+
+	if (intp->chip_id > 0x11) {
+		intp->result[demod].locked = FALSE;
+		return signal_type;
+	}
+
+	if ((stv0900_get_bits(intp, HEADER_MODE) == STV0900_DVBS_FOUND) &&
+	   (intp->srch_iq_inv[demod] <= STV0900_IQ_AUTO_NORMAL_FIRST))
+		signal_type = stv0900_dvbs1_acq_workaround(fe);
+
+	return signal_type;
+}
+
diff --git a/drivers/media/dvb-frontends/stv090x.c b/drivers/media/dvb-frontends/stv090x.c
new file mode 100644
index 0000000..13caec0
--- /dev/null
+++ b/drivers/media/dvb-frontends/stv090x.c
@@ -0,0 +1,4855 @@
+/*
+	STV0900/0903 Multistandard Broadcast Frontend driver
+	Copyright (C) Manu Abraham <abraham.manu@gmail.com>
+
+	Copyright (C) ST Microelectronics
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the 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/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/mutex.h>
+
+#include <linux/dvb/frontend.h>
+#include "dvb_frontend.h"
+
+#include "stv6110x.h" /* for demodulator internal modes */
+
+#include "stv090x_reg.h"
+#include "stv090x.h"
+#include "stv090x_priv.h"
+
+static unsigned int verbose;
+module_param(verbose, int, 0644);
+
+/* internal params node */
+struct stv090x_dev {
+	/* pointer for internal params, one for each pair of demods */
+	struct stv090x_internal		*internal;
+	struct stv090x_dev		*next_dev;
+};
+
+/* first internal params */
+static struct stv090x_dev *stv090x_first_dev;
+
+/* find chip by i2c adapter and i2c address */
+static struct stv090x_dev *find_dev(struct i2c_adapter *i2c_adap,
+					u8 i2c_addr)
+{
+	struct stv090x_dev *temp_dev = stv090x_first_dev;
+
+	/*
+	 Search of the last stv0900 chip or
+	 find it by i2c adapter and i2c address */
+	while ((temp_dev != NULL) &&
+		((temp_dev->internal->i2c_adap != i2c_adap) ||
+		(temp_dev->internal->i2c_addr != i2c_addr))) {
+
+		temp_dev = temp_dev->next_dev;
+	}
+
+	return temp_dev;
+}
+
+/* deallocating chip */
+static void remove_dev(struct stv090x_internal *internal)
+{
+	struct stv090x_dev *prev_dev = stv090x_first_dev;
+	struct stv090x_dev *del_dev = find_dev(internal->i2c_adap,
+						internal->i2c_addr);
+
+	if (del_dev != NULL) {
+		if (del_dev == stv090x_first_dev) {
+			stv090x_first_dev = del_dev->next_dev;
+		} else {
+			while (prev_dev->next_dev != del_dev)
+				prev_dev = prev_dev->next_dev;
+
+			prev_dev->next_dev = del_dev->next_dev;
+		}
+
+		kfree(del_dev);
+	}
+}
+
+/* allocating new chip */
+static struct stv090x_dev *append_internal(struct stv090x_internal *internal)
+{
+	struct stv090x_dev *new_dev;
+	struct stv090x_dev *temp_dev;
+
+	new_dev = kmalloc(sizeof(struct stv090x_dev), GFP_KERNEL);
+	if (new_dev != NULL) {
+		new_dev->internal = internal;
+		new_dev->next_dev = NULL;
+
+		/* append to list */
+		if (stv090x_first_dev == NULL) {
+			stv090x_first_dev = new_dev;
+		} else {
+			temp_dev = stv090x_first_dev;
+			while (temp_dev->next_dev != NULL)
+				temp_dev = temp_dev->next_dev;
+
+			temp_dev->next_dev = new_dev;
+		}
+	}
+
+	return new_dev;
+}
+
+
+/* DVBS1 and DSS C/N Lookup table */
+static const struct stv090x_tab stv090x_s1cn_tab[] = {
+	{   0, 8917 }, /*  0.0dB */
+	{   5, 8801 }, /*  0.5dB */
+	{  10, 8667 }, /*  1.0dB */
+	{  15, 8522 }, /*  1.5dB */
+	{  20, 8355 }, /*  2.0dB */
+	{  25, 8175 }, /*  2.5dB */
+	{  30, 7979 }, /*  3.0dB */
+	{  35, 7763 }, /*  3.5dB */
+	{  40, 7530 }, /*  4.0dB */
+	{  45, 7282 }, /*  4.5dB */
+	{  50, 7026 }, /*  5.0dB */
+	{  55, 6781 }, /*  5.5dB */
+	{  60, 6514 }, /*  6.0dB */
+	{  65, 6241 }, /*  6.5dB */
+	{  70, 5965 }, /*  7.0dB */
+	{  75, 5690 }, /*  7.5dB */
+	{  80, 5424 }, /*  8.0dB */
+	{  85, 5161 }, /*  8.5dB */
+	{  90, 4902 }, /*  9.0dB */
+	{  95, 4654 }, /*  9.5dB */
+	{ 100, 4417 }, /* 10.0dB */
+	{ 105, 4186 }, /* 10.5dB */
+	{ 110, 3968 }, /* 11.0dB */
+	{ 115, 3757 }, /* 11.5dB */
+	{ 120, 3558 }, /* 12.0dB */
+	{ 125, 3366 }, /* 12.5dB */
+	{ 130, 3185 }, /* 13.0dB */
+	{ 135, 3012 }, /* 13.5dB */
+	{ 140, 2850 }, /* 14.0dB */
+	{ 145, 2698 }, /* 14.5dB */
+	{ 150, 2550 }, /* 15.0dB */
+	{ 160, 2283 }, /* 16.0dB */
+	{ 170, 2042 }, /* 17.0dB */
+	{ 180, 1827 }, /* 18.0dB */
+	{ 190, 1636 }, /* 19.0dB */
+	{ 200, 1466 }, /* 20.0dB */
+	{ 210, 1315 }, /* 21.0dB */
+	{ 220, 1181 }, /* 22.0dB */
+	{ 230, 1064 }, /* 23.0dB */
+	{ 240,	960 }, /* 24.0dB */
+	{ 250,	869 }, /* 25.0dB */
+	{ 260,	792 }, /* 26.0dB */
+	{ 270,	724 }, /* 27.0dB */
+	{ 280,	665 }, /* 28.0dB */
+	{ 290,	616 }, /* 29.0dB */
+	{ 300,	573 }, /* 30.0dB */
+	{ 310,	537 }, /* 31.0dB */
+	{ 320,	507 }, /* 32.0dB */
+	{ 330,	483 }, /* 33.0dB */
+	{ 400,	398 }, /* 40.0dB */
+	{ 450,	381 }, /* 45.0dB */
+	{ 500,	377 }  /* 50.0dB */
+};
+
+/* DVBS2 C/N Lookup table */
+static const struct stv090x_tab stv090x_s2cn_tab[] = {
+	{ -30, 13348 }, /* -3.0dB */
+	{ -20, 12640 }, /* -2d.0B */
+	{ -10, 11883 }, /* -1.0dB */
+	{   0, 11101 }, /* -0.0dB */
+	{   5, 10718 }, /*  0.5dB */
+	{  10, 10339 }, /*  1.0dB */
+	{  15,  9947 }, /*  1.5dB */
+	{  20,  9552 }, /*  2.0dB */
+	{  25,  9183 }, /*  2.5dB */
+	{  30,  8799 }, /*  3.0dB */
+	{  35,  8422 }, /*  3.5dB */
+	{  40,  8062 }, /*  4.0dB */
+	{  45,  7707 }, /*  4.5dB */
+	{  50,  7353 }, /*  5.0dB */
+	{  55,  7025 }, /*  5.5dB */
+	{  60,  6684 }, /*  6.0dB */
+	{  65,  6331 }, /*  6.5dB */
+	{  70,  6036 }, /*  7.0dB */
+	{  75,  5727 }, /*  7.5dB */
+	{  80,  5437 }, /*  8.0dB */
+	{  85,  5164 }, /*  8.5dB */
+	{  90,  4902 }, /*  9.0dB */
+	{  95,  4653 }, /*  9.5dB */
+	{ 100,  4408 }, /* 10.0dB */
+	{ 105,  4187 }, /* 10.5dB */
+	{ 110,  3961 }, /* 11.0dB */
+	{ 115,  3751 }, /* 11.5dB */
+	{ 120,  3558 }, /* 12.0dB */
+	{ 125,  3368 }, /* 12.5dB */
+	{ 130,  3191 }, /* 13.0dB */
+	{ 135,  3017 }, /* 13.5dB */
+	{ 140,  2862 }, /* 14.0dB */
+	{ 145,  2710 }, /* 14.5dB */
+	{ 150,  2565 }, /* 15.0dB */
+	{ 160,  2300 }, /* 16.0dB */
+	{ 170,  2058 }, /* 17.0dB */
+	{ 180,  1849 }, /* 18.0dB */
+	{ 190,  1663 }, /* 19.0dB */
+	{ 200,  1495 }, /* 20.0dB */
+	{ 210,  1349 }, /* 21.0dB */
+	{ 220,  1222 }, /* 22.0dB */
+	{ 230,  1110 }, /* 23.0dB */
+	{ 240,  1011 }, /* 24.0dB */
+	{ 250,   925 }, /* 25.0dB */
+	{ 260,   853 }, /* 26.0dB */
+	{ 270,   789 }, /* 27.0dB */
+	{ 280,   734 }, /* 28.0dB */
+	{ 290,   690 }, /* 29.0dB */
+	{ 300,   650 }, /* 30.0dB */
+	{ 310,   619 }, /* 31.0dB */
+	{ 320,   593 }, /* 32.0dB */
+	{ 330,   571 }, /* 33.0dB */
+	{ 400,   498 }, /* 40.0dB */
+	{ 450,	 484 }, /* 45.0dB */
+	{ 500,	 481 }	/* 50.0dB */
+};
+
+/* RF level C/N lookup table */
+static const struct stv090x_tab stv090x_rf_tab[] = {
+	{  -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, 0x07aa }	 /* -70dBm */
+};
+
+
+static struct stv090x_reg stv0900_initval[] = {
+
+	{ STV090x_OUTCFG,		0x00 },
+	{ STV090x_MODECFG,		0xff },
+	{ STV090x_AGCRF1CFG,		0x11 },
+	{ STV090x_AGCRF2CFG,		0x13 },
+	{ STV090x_TSGENERAL1X,		0x14 },
+	{ STV090x_TSTTNR2,		0x21 },
+	{ STV090x_TSTTNR4,		0x21 },
+	{ STV090x_P2_DISTXCTL,		0x22 },
+	{ STV090x_P2_F22TX,		0xc0 },
+	{ STV090x_P2_F22RX,		0xc0 },
+	{ STV090x_P2_DISRXCTL,		0x00 },
+	{ STV090x_P2_DMDCFGMD,		0xF9 },
+	{ STV090x_P2_DEMOD,		0x08 },
+	{ STV090x_P2_DMDCFG3,		0xc4 },
+	{ STV090x_P2_CARFREQ,		0xed },
+	{ STV090x_P2_LDT,		0xd0 },
+	{ STV090x_P2_LDT2,		0xb8 },
+	{ STV090x_P2_TMGCFG,		0xd2 },
+	{ STV090x_P2_TMGTHRISE,		0x20 },
+	{ STV090x_P1_TMGCFG,		0xd2 },
+
+	{ STV090x_P2_TMGTHFALL,		0x00 },
+	{ STV090x_P2_FECSPY,		0x88 },
+	{ STV090x_P2_FSPYDATA,		0x3a },
+	{ STV090x_P2_FBERCPT4,		0x00 },
+	{ STV090x_P2_FSPYBER,		0x10 },
+	{ STV090x_P2_ERRCTRL1,		0x35 },
+	{ STV090x_P2_ERRCTRL2,		0xc1 },
+	{ STV090x_P2_CFRICFG,		0xf8 },
+	{ STV090x_P2_NOSCFG,		0x1c },
+	{ STV090x_P2_DMDTOM,		0x20 },
+	{ STV090x_P2_CORRELMANT,	0x70 },
+	{ STV090x_P2_CORRELABS,		0x88 },
+	{ STV090x_P2_AGC2O,		0x5b },
+	{ STV090x_P2_AGC2REF,		0x38 },
+	{ STV090x_P2_CARCFG,		0xe4 },
+	{ STV090x_P2_ACLC,		0x1A },
+	{ STV090x_P2_BCLC,		0x09 },
+	{ STV090x_P2_CARHDR,		0x08 },
+	{ STV090x_P2_KREFTMG,		0xc1 },
+	{ STV090x_P2_SFRUPRATIO,	0xf0 },
+	{ STV090x_P2_SFRLOWRATIO,	0x70 },
+	{ STV090x_P2_SFRSTEP,		0x58 },
+	{ STV090x_P2_TMGCFG2,		0x01 },
+	{ STV090x_P2_CAR2CFG,		0x26 },
+	{ STV090x_P2_BCLC2S2Q,		0x86 },
+	{ STV090x_P2_BCLC2S28,		0x86 },
+	{ STV090x_P2_SMAPCOEF7,		0x77 },
+	{ STV090x_P2_SMAPCOEF6,		0x85 },
+	{ STV090x_P2_SMAPCOEF5,		0x77 },
+	{ STV090x_P2_TSCFGL,		0x20 },
+	{ STV090x_P2_DMDCFG2,		0x3b },
+	{ STV090x_P2_MODCODLST0,	0xff },
+	{ STV090x_P2_MODCODLST1,	0xff },
+	{ STV090x_P2_MODCODLST2,	0xff },
+	{ STV090x_P2_MODCODLST3,	0xff },
+	{ STV090x_P2_MODCODLST4,	0xff },
+	{ STV090x_P2_MODCODLST5,	0xff },
+	{ STV090x_P2_MODCODLST6,	0xff },
+	{ STV090x_P2_MODCODLST7,	0xcc },
+	{ STV090x_P2_MODCODLST8,	0xcc },
+	{ STV090x_P2_MODCODLST9,	0xcc },
+	{ STV090x_P2_MODCODLSTA,	0xcc },
+	{ STV090x_P2_MODCODLSTB,	0xcc },
+	{ STV090x_P2_MODCODLSTC,	0xcc },
+	{ STV090x_P2_MODCODLSTD,	0xcc },
+	{ STV090x_P2_MODCODLSTE,	0xcc },
+	{ STV090x_P2_MODCODLSTF,	0xcf },
+	{ STV090x_P1_DISTXCTL,		0x22 },
+	{ STV090x_P1_F22TX,		0xc0 },
+	{ STV090x_P1_F22RX,		0xc0 },
+	{ STV090x_P1_DISRXCTL,		0x00 },
+	{ STV090x_P1_DMDCFGMD,		0xf9 },
+	{ STV090x_P1_DEMOD,		0x08 },
+	{ STV090x_P1_DMDCFG3,		0xc4 },
+	{ STV090x_P1_DMDTOM,		0x20 },
+	{ STV090x_P1_CARFREQ,		0xed },
+	{ STV090x_P1_LDT,		0xd0 },
+	{ STV090x_P1_LDT2,		0xb8 },
+	{ STV090x_P1_TMGCFG,		0xd2 },
+	{ STV090x_P1_TMGTHRISE,		0x20 },
+	{ STV090x_P1_TMGTHFALL,		0x00 },
+	{ STV090x_P1_SFRUPRATIO,	0xf0 },
+	{ STV090x_P1_SFRLOWRATIO,	0x70 },
+	{ STV090x_P1_TSCFGL,		0x20 },
+	{ STV090x_P1_FECSPY,		0x88 },
+	{ STV090x_P1_FSPYDATA,		0x3a },
+	{ STV090x_P1_FBERCPT4,		0x00 },
+	{ STV090x_P1_FSPYBER,		0x10 },
+	{ STV090x_P1_ERRCTRL1,		0x35 },
+	{ STV090x_P1_ERRCTRL2,		0xc1 },
+	{ STV090x_P1_CFRICFG,		0xf8 },
+	{ STV090x_P1_NOSCFG,		0x1c },
+	{ STV090x_P1_CORRELMANT,	0x70 },
+	{ STV090x_P1_CORRELABS,		0x88 },
+	{ STV090x_P1_AGC2O,		0x5b },
+	{ STV090x_P1_AGC2REF,		0x38 },
+	{ STV090x_P1_CARCFG,		0xe4 },
+	{ STV090x_P1_ACLC,		0x1A },
+	{ STV090x_P1_BCLC,		0x09 },
+	{ STV090x_P1_CARHDR,		0x08 },
+	{ STV090x_P1_KREFTMG,		0xc1 },
+	{ STV090x_P1_SFRSTEP,		0x58 },
+	{ STV090x_P1_TMGCFG2,		0x01 },
+	{ STV090x_P1_CAR2CFG,		0x26 },
+	{ STV090x_P1_BCLC2S2Q,		0x86 },
+	{ STV090x_P1_BCLC2S28,		0x86 },
+	{ STV090x_P1_SMAPCOEF7,		0x77 },
+	{ STV090x_P1_SMAPCOEF6,		0x85 },
+	{ STV090x_P1_SMAPCOEF5,		0x77 },
+	{ STV090x_P1_DMDCFG2,		0x3b },
+	{ STV090x_P1_MODCODLST0,	0xff },
+	{ STV090x_P1_MODCODLST1,	0xff },
+	{ STV090x_P1_MODCODLST2,	0xff },
+	{ STV090x_P1_MODCODLST3,	0xff },
+	{ STV090x_P1_MODCODLST4,	0xff },
+	{ STV090x_P1_MODCODLST5,	0xff },
+	{ STV090x_P1_MODCODLST6,	0xff },
+	{ STV090x_P1_MODCODLST7,	0xcc },
+	{ STV090x_P1_MODCODLST8,	0xcc },
+	{ STV090x_P1_MODCODLST9,	0xcc },
+	{ STV090x_P1_MODCODLSTA,	0xcc },
+	{ STV090x_P1_MODCODLSTB,	0xcc },
+	{ STV090x_P1_MODCODLSTC,	0xcc },
+	{ STV090x_P1_MODCODLSTD,	0xcc },
+	{ STV090x_P1_MODCODLSTE,	0xcc },
+	{ STV090x_P1_MODCODLSTF,	0xcf },
+	{ STV090x_GENCFG,		0x1d },
+	{ STV090x_NBITER_NF4,		0x37 },
+	{ STV090x_NBITER_NF5,		0x29 },
+	{ STV090x_NBITER_NF6,		0x37 },
+	{ STV090x_NBITER_NF7,		0x33 },
+	{ STV090x_NBITER_NF8,		0x31 },
+	{ STV090x_NBITER_NF9,		0x2f },
+	{ STV090x_NBITER_NF10,		0x39 },
+	{ STV090x_NBITER_NF11,		0x3a },
+	{ STV090x_NBITER_NF12,		0x29 },
+	{ STV090x_NBITER_NF13,		0x37 },
+	{ STV090x_NBITER_NF14,		0x33 },
+	{ STV090x_NBITER_NF15,		0x2f },
+	{ STV090x_NBITER_NF16,		0x39 },
+	{ STV090x_NBITER_NF17,		0x3a },
+	{ STV090x_NBITERNOERR,		0x04 },
+	{ STV090x_GAINLLR_NF4,		0x0C },
+	{ STV090x_GAINLLR_NF5,		0x0F },
+	{ STV090x_GAINLLR_NF6,		0x11 },
+	{ STV090x_GAINLLR_NF7,		0x14 },
+	{ STV090x_GAINLLR_NF8,		0x17 },
+	{ STV090x_GAINLLR_NF9,		0x19 },
+	{ STV090x_GAINLLR_NF10,		0x20 },
+	{ STV090x_GAINLLR_NF11,		0x21 },
+	{ STV090x_GAINLLR_NF12,		0x0D },
+	{ STV090x_GAINLLR_NF13,		0x0F },
+	{ STV090x_GAINLLR_NF14,		0x13 },
+	{ STV090x_GAINLLR_NF15,		0x1A },
+	{ STV090x_GAINLLR_NF16,		0x1F },
+	{ STV090x_GAINLLR_NF17,		0x21 },
+	{ STV090x_RCCFGH,		0x20 },
+	{ STV090x_P1_FECM,		0x01 }, /* disable DSS modes */
+	{ STV090x_P2_FECM,		0x01 }, /* disable DSS modes */
+	{ STV090x_P1_PRVIT,		0x2F }, /* disable PR 6/7 */
+	{ STV090x_P2_PRVIT,		0x2F }, /* disable PR 6/7 */
+};
+
+static struct stv090x_reg stv0903_initval[] = {
+	{ STV090x_OUTCFG,		0x00 },
+	{ STV090x_AGCRF1CFG,		0x11 },
+	{ STV090x_STOPCLK1,		0x48 },
+	{ STV090x_STOPCLK2,		0x14 },
+	{ STV090x_TSTTNR1,		0x27 },
+	{ STV090x_TSTTNR2,		0x21 },
+	{ STV090x_P1_DISTXCTL,		0x22 },
+	{ STV090x_P1_F22TX,		0xc0 },
+	{ STV090x_P1_F22RX,		0xc0 },
+	{ STV090x_P1_DISRXCTL,		0x00 },
+	{ STV090x_P1_DMDCFGMD,		0xF9 },
+	{ STV090x_P1_DEMOD,		0x08 },
+	{ STV090x_P1_DMDCFG3,		0xc4 },
+	{ STV090x_P1_CARFREQ,		0xed },
+	{ STV090x_P1_TNRCFG2,		0x82 },
+	{ STV090x_P1_LDT,		0xd0 },
+	{ STV090x_P1_LDT2,		0xb8 },
+	{ STV090x_P1_TMGCFG,		0xd2 },
+	{ STV090x_P1_TMGTHRISE,		0x20 },
+	{ STV090x_P1_TMGTHFALL,		0x00 },
+	{ STV090x_P1_SFRUPRATIO,	0xf0 },
+	{ STV090x_P1_SFRLOWRATIO,	0x70 },
+	{ STV090x_P1_TSCFGL,		0x20 },
+	{ STV090x_P1_FECSPY,		0x88 },
+	{ STV090x_P1_FSPYDATA,		0x3a },
+	{ STV090x_P1_FBERCPT4,		0x00 },
+	{ STV090x_P1_FSPYBER,		0x10 },
+	{ STV090x_P1_ERRCTRL1,		0x35 },
+	{ STV090x_P1_ERRCTRL2,		0xc1 },
+	{ STV090x_P1_CFRICFG,		0xf8 },
+	{ STV090x_P1_NOSCFG,		0x1c },
+	{ STV090x_P1_DMDTOM,		0x20 },
+	{ STV090x_P1_CORRELMANT,	0x70 },
+	{ STV090x_P1_CORRELABS,		0x88 },
+	{ STV090x_P1_AGC2O,		0x5b },
+	{ STV090x_P1_AGC2REF,		0x38 },
+	{ STV090x_P1_CARCFG,		0xe4 },
+	{ STV090x_P1_ACLC,		0x1A },
+	{ STV090x_P1_BCLC,		0x09 },
+	{ STV090x_P1_CARHDR,		0x08 },
+	{ STV090x_P1_KREFTMG,		0xc1 },
+	{ STV090x_P1_SFRSTEP,		0x58 },
+	{ STV090x_P1_TMGCFG2,		0x01 },
+	{ STV090x_P1_CAR2CFG,		0x26 },
+	{ STV090x_P1_BCLC2S2Q,		0x86 },
+	{ STV090x_P1_BCLC2S28,		0x86 },
+	{ STV090x_P1_SMAPCOEF7,		0x77 },
+	{ STV090x_P1_SMAPCOEF6,		0x85 },
+	{ STV090x_P1_SMAPCOEF5,		0x77 },
+	{ STV090x_P1_DMDCFG2,		0x3b },
+	{ STV090x_P1_MODCODLST0,	0xff },
+	{ STV090x_P1_MODCODLST1,	0xff },
+	{ STV090x_P1_MODCODLST2,	0xff },
+	{ STV090x_P1_MODCODLST3,	0xff },
+	{ STV090x_P1_MODCODLST4,	0xff },
+	{ STV090x_P1_MODCODLST5,	0xff },
+	{ STV090x_P1_MODCODLST6,	0xff },
+	{ STV090x_P1_MODCODLST7,	0xcc },
+	{ STV090x_P1_MODCODLST8,	0xcc },
+	{ STV090x_P1_MODCODLST9,	0xcc },
+	{ STV090x_P1_MODCODLSTA,	0xcc },
+	{ STV090x_P1_MODCODLSTB,	0xcc },
+	{ STV090x_P1_MODCODLSTC,	0xcc },
+	{ STV090x_P1_MODCODLSTD,	0xcc },
+	{ STV090x_P1_MODCODLSTE,	0xcc },
+	{ STV090x_P1_MODCODLSTF,	0xcf },
+	{ STV090x_GENCFG,		0x1c },
+	{ STV090x_NBITER_NF4,		0x37 },
+	{ STV090x_NBITER_NF5,		0x29 },
+	{ STV090x_NBITER_NF6,		0x37 },
+	{ STV090x_NBITER_NF7,		0x33 },
+	{ STV090x_NBITER_NF8,		0x31 },
+	{ STV090x_NBITER_NF9,		0x2f },
+	{ STV090x_NBITER_NF10,		0x39 },
+	{ STV090x_NBITER_NF11,		0x3a },
+	{ STV090x_NBITER_NF12,		0x29 },
+	{ STV090x_NBITER_NF13,		0x37 },
+	{ STV090x_NBITER_NF14,		0x33 },
+	{ STV090x_NBITER_NF15,		0x2f },
+	{ STV090x_NBITER_NF16,		0x39 },
+	{ STV090x_NBITER_NF17,		0x3a },
+	{ STV090x_NBITERNOERR,		0x04 },
+	{ STV090x_GAINLLR_NF4,		0x0C },
+	{ STV090x_GAINLLR_NF5,		0x0F },
+	{ STV090x_GAINLLR_NF6,		0x11 },
+	{ STV090x_GAINLLR_NF7,		0x14 },
+	{ STV090x_GAINLLR_NF8,		0x17 },
+	{ STV090x_GAINLLR_NF9,		0x19 },
+	{ STV090x_GAINLLR_NF10,		0x20 },
+	{ STV090x_GAINLLR_NF11,		0x21 },
+	{ STV090x_GAINLLR_NF12,		0x0D },
+	{ STV090x_GAINLLR_NF13,		0x0F },
+	{ STV090x_GAINLLR_NF14,		0x13 },
+	{ STV090x_GAINLLR_NF15,		0x1A },
+	{ STV090x_GAINLLR_NF16,		0x1F },
+	{ STV090x_GAINLLR_NF17,		0x21 },
+	{ STV090x_RCCFGH,		0x20 },
+	{ STV090x_P1_FECM,		0x01 }, /*disable the DSS mode */
+	{ STV090x_P1_PRVIT,		0x2f }  /*disable puncture rate 6/7*/
+};
+
+static struct stv090x_reg stv0900_cut20_val[] = {
+
+	{ STV090x_P2_DMDCFG3,		0xe8 },
+	{ STV090x_P2_DMDCFG4,		0x10 },
+	{ STV090x_P2_CARFREQ,		0x38 },
+	{ STV090x_P2_CARHDR,		0x20 },
+	{ STV090x_P2_KREFTMG,		0x5a },
+	{ STV090x_P2_SMAPCOEF7,		0x06 },
+	{ STV090x_P2_SMAPCOEF6,		0x00 },
+	{ STV090x_P2_SMAPCOEF5,		0x04 },
+	{ STV090x_P2_NOSCFG,		0x0c },
+	{ STV090x_P1_DMDCFG3,		0xe8 },
+	{ STV090x_P1_DMDCFG4,		0x10 },
+	{ STV090x_P1_CARFREQ,		0x38 },
+	{ STV090x_P1_CARHDR,		0x20 },
+	{ STV090x_P1_KREFTMG,		0x5a },
+	{ STV090x_P1_SMAPCOEF7,		0x06 },
+	{ STV090x_P1_SMAPCOEF6,		0x00 },
+	{ STV090x_P1_SMAPCOEF5,		0x04 },
+	{ STV090x_P1_NOSCFG,		0x0c },
+	{ STV090x_GAINLLR_NF4,		0x21 },
+	{ STV090x_GAINLLR_NF5,		0x21 },
+	{ STV090x_GAINLLR_NF6,		0x20 },
+	{ STV090x_GAINLLR_NF7,		0x1F },
+	{ STV090x_GAINLLR_NF8,		0x1E },
+	{ STV090x_GAINLLR_NF9,		0x1E },
+	{ STV090x_GAINLLR_NF10,		0x1D },
+	{ STV090x_GAINLLR_NF11,		0x1B },
+	{ STV090x_GAINLLR_NF12,		0x20 },
+	{ STV090x_GAINLLR_NF13,		0x20 },
+	{ STV090x_GAINLLR_NF14,		0x20 },
+	{ STV090x_GAINLLR_NF15,		0x20 },
+	{ STV090x_GAINLLR_NF16,		0x20 },
+	{ STV090x_GAINLLR_NF17,		0x21 },
+};
+
+static struct stv090x_reg stv0903_cut20_val[] = {
+	{ STV090x_P1_DMDCFG3,		0xe8 },
+	{ STV090x_P1_DMDCFG4,		0x10 },
+	{ STV090x_P1_CARFREQ,		0x38 },
+	{ STV090x_P1_CARHDR,		0x20 },
+	{ STV090x_P1_KREFTMG,		0x5a },
+	{ STV090x_P1_SMAPCOEF7,		0x06 },
+	{ STV090x_P1_SMAPCOEF6,		0x00 },
+	{ STV090x_P1_SMAPCOEF5,		0x04 },
+	{ STV090x_P1_NOSCFG,		0x0c },
+	{ STV090x_GAINLLR_NF4,		0x21 },
+	{ STV090x_GAINLLR_NF5,		0x21 },
+	{ STV090x_GAINLLR_NF6,		0x20 },
+	{ STV090x_GAINLLR_NF7,		0x1F },
+	{ STV090x_GAINLLR_NF8,		0x1E },
+	{ STV090x_GAINLLR_NF9,		0x1E },
+	{ STV090x_GAINLLR_NF10,		0x1D },
+	{ STV090x_GAINLLR_NF11,		0x1B },
+	{ STV090x_GAINLLR_NF12,		0x20 },
+	{ STV090x_GAINLLR_NF13,		0x20 },
+	{ STV090x_GAINLLR_NF14,		0x20 },
+	{ STV090x_GAINLLR_NF15,		0x20 },
+	{ STV090x_GAINLLR_NF16,		0x20 },
+	{ STV090x_GAINLLR_NF17,		0x21 }
+};
+
+/* Cut 2.0 Long Frame Tracking CR loop */
+static struct stv090x_long_frame_crloop stv090x_s2_crl_cut20[] = {
+	/* MODCOD  2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff 20MPon 20MPoff 30MPon 30MPoff */
+	{ STV090x_QPSK_12,  0x1f, 0x3f, 0x1e, 0x3f, 0x3d, 0x1f, 0x3d, 0x3e, 0x3d, 0x1e },
+	{ STV090x_QPSK_35,  0x2f, 0x3f, 0x2e, 0x2f, 0x3d, 0x0f, 0x0e, 0x2e, 0x3d, 0x0e },
+	{ STV090x_QPSK_23,  0x2f, 0x3f, 0x2e, 0x2f, 0x0e, 0x0f, 0x0e, 0x1e, 0x3d, 0x3d },
+	{ STV090x_QPSK_34,  0x3f, 0x3f, 0x3e, 0x1f, 0x0e, 0x3e, 0x0e, 0x1e, 0x3d, 0x3d },
+	{ STV090x_QPSK_45,  0x3f, 0x3f, 0x3e, 0x1f, 0x0e, 0x3e, 0x0e, 0x1e, 0x3d, 0x3d },
+	{ STV090x_QPSK_56,  0x3f, 0x3f, 0x3e, 0x1f, 0x0e, 0x3e, 0x0e, 0x1e, 0x3d, 0x3d },
+	{ STV090x_QPSK_89,  0x3f, 0x3f, 0x3e, 0x1f, 0x1e, 0x3e, 0x0e, 0x1e, 0x3d, 0x3d },
+	{ STV090x_QPSK_910, 0x3f, 0x3f, 0x3e, 0x1f, 0x1e, 0x3e, 0x0e, 0x1e, 0x3d, 0x3d },
+	{ STV090x_8PSK_35,  0x3c, 0x3e, 0x1c, 0x2e, 0x0c, 0x1e, 0x2b, 0x2d, 0x1b, 0x1d },
+	{ STV090x_8PSK_23,  0x1d, 0x3e, 0x3c, 0x2e, 0x2c, 0x1e, 0x0c, 0x2d, 0x2b, 0x1d },
+	{ STV090x_8PSK_34,  0x0e, 0x3e, 0x3d, 0x2e, 0x0d, 0x1e, 0x2c, 0x2d, 0x0c, 0x1d },
+	{ STV090x_8PSK_56,  0x2e, 0x3e, 0x1e, 0x2e, 0x2d, 0x1e, 0x3c, 0x2d, 0x2c, 0x1d },
+	{ STV090x_8PSK_89,  0x3e, 0x3e, 0x1e, 0x2e, 0x3d, 0x1e, 0x0d, 0x2d, 0x3c, 0x1d },
+	{ STV090x_8PSK_910, 0x3e, 0x3e, 0x1e, 0x2e, 0x3d, 0x1e, 0x1d, 0x2d, 0x0d, 0x1d }
+};
+
+/* Cut 3.0 Long Frame Tracking CR loop */
+static	struct stv090x_long_frame_crloop stv090x_s2_crl_cut30[] = {
+	/* MODCOD  2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff 20MPon 20MPoff 30MPon 30MPoff */
+	{ STV090x_QPSK_12,  0x3c, 0x2c, 0x0c, 0x2c, 0x1b, 0x2c, 0x1b, 0x1c, 0x0b, 0x3b },
+	{ STV090x_QPSK_35,  0x0d, 0x0d, 0x0c, 0x0d, 0x1b, 0x3c, 0x1b, 0x1c, 0x0b, 0x3b },
+	{ STV090x_QPSK_23,  0x1d, 0x0d, 0x0c, 0x1d, 0x2b, 0x3c, 0x1b, 0x1c, 0x0b, 0x3b },
+	{ STV090x_QPSK_34,  0x1d, 0x1d, 0x0c, 0x1d, 0x2b, 0x3c, 0x1b, 0x1c, 0x0b, 0x3b },
+	{ STV090x_QPSK_45,  0x2d, 0x1d, 0x1c, 0x1d, 0x2b, 0x3c, 0x2b, 0x0c, 0x1b, 0x3b },
+	{ STV090x_QPSK_56,  0x2d, 0x1d, 0x1c, 0x1d, 0x2b, 0x3c, 0x2b, 0x0c, 0x1b, 0x3b },
+	{ STV090x_QPSK_89,  0x3d, 0x2d, 0x1c, 0x1d, 0x3b, 0x3c, 0x2b, 0x0c, 0x1b, 0x3b },
+	{ STV090x_QPSK_910, 0x3d, 0x2d, 0x1c, 0x1d, 0x3b, 0x3c, 0x2b, 0x0c, 0x1b, 0x3b },
+	{ STV090x_8PSK_35,  0x39, 0x29, 0x39, 0x19, 0x19, 0x19, 0x19, 0x19, 0x09, 0x19 },
+	{ STV090x_8PSK_23,  0x2a, 0x39, 0x1a, 0x0a, 0x39, 0x0a, 0x29, 0x39, 0x29, 0x0a },
+	{ STV090x_8PSK_34,  0x2b, 0x3a, 0x1b, 0x1b, 0x3a, 0x1b, 0x1a, 0x0b, 0x1a, 0x3a },
+	{ STV090x_8PSK_56,  0x0c, 0x1b, 0x3b, 0x3b, 0x1b, 0x3b, 0x3a, 0x3b, 0x3a, 0x1b },
+	{ STV090x_8PSK_89,  0x0d, 0x3c, 0x2c, 0x2c, 0x2b, 0x0c, 0x0b, 0x3b, 0x0b, 0x1b },
+	{ STV090x_8PSK_910, 0x0d, 0x0d, 0x2c, 0x3c, 0x3b, 0x1c, 0x0b, 0x3b, 0x0b, 0x1b }
+};
+
+/* Cut 2.0 Long Frame Tracking CR Loop */
+static struct stv090x_long_frame_crloop stv090x_s2_apsk_crl_cut20[] = {
+	/* MODCOD  2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff 20MPon 20MPoff 30MPon 30MPoff */
+	{ STV090x_16APSK_23,  0x0c, 0x0c, 0x0c, 0x0c, 0x1d, 0x0c, 0x3c, 0x0c, 0x2c, 0x0c },
+	{ STV090x_16APSK_34,  0x0c, 0x0c, 0x0c, 0x0c, 0x0e, 0x0c, 0x2d, 0x0c, 0x1d, 0x0c },
+	{ STV090x_16APSK_45,  0x0c, 0x0c, 0x0c, 0x0c, 0x1e, 0x0c, 0x3d, 0x0c, 0x2d, 0x0c },
+	{ STV090x_16APSK_56,  0x0c, 0x0c, 0x0c, 0x0c, 0x1e, 0x0c, 0x3d, 0x0c, 0x2d, 0x0c },
+	{ STV090x_16APSK_89,  0x0c, 0x0c, 0x0c, 0x0c, 0x2e, 0x0c, 0x0e, 0x0c, 0x3d, 0x0c },
+	{ STV090x_16APSK_910, 0x0c, 0x0c, 0x0c, 0x0c, 0x2e, 0x0c, 0x0e, 0x0c, 0x3d, 0x0c },
+	{ STV090x_32APSK_34,  0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c },
+	{ STV090x_32APSK_45,  0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c },
+	{ STV090x_32APSK_56,  0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c },
+	{ STV090x_32APSK_89,  0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c },
+	{ STV090x_32APSK_910, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c }
+};
+
+/* Cut 3.0 Long Frame Tracking CR Loop */
+static struct stv090x_long_frame_crloop	stv090x_s2_apsk_crl_cut30[] = {
+	/* MODCOD  2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff 20MPon 20MPoff 30MPon 30MPoff */
+	{ STV090x_16APSK_23,  0x0a, 0x0a, 0x0a, 0x0a, 0x1a, 0x0a, 0x3a, 0x0a, 0x2a, 0x0a },
+	{ STV090x_16APSK_34,  0x0a, 0x0a, 0x0a, 0x0a, 0x0b, 0x0a, 0x3b, 0x0a, 0x1b, 0x0a },
+	{ STV090x_16APSK_45,  0x0a, 0x0a, 0x0a, 0x0a, 0x1b, 0x0a, 0x3b, 0x0a, 0x2b, 0x0a },
+	{ STV090x_16APSK_56,  0x0a, 0x0a, 0x0a, 0x0a, 0x1b, 0x0a, 0x3b, 0x0a, 0x2b, 0x0a },
+	{ STV090x_16APSK_89,  0x0a, 0x0a, 0x0a, 0x0a, 0x2b, 0x0a, 0x0c, 0x0a, 0x3b, 0x0a },
+	{ STV090x_16APSK_910, 0x0a, 0x0a, 0x0a, 0x0a, 0x2b, 0x0a, 0x0c, 0x0a, 0x3b, 0x0a },
+	{ STV090x_32APSK_34,  0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a },
+	{ STV090x_32APSK_45,  0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a },
+	{ STV090x_32APSK_56,  0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a },
+	{ STV090x_32APSK_89,  0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a },
+	{ STV090x_32APSK_910, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a }
+};
+
+static struct stv090x_long_frame_crloop stv090x_s2_lowqpsk_crl_cut20[] = {
+	/* MODCOD  2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff 20MPon 20MPoff 30MPon 30MPoff */
+	{ STV090x_QPSK_14,  0x0f, 0x3f, 0x0e, 0x3f, 0x2d, 0x2f, 0x2d, 0x1f, 0x3d, 0x3e },
+	{ STV090x_QPSK_13,  0x0f, 0x3f, 0x0e, 0x3f, 0x2d, 0x2f, 0x3d, 0x0f, 0x3d, 0x2e },
+	{ STV090x_QPSK_25,  0x1f, 0x3f, 0x1e, 0x3f, 0x3d, 0x1f, 0x3d, 0x3e, 0x3d, 0x2e }
+};
+
+static struct stv090x_long_frame_crloop	stv090x_s2_lowqpsk_crl_cut30[] = {
+	/* MODCOD  2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff 20MPon 20MPoff 30MPon 30MPoff */
+	{ STV090x_QPSK_14,  0x0c, 0x3c, 0x0b, 0x3c, 0x2a, 0x2c, 0x2a, 0x1c, 0x3a, 0x3b },
+	{ STV090x_QPSK_13,  0x0c, 0x3c, 0x0b, 0x3c, 0x2a, 0x2c, 0x3a, 0x0c, 0x3a, 0x2b },
+	{ STV090x_QPSK_25,  0x1c, 0x3c, 0x1b, 0x3c, 0x3a, 0x1c, 0x3a, 0x3b, 0x3a, 0x2b }
+};
+
+/* Cut 2.0 Short Frame Tracking CR Loop */
+static struct stv090x_short_frame_crloop stv090x_s2_short_crl_cut20[] = {
+	/* MODCOD	  2M    5M    10M   20M   30M */
+	{ STV090x_QPSK,   0x2f, 0x2e, 0x0e, 0x0e, 0x3d },
+	{ STV090x_8PSK,   0x3e, 0x0e, 0x2d, 0x0d, 0x3c },
+	{ STV090x_16APSK, 0x1e, 0x1e, 0x1e, 0x3d, 0x2d },
+	{ STV090x_32APSK, 0x1e, 0x1e, 0x1e, 0x3d, 0x2d }
+};
+
+/* Cut 3.0 Short Frame Tracking CR Loop */
+static struct stv090x_short_frame_crloop stv090x_s2_short_crl_cut30[] = {
+	/* MODCOD  	  2M	5M    10M   20M	  30M */
+	{ STV090x_QPSK,   0x2C, 0x2B, 0x0B, 0x0B, 0x3A },
+	{ STV090x_8PSK,   0x3B, 0x0B, 0x2A, 0x0A, 0x39 },
+	{ STV090x_16APSK, 0x1B, 0x1B, 0x1B, 0x3A, 0x2A },
+	{ STV090x_32APSK, 0x1B, 0x1B, 0x1B, 0x3A, 0x2A }
+};
+
+static inline s32 comp2(s32 __x, s32 __width)
+{
+	if (__width == 32)
+		return __x;
+	else
+		return (__x >= (1 << (__width - 1))) ? (__x - (1 << __width)) : __x;
+}
+
+static int stv090x_read_reg(struct stv090x_state *state, unsigned int reg)
+{
+	const struct stv090x_config *config = state->config;
+	int ret;
+
+	u8 b0[] = { reg >> 8, reg & 0xff };
+	u8 buf;
+
+	struct i2c_msg msg[] = {
+		{ .addr	= config->address, .flags	= 0, 		.buf = b0,   .len = 2 },
+		{ .addr	= config->address, .flags	= I2C_M_RD,	.buf = &buf, .len = 1 }
+	};
+
+	ret = i2c_transfer(state->i2c, msg, 2);
+	if (ret != 2) {
+		if (ret != -ERESTARTSYS)
+			dprintk(FE_ERROR, 1,
+				"Read error, Reg=[0x%02x], Status=%d",
+				reg, ret);
+
+		return ret < 0 ? ret : -EREMOTEIO;
+	}
+	if (unlikely(*state->verbose >= FE_DEBUGREG))
+		dprintk(FE_ERROR, 1, "Reg=[0x%02x], data=%02x",
+			reg, buf);
+
+	return (unsigned int) buf;
+}
+
+static int stv090x_write_regs(struct stv090x_state *state, unsigned int reg, u8 *data, u32 count)
+{
+	const struct stv090x_config *config = state->config;
+	int ret;
+	u8 buf[2 + count];
+	struct i2c_msg i2c_msg = { .addr = config->address, .flags = 0, .buf = buf, .len = 2 + count };
+
+	buf[0] = reg >> 8;
+	buf[1] = reg & 0xff;
+	memcpy(&buf[2], data, count);
+
+	if (unlikely(*state->verbose >= FE_DEBUGREG)) {
+		int i;
+
+		printk(KERN_DEBUG "%s [0x%04x]:", __func__, reg);
+		for (i = 0; i < count; i++)
+			printk(" %02x", data[i]);
+		printk("\n");
+	}
+
+	ret = i2c_transfer(state->i2c, &i2c_msg, 1);
+	if (ret != 1) {
+		if (ret != -ERESTARTSYS)
+			dprintk(FE_ERROR, 1, "Reg=[0x%04x], Data=[0x%02x ...], Count=%u, Status=%d",
+				reg, data[0], count, ret);
+		return ret < 0 ? ret : -EREMOTEIO;
+	}
+
+	return 0;
+}
+
+static int stv090x_write_reg(struct stv090x_state *state, unsigned int reg, u8 data)
+{
+	return stv090x_write_regs(state, reg, &data, 1);
+}
+
+static int stv090x_i2c_gate_ctrl(struct stv090x_state *state, int enable)
+{
+	u32 reg;
+
+	/*
+	 * NOTE! A lock is used as a FSM to control the state in which
+	 * access is serialized between two tuners on the same demod.
+	 * This has nothing to do with a lock to protect a critical section
+	 * which may in some other cases be confused with protecting I/O
+	 * access to the demodulator gate.
+	 * In case of any error, the lock is unlocked and exit within the
+	 * relevant operations themselves.
+	 */
+	if (enable) {
+		if (state->config->tuner_i2c_lock)
+			state->config->tuner_i2c_lock(&state->frontend, 1);
+		else
+			mutex_lock(&state->internal->tuner_lock);
+	}
+
+	reg = STV090x_READ_DEMOD(state, I2CRPT);
+	if (enable) {
+		dprintk(FE_DEBUG, 1, "Enable Gate");
+		STV090x_SETFIELD_Px(reg, I2CT_ON_FIELD, 1);
+		if (STV090x_WRITE_DEMOD(state, I2CRPT, reg) < 0)
+			goto err;
+
+	} else {
+		dprintk(FE_DEBUG, 1, "Disable Gate");
+		STV090x_SETFIELD_Px(reg, I2CT_ON_FIELD, 0);
+		if ((STV090x_WRITE_DEMOD(state, I2CRPT, reg)) < 0)
+			goto err;
+	}
+
+	if (!enable) {
+		if (state->config->tuner_i2c_lock)
+			state->config->tuner_i2c_lock(&state->frontend, 0);
+		else
+			mutex_unlock(&state->internal->tuner_lock);
+	}
+
+	return 0;
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	if (state->config->tuner_i2c_lock)
+		state->config->tuner_i2c_lock(&state->frontend, 0);
+	else
+		mutex_unlock(&state->internal->tuner_lock);
+	return -1;
+}
+
+static void stv090x_get_lock_tmg(struct stv090x_state *state)
+{
+	switch (state->algo) {
+	case STV090x_BLIND_SEARCH:
+		dprintk(FE_DEBUG, 1, "Blind Search");
+		if (state->srate <= 1500000) {  /*10Msps< SR <=15Msps*/
+			state->DemodTimeout = 1500;
+			state->FecTimeout = 400;
+		} else if (state->srate <= 5000000) {  /*10Msps< SR <=15Msps*/
+			state->DemodTimeout = 1000;
+			state->FecTimeout = 300;
+		} else {  /*SR >20Msps*/
+			state->DemodTimeout = 700;
+			state->FecTimeout = 100;
+		}
+		break;
+
+	case STV090x_COLD_SEARCH:
+	case STV090x_WARM_SEARCH:
+	default:
+		dprintk(FE_DEBUG, 1, "Normal Search");
+		if (state->srate <= 1000000) {  /*SR <=1Msps*/
+			state->DemodTimeout = 4500;
+			state->FecTimeout = 1700;
+		} else if (state->srate <= 2000000) { /*1Msps < SR <= 2Msps */
+			state->DemodTimeout = 2500;
+			state->FecTimeout = 1100;
+		} else if (state->srate <= 5000000) { /*2Msps < SR <= 5Msps */
+			state->DemodTimeout = 1000;
+			state->FecTimeout = 550;
+		} else if (state->srate <= 10000000) { /*5Msps < SR <= 10Msps */
+			state->DemodTimeout = 700;
+			state->FecTimeout = 250;
+		} else if (state->srate <= 20000000) { /*10Msps < SR <= 20Msps */
+			state->DemodTimeout = 400;
+			state->FecTimeout = 130;
+		} else {   /*SR >20Msps*/
+			state->DemodTimeout = 300;
+			state->FecTimeout = 100;
+		}
+		break;
+	}
+
+	if (state->algo == STV090x_WARM_SEARCH)
+		state->DemodTimeout /= 2;
+}
+
+static int stv090x_set_srate(struct stv090x_state *state, u32 srate)
+{
+	u32 sym;
+
+	if (srate > 60000000) {
+		sym  = (srate << 4); /* SR * 2^16 / master_clk */
+		sym /= (state->internal->mclk >> 12);
+	} else if (srate > 6000000) {
+		sym  = (srate << 6);
+		sym /= (state->internal->mclk >> 10);
+	} else {
+		sym  = (srate << 9);
+		sym /= (state->internal->mclk >> 7);
+	}
+
+	if (STV090x_WRITE_DEMOD(state, SFRINIT1, (sym >> 8) & 0x7f) < 0) /* MSB */
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, SFRINIT0, (sym & 0xff)) < 0) /* LSB */
+		goto err;
+
+	return 0;
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static int stv090x_set_max_srate(struct stv090x_state *state, u32 clk, u32 srate)
+{
+	u32 sym;
+
+	srate = 105 * (srate / 100);
+	if (srate > 60000000) {
+		sym  = (srate << 4); /* SR * 2^16 / master_clk */
+		sym /= (state->internal->mclk >> 12);
+	} else if (srate > 6000000) {
+		sym  = (srate << 6);
+		sym /= (state->internal->mclk >> 10);
+	} else {
+		sym  = (srate << 9);
+		sym /= (state->internal->mclk >> 7);
+	}
+
+	if (sym < 0x7fff) {
+		if (STV090x_WRITE_DEMOD(state, SFRUP1, (sym >> 8) & 0x7f) < 0) /* MSB */
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, SFRUP0, sym & 0xff) < 0) /* LSB */
+			goto err;
+	} else {
+		if (STV090x_WRITE_DEMOD(state, SFRUP1, 0x7f) < 0) /* MSB */
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, SFRUP0, 0xff) < 0) /* LSB */
+			goto err;
+	}
+
+	return 0;
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static int stv090x_set_min_srate(struct stv090x_state *state, u32 clk, u32 srate)
+{
+	u32 sym;
+
+	srate = 95 * (srate / 100);
+	if (srate > 60000000) {
+		sym  = (srate << 4); /* SR * 2^16 / master_clk */
+		sym /= (state->internal->mclk >> 12);
+	} else if (srate > 6000000) {
+		sym  = (srate << 6);
+		sym /= (state->internal->mclk >> 10);
+	} else {
+		sym  = (srate << 9);
+		sym /= (state->internal->mclk >> 7);
+	}
+
+	if (STV090x_WRITE_DEMOD(state, SFRLOW1, ((sym >> 8) & 0x7f)) < 0) /* MSB */
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, SFRLOW0, (sym & 0xff)) < 0) /* LSB */
+		goto err;
+	return 0;
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static u32 stv090x_car_width(u32 srate, enum stv090x_rolloff rolloff)
+{
+	u32 ro;
+
+	switch (rolloff) {
+	case STV090x_RO_20:
+		ro = 20;
+		break;
+	case STV090x_RO_25:
+		ro = 25;
+		break;
+	case STV090x_RO_35:
+	default:
+		ro = 35;
+		break;
+	}
+
+	return srate + (srate * ro) / 100;
+}
+
+static int stv090x_set_vit_thacq(struct stv090x_state *state)
+{
+	if (STV090x_WRITE_DEMOD(state, VTH12, 0x96) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, VTH23, 0x64) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, VTH34, 0x36) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, VTH56, 0x23) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, VTH67, 0x1e) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, VTH78, 0x19) < 0)
+		goto err;
+	return 0;
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static int stv090x_set_vit_thtracq(struct stv090x_state *state)
+{
+	if (STV090x_WRITE_DEMOD(state, VTH12, 0xd0) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, VTH23, 0x7d) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, VTH34, 0x53) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, VTH56, 0x2f) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, VTH67, 0x24) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, VTH78, 0x1f) < 0)
+		goto err;
+	return 0;
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static int stv090x_set_viterbi(struct stv090x_state *state)
+{
+	switch (state->search_mode) {
+	case STV090x_SEARCH_AUTO:
+		if (STV090x_WRITE_DEMOD(state, FECM, 0x10) < 0) /* DVB-S and DVB-S2 */
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, PRVIT, 0x3f) < 0) /* all puncture rate */
+			goto err;
+		break;
+	case STV090x_SEARCH_DVBS1:
+		if (STV090x_WRITE_DEMOD(state, FECM, 0x00) < 0) /* disable DSS */
+			goto err;
+		switch (state->fec) {
+		case STV090x_PR12:
+			if (STV090x_WRITE_DEMOD(state, PRVIT, 0x01) < 0)
+				goto err;
+			break;
+
+		case STV090x_PR23:
+			if (STV090x_WRITE_DEMOD(state, PRVIT, 0x02) < 0)
+				goto err;
+			break;
+
+		case STV090x_PR34:
+			if (STV090x_WRITE_DEMOD(state, PRVIT, 0x04) < 0)
+				goto err;
+			break;
+
+		case STV090x_PR56:
+			if (STV090x_WRITE_DEMOD(state, PRVIT, 0x08) < 0)
+				goto err;
+			break;
+
+		case STV090x_PR78:
+			if (STV090x_WRITE_DEMOD(state, PRVIT, 0x20) < 0)
+				goto err;
+			break;
+
+		default:
+			if (STV090x_WRITE_DEMOD(state, PRVIT, 0x2f) < 0) /* all */
+				goto err;
+			break;
+		}
+		break;
+	case STV090x_SEARCH_DSS:
+		if (STV090x_WRITE_DEMOD(state, FECM, 0x80) < 0)
+			goto err;
+		switch (state->fec) {
+		case STV090x_PR12:
+			if (STV090x_WRITE_DEMOD(state, PRVIT, 0x01) < 0)
+				goto err;
+			break;
+
+		case STV090x_PR23:
+			if (STV090x_WRITE_DEMOD(state, PRVIT, 0x02) < 0)
+				goto err;
+			break;
+
+		case STV090x_PR67:
+			if (STV090x_WRITE_DEMOD(state, PRVIT, 0x10) < 0)
+				goto err;
+			break;
+
+		default:
+			if (STV090x_WRITE_DEMOD(state, PRVIT, 0x13) < 0) /* 1/2, 2/3, 6/7 */
+				goto err;
+			break;
+		}
+		break;
+	default:
+		break;
+	}
+	return 0;
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static int stv090x_stop_modcod(struct stv090x_state *state)
+{
+	if (STV090x_WRITE_DEMOD(state, MODCODLST0, 0xff) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLST1, 0xff) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLST2, 0xff) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLST3, 0xff) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLST4, 0xff) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLST5, 0xff) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLST6, 0xff) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLST7, 0xff) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLST8, 0xff) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLST9, 0xff) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLSTA, 0xff) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLSTB, 0xff) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLSTC, 0xff) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLSTD, 0xff) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLSTE, 0xff) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLSTF, 0xff) < 0)
+		goto err;
+	return 0;
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static int stv090x_activate_modcod(struct stv090x_state *state)
+{
+	if (STV090x_WRITE_DEMOD(state, MODCODLST0, 0xff) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLST1, 0xfc) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLST2, 0xcc) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLST3, 0xcc) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLST4, 0xcc) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLST5, 0xcc) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLST6, 0xcc) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLST7, 0xcc) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLST8, 0xcc) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLST9, 0xcc) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLSTA, 0xcc) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLSTB, 0xcc) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLSTC, 0xcc) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLSTD, 0xcc) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLSTE, 0xcc) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLSTF, 0xcf) < 0)
+		goto err;
+
+	return 0;
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static int stv090x_activate_modcod_single(struct stv090x_state *state)
+{
+
+	if (STV090x_WRITE_DEMOD(state, MODCODLST0, 0xff) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLST1, 0xf0) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLST2, 0x00) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLST3, 0x00) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLST4, 0x00) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLST5, 0x00) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLST6, 0x00) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLST7, 0x00) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLST8, 0x00) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLST9, 0x00) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLSTA, 0x00) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLSTB, 0x00) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLSTC, 0x00) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLSTD, 0x00) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLSTE, 0x00) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, MODCODLSTF, 0x0f) < 0)
+		goto err;
+
+	return 0;
+
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static int stv090x_vitclk_ctl(struct stv090x_state *state, int enable)
+{
+	u32 reg;
+
+	switch (state->demod) {
+	case STV090x_DEMODULATOR_0:
+		mutex_lock(&state->internal->demod_lock);
+		reg = stv090x_read_reg(state, STV090x_STOPCLK2);
+		STV090x_SETFIELD(reg, STOP_CLKVIT1_FIELD, enable);
+		if (stv090x_write_reg(state, STV090x_STOPCLK2, reg) < 0)
+			goto err;
+		mutex_unlock(&state->internal->demod_lock);
+		break;
+
+	case STV090x_DEMODULATOR_1:
+		mutex_lock(&state->internal->demod_lock);
+		reg = stv090x_read_reg(state, STV090x_STOPCLK2);
+		STV090x_SETFIELD(reg, STOP_CLKVIT2_FIELD, enable);
+		if (stv090x_write_reg(state, STV090x_STOPCLK2, reg) < 0)
+			goto err;
+		mutex_unlock(&state->internal->demod_lock);
+		break;
+
+	default:
+		dprintk(FE_ERROR, 1, "Wrong demodulator!");
+		break;
+	}
+	return 0;
+err:
+	mutex_unlock(&state->internal->demod_lock);
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static int stv090x_dvbs_track_crl(struct stv090x_state *state)
+{
+	if (state->internal->dev_ver >= 0x30) {
+		/* Set ACLC BCLC optimised value vs SR */
+		if (state->srate >= 15000000) {
+			if (STV090x_WRITE_DEMOD(state, ACLC, 0x2b) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, BCLC, 0x1a) < 0)
+				goto err;
+		} else if ((state->srate >= 7000000) && (15000000 > state->srate)) {
+			if (STV090x_WRITE_DEMOD(state, ACLC, 0x0c) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, BCLC, 0x1b) < 0)
+				goto err;
+		} else if (state->srate < 7000000) {
+			if (STV090x_WRITE_DEMOD(state, ACLC, 0x2c) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, BCLC, 0x1c) < 0)
+				goto err;
+		}
+
+	} else {
+		/* Cut 2.0 */
+		if (STV090x_WRITE_DEMOD(state, ACLC, 0x1a) < 0)
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, BCLC, 0x09) < 0)
+			goto err;
+	}
+	return 0;
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static int stv090x_delivery_search(struct stv090x_state *state)
+{
+	u32 reg;
+
+	switch (state->search_mode) {
+	case STV090x_SEARCH_DVBS1:
+	case STV090x_SEARCH_DSS:
+		reg = STV090x_READ_DEMOD(state, DMDCFGMD);
+		STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 1);
+		STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 0);
+		if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
+			goto err;
+
+		/* Activate Viterbi decoder in legacy search,
+		 * do not use FRESVIT1, might impact VITERBI2
+		 */
+		if (stv090x_vitclk_ctl(state, 0) < 0)
+			goto err;
+
+		if (stv090x_dvbs_track_crl(state) < 0)
+			goto err;
+
+		if (STV090x_WRITE_DEMOD(state, CAR2CFG, 0x22) < 0) /* disable DVB-S2 */
+			goto err;
+
+		if (stv090x_set_vit_thacq(state) < 0)
+			goto err;
+		if (stv090x_set_viterbi(state) < 0)
+			goto err;
+		break;
+
+	case STV090x_SEARCH_DVBS2:
+		reg = STV090x_READ_DEMOD(state, DMDCFGMD);
+		STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 0);
+		STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 0);
+		if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
+			goto err;
+		STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 1);
+		STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 1);
+		if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
+			goto err;
+
+		if (stv090x_vitclk_ctl(state, 1) < 0)
+			goto err;
+
+		if (STV090x_WRITE_DEMOD(state, ACLC, 0x1a) < 0) /* stop DVB-S CR loop */
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, BCLC, 0x09) < 0)
+			goto err;
+
+		if (state->internal->dev_ver <= 0x20) {
+			/* enable S2 carrier loop */
+			if (STV090x_WRITE_DEMOD(state, CAR2CFG, 0x26) < 0)
+				goto err;
+		} else {
+			/* > Cut 3: Stop carrier 3 */
+			if (STV090x_WRITE_DEMOD(state, CAR2CFG, 0x66) < 0)
+				goto err;
+		}
+
+		if (state->demod_mode != STV090x_SINGLE) {
+			/* Cut 2: enable link during search */
+			if (stv090x_activate_modcod(state) < 0)
+				goto err;
+		} else {
+			/* Single demodulator
+			 * Authorize SHORT and LONG frames,
+			 * QPSK, 8PSK, 16APSK and 32APSK
+			 */
+			if (stv090x_activate_modcod_single(state) < 0)
+				goto err;
+		}
+
+		if (stv090x_set_vit_thtracq(state) < 0)
+			goto err;
+		break;
+
+	case STV090x_SEARCH_AUTO:
+	default:
+		/* enable DVB-S2 and DVB-S2 in Auto MODE */
+		reg = STV090x_READ_DEMOD(state, DMDCFGMD);
+		STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 0);
+		STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 0);
+		if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
+			goto err;
+		STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 1);
+		STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 1);
+		if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
+			goto err;
+
+		if (stv090x_vitclk_ctl(state, 0) < 0)
+			goto err;
+
+		if (stv090x_dvbs_track_crl(state) < 0)
+			goto err;
+
+		if (state->internal->dev_ver <= 0x20) {
+			/* enable S2 carrier loop */
+			if (STV090x_WRITE_DEMOD(state, CAR2CFG, 0x26) < 0)
+				goto err;
+		} else {
+			/* > Cut 3: Stop carrier 3 */
+			if (STV090x_WRITE_DEMOD(state, CAR2CFG, 0x66) < 0)
+				goto err;
+		}
+
+		if (state->demod_mode != STV090x_SINGLE) {
+			/* Cut 2: enable link during search */
+			if (stv090x_activate_modcod(state) < 0)
+				goto err;
+		} else {
+			/* Single demodulator
+			 * Authorize SHORT and LONG frames,
+			 * QPSK, 8PSK, 16APSK and 32APSK
+			 */
+			if (stv090x_activate_modcod_single(state) < 0)
+				goto err;
+		}
+
+		if (stv090x_set_vit_thacq(state) < 0)
+			goto err;
+
+		if (stv090x_set_viterbi(state) < 0)
+			goto err;
+		break;
+	}
+	return 0;
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static int stv090x_start_search(struct stv090x_state *state)
+{
+	u32 reg, freq_abs;
+	s16 freq;
+
+	/* Reset demodulator */
+	reg = STV090x_READ_DEMOD(state, DMDISTATE);
+	STV090x_SETFIELD_Px(reg, I2C_DEMOD_MODE_FIELD, 0x1f);
+	if (STV090x_WRITE_DEMOD(state, DMDISTATE, reg) < 0)
+		goto err;
+
+	if (state->internal->dev_ver <= 0x20) {
+		if (state->srate <= 5000000) {
+			if (STV090x_WRITE_DEMOD(state, CARCFG, 0x44) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, CFRUP1, 0x0f) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, CFRUP0, 0xff) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, CFRLOW1, 0xf0) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, CFRLOW0, 0x00) < 0)
+				goto err;
+
+			/*enlarge the timing bandwidth for Low SR*/
+			if (STV090x_WRITE_DEMOD(state, RTCS2, 0x68) < 0)
+				goto err;
+		} else {
+			/* If the symbol rate is >5 Msps
+			Set The carrier search up and low to auto mode */
+			if (STV090x_WRITE_DEMOD(state, CARCFG, 0xc4) < 0)
+				goto err;
+			/*reduce the timing bandwidth for high SR*/
+			if (STV090x_WRITE_DEMOD(state, RTCS2, 0x44) < 0)
+				goto err;
+		}
+	} else {
+		/* >= Cut 3 */
+		if (state->srate <= 5000000) {
+			/* enlarge the timing bandwidth for Low SR */
+			STV090x_WRITE_DEMOD(state, RTCS2, 0x68);
+		} else {
+			/* reduce timing bandwidth for high SR */
+			STV090x_WRITE_DEMOD(state, RTCS2, 0x44);
+		}
+
+		/* Set CFR min and max to manual mode */
+		STV090x_WRITE_DEMOD(state, CARCFG, 0x46);
+
+		if (state->algo == STV090x_WARM_SEARCH) {
+			/* WARM Start
+			 * CFR min = -1MHz,
+			 * CFR max = +1MHz
+			 */
+			freq_abs  = 1000 << 16;
+			freq_abs /= (state->internal->mclk / 1000);
+			freq      = (s16) freq_abs;
+		} else {
+			/* COLD Start
+			 * CFR min =- (SearchRange / 2 + 600KHz)
+			 * CFR max = +(SearchRange / 2 + 600KHz)
+			 * (600KHz for the tuner step size)
+			 */
+			freq_abs  = (state->search_range / 2000) + 600;
+			freq_abs  = freq_abs << 16;
+			freq_abs /= (state->internal->mclk / 1000);
+			freq      = (s16) freq_abs;
+		}
+
+		if (STV090x_WRITE_DEMOD(state, CFRUP1, MSB(freq)) < 0)
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, CFRUP0, LSB(freq)) < 0)
+			goto err;
+
+		freq *= -1;
+
+		if (STV090x_WRITE_DEMOD(state, CFRLOW1, MSB(freq)) < 0)
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, CFRLOW0, LSB(freq)) < 0)
+			goto err;
+
+	}
+
+	if (STV090x_WRITE_DEMOD(state, CFRINIT1, 0) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, CFRINIT0, 0) < 0)
+		goto err;
+
+	if (state->internal->dev_ver >= 0x20) {
+		if (STV090x_WRITE_DEMOD(state, EQUALCFG, 0x41) < 0)
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, FFECFG, 0x41) < 0)
+			goto err;
+
+		if ((state->search_mode == STV090x_SEARCH_DVBS1)	||
+			(state->search_mode == STV090x_SEARCH_DSS)	||
+			(state->search_mode == STV090x_SEARCH_AUTO)) {
+
+			if (STV090x_WRITE_DEMOD(state, VITSCALE, 0x82) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, VAVSRVIT, 0x00) < 0)
+				goto err;
+		}
+	}
+
+	if (STV090x_WRITE_DEMOD(state, SFRSTEP, 0x00) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, TMGTHRISE, 0xe0) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, TMGTHFALL, 0xc0) < 0)
+		goto err;
+
+	reg = STV090x_READ_DEMOD(state, DMDCFGMD);
+	STV090x_SETFIELD_Px(reg, SCAN_ENABLE_FIELD, 0);
+	STV090x_SETFIELD_Px(reg, CFR_AUTOSCAN_FIELD, 0);
+	if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
+		goto err;
+	reg = STV090x_READ_DEMOD(state, DMDCFG2);
+	STV090x_SETFIELD_Px(reg, S1S2_SEQUENTIAL_FIELD, 0x0);
+	if (STV090x_WRITE_DEMOD(state, DMDCFG2, reg) < 0)
+		goto err;
+
+	if (STV090x_WRITE_DEMOD(state, RTC, 0x88) < 0)
+		goto err;
+
+	if (state->internal->dev_ver >= 0x20) {
+		/*Frequency offset detector setting*/
+		if (state->srate < 2000000) {
+			if (state->internal->dev_ver <= 0x20) {
+				/* Cut 2 */
+				if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x39) < 0)
+					goto err;
+			} else {
+				/* Cut 3 */
+				if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x89) < 0)
+					goto err;
+			}
+			if (STV090x_WRITE_DEMOD(state, CARHDR, 0x40) < 0)
+				goto err;
+		} else if (state->srate < 10000000) {
+			if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x4c) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, CARHDR, 0x20) < 0)
+				goto err;
+		} else {
+			if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x4b) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, CARHDR, 0x20) < 0)
+				goto err;
+		}
+	} else {
+		if (state->srate < 10000000) {
+			if (STV090x_WRITE_DEMOD(state, CARFREQ, 0xef) < 0)
+				goto err;
+		} else {
+			if (STV090x_WRITE_DEMOD(state, CARFREQ, 0xed) < 0)
+				goto err;
+		}
+	}
+
+	switch (state->algo) {
+	case STV090x_WARM_SEARCH:
+		/* The symbol rate and the exact
+		 * carrier Frequency are known
+		 */
+		if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0)
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x18) < 0)
+			goto err;
+		break;
+
+	case STV090x_COLD_SEARCH:
+		/* The symbol rate is known */
+		if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0)
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x15) < 0)
+			goto err;
+		break;
+
+	default:
+		break;
+	}
+	return 0;
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static int stv090x_get_agc2_min_level(struct stv090x_state *state)
+{
+	u32 agc2_min = 0xffff, agc2 = 0, freq_init, freq_step, reg;
+	s32 i, j, steps, dir;
+
+	if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x38) < 0)
+		goto err;
+	reg = STV090x_READ_DEMOD(state, DMDCFGMD);
+	STV090x_SETFIELD_Px(reg, SCAN_ENABLE_FIELD, 0);
+	STV090x_SETFIELD_Px(reg, CFR_AUTOSCAN_FIELD, 0);
+	if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
+		goto err;
+
+	if (STV090x_WRITE_DEMOD(state, SFRUP1, 0x83) < 0) /* SR = 65 Msps Max */
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, SFRUP0, 0xc0) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, SFRLOW1, 0x82) < 0) /* SR= 400 ksps Min */
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, SFRLOW0, 0xa0) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, DMDTOM, 0x00) < 0) /* stop acq @ coarse carrier state */
+		goto err;
+	if (stv090x_set_srate(state, 1000000) < 0)
+		goto err;
+
+	steps  = state->search_range / 1000000;
+	if (steps <= 0)
+		steps = 1;
+
+	dir = 1;
+	freq_step = (1000000 * 256) / (state->internal->mclk / 256);
+	freq_init = 0;
+
+	for (i = 0; i < steps; i++) {
+		if (dir > 0)
+			freq_init = freq_init + (freq_step * i);
+		else
+			freq_init = freq_init - (freq_step * i);
+
+		dir *= -1;
+
+		if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x5c) < 0) /* Demod RESET */
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, CFRINIT1, (freq_init >> 8) & 0xff) < 0)
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, CFRINIT0, freq_init & 0xff) < 0)
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x58) < 0) /* Demod RESET */
+			goto err;
+		msleep(10);
+
+		agc2 = 0;
+		for (j = 0; j < 10; j++) {
+			agc2 += (STV090x_READ_DEMOD(state, AGC2I1) << 8) |
+				STV090x_READ_DEMOD(state, AGC2I0);
+		}
+		agc2 /= 10;
+		if (agc2 < agc2_min)
+			agc2_min = agc2;
+	}
+
+	return agc2_min;
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static u32 stv090x_get_srate(struct stv090x_state *state, u32 clk)
+{
+	u8 r3, r2, r1, r0;
+	s32 srate, int_1, int_2, tmp_1, tmp_2;
+
+	r3 = STV090x_READ_DEMOD(state, SFR3);
+	r2 = STV090x_READ_DEMOD(state, SFR2);
+	r1 = STV090x_READ_DEMOD(state, SFR1);
+	r0 = STV090x_READ_DEMOD(state, SFR0);
+
+	srate = ((r3 << 24) | (r2 << 16) | (r1 <<  8) | r0);
+
+	int_1 = clk >> 16;
+	int_2 = srate >> 16;
+
+	tmp_1 = clk % 0x10000;
+	tmp_2 = srate % 0x10000;
+
+	srate = (int_1 * int_2) +
+		((int_1 * tmp_2) >> 16) +
+		((int_2 * tmp_1) >> 16);
+
+	return srate;
+}
+
+static u32 stv090x_srate_srch_coarse(struct stv090x_state *state)
+{
+	struct dvb_frontend *fe = &state->frontend;
+
+	int tmg_lock = 0, i;
+	s32 tmg_cpt = 0, dir = 1, steps, cur_step = 0, freq;
+	u32 srate_coarse = 0, agc2 = 0, car_step = 1200, reg;
+	u32 agc2th;
+
+	if (state->internal->dev_ver >= 0x30)
+		agc2th = 0x2e00;
+	else
+		agc2th = 0x1f00;
+
+	reg = STV090x_READ_DEMOD(state, DMDISTATE);
+	STV090x_SETFIELD_Px(reg, I2C_DEMOD_MODE_FIELD, 0x1f); /* Demod RESET */
+	if (STV090x_WRITE_DEMOD(state, DMDISTATE, reg) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, TMGCFG, 0x12) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, TMGCFG2, 0xc0) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, TMGTHRISE, 0xf0) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, TMGTHFALL, 0xe0) < 0)
+		goto err;
+	reg = STV090x_READ_DEMOD(state, DMDCFGMD);
+	STV090x_SETFIELD_Px(reg, SCAN_ENABLE_FIELD, 1);
+	STV090x_SETFIELD_Px(reg, CFR_AUTOSCAN_FIELD, 0);
+	if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
+		goto err;
+
+	if (STV090x_WRITE_DEMOD(state, SFRUP1, 0x83) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, SFRUP0, 0xc0) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, SFRLOW1, 0x82) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, SFRLOW0, 0xa0) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, DMDTOM, 0x00) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x50) < 0)
+		goto err;
+
+	if (state->internal->dev_ver >= 0x30) {
+		if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x99) < 0)
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, SFRSTEP, 0x98) < 0)
+			goto err;
+
+	} else if (state->internal->dev_ver >= 0x20) {
+		if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x6a) < 0)
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, SFRSTEP, 0x95) < 0)
+			goto err;
+	}
+
+	if (state->srate <= 2000000)
+		car_step = 1000;
+	else if (state->srate <= 5000000)
+		car_step = 2000;
+	else if (state->srate <= 12000000)
+		car_step = 3000;
+	else
+		car_step = 5000;
+
+	steps  = -1 + ((state->search_range / 1000) / car_step);
+	steps /= 2;
+	steps  = (2 * steps) + 1;
+	if (steps < 0)
+		steps = 1;
+	else if (steps > 10) {
+		steps = 11;
+		car_step = (state->search_range / 1000) / 10;
+	}
+	cur_step = 0;
+	dir = 1;
+	freq = state->frequency;
+
+	while ((!tmg_lock) && (cur_step < steps)) {
+		if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x5f) < 0) /* Demod RESET */
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, CFRINIT1, 0x00) < 0)
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, CFRINIT0, 0x00) < 0)
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, SFRINIT1, 0x00) < 0)
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, SFRINIT0, 0x00) < 0)
+			goto err;
+		/* trigger acquisition */
+		if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x40) < 0)
+			goto err;
+		msleep(50);
+		for (i = 0; i < 10; i++) {
+			reg = STV090x_READ_DEMOD(state, DSTATUS);
+			if (STV090x_GETFIELD_Px(reg, TMGLOCK_QUALITY_FIELD) >= 2)
+				tmg_cpt++;
+			agc2 += (STV090x_READ_DEMOD(state, AGC2I1) << 8) |
+				STV090x_READ_DEMOD(state, AGC2I0);
+		}
+		agc2 /= 10;
+		srate_coarse = stv090x_get_srate(state, state->internal->mclk);
+		cur_step++;
+		dir *= -1;
+		if ((tmg_cpt >= 5) && (agc2 < agc2th) &&
+		    (srate_coarse < 50000000) && (srate_coarse > 850000))
+			tmg_lock = 1;
+		else if (cur_step < steps) {
+			if (dir > 0)
+				freq += cur_step * car_step;
+			else
+				freq -= cur_step * car_step;
+
+			/* Setup tuner */
+			if (stv090x_i2c_gate_ctrl(state, 1) < 0)
+				goto err;
+
+			if (state->config->tuner_set_frequency) {
+				if (state->config->tuner_set_frequency(fe, freq) < 0)
+					goto err_gateoff;
+			}
+
+			if (state->config->tuner_set_bandwidth) {
+				if (state->config->tuner_set_bandwidth(fe, state->tuner_bw) < 0)
+					goto err_gateoff;
+			}
+
+			if (stv090x_i2c_gate_ctrl(state, 0) < 0)
+				goto err;
+
+			msleep(50);
+
+			if (stv090x_i2c_gate_ctrl(state, 1) < 0)
+				goto err;
+
+			if (state->config->tuner_get_status) {
+				if (state->config->tuner_get_status(fe, &reg) < 0)
+					goto err_gateoff;
+			}
+
+			if (reg)
+				dprintk(FE_DEBUG, 1, "Tuner phase locked");
+			else
+				dprintk(FE_DEBUG, 1, "Tuner unlocked");
+
+			if (stv090x_i2c_gate_ctrl(state, 0) < 0)
+				goto err;
+
+		}
+	}
+	if (!tmg_lock)
+		srate_coarse = 0;
+	else
+		srate_coarse = stv090x_get_srate(state, state->internal->mclk);
+
+	return srate_coarse;
+
+err_gateoff:
+	stv090x_i2c_gate_ctrl(state, 0);
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static u32 stv090x_srate_srch_fine(struct stv090x_state *state)
+{
+	u32 srate_coarse, freq_coarse, sym, reg;
+
+	srate_coarse = stv090x_get_srate(state, state->internal->mclk);
+	freq_coarse  = STV090x_READ_DEMOD(state, CFR2) << 8;
+	freq_coarse |= STV090x_READ_DEMOD(state, CFR1);
+	sym = 13 * (srate_coarse / 10); /* SFRUP = SFR + 30% */
+
+	if (sym < state->srate)
+		srate_coarse = 0;
+	else {
+		if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0) /* Demod RESET */
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, TMGCFG2, 0xc1) < 0)
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, TMGTHRISE, 0x20) < 0)
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, TMGTHFALL, 0x00) < 0)
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, TMGCFG, 0xd2) < 0)
+			goto err;
+		reg = STV090x_READ_DEMOD(state, DMDCFGMD);
+		STV090x_SETFIELD_Px(reg, CFR_AUTOSCAN_FIELD, 0x00);
+		if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
+			goto err;
+
+		if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x38) < 0)
+			goto err;
+
+		if (state->internal->dev_ver >= 0x30) {
+			if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x79) < 0)
+				goto err;
+		} else if (state->internal->dev_ver >= 0x20) {
+			if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x49) < 0)
+				goto err;
+		}
+
+		if (srate_coarse > 3000000) {
+			sym  = 13 * (srate_coarse / 10); /* SFRUP = SFR + 30% */
+			sym  = (sym / 1000) * 65536;
+			sym /= (state->internal->mclk / 1000);
+			if (STV090x_WRITE_DEMOD(state, SFRUP1, (sym >> 8) & 0x7f) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, SFRUP0, sym & 0xff) < 0)
+				goto err;
+			sym  = 10 * (srate_coarse / 13); /* SFRLOW = SFR - 30% */
+			sym  = (sym / 1000) * 65536;
+			sym /= (state->internal->mclk / 1000);
+			if (STV090x_WRITE_DEMOD(state, SFRLOW1, (sym >> 8) & 0x7f) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, SFRLOW0, sym & 0xff) < 0)
+				goto err;
+			sym  = (srate_coarse / 1000) * 65536;
+			sym /= (state->internal->mclk / 1000);
+			if (STV090x_WRITE_DEMOD(state, SFRINIT1, (sym >> 8) & 0xff) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, SFRINIT0, sym & 0xff) < 0)
+				goto err;
+		} else {
+			sym  = 13 * (srate_coarse / 10); /* SFRUP = SFR + 30% */
+			sym  = (sym / 100) * 65536;
+			sym /= (state->internal->mclk / 100);
+			if (STV090x_WRITE_DEMOD(state, SFRUP1, (sym >> 8) & 0x7f) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, SFRUP0, sym & 0xff) < 0)
+				goto err;
+			sym  = 10 * (srate_coarse / 14); /* SFRLOW = SFR - 30% */
+			sym  = (sym / 100) * 65536;
+			sym /= (state->internal->mclk / 100);
+			if (STV090x_WRITE_DEMOD(state, SFRLOW1, (sym >> 8) & 0x7f) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, SFRLOW0, sym & 0xff) < 0)
+				goto err;
+			sym  = (srate_coarse / 100) * 65536;
+			sym /= (state->internal->mclk / 100);
+			if (STV090x_WRITE_DEMOD(state, SFRINIT1, (sym >> 8) & 0xff) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, SFRINIT0, sym & 0xff) < 0)
+				goto err;
+		}
+		if (STV090x_WRITE_DEMOD(state, DMDTOM, 0x20) < 0)
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, CFRINIT1, (freq_coarse >> 8) & 0xff) < 0)
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, CFRINIT0, freq_coarse & 0xff) < 0)
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x15) < 0) /* trigger acquisition */
+			goto err;
+	}
+
+	return srate_coarse;
+
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static int stv090x_get_dmdlock(struct stv090x_state *state, s32 timeout)
+{
+	s32 timer = 0, lock = 0;
+	u32 reg;
+	u8 stat;
+
+	while ((timer < timeout) && (!lock)) {
+		reg = STV090x_READ_DEMOD(state, DMDSTATE);
+		stat = STV090x_GETFIELD_Px(reg, HEADER_MODE_FIELD);
+
+		switch (stat) {
+		case 0: /* searching */
+		case 1: /* first PLH detected */
+		default:
+			dprintk(FE_DEBUG, 1, "Demodulator searching ..");
+			lock = 0;
+			break;
+		case 2: /* DVB-S2 mode */
+		case 3: /* DVB-S1/legacy mode */
+			reg = STV090x_READ_DEMOD(state, DSTATUS);
+			lock = STV090x_GETFIELD_Px(reg, LOCK_DEFINITIF_FIELD);
+			break;
+		}
+
+		if (!lock)
+			msleep(10);
+		else
+			dprintk(FE_DEBUG, 1, "Demodulator acquired LOCK");
+
+		timer += 10;
+	}
+	return lock;
+}
+
+static int stv090x_blind_search(struct stv090x_state *state)
+{
+	u32 agc2, reg, srate_coarse;
+	s32 cpt_fail, agc2_ovflw, i;
+	u8 k_ref, k_max, k_min;
+	int coarse_fail = 0;
+	int lock;
+
+	k_max = 110;
+	k_min = 10;
+
+	agc2 = stv090x_get_agc2_min_level(state);
+
+	if (agc2 > STV090x_SEARCH_AGC2_TH(state->internal->dev_ver)) {
+		lock = 0;
+	} else {
+
+		if (state->internal->dev_ver <= 0x20) {
+			if (STV090x_WRITE_DEMOD(state, CARCFG, 0xc4) < 0)
+				goto err;
+		} else {
+			/* > Cut 3 */
+			if (STV090x_WRITE_DEMOD(state, CARCFG, 0x06) < 0)
+				goto err;
+		}
+
+		if (STV090x_WRITE_DEMOD(state, RTCS2, 0x44) < 0)
+			goto err;
+
+		if (state->internal->dev_ver >= 0x20) {
+			if (STV090x_WRITE_DEMOD(state, EQUALCFG, 0x41) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, FFECFG, 0x41) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, VITSCALE, 0x82) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, VAVSRVIT, 0x00) < 0) /* set viterbi hysteresis */
+				goto err;
+		}
+
+		k_ref = k_max;
+		do {
+			if (STV090x_WRITE_DEMOD(state, KREFTMG, k_ref) < 0)
+				goto err;
+			if (stv090x_srate_srch_coarse(state) != 0) {
+				srate_coarse = stv090x_srate_srch_fine(state);
+				if (srate_coarse != 0) {
+					stv090x_get_lock_tmg(state);
+					lock = stv090x_get_dmdlock(state,
+							state->DemodTimeout);
+				} else {
+					lock = 0;
+				}
+			} else {
+				cpt_fail = 0;
+				agc2_ovflw = 0;
+				for (i = 0; i < 10; i++) {
+					agc2 += (STV090x_READ_DEMOD(state, AGC2I1) << 8) |
+						STV090x_READ_DEMOD(state, AGC2I0);
+					if (agc2 >= 0xff00)
+						agc2_ovflw++;
+					reg = STV090x_READ_DEMOD(state, DSTATUS2);
+					if ((STV090x_GETFIELD_Px(reg, CFR_OVERFLOW_FIELD) == 0x01) &&
+					    (STV090x_GETFIELD_Px(reg, DEMOD_DELOCK_FIELD) == 0x01))
+
+						cpt_fail++;
+				}
+				if ((cpt_fail > 7) || (agc2_ovflw > 7))
+					coarse_fail = 1;
+
+				lock = 0;
+			}
+			k_ref -= 20;
+		} while ((k_ref >= k_min) && (!lock) && (!coarse_fail));
+	}
+
+	return lock;
+
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static int stv090x_chk_tmg(struct stv090x_state *state)
+{
+	u32 reg;
+	s32 tmg_cpt = 0, i;
+	u8 freq, tmg_thh, tmg_thl;
+	int tmg_lock = 0;
+
+	freq = STV090x_READ_DEMOD(state, CARFREQ);
+	tmg_thh = STV090x_READ_DEMOD(state, TMGTHRISE);
+	tmg_thl = STV090x_READ_DEMOD(state, TMGTHFALL);
+	if (STV090x_WRITE_DEMOD(state, TMGTHRISE, 0x20) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, TMGTHFALL, 0x00) < 0)
+		goto err;
+
+	reg = STV090x_READ_DEMOD(state, DMDCFGMD);
+	STV090x_SETFIELD_Px(reg, CFR_AUTOSCAN_FIELD, 0x00); /* stop carrier offset search */
+	if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, RTC, 0x80) < 0)
+		goto err;
+
+	if (STV090x_WRITE_DEMOD(state, RTCS2, 0x40) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x00) < 0)
+		goto err;
+
+	if (STV090x_WRITE_DEMOD(state, CFRINIT1, 0x00) < 0) /* set car ofset to 0 */
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, CFRINIT0, 0x00) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x65) < 0)
+		goto err;
+
+	if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x18) < 0) /* trigger acquisition */
+		goto err;
+	msleep(10);
+
+	for (i = 0; i < 10; i++) {
+		reg = STV090x_READ_DEMOD(state, DSTATUS);
+		if (STV090x_GETFIELD_Px(reg, TMGLOCK_QUALITY_FIELD) >= 2)
+			tmg_cpt++;
+		msleep(1);
+	}
+	if (tmg_cpt >= 3)
+		tmg_lock = 1;
+
+	if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x38) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, RTC, 0x88) < 0) /* DVB-S1 timing */
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, RTCS2, 0x68) < 0) /* DVB-S2 timing */
+		goto err;
+
+	if (STV090x_WRITE_DEMOD(state, CARFREQ, freq) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, TMGTHRISE, tmg_thh) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, TMGTHFALL, tmg_thl) < 0)
+		goto err;
+
+	return	tmg_lock;
+
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static int stv090x_get_coldlock(struct stv090x_state *state, s32 timeout_dmd)
+{
+	struct dvb_frontend *fe = &state->frontend;
+
+	u32 reg;
+	s32 car_step, steps, cur_step, dir, freq, timeout_lock;
+	int lock = 0;
+
+	if (state->srate >= 10000000)
+		timeout_lock = timeout_dmd / 3;
+	else
+		timeout_lock = timeout_dmd / 2;
+
+	lock = stv090x_get_dmdlock(state, timeout_lock); /* cold start wait */
+	if (!lock) {
+		if (state->srate >= 10000000) {
+			if (stv090x_chk_tmg(state)) {
+				if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0)
+					goto err;
+				if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x15) < 0)
+					goto err;
+				lock = stv090x_get_dmdlock(state, timeout_dmd);
+			} else {
+				lock = 0;
+			}
+		} else {
+			if (state->srate <= 4000000)
+				car_step = 1000;
+			else if (state->srate <= 7000000)
+				car_step = 2000;
+			else if (state->srate <= 10000000)
+				car_step = 3000;
+			else
+				car_step = 5000;
+
+			steps  = (state->search_range / 1000) / car_step;
+			steps /= 2;
+			steps  = 2 * (steps + 1);
+			if (steps < 0)
+				steps = 2;
+			else if (steps > 12)
+				steps = 12;
+
+			cur_step = 1;
+			dir = 1;
+
+			if (!lock) {
+				freq = state->frequency;
+				state->tuner_bw = stv090x_car_width(state->srate, state->rolloff) + state->srate;
+				while ((cur_step <= steps) && (!lock)) {
+					if (dir > 0)
+						freq += cur_step * car_step;
+					else
+						freq -= cur_step * car_step;
+
+					/* Setup tuner */
+					if (stv090x_i2c_gate_ctrl(state, 1) < 0)
+						goto err;
+
+					if (state->config->tuner_set_frequency) {
+						if (state->config->tuner_set_frequency(fe, freq) < 0)
+							goto err_gateoff;
+					}
+
+					if (state->config->tuner_set_bandwidth) {
+						if (state->config->tuner_set_bandwidth(fe, state->tuner_bw) < 0)
+							goto err_gateoff;
+					}
+
+					if (stv090x_i2c_gate_ctrl(state, 0) < 0)
+						goto err;
+
+					msleep(50);
+
+					if (stv090x_i2c_gate_ctrl(state, 1) < 0)
+						goto err;
+
+					if (state->config->tuner_get_status) {
+						if (state->config->tuner_get_status(fe, &reg) < 0)
+							goto err_gateoff;
+					}
+
+					if (reg)
+						dprintk(FE_DEBUG, 1, "Tuner phase locked");
+					else
+						dprintk(FE_DEBUG, 1, "Tuner unlocked");
+
+					if (stv090x_i2c_gate_ctrl(state, 0) < 0)
+						goto err;
+
+					STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1c);
+					if (STV090x_WRITE_DEMOD(state, CFRINIT1, 0x00) < 0)
+						goto err;
+					if (STV090x_WRITE_DEMOD(state, CFRINIT0, 0x00) < 0)
+						goto err;
+					if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0)
+						goto err;
+					if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x15) < 0)
+						goto err;
+					lock = stv090x_get_dmdlock(state, (timeout_dmd / 3));
+
+					dir *= -1;
+					cur_step++;
+				}
+			}
+		}
+	}
+
+	return lock;
+
+err_gateoff:
+	stv090x_i2c_gate_ctrl(state, 0);
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static int stv090x_get_loop_params(struct stv090x_state *state, s32 *freq_inc, s32 *timeout_sw, s32 *steps)
+{
+	s32 timeout, inc, steps_max, srate, car_max;
+
+	srate = state->srate;
+	car_max = state->search_range / 1000;
+	car_max += car_max / 10;
+	car_max  = 65536 * (car_max / 2);
+	car_max /= (state->internal->mclk / 1000);
+
+	if (car_max > 0x4000)
+		car_max = 0x4000 ; /* maxcarrier should be<= +-1/4 Mclk */
+
+	inc  = srate;
+	inc /= state->internal->mclk / 1000;
+	inc *= 256;
+	inc *= 256;
+	inc /= 1000;
+
+	switch (state->search_mode) {
+	case STV090x_SEARCH_DVBS1:
+	case STV090x_SEARCH_DSS:
+		inc *= 3; /* freq step = 3% of srate */
+		timeout = 20;
+		break;
+
+	case STV090x_SEARCH_DVBS2:
+		inc *= 4;
+		timeout = 25;
+		break;
+
+	case STV090x_SEARCH_AUTO:
+	default:
+		inc *= 3;
+		timeout = 25;
+		break;
+	}
+	inc /= 100;
+	if ((inc > car_max) || (inc < 0))
+		inc = car_max / 2; /* increment <= 1/8 Mclk */
+
+	timeout *= 27500; /* 27.5 Msps reference */
+	if (srate > 0)
+		timeout /= (srate / 1000);
+
+	if ((timeout > 100) || (timeout < 0))
+		timeout = 100;
+
+	steps_max = (car_max / inc) + 1; /* min steps = 3 */
+	if ((steps_max > 100) || (steps_max < 0)) {
+		steps_max = 100; /* max steps <= 100 */
+		inc = car_max / steps_max;
+	}
+	*freq_inc = inc;
+	*timeout_sw = timeout;
+	*steps = steps_max;
+
+	return 0;
+}
+
+static int stv090x_chk_signal(struct stv090x_state *state)
+{
+	s32 offst_car, agc2, car_max;
+	int no_signal;
+
+	offst_car  = STV090x_READ_DEMOD(state, CFR2) << 8;
+	offst_car |= STV090x_READ_DEMOD(state, CFR1);
+	offst_car = comp2(offst_car, 16);
+
+	agc2  = STV090x_READ_DEMOD(state, AGC2I1) << 8;
+	agc2 |= STV090x_READ_DEMOD(state, AGC2I0);
+	car_max = state->search_range / 1000;
+
+	car_max += (car_max / 10); /* 10% margin */
+	car_max  = (65536 * car_max / 2);
+	car_max /= state->internal->mclk / 1000;
+
+	if (car_max > 0x4000)
+		car_max = 0x4000;
+
+	if ((agc2 > 0x2000) || (offst_car > 2 * car_max) || (offst_car < -2 * car_max)) {
+		no_signal = 1;
+		dprintk(FE_DEBUG, 1, "No Signal");
+	} else {
+		no_signal = 0;
+		dprintk(FE_DEBUG, 1, "Found Signal");
+	}
+
+	return no_signal;
+}
+
+static int stv090x_search_car_loop(struct stv090x_state *state, s32 inc, s32 timeout, int zigzag, s32 steps_max)
+{
+	int no_signal, lock = 0;
+	s32 cpt_step = 0, offst_freq, car_max;
+	u32 reg;
+
+	car_max  = state->search_range / 1000;
+	car_max += (car_max / 10);
+	car_max  = (65536 * car_max / 2);
+	car_max /= (state->internal->mclk / 1000);
+	if (car_max > 0x4000)
+		car_max = 0x4000;
+
+	if (zigzag)
+		offst_freq = 0;
+	else
+		offst_freq = -car_max + inc;
+
+	do {
+		if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1c) < 0)
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, CFRINIT1, ((offst_freq / 256) & 0xff)) < 0)
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, CFRINIT0, offst_freq & 0xff) < 0)
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x18) < 0)
+			goto err;
+
+		reg = STV090x_READ_DEMOD(state, PDELCTRL1);
+		STV090x_SETFIELD_Px(reg, ALGOSWRST_FIELD, 0x1); /* stop DVB-S2 packet delin */
+		if (STV090x_WRITE_DEMOD(state, PDELCTRL1, reg) < 0)
+			goto err;
+
+		if (zigzag) {
+			if (offst_freq >= 0)
+				offst_freq = -offst_freq - 2 * inc;
+			else
+				offst_freq = -offst_freq;
+		} else {
+			offst_freq += 2 * inc;
+		}
+
+		cpt_step++;
+
+		lock = stv090x_get_dmdlock(state, timeout);
+		no_signal = stv090x_chk_signal(state);
+
+	} while ((!lock) &&
+		 (!no_signal) &&
+		  ((offst_freq - inc) < car_max) &&
+		  ((offst_freq + inc) > -car_max) &&
+		  (cpt_step < steps_max));
+
+	reg = STV090x_READ_DEMOD(state, PDELCTRL1);
+	STV090x_SETFIELD_Px(reg, ALGOSWRST_FIELD, 0);
+	if (STV090x_WRITE_DEMOD(state, PDELCTRL1, reg) < 0)
+			goto err;
+
+	return lock;
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static int stv090x_sw_algo(struct stv090x_state *state)
+{
+	int no_signal, zigzag, lock = 0;
+	u32 reg;
+
+	s32 dvbs2_fly_wheel;
+	s32 inc, timeout_step, trials, steps_max;
+
+	/* get params */
+	stv090x_get_loop_params(state, &inc, &timeout_step, &steps_max);
+
+	switch (state->search_mode) {
+	case STV090x_SEARCH_DVBS1:
+	case STV090x_SEARCH_DSS:
+		/* accelerate the frequency detector */
+		if (state->internal->dev_ver >= 0x20) {
+			if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x3B) < 0)
+				goto err;
+		}
+
+		if (STV090x_WRITE_DEMOD(state, DMDCFGMD, 0x49) < 0)
+			goto err;
+		zigzag = 0;
+		break;
+
+	case STV090x_SEARCH_DVBS2:
+		if (state->internal->dev_ver >= 0x20) {
+			if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x79) < 0)
+				goto err;
+		}
+
+		if (STV090x_WRITE_DEMOD(state, DMDCFGMD, 0x89) < 0)
+			goto err;
+		zigzag = 1;
+		break;
+
+	case STV090x_SEARCH_AUTO:
+	default:
+		/* accelerate the frequency detector */
+		if (state->internal->dev_ver >= 0x20) {
+			if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x3b) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x79) < 0)
+				goto err;
+		}
+
+		if (STV090x_WRITE_DEMOD(state, DMDCFGMD, 0xc9) < 0)
+			goto err;
+		zigzag = 0;
+		break;
+	}
+
+	trials = 0;
+	do {
+		lock = stv090x_search_car_loop(state, inc, timeout_step, zigzag, steps_max);
+		no_signal = stv090x_chk_signal(state);
+		trials++;
+
+		/*run the SW search 2 times maximum*/
+		if (lock || no_signal || (trials == 2)) {
+			/*Check if the demod is not losing lock in DVBS2*/
+			if (state->internal->dev_ver >= 0x20) {
+				if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x49) < 0)
+					goto err;
+				if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x9e) < 0)
+					goto err;
+			}
+
+			reg = STV090x_READ_DEMOD(state, DMDSTATE);
+			if ((lock) && (STV090x_GETFIELD_Px(reg, HEADER_MODE_FIELD) == STV090x_DVBS2)) {
+				/*Check if the demod is not losing lock in DVBS2*/
+				msleep(timeout_step);
+				reg = STV090x_READ_DEMOD(state, DMDFLYW);
+				dvbs2_fly_wheel = STV090x_GETFIELD_Px(reg, FLYWHEEL_CPT_FIELD);
+				if (dvbs2_fly_wheel < 0xd) {	 /*if correct frames is decrementing */
+					msleep(timeout_step);
+					reg = STV090x_READ_DEMOD(state, DMDFLYW);
+					dvbs2_fly_wheel = STV090x_GETFIELD_Px(reg, FLYWHEEL_CPT_FIELD);
+				}
+				if (dvbs2_fly_wheel < 0xd) {
+					/*FALSE lock, The demod is losing lock */
+					lock = 0;
+					if (trials < 2) {
+						if (state->internal->dev_ver >= 0x20) {
+							if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x79) < 0)
+								goto err;
+						}
+
+						if (STV090x_WRITE_DEMOD(state, DMDCFGMD, 0x89) < 0)
+							goto err;
+					}
+				}
+			}
+		}
+	} while ((!lock) && (trials < 2) && (!no_signal));
+
+	return lock;
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static enum stv090x_delsys stv090x_get_std(struct stv090x_state *state)
+{
+	u32 reg;
+	enum stv090x_delsys delsys;
+
+	reg = STV090x_READ_DEMOD(state, DMDSTATE);
+	if (STV090x_GETFIELD_Px(reg, HEADER_MODE_FIELD) == 2)
+		delsys = STV090x_DVBS2;
+	else if (STV090x_GETFIELD_Px(reg, HEADER_MODE_FIELD) == 3) {
+		reg = STV090x_READ_DEMOD(state, FECM);
+		if (STV090x_GETFIELD_Px(reg, DSS_DVB_FIELD) == 1)
+			delsys = STV090x_DSS;
+		else
+			delsys = STV090x_DVBS1;
+	} else {
+		delsys = STV090x_ERROR;
+	}
+
+	return delsys;
+}
+
+/* in Hz */
+static s32 stv090x_get_car_freq(struct stv090x_state *state, u32 mclk)
+{
+	s32 derot, int_1, int_2, tmp_1, tmp_2;
+
+	derot  = STV090x_READ_DEMOD(state, CFR2) << 16;
+	derot |= STV090x_READ_DEMOD(state, CFR1) <<  8;
+	derot |= STV090x_READ_DEMOD(state, CFR0);
+
+	derot = comp2(derot, 24);
+	int_1 = mclk >> 12;
+	int_2 = derot >> 12;
+
+	/* carrier_frequency = MasterClock * Reg / 2^24 */
+	tmp_1 = mclk % 0x1000;
+	tmp_2 = derot % 0x1000;
+
+	derot = (int_1 * int_2) +
+		((int_1 * tmp_2) >> 12) +
+		((int_2 * tmp_1) >> 12);
+
+	return derot;
+}
+
+static int stv090x_get_viterbi(struct stv090x_state *state)
+{
+	u32 reg, rate;
+
+	reg = STV090x_READ_DEMOD(state, VITCURPUN);
+	rate = STV090x_GETFIELD_Px(reg, VIT_CURPUN_FIELD);
+
+	switch (rate) {
+	case 13:
+		state->fec = STV090x_PR12;
+		break;
+
+	case 18:
+		state->fec = STV090x_PR23;
+		break;
+
+	case 21:
+		state->fec = STV090x_PR34;
+		break;
+
+	case 24:
+		state->fec = STV090x_PR56;
+		break;
+
+	case 25:
+		state->fec = STV090x_PR67;
+		break;
+
+	case 26:
+		state->fec = STV090x_PR78;
+		break;
+
+	default:
+		state->fec = STV090x_PRERR;
+		break;
+	}
+
+	return 0;
+}
+
+static enum stv090x_signal_state stv090x_get_sig_params(struct stv090x_state *state)
+{
+	struct dvb_frontend *fe = &state->frontend;
+
+	u8 tmg;
+	u32 reg;
+	s32 i = 0, offst_freq;
+
+	msleep(5);
+
+	if (state->algo == STV090x_BLIND_SEARCH) {
+		tmg = STV090x_READ_DEMOD(state, TMGREG2);
+		STV090x_WRITE_DEMOD(state, SFRSTEP, 0x5c);
+		while ((i <= 50) && (tmg != 0) && (tmg != 0xff)) {
+			tmg = STV090x_READ_DEMOD(state, TMGREG2);
+			msleep(5);
+			i += 5;
+		}
+	}
+	state->delsys = stv090x_get_std(state);
+
+	if (stv090x_i2c_gate_ctrl(state, 1) < 0)
+		goto err;
+
+	if (state->config->tuner_get_frequency) {
+		if (state->config->tuner_get_frequency(fe, &state->frequency) < 0)
+			goto err_gateoff;
+	}
+
+	if (stv090x_i2c_gate_ctrl(state, 0) < 0)
+		goto err;
+
+	offst_freq = stv090x_get_car_freq(state, state->internal->mclk) / 1000;
+	state->frequency += offst_freq;
+
+	if (stv090x_get_viterbi(state) < 0)
+		goto err;
+
+	reg = STV090x_READ_DEMOD(state, DMDMODCOD);
+	state->modcod = STV090x_GETFIELD_Px(reg, DEMOD_MODCOD_FIELD);
+	state->pilots = STV090x_GETFIELD_Px(reg, DEMOD_TYPE_FIELD) & 0x01;
+	state->frame_len = STV090x_GETFIELD_Px(reg, DEMOD_TYPE_FIELD) >> 1;
+	reg = STV090x_READ_DEMOD(state, TMGOBS);
+	state->rolloff = STV090x_GETFIELD_Px(reg, ROLLOFF_STATUS_FIELD);
+	reg = STV090x_READ_DEMOD(state, FECM);
+	state->inversion = STV090x_GETFIELD_Px(reg, IQINV_FIELD);
+
+	if ((state->algo == STV090x_BLIND_SEARCH) || (state->srate < 10000000)) {
+
+		if (stv090x_i2c_gate_ctrl(state, 1) < 0)
+			goto err;
+
+		if (state->config->tuner_get_frequency) {
+			if (state->config->tuner_get_frequency(fe, &state->frequency) < 0)
+				goto err_gateoff;
+		}
+
+		if (stv090x_i2c_gate_ctrl(state, 0) < 0)
+			goto err;
+
+		if (abs(offst_freq) <= ((state->search_range / 2000) + 500))
+			return STV090x_RANGEOK;
+		else if (abs(offst_freq) <= (stv090x_car_width(state->srate, state->rolloff) / 2000))
+			return STV090x_RANGEOK;
+		else
+			return STV090x_OUTOFRANGE; /* Out of Range */
+	} else {
+		if (abs(offst_freq) <= ((state->search_range / 2000) + 500))
+			return STV090x_RANGEOK;
+		else
+			return STV090x_OUTOFRANGE;
+	}
+
+	return STV090x_OUTOFRANGE;
+
+err_gateoff:
+	stv090x_i2c_gate_ctrl(state, 0);
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static u32 stv090x_get_tmgoffst(struct stv090x_state *state, u32 srate)
+{
+	s32 offst_tmg;
+
+	offst_tmg  = STV090x_READ_DEMOD(state, TMGREG2) << 16;
+	offst_tmg |= STV090x_READ_DEMOD(state, TMGREG1) <<  8;
+	offst_tmg |= STV090x_READ_DEMOD(state, TMGREG0);
+
+	offst_tmg = comp2(offst_tmg, 24); /* 2's complement */
+	if (!offst_tmg)
+		offst_tmg = 1;
+
+	offst_tmg  = ((s32) srate * 10) / ((s32) 0x1000000 / offst_tmg);
+	offst_tmg /= 320;
+
+	return offst_tmg;
+}
+
+static u8 stv090x_optimize_carloop(struct stv090x_state *state, enum stv090x_modcod modcod, s32 pilots)
+{
+	u8 aclc = 0x29;
+	s32 i;
+	struct stv090x_long_frame_crloop *car_loop, *car_loop_qpsk_low, *car_loop_apsk_low;
+
+	if (state->internal->dev_ver == 0x20) {
+		car_loop		= stv090x_s2_crl_cut20;
+		car_loop_qpsk_low	= stv090x_s2_lowqpsk_crl_cut20;
+		car_loop_apsk_low	= stv090x_s2_apsk_crl_cut20;
+	} else {
+		/* >= Cut 3 */
+		car_loop		= stv090x_s2_crl_cut30;
+		car_loop_qpsk_low	= stv090x_s2_lowqpsk_crl_cut30;
+		car_loop_apsk_low	= stv090x_s2_apsk_crl_cut30;
+	}
+
+	if (modcod < STV090x_QPSK_12) {
+		i = 0;
+		while ((i < 3) && (modcod != car_loop_qpsk_low[i].modcod))
+			i++;
+
+		if (i >= 3)
+			i = 2;
+
+	} else {
+		i = 0;
+		while ((i < 14) && (modcod != car_loop[i].modcod))
+			i++;
+
+		if (i >= 14) {
+			i = 0;
+			while ((i < 11) && (modcod != car_loop_apsk_low[i].modcod))
+				i++;
+
+			if (i >= 11)
+				i = 10;
+		}
+	}
+
+	if (modcod <= STV090x_QPSK_25) {
+		if (pilots) {
+			if (state->srate <= 3000000)
+				aclc = car_loop_qpsk_low[i].crl_pilots_on_2;
+			else if (state->srate <= 7000000)
+				aclc = car_loop_qpsk_low[i].crl_pilots_on_5;
+			else if (state->srate <= 15000000)
+				aclc = car_loop_qpsk_low[i].crl_pilots_on_10;
+			else if (state->srate <= 25000000)
+				aclc = car_loop_qpsk_low[i].crl_pilots_on_20;
+			else
+				aclc = car_loop_qpsk_low[i].crl_pilots_on_30;
+		} else {
+			if (state->srate <= 3000000)
+				aclc = car_loop_qpsk_low[i].crl_pilots_off_2;
+			else if (state->srate <= 7000000)
+				aclc = car_loop_qpsk_low[i].crl_pilots_off_5;
+			else if (state->srate <= 15000000)
+				aclc = car_loop_qpsk_low[i].crl_pilots_off_10;
+			else if (state->srate <= 25000000)
+				aclc = car_loop_qpsk_low[i].crl_pilots_off_20;
+			else
+				aclc = car_loop_qpsk_low[i].crl_pilots_off_30;
+		}
+
+	} else if (modcod <= STV090x_8PSK_910) {
+		if (pilots) {
+			if (state->srate <= 3000000)
+				aclc = car_loop[i].crl_pilots_on_2;
+			else if (state->srate <= 7000000)
+				aclc = car_loop[i].crl_pilots_on_5;
+			else if (state->srate <= 15000000)
+				aclc = car_loop[i].crl_pilots_on_10;
+			else if (state->srate <= 25000000)
+				aclc = car_loop[i].crl_pilots_on_20;
+			else
+				aclc = car_loop[i].crl_pilots_on_30;
+		} else {
+			if (state->srate <= 3000000)
+				aclc = car_loop[i].crl_pilots_off_2;
+			else if (state->srate <= 7000000)
+				aclc = car_loop[i].crl_pilots_off_5;
+			else if (state->srate <= 15000000)
+				aclc = car_loop[i].crl_pilots_off_10;
+			else if (state->srate <= 25000000)
+				aclc = car_loop[i].crl_pilots_off_20;
+			else
+				aclc = car_loop[i].crl_pilots_off_30;
+		}
+	} else { /* 16APSK and 32APSK */
+		if (state->srate <= 3000000)
+			aclc = car_loop_apsk_low[i].crl_pilots_on_2;
+		else if (state->srate <= 7000000)
+			aclc = car_loop_apsk_low[i].crl_pilots_on_5;
+		else if (state->srate <= 15000000)
+			aclc = car_loop_apsk_low[i].crl_pilots_on_10;
+		else if (state->srate <= 25000000)
+			aclc = car_loop_apsk_low[i].crl_pilots_on_20;
+		else
+			aclc = car_loop_apsk_low[i].crl_pilots_on_30;
+	}
+
+	return aclc;
+}
+
+static u8 stv090x_optimize_carloop_short(struct stv090x_state *state)
+{
+	struct stv090x_short_frame_crloop *short_crl = NULL;
+	s32 index = 0;
+	u8 aclc = 0x0b;
+
+	switch (state->modulation) {
+	case STV090x_QPSK:
+	default:
+		index = 0;
+		break;
+	case STV090x_8PSK:
+		index = 1;
+		break;
+	case STV090x_16APSK:
+		index = 2;
+		break;
+	case STV090x_32APSK:
+		index = 3;
+		break;
+	}
+
+	if (state->internal->dev_ver >= 0x30) {
+		/* Cut 3.0 and up */
+		short_crl = stv090x_s2_short_crl_cut30;
+	} else {
+		/* Cut 2.0 and up: we don't support cuts older than 2.0 */
+		short_crl = stv090x_s2_short_crl_cut20;
+	}
+
+	if (state->srate <= 3000000)
+		aclc = short_crl[index].crl_2;
+	else if (state->srate <= 7000000)
+		aclc = short_crl[index].crl_5;
+	else if (state->srate <= 15000000)
+		aclc = short_crl[index].crl_10;
+	else if (state->srate <= 25000000)
+		aclc = short_crl[index].crl_20;
+	else
+		aclc = short_crl[index].crl_30;
+
+	return aclc;
+}
+
+static int stv090x_optimize_track(struct stv090x_state *state)
+{
+	struct dvb_frontend *fe = &state->frontend;
+
+	enum stv090x_modcod modcod;
+
+	s32 srate, pilots, aclc, f_1, f_0, i = 0, blind_tune = 0;
+	u32 reg;
+
+	srate  = stv090x_get_srate(state, state->internal->mclk);
+	srate += stv090x_get_tmgoffst(state, srate);
+
+	switch (state->delsys) {
+	case STV090x_DVBS1:
+	case STV090x_DSS:
+		if (state->search_mode == STV090x_SEARCH_AUTO) {
+			reg = STV090x_READ_DEMOD(state, DMDCFGMD);
+			STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 1);
+			STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 0);
+			if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
+				goto err;
+		}
+		reg = STV090x_READ_DEMOD(state, DEMOD);
+		STV090x_SETFIELD_Px(reg, ROLLOFF_CONTROL_FIELD, state->rolloff);
+		STV090x_SETFIELD_Px(reg, MANUAL_SXROLLOFF_FIELD, 0x01);
+		if (STV090x_WRITE_DEMOD(state, DEMOD, reg) < 0)
+			goto err;
+
+		if (state->internal->dev_ver >= 0x30) {
+			if (stv090x_get_viterbi(state) < 0)
+				goto err;
+
+			if (state->fec == STV090x_PR12) {
+				if (STV090x_WRITE_DEMOD(state, GAUSSR0, 0x98) < 0)
+					goto err;
+				if (STV090x_WRITE_DEMOD(state, CCIR0, 0x18) < 0)
+					goto err;
+			} else {
+				if (STV090x_WRITE_DEMOD(state, GAUSSR0, 0x18) < 0)
+					goto err;
+				if (STV090x_WRITE_DEMOD(state, CCIR0, 0x18) < 0)
+					goto err;
+			}
+		}
+
+		if (STV090x_WRITE_DEMOD(state, ERRCTRL1, 0x75) < 0)
+			goto err;
+		break;
+
+	case STV090x_DVBS2:
+		reg = STV090x_READ_DEMOD(state, DMDCFGMD);
+		STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 0);
+		STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 1);
+		if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
+			goto err;
+		if (state->internal->dev_ver >= 0x30) {
+			if (STV090x_WRITE_DEMOD(state, ACLC, 0) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, BCLC, 0) < 0)
+				goto err;
+		}
+		if (state->frame_len == STV090x_LONG_FRAME) {
+			reg = STV090x_READ_DEMOD(state, DMDMODCOD);
+			modcod = STV090x_GETFIELD_Px(reg, DEMOD_MODCOD_FIELD);
+			pilots = STV090x_GETFIELD_Px(reg, DEMOD_TYPE_FIELD) & 0x01;
+			aclc = stv090x_optimize_carloop(state, modcod, pilots);
+			if (modcod <= STV090x_QPSK_910) {
+				STV090x_WRITE_DEMOD(state, ACLC2S2Q, aclc);
+			} else if (modcod <= STV090x_8PSK_910) {
+				if (STV090x_WRITE_DEMOD(state, ACLC2S2Q, 0x2a) < 0)
+					goto err;
+				if (STV090x_WRITE_DEMOD(state, ACLC2S28, aclc) < 0)
+					goto err;
+			}
+			if ((state->demod_mode == STV090x_SINGLE) && (modcod > STV090x_8PSK_910)) {
+				if (modcod <= STV090x_16APSK_910) {
+					if (STV090x_WRITE_DEMOD(state, ACLC2S2Q, 0x2a) < 0)
+						goto err;
+					if (STV090x_WRITE_DEMOD(state, ACLC2S216A, aclc) < 0)
+						goto err;
+				} else {
+					if (STV090x_WRITE_DEMOD(state, ACLC2S2Q, 0x2a) < 0)
+						goto err;
+					if (STV090x_WRITE_DEMOD(state, ACLC2S232A, aclc) < 0)
+						goto err;
+				}
+			}
+		} else {
+			/*Carrier loop setting for short frame*/
+			aclc = stv090x_optimize_carloop_short(state);
+			if (state->modulation == STV090x_QPSK) {
+				if (STV090x_WRITE_DEMOD(state, ACLC2S2Q, aclc) < 0)
+					goto err;
+			} else if (state->modulation == STV090x_8PSK) {
+				if (STV090x_WRITE_DEMOD(state, ACLC2S2Q, 0x2a) < 0)
+					goto err;
+				if (STV090x_WRITE_DEMOD(state, ACLC2S28, aclc) < 0)
+					goto err;
+			} else if (state->modulation == STV090x_16APSK) {
+				if (STV090x_WRITE_DEMOD(state, ACLC2S2Q, 0x2a) < 0)
+					goto err;
+				if (STV090x_WRITE_DEMOD(state, ACLC2S216A, aclc) < 0)
+					goto err;
+			} else if (state->modulation == STV090x_32APSK)  {
+				if (STV090x_WRITE_DEMOD(state, ACLC2S2Q, 0x2a) < 0)
+					goto err;
+				if (STV090x_WRITE_DEMOD(state, ACLC2S232A, aclc) < 0)
+					goto err;
+			}
+		}
+
+		STV090x_WRITE_DEMOD(state, ERRCTRL1, 0x67); /* PER */
+		break;
+
+	case STV090x_ERROR:
+	default:
+		reg = STV090x_READ_DEMOD(state, DMDCFGMD);
+		STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 1);
+		STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 1);
+		if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
+			goto err;
+		break;
+	}
+
+	f_1 = STV090x_READ_DEMOD(state, CFR2);
+	f_0 = STV090x_READ_DEMOD(state, CFR1);
+	reg = STV090x_READ_DEMOD(state, TMGOBS);
+
+	if (state->algo == STV090x_BLIND_SEARCH) {
+		STV090x_WRITE_DEMOD(state, SFRSTEP, 0x00);
+		reg = STV090x_READ_DEMOD(state, DMDCFGMD);
+		STV090x_SETFIELD_Px(reg, SCAN_ENABLE_FIELD, 0x00);
+		STV090x_SETFIELD_Px(reg, CFR_AUTOSCAN_FIELD, 0x00);
+		if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, TMGCFG2, 0xc1) < 0)
+			goto err;
+
+		if (stv090x_set_srate(state, srate) < 0)
+			goto err;
+		blind_tune = 1;
+
+		if (stv090x_dvbs_track_crl(state) < 0)
+			goto err;
+	}
+
+	if (state->internal->dev_ver >= 0x20) {
+		if ((state->search_mode == STV090x_SEARCH_DVBS1)	||
+		    (state->search_mode == STV090x_SEARCH_DSS)		||
+		    (state->search_mode == STV090x_SEARCH_AUTO)) {
+
+			if (STV090x_WRITE_DEMOD(state, VAVSRVIT, 0x0a) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, VITSCALE, 0x00) < 0)
+				goto err;
+		}
+	}
+
+	if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x38) < 0)
+		goto err;
+
+	/* AUTO tracking MODE */
+	if (STV090x_WRITE_DEMOD(state, SFRUP1, 0x80) < 0)
+		goto err;
+	/* AUTO tracking MODE */
+	if (STV090x_WRITE_DEMOD(state, SFRLOW1, 0x80) < 0)
+		goto err;
+
+	if ((state->internal->dev_ver >= 0x20) || (blind_tune == 1) ||
+	    (state->srate < 10000000)) {
+		/* update initial carrier freq with the found freq offset */
+		if (STV090x_WRITE_DEMOD(state, CFRINIT1, f_1) < 0)
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, CFRINIT0, f_0) < 0)
+			goto err;
+		state->tuner_bw = stv090x_car_width(srate, state->rolloff) + 10000000;
+
+		if ((state->internal->dev_ver >= 0x20) || (blind_tune == 1)) {
+
+			if (state->algo != STV090x_WARM_SEARCH) {
+
+				if (stv090x_i2c_gate_ctrl(state, 1) < 0)
+					goto err;
+
+				if (state->config->tuner_set_bandwidth) {
+					if (state->config->tuner_set_bandwidth(fe, state->tuner_bw) < 0)
+						goto err_gateoff;
+				}
+
+				if (stv090x_i2c_gate_ctrl(state, 0) < 0)
+					goto err;
+
+			}
+		}
+		if ((state->algo == STV090x_BLIND_SEARCH) || (state->srate < 10000000))
+			msleep(50); /* blind search: wait 50ms for SR stabilization */
+		else
+			msleep(5);
+
+		stv090x_get_lock_tmg(state);
+
+		if (!(stv090x_get_dmdlock(state, (state->DemodTimeout / 2)))) {
+			if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, CFRINIT1, f_1) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, CFRINIT0, f_0) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x18) < 0)
+				goto err;
+
+			i = 0;
+
+			while ((!(stv090x_get_dmdlock(state, (state->DemodTimeout / 2)))) && (i <= 2)) {
+
+				if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0)
+					goto err;
+				if (STV090x_WRITE_DEMOD(state, CFRINIT1, f_1) < 0)
+					goto err;
+				if (STV090x_WRITE_DEMOD(state, CFRINIT0, f_0) < 0)
+					goto err;
+				if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x18) < 0)
+					goto err;
+				i++;
+			}
+		}
+
+	}
+
+	if (state->internal->dev_ver >= 0x20) {
+		if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x49) < 0)
+			goto err;
+	}
+
+	if ((state->delsys == STV090x_DVBS1) || (state->delsys == STV090x_DSS))
+		stv090x_set_vit_thtracq(state);
+
+	return 0;
+
+err_gateoff:
+	stv090x_i2c_gate_ctrl(state, 0);
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static int stv090x_get_feclock(struct stv090x_state *state, s32 timeout)
+{
+	s32 timer = 0, lock = 0, stat;
+	u32 reg;
+
+	while ((timer < timeout) && (!lock)) {
+		reg = STV090x_READ_DEMOD(state, DMDSTATE);
+		stat = STV090x_GETFIELD_Px(reg, HEADER_MODE_FIELD);
+
+		switch (stat) {
+		case 0: /* searching */
+		case 1: /* first PLH detected */
+		default:
+			lock = 0;
+			break;
+
+		case 2: /* DVB-S2 mode */
+			reg = STV090x_READ_DEMOD(state, PDELSTATUS1);
+			lock = STV090x_GETFIELD_Px(reg, PKTDELIN_LOCK_FIELD);
+			break;
+
+		case 3: /* DVB-S1/legacy mode */
+			reg = STV090x_READ_DEMOD(state, VSTATUSVIT);
+			lock = STV090x_GETFIELD_Px(reg, LOCKEDVIT_FIELD);
+			break;
+		}
+		if (!lock) {
+			msleep(10);
+			timer += 10;
+		}
+	}
+	return lock;
+}
+
+static int stv090x_get_lock(struct stv090x_state *state, s32 timeout_dmd, s32 timeout_fec)
+{
+	u32 reg;
+	s32 timer = 0;
+	int lock;
+
+	lock = stv090x_get_dmdlock(state, timeout_dmd);
+	if (lock)
+		lock = stv090x_get_feclock(state, timeout_fec);
+
+	if (lock) {
+		lock = 0;
+
+		while ((timer < timeout_fec) && (!lock)) {
+			reg = STV090x_READ_DEMOD(state, TSSTATUS);
+			lock = STV090x_GETFIELD_Px(reg, TSFIFO_LINEOK_FIELD);
+			msleep(1);
+			timer++;
+		}
+	}
+
+	return lock;
+}
+
+static int stv090x_set_s2rolloff(struct stv090x_state *state)
+{
+	u32 reg;
+
+	if (state->internal->dev_ver <= 0x20) {
+		/* rolloff to auto mode if DVBS2 */
+		reg = STV090x_READ_DEMOD(state, DEMOD);
+		STV090x_SETFIELD_Px(reg, MANUAL_SXROLLOFF_FIELD, 0x00);
+		if (STV090x_WRITE_DEMOD(state, DEMOD, reg) < 0)
+			goto err;
+	} else {
+		/* DVB-S2 rolloff to auto mode if DVBS2 */
+		reg = STV090x_READ_DEMOD(state, DEMOD);
+		STV090x_SETFIELD_Px(reg, MANUAL_S2ROLLOFF_FIELD, 0x00);
+		if (STV090x_WRITE_DEMOD(state, DEMOD, reg) < 0)
+			goto err;
+	}
+	return 0;
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+
+static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state)
+{
+	struct dvb_frontend *fe = &state->frontend;
+	enum stv090x_signal_state signal_state = STV090x_NOCARRIER;
+	u32 reg;
+	s32 agc1_power, power_iq = 0, i;
+	int lock = 0, low_sr = 0;
+
+	reg = STV090x_READ_DEMOD(state, TSCFGH);
+	STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 1); /* Stop path 1 stream merger */
+	if (STV090x_WRITE_DEMOD(state, TSCFGH, reg) < 0)
+		goto err;
+
+	if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x5c) < 0) /* Demod stop */
+		goto err;
+
+	if (state->internal->dev_ver >= 0x20) {
+		if (state->srate > 5000000) {
+			if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x9e) < 0)
+				goto err;
+		} else {
+			if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x82) < 0)
+				goto err;
+		}
+	}
+
+	stv090x_get_lock_tmg(state);
+
+	if (state->algo == STV090x_BLIND_SEARCH) {
+		state->tuner_bw = 2 * 36000000; /* wide bw for unknown srate */
+		if (STV090x_WRITE_DEMOD(state, TMGCFG2, 0xc0) < 0) /* wider srate scan */
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, CORRELMANT, 0x70) < 0)
+			goto err;
+		if (stv090x_set_srate(state, 1000000) < 0) /* initial srate = 1Msps */
+			goto err;
+	} else {
+		/* known srate */
+		if (STV090x_WRITE_DEMOD(state, DMDTOM, 0x20) < 0)
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, TMGCFG, 0xd2) < 0)
+			goto err;
+
+		if (state->srate < 2000000) {
+			/* SR < 2MSPS */
+			if (STV090x_WRITE_DEMOD(state, CORRELMANT, 0x63) < 0)
+				goto err;
+		} else {
+			/* SR >= 2Msps */
+			if (STV090x_WRITE_DEMOD(state, CORRELMANT, 0x70) < 0)
+				goto err;
+		}
+
+		if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x38) < 0)
+			goto err;
+
+		if (state->internal->dev_ver >= 0x20) {
+			if (STV090x_WRITE_DEMOD(state, KREFTMG, 0x5a) < 0)
+				goto err;
+			if (state->algo == STV090x_COLD_SEARCH)
+				state->tuner_bw = (15 * (stv090x_car_width(state->srate, state->rolloff) + 10000000)) / 10;
+			else if (state->algo == STV090x_WARM_SEARCH)
+				state->tuner_bw = stv090x_car_width(state->srate, state->rolloff) + 10000000;
+		}
+
+		/* if cold start or warm  (Symbolrate is known)
+		 * use a Narrow symbol rate scan range
+		 */
+		if (STV090x_WRITE_DEMOD(state, TMGCFG2, 0xc1) < 0) /* narrow srate scan */
+			goto err;
+
+		if (stv090x_set_srate(state, state->srate) < 0)
+			goto err;
+
+		if (stv090x_set_max_srate(state, state->internal->mclk,
+					  state->srate) < 0)
+			goto err;
+		if (stv090x_set_min_srate(state, state->internal->mclk,
+					  state->srate) < 0)
+			goto err;
+
+		if (state->srate >= 10000000)
+			low_sr = 0;
+		else
+			low_sr = 1;
+	}
+
+	/* Setup tuner */
+	if (stv090x_i2c_gate_ctrl(state, 1) < 0)
+		goto err;
+
+	if (state->config->tuner_set_bbgain) {
+		reg = state->config->tuner_bbgain;
+		if (reg == 0)
+			reg = 10; /* default: 10dB */
+		if (state->config->tuner_set_bbgain(fe, reg) < 0)
+			goto err_gateoff;
+	}
+
+	if (state->config->tuner_set_frequency) {
+		if (state->config->tuner_set_frequency(fe, state->frequency) < 0)
+			goto err_gateoff;
+	}
+
+	if (state->config->tuner_set_bandwidth) {
+		if (state->config->tuner_set_bandwidth(fe, state->tuner_bw) < 0)
+			goto err_gateoff;
+	}
+
+	if (stv090x_i2c_gate_ctrl(state, 0) < 0)
+		goto err;
+
+	msleep(50);
+
+	if (state->config->tuner_get_status) {
+		if (stv090x_i2c_gate_ctrl(state, 1) < 0)
+			goto err;
+		if (state->config->tuner_get_status(fe, &reg) < 0)
+			goto err_gateoff;
+		if (stv090x_i2c_gate_ctrl(state, 0) < 0)
+			goto err;
+
+		if (reg)
+			dprintk(FE_DEBUG, 1, "Tuner phase locked");
+		else {
+			dprintk(FE_DEBUG, 1, "Tuner unlocked");
+			return STV090x_NOCARRIER;
+		}
+	}
+
+	msleep(10);
+	agc1_power = MAKEWORD16(STV090x_READ_DEMOD(state, AGCIQIN1),
+				STV090x_READ_DEMOD(state, AGCIQIN0));
+
+	if (agc1_power == 0) {
+		/* If AGC1 integrator value is 0
+		 * then read POWERI, POWERQ
+		 */
+		for (i = 0; i < 5; i++) {
+			power_iq += (STV090x_READ_DEMOD(state, POWERI) +
+				     STV090x_READ_DEMOD(state, POWERQ)) >> 1;
+		}
+		power_iq /= 5;
+	}
+
+	if ((agc1_power == 0) && (power_iq < STV090x_IQPOWER_THRESHOLD)) {
+		dprintk(FE_ERROR, 1, "No Signal: POWER_IQ=0x%02x", power_iq);
+		lock = 0;
+		signal_state = STV090x_NOAGC1;
+	} else {
+		reg = STV090x_READ_DEMOD(state, DEMOD);
+		STV090x_SETFIELD_Px(reg, SPECINV_CONTROL_FIELD, state->inversion);
+
+		if (state->internal->dev_ver <= 0x20) {
+			/* rolloff to auto mode if DVBS2 */
+			STV090x_SETFIELD_Px(reg, MANUAL_SXROLLOFF_FIELD, 1);
+		} else {
+			/* DVB-S2 rolloff to auto mode if DVBS2 */
+			STV090x_SETFIELD_Px(reg, MANUAL_S2ROLLOFF_FIELD, 1);
+		}
+		if (STV090x_WRITE_DEMOD(state, DEMOD, reg) < 0)
+			goto err;
+
+		if (stv090x_delivery_search(state) < 0)
+			goto err;
+
+		if (state->algo != STV090x_BLIND_SEARCH) {
+			if (stv090x_start_search(state) < 0)
+				goto err;
+		}
+	}
+
+	if (signal_state == STV090x_NOAGC1)
+		return signal_state;
+
+	if (state->algo == STV090x_BLIND_SEARCH)
+		lock = stv090x_blind_search(state);
+
+	else if (state->algo == STV090x_COLD_SEARCH)
+		lock = stv090x_get_coldlock(state, state->DemodTimeout);
+
+	else if (state->algo == STV090x_WARM_SEARCH)
+		lock = stv090x_get_dmdlock(state, state->DemodTimeout);
+
+	if ((!lock) && (state->algo == STV090x_COLD_SEARCH)) {
+		if (!low_sr) {
+			if (stv090x_chk_tmg(state))
+				lock = stv090x_sw_algo(state);
+		}
+	}
+
+	if (lock)
+		signal_state = stv090x_get_sig_params(state);
+
+	if ((lock) && (signal_state == STV090x_RANGEOK)) { /* signal within Range */
+		stv090x_optimize_track(state);
+
+		if (state->internal->dev_ver >= 0x20) {
+			/* >= Cut 2.0 :release TS reset after
+			 * demod lock and optimized Tracking
+			 */
+			reg = STV090x_READ_DEMOD(state, TSCFGH);
+			STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0); /* release merger reset */
+			if (STV090x_WRITE_DEMOD(state, TSCFGH, reg) < 0)
+				goto err;
+
+			msleep(3);
+
+			STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 1); /* merger reset */
+			if (STV090x_WRITE_DEMOD(state, TSCFGH, reg) < 0)
+				goto err;
+
+			STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0); /* release merger reset */
+			if (STV090x_WRITE_DEMOD(state, TSCFGH, reg) < 0)
+				goto err;
+		}
+
+		lock = stv090x_get_lock(state, state->FecTimeout,
+				state->FecTimeout);
+		if (lock) {
+			if (state->delsys == STV090x_DVBS2) {
+				stv090x_set_s2rolloff(state);
+
+				reg = STV090x_READ_DEMOD(state, PDELCTRL2);
+				STV090x_SETFIELD_Px(reg, RESET_UPKO_COUNT, 1);
+				if (STV090x_WRITE_DEMOD(state, PDELCTRL2, reg) < 0)
+					goto err;
+				/* Reset DVBS2 packet delinator error counter */
+				reg = STV090x_READ_DEMOD(state, PDELCTRL2);
+				STV090x_SETFIELD_Px(reg, RESET_UPKO_COUNT, 0);
+				if (STV090x_WRITE_DEMOD(state, PDELCTRL2, reg) < 0)
+					goto err;
+
+				if (STV090x_WRITE_DEMOD(state, ERRCTRL1, 0x67) < 0) /* PER */
+					goto err;
+			} else {
+				if (STV090x_WRITE_DEMOD(state, ERRCTRL1, 0x75) < 0)
+					goto err;
+			}
+			/* Reset the Total packet counter */
+			if (STV090x_WRITE_DEMOD(state, FBERCPT4, 0x00) < 0)
+				goto err;
+			/* Reset the packet Error counter2 */
+			if (STV090x_WRITE_DEMOD(state, ERRCTRL2, 0xc1) < 0)
+				goto err;
+		} else {
+			signal_state = STV090x_NODATA;
+			stv090x_chk_signal(state);
+		}
+	}
+	return signal_state;
+
+err_gateoff:
+	stv090x_i2c_gate_ctrl(state, 0);
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static int stv090x_set_mis(struct stv090x_state *state, int mis)
+{
+	u32 reg;
+
+	if (mis < 0 || mis > 255) {
+		dprintk(FE_DEBUG, 1, "Disable MIS filtering");
+		reg = STV090x_READ_DEMOD(state, PDELCTRL1);
+		STV090x_SETFIELD_Px(reg, FILTER_EN_FIELD, 0x00);
+		if (STV090x_WRITE_DEMOD(state, PDELCTRL1, reg) < 0)
+			goto err;
+	} else {
+		dprintk(FE_DEBUG, 1, "Enable MIS filtering - %d", mis);
+		reg = STV090x_READ_DEMOD(state, PDELCTRL1);
+		STV090x_SETFIELD_Px(reg, FILTER_EN_FIELD, 0x01);
+		if (STV090x_WRITE_DEMOD(state, PDELCTRL1, reg) < 0)
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, ISIENTRY, mis) < 0)
+			goto err;
+		if (STV090x_WRITE_DEMOD(state, ISIBITENA, 0xff) < 0)
+			goto err;
+	}
+	return 0;
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static enum dvbfe_search stv090x_search(struct dvb_frontend *fe)
+{
+	struct stv090x_state *state = fe->demodulator_priv;
+	struct dtv_frontend_properties *props = &fe->dtv_property_cache;
+
+	if (props->frequency == 0)
+		return DVBFE_ALGO_SEARCH_INVALID;
+
+	state->delsys = props->delivery_system;
+	state->frequency = props->frequency;
+	state->srate = props->symbol_rate;
+	state->search_mode = STV090x_SEARCH_AUTO;
+	state->algo = STV090x_COLD_SEARCH;
+	state->fec = STV090x_PRERR;
+	if (state->srate > 10000000) {
+		dprintk(FE_DEBUG, 1, "Search range: 10 MHz");
+		state->search_range = 10000000;
+	} else {
+		dprintk(FE_DEBUG, 1, "Search range: 5 MHz");
+		state->search_range = 5000000;
+	}
+
+	stv090x_set_mis(state, props->stream_id);
+
+	if (stv090x_algo(state) == STV090x_RANGEOK) {
+		dprintk(FE_DEBUG, 1, "Search success!");
+		return DVBFE_ALGO_SEARCH_SUCCESS;
+	} else {
+		dprintk(FE_DEBUG, 1, "Search failed!");
+		return DVBFE_ALGO_SEARCH_FAILED;
+	}
+
+	return DVBFE_ALGO_SEARCH_ERROR;
+}
+
+static int stv090x_read_status(struct dvb_frontend *fe, enum fe_status *status)
+{
+	struct stv090x_state *state = fe->demodulator_priv;
+	u32 reg, dstatus;
+	u8 search_state;
+
+	*status = 0;
+
+	dstatus = STV090x_READ_DEMOD(state, DSTATUS);
+	if (STV090x_GETFIELD_Px(dstatus, CAR_LOCK_FIELD))
+		*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER;
+
+	reg = STV090x_READ_DEMOD(state, DMDSTATE);
+	search_state = STV090x_GETFIELD_Px(reg, HEADER_MODE_FIELD);
+
+	switch (search_state) {
+	case 0: /* searching */
+	case 1: /* first PLH detected */
+	default:
+		dprintk(FE_DEBUG, 1, "Status: Unlocked (Searching ..)");
+		break;
+
+	case 2: /* DVB-S2 mode */
+		dprintk(FE_DEBUG, 1, "Delivery system: DVB-S2");
+		if (STV090x_GETFIELD_Px(dstatus, LOCK_DEFINITIF_FIELD)) {
+			reg = STV090x_READ_DEMOD(state, PDELSTATUS1);
+			if (STV090x_GETFIELD_Px(reg, PKTDELIN_LOCK_FIELD)) {
+				*status |= FE_HAS_VITERBI;
+				reg = STV090x_READ_DEMOD(state, TSSTATUS);
+				if (STV090x_GETFIELD_Px(reg, TSFIFO_LINEOK_FIELD))
+					*status |= FE_HAS_SYNC | FE_HAS_LOCK;
+			}
+		}
+		break;
+
+	case 3: /* DVB-S1/legacy mode */
+		dprintk(FE_DEBUG, 1, "Delivery system: DVB-S");
+		if (STV090x_GETFIELD_Px(dstatus, LOCK_DEFINITIF_FIELD)) {
+			reg = STV090x_READ_DEMOD(state, VSTATUSVIT);
+			if (STV090x_GETFIELD_Px(reg, LOCKEDVIT_FIELD)) {
+				*status |= FE_HAS_VITERBI;
+				reg = STV090x_READ_DEMOD(state, TSSTATUS);
+				if (STV090x_GETFIELD_Px(reg, TSFIFO_LINEOK_FIELD))
+					*status |= FE_HAS_SYNC | FE_HAS_LOCK;
+			}
+		}
+		break;
+	}
+
+	return 0;
+}
+
+static int stv090x_read_per(struct dvb_frontend *fe, u32 *per)
+{
+	struct stv090x_state *state = fe->demodulator_priv;
+
+	s32 count_4, count_3, count_2, count_1, count_0, count;
+	u32 reg, h, m, l;
+	enum fe_status status;
+
+	stv090x_read_status(fe, &status);
+	if (!(status & FE_HAS_LOCK)) {
+		*per = 1 << 23; /* Max PER */
+	} else {
+		/* Counter 2 */
+		reg = STV090x_READ_DEMOD(state, ERRCNT22);
+		h = STV090x_GETFIELD_Px(reg, ERR_CNT2_FIELD);
+
+		reg = STV090x_READ_DEMOD(state, ERRCNT21);
+		m = STV090x_GETFIELD_Px(reg, ERR_CNT21_FIELD);
+
+		reg = STV090x_READ_DEMOD(state, ERRCNT20);
+		l = STV090x_GETFIELD_Px(reg, ERR_CNT20_FIELD);
+
+		*per = ((h << 16) | (m << 8) | l);
+
+		count_4 = STV090x_READ_DEMOD(state, FBERCPT4);
+		count_3 = STV090x_READ_DEMOD(state, FBERCPT3);
+		count_2 = STV090x_READ_DEMOD(state, FBERCPT2);
+		count_1 = STV090x_READ_DEMOD(state, FBERCPT1);
+		count_0 = STV090x_READ_DEMOD(state, FBERCPT0);
+
+		if ((!count_4) && (!count_3)) {
+			count  = (count_2 & 0xff) << 16;
+			count |= (count_1 & 0xff) <<  8;
+			count |=  count_0 & 0xff;
+		} else {
+			count = 1 << 24;
+		}
+		if (count == 0)
+			*per = 1;
+	}
+	if (STV090x_WRITE_DEMOD(state, FBERCPT4, 0) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, ERRCTRL2, 0xc1) < 0)
+		goto err;
+
+	return 0;
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static int stv090x_table_lookup(const struct stv090x_tab *tab, int max, int val)
+{
+	int res = 0;
+	int min = 0, med;
+
+	if ((val >= tab[min].read && val < tab[max].read) ||
+	    (val >= tab[max].read && val < tab[min].read)) {
+		while ((max - min) > 1) {
+			med = (max + min) / 2;
+			if ((val >= tab[min].read && val < tab[med].read) ||
+			    (val >= tab[med].read && val < tab[min].read))
+				max = med;
+			else
+				min = med;
+		}
+		res = ((val - tab[min].read) *
+		       (tab[max].real - tab[min].real) /
+		       (tab[max].read - tab[min].read)) +
+			tab[min].real;
+	} else {
+		if (tab[min].read < tab[max].read) {
+			if (val < tab[min].read)
+				res = tab[min].real;
+			else if (val >= tab[max].read)
+				res = tab[max].real;
+		} else {
+			if (val >= tab[min].read)
+				res = tab[min].real;
+			else if (val < tab[max].read)
+				res = tab[max].real;
+		}
+	}
+
+	return res;
+}
+
+static int stv090x_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
+{
+	struct stv090x_state *state = fe->demodulator_priv;
+	u32 reg;
+	s32 agc_0, agc_1, agc;
+	s32 str;
+
+	reg = STV090x_READ_DEMOD(state, AGCIQIN1);
+	agc_1 = STV090x_GETFIELD_Px(reg, AGCIQ_VALUE_FIELD);
+	reg = STV090x_READ_DEMOD(state, AGCIQIN0);
+	agc_0 = STV090x_GETFIELD_Px(reg, AGCIQ_VALUE_FIELD);
+	agc = MAKEWORD16(agc_1, agc_0);
+
+	str = stv090x_table_lookup(stv090x_rf_tab,
+		ARRAY_SIZE(stv090x_rf_tab) - 1, agc);
+	if (agc > stv090x_rf_tab[0].read)
+		str = 0;
+	else if (agc < stv090x_rf_tab[ARRAY_SIZE(stv090x_rf_tab) - 1].read)
+		str = -100;
+	*strength = (str + 100) * 0xFFFF / 100;
+
+	return 0;
+}
+
+static int stv090x_read_cnr(struct dvb_frontend *fe, u16 *cnr)
+{
+	struct stv090x_state *state = fe->demodulator_priv;
+	u32 reg_0, reg_1, reg, i;
+	s32 val_0, val_1, val = 0;
+	u8 lock_f;
+	s32 div;
+	u32 last;
+
+	switch (state->delsys) {
+	case STV090x_DVBS2:
+		reg = STV090x_READ_DEMOD(state, DSTATUS);
+		lock_f = STV090x_GETFIELD_Px(reg, LOCK_DEFINITIF_FIELD);
+		if (lock_f) {
+			msleep(5);
+			for (i = 0; i < 16; i++) {
+				reg_1 = STV090x_READ_DEMOD(state, NNOSPLHT1);
+				val_1 = STV090x_GETFIELD_Px(reg_1, NOSPLHT_NORMED_FIELD);
+				reg_0 = STV090x_READ_DEMOD(state, NNOSPLHT0);
+				val_0 = STV090x_GETFIELD_Px(reg_0, NOSPLHT_NORMED_FIELD);
+				val  += MAKEWORD16(val_1, val_0);
+				msleep(1);
+			}
+			val /= 16;
+			last = ARRAY_SIZE(stv090x_s2cn_tab) - 1;
+			div = stv090x_s2cn_tab[0].read -
+			      stv090x_s2cn_tab[last].read;
+			*cnr = 0xFFFF - ((val * 0xFFFF) / div);
+		}
+		break;
+
+	case STV090x_DVBS1:
+	case STV090x_DSS:
+		reg = STV090x_READ_DEMOD(state, DSTATUS);
+		lock_f = STV090x_GETFIELD_Px(reg, LOCK_DEFINITIF_FIELD);
+		if (lock_f) {
+			msleep(5);
+			for (i = 0; i < 16; i++) {
+				reg_1 = STV090x_READ_DEMOD(state, NOSDATAT1);
+				val_1 = STV090x_GETFIELD_Px(reg_1, NOSDATAT_UNNORMED_FIELD);
+				reg_0 = STV090x_READ_DEMOD(state, NOSDATAT0);
+				val_0 = STV090x_GETFIELD_Px(reg_0, NOSDATAT_UNNORMED_FIELD);
+				val  += MAKEWORD16(val_1, val_0);
+				msleep(1);
+			}
+			val /= 16;
+			last = ARRAY_SIZE(stv090x_s1cn_tab) - 1;
+			div = stv090x_s1cn_tab[0].read -
+			      stv090x_s1cn_tab[last].read;
+			*cnr = 0xFFFF - ((val * 0xFFFF) / div);
+		}
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static int stv090x_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
+{
+	struct stv090x_state *state = fe->demodulator_priv;
+	u32 reg;
+
+	reg = STV090x_READ_DEMOD(state, DISTXCTL);
+	switch (tone) {
+	case SEC_TONE_ON:
+		STV090x_SETFIELD_Px(reg, DISTX_MODE_FIELD, 0);
+		STV090x_SETFIELD_Px(reg, DISEQC_RESET_FIELD, 1);
+		if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0)
+			goto err;
+		STV090x_SETFIELD_Px(reg, DISEQC_RESET_FIELD, 0);
+		if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0)
+			goto err;
+		break;
+
+	case SEC_TONE_OFF:
+		STV090x_SETFIELD_Px(reg, DISTX_MODE_FIELD, 0);
+		STV090x_SETFIELD_Px(reg, DISEQC_RESET_FIELD, 1);
+		if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0)
+			goto err;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+
+static enum dvbfe_algo stv090x_frontend_algo(struct dvb_frontend *fe)
+{
+	return DVBFE_ALGO_CUSTOM;
+}
+
+static int stv090x_send_diseqc_msg(struct dvb_frontend *fe, struct dvb_diseqc_master_cmd *cmd)
+{
+	struct stv090x_state *state = fe->demodulator_priv;
+	u32 reg, idle = 0, fifo_full = 1;
+	int i;
+
+	reg = STV090x_READ_DEMOD(state, DISTXCTL);
+
+	STV090x_SETFIELD_Px(reg, DISTX_MODE_FIELD,
+		(state->config->diseqc_envelope_mode) ? 4 : 2);
+	STV090x_SETFIELD_Px(reg, DISEQC_RESET_FIELD, 1);
+	if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0)
+		goto err;
+	STV090x_SETFIELD_Px(reg, DISEQC_RESET_FIELD, 0);
+	if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0)
+		goto err;
+
+	STV090x_SETFIELD_Px(reg, DIS_PRECHARGE_FIELD, 1);
+	if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0)
+		goto err;
+
+	for (i = 0; i < cmd->msg_len; i++) {
+
+		while (fifo_full) {
+			reg = STV090x_READ_DEMOD(state, DISTXSTATUS);
+			fifo_full = STV090x_GETFIELD_Px(reg, FIFO_FULL_FIELD);
+		}
+
+		if (STV090x_WRITE_DEMOD(state, DISTXDATA, cmd->msg[i]) < 0)
+			goto err;
+	}
+	reg = STV090x_READ_DEMOD(state, DISTXCTL);
+	STV090x_SETFIELD_Px(reg, DIS_PRECHARGE_FIELD, 0);
+	if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0)
+		goto err;
+
+	i = 0;
+
+	while ((!idle) && (i < 10)) {
+		reg = STV090x_READ_DEMOD(state, DISTXSTATUS);
+		idle = STV090x_GETFIELD_Px(reg, TX_IDLE_FIELD);
+		msleep(10);
+		i++;
+	}
+
+	return 0;
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static int stv090x_send_diseqc_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t burst)
+{
+	struct stv090x_state *state = fe->demodulator_priv;
+	u32 reg, idle = 0, fifo_full = 1;
+	u8 mode, value;
+	int i;
+
+	reg = STV090x_READ_DEMOD(state, DISTXCTL);
+
+	if (burst == SEC_MINI_A) {
+		mode = (state->config->diseqc_envelope_mode) ? 5 : 3;
+		value = 0x00;
+	} else {
+		mode = (state->config->diseqc_envelope_mode) ? 4 : 2;
+		value = 0xFF;
+	}
+
+	STV090x_SETFIELD_Px(reg, DISTX_MODE_FIELD, mode);
+	STV090x_SETFIELD_Px(reg, DISEQC_RESET_FIELD, 1);
+	if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0)
+		goto err;
+	STV090x_SETFIELD_Px(reg, DISEQC_RESET_FIELD, 0);
+	if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0)
+		goto err;
+
+	STV090x_SETFIELD_Px(reg, DIS_PRECHARGE_FIELD, 1);
+	if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0)
+		goto err;
+
+	while (fifo_full) {
+		reg = STV090x_READ_DEMOD(state, DISTXSTATUS);
+		fifo_full = STV090x_GETFIELD_Px(reg, FIFO_FULL_FIELD);
+	}
+
+	if (STV090x_WRITE_DEMOD(state, DISTXDATA, value) < 0)
+		goto err;
+
+	reg = STV090x_READ_DEMOD(state, DISTXCTL);
+	STV090x_SETFIELD_Px(reg, DIS_PRECHARGE_FIELD, 0);
+	if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0)
+		goto err;
+
+	i = 0;
+
+	while ((!idle) && (i < 10)) {
+		reg = STV090x_READ_DEMOD(state, DISTXSTATUS);
+		idle = STV090x_GETFIELD_Px(reg, TX_IDLE_FIELD);
+		msleep(10);
+		i++;
+	}
+
+	return 0;
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static int stv090x_recv_slave_reply(struct dvb_frontend *fe, struct dvb_diseqc_slave_reply *reply)
+{
+	struct stv090x_state *state = fe->demodulator_priv;
+	u32 reg = 0, i = 0, rx_end = 0;
+
+	while ((rx_end != 1) && (i < 10)) {
+		msleep(10);
+		i++;
+		reg = STV090x_READ_DEMOD(state, DISRX_ST0);
+		rx_end = STV090x_GETFIELD_Px(reg, RX_END_FIELD);
+	}
+
+	if (rx_end) {
+		reply->msg_len = STV090x_GETFIELD_Px(reg, FIFO_BYTENBR_FIELD);
+		for (i = 0; i < reply->msg_len; i++)
+			reply->msg[i] = STV090x_READ_DEMOD(state, DISRXDATA);
+	}
+
+	return 0;
+}
+
+static int stv090x_sleep(struct dvb_frontend *fe)
+{
+	struct stv090x_state *state = fe->demodulator_priv;
+	u32 reg;
+	u8 full_standby = 0;
+
+	if (stv090x_i2c_gate_ctrl(state, 1) < 0)
+		goto err;
+
+	if (state->config->tuner_sleep) {
+		if (state->config->tuner_sleep(fe) < 0)
+			goto err_gateoff;
+	}
+
+	if (stv090x_i2c_gate_ctrl(state, 0) < 0)
+		goto err;
+
+	dprintk(FE_DEBUG, 1, "Set %s(%d) to sleep",
+		state->device == STV0900 ? "STV0900" : "STV0903",
+		state->demod);
+
+	mutex_lock(&state->internal->demod_lock);
+
+	switch (state->demod) {
+	case STV090x_DEMODULATOR_0:
+		/* power off ADC 1 */
+		reg = stv090x_read_reg(state, STV090x_TSTTNR1);
+		STV090x_SETFIELD(reg, ADC1_PON_FIELD, 0);
+		if (stv090x_write_reg(state, STV090x_TSTTNR1, reg) < 0)
+			goto err;
+		/* power off DiSEqC 1 */
+		reg = stv090x_read_reg(state, STV090x_TSTTNR2);
+		STV090x_SETFIELD(reg, DISEQC1_PON_FIELD, 0);
+		if (stv090x_write_reg(state, STV090x_TSTTNR2, reg) < 0)
+			goto err;
+
+		/* check whether path 2 is already sleeping, that is when
+		   ADC2 is off */
+		reg = stv090x_read_reg(state, STV090x_TSTTNR3);
+		if (STV090x_GETFIELD(reg, ADC2_PON_FIELD) == 0)
+			full_standby = 1;
+
+		/* stop clocks */
+		reg = stv090x_read_reg(state, STV090x_STOPCLK1);
+		/* packet delineator 1 clock */
+		STV090x_SETFIELD(reg, STOP_CLKPKDT1_FIELD, 1);
+		/* ADC 1 clock */
+		STV090x_SETFIELD(reg, STOP_CLKADCI1_FIELD, 1);
+		/* FEC clock is shared between the two paths, only stop it
+		   when full standby is possible */
+		if (full_standby)
+			STV090x_SETFIELD(reg, STOP_CLKFEC_FIELD, 1);
+		if (stv090x_write_reg(state, STV090x_STOPCLK1, reg) < 0)
+			goto err;
+		reg = stv090x_read_reg(state, STV090x_STOPCLK2);
+		/* sampling 1 clock */
+		STV090x_SETFIELD(reg, STOP_CLKSAMP1_FIELD, 1);
+		/* viterbi 1 clock */
+		STV090x_SETFIELD(reg, STOP_CLKVIT1_FIELD, 1);
+		/* TS clock is shared between the two paths, only stop it
+		   when full standby is possible */
+		if (full_standby)
+			STV090x_SETFIELD(reg, STOP_CLKTS_FIELD, 1);
+		if (stv090x_write_reg(state, STV090x_STOPCLK2, reg) < 0)
+			goto err;
+		break;
+
+	case STV090x_DEMODULATOR_1:
+		/* power off ADC 2 */
+		reg = stv090x_read_reg(state, STV090x_TSTTNR3);
+		STV090x_SETFIELD(reg, ADC2_PON_FIELD, 0);
+		if (stv090x_write_reg(state, STV090x_TSTTNR3, reg) < 0)
+			goto err;
+		/* power off DiSEqC 2 */
+		reg = stv090x_read_reg(state, STV090x_TSTTNR4);
+		STV090x_SETFIELD(reg, DISEQC2_PON_FIELD, 0);
+		if (stv090x_write_reg(state, STV090x_TSTTNR4, reg) < 0)
+			goto err;
+
+		/* check whether path 1 is already sleeping, that is when
+		   ADC1 is off */
+		reg = stv090x_read_reg(state, STV090x_TSTTNR1);
+		if (STV090x_GETFIELD(reg, ADC1_PON_FIELD) == 0)
+			full_standby = 1;
+
+		/* stop clocks */
+		reg = stv090x_read_reg(state, STV090x_STOPCLK1);
+		/* packet delineator 2 clock */
+		STV090x_SETFIELD(reg, STOP_CLKPKDT2_FIELD, 1);
+		/* ADC 2 clock */
+		STV090x_SETFIELD(reg, STOP_CLKADCI2_FIELD, 1);
+		/* FEC clock is shared between the two paths, only stop it
+		   when full standby is possible */
+		if (full_standby)
+			STV090x_SETFIELD(reg, STOP_CLKFEC_FIELD, 1);
+		if (stv090x_write_reg(state, STV090x_STOPCLK1, reg) < 0)
+			goto err;
+		reg = stv090x_read_reg(state, STV090x_STOPCLK2);
+		/* sampling 2 clock */
+		STV090x_SETFIELD(reg, STOP_CLKSAMP2_FIELD, 1);
+		/* viterbi 2 clock */
+		STV090x_SETFIELD(reg, STOP_CLKVIT2_FIELD, 1);
+		/* TS clock is shared between the two paths, only stop it
+		   when full standby is possible */
+		if (full_standby)
+			STV090x_SETFIELD(reg, STOP_CLKTS_FIELD, 1);
+		if (stv090x_write_reg(state, STV090x_STOPCLK2, reg) < 0)
+			goto err;
+		break;
+
+	default:
+		dprintk(FE_ERROR, 1, "Wrong demodulator!");
+		break;
+	}
+
+	if (full_standby) {
+		/* general power off */
+		reg = stv090x_read_reg(state, STV090x_SYNTCTRL);
+		STV090x_SETFIELD(reg, STANDBY_FIELD, 0x01);
+		if (stv090x_write_reg(state, STV090x_SYNTCTRL, reg) < 0)
+			goto err;
+	}
+
+	mutex_unlock(&state->internal->demod_lock);
+	return 0;
+
+err_gateoff:
+	stv090x_i2c_gate_ctrl(state, 0);
+err:
+	mutex_unlock(&state->internal->demod_lock);
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static int stv090x_wakeup(struct dvb_frontend *fe)
+{
+	struct stv090x_state *state = fe->demodulator_priv;
+	u32 reg;
+
+	dprintk(FE_DEBUG, 1, "Wake %s(%d) from standby",
+		state->device == STV0900 ? "STV0900" : "STV0903",
+		state->demod);
+
+	mutex_lock(&state->internal->demod_lock);
+
+	/* general power on */
+	reg = stv090x_read_reg(state, STV090x_SYNTCTRL);
+	STV090x_SETFIELD(reg, STANDBY_FIELD, 0x00);
+	if (stv090x_write_reg(state, STV090x_SYNTCTRL, reg) < 0)
+		goto err;
+
+	switch (state->demod) {
+	case STV090x_DEMODULATOR_0:
+		/* power on ADC 1 */
+		reg = stv090x_read_reg(state, STV090x_TSTTNR1);
+		STV090x_SETFIELD(reg, ADC1_PON_FIELD, 1);
+		if (stv090x_write_reg(state, STV090x_TSTTNR1, reg) < 0)
+			goto err;
+		/* power on DiSEqC 1 */
+		reg = stv090x_read_reg(state, STV090x_TSTTNR2);
+		STV090x_SETFIELD(reg, DISEQC1_PON_FIELD, 1);
+		if (stv090x_write_reg(state, STV090x_TSTTNR2, reg) < 0)
+			goto err;
+
+		/* activate clocks */
+		reg = stv090x_read_reg(state, STV090x_STOPCLK1);
+		/* packet delineator 1 clock */
+		STV090x_SETFIELD(reg, STOP_CLKPKDT1_FIELD, 0);
+		/* ADC 1 clock */
+		STV090x_SETFIELD(reg, STOP_CLKADCI1_FIELD, 0);
+		/* FEC clock */
+		STV090x_SETFIELD(reg, STOP_CLKFEC_FIELD, 0);
+		if (stv090x_write_reg(state, STV090x_STOPCLK1, reg) < 0)
+			goto err;
+		reg = stv090x_read_reg(state, STV090x_STOPCLK2);
+		/* sampling 1 clock */
+		STV090x_SETFIELD(reg, STOP_CLKSAMP1_FIELD, 0);
+		/* viterbi 1 clock */
+		STV090x_SETFIELD(reg, STOP_CLKVIT1_FIELD, 0);
+		/* TS clock */
+		STV090x_SETFIELD(reg, STOP_CLKTS_FIELD, 0);
+		if (stv090x_write_reg(state, STV090x_STOPCLK2, reg) < 0)
+			goto err;
+		break;
+
+	case STV090x_DEMODULATOR_1:
+		/* power on ADC 2 */
+		reg = stv090x_read_reg(state, STV090x_TSTTNR3);
+		STV090x_SETFIELD(reg, ADC2_PON_FIELD, 1);
+		if (stv090x_write_reg(state, STV090x_TSTTNR3, reg) < 0)
+			goto err;
+		/* power on DiSEqC 2 */
+		reg = stv090x_read_reg(state, STV090x_TSTTNR4);
+		STV090x_SETFIELD(reg, DISEQC2_PON_FIELD, 1);
+		if (stv090x_write_reg(state, STV090x_TSTTNR4, reg) < 0)
+			goto err;
+
+		/* activate clocks */
+		reg = stv090x_read_reg(state, STV090x_STOPCLK1);
+		/* packet delineator 2 clock */
+		STV090x_SETFIELD(reg, STOP_CLKPKDT2_FIELD, 0);
+		/* ADC 2 clock */
+		STV090x_SETFIELD(reg, STOP_CLKADCI2_FIELD, 0);
+		/* FEC clock */
+		STV090x_SETFIELD(reg, STOP_CLKFEC_FIELD, 0);
+		if (stv090x_write_reg(state, STV090x_STOPCLK1, reg) < 0)
+			goto err;
+		reg = stv090x_read_reg(state, STV090x_STOPCLK2);
+		/* sampling 2 clock */
+		STV090x_SETFIELD(reg, STOP_CLKSAMP2_FIELD, 0);
+		/* viterbi 2 clock */
+		STV090x_SETFIELD(reg, STOP_CLKVIT2_FIELD, 0);
+		/* TS clock */
+		STV090x_SETFIELD(reg, STOP_CLKTS_FIELD, 0);
+		if (stv090x_write_reg(state, STV090x_STOPCLK2, reg) < 0)
+			goto err;
+		break;
+
+	default:
+		dprintk(FE_ERROR, 1, "Wrong demodulator!");
+		break;
+	}
+
+	mutex_unlock(&state->internal->demod_lock);
+	return 0;
+err:
+	mutex_unlock(&state->internal->demod_lock);
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static void stv090x_release(struct dvb_frontend *fe)
+{
+	struct stv090x_state *state = fe->demodulator_priv;
+
+	state->internal->num_used--;
+	if (state->internal->num_used <= 0) {
+
+		dprintk(FE_ERROR, 1, "Actually removing");
+
+		remove_dev(state->internal);
+		kfree(state->internal);
+	}
+
+	kfree(state);
+}
+
+static int stv090x_ldpc_mode(struct stv090x_state *state, enum stv090x_mode ldpc_mode)
+{
+	u32 reg = 0;
+
+	reg = stv090x_read_reg(state, STV090x_GENCFG);
+
+	switch (ldpc_mode) {
+	case STV090x_DUAL:
+	default:
+		if ((state->demod_mode != STV090x_DUAL) || (STV090x_GETFIELD(reg, DDEMOD_FIELD) != 1)) {
+			/* set LDPC to dual mode */
+			if (stv090x_write_reg(state, STV090x_GENCFG, 0x1d) < 0)
+				goto err;
+
+			state->demod_mode = STV090x_DUAL;
+
+			reg = stv090x_read_reg(state, STV090x_TSTRES0);
+			STV090x_SETFIELD(reg, FRESFEC_FIELD, 0x1);
+			if (stv090x_write_reg(state, STV090x_TSTRES0, reg) < 0)
+				goto err;
+			STV090x_SETFIELD(reg, FRESFEC_FIELD, 0x0);
+			if (stv090x_write_reg(state, STV090x_TSTRES0, reg) < 0)
+				goto err;
+
+			if (STV090x_WRITE_DEMOD(state, MODCODLST0, 0xff) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, MODCODLST1, 0xff) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, MODCODLST2, 0xff) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, MODCODLST3, 0xff) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, MODCODLST4, 0xff) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, MODCODLST5, 0xff) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, MODCODLST6, 0xff) < 0)
+				goto err;
+
+			if (STV090x_WRITE_DEMOD(state, MODCODLST7, 0xcc) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, MODCODLST8, 0xcc) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, MODCODLST9, 0xcc) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, MODCODLSTA, 0xcc) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, MODCODLSTB, 0xcc) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, MODCODLSTC, 0xcc) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, MODCODLSTD, 0xcc) < 0)
+				goto err;
+
+			if (STV090x_WRITE_DEMOD(state, MODCODLSTE, 0xff) < 0)
+				goto err;
+			if (STV090x_WRITE_DEMOD(state, MODCODLSTF, 0xcf) < 0)
+				goto err;
+		}
+		break;
+
+	case STV090x_SINGLE:
+		if (stv090x_stop_modcod(state) < 0)
+			goto err;
+		if (stv090x_activate_modcod_single(state) < 0)
+			goto err;
+
+		if (state->demod == STV090x_DEMODULATOR_1) {
+			if (stv090x_write_reg(state, STV090x_GENCFG, 0x06) < 0) /* path 2 */
+				goto err;
+		} else {
+			if (stv090x_write_reg(state, STV090x_GENCFG, 0x04) < 0) /* path 1 */
+				goto err;
+		}
+
+		reg = stv090x_read_reg(state, STV090x_TSTRES0);
+		STV090x_SETFIELD(reg, FRESFEC_FIELD, 0x1);
+		if (stv090x_write_reg(state, STV090x_TSTRES0, reg) < 0)
+			goto err;
+		STV090x_SETFIELD(reg, FRESFEC_FIELD, 0x0);
+		if (stv090x_write_reg(state, STV090x_TSTRES0, reg) < 0)
+			goto err;
+
+		reg = STV090x_READ_DEMOD(state, PDELCTRL1);
+		STV090x_SETFIELD_Px(reg, ALGOSWRST_FIELD, 0x01);
+		if (STV090x_WRITE_DEMOD(state, PDELCTRL1, reg) < 0)
+			goto err;
+		STV090x_SETFIELD_Px(reg, ALGOSWRST_FIELD, 0x00);
+		if (STV090x_WRITE_DEMOD(state, PDELCTRL1, reg) < 0)
+			goto err;
+		break;
+	}
+
+	return 0;
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+/* return (Hz), clk in Hz*/
+static u32 stv090x_get_mclk(struct stv090x_state *state)
+{
+	const struct stv090x_config *config = state->config;
+	u32 div, reg;
+	u8 ratio;
+
+	div = stv090x_read_reg(state, STV090x_NCOARSE);
+	reg = stv090x_read_reg(state, STV090x_SYNTCTRL);
+	ratio = STV090x_GETFIELD(reg, SELX1RATIO_FIELD) ? 4 : 6;
+
+	return (div + 1) * config->xtal / ratio; /* kHz */
+}
+
+static int stv090x_set_mclk(struct stv090x_state *state, u32 mclk, u32 clk)
+{
+	const struct stv090x_config *config = state->config;
+	u32 reg, div, clk_sel;
+
+	reg = stv090x_read_reg(state, STV090x_SYNTCTRL);
+	clk_sel = ((STV090x_GETFIELD(reg, SELX1RATIO_FIELD) == 1) ? 4 : 6);
+
+	div = ((clk_sel * mclk) / config->xtal) - 1;
+
+	reg = stv090x_read_reg(state, STV090x_NCOARSE);
+	STV090x_SETFIELD(reg, M_DIV_FIELD, div);
+	if (stv090x_write_reg(state, STV090x_NCOARSE, reg) < 0)
+		goto err;
+
+	state->internal->mclk = stv090x_get_mclk(state);
+
+	/*Set the DiseqC frequency to 22KHz */
+	div = state->internal->mclk / 704000;
+	if (STV090x_WRITE_DEMOD(state, F22TX, div) < 0)
+		goto err;
+	if (STV090x_WRITE_DEMOD(state, F22RX, div) < 0)
+		goto err;
+
+	return 0;
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static int stv090x_set_tspath(struct stv090x_state *state)
+{
+	u32 reg;
+
+	if (state->internal->dev_ver >= 0x20) {
+		switch (state->config->ts1_mode) {
+		case STV090x_TSMODE_PARALLEL_PUNCTURED:
+		case STV090x_TSMODE_DVBCI:
+			switch (state->config->ts2_mode) {
+			case STV090x_TSMODE_SERIAL_PUNCTURED:
+			case STV090x_TSMODE_SERIAL_CONTINUOUS:
+			default:
+				stv090x_write_reg(state, STV090x_TSGENERAL, 0x00);
+				break;
+
+			case STV090x_TSMODE_PARALLEL_PUNCTURED:
+			case STV090x_TSMODE_DVBCI:
+				if (stv090x_write_reg(state, STV090x_TSGENERAL, 0x06) < 0) /* Mux'd stream mode */
+					goto err;
+				reg = stv090x_read_reg(state, STV090x_P1_TSCFGM);
+				STV090x_SETFIELD_Px(reg, TSFIFO_MANSPEED_FIELD, 3);
+				if (stv090x_write_reg(state, STV090x_P1_TSCFGM, reg) < 0)
+					goto err;
+				reg = stv090x_read_reg(state, STV090x_P2_TSCFGM);
+				STV090x_SETFIELD_Px(reg, TSFIFO_MANSPEED_FIELD, 3);
+				if (stv090x_write_reg(state, STV090x_P2_TSCFGM, reg) < 0)
+					goto err;
+				if (stv090x_write_reg(state, STV090x_P1_TSSPEED, 0x14) < 0)
+					goto err;
+				if (stv090x_write_reg(state, STV090x_P2_TSSPEED, 0x28) < 0)
+					goto err;
+				break;
+			}
+			break;
+
+		case STV090x_TSMODE_SERIAL_PUNCTURED:
+		case STV090x_TSMODE_SERIAL_CONTINUOUS:
+		default:
+			switch (state->config->ts2_mode) {
+			case STV090x_TSMODE_SERIAL_PUNCTURED:
+			case STV090x_TSMODE_SERIAL_CONTINUOUS:
+			default:
+				if (stv090x_write_reg(state, STV090x_TSGENERAL, 0x0c) < 0)
+					goto err;
+				break;
+
+			case STV090x_TSMODE_PARALLEL_PUNCTURED:
+			case STV090x_TSMODE_DVBCI:
+				if (stv090x_write_reg(state, STV090x_TSGENERAL, 0x0a) < 0)
+					goto err;
+				break;
+			}
+			break;
+		}
+	} else {
+		switch (state->config->ts1_mode) {
+		case STV090x_TSMODE_PARALLEL_PUNCTURED:
+		case STV090x_TSMODE_DVBCI:
+			switch (state->config->ts2_mode) {
+			case STV090x_TSMODE_SERIAL_PUNCTURED:
+			case STV090x_TSMODE_SERIAL_CONTINUOUS:
+			default:
+				stv090x_write_reg(state, STV090x_TSGENERAL1X, 0x10);
+				break;
+
+			case STV090x_TSMODE_PARALLEL_PUNCTURED:
+			case STV090x_TSMODE_DVBCI:
+				stv090x_write_reg(state, STV090x_TSGENERAL1X, 0x16);
+				reg = stv090x_read_reg(state, STV090x_P1_TSCFGM);
+				STV090x_SETFIELD_Px(reg, TSFIFO_MANSPEED_FIELD, 3);
+				if (stv090x_write_reg(state, STV090x_P1_TSCFGM, reg) < 0)
+					goto err;
+				reg = stv090x_read_reg(state, STV090x_P1_TSCFGM);
+				STV090x_SETFIELD_Px(reg, TSFIFO_MANSPEED_FIELD, 0);
+				if (stv090x_write_reg(state, STV090x_P1_TSCFGM, reg) < 0)
+					goto err;
+				if (stv090x_write_reg(state, STV090x_P1_TSSPEED, 0x14) < 0)
+					goto err;
+				if (stv090x_write_reg(state, STV090x_P2_TSSPEED, 0x28) < 0)
+					goto err;
+				break;
+			}
+			break;
+
+		case STV090x_TSMODE_SERIAL_PUNCTURED:
+		case STV090x_TSMODE_SERIAL_CONTINUOUS:
+		default:
+			switch (state->config->ts2_mode) {
+			case STV090x_TSMODE_SERIAL_PUNCTURED:
+			case STV090x_TSMODE_SERIAL_CONTINUOUS:
+			default:
+				stv090x_write_reg(state, STV090x_TSGENERAL1X, 0x14);
+				break;
+
+			case STV090x_TSMODE_PARALLEL_PUNCTURED:
+			case STV090x_TSMODE_DVBCI:
+				stv090x_write_reg(state, STV090x_TSGENERAL1X, 0x12);
+				break;
+			}
+			break;
+		}
+	}
+
+	switch (state->config->ts1_mode) {
+	case STV090x_TSMODE_PARALLEL_PUNCTURED:
+		reg = stv090x_read_reg(state, STV090x_P1_TSCFGH);
+		STV090x_SETFIELD_Px(reg, TSFIFO_TEIUPDATE_FIELD, state->config->ts1_tei);
+		STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x00);
+		STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x00);
+		if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0)
+			goto err;
+		break;
+
+	case STV090x_TSMODE_DVBCI:
+		reg = stv090x_read_reg(state, STV090x_P1_TSCFGH);
+		STV090x_SETFIELD_Px(reg, TSFIFO_TEIUPDATE_FIELD, state->config->ts1_tei);
+		STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x00);
+		STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x01);
+		if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0)
+			goto err;
+		break;
+
+	case STV090x_TSMODE_SERIAL_PUNCTURED:
+		reg = stv090x_read_reg(state, STV090x_P1_TSCFGH);
+		STV090x_SETFIELD_Px(reg, TSFIFO_TEIUPDATE_FIELD, state->config->ts1_tei);
+		STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x01);
+		STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x00);
+		if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0)
+			goto err;
+		break;
+
+	case STV090x_TSMODE_SERIAL_CONTINUOUS:
+		reg = stv090x_read_reg(state, STV090x_P1_TSCFGH);
+		STV090x_SETFIELD_Px(reg, TSFIFO_TEIUPDATE_FIELD, state->config->ts1_tei);
+		STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x01);
+		STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x01);
+		if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0)
+			goto err;
+		break;
+
+	default:
+		break;
+	}
+
+	switch (state->config->ts2_mode) {
+	case STV090x_TSMODE_PARALLEL_PUNCTURED:
+		reg = stv090x_read_reg(state, STV090x_P2_TSCFGH);
+		STV090x_SETFIELD_Px(reg, TSFIFO_TEIUPDATE_FIELD, state->config->ts2_tei);
+		STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x00);
+		STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x00);
+		if (stv090x_write_reg(state, STV090x_P2_TSCFGH, reg) < 0)
+			goto err;
+		break;
+
+	case STV090x_TSMODE_DVBCI:
+		reg = stv090x_read_reg(state, STV090x_P2_TSCFGH);
+		STV090x_SETFIELD_Px(reg, TSFIFO_TEIUPDATE_FIELD, state->config->ts2_tei);
+		STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x00);
+		STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x01);
+		if (stv090x_write_reg(state, STV090x_P2_TSCFGH, reg) < 0)
+			goto err;
+		break;
+
+	case STV090x_TSMODE_SERIAL_PUNCTURED:
+		reg = stv090x_read_reg(state, STV090x_P2_TSCFGH);
+		STV090x_SETFIELD_Px(reg, TSFIFO_TEIUPDATE_FIELD, state->config->ts2_tei);
+		STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x01);
+		STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x00);
+		if (stv090x_write_reg(state, STV090x_P2_TSCFGH, reg) < 0)
+			goto err;
+		break;
+
+	case STV090x_TSMODE_SERIAL_CONTINUOUS:
+		reg = stv090x_read_reg(state, STV090x_P2_TSCFGH);
+		STV090x_SETFIELD_Px(reg, TSFIFO_TEIUPDATE_FIELD, state->config->ts2_tei);
+		STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x01);
+		STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x01);
+		if (stv090x_write_reg(state, STV090x_P2_TSCFGH, reg) < 0)
+			goto err;
+		break;
+
+	default:
+		break;
+	}
+
+	if (state->config->ts1_clk > 0) {
+		u32 speed;
+
+		switch (state->config->ts1_mode) {
+		case STV090x_TSMODE_PARALLEL_PUNCTURED:
+		case STV090x_TSMODE_DVBCI:
+		default:
+			speed = state->internal->mclk /
+				(state->config->ts1_clk / 4);
+			if (speed < 0x08)
+				speed = 0x08;
+			if (speed > 0xFF)
+				speed = 0xFF;
+			break;
+		case STV090x_TSMODE_SERIAL_PUNCTURED:
+		case STV090x_TSMODE_SERIAL_CONTINUOUS:
+			speed = state->internal->mclk /
+				(state->config->ts1_clk / 32);
+			if (speed < 0x20)
+				speed = 0x20;
+			if (speed > 0xFF)
+				speed = 0xFF;
+			break;
+		}
+		reg = stv090x_read_reg(state, STV090x_P1_TSCFGM);
+		STV090x_SETFIELD_Px(reg, TSFIFO_MANSPEED_FIELD, 3);
+		if (stv090x_write_reg(state, STV090x_P1_TSCFGM, reg) < 0)
+			goto err;
+		if (stv090x_write_reg(state, STV090x_P1_TSSPEED, speed) < 0)
+			goto err;
+	}
+
+	if (state->config->ts2_clk > 0) {
+		u32 speed;
+
+		switch (state->config->ts2_mode) {
+		case STV090x_TSMODE_PARALLEL_PUNCTURED:
+		case STV090x_TSMODE_DVBCI:
+		default:
+			speed = state->internal->mclk /
+				(state->config->ts2_clk / 4);
+			if (speed < 0x08)
+				speed = 0x08;
+			if (speed > 0xFF)
+				speed = 0xFF;
+			break;
+		case STV090x_TSMODE_SERIAL_PUNCTURED:
+		case STV090x_TSMODE_SERIAL_CONTINUOUS:
+			speed = state->internal->mclk /
+				(state->config->ts2_clk / 32);
+			if (speed < 0x20)
+				speed = 0x20;
+			if (speed > 0xFF)
+				speed = 0xFF;
+			break;
+		}
+		reg = stv090x_read_reg(state, STV090x_P2_TSCFGM);
+		STV090x_SETFIELD_Px(reg, TSFIFO_MANSPEED_FIELD, 3);
+		if (stv090x_write_reg(state, STV090x_P2_TSCFGM, reg) < 0)
+			goto err;
+		if (stv090x_write_reg(state, STV090x_P2_TSSPEED, speed) < 0)
+			goto err;
+	}
+
+	reg = stv090x_read_reg(state, STV090x_P2_TSCFGH);
+	STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0x01);
+	if (stv090x_write_reg(state, STV090x_P2_TSCFGH, reg) < 0)
+		goto err;
+	STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0x00);
+	if (stv090x_write_reg(state, STV090x_P2_TSCFGH, reg) < 0)
+		goto err;
+
+	reg = stv090x_read_reg(state, STV090x_P1_TSCFGH);
+	STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0x01);
+	if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0)
+		goto err;
+	STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0x00);
+	if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0)
+		goto err;
+
+	return 0;
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static int stv090x_init(struct dvb_frontend *fe)
+{
+	struct stv090x_state *state = fe->demodulator_priv;
+	const struct stv090x_config *config = state->config;
+	u32 reg;
+
+	if (state->internal->mclk == 0) {
+		/* call tuner init to configure the tuner's clock output
+		   divider directly before setting up the master clock of
+		   the stv090x. */
+		if (stv090x_i2c_gate_ctrl(state, 1) < 0)
+			goto err;
+
+		if (config->tuner_init) {
+			if (config->tuner_init(fe) < 0)
+				goto err_gateoff;
+		}
+
+		if (stv090x_i2c_gate_ctrl(state, 0) < 0)
+			goto err;
+
+		stv090x_set_mclk(state, 135000000, config->xtal); /* 135 Mhz */
+		msleep(5);
+		if (stv090x_write_reg(state, STV090x_SYNTCTRL,
+				      0x20 | config->clk_mode) < 0)
+			goto err;
+		stv090x_get_mclk(state);
+	}
+
+	if (stv090x_wakeup(fe) < 0) {
+		dprintk(FE_ERROR, 1, "Error waking device");
+		goto err;
+	}
+
+	if (stv090x_ldpc_mode(state, state->demod_mode) < 0)
+		goto err;
+
+	reg = STV090x_READ_DEMOD(state, TNRCFG2);
+	STV090x_SETFIELD_Px(reg, TUN_IQSWAP_FIELD, state->inversion);
+	if (STV090x_WRITE_DEMOD(state, TNRCFG2, reg) < 0)
+		goto err;
+	reg = STV090x_READ_DEMOD(state, DEMOD);
+	STV090x_SETFIELD_Px(reg, ROLLOFF_CONTROL_FIELD, state->rolloff);
+	if (STV090x_WRITE_DEMOD(state, DEMOD, reg) < 0)
+		goto err;
+
+	if (stv090x_i2c_gate_ctrl(state, 1) < 0)
+		goto err;
+
+	if (config->tuner_set_mode) {
+		if (config->tuner_set_mode(fe, TUNER_WAKE) < 0)
+			goto err_gateoff;
+	}
+
+	if (config->tuner_init) {
+		if (config->tuner_init(fe) < 0)
+			goto err_gateoff;
+	}
+
+	if (stv090x_i2c_gate_ctrl(state, 0) < 0)
+		goto err;
+
+	if (stv090x_set_tspath(state) < 0)
+		goto err;
+
+	return 0;
+
+err_gateoff:
+	stv090x_i2c_gate_ctrl(state, 0);
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+static int stv090x_setup(struct dvb_frontend *fe)
+{
+	struct stv090x_state *state = fe->demodulator_priv;
+	const struct stv090x_config *config = state->config;
+	const struct stv090x_reg *stv090x_initval = NULL;
+	const struct stv090x_reg *stv090x_cut20_val = NULL;
+	unsigned long t1_size = 0, t2_size = 0;
+	u32 reg = 0;
+
+	int i;
+
+	if (state->device == STV0900) {
+		dprintk(FE_DEBUG, 1, "Initializing STV0900");
+		stv090x_initval = stv0900_initval;
+		t1_size = ARRAY_SIZE(stv0900_initval);
+		stv090x_cut20_val = stv0900_cut20_val;
+		t2_size = ARRAY_SIZE(stv0900_cut20_val);
+	} else if (state->device == STV0903) {
+		dprintk(FE_DEBUG, 1, "Initializing STV0903");
+		stv090x_initval = stv0903_initval;
+		t1_size = ARRAY_SIZE(stv0903_initval);
+		stv090x_cut20_val = stv0903_cut20_val;
+		t2_size = ARRAY_SIZE(stv0903_cut20_val);
+	}
+
+	/* STV090x init */
+
+	/* Stop Demod */
+	if (stv090x_write_reg(state, STV090x_P1_DMDISTATE, 0x5c) < 0)
+		goto err;
+	if (stv090x_write_reg(state, STV090x_P2_DMDISTATE, 0x5c) < 0)
+		goto err;
+
+	msleep(5);
+
+	/* Set No Tuner Mode */
+	if (stv090x_write_reg(state, STV090x_P1_TNRCFG, 0x6c) < 0)
+		goto err;
+	if (stv090x_write_reg(state, STV090x_P2_TNRCFG, 0x6c) < 0)
+		goto err;
+
+	/* I2C repeater OFF */
+	STV090x_SETFIELD_Px(reg, ENARPT_LEVEL_FIELD, config->repeater_level);
+	if (stv090x_write_reg(state, STV090x_P1_I2CRPT, reg) < 0)
+		goto err;
+	if (stv090x_write_reg(state, STV090x_P2_I2CRPT, reg) < 0)
+		goto err;
+
+	if (stv090x_write_reg(state, STV090x_NCOARSE, 0x13) < 0) /* set PLL divider */
+		goto err;
+	msleep(5);
+	if (stv090x_write_reg(state, STV090x_I2CCFG, 0x08) < 0) /* 1/41 oversampling */
+		goto err;
+	if (stv090x_write_reg(state, STV090x_SYNTCTRL, 0x20 | config->clk_mode) < 0) /* enable PLL */
+		goto err;
+	msleep(5);
+
+	/* write initval */
+	dprintk(FE_DEBUG, 1, "Setting up initial values");
+	for (i = 0; i < t1_size; i++) {
+		if (stv090x_write_reg(state, stv090x_initval[i].addr, stv090x_initval[i].data) < 0)
+			goto err;
+	}
+
+	state->internal->dev_ver = stv090x_read_reg(state, STV090x_MID);
+	if (state->internal->dev_ver >= 0x20) {
+		if (stv090x_write_reg(state, STV090x_TSGENERAL, 0x0c) < 0)
+			goto err;
+
+		/* write cut20_val*/
+		dprintk(FE_DEBUG, 1, "Setting up Cut 2.0 initial values");
+		for (i = 0; i < t2_size; i++) {
+			if (stv090x_write_reg(state, stv090x_cut20_val[i].addr, stv090x_cut20_val[i].data) < 0)
+				goto err;
+		}
+
+	} else if (state->internal->dev_ver < 0x20) {
+		dprintk(FE_ERROR, 1, "ERROR: Unsupported Cut: 0x%02x!",
+			state->internal->dev_ver);
+
+		goto err;
+	} else if (state->internal->dev_ver > 0x30) {
+		/* we shouldn't bail out from here */
+		dprintk(FE_ERROR, 1, "INFO: Cut: 0x%02x probably incomplete support!",
+			state->internal->dev_ver);
+	}
+
+	/* ADC1 range */
+	reg = stv090x_read_reg(state, STV090x_TSTTNR1);
+	STV090x_SETFIELD(reg, ADC1_INMODE_FIELD,
+		(config->adc1_range == STV090x_ADC_1Vpp) ? 0 : 1);
+	if (stv090x_write_reg(state, STV090x_TSTTNR1, reg) < 0)
+		goto err;
+
+	/* ADC2 range */
+	reg = stv090x_read_reg(state, STV090x_TSTTNR3);
+	STV090x_SETFIELD(reg, ADC2_INMODE_FIELD,
+		(config->adc2_range == STV090x_ADC_1Vpp) ? 0 : 1);
+	if (stv090x_write_reg(state, STV090x_TSTTNR3, reg) < 0)
+		goto err;
+
+	if (stv090x_write_reg(state, STV090x_TSTRES0, 0x80) < 0)
+		goto err;
+	if (stv090x_write_reg(state, STV090x_TSTRES0, 0x00) < 0)
+		goto err;
+
+	return 0;
+err:
+	dprintk(FE_ERROR, 1, "I/O error");
+	return -1;
+}
+
+int stv090x_set_gpio(struct dvb_frontend *fe, u8 gpio, u8 dir, u8 value,
+		u8 xor_value)
+{
+	struct stv090x_state *state = fe->demodulator_priv;
+	u8 reg = 0;
+
+	STV090x_SETFIELD(reg, GPIOx_OPD_FIELD, dir);
+	STV090x_SETFIELD(reg, GPIOx_CONFIG_FIELD, value);
+	STV090x_SETFIELD(reg, GPIOx_XOR_FIELD, xor_value);
+
+	return stv090x_write_reg(state, STV090x_GPIOxCFG(gpio), reg);
+}
+EXPORT_SYMBOL(stv090x_set_gpio);
+
+static struct dvb_frontend_ops stv090x_ops = {
+	.delsys = { SYS_DVBS, SYS_DVBS2, SYS_DSS },
+	.info = {
+		.name			= "STV090x Multistandard",
+		.frequency_min		= 950000,
+		.frequency_max 		= 2150000,
+		.frequency_stepsize	= 0,
+		.frequency_tolerance	= 0,
+		.symbol_rate_min 	= 1000000,
+		.symbol_rate_max 	= 45000000,
+		.caps			= FE_CAN_INVERSION_AUTO |
+					  FE_CAN_FEC_AUTO       |
+					  FE_CAN_QPSK           |
+					  FE_CAN_2G_MODULATION
+	},
+
+	.release			= stv090x_release,
+	.init				= stv090x_init,
+
+	.sleep				= stv090x_sleep,
+	.get_frontend_algo		= stv090x_frontend_algo,
+
+	.diseqc_send_master_cmd		= stv090x_send_diseqc_msg,
+	.diseqc_send_burst		= stv090x_send_diseqc_burst,
+	.diseqc_recv_slave_reply	= stv090x_recv_slave_reply,
+	.set_tone			= stv090x_set_tone,
+
+	.search				= stv090x_search,
+	.read_status			= stv090x_read_status,
+	.read_ber			= stv090x_read_per,
+	.read_signal_strength		= stv090x_read_signal_strength,
+	.read_snr			= stv090x_read_cnr,
+};
+
+
+struct dvb_frontend *stv090x_attach(const struct stv090x_config *config,
+				    struct i2c_adapter *i2c,
+				    enum stv090x_demodulator demod)
+{
+	struct stv090x_state *state = NULL;
+	struct stv090x_dev *temp_int;
+
+	state = kzalloc(sizeof (struct stv090x_state), GFP_KERNEL);
+	if (state == NULL)
+		goto error;
+
+	state->verbose				= &verbose;
+	state->config				= config;
+	state->i2c				= i2c;
+	state->frontend.ops			= stv090x_ops;
+	state->frontend.demodulator_priv	= state;
+	state->demod				= demod;
+	state->demod_mode 			= config->demod_mode; /* Single or Dual mode */
+	state->device				= config->device;
+	state->rolloff				= STV090x_RO_35; /* default */
+
+	temp_int = find_dev(state->i2c,
+				state->config->address);
+
+	if ((temp_int != NULL) && (state->demod_mode == STV090x_DUAL)) {
+		state->internal = temp_int->internal;
+		state->internal->num_used++;
+		dprintk(FE_INFO, 1, "Found Internal Structure!");
+	} else {
+		state->internal = kmalloc(sizeof(struct stv090x_internal),
+					  GFP_KERNEL);
+		if (!state->internal)
+			goto error;
+		temp_int = append_internal(state->internal);
+		if (!temp_int) {
+			kfree(state->internal);
+			goto error;
+		}
+		state->internal->num_used = 1;
+		state->internal->mclk = 0;
+		state->internal->dev_ver = 0;
+		state->internal->i2c_adap = state->i2c;
+		state->internal->i2c_addr = state->config->address;
+		dprintk(FE_INFO, 1, "Create New Internal Structure!");
+
+		mutex_init(&state->internal->demod_lock);
+		mutex_init(&state->internal->tuner_lock);
+
+		if (stv090x_setup(&state->frontend) < 0) {
+			dprintk(FE_ERROR, 1, "Error setting up device");
+			goto err_remove;
+		}
+	}
+
+	if (state->internal->dev_ver >= 0x30)
+		state->frontend.ops.info.caps |= FE_CAN_MULTISTREAM;
+
+	/* workaround for stuck DiSEqC output */
+	if (config->diseqc_envelope_mode)
+		stv090x_send_diseqc_burst(&state->frontend, SEC_MINI_A);
+
+	dprintk(FE_ERROR, 1, "Attaching %s demodulator(%d) Cut=0x%02x",
+	       state->device == STV0900 ? "STV0900" : "STV0903",
+	       demod,
+	       state->internal->dev_ver);
+
+	return &state->frontend;
+
+err_remove:
+	remove_dev(state->internal);
+	kfree(state->internal);
+error:
+	kfree(state);
+	return NULL;
+}
+EXPORT_SYMBOL(stv090x_attach);
+MODULE_PARM_DESC(verbose, "Set Verbosity level");
+MODULE_AUTHOR("Manu Abraham");
+MODULE_DESCRIPTION("STV090x Multi-Std Broadcast frontend");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb-frontends/stv090x.h b/drivers/media/dvb-frontends/stv090x.h
new file mode 100644
index 0000000..29cdc2b
--- /dev/null
+++ b/drivers/media/dvb-frontends/stv090x.h
@@ -0,0 +1,134 @@
+/*
+	STV0900/0903 Multistandard Broadcast Frontend driver
+	Copyright (C) Manu Abraham <abraham.manu@gmail.com>
+
+	Copyright (C) ST Microelectronics
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the 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 __STV090x_H
+#define __STV090x_H
+
+enum stv090x_demodulator {
+	STV090x_DEMODULATOR_0 = 1,
+	STV090x_DEMODULATOR_1
+};
+
+enum stv090x_device {
+	STV0903	=  0,
+	STV0900,
+};
+
+enum stv090x_mode {
+	STV090x_DUAL = 0,
+	STV090x_SINGLE
+};
+
+enum stv090x_tsmode {
+	STV090x_TSMODE_SERIAL_PUNCTURED	= 1,
+	STV090x_TSMODE_SERIAL_CONTINUOUS,
+	STV090x_TSMODE_PARALLEL_PUNCTURED,
+	STV090x_TSMODE_DVBCI
+};
+
+enum stv090x_clkmode {
+	STV090x_CLK_INT = 0, /* Clk i/p = CLKI */
+	STV090x_CLK_EXT = 2 /* Clk i/p = XTALI */
+};
+
+enum stv090x_i2crpt {
+	STV090x_RPTLEVEL_256	= 0,
+	STV090x_RPTLEVEL_128	= 1,
+	STV090x_RPTLEVEL_64	= 2,
+	STV090x_RPTLEVEL_32	= 3,
+	STV090x_RPTLEVEL_16	= 4,
+	STV090x_RPTLEVEL_8	= 5,
+	STV090x_RPTLEVEL_4	= 6,
+	STV090x_RPTLEVEL_2	= 7,
+};
+
+enum stv090x_adc_range {
+	STV090x_ADC_2Vpp	= 0,
+	STV090x_ADC_1Vpp	= 1
+};
+
+struct stv090x_config {
+	enum stv090x_device	device;
+	enum stv090x_mode	demod_mode;
+	enum stv090x_clkmode	clk_mode;
+
+	u32 xtal; /* default: 8000000 */
+	u8 address; /* default: 0x68 */
+
+	u8 ts1_mode;
+	u8 ts2_mode;
+	u32 ts1_clk;
+	u32 ts2_clk;
+
+	u8 ts1_tei : 1;
+	u8 ts2_tei : 1;
+
+	enum stv090x_i2crpt	repeater_level;
+
+	u8			tuner_bbgain; /* default: 10db */
+	enum stv090x_adc_range	adc1_range; /* default: 2Vpp */
+	enum stv090x_adc_range	adc2_range; /* default: 2Vpp */
+
+	bool diseqc_envelope_mode;
+
+	int (*tuner_init) (struct dvb_frontend *fe);
+	int (*tuner_sleep) (struct dvb_frontend *fe);
+	int (*tuner_set_mode) (struct dvb_frontend *fe, enum tuner_mode mode);
+	int (*tuner_set_frequency) (struct dvb_frontend *fe, u32 frequency);
+	int (*tuner_get_frequency) (struct dvb_frontend *fe, u32 *frequency);
+	int (*tuner_set_bandwidth) (struct dvb_frontend *fe, u32 bandwidth);
+	int (*tuner_get_bandwidth) (struct dvb_frontend *fe, u32 *bandwidth);
+	int (*tuner_set_bbgain) (struct dvb_frontend *fe, u32 gain);
+	int (*tuner_get_bbgain) (struct dvb_frontend *fe, u32 *gain);
+	int (*tuner_set_refclk)  (struct dvb_frontend *fe, u32 refclk);
+	int (*tuner_get_status) (struct dvb_frontend *fe, u32 *status);
+	void (*tuner_i2c_lock) (struct dvb_frontend *fe, int lock);
+};
+
+#if defined(CONFIG_DVB_STV090x) || (defined(CONFIG_DVB_STV090x_MODULE) && defined(MODULE))
+
+extern struct dvb_frontend *stv090x_attach(const struct stv090x_config *config,
+					   struct i2c_adapter *i2c,
+					   enum stv090x_demodulator demod);
+
+/* dir = 0 -> output, dir = 1 -> input/open-drain */
+extern int stv090x_set_gpio(struct dvb_frontend *fe, u8 gpio,
+		u8 dir, u8 value, u8 xor_value);
+
+#else
+
+static inline struct dvb_frontend *stv090x_attach(const struct stv090x_config *config,
+						  struct i2c_adapter *i2c,
+						  enum stv090x_demodulator demod)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+
+static inline int stv090x_set_gpio(struct dvb_frontend *fe, u8 gpio,
+		u8 opd, u8 value, u8 xor_value)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return -ENODEV;
+}
+#endif /* CONFIG_DVB_STV090x */
+
+#endif /* __STV090x_H */
diff --git a/drivers/media/dvb-frontends/stv090x_priv.h b/drivers/media/dvb-frontends/stv090x_priv.h
new file mode 100644
index 0000000..5b780c8
--- /dev/null
+++ b/drivers/media/dvb-frontends/stv090x_priv.h
@@ -0,0 +1,279 @@
+/*
+	STV0900/0903 Multistandard Broadcast Frontend driver
+	Copyright (C) Manu Abraham <abraham.manu@gmail.com>
+
+	Copyright (C) ST Microelectronics
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the 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 __STV090x_PRIV_H
+#define __STV090x_PRIV_H
+
+#include "dvb_frontend.h"
+
+#define FE_ERROR				0
+#define FE_NOTICE				1
+#define FE_INFO					2
+#define FE_DEBUG				3
+#define FE_DEBUGREG				4
+
+#define dprintk(__y, __z, format, arg...) do {						\
+	if (__z) {									\
+		if	((verbose > FE_ERROR) && (verbose > __y))			\
+			printk(KERN_ERR "%s: " format "\n", __func__ , ##arg);		\
+		else if	((verbose > FE_NOTICE) && (verbose > __y))			\
+			printk(KERN_NOTICE "%s: " format "\n", __func__ , ##arg);	\
+		else if ((verbose > FE_INFO) && (verbose > __y))			\
+			printk(KERN_INFO "%s: " format "\n", __func__ , ##arg);		\
+		else if ((verbose > FE_DEBUG) && (verbose > __y))			\
+			printk(KERN_DEBUG "%s: " format "\n", __func__ , ##arg);	\
+	} else {									\
+		if (verbose > __y)							\
+			printk(format, ##arg);						\
+	}										\
+} while (0)
+
+#define STV090x_READ_DEMOD(__state, __reg) ((			\
+	(__state)->demod == STV090x_DEMODULATOR_1)	?	\
+	stv090x_read_reg(__state, STV090x_P2_##__reg) :		\
+	stv090x_read_reg(__state, STV090x_P1_##__reg))
+
+#define STV090x_WRITE_DEMOD(__state, __reg, __data) ((		\
+	(__state)->demod == STV090x_DEMODULATOR_1)	?	\
+	stv090x_write_reg(__state, STV090x_P2_##__reg, __data) :\
+	stv090x_write_reg(__state, STV090x_P1_##__reg, __data))
+
+#define STV090x_ADDR_OFFST(__state, __x) ((			\
+	(__state->demod) == STV090x_DEMODULATOR_1)	?	\
+		STV090x_P1_##__x :				\
+		STV090x_P2_##__x)
+
+
+#define STV090x_SETFIELD(mask, bitf, val)	(mask = (mask & (~(((1 << STV090x_WIDTH_##bitf) - 1) <<\
+							 STV090x_OFFST_##bitf))) | \
+							 (val << STV090x_OFFST_##bitf))
+
+#define STV090x_GETFIELD(val, bitf)		((val >> STV090x_OFFST_##bitf) & ((1 << STV090x_WIDTH_##bitf) - 1))
+
+
+#define STV090x_SETFIELD_Px(mask, bitf, val)	(mask = (mask & (~(((1 << STV090x_WIDTH_Px_##bitf) - 1) <<\
+							 STV090x_OFFST_Px_##bitf))) | \
+							 (val << STV090x_OFFST_Px_##bitf))
+
+#define STV090x_GETFIELD_Px(val, bitf)		((val >> STV090x_OFFST_Px_##bitf) & ((1 << STV090x_WIDTH_Px_##bitf) - 1))
+
+#define MAKEWORD16(__a, __b)			(((__a) << 8) | (__b))
+
+#define MSB(__x)				((__x >> 8) & 0xff)
+#define LSB(__x)				(__x & 0xff)
+
+
+#define STV090x_IQPOWER_THRESHOLD	  30
+#define STV090x_SEARCH_AGC2_TH_CUT20	 700
+#define STV090x_SEARCH_AGC2_TH_CUT30	1400
+
+#define STV090x_SEARCH_AGC2_TH(__ver)	\
+	((__ver <= 0x20) ?		\
+	STV090x_SEARCH_AGC2_TH_CUT20 :	\
+	STV090x_SEARCH_AGC2_TH_CUT30)
+
+enum stv090x_signal_state {
+	STV090x_NOAGC1,
+	STV090x_NOCARRIER,
+	STV090x_NODATA,
+	STV090x_DATAOK,
+	STV090x_RANGEOK,
+	STV090x_OUTOFRANGE
+};
+
+enum stv090x_fec {
+	STV090x_PR12 = 0,
+	STV090x_PR23,
+	STV090x_PR34,
+	STV090x_PR45,
+	STV090x_PR56,
+	STV090x_PR67,
+	STV090x_PR78,
+	STV090x_PR89,
+	STV090x_PR910,
+	STV090x_PRERR
+};
+
+enum stv090x_modulation {
+	STV090x_QPSK,
+	STV090x_8PSK,
+	STV090x_16APSK,
+	STV090x_32APSK,
+	STV090x_UNKNOWN
+};
+
+enum stv090x_frame {
+	STV090x_LONG_FRAME,
+	STV090x_SHORT_FRAME
+};
+
+enum stv090x_pilot {
+	STV090x_PILOTS_OFF,
+	STV090x_PILOTS_ON
+};
+
+enum stv090x_rolloff {
+	STV090x_RO_35,
+	STV090x_RO_25,
+	STV090x_RO_20
+};
+
+enum stv090x_inversion {
+	STV090x_IQ_AUTO,
+	STV090x_IQ_NORMAL,
+	STV090x_IQ_SWAP
+};
+
+enum stv090x_modcod {
+	STV090x_DUMMY_PLF = 0,
+	STV090x_QPSK_14,
+	STV090x_QPSK_13,
+	STV090x_QPSK_25,
+	STV090x_QPSK_12,
+	STV090x_QPSK_35,
+	STV090x_QPSK_23,
+	STV090x_QPSK_34,
+	STV090x_QPSK_45,
+	STV090x_QPSK_56,
+	STV090x_QPSK_89,
+	STV090x_QPSK_910,
+	STV090x_8PSK_35,
+	STV090x_8PSK_23,
+	STV090x_8PSK_34,
+	STV090x_8PSK_56,
+	STV090x_8PSK_89,
+	STV090x_8PSK_910,
+	STV090x_16APSK_23,
+	STV090x_16APSK_34,
+	STV090x_16APSK_45,
+	STV090x_16APSK_56,
+	STV090x_16APSK_89,
+	STV090x_16APSK_910,
+	STV090x_32APSK_34,
+	STV090x_32APSK_45,
+	STV090x_32APSK_56,
+	STV090x_32APSK_89,
+	STV090x_32APSK_910,
+	STV090x_MODCODE_UNKNOWN
+};
+
+enum stv090x_search {
+	STV090x_SEARCH_DSS = 0,
+	STV090x_SEARCH_DVBS1,
+	STV090x_SEARCH_DVBS2,
+	STV090x_SEARCH_AUTO
+};
+
+enum stv090x_algo {
+	STV090x_BLIND_SEARCH,
+	STV090x_COLD_SEARCH,
+	STV090x_WARM_SEARCH
+};
+
+enum stv090x_delsys {
+	STV090x_ERROR = 0,
+	STV090x_DVBS1 = 1,
+	STV090x_DVBS2,
+	STV090x_DSS
+};
+
+struct stv090x_long_frame_crloop {
+	enum stv090x_modcod	modcod;
+
+	u8 crl_pilots_on_2;
+	u8 crl_pilots_off_2;
+	u8 crl_pilots_on_5;
+	u8 crl_pilots_off_5;
+	u8 crl_pilots_on_10;
+	u8 crl_pilots_off_10;
+	u8 crl_pilots_on_20;
+	u8 crl_pilots_off_20;
+	u8 crl_pilots_on_30;
+	u8 crl_pilots_off_30;
+};
+
+struct stv090x_short_frame_crloop {
+	enum stv090x_modulation	modulation;
+
+	u8 crl_2;  /*      SR <   3M */
+	u8 crl_5;  /*  3 < SR <=  7M */
+	u8 crl_10; /*  7 < SR <= 15M */
+	u8 crl_20; /* 10 < SR <= 25M */
+	u8 crl_30; /* 10 < SR <= 45M */
+};
+
+struct stv090x_reg {
+	u16 addr;
+	u8  data;
+};
+
+struct stv090x_tab {
+	s32 real;
+	s32 read;
+};
+
+struct stv090x_internal {
+	struct i2c_adapter 	*i2c_adap;
+	u8			i2c_addr;
+
+	struct mutex		demod_lock; /* Lock access to shared register */
+	struct mutex		tuner_lock; /* Lock access to tuners */
+	s32			mclk; /* Masterclock Divider factor */
+	u32			dev_ver;
+
+	int			num_used;
+};
+
+struct stv090x_state {
+	enum stv090x_device		device;
+	enum stv090x_demodulator	demod;
+	enum stv090x_mode		demod_mode;
+	struct stv090x_internal		*internal;
+
+	struct i2c_adapter		*i2c;
+	const struct stv090x_config	*config;
+	struct dvb_frontend		frontend;
+
+	u32				*verbose; /* Cached module verbosity */
+
+	enum stv090x_delsys		delsys;
+	enum stv090x_fec		fec;
+	enum stv090x_modulation		modulation;
+	enum stv090x_modcod		modcod;
+	enum stv090x_search		search_mode;
+	enum stv090x_frame		frame_len;
+	enum stv090x_pilot		pilots;
+	enum stv090x_rolloff		rolloff;
+	enum stv090x_inversion		inversion;
+	enum stv090x_algo		algo;
+
+	u32				frequency;
+	u32				srate;
+
+	s32				tuner_bw;
+
+	s32				search_range;
+
+	s32				DemodTimeout;
+	s32				FecTimeout;
+};
+
+#endif /* __STV090x_PRIV_H */
diff --git a/drivers/media/dvb-frontends/stv090x_reg.h b/drivers/media/dvb-frontends/stv090x_reg.h
new file mode 100644
index 0000000..93741ee
--- /dev/null
+++ b/drivers/media/dvb-frontends/stv090x_reg.h
@@ -0,0 +1,2371 @@
+/*
+	STV0900/0903 Multistandard Broadcast Frontend driver
+	Copyright (C) Manu Abraham <abraham.manu@gmail.com>
+
+	Copyright (C) ST Microelectronics
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the 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 __STV090x_REG_H
+#define __STV090x_REG_H
+
+#define STV090x_MID				0xf100
+#define STV090x_OFFST_MCHIP_IDENT_FIELD		4
+#define STV090x_WIDTH_MCHIP_IDENT_FIELD		4
+#define STV090x_OFFST_MRELEASE_FIELD		0
+#define STV090x_WIDTH_MRELEASE_FIELD		4
+
+#define STV090x_DACR1				0xf113
+#define STV090x_OFFST_DACR1_MODE_FIELD		5
+#define STV090x_WIDTH_DACR1_MODE_FIELD		3
+#define STV090x_OFFST_DACR1_VALUE_FIELD		0
+#define STV090x_WIDTH_DACR1_VALUE_FIELD		4
+
+#define STV090x_DACR2				0xf114
+#define STV090x_OFFST_DACR2_VALUE_FIELD		0
+#define STV090x_WIDTH_DACR2_VALUE_FIELD		8
+
+#define STV090x_OUTCFG				0xf11c
+#define STV090x_OFFST_OUTSERRS1_HZ_FIELD	6
+#define STV090x_WIDTH_OUTSERRS1_HZ_FIELD	1
+#define STV090x_OFFST_OUTSERRS2_HZ_FIELD	5
+#define STV090x_WIDTH_OUTSERRS2_HZ_FIELD	1
+#define STV090x_OFFST_OUTSERRS3_HZ_FIELD	4
+#define STV090x_WIDTH_OUTSERRS3_HZ_FIELD	1
+#define STV090x_OFFST_OUTPARRS3_HZ_FIELD	3
+#define STV090x_WIDTH_OUTPARRS3_HZ_FIELD	1
+
+#define STV090x_MODECFG				0xf11d
+
+#define STV090x_IRQSTATUS3			0xf120
+#define STV090x_OFFST_SPLL_LOCK_FIELD		5
+#define STV090x_WIDTH_SPLL_LOCK_FIELD		1
+#define STV090x_OFFST_SSTREAM_LCK_3_FIELD	4
+#define STV090x_WIDTH_SSTREAM_LCK_3_FIELD	1
+#define STV090x_OFFST_SSTREAM_LCK_2_FIELD	3
+#define STV090x_WIDTH_SSTREAM_LCK_2_FIELD	1
+#define STV090x_OFFST_SSTREAM_LCK_1_FIELD	2
+#define STV090x_WIDTH_SSTREAM_LCK_1_FIELD	1
+#define STV090x_OFFST_SDVBS1_PRF_2_FIELD	1
+#define STV090x_WIDTH_SDVBS1_PRF_2_FIELD	1
+#define STV090x_OFFST_SDVBS1_PRF_1_FIELD	0
+#define STV090x_WIDTH_SDVBS1_PRF_1_FIELD	1
+
+#define STV090x_IRQSTATUS2			0xf121
+#define STV090x_OFFST_SSPY_ENDSIM_3_FIELD	7
+#define STV090x_WIDTH_SSPY_ENDSIM_3_FIELD	1
+#define STV090x_OFFST_SSPY_ENDSIM_2_FIELD	6
+#define STV090x_WIDTH_SSPY_ENDSIM_2_FIELD	1
+#define STV090x_OFFST_SSPY_ENDSIM_1_FIELD	5
+#define STV090x_WIDTH_SSPY_ENDSIM_1_FIELD	1
+#define STV090x_OFFST_SPKTDEL_ERROR_2_FIELD	4
+#define STV090x_WIDTH_SPKTDEL_ERROR_2_FIELD	1
+#define STV090x_OFFST_SPKTDEL_LOCKB_2_FIELD	3
+#define STV090x_WIDTH_SPKTDEL_LOCKB_2_FIELD	1
+#define STV090x_OFFST_SPKTDEL_LOCK_2_FIELD	2
+#define STV090x_WIDTH_SPKTDEL_LOCK_2_FIELD	1
+#define STV090x_OFFST_SPKTDEL_ERROR_1_FIELD	1
+#define STV090x_WIDTH_SPKTDEL_ERROR_1_FIELD	1
+#define STV090x_OFFST_SPKTDEL_LOCKB_1_FIELD	0
+#define STV090x_WIDTH_SPKTDEL_LOCKB_1_FIELD	1
+
+#define STV090x_IRQSTATUS1			0xf122
+#define STV090x_OFFST_SPKTDEL_LOCK_1_FIELD	7
+#define STV090x_WIDTH_SPKTDEL_LOCK_1_FIELD	1
+#define STV090x_OFFST_SDEMOD_LOCKB_2_FIELD	2
+#define STV090x_WIDTH_SDEMOD_LOCKB_2_FIELD	1
+#define STV090x_OFFST_SDEMOD_LOCK_2_FIELD	1
+#define STV090x_WIDTH_SDEMOD_LOCK_2_FIELD	1
+#define STV090x_OFFST_SDEMOD_IRQ_2_FIELD	0
+#define STV090x_WIDTH_SDEMOD_IRQ_2_FIELD	1
+
+#define STV090x_IRQSTATUS0			0xf123
+#define STV090x_OFFST_SDEMOD_LOCKB_1_FIELD	7
+#define STV090x_WIDTH_SDEMOD_LOCKB_1_FIELD	1
+#define STV090x_OFFST_SDEMOD_LOCK_1_FIELD	6
+#define STV090x_WIDTH_SDEMOD_LOCK_1_FIELD	1
+#define STV090x_OFFST_SDEMOD_IRQ_1_FIELD	5
+#define STV090x_WIDTH_SDEMOD_IRQ_1_FIELD	1
+#define STV090x_OFFST_SBCH_ERRFLAG_FIELD	4
+#define STV090x_WIDTH_SBCH_ERRFLAG_FIELD	1
+#define STV090x_OFFST_SDISEQC2RX_IRQ_FIELD	3
+#define STV090x_WIDTH_SDISEQC2RX_IRQ_FIELD	1
+#define STV090x_OFFST_SDISEQC2TX_IRQ_FIELD	2
+#define STV090x_WIDTH_SDISEQC2TX_IRQ_FIELD	1
+#define STV090x_OFFST_SDISEQC1RX_IRQ_FIELD	1
+#define STV090x_WIDTH_SDISEQC1RX_IRQ_FIELD	1
+#define STV090x_OFFST_SDISEQC1TX_IRQ_FIELD	0
+#define STV090x_WIDTH_SDISEQC1TX_IRQ_FIELD	1
+
+#define STV090x_IRQMASK3			0xf124
+#define STV090x_OFFST_MPLL_LOCK_FIELD		5
+#define STV090x_WIDTH_MPLL_LOCK_FIELD		1
+#define STV090x_OFFST_MSTREAM_LCK_3_FIELD	4
+#define STV090x_WIDTH_MSTREAM_LCK_3_FIELD	1
+#define STV090x_OFFST_MSTREAM_LCK_2_FIELD	3
+#define STV090x_WIDTH_MSTREAM_LCK_2_FIELD	1
+#define STV090x_OFFST_MSTREAM_LCK_1_FIELD	2
+#define STV090x_WIDTH_MSTREAM_LCK_1_FIELD	1
+#define STV090x_OFFST_MDVBS1_PRF_2_FIELD	1
+#define STV090x_WIDTH_MDVBS1_PRF_2_FIELD	1
+#define STV090x_OFFST_MDVBS1_PRF_1_FIELD	0
+#define STV090x_WIDTH_MDVBS1_PRF_1_FIELD	1
+
+#define STV090x_IRQMASK2			0xf125
+#define STV090x_OFFST_MSPY_ENDSIM_3_FIELD	7
+#define STV090x_WIDTH_MSPY_ENDSIM_3_FIELD	1
+#define STV090x_OFFST_MSPY_ENDSIM_2_FIELD	6
+#define STV090x_WIDTH_MSPY_ENDSIM_2_FIELD	1
+#define STV090x_OFFST_MSPY_ENDSIM_1_FIELD	5
+#define STV090x_WIDTH_MSPY_ENDSIM_1_FIELD	1
+#define STV090x_OFFST_MPKTDEL_ERROR_2_FIELD	4
+#define STV090x_WIDTH_MPKTDEL_ERROR_2_FIELD	1
+#define STV090x_OFFST_MPKTDEL_LOCKB_2_FIELD	3
+#define STV090x_WIDTH_MPKTDEL_LOCKB_2_FIELD	1
+#define STV090x_OFFST_MPKTDEL_LOCK_2_FIELD	2
+#define STV090x_WIDTH_MPKTDEL_LOCK_2_FIELD	1
+#define STV090x_OFFST_MPKTDEL_ERROR_1_FIELD	1
+#define STV090x_WIDTH_MPKTDEL_ERROR_1_FIELD	1
+#define STV090x_OFFST_MPKTDEL_LOCKB_1_FIELD	0
+#define STV090x_WIDTH_MPKTDEL_LOCKB_1_FIELD	1
+
+#define STV090x_IRQMASK1			0xf126
+#define STV090x_OFFST_MPKTDEL_LOCK_1_FIELD	7
+#define STV090x_WIDTH_MPKTDEL_LOCK_1_FIELD	1
+#define STV090x_OFFST_MEXTPINB2_FIELD		6
+#define STV090x_WIDTH_MEXTPINB2_FIELD		1
+#define STV090x_OFFST_MEXTPIN2_FIELD		5
+#define STV090x_WIDTH_MEXTPIN2_FIELD		1
+#define STV090x_OFFST_MEXTPINB1_FIELD		4
+#define STV090x_WIDTH_MEXTPINB1_FIELD		1
+#define STV090x_OFFST_MEXTPIN1_FIELD		3
+#define STV090x_WIDTH_MEXTPIN1_FIELD		1
+#define STV090x_OFFST_MDEMOD_LOCKB_2_FIELD	2
+#define STV090x_WIDTH_MDEMOD_LOCKB_2_FIELD	1
+#define STV090x_OFFST_MDEMOD_LOCK_2_FIELD	1
+#define STV090x_WIDTH_MDEMOD_LOCK_2_FIELD	1
+#define STV090x_OFFST_MDEMOD_IRQ_2_FIELD	0
+#define STV090x_WIDTH_MDEMOD_IRQ_2_FIELD	1
+
+#define STV090x_IRQMASK0			0xf127
+#define STV090x_OFFST_MDEMOD_LOCKB_1_FIELD	7
+#define STV090x_WIDTH_MDEMOD_LOCKB_1_FIELD	1
+#define STV090x_OFFST_MDEMOD_LOCK_1_FIELD	6
+#define STV090x_WIDTH_MDEMOD_LOCK_1_FIELD	1
+#define STV090x_OFFST_MDEMOD_IRQ_1_FIELD	5
+#define STV090x_WIDTH_MDEMOD_IRQ_1_FIELD	1
+#define STV090x_OFFST_MBCH_ERRFLAG_FIELD	4
+#define STV090x_WIDTH_MBCH_ERRFLAG_FIELD	1
+#define STV090x_OFFST_MDISEQC2RX_IRQ_FIELD	3
+#define STV090x_WIDTH_MDISEQC2RX_IRQ_FIELD	1
+#define STV090x_OFFST_MDISEQC2TX_IRQ_FIELD	2
+#define STV090x_WIDTH_MDISEQC2TX_IRQ_FIELD	1
+#define STV090x_OFFST_MDISEQC1RX_IRQ_FIELD	1
+#define STV090x_WIDTH_MDISEQC1RX_IRQ_FIELD	1
+#define STV090x_OFFST_MDISEQC1TX_IRQ_FIELD	0
+#define STV090x_WIDTH_MDISEQC1TX_IRQ_FIELD	1
+
+#define STV090x_I2CCFG				0xf129
+#define STV090x_OFFST_12C_FASTMODE_FIELD	3
+#define STV090x_WIDTH_12C_FASTMODE_FIELD	1
+#define STV090x_OFFST_12CADDR_INC_FIELD		0
+#define STV090x_WIDTH_12CADDR_INC_FIELD		2
+
+#define STV090x_Px_I2CRPT(__x)			(0xf12a + (__x - 1) * 0x1)
+#define STV090x_P1_I2CRPT			STV090x_Px_I2CRPT(1)
+#define STV090x_P2_I2CRPT			STV090x_Px_I2CRPT(2)
+#define STV090x_OFFST_Px_I2CT_ON_FIELD		7
+#define STV090x_WIDTH_Px_I2CT_ON_FIELD		1
+#define STV090x_OFFST_Px_ENARPT_LEVEL_FIELD	4
+#define STV090x_WIDTH_Px_ENARPT_LEVEL_FIELD	3
+#define STV090x_OFFST_Px_SCLT_DELAY_FIELD	3
+#define STV090x_WIDTH_Px_SCLT_DELAY_FIELD	1
+#define STV090x_OFFST_Px_STOP_ENABLE_FIELD	2
+#define STV090x_WIDTH_Px_STOP_ENABLE_FIELD	1
+#define STV090x_OFFST_Px_STOP_SDAT2SDA_FIELD	1
+#define STV090x_WIDTH_Px_STOP_SDAT2SDA_FIELD	1
+
+#define STV090x_CLKI2CFG			0xf140
+#define STV090x_OFFST_CLKI2_OPD_FIELD		7
+#define STV090x_WIDTH_CLKI2_OPD_FIELD		1
+#define STV090x_OFFST_CLKI2_CONFIG_FIELD	1
+#define STV090x_WIDTH_CLKI2_CONFIG_FIELD	6
+#define STV090x_OFFST_CLKI2_XOR_FIELD		0
+#define STV090x_WIDTH_CLKI2_XOR_FIELD		1
+
+#define STV090x_GPIOxCFG(__x)			(0xf141 + (__x - 1))
+#define STV090x_GPIO1CFG			STV090x_GPIOxCFG(1)
+#define STV090x_GPIO2CFG			STV090x_GPIOxCFG(2)
+#define STV090x_GPIO3CFG			STV090x_GPIOxCFG(3)
+#define STV090x_GPIO4CFG			STV090x_GPIOxCFG(4)
+#define STV090x_GPIO5CFG			STV090x_GPIOxCFG(5)
+#define STV090x_GPIO6CFG			STV090x_GPIOxCFG(6)
+#define STV090x_GPIO7CFG			STV090x_GPIOxCFG(7)
+#define STV090x_GPIO8CFG			STV090x_GPIOxCFG(8)
+#define STV090x_GPIO9CFG			STV090x_GPIOxCFG(9)
+#define STV090x_GPIO10CFG			STV090x_GPIOxCFG(10)
+#define STV090x_GPIO11CFG			STV090x_GPIOxCFG(11)
+#define STV090x_GPIO12CFG			STV090x_GPIOxCFG(12)
+#define STV090x_GPIO13CFG			STV090x_GPIOxCFG(13)
+#define STV090x_OFFST_GPIOx_OPD_FIELD		7
+#define STV090x_WIDTH_GPIOx_OPD_FIELD		1
+#define STV090x_OFFST_GPIOx_CONFIG_FIELD	1
+#define STV090x_WIDTH_GPIOx_CONFIG_FIELD	6
+#define STV090x_OFFST_GPIOx_XOR_FIELD		0
+#define STV090x_WIDTH_GPIOx_XOR_FIELD		1
+
+#define STV090x_CSxCFG(__x)			(0xf14e + __x * 0x1)
+#define STV090x_CS0CFG				STV090x_CSxCFG(0)
+#define STV090x_CS1CFG				STV090x_CSxCFG(1)
+#define STV090x_OFFST_CSX_OPD_FIELD		7
+#define STV090x_WIDTH_CSX_OPD_FIELD		1
+#define STV090x_OFFST_CSX_CONFIG_FIELD		1
+#define STV090x_WIDTH_CSX_CONFIG_FIELD		6
+#define STV090x_OFFST_CSX_XOR_FIELD		0
+#define STV090x_WIDTH_CSX_XOR_FIELD		1
+
+
+#define STV090x_STDBYCFG			0xf150
+#define STV090x_OFFST_STDBY_OPD_FIELD		7
+#define STV090x_WIDTH_STDBY_OPD_FIELD		1
+#define STV090x_OFFST_STDBY_CONFIG_FIELD	1
+#define STV090x_WIDTH_STDBY_CONFIG_FIELD	6
+#define STV090x_OFFST_STDBY_XOR_FIELD		0
+#define STV090x_WIDTH_STDBY_XOR_FIELD		1
+
+#define STV090x_DIRCLKCFG			0xf151
+#define STV090x_OFFST_DIRCLK_OPD_FIELD		7
+#define STV090x_WIDTH_DIRCLK_OPD_FIELD		1
+#define STV090x_OFFST_DIRCLK_CONFIG_FIELD	1
+#define STV090x_WIDTH_DIRCLK_CONFIG_FIELD	6
+#define STV090x_OFFST_DIRCLK_XOR_FIELD		0
+#define STV090x_WIDTH_DIRCLK_XOR_FIELD		1
+
+
+#define STV090x_AGCRFxCFG(__x)			(0xf152 + (__x - 1) * 0x4)
+#define STV090x_AGCRF1CFG			STV090x_AGCRFxCFG(1)
+#define STV090x_AGCRF2CFG			STV090x_AGCRFxCFG(2)
+#define STV090x_OFFST_AGCRFx_OPD_FIELD		7
+#define STV090x_WIDTH_AGCRFx_OPD_FIELD		1
+#define STV090x_OFFST_AGCRFx_CONFIG_FIELD	1
+#define STV090x_WIDTH_AGCRFx_CONFIG_FIELD	6
+#define STV090x_OFFST_AGCRFx_XOR_FIELD		0
+#define STV090x_WIDTH_AGCRFx_XOR_FIELD		1
+
+#define STV090x_SDATxCFG(__x)			(0xf153 + (__x - 1) * 0x4)
+#define STV090x_SDAT1CFG			STV090x_SDATxCFG(1)
+#define STV090x_SDAT2CFG			STV090x_SDATxCFG(2)
+#define STV090x_OFFST_SDATx_OPD_FIELD		7
+#define STV090x_WIDTH_SDATx_OPD_FIELD		1
+#define STV090x_OFFST_SDATx_CONFIG_FIELD	1
+#define STV090x_WIDTH_SDATx_CONFIG_FIELD	6
+#define STV090x_OFFST_SDATx_XOR_FIELD		0
+#define STV090x_WIDTH_SDATx_XOR_FIELD		1
+
+#define STV090x_SCLTxCFG(__x)			(0xf154 + (__x - 1) * 0x4)
+#define STV090x_SCLT1CFG			STV090x_SCLTxCFG(1)
+#define STV090x_SCLT2CFG			STV090x_SCLTxCFG(2)
+#define STV090x_OFFST_SCLTx_OPD_FIELD		7
+#define STV090x_WIDTH_SCLTx_OPD_FIELD		1
+#define STV090x_OFFST_SCLTx_CONFIG_FIELD	1
+#define STV090x_WIDTH_SCLTx_CONFIG_FIELD	6
+#define STV090x_OFFST_SCLTx_XOR_FIELD		0
+#define STV090x_WIDTH_SCLTx_XOR_FIELD		1
+
+#define STV090x_DISEQCOxCFG(__x)		(0xf155 + (__x - 1) * 0x4)
+#define STV090x_DISEQCO1CFG			STV090x_DISEQCOxCFG(1)
+#define STV090x_DISEQCO2CFG			STV090x_DISEQCOxCFG(2)
+#define STV090x_OFFST_DISEQCOx_OPD_FIELD	7
+#define STV090x_WIDTH_DISEQCOx_OPD_FIELD	1
+#define STV090x_OFFST_DISEQCOx_CONFIG_FIELD	1
+#define STV090x_WIDTH_DISEQCOx_CONFIG_FIELD	6
+#define STV090x_OFFST_DISEQCOx_XOR_FIELD	0
+#define STV090x_WIDTH_DISEQCOx_XOR_FIELD	1
+
+#define STV090x_CLKOUT27CFG			0xf15a
+#define STV090x_OFFST_CLKOUT27_OPD_FIELD	7
+#define STV090x_WIDTH_CLKOUT27_OPD_FIELD	1
+#define STV090x_OFFST_CLKOUT27_CONFIG_FIELD	1
+#define STV090x_WIDTH_CLKOUT27_CONFIG_FIELD	6
+#define STV090x_OFFST_CLKOUT27_XOR_FIELD	0
+#define STV090x_WIDTH_CLKOUT27_XOR_FIELD	1
+
+#define STV090x_ERRORxCFG(__x)			(0xf15b + (__x - 1) * 0x5)
+#define STV090x_ERROR1CFG			STV090x_ERRORxCFG(1)
+#define STV090x_ERROR2CFG			STV090x_ERRORxCFG(2)
+#define STV090x_ERROR3CFG			STV090x_ERRORxCFG(3)
+#define STV090x_OFFST_ERRORx_OPD_FIELD		7
+#define STV090x_WIDTH_ERRORx_OPD_FIELD		1
+#define STV090x_OFFST_ERRORx_CONFIG_FIELD	1
+#define STV090x_WIDTH_ERRORx_CONFIG_FIELD	6
+#define STV090x_OFFST_ERRORx_XOR_FIELD		0
+#define STV090x_WIDTH_ERRORx_XOR_FIELD		1
+
+#define STV090x_DPNxCFG(__x)			(0xf15c + (__x - 1) * 0x5)
+#define STV090x_DPN1CFG				STV090x_DPNxCFG(1)
+#define STV090x_DPN2CFG				STV090x_DPNxCFG(2)
+#define STV090x_DPN3CFG				STV090x_DPNxCFG(3)
+#define STV090x_OFFST_DPNx_OPD_FIELD		7
+#define STV090x_WIDTH_DPNx_OPD_FIELD		1
+#define STV090x_OFFST_DPNx_CONFIG_FIELD		1
+#define STV090x_WIDTH_DPNx_CONFIG_FIELD		6
+#define STV090x_OFFST_DPNx_XOR_FIELD		0
+#define STV090x_WIDTH_DPNx_XOR_FIELD		1
+
+#define STV090x_STROUTxCFG(__x)			(0xf15d + (__x - 1) * 0x5)
+#define STV090x_STROUT1CFG			STV090x_STROUTxCFG(1)
+#define STV090x_STROUT2CFG			STV090x_STROUTxCFG(2)
+#define STV090x_STROUT3CFG			STV090x_STROUTxCFG(3)
+#define STV090x_OFFST_STROUTx_OPD_FIELD		7
+#define STV090x_WIDTH_STROUTx_OPD_FIELD		1
+#define STV090x_OFFST_STROUTx_CONFIG_FIELD	1
+#define STV090x_WIDTH_STROUTx_CONFIG_FIELD	6
+#define STV090x_OFFST_STROUTx_XOR_FIELD		0
+#define STV090x_WIDTH_STROUTx_XOR_FIELD		1
+
+#define STV090x_CLKOUTxCFG(__x)			(0xf15e + (__x - 1) * 0x5)
+#define STV090x_CLKOUT1CFG			STV090x_CLKOUTxCFG(1)
+#define STV090x_CLKOUT2CFG			STV090x_CLKOUTxCFG(2)
+#define STV090x_CLKOUT3CFG			STV090x_CLKOUTxCFG(3)
+#define STV090x_OFFST_CLKOUTx_OPD_FIELD		7
+#define STV090x_WIDTH_CLKOUTx_OPD_FIELD		1
+#define STV090x_OFFST_CLKOUTx_CONFIG_FIELD	1
+#define STV090x_WIDTH_CLKOUTx_CONFIG_FIELD	6
+#define STV090x_OFFST_CLKOUTx_XOR_FIELD		0
+#define STV090x_WIDTH_CLKOUTx_XOR_FIELD		1
+
+#define STV090x_DATAxCFG(__x)			(0xf15f + (__x - 71) * 0x5)
+#define STV090x_DATA71CFG			STV090x_DATAxCFG(71)
+#define STV090x_DATA72CFG			STV090x_DATAxCFG(72)
+#define STV090x_DATA73CFG			STV090x_DATAxCFG(73)
+#define STV090x_OFFST_DATAx_OPD_FIELD		7
+#define STV090x_WIDTH_DATAx_OPD_FIELD		1
+#define STV090x_OFFST_DATAx_CONFIG_FIELD	1
+#define STV090x_WIDTH_DATAx_CONFIG_FIELD	6
+#define STV090x_OFFST_DATAx_XOR_FIELD		0
+#define STV090x_WIDTH_DATAx_XOR_FIELD		1
+
+#define STV090x_NCOARSE				0xf1b3
+#define STV090x_OFFST_M_DIV_FIELD		0
+#define STV090x_WIDTH_M_DIV_FIELD		8
+
+#define STV090x_SYNTCTRL			0xf1b6
+#define STV090x_OFFST_STANDBY_FIELD		7
+#define STV090x_WIDTH_STANDBY_FIELD		1
+#define STV090x_OFFST_BYPASSPLLCORE_FIELD	6
+#define STV090x_WIDTH_BYPASSPLLCORE_FIELD	1
+#define STV090x_OFFST_SELX1RATIO_FIELD		5
+#define STV090x_WIDTH_SELX1RATIO_FIELD		1
+#define STV090x_OFFST_STOP_PLL_FIELD		3
+#define STV090x_WIDTH_STOP_PLL_FIELD		1
+#define STV090x_OFFST_BYPASSPLLFSK_FIELD	2
+#define STV090x_WIDTH_BYPASSPLLFSK_FIELD	1
+#define STV090x_OFFST_SELOSCI_FIELD		1
+#define STV090x_WIDTH_SELOSCI_FIELD		1
+#define STV090x_OFFST_BYPASSPLLADC_FIELD	0
+#define STV090x_WIDTH_BYPASSPLLADC_FIELD	1
+
+#define STV090x_FILTCTRL			0xf1b7
+#define STV090x_OFFST_INV_CLK135_FIELD		7
+#define STV090x_WIDTH_INV_CLK135_FIELD		1
+#define STV090x_OFFST_SEL_FSKCKDIV_FIELD	2
+#define STV090x_WIDTH_SEL_FSKCKDIV_FIELD	1
+#define STV090x_OFFST_INV_CLKFSK_FIELD		1
+#define STV090x_WIDTH_INV_CLKFSK_FIELD		1
+#define STV090x_OFFST_BYPASS_APPLI_FIELD	0
+#define STV090x_WIDTH_BYPASS_APPLI_FIELD	1
+
+#define STV090x_PLLSTAT				0xf1b8
+#define STV090x_OFFST_PLLLOCK_FIELD		0
+#define STV090x_WIDTH_PLLLOCK_FIELD		1
+
+#define STV090x_STOPCLK1			0xf1c2
+#define STV090x_OFFST_STOP_CLKPKDT2_FIELD	6
+#define STV090x_WIDTH_STOP_CLKPKDT2_FIELD	1
+#define STV090x_OFFST_STOP_CLKPKDT1_FIELD	5
+#define STV090x_WIDTH_STOP_CLKPKDT1_FIELD	1
+#define STV090x_OFFST_STOP_CLKFEC_FIELD		4
+#define STV090x_WIDTH_STOP_CLKFEC_FIELD		1
+#define STV090x_OFFST_STOP_CLKADCI2_FIELD	3
+#define STV090x_WIDTH_STOP_CLKADCI2_FIELD	1
+#define STV090x_OFFST_INV_CLKADCI2_FIELD	2
+#define STV090x_WIDTH_INV_CLKADCI2_FIELD	1
+#define STV090x_OFFST_STOP_CLKADCI1_FIELD	1
+#define STV090x_WIDTH_STOP_CLKADCI1_FIELD	1
+#define STV090x_OFFST_INV_CLKADCI1_FIELD	0
+#define STV090x_WIDTH_INV_CLKADCI1_FIELD	1
+
+#define STV090x_STOPCLK2			0xf1c3
+#define STV090x_OFFST_STOP_CLKSAMP2_FIELD	4
+#define STV090x_WIDTH_STOP_CLKSAMP2_FIELD	1
+#define STV090x_OFFST_STOP_CLKSAMP1_FIELD	3
+#define STV090x_WIDTH_STOP_CLKSAMP1_FIELD	1
+#define STV090x_OFFST_STOP_CLKVIT2_FIELD	2
+#define STV090x_WIDTH_STOP_CLKVIT2_FIELD	1
+#define STV090x_OFFST_STOP_CLKVIT1_FIELD	1
+#define STV090x_WIDTH_STOP_CLKVIT1_FIELD	1
+#define STV090x_OFFST_STOP_CLKTS_FIELD		0
+#define STV090x_WIDTH_STOP_CLKTS_FIELD		1
+
+#define STV090x_TSTTNR0				0xf1df
+#define STV090x_OFFST_SEL_FSK_FIELD		7
+#define STV090x_WIDTH_SEL_FSK_FIELD		1
+#define STV090x_OFFST_FSK_PON_FIELD		2
+#define STV090x_WIDTH_FSK_PON_FIELD		1
+
+#define STV090x_TSTTNR1				0xf1e0
+#define STV090x_OFFST_ADC1_PON_FIELD		1
+#define STV090x_WIDTH_ADC1_PON_FIELD		1
+#define STV090x_OFFST_ADC1_INMODE_FIELD		0
+#define STV090x_WIDTH_ADC1_INMODE_FIELD		1
+
+#define STV090x_TSTTNR2				0xf1e1
+#define STV090x_OFFST_DISEQC1_PON_FIELD		5
+#define STV090x_WIDTH_DISEQC1_PON_FIELD		1
+
+#define STV090x_TSTTNR3				0xf1e2
+#define STV090x_OFFST_ADC2_PON_FIELD		1
+#define STV090x_WIDTH_ADC2_PON_FIELD		1
+#define STV090x_OFFST_ADC2_INMODE_FIELD		0
+#define STV090x_WIDTH_ADC2_INMODE_FIELD		1
+
+#define STV090x_TSTTNR4				0xf1e3
+#define STV090x_OFFST_DISEQC2_PON_FIELD		5
+#define STV090x_WIDTH_DISEQC2_PON_FIELD		1
+
+#define STV090x_FSKTFC2				0xf170
+#define STV090x_OFFST_FSKT_KMOD_FIELD		2
+#define STV090x_WIDTH_FSKT_KMOD_FIELD		6
+#define STV090x_OFFST_FSKT_CAR_FIELD		0
+#define STV090x_WIDTH_FSKT_CAR_FIELD		2
+
+#define STV090x_FSKTFC1				0xf171
+#define STV090x_OFFST_FSKTC1_CAR_FIELD		0
+#define STV090x_WIDTH_FSKTC1_CAR_FIELD		8
+
+#define STV090x_FSKTFC0				0xf172
+#define STV090x_OFFST_FSKTC0_CAR_FIELD		0
+#define STV090x_WIDTH_FSKTC0_CAR_FIELD		8
+
+#define STV090x_FSKTDELTAF1			0xf173
+#define STV090x_OFFST_FSKTF1_DELTAF_FIELD	0
+#define STV090x_WIDTH_FSKTF1_DELTAF_FIELD	4
+
+#define STV090x_FSKTDELTAF0			0xf174
+#define STV090x_OFFST_FSKTF0_DELTAF_FIELD	0
+#define STV090x_WIDTH_FSKTF0_DELTAF_FIELD	8
+
+#define STV090x_FSKTCTRL			0xf175
+#define STV090x_OFFST_FSKT_EN_SGN_FIELD		6
+#define STV090x_WIDTH_FSKT_EN_SGN_FIELD		1
+#define STV090x_OFFST_FSKT_MOD_SGN_FIELD	5
+#define STV090x_WIDTH_FSKT_MOD_SGN_FIELD	1
+#define STV090x_OFFST_FSKT_MOD_EN_FIELD		2
+#define STV090x_WIDTH_FSKT_MOD_EN_FIELD		3
+#define STV090x_OFFST_FSKT_DACMODE_FIELD	0
+#define STV090x_WIDTH_FSKT_DACMODE_FIELD	2
+
+#define STV090x_FSKRFC2				0xf176
+#define STV090x_OFFST_FSKRC2_DETSGN_FIELD	6
+#define STV090x_WIDTH_FSKRC2_DETSGN_FIELD	1
+#define STV090x_OFFST_FSKRC2_OUTSGN_FIELD	5
+#define STV090x_WIDTH_FSKRC2_OUTSGN_FIELD	1
+#define STV090x_OFFST_FSKRC2_KAGC_FIELD		2
+#define STV090x_WIDTH_FSKRC2_KAGC_FIELD		3
+#define STV090x_OFFST_FSKRC2_CAR_FIELD		0
+#define STV090x_WIDTH_FSKRC2_CAR_FIELD		2
+
+#define STV090x_FSKRFC1				0xf177
+#define STV090x_OFFST_FSKRC1_CAR_FIELD		0
+#define STV090x_WIDTH_FSKRC1_CAR_FIELD		8
+
+#define STV090x_FSKRFC0				0xf178
+#define STV090x_OFFST_FSKRC0_CAR_FIELD		0
+#define STV090x_WIDTH_FSKRC0_CAR_FIELD		8
+
+#define STV090x_FSKRK1				0xf179
+#define STV090x_OFFST_FSKR_K1_EXP_FIELD		5
+#define STV090x_WIDTH_FSKR_K1_EXP_FIELD		3
+#define STV090x_OFFST_FSKR_K1_MANT_FIELD	0
+#define STV090x_WIDTH_FSKR_K1_MANT_FIELD	5
+
+#define STV090x_FSKRK2				0xf17a
+#define STV090x_OFFST_FSKR_K2_EXP_FIELD		5
+#define STV090x_WIDTH_FSKR_K2_EXP_FIELD		3
+#define STV090x_OFFST_FSKR_K2_MANT_FIELD	0
+#define STV090x_WIDTH_FSKR_K2_MANT_FIELD	5
+
+#define STV090x_FSKRAGCR			0xf17b
+#define STV090x_OFFST_FSKR_OUTCTL_FIELD		6
+#define STV090x_WIDTH_FSKR_OUTCTL_FIELD		2
+#define STV090x_OFFST_FSKR_AGC_REF_FIELD	0
+#define STV090x_WIDTH_FSKR_AGC_REF_FIELD	6
+
+#define STV090x_FSKRAGC				0xf17c
+#define STV090x_OFFST_FSKR_AGC_ACCU_FIELD	0
+#define STV090x_WIDTH_FSKR_AGC_ACCU_FIELD	8
+
+#define STV090x_FSKRALPHA			0xf17d
+#define STV090x_OFFST_FSKR_ALPHA_EXP_FIELD	2
+#define STV090x_WIDTH_FSKR_ALPHA_EXP_FIELD	3
+#define STV090x_OFFST_FSKR_ALPHA_M_FIELD	0
+#define STV090x_WIDTH_FSKR_ALPHA_M_FIELD	2
+
+#define STV090x_FSKRPLTH1			0xf17e
+#define STV090x_OFFST_FSKR_BETA_FIELD		4
+#define STV090x_WIDTH_FSKR_BETA_FIELD		4
+#define STV090x_OFFST_FSKR_PLL_TRESH1_FIELD	0
+#define STV090x_WIDTH_FSKR_PLL_TRESH1_FIELD	4
+
+#define STV090x_FSKRPLTH0			0xf17f
+#define STV090x_OFFST_FSKR_PLL_TRESH0_FIELD	0
+#define STV090x_WIDTH_FSKR_PLL_TRESH0_FIELD	8
+
+#define STV090x_FSKRDF1				0xf180
+#define STV090x_OFFST_FSKR_DELTAF1_FIELD	0
+#define STV090x_WIDTH_FSKR_DELTAF1_FIELD	5
+
+#define STV090x_FSKRDF0				0xf181
+#define STV090x_OFFST_FSKR_DELTAF0_FIELD	0
+#define STV090x_WIDTH_FSKR_DELTAF0_FIELD	8
+
+#define STV090x_FSKRSTEPP			0xf182
+#define STV090x_OFFST_FSKR_STEP_PLUS_FIELD	0
+#define STV090x_WIDTH_FSKR_STEP_PLUS_FIELD	8
+
+#define STV090x_FSKRSTEPM			0xf183
+#define STV090x_OFFST_FSKR_STEP_MINUS_FIELD	0
+#define STV090x_WIDTH_FSKR_STEP_MINUS_FIELD	8
+
+#define STV090x_FSKRDET1			0xf184
+#define STV090x_OFFST_FSKR_CARDET1_ACCU_FIELD	0
+#define STV090x_WIDTH_FSKR_CARDET1_ACCU_FIELD	4
+
+#define STV090x_FSKRDET0			0xf185
+#define STV090x_OFFST_FSKR_CARDET0_ACCU_FIELD	0
+#define STV090x_WIDTH_FSKR_CARDET0_ACCU_FIELD	8
+
+#define STV090x_FSKRDTH1				0xf186
+#define STV090x_OFFST_FSKR_CARLOSS_THRESH1_FIELD	4
+#define STV090x_WIDTH_FSKR_CARLOSS_THRESH1_FIELD	4
+#define STV090x_OFFST_FSKR_CARDET_THRESH1_FIELD		0
+#define STV090x_WIDTH_FSKR_CARDET_THRESH1_FIELD		4
+
+#define STV090x_FSKRDTH0			0xf187
+#define STV090x_OFFST_FSKR_CARDET_THRESH0_FIELD	0
+#define STV090x_WIDTH_FSKR_CARDET_THRESH0_FIELD	8
+
+#define STV090x_FSKRLOSS			0xf188
+#define STV090x_OFFST_FSKR_CARLOSS_THRESH_FIELD	0
+#define STV090x_WIDTH_FSKR_CARLOSS_THRESH_FIELD	8
+
+#define STV090x_Px_DISTXCTL(__x)		(0xF1A0 - (__x - 1) * 0x10)
+#define STV090x_P1_DISTXCTL			STV090x_Px_DISTXCTL(1)
+#define STV090x_P2_DISTXCTL			STV090x_Px_DISTXCTL(2)
+#define STV090x_OFFST_Px_TIM_OFF_FIELD		7
+#define STV090x_WIDTH_Px_TIM_OFF_FIELD		1
+#define STV090x_OFFST_Px_DISEQC_RESET_FIELD	6
+#define STV090x_WIDTH_Px_DISEQC_RESET_FIELD	1
+#define STV090x_OFFST_Px_TIM_CMD_FIELD		4
+#define STV090x_WIDTH_Px_TIM_CMD_FIELD		2
+#define STV090x_OFFST_Px_DIS_PRECHARGE_FIELD	3
+#define STV090x_WIDTH_Px_DIS_PRECHARGE_FIELD	1
+#define STV090x_OFFST_Px_DISTX_MODE_FIELD	0
+#define STV090x_WIDTH_Px_DISTX_MODE_FIELD	3
+
+#define STV090x_Px_DISRXCTL(__x)		(0xf1a1 - (__x - 1) * 0x10)
+#define STV090x_P1_DISRXCTL			STV090x_Px_DISRXCTL(1)
+#define STV090x_P2_DISRXCTL			STV090x_Px_DISRXCTL(2)
+#define STV090x_OFFST_Px_RECEIVER_ON_FIELD	7
+#define STV090x_WIDTH_Px_RECEIVER_ON_FIELD	1
+#define STV090x_OFFST_Px_IGNO_SHORT22K_FIELD	6
+#define STV090x_WIDTH_Px_IGNO_SHORT22K_FIELD	1
+#define STV090x_OFFST_Px_ONECHIP_TRX_FIELD	5
+#define STV090x_WIDTH_Px_ONECHIP_TRX_FIELD	1
+#define STV090x_OFFST_Px_EXT_ENVELOP_FIELD	4
+#define STV090x_WIDTH_Px_EXT_ENVELOP_FIELD	1
+#define STV090x_OFFST_Px_PIN_SELECT_FIELD	2
+#define STV090x_WIDTH_Px_PIN_SELECT_FIELD	2
+#define STV090x_OFFST_Px_IRQ_RXEND_FIELD	1
+#define STV090x_WIDTH_Px_IRQ_RXEND_FIELD	1
+#define STV090x_OFFST_Px_IRQ_4NBYTES_FIELD	0
+#define STV090x_WIDTH_Px_IRQ_4NBYTES_FIELD	1
+
+#define STV090x_Px_DISRX_ST0(__x)		(0xf1a4 - (__x - 1) * 0x10)
+#define STV090x_P1_DISRX_ST0			STV090x_Px_DISRX_ST0(1)
+#define STV090x_P2_DISRX_ST0			STV090x_Px_DISRX_ST0(2)
+#define STV090x_OFFST_Px_RX_END_FIELD		7
+#define STV090x_WIDTH_Px_RX_END_FIELD		1
+#define STV090x_OFFST_Px_RX_ACTIVE_FIELD	6
+#define STV090x_WIDTH_Px_RX_ACTIVE_FIELD	1
+#define STV090x_OFFST_Px_SHORT_22KHZ_FIELD	5
+#define STV090x_WIDTH_Px_SHORT_22KHZ_FIELD	1
+#define STV090x_OFFST_Px_CONT_TONE_FIELD	4
+#define STV090x_WIDTH_Px_CONT_TONE_FIELD	1
+#define STV090x_OFFST_Px_FIFO_4BREADY_FIELD	3
+#define STV090x_WIDTH_Px_FIFO_4BREADY_FIELD	1
+#define STV090x_OFFST_Px_FIFO_EMPTY_FIELD	2
+#define STV090x_WIDTH_Px_FIFO_EMPTY_FIELD	1
+#define STV090x_OFFST_Px_ABORT_DISRX_FIELD	0
+#define STV090x_WIDTH_Px_ABORT_DISRX_FIELD	1
+
+#define STV090x_Px_DISRX_ST1(__x)		(0xf1a5 - (__x - 1) * 0x10)
+#define STV090x_P1_DISRX_ST1			STV090x_Px_DISRX_ST1(1)
+#define STV090x_P2_DISRX_ST1			STV090x_Px_DISRX_ST1(2)
+#define STV090x_OFFST_Px_RX_FAIL_FIELD		7
+#define STV090x_WIDTH_Px_RX_FAIL_FIELD		1
+#define STV090x_OFFST_Px_FIFO_PARITYFAIL_FIELD	6
+#define STV090x_WIDTH_Px_FIFO_PARITYFAIL_FIELD	1
+#define STV090x_OFFST_Px_RX_NONBYTE_FIELD	5
+#define STV090x_WIDTH_Px_RX_NONBYTE_FIELD	1
+#define STV090x_OFFST_Px_FIFO_OVERFLOW_FIELD	4
+#define STV090x_WIDTH_Px_FIFO_OVERFLOW_FIELD	1
+#define STV090x_OFFST_Px_FIFO_BYTENBR_FIELD	0
+#define STV090x_WIDTH_Px_FIFO_BYTENBR_FIELD	4
+
+#define STV090x_Px_DISRXDATA(__x)		(0xf1a6 - (__x - 1) * 0x10)
+#define STV090x_P1_DISRXDATA			STV090x_Px_DISRXDATA(1)
+#define STV090x_P2_DISRXDATA			STV090x_Px_DISRXDATA(2)
+#define STV090x_OFFST_Px_DISRX_DATA_FIELD	0
+#define STV090x_WIDTH_Px_DISRX_DATA_FIELD	8
+
+#define STV090x_Px_DISTXDATA(__x)		(0xf1a7 - (__x - 1) * 0x10)
+#define STV090x_P1_DISTXDATA			STV090x_Px_DISTXDATA(1)
+#define STV090x_P2_DISTXDATA			STV090x_Px_DISTXDATA(2)
+#define STV090x_OFFST_Px_DISEQC_FIFO_FIELD	0
+#define STV090x_WIDTH_Px_DISEQC_FIFO_FIELD	8
+
+#define STV090x_Px_DISTXSTATUS(__x)		(0xf1a8 - (__x - 1) * 0x10)
+#define STV090x_P1_DISTXSTATUS			STV090x_Px_DISTXSTATUS(1)
+#define STV090x_P2_DISTXSTATUS			STV090x_Px_DISTXSTATUS(2)
+#define STV090x_OFFST_Px_TX_FAIL_FIELD		7
+#define STV090x_WIDTH_Px_TX_FAIL_FIELD		1
+#define STV090x_OFFST_Px_FIFO_FULL_FIELD	6
+#define STV090x_WIDTH_Px_FIFO_FULL_FIELD	1
+#define STV090x_OFFST_Px_TX_IDLE_FIELD		5
+#define STV090x_WIDTH_Px_TX_IDLE_FIELD		1
+#define STV090x_OFFST_Px_GAP_BURST_FIELD	4
+#define STV090x_WIDTH_Px_GAP_BURST_FIELD	1
+#define STV090x_OFFST_Px_TXFIFO_BYTES_FIELD	0
+#define STV090x_WIDTH_Px_TXFIFO_BYTES_FIELD	4
+
+#define STV090x_Px_F22TX(__x)			(0xf1a9 - (__x - 1) * 0x10)
+#define STV090x_P1_F22TX			STV090x_Px_F22TX(1)
+#define STV090x_P2_F22TX			STV090x_Px_F22TX(2)
+#define STV090x_OFFST_Px_F22_REG_FIELD		0
+#define STV090x_WIDTH_Px_F22_REG_FIELD		8
+
+#define STV090x_Px_F22RX(__x)			(0xf1aa - (__x - 1) * 0x10)
+#define STV090x_P1_F22RX			STV090x_Px_F22RX(1)
+#define STV090x_P2_F22RX			STV090x_Px_F22RX(2)
+#define STV090x_OFFST_Px_F22RX_REG_FIELD	0
+#define STV090x_WIDTH_Px_F22RX_REG_FIELD	8
+
+#define STV090x_Px_ACRPRESC(__x)		(0xf1ac - (__x - 1) * 0x10)
+#define STV090x_P1_ACRPRESC			STV090x_Px_ACRPRESC(1)
+#define STV090x_P2_ACRPRESC			STV090x_Px_ACRPRESC(2)
+#define STV090x_OFFST_Px_ACR_PRESC_FIELD	0
+#define STV090x_WIDTH_Px_ACR_PRESC_FIELD	3
+
+#define STV090x_Px_ACRDIV(__x)			(0xf1ad - (__x - 1) * 0x10)
+#define STV090x_P1_ACRDIV			STV090x_Px_ACRDIV(1)
+#define STV090x_P2_ACRDIV			STV090x_Px_ACRDIV(2)
+#define STV090x_OFFST_Px_ACR_DIV_FIELD		0
+#define STV090x_WIDTH_Px_ACR_DIV_FIELD		8
+
+#define STV090x_Px_IQCONST(__x)			(0xF400 - (__x - 1) * 0x200)
+#define STV090x_P1_IQCONST			STV090x_Px_IQCONST(1)
+#define STV090x_P2_IQCONST			STV090x_Px_IQCONST(2)
+#define STV090x_OFFST_Px_CONSTEL_SELECT_FIELD	5
+#define STV090x_WIDTH_Px_CONSTEL_SELECT_FIELD	2
+
+#define STV090x_Px_NOSCFG(__x)			(0xF401 - (__x - 1) * 0x200)
+#define STV090x_P1_NOSCFG			STV090x_Px_NOSCFG(1)
+#define STV090x_P2_NOSCFG			STV090x_Px_NOSCFG(2)
+#define STV090x_OFFST_Px_NOSPLH_BETA_FIELD	3
+#define STV090x_WIDTH_Px_NOSPLH_BETA_FIELD	2
+#define STV090x_OFFST_Px_NOSDATA_BETA_FIELD	0
+#define STV090x_WIDTH_Px_NOSDATA_BETA_FIELD	3
+
+#define STV090x_Px_ISYMB(__x)			(0xF402 - (__x - 1) * 0x200)
+#define STV090x_P1_ISYMB			STV090x_Px_ISYMB(1)
+#define STV090x_P2_ISYMB			STV090x_Px_ISYMB(2)
+#define STV090x_OFFST_Px_I_SYMBOL_FIELD		0
+#define STV090x_WIDTH_Px_I_SYMBOL_FIELD		8
+
+#define STV090x_Px_QSYMB(__x)			(0xF403 - (__x - 1) * 0x200)
+#define STV090x_P1_QSYMB			STV090x_Px_QSYMB(1)
+#define STV090x_P2_QSYMB			STV090x_Px_QSYMB(2)
+#define STV090x_OFFST_Px_Q_SYMBOL_FIELD		0
+#define STV090x_WIDTH_Px_Q_SYMBOL_FIELD		8
+
+#define STV090x_Px_AGC1CFG(__x)			(0xF404 - (__x - 1) * 0x200)
+#define STV090x_P1_AGC1CFG			STV090x_Px_AGC1CFG(1)
+#define STV090x_P2_AGC1CFG			STV090x_Px_AGC1CFG(2)
+#define STV090x_OFFST_Px_DC_FROZEN_FIELD	7
+#define STV090x_WIDTH_Px_DC_FROZEN_FIELD	1
+#define STV090x_OFFST_Px_DC_CORRECT_FIELD	6
+#define STV090x_WIDTH_Px_DC_CORRECT_FIELD	1
+#define STV090x_OFFST_Px_AMM_FROZEN_FIELD	5
+#define STV090x_WIDTH_Px_AMM_FROZEN_FIELD	1
+#define STV090x_OFFST_Px_AMM_CORRECT_FIELD	4
+#define STV090x_WIDTH_Px_AMM_CORRECT_FIELD	1
+#define STV090x_OFFST_Px_QUAD_FROZEN_FIELD	3
+#define STV090x_WIDTH_Px_QUAD_FROZEN_FIELD	1
+#define STV090x_OFFST_Px_QUAD_CORRECT_FIELD	2
+#define STV090x_WIDTH_Px_QUAD_CORRECT_FIELD	1
+
+#define STV090x_Px_AGC1CN(__x)			(0xF406 - (__x - 1) * 0x200)
+#define STV090x_P1_AGC1CN			STV090x_Px_AGC1CN(1)
+#define STV090x_P2_AGC1CN			STV090x_Px_AGC1CN(2)
+#define STV090x_WIDTH_Px_AGC1_LOCKED_FIELD	7
+#define STV090x_OFFST_Px_AGC1_LOCKED_FIELD	1
+#define STV090x_OFFST_Px_AGC1_MINPOWER_FIELD	4
+#define STV090x_WIDTH_Px_AGC1_MINPOWER_FIELD	1
+#define STV090x_OFFST_Px_AGCOUT_FAST_FIELD	3
+#define STV090x_WIDTH_Px_AGCOUT_FAST_FIELD	1
+#define STV090x_OFFST_Px_AGCIQ_BETA_FIELD	0
+#define STV090x_WIDTH_Px_AGCIQ_BETA_FIELD	3
+
+#define STV090x_Px_AGC1REF(__x)			(0xF407 - (__x - 1) * 0x200)
+#define STV090x_P1_AGC1REF			STV090x_Px_AGC1REF(1)
+#define STV090x_P2_AGC1REF			STV090x_Px_AGC1REF(2)
+#define STV090x_OFFST_Px_AGCIQ_REF_FIELD	0
+#define STV090x_WIDTH_Px_AGCIQ_REF_FIELD	8
+
+#define STV090x_Px_IDCCOMP(__x)			(0xF408 - (__x - 1) * 0x200)
+#define STV090x_P1_IDCCOMP			STV090x_Px_IDCCOMP(1)
+#define STV090x_P2_IDCCOMP			STV090x_Px_IDCCOMP(2)
+#define STV090x_OFFST_Px_IAVERAGE_ADJ_FIELD	0
+#define STV090x_WIDTH_Px_IAVERAGE_ADJ_FIELD	8
+
+#define STV090x_Px_QDCCOMP(__x)			(0xF409 - (__x - 1) * 0x200)
+#define STV090x_P1_QDCCOMP			STV090x_Px_QDCCOMP(1)
+#define STV090x_P2_QDCCOMP			STV090x_Px_QDCCOMP(2)
+#define STV090x_OFFST_Px_QAVERAGE_ADJ_FIELD	0
+#define STV090x_WIDTH_Px_QAVERAGE_ADJ_FIELD	8
+
+#define STV090x_Px_POWERI(__x)			(0xF40A - (__x - 1) * 0x200)
+#define STV090x_P1_POWERI			STV090x_Px_POWERI(1)
+#define STV090x_P2_POWERI			STV090x_Px_POWERI(2)
+#define STV090x_OFFST_Px_POWER_I_FIELD		0
+#define STV090x_WIDTH_Px_POWER_I_FIELD		8
+
+#define STV090x_Px_POWERQ(__x)			(0xF40B - (__x - 1) * 0x200)
+#define STV090x_P1_POWERQ			STV090x_Px_POWERQ(1)
+#define STV090x_P2_POWERQ			STV090x_Px_POWERQ(2)
+#define STV090x_OFFST_Px_POWER_Q_FIELD		0
+#define STV090x_WIDTH_Px_POWER_Q_FIELD		8
+
+#define STV090x_Px_AGC1AMM(__x)			(0xF40C - (__x - 1) * 0x200)
+#define STV090x_P1_AGC1AMM			STV090x_Px_AGC1AMM(1)
+#define STV090x_P2_AGC1AMM			STV090x_Px_AGC1AMM(2)
+#define STV090x_OFFST_Px_AMM_VALUE_FIELD	0
+#define STV090x_WIDTH_Px_AMM_VALUE_FIELD	8
+
+#define STV090x_Px_AGC1QUAD(__x)		(0xF40D - (__x - 1) * 0x200)
+#define STV090x_P1_AGC1QUAD			STV090x_Px_AGC1QUAD(1)
+#define STV090x_P2_AGC1QUAD			STV090x_Px_AGC1QUAD(2)
+#define STV090x_OFFST_Px_QUAD_VALUE_FIELD	0
+#define STV090x_WIDTH_Px_QUAD_VALUE_FIELD	8
+
+#define STV090x_Px_AGCIQINy(__x, __y)		(0xF40F - (__x-1) * 0x200 - __y * 0x1)
+#define STV090x_P1_AGCIQIN0			STV090x_Px_AGCIQINy(1, 0)
+#define STV090x_P1_AGCIQIN1			STV090x_Px_AGCIQINy(1, 1)
+#define STV090x_P2_AGCIQIN0			STV090x_Px_AGCIQINy(2, 0)
+#define STV090x_P2_AGCIQIN1			STV090x_Px_AGCIQINy(2, 1)
+#define STV090x_OFFST_Px_AGCIQ_VALUE_FIELD	0
+#define STV090x_WIDTH_Px_AGCIQ_VALUE_FIELD	8
+
+#define STV090x_Px_DEMOD(__x)			(0xF410 - (__x - 1) * 0x200)
+#define STV090x_P1_DEMOD			STV090x_Px_DEMOD(1)
+#define STV090x_P2_DEMOD			STV090x_Px_DEMOD(2)
+#define STV090x_OFFST_Px_MANUAL_S2ROLLOFF_FIELD	7
+#define STV090x_WIDTH_Px_MANUAL_S2ROLLOFF_FIELD	1
+#define STV090x_OFFST_Px_DEMOD_STOP_FIELD	6
+#define STV090x_WIDTH_Px_DEMOD_STOP_FIELD	1
+#define STV090x_OFFST_Px_SPECINV_CONTROL_FIELD	4
+#define STV090x_WIDTH_Px_SPECINV_CONTROL_FIELD	2
+#define STV090x_OFFST_Px_FORCE_ENASAMP_FIELD	3
+#define STV090x_WIDTH_Px_FORCE_ENASAMP_FIELD	1
+#define STV090x_OFFST_Px_MANUAL_SXROLLOFF_FIELD	2
+#define STV090x_WIDTH_Px_MANUAL_SXROLLOFF_FIELD	1
+#define STV090x_OFFST_Px_ROLLOFF_CONTROL_FIELD	0
+#define STV090x_WIDTH_Px_ROLLOFF_CONTROL_FIELD	2
+
+#define STV090x_Px_DMDMODCOD(__x)		(0xF411 - (__x - 1) * 0x200)
+#define STV090x_P1_DMDMODCOD			STV090x_Px_DMDMODCOD(1)
+#define STV090x_P2_DMDMODCOD			STV090x_Px_DMDMODCOD(2)
+#define STV090x_OFFST_Px_MANUAL_MODCOD_FIELD	7
+#define STV090x_WIDTH_Px_MANUAL_MODCOD_FIELD	1
+#define STV090x_OFFST_Px_DEMOD_MODCOD_FIELD	2
+#define STV090x_WIDTH_Px_DEMOD_MODCOD_FIELD	5
+#define STV090x_OFFST_Px_DEMOD_TYPE_FIELD	0
+#define STV090x_WIDTH_Px_DEMOD_TYPE_FIELD	2
+
+#define STV090x_Px_DSTATUS(__x)			(0xF412 - (__x - 1) * 0x200)
+#define STV090x_P1_DSTATUS			STV090x_Px_DSTATUS(1)
+#define STV090x_P2_DSTATUS			STV090x_Px_DSTATUS(2)
+#define STV090x_OFFST_Px_CAR_LOCK_FIELD		7
+#define STV090x_WIDTH_Px_CAR_LOCK_FIELD		1
+#define STV090x_OFFST_Px_TMGLOCK_QUALITY_FIELD	5
+#define STV090x_WIDTH_Px_TMGLOCK_QUALITY_FIELD	2
+#define STV090x_OFFST_Px_LOCK_DEFINITIF_FIELD	3
+#define STV090x_WIDTH_Px_LOCK_DEFINITIF_FIELD	1
+
+#define STV090x_Px_DSTATUS2(__x)		(0xF413 - (__x - 1) * 0x200)
+#define STV090x_P1_DSTATUS2			STV090x_Px_DSTATUS2(1)
+#define STV090x_P2_DSTATUS2			STV090x_Px_DSTATUS2(2)
+#define STV090x_OFFST_Px_DEMOD_DELOCK_FIELD	7
+#define STV090x_WIDTH_Px_DEMOD_DELOCK_FIELD	1
+#define STV090x_OFFST_Px_AGC1_NOSIGNALACK_FIELD	3
+#define STV090x_WIDTH_Px_AGC1_NOSIGNALACK_FIELD	1
+#define STV090x_OFFST_Px_AGC2_OVERFLOW_FIELD	2
+#define STV090x_WIDTH_Px_AGC2_OVERFLOW_FIELD	1
+#define STV090x_OFFST_Px_CFR_OVERFLOW_FIELD	1
+#define STV090x_WIDTH_Px_CFR_OVERFLOW_FIELD	1
+#define STV090x_OFFST_Px_GAMMA_OVERUNDER_FIELD	0
+#define STV090x_WIDTH_Px_GAMMA_OVERUNDER_FIELD	1
+
+#define STV090x_Px_DMDCFGMD(__x)		(0xF414 - (__x - 1) * 0x200)
+#define STV090x_P1_DMDCFGMD			STV090x_Px_DMDCFGMD(1)
+#define STV090x_P2_DMDCFGMD			STV090x_Px_DMDCFGMD(2)
+#define STV090x_OFFST_Px_DVBS2_ENABLE_FIELD	7
+#define STV090x_WIDTH_Px_DVBS2_ENABLE_FIELD	1
+#define STV090x_OFFST_Px_DVBS1_ENABLE_FIELD	6
+#define STV090x_WIDTH_Px_DVBS1_ENABLE_FIELD	1
+#define STV090x_OFFST_Px_SCAN_ENABLE_FIELD	4
+#define STV090x_WIDTH_Px_SCAN_ENABLE_FIELD	1
+#define STV090x_OFFST_Px_CFR_AUTOSCAN_FIELD	3
+#define STV090x_WIDTH_Px_CFR_AUTOSCAN_FIELD	1
+#define STV090x_OFFST_Px_NOFORCE_RELOCK_FIELD	2
+#define STV090x_WIDTH_Px_NOFORCE_RELOCK_FIELD	1
+#define STV090x_OFFST_Px_TUN_RNG_FIELD		0
+#define STV090x_WIDTH_Px_TUN_RNG_FIELD		2
+
+#define STV090x_Px_DMDCFG2(__x)			(0xF415 - (__x - 1) * 0x200)
+#define STV090x_P1_DMDCFG2			STV090x_Px_DMDCFG2(1)
+#define STV090x_P2_DMDCFG2			STV090x_Px_DMDCFG2(2)
+#define STV090x_OFFST_Px_S1S2_SEQUENTIAL_FIELD	6
+#define STV090x_WIDTH_Px_S1S2_SEQUENTIAL_FIELD	1
+
+#define STV090x_Px_DMDISTATE(__x)		(0xF416 - (__x - 1) * 0x200)
+#define STV090x_P1_DMDISTATE			STV090x_Px_DMDISTATE(1)
+#define STV090x_P2_DMDISTATE			STV090x_Px_DMDISTATE(2)
+#define STV090x_OFFST_Px_I2C_DEMOD_MODE_FIELD	0
+#define STV090x_WIDTH_Px_I2C_DEMOD_MODE_FIELD	5
+
+#define STV090x_Px_DMDTOM(__x)			(0xF417 - (__x - 1) * 0x200) /* check */
+#define STV090x_P1_DMDTOM			STV090x_Px_DMDTOM(1)
+#define STV090x_P2_DMDTOM			STV090x_Px_DMDTOM(2)
+
+#define STV090x_Px_DMDSTATE(__x)		(0xF41B - (__x - 1) * 0x200)
+#define STV090x_P1_DMDSTATE			STV090x_Px_DMDSTATE(1)
+#define STV090x_P2_DMDSTATE			STV090x_Px_DMDSTATE(2)
+#define STV090x_OFFST_Px_HEADER_MODE_FIELD	5
+#define STV090x_WIDTH_Px_HEADER_MODE_FIELD	2
+
+#define STV090x_Px_DMDFLYW(__x)			(0xF41C - (__x - 1) * 0x200)
+#define STV090x_P1_DMDFLYW			STV090x_Px_DMDFLYW(1)
+#define STV090x_P2_DMDFLYW			STV090x_Px_DMDFLYW(2)
+#define STV090x_OFFST_Px_I2C_IRQVAL_FIELD	4
+#define STV090x_WIDTH_Px_I2C_IRQVAL_FIELD	4
+#define STV090x_OFFST_Px_FLYWHEEL_CPT_FIELD	0
+#define STV090x_WIDTH_Px_FLYWHEEL_CPT_FIELD	4
+
+#define STV090x_Px_DSTATUS3(__x)		(0xF41D - (__x - 1) * 0x200)
+#define STV090x_P1_DSTATUS3			STV090x_Px_DSTATUS3(1)
+#define STV090x_P2_DSTATUS3			STV090x_Px_DSTATUS3(2)
+#define STV090x_OFFST_Px_DEMOD_CFGMODE_FIELD	5
+#define STV090x_WIDTH_Px_DEMOD_CFGMODE_FIELD	2
+
+#define STV090x_Px_DMDCFG3(__x)			(0xF41E - (__x - 1) * 0x200)
+#define STV090x_P1_DMDCFG3			STV090x_Px_DMDCFG3(1)
+#define STV090x_P2_DMDCFG3			STV090x_Px_DMDCFG3(2)
+#define STV090x_OFFST_Px_NOSTOP_FIFOFULL_FIELD	3
+#define STV090x_WIDTH_Px_NOSTOP_FIFOFULL_FIELD	1
+
+#define STV090x_Px_DMDCFG4(__x)			(0xf41f - (__x - 1) * 0x200)
+#define STV090x_P1_DMDCFG4			STV090x_Px_DMDCFG4(1)
+#define STV090x_P2_DMDCFG4			STV090x_Px_DMDCFG4(2)
+
+#define STV090x_Px_CORRELMANT(__x)		(0xF420 - (__x - 1) * 0x200)
+#define STV090x_P1_CORRELMANT			STV090x_Px_CORRELMANT(1)
+#define STV090x_P2_CORRELMANT			STV090x_Px_CORRELMANT(2)
+#define STV090x_OFFST_Px_CORREL_MANT_FIELD	0
+#define STV090x_WIDTH_Px_CORREL_MANT_FIELD	8
+
+#define STV090x_Px_CORRELABS(__x)		(0xF421 - (__x - 1) * 0x200)
+#define STV090x_P1_CORRELABS			STV090x_Px_CORRELABS(1)
+#define STV090x_P2_CORRELABS			STV090x_Px_CORRELABS(2)
+#define STV090x_OFFST_Px_CORREL_ABS_FIELD	0
+#define STV090x_WIDTH_Px_CORREL_ABS_FIELD	8
+
+#define STV090x_Px_CORRELEXP(__x)		(0xF422 - (__x - 1) * 0x200)
+#define STV090x_P1_CORRELEXP			STV090x_Px_CORRELEXP(1)
+#define STV090x_P2_CORRELEXP			STV090x_Px_CORRELEXP(2)
+#define STV090x_OFFST_Px_CORREL_ABSEXP_FIELD	4
+#define STV090x_WIDTH_Px_CORREL_ABSEXP_FIELD	4
+#define STV090x_OFFST_Px_CORREL_EXP_FIELD	0
+#define STV090x_WIDTH_Px_CORREL_EXP_FIELD	4
+
+#define STV090x_Px_PLHMODCOD(__x)		(0xF424 - (__x - 1) * 0x200)
+#define STV090x_P1_PLHMODCOD			STV090x_Px_PLHMODCOD(1)
+#define STV090x_P2_PLHMODCOD			STV090x_Px_PLHMODCOD(2)
+#define STV090x_OFFST_Px_SPECINV_DEMOD_FIELD	7
+#define STV090x_WIDTH_Px_SPECINV_DEMOD_FIELD	1
+#define STV090x_OFFST_Px_PLH_MODCOD_FIELD	2
+#define STV090x_WIDTH_Px_PLH_MODCOD_FIELD	5
+#define STV090x_OFFST_Px_PLH_TYPE_FIELD		0
+#define STV090x_WIDTH_Px_PLH_TYPE_FIELD		2
+
+#define STV090x_Px_AGCK32(__x)			(0xf42b - (__x - 1) * 0x200)
+#define STV090x_P1_AGCK32			STV090x_Px_AGCK32(1)
+#define STV090x_P2_AGCK32			STV090x_Px_AGCK32(2)
+
+#define STV090x_Px_AGC2O(__x)			(0xF42C - (__x - 1) * 0x200)
+#define STV090x_P1_AGC2O			STV090x_Px_AGC2O(1)
+#define STV090x_P2_AGC2O			STV090x_Px_AGC2O(2)
+
+#define STV090x_Px_AGC2REF(__x)			(0xF42D - (__x - 1) * 0x200)
+#define STV090x_P1_AGC2REF			STV090x_Px_AGC2REF(1)
+#define STV090x_P2_AGC2REF			STV090x_Px_AGC2REF(2)
+#define STV090x_OFFST_Px_AGC2_REF_FIELD		0
+#define STV090x_WIDTH_Px_AGC2_REF_FIELD		8
+
+#define STV090x_Px_AGC1ADJ(__x)			(0xF42E - (__x - 1) * 0x200)
+#define STV090x_P1_AGC1ADJ			STV090x_Px_AGC1ADJ(1)
+#define STV090x_P2_AGC1ADJ			STV090x_Px_AGC1ADJ(2)
+#define STV090x_OFFST_Px_AGC1_ADJUSTED_FIELD	0
+#define STV090x_WIDTH_Px_AGC1_ADJUSTED_FIELD	7
+
+#define STV090x_Px_AGC2Iy(__x, __y)		(0xF437 - (__x - 1) * 0x200 - __y * 0x1)
+#define STV090x_P1_AGC2I0			STV090x_Px_AGC2Iy(1, 0)
+#define STV090x_P1_AGC2I1			STV090x_Px_AGC2Iy(1, 1)
+#define STV090x_P2_AGC2I0			STV090x_Px_AGC2Iy(2, 0)
+#define STV090x_P2_AGC2I1			STV090x_Px_AGC2Iy(2, 1)
+#define STV090x_OFFST_Px_AGC2_INTEGRATOR_FIELD	0
+#define STV090x_WIDTH_Px_AGC2_INTEGRATOR_FIELD	8
+
+#define STV090x_Px_CARCFG(__x)			(0xF438 - (__x - 1) * 0x200)
+#define STV090x_P1_CARCFG			STV090x_Px_CARCFG(1)
+#define STV090x_P2_CARCFG			STV090x_Px_CARCFG(2)
+#define STV090x_OFFST_Px_EN_CAR2CENTER_FIELD	5
+#define STV090x_WIDTH_Px_EN_CAR2CENTER_FIELD	1
+#define STV090x_OFFST_Px_ROTATON_FIELD		2
+#define STV090x_WIDTH_Px_ROTATON_FIELD		1
+#define STV090x_OFFST_Px_PH_DET_ALGO_FIELD	0
+#define STV090x_WIDTH_Px_PH_DET_ALGO_FIELD	2
+
+#define STV090x_Px_ACLC(__x)			(0xF439 - (__x - 1) * 0x200)
+#define STV090x_P1_ACLC				STV090x_Px_ACLC(1)
+#define STV090x_P2_ACLC				STV090x_Px_ACLC(2)
+#define STV090x_OFFST_Px_CAR_ALPHA_MANT_FIELD	4
+#define STV090x_WIDTH_Px_CAR_ALPHA_MANT_FIELD	2
+#define STV090x_OFFST_Px_CAR_ALPHA_EXP_FIELD	0
+#define STV090x_WIDTH_Px_CAR_ALPHA_EXP_FIELD	4
+
+#define STV090x_Px_BCLC(__x)			(0xF43A - (__x - 1) * 0x200)
+#define STV090x_P1_BCLC				STV090x_Px_BCLC(1)
+#define STV090x_P2_BCLC				STV090x_Px_BCLC(2)
+#define STV090x_OFFST_Px_CAR_BETA_MANT_FIELD	4
+#define STV090x_WIDTH_Px_CAR_BETA_MANT_FIELD	2
+#define STV090x_OFFST_Px_CAR_BETA_EXP_FIELD	0
+#define STV090x_WIDTH_Px_CAR_BETA_EXP_FIELD	4
+
+#define STV090x_Px_CARFREQ(__x)			(0xF43D - (__x - 1) * 0x200)
+#define STV090x_P1_CARFREQ			STV090x_Px_CARFREQ(1)
+#define STV090x_P2_CARFREQ			STV090x_Px_CARFREQ(2)
+#define STV090x_OFFST_Px_KC_COARSE_EXP_FIELD	4
+#define STV090x_WIDTH_Px_KC_COARSE_EXP_FIELD	4
+#define STV090x_OFFST_Px_BETA_FREQ_FIELD	0
+#define STV090x_WIDTH_Px_BETA_FREQ_FIELD	4
+
+#define STV090x_Px_CARHDR(__x)			(0xF43E - (__x - 1) * 0x200)
+#define STV090x_P1_CARHDR			STV090x_Px_CARHDR(1)
+#define STV090x_P2_CARHDR			STV090x_Px_CARHDR(2)
+#define STV090x_OFFST_Px_FREQ_HDR_FIELD		0
+#define STV090x_WIDTH_Px_FREQ_HDR_FIELD		8
+
+#define STV090x_Px_LDT(__x)			(0xF43F - (__x - 1) * 0x200)
+#define STV090x_P1_LDT				STV090x_Px_LDT(1)
+#define STV090x_P2_LDT				STV090x_Px_LDT(2)
+#define STV090x_OFFST_Px_CARLOCK_THRES_FIELD	0
+#define STV090x_WIDTH_Px_CARLOCK_THRES_FIELD	8
+
+#define STV090x_Px_LDT2(__x)			(0xF440 - (__x - 1) * 0x200)
+#define STV090x_P1_LDT2				STV090x_Px_LDT2(1)
+#define STV090x_P2_LDT2				STV090x_Px_LDT2(2)
+#define STV090x_OFFST_Px_CARLOCK_THRES2_FIELD	0
+#define STV090x_WIDTH_Px_CARLOCK_THRES2_FIELD	8
+
+#define STV090x_Px_CFRICFG(__x)			(0xF441 - (__x - 1) * 0x200)
+#define STV090x_P1_CFRICFG			STV090x_Px_CFRICFG(1)
+#define STV090x_P2_CFRICFG			STV090x_Px_CFRICFG(2)
+#define STV090x_OFFST_Px_NEG_CFRSTEP_FIELD	0
+#define STV090x_WIDTH_Px_NEG_CFRSTEP_FIELD	1
+
+#define STV090x_Pn_CFRUPy(__x, __y)		(0xF443 - (__x - 1) * 0x200 - __y * 0x1)
+#define STV090x_P1_CFRUP0			STV090x_Pn_CFRUPy(1, 0)
+#define STV090x_P1_CFRUP1			STV090x_Pn_CFRUPy(1, 1)
+#define STV090x_P2_CFRUP0			STV090x_Pn_CFRUPy(2, 0)
+#define STV090x_P2_CFRUP1			STV090x_Pn_CFRUPy(2, 1)
+#define STV090x_OFFST_Px_CFR_UP_FIELD		0
+#define STV090x_WIDTH_Px_CFR_UP_FIELD		8
+
+#define STV090x_Pn_CFRLOWy(__x, __y)		(0xF447 - (__x - 1) * 0x200 - __y * 0x1)
+#define STV090x_P1_CFRLOW0			STV090x_Pn_CFRLOWy(1, 0)
+#define STV090x_P1_CFRLOW1			STV090x_Pn_CFRLOWy(1, 1)
+#define STV090x_P2_CFRLOW0			STV090x_Pn_CFRLOWy(2, 0)
+#define STV090x_P2_CFRLOW1			STV090x_Pn_CFRLOWy(2, 1)
+#define STV090x_OFFST_Px_CFR_LOW_FIELD		0
+#define STV090x_WIDTH_Px_CFR_LOW_FIELD		8
+
+#define STV090x_Pn_CFRINITy(__x, __y)		(0xF449 - (__x - 1) * 0x200 - __y * 0x1)
+#define STV090x_P1_CFRINIT0			STV090x_Pn_CFRINITy(1, 0)
+#define STV090x_P1_CFRINIT1			STV090x_Pn_CFRINITy(1, 1)
+#define STV090x_P2_CFRINIT0			STV090x_Pn_CFRINITy(2, 0)
+#define STV090x_P2_CFRINIT1			STV090x_Pn_CFRINITy(2, 1)
+#define STV090x_OFFST_Px_CFR_INIT_FIELD		0
+#define STV090x_WIDTH_Px_CFR_INIT_FIELD		8
+
+#define STV090x_Px_CFRINC1(__x)			(0xF44A - (__x - 1) * 0x200)
+#define STV090x_P1_CFRINC1			STV090x_Px_CFRINC1(1)
+#define STV090x_P2_CFRINC1			STV090x_Px_CFRINC1(2)
+#define STV090x_OFFST_Px_CFR_INC1_FIELD		0
+#define STV090x_WIDTH_Px_CFR_INC1_FIELD		7 /* check */
+
+#define STV090x_Px_CFRINC0(__x)			(0xF44B - (__x - 1) * 0x200)
+#define STV090x_P1_CFRINC0			STV090x_Px_CFRINC0(1)
+#define STV090x_P2_CFRINC0			STV090x_Px_CFRINC0(2)
+#define STV090x_OFFST_Px_CFR_INC0_FIELD		4 /* check */
+#define STV090x_WIDTH_Px_CFR_INC0_FIELD		4
+
+#define STV090x_Pn_CFRy(__x, __y)		(0xF44E - (__x - 1) * 0x200 - __y * 0x1)
+#define STV090x_P1_CFR0				STV090x_Pn_CFRy(1, 0)
+#define STV090x_P1_CFR1				STV090x_Pn_CFRy(1, 1)
+#define STV090x_P1_CFR2				STV090x_Pn_CFRy(1, 2)
+#define STV090x_P2_CFR0				STV090x_Pn_CFRy(2, 0)
+#define STV090x_P2_CFR1				STV090x_Pn_CFRy(2, 1)
+#define STV090x_P2_CFR2				STV090x_Pn_CFRy(2, 2)
+#define STV090x_OFFST_Px_CAR_FREQ_FIELD		0
+#define STV090x_WIDTH_Px_CAR_FREQ_FIELD		8
+
+#define STV090x_Px_LDI(__x)			(0xF44F - (__x - 1) * 0x200)
+#define STV090x_P1_LDI				STV090x_Px_LDI(1)
+#define STV090x_P2_LDI				STV090x_Px_LDI(2)
+#define STV090x_OFFST_Px_LOCK_DET_INTEGR_FIELD	0
+#define STV090x_WIDTH_Px_LOCK_DET_INTEGR_FIELD	8
+
+#define STV090x_Px_TMGCFG(__x)			(0xF450 - (__x - 1) * 0x200)
+#define STV090x_P1_TMGCFG			STV090x_Px_TMGCFG(1)
+#define STV090x_P2_TMGCFG			STV090x_Px_TMGCFG(2)
+#define STV090x_OFFST_Px_TMGLOCK_BETA_FIELD	6
+#define STV090x_WIDTH_Px_TMGLOCK_BETA_FIELD	2
+#define STV090x_OFFST_Px_DO_TIMING_FIELD	4
+#define STV090x_WIDTH_Px_DO_TIMING_FIELD	1
+#define STV090x_OFFST_Px_TMG_MINFREQ_FIELD	0
+#define STV090x_WIDTH_Px_TMG_MINFREQ_FIELD	2
+
+#define STV090x_Px_RTC(__x)			(0xF451 - (__x - 1) * 0x200)
+#define STV090x_P1_RTC				STV090x_Px_RTC(1)
+#define STV090x_P2_RTC				STV090x_Px_RTC(2)
+#define STV090x_OFFST_Px_TMGALPHA_EXP_FIELD	4
+#define STV090x_WIDTH_Px_TMGALPHA_EXP_FIELD	4
+#define STV090x_OFFST_Px_TMGBETA_EXP_FIELD	0
+#define STV090x_WIDTH_Px_TMGBETA_EXP_FIELD	4
+
+#define STV090x_Px_RTCS2(__x)			(0xF452 - (__x - 1) * 0x200)
+#define STV090x_P1_RTCS2			STV090x_Px_RTCS2(1)
+#define STV090x_P2_RTCS2			STV090x_Px_RTCS2(2)
+#define STV090x_OFFST_Px_TMGALPHAS2_EXP_FIELD	4
+#define STV090x_WIDTH_Px_TMGALPHAS2_EXP_FIELD	4
+#define STV090x_OFFST_Px_TMGBETAS2_EXP_FIELD	0
+#define STV090x_WIDTH_Px_TMGBETAS2_EXP_FIELD	4
+
+#define STV090x_Px_TMGTHRISE(__x)		(0xF453 - (__x - 1) * 0x200)
+#define STV090x_P1_TMGTHRISE			STV090x_Px_TMGTHRISE(1)
+#define STV090x_P2_TMGTHRISE			STV090x_Px_TMGTHRISE(2)
+#define STV090x_OFFST_Px_TMGLOCK_THRISE_FIELD	0
+#define STV090x_WIDTH_Px_TMGLOCK_THRISE_FIELD	8
+
+#define STV090x_Px_TMGTHFALL(__x)		(0xF454 - (__x - 1) * 0x200)
+#define STV090x_P1_TMGTHFALL			STV090x_Px_TMGTHFALL(1)
+#define STV090x_P2_TMGTHFALL			STV090x_Px_TMGTHFALL(2)
+#define STV090x_OFFST_Px_TMGLOCK_THFALL_FIELD	0
+#define STV090x_WIDTH_Px_TMGLOCK_THFALL_FIELD	8
+
+#define STV090x_Px_SFRUPRATIO(__x)		(0xF455 - (__x - 1) * 0x200)
+#define STV090x_P1_SFRUPRATIO			STV090x_Px_SFRUPRATIO(1)
+#define STV090x_P2_SFRUPRATIO			STV090x_Px_SFRUPRATIO(2)
+#define STV090x_OFFST_Px_SFR_UPRATIO_FIELD	0
+#define STV090x_WIDTH_Px_SFR_UPRATIO_FIELD	8
+
+#define STV090x_Px_SFRLOWRATIO(__x)		(0xF456 - (__x - 1) * 0x200)
+#define STV090x_P1_SFRLOWRATIO			STV090x_Px_SFRLOWRATIO(1)
+#define STV090x_P2_SFRLOWRATIO			STV090x_Px_SFRLOWRATIO(2)
+#define STV090x_OFFST_Px_SFR_LOWRATIO_FIELD	0
+#define STV090x_WIDTH_Px_SFR_LOWRATIO_FIELD	8
+
+#define STV090x_Px_KREFTMG(__x)			(0xF458 - (__x - 1) * 0x200)
+#define STV090x_P1_KREFTMG			STV090x_Px_KREFTMG(1)
+#define STV090x_P2_KREFTMG			STV090x_Px_KREFTMG(2)
+#define STV090x_OFFST_Px_KREF_TMG_FIELD		0
+#define STV090x_WIDTH_Px_KREF_TMG_FIELD		8
+
+#define STV090x_Px_SFRSTEP(__x)			(0xF459 - (__x - 1) * 0x200)
+#define STV090x_P1_SFRSTEP			STV090x_Px_SFRSTEP(1)
+#define STV090x_P2_SFRSTEP			STV090x_Px_SFRSTEP(2)
+#define STV090x_OFFST_Px_SFR_SCANSTEP_FIELD	4
+#define STV090x_WIDTH_Px_SFR_SCANSTEP_FIELD	4
+#define STV090x_OFFST_Px_SFR_CENTERSTEP_FIELD	0
+#define STV090x_WIDTH_Px_SFR_CENTERSTEP_FIELD	4
+
+#define STV090x_Px_TMGCFG2(__x)			(0xF45A - (__x - 1) * 0x200)
+#define STV090x_P1_TMGCFG2			STV090x_Px_TMGCFG2(1)
+#define STV090x_P2_TMGCFG2			STV090x_Px_TMGCFG2(2)
+#define STV090x_OFFST_Px_SFRRATIO_FINE_FIELD	0
+#define STV090x_WIDTH_Px_SFRRATIO_FINE_FIELD	1
+
+#define STV090x_Px_SFRINIT1(__x)		(0xF45E - (__x - 1) * 0x200)
+#define STV090x_P1_SFRINIT1			STV090x_Px_SFRINIT1(1)
+#define STV090x_P2_SFRINIT1			STV090x_Px_SFRINIT1(2)
+#define STV090x_OFFST_Px_SFR_INIT1_FIELD	0
+#define STV090x_WIDTH_Px_SFR_INIT1_FIELD	7
+
+#define STV090x_Px_SFRINIT0(__x)		(0xF45F - (__x - 1) * 0x200)
+#define STV090x_P1_SFRINIT0			STV090x_Px_SFRINIT0(1)
+#define STV090x_P2_SFRINIT0			STV090x_Px_SFRINIT0(2)
+#define STV090x_OFFST_Px_SFR_INIT0_FIELD	0
+#define STV090x_WIDTH_Px_SFR_INIT0_FIELD	8
+
+#define STV090x_Px_SFRUP1(__x)			(0xF460 - (__x - 1) * 0x200)
+#define STV090x_P1_SFRUP1			STV090x_Px_SFRUP1(1)
+#define STV090x_P2_SFRUP1			STV090x_Px_SFRUP1(2)
+#define STV090x_OFFST_Px_SYMB_FREQ_UP1_FIELD	0
+#define STV090x_WIDTH_Px_SYMB_FREQ_UP1_FIELD	7
+
+#define STV090x_Px_SFRUP0(__x)			(0xF461 - (__x - 1) * 0x200)
+#define STV090x_P1_SFRUP0			STV090x_Px_SFRUP0(1)
+#define STV090x_P2_SFRUP0			STV090x_Px_SFRUP0(2)
+#define STV090x_OFFST_Px_SYMB_FREQ_UP0_FIELD	0
+#define STV090x_WIDTH_Px_SYMB_FREQ_UP0_FIELD	8
+
+#define STV090x_Px_SFRLOW1(__x)			(0xF462 - (__x - 1) * 0x200)
+#define STV090x_P1_SFRLOW1			STV090x_Px_SFRLOW1(1)
+#define STV090x_P2_SFRLOW1			STV090x_Px_SFRLOW1(2)
+#define STV090x_OFFST_Px_SYMB_FREQ_LOW1_FIELD	0
+#define STV090x_WIDTH_Px_SYMB_FREQ_LOW1_FIELD	7
+
+#define STV090x_Px_SFRLOW0(__x)			(0xF463 - (__x - 1) * 0x200)
+#define STV090x_P1_SFRLOW0			STV090x_Px_SFRLOW0(1)
+#define STV090x_P2_SFRLOW0			STV090x_Px_SFRLOW0(2)
+#define STV090x_OFFST_Px_SYMB_FREQ_LOW0_FIELD	0
+#define STV090x_WIDTH_Px_SYMB_FREQ_LOW0_FIELD	8
+
+#define STV090x_Px_SFRy(__x, __y)		(0xF467 - (__x-1) * 0x200 - __y)
+#define STV090x_P1_SFR0				STV090x_Px_SFRy(1, 0)
+#define STV090x_P1_SFR1				STV090x_Px_SFRy(1, 1)
+#define STV090x_P1_SFR2				STV090x_Px_SFRy(1, 2)
+#define STV090x_P1_SFR3				STV090x_Px_SFRy(1, 3)
+#define STV090x_P2_SFR0				STV090x_Px_SFRy(2, 0)
+#define STV090x_P2_SFR1				STV090x_Px_SFRy(2, 1)
+#define STV090x_P2_SFR2				STV090x_Px_SFRy(2, 2)
+#define STV090x_P2_SFR3				STV090x_Px_SFRy(2, 3)
+#define STV090x_OFFST_Px_SYMB_FREQ_FIELD	0
+#define STV090x_WIDTH_Px_SYMB_FREQ_FIELD	8
+
+#define STV090x_Px_TMGREG2(__x)			(0xF468 - (__x - 1) * 0x200)
+#define STV090x_P1_TMGREG2			STV090x_Px_TMGREG2(1)
+#define STV090x_P2_TMGREG2			STV090x_Px_TMGREG2(2)
+#define STV090x_OFFST_Px_TMGREG_FIELD		0
+#define STV090x_WIDTH_Px_TMGREG_FIELD		8
+
+#define STV090x_Px_TMGREG1(__x)			(0xF469 - (__x - 1) * 0x200)
+#define STV090x_P1_TMGREG1			STV090x_Px_TMGREG1(1)
+#define STV090x_P2_TMGREG1			STV090x_Px_TMGREG1(2)
+#define STV090x_OFFST_Px_TMGREG_FIELD		0
+#define STV090x_WIDTH_Px_TMGREG_FIELD		8
+
+#define STV090x_Px_TMGREG0(__x)			(0xF46A - (__x - 1) * 0x200)
+#define STV090x_P1_TMGREG0			STV090x_Px_TMGREG0(1)
+#define STV090x_P2_TMGREG0			STV090x_Px_TMGREG0(2)
+#define STV090x_OFFST_Px_TMGREG_FIELD		0
+#define STV090x_WIDTH_Px_TMGREG_FIELD		8
+
+#define STV090x_Px_TMGLOCKy(__x, __y)		(0xF46C - (__x - 1) * 0x200 - __y * 0x1)
+#define STV090x_P1_TMGLOCK0			STV090x_Px_TMGLOCKy(1, 0)
+#define STV090x_P1_TMGLOCK1			STV090x_Px_TMGLOCKy(1, 1)
+#define STV090x_P2_TMGLOCK0			STV090x_Px_TMGLOCKy(2, 0)
+#define STV090x_P2_TMGLOCK1			STV090x_Px_TMGLOCKy(2, 1)
+#define STV090x_OFFST_Px_TMGLOCK_LEVEL_FIELD	0
+#define STV090x_WIDTH_Px_TMGLOCK_LEVEL_FIELD	8
+
+#define STV090x_Px_TMGOBS(__x)			(0xF46D - (__x - 1) * 0x200)
+#define STV090x_P1_TMGOBS			STV090x_Px_TMGOBS(1)
+#define STV090x_P2_TMGOBS			STV090x_Px_TMGOBS(2)
+#define STV090x_OFFST_Px_ROLLOFF_STATUS_FIELD	6
+#define STV090x_WIDTH_Px_ROLLOFF_STATUS_FIELD	2
+
+#define STV090x_Px_EQUALCFG(__x)		(0xF46F - (__x - 1) * 0x200)
+#define STV090x_P1_EQUALCFG			STV090x_Px_EQUALCFG(1)
+#define STV090x_P2_EQUALCFG			STV090x_Px_EQUALCFG(2)
+#define STV090x_OFFST_Px_EQUAL_ON_FIELD		6
+#define STV090x_WIDTH_Px_EQUAL_ON_FIELD		1
+#define STV090x_OFFST_Px_MU_EQUALDFE_FIELD	0
+#define STV090x_WIDTH_Px_MU_EQUALDFE_FIELD	3
+
+#define STV090x_Px_EQUAIy(__x, __y)	(0xf470 - (__x-1) * 0x200 + 2 * (__y-1))
+#define STV090x_P1_EQUAI1			STV090x_Px_EQUAIy(1, 1)
+#define STV090x_P1_EQUAI2			STV090x_Px_EQUAIy(1, 2)
+#define STV090x_P1_EQUAI3			STV090x_Px_EQUAIy(1, 3)
+#define STV090x_P1_EQUAI4			STV090x_Px_EQUAIy(1, 4)
+#define STV090x_P1_EQUAI5			STV090x_Px_EQUAIy(1, 5)
+#define STV090x_P1_EQUAI6			STV090x_Px_EQUAIy(1, 6)
+#define STV090x_P1_EQUAI7			STV090x_Px_EQUAIy(1, 7)
+#define STV090x_P1_EQUAI8			STV090x_Px_EQUAIy(1, 8)
+
+#define STV090x_P2_EQUAI1			STV090x_Px_EQUAIy(2, 1)
+#define STV090x_P2_EQUAI2			STV090x_Px_EQUAIy(2, 2)
+#define STV090x_P2_EQUAI3			STV090x_Px_EQUAIy(2, 3)
+#define STV090x_P2_EQUAI4			STV090x_Px_EQUAIy(2, 4)
+#define STV090x_P2_EQUAI5			STV090x_Px_EQUAIy(2, 5)
+#define STV090x_P2_EQUAI6			STV090x_Px_EQUAIy(2, 6)
+#define STV090x_P2_EQUAI7			STV090x_Px_EQUAIy(2, 7)
+#define STV090x_P2_EQUAI8			STV090x_Px_EQUAIy(2, 8)
+#define STV090x_OFFST_Px_EQUA_ACCIy_FIELD	0
+#define STV090x_WIDTH_Px_EQUA_ACCIy_FIELD	8
+
+#define STV090x_Px_EQUAQy(__x, __y)	(0xf471 - (__x-1) * 0x200 + 2 * (__y-1))
+#define STV090x_P1_EQUAQ1			STV090x_Px_EQUAQy(1, 1)
+#define STV090x_P1_EQUAQ2			STV090x_Px_EQUAQy(1, 2)
+#define STV090x_P1_EQUAQ3			STV090x_Px_EQUAQy(1, 3)
+#define STV090x_P1_EQUAQ4			STV090x_Px_EQUAQy(1, 4)
+#define STV090x_P1_EQUAQ5			STV090x_Px_EQUAQy(1, 5)
+#define STV090x_P1_EQUAQ6			STV090x_Px_EQUAQy(1, 6)
+#define STV090x_P1_EQUAQ7			STV090x_Px_EQUAQy(1, 7)
+#define STV090x_P1_EQUAQ8			STV090x_Px_EQUAQy(1, 8)
+
+#define STV090x_P2_EQUAQ1			STV090x_Px_EQUAQy(2, 1)
+#define STV090x_P2_EQUAQ2			STV090x_Px_EQUAQy(2, 2)
+#define STV090x_P2_EQUAQ3			STV090x_Px_EQUAQy(2, 3)
+#define STV090x_P2_EQUAQ4			STV090x_Px_EQUAQy(2, 4)
+#define STV090x_P2_EQUAQ5			STV090x_Px_EQUAQy(2, 5)
+#define STV090x_P2_EQUAQ6			STV090x_Px_EQUAQy(2, 6)
+#define STV090x_P2_EQUAQ7			STV090x_Px_EQUAQy(2, 7)
+#define STV090x_P2_EQUAQ8			STV090x_Px_EQUAQy(2, 8)
+#define STV090x_OFFST_Px_EQUA_ACCQy_FIELD	0
+#define STV090x_WIDTH_Px_EQUA_ACCQy_FIELD	8
+
+#define STV090x_Px_NNOSDATATy(__x, __y)		(0xf481 - (__x - 1) * 0x200 - __y * 0x1)
+#define STV090x_P1_NNOSDATAT0			STV090x_Px_NNOSDATATy(1, 0)
+#define STV090x_P1_NNOSDATAT1			STV090x_Px_NNOSDATATy(1, 1)
+#define STV090x_P2_NNOSDATAT0			STV090x_Px_NNOSDATATy(2, 0)
+#define STV090x_P2_NNOSDATAT1			STV090x_Px_NNOSDATATy(2, 1)
+#define STV090x_OFFST_Px_NOSDATAT_NORMED_FIELD	0
+#define STV090x_WIDTH_Px_NOSDATAT_NORMED_FIELD	8
+
+#define STV090x_Px_NNOSDATAy(__x, __y)		(0xf483 - (__x - 1) * 0x200 - __y * 0x1)
+#define STV090x_P1_NNOSDATA0			STV090x_Px_NNOSDATAy(1, 0)
+#define STV090x_P1_NNOSDATA1			STV090x_Px_NNOSDATAy(1, 1)
+#define STV090x_P2_NNOSDATA0			STV090x_Px_NNOSDATAy(2, 0)
+#define STV090x_P2_NNOSDATA1			STV090x_Px_NNOSDATAy(2, 1)
+#define STV090x_OFFST_Px_NOSDATA_NORMED_FIELD	0
+#define STV090x_WIDTH_Px_NOSDATA_NORMED_FIELD	8
+
+#define STV090x_Px_NNOSPLHTy(__x, __y)		(0xf485 - (__x - 1) * 0x200 - __y * 0x1)
+#define STV090x_P1_NNOSPLHT0			STV090x_Px_NNOSPLHTy(1, 0)
+#define STV090x_P1_NNOSPLHT1			STV090x_Px_NNOSPLHTy(1, 1)
+#define STV090x_P2_NNOSPLHT0			STV090x_Px_NNOSPLHTy(2, 0)
+#define STV090x_P2_NNOSPLHT1			STV090x_Px_NNOSPLHTy(2, 1)
+#define STV090x_OFFST_Px_NOSPLHT_NORMED_FIELD	0
+#define STV090x_WIDTH_Px_NOSPLHT_NORMED_FIELD	8
+
+#define STV090x_Px_NNOSPLHy(__x, __y)		(0xf487 - (__x - 1) * 0x200 - __y * 0x1)
+#define STV090x_P1_NNOSPLH0			STV090x_Px_NNOSPLHy(1, 0)
+#define STV090x_P1_NNOSPLH1			STV090x_Px_NNOSPLHy(1, 1)
+#define STV090x_P2_NNOSPLH0			STV090x_Px_NNOSPLHy(2, 0)
+#define STV090x_P2_NNOSPLH1			STV090x_Px_NNOSPLHy(2, 1)
+#define STV090x_OFFST_Px_NOSPLH_NORMED_FIELD	0
+#define STV090x_WIDTH_Px_NOSPLH_NORMED_FIELD	8
+
+#define STV090x_Px_NOSDATATy(__x, __y)			(0xf489 - (__x - 1) * 0x200 - __y * 0x1)
+#define STV090x_P1_NOSDATAT0				STV090x_Px_NOSDATATy(1, 0)
+#define STV090x_P1_NOSDATAT1				STV090x_Px_NOSDATATy(1, 1)
+#define STV090x_P2_NOSDATAT0				STV090x_Px_NOSDATATy(2, 0)
+#define STV090x_P2_NOSDATAT1				STV090x_Px_NOSDATATy(2, 1)
+#define STV090x_OFFST_Px_NOSDATAT_UNNORMED_FIELD	0
+#define STV090x_WIDTH_Px_NOSDATAT_UNNORMED_FIELD	8
+
+#define STV090x_Px_NOSDATAy(__x, __y)		(0xf48b - (__x - 1) * 0x200 - __y * 0x1)
+#define STV090x_P1_NOSDATA0			STV090x_Px_NOSDATAy(1, 0)
+#define STV090x_P1_NOSDATA1			STV090x_Px_NOSDATAy(1, 1)
+#define STV090x_P2_NOSDATA0			STV090x_Px_NOSDATAy(2, 0)
+#define STV090x_P2_NOSDATA1			STV090x_Px_NOSDATAy(2, 1)
+#define STV090x_OFFST_Px_NOSDATA_UNNORMED_FIELD	0
+#define STV090x_WIDTH_Px_NOSDATA_UNNORMED_FIELD	8
+
+#define STV090x_Px_NOSPLHTy(__x, __y)		(0xf48d - (__x - 1) * 0x200 - __y * 0x1)
+#define STV090x_P1_NOSPLHT0			STV090x_Px_NOSPLHTy(1, 0)
+#define STV090x_P1_NOSPLHT1			STV090x_Px_NOSPLHTy(1, 1)
+#define STV090x_P2_NOSPLHT0			STV090x_Px_NOSPLHTy(2, 0)
+#define STV090x_P2_NOSPLHT1			STV090x_Px_NOSPLHTy(2, 1)
+#define STV090x_OFFST_Px_NOSPLHT_UNNORMED_FIELD	0
+#define STV090x_WIDTH_Px_NOSPLHT_UNNORMED_FIELD	8
+
+#define STV090x_Px_NOSPLHy(__x, __y)		(0xf48f - (__x - 1) * 0x200 - __y * 0x1)
+#define STV090x_P1_NOSPLH0			STV090x_Px_NOSPLHy(1, 0)
+#define STV090x_P1_NOSPLH1			STV090x_Px_NOSPLHy(1, 1)
+#define STV090x_P2_NOSPLH0			STV090x_Px_NOSPLHy(2, 0)
+#define STV090x_P2_NOSPLH1			STV090x_Px_NOSPLHy(2, 1)
+#define STV090x_OFFST_Px_NOSPLH_UNNORMED_FIELD	0
+#define STV090x_WIDTH_Px_NOSPLH_UNNORMED_FIELD	8
+
+#define STV090x_Px_CAR2CFG(__x)			(0xf490 - (__x - 1) * 0x200)
+#define STV090x_P1_CAR2CFG			STV090x_Px_CAR2CFG(1)
+#define STV090x_P2_CAR2CFG			STV090x_Px_CAR2CFG(2)
+#define STV090x_OFFST_Px_PN4_SELECT_FIELD	6
+#define STV090x_WIDTH_Px_PN4_SELECT_FIELD	1
+#define STV090x_OFFST_Px_CFR2_STOPDVBS1_FIELD	5
+#define STV090x_WIDTH_Px_CFR2_STOPDVBS1_FIELD	1
+#define STV090x_OFFST_Px_ROTA2ON_FIELD		2
+#define STV090x_WIDTH_Px_ROTA2ON_FIELD		1
+#define STV090x_OFFST_Px_PH_DET_ALGO2_FIELD	0
+#define STV090x_WIDTH_Px_PH_DET_ALGO2_FIELD	2
+
+#define STV090x_Px_ACLC2(__x)			(0xf491 - (__x - 1) * 0x200)
+#define STV090x_P1_ACLC2			STV090x_Px_ACLC2(1)
+#define STV090x_P2_ACLC2			STV090x_Px_ACLC2(2)
+#define STV090x_OFFST_Px_CAR2_ALPHA_MANT_FIELD	4
+#define STV090x_WIDTH_Px_CAR2_ALPHA_MANT_FIELD	2
+#define STV090x_OFFST_Px_CAR2_ALPHA_EXP_FIELD	0
+#define STV090x_WIDTH_Px_CAR2_ALPHA_EXP_FIELD	4
+
+#define STV090x_Px_BCLC2(__x)			(0xf492 - (__x - 1) * 0x200)
+#define STV090x_P1_BCLC2			STV090x_Px_BCLC2(1)
+#define STV090x_P2_BCLC2			STV090x_Px_BCLC2(2)
+#define STV090x_OFFST_Px_CAR2_BETA_MANT_FIELD	4
+#define STV090x_WIDTH_Px_CAR2_BETA_MANT_FIELD	2
+#define STV090x_OFFST_Px_CAR2_BETA_EXP_FIELD	0
+#define STV090x_WIDTH_Px_CAR2_BETA_EXP_FIELD	4
+
+#define STV090x_Px_ACLC2S2Q(__x)		(0xf497 - (__x - 1) * 0x200)
+#define STV090x_P1_ACLC2S2Q			STV090x_Px_ACLC2S2Q(1)
+#define STV090x_P2_ACLC2S2Q			STV090x_Px_ACLC2S2Q(2)
+#define STV090x_OFFST_Px_ENAB_SPSKSYMB_FIELD	7
+#define STV090x_WIDTH_Px_ENAB_SPSKSYMB_FIELD	1
+#define STV090x_OFFST_Px_CAR2S2_Q_ALPH_M_FIELD	4
+#define STV090x_WIDTH_Px_CAR2S2_Q_ALPH_M_FIELD	2
+#define STV090x_OFFST_Px_CAR2S2_Q_ALPH_E_FIELD	0
+#define STV090x_WIDTH_Px_CAR2S2_Q_ALPH_E_FIELD	4
+
+#define STV090x_Px_ACLC2S28(__x)		(0xf498 - (__x - 1) * 0x200)
+#define STV090x_P1_ACLC2S28			STV090x_Px_ACLC2S28(1)
+#define STV090x_P2_ACLC2S28			STV090x_Px_ACLC2S28(2)
+#define STV090x_OFFST_Px_CAR2S2_8_ALPH_M_FIELD	4
+#define STV090x_WIDTH_Px_CAR2S2_8_ALPH_M_FIELD	2
+#define STV090x_OFFST_Px_CAR2S2_8_ALPH_E_FIELD	0
+#define STV090x_WIDTH_Px_CAR2S2_8_ALPH_E_FIELD	4
+
+#define STV090x_Px_ACLC2S216A(__x)		(0xf499 - (__x - 1) * 0x200)
+#define STV090x_P1_ACLC2S216A			STV090x_Px_ACLC2S216A(1)
+#define STV090x_P2_ACLC2S216A			STV090x_Px_ACLC2S216A(2)
+#define STV090x_OFFST_Px_CAR2S2_16A_ALPH_M_FIELD	4
+#define STV090x_WIDTH_Px_CAR2S2_16A_ALPH_M_FIELD	2
+#define STV090x_OFFST_Px_CAR2S2_16A_ALPH_E_FIELD	0
+#define STV090x_WIDTH_Px_CAR2S2_16A_ALPH_E_FIELD	4
+
+#define STV090x_Px_ACLC2S232A(__x)		(0xf49A - (__x - 1) * 0x200)
+#define STV090x_P1_ACLC2S232A			STV090x_Px_ACLC2S232A(1)
+#define STV090x_P2_ACLC2S232A			STV090x_Px_ACLC2S232A(2)
+#define STV090x_OFFST_Px_CAR2S2_32A_ALPH_M_FIELD	4
+#define STV090x_WIDTH_Px_CAR2S2_32A_ALPH_M_FIELD	2
+#define STV090x_OFFST_Px_CAR2S2_32A_ALPH_E_FIELD	0
+#define STV090x_WIDTH_Px_CAR2S2_32A_ALPH_E_FIELD	4
+
+#define STV090x_Px_BCLC2S2Q(__x)		(0xf49c - (__x - 1) * 0x200)
+#define STV090x_P1_BCLC2S2Q			STV090x_Px_BCLC2S2Q(1)
+#define STV090x_P2_BCLC2S2Q			STV090x_Px_BCLC2S2Q(2)
+#define STV090x_OFFST_Px_CAR2S2_Q_BETA_M_FIELD	4
+#define STV090x_WIDTH_Px_CAR2S2_Q_BETA_M_FIELD	2
+#define STV090x_OFFST_Px_CAR2S2_Q_BETA_E_FIELD	0
+#define STV090x_WIDTH_Px_CAR2S2_Q_BETA_E_FIELD	4
+
+#define STV090x_Px_BCLC2S28(__x)		(0xf49d - (__x - 1) * 0x200)
+#define STV090x_P1_BCLC2S28			STV090x_Px_BCLC2S28(1)
+#define STV090x_P2_BCLC2S28			STV090x_Px_BCLC2S28(2)
+#define STV090x_OFFST_Px_CAR2S2_8_BETA_M_FIELD	4
+#define STV090x_WIDTH_Px_CAR2S2_8_BETA_M_FIELD	2
+#define STV090x_OFFST_Px_CAR2S2_8_BETA_E_FIELD	0
+#define STV090x_WIDTH_Px_CAR2S2_8_BETA_E_FIELD	4
+
+#define STV090x_Px_BCLC2S216A(__x)		(0xf49e - (__x - 1) * 0x200)
+#define STV090x_P1_BCLC2S216A			STV090x_Px_BCLC2S216A(1)
+#define STV090x_P2_BCLC2S216A			STV090x_Px_BCLC2S216A(2)
+#define STV090x_OFFST_Px_CAR2S2_16A_BETA_M_FIELD	4
+#define STV090x_WIDTH_Px_CAR2S2_16A_BETA_M_FIELD	2
+#define STV090x_OFFST_Px_CAR2S2_16A_BETA_E_FIELD	0
+#define STV090x_WIDTH_Px_CAR2S2_16A_BETA_E_FIELD	4
+
+#define STV090x_Px_BCLC2S232A(__x)		(0xf49f - (__x - 1) * 0x200)
+#define STV090x_P1_BCLC2S232A			STV090x_Px_BCLC2S232A(1)
+#define STV090x_P2_BCLC2S232A			STV090x_Px_BCLC2S232A(2)
+#define STV090x_OFFST_Px_CAR2S2_32A_BETA_M_FIELD	4
+#define STV090x_WIDTH_Px_CAR2S2_32A_BETA_M_FIELD	2
+#define STV090x_OFFST_Px_CAR2S2_32A_BETA_E_FIELD	0
+#define STV090x_WIDTH_Px_CAR2S2_32A_BETA_E_FIELD	4
+
+#define STV090x_Px_PLROOT2(__x)			(0xf4ac - (__x - 1) * 0x200)
+#define STV090x_P1_PLROOT2			STV090x_Px_PLROOT2(1)
+#define STV090x_P2_PLROOT2			STV090x_Px_PLROOT2(2)
+#define STV090x_OFFST_Px_PLSCRAMB_MODE_FIELD	2
+#define STV090x_WIDTH_Px_PLSCRAMB_MODE_FIELD	2
+#define STV090x_OFFST_Px_PLSCRAMB_ROOT_FIELD	0
+#define STV090x_WIDTH_Px_PLSCRAMB_ROOT_FIELD	2
+
+#define STV090x_Px_PLROOT1(__x)			(0xf4ad - (__x - 1) * 0x200)
+#define STV090x_P1_PLROOT1			STV090x_Px_PLROOT1(1)
+#define STV090x_P2_PLROOT1			STV090x_Px_PLROOT1(2)
+#define STV090x_OFFST_Px_PLSCRAMB_ROOT1_FIELD	0
+#define STV090x_WIDTH_Px_PLSCRAMB_ROOT1_FIELD	8
+
+#define STV090x_Px_PLROOT0(__x)			(0xf4ae - (__x - 1) * 0x200)
+#define STV090x_P1_PLROOT0			STV090x_Px_PLROOT0(1)
+#define STV090x_P2_PLROOT0			STV090x_Px_PLROOT0(2)
+#define STV090x_OFFST_Px_PLSCRAMB_ROOT0_FIELD	0
+#define STV090x_WIDTH_Px_PLSCRAMB_ROOT0_FIELD	8
+
+#define STV090x_Px_MODCODLST0(__x)		(0xf4b0 - (__x - 1) * 0x200) /* check */
+#define STV090x_P1_MODCODLST0			STV090x_Px_MODCODLST0(1)
+#define STV090x_P2_MODCODLST0			STV090x_Px_MODCODLST0(2)
+
+#define STV090x_Px_MODCODLST1(__x)		(0xf4b1 - (__x - 1) * 0x200)
+#define STV090x_P1_MODCODLST1			STV090x_Px_MODCODLST1(1)
+#define STV090x_P2_MODCODLST1			STV090x_Px_MODCODLST1(2)
+#define STV090x_OFFST_Px_DIS_MODCOD29_FIELD	4
+#define STV090x_WIDTH_Px_DIS_MODCOD29_FIELD	4
+#define STV090x_OFFST_Px_DIS_32PSK_9_10_FIELD	0
+#define STV090x_WIDTH_Px_DIS_32PSK_9_10_FIELD	4
+
+#define STV090x_Px_MODCODLST2(__x)		(0xf4b2 - (__x - 1) * 0x200)
+#define STV090x_P1_MODCODLST2			STV090x_Px_MODCODLST2(1)
+#define STV090x_P2_MODCODLST2			STV090x_Px_MODCODLST2(2)
+#define STV090x_OFFST_Px_DIS_32PSK_8_9_FIELD	4
+#define STV090x_WIDTH_Px_DIS_32PSK_8_9_FIELD	4
+#define STV090x_OFFST_Px_DIS_32PSK_5_6_FIELD	0
+#define STV090x_WIDTH_Px_DIS_32PSK_5_6_FIELD	4
+
+#define STV090x_Px_MODCODLST3(__x)		(0xf4b3 - (__x - 1) * 0x200)
+#define STV090x_P1_MODCODLST3			STV090x_Px_MODCODLST3(1)
+#define STV090x_P2_MODCODLST3			STV090x_Px_MODCODLST3(2)
+#define STV090x_OFFST_Px_DIS_32PSK_4_5_FIELD	4
+#define STV090x_WIDTH_Px_DIS_32PSK_4_5_FIELD	4
+#define STV090x_OFFST_Px_DIS_32PSK_3_4_FIELD	0
+#define STV090x_WIDTH_Px_DIS_32PSK_3_4_FIELD	4
+
+#define STV090x_Px_MODCODLST4(__x)		(0xf4b4 - (__x - 1) * 0x200)
+#define STV090x_P1_MODCODLST4			STV090x_Px_MODCODLST4(1)
+#define STV090x_P2_MODCODLST4			STV090x_Px_MODCODLST4(2)
+#define STV090x_OFFST_Px_DIS_16PSK_9_10_FIELD	4
+#define STV090x_WIDTH_Px_DIS_16PSK_9_10_FIELD	4
+#define STV090x_OFFST_Px_DIS_16PSK_8_9_FIELD	0
+#define STV090x_WIDTH_Px_DIS_16PSK_8_9_FIELD	4
+
+#define STV090x_Px_MODCODLST5(__x)		(0xf4b5 - (__x - 1) * 0x200)
+#define STV090x_P1_MODCODLST5			STV090x_Px_MODCODLST5(1)
+#define STV090x_P2_MODCODLST5			STV090x_Px_MODCODLST5(2)
+#define STV090x_OFFST_Px_DIS_16PSK_5_6_FIELD	4
+#define STV090x_WIDTH_Px_DIS_16PSK_5_6_FIELD	4
+#define STV090x_OFFST_Px_DIS_16PSK_4_5_FIELD	0
+#define STV090x_WIDTH_Px_DIS_16PSK_4_5_FIELD	4
+
+#define STV090x_Px_MODCODLST6(__x)		(0xf4b6 - (__x - 1) * 0x200)
+#define STV090x_P1_MODCODLST6			STV090x_Px_MODCODLST6(1)
+#define STV090x_P2_MODCODLST6			STV090x_Px_MODCODLST6(2)
+#define STV090x_OFFST_Px_DIS_16PSK_3_4_FIELD	4
+#define STV090x_WIDTH_Px_DIS_16PSK_3_4_FIELD	4
+#define STV090x_OFFST_Px_DIS_16PSK_2_3_FIELD	0
+#define STV090x_WIDTH_Px_DIS_16PSK_2_3_FIELD	4
+
+#define STV090x_Px_MODCODLST7(__x)		(0xf4b7 - (__x - 1) * 0x200)
+#define STV090x_P1_MODCODLST7			STV090x_Px_MODCODLST7(1)
+#define STV090x_P2_MODCODLST7			STV090x_Px_MODCODLST7(2)
+#define STV090x_OFFST_Px_DIS_8P_9_10_FIELD	4
+#define STV090x_WIDTH_Px_DIS_8P_9_10_FIELD	4
+#define STV090x_OFFST_Px_DIS_8P_8_9_FIELD	0
+#define STV090x_WIDTH_Px_DIS_8P_8_9_FIELD	4
+
+#define STV090x_Px_MODCODLST8(__x)		(0xf4b8 - (__x - 1) * 0x200)
+#define STV090x_P1_MODCODLST8			STV090x_Px_MODCODLST8(1)
+#define STV090x_P2_MODCODLST8			STV090x_Px_MODCODLST8(2)
+#define STV090x_OFFST_Px_DIS_8P_5_6_FIELD	4
+#define STV090x_WIDTH_Px_DIS_8P_5_6_FIELD	4
+#define STV090x_OFFST_Px_DIS_8P_3_4_FIELD	0
+#define STV090x_WIDTH_Px_DIS_8P_3_4_FIELD	4
+
+#define STV090x_Px_MODCODLST9(__x)		(0xf4b9 - (__x - 1) * 0x200)
+#define STV090x_P1_MODCODLST9			STV090x_Px_MODCODLST9(1)
+#define STV090x_P2_MODCODLST9			STV090x_Px_MODCODLST9(2)
+#define STV090x_OFFST_Px_DIS_8P_2_3_FIELD	4
+#define STV090x_WIDTH_Px_DIS_8P_2_3_FIELD	4
+#define STV090x_OFFST_Px_DIS_8P_3_5_FIELD	0
+#define STV090x_WIDTH_Px_DIS_8P_3_5_FIELD	4
+
+#define STV090x_Px_MODCODLSTA(__x)		(0xf4ba - (__x - 1) * 0x200)
+#define STV090x_P1_MODCODLSTA			STV090x_Px_MODCODLSTA(1)
+#define STV090x_P2_MODCODLSTA			STV090x_Px_MODCODLSTA(2)
+#define STV090x_OFFST_Px_DIS_QP_9_10_FIELD	4
+#define STV090x_WIDTH_Px_DIS_QP_9_10_FIELD	4
+#define STV090x_OFFST_Px_DIS_QP_8_9_FIELD	0
+#define STV090x_WIDTH_Px_DIS_QP_8_9_FIELD	4
+
+#define STV090x_Px_MODCODLSTB(__x)		(0xf4bb - (__x - 1) * 0x200)
+#define STV090x_P1_MODCODLSTB			STV090x_Px_MODCODLSTB(1)
+#define STV090x_P2_MODCODLSTB			STV090x_Px_MODCODLSTB(2)
+#define STV090x_OFFST_Px_DIS_QP_5_6_FIELD	4
+#define STV090x_WIDTH_Px_DIS_QP_5_6_FIELD	4
+#define STV090x_OFFST_Px_DIS_QP_4_5_FIELD	0
+#define STV090x_WIDTH_Px_DIS_QP_4_5_FIELD	4
+
+#define STV090x_Px_MODCODLSTC(__x)		(0xf4bc - (__x - 1) * 0x200)
+#define STV090x_P1_MODCODLSTC			STV090x_Px_MODCODLSTC(1)
+#define STV090x_P2_MODCODLSTC			STV090x_Px_MODCODLSTC(2)
+#define STV090x_OFFST_Px_DIS_QP_3_4_FIELD	4
+#define STV090x_WIDTH_Px_DIS_QP_3_4_FIELD	4
+#define STV090x_OFFST_Px_DIS_QP_2_3_FIELD	0
+#define STV090x_WIDTH_Px_DIS_QP_2_3_FIELD	4
+
+#define STV090x_Px_MODCODLSTD(__x)		(0xf4bd - (__x - 1) * 0x200)
+#define STV090x_P1_MODCODLSTD			STV090x_Px_MODCODLSTD(1)
+#define STV090x_P2_MODCODLSTD			STV090x_Px_MODCODLSTD(2)
+#define STV090x_OFFST_Px_DIS_QP_3_5_FIELD	4
+#define STV090x_WIDTH_Px_DIS_QP_3_5_FIELD	4
+#define STV090x_OFFST_Px_DIS_QP_1_2_FIELD	0
+#define STV090x_WIDTH_Px_DIS_QP_1_2_FIELD	4
+
+#define STV090x_Px_MODCODLSTE(__x)		(0xf4be - (__x - 1) * 0x200)
+#define STV090x_P1_MODCODLSTE			STV090x_Px_MODCODLSTE(1)
+#define STV090x_P2_MODCODLSTE			STV090x_Px_MODCODLSTE(2)
+#define STV090x_OFFST_Px_DIS_QP_2_5_FIELD	4
+#define STV090x_WIDTH_Px_DIS_QP_2_5_FIELD	4
+#define STV090x_OFFST_Px_DIS_QP_1_3_FIELD	0
+#define STV090x_WIDTH_Px_DIS_QP_1_3_FIELD	4
+
+#define STV090x_Px_MODCODLSTF(__x)		(0xf4bf - (__x - 1) * 0x200)
+#define STV090x_P1_MODCODLSTF			STV090x_Px_MODCODLSTF(1)
+#define STV090x_P2_MODCODLSTF			STV090x_Px_MODCODLSTF(2)
+#define STV090x_OFFST_Px_DIS_QP_1_4_FIELD	4
+#define STV090x_WIDTH_Px_DIS_QP_1_4_FIELD	4
+
+#define STV090x_Px_GAUSSR0(__x)			(0xf4c0 - (__x - 1) * 0x200)
+#define STV090x_P1_GAUSSR0			STV090x_Px_GAUSSR0(1)
+#define STV090x_P2_GAUSSR0			STV090x_Px_GAUSSR0(2)
+#define STV090x_OFFST_Px_EN_CCIMODE_FIELD	7
+#define STV090x_WIDTH_Px_EN_CCIMODE_FIELD	1
+#define STV090x_OFFST_Px_R0_GAUSSIEN_FIELD	0
+#define STV090x_WIDTH_Px_R0_GAUSSIEN_FIELD	7
+
+#define STV090x_Px_CCIR0(__x)			(0xf4c1 - (__x - 1) * 0x200)
+#define STV090x_P1_CCIR0			STV090x_Px_CCIR0(1)
+#define STV090x_P2_CCIR0			STV090x_Px_CCIR0(2)
+#define STV090x_OFFST_Px_CCIDETECT_PLH_FIELD	7
+#define STV090x_WIDTH_Px_CCIDETECT_PLH_FIELD	1
+#define STV090x_OFFST_Px_R0_CCI_FIELD		0
+#define STV090x_WIDTH_Px_R0_CCI_FIELD		7
+
+#define STV090x_Px_CCIQUANT(__x)		(0xf4c2 - (__x - 1) * 0x200)
+#define STV090x_P1_CCIQUANT			STV090x_Px_CCIQUANT(1)
+#define STV090x_P2_CCIQUANT			STV090x_Px_CCIQUANT(2)
+#define STV090x_OFFST_Px_CCI_BETA_FIELD		5
+#define STV090x_WIDTH_Px_CCI_BETA_FIELD		3
+#define STV090x_OFFST_Px_CCI_QUANT_FIELD	0
+#define STV090x_WIDTH_Px_CCI_QUANT_FIELD	5
+
+#define STV090x_Px_CCITHRESH(__x)		(0xf4c3 - (__x - 1) * 0x200)
+#define STV090x_P1_CCITHRESH			STV090x_Px_CCITHRESH(1)
+#define STV090x_P2_CCITHRESH			STV090x_Px_CCITHRESH(2)
+#define STV090x_OFFST_Px_CCI_THRESHOLD_FIELD	0
+#define STV090x_WIDTH_Px_CCI_THRESHOLD_FIELD	8
+
+#define STV090x_Px_CCIACC(__x)			(0xf4c4 - (__x - 1) * 0x200)
+#define STV090x_P1_CCIACC			STV090x_Px_CCIACC(1)
+#define STV090x_P2_CCIACC			STV090x_Px_CCIACC(2)
+#define STV090x_OFFST_Px_CCI_VALUE_FIELD	0
+#define STV090x_WIDTH_Px_CCI_VALUE_FIELD	8
+
+#define STV090x_Px_DMDRESCFG(__x)		(0xF4C6 - (__x - 1) * 0x200)
+#define STV090x_P1_DMDRESCFG			STV090x_Px_DMDRESCFG(1)
+#define STV090x_P2_DMDRESCFG			STV090x_Px_DMDRESCFG(2)
+#define STV090x_OFFST_Px_DMDRES_RESET_FIELD	7
+#define STV090x_WIDTH_Px_DMDRES_RESET_FIELD	1
+
+#define STV090x_Px_DMDRESADR(__x)		(0xF4C7 - (__x - 1) * 0x200)
+#define STV090x_P1_DMDRESADR			STV090x_Px_DMDRESADR(1)
+#define STV090x_P2_DMDRESADR			STV090x_Px_DMDRESADR(2)
+#define STV090x_OFFST_Px_DMDRES_RESNBR_FIELD	0
+#define STV090x_WIDTH_Px_DMDRES_RESNBR_FIELD	4
+
+#define STV090x_Px_DMDRESDATAy(__x, __y)	(0xF4C8 - (__x - 1) * 0x200 + (7 - __y))
+#define STV090x_P1_DMDRESDATA0			STV090x_Px_DMDRESDATAy(1, 0)
+#define STV090x_P1_DMDRESDATA1			STV090x_Px_DMDRESDATAy(1, 1)
+#define STV090x_P1_DMDRESDATA2			STV090x_Px_DMDRESDATAy(1, 2)
+#define STV090x_P1_DMDRESDATA3			STV090x_Px_DMDRESDATAy(1, 3)
+#define STV090x_P1_DMDRESDATA4			STV090x_Px_DMDRESDATAy(1, 4)
+#define STV090x_P1_DMDRESDATA5			STV090x_Px_DMDRESDATAy(1, 5)
+#define STV090x_P1_DMDRESDATA6			STV090x_Px_DMDRESDATAy(1, 6)
+#define STV090x_P1_DMDRESDATA7			STV090x_Px_DMDRESDATAy(1, 7)
+#define STV090x_P2_DMDRESDATA0			STV090x_Px_DMDRESDATAy(2, 0)
+#define STV090x_P2_DMDRESDATA1			STV090x_Px_DMDRESDATAy(2, 1)
+#define STV090x_P2_DMDRESDATA2			STV090x_Px_DMDRESDATAy(2, 2)
+#define STV090x_P2_DMDRESDATA3			STV090x_Px_DMDRESDATAy(2, 3)
+#define STV090x_P2_DMDRESDATA4			STV090x_Px_DMDRESDATAy(2, 4)
+#define STV090x_P2_DMDRESDATA5			STV090x_Px_DMDRESDATAy(2, 5)
+#define STV090x_P2_DMDRESDATA6			STV090x_Px_DMDRESDATAy(2, 6)
+#define STV090x_P2_DMDRESDATA7			STV090x_Px_DMDRESDATAy(2, 7)
+#define STV090x_OFFST_Px_DMDRES_DATA_FIELD	0
+#define STV090x_WIDTH_Px_DMDRES_DATA_FIELD	8
+
+#define STV090x_Px_FFEIy(__x, __y)		(0xf4d0 - (__x - 1) * 0x200 + 0x2 * (__y - 1))
+#define STV090x_P1_FFEI1			STV090x_Px_FFEIy(1, 1)
+#define STV090x_P1_FFEI2			STV090x_Px_FFEIy(1, 2)
+#define STV090x_P1_FFEI3			STV090x_Px_FFEIy(1, 3)
+#define STV090x_P1_FFEI4			STV090x_Px_FFEIy(1, 4)
+#define STV090x_P2_FFEI1			STV090x_Px_FFEIy(2, 1)
+#define STV090x_P2_FFEI2			STV090x_Px_FFEIy(2, 2)
+#define STV090x_P2_FFEI3			STV090x_Px_FFEIy(2, 3)
+#define STV090x_P2_FFEI4			STV090x_Px_FFEIy(2, 4)
+#define STV090x_OFFST_Px_FFE_ACCIy_FIELD	0
+#define STV090x_WIDTH_Px_FFE_ACCIy_FIELD	8
+
+#define STV090x_Px_FFEQy(__x, __y)		(0xf4d1 - (__x - 1) * 0x200 + 0x2 * (__y - 1))
+#define STV090x_P1_FFEQ1			STV090x_Px_FFEQy(1, 1)
+#define STV090x_P1_FFEQ2			STV090x_Px_FFEQy(1, 2)
+#define STV090x_P1_FFEQ3			STV090x_Px_FFEQy(1, 3)
+#define STV090x_P1_FFEQ4			STV090x_Px_FFEQy(1, 4)
+#define STV090x_P2_FFEQ1			STV090x_Px_FFEQy(2, 1)
+#define STV090x_P2_FFEQ2			STV090x_Px_FFEQy(2, 2)
+#define STV090x_P2_FFEQ3			STV090x_Px_FFEQy(2, 3)
+#define STV090x_P2_FFEQ4			STV090x_Px_FFEQy(2, 4)
+#define STV090x_OFFST_Px_FFE_ACCQy_FIELD	0
+#define STV090x_WIDTH_Px_FFE_ACCQy_FIELD	8
+
+#define STV090x_Px_FFECFG(__x)			(0xf4d8 - (__x - 1) * 0x200)
+#define STV090x_P1_FFECFG			STV090x_Px_FFECFG(1)
+#define STV090x_P2_FFECFG			STV090x_Px_FFECFG(2)
+#define STV090x_OFFST_Px_EQUALFFE_ON_FIELD	6
+#define STV090x_WIDTH_Px_EQUALFFE_ON_FIELD	1
+
+#define STV090x_Px_SMAPCOEF7(__x)		(0xf500 - (__x - 1) * 0x200)
+#define STV090x_P1_SMAPCOEF7			STV090x_Px_SMAPCOEF7(1)
+#define STV090x_P2_SMAPCOEF7			STV090x_Px_SMAPCOEF7(2)
+#define STV090x_OFFST_Px_DIS_QSCALE_FIELD	7
+#define STV090x_WIDTH_Px_DIS_QSCALE_FIELD	1
+#define STV090x_OFFST_Px_SMAPCOEF_Q_LLR12_FIELD	0
+#define STV090x_WIDTH_Px_SMAPCOEF_Q_LLR12_FIELD	7
+
+#define STV090x_Px_SMAPCOEF6(__x)		(0xf501 - (__x - 1) * 0x200)
+#define STV090x_P1_SMAPCOEF6			STV090x_Px_SMAPCOEF6(1)
+#define STV090x_P2_SMAPCOEF6			STV090x_Px_SMAPCOEF6(2)
+#define STV090x_OFFST_Px_ADJ_8PSKLLR1_FIELD	2
+#define STV090x_WIDTH_Px_ADJ_8PSKLLR1_FIELD	1
+#define STV090x_OFFST_Px_OLD_8PSKLLR1_FIELD	1
+#define STV090x_WIDTH_Px_OLD_8PSKLLR1_FIELD	1
+#define STV090x_OFFST_Px_DIS_AB8PSK_FIELD	0
+#define STV090x_WIDTH_Px_DIS_AB8PSK_FIELD	1
+
+#define STV090x_Px_SMAPCOEF5(__x)			(0xf502 - (__x - 1) * 0x200)
+#define STV090x_P1_SMAPCOEF5				STV090x_Px_SMAPCOEF5(1)
+#define STV090x_P2_SMAPCOEF5				STV090x_Px_SMAPCOEF5(2)
+#define STV090x_OFFST_Px_DIS_8SCALE_FIELD		7
+#define STV090x_WIDTH_Px_DIS_8SCALE_FIELD		1
+#define STV090x_OFFST_Px_SMAPCOEF_8P_LLR23_FIELD	0
+#define STV090x_WIDTH_Px_SMAPCOEF_8P_LLR23_FIELD	7
+
+#define STV090x_Px_DMDPLHSTAT(__x)		(0xF520 - (__x - 1) * 0x200)
+#define STV090x_P1_DMDPLHSTAT			STV090x_Px_DMDPLHSTAT(1)
+#define STV090x_P2_DMDPLHSTAT			STV090x_Px_DMDPLHSTAT(2)
+#define STV090x_OFFST_Px_PLH_STATISTIC_FIELD	0
+#define STV090x_WIDTH_Px_PLH_STATISTIC_FIELD	8
+
+#define STV090x_Px_LOCKTIMEy(__x, __y)		(0xF525 - (__x - 1) * 0x200 - __y * 0x1)
+#define STV090x_P1_LOCKTIME0			STV090x_Px_LOCKTIMEy(1, 0)
+#define STV090x_P1_LOCKTIME1			STV090x_Px_LOCKTIMEy(1, 1)
+#define STV090x_P1_LOCKTIME2			STV090x_Px_LOCKTIMEy(1, 2)
+#define STV090x_P1_LOCKTIME3			STV090x_Px_LOCKTIMEy(1, 3)
+#define STV090x_P2_LOCKTIME0			STV090x_Px_LOCKTIMEy(2, 0)
+#define STV090x_P2_LOCKTIME1			STV090x_Px_LOCKTIMEy(2, 1)
+#define STV090x_P2_LOCKTIME2			STV090x_Px_LOCKTIMEy(2, 2)
+#define STV090x_P2_LOCKTIME3			STV090x_Px_LOCKTIMEy(2, 3)
+#define STV090x_OFFST_Px_DEMOD_LOCKTIME_FIELD	0
+#define STV090x_WIDTH_Px_DEMOD_LOCKTIME_FIELD	8
+
+#define STV090x_Px_TNRCFG(__x)			(0xf4e0 - (__x - 1) * 0x200) /* check */
+#define STV090x_P1_TNRCFG			STV090x_Px_TNRCFG(1)
+#define STV090x_P2_TNRCFG			STV090x_Px_TNRCFG(2)
+
+#define STV090x_Px_TNRCFG2(__x)			(0xf4e1 - (__x - 1) * 0x200)
+#define STV090x_P1_TNRCFG2			STV090x_Px_TNRCFG2(1)
+#define STV090x_P2_TNRCFG2			STV090x_Px_TNRCFG2(2)
+#define STV090x_OFFST_Px_TUN_IQSWAP_FIELD	7
+#define STV090x_WIDTH_Px_TUN_IQSWAP_FIELD	1
+
+#define STV090x_Px_VITSCALE(__x)		(0xf532 - (__x - 1) * 0x200)
+#define STV090x_P1_VITSCALE			STV090x_Px_VITSCALE(1)
+#define STV090x_P2_VITSCALE			STV090x_Px_VITSCALE(2)
+#define STV090x_OFFST_Px_NVTH_NOSRANGE_FIELD	7
+#define STV090x_WIDTH_Px_NVTH_NOSRANGE_FIELD	1
+#define STV090x_OFFST_Px_VERROR_MAXMODE_FIELD	6
+#define STV090x_WIDTH_Px_VERROR_MAXMODE_FIELD	1
+#define STV090x_OFFST_Px_NSLOWSN_LOCKED_FIELD	3
+#define STV090x_WIDTH_Px_NSLOWSN_LOCKED_FIELD	1
+#define STV090x_OFFST_Px_DIS_RSFLOCK_FIELD	1
+#define STV090x_WIDTH_Px_DIS_RSFLOCK_FIELD	1
+
+#define STV090x_Px_FECM(__x)			(0xf533 - (__x - 1) * 0x200)
+#define STV090x_P1_FECM				STV090x_Px_FECM(1)
+#define STV090x_P2_FECM				STV090x_Px_FECM(2)
+#define STV090x_OFFST_Px_DSS_DVB_FIELD		7
+#define STV090x_WIDTH_Px_DSS_DVB_FIELD		1
+#define STV090x_OFFST_Px_DSS_SRCH_FIELD		4
+#define STV090x_WIDTH_Px_DSS_SRCH_FIELD		1
+#define STV090x_OFFST_Px_SYNCVIT_FIELD		1
+#define STV090x_WIDTH_Px_SYNCVIT_FIELD		1
+#define STV090x_OFFST_Px_IQINV_FIELD		0
+#define STV090x_WIDTH_Px_IQINV_FIELD		1
+
+#define STV090x_Px_VTH12(__x)			(0xf534 - (__x - 1) * 0x200)
+#define STV090x_P1_VTH12			STV090x_Px_VTH12(1)
+#define STV090x_P2_VTH12			STV090x_Px_VTH12(2)
+#define STV090x_OFFST_Px_VTH12_FIELD		0
+#define STV090x_WIDTH_Px_VTH12_FIELD		8
+
+#define STV090x_Px_VTH23(__x)			(0xf535 - (__x - 1) * 0x200)
+#define STV090x_P1_VTH23			STV090x_Px_VTH23(1)
+#define STV090x_P2_VTH23			STV090x_Px_VTH23(2)
+#define STV090x_OFFST_Px_VTH23_FIELD		0
+#define STV090x_WIDTH_Px_VTH23_FIELD		8
+
+#define STV090x_Px_VTH34(__x)			(0xf536 - (__x - 1) * 0x200)
+#define STV090x_P1_VTH34			STV090x_Px_VTH34(1)
+#define STV090x_P2_VTH34			STV090x_Px_VTH34(2)
+#define STV090x_OFFST_Px_VTH34_FIELD		0
+#define STV090x_WIDTH_Px_VTH34_FIELD		8
+
+#define STV090x_Px_VTH56(__x)			(0xf537 - (__x - 1) * 0x200)
+#define STV090x_P1_VTH56			STV090x_Px_VTH56(1)
+#define STV090x_P2_VTH56			STV090x_Px_VTH56(2)
+#define STV090x_OFFST_Px_VTH56_FIELD		0
+#define STV090x_WIDTH_Px_VTH56_FIELD		8
+
+#define STV090x_Px_VTH67(__x)			(0xf538 - (__x - 1) * 0x200)
+#define STV090x_P1_VTH67			STV090x_Px_VTH67(1)
+#define STV090x_P2_VTH67			STV090x_Px_VTH67(2)
+#define STV090x_OFFST_Px_VTH67_FIELD		0
+#define STV090x_WIDTH_Px_VTH67_FIELD		8
+
+#define STV090x_Px_VTH78(__x)			(0xf539 - (__x - 1) * 0x200)
+#define STV090x_P1_VTH78			STV090x_Px_VTH78(1)
+#define STV090x_P2_VTH78			STV090x_Px_VTH78(2)
+#define STV090x_OFFST_Px_VTH78_FIELD		0
+#define STV090x_WIDTH_Px_VTH78_FIELD		8
+
+#define STV090x_Px_VITCURPUN(__x)		(0xf53a - (__x - 1) * 0x200)
+#define STV090x_P1_VITCURPUN			STV090x_Px_VITCURPUN(1)
+#define STV090x_P2_VITCURPUN			STV090x_Px_VITCURPUN(2)
+#define STV090x_OFFST_Px_VIT_CURPUN_FIELD	0
+#define STV090x_WIDTH_Px_VIT_CURPUN_FIELD	5
+
+#define STV090x_Px_VERROR(__x)			(0xf53b - (__x - 1) * 0x200)
+#define STV090x_P1_VERROR			STV090x_Px_VERROR(1)
+#define STV090x_P2_VERROR			STV090x_Px_VERROR(2)
+#define STV090x_OFFST_Px_REGERR_VIT_FIELD	0
+#define STV090x_WIDTH_Px_REGERR_VIT_FIELD	8
+
+#define STV090x_Px_PRVIT(__x)			(0xf53c - (__x - 1) * 0x200)
+#define STV090x_P1_PRVIT			STV090x_Px_PRVIT(1)
+#define STV090x_P2_PRVIT			STV090x_Px_PRVIT(2)
+#define STV090x_OFFST_Px_DIS_VTHLOCK_FIELD	6
+#define STV090x_WIDTH_Px_DIS_VTHLOCK_FIELD	1
+#define STV090x_OFFST_Px_E7_8VIT_FIELD		5
+#define STV090x_WIDTH_Px_E7_8VIT_FIELD		1
+#define STV090x_OFFST_Px_E6_7VIT_FIELD		4
+#define STV090x_WIDTH_Px_E6_7VIT_FIELD		1
+#define STV090x_OFFST_Px_E5_6VIT_FIELD		3
+#define STV090x_WIDTH_Px_E5_6VIT_FIELD		1
+#define STV090x_OFFST_Px_E3_4VIT_FIELD		2
+#define STV090x_WIDTH_Px_E3_4VIT_FIELD		1
+#define STV090x_OFFST_Px_E2_3VIT_FIELD		1
+#define STV090x_WIDTH_Px_E2_3VIT_FIELD		1
+#define STV090x_OFFST_Px_E1_2VIT_FIELD		0
+#define STV090x_WIDTH_Px_E1_2VIT_FIELD		1
+
+#define STV090x_Px_VAVSRVIT(__x)		(0xf53d - (__x - 1) * 0x200)
+#define STV090x_P1_VAVSRVIT			STV090x_Px_VAVSRVIT(1)
+#define STV090x_P2_VAVSRVIT			STV090x_Px_VAVSRVIT(2)
+#define STV090x_OFFST_Px_SNVIT_FIELD		4
+#define STV090x_WIDTH_Px_SNVIT_FIELD		2
+#define STV090x_OFFST_Px_TOVVIT_FIELD		2
+#define STV090x_WIDTH_Px_TOVVIT_FIELD		2
+#define STV090x_OFFST_Px_HYPVIT_FIELD		0
+#define STV090x_WIDTH_Px_HYPVIT_FIELD		2
+
+#define STV090x_Px_VSTATUSVIT(__x)		(0xf53e - (__x - 1) * 0x200)
+#define STV090x_P1_VSTATUSVIT			STV090x_Px_VSTATUSVIT(1)
+#define STV090x_P2_VSTATUSVIT			STV090x_Px_VSTATUSVIT(2)
+#define STV090x_OFFST_Px_PRFVIT_FIELD		4
+#define STV090x_WIDTH_Px_PRFVIT_FIELD		1
+#define STV090x_OFFST_Px_LOCKEDVIT_FIELD	3
+#define STV090x_WIDTH_Px_LOCKEDVIT_FIELD	1
+
+#define STV090x_Px_VTHINUSE(__x)		(0xf53f - (__x - 1) * 0x200)
+#define STV090x_P1_VTHINUSE			STV090x_Px_VTHINUSE(1)
+#define STV090x_P2_VTHINUSE			STV090x_Px_VTHINUSE(2)
+#define STV090x_OFFST_Px_VIT_INUSE_FIELD	0
+#define STV090x_WIDTH_Px_VIT_INUSE_FIELD	8
+
+#define STV090x_Px_KDIV12(__x)			(0xf540 - (__x - 1) * 0x200)
+#define STV090x_P1_KDIV12			STV090x_Px_KDIV12(1)
+#define STV090x_P2_KDIV12			STV090x_Px_KDIV12(2)
+#define STV090x_OFFST_Px_K_DIVIDER_12_FIELD	0
+#define STV090x_WIDTH_Px_K_DIVIDER_12_FIELD	7
+
+#define STV090x_Px_KDIV23(__x)			(0xf541 - (__x - 1) * 0x200)
+#define STV090x_P1_KDIV23			STV090x_Px_KDIV23(1)
+#define STV090x_P2_KDIV23			STV090x_Px_KDIV23(2)
+#define STV090x_OFFST_Px_K_DIVIDER_23_FIELD	0
+#define STV090x_WIDTH_Px_K_DIVIDER_23_FIELD	7
+
+#define STV090x_Px_KDIV34(__x)			(0xf542 - (__x - 1) * 0x200)
+#define STV090x_P1_KDIV34			STV090x_Px_KDIV34(1)
+#define STV090x_P2_KDIV34			STV090x_Px_KDIV34(2)
+#define STV090x_OFFST_Px_K_DIVIDER_34_FIELD	0
+#define STV090x_WIDTH_Px_K_DIVIDER_34_FIELD	7
+
+#define STV090x_Px_KDIV56(__x)			(0xf543 - (__x - 1) * 0x200)
+#define STV090x_P1_KDIV56			STV090x_Px_KDIV56(1)
+#define STV090x_P2_KDIV56			STV090x_Px_KDIV56(2)
+#define STV090x_OFFST_Px_K_DIVIDER_56_FIELD	0
+#define STV090x_WIDTH_Px_K_DIVIDER_56_FIELD	7
+
+#define STV090x_Px_KDIV67(__x)			(0xf544 - (__x - 1) * 0x200)
+#define STV090x_P1_KDIV67			STV090x_Px_KDIV67(1)
+#define STV090x_P2_KDIV67			STV090x_Px_KDIV67(2)
+#define STV090x_OFFST_Px_K_DIVIDER_67_FIELD	0
+#define STV090x_WIDTH_Px_K_DIVIDER_67_FIELD	7
+
+#define STV090x_Px_KDIV78(__x)			(0xf545 - (__x - 1) * 0x200)
+#define STV090x_P1_KDIV78			STV090x_Px_KDIV78(1)
+#define STV090x_P2_KDIV78			STV090x_Px_KDIV78(2)
+#define STV090x_OFFST_Px_K_DIVIDER_78_FIELD	0
+#define STV090x_WIDTH_Px_K_DIVIDER_78_FIELD	7
+
+#define STV090x_Px_PDELCTRL1(__x)		(0xf550 - (__x - 1) * 0x200)
+#define STV090x_P1_PDELCTRL1			STV090x_Px_PDELCTRL1(1)
+#define STV090x_P2_PDELCTRL1			STV090x_Px_PDELCTRL1(2)
+#define STV090x_OFFST_Px_INV_MISMASK_FIELD	7
+#define STV090x_WIDTH_Px_INV_MISMASK_FIELD	1
+#define STV090x_OFFST_Px_FILTER_EN_FIELD	5
+#define STV090x_WIDTH_Px_FILTER_EN_FIELD	1
+#define STV090x_OFFST_Px_EN_MIS00_FIELD		1
+#define STV090x_WIDTH_Px_EN_MIS00_FIELD		1
+#define STV090x_OFFST_Px_ALGOSWRST_FIELD	0
+#define STV090x_WIDTH_Px_ALGOSWRST_FIELD	1
+
+#define STV090x_Px_PDELCTRL2(__x)		(0xf551 - (__x - 1) * 0x200)
+#define STV090x_P1_PDELCTRL2			STV090x_Px_PDELCTRL2(1)
+#define STV090x_P2_PDELCTRL2			STV090x_Px_PDELCTRL2(2)
+#define STV090x_OFFST_Px_FORCE_CONTINUOUS	7
+#define STV090x_WIDTH_Px_FORCE_CONTINUOUS	1
+#define STV090x_OFFST_Px_RESET_UPKO_COUNT	6
+#define STV090x_WIDTH_Px_RESET_UPKO_COUNT	1
+#define STV090x_OFFST_Px_USER_PKTDELIN_NB	5
+#define STV090x_WIDTH_Px_USER_PKTDELIN_NB	1
+#define STV090x_OFFST_Px_FORCE_LOCKED		4
+#define STV090x_WIDTH_Px_FORCE_LOCKED		1
+#define STV090x_OFFST_Px_DATA_UNBBSCRAM		3
+#define STV090x_WIDTH_Px_DATA_UNBBSCRAM		1
+#define STV090x_OFFST_Px_FORCE_LONGPACKET	2
+#define STV090x_WIDTH_Px_FORCE_LONGPACKET	1
+#define STV090x_OFFST_Px_FRAME_MODE_FIELD	1
+#define STV090x_WIDTH_Px_FRAME_MODE_FIELD	1
+
+#define STV090x_Px_HYSTTHRESH(__x)		(0xf554 - (__x - 1) * 0x200)
+#define STV090x_P1_HYSTTHRESH			STV090x_Px_HYSTTHRESH(1)
+#define STV090x_P2_HYSTTHRESH			STV090x_Px_HYSTTHRESH(2)
+#define STV090x_OFFST_Px_UNLCK_THRESH_FIELD	4
+#define STV090x_WIDTH_Px_UNLCK_THRESH_FIELD	4
+#define STV090x_OFFST_Px_DELIN_LCK_THRESH_FIELD	0
+#define STV090x_WIDTH_Px_DELIN_LCK_THRESH_FIELD	4
+
+#define STV090x_Px_ISIENTRY(__x)		(0xf55e - (__x - 1) * 0x200)
+#define STV090x_P1_ISIENTRY			STV090x_Px_ISIENTRY(1)
+#define STV090x_P2_ISIENTRY			STV090x_Px_ISIENTRY(2)
+#define STV090x_OFFST_Px_ISI_ENTRY_FIELD	0
+#define STV090x_WIDTH_Px_ISI_ENTRY_FIELD	8
+
+#define STV090x_Px_ISIBITENA(__x)		(0xf55f - (__x - 1) * 0x200)
+#define STV090x_P1_ISIBITENA			STV090x_Px_ISIBITENA(1)
+#define STV090x_P2_ISIBITENA			STV090x_Px_ISIBITENA(2)
+#define STV090x_OFFST_Px_ISI_BIT_EN_FIELD	0
+#define STV090x_WIDTH_Px_ISI_BIT_EN_FIELD	8
+
+#define STV090x_Px_MATSTRy(__x, __y)		(0xf561 - (__x - 1) * 0x200 - __y * 0x1)
+#define STV090x_P1_MATSTR0			STV090x_Px_MATSTRy(1, 0)
+#define STV090x_P1_MATSTR1			STV090x_Px_MATSTRy(1, 1)
+#define STV090x_P2_MATSTR0			STV090x_Px_MATSTRy(2, 0)
+#define STV090x_P2_MATSTR1			STV090x_Px_MATSTRy(2, 1)
+#define STV090x_OFFST_Px_MATYPE_CURRENT_FIELD	0
+#define STV090x_WIDTH_Px_MATYPE_CURRENT_FIELD	8
+
+#define STV090x_Px_UPLSTRy(__x, __y)		(0xf563 - (__x - 1) * 0x200 - __y * 0x1)
+#define STV090x_P1_UPLSTR0			STV090x_Px_UPLSTRy(1, 0)
+#define STV090x_P1_UPLSTR1			STV090x_Px_UPLSTRy(1, 1)
+#define STV090x_P2_UPLSTR0			STV090x_Px_UPLSTRy(2, 0)
+#define STV090x_P2_UPLSTR1			STV090x_Px_UPLSTRy(2, 1)
+#define STV090x_OFFST_Px_UPL_CURRENT_FIELD	0
+#define STV090x_WIDTH_Px_UPL_CURRENT_FIELD	8
+
+#define STV090x_Px_DFLSTRy(__x, __y)		(0xf565 - (__x - 1) * 0x200 - __y * 0x1)
+#define STV090x_P1_DFLSTR0			STV090x_Px_DFLSTRy(1, 0)
+#define STV090x_P1_DFLSTR1			STV090x_Px_DFLSTRy(1, 1)
+#define STV090x_P2_DFLSTR0			STV090x_Px_DFLSTRy(2, 0)
+#define STV090x_P2_DFLSTR1			STV090x_Px_DFLSTRy(2, 1)
+#define STV090x_OFFST_Px_DFL_CURRENT_FIELD	0
+#define STV090x_WIDTH_Px_DFL_CURRENT_FIELD	8
+
+#define STV090x_Px_SYNCSTR(__x)			(0xf566 - (__x - 1) * 0x200)
+#define STV090x_P1_SYNCSTR			STV090x_Px_SYNCSTR(1)
+#define STV090x_P2_SYNCSTR			STV090x_Px_SYNCSTR(2)
+#define STV090x_OFFST_Px_SYNC_CURRENT_FIELD	0
+#define STV090x_WIDTH_Px_SYNC_CURRENT_FIELD	8
+
+#define STV090x_Px_SYNCDSTRy(__x, __y)		(0xf568 - (__x - 1) * 0x200 - __y * 0x1)
+#define STV090x_P1_SYNCDSTR0			STV090x_Px_SYNCDSTRy(1, 0)
+#define STV090x_P1_SYNCDSTR1			STV090x_Px_SYNCDSTRy(1, 1)
+#define STV090x_P2_SYNCDSTR0			STV090x_Px_SYNCDSTRy(2, 0)
+#define STV090x_P2_SYNCDSTR1			STV090x_Px_SYNCDSTRy(2, 1)
+#define STV090x_OFFST_Px_SYNCD_CURRENT_FIELD	0
+#define STV090x_WIDTH_Px_SYNCD_CURRENT_FIELD	8
+
+#define STV090x_Px_PDELSTATUS1(__x)		(0xf569 - (__x - 1) * 0x200)
+#define STV090x_P1_PDELSTATUS1			STV090x_Px_PDELSTATUS1(1)
+#define STV090x_P2_PDELSTATUS1			STV090x_Px_PDELSTATUS1(2)
+#define STV090x_OFFST_Px_PKTDELIN_LOCK_FIELD	1
+#define STV090x_WIDTH_Px_PKTDELIN_LOCK_FIELD	1
+#define STV090x_OFFST_Px_FIRST_LOCK_FIELD	0
+#define STV090x_WIDTH_Px_FIRST_LOCK_FIELD	1
+
+#define STV090x_Px_PDELSTATUS2(__x)		(0xf56a - (__x - 1) * 0x200)
+#define STV090x_P1_PDELSTATUS2			STV090x_Px_PDELSTATUS2(1)
+#define STV090x_P2_PDELSTATUS2			STV090x_Px_PDELSTATUS2(2)
+#define STV090x_OFFST_Px_FRAME_MODCOD_FIELD	2
+#define STV090x_WIDTH_Px_FRAME_MODCOD_FIELD	5
+#define STV090x_OFFST_Px_FRAME_TYPE_FIELD	0
+#define STV090x_WIDTH_Px_FRAME_TYPE_FIELD	2
+
+#define STV090x_Px_BBFCRCKO1(__x)		(0xf56b - (__x - 1) * 0x200)
+#define STV090x_P1_BBFCRCKO1			STV090x_Px_BBFCRCKO1(1)
+#define STV090x_P2_BBFCRCKO1			STV090x_Px_BBFCRCKO1(2)
+#define STV090x_OFFST_Px_BBHCRC_KOCNT_FIELD	0
+#define STV090x_WIDTH_Px_BBHCRC_KOCNT_FIELD	8
+
+#define STV090x_Px_BBFCRCKO0(__x)		(0xf56c - (__x - 1) * 0x200)
+#define STV090x_P1_BBFCRCKO0			STV090x_Px_BBFCRCKO0(1)
+#define STV090x_P2_BBFCRCKO0			STV090x_Px_BBFCRCKO0(2)
+#define STV090x_OFFST_Px_BBHCRC_KOCNT_FIELD	0
+#define STV090x_WIDTH_Px_BBHCRC_KOCNT_FIELD	8
+
+#define STV090x_Px_UPCRCKO1(__x)		(0xf56d - (__x - 1) * 0x200)
+#define STV090x_P1_UPCRCKO1			STV090x_Px_UPCRCKO1(1)
+#define STV090x_P2_UPCRCKO1			STV090x_Px_UPCRCKO1(2)
+#define STV090x_OFFST_Px_PKTCRC_KOCNT_FIELD	0
+#define STV090x_WIDTH_Px_PKTCRC_KOCNT_FIELD	8
+
+#define STV090x_Px_UPCRCKO0(__x)		(0xf56e - (__x - 1) * 0x200)
+#define STV090x_P1_UPCRCKO0			STV090x_Px_UPCRCKO0(1)
+#define STV090x_P2_UPCRCKO0			STV090x_Px_UPCRCKO0(2)
+#define STV090x_OFFST_Px_PKTCRC_KOCNT_FIELD	0
+#define STV090x_WIDTH_Px_PKTCRC_KOCNT_FIELD	8
+
+#define STV090x_NBITER_NFx(__x)				(0xFA03 + (__x - 4) * 0x1)
+#define STV090x_NBITER_NF4				STV090x_NBITER_NFx(4)
+#define STV090x_NBITER_NF5				STV090x_NBITER_NFx(5)
+#define STV090x_NBITER_NF6				STV090x_NBITER_NFx(6)
+#define STV090x_NBITER_NF7				STV090x_NBITER_NFx(7)
+#define STV090x_NBITER_NF8				STV090x_NBITER_NFx(8)
+#define STV090x_NBITER_NF9				STV090x_NBITER_NFx(9)
+#define STV090x_NBITER_NF10				STV090x_NBITER_NFx(10)
+#define STV090x_NBITER_NF11				STV090x_NBITER_NFx(11)
+#define STV090x_NBITER_NF12				STV090x_NBITER_NFx(12)
+#define STV090x_NBITER_NF13				STV090x_NBITER_NFx(13)
+#define STV090x_NBITER_NF14				STV090x_NBITER_NFx(14)
+#define STV090x_NBITER_NF15				STV090x_NBITER_NFx(15)
+#define STV090x_NBITER_NF16				STV090x_NBITER_NFx(16)
+#define STV090x_NBITER_NF17				STV090x_NBITER_NFx(17)
+
+#define STV090x_NBITERNOERR				0xFA3F
+#define STV090x_OFFST_NBITER_STOP_CRIT_FIELD		0
+#define STV090x_WIDTH_NBITER_STOP_CRIT_FIELD		4
+
+#define STV090x_GAINLLR_NFx(__x)			(0xFA43 + (__x - 4) * 0x1)
+#define STV090x_GAINLLR_NF4				STV090x_GAINLLR_NFx(4)
+#define STV090x_OFFST_GAINLLR_NF_QP_1_2_FIELD		0
+#define STV090x_WIDTH_GAINLLR_NF_QP_1_2_FIELD		7
+
+#define STV090x_GAINLLR_NF5				STV090x_GAINLLR_NFx(5)
+#define STV090x_OFFST_GAINLLR_NF_QP_3_5_FIELD		0
+#define STV090x_WIDTH_GAINLLR_NF_QP_3_5_FIELD		7
+
+#define STV090x_GAINLLR_NF6				STV090x_GAINLLR_NFx(6)
+#define STV090x_OFFST_GAINLLR_NF_QP_2_3_FIELD		0
+#define STV090x_WIDTH_GAINLLR_NF_QP_2_3_FIELD		7
+
+#define STV090x_GAINLLR_NF7				STV090x_GAINLLR_NFx(7)
+#define STV090x_OFFST_GAINLLR_NF_QP_3_4_FIELD		0
+#define STV090x_WIDTH_GAINLLR_NF_QP_3_4_FIELD		7
+
+#define STV090x_GAINLLR_NF8				STV090x_GAINLLR_NFx(8)
+#define STV090x_OFFST_GAINLLR_NF_QP_4_5_FIELD		0
+#define STV090x_WIDTH_GAINLLR_NF_QP_4_5_FIELD		7
+
+#define STV090x_GAINLLR_NF9				STV090x_GAINLLR_NFx(9)
+#define STV090x_OFFST_GAINLLR_NF_QP_5_6_FIELD		0
+#define STV090x_WIDTH_GAINLLR_NF_QP_5_6_FIELD		7
+
+#define STV090x_GAINLLR_NF10				STV090x_GAINLLR_NFx(10)
+#define STV090x_OFFST_GAINLLR_NF_QP_8_9_FIELD		0
+#define STV090x_WIDTH_GAINLLR_NF_QP_8_9_FIELD		7
+
+#define STV090x_GAINLLR_NF11				STV090x_GAINLLR_NFx(11)
+#define STV090x_OFFST_GAINLLR_NF_QP_9_10_FIELD		0
+#define STV090x_WIDTH_GAINLLR_NF_QP_9_10_FIELD		7
+
+#define STV090x_GAINLLR_NF12				STV090x_GAINLLR_NFx(12)
+#define STV090x_OFFST_GAINLLR_NF_8P_3_5_FIELD		0
+#define STV090x_WIDTH_GAINLLR_NF_8P_3_5_FIELD		7
+
+#define STV090x_GAINLLR_NF13				STV090x_GAINLLR_NFx(13)
+#define STV090x_OFFST_GAINLLR_NF_8P_2_3_FIELD		0
+#define STV090x_WIDTH_GAINLLR_NF_8P_2_3_FIELD		7
+
+#define STV090x_GAINLLR_NF14				STV090x_GAINLLR_NFx(14)
+#define STV090x_OFFST_GAINLLR_NF_8P_3_4_FIELD		0
+#define STV090x_WIDTH_GAINLLR_NF_8P_3_4_FIELD		7
+
+#define STV090x_GAINLLR_NF15				STV090x_GAINLLR_NFx(15)
+#define STV090x_OFFST_GAINLLR_NF_8P_5_6_FIELD		0
+#define STV090x_WIDTH_GAINLLR_NF_8P_5_6_FIELD		7
+
+#define STV090x_GAINLLR_NF16				STV090x_GAINLLR_NFx(16)
+#define STV090x_OFFST_GAINLLR_NF_8P_8_9_FIELD		0
+#define STV090x_WIDTH_GAINLLR_NF_8P_8_9_FIELD		7
+
+#define STV090x_GAINLLR_NF17				STV090x_GAINLLR_NFx(17)
+#define STV090x_OFFST_GAINLLR_NF_8P_9_10_FIELD		0
+#define STV090x_WIDTH_GAINLLR_NF_8P_9_10_FIELD		7
+
+#define STV090x_GENCFG					0xFA86
+#define STV090x_OFFST_BROADCAST_FIELD			4
+#define STV090x_WIDTH_BROADCAST_FIELD			1
+#define STV090x_OFFST_PRIORITY_FIELD			1
+#define STV090x_WIDTH_PRIORITY_FIELD			1
+#define STV090x_OFFST_DDEMOD_FIELD			0
+#define STV090x_WIDTH_DDEMOD_FIELD			1
+
+#define STV090x_LDPCERRx(__x)				(0xFA97 - (__x  * 0x1))
+#define STV090x_LDPCERR0				STV090x_LDPCERRx(0)
+#define STV090x_LDPCERR1				STV090x_LDPCERRx(1)
+#define STV090x_OFFST_Px_LDPC_ERRORS_COUNTER_FIELD	0
+#define STV090x_WIDTH_Px_LDPC_ERRORS_COUNTER_FIELD	8
+
+#define STV090x_BCHERR					0xFA98
+#define STV090x_OFFST_Px_ERRORFLAG_FIELD		4
+#define STV090x_WIDTH_Px_ERRORFLAG_FIELD		1
+#define STV090x_OFFST_Px_BCH_ERRORS_COUNTER_FIELD	0
+#define STV090x_WIDTH_Px_BCH_ERRORS_COUNTER_FIELD	4
+
+#define STV090x_Px_TSSTATEM(__x)			(0xF570 - (__x - 1) * 0x200)
+#define STV090x_P1_TSSTATEM				STV090x_Px_TSSTATEM(1)
+#define STV090x_P2_TSSTATEM				STV090x_Px_TSSTATEM(2)
+#define STV090x_OFFST_Px_TSDIL_ON_FIELD			7
+#define STV090x_WIDTH_Px_TSDIL_ON_FIELD			1
+#define STV090x_OFFST_Px_TSRS_ON_FIELD			5
+#define STV090x_WIDTH_Px_TSRS_ON_FIELD			1
+
+#define STV090x_Px_TSCFGH(__x)				(0xF572 - (__x - 1) * 0x200)
+#define STV090x_P1_TSCFGH				STV090x_Px_TSCFGH(1)
+#define STV090x_P2_TSCFGH				STV090x_Px_TSCFGH(2)
+#define STV090x_OFFST_Px_TSFIFO_DVBCI_FIELD		7
+#define STV090x_WIDTH_Px_TSFIFO_DVBCI_FIELD		1
+#define STV090x_OFFST_Px_TSFIFO_SERIAL_FIELD		6
+#define STV090x_WIDTH_Px_TSFIFO_SERIAL_FIELD		1
+#define STV090x_OFFST_Px_TSFIFO_TEIUPDATE_FIELD		5
+#define STV090x_WIDTH_Px_TSFIFO_TEIUPDATE_FIELD		1
+#define STV090x_OFFST_Px_TSFIFO_DUTY50_FIELD		4
+#define STV090x_WIDTH_Px_TSFIFO_DUTY50_FIELD		1
+#define STV090x_OFFST_Px_TSFIFO_HSGNLOUT_FIELD		3
+#define STV090x_WIDTH_Px_TSFIFO_HSGNLOUT_FIELD		1
+#define STV090x_OFFST_Px_TSFIFO_ERRORMODE_FIELD		1
+#define STV090x_WIDTH_Px_TSFIFO_ERRORMODE_FIELD		2
+#define STV090x_OFFST_Px_RST_HWARE_FIELD		0
+#define STV090x_WIDTH_Px_RST_HWARE_FIELD		1
+
+#define STV090x_Px_TSCFGM(__x)				(0xF573 - (__x - 1) * 0x200)
+#define STV090x_P1_TSCFGM				STV090x_Px_TSCFGM(1)
+#define STV090x_P2_TSCFGM				STV090x_Px_TSCFGM(2)
+#define STV090x_OFFST_Px_TSFIFO_MANSPEED_FIELD		6
+#define STV090x_WIDTH_Px_TSFIFO_MANSPEED_FIELD		2
+#define STV090x_OFFST_Px_TSFIFO_PERMDATA_FIELD		5
+#define STV090x_WIDTH_Px_TSFIFO_PERMDATA_FIELD		1
+#define STV090x_OFFST_Px_TSFIFO_INVDATA_FIELD		0
+#define STV090x_WIDTH_Px_TSFIFO_INVDATA_FIELD		1
+
+#define STV090x_Px_TSCFGL(__x)				(0xF574 - (__x - 1) * 0x200)
+#define STV090x_P1_TSCFGL				STV090x_Px_TSCFGL(1)
+#define STV090x_P2_TSCFGL				STV090x_Px_TSCFGL(2)
+#define STV090x_OFFST_Px_TSFIFO_BCLKDEL1CK_FIELD	6
+#define STV090x_WIDTH_Px_TSFIFO_BCLKDEL1CK_FIELD	2
+#define STV090x_OFFST_Px_BCHERROR_MODE_FIELD		4
+#define STV090x_WIDTH_Px_BCHERROR_MODE_FIELD		2
+#define STV090x_OFFST_Px_TSFIFO_NSGNL2DATA_FIELD	3
+#define STV090x_WIDTH_Px_TSFIFO_NSGNL2DATA_FIELD	1
+#define STV090x_OFFST_Px_TSFIFO_EMBINDVB_FIELD		2
+#define STV090x_WIDTH_Px_TSFIFO_EMBINDVB_FIELD		1
+#define STV090x_OFFST_Px_TSFIFO_DPUNACT_FIELD		1
+#define STV090x_WIDTH_Px_TSFIFO_DPUNACT_FIELD		1
+
+#define STV090x_Px_TSINSDELH(__x)			(0xF576 - (__x - 1) * 0x200)
+#define STV090x_P1_TSINSDELH				STV090x_Px_TSINSDELH(1)
+#define STV090x_P2_TSINSDELH				STV090x_Px_TSINSDELH(2)
+#define STV090x_OFFST_Px_TSDEL_SYNCBYTE_FIELD		7
+#define STV090x_WIDTH_Px_TSDEL_SYNCBYTE_FIELD		1
+#define STV090x_OFFST_Px_TSDEL_XXHEADER_FIELD		6
+#define STV090x_WIDTH_Px_TSDEL_XXHEADER_FIELD		1
+
+#define STV090x_Px_TSSPEED(__x)				(0xF580 - (__x - 1) * 0x200)
+#define STV090x_P1_TSSPEED				STV090x_Px_TSSPEED(1)
+#define STV090x_P2_TSSPEED				STV090x_Px_TSSPEED(2)
+#define STV090x_OFFST_Px_TSFIFO_OUTSPEED_FIELD		0
+#define STV090x_WIDTH_Px_TSFIFO_OUTSPEED_FIELD		8
+
+#define STV090x_Px_TSSTATUS(__x)			(0xF581 - (__x - 1) * 0x200)
+#define STV090x_P1_TSSTATUS				STV090x_Px_TSSTATUS(1)
+#define STV090x_P2_TSSTATUS				STV090x_Px_TSSTATUS(2)
+#define STV090x_OFFST_Px_TSFIFO_LINEOK_FIELD		7
+#define STV090x_WIDTH_Px_TSFIFO_LINEOK_FIELD		1
+#define STV090x_OFFST_Px_TSFIFO_ERROR_FIELD		6
+#define STV090x_WIDTH_Px_TSFIFO_ERROR_FIELD		1
+
+#define STV090x_Px_TSSTATUS2(__x)			(0xF582 - (__x - 1) * 0x200)
+#define STV090x_P1_TSSTATUS2				STV090x_Px_TSSTATUS2(1)
+#define STV090x_P2_TSSTATUS2				STV090x_Px_TSSTATUS2(2)
+#define STV090x_OFFST_Px_TSFIFO_DEMODSEL_FIELD		7
+#define STV090x_WIDTH_Px_TSFIFO_DEMODSEL_FIELD		1
+#define STV090x_OFFST_Px_TSFIFOSPEED_STORE_FIELD	6
+#define STV090x_WIDTH_Px_TSFIFOSPEED_STORE_FIELD	1
+#define STV090x_OFFST_Px_DILXX_RESET_FIELD		5
+#define STV090x_WIDTH_Px_DILXX_RESET_FIELD		1
+#define STV090x_OFFST_Px_TSSERIAL_IMPOS_FIELD		4
+#define STV090x_WIDTH_Px_TSSERIAL_IMPOS_FIELD		1
+#define STV090x_OFFST_Px_SCRAMBDETECT_FIELD		1
+#define STV090x_WIDTH_Px_SCRAMBDETECT_FIELD		1
+
+#define STV090x_Px_TSBITRATEy(__x, __y)			(0xF584 - (__x - 1) * 0x200 - __y * 0x1)
+#define STV090x_P1_TSBITRATE0				STV090x_Px_TSBITRATEy(1, 0)
+#define STV090x_P1_TSBITRATE1				STV090x_Px_TSBITRATEy(1, 1)
+#define STV090x_P2_TSBITRATE0				STV090x_Px_TSBITRATEy(2, 0)
+#define STV090x_P2_TSBITRATE1				STV090x_Px_TSBITRATEy(2, 1)
+#define STV090x_OFFST_Px_TSFIFO_BITRATE_FIELD		0
+#define STV090x_WIDTH_Px_TSFIFO_BITRATE_FIELD		8
+
+#define STV090x_Px_ERRCTRL1(__x)			(0xF598 - (__x - 1) * 0x200)
+#define STV090x_P1_ERRCTRL1				STV090x_Px_ERRCTRL1(1)
+#define STV090x_P2_ERRCTRL1				STV090x_Px_ERRCTRL1(2)
+#define STV090x_OFFST_Px_ERR_SOURCE_FIELD		4
+#define STV090x_WIDTH_Px_ERR_SOURCE_FIELD		4
+#define STV090x_OFFST_Px_NUM_EVENT_FIELD		0
+#define STV090x_WIDTH_Px_NUM_EVENT_FIELD		3
+
+#define STV090x_Px_ERRCNT12(__x)			(0xF599 - (__x - 1) * 0x200)
+#define STV090x_P1_ERRCNT12				STV090x_Px_ERRCNT12(1)
+#define STV090x_P2_ERRCNT12				STV090x_Px_ERRCNT12(2)
+#define STV090x_OFFST_Px_ERRCNT1_OLDVALUE_FIELD		7
+#define STV090x_WIDTH_Px_ERRCNT1_OLDVALUE_FIELD		1
+#define STV090x_OFFST_Px_ERR_CNT12_FIELD		0
+#define STV090x_WIDTH_Px_ERR_CNT12_FIELD		7
+
+#define STV090x_Px_ERRCNT11(__x)			(0xF59A - (__x - 1) * 0x200)
+#define STV090x_P1_ERRCNT11				STV090x_Px_ERRCNT11(1)
+#define STV090x_P2_ERRCNT11				STV090x_Px_ERRCNT11(2)
+#define STV090x_OFFST_Px_ERR_CNT11_FIELD		0
+#define STV090x_WIDTH_Px_ERR_CNT11_FIELD		8
+
+#define STV090x_Px_ERRCNT10(__x)			(0xF59B - (__x - 1) * 0x200)
+#define STV090x_P1_ERRCNT10				STV090x_Px_ERRCNT10(1)
+#define STV090x_P2_ERRCNT10				STV090x_Px_ERRCNT10(2)
+#define STV090x_OFFST_Px_ERR_CNT10_FIELD		0
+#define STV090x_WIDTH_Px_ERR_CNT10_FIELD		8
+
+#define STV090x_Px_ERRCTRL2(__x)			(0xF59C - (__x - 1) * 0x200)
+#define STV090x_P1_ERRCTRL2				STV090x_Px_ERRCTRL2(1)
+#define STV090x_P2_ERRCTRL2				STV090x_Px_ERRCTRL2(2)
+#define STV090x_OFFST_Px_ERR_SOURCE2_FIELD		4
+#define STV090x_WIDTH_Px_ERR_SOURCE2_FIELD		4
+#define STV090x_OFFST_Px_NUM_EVENT2_FIELD		0
+#define STV090x_WIDTH_Px_NUM_EVENT2_FIELD		3
+
+#define STV090x_Px_ERRCNT22(__x)			(0xF59D - (__x - 1) * 0x200)
+#define STV090x_P1_ERRCNT22				STV090x_Px_ERRCNT22(1)
+#define STV090x_P2_ERRCNT22				STV090x_Px_ERRCNT22(2)
+#define STV090x_OFFST_Px_ERRCNT2_OLDVALUE_FIELD		7
+#define STV090x_WIDTH_Px_ERRCNT2_OLDVALUE_FIELD		1
+#define STV090x_OFFST_Px_ERR_CNT2_FIELD			0
+#define STV090x_WIDTH_Px_ERR_CNT2_FIELD			7
+
+#define STV090x_Px_ERRCNT21(__x)			(0xF59E - (__x - 1) * 0x200)
+#define STV090x_P1_ERRCNT21				STV090x_Px_ERRCNT21(1)
+#define STV090x_P2_ERRCNT21				STV090x_Px_ERRCNT21(2)
+#define STV090x_OFFST_Px_ERR_CNT21_FIELD		0
+#define STV090x_WIDTH_Px_ERR_CNT21_FIELD		8
+
+#define STV090x_Px_ERRCNT20(__x)			(0xF59F - (__x - 1) * 0x200)
+#define STV090x_P1_ERRCNT20				STV090x_Px_ERRCNT20(1)
+#define STV090x_P2_ERRCNT20				STV090x_Px_ERRCNT20(2)
+#define STV090x_OFFST_Px_ERR_CNT20_FIELD		0
+#define STV090x_WIDTH_Px_ERR_CNT20_FIELD		8
+
+#define STV090x_Px_FECSPY(__x)				(0xF5A0 - (__x - 1) * 0x200)
+#define STV090x_P1_FECSPY				STV090x_Px_FECSPY(1)
+#define STV090x_P2_FECSPY				STV090x_Px_FECSPY(2)
+#define STV090x_OFFST_Px_SPY_ENABLE_FIELD		7
+#define STV090x_WIDTH_Px_SPY_ENABLE_FIELD		1
+#define STV090x_OFFST_Px_BERMETER_DATAMAODE_FIELD	2
+#define STV090x_WIDTH_Px_BERMETER_DATAMAODE_FIELD	2
+
+#define STV090x_Px_FSPYCFG(__x)				(0xF5A1 - (__x - 1) * 0x200)
+#define STV090x_P1_FSPYCFG				STV090x_Px_FSPYCFG(1)
+#define STV090x_P2_FSPYCFG				STV090x_Px_FSPYCFG(2)
+#define STV090x_OFFST_Px_RST_ON_ERROR_FIELD		5
+#define STV090x_WIDTH_Px_RST_ON_ERROR_FIELD		1
+#define STV090x_OFFST_Px_ONE_SHOT_FIELD			4
+#define STV090x_WIDTH_Px_ONE_SHOT_FIELD			1
+#define STV090x_OFFST_Px_I2C_MODE_FIELD			2
+#define STV090x_WIDTH_Px_I2C_MODE_FIELD			2
+
+#define STV090x_Px_FSPYDATA(__x)			(0xF5A2 - (__x - 1) * 0x200)
+#define STV090x_P1_FSPYDATA				STV090x_Px_FSPYDATA(1)
+#define STV090x_P2_FSPYDATA				STV090x_Px_FSPYDATA(2)
+#define STV090x_OFFST_Px_SPY_STUFFING_FIELD		7
+#define STV090x_WIDTH_Px_SPY_STUFFING_FIELD		1
+#define STV090x_OFFST_Px_SPY_CNULLPKT_FIELD		5
+#define STV090x_WIDTH_Px_SPY_CNULLPKT_FIELD		1
+#define STV090x_OFFST_Px_SPY_OUTDATA_MODE_FIELD		0
+#define STV090x_WIDTH_Px_SPY_OUTDATA_MODE_FIELD		5
+
+#define STV090x_Px_FSPYOUT(__x)				(0xF5A3 - (__x - 1) * 0x200)
+#define STV090x_P1_FSPYOUT				STV090x_Px_FSPYOUT(1)
+#define STV090x_P2_FSPYOUT				STV090x_Px_FSPYOUT(2)
+#define STV090x_OFFST_Px_FSPY_DIRECT_FIELD		7
+#define STV090x_WIDTH_Px_FSPY_DIRECT_FIELD		1
+#define STV090x_OFFST_Px_STUFF_MODE_FIELD		0
+#define STV090x_WIDTH_Px_STUFF_MODE_FIELD		3
+
+#define STV090x_Px_FSTATUS(__x)				(0xF5A4 - (__x - 1) * 0x200)
+#define STV090x_P1_FSTATUS				STV090x_Px_FSTATUS(1)
+#define STV090x_P2_FSTATUS				STV090x_Px_FSTATUS(2)
+#define STV090x_OFFST_Px_SPY_ENDSIM_FIELD		7
+#define STV090x_WIDTH_Px_SPY_ENDSIM_FIELD		1
+#define STV090x_OFFST_Px_VALID_SIM_FIELD		6
+#define STV090x_WIDTH_Px_VALID_SIM_FIELD		1
+#define STV090x_OFFST_Px_FOUND_SIGNAL_FIELD		5
+#define STV090x_WIDTH_Px_FOUND_SIGNAL_FIELD		1
+#define STV090x_OFFST_Px_DSS_SYNCBYTE_FIELD		4
+#define STV090x_WIDTH_Px_DSS_SYNCBYTE_FIELD		1
+#define STV090x_OFFST_Px_RESULT_STATE_FIELD		0
+#define STV090x_WIDTH_Px_RESULT_STATE_FIELD		4
+
+#define STV090x_Px_FBERCPT4(__x)			(0xF5A8 - (__x - 1) * 0x200)
+#define STV090x_P1_FBERCPT4				STV090x_Px_FBERCPT4(1)
+#define STV090x_P2_FBERCPT4				STV090x_Px_FBERCPT4(2)
+#define STV090x_OFFST_Px_FBERMETER_CPT_FIELD		0
+#define STV090x_WIDTH_Px_FBERMETER_CPT_FIELD		8
+
+#define STV090x_Px_FBERCPT3(__x)			(0xF5A9 - (__x - 1) * 0x200)
+#define STV090x_P1_FBERCPT3				STV090x_Px_FBERCPT3(1)
+#define STV090x_P2_FBERCPT3				STV090x_Px_FBERCPT3(2)
+#define STV090x_OFFST_Px_FBERMETER_CPT_FIELD		0
+#define STV090x_WIDTH_Px_FBERMETER_CPT_FIELD		8
+
+#define STV090x_Px_FBERCPT2(__x)			(0xF5AA - (__x - 1) * 0x200)
+#define STV090x_P1_FBERCPT2				STV090x_Px_FBERCPT2(1)
+#define STV090x_P2_FBERCPT2				STV090x_Px_FBERCPT2(2)
+#define STV090x_OFFST_Px_FBERMETER_CPT_FIELD		0
+#define STV090x_WIDTH_Px_FBERMETER_CPT_FIELD		8
+
+#define STV090x_Px_FBERCPT1(__x)			(0xF5AB - (__x - 1) * 0x200)
+#define STV090x_P1_FBERCPT1				STV090x_Px_FBERCPT1(1)
+#define STV090x_P2_FBERCPT1				STV090x_Px_FBERCPT1(2)
+#define STV090x_OFFST_Px_FBERMETER_CPT_FIELD		0
+#define STV090x_WIDTH_Px_FBERMETER_CPT_FIELD		8
+
+#define STV090x_Px_FBERCPT0(__x)			(0xF5AC - (__x - 1) * 0x200)
+#define STV090x_P1_FBERCPT0				STV090x_Px_FBERCPT0(1)
+#define STV090x_P2_FBERCPT0				STV090x_Px_FBERCPT0(2)
+#define STV090x_OFFST_Px_FBERMETER_CPT_FIELD		0
+#define STV090x_WIDTH_Px_FBERMETER_CPT_FIELD		8
+
+#define STV090x_Px_FBERERRy(__x, __y)			(0xF5AF - (__x - 1) * 0x200 - __y * 0x1)
+#define STV090x_P1_FBERERR0				STV090x_Px_FBERERRy(1, 0)
+#define STV090x_P1_FBERERR1				STV090x_Px_FBERERRy(1, 1)
+#define STV090x_P1_FBERERR2				STV090x_Px_FBERERRy(1, 2)
+#define STV090x_P2_FBERERR0				STV090x_Px_FBERERRy(2, 0)
+#define STV090x_P2_FBERERR1				STV090x_Px_FBERERRy(2, 1)
+#define STV090x_P2_FBERERR2				STV090x_Px_FBERERRy(2, 2)
+#define STV090x_OFFST_Px_FBERMETER_CPT_ERR_FIELD	0
+#define STV090x_WIDTH_Px_FBERMETER_CPT_ERR_FIELD	8
+
+#define STV090x_Px_FSPYBER(__x)				(0xF5B2 - (__x - 1) * 0x200)
+#define STV090x_P1_FSPYBER				STV090x_Px_FSPYBER(1)
+#define STV090x_P2_FSPYBER				STV090x_Px_FSPYBER(2)
+#define STV090x_OFFST_Px_FSPYBER_SYNCBYTE_FIELD		4
+#define STV090x_WIDTH_Px_FSPYBER_SYNCBYTE_FIELD		1
+#define STV090x_OFFST_Px_FSPYBER_UNSYNC_FIELD		3
+#define STV090x_WIDTH_Px_FSPYBER_UNSYNC_FIELD		1
+#define STV090x_OFFST_Px_FSPYBER_CTIME_FIELD		0
+#define STV090x_WIDTH_Px_FSPYBER_CTIME_FIELD		3
+
+#define STV090x_RCCFGH					0xf600
+
+#define STV090x_TSGENERAL				0xF630
+#define STV090x_OFFST_Px_MUXSTREAM_OUT_FIELD		3
+#define STV090x_WIDTH_Px_MUXSTREAM_OUT_FIELD		1
+#define STV090x_OFFST_Px_TSFIFO_PERMPARAL_FIELD		1
+#define STV090x_WIDTH_Px_TSFIFO_PERMPARAL_FIELD		2
+
+#define STV090x_TSGENERAL1X				0xf670
+#define STV090x_CFGEXT					0xfa80
+
+#define STV090x_TSTRES0					0xFF11
+#define STV090x_OFFST_FRESFEC_FIELD			7
+#define STV090x_WIDTH_FRESFEC_FIELD			1
+
+#define STV090x_Px_TSTDISRX(__x)			(0xFF67 - (__x - 1) * 0x2)
+#define STV090x_P1_TSTDISRX				STV090x_Px_TSTDISRX(1)
+#define STV090x_P2_TSTDISRX				STV090x_Px_TSTDISRX(2)
+#define STV090x_OFFST_Px_TSTDISRX_SELECT_FIELD		3
+#define STV090x_WIDTH_Px_TSTDISRX_SELECT_FIELD		1
+
+#endif /* __STV090x_REG_H */
diff --git a/drivers/media/dvb-frontends/stv6110.c b/drivers/media/dvb-frontends/stv6110.c
new file mode 100644
index 0000000..20b5fa9
--- /dev/null
+++ b/drivers/media/dvb-frontends/stv6110.c
@@ -0,0 +1,451 @@
+/*
+ * 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/slab.h>
+#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 clk_div;
+	u8 gain;
+	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[] = {
+		{
+			.addr	= priv->i2c_address,
+			.flags	= 0,
+			.buf	= reg,
+			.len	= 1,
+		}, {
+			.addr	= priv->i2c_address,
+			.flags	= I2C_M_RD,
+			.buf	= regs,
+			.len	= len,
+		},
+	};
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+
+	rc = i2c_transfer(priv->i2c, msg, 2);
+	if (rc != 2)
+		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);
+
+	/* divisor value for the output clock */
+	priv->regs[RSTV6110_CTRL2] &= ~0xc0;
+	priv->regs[RSTV6110_CTRL2] |= (priv->clk_div << 6);
+
+	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;
+
+	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;
+
+	priv->regs[RSTV6110_CTRL2] &= ~0x0f;
+	priv->regs[RSTV6110_CTRL2] |= (priv->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 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;
+
+	/* divisor value for the output clock */
+	reg0[2] &= ~0xc0;
+	reg0[2] |= (config->clk_div << 6);
+
+	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;
+	priv->clk_div = config->clk_div;
+	priv->gain = config->gain;
+
+	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..fe71bba
--- /dev/null
+++ b/drivers/media/dvb-frontends/stv6110.h
@@ -0,0 +1,63 @@
+/*
+ * 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;
+	u8 gain;
+	u8 clk_div;	/* divisor value for the output clock */
+};
+
+#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/stv6110x.c b/drivers/media/dvb-frontends/stv6110x.c
new file mode 100644
index 0000000..f36cab1
--- /dev/null
+++ b/drivers/media/dvb-frontends/stv6110x.c
@@ -0,0 +1,405 @@
+/*
+	STV6110(A) Silicon tuner driver
+
+	Copyright (C) Manu Abraham <abraham.manu@gmail.com>
+
+	Copyright (C) ST Microelectronics
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the 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/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+
+#include "dvb_frontend.h"
+
+#include "stv6110x_reg.h"
+#include "stv6110x.h"
+#include "stv6110x_priv.h"
+
+static unsigned int verbose;
+module_param(verbose, int, 0644);
+MODULE_PARM_DESC(verbose, "Set Verbosity level");
+
+static int stv6110x_read_reg(struct stv6110x_state *stv6110x, u8 reg, u8 *data)
+{
+	int ret;
+	const struct stv6110x_config *config = stv6110x->config;
+	u8 b0[] = { reg };
+	u8 b1[] = { 0 };
+	struct i2c_msg msg[] = {
+		{ .addr = config->addr, .flags = 0, 	   .buf = b0, .len = 1 },
+		{ .addr = config->addr, .flags = I2C_M_RD, .buf = b1, .len = 1 }
+	};
+
+	ret = i2c_transfer(stv6110x->i2c, msg, 2);
+	if (ret != 2) {
+		dprintk(FE_ERROR, 1, "I/O Error");
+		return -EREMOTEIO;
+	}
+	*data = b1[0];
+
+	return 0;
+}
+
+static int stv6110x_write_regs(struct stv6110x_state *stv6110x, int start, u8 data[], int len)
+{
+	int ret;
+	const struct stv6110x_config *config = stv6110x->config;
+	u8 buf[len + 1];
+	struct i2c_msg msg = {
+		.addr = config->addr,
+		.flags = 0,
+		.buf = buf,
+		.len = len + 1
+	};
+
+	if (start + len > 8)
+		return -EINVAL;
+
+	buf[0] = start;
+	memcpy(&buf[1], data, len);
+
+	ret = i2c_transfer(stv6110x->i2c, &msg, 1);
+	if (ret != 1) {
+		dprintk(FE_ERROR, 1, "I/O Error");
+		return -EREMOTEIO;
+	}
+
+	return 0;
+}
+
+static int stv6110x_write_reg(struct stv6110x_state *stv6110x, u8 reg, u8 data)
+{
+	return stv6110x_write_regs(stv6110x, reg, &data, 1);
+}
+
+static int stv6110x_init(struct dvb_frontend *fe)
+{
+	struct stv6110x_state *stv6110x = fe->tuner_priv;
+	int ret;
+
+	ret = stv6110x_write_regs(stv6110x, 0, stv6110x->regs,
+				  ARRAY_SIZE(stv6110x->regs));
+	if (ret < 0) {
+		dprintk(FE_ERROR, 1, "Initialization failed");
+		return -1;
+	}
+
+	return 0;
+}
+
+static int stv6110x_set_frequency(struct dvb_frontend *fe, u32 frequency)
+{
+	struct stv6110x_state *stv6110x = fe->tuner_priv;
+	u32 rDiv, divider;
+	s32 pVal, pCalc, rDivOpt = 0, pCalcOpt = 1000;
+	u8 i;
+
+	STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL1], CTRL1_K, (REFCLOCK_MHz - 16));
+
+	if (frequency <= 1023000) {
+		STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_DIV4SEL, 1);
+		STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_PRESC32_ON, 0);
+		pVal = 40;
+	} else if (frequency <= 1300000) {
+		STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_DIV4SEL, 1);
+		STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_PRESC32_ON, 1);
+		pVal = 40;
+	} else if (frequency <= 2046000) {
+		STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_DIV4SEL, 0);
+		STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_PRESC32_ON, 0);
+		pVal = 20;
+	} else {
+		STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_DIV4SEL, 0);
+		STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_PRESC32_ON, 1);
+		pVal = 20;
+	}
+
+	for (rDiv = 0; rDiv <= 3; rDiv++) {
+		pCalc = (REFCLOCK_kHz / 100) / R_DIV(rDiv);
+
+		if ((abs((s32)(pCalc - pVal))) < (abs((s32)(pCalcOpt - pVal))))
+			rDivOpt = rDiv;
+
+		pCalcOpt = (REFCLOCK_kHz / 100) / R_DIV(rDivOpt);
+	}
+
+	divider = (frequency * R_DIV(rDivOpt) * pVal) / REFCLOCK_kHz;
+	divider = (divider + 5) / 10;
+
+	STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_R_DIV, rDivOpt);
+	STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_N_DIV_11_8, MSB(divider));
+	STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG0], TNG0_N_DIV_7_0, LSB(divider));
+
+	/* VCO Auto calibration */
+	STV6110x_SETFIELD(stv6110x->regs[STV6110x_STAT1], STAT1_CALVCO_STRT, 1);
+
+	stv6110x_write_reg(stv6110x, STV6110x_CTRL1, stv6110x->regs[STV6110x_CTRL1]);
+	stv6110x_write_reg(stv6110x, STV6110x_TNG1, stv6110x->regs[STV6110x_TNG1]);
+	stv6110x_write_reg(stv6110x, STV6110x_TNG0, stv6110x->regs[STV6110x_TNG0]);
+	stv6110x_write_reg(stv6110x, STV6110x_STAT1, stv6110x->regs[STV6110x_STAT1]);
+
+	for (i = 0; i < TRIALS; i++) {
+		stv6110x_read_reg(stv6110x, STV6110x_STAT1, &stv6110x->regs[STV6110x_STAT1]);
+		if (!STV6110x_GETFIELD(STAT1_CALVCO_STRT, stv6110x->regs[STV6110x_STAT1]))
+				break;
+		msleep(1);
+	}
+
+	return 0;
+}
+
+static int stv6110x_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+	struct stv6110x_state *stv6110x = fe->tuner_priv;
+
+	stv6110x_read_reg(stv6110x, STV6110x_TNG1, &stv6110x->regs[STV6110x_TNG1]);
+	stv6110x_read_reg(stv6110x, STV6110x_TNG0, &stv6110x->regs[STV6110x_TNG0]);
+
+	*frequency = (MAKEWORD16(STV6110x_GETFIELD(TNG1_N_DIV_11_8, stv6110x->regs[STV6110x_TNG1]),
+				 STV6110x_GETFIELD(TNG0_N_DIV_7_0, stv6110x->regs[STV6110x_TNG0]))) * REFCLOCK_kHz;
+
+	*frequency /= (1 << (STV6110x_GETFIELD(TNG1_R_DIV, stv6110x->regs[STV6110x_TNG1]) +
+			     STV6110x_GETFIELD(TNG1_DIV4SEL, stv6110x->regs[STV6110x_TNG1])));
+
+	*frequency >>= 2;
+
+	return 0;
+}
+
+static int stv6110x_set_bandwidth(struct dvb_frontend *fe, u32 bandwidth)
+{
+	struct stv6110x_state *stv6110x = fe->tuner_priv;
+	u32 halfbw;
+	u8 i;
+
+	halfbw = bandwidth >> 1;
+
+	if (halfbw > 36000000)
+		STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL3], CTRL3_CF, 31); /* LPF */
+	else if (halfbw < 5000000)
+		STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL3], CTRL3_CF, 0); /* LPF */
+	else
+		STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL3], CTRL3_CF, ((halfbw / 1000000) - 5)); /* LPF */
+
+
+	STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL3], CTRL3_RCCLK_OFF, 0x0); /* cal. clk activated */
+	STV6110x_SETFIELD(stv6110x->regs[STV6110x_STAT1], STAT1_CALRC_STRT, 0x1); /* LPF auto cal */
+
+	stv6110x_write_reg(stv6110x, STV6110x_CTRL3, stv6110x->regs[STV6110x_CTRL3]);
+	stv6110x_write_reg(stv6110x, STV6110x_STAT1, stv6110x->regs[STV6110x_STAT1]);
+
+	for (i = 0; i < TRIALS; i++) {
+		stv6110x_read_reg(stv6110x, STV6110x_STAT1, &stv6110x->regs[STV6110x_STAT1]);
+		if (!STV6110x_GETFIELD(STAT1_CALRC_STRT, stv6110x->regs[STV6110x_STAT1]))
+			break;
+		msleep(1);
+	}
+	STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL3], CTRL3_RCCLK_OFF, 0x1); /* cal. done */
+	stv6110x_write_reg(stv6110x, STV6110x_CTRL3, stv6110x->regs[STV6110x_CTRL3]);
+
+	return 0;
+}
+
+static int stv6110x_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
+{
+	struct stv6110x_state *stv6110x = fe->tuner_priv;
+
+	stv6110x_read_reg(stv6110x, STV6110x_CTRL3, &stv6110x->regs[STV6110x_CTRL3]);
+	*bandwidth = (STV6110x_GETFIELD(CTRL3_CF, stv6110x->regs[STV6110x_CTRL3]) + 5) * 2000000;
+
+	return 0;
+}
+
+static int stv6110x_set_refclock(struct dvb_frontend *fe, u32 refclock)
+{
+	struct stv6110x_state *stv6110x = fe->tuner_priv;
+
+	/* setup divider */
+	switch (refclock) {
+	default:
+	case 1:
+		STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 0);
+		break;
+	case 2:
+		STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 1);
+		break;
+	case 4:
+		STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 2);
+		break;
+	case 8:
+	case 0:
+		STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 3);
+		break;
+	}
+	stv6110x_write_reg(stv6110x, STV6110x_CTRL2, stv6110x->regs[STV6110x_CTRL2]);
+
+	return 0;
+}
+
+static int stv6110x_get_bbgain(struct dvb_frontend *fe, u32 *gain)
+{
+	struct stv6110x_state *stv6110x = fe->tuner_priv;
+
+	stv6110x_read_reg(stv6110x, STV6110x_CTRL2, &stv6110x->regs[STV6110x_CTRL2]);
+	*gain = 2 * STV6110x_GETFIELD(CTRL2_BBGAIN, stv6110x->regs[STV6110x_CTRL2]);
+
+	return 0;
+}
+
+static int stv6110x_set_bbgain(struct dvb_frontend *fe, u32 gain)
+{
+	struct stv6110x_state *stv6110x = fe->tuner_priv;
+
+	STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_BBGAIN, gain / 2);
+	stv6110x_write_reg(stv6110x, STV6110x_CTRL2, stv6110x->regs[STV6110x_CTRL2]);
+
+	return 0;
+}
+
+static int stv6110x_set_mode(struct dvb_frontend *fe, enum tuner_mode mode)
+{
+	struct stv6110x_state *stv6110x = fe->tuner_priv;
+	int ret;
+
+	switch (mode) {
+	case TUNER_SLEEP:
+		STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL1], CTRL1_SYN, 0);
+		STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL1], CTRL1_RX, 0);
+		STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL1], CTRL1_LPT, 0);
+		break;
+
+	case TUNER_WAKE:
+		STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL1], CTRL1_SYN, 1);
+		STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL1], CTRL1_RX, 1);
+		STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL1], CTRL1_LPT, 1);
+		break;
+	}
+
+	ret = stv6110x_write_reg(stv6110x, STV6110x_CTRL1, stv6110x->regs[STV6110x_CTRL1]);
+	if (ret < 0) {
+		dprintk(FE_ERROR, 1, "I/O Error");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int stv6110x_sleep(struct dvb_frontend *fe)
+{
+	if (fe->tuner_priv)
+		return stv6110x_set_mode(fe, TUNER_SLEEP);
+
+	return 0;
+}
+
+static int stv6110x_get_status(struct dvb_frontend *fe, u32 *status)
+{
+	struct stv6110x_state *stv6110x = fe->tuner_priv;
+
+	stv6110x_read_reg(stv6110x, STV6110x_STAT1, &stv6110x->regs[STV6110x_STAT1]);
+
+	if (STV6110x_GETFIELD(STAT1_LOCK, stv6110x->regs[STV6110x_STAT1]))
+		*status = TUNER_PHASELOCKED;
+	else
+		*status = 0;
+
+	return 0;
+}
+
+
+static int stv6110x_release(struct dvb_frontend *fe)
+{
+	struct stv6110x_state *stv6110x = fe->tuner_priv;
+
+	fe->tuner_priv = NULL;
+	kfree(stv6110x);
+
+	return 0;
+}
+
+static struct dvb_tuner_ops stv6110x_ops = {
+	.info = {
+		.name		= "STV6110(A) Silicon Tuner",
+		.frequency_min	=  950000,
+		.frequency_max	= 2150000,
+		.frequency_step	= 0,
+	},
+	.release		= stv6110x_release
+};
+
+static struct stv6110x_devctl stv6110x_ctl = {
+	.tuner_init		= stv6110x_init,
+	.tuner_sleep		= stv6110x_sleep,
+	.tuner_set_mode		= stv6110x_set_mode,
+	.tuner_set_frequency	= stv6110x_set_frequency,
+	.tuner_get_frequency	= stv6110x_get_frequency,
+	.tuner_set_bandwidth	= stv6110x_set_bandwidth,
+	.tuner_get_bandwidth	= stv6110x_get_bandwidth,
+	.tuner_set_bbgain	= stv6110x_set_bbgain,
+	.tuner_get_bbgain	= stv6110x_get_bbgain,
+	.tuner_set_refclk	= stv6110x_set_refclock,
+	.tuner_get_status	= stv6110x_get_status,
+};
+
+struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe,
+					const struct stv6110x_config *config,
+					struct i2c_adapter *i2c)
+{
+	struct stv6110x_state *stv6110x;
+	u8 default_regs[] = {0x07, 0x11, 0xdc, 0x85, 0x17, 0x01, 0xe6, 0x1e};
+
+	stv6110x = kzalloc(sizeof (struct stv6110x_state), GFP_KERNEL);
+	if (!stv6110x)
+		return NULL;
+
+	stv6110x->i2c		= i2c;
+	stv6110x->config	= config;
+	stv6110x->devctl	= &stv6110x_ctl;
+	memcpy(stv6110x->regs, default_regs, 8);
+
+	/* setup divider */
+	switch (stv6110x->config->clk_div) {
+	default:
+	case 1:
+		STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 0);
+		break;
+	case 2:
+		STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 1);
+		break;
+	case 4:
+		STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 2);
+		break;
+	case 8:
+	case 0:
+		STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 3);
+		break;
+	}
+
+	fe->tuner_priv		= stv6110x;
+	fe->ops.tuner_ops	= stv6110x_ops;
+
+	printk(KERN_INFO "%s: Attaching STV6110x\n", __func__);
+	return stv6110x->devctl;
+}
+EXPORT_SYMBOL(stv6110x_attach);
+
+MODULE_AUTHOR("Manu Abraham");
+MODULE_DESCRIPTION("STV6110x Silicon tuner");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb-frontends/stv6110x.h b/drivers/media/dvb-frontends/stv6110x.h
new file mode 100644
index 0000000..47516753
--- /dev/null
+++ b/drivers/media/dvb-frontends/stv6110x.h
@@ -0,0 +1,73 @@
+/*
+	STV6110(A) Silicon tuner driver
+
+	Copyright (C) Manu Abraham <abraham.manu@gmail.com>
+
+	Copyright (C) ST Microelectronics
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the 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 __STV6110x_H
+#define __STV6110x_H
+
+struct stv6110x_config {
+	u8	addr;
+	u32	refclk;
+	u8	clk_div; /* divisor value for the output clock */
+};
+
+enum tuner_mode {
+	TUNER_SLEEP = 1,
+	TUNER_WAKE,
+};
+
+enum tuner_status {
+	TUNER_PHASELOCKED = 1,
+};
+
+struct stv6110x_devctl {
+	int (*tuner_init) (struct dvb_frontend *fe);
+	int (*tuner_sleep) (struct dvb_frontend *fe);
+	int (*tuner_set_mode) (struct dvb_frontend *fe, enum tuner_mode mode);
+	int (*tuner_set_frequency) (struct dvb_frontend *fe, u32 frequency);
+	int (*tuner_get_frequency) (struct dvb_frontend *fe, u32 *frequency);
+	int (*tuner_set_bandwidth) (struct dvb_frontend *fe, u32 bandwidth);
+	int (*tuner_get_bandwidth) (struct dvb_frontend *fe, u32 *bandwidth);
+	int (*tuner_set_bbgain) (struct dvb_frontend *fe, u32 gain);
+	int (*tuner_get_bbgain) (struct dvb_frontend *fe, u32 *gain);
+	int (*tuner_set_refclk)  (struct dvb_frontend *fe, u32 refclk);
+	int (*tuner_get_status) (struct dvb_frontend *fe, u32 *status);
+};
+
+
+#if defined(CONFIG_DVB_STV6110x) || (defined(CONFIG_DVB_STV6110x_MODULE) && defined(MODULE))
+
+extern struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe,
+					       const struct stv6110x_config *config,
+					       struct i2c_adapter *i2c);
+
+#else
+static inline struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe,
+						      const struct stv6110x_config *config,
+						      struct i2c_adapter *i2c)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+
+#endif /* CONFIG_DVB_STV6110x */
+
+#endif /* __STV6110x_H */
diff --git a/drivers/media/dvb-frontends/stv6110x_priv.h b/drivers/media/dvb-frontends/stv6110x_priv.h
new file mode 100644
index 0000000..0ec936a
--- /dev/null
+++ b/drivers/media/dvb-frontends/stv6110x_priv.h
@@ -0,0 +1,76 @@
+/*
+	STV6110(A) Silicon tuner driver
+
+	Copyright (C) Manu Abraham <abraham.manu@gmail.com>
+
+	Copyright (C) ST Microelectronics
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the 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 __STV6110x_PRIV_H
+#define __STV6110x_PRIV_H
+
+#define FE_ERROR				0
+#define FE_NOTICE				1
+#define FE_INFO					2
+#define FE_DEBUG				3
+#define FE_DEBUGREG				4
+
+#define dprintk(__y, __z, format, arg...) do {						\
+	if (__z) {									\
+		if	((verbose > FE_ERROR) && (verbose > __y))			\
+			printk(KERN_ERR "%s: " format "\n", __func__ , ##arg);		\
+		else if	((verbose > FE_NOTICE) && (verbose > __y))			\
+			printk(KERN_NOTICE "%s: " format "\n", __func__ , ##arg);	\
+		else if ((verbose > FE_INFO) && (verbose > __y))			\
+			printk(KERN_INFO "%s: " format "\n", __func__ , ##arg);		\
+		else if ((verbose > FE_DEBUG) && (verbose > __y))			\
+			printk(KERN_DEBUG "%s: " format "\n", __func__ , ##arg);	\
+	} else {									\
+		if (verbose > __y)							\
+			printk(format, ##arg);						\
+	}										\
+} while (0)
+
+
+#define STV6110x_SETFIELD(mask, bitf, val)				\
+	(mask = (mask & (~(((1 << STV6110x_WIDTH_##bitf) - 1) <<	\
+				  STV6110x_OFFST_##bitf))) | 		\
+			  (val << STV6110x_OFFST_##bitf))
+
+#define STV6110x_GETFIELD(bitf, val)					\
+	((val >> STV6110x_OFFST_##bitf) & 				\
+	((1 << STV6110x_WIDTH_##bitf) - 1))
+
+#define MAKEWORD16(a, b)			(((a) << 8) | (b))
+
+#define LSB(x)					((x & 0xff))
+#define MSB(y)					((y >> 8) & 0xff)
+
+#define TRIALS					10
+#define R_DIV(__div)				(1 << (__div + 1))
+#define REFCLOCK_kHz				(stv6110x->config->refclk /    1000)
+#define REFCLOCK_MHz				(stv6110x->config->refclk / 1000000)
+
+struct stv6110x_state {
+	struct i2c_adapter		*i2c;
+	const struct stv6110x_config	*config;
+	u8 				regs[8];
+
+	struct stv6110x_devctl		*devctl;
+};
+
+#endif /* __STV6110x_PRIV_H */
diff --git a/drivers/media/dvb-frontends/stv6110x_reg.h b/drivers/media/dvb-frontends/stv6110x_reg.h
new file mode 100644
index 0000000..93e5c70
--- /dev/null
+++ b/drivers/media/dvb-frontends/stv6110x_reg.h
@@ -0,0 +1,82 @@
+/*
+	STV6110(A) Silicon tuner driver
+
+	Copyright (C) Manu Abraham <abraham.manu@gmail.com>
+
+	Copyright (C) ST Microelectronics
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the 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 __STV6110x_REG_H
+#define __STV6110x_REG_H
+
+#define STV6110x_CTRL1				0x00
+#define STV6110x_OFFST_CTRL1_K			3
+#define STV6110x_WIDTH_CTRL1_K			5
+#define STV6110x_OFFST_CTRL1_LPT		2
+#define STV6110x_WIDTH_CTRL1_LPT		1
+#define STV6110x_OFFST_CTRL1_RX			1
+#define STV6110x_WIDTH_CTRL1_RX			1
+#define STV6110x_OFFST_CTRL1_SYN		0
+#define STV6110x_WIDTH_CTRL1_SYN		1
+
+#define STV6110x_CTRL2				0x01
+#define STV6110x_OFFST_CTRL2_CO_DIV		6
+#define STV6110x_WIDTH_CTRL2_CO_DIV		2
+#define STV6110x_OFFST_CTRL2_RSVD		5
+#define STV6110x_WIDTH_CTRL2_RSVD		1
+#define STV6110x_OFFST_CTRL2_REFOUT_SEL		4
+#define STV6110x_WIDTH_CTRL2_REFOUT_SEL		1
+#define STV6110x_OFFST_CTRL2_BBGAIN		0
+#define STV6110x_WIDTH_CTRL2_BBGAIN		4
+
+#define STV6110x_TNG0				0x02
+#define STV6110x_OFFST_TNG0_N_DIV_7_0		0
+#define STV6110x_WIDTH_TNG0_N_DIV_7_0		8
+
+#define STV6110x_TNG1				0x03
+#define STV6110x_OFFST_TNG1_R_DIV		6
+#define STV6110x_WIDTH_TNG1_R_DIV		2
+#define STV6110x_OFFST_TNG1_PRESC32_ON		5
+#define STV6110x_WIDTH_TNG1_PRESC32_ON		1
+#define STV6110x_OFFST_TNG1_DIV4SEL		4
+#define STV6110x_WIDTH_TNG1_DIV4SEL		1
+#define STV6110x_OFFST_TNG1_N_DIV_11_8		0
+#define STV6110x_WIDTH_TNG1_N_DIV_11_8		4
+
+
+#define STV6110x_CTRL3				0x04
+#define STV6110x_OFFST_CTRL3_DCLOOP_OFF		7
+#define STV6110x_WIDTH_CTRL3_DCLOOP_OFF		1
+#define STV6110x_OFFST_CTRL3_RCCLK_OFF		6
+#define STV6110x_WIDTH_CTRL3_RCCLK_OFF		1
+#define STV6110x_OFFST_CTRL3_ICP		5
+#define STV6110x_WIDTH_CTRL3_ICP		1
+#define STV6110x_OFFST_CTRL3_CF			0
+#define STV6110x_WIDTH_CTRL3_CF			5
+
+#define STV6110x_STAT1				0x05
+#define STV6110x_OFFST_STAT1_CALVCO_STRT	2
+#define STV6110x_WIDTH_STAT1_CALVCO_STRT	1
+#define STV6110x_OFFST_STAT1_CALRC_STRT		1
+#define STV6110x_WIDTH_STAT1_CALRC_STRT		1
+#define STV6110x_OFFST_STAT1_LOCK		0
+#define STV6110x_WIDTH_STAT1_LOCK		1
+
+#define STV6110x_STAT2				0x06
+#define STV6110x_STAT3				0x07
+
+#endif /* __STV6110x_REG_H */
diff --git a/drivers/media/dvb-frontends/tda10021.c b/drivers/media/dvb-frontends/tda10021.c
new file mode 100644
index 0000000..1bff7f4
--- /dev/null
+++ b/drivers/media/dvb-frontends/tda10021.c
@@ -0,0 +1,528 @@
+/*
+    TDA10021  - Single Chip Cable Channel Receiver driver module
+	       used on the Siemens DVB-C cards
+
+    Copyright (C) 1999 Convergence Integrated Media GmbH <ralph@convergence.de>
+    Copyright (C) 2004 Markus Schulz <msc@antzsystem.de>
+		   Support for TDA10021
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the 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/delay.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+
+#include "dvb_frontend.h"
+#include "tda1002x.h"
+
+
+struct tda10021_state {
+	struct i2c_adapter* i2c;
+	/* configuration settings */
+	const struct tda1002x_config* config;
+	struct dvb_frontend frontend;
+
+	u8 pwm;
+	u8 reg0;
+};
+
+
+#if 0
+#define dprintk(x...) printk(x)
+#else
+#define dprintk(x...)
+#endif
+
+static int verbose;
+
+#define XIN 57840000UL
+
+#define FIN (XIN >> 4)
+
+static int tda10021_inittab_size = 0x40;
+static u8 tda10021_inittab[0x40]=
+{
+	0x73, 0x6a, 0x23, 0x0a, 0x02, 0x37, 0x77, 0x1a,
+	0x37, 0x6a, 0x17, 0x8a, 0x1e, 0x86, 0x43, 0x40,
+	0xb8, 0x3f, 0xa1, 0x00, 0xcd, 0x01, 0x00, 0xff,
+	0x11, 0x00, 0x7c, 0x31, 0x30, 0x20, 0x00, 0x00,
+	0x02, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x00, 0x00,
+	0x07, 0x00, 0x33, 0x11, 0x0d, 0x95, 0x08, 0x58,
+	0x00, 0x00, 0x80, 0x00, 0x80, 0xff, 0x00, 0x00,
+	0x04, 0x2d, 0x2f, 0xff, 0x00, 0x00, 0x00, 0x00,
+};
+
+static int _tda10021_writereg (struct tda10021_state* state, u8 reg, u8 data)
+{
+	u8 buf[] = { reg, data };
+	struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 };
+	int ret;
+
+	ret = i2c_transfer (state->i2c, &msg, 1);
+	if (ret != 1)
+		printk("DVB: TDA10021(%d): %s, writereg error "
+			"(reg == 0x%02x, val == 0x%02x, ret == %i)\n",
+			state->frontend.dvb->num, __func__, reg, data, ret);
+
+	msleep(10);
+	return (ret != 1) ? -EREMOTEIO : 0;
+}
+
+static u8 tda10021_readreg (struct tda10021_state* state, u8 reg)
+{
+	u8 b0 [] = { reg };
+	u8 b1 [] = { 0 };
+	struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 },
+				  { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } };
+	int ret;
+
+	ret = i2c_transfer (state->i2c, msg, 2);
+	// Don't print an error message if the id is read.
+	if (ret != 2 && reg != 0x1a)
+		printk("DVB: TDA10021: %s: readreg error (ret == %i)\n",
+				__func__, ret);
+	return b1[0];
+}
+
+//get access to tuner
+static int lock_tuner(struct tda10021_state* state)
+{
+	u8 buf[2] = { 0x0f, tda10021_inittab[0x0f] | 0x80 };
+	struct i2c_msg msg = {.addr=state->config->demod_address, .flags=0, .buf=buf, .len=2};
+
+	if(i2c_transfer(state->i2c, &msg, 1) != 1)
+	{
+		printk("tda10021: lock tuner fails\n");
+		return -EREMOTEIO;
+	}
+	return 0;
+}
+
+//release access from tuner
+static int unlock_tuner(struct tda10021_state* state)
+{
+	u8 buf[2] = { 0x0f, tda10021_inittab[0x0f] & 0x7f };
+	struct i2c_msg msg_post={.addr=state->config->demod_address, .flags=0, .buf=buf, .len=2};
+
+	if(i2c_transfer(state->i2c, &msg_post, 1) != 1)
+	{
+		printk("tda10021: unlock tuner fails\n");
+		return -EREMOTEIO;
+	}
+	return 0;
+}
+
+static int tda10021_setup_reg0 (struct tda10021_state* state, u8 reg0,
+				fe_spectral_inversion_t inversion)
+{
+	reg0 |= state->reg0 & 0x63;
+
+	if ((INVERSION_ON == inversion) ^ (state->config->invert == 0))
+		reg0 &= ~0x20;
+	else
+		reg0 |= 0x20;
+
+	_tda10021_writereg (state, 0x00, reg0 & 0xfe);
+	_tda10021_writereg (state, 0x00, reg0 | 0x01);
+
+	state->reg0 = reg0;
+	return 0;
+}
+
+static int tda10021_set_symbolrate (struct tda10021_state* state, u32 symbolrate)
+{
+	s32 BDR;
+	s32 BDRI;
+	s16 SFIL=0;
+	u16 NDEC = 0;
+	u32 tmp, ratio;
+
+	if (symbolrate > XIN/2)
+		symbolrate = XIN/2;
+	if (symbolrate < 500000)
+		symbolrate = 500000;
+
+	if (symbolrate < XIN/16) NDEC = 1;
+	if (symbolrate < XIN/32) NDEC = 2;
+	if (symbolrate < XIN/64) NDEC = 3;
+
+	if (symbolrate < (u32)(XIN/12.3)) SFIL = 1;
+	if (symbolrate < (u32)(XIN/16))	 SFIL = 0;
+	if (symbolrate < (u32)(XIN/24.6)) SFIL = 1;
+	if (symbolrate < (u32)(XIN/32))	 SFIL = 0;
+	if (symbolrate < (u32)(XIN/49.2)) SFIL = 1;
+	if (symbolrate < (u32)(XIN/64))	 SFIL = 0;
+	if (symbolrate < (u32)(XIN/98.4)) SFIL = 1;
+
+	symbolrate <<= NDEC;
+	ratio = (symbolrate << 4) / FIN;
+	tmp =  ((symbolrate << 4) % FIN) << 8;
+	ratio = (ratio << 8) + tmp / FIN;
+	tmp = (tmp % FIN) << 8;
+	ratio = (ratio << 8) + DIV_ROUND_CLOSEST(tmp, FIN);
+
+	BDR = ratio;
+	BDRI = (((XIN << 5) / symbolrate) + 1) / 2;
+
+	if (BDRI > 0xFF)
+		BDRI = 0xFF;
+
+	SFIL = (SFIL << 4) | tda10021_inittab[0x0E];
+
+	NDEC = (NDEC << 6) | tda10021_inittab[0x03];
+
+	_tda10021_writereg (state, 0x03, NDEC);
+	_tda10021_writereg (state, 0x0a, BDR&0xff);
+	_tda10021_writereg (state, 0x0b, (BDR>> 8)&0xff);
+	_tda10021_writereg (state, 0x0c, (BDR>>16)&0x3f);
+
+	_tda10021_writereg (state, 0x0d, BDRI);
+	_tda10021_writereg (state, 0x0e, SFIL);
+
+	return 0;
+}
+
+static int tda10021_init (struct dvb_frontend *fe)
+{
+	struct tda10021_state* state = fe->demodulator_priv;
+	int i;
+
+	dprintk("DVB: TDA10021(%d): init chip\n", fe->adapter->num);
+
+	//_tda10021_writereg (fe, 0, 0);
+
+	for (i=0; i<tda10021_inittab_size; i++)
+		_tda10021_writereg (state, i, tda10021_inittab[i]);
+
+	_tda10021_writereg (state, 0x34, state->pwm);
+
+	//Comment by markus
+	//0x2A[3-0] == PDIV -> P multiplaying factor (P=PDIV+1)(default 0)
+	//0x2A[4] == BYPPLL -> Power down mode (default 1)
+	//0x2A[5] == LCK -> PLL Lock Flag
+	//0x2A[6] == POLAXIN -> Polarity of the input reference clock (default 0)
+
+	//Activate PLL
+	_tda10021_writereg(state, 0x2a, tda10021_inittab[0x2a] & 0xef);
+	return 0;
+}
+
+struct qam_params {
+	u8 conf, agcref, lthr, mseth, aref;
+};
+
+static int tda10021_set_parameters(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	u32 delsys  = c->delivery_system;
+	unsigned qam = c->modulation;
+	bool is_annex_c;
+	u32 reg0x3d;
+	struct tda10021_state* state = fe->demodulator_priv;
+	static const struct qam_params qam_params[] = {
+		/* Modulation  Conf  AGCref  LTHR  MSETH  AREF */
+		[QPSK]	   = { 0x14, 0x78,   0x78, 0x8c,  0x96 },
+		[QAM_16]   = { 0x00, 0x8c,   0x87, 0xa2,  0x91 },
+		[QAM_32]   = { 0x04, 0x8c,   0x64, 0x74,  0x96 },
+		[QAM_64]   = { 0x08, 0x6a,   0x46, 0x43,  0x6a },
+		[QAM_128]  = { 0x0c, 0x78,   0x36, 0x34,  0x7e },
+		[QAM_256]  = { 0x10, 0x5c,   0x26, 0x23,  0x6b },
+	};
+
+	switch (delsys) {
+	case SYS_DVBC_ANNEX_A:
+		is_annex_c = false;
+		break;
+	case SYS_DVBC_ANNEX_C:
+		is_annex_c = true;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/*
+	 * gcc optimizes the code bellow the same way as it would code:
+	 *           "if (qam > 5) return -EINVAL;"
+	 * Yet, the code is clearer, as it shows what QAM standards are
+	 * supported by the driver, and avoids the usage of magic numbers on
+	 * it.
+	 */
+	switch (qam) {
+	case QPSK:
+	case QAM_16:
+	case QAM_32:
+	case QAM_64:
+	case QAM_128:
+	case QAM_256:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (c->inversion != INVERSION_ON && c->inversion != INVERSION_OFF)
+		return -EINVAL;
+
+	/*printk("tda10021: set frequency to %d qam=%d symrate=%d\n", p->frequency,qam,p->symbol_rate);*/
+
+	if (fe->ops.tuner_ops.set_params) {
+		fe->ops.tuner_ops.set_params(fe);
+		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+	}
+
+	tda10021_set_symbolrate(state, c->symbol_rate);
+	_tda10021_writereg(state, 0x34, state->pwm);
+
+	_tda10021_writereg(state, 0x01, qam_params[qam].agcref);
+	_tda10021_writereg(state, 0x05, qam_params[qam].lthr);
+	_tda10021_writereg(state, 0x08, qam_params[qam].mseth);
+	_tda10021_writereg(state, 0x09, qam_params[qam].aref);
+
+	/*
+	 * Bit 0 == 0 means roll-off = 0.15 (Annex A)
+	 *	 == 1 means roll-off = 0.13 (Annex C)
+	 */
+	reg0x3d = tda10021_readreg (state, 0x3d);
+	if (is_annex_c)
+		_tda10021_writereg (state, 0x3d, 0x01 | reg0x3d);
+	else
+		_tda10021_writereg (state, 0x3d, 0xfe & reg0x3d);
+	tda10021_setup_reg0(state, qam_params[qam].conf, c->inversion);
+
+	return 0;
+}
+
+static int tda10021_read_status(struct dvb_frontend* fe, fe_status_t* status)
+{
+	struct tda10021_state* state = fe->demodulator_priv;
+	int sync;
+
+	*status = 0;
+	//0x11[0] == EQALGO -> Equalizer algorithms state
+	//0x11[1] == CARLOCK -> Carrier locked
+	//0x11[2] == FSYNC -> Frame synchronisation
+	//0x11[3] == FEL -> Front End locked
+	//0x11[6] == NODVB -> DVB Mode Information
+	sync = tda10021_readreg (state, 0x11);
+
+	if (sync & 2)
+		*status |= FE_HAS_SIGNAL|FE_HAS_CARRIER;
+
+	if (sync & 4)
+		*status |= FE_HAS_SYNC|FE_HAS_VITERBI;
+
+	if (sync & 8)
+		*status |= FE_HAS_LOCK;
+
+	return 0;
+}
+
+static int tda10021_read_ber(struct dvb_frontend* fe, u32* ber)
+{
+	struct tda10021_state* state = fe->demodulator_priv;
+
+	u32 _ber = tda10021_readreg(state, 0x14) |
+		(tda10021_readreg(state, 0x15) << 8) |
+		((tda10021_readreg(state, 0x16) & 0x0f) << 16);
+	_tda10021_writereg(state, 0x10, (tda10021_readreg(state, 0x10) & ~0xc0)
+					| (tda10021_inittab[0x10] & 0xc0));
+	*ber = 10 * _ber;
+
+	return 0;
+}
+
+static int tda10021_read_signal_strength(struct dvb_frontend* fe, u16* strength)
+{
+	struct tda10021_state* state = fe->demodulator_priv;
+
+	u8 config = tda10021_readreg(state, 0x02);
+	u8 gain = tda10021_readreg(state, 0x17);
+	if (config & 0x02)
+		/* the agc value is inverted */
+		gain = ~gain;
+	*strength = (gain << 8) | gain;
+
+	return 0;
+}
+
+static int tda10021_read_snr(struct dvb_frontend* fe, u16* snr)
+{
+	struct tda10021_state* state = fe->demodulator_priv;
+
+	u8 quality = ~tda10021_readreg(state, 0x18);
+	*snr = (quality << 8) | quality;
+
+	return 0;
+}
+
+static int tda10021_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
+{
+	struct tda10021_state* state = fe->demodulator_priv;
+
+	*ucblocks = tda10021_readreg (state, 0x13) & 0x7f;
+	if (*ucblocks == 0x7f)
+		*ucblocks = 0xffffffff;
+
+	/* reset uncorrected block counter */
+	_tda10021_writereg (state, 0x10, tda10021_inittab[0x10] & 0xdf);
+	_tda10021_writereg (state, 0x10, tda10021_inittab[0x10]);
+
+	return 0;
+}
+
+static int tda10021_get_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct tda10021_state* state = fe->demodulator_priv;
+	int sync;
+	s8 afc = 0;
+
+	sync = tda10021_readreg(state, 0x11);
+	afc = tda10021_readreg(state, 0x19);
+	if (verbose) {
+		/* AFC only valid when carrier has been recovered */
+		printk(sync & 2 ? "DVB: TDA10021(%d): AFC (%d) %dHz\n" :
+				  "DVB: TDA10021(%d): [AFC (%d) %dHz]\n",
+			state->frontend.dvb->num, afc,
+		       -((s32)p->symbol_rate * afc) >> 10);
+	}
+
+	p->inversion = ((state->reg0 & 0x20) == 0x20) ^ (state->config->invert != 0) ? INVERSION_ON : INVERSION_OFF;
+	p->modulation = ((state->reg0 >> 2) & 7) + QAM_16;
+
+	p->fec_inner = FEC_NONE;
+	p->frequency = ((p->frequency + 31250) / 62500) * 62500;
+
+	if (sync & 2)
+		p->frequency -= ((s32)p->symbol_rate * afc) >> 10;
+
+	return 0;
+}
+
+static int tda10021_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+{
+	struct tda10021_state* state = fe->demodulator_priv;
+
+	if (enable) {
+		lock_tuner(state);
+	} else {
+		unlock_tuner(state);
+	}
+	return 0;
+}
+
+static int tda10021_sleep(struct dvb_frontend* fe)
+{
+	struct tda10021_state* state = fe->demodulator_priv;
+
+	_tda10021_writereg (state, 0x1b, 0x02);  /* pdown ADC */
+	_tda10021_writereg (state, 0x00, 0x80);  /* standby */
+
+	return 0;
+}
+
+static void tda10021_release(struct dvb_frontend* fe)
+{
+	struct tda10021_state* state = fe->demodulator_priv;
+	kfree(state);
+}
+
+static struct dvb_frontend_ops tda10021_ops;
+
+struct dvb_frontend* tda10021_attach(const struct tda1002x_config* config,
+				     struct i2c_adapter* i2c,
+				     u8 pwm)
+{
+	struct tda10021_state* state = NULL;
+	u8 id;
+
+	/* allocate memory for the internal state */
+	state = kzalloc(sizeof(struct tda10021_state), GFP_KERNEL);
+	if (state == NULL) goto error;
+
+	/* setup the state */
+	state->config = config;
+	state->i2c = i2c;
+	state->pwm = pwm;
+	state->reg0 = tda10021_inittab[0];
+
+	/* check if the demod is there */
+	id = tda10021_readreg(state, 0x1a);
+	if ((id & 0xf0) != 0x70) goto error;
+
+	/* Don't claim TDA10023 */
+	if (id == 0x7d)
+		goto error;
+
+	printk("TDA10021: i2c-addr = 0x%02x, id = 0x%02x\n",
+	       state->config->demod_address, id);
+
+	/* create dvb_frontend */
+	memcpy(&state->frontend.ops, &tda10021_ops, sizeof(struct dvb_frontend_ops));
+	state->frontend.demodulator_priv = state;
+	return &state->frontend;
+
+error:
+	kfree(state);
+	return NULL;
+}
+
+static struct dvb_frontend_ops tda10021_ops = {
+	.delsys = { SYS_DVBC_ANNEX_A, SYS_DVBC_ANNEX_C },
+	.info = {
+		.name = "Philips TDA10021 DVB-C",
+		.frequency_stepsize = 62500,
+		.frequency_min = 47000000,
+		.frequency_max = 862000000,
+		.symbol_rate_min = (XIN/2)/64,     /* SACLK/64 == (XIN/2)/64 */
+		.symbol_rate_max = (XIN/2)/4,      /* SACLK/4 */
+	#if 0
+		.frequency_tolerance = ???,
+		.symbol_rate_tolerance = ???,  /* ppm */  /* == 8% (spec p. 5) */
+	#endif
+		.caps = 0x400 | //FE_CAN_QAM_4
+			FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 |
+			FE_CAN_QAM_128 | FE_CAN_QAM_256 |
+			FE_CAN_FEC_AUTO
+	},
+
+	.release = tda10021_release,
+
+	.init = tda10021_init,
+	.sleep = tda10021_sleep,
+	.i2c_gate_ctrl = tda10021_i2c_gate_ctrl,
+
+	.set_frontend = tda10021_set_parameters,
+	.get_frontend = tda10021_get_frontend,
+
+	.read_status = tda10021_read_status,
+	.read_ber = tda10021_read_ber,
+	.read_signal_strength = tda10021_read_signal_strength,
+	.read_snr = tda10021_read_snr,
+	.read_ucblocks = tda10021_read_ucblocks,
+};
+
+module_param(verbose, int, 0644);
+MODULE_PARM_DESC(verbose, "print AFC offset after tuning for debugging the PWM setting");
+
+MODULE_DESCRIPTION("Philips TDA10021 DVB-C demodulator driver");
+MODULE_AUTHOR("Ralph Metzler, Holger Waechtler, Markus Schulz");
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(tda10021_attach);
diff --git a/drivers/media/dvb-frontends/tda10023.c b/drivers/media/dvb-frontends/tda10023.c
new file mode 100644
index 0000000..ca1e0d5
--- /dev/null
+++ b/drivers/media/dvb-frontends/tda10023.c
@@ -0,0 +1,610 @@
+/*
+    TDA10023  - DVB-C decoder
+    (as used in Philips CU1216-3 NIM and the Reelbox DVB-C tuner card)
+
+    Copyright (C) 2005 Georg Acher, BayCom GmbH (acher at baycom dot de)
+    Copyright (c) 2006 Hartmut Birr (e9hack at gmail dot com)
+
+    Remotely based on tda10021.c
+    Copyright (C) 1999 Convergence Integrated Media GmbH <ralph@convergence.de>
+    Copyright (C) 2004 Markus Schulz <msc@antzsystem.de>
+		   Support for TDA10021
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the 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/delay.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+
+#include <asm/div64.h>
+
+#include "dvb_frontend.h"
+#include "tda1002x.h"
+
+#define REG0_INIT_VAL 0x23
+
+struct tda10023_state {
+	struct i2c_adapter* i2c;
+	/* configuration settings */
+	const struct tda10023_config *config;
+	struct dvb_frontend frontend;
+
+	u8 pwm;
+	u8 reg0;
+
+	/* clock settings */
+	u32 xtal;
+	u8 pll_m;
+	u8 pll_p;
+	u8 pll_n;
+	u32 sysclk;
+};
+
+#define dprintk(x...)
+
+static int verbose;
+
+static u8 tda10023_readreg (struct tda10023_state* state, u8 reg)
+{
+	u8 b0 [] = { reg };
+	u8 b1 [] = { 0 };
+	struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 },
+				  { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } };
+	int ret;
+
+	ret = i2c_transfer (state->i2c, msg, 2);
+	if (ret != 2) {
+		int num = state->frontend.dvb ? state->frontend.dvb->num : -1;
+		printk(KERN_ERR "DVB: TDA10023(%d): %s: readreg error "
+			"(reg == 0x%02x, ret == %i)\n",
+			num, __func__, reg, ret);
+	}
+	return b1[0];
+}
+
+static int tda10023_writereg (struct tda10023_state* state, u8 reg, u8 data)
+{
+	u8 buf[] = { reg, data };
+	struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 };
+	int ret;
+
+	ret = i2c_transfer (state->i2c, &msg, 1);
+	if (ret != 1) {
+		int num = state->frontend.dvb ? state->frontend.dvb->num : -1;
+		printk(KERN_ERR "DVB: TDA10023(%d): %s, writereg error "
+			"(reg == 0x%02x, val == 0x%02x, ret == %i)\n",
+			num, __func__, reg, data, ret);
+	}
+	return (ret != 1) ? -EREMOTEIO : 0;
+}
+
+
+static int tda10023_writebit (struct tda10023_state* state, u8 reg, u8 mask,u8 data)
+{
+	if (mask==0xff)
+		return tda10023_writereg(state, reg, data);
+	else {
+		u8 val;
+		val=tda10023_readreg(state,reg);
+		val&=~mask;
+		val|=(data&mask);
+		return tda10023_writereg(state, reg, val);
+	}
+}
+
+static void tda10023_writetab(struct tda10023_state* state, u8* tab)
+{
+	u8 r,m,v;
+	while (1) {
+		r=*tab++;
+		m=*tab++;
+		v=*tab++;
+		if (r==0xff) {
+			if (m==0xff)
+				break;
+			else
+				msleep(m);
+		}
+		else
+			tda10023_writebit(state,r,m,v);
+	}
+}
+
+//get access to tuner
+static int lock_tuner(struct tda10023_state* state)
+{
+	u8 buf[2] = { 0x0f, 0xc0 };
+	struct i2c_msg msg = {.addr=state->config->demod_address, .flags=0, .buf=buf, .len=2};
+
+	if(i2c_transfer(state->i2c, &msg, 1) != 1)
+	{
+		printk("tda10023: lock tuner fails\n");
+		return -EREMOTEIO;
+	}
+	return 0;
+}
+
+//release access from tuner
+static int unlock_tuner(struct tda10023_state* state)
+{
+	u8 buf[2] = { 0x0f, 0x40 };
+	struct i2c_msg msg_post={.addr=state->config->demod_address, .flags=0, .buf=buf, .len=2};
+
+	if(i2c_transfer(state->i2c, &msg_post, 1) != 1)
+	{
+		printk("tda10023: unlock tuner fails\n");
+		return -EREMOTEIO;
+	}
+	return 0;
+}
+
+static int tda10023_setup_reg0 (struct tda10023_state* state, u8 reg0)
+{
+	reg0 |= state->reg0 & 0x63;
+
+	tda10023_writereg (state, 0x00, reg0 & 0xfe);
+	tda10023_writereg (state, 0x00, reg0 | 0x01);
+
+	state->reg0 = reg0;
+	return 0;
+}
+
+static int tda10023_set_symbolrate (struct tda10023_state* state, u32 sr)
+{
+	s32 BDR;
+	s32 BDRI;
+	s16 SFIL=0;
+	u16 NDEC = 0;
+
+	/* avoid floating point operations multiplying syscloc and divider
+	   by 10 */
+	u32 sysclk_x_10 = state->sysclk * 10;
+
+	if (sr < (u32)(sysclk_x_10/984)) {
+		NDEC=3;
+		SFIL=1;
+	} else if (sr < (u32)(sysclk_x_10/640)) {
+		NDEC=3;
+		SFIL=0;
+	} else if (sr < (u32)(sysclk_x_10/492)) {
+		NDEC=2;
+		SFIL=1;
+	} else if (sr < (u32)(sysclk_x_10/320)) {
+		NDEC=2;
+		SFIL=0;
+	} else if (sr < (u32)(sysclk_x_10/246)) {
+		NDEC=1;
+		SFIL=1;
+	} else if (sr < (u32)(sysclk_x_10/160)) {
+		NDEC=1;
+		SFIL=0;
+	} else if (sr < (u32)(sysclk_x_10/123)) {
+		NDEC=0;
+		SFIL=1;
+	}
+
+	BDRI = (state->sysclk)*16;
+	BDRI>>=NDEC;
+	BDRI +=sr/2;
+	BDRI /=sr;
+
+	if (BDRI>255)
+		BDRI=255;
+
+	{
+		u64 BDRX;
+
+		BDRX=1<<(24+NDEC);
+		BDRX*=sr;
+		do_div(BDRX, state->sysclk); 	/* BDRX/=SYSCLK; */
+
+		BDR=(s32)BDRX;
+	}
+	dprintk("Symbolrate %i, BDR %i BDRI %i, NDEC %i\n",
+		sr, BDR, BDRI, NDEC);
+	tda10023_writebit (state, 0x03, 0xc0, NDEC<<6);
+	tda10023_writereg (state, 0x0a, BDR&255);
+	tda10023_writereg (state, 0x0b, (BDR>>8)&255);
+	tda10023_writereg (state, 0x0c, (BDR>>16)&31);
+	tda10023_writereg (state, 0x0d, BDRI);
+	tda10023_writereg (state, 0x3d, (SFIL<<7));
+	return 0;
+}
+
+static int tda10023_init (struct dvb_frontend *fe)
+{
+	struct tda10023_state* state = fe->demodulator_priv;
+	u8 tda10023_inittab[] = {
+/*        reg  mask val */
+/* 000 */ 0x2a, 0xff, 0x02,  /* PLL3, Bypass, Power Down */
+/* 003 */ 0xff, 0x64, 0x00,  /* Sleep 100ms */
+/* 006 */ 0x2a, 0xff, 0x03,  /* PLL3, Bypass, Power Down */
+/* 009 */ 0xff, 0x64, 0x00,  /* Sleep 100ms */
+			   /* PLL1 */
+/* 012 */ 0x28, 0xff, (state->pll_m-1),
+			   /* PLL2 */
+/* 015 */ 0x29, 0xff, ((state->pll_p-1)<<6)|(state->pll_n-1),
+			   /* GPR FSAMPLING=1 */
+/* 018 */ 0x00, 0xff, REG0_INIT_VAL,
+/* 021 */ 0x2a, 0xff, 0x08,  /* PLL3 PSACLK=1 */
+/* 024 */ 0xff, 0x64, 0x00,  /* Sleep 100ms */
+/* 027 */ 0x1f, 0xff, 0x00,  /* RESET */
+/* 030 */ 0xff, 0x64, 0x00,  /* Sleep 100ms */
+/* 033 */ 0xe6, 0x0c, 0x04,  /* RSCFG_IND */
+/* 036 */ 0x10, 0xc0, 0x80,  /* DECDVBCFG1 PBER=1 */
+
+/* 039 */ 0x0e, 0xff, 0x82,  /* GAIN1 */
+/* 042 */ 0x03, 0x08, 0x08,  /* CLKCONF DYN=1 */
+/* 045 */ 0x2e, 0xbf, 0x30,  /* AGCCONF2 TRIAGC=0,POSAGC=ENAGCIF=1
+				       PPWMTUN=0 PPWMIF=0 */
+/* 048 */ 0x01, 0xff, 0x30,  /* AGCREF */
+/* 051 */ 0x1e, 0x84, 0x84,  /* CONTROL SACLK_ON=1 */
+/* 054 */ 0x1b, 0xff, 0xc8,  /* ADC TWOS=1 */
+/* 057 */ 0x3b, 0xff, 0xff,  /* IFMAX */
+/* 060 */ 0x3c, 0xff, 0x00,  /* IFMIN */
+/* 063 */ 0x34, 0xff, 0x00,  /* PWMREF */
+/* 066 */ 0x35, 0xff, 0xff,  /* TUNMAX */
+/* 069 */ 0x36, 0xff, 0x00,  /* TUNMIN */
+/* 072 */ 0x06, 0xff, 0x7f,  /* EQCONF1 POSI=7 ENADAPT=ENEQUAL=DFE=1 */
+/* 075 */ 0x1c, 0x30, 0x30,  /* EQCONF2 STEPALGO=SGNALGO=1 */
+/* 078 */ 0x37, 0xff, 0xf6,  /* DELTAF_LSB */
+/* 081 */ 0x38, 0xff, 0xff,  /* DELTAF_MSB */
+/* 084 */ 0x02, 0xff, 0x93,  /* AGCCONF1  IFS=1 KAGCIF=2 KAGCTUN=3 */
+/* 087 */ 0x2d, 0xff, 0xf6,  /* SWEEP SWPOS=1 SWDYN=7 SWSTEP=1 SWLEN=2 */
+/* 090 */ 0x04, 0x10, 0x00,  /* SWRAMP=1 */
+/* 093 */ 0x12, 0xff, TDA10023_OUTPUT_MODE_PARALLEL_B, /*
+				INTP1 POCLKP=1 FEL=1 MFS=0 */
+/* 096 */ 0x2b, 0x01, 0xa1,  /* INTS1 */
+/* 099 */ 0x20, 0xff, 0x04,  /* INTP2 SWAPP=? MSBFIRSTP=? INTPSEL=? */
+/* 102 */ 0x2c, 0xff, 0x0d,  /* INTP/S TRIP=0 TRIS=0 */
+/* 105 */ 0xc4, 0xff, 0x00,
+/* 108 */ 0xc3, 0x30, 0x00,
+/* 111 */ 0xb5, 0xff, 0x19,  /* ERAGC_THD */
+/* 114 */ 0x00, 0x03, 0x01,  /* GPR, CLBS soft reset */
+/* 117 */ 0x00, 0x03, 0x03,  /* GPR, CLBS soft reset */
+/* 120 */ 0xff, 0x64, 0x00,  /* Sleep 100ms */
+/* 123 */ 0xff, 0xff, 0xff
+};
+	dprintk("DVB: TDA10023(%d): init chip\n", fe->dvb->num);
+
+	/* override default values if set in config */
+	if (state->config->deltaf) {
+		tda10023_inittab[80] = (state->config->deltaf & 0xff);
+		tda10023_inittab[83] = (state->config->deltaf >> 8);
+	}
+
+	if (state->config->output_mode)
+		tda10023_inittab[95] = state->config->output_mode;
+
+	tda10023_writetab(state, tda10023_inittab);
+
+	return 0;
+}
+
+struct qam_params {
+	u8 qam, lockthr, mseth, aref, agcrefnyq, eragnyq_thd;
+};
+
+static int tda10023_set_parameters(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	u32 delsys  = c->delivery_system;
+	unsigned qam = c->modulation;
+	bool is_annex_c;
+	struct tda10023_state* state = fe->demodulator_priv;
+	static const struct qam_params qam_params[] = {
+		/* Modulation  QAM    LOCKTHR   MSETH   AREF AGCREFNYQ ERAGCNYQ_THD */
+		[QPSK]    = { (5<<2),  0x78,    0x8c,   0x96,   0x78,   0x4c  },
+		[QAM_16]  = { (0<<2),  0x87,    0xa2,   0x91,   0x8c,   0x57  },
+		[QAM_32]  = { (1<<2),  0x64,    0x74,   0x96,   0x8c,   0x57  },
+		[QAM_64]  = { (2<<2),  0x46,    0x43,   0x6a,   0x6a,   0x44  },
+		[QAM_128] = { (3<<2),  0x36,    0x34,   0x7e,   0x78,   0x4c  },
+		[QAM_256] = { (4<<2),  0x26,    0x23,   0x6c,   0x5c,   0x3c  },
+	};
+
+	switch (delsys) {
+	case SYS_DVBC_ANNEX_A:
+		is_annex_c = false;
+		break;
+	case SYS_DVBC_ANNEX_C:
+		is_annex_c = true;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/*
+	 * gcc optimizes the code bellow the same way as it would code:
+	 *		 "if (qam > 5) return -EINVAL;"
+	 * Yet, the code is clearer, as it shows what QAM standards are
+	 * supported by the driver, and avoids the usage of magic numbers on
+	 * it.
+	 */
+	switch (qam) {
+	case QPSK:
+	case QAM_16:
+	case QAM_32:
+	case QAM_64:
+	case QAM_128:
+	case QAM_256:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (fe->ops.tuner_ops.set_params) {
+		fe->ops.tuner_ops.set_params(fe);
+		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+	}
+
+	tda10023_set_symbolrate(state, c->symbol_rate);
+	tda10023_writereg(state, 0x05, qam_params[qam].lockthr);
+	tda10023_writereg(state, 0x08, qam_params[qam].mseth);
+	tda10023_writereg(state, 0x09, qam_params[qam].aref);
+	tda10023_writereg(state, 0xb4, qam_params[qam].agcrefnyq);
+	tda10023_writereg(state, 0xb6, qam_params[qam].eragnyq_thd);
+#if 0
+	tda10023_writereg(state, 0x04, (c->inversion ? 0x12 : 0x32));
+	tda10023_writebit(state, 0x04, 0x60, (c->inversion ? 0 : 0x20));
+#endif
+	tda10023_writebit(state, 0x04, 0x40, 0x40);
+
+	if (is_annex_c)
+		tda10023_writebit(state, 0x3d, 0xfc, 0x03);
+	else
+		tda10023_writebit(state, 0x3d, 0xfc, 0x02);
+
+	tda10023_setup_reg0(state, qam_params[qam].qam);
+
+	return 0;
+}
+
+static int tda10023_read_status(struct dvb_frontend* fe, fe_status_t* status)
+{
+	struct tda10023_state* state = fe->demodulator_priv;
+	int sync;
+
+	*status = 0;
+
+	//0x11[1] == CARLOCK -> Carrier locked
+	//0x11[2] == FSYNC -> Frame synchronisation
+	//0x11[3] == FEL -> Front End locked
+	//0x11[6] == NODVB -> DVB Mode Information
+	sync = tda10023_readreg (state, 0x11);
+
+	if (sync & 2)
+		*status |= FE_HAS_SIGNAL|FE_HAS_CARRIER;
+
+	if (sync & 4)
+		*status |= FE_HAS_SYNC|FE_HAS_VITERBI;
+
+	if (sync & 8)
+		*status |= FE_HAS_LOCK;
+
+	return 0;
+}
+
+static int tda10023_read_ber(struct dvb_frontend* fe, u32* ber)
+{
+	struct tda10023_state* state = fe->demodulator_priv;
+	u8 a,b,c;
+	a=tda10023_readreg(state, 0x14);
+	b=tda10023_readreg(state, 0x15);
+	c=tda10023_readreg(state, 0x16)&0xf;
+	tda10023_writebit (state, 0x10, 0xc0, 0x00);
+
+	*ber = a | (b<<8)| (c<<16);
+	return 0;
+}
+
+static int tda10023_read_signal_strength(struct dvb_frontend* fe, u16* strength)
+{
+	struct tda10023_state* state = fe->demodulator_priv;
+	u8 ifgain=tda10023_readreg(state, 0x2f);
+
+	u16 gain = ((255-tda10023_readreg(state, 0x17))) + (255-ifgain)/16;
+	// Max raw value is about 0xb0 -> Normalize to >0xf0 after 0x90
+	if (gain>0x90)
+		gain=gain+2*(gain-0x90);
+	if (gain>255)
+		gain=255;
+
+	*strength = (gain<<8)|gain;
+	return 0;
+}
+
+static int tda10023_read_snr(struct dvb_frontend* fe, u16* snr)
+{
+	struct tda10023_state* state = fe->demodulator_priv;
+
+	u8 quality = ~tda10023_readreg(state, 0x18);
+	*snr = (quality << 8) | quality;
+	return 0;
+}
+
+static int tda10023_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
+{
+	struct tda10023_state* state = fe->demodulator_priv;
+	u8 a,b,c,d;
+	a= tda10023_readreg (state, 0x74);
+	b= tda10023_readreg (state, 0x75);
+	c= tda10023_readreg (state, 0x76);
+	d= tda10023_readreg (state, 0x77);
+	*ucblocks = a | (b<<8)|(c<<16)|(d<<24);
+
+	tda10023_writebit (state, 0x10, 0x20,0x00);
+	tda10023_writebit (state, 0x10, 0x20,0x20);
+	tda10023_writebit (state, 0x13, 0x01, 0x00);
+
+	return 0;
+}
+
+static int tda10023_get_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct tda10023_state* state = fe->demodulator_priv;
+	int sync,inv;
+	s8 afc = 0;
+
+	sync = tda10023_readreg(state, 0x11);
+	afc = tda10023_readreg(state, 0x19);
+	inv = tda10023_readreg(state, 0x04);
+
+	if (verbose) {
+		/* AFC only valid when carrier has been recovered */
+		printk(sync & 2 ? "DVB: TDA10023(%d): AFC (%d) %dHz\n" :
+				  "DVB: TDA10023(%d): [AFC (%d) %dHz]\n",
+			state->frontend.dvb->num, afc,
+		       -((s32)p->symbol_rate * afc) >> 10);
+	}
+
+	p->inversion = (inv&0x20?0:1);
+	p->modulation = ((state->reg0 >> 2) & 7) + QAM_16;
+
+	p->fec_inner = FEC_NONE;
+	p->frequency = ((p->frequency + 31250) / 62500) * 62500;
+
+	if (sync & 2)
+		p->frequency -= ((s32)p->symbol_rate * afc) >> 10;
+
+	return 0;
+}
+
+static int tda10023_sleep(struct dvb_frontend* fe)
+{
+	struct tda10023_state* state = fe->demodulator_priv;
+
+	tda10023_writereg (state, 0x1b, 0x02);  /* pdown ADC */
+	tda10023_writereg (state, 0x00, 0x80);  /* standby */
+
+	return 0;
+}
+
+static int tda10023_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+{
+	struct tda10023_state* state = fe->demodulator_priv;
+
+	if (enable) {
+		lock_tuner(state);
+	} else {
+		unlock_tuner(state);
+	}
+	return 0;
+}
+
+static void tda10023_release(struct dvb_frontend* fe)
+{
+	struct tda10023_state* state = fe->demodulator_priv;
+	kfree(state);
+}
+
+static struct dvb_frontend_ops tda10023_ops;
+
+struct dvb_frontend *tda10023_attach(const struct tda10023_config *config,
+				     struct i2c_adapter *i2c,
+				     u8 pwm)
+{
+	struct tda10023_state* state = NULL;
+
+	/* allocate memory for the internal state */
+	state = kzalloc(sizeof(struct tda10023_state), GFP_KERNEL);
+	if (state == NULL) goto error;
+
+	/* setup the state */
+	state->config = config;
+	state->i2c = i2c;
+
+	/* wakeup if in standby */
+	tda10023_writereg (state, 0x00, 0x33);
+	/* check if the demod is there */
+	if ((tda10023_readreg(state, 0x1a) & 0xf0) != 0x70) goto error;
+
+	/* create dvb_frontend */
+	memcpy(&state->frontend.ops, &tda10023_ops, sizeof(struct dvb_frontend_ops));
+	state->pwm = pwm;
+	state->reg0 = REG0_INIT_VAL;
+	if (state->config->xtal) {
+		state->xtal  = state->config->xtal;
+		state->pll_m = state->config->pll_m;
+		state->pll_p = state->config->pll_p;
+		state->pll_n = state->config->pll_n;
+	} else {
+		/* set default values if not defined in config */
+		state->xtal  = 28920000;
+		state->pll_m = 8;
+		state->pll_p = 4;
+		state->pll_n = 1;
+	}
+
+	/* calc sysclk */
+	state->sysclk = (state->xtal * state->pll_m / \
+			(state->pll_n * state->pll_p));
+
+	state->frontend.ops.info.symbol_rate_min = (state->sysclk/2)/64;
+	state->frontend.ops.info.symbol_rate_max = (state->sysclk/2)/4;
+
+	dprintk("DVB: TDA10023 %s: xtal:%d pll_m:%d pll_p:%d pll_n:%d\n",
+		__func__, state->xtal, state->pll_m, state->pll_p,
+		state->pll_n);
+
+	state->frontend.demodulator_priv = state;
+	return &state->frontend;
+
+error:
+	kfree(state);
+	return NULL;
+}
+
+static struct dvb_frontend_ops tda10023_ops = {
+	.delsys = { SYS_DVBC_ANNEX_A, SYS_DVBC_ANNEX_C },
+	.info = {
+		.name = "Philips TDA10023 DVB-C",
+		.frequency_stepsize = 62500,
+		.frequency_min =  47000000,
+		.frequency_max = 862000000,
+		.symbol_rate_min = 0,  /* set in tda10023_attach */
+		.symbol_rate_max = 0,  /* set in tda10023_attach */
+		.caps = 0x400 | //FE_CAN_QAM_4
+			FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 |
+			FE_CAN_QAM_128 | FE_CAN_QAM_256 |
+			FE_CAN_FEC_AUTO
+	},
+
+	.release = tda10023_release,
+
+	.init = tda10023_init,
+	.sleep = tda10023_sleep,
+	.i2c_gate_ctrl = tda10023_i2c_gate_ctrl,
+
+	.set_frontend = tda10023_set_parameters,
+	.get_frontend = tda10023_get_frontend,
+	.read_status = tda10023_read_status,
+	.read_ber = tda10023_read_ber,
+	.read_signal_strength = tda10023_read_signal_strength,
+	.read_snr = tda10023_read_snr,
+	.read_ucblocks = tda10023_read_ucblocks,
+};
+
+
+MODULE_DESCRIPTION("Philips TDA10023 DVB-C demodulator driver");
+MODULE_AUTHOR("Georg Acher, Hartmut Birr");
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(tda10023_attach);
diff --git a/drivers/media/dvb-frontends/tda1002x.h b/drivers/media/dvb-frontends/tda1002x.h
new file mode 100644
index 0000000..04d1941
--- /dev/null
+++ b/drivers/media/dvb-frontends/tda1002x.h
@@ -0,0 +1,87 @@
+/*
+    TDA10021/TDA10023  - Single Chip Cable Channel Receiver driver module
+			 used on the the Siemens DVB-C cards
+
+    Copyright (C) 1999 Convergence Integrated Media GmbH <ralph@convergence.de>
+    Copyright (C) 2004 Markus Schulz <msc@antzsystem.de>
+		   Support for TDA10021
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the 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 TDA1002x_H
+#define TDA1002x_H
+
+#include <linux/dvb/frontend.h>
+
+struct tda1002x_config {
+	/* the demodulator's i2c address */
+	u8 demod_address;
+	u8 invert;
+};
+
+enum tda10023_output_mode {
+	TDA10023_OUTPUT_MODE_PARALLEL_A = 0xe0,
+	TDA10023_OUTPUT_MODE_PARALLEL_B = 0xa1,
+	TDA10023_OUTPUT_MODE_PARALLEL_C = 0xa0,
+	TDA10023_OUTPUT_MODE_SERIAL, /* TODO: not implemented */
+};
+
+struct tda10023_config {
+	/* the demodulator's i2c address */
+	u8 demod_address;
+	u8 invert;
+
+	/* clock settings */
+	u32 xtal; /* defaults: 28920000 */
+	u8 pll_m; /* defaults: 8 */
+	u8 pll_p; /* defaults: 4 */
+	u8 pll_n; /* defaults: 1 */
+
+	/* MPEG2 TS output mode */
+	u8 output_mode;
+
+	/* input freq offset + baseband conversion type */
+	u16 deltaf;
+};
+
+#if defined(CONFIG_DVB_TDA10021) || (defined(CONFIG_DVB_TDA10021_MODULE) && defined(MODULE))
+extern struct dvb_frontend* tda10021_attach(const struct tda1002x_config* config,
+					    struct i2c_adapter* i2c, u8 pwm);
+#else
+static inline struct dvb_frontend* tda10021_attach(const struct tda1002x_config* config,
+					    struct i2c_adapter* i2c, u8 pwm)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif // CONFIG_DVB_TDA10021
+
+#if defined(CONFIG_DVB_TDA10023) || \
+	(defined(CONFIG_DVB_TDA10023_MODULE) && defined(MODULE))
+extern struct dvb_frontend *tda10023_attach(
+	const struct tda10023_config *config,
+	struct i2c_adapter *i2c, u8 pwm);
+#else
+static inline struct dvb_frontend *tda10023_attach(
+	const struct tda10023_config *config,
+	struct i2c_adapter *i2c, u8 pwm)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif // CONFIG_DVB_TDA10023
+
+#endif // TDA1002x_H
diff --git a/drivers/media/dvb-frontends/tda10048.c b/drivers/media/dvb-frontends/tda10048.c
new file mode 100644
index 0000000..71fb632
--- /dev/null
+++ b/drivers/media/dvb-frontends/tda10048.c
@@ -0,0 +1,1191 @@
+/*
+    NXP TDA10048HN DVB OFDM demodulator driver
+
+    Copyright (C) 2009 Steven Toth <stoth@kernellabs.com>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/math64.h>
+#include <asm/div64.h>
+#include "dvb_frontend.h"
+#include "dvb_math.h"
+#include "tda10048.h"
+
+#define TDA10048_DEFAULT_FIRMWARE "dvb-fe-tda10048-1.0.fw"
+#define TDA10048_DEFAULT_FIRMWARE_SIZE 24878
+
+/* Register name definitions */
+#define TDA10048_IDENTITY          0x00
+#define TDA10048_VERSION           0x01
+#define TDA10048_DSP_CODE_CPT      0x0C
+#define TDA10048_DSP_CODE_IN       0x0E
+#define TDA10048_IN_CONF1          0x10
+#define TDA10048_IN_CONF2          0x11
+#define TDA10048_IN_CONF3          0x12
+#define TDA10048_OUT_CONF1         0x14
+#define TDA10048_OUT_CONF2         0x15
+#define TDA10048_OUT_CONF3         0x16
+#define TDA10048_AUTO              0x18
+#define TDA10048_SYNC_STATUS       0x1A
+#define TDA10048_CONF_C4_1         0x1E
+#define TDA10048_CONF_C4_2         0x1F
+#define TDA10048_CODE_IN_RAM       0x20
+#define TDA10048_CHANNEL_INFO1_R   0x22
+#define TDA10048_CHANNEL_INFO2_R   0x23
+#define TDA10048_CHANNEL_INFO1     0x24
+#define TDA10048_CHANNEL_INFO2     0x25
+#define TDA10048_TIME_ERROR_R      0x26
+#define TDA10048_TIME_ERROR        0x27
+#define TDA10048_FREQ_ERROR_LSB_R  0x28
+#define TDA10048_FREQ_ERROR_MSB_R  0x29
+#define TDA10048_FREQ_ERROR_LSB    0x2A
+#define TDA10048_FREQ_ERROR_MSB    0x2B
+#define TDA10048_IT_SEL            0x30
+#define TDA10048_IT_STAT           0x32
+#define TDA10048_DSP_AD_LSB        0x3C
+#define TDA10048_DSP_AD_MSB        0x3D
+#define TDA10048_DSP_REG_LSB       0x3E
+#define TDA10048_DSP_REG_MSB       0x3F
+#define TDA10048_CONF_TRISTATE1    0x44
+#define TDA10048_CONF_TRISTATE2    0x45
+#define TDA10048_CONF_POLARITY     0x46
+#define TDA10048_GPIO_SP_DS0       0x48
+#define TDA10048_GPIO_SP_DS1       0x49
+#define TDA10048_GPIO_SP_DS2       0x4A
+#define TDA10048_GPIO_SP_DS3       0x4B
+#define TDA10048_GPIO_OUT_SEL      0x4C
+#define TDA10048_GPIO_SELECT       0x4D
+#define TDA10048_IC_MODE           0x4E
+#define TDA10048_CONF_XO           0x50
+#define TDA10048_CONF_PLL1         0x51
+#define TDA10048_CONF_PLL2         0x52
+#define TDA10048_CONF_PLL3         0x53
+#define TDA10048_CONF_ADC          0x54
+#define TDA10048_CONF_ADC_2        0x55
+#define TDA10048_CONF_C1_1         0x60
+#define TDA10048_CONF_C1_3         0x62
+#define TDA10048_AGC_CONF          0x70
+#define TDA10048_AGC_THRESHOLD_LSB 0x72
+#define TDA10048_AGC_THRESHOLD_MSB 0x73
+#define TDA10048_AGC_RENORM        0x74
+#define TDA10048_AGC_GAINS         0x76
+#define TDA10048_AGC_TUN_MIN       0x78
+#define TDA10048_AGC_TUN_MAX       0x79
+#define TDA10048_AGC_IF_MIN        0x7A
+#define TDA10048_AGC_IF_MAX        0x7B
+#define TDA10048_AGC_TUN_LEVEL     0x7E
+#define TDA10048_AGC_IF_LEVEL      0x7F
+#define TDA10048_DIG_AGC_LEVEL     0x81
+#define TDA10048_FREQ_PHY2_LSB     0x86
+#define TDA10048_FREQ_PHY2_MSB     0x87
+#define TDA10048_TIME_INVWREF_LSB  0x88
+#define TDA10048_TIME_INVWREF_MSB  0x89
+#define TDA10048_TIME_WREF_LSB     0x8A
+#define TDA10048_TIME_WREF_MID1    0x8B
+#define TDA10048_TIME_WREF_MID2    0x8C
+#define TDA10048_TIME_WREF_MSB     0x8D
+#define TDA10048_NP_OUT            0xA2
+#define TDA10048_CELL_ID_LSB       0xA4
+#define TDA10048_CELL_ID_MSB       0xA5
+#define TDA10048_EXTTPS_ODD        0xAA
+#define TDA10048_EXTTPS_EVEN       0xAB
+#define TDA10048_TPS_LENGTH        0xAC
+#define TDA10048_FREE_REG_1        0xB2
+#define TDA10048_FREE_REG_2        0xB3
+#define TDA10048_CONF_C3_1         0xC0
+#define TDA10048_CVBER_CTRL        0xC2
+#define TDA10048_CBER_NMAX_LSB     0xC4
+#define TDA10048_CBER_NMAX_MSB     0xC5
+#define TDA10048_CBER_LSB          0xC6
+#define TDA10048_CBER_MSB          0xC7
+#define TDA10048_VBER_LSB          0xC8
+#define TDA10048_VBER_MID          0xC9
+#define TDA10048_VBER_MSB          0xCA
+#define TDA10048_CVBER_LUT         0xCC
+#define TDA10048_UNCOR_CTRL        0xCD
+#define TDA10048_UNCOR_CPT_LSB     0xCE
+#define TDA10048_UNCOR_CPT_MSB     0xCF
+#define TDA10048_SOFT_IT_C3        0xD6
+#define TDA10048_CONF_TS2          0xE0
+#define TDA10048_CONF_TS1          0xE1
+
+static unsigned int debug;
+
+#define dprintk(level, fmt, arg...)\
+	do { if (debug >= level)\
+		printk(KERN_DEBUG "tda10048: " fmt, ## arg);\
+	} while (0)
+
+struct tda10048_state {
+
+	struct i2c_adapter *i2c;
+
+	/* We'll cache and update the attach config settings */
+	struct tda10048_config config;
+	struct dvb_frontend frontend;
+
+	int fwloaded;
+
+	u32 freq_if_hz;
+	u32 xtal_hz;
+	u32 pll_mfactor;
+	u32 pll_nfactor;
+	u32 pll_pfactor;
+	u32 sample_freq;
+
+	u32 bandwidth;
+};
+
+static struct init_tab {
+	u8	reg;
+	u16	data;
+} init_tab[] = {
+	{ TDA10048_CONF_PLL1, 0x08 },
+	{ TDA10048_CONF_ADC_2, 0x00 },
+	{ TDA10048_CONF_C4_1, 0x00 },
+	{ TDA10048_CONF_PLL1, 0x0f },
+	{ TDA10048_CONF_PLL2, 0x0a },
+	{ TDA10048_CONF_PLL3, 0x43 },
+	{ TDA10048_FREQ_PHY2_LSB, 0x02 },
+	{ TDA10048_FREQ_PHY2_MSB, 0x0a },
+	{ TDA10048_TIME_WREF_LSB, 0xbd },
+	{ TDA10048_TIME_WREF_MID1, 0xe4 },
+	{ TDA10048_TIME_WREF_MID2, 0xa8 },
+	{ TDA10048_TIME_WREF_MSB, 0x02 },
+	{ TDA10048_TIME_INVWREF_LSB, 0x04 },
+	{ TDA10048_TIME_INVWREF_MSB, 0x06 },
+	{ TDA10048_CONF_C4_1, 0x00 },
+	{ TDA10048_CONF_C1_1, 0xa8 },
+	{ TDA10048_AGC_CONF, 0x16 },
+	{ TDA10048_CONF_C1_3, 0x0b },
+	{ TDA10048_AGC_TUN_MIN, 0x00 },
+	{ TDA10048_AGC_TUN_MAX, 0xff },
+	{ TDA10048_AGC_IF_MIN, 0x00 },
+	{ TDA10048_AGC_IF_MAX, 0xff },
+	{ TDA10048_AGC_THRESHOLD_MSB, 0x00 },
+	{ TDA10048_AGC_THRESHOLD_LSB, 0x70 },
+	{ TDA10048_CVBER_CTRL, 0x38 },
+	{ TDA10048_AGC_GAINS, 0x12 },
+	{ TDA10048_CONF_XO, 0x00 },
+	{ TDA10048_CONF_TS1, 0x07 },
+	{ TDA10048_IC_MODE, 0x00 },
+	{ TDA10048_CONF_TS2, 0xc0 },
+	{ TDA10048_CONF_TRISTATE1, 0x21 },
+	{ TDA10048_CONF_TRISTATE2, 0x00 },
+	{ TDA10048_CONF_POLARITY, 0x00 },
+	{ TDA10048_CONF_C4_2, 0x04 },
+	{ TDA10048_CONF_ADC, 0x60 },
+	{ TDA10048_CONF_ADC_2, 0x10 },
+	{ TDA10048_CONF_ADC, 0x60 },
+	{ TDA10048_CONF_ADC_2, 0x00 },
+	{ TDA10048_CONF_C1_1, 0xa8 },
+	{ TDA10048_UNCOR_CTRL, 0x00 },
+	{ TDA10048_CONF_C4_2, 0x04 },
+};
+
+static struct pll_tab {
+	u32	clk_freq_khz;
+	u32	if_freq_khz;
+} pll_tab[] = {
+	{ TDA10048_CLK_4000,  TDA10048_IF_36130 },
+	{ TDA10048_CLK_16000, TDA10048_IF_3300 },
+	{ TDA10048_CLK_16000, TDA10048_IF_3500 },
+	{ TDA10048_CLK_16000, TDA10048_IF_3800 },
+	{ TDA10048_CLK_16000, TDA10048_IF_4000 },
+	{ TDA10048_CLK_16000, TDA10048_IF_4300 },
+	{ TDA10048_CLK_16000, TDA10048_IF_4500 },
+	{ TDA10048_CLK_16000, TDA10048_IF_5000 },
+	{ TDA10048_CLK_16000, TDA10048_IF_36130 },
+};
+
+static int tda10048_writereg(struct tda10048_state *state, u8 reg, u8 data)
+{
+	struct tda10048_config *config = &state->config;
+	int ret;
+	u8 buf[] = { reg, data };
+	struct i2c_msg msg = {
+		.addr = config->demod_address,
+		.flags = 0, .buf = buf, .len = 2 };
+
+	dprintk(2, "%s(reg = 0x%02x, data = 0x%02x)\n", __func__, reg, data);
+
+	ret = i2c_transfer(state->i2c, &msg, 1);
+
+	if (ret != 1)
+		printk("%s: writereg error (ret == %i)\n", __func__, ret);
+
+	return (ret != 1) ? -1 : 0;
+}
+
+static u8 tda10048_readreg(struct tda10048_state *state, u8 reg)
+{
+	struct tda10048_config *config = &state->config;
+	int ret;
+	u8 b0[] = { reg };
+	u8 b1[] = { 0 };
+	struct i2c_msg msg[] = {
+		{ .addr = config->demod_address,
+			.flags = 0, .buf = b0, .len = 1 },
+		{ .addr = config->demod_address,
+			.flags = I2C_M_RD, .buf = b1, .len = 1 } };
+
+	dprintk(2, "%s(reg = 0x%02x)\n", __func__, reg);
+
+	ret = i2c_transfer(state->i2c, msg, 2);
+
+	if (ret != 2)
+		printk(KERN_ERR "%s: readreg error (ret == %i)\n",
+			__func__, ret);
+
+	return b1[0];
+}
+
+static int tda10048_writeregbulk(struct tda10048_state *state, u8 reg,
+				 const u8 *data, u16 len)
+{
+	struct tda10048_config *config = &state->config;
+	int ret = -EREMOTEIO;
+	struct i2c_msg msg;
+	u8 *buf;
+
+	dprintk(2, "%s(%d, ?, len = %d)\n", __func__, reg, len);
+
+	buf = kmalloc(len + 1, GFP_KERNEL);
+	if (buf == NULL) {
+		ret = -ENOMEM;
+		goto error;
+	}
+
+	*buf = reg;
+	memcpy(buf + 1, data, len);
+
+	msg.addr = config->demod_address;
+	msg.flags = 0;
+	msg.buf = buf;
+	msg.len = len + 1;
+
+	dprintk(2, "%s():  write len = %d\n",
+		__func__, msg.len);
+
+	ret = i2c_transfer(state->i2c, &msg, 1);
+	if (ret != 1) {
+		printk(KERN_ERR "%s(): writereg error err %i\n",
+			 __func__, ret);
+		ret = -EREMOTEIO;
+	}
+
+error:
+	kfree(buf);
+
+	return ret;
+}
+
+static int tda10048_set_phy2(struct dvb_frontend *fe, u32 sample_freq_hz,
+			     u32 if_hz)
+{
+	struct tda10048_state *state = fe->demodulator_priv;
+	u64 t;
+
+	dprintk(1, "%s()\n", __func__);
+
+	if (sample_freq_hz == 0)
+		return -EINVAL;
+
+	if (if_hz < (sample_freq_hz / 2)) {
+		/* PHY2 = (if2/fs) * 2^15 */
+		t = if_hz;
+		t *= 10;
+		t *= 32768;
+		do_div(t, sample_freq_hz);
+		t += 5;
+		do_div(t, 10);
+	} else {
+		/* PHY2 = ((IF1-fs)/fs) * 2^15 */
+		t = sample_freq_hz - if_hz;
+		t *= 10;
+		t *= 32768;
+		do_div(t, sample_freq_hz);
+		t += 5;
+		do_div(t, 10);
+		t = ~t + 1;
+	}
+
+	tda10048_writereg(state, TDA10048_FREQ_PHY2_LSB, (u8)t);
+	tda10048_writereg(state, TDA10048_FREQ_PHY2_MSB, (u8)(t >> 8));
+
+	return 0;
+}
+
+static int tda10048_set_wref(struct dvb_frontend *fe, u32 sample_freq_hz,
+			     u32 bw)
+{
+	struct tda10048_state *state = fe->demodulator_priv;
+	u64 t, z;
+
+	dprintk(1, "%s()\n", __func__);
+
+	if (sample_freq_hz == 0)
+		return -EINVAL;
+
+	/* WREF = (B / (7 * fs)) * 2^31 */
+	t = bw * 10;
+	/* avoid warning: this decimal constant is unsigned only in ISO C90 */
+	/* t *= 2147483648 on 32bit platforms */
+	t *= (2048 * 1024);
+	t *= 1024;
+	z = 7 * sample_freq_hz;
+	do_div(t, z);
+	t += 5;
+	do_div(t, 10);
+
+	tda10048_writereg(state, TDA10048_TIME_WREF_LSB, (u8)t);
+	tda10048_writereg(state, TDA10048_TIME_WREF_MID1, (u8)(t >> 8));
+	tda10048_writereg(state, TDA10048_TIME_WREF_MID2, (u8)(t >> 16));
+	tda10048_writereg(state, TDA10048_TIME_WREF_MSB, (u8)(t >> 24));
+
+	return 0;
+}
+
+static int tda10048_set_invwref(struct dvb_frontend *fe, u32 sample_freq_hz,
+				u32 bw)
+{
+	struct tda10048_state *state = fe->demodulator_priv;
+	u64 t;
+
+	dprintk(1, "%s()\n", __func__);
+
+	if (sample_freq_hz == 0)
+		return -EINVAL;
+
+	/* INVWREF = ((7 * fs) / B) * 2^5 */
+	t = sample_freq_hz;
+	t *= 7;
+	t *= 32;
+	t *= 10;
+	do_div(t, bw);
+	t += 5;
+	do_div(t, 10);
+
+	tda10048_writereg(state, TDA10048_TIME_INVWREF_LSB, (u8)t);
+	tda10048_writereg(state, TDA10048_TIME_INVWREF_MSB, (u8)(t >> 8));
+
+	return 0;
+}
+
+static int tda10048_set_bandwidth(struct dvb_frontend *fe,
+	u32 bw)
+{
+	struct tda10048_state *state = fe->demodulator_priv;
+	dprintk(1, "%s(bw=%d)\n", __func__, bw);
+
+	/* Bandwidth setting may need to be adjusted */
+	switch (bw) {
+	case 6000000:
+	case 7000000:
+	case 8000000:
+		tda10048_set_wref(fe, state->sample_freq, bw);
+		tda10048_set_invwref(fe, state->sample_freq, bw);
+		break;
+	default:
+		printk(KERN_ERR "%s() invalid bandwidth\n", __func__);
+		return -EINVAL;
+	}
+
+	state->bandwidth = bw;
+
+	return 0;
+}
+
+static int tda10048_set_if(struct dvb_frontend *fe, u32 bw)
+{
+	struct tda10048_state *state = fe->demodulator_priv;
+	struct tda10048_config *config = &state->config;
+	int i;
+	u32 if_freq_khz;
+
+	dprintk(1, "%s(bw = %d)\n", __func__, bw);
+
+	/* based on target bandwidth and clk we calculate pll factors */
+	switch (bw) {
+	case 6000000:
+		if_freq_khz = config->dtv6_if_freq_khz;
+		break;
+	case 7000000:
+		if_freq_khz = config->dtv7_if_freq_khz;
+		break;
+	case 8000000:
+		if_freq_khz = config->dtv8_if_freq_khz;
+		break;
+	default:
+		printk(KERN_ERR "%s() no default\n", __func__);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(pll_tab); i++) {
+		if ((pll_tab[i].clk_freq_khz == config->clk_freq_khz) &&
+			(pll_tab[i].if_freq_khz == if_freq_khz)) {
+
+			state->freq_if_hz = pll_tab[i].if_freq_khz * 1000;
+			state->xtal_hz = pll_tab[i].clk_freq_khz * 1000;
+			break;
+		}
+	}
+	if (i == ARRAY_SIZE(pll_tab)) {
+		printk(KERN_ERR "%s() Incorrect attach settings\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	dprintk(1, "- freq_if_hz = %d\n", state->freq_if_hz);
+	dprintk(1, "- xtal_hz = %d\n", state->xtal_hz);
+	dprintk(1, "- pll_mfactor = %d\n", state->pll_mfactor);
+	dprintk(1, "- pll_nfactor = %d\n", state->pll_nfactor);
+	dprintk(1, "- pll_pfactor = %d\n", state->pll_pfactor);
+
+	/* Calculate the sample frequency */
+	state->sample_freq = state->xtal_hz * (state->pll_mfactor + 45);
+	state->sample_freq /= (state->pll_nfactor + 1);
+	state->sample_freq /= (state->pll_pfactor + 4);
+	dprintk(1, "- sample_freq = %d\n", state->sample_freq);
+
+	/* Update the I/F */
+	tda10048_set_phy2(fe, state->sample_freq, state->freq_if_hz);
+
+	return 0;
+}
+
+static int tda10048_firmware_upload(struct dvb_frontend *fe)
+{
+	struct tda10048_state *state = fe->demodulator_priv;
+	struct tda10048_config *config = &state->config;
+	const struct firmware *fw;
+	int ret;
+	int pos = 0;
+	int cnt;
+	u8 wlen = config->fwbulkwritelen;
+
+	if ((wlen != TDA10048_BULKWRITE_200) && (wlen != TDA10048_BULKWRITE_50))
+		wlen = TDA10048_BULKWRITE_200;
+
+	/* request the firmware, this will block and timeout */
+	printk(KERN_INFO "%s: waiting for firmware upload (%s)...\n",
+		__func__,
+		TDA10048_DEFAULT_FIRMWARE);
+
+	ret = request_firmware(&fw, TDA10048_DEFAULT_FIRMWARE,
+		state->i2c->dev.parent);
+	if (ret) {
+		printk(KERN_ERR "%s: Upload failed. (file not found?)\n",
+			__func__);
+		return -EIO;
+	} else {
+		printk(KERN_INFO "%s: firmware read %Zu bytes.\n",
+			__func__,
+			fw->size);
+		ret = 0;
+	}
+
+	if (fw->size != TDA10048_DEFAULT_FIRMWARE_SIZE) {
+		printk(KERN_ERR "%s: firmware incorrect size\n", __func__);
+		ret = -EIO;
+	} else {
+		printk(KERN_INFO "%s: firmware uploading\n", __func__);
+
+		/* Soft reset */
+		tda10048_writereg(state, TDA10048_CONF_TRISTATE1,
+			tda10048_readreg(state, TDA10048_CONF_TRISTATE1)
+				& 0xfe);
+		tda10048_writereg(state, TDA10048_CONF_TRISTATE1,
+			tda10048_readreg(state, TDA10048_CONF_TRISTATE1)
+				| 0x01);
+
+		/* Put the demod into host download mode */
+		tda10048_writereg(state, TDA10048_CONF_C4_1,
+			tda10048_readreg(state, TDA10048_CONF_C4_1) & 0xf9);
+
+		/* Boot the DSP */
+		tda10048_writereg(state, TDA10048_CONF_C4_1,
+			tda10048_readreg(state, TDA10048_CONF_C4_1) | 0x08);
+
+		/* Prepare for download */
+		tda10048_writereg(state, TDA10048_DSP_CODE_CPT, 0);
+
+		/* Download the firmware payload */
+		while (pos < fw->size) {
+
+			if ((fw->size - pos) > wlen)
+				cnt = wlen;
+			else
+				cnt = fw->size - pos;
+
+			tda10048_writeregbulk(state, TDA10048_DSP_CODE_IN,
+				&fw->data[pos], cnt);
+
+			pos += cnt;
+		}
+
+		ret = -EIO;
+		/* Wait up to 250ms for the DSP to boot */
+		for (cnt = 0; cnt < 250 ; cnt += 10) {
+
+			msleep(10);
+
+			if (tda10048_readreg(state, TDA10048_SYNC_STATUS)
+				& 0x40) {
+				ret = 0;
+				break;
+			}
+		}
+	}
+
+	release_firmware(fw);
+
+	if (ret == 0) {
+		printk(KERN_INFO "%s: firmware uploaded\n", __func__);
+		state->fwloaded = 1;
+	} else
+		printk(KERN_ERR "%s: firmware upload failed\n", __func__);
+
+	return ret;
+}
+
+static int tda10048_set_inversion(struct dvb_frontend *fe, int inversion)
+{
+	struct tda10048_state *state = fe->demodulator_priv;
+
+	dprintk(1, "%s(%d)\n", __func__, inversion);
+
+	if (inversion == TDA10048_INVERSION_ON)
+		tda10048_writereg(state, TDA10048_CONF_C1_1,
+			tda10048_readreg(state, TDA10048_CONF_C1_1) | 0x20);
+	else
+		tda10048_writereg(state, TDA10048_CONF_C1_1,
+			tda10048_readreg(state, TDA10048_CONF_C1_1) & 0xdf);
+
+	return 0;
+}
+
+/* Retrieve the demod settings */
+static int tda10048_get_tps(struct tda10048_state *state,
+	struct dtv_frontend_properties *p)
+{
+	u8 val;
+
+	/* Make sure the TPS regs are valid */
+	if (!(tda10048_readreg(state, TDA10048_AUTO) & 0x01))
+		return -EAGAIN;
+
+	val = tda10048_readreg(state, TDA10048_OUT_CONF2);
+	switch ((val & 0x60) >> 5) {
+	case 0:
+		p->modulation = QPSK;
+		break;
+	case 1:
+		p->modulation = QAM_16;
+		break;
+	case 2:
+		p->modulation = QAM_64;
+		break;
+	}
+	switch ((val & 0x18) >> 3) {
+	case 0:
+		p->hierarchy = HIERARCHY_NONE;
+		break;
+	case 1:
+		p->hierarchy = HIERARCHY_1;
+		break;
+	case 2:
+		p->hierarchy = HIERARCHY_2;
+		break;
+	case 3:
+		p->hierarchy = HIERARCHY_4;
+		break;
+	}
+	switch (val & 0x07) {
+	case 0:
+		p->code_rate_HP = FEC_1_2;
+		break;
+	case 1:
+		p->code_rate_HP = FEC_2_3;
+		break;
+	case 2:
+		p->code_rate_HP = FEC_3_4;
+		break;
+	case 3:
+		p->code_rate_HP = FEC_5_6;
+		break;
+	case 4:
+		p->code_rate_HP = FEC_7_8;
+		break;
+	}
+
+	val = tda10048_readreg(state, TDA10048_OUT_CONF3);
+	switch (val & 0x07) {
+	case 0:
+		p->code_rate_LP = FEC_1_2;
+		break;
+	case 1:
+		p->code_rate_LP = FEC_2_3;
+		break;
+	case 2:
+		p->code_rate_LP = FEC_3_4;
+		break;
+	case 3:
+		p->code_rate_LP = FEC_5_6;
+		break;
+	case 4:
+		p->code_rate_LP = FEC_7_8;
+		break;
+	}
+
+	val = tda10048_readreg(state, TDA10048_OUT_CONF1);
+	switch ((val & 0x0c) >> 2) {
+	case 0:
+		p->guard_interval = GUARD_INTERVAL_1_32;
+		break;
+	case 1:
+		p->guard_interval = GUARD_INTERVAL_1_16;
+		break;
+	case 2:
+		p->guard_interval =  GUARD_INTERVAL_1_8;
+		break;
+	case 3:
+		p->guard_interval =  GUARD_INTERVAL_1_4;
+		break;
+	}
+	switch (val & 0x03) {
+	case 0:
+		p->transmission_mode = TRANSMISSION_MODE_2K;
+		break;
+	case 1:
+		p->transmission_mode = TRANSMISSION_MODE_8K;
+		break;
+	}
+
+	return 0;
+}
+
+static int tda10048_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+	struct tda10048_state *state = fe->demodulator_priv;
+	struct tda10048_config *config = &state->config;
+	dprintk(1, "%s(%d)\n", __func__, enable);
+
+	if (config->disable_gate_access)
+		return 0;
+
+	if (enable)
+		return tda10048_writereg(state, TDA10048_CONF_C4_1,
+			tda10048_readreg(state, TDA10048_CONF_C4_1) | 0x02);
+	else
+		return tda10048_writereg(state, TDA10048_CONF_C4_1,
+			tda10048_readreg(state, TDA10048_CONF_C4_1) & 0xfd);
+}
+
+static int tda10048_output_mode(struct dvb_frontend *fe, int serial)
+{
+	struct tda10048_state *state = fe->demodulator_priv;
+	dprintk(1, "%s(%d)\n", __func__, serial);
+
+	/* Ensure pins are out of tri-state */
+	tda10048_writereg(state, TDA10048_CONF_TRISTATE1, 0x21);
+	tda10048_writereg(state, TDA10048_CONF_TRISTATE2, 0x00);
+
+	if (serial) {
+		tda10048_writereg(state, TDA10048_IC_MODE, 0x80 | 0x20);
+		tda10048_writereg(state, TDA10048_CONF_TS2, 0xc0);
+	} else {
+		tda10048_writereg(state, TDA10048_IC_MODE, 0x00);
+		tda10048_writereg(state, TDA10048_CONF_TS2, 0x01);
+	}
+
+	return 0;
+}
+
+/* Talk to the demod, set the FEC, GUARD, QAM settings etc */
+/* TODO: Support manual tuning with specific params */
+static int tda10048_set_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct tda10048_state *state = fe->demodulator_priv;
+
+	dprintk(1, "%s(frequency=%d)\n", __func__, p->frequency);
+
+	/* Update the I/F pll's if the bandwidth changes */
+	if (p->bandwidth_hz != state->bandwidth) {
+		tda10048_set_if(fe, p->bandwidth_hz);
+		tda10048_set_bandwidth(fe, p->bandwidth_hz);
+	}
+
+	if (fe->ops.tuner_ops.set_params) {
+
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 1);
+
+		fe->ops.tuner_ops.set_params(fe);
+
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 0);
+	}
+
+	/* Enable demod TPS auto detection and begin acquisition */
+	tda10048_writereg(state, TDA10048_AUTO, 0x57);
+	/* trigger cber and vber acquisition */
+	tda10048_writereg(state, TDA10048_CVBER_CTRL, 0x3B);
+
+	return 0;
+}
+
+/* Establish sane defaults and load firmware. */
+static int tda10048_init(struct dvb_frontend *fe)
+{
+	struct tda10048_state *state = fe->demodulator_priv;
+	struct tda10048_config *config = &state->config;
+	int ret = 0, i;
+
+	dprintk(1, "%s()\n", __func__);
+
+	/* PLL */
+	init_tab[4].data = (u8)(state->pll_mfactor);
+	init_tab[5].data = (u8)(state->pll_nfactor) | 0x40;
+
+	/* Apply register defaults */
+	for (i = 0; i < ARRAY_SIZE(init_tab); i++)
+		tda10048_writereg(state, init_tab[i].reg, init_tab[i].data);
+
+	if (state->fwloaded == 0)
+		ret = tda10048_firmware_upload(fe);
+
+	/* Set either serial or parallel */
+	tda10048_output_mode(fe, config->output_mode);
+
+	/* Set inversion */
+	tda10048_set_inversion(fe, config->inversion);
+
+	/* Establish default RF values */
+	tda10048_set_if(fe, 8000000);
+	tda10048_set_bandwidth(fe, 8000000);
+
+	/* Ensure we leave the gate closed */
+	tda10048_i2c_gate_ctrl(fe, 0);
+
+	return ret;
+}
+
+static int tda10048_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+	struct tda10048_state *state = fe->demodulator_priv;
+	u8 reg;
+
+	*status = 0;
+
+	reg = tda10048_readreg(state, TDA10048_SYNC_STATUS);
+
+	dprintk(1, "%s() status =0x%02x\n", __func__, reg);
+
+	if (reg & 0x02)
+		*status |= FE_HAS_CARRIER;
+
+	if (reg & 0x04)
+		*status |= FE_HAS_SIGNAL;
+
+	if (reg & 0x08) {
+		*status |= FE_HAS_LOCK;
+		*status |= FE_HAS_VITERBI;
+		*status |= FE_HAS_SYNC;
+	}
+
+	return 0;
+}
+
+static int tda10048_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+	struct tda10048_state *state = fe->demodulator_priv;
+	static u32 cber_current;
+	u32 cber_nmax;
+	u64 cber_tmp;
+
+	dprintk(1, "%s()\n", __func__);
+
+	/* update cber on interrupt */
+	if (tda10048_readreg(state, TDA10048_SOFT_IT_C3) & 0x01) {
+		cber_tmp = tda10048_readreg(state, TDA10048_CBER_MSB) << 8 |
+			tda10048_readreg(state, TDA10048_CBER_LSB);
+		cber_nmax = tda10048_readreg(state, TDA10048_CBER_NMAX_MSB) << 8 |
+			tda10048_readreg(state, TDA10048_CBER_NMAX_LSB);
+		cber_tmp *= 100000000;
+		cber_tmp *= 2;
+		cber_tmp = div_u64(cber_tmp, (cber_nmax * 32) + 1);
+		cber_current = (u32)cber_tmp;
+		/* retrigger cber acquisition */
+		tda10048_writereg(state, TDA10048_CVBER_CTRL, 0x39);
+	}
+	/* actual cber is (*ber)/1e8 */
+	*ber = cber_current;
+
+	return 0;
+}
+
+static int tda10048_read_signal_strength(struct dvb_frontend *fe,
+	u16 *signal_strength)
+{
+	struct tda10048_state *state = fe->demodulator_priv;
+	u8 v;
+
+	dprintk(1, "%s()\n", __func__);
+
+	*signal_strength = 65535;
+
+	v = tda10048_readreg(state, TDA10048_NP_OUT);
+	if (v > 0)
+		*signal_strength -= (v << 8) | v;
+
+	return 0;
+}
+
+/* SNR lookup table */
+static struct snr_tab {
+	u8 val;
+	u8 data;
+} snr_tab[] = {
+	{   0,   0 },
+	{   1, 246 },
+	{   2, 215 },
+	{   3, 198 },
+	{   4, 185 },
+	{   5, 176 },
+	{   6, 168 },
+	{   7, 161 },
+	{   8, 155 },
+	{   9, 150 },
+	{  10, 146 },
+	{  11, 141 },
+	{  12, 138 },
+	{  13, 134 },
+	{  14, 131 },
+	{  15, 128 },
+	{  16, 125 },
+	{  17, 122 },
+	{  18, 120 },
+	{  19, 118 },
+	{  20, 115 },
+	{  21, 113 },
+	{  22, 111 },
+	{  23, 109 },
+	{  24, 107 },
+	{  25, 106 },
+	{  26, 104 },
+	{  27, 102 },
+	{  28, 101 },
+	{  29,  99 },
+	{  30,  98 },
+	{  31,  96 },
+	{  32,  95 },
+	{  33,  94 },
+	{  34,  92 },
+	{  35,  91 },
+	{  36,  90 },
+	{  37,  89 },
+	{  38,  88 },
+	{  39,  86 },
+	{  40,  85 },
+	{  41,  84 },
+	{  42,  83 },
+	{  43,  82 },
+	{  44,  81 },
+	{  45,  80 },
+	{  46,  79 },
+	{  47,  78 },
+	{  48,  77 },
+	{  49,  76 },
+	{  50,  76 },
+	{  51,  75 },
+	{  52,  74 },
+	{  53,  73 },
+	{  54,  72 },
+	{  56,  71 },
+	{  57,  70 },
+	{  58,  69 },
+	{  60,  68 },
+	{  61,  67 },
+	{  63,  66 },
+	{  64,  65 },
+	{  66,  64 },
+	{  67,  63 },
+	{  68,  62 },
+	{  69,  62 },
+	{  70,  61 },
+	{  72,  60 },
+	{  74,  59 },
+	{  75,  58 },
+	{  77,  57 },
+	{  79,  56 },
+	{  81,  55 },
+	{  83,  54 },
+	{  85,  53 },
+	{  87,  52 },
+	{  89,  51 },
+	{  91,  50 },
+	{  93,  49 },
+	{  95,  48 },
+	{  97,  47 },
+	{ 100,  46 },
+	{ 102,  45 },
+	{ 104,  44 },
+	{ 107,  43 },
+	{ 109,  42 },
+	{ 112,  41 },
+	{ 114,  40 },
+	{ 117,  39 },
+	{ 120,  38 },
+	{ 123,  37 },
+	{ 125,  36 },
+	{ 128,  35 },
+	{ 131,  34 },
+	{ 134,  33 },
+	{ 138,  32 },
+	{ 141,  31 },
+	{ 144,  30 },
+	{ 147,  29 },
+	{ 151,  28 },
+	{ 154,  27 },
+	{ 158,  26 },
+	{ 162,  25 },
+	{ 165,  24 },
+	{ 169,  23 },
+	{ 173,  22 },
+	{ 177,  21 },
+	{ 181,  20 },
+	{ 186,  19 },
+	{ 190,  18 },
+	{ 194,  17 },
+	{ 199,  16 },
+	{ 204,  15 },
+	{ 208,  14 },
+	{ 213,  13 },
+	{ 218,  12 },
+	{ 223,  11 },
+	{ 229,  10 },
+	{ 234,   9 },
+	{ 239,   8 },
+	{ 245,   7 },
+	{ 251,   6 },
+	{ 255,   5 },
+};
+
+static int tda10048_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+	struct tda10048_state *state = fe->demodulator_priv;
+	u8 v;
+	int i, ret = -EINVAL;
+
+	dprintk(1, "%s()\n", __func__);
+
+	v = tda10048_readreg(state, TDA10048_NP_OUT);
+	for (i = 0; i < ARRAY_SIZE(snr_tab); i++) {
+		if (v <= snr_tab[i].val) {
+			*snr = snr_tab[i].data;
+			ret = 0;
+			break;
+		}
+	}
+
+	return ret;
+}
+
+static int tda10048_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+	struct tda10048_state *state = fe->demodulator_priv;
+
+	dprintk(1, "%s()\n", __func__);
+
+	*ucblocks = tda10048_readreg(state, TDA10048_UNCOR_CPT_MSB) << 8 |
+		tda10048_readreg(state, TDA10048_UNCOR_CPT_LSB);
+	/* clear the uncorrected TS packets counter when saturated */
+	if (*ucblocks == 0xFFFF)
+		tda10048_writereg(state, TDA10048_UNCOR_CTRL, 0x80);
+
+	return 0;
+}
+
+static int tda10048_get_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct tda10048_state *state = fe->demodulator_priv;
+
+	dprintk(1, "%s()\n", __func__);
+
+	p->inversion = tda10048_readreg(state, TDA10048_CONF_C1_1)
+		& 0x20 ? INVERSION_ON : INVERSION_OFF;
+
+	return tda10048_get_tps(state, p);
+}
+
+static int tda10048_get_tune_settings(struct dvb_frontend *fe,
+	struct dvb_frontend_tune_settings *tune)
+{
+	tune->min_delay_ms = 1000;
+	return 0;
+}
+
+static void tda10048_release(struct dvb_frontend *fe)
+{
+	struct tda10048_state *state = fe->demodulator_priv;
+	dprintk(1, "%s()\n", __func__);
+	kfree(state);
+}
+
+static void tda10048_establish_defaults(struct dvb_frontend *fe)
+{
+	struct tda10048_state *state = fe->demodulator_priv;
+	struct tda10048_config *config = &state->config;
+
+	/* Validate/default the config */
+	if (config->dtv6_if_freq_khz == 0) {
+		config->dtv6_if_freq_khz = TDA10048_IF_4300;
+		printk(KERN_WARNING "%s() tda10048_config.dtv6_if_freq_khz "
+			"is not set (defaulting to %d)\n",
+			__func__,
+			config->dtv6_if_freq_khz);
+	}
+
+	if (config->dtv7_if_freq_khz == 0) {
+		config->dtv7_if_freq_khz = TDA10048_IF_4300;
+		printk(KERN_WARNING "%s() tda10048_config.dtv7_if_freq_khz "
+			"is not set (defaulting to %d)\n",
+			__func__,
+			config->dtv7_if_freq_khz);
+	}
+
+	if (config->dtv8_if_freq_khz == 0) {
+		config->dtv8_if_freq_khz = TDA10048_IF_4300;
+		printk(KERN_WARNING "%s() tda10048_config.dtv8_if_freq_khz "
+			"is not set (defaulting to %d)\n",
+			__func__,
+			config->dtv8_if_freq_khz);
+	}
+
+	if (config->clk_freq_khz == 0) {
+		config->clk_freq_khz = TDA10048_CLK_16000;
+		printk(KERN_WARNING "%s() tda10048_config.clk_freq_khz "
+			"is not set (defaulting to %d)\n",
+			__func__,
+			config->clk_freq_khz);
+	}
+}
+
+static struct dvb_frontend_ops tda10048_ops;
+
+struct dvb_frontend *tda10048_attach(const struct tda10048_config *config,
+	struct i2c_adapter *i2c)
+{
+	struct tda10048_state *state = NULL;
+
+	dprintk(1, "%s()\n", __func__);
+
+	/* allocate memory for the internal state */
+	state = kzalloc(sizeof(struct tda10048_state), GFP_KERNEL);
+	if (state == NULL)
+		goto error;
+
+	/* setup the state and clone the config */
+	memcpy(&state->config, config, sizeof(*config));
+	state->i2c = i2c;
+	state->fwloaded = config->no_firmware;
+	state->bandwidth = 8000000;
+
+	/* check if the demod is present */
+	if (tda10048_readreg(state, TDA10048_IDENTITY) != 0x048)
+		goto error;
+
+	/* create dvb_frontend */
+	memcpy(&state->frontend.ops, &tda10048_ops,
+		sizeof(struct dvb_frontend_ops));
+	state->frontend.demodulator_priv = state;
+
+	/* set pll */
+	if (config->set_pll) {
+		state->pll_mfactor = config->pll_m;
+		state->pll_nfactor = config->pll_n;
+		state->pll_pfactor = config->pll_p;
+	} else {
+		state->pll_mfactor = 10;
+		state->pll_nfactor = 3;
+		state->pll_pfactor = 0;
+	}
+
+	/* Establish any defaults the the user didn't pass */
+	tda10048_establish_defaults(&state->frontend);
+
+	/* Set the xtal and freq defaults */
+	if (tda10048_set_if(&state->frontend, 8000000) != 0)
+		goto error;
+
+	/* Default bandwidth */
+	if (tda10048_set_bandwidth(&state->frontend, 8000000) != 0)
+		goto error;
+
+	/* Leave the gate closed */
+	tda10048_i2c_gate_ctrl(&state->frontend, 0);
+
+	return &state->frontend;
+
+error:
+	kfree(state);
+	return NULL;
+}
+EXPORT_SYMBOL(tda10048_attach);
+
+static struct dvb_frontend_ops tda10048_ops = {
+	.delsys = { SYS_DVBT },
+	.info = {
+		.name			= "NXP TDA10048HN DVB-T",
+		.frequency_min		= 177000000,
+		.frequency_max		= 858000000,
+		.frequency_stepsize	= 166666,
+		.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_FEC_AUTO |
+		FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
+		FE_CAN_HIERARCHY_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |
+		FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_RECOVER
+	},
+
+	.release = tda10048_release,
+	.init = tda10048_init,
+	.i2c_gate_ctrl = tda10048_i2c_gate_ctrl,
+	.set_frontend = tda10048_set_frontend,
+	.get_frontend = tda10048_get_frontend,
+	.get_tune_settings = tda10048_get_tune_settings,
+	.read_status = tda10048_read_status,
+	.read_ber = tda10048_read_ber,
+	.read_signal_strength = tda10048_read_signal_strength,
+	.read_snr = tda10048_read_snr,
+	.read_ucblocks = tda10048_read_ucblocks,
+};
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Enable verbose debug messages");
+
+MODULE_DESCRIPTION("NXP TDA10048HN DVB-T Demodulator driver");
+MODULE_AUTHOR("Steven Toth");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb-frontends/tda10048.h b/drivers/media/dvb-frontends/tda10048.h
new file mode 100644
index 0000000..fb2ef5a
--- /dev/null
+++ b/drivers/media/dvb-frontends/tda10048.h
@@ -0,0 +1,90 @@
+/*
+    NXP TDA10048HN DVB OFDM demodulator driver
+
+    Copyright (C) 2009 Steven Toth <stoth@kernellabs.com>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef TDA10048_H
+#define TDA10048_H
+
+#include <linux/dvb/frontend.h>
+#include <linux/firmware.h>
+
+struct tda10048_config {
+
+	/* the demodulator's i2c address */
+	u8 demod_address;
+
+	/* serial/parallel output */
+#define TDA10048_PARALLEL_OUTPUT 0
+#define TDA10048_SERIAL_OUTPUT   1
+	u8 output_mode;
+
+#define TDA10048_BULKWRITE_200	200
+#define TDA10048_BULKWRITE_50	50
+	u8 fwbulkwritelen;
+
+	/* Spectral Inversion */
+#define TDA10048_INVERSION_OFF 0
+#define TDA10048_INVERSION_ON  1
+	u8 inversion;
+
+#define TDA10048_IF_3300  3300
+#define TDA10048_IF_3500  3500
+#define TDA10048_IF_3800  3800
+#define TDA10048_IF_4000  4000
+#define TDA10048_IF_4300  4300
+#define TDA10048_IF_4500  4500
+#define TDA10048_IF_4750  4750
+#define TDA10048_IF_5000  5000
+#define TDA10048_IF_36130 36130
+	u16 dtv6_if_freq_khz;
+	u16 dtv7_if_freq_khz;
+	u16 dtv8_if_freq_khz;
+
+#define TDA10048_CLK_4000  4000
+#define TDA10048_CLK_16000 16000
+	u16 clk_freq_khz;
+
+	/* Disable I2C gate access */
+	u8 disable_gate_access;
+
+	bool no_firmware;
+
+	bool set_pll;
+	u8 pll_m;
+	u8 pll_p;
+	u8 pll_n;
+};
+
+#if defined(CONFIG_DVB_TDA10048) || \
+	(defined(CONFIG_DVB_TDA10048_MODULE) && defined(MODULE))
+extern struct dvb_frontend *tda10048_attach(
+	const struct tda10048_config *config,
+	struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend *tda10048_attach(
+	const struct tda10048_config *config,
+	struct i2c_adapter *i2c)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif /* CONFIG_DVB_TDA10048 */
+
+#endif /* TDA10048_H */
diff --git a/drivers/media/dvb-frontends/tda1004x.c b/drivers/media/dvb-frontends/tda1004x.c
new file mode 100644
index 0000000..35d72b4
--- /dev/null
+++ b/drivers/media/dvb-frontends/tda1004x.c
@@ -0,0 +1,1381 @@
+  /*
+     Driver for Philips tda1004xh OFDM Demodulator
+
+     (c) 2003, 2004 Andrew de Quincey & Robert Schlabbach
+
+     This program is free software; you can redistribute it and/or modify
+     it under the terms of the 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.
+
+   */
+/*
+ * This driver needs external firmware. Please use the commands
+ * "<kerneldir>/Documentation/dvb/get_dvb_firmware tda10045",
+ * "<kerneldir>/Documentation/dvb/get_dvb_firmware tda10046" to
+ * download/extract them, and then copy them to /usr/lib/hotplug/firmware
+ * or /lib/firmware (depending on configuration of firmware hotplug).
+ */
+#define TDA10045_DEFAULT_FIRMWARE "dvb-fe-tda10045.fw"
+#define TDA10046_DEFAULT_FIRMWARE "dvb-fe-tda10046.fw"
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/jiffies.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+
+#include "dvb_frontend.h"
+#include "tda1004x.h"
+
+static int debug;
+#define dprintk(args...) \
+	do { \
+		if (debug) printk(KERN_DEBUG "tda1004x: " args); \
+	} while (0)
+
+#define TDA1004X_CHIPID		 0x00
+#define TDA1004X_AUTO		 0x01
+#define TDA1004X_IN_CONF1	 0x02
+#define TDA1004X_IN_CONF2	 0x03
+#define TDA1004X_OUT_CONF1	 0x04
+#define TDA1004X_OUT_CONF2	 0x05
+#define TDA1004X_STATUS_CD	 0x06
+#define TDA1004X_CONFC4		 0x07
+#define TDA1004X_DSSPARE2	 0x0C
+#define TDA10045H_CODE_IN	 0x0D
+#define TDA10045H_FWPAGE	 0x0E
+#define TDA1004X_SCAN_CPT	 0x10
+#define TDA1004X_DSP_CMD	 0x11
+#define TDA1004X_DSP_ARG	 0x12
+#define TDA1004X_DSP_DATA1	 0x13
+#define TDA1004X_DSP_DATA2	 0x14
+#define TDA1004X_CONFADC1	 0x15
+#define TDA1004X_CONFC1		 0x16
+#define TDA10045H_S_AGC		 0x1a
+#define TDA10046H_AGC_TUN_LEVEL	 0x1a
+#define TDA1004X_SNR		 0x1c
+#define TDA1004X_CONF_TS1	 0x1e
+#define TDA1004X_CONF_TS2	 0x1f
+#define TDA1004X_CBER_RESET	 0x20
+#define TDA1004X_CBER_MSB	 0x21
+#define TDA1004X_CBER_LSB	 0x22
+#define TDA1004X_CVBER_LUT	 0x23
+#define TDA1004X_VBER_MSB	 0x24
+#define TDA1004X_VBER_MID	 0x25
+#define TDA1004X_VBER_LSB	 0x26
+#define TDA1004X_UNCOR		 0x27
+
+#define TDA10045H_CONFPLL_P	 0x2D
+#define TDA10045H_CONFPLL_M_MSB	 0x2E
+#define TDA10045H_CONFPLL_M_LSB	 0x2F
+#define TDA10045H_CONFPLL_N	 0x30
+
+#define TDA10046H_CONFPLL1	 0x2D
+#define TDA10046H_CONFPLL2	 0x2F
+#define TDA10046H_CONFPLL3	 0x30
+#define TDA10046H_TIME_WREF1	 0x31
+#define TDA10046H_TIME_WREF2	 0x32
+#define TDA10046H_TIME_WREF3	 0x33
+#define TDA10046H_TIME_WREF4	 0x34
+#define TDA10046H_TIME_WREF5	 0x35
+
+#define TDA10045H_UNSURW_MSB	 0x31
+#define TDA10045H_UNSURW_LSB	 0x32
+#define TDA10045H_WREF_MSB	 0x33
+#define TDA10045H_WREF_MID	 0x34
+#define TDA10045H_WREF_LSB	 0x35
+#define TDA10045H_MUXOUT	 0x36
+#define TDA1004X_CONFADC2	 0x37
+
+#define TDA10045H_IOFFSET	 0x38
+
+#define TDA10046H_CONF_TRISTATE1 0x3B
+#define TDA10046H_CONF_TRISTATE2 0x3C
+#define TDA10046H_CONF_POLARITY	 0x3D
+#define TDA10046H_FREQ_OFFSET	 0x3E
+#define TDA10046H_GPIO_OUT_SEL	 0x41
+#define TDA10046H_GPIO_SELECT	 0x42
+#define TDA10046H_AGC_CONF	 0x43
+#define TDA10046H_AGC_THR	 0x44
+#define TDA10046H_AGC_RENORM	 0x45
+#define TDA10046H_AGC_GAINS	 0x46
+#define TDA10046H_AGC_TUN_MIN	 0x47
+#define TDA10046H_AGC_TUN_MAX	 0x48
+#define TDA10046H_AGC_IF_MIN	 0x49
+#define TDA10046H_AGC_IF_MAX	 0x4A
+
+#define TDA10046H_FREQ_PHY2_MSB	 0x4D
+#define TDA10046H_FREQ_PHY2_LSB	 0x4E
+
+#define TDA10046H_CVBER_CTRL	 0x4F
+#define TDA10046H_AGC_IF_LEVEL	 0x52
+#define TDA10046H_CODE_CPT	 0x57
+#define TDA10046H_CODE_IN	 0x58
+
+
+static int tda1004x_write_byteI(struct tda1004x_state *state, int reg, int data)
+{
+	int ret;
+	u8 buf[] = { reg, data };
+	struct i2c_msg msg = { .flags = 0, .buf = buf, .len = 2 };
+
+	dprintk("%s: reg=0x%x, data=0x%x\n", __func__, reg, data);
+
+	msg.addr = state->config->demod_address;
+	ret = i2c_transfer(state->i2c, &msg, 1);
+
+	if (ret != 1)
+		dprintk("%s: error reg=0x%x, data=0x%x, ret=%i\n",
+			__func__, reg, data, ret);
+
+	dprintk("%s: success reg=0x%x, data=0x%x, ret=%i\n", __func__,
+		reg, data, ret);
+	return (ret != 1) ? -1 : 0;
+}
+
+static int tda1004x_read_byte(struct tda1004x_state *state, int reg)
+{
+	int ret;
+	u8 b0[] = { reg };
+	u8 b1[] = { 0 };
+	struct i2c_msg msg[] = {{ .flags = 0, .buf = b0, .len = 1 },
+				{ .flags = I2C_M_RD, .buf = b1, .len = 1 }};
+
+	dprintk("%s: reg=0x%x\n", __func__, reg);
+
+	msg[0].addr = state->config->demod_address;
+	msg[1].addr = state->config->demod_address;
+	ret = i2c_transfer(state->i2c, msg, 2);
+
+	if (ret != 2) {
+		dprintk("%s: error reg=0x%x, ret=%i\n", __func__, reg,
+			ret);
+		return -EINVAL;
+	}
+
+	dprintk("%s: success reg=0x%x, data=0x%x, ret=%i\n", __func__,
+		reg, b1[0], ret);
+	return b1[0];
+}
+
+static int tda1004x_write_mask(struct tda1004x_state *state, int reg, int mask, int data)
+{
+	int val;
+	dprintk("%s: reg=0x%x, mask=0x%x, data=0x%x\n", __func__, reg,
+		mask, data);
+
+	// read a byte and check
+	val = tda1004x_read_byte(state, reg);
+	if (val < 0)
+		return val;
+
+	// mask if off
+	val = val & ~mask;
+	val |= data & 0xff;
+
+	// write it out again
+	return tda1004x_write_byteI(state, reg, val);
+}
+
+static int tda1004x_write_buf(struct tda1004x_state *state, int reg, unsigned char *buf, int len)
+{
+	int i;
+	int result;
+
+	dprintk("%s: reg=0x%x, len=0x%x\n", __func__, reg, len);
+
+	result = 0;
+	for (i = 0; i < len; i++) {
+		result = tda1004x_write_byteI(state, reg + i, buf[i]);
+		if (result != 0)
+			break;
+	}
+
+	return result;
+}
+
+static int tda1004x_enable_tuner_i2c(struct tda1004x_state *state)
+{
+	int result;
+	dprintk("%s\n", __func__);
+
+	result = tda1004x_write_mask(state, TDA1004X_CONFC4, 2, 2);
+	msleep(20);
+	return result;
+}
+
+static int tda1004x_disable_tuner_i2c(struct tda1004x_state *state)
+{
+	dprintk("%s\n", __func__);
+
+	return tda1004x_write_mask(state, TDA1004X_CONFC4, 2, 0);
+}
+
+static int tda10045h_set_bandwidth(struct tda1004x_state *state,
+				   u32 bandwidth)
+{
+	static u8 bandwidth_6mhz[] = { 0x02, 0x00, 0x3d, 0x00, 0x60, 0x1e, 0xa7, 0x45, 0x4f };
+	static u8 bandwidth_7mhz[] = { 0x02, 0x00, 0x37, 0x00, 0x4a, 0x2f, 0x6d, 0x76, 0xdb };
+	static u8 bandwidth_8mhz[] = { 0x02, 0x00, 0x3d, 0x00, 0x48, 0x17, 0x89, 0xc7, 0x14 };
+
+	switch (bandwidth) {
+	case 6000000:
+		tda1004x_write_buf(state, TDA10045H_CONFPLL_P, bandwidth_6mhz, sizeof(bandwidth_6mhz));
+		break;
+
+	case 7000000:
+		tda1004x_write_buf(state, TDA10045H_CONFPLL_P, bandwidth_7mhz, sizeof(bandwidth_7mhz));
+		break;
+
+	case 8000000:
+		tda1004x_write_buf(state, TDA10045H_CONFPLL_P, bandwidth_8mhz, sizeof(bandwidth_8mhz));
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	tda1004x_write_byteI(state, TDA10045H_IOFFSET, 0);
+
+	return 0;
+}
+
+static int tda10046h_set_bandwidth(struct tda1004x_state *state,
+				   u32 bandwidth)
+{
+	static u8 bandwidth_6mhz_53M[] = { 0x7b, 0x2e, 0x11, 0xf0, 0xd2 };
+	static u8 bandwidth_7mhz_53M[] = { 0x6a, 0x02, 0x6a, 0x43, 0x9f };
+	static u8 bandwidth_8mhz_53M[] = { 0x5c, 0x32, 0xc2, 0x96, 0x6d };
+
+	static u8 bandwidth_6mhz_48M[] = { 0x70, 0x02, 0x49, 0x24, 0x92 };
+	static u8 bandwidth_7mhz_48M[] = { 0x60, 0x02, 0xaa, 0xaa, 0xab };
+	static u8 bandwidth_8mhz_48M[] = { 0x54, 0x03, 0x0c, 0x30, 0xc3 };
+	int tda10046_clk53m;
+
+	if ((state->config->if_freq == TDA10046_FREQ_045) ||
+	    (state->config->if_freq == TDA10046_FREQ_052))
+		tda10046_clk53m = 0;
+	else
+		tda10046_clk53m = 1;
+	switch (bandwidth) {
+	case 6000000:
+		if (tda10046_clk53m)
+			tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_6mhz_53M,
+						  sizeof(bandwidth_6mhz_53M));
+		else
+			tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_6mhz_48M,
+						  sizeof(bandwidth_6mhz_48M));
+		if (state->config->if_freq == TDA10046_FREQ_045) {
+			tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0a);
+			tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0xab);
+		}
+		break;
+
+	case 7000000:
+		if (tda10046_clk53m)
+			tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_7mhz_53M,
+						  sizeof(bandwidth_7mhz_53M));
+		else
+			tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_7mhz_48M,
+						  sizeof(bandwidth_7mhz_48M));
+		if (state->config->if_freq == TDA10046_FREQ_045) {
+			tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0c);
+			tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x00);
+		}
+		break;
+
+	case 8000000:
+		if (tda10046_clk53m)
+			tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_8mhz_53M,
+						  sizeof(bandwidth_8mhz_53M));
+		else
+			tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_8mhz_48M,
+						  sizeof(bandwidth_8mhz_48M));
+		if (state->config->if_freq == TDA10046_FREQ_045) {
+			tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0d);
+			tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x55);
+		}
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int tda1004x_do_upload(struct tda1004x_state *state,
+			      const unsigned char *mem, unsigned int len,
+			      u8 dspCodeCounterReg, u8 dspCodeInReg)
+{
+	u8 buf[65];
+	struct i2c_msg fw_msg = { .flags = 0, .buf = buf, .len = 0 };
+	int tx_size;
+	int pos = 0;
+
+	/* clear code counter */
+	tda1004x_write_byteI(state, dspCodeCounterReg, 0);
+	fw_msg.addr = state->config->demod_address;
+
+	buf[0] = dspCodeInReg;
+	while (pos != len) {
+		// work out how much to send this time
+		tx_size = len - pos;
+		if (tx_size > 0x10)
+			tx_size = 0x10;
+
+		// send the chunk
+		memcpy(buf + 1, mem + pos, tx_size);
+		fw_msg.len = tx_size + 1;
+		if (i2c_transfer(state->i2c, &fw_msg, 1) != 1) {
+			printk(KERN_ERR "tda1004x: Error during firmware upload\n");
+			return -EIO;
+		}
+		pos += tx_size;
+
+		dprintk("%s: fw_pos=0x%x\n", __func__, pos);
+	}
+	// give the DSP a chance to settle 03/10/05 Hac
+	msleep(100);
+
+	return 0;
+}
+
+static int tda1004x_check_upload_ok(struct tda1004x_state *state)
+{
+	u8 data1, data2;
+	unsigned long timeout;
+
+	if (state->demod_type == TDA1004X_DEMOD_TDA10046) {
+		timeout = jiffies + 2 * HZ;
+		while(!(tda1004x_read_byte(state, TDA1004X_STATUS_CD) & 0x20)) {
+			if (time_after(jiffies, timeout)) {
+				printk(KERN_ERR "tda1004x: timeout waiting for DSP ready\n");
+				break;
+			}
+			msleep(1);
+		}
+	} else
+		msleep(100);
+
+	// check upload was OK
+	tda1004x_write_mask(state, TDA1004X_CONFC4, 0x10, 0); // we want to read from the DSP
+	tda1004x_write_byteI(state, TDA1004X_DSP_CMD, 0x67);
+
+	data1 = tda1004x_read_byte(state, TDA1004X_DSP_DATA1);
+	data2 = tda1004x_read_byte(state, TDA1004X_DSP_DATA2);
+	if (data1 != 0x67 || data2 < 0x20 || data2 > 0x2e) {
+		printk(KERN_INFO "tda1004x: found firmware revision %x -- invalid\n", data2);
+		return -EIO;
+	}
+	printk(KERN_INFO "tda1004x: found firmware revision %x -- ok\n", data2);
+	return 0;
+}
+
+static int tda10045_fwupload(struct dvb_frontend* fe)
+{
+	struct tda1004x_state* state = fe->demodulator_priv;
+	int ret;
+	const struct firmware *fw;
+
+	/* don't re-upload unless necessary */
+	if (tda1004x_check_upload_ok(state) == 0)
+		return 0;
+
+	/* request the firmware, this will block until someone uploads it */
+	printk(KERN_INFO "tda1004x: waiting for firmware upload (%s)...\n", TDA10045_DEFAULT_FIRMWARE);
+	ret = state->config->request_firmware(fe, &fw, TDA10045_DEFAULT_FIRMWARE);
+	if (ret) {
+		printk(KERN_ERR "tda1004x: no firmware upload (timeout or file not found?)\n");
+		return ret;
+	}
+
+	/* reset chip */
+	tda1004x_write_mask(state, TDA1004X_CONFC4, 0x10, 0);
+	tda1004x_write_mask(state, TDA1004X_CONFC4, 8, 8);
+	tda1004x_write_mask(state, TDA1004X_CONFC4, 8, 0);
+	msleep(10);
+
+	/* set parameters */
+	tda10045h_set_bandwidth(state, 8000000);
+
+	ret = tda1004x_do_upload(state, fw->data, fw->size, TDA10045H_FWPAGE, TDA10045H_CODE_IN);
+	release_firmware(fw);
+	if (ret)
+		return ret;
+	printk(KERN_INFO "tda1004x: firmware upload complete\n");
+
+	/* wait for DSP to initialise */
+	/* DSPREADY doesn't seem to work on the TDA10045H */
+	msleep(100);
+
+	return tda1004x_check_upload_ok(state);
+}
+
+static void tda10046_init_plls(struct dvb_frontend* fe)
+{
+	struct tda1004x_state* state = fe->demodulator_priv;
+	int tda10046_clk53m;
+
+	if ((state->config->if_freq == TDA10046_FREQ_045) ||
+	    (state->config->if_freq == TDA10046_FREQ_052))
+		tda10046_clk53m = 0;
+	else
+		tda10046_clk53m = 1;
+
+	tda1004x_write_byteI(state, TDA10046H_CONFPLL1, 0xf0);
+	if(tda10046_clk53m) {
+		printk(KERN_INFO "tda1004x: setting up plls for 53MHz sampling clock\n");
+		tda1004x_write_byteI(state, TDA10046H_CONFPLL2, 0x08); // PLL M = 8
+	} else {
+		printk(KERN_INFO "tda1004x: setting up plls for 48MHz sampling clock\n");
+		tda1004x_write_byteI(state, TDA10046H_CONFPLL2, 0x03); // PLL M = 3
+	}
+	if (state->config->xtal_freq == TDA10046_XTAL_4M ) {
+		dprintk("%s: setting up PLLs for a 4 MHz Xtal\n", __func__);
+		tda1004x_write_byteI(state, TDA10046H_CONFPLL3, 0); // PLL P = N = 0
+	} else {
+		dprintk("%s: setting up PLLs for a 16 MHz Xtal\n", __func__);
+		tda1004x_write_byteI(state, TDA10046H_CONFPLL3, 3); // PLL P = 0, N = 3
+	}
+	if(tda10046_clk53m)
+		tda1004x_write_byteI(state, TDA10046H_FREQ_OFFSET, 0x67);
+	else
+		tda1004x_write_byteI(state, TDA10046H_FREQ_OFFSET, 0x72);
+	/* Note clock frequency is handled implicitly */
+	switch (state->config->if_freq) {
+	case TDA10046_FREQ_045:
+		tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0c);
+		tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x00);
+		break;
+	case TDA10046_FREQ_052:
+		tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0d);
+		tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0xc7);
+		break;
+	case TDA10046_FREQ_3617:
+		tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0xd7);
+		tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x59);
+		break;
+	case TDA10046_FREQ_3613:
+		tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0xd7);
+		tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x3f);
+		break;
+	}
+	tda10046h_set_bandwidth(state, 8000000); /* default bandwidth 8 MHz */
+	/* let the PLLs settle */
+	msleep(120);
+}
+
+static int tda10046_fwupload(struct dvb_frontend* fe)
+{
+	struct tda1004x_state* state = fe->demodulator_priv;
+	int ret, confc4;
+	const struct firmware *fw;
+
+	/* reset + wake up chip */
+	if (state->config->xtal_freq == TDA10046_XTAL_4M) {
+		confc4 = 0;
+	} else {
+		dprintk("%s: 16MHz Xtal, reducing I2C speed\n", __func__);
+		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) {
+		tda1004x_write_byteI(state, TDA10046H_CONF_TRISTATE2, 0x33);
+		tda1004x_write_mask(state, TDA10046H_CONF_POLARITY, 0x0f, state->config->gpio_config &0x0f);
+	}
+	/* let the clocks recover from sleep */
+	msleep(10);
+
+	/* The PLLs need to be reprogrammed after sleep */
+	tda10046_init_plls(fe);
+	tda1004x_write_mask(state, TDA1004X_CONFADC2, 0xc0, 0);
+
+	/* don't re-upload unless necessary */
+	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_byteI(state, TDA1004X_CONFC4, 4);
+	msleep(300);
+	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");
+		ret = state->config->request_firmware(fe, &fw, TDA10046_DEFAULT_FIRMWARE);
+		if (ret) {
+			/* remain compatible to old bug: try to load with tda10045 image name */
+			ret = state->config->request_firmware(fe, &fw, TDA10045_DEFAULT_FIRMWARE);
+			if (ret) {
+				printk(KERN_ERR "tda1004x: no firmware upload (timeout or file not found?)\n");
+				return ret;
+			} else {
+				printk(KERN_INFO "tda1004x: please rename the firmware file to %s\n",
+						  TDA10046_DEFAULT_FIRMWARE);
+			}
+		}
+	} else {
+		printk(KERN_ERR "tda1004x: no request function defined, can't upload from file\n");
+		return -EIO;
+	}
+	tda1004x_write_mask(state, TDA1004X_CONFC4, 8, 8); // going to boot from HOST
+	ret = tda1004x_do_upload(state, fw->data, fw->size, TDA10046H_CODE_CPT, TDA10046H_CODE_IN);
+	release_firmware(fw);
+	return tda1004x_check_upload_ok(state);
+}
+
+static int tda1004x_encode_fec(int fec)
+{
+	// convert known FEC values
+	switch (fec) {
+	case FEC_1_2:
+		return 0;
+	case FEC_2_3:
+		return 1;
+	case FEC_3_4:
+		return 2;
+	case FEC_5_6:
+		return 3;
+	case FEC_7_8:
+		return 4;
+	}
+
+	// unsupported
+	return -EINVAL;
+}
+
+static int tda1004x_decode_fec(int tdafec)
+{
+	// convert known FEC values
+	switch (tdafec) {
+	case 0:
+		return FEC_1_2;
+	case 1:
+		return FEC_2_3;
+	case 2:
+		return FEC_3_4;
+	case 3:
+		return FEC_5_6;
+	case 4:
+		return FEC_7_8;
+	}
+
+	// unsupported
+	return -1;
+}
+
+static int tda1004x_write(struct dvb_frontend* fe, const u8 buf[], int len)
+{
+	struct tda1004x_state* state = fe->demodulator_priv;
+
+	if (len != 2)
+		return -EINVAL;
+
+	return tda1004x_write_byteI(state, buf[0], buf[1]);
+}
+
+static int tda10045_init(struct dvb_frontend* fe)
+{
+	struct tda1004x_state* state = fe->demodulator_priv;
+
+	dprintk("%s\n", __func__);
+
+	if (tda10045_fwupload(fe)) {
+		printk("tda1004x: firmware upload failed\n");
+		return -EIO;
+	}
+
+	tda1004x_write_mask(state, TDA1004X_CONFADC1, 0x10, 0); // wake up the ADC
+
+	// tda setup
+	tda1004x_write_mask(state, TDA1004X_CONFC4, 0x20, 0); // disable DSP watchdog timer
+	tda1004x_write_mask(state, TDA1004X_AUTO, 8, 0); // select HP stream
+	tda1004x_write_mask(state, TDA1004X_CONFC1, 0x40, 0); // set polarity of VAGC signal
+	tda1004x_write_mask(state, TDA1004X_CONFC1, 0x80, 0x80); // enable pulse killer
+	tda1004x_write_mask(state, TDA1004X_AUTO, 0x10, 0x10); // enable auto offset
+	tda1004x_write_mask(state, TDA1004X_IN_CONF2, 0xC0, 0x0); // no frequency offset
+	tda1004x_write_byteI(state, TDA1004X_CONF_TS1, 0); // setup MPEG2 TS interface
+	tda1004x_write_byteI(state, TDA1004X_CONF_TS2, 0); // setup MPEG2 TS interface
+	tda1004x_write_mask(state, TDA1004X_VBER_MSB, 0xe0, 0xa0); // 10^6 VBER measurement bits
+	tda1004x_write_mask(state, TDA1004X_CONFC1, 0x10, 0); // VAGC polarity
+	tda1004x_write_byteI(state, TDA1004X_CONFADC1, 0x2e);
+
+	tda1004x_write_mask(state, 0x1f, 0x01, state->config->invert_oclk);
+
+	return 0;
+}
+
+static int tda10046_init(struct dvb_frontend* fe)
+{
+	struct tda1004x_state* state = fe->demodulator_priv;
+	dprintk("%s\n", __func__);
+
+	if (tda10046_fwupload(fe)) {
+		printk("tda1004x: firmware upload failed\n");
+			return -EIO;
+	}
+
+	// tda setup
+	tda1004x_write_mask(state, TDA1004X_CONFC4, 0x20, 0); // disable DSP watchdog timer
+	tda1004x_write_byteI(state, TDA1004X_AUTO, 0x87);    // 100 ppm crystal, select HP stream
+	tda1004x_write_byteI(state, TDA1004X_CONFC1, 0x88);      // enable pulse killer
+
+	switch (state->config->agc_config) {
+	case TDA10046_AGC_DEFAULT:
+		tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x00); // AGC setup
+		tda1004x_write_mask(state, TDA10046H_CONF_POLARITY, 0xf0, 0x60);  // set AGC polarities
+		break;
+	case TDA10046_AGC_IFO_AUTO_NEG:
+		tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x0a); // AGC setup
+		tda1004x_write_mask(state, TDA10046H_CONF_POLARITY, 0xf0, 0x60);  // set AGC polarities
+		break;
+	case TDA10046_AGC_IFO_AUTO_POS:
+		tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x0a); // AGC setup
+		tda1004x_write_mask(state, TDA10046H_CONF_POLARITY, 0xf0, 0x00);  // set AGC polarities
+		break;
+	case TDA10046_AGC_TDA827X:
+		tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x02);   // AGC setup
+		tda1004x_write_byteI(state, TDA10046H_AGC_THR, 0x70);    // AGC Threshold
+		tda1004x_write_byteI(state, TDA10046H_AGC_RENORM, 0x08); // Gain Renormalize
+		tda1004x_write_mask(state, TDA10046H_CONF_POLARITY, 0xf0, 0x60);  // set AGC polarities
+		break;
+	}
+	if (state->config->ts_mode == 0) {
+		tda1004x_write_mask(state, TDA10046H_CONF_TRISTATE1, 0xc0, 0x40);
+		tda1004x_write_mask(state, 0x3a, 0x80, state->config->invert_oclk << 7);
+	} else {
+		tda1004x_write_mask(state, TDA10046H_CONF_TRISTATE1, 0xc0, 0x80);
+		tda1004x_write_mask(state, TDA10046H_CONF_POLARITY, 0x10,
+							state->config->invert_oclk << 4);
+	}
+	tda1004x_write_byteI(state, TDA1004X_CONFADC2, 0x38);
+	tda1004x_write_mask (state, TDA10046H_CONF_TRISTATE1, 0x3e, 0x38); // Turn IF AGC output on
+	tda1004x_write_byteI(state, TDA10046H_AGC_TUN_MIN, 0);	  // }
+	tda1004x_write_byteI(state, TDA10046H_AGC_TUN_MAX, 0xff); // } AGC min/max values
+	tda1004x_write_byteI(state, TDA10046H_AGC_IF_MIN, 0);	  // }
+	tda1004x_write_byteI(state, TDA10046H_AGC_IF_MAX, 0xff);  // }
+	tda1004x_write_byteI(state, TDA10046H_AGC_GAINS, 0x12); // IF gain 2, TUN gain 1
+	tda1004x_write_byteI(state, TDA10046H_CVBER_CTRL, 0x1a); // 10^6 VBER measurement bits
+	tda1004x_write_byteI(state, TDA1004X_CONF_TS1, 7); // MPEG2 interface config
+	tda1004x_write_byteI(state, TDA1004X_CONF_TS2, 0xc0); // MPEG2 interface config
+	// tda1004x_write_mask(state, 0x50, 0x80, 0x80);         // handle out of guard echoes
+
+	return 0;
+}
+
+static int tda1004x_set_fe(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *fe_params = &fe->dtv_property_cache;
+	struct tda1004x_state* state = fe->demodulator_priv;
+	int tmp;
+	int inversion;
+
+	dprintk("%s\n", __func__);
+
+	if (state->demod_type == TDA1004X_DEMOD_TDA10046) {
+		// setup auto offset
+		tda1004x_write_mask(state, TDA1004X_AUTO, 0x10, 0x10);
+		tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x80, 0);
+		tda1004x_write_mask(state, TDA1004X_IN_CONF2, 0xC0, 0);
+
+		// disable agc_conf[2]
+		tda1004x_write_mask(state, TDA10046H_AGC_CONF, 4, 0);
+	}
+
+	// set frequency
+	if (fe->ops.tuner_ops.set_params) {
+		fe->ops.tuner_ops.set_params(fe);
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 0);
+	}
+
+	// Hardcoded to use auto as much as possible on the TDA10045 as it
+	// is very unreliable if AUTO mode is _not_ used.
+	if (state->demod_type == TDA1004X_DEMOD_TDA10045) {
+		fe_params->code_rate_HP = FEC_AUTO;
+		fe_params->guard_interval = GUARD_INTERVAL_AUTO;
+		fe_params->transmission_mode = TRANSMISSION_MODE_AUTO;
+	}
+
+	// Set standard params.. or put them to auto
+	if ((fe_params->code_rate_HP == FEC_AUTO) ||
+		(fe_params->code_rate_LP == FEC_AUTO) ||
+		(fe_params->modulation == QAM_AUTO) ||
+		(fe_params->hierarchy == HIERARCHY_AUTO)) {
+		tda1004x_write_mask(state, TDA1004X_AUTO, 1, 1);	// enable auto
+		tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x03, 0);	/* turn off modulation bits */
+		tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x60, 0);	// turn off hierarchy bits
+		tda1004x_write_mask(state, TDA1004X_IN_CONF2, 0x3f, 0);	// turn off FEC bits
+	} else {
+		tda1004x_write_mask(state, TDA1004X_AUTO, 1, 0);	// disable auto
+
+		// set HP FEC
+		tmp = tda1004x_encode_fec(fe_params->code_rate_HP);
+		if (tmp < 0)
+			return tmp;
+		tda1004x_write_mask(state, TDA1004X_IN_CONF2, 7, tmp);
+
+		// set LP FEC
+		tmp = tda1004x_encode_fec(fe_params->code_rate_LP);
+		if (tmp < 0)
+			return tmp;
+		tda1004x_write_mask(state, TDA1004X_IN_CONF2, 0x38, tmp << 3);
+
+		/* set modulation */
+		switch (fe_params->modulation) {
+		case QPSK:
+			tda1004x_write_mask(state, TDA1004X_IN_CONF1, 3, 0);
+			break;
+
+		case QAM_16:
+			tda1004x_write_mask(state, TDA1004X_IN_CONF1, 3, 1);
+			break;
+
+		case QAM_64:
+			tda1004x_write_mask(state, TDA1004X_IN_CONF1, 3, 2);
+			break;
+
+		default:
+			return -EINVAL;
+		}
+
+		// set hierarchy
+		switch (fe_params->hierarchy) {
+		case HIERARCHY_NONE:
+			tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x60, 0 << 5);
+			break;
+
+		case HIERARCHY_1:
+			tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x60, 1 << 5);
+			break;
+
+		case HIERARCHY_2:
+			tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x60, 2 << 5);
+			break;
+
+		case HIERARCHY_4:
+			tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x60, 3 << 5);
+			break;
+
+		default:
+			return -EINVAL;
+		}
+	}
+
+	// set bandwidth
+	switch (state->demod_type) {
+	case TDA1004X_DEMOD_TDA10045:
+		tda10045h_set_bandwidth(state, fe_params->bandwidth_hz);
+		break;
+
+	case TDA1004X_DEMOD_TDA10046:
+		tda10046h_set_bandwidth(state, fe_params->bandwidth_hz);
+		break;
+	}
+
+	// set inversion
+	inversion = fe_params->inversion;
+	if (state->config->invert)
+		inversion = inversion ? INVERSION_OFF : INVERSION_ON;
+	switch (inversion) {
+	case INVERSION_OFF:
+		tda1004x_write_mask(state, TDA1004X_CONFC1, 0x20, 0);
+		break;
+
+	case INVERSION_ON:
+		tda1004x_write_mask(state, TDA1004X_CONFC1, 0x20, 0x20);
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	// set guard interval
+	switch (fe_params->guard_interval) {
+	case GUARD_INTERVAL_1_32:
+		tda1004x_write_mask(state, TDA1004X_AUTO, 2, 0);
+		tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x0c, 0 << 2);
+		break;
+
+	case GUARD_INTERVAL_1_16:
+		tda1004x_write_mask(state, TDA1004X_AUTO, 2, 0);
+		tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x0c, 1 << 2);
+		break;
+
+	case GUARD_INTERVAL_1_8:
+		tda1004x_write_mask(state, TDA1004X_AUTO, 2, 0);
+		tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x0c, 2 << 2);
+		break;
+
+	case GUARD_INTERVAL_1_4:
+		tda1004x_write_mask(state, TDA1004X_AUTO, 2, 0);
+		tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x0c, 3 << 2);
+		break;
+
+	case GUARD_INTERVAL_AUTO:
+		tda1004x_write_mask(state, TDA1004X_AUTO, 2, 2);
+		tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x0c, 0 << 2);
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	// set transmission mode
+	switch (fe_params->transmission_mode) {
+	case TRANSMISSION_MODE_2K:
+		tda1004x_write_mask(state, TDA1004X_AUTO, 4, 0);
+		tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x10, 0 << 4);
+		break;
+
+	case TRANSMISSION_MODE_8K:
+		tda1004x_write_mask(state, TDA1004X_AUTO, 4, 0);
+		tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x10, 1 << 4);
+		break;
+
+	case TRANSMISSION_MODE_AUTO:
+		tda1004x_write_mask(state, TDA1004X_AUTO, 4, 4);
+		tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x10, 0);
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	// start the lock
+	switch (state->demod_type) {
+	case TDA1004X_DEMOD_TDA10045:
+		tda1004x_write_mask(state, TDA1004X_CONFC4, 8, 8);
+		tda1004x_write_mask(state, TDA1004X_CONFC4, 8, 0);
+		break;
+
+	case TDA1004X_DEMOD_TDA10046:
+		tda1004x_write_mask(state, TDA1004X_AUTO, 0x40, 0x40);
+		msleep(1);
+		tda1004x_write_mask(state, TDA10046H_AGC_CONF, 4, 1);
+		break;
+	}
+
+	msleep(10);
+
+	return 0;
+}
+
+static int tda1004x_get_fe(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *fe_params = &fe->dtv_property_cache;
+	struct tda1004x_state* state = fe->demodulator_priv;
+
+	dprintk("%s\n", __func__);
+
+	// inversion status
+	fe_params->inversion = INVERSION_OFF;
+	if (tda1004x_read_byte(state, TDA1004X_CONFC1) & 0x20)
+		fe_params->inversion = INVERSION_ON;
+	if (state->config->invert)
+		fe_params->inversion = fe_params->inversion ? INVERSION_OFF : INVERSION_ON;
+
+	// bandwidth
+	switch (state->demod_type) {
+	case TDA1004X_DEMOD_TDA10045:
+		switch (tda1004x_read_byte(state, TDA10045H_WREF_LSB)) {
+		case 0x14:
+			fe_params->bandwidth_hz = 8000000;
+			break;
+		case 0xdb:
+			fe_params->bandwidth_hz = 7000000;
+			break;
+		case 0x4f:
+			fe_params->bandwidth_hz = 6000000;
+			break;
+		}
+		break;
+	case TDA1004X_DEMOD_TDA10046:
+		switch (tda1004x_read_byte(state, TDA10046H_TIME_WREF1)) {
+		case 0x5c:
+		case 0x54:
+			fe_params->bandwidth_hz = 8000000;
+			break;
+		case 0x6a:
+		case 0x60:
+			fe_params->bandwidth_hz = 7000000;
+			break;
+		case 0x7b:
+		case 0x70:
+			fe_params->bandwidth_hz = 6000000;
+			break;
+		}
+		break;
+	}
+
+	// FEC
+	fe_params->code_rate_HP =
+	    tda1004x_decode_fec(tda1004x_read_byte(state, TDA1004X_OUT_CONF2) & 7);
+	fe_params->code_rate_LP =
+	    tda1004x_decode_fec((tda1004x_read_byte(state, TDA1004X_OUT_CONF2) >> 3) & 7);
+
+	/* modulation */
+	switch (tda1004x_read_byte(state, TDA1004X_OUT_CONF1) & 3) {
+	case 0:
+		fe_params->modulation = QPSK;
+		break;
+	case 1:
+		fe_params->modulation = QAM_16;
+		break;
+	case 2:
+		fe_params->modulation = QAM_64;
+		break;
+	}
+
+	// transmission mode
+	fe_params->transmission_mode = TRANSMISSION_MODE_2K;
+	if (tda1004x_read_byte(state, TDA1004X_OUT_CONF1) & 0x10)
+		fe_params->transmission_mode = TRANSMISSION_MODE_8K;
+
+	// guard interval
+	switch ((tda1004x_read_byte(state, TDA1004X_OUT_CONF1) & 0x0c) >> 2) {
+	case 0:
+		fe_params->guard_interval = GUARD_INTERVAL_1_32;
+		break;
+	case 1:
+		fe_params->guard_interval = GUARD_INTERVAL_1_16;
+		break;
+	case 2:
+		fe_params->guard_interval = GUARD_INTERVAL_1_8;
+		break;
+	case 3:
+		fe_params->guard_interval = GUARD_INTERVAL_1_4;
+		break;
+	}
+
+	// hierarchy
+	switch ((tda1004x_read_byte(state, TDA1004X_OUT_CONF1) & 0x60) >> 5) {
+	case 0:
+		fe_params->hierarchy = HIERARCHY_NONE;
+		break;
+	case 1:
+		fe_params->hierarchy = HIERARCHY_1;
+		break;
+	case 2:
+		fe_params->hierarchy = HIERARCHY_2;
+		break;
+	case 3:
+		fe_params->hierarchy = HIERARCHY_4;
+		break;
+	}
+
+	return 0;
+}
+
+static int tda1004x_read_status(struct dvb_frontend* fe, fe_status_t * fe_status)
+{
+	struct tda1004x_state* state = fe->demodulator_priv;
+	int status;
+	int cber;
+	int vber;
+
+	dprintk("%s\n", __func__);
+
+	// read status
+	status = tda1004x_read_byte(state, TDA1004X_STATUS_CD);
+	if (status == -1)
+		return -EIO;
+
+	// decode
+	*fe_status = 0;
+	if (status & 4)
+		*fe_status |= FE_HAS_SIGNAL;
+	if (status & 2)
+		*fe_status |= FE_HAS_CARRIER;
+	if (status & 8)
+		*fe_status |= FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
+
+	// if we don't already have VITERBI (i.e. not LOCKED), see if the viterbi
+	// is getting anything valid
+	if (!(*fe_status & FE_HAS_VITERBI)) {
+		// read the CBER
+		cber = tda1004x_read_byte(state, TDA1004X_CBER_LSB);
+		if (cber == -1)
+			return -EIO;
+		status = tda1004x_read_byte(state, TDA1004X_CBER_MSB);
+		if (status == -1)
+			return -EIO;
+		cber |= (status << 8);
+		// The address 0x20 should be read to cope with a TDA10046 bug
+		tda1004x_read_byte(state, TDA1004X_CBER_RESET);
+
+		if (cber != 65535)
+			*fe_status |= FE_HAS_VITERBI;
+	}
+
+	// if we DO have some valid VITERBI output, but don't already have SYNC
+	// bytes (i.e. not LOCKED), see if the RS decoder is getting anything valid.
+	if ((*fe_status & FE_HAS_VITERBI) && (!(*fe_status & FE_HAS_SYNC))) {
+		// read the VBER
+		vber = tda1004x_read_byte(state, TDA1004X_VBER_LSB);
+		if (vber == -1)
+			return -EIO;
+		status = tda1004x_read_byte(state, TDA1004X_VBER_MID);
+		if (status == -1)
+			return -EIO;
+		vber |= (status << 8);
+		status = tda1004x_read_byte(state, TDA1004X_VBER_MSB);
+		if (status == -1)
+			return -EIO;
+		vber |= (status & 0x0f) << 16;
+		// The CVBER_LUT should be read to cope with TDA10046 hardware bug
+		tda1004x_read_byte(state, TDA1004X_CVBER_LUT);
+
+		// if RS has passed some valid TS packets, then we must be
+		// getting some SYNC bytes
+		if (vber < 16632)
+			*fe_status |= FE_HAS_SYNC;
+	}
+
+	// success
+	dprintk("%s: fe_status=0x%x\n", __func__, *fe_status);
+	return 0;
+}
+
+static int tda1004x_read_signal_strength(struct dvb_frontend* fe, u16 * signal)
+{
+	struct tda1004x_state* state = fe->demodulator_priv;
+	int tmp;
+	int reg = 0;
+
+	dprintk("%s\n", __func__);
+
+	// determine the register to use
+	switch (state->demod_type) {
+	case TDA1004X_DEMOD_TDA10045:
+		reg = TDA10045H_S_AGC;
+		break;
+
+	case TDA1004X_DEMOD_TDA10046:
+		reg = TDA10046H_AGC_IF_LEVEL;
+		break;
+	}
+
+	// read it
+	tmp = tda1004x_read_byte(state, reg);
+	if (tmp < 0)
+		return -EIO;
+
+	*signal = (tmp << 8) | tmp;
+	dprintk("%s: signal=0x%x\n", __func__, *signal);
+	return 0;
+}
+
+static int tda1004x_read_snr(struct dvb_frontend* fe, u16 * snr)
+{
+	struct tda1004x_state* state = fe->demodulator_priv;
+	int tmp;
+
+	dprintk("%s\n", __func__);
+
+	// read it
+	tmp = tda1004x_read_byte(state, TDA1004X_SNR);
+	if (tmp < 0)
+		return -EIO;
+	tmp = 255 - tmp;
+
+	*snr = ((tmp << 8) | tmp);
+	dprintk("%s: snr=0x%x\n", __func__, *snr);
+	return 0;
+}
+
+static int tda1004x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
+{
+	struct tda1004x_state* state = fe->demodulator_priv;
+	int tmp;
+	int tmp2;
+	int counter;
+
+	dprintk("%s\n", __func__);
+
+	// read the UCBLOCKS and reset
+	counter = 0;
+	tmp = tda1004x_read_byte(state, TDA1004X_UNCOR);
+	if (tmp < 0)
+		return -EIO;
+	tmp &= 0x7f;
+	while (counter++ < 5) {
+		tda1004x_write_mask(state, TDA1004X_UNCOR, 0x80, 0);
+		tda1004x_write_mask(state, TDA1004X_UNCOR, 0x80, 0);
+		tda1004x_write_mask(state, TDA1004X_UNCOR, 0x80, 0);
+
+		tmp2 = tda1004x_read_byte(state, TDA1004X_UNCOR);
+		if (tmp2 < 0)
+			return -EIO;
+		tmp2 &= 0x7f;
+		if ((tmp2 < tmp) || (tmp2 == 0))
+			break;
+	}
+
+	if (tmp != 0x7f)
+		*ucblocks = tmp;
+	else
+		*ucblocks = 0xffffffff;
+
+	dprintk("%s: ucblocks=0x%x\n", __func__, *ucblocks);
+	return 0;
+}
+
+static int tda1004x_read_ber(struct dvb_frontend* fe, u32* ber)
+{
+	struct tda1004x_state* state = fe->demodulator_priv;
+	int tmp;
+
+	dprintk("%s\n", __func__);
+
+	// read it in
+	tmp = tda1004x_read_byte(state, TDA1004X_CBER_LSB);
+	if (tmp < 0)
+		return -EIO;
+	*ber = tmp << 1;
+	tmp = tda1004x_read_byte(state, TDA1004X_CBER_MSB);
+	if (tmp < 0)
+		return -EIO;
+	*ber |= (tmp << 9);
+	// The address 0x20 should be read to cope with a TDA10046 bug
+	tda1004x_read_byte(state, TDA1004X_CBER_RESET);
+
+	dprintk("%s: ber=0x%x\n", __func__, *ber);
+	return 0;
+}
+
+static int tda1004x_sleep(struct dvb_frontend* fe)
+{
+	struct tda1004x_state* state = fe->demodulator_priv;
+	int gpio_conf;
+
+	switch (state->demod_type) {
+	case TDA1004X_DEMOD_TDA10045:
+		tda1004x_write_mask(state, TDA1004X_CONFADC1, 0x10, 0x10);
+		break;
+
+	case TDA1004X_DEMOD_TDA10046:
+		/* set outputs to tristate */
+		tda1004x_write_byteI(state, TDA10046H_CONF_TRISTATE1, 0xff);
+		/* invert GPIO 1 and 3 if desired*/
+		gpio_conf = state->config->gpio_config;
+		if (gpio_conf >= TDA10046_GP00_I)
+			tda1004x_write_mask(state, TDA10046H_CONF_POLARITY, 0x0f,
+							(gpio_conf & 0x0f) ^ 0x0a);
+
+		tda1004x_write_mask(state, TDA1004X_CONFADC2, 0xc0, 0xc0);
+		tda1004x_write_mask(state, TDA1004X_CONFC4, 1, 1);
+		break;
+	}
+
+	return 0;
+}
+
+static int tda1004x_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+{
+	struct tda1004x_state* state = fe->demodulator_priv;
+
+	if (enable) {
+		return tda1004x_enable_tuner_i2c(state);
+	} else {
+		return tda1004x_disable_tuner_i2c(state);
+	}
+}
+
+static int tda1004x_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings)
+{
+	fesettings->min_delay_ms = 800;
+	/* Drift compensation makes no sense for DVB-T */
+	fesettings->step_size = 0;
+	fesettings->max_drift = 0;
+	return 0;
+}
+
+static void tda1004x_release(struct dvb_frontend* fe)
+{
+	struct tda1004x_state *state = fe->demodulator_priv;
+	kfree(state);
+}
+
+static struct dvb_frontend_ops tda10045_ops = {
+	.delsys = { SYS_DVBT },
+	.info = {
+		.name = "Philips TDA10045H DVB-T",
+		.frequency_min = 51000000,
+		.frequency_max = 858000000,
+		.frequency_stepsize = 166667,
+		.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_FEC_AUTO |
+		    FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
+		    FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO
+	},
+
+	.release = tda1004x_release,
+
+	.init = tda10045_init,
+	.sleep = tda1004x_sleep,
+	.write = tda1004x_write,
+	.i2c_gate_ctrl = tda1004x_i2c_gate_ctrl,
+
+	.set_frontend = tda1004x_set_fe,
+	.get_frontend = tda1004x_get_fe,
+	.get_tune_settings = tda1004x_get_tune_settings,
+
+	.read_status = tda1004x_read_status,
+	.read_ber = tda1004x_read_ber,
+	.read_signal_strength = tda1004x_read_signal_strength,
+	.read_snr = tda1004x_read_snr,
+	.read_ucblocks = tda1004x_read_ucblocks,
+};
+
+struct dvb_frontend* tda10045_attach(const struct tda1004x_config* config,
+				     struct i2c_adapter* i2c)
+{
+	struct tda1004x_state *state;
+	int id;
+
+	/* allocate memory for the internal state */
+	state = kzalloc(sizeof(struct tda1004x_state), GFP_KERNEL);
+	if (!state) {
+		printk(KERN_ERR "Can't allocate memory for tda10045 state\n");
+		return NULL;
+	}
+
+	/* setup the state */
+	state->config = config;
+	state->i2c = i2c;
+	state->demod_type = TDA1004X_DEMOD_TDA10045;
+
+	/* check if the demod is there */
+	id = tda1004x_read_byte(state, TDA1004X_CHIPID);
+	if (id < 0) {
+		printk(KERN_ERR "tda10045: chip is not answering. Giving up.\n");
+		kfree(state);
+		return NULL;
+	}
+
+	if (id != 0x25) {
+		printk(KERN_ERR "Invalid tda1004x ID = 0x%02x. Can't proceed\n", id);
+		kfree(state);
+		return NULL;
+	}
+
+	/* create dvb_frontend */
+	memcpy(&state->frontend.ops, &tda10045_ops, sizeof(struct dvb_frontend_ops));
+	state->frontend.demodulator_priv = state;
+	return &state->frontend;
+}
+
+static struct dvb_frontend_ops tda10046_ops = {
+	.delsys = { SYS_DVBT },
+	.info = {
+		.name = "Philips TDA10046H DVB-T",
+		.frequency_min = 51000000,
+		.frequency_max = 858000000,
+		.frequency_stepsize = 166667,
+		.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_FEC_AUTO |
+		    FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
+		    FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO
+	},
+
+	.release = tda1004x_release,
+
+	.init = tda10046_init,
+	.sleep = tda1004x_sleep,
+	.write = tda1004x_write,
+	.i2c_gate_ctrl = tda1004x_i2c_gate_ctrl,
+
+	.set_frontend = tda1004x_set_fe,
+	.get_frontend = tda1004x_get_fe,
+	.get_tune_settings = tda1004x_get_tune_settings,
+
+	.read_status = tda1004x_read_status,
+	.read_ber = tda1004x_read_ber,
+	.read_signal_strength = tda1004x_read_signal_strength,
+	.read_snr = tda1004x_read_snr,
+	.read_ucblocks = tda1004x_read_ucblocks,
+};
+
+struct dvb_frontend* tda10046_attach(const struct tda1004x_config* config,
+				     struct i2c_adapter* i2c)
+{
+	struct tda1004x_state *state;
+	int id;
+
+	/* allocate memory for the internal state */
+	state = kzalloc(sizeof(struct tda1004x_state), GFP_KERNEL);
+	if (!state) {
+		printk(KERN_ERR "Can't allocate memory for tda10046 state\n");
+		return NULL;
+	}
+
+	/* setup the state */
+	state->config = config;
+	state->i2c = i2c;
+	state->demod_type = TDA1004X_DEMOD_TDA10046;
+
+	/* check if the demod is there */
+	id = tda1004x_read_byte(state, TDA1004X_CHIPID);
+	if (id < 0) {
+		printk(KERN_ERR "tda10046: chip is not answering. Giving up.\n");
+		kfree(state);
+		return NULL;
+	}
+	if (id != 0x46) {
+		printk(KERN_ERR "Invalid tda1004x ID = 0x%02x. Can't proceed\n", id);
+		kfree(state);
+		return NULL;
+	}
+
+	/* create dvb_frontend */
+	memcpy(&state->frontend.ops, &tda10046_ops, sizeof(struct dvb_frontend_ops));
+	state->frontend.demodulator_priv = state;
+	return &state->frontend;
+}
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+
+MODULE_DESCRIPTION("Philips TDA10045H & TDA10046H DVB-T Demodulator");
+MODULE_AUTHOR("Andrew de Quincey & Robert Schlabbach");
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(tda10045_attach);
+EXPORT_SYMBOL(tda10046_attach);
diff --git a/drivers/media/dvb-frontends/tda1004x.h b/drivers/media/dvb-frontends/tda1004x.h
new file mode 100644
index 0000000..4e27ffb
--- /dev/null
+++ b/drivers/media/dvb-frontends/tda1004x.h
@@ -0,0 +1,149 @@
+  /*
+     Driver for Philips tda1004xh OFDM Frontend
+
+     (c) 2004 Andrew de Quincey
+
+     This program is free software; you can redistribute it and/or modify
+     it under the terms of the 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 TDA1004X_H
+#define TDA1004X_H
+
+#include <linux/dvb/frontend.h>
+#include <linux/firmware.h>
+
+enum tda10046_xtal {
+	TDA10046_XTAL_4M,
+	TDA10046_XTAL_16M,
+};
+
+enum tda10046_agc {
+	TDA10046_AGC_DEFAULT,		/* original configuration */
+	TDA10046_AGC_IFO_AUTO_NEG,	/* IF AGC only, automatic, negtive */
+	TDA10046_AGC_IFO_AUTO_POS,	/* IF AGC only, automatic, positive */
+	TDA10046_AGC_TDA827X,		/* IF AGC only, special setup for tda827x */
+};
+
+/* Many (hybrid) boards use GPIO 1 and 3
+	GPIO1	analog - dvb switch
+	GPIO3	firmware eeprom address switch
+*/
+enum tda10046_gpio {
+	TDA10046_GPTRI  = 0x00,		/* All GPIOs tristate */
+	TDA10046_GP00   = 0x40,		/* GPIO3=0, GPIO1=0 */
+	TDA10046_GP01   = 0x42,		/* GPIO3=0, GPIO1=1 */
+	TDA10046_GP10   = 0x48,		/* GPIO3=1, GPIO1=0 */
+	TDA10046_GP11   = 0x4a,		/* GPIO3=1, GPIO1=1 */
+	TDA10046_GP00_I = 0x80,		/* GPIO3=0, GPIO1=0, invert in sleep mode*/
+	TDA10046_GP01_I = 0x82,		/* GPIO3=0, GPIO1=1, invert in sleep mode */
+	TDA10046_GP10_I = 0x88,		/* GPIO3=1, GPIO1=0, invert in sleep mode */
+	TDA10046_GP11_I = 0x8a,		/* GPIO3=1, GPIO1=1, invert in sleep mode */
+};
+
+enum tda10046_if {
+	TDA10046_FREQ_3617,		/* original config, 36,166 MHZ */
+	TDA10046_FREQ_3613,		/* 36,13 MHZ */
+	TDA10046_FREQ_045,		/* low IF, 4.0, 4.5, or 5.0 MHZ */
+	TDA10046_FREQ_052,		/* low IF, 5.1667 MHZ for tda9889 */
+};
+
+enum tda10046_tsout {
+	TDA10046_TS_PARALLEL  = 0x00,	/* parallel transport stream, default */
+	TDA10046_TS_SERIAL    = 0x01,	/* serial transport stream */
+};
+
+struct tda1004x_config
+{
+	/* the demodulator's i2c address */
+	u8 demod_address;
+
+	/* does the "inversion" need inverted? */
+	u8 invert;
+
+	/* Does the OCLK signal need inverted? */
+	u8 invert_oclk;
+
+	/* parallel or serial transport stream */
+	enum tda10046_tsout ts_mode;
+
+	/* Xtal frequency, 4 or 16MHz*/
+	enum tda10046_xtal xtal_freq;
+
+	/* IF frequency */
+	enum tda10046_if if_freq;
+
+	/* AGC configuration */
+	enum tda10046_agc agc_config;
+
+	/* setting of GPIO1 and 3 */
+	enum tda10046_gpio gpio_config;
+
+	/* slave address and configuration of the tuner */
+	u8 tuner_address;
+	u8 antenna_switch;
+
+	/* if the board uses another I2c Bridge (tda8290), its address */
+	u8 i2c_gate;
+
+	/* request firmware for device */
+	int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name);
+};
+
+enum tda1004x_demod {
+	TDA1004X_DEMOD_TDA10045,
+	TDA1004X_DEMOD_TDA10046,
+};
+
+struct tda1004x_state {
+	struct i2c_adapter* i2c;
+	const struct tda1004x_config* config;
+	struct dvb_frontend frontend;
+
+	/* private demod data */
+	enum tda1004x_demod demod_type;
+};
+
+#if defined(CONFIG_DVB_TDA1004X) || (defined(CONFIG_DVB_TDA1004X_MODULE) && defined(MODULE))
+extern struct dvb_frontend* tda10045_attach(const struct tda1004x_config* config,
+					    struct i2c_adapter* i2c);
+
+extern struct dvb_frontend* tda10046_attach(const struct tda1004x_config* config,
+					    struct i2c_adapter* i2c);
+#else
+static inline struct dvb_frontend* tda10045_attach(const struct tda1004x_config* config,
+					    struct i2c_adapter* i2c)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+static inline struct dvb_frontend* tda10046_attach(const struct tda1004x_config* config,
+					    struct i2c_adapter* i2c)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif // CONFIG_DVB_TDA1004X
+
+static inline int tda1004x_writereg(struct dvb_frontend *fe, u8 reg, u8 val) {
+	int r = 0;
+	u8 buf[] = {reg, val};
+	if (fe->ops.write)
+		r = fe->ops.write(fe, buf, 2);
+	return r;
+}
+
+#endif // TDA1004X_H
diff --git a/drivers/media/dvb-frontends/tda10071.c b/drivers/media/dvb-frontends/tda10071.c
new file mode 100644
index 0000000..a83bf68
--- /dev/null
+++ b/drivers/media/dvb-frontends/tda10071.c
@@ -0,0 +1,1285 @@
+/*
+ * NXP TDA10071 + Conexant CX24118A DVB-S/S2 demodulator + tuner driver
+ *
+ * Copyright (C) 2011 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.,
+ *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "tda10071_priv.h"
+
+static struct dvb_frontend_ops tda10071_ops;
+
+/* write multiple registers */
+static int tda10071_wr_regs(struct tda10071_priv *priv, u8 reg, u8 *val,
+	int len)
+{
+	int ret;
+	u8 buf[len+1];
+	struct i2c_msg msg[1] = {
+		{
+			.addr = priv->cfg.i2c_address,
+			.flags = 0,
+			.len = sizeof(buf),
+			.buf = buf,
+		}
+	};
+
+	buf[0] = reg;
+	memcpy(&buf[1], val, len);
+
+	ret = i2c_transfer(priv->i2c, msg, 1);
+	if (ret == 1) {
+		ret = 0;
+	} else {
+		dev_warn(&priv->i2c->dev, "%s: i2c wr failed=%d reg=%02x " \
+				"len=%d\n", KBUILD_MODNAME, ret, reg, len);
+		ret = -EREMOTEIO;
+	}
+	return ret;
+}
+
+/* read multiple registers */
+static int tda10071_rd_regs(struct tda10071_priv *priv, u8 reg, u8 *val,
+	int len)
+{
+	int ret;
+	u8 buf[len];
+	struct i2c_msg msg[2] = {
+		{
+			.addr = priv->cfg.i2c_address,
+			.flags = 0,
+			.len = 1,
+			.buf = &reg,
+		}, {
+			.addr = priv->cfg.i2c_address,
+			.flags = I2C_M_RD,
+			.len = sizeof(buf),
+			.buf = buf,
+		}
+	};
+
+	ret = i2c_transfer(priv->i2c, msg, 2);
+	if (ret == 2) {
+		memcpy(val, buf, len);
+		ret = 0;
+	} else {
+		dev_warn(&priv->i2c->dev, "%s: i2c rd failed=%d reg=%02x " \
+				"len=%d\n", KBUILD_MODNAME, ret, reg, len);
+		ret = -EREMOTEIO;
+	}
+	return ret;
+}
+
+/* write single register */
+static int tda10071_wr_reg(struct tda10071_priv *priv, u8 reg, u8 val)
+{
+	return tda10071_wr_regs(priv, reg, &val, 1);
+}
+
+/* read single register */
+static int tda10071_rd_reg(struct tda10071_priv *priv, u8 reg, u8 *val)
+{
+	return tda10071_rd_regs(priv, reg, val, 1);
+}
+
+/* write single register with mask */
+int tda10071_wr_reg_mask(struct tda10071_priv *priv, u8 reg, u8 val, u8 mask)
+{
+	int ret;
+	u8 tmp;
+
+	/* no need for read if whole reg is written */
+	if (mask != 0xff) {
+		ret = tda10071_rd_regs(priv, reg, &tmp, 1);
+		if (ret)
+			return ret;
+
+		val &= mask;
+		tmp &= ~mask;
+		val |= tmp;
+	}
+
+	return tda10071_wr_regs(priv, reg, &val, 1);
+}
+
+/* read single register with mask */
+int tda10071_rd_reg_mask(struct tda10071_priv *priv, u8 reg, u8 *val, u8 mask)
+{
+	int ret, i;
+	u8 tmp;
+
+	ret = tda10071_rd_regs(priv, reg, &tmp, 1);
+	if (ret)
+		return ret;
+
+	tmp &= mask;
+
+	/* find position of the first bit */
+	for (i = 0; i < 8; i++) {
+		if ((mask >> i) & 0x01)
+			break;
+	}
+	*val = tmp >> i;
+
+	return 0;
+}
+
+/* execute firmware command */
+static int tda10071_cmd_execute(struct tda10071_priv *priv,
+	struct tda10071_cmd *cmd)
+{
+	int ret, i;
+	u8 tmp;
+
+	if (!priv->warm) {
+		ret = -EFAULT;
+		goto error;
+	}
+
+	/* write cmd and args for firmware */
+	ret = tda10071_wr_regs(priv, 0x00, cmd->args, cmd->len);
+	if (ret)
+		goto error;
+
+	/* start cmd execution */
+	ret = tda10071_wr_reg(priv, 0x1f, 1);
+	if (ret)
+		goto error;
+
+	/* wait cmd execution terminate */
+	for (i = 1000, tmp = 1; i && tmp; i--) {
+		ret = tda10071_rd_reg(priv, 0x1f, &tmp);
+		if (ret)
+			goto error;
+
+		usleep_range(200, 5000);
+	}
+
+	dev_dbg(&priv->i2c->dev, "%s: loop=%d\n", __func__, i);
+
+	if (i == 0) {
+		ret = -ETIMEDOUT;
+		goto error;
+	}
+
+	return ret;
+error:
+	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	return ret;
+}
+
+static int tda10071_set_tone(struct dvb_frontend *fe,
+	fe_sec_tone_mode_t fe_sec_tone_mode)
+{
+	struct tda10071_priv *priv = fe->demodulator_priv;
+	struct tda10071_cmd cmd;
+	int ret;
+	u8 tone;
+
+	if (!priv->warm) {
+		ret = -EFAULT;
+		goto error;
+	}
+
+	dev_dbg(&priv->i2c->dev, "%s: tone_mode=%d\n", __func__,
+			fe_sec_tone_mode);
+
+	switch (fe_sec_tone_mode) {
+	case SEC_TONE_ON:
+		tone = 1;
+		break;
+	case SEC_TONE_OFF:
+		tone = 0;
+		break;
+	default:
+		dev_dbg(&priv->i2c->dev, "%s: invalid fe_sec_tone_mode\n",
+				__func__);
+		ret = -EINVAL;
+		goto error;
+	}
+
+	cmd.args[0] = CMD_LNB_PCB_CONFIG;
+	cmd.args[1] = 0;
+	cmd.args[2] = 0x00;
+	cmd.args[3] = 0x00;
+	cmd.args[4] = tone;
+	cmd.len = 5;
+	ret = tda10071_cmd_execute(priv, &cmd);
+	if (ret)
+		goto error;
+
+	return ret;
+error:
+	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	return ret;
+}
+
+static int tda10071_set_voltage(struct dvb_frontend *fe,
+	fe_sec_voltage_t fe_sec_voltage)
+{
+	struct tda10071_priv *priv = fe->demodulator_priv;
+	struct tda10071_cmd cmd;
+	int ret;
+	u8 voltage;
+
+	if (!priv->warm) {
+		ret = -EFAULT;
+		goto error;
+	}
+
+	dev_dbg(&priv->i2c->dev, "%s: voltage=%d\n", __func__, fe_sec_voltage);
+
+	switch (fe_sec_voltage) {
+	case SEC_VOLTAGE_13:
+		voltage = 0;
+		break;
+	case SEC_VOLTAGE_18:
+		voltage = 1;
+		break;
+	case SEC_VOLTAGE_OFF:
+		voltage = 0;
+		break;
+	default:
+		dev_dbg(&priv->i2c->dev, "%s: invalid fe_sec_voltage\n",
+				__func__);
+		ret = -EINVAL;
+		goto error;
+	}
+
+	cmd.args[0] = CMD_LNB_SET_DC_LEVEL;
+	cmd.args[1] = 0;
+	cmd.args[2] = voltage;
+	cmd.len = 3;
+	ret = tda10071_cmd_execute(priv, &cmd);
+	if (ret)
+		goto error;
+
+	return ret;
+error:
+	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	return ret;
+}
+
+static int tda10071_diseqc_send_master_cmd(struct dvb_frontend *fe,
+	struct dvb_diseqc_master_cmd *diseqc_cmd)
+{
+	struct tda10071_priv *priv = fe->demodulator_priv;
+	struct tda10071_cmd cmd;
+	int ret, i;
+	u8 tmp;
+
+	if (!priv->warm) {
+		ret = -EFAULT;
+		goto error;
+	}
+
+	dev_dbg(&priv->i2c->dev, "%s: msg_len=%d\n", __func__,
+			diseqc_cmd->msg_len);
+
+	if (diseqc_cmd->msg_len < 3 || diseqc_cmd->msg_len > 6) {
+		ret = -EINVAL;
+		goto error;
+	}
+
+	/* wait LNB TX */
+	for (i = 500, tmp = 0; i && !tmp; i--) {
+		ret = tda10071_rd_reg_mask(priv, 0x47, &tmp, 0x01);
+		if (ret)
+			goto error;
+
+		usleep_range(10000, 20000);
+	}
+
+	dev_dbg(&priv->i2c->dev, "%s: loop=%d\n", __func__, i);
+
+	if (i == 0) {
+		ret = -ETIMEDOUT;
+		goto error;
+	}
+
+	ret = tda10071_wr_reg_mask(priv, 0x47, 0x00, 0x01);
+	if (ret)
+		goto error;
+
+	cmd.args[0] = CMD_LNB_SEND_DISEQC;
+	cmd.args[1] = 0;
+	cmd.args[2] = 0;
+	cmd.args[3] = 0;
+	cmd.args[4] = 2;
+	cmd.args[5] = 0;
+	cmd.args[6] = diseqc_cmd->msg_len;
+	memcpy(&cmd.args[7], diseqc_cmd->msg, diseqc_cmd->msg_len);
+	cmd.len = 7 + diseqc_cmd->msg_len;
+	ret = tda10071_cmd_execute(priv, &cmd);
+	if (ret)
+		goto error;
+
+	return ret;
+error:
+	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	return ret;
+}
+
+static int tda10071_diseqc_recv_slave_reply(struct dvb_frontend *fe,
+	struct dvb_diseqc_slave_reply *reply)
+{
+	struct tda10071_priv *priv = fe->demodulator_priv;
+	struct tda10071_cmd cmd;
+	int ret, i;
+	u8 tmp;
+
+	if (!priv->warm) {
+		ret = -EFAULT;
+		goto error;
+	}
+
+	dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
+
+	/* wait LNB RX */
+	for (i = 500, tmp = 0; i && !tmp; i--) {
+		ret = tda10071_rd_reg_mask(priv, 0x47, &tmp, 0x02);
+		if (ret)
+			goto error;
+
+		usleep_range(10000, 20000);
+	}
+
+	dev_dbg(&priv->i2c->dev, "%s: loop=%d\n", __func__, i);
+
+	if (i == 0) {
+		ret = -ETIMEDOUT;
+		goto error;
+	}
+
+	/* reply len */
+	ret = tda10071_rd_reg(priv, 0x46, &tmp);
+	if (ret)
+		goto error;
+
+	reply->msg_len = tmp & 0x1f; /* [4:0] */
+	if (reply->msg_len > sizeof(reply->msg))
+		reply->msg_len = sizeof(reply->msg); /* truncate API max */
+
+	/* read reply */
+	cmd.args[0] = CMD_LNB_UPDATE_REPLY;
+	cmd.args[1] = 0;
+	cmd.len = 2;
+	ret = tda10071_cmd_execute(priv, &cmd);
+	if (ret)
+		goto error;
+
+	ret = tda10071_rd_regs(priv, cmd.len, reply->msg, reply->msg_len);
+	if (ret)
+		goto error;
+
+	return ret;
+error:
+	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	return ret;
+}
+
+static int tda10071_diseqc_send_burst(struct dvb_frontend *fe,
+	fe_sec_mini_cmd_t fe_sec_mini_cmd)
+{
+	struct tda10071_priv *priv = fe->demodulator_priv;
+	struct tda10071_cmd cmd;
+	int ret, i;
+	u8 tmp, burst;
+
+	if (!priv->warm) {
+		ret = -EFAULT;
+		goto error;
+	}
+
+	dev_dbg(&priv->i2c->dev, "%s: fe_sec_mini_cmd=%d\n", __func__,
+			fe_sec_mini_cmd);
+
+	switch (fe_sec_mini_cmd) {
+	case SEC_MINI_A:
+		burst = 0;
+		break;
+	case SEC_MINI_B:
+		burst = 1;
+		break;
+	default:
+		dev_dbg(&priv->i2c->dev, "%s: invalid fe_sec_mini_cmd\n",
+				__func__);
+		ret = -EINVAL;
+		goto error;
+	}
+
+	/* wait LNB TX */
+	for (i = 500, tmp = 0; i && !tmp; i--) {
+		ret = tda10071_rd_reg_mask(priv, 0x47, &tmp, 0x01);
+		if (ret)
+			goto error;
+
+		usleep_range(10000, 20000);
+	}
+
+	dev_dbg(&priv->i2c->dev, "%s: loop=%d\n", __func__, i);
+
+	if (i == 0) {
+		ret = -ETIMEDOUT;
+		goto error;
+	}
+
+	ret = tda10071_wr_reg_mask(priv, 0x47, 0x00, 0x01);
+	if (ret)
+		goto error;
+
+	cmd.args[0] = CMD_LNB_SEND_TONEBURST;
+	cmd.args[1] = 0;
+	cmd.args[2] = burst;
+	cmd.len = 3;
+	ret = tda10071_cmd_execute(priv, &cmd);
+	if (ret)
+		goto error;
+
+	return ret;
+error:
+	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	return ret;
+}
+
+static int tda10071_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+	struct tda10071_priv *priv = fe->demodulator_priv;
+	int ret;
+	u8 tmp;
+
+	*status = 0;
+
+	if (!priv->warm) {
+		ret = 0;
+		goto error;
+	}
+
+	ret = tda10071_rd_reg(priv, 0x39, &tmp);
+	if (ret)
+		goto error;
+
+	if (tmp & 0x01) /* tuner PLL */
+		*status |= FE_HAS_SIGNAL;
+	if (tmp & 0x02) /* demod PLL */
+		*status |= FE_HAS_CARRIER;
+	if (tmp & 0x04) /* viterbi or LDPC*/
+		*status |= FE_HAS_VITERBI;
+	if (tmp & 0x08) /* RS or BCH */
+		*status |= FE_HAS_SYNC | FE_HAS_LOCK;
+
+	priv->fe_status = *status;
+
+	return ret;
+error:
+	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	return ret;
+}
+
+static int tda10071_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+	struct tda10071_priv *priv = fe->demodulator_priv;
+	int ret;
+	u8 buf[2];
+
+	if (!priv->warm || !(priv->fe_status & FE_HAS_LOCK)) {
+		*snr = 0;
+		ret = 0;
+		goto error;
+	}
+
+	ret = tda10071_rd_regs(priv, 0x3a, buf, 2);
+	if (ret)
+		goto error;
+
+	/* Es/No dBx10 */
+	*snr = buf[0] << 8 | buf[1];
+
+	return ret;
+error:
+	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	return ret;
+}
+
+static int tda10071_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
+{
+	struct tda10071_priv *priv = fe->demodulator_priv;
+	struct tda10071_cmd cmd;
+	int ret;
+	u8 tmp;
+
+	if (!priv->warm || !(priv->fe_status & FE_HAS_LOCK)) {
+		*strength = 0;
+		ret = 0;
+		goto error;
+	}
+
+	cmd.args[0] = CMD_GET_AGCACC;
+	cmd.args[1] = 0;
+	cmd.len = 2;
+	ret = tda10071_cmd_execute(priv, &cmd);
+	if (ret)
+		goto error;
+
+	/* input power estimate dBm */
+	ret = tda10071_rd_reg(priv, 0x50, &tmp);
+	if (ret)
+		goto error;
+
+	if (tmp < 181)
+		tmp = 181; /* -75 dBm */
+	else if (tmp > 236)
+		tmp = 236; /* -20 dBm */
+
+	/* scale value to 0x0000-0xffff */
+	*strength = (tmp-181) * 0xffff / (236-181);
+
+	return ret;
+error:
+	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	return ret;
+}
+
+static int tda10071_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+	struct tda10071_priv *priv = fe->demodulator_priv;
+	struct tda10071_cmd cmd;
+	int ret, i, len;
+	u8 tmp, reg, buf[8];
+
+	if (!priv->warm || !(priv->fe_status & FE_HAS_LOCK)) {
+		*ber = priv->ber = 0;
+		ret = 0;
+		goto error;
+	}
+
+	switch (priv->delivery_system) {
+	case SYS_DVBS:
+		reg = 0x4c;
+		len = 8;
+		i = 1;
+		break;
+	case SYS_DVBS2:
+		reg = 0x4d;
+		len = 4;
+		i = 0;
+		break;
+	default:
+		*ber = priv->ber = 0;
+		return 0;
+	}
+
+	ret = tda10071_rd_reg(priv, reg, &tmp);
+	if (ret)
+		goto error;
+
+	if (priv->meas_count[i] == tmp) {
+		dev_dbg(&priv->i2c->dev, "%s: meas not ready=%02x\n", __func__,
+				tmp);
+		*ber = priv->ber;
+		return 0;
+	} else {
+		priv->meas_count[i] = tmp;
+	}
+
+	cmd.args[0] = CMD_BER_UPDATE_COUNTERS;
+	cmd.args[1] = 0;
+	cmd.args[2] = i;
+	cmd.len = 3;
+	ret = tda10071_cmd_execute(priv, &cmd);
+	if (ret)
+		goto error;
+
+	ret = tda10071_rd_regs(priv, cmd.len, buf, len);
+	if (ret)
+		goto error;
+
+	if (priv->delivery_system == SYS_DVBS) {
+		*ber = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
+		priv->ucb += (buf[4] << 8) | buf[5];
+	} else {
+		*ber = (buf[0] << 8) | buf[1];
+	}
+	priv->ber = *ber;
+
+	return ret;
+error:
+	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	return ret;
+}
+
+static int tda10071_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+	struct tda10071_priv *priv = fe->demodulator_priv;
+	int ret = 0;
+
+	if (!priv->warm || !(priv->fe_status & FE_HAS_LOCK)) {
+		*ucblocks = 0;
+		goto error;
+	}
+
+	/* UCB is updated when BER is read. Assume BER is read anyway. */
+
+	*ucblocks = priv->ucb;
+
+	return ret;
+error:
+	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	return ret;
+}
+
+static int tda10071_set_frontend(struct dvb_frontend *fe)
+{
+	struct tda10071_priv *priv = fe->demodulator_priv;
+	struct tda10071_cmd cmd;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	int ret, i;
+	u8 mode, rolloff, pilot, inversion, div;
+
+	dev_dbg(&priv->i2c->dev, "%s: delivery_system=%d modulation=%d " \
+		"frequency=%d symbol_rate=%d inversion=%d pilot=%d " \
+		"rolloff=%d\n", __func__, c->delivery_system, c->modulation,
+		c->frequency, c->symbol_rate, c->inversion, c->pilot,
+		c->rolloff);
+
+	priv->delivery_system = SYS_UNDEFINED;
+
+	if (!priv->warm) {
+		ret = -EFAULT;
+		goto error;
+	}
+
+	switch (c->inversion) {
+	case INVERSION_OFF:
+		inversion = 1;
+		break;
+	case INVERSION_ON:
+		inversion = 0;
+		break;
+	case INVERSION_AUTO:
+		/* 2 = auto; try first on then off
+		 * 3 = auto; try first off then on */
+		inversion = 3;
+		break;
+	default:
+		dev_dbg(&priv->i2c->dev, "%s: invalid inversion\n", __func__);
+		ret = -EINVAL;
+		goto error;
+	}
+
+	switch (c->delivery_system) {
+	case SYS_DVBS:
+		rolloff = 0;
+		pilot = 2;
+		break;
+	case SYS_DVBS2:
+		switch (c->rolloff) {
+		case ROLLOFF_20:
+			rolloff = 2;
+			break;
+		case ROLLOFF_25:
+			rolloff = 1;
+			break;
+		case ROLLOFF_35:
+			rolloff = 0;
+			break;
+		case ROLLOFF_AUTO:
+		default:
+			dev_dbg(&priv->i2c->dev, "%s: invalid rolloff\n",
+					__func__);
+			ret = -EINVAL;
+			goto error;
+		}
+
+		switch (c->pilot) {
+		case PILOT_OFF:
+			pilot = 0;
+			break;
+		case PILOT_ON:
+			pilot = 1;
+			break;
+		case PILOT_AUTO:
+			pilot = 2;
+			break;
+		default:
+			dev_dbg(&priv->i2c->dev, "%s: invalid pilot\n",
+					__func__);
+			ret = -EINVAL;
+			goto error;
+		}
+		break;
+	default:
+		dev_dbg(&priv->i2c->dev, "%s: invalid delivery_system\n",
+				__func__);
+		ret = -EINVAL;
+		goto error;
+	}
+
+	for (i = 0, mode = 0xff; i < ARRAY_SIZE(TDA10071_MODCOD); i++) {
+		if (c->delivery_system == TDA10071_MODCOD[i].delivery_system &&
+			c->modulation == TDA10071_MODCOD[i].modulation &&
+			c->fec_inner == TDA10071_MODCOD[i].fec) {
+			mode = TDA10071_MODCOD[i].val;
+			dev_dbg(&priv->i2c->dev, "%s: mode found=%02x\n",
+					__func__, mode);
+			break;
+		}
+	}
+
+	if (mode == 0xff) {
+		dev_dbg(&priv->i2c->dev, "%s: invalid parameter combination\n",
+				__func__);
+		ret = -EINVAL;
+		goto error;
+	}
+
+	if (c->symbol_rate <= 5000000)
+		div = 14;
+	else
+		div = 4;
+
+	ret = tda10071_wr_reg(priv, 0x81, div);
+	if (ret)
+		goto error;
+
+	ret = tda10071_wr_reg(priv, 0xe3, div);
+	if (ret)
+		goto error;
+
+	cmd.args[0] = CMD_CHANGE_CHANNEL;
+	cmd.args[1] = 0;
+	cmd.args[2] = mode;
+	cmd.args[3] = (c->frequency >> 16) & 0xff;
+	cmd.args[4] = (c->frequency >>  8) & 0xff;
+	cmd.args[5] = (c->frequency >>  0) & 0xff;
+	cmd.args[6] = ((c->symbol_rate / 1000) >> 8) & 0xff;
+	cmd.args[7] = ((c->symbol_rate / 1000) >> 0) & 0xff;
+	cmd.args[8] = (tda10071_ops.info.frequency_tolerance >> 8) & 0xff;
+	cmd.args[9] = (tda10071_ops.info.frequency_tolerance >> 0) & 0xff;
+	cmd.args[10] = rolloff;
+	cmd.args[11] = inversion;
+	cmd.args[12] = pilot;
+	cmd.args[13] = 0x00;
+	cmd.args[14] = 0x00;
+	cmd.len = 15;
+	ret = tda10071_cmd_execute(priv, &cmd);
+	if (ret)
+		goto error;
+
+	priv->delivery_system = c->delivery_system;
+
+	return ret;
+error:
+	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	return ret;
+}
+
+static int tda10071_get_frontend(struct dvb_frontend *fe)
+{
+	struct tda10071_priv *priv = fe->demodulator_priv;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	int ret, i;
+	u8 buf[5], tmp;
+
+	if (!priv->warm || !(priv->fe_status & FE_HAS_LOCK)) {
+		ret = -EFAULT;
+		goto error;
+	}
+
+	ret = tda10071_rd_regs(priv, 0x30, buf, 5);
+	if (ret)
+		goto error;
+
+	tmp = buf[0] & 0x3f;
+	for (i = 0; i < ARRAY_SIZE(TDA10071_MODCOD); i++) {
+		if (tmp == TDA10071_MODCOD[i].val) {
+			c->modulation = TDA10071_MODCOD[i].modulation;
+			c->fec_inner = TDA10071_MODCOD[i].fec;
+			c->delivery_system = TDA10071_MODCOD[i].delivery_system;
+		}
+	}
+
+	switch ((buf[1] >> 0) & 0x01) {
+	case 0:
+		c->inversion = INVERSION_OFF;
+		break;
+	case 1:
+		c->inversion = INVERSION_ON;
+		break;
+	}
+
+	switch ((buf[1] >> 7) & 0x01) {
+	case 0:
+		c->pilot = PILOT_OFF;
+		break;
+	case 1:
+		c->pilot = PILOT_ON;
+		break;
+	}
+
+	c->frequency = (buf[2] << 16) | (buf[3] << 8) | (buf[4] << 0);
+
+	ret = tda10071_rd_regs(priv, 0x52, buf, 3);
+	if (ret)
+		goto error;
+
+	c->symbol_rate = (buf[0] << 16) | (buf[1] << 8) | (buf[2] << 0);
+
+	return ret;
+error:
+	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	return ret;
+}
+
+static int tda10071_init(struct dvb_frontend *fe)
+{
+	struct tda10071_priv *priv = fe->demodulator_priv;
+	struct tda10071_cmd cmd;
+	int ret, i, len, remaining, fw_size;
+	const struct firmware *fw;
+	u8 *fw_file = TDA10071_FIRMWARE;
+	u8 tmp, buf[4];
+	struct tda10071_reg_val_mask tab[] = {
+		{ 0xcd, 0x00, 0x07 },
+		{ 0x80, 0x00, 0x02 },
+		{ 0xcd, 0x00, 0xc0 },
+		{ 0xce, 0x00, 0x1b },
+		{ 0x9d, 0x00, 0x01 },
+		{ 0x9d, 0x00, 0x02 },
+		{ 0x9e, 0x00, 0x01 },
+		{ 0x87, 0x00, 0x80 },
+		{ 0xce, 0x00, 0x08 },
+		{ 0xce, 0x00, 0x10 },
+	};
+	struct tda10071_reg_val_mask tab2[] = {
+		{ 0xf1, 0x70, 0xff },
+		{ 0x88, priv->cfg.pll_multiplier, 0x3f },
+		{ 0x89, 0x00, 0x10 },
+		{ 0x89, 0x10, 0x10 },
+		{ 0xc0, 0x01, 0x01 },
+		{ 0xc0, 0x00, 0x01 },
+		{ 0xe0, 0xff, 0xff },
+		{ 0xe0, 0x00, 0xff },
+		{ 0x96, 0x1e, 0x7e },
+		{ 0x8b, 0x08, 0x08 },
+		{ 0x8b, 0x00, 0x08 },
+		{ 0x8f, 0x1a, 0x7e },
+		{ 0x8c, 0x68, 0xff },
+		{ 0x8d, 0x08, 0xff },
+		{ 0x8e, 0x4c, 0xff },
+		{ 0x8f, 0x01, 0x01 },
+		{ 0x8b, 0x04, 0x04 },
+		{ 0x8b, 0x00, 0x04 },
+		{ 0x87, 0x05, 0x07 },
+		{ 0x80, 0x00, 0x20 },
+		{ 0xc8, 0x01, 0xff },
+		{ 0xb4, 0x47, 0xff },
+		{ 0xb5, 0x9c, 0xff },
+		{ 0xb6, 0x7d, 0xff },
+		{ 0xba, 0x00, 0x03 },
+		{ 0xb7, 0x47, 0xff },
+		{ 0xb8, 0x9c, 0xff },
+		{ 0xb9, 0x7d, 0xff },
+		{ 0xba, 0x00, 0x0c },
+		{ 0xc8, 0x00, 0xff },
+		{ 0xcd, 0x00, 0x04 },
+		{ 0xcd, 0x00, 0x20 },
+		{ 0xe8, 0x02, 0xff },
+		{ 0xcf, 0x20, 0xff },
+		{ 0x9b, 0xd7, 0xff },
+		{ 0x9a, 0x01, 0x03 },
+		{ 0xa8, 0x05, 0x0f },
+		{ 0xa8, 0x65, 0xf0 },
+		{ 0xa6, 0xa0, 0xf0 },
+		{ 0x9d, 0x50, 0xfc },
+		{ 0x9e, 0x20, 0xe0 },
+		{ 0xa3, 0x1c, 0x7c },
+		{ 0xd5, 0x03, 0x03 },
+	};
+
+	/* firmware status */
+	ret = tda10071_rd_reg(priv, 0x51, &tmp);
+	if (ret)
+		goto error;
+
+	if (!tmp) {
+		/* warm state - wake up device from sleep */
+		priv->warm = 1;
+
+		for (i = 0; i < ARRAY_SIZE(tab); i++) {
+			ret = tda10071_wr_reg_mask(priv, tab[i].reg,
+				tab[i].val, tab[i].mask);
+			if (ret)
+				goto error;
+		}
+
+		cmd.args[0] = CMD_SET_SLEEP_MODE;
+		cmd.args[1] = 0;
+		cmd.args[2] = 0;
+		cmd.len = 3;
+		ret = tda10071_cmd_execute(priv, &cmd);
+		if (ret)
+			goto error;
+	} else {
+		/* cold state - try to download firmware */
+		priv->warm = 0;
+
+		/* request the firmware, this will block and timeout */
+		ret = request_firmware(&fw, fw_file, priv->i2c->dev.parent);
+		if (ret) {
+			dev_err(&priv->i2c->dev, "%s: did not find the " \
+					"firmware file. (%s) Please see " \
+					"linux/Documentation/dvb/ for more " \
+					"details on firmware-problems. (%d)\n",
+					KBUILD_MODNAME, fw_file, ret);
+			goto error;
+		}
+
+		/* init */
+		for (i = 0; i < ARRAY_SIZE(tab2); i++) {
+			ret = tda10071_wr_reg_mask(priv, tab2[i].reg,
+				tab2[i].val, tab2[i].mask);
+			if (ret)
+				goto error_release_firmware;
+		}
+
+		/*  download firmware */
+		ret = tda10071_wr_reg(priv, 0xe0, 0x7f);
+		if (ret)
+			goto error_release_firmware;
+
+		ret = tda10071_wr_reg(priv, 0xf7, 0x81);
+		if (ret)
+			goto error_release_firmware;
+
+		ret = tda10071_wr_reg(priv, 0xf8, 0x00);
+		if (ret)
+			goto error_release_firmware;
+
+		ret = tda10071_wr_reg(priv, 0xf9, 0x00);
+		if (ret)
+			goto error_release_firmware;
+
+		dev_info(&priv->i2c->dev, "%s: found a '%s' in cold state, " \
+				"will try to load a firmware\n", KBUILD_MODNAME,
+				tda10071_ops.info.name);
+		dev_info(&priv->i2c->dev, "%s: downloading firmware from " \
+				"file '%s'\n", KBUILD_MODNAME, fw_file);
+
+		/* do not download last byte */
+		fw_size = fw->size - 1;
+
+		for (remaining = fw_size; remaining > 0;
+			remaining -= (priv->cfg.i2c_wr_max - 1)) {
+			len = remaining;
+			if (len > (priv->cfg.i2c_wr_max - 1))
+				len = (priv->cfg.i2c_wr_max - 1);
+
+			ret = tda10071_wr_regs(priv, 0xfa,
+				(u8 *) &fw->data[fw_size - remaining], len);
+			if (ret) {
+				dev_err(&priv->i2c->dev, "%s: firmware " \
+						"download failed=%d\n",
+						KBUILD_MODNAME, ret);
+				if (ret)
+					goto error_release_firmware;
+			}
+		}
+		release_firmware(fw);
+
+		ret = tda10071_wr_reg(priv, 0xf7, 0x0c);
+		if (ret)
+			goto error;
+
+		ret = tda10071_wr_reg(priv, 0xe0, 0x00);
+		if (ret)
+			goto error;
+
+		/* wait firmware start */
+		msleep(250);
+
+		/* firmware status */
+		ret = tda10071_rd_reg(priv, 0x51, &tmp);
+		if (ret)
+			goto error;
+
+		if (tmp) {
+			dev_info(&priv->i2c->dev, "%s: firmware did not run\n",
+					KBUILD_MODNAME);
+			ret = -EFAULT;
+			goto error;
+		} else {
+			priv->warm = 1;
+		}
+
+		cmd.args[0] = CMD_GET_FW_VERSION;
+		cmd.len = 1;
+		ret = tda10071_cmd_execute(priv, &cmd);
+		if (ret)
+			goto error;
+
+		ret = tda10071_rd_regs(priv, cmd.len, buf, 4);
+		if (ret)
+			goto error;
+
+		dev_info(&priv->i2c->dev, "%s: firmware version %d.%d.%d.%d\n",
+				KBUILD_MODNAME, buf[0], buf[1], buf[2], buf[3]);
+		dev_info(&priv->i2c->dev, "%s: found a '%s' in warm state\n",
+				KBUILD_MODNAME, tda10071_ops.info.name);
+
+		ret = tda10071_rd_regs(priv, 0x81, buf, 2);
+		if (ret)
+			goto error;
+
+		cmd.args[0] = CMD_DEMOD_INIT;
+		cmd.args[1] = ((priv->cfg.xtal / 1000) >> 8) & 0xff;
+		cmd.args[2] = ((priv->cfg.xtal / 1000) >> 0) & 0xff;
+		cmd.args[3] = buf[0];
+		cmd.args[4] = buf[1];
+		cmd.args[5] = priv->cfg.pll_multiplier;
+		cmd.args[6] = priv->cfg.spec_inv;
+		cmd.args[7] = 0x00;
+		cmd.len = 8;
+		ret = tda10071_cmd_execute(priv, &cmd);
+		if (ret)
+			goto error;
+
+		cmd.args[0] = CMD_TUNER_INIT;
+		cmd.args[1] = 0x00;
+		cmd.args[2] = 0x00;
+		cmd.args[3] = 0x00;
+		cmd.args[4] = 0x00;
+		cmd.args[5] = 0x14;
+		cmd.args[6] = 0x00;
+		cmd.args[7] = 0x03;
+		cmd.args[8] = 0x02;
+		cmd.args[9] = 0x02;
+		cmd.args[10] = 0x00;
+		cmd.args[11] = 0x00;
+		cmd.args[12] = 0x00;
+		cmd.args[13] = 0x00;
+		cmd.args[14] = 0x00;
+		cmd.len = 15;
+		ret = tda10071_cmd_execute(priv, &cmd);
+		if (ret)
+			goto error;
+
+		cmd.args[0] = CMD_MPEG_CONFIG;
+		cmd.args[1] = 0;
+		cmd.args[2] = priv->cfg.ts_mode;
+		cmd.args[3] = 0x00;
+		cmd.args[4] = 0x04;
+		cmd.args[5] = 0x00;
+		cmd.len = 6;
+		ret = tda10071_cmd_execute(priv, &cmd);
+		if (ret)
+			goto error;
+
+		ret = tda10071_wr_reg_mask(priv, 0xf0, 0x01, 0x01);
+		if (ret)
+			goto error;
+
+		cmd.args[0] = CMD_LNB_CONFIG;
+		cmd.args[1] = 0;
+		cmd.args[2] = 150;
+		cmd.args[3] = 3;
+		cmd.args[4] = 22;
+		cmd.args[5] = 1;
+		cmd.args[6] = 1;
+		cmd.args[7] = 30;
+		cmd.args[8] = 30;
+		cmd.args[9] = 30;
+		cmd.args[10] = 30;
+		cmd.len = 11;
+		ret = tda10071_cmd_execute(priv, &cmd);
+		if (ret)
+			goto error;
+
+		cmd.args[0] = CMD_BER_CONTROL;
+		cmd.args[1] = 0;
+		cmd.args[2] = 14;
+		cmd.args[3] = 14;
+		cmd.len = 4;
+		ret = tda10071_cmd_execute(priv, &cmd);
+		if (ret)
+			goto error;
+	}
+
+	return ret;
+error_release_firmware:
+	release_firmware(fw);
+error:
+	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	return ret;
+}
+
+static int tda10071_sleep(struct dvb_frontend *fe)
+{
+	struct tda10071_priv *priv = fe->demodulator_priv;
+	struct tda10071_cmd cmd;
+	int ret, i;
+	struct tda10071_reg_val_mask tab[] = {
+		{ 0xcd, 0x07, 0x07 },
+		{ 0x80, 0x02, 0x02 },
+		{ 0xcd, 0xc0, 0xc0 },
+		{ 0xce, 0x1b, 0x1b },
+		{ 0x9d, 0x01, 0x01 },
+		{ 0x9d, 0x02, 0x02 },
+		{ 0x9e, 0x01, 0x01 },
+		{ 0x87, 0x80, 0x80 },
+		{ 0xce, 0x08, 0x08 },
+		{ 0xce, 0x10, 0x10 },
+	};
+
+	if (!priv->warm) {
+		ret = -EFAULT;
+		goto error;
+	}
+
+	cmd.args[0] = CMD_SET_SLEEP_MODE;
+	cmd.args[1] = 0;
+	cmd.args[2] = 1;
+	cmd.len = 3;
+	ret = tda10071_cmd_execute(priv, &cmd);
+	if (ret)
+		goto error;
+
+	for (i = 0; i < ARRAY_SIZE(tab); i++) {
+		ret = tda10071_wr_reg_mask(priv, tab[i].reg, tab[i].val,
+			tab[i].mask);
+		if (ret)
+			goto error;
+	}
+
+	return ret;
+error:
+	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+	return ret;
+}
+
+static int tda10071_get_tune_settings(struct dvb_frontend *fe,
+	struct dvb_frontend_tune_settings *s)
+{
+	s->min_delay_ms = 8000;
+	s->step_size = 0;
+	s->max_drift = 0;
+
+	return 0;
+}
+
+static void tda10071_release(struct dvb_frontend *fe)
+{
+	struct tda10071_priv *priv = fe->demodulator_priv;
+	kfree(priv);
+}
+
+struct dvb_frontend *tda10071_attach(const struct tda10071_config *config,
+	struct i2c_adapter *i2c)
+{
+	int ret;
+	struct tda10071_priv *priv = NULL;
+	u8 tmp;
+
+	/* allocate memory for the internal priv */
+	priv = kzalloc(sizeof(struct tda10071_priv), GFP_KERNEL);
+	if (priv == NULL) {
+		ret = -ENOMEM;
+		goto error;
+	}
+
+	/* setup the priv */
+	priv->i2c = i2c;
+	memcpy(&priv->cfg, config, sizeof(struct tda10071_config));
+
+	/* chip ID */
+	ret = tda10071_rd_reg(priv, 0xff, &tmp);
+	if (ret || tmp != 0x0f)
+		goto error;
+
+	/* chip type */
+	ret = tda10071_rd_reg(priv, 0xdd, &tmp);
+	if (ret || tmp != 0x00)
+		goto error;
+
+	/* chip version */
+	ret = tda10071_rd_reg(priv, 0xfe, &tmp);
+	if (ret || tmp != 0x01)
+		goto error;
+
+	/* create dvb_frontend */
+	memcpy(&priv->fe.ops, &tda10071_ops, sizeof(struct dvb_frontend_ops));
+	priv->fe.demodulator_priv = priv;
+
+	return &priv->fe;
+error:
+	dev_dbg(&i2c->dev, "%s: failed=%d\n", __func__, ret);
+	kfree(priv);
+	return NULL;
+}
+EXPORT_SYMBOL(tda10071_attach);
+
+static struct dvb_frontend_ops tda10071_ops = {
+	.delsys = { SYS_DVBS, SYS_DVBS2 },
+	.info = {
+		.name = "NXP TDA10071",
+		.frequency_min = 950000,
+		.frequency_max = 2150000,
+		.frequency_tolerance = 5000,
+		.symbol_rate_min = 1000000,
+		.symbol_rate_max = 45000000,
+		.caps = FE_CAN_INVERSION_AUTO |
+			FE_CAN_FEC_1_2 |
+			FE_CAN_FEC_2_3 |
+			FE_CAN_FEC_3_4 |
+			FE_CAN_FEC_4_5 |
+			FE_CAN_FEC_5_6 |
+			FE_CAN_FEC_6_7 |
+			FE_CAN_FEC_7_8 |
+			FE_CAN_FEC_8_9 |
+			FE_CAN_FEC_AUTO |
+			FE_CAN_QPSK |
+			FE_CAN_RECOVER |
+			FE_CAN_2G_MODULATION
+	},
+
+	.release = tda10071_release,
+
+	.get_tune_settings = tda10071_get_tune_settings,
+
+	.init = tda10071_init,
+	.sleep = tda10071_sleep,
+
+	.set_frontend = tda10071_set_frontend,
+	.get_frontend = tda10071_get_frontend,
+
+	.read_status = tda10071_read_status,
+	.read_snr = tda10071_read_snr,
+	.read_signal_strength = tda10071_read_signal_strength,
+	.read_ber = tda10071_read_ber,
+	.read_ucblocks = tda10071_read_ucblocks,
+
+	.diseqc_send_master_cmd = tda10071_diseqc_send_master_cmd,
+	.diseqc_recv_slave_reply = tda10071_diseqc_recv_slave_reply,
+	.diseqc_send_burst = tda10071_diseqc_send_burst,
+
+	.set_tone = tda10071_set_tone,
+	.set_voltage = tda10071_set_voltage,
+};
+
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
+MODULE_DESCRIPTION("NXP TDA10071 DVB-S/S2 demodulator driver");
+MODULE_LICENSE("GPL");
+MODULE_FIRMWARE(TDA10071_FIRMWARE);
diff --git a/drivers/media/dvb-frontends/tda10071.h b/drivers/media/dvb-frontends/tda10071.h
new file mode 100644
index 0000000..21163c4
--- /dev/null
+++ b/drivers/media/dvb-frontends/tda10071.h
@@ -0,0 +1,81 @@
+/*
+ * NXP TDA10071 + Conexant CX24118A DVB-S/S2 demodulator + tuner driver
+ *
+ * Copyright (C) 2011 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.,
+ *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef TDA10071_H
+#define TDA10071_H
+
+#include <linux/dvb/frontend.h>
+
+struct tda10071_config {
+	/* Demodulator I2C address.
+	 * Default: none, must set
+	 * Values: 0x55,
+	 */
+	u8 i2c_address;
+
+	/* Max bytes I2C provider can write at once.
+	 * Note: Buffer is taken from the stack currently!
+	 * Default: none, must set
+	 * Values:
+	 */
+	u16 i2c_wr_max;
+
+	/* TS output mode.
+	 * Default: TDA10071_TS_SERIAL
+	 * Values:
+	 */
+#define TDA10071_TS_SERIAL        0
+#define TDA10071_TS_PARALLEL      1
+	u8 ts_mode;
+
+	/* Input spectrum inversion.
+	 * Default: 0
+	 * Values: 0, 1
+	 */
+	bool spec_inv;
+
+	/* Xtal frequency Hz
+	 * Default: none, must set
+	 * Values:
+	 */
+	u32 xtal;
+
+	/* PLL multiplier.
+	 * Default: none, must set
+	 * Values:
+	 */
+	u8 pll_multiplier;
+};
+
+
+#if defined(CONFIG_DVB_TDA10071) || \
+	(defined(CONFIG_DVB_TDA10071_MODULE) && defined(MODULE))
+extern struct dvb_frontend *tda10071_attach(
+	const struct tda10071_config *config, struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend *tda10071_attach(
+	const struct tda10071_config *config, struct i2c_adapter *i2c)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif
+
+#endif /* TDA10071_H */
diff --git a/drivers/media/dvb-frontends/tda10071_priv.h b/drivers/media/dvb-frontends/tda10071_priv.h
new file mode 100644
index 0000000..4baf14b
--- /dev/null
+++ b/drivers/media/dvb-frontends/tda10071_priv.h
@@ -0,0 +1,109 @@
+/*
+ * NXP TDA10071 + Conexant CX24118A DVB-S/S2 demodulator + tuner driver
+ *
+ * Copyright (C) 2011 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.,
+ *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef TDA10071_PRIV
+#define TDA10071_PRIV
+
+#include "dvb_frontend.h"
+#include "tda10071.h"
+#include <linux/firmware.h>
+
+struct tda10071_priv {
+	struct i2c_adapter *i2c;
+	struct dvb_frontend fe;
+	struct tda10071_config cfg;
+
+	u8 meas_count[2];
+	u32 ber;
+	u32 ucb;
+	fe_status_t fe_status;
+	fe_delivery_system_t delivery_system;
+	bool warm; /* FW running */
+};
+
+static struct tda10071_modcod {
+	fe_delivery_system_t delivery_system;
+	fe_modulation_t modulation;
+	fe_code_rate_t fec;
+	u8 val;
+} TDA10071_MODCOD[] = {
+	/* NBC-QPSK */
+	{ SYS_DVBS2, QPSK,  FEC_AUTO, 0x00 },
+	{ SYS_DVBS2, QPSK,  FEC_1_2,  0x04 },
+	{ SYS_DVBS2, QPSK,  FEC_3_5,  0x05 },
+	{ SYS_DVBS2, QPSK,  FEC_2_3,  0x06 },
+	{ SYS_DVBS2, QPSK,  FEC_3_4,  0x07 },
+	{ SYS_DVBS2, QPSK,  FEC_4_5,  0x08 },
+	{ SYS_DVBS2, QPSK,  FEC_5_6,  0x09 },
+	{ SYS_DVBS2, QPSK,  FEC_8_9,  0x0a },
+	{ SYS_DVBS2, QPSK,  FEC_9_10, 0x0b },
+	/* 8PSK */
+	{ SYS_DVBS2, PSK_8, FEC_3_5,  0x0c },
+	{ SYS_DVBS2, PSK_8, FEC_2_3,  0x0d },
+	{ SYS_DVBS2, PSK_8, FEC_3_4,  0x0e },
+	{ SYS_DVBS2, PSK_8, FEC_5_6,  0x0f },
+	{ SYS_DVBS2, PSK_8, FEC_8_9,  0x10 },
+	{ SYS_DVBS2, PSK_8, FEC_9_10, 0x11 },
+	/* QPSK */
+	{ SYS_DVBS,  QPSK,  FEC_AUTO, 0x2d },
+	{ SYS_DVBS,  QPSK,  FEC_1_2,  0x2e },
+	{ SYS_DVBS,  QPSK,  FEC_2_3,  0x2f },
+	{ SYS_DVBS,  QPSK,  FEC_3_4,  0x30 },
+	{ SYS_DVBS,  QPSK,  FEC_5_6,  0x31 },
+	{ SYS_DVBS,  QPSK,  FEC_7_8,  0x32 },
+};
+
+struct tda10071_reg_val_mask {
+	u8 reg;
+	u8 val;
+	u8 mask;
+};
+
+/* firmware filename */
+#define TDA10071_FIRMWARE "dvb-fe-tda10071.fw"
+
+/* firmware commands */
+#define CMD_DEMOD_INIT          0x10
+#define CMD_CHANGE_CHANNEL      0x11
+#define CMD_MPEG_CONFIG         0x13
+#define CMD_TUNER_INIT          0x15
+#define CMD_GET_AGCACC          0x1a
+
+#define CMD_LNB_CONFIG          0x20
+#define CMD_LNB_SEND_DISEQC     0x21
+#define CMD_LNB_SET_DC_LEVEL    0x22
+#define CMD_LNB_PCB_CONFIG      0x23
+#define CMD_LNB_SEND_TONEBURST  0x24
+#define CMD_LNB_UPDATE_REPLY    0x25
+
+#define CMD_GET_FW_VERSION      0x35
+#define CMD_SET_SLEEP_MODE      0x36
+#define CMD_BER_CONTROL         0x3e
+#define CMD_BER_UPDATE_COUNTERS 0x3f
+
+/* firmare command struct */
+#define TDA10071_ARGLEN      30
+struct tda10071_cmd {
+	u8 args[TDA10071_ARGLEN];
+	u8 len;
+};
+
+
+#endif /* TDA10071_PRIV */
diff --git a/drivers/media/dvb-frontends/tda10086.c b/drivers/media/dvb-frontends/tda10086.c
new file mode 100644
index 0000000..fcfe2e0
--- /dev/null
+++ b/drivers/media/dvb-frontends/tda10086.c
@@ -0,0 +1,777 @@
+  /*
+     Driver for Philips tda10086 DVBS Demodulator
+
+     (c) 2006 Andrew de Quincey
+
+     This program is free software; you can redistribute it and/or modify
+     it under the terms of the 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/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/jiffies.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+
+#include "dvb_frontend.h"
+#include "tda10086.h"
+
+#define SACLK 96000000
+
+struct tda10086_state {
+	struct i2c_adapter* i2c;
+	const struct tda10086_config* config;
+	struct dvb_frontend frontend;
+
+	/* private demod data */
+	u32 frequency;
+	u32 symbol_rate;
+	bool has_lock;
+};
+
+static int debug;
+#define dprintk(args...) \
+	do { \
+		if (debug) printk(KERN_DEBUG "tda10086: " args); \
+	} while (0)
+
+static int tda10086_write_byte(struct tda10086_state *state, int reg, int data)
+{
+	int ret;
+	u8 b0[] = { reg, data };
+	struct i2c_msg msg = { .flags = 0, .buf = b0, .len = 2 };
+
+	msg.addr = state->config->demod_address;
+	ret = i2c_transfer(state->i2c, &msg, 1);
+
+	if (ret != 1)
+		dprintk("%s: error reg=0x%x, data=0x%x, ret=%i\n",
+			__func__, reg, data, ret);
+
+	return (ret != 1) ? ret : 0;
+}
+
+static int tda10086_read_byte(struct tda10086_state *state, int reg)
+{
+	int ret;
+	u8 b0[] = { reg };
+	u8 b1[] = { 0 };
+	struct i2c_msg msg[] = {{ .flags = 0, .buf = b0, .len = 1 },
+				{ .flags = I2C_M_RD, .buf = b1, .len = 1 }};
+
+	msg[0].addr = state->config->demod_address;
+	msg[1].addr = state->config->demod_address;
+	ret = i2c_transfer(state->i2c, msg, 2);
+
+	if (ret != 2) {
+		dprintk("%s: error reg=0x%x, ret=%i\n", __func__, reg,
+			ret);
+		return ret;
+	}
+
+	return b1[0];
+}
+
+static int tda10086_write_mask(struct tda10086_state *state, int reg, int mask, int data)
+{
+	int val;
+
+	/* read a byte and check */
+	val = tda10086_read_byte(state, reg);
+	if (val < 0)
+		return val;
+
+	/* mask if off */
+	val = val & ~mask;
+	val |= data & 0xff;
+
+	/* write it out again */
+	return tda10086_write_byte(state, reg, val);
+}
+
+static int tda10086_init(struct dvb_frontend* fe)
+{
+	struct tda10086_state* state = fe->demodulator_priv;
+	u8 t22k_off = 0x80;
+
+	dprintk ("%s\n", __func__);
+
+	if (state->config->diseqc_tone)
+		t22k_off = 0;
+	/* reset */
+	tda10086_write_byte(state, 0x00, 0x00);
+	msleep(10);
+
+	/* misc setup */
+	tda10086_write_byte(state, 0x01, 0x94);
+	tda10086_write_byte(state, 0x02, 0x35); /* NOTE: TT drivers appear to disable CSWP */
+	tda10086_write_byte(state, 0x03, 0xe4);
+	tda10086_write_byte(state, 0x04, 0x43);
+	tda10086_write_byte(state, 0x0c, 0x0c);
+	tda10086_write_byte(state, 0x1b, 0xb0); /* noise threshold */
+	tda10086_write_byte(state, 0x20, 0x89); /* misc */
+	tda10086_write_byte(state, 0x30, 0x04); /* acquisition period length */
+	tda10086_write_byte(state, 0x32, 0x00); /* irq off */
+	tda10086_write_byte(state, 0x31, 0x56); /* setup AFC */
+
+	/* setup PLL (this assumes SACLK = 96MHz) */
+	tda10086_write_byte(state, 0x55, 0x2c); /* misc PLL setup */
+	if (state->config->xtal_freq == TDA10086_XTAL_16M) {
+		tda10086_write_byte(state, 0x3a, 0x0b); /* M=12 */
+		tda10086_write_byte(state, 0x3b, 0x01); /* P=2 */
+	} else {
+		tda10086_write_byte(state, 0x3a, 0x17); /* M=24 */
+		tda10086_write_byte(state, 0x3b, 0x00); /* P=1 */
+	}
+	tda10086_write_mask(state, 0x55, 0x20, 0x00); /* powerup PLL */
+
+	/* setup TS interface */
+	tda10086_write_byte(state, 0x11, 0x81);
+	tda10086_write_byte(state, 0x12, 0x81);
+	tda10086_write_byte(state, 0x19, 0x40); /* parallel mode A + MSBFIRST */
+	tda10086_write_byte(state, 0x56, 0x80); /* powerdown WPLL - unused in the mode we use */
+	tda10086_write_byte(state, 0x57, 0x08); /* bypass WPLL - unused in the mode we use */
+	tda10086_write_byte(state, 0x10, 0x2a);
+
+	/* setup ADC */
+	tda10086_write_byte(state, 0x58, 0x61); /* ADC setup */
+	tda10086_write_mask(state, 0x58, 0x01, 0x00); /* powerup ADC */
+
+	/* setup AGC */
+	tda10086_write_byte(state, 0x05, 0x0B);
+	tda10086_write_byte(state, 0x37, 0x63);
+	tda10086_write_byte(state, 0x3f, 0x0a); /* NOTE: flydvb varies it */
+	tda10086_write_byte(state, 0x40, 0x64);
+	tda10086_write_byte(state, 0x41, 0x4f);
+	tda10086_write_byte(state, 0x42, 0x43);
+
+	/* setup viterbi */
+	tda10086_write_byte(state, 0x1a, 0x11); /* VBER 10^6, DVB, QPSK */
+
+	/* setup carrier recovery */
+	tda10086_write_byte(state, 0x3d, 0x80);
+
+	/* setup SEC */
+	tda10086_write_byte(state, 0x36, t22k_off); /* all SEC off, 22k tone */
+	tda10086_write_byte(state, 0x34, (((1<<19) * (22000/1000)) / (SACLK/1000)));
+	tda10086_write_byte(state, 0x35, (((1<<19) * (22000/1000)) / (SACLK/1000)) >> 8);
+
+	return 0;
+}
+
+static void tda10086_diseqc_wait(struct tda10086_state *state)
+{
+	unsigned long timeout = jiffies + msecs_to_jiffies(200);
+	while (!(tda10086_read_byte(state, 0x50) & 0x01)) {
+		if(time_after(jiffies, timeout)) {
+			printk("%s: diseqc queue not ready, command may be lost.\n", __func__);
+			break;
+		}
+		msleep(10);
+	}
+}
+
+static int tda10086_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
+{
+	struct tda10086_state* state = fe->demodulator_priv;
+	u8 t22k_off = 0x80;
+
+	dprintk ("%s\n", __func__);
+
+	if (state->config->diseqc_tone)
+		t22k_off = 0;
+
+	switch (tone) {
+	case SEC_TONE_OFF:
+		tda10086_write_byte(state, 0x36, t22k_off);
+		break;
+
+	case SEC_TONE_ON:
+		tda10086_write_byte(state, 0x36, 0x01 + t22k_off);
+		break;
+	}
+
+	return 0;
+}
+
+static int tda10086_send_master_cmd (struct dvb_frontend* fe,
+				    struct dvb_diseqc_master_cmd* cmd)
+{
+	struct tda10086_state* state = fe->demodulator_priv;
+	int i;
+	u8 oldval;
+	u8 t22k_off = 0x80;
+
+	dprintk ("%s\n", __func__);
+
+	if (state->config->diseqc_tone)
+		t22k_off = 0;
+
+	if (cmd->msg_len > 6)
+		return -EINVAL;
+	oldval = tda10086_read_byte(state, 0x36);
+
+	for(i=0; i< cmd->msg_len; i++) {
+		tda10086_write_byte(state, 0x48+i, cmd->msg[i]);
+	}
+	tda10086_write_byte(state, 0x36, (0x08 + t22k_off)
+					| ((cmd->msg_len - 1) << 4));
+
+	tda10086_diseqc_wait(state);
+
+	tda10086_write_byte(state, 0x36, oldval);
+
+	return 0;
+}
+
+static int tda10086_send_burst (struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd)
+{
+	struct tda10086_state* state = fe->demodulator_priv;
+	u8 oldval = tda10086_read_byte(state, 0x36);
+	u8 t22k_off = 0x80;
+
+	dprintk ("%s\n", __func__);
+
+	if (state->config->diseqc_tone)
+		t22k_off = 0;
+
+	switch(minicmd) {
+	case SEC_MINI_A:
+		tda10086_write_byte(state, 0x36, 0x04 + t22k_off);
+		break;
+
+	case SEC_MINI_B:
+		tda10086_write_byte(state, 0x36, 0x06 + t22k_off);
+		break;
+	}
+
+	tda10086_diseqc_wait(state);
+
+	tda10086_write_byte(state, 0x36, oldval);
+
+	return 0;
+}
+
+static int tda10086_set_inversion(struct tda10086_state *state,
+				  struct dtv_frontend_properties *fe_params)
+{
+	u8 invval = 0x80;
+
+	dprintk ("%s %i %i\n", __func__, fe_params->inversion, state->config->invert);
+
+	switch(fe_params->inversion) {
+	case INVERSION_OFF:
+		if (state->config->invert)
+			invval = 0x40;
+		break;
+	case INVERSION_ON:
+		if (!state->config->invert)
+			invval = 0x40;
+		break;
+	case INVERSION_AUTO:
+		invval = 0x00;
+		break;
+	}
+	tda10086_write_mask(state, 0x0c, 0xc0, invval);
+
+	return 0;
+}
+
+static int tda10086_set_symbol_rate(struct tda10086_state *state,
+				    struct dtv_frontend_properties *fe_params)
+{
+	u8 dfn = 0;
+	u8 afs = 0;
+	u8 byp = 0;
+	u8 reg37 = 0x43;
+	u8 reg42 = 0x43;
+	u64 big;
+	u32 tmp;
+	u32 bdr;
+	u32 bdri;
+	u32 symbol_rate = fe_params->symbol_rate;
+
+	dprintk ("%s %i\n", __func__, symbol_rate);
+
+	/* setup the decimation and anti-aliasing filters.. */
+	if (symbol_rate < (u32) (SACLK * 0.0137)) {
+		dfn=4;
+		afs=1;
+	} else if (symbol_rate < (u32) (SACLK * 0.0208)) {
+		dfn=4;
+		afs=0;
+	} else if (symbol_rate < (u32) (SACLK * 0.0270)) {
+		dfn=3;
+		afs=1;
+	} else if (symbol_rate < (u32) (SACLK * 0.0416)) {
+		dfn=3;
+		afs=0;
+	} else if (symbol_rate < (u32) (SACLK * 0.0550)) {
+		dfn=2;
+		afs=1;
+	} else if (symbol_rate < (u32) (SACLK * 0.0833)) {
+		dfn=2;
+		afs=0;
+	} else if (symbol_rate < (u32) (SACLK * 0.1100)) {
+		dfn=1;
+		afs=1;
+	} else if (symbol_rate < (u32) (SACLK * 0.1666)) {
+		dfn=1;
+		afs=0;
+	} else if (symbol_rate < (u32) (SACLK * 0.2200)) {
+		dfn=0;
+		afs=1;
+	} else if (symbol_rate < (u32) (SACLK * 0.3333)) {
+		dfn=0;
+		afs=0;
+	} else {
+		reg37 = 0x63;
+		reg42 = 0x4f;
+		byp=1;
+	}
+
+	/* calculate BDR */
+	big = (1ULL<<21) * ((u64) symbol_rate/1000ULL) * (1ULL<<dfn);
+	big += ((SACLK/1000ULL)-1ULL);
+	do_div(big, (SACLK/1000ULL));
+	bdr = big & 0xfffff;
+
+	/* calculate BDRI */
+	tmp = (1<<dfn)*(symbol_rate/1000);
+	bdri = ((32 * (SACLK/1000)) + (tmp-1)) / tmp;
+
+	tda10086_write_byte(state, 0x21, (afs << 7) | dfn);
+	tda10086_write_mask(state, 0x20, 0x08, byp << 3);
+	tda10086_write_byte(state, 0x06, bdr);
+	tda10086_write_byte(state, 0x07, bdr >> 8);
+	tda10086_write_byte(state, 0x08, bdr >> 16);
+	tda10086_write_byte(state, 0x09, bdri);
+	tda10086_write_byte(state, 0x37, reg37);
+	tda10086_write_byte(state, 0x42, reg42);
+
+	return 0;
+}
+
+static int tda10086_set_fec(struct tda10086_state *state,
+			    struct dtv_frontend_properties *fe_params)
+{
+	u8 fecval;
+
+	dprintk("%s %i\n", __func__, fe_params->fec_inner);
+
+	switch (fe_params->fec_inner) {
+	case FEC_1_2:
+		fecval = 0x00;
+		break;
+	case FEC_2_3:
+		fecval = 0x01;
+		break;
+	case FEC_3_4:
+		fecval = 0x02;
+		break;
+	case FEC_4_5:
+		fecval = 0x03;
+		break;
+	case FEC_5_6:
+		fecval = 0x04;
+		break;
+	case FEC_6_7:
+		fecval = 0x05;
+		break;
+	case FEC_7_8:
+		fecval = 0x06;
+		break;
+	case FEC_8_9:
+		fecval = 0x07;
+		break;
+	case FEC_AUTO:
+		fecval = 0x08;
+		break;
+	default:
+		return -1;
+	}
+	tda10086_write_byte(state, 0x0d, fecval);
+
+	return 0;
+}
+
+static int tda10086_set_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *fe_params = &fe->dtv_property_cache;
+	struct tda10086_state *state = fe->demodulator_priv;
+	int ret;
+	u32 freq = 0;
+	int freqoff;
+
+	dprintk ("%s\n", __func__);
+
+	/* modify parameters for tuning */
+	tda10086_write_byte(state, 0x02, 0x35);
+	state->has_lock = false;
+
+	/* set params */
+	if (fe->ops.tuner_ops.set_params) {
+		fe->ops.tuner_ops.set_params(fe);
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 0);
+
+		if (fe->ops.tuner_ops.get_frequency)
+			fe->ops.tuner_ops.get_frequency(fe, &freq);
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 0);
+	}
+
+	/* calcluate the frequency offset (in *Hz* not kHz) */
+	freqoff = fe_params->frequency - freq;
+	freqoff = ((1<<16) * freqoff) / (SACLK/1000);
+	tda10086_write_byte(state, 0x3d, 0x80 | ((freqoff >> 8) & 0x7f));
+	tda10086_write_byte(state, 0x3e, freqoff);
+
+	if ((ret = tda10086_set_inversion(state, fe_params)) < 0)
+		return ret;
+	if ((ret = tda10086_set_symbol_rate(state, fe_params)) < 0)
+		return ret;
+	if ((ret = tda10086_set_fec(state, fe_params)) < 0)
+		return ret;
+
+	/* soft reset + disable TS output until lock */
+	tda10086_write_mask(state, 0x10, 0x40, 0x40);
+	tda10086_write_mask(state, 0x00, 0x01, 0x00);
+
+	state->symbol_rate = fe_params->symbol_rate;
+	state->frequency = fe_params->frequency;
+	return 0;
+}
+
+static int tda10086_get_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *fe_params = &fe->dtv_property_cache;
+	struct tda10086_state* state = fe->demodulator_priv;
+	u8 val;
+	int tmp;
+	u64 tmp64;
+
+	dprintk ("%s\n", __func__);
+
+	/* check for invalid symbol rate */
+	if (fe_params->symbol_rate < 500000)
+		return -EINVAL;
+
+	/* calculate the updated frequency (note: we convert from Hz->kHz) */
+	tmp64 = tda10086_read_byte(state, 0x52);
+	tmp64 |= (tda10086_read_byte(state, 0x51) << 8);
+	if (tmp64 & 0x8000)
+		tmp64 |= 0xffffffffffff0000ULL;
+	tmp64 = (tmp64 * (SACLK/1000ULL));
+	do_div(tmp64, (1ULL<<15) * (1ULL<<1));
+	fe_params->frequency = (int) state->frequency + (int) tmp64;
+
+	/* the inversion */
+	val = tda10086_read_byte(state, 0x0c);
+	if (val & 0x80) {
+		switch(val & 0x40) {
+		case 0x00:
+			fe_params->inversion = INVERSION_OFF;
+			if (state->config->invert)
+				fe_params->inversion = INVERSION_ON;
+			break;
+		default:
+			fe_params->inversion = INVERSION_ON;
+			if (state->config->invert)
+				fe_params->inversion = INVERSION_OFF;
+			break;
+		}
+	} else {
+		tda10086_read_byte(state, 0x0f);
+		switch(val & 0x02) {
+		case 0x00:
+			fe_params->inversion = INVERSION_OFF;
+			if (state->config->invert)
+				fe_params->inversion = INVERSION_ON;
+			break;
+		default:
+			fe_params->inversion = INVERSION_ON;
+			if (state->config->invert)
+				fe_params->inversion = INVERSION_OFF;
+			break;
+		}
+	}
+
+	/* calculate the updated symbol rate */
+	tmp = tda10086_read_byte(state, 0x1d);
+	if (tmp & 0x80)
+		tmp |= 0xffffff00;
+	tmp = (tmp * 480 * (1<<1)) / 128;
+	tmp = ((state->symbol_rate/1000) * tmp) / (1000000/1000);
+	fe_params->symbol_rate = state->symbol_rate + tmp;
+
+	/* the FEC */
+	val = (tda10086_read_byte(state, 0x0d) & 0x70) >> 4;
+	switch(val) {
+	case 0x00:
+		fe_params->fec_inner = FEC_1_2;
+		break;
+	case 0x01:
+		fe_params->fec_inner = FEC_2_3;
+		break;
+	case 0x02:
+		fe_params->fec_inner = FEC_3_4;
+		break;
+	case 0x03:
+		fe_params->fec_inner = FEC_4_5;
+		break;
+	case 0x04:
+		fe_params->fec_inner = FEC_5_6;
+		break;
+	case 0x05:
+		fe_params->fec_inner = FEC_6_7;
+		break;
+	case 0x06:
+		fe_params->fec_inner = FEC_7_8;
+		break;
+	case 0x07:
+		fe_params->fec_inner = FEC_8_9;
+		break;
+	}
+
+	return 0;
+}
+
+static int tda10086_read_status(struct dvb_frontend* fe, fe_status_t *fe_status)
+{
+	struct tda10086_state* state = fe->demodulator_priv;
+	u8 val;
+
+	dprintk ("%s\n", __func__);
+
+	val = tda10086_read_byte(state, 0x0e);
+	*fe_status = 0;
+	if (val & 0x01)
+		*fe_status |= FE_HAS_SIGNAL;
+	if (val & 0x02)
+		*fe_status |= FE_HAS_CARRIER;
+	if (val & 0x04)
+		*fe_status |= FE_HAS_VITERBI;
+	if (val & 0x08)
+		*fe_status |= FE_HAS_SYNC;
+	if (val & 0x10) {
+		*fe_status |= FE_HAS_LOCK;
+		if (!state->has_lock) {
+			state->has_lock = true;
+			/* modify parameters for stable reception */
+			tda10086_write_byte(state, 0x02, 0x00);
+		}
+	}
+
+	return 0;
+}
+
+static int tda10086_read_signal_strength(struct dvb_frontend* fe, u16 * signal)
+{
+	struct tda10086_state* state = fe->demodulator_priv;
+	u8 _str;
+
+	dprintk ("%s\n", __func__);
+
+	_str = 0xff - tda10086_read_byte(state, 0x43);
+	*signal = (_str << 8) | _str;
+
+	return 0;
+}
+
+static int tda10086_read_snr(struct dvb_frontend* fe, u16 * snr)
+{
+	struct tda10086_state* state = fe->demodulator_priv;
+	u8 _snr;
+
+	dprintk ("%s\n", __func__);
+
+	_snr = 0xff - tda10086_read_byte(state, 0x1c);
+	*snr = (_snr << 8) | _snr;
+
+	return 0;
+}
+
+static int tda10086_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
+{
+	struct tda10086_state* state = fe->demodulator_priv;
+
+	dprintk ("%s\n", __func__);
+
+	/* read it */
+	*ucblocks = tda10086_read_byte(state, 0x18) & 0x7f;
+
+	/* reset counter */
+	tda10086_write_byte(state, 0x18, 0x00);
+	tda10086_write_byte(state, 0x18, 0x80);
+
+	return 0;
+}
+
+static int tda10086_read_ber(struct dvb_frontend* fe, u32* ber)
+{
+	struct tda10086_state* state = fe->demodulator_priv;
+
+	dprintk ("%s\n", __func__);
+
+	/* read it */
+	*ber = 0;
+	*ber |= tda10086_read_byte(state, 0x15);
+	*ber |= tda10086_read_byte(state, 0x16) << 8;
+	*ber |= (tda10086_read_byte(state, 0x17) & 0xf) << 16;
+
+	return 0;
+}
+
+static int tda10086_sleep(struct dvb_frontend* fe)
+{
+	struct tda10086_state* state = fe->demodulator_priv;
+
+	dprintk ("%s\n", __func__);
+
+	tda10086_write_mask(state, 0x00, 0x08, 0x08);
+
+	return 0;
+}
+
+static int tda10086_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+{
+	struct tda10086_state* state = fe->demodulator_priv;
+
+	dprintk ("%s\n", __func__);
+
+	if (enable) {
+		tda10086_write_mask(state, 0x00, 0x10, 0x10);
+	} else {
+		tda10086_write_mask(state, 0x00, 0x10, 0x00);
+	}
+
+	return 0;
+}
+
+static int tda10086_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+
+	if (p->symbol_rate > 20000000) {
+		fesettings->min_delay_ms = 50;
+		fesettings->step_size = 2000;
+		fesettings->max_drift = 8000;
+	} else if (p->symbol_rate > 12000000) {
+		fesettings->min_delay_ms = 100;
+		fesettings->step_size = 1500;
+		fesettings->max_drift = 9000;
+	} else if (p->symbol_rate > 8000000) {
+		fesettings->min_delay_ms = 100;
+		fesettings->step_size = 1000;
+		fesettings->max_drift = 8000;
+	} else if (p->symbol_rate > 4000000) {
+		fesettings->min_delay_ms = 100;
+		fesettings->step_size = 500;
+		fesettings->max_drift = 7000;
+	} else if (p->symbol_rate > 2000000) {
+		fesettings->min_delay_ms = 200;
+		fesettings->step_size = p->symbol_rate / 8000;
+		fesettings->max_drift = 14 * fesettings->step_size;
+	} else {
+		fesettings->min_delay_ms = 200;
+		fesettings->step_size =  p->symbol_rate / 8000;
+		fesettings->max_drift = 18 * fesettings->step_size;
+	}
+
+	return 0;
+}
+
+static void tda10086_release(struct dvb_frontend* fe)
+{
+	struct tda10086_state *state = fe->demodulator_priv;
+	tda10086_sleep(fe);
+	kfree(state);
+}
+
+static struct dvb_frontend_ops tda10086_ops = {
+	.delsys = { SYS_DVBS },
+	.info = {
+		.name     = "Philips TDA10086 DVB-S",
+		.frequency_min    = 950000,
+		.frequency_max    = 2150000,
+		.frequency_stepsize = 125,     /* kHz for QPSK frontends */
+		.symbol_rate_min  = 1000000,
+		.symbol_rate_max  = 45000000,
+		.caps = FE_CAN_INVERSION_AUTO |
+			FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
+			FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
+			FE_CAN_QPSK
+	},
+
+	.release = tda10086_release,
+
+	.init = tda10086_init,
+	.sleep = tda10086_sleep,
+	.i2c_gate_ctrl = tda10086_i2c_gate_ctrl,
+
+	.set_frontend = tda10086_set_frontend,
+	.get_frontend = tda10086_get_frontend,
+	.get_tune_settings = tda10086_get_tune_settings,
+
+	.read_status = tda10086_read_status,
+	.read_ber = tda10086_read_ber,
+	.read_signal_strength = tda10086_read_signal_strength,
+	.read_snr = tda10086_read_snr,
+	.read_ucblocks = tda10086_read_ucblocks,
+
+	.diseqc_send_master_cmd = tda10086_send_master_cmd,
+	.diseqc_send_burst = tda10086_send_burst,
+	.set_tone = tda10086_set_tone,
+};
+
+struct dvb_frontend* tda10086_attach(const struct tda10086_config* config,
+				     struct i2c_adapter* i2c)
+{
+	struct tda10086_state *state;
+
+	dprintk ("%s\n", __func__);
+
+	/* allocate memory for the internal state */
+	state = kzalloc(sizeof(struct tda10086_state), GFP_KERNEL);
+	if (!state)
+		return NULL;
+
+	/* setup the state */
+	state->config = config;
+	state->i2c = i2c;
+
+	/* check if the demod is there */
+	if (tda10086_read_byte(state, 0x1e) != 0xe1) {
+		kfree(state);
+		return NULL;
+	}
+
+	/* create dvb_frontend */
+	memcpy(&state->frontend.ops, &tda10086_ops, sizeof(struct dvb_frontend_ops));
+	state->frontend.demodulator_priv = state;
+	return &state->frontend;
+}
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+
+MODULE_DESCRIPTION("Philips TDA10086 DVB-S Demodulator");
+MODULE_AUTHOR("Andrew de Quincey");
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(tda10086_attach);
diff --git a/drivers/media/dvb-frontends/tda10086.h b/drivers/media/dvb-frontends/tda10086.h
new file mode 100644
index 0000000..61148c5
--- /dev/null
+++ b/drivers/media/dvb-frontends/tda10086.h
@@ -0,0 +1,61 @@
+  /*
+     Driver for Philips tda10086 DVBS Frontend
+
+     (c) 2006 Andrew de Quincey
+
+     This program is free software; you can redistribute it and/or modify
+     it under the terms of the 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 TDA10086_H
+#define TDA10086_H
+
+#include <linux/dvb/frontend.h>
+#include <linux/firmware.h>
+
+enum tda10086_xtal {
+	TDA10086_XTAL_16M,
+	TDA10086_XTAL_4M
+};
+
+struct tda10086_config
+{
+	/* the demodulator's i2c address */
+	u8 demod_address;
+
+	/* does the "inversion" need inverted? */
+	u8 invert;
+
+	/* do we need the diseqc signal with carrier? */
+	u8 diseqc_tone;
+
+	/* frequency of the reference xtal */
+	enum tda10086_xtal xtal_freq;
+};
+
+#if defined(CONFIG_DVB_TDA10086) || (defined(CONFIG_DVB_TDA10086_MODULE) && defined(MODULE))
+extern struct dvb_frontend* tda10086_attach(const struct tda10086_config* config,
+					    struct i2c_adapter* i2c);
+#else
+static inline struct dvb_frontend* tda10086_attach(const struct tda10086_config* config,
+						   struct i2c_adapter* i2c)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif /* CONFIG_DVB_TDA10086 */
+
+#endif /* TDA10086_H */
diff --git a/drivers/media/dvb-frontends/tda18271c2dd.c b/drivers/media/dvb-frontends/tda18271c2dd.c
new file mode 100644
index 0000000..ad7c72e
--- /dev/null
+++ b/drivers/media/dvb-frontends/tda18271c2dd.c
@@ -0,0 +1,1246 @@
+/*
+ * tda18271c2dd: Driver for the TDA18271C2 tuner
+ *
+ * Copyright (C) 2010 Digital Devices GmbH
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 only, as published by the Free Software Foundation.
+ *
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/firmware.h>
+#include <linux/i2c.h>
+#include <asm/div64.h>
+
+#include "dvb_frontend.h"
+
+struct SStandardParam {
+	s32   m_IFFrequency;
+	u32   m_BandWidth;
+	u8    m_EP3_4_0;
+	u8    m_EB22;
+};
+
+struct SMap {
+	u32   m_Frequency;
+	u8    m_Param;
+};
+
+struct SMapI {
+	u32   m_Frequency;
+	s32    m_Param;
+};
+
+struct SMap2 {
+	u32   m_Frequency;
+	u8    m_Param1;
+	u8    m_Param2;
+};
+
+struct SRFBandMap {
+	u32   m_RF_max;
+	u32   m_RF1_Default;
+	u32   m_RF2_Default;
+	u32   m_RF3_Default;
+};
+
+enum ERegister {
+	ID = 0,
+	TM,
+	PL,
+	EP1, EP2, EP3, EP4, EP5,
+	CPD, CD1, CD2, CD3,
+	MPD, MD1, MD2, MD3,
+	EB1, EB2, EB3, EB4, EB5, EB6, EB7, EB8, EB9, EB10,
+	EB11, EB12, EB13, EB14, EB15, EB16, EB17, EB18, EB19, EB20,
+	EB21, EB22, EB23,
+	NUM_REGS
+};
+
+struct tda_state {
+	struct i2c_adapter *i2c;
+	u8 adr;
+
+	u32   m_Frequency;
+	u32   IF;
+
+	u8    m_IFLevelAnalog;
+	u8    m_IFLevelDigital;
+	u8    m_IFLevelDVBC;
+	u8    m_IFLevelDVBT;
+
+	u8    m_EP4;
+	u8    m_EP3_Standby;
+
+	bool  m_bMaster;
+
+	s32   m_SettlingTime;
+
+	u8    m_Regs[NUM_REGS];
+
+	/* Tracking filter settings for band 0..6 */
+	u32   m_RF1[7];
+	s32   m_RF_A1[7];
+	s32   m_RF_B1[7];
+	u32   m_RF2[7];
+	s32   m_RF_A2[7];
+	s32   m_RF_B2[7];
+	u32   m_RF3[7];
+
+	u8    m_TMValue_RFCal;    /* Calibration temperatur */
+
+	bool  m_bFMInput;         /* true to use Pin 8 for FM Radio */
+
+};
+
+static int PowerScan(struct tda_state *state,
+		     u8 RFBand, u32 RF_in,
+		     u32 *pRF_Out, bool *pbcal);
+
+static int i2c_readn(struct i2c_adapter *adapter, u8 adr, u8 *data, int len)
+{
+	struct i2c_msg msgs[1] = {{.addr = adr,  .flags = I2C_M_RD,
+				   .buf  = data, .len   = len} };
+	return (i2c_transfer(adapter, msgs, 1) == 1) ? 0 : -1;
+}
+
+static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len)
+{
+	struct i2c_msg msg = {.addr = adr, .flags = 0,
+			      .buf = data, .len = len};
+
+	if (i2c_transfer(adap, &msg, 1) != 1) {
+		printk(KERN_ERR "tda18271c2dd: i2c write error at addr %i\n", adr);
+		return -1;
+	}
+	return 0;
+}
+
+static int WriteRegs(struct tda_state *state,
+		     u8 SubAddr, u8 *Regs, u16 nRegs)
+{
+	u8 data[nRegs+1];
+
+	data[0] = SubAddr;
+	memcpy(data + 1, Regs, nRegs);
+	return i2c_write(state->i2c, state->adr, data, nRegs+1);
+}
+
+static int WriteReg(struct tda_state *state, u8 SubAddr, u8 Reg)
+{
+	u8 msg[2] = {SubAddr, Reg};
+
+	return i2c_write(state->i2c, state->adr, msg, 2);
+}
+
+static int Read(struct tda_state *state, u8 * Regs)
+{
+	return i2c_readn(state->i2c, state->adr, Regs, 16);
+}
+
+static int ReadExtented(struct tda_state *state, u8 * Regs)
+{
+	return i2c_readn(state->i2c, state->adr, Regs, NUM_REGS);
+}
+
+static int UpdateRegs(struct tda_state *state, u8 RegFrom, u8 RegTo)
+{
+	return WriteRegs(state, RegFrom,
+			 &state->m_Regs[RegFrom], RegTo-RegFrom+1);
+}
+static int UpdateReg(struct tda_state *state, u8 Reg)
+{
+	return WriteReg(state, Reg, state->m_Regs[Reg]);
+}
+
+#include "tda18271c2dd_maps.h"
+
+static void reset(struct tda_state *state)
+{
+	u32   ulIFLevelAnalog = 0;
+	u32   ulIFLevelDigital = 2;
+	u32   ulIFLevelDVBC = 7;
+	u32   ulIFLevelDVBT = 6;
+	u32   ulXTOut = 0;
+	u32   ulStandbyMode = 0x06;    /* Send in stdb, but leave osc on */
+	u32   ulSlave = 0;
+	u32   ulFMInput = 0;
+	u32   ulSettlingTime = 100;
+
+	state->m_Frequency         = 0;
+	state->m_SettlingTime = 100;
+	state->m_IFLevelAnalog = (ulIFLevelAnalog & 0x07) << 2;
+	state->m_IFLevelDigital = (ulIFLevelDigital & 0x07) << 2;
+	state->m_IFLevelDVBC = (ulIFLevelDVBC & 0x07) << 2;
+	state->m_IFLevelDVBT = (ulIFLevelDVBT & 0x07) << 2;
+
+	state->m_EP4 = 0x20;
+	if (ulXTOut != 0)
+		state->m_EP4 |= 0x40;
+
+	state->m_EP3_Standby = ((ulStandbyMode & 0x07) << 5) | 0x0F;
+	state->m_bMaster = (ulSlave == 0);
+
+	state->m_SettlingTime = ulSettlingTime;
+
+	state->m_bFMInput = (ulFMInput == 2);
+}
+
+static bool SearchMap1(struct SMap Map[],
+		       u32 Frequency, u8 *pParam)
+{
+	int i = 0;
+
+	while ((Map[i].m_Frequency != 0) && (Frequency > Map[i].m_Frequency))
+		i += 1;
+	if (Map[i].m_Frequency == 0)
+		return false;
+	*pParam = Map[i].m_Param;
+	return true;
+}
+
+static bool SearchMap2(struct SMapI Map[],
+		       u32 Frequency, s32 *pParam)
+{
+	int i = 0;
+
+	while ((Map[i].m_Frequency != 0) &&
+	       (Frequency > Map[i].m_Frequency))
+		i += 1;
+	if (Map[i].m_Frequency == 0)
+		return false;
+	*pParam = Map[i].m_Param;
+	return true;
+}
+
+static bool SearchMap3(struct SMap2 Map[], u32 Frequency,
+		       u8 *pParam1, u8 *pParam2)
+{
+	int i = 0;
+
+	while ((Map[i].m_Frequency != 0) &&
+	       (Frequency > Map[i].m_Frequency))
+		i += 1;
+	if (Map[i].m_Frequency == 0)
+		return false;
+	*pParam1 = Map[i].m_Param1;
+	*pParam2 = Map[i].m_Param2;
+	return true;
+}
+
+static bool SearchMap4(struct SRFBandMap Map[],
+		       u32 Frequency, u8 *pRFBand)
+{
+	int i = 0;
+
+	while (i < 7 && (Frequency > Map[i].m_RF_max))
+		i += 1;
+	if (i == 7)
+		return false;
+	*pRFBand = i;
+	return true;
+}
+
+static int ThermometerRead(struct tda_state *state, u8 *pTM_Value)
+{
+	int status = 0;
+
+	do {
+		u8 Regs[16];
+		state->m_Regs[TM] |= 0x10;
+		status = UpdateReg(state, TM);
+		if (status < 0)
+			break;
+		status = Read(state, Regs);
+		if (status < 0)
+			break;
+		if (((Regs[TM] & 0x0F) == 0 && (Regs[TM] & 0x20) == 0x20) ||
+		    ((Regs[TM] & 0x0F) == 8 && (Regs[TM] & 0x20) == 0x00)) {
+			state->m_Regs[TM] ^= 0x20;
+			status = UpdateReg(state, TM);
+			if (status < 0)
+				break;
+			msleep(10);
+			status = Read(state, Regs);
+			if (status < 0)
+				break;
+		}
+		*pTM_Value = (Regs[TM] & 0x20)
+				? m_Thermometer_Map_2[Regs[TM] & 0x0F]
+				: m_Thermometer_Map_1[Regs[TM] & 0x0F] ;
+		state->m_Regs[TM] &= ~0x10;        /* Thermometer off */
+		status = UpdateReg(state, TM);
+		if (status < 0)
+			break;
+		state->m_Regs[EP4] &= ~0x03;       /* CAL_mode = 0 ????????? */
+		status = UpdateReg(state, EP4);
+		if (status < 0)
+			break;
+	} while (0);
+
+	return status;
+}
+
+static int StandBy(struct tda_state *state)
+{
+	int status = 0;
+	do {
+		state->m_Regs[EB12] &= ~0x20;  /* PD_AGC1_Det = 0 */
+		status = UpdateReg(state, EB12);
+		if (status < 0)
+			break;
+		state->m_Regs[EB18] &= ~0x83;  /* AGC1_loop_off = 0, AGC1_Gain = 6 dB */
+		status = UpdateReg(state, EB18);
+		if (status < 0)
+			break;
+		state->m_Regs[EB21] |= 0x03; /* AGC2_Gain = -6 dB */
+		state->m_Regs[EP3] = state->m_EP3_Standby;
+		status = UpdateReg(state, EP3);
+		if (status < 0)
+			break;
+		state->m_Regs[EB23] &= ~0x06; /* ForceLP_Fc2_En = 0, LP_Fc[2] = 0 */
+		status = UpdateRegs(state, EB21, EB23);
+		if (status < 0)
+			break;
+	} while (0);
+	return status;
+}
+
+static int CalcMainPLL(struct tda_state *state, u32 freq)
+{
+
+	u8  PostDiv;
+	u8  Div;
+	u64 OscFreq;
+	u32 MainDiv;
+
+	if (!SearchMap3(m_Main_PLL_Map, freq, &PostDiv, &Div))
+		return -EINVAL;
+
+	OscFreq = (u64) freq * (u64) Div;
+	OscFreq *= (u64) 16384;
+	do_div(OscFreq, (u64)16000000);
+	MainDiv = OscFreq;
+
+	state->m_Regs[MPD] = PostDiv & 0x77;
+	state->m_Regs[MD1] = ((MainDiv >> 16) & 0x7F);
+	state->m_Regs[MD2] = ((MainDiv >>  8) & 0xFF);
+	state->m_Regs[MD3] = (MainDiv & 0xFF);
+
+	return UpdateRegs(state, MPD, MD3);
+}
+
+static int CalcCalPLL(struct tda_state *state, u32 freq)
+{
+	u8 PostDiv;
+	u8 Div;
+	u64 OscFreq;
+	u32 CalDiv;
+
+	if (!SearchMap3(m_Cal_PLL_Map, freq, &PostDiv, &Div))
+		return -EINVAL;
+
+	OscFreq = (u64)freq * (u64)Div;
+	/* CalDiv = u32( OscFreq * 16384 / 16000000 ); */
+	OscFreq *= (u64)16384;
+	do_div(OscFreq, (u64)16000000);
+	CalDiv = OscFreq;
+
+	state->m_Regs[CPD] = PostDiv;
+	state->m_Regs[CD1] = ((CalDiv >> 16) & 0xFF);
+	state->m_Regs[CD2] = ((CalDiv >>  8) & 0xFF);
+	state->m_Regs[CD3] = (CalDiv & 0xFF);
+
+	return UpdateRegs(state, CPD, CD3);
+}
+
+static int CalibrateRF(struct tda_state *state,
+		       u8 RFBand, u32 freq, s32 *pCprog)
+{
+	int status = 0;
+	u8 Regs[NUM_REGS];
+	do {
+		u8 BP_Filter = 0;
+		u8 GainTaper = 0;
+		u8 RFC_K = 0;
+		u8 RFC_M = 0;
+
+		state->m_Regs[EP4] &= ~0x03; /* CAL_mode = 0 */
+		status = UpdateReg(state, EP4);
+		if (status < 0)
+			break;
+		state->m_Regs[EB18] |= 0x03;  /* AGC1_Gain = 3 */
+		status = UpdateReg(state, EB18);
+		if (status < 0)
+			break;
+
+		/* Switching off LT (as datasheet says) causes calibration on C1 to fail */
+		/* (Readout of Cprog is allways 255) */
+		if (state->m_Regs[ID] != 0x83)    /* C1: ID == 83, C2: ID == 84 */
+			state->m_Regs[EP3] |= 0x40; /* SM_LT = 1 */
+
+		if (!(SearchMap1(m_BP_Filter_Map, freq, &BP_Filter) &&
+			SearchMap1(m_GainTaper_Map, freq, &GainTaper) &&
+			SearchMap3(m_KM_Map, freq, &RFC_K, &RFC_M)))
+			return -EINVAL;
+
+		state->m_Regs[EP1] = (state->m_Regs[EP1] & ~0x07) | BP_Filter;
+		state->m_Regs[EP2] = (RFBand << 5) | GainTaper;
+
+		state->m_Regs[EB13] = (state->m_Regs[EB13] & ~0x7C) | (RFC_K << 4) | (RFC_M << 2);
+
+		status = UpdateRegs(state, EP1, EP3);
+		if (status < 0)
+			break;
+		status = UpdateReg(state, EB13);
+		if (status < 0)
+			break;
+
+		state->m_Regs[EB4] |= 0x20;    /* LO_ForceSrce = 1 */
+		status = UpdateReg(state, EB4);
+		if (status < 0)
+			break;
+
+		state->m_Regs[EB7] |= 0x20;    /* CAL_ForceSrce = 1 */
+		status = UpdateReg(state, EB7);
+		if (status < 0)
+			break;
+
+		state->m_Regs[EB14] = 0; /* RFC_Cprog = 0 */
+		status = UpdateReg(state, EB14);
+		if (status < 0)
+			break;
+
+		state->m_Regs[EB20] &= ~0x20;  /* ForceLock = 0; */
+		status = UpdateReg(state, EB20);
+		if (status < 0)
+			break;
+
+		state->m_Regs[EP4] |= 0x03;  /* CAL_Mode = 3 */
+		status = UpdateRegs(state, EP4, EP5);
+		if (status < 0)
+			break;
+
+		status = CalcCalPLL(state, freq);
+		if (status < 0)
+			break;
+		status = CalcMainPLL(state, freq + 1000000);
+		if (status < 0)
+			break;
+
+		msleep(5);
+		status = UpdateReg(state, EP2);
+		if (status < 0)
+			break;
+		status = UpdateReg(state, EP1);
+		if (status < 0)
+			break;
+		status = UpdateReg(state, EP2);
+		if (status < 0)
+			break;
+		status = UpdateReg(state, EP1);
+		if (status < 0)
+			break;
+
+		state->m_Regs[EB4] &= ~0x20;    /* LO_ForceSrce = 0 */
+		status = UpdateReg(state, EB4);
+		if (status < 0)
+			break;
+
+		state->m_Regs[EB7] &= ~0x20;    /* CAL_ForceSrce = 0 */
+		status = UpdateReg(state, EB7);
+		if (status < 0)
+			break;
+		msleep(10);
+
+		state->m_Regs[EB20] |= 0x20;  /* ForceLock = 1; */
+		status = UpdateReg(state, EB20);
+		if (status < 0)
+			break;
+		msleep(60);
+
+		state->m_Regs[EP4] &= ~0x03;  /* CAL_Mode = 0 */
+		state->m_Regs[EP3] &= ~0x40; /* SM_LT = 0 */
+		state->m_Regs[EB18] &= ~0x03;  /* AGC1_Gain = 0 */
+		status = UpdateReg(state, EB18);
+		if (status < 0)
+			break;
+		status = UpdateRegs(state, EP3, EP4);
+		if (status < 0)
+			break;
+		status = UpdateReg(state, EP1);
+		if (status < 0)
+			break;
+
+		status = ReadExtented(state, Regs);
+		if (status < 0)
+			break;
+
+		*pCprog = Regs[EB14];
+
+	} while (0);
+	return status;
+}
+
+static int RFTrackingFiltersInit(struct tda_state *state,
+				 u8 RFBand)
+{
+	int status = 0;
+
+	u32   RF1 = m_RF_Band_Map[RFBand].m_RF1_Default;
+	u32   RF2 = m_RF_Band_Map[RFBand].m_RF2_Default;
+	u32   RF3 = m_RF_Band_Map[RFBand].m_RF3_Default;
+	bool    bcal = false;
+
+	s32    Cprog_cal1 = 0;
+	s32    Cprog_table1 = 0;
+	s32    Cprog_cal2 = 0;
+	s32    Cprog_table2 = 0;
+	s32    Cprog_cal3 = 0;
+	s32    Cprog_table3 = 0;
+
+	state->m_RF_A1[RFBand] = 0;
+	state->m_RF_B1[RFBand] = 0;
+	state->m_RF_A2[RFBand] = 0;
+	state->m_RF_B2[RFBand] = 0;
+
+	do {
+		status = PowerScan(state, RFBand, RF1, &RF1, &bcal);
+		if (status < 0)
+			break;
+		if (bcal) {
+			status = CalibrateRF(state, RFBand, RF1, &Cprog_cal1);
+			if (status < 0)
+				break;
+		}
+		SearchMap2(m_RF_Cal_Map, RF1, &Cprog_table1);
+		if (!bcal)
+			Cprog_cal1 = Cprog_table1;
+		state->m_RF_B1[RFBand] = Cprog_cal1 - Cprog_table1;
+		/* state->m_RF_A1[RF_Band] = ???? */
+
+		if (RF2 == 0)
+			break;
+
+		status = PowerScan(state, RFBand, RF2, &RF2, &bcal);
+		if (status < 0)
+			break;
+		if (bcal) {
+			status = CalibrateRF(state, RFBand, RF2, &Cprog_cal2);
+			if (status < 0)
+				break;
+		}
+		SearchMap2(m_RF_Cal_Map, RF2, &Cprog_table2);
+		if (!bcal)
+			Cprog_cal2 = Cprog_table2;
+
+		state->m_RF_A1[RFBand] =
+			(Cprog_cal2 - Cprog_table2 - Cprog_cal1 + Cprog_table1) /
+			((s32)(RF2) - (s32)(RF1));
+
+		if (RF3 == 0)
+			break;
+
+		status = PowerScan(state, RFBand, RF3, &RF3, &bcal);
+		if (status < 0)
+			break;
+		if (bcal) {
+			status = CalibrateRF(state, RFBand, RF3, &Cprog_cal3);
+			if (status < 0)
+				break;
+		}
+		SearchMap2(m_RF_Cal_Map, RF3, &Cprog_table3);
+		if (!bcal)
+			Cprog_cal3 = Cprog_table3;
+		state->m_RF_A2[RFBand] = (Cprog_cal3 - Cprog_table3 - Cprog_cal2 + Cprog_table2) / ((s32)(RF3) - (s32)(RF2));
+		state->m_RF_B2[RFBand] = Cprog_cal2 - Cprog_table2;
+
+	} while (0);
+
+	state->m_RF1[RFBand] = RF1;
+	state->m_RF2[RFBand] = RF2;
+	state->m_RF3[RFBand] = RF3;
+
+#if 0
+	printk(KERN_ERR "tda18271c2dd: %s %d RF1 = %d A1 = %d B1 = %d RF2 = %d A2 = %d B2 = %d RF3 = %d\n", __func__,
+	       RFBand, RF1, state->m_RF_A1[RFBand], state->m_RF_B1[RFBand], RF2,
+	       state->m_RF_A2[RFBand], state->m_RF_B2[RFBand], RF3);
+#endif
+
+	return status;
+}
+
+static int PowerScan(struct tda_state *state,
+		     u8 RFBand, u32 RF_in, u32 *pRF_Out, bool *pbcal)
+{
+	int status = 0;
+	do {
+		u8   Gain_Taper = 0;
+		s32  RFC_Cprog = 0;
+		u8   CID_Target = 0;
+		u8   CountLimit = 0;
+		u32  freq_MainPLL;
+		u8   Regs[NUM_REGS];
+		u8   CID_Gain;
+		s32  Count = 0;
+		int  sign  = 1;
+		bool wait = false;
+
+		if (!(SearchMap2(m_RF_Cal_Map, RF_in, &RFC_Cprog) &&
+		      SearchMap1(m_GainTaper_Map, RF_in, &Gain_Taper) &&
+		      SearchMap3(m_CID_Target_Map, RF_in, &CID_Target, &CountLimit))) {
+
+			printk(KERN_ERR "tda18271c2dd: %s Search map failed\n", __func__);
+			return -EINVAL;
+		}
+
+		state->m_Regs[EP2] = (RFBand << 5) | Gain_Taper;
+		state->m_Regs[EB14] = (RFC_Cprog);
+		status = UpdateReg(state, EP2);
+		if (status < 0)
+			break;
+		status = UpdateReg(state, EB14);
+		if (status < 0)
+			break;
+
+		freq_MainPLL = RF_in + 1000000;
+		status = CalcMainPLL(state, freq_MainPLL);
+		if (status < 0)
+			break;
+		msleep(5);
+		state->m_Regs[EP4] = (state->m_Regs[EP4] & ~0x03) | 1;    /* CAL_mode = 1 */
+		status = UpdateReg(state, EP4);
+		if (status < 0)
+			break;
+		status = UpdateReg(state, EP2);  /* Launch power measurement */
+		if (status < 0)
+			break;
+		status = ReadExtented(state, Regs);
+		if (status < 0)
+			break;
+		CID_Gain = Regs[EB10] & 0x3F;
+		state->m_Regs[ID] = Regs[ID];  /* Chip version, (needed for C1 workarround in CalibrateRF) */
+
+		*pRF_Out = RF_in;
+
+		while (CID_Gain < CID_Target) {
+			freq_MainPLL = RF_in + sign * Count + 1000000;
+			status = CalcMainPLL(state, freq_MainPLL);
+			if (status < 0)
+				break;
+			msleep(wait ? 5 : 1);
+			wait = false;
+			status = UpdateReg(state, EP2);  /* Launch power measurement */
+			if (status < 0)
+				break;
+			status = ReadExtented(state, Regs);
+			if (status < 0)
+				break;
+			CID_Gain = Regs[EB10] & 0x3F;
+			Count += 200000;
+
+			if (Count < CountLimit * 100000)
+				continue;
+			if (sign < 0)
+				break;
+
+			sign = -sign;
+			Count = 200000;
+			wait = true;
+		}
+		status = status;
+		if (status < 0)
+			break;
+		if (CID_Gain >= CID_Target) {
+			*pbcal = true;
+			*pRF_Out = freq_MainPLL - 1000000;
+		} else
+			*pbcal = false;
+	} while (0);
+
+	return status;
+}
+
+static int PowerScanInit(struct tda_state *state)
+{
+	int status = 0;
+	do {
+		state->m_Regs[EP3] = (state->m_Regs[EP3] & ~0x1F) | 0x12;
+		state->m_Regs[EP4] = (state->m_Regs[EP4] & ~0x1F); /* If level = 0, Cal mode = 0 */
+		status = UpdateRegs(state, EP3, EP4);
+		if (status < 0)
+			break;
+		state->m_Regs[EB18] = (state->m_Regs[EB18] & ~0x03); /* AGC 1 Gain = 0 */
+		status = UpdateReg(state, EB18);
+		if (status < 0)
+			break;
+		state->m_Regs[EB21] = (state->m_Regs[EB21] & ~0x03); /* AGC 2 Gain = 0 (Datasheet = 3) */
+		state->m_Regs[EB23] = (state->m_Regs[EB23] | 0x06); /* ForceLP_Fc2_En = 1, LPFc[2] = 1 */
+		status = UpdateRegs(state, EB21, EB23);
+		if (status < 0)
+			break;
+	} while (0);
+	return status;
+}
+
+static int CalcRFFilterCurve(struct tda_state *state)
+{
+	int status = 0;
+	do {
+		msleep(200);      /* Temperature stabilisation */
+		status = PowerScanInit(state);
+		if (status < 0)
+			break;
+		status = RFTrackingFiltersInit(state, 0);
+		if (status < 0)
+			break;
+		status = RFTrackingFiltersInit(state, 1);
+		if (status < 0)
+			break;
+		status = RFTrackingFiltersInit(state, 2);
+		if (status < 0)
+			break;
+		status = RFTrackingFiltersInit(state, 3);
+		if (status < 0)
+			break;
+		status = RFTrackingFiltersInit(state, 4);
+		if (status < 0)
+			break;
+		status = RFTrackingFiltersInit(state, 5);
+		if (status < 0)
+			break;
+		status = RFTrackingFiltersInit(state, 6);
+		if (status < 0)
+			break;
+		status = ThermometerRead(state, &state->m_TMValue_RFCal); /* also switches off Cal mode !!! */
+		if (status < 0)
+			break;
+	} while (0);
+
+	return status;
+}
+
+static int FixedContentsI2CUpdate(struct tda_state *state)
+{
+	static u8 InitRegs[] = {
+		0x08, 0x80, 0xC6,
+		0xDF, 0x16, 0x60, 0x80,
+		0x80, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00,
+		0xFC, 0x01, 0x84, 0x41,
+		0x01, 0x84, 0x40, 0x07,
+		0x00, 0x00, 0x96, 0x3F,
+		0xC1, 0x00, 0x8F, 0x00,
+		0x00, 0x8C, 0x00, 0x20,
+		0xB3, 0x48, 0xB0,
+	};
+	int status = 0;
+	memcpy(&state->m_Regs[TM], InitRegs, EB23 - TM + 1);
+	do {
+		status = UpdateRegs(state, TM, EB23);
+		if (status < 0)
+			break;
+
+		/* AGC1 gain setup */
+		state->m_Regs[EB17] = 0x00;
+		status = UpdateReg(state, EB17);
+		if (status < 0)
+			break;
+		state->m_Regs[EB17] = 0x03;
+		status = UpdateReg(state, EB17);
+		if (status < 0)
+			break;
+		state->m_Regs[EB17] = 0x43;
+		status = UpdateReg(state, EB17);
+		if (status < 0)
+			break;
+		state->m_Regs[EB17] = 0x4C;
+		status = UpdateReg(state, EB17);
+		if (status < 0)
+			break;
+
+		/* IRC Cal Low band */
+		state->m_Regs[EP3] = 0x1F;
+		state->m_Regs[EP4] = 0x66;
+		state->m_Regs[EP5] = 0x81;
+		state->m_Regs[CPD] = 0xCC;
+		state->m_Regs[CD1] = 0x6C;
+		state->m_Regs[CD2] = 0x00;
+		state->m_Regs[CD3] = 0x00;
+		state->m_Regs[MPD] = 0xC5;
+		state->m_Regs[MD1] = 0x77;
+		state->m_Regs[MD2] = 0x08;
+		state->m_Regs[MD3] = 0x00;
+		status = UpdateRegs(state, EP2, MD3); /* diff between sw and datasheet (ep3-md3) */
+		if (status < 0)
+			break;
+
+#if 0
+		state->m_Regs[EB4] = 0x61;          /* missing in sw */
+		status = UpdateReg(state, EB4);
+		if (status < 0)
+			break;
+		msleep(1);
+		state->m_Regs[EB4] = 0x41;
+		status = UpdateReg(state, EB4);
+		if (status < 0)
+			break;
+#endif
+
+		msleep(5);
+		status = UpdateReg(state, EP1);
+		if (status < 0)
+			break;
+		msleep(5);
+
+		state->m_Regs[EP5] = 0x85;
+		state->m_Regs[CPD] = 0xCB;
+		state->m_Regs[CD1] = 0x66;
+		state->m_Regs[CD2] = 0x70;
+		status = UpdateRegs(state, EP3, CD3);
+		if (status < 0)
+			break;
+		msleep(5);
+		status = UpdateReg(state, EP2);
+		if (status < 0)
+			break;
+		msleep(30);
+
+		/* IRC Cal mid band */
+		state->m_Regs[EP5] = 0x82;
+		state->m_Regs[CPD] = 0xA8;
+		state->m_Regs[CD2] = 0x00;
+		state->m_Regs[MPD] = 0xA1; /* Datasheet = 0xA9 */
+		state->m_Regs[MD1] = 0x73;
+		state->m_Regs[MD2] = 0x1A;
+		status = UpdateRegs(state, EP3, MD3);
+		if (status < 0)
+			break;
+
+		msleep(5);
+		status = UpdateReg(state, EP1);
+		if (status < 0)
+			break;
+		msleep(5);
+
+		state->m_Regs[EP5] = 0x86;
+		state->m_Regs[CPD] = 0xA8;
+		state->m_Regs[CD1] = 0x66;
+		state->m_Regs[CD2] = 0xA0;
+		status = UpdateRegs(state, EP3, CD3);
+		if (status < 0)
+			break;
+		msleep(5);
+		status = UpdateReg(state, EP2);
+		if (status < 0)
+			break;
+		msleep(30);
+
+		/* IRC Cal high band */
+		state->m_Regs[EP5] = 0x83;
+		state->m_Regs[CPD] = 0x98;
+		state->m_Regs[CD1] = 0x65;
+		state->m_Regs[CD2] = 0x00;
+		state->m_Regs[MPD] = 0x91;  /* Datasheet = 0x91 */
+		state->m_Regs[MD1] = 0x71;
+		state->m_Regs[MD2] = 0xCD;
+		status = UpdateRegs(state, EP3, MD3);
+		if (status < 0)
+			break;
+		msleep(5);
+		status = UpdateReg(state, EP1);
+		if (status < 0)
+			break;
+		msleep(5);
+		state->m_Regs[EP5] = 0x87;
+		state->m_Regs[CD1] = 0x65;
+		state->m_Regs[CD2] = 0x50;
+		status = UpdateRegs(state, EP3, CD3);
+		if (status < 0)
+			break;
+		msleep(5);
+		status = UpdateReg(state, EP2);
+		if (status < 0)
+			break;
+		msleep(30);
+
+		/* Back to normal */
+		state->m_Regs[EP4] = 0x64;
+		status = UpdateReg(state, EP4);
+		if (status < 0)
+			break;
+		status = UpdateReg(state, EP1);
+		if (status < 0)
+			break;
+
+	} while (0);
+	return status;
+}
+
+static int InitCal(struct tda_state *state)
+{
+	int status = 0;
+
+	do {
+		status = FixedContentsI2CUpdate(state);
+		if (status < 0)
+			break;
+		status = CalcRFFilterCurve(state);
+		if (status < 0)
+			break;
+		status = StandBy(state);
+		if (status < 0)
+			break;
+		/* m_bInitDone = true; */
+	} while (0);
+	return status;
+};
+
+static int RFTrackingFiltersCorrection(struct tda_state *state,
+				       u32 Frequency)
+{
+	int status = 0;
+	s32 Cprog_table;
+	u8 RFBand;
+	u8 dCoverdT;
+
+	if (!SearchMap2(m_RF_Cal_Map, Frequency, &Cprog_table) ||
+	    !SearchMap4(m_RF_Band_Map, Frequency, &RFBand) ||
+	    !SearchMap1(m_RF_Cal_DC_Over_DT_Map, Frequency, &dCoverdT))
+
+		return -EINVAL;
+
+	do {
+		u8 TMValue_Current;
+		u32   RF1 = state->m_RF1[RFBand];
+		u32   RF2 = state->m_RF1[RFBand];
+		u32   RF3 = state->m_RF1[RFBand];
+		s32    RF_A1 = state->m_RF_A1[RFBand];
+		s32    RF_B1 = state->m_RF_B1[RFBand];
+		s32    RF_A2 = state->m_RF_A2[RFBand];
+		s32    RF_B2 = state->m_RF_B2[RFBand];
+		s32 Capprox = 0;
+		int TComp;
+
+		state->m_Regs[EP3] &= ~0xE0;  /* Power up */
+		status = UpdateReg(state, EP3);
+		if (status < 0)
+			break;
+
+		status = ThermometerRead(state, &TMValue_Current);
+		if (status < 0)
+			break;
+
+		if (RF3 == 0 || Frequency < RF2)
+			Capprox = RF_A1 * ((s32)(Frequency) - (s32)(RF1)) + RF_B1 + Cprog_table;
+		else
+			Capprox = RF_A2 * ((s32)(Frequency) - (s32)(RF2)) + RF_B2 + Cprog_table;
+
+		TComp = (int)(dCoverdT) * ((int)(TMValue_Current) - (int)(state->m_TMValue_RFCal))/1000;
+
+		Capprox += TComp;
+
+		if (Capprox < 0)
+			Capprox = 0;
+		else if (Capprox > 255)
+			Capprox = 255;
+
+
+		/* TODO Temperature compensation. There is defenitely a scale factor */
+		/*      missing in the datasheet, so leave it out for now.           */
+		state->m_Regs[EB14] = Capprox;
+
+		status = UpdateReg(state, EB14);
+		if (status < 0)
+			break;
+
+	} while (0);
+	return status;
+}
+
+static int ChannelConfiguration(struct tda_state *state,
+				u32 Frequency, int Standard)
+{
+
+	s32 IntermediateFrequency = m_StandardTable[Standard].m_IFFrequency;
+	int status = 0;
+
+	u8 BP_Filter = 0;
+	u8 RF_Band = 0;
+	u8 GainTaper = 0;
+	u8 IR_Meas = 0;
+
+	state->IF = IntermediateFrequency;
+	/* printk("tda18271c2dd: %s Freq = %d Standard = %d IF = %d\n", __func__, Frequency, Standard, IntermediateFrequency); */
+	/* get values from tables */
+
+	if (!(SearchMap1(m_BP_Filter_Map, Frequency, &BP_Filter) &&
+	       SearchMap1(m_GainTaper_Map, Frequency, &GainTaper) &&
+	       SearchMap1(m_IR_Meas_Map, Frequency, &IR_Meas) &&
+	       SearchMap4(m_RF_Band_Map, Frequency, &RF_Band))) {
+
+		printk(KERN_ERR "tda18271c2dd: %s SearchMap failed\n", __func__);
+		return -EINVAL;
+	}
+
+	do {
+		state->m_Regs[EP3] = (state->m_Regs[EP3] & ~0x1F) | m_StandardTable[Standard].m_EP3_4_0;
+		state->m_Regs[EP3] &= ~0x04;   /* switch RFAGC to high speed mode */
+
+		/* m_EP4 default for XToutOn, CAL_Mode (0) */
+		state->m_Regs[EP4] = state->m_EP4 | ((Standard > HF_AnalogMax) ? state->m_IFLevelDigital : state->m_IFLevelAnalog);
+		/* state->m_Regs[EP4] = state->m_EP4 | state->m_IFLevelDigital; */
+		if (Standard <= HF_AnalogMax)
+			state->m_Regs[EP4] = state->m_EP4 | state->m_IFLevelAnalog;
+		else if (Standard <= HF_ATSC)
+			state->m_Regs[EP4] = state->m_EP4 | state->m_IFLevelDVBT;
+		else if (Standard <= HF_DVBC)
+			state->m_Regs[EP4] = state->m_EP4 | state->m_IFLevelDVBC;
+		else
+			state->m_Regs[EP4] = state->m_EP4 | state->m_IFLevelDigital;
+
+		if ((Standard == HF_FM_Radio) && state->m_bFMInput)
+			state->m_Regs[EP4] |= 80;
+
+		state->m_Regs[MPD] &= ~0x80;
+		if (Standard > HF_AnalogMax)
+			state->m_Regs[MPD] |= 0x80; /* Add IF_notch for digital */
+
+		state->m_Regs[EB22] = m_StandardTable[Standard].m_EB22;
+
+		/* Note: This is missing from flowchart in TDA18271 specification ( 1.5 MHz cutoff for FM ) */
+		if (Standard == HF_FM_Radio)
+			state->m_Regs[EB23] |=  0x06; /* ForceLP_Fc2_En = 1, LPFc[2] = 1 */
+		else
+			state->m_Regs[EB23] &= ~0x06; /* ForceLP_Fc2_En = 0, LPFc[2] = 0 */
+
+		status = UpdateRegs(state, EB22, EB23);
+		if (status < 0)
+			break;
+
+		state->m_Regs[EP1] = (state->m_Regs[EP1] & ~0x07) | 0x40 | BP_Filter;   /* Dis_Power_level = 1, Filter */
+		state->m_Regs[EP5] = (state->m_Regs[EP5] & ~0x07) | IR_Meas;
+		state->m_Regs[EP2] = (RF_Band << 5) | GainTaper;
+
+		state->m_Regs[EB1] = (state->m_Regs[EB1] & ~0x07) |
+			(state->m_bMaster ? 0x04 : 0x00); /* CALVCO_FortLOn = MS */
+		/* AGC1_always_master = 0 */
+		/* AGC_firstn = 0 */
+		status = UpdateReg(state, EB1);
+		if (status < 0)
+			break;
+
+		if (state->m_bMaster) {
+			status = CalcMainPLL(state, Frequency + IntermediateFrequency);
+			if (status < 0)
+				break;
+			status = UpdateRegs(state, TM, EP5);
+			if (status < 0)
+				break;
+			state->m_Regs[EB4] |= 0x20;    /* LO_forceSrce = 1 */
+			status = UpdateReg(state, EB4);
+			if (status < 0)
+				break;
+			msleep(1);
+			state->m_Regs[EB4] &= ~0x20;   /* LO_forceSrce = 0 */
+			status = UpdateReg(state, EB4);
+			if (status < 0)
+				break;
+		} else {
+			u8 PostDiv = 0;
+			u8 Div;
+			status = CalcCalPLL(state, Frequency + IntermediateFrequency);
+			if (status < 0)
+				break;
+
+			SearchMap3(m_Cal_PLL_Map, Frequency + IntermediateFrequency, &PostDiv, &Div);
+			state->m_Regs[MPD] = (state->m_Regs[MPD] & ~0x7F) | (PostDiv & 0x77);
+			status = UpdateReg(state, MPD);
+			if (status < 0)
+				break;
+			status = UpdateRegs(state, TM, EP5);
+			if (status < 0)
+				break;
+
+			state->m_Regs[EB7] |= 0x20;    /* CAL_forceSrce = 1 */
+			status = UpdateReg(state, EB7);
+			if (status < 0)
+				break;
+			msleep(1);
+			state->m_Regs[EB7] &= ~0x20;   /* CAL_forceSrce = 0 */
+			status = UpdateReg(state, EB7);
+			if (status < 0)
+				break;
+		}
+		msleep(20);
+		if (Standard != HF_FM_Radio)
+			state->m_Regs[EP3] |= 0x04;    /* RFAGC to normal mode */
+		status = UpdateReg(state, EP3);
+		if (status < 0)
+			break;
+
+	} while (0);
+	return status;
+}
+
+static int sleep(struct dvb_frontend *fe)
+{
+	struct tda_state *state = fe->tuner_priv;
+
+	StandBy(state);
+	return 0;
+}
+
+static int init(struct dvb_frontend *fe)
+{
+	return 0;
+}
+
+static int release(struct dvb_frontend *fe)
+{
+	kfree(fe->tuner_priv);
+	fe->tuner_priv = NULL;
+	return 0;
+}
+
+
+static int set_params(struct dvb_frontend *fe)
+{
+	struct tda_state *state = fe->tuner_priv;
+	int status = 0;
+	int Standard;
+	u32 bw = fe->dtv_property_cache.bandwidth_hz;
+	u32 delsys  = fe->dtv_property_cache.delivery_system;
+
+	state->m_Frequency = fe->dtv_property_cache.frequency;
+
+	switch (delsys) {
+	case  SYS_DVBT:
+	case  SYS_DVBT2:
+		switch (bw) {
+		case 6000000:
+			Standard = HF_DVBT_6MHZ;
+			break;
+		case 7000000:
+			Standard = HF_DVBT_7MHZ;
+			break;
+		case 8000000:
+			Standard = HF_DVBT_8MHZ;
+			break;
+		default:
+			return -EINVAL;
+		}
+	case SYS_DVBC_ANNEX_A:
+	case SYS_DVBC_ANNEX_C:
+		if (bw <= 6000000)
+			Standard = HF_DVBC_6MHZ;
+		else if (bw <= 7000000)
+			Standard = HF_DVBC_7MHZ;
+		else
+			Standard = HF_DVBC_8MHZ;
+		break;
+	default:
+		return -EINVAL;
+	}
+	do {
+		status = RFTrackingFiltersCorrection(state, state->m_Frequency);
+		if (status < 0)
+			break;
+		status = ChannelConfiguration(state, state->m_Frequency,
+					      Standard);
+		if (status < 0)
+			break;
+
+		msleep(state->m_SettlingTime);  /* Allow AGC's to settle down */
+	} while (0);
+	return status;
+}
+
+#if 0
+static int GetSignalStrength(s32 *pSignalStrength, u32 RFAgc, u32 IFAgc)
+{
+	if (IFAgc < 500) {
+		/* Scale this from 0 to 50000 */
+		*pSignalStrength = IFAgc * 100;
+	} else {
+		/* Scale range 500-1500 to 50000-80000 */
+		*pSignalStrength = 50000 + (IFAgc - 500) * 30;
+	}
+
+	return 0;
+}
+#endif
+
+static int get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+	struct tda_state *state = fe->tuner_priv;
+
+	*frequency = state->IF;
+	return 0;
+}
+
+static int get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
+{
+	/* struct tda_state *state = fe->tuner_priv; */
+	/* *bandwidth = priv->bandwidth; */
+	return 0;
+}
+
+
+static struct dvb_tuner_ops tuner_ops = {
+	.info = {
+		.name = "NXP TDA18271C2D",
+		.frequency_min  =  47125000,
+		.frequency_max  = 865000000,
+		.frequency_step =     62500
+	},
+	.init              = init,
+	.sleep             = sleep,
+	.set_params        = set_params,
+	.release           = release,
+	.get_if_frequency  = get_if_frequency,
+	.get_bandwidth     = get_bandwidth,
+};
+
+struct dvb_frontend *tda18271c2dd_attach(struct dvb_frontend *fe,
+					 struct i2c_adapter *i2c, u8 adr)
+{
+	struct tda_state *state;
+
+	state = kzalloc(sizeof(struct tda_state), GFP_KERNEL);
+	if (!state)
+		return NULL;
+
+	fe->tuner_priv = state;
+	state->adr = adr;
+	state->i2c = i2c;
+	memcpy(&fe->ops.tuner_ops, &tuner_ops, sizeof(struct dvb_tuner_ops));
+	reset(state);
+	InitCal(state);
+
+	return fe;
+}
+EXPORT_SYMBOL_GPL(tda18271c2dd_attach);
+
+MODULE_DESCRIPTION("TDA18271C2 driver");
+MODULE_AUTHOR("DD");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb-frontends/tda18271c2dd.h b/drivers/media/dvb-frontends/tda18271c2dd.h
new file mode 100644
index 0000000..1389c74
--- /dev/null
+++ b/drivers/media/dvb-frontends/tda18271c2dd.h
@@ -0,0 +1,16 @@
+#ifndef _TDA18271C2DD_H_
+#define _TDA18271C2DD_H_
+#if defined(CONFIG_DVB_TDA18271C2DD) || (defined(CONFIG_DVB_TDA18271C2DD_MODULE) \
+        && defined(MODULE))
+struct dvb_frontend *tda18271c2dd_attach(struct dvb_frontend *fe,
+					 struct i2c_adapter *i2c, u8 adr);
+#else
+static inline struct dvb_frontend *tda18271c2dd_attach(struct dvb_frontend *fe,
+					 struct i2c_adapter *i2c, u8 adr)
+{
+        printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+        return NULL;
+}
+#endif
+
+#endif
diff --git a/drivers/media/dvb-frontends/tda18271c2dd_maps.h b/drivers/media/dvb-frontends/tda18271c2dd_maps.h
new file mode 100644
index 0000000..b87661b
--- /dev/null
+++ b/drivers/media/dvb-frontends/tda18271c2dd_maps.h
@@ -0,0 +1,814 @@
+enum HF_S {
+	HF_None = 0, HF_B, HF_DK, HF_G, HF_I, HF_L, HF_L1, HF_MN, HF_FM_Radio,
+	HF_AnalogMax, HF_DVBT_6MHZ, HF_DVBT_7MHZ, HF_DVBT_8MHZ,
+	HF_DVBT, HF_ATSC,  HF_DVBC_6MHZ,  HF_DVBC_7MHZ,
+	HF_DVBC_8MHZ, HF_DVBC
+};
+
+struct SStandardParam m_StandardTable[] = {
+	{       0,        0, 0x00, 0x00 },    /* HF_None */
+	{ 6000000,  7000000, 0x1D, 0x2C },    /* HF_B, */
+	{ 6900000,  8000000, 0x1E, 0x2C },    /* HF_DK, */
+	{ 7100000,  8000000, 0x1E, 0x2C },    /* HF_G, */
+	{ 7250000,  8000000, 0x1E, 0x2C },    /* HF_I, */
+	{ 6900000,  8000000, 0x1E, 0x2C },    /* HF_L, */
+	{ 1250000,  8000000, 0x1E, 0x2C },    /* HF_L1, */
+	{ 5400000,  6000000, 0x1C, 0x2C },    /* HF_MN, */
+	{ 1250000,   500000, 0x18, 0x2C },    /* HF_FM_Radio, */
+	{       0,        0, 0x00, 0x00 },    /* HF_AnalogMax (Unused) */
+	{ 3300000,  6000000, 0x1C, 0x58 },    /* HF_DVBT_6MHZ */
+	{ 3500000,  7000000, 0x1C, 0x37 },    /* HF_DVBT_7MHZ */
+	{ 4000000,  8000000, 0x1D, 0x37 },    /* HF_DVBT_8MHZ */
+	{       0,        0, 0x00, 0x00 },    /* HF_DVBT (Unused) */
+	{ 5000000,  6000000, 0x1C, 0x37 },    /* HF_ATSC  (center = 3.25 MHz) */
+	{ 4000000,  6000000, 0x1D, 0x58 },    /* HF_DVBC_6MHZ (Chicago) */
+	{ 4500000,  7000000, 0x1E, 0x37 },    /* HF_DVBC_7MHZ (not documented by NXP) */
+	{ 5000000,  8000000, 0x1F, 0x37 },    /* HF_DVBC_8MHZ */
+	{       0,        0, 0x00, 0x00 },    /* HF_DVBC (Unused) */
+};
+
+struct SMap  m_BP_Filter_Map[] = {
+	{   62000000,  0x00 },
+	{   84000000,  0x01 },
+	{  100000000,  0x02 },
+	{  140000000,  0x03 },
+	{  170000000,  0x04 },
+	{  180000000,  0x05 },
+	{  865000000,  0x06 },
+	{          0,  0x00 },    /* Table End */
+};
+
+static struct SMapI m_RF_Cal_Map[] = {
+	{   41000000,  0x0F },
+	{   43000000,  0x1C },
+	{   45000000,  0x2F },
+	{   46000000,  0x39 },
+	{   47000000,  0x40 },
+	{   47900000,  0x50 },
+	{   49100000,  0x16 },
+	{   50000000,  0x18 },
+	{   51000000,  0x20 },
+	{   53000000,  0x28 },
+	{   55000000,  0x2B },
+	{   56000000,  0x32 },
+	{   57000000,  0x35 },
+	{   58000000,  0x3E },
+	{   59000000,  0x43 },
+	{   60000000,  0x4E },
+	{   61100000,  0x55 },
+	{   63000000,  0x0F },
+	{   64000000,  0x11 },
+	{   65000000,  0x12 },
+	{   66000000,  0x15 },
+	{   67000000,  0x16 },
+	{   68000000,  0x17 },
+	{   70000000,  0x19 },
+	{   71000000,  0x1C },
+	{   72000000,  0x1D },
+	{   73000000,  0x1F },
+	{   74000000,  0x20 },
+	{   75000000,  0x21 },
+	{   76000000,  0x24 },
+	{   77000000,  0x25 },
+	{   78000000,  0x27 },
+	{   80000000,  0x28 },
+	{   81000000,  0x29 },
+	{   82000000,  0x2D },
+	{   83000000,  0x2E },
+	{   84000000,  0x2F },
+	{   85000000,  0x31 },
+	{   86000000,  0x33 },
+	{   87000000,  0x34 },
+	{   88000000,  0x35 },
+	{   89000000,  0x37 },
+	{   90000000,  0x38 },
+	{   91000000,  0x39 },
+	{   93000000,  0x3C },
+	{   94000000,  0x3E },
+	{   95000000,  0x3F },
+	{   96000000,  0x40 },
+	{   97000000,  0x42 },
+	{   99000000,  0x45 },
+	{  100000000,  0x46 },
+	{  102000000,  0x48 },
+	{  103000000,  0x4A },
+	{  105000000,  0x4D },
+	{  106000000,  0x4E },
+	{  107000000,  0x50 },
+	{  108000000,  0x51 },
+	{  110000000,  0x54 },
+	{  111000000,  0x56 },
+	{  112000000,  0x57 },
+	{  113000000,  0x58 },
+	{  114000000,  0x59 },
+	{  115000000,  0x5C },
+	{  116000000,  0x5D },
+	{  117000000,  0x5F },
+	{  119000000,  0x60 },
+	{  120000000,  0x64 },
+	{  121000000,  0x65 },
+	{  122000000,  0x66 },
+	{  123000000,  0x68 },
+	{  124000000,  0x69 },
+	{  125000000,  0x6C },
+	{  126000000,  0x6D },
+	{  127000000,  0x6E },
+	{  128000000,  0x70 },
+	{  129000000,  0x71 },
+	{  130000000,  0x75 },
+	{  131000000,  0x77 },
+	{  132000000,  0x78 },
+	{  133000000,  0x7B },
+	{  134000000,  0x7E },
+	{  135000000,  0x81 },
+	{  136000000,  0x82 },
+	{  137000000,  0x87 },
+	{  138000000,  0x88 },
+	{  139000000,  0x8D },
+	{  140000000,  0x8E },
+	{  141000000,  0x91 },
+	{  142000000,  0x95 },
+	{  143000000,  0x9A },
+	{  144000000,  0x9D },
+	{  145000000,  0xA1 },
+	{  146000000,  0xA2 },
+	{  147000000,  0xA4 },
+	{  148000000,  0xA9 },
+	{  149000000,  0xAE },
+	{  150000000,  0xB0 },
+	{  151000000,  0xB1 },
+	{  152000000,  0xB7 },
+	{  152600000,  0xBD },
+	{  154000000,  0x20 },
+	{  155000000,  0x22 },
+	{  156000000,  0x24 },
+	{  157000000,  0x25 },
+	{  158000000,  0x27 },
+	{  159000000,  0x29 },
+	{  160000000,  0x2C },
+	{  161000000,  0x2D },
+	{  163000000,  0x2E },
+	{  164000000,  0x2F },
+	{  164700000,  0x30 },
+	{  166000000,  0x11 },
+	{  167000000,  0x12 },
+	{  168000000,  0x13 },
+	{  169000000,  0x14 },
+	{  170000000,  0x15 },
+	{  172000000,  0x16 },
+	{  173000000,  0x17 },
+	{  174000000,  0x18 },
+	{  175000000,  0x1A },
+	{  176000000,  0x1B },
+	{  178000000,  0x1D },
+	{  179000000,  0x1E },
+	{  180000000,  0x1F },
+	{  181000000,  0x20 },
+	{  182000000,  0x21 },
+	{  183000000,  0x22 },
+	{  184000000,  0x24 },
+	{  185000000,  0x25 },
+	{  186000000,  0x26 },
+	{  187000000,  0x27 },
+	{  188000000,  0x29 },
+	{  189000000,  0x2A },
+	{  190000000,  0x2C },
+	{  191000000,  0x2D },
+	{  192000000,  0x2E },
+	{  193000000,  0x2F },
+	{  194000000,  0x30 },
+	{  195000000,  0x33 },
+	{  196000000,  0x35 },
+	{  198000000,  0x36 },
+	{  200000000,  0x38 },
+	{  201000000,  0x3C },
+	{  202000000,  0x3D },
+	{  203500000,  0x3E },
+	{  206000000,  0x0E },
+	{  208000000,  0x0F },
+	{  212000000,  0x10 },
+	{  216000000,  0x11 },
+	{  217000000,  0x12 },
+	{  218000000,  0x13 },
+	{  220000000,  0x14 },
+	{  222000000,  0x15 },
+	{  225000000,  0x16 },
+	{  228000000,  0x17 },
+	{  231000000,  0x18 },
+	{  234000000,  0x19 },
+	{  235000000,  0x1A },
+	{  236000000,  0x1B },
+	{  237000000,  0x1C },
+	{  240000000,  0x1D },
+	{  242000000,  0x1E },
+	{  244000000,  0x1F },
+	{  247000000,  0x20 },
+	{  249000000,  0x21 },
+	{  252000000,  0x22 },
+	{  253000000,  0x23 },
+	{  254000000,  0x24 },
+	{  256000000,  0x25 },
+	{  259000000,  0x26 },
+	{  262000000,  0x27 },
+	{  264000000,  0x28 },
+	{  267000000,  0x29 },
+	{  269000000,  0x2A },
+	{  271000000,  0x2B },
+	{  273000000,  0x2C },
+	{  275000000,  0x2D },
+	{  277000000,  0x2E },
+	{  279000000,  0x2F },
+	{  282000000,  0x30 },
+	{  284000000,  0x31 },
+	{  286000000,  0x32 },
+	{  287000000,  0x33 },
+	{  290000000,  0x34 },
+	{  293000000,  0x35 },
+	{  295000000,  0x36 },
+	{  297000000,  0x37 },
+	{  300000000,  0x38 },
+	{  303000000,  0x39 },
+	{  305000000,  0x3A },
+	{  306000000,  0x3B },
+	{  307000000,  0x3C },
+	{  310000000,  0x3D },
+	{  312000000,  0x3E },
+	{  315000000,  0x3F },
+	{  318000000,  0x40 },
+	{  320000000,  0x41 },
+	{  323000000,  0x42 },
+	{  324000000,  0x43 },
+	{  325000000,  0x44 },
+	{  327000000,  0x45 },
+	{  331000000,  0x46 },
+	{  334000000,  0x47 },
+	{  337000000,  0x48 },
+	{  339000000,  0x49 },
+	{  340000000,  0x4A },
+	{  341000000,  0x4B },
+	{  343000000,  0x4C },
+	{  345000000,  0x4D },
+	{  349000000,  0x4E },
+	{  352000000,  0x4F },
+	{  353000000,  0x50 },
+	{  355000000,  0x51 },
+	{  357000000,  0x52 },
+	{  359000000,  0x53 },
+	{  361000000,  0x54 },
+	{  362000000,  0x55 },
+	{  364000000,  0x56 },
+	{  368000000,  0x57 },
+	{  370000000,  0x58 },
+	{  372000000,  0x59 },
+	{  375000000,  0x5A },
+	{  376000000,  0x5B },
+	{  377000000,  0x5C },
+	{  379000000,  0x5D },
+	{  382000000,  0x5E },
+	{  384000000,  0x5F },
+	{  385000000,  0x60 },
+	{  386000000,  0x61 },
+	{  388000000,  0x62 },
+	{  390000000,  0x63 },
+	{  393000000,  0x64 },
+	{  394000000,  0x65 },
+	{  396000000,  0x66 },
+	{  397000000,  0x67 },
+	{  398000000,  0x68 },
+	{  400000000,  0x69 },
+	{  402000000,  0x6A },
+	{  403000000,  0x6B },
+	{  407000000,  0x6C },
+	{  408000000,  0x6D },
+	{  409000000,  0x6E },
+	{  410000000,  0x6F },
+	{  411000000,  0x70 },
+	{  412000000,  0x71 },
+	{  413000000,  0x72 },
+	{  414000000,  0x73 },
+	{  417000000,  0x74 },
+	{  418000000,  0x75 },
+	{  420000000,  0x76 },
+	{  422000000,  0x77 },
+	{  423000000,  0x78 },
+	{  424000000,  0x79 },
+	{  427000000,  0x7A },
+	{  428000000,  0x7B },
+	{  429000000,  0x7D },
+	{  432000000,  0x7F },
+	{  434000000,  0x80 },
+	{  435000000,  0x81 },
+	{  436000000,  0x83 },
+	{  437000000,  0x84 },
+	{  438000000,  0x85 },
+	{  439000000,  0x86 },
+	{  440000000,  0x87 },
+	{  441000000,  0x88 },
+	{  442000000,  0x89 },
+	{  445000000,  0x8A },
+	{  446000000,  0x8B },
+	{  447000000,  0x8C },
+	{  448000000,  0x8E },
+	{  449000000,  0x8F },
+	{  450000000,  0x90 },
+	{  452000000,  0x91 },
+	{  453000000,  0x93 },
+	{  454000000,  0x94 },
+	{  456000000,  0x96 },
+	{  457800000,  0x98 },
+	{  461000000,  0x11 },
+	{  468000000,  0x12 },
+	{  472000000,  0x13 },
+	{  473000000,  0x14 },
+	{  474000000,  0x15 },
+	{  481000000,  0x16 },
+	{  486000000,  0x17 },
+	{  491000000,  0x18 },
+	{  498000000,  0x19 },
+	{  499000000,  0x1A },
+	{  501000000,  0x1B },
+	{  506000000,  0x1C },
+	{  511000000,  0x1D },
+	{  516000000,  0x1E },
+	{  520000000,  0x1F },
+	{  521000000,  0x20 },
+	{  525000000,  0x21 },
+	{  529000000,  0x22 },
+	{  533000000,  0x23 },
+	{  539000000,  0x24 },
+	{  541000000,  0x25 },
+	{  547000000,  0x26 },
+	{  549000000,  0x27 },
+	{  551000000,  0x28 },
+	{  556000000,  0x29 },
+	{  561000000,  0x2A },
+	{  563000000,  0x2B },
+	{  565000000,  0x2C },
+	{  569000000,  0x2D },
+	{  571000000,  0x2E },
+	{  577000000,  0x2F },
+	{  580000000,  0x30 },
+	{  582000000,  0x31 },
+	{  584000000,  0x32 },
+	{  588000000,  0x33 },
+	{  591000000,  0x34 },
+	{  596000000,  0x35 },
+	{  598000000,  0x36 },
+	{  603000000,  0x37 },
+	{  604000000,  0x38 },
+	{  606000000,  0x39 },
+	{  612000000,  0x3A },
+	{  615000000,  0x3B },
+	{  617000000,  0x3C },
+	{  621000000,  0x3D },
+	{  622000000,  0x3E },
+	{  625000000,  0x3F },
+	{  632000000,  0x40 },
+	{  633000000,  0x41 },
+	{  634000000,  0x42 },
+	{  642000000,  0x43 },
+	{  643000000,  0x44 },
+	{  647000000,  0x45 },
+	{  650000000,  0x46 },
+	{  652000000,  0x47 },
+	{  657000000,  0x48 },
+	{  661000000,  0x49 },
+	{  662000000,  0x4A },
+	{  665000000,  0x4B },
+	{  667000000,  0x4C },
+	{  670000000,  0x4D },
+	{  673000000,  0x4E },
+	{  676000000,  0x4F },
+	{  677000000,  0x50 },
+	{  681000000,  0x51 },
+	{  683000000,  0x52 },
+	{  686000000,  0x53 },
+	{  688000000,  0x54 },
+	{  689000000,  0x55 },
+	{  691000000,  0x56 },
+	{  695000000,  0x57 },
+	{  698000000,  0x58 },
+	{  703000000,  0x59 },
+	{  704000000,  0x5A },
+	{  705000000,  0x5B },
+	{  707000000,  0x5C },
+	{  710000000,  0x5D },
+	{  712000000,  0x5E },
+	{  717000000,  0x5F },
+	{  718000000,  0x60 },
+	{  721000000,  0x61 },
+	{  722000000,  0x62 },
+	{  723000000,  0x63 },
+	{  725000000,  0x64 },
+	{  727000000,  0x65 },
+	{  730000000,  0x66 },
+	{  732000000,  0x67 },
+	{  735000000,  0x68 },
+	{  740000000,  0x69 },
+	{  741000000,  0x6A },
+	{  742000000,  0x6B },
+	{  743000000,  0x6C },
+	{  745000000,  0x6D },
+	{  747000000,  0x6E },
+	{  748000000,  0x6F },
+	{  750000000,  0x70 },
+	{  752000000,  0x71 },
+	{  754000000,  0x72 },
+	{  757000000,  0x73 },
+	{  758000000,  0x74 },
+	{  760000000,  0x75 },
+	{  763000000,  0x76 },
+	{  764000000,  0x77 },
+	{  766000000,  0x78 },
+	{  767000000,  0x79 },
+	{  768000000,  0x7A },
+	{  773000000,  0x7B },
+	{  774000000,  0x7C },
+	{  776000000,  0x7D },
+	{  777000000,  0x7E },
+	{  778000000,  0x7F },
+	{  779000000,  0x80 },
+	{  781000000,  0x81 },
+	{  783000000,  0x82 },
+	{  784000000,  0x83 },
+	{  785000000,  0x84 },
+	{  786000000,  0x85 },
+	{  793000000,  0x86 },
+	{  794000000,  0x87 },
+	{  795000000,  0x88 },
+	{  797000000,  0x89 },
+	{  799000000,  0x8A },
+	{  801000000,  0x8B },
+	{  802000000,  0x8C },
+	{  803000000,  0x8D },
+	{  804000000,  0x8E },
+	{  810000000,  0x90 },
+	{  811000000,  0x91 },
+	{  812000000,  0x92 },
+	{  814000000,  0x93 },
+	{  816000000,  0x94 },
+	{  817000000,  0x96 },
+	{  818000000,  0x97 },
+	{  820000000,  0x98 },
+	{  821000000,  0x99 },
+	{  822000000,  0x9A },
+	{  828000000,  0x9B },
+	{  829000000,  0x9D },
+	{  830000000,  0x9F },
+	{  831000000,  0xA0 },
+	{  833000000,  0xA1 },
+	{  835000000,  0xA2 },
+	{  836000000,  0xA3 },
+	{  837000000,  0xA4 },
+	{  838000000,  0xA6 },
+	{  840000000,  0xA8 },
+	{  842000000,  0xA9 },
+	{  845000000,  0xAA },
+	{  846000000,  0xAB },
+	{  847000000,  0xAD },
+	{  848000000,  0xAE },
+	{  852000000,  0xAF },
+	{  853000000,  0xB0 },
+	{  858000000,  0xB1 },
+	{  860000000,  0xB2 },
+	{  861000000,  0xB3 },
+	{  862000000,  0xB4 },
+	{  863000000,  0xB6 },
+	{  864000000,  0xB8 },
+	{  865000000,  0xB9 },
+	{          0,  0x00 },    /* Table End */
+};
+
+
+static struct SMap2  m_KM_Map[] = {
+	{   47900000,  3, 2 },
+	{   61100000,  3, 1 },
+	{  350000000,  3, 0 },
+	{  720000000,  2, 1 },
+	{  865000000,  3, 3 },
+	{          0,  0x00 },    /* Table End */
+};
+
+static struct SMap2 m_Main_PLL_Map[] = {
+	{  33125000, 0x57, 0xF0 },
+	{  35500000, 0x56, 0xE0 },
+	{  38188000, 0x55, 0xD0 },
+	{  41375000, 0x54, 0xC0 },
+	{  45125000, 0x53, 0xB0 },
+	{  49688000, 0x52, 0xA0 },
+	{  55188000, 0x51, 0x90 },
+	{  62125000, 0x50, 0x80 },
+	{  66250000, 0x47, 0x78 },
+	{  71000000, 0x46, 0x70 },
+	{  76375000, 0x45, 0x68 },
+	{  82750000, 0x44, 0x60 },
+	{  90250000, 0x43, 0x58 },
+	{  99375000, 0x42, 0x50 },
+	{ 110375000, 0x41, 0x48 },
+	{ 124250000, 0x40, 0x40 },
+	{ 132500000, 0x37, 0x3C },
+	{ 142000000, 0x36, 0x38 },
+	{ 152750000, 0x35, 0x34 },
+	{ 165500000, 0x34, 0x30 },
+	{ 180500000, 0x33, 0x2C },
+	{ 198750000, 0x32, 0x28 },
+	{ 220750000, 0x31, 0x24 },
+	{ 248500000, 0x30, 0x20 },
+	{ 265000000, 0x27, 0x1E },
+	{ 284000000, 0x26, 0x1C },
+	{ 305500000, 0x25, 0x1A },
+	{ 331000000, 0x24, 0x18 },
+	{ 361000000, 0x23, 0x16 },
+	{ 397500000, 0x22, 0x14 },
+	{ 441500000, 0x21, 0x12 },
+	{ 497000000, 0x20, 0x10 },
+	{ 530000000, 0x17, 0x0F },
+	{ 568000000, 0x16, 0x0E },
+	{ 611000000, 0x15, 0x0D },
+	{ 662000000, 0x14, 0x0C },
+	{ 722000000, 0x13, 0x0B },
+	{ 795000000, 0x12, 0x0A },
+	{ 883000000, 0x11, 0x09 },
+	{ 994000000, 0x10, 0x08 },
+	{         0, 0x00, 0x00 },    /* Table End */
+};
+
+static struct SMap2 m_Cal_PLL_Map[] = {
+	{  33813000, 0xDD, 0xD0 },
+	{  36625000, 0xDC, 0xC0 },
+	{  39938000, 0xDB, 0xB0 },
+	{  43938000, 0xDA, 0xA0 },
+	{  48813000, 0xD9, 0x90 },
+	{  54938000, 0xD8, 0x80 },
+	{  62813000, 0xD3, 0x70 },
+	{  67625000, 0xCD, 0x68 },
+	{  73250000, 0xCC, 0x60 },
+	{  79875000, 0xCB, 0x58 },
+	{  87875000, 0xCA, 0x50 },
+	{  97625000, 0xC9, 0x48 },
+	{ 109875000, 0xC8, 0x40 },
+	{ 125625000, 0xC3, 0x38 },
+	{ 135250000, 0xBD, 0x34 },
+	{ 146500000, 0xBC, 0x30 },
+	{ 159750000, 0xBB, 0x2C },
+	{ 175750000, 0xBA, 0x28 },
+	{ 195250000, 0xB9, 0x24 },
+	{ 219750000, 0xB8, 0x20 },
+	{ 251250000, 0xB3, 0x1C },
+	{ 270500000, 0xAD, 0x1A },
+	{ 293000000, 0xAC, 0x18 },
+	{ 319500000, 0xAB, 0x16 },
+	{ 351500000, 0xAA, 0x14 },
+	{ 390500000, 0xA9, 0x12 },
+	{ 439500000, 0xA8, 0x10 },
+	{ 502500000, 0xA3, 0x0E },
+	{ 541000000, 0x9D, 0x0D },
+	{ 586000000, 0x9C, 0x0C },
+	{ 639000000, 0x9B, 0x0B },
+	{ 703000000, 0x9A, 0x0A },
+	{ 781000000, 0x99, 0x09 },
+	{ 879000000, 0x98, 0x08 },
+	{         0, 0x00, 0x00 },    /* Table End */
+};
+
+static struct SMap  m_GainTaper_Map[] = {
+	{  45400000, 0x1F },
+	{  45800000, 0x1E },
+	{  46200000, 0x1D },
+	{  46700000, 0x1C },
+	{  47100000, 0x1B },
+	{  47500000, 0x1A },
+	{  47900000, 0x19 },
+	{  49600000, 0x17 },
+	{  51200000, 0x16 },
+	{  52900000, 0x15 },
+	{  54500000, 0x14 },
+	{  56200000, 0x13 },
+	{  57800000, 0x12 },
+	{  59500000, 0x11 },
+	{  61100000, 0x10 },
+	{  67600000, 0x0D },
+	{  74200000, 0x0C },
+	{  80700000, 0x0B },
+	{  87200000, 0x0A },
+	{  93800000, 0x09 },
+	{ 100300000, 0x08 },
+	{ 106900000, 0x07 },
+	{ 113400000, 0x06 },
+	{ 119900000, 0x05 },
+	{ 126500000, 0x04 },
+	{ 133000000, 0x03 },
+	{ 139500000, 0x02 },
+	{ 146100000, 0x01 },
+	{ 152600000, 0x00 },
+	{ 154300000, 0x1F },
+	{ 156100000, 0x1E },
+	{ 157800000, 0x1D },
+	{ 159500000, 0x1C },
+	{ 161200000, 0x1B },
+	{ 163000000, 0x1A },
+	{ 164700000, 0x19 },
+	{ 170200000, 0x17 },
+	{ 175800000, 0x16 },
+	{ 181300000, 0x15 },
+	{ 186900000, 0x14 },
+	{ 192400000, 0x13 },
+	{ 198000000, 0x12 },
+	{ 203500000, 0x11 },
+	{ 216200000, 0x14 },
+	{ 228900000, 0x13 },
+	{ 241600000, 0x12 },
+	{ 254400000, 0x11 },
+	{ 267100000, 0x10 },
+	{ 279800000, 0x0F },
+	{ 292500000, 0x0E },
+	{ 305200000, 0x0D },
+	{ 317900000, 0x0C },
+	{ 330700000, 0x0B },
+	{ 343400000, 0x0A },
+	{ 356100000, 0x09 },
+	{ 368800000, 0x08 },
+	{ 381500000, 0x07 },
+	{ 394200000, 0x06 },
+	{ 406900000, 0x05 },
+	{ 419700000, 0x04 },
+	{ 432400000, 0x03 },
+	{ 445100000, 0x02 },
+	{ 457800000, 0x01 },
+	{ 476300000, 0x19 },
+	{ 494800000, 0x18 },
+	{ 513300000, 0x17 },
+	{ 531800000, 0x16 },
+	{ 550300000, 0x15 },
+	{ 568900000, 0x14 },
+	{ 587400000, 0x13 },
+	{ 605900000, 0x12 },
+	{ 624400000, 0x11 },
+	{ 642900000, 0x10 },
+	{ 661400000, 0x0F },
+	{ 679900000, 0x0E },
+	{ 698400000, 0x0D },
+	{ 716900000, 0x0C },
+	{ 735400000, 0x0B },
+	{ 753900000, 0x0A },
+	{ 772500000, 0x09 },
+	{ 791000000, 0x08 },
+	{ 809500000, 0x07 },
+	{ 828000000, 0x06 },
+	{ 846500000, 0x05 },
+	{ 865000000, 0x04 },
+	{         0, 0x00 },    /* Table End */
+};
+
+static struct SMap m_RF_Cal_DC_Over_DT_Map[] = {
+	{  47900000, 0x00 },
+	{  55000000, 0x00 },
+	{  61100000, 0x0A },
+	{  64000000, 0x0A },
+	{  82000000, 0x14 },
+	{  84000000, 0x19 },
+	{ 119000000, 0x1C },
+	{ 124000000, 0x20 },
+	{ 129000000, 0x2A },
+	{ 134000000, 0x32 },
+	{ 139000000, 0x39 },
+	{ 144000000, 0x3E },
+	{ 149000000, 0x3F },
+	{ 152600000, 0x40 },
+	{ 154000000, 0x40 },
+	{ 164700000, 0x41 },
+	{ 203500000, 0x32 },
+	{ 353000000, 0x19 },
+	{ 356000000, 0x1A },
+	{ 359000000, 0x1B },
+	{ 363000000, 0x1C },
+	{ 366000000, 0x1D },
+	{ 369000000, 0x1E },
+	{ 373000000, 0x1F },
+	{ 376000000, 0x20 },
+	{ 379000000, 0x21 },
+	{ 383000000, 0x22 },
+	{ 386000000, 0x23 },
+	{ 389000000, 0x24 },
+	{ 393000000, 0x25 },
+	{ 396000000, 0x26 },
+	{ 399000000, 0x27 },
+	{ 402000000, 0x28 },
+	{ 404000000, 0x29 },
+	{ 407000000, 0x2A },
+	{ 409000000, 0x2B },
+	{ 412000000, 0x2C },
+	{ 414000000, 0x2D },
+	{ 417000000, 0x2E },
+	{ 419000000, 0x2F },
+	{ 422000000, 0x30 },
+	{ 424000000, 0x31 },
+	{ 427000000, 0x32 },
+	{ 429000000, 0x33 },
+	{ 432000000, 0x34 },
+	{ 434000000, 0x35 },
+	{ 437000000, 0x36 },
+	{ 439000000, 0x37 },
+	{ 442000000, 0x38 },
+	{ 444000000, 0x39 },
+	{ 447000000, 0x3A },
+	{ 449000000, 0x3B },
+	{ 457800000, 0x3C },
+	{ 465000000, 0x0F },
+	{ 477000000, 0x12 },
+	{ 483000000, 0x14 },
+	{ 502000000, 0x19 },
+	{ 508000000, 0x1B },
+	{ 519000000, 0x1C },
+	{ 522000000, 0x1D },
+	{ 524000000, 0x1E },
+	{ 534000000, 0x1F },
+	{ 549000000, 0x20 },
+	{ 554000000, 0x22 },
+	{ 584000000, 0x24 },
+	{ 589000000, 0x26 },
+	{ 658000000, 0x27 },
+	{ 664000000, 0x2C },
+	{ 669000000, 0x2D },
+	{ 699000000, 0x2E },
+	{ 704000000, 0x30 },
+	{ 709000000, 0x31 },
+	{ 714000000, 0x32 },
+	{ 724000000, 0x33 },
+	{ 729000000, 0x36 },
+	{ 739000000, 0x38 },
+	{ 744000000, 0x39 },
+	{ 749000000, 0x3B },
+	{ 754000000, 0x3C },
+	{ 759000000, 0x3D },
+	{ 764000000, 0x3E },
+	{ 769000000, 0x3F },
+	{ 774000000, 0x40 },
+	{ 779000000, 0x41 },
+	{ 784000000, 0x43 },
+	{ 789000000, 0x46 },
+	{ 794000000, 0x48 },
+	{ 799000000, 0x4B },
+	{ 804000000, 0x4F },
+	{ 809000000, 0x54 },
+	{ 814000000, 0x59 },
+	{ 819000000, 0x5D },
+	{ 824000000, 0x61 },
+	{ 829000000, 0x68 },
+	{ 834000000, 0x6E },
+	{ 839000000, 0x75 },
+	{ 844000000, 0x7E },
+	{ 849000000, 0x82 },
+	{ 854000000, 0x84 },
+	{ 859000000, 0x8F },
+	{ 865000000, 0x9A },
+	{         0, 0x00 },    /* Table End */
+};
+
+
+static struct SMap  m_IR_Meas_Map[] = {
+	{ 200000000, 0x05 },
+	{ 400000000, 0x06 },
+	{ 865000000, 0x07 },
+	{         0, 0x00 },    /* Table End */
+};
+
+static struct SMap2 m_CID_Target_Map[] = {
+	{  46000000, 0x04, 18 },
+	{  52200000, 0x0A, 15 },
+	{  70100000, 0x01, 40 },
+	{ 136800000, 0x18, 40 },
+	{ 156700000, 0x18, 40 },
+	{ 186250000, 0x0A, 40 },
+	{ 230000000, 0x0A, 40 },
+	{ 345000000, 0x18, 40 },
+	{ 426000000, 0x0E, 40 },
+	{ 489500000, 0x1E, 40 },
+	{ 697500000, 0x32, 40 },
+	{ 842000000, 0x3A, 40 },
+	{         0, 0x00,  0 },    /* Table End */
+};
+
+static struct SRFBandMap  m_RF_Band_Map[7] = {
+	{   47900000,   46000000,           0,          0},
+	{   61100000,   52200000,           0,          0},
+	{  152600000,   70100000,   136800000,          0},
+	{  164700000,  156700000,           0,          0},
+	{  203500000,  186250000,           0,          0},
+	{  457800000,  230000000,   345000000,  426000000},
+	{  865000000,  489500000,   697500000,  842000000},
+};
+
+u8 m_Thermometer_Map_1[16] = {
+	60, 62, 66, 64,
+	74, 72, 68, 70,
+	90, 88, 84, 86,
+	76, 78, 82, 80,
+};
+
+u8 m_Thermometer_Map_2[16] = {
+	92, 94, 98, 96,
+	106, 104, 100, 102,
+	122, 120, 116, 118,
+	108, 110, 114, 112,
+};
diff --git a/drivers/media/dvb-frontends/tda665x.c b/drivers/media/dvb-frontends/tda665x.c
new file mode 100644
index 0000000..2c1c759
--- /dev/null
+++ b/drivers/media/dvb-frontends/tda665x.c
@@ -0,0 +1,258 @@
+/*
+	TDA665x tuner driver
+	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include "dvb_frontend.h"
+#include "tda665x.h"
+
+struct tda665x_state {
+	struct dvb_frontend		*fe;
+	struct i2c_adapter		*i2c;
+	const struct tda665x_config	*config;
+
+	u32 frequency;
+	u32 bandwidth;
+};
+
+static int tda665x_read(struct tda665x_state *state, u8 *buf)
+{
+	const struct tda665x_config *config = state->config;
+	int err = 0;
+	struct i2c_msg msg = { .addr = config->addr, .flags = I2C_M_RD, .buf = buf, .len = 2 };
+
+	err = i2c_transfer(state->i2c, &msg, 1);
+	if (err != 1)
+		goto exit;
+
+	return err;
+exit:
+	printk(KERN_ERR "%s: I/O Error err=<%d>\n", __func__, err);
+	return err;
+}
+
+static int tda665x_write(struct tda665x_state *state, u8 *buf, u8 length)
+{
+	const struct tda665x_config *config = state->config;
+	int err = 0;
+	struct i2c_msg msg = { .addr = config->addr, .flags = 0, .buf = buf, .len = length };
+
+	err = i2c_transfer(state->i2c, &msg, 1);
+	if (err != 1)
+		goto exit;
+
+	return err;
+exit:
+	printk(KERN_ERR "%s: I/O Error err=<%d>\n", __func__, err);
+	return err;
+}
+
+static int tda665x_get_state(struct dvb_frontend *fe,
+			     enum tuner_param param,
+			     struct tuner_state *tstate)
+{
+	struct tda665x_state *state = fe->tuner_priv;
+	int err = 0;
+
+	switch (param) {
+	case DVBFE_TUNER_FREQUENCY:
+		tstate->frequency = state->frequency;
+		break;
+	case DVBFE_TUNER_BANDWIDTH:
+		break;
+	default:
+		printk(KERN_ERR "%s: Unknown parameter (param=%d)\n", __func__, param);
+		err = -EINVAL;
+		break;
+	}
+
+	return err;
+}
+
+static int tda665x_get_status(struct dvb_frontend *fe, u32 *status)
+{
+	struct tda665x_state *state = fe->tuner_priv;
+	u8 result = 0;
+	int err = 0;
+
+	*status = 0;
+
+	err = tda665x_read(state, &result);
+	if (err < 0)
+		goto exit;
+
+	if ((result >> 6) & 0x01) {
+		printk(KERN_DEBUG "%s: Tuner Phase Locked\n", __func__);
+		*status = 1;
+	}
+
+	return err;
+exit:
+	printk(KERN_ERR "%s: I/O Error\n", __func__);
+	return err;
+}
+
+static int tda665x_set_state(struct dvb_frontend *fe,
+			     enum tuner_param param,
+			     struct tuner_state *tstate)
+{
+	struct tda665x_state *state = fe->tuner_priv;
+	const struct tda665x_config *config = state->config;
+	u32 frequency, status = 0;
+	u8 buf[4];
+	int err = 0;
+
+	if (param & DVBFE_TUNER_FREQUENCY) {
+
+		frequency = tstate->frequency;
+		if ((frequency < config->frequency_max) || (frequency > config->frequency_min)) {
+			printk(KERN_ERR "%s: Frequency beyond limits, frequency=%d\n", __func__, frequency);
+			return -EINVAL;
+		}
+
+		frequency += config->frequency_offst;
+		frequency *= config->ref_multiplier;
+		frequency += config->ref_divider >> 1;
+		frequency /= config->ref_divider;
+
+		buf[0] = (u8) ((frequency & 0x7f00) >> 8);
+		buf[1] = (u8) (frequency & 0x00ff) >> 0;
+		buf[2] = 0x80 | 0x40 | 0x02;
+		buf[3] = 0x00;
+
+		/* restore frequency */
+		frequency = tstate->frequency;
+
+		if (frequency < 153000000) {
+			/* VHF-L */
+			buf[3] |= 0x01; /* fc, Low Band, 47 - 153 MHz */
+			if (frequency < 68000000)
+				buf[3] |= 0x40; /* 83uA */
+			if (frequency < 1040000000)
+				buf[3] |= 0x60; /* 122uA */
+			if (frequency < 1250000000)
+				buf[3] |= 0x80; /* 163uA */
+			else
+				buf[3] |= 0xa0; /* 254uA */
+		} else if (frequency < 438000000) {
+			/* VHF-H */
+			buf[3] |= 0x02; /* fc, Mid Band, 153 - 438 MHz */
+			if (frequency < 230000000)
+				buf[3] |= 0x40;
+			if (frequency < 300000000)
+				buf[3] |= 0x60;
+			else
+				buf[3] |= 0x80;
+		} else {
+			/* UHF */
+			buf[3] |= 0x04; /* fc, High Band, 438 - 862 MHz */
+			if (frequency < 470000000)
+				buf[3] |= 0x60;
+			if (frequency < 526000000)
+				buf[3] |= 0x80;
+			else
+				buf[3] |= 0xa0;
+		}
+
+		/* Set params */
+		err = tda665x_write(state, buf, 5);
+		if (err < 0)
+			goto exit;
+
+		/* sleep for some time */
+		printk(KERN_DEBUG "%s: Waiting to Phase LOCK\n", __func__);
+		msleep(20);
+		/* check status */
+		err = tda665x_get_status(fe, &status);
+		if (err < 0)
+			goto exit;
+
+		if (status == 1) {
+			printk(KERN_DEBUG "%s: Tuner Phase locked: status=%d\n", __func__, status);
+			state->frequency = frequency; /* cache successful state */
+		} else {
+			printk(KERN_ERR "%s: No Phase lock: status=%d\n", __func__, status);
+		}
+	} else {
+		printk(KERN_ERR "%s: Unknown parameter (param=%d)\n", __func__, param);
+		return -EINVAL;
+	}
+
+	return 0;
+exit:
+	printk(KERN_ERR "%s: I/O Error\n", __func__);
+	return err;
+}
+
+static int tda665x_release(struct dvb_frontend *fe)
+{
+	struct tda665x_state *state = fe->tuner_priv;
+
+	fe->tuner_priv = NULL;
+	kfree(state);
+	return 0;
+}
+
+static struct dvb_tuner_ops tda665x_ops = {
+
+	.set_state	= tda665x_set_state,
+	.get_state	= tda665x_get_state,
+	.get_status	= tda665x_get_status,
+	.release	= tda665x_release
+};
+
+struct dvb_frontend *tda665x_attach(struct dvb_frontend *fe,
+				    const struct tda665x_config *config,
+				    struct i2c_adapter *i2c)
+{
+	struct tda665x_state *state = NULL;
+	struct dvb_tuner_info *info;
+
+	state = kzalloc(sizeof(struct tda665x_state), GFP_KERNEL);
+	if (state == NULL)
+		goto exit;
+
+	state->config		= config;
+	state->i2c		= i2c;
+	state->fe		= fe;
+	fe->tuner_priv		= state;
+	fe->ops.tuner_ops	= tda665x_ops;
+	info			 = &fe->ops.tuner_ops.info;
+
+	memcpy(info->name, config->name, sizeof(config->name));
+	info->frequency_min	= config->frequency_min;
+	info->frequency_max	= config->frequency_max;
+	info->frequency_step	= config->frequency_offst;
+
+	printk(KERN_DEBUG "%s: Attaching TDA665x (%s) tuner\n", __func__, info->name);
+
+	return fe;
+
+exit:
+	kfree(state);
+	return NULL;
+}
+EXPORT_SYMBOL(tda665x_attach);
+
+MODULE_DESCRIPTION("TDA665x driver");
+MODULE_AUTHOR("Manu Abraham");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb-frontends/tda665x.h b/drivers/media/dvb-frontends/tda665x.h
new file mode 100644
index 0000000..ec7927a
--- /dev/null
+++ b/drivers/media/dvb-frontends/tda665x.h
@@ -0,0 +1,52 @@
+/*
+	TDA665x tuner driver
+	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __TDA665x_H
+#define __TDA665x_H
+
+struct tda665x_config {
+	char name[128];
+
+	u8	addr;
+	u32	frequency_min;
+	u32	frequency_max;
+	u32	frequency_offst;
+	u32	ref_multiplier;
+	u32	ref_divider;
+};
+
+#if defined(CONFIG_DVB_TDA665x) || (defined(CONFIG_DVB_TDA665x_MODULE) && defined(MODULE))
+
+extern struct dvb_frontend *tda665x_attach(struct dvb_frontend *fe,
+					   const struct tda665x_config *config,
+					   struct i2c_adapter *i2c);
+
+#else
+
+static inline struct dvb_frontend *tda665x_attach(struct dvb_frontend *fe,
+						  const struct tda665x_config *config,
+						  struct i2c_adapter *i2c)
+{
+	printk(KERN_WARNING "%s: Driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+
+#endif /* CONFIG_DVB_TDA665x */
+
+#endif /* __TDA665x_H */
diff --git a/drivers/media/dvb-frontends/tda8083.c b/drivers/media/dvb-frontends/tda8083.c
new file mode 100644
index 0000000..15912c9
--- /dev/null
+++ b/drivers/media/dvb-frontends/tda8083.c
@@ -0,0 +1,487 @@
+/*
+    Driver for Philips TDA8083 based QPSK Demodulator
+
+    Copyright (C) 2001 Convergence Integrated Media GmbH
+
+    written by Ralph Metzler <ralph@convergence.de>
+
+    adoption to the new DVB frontend API and diagnostic ioctl's
+    by Holger Waechtler <holger@convergence.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/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include "dvb_frontend.h"
+#include "tda8083.h"
+
+
+struct tda8083_state {
+	struct i2c_adapter* i2c;
+	/* configuration settings */
+	const struct tda8083_config* config;
+	struct dvb_frontend frontend;
+};
+
+static int debug;
+#define dprintk(args...) \
+	do { \
+		if (debug) printk(KERN_DEBUG "tda8083: " args); \
+	} while (0)
+
+
+static u8 tda8083_init_tab [] = {
+	0x04, 0x00, 0x4a, 0x79, 0x04, 0x00, 0xff, 0xea,
+	0x48, 0x42, 0x79, 0x60, 0x70, 0x52, 0x9a, 0x10,
+	0x0e, 0x10, 0xf2, 0xa7, 0x93, 0x0b, 0x05, 0xc8,
+	0x9d, 0x00, 0x42, 0x80, 0x00, 0x60, 0x40, 0x00,
+	0x00, 0x75, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00
+};
+
+
+static int tda8083_writereg (struct tda8083_state* state, u8 reg, u8 data)
+{
+	int ret;
+	u8 buf [] = { reg, data };
+	struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 };
+
+	ret = i2c_transfer(state->i2c, &msg, 1);
+
+	if (ret != 1)
+		dprintk ("%s: writereg error (reg %02x, ret == %i)\n",
+			__func__, reg, ret);
+
+	return (ret != 1) ? -1 : 0;
+}
+
+static int tda8083_readregs (struct tda8083_state* state, u8 reg1, u8 *b, u8 len)
+{
+	int ret;
+	struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = &reg1, .len = 1 },
+			   { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b, .len = len } };
+
+	ret = i2c_transfer(state->i2c, msg, 2);
+
+	if (ret != 2)
+		dprintk ("%s: readreg error (reg %02x, ret == %i)\n",
+			__func__, reg1, ret);
+
+	return ret == 2 ? 0 : -1;
+}
+
+static inline u8 tda8083_readreg (struct tda8083_state* state, u8 reg)
+{
+	u8 val;
+
+	tda8083_readregs (state, reg, &val, 1);
+
+	return val;
+}
+
+static int tda8083_set_inversion (struct tda8083_state* state, fe_spectral_inversion_t inversion)
+{
+	/*  XXX FIXME: implement other modes than FEC_AUTO */
+	if (inversion == INVERSION_AUTO)
+		return 0;
+
+	return -EINVAL;
+}
+
+static int tda8083_set_fec (struct tda8083_state* state, fe_code_rate_t fec)
+{
+	if (fec == FEC_AUTO)
+		return tda8083_writereg (state, 0x07, 0xff);
+
+	if (fec >= FEC_1_2 && fec <= FEC_8_9)
+		return tda8083_writereg (state, 0x07, 1 << (FEC_8_9 - fec));
+
+	return -EINVAL;
+}
+
+static fe_code_rate_t tda8083_get_fec (struct tda8083_state* state)
+{
+	u8 index;
+	static fe_code_rate_t fec_tab [] = { FEC_8_9, FEC_1_2, FEC_2_3, FEC_3_4,
+				       FEC_4_5, FEC_5_6, FEC_6_7, FEC_7_8 };
+
+	index = tda8083_readreg(state, 0x0e) & 0x07;
+
+	return fec_tab [index];
+}
+
+static int tda8083_set_symbolrate (struct tda8083_state* state, u32 srate)
+{
+	u32 ratio;
+	u32 tmp;
+	u8 filter;
+
+	if (srate > 32000000)
+		srate = 32000000;
+	if (srate < 500000)
+		srate = 500000;
+
+	filter = 0;
+	if (srate < 24000000)
+		filter = 2;
+	if (srate < 16000000)
+		filter = 3;
+
+	tmp = 31250 << 16;
+	ratio = tmp / srate;
+
+	tmp = (tmp % srate) << 8;
+	ratio = (ratio << 8) + tmp / srate;
+
+	tmp = (tmp % srate) << 8;
+	ratio = (ratio << 8) + tmp / srate;
+
+	dprintk("tda8083: ratio == %08x\n", (unsigned int) ratio);
+
+	tda8083_writereg (state, 0x05, filter);
+	tda8083_writereg (state, 0x02, (ratio >> 16) & 0xff);
+	tda8083_writereg (state, 0x03, (ratio >>  8) & 0xff);
+	tda8083_writereg (state, 0x04, (ratio      ) & 0xff);
+
+	tda8083_writereg (state, 0x00, 0x3c);
+	tda8083_writereg (state, 0x00, 0x04);
+
+	return 1;
+}
+
+static void tda8083_wait_diseqc_fifo (struct tda8083_state* state, int timeout)
+{
+	unsigned long start = jiffies;
+
+	while (jiffies - start < timeout &&
+	       !(tda8083_readreg(state, 0x02) & 0x80))
+	{
+		msleep(50);
+	};
+}
+
+static int tda8083_set_tone (struct tda8083_state* state, fe_sec_tone_mode_t tone)
+{
+	tda8083_writereg (state, 0x26, 0xf1);
+
+	switch (tone) {
+	case SEC_TONE_OFF:
+		return tda8083_writereg (state, 0x29, 0x00);
+	case SEC_TONE_ON:
+		return tda8083_writereg (state, 0x29, 0x80);
+	default:
+		return -EINVAL;
+	};
+}
+
+static int tda8083_set_voltage (struct tda8083_state* state, fe_sec_voltage_t voltage)
+{
+	switch (voltage) {
+	case SEC_VOLTAGE_13:
+		return tda8083_writereg (state, 0x20, 0x00);
+	case SEC_VOLTAGE_18:
+		return tda8083_writereg (state, 0x20, 0x11);
+	default:
+		return -EINVAL;
+	};
+}
+
+static int tda8083_send_diseqc_burst (struct tda8083_state* state, fe_sec_mini_cmd_t burst)
+{
+	switch (burst) {
+	case SEC_MINI_A:
+		tda8083_writereg (state, 0x29, (5 << 2));  /* send burst A */
+		break;
+	case SEC_MINI_B:
+		tda8083_writereg (state, 0x29, (7 << 2));  /* send B */
+		break;
+	default:
+		return -EINVAL;
+	};
+
+	tda8083_wait_diseqc_fifo (state, 100);
+
+	return 0;
+}
+
+static int tda8083_send_diseqc_msg (struct dvb_frontend* fe,
+				    struct dvb_diseqc_master_cmd *m)
+{
+	struct tda8083_state* state = fe->demodulator_priv;
+	int i;
+
+	tda8083_writereg (state, 0x29, (m->msg_len - 3) | (1 << 2)); /* enable */
+
+	for (i=0; i<m->msg_len; i++)
+		tda8083_writereg (state, 0x23 + i, m->msg[i]);
+
+	tda8083_writereg (state, 0x29, (m->msg_len - 3) | (3 << 2)); /* send!! */
+
+	tda8083_wait_diseqc_fifo (state, 100);
+
+	return 0;
+}
+
+static int tda8083_read_status(struct dvb_frontend* fe, fe_status_t* status)
+{
+	struct tda8083_state* state = fe->demodulator_priv;
+
+	u8 signal = ~tda8083_readreg (state, 0x01);
+	u8 sync = tda8083_readreg (state, 0x02);
+
+	*status = 0;
+
+	if (signal > 10)
+		*status |= FE_HAS_SIGNAL;
+
+	if (sync & 0x01)
+		*status |= FE_HAS_CARRIER;
+
+	if (sync & 0x02)
+		*status |= FE_HAS_VITERBI;
+
+	if (sync & 0x10)
+		*status |= FE_HAS_SYNC;
+
+	if (sync & 0x20) /* frontend can not lock */
+		*status |= FE_TIMEDOUT;
+
+	if ((sync & 0x1f) == 0x1f)
+		*status |= FE_HAS_LOCK;
+
+	return 0;
+}
+
+static int tda8083_read_ber(struct dvb_frontend* fe, u32* ber)
+{
+	struct tda8083_state* state = fe->demodulator_priv;
+	int ret;
+	u8 buf[3];
+
+	if ((ret = tda8083_readregs(state, 0x0b, buf, sizeof(buf))))
+		return ret;
+
+	*ber = ((buf[0] & 0x1f) << 16) | (buf[1] << 8) | buf[2];
+
+	return 0;
+}
+
+static int tda8083_read_signal_strength(struct dvb_frontend* fe, u16* strength)
+{
+	struct tda8083_state* state = fe->demodulator_priv;
+
+	u8 signal = ~tda8083_readreg (state, 0x01);
+	*strength = (signal << 8) | signal;
+
+	return 0;
+}
+
+static int tda8083_read_snr(struct dvb_frontend* fe, u16* snr)
+{
+	struct tda8083_state* state = fe->demodulator_priv;
+
+	u8 _snr = tda8083_readreg (state, 0x08);
+	*snr = (_snr << 8) | _snr;
+
+	return 0;
+}
+
+static int tda8083_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
+{
+	struct tda8083_state* state = fe->demodulator_priv;
+
+	*ucblocks = tda8083_readreg(state, 0x0f);
+	if (*ucblocks == 0xff)
+		*ucblocks = 0xffffffff;
+
+	return 0;
+}
+
+static int tda8083_set_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct tda8083_state* state = fe->demodulator_priv;
+
+	if (fe->ops.tuner_ops.set_params) {
+		fe->ops.tuner_ops.set_params(fe);
+		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+	}
+
+	tda8083_set_inversion (state, p->inversion);
+	tda8083_set_fec(state, p->fec_inner);
+	tda8083_set_symbolrate(state, p->symbol_rate);
+
+	tda8083_writereg (state, 0x00, 0x3c);
+	tda8083_writereg (state, 0x00, 0x04);
+
+	return 0;
+}
+
+static int tda8083_get_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct tda8083_state* state = fe->demodulator_priv;
+
+	/*  FIXME: get symbolrate & frequency offset...*/
+	/*p->frequency = ???;*/
+	p->inversion = (tda8083_readreg (state, 0x0e) & 0x80) ?
+			INVERSION_ON : INVERSION_OFF;
+	p->fec_inner = tda8083_get_fec(state);
+	/*p->symbol_rate = tda8083_get_symbolrate (state);*/
+
+	return 0;
+}
+
+static int tda8083_sleep(struct dvb_frontend* fe)
+{
+	struct tda8083_state* state = fe->demodulator_priv;
+
+	tda8083_writereg (state, 0x00, 0x02);
+	return 0;
+}
+
+static int tda8083_init(struct dvb_frontend* fe)
+{
+	struct tda8083_state* state = fe->demodulator_priv;
+	int i;
+
+	for (i=0; i<44; i++)
+		tda8083_writereg (state, i, tda8083_init_tab[i]);
+
+	tda8083_writereg (state, 0x00, 0x3c);
+	tda8083_writereg (state, 0x00, 0x04);
+
+	return 0;
+}
+
+static int tda8083_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t burst)
+{
+	struct tda8083_state* state = fe->demodulator_priv;
+
+	tda8083_send_diseqc_burst (state, burst);
+	tda8083_writereg (state, 0x00, 0x3c);
+	tda8083_writereg (state, 0x00, 0x04);
+
+	return 0;
+}
+
+static int tda8083_diseqc_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
+{
+	struct tda8083_state* state = fe->demodulator_priv;
+
+	tda8083_set_tone (state, tone);
+	tda8083_writereg (state, 0x00, 0x3c);
+	tda8083_writereg (state, 0x00, 0x04);
+
+	return 0;
+}
+
+static int tda8083_diseqc_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
+{
+	struct tda8083_state* state = fe->demodulator_priv;
+
+	tda8083_set_voltage (state, voltage);
+	tda8083_writereg (state, 0x00, 0x3c);
+	tda8083_writereg (state, 0x00, 0x04);
+
+	return 0;
+}
+
+static void tda8083_release(struct dvb_frontend* fe)
+{
+	struct tda8083_state* state = fe->demodulator_priv;
+	kfree(state);
+}
+
+static struct dvb_frontend_ops tda8083_ops;
+
+struct dvb_frontend* tda8083_attach(const struct tda8083_config* config,
+				    struct i2c_adapter* i2c)
+{
+	struct tda8083_state* state = NULL;
+
+	/* allocate memory for the internal state */
+	state = kzalloc(sizeof(struct tda8083_state), GFP_KERNEL);
+	if (state == NULL) goto error;
+
+	/* setup the state */
+	state->config = config;
+	state->i2c = i2c;
+
+	/* check if the demod is there */
+	if ((tda8083_readreg(state, 0x00)) != 0x05) goto error;
+
+	/* create dvb_frontend */
+	memcpy(&state->frontend.ops, &tda8083_ops, sizeof(struct dvb_frontend_ops));
+	state->frontend.demodulator_priv = state;
+	return &state->frontend;
+
+error:
+	kfree(state);
+	return NULL;
+}
+
+static struct dvb_frontend_ops tda8083_ops = {
+	.delsys = { SYS_DVBS },
+	.info = {
+		.name			= "Philips TDA8083 DVB-S",
+		.frequency_min		= 920000,     /* TDA8060 */
+		.frequency_max		= 2200000,    /* TDA8060 */
+		.frequency_stepsize	= 125,   /* kHz for QPSK frontends */
+	/*      .frequency_tolerance	= ???,*/
+		.symbol_rate_min	= 12000000,
+		.symbol_rate_max	= 30000000,
+	/*      .symbol_rate_tolerance	= ???,*/
+		.caps = FE_CAN_INVERSION_AUTO |
+			FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
+			FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
+			FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO |
+			FE_CAN_QPSK | FE_CAN_MUTE_TS
+	},
+
+	.release = tda8083_release,
+
+	.init = tda8083_init,
+	.sleep = tda8083_sleep,
+
+	.set_frontend = tda8083_set_frontend,
+	.get_frontend = tda8083_get_frontend,
+
+	.read_status = tda8083_read_status,
+	.read_signal_strength = tda8083_read_signal_strength,
+	.read_snr = tda8083_read_snr,
+	.read_ber = tda8083_read_ber,
+	.read_ucblocks = tda8083_read_ucblocks,
+
+	.diseqc_send_master_cmd = tda8083_send_diseqc_msg,
+	.diseqc_send_burst = tda8083_diseqc_send_burst,
+	.set_tone = tda8083_diseqc_set_tone,
+	.set_voltage = tda8083_diseqc_set_voltage,
+};
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+
+MODULE_DESCRIPTION("Philips TDA8083 DVB-S Demodulator");
+MODULE_AUTHOR("Ralph Metzler, Holger Waechtler");
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(tda8083_attach);
diff --git a/drivers/media/dvb-frontends/tda8083.h b/drivers/media/dvb-frontends/tda8083.h
new file mode 100644
index 0000000..5a03c14
--- /dev/null
+++ b/drivers/media/dvb-frontends/tda8083.h
@@ -0,0 +1,50 @@
+/*
+    Driver for Grundig 29504-491, a Philips TDA8083 based QPSK Frontend
+
+    Copyright (C) 2001 Convergence Integrated Media GmbH
+
+    written by Ralph Metzler <ralph@convergence.de>
+
+    adoption to the new DVB frontend API and diagnostic ioctl's
+    by Holger Waechtler <holger@convergence.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 TDA8083_H
+#define TDA8083_H
+
+#include <linux/dvb/frontend.h>
+
+struct tda8083_config
+{
+	/* the demodulator's i2c address */
+	u8 demod_address;
+};
+
+#if defined(CONFIG_DVB_TDA8083) || (defined(CONFIG_DVB_TDA8083_MODULE) && defined(MODULE))
+extern struct dvb_frontend* tda8083_attach(const struct tda8083_config* config,
+					   struct i2c_adapter* i2c);
+#else
+static inline struct dvb_frontend* tda8083_attach(const struct tda8083_config* config,
+					   struct i2c_adapter* i2c)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif // CONFIG_DVB_TDA8083
+
+#endif // TDA8083_H
diff --git a/drivers/media/dvb-frontends/tda8261.c b/drivers/media/dvb-frontends/tda8261.c
new file mode 100644
index 0000000..19c4888
--- /dev/null
+++ b/drivers/media/dvb-frontends/tda8261.c
@@ -0,0 +1,230 @@
+/*
+	TDA8261 8PSK/QPSK tuner driver
+	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include "dvb_frontend.h"
+#include "tda8261.h"
+
+struct tda8261_state {
+	struct dvb_frontend		*fe;
+	struct i2c_adapter		*i2c;
+	const struct tda8261_config	*config;
+
+	/* state cache */
+	u32 frequency;
+	u32 bandwidth;
+};
+
+static int tda8261_read(struct tda8261_state *state, u8 *buf)
+{
+	const struct tda8261_config *config = state->config;
+	int err = 0;
+	struct i2c_msg msg = { .addr	= config->addr, .flags = I2C_M_RD,.buf = buf,  .len = 1 };
+
+	if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1)
+		pr_err("%s: read error, err=%d\n", __func__, err);
+
+	return err;
+}
+
+static int tda8261_write(struct tda8261_state *state, u8 *buf)
+{
+	const struct tda8261_config *config = state->config;
+	int err = 0;
+	struct i2c_msg msg = { .addr = config->addr, .flags = 0, .buf = buf, .len = 4 };
+
+	if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1)
+		pr_err("%s: write error, err=%d\n", __func__, err);
+
+	return err;
+}
+
+static int tda8261_get_status(struct dvb_frontend *fe, u32 *status)
+{
+	struct tda8261_state *state = fe->tuner_priv;
+	u8 result = 0;
+	int err = 0;
+
+	*status = 0;
+
+	if ((err = tda8261_read(state, &result)) < 0) {
+		pr_err("%s: I/O Error\n", __func__);
+		return err;
+	}
+	if ((result >> 6) & 0x01) {
+		pr_debug("%s: Tuner Phase Locked\n", __func__);
+		*status = 1;
+	}
+
+	return err;
+}
+
+static const u32 div_tab[] = { 2000, 1000,  500,  250,  125 }; /* kHz */
+static const u8  ref_div[] = { 0x00, 0x01, 0x02, 0x05, 0x07 };
+
+static int tda8261_get_state(struct dvb_frontend *fe,
+			     enum tuner_param param,
+			     struct tuner_state *tstate)
+{
+	struct tda8261_state *state = fe->tuner_priv;
+	int err = 0;
+
+	switch (param) {
+	case DVBFE_TUNER_FREQUENCY:
+		tstate->frequency = state->frequency;
+		break;
+	case DVBFE_TUNER_BANDWIDTH:
+		tstate->bandwidth = 40000000; /* FIXME! need to calculate Bandwidth */
+		break;
+	default:
+		pr_err("%s: Unknown parameter (param=%d)\n", __func__, param);
+		err = -EINVAL;
+		break;
+	}
+
+	return err;
+}
+
+static int tda8261_set_state(struct dvb_frontend *fe,
+			     enum tuner_param param,
+			     struct tuner_state *tstate)
+{
+	struct tda8261_state *state = fe->tuner_priv;
+	const struct tda8261_config *config = state->config;
+	u32 frequency, N, status = 0;
+	u8 buf[4];
+	int err = 0;
+
+	if (param & DVBFE_TUNER_FREQUENCY) {
+		/**
+		 * N = Max VCO Frequency / Channel Spacing
+		 * Max VCO Frequency = VCO frequency + (channel spacing - 1)
+		 * (to account for half channel spacing on either side)
+		 */
+		frequency = tstate->frequency;
+		if ((frequency < 950000) || (frequency > 2150000)) {
+			pr_warn("%s: Frequency beyond limits, frequency=%d\n", __func__, frequency);
+			return -EINVAL;
+		}
+		N = (frequency + (div_tab[config->step_size] - 1)) / div_tab[config->step_size];
+		pr_debug("%s: Step size=%d, Divider=%d, PG=0x%02x (%d)\n",
+			__func__, config->step_size, div_tab[config->step_size], N, N);
+
+		buf[0] = (N >> 8) & 0xff;
+		buf[1] = N & 0xff;
+		buf[2] = (0x01 << 7) | ((ref_div[config->step_size] & 0x07) << 1);
+
+		if (frequency < 1450000)
+			buf[3] = 0x00;
+		else if (frequency < 2000000)
+			buf[3] = 0x40;
+		else if (frequency < 2150000)
+			buf[3] = 0x80;
+
+		/* Set params */
+		if ((err = tda8261_write(state, buf)) < 0) {
+			pr_err("%s: I/O Error\n", __func__);
+			return err;
+		}
+		/* sleep for some time */
+		pr_debug("%s: Waiting to Phase LOCK\n", __func__);
+		msleep(20);
+		/* check status */
+		if ((err = tda8261_get_status(fe, &status)) < 0) {
+			pr_err("%s: I/O Error\n", __func__);
+			return err;
+		}
+		if (status == 1) {
+			pr_debug("%s: Tuner Phase locked: status=%d\n", __func__, status);
+			state->frequency = frequency; /* cache successful state */
+		} else {
+			pr_debug("%s: No Phase lock: status=%d\n", __func__, status);
+		}
+	} else {
+		pr_err("%s: Unknown parameter (param=%d)\n", __func__, param);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int tda8261_release(struct dvb_frontend *fe)
+{
+	struct tda8261_state *state = fe->tuner_priv;
+
+	fe->tuner_priv = NULL;
+	kfree(state);
+	return 0;
+}
+
+static struct dvb_tuner_ops tda8261_ops = {
+
+	.info = {
+		.name		= "TDA8261",
+//		.tuner_name	= NULL,
+		.frequency_min	=  950000,
+		.frequency_max	= 2150000,
+		.frequency_step = 0
+	},
+
+	.set_state	= tda8261_set_state,
+	.get_state	= tda8261_get_state,
+	.get_status	= tda8261_get_status,
+	.release	= tda8261_release
+};
+
+struct dvb_frontend *tda8261_attach(struct dvb_frontend *fe,
+				    const struct tda8261_config *config,
+				    struct i2c_adapter *i2c)
+{
+	struct tda8261_state *state = NULL;
+
+	if ((state = kzalloc(sizeof (struct tda8261_state), GFP_KERNEL)) == NULL)
+		goto exit;
+
+	state->config		= config;
+	state->i2c		= i2c;
+	state->fe		= fe;
+	fe->tuner_priv		= state;
+	fe->ops.tuner_ops	= tda8261_ops;
+
+	fe->ops.tuner_ops.info.frequency_step = div_tab[config->step_size];
+//	fe->ops.tuner_ops.tuner_name	 = &config->buf;
+
+//	printk("%s: Attaching %s TDA8261 8PSK/QPSK tuner\n",
+//		__func__, fe->ops.tuner_ops.tuner_name);
+	pr_info("%s: Attaching TDA8261 8PSK/QPSK tuner\n", __func__);
+
+	return fe;
+
+exit:
+	kfree(state);
+	return NULL;
+}
+
+EXPORT_SYMBOL(tda8261_attach);
+
+MODULE_AUTHOR("Manu Abraham");
+MODULE_DESCRIPTION("TDA8261 8PSK/QPSK Tuner");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb-frontends/tda8261.h b/drivers/media/dvb-frontends/tda8261.h
new file mode 100644
index 0000000..006e453
--- /dev/null
+++ b/drivers/media/dvb-frontends/tda8261.h
@@ -0,0 +1,55 @@
+/*
+	TDA8261 8PSK/QPSK tuner driver
+	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __TDA8261_H
+#define __TDA8261_H
+
+enum tda8261_step {
+	TDA8261_STEP_2000 = 0,	/* 2000 kHz */
+	TDA8261_STEP_1000,	/* 1000 kHz */
+	TDA8261_STEP_500,	/*  500 kHz */
+	TDA8261_STEP_250,	/*  250 kHz */
+	TDA8261_STEP_125	/*  125 kHz */
+};
+
+struct tda8261_config {
+//	u8			buf[16];
+	u8			addr;
+	enum tda8261_step	step_size;
+};
+
+#if defined(CONFIG_DVB_TDA8261) || (defined(CONFIG_DVB_TDA8261_MODULE) && defined(MODULE))
+
+extern struct dvb_frontend *tda8261_attach(struct dvb_frontend *fe,
+					   const struct tda8261_config *config,
+					   struct i2c_adapter *i2c);
+
+#else
+
+static inline struct dvb_frontend *tda8261_attach(struct dvb_frontend *fe,
+						  const struct tda8261_config *config,
+						  struct i2c_adapter *i2c)
+{
+	printk(KERN_WARNING "%s: Driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+
+#endif //CONFIG_DVB_TDA8261
+
+#endif// __TDA8261_H
diff --git a/drivers/media/dvb-frontends/tda8261_cfg.h b/drivers/media/dvb-frontends/tda8261_cfg.h
new file mode 100644
index 0000000..1af1ee4
--- /dev/null
+++ b/drivers/media/dvb-frontends/tda8261_cfg.h
@@ -0,0 +1,84 @@
+/*
+	TDA8261 8PSK/QPSK tuner driver
+	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+static int tda8261_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+	struct dvb_frontend_ops	*frontend_ops = NULL;
+	struct dvb_tuner_ops	*tuner_ops = NULL;
+	struct tuner_state	t_state;
+	int err = 0;
+
+	if (&fe->ops)
+		frontend_ops = &fe->ops;
+	if (&frontend_ops->tuner_ops)
+		tuner_ops = &frontend_ops->tuner_ops;
+	if (tuner_ops->get_state) {
+		if ((err = tuner_ops->get_state(fe, DVBFE_TUNER_FREQUENCY, &t_state)) < 0) {
+			printk("%s: Invalid parameter\n", __func__);
+			return err;
+		}
+		*frequency = t_state.frequency;
+		printk("%s: Frequency=%d\n", __func__, t_state.frequency);
+	}
+	return 0;
+}
+
+static int tda8261_set_frequency(struct dvb_frontend *fe, u32 frequency)
+{
+	struct dvb_frontend_ops	*frontend_ops = NULL;
+	struct dvb_tuner_ops	*tuner_ops = NULL;
+	struct tuner_state	t_state;
+	int err = 0;
+
+	t_state.frequency = frequency;
+	if (&fe->ops)
+		frontend_ops = &fe->ops;
+	if (&frontend_ops->tuner_ops)
+		tuner_ops = &frontend_ops->tuner_ops;
+	if (tuner_ops->set_state) {
+		if ((err = tuner_ops->set_state(fe, DVBFE_TUNER_FREQUENCY, &t_state)) < 0) {
+			printk("%s: Invalid parameter\n", __func__);
+			return err;
+		}
+	}
+	printk("%s: Frequency=%d\n", __func__, t_state.frequency);
+	return 0;
+}
+
+static int tda8261_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
+{
+	struct dvb_frontend_ops	*frontend_ops = &fe->ops;
+	struct dvb_tuner_ops	*tuner_ops = &frontend_ops->tuner_ops;
+	struct tuner_state	t_state;
+	int err = 0;
+
+	if (&fe->ops)
+		frontend_ops = &fe->ops;
+	if (&frontend_ops->tuner_ops)
+		tuner_ops = &frontend_ops->tuner_ops;
+	if (tuner_ops->get_state) {
+		if ((err = tuner_ops->get_state(fe, DVBFE_TUNER_BANDWIDTH, &t_state)) < 0) {
+			printk("%s: Invalid parameter\n", __func__);
+			return err;
+		}
+		*bandwidth = t_state.bandwidth;
+	}
+	printk("%s: Bandwidth=%d\n", __func__, t_state.bandwidth);
+	return 0;
+}
diff --git a/drivers/media/dvb-frontends/tda826x.c b/drivers/media/dvb-frontends/tda826x.c
new file mode 100644
index 0000000..04bbcc2
--- /dev/null
+++ b/drivers/media/dvb-frontends/tda826x.c
@@ -0,0 +1,188 @@
+  /*
+     Driver for Philips tda8262/tda8263 DVBS Silicon tuners
+
+     (c) 2006 Andrew de Quincey
+
+     This program is free software; you can redistribute it and/or modify
+     it under the terms of the 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/slab.h>
+#include <linux/module.h>
+#include <linux/dvb/frontend.h>
+#include <asm/types.h>
+
+#include "tda826x.h"
+
+static int debug;
+#define dprintk(args...) \
+	do { \
+		if (debug) printk(KERN_DEBUG "tda826x: " args); \
+	} while (0)
+
+struct tda826x_priv {
+	/* i2c details */
+	int i2c_address;
+	struct i2c_adapter *i2c;
+	u8 has_loopthrough:1;
+	u32 frequency;
+};
+
+static int tda826x_release(struct dvb_frontend *fe)
+{
+	kfree(fe->tuner_priv);
+	fe->tuner_priv = NULL;
+	return 0;
+}
+
+static int tda826x_sleep(struct dvb_frontend *fe)
+{
+	struct tda826x_priv *priv = fe->tuner_priv;
+	int ret;
+	u8 buf [] = { 0x00, 0x8d };
+	struct i2c_msg msg = { .addr = priv->i2c_address, .flags = 0, .buf = buf, .len = 2 };
+
+	dprintk("%s:\n", __func__);
+
+	if (!priv->has_loopthrough)
+		buf[1] = 0xad;
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+	if ((ret = i2c_transfer (priv->i2c, &msg, 1)) != 1) {
+		dprintk("%s: i2c error\n", __func__);
+	}
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 0);
+
+	return (ret == 1) ? 0 : ret;
+}
+
+static int tda826x_set_params(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct tda826x_priv *priv = fe->tuner_priv;
+	int ret;
+	u32 div;
+	u32 ksyms;
+	u32 bandwidth;
+	u8 buf [11];
+	struct i2c_msg msg = { .addr = priv->i2c_address, .flags = 0, .buf = buf, .len = 11 };
+
+	dprintk("%s:\n", __func__);
+
+	div = (p->frequency + (1000-1)) / 1000;
+
+	/* BW = ((1 + RO) * SR/2 + 5) * 1.3      [SR in MSPS, BW in MHz] */
+	/* with R0 = 0.35 and some transformations: */
+	ksyms = p->symbol_rate / 1000;
+	bandwidth = (878 * ksyms + 6500000) / 1000000 + 1;
+	if (bandwidth < 5)
+		bandwidth = 5;
+	else if (bandwidth > 36)
+		bandwidth = 36;
+
+	buf[0] = 0x00; // subaddress
+	buf[1] = 0x09; // powerdown RSSI + the magic value 1
+	if (!priv->has_loopthrough)
+		buf[1] |= 0x20; // power down loopthrough if not needed
+	buf[2] = (1<<5) | 0x0b; // 1Mhz + 0.45 VCO
+	buf[3] = div >> 7;
+	buf[4] = div << 1;
+	buf[5] = ((bandwidth - 5) << 3) | 7; /* baseband cut-off */
+	buf[6] = 0xfe; // baseband gain 9 db + no RF attenuation
+	buf[7] = 0x83; // charge pumps at high, tests off
+	buf[8] = 0x80; // recommended value 4 for AMPVCO + disable ports.
+	buf[9] = 0x1a; // normal caltime + recommended values for SELTH + SELVTL
+	buf[10] = 0xd4; // recommended value 13 for BBIAS + unknown bit set on
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+	if ((ret = i2c_transfer (priv->i2c, &msg, 1)) != 1) {
+		dprintk("%s: i2c error\n", __func__);
+	}
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 0);
+
+	priv->frequency = div * 1000;
+
+	return (ret == 1) ? 0 : ret;
+}
+
+static int tda826x_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+	struct tda826x_priv *priv = fe->tuner_priv;
+	*frequency = priv->frequency;
+	return 0;
+}
+
+static struct dvb_tuner_ops tda826x_tuner_ops = {
+	.info = {
+		.name = "Philips TDA826X",
+		.frequency_min = 950000,
+		.frequency_max = 2175000
+	},
+	.release = tda826x_release,
+	.sleep = tda826x_sleep,
+	.set_params = tda826x_set_params,
+	.get_frequency = tda826x_get_frequency,
+};
+
+struct dvb_frontend *tda826x_attach(struct dvb_frontend *fe, int addr, struct i2c_adapter *i2c, int has_loopthrough)
+{
+	struct tda826x_priv *priv = NULL;
+	u8 b1 [] = { 0, 0 };
+	struct i2c_msg msg[2] = {
+		{ .addr = addr, .flags = 0,        .buf = NULL, .len = 0 },
+		{ .addr = addr, .flags = I2C_M_RD, .buf = b1, .len = 2 }
+	};
+	int ret;
+
+	dprintk("%s:\n", __func__);
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+	ret = i2c_transfer (i2c, msg, 2);
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 0);
+
+	if (ret != 2)
+		return NULL;
+	if (!(b1[1] & 0x80))
+		return NULL;
+
+	priv = kzalloc(sizeof(struct tda826x_priv), GFP_KERNEL);
+	if (priv == NULL)
+		return NULL;
+
+	priv->i2c_address = addr;
+	priv->i2c = i2c;
+	priv->has_loopthrough = has_loopthrough;
+
+	memcpy(&fe->ops.tuner_ops, &tda826x_tuner_ops, sizeof(struct dvb_tuner_ops));
+
+	fe->tuner_priv = priv;
+
+	return fe;
+}
+EXPORT_SYMBOL(tda826x_attach);
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+
+MODULE_DESCRIPTION("DVB TDA826x driver");
+MODULE_AUTHOR("Andrew de Quincey");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb-frontends/tda826x.h b/drivers/media/dvb-frontends/tda826x.h
new file mode 100644
index 0000000..89e9792
--- /dev/null
+++ b/drivers/media/dvb-frontends/tda826x.h
@@ -0,0 +1,53 @@
+  /*
+     Driver for Philips tda8262/tda8263 DVBS Silicon tuners
+
+     (c) 2006 Andrew de Quincey
+
+     This program is free software; you can redistribute it and/or modify
+     it under the terms of the 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_TDA826X_H__
+#define __DVB_TDA826X_H__
+
+#include <linux/i2c.h>
+#include "dvb_frontend.h"
+
+/**
+ * Attach a tda826x tuner to the supplied frontend structure.
+ *
+ * @param fe Frontend to attach to.
+ * @param addr i2c address of the tuner.
+ * @param i2c i2c adapter to use.
+ * @param has_loopthrough Set to 1 if the card has a loopthrough RF connector.
+ * @return FE pointer on success, NULL on failure.
+ */
+#if defined(CONFIG_DVB_TDA826X) || (defined(CONFIG_DVB_TDA826X_MODULE) && defined(MODULE))
+extern struct dvb_frontend* tda826x_attach(struct dvb_frontend *fe, int addr,
+					   struct i2c_adapter *i2c,
+					   int has_loopthrough);
+#else
+static inline struct dvb_frontend* tda826x_attach(struct dvb_frontend *fe,
+						  int addr,
+						  struct i2c_adapter *i2c,
+						  int has_loopthrough)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif // CONFIG_DVB_TDA826X
+
+#endif // __DVB_TDA826X_H__
diff --git a/drivers/media/dvb-frontends/tdhd1.h b/drivers/media/dvb-frontends/tdhd1.h
new file mode 100644
index 0000000..1775098
--- /dev/null
+++ b/drivers/media/dvb-frontends/tdhd1.h
@@ -0,0 +1,74 @@
+/*
+ * tdhd1.h - ALPS TDHD1-204A tuner support
+ *
+ * Copyright (C) 2008 Oliver Endriss <o.endriss@gmx.de>
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * 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.
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ *
+ *
+ * The project's page is at http://www.linuxtv.org
+ */
+
+#ifndef TDHD1_H
+#define TDHD1_H
+
+#include "tda1004x.h"
+
+static int alps_tdhd1_204_request_firmware(struct dvb_frontend *fe, const struct firmware **fw, char *name);
+
+static struct tda1004x_config alps_tdhd1_204a_config = {
+	.demod_address = 0x8,
+	.invert = 1,
+	.invert_oclk = 0,
+	.xtal_freq = TDA10046_XTAL_4M,
+	.agc_config = TDA10046_AGC_DEFAULT,
+	.if_freq = TDA10046_FREQ_3617,
+	.request_firmware = alps_tdhd1_204_request_firmware
+};
+
+static int alps_tdhd1_204a_tuner_set_params(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct i2c_adapter *i2c = fe->tuner_priv;
+	u8 data[4];
+	struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
+	u32 div;
+
+	div = (p->frequency + 36166666) / 166666;
+
+	data[0] = (div >> 8) & 0x7f;
+	data[1] = div & 0xff;
+	data[2] = 0x85;
+
+	if (p->frequency >= 174000000 && p->frequency <= 230000000)
+		data[3] = 0x02;
+	else if (p->frequency >= 470000000 && p->frequency <= 823000000)
+		data[3] = 0x0C;
+	else if (p->frequency > 823000000 && p->frequency <= 862000000)
+		data[3] = 0x8C;
+	else
+		return -EINVAL;
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+	if (i2c_transfer(i2c, &msg, 1) != 1)
+		return -EIO;
+
+	return 0;
+}
+
+#endif /* TDHD1_H */
diff --git a/drivers/media/dvb-frontends/tua6100.c b/drivers/media/dvb-frontends/tua6100.c
new file mode 100644
index 0000000..029384d
--- /dev/null
+++ b/drivers/media/dvb-frontends/tua6100.c
@@ -0,0 +1,206 @@
+/**
+ * Driver for Infineon tua6100 pll.
+ *
+ * (c) 2006 Andrew de Quincey
+ *
+ * Based on code found in budget-av.c, which has the following:
+ * Compiled from various sources by Michael Hunold <michael@mihu.de>
+ *
+ * CI interface support (c) 2004 Olivier Gournet <ogournet@anevia.com> &
+ *                               Andrew de Quincey <adq_dvb@lidskialf.net>
+ *
+ * Copyright (C) 2002 Ralph Metzler <rjkm@metzlerbros.de>
+ *
+ * Copyright (C) 1999-2002 Ralph  Metzler
+ *                       & Marcus Metzler for convergence integrated media GmbH
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/slab.h>
+#include <linux/module.h>
+#include <linux/dvb/frontend.h>
+#include <asm/types.h>
+
+#include "tua6100.h"
+
+struct tua6100_priv {
+	/* i2c details */
+	int i2c_address;
+	struct i2c_adapter *i2c;
+	u32 frequency;
+};
+
+static int tua6100_release(struct dvb_frontend *fe)
+{
+	kfree(fe->tuner_priv);
+	fe->tuner_priv = NULL;
+	return 0;
+}
+
+static int tua6100_sleep(struct dvb_frontend *fe)
+{
+	struct tua6100_priv *priv = fe->tuner_priv;
+	int ret;
+	u8 reg0[] = { 0x00, 0x00 };
+	struct i2c_msg msg = { .addr = priv->i2c_address, .flags = 0, .buf = reg0, .len = 2 };
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+	if ((ret = i2c_transfer (priv->i2c, &msg, 1)) != 1) {
+		printk("%s: i2c error\n", __func__);
+	}
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 0);
+
+	return (ret == 1) ? 0 : ret;
+}
+
+static int tua6100_set_params(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	struct tua6100_priv *priv = fe->tuner_priv;
+	u32 div;
+	u32 prediv;
+	u8 reg0[] = { 0x00, 0x00 };
+	u8 reg1[] = { 0x01, 0x00, 0x00, 0x00 };
+	u8 reg2[] = { 0x02, 0x00, 0x00 };
+	struct i2c_msg msg0 = { .addr = priv->i2c_address, .flags = 0, .buf = reg0, .len = 2 };
+	struct i2c_msg msg1 = { .addr = priv->i2c_address, .flags = 0, .buf = reg1, .len = 4 };
+	struct i2c_msg msg2 = { .addr = priv->i2c_address, .flags = 0, .buf = reg2, .len = 3 };
+
+#define _R 4
+#define _P 32
+#define _ri 4000000
+
+	// setup register 0
+	if (c->frequency < 2000000)
+		reg0[1] = 0x03;
+	else
+		reg0[1] = 0x07;
+
+	// setup register 1
+	if (c->frequency < 1630000)
+		reg1[1] = 0x2c;
+	else
+		reg1[1] = 0x0c;
+
+	if (_P == 64)
+		reg1[1] |= 0x40;
+	if (c->frequency >= 1525000)
+		reg1[1] |= 0x80;
+
+	// register 2
+	reg2[1] = (_R >> 8) & 0x03;
+	reg2[2] = _R;
+	if (c->frequency < 1455000)
+		reg2[1] |= 0x1c;
+	else if (c->frequency < 1630000)
+		reg2[1] |= 0x0c;
+	else
+		reg2[1] |= 0x1c;
+
+	/*
+	 * The N divisor ratio (note: c->frequency is in kHz, but we
+	 * need it in Hz)
+	 */
+	prediv = (c->frequency * _R) / (_ri / 1000);
+	div = prediv / _P;
+	reg1[1] |= (div >> 9) & 0x03;
+	reg1[2] = div >> 1;
+	reg1[3] = (div << 7);
+	priv->frequency = ((div * _P) * (_ri / 1000)) / _R;
+
+	// Finally, calculate and store the value for A
+	reg1[3] |= (prediv - (div*_P)) & 0x7f;
+
+#undef _R
+#undef _P
+#undef _ri
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+	if (i2c_transfer(priv->i2c, &msg0, 1) != 1)
+		return -EIO;
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+	if (i2c_transfer(priv->i2c, &msg2, 1) != 1)
+		return -EIO;
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+	if (i2c_transfer(priv->i2c, &msg1, 1) != 1)
+		return -EIO;
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 0);
+
+	return 0;
+}
+
+static int tua6100_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+	struct tua6100_priv *priv = fe->tuner_priv;
+	*frequency = priv->frequency;
+	return 0;
+}
+
+static struct dvb_tuner_ops tua6100_tuner_ops = {
+	.info = {
+		.name = "Infineon TUA6100",
+		.frequency_min = 950000,
+		.frequency_max = 2150000,
+		.frequency_step = 1000,
+	},
+	.release = tua6100_release,
+	.sleep = tua6100_sleep,
+	.set_params = tua6100_set_params,
+	.get_frequency = tua6100_get_frequency,
+};
+
+struct dvb_frontend *tua6100_attach(struct dvb_frontend *fe, int addr, struct i2c_adapter *i2c)
+{
+	struct tua6100_priv *priv = NULL;
+	u8 b1 [] = { 0x80 };
+	u8 b2 [] = { 0x00 };
+	struct i2c_msg msg [] = { { .addr = addr, .flags = 0, .buf = b1, .len = 1 },
+				  { .addr = addr, .flags = I2C_M_RD, .buf = b2, .len = 1 } };
+	int ret;
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+	ret = i2c_transfer (i2c, msg, 2);
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 0);
+
+	if (ret != 2)
+		return NULL;
+
+	priv = kzalloc(sizeof(struct tua6100_priv), GFP_KERNEL);
+	if (priv == NULL)
+		return NULL;
+
+	priv->i2c_address = addr;
+	priv->i2c = i2c;
+
+	memcpy(&fe->ops.tuner_ops, &tua6100_tuner_ops, sizeof(struct dvb_tuner_ops));
+	fe->tuner_priv = priv;
+	return fe;
+}
+EXPORT_SYMBOL(tua6100_attach);
+
+MODULE_DESCRIPTION("DVB tua6100 driver");
+MODULE_AUTHOR("Andrew de Quincey");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb-frontends/tua6100.h b/drivers/media/dvb-frontends/tua6100.h
new file mode 100644
index 0000000..f83dbd5
--- /dev/null
+++ b/drivers/media/dvb-frontends/tua6100.h
@@ -0,0 +1,47 @@
+/**
+ * Driver for Infineon tua6100 PLL.
+ *
+ * (c) 2006 Andrew de Quincey
+ *
+ * Based on code found in budget-av.c, which has the following:
+ * Compiled from various sources by Michael Hunold <michael@mihu.de>
+ *
+ * CI interface support (c) 2004 Olivier Gournet <ogournet@anevia.com> &
+ *                               Andrew de Quincey <adq_dvb@lidskialf.net>
+ *
+ * Copyright (C) 2002 Ralph Metzler <rjkm@metzlerbros.de>
+ *
+ * Copyright (C) 1999-2002 Ralph  Metzler
+ *                       & Marcus Metzler for convergence integrated media GmbH
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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_TUA6100_H__
+#define __DVB_TUA6100_H__
+
+#include <linux/i2c.h>
+#include "dvb_frontend.h"
+
+#if defined(CONFIG_DVB_TUA6100) || (defined(CONFIG_DVB_TUA6100_MODULE) && defined(MODULE))
+extern struct dvb_frontend *tua6100_attach(struct dvb_frontend *fe, int addr, struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend* tua6100_attach(struct dvb_frontend *fe, int addr, struct i2c_adapter *i2c)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif // CONFIG_DVB_TUA6100
+
+#endif
diff --git a/drivers/media/dvb-frontends/ves1820.c b/drivers/media/dvb-frontends/ves1820.c
new file mode 100644
index 0000000..bb42b56
--- /dev/null
+++ b/drivers/media/dvb-frontends/ves1820.c
@@ -0,0 +1,447 @@
+/*
+    VES1820  - Single Chip Cable Channel Receiver driver module
+
+    Copyright (C) 1999 Convergence Integrated Media GmbH <ralph@convergence.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/delay.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <asm/div64.h>
+
+#include "dvb_frontend.h"
+#include "ves1820.h"
+
+
+
+struct ves1820_state {
+	struct i2c_adapter* i2c;
+	/* configuration settings */
+	const struct ves1820_config* config;
+	struct dvb_frontend frontend;
+
+	/* private demodulator data */
+	u8 reg0;
+	u8 pwm;
+};
+
+
+static int verbose;
+
+static u8 ves1820_inittab[] = {
+	0x69, 0x6A, 0x93, 0x1A, 0x12, 0x46, 0x26, 0x1A,
+	0x43, 0x6A, 0xAA, 0xAA, 0x1E, 0x85, 0x43, 0x20,
+	0xE0, 0x00, 0xA1, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+	0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x40
+};
+
+static int ves1820_writereg(struct ves1820_state *state, u8 reg, u8 data)
+{
+	u8 buf[] = { 0x00, reg, data };
+	struct i2c_msg msg = {.addr = state->config->demod_address,.flags = 0,.buf = buf,.len = 3 };
+	int ret;
+
+	ret = i2c_transfer(state->i2c, &msg, 1);
+
+	if (ret != 1)
+		printk("ves1820: %s(): writereg error (reg == 0x%02x, "
+			"val == 0x%02x, ret == %i)\n", __func__, reg, data, ret);
+
+	return (ret != 1) ? -EREMOTEIO : 0;
+}
+
+static u8 ves1820_readreg(struct ves1820_state *state, u8 reg)
+{
+	u8 b0[] = { 0x00, reg };
+	u8 b1[] = { 0 };
+	struct i2c_msg msg[] = {
+		{.addr = state->config->demod_address,.flags = 0,.buf = b0,.len = 2},
+		{.addr = state->config->demod_address,.flags = I2C_M_RD,.buf = b1,.len = 1}
+	};
+	int ret;
+
+	ret = i2c_transfer(state->i2c, msg, 2);
+
+	if (ret != 2)
+		printk("ves1820: %s(): readreg error (reg == 0x%02x, "
+		"ret == %i)\n", __func__, reg, ret);
+
+	return b1[0];
+}
+
+static int ves1820_setup_reg0(struct ves1820_state *state, u8 reg0, fe_spectral_inversion_t inversion)
+{
+	reg0 |= state->reg0 & 0x62;
+
+	if (INVERSION_ON == inversion) {
+		if (!state->config->invert) reg0 |= 0x20;
+		else reg0 &= ~0x20;
+	} else if (INVERSION_OFF == inversion) {
+		if (!state->config->invert) reg0 &= ~0x20;
+		else reg0 |= 0x20;
+	}
+
+	ves1820_writereg(state, 0x00, reg0 & 0xfe);
+	ves1820_writereg(state, 0x00, reg0 | 0x01);
+
+	state->reg0 = reg0;
+
+	return 0;
+}
+
+static int ves1820_set_symbolrate(struct ves1820_state *state, u32 symbolrate)
+{
+	s32 BDR;
+	s32 BDRI;
+	s16 SFIL = 0;
+	u16 NDEC = 0;
+	u32 ratio;
+	u32 fin;
+	u32 tmp;
+	u64 fptmp;
+	u64 fpxin;
+
+	if (symbolrate > state->config->xin / 2)
+		symbolrate = state->config->xin / 2;
+
+	if (symbolrate < 500000)
+		symbolrate = 500000;
+
+	if (symbolrate < state->config->xin / 16)
+		NDEC = 1;
+	if (symbolrate < state->config->xin / 32)
+		NDEC = 2;
+	if (symbolrate < state->config->xin / 64)
+		NDEC = 3;
+
+	/* yeuch! */
+	fpxin = state->config->xin * 10;
+	fptmp = fpxin; do_div(fptmp, 123);
+	if (symbolrate < fptmp)
+		SFIL = 1;
+	fptmp = fpxin; do_div(fptmp, 160);
+	if (symbolrate < fptmp)
+		SFIL = 0;
+	fptmp = fpxin; do_div(fptmp, 246);
+	if (symbolrate < fptmp)
+		SFIL = 1;
+	fptmp = fpxin; do_div(fptmp, 320);
+	if (symbolrate < fptmp)
+		SFIL = 0;
+	fptmp = fpxin; do_div(fptmp, 492);
+	if (symbolrate < fptmp)
+		SFIL = 1;
+	fptmp = fpxin; do_div(fptmp, 640);
+	if (symbolrate < fptmp)
+		SFIL = 0;
+	fptmp = fpxin; do_div(fptmp, 984);
+	if (symbolrate < fptmp)
+		SFIL = 1;
+
+	fin = state->config->xin >> 4;
+	symbolrate <<= NDEC;
+	ratio = (symbolrate << 4) / fin;
+	tmp = ((symbolrate << 4) % fin) << 8;
+	ratio = (ratio << 8) + tmp / fin;
+	tmp = (tmp % fin) << 8;
+	ratio = (ratio << 8) + DIV_ROUND_CLOSEST(tmp, fin);
+
+	BDR = ratio;
+	BDRI = (((state->config->xin << 5) / symbolrate) + 1) / 2;
+
+	if (BDRI > 0xFF)
+		BDRI = 0xFF;
+
+	SFIL = (SFIL << 4) | ves1820_inittab[0x0E];
+
+	NDEC = (NDEC << 6) | ves1820_inittab[0x03];
+
+	ves1820_writereg(state, 0x03, NDEC);
+	ves1820_writereg(state, 0x0a, BDR & 0xff);
+	ves1820_writereg(state, 0x0b, (BDR >> 8) & 0xff);
+	ves1820_writereg(state, 0x0c, (BDR >> 16) & 0x3f);
+
+	ves1820_writereg(state, 0x0d, BDRI);
+	ves1820_writereg(state, 0x0e, SFIL);
+
+	return 0;
+}
+
+static int ves1820_init(struct dvb_frontend* fe)
+{
+	struct ves1820_state* state = fe->demodulator_priv;
+	int i;
+
+	ves1820_writereg(state, 0, 0);
+
+	for (i = 0; i < sizeof(ves1820_inittab); i++)
+		ves1820_writereg(state, i, ves1820_inittab[i]);
+	if (state->config->selagc)
+		ves1820_writereg(state, 2, ves1820_inittab[2] | 0x08);
+
+	ves1820_writereg(state, 0x34, state->pwm);
+
+	return 0;
+}
+
+static int ves1820_set_parameters(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct ves1820_state* state = fe->demodulator_priv;
+	static const u8 reg0x00[] = { 0x00, 0x04, 0x08, 0x0c, 0x10 };
+	static const u8 reg0x01[] = { 140, 140, 106, 100, 92 };
+	static const u8 reg0x05[] = { 135, 100, 70, 54, 38 };
+	static const u8 reg0x08[] = { 162, 116, 67, 52, 35 };
+	static const u8 reg0x09[] = { 145, 150, 106, 126, 107 };
+	int real_qam = p->modulation - QAM_16;
+
+	if (real_qam < 0 || real_qam > 4)
+		return -EINVAL;
+
+	if (fe->ops.tuner_ops.set_params) {
+		fe->ops.tuner_ops.set_params(fe);
+		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+	}
+
+	ves1820_set_symbolrate(state, p->symbol_rate);
+	ves1820_writereg(state, 0x34, state->pwm);
+
+	ves1820_writereg(state, 0x01, reg0x01[real_qam]);
+	ves1820_writereg(state, 0x05, reg0x05[real_qam]);
+	ves1820_writereg(state, 0x08, reg0x08[real_qam]);
+	ves1820_writereg(state, 0x09, reg0x09[real_qam]);
+
+	ves1820_setup_reg0(state, reg0x00[real_qam], p->inversion);
+	ves1820_writereg(state, 2, ves1820_inittab[2] | (state->config->selagc ? 0x08 : 0));
+	return 0;
+}
+
+static int ves1820_read_status(struct dvb_frontend* fe, fe_status_t* status)
+{
+	struct ves1820_state* state = fe->demodulator_priv;
+	int sync;
+
+	*status = 0;
+	sync = ves1820_readreg(state, 0x11);
+
+	if (sync & 1)
+		*status |= FE_HAS_SIGNAL;
+
+	if (sync & 2)
+		*status |= FE_HAS_CARRIER;
+
+	if (sync & 2)	/* XXX FIXME! */
+		*status |= FE_HAS_VITERBI;
+
+	if (sync & 4)
+		*status |= FE_HAS_SYNC;
+
+	if (sync & 8)
+		*status |= FE_HAS_LOCK;
+
+	return 0;
+}
+
+static int ves1820_read_ber(struct dvb_frontend* fe, u32* ber)
+{
+	struct ves1820_state* state = fe->demodulator_priv;
+
+	u32 _ber = ves1820_readreg(state, 0x14) |
+			(ves1820_readreg(state, 0x15) << 8) |
+			((ves1820_readreg(state, 0x16) & 0x0f) << 16);
+	*ber = 10 * _ber;
+
+	return 0;
+}
+
+static int ves1820_read_signal_strength(struct dvb_frontend* fe, u16* strength)
+{
+	struct ves1820_state* state = fe->demodulator_priv;
+
+	u8 gain = ves1820_readreg(state, 0x17);
+	*strength = (gain << 8) | gain;
+
+	return 0;
+}
+
+static int ves1820_read_snr(struct dvb_frontend* fe, u16* snr)
+{
+	struct ves1820_state* state = fe->demodulator_priv;
+
+	u8 quality = ~ves1820_readreg(state, 0x18);
+	*snr = (quality << 8) | quality;
+
+	return 0;
+}
+
+static int ves1820_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
+{
+	struct ves1820_state* state = fe->demodulator_priv;
+
+	*ucblocks = ves1820_readreg(state, 0x13) & 0x7f;
+	if (*ucblocks == 0x7f)
+		*ucblocks = 0xffffffff;
+
+	/* reset uncorrected block counter */
+	ves1820_writereg(state, 0x10, ves1820_inittab[0x10] & 0xdf);
+	ves1820_writereg(state, 0x10, ves1820_inittab[0x10]);
+
+	return 0;
+}
+
+static int ves1820_get_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct ves1820_state* state = fe->demodulator_priv;
+	int sync;
+	s8 afc = 0;
+
+	sync = ves1820_readreg(state, 0x11);
+	afc = ves1820_readreg(state, 0x19);
+	if (verbose) {
+		/* AFC only valid when carrier has been recovered */
+		printk(sync & 2 ? "ves1820: AFC (%d) %dHz\n" :
+			"ves1820: [AFC (%d) %dHz]\n", afc, -((s32) p->symbol_rate * afc) >> 10);
+	}
+
+	if (!state->config->invert) {
+		p->inversion = (state->reg0 & 0x20) ? INVERSION_ON : INVERSION_OFF;
+	} else {
+		p->inversion = (!(state->reg0 & 0x20)) ? INVERSION_ON : INVERSION_OFF;
+	}
+
+	p->modulation = ((state->reg0 >> 2) & 7) + QAM_16;
+
+	p->fec_inner = FEC_NONE;
+
+	p->frequency = ((p->frequency + 31250) / 62500) * 62500;
+	if (sync & 2)
+		p->frequency -= ((s32) p->symbol_rate * afc) >> 10;
+
+	return 0;
+}
+
+static int ves1820_sleep(struct dvb_frontend* fe)
+{
+	struct ves1820_state* state = fe->demodulator_priv;
+
+	ves1820_writereg(state, 0x1b, 0x02);	/* pdown ADC */
+	ves1820_writereg(state, 0x00, 0x80);	/* standby */
+
+	return 0;
+}
+
+static int ves1820_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings)
+{
+
+	fesettings->min_delay_ms = 200;
+	fesettings->step_size = 0;
+	fesettings->max_drift = 0;
+	return 0;
+}
+
+static void ves1820_release(struct dvb_frontend* fe)
+{
+	struct ves1820_state* state = fe->demodulator_priv;
+	kfree(state);
+}
+
+static struct dvb_frontend_ops ves1820_ops;
+
+struct dvb_frontend* ves1820_attach(const struct ves1820_config* config,
+				    struct i2c_adapter* i2c,
+				    u8 pwm)
+{
+	struct ves1820_state* state = NULL;
+
+	/* allocate memory for the internal state */
+	state = kzalloc(sizeof(struct ves1820_state), GFP_KERNEL);
+	if (state == NULL)
+		goto error;
+
+	/* setup the state */
+	state->reg0 = ves1820_inittab[0];
+	state->config = config;
+	state->i2c = i2c;
+	state->pwm = pwm;
+
+	/* check if the demod is there */
+	if ((ves1820_readreg(state, 0x1a) & 0xf0) != 0x70)
+		goto error;
+
+	if (verbose)
+		printk("ves1820: pwm=0x%02x\n", state->pwm);
+
+	/* create dvb_frontend */
+	memcpy(&state->frontend.ops, &ves1820_ops, sizeof(struct dvb_frontend_ops));
+	state->frontend.ops.info.symbol_rate_min = (state->config->xin / 2) / 64;      /* SACLK/64 == (XIN/2)/64 */
+	state->frontend.ops.info.symbol_rate_max = (state->config->xin / 2) / 4;       /* SACLK/4 */
+	state->frontend.demodulator_priv = state;
+
+	return &state->frontend;
+
+error:
+	kfree(state);
+	return NULL;
+}
+
+static struct dvb_frontend_ops ves1820_ops = {
+	.delsys = { SYS_DVBC_ANNEX_A },
+	.info = {
+		.name = "VLSI VES1820 DVB-C",
+		.frequency_stepsize = 62500,
+		.frequency_min = 47000000,
+		.frequency_max = 862000000,
+		.caps = FE_CAN_QAM_16 |
+			FE_CAN_QAM_32 |
+			FE_CAN_QAM_64 |
+			FE_CAN_QAM_128 |
+			FE_CAN_QAM_256 |
+			FE_CAN_FEC_AUTO
+	},
+
+	.release = ves1820_release,
+
+	.init = ves1820_init,
+	.sleep = ves1820_sleep,
+
+	.set_frontend = ves1820_set_parameters,
+	.get_frontend = ves1820_get_frontend,
+	.get_tune_settings = ves1820_get_tune_settings,
+
+	.read_status = ves1820_read_status,
+	.read_ber = ves1820_read_ber,
+	.read_signal_strength = ves1820_read_signal_strength,
+	.read_snr = ves1820_read_snr,
+	.read_ucblocks = ves1820_read_ucblocks,
+};
+
+module_param(verbose, int, 0644);
+MODULE_PARM_DESC(verbose, "print AFC offset after tuning for debugging the PWM setting");
+
+MODULE_DESCRIPTION("VLSI VES1820 DVB-C Demodulator driver");
+MODULE_AUTHOR("Ralph Metzler, Holger Waechtler");
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(ves1820_attach);
diff --git a/drivers/media/dvb-frontends/ves1820.h b/drivers/media/dvb-frontends/ves1820.h
new file mode 100644
index 0000000..e902ed6
--- /dev/null
+++ b/drivers/media/dvb-frontends/ves1820.h
@@ -0,0 +1,56 @@
+/*
+    VES1820  - Single Chip Cable Channel Receiver driver module
+
+    Copyright (C) 1999 Convergence Integrated Media GmbH <ralph@convergence.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 VES1820_H
+#define VES1820_H
+
+#include <linux/dvb/frontend.h>
+
+#define VES1820_SELAGC_PWM 0
+#define VES1820_SELAGC_SIGNAMPERR 1
+
+struct ves1820_config
+{
+	/* the demodulator's i2c address */
+	u8 demod_address;
+
+	/* value of XIN to use */
+	u32 xin;
+
+	/* does inversion need inverted? */
+	u8 invert:1;
+
+	/* SELAGC control */
+	u8 selagc:1;
+};
+
+#if defined(CONFIG_DVB_VES1820) || (defined(CONFIG_DVB_VES1820_MODULE) && defined(MODULE))
+extern struct dvb_frontend* ves1820_attach(const struct ves1820_config* config,
+					   struct i2c_adapter* i2c, u8 pwm);
+#else
+static inline struct dvb_frontend* ves1820_attach(const struct ves1820_config* config,
+					   struct i2c_adapter* i2c, u8 pwm)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif // CONFIG_DVB_VES1820
+
+#endif // VES1820_H
diff --git a/drivers/media/dvb-frontends/ves1x93.c b/drivers/media/dvb-frontends/ves1x93.c
new file mode 100644
index 0000000..9c17eac
--- /dev/null
+++ b/drivers/media/dvb-frontends/ves1x93.c
@@ -0,0 +1,553 @@
+/*
+    Driver for VES1893 and VES1993 QPSK Demodulators
+
+    Copyright (C) 1999 Convergence Integrated Media GmbH <ralph@convergence.de>
+    Copyright (C) 2001 Ronny Strutz <3des@elitedvb.de>
+    Copyright (C) 2002 Dennis Noermann <dennis.noermann@noernet.de>
+    Copyright (C) 2002-2003 Andreas Oberritter <obi@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/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+
+#include "dvb_frontend.h"
+#include "ves1x93.h"
+
+
+struct ves1x93_state {
+	struct i2c_adapter* i2c;
+	/* configuration settings */
+	const struct ves1x93_config* config;
+	struct dvb_frontend frontend;
+
+	/* previous uncorrected block counter */
+	fe_spectral_inversion_t inversion;
+	u8 *init_1x93_tab;
+	u8 *init_1x93_wtab;
+	u8 tab_size;
+	u8 demod_type;
+	u32 frequency;
+};
+
+static int debug;
+#define dprintk	if (debug) printk
+
+#define DEMOD_VES1893		0
+#define DEMOD_VES1993		1
+
+static u8 init_1893_tab [] = {
+	0x01, 0xa4, 0x35, 0x80, 0x2a, 0x0b, 0x55, 0xc4,
+	0x09, 0x69, 0x00, 0x86, 0x4c, 0x28, 0x7f, 0x00,
+	0x00, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x80, 0x00, 0x21, 0xb0, 0x14, 0x00, 0xdc, 0x00,
+	0x81, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x55, 0x00, 0x00, 0x7f, 0x00
+};
+
+static u8 init_1993_tab [] = {
+	0x00, 0x9c, 0x35, 0x80, 0x6a, 0x09, 0x72, 0x8c,
+	0x09, 0x6b, 0x00, 0x00, 0x4c, 0x08, 0x00, 0x00,
+	0x00, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x80, 0x40, 0x21, 0xb0, 0x00, 0x00, 0x00, 0x10,
+	0x81, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x55, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03,
+	0x00, 0x00, 0x0e, 0x80, 0x00
+};
+
+static u8 init_1893_wtab[] =
+{
+	1,1,1,1,1,1,1,1, 1,1,0,0,1,1,0,0,
+	0,1,0,0,0,0,0,0, 1,0,1,1,0,0,0,1,
+	1,1,1,0,0,0,0,0, 0,0,1,1,0,0,0,0,
+	1,1,1,0,1,1
+};
+
+static u8 init_1993_wtab[] =
+{
+	1,1,1,1,1,1,1,1, 1,1,0,0,1,1,0,0,
+	0,1,0,0,0,0,0,0, 1,1,1,1,0,0,0,1,
+	1,1,1,0,0,0,0,0, 0,0,1,1,0,0,0,0,
+	1,1,1,0,1,1,1,1, 1,1,1,1,1
+};
+
+static int ves1x93_writereg (struct ves1x93_state* state, u8 reg, u8 data)
+{
+	u8 buf [] = { 0x00, reg, data };
+	struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 3 };
+	int err;
+
+	if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
+		dprintk ("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __func__, err, reg, data);
+		return -EREMOTEIO;
+	}
+
+	return 0;
+}
+
+static u8 ves1x93_readreg (struct ves1x93_state* state, u8 reg)
+{
+	int ret;
+	u8 b0 [] = { 0x00, reg };
+	u8 b1 [] = { 0 };
+	struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 2 },
+			   { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } };
+
+	ret = i2c_transfer (state->i2c, msg, 2);
+
+	if (ret != 2) return ret;
+
+	return b1[0];
+}
+
+static int ves1x93_clr_bit (struct ves1x93_state* state)
+{
+	msleep(10);
+	ves1x93_writereg (state, 0, state->init_1x93_tab[0] & 0xfe);
+	ves1x93_writereg (state, 0, state->init_1x93_tab[0]);
+	msleep(50);
+	return 0;
+}
+
+static int ves1x93_set_inversion (struct ves1x93_state* state, fe_spectral_inversion_t inversion)
+{
+	u8 val;
+
+	/*
+	 * inversion on/off are interchanged because i and q seem to
+	 * be swapped on the hardware
+	 */
+
+	switch (inversion) {
+	case INVERSION_OFF:
+		val = 0xc0;
+		break;
+	case INVERSION_ON:
+		val = 0x80;
+		break;
+	case INVERSION_AUTO:
+		val = 0x00;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return ves1x93_writereg (state, 0x0c, (state->init_1x93_tab[0x0c] & 0x3f) | val);
+}
+
+static int ves1x93_set_fec (struct ves1x93_state* state, fe_code_rate_t fec)
+{
+	if (fec == FEC_AUTO)
+		return ves1x93_writereg (state, 0x0d, 0x08);
+	else if (fec < FEC_1_2 || fec > FEC_8_9)
+		return -EINVAL;
+	else
+		return ves1x93_writereg (state, 0x0d, fec - FEC_1_2);
+}
+
+static fe_code_rate_t ves1x93_get_fec (struct ves1x93_state* state)
+{
+	return FEC_1_2 + ((ves1x93_readreg (state, 0x0d) >> 4) & 0x7);
+}
+
+static int ves1x93_set_symbolrate (struct ves1x93_state* state, u32 srate)
+{
+	u32 BDR;
+	u32 ratio;
+	u8  ADCONF, FCONF, FNR, AGCR;
+	u32 BDRI;
+	u32 tmp;
+	u32 FIN;
+
+	dprintk("%s: srate == %d\n", __func__, (unsigned int) srate);
+
+	if (srate > state->config->xin/2)
+		srate = state->config->xin/2;
+
+	if (srate < 500000)
+		srate = 500000;
+
+#define MUL (1UL<<26)
+
+	FIN = (state->config->xin + 6000) >> 4;
+
+	tmp = srate << 6;
+	ratio = tmp / FIN;
+
+	tmp = (tmp % FIN) << 8;
+	ratio = (ratio << 8) + tmp / FIN;
+
+	tmp = (tmp % FIN) << 8;
+	ratio = (ratio << 8) + tmp / FIN;
+
+	FNR = 0xff;
+
+	if (ratio < MUL/3)	     FNR = 0;
+	if (ratio < (MUL*11)/50)     FNR = 1;
+	if (ratio < MUL/6)	     FNR = 2;
+	if (ratio < MUL/9)	     FNR = 3;
+	if (ratio < MUL/12)	     FNR = 4;
+	if (ratio < (MUL*11)/200)    FNR = 5;
+	if (ratio < MUL/24)	     FNR = 6;
+	if (ratio < (MUL*27)/1000)   FNR = 7;
+	if (ratio < MUL/48)	     FNR = 8;
+	if (ratio < (MUL*137)/10000) FNR = 9;
+
+	if (FNR == 0xff) {
+		ADCONF = 0x89;
+		FCONF  = 0x80;
+		FNR	= 0;
+	} else {
+		ADCONF = 0x81;
+		FCONF  = 0x88 | (FNR >> 1) | ((FNR & 0x01) << 5);
+		/*FCONF	 = 0x80 | ((FNR & 0x01) << 5) | (((FNR > 1) & 0x03) << 3) | ((FNR >> 1) & 0x07);*/
+	}
+
+	BDR = (( (ratio << (FNR >> 1)) >> 4) + 1) >> 1;
+	BDRI = ( ((FIN << 8) / ((srate << (FNR >> 1)) >> 2)) + 1) >> 1;
+
+	dprintk("FNR= %d\n", FNR);
+	dprintk("ratio= %08x\n", (unsigned int) ratio);
+	dprintk("BDR= %08x\n", (unsigned int) BDR);
+	dprintk("BDRI= %02x\n", (unsigned int) BDRI);
+
+	if (BDRI > 0xff)
+		BDRI = 0xff;
+
+	ves1x93_writereg (state, 0x06, 0xff & BDR);
+	ves1x93_writereg (state, 0x07, 0xff & (BDR >> 8));
+	ves1x93_writereg (state, 0x08, 0x0f & (BDR >> 16));
+
+	ves1x93_writereg (state, 0x09, BDRI);
+	ves1x93_writereg (state, 0x20, ADCONF);
+	ves1x93_writereg (state, 0x21, FCONF);
+
+	AGCR = state->init_1x93_tab[0x05];
+	if (state->config->invert_pwm)
+		AGCR |= 0x20;
+
+	if (srate < 6000000)
+		AGCR |= 0x80;
+	else
+		AGCR &= ~0x80;
+
+	ves1x93_writereg (state, 0x05, AGCR);
+
+	/* ves1993 hates this, will lose lock */
+	if (state->demod_type != DEMOD_VES1993)
+		ves1x93_clr_bit (state);
+
+	return 0;
+}
+
+static int ves1x93_init (struct dvb_frontend* fe)
+{
+	struct ves1x93_state* state = fe->demodulator_priv;
+	int i;
+	int val;
+
+	dprintk("%s: init chip\n", __func__);
+
+	for (i = 0; i < state->tab_size; i++) {
+		if (state->init_1x93_wtab[i]) {
+			val = state->init_1x93_tab[i];
+
+			if (state->config->invert_pwm && (i == 0x05)) val |= 0x20; /* invert PWM */
+			ves1x93_writereg (state, i, val);
+		}
+	}
+
+	return 0;
+}
+
+static int ves1x93_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltage)
+{
+	struct ves1x93_state* state = fe->demodulator_priv;
+
+	switch (voltage) {
+	case SEC_VOLTAGE_13:
+		return ves1x93_writereg (state, 0x1f, 0x20);
+	case SEC_VOLTAGE_18:
+		return ves1x93_writereg (state, 0x1f, 0x30);
+	case SEC_VOLTAGE_OFF:
+		return ves1x93_writereg (state, 0x1f, 0x00);
+	default:
+		return -EINVAL;
+	}
+}
+
+static int ves1x93_read_status(struct dvb_frontend* fe, fe_status_t* status)
+{
+	struct ves1x93_state* state = fe->demodulator_priv;
+
+	u8 sync = ves1x93_readreg (state, 0x0e);
+
+	/*
+	 * The ves1893 sometimes returns sync values that make no sense,
+	 * because, e.g., the SIGNAL bit is 0, while some of the higher
+	 * bits are 1 (and how can there be a CARRIER w/o a SIGNAL?).
+	 * Tests showed that the VITERBI and SYNC bits are returned
+	 * reliably, while the SIGNAL and CARRIER bits ar sometimes wrong.
+	 * If such a case occurs, we read the value again, until we get a
+	 * valid value.
+	 */
+	int maxtry = 10; /* just for safety - let's not get stuck here */
+	while ((sync & 0x03) != 0x03 && (sync & 0x0c) && maxtry--) {
+		msleep(10);
+		sync = ves1x93_readreg (state, 0x0e);
+	}
+
+	*status = 0;
+
+	if (sync & 1)
+		*status |= FE_HAS_SIGNAL;
+
+	if (sync & 2)
+		*status |= FE_HAS_CARRIER;
+
+	if (sync & 4)
+		*status |= FE_HAS_VITERBI;
+
+	if (sync & 8)
+		*status |= FE_HAS_SYNC;
+
+	if ((sync & 0x1f) == 0x1f)
+		*status |= FE_HAS_LOCK;
+
+	return 0;
+}
+
+static int ves1x93_read_ber(struct dvb_frontend* fe, u32* ber)
+{
+	struct ves1x93_state* state = fe->demodulator_priv;
+
+	*ber = ves1x93_readreg (state, 0x15);
+	*ber |= (ves1x93_readreg (state, 0x16) << 8);
+	*ber |= ((ves1x93_readreg (state, 0x17) & 0x0F) << 16);
+	*ber *= 10;
+
+	return 0;
+}
+
+static int ves1x93_read_signal_strength(struct dvb_frontend* fe, u16* strength)
+{
+	struct ves1x93_state* state = fe->demodulator_priv;
+
+	u8 signal = ~ves1x93_readreg (state, 0x0b);
+	*strength = (signal << 8) | signal;
+
+	return 0;
+}
+
+static int ves1x93_read_snr(struct dvb_frontend* fe, u16* snr)
+{
+	struct ves1x93_state* state = fe->demodulator_priv;
+
+	u8 _snr = ~ves1x93_readreg (state, 0x1c);
+	*snr = (_snr << 8) | _snr;
+
+	return 0;
+}
+
+static int ves1x93_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
+{
+	struct ves1x93_state* state = fe->demodulator_priv;
+
+	*ucblocks = ves1x93_readreg (state, 0x18) & 0x7f;
+
+	if (*ucblocks == 0x7f)
+		*ucblocks = 0xffffffff;   /* counter overflow... */
+
+	ves1x93_writereg (state, 0x18, 0x00);  /* reset the counter */
+	ves1x93_writereg (state, 0x18, 0x80);  /* dto. */
+
+	return 0;
+}
+
+static int ves1x93_set_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct ves1x93_state* state = fe->demodulator_priv;
+
+	if (fe->ops.tuner_ops.set_params) {
+		fe->ops.tuner_ops.set_params(fe);
+		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+	}
+	ves1x93_set_inversion (state, p->inversion);
+	ves1x93_set_fec(state, p->fec_inner);
+	ves1x93_set_symbolrate(state, p->symbol_rate);
+	state->inversion = p->inversion;
+	state->frequency = p->frequency;
+
+	return 0;
+}
+
+static int ves1x93_get_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct ves1x93_state* state = fe->demodulator_priv;
+	int afc;
+
+	afc = ((int)((char)(ves1x93_readreg (state, 0x0a) << 1)))/2;
+	afc = (afc * (int)(p->symbol_rate/1000/8))/16;
+
+	p->frequency = state->frequency - afc;
+
+	/*
+	 * inversion indicator is only valid
+	 * if auto inversion was used
+	 */
+	if (state->inversion == INVERSION_AUTO)
+		p->inversion = (ves1x93_readreg (state, 0x0f) & 2) ?
+				INVERSION_OFF : INVERSION_ON;
+	p->fec_inner = ves1x93_get_fec(state);
+	/*  XXX FIXME: timing offset !! */
+
+	return 0;
+}
+
+static int ves1x93_sleep(struct dvb_frontend* fe)
+{
+	struct ves1x93_state* state = fe->demodulator_priv;
+
+	return ves1x93_writereg (state, 0x00, 0x08);
+}
+
+static void ves1x93_release(struct dvb_frontend* fe)
+{
+	struct ves1x93_state* state = fe->demodulator_priv;
+	kfree(state);
+}
+
+static int ves1x93_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+{
+	struct ves1x93_state* state = fe->demodulator_priv;
+
+	if (enable) {
+		return ves1x93_writereg(state, 0x00, 0x11);
+	} else {
+		return ves1x93_writereg(state, 0x00, 0x01);
+	}
+}
+
+static struct dvb_frontend_ops ves1x93_ops;
+
+struct dvb_frontend* ves1x93_attach(const struct ves1x93_config* config,
+				    struct i2c_adapter* i2c)
+{
+	struct ves1x93_state* state = NULL;
+	u8 identity;
+
+	/* allocate memory for the internal state */
+	state = kzalloc(sizeof(struct ves1x93_state), GFP_KERNEL);
+	if (state == NULL) goto error;
+
+	/* setup the state */
+	state->config = config;
+	state->i2c = i2c;
+	state->inversion = INVERSION_OFF;
+
+	/* check if the demod is there + identify it */
+	identity = ves1x93_readreg(state, 0x1e);
+	switch (identity) {
+	case 0xdc: /* VES1893A rev1 */
+		printk("ves1x93: Detected ves1893a rev1\n");
+		state->demod_type = DEMOD_VES1893;
+		state->init_1x93_tab = init_1893_tab;
+		state->init_1x93_wtab = init_1893_wtab;
+		state->tab_size = sizeof(init_1893_tab);
+		break;
+
+	case 0xdd: /* VES1893A rev2 */
+		printk("ves1x93: Detected ves1893a rev2\n");
+		state->demod_type = DEMOD_VES1893;
+		state->init_1x93_tab = init_1893_tab;
+		state->init_1x93_wtab = init_1893_wtab;
+		state->tab_size = sizeof(init_1893_tab);
+		break;
+
+	case 0xde: /* VES1993 */
+		printk("ves1x93: Detected ves1993\n");
+		state->demod_type = DEMOD_VES1993;
+		state->init_1x93_tab = init_1993_tab;
+		state->init_1x93_wtab = init_1993_wtab;
+		state->tab_size = sizeof(init_1993_tab);
+		break;
+
+	default:
+		goto error;
+	}
+
+	/* create dvb_frontend */
+	memcpy(&state->frontend.ops, &ves1x93_ops, sizeof(struct dvb_frontend_ops));
+	state->frontend.demodulator_priv = state;
+	return &state->frontend;
+
+error:
+	kfree(state);
+	return NULL;
+}
+
+static struct dvb_frontend_ops ves1x93_ops = {
+	.delsys = { SYS_DVBS },
+	.info = {
+		.name			= "VLSI VES1x93 DVB-S",
+		.frequency_min		= 950000,
+		.frequency_max		= 2150000,
+		.frequency_stepsize	= 125,		 /* kHz for QPSK frontends */
+		.frequency_tolerance	= 29500,
+		.symbol_rate_min	= 1000000,
+		.symbol_rate_max	= 45000000,
+	/*	.symbol_rate_tolerance	=	???,*/
+		.caps = FE_CAN_INVERSION_AUTO |
+			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_FEC_AUTO |
+			FE_CAN_QPSK
+	},
+
+	.release = ves1x93_release,
+
+	.init = ves1x93_init,
+	.sleep = ves1x93_sleep,
+	.i2c_gate_ctrl = ves1x93_i2c_gate_ctrl,
+
+	.set_frontend = ves1x93_set_frontend,
+	.get_frontend = ves1x93_get_frontend,
+
+	.read_status = ves1x93_read_status,
+	.read_ber = ves1x93_read_ber,
+	.read_signal_strength = ves1x93_read_signal_strength,
+	.read_snr = ves1x93_read_snr,
+	.read_ucblocks = ves1x93_read_ucblocks,
+
+	.set_voltage = ves1x93_set_voltage,
+};
+
+module_param(debug, int, 0644);
+
+MODULE_DESCRIPTION("VLSI VES1x93 DVB-S Demodulator driver");
+MODULE_AUTHOR("Ralph Metzler");
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(ves1x93_attach);
diff --git a/drivers/media/dvb-frontends/ves1x93.h b/drivers/media/dvb-frontends/ves1x93.h
new file mode 100644
index 0000000..8a5a49e
--- /dev/null
+++ b/drivers/media/dvb-frontends/ves1x93.h
@@ -0,0 +1,55 @@
+/*
+    Driver for VES1893 and VES1993 QPSK Demodulators
+
+    Copyright (C) 1999 Convergence Integrated Media GmbH <ralph@convergence.de>
+    Copyright (C) 2001 Ronny Strutz <3des@elitedvb.de>
+    Copyright (C) 2002 Dennis Noermann <dennis.noermann@noernet.de>
+    Copyright (C) 2002-2003 Andreas Oberritter <obi@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 VES1X93_H
+#define VES1X93_H
+
+#include <linux/dvb/frontend.h>
+
+struct ves1x93_config
+{
+	/* the demodulator's i2c address */
+	u8 demod_address;
+
+	/* value of XIN to use */
+	u32 xin;
+
+	/* should PWM be inverted? */
+	u8 invert_pwm:1;
+};
+
+#if defined(CONFIG_DVB_VES1X93) || (defined(CONFIG_DVB_VES1X93_MODULE) && defined(MODULE))
+extern struct dvb_frontend* ves1x93_attach(const struct ves1x93_config* config,
+					   struct i2c_adapter* i2c);
+#else
+static inline struct dvb_frontend* ves1x93_attach(const struct ves1x93_config* config,
+					   struct i2c_adapter* i2c)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif // CONFIG_DVB_VES1X93
+
+#endif // VES1X93_H
diff --git a/drivers/media/dvb-frontends/z0194a.h b/drivers/media/dvb-frontends/z0194a.h
new file mode 100644
index 0000000..96d86d6
--- /dev/null
+++ b/drivers/media/dvb-frontends/z0194a.h
@@ -0,0 +1,85 @@
+/* z0194a.h Sharp z0194a tuner support
+*
+* Copyright (C) 2008 Igor M. Liplianin (liplianin@me.by)
+*
+*	This program is free software; 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.
+*
+* see Documentation/dvb/README.dvb-usb for more information
+*/
+
+#ifndef Z0194A
+#define Z0194A
+
+static int sharp_z0194a_set_symbol_rate(struct dvb_frontend *fe,
+					 u32 srate, u32 ratio)
+{
+	u8 aclk = 0;
+	u8 bclk = 0;
+
+	if (srate < 1500000) {
+		aclk = 0xb7; bclk = 0x47; }
+	else if (srate < 3000000) {
+		aclk = 0xb7; bclk = 0x4b; }
+	else if (srate < 7000000) {
+		aclk = 0xb7; bclk = 0x4f; }
+	else if (srate < 14000000) {
+		aclk = 0xb7; bclk = 0x53; }
+	else if (srate < 30000000) {
+		aclk = 0xb6; bclk = 0x53; }
+	else if (srate < 45000000) {
+		aclk = 0xb4; bclk = 0x51; }
+
+	stv0299_writereg(fe, 0x13, aclk);
+	stv0299_writereg(fe, 0x14, bclk);
+	stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
+	stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff);
+	stv0299_writereg(fe, 0x21, (ratio) & 0xf0);
+
+	return 0;
+}
+
+static u8 sharp_z0194a_inittab[] = {
+	0x01, 0x15,
+	0x02, 0x30,
+	0x03, 0x00,
+	0x04, 0x7d,   /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */
+	0x05, 0x35,   /* I2CT = 0, SCLT = 1, SDAT = 1 */
+	0x06, 0x40,   /* DAC not used, set to high impendance mode */
+	0x07, 0x00,   /* DAC LSB */
+	0x08, 0x40,   /* DiSEqC off, LNB power on OP2/LOCK pin on */
+	0x09, 0x00,   /* FIFO */
+	0x0c, 0x51,   /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */
+	0x0d, 0x82,   /* DC offset compensation = ON, beta_agc1 = 2 */
+	0x0e, 0x23,   /* alpha_tmg = 2, beta_tmg = 3 */
+	0x10, 0x3f,   /* AGC2  0x3d */
+	0x11, 0x84,
+	0x12, 0xb9,
+	0x15, 0xc9,   /* lock detector threshold */
+	0x16, 0x00,
+	0x17, 0x00,
+	0x18, 0x00,
+	0x19, 0x00,
+	0x1a, 0x00,
+	0x1f, 0x50,
+	0x20, 0x00,
+	0x21, 0x00,
+	0x22, 0x00,
+	0x23, 0x00,
+	0x28, 0x00,  /* out imp: normal  out type: parallel FEC mode:0 */
+	0x29, 0x1e,  /* 1/2 threshold */
+	0x2a, 0x14,  /* 2/3 threshold */
+	0x2b, 0x0f,  /* 3/4 threshold */
+	0x2c, 0x09,  /* 5/6 threshold */
+	0x2d, 0x05,  /* 7/8 threshold */
+	0x2e, 0x01,
+	0x31, 0x1f,  /* test all FECs */
+	0x32, 0x19,  /* viterbi and synchro search */
+	0x33, 0xfc,  /* rs control */
+	0x34, 0x93,  /* error control */
+	0x0f, 0x52,
+	0xff, 0xff
+};
+
+#endif
diff --git a/drivers/media/dvb-frontends/zl10036.c b/drivers/media/dvb-frontends/zl10036.c
new file mode 100644
index 0000000..0903d46
--- /dev/null
+++ b/drivers/media/dvb-frontends/zl10036.c
@@ -0,0 +1,520 @@
+/**
+ * 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 <linux/slab.h>
+#include <linux/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 dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct zl10036_state *state = fe->tuner_priv;
+	int ret = 0;
+	u32 frequency = p->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 * p->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, p->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][0] |= 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;
+	int ret;
+
+	if (!config) {
+		printk(KERN_ERR "%s: no config specified", __func__);
+		return NULL;
+	}
+
+	state = kzalloc(sizeof(struct zl10036_state), GFP_KERNEL);
+	if (!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:
+	kfree(state);
+	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/zl10039.c b/drivers/media/dvb-frontends/zl10039.c
new file mode 100644
index 0000000..eff9c5f
--- /dev/null
+++ b/drivers/media/dvb-frontends/zl10039.c
@@ -0,0 +1,307 @@
+/*
+ *  Driver for Zarlink ZL10039 DVB-S tuner
+ *
+ *  Copyright 2007 Jan D. Louw <jd.louw@mweb.co.za>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the 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/init.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/dvb/frontend.h>
+
+#include "dvb_frontend.h"
+#include "zl10039.h"
+
+static int debug;
+
+#define dprintk(args...) \
+	do { \
+		if (debug) \
+			printk(KERN_DEBUG args); \
+	} while (0)
+
+enum zl10039_model_id {
+	ID_ZL10039 = 1
+};
+
+struct zl10039_state {
+	struct i2c_adapter *i2c;
+	u8 i2c_addr;
+	u8 id;
+};
+
+enum zl10039_reg_addr {
+	PLL0 = 0,
+	PLL1,
+	PLL2,
+	PLL3,
+	RFFE,
+	BASE0,
+	BASE1,
+	BASE2,
+	LO0,
+	LO1,
+	LO2,
+	LO3,
+	LO4,
+	LO5,
+	LO6,
+	GENERAL
+};
+
+static int zl10039_read(const struct zl10039_state *state,
+			const enum zl10039_reg_addr reg, u8 *buf,
+			const size_t count)
+{
+	u8 regbuf[] = { reg };
+	struct i2c_msg msg[] = {
+		{/* Write register address */
+			.addr = state->i2c_addr,
+			.flags = 0,
+			.buf = regbuf,
+			.len = 1,
+		}, {/* Read count bytes */
+			.addr = state->i2c_addr,
+			.flags = I2C_M_RD,
+			.buf = buf,
+			.len = count,
+		},
+	};
+
+	dprintk("%s\n", __func__);
+
+	if (i2c_transfer(state->i2c, msg, 2) != 2) {
+		dprintk("%s: i2c read error\n", __func__);
+		return -EREMOTEIO;
+	}
+
+	return 0; /* Success */
+}
+
+static int zl10039_write(struct zl10039_state *state,
+			const enum zl10039_reg_addr reg, const u8 *src,
+			const size_t count)
+{
+	u8 buf[count + 1];
+	struct i2c_msg msg = {
+		.addr = state->i2c_addr,
+		.flags = 0,
+		.buf = buf,
+		.len = count + 1,
+	};
+
+	dprintk("%s\n", __func__);
+	/* Write register address and data in one go */
+	buf[0] = reg;
+	memcpy(&buf[1], src, count);
+	if (i2c_transfer(state->i2c, &msg, 1) != 1) {
+		dprintk("%s: i2c write error\n", __func__);
+		return -EREMOTEIO;
+	}
+
+	return 0; /* Success */
+}
+
+static inline int zl10039_readreg(struct zl10039_state *state,
+				const enum zl10039_reg_addr reg, u8 *val)
+{
+	return zl10039_read(state, reg, val, 1);
+}
+
+static inline int zl10039_writereg(struct zl10039_state *state,
+				const enum zl10039_reg_addr reg,
+				const u8 val)
+{
+	return zl10039_write(state, reg, &val, 1);
+}
+
+static int zl10039_init(struct dvb_frontend *fe)
+{
+	struct zl10039_state *state = fe->tuner_priv;
+	int ret;
+
+	dprintk("%s\n", __func__);
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+	/* Reset logic */
+	ret = zl10039_writereg(state, GENERAL, 0x40);
+	if (ret < 0) {
+		dprintk("Note: i2c write error normal when resetting the "
+			"tuner\n");
+	}
+	/* Wake up */
+	ret = zl10039_writereg(state, GENERAL, 0x01);
+	if (ret < 0) {
+		dprintk("Tuner power up failed\n");
+		return ret;
+	}
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 0);
+
+	return 0;
+}
+
+static int zl10039_sleep(struct dvb_frontend *fe)
+{
+	struct zl10039_state *state = fe->tuner_priv;
+	int ret;
+
+	dprintk("%s\n", __func__);
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+	ret = zl10039_writereg(state, GENERAL, 0x80);
+	if (ret < 0) {
+		dprintk("Tuner sleep failed\n");
+		return ret;
+	}
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 0);
+
+	return 0;
+}
+
+static int zl10039_set_params(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	struct zl10039_state *state = fe->tuner_priv;
+	u8 buf[6];
+	u8 bf;
+	u32 fbw;
+	u32 div;
+	int ret;
+
+	dprintk("%s\n", __func__);
+	dprintk("Set frequency = %d, symbol rate = %d\n",
+			c->frequency, c->symbol_rate);
+
+	/* Assumed 10.111 MHz crystal oscillator */
+	/* Cancelled num/den 80 to prevent overflow */
+	div = (c->frequency * 1000) / 126387;
+	fbw = (c->symbol_rate * 27) / 32000;
+	/* Cancelled num/den 10 to prevent overflow */
+	bf = ((fbw * 5088) / 1011100) - 1;
+
+	/*PLL divider*/
+	buf[0] = (div >> 8) & 0x7f;
+	buf[1] = (div >> 0) & 0xff;
+	/*Reference divider*/
+	/* Select reference ratio of 80 */
+	buf[2] = 0x1D;
+	/*PLL test modes*/
+	buf[3] = 0x40;
+	/*RF Control register*/
+	buf[4] = 0x6E; /* Bypass enable */
+	/*Baseband filter cutoff */
+	buf[5] = bf;
+
+	/* Open i2c gate */
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+	/* BR = 10, Enable filter adjustment */
+	ret = zl10039_writereg(state, BASE1, 0x0A);
+	if (ret < 0)
+		goto error;
+	/* Write new config values */
+	ret = zl10039_write(state, PLL0, buf, sizeof(buf));
+	if (ret < 0)
+		goto error;
+	/* BR = 10, Disable filter adjustment */
+	ret = zl10039_writereg(state, BASE1, 0x6A);
+	if (ret < 0)
+		goto error;
+
+	/* Close i2c gate */
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 0);
+	return 0;
+error:
+	dprintk("Error setting tuner\n");
+	return ret;
+}
+
+static int zl10039_release(struct dvb_frontend *fe)
+{
+	struct zl10039_state *state = fe->tuner_priv;
+
+	dprintk("%s\n", __func__);
+	kfree(state);
+	fe->tuner_priv = NULL;
+	return 0;
+}
+
+static struct dvb_tuner_ops zl10039_ops = {
+	.release = zl10039_release,
+	.init = zl10039_init,
+	.sleep = zl10039_sleep,
+	.set_params = zl10039_set_params,
+};
+
+struct dvb_frontend *zl10039_attach(struct dvb_frontend *fe,
+		u8 i2c_addr, struct i2c_adapter *i2c)
+{
+	struct zl10039_state *state = NULL;
+
+	dprintk("%s\n", __func__);
+	state = kmalloc(sizeof(struct zl10039_state), GFP_KERNEL);
+	if (state == NULL)
+		goto error;
+
+	state->i2c = i2c;
+	state->i2c_addr = i2c_addr;
+
+	/* Open i2c gate */
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+	/* check if this is a valid tuner */
+	if (zl10039_readreg(state, GENERAL, &state->id) < 0) {
+		/* Close i2c gate */
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 0);
+		goto error;
+	}
+	/* Close i2c gate */
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 0);
+
+	state->id = state->id & 0x0f;
+	switch (state->id) {
+	case ID_ZL10039:
+		strcpy(fe->ops.tuner_ops.info.name,
+			"Zarlink ZL10039 DVB-S tuner");
+		break;
+	default:
+		dprintk("Chip ID=%x does not match a known type\n", state->id);
+		goto error;
+	}
+
+	memcpy(&fe->ops.tuner_ops, &zl10039_ops, sizeof(struct dvb_tuner_ops));
+	fe->tuner_priv = state;
+	dprintk("Tuner attached @ i2c address 0x%02x\n", i2c_addr);
+	return fe;
+error:
+	kfree(state);
+	return NULL;
+}
+EXPORT_SYMBOL(zl10039_attach);
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+MODULE_DESCRIPTION("Zarlink ZL10039 DVB-S tuner driver");
+MODULE_AUTHOR("Jan D. Louw <jd.louw@mweb.co.za>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb-frontends/zl10039.h b/drivers/media/dvb-frontends/zl10039.h
new file mode 100644
index 0000000..5eee7ea
--- /dev/null
+++ b/drivers/media/dvb-frontends/zl10039.h
@@ -0,0 +1,40 @@
+/*
+    Driver for Zarlink ZL10039 DVB-S tuner
+
+    Copyright (C) 2007 Jan D. Louw <jd.louw@mweb.co.za>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the 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 ZL10039_H
+#define ZL10039_H
+
+#if defined(CONFIG_DVB_ZL10039) || (defined(CONFIG_DVB_ZL10039_MODULE) \
+	    && defined(MODULE))
+struct dvb_frontend *zl10039_attach(struct dvb_frontend *fe,
+					u8 i2c_addr,
+					struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend *zl10039_attach(struct dvb_frontend *fe,
+					u8 i2c_addr,
+					struct i2c_adapter *i2c)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif /* CONFIG_DVB_ZL10039 */
+
+#endif /* ZL10039_H */
diff --git a/drivers/media/dvb-frontends/zl10353.c b/drivers/media/dvb-frontends/zl10353.c
new file mode 100644
index 0000000..82946cd
--- /dev/null
+++ b/drivers/media/dvb-frontends/zl10353.c
@@ -0,0 +1,684 @@
+/*
+ * Driver for Zarlink DVB-T ZL10353 demodulator
+ *
+ * Copyright (C) 2006, 2007 Christopher Pascoe <c.pascoe@itee.uq.edu.au>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ * GNU General Public License for more details.
+ *
+ * You 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/init.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <asm/div64.h>
+
+#include "dvb_frontend.h"
+#include "zl10353_priv.h"
+#include "zl10353.h"
+
+struct zl10353_state {
+	struct i2c_adapter *i2c;
+	struct dvb_frontend frontend;
+
+	struct zl10353_config config;
+
+	u32 bandwidth;
+	u32 ucblocks;
+	u32 frequency;
+};
+
+static int debug;
+#define dprintk(args...) \
+	do { \
+		if (debug) printk(KERN_DEBUG "zl10353: " args); \
+	} while (0)
+
+static int debug_regs;
+
+static int zl10353_single_write(struct dvb_frontend *fe, u8 reg, u8 val)
+{
+	struct zl10353_state *state = fe->demodulator_priv;
+	u8 buf[2] = { reg, val };
+	struct i2c_msg msg = { .addr = state->config.demod_address, .flags = 0,
+			       .buf = buf, .len = 2 };
+	int err = i2c_transfer(state->i2c, &msg, 1);
+	if (err != 1) {
+		printk("zl10353: write to reg %x failed (err = %d)!\n", reg, err);
+		return err;
+	}
+	return 0;
+}
+
+static int zl10353_write(struct dvb_frontend *fe, const u8 ibuf[], int ilen)
+{
+	int err, i;
+	for (i = 0; i < ilen - 1; i++)
+		if ((err = zl10353_single_write(fe, ibuf[0] + i, ibuf[i + 1])))
+			return err;
+
+	return 0;
+}
+
+static int zl10353_read_register(struct zl10353_state *state, u8 reg)
+{
+	int ret;
+	u8 b0[1] = { reg };
+	u8 b1[1] = { 0 };
+	struct i2c_msg msg[2] = { { .addr = state->config.demod_address,
+				    .flags = 0,
+				    .buf = b0, .len = 1 },
+				  { .addr = state->config.demod_address,
+				    .flags = I2C_M_RD,
+				    .buf = b1, .len = 1 } };
+
+	ret = i2c_transfer(state->i2c, msg, 2);
+
+	if (ret != 2) {
+		printk("%s: readreg error (reg=%d, ret==%i)\n",
+		       __func__, reg, ret);
+		return ret;
+	}
+
+	return b1[0];
+}
+
+static void zl10353_dump_regs(struct dvb_frontend *fe)
+{
+	struct zl10353_state *state = fe->demodulator_priv;
+	int ret;
+	u8 reg;
+
+	/* Dump all registers. */
+	for (reg = 0; ; reg++) {
+		if (reg % 16 == 0) {
+			if (reg)
+				printk(KERN_CONT "\n");
+			printk(KERN_DEBUG "%02x:", reg);
+		}
+		ret = zl10353_read_register(state, reg);
+		if (ret >= 0)
+			printk(KERN_CONT " %02x", (u8)ret);
+		else
+			printk(KERN_CONT " --");
+		if (reg == 0xff)
+			break;
+	}
+	printk(KERN_CONT "\n");
+}
+
+static void zl10353_calc_nominal_rate(struct dvb_frontend *fe,
+				      u32 bandwidth,
+				      u16 *nominal_rate)
+{
+	struct zl10353_state *state = fe->demodulator_priv;
+	u32 adc_clock = 450560; /* 45.056 MHz */
+	u64 value;
+	u8 bw = bandwidth / 1000000;
+
+	if (state->config.adc_clock)
+		adc_clock = state->config.adc_clock;
+
+	value = (u64)10 * (1 << 23) / 7 * 125;
+	value = (bw * value) + adc_clock / 2;
+	do_div(value, adc_clock);
+	*nominal_rate = value;
+
+	dprintk("%s: bw %d, adc_clock %d => 0x%x\n",
+		__func__, bw, adc_clock, *nominal_rate);
+}
+
+static void zl10353_calc_input_freq(struct dvb_frontend *fe,
+				    u16 *input_freq)
+{
+	struct zl10353_state *state = fe->demodulator_priv;
+	u32 adc_clock = 450560;	/* 45.056  MHz */
+	int if2 = 361667;	/* 36.1667 MHz */
+	int ife;
+	u64 value;
+
+	if (state->config.adc_clock)
+		adc_clock = state->config.adc_clock;
+	if (state->config.if2)
+		if2 = state->config.if2;
+
+	if (adc_clock >= if2 * 2)
+		ife = if2;
+	else {
+		ife = adc_clock - (if2 % adc_clock);
+		if (ife > adc_clock / 2)
+			ife = adc_clock - ife;
+	}
+	value = (u64)65536 * ife + adc_clock / 2;
+	do_div(value, adc_clock);
+	*input_freq = -value;
+
+	dprintk("%s: if2 %d, ife %d, adc_clock %d => %d / 0x%x\n",
+		__func__, if2, ife, adc_clock, -(int)value, *input_freq);
+}
+
+static int zl10353_sleep(struct dvb_frontend *fe)
+{
+	static u8 zl10353_softdown[] = { 0x50, 0x0C, 0x44 };
+
+	zl10353_write(fe, zl10353_softdown, sizeof(zl10353_softdown));
+	return 0;
+}
+
+static int zl10353_set_parameters(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	struct zl10353_state *state = fe->demodulator_priv;
+	u16 nominal_rate, input_freq;
+	u8 pllbuf[6] = { 0x67 }, acq_ctl = 0;
+	u16 tps = 0;
+
+	state->frequency = c->frequency;
+
+	zl10353_single_write(fe, RESET, 0x80);
+	udelay(200);
+	zl10353_single_write(fe, 0xEA, 0x01);
+	udelay(200);
+	zl10353_single_write(fe, 0xEA, 0x00);
+
+	zl10353_single_write(fe, AGC_TARGET, 0x28);
+
+	if (c->transmission_mode != TRANSMISSION_MODE_AUTO)
+		acq_ctl |= (1 << 0);
+	if (c->guard_interval != GUARD_INTERVAL_AUTO)
+		acq_ctl |= (1 << 1);
+	zl10353_single_write(fe, ACQ_CTL, acq_ctl);
+
+	switch (c->bandwidth_hz) {
+	case 6000000:
+		/* These are extrapolated from the 7 and 8MHz values */
+		zl10353_single_write(fe, MCLK_RATIO, 0x97);
+		zl10353_single_write(fe, 0x64, 0x34);
+		zl10353_single_write(fe, 0xcc, 0xdd);
+		break;
+	case 7000000:
+		zl10353_single_write(fe, MCLK_RATIO, 0x86);
+		zl10353_single_write(fe, 0x64, 0x35);
+		zl10353_single_write(fe, 0xcc, 0x73);
+		break;
+	default:
+		c->bandwidth_hz = 8000000;
+		/* fall though */
+	case 8000000:
+		zl10353_single_write(fe, MCLK_RATIO, 0x75);
+		zl10353_single_write(fe, 0x64, 0x36);
+		zl10353_single_write(fe, 0xcc, 0x73);
+	}
+
+	zl10353_calc_nominal_rate(fe, c->bandwidth_hz, &nominal_rate);
+	zl10353_single_write(fe, TRL_NOMINAL_RATE_1, msb(nominal_rate));
+	zl10353_single_write(fe, TRL_NOMINAL_RATE_0, lsb(nominal_rate));
+	state->bandwidth = c->bandwidth_hz;
+
+	zl10353_calc_input_freq(fe, &input_freq);
+	zl10353_single_write(fe, INPUT_FREQ_1, msb(input_freq));
+	zl10353_single_write(fe, INPUT_FREQ_0, lsb(input_freq));
+
+	/* Hint at TPS settings */
+	switch (c->code_rate_HP) {
+	case FEC_2_3:
+		tps |= (1 << 7);
+		break;
+	case FEC_3_4:
+		tps |= (2 << 7);
+		break;
+	case FEC_5_6:
+		tps |= (3 << 7);
+		break;
+	case FEC_7_8:
+		tps |= (4 << 7);
+		break;
+	case FEC_1_2:
+	case FEC_AUTO:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (c->code_rate_LP) {
+	case FEC_2_3:
+		tps |= (1 << 4);
+		break;
+	case FEC_3_4:
+		tps |= (2 << 4);
+		break;
+	case FEC_5_6:
+		tps |= (3 << 4);
+		break;
+	case FEC_7_8:
+		tps |= (4 << 4);
+		break;
+	case FEC_1_2:
+	case FEC_AUTO:
+		break;
+	case FEC_NONE:
+		if (c->hierarchy == HIERARCHY_AUTO ||
+		    c->hierarchy == HIERARCHY_NONE)
+			break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (c->modulation) {
+	case QPSK:
+		break;
+	case QAM_AUTO:
+	case QAM_16:
+		tps |= (1 << 13);
+		break;
+	case QAM_64:
+		tps |= (2 << 13);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (c->transmission_mode) {
+	case TRANSMISSION_MODE_2K:
+	case TRANSMISSION_MODE_AUTO:
+		break;
+	case TRANSMISSION_MODE_8K:
+		tps |= (1 << 0);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (c->guard_interval) {
+	case GUARD_INTERVAL_1_32:
+	case GUARD_INTERVAL_AUTO:
+		break;
+	case GUARD_INTERVAL_1_16:
+		tps |= (1 << 2);
+		break;
+	case GUARD_INTERVAL_1_8:
+		tps |= (2 << 2);
+		break;
+	case GUARD_INTERVAL_1_4:
+		tps |= (3 << 2);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (c->hierarchy) {
+	case HIERARCHY_AUTO:
+	case HIERARCHY_NONE:
+		break;
+	case HIERARCHY_1:
+		tps |= (1 << 10);
+		break;
+	case HIERARCHY_2:
+		tps |= (2 << 10);
+		break;
+	case HIERARCHY_4:
+		tps |= (3 << 10);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	zl10353_single_write(fe, TPS_GIVEN_1, msb(tps));
+	zl10353_single_write(fe, TPS_GIVEN_0, lsb(tps));
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 0);
+
+	/*
+	 * If there is no tuner attached to the secondary I2C bus, we call
+	 * set_params to program a potential tuner attached somewhere else.
+	 * Otherwise, we update the PLL registers via calc_regs.
+	 */
+	if (state->config.no_tuner) {
+		if (fe->ops.tuner_ops.set_params) {
+			fe->ops.tuner_ops.set_params(fe);
+			if (fe->ops.i2c_gate_ctrl)
+				fe->ops.i2c_gate_ctrl(fe, 0);
+		}
+	} else if (fe->ops.tuner_ops.calc_regs) {
+		fe->ops.tuner_ops.calc_regs(fe, pllbuf + 1, 5);
+		pllbuf[1] <<= 1;
+		zl10353_write(fe, pllbuf, sizeof(pllbuf));
+	}
+
+	zl10353_single_write(fe, 0x5F, 0x13);
+
+	/* If no attached tuner or invalid PLL registers, just start the FSM. */
+	if (state->config.no_tuner || fe->ops.tuner_ops.calc_regs == NULL)
+		zl10353_single_write(fe, FSM_GO, 0x01);
+	else
+		zl10353_single_write(fe, TUNER_GO, 0x01);
+
+	return 0;
+}
+
+static int zl10353_get_parameters(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	struct zl10353_state *state = fe->demodulator_priv;
+	int s6, s9;
+	u16 tps;
+	static const u8 tps_fec_to_api[8] = {
+		FEC_1_2,
+		FEC_2_3,
+		FEC_3_4,
+		FEC_5_6,
+		FEC_7_8,
+		FEC_AUTO,
+		FEC_AUTO,
+		FEC_AUTO
+	};
+
+	s6 = zl10353_read_register(state, STATUS_6);
+	s9 = zl10353_read_register(state, STATUS_9);
+	if (s6 < 0 || s9 < 0)
+		return -EREMOTEIO;
+	if ((s6 & (1 << 5)) == 0 || (s9 & (1 << 4)) == 0)
+		return -EINVAL;	/* no FE or TPS lock */
+
+	tps = zl10353_read_register(state, TPS_RECEIVED_1) << 8 |
+	      zl10353_read_register(state, TPS_RECEIVED_0);
+
+	c->code_rate_HP = tps_fec_to_api[(tps >> 7) & 7];
+	c->code_rate_LP = tps_fec_to_api[(tps >> 4) & 7];
+
+	switch ((tps >> 13) & 3) {
+	case 0:
+		c->modulation = QPSK;
+		break;
+	case 1:
+		c->modulation = QAM_16;
+		break;
+	case 2:
+		c->modulation = QAM_64;
+		break;
+	default:
+		c->modulation = QAM_AUTO;
+		break;
+	}
+
+	c->transmission_mode = (tps & 0x01) ? TRANSMISSION_MODE_8K :
+					       TRANSMISSION_MODE_2K;
+
+	switch ((tps >> 2) & 3) {
+	case 0:
+		c->guard_interval = GUARD_INTERVAL_1_32;
+		break;
+	case 1:
+		c->guard_interval = GUARD_INTERVAL_1_16;
+		break;
+	case 2:
+		c->guard_interval = GUARD_INTERVAL_1_8;
+		break;
+	case 3:
+		c->guard_interval = GUARD_INTERVAL_1_4;
+		break;
+	default:
+		c->guard_interval = GUARD_INTERVAL_AUTO;
+		break;
+	}
+
+	switch ((tps >> 10) & 7) {
+	case 0:
+		c->hierarchy = HIERARCHY_NONE;
+		break;
+	case 1:
+		c->hierarchy = HIERARCHY_1;
+		break;
+	case 2:
+		c->hierarchy = HIERARCHY_2;
+		break;
+	case 3:
+		c->hierarchy = HIERARCHY_4;
+		break;
+	default:
+		c->hierarchy = HIERARCHY_AUTO;
+		break;
+	}
+
+	c->frequency = state->frequency;
+	c->bandwidth_hz = state->bandwidth;
+	c->inversion = INVERSION_AUTO;
+
+	return 0;
+}
+
+static int zl10353_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+	struct zl10353_state *state = fe->demodulator_priv;
+	int s6, s7, s8;
+
+	if ((s6 = zl10353_read_register(state, STATUS_6)) < 0)
+		return -EREMOTEIO;
+	if ((s7 = zl10353_read_register(state, STATUS_7)) < 0)
+		return -EREMOTEIO;
+	if ((s8 = zl10353_read_register(state, STATUS_8)) < 0)
+		return -EREMOTEIO;
+
+	*status = 0;
+	if (s6 & (1 << 2))
+		*status |= FE_HAS_CARRIER;
+	if (s6 & (1 << 1))
+		*status |= FE_HAS_VITERBI;
+	if (s6 & (1 << 5))
+		*status |= FE_HAS_LOCK;
+	if (s7 & (1 << 4))
+		*status |= FE_HAS_SYNC;
+	if (s8 & (1 << 6))
+		*status |= FE_HAS_SIGNAL;
+
+	if ((*status & (FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC)) !=
+	    (FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC))
+		*status &= ~FE_HAS_LOCK;
+
+	return 0;
+}
+
+static int zl10353_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+	struct zl10353_state *state = fe->demodulator_priv;
+
+	*ber = zl10353_read_register(state, RS_ERR_CNT_2) << 16 |
+	       zl10353_read_register(state, RS_ERR_CNT_1) << 8 |
+	       zl10353_read_register(state, RS_ERR_CNT_0);
+
+	return 0;
+}
+
+static int zl10353_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
+{
+	struct zl10353_state *state = fe->demodulator_priv;
+
+	u16 signal = zl10353_read_register(state, AGC_GAIN_1) << 10 |
+		     zl10353_read_register(state, AGC_GAIN_0) << 2 | 3;
+
+	*strength = ~signal;
+
+	return 0;
+}
+
+static int zl10353_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+	struct zl10353_state *state = fe->demodulator_priv;
+	u8 _snr;
+
+	if (debug_regs)
+		zl10353_dump_regs(fe);
+
+	_snr = zl10353_read_register(state, SNR);
+	*snr = 10 * _snr / 8;
+
+	return 0;
+}
+
+static int zl10353_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+	struct zl10353_state *state = fe->demodulator_priv;
+       u32 ubl = 0;
+
+       ubl = zl10353_read_register(state, RS_UBC_1) << 8 |
+	     zl10353_read_register(state, RS_UBC_0);
+
+       state->ucblocks += ubl;
+       *ucblocks = state->ucblocks;
+
+	return 0;
+}
+
+static int zl10353_get_tune_settings(struct dvb_frontend *fe,
+				     struct dvb_frontend_tune_settings
+					 *fe_tune_settings)
+{
+	fe_tune_settings->min_delay_ms = 1000;
+	fe_tune_settings->step_size = 0;
+	fe_tune_settings->max_drift = 0;
+
+	return 0;
+}
+
+static int zl10353_init(struct dvb_frontend *fe)
+{
+	struct zl10353_state *state = fe->demodulator_priv;
+	u8 zl10353_reset_attach[6] = { 0x50, 0x03, 0x64, 0x46, 0x15, 0x0F };
+
+	if (debug_regs)
+		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] ||
+	    zl10353_read_register(state, 0x51) != zl10353_reset_attach[2]) {
+		zl10353_write(fe, zl10353_reset_attach,
+				   sizeof(zl10353_reset_attach));
+		if (debug_regs)
+			zl10353_dump_regs(fe);
+	}
+
+	return 0;
+}
+
+static int zl10353_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+{
+	struct zl10353_state *state = fe->demodulator_priv;
+	u8 val = 0x0a;
+
+	if (state->config.disable_i2c_gate_ctrl) {
+		/* No tuner attached to the internal I2C bus */
+		/* If set enable I2C bridge, the main I2C bus stopped hardly */
+		return 0;
+	}
+
+	if (enable)
+		val |= 0x10;
+
+	return zl10353_single_write(fe, 0x62, val);
+}
+
+static void zl10353_release(struct dvb_frontend *fe)
+{
+	struct zl10353_state *state = fe->demodulator_priv;
+	kfree(state);
+}
+
+static struct dvb_frontend_ops zl10353_ops;
+
+struct dvb_frontend *zl10353_attach(const struct zl10353_config *config,
+				    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);
+	if (state == NULL)
+		goto error;
+
+	/* setup the state */
+	state->i2c = i2c;
+	memcpy(&state->config, config, sizeof(struct zl10353_config));
+
+	/* check if the demod is there */
+	id = zl10353_read_register(state, CHIP_ID);
+	if ((id != ID_ZL10353) && (id != ID_CE6230) && (id != ID_CE6231))
+		goto error;
+
+	/* create dvb_frontend */
+	memcpy(&state->frontend.ops, &zl10353_ops, sizeof(struct dvb_frontend_ops));
+	state->frontend.demodulator_priv = state;
+
+	return &state->frontend;
+error:
+	kfree(state);
+	return NULL;
+}
+
+static struct dvb_frontend_ops zl10353_ops = {
+	.delsys = { SYS_DVBT },
+	.info = {
+		.name			= "Zarlink ZL10353 DVB-T",
+		.frequency_min		= 174000000,
+		.frequency_max		= 862000000,
+		.frequency_stepsize	= 166667,
+		.frequency_tolerance	= 0,
+		.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_FEC_AUTO |
+			FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
+			FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |
+			FE_CAN_HIERARCHY_AUTO | FE_CAN_RECOVER |
+			FE_CAN_MUTE_TS
+	},
+
+	.release = zl10353_release,
+
+	.init = zl10353_init,
+	.sleep = zl10353_sleep,
+	.i2c_gate_ctrl = zl10353_i2c_gate_ctrl,
+	.write = zl10353_write,
+
+	.set_frontend = zl10353_set_parameters,
+	.get_frontend = zl10353_get_parameters,
+	.get_tune_settings = zl10353_get_tune_settings,
+
+	.read_status = zl10353_read_status,
+	.read_ber = zl10353_read_ber,
+	.read_signal_strength = zl10353_read_signal_strength,
+	.read_snr = zl10353_read_snr,
+	.read_ucblocks = zl10353_read_ucblocks,
+};
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
+
+module_param(debug_regs, int, 0644);
+MODULE_PARM_DESC(debug_regs, "Turn on/off frontend register dumps (default:off).");
+
+MODULE_DESCRIPTION("Zarlink ZL10353 DVB-T demodulator driver");
+MODULE_AUTHOR("Chris Pascoe");
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(zl10353_attach);
diff --git a/drivers/media/dvb-frontends/zl10353.h b/drivers/media/dvb-frontends/zl10353.h
new file mode 100644
index 0000000..6e3ca9e
--- /dev/null
+++ b/drivers/media/dvb-frontends/zl10353.h
@@ -0,0 +1,62 @@
+/*
+ *  Driver for Zarlink DVB-T ZL10353 demodulator
+ *
+ *  Copyright (C) 2006, 2007 Christopher Pascoe <c.pascoe@itee.uq.edu.au>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You 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 ZL10353_H
+#define ZL10353_H
+
+#include <linux/dvb/frontend.h>
+
+struct zl10353_config
+{
+	/* demodulator's I2C address */
+	u8 demod_address;
+
+	/* frequencies in units of 0.1kHz */
+	int adc_clock;	/* default: 450560 (45.056  MHz) */
+	int if2;	/* default: 361667 (36.1667 MHz) */
+
+	/* set if no pll is connected to the secondary i2c bus */
+	int no_tuner;
+
+	/* set if parallel ts output is required */
+	int parallel_ts;
+
+	/* 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))
+extern struct dvb_frontend* zl10353_attach(const struct zl10353_config *config,
+					   struct i2c_adapter *i2c);
+#else
+static inline struct dvb_frontend* zl10353_attach(const struct zl10353_config *config,
+					   struct i2c_adapter *i2c)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif /* CONFIG_DVB_ZL10353 */
+
+#endif /* ZL10353_H */
diff --git a/drivers/media/dvb-frontends/zl10353_priv.h b/drivers/media/dvb-frontends/zl10353_priv.h
new file mode 100644
index 0000000..e0dd1d3
--- /dev/null
+++ b/drivers/media/dvb-frontends/zl10353_priv.h
@@ -0,0 +1,79 @@
+/*
+ *  Driver for Zarlink DVB-T ZL10353 demodulator
+ *
+ *  Copyright (C) 2006, 2007 Christopher Pascoe <c.pascoe@itee.uq.edu.au>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You 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 _ZL10353_PRIV_
+#define _ZL10353_PRIV_
+
+#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)
+
+enum zl10353_reg_addr {
+	INTERRUPT_0        = 0x00,
+	INTERRUPT_1        = 0x01,
+	INTERRUPT_2        = 0x02,
+	INTERRUPT_3        = 0x03,
+	INTERRUPT_4        = 0x04,
+	INTERRUPT_5        = 0x05,
+	STATUS_6           = 0x06,
+	STATUS_7           = 0x07,
+	STATUS_8           = 0x08,
+	STATUS_9           = 0x09,
+	AGC_GAIN_1         = 0x0A,
+	AGC_GAIN_0         = 0x0B,
+	SNR                = 0x10,
+	RS_ERR_CNT_2       = 0x11,
+	RS_ERR_CNT_1       = 0x12,
+	RS_ERR_CNT_0       = 0x13,
+	RS_UBC_1           = 0x14,
+	RS_UBC_0           = 0x15,
+	TPS_RECEIVED_1     = 0x1D,
+	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,
+	ACQ_CTL            = 0x5E,
+	TRL_NOMINAL_RATE_1 = 0x65,
+	TRL_NOMINAL_RATE_0 = 0x66,
+	INPUT_FREQ_1       = 0x6C,
+	INPUT_FREQ_0       = 0x6D,
+	TPS_GIVEN_1        = 0x6E,
+	TPS_GIVEN_0        = 0x6F,
+	TUNER_GO           = 0x70,
+	FSM_GO             = 0x71,
+	CHIP_ID            = 0x7F,
+	CHAN_STEP_1        = 0xE4,
+	CHAN_STEP_0        = 0xE5,
+	OFDM_LOCK_TIME     = 0xE7,
+	FEC_LOCK_TIME      = 0xE8,
+	ACQ_DELAY          = 0xE9,
+};
+
+#endif                          /* _ZL10353_PRIV_ */
diff --git a/drivers/media/dvb/Kconfig b/drivers/media/dvb/Kconfig
deleted file mode 100644
index f6e40b3..0000000
--- a/drivers/media/dvb/Kconfig
+++ /dev/null
@@ -1,91 +0,0 @@
-#
-# DVB device configuration
-#
-
-config DVB_MAX_ADAPTERS
-	int "maximum number of DVB/ATSC adapters"
-	depends on DVB_CORE
-	default 8
-	range 1 255
-	help
-	  Maximum number of DVB/ATSC adapters. Increasing this number
-	  increases the memory consumption of the DVB subsystem even
-	  if a much lower number of DVB/ATSC adapters is present.
-	  Only values in the range 4-32 are tested.
-
-	  If you are unsure about this, use the default value 8
-
-config DVB_DYNAMIC_MINORS
-	bool "Dynamic DVB minor allocation"
-	depends on DVB_CORE
-	default n
-	help
-	  If you say Y here, the DVB subsystem will use dynamic minor
-	  allocation for any device that uses the DVB major number.
-	  This means that you can have more than 4 of a single type
-	  of device (like demuxes and frontends) per adapter, but udev
-	  will be required to manage the device nodes.
-
-	  If you are unsure about this, say N here.
-
-menuconfig DVB_CAPTURE_DRIVERS
-	bool "DVB/ATSC adapters"
-	depends on DVB_CORE
-	default y
-	---help---
-	  Say Y to select Digital TV adapters
-
-if DVB_CAPTURE_DRIVERS && DVB_CORE
-
-comment "Supported SAA7146 based PCI Adapters"
-	depends on DVB_CORE && PCI && I2C
-source "drivers/media/dvb/ttpci/Kconfig"
-
-comment "Supported USB Adapters"
-	depends on DVB_CORE && USB && I2C
-source "drivers/media/dvb/dvb-usb/Kconfig"
-source "drivers/media/dvb/ttusb-budget/Kconfig"
-source "drivers/media/dvb/ttusb-dec/Kconfig"
-source "drivers/media/dvb/siano/Kconfig"
-
-comment "Supported FlexCopII (B2C2) Adapters"
-	depends on DVB_CORE && (PCI || USB) && I2C
-source "drivers/media/dvb/b2c2/Kconfig"
-
-comment "Supported BT878 Adapters"
-	depends on DVB_CORE && PCI && I2C
-source "drivers/media/dvb/bt8xx/Kconfig"
-
-comment "Supported Pluto2 Adapters"
-	depends on DVB_CORE && PCI && I2C
-source "drivers/media/dvb/pluto2/Kconfig"
-
-comment "Supported SDMC DM1105 Adapters"
-	depends on DVB_CORE && PCI && I2C
-source "drivers/media/dvb/dm1105/Kconfig"
-
-comment "Supported FireWire (IEEE 1394) Adapters"
-	depends on DVB_CORE && FIREWIRE
-source "drivers/media/dvb/firewire/Kconfig"
-
-comment "Supported Earthsoft PT1 Adapters"
-	depends on DVB_CORE && PCI && I2C
-source "drivers/media/dvb/pt1/Kconfig"
-
-comment "Supported Mantis Adapters"
-	depends on DVB_CORE && PCI && I2C
-	source "drivers/media/dvb/mantis/Kconfig"
-
-comment "Supported nGene Adapters"
-	depends on DVB_CORE && PCI && I2C
-	source "drivers/media/dvb/ngene/Kconfig"
-
-comment "Supported ddbridge ('Octopus') Adapters"
-	depends on DVB_CORE && PCI && I2C
-	source "drivers/media/dvb/ddbridge/Kconfig"
-
-comment "Supported DVB Frontends"
-	depends on DVB_CORE
-source "drivers/media/dvb/frontends/Kconfig"
-
-endif # DVB_CAPTURE_DRIVERS
diff --git a/drivers/media/dvb/Makefile b/drivers/media/dvb/Makefile
deleted file mode 100644
index b2cefe6..0000000
--- a/drivers/media/dvb/Makefile
+++ /dev/null
@@ -1,21 +0,0 @@
-#
-# Makefile for the kernel multimedia device drivers.
-#
-
-obj-y        := dvb-core/	\
-		frontends/	\
-		ttpci/		\
-		ttusb-dec/	\
-		ttusb-budget/	\
-		b2c2/		\
-		bt8xx/		\
-		dvb-usb/	\
-		pluto2/		\
-		siano/		\
-		dm1105/		\
-		pt1/		\
-		mantis/		\
-		ngene/		\
-		ddbridge/
-
-obj-$(CONFIG_DVB_FIREDTV)	+= firewire/
diff --git a/drivers/media/dvb/b2c2/Kconfig b/drivers/media/dvb/b2c2/Kconfig
deleted file mode 100644
index 9e57814..0000000
--- a/drivers/media/dvb/b2c2/Kconfig
+++ /dev/null
@@ -1,45 +0,0 @@
-config DVB_B2C2_FLEXCOP
-	tristate "Technisat/B2C2 FlexCopII(b) and FlexCopIII adapters"
-	depends on DVB_CORE && I2C
-	select DVB_PLL if !DVB_FE_CUSTOMISE
-	select DVB_STV0299 if !DVB_FE_CUSTOMISE
-	select DVB_MT352 if !DVB_FE_CUSTOMISE
-	select DVB_MT312 if !DVB_FE_CUSTOMISE
-	select DVB_NXT200X if !DVB_FE_CUSTOMISE
-	select DVB_STV0297 if !DVB_FE_CUSTOMISE
-	select DVB_BCM3510 if !DVB_FE_CUSTOMISE
-	select DVB_LGDT330X if !DVB_FE_CUSTOMISE
-	select DVB_S5H1420 if !DVB_FE_CUSTOMISE
-	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_CUSTOMISE
-	select DVB_TUNER_CX24113 if !DVB_FE_CUSTOMISE
-	help
-	  Support for the digital TV receiver chip made by B2C2 Inc. included in
-	  Technisats PCI cards and USB boxes.
-
-	  Say Y if you own such a device and want to use it.
-
-config DVB_B2C2_FLEXCOP_PCI
-	tristate "Technisat/B2C2 Air/Sky/Cable2PC PCI"
-	depends on DVB_B2C2_FLEXCOP && PCI && I2C
-	help
-	  Support for the Air/Sky/CableStar2 PCI card (DVB/ATSC) by Technisat/B2C2.
-
-	  Say Y if you own such a device and want to use it.
-
-config DVB_B2C2_FLEXCOP_USB
-	tristate "Technisat/B2C2 Air/Sky/Cable2PC USB"
-	depends on DVB_B2C2_FLEXCOP && USB && I2C
-	help
-	  Support for the Air/Sky/Cable2PC USB1.1 box (DVB/ATSC) by Technisat/B2C2,
-
-	  Say Y if you own such a device and want to use it.
-
-config DVB_B2C2_FLEXCOP_DEBUG
-	bool "Enable debug for the B2C2 FlexCop drivers"
-	depends on DVB_B2C2_FLEXCOP
-	help
-	  Say Y if you want to enable the module option to control debug messages
-	  of all B2C2 FlexCop drivers.
diff --git a/drivers/media/dvb/b2c2/Makefile b/drivers/media/dvb/b2c2/Makefile
deleted file mode 100644
index 3d04a8d..0000000
--- a/drivers/media/dvb/b2c2/Makefile
+++ /dev/null
@@ -1,16 +0,0 @@
-b2c2-flexcop-objs = flexcop.o flexcop-fe-tuner.o flexcop-i2c.o \
-	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
-
-b2c2-flexcop-pci-objs = flexcop-pci.o
-obj-$(CONFIG_DVB_B2C2_FLEXCOP_PCI) += b2c2-flexcop-pci.o
-
-b2c2-flexcop-usb-objs = flexcop-usb.o
-obj-$(CONFIG_DVB_B2C2_FLEXCOP_USB) += b2c2-flexcop-usb.o
-
-ccflags-y += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
-ccflags-y += -Idrivers/media/common/tuners/
diff --git a/drivers/media/dvb/b2c2/flexcop-common.h b/drivers/media/dvb/b2c2/flexcop-common.h
deleted file mode 100644
index 437912e..0000000
--- a/drivers/media/dvb/b2c2/flexcop-common.h
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
- * flexcop-common.h - common header file for device-specific source files
- * see flexcop.c for copyright information
- */
-#ifndef __FLEXCOP_COMMON_H__
-#define __FLEXCOP_COMMON_H__
-
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/mutex.h>
-
-#include "flexcop-reg.h"
-
-#include "dmxdev.h"
-#include "dvb_demux.h"
-#include "dvb_filter.h"
-#include "dvb_net.h"
-#include "dvb_frontend.h"
-
-#define FC_MAX_FEED 256
-
-#ifndef FC_LOG_PREFIX
-#warning please define a log prefix for your file, using a default one
-#define FC_LOG_PREFIX "b2c2-undef"
-#endif
-
-/* Steal from usb.h */
-#undef err
-#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)
-#undef warn
-#define warn(format, arg...) \
-	printk(KERN_WARNING FC_LOG_PREFIX ": " format "\n" , ## arg)
-
-struct flexcop_dma {
-	struct pci_dev *pdev;
-
-	u8 *cpu_addr0;
-	dma_addr_t dma_addr0;
-	u8 *cpu_addr1;
-	dma_addr_t dma_addr1;
-	u32 size; /* size of each address in bytes */
-};
-
-struct flexcop_i2c_adapter {
-	struct flexcop_device *fc;
-	struct i2c_adapter i2c_adap;
-
-	u8 no_base_addr;
-	flexcop_i2c_port_t port;
-};
-
-/* Control structure for data definitions that are common to
- * the B2C2-based PCI and USB devices.
- */
-struct flexcop_device {
-	/* general */
-	struct device *dev; /* for firmware_class */
-
-#define FC_STATE_DVB_INIT 0x01
-#define FC_STATE_I2C_INIT 0x02
-#define FC_STATE_FE_INIT  0x04
-	int init_state;
-
-	/* device information */
-	int has_32_hw_pid_filter;
-	flexcop_revision_t rev;
-	flexcop_device_type_t dev_type;
-	flexcop_bus_t bus_type;
-
-	/* dvb stuff */
-	struct dvb_adapter dvb_adapter;
-	struct dvb_frontend *fe;
-	struct dvb_net dvbnet;
-	struct dvb_demux demux;
-	struct dmxdev dmxdev;
-	struct dmx_frontend hw_frontend;
-	struct dmx_frontend mem_frontend;
-	int (*fe_sleep) (struct dvb_frontend *);
-
-	struct flexcop_i2c_adapter fc_i2c_adap[3];
-	struct mutex i2c_mutex;
-	struct module *owner;
-
-	/* options and status */
-	int extra_feedcount;
-	int feedcount;
-	int pid_filtering;
-	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_access_op_t, u8 chipaddr, u8 addr, u8 *buf, u16 len);
-	int (*stream_control) (struct flexcop_device *, int);
-	int (*get_mac_addr) (struct flexcop_device *fc, int extended);
-	void *bus_specific;
-};
-
-/* exported prototypes */
-
-/* from flexcop.c */
-void flexcop_pass_dmx_data(struct flexcop_device *fc, u8 *buf, u32 len);
-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 *);
-
-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);
-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);
-
-/* from flexcop-eeprom.c */
-/* the PCI part uses this call to get the MAC address, the USB part has its own */
-int flexcop_eeprom_check_mac_addr(struct flexcop_device *fc, int extended);
-
-/* from flexcop-i2c.c */
-/* the PCI part uses this a i2c_request callback, whereas the usb part has its own
- * one. We have it in flexcop-i2c.c, because it is going via the actual
- * I2C-channel of the flexcop.
- */
-int flexcop_i2c_request(struct flexcop_i2c_adapter*, flexcop_access_op_t,
-	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);
-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);
-
-/* global prototypes for the flexcop-chip */
-/* from flexcop-fe-tuner.c */
-int flexcop_frontend_init(struct flexcop_device *fc);
-void flexcop_frontend_exit(struct flexcop_device *fc);
-
-/* from flexcop-i2c.c */
-int flexcop_i2c_init(struct flexcop_device *fc);
-void flexcop_i2c_exit(struct flexcop_device *fc);
-
-/* from flexcop-sram.c */
-int flexcop_sram_init(struct flexcop_device *fc);
-
-/* 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);
-
-/* from flexcop-hw-filter.c */
-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);
-
-void flexcop_set_mac_filter(struct flexcop_device *fc, u8 mac[6]);
-void flexcop_mac_filter_ctrl(struct flexcop_device *fc, int onoff);
-
-#endif
diff --git a/drivers/media/dvb/b2c2/flexcop-dma.c b/drivers/media/dvb/b2c2/flexcop-dma.c
deleted file mode 100644
index 2881e0d..0000000
--- a/drivers/media/dvb/b2c2/flexcop-dma.c
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * 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)
-{
-	u8 *tcpu;
-	dma_addr_t tdma = 0;
-
-	if (size % 2) {
-		err("dma buffersize has to be even.");
-		return -EINVAL;
-	}
-
-	if ((tcpu = pci_alloc_consistent(pdev, size, &tdma)) != NULL) {
-		dma->pdev = pdev;
-		dma->cpu_addr0 = tcpu;
-		dma->dma_addr0 = tdma;
-		dma->cpu_addr1 = tcpu + size/2;
-		dma->dma_addr1 = tdma + size/2;
-		dma->size = size/2;
-		return 0;
-	}
-	return -ENOMEM;
-}
-EXPORT_SYMBOL(flexcop_dma_allocate);
-
-void flexcop_dma_free(struct flexcop_dma *dma)
-{
-	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);
-
-int flexcop_dma_config(struct flexcop_device *fc,
-		struct flexcop_dma *dma,
-		flexcop_dma_index_t dma_idx)
-{
-	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;
-	v0x4.dma_0x4_write.dma_addr_size = dma->size / 4;
-
-	if ((dma_idx & FC_DMA_1) == dma_idx) {
-		fc->write_ibi_reg(fc,dma1_000,v0x0);
-		fc->write_ibi_reg(fc,dma1_004,v0x4);
-		fc->write_ibi_reg(fc,dma1_00c,v0xc);
-	} else if ((dma_idx & FC_DMA_2) == dma_idx) {
-		fc->write_ibi_reg(fc,dma2_010,v0x0);
-		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 within one "
-			"flexcop_dma_config call.");
-		return -EINVAL;
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL(flexcop_dma_config);
-
-/* start the DMA transfers, but not the DMA IRQs */
-int flexcop_dma_xfer_control(struct flexcop_device *fc,
-		flexcop_dma_index_t dma_idx,
-		flexcop_dma_addr_index_t index,
-		int onoff)
-{
-	flexcop_ibi_value v0x0,v0xc;
-	flexcop_ibi_register r0x0,r0xc;
-
-	if ((dma_idx & FC_DMA_1) == dma_idx) {
-		r0x0 = dma1_000;
-		r0xc = dma1_00c;
-	} else if ((dma_idx & FC_DMA_2) == dma_idx) {
-		r0x0 = dma2_010;
-		r0xc = dma2_01c;
-	} else {
-		err("either transfer DMA1 or DMA2 can be started within one "
-			"flexcop_dma_xfer_control call.");
-		return -EINVAL;
-	}
-
-	v0x0 = fc->read_ibi_reg(fc,r0x0);
-	v0xc = fc->read_ibi_reg(fc,r0xc);
-
-	deb_rdump("reg: %03x: %x\n",r0x0,v0x0.raw);
-	deb_rdump("reg: %03x: %x\n",r0xc,v0xc.raw);
-
-	if (index & FC_DMA_SUBADDR_0)
-		v0x0.dma_0x0.dma_0start = onoff;
-
-	if (index & FC_DMA_SUBADDR_1)
-		v0xc.dma_0xc.dma_1start = onoff;
-
-	fc->write_ibi_reg(fc,r0x0,v0x0);
-	fc->write_ibi_reg(fc,r0xc,v0xc);
-
-	deb_rdump("reg: %03x: %x\n",r0x0,v0x0.raw);
-	deb_rdump("reg: %03x: %x\n",r0xc,v0xc.raw);
-	return 0;
-}
-EXPORT_SYMBOL(flexcop_dma_xfer_control);
-
-static int flexcop_dma_remap(struct flexcop_device *fc,
-		flexcop_dma_index_t dma_idx,
-		int onoff)
-{
-	flexcop_ibi_register r = (dma_idx & FC_DMA_1) ? dma1_00c : dma2_01c;
-	flexcop_ibi_value v = fc->read_ibi_reg(fc,r);
-	deb_info("%s\n",__func__);
-	v.dma_0xc.remap_enable = onoff;
-	fc->write_ibi_reg(fc,r,v);
-	return 0;
-}
-
-int flexcop_dma_control_size_irq(struct flexcop_device *fc,
-		flexcop_dma_index_t no,
-		int onoff)
-{
-	flexcop_ibi_value v = fc->read_ibi_reg(fc,ctrl_208);
-
-	if (no & FC_DMA_1)
-		v.ctrl_208.DMA1_IRQ_Enable_sig = onoff;
-
-	if (no & FC_DMA_2)
-		v.ctrl_208.DMA2_IRQ_Enable_sig = onoff;
-
-	fc->write_ibi_reg(fc,ctrl_208,v);
-	return 0;
-}
-EXPORT_SYMBOL(flexcop_dma_control_size_irq);
-
-int flexcop_dma_control_timer_irq(struct flexcop_device *fc,
-		flexcop_dma_index_t no,
-		int onoff)
-{
-	flexcop_ibi_value v = fc->read_ibi_reg(fc,ctrl_208);
-
-	if (no & FC_DMA_1)
-		v.ctrl_208.DMA1_Timer_Enable_sig = onoff;
-
-	if (no & FC_DMA_2)
-		v.ctrl_208.DMA2_Timer_Enable_sig = onoff;
-
-	fc->write_ibi_reg(fc,ctrl_208,v);
-	return 0;
-}
-EXPORT_SYMBOL(flexcop_dma_control_timer_irq);
-
-/* 1 cycles = 1.97 msec */
-int flexcop_dma_config_timer(struct flexcop_device *fc,
-		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);
-
-	flexcop_dma_remap(fc,dma_idx,0);
-
-	deb_info("%s\n",__func__);
-	v.dma_0x4_write.dmatimer = cycles;
-	fc->write_ibi_reg(fc,r,v);
-	return 0;
-}
-EXPORT_SYMBOL(flexcop_dma_config_timer);
-
diff --git a/drivers/media/dvb/b2c2/flexcop-eeprom.c b/drivers/media/dvb/b2c2/flexcop-eeprom.c
deleted file mode 100644
index a25373a..0000000
--- a/drivers/media/dvb/b2c2/flexcop-eeprom.c
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * 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"
-
-#if 0
-/*EEPROM (Skystar2 has one "24LC08B" chip on board) */
-static int eeprom_write(struct adapter *adapter, u16 addr, u8 *buf, u16 len)
-{
-	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)
-{
-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;
-		}
-	}
-	return 0;
-}
-
-/* These functions could be used to unlock SkyStar2 cards. */
-
-static int eeprom_writeKey(struct adapter *adapter, u8 *key, u32 len)
-{
-	u8 rbuf[20];
-	u8 wbuf[20];
-
-	if (len != 16)
-		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);
-}
-
-static int eeprom_readKey(struct adapter *adapter, u8 *key, u32 len)
-{
-	u8 buf[20];
-
-	if (len != 16)
-		return 0;
-
-	if (eeprom_lrc_read(adapter, 0x3e4, 20, buf, 4) == 0)
-		return 0;
-
-	memcpy(key, buf, len);
-	return 1;
-}
-
-static char eeprom_set_mac_addr(struct adapter *adapter, char type, u8 *mac)
-{
-	u8 tmp[8];
-
-	if (type != 0) {
-		tmp[0] = mac[0];
-		tmp[1] = mac[1];
-		tmp[2] = mac[2];
-		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];
-		tmp[3] = mac[3];
-		tmp[4] = mac[4];
-		tmp[5] = mac[5];
-	}
-
-	tmp[6] = 0;
-	tmp[7] = calc_lrc(tmp, 7);
-
-	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)
-{
-	return fc->i2c_request(fc,FC_READ,FC_I2C_PORT_EEPROM,0x50,addr,buf,len);
-}
-
-#endif
-
-static u8 calc_lrc(u8 *buf, int len)
-{
-	int i;
-	u8 sum = 0;
-	for (i = 0; i < len; i++)
-		sum = sum ^ buf[i];
-	return sum;
-}
-
-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);
-	for (i = 0; i < retries; i++) {
-		ret = fc->i2c_request(&fc->fc_i2c_adap[1], op, chipaddr,
-			addr & 0xff, buf, len);
-		if (ret == 0)
-			break;
-	}
-	return ret;
-}
-
-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)
-		if (calc_lrc(buf, len - 1) != buf[len - 1])
-			ret = -EINVAL;
-	return ret;
-}
-
-/* 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 */
-int flexcop_eeprom_check_mac_addr(struct flexcop_device *fc, int extended)
-{
-	u8 buf[8];
-	int ret = 0;
-
-	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");
-			ret = -EINVAL;
-		} else
-			memcpy(fc->dvb_adapter.proposed_mac,buf,6);
-	}
-	return ret;
-}
-EXPORT_SYMBOL(flexcop_eeprom_check_mac_addr);
diff --git a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
deleted file mode 100644
index 850a6c6..0000000
--- a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
+++ /dev/null
@@ -1,678 +0,0 @@
-/*
- * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
- * flexcop-fe-tuner.c - methods for frontend attachment and DiSEqC controlling
- * see flexcop.c for copyright information
- */
-#include <media/tuner.h>
-#include "flexcop.h"
-#include "mt312.h"
-#include "stv0299.h"
-#include "s5h1420.h"
-#include "itd1000.h"
-#include "cx24113.h"
-#include "cx24123.h"
-#include "isl6421.h"
-#include "mt352.h"
-#include "bcm3510.h"
-#include "nxt200x.h"
-#include "dvb-pll.h"
-#include "lgdt330x.h"
-#include "tuner-simple.h"
-#include "stv0297.h"
-
-
-/* Can we use the specified front-end?  Remember that if we are compiled
- * into the kernel we can't call code that's in modules.  */
-#define FE_SUPPORTED(fe) (defined(CONFIG_DVB_##fe) || \
-	(defined(CONFIG_DVB_##fe##_MODULE) && defined(MODULE)))
-
-/* lnb control */
-#if FE_SUPPORTED(MT312) || FE_SUPPORTED(STV0299)
-static int flexcop_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
-{
-	struct flexcop_device *fc = fe->dvb->priv;
-	flexcop_ibi_value v;
-	deb_tuner("polarity/voltage = %u\n", voltage);
-
-	v = fc->read_ibi_reg(fc, misc_204);
-	switch (voltage) {
-	case SEC_VOLTAGE_OFF:
-		v.misc_204.ACPI1_sig = 1;
-		break;
-	case SEC_VOLTAGE_13:
-		v.misc_204.ACPI1_sig = 0;
-		v.misc_204.LNB_L_H_sig = 0;
-		break;
-	case SEC_VOLTAGE_18:
-		v.misc_204.ACPI1_sig = 0;
-		v.misc_204.LNB_L_H_sig = 1;
-		break;
-	default:
-		err("unknown SEC_VOLTAGE value");
-		return -EINVAL;
-	}
-	return fc->write_ibi_reg(fc, misc_204, v);
-}
-#endif
-
-#if FE_SUPPORTED(S5H1420) || FE_SUPPORTED(STV0299) || FE_SUPPORTED(MT312)
-static int flexcop_sleep(struct dvb_frontend* fe)
-{
-	struct flexcop_device *fc = fe->dvb->priv;
-	if (fc->fe_sleep)
-		return fc->fe_sleep(fe);
-	return 0;
-}
-#endif
-
-/* SkyStar2 DVB-S rev 2.3 */
-#if FE_SUPPORTED(MT312) && FE_SUPPORTED(PLL)
-static int flexcop_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
-{
-/* u16 wz_half_period_for_45_mhz[] = { 0x01ff, 0x0154, 0x00ff, 0x00cc }; */
-	struct flexcop_device *fc = fe->dvb->priv;
-	flexcop_ibi_value v;
-	u16 ax;
-	v.raw = 0;
-	deb_tuner("tone = %u\n",tone);
-
-	switch (tone) {
-	case SEC_TONE_ON:
-		ax = 0x01ff;
-		break;
-	case SEC_TONE_OFF:
-		ax = 0;
-		break;
-	default:
-		err("unknown SEC_TONE value");
-		return -EINVAL;
-	}
-
-	v.lnb_switch_freq_200.LNB_CTLPrescaler_sig = 1; /* divide by 2 */
-	v.lnb_switch_freq_200.LNB_CTLHighCount_sig = ax;
-	v.lnb_switch_freq_200.LNB_CTLLowCount_sig  = ax == 0 ? 0x1ff : ax;
-	return fc->write_ibi_reg(fc,lnb_switch_freq_200,v);
-}
-
-static void flexcop_diseqc_send_bit(struct dvb_frontend* fe, int data)
-{
-	flexcop_set_tone(fe, SEC_TONE_ON);
-	udelay(data ? 500 : 1000);
-	flexcop_set_tone(fe, SEC_TONE_OFF);
-	udelay(data ? 1000 : 500);
-}
-
-static void flexcop_diseqc_send_byte(struct dvb_frontend* fe, int data)
-{
-	int i, par = 1, d;
-	for (i = 7; i >= 0; i--) {
-		d = (data >> i) & 1;
-		par ^= d;
-		flexcop_diseqc_send_bit(fe, d);
-	}
-	flexcop_diseqc_send_bit(fe, par);
-}
-
-static int flexcop_send_diseqc_msg(struct dvb_frontend *fe,
-	int len, u8 *msg, unsigned long burst)
-{
-	int i;
-
-	flexcop_set_tone(fe, SEC_TONE_OFF);
-	mdelay(16);
-
-	for (i = 0; i < len; i++)
-		flexcop_diseqc_send_byte(fe,msg[i]);
-	mdelay(16);
-
-	if (burst != -1) {
-		if (burst)
-			flexcop_diseqc_send_byte(fe, 0xff);
-		else {
-			flexcop_set_tone(fe, SEC_TONE_ON);
-			mdelay(12);
-			udelay(500);
-			flexcop_set_tone(fe, SEC_TONE_OFF);
-		}
-		msleep(20);
-	}
-	return 0;
-}
-
-static int flexcop_diseqc_send_master_cmd(struct dvb_frontend *fe,
-	struct dvb_diseqc_master_cmd *cmd)
-{
-	return flexcop_send_diseqc_msg(fe, cmd->msg_len, cmd->msg, 0);
-}
-
-static int flexcop_diseqc_send_burst(struct dvb_frontend *fe,
-	fe_sec_mini_cmd_t minicmd)
-{
-	return flexcop_send_diseqc_msg(fe, 0, NULL, minicmd);
-}
-
-static struct mt312_config skystar23_samsung_tbdu18132_config = {
-	.demod_address = 0x0e,
-};
-
-static int skystar2_rev23_attach(struct flexcop_device *fc,
-	struct i2c_adapter *i2c)
-{
-	struct dvb_frontend_ops *ops;
-
-	fc->fe = dvb_attach(mt312_attach, &skystar23_samsung_tbdu18132_config, i2c);
-	if (!fc->fe)
-		return 0;
-
-	if (!dvb_attach(dvb_pll_attach, fc->fe, 0x61, i2c,
-			DVB_PLL_SAMSUNG_TBDU18132))
-		return 0;
-
-	ops = &fc->fe->ops;
-	ops->diseqc_send_master_cmd = flexcop_diseqc_send_master_cmd;
-	ops->diseqc_send_burst      = flexcop_diseqc_send_burst;
-	ops->set_tone               = flexcop_set_tone;
-	ops->set_voltage            = flexcop_set_voltage;
-	fc->fe_sleep                = ops->sleep;
-	ops->sleep                  = flexcop_sleep;
-	return 1;
-}
-#else
-#define skystar2_rev23_attach NULL
-#endif
-
-/* SkyStar2 DVB-S rev 2.6 */
-#if FE_SUPPORTED(STV0299) && FE_SUPPORTED(PLL)
-static int samsung_tbmu24112_set_symbol_rate(struct dvb_frontend *fe,
-	u32 srate, u32 ratio)
-{
-	u8 aclk = 0;
-	u8 bclk = 0;
-
-	if (srate < 1500000) {
-		aclk = 0xb7; bclk = 0x47;
-	} else if (srate < 3000000) {
-		aclk = 0xb7; bclk = 0x4b;
-	} else if (srate < 7000000) {
-		aclk = 0xb7; bclk = 0x4f;
-	} else if (srate < 14000000) {
-		aclk = 0xb7; bclk = 0x53;
-	} else if (srate < 30000000) {
-		aclk = 0xb6; bclk = 0x53;
-	} else if (srate < 45000000) {
-		aclk = 0xb4; bclk = 0x51;
-	}
-
-	stv0299_writereg(fe, 0x13, aclk);
-	stv0299_writereg(fe, 0x14, bclk);
-	stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
-	stv0299_writereg(fe, 0x20, (ratio >>  8) & 0xff);
-	stv0299_writereg(fe, 0x21,  ratio        & 0xf0);
-	return 0;
-}
-
-static u8 samsung_tbmu24112_inittab[] = {
-	0x01, 0x15,
-	0x02, 0x30,
-	0x03, 0x00,
-	0x04, 0x7D,
-	0x05, 0x35,
-	0x06, 0x02,
-	0x07, 0x00,
-	0x08, 0xC3,
-	0x0C, 0x00,
-	0x0D, 0x81,
-	0x0E, 0x23,
-	0x0F, 0x12,
-	0x10, 0x7E,
-	0x11, 0x84,
-	0x12, 0xB9,
-	0x13, 0x88,
-	0x14, 0x89,
-	0x15, 0xC9,
-	0x16, 0x00,
-	0x17, 0x5C,
-	0x18, 0x00,
-	0x19, 0x00,
-	0x1A, 0x00,
-	0x1C, 0x00,
-	0x1D, 0x00,
-	0x1E, 0x00,
-	0x1F, 0x3A,
-	0x20, 0x2E,
-	0x21, 0x80,
-	0x22, 0xFF,
-	0x23, 0xC1,
-	0x28, 0x00,
-	0x29, 0x1E,
-	0x2A, 0x14,
-	0x2B, 0x0F,
-	0x2C, 0x09,
-	0x2D, 0x05,
-	0x31, 0x1F,
-	0x32, 0x19,
-	0x33, 0xFE,
-	0x34, 0x93,
-	0xff, 0xff,
-};
-
-static struct stv0299_config samsung_tbmu24112_config = {
-	.demod_address = 0x68,
-	.inittab = samsung_tbmu24112_inittab,
-	.mclk = 88000000UL,
-	.invert = 0,
-	.skip_reinit = 0,
-	.lock_output = STV0299_LOCKOUTPUT_LK,
-	.volt13_op0_op1 = STV0299_VOLT13_OP1,
-	.min_delay_ms = 100,
-	.set_symbol_rate = samsung_tbmu24112_set_symbol_rate,
-};
-
-static int skystar2_rev26_attach(struct flexcop_device *fc,
-	struct i2c_adapter *i2c)
-{
-	fc->fe = dvb_attach(stv0299_attach, &samsung_tbmu24112_config, i2c);
-	if (!fc->fe)
-		return 0;
-
-	if (!dvb_attach(dvb_pll_attach, fc->fe, 0x61, i2c,
-			DVB_PLL_SAMSUNG_TBMU24112))
-		return 0;
-
-	fc->fe->ops.set_voltage = flexcop_set_voltage;
-	fc->fe_sleep = fc->fe->ops.sleep;
-	fc->fe->ops.sleep = flexcop_sleep;
-	return 1;
-
-}
-#else
-#define skystar2_rev26_attach NULL
-#endif
-
-/* SkyStar2 DVB-S rev 2.7 */
-#if FE_SUPPORTED(S5H1420) && FE_SUPPORTED(ISL6421) && FE_SUPPORTED(TUNER_ITD1000)
-static struct s5h1420_config skystar2_rev2_7_s5h1420_config = {
-	.demod_address = 0x53,
-	.invert = 1,
-	.repeated_start_workaround = 1,
-	.serial_mpeg = 1,
-};
-
-static struct itd1000_config skystar2_rev2_7_itd1000_config = {
-	.i2c_address = 0x61,
-};
-
-static int skystar2_rev27_attach(struct flexcop_device *fc,
-	struct i2c_adapter *i2c)
-{
-	flexcop_ibi_value r108;
-	struct i2c_adapter *i2c_tuner;
-
-	/* enable no_base_addr - no repeated start when reading */
-	fc->fc_i2c_adap[0].no_base_addr = 1;
-	fc->fe = dvb_attach(s5h1420_attach, &skystar2_rev2_7_s5h1420_config,
-			    i2c);
-	if (!fc->fe)
-		goto fail;
-
-	i2c_tuner = s5h1420_get_tuner_i2c_adapter(fc->fe);
-	if (!i2c_tuner)
-		goto fail;
-
-	fc->fe_sleep = fc->fe->ops.sleep;
-	fc->fe->ops.sleep = flexcop_sleep;
-
-	/* enable no_base_addr - no repeated start when reading */
-	fc->fc_i2c_adap[2].no_base_addr = 1;
-	if (!dvb_attach(isl6421_attach, fc->fe, &fc->fc_i2c_adap[2].i2c_adap,
-			0x08, 1, 1)) {
-		err("ISL6421 could NOT be attached");
-		goto fail_isl;
-	}
-	info("ISL6421 successfully attached");
-
-	/* the ITD1000 requires a lower i2c clock - is it a problem ? */
-	r108.raw = 0x00000506;
-	fc->write_ibi_reg(fc, tw_sm_c_108, r108);
-	if (!dvb_attach(itd1000_attach, fc->fe, i2c_tuner,
-			&skystar2_rev2_7_itd1000_config)) {
-		err("ITD1000 could NOT be attached");
-		/* Should i2c clock be restored? */
-		goto fail_isl;
-	}
-	info("ITD1000 successfully attached");
-
-	return 1;
-
-fail_isl:
-	fc->fc_i2c_adap[2].no_base_addr = 0;
-fail:
-	/* for the next devices we need it again */
-	fc->fc_i2c_adap[0].no_base_addr = 0;
-	return 0;
-}
-#else
-#define skystar2_rev27_attach NULL
-#endif
-
-/* SkyStar2 rev 2.8 */
-#if FE_SUPPORTED(CX24123) && FE_SUPPORTED(ISL6421) && FE_SUPPORTED(TUNER_CX24113)
-static struct cx24123_config skystar2_rev2_8_cx24123_config = {
-	.demod_address = 0x55,
-	.dont_use_pll = 1,
-	.agc_callback = cx24113_agc_callback,
-};
-
-static const struct cx24113_config skystar2_rev2_8_cx24113_config = {
-	.i2c_addr = 0x54,
-	.xtal_khz = 10111,
-};
-
-static int skystar2_rev28_attach(struct flexcop_device *fc,
-	struct i2c_adapter *i2c)
-{
-	struct i2c_adapter *i2c_tuner;
-
-	fc->fe = dvb_attach(cx24123_attach, &skystar2_rev2_8_cx24123_config,
-			    i2c);
-	if (!fc->fe)
-		return 0;
-
-	i2c_tuner = cx24123_get_tuner_i2c_adapter(fc->fe);
-	if (!i2c_tuner)
-		return 0;
-
-	if (!dvb_attach(cx24113_attach, fc->fe, &skystar2_rev2_8_cx24113_config,
-			i2c_tuner)) {
-		err("CX24113 could NOT be attached");
-		return 0;
-	}
-	info("CX24113 successfully attached");
-
-	fc->fc_i2c_adap[2].no_base_addr = 1;
-	if (!dvb_attach(isl6421_attach, fc->fe, &fc->fc_i2c_adap[2].i2c_adap,
-			0x08, 0, 0)) {
-		err("ISL6421 could NOT be attached");
-		fc->fc_i2c_adap[2].no_base_addr = 0;
-		return 0;
-	}
-	info("ISL6421 successfully attached");
-	/* TODO on i2c_adap[1] addr 0x11 (EEPROM) there seems to be an
-	 * IR-receiver (PIC16F818) - but the card has no input for that ??? */
-	return 1;
-}
-#else
-#define skystar2_rev28_attach NULL
-#endif
-
-/* AirStar DVB-T */
-#if FE_SUPPORTED(MT352) && FE_SUPPORTED(PLL)
-static int samsung_tdtc9251dh0_demod_init(struct dvb_frontend *fe)
-{
-	static u8 mt352_clock_config[] = { 0x89, 0x18, 0x2d };
-	static u8 mt352_reset[] = { 0x50, 0x80 };
-	static u8 mt352_adc_ctl_1_cfg[] = { 0x8E, 0x40 };
-	static u8 mt352_agc_cfg[] = { 0x67, 0x28, 0xa1 };
-	static u8 mt352_capt_range_cfg[] = { 0x75, 0x32 };
-
-	mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config));
-	udelay(2000);
-	mt352_write(fe, mt352_reset, sizeof(mt352_reset));
-	mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg));
-	mt352_write(fe, mt352_agc_cfg, sizeof(mt352_agc_cfg));
-	mt352_write(fe, mt352_capt_range_cfg, sizeof(mt352_capt_range_cfg));
-	return 0;
-}
-
-static struct mt352_config samsung_tdtc9251dh0_config = {
-	.demod_address = 0x0f,
-	.demod_init    = samsung_tdtc9251dh0_demod_init,
-};
-
-static int airstar_dvbt_attach(struct flexcop_device *fc,
-	struct i2c_adapter *i2c)
-{
-	fc->fe = dvb_attach(mt352_attach, &samsung_tdtc9251dh0_config, i2c);
-	if (!fc->fe)
-		return 0;
-
-	return !!dvb_attach(dvb_pll_attach, fc->fe, 0x61, NULL,
-			    DVB_PLL_SAMSUNG_TDTC9251DH0);
-}
-#else
-#define airstar_dvbt_attach NULL
-#endif
-
-/* AirStar ATSC 1st generation */
-#if FE_SUPPORTED(BCM3510)
-static int flexcop_fe_request_firmware(struct dvb_frontend *fe,
-	const struct firmware **fw, char* name)
-{
-	struct flexcop_device *fc = fe->dvb->priv;
-	return request_firmware(fw, name, fc->dev);
-}
-
-static struct bcm3510_config air2pc_atsc_first_gen_config = {
-	.demod_address    = 0x0f,
-	.request_firmware = flexcop_fe_request_firmware,
-};
-
-static int airstar_atsc1_attach(struct flexcop_device *fc,
-	struct i2c_adapter *i2c)
-{
-	fc->fe = dvb_attach(bcm3510_attach, &air2pc_atsc_first_gen_config, i2c);
-	return fc->fe != NULL;
-}
-#else
-#define airstar_atsc1_attach NULL
-#endif
-
-/* AirStar ATSC 2nd generation */
-#if FE_SUPPORTED(NXT200X) && FE_SUPPORTED(PLL)
-static struct nxt200x_config samsung_tbmv_config = {
-	.demod_address = 0x0a,
-};
-
-static int airstar_atsc2_attach(struct flexcop_device *fc,
-	struct i2c_adapter *i2c)
-{
-	fc->fe = dvb_attach(nxt200x_attach, &samsung_tbmv_config, i2c);
-	if (!fc->fe)
-		return 0;
-
-	return !!dvb_attach(dvb_pll_attach, fc->fe, 0x61, NULL,
-			    DVB_PLL_SAMSUNG_TBMV);
-}
-#else
-#define airstar_atsc2_attach NULL
-#endif
-
-/* AirStar ATSC 3rd generation */
-#if FE_SUPPORTED(LGDT330X)
-static struct lgdt330x_config air2pc_atsc_hd5000_config = {
-	.demod_address       = 0x59,
-	.demod_chip          = LGDT3303,
-	.serial_mpeg         = 0x04,
-	.clock_polarity_flip = 1,
-};
-
-static int airstar_atsc3_attach(struct flexcop_device *fc,
-	struct i2c_adapter *i2c)
-{
-	fc->fe = dvb_attach(lgdt330x_attach, &air2pc_atsc_hd5000_config, i2c);
-	if (!fc->fe)
-		return 0;
-
-	return !!dvb_attach(simple_tuner_attach, fc->fe, i2c, 0x61,
-			    TUNER_LG_TDVS_H06XF);
-}
-#else
-#define airstar_atsc3_attach NULL
-#endif
-
-/* CableStar2 DVB-C */
-#if FE_SUPPORTED(STV0297) && FE_SUPPORTED(PLL)
-static u8 alps_tdee4_stv0297_inittab[] = {
-	0x80, 0x01,
-	0x80, 0x00,
-	0x81, 0x01,
-	0x81, 0x00,
-	0x00, 0x48,
-	0x01, 0x58,
-	0x03, 0x00,
-	0x04, 0x00,
-	0x07, 0x00,
-	0x08, 0x00,
-	0x30, 0xff,
-	0x31, 0x9d,
-	0x32, 0xff,
-	0x33, 0x00,
-	0x34, 0x29,
-	0x35, 0x55,
-	0x36, 0x80,
-	0x37, 0x6e,
-	0x38, 0x9c,
-	0x40, 0x1a,
-	0x41, 0xfe,
-	0x42, 0x33,
-	0x43, 0x00,
-	0x44, 0xff,
-	0x45, 0x00,
-	0x46, 0x00,
-	0x49, 0x04,
-	0x4a, 0x51,
-	0x4b, 0xf8,
-	0x52, 0x30,
-	0x53, 0x06,
-	0x59, 0x06,
-	0x5a, 0x5e,
-	0x5b, 0x04,
-	0x61, 0x49,
-	0x62, 0x0a,
-	0x70, 0xff,
-	0x71, 0x04,
-	0x72, 0x00,
-	0x73, 0x00,
-	0x74, 0x0c,
-	0x80, 0x20,
-	0x81, 0x00,
-	0x82, 0x30,
-	0x83, 0x00,
-	0x84, 0x04,
-	0x85, 0x22,
-	0x86, 0x08,
-	0x87, 0x1b,
-	0x88, 0x00,
-	0x89, 0x00,
-	0x90, 0x00,
-	0x91, 0x04,
-	0xa0, 0x86,
-	0xa1, 0x00,
-	0xa2, 0x00,
-	0xb0, 0x91,
-	0xb1, 0x0b,
-	0xc0, 0x5b,
-	0xc1, 0x10,
-	0xc2, 0x12,
-	0xd0, 0x02,
-	0xd1, 0x00,
-	0xd2, 0x00,
-	0xd3, 0x00,
-	0xd4, 0x02,
-	0xd5, 0x00,
-	0xde, 0x00,
-	0xdf, 0x01,
-	0xff, 0xff,
-};
-
-static struct stv0297_config alps_tdee4_stv0297_config = {
-	.demod_address = 0x1c,
-	.inittab = alps_tdee4_stv0297_inittab,
-};
-
-static int cablestar2_attach(struct flexcop_device *fc,
-	struct i2c_adapter *i2c)
-{
-	fc->fc_i2c_adap[0].no_base_addr = 1;
-	fc->fe = dvb_attach(stv0297_attach, &alps_tdee4_stv0297_config, i2c);
-	if (!fc->fe)
-		goto fail;
-
-	/* This tuner doesn't use the stv0297's I2C gate, but instead the
-	 * tuner is connected to a different flexcop I2C adapter.  */
-	if (fc->fe->ops.i2c_gate_ctrl)
-		fc->fe->ops.i2c_gate_ctrl(fc->fe, 0);
-	fc->fe->ops.i2c_gate_ctrl = NULL;
-
-	if (!dvb_attach(dvb_pll_attach, fc->fe, 0x61,
-			&fc->fc_i2c_adap[2].i2c_adap, DVB_PLL_TDEE4))
-		goto fail;
-
-	return 1;
-
-fail:
-	/* Reset for next frontend to try */
-	fc->fc_i2c_adap[0].no_base_addr = 0;
-	return 0;
-}
-#else
-#define cablestar2_attach NULL
-#endif
-
-static struct {
-	flexcop_device_type_t type;
-	int (*attach)(struct flexcop_device *, struct i2c_adapter *);
-} flexcop_frontends[] = {
-	{ FC_SKY_REV27, skystar2_rev27_attach },
-	{ FC_SKY_REV28, skystar2_rev28_attach },
-	{ FC_SKY_REV26, skystar2_rev26_attach },
-	{ FC_AIR_DVBT, airstar_dvbt_attach },
-	{ FC_AIR_ATSC2, airstar_atsc2_attach },
-	{ FC_AIR_ATSC3, airstar_atsc3_attach },
-	{ FC_AIR_ATSC1, airstar_atsc1_attach },
-	{ FC_CABLE, cablestar2_attach },
-	{ FC_SKY_REV23, skystar2_rev23_attach },
-};
-
-/* try to figure out the frontend */
-int flexcop_frontend_init(struct flexcop_device *fc)
-{
-	int i;
-	for (i = 0; i < ARRAY_SIZE(flexcop_frontends); i++) {
-		if (!flexcop_frontends[i].attach)
-			continue;
-		/* type needs to be set before, because of some workarounds
-		 * done based on the probed card type */
-		fc->dev_type = flexcop_frontends[i].type;
-		if (flexcop_frontends[i].attach(fc, &fc->fc_i2c_adap[0].i2c_adap))
-			goto fe_found;
-		/* Clean up partially attached frontend */
-		if (fc->fe) {
-			dvb_frontend_detach(fc->fe);
-			fc->fe = NULL;
-		}
-	}
-	fc->dev_type = FC_UNK;
-	err("no frontend driver found for this B2C2/FlexCop adapter");
-	return -ENODEV;
-
-fe_found:
-	info("found '%s' .", fc->fe->ops.info.name);
-	if (dvb_register_frontend(&fc->dvb_adapter, fc->fe)) {
-		err("frontend registration failed!");
-		dvb_frontend_detach(fc->fe);
-		fc->fe = NULL;
-		return -EINVAL;
-	}
-	fc->init_state |= FC_STATE_FE_INIT;
-	return 0;
-}
-
-void flexcop_frontend_exit(struct flexcop_device *fc)
-{
-	if (fc->init_state & FC_STATE_FE_INIT) {
-		dvb_unregister_frontend(fc->fe);
-		dvb_frontend_detach(fc->fe);
-	}
-	fc->init_state &= ~FC_STATE_FE_INIT;
-}
diff --git a/drivers/media/dvb/b2c2/flexcop-hw-filter.c b/drivers/media/dvb/b2c2/flexcop-hw-filter.c
deleted file mode 100644
index 77e4547..0000000
--- a/drivers/media/dvb/b2c2/flexcop-hw-filter.c
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
- * 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");
-}
-
-void flexcop_smc_ctrl(struct flexcop_device *fc, int 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);
-}
-
-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);
-
-	v418.mac_address_418.MAC1 = mac[0];
-	v418.mac_address_418.MAC2 = mac[1];
-	v418.mac_address_418.MAC3 = mac[2];
-	v418.mac_address_418.MAC6 = mac[3];
-	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);
-}
-
-void flexcop_mac_filter_ctrl(struct flexcop_device *fc, int 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)
-{
-	/* 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);
-}
-
-static void flexcop_pid_group_filter_ctrl(struct flexcop_device *fc, int 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
- * the first 6 PIDs
- */
-
-#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);
-
-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);
-}
-
-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);
-}
-
-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);
-}
-
-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);
-}
-
-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);
-}
-
-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);
-}
-
-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");
-
-	/* 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;
-
-			/* 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;
-	}
-}
-
-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);
-		fc->fullts_streaming_state = onoff;
-	}
-	return 0;
-}
-
-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;
-
-	fc->feedcount += onoff ? 1 : -1; /* the number of PIDs/Feed currently requested */
-	if (dvbdmxfeed->index >= max_pid_filter)
-		fc->extra_feedcount += onoff ? 1 : -1;
-
-	/* toggle complete-TS-streaming when:
-	 * - pid_filtering is not enabled and it is the first or last feed requested
-	 * - pid_filtering is enabled,
-	 *   - but the number of requested feeds is exceeded
-	 *   - or the requested pid is 0x2000 */
-
-	if (!fc->pid_filtering && fc->feedcount == onoff)
-		flexcop_toggle_fullts_streaming(fc, onoff);
-
-	if (fc->pid_filtering) {
-		flexcop_pid_control \
-			(fc, dvbdmxfeed->index, dvbdmxfeed->pid, onoff);
-
-		if (fc->extra_feedcount > 0)
-			flexcop_toggle_fullts_streaming(fc, 1);
-		else if (dvbdmxfeed->pid == 0x2000)
-			flexcop_toggle_fullts_streaming(fc, onoff);
-		else
-			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);
-		if (fc->stream_control) /* device specific stream control */
-			fc->stream_control(fc, onoff);
-
-		/* feeding stopped -> reset the flexcop filter*/
-		if (onoff == 0) {
-			flexcop_reset_block_300(fc);
-			flexcop_hw_filter_init(fc);
-		}
-	}
-	return 0;
-}
-EXPORT_SYMBOL(flexcop_pid_feed_control);
-
-void flexcop_hw_filter_init(struct flexcop_device *fc)
-{
-	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_group_filter(fc, 0, 0x1fe0);
-	flexcop_pid_group_filter_ctrl(fc, 0);
-
-	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);
-
-	flexcop_null_filter_ctrl(fc, 1);
-}
diff --git a/drivers/media/dvb/b2c2/flexcop-i2c.c b/drivers/media/dvb/b2c2/flexcop-i2c.c
deleted file mode 100644
index 965d5eb..0000000
--- a/drivers/media/dvb/b2c2/flexcop-i2c.c
+++ /dev/null
@@ -1,288 +0,0 @@
-/*
- * 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
- */
-#include "flexcop.h"
-
-#define FC_MAX_I2C_RETRIES 100000
-
-static int flexcop_i2c_operation(struct flexcop_device *fc,
-		flexcop_ibi_value *r100)
-{
-	int i;
-	flexcop_ibi_value r;
-
-	r100->tw_sm_c_100.working_start = 1;
-	deb_i2c("r100 before: %08x\n",r100->raw);
-
-	fc->write_ibi_reg(fc, tw_sm_c_100, ibi_zero);
-	fc->write_ibi_reg(fc, tw_sm_c_100, *r100); /* initiating i2c operation */
-
-	for (i = 0; i < FC_MAX_I2C_RETRIES; i++) {
-		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) {
-				*r100 = r;
-				deb_i2c("i2c success\n");
-				return 0;
-			}
-		} else {
-			deb_i2c("suffering from an i2c ack_error\n");
-			return -EREMOTEIO;
-		}
-	}
-	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 r104;
-	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");
-		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("read failed. %d\n", ret);
-		return ret;
-	}
-
-	buf[0] = r100.tw_sm_c_100.data1_reg;
-
-	if (len > 0) {
-		r104 = i2c->fc->read_ibi_reg(i2c->fc, tw_sm_c_104);
-		deb_i2c("read: r100: %08x, r104: %08x\n", r100.raw, r104.raw);
-
-		/* there is at least one more byte, otherwise we wouldn't be here */
-		buf[1] = r104.tw_sm_c_104.data2_reg;
-		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)
-{
-	flexcop_ibi_value r104;
-	int len = r100.tw_sm_c_100.total_bytes; /* remember total_bytes is buflen-1 */
-	r104.raw = 0;
-
-	/* 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;
-
-	deb_i2c("write: r100: %08x, r104: %08x\n", r100.raw, r104.raw);
-
-	/* write the additional i2c data before doing the actual i2c operation */
-	fc->write_ibi_reg(fc, tw_sm_c_104, r104);
-	return flexcop_i2c_operation(fc, &r100);
-}
-
-int flexcop_i2c_request(struct flexcop_i2c_adapter *i2c,
-		flexcop_access_op_t op, u8 chipaddr, u8 addr, u8 *buf, u16 len)
-{
-	int ret;
-
-#ifdef DUMP_I2C_MESSAGES
-	int i;
-#endif
-
-	u16 bytes_to_transfer;
-	flexcop_ibi_value r100;
-
-	deb_i2c("op = %d\n",op);
-	r100.raw = 0;
-	r100.tw_sm_c_100.chipaddr = chipaddr;
-	r100.tw_sm_c_100.twoWS_rw = op;
-	r100.tw_sm_c_100.twoWS_port_reg = i2c->port;
-
-#ifdef DUMP_I2C_MESSAGES
-	printk(KERN_DEBUG "%d ", i2c->port);
-	if (op == FC_READ)
-		printk("rd(");
-	else
-		printk("wr(");
-	printk("%02x): %02x ", chipaddr, addr);
-#endif
-
-	/* in that case addr is the only value ->
-	 * we write it twice as baseaddr and val0
-	 * BBTI is doing it like that for ISL6421 at least */
-	if (i2c->no_base_addr && len == 0 && op == FC_WRITE) {
-		buf = &addr;
-		len = 1;
-	}
-
-	while (len != 0) {
-		bytes_to_transfer = len > 4 ? 4 : len;
-
-		r100.tw_sm_c_100.total_bytes = bytes_to_transfer - 1;
-		r100.tw_sm_c_100.baseaddr = addr;
-
-		if (op == FC_READ)
-			ret = flexcop_i2c_read4(i2c, r100, buf);
-		else
-			ret = flexcop_i2c_write4(i2c->fc, r100, buf);
-
-#ifdef DUMP_I2C_MESSAGES
-		for (i = 0; i < bytes_to_transfer; i++)
-			printk("%02x ", buf[i]);
-#endif
-
-		if (ret < 0)
-			return ret;
-
-		buf  += bytes_to_transfer;
-		addr += bytes_to_transfer;
-		len  -= bytes_to_transfer;
-	}
-
-#ifdef DUMP_I2C_MESSAGES
-	printk("\n");
-#endif
-
-	return 0;
-}
-/* exported for PCI i2c */
-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)
-{
-	struct flexcop_i2c_adapter *i2c = i2c_get_adapdata(i2c_adap);
-	int i, ret = 0;
-
-	/* Some drivers use 1 byte or 0 byte reads as probes, which this
-	 * driver doesn't support.  These probes will always fail, so this
-	 * hack makes them always succeed.  If one knew how, it would of
-	 * course be better to actually do the read.  */
-	if (num == 1 && msgs[0].flags == I2C_M_RD && msgs[0].len <= 1)
-		return 1;
-
-	if (mutex_lock_interruptible(&i2c->fc->i2c_mutex))
-		return -ERESTARTSYS;
-
-	for (i = 0; i < num; i++) {
-		/* 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);
-			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);
-		if (ret < 0) {
-			deb_i2c("i2c master_xfer failed");
-			break;
-		}
-	}
-
-	mutex_unlock(&i2c->fc->i2c_mutex);
-
-	if (ret == 0)
-		ret = num;
-	return ret;
-}
-
-static u32 flexcop_i2c_func(struct i2c_adapter *adapter)
-{
-	return I2C_FUNC_I2C;
-}
-
-static struct i2c_algorithm flexcop_algo = {
-	.master_xfer	= flexcop_master_xfer,
-	.functionality	= flexcop_i2c_func,
-};
-
-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));
-	strlcpy(fc->fc_i2c_adap[1].i2c_adap.name, "B2C2 FlexCop I2C to eeprom",
-			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));
-
-	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]);
-	i2c_set_adapdata(&fc->fc_i2c_adap[2].i2c_adap, &fc->fc_i2c_adap[2]);
-
-	fc->fc_i2c_adap[0].i2c_adap.algo =
-		fc->fc_i2c_adap[1].i2c_adap.algo =
-		fc->fc_i2c_adap[2].i2c_adap.algo = &flexcop_algo;
-	fc->fc_i2c_adap[0].i2c_adap.algo_data =
-		fc->fc_i2c_adap[1].i2c_adap.algo_data =
-		fc->fc_i2c_adap[2].i2c_adap.algo_data = NULL;
-	fc->fc_i2c_adap[0].i2c_adap.dev.parent =
-		fc->fc_i2c_adap[1].i2c_adap.dev.parent =
-		fc->fc_i2c_adap[2].i2c_adap.dev.parent = fc->dev;
-
-	ret = i2c_add_adapter(&fc->fc_i2c_adap[0].i2c_adap);
-	if (ret < 0)
-		return ret;
-
-	ret = i2c_add_adapter(&fc->fc_i2c_adap[1].i2c_adap);
-	if (ret < 0)
-		goto adap_1_failed;
-
-	ret = i2c_add_adapter(&fc->fc_i2c_adap[2].i2c_adap);
-	if (ret < 0)
-		goto adap_2_failed;
-
-	fc->init_state |= FC_STATE_I2C_INIT;
-	return 0;
-
-adap_2_failed:
-	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;
-}
-
-void flexcop_i2c_exit(struct flexcop_device *fc)
-{
-	if (fc->init_state & FC_STATE_I2C_INIT) {
-		i2c_del_adapter(&fc->fc_i2c_adap[2].i2c_adap);
-		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
deleted file mode 100644
index f06f3a9..0000000
--- a/drivers/media/dvb/b2c2/flexcop-misc.c
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * 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"
-
-void flexcop_determine_revision(struct flexcop_device *fc)
-{
-	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("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");
-	else
-		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[] = {
-	"Unknown chip",
-	"FlexCopII",
-	"FlexCopIIb",
-	"FlexCopIII",
-};
-
-static const char *flexcop_device_names[] = {
-	[FC_UNK]	= "Unknown device",
-	[FC_CABLE]	= "Cable2PC/CableStar 2 DVB-C",
-	[FC_AIR_DVBT]	= "Air2PC/AirStar 2 DVB-T",
-	[FC_AIR_ATSC1]	= "Air2PC/AirStar 2 ATSC 1st generation",
-	[FC_AIR_ATSC2]	= "Air2PC/AirStar 2 ATSC 2nd generation",
-	[FC_AIR_ATSC3]	= "Air2PC/AirStar 2 ATSC 3rd generation (HD5000)",
-	[FC_SKY_REV23]	= "Sky2PC/SkyStar 2 DVB-S rev 2.3 (old version)",
-	[FC_SKY_REV26]	= "Sky2PC/SkyStar 2 DVB-S rev 2.6",
-	[FC_SKY_REV27]	= "Sky2PC/SkyStar 2 DVB-S rev 2.7a/u",
-	[FC_SKY_REV28]	= "Sky2PC/SkyStar 2 DVB-S rev 2.8",
-};
-
-static const char *flexcop_bus_names[] = {
-	"USB",
-	"PCI",
-};
-
-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);
-}
-
-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);
-	}
-	deb_rdump("\n");
-}
-EXPORT_SYMBOL(flexcop_dump_reg);
diff --git a/drivers/media/dvb/b2c2/flexcop-pci.c b/drivers/media/dvb/b2c2/flexcop-pci.c
deleted file mode 100644
index 44f8fb5..0000000
--- a/drivers/media/dvb/b2c2/flexcop-pci.c
+++ /dev/null
@@ -1,450 +0,0 @@
-/*
- * 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"
-#include "flexcop-common.h"
-
-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");
-
-static int irq_chk_intv = 100;
-module_param(irq_chk_intv, int, 0644);
-MODULE_PARM_DESC(irq_chk_intv, "set the interval for IRQ streaming watchdog.");
-
-#ifdef CONFIG_DVB_B2C2_FLEXCOP_DEBUG
-#define dprintk(level,args...) \
-	do { if ((debug & level)) printk(args); } while (0)
-#define DEBSTATUS ""
-#else
-#define dprintk(level,args...)
-#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)
-
-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);
-
-#define DRIVER_VERSION "0.1"
-#define DRIVER_NAME "flexcop-pci"
-#define DRIVER_AUTHOR "Patrick Boettcher <patrick.boettcher@desy.de>"
-
-struct flexcop_pci {
-	struct pci_dev *pdev;
-
-#define FC_PCI_INIT     0x01
-#define FC_PCI_DMA_INIT 0x02
-	int init_state;
-
-	void __iomem *io_mem;
-	u32 irq;
-	/* 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 occurred */
-	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 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;
-	v.raw = readl(fc_pci->io_mem + r);
-
-	if (lastrreg != r || lastrval != v.raw) {
-		lastrreg = r; lastrval = 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)
-{
-	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);
-	}
-
-	writel(v.raw, fc_pci->io_mem + r);
-	return 0;
-}
-
-static void flexcop_pci_irq_check_work(struct work_struct *work)
-{
-	struct flexcop_pci *fc_pci =
-		container_of(work, struct flexcop_pci, irq_check_work.work);
-	struct flexcop_device *fc = fc_pci->fc_dev;
-
-	if (fc->feedcount) {
-
-		if (fc_pci->count == fc_pci->count_prev) {
-			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) {
-					flexcop_pid_feed_control(fc, feed, 0);
-				}
-
-				list_for_each_entry(feed, &fc->demux.feed_list,
-						list_head) {
-					flexcop_pid_feed_control(fc, feed, 1);
-				}
-				spin_unlock_irq(&fc->demux.lock);
-
-				fc_pci->stream_problem = 0;
-			}
-		} else {
-			fc_pci->stream_problem = 0;
-			fc_pci->count_prev = fc_pci->count;
-		}
-	}
-
-	schedule_delayed_work(&fc_pci->irq_check_work,
-			msecs_to_jiffies(irq_chk_intv < 100 ? 100 : irq_chk_intv));
-}
-
-/* When PID filtering is turned on, we use the timer IRQ, because small amounts
- * of data need to be passed to the user space instantly as well. When PID
- * filtering is turned off, we use the page-change-IRQ */
-static irqreturn_t flexcop_pci_isr(int irq, void *dev_id)
-{
-	struct flexcop_pci *fc_pci = dev_id;
-	struct flexcop_device *fc = fc_pci->fc_dev;
-	unsigned long flags;
-	flexcop_ibi_value v;
-	irqreturn_t ret = IRQ_HANDLED;
-
-	spin_lock_irqsave(&fc_pci->irq_lock, flags);
-	v = fc->read_ibi_reg(fc, irq_20c);
-
-	/* errors */
-	if (v.irq_20c.Data_receiver_error)
-		deb_chk("data receiver error\n");
-	if (v.irq_20c.Continuity_error_flag)
-		deb_chk("Contunuity error flag is set\n");
-	if (v.irq_20c.LLC_SNAP_FLAG_set)
-		deb_chk("LLC_SNAP_FLAG_set is set\n");
-	if (v.irq_20c.Transport_Error)
-		deb_chk("Transport error\n");
-
-	if ((fc_pci->count % 1000) == 0)
-		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);
-		else
-			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;
-		/* 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 ",
-				jiffies_to_usecs(jiffies - fc_pci->last_irq),
-				v.raw, (unsigned long long)cur_addr, cur_pos,
-				fc_pci->last_dma1_cur_pos);
-		fc_pci->last_irq = jiffies;
-
-		/* buffer end was reached, restarted from the beginning
-		 * 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);
-			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->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);
-			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);
-		}
-		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);
-		ret = IRQ_NONE;
-	}
-
-	spin_unlock_irqrestore(&fc_pci->irq_lock, flags);
-	return ret;
-}
-
-static int flexcop_pci_stream_control(struct flexcop_device *fc, int onoff)
-{
-	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);
-		deb_irq("DMA xfer enabled\n");
-
-		fc_pci->last_dma1_cur_pos = 0;
-		flexcop_dma_control_timer_irq(fc, FC_DMA_1, 1);
-		deb_irq("IRQ enabled\n");
-		fc_pci->count_prev = fc_pci->count;
-	} else {
-		flexcop_dma_control_timer_irq(fc, FC_DMA_1, 0);
-		deb_irq("IRQ disabled\n");
-
-		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;
-	ret = flexcop_dma_allocate(fc_pci->pdev, &fc_pci->dma[0],
-			FC_DEFAULT_DMA1_BUFSIZE);
-	if (ret != 0)
-		return ret;
-
-	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);
-	fc_pci->init_state |= FC_PCI_DMA_INIT;
-	return ret;
-}
-
-static void flexcop_pci_dma_exit(struct flexcop_pci *fc_pci)
-{
-	if (fc_pci->init_state & FC_PCI_DMA_INIT) {
-		flexcop_dma_free(&fc_pci->dma[0]);
-		flexcop_dma_free(&fc_pci->dma[1]);
-	}
-	fc_pci->init_state &= ~FC_PCI_DMA_INIT;
-}
-
-static int flexcop_pci_init(struct flexcop_pci *fc_pci)
-{
-	int ret;
-
-	info("card revision %x", fc_pci->pdev->revision);
-
-	if ((ret = pci_enable_device(fc_pci->pdev)) != 0)
-		return ret;
-	pci_set_master(fc_pci->pdev);
-
-	if ((ret = pci_request_regions(fc_pci->pdev, DRIVER_NAME)) != 0)
-		goto err_pci_disable_device;
-
-	fc_pci->io_mem = pci_iomap(fc_pci->pdev, 0, 0x800);
-
-	if (!fc_pci->io_mem) {
-		err("cannot map io memory\n");
-		ret = -EIO;
-		goto err_pci_release_regions;
-	}
-
-	pci_set_drvdata(fc_pci->pdev, fc_pci);
-	spin_lock_init(&fc_pci->irq_lock);
-	if ((ret = request_irq(fc_pci->pdev->irq, flexcop_pci_isr,
-					IRQF_SHARED, DRIVER_NAME, fc_pci)) != 0)
-		goto err_pci_iounmap;
-
-	fc_pci->init_state |= FC_PCI_INIT;
-	return ret;
-
-err_pci_iounmap:
-	pci_iounmap(fc_pci->pdev, fc_pci->io_mem);
-	pci_set_drvdata(fc_pci->pdev, NULL);
-err_pci_release_regions:
-	pci_release_regions(fc_pci->pdev);
-err_pci_disable_device:
-	pci_disable_device(fc_pci->pdev);
-	return ret;
-}
-
-static void flexcop_pci_exit(struct flexcop_pci *fc_pci)
-{
-	if (fc_pci->init_state & FC_PCI_INIT) {
-		free_irq(fc_pci->pdev->irq, fc_pci);
-		pci_iounmap(fc_pci->pdev, fc_pci->io_mem);
-		pci_set_drvdata(fc_pci->pdev, NULL);
-		pci_release_regions(fc_pci->pdev);
-		pci_disable_device(fc_pci->pdev);
-	}
-	fc_pci->init_state &= ~FC_PCI_INIT;
-}
-
-static int flexcop_pci_probe(struct pci_dev *pdev,
-		const struct pci_device_id *ent)
-{
-	struct flexcop_device *fc;
-	struct flexcop_pci *fc_pci;
-	int ret = -ENOMEM;
-
-	if ((fc = flexcop_device_kmalloc(sizeof(struct flexcop_pci))) == NULL) {
-		err("out of memory\n");
-		return -ENOMEM;
-	}
-
-	/* general flexcop init */
-	fc_pci = fc->bus_specific;
-	fc_pci->fc_dev = fc;
-
-	fc->read_ibi_reg = flexcop_pci_read_ibi_reg;
-	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)
-		info("will use the HW PID filter.");
-	else
-		info("will pass the complete TS to the demuxer.");
-
-	fc->pid_filtering = enable_pid_filtering;
-	fc->bus_type = FC_PCI;
-	fc->dev = &pdev->dev;
-	fc->owner = THIS_MODULE;
-
-	/* bus specific part */
-	fc_pci->pdev = pdev;
-	if ((ret = flexcop_pci_init(fc_pci)) != 0)
-		goto err_kfree;
-
-	/* init flexcop */
-	if ((ret = flexcop_device_initialize(fc)) != 0)
-		goto err_pci_exit;
-
-	/* 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));
-	return ret;
-
-err_fc_exit:
-	flexcop_device_exit(fc);
-err_pci_exit:
-	flexcop_pci_exit(fc_pci);
-err_kfree:
-	flexcop_device_kfree(fc);
-	return ret;
-}
-
-/* in theory every _exit function should be called exactly two times,
- * here and in the bail-out-part of the _init-function
- */
-static void flexcop_pci_remove(struct pci_dev *pdev)
-{
-	struct flexcop_pci *fc_pci = pci_get_drvdata(pdev);
-
-	if (irq_chk_intv > 0)
-		cancel_delayed_work(&fc_pci->irq_check_work);
-
-	flexcop_pci_dma_exit(fc_pci);
-	flexcop_device_exit(fc_pci->fc_dev);
-	flexcop_pci_exit(fc_pci);
-	flexcop_device_kfree(fc_pci->fc_dev);
-}
-
-static struct pci_device_id flexcop_pci_tbl[] = {
-	{ PCI_DEVICE(0x13d0, 0x2103) },
-	{ },
-};
-
-MODULE_DEVICE_TABLE(pci, flexcop_pci_tbl);
-
-static struct pci_driver flexcop_pci_driver = {
-	.name     = "b2c2_flexcop_pci",
-	.id_table = flexcop_pci_tbl,
-	.probe    = flexcop_pci_probe,
-	.remove   = flexcop_pci_remove,
-};
-
-static int __init flexcop_pci_module_init(void)
-{
-	return pci_register_driver(&flexcop_pci_driver);
-}
-
-static void __exit flexcop_pci_module_exit(void)
-{
-	pci_unregister_driver(&flexcop_pci_driver);
-}
-
-module_init(flexcop_pci_module_init);
-module_exit(flexcop_pci_module_exit);
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_NAME);
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/b2c2/flexcop-reg.h b/drivers/media/dvb/b2c2/flexcop-reg.h
deleted file mode 100644
index dc4528d..0000000
--- a/drivers/media/dvb/b2c2/flexcop-reg.h
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * 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
- */
-#ifndef __FLEXCOP_REG_H__
-#define __FLEXCOP_REG_H__
-
-typedef enum {
-	FLEXCOP_UNK = 0,
-	FLEXCOP_II,
-	FLEXCOP_IIB,
-	FLEXCOP_III,
-} flexcop_revision_t;
-
-typedef enum {
-	FC_UNK = 0,
-	FC_CABLE,
-	FC_AIR_DVBT,
-	FC_AIR_ATSC1,
-	FC_AIR_ATSC2,
-	FC_AIR_ATSC3,
-	FC_SKY_REV23,
-	FC_SKY_REV26,
-	FC_SKY_REV27,
-	FC_SKY_REV28,
-} flexcop_device_type_t;
-
-typedef enum {
-	FC_USB = 0,
-	FC_PCI,
-} flexcop_bus_t;
-
-/* FlexCop IBI Registers */
-#if defined(__LITTLE_ENDIAN)
-#include "flexcop_ibi_value_le.h"
-#else
-#if defined(__BIG_ENDIAN)
-#include "flexcop_ibi_value_be.h"
-#else
-#error no endian defined
-#endif
-#endif
-
-#define fc_data_Tag_ID_DVB  0x3e
-#define fc_data_Tag_ID_ATSC 0x3f
-#define fc_data_Tag_ID_IDSB 0x8b
-
-#define fc_key_code_default 0x1
-#define fc_key_code_even    0x2
-#define fc_key_code_odd     0x3
-
-extern flexcop_ibi_value ibi_zero;
-
-typedef enum {
-	FC_I2C_PORT_DEMOD  = 1,
-	FC_I2C_PORT_EEPROM = 2,
-	FC_I2C_PORT_TUNER  = 3,
-} flexcop_i2c_port_t;
-
-typedef enum {
-	FC_WRITE = 0,
-	FC_READ  = 1,
-} flexcop_access_op_t;
-
-typedef enum {
-	FC_SRAM_DEST_NET   = 1,
-	FC_SRAM_DEST_CAI   = 2,
-	FC_SRAM_DEST_CAO   = 4,
-	FC_SRAM_DEST_MEDIA = 8
-} flexcop_sram_dest_t;
-
-typedef enum {
-	FC_SRAM_DEST_TARGET_WAN_USB = 0,
-	FC_SRAM_DEST_TARGET_DMA1    = 1,
-	FC_SRAM_DEST_TARGET_DMA2    = 2,
-	FC_SRAM_DEST_TARGET_FC3_CA  = 3
-} flexcop_sram_dest_target_t;
-
-typedef enum {
-	FC_SRAM_2_32KB  = 0, /*  64KB */
-	FC_SRAM_1_32KB  = 1, /*  32KB - default fow FCII */
-	FC_SRAM_1_128KB = 2, /* 128KB */
-	FC_SRAM_1_48KB  = 3, /*  48KB - default for FCIII */
-} flexcop_sram_type_t;
-
-typedef enum {
-	FC_WAN_SPEED_4MBITS  = 0,
-	FC_WAN_SPEED_8MBITS  = 1,
-	FC_WAN_SPEED_12MBITS = 2,
-	FC_WAN_SPEED_16MBITS = 3,
-} flexcop_wan_speed_t;
-
-typedef enum {
-	FC_DMA_1 = 1,
-	FC_DMA_2 = 2,
-} flexcop_dma_index_t;
-
-typedef enum {
-	FC_DMA_SUBADDR_0 = 1,
-	FC_DMA_SUBADDR_1 = 2,
-} flexcop_dma_addr_index_t;
-
-/* names of the particular registers */
-typedef enum {
-	dma1_000            = 0x000,
-	dma1_004            = 0x004,
-	dma1_008            = 0x008,
-	dma1_00c            = 0x00c,
-	dma2_010            = 0x010,
-	dma2_014            = 0x014,
-	dma2_018            = 0x018,
-	dma2_01c            = 0x01c,
-
-	tw_sm_c_100         = 0x100,
-	tw_sm_c_104         = 0x104,
-	tw_sm_c_108         = 0x108,
-	tw_sm_c_10c         = 0x10c,
-	tw_sm_c_110         = 0x110,
-
-	lnb_switch_freq_200 = 0x200,
-	misc_204            = 0x204,
-	ctrl_208            = 0x208,
-	irq_20c             = 0x20c,
-	sw_reset_210        = 0x210,
-	misc_214            = 0x214,
-	mbox_v8_to_host_218 = 0x218,
-	mbox_host_to_v8_21c = 0x21c,
-
-	pid_filter_300      = 0x300,
-	pid_filter_304      = 0x304,
-	pid_filter_308      = 0x308,
-	pid_filter_30c      = 0x30c,
-	index_reg_310       = 0x310,
-	pid_n_reg_314       = 0x314,
-	mac_low_reg_318     = 0x318,
-	mac_high_reg_31c    = 0x31c,
-
-	data_tag_400        = 0x400,
-	card_id_408         = 0x408,
-	card_id_40c         = 0x40c,
-	mac_address_418     = 0x418,
-	mac_address_41c     = 0x41c,
-
-	ci_600              = 0x600,
-	pi_604              = 0x604,
-	pi_608              = 0x608,
-	dvb_reg_60c         = 0x60c,
-
-	sram_ctrl_reg_700   = 0x700,
-	net_buf_reg_704     = 0x704,
-	cai_buf_reg_708     = 0x708,
-	cao_buf_reg_70c     = 0x70c,
-	media_buf_reg_710   = 0x710,
-	sram_dest_reg_714   = 0x714,
-	net_buf_reg_718     = 0x718,
-	wan_ctrl_reg_71c    = 0x71c,
-} flexcop_ibi_register;
-
-#define flexcop_set_ibi_value(reg,attr,val) { \
-	flexcop_ibi_value v = fc->read_ibi_reg(fc,reg); \
-	v.reg.attr = val; \
-	fc->write_ibi_reg(fc,reg,v); \
-}
-
-#endif
diff --git a/drivers/media/dvb/b2c2/flexcop-sram.c b/drivers/media/dvb/b2c2/flexcop-sram.c
deleted file mode 100644
index f2199e4..0000000
--- a/drivers/media/dvb/b2c2/flexcop-sram.c
+++ /dev/null
@@ -1,363 +0,0 @@
-/*
- * 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)
-{
-	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;
-	}
-	return 0;
-}
-
-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);
-
-	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);
-
-	if (dest & FC_SRAM_DEST_NET)
-		v.sram_dest_reg_714.NET_Dest = target;
-	if (dest & FC_SRAM_DEST_CAI)
-		v.sram_dest_reg_714.CAI_Dest = target;
-	if (dest & FC_SRAM_DEST_CAO)
-		v.sram_dest_reg_714.CAO_Dest = target;
-	if (dest & FC_SRAM_DEST_MEDIA)
-		v.sram_dest_reg_714.MEDIA_Dest = target;
-
-	fc->write_ibi_reg(fc,sram_dest_reg_714,v);
-	udelay(1000); /* TODO delay really necessary */
-
-	return 0;
-}
-EXPORT_SYMBOL(flexcop_sram_set_dest);
-
-void flexcop_wan_set_speed(struct flexcop_device *fc, flexcop_wan_speed_t s)
-{
-	flexcop_set_ibi_value(wan_ctrl_reg_71c,wan_speed_sig,s);
-}
-EXPORT_SYMBOL(flexcop_wan_set_speed);
-
-void flexcop_sram_ctrl(struct flexcop_device *fc, int usb_wan, int sramdma, int maximumfill)
-{
-	flexcop_ibi_value v = fc->read_ibi_reg(fc,sram_dest_reg_714);
-	v.sram_dest_reg_714.ctrl_usb_wan = usb_wan;
-	v.sram_dest_reg_714.ctrl_sramdma = sramdma;
-	v.sram_dest_reg_714.ctrl_maximumfill = maximumfill;
-	fc->write_ibi_reg(fc,sram_dest_reg_714,v);
-}
-EXPORT_SYMBOL(flexcop_sram_ctrl);
-
-#if 0
-static void flexcop_sram_write(struct adapter *adapter, u32 bank, u32 addr, u8 *buf, u32 len)
-{
-	int i, retries;
-	u32 command;
-
-	for (i = 0; i < len; i++) {
-		command = bank | addr | 0x04000000 | (*buf << 0x10);
-
-		retries = 2;
-
-		while (((read_reg_dw(adapter, 0x700) & 0x80000000) != 0) && (retries > 0)) {
-			mdelay(1);
-			retries--;
-		};
-
-		if (retries == 0)
-			printk("%s: SRAM timeout\n", __func__);
-
-		write_reg_dw(adapter, 0x700, command);
-
-		buf++;
-		addr++;
-	}
-}
-
-static void flex_sram_read(struct adapter *adapter, u32 bank, u32 addr, u8 *buf, u32 len)
-{
-	int i, retries;
-	u32 command, value;
-
-	for (i = 0; i < len; i++) {
-		command = bank | addr | 0x04008000;
-
-		retries = 10000;
-
-		while (((read_reg_dw(adapter, 0x700) & 0x80000000) != 0) && (retries > 0)) {
-			mdelay(1);
-			retries--;
-		};
-
-		if (retries == 0)
-			printk("%s: SRAM timeout\n", __func__);
-
-		write_reg_dw(adapter, 0x700, command);
-
-		retries = 10000;
-
-		while (((read_reg_dw(adapter, 0x700) & 0x80000000) != 0) && (retries > 0)) {
-			mdelay(1);
-			retries--;
-		};
-
-		if (retries == 0)
-			printk("%s: SRAM timeout\n", __func__);
-
-		value = read_reg_dw(adapter, 0x700) >> 0x10;
-
-		*buf = (value & 0xff);
-
-		addr++;
-		buf++;
-	}
-}
-
-static void sram_write_chunk(struct adapter *adapter, u32 addr, u8 *buf, u16 len)
-{
-	u32 bank;
-
-	bank = 0;
-
-	if (adapter->dw_sram_type == 0x20000) {
-		bank = (addr & 0x18000) << 0x0d;
-	}
-
-	if (adapter->dw_sram_type == 0x00000) {
-		if ((addr >> 0x0f) == 0)
-			bank = 0x20000000;
-		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) {
-		bank = (addr & 0x18000) << 0x0d;
-	}
-
-	if (adapter->dw_sram_type == 0x00000) {
-		if ((addr >> 0x0f) == 0)
-			bank = 0x20000000;
-		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 */
-		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;
-	}
-}
-
-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 */
-		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;
-	}
-}
-
-static void sram_set_size(struct adapter *adapter, u32 mask)
-{
-	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);
-	}
-}
-
-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);
-	sram_init(adapter);
-
-	tmp2 = 0xa5;
-	tmp1 = 0x4f;
-
-	sram_write(adapter, addr, &tmp2, 1);
-	sram_write(adapter, addr + 4, &tmp1, 1);
-
-	tmp2 = 0;
-	mdelay(20);
-
-	sram_read(adapter, addr, &tmp2, 1);
-	sram_read(adapter, addr, &tmp2, 1);
-
-	dprintk("%s: wrote 0xa5, read 0x%2x\n", __func__, tmp2);
-
-	if (tmp2 != 0xa5)
-		return 0;
-
-	tmp2 = 0x5a;
-	tmp1 = 0xf4;
-
-	sram_write(adapter, addr, &tmp2, 1);
-	sram_write(adapter, addr + 4, &tmp1, 1);
-
-	tmp2 = 0;
-	mdelay(20);
-
-	sram_read(adapter, addr, &tmp2, 1);
-	sram_read(adapter, addr, &tmp2, 1);
-
-	dprintk("%s: wrote 0x5a, read 0x%2x\n", __func__, tmp2);
-
-	if (tmp2 != 0x5a)
-		return 0;
-	return 1;
-}
-
-static u32 sram_length(struct adapter *adapter)
-{
-	if (adapter->dw_sram_type == 0x10000)
-		return 32768; /* 32K */
-	if (adapter->dw_sram_type == 0x00000)
-		return 65536; /* 64K */
-	if (adapter->dw_sram_type == 0x20000)
-		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.
-
-   FlexCop works only with one bank at a time. The bank is selected
-   by bits 28-29 of the 0x700 register.
-
-   bank 0 covers addresses 0x00000-0x07fff
-   bank 1 covers addresses 0x08000-0x0ffff
-   bank 2 covers addresses 0x10000-0x17fff
-   bank 3 covers addresses 0x18000-0x1ffff */
-
-static int flexcop_sram_detect(struct flexcop_device *fc)
-{
-	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 ???
-	tmp3--;
-	if (tmp3 != 0) {
-		sram_set_size(adapter, 0x10000);
-		sram_init(adapter);
-		write_reg_dw(adapter, 0x208, tmp);
-		dprintk("%s: sram size = 32K\n", __func__);
-		return 32;
-	}
-
-	if (sram_test_location(adapter, 0x20000, 0x18000) != 0) {
-		sram_set_size(adapter, 0x20000);
-		sram_init(adapter);
-		write_reg_dw(adapter, 0x208, tmp);
-		dprintk("%s: sram size = 128K\n", __func__);
-		return 128;
-	}
-
-	if (sram_test_location(adapter, 0x00000, 0x10000) != 0) {
-		sram_set_size(adapter, 0x00000);
-		sram_init(adapter);
-		write_reg_dw(adapter, 0x208, tmp);
-		dprintk("%s: sram size = 64K\n", __func__);
-		return 64;
-	}
-
-	if (sram_test_location(adapter, 0x10000, 0x00000) != 0) {
-		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;
-}
-
-static void sll_detect_sram_size(struct adapter *adapter)
-{
-	sram_detect_for_flex2(adapter);
-}
-
-#endif
diff --git a/drivers/media/dvb/b2c2/flexcop-usb.c b/drivers/media/dvb/b2c2/flexcop-usb.c
deleted file mode 100644
index 26c666d..0000000
--- a/drivers/media/dvb/b2c2/flexcop-usb.c
+++ /dev/null
@@ -1,590 +0,0 @@
-/*
- * 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"
-
-/* Version information */
-#define DRIVER_VERSION "0.1"
-#define DRIVER_NAME "Technisat/B2C2 FlexCop II/IIb/III Digital TV USB Driver"
-#define DRIVER_AUTHOR "Patrick Boettcher <patrick.boettcher@desy.de>"
-
-/* 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 {\
-	int i; \
-	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 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);
-#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)
-
-/* 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 (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))
-
-/*
- * DKT 020228
- * - forget about this VENDOR_BUFFER_SIZE, read and write register
- *   deal with DWORD or 4 bytes, that should be should from now on
- * - from now on, we don't support anything older than firm 1.00
- *   I eliminated the write register as a 2 trip of writing hi word and lo word
- *   and force this to write only 4 bytes at a time.
- *   NOTE: this should work with all the firmware from 1.00 and newer
- */
-static int flexcop_usb_readwrite_dw(struct flexcop_device *fc, u16 wRegOffsPCI, u32 *val, u8 read)
-{
-	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);
-
-	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 */
-			wAddress,
-			0,
-			val,
-			sizeof(u32),
-			B2C2_WAIT_FOR_OPERATION_RDW * HZ);
-
-	if (len != sizeof(u32)) {
-		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 request_type = USB_TYPE_VENDOR;
-	u16 wIndex;
-	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;
-		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;
-		pipe = B2C2_USB_CTRL_PIPE_OUT;
-		break;
-	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);
-		return -EINVAL;
-	}
-	deb_v8("v8mem: %02x %02x %04x %04x, len: %d\n", request_type, req,
-			wAddress, wIndex, buflen);
-
-	len = usb_control_msg(fc_usb->udev, pipe,
-			req,
-			request_type,
-			wAddress,
-			wIndex,
-			pbBuffer,
-			buflen,
-			nWaitTime * HZ);
-
-	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)))
-
-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;
-		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));
-
-		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;
-	}
-	return 0;
-}
-
-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);
-}
-
-#if 0
-static int flexcop_usb_utility_req(struct flexcop_usb *fc_usb, int set,
-		flexcop_usb_utility_function_t func, u8 extra, u16 wIndex,
-		u16 buflen, u8 *pvBuffer)
-{
-	u16 wValue;
-	u8 request_type = (set ? USB_DIR_OUT : USB_DIR_IN) | USB_TYPE_VENDOR;
-	int nWaitTime = 2,
-	    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,
-			B2C2_USB_UTILITY,
-			request_type,
-			wValue,
-			wIndex,
-			pvBuffer,
-			buflen,
-			nWaitTime * HZ);
-	return len == buflen ? 0 : -EIO;
-}
-#endif
-
-/* usb i2c stuff */
-static int flexcop_usb_i2c_req(struct flexcop_i2c_adapter *i2c,
-		flexcop_usb_request_t req, flexcop_usb_i2c_function_t func,
-		u8 chipaddr, u8 addr, u8 *buf, u8 buflen)
-{
-	struct flexcop_usb *fc_usb = i2c->fc->bus_specific;
-	u16 wValue, wIndex;
-	int nWaitTime,pipe,len;
-	u8 request_type = USB_TYPE_VENDOR;
-
-	switch (func) {
-	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;
-		request_type |= USB_DIR_OUT;
-		break;
-	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;
-	}
-	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);
-
-	len = usb_control_msg(fc_usb->udev,pipe,
-			req,
-			request_type,
-			wValue,
-			wIndex,
-			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)
-{
-	flexcop_ibi_value val;
-	val.raw = 0;
-	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)
-{
-	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)
-{
-	if (op == FC_READ)
-		return flexcop_usb_i2c_req(i2c, B2C2_USB_I2C_REQUEST,
-				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);
-}
-
-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);
-
-	if (fc_usb->tmp_buffer_length > 0) {
-		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;
-	} else {
-		b=buffer;
-		l=buffer_length;
-	}
-
-	while (l >= 190) {
-		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;
-				break;
-			default:
-				deb_ts("wrong packet type\n");
-				l = 0;
-				break;
-			}
-		} else {
-			deb_ts("wrong header\n");
-			l = 0;
-		}
-	}
-
-	if (l>0)
-		memcpy(fc_usb->tmp_buffer, b, l);
-	fc_usb->tmp_buffer_length = l;
-}
-
-static void flexcop_usb_urb_complete(struct urb *urb)
-{
-	struct flexcop_usb *fc_usb = urb->context;
-	int i;
-
-	if (urb->actual_length > 0)
-		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);
-		} 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);
-
-				flexcop_usb_process_frame(fc_usb,
-					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);
-}
-
-static int flexcop_usb_stream_control(struct flexcop_device *fc, int onoff)
-{
-	/* submit/kill iso packets */
-	return 0;
-}
-
-static void flexcop_usb_transfer_exit(struct flexcop_usb *fc_usb)
-{
-	int i;
-	for (i = 0; i < B2C2_USB_NUM_ISO_URB; i++)
-		if (fc_usb->iso_urb[i] != NULL) {
-			deb_ts("unlinking/killing urb no. %d\n",i);
-			usb_kill_urb(fc_usb->iso_urb[i]);
-			usb_free_urb(fc_usb->iso_urb[i]);
-		}
-
-	if (fc_usb->iso_buffer != NULL)
-		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;
-	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);
-
-	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++) {
-		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);
-
-		urb->dev = fc_usb->udev;
-		urb->context = fc_usb;
-		urb->complete = flexcop_usb_urb_complete;
-		urb->pipe = B2C2_USB_DATA_PIPE;
-		urb->transfer_flags = URB_ISO_ASAP;
-		urb->interval = 1;
-		urb->number_of_packets = B2C2_USB_FRAMES_PER_ISO;
-		urb->transfer_buffer_length = frame_size * B2C2_USB_FRAMES_PER_ISO;
-		urb->transfer_buffer = fc_usb->iso_buffer + buffer_offset;
-
-		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);
-			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);
-			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);
-	return 0;
-
-urb_error:
-	flexcop_usb_transfer_exit(fc_usb);
-	return ret;
-}
-
-static int flexcop_usb_init(struct flexcop_usb *fc_usb)
-{
-	/* 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 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;
-}
-
-static void flexcop_usb_exit(struct flexcop_usb *fc_usb)
-{
-	usb_set_intfdata(fc_usb->uintf, NULL);
-}
-
-static int flexcop_usb_probe(struct usb_interface *intf,
-		const struct usb_device_id *id)
-{
-	struct usb_device *udev = interface_to_usbdev(intf);
-	struct flexcop_usb *fc_usb = NULL;
-	struct flexcop_device *fc = NULL;
-	int ret;
-
-	if ((fc = flexcop_device_kmalloc(sizeof(struct flexcop_usb))) == NULL) {
-		err("out of memory\n");
-		return -ENOMEM;
-	}
-
-	/* general flexcop init */
-	fc_usb = fc->bus_specific;
-	fc_usb->fc_dev = fc;
-
-	fc->read_ibi_reg  = flexcop_usb_read_ibi_reg;
-	fc->write_ibi_reg = flexcop_usb_write_ibi_reg;
-	fc->i2c_request = flexcop_usb_i2c_request;
-	fc->get_mac_addr = flexcop_usb_get_mac_addr;
-
-	fc->stream_control = flexcop_usb_stream_control;
-
-	fc->pid_filtering = 1;
-	fc->bus_type = FC_USB;
-
-	fc->dev = &udev->dev;
-	fc->owner = THIS_MODULE;
-
-	/* bus specific part */
-	fc_usb->udev = udev;
-	fc_usb->uintf = intf;
-	if ((ret = flexcop_usb_init(fc_usb)) != 0)
-		goto err_kfree;
-
-	/* init flexcop */
-	if ((ret = flexcop_device_initialize(fc)) != 0)
-		goto err_usb_exit;
-
-	/* xfer init */
-	if ((ret = flexcop_usb_transfer_init(fc_usb)) != 0)
-		goto err_fc_exit;
-
-	info("%s successfully initialized and connected.", DRIVER_NAME);
-	return 0;
-
-err_fc_exit:
-	flexcop_device_exit(fc);
-err_usb_exit:
-	flexcop_usb_exit(fc_usb);
-err_kfree:
-	flexcop_device_kfree(fc);
-	return ret;
-}
-
-static void flexcop_usb_disconnect(struct usb_interface *intf)
-{
-	struct flexcop_usb *fc_usb = usb_get_intfdata(intf);
-	flexcop_usb_transfer_exit(fc_usb);
-	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);
-}
-
-static struct usb_device_id flexcop_usb_table [] = {
-	{ USB_DEVICE(0x0af7, 0x0101) },
-	{ }
-};
-MODULE_DEVICE_TABLE (usb, flexcop_usb_table);
-
-/* usb specific object needed to register this driver with the usb subsystem */
-static struct usb_driver flexcop_usb_driver = {
-	.name		= "b2c2_flexcop_usb",
-	.probe		= flexcop_usb_probe,
-	.disconnect = flexcop_usb_disconnect,
-	.id_table	= flexcop_usb_table,
-};
-
-module_usb_driver(flexcop_usb_driver);
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_NAME);
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/b2c2/flexcop-usb.h b/drivers/media/dvb/b2c2/flexcop-usb.h
deleted file mode 100644
index 92529a9..0000000
--- a/drivers/media/dvb/b2c2/flexcop-usb.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * 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_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;
-	struct usb_interface *uintf;
-
-	u8 *iso_buffer;
-	int buffer_size;
-	dma_addr_t dma_addr;
-
-	struct urb *iso_urb[B2C2_USB_NUM_ISO_URB];
-	struct flexcop_device *fc_dev;
-
-	u8 tmp_buffer[1023+190];
-	int tmp_buffer_length;
-};
-
-#if 0
-/* request types TODO What is its use?*/
-typedef enum {
-
-} flexcop_usb_request_type_t;
-#endif
-
-/* request */
-typedef enum {
-	B2C2_USB_WRITE_V8_MEM = 0x04,
-	B2C2_USB_READ_V8_MEM  = 0x05,
-	B2C2_USB_READ_REG     = 0x08,
-	B2C2_USB_WRITE_REG    = 0x0A,
-	B2C2_USB_WRITEREGHI   = 0x0B,
-	B2C2_USB_FLASH_BLOCK  = 0x10,
-	B2C2_USB_I2C_REQUEST  = 0x11,
-	B2C2_USB_UTILITY      = 0x12,
-} flexcop_usb_request_t;
-
-/* function definition for I2C_REQUEST */
-typedef enum {
-	USB_FUNC_I2C_WRITE       = 0x01,
-	USB_FUNC_I2C_MULTIWRITE  = 0x02,
-	USB_FUNC_I2C_READ        = 0x03,
-	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 */
-	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 */
-typedef enum {
-	UTILITY_SET_FILTER          = 0x01,
-	UTILITY_DATA_ENABLE         = 0x02,
-	UTILITY_FLEX_MULTIWRITE     = 0x03,
-	UTILITY_SET_BUFFER_SIZE     = 0x04,
-	UTILITY_FLEX_OPERATOR       = 0x05,
-	UTILITY_FLEX_RESET300_START = 0x06,
-	UTILITY_FLEX_RESET300_STOP  = 0x07,
-	UTILITY_FLEX_RESET300       = 0x08,
-	UTILITY_SET_ISO_SIZE        = 0x09,
-	UTILITY_DATA_RESET          = 0x0A,
-	UTILITY_GET_DATA_STATUS     = 0x10,
-	UTILITY_GET_V8_REG          = 0x11,
-	/* DKT 020326 - add function for v1.14 */
-	UTILITY_SRAM_WRITE          = 0x12,
-	UTILITY_SRAM_READ           = 0x13,
-	UTILITY_SRAM_TESTFILL       = 0x14,
-	UTILITY_SRAM_TESTSET        = 0x15,
-	UTILITY_SRAM_TESTVERIFY     = 0x16,
-} flexcop_usb_utility_function_t;
-
-#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)
-#define B2C2_WAIT_FOR_OPERATION_V8WRITE (3*HZ)
-#define B2C2_WAIT_FOR_OPERATION_V8FLASH (3*HZ)
-
-typedef enum {
-	V8_MEMORY_PAGE_DVB_CI = 0x20,
-	V8_MEMORY_PAGE_DVB_DS = 0x40,
-	V8_MEMORY_PAGE_MULTI2 = 0x60,
-	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
-
-#endif
diff --git a/drivers/media/dvb/b2c2/flexcop.c b/drivers/media/dvb/b2c2/flexcop.c
deleted file mode 100644
index b1e8c99..0000000
--- a/drivers/media/dvb/b2c2/flexcop.c
+++ /dev/null
@@ -1,324 +0,0 @@
-/*
- * 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)
- *
- * 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)
- *   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
- * as published by the Free Software Foundation; either version 2.1
- * 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 Lesser General Public 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 "flexcop.h"
-
-#define DRIVER_NAME "B2C2 FlexcopII/II(b)/III digital TV receiver chip"
-#define DRIVER_AUTHOR "Patrick Boettcher <patrick.boettcher@desy.de"
-
-#ifdef CONFIG_DVB_B2C2_FLEXCOP_DEBUG
-#define DEBSTATUS ""
-#else
-#define DEBSTATUS " (debugging is not enabled)"
-#endif
-
-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);
-#undef DEBSTATUS
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-/* global zero for ibi values */
-flexcop_ibi_value ibi_zero;
-
-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);
-}
-
-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);
-}
-
-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);
-	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.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;
-
-	ret = dvb_dmx_init(&fc->demux);
-	if (ret < 0) {
-		err("dvb_dmx failed: error %d", ret);
-		goto err_dmx;
-	}
-
-	fc->hw_frontend.source = DMX_FRONTEND_0;
-
-	fc->dmxdev.filternum = fc->demux.feednum;
-	fc->dmxdev.demux = &fc->demux.dmx;
-	fc->dmxdev.capabilities = 0;
-	ret = dvb_dmxdev_init(&fc->dmxdev, &fc->dvb_adapter);
-	if (ret < 0) {
-		err("dvb_dmxdev_init failed: error %d", ret);
-		goto err_dmx_dev;
-	}
-
-	ret = fc->demux.dmx.add_frontend(&fc->demux.dmx, &fc->hw_frontend);
-	if (ret < 0) {
-		err("adding hw_frontend to dmx failed: error %d", ret);
-		goto err_dmx_add_hw_frontend;
-	}
-
-	fc->mem_frontend.source = DMX_MEMORY_FE;
-	ret = fc->demux.dmx.add_frontend(&fc->demux.dmx, &fc->mem_frontend);
-	if (ret < 0) {
-		err("adding mem_frontend to dmx failed: error %d", ret);
-		goto err_dmx_add_mem_frontend;
-	}
-
-	ret = fc->demux.dmx.connect_frontend(&fc->demux.dmx, &fc->hw_frontend);
-	if (ret < 0) {
-		err("connect frontend failed: error %d", ret);
-		goto err_connect_frontend;
-	}
-
-	ret = dvb_net_init(&fc->dvb_adapter, &fc->dvbnet, &fc->demux.dmx);
-	if (ret < 0) {
-		err("dvb_net_init failed: error %d", ret);
-		goto err_net;
-	}
-
-	fc->init_state |= FC_STATE_DVB_INIT;
-	return 0;
-
-err_net:
-	fc->demux.dmx.disconnect_frontend(&fc->demux.dmx);
-err_connect_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);
-err_dmx_add_hw_frontend:
-	dvb_dmxdev_release(&fc->dmxdev);
-err_dmx_dev:
-	dvb_dmx_release(&fc->demux);
-err_dmx:
-	dvb_unregister_adapter(&fc->dvb_adapter);
-	return ret;
-}
-
-static void flexcop_dvb_exit(struct flexcop_device *fc)
-{
-	if (fc->init_state & FC_STATE_DVB_INIT) {
-		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);
-		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;
-}
-
-/* these methods are necessary to achieve the long-term-goal of hiding the
- * struct flexcop_device from the bus-parts */
-void flexcop_pass_dmx_data(struct flexcop_device *fc, u8 *buf, u32 len)
-{
-	dvb_dmx_swfilter(&fc->demux, buf, len);
-}
-EXPORT_SYMBOL(flexcop_pass_dmx_data);
-
-void flexcop_pass_dmx_packets(struct flexcop_device *fc, u8 *buf, u32 no)
-{
-	dvb_dmx_swfilter_packets(&fc->demux, buf, no);
-}
-EXPORT_SYMBOL(flexcop_pass_dmx_packets);
-
-static void flexcop_reset(struct flexcop_device *fc)
-{
-	flexcop_ibi_value v210, v204;
-
-	/* reset the flexcop itself */
-	fc->write_ibi_reg(fc,ctrl_208,ibi_zero);
-
-	v210.raw = 0;
-	v210.sw_reset_210.reset_block_000 = 1;
-	v210.sw_reset_210.reset_block_100 = 1;
-	v210.sw_reset_210.reset_block_200 = 1;
-	v210.sw_reset_210.reset_block_300 = 1;
-	v210.sw_reset_210.reset_block_400 = 1;
-	v210.sw_reset_210.reset_block_500 = 1;
-	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 */
-
-	v204 = fc->read_ibi_reg(fc,misc_204);
-	v204.misc_204.Per_reset_sig = 0;
-	fc->write_ibi_reg(fc,misc_204,v204);
-	msleep(1);
-	v204.misc_204.Per_reset_sig = 1;
-	fc->write_ibi_reg(fc,misc_204,v204);
-}
-
-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);
-
-	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);
-	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);
-	if (!fc) {
-		err("no memory");
-		return NULL;
-	}
-
-	bus = kzalloc(bus_specific_len, GFP_KERNEL);
-	if (!bus) {
-		err("no memory");
-		kfree(fc);
-		return NULL;
-	}
-
-	fc->bus_specific = bus;
-
-	return fc;
-}
-EXPORT_SYMBOL(flexcop_device_kmalloc);
-
-void flexcop_device_kfree(struct flexcop_device *fc)
-{
-	kfree(fc->bus_specific);
-	kfree(fc);
-}
-EXPORT_SYMBOL(flexcop_device_kfree);
-
-int flexcop_device_initialize(struct flexcop_device *fc)
-{
-	int ret;
-	ibi_zero.raw = 0;
-
-	flexcop_reset(fc);
-	flexcop_determine_revision(fc);
-	flexcop_sram_init(fc);
-	flexcop_hw_filter_init(fc);
-	flexcop_smc_ctrl(fc, 0);
-
-	ret = flexcop_dvb_init(fc);
-	if (ret)
-		goto error;
-
-	/* i2c has to be done before doing EEProm stuff -
-	 * because the EEProm is accessed via i2c */
-	ret = flexcop_i2c_init(fc);
-	if (ret)
-		goto error;
-
-	/* do the MAC address reading after initializing the dvb_adapter */
-	if (fc->get_mac_addr(fc, 0) == 0) {
-		u8 *b = fc->dvb_adapter.proposed_mac;
-		info("MAC address = %pM", b);
-		flexcop_set_mac_filter(fc,b);
-		flexcop_mac_filter_ctrl(fc,1);
-	} else
-		warn("reading of MAC address failed.\n");
-
-	ret = flexcop_frontend_init(fc);
-	if (ret)
-		goto error;
-
-	flexcop_device_name(fc,"initialization of","complete");
-	return 0;
-
-error:
-	flexcop_device_exit(fc);
-	return ret;
-}
-EXPORT_SYMBOL(flexcop_device_initialize);
-
-void flexcop_device_exit(struct flexcop_device *fc)
-{
-	flexcop_frontend_exit(fc);
-	flexcop_i2c_exit(fc);
-	flexcop_dvb_exit(fc);
-}
-EXPORT_SYMBOL(flexcop_device_exit);
-
-static int flexcop_module_init(void)
-{
-	info(DRIVER_NAME " loaded successfully");
-	return 0;
-}
-
-static void flexcop_module_cleanup(void)
-{
-	info(DRIVER_NAME " unloaded successfully");
-}
-
-module_init(flexcop_module_init);
-module_exit(flexcop_module_cleanup);
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_NAME);
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/b2c2/flexcop.h b/drivers/media/dvb/b2c2/flexcop.h
deleted file mode 100644
index 897b10c..0000000
--- a/drivers/media/dvb/b2c2/flexcop.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * 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___
-
-#define FC_LOG_PREFIX "b2c2-flexcop"
-#include "flexcop-common.h"
-
-extern int b2c2_flexcop_debug;
-
-/* debug */
-#ifdef CONFIG_DVB_B2C2_FLEXCOP_DEBUG
-#define dprintk(level,args...) \
-	do { if ((b2c2_flexcop_debug & level)) printk(args); } while (0)
-#else
-#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)
-
-#endif
diff --git a/drivers/media/dvb/b2c2/flexcop_ibi_value_be.h b/drivers/media/dvb/b2c2/flexcop_ibi_value_be.h
deleted file mode 100644
index 8f64bdb..0000000
--- a/drivers/media/dvb/b2c2/flexcop_ibi_value_be.h
+++ /dev/null
@@ -1,455 +0,0 @@
-/* Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
- * register descriptions
- * 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__
-
-typedef union {
-	u32 raw;
-
-	struct {
-		u32 dma_address0                   :30;
-		u32 dma_0No_update                 : 1;
-		u32 dma_0start                     : 1;
-	} dma_0x0;
-
-	struct {
-		u32 dma_addr_size                  :24;
-		u32 DMA_maxpackets                 : 8;
-	} dma_0x4_remap;
-
-	struct {
-		u32 dma_addr_size                  :24;
-		u32 unused                         : 1;
-		u32 dma1timer                      : 7;
-	} dma_0x4_read;
-
-	struct {
-		u32 dma_addr_size                  :24;
-		u32 dmatimer                       : 7;
-		u32 unused                         : 1;
-	} dma_0x4_write;
-
-	struct {
-		u32 dma_cur_addr                   :30;
-		u32 unused                         : 2;
-	} dma_0x8;
-
-	struct {
-		u32 dma_address1                   :30;
-		u32 remap_enable                   : 1;
-		u32 dma_1start                     : 1;
-	} dma_0xc;
-
-	struct {
-		u32 st_done                        : 1;
-		u32 no_base_addr_ack_error         : 1;
-		u32 twoWS_port_reg                 : 2;
-		u32 total_bytes                    : 2;
-		u32 twoWS_rw                       : 1;
-		u32 working_start                  : 1;
-		u32 data1_reg                      : 8;
-		u32 baseaddr                       : 8;
-		u32 reserved1                      : 1;
-		u32 chipaddr                       : 7;
-	} tw_sm_c_100;
-
-	struct {
-		u32 unused                         : 6;
-		u32 force_stop                     : 1;
-		u32 exlicit_stops                  : 1;
-		u32 data4_reg                      : 8;
-		u32 data3_reg                      : 8;
-		u32 data2_reg                      : 8;
-	} tw_sm_c_104;
-
-	struct {
-		u32 reserved2                      :19;
-		u32 tlo1                           : 5;
-		u32 reserved1                      : 2;
-		u32 thi1                           : 6;
-	} tw_sm_c_108;
-
-	struct {
-		u32 reserved2                      :19;
-		u32 tlo1                           : 5;
-		u32 reserved1                      : 2;
-		u32 thi1                           : 6;
-	} tw_sm_c_10c;
-
-	struct {
-		u32 reserved2                      :19;
-		u32 tlo1                           : 5;
-		u32 reserved1                      : 2;
-		u32 thi1                           : 6;
-	} tw_sm_c_110;
-
-	struct {
-		u32 LNB_CTLPrescaler_sig           : 2;
-		u32 LNB_CTLLowCount_sig            :15;
-		u32 LNB_CTLHighCount_sig           :15;
-	} lnb_switch_freq_200;
-
-	struct {
-		u32 Rev_N_sig_reserved2            : 1;
-		u32 Rev_N_sig_caps                 : 1;
-		u32 Rev_N_sig_reserved1            : 2;
-		u32 Rev_N_sig_revision_hi          : 4;
-		u32 reserved                       :20;
-		u32 Per_reset_sig                  : 1;
-		u32 LNB_L_H_sig                    : 1;
-		u32 ACPI3_sig                      : 1;
-		u32 ACPI1_sig                      : 1;
-	} misc_204;
-
-	struct {
-		u32 unused                         : 9;
-		u32 Mailbox_from_V8_Enable_sig     : 1;
-		u32 DMA2_Size_IRQ_Enable_sig       : 1;
-		u32 DMA1_Size_IRQ_Enable_sig       : 1;
-		u32 DMA2_Timer_Enable_sig          : 1;
-		u32 DMA2_IRQ_Enable_sig            : 1;
-		u32 DMA1_Timer_Enable_sig          : 1;
-		u32 DMA1_IRQ_Enable_sig            : 1;
-		u32 Rcv_Data_sig                   : 1;
-		u32 MAC_filter_Mode_sig            : 1;
-		u32 Multi2_Enable_sig              : 1;
-		u32 Per_CA_Enable_sig              : 1;
-		u32 SMC_Enable_sig                 : 1;
-		u32 CA_Enable_sig                  : 1;
-		u32 WAN_CA_Enable_sig              : 1;
-		u32 WAN_Enable_sig                 : 1;
-		u32 Mask_filter_sig                : 1;
-		u32 Null_filter_sig                : 1;
-		u32 ECM_filter_sig                 : 1;
-		u32 EMM_filter_sig                 : 1;
-		u32 PMT_filter_sig                 : 1;
-		u32 PCR_filter_sig                 : 1;
-		u32 Stream2_filter_sig             : 1;
-		u32 Stream1_filter_sig             : 1;
-	} ctrl_208;
-
-	struct {
-		u32 reserved                       :21;
-		u32 Transport_Error                : 1;
-		u32 LLC_SNAP_FLAG_set              : 1;
-		u32 Continuity_error_flag          : 1;
-		u32 Data_receiver_error            : 1;
-		u32 Mailbox_from_V8_Status_sig     : 1;
-		u32 DMA2_Size_IRQ_Status           : 1;
-		u32 DMA1_Size_IRQ_Status           : 1;
-		u32 DMA2_Timer_Status              : 1;
-		u32 DMA2_IRQ_Status                : 1;
-		u32 DMA1_Timer_Status              : 1;
-		u32 DMA1_IRQ_Status                : 1;
-	} irq_20c;
-
-	struct {
-		u32 Special_controls               :16;
-		u32 Block_reset_enable             : 8;
-		u32 reset_block_700                : 1;
-		u32 reset_block_600                : 1;
-		u32 reset_block_500                : 1;
-		u32 reset_block_400                : 1;
-		u32 reset_block_300                : 1;
-		u32 reset_block_200                : 1;
-		u32 reset_block_100                : 1;
-		u32 reset_block_000                : 1;
-	} sw_reset_210;
-
-	struct {
-		u32 unused2                        :20;
-		u32 polarity_PS_ERR_sig            : 1;
-		u32 polarity_PS_SYNC_sig           : 1;
-		u32 polarity_PS_VALID_sig          : 1;
-		u32 polarity_PS_CLK_sig            : 1;
-		u32 unused1                        : 3;
-		u32 s2p_sel_sig                    : 1;
-		u32 section_pkg_enable_sig         : 1;
-		u32 halt_V8_sig                    : 1;
-		u32 v2WS_oe_sig                    : 1;
-		u32 vuart_oe_sig                   : 1;
-	} misc_214;
-
-	struct {
-		u32 Mailbox_from_V8                :32;
-	} mbox_v8_to_host_218;
-
-	struct {
-		u32 sysramaccess_busmuster         : 1;
-		u32 sysramaccess_write             : 1;
-		u32 unused                         : 7;
-		u32 sysramaccess_addr              :15;
-		u32 sysramaccess_data              : 8;
-	} mbox_host_to_v8_21c;
-
-	struct {
-		u32 debug_fifo_problem             : 1;
-		u32 debug_flag_write_status00      : 1;
-		u32 Stream2_trans                  : 1;
-		u32 Stream2_PID                    :13;
-		u32 debug_flag_pid_saved           : 1;
-		u32 MAC_Multicast_filter           : 1;
-		u32 Stream1_trans                  : 1;
-		u32 Stream1_PID                    :13;
-	} pid_filter_300;
-
-	struct {
-		u32 reserved                       : 2;
-		u32 PMT_trans                      : 1;
-		u32 PMT_PID                        :13;
-		u32 debug_overrun2                 : 1;
-		u32 debug_overrun3                 : 1;
-		u32 PCR_trans                      : 1;
-		u32 PCR_PID                        :13;
-	} pid_filter_304;
-
-	struct {
-		u32 reserved                       : 2;
-		u32 ECM_trans                      : 1;
-		u32 ECM_PID                        :13;
-		u32 EMM_filter_6                   : 1;
-		u32 EMM_filter_4                   : 1;
-		u32 EMM_trans                      : 1;
-		u32 EMM_PID                        :13;
-	} pid_filter_308;
-
-	struct {
-		u32 unused2                        : 3;
-		u32 Group_mask                     :13;
-		u32 unused1                        : 2;
-		u32 Group_trans                    : 1;
-		u32 Group_PID                      :13;
-	} pid_filter_30c_ext_ind_0_7;
-
-	struct {
-		u32 unused                         :15;
-		u32 net_master_read                :17;
-	} pid_filter_30c_ext_ind_1;
-
-	struct {
-		u32 unused                         :15;
-		u32 net_master_write               :17;
-	} pid_filter_30c_ext_ind_2;
-
-	struct {
-		u32 unused                         :15;
-		u32 next_net_master_write          :17;
-	} pid_filter_30c_ext_ind_3;
-
-	struct {
-		u32 reserved2                      : 5;
-		u32 stack_read                     :10;
-		u32 reserved1                      : 6;
-		u32 state_write                    :10;
-		u32 unused1                        : 1;
-	} pid_filter_30c_ext_ind_4;
-
-	struct {
-		u32 unused                         :22;
-		u32 stack_cnt                      :10;
-	} pid_filter_30c_ext_ind_5;
-
-	struct {
-		u32 unused                         : 4;
-		u32 data_size_reg                  :12;
-		u32 write_status4                  : 2;
-		u32 write_status1                  : 2;
-		u32 pid_fsm_save_reg300            : 2;
-		u32 pid_fsm_save_reg4              : 2;
-		u32 pid_fsm_save_reg3              : 2;
-		u32 pid_fsm_save_reg2              : 2;
-		u32 pid_fsm_save_reg1              : 2;
-		u32 pid_fsm_save_reg0              : 2;
-	} pid_filter_30c_ext_ind_6;
-
-	struct {
-		u32 unused                         :22;
-		u32 pass_alltables                 : 1;
-		u32 AB_select                      : 1;
-		u32 extra_index_reg                : 3;
-		u32 index_reg                      : 5;
-	} index_reg_310;
-
-	struct {
-		u32 reserved                       :17;
-		u32 PID_enable_bit                 : 1;
-		u32 PID_trans                      : 1;
-		u32 PID                            :13;
-	} pid_n_reg_314;
-
-	struct {
-		u32 reserved                       : 6;
-		u32 HighAB_bit                     : 1;
-		u32 Enable_bit                     : 1;
-		u32 A6_byte                        : 8;
-		u32 A5_byte                        : 8;
-		u32 A4_byte                        : 8;
-	} mac_low_reg_318;
-
-	struct {
-		u32 reserved                       : 8;
-		u32 A3_byte                        : 8;
-		u32 A2_byte                        : 8;
-		u32 A1_byte                        : 8;
-	} mac_high_reg_31c;
-
-	struct {
-		u32 data_Tag_ID                    :16;
-		u32 reserved                       :16;
-	} data_tag_400;
-
-	struct {
-		u32 Card_IDbyte3                   : 8;
-		u32 Card_IDbyte4                   : 8;
-		u32 Card_IDbyte5                   : 8;
-		u32 Card_IDbyte6                   : 8;
-	} card_id_408;
-
-	struct {
-		u32 Card_IDbyte1                   : 8;
-		u32 Card_IDbyte2                   : 8;
-	} card_id_40c;
-
-	struct {
-		u32 MAC6                           : 8;
-		u32 MAC3                           : 8;
-		u32 MAC2                           : 8;
-		u32 MAC1                           : 8;
-	} mac_address_418;
-
-	struct {
-		u32 reserved                       :16;
-		u32 MAC8                           : 8;
-		u32 MAC7                           : 8;
-	} mac_address_41c;
-
-	struct {
-		u32 reserved                       :21;
-		u32 txbuffempty                    : 1;
-		u32 ReceiveByteFrameError          : 1;
-		u32 ReceiveDataReady               : 1;
-		u32 transmitter_data_byte          : 8;
-	} ci_600;
-
-	struct {
-		u32 pi_component_reg               : 3;
-		u32 pi_rw                          : 1;
-		u32 pi_ha                          :20;
-		u32 pi_d                           : 8;
-	} pi_604;
-
-	struct {
-		u32 pi_busy_n                      : 1;
-		u32 pi_wait_n                      : 1;
-		u32 pi_timeout_status              : 1;
-		u32 pi_CiMax_IRQ_n                 : 1;
-		u32 config_cclk                    : 1;
-		u32 config_cs_n                    : 1;
-		u32 config_wr_n                    : 1;
-		u32 config_Prog_n                  : 1;
-		u32 config_Init_stat               : 1;
-		u32 config_Done_stat               : 1;
-		u32 pcmcia_b_mod_pwr_n             : 1;
-		u32 pcmcia_a_mod_pwr_n             : 1;
-		u32 reserved                       : 3;
-		u32 Timer_addr                     : 5;
-		u32 unused                         : 1;
-		u32 timer_data                     : 7;
-		u32 Timer_Load_req                 : 1;
-		u32 Timer_Read_req                 : 1;
-		u32 oncecycle_read                 : 1;
-		u32 serialReset                    : 1;
-	} pi_608;
-
-	struct {
-		u32 reserved                       : 6;
-		u32 rw_flag                        : 1;
-		u32 dvb_en                         : 1;
-		u32 key_array_row                  : 5;
-		u32 key_array_col                  : 3;
-		u32 key_code                       : 2;
-		u32 key_enable                     : 1;
-		u32 PID                            :13;
-	} dvb_reg_60c;
-
-	struct {
-		u32 start_sram_ibi                 : 1;
-		u32 reserved2                      : 1;
-		u32 ce_pin_reg                     : 1;
-		u32 oe_pin_reg                     : 1;
-		u32 reserved1                      : 3;
-		u32 sc_xfer_bit                    : 1;
-		u32 sram_data                      : 8;
-		u32 sram_rw                        : 1;
-		u32 sram_addr                      :15;
-	} sram_ctrl_reg_700;
-
-	struct {
-		u32 net_addr_write                 :16;
-		u32 net_addr_read                  :16;
-	} net_buf_reg_704;
-
-	struct {
-		u32 cai_cnt                        : 4;
-		u32 reserved2                      : 6;
-		u32 cai_write                      :11;
-		u32 reserved1                      : 5;
-		u32 cai_read                       :11;
-	} cai_buf_reg_708;
-
-	struct {
-		u32 cao_cnt                        : 4;
-		u32 reserved2                      : 6;
-		u32 cap_write                      :11;
-		u32 reserved1                      : 5;
-		u32 cao_read                       :11;
-	} cao_buf_reg_70c;
-
-	struct {
-		u32 media_cnt                      : 4;
-		u32 reserved2                      : 6;
-		u32 media_write                    :11;
-		u32 reserved1                      : 5;
-		u32 media_read                     :11;
-	} media_buf_reg_710;
-
-	struct {
-		u32 reserved                       :17;
-		u32 ctrl_maximumfill               : 1;
-		u32 ctrl_sramdma                   : 1;
-		u32 ctrl_usb_wan                   : 1;
-		u32 cao_ovflow_error               : 1;
-		u32 cai_ovflow_error               : 1;
-		u32 media_ovflow_error             : 1;
-		u32 net_ovflow_error               : 1;
-		u32 MEDIA_Dest                     : 2;
-		u32 CAO_Dest                       : 2;
-		u32 CAI_Dest                       : 2;
-		u32 NET_Dest                       : 2;
-	} sram_dest_reg_714;
-
-	struct {
-		u32 reserved3                      :11;
-		u32 net_addr_write                 : 1;
-		u32 reserved2                      : 3;
-		u32 net_addr_read                  : 1;
-		u32 reserved1                      : 4;
-		u32 net_cnt                        :12;
-	} net_buf_reg_718;
-
-	struct {
-		u32 reserved3                      : 4;
-		u32 wan_pkt_frame                  : 4;
-		u32 reserved2                      : 4;
-		u32 sram_memmap                    : 2;
-		u32 sram_chip                      : 2;
-		u32 wan_wait_state                 : 8;
-		u32 reserved1                      : 6;
-		u32 wan_speed_sig                  : 2;
-	} wan_ctrl_reg_71c;
-} flexcop_ibi_value;
-
-#endif
diff --git a/drivers/media/dvb/b2c2/flexcop_ibi_value_le.h b/drivers/media/dvb/b2c2/flexcop_ibi_value_le.h
deleted file mode 100644
index c75830d..0000000
--- a/drivers/media/dvb/b2c2/flexcop_ibi_value_le.h
+++ /dev/null
@@ -1,455 +0,0 @@
-/* Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
- * register descriptions
- * 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__
-
-typedef union {
-	u32 raw;
-
-	struct {
-		u32 dma_0start                     : 1;
-		u32 dma_0No_update                 : 1;
-		u32 dma_address0                   :30;
-	} dma_0x0;
-
-	struct {
-		u32 DMA_maxpackets                 : 8;
-		u32 dma_addr_size                  :24;
-	} dma_0x4_remap;
-
-	struct {
-		u32 dma1timer                      : 7;
-		u32 unused                         : 1;
-		u32 dma_addr_size                  :24;
-	} dma_0x4_read;
-
-	struct {
-		u32 unused                         : 1;
-		u32 dmatimer                       : 7;
-		u32 dma_addr_size                  :24;
-	} dma_0x4_write;
-
-	struct {
-		u32 unused                         : 2;
-		u32 dma_cur_addr                   :30;
-	} dma_0x8;
-
-	struct {
-		u32 dma_1start                     : 1;
-		u32 remap_enable                   : 1;
-		u32 dma_address1                   :30;
-	} dma_0xc;
-
-	struct {
-		u32 chipaddr                       : 7;
-		u32 reserved1                      : 1;
-		u32 baseaddr                       : 8;
-		u32 data1_reg                      : 8;
-		u32 working_start                  : 1;
-		u32 twoWS_rw                       : 1;
-		u32 total_bytes                    : 2;
-		u32 twoWS_port_reg                 : 2;
-		u32 no_base_addr_ack_error         : 1;
-		u32 st_done                        : 1;
-	} tw_sm_c_100;
-
-	struct {
-		u32 data2_reg                      : 8;
-		u32 data3_reg                      : 8;
-		u32 data4_reg                      : 8;
-		u32 exlicit_stops                  : 1;
-		u32 force_stop                     : 1;
-		u32 unused                         : 6;
-	} tw_sm_c_104;
-
-	struct {
-		u32 thi1                           : 6;
-		u32 reserved1                      : 2;
-		u32 tlo1                           : 5;
-		u32 reserved2                      :19;
-	} tw_sm_c_108;
-
-	struct {
-		u32 thi1                           : 6;
-		u32 reserved1                      : 2;
-		u32 tlo1                           : 5;
-		u32 reserved2                      :19;
-	} tw_sm_c_10c;
-
-	struct {
-		u32 thi1                           : 6;
-		u32 reserved1                      : 2;
-		u32 tlo1                           : 5;
-		u32 reserved2                      :19;
-	} tw_sm_c_110;
-
-	struct {
-		u32 LNB_CTLHighCount_sig           :15;
-		u32 LNB_CTLLowCount_sig            :15;
-		u32 LNB_CTLPrescaler_sig           : 2;
-	} lnb_switch_freq_200;
-
-	struct {
-		u32 ACPI1_sig                      : 1;
-		u32 ACPI3_sig                      : 1;
-		u32 LNB_L_H_sig                    : 1;
-		u32 Per_reset_sig                  : 1;
-		u32 reserved                       :20;
-		u32 Rev_N_sig_revision_hi          : 4;
-		u32 Rev_N_sig_reserved1            : 2;
-		u32 Rev_N_sig_caps                 : 1;
-		u32 Rev_N_sig_reserved2            : 1;
-	} misc_204;
-
-	struct {
-		u32 Stream1_filter_sig             : 1;
-		u32 Stream2_filter_sig             : 1;
-		u32 PCR_filter_sig                 : 1;
-		u32 PMT_filter_sig                 : 1;
-		u32 EMM_filter_sig                 : 1;
-		u32 ECM_filter_sig                 : 1;
-		u32 Null_filter_sig                : 1;
-		u32 Mask_filter_sig                : 1;
-		u32 WAN_Enable_sig                 : 1;
-		u32 WAN_CA_Enable_sig              : 1;
-		u32 CA_Enable_sig                  : 1;
-		u32 SMC_Enable_sig                 : 1;
-		u32 Per_CA_Enable_sig              : 1;
-		u32 Multi2_Enable_sig              : 1;
-		u32 MAC_filter_Mode_sig            : 1;
-		u32 Rcv_Data_sig                   : 1;
-		u32 DMA1_IRQ_Enable_sig            : 1;
-		u32 DMA1_Timer_Enable_sig          : 1;
-		u32 DMA2_IRQ_Enable_sig            : 1;
-		u32 DMA2_Timer_Enable_sig          : 1;
-		u32 DMA1_Size_IRQ_Enable_sig       : 1;
-		u32 DMA2_Size_IRQ_Enable_sig       : 1;
-		u32 Mailbox_from_V8_Enable_sig     : 1;
-		u32 unused                         : 9;
-	} ctrl_208;
-
-	struct {
-		u32 DMA1_IRQ_Status                : 1;
-		u32 DMA1_Timer_Status              : 1;
-		u32 DMA2_IRQ_Status                : 1;
-		u32 DMA2_Timer_Status              : 1;
-		u32 DMA1_Size_IRQ_Status           : 1;
-		u32 DMA2_Size_IRQ_Status           : 1;
-		u32 Mailbox_from_V8_Status_sig     : 1;
-		u32 Data_receiver_error            : 1;
-		u32 Continuity_error_flag          : 1;
-		u32 LLC_SNAP_FLAG_set              : 1;
-		u32 Transport_Error                : 1;
-		u32 reserved                       :21;
-	} irq_20c;
-
-	struct {
-		u32 reset_block_000                : 1;
-		u32 reset_block_100                : 1;
-		u32 reset_block_200                : 1;
-		u32 reset_block_300                : 1;
-		u32 reset_block_400                : 1;
-		u32 reset_block_500                : 1;
-		u32 reset_block_600                : 1;
-		u32 reset_block_700                : 1;
-		u32 Block_reset_enable             : 8;
-		u32 Special_controls               :16;
-	} sw_reset_210;
-
-	struct {
-		u32 vuart_oe_sig                   : 1;
-		u32 v2WS_oe_sig                    : 1;
-		u32 halt_V8_sig                    : 1;
-		u32 section_pkg_enable_sig         : 1;
-		u32 s2p_sel_sig                    : 1;
-		u32 unused1                        : 3;
-		u32 polarity_PS_CLK_sig            : 1;
-		u32 polarity_PS_VALID_sig          : 1;
-		u32 polarity_PS_SYNC_sig           : 1;
-		u32 polarity_PS_ERR_sig            : 1;
-		u32 unused2                        :20;
-	} misc_214;
-
-	struct {
-		u32 Mailbox_from_V8                :32;
-	} mbox_v8_to_host_218;
-
-	struct {
-		u32 sysramaccess_data              : 8;
-		u32 sysramaccess_addr              :15;
-		u32 unused                         : 7;
-		u32 sysramaccess_write             : 1;
-		u32 sysramaccess_busmuster         : 1;
-	} mbox_host_to_v8_21c;
-
-	struct {
-		u32 Stream1_PID                    :13;
-		u32 Stream1_trans                  : 1;
-		u32 MAC_Multicast_filter           : 1;
-		u32 debug_flag_pid_saved           : 1;
-		u32 Stream2_PID                    :13;
-		u32 Stream2_trans                  : 1;
-		u32 debug_flag_write_status00      : 1;
-		u32 debug_fifo_problem             : 1;
-	} pid_filter_300;
-
-	struct {
-		u32 PCR_PID                        :13;
-		u32 PCR_trans                      : 1;
-		u32 debug_overrun3                 : 1;
-		u32 debug_overrun2                 : 1;
-		u32 PMT_PID                        :13;
-		u32 PMT_trans                      : 1;
-		u32 reserved                       : 2;
-	} pid_filter_304;
-
-	struct {
-		u32 EMM_PID                        :13;
-		u32 EMM_trans                      : 1;
-		u32 EMM_filter_4                   : 1;
-		u32 EMM_filter_6                   : 1;
-		u32 ECM_PID                        :13;
-		u32 ECM_trans                      : 1;
-		u32 reserved                       : 2;
-	} pid_filter_308;
-
-	struct {
-		u32 Group_PID                      :13;
-		u32 Group_trans                    : 1;
-		u32 unused1                        : 2;
-		u32 Group_mask                     :13;
-		u32 unused2                        : 3;
-	} pid_filter_30c_ext_ind_0_7;
-
-	struct {
-		u32 net_master_read                :17;
-		u32 unused                         :15;
-	} pid_filter_30c_ext_ind_1;
-
-	struct {
-		u32 net_master_write               :17;
-		u32 unused                         :15;
-	} pid_filter_30c_ext_ind_2;
-
-	struct {
-		u32 next_net_master_write          :17;
-		u32 unused                         :15;
-	} pid_filter_30c_ext_ind_3;
-
-	struct {
-		u32 unused1                        : 1;
-		u32 state_write                    :10;
-		u32 reserved1                      : 6;
-		u32 stack_read                     :10;
-		u32 reserved2                      : 5;
-	} pid_filter_30c_ext_ind_4;
-
-	struct {
-		u32 stack_cnt                      :10;
-		u32 unused                         :22;
-	} pid_filter_30c_ext_ind_5;
-
-	struct {
-		u32 pid_fsm_save_reg0              : 2;
-		u32 pid_fsm_save_reg1              : 2;
-		u32 pid_fsm_save_reg2              : 2;
-		u32 pid_fsm_save_reg3              : 2;
-		u32 pid_fsm_save_reg4              : 2;
-		u32 pid_fsm_save_reg300            : 2;
-		u32 write_status1                  : 2;
-		u32 write_status4                  : 2;
-		u32 data_size_reg                  :12;
-		u32 unused                         : 4;
-	} pid_filter_30c_ext_ind_6;
-
-	struct {
-		u32 index_reg                      : 5;
-		u32 extra_index_reg                : 3;
-		u32 AB_select                      : 1;
-		u32 pass_alltables                 : 1;
-		u32 unused                         :22;
-	} index_reg_310;
-
-	struct {
-		u32 PID                            :13;
-		u32 PID_trans                      : 1;
-		u32 PID_enable_bit                 : 1;
-		u32 reserved                       :17;
-	} pid_n_reg_314;
-
-	struct {
-		u32 A4_byte                        : 8;
-		u32 A5_byte                        : 8;
-		u32 A6_byte                        : 8;
-		u32 Enable_bit                     : 1;
-		u32 HighAB_bit                     : 1;
-		u32 reserved                       : 6;
-	} mac_low_reg_318;
-
-	struct {
-		u32 A1_byte                        : 8;
-		u32 A2_byte                        : 8;
-		u32 A3_byte                        : 8;
-		u32 reserved                       : 8;
-	} mac_high_reg_31c;
-
-	struct {
-		u32 reserved                       :16;
-		u32 data_Tag_ID                    :16;
-	} data_tag_400;
-
-	struct {
-		u32 Card_IDbyte6                   : 8;
-		u32 Card_IDbyte5                   : 8;
-		u32 Card_IDbyte4                   : 8;
-		u32 Card_IDbyte3                   : 8;
-	} card_id_408;
-
-	struct {
-		u32 Card_IDbyte2                   : 8;
-		u32 Card_IDbyte1                   : 8;
-	} card_id_40c;
-
-	struct {
-		u32 MAC1                           : 8;
-		u32 MAC2                           : 8;
-		u32 MAC3                           : 8;
-		u32 MAC6                           : 8;
-	} mac_address_418;
-
-	struct {
-		u32 MAC7                           : 8;
-		u32 MAC8                           : 8;
-		u32 reserved                       :16;
-	} mac_address_41c;
-
-	struct {
-		u32 transmitter_data_byte          : 8;
-		u32 ReceiveDataReady               : 1;
-		u32 ReceiveByteFrameError          : 1;
-		u32 txbuffempty                    : 1;
-		u32 reserved                       :21;
-	} ci_600;
-
-	struct {
-		u32 pi_d                           : 8;
-		u32 pi_ha                          :20;
-		u32 pi_rw                          : 1;
-		u32 pi_component_reg               : 3;
-	} pi_604;
-
-	struct {
-		u32 serialReset                    : 1;
-		u32 oncecycle_read                 : 1;
-		u32 Timer_Read_req                 : 1;
-		u32 Timer_Load_req                 : 1;
-		u32 timer_data                     : 7;
-		u32 unused                         : 1;
-		u32 Timer_addr                     : 5;
-		u32 reserved                       : 3;
-		u32 pcmcia_a_mod_pwr_n             : 1;
-		u32 pcmcia_b_mod_pwr_n             : 1;
-		u32 config_Done_stat               : 1;
-		u32 config_Init_stat               : 1;
-		u32 config_Prog_n                  : 1;
-		u32 config_wr_n                    : 1;
-		u32 config_cs_n                    : 1;
-		u32 config_cclk                    : 1;
-		u32 pi_CiMax_IRQ_n                 : 1;
-		u32 pi_timeout_status              : 1;
-		u32 pi_wait_n                      : 1;
-		u32 pi_busy_n                      : 1;
-	} pi_608;
-
-	struct {
-		u32 PID                            :13;
-		u32 key_enable                     : 1;
-		u32 key_code                       : 2;
-		u32 key_array_col                  : 3;
-		u32 key_array_row                  : 5;
-		u32 dvb_en                         : 1;
-		u32 rw_flag                        : 1;
-		u32 reserved                       : 6;
-	} dvb_reg_60c;
-
-	struct {
-		u32 sram_addr                      :15;
-		u32 sram_rw                        : 1;
-		u32 sram_data                      : 8;
-		u32 sc_xfer_bit                    : 1;
-		u32 reserved1                      : 3;
-		u32 oe_pin_reg                     : 1;
-		u32 ce_pin_reg                     : 1;
-		u32 reserved2                      : 1;
-		u32 start_sram_ibi                 : 1;
-	} sram_ctrl_reg_700;
-
-	struct {
-		u32 net_addr_read                  :16;
-		u32 net_addr_write                 :16;
-	} net_buf_reg_704;
-
-	struct {
-		u32 cai_read                       :11;
-		u32 reserved1                      : 5;
-		u32 cai_write                      :11;
-		u32 reserved2                      : 6;
-		u32 cai_cnt                        : 4;
-	} cai_buf_reg_708;
-
-	struct {
-		u32 cao_read                       :11;
-		u32 reserved1                      : 5;
-		u32 cap_write                      :11;
-		u32 reserved2                      : 6;
-		u32 cao_cnt                        : 4;
-	} cao_buf_reg_70c;
-
-	struct {
-		u32 media_read                     :11;
-		u32 reserved1                      : 5;
-		u32 media_write                    :11;
-		u32 reserved2                      : 6;
-		u32 media_cnt                      : 4;
-	} media_buf_reg_710;
-
-	struct {
-		u32 NET_Dest                       : 2;
-		u32 CAI_Dest                       : 2;
-		u32 CAO_Dest                       : 2;
-		u32 MEDIA_Dest                     : 2;
-		u32 net_ovflow_error               : 1;
-		u32 media_ovflow_error             : 1;
-		u32 cai_ovflow_error               : 1;
-		u32 cao_ovflow_error               : 1;
-		u32 ctrl_usb_wan                   : 1;
-		u32 ctrl_sramdma                   : 1;
-		u32 ctrl_maximumfill               : 1;
-		u32 reserved                       :17;
-	} sram_dest_reg_714;
-
-	struct {
-		u32 net_cnt                        :12;
-		u32 reserved1                      : 4;
-		u32 net_addr_read                  : 1;
-		u32 reserved2                      : 3;
-		u32 net_addr_write                 : 1;
-		u32 reserved3                      :11;
-	} net_buf_reg_718;
-
-	struct {
-		u32 wan_speed_sig                  : 2;
-		u32 reserved1                      : 6;
-		u32 wan_wait_state                 : 8;
-		u32 sram_chip                      : 2;
-		u32 sram_memmap                    : 2;
-		u32 reserved2                      : 4;
-		u32 wan_pkt_frame                  : 4;
-		u32 reserved3                      : 4;
-	} wan_ctrl_reg_71c;
-} flexcop_ibi_value;
-
-#endif
diff --git a/drivers/media/dvb/bt8xx/Kconfig b/drivers/media/dvb/bt8xx/Kconfig
deleted file mode 100644
index 8668e63..0000000
--- a/drivers/media/dvb/bt8xx/Kconfig
+++ /dev/null
@@ -1,22 +0,0 @@
-config DVB_BT8XX
-	tristate "BT8xx based PCI cards"
-	depends on DVB_CORE && PCI && I2C && VIDEO_BT848
-	select DVB_MT352 if !DVB_FE_CUSTOMISE
-	select DVB_SP887X if !DVB_FE_CUSTOMISE
-	select DVB_NXT6000 if !DVB_FE_CUSTOMISE
-	select DVB_CX24110 if !DVB_FE_CUSTOMISE
-	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_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,
-	  the pcHDTV HD2000 cards, the DViCO FusionHDTV Lite cards, and
-	  some AVerMedia cards.
-
-	  Since these cards have no MPEG decoder onboard, they transmit
-	  only compressed MPEG data over the PCI bus, so you need
-	  an external software decoder to watch TV on your computer.
-
-	  Say Y if you own such a device and want to use it.
diff --git a/drivers/media/dvb/bt8xx/Makefile b/drivers/media/dvb/bt8xx/Makefile
deleted file mode 100644
index 0713b3a..0000000
--- a/drivers/media/dvb/bt8xx/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-obj-$(CONFIG_DVB_BT8XX) += bt878.o dvb-bt8xx.o dst.o dst_ca.o
-
-ccflags-y += -Idrivers/media/dvb/dvb-core
-ccflags-y += -Idrivers/media/dvb/frontends
-ccflags-y += -Idrivers/media/video/bt8xx
-ccflags-y += -Idrivers/media/common/tuners
diff --git a/drivers/media/dvb/bt8xx/bt878.c b/drivers/media/dvb/bt8xx/bt878.c
deleted file mode 100644
index b34fa95..0000000
--- a/drivers/media/dvb/bt8xx/bt878.c
+++ /dev/null
@@ -1,609 +0,0 @@
-/*
- * bt878.c: part of the driver for the Pinnacle PCTV Sat DVB PCI card
- *
- * Copyright (C) 2002 Peter Hettkamp <peter.hettkamp@htp-tel.de>
- *
- * large parts based on the bttv driver
- * Copyright (C) 1996,97,98 Ralph  Metzler (rjkm@metzlerbros.de)
- *                        & Marcus Metzler (mocm@metzlerbros.de)
- * (c) 1999,2000 Gerd Knorr <kraxel@goldbach.in-berlin.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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- *
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <asm/io.h>
-#include <linux/ioport.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/kmod.h>
-#include <linux/vmalloc.h>
-#include <linux/init.h>
-
-#include "dmxdev.h"
-#include "dvbdev.h"
-#include "bt878.h"
-#include "dst_priv.h"
-
-
-/**************************************/
-/* Miscellaneous utility  definitions */
-/**************************************/
-
-static unsigned int bt878_verbose = 1;
-static unsigned int bt878_debug;
-
-module_param_named(verbose, bt878_verbose, int, 0444);
-MODULE_PARM_DESC(verbose,
-		 "verbose startup messages, default is 1 (yes)");
-module_param_named(debug, bt878_debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off debugging, default is 0 (off).");
-
-int bt878_num;
-struct bt878 bt878[BT878_MAX];
-
-EXPORT_SYMBOL(bt878_num);
-EXPORT_SYMBOL(bt878);
-
-#define btwrite(dat,adr)    bmtwrite((dat), (bt->bt878_mem+(adr)))
-#define btread(adr)         bmtread(bt->bt878_mem+(adr))
-
-#define btand(dat,adr)      btwrite((dat) & btread(adr), adr)
-#define btor(dat,adr)       btwrite((dat) | btread(adr), adr)
-#define btaor(dat,mask,adr) btwrite((dat) | ((mask) & btread(adr)), adr)
-
-#if defined(dprintk)
-#undef dprintk
-#endif
-#define dprintk(fmt, arg...) \
-	do { \
-		if (bt878_debug) \
-			printk(KERN_DEBUG fmt, ##arg); \
-	} while (0)
-
-static void bt878_mem_free(struct bt878 *bt)
-{
-	if (bt->buf_cpu) {
-		pci_free_consistent(bt->dev, bt->buf_size, bt->buf_cpu,
-				    bt->buf_dma);
-		bt->buf_cpu = NULL;
-	}
-
-	if (bt->risc_cpu) {
-		pci_free_consistent(bt->dev, bt->risc_size, bt->risc_cpu,
-				    bt->risc_dma);
-		bt->risc_cpu = NULL;
-	}
-}
-
-static int bt878_mem_alloc(struct bt878 *bt)
-{
-	if (!bt->buf_cpu) {
-		bt->buf_size = 128 * 1024;
-
-		bt->buf_cpu =
-		    pci_alloc_consistent(bt->dev, bt->buf_size,
-					 &bt->buf_dma);
-
-		if (!bt->buf_cpu)
-			return -ENOMEM;
-
-		memset(bt->buf_cpu, 0, bt->buf_size);
-	}
-
-	if (!bt->risc_cpu) {
-		bt->risc_size = PAGE_SIZE;
-		bt->risc_cpu =
-		    pci_alloc_consistent(bt->dev, bt->risc_size,
-					 &bt->risc_dma);
-
-		if (!bt->risc_cpu) {
-			bt878_mem_free(bt);
-			return -ENOMEM;
-		}
-
-		memset(bt->risc_cpu, 0, bt->risc_size);
-	}
-
-	return 0;
-}
-
-/* RISC instructions */
-#define RISC_WRITE		(0x01 << 28)
-#define RISC_JUMP		(0x07 << 28)
-#define RISC_SYNC		(0x08 << 28)
-
-/* RISC bits */
-#define RISC_WR_SOL		(1 << 27)
-#define RISC_WR_EOL		(1 << 26)
-#define RISC_IRQ		(1 << 24)
-#define RISC_STATUS(status)	((((~status) & 0x0F) << 20) | ((status & 0x0F) << 16))
-#define RISC_SYNC_RESYNC	(1 << 15)
-#define RISC_SYNC_FM1		0x06
-#define RISC_SYNC_VRO		0x0C
-
-#define RISC_FLUSH()		bt->risc_pos = 0
-#define RISC_INSTR(instr)	bt->risc_cpu[bt->risc_pos++] = cpu_to_le32(instr)
-
-static int bt878_make_risc(struct bt878 *bt)
-{
-	bt->block_bytes = bt->buf_size >> 4;
-	bt->block_count = 1 << 4;
-	bt->line_bytes = bt->block_bytes;
-	bt->line_count = bt->block_count;
-
-	while (bt->line_bytes > 4095) {
-		bt->line_bytes >>= 1;
-		bt->line_count <<= 1;
-	}
-
-	if (bt->line_count > 255) {
-		printk(KERN_ERR "bt878: buffer size error!\n");
-		return -EINVAL;
-	}
-	return 0;
-}
-
-
-static void bt878_risc_program(struct bt878 *bt, u32 op_sync_orin)
-{
-	u32 buf_pos = 0;
-	u32 line;
-
-	RISC_FLUSH();
-	RISC_INSTR(RISC_SYNC | RISC_SYNC_FM1 | op_sync_orin);
-	RISC_INSTR(0);
-
-	dprintk("bt878: risc len lines %u, bytes per line %u\n",
-			bt->line_count, bt->line_bytes);
-	for (line = 0; line < bt->line_count; line++) {
-		// At the beginning of every block we issue an IRQ with previous (finished) block number set
-		if (!(buf_pos % bt->block_bytes))
-			RISC_INSTR(RISC_WRITE | RISC_WR_SOL | RISC_WR_EOL |
-				   RISC_IRQ |
-				   RISC_STATUS(((buf_pos /
-						 bt->block_bytes) +
-						(bt->block_count -
-						 1)) %
-					       bt->block_count) | bt->
-				   line_bytes);
-		else
-			RISC_INSTR(RISC_WRITE | RISC_WR_SOL | RISC_WR_EOL |
-				   bt->line_bytes);
-		RISC_INSTR(bt->buf_dma + buf_pos);
-		buf_pos += bt->line_bytes;
-	}
-
-	RISC_INSTR(RISC_SYNC | op_sync_orin | RISC_SYNC_VRO);
-	RISC_INSTR(0);
-
-	RISC_INSTR(RISC_JUMP);
-	RISC_INSTR(bt->risc_dma);
-
-	btwrite((bt->line_count << 16) | bt->line_bytes, BT878_APACK_LEN);
-}
-
-/*****************************/
-/* Start/Stop grabbing funcs */
-/*****************************/
-
-void bt878_start(struct bt878 *bt, u32 controlreg, u32 op_sync_orin,
-		u32 irq_err_ignore)
-{
-	u32 int_mask;
-
-	dprintk("bt878 debug: bt878_start (ctl=%8.8x)\n", controlreg);
-	/* complete the writing of the risc dma program now we have
-	 * the card specifics
-	 */
-	bt878_risc_program(bt, op_sync_orin);
-	controlreg &= ~0x1f;
-	controlreg |= 0x1b;
-
-	btwrite(bt->risc_dma, BT878_ARISC_START);
-
-	/* original int mask had :
-	 *    6    2    8    4    0
-	 * 1111 1111 1000 0000 0000
-	 * SCERR|OCERR|PABORT|RIPERR|FDSR|FTRGT|FBUS|RISCI
-	 * Hacked for DST to:
-	 * SCERR | OCERR | FDSR | FTRGT | FBUS | RISCI
-	 */
-	int_mask = BT878_ASCERR | BT878_AOCERR | BT878_APABORT |
-		BT878_ARIPERR | BT878_APPERR | BT878_AFDSR | BT878_AFTRGT |
-		BT878_AFBUS | BT878_ARISCI;
-
-
-	/* ignore pesky bits */
-	int_mask &= ~irq_err_ignore;
-
-	btwrite(int_mask, BT878_AINT_MASK);
-	btwrite(controlreg, BT878_AGPIO_DMA_CTL);
-}
-
-void bt878_stop(struct bt878 *bt)
-{
-	u32 stat;
-	int i = 0;
-
-	dprintk("bt878 debug: bt878_stop\n");
-
-	btwrite(0, BT878_AINT_MASK);
-	btand(~0x13, BT878_AGPIO_DMA_CTL);
-
-	do {
-		stat = btread(BT878_AINT_STAT);
-		if (!(stat & BT878_ARISC_EN))
-			break;
-		i++;
-	} while (i < 500);
-
-	dprintk("bt878(%d) debug: bt878_stop, i=%d, stat=0x%8.8x\n",
-		bt->nr, i, stat);
-}
-
-EXPORT_SYMBOL(bt878_start);
-EXPORT_SYMBOL(bt878_stop);
-
-/*****************************/
-/* Interrupt service routine */
-/*****************************/
-
-static irqreturn_t bt878_irq(int irq, void *dev_id)
-{
-	u32 stat, astat, mask;
-	int count;
-	struct bt878 *bt;
-
-	bt = (struct bt878 *) dev_id;
-
-	count = 0;
-	while (1) {
-		stat = btread(BT878_AINT_STAT);
-		mask = btread(BT878_AINT_MASK);
-		if (!(astat = (stat & mask)))
-			return IRQ_NONE;	/* this interrupt is not for me */
-/*		dprintk("bt878(%d) debug: irq count %d, stat 0x%8.8x, mask 0x%8.8x\n",bt->nr,count,stat,mask); */
-		btwrite(astat, BT878_AINT_STAT);	/* try to clear interrupt condition */
-
-
-		if (astat & (BT878_ASCERR | BT878_AOCERR)) {
-			if (bt878_verbose) {
-				printk(KERN_INFO
-				       "bt878(%d): irq%s%s risc_pc=%08x\n",
-				       bt->nr,
-				       (astat & BT878_ASCERR) ? " SCERR" :
-				       "",
-				       (astat & BT878_AOCERR) ? " OCERR" :
-				       "", btread(BT878_ARISC_PC));
-			}
-		}
-		if (astat & (BT878_APABORT | BT878_ARIPERR | BT878_APPERR)) {
-			if (bt878_verbose) {
-				printk(KERN_INFO
-				     "bt878(%d): irq%s%s%s risc_pc=%08x\n",
-				     bt->nr,
-				     (astat & BT878_APABORT) ? " PABORT" :
-				     "",
-				     (astat & BT878_ARIPERR) ? " RIPERR" :
-				     "",
-				     (astat & BT878_APPERR) ? " PPERR" :
-				     "", btread(BT878_ARISC_PC));
-			}
-		}
-		if (astat & (BT878_AFDSR | BT878_AFTRGT | BT878_AFBUS)) {
-			if (bt878_verbose) {
-				printk(KERN_INFO
-				     "bt878(%d): irq%s%s%s risc_pc=%08x\n",
-				     bt->nr,
-				     (astat & BT878_AFDSR) ? " FDSR" : "",
-				     (astat & BT878_AFTRGT) ? " FTRGT" :
-				     "",
-				     (astat & BT878_AFBUS) ? " FBUS" : "",
-				     btread(BT878_ARISC_PC));
-			}
-		}
-		if (astat & BT878_ARISCI) {
-			bt->finished_block = (stat & BT878_ARISCS) >> 28;
-			tasklet_schedule(&bt->tasklet);
-			break;
-		}
-		count++;
-		if (count > 20) {
-			btwrite(0, BT878_AINT_MASK);
-			printk(KERN_ERR
-			       "bt878(%d): IRQ lockup, cleared int mask\n",
-			       bt->nr);
-			break;
-		}
-	}
-	return IRQ_HANDLED;
-}
-
-int
-bt878_device_control(struct bt878 *bt, unsigned int cmd, union dst_gpio_packet *mp)
-{
-	int retval;
-
-	retval = 0;
-	if (mutex_lock_interruptible(&bt->gpio_lock))
-		return -ERESTARTSYS;
-	/* special gpio signal */
-	switch (cmd) {
-	    case DST_IG_ENABLE:
-		// dprintk("dvb_bt8xx: dst enable mask 0x%02x enb 0x%02x \n", mp->dstg.enb.mask, mp->dstg.enb.enable);
-		retval = bttv_gpio_enable(bt->bttv_nr,
-				mp->enb.mask,
-				mp->enb.enable);
-		break;
-	    case DST_IG_WRITE:
-		// dprintk("dvb_bt8xx: dst write gpio mask 0x%02x out 0x%02x\n", mp->dstg.outp.mask, mp->dstg.outp.highvals);
-		retval = bttv_write_gpio(bt->bttv_nr,
-				mp->outp.mask,
-				mp->outp.highvals);
-
-		break;
-	    case DST_IG_READ:
-		/* read */
-		retval =  bttv_read_gpio(bt->bttv_nr, &mp->rd.value);
-		// dprintk("dvb_bt8xx: dst read gpio 0x%02x\n", (unsigned)mp->dstg.rd.value);
-		break;
-	    case DST_IG_TS:
-		/* Set packet size */
-		bt->TS_Size = mp->psize;
-		break;
-
-	    default:
-		retval = -EINVAL;
-		break;
-	}
-	mutex_unlock(&bt->gpio_lock);
-	return retval;
-}
-
-EXPORT_SYMBOL(bt878_device_control);
-
-#define BROOKTREE_878_DEVICE(vend, dev, name) \
-	{ \
-		.vendor = PCI_VENDOR_ID_BROOKTREE, \
-		.device = PCI_DEVICE_ID_BROOKTREE_878, \
-		.subvendor = (vend), .subdevice = (dev), \
-		.driver_data = (unsigned long) name \
-	}
-
-static struct pci_device_id bt878_pci_tbl[] __devinitdata = {
-	BROOKTREE_878_DEVICE(0x0071, 0x0101, "Nebula Electronics DigiTV"),
-	BROOKTREE_878_DEVICE(0x1461, 0x0761, "AverMedia AverTV DVB-T 761"),
-	BROOKTREE_878_DEVICE(0x11bd, 0x001c, "Pinnacle PCTV Sat"),
-	BROOKTREE_878_DEVICE(0x11bd, 0x0026, "Pinnacle PCTV SAT CI"),
-	BROOKTREE_878_DEVICE(0x1822, 0x0001, "Twinhan VisionPlus DVB"),
-	BROOKTREE_878_DEVICE(0x270f, 0xfc00,
-				"ChainTech digitop DST-1000 DVB-S"),
-	BROOKTREE_878_DEVICE(0x1461, 0x0771, "AVermedia AverTV DVB-T 771"),
-	BROOKTREE_878_DEVICE(0x18ac, 0xdb10, "DViCO FusionHDTV DVB-T Lite"),
-	BROOKTREE_878_DEVICE(0x18ac, 0xdb11, "Ultraview DVB-T Lite"),
-	BROOKTREE_878_DEVICE(0x18ac, 0xd500, "DViCO FusionHDTV 5 Lite"),
-	BROOKTREE_878_DEVICE(0x7063, 0x2000, "pcHDTV HD-2000 TV"),
-	BROOKTREE_878_DEVICE(0x1822, 0x0026, "DNTV Live! Mini"),
-	{ }
-};
-
-MODULE_DEVICE_TABLE(pci, bt878_pci_tbl);
-
-static const char * __devinit card_name(const struct pci_device_id *id)
-{
-	return id->driver_data ? (const char *)id->driver_data : "Unknown";
-}
-
-/***********************/
-/* PCI device handling */
-/***********************/
-
-static int __devinit bt878_probe(struct pci_dev *dev,
-				 const struct pci_device_id *pci_id)
-{
-	int result = 0;
-	unsigned char lat;
-	struct bt878 *bt;
-#if defined(__powerpc__)
-	unsigned int cmd;
-#endif
-	unsigned int cardid;
-
-	printk(KERN_INFO "bt878: Bt878 AUDIO function found (%d).\n",
-	       bt878_num);
-	if (bt878_num >= BT878_MAX) {
-		printk(KERN_ERR "bt878: Too many devices inserted\n");
-		result = -ENOMEM;
-		goto fail0;
-	}
-	if (pci_enable_device(dev))
-		return -EIO;
-
-	cardid = dev->subsystem_device << 16;
-	cardid |= dev->subsystem_vendor;
-
-	printk(KERN_INFO "%s: card id=[0x%x],[ %s ] has DVB functions.\n",
-				__func__, cardid, card_name(pci_id));
-
-	bt = &bt878[bt878_num];
-	bt->dev = dev;
-	bt->nr = bt878_num;
-	bt->shutdown = 0;
-
-	bt->id = dev->device;
-	bt->irq = dev->irq;
-	bt->bt878_adr = pci_resource_start(dev, 0);
-	if (!request_mem_region(pci_resource_start(dev, 0),
-				pci_resource_len(dev, 0), "bt878")) {
-		result = -EBUSY;
-		goto fail0;
-	}
-
-	bt->revision = dev->revision;
-	pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
-
-
-	printk(KERN_INFO "bt878(%d): Bt%x (rev %d) at %02x:%02x.%x, ",
-	       bt878_num, bt->id, bt->revision, dev->bus->number,
-	       PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
-	printk("irq: %d, latency: %d, memory: 0x%lx\n",
-	       bt->irq, lat, bt->bt878_adr);
-
-
-#if defined(__powerpc__)
-	/* on OpenFirmware machines (PowerMac at least), PCI memory cycle */
-	/* response on cards with no firmware is not enabled by OF */
-	pci_read_config_dword(dev, PCI_COMMAND, &cmd);
-	cmd = (cmd | PCI_COMMAND_MEMORY);
-	pci_write_config_dword(dev, PCI_COMMAND, cmd);
-#endif
-
-#ifdef __sparc__
-	bt->bt878_mem = (unsigned char *) bt->bt878_adr;
-#else
-	bt->bt878_mem = ioremap(bt->bt878_adr, 0x1000);
-#endif
-
-	/* clear interrupt mask */
-	btwrite(0, BT848_INT_MASK);
-
-	result = request_irq(bt->irq, bt878_irq,
-			     IRQF_SHARED | IRQF_DISABLED, "bt878",
-			     (void *) bt);
-	if (result == -EINVAL) {
-		printk(KERN_ERR "bt878(%d): Bad irq number or handler\n",
-		       bt878_num);
-		goto fail1;
-	}
-	if (result == -EBUSY) {
-		printk(KERN_ERR
-		       "bt878(%d): IRQ %d busy, change your PnP config in BIOS\n",
-		       bt878_num, bt->irq);
-		goto fail1;
-	}
-	if (result < 0)
-		goto fail1;
-
-	pci_set_master(dev);
-	pci_set_drvdata(dev, bt);
-
-	if ((result = bt878_mem_alloc(bt))) {
-		printk(KERN_ERR "bt878: failed to allocate memory!\n");
-		goto fail2;
-	}
-
-	bt878_make_risc(bt);
-	btwrite(0, BT878_AINT_MASK);
-	bt878_num++;
-
-	return 0;
-
-      fail2:
-	free_irq(bt->irq, bt);
-      fail1:
-	release_mem_region(pci_resource_start(bt->dev, 0),
-			   pci_resource_len(bt->dev, 0));
-      fail0:
-	pci_disable_device(dev);
-	return result;
-}
-
-static void __devexit bt878_remove(struct pci_dev *pci_dev)
-{
-	u8 command;
-	struct bt878 *bt = pci_get_drvdata(pci_dev);
-
-	if (bt878_verbose)
-		printk(KERN_INFO "bt878(%d): unloading\n", bt->nr);
-
-	/* turn off all capturing, DMA and IRQs */
-	btand(~0x13, BT878_AGPIO_DMA_CTL);
-
-	/* first disable interrupts before unmapping the memory! */
-	btwrite(0, BT878_AINT_MASK);
-	btwrite(~0U, BT878_AINT_STAT);
-
-	/* disable PCI bus-mastering */
-	pci_read_config_byte(bt->dev, PCI_COMMAND, &command);
-	/* Should this be &=~ ?? */
-	command &= ~PCI_COMMAND_MASTER;
-	pci_write_config_byte(bt->dev, PCI_COMMAND, command);
-
-	free_irq(bt->irq, bt);
-	printk(KERN_DEBUG "bt878_mem: 0x%p.\n", bt->bt878_mem);
-	if (bt->bt878_mem)
-		iounmap(bt->bt878_mem);
-
-	release_mem_region(pci_resource_start(bt->dev, 0),
-			   pci_resource_len(bt->dev, 0));
-	/* wake up any waiting processes
-	   because shutdown flag is set, no new processes (in this queue)
-	   are expected
-	 */
-	bt->shutdown = 1;
-	bt878_mem_free(bt);
-
-	pci_set_drvdata(pci_dev, NULL);
-	pci_disable_device(pci_dev);
-	return;
-}
-
-static struct pci_driver bt878_pci_driver = {
-      .name	= "bt878",
-      .id_table = bt878_pci_tbl,
-      .probe	= bt878_probe,
-      .remove	= __devexit_p(bt878_remove),
-};
-
-/*******************************/
-/* Module management functions */
-/*******************************/
-
-static int __init bt878_init_module(void)
-{
-	bt878_num = 0;
-
-	printk(KERN_INFO "bt878: AUDIO driver version %d.%d.%d loaded\n",
-	       (BT878_VERSION_CODE >> 16) & 0xff,
-	       (BT878_VERSION_CODE >> 8) & 0xff,
-	       BT878_VERSION_CODE & 0xff);
-
-	return pci_register_driver(&bt878_pci_driver);
-}
-
-static void __exit bt878_cleanup_module(void)
-{
-	pci_unregister_driver(&bt878_pci_driver);
-}
-
-module_init(bt878_init_module);
-module_exit(bt878_cleanup_module);
-
-MODULE_LICENSE("GPL");
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/dvb/bt8xx/bt878.h b/drivers/media/dvb/bt8xx/bt878.h
deleted file mode 100644
index d19b592..0000000
--- a/drivers/media/dvb/bt8xx/bt878.h
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
-    bt878.h - Bt878 audio module (register offsets)
-
-    Copyright (C) 2002 Peter Hettkamp <peter.hettkamp@htp-tel.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 _BT878_H_
-#define _BT878_H_
-
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/sched.h>
-#include <linux/spinlock.h>
-#include <linux/mutex.h>
-
-#include "bt848.h"
-#include "bttv.h"
-
-#define BT878_VERSION_CODE 0x000000
-
-#define BT878_AINT_STAT		0x100
-#define BT878_ARISCS		(0xf<<28)
-#define BT878_ARISC_EN		(1<<27)
-#define BT878_ASCERR		(1<<19)
-#define BT878_AOCERR		(1<<18)
-#define BT878_APABORT		(1<<17)
-#define BT878_ARIPERR		(1<<16)
-#define BT878_APPERR		(1<<15)
-#define BT878_AFDSR		(1<<14)
-#define BT878_AFTRGT		(1<<13)
-#define BT878_AFBUS		(1<<12)
-#define BT878_ARISCI		(1<<11)
-#define BT878_AOFLOW		(1<<3)
-
-#define BT878_AINT_MASK		0x104
-
-#define BT878_AGPIO_DMA_CTL	0x10c
-#define BT878_A_GAIN		(0xf<<28)
-#define BT878_A_G2X		(1<<27)
-#define BT878_A_PWRDN		(1<<26)
-#define BT878_A_SEL		(3<<24)
-#define BT878_DA_SCE		(1<<23)
-#define BT878_DA_LRI		(1<<22)
-#define BT878_DA_MLB		(1<<21)
-#define BT878_DA_LRD		(0x1f<<16)
-#define BT878_DA_DPM		(1<<15)
-#define BT878_DA_SBR		(1<<14)
-#define BT878_DA_ES2		(1<<13)
-#define BT878_DA_LMT		(1<<12)
-#define BT878_DA_SDR		(0xf<<8)
-#define BT878_DA_IOM		(3<<6)
-#define BT878_DA_APP		(1<<5)
-#define BT878_ACAP_EN		(1<<4)
-#define BT878_PKTP		(3<<2)
-#define BT878_RISC_EN		(1<<1)
-#define BT878_FIFO_EN		1
-
-#define BT878_APACK_LEN		0x110
-#define BT878_AFP_LEN		(0xff<<16)
-#define BT878_ALP_LEN		0xfff
-
-#define BT878_ARISC_START	0x114
-
-#define BT878_ARISC_PC		0x120
-
-/* BT878 FUNCTION 0 REGISTERS */
-#define BT878_GPIO_DMA_CTL	0x10c
-
-/* Interrupt register */
-#define BT878_INT_STAT		0x100
-#define BT878_INT_MASK		0x104
-#define BT878_I2CRACK		(1<<25)
-#define BT878_I2CDONE		(1<<8)
-
-#define BT878_MAX 4
-
-#define BT878_RISC_SYNC_MASK	(1 << 15)
-
-
-#define BTTV_BOARD_UNKNOWN                 0x00
-#define BTTV_BOARD_PINNACLESAT             0x5e
-#define BTTV_BOARD_NEBULA_DIGITV           0x68
-#define BTTV_BOARD_PC_HDTV                 0x70
-#define BTTV_BOARD_TWINHAN_DST             0x71
-#define BTTV_BOARD_AVDVBT_771              0x7b
-#define BTTV_BOARD_AVDVBT_761              0x7c
-#define BTTV_BOARD_DVICO_DVBT_LITE         0x80
-#define BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE 0x87
-
-extern int bt878_num;
-
-struct bt878 {
-	struct mutex gpio_lock;
-	unsigned int nr;
-	unsigned int bttv_nr;
-	struct i2c_adapter *adapter;
-	struct pci_dev *dev;
-	unsigned int id;
-	unsigned int TS_Size;
-	unsigned char revision;
-	unsigned int irq;
-	unsigned long bt878_adr;
-	volatile void __iomem *bt878_mem; /* function 1 */
-
-	volatile u32 finished_block;
-	volatile u32 last_block;
-	u32 block_count;
-	u32 block_bytes;
-	u32 line_bytes;
-	u32 line_count;
-
-	u32 buf_size;
-	u8 *buf_cpu;
-	dma_addr_t buf_dma;
-
-	u32 risc_size;
-	__le32 *risc_cpu;
-	dma_addr_t risc_dma;
-	u32 risc_pos;
-
-	struct tasklet_struct tasklet;
-	int shutdown;
-};
-
-extern struct bt878 bt878[BT878_MAX];
-
-void bt878_start(struct bt878 *bt, u32 controlreg, u32 op_sync_orin,
-		u32 irq_err_ignore);
-void bt878_stop(struct bt878 *bt);
-
-#if defined(__powerpc__)	/* big-endian */
-static inline void io_st_le32(volatile unsigned __iomem *addr, unsigned val)
-{
-	st_le32(addr, val);
-	eieio();
-}
-
-#define bmtwrite(dat,adr)  io_st_le32((adr),(dat))
-#define bmtread(adr)       ld_le32((adr))
-#else
-#define bmtwrite(dat,adr)  writel((dat), (adr))
-#define bmtread(adr)       readl(adr)
-#endif
-
-#endif
diff --git a/drivers/media/dvb/bt8xx/dst.c b/drivers/media/dvb/bt8xx/dst.c
deleted file mode 100644
index 430b3eb..0000000
--- a/drivers/media/dvb/bt8xx/dst.c
+++ /dev/null
@@ -1,1873 +0,0 @@
-/*
-	Frontend/Card driver for TwinHan DST Frontend
-	Copyright (C) 2003 Jamie Honan
-	Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.com)
-
-	This program is free software; you can redistribute it and/or modify
-	it under the terms of the GNU General Public License as published by
-	the Free Software Foundation; either version 2 of the License, or
-	(at your option) any later version.
-
-	This program is distributed in the hope that it will be useful,
-	but WITHOUT ANY WARRANTY; without even the implied warranty of
-	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	GNU General Public License for more details.
-
-	You should have received a copy of the GNU General Public License
-	along with this program; if not, write to the Free Software
-	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/delay.h>
-#include <asm/div64.h>
-#include "dvb_frontend.h"
-#include "dst_priv.h"
-#include "dst_common.h"
-
-static unsigned int verbose = 1;
-module_param(verbose, int, 0644);
-MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)");
-
-static unsigned int dst_addons;
-module_param(dst_addons, int, 0644);
-MODULE_PARM_DESC(dst_addons, "CA daughterboard, default is 0 (No addons)");
-
-static unsigned int dst_algo;
-module_param(dst_algo, int, 0644);
-MODULE_PARM_DESC(dst_algo, "tuning algo: default is 0=(SW), 1=(HW)");
-
-#define HAS_LOCK		1
-#define ATTEMPT_TUNE		2
-#define HAS_POWER		4
-
-#define DST_ERROR		0
-#define DST_NOTICE		1
-#define DST_INFO		2
-#define DST_DEBUG		3
-
-#define dprintk(x, y, z, format, arg...) do {				\
-	if (z) {							\
-		if	((x > DST_ERROR) && (x > y))			\
-			printk(KERN_ERR "dst(%d) %s: " format "\n",	\
-				state->bt->nr, __func__ , ##arg);	\
-		else if	((x > DST_NOTICE) && (x > y))			\
-			printk(KERN_NOTICE "dst(%d) %s: " format "\n",  \
-				state->bt->nr, __func__ , ##arg);	\
-		else if ((x > DST_INFO) && (x > y))			\
-			printk(KERN_INFO "dst(%d) %s: " format "\n",	\
-				state->bt->nr, __func__ , ##arg);	\
-		else if ((x > DST_DEBUG) && (x > y))			\
-			printk(KERN_DEBUG "dst(%d) %s: " format "\n",	\
-				state->bt->nr,  __func__ , ##arg);	\
-	} else {							\
-		if (x > y)						\
-			printk(format, ##arg);				\
-	}								\
-} while(0)
-
-static int dst_command(struct dst_state *state, u8 *data, u8 len);
-
-static void dst_packsize(struct dst_state *state, int psize)
-{
-	union dst_gpio_packet bits;
-
-	bits.psize = psize;
-	bt878_device_control(state->bt, DST_IG_TS, &bits);
-}
-
-static int dst_gpio_outb(struct dst_state *state, u32 mask, u32 enbb,
-			 u32 outhigh, int delay)
-{
-	union dst_gpio_packet enb;
-	union dst_gpio_packet bits;
-	int err;
-
-	enb.enb.mask = mask;
-	enb.enb.enable = enbb;
-
-	dprintk(verbose, DST_INFO, 1, "mask=[%04x], enbb=[%04x], outhigh=[%04x]", mask, enbb, outhigh);
-	if ((err = bt878_device_control(state->bt, DST_IG_ENABLE, &enb)) < 0) {
-		dprintk(verbose, DST_INFO, 1, "dst_gpio_enb error (err == %i, mask == %02x, enb == %02x)", err, mask, enbb);
-		return -EREMOTEIO;
-	}
-	udelay(1000);
-	/* because complete disabling means no output, no need to do output packet */
-	if (enbb == 0)
-		return 0;
-	if (delay)
-		msleep(10);
-	bits.outp.mask = enbb;
-	bits.outp.highvals = outhigh;
-	if ((err = bt878_device_control(state->bt, DST_IG_WRITE, &bits)) < 0) {
-		dprintk(verbose, DST_INFO, 1, "dst_gpio_outb error (err == %i, enbb == %02x, outhigh == %02x)", err, enbb, outhigh);
-		return -EREMOTEIO;
-	}
-
-	return 0;
-}
-
-static int dst_gpio_inb(struct dst_state *state, u8 *result)
-{
-	union dst_gpio_packet rd_packet;
-	int err;
-
-	*result = 0;
-	if ((err = bt878_device_control(state->bt, DST_IG_READ, &rd_packet)) < 0) {
-		dprintk(verbose, DST_ERROR, 1, "dst_gpio_inb error (err == %i)", err);
-		return -EREMOTEIO;
-	}
-	*result = (u8) rd_packet.rd.value;
-
-	return 0;
-}
-
-int rdc_reset_state(struct dst_state *state)
-{
-	dprintk(verbose, DST_INFO, 1, "Resetting state machine");
-	if (dst_gpio_outb(state, RDC_8820_INT, RDC_8820_INT, 0, NO_DELAY) < 0) {
-		dprintk(verbose, DST_ERROR, 1, "dst_gpio_outb ERROR !");
-		return -1;
-	}
-	msleep(10);
-	if (dst_gpio_outb(state, RDC_8820_INT, RDC_8820_INT, RDC_8820_INT, NO_DELAY) < 0) {
-		dprintk(verbose, DST_ERROR, 1, "dst_gpio_outb ERROR !");
-		msleep(10);
-		return -1;
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL(rdc_reset_state);
-
-static int rdc_8820_reset(struct dst_state *state)
-{
-	dprintk(verbose, DST_DEBUG, 1, "Resetting DST");
-	if (dst_gpio_outb(state, RDC_8820_RESET, RDC_8820_RESET, 0, NO_DELAY) < 0) {
-		dprintk(verbose, DST_ERROR, 1, "dst_gpio_outb ERROR !");
-		return -1;
-	}
-	udelay(1000);
-	if (dst_gpio_outb(state, RDC_8820_RESET, RDC_8820_RESET, RDC_8820_RESET, DELAY) < 0) {
-		dprintk(verbose, DST_ERROR, 1, "dst_gpio_outb ERROR !");
-		return -1;
-	}
-
-	return 0;
-}
-
-static int dst_pio_enable(struct dst_state *state)
-{
-	if (dst_gpio_outb(state, ~0, RDC_8820_PIO_0_ENABLE, 0, NO_DELAY) < 0) {
-		dprintk(verbose, DST_ERROR, 1, "dst_gpio_outb ERROR !");
-		return -1;
-	}
-	udelay(1000);
-
-	return 0;
-}
-
-int dst_pio_disable(struct dst_state *state)
-{
-	if (dst_gpio_outb(state, ~0, RDC_8820_PIO_0_DISABLE, RDC_8820_PIO_0_DISABLE, NO_DELAY) < 0) {
-		dprintk(verbose, DST_ERROR, 1, "dst_gpio_outb ERROR !");
-		return -1;
-	}
-	if (state->type_flags & DST_TYPE_HAS_FW_1)
-		udelay(1000);
-
-	return 0;
-}
-EXPORT_SYMBOL(dst_pio_disable);
-
-int dst_wait_dst_ready(struct dst_state *state, u8 delay_mode)
-{
-	u8 reply;
-	int i;
-
-	for (i = 0; i < 200; i++) {
-		if (dst_gpio_inb(state, &reply) < 0) {
-			dprintk(verbose, DST_ERROR, 1, "dst_gpio_inb ERROR !");
-			return -1;
-		}
-		if ((reply & RDC_8820_PIO_0_ENABLE) == 0) {
-			dprintk(verbose, DST_INFO, 1, "dst wait ready after %d", i);
-			return 1;
-		}
-		msleep(10);
-	}
-	dprintk(verbose, DST_NOTICE, 1, "dst wait NOT ready after %d", i);
-
-	return 0;
-}
-EXPORT_SYMBOL(dst_wait_dst_ready);
-
-int dst_error_recovery(struct dst_state *state)
-{
-	dprintk(verbose, DST_NOTICE, 1, "Trying to return from previous errors.");
-	dst_pio_disable(state);
-	msleep(10);
-	dst_pio_enable(state);
-	msleep(10);
-
-	return 0;
-}
-EXPORT_SYMBOL(dst_error_recovery);
-
-int dst_error_bailout(struct dst_state *state)
-{
-	dprintk(verbose, DST_INFO, 1, "Trying to bailout from previous error.");
-	rdc_8820_reset(state);
-	dst_pio_disable(state);
-	msleep(10);
-
-	return 0;
-}
-EXPORT_SYMBOL(dst_error_bailout);
-
-int dst_comm_init(struct dst_state *state)
-{
-	dprintk(verbose, DST_INFO, 1, "Initializing DST.");
-	if ((dst_pio_enable(state)) < 0) {
-		dprintk(verbose, DST_ERROR, 1, "PIO Enable Failed");
-		return -1;
-	}
-	if ((rdc_reset_state(state)) < 0) {
-		dprintk(verbose, DST_ERROR, 1, "RDC 8820 State RESET Failed.");
-		return -1;
-	}
-	if (state->type_flags & DST_TYPE_HAS_FW_1)
-		msleep(100);
-	else
-		msleep(5);
-
-	return 0;
-}
-EXPORT_SYMBOL(dst_comm_init);
-
-int write_dst(struct dst_state *state, u8 *data, u8 len)
-{
-	struct i2c_msg msg = {
-		.addr = state->config->demod_address,
-		.flags = 0,
-		.buf = data,
-		.len = len
-	};
-
-	int err;
-	u8 cnt, i;
-
-	dprintk(verbose, DST_NOTICE, 0, "writing [ ");
-	for (i = 0; i < len; i++)
-		dprintk(verbose, DST_NOTICE, 0, "%02x ", data[i]);
-	dprintk(verbose, DST_NOTICE, 0, "]\n");
-
-	for (cnt = 0; cnt < 2; cnt++) {
-		if ((err = i2c_transfer(state->i2c, &msg, 1)) < 0) {
-			dprintk(verbose, DST_INFO, 1, "_write_dst error (err == %i, len == 0x%02x, b0 == 0x%02x)", err, len, data[0]);
-			dst_error_recovery(state);
-			continue;
-		} else
-			break;
-	}
-	if (cnt >= 2) {
-		dprintk(verbose, DST_INFO, 1, "RDC 8820 RESET");
-		dst_error_bailout(state);
-
-		return -1;
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL(write_dst);
-
-int read_dst(struct dst_state *state, u8 *ret, u8 len)
-{
-	struct i2c_msg msg = {
-		.addr = state->config->demod_address,
-		.flags = I2C_M_RD,
-		.buf = ret,
-		.len = len
-	};
-
-	int err;
-	int cnt;
-
-	for (cnt = 0; cnt < 2; cnt++) {
-		if ((err = i2c_transfer(state->i2c, &msg, 1)) < 0) {
-			dprintk(verbose, DST_INFO, 1, "read_dst error (err == %i, len == 0x%02x, b0 == 0x%02x)", err, len, ret[0]);
-			dst_error_recovery(state);
-			continue;
-		} else
-			break;
-	}
-	if (cnt >= 2) {
-		dprintk(verbose, DST_INFO, 1, "RDC 8820 RESET");
-		dst_error_bailout(state);
-
-		return -1;
-	}
-	dprintk(verbose, DST_DEBUG, 1, "reply is 0x%x", ret[0]);
-	for (err = 1; err < len; err++)
-		dprintk(verbose, DST_DEBUG, 0, " 0x%x", ret[err]);
-	if (err > 1)
-		dprintk(verbose, DST_DEBUG, 0, "\n");
-
-	return 0;
-}
-EXPORT_SYMBOL(read_dst);
-
-static int dst_set_polarization(struct dst_state *state)
-{
-	switch (state->voltage) {
-	case SEC_VOLTAGE_13:	/*	Vertical	*/
-		dprintk(verbose, DST_INFO, 1, "Polarization=[Vertical]");
-		state->tx_tuna[8] &= ~0x40;
-		break;
-	case SEC_VOLTAGE_18:	/*	Horizontal	*/
-		dprintk(verbose, DST_INFO, 1, "Polarization=[Horizontal]");
-		state->tx_tuna[8] |= 0x40;
-		break;
-	case SEC_VOLTAGE_OFF:
-		break;
-	}
-
-	return 0;
-}
-
-static int dst_set_freq(struct dst_state *state, u32 freq)
-{
-	state->frequency = freq;
-	dprintk(verbose, DST_INFO, 1, "set Frequency %u", freq);
-
-	if (state->dst_type == DST_TYPE_IS_SAT) {
-		freq = freq / 1000;
-		if (freq < 950 || freq > 2150)
-			return -EINVAL;
-		state->tx_tuna[2] = (freq >> 8);
-		state->tx_tuna[3] = (u8) freq;
-		state->tx_tuna[4] = 0x01;
-		state->tx_tuna[8] &= ~0x04;
-		if (state->type_flags & DST_TYPE_HAS_OBS_REGS) {
-			if (freq < 1531)
-				state->tx_tuna[8] |= 0x04;
-		}
-	} else if (state->dst_type == DST_TYPE_IS_TERR) {
-		freq = freq / 1000;
-		if (freq < 137000 || freq > 858000)
-			return -EINVAL;
-		state->tx_tuna[2] = (freq >> 16) & 0xff;
-		state->tx_tuna[3] = (freq >> 8) & 0xff;
-		state->tx_tuna[4] = (u8) freq;
-	} else if (state->dst_type == DST_TYPE_IS_CABLE) {
-		freq = freq / 1000;
-		state->tx_tuna[2] = (freq >> 16) & 0xff;
-		state->tx_tuna[3] = (freq >> 8) & 0xff;
-		state->tx_tuna[4] = (u8) freq;
-	} else if (state->dst_type == DST_TYPE_IS_ATSC) {
-		freq = freq / 1000;
-		if (freq < 51000 || freq > 858000)
-			return -EINVAL;
-		state->tx_tuna[2] = (freq >> 16) & 0xff;
-		state->tx_tuna[3] = (freq >>  8) & 0xff;
-		state->tx_tuna[4] = (u8) freq;
-		state->tx_tuna[5] = 0x00;		/*	ATSC	*/
-		state->tx_tuna[6] = 0x00;
-		if (state->dst_hw_cap & DST_TYPE_HAS_ANALOG)
-			state->tx_tuna[7] = 0x00;	/*	Digital	*/
-	} else
-		return -EINVAL;
-
-	return 0;
-}
-
-static int dst_set_bandwidth(struct dst_state *state, u32 bandwidth)
-{
-	state->bandwidth = bandwidth;
-
-	if (state->dst_type != DST_TYPE_IS_TERR)
-		return -EOPNOTSUPP;
-
-	switch (bandwidth) {
-	case 6000000:
-		if (state->dst_hw_cap & DST_TYPE_HAS_CA)
-			state->tx_tuna[7] = 0x06;
-		else {
-			state->tx_tuna[6] = 0x06;
-			state->tx_tuna[7] = 0x00;
-		}
-		break;
-	case 7000000:
-		if (state->dst_hw_cap & DST_TYPE_HAS_CA)
-			state->tx_tuna[7] = 0x07;
-		else {
-			state->tx_tuna[6] = 0x07;
-			state->tx_tuna[7] = 0x00;
-		}
-		break;
-	case 8000000:
-		if (state->dst_hw_cap & DST_TYPE_HAS_CA)
-			state->tx_tuna[7] = 0x08;
-		else {
-			state->tx_tuna[6] = 0x08;
-			state->tx_tuna[7] = 0x00;
-		}
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int dst_set_inversion(struct dst_state *state, fe_spectral_inversion_t inversion)
-{
-	state->inversion = inversion;
-	switch (inversion) {
-	case INVERSION_OFF:	/*	Inversion = Normal	*/
-		state->tx_tuna[8] &= ~0x80;
-		break;
-	case INVERSION_ON:
-		state->tx_tuna[8] |= 0x80;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int dst_set_fec(struct dst_state *state, fe_code_rate_t fec)
-{
-	state->fec = fec;
-	return 0;
-}
-
-static fe_code_rate_t dst_get_fec(struct dst_state *state)
-{
-	return state->fec;
-}
-
-static int dst_set_symbolrate(struct dst_state *state, u32 srate)
-{
-	u32 symcalc;
-	u64 sval;
-
-	state->symbol_rate = srate;
-	if (state->dst_type == DST_TYPE_IS_TERR) {
-		return -EOPNOTSUPP;
-	}
-	dprintk(verbose, DST_INFO, 1, "set symrate %u", srate);
-	srate /= 1000;
-	if (state->dst_type == DST_TYPE_IS_SAT) {
-		if (state->type_flags & DST_TYPE_HAS_SYMDIV) {
-			sval = srate;
-			sval <<= 20;
-			do_div(sval, 88000);
-			symcalc = (u32) sval;
-			dprintk(verbose, DST_INFO, 1, "set symcalc %u", symcalc);
-			state->tx_tuna[5] = (u8) (symcalc >> 12);
-			state->tx_tuna[6] = (u8) (symcalc >> 4);
-			state->tx_tuna[7] = (u8) (symcalc << 4);
-		} else {
-			state->tx_tuna[5] = (u8) (srate >> 16) & 0x7f;
-			state->tx_tuna[6] = (u8) (srate >> 8);
-			state->tx_tuna[7] = (u8) srate;
-		}
-		state->tx_tuna[8] &= ~0x20;
-		if (state->type_flags & DST_TYPE_HAS_OBS_REGS) {
-			if (srate > 8000)
-				state->tx_tuna[8] |= 0x20;
-		}
-	} else if (state->dst_type == DST_TYPE_IS_CABLE) {
-		dprintk(verbose, DST_DEBUG, 1, "%s", state->fw_name);
-		if (!strncmp(state->fw_name, "DCTNEW", 6)) {
-			state->tx_tuna[5] = (u8) (srate >> 8);
-			state->tx_tuna[6] = (u8) srate;
-			state->tx_tuna[7] = 0x00;
-		} else if (!strncmp(state->fw_name, "DCT-CI", 6)) {
-			state->tx_tuna[5] = 0x00;
-			state->tx_tuna[6] = (u8) (srate >> 8);
-			state->tx_tuna[7] = (u8) srate;
-		}
-	}
-	return 0;
-}
-
-static int dst_set_modulation(struct dst_state *state, fe_modulation_t modulation)
-{
-	if (state->dst_type != DST_TYPE_IS_CABLE)
-		return -EOPNOTSUPP;
-
-	state->modulation = modulation;
-	switch (modulation) {
-	case QAM_16:
-		state->tx_tuna[8] = 0x10;
-		break;
-	case QAM_32:
-		state->tx_tuna[8] = 0x20;
-		break;
-	case QAM_64:
-		state->tx_tuna[8] = 0x40;
-		break;
-	case QAM_128:
-		state->tx_tuna[8] = 0x80;
-		break;
-	case QAM_256:
-		if (!strncmp(state->fw_name, "DCTNEW", 6))
-			state->tx_tuna[8] = 0xff;
-		else if (!strncmp(state->fw_name, "DCT-CI", 6))
-			state->tx_tuna[8] = 0x00;
-		break;
-	case QPSK:
-	case QAM_AUTO:
-	case VSB_8:
-	case VSB_16:
-	default:
-		return -EINVAL;
-
-	}
-
-	return 0;
-}
-
-static fe_modulation_t dst_get_modulation(struct dst_state *state)
-{
-	return state->modulation;
-}
-
-
-u8 dst_check_sum(u8 *buf, u32 len)
-{
-	u32 i;
-	u8 val = 0;
-	if (!len)
-		return 0;
-	for (i = 0; i < len; i++) {
-		val += buf[i];
-	}
-	return ((~val) + 1);
-}
-EXPORT_SYMBOL(dst_check_sum);
-
-static void dst_type_flags_print(struct dst_state *state)
-{
-	u32 type_flags = state->type_flags;
-
-	dprintk(verbose, DST_ERROR, 0, "DST type flags :");
-	if (type_flags & DST_TYPE_HAS_TS188)
-		dprintk(verbose, DST_ERROR, 0, " 0x%x newtuner", DST_TYPE_HAS_TS188);
-	if (type_flags & DST_TYPE_HAS_NEWTUNE_2)
-		dprintk(verbose, DST_ERROR, 0, " 0x%x newtuner 2", DST_TYPE_HAS_NEWTUNE_2);
-	if (type_flags & DST_TYPE_HAS_TS204)
-		dprintk(verbose, DST_ERROR, 0, " 0x%x ts204", DST_TYPE_HAS_TS204);
-	if (type_flags & DST_TYPE_HAS_VLF)
-		dprintk(verbose, DST_ERROR, 0, " 0x%x VLF", DST_TYPE_HAS_VLF);
-	if (type_flags & DST_TYPE_HAS_SYMDIV)
-		dprintk(verbose, DST_ERROR, 0, " 0x%x symdiv", DST_TYPE_HAS_SYMDIV);
-	if (type_flags & DST_TYPE_HAS_FW_1)
-		dprintk(verbose, DST_ERROR, 0, " 0x%x firmware version = 1", DST_TYPE_HAS_FW_1);
-	if (type_flags & DST_TYPE_HAS_FW_2)
-		dprintk(verbose, DST_ERROR, 0, " 0x%x firmware version = 2", DST_TYPE_HAS_FW_2);
-	if (type_flags & DST_TYPE_HAS_FW_3)
-		dprintk(verbose, DST_ERROR, 0, " 0x%x firmware version = 3", DST_TYPE_HAS_FW_3);
-	dprintk(verbose, DST_ERROR, 0, "\n");
-}
-
-
-static int dst_type_print(struct dst_state *state, u8 type)
-{
-	char *otype;
-	switch (type) {
-	case DST_TYPE_IS_SAT:
-		otype = "satellite";
-		break;
-
-	case DST_TYPE_IS_TERR:
-		otype = "terrestrial";
-		break;
-
-	case DST_TYPE_IS_CABLE:
-		otype = "cable";
-		break;
-
-	case DST_TYPE_IS_ATSC:
-		otype = "atsc";
-		break;
-
-	default:
-		dprintk(verbose, DST_INFO, 1, "invalid dst type %d", type);
-		return -EINVAL;
-	}
-	dprintk(verbose, DST_INFO, 1, "DST type: %s", otype);
-
-	return 0;
-}
-
-static struct tuner_types tuner_list[] = {
-	{
-		.tuner_type = TUNER_TYPE_L64724,
-		.tuner_name = "L 64724",
-		.board_name = "UNKNOWN",
-		.fw_name    = "UNKNOWN"
-	},
-
-	{
-		.tuner_type = TUNER_TYPE_STV0299,
-		.tuner_name = "STV 0299",
-		.board_name = "VP1020",
-		.fw_name    = "DST-MOT"
-	},
-
-	{
-		.tuner_type = TUNER_TYPE_STV0299,
-		.tuner_name = "STV 0299",
-		.board_name = "VP1020",
-		.fw_name    = "DST-03T"
-	},
-
-	{
-		.tuner_type = TUNER_TYPE_MB86A15,
-		.tuner_name = "MB 86A15",
-		.board_name = "VP1022",
-		.fw_name    = "DST-03T"
-	},
-
-	{
-		.tuner_type = TUNER_TYPE_MB86A15,
-		.tuner_name = "MB 86A15",
-		.board_name = "VP1025",
-		.fw_name    = "DST-03T"
-	},
-
-	{
-		.tuner_type = TUNER_TYPE_STV0299,
-		.tuner_name = "STV 0299",
-		.board_name = "VP1030",
-		.fw_name    = "DST-CI"
-	},
-
-	{
-		.tuner_type = TUNER_TYPE_STV0299,
-		.tuner_name = "STV 0299",
-		.board_name = "VP1030",
-		.fw_name    = "DSTMCI"
-	},
-
-	{
-		.tuner_type = TUNER_TYPE_UNKNOWN,
-		.tuner_name = "UNKNOWN",
-		.board_name = "VP2021",
-		.fw_name    = "DCTNEW"
-	},
-
-	{
-		.tuner_type = TUNER_TYPE_UNKNOWN,
-		.tuner_name = "UNKNOWN",
-		.board_name = "VP2030",
-		.fw_name    = "DCT-CI"
-	},
-
-	{
-		.tuner_type = TUNER_TYPE_UNKNOWN,
-		.tuner_name = "UNKNOWN",
-		.board_name = "VP2031",
-		.fw_name    = "DCT-CI"
-	},
-
-	{
-		.tuner_type = TUNER_TYPE_UNKNOWN,
-		.tuner_name = "UNKNOWN",
-		.board_name = "VP2040",
-		.fw_name    = "DCT-CI"
-	},
-
-	{
-		.tuner_type = TUNER_TYPE_UNKNOWN,
-		.tuner_name = "UNKNOWN",
-		.board_name = "VP3020",
-		.fw_name    = "DTTFTA"
-	},
-
-	{
-		.tuner_type = TUNER_TYPE_UNKNOWN,
-		.tuner_name = "UNKNOWN",
-		.board_name = "VP3021",
-		.fw_name    = "DTTFTA"
-	},
-
-	{
-		.tuner_type = TUNER_TYPE_TDA10046,
-		.tuner_name = "TDA10046",
-		.board_name = "VP3040",
-		.fw_name    = "DTT-CI"
-	},
-
-	{
-		.tuner_type = TUNER_TYPE_UNKNOWN,
-		.tuner_name = "UNKNOWN",
-		.board_name = "VP3051",
-		.fw_name    = "DTTNXT"
-	},
-
-	{
-		.tuner_type = TUNER_TYPE_NXT200x,
-		.tuner_name = "NXT200x",
-		.board_name = "VP3220",
-		.fw_name    = "ATSCDI"
-	},
-
-	{
-		.tuner_type = TUNER_TYPE_NXT200x,
-		.tuner_name = "NXT200x",
-		.board_name = "VP3250",
-		.fw_name    = "ATSCAD"
-	},
-};
-
-/*
-	Known cards list
-	Satellite
-	-------------------
-		  200103A
-	VP-1020   DST-MOT	LG(old), TS=188
-
-	VP-1020   DST-03T	LG(new), TS=204
-	VP-1022   DST-03T	LG(new), TS=204
-	VP-1025   DST-03T	LG(new), TS=204
-
-	VP-1030   DSTMCI,	LG(new), TS=188
-	VP-1032   DSTMCI,	LG(new), TS=188
-
-	Cable
-	-------------------
-	VP-2030   DCT-CI,	Samsung, TS=204
-	VP-2021   DCT-CI,	Unknown, TS=204
-	VP-2031   DCT-CI,	Philips, TS=188
-	VP-2040   DCT-CI,	Philips, TS=188, with CA daughter board
-	VP-2040   DCT-CI,	Philips, TS=204, without CA daughter board
-
-	Terrestrial
-	-------------------
-	VP-3050  DTTNXT			 TS=188
-	VP-3040  DTT-CI,	Philips, TS=188
-	VP-3040  DTT-CI,	Philips, TS=204
-
-	ATSC
-	-------------------
-	VP-3220  ATSCDI,		 TS=188
-	VP-3250  ATSCAD,		 TS=188
-
-*/
-
-static struct dst_types dst_tlist[] = {
-	{
-		.device_id = "200103A",
-		.offset = 0,
-		.dst_type =  DST_TYPE_IS_SAT,
-		.type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_FW_1 | DST_TYPE_HAS_OBS_REGS,
-		.dst_feature = 0,
-		.tuner_type = 0
-	},	/*	obsolete	*/
-
-	{
-		.device_id = "DST-020",
-		.offset = 0,
-		.dst_type =  DST_TYPE_IS_SAT,
-		.type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_FW_1,
-		.dst_feature = 0,
-		.tuner_type = 0
-	},	/*	obsolete	*/
-
-	{
-		.device_id = "DST-030",
-		.offset =  0,
-		.dst_type = DST_TYPE_IS_SAT,
-		.type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_TS188 | DST_TYPE_HAS_FW_1,
-		.dst_feature = 0,
-		.tuner_type = 0
-	},	/*	obsolete	*/
-
-	{
-		.device_id = "DST-03T",
-		.offset = 0,
-		.dst_type = DST_TYPE_IS_SAT,
-		.type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_TS204 | DST_TYPE_HAS_FW_2,
-		.dst_feature = DST_TYPE_HAS_DISEQC3 | DST_TYPE_HAS_DISEQC4 | DST_TYPE_HAS_DISEQC5
-							 | DST_TYPE_HAS_MAC | DST_TYPE_HAS_MOTO,
-		.tuner_type = TUNER_TYPE_MULTI
-	 },
-
-	{
-		.device_id = "DST-MOT",
-		.offset =  0,
-		.dst_type = DST_TYPE_IS_SAT,
-		.type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_FW_1,
-		.dst_feature = 0,
-		.tuner_type = 0
-	},	/*	obsolete	*/
-
-	{
-		.device_id = "DST-CI",
-		.offset = 1,
-		.dst_type = DST_TYPE_IS_SAT,
-		.type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_FW_1,
-		.dst_feature = DST_TYPE_HAS_CA,
-		.tuner_type = 0
-	},	/*	An OEM board	*/
-
-	{
-		.device_id = "DSTMCI",
-		.offset = 1,
-		.dst_type = DST_TYPE_IS_SAT,
-		.type_flags = DST_TYPE_HAS_TS188 | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_FW_BUILD | DST_TYPE_HAS_INC_COUNT | DST_TYPE_HAS_VLF,
-		.dst_feature = DST_TYPE_HAS_CA | DST_TYPE_HAS_DISEQC3 | DST_TYPE_HAS_DISEQC4
-							| DST_TYPE_HAS_MOTO | DST_TYPE_HAS_MAC,
-		.tuner_type = TUNER_TYPE_MULTI
-	},
-
-	{
-		.device_id = "DSTFCI",
-		.offset = 1,
-		.dst_type = DST_TYPE_IS_SAT,
-		.type_flags = DST_TYPE_HAS_TS188 | DST_TYPE_HAS_FW_1,
-		.dst_feature = 0,
-		.tuner_type = 0
-	},	/* unknown to vendor	*/
-
-	{
-		.device_id = "DCT-CI",
-		.offset = 1,
-		.dst_type = DST_TYPE_IS_CABLE,
-		.type_flags = DST_TYPE_HAS_MULTI_FE | DST_TYPE_HAS_FW_1	| DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_VLF,
-		.dst_feature = DST_TYPE_HAS_CA,
-		.tuner_type = 0
-	},
-
-	{
-		.device_id = "DCTNEW",
-		.offset = 1,
-		.dst_type = DST_TYPE_IS_CABLE,
-		.type_flags = DST_TYPE_HAS_TS188 | DST_TYPE_HAS_FW_3 | DST_TYPE_HAS_FW_BUILD | DST_TYPE_HAS_MULTI_FE,
-		.dst_feature = 0,
-		.tuner_type = 0
-	},
-
-	{
-		.device_id = "DTT-CI",
-		.offset = 1,
-		.dst_type = DST_TYPE_IS_TERR,
-		.type_flags = DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_MULTI_FE | DST_TYPE_HAS_VLF,
-		.dst_feature = DST_TYPE_HAS_CA,
-		.tuner_type = 0
-	},
-
-	{
-		.device_id = "DTTDIG",
-		.offset = 1,
-		.dst_type = DST_TYPE_IS_TERR,
-		.type_flags = DST_TYPE_HAS_FW_2,
-		.dst_feature = 0,
-		.tuner_type = 0
-	},
-
-	{
-		.device_id = "DTTNXT",
-		.offset = 1,
-		.dst_type = DST_TYPE_IS_TERR,
-		.type_flags = DST_TYPE_HAS_FW_2,
-		.dst_feature = DST_TYPE_HAS_ANALOG,
-		.tuner_type = 0
-	},
-
-	{
-		.device_id = "ATSCDI",
-		.offset = 1,
-		.dst_type = DST_TYPE_IS_ATSC,
-		.type_flags = DST_TYPE_HAS_FW_2,
-		.dst_feature = 0,
-		.tuner_type = 0
-	},
-
-	{
-		.device_id = "ATSCAD",
-		.offset = 1,
-		.dst_type = DST_TYPE_IS_ATSC,
-		.type_flags = DST_TYPE_HAS_MULTI_FE | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_FW_BUILD,
-		.dst_feature = DST_TYPE_HAS_MAC | DST_TYPE_HAS_ANALOG,
-		.tuner_type = 0
-	},
-
-	{ }
-
-};
-
-static int dst_get_mac(struct dst_state *state)
-{
-	u8 get_mac[] = { 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-	get_mac[7] = dst_check_sum(get_mac, 7);
-	if (dst_command(state, get_mac, 8) < 0) {
-		dprintk(verbose, DST_INFO, 1, "Unsupported Command");
-		return -1;
-	}
-	memset(&state->mac_address, '\0', 8);
-	memcpy(&state->mac_address, &state->rxbuffer, 6);
-	dprintk(verbose, DST_ERROR, 1, "MAC Address=[%pM]", state->mac_address);
-
-	return 0;
-}
-
-static int dst_fw_ver(struct dst_state *state)
-{
-	u8 get_ver[] = { 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-	get_ver[7] = dst_check_sum(get_ver, 7);
-	if (dst_command(state, get_ver, 8) < 0) {
-		dprintk(verbose, DST_INFO, 1, "Unsupported Command");
-		return -1;
-	}
-	memcpy(&state->fw_version, &state->rxbuffer, 8);
-	dprintk(verbose, DST_ERROR, 1, "Firmware Ver = %x.%x Build = %02x, on %x:%x, %x-%x-20%02x",
-		state->fw_version[0] >> 4, state->fw_version[0] & 0x0f,
-		state->fw_version[1],
-		state->fw_version[5], state->fw_version[6],
-		state->fw_version[4], state->fw_version[3], state->fw_version[2]);
-
-	return 0;
-}
-
-static int dst_card_type(struct dst_state *state)
-{
-	int j;
-	struct tuner_types *p_tuner_list = NULL;
-
-	u8 get_type[] = { 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-	get_type[7] = dst_check_sum(get_type, 7);
-	if (dst_command(state, get_type, 8) < 0) {
-		dprintk(verbose, DST_INFO, 1, "Unsupported Command");
-		return -1;
-	}
-	memset(&state->card_info, '\0', 8);
-	memcpy(&state->card_info, &state->rxbuffer, 7);
-	dprintk(verbose, DST_ERROR, 1, "Device Model=[%s]", &state->card_info[0]);
-
-	for (j = 0, p_tuner_list = tuner_list; j < ARRAY_SIZE(tuner_list); j++, p_tuner_list++) {
-		if (!strcmp(&state->card_info[0], p_tuner_list->board_name)) {
-			state->tuner_type = p_tuner_list->tuner_type;
-			dprintk(verbose, DST_ERROR, 1, "DST has [%s] tuner, tuner type=[%d]",
-				p_tuner_list->tuner_name, p_tuner_list->tuner_type);
-		}
-	}
-
-	return 0;
-}
-
-static int dst_get_vendor(struct dst_state *state)
-{
-	u8 get_vendor[] = { 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-	get_vendor[7] = dst_check_sum(get_vendor, 7);
-	if (dst_command(state, get_vendor, 8) < 0) {
-		dprintk(verbose, DST_INFO, 1, "Unsupported Command");
-		return -1;
-	}
-	memset(&state->vendor, '\0', 8);
-	memcpy(&state->vendor, &state->rxbuffer, 7);
-	dprintk(verbose, DST_ERROR, 1, "Vendor=[%s]", &state->vendor[0]);
-
-	return 0;
-}
-
-static void debug_dst_buffer(struct dst_state *state)
-{
-	int i;
-
-	if (verbose > 2) {
-		printk("%s: [", __func__);
-		for (i = 0; i < 8; i++)
-			printk(" %02x", state->rxbuffer[i]);
-		printk("]\n");
-	}
-}
-
-static int dst_check_stv0299(struct dst_state *state)
-{
-	u8 check_stv0299[] = { 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-
-	check_stv0299[7] = dst_check_sum(check_stv0299, 7);
-	if (dst_command(state, check_stv0299, 8) < 0) {
-		dprintk(verbose, DST_ERROR, 1, "Cmd=[0x04] failed");
-		return -1;
-	}
-	debug_dst_buffer(state);
-
-	if (memcmp(&check_stv0299, &state->rxbuffer, 8)) {
-		dprintk(verbose, DST_ERROR, 1, "Found a STV0299 NIM");
-		state->tuner_type = TUNER_TYPE_STV0299;
-		return 0;
-	}
-
-	return -1;
-}
-
-static int dst_check_mb86a15(struct dst_state *state)
-{
-	u8 check_mb86a15[] = { 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-
-	check_mb86a15[7] = dst_check_sum(check_mb86a15, 7);
-	if (dst_command(state, check_mb86a15, 8) < 0) {
-		dprintk(verbose, DST_ERROR, 1, "Cmd=[0x10], failed");
-		return -1;
-	}
-	debug_dst_buffer(state);
-
-	if (memcmp(&check_mb86a15, &state->rxbuffer, 8) < 0) {
-		dprintk(verbose, DST_ERROR, 1, "Found a MB86A15 NIM");
-		state->tuner_type = TUNER_TYPE_MB86A15;
-		return 0;
-	}
-
-	return -1;
-}
-
-static int dst_get_tuner_info(struct dst_state *state)
-{
-	u8 get_tuner_1[] = { 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-	u8 get_tuner_2[] = { 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-
-	get_tuner_1[7] = dst_check_sum(get_tuner_1, 7);
-	get_tuner_2[7] = dst_check_sum(get_tuner_2, 7);
-	dprintk(verbose, DST_ERROR, 1, "DST TYpe = MULTI FE");
-	if (state->type_flags & DST_TYPE_HAS_MULTI_FE) {
-		if (dst_command(state, get_tuner_1, 8) < 0) {
-			dprintk(verbose, DST_INFO, 1, "Cmd=[0x13], Unsupported");
-			goto force;
-		}
-	} else {
-		if (dst_command(state, get_tuner_2, 8) < 0) {
-			dprintk(verbose, DST_INFO, 1, "Cmd=[0xb], Unsupported");
-			goto force;
-		}
-	}
-	memcpy(&state->board_info, &state->rxbuffer, 8);
-	if (state->type_flags & DST_TYPE_HAS_MULTI_FE) {
-		dprintk(verbose, DST_ERROR, 1, "DST type has TS=188");
-	}
-	if (state->board_info[0] == 0xbc) {
-		if (state->dst_type != DST_TYPE_IS_ATSC)
-			state->type_flags |= DST_TYPE_HAS_TS188;
-		else
-			state->type_flags |= DST_TYPE_HAS_NEWTUNE_2;
-
-		if (state->board_info[1] == 0x01) {
-			state->dst_hw_cap |= DST_TYPE_HAS_DBOARD;
-			dprintk(verbose, DST_ERROR, 1, "DST has Daughterboard");
-		}
-	}
-
-	return 0;
-force:
-	if (!strncmp(state->fw_name, "DCT-CI", 6)) {
-		state->type_flags |= DST_TYPE_HAS_TS204;
-		dprintk(verbose, DST_ERROR, 1, "Forcing [%s] to TS188", state->fw_name);
-	}
-
-	return -1;
-}
-
-static int dst_get_device_id(struct dst_state *state)
-{
-	u8 reply;
-
-	int i, j;
-	struct dst_types *p_dst_type = NULL;
-	struct tuner_types *p_tuner_list = NULL;
-
-	u8 use_dst_type = 0;
-	u32 use_type_flags = 0;
-
-	static u8 device_type[8] = {0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff};
-
-	state->tuner_type = 0;
-	device_type[7] = dst_check_sum(device_type, 7);
-
-	if (write_dst(state, device_type, FIXED_COMM))
-		return -1;		/*	Write failed		*/
-	if ((dst_pio_disable(state)) < 0)
-		return -1;
-	if (read_dst(state, &reply, GET_ACK))
-		return -1;		/*	Read failure		*/
-	if (reply != ACK) {
-		dprintk(verbose, DST_INFO, 1, "Write not Acknowledged! [Reply=0x%02x]", reply);
-		return -1;		/*	Unack'd write		*/
-	}
-	if (!dst_wait_dst_ready(state, DEVICE_INIT))
-		return -1;		/*	DST not ready yet	*/
-	if (read_dst(state, state->rxbuffer, FIXED_COMM))
-		return -1;
-
-	dst_pio_disable(state);
-	if (state->rxbuffer[7] != dst_check_sum(state->rxbuffer, 7)) {
-		dprintk(verbose, DST_INFO, 1, "Checksum failure!");
-		return -1;		/*	Checksum failure	*/
-	}
-	state->rxbuffer[7] = '\0';
-
-	for (i = 0, p_dst_type = dst_tlist; i < ARRAY_SIZE(dst_tlist); i++, p_dst_type++) {
-		if (!strncmp (&state->rxbuffer[p_dst_type->offset], p_dst_type->device_id, strlen (p_dst_type->device_id))) {
-			use_type_flags = p_dst_type->type_flags;
-			use_dst_type = p_dst_type->dst_type;
-
-			/*	Card capabilities	*/
-			state->dst_hw_cap = p_dst_type->dst_feature;
-			dprintk(verbose, DST_ERROR, 1, "Recognise [%s]", p_dst_type->device_id);
-			strncpy(&state->fw_name[0], p_dst_type->device_id, 6);
-			/*	Multiple tuners		*/
-			if (p_dst_type->tuner_type & TUNER_TYPE_MULTI) {
-				switch (use_dst_type) {
-				case DST_TYPE_IS_SAT:
-					/*	STV0299 check	*/
-					if (dst_check_stv0299(state) < 0) {
-						dprintk(verbose, DST_ERROR, 1, "Unsupported");
-						state->tuner_type = TUNER_TYPE_MB86A15;
-					}
-					break;
-				default:
-					break;
-				}
-				if (dst_check_mb86a15(state) < 0)
-					dprintk(verbose, DST_ERROR, 1, "Unsupported");
-			/*	Single tuner		*/
-			} else {
-				state->tuner_type = p_dst_type->tuner_type;
-			}
-			for (j = 0, p_tuner_list = tuner_list; j < ARRAY_SIZE(tuner_list); j++, p_tuner_list++) {
-				if (!(strncmp(p_dst_type->device_id, p_tuner_list->fw_name, 7)) &&
-					p_tuner_list->tuner_type == state->tuner_type) {
-					dprintk(verbose, DST_ERROR, 1, "[%s] has a [%s]",
-						p_dst_type->device_id, p_tuner_list->tuner_name);
-				}
-			}
-			break;
-		}
-	}
-
-	if (i >= ARRAY_SIZE(dst_tlist)) {
-		dprintk(verbose, DST_ERROR, 1, "Unable to recognize %s or %s", &state->rxbuffer[0], &state->rxbuffer[1]);
-		dprintk(verbose, DST_ERROR, 1, "please email linux-dvb@linuxtv.org with this type in");
-		use_dst_type = DST_TYPE_IS_SAT;
-		use_type_flags = DST_TYPE_HAS_SYMDIV;
-	}
-	dst_type_print(state, use_dst_type);
-	state->type_flags = use_type_flags;
-	state->dst_type = use_dst_type;
-	dst_type_flags_print(state);
-
-	return 0;
-}
-
-static int dst_probe(struct dst_state *state)
-{
-	mutex_init(&state->dst_mutex);
-	if (dst_addons & DST_TYPE_HAS_CA) {
-		if ((rdc_8820_reset(state)) < 0) {
-			dprintk(verbose, DST_ERROR, 1, "RDC 8820 RESET Failed.");
-			return -1;
-		}
-		msleep(4000);
-	} else {
-		msleep(100);
-	}
-	if ((dst_comm_init(state)) < 0) {
-		dprintk(verbose, DST_ERROR, 1, "DST Initialization Failed.");
-		return -1;
-	}
-	msleep(100);
-	if (dst_get_device_id(state) < 0) {
-		dprintk(verbose, DST_ERROR, 1, "unknown device.");
-		return -1;
-	}
-	if (dst_get_mac(state) < 0) {
-		dprintk(verbose, DST_INFO, 1, "MAC: Unsupported command");
-	}
-	if ((state->type_flags & DST_TYPE_HAS_MULTI_FE) || (state->type_flags & DST_TYPE_HAS_FW_BUILD)) {
-		if (dst_get_tuner_info(state) < 0)
-			dprintk(verbose, DST_INFO, 1, "Tuner: Unsupported command");
-	}
-	if (state->type_flags & DST_TYPE_HAS_TS204) {
-		dst_packsize(state, 204);
-	}
-	if (state->type_flags & DST_TYPE_HAS_FW_BUILD) {
-		if (dst_fw_ver(state) < 0) {
-			dprintk(verbose, DST_INFO, 1, "FW: Unsupported command");
-			return 0;
-		}
-		if (dst_card_type(state) < 0) {
-			dprintk(verbose, DST_INFO, 1, "Card: Unsupported command");
-			return 0;
-		}
-		if (dst_get_vendor(state) < 0) {
-			dprintk(verbose, DST_INFO, 1, "Vendor: Unsupported command");
-			return 0;
-		}
-	}
-
-	return 0;
-}
-
-static int dst_command(struct dst_state *state, u8 *data, u8 len)
-{
-	u8 reply;
-
-	mutex_lock(&state->dst_mutex);
-	if ((dst_comm_init(state)) < 0) {
-		dprintk(verbose, DST_NOTICE, 1, "DST Communication Initialization Failed.");
-		goto error;
-	}
-	if (write_dst(state, data, len)) {
-		dprintk(verbose, DST_INFO, 1, "Trying to recover.. ");
-		if ((dst_error_recovery(state)) < 0) {
-			dprintk(verbose, DST_ERROR, 1, "Recovery Failed.");
-			goto error;
-		}
-		goto error;
-	}
-	if ((dst_pio_disable(state)) < 0) {
-		dprintk(verbose, DST_ERROR, 1, "PIO Disable Failed.");
-		goto error;
-	}
-	if (state->type_flags & DST_TYPE_HAS_FW_1)
-		mdelay(3);
-	if (read_dst(state, &reply, GET_ACK)) {
-		dprintk(verbose, DST_DEBUG, 1, "Trying to recover.. ");
-		if ((dst_error_recovery(state)) < 0) {
-			dprintk(verbose, DST_INFO, 1, "Recovery Failed.");
-			goto error;
-		}
-		goto error;
-	}
-	if (reply != ACK) {
-		dprintk(verbose, DST_INFO, 1, "write not acknowledged 0x%02x ", reply);
-		goto error;
-	}
-	if (len >= 2 && data[0] == 0 && (data[1] == 1 || data[1] == 3))
-		goto error;
-	if (state->type_flags & DST_TYPE_HAS_FW_1)
-		mdelay(3);
-	else
-		udelay(2000);
-	if (!dst_wait_dst_ready(state, NO_DELAY))
-		goto error;
-	if (read_dst(state, state->rxbuffer, FIXED_COMM)) {
-		dprintk(verbose, DST_DEBUG, 1, "Trying to recover.. ");
-		if ((dst_error_recovery(state)) < 0) {
-			dprintk(verbose, DST_INFO, 1, "Recovery failed.");
-			goto error;
-		}
-		goto error;
-	}
-	if (state->rxbuffer[7] != dst_check_sum(state->rxbuffer, 7)) {
-		dprintk(verbose, DST_INFO, 1, "checksum failure");
-		goto error;
-	}
-	mutex_unlock(&state->dst_mutex);
-	return 0;
-
-error:
-	mutex_unlock(&state->dst_mutex);
-	return -EIO;
-
-}
-
-static int dst_get_signal(struct dst_state *state)
-{
-	int retval;
-	u8 get_signal[] = { 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb };
-	//dprintk("%s: Getting Signal strength and other parameters\n", __func__);
-	if ((state->diseq_flags & ATTEMPT_TUNE) == 0) {
-		state->decode_lock = state->decode_strength = state->decode_snr = 0;
-		return 0;
-	}
-	if (0 == (state->diseq_flags & HAS_LOCK)) {
-		state->decode_lock = state->decode_strength = state->decode_snr = 0;
-		return 0;
-	}
-	if (time_after_eq(jiffies, state->cur_jiff + (HZ / 5))) {
-		retval = dst_command(state, get_signal, 8);
-		if (retval < 0)
-			return retval;
-		if (state->dst_type == DST_TYPE_IS_SAT) {
-			state->decode_lock = ((state->rxbuffer[6] & 0x10) == 0) ? 1 : 0;
-			state->decode_strength = state->rxbuffer[5] << 8;
-			state->decode_snr = state->rxbuffer[2] << 8 | state->rxbuffer[3];
-		} else if ((state->dst_type == DST_TYPE_IS_TERR) || (state->dst_type == DST_TYPE_IS_CABLE)) {
-			state->decode_lock = (state->rxbuffer[1]) ? 1 : 0;
-			state->decode_strength = state->rxbuffer[4] << 8;
-			state->decode_snr = state->rxbuffer[3] << 8;
-		} else if (state->dst_type == DST_TYPE_IS_ATSC) {
-			state->decode_lock = (state->rxbuffer[6] == 0x00) ? 1 : 0;
-			state->decode_strength = state->rxbuffer[4] << 8;
-			state->decode_snr = state->rxbuffer[2] << 8 | state->rxbuffer[3];
-		}
-		state->cur_jiff = jiffies;
-	}
-	return 0;
-}
-
-static int dst_tone_power_cmd(struct dst_state *state)
-{
-	u8 paket[8] = { 0x00, 0x09, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00 };
-
-	if (state->dst_type != DST_TYPE_IS_SAT)
-		return -EOPNOTSUPP;
-	paket[4] = state->tx_tuna[4];
-	paket[2] = state->tx_tuna[2];
-	paket[3] = state->tx_tuna[3];
-	paket[7] = dst_check_sum (paket, 7);
-	return dst_command(state, paket, 8);
-}
-
-static int dst_get_tuna(struct dst_state *state)
-{
-	int retval;
-
-	if ((state->diseq_flags & ATTEMPT_TUNE) == 0)
-		return 0;
-	state->diseq_flags &= ~(HAS_LOCK);
-	if (!dst_wait_dst_ready(state, NO_DELAY))
-		return -EIO;
-	if ((state->type_flags & DST_TYPE_HAS_VLF) &&
-		!(state->dst_type == DST_TYPE_IS_ATSC))
-
-		retval = read_dst(state, state->rx_tuna, 10);
-	else
-		retval = read_dst(state, &state->rx_tuna[2], FIXED_COMM);
-	if (retval < 0) {
-		dprintk(verbose, DST_DEBUG, 1, "read not successful");
-		return retval;
-	}
-	if ((state->type_flags & DST_TYPE_HAS_VLF) &&
-	   !(state->dst_type == DST_TYPE_IS_ATSC)) {
-
-		if (state->rx_tuna[9] != dst_check_sum(&state->rx_tuna[0], 9)) {
-			dprintk(verbose, DST_INFO, 1, "checksum failure ? ");
-			return -EIO;
-		}
-	} else {
-		if (state->rx_tuna[9] != dst_check_sum(&state->rx_tuna[2], 7)) {
-			dprintk(verbose, DST_INFO, 1, "checksum failure? ");
-			return -EIO;
-		}
-	}
-	if (state->rx_tuna[2] == 0 && state->rx_tuna[3] == 0)
-		return 0;
-	if (state->dst_type == DST_TYPE_IS_SAT) {
-		state->decode_freq = ((state->rx_tuna[2] & 0x7f) << 8) + state->rx_tuna[3];
-	} else {
-		state->decode_freq = ((state->rx_tuna[2] & 0x7f) << 16) + (state->rx_tuna[3] << 8) + state->rx_tuna[4];
-	}
-	state->decode_freq = state->decode_freq * 1000;
-	state->decode_lock = 1;
-	state->diseq_flags |= HAS_LOCK;
-
-	return 1;
-}
-
-static int dst_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage);
-
-static int dst_write_tuna(struct dvb_frontend *fe)
-{
-	struct dst_state *state = fe->demodulator_priv;
-	int retval;
-	u8 reply;
-
-	dprintk(verbose, DST_INFO, 1, "type_flags 0x%x ", state->type_flags);
-	state->decode_freq = 0;
-	state->decode_lock = state->decode_strength = state->decode_snr = 0;
-	if (state->dst_type == DST_TYPE_IS_SAT) {
-		if (!(state->diseq_flags & HAS_POWER))
-			dst_set_voltage(fe, SEC_VOLTAGE_13);
-	}
-	state->diseq_flags &= ~(HAS_LOCK | ATTEMPT_TUNE);
-	mutex_lock(&state->dst_mutex);
-	if ((dst_comm_init(state)) < 0) {
-		dprintk(verbose, DST_DEBUG, 1, "DST Communication initialization failed.");
-		goto error;
-	}
-//	if (state->type_flags & DST_TYPE_HAS_NEWTUNE) {
-	if ((state->type_flags & DST_TYPE_HAS_VLF) &&
-		(!(state->dst_type == DST_TYPE_IS_ATSC))) {
-
-		state->tx_tuna[9] = dst_check_sum(&state->tx_tuna[0], 9);
-		retval = write_dst(state, &state->tx_tuna[0], 10);
-	} else {
-		state->tx_tuna[9] = dst_check_sum(&state->tx_tuna[2], 7);
-		retval = write_dst(state, &state->tx_tuna[2], FIXED_COMM);
-	}
-	if (retval < 0) {
-		dst_pio_disable(state);
-		dprintk(verbose, DST_DEBUG, 1, "write not successful");
-		goto werr;
-	}
-	if ((dst_pio_disable(state)) < 0) {
-		dprintk(verbose, DST_DEBUG, 1, "DST PIO disable failed !");
-		goto error;
-	}
-	if ((read_dst(state, &reply, GET_ACK) < 0)) {
-		dprintk(verbose, DST_DEBUG, 1, "read verify not successful.");
-		goto error;
-	}
-	if (reply != ACK) {
-		dprintk(verbose, DST_DEBUG, 1, "write not acknowledged 0x%02x ", reply);
-		goto error;
-	}
-	state->diseq_flags |= ATTEMPT_TUNE;
-	retval = dst_get_tuna(state);
-werr:
-	mutex_unlock(&state->dst_mutex);
-	return retval;
-
-error:
-	mutex_unlock(&state->dst_mutex);
-	return -EIO;
-}
-
-/*
- * line22k0    0x00, 0x09, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00
- * line22k1    0x00, 0x09, 0x01, 0xff, 0x01, 0x00, 0x00, 0x00
- * line22k2    0x00, 0x09, 0x02, 0xff, 0x01, 0x00, 0x00, 0x00
- * tone        0x00, 0x09, 0xff, 0x00, 0x01, 0x00, 0x00, 0x00
- * data        0x00, 0x09, 0xff, 0x01, 0x01, 0x00, 0x00, 0x00
- * power_off   0x00, 0x09, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00
- * power_on    0x00, 0x09, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00
- * Diseqc 1    0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf0, 0xec
- * Diseqc 2    0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf4, 0xe8
- * Diseqc 3    0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf8, 0xe4
- * Diseqc 4    0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xfc, 0xe0
- */
-
-static int dst_set_diseqc(struct dvb_frontend *fe, struct dvb_diseqc_master_cmd *cmd)
-{
-	struct dst_state *state = fe->demodulator_priv;
-	u8 paket[8] = { 0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf0, 0xec };
-
-	if (state->dst_type != DST_TYPE_IS_SAT)
-		return -EOPNOTSUPP;
-	if (cmd->msg_len > 0 && cmd->msg_len < 5)
-		memcpy(&paket[3], cmd->msg, cmd->msg_len);
-	else if (cmd->msg_len == 5 && state->dst_hw_cap & DST_TYPE_HAS_DISEQC5)
-		memcpy(&paket[2], cmd->msg, cmd->msg_len);
-	else
-		return -EINVAL;
-	paket[7] = dst_check_sum(&paket[0], 7);
-	return dst_command(state, paket, 8);
-}
-
-static int dst_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
-{
-	int need_cmd, retval = 0;
-	struct dst_state *state = fe->demodulator_priv;
-
-	state->voltage = voltage;
-	if (state->dst_type != DST_TYPE_IS_SAT)
-		return -EOPNOTSUPP;
-
-	need_cmd = 0;
-
-	switch (voltage) {
-	case SEC_VOLTAGE_13:
-	case SEC_VOLTAGE_18:
-		if ((state->diseq_flags & HAS_POWER) == 0)
-			need_cmd = 1;
-		state->diseq_flags |= HAS_POWER;
-		state->tx_tuna[4] = 0x01;
-		break;
-	case SEC_VOLTAGE_OFF:
-		need_cmd = 1;
-		state->diseq_flags &= ~(HAS_POWER | HAS_LOCK | ATTEMPT_TUNE);
-		state->tx_tuna[4] = 0x00;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	if (need_cmd)
-		retval = dst_tone_power_cmd(state);
-
-	return retval;
-}
-
-static int dst_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
-{
-	struct dst_state *state = fe->demodulator_priv;
-
-	state->tone = tone;
-	if (state->dst_type != DST_TYPE_IS_SAT)
-		return -EOPNOTSUPP;
-
-	switch (tone) {
-	case SEC_TONE_OFF:
-		if (state->type_flags & DST_TYPE_HAS_OBS_REGS)
-		    state->tx_tuna[2] = 0x00;
-		else
-		    state->tx_tuna[2] = 0xff;
-		break;
-
-	case SEC_TONE_ON:
-		state->tx_tuna[2] = 0x02;
-		break;
-	default:
-		return -EINVAL;
-	}
-	return dst_tone_power_cmd(state);
-}
-
-static int dst_send_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t minicmd)
-{
-	struct dst_state *state = fe->demodulator_priv;
-
-	if (state->dst_type != DST_TYPE_IS_SAT)
-		return -EOPNOTSUPP;
-	state->minicmd = minicmd;
-	switch (minicmd) {
-	case SEC_MINI_A:
-		state->tx_tuna[3] = 0x02;
-		break;
-	case SEC_MINI_B:
-		state->tx_tuna[3] = 0xff;
-		break;
-	}
-	return dst_tone_power_cmd(state);
-}
-
-
-static int dst_init(struct dvb_frontend *fe)
-{
-	struct dst_state *state = fe->demodulator_priv;
-
-	static u8 sat_tuna_188[] = { 0x09, 0x00, 0x03, 0xb6, 0x01, 0x00, 0x73, 0x21, 0x00, 0x00 };
-	static u8 sat_tuna_204[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x55, 0xbd, 0x50, 0x00, 0x00 };
-	static u8 ter_tuna_188[] = { 0x09, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
-	static u8 ter_tuna_204[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
-	static u8 cab_tuna_188[] = { 0x09, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
-	static u8 cab_tuna_204[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
-	static u8 atsc_tuner[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
-
-	state->inversion = INVERSION_OFF;
-	state->voltage = SEC_VOLTAGE_13;
-	state->tone = SEC_TONE_OFF;
-	state->diseq_flags = 0;
-	state->k22 = 0x02;
-	state->bandwidth = 7000000;
-	state->cur_jiff = jiffies;
-	if (state->dst_type == DST_TYPE_IS_SAT)
-		memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_VLF) ? sat_tuna_188 : sat_tuna_204), sizeof (sat_tuna_204));
-	else if (state->dst_type == DST_TYPE_IS_TERR)
-		memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_VLF) ? ter_tuna_188 : ter_tuna_204), sizeof (ter_tuna_204));
-	else if (state->dst_type == DST_TYPE_IS_CABLE)
-		memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_VLF) ? cab_tuna_188 : cab_tuna_204), sizeof (cab_tuna_204));
-	else if (state->dst_type == DST_TYPE_IS_ATSC)
-		memcpy(state->tx_tuna, atsc_tuner, sizeof (atsc_tuner));
-
-	return 0;
-}
-
-static int dst_read_status(struct dvb_frontend *fe, fe_status_t *status)
-{
-	struct dst_state *state = fe->demodulator_priv;
-
-	*status = 0;
-	if (state->diseq_flags & HAS_LOCK) {
-//		dst_get_signal(state);	// don't require(?) to ask MCU
-		if (state->decode_lock)
-			*status |= FE_HAS_LOCK | FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_SYNC | FE_HAS_VITERBI;
-	}
-
-	return 0;
-}
-
-static int dst_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
-{
-	struct dst_state *state = fe->demodulator_priv;
-
-	int retval = dst_get_signal(state);
-	*strength = state->decode_strength;
-
-	return retval;
-}
-
-static int dst_read_snr(struct dvb_frontend *fe, u16 *snr)
-{
-	struct dst_state *state = fe->demodulator_priv;
-
-	int retval = dst_get_signal(state);
-	*snr = state->decode_snr;
-
-	return retval;
-}
-
-static int dst_set_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	int retval = -EINVAL;
-	struct dst_state *state = fe->demodulator_priv;
-
-	if (p != NULL) {
-		retval = dst_set_freq(state, p->frequency);
-		if(retval != 0)
-			return retval;
-		dprintk(verbose, DST_DEBUG, 1, "Set Frequency=[%d]", p->frequency);
-
-		if (state->dst_type == DST_TYPE_IS_SAT) {
-			if (state->type_flags & DST_TYPE_HAS_OBS_REGS)
-				dst_set_inversion(state, p->inversion);
-			dst_set_fec(state, p->fec_inner);
-			dst_set_symbolrate(state, p->symbol_rate);
-			dst_set_polarization(state);
-			dprintk(verbose, DST_DEBUG, 1, "Set Symbolrate=[%d]", p->symbol_rate);
-
-		} else if (state->dst_type == DST_TYPE_IS_TERR)
-			dst_set_bandwidth(state, p->bandwidth_hz);
-		else if (state->dst_type == DST_TYPE_IS_CABLE) {
-			dst_set_fec(state, p->fec_inner);
-			dst_set_symbolrate(state, p->symbol_rate);
-			dst_set_modulation(state, p->modulation);
-		}
-		retval = dst_write_tuna(fe);
-	}
-
-	return retval;
-}
-
-static int dst_tune_frontend(struct dvb_frontend* fe,
-			    bool re_tune,
-			    unsigned int mode_flags,
-			    unsigned int *delay,
-			    fe_status_t *status)
-{
-	struct dst_state *state = fe->demodulator_priv;
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-
-	if (re_tune) {
-		dst_set_freq(state, p->frequency);
-		dprintk(verbose, DST_DEBUG, 1, "Set Frequency=[%d]", p->frequency);
-
-		if (state->dst_type == DST_TYPE_IS_SAT) {
-			if (state->type_flags & DST_TYPE_HAS_OBS_REGS)
-				dst_set_inversion(state, p->inversion);
-			dst_set_fec(state, p->fec_inner);
-			dst_set_symbolrate(state, p->symbol_rate);
-			dst_set_polarization(state);
-			dprintk(verbose, DST_DEBUG, 1, "Set Symbolrate=[%d]", p->symbol_rate);
-
-		} else if (state->dst_type == DST_TYPE_IS_TERR)
-			dst_set_bandwidth(state, p->bandwidth_hz);
-		else if (state->dst_type == DST_TYPE_IS_CABLE) {
-			dst_set_fec(state, p->fec_inner);
-			dst_set_symbolrate(state, p->symbol_rate);
-			dst_set_modulation(state, p->modulation);
-		}
-		dst_write_tuna(fe);
-	}
-
-	if (!(mode_flags & FE_TUNE_MODE_ONESHOT))
-		dst_read_status(fe, status);
-
-	*delay = HZ/10;
-	return 0;
-}
-
-static int dst_get_tuning_algo(struct dvb_frontend *fe)
-{
-	return dst_algo ? DVBFE_ALGO_HW : DVBFE_ALGO_SW;
-}
-
-static int dst_get_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct dst_state *state = fe->demodulator_priv;
-
-	p->frequency = state->decode_freq;
-	if (state->dst_type == DST_TYPE_IS_SAT) {
-		if (state->type_flags & DST_TYPE_HAS_OBS_REGS)
-			p->inversion = state->inversion;
-		p->symbol_rate = state->symbol_rate;
-		p->fec_inner = dst_get_fec(state);
-	} else if (state->dst_type == DST_TYPE_IS_TERR) {
-		p->bandwidth_hz = state->bandwidth;
-	} else if (state->dst_type == DST_TYPE_IS_CABLE) {
-		p->symbol_rate = state->symbol_rate;
-		p->fec_inner = dst_get_fec(state);
-		p->modulation = dst_get_modulation(state);
-	}
-
-	return 0;
-}
-
-static void dst_release(struct dvb_frontend *fe)
-{
-	struct dst_state *state = fe->demodulator_priv;
-	if (state->dst_ca) {
-		dvb_unregister_device(state->dst_ca);
-#ifdef CONFIG_MEDIA_ATTACH
-		symbol_put(dst_ca_attach);
-#endif
-	}
-	kfree(state);
-}
-
-static struct dvb_frontend_ops dst_dvbt_ops;
-static struct dvb_frontend_ops dst_dvbs_ops;
-static struct dvb_frontend_ops dst_dvbc_ops;
-static struct dvb_frontend_ops dst_atsc_ops;
-
-struct dst_state *dst_attach(struct dst_state *state, struct dvb_adapter *dvb_adapter)
-{
-	/* check if the ASIC is there */
-	if (dst_probe(state) < 0) {
-		kfree(state);
-		return NULL;
-	}
-	/* determine settings based on type */
-	/* create dvb_frontend */
-	switch (state->dst_type) {
-	case DST_TYPE_IS_TERR:
-		memcpy(&state->frontend.ops, &dst_dvbt_ops, sizeof(struct dvb_frontend_ops));
-		break;
-	case DST_TYPE_IS_CABLE:
-		memcpy(&state->frontend.ops, &dst_dvbc_ops, sizeof(struct dvb_frontend_ops));
-		break;
-	case DST_TYPE_IS_SAT:
-		memcpy(&state->frontend.ops, &dst_dvbs_ops, sizeof(struct dvb_frontend_ops));
-		break;
-	case DST_TYPE_IS_ATSC:
-		memcpy(&state->frontend.ops, &dst_atsc_ops, sizeof(struct dvb_frontend_ops));
-		break;
-	default:
-		dprintk(verbose, DST_ERROR, 1, "unknown DST type. please report to the LinuxTV.org DVB mailinglist.");
-		kfree(state);
-		return NULL;
-	}
-	state->frontend.demodulator_priv = state;
-
-	return state;				/*	Manu (DST is a card not a frontend)	*/
-}
-
-EXPORT_SYMBOL(dst_attach);
-
-static struct dvb_frontend_ops dst_dvbt_ops = {
-	.delsys = { SYS_DVBT },
-	.info = {
-		.name = "DST DVB-T",
-		.frequency_min = 137000000,
-		.frequency_max = 858000000,
-		.frequency_stepsize = 166667,
-		.caps = FE_CAN_FEC_AUTO			|
-			FE_CAN_QAM_AUTO			|
-			FE_CAN_QAM_16			|
-			FE_CAN_QAM_32			|
-			FE_CAN_QAM_64			|
-			FE_CAN_QAM_128			|
-			FE_CAN_QAM_256			|
-			FE_CAN_TRANSMISSION_MODE_AUTO	|
-			FE_CAN_GUARD_INTERVAL_AUTO
-	},
-
-	.release = dst_release,
-	.init = dst_init,
-	.tune = dst_tune_frontend,
-	.set_frontend = dst_set_frontend,
-	.get_frontend = dst_get_frontend,
-	.get_frontend_algo = dst_get_tuning_algo,
-	.read_status = dst_read_status,
-	.read_signal_strength = dst_read_signal_strength,
-	.read_snr = dst_read_snr,
-};
-
-static struct dvb_frontend_ops dst_dvbs_ops = {
-	.delsys = { SYS_DVBS },
-	.info = {
-		.name = "DST DVB-S",
-		.frequency_min = 950000,
-		.frequency_max = 2150000,
-		.frequency_stepsize = 1000,	/* kHz for QPSK frontends */
-		.frequency_tolerance = 29500,
-		.symbol_rate_min = 1000000,
-		.symbol_rate_max = 45000000,
-	/*     . symbol_rate_tolerance	=	???,*/
-		.caps = FE_CAN_FEC_AUTO | FE_CAN_QPSK
-	},
-
-	.release = dst_release,
-	.init = dst_init,
-	.tune = dst_tune_frontend,
-	.set_frontend = dst_set_frontend,
-	.get_frontend = dst_get_frontend,
-	.get_frontend_algo = dst_get_tuning_algo,
-	.read_status = dst_read_status,
-	.read_signal_strength = dst_read_signal_strength,
-	.read_snr = dst_read_snr,
-	.diseqc_send_burst = dst_send_burst,
-	.diseqc_send_master_cmd = dst_set_diseqc,
-	.set_voltage = dst_set_voltage,
-	.set_tone = dst_set_tone,
-};
-
-static struct dvb_frontend_ops dst_dvbc_ops = {
-	.delsys = { SYS_DVBC_ANNEX_A },
-	.info = {
-		.name = "DST DVB-C",
-		.frequency_stepsize = 62500,
-		.frequency_min = 51000000,
-		.frequency_max = 858000000,
-		.symbol_rate_min = 1000000,
-		.symbol_rate_max = 45000000,
-		.caps = FE_CAN_FEC_AUTO |
-			FE_CAN_QAM_AUTO |
-			FE_CAN_QAM_16	|
-			FE_CAN_QAM_32	|
-			FE_CAN_QAM_64	|
-			FE_CAN_QAM_128	|
-			FE_CAN_QAM_256
-	},
-
-	.release = dst_release,
-	.init = dst_init,
-	.tune = dst_tune_frontend,
-	.set_frontend = dst_set_frontend,
-	.get_frontend = dst_get_frontend,
-	.get_frontend_algo = dst_get_tuning_algo,
-	.read_status = dst_read_status,
-	.read_signal_strength = dst_read_signal_strength,
-	.read_snr = dst_read_snr,
-};
-
-static struct dvb_frontend_ops dst_atsc_ops = {
-	.delsys = { SYS_ATSC },
-	.info = {
-		.name = "DST ATSC",
-		.frequency_stepsize = 62500,
-		.frequency_min = 510000000,
-		.frequency_max = 858000000,
-		.symbol_rate_min = 1000000,
-		.symbol_rate_max = 45000000,
-		.caps = FE_CAN_FEC_AUTO | FE_CAN_QAM_AUTO | FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
-	},
-
-	.release = dst_release,
-	.init = dst_init,
-	.tune = dst_tune_frontend,
-	.set_frontend = dst_set_frontend,
-	.get_frontend = dst_get_frontend,
-	.get_frontend_algo = dst_get_tuning_algo,
-	.read_status = dst_read_status,
-	.read_signal_strength = dst_read_signal_strength,
-	.read_snr = dst_read_snr,
-};
-
-MODULE_DESCRIPTION("DST DVB-S/T/C/ATSC Combo Frontend driver");
-MODULE_AUTHOR("Jamie Honan, Manu Abraham");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/bt8xx/dst_ca.c b/drivers/media/dvb/bt8xx/dst_ca.c
deleted file mode 100644
index 66f52f1..0000000
--- a/drivers/media/dvb/bt8xx/dst_ca.c
+++ /dev/null
@@ -1,725 +0,0 @@
-/*
-	CA-driver for TwinHan DST Frontend/Card
-
-	Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.com)
-
-	This program is free software; you can redistribute it and/or modify
-	it under the terms of the GNU General Public License as published by
-	the Free Software Foundation; either version 2 of the License, or
-	(at your option) any later version.
-
-	This program is distributed in the hope that it will be useful,
-	but WITHOUT ANY WARRANTY; without even the implied warranty of
-	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	GNU General Public License for more details.
-
-	You should have received a copy of the GNU General Public License
-	along with this program; if not, write to the Free Software
-	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/mutex.h>
-#include <linux/string.h>
-#include <linux/dvb/ca.h>
-#include "dvbdev.h"
-#include "dvb_frontend.h"
-#include "dst_ca.h"
-#include "dst_common.h"
-
-#define DST_CA_ERROR		0
-#define DST_CA_NOTICE		1
-#define DST_CA_INFO		2
-#define DST_CA_DEBUG		3
-
-#define dprintk(x, y, z, format, arg...) do {						\
-	if (z) {									\
-		if	((x > DST_CA_ERROR) && (x > y))					\
-			printk(KERN_ERR "%s: " format "\n", __func__ , ##arg);	\
-		else if	((x > DST_CA_NOTICE) && (x > y))				\
-			printk(KERN_NOTICE "%s: " format "\n", __func__ , ##arg);	\
-		else if ((x > DST_CA_INFO) && (x > y))					\
-			printk(KERN_INFO "%s: " format "\n", __func__ , ##arg);	\
-		else if ((x > DST_CA_DEBUG) && (x > y))					\
-			printk(KERN_DEBUG "%s: " format "\n", __func__ , ##arg);	\
-	} else {									\
-		if (x > y)								\
-			printk(format, ## arg);						\
-	}										\
-} while(0)
-
-
-static DEFINE_MUTEX(dst_ca_mutex);
-static unsigned int verbose = 5;
-module_param(verbose, int, 0644);
-MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)");
-
-/*	Need some more work	*/
-static int ca_set_slot_descr(void)
-{
-	/*	We could make this more graceful ?	*/
-	return -EOPNOTSUPP;
-}
-
-/*	Need some more work	*/
-static int ca_set_pid(void)
-{
-	/*	We could make this more graceful ?	*/
-	return -EOPNOTSUPP;
-}
-
-static void put_command_and_length(u8 *data, int command, int length)
-{
-	data[0] = (command >> 16) & 0xff;
-	data[1] = (command >> 8) & 0xff;
-	data[2] = command & 0xff;
-	data[3] = length;
-}
-
-static void put_checksum(u8 *check_string, int length)
-{
-	dprintk(verbose, DST_CA_DEBUG, 1, " Computing string checksum.");
-	dprintk(verbose, DST_CA_DEBUG, 1, "  -> string length : 0x%02x", length);
-	check_string[length] = dst_check_sum (check_string, length);
-	dprintk(verbose, DST_CA_DEBUG, 1, "  -> checksum      : 0x%02x", check_string[length]);
-}
-
-static int dst_ci_command(struct dst_state* state, u8 * data, u8 *ca_string, u8 len, int read)
-{
-	u8 reply;
-
-	mutex_lock(&state->dst_mutex);
-	dst_comm_init(state);
-	msleep(65);
-
-	if (write_dst(state, data, len)) {
-		dprintk(verbose, DST_CA_INFO, 1, " Write not successful, trying to recover");
-		dst_error_recovery(state);
-		goto error;
-	}
-	if ((dst_pio_disable(state)) < 0) {
-		dprintk(verbose, DST_CA_ERROR, 1, " DST PIO disable failed.");
-		goto error;
-	}
-	if (read_dst(state, &reply, GET_ACK) < 0) {
-		dprintk(verbose, DST_CA_INFO, 1, " Read not successful, trying to recover");
-		dst_error_recovery(state);
-		goto error;
-	}
-	if (read) {
-		if (! dst_wait_dst_ready(state, LONG_DELAY)) {
-			dprintk(verbose, DST_CA_NOTICE, 1, " 8820 not ready");
-			goto error;
-		}
-		if (read_dst(state, ca_string, 128) < 0) {	/*	Try to make this dynamic	*/
-			dprintk(verbose, DST_CA_INFO, 1, " Read not successful, trying to recover");
-			dst_error_recovery(state);
-			goto error;
-		}
-	}
-	mutex_unlock(&state->dst_mutex);
-	return 0;
-
-error:
-	mutex_unlock(&state->dst_mutex);
-	return -EIO;
-}
-
-
-static int dst_put_ci(struct dst_state *state, u8 *data, int len, u8 *ca_string, int read)
-{
-	u8 dst_ca_comm_err = 0;
-
-	while (dst_ca_comm_err < RETRIES) {
-		dprintk(verbose, DST_CA_NOTICE, 1, " Put Command");
-		if (dst_ci_command(state, data, ca_string, len, read)) {	// If error
-			dst_error_recovery(state);
-			dst_ca_comm_err++; // work required here.
-		} else {
-			break;
-		}
-	}
-
-	if(dst_ca_comm_err == RETRIES)
-		return -1;
-
-	return 0;
-}
-
-
-
-static int ca_get_app_info(struct dst_state *state)
-{
-	int length, str_length;
-	static u8 command[8] = {0x07, 0x40, 0x01, 0x00, 0x01, 0x00, 0x00, 0xff};
-
-	put_checksum(&command[0], command[0]);
-	if ((dst_put_ci(state, command, sizeof(command), state->messages, GET_REPLY)) < 0) {
-		dprintk(verbose, DST_CA_ERROR, 1, " -->dst_put_ci FAILED !");
-		return -1;
-	}
-	dprintk(verbose, DST_CA_INFO, 1, " -->dst_put_ci SUCCESS !");
-	dprintk(verbose, DST_CA_INFO, 1, " ================================ CI Module Application Info ======================================");
-	dprintk(verbose, DST_CA_INFO, 1, " Application Type=[%d], Application Vendor=[%d], Vendor Code=[%d]\n%s: Application info=[%s]",
-		state->messages[7], (state->messages[8] << 8) | state->messages[9],
-		(state->messages[10] << 8) | state->messages[11], __func__, (char *)(&state->messages[12]));
-	dprintk(verbose, DST_CA_INFO, 1, " ==================================================================================================");
-
-	// Transform dst message to correct application_info message
-	length = state->messages[5];
-	str_length = length - 6;
-	if (str_length < 0) {
-		str_length = 0;
-		dprintk(verbose, DST_CA_ERROR, 1, "Invalid string length returned in ca_get_app_info(). Recovering.");
-	}
-
-	// First, the command and length fields
-	put_command_and_length(&state->messages[0], CA_APP_INFO, length);
-
-	// Copy application_type, application_manufacturer and manufacturer_code
-	memcpy(&state->messages[4], &state->messages[7], 5);
-
-	// Set string length and copy string
-	state->messages[9] = str_length;
-	memcpy(&state->messages[10], &state->messages[12], str_length);
-
-	return 0;
-}
-
-static int ca_get_ca_info(struct dst_state *state)
-{
-	int srcPtr, dstPtr, i, num_ids;
-	static u8 slot_command[8] = {0x07, 0x40, 0x00, 0x00, 0x02, 0x00, 0x00, 0xff};
-	const int in_system_id_pos = 8, out_system_id_pos = 4, in_num_ids_pos = 7;
-
-	put_checksum(&slot_command[0], slot_command[0]);
-	if ((dst_put_ci(state, slot_command, sizeof (slot_command), state->messages, GET_REPLY)) < 0) {
-		dprintk(verbose, DST_CA_ERROR, 1, " -->dst_put_ci FAILED !");
-		return -1;
-	}
-	dprintk(verbose, DST_CA_INFO, 1, " -->dst_put_ci SUCCESS !");
-
-	// Print raw data
-	dprintk(verbose, DST_CA_INFO, 0, " DST data = [");
-	for (i = 0; i < state->messages[0] + 1; i++) {
-		dprintk(verbose, DST_CA_INFO, 0, " 0x%02x", state->messages[i]);
-	}
-	dprintk(verbose, DST_CA_INFO, 0, "]\n");
-
-	// Set the command and length of the output
-	num_ids = state->messages[in_num_ids_pos];
-	if (num_ids >= 100) {
-		num_ids = 100;
-		dprintk(verbose, DST_CA_ERROR, 1, "Invalid number of ids (>100). Recovering.");
-	}
-	put_command_and_length(&state->messages[0], CA_INFO, num_ids * 2);
-
-	dprintk(verbose, DST_CA_INFO, 0, " CA_INFO = [");
-	srcPtr = in_system_id_pos;
-	dstPtr = out_system_id_pos;
-	for(i = 0; i < num_ids; i++) {
-		dprintk(verbose, DST_CA_INFO, 0, " 0x%02x%02x", state->messages[srcPtr + 0], state->messages[srcPtr + 1]);
-		// Append to output
-		state->messages[dstPtr + 0] = state->messages[srcPtr + 0];
-		state->messages[dstPtr + 1] = state->messages[srcPtr + 1];
-		srcPtr += 2;
-		dstPtr += 2;
-	}
-	dprintk(verbose, DST_CA_INFO, 0, "]\n");
-
-	return 0;
-}
-
-static int ca_get_slot_caps(struct dst_state *state, struct ca_caps *p_ca_caps, void __user *arg)
-{
-	int i;
-	u8 slot_cap[256];
-	static u8 slot_command[8] = {0x07, 0x40, 0x02, 0x00, 0x02, 0x00, 0x00, 0xff};
-
-	put_checksum(&slot_command[0], slot_command[0]);
-	if ((dst_put_ci(state, slot_command, sizeof (slot_command), slot_cap, GET_REPLY)) < 0) {
-		dprintk(verbose, DST_CA_ERROR, 1, " -->dst_put_ci FAILED !");
-		return -1;
-	}
-	dprintk(verbose, DST_CA_NOTICE, 1, " -->dst_put_ci SUCCESS !");
-
-	/*	Will implement the rest soon		*/
-
-	dprintk(verbose, DST_CA_INFO, 1, " Slot cap = [%d]", slot_cap[7]);
-	dprintk(verbose, DST_CA_INFO, 0, "===================================\n");
-	for (i = 0; i < slot_cap[0] + 1; i++)
-		dprintk(verbose, DST_CA_INFO, 0, " %d", slot_cap[i]);
-	dprintk(verbose, DST_CA_INFO, 0, "\n");
-
-	p_ca_caps->slot_num = 1;
-	p_ca_caps->slot_type = 1;
-	p_ca_caps->descr_num = slot_cap[7];
-	p_ca_caps->descr_type = 1;
-
-	if (copy_to_user(arg, p_ca_caps, sizeof (struct ca_caps)))
-		return -EFAULT;
-
-	return 0;
-}
-
-/*	Need some more work	*/
-static int ca_get_slot_descr(struct dst_state *state, struct ca_msg *p_ca_message, void __user *arg)
-{
-	return -EOPNOTSUPP;
-}
-
-
-static int ca_get_slot_info(struct dst_state *state, struct ca_slot_info *p_ca_slot_info, void __user *arg)
-{
-	int i;
-	static u8 slot_command[8] = {0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff};
-
-	u8 *slot_info = state->messages;
-
-	put_checksum(&slot_command[0], 7);
-	if ((dst_put_ci(state, slot_command, sizeof (slot_command), slot_info, GET_REPLY)) < 0) {
-		dprintk(verbose, DST_CA_ERROR, 1, " -->dst_put_ci FAILED !");
-		return -1;
-	}
-	dprintk(verbose, DST_CA_INFO, 1, " -->dst_put_ci SUCCESS !");
-
-	/*	Will implement the rest soon		*/
-
-	dprintk(verbose, DST_CA_INFO, 1, " Slot info = [%d]", slot_info[3]);
-	dprintk(verbose, DST_CA_INFO, 0, "===================================\n");
-	for (i = 0; i < 8; i++)
-		dprintk(verbose, DST_CA_INFO, 0, " %d", slot_info[i]);
-	dprintk(verbose, DST_CA_INFO, 0, "\n");
-
-	if (slot_info[4] & 0x80) {
-		p_ca_slot_info->flags = CA_CI_MODULE_PRESENT;
-		p_ca_slot_info->num = 1;
-		p_ca_slot_info->type = CA_CI;
-	} else if (slot_info[4] & 0x40) {
-		p_ca_slot_info->flags = CA_CI_MODULE_READY;
-		p_ca_slot_info->num = 1;
-		p_ca_slot_info->type = CA_CI;
-	} else
-		p_ca_slot_info->flags = 0;
-
-	if (copy_to_user(arg, p_ca_slot_info, sizeof (struct ca_slot_info)))
-		return -EFAULT;
-
-	return 0;
-}
-
-
-static int ca_get_message(struct dst_state *state, struct ca_msg *p_ca_message, void __user *arg)
-{
-	u8 i = 0;
-	u32 command = 0;
-
-	if (copy_from_user(p_ca_message, arg, sizeof (struct ca_msg)))
-		return -EFAULT;
-
-	if (p_ca_message->msg) {
-		dprintk(verbose, DST_CA_NOTICE, 1, " Message = [%02x %02x %02x]", p_ca_message->msg[0], p_ca_message->msg[1], p_ca_message->msg[2]);
-
-		for (i = 0; i < 3; i++) {
-			command = command | p_ca_message->msg[i];
-			if (i < 2)
-				command = command << 8;
-		}
-		dprintk(verbose, DST_CA_NOTICE, 1, " Command=[0x%x]", command);
-
-		switch (command) {
-		case CA_APP_INFO:
-			memcpy(p_ca_message->msg, state->messages, 128);
-			if (copy_to_user(arg, p_ca_message, sizeof (struct ca_msg)) )
-				return -EFAULT;
-			break;
-		case CA_INFO:
-			memcpy(p_ca_message->msg, state->messages, 128);
-			if (copy_to_user(arg, p_ca_message, sizeof (struct ca_msg)) )
-				return -EFAULT;
-			break;
-		}
-	}
-
-	return 0;
-}
-
-static int handle_dst_tag(struct dst_state *state, struct ca_msg *p_ca_message, struct ca_msg *hw_buffer, u32 length)
-{
-	if (state->dst_hw_cap & DST_TYPE_HAS_SESSION) {
-		hw_buffer->msg[2] = p_ca_message->msg[1];	/*	MSB	*/
-		hw_buffer->msg[3] = p_ca_message->msg[2];	/*	LSB	*/
-	} else {
-		if (length > 247) {
-			dprintk(verbose, DST_CA_ERROR, 1, " Message too long ! *** Bailing Out *** !");
-			return -1;
-		}
-		hw_buffer->msg[0] = (length & 0xff) + 7;
-		hw_buffer->msg[1] = 0x40;
-		hw_buffer->msg[2] = 0x03;
-		hw_buffer->msg[3] = 0x00;
-		hw_buffer->msg[4] = 0x03;
-		hw_buffer->msg[5] = length & 0xff;
-		hw_buffer->msg[6] = 0x00;
-
-		/*
-		 *	Need to compute length for EN50221 section 8.3.2, for the time being
-		 *	assuming 8.3.2 is not applicable
-		 */
-		memcpy(&hw_buffer->msg[7], &p_ca_message->msg[4], length);
-	}
-
-	return 0;
-}
-
-static int write_to_8820(struct dst_state *state, struct ca_msg *hw_buffer, u8 length, u8 reply)
-{
-	if ((dst_put_ci(state, hw_buffer->msg, length, hw_buffer->msg, reply)) < 0) {
-		dprintk(verbose, DST_CA_ERROR, 1, " DST-CI Command failed.");
-		dprintk(verbose, DST_CA_NOTICE, 1, " Resetting DST.");
-		rdc_reset_state(state);
-		return -1;
-	}
-	dprintk(verbose, DST_CA_NOTICE, 1, " DST-CI Command success.");
-
-	return 0;
-}
-
-static u32 asn_1_decode(u8 *asn_1_array)
-{
-	u8 length_field = 0, word_count = 0, count = 0;
-	u32 length = 0;
-
-	length_field = asn_1_array[0];
-	dprintk(verbose, DST_CA_DEBUG, 1, " Length field=[%02x]", length_field);
-	if (length_field < 0x80) {
-		length = length_field & 0x7f;
-		dprintk(verbose, DST_CA_DEBUG, 1, " Length=[%02x]\n", length);
-	} else {
-		word_count = length_field & 0x7f;
-		for (count = 0; count < word_count; count++) {
-			length = length  << 8;
-			length += asn_1_array[count + 1];
-			dprintk(verbose, DST_CA_DEBUG, 1, " Length=[%04x]", length);
-		}
-	}
-	return length;
-}
-
-static int debug_string(u8 *msg, u32 length, u32 offset)
-{
-	u32 i;
-
-	dprintk(verbose, DST_CA_DEBUG, 0, " String=[ ");
-	for (i = offset; i < length; i++)
-		dprintk(verbose, DST_CA_DEBUG, 0, "%02x ", msg[i]);
-	dprintk(verbose, DST_CA_DEBUG, 0, "]\n");
-
-	return 0;
-}
-
-
-static int ca_set_pmt(struct dst_state *state, struct ca_msg *p_ca_message, struct ca_msg *hw_buffer, u8 reply, u8 query)
-{
-	u32 length = 0;
-	u8 tag_length = 8;
-
-	length = asn_1_decode(&p_ca_message->msg[3]);
-	dprintk(verbose, DST_CA_DEBUG, 1, " CA Message length=[%d]", length);
-	debug_string(&p_ca_message->msg[4], length, 0); /*	length is excluding tag & length	*/
-
-	memset(hw_buffer->msg, '\0', length);
-	handle_dst_tag(state, p_ca_message, hw_buffer, length);
-	put_checksum(hw_buffer->msg, hw_buffer->msg[0]);
-
-	debug_string(hw_buffer->msg, (length + tag_length), 0); /*	tags too	*/
-	write_to_8820(state, hw_buffer, (length + tag_length), reply);
-
-	return 0;
-}
-
-
-/*	Board supports CA PMT reply ?		*/
-static int dst_check_ca_pmt(struct dst_state *state, struct ca_msg *p_ca_message, struct ca_msg *hw_buffer)
-{
-	int ca_pmt_reply_test = 0;
-
-	/*	Do test board			*/
-	/*	Not there yet but soon		*/
-
-	/*	CA PMT Reply capable		*/
-	if (ca_pmt_reply_test) {
-		if ((ca_set_pmt(state, p_ca_message, hw_buffer, 1, GET_REPLY)) < 0) {
-			dprintk(verbose, DST_CA_ERROR, 1, " ca_set_pmt.. failed !");
-			return -1;
-		}
-
-	/*	Process CA PMT Reply		*/
-	/*	will implement soon		*/
-		dprintk(verbose, DST_CA_ERROR, 1, " Not there yet");
-	}
-	/*	CA PMT Reply not capable	*/
-	if (!ca_pmt_reply_test) {
-		if ((ca_set_pmt(state, p_ca_message, hw_buffer, 0, NO_REPLY)) < 0) {
-			dprintk(verbose, DST_CA_ERROR, 1, " ca_set_pmt.. failed !");
-			return -1;
-		}
-		dprintk(verbose, DST_CA_NOTICE, 1, " ca_set_pmt.. success !");
-	/*	put a dummy message		*/
-
-	}
-	return 0;
-}
-
-static int ca_send_message(struct dst_state *state, struct ca_msg *p_ca_message, void __user *arg)
-{
-	int i = 0;
-
-	u32 command = 0;
-	struct ca_msg *hw_buffer;
-	int result = 0;
-
-	if ((hw_buffer = kmalloc(sizeof (struct ca_msg), GFP_KERNEL)) == NULL) {
-		dprintk(verbose, DST_CA_ERROR, 1, " Memory allocation failure");
-		return -ENOMEM;
-	}
-	dprintk(verbose, DST_CA_DEBUG, 1, " ");
-
-	if (copy_from_user(p_ca_message, arg, sizeof (struct ca_msg))) {
-		result = -EFAULT;
-		goto free_mem_and_exit;
-	}
-
-
-	if (p_ca_message->msg) {
-		/*	EN50221 tag	*/
-		command = 0;
-
-		for (i = 0; i < 3; i++) {
-			command = command | p_ca_message->msg[i];
-			if (i < 2)
-				command = command << 8;
-		}
-		dprintk(verbose, DST_CA_DEBUG, 1, " Command=[0x%x]\n", command);
-
-		switch (command) {
-		case CA_PMT:
-			dprintk(verbose, DST_CA_DEBUG, 1, "Command = SEND_CA_PMT");
-			if ((ca_set_pmt(state, p_ca_message, hw_buffer, 0, 0)) < 0) {	// code simplification started
-				dprintk(verbose, DST_CA_ERROR, 1, " -->CA_PMT Failed !");
-				result = -1;
-				goto free_mem_and_exit;
-			}
-			dprintk(verbose, DST_CA_INFO, 1, " -->CA_PMT Success !");
-			break;
-		case CA_PMT_REPLY:
-			dprintk(verbose, DST_CA_INFO, 1, "Command = CA_PMT_REPLY");
-			/*      Have to handle the 2 basic types of cards here  */
-			if ((dst_check_ca_pmt(state, p_ca_message, hw_buffer)) < 0) {
-				dprintk(verbose, DST_CA_ERROR, 1, " -->CA_PMT_REPLY Failed !");
-				result = -1;
-				goto free_mem_and_exit;
-			}
-			dprintk(verbose, DST_CA_INFO, 1, " -->CA_PMT_REPLY Success !");
-			break;
-		case CA_APP_INFO_ENQUIRY:		// only for debugging
-			dprintk(verbose, DST_CA_INFO, 1, " Getting Cam Application information");
-
-			if ((ca_get_app_info(state)) < 0) {
-				dprintk(verbose, DST_CA_ERROR, 1, " -->CA_APP_INFO_ENQUIRY Failed !");
-				result = -1;
-				goto free_mem_and_exit;
-			}
-			dprintk(verbose, DST_CA_INFO, 1, " -->CA_APP_INFO_ENQUIRY Success !");
-			break;
-		case CA_INFO_ENQUIRY:
-			dprintk(verbose, DST_CA_INFO, 1, " Getting CA Information");
-
-			if ((ca_get_ca_info(state)) < 0) {
-				dprintk(verbose, DST_CA_ERROR, 1, " -->CA_INFO_ENQUIRY Failed !");
-				result = -1;
-				goto free_mem_and_exit;
-			}
-			dprintk(verbose, DST_CA_INFO, 1, " -->CA_INFO_ENQUIRY Success !");
-			break;
-		}
-	}
-free_mem_and_exit:
-	kfree (hw_buffer);
-
-	return result;
-}
-
-static long dst_ca_ioctl(struct file *file, unsigned int cmd, unsigned long ioctl_arg)
-{
-	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;
-
-	mutex_lock(&dst_ca_mutex);
-	dvbdev = 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);
-	if (!p_ca_message || !p_ca_slot_info || !p_ca_caps) {
-		dprintk(verbose, DST_CA_ERROR, 1, " Memory allocation failure");
-		result = -ENOMEM;
-		goto free_mem_and_exit;
-	}
-
-	/*	We have now only the standard ioctl's, the driver is upposed to handle internals.	*/
-	switch (cmd) {
-	case CA_SEND_MSG:
-		dprintk(verbose, DST_CA_INFO, 1, " Sending message");
-		if ((ca_send_message(state, p_ca_message, arg)) < 0) {
-			dprintk(verbose, DST_CA_ERROR, 1, " -->CA_SEND_MSG Failed !");
-			result = -1;
-			goto free_mem_and_exit;
-		}
-		break;
-	case CA_GET_MSG:
-		dprintk(verbose, DST_CA_INFO, 1, " Getting message");
-		if ((ca_get_message(state, p_ca_message, arg)) < 0) {
-			dprintk(verbose, DST_CA_ERROR, 1, " -->CA_GET_MSG Failed !");
-			result = -1;
-			goto free_mem_and_exit;
-		}
-		dprintk(verbose, DST_CA_INFO, 1, " -->CA_GET_MSG Success !");
-		break;
-	case CA_RESET:
-		dprintk(verbose, DST_CA_ERROR, 1, " Resetting DST");
-		dst_error_bailout(state);
-		msleep(4000);
-		break;
-	case CA_GET_SLOT_INFO:
-		dprintk(verbose, DST_CA_INFO, 1, " Getting Slot info");
-		if ((ca_get_slot_info(state, p_ca_slot_info, arg)) < 0) {
-			dprintk(verbose, DST_CA_ERROR, 1, " -->CA_GET_SLOT_INFO Failed !");
-			result = -1;
-			goto free_mem_and_exit;
-		}
-		dprintk(verbose, DST_CA_INFO, 1, " -->CA_GET_SLOT_INFO Success !");
-		break;
-	case CA_GET_CAP:
-		dprintk(verbose, DST_CA_INFO, 1, " Getting Slot capabilities");
-		if ((ca_get_slot_caps(state, p_ca_caps, arg)) < 0) {
-			dprintk(verbose, DST_CA_ERROR, 1, " -->CA_GET_CAP Failed !");
-			result = -1;
-			goto free_mem_and_exit;
-		}
-		dprintk(verbose, DST_CA_INFO, 1, " -->CA_GET_CAP Success !");
-		break;
-	case CA_GET_DESCR_INFO:
-		dprintk(verbose, DST_CA_INFO, 1, " Getting descrambler description");
-		if ((ca_get_slot_descr(state, p_ca_message, arg)) < 0) {
-			dprintk(verbose, DST_CA_ERROR, 1, " -->CA_GET_DESCR_INFO Failed !");
-			result = -1;
-			goto free_mem_and_exit;
-		}
-		dprintk(verbose, DST_CA_INFO, 1, " -->CA_GET_DESCR_INFO Success !");
-		break;
-	case CA_SET_DESCR:
-		dprintk(verbose, DST_CA_INFO, 1, " Setting descrambler");
-		if ((ca_set_slot_descr()) < 0) {
-			dprintk(verbose, DST_CA_ERROR, 1, " -->CA_SET_DESCR Failed !");
-			result = -1;
-			goto free_mem_and_exit;
-		}
-		dprintk(verbose, DST_CA_INFO, 1, " -->CA_SET_DESCR Success !");
-		break;
-	case CA_SET_PID:
-		dprintk(verbose, DST_CA_INFO, 1, " Setting PID");
-		if ((ca_set_pid()) < 0) {
-			dprintk(verbose, DST_CA_ERROR, 1, " -->CA_SET_PID Failed !");
-			result = -1;
-			goto free_mem_and_exit;
-		}
-		dprintk(verbose, DST_CA_INFO, 1, " -->CA_SET_PID Success !");
-	default:
-		result = -EOPNOTSUPP;
-	};
- free_mem_and_exit:
-	kfree (p_ca_message);
-	kfree (p_ca_slot_info);
-	kfree (p_ca_caps);
-
-	mutex_unlock(&dst_ca_mutex);
-	return result;
-}
-
-static int dst_ca_open(struct inode *inode, struct file *file)
-{
-	dprintk(verbose, DST_CA_DEBUG, 1, " Device opened [%p] ", file);
-	try_module_get(THIS_MODULE);
-
-	return 0;
-}
-
-static int dst_ca_release(struct inode *inode, struct file *file)
-{
-	dprintk(verbose, DST_CA_DEBUG, 1, " Device closed.");
-	module_put(THIS_MODULE);
-
-	return 0;
-}
-
-static ssize_t dst_ca_read(struct file *file, char __user *buffer, size_t length, loff_t *offset)
-{
-	ssize_t bytes_read = 0;
-
-	dprintk(verbose, DST_CA_DEBUG, 1, " Device read.");
-
-	return bytes_read;
-}
-
-static ssize_t dst_ca_write(struct file *file, const char __user *buffer, size_t length, loff_t *offset)
-{
-	dprintk(verbose, DST_CA_DEBUG, 1, " Device write.");
-
-	return 0;
-}
-
-static const struct file_operations dst_ca_fops = {
-	.owner = THIS_MODULE,
-	.unlocked_ioctl = dst_ca_ioctl,
-	.open = dst_ca_open,
-	.release = dst_ca_release,
-	.read = dst_ca_read,
-	.write = dst_ca_write,
-	.llseek = noop_llseek,
-};
-
-static struct dvb_device dvbdev_ca = {
-	.priv = NULL,
-	.users = 1,
-	.readers = 1,
-	.writers = 1,
-	.fops = &dst_ca_fops
-};
-
-struct dvb_device *dst_ca_attach(struct dst_state *dst, struct dvb_adapter *dvb_adapter)
-{
-	struct dvb_device *dvbdev;
-
-	dprintk(verbose, DST_CA_ERROR, 1, "registering DST-CA device");
-	if (dvb_register_device(dvb_adapter, &dvbdev, &dvbdev_ca, dst, DVB_DEVICE_CA) == 0) {
-		dst->dst_ca = dvbdev;
-		return dst->dst_ca;
-	}
-
-	return NULL;
-}
-
-EXPORT_SYMBOL(dst_ca_attach);
-
-MODULE_DESCRIPTION("DST DVB-S/T/C Combo CA driver");
-MODULE_AUTHOR("Manu Abraham");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/bt8xx/dst_ca.h b/drivers/media/dvb/bt8xx/dst_ca.h
deleted file mode 100644
index 59cd0dd..0000000
--- a/drivers/media/dvb/bt8xx/dst_ca.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
-	CA-driver for TwinHan DST Frontend/Card
-
-	Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.com)
-
-	This program is free software; you can redistribute it and/or modify
-	it under the terms of the GNU General Public License as published by
-	the Free Software Foundation; either version 2 of the License, or
-	(at your option) any later version.
-
-	This program is distributed in the hope that it will be useful,
-	but WITHOUT ANY WARRANTY; without even the implied warranty of
-	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	GNU General Public License for more details.
-
-	You should have received a copy of the GNU General Public License
-	along with this program; if not, write to the Free Software
-	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#ifndef _DST_CA_H_
-#define _DST_CA_H_
-
-#define RETRIES			5
-
-
-#define	CA_APP_INFO_ENQUIRY	0x9f8020
-#define	CA_APP_INFO		0x9f8021
-#define	CA_ENTER_MENU		0x9f8022
-#define CA_INFO_ENQUIRY		0x9f8030
-#define	CA_INFO			0x9f8031
-#define CA_PMT			0x9f8032
-#define CA_PMT_REPLY		0x9f8033
-
-#define CA_CLOSE_MMI		0x9f8800
-#define CA_DISPLAY_CONTROL	0x9f8801
-#define CA_DISPLAY_REPLY	0x9f8802
-#define CA_TEXT_LAST		0x9f8803
-#define CA_TEXT_MORE		0x9f8804
-#define CA_KEYPAD_CONTROL	0x9f8805
-#define CA_KEYPRESS		0x9f8806
-
-#define CA_ENQUIRY		0x9f8807
-#define CA_ANSWER		0x9f8808
-#define CA_MENU_LAST		0x9f8809
-#define CA_MENU_MORE		0x9f880a
-#define CA_MENU_ANSWER		0x9f880b
-#define CA_LIST_LAST		0x9f880c
-#define CA_LIST_MORE		0x9f880d
-
-
-struct dst_ca_private {
-	struct dst_state *dst;
-	struct dvb_device *dvbdev;
-};
-
-
-#endif
diff --git a/drivers/media/dvb/bt8xx/dst_common.h b/drivers/media/dvb/bt8xx/dst_common.h
deleted file mode 100644
index d70d98f..0000000
--- a/drivers/media/dvb/bt8xx/dst_common.h
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
-	Frontend-driver for TwinHan DST Frontend
-
-	Copyright (C) 2003 Jamie Honan
-	Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.com)
-
-	This program is free software; you can redistribute it and/or modify
-	it under the terms of the GNU General Public License as published by
-	the Free Software Foundation; either version 2 of the License, or
-	(at your option) any later version.
-
-	This program is distributed in the hope that it will be useful,
-	but WITHOUT ANY WARRANTY; without even the implied warranty of
-	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	GNU General Public License for more details.
-
-	You should have received a copy of the GNU General Public License
-	along with this program; if not, write to the Free Software
-	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#ifndef DST_COMMON_H
-#define DST_COMMON_H
-
-#include <linux/dvb/frontend.h>
-#include <linux/device.h>
-#include <linux/mutex.h>
-#include "bt878.h"
-
-#include "dst_ca.h"
-
-
-#define NO_DELAY		0
-#define LONG_DELAY		1
-#define DEVICE_INIT		2
-
-#define DELAY			1
-
-#define DST_TYPE_IS_SAT		0
-#define DST_TYPE_IS_TERR	1
-#define DST_TYPE_IS_CABLE	2
-#define DST_TYPE_IS_ATSC	3
-
-#define DST_TYPE_HAS_TS188	1
-#define DST_TYPE_HAS_TS204	2
-#define DST_TYPE_HAS_SYMDIV	4
-#define DST_TYPE_HAS_FW_1	8
-#define DST_TYPE_HAS_FW_2	16
-#define DST_TYPE_HAS_FW_3	32
-#define DST_TYPE_HAS_FW_BUILD	64
-#define DST_TYPE_HAS_OBS_REGS	128
-#define DST_TYPE_HAS_INC_COUNT	256
-#define DST_TYPE_HAS_MULTI_FE	512
-#define DST_TYPE_HAS_NEWTUNE_2	1024
-#define DST_TYPE_HAS_DBOARD	2048
-#define DST_TYPE_HAS_VLF	4096
-
-/*	Card capability list	*/
-
-#define DST_TYPE_HAS_MAC	1
-#define DST_TYPE_HAS_DISEQC3	2
-#define DST_TYPE_HAS_DISEQC4	4
-#define DST_TYPE_HAS_DISEQC5	8
-#define DST_TYPE_HAS_MOTO	16
-#define DST_TYPE_HAS_CA		32
-#define	DST_TYPE_HAS_ANALOG	64	/*	Analog inputs	*/
-#define DST_TYPE_HAS_SESSION	128
-
-#define TUNER_TYPE_MULTI	1
-#define TUNER_TYPE_UNKNOWN	2
-/*	DVB-S		*/
-#define TUNER_TYPE_L64724	4
-#define TUNER_TYPE_STV0299	8
-#define TUNER_TYPE_MB86A15	16
-
-/*	DVB-T		*/
-#define TUNER_TYPE_TDA10046	32
-
-/*	ATSC		*/
-#define TUNER_TYPE_NXT200x	64
-
-
-#define RDC_8820_PIO_0_DISABLE	0
-#define RDC_8820_PIO_0_ENABLE	1
-#define RDC_8820_INT		2
-#define RDC_8820_RESET		4
-
-/*	DST Communication	*/
-#define GET_REPLY		1
-#define NO_REPLY		0
-
-#define GET_ACK			1
-#define FIXED_COMM		8
-
-#define ACK			0xff
-
-struct dst_state {
-
-	struct i2c_adapter* i2c;
-
-	struct bt878* bt;
-
-	/* configuration settings */
-	const struct dst_config* config;
-
-	struct dvb_frontend frontend;
-
-	/* private ASIC data */
-	u8 tx_tuna[10];
-	u8 rx_tuna[10];
-	u8 rxbuffer[10];
-	u8 diseq_flags;
-	u8 dst_type;
-	u32 type_flags;
-	u32 frequency;		/* intermediate frequency in kHz for QPSK */
-	fe_spectral_inversion_t inversion;
-	u32 symbol_rate;	/* symbol rate in Symbols per second */
-	fe_code_rate_t fec;
-	fe_sec_voltage_t voltage;
-	fe_sec_tone_mode_t tone;
-	u32 decode_freq;
-	u8 decode_lock;
-	u16 decode_strength;
-	u16 decode_snr;
-	unsigned long cur_jiff;
-	u8 k22;
-	u32 bandwidth;
-	u32 dst_hw_cap;
-	u8 dst_fw_version;
-	fe_sec_mini_cmd_t minicmd;
-	fe_modulation_t modulation;
-	u8 messages[256];
-	u8 mac_address[8];
-	u8 fw_version[8];
-	u8 card_info[8];
-	u8 vendor[8];
-	u8 board_info[8];
-	u32 tuner_type;
-	char *tuner_name;
-	struct mutex dst_mutex;
-	u8 fw_name[8];
-	struct dvb_device *dst_ca;
-};
-
-struct tuner_types {
-	u32 tuner_type;
-	char *tuner_name;
-	char *board_name;
-	char *fw_name;
-};
-
-struct dst_types {
-	char *device_id;
-	int offset;
-	u8 dst_type;
-	u32 type_flags;
-	u32 dst_feature;
-	u32 tuner_type;
-};
-
-struct dst_config
-{
-	/* the ASIC i2c address */
-	u8 demod_address;
-};
-
-int rdc_reset_state(struct dst_state *state);
-
-int dst_wait_dst_ready(struct dst_state *state, u8 delay_mode);
-int dst_pio_disable(struct dst_state *state);
-int dst_error_recovery(struct dst_state* state);
-int dst_error_bailout(struct dst_state *state);
-int dst_comm_init(struct dst_state* state);
-
-int write_dst(struct dst_state *state, u8 * data, u8 len);
-int read_dst(struct dst_state *state, u8 * ret, u8 len);
-u8 dst_check_sum(u8 * buf, u32 len);
-struct dst_state* dst_attach(struct dst_state* state, struct dvb_adapter *dvb_adapter);
-struct dvb_device *dst_ca_attach(struct dst_state *state, struct dvb_adapter *dvb_adapter);
-
-
-#endif // DST_COMMON_H
diff --git a/drivers/media/dvb/bt8xx/dst_priv.h b/drivers/media/dvb/bt8xx/dst_priv.h
deleted file mode 100644
index 3974a4c..0000000
--- a/drivers/media/dvb/bt8xx/dst_priv.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * dst-bt878.h: part of the DST driver for the TwinHan DST Frontend
- *
- * Copyright (C) 2003 Jamie Honan
- */
-
-struct dst_gpio_enable {
-	u32	mask;
-	u32	enable;
-};
-
-struct dst_gpio_output {
-	u32	mask;
-	u32	highvals;
-};
-
-struct dst_gpio_read {
-	unsigned long value;
-};
-
-union dst_gpio_packet {
-	struct dst_gpio_enable enb;
-	struct dst_gpio_output outp;
-	struct dst_gpio_read rd;
-	int    psize;
-};
-
-#define DST_IG_ENABLE	0
-#define DST_IG_WRITE	1
-#define DST_IG_READ	2
-#define DST_IG_TS       3
-
-struct bt878;
-
-int bt878_device_control(struct bt878 *bt, unsigned int cmd, union dst_gpio_packet *mp);
diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c
deleted file mode 100644
index 81fab9a..0000000
--- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c
+++ /dev/null
@@ -1,975 +0,0 @@
-/*
- * Bt8xx based DVB adapter driver
- *
- * Copyright (C) 2002,2003 Florian Schirmer <jolt@tuxbox.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.
- *
- */
-
-#define pr_fmt(fmt) "dvb_bt8xx: " fmt
-
-#include <linux/bitops.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/device.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/i2c.h>
-
-#include "dmxdev.h"
-#include "dvbdev.h"
-#include "dvb_demux.h"
-#include "dvb_frontend.h"
-#include "dvb-bt8xx.h"
-#include "bt878.h"
-
-static int debug;
-
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-#define dprintk( args... ) \
-	do { \
-		if (debug) printk(KERN_DEBUG args); \
-	} while (0)
-
-#define IF_FREQUENCYx6 217    /* 6 * 36.16666666667MHz */
-
-static void dvb_bt8xx_task(unsigned long data)
-{
-	struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *)data;
-
-	//printk("%d ", card->bt->finished_block);
-
-	while (card->bt->last_block != card->bt->finished_block) {
-		(card->bt->TS_Size ? dvb_dmx_swfilter_204 : dvb_dmx_swfilter)
-			(&card->demux,
-			 &card->bt->buf_cpu[card->bt->last_block *
-					    card->bt->block_bytes],
-			 card->bt->block_bytes);
-		card->bt->last_block = (card->bt->last_block + 1) %
-					card->bt->block_count;
-	}
-}
-
-static int dvb_bt8xx_start_feed(struct dvb_demux_feed *dvbdmxfeed)
-{
-	struct dvb_demux*dvbdmx = dvbdmxfeed->demux;
-	struct dvb_bt8xx_card *card = dvbdmx->priv;
-	int rc;
-
-	dprintk("dvb_bt8xx: start_feed\n");
-
-	if (!dvbdmx->dmx.frontend)
-		return -EINVAL;
-
-	mutex_lock(&card->lock);
-	card->nfeeds++;
-	rc = card->nfeeds;
-	if (card->nfeeds == 1)
-		bt878_start(card->bt, card->gpio_mode,
-			    card->op_sync_orin, card->irq_err_ignore);
-	mutex_unlock(&card->lock);
-	return rc;
-}
-
-static int dvb_bt8xx_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
-{
-	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
-	struct dvb_bt8xx_card *card = dvbdmx->priv;
-
-	dprintk("dvb_bt8xx: stop_feed\n");
-
-	if (!dvbdmx->dmx.frontend)
-		return -EINVAL;
-
-	mutex_lock(&card->lock);
-	card->nfeeds--;
-	if (card->nfeeds == 0)
-		bt878_stop(card->bt);
-	mutex_unlock(&card->lock);
-
-	return 0;
-}
-
-static int is_pci_slot_eq(struct pci_dev* adev, struct pci_dev* bdev)
-{
-	if ((adev->subsystem_vendor == bdev->subsystem_vendor) &&
-		(adev->subsystem_device == bdev->subsystem_device) &&
-		(adev->bus->number == bdev->bus->number) &&
-		(PCI_SLOT(adev->devfn) == PCI_SLOT(bdev->devfn)))
-		return 1;
-	return 0;
-}
-
-static struct bt878 __devinit *dvb_bt8xx_878_match(unsigned int bttv_nr, struct pci_dev* bttv_pci_dev)
-{
-	unsigned int card_nr;
-
-	/* Hmm, n squared. Hope n is small */
-	for (card_nr = 0; card_nr < bt878_num; card_nr++)
-		if (is_pci_slot_eq(bt878[card_nr].dev, bttv_pci_dev))
-			return &bt878[card_nr];
-	return NULL;
-}
-
-static int thomson_dtt7579_demod_init(struct dvb_frontend* fe)
-{
-	static u8 mt352_clock_config [] = { 0x89, 0x38, 0x38 };
-	static u8 mt352_reset [] = { 0x50, 0x80 };
-	static u8 mt352_adc_ctl_1_cfg [] = { 0x8E, 0x40 };
-	static u8 mt352_agc_cfg [] = { 0x67, 0x28, 0x20 };
-	static u8 mt352_gpp_ctl_cfg [] = { 0x8C, 0x33 };
-	static u8 mt352_capt_range_cfg[] = { 0x75, 0x32 };
-
-	mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config));
-	udelay(2000);
-	mt352_write(fe, mt352_reset, sizeof(mt352_reset));
-	mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg));
-
-	mt352_write(fe, mt352_agc_cfg, sizeof(mt352_agc_cfg));
-	mt352_write(fe, mt352_gpp_ctl_cfg, sizeof(mt352_gpp_ctl_cfg));
-	mt352_write(fe, mt352_capt_range_cfg, sizeof(mt352_capt_range_cfg));
-
-	return 0;
-}
-
-static int thomson_dtt7579_tuner_calc_regs(struct dvb_frontend *fe, u8* pllbuf, int buf_len)
-{
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	u32 div;
-	unsigned char bs = 0;
-	unsigned char cp = 0;
-
-	if (buf_len < 5)
-		return -EINVAL;
-
-	div = (((c->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
-
-	if (c->frequency < 542000000)
-		cp = 0xb4;
-	else if (c->frequency < 771000000)
-		cp = 0xbc;
-	else
-		cp = 0xf4;
-
-	if (c->frequency == 0)
-		bs = 0x03;
-	else if (c->frequency < 443250000)
-		bs = 0x02;
-	else
-		bs = 0x08;
-
-	pllbuf[0] = 0x60;
-	pllbuf[1] = div >> 8;
-	pllbuf[2] = div & 0xff;
-	pllbuf[3] = cp;
-	pllbuf[4] = bs;
-
-	return 5;
-}
-
-static struct mt352_config thomson_dtt7579_config = {
-	.demod_address = 0x0f,
-	.demod_init = thomson_dtt7579_demod_init,
-};
-
-static struct zl10353_config thomson_dtt7579_zl10353_config = {
-	.demod_address = 0x0f,
-};
-
-static int cx24108_tuner_set_params(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	u32 freq = c->frequency;
-	int i, a, n, pump;
-	u32 band, pll;
-	u32 osci[]={950000,1019000,1075000,1178000,1296000,1432000,
-		1576000,1718000,1856000,2036000,2150000};
-	u32 bandsel[]={0,0x00020000,0x00040000,0x00100800,0x00101000,
-		0x00102000,0x00104000,0x00108000,0x00110000,
-		0x00120000,0x00140000};
-
-	#define XTAL 1011100 /* Hz, really 1.0111 MHz and a /10 prescaler */
-	dprintk("cx24108 debug: entering SetTunerFreq, freq=%d\n", freq);
-
-	/* This is really the bit driving the tuner chip cx24108 */
-
-	if (freq<950000)
-		freq = 950000; /* kHz */
-	else if (freq>2150000)
-		freq = 2150000; /* satellite IF is 950..2150MHz */
-
-	/* decide which VCO to use for the input frequency */
-	for(i = 1; (i < ARRAY_SIZE(osci) - 1) && (osci[i] < freq); i++);
-	dprintk("cx24108 debug: select vco #%d (f=%d)\n", i, freq);
-	band=bandsel[i];
-	/* the gain values must be set by SetSymbolrate */
-	/* compute the pll divider needed, from Conexant data sheet,
-	   resolved for (n*32+a), remember f(vco) is f(receive) *2 or *4,
-	   depending on the divider bit. It is set to /4 on the 2 lowest
-	   bands  */
-	n=((i<=2?2:1)*freq*10L)/(XTAL/100);
-	a=n%32; n/=32; if(a==0) n--;
-	pump=(freq<(osci[i-1]+osci[i])/2);
-	pll=0xf8000000|
-	    ((pump?1:2)<<(14+11))|
-	    ((n&0x1ff)<<(5+11))|
-	    ((a&0x1f)<<11);
-	/* everything is shifted left 11 bits to left-align the bits in the
-	   32bit word. Output to the tuner goes MSB-aligned, after all */
-	dprintk("cx24108 debug: pump=%d, n=%d, a=%d\n", pump, n, a);
-	cx24110_pll_write(fe,band);
-	/* set vga and vca to their widest-band settings, as a precaution.
-	   SetSymbolrate might not be called to set this up */
-	cx24110_pll_write(fe,0x500c0000);
-	cx24110_pll_write(fe,0x83f1f800);
-	cx24110_pll_write(fe,pll);
-	//writereg(client,0x56,0x7f);
-
-	return 0;
-}
-
-static int pinnsat_tuner_init(struct dvb_frontend* fe)
-{
-	struct dvb_bt8xx_card *card = fe->dvb->priv;
-
-	bttv_gpio_enable(card->bttv_nr, 1, 1);  /* output */
-	bttv_write_gpio(card->bttv_nr, 1, 1);   /* relay on */
-
-	return 0;
-}
-
-static int pinnsat_tuner_sleep(struct dvb_frontend* fe)
-{
-	struct dvb_bt8xx_card *card = fe->dvb->priv;
-
-	bttv_write_gpio(card->bttv_nr, 1, 0);   /* relay off */
-
-	return 0;
-}
-
-static struct cx24110_config pctvsat_config = {
-	.demod_address = 0x55,
-};
-
-static int microtune_mt7202dtf_tuner_set_params(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *) fe->dvb->priv;
-	u8 cfg, cpump, band_select;
-	u8 data[4];
-	u32 div;
-	struct i2c_msg msg = { .addr = 0x60, .flags = 0, .buf = data, .len = sizeof(data) };
-
-	div = (36000000 + c->frequency + 83333) / 166666;
-	cfg = 0x88;
-
-	if (c->frequency < 175000000)
-		cpump = 2;
-	else if (c->frequency < 390000000)
-		cpump = 1;
-	else if (c->frequency < 470000000)
-		cpump = 2;
-	else if (c->frequency < 750000000)
-		cpump = 2;
-	else
-		cpump = 3;
-
-	if (c->frequency < 175000000)
-		band_select = 0x0e;
-	else if (c->frequency < 470000000)
-		band_select = 0x05;
-	else
-		band_select = 0x03;
-
-	data[0] = (div >> 8) & 0x7f;
-	data[1] = div & 0xff;
-	data[2] = ((div >> 10) & 0x60) | cfg;
-	data[3] = (cpump << 6) | band_select;
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	i2c_transfer(card->i2c_adapter, &msg, 1);
-	return (div * 166666 - 36000000);
-}
-
-static int microtune_mt7202dtf_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name)
-{
-	struct dvb_bt8xx_card* bt = (struct dvb_bt8xx_card*) fe->dvb->priv;
-
-	return request_firmware(fw, name, &bt->bt->dev->dev);
-}
-
-static struct sp887x_config microtune_mt7202dtf_config = {
-	.demod_address = 0x70,
-	.request_firmware = microtune_mt7202dtf_request_firmware,
-};
-
-static int advbt771_samsung_tdtc9251dh0_demod_init(struct dvb_frontend* fe)
-{
-	static u8 mt352_clock_config [] = { 0x89, 0x38, 0x2d };
-	static u8 mt352_reset [] = { 0x50, 0x80 };
-	static u8 mt352_adc_ctl_1_cfg [] = { 0x8E, 0x40 };
-	static u8 mt352_agc_cfg [] = { 0x67, 0x10, 0x23, 0x00, 0xFF, 0xFF,
-				       0x00, 0xFF, 0x00, 0x40, 0x40 };
-	static u8 mt352_av771_extra[] = { 0xB5, 0x7A };
-	static u8 mt352_capt_range_cfg[] = { 0x75, 0x32 };
-
-	mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config));
-	udelay(2000);
-	mt352_write(fe, mt352_reset, sizeof(mt352_reset));
-	mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg));
-
-	mt352_write(fe, mt352_agc_cfg,sizeof(mt352_agc_cfg));
-	udelay(2000);
-	mt352_write(fe, mt352_av771_extra,sizeof(mt352_av771_extra));
-	mt352_write(fe, mt352_capt_range_cfg, sizeof(mt352_capt_range_cfg));
-
-	return 0;
-}
-
-static int advbt771_samsung_tdtc9251dh0_tuner_calc_regs(struct dvb_frontend *fe, u8 *pllbuf, int buf_len)
-{
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	u32 div;
-	unsigned char bs = 0;
-	unsigned char cp = 0;
-
-	if (buf_len < 5) return -EINVAL;
-
-	div = (((c->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
-
-	if (c->frequency < 150000000)
-		cp = 0xB4;
-	else if (c->frequency < 173000000)
-		cp = 0xBC;
-	else if (c->frequency < 250000000)
-		cp = 0xB4;
-	else if (c->frequency < 400000000)
-		cp = 0xBC;
-	else if (c->frequency < 420000000)
-		cp = 0xF4;
-	else if (c->frequency < 470000000)
-		cp = 0xFC;
-	else if (c->frequency < 600000000)
-		cp = 0xBC;
-	else if (c->frequency < 730000000)
-		cp = 0xF4;
-	else
-		cp = 0xFC;
-
-	if (c->frequency < 150000000)
-		bs = 0x01;
-	else if (c->frequency < 173000000)
-		bs = 0x01;
-	else if (c->frequency < 250000000)
-		bs = 0x02;
-	else if (c->frequency < 400000000)
-		bs = 0x02;
-	else if (c->frequency < 420000000)
-		bs = 0x02;
-	else if (c->frequency < 470000000)
-		bs = 0x02;
-	else if (c->frequency < 600000000)
-		bs = 0x08;
-	else if (c->frequency < 730000000)
-		bs = 0x08;
-	else
-		bs = 0x08;
-
-	pllbuf[0] = 0x61;
-	pllbuf[1] = div >> 8;
-	pllbuf[2] = div & 0xff;
-	pllbuf[3] = cp;
-	pllbuf[4] = bs;
-
-	return 5;
-}
-
-static struct mt352_config advbt771_samsung_tdtc9251dh0_config = {
-	.demod_address = 0x0f,
-	.demod_init = advbt771_samsung_tdtc9251dh0_demod_init,
-};
-
-static struct dst_config dst_config = {
-	.demod_address = 0x55,
-};
-
-static int or51211_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name)
-{
-	struct dvb_bt8xx_card* bt = (struct dvb_bt8xx_card*) fe->dvb->priv;
-
-	return request_firmware(fw, name, &bt->bt->dev->dev);
-}
-
-static void or51211_setmode(struct dvb_frontend * fe, int mode)
-{
-	struct dvb_bt8xx_card *bt = fe->dvb->priv;
-	bttv_write_gpio(bt->bttv_nr, 0x0002, mode);   /* Reset */
-	msleep(20);
-}
-
-static void or51211_reset(struct dvb_frontend * fe)
-{
-	struct dvb_bt8xx_card *bt = fe->dvb->priv;
-
-	/* RESET DEVICE
-	 * reset is controlled by GPIO-0
-	 * when set to 0 causes reset and when to 1 for normal op
-	 * must remain reset for 128 clock cycles on a 50Mhz clock
-	 * also PRM1 PRM2 & PRM4 are controlled by GPIO-1,GPIO-2 & GPIO-4
-	 * We assume that the reset has be held low long enough or we
-	 * have been reset by a power on.  When the driver is unloaded
-	 * reset set to 0 so if reloaded we have been reset.
-	 */
-	/* reset & PRM1,2&4 are outputs */
-	int ret = bttv_gpio_enable(bt->bttv_nr, 0x001F, 0x001F);
-	if (ret != 0)
-		printk(KERN_WARNING "or51211: Init Error - Can't Reset DVR (%i)\n", ret);
-	bttv_write_gpio(bt->bttv_nr, 0x001F, 0x0000);   /* Reset */
-	msleep(20);
-	/* Now set for normal operation */
-	bttv_write_gpio(bt->bttv_nr, 0x0001F, 0x0001);
-	/* wait for operation to begin */
-	msleep(500);
-}
-
-static void or51211_sleep(struct dvb_frontend * fe)
-{
-	struct dvb_bt8xx_card *bt = fe->dvb->priv;
-	bttv_write_gpio(bt->bttv_nr, 0x0001, 0x0000);
-}
-
-static struct or51211_config or51211_config = {
-	.demod_address = 0x15,
-	.request_firmware = or51211_request_firmware,
-	.setmode = or51211_setmode,
-	.reset = or51211_reset,
-	.sleep = or51211_sleep,
-};
-
-static int vp3021_alps_tded4_tuner_set_params(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *) fe->dvb->priv;
-	u8 buf[4];
-	u32 div;
-	struct i2c_msg msg = { .addr = 0x60, .flags = 0, .buf = buf, .len = sizeof(buf) };
-
-	div = (c->frequency + 36166667) / 166667;
-
-	buf[0] = (div >> 8) & 0x7F;
-	buf[1] = div & 0xFF;
-	buf[2] = 0x85;
-	if ((c->frequency >= 47000000) && (c->frequency < 153000000))
-		buf[3] = 0x01;
-	else if ((c->frequency >= 153000000) && (c->frequency < 430000000))
-		buf[3] = 0x02;
-	else if ((c->frequency >= 430000000) && (c->frequency < 824000000))
-		buf[3] = 0x0C;
-	else if ((c->frequency >= 824000000) && (c->frequency < 863000000))
-		buf[3] = 0x8C;
-	else
-		return -EINVAL;
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	i2c_transfer(card->i2c_adapter, &msg, 1);
-	return 0;
-}
-
-static struct nxt6000_config vp3021_alps_tded4_config = {
-	.demod_address = 0x0a,
-	.clock_inversion = 1,
-};
-
-static int digitv_alps_tded4_demod_init(struct dvb_frontend* fe)
-{
-	static u8 mt352_clock_config [] = { 0x89, 0x38, 0x2d };
-	static u8 mt352_reset [] = { 0x50, 0x80 };
-	static u8 mt352_adc_ctl_1_cfg [] = { 0x8E, 0x40 };
-	static u8 mt352_agc_cfg [] = { 0x67, 0x20, 0xa0 };
-	static u8 mt352_capt_range_cfg[] = { 0x75, 0x32 };
-
-	mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config));
-	udelay(2000);
-	mt352_write(fe, mt352_reset, sizeof(mt352_reset));
-	mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg));
-	mt352_write(fe, mt352_agc_cfg,sizeof(mt352_agc_cfg));
-	mt352_write(fe, mt352_capt_range_cfg, sizeof(mt352_capt_range_cfg));
-
-	return 0;
-}
-
-static int digitv_alps_tded4_tuner_calc_regs(struct dvb_frontend *fe,  u8 *pllbuf, int buf_len)
-{
-	u32 div;
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-
-	if (buf_len < 5)
-		return -EINVAL;
-
-	div = (((c->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
-
-	pllbuf[0] = 0x61;
-	pllbuf[1] = (div >> 8) & 0x7F;
-	pllbuf[2] = div & 0xFF;
-	pllbuf[3] = 0x85;
-
-	dprintk("frequency %u, div %u\n", c->frequency, div);
-
-	if (c->frequency < 470000000)
-		pllbuf[4] = 0x02;
-	else if (c->frequency > 823000000)
-		pllbuf[4] = 0x88;
-	else
-		pllbuf[4] = 0x08;
-
-	if (c->bandwidth_hz == 8000000)
-		pllbuf[4] |= 0x04;
-
-	return 5;
-}
-
-static void digitv_alps_tded4_reset(struct dvb_bt8xx_card *bt)
-{
-	/*
-	 * Reset the frontend, must be called before trying
-	 * to initialise the MT352 or mt352_attach
-	 * will fail. Same goes for the nxt6000 frontend.
-	 *
-	 */
-
-	int ret = bttv_gpio_enable(bt->bttv_nr, 0x08, 0x08);
-	if (ret != 0)
-		printk(KERN_WARNING "digitv_alps_tded4: Init Error - Can't Reset DVR (%i)\n", ret);
-
-	/* Pulse the reset line */
-	bttv_write_gpio(bt->bttv_nr, 0x08, 0x08); /* High */
-	bttv_write_gpio(bt->bttv_nr, 0x08, 0x00); /* Low  */
-	msleep(100);
-
-	bttv_write_gpio(bt->bttv_nr, 0x08, 0x08); /* High */
-}
-
-static struct mt352_config digitv_alps_tded4_config = {
-	.demod_address = 0x0a,
-	.demod_init = digitv_alps_tded4_demod_init,
-};
-
-static struct lgdt330x_config tdvs_tua6034_config = {
-	.demod_address    = 0x0e,
-	.demod_chip       = LGDT3303,
-	.serial_mpeg      = 0x40, /* TPSERIAL for 3303 in TOP_CONTROL */
-};
-
-static void lgdt330x_reset(struct dvb_bt8xx_card *bt)
-{
-	/* Set pin 27 of the lgdt3303 chip high to reset the frontend */
-
-	/* Pulse the reset line */
-	bttv_write_gpio(bt->bttv_nr, 0x00e00007, 0x00000001); /* High */
-	bttv_write_gpio(bt->bttv_nr, 0x00e00007, 0x00000000); /* Low  */
-	msleep(100);
-
-	bttv_write_gpio(bt->bttv_nr, 0x00e00007, 0x00000001); /* High */
-	msleep(100);
-}
-
-static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
-{
-	struct dst_state* state = NULL;
-
-	switch(type) {
-	case BTTV_BOARD_DVICO_DVBT_LITE:
-		card->fe = dvb_attach(mt352_attach, &thomson_dtt7579_config, card->i2c_adapter);
-
-		if (card->fe == NULL)
-			card->fe = dvb_attach(zl10353_attach, &thomson_dtt7579_zl10353_config,
-						  card->i2c_adapter);
-
-		if (card->fe != NULL) {
-			card->fe->ops.tuner_ops.calc_regs = thomson_dtt7579_tuner_calc_regs;
-			card->fe->ops.info.frequency_min = 174000000;
-			card->fe->ops.info.frequency_max = 862000000;
-		}
-		break;
-
-	case BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE:
-		lgdt330x_reset(card);
-		card->fe = dvb_attach(lgdt330x_attach, &tdvs_tua6034_config, card->i2c_adapter);
-		if (card->fe != NULL) {
-			dvb_attach(simple_tuner_attach, card->fe,
-				   card->i2c_adapter, 0x61,
-				   TUNER_LG_TDVS_H06XF);
-			dprintk ("dvb_bt8xx: lgdt330x detected\n");
-		}
-		break;
-
-	case BTTV_BOARD_NEBULA_DIGITV:
-		/*
-		 * It is possible to determine the correct frontend using the I2C bus (see the Nebula SDK);
-		 * this would be a cleaner solution than trying each frontend in turn.
-		 */
-
-		/* Old Nebula (marked (c)2003 on high profile pci card) has nxt6000 demod */
-		digitv_alps_tded4_reset(card);
-		card->fe = dvb_attach(nxt6000_attach, &vp3021_alps_tded4_config, card->i2c_adapter);
-		if (card->fe != NULL) {
-			card->fe->ops.tuner_ops.set_params = vp3021_alps_tded4_tuner_set_params;
-			dprintk ("dvb_bt8xx: an nxt6000 was detected on your digitv card\n");
-			break;
-		}
-
-		/* New Nebula (marked (c)2005 on low profile pci card) has mt352 demod */
-		digitv_alps_tded4_reset(card);
-		card->fe = dvb_attach(mt352_attach, &digitv_alps_tded4_config, card->i2c_adapter);
-
-		if (card->fe != NULL) {
-			card->fe->ops.tuner_ops.calc_regs = digitv_alps_tded4_tuner_calc_regs;
-			dprintk ("dvb_bt8xx: an mt352 was detected on your digitv card\n");
-		}
-		break;
-
-	case BTTV_BOARD_AVDVBT_761:
-		card->fe = dvb_attach(sp887x_attach, &microtune_mt7202dtf_config, card->i2c_adapter);
-		if (card->fe) {
-			card->fe->ops.tuner_ops.set_params = microtune_mt7202dtf_tuner_set_params;
-		}
-		break;
-
-	case BTTV_BOARD_AVDVBT_771:
-		card->fe = dvb_attach(mt352_attach, &advbt771_samsung_tdtc9251dh0_config, card->i2c_adapter);
-		if (card->fe != NULL) {
-			card->fe->ops.tuner_ops.calc_regs = advbt771_samsung_tdtc9251dh0_tuner_calc_regs;
-			card->fe->ops.info.frequency_min = 174000000;
-			card->fe->ops.info.frequency_max = 862000000;
-		}
-		break;
-
-	case BTTV_BOARD_TWINHAN_DST:
-		/*	DST is not a frontend driver !!!		*/
-		state = kmalloc(sizeof (struct dst_state), GFP_KERNEL);
-		if (!state) {
-			pr_err("No memory\n");
-			break;
-		}
-		/*	Setup the Card					*/
-		state->config = &dst_config;
-		state->i2c = card->i2c_adapter;
-		state->bt = card->bt;
-		state->dst_ca = NULL;
-		/*	DST is not a frontend, attaching the ASIC	*/
-		if (dvb_attach(dst_attach, state, &card->dvb_adapter) == NULL) {
-			pr_err("%s: Could not find a Twinhan DST\n", __func__);
-			break;
-		}
-		/*	Attach other DST peripherals if any		*/
-		/*	Conditional Access device			*/
-		card->fe = &state->frontend;
-		if (state->dst_hw_cap & DST_TYPE_HAS_CA)
-			dvb_attach(dst_ca_attach, state, &card->dvb_adapter);
-		break;
-
-	case BTTV_BOARD_PINNACLESAT:
-		card->fe = dvb_attach(cx24110_attach, &pctvsat_config, card->i2c_adapter);
-		if (card->fe) {
-			card->fe->ops.tuner_ops.init = pinnsat_tuner_init;
-			card->fe->ops.tuner_ops.sleep = pinnsat_tuner_sleep;
-			card->fe->ops.tuner_ops.set_params = cx24108_tuner_set_params;
-		}
-		break;
-
-	case BTTV_BOARD_PC_HDTV:
-		card->fe = dvb_attach(or51211_attach, &or51211_config, card->i2c_adapter);
-		if (card->fe != NULL)
-			dvb_attach(simple_tuner_attach, card->fe,
-				   card->i2c_adapter, 0x61,
-				   TUNER_PHILIPS_FCV1236D);
-		break;
-	}
-
-	if (card->fe == NULL)
-		pr_err("A frontend driver was not found for device [%04x:%04x] subsystem [%04x:%04x]\n",
-		       card->bt->dev->vendor,
-		       card->bt->dev->device,
-		       card->bt->dev->subsystem_vendor,
-		       card->bt->dev->subsystem_device);
-	else
-		if (dvb_register_frontend(&card->dvb_adapter, card->fe)) {
-			pr_err("Frontend registration failed!\n");
-			dvb_frontend_detach(card->fe);
-			card->fe = NULL;
-		}
-}
-
-static int __devinit dvb_bt8xx_load_card(struct dvb_bt8xx_card *card, u32 type)
-{
-	int result;
-
-	result = dvb_register_adapter(&card->dvb_adapter, card->card_name,
-				      THIS_MODULE, &card->bt->dev->dev,
-				      adapter_nr);
-	if (result < 0) {
-		pr_err("dvb_register_adapter failed (errno = %d)\n", result);
-		return result;
-	}
-	card->dvb_adapter.priv = card;
-
-	card->bt->adapter = card->i2c_adapter;
-
-	memset(&card->demux, 0, sizeof(struct dvb_demux));
-
-	card->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING | DMX_MEMORY_BASED_FILTERING;
-
-	card->demux.priv = card;
-	card->demux.filternum = 256;
-	card->demux.feednum = 256;
-	card->demux.start_feed = dvb_bt8xx_start_feed;
-	card->demux.stop_feed = dvb_bt8xx_stop_feed;
-	card->demux.write_to_decoder = NULL;
-
-	result = dvb_dmx_init(&card->demux);
-	if (result < 0) {
-		pr_err("dvb_dmx_init failed (errno = %d)\n", result);
-		goto err_unregister_adaptor;
-	}
-
-	card->dmxdev.filternum = 256;
-	card->dmxdev.demux = &card->demux.dmx;
-	card->dmxdev.capabilities = 0;
-
-	result = dvb_dmxdev_init(&card->dmxdev, &card->dvb_adapter);
-	if (result < 0) {
-		pr_err("dvb_dmxdev_init failed (errno = %d)\n", result);
-		goto err_dmx_release;
-	}
-
-	card->fe_hw.source = DMX_FRONTEND_0;
-
-	result = card->demux.dmx.add_frontend(&card->demux.dmx, &card->fe_hw);
-	if (result < 0) {
-		pr_err("dvb_dmx_init failed (errno = %d)\n", result);
-		goto err_dmxdev_release;
-	}
-
-	card->fe_mem.source = DMX_MEMORY_FE;
-
-	result = card->demux.dmx.add_frontend(&card->demux.dmx, &card->fe_mem);
-	if (result < 0) {
-		pr_err("dvb_dmx_init failed (errno = %d)\n", result);
-		goto err_remove_hw_frontend;
-	}
-
-	result = card->demux.dmx.connect_frontend(&card->demux.dmx, &card->fe_hw);
-	if (result < 0) {
-		pr_err("dvb_dmx_init failed (errno = %d)\n", result);
-		goto err_remove_mem_frontend;
-	}
-
-	result = dvb_net_init(&card->dvb_adapter, &card->dvbnet, &card->demux.dmx);
-	if (result < 0) {
-		pr_err("dvb_net_init failed (errno = %d)\n", result);
-		goto err_disconnect_frontend;
-	}
-
-	tasklet_init(&card->bt->tasklet, dvb_bt8xx_task, (unsigned long) card);
-
-	frontend_init(card, type);
-
-	return 0;
-
-err_disconnect_frontend:
-	card->demux.dmx.disconnect_frontend(&card->demux.dmx);
-err_remove_mem_frontend:
-	card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_mem);
-err_remove_hw_frontend:
-	card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_hw);
-err_dmxdev_release:
-	dvb_dmxdev_release(&card->dmxdev);
-err_dmx_release:
-	dvb_dmx_release(&card->demux);
-err_unregister_adaptor:
-	dvb_unregister_adapter(&card->dvb_adapter);
-	return result;
-}
-
-static int __devinit dvb_bt8xx_probe(struct bttv_sub_device *sub)
-{
-	struct dvb_bt8xx_card *card;
-	struct pci_dev* bttv_pci_dev;
-	int ret;
-
-	if (!(card = kzalloc(sizeof(struct dvb_bt8xx_card), GFP_KERNEL)))
-		return -ENOMEM;
-
-	mutex_init(&card->lock);
-	card->bttv_nr = sub->core->nr;
-	strlcpy(card->card_name, sub->core->v4l2_dev.name, sizeof(card->card_name));
-	card->i2c_adapter = &sub->core->i2c_adap;
-
-	switch(sub->core->type) {
-	case BTTV_BOARD_PINNACLESAT:
-		card->gpio_mode = 0x0400c060;
-		/* should be: BT878_A_GAIN=0,BT878_A_PWRDN,BT878_DA_DPM,BT878_DA_SBR,
-			      BT878_DA_IOM=1,BT878_DA_APP to enable serial highspeed mode. */
-		card->op_sync_orin = BT878_RISC_SYNC_MASK;
-		card->irq_err_ignore = BT878_AFBUS | BT878_AFDSR;
-		break;
-
-	case BTTV_BOARD_DVICO_DVBT_LITE:
-		card->gpio_mode = 0x0400C060;
-		card->op_sync_orin = BT878_RISC_SYNC_MASK;
-		card->irq_err_ignore = BT878_AFBUS | BT878_AFDSR;
-		/* 26, 15, 14, 6, 5
-		 * A_PWRDN  DA_DPM DA_SBR DA_IOM_DA
-		 * DA_APP(parallel) */
-		break;
-
-	case BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE:
-		card->gpio_mode = 0x0400c060;
-		card->op_sync_orin = BT878_RISC_SYNC_MASK;
-		card->irq_err_ignore = BT878_AFBUS | BT878_AFDSR;
-		break;
-
-	case BTTV_BOARD_NEBULA_DIGITV:
-	case BTTV_BOARD_AVDVBT_761:
-		card->gpio_mode = (1 << 26) | (1 << 14) | (1 << 5);
-		card->op_sync_orin = BT878_RISC_SYNC_MASK;
-		card->irq_err_ignore = BT878_AFBUS | BT878_AFDSR;
-		/* A_PWRDN DA_SBR DA_APP (high speed serial) */
-		break;
-
-	case BTTV_BOARD_AVDVBT_771: //case 0x07711461:
-		card->gpio_mode = 0x0400402B;
-		card->op_sync_orin = BT878_RISC_SYNC_MASK;
-		card->irq_err_ignore = BT878_AFBUS | BT878_AFDSR;
-		/* A_PWRDN DA_SBR  DA_APP[0] PKTP=10 RISC_ENABLE FIFO_ENABLE*/
-		break;
-
-	case BTTV_BOARD_TWINHAN_DST:
-		card->gpio_mode = 0x2204f2c;
-		card->op_sync_orin = BT878_RISC_SYNC_MASK;
-		card->irq_err_ignore = BT878_APABORT | BT878_ARIPERR |
-				       BT878_APPERR | BT878_AFBUS;
-		/* 25,21,14,11,10,9,8,3,2 then
-		 * 0x33 = 5,4,1,0
-		 * A_SEL=SML, DA_MLB, DA_SBR,
-		 * DA_SDR=f, fifo trigger = 32 DWORDS
-		 * IOM = 0 == audio A/D
-		 * DPM = 0 == digital audio mode
-		 * == async data parallel port
-		 * then 0x33 (13 is set by start_capture)
-		 * DA_APP = async data parallel port,
-		 * ACAP_EN = 1,
-		 * RISC+FIFO ENABLE */
-		break;
-
-	case BTTV_BOARD_PC_HDTV:
-		card->gpio_mode = 0x0100EC7B;
-		card->op_sync_orin = BT878_RISC_SYNC_MASK;
-		card->irq_err_ignore = BT878_AFBUS | BT878_AFDSR;
-		break;
-
-	default:
-		pr_err("Unknown bttv card type: %d\n", sub->core->type);
-		kfree(card);
-		return -ENODEV;
-	}
-
-	dprintk("dvb_bt8xx: identified card%d as %s\n", card->bttv_nr, card->card_name);
-
-	if (!(bttv_pci_dev = bttv_get_pcidev(card->bttv_nr))) {
-		pr_err("no pci device for card %d\n", card->bttv_nr);
-		kfree(card);
-		return -ENODEV;
-	}
-
-	if (!(card->bt = dvb_bt8xx_878_match(card->bttv_nr, bttv_pci_dev))) {
-		pr_err("unable to determine DMA core of card %d,\n", card->bttv_nr);
-		pr_err("if you have the ALSA bt87x audio driver installed, try removing it.\n");
-
-		kfree(card);
-		return -ENODEV;
-	}
-
-	mutex_init(&card->bt->gpio_lock);
-	card->bt->bttv_nr = sub->core->nr;
-
-	if ( (ret = dvb_bt8xx_load_card(card, sub->core->type)) ) {
-		kfree(card);
-		return ret;
-	}
-
-	dev_set_drvdata(&sub->dev, card);
-	return 0;
-}
-
-static void dvb_bt8xx_remove(struct bttv_sub_device *sub)
-{
-	struct dvb_bt8xx_card *card = dev_get_drvdata(&sub->dev);
-
-	dprintk("dvb_bt8xx: unloading card%d\n", card->bttv_nr);
-
-	bt878_stop(card->bt);
-	tasklet_kill(&card->bt->tasklet);
-	dvb_net_release(&card->dvbnet);
-	card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_mem);
-	card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_hw);
-	dvb_dmxdev_release(&card->dmxdev);
-	dvb_dmx_release(&card->demux);
-	if (card->fe) {
-		dvb_unregister_frontend(card->fe);
-		dvb_frontend_detach(card->fe);
-	}
-	dvb_unregister_adapter(&card->dvb_adapter);
-
-	kfree(card);
-}
-
-static struct bttv_sub_driver driver = {
-	.drv = {
-		.name		= "dvb-bt8xx",
-	},
-	.probe		= dvb_bt8xx_probe,
-	.remove		= dvb_bt8xx_remove,
-	/* FIXME:
-	 * .shutdown	= dvb_bt8xx_shutdown,
-	 * .suspend	= dvb_bt8xx_suspend,
-	 * .resume	= dvb_bt8xx_resume,
-	 */
-};
-
-static int __init dvb_bt8xx_init(void)
-{
-	return bttv_sub_register(&driver, "dvb");
-}
-
-static void __exit dvb_bt8xx_exit(void)
-{
-	bttv_sub_unregister(&driver);
-}
-
-module_init(dvb_bt8xx_init);
-module_exit(dvb_bt8xx_exit);
-
-MODULE_DESCRIPTION("Bt8xx based DVB adapter driver");
-MODULE_AUTHOR("Florian Schirmer <jolt@tuxbox.org>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.h b/drivers/media/dvb/bt8xx/dvb-bt8xx.h
deleted file mode 100644
index 4499ed2..0000000
--- a/drivers/media/dvb/bt8xx/dvb-bt8xx.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Bt8xx based DVB adapter driver
- *
- * Copyright (C) 2002,2003 Florian Schirmer <jolt@tuxbox.org>
- * Copyright (C) 2002 Peter Hettkamp <peter.hettkamp@htp-tel.de>
- * Copyright (C) 1999-2001 Ralph  Metzler & Marcus Metzler for convergence integrated media GmbH
- * Copyright (C) 1998,1999 Christian Theiss <mistert@rz.fh-augsburg.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 DVB_BT8XX_H
-#define DVB_BT8XX_H
-
-#include <linux/i2c.h>
-#include <linux/mutex.h>
-#include "dvbdev.h"
-#include "dvb_net.h"
-#include "bttv.h"
-#include "mt352.h"
-#include "sp887x.h"
-#include "dst_common.h"
-#include "nxt6000.h"
-#include "cx24110.h"
-#include "or51211.h"
-#include "lgdt330x.h"
-#include "zl10353.h"
-#include "tuner-simple.h"
-
-struct dvb_bt8xx_card {
-	struct mutex lock;
-	int nfeeds;
-	char card_name[32];
-	struct dvb_adapter dvb_adapter;
-	struct bt878 *bt;
-	unsigned int bttv_nr;
-	struct dvb_demux demux;
-	struct dmxdev dmxdev;
-	struct dmx_frontend fe_hw;
-	struct dmx_frontend fe_mem;
-	u32 gpio_mode;
-	u32 op_sync_orin;
-	u32 irq_err_ignore;
-	struct i2c_adapter *i2c_adapter;
-	struct dvb_net dvbnet;
-
-	struct dvb_frontend* fe;
-};
-
-#endif /* DVB_BT8XX_H */
diff --git a/drivers/media/dvb/ddbridge/Kconfig b/drivers/media/dvb/ddbridge/Kconfig
deleted file mode 100644
index d099e1a..0000000
--- a/drivers/media/dvb/ddbridge/Kconfig
+++ /dev/null
@@ -1,18 +0,0 @@
-config DVB_DDBRIDGE
-	tristate "Digital Devices bridge support"
-	depends on DVB_CORE && PCI && I2C
-	select DVB_LNBP21 if !DVB_FE_CUSTOMISE
-	select DVB_STV6110x if !DVB_FE_CUSTOMISE
-	select DVB_STV090x if !DVB_FE_CUSTOMISE
-	select DVB_DRXK if !DVB_FE_CUSTOMISE
-	select DVB_TDA18271C2DD if !DVB_FE_CUSTOMISE
-	---help---
-	  Support for cards with the Digital Devices PCI express bridge:
-	  - Octopus PCIe Bridge
-	  - Octopus mini PCIe Bridge
-	  - Octopus LE
-	  - DuoFlex S2 Octopus
-	  - DuoFlex CT Octopus
-	  - cineS2(v6)
-
-	  Say Y if you own such a card and want to use it.
diff --git a/drivers/media/dvb/ddbridge/Makefile b/drivers/media/dvb/ddbridge/Makefile
deleted file mode 100644
index 38019ba..0000000
--- a/drivers/media/dvb/ddbridge/Makefile
+++ /dev/null
@@ -1,14 +0,0 @@
-#
-# Makefile for the ddbridge device driver
-#
-
-ddbridge-objs := ddbridge-core.o
-
-obj-$(CONFIG_DVB_DDBRIDGE) += ddbridge.o
-
-ccflags-y += -Idrivers/media/dvb/dvb-core/
-ccflags-y += -Idrivers/media/dvb/frontends/
-ccflags-y += -Idrivers/media/common/tuners/
-
-# For the staging CI driver cxd2099
-ccflags-y += -Idrivers/staging/media/cxd2099/
diff --git a/drivers/media/dvb/ddbridge/ddbridge-core.c b/drivers/media/dvb/ddbridge/ddbridge-core.c
deleted file mode 100644
index ebf3f05..0000000
--- a/drivers/media/dvb/ddbridge/ddbridge-core.c
+++ /dev/null
@@ -1,1723 +0,0 @@
-/*
- * ddbridge.c: Digital Devices PCIe bridge driver
- *
- * Copyright (C) 2010-2011 Digital Devices GmbH
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 only, as published by the Free Software Foundation.
- *
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/poll.h>
-#include <linux/io.h>
-#include <linux/pci.h>
-#include <linux/pci_ids.h>
-#include <linux/timer.h>
-#include <linux/i2c.h>
-#include <linux/swab.h>
-#include <linux/vmalloc.h>
-#include "ddbridge.h"
-
-#include "ddbridge-regs.h"
-
-#include "tda18271c2dd.h"
-#include "stv6110x.h"
-#include "stv090x.h"
-#include "lnbh24.h"
-#include "drxk.h"
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-/* MSI had problems with lost interrupts, fixed but needs testing */
-#undef CONFIG_PCI_MSI
-
-/******************************************************************************/
-
-static int i2c_read(struct i2c_adapter *adapter, u8 adr, u8 *val)
-{
-	struct i2c_msg msgs[1] = {{.addr = adr,  .flags = I2C_M_RD,
-				   .buf  = val,  .len   = 1 } };
-	return (i2c_transfer(adapter, msgs, 1) == 1) ? 0 : -1;
-}
-
-static int i2c_read_reg(struct i2c_adapter *adapter, u8 adr, u8 reg, u8 *val)
-{
-	struct i2c_msg msgs[2] = {{.addr = adr,  .flags = 0,
-				   .buf  = &reg, .len   = 1 },
-				  {.addr = adr,  .flags = I2C_M_RD,
-				   .buf  = val,  .len   = 1 } };
-	return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1;
-}
-
-static int i2c_read_reg16(struct i2c_adapter *adapter, u8 adr,
-			  u16 reg, u8 *val)
-{
-	u8 msg[2] = {reg>>8, reg&0xff};
-	struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0,
-				   .buf  = msg, .len   = 2},
-				  {.addr = adr, .flags = I2C_M_RD,
-				   .buf  = val, .len   = 1} };
-	return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1;
-}
-
-static int ddb_i2c_cmd(struct ddb_i2c *i2c, u32 adr, u32 cmd)
-{
-	struct ddb *dev = i2c->dev;
-	int stat;
-	u32 val;
-
-	i2c->done = 0;
-	ddbwritel((adr << 9) | cmd, i2c->regs + I2C_COMMAND);
-	stat = wait_event_timeout(i2c->wq, i2c->done == 1, HZ);
-	if (stat <= 0) {
-		printk(KERN_ERR "I2C timeout\n");
-		{ /* MSI debugging*/
-			u32 istat = ddbreadl(INTERRUPT_STATUS);
-			printk(KERN_ERR "IRS %08x\n", istat);
-			ddbwritel(istat, INTERRUPT_ACK);
-		}
-		return -EIO;
-	}
-	val = ddbreadl(i2c->regs+I2C_COMMAND);
-	if (val & 0x70000)
-		return -EIO;
-	return 0;
-}
-
-static int ddb_i2c_master_xfer(struct i2c_adapter *adapter,
-			       struct i2c_msg msg[], int num)
-{
-	struct ddb_i2c *i2c = (struct ddb_i2c *)i2c_get_adapdata(adapter);
-	struct ddb *dev = i2c->dev;
-	u8 addr = 0;
-
-	if (num)
-		addr = msg[0].addr;
-
-	if (num == 2 && msg[1].flags & I2C_M_RD &&
-	    !(msg[0].flags & I2C_M_RD)) {
-		memcpy_toio(dev->regs + I2C_TASKMEM_BASE + i2c->wbuf,
-			    msg[0].buf, msg[0].len);
-		ddbwritel(msg[0].len|(msg[1].len << 16),
-			  i2c->regs+I2C_TASKLENGTH);
-		if (!ddb_i2c_cmd(i2c, addr, 1)) {
-			memcpy_fromio(msg[1].buf,
-				      dev->regs + I2C_TASKMEM_BASE + i2c->rbuf,
-				      msg[1].len);
-			return num;
-		}
-	}
-
-	if (num == 1 && !(msg[0].flags & I2C_M_RD)) {
-		ddbcpyto(I2C_TASKMEM_BASE + i2c->wbuf, msg[0].buf, msg[0].len);
-		ddbwritel(msg[0].len, i2c->regs + I2C_TASKLENGTH);
-		if (!ddb_i2c_cmd(i2c, addr, 2))
-			return num;
-	}
-	if (num == 1 && (msg[0].flags & I2C_M_RD)) {
-		ddbwritel(msg[0].len << 16, i2c->regs + I2C_TASKLENGTH);
-		if (!ddb_i2c_cmd(i2c, addr, 3)) {
-			ddbcpyfrom(msg[0].buf,
-				   I2C_TASKMEM_BASE + i2c->rbuf, msg[0].len);
-			return num;
-		}
-	}
-	return -EIO;
-}
-
-
-static u32 ddb_i2c_functionality(struct i2c_adapter *adap)
-{
-	return I2C_FUNC_SMBUS_EMUL;
-}
-
-struct i2c_algorithm ddb_i2c_algo = {
-	.master_xfer   = ddb_i2c_master_xfer,
-	.functionality = ddb_i2c_functionality,
-};
-
-static void ddb_i2c_release(struct ddb *dev)
-{
-	int i;
-	struct ddb_i2c *i2c;
-	struct i2c_adapter *adap;
-
-	for (i = 0; i < dev->info->port_num; i++) {
-		i2c = &dev->i2c[i];
-		adap = &i2c->adap;
-		i2c_del_adapter(adap);
-	}
-}
-
-static int ddb_i2c_init(struct ddb *dev)
-{
-	int i, j, stat = 0;
-	struct ddb_i2c *i2c;
-	struct i2c_adapter *adap;
-
-	for (i = 0; i < dev->info->port_num; i++) {
-		i2c = &dev->i2c[i];
-		i2c->dev = dev;
-		i2c->nr = i;
-		i2c->wbuf = i * (I2C_TASKMEM_SIZE / 4);
-		i2c->rbuf = i2c->wbuf + (I2C_TASKMEM_SIZE / 8);
-		i2c->regs = 0x80 + i * 0x20;
-		ddbwritel(I2C_SPEED_100, i2c->regs + I2C_TIMING);
-		ddbwritel((i2c->rbuf << 16) | i2c->wbuf,
-			  i2c->regs + I2C_TASKADDRESS);
-		init_waitqueue_head(&i2c->wq);
-
-		adap = &i2c->adap;
-		i2c_set_adapdata(adap, i2c);
-#ifdef I2C_ADAP_CLASS_TV_DIGITAL
-		adap->class = I2C_ADAP_CLASS_TV_DIGITAL|I2C_CLASS_TV_ANALOG;
-#else
-#ifdef I2C_CLASS_TV_ANALOG
-		adap->class = I2C_CLASS_TV_ANALOG;
-#endif
-#endif
-		strcpy(adap->name, "ddbridge");
-		adap->algo = &ddb_i2c_algo;
-		adap->algo_data = (void *)i2c;
-		adap->dev.parent = &dev->pdev->dev;
-		stat = i2c_add_adapter(adap);
-		if (stat)
-			break;
-	}
-	if (stat)
-		for (j = 0; j < i; j++) {
-			i2c = &dev->i2c[j];
-			adap = &i2c->adap;
-			i2c_del_adapter(adap);
-		}
-	return stat;
-}
-
-
-/******************************************************************************/
-/******************************************************************************/
-/******************************************************************************/
-
-#if 0
-static void set_table(struct ddb *dev, u32 off,
-		      dma_addr_t *pbuf, u32 num)
-{
-	u32 i, base;
-	u64 mem;
-
-	base = DMA_BASE_ADDRESS_TABLE + off;
-	for (i = 0; i < num; i++) {
-		mem = pbuf[i];
-		ddbwritel(mem & 0xffffffff, base + i * 8);
-		ddbwritel(mem >> 32, base + i * 8 + 4);
-	}
-}
-#endif
-
-static void ddb_address_table(struct ddb *dev)
-{
-	u32 i, j, base;
-	u64 mem;
-	dma_addr_t *pbuf;
-
-	for (i = 0; i < dev->info->port_num * 2; i++) {
-		base = DMA_BASE_ADDRESS_TABLE + i * 0x100;
-		pbuf = dev->input[i].pbuf;
-		for (j = 0; j < dev->input[i].dma_buf_num; j++) {
-			mem = pbuf[j];
-			ddbwritel(mem & 0xffffffff, base + j * 8);
-			ddbwritel(mem >> 32, base + j * 8 + 4);
-		}
-	}
-	for (i = 0; i < dev->info->port_num; i++) {
-		base = DMA_BASE_ADDRESS_TABLE + 0x800 + i * 0x100;
-		pbuf = dev->output[i].pbuf;
-		for (j = 0; j < dev->output[i].dma_buf_num; j++) {
-			mem = pbuf[j];
-			ddbwritel(mem & 0xffffffff, base + j * 8);
-			ddbwritel(mem >> 32, base + j * 8 + 4);
-		}
-	}
-}
-
-static void io_free(struct pci_dev *pdev, u8 **vbuf,
-		    dma_addr_t *pbuf, u32 size, int num)
-{
-	int i;
-
-	for (i = 0; i < num; i++) {
-		if (vbuf[i]) {
-			pci_free_consistent(pdev, size, vbuf[i], pbuf[i]);
-			vbuf[i] = 0;
-		}
-	}
-}
-
-static int io_alloc(struct pci_dev *pdev, u8 **vbuf,
-		    dma_addr_t *pbuf, u32 size, int num)
-{
-	int i;
-
-	for (i = 0; i < num; i++) {
-		vbuf[i] = pci_alloc_consistent(pdev, size, &pbuf[i]);
-		if (!vbuf[i])
-			return -ENOMEM;
-	}
-	return 0;
-}
-
-static int ddb_buffers_alloc(struct ddb *dev)
-{
-	int i;
-	struct ddb_port *port;
-
-	for (i = 0; i < dev->info->port_num; i++) {
-		port = &dev->port[i];
-		switch (port->class) {
-		case DDB_PORT_TUNER:
-			if (io_alloc(dev->pdev, port->input[0]->vbuf,
-				     port->input[0]->pbuf,
-				     port->input[0]->dma_buf_size,
-				     port->input[0]->dma_buf_num) < 0)
-				return -1;
-			if (io_alloc(dev->pdev, port->input[1]->vbuf,
-				     port->input[1]->pbuf,
-				     port->input[1]->dma_buf_size,
-				     port->input[1]->dma_buf_num) < 0)
-				return -1;
-			break;
-		case DDB_PORT_CI:
-			if (io_alloc(dev->pdev, port->input[0]->vbuf,
-				     port->input[0]->pbuf,
-				     port->input[0]->dma_buf_size,
-				     port->input[0]->dma_buf_num) < 0)
-				return -1;
-			if (io_alloc(dev->pdev, port->output->vbuf,
-				     port->output->pbuf,
-				     port->output->dma_buf_size,
-				     port->output->dma_buf_num) < 0)
-				return -1;
-			break;
-		default:
-			break;
-		}
-	}
-	ddb_address_table(dev);
-	return 0;
-}
-
-static void ddb_buffers_free(struct ddb *dev)
-{
-	int i;
-	struct ddb_port *port;
-
-	for (i = 0; i < dev->info->port_num; i++) {
-		port = &dev->port[i];
-		io_free(dev->pdev, port->input[0]->vbuf,
-			port->input[0]->pbuf,
-			port->input[0]->dma_buf_size,
-			port->input[0]->dma_buf_num);
-		io_free(dev->pdev, port->input[1]->vbuf,
-			port->input[1]->pbuf,
-			port->input[1]->dma_buf_size,
-			port->input[1]->dma_buf_num);
-		io_free(dev->pdev, port->output->vbuf,
-			port->output->pbuf,
-			port->output->dma_buf_size,
-			port->output->dma_buf_num);
-	}
-}
-
-static void ddb_input_start(struct ddb_input *input)
-{
-	struct ddb *dev = input->port->dev;
-
-	spin_lock_irq(&input->lock);
-	input->cbuf = 0;
-	input->coff = 0;
-
-	/* reset */
-	ddbwritel(0, TS_INPUT_CONTROL(input->nr));
-	ddbwritel(2, TS_INPUT_CONTROL(input->nr));
-	ddbwritel(0, TS_INPUT_CONTROL(input->nr));
-
-	ddbwritel((1 << 16) |
-		  (input->dma_buf_num << 11) |
-		  (input->dma_buf_size >> 7),
-		  DMA_BUFFER_SIZE(input->nr));
-	ddbwritel(0, DMA_BUFFER_ACK(input->nr));
-
-	ddbwritel(1, DMA_BASE_WRITE);
-	ddbwritel(3, DMA_BUFFER_CONTROL(input->nr));
-	ddbwritel(9, TS_INPUT_CONTROL(input->nr));
-	input->running = 1;
-	spin_unlock_irq(&input->lock);
-}
-
-static void ddb_input_stop(struct ddb_input *input)
-{
-	struct ddb *dev = input->port->dev;
-
-	spin_lock_irq(&input->lock);
-	ddbwritel(0, TS_INPUT_CONTROL(input->nr));
-	ddbwritel(0, DMA_BUFFER_CONTROL(input->nr));
-	input->running = 0;
-	spin_unlock_irq(&input->lock);
-}
-
-static void ddb_output_start(struct ddb_output *output)
-{
-	struct ddb *dev = output->port->dev;
-
-	spin_lock_irq(&output->lock);
-	output->cbuf = 0;
-	output->coff = 0;
-	ddbwritel(0, TS_OUTPUT_CONTROL(output->nr));
-	ddbwritel(2, TS_OUTPUT_CONTROL(output->nr));
-	ddbwritel(0, TS_OUTPUT_CONTROL(output->nr));
-	ddbwritel(0x3c, TS_OUTPUT_CONTROL(output->nr));
-	ddbwritel((1 << 16) |
-		  (output->dma_buf_num << 11) |
-		  (output->dma_buf_size >> 7),
-		  DMA_BUFFER_SIZE(output->nr + 8));
-	ddbwritel(0, DMA_BUFFER_ACK(output->nr + 8));
-
-	ddbwritel(1, DMA_BASE_READ);
-	ddbwritel(3, DMA_BUFFER_CONTROL(output->nr + 8));
-	/* ddbwritel(0xbd, TS_OUTPUT_CONTROL(output->nr)); */
-	ddbwritel(0x1d, TS_OUTPUT_CONTROL(output->nr));
-	output->running = 1;
-	spin_unlock_irq(&output->lock);
-}
-
-static void ddb_output_stop(struct ddb_output *output)
-{
-	struct ddb *dev = output->port->dev;
-
-	spin_lock_irq(&output->lock);
-	ddbwritel(0, TS_OUTPUT_CONTROL(output->nr));
-	ddbwritel(0, DMA_BUFFER_CONTROL(output->nr + 8));
-	output->running = 0;
-	spin_unlock_irq(&output->lock);
-}
-
-static u32 ddb_output_free(struct ddb_output *output)
-{
-	u32 idx, off, stat = output->stat;
-	s32 diff;
-
-	idx = (stat >> 11) & 0x1f;
-	off = (stat & 0x7ff) << 7;
-
-	if (output->cbuf != idx) {
-		if ((((output->cbuf + 1) % output->dma_buf_num) == idx) &&
-		    (output->dma_buf_size - output->coff <= 188))
-			return 0;
-		return 188;
-	}
-	diff = off - output->coff;
-	if (diff <= 0 || diff > 188)
-		return 188;
-	return 0;
-}
-
-static ssize_t ddb_output_write(struct ddb_output *output,
-				const u8 *buf, size_t count)
-{
-	struct ddb *dev = output->port->dev;
-	u32 idx, off, stat = output->stat;
-	u32 left = count, len;
-
-	idx = (stat >> 11) & 0x1f;
-	off = (stat & 0x7ff) << 7;
-
-	while (left) {
-		len = output->dma_buf_size - output->coff;
-		if ((((output->cbuf + 1) % output->dma_buf_num) == idx) &&
-		    (off == 0)) {
-			if (len <= 188)
-				break;
-			len -= 188;
-		}
-		if (output->cbuf == idx) {
-			if (off > output->coff) {
-#if 1
-				len = off - output->coff;
-				len -= (len % 188);
-				if (len <= 188)
-
-#endif
-					break;
-				len -= 188;
-			}
-		}
-		if (len > left)
-			len = left;
-		if (copy_from_user(output->vbuf[output->cbuf] + output->coff,
-				   buf, len))
-			return -EIO;
-		left -= len;
-		buf += len;
-		output->coff += len;
-		if (output->coff == output->dma_buf_size) {
-			output->coff = 0;
-			output->cbuf = ((output->cbuf + 1) % output->dma_buf_num);
-		}
-		ddbwritel((output->cbuf << 11) | (output->coff >> 7),
-			  DMA_BUFFER_ACK(output->nr + 8));
-	}
-	return count - left;
-}
-
-static u32 ddb_input_avail(struct ddb_input *input)
-{
-	struct ddb *dev = input->port->dev;
-	u32 idx, off, stat = input->stat;
-	u32 ctrl = ddbreadl(DMA_BUFFER_CONTROL(input->nr));
-
-	idx = (stat >> 11) & 0x1f;
-	off = (stat & 0x7ff) << 7;
-
-	if (ctrl & 4) {
-		printk(KERN_ERR "IA %d %d %08x\n", idx, off, ctrl);
-		ddbwritel(input->stat, DMA_BUFFER_ACK(input->nr));
-		return 0;
-	}
-	if (input->cbuf != idx)
-		return 188;
-	return 0;
-}
-
-static ssize_t ddb_input_read(struct ddb_input *input, u8 *buf, size_t count)
-{
-	struct ddb *dev = input->port->dev;
-	u32 left = count;
-	u32 idx, free, stat = input->stat;
-	int ret;
-
-	idx = (stat >> 11) & 0x1f;
-
-	while (left) {
-		if (input->cbuf == idx)
-			return count - left;
-		free = input->dma_buf_size - input->coff;
-		if (free > left)
-			free = left;
-		ret = copy_to_user(buf, input->vbuf[input->cbuf] +
-				   input->coff, free);
-		if (ret)
-			return -EFAULT;
-		input->coff += free;
-		if (input->coff == input->dma_buf_size) {
-			input->coff = 0;
-			input->cbuf = (input->cbuf+1) % input->dma_buf_num;
-		}
-		left -= free;
-		ddbwritel((input->cbuf << 11) | (input->coff >> 7),
-			  DMA_BUFFER_ACK(input->nr));
-	}
-	return count;
-}
-
-/******************************************************************************/
-/******************************************************************************/
-/******************************************************************************/
-
-#if 0
-static struct ddb_input *fe2input(struct ddb *dev, struct dvb_frontend *fe)
-{
-	int i;
-
-	for (i = 0; i < dev->info->port_num * 2; i++) {
-		if (dev->input[i].fe == fe)
-			return &dev->input[i];
-	}
-	return NULL;
-}
-#endif
-
-static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable)
-{
-	struct ddb_input *input = fe->sec_priv;
-	struct ddb_port *port = input->port;
-	int status;
-
-	if (enable) {
-		mutex_lock(&port->i2c_gate_lock);
-		status = input->gate_ctrl(fe, 1);
-	} else {
-		status = input->gate_ctrl(fe, 0);
-		mutex_unlock(&port->i2c_gate_lock);
-	}
-	return status;
-}
-
-static int demod_attach_drxk(struct ddb_input *input)
-{
-	struct i2c_adapter *i2c = &input->port->i2c->adap;
-	struct dvb_frontend *fe;
-	struct drxk_config config;
-
-	memset(&config, 0, sizeof(config));
-	config.microcode_name = "drxk_a3.mc";
-	config.qam_demod_parameter_count = 4;
-	config.adr = 0x29 + (input->nr & 1);
-
-	fe = input->fe = dvb_attach(drxk_attach, &config, i2c);
-	if (!input->fe) {
-		printk(KERN_ERR "No DRXK found!\n");
-		return -ENODEV;
-	}
-	fe->sec_priv = input;
-	input->gate_ctrl = fe->ops.i2c_gate_ctrl;
-	fe->ops.i2c_gate_ctrl = drxk_gate_ctrl;
-	return 0;
-}
-
-static int tuner_attach_tda18271(struct ddb_input *input)
-{
-	struct i2c_adapter *i2c = &input->port->i2c->adap;
-	struct dvb_frontend *fe;
-
-	if (input->fe->ops.i2c_gate_ctrl)
-		input->fe->ops.i2c_gate_ctrl(input->fe, 1);
-	fe = dvb_attach(tda18271c2dd_attach, input->fe, i2c, 0x60);
-	if (!fe) {
-		printk(KERN_ERR "No TDA18271 found!\n");
-		return -ENODEV;
-	}
-	if (input->fe->ops.i2c_gate_ctrl)
-		input->fe->ops.i2c_gate_ctrl(input->fe, 0);
-	return 0;
-}
-
-/******************************************************************************/
-/******************************************************************************/
-/******************************************************************************/
-
-static struct stv090x_config stv0900 = {
-	.device         = STV0900,
-	.demod_mode     = STV090x_DUAL,
-	.clk_mode       = STV090x_CLK_EXT,
-
-	.xtal           = 27000000,
-	.address        = 0x69,
-
-	.ts1_mode       = STV090x_TSMODE_SERIAL_PUNCTURED,
-	.ts2_mode       = STV090x_TSMODE_SERIAL_PUNCTURED,
-
-	.repeater_level = STV090x_RPTLEVEL_16,
-
-	.adc1_range	= STV090x_ADC_1Vpp,
-	.adc2_range	= STV090x_ADC_1Vpp,
-
-	.diseqc_envelope_mode = true,
-};
-
-static struct stv090x_config stv0900_aa = {
-	.device         = STV0900,
-	.demod_mode     = STV090x_DUAL,
-	.clk_mode       = STV090x_CLK_EXT,
-
-	.xtal           = 27000000,
-	.address        = 0x68,
-
-	.ts1_mode       = STV090x_TSMODE_SERIAL_PUNCTURED,
-	.ts2_mode       = STV090x_TSMODE_SERIAL_PUNCTURED,
-
-	.repeater_level = STV090x_RPTLEVEL_16,
-
-	.adc1_range	= STV090x_ADC_1Vpp,
-	.adc2_range	= STV090x_ADC_1Vpp,
-
-	.diseqc_envelope_mode = true,
-};
-
-static struct stv6110x_config stv6110a = {
-	.addr    = 0x60,
-	.refclk	 = 27000000,
-	.clk_div = 1,
-};
-
-static struct stv6110x_config stv6110b = {
-	.addr    = 0x63,
-	.refclk	 = 27000000,
-	.clk_div = 1,
-};
-
-static int demod_attach_stv0900(struct ddb_input *input, int type)
-{
-	struct i2c_adapter *i2c = &input->port->i2c->adap;
-	struct stv090x_config *feconf = type ? &stv0900_aa : &stv0900;
-
-	input->fe = dvb_attach(stv090x_attach, feconf, i2c,
-			       (input->nr & 1) ? STV090x_DEMODULATOR_1
-			       : STV090x_DEMODULATOR_0);
-	if (!input->fe) {
-		printk(KERN_ERR "No STV0900 found!\n");
-		return -ENODEV;
-	}
-	if (!dvb_attach(lnbh24_attach, input->fe, i2c, 0,
-			0, (input->nr & 1) ?
-			(0x09 - type) : (0x0b - type))) {
-		printk(KERN_ERR "No LNBH24 found!\n");
-		return -ENODEV;
-	}
-	return 0;
-}
-
-static int tuner_attach_stv6110(struct ddb_input *input, int type)
-{
-	struct i2c_adapter *i2c = &input->port->i2c->adap;
-	struct stv090x_config *feconf = type ? &stv0900_aa : &stv0900;
-	struct stv6110x_config *tunerconf = (input->nr & 1) ?
-		&stv6110b : &stv6110a;
-	struct stv6110x_devctl *ctl;
-
-	ctl = dvb_attach(stv6110x_attach, input->fe, tunerconf, i2c);
-	if (!ctl) {
-		printk(KERN_ERR "No STV6110X found!\n");
-		return -ENODEV;
-	}
-	printk(KERN_INFO "attach tuner input %d adr %02x\n",
-			 input->nr, tunerconf->addr);
-
-	feconf->tuner_init          = ctl->tuner_init;
-	feconf->tuner_sleep         = ctl->tuner_sleep;
-	feconf->tuner_set_mode      = ctl->tuner_set_mode;
-	feconf->tuner_set_frequency = ctl->tuner_set_frequency;
-	feconf->tuner_get_frequency = ctl->tuner_get_frequency;
-	feconf->tuner_set_bandwidth = ctl->tuner_set_bandwidth;
-	feconf->tuner_get_bandwidth = ctl->tuner_get_bandwidth;
-	feconf->tuner_set_bbgain    = ctl->tuner_set_bbgain;
-	feconf->tuner_get_bbgain    = ctl->tuner_get_bbgain;
-	feconf->tuner_set_refclk    = ctl->tuner_set_refclk;
-	feconf->tuner_get_status    = ctl->tuner_get_status;
-
-	return 0;
-}
-
-static int my_dvb_dmx_ts_card_init(struct dvb_demux *dvbdemux, char *id,
-			    int (*start_feed)(struct dvb_demux_feed *),
-			    int (*stop_feed)(struct dvb_demux_feed *),
-			    void *priv)
-{
-	dvbdemux->priv = priv;
-
-	dvbdemux->filternum = 256;
-	dvbdemux->feednum = 256;
-	dvbdemux->start_feed = start_feed;
-	dvbdemux->stop_feed = stop_feed;
-	dvbdemux->write_to_decoder = NULL;
-	dvbdemux->dmx.capabilities = (DMX_TS_FILTERING |
-				      DMX_SECTION_FILTERING |
-				      DMX_MEMORY_BASED_FILTERING);
-	return dvb_dmx_init(dvbdemux);
-}
-
-static int my_dvb_dmxdev_ts_card_init(struct dmxdev *dmxdev,
-			       struct dvb_demux *dvbdemux,
-			       struct dmx_frontend *hw_frontend,
-			       struct dmx_frontend *mem_frontend,
-			       struct dvb_adapter *dvb_adapter)
-{
-	int ret;
-
-	dmxdev->filternum = 256;
-	dmxdev->demux = &dvbdemux->dmx;
-	dmxdev->capabilities = 0;
-	ret = dvb_dmxdev_init(dmxdev, dvb_adapter);
-	if (ret < 0)
-		return ret;
-
-	hw_frontend->source = DMX_FRONTEND_0;
-	dvbdemux->dmx.add_frontend(&dvbdemux->dmx, hw_frontend);
-	mem_frontend->source = DMX_MEMORY_FE;
-	dvbdemux->dmx.add_frontend(&dvbdemux->dmx, mem_frontend);
-	return dvbdemux->dmx.connect_frontend(&dvbdemux->dmx, hw_frontend);
-}
-
-static int start_feed(struct dvb_demux_feed *dvbdmxfeed)
-{
-	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
-	struct ddb_input *input = dvbdmx->priv;
-
-	if (!input->users)
-		ddb_input_start(input);
-
-	return ++input->users;
-}
-
-static int stop_feed(struct dvb_demux_feed *dvbdmxfeed)
-{
-	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
-	struct ddb_input *input = dvbdmx->priv;
-
-	if (--input->users)
-		return input->users;
-
-	ddb_input_stop(input);
-	return 0;
-}
-
-
-static void dvb_input_detach(struct ddb_input *input)
-{
-	struct dvb_adapter *adap = &input->adap;
-	struct dvb_demux *dvbdemux = &input->demux;
-
-	switch (input->attached) {
-	case 5:
-		if (input->fe2)
-			dvb_unregister_frontend(input->fe2);
-		if (input->fe) {
-			dvb_unregister_frontend(input->fe);
-			dvb_frontend_detach(input->fe);
-			input->fe = NULL;
-		}
-	case 4:
-		dvb_net_release(&input->dvbnet);
-
-	case 3:
-		dvbdemux->dmx.close(&dvbdemux->dmx);
-		dvbdemux->dmx.remove_frontend(&dvbdemux->dmx,
-					      &input->hw_frontend);
-		dvbdemux->dmx.remove_frontend(&dvbdemux->dmx,
-					      &input->mem_frontend);
-		dvb_dmxdev_release(&input->dmxdev);
-
-	case 2:
-		dvb_dmx_release(&input->demux);
-
-	case 1:
-		dvb_unregister_adapter(adap);
-	}
-	input->attached = 0;
-}
-
-static int dvb_input_attach(struct ddb_input *input)
-{
-	int ret;
-	struct ddb_port *port = input->port;
-	struct dvb_adapter *adap = &input->adap;
-	struct dvb_demux *dvbdemux = &input->demux;
-
-	ret = dvb_register_adapter(adap, "DDBridge", THIS_MODULE,
-				   &input->port->dev->pdev->dev,
-				   adapter_nr);
-	if (ret < 0) {
-		printk(KERN_ERR "ddbridge: Could not register adapter."
-		       "Check if you enabled enough adapters in dvb-core!\n");
-		return ret;
-	}
-	input->attached = 1;
-
-	ret = my_dvb_dmx_ts_card_init(dvbdemux, "SW demux",
-				      start_feed,
-				      stop_feed, input);
-	if (ret < 0)
-		return ret;
-	input->attached = 2;
-
-	ret = my_dvb_dmxdev_ts_card_init(&input->dmxdev, &input->demux,
-					 &input->hw_frontend,
-					 &input->mem_frontend, adap);
-	if (ret < 0)
-		return ret;
-	input->attached = 3;
-
-	ret = dvb_net_init(adap, &input->dvbnet, input->dmxdev.demux);
-	if (ret < 0)
-		return ret;
-	input->attached = 4;
-
-	input->fe = 0;
-	switch (port->type) {
-	case DDB_TUNER_DVBS_ST:
-		if (demod_attach_stv0900(input, 0) < 0)
-			return -ENODEV;
-		if (tuner_attach_stv6110(input, 0) < 0)
-			return -ENODEV;
-		if (input->fe) {
-			if (dvb_register_frontend(adap, input->fe) < 0)
-				return -ENODEV;
-		}
-		break;
-	case DDB_TUNER_DVBS_ST_AA:
-		if (demod_attach_stv0900(input, 1) < 0)
-			return -ENODEV;
-		if (tuner_attach_stv6110(input, 1) < 0)
-			return -ENODEV;
-		if (input->fe) {
-			if (dvb_register_frontend(adap, input->fe) < 0)
-				return -ENODEV;
-		}
-		break;
-	case DDB_TUNER_DVBCT_TR:
-		if (demod_attach_drxk(input) < 0)
-			return -ENODEV;
-		if (tuner_attach_tda18271(input) < 0)
-			return -ENODEV;
-		if (input->fe) {
-			if (dvb_register_frontend(adap, input->fe) < 0)
-				return -ENODEV;
-		}
-		if (input->fe2) {
-			if (dvb_register_frontend(adap, input->fe2) < 0)
-				return -ENODEV;
-			input->fe2->tuner_priv = input->fe->tuner_priv;
-			memcpy(&input->fe2->ops.tuner_ops,
-			       &input->fe->ops.tuner_ops,
-			       sizeof(struct dvb_tuner_ops));
-		}
-		break;
-	}
-	input->attached = 5;
-	return 0;
-}
-
-/****************************************************************************/
-/****************************************************************************/
-
-static ssize_t ts_write(struct file *file, const char *buf,
-			size_t count, loff_t *ppos)
-{
-	struct dvb_device *dvbdev = file->private_data;
-	struct ddb_output *output = dvbdev->priv;
-	size_t left = count;
-	int stat;
-
-	while (left) {
-		if (ddb_output_free(output) < 188) {
-			if (file->f_flags & O_NONBLOCK)
-				break;
-			if (wait_event_interruptible(
-				    output->wq, ddb_output_free(output) >= 188) < 0)
-				break;
-		}
-		stat = ddb_output_write(output, buf, left);
-		if (stat < 0)
-			break;
-		buf += stat;
-		left -= stat;
-	}
-	return (left == count) ? -EAGAIN : (count - left);
-}
-
-static ssize_t ts_read(struct file *file, char *buf,
-		       size_t count, loff_t *ppos)
-{
-	struct dvb_device *dvbdev = file->private_data;
-	struct ddb_output *output = dvbdev->priv;
-	struct ddb_input *input = output->port->input[0];
-	int left, read;
-
-	count -= count % 188;
-	left = count;
-	while (left) {
-		if (ddb_input_avail(input) < 188) {
-			if (file->f_flags & O_NONBLOCK)
-				break;
-			if (wait_event_interruptible(
-				    input->wq, ddb_input_avail(input) >= 188) < 0)
-				break;
-		}
-		read = ddb_input_read(input, buf, left);
-		if (read < 0)
-			return read;
-		left -= read;
-		buf += read;
-	}
-	return (left == count) ? -EAGAIN : (count - left);
-}
-
-static unsigned int ts_poll(struct file *file, poll_table *wait)
-{
-	/*
-	struct dvb_device *dvbdev = file->private_data;
-	struct ddb_output *output = dvbdev->priv;
-	struct ddb_input *input = output->port->input[0];
-	*/
-	unsigned int mask = 0;
-
-#if 0
-	if (data_avail_to_read)
-		mask |= POLLIN | POLLRDNORM;
-	if (data_avail_to_write)
-		mask |= POLLOUT | POLLWRNORM;
-
-	poll_wait(file, &read_queue, wait);
-	poll_wait(file, &write_queue, wait);
-#endif
-	return mask;
-}
-
-static const struct file_operations ci_fops = {
-	.owner   = THIS_MODULE,
-	.read    = ts_read,
-	.write   = ts_write,
-	.open    = dvb_generic_open,
-	.release = dvb_generic_release,
-	.poll    = ts_poll,
-	.mmap    = 0,
-};
-
-static struct dvb_device dvbdev_ci = {
-	.priv    = 0,
-	.readers = -1,
-	.writers = -1,
-	.users   = -1,
-	.fops    = &ci_fops,
-};
-
-/****************************************************************************/
-/****************************************************************************/
-/****************************************************************************/
-
-static void input_tasklet(unsigned long data)
-{
-	struct ddb_input *input = (struct ddb_input *) data;
-	struct ddb *dev = input->port->dev;
-
-	spin_lock(&input->lock);
-	if (!input->running) {
-		spin_unlock(&input->lock);
-		return;
-	}
-	input->stat = ddbreadl(DMA_BUFFER_CURRENT(input->nr));
-
-	if (input->port->class == DDB_PORT_TUNER) {
-		if (4&ddbreadl(DMA_BUFFER_CONTROL(input->nr)))
-			printk(KERN_ERR "Overflow input %d\n", input->nr);
-		while (input->cbuf != ((input->stat >> 11) & 0x1f)
-		       || (4&ddbreadl(DMA_BUFFER_CONTROL(input->nr)))) {
-			dvb_dmx_swfilter_packets(&input->demux,
-						 input->vbuf[input->cbuf],
-						 input->dma_buf_size / 188);
-
-			input->cbuf = (input->cbuf + 1) % input->dma_buf_num;
-			ddbwritel((input->cbuf << 11),
-				  DMA_BUFFER_ACK(input->nr));
-			input->stat = ddbreadl(DMA_BUFFER_CURRENT(input->nr));
-		       }
-	}
-	if (input->port->class == DDB_PORT_CI)
-		wake_up(&input->wq);
-	spin_unlock(&input->lock);
-}
-
-static void output_tasklet(unsigned long data)
-{
-	struct ddb_output *output = (struct ddb_output *) data;
-	struct ddb *dev = output->port->dev;
-
-	spin_lock(&output->lock);
-	if (!output->running) {
-		spin_unlock(&output->lock);
-		return;
-	}
-	output->stat = ddbreadl(DMA_BUFFER_CURRENT(output->nr + 8));
-	wake_up(&output->wq);
-	spin_unlock(&output->lock);
-}
-
-
-struct cxd2099_cfg cxd_cfg = {
-	.bitrate =  62000,
-	.adr     =  0x40,
-	.polarity = 1,
-	.clock_mode = 1,
-};
-
-static int ddb_ci_attach(struct ddb_port *port)
-{
-	int ret;
-
-	ret = dvb_register_adapter(&port->output->adap,
-				   "DDBridge",
-				   THIS_MODULE,
-				   &port->dev->pdev->dev,
-				   adapter_nr);
-	if (ret < 0)
-		return ret;
-	port->en = cxd2099_attach(&cxd_cfg, port, &port->i2c->adap);
-	if (!port->en) {
-		dvb_unregister_adapter(&port->output->adap);
-		return -ENODEV;
-	}
-	ddb_input_start(port->input[0]);
-	ddb_output_start(port->output);
-	dvb_ca_en50221_init(&port->output->adap,
-			    port->en, 0, 1);
-	ret = dvb_register_device(&port->output->adap, &port->output->dev,
-				  &dvbdev_ci, (void *) port->output,
-				  DVB_DEVICE_SEC);
-	return ret;
-}
-
-static int ddb_port_attach(struct ddb_port *port)
-{
-	int ret = 0;
-
-	switch (port->class) {
-	case DDB_PORT_TUNER:
-		ret = dvb_input_attach(port->input[0]);
-		if (ret < 0)
-			break;
-		ret = dvb_input_attach(port->input[1]);
-		break;
-	case DDB_PORT_CI:
-		ret = ddb_ci_attach(port);
-		break;
-	default:
-		break;
-	}
-	if (ret < 0)
-		printk(KERN_ERR "port_attach on port %d failed\n", port->nr);
-	return ret;
-}
-
-static int ddb_ports_attach(struct ddb *dev)
-{
-	int i, ret = 0;
-	struct ddb_port *port;
-
-	for (i = 0; i < dev->info->port_num; i++) {
-		port = &dev->port[i];
-		ret = ddb_port_attach(port);
-		if (ret < 0)
-			break;
-	}
-	return ret;
-}
-
-static void ddb_ports_detach(struct ddb *dev)
-{
-	int i;
-	struct ddb_port *port;
-
-	for (i = 0; i < dev->info->port_num; i++) {
-		port = &dev->port[i];
-		switch (port->class) {
-		case DDB_PORT_TUNER:
-			dvb_input_detach(port->input[0]);
-			dvb_input_detach(port->input[1]);
-			break;
-		case DDB_PORT_CI:
-			if (port->output->dev)
-				dvb_unregister_device(port->output->dev);
-			if (port->en) {
-				ddb_input_stop(port->input[0]);
-				ddb_output_stop(port->output);
-				dvb_ca_en50221_release(port->en);
-				kfree(port->en);
-				port->en = 0;
-				dvb_unregister_adapter(&port->output->adap);
-			}
-			break;
-		}
-	}
-}
-
-/****************************************************************************/
-/****************************************************************************/
-
-static int port_has_ci(struct ddb_port *port)
-{
-	u8 val;
-	return i2c_read_reg(&port->i2c->adap, 0x40, 0, &val) ? 0 : 1;
-}
-
-static int port_has_stv0900(struct ddb_port *port)
-{
-	u8 val;
-	if (i2c_read_reg16(&port->i2c->adap, 0x69, 0xf100, &val) < 0)
-		return 0;
-	return 1;
-}
-
-static int port_has_stv0900_aa(struct ddb_port *port)
-{
-	u8 val;
-	if (i2c_read_reg16(&port->i2c->adap, 0x68, 0xf100, &val) < 0)
-		return 0;
-	return 1;
-}
-
-static int port_has_drxks(struct ddb_port *port)
-{
-	u8 val;
-	if (i2c_read(&port->i2c->adap, 0x29, &val) < 0)
-		return 0;
-	if (i2c_read(&port->i2c->adap, 0x2a, &val) < 0)
-		return 0;
-	return 1;
-}
-
-static void ddb_port_probe(struct ddb_port *port)
-{
-	struct ddb *dev = port->dev;
-	char *modname = "NO MODULE";
-
-	port->class = DDB_PORT_NONE;
-
-	if (port_has_ci(port)) {
-		modname = "CI";
-		port->class = DDB_PORT_CI;
-		ddbwritel(I2C_SPEED_400, port->i2c->regs + I2C_TIMING);
-	} else if (port_has_stv0900(port)) {
-		modname = "DUAL DVB-S2";
-		port->class = DDB_PORT_TUNER;
-		port->type = DDB_TUNER_DVBS_ST;
-		ddbwritel(I2C_SPEED_100, port->i2c->regs + I2C_TIMING);
-	} else if (port_has_stv0900_aa(port)) {
-		modname = "DUAL DVB-S2";
-		port->class = DDB_PORT_TUNER;
-		port->type = DDB_TUNER_DVBS_ST_AA;
-		ddbwritel(I2C_SPEED_100, port->i2c->regs + I2C_TIMING);
-	} else if (port_has_drxks(port)) {
-		modname = "DUAL DVB-C/T";
-		port->class = DDB_PORT_TUNER;
-		port->type = DDB_TUNER_DVBCT_TR;
-		ddbwritel(I2C_SPEED_400, port->i2c->regs + I2C_TIMING);
-	}
-	printk(KERN_INFO "Port %d (TAB %d): %s\n",
-			 port->nr, port->nr+1, modname);
-}
-
-static void ddb_input_init(struct ddb_port *port, int nr)
-{
-	struct ddb *dev = port->dev;
-	struct ddb_input *input = &dev->input[nr];
-
-	input->nr = nr;
-	input->port = port;
-	input->dma_buf_num = INPUT_DMA_BUFS;
-	input->dma_buf_size = INPUT_DMA_SIZE;
-	ddbwritel(0, TS_INPUT_CONTROL(nr));
-	ddbwritel(2, TS_INPUT_CONTROL(nr));
-	ddbwritel(0, TS_INPUT_CONTROL(nr));
-	ddbwritel(0, DMA_BUFFER_ACK(nr));
-	tasklet_init(&input->tasklet, input_tasklet, (unsigned long) input);
-	spin_lock_init(&input->lock);
-	init_waitqueue_head(&input->wq);
-}
-
-static void ddb_output_init(struct ddb_port *port, int nr)
-{
-	struct ddb *dev = port->dev;
-	struct ddb_output *output = &dev->output[nr];
-	output->nr = nr;
-	output->port = port;
-	output->dma_buf_num = OUTPUT_DMA_BUFS;
-	output->dma_buf_size = OUTPUT_DMA_SIZE;
-
-	ddbwritel(0, TS_OUTPUT_CONTROL(nr));
-	ddbwritel(2, TS_OUTPUT_CONTROL(nr));
-	ddbwritel(0, TS_OUTPUT_CONTROL(nr));
-	tasklet_init(&output->tasklet, output_tasklet, (unsigned long) output);
-	init_waitqueue_head(&output->wq);
-}
-
-static void ddb_ports_init(struct ddb *dev)
-{
-	int i;
-	struct ddb_port *port;
-
-	for (i = 0; i < dev->info->port_num; i++) {
-		port = &dev->port[i];
-		port->dev = dev;
-		port->nr = i;
-		port->i2c = &dev->i2c[i];
-		port->input[0] = &dev->input[2 * i];
-		port->input[1] = &dev->input[2 * i + 1];
-		port->output = &dev->output[i];
-
-		mutex_init(&port->i2c_gate_lock);
-		ddb_port_probe(port);
-		ddb_input_init(port, 2 * i);
-		ddb_input_init(port, 2 * i + 1);
-		ddb_output_init(port, i);
-	}
-}
-
-static void ddb_ports_release(struct ddb *dev)
-{
-	int i;
-	struct ddb_port *port;
-
-	for (i = 0; i < dev->info->port_num; i++) {
-		port = &dev->port[i];
-		port->dev = dev;
-		tasklet_kill(&port->input[0]->tasklet);
-		tasklet_kill(&port->input[1]->tasklet);
-		tasklet_kill(&port->output->tasklet);
-	}
-}
-
-/****************************************************************************/
-/****************************************************************************/
-/****************************************************************************/
-
-static void irq_handle_i2c(struct ddb *dev, int n)
-{
-	struct ddb_i2c *i2c = &dev->i2c[n];
-
-	i2c->done = 1;
-	wake_up(&i2c->wq);
-}
-
-static irqreturn_t irq_handler(int irq, void *dev_id)
-{
-	struct ddb *dev = (struct ddb *) dev_id;
-	u32 s = ddbreadl(INTERRUPT_STATUS);
-
-	if (!s)
-		return IRQ_NONE;
-
-	do {
-		ddbwritel(s, INTERRUPT_ACK);
-
-		if (s & 0x00000001)
-			irq_handle_i2c(dev, 0);
-		if (s & 0x00000002)
-			irq_handle_i2c(dev, 1);
-		if (s & 0x00000004)
-			irq_handle_i2c(dev, 2);
-		if (s & 0x00000008)
-			irq_handle_i2c(dev, 3);
-
-		if (s & 0x00000100)
-			tasklet_schedule(&dev->input[0].tasklet);
-		if (s & 0x00000200)
-			tasklet_schedule(&dev->input[1].tasklet);
-		if (s & 0x00000400)
-			tasklet_schedule(&dev->input[2].tasklet);
-		if (s & 0x00000800)
-			tasklet_schedule(&dev->input[3].tasklet);
-		if (s & 0x00001000)
-			tasklet_schedule(&dev->input[4].tasklet);
-		if (s & 0x00002000)
-			tasklet_schedule(&dev->input[5].tasklet);
-		if (s & 0x00004000)
-			tasklet_schedule(&dev->input[6].tasklet);
-		if (s & 0x00008000)
-			tasklet_schedule(&dev->input[7].tasklet);
-
-		if (s & 0x00010000)
-			tasklet_schedule(&dev->output[0].tasklet);
-		if (s & 0x00020000)
-			tasklet_schedule(&dev->output[1].tasklet);
-		if (s & 0x00040000)
-			tasklet_schedule(&dev->output[2].tasklet);
-		if (s & 0x00080000)
-			tasklet_schedule(&dev->output[3].tasklet);
-
-		/* if (s & 0x000f0000)	printk(KERN_DEBUG "%08x\n", istat); */
-	} while ((s = ddbreadl(INTERRUPT_STATUS)));
-
-	return IRQ_HANDLED;
-}
-
-/******************************************************************************/
-/******************************************************************************/
-/******************************************************************************/
-
-static int flashio(struct ddb *dev, u8 *wbuf, u32 wlen, u8 *rbuf, u32 rlen)
-{
-	u32 data, shift;
-
-	if (wlen > 4)
-		ddbwritel(1, SPI_CONTROL);
-	while (wlen > 4) {
-		/* FIXME: check for big-endian */
-		data = swab32(*(u32 *)wbuf);
-		wbuf += 4;
-		wlen -= 4;
-		ddbwritel(data, SPI_DATA);
-		while (ddbreadl(SPI_CONTROL) & 0x0004)
-			;
-	}
-
-	if (rlen)
-		ddbwritel(0x0001 | ((wlen << (8 + 3)) & 0x1f00), SPI_CONTROL);
-	else
-		ddbwritel(0x0003 | ((wlen << (8 + 3)) & 0x1f00), SPI_CONTROL);
-
-	data = 0;
-	shift = ((4 - wlen) * 8);
-	while (wlen) {
-		data <<= 8;
-		data |= *wbuf;
-		wlen--;
-		wbuf++;
-	}
-	if (shift)
-		data <<= shift;
-	ddbwritel(data, SPI_DATA);
-	while (ddbreadl(SPI_CONTROL) & 0x0004)
-		;
-
-	if (!rlen) {
-		ddbwritel(0, SPI_CONTROL);
-		return 0;
-	}
-	if (rlen > 4)
-		ddbwritel(1, SPI_CONTROL);
-
-	while (rlen > 4) {
-		ddbwritel(0xffffffff, SPI_DATA);
-		while (ddbreadl(SPI_CONTROL) & 0x0004)
-			;
-		data = ddbreadl(SPI_DATA);
-		*(u32 *) rbuf = swab32(data);
-		rbuf += 4;
-		rlen -= 4;
-	}
-	ddbwritel(0x0003 | ((rlen << (8 + 3)) & 0x1F00), SPI_CONTROL);
-	ddbwritel(0xffffffff, SPI_DATA);
-	while (ddbreadl(SPI_CONTROL) & 0x0004)
-		;
-
-	data = ddbreadl(SPI_DATA);
-	ddbwritel(0, SPI_CONTROL);
-
-	if (rlen < 4)
-		data <<= ((4 - rlen) * 8);
-
-	while (rlen > 0) {
-		*rbuf = ((data >> 24) & 0xff);
-		data <<= 8;
-		rbuf++;
-		rlen--;
-	}
-	return 0;
-}
-
-#define DDB_MAGIC 'd'
-
-struct ddb_flashio {
-	__u8 *write_buf;
-	__u32 write_len;
-	__u8 *read_buf;
-	__u32 read_len;
-};
-
-#define IOCTL_DDB_FLASHIO  _IOWR(DDB_MAGIC, 0x00, struct ddb_flashio)
-
-#define DDB_NAME "ddbridge"
-
-static u32 ddb_num;
-static struct ddb *ddbs[32];
-static struct class *ddb_class;
-static int ddb_major;
-
-static int ddb_open(struct inode *inode, struct file *file)
-{
-	struct ddb *dev = ddbs[iminor(inode)];
-
-	file->private_data = dev;
-	return 0;
-}
-
-static long ddb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
-	struct ddb *dev = file->private_data;
-	void *parg = (void *)arg;
-	int res;
-
-	switch (cmd) {
-	case IOCTL_DDB_FLASHIO:
-	{
-		struct ddb_flashio fio;
-		u8 *rbuf, *wbuf;
-
-		if (copy_from_user(&fio, parg, sizeof(fio)))
-			return -EFAULT;
-
-		if (fio.write_len > 1028 || fio.read_len > 1028)
-			return -EINVAL;
-		if (fio.write_len + fio.read_len > 1028)
-			return -EINVAL;
-
-		wbuf = &dev->iobuf[0];
-		rbuf = wbuf + fio.write_len;
-
-		if (copy_from_user(wbuf, fio.write_buf, fio.write_len))
-			return -EFAULT;
-		res = flashio(dev, wbuf, fio.write_len, rbuf, fio.read_len);
-		if (res)
-			return res;
-		if (copy_to_user(fio.read_buf, rbuf, fio.read_len))
-			return -EFAULT;
-		break;
-	}
-	default:
-		return -ENOTTY;
-	}
-	return 0;
-}
-
-static const struct file_operations ddb_fops = {
-	.unlocked_ioctl = ddb_ioctl,
-	.open           = ddb_open,
-};
-
-static char *ddb_devnode(struct device *device, umode_t *mode)
-{
-	struct ddb *dev = dev_get_drvdata(device);
-
-	return kasprintf(GFP_KERNEL, "ddbridge/card%d", dev->nr);
-}
-
-static int ddb_class_create(void)
-{
-	ddb_major = register_chrdev(0, DDB_NAME, &ddb_fops);
-	if (ddb_major < 0)
-		return ddb_major;
-
-	ddb_class = class_create(THIS_MODULE, DDB_NAME);
-	if (IS_ERR(ddb_class)) {
-		unregister_chrdev(ddb_major, DDB_NAME);
-		return -1;
-	}
-	ddb_class->devnode = ddb_devnode;
-	return 0;
-}
-
-static void ddb_class_destroy(void)
-{
-	class_destroy(ddb_class);
-	unregister_chrdev(ddb_major, DDB_NAME);
-}
-
-static int ddb_device_create(struct ddb *dev)
-{
-	dev->nr = ddb_num++;
-	dev->ddb_dev = device_create(ddb_class, NULL,
-				     MKDEV(ddb_major, dev->nr),
-				     dev, "ddbridge%d", dev->nr);
-	ddbs[dev->nr] = dev;
-	if (IS_ERR(dev->ddb_dev))
-		return -1;
-	return 0;
-}
-
-static void ddb_device_destroy(struct ddb *dev)
-{
-	ddb_num--;
-	if (IS_ERR(dev->ddb_dev))
-		return;
-	device_destroy(ddb_class, MKDEV(ddb_major, 0));
-}
-
-
-/****************************************************************************/
-/****************************************************************************/
-/****************************************************************************/
-
-static void ddb_unmap(struct ddb *dev)
-{
-	if (dev->regs)
-		iounmap(dev->regs);
-	vfree(dev);
-}
-
-
-static void __devexit ddb_remove(struct pci_dev *pdev)
-{
-	struct ddb *dev = (struct ddb *) pci_get_drvdata(pdev);
-
-	ddb_ports_detach(dev);
-	ddb_i2c_release(dev);
-
-	ddbwritel(0, INTERRUPT_ENABLE);
-	free_irq(dev->pdev->irq, dev);
-#ifdef CONFIG_PCI_MSI
-	if (dev->msi)
-		pci_disable_msi(dev->pdev);
-#endif
-	ddb_ports_release(dev);
-	ddb_buffers_free(dev);
-	ddb_device_destroy(dev);
-
-	ddb_unmap(dev);
-	pci_set_drvdata(pdev, 0);
-	pci_disable_device(pdev);
-}
-
-
-static int __devinit ddb_probe(struct pci_dev *pdev,
-			       const struct pci_device_id *id)
-{
-	struct ddb *dev;
-	int stat = 0;
-	int irq_flag = IRQF_SHARED;
-
-	if (pci_enable_device(pdev) < 0)
-		return -ENODEV;
-
-	dev = vmalloc(sizeof(struct ddb));
-	if (dev == NULL)
-		return -ENOMEM;
-	memset(dev, 0, sizeof(struct ddb));
-
-	dev->pdev = pdev;
-	pci_set_drvdata(pdev, dev);
-	dev->info = (struct ddb_info *) id->driver_data;
-	printk(KERN_INFO "DDBridge driver detected: %s\n", dev->info->name);
-
-	dev->regs = ioremap(pci_resource_start(dev->pdev, 0),
-			    pci_resource_len(dev->pdev, 0));
-	if (!dev->regs) {
-		stat = -ENOMEM;
-		goto fail;
-	}
-	printk(KERN_INFO "HW %08x FW %08x\n", ddbreadl(0), ddbreadl(4));
-
-#ifdef CONFIG_PCI_MSI
-	if (pci_msi_enabled())
-		stat = pci_enable_msi(dev->pdev);
-	if (stat) {
-		printk(KERN_INFO ": MSI not available.\n");
-	} else {
-		irq_flag = 0;
-		dev->msi = 1;
-	}
-#endif
-	stat = request_irq(dev->pdev->irq, irq_handler,
-			   irq_flag, "DDBridge", (void *) dev);
-	if (stat < 0)
-		goto fail1;
-	ddbwritel(0, DMA_BASE_WRITE);
-	ddbwritel(0, DMA_BASE_READ);
-	ddbwritel(0xffffffff, INTERRUPT_ACK);
-	ddbwritel(0xfff0f, INTERRUPT_ENABLE);
-	ddbwritel(0, MSI1_ENABLE);
-
-	if (ddb_i2c_init(dev) < 0)
-		goto fail1;
-	ddb_ports_init(dev);
-	if (ddb_buffers_alloc(dev) < 0) {
-		printk(KERN_INFO ": Could not allocate buffer memory\n");
-		goto fail2;
-	}
-	if (ddb_ports_attach(dev) < 0)
-		goto fail3;
-	ddb_device_create(dev);
-	return 0;
-
-fail3:
-	ddb_ports_detach(dev);
-	printk(KERN_ERR "fail3\n");
-	ddb_ports_release(dev);
-fail2:
-	printk(KERN_ERR "fail2\n");
-	ddb_buffers_free(dev);
-fail1:
-	printk(KERN_ERR "fail1\n");
-	if (dev->msi)
-		pci_disable_msi(dev->pdev);
-	free_irq(dev->pdev->irq, dev);
-fail:
-	printk(KERN_ERR "fail\n");
-	ddb_unmap(dev);
-	pci_set_drvdata(pdev, 0);
-	pci_disable_device(pdev);
-	return -1;
-}
-
-/******************************************************************************/
-/******************************************************************************/
-/******************************************************************************/
-
-static struct ddb_info ddb_none = {
-	.type     = DDB_NONE,
-	.name     = "Digital Devices PCIe bridge",
-};
-
-static struct ddb_info ddb_octopus = {
-	.type     = DDB_OCTOPUS,
-	.name     = "Digital Devices Octopus DVB adapter",
-	.port_num = 4,
-};
-
-static struct ddb_info ddb_octopus_le = {
-	.type     = DDB_OCTOPUS,
-	.name     = "Digital Devices Octopus LE DVB adapter",
-	.port_num = 2,
-};
-
-static struct ddb_info ddb_v6 = {
-	.type     = DDB_OCTOPUS,
-	.name     = "Digital Devices Cine S2 V6 DVB adapter",
-	.port_num = 3,
-};
-
-#define DDVID 0xdd01 /* Digital Devices Vendor ID */
-
-#define DDB_ID(_vend, _dev, _subvend, _subdev, _driverdata) {	\
-	.vendor      = _vend,    .device    = _dev, \
-	.subvendor   = _subvend, .subdevice = _subdev, \
-	.driver_data = (unsigned long)&_driverdata }
-
-static const struct pci_device_id ddb_id_tbl[] __devinitdata = {
-	DDB_ID(DDVID, 0x0002, DDVID, 0x0001, ddb_octopus),
-	DDB_ID(DDVID, 0x0003, DDVID, 0x0001, ddb_octopus),
-	DDB_ID(DDVID, 0x0003, DDVID, 0x0002, ddb_octopus_le),
-	DDB_ID(DDVID, 0x0003, DDVID, 0x0010, ddb_octopus),
-	DDB_ID(DDVID, 0x0003, DDVID, 0x0020, ddb_v6),
-	/* in case sub-ids got deleted in flash */
-	DDB_ID(DDVID, 0x0003, PCI_ANY_ID, PCI_ANY_ID, ddb_none),
-	{0}
-};
-MODULE_DEVICE_TABLE(pci, ddb_id_tbl);
-
-
-static struct pci_driver ddb_pci_driver = {
-	.name        = "DDBridge",
-	.id_table    = ddb_id_tbl,
-	.probe       = ddb_probe,
-	.remove      = __devexit_p(ddb_remove),
-};
-
-static __init int module_init_ddbridge(void)
-{
-	printk(KERN_INFO "Digital Devices PCIE bridge driver, "
-	       "Copyright (C) 2010-11 Digital Devices GmbH\n");
-	if (ddb_class_create())
-		return -1;
-	return pci_register_driver(&ddb_pci_driver);
-}
-
-static __exit void module_exit_ddbridge(void)
-{
-	pci_unregister_driver(&ddb_pci_driver);
-	ddb_class_destroy();
-}
-
-module_init(module_init_ddbridge);
-module_exit(module_exit_ddbridge);
-
-MODULE_DESCRIPTION("Digital Devices PCIe Bridge");
-MODULE_AUTHOR("Ralph Metzler");
-MODULE_LICENSE("GPL");
-MODULE_VERSION("0.5");
diff --git a/drivers/media/dvb/ddbridge/ddbridge-regs.h b/drivers/media/dvb/ddbridge/ddbridge-regs.h
deleted file mode 100644
index a3ccb31..0000000
--- a/drivers/media/dvb/ddbridge/ddbridge-regs.h
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * ddbridge-regs.h: Digital Devices PCIe bridge driver
- *
- * Copyright (C) 2010-2011 Digital Devices GmbH
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 only, as published by the Free Software Foundation.
- *
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-/* DD-DVBBridgeV1.h 273 2010-09-17 05:03:16Z manfred */
-
-/* Register Definitions */
-
-#define CUR_REGISTERMAP_VERSION 0x10000
-
-#define HARDWARE_VERSION       0x00
-#define REGISTERMAP_VERSION    0x04
-
-/* ------------------------------------------------------------------------- */
-/* SPI Controller */
-
-#define SPI_CONTROL     0x10
-#define SPI_DATA        0x14
-
-/* ------------------------------------------------------------------------- */
-
-/* Interrupt controller                                     */
-/* How many MSI's are available depends on HW (Min 2 max 8) */
-/* How many are usable also depends on Host platform        */
-
-#define INTERRUPT_BASE   (0x40)
-
-#define INTERRUPT_ENABLE (INTERRUPT_BASE + 0x00)
-#define MSI0_ENABLE      (INTERRUPT_BASE + 0x00)
-#define MSI1_ENABLE      (INTERRUPT_BASE + 0x04)
-#define MSI2_ENABLE      (INTERRUPT_BASE + 0x08)
-#define MSI3_ENABLE      (INTERRUPT_BASE + 0x0C)
-#define MSI4_ENABLE      (INTERRUPT_BASE + 0x10)
-#define MSI5_ENABLE      (INTERRUPT_BASE + 0x14)
-#define MSI6_ENABLE      (INTERRUPT_BASE + 0x18)
-#define MSI7_ENABLE      (INTERRUPT_BASE + 0x1C)
-
-#define INTERRUPT_STATUS (INTERRUPT_BASE + 0x20)
-#define INTERRUPT_ACK    (INTERRUPT_BASE + 0x20)
-
-#define INTMASK_I2C1        (0x00000001)
-#define INTMASK_I2C2        (0x00000002)
-#define INTMASK_I2C3        (0x00000004)
-#define INTMASK_I2C4        (0x00000008)
-
-#define INTMASK_CIRQ1       (0x00000010)
-#define INTMASK_CIRQ2       (0x00000020)
-#define INTMASK_CIRQ3       (0x00000040)
-#define INTMASK_CIRQ4       (0x00000080)
-
-#define INTMASK_TSINPUT1    (0x00000100)
-#define INTMASK_TSINPUT2    (0x00000200)
-#define INTMASK_TSINPUT3    (0x00000400)
-#define INTMASK_TSINPUT4    (0x00000800)
-#define INTMASK_TSINPUT5    (0x00001000)
-#define INTMASK_TSINPUT6    (0x00002000)
-#define INTMASK_TSINPUT7    (0x00004000)
-#define INTMASK_TSINPUT8    (0x00008000)
-
-#define INTMASK_TSOUTPUT1   (0x00010000)
-#define INTMASK_TSOUTPUT2   (0x00020000)
-#define INTMASK_TSOUTPUT3   (0x00040000)
-#define INTMASK_TSOUTPUT4   (0x00080000)
-
-/* ------------------------------------------------------------------------- */
-/* I2C Master Controller */
-
-#define I2C_BASE        (0x80)  /* Byte offset */
-
-#define I2C_COMMAND     (0x00)
-#define I2C_TIMING      (0x04)
-#define I2C_TASKLENGTH  (0x08)     /* High read, low write */
-#define I2C_TASKADDRESS (0x0C)     /* High read, low write */
-
-#define I2C_MONITOR     (0x1C)
-
-#define I2C_BASE_1      (I2C_BASE + 0x00)
-#define I2C_BASE_2      (I2C_BASE + 0x20)
-#define I2C_BASE_3      (I2C_BASE + 0x40)
-#define I2C_BASE_4      (I2C_BASE + 0x60)
-
-#define I2C_BASE_N(i)   (I2C_BASE + (i) * 0x20)
-
-#define I2C_TASKMEM_BASE    (0x1000)    /* Byte offset */
-#define I2C_TASKMEM_SIZE    (0x1000)
-
-#define I2C_SPEED_400   (0x04030404)
-#define I2C_SPEED_200   (0x09080909)
-#define I2C_SPEED_154   (0x0C0B0C0C)
-#define I2C_SPEED_100   (0x13121313)
-#define I2C_SPEED_77    (0x19181919)
-#define I2C_SPEED_50    (0x27262727)
-
-
-/* ------------------------------------------------------------------------- */
-/* DMA  Controller */
-
-#define DMA_BASE_WRITE        (0x100)
-#define DMA_BASE_READ         (0x140)
-
-#define DMA_CONTROL     (0x00)                  /* 64 */
-#define DMA_ERROR       (0x04)                  /* 65 ( only read instance ) */
-
-#define DMA_DIAG_CONTROL                (0x1C)  /* 71 */
-#define DMA_DIAG_PACKETCOUNTER_LOW      (0x20)  /* 72 */
-#define DMA_DIAG_PACKETCOUNTER_HIGH     (0x24)  /* 73 */
-#define DMA_DIAG_TIMECOUNTER_LOW        (0x28)  /* 74 */
-#define DMA_DIAG_TIMECOUNTER_HIGH       (0x2C)  /* 75 */
-#define DMA_DIAG_RECHECKCOUNTER         (0x30)  /* 76  ( Split completions on read ) */
-#define DMA_DIAG_WAITTIMEOUTINIT        (0x34)  /* 77 */
-#define DMA_DIAG_WAITOVERFLOWCOUNTER    (0x38)  /* 78 */
-#define DMA_DIAG_WAITCOUNTER            (0x3C)  /* 79 */
-
-/* ------------------------------------------------------------------------- */
-/* DMA  Buffer */
-
-#define TS_INPUT_BASE       (0x200)
-#define TS_INPUT_CONTROL(i)         (TS_INPUT_BASE + (i) * 16 + 0x00)
-
-#define TS_OUTPUT_BASE       (0x280)
-#define TS_OUTPUT_CONTROL(i)         (TS_OUTPUT_BASE + (i) * 16 + 0x00)
-
-#define DMA_BUFFER_BASE     (0x300)
-
-#define DMA_BUFFER_CONTROL(i)       (DMA_BUFFER_BASE + (i) * 16 + 0x00)
-#define DMA_BUFFER_ACK(i)           (DMA_BUFFER_BASE + (i) * 16 + 0x04)
-#define DMA_BUFFER_CURRENT(i)       (DMA_BUFFER_BASE + (i) * 16 + 0x08)
-#define DMA_BUFFER_SIZE(i)          (DMA_BUFFER_BASE + (i) * 16 + 0x0c)
-
-#define DMA_BASE_ADDRESS_TABLE  (0x2000)
-#define DMA_BASE_ADDRESS_TABLE_ENTRIES (512)
-
diff --git a/drivers/media/dvb/ddbridge/ddbridge.h b/drivers/media/dvb/ddbridge/ddbridge.h
deleted file mode 100644
index 8b1b41d..0000000
--- a/drivers/media/dvb/ddbridge/ddbridge.h
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * ddbridge.h: Digital Devices PCIe bridge driver
- *
- * Copyright (C) 2010-2011 Digital Devices GmbH
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 only, as published by the Free Software Foundation.
- *
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#ifndef _DDBRIDGE_H_
-#define _DDBRIDGE_H_
-
-#include <linux/types.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/i2c.h>
-#include <linux/mutex.h>
-#include <asm/dma.h>
-#include <linux/dvb/frontend.h>
-#include <linux/dvb/ca.h>
-#include <linux/socket.h>
-
-#include "dmxdev.h"
-#include "dvbdev.h"
-#include "dvb_demux.h"
-#include "dvb_frontend.h"
-#include "dvb_ringbuffer.h"
-#include "dvb_ca_en50221.h"
-#include "dvb_net.h"
-#include "cxd2099.h"
-
-#define DDB_MAX_I2C     4
-#define DDB_MAX_PORT    4
-#define DDB_MAX_INPUT   8
-#define DDB_MAX_OUTPUT  4
-
-struct ddb_info {
-	int   type;
-#define DDB_NONE         0
-#define DDB_OCTOPUS      1
-	char *name;
-	int   port_num;
-	u32   port_type[DDB_MAX_PORT];
-};
-
-/* DMA_SIZE MUST be divisible by 188 and 128 !!! */
-
-#define INPUT_DMA_MAX_BUFS 32      /* hardware table limit */
-#define INPUT_DMA_BUFS 8
-#define INPUT_DMA_SIZE (128*47*21)
-
-#define OUTPUT_DMA_MAX_BUFS 32
-#define OUTPUT_DMA_BUFS 8
-#define OUTPUT_DMA_SIZE (128*47*21)
-
-struct ddb;
-struct ddb_port;
-
-struct ddb_input {
-	struct ddb_port       *port;
-	u32                    nr;
-	int                    attached;
-
-	dma_addr_t             pbuf[INPUT_DMA_MAX_BUFS];
-	u8                    *vbuf[INPUT_DMA_MAX_BUFS];
-	u32                    dma_buf_num;
-	u32                    dma_buf_size;
-
-	struct tasklet_struct  tasklet;
-	spinlock_t             lock;
-	wait_queue_head_t      wq;
-	int                    running;
-	u32                    stat;
-	u32                    cbuf;
-	u32                    coff;
-
-	struct dvb_adapter     adap;
-	struct dvb_device     *dev;
-	struct dvb_frontend   *fe;
-	struct dvb_frontend   *fe2;
-	struct dmxdev          dmxdev;
-	struct dvb_demux       demux;
-	struct dvb_net         dvbnet;
-	struct dmx_frontend    hw_frontend;
-	struct dmx_frontend    mem_frontend;
-	int                    users;
-	int (*gate_ctrl)(struct dvb_frontend *, int);
-};
-
-struct ddb_output {
-	struct ddb_port       *port;
-	u32                    nr;
-	dma_addr_t             pbuf[OUTPUT_DMA_MAX_BUFS];
-	u8                    *vbuf[OUTPUT_DMA_MAX_BUFS];
-	u32                    dma_buf_num;
-	u32                    dma_buf_size;
-	struct tasklet_struct  tasklet;
-	spinlock_t             lock;
-	wait_queue_head_t      wq;
-	int                    running;
-	u32                    stat;
-	u32                    cbuf;
-	u32                    coff;
-
-	struct dvb_adapter     adap;
-	struct dvb_device     *dev;
-};
-
-struct ddb_i2c {
-	struct ddb            *dev;
-	u32                    nr;
-	struct i2c_adapter     adap;
-	struct i2c_adapter     adap2;
-	u32                    regs;
-	u32                    rbuf;
-	u32                    wbuf;
-	int                    done;
-	wait_queue_head_t      wq;
-};
-
-struct ddb_port {
-	struct ddb            *dev;
-	u32                    nr;
-	struct ddb_i2c        *i2c;
-	struct mutex           i2c_gate_lock;
-	u32                    class;
-#define DDB_PORT_NONE           0
-#define DDB_PORT_CI             1
-#define DDB_PORT_TUNER          2
-	u32                    type;
-#define DDB_TUNER_NONE          0
-#define DDB_TUNER_DVBS_ST       1
-#define DDB_TUNER_DVBS_ST_AA    2
-#define DDB_TUNER_DVBCT_TR     16
-#define DDB_TUNER_DVBCT_ST     17
-	u32                    adr;
-
-	struct ddb_input      *input[2];
-	struct ddb_output     *output;
-	struct dvb_ca_en50221 *en;
-};
-
-struct ddb {
-	struct pci_dev        *pdev;
-	unsigned char         *regs;
-	struct ddb_port        port[DDB_MAX_PORT];
-	struct ddb_i2c         i2c[DDB_MAX_I2C];
-	struct ddb_input       input[DDB_MAX_INPUT];
-	struct ddb_output      output[DDB_MAX_OUTPUT];
-
-	struct device         *ddb_dev;
-	int                    nr;
-	u8                     iobuf[1028];
-
-	struct ddb_info       *info;
-	int                    msi;
-};
-
-/****************************************************************************/
-
-#define ddbwritel(_val, _adr)        writel((_val), \
-				     (char *) (dev->regs+(_adr)))
-#define ddbreadl(_adr)               readl((char *) (dev->regs+(_adr)))
-#define ddbcpyto(_adr, _src, _count) memcpy_toio((char *)	\
-				     (dev->regs+(_adr)), (_src), (_count))
-#define ddbcpyfrom(_dst, _adr, _count) memcpy_fromio((_dst), (char *) \
-				       (dev->regs+(_adr)), (_count))
-
-/****************************************************************************/
-
-#endif
diff --git a/drivers/media/dvb/dm1105/Kconfig b/drivers/media/dvb/dm1105/Kconfig
deleted file mode 100644
index f3de0a4..0000000
--- a/drivers/media/dvb/dm1105/Kconfig
+++ /dev/null
@@ -1,20 +0,0 @@
-config DVB_DM1105
-	tristate "SDMC DM1105 based PCI cards"
-	depends on DVB_CORE && PCI && I2C
-	select DVB_PLL if !DVB_FE_CUSTOMISE
-	select DVB_STV0299 if !DVB_FE_CUSTOMISE
-	select DVB_STV0288 if !DVB_FE_CUSTOMISE
-	select DVB_STB6000 if !DVB_FE_CUSTOMISE
-	select DVB_CX24116 if !DVB_FE_CUSTOMISE
-	select DVB_SI21XX if !DVB_FE_CUSTOMISE
-	select DVB_DS3000 if !DVB_FE_CUSTOMISE
-	depends on RC_CORE
-	help
-	  Support for cards based on the SDMC DM1105 PCI chip like
-	  DvbWorld 2002
-
-	  Since these cards have no MPEG decoder onboard, they transmit
-	  only compressed MPEG data over the PCI bus, so you need
-	  an external software decoder to watch TV on your computer.
-
-	  Say Y or M if you own such a device and want to use it.
diff --git a/drivers/media/dvb/dm1105/Makefile b/drivers/media/dvb/dm1105/Makefile
deleted file mode 100644
index 95a008b..0000000
--- a/drivers/media/dvb/dm1105/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-obj-$(CONFIG_DVB_DM1105) += dm1105.o
-
-ccflags-y += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends
diff --git a/drivers/media/dvb/dm1105/dm1105.c b/drivers/media/dvb/dm1105/dm1105.c
deleted file mode 100644
index a609b3a..0000000
--- a/drivers/media/dvb/dm1105/dm1105.c
+++ /dev/null
@@ -1,1248 +0,0 @@
-/*
- * dm1105.c - driver for DVB cards based on SDMC DM1105 PCI chip
- *
- * Copyright (C) 2008 Igor M. Liplianin <liplianin@me.by>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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/i2c.h>
-#include <linux/i2c-algo-bit.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/proc_fs.h>
-#include <linux/pci.h>
-#include <linux/dma-mapping.h>
-#include <linux/slab.h>
-#include <media/rc-core.h>
-
-#include "demux.h"
-#include "dmxdev.h"
-#include "dvb_demux.h"
-#include "dvb_frontend.h"
-#include "dvb_net.h"
-#include "dvbdev.h"
-#include "dvb-pll.h"
-
-#include "stv0299.h"
-#include "stv0288.h"
-#include "stb6000.h"
-#include "si21xx.h"
-#include "cx24116.h"
-#include "z0194a.h"
-#include "ds3000.h"
-
-#define MODULE_NAME "dm1105"
-
-#define UNSET (-1U)
-
-#define DM1105_BOARD_NOAUTO			UNSET
-#define DM1105_BOARD_UNKNOWN			0
-#define DM1105_BOARD_DVBWORLD_2002		1
-#define DM1105_BOARD_DVBWORLD_2004		2
-#define DM1105_BOARD_AXESS_DM05			3
-#define DM1105_BOARD_UNBRANDED_I2C_ON_GPIO	4
-
-/* ----------------------------------------------- */
-/*
- * PCI ID's
- */
-#ifndef PCI_VENDOR_ID_TRIGEM
-#define PCI_VENDOR_ID_TRIGEM	0x109f
-#endif
-#ifndef PCI_VENDOR_ID_AXESS
-#define PCI_VENDOR_ID_AXESS	0x195d
-#endif
-#ifndef PCI_DEVICE_ID_DM1105
-#define PCI_DEVICE_ID_DM1105	0x036f
-#endif
-#ifndef PCI_DEVICE_ID_DW2002
-#define PCI_DEVICE_ID_DW2002	0x2002
-#endif
-#ifndef PCI_DEVICE_ID_DW2004
-#define PCI_DEVICE_ID_DW2004	0x2004
-#endif
-#ifndef PCI_DEVICE_ID_DM05
-#define PCI_DEVICE_ID_DM05	0x1105
-#endif
-/* ----------------------------------------------- */
-/* sdmc dm1105 registers */
-
-/* TS Control */
-#define DM1105_TSCTR				0x00
-#define DM1105_DTALENTH				0x04
-
-/* GPIO Interface */
-#define DM1105_GPIOVAL				0x08
-#define DM1105_GPIOCTR				0x0c
-
-/* PID serial number */
-#define DM1105_PIDN				0x10
-
-/* Odd-even secret key select */
-#define DM1105_CWSEL				0x14
-
-/* Host Command Interface */
-#define DM1105_HOST_CTR				0x18
-#define DM1105_HOST_AD				0x1c
-
-/* PCI Interface */
-#define DM1105_CR				0x30
-#define DM1105_RST				0x34
-#define DM1105_STADR				0x38
-#define DM1105_RLEN				0x3c
-#define DM1105_WRP				0x40
-#define DM1105_INTCNT				0x44
-#define DM1105_INTMAK				0x48
-#define DM1105_INTSTS				0x4c
-
-/* CW Value */
-#define DM1105_ODD				0x50
-#define DM1105_EVEN				0x58
-
-/* PID Value */
-#define DM1105_PID				0x60
-
-/* IR Control */
-#define DM1105_IRCTR				0x64
-#define DM1105_IRMODE				0x68
-#define DM1105_SYSTEMCODE			0x6c
-#define DM1105_IRCODE				0x70
-
-/* Unknown Values */
-#define DM1105_ENCRYPT				0x74
-#define DM1105_VER				0x7c
-
-/* I2C Interface */
-#define DM1105_I2CCTR				0x80
-#define DM1105_I2CSTS				0x81
-#define DM1105_I2CDAT				0x82
-#define DM1105_I2C_RA				0x83
-/* ----------------------------------------------- */
-/* Interrupt Mask Bits */
-
-#define INTMAK_TSIRQM				0x01
-#define INTMAK_HIRQM				0x04
-#define INTMAK_IRM				0x08
-#define INTMAK_ALLMASK				(INTMAK_TSIRQM | \
-						INTMAK_HIRQM | \
-						INTMAK_IRM)
-#define INTMAK_NONEMASK				0x00
-
-/* Interrupt Status Bits */
-#define INTSTS_TSIRQ				0x01
-#define INTSTS_HIRQ				0x04
-#define INTSTS_IR				0x08
-
-/* IR Control Bits */
-#define DM1105_IR_EN				0x01
-#define DM1105_SYS_CHK				0x02
-#define DM1105_REP_FLG				0x08
-
-/* EEPROM addr */
-#define IIC_24C01_addr				0xa0
-/* Max board count */
-#define DM1105_MAX				0x04
-
-#define DRIVER_NAME				"dm1105"
-#define DM1105_I2C_GPIO_NAME			"dm1105-gpio"
-
-#define DM1105_DMA_PACKETS			47
-#define DM1105_DMA_PACKET_LENGTH		(128*4)
-#define DM1105_DMA_BYTES			(128 * 4 * DM1105_DMA_PACKETS)
-
-/*  */
-#define GPIO08					(1 << 8)
-#define GPIO13					(1 << 13)
-#define GPIO14					(1 << 14)
-#define GPIO15					(1 << 15)
-#define GPIO16					(1 << 16)
-#define GPIO17					(1 << 17)
-#define GPIO_ALL				0x03ffff
-
-/* GPIO's for LNB power control */
-#define DM1105_LNB_MASK				(GPIO_ALL & ~(GPIO14 | GPIO13))
-#define DM1105_LNB_OFF				GPIO17
-#define DM1105_LNB_13V				(GPIO16 | GPIO08)
-#define DM1105_LNB_18V				GPIO08
-
-/* GPIO's for LNB power control for Axess DM05 */
-#define DM05_LNB_MASK				(GPIO_ALL & ~(GPIO14 | GPIO13))
-#define DM05_LNB_OFF				GPIO17/* actually 13v */
-#define DM05_LNB_13V				GPIO17
-#define DM05_LNB_18V				(GPIO17 | GPIO16)
-
-/* GPIO's for LNB power control for unbranded with I2C on GPIO */
-#define UNBR_LNB_MASK				(GPIO17 | GPIO16)
-#define UNBR_LNB_OFF				0
-#define UNBR_LNB_13V				GPIO17
-#define UNBR_LNB_18V				(GPIO17 | GPIO16)
-
-static unsigned int card[]  = {[0 ... 3] = UNSET };
-module_param_array(card,  int, NULL, 0444);
-MODULE_PARM_DESC(card, "card type");
-
-static int ir_debug;
-module_param(ir_debug, int, 0644);
-MODULE_PARM_DESC(ir_debug, "enable debugging information for IR decoding");
-
-static unsigned int dm1105_devcount;
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-struct dm1105_board {
-	char	*name;
-	struct	{
-		u32	mask, off, v13, v18;
-	} lnb;
-	u32	gpio_scl, gpio_sda;
-};
-
-struct dm1105_subid {
-	u16     subvendor;
-	u16     subdevice;
-	u32     card;
-};
-
-static const struct dm1105_board dm1105_boards[] = {
-	[DM1105_BOARD_UNKNOWN] = {
-		.name		= "UNKNOWN/GENERIC",
-		.lnb = {
-			.mask = DM1105_LNB_MASK,
-			.off = DM1105_LNB_OFF,
-			.v13 = DM1105_LNB_13V,
-			.v18 = DM1105_LNB_18V,
-		},
-	},
-	[DM1105_BOARD_DVBWORLD_2002] = {
-		.name		= "DVBWorld PCI 2002",
-		.lnb = {
-			.mask = DM1105_LNB_MASK,
-			.off = DM1105_LNB_OFF,
-			.v13 = DM1105_LNB_13V,
-			.v18 = DM1105_LNB_18V,
-		},
-	},
-	[DM1105_BOARD_DVBWORLD_2004] = {
-		.name		= "DVBWorld PCI 2004",
-		.lnb = {
-			.mask = DM1105_LNB_MASK,
-			.off = DM1105_LNB_OFF,
-			.v13 = DM1105_LNB_13V,
-			.v18 = DM1105_LNB_18V,
-		},
-	},
-	[DM1105_BOARD_AXESS_DM05] = {
-		.name		= "Axess/EasyTv DM05",
-		.lnb = {
-			.mask = DM05_LNB_MASK,
-			.off = DM05_LNB_OFF,
-			.v13 = DM05_LNB_13V,
-			.v18 = DM05_LNB_18V,
-		},
-	},
-	[DM1105_BOARD_UNBRANDED_I2C_ON_GPIO] = {
-		.name		= "Unbranded DM1105 with i2c on GPIOs",
-		.lnb = {
-			.mask = UNBR_LNB_MASK,
-			.off = UNBR_LNB_OFF,
-			.v13 = UNBR_LNB_13V,
-			.v18 = UNBR_LNB_18V,
-		},
-		.gpio_scl	= GPIO14,
-		.gpio_sda	= GPIO13,
-	},
-};
-
-static const struct dm1105_subid dm1105_subids[] = {
-	{
-		.subvendor = 0x0000,
-		.subdevice = 0x2002,
-		.card      = DM1105_BOARD_DVBWORLD_2002,
-	}, {
-		.subvendor = 0x0001,
-		.subdevice = 0x2002,
-		.card      = DM1105_BOARD_DVBWORLD_2002,
-	}, {
-		.subvendor = 0x0000,
-		.subdevice = 0x2004,
-		.card      = DM1105_BOARD_DVBWORLD_2004,
-	}, {
-		.subvendor = 0x0001,
-		.subdevice = 0x2004,
-		.card      = DM1105_BOARD_DVBWORLD_2004,
-	}, {
-		.subvendor = 0x195d,
-		.subdevice = 0x1105,
-		.card      = DM1105_BOARD_AXESS_DM05,
-	},
-};
-
-static void dm1105_card_list(struct pci_dev *pci)
-{
-	int i;
-
-	if (0 == pci->subsystem_vendor &&
-			0 == pci->subsystem_device) {
-		printk(KERN_ERR
-			"dm1105: Your board has no valid PCI Subsystem ID\n"
-			"dm1105: and thus can't be autodetected\n"
-			"dm1105: Please pass card=<n> insmod option to\n"
-			"dm1105: workaround that.  Redirect complaints to\n"
-			"dm1105: the vendor of the TV card.  Best regards,\n"
-			"dm1105: -- tux\n");
-	} else {
-		printk(KERN_ERR
-			"dm1105: Your board isn't known (yet) to the driver.\n"
-			"dm1105: You can try to pick one of the existing\n"
-			"dm1105: card configs via card=<n> insmod option.\n"
-			"dm1105: Updating to the latest version might help\n"
-			"dm1105: as well.\n");
-	}
-	printk(KERN_ERR "Here is a list of valid choices for the card=<n> "
-		   "insmod option:\n");
-	for (i = 0; i < ARRAY_SIZE(dm1105_boards); i++)
-		printk(KERN_ERR "dm1105:    card=%d -> %s\n",
-				i, dm1105_boards[i].name);
-}
-
-/* infrared remote control */
-struct infrared {
-	struct rc_dev		*dev;
-	char			input_phys[32];
-	struct work_struct	work;
-	u32			ir_command;
-};
-
-struct dm1105_dev {
-	/* pci */
-	struct pci_dev *pdev;
-	u8 __iomem *io_mem;
-
-	/* ir */
-	struct infrared ir;
-
-	/* dvb */
-	struct dmx_frontend hw_frontend;
-	struct dmx_frontend mem_frontend;
-	struct dmxdev dmxdev;
-	struct dvb_adapter dvb_adapter;
-	struct dvb_demux demux;
-	struct dvb_frontend *fe;
-	struct dvb_net dvbnet;
-	unsigned int full_ts_users;
-	unsigned int boardnr;
-	int nr;
-
-	/* i2c */
-	struct i2c_adapter i2c_adap;
-	struct i2c_adapter i2c_bb_adap;
-	struct i2c_algo_bit_data i2c_bit;
-
-	/* irq */
-	struct work_struct work;
-	struct workqueue_struct *wq;
-	char wqn[16];
-
-	/* dma */
-	dma_addr_t dma_addr;
-	unsigned char *ts_buf;
-	u32 wrp;
-	u32 nextwrp;
-	u32 buffer_size;
-	unsigned int	PacketErrorCount;
-	unsigned int dmarst;
-	spinlock_t lock;
-};
-
-#define dm_io_mem(reg)	((unsigned long)(&dev->io_mem[reg]))
-
-#define dm_readb(reg)		inb(dm_io_mem(reg))
-#define dm_writeb(reg, value)	outb((value), (dm_io_mem(reg)))
-
-#define dm_readw(reg)		inw(dm_io_mem(reg))
-#define dm_writew(reg, value)	outw((value), (dm_io_mem(reg)))
-
-#define dm_readl(reg)		inl(dm_io_mem(reg))
-#define dm_writel(reg, value)	outl((value), (dm_io_mem(reg)))
-
-#define dm_andorl(reg, mask, value) \
-	outl((inl(dm_io_mem(reg)) & ~(mask)) |\
-		((value) & (mask)), (dm_io_mem(reg)))
-
-#define dm_setl(reg, bit)	dm_andorl((reg), (bit), (bit))
-#define dm_clearl(reg, bit)	dm_andorl((reg), (bit), 0)
-
-/* The chip has 18 GPIOs. In HOST mode GPIO's used as 15 bit address lines,
- so we can use only 3 GPIO's from GPIO15 to GPIO17.
- Here I don't check whether HOST is enebled as it is not implemented yet.
- */
-static void dm1105_gpio_set(struct dm1105_dev *dev, u32 mask)
-{
-	if (mask & 0xfffc0000)
-		printk(KERN_ERR "%s: Only 18 GPIO's are allowed\n", __func__);
-
-	if (mask & 0x0003ffff)
-		dm_setl(DM1105_GPIOVAL, mask & 0x0003ffff);
-
-}
-
-static void dm1105_gpio_clear(struct dm1105_dev *dev, u32 mask)
-{
-	if (mask & 0xfffc0000)
-		printk(KERN_ERR "%s: Only 18 GPIO's are allowed\n", __func__);
-
-	if (mask & 0x0003ffff)
-		dm_clearl(DM1105_GPIOVAL, mask & 0x0003ffff);
-
-}
-
-static void dm1105_gpio_andor(struct dm1105_dev *dev, u32 mask, u32 val)
-{
-	if (mask & 0xfffc0000)
-		printk(KERN_ERR "%s: Only 18 GPIO's are allowed\n", __func__);
-
-	if (mask & 0x0003ffff)
-		dm_andorl(DM1105_GPIOVAL, mask & 0x0003ffff, val);
-
-}
-
-static u32 dm1105_gpio_get(struct dm1105_dev *dev, u32 mask)
-{
-	if (mask & 0xfffc0000)
-		printk(KERN_ERR "%s: Only 18 GPIO's are allowed\n", __func__);
-
-	if (mask & 0x0003ffff)
-		return dm_readl(DM1105_GPIOVAL) & mask & 0x0003ffff;
-
-	return 0;
-}
-
-static void dm1105_gpio_enable(struct dm1105_dev *dev, u32 mask, int asoutput)
-{
-	if (mask & 0xfffc0000)
-		printk(KERN_ERR "%s: Only 18 GPIO's are allowed\n", __func__);
-
-	if ((mask & 0x0003ffff) && asoutput)
-		dm_clearl(DM1105_GPIOCTR, mask & 0x0003ffff);
-	else if ((mask & 0x0003ffff) && !asoutput)
-		dm_setl(DM1105_GPIOCTR, mask & 0x0003ffff);
-
-}
-
-static void dm1105_setline(struct dm1105_dev *dev, u32 line, int state)
-{
-	if (state)
-		dm1105_gpio_enable(dev, line, 0);
-	else {
-		dm1105_gpio_enable(dev, line, 1);
-		dm1105_gpio_clear(dev, line);
-	}
-}
-
-static void dm1105_setsda(void *data, int state)
-{
-	struct dm1105_dev *dev = data;
-
-	dm1105_setline(dev, dm1105_boards[dev->boardnr].gpio_sda, state);
-}
-
-static void dm1105_setscl(void *data, int state)
-{
-	struct dm1105_dev *dev = data;
-
-	dm1105_setline(dev, dm1105_boards[dev->boardnr].gpio_scl, state);
-}
-
-static int dm1105_getsda(void *data)
-{
-	struct dm1105_dev *dev = data;
-
-	return dm1105_gpio_get(dev, dm1105_boards[dev->boardnr].gpio_sda)
-									? 1 : 0;
-}
-
-static int dm1105_getscl(void *data)
-{
-	struct dm1105_dev *dev = data;
-
-	return dm1105_gpio_get(dev, dm1105_boards[dev->boardnr].gpio_scl)
-									? 1 : 0;
-}
-
-static int dm1105_i2c_xfer(struct i2c_adapter *i2c_adap,
-			    struct i2c_msg *msgs, int num)
-{
-	struct dm1105_dev *dev ;
-
-	int addr, rc, i, j, k, len, byte, data;
-	u8 status;
-
-	dev = i2c_adap->algo_data;
-	for (i = 0; i < num; i++) {
-		dm_writeb(DM1105_I2CCTR, 0x00);
-		if (msgs[i].flags & I2C_M_RD) {
-			/* read bytes */
-			addr  = msgs[i].addr << 1;
-			addr |= 1;
-			dm_writeb(DM1105_I2CDAT, addr);
-			for (byte = 0; byte < msgs[i].len; byte++)
-				dm_writeb(DM1105_I2CDAT + byte + 1, 0);
-
-			dm_writeb(DM1105_I2CCTR, 0x81 + msgs[i].len);
-			for (j = 0; j < 55; j++) {
-				mdelay(10);
-				status = dm_readb(DM1105_I2CSTS);
-				if ((status & 0xc0) == 0x40)
-					break;
-			}
-			if (j >= 55)
-				return -1;
-
-			for (byte = 0; byte < msgs[i].len; byte++) {
-				rc = dm_readb(DM1105_I2CDAT + byte + 1);
-				if (rc < 0)
-					goto err;
-				msgs[i].buf[byte] = rc;
-			}
-		} else if ((msgs[i].buf[0] == 0xf7) && (msgs[i].addr == 0x55)) {
-			/* prepaired for cx24116 firmware */
-			/* Write in small blocks */
-			len = msgs[i].len - 1;
-			k = 1;
-			do {
-				dm_writeb(DM1105_I2CDAT, msgs[i].addr << 1);
-				dm_writeb(DM1105_I2CDAT + 1, 0xf7);
-				for (byte = 0; byte < (len > 48 ? 48 : len); byte++) {
-					data = msgs[i].buf[k + byte];
-					dm_writeb(DM1105_I2CDAT + byte + 2, data);
-				}
-				dm_writeb(DM1105_I2CCTR, 0x82 + (len > 48 ? 48 : len));
-				for (j = 0; j < 25; j++) {
-					mdelay(10);
-					status = dm_readb(DM1105_I2CSTS);
-					if ((status & 0xc0) == 0x40)
-						break;
-				}
-
-				if (j >= 25)
-					return -1;
-
-				k += 48;
-				len -= 48;
-			} while (len > 0);
-		} else {
-			/* write bytes */
-			dm_writeb(DM1105_I2CDAT, msgs[i].addr << 1);
-			for (byte = 0; byte < msgs[i].len; byte++) {
-				data = msgs[i].buf[byte];
-				dm_writeb(DM1105_I2CDAT + byte + 1, data);
-			}
-			dm_writeb(DM1105_I2CCTR, 0x81 + msgs[i].len);
-			for (j = 0; j < 25; j++) {
-				mdelay(10);
-				status = dm_readb(DM1105_I2CSTS);
-				if ((status & 0xc0) == 0x40)
-					break;
-			}
-
-			if (j >= 25)
-				return -1;
-		}
-	}
-	return num;
- err:
-	return rc;
-}
-
-static u32 functionality(struct i2c_adapter *adap)
-{
-	return I2C_FUNC_I2C;
-}
-
-static struct i2c_algorithm dm1105_algo = {
-	.master_xfer   = dm1105_i2c_xfer,
-	.functionality = functionality,
-};
-
-static inline struct dm1105_dev *feed_to_dm1105_dev(struct dvb_demux_feed *feed)
-{
-	return container_of(feed->demux, struct dm1105_dev, demux);
-}
-
-static inline struct dm1105_dev *frontend_to_dm1105_dev(struct dvb_frontend *fe)
-{
-	return container_of(fe->dvb, struct dm1105_dev, dvb_adapter);
-}
-
-static int dm1105_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
-{
-	struct dm1105_dev *dev = frontend_to_dm1105_dev(fe);
-
-	dm1105_gpio_enable(dev, dm1105_boards[dev->boardnr].lnb.mask, 1);
-	if (voltage == SEC_VOLTAGE_18)
-		dm1105_gpio_andor(dev,
-				dm1105_boards[dev->boardnr].lnb.mask,
-				dm1105_boards[dev->boardnr].lnb.v18);
-	else if (voltage == SEC_VOLTAGE_13)
-		dm1105_gpio_andor(dev,
-				dm1105_boards[dev->boardnr].lnb.mask,
-				dm1105_boards[dev->boardnr].lnb.v13);
-	else
-		dm1105_gpio_andor(dev,
-				dm1105_boards[dev->boardnr].lnb.mask,
-				dm1105_boards[dev->boardnr].lnb.off);
-
-	return 0;
-}
-
-static void dm1105_set_dma_addr(struct dm1105_dev *dev)
-{
-	dm_writel(DM1105_STADR, cpu_to_le32(dev->dma_addr));
-}
-
-static int __devinit dm1105_dma_map(struct dm1105_dev *dev)
-{
-	dev->ts_buf = pci_alloc_consistent(dev->pdev,
-					6 * DM1105_DMA_BYTES,
-					&dev->dma_addr);
-
-	return !dev->ts_buf;
-}
-
-static void dm1105_dma_unmap(struct dm1105_dev *dev)
-{
-	pci_free_consistent(dev->pdev,
-			6 * DM1105_DMA_BYTES,
-			dev->ts_buf,
-			dev->dma_addr);
-}
-
-static void dm1105_enable_irqs(struct dm1105_dev *dev)
-{
-	dm_writeb(DM1105_INTMAK, INTMAK_ALLMASK);
-	dm_writeb(DM1105_CR, 1);
-}
-
-static void dm1105_disable_irqs(struct dm1105_dev *dev)
-{
-	dm_writeb(DM1105_INTMAK, INTMAK_IRM);
-	dm_writeb(DM1105_CR, 0);
-}
-
-static int dm1105_start_feed(struct dvb_demux_feed *f)
-{
-	struct dm1105_dev *dev = feed_to_dm1105_dev(f);
-
-	if (dev->full_ts_users++ == 0)
-		dm1105_enable_irqs(dev);
-
-	return 0;
-}
-
-static int dm1105_stop_feed(struct dvb_demux_feed *f)
-{
-	struct dm1105_dev *dev = feed_to_dm1105_dev(f);
-
-	if (--dev->full_ts_users == 0)
-		dm1105_disable_irqs(dev);
-
-	return 0;
-}
-
-/* ir work handler */
-static void dm1105_emit_key(struct work_struct *work)
-{
-	struct infrared *ir = container_of(work, struct infrared, work);
-	u32 ircom = ir->ir_command;
-	u8 data;
-
-	if (ir_debug)
-		printk(KERN_INFO "%s: received byte 0x%04x\n", __func__, ircom);
-
-	data = (ircom >> 8) & 0x7f;
-
-	rc_keydown(ir->dev, data, 0);
-}
-
-/* work handler */
-static void dm1105_dmx_buffer(struct work_struct *work)
-{
-	struct dm1105_dev *dev = container_of(work, struct dm1105_dev, work);
-	unsigned int nbpackets;
-	u32 oldwrp = dev->wrp;
-	u32 nextwrp = dev->nextwrp;
-
-	if (!((dev->ts_buf[oldwrp] == 0x47) &&
-			(dev->ts_buf[oldwrp + 188] == 0x47) &&
-			(dev->ts_buf[oldwrp + 188 * 2] == 0x47))) {
-		dev->PacketErrorCount++;
-		/* bad packet found */
-		if ((dev->PacketErrorCount >= 2) &&
-				(dev->dmarst == 0)) {
-			dm_writeb(DM1105_RST, 1);
-			dev->wrp = 0;
-			dev->PacketErrorCount = 0;
-			dev->dmarst = 0;
-			return;
-		}
-	}
-
-	if (nextwrp < oldwrp) {
-		memcpy(dev->ts_buf + dev->buffer_size, dev->ts_buf, nextwrp);
-		nbpackets = ((dev->buffer_size - oldwrp) + nextwrp) / 188;
-	} else
-		nbpackets = (nextwrp - oldwrp) / 188;
-
-	dev->wrp = nextwrp;
-	dvb_dmx_swfilter_packets(&dev->demux, &dev->ts_buf[oldwrp], nbpackets);
-}
-
-static irqreturn_t dm1105_irq(int irq, void *dev_id)
-{
-	struct dm1105_dev *dev = dev_id;
-
-	/* Read-Write INSTS Ack's Interrupt for DM1105 chip 16.03.2008 */
-	unsigned int intsts = dm_readb(DM1105_INTSTS);
-	dm_writeb(DM1105_INTSTS, intsts);
-
-	switch (intsts) {
-	case INTSTS_TSIRQ:
-	case (INTSTS_TSIRQ | INTSTS_IR):
-		dev->nextwrp = dm_readl(DM1105_WRP) - dm_readl(DM1105_STADR);
-		queue_work(dev->wq, &dev->work);
-		break;
-	case INTSTS_IR:
-		dev->ir.ir_command = dm_readl(DM1105_IRCODE);
-		schedule_work(&dev->ir.work);
-		break;
-	}
-
-	return IRQ_HANDLED;
-}
-
-int __devinit dm1105_ir_init(struct dm1105_dev *dm1105)
-{
-	struct rc_dev *dev;
-	int err = -ENOMEM;
-
-	dev = rc_allocate_device();
-	if (!dev)
-		return -ENOMEM;
-
-	snprintf(dm1105->ir.input_phys, sizeof(dm1105->ir.input_phys),
-		"pci-%s/ir0", pci_name(dm1105->pdev));
-
-	dev->driver_name = MODULE_NAME;
-	dev->map_name = RC_MAP_DM1105_NEC;
-	dev->driver_type = RC_DRIVER_SCANCODE;
-	dev->input_name = "DVB on-card IR receiver";
-	dev->input_phys = dm1105->ir.input_phys;
-	dev->input_id.bustype = BUS_PCI;
-	dev->input_id.version = 1;
-	if (dm1105->pdev->subsystem_vendor) {
-		dev->input_id.vendor = dm1105->pdev->subsystem_vendor;
-		dev->input_id.product = dm1105->pdev->subsystem_device;
-	} else {
-		dev->input_id.vendor = dm1105->pdev->vendor;
-		dev->input_id.product = dm1105->pdev->device;
-	}
-	dev->dev.parent = &dm1105->pdev->dev;
-
-	INIT_WORK(&dm1105->ir.work, dm1105_emit_key);
-
-	err = rc_register_device(dev);
-	if (err < 0) {
-		rc_free_device(dev);
-		return err;
-	}
-
-	dm1105->ir.dev = dev;
-	return 0;
-}
-
-void __devexit dm1105_ir_exit(struct dm1105_dev *dm1105)
-{
-	rc_unregister_device(dm1105->ir.dev);
-}
-
-static int __devinit dm1105_hw_init(struct dm1105_dev *dev)
-{
-	dm1105_disable_irqs(dev);
-
-	dm_writeb(DM1105_HOST_CTR, 0);
-
-	/*DATALEN 188,*/
-	dm_writeb(DM1105_DTALENTH, 188);
-	/*TS_STRT TS_VALP MSBFIRST TS_MODE ALPAS TSPES*/
-	dm_writew(DM1105_TSCTR, 0xc10a);
-
-	/* map DMA and set address */
-	dm1105_dma_map(dev);
-	dm1105_set_dma_addr(dev);
-	/* big buffer */
-	dm_writel(DM1105_RLEN, 5 * DM1105_DMA_BYTES);
-	dm_writeb(DM1105_INTCNT, 47);
-
-	/* IR NEC mode enable */
-	dm_writeb(DM1105_IRCTR, (DM1105_IR_EN | DM1105_SYS_CHK));
-	dm_writeb(DM1105_IRMODE, 0);
-	dm_writew(DM1105_SYSTEMCODE, 0);
-
-	return 0;
-}
-
-static void dm1105_hw_exit(struct dm1105_dev *dev)
-{
-	dm1105_disable_irqs(dev);
-
-	/* IR disable */
-	dm_writeb(DM1105_IRCTR, 0);
-	dm_writeb(DM1105_INTMAK, INTMAK_NONEMASK);
-
-	dm1105_dma_unmap(dev);
-}
-
-static struct stv0299_config sharp_z0194a_config = {
-	.demod_address = 0x68,
-	.inittab = sharp_z0194a_inittab,
-	.mclk = 88000000UL,
-	.invert = 1,
-	.skip_reinit = 0,
-	.lock_output = STV0299_LOCKOUTPUT_1,
-	.volt13_op0_op1 = STV0299_VOLT13_OP1,
-	.min_delay_ms = 100,
-	.set_symbol_rate = sharp_z0194a_set_symbol_rate,
-};
-
-static struct stv0288_config earda_config = {
-	.demod_address = 0x68,
-	.min_delay_ms = 100,
-};
-
-static struct si21xx_config serit_config = {
-	.demod_address = 0x68,
-	.min_delay_ms = 100,
-
-};
-
-static struct cx24116_config serit_sp2633_config = {
-	.demod_address = 0x55,
-};
-
-static struct ds3000_config dvbworld_ds3000_config = {
-	.demod_address = 0x68,
-};
-
-static int __devinit frontend_init(struct dm1105_dev *dev)
-{
-	int ret;
-
-	switch (dev->boardnr) {
-	case DM1105_BOARD_UNBRANDED_I2C_ON_GPIO:
-		dm1105_gpio_enable(dev, GPIO15, 1);
-		dm1105_gpio_clear(dev, GPIO15);
-		msleep(100);
-		dm1105_gpio_set(dev, GPIO15);
-		msleep(200);
-		dev->fe = dvb_attach(
-			stv0299_attach, &sharp_z0194a_config,
-			&dev->i2c_bb_adap);
-		if (dev->fe) {
-			dev->fe->ops.set_voltage = dm1105_set_voltage;
-			dvb_attach(dvb_pll_attach, dev->fe, 0x60,
-					&dev->i2c_bb_adap, DVB_PLL_OPERA1);
-			break;
-		}
-
-		dev->fe = dvb_attach(
-			stv0288_attach, &earda_config,
-			&dev->i2c_bb_adap);
-		if (dev->fe) {
-			dev->fe->ops.set_voltage = dm1105_set_voltage;
-			dvb_attach(stb6000_attach, dev->fe, 0x61,
-					&dev->i2c_bb_adap);
-			break;
-		}
-
-		dev->fe = dvb_attach(
-			si21xx_attach, &serit_config,
-			&dev->i2c_bb_adap);
-		if (dev->fe)
-			dev->fe->ops.set_voltage = dm1105_set_voltage;
-		break;
-	case DM1105_BOARD_DVBWORLD_2004:
-		dev->fe = dvb_attach(
-			cx24116_attach, &serit_sp2633_config,
-			&dev->i2c_adap);
-		if (dev->fe) {
-			dev->fe->ops.set_voltage = dm1105_set_voltage;
-			break;
-		}
-
-		dev->fe = dvb_attach(
-			ds3000_attach, &dvbworld_ds3000_config,
-			&dev->i2c_adap);
-		if (dev->fe)
-			dev->fe->ops.set_voltage = dm1105_set_voltage;
-
-		break;
-	case DM1105_BOARD_DVBWORLD_2002:
-	case DM1105_BOARD_AXESS_DM05:
-	default:
-		dev->fe = dvb_attach(
-			stv0299_attach, &sharp_z0194a_config,
-			&dev->i2c_adap);
-		if (dev->fe) {
-			dev->fe->ops.set_voltage = dm1105_set_voltage;
-			dvb_attach(dvb_pll_attach, dev->fe, 0x60,
-					&dev->i2c_adap, DVB_PLL_OPERA1);
-			break;
-		}
-
-		dev->fe = dvb_attach(
-			stv0288_attach, &earda_config,
-			&dev->i2c_adap);
-		if (dev->fe) {
-			dev->fe->ops.set_voltage = dm1105_set_voltage;
-			dvb_attach(stb6000_attach, dev->fe, 0x61,
-					&dev->i2c_adap);
-			break;
-		}
-
-		dev->fe = dvb_attach(
-			si21xx_attach, &serit_config,
-			&dev->i2c_adap);
-		if (dev->fe)
-			dev->fe->ops.set_voltage = dm1105_set_voltage;
-
-	}
-
-	if (!dev->fe) {
-		dev_err(&dev->pdev->dev, "could not attach frontend\n");
-		return -ENODEV;
-	}
-
-	ret = dvb_register_frontend(&dev->dvb_adapter, dev->fe);
-	if (ret < 0) {
-		if (dev->fe->ops.release)
-			dev->fe->ops.release(dev->fe);
-		dev->fe = NULL;
-		return ret;
-	}
-
-	return 0;
-}
-
-static void __devinit dm1105_read_mac(struct dm1105_dev *dev, u8 *mac)
-{
-	static u8 command[1] = { 0x28 };
-
-	struct i2c_msg msg[] = {
-		{
-			.addr = IIC_24C01_addr >> 1,
-			.flags = 0,
-			.buf = command,
-			.len = 1
-		}, {
-			.addr = IIC_24C01_addr >> 1,
-			.flags = I2C_M_RD,
-			.buf = mac,
-			.len = 6
-		},
-	};
-
-	dm1105_i2c_xfer(&dev->i2c_adap, msg , 2);
-	dev_info(&dev->pdev->dev, "MAC %pM\n", mac);
-}
-
-static int __devinit dm1105_probe(struct pci_dev *pdev,
-				  const struct pci_device_id *ent)
-{
-	struct dm1105_dev *dev;
-	struct dvb_adapter *dvb_adapter;
-	struct dvb_demux *dvbdemux;
-	struct dmx_demux *dmx;
-	int ret = -ENOMEM;
-	int i;
-
-	dev = kzalloc(sizeof(struct dm1105_dev), GFP_KERNEL);
-	if (!dev)
-		return -ENOMEM;
-
-	/* board config */
-	dev->nr = dm1105_devcount;
-	dev->boardnr = UNSET;
-	if (card[dev->nr] < ARRAY_SIZE(dm1105_boards))
-		dev->boardnr = card[dev->nr];
-	for (i = 0; UNSET == dev->boardnr &&
-				i < ARRAY_SIZE(dm1105_subids); i++)
-		if (pdev->subsystem_vendor ==
-			dm1105_subids[i].subvendor &&
-				pdev->subsystem_device ==
-					dm1105_subids[i].subdevice)
-			dev->boardnr = dm1105_subids[i].card;
-
-	if (UNSET == dev->boardnr) {
-		dev->boardnr = DM1105_BOARD_UNKNOWN;
-		dm1105_card_list(pdev);
-	}
-
-	dm1105_devcount++;
-	dev->pdev = pdev;
-	dev->buffer_size = 5 * DM1105_DMA_BYTES;
-	dev->PacketErrorCount = 0;
-	dev->dmarst = 0;
-
-	ret = pci_enable_device(pdev);
-	if (ret < 0)
-		goto err_kfree;
-
-	ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
-	if (ret < 0)
-		goto err_pci_disable_device;
-
-	pci_set_master(pdev);
-
-	ret = pci_request_regions(pdev, DRIVER_NAME);
-	if (ret < 0)
-		goto err_pci_disable_device;
-
-	dev->io_mem = pci_iomap(pdev, 0, pci_resource_len(pdev, 0));
-	if (!dev->io_mem) {
-		ret = -EIO;
-		goto err_pci_release_regions;
-	}
-
-	spin_lock_init(&dev->lock);
-	pci_set_drvdata(pdev, dev);
-
-	ret = dm1105_hw_init(dev);
-	if (ret < 0)
-		goto err_pci_iounmap;
-
-	/* i2c */
-	i2c_set_adapdata(&dev->i2c_adap, dev);
-	strcpy(dev->i2c_adap.name, DRIVER_NAME);
-	dev->i2c_adap.owner = THIS_MODULE;
-	dev->i2c_adap.dev.parent = &pdev->dev;
-	dev->i2c_adap.algo = &dm1105_algo;
-	dev->i2c_adap.algo_data = dev;
-	ret = i2c_add_adapter(&dev->i2c_adap);
-
-	if (ret < 0)
-		goto err_dm1105_hw_exit;
-
-	i2c_set_adapdata(&dev->i2c_bb_adap, dev);
-	strcpy(dev->i2c_bb_adap.name, DM1105_I2C_GPIO_NAME);
-	dev->i2c_bb_adap.owner = THIS_MODULE;
-	dev->i2c_bb_adap.dev.parent = &pdev->dev;
-	dev->i2c_bb_adap.algo_data = &dev->i2c_bit;
-	dev->i2c_bit.data = dev;
-	dev->i2c_bit.setsda = dm1105_setsda;
-	dev->i2c_bit.setscl = dm1105_setscl;
-	dev->i2c_bit.getsda = dm1105_getsda;
-	dev->i2c_bit.getscl = dm1105_getscl;
-	dev->i2c_bit.udelay = 10;
-	dev->i2c_bit.timeout = 10;
-
-	/* Raise SCL and SDA */
-	dm1105_setsda(dev, 1);
-	dm1105_setscl(dev, 1);
-
-	ret = i2c_bit_add_bus(&dev->i2c_bb_adap);
-	if (ret < 0)
-		goto err_i2c_del_adapter;
-
-	/* dvb */
-	ret = dvb_register_adapter(&dev->dvb_adapter, DRIVER_NAME,
-					THIS_MODULE, &pdev->dev, adapter_nr);
-	if (ret < 0)
-		goto err_i2c_del_adapters;
-
-	dvb_adapter = &dev->dvb_adapter;
-
-	dm1105_read_mac(dev, dvb_adapter->proposed_mac);
-
-	dvbdemux = &dev->demux;
-	dvbdemux->filternum = 256;
-	dvbdemux->feednum = 256;
-	dvbdemux->start_feed = dm1105_start_feed;
-	dvbdemux->stop_feed = dm1105_stop_feed;
-	dvbdemux->dmx.capabilities = (DMX_TS_FILTERING |
-			DMX_SECTION_FILTERING | DMX_MEMORY_BASED_FILTERING);
-	ret = dvb_dmx_init(dvbdemux);
-	if (ret < 0)
-		goto err_dvb_unregister_adapter;
-
-	dmx = &dvbdemux->dmx;
-	dev->dmxdev.filternum = 256;
-	dev->dmxdev.demux = dmx;
-	dev->dmxdev.capabilities = 0;
-
-	ret = dvb_dmxdev_init(&dev->dmxdev, dvb_adapter);
-	if (ret < 0)
-		goto err_dvb_dmx_release;
-
-	dev->hw_frontend.source = DMX_FRONTEND_0;
-
-	ret = dmx->add_frontend(dmx, &dev->hw_frontend);
-	if (ret < 0)
-		goto err_dvb_dmxdev_release;
-
-	dev->mem_frontend.source = DMX_MEMORY_FE;
-
-	ret = dmx->add_frontend(dmx, &dev->mem_frontend);
-	if (ret < 0)
-		goto err_remove_hw_frontend;
-
-	ret = dmx->connect_frontend(dmx, &dev->hw_frontend);
-	if (ret < 0)
-		goto err_remove_mem_frontend;
-
-	ret = dvb_net_init(dvb_adapter, &dev->dvbnet, dmx);
-	if (ret < 0)
-		goto err_disconnect_frontend;
-
-	ret = frontend_init(dev);
-	if (ret < 0)
-		goto err_dvb_net;
-
-	dm1105_ir_init(dev);
-
-	INIT_WORK(&dev->work, dm1105_dmx_buffer);
-	sprintf(dev->wqn, "%s/%d", dvb_adapter->name, dvb_adapter->num);
-	dev->wq = create_singlethread_workqueue(dev->wqn);
-	if (!dev->wq)
-		goto err_dvb_net;
-
-	ret = request_irq(pdev->irq, dm1105_irq, IRQF_SHARED,
-						DRIVER_NAME, dev);
-	if (ret < 0)
-		goto err_workqueue;
-
-	return 0;
-
-err_workqueue:
-	destroy_workqueue(dev->wq);
-err_dvb_net:
-	dvb_net_release(&dev->dvbnet);
-err_disconnect_frontend:
-	dmx->disconnect_frontend(dmx);
-err_remove_mem_frontend:
-	dmx->remove_frontend(dmx, &dev->mem_frontend);
-err_remove_hw_frontend:
-	dmx->remove_frontend(dmx, &dev->hw_frontend);
-err_dvb_dmxdev_release:
-	dvb_dmxdev_release(&dev->dmxdev);
-err_dvb_dmx_release:
-	dvb_dmx_release(dvbdemux);
-err_dvb_unregister_adapter:
-	dvb_unregister_adapter(dvb_adapter);
-err_i2c_del_adapters:
-	i2c_del_adapter(&dev->i2c_bb_adap);
-err_i2c_del_adapter:
-	i2c_del_adapter(&dev->i2c_adap);
-err_dm1105_hw_exit:
-	dm1105_hw_exit(dev);
-err_pci_iounmap:
-	pci_iounmap(pdev, dev->io_mem);
-err_pci_release_regions:
-	pci_release_regions(pdev);
-err_pci_disable_device:
-	pci_disable_device(pdev);
-err_kfree:
-	pci_set_drvdata(pdev, NULL);
-	kfree(dev);
-	return ret;
-}
-
-static void __devexit dm1105_remove(struct pci_dev *pdev)
-{
-	struct dm1105_dev *dev = pci_get_drvdata(pdev);
-	struct dvb_adapter *dvb_adapter = &dev->dvb_adapter;
-	struct dvb_demux *dvbdemux = &dev->demux;
-	struct dmx_demux *dmx = &dvbdemux->dmx;
-
-	dm1105_ir_exit(dev);
-	dmx->close(dmx);
-	dvb_net_release(&dev->dvbnet);
-	if (dev->fe)
-		dvb_unregister_frontend(dev->fe);
-
-	dmx->disconnect_frontend(dmx);
-	dmx->remove_frontend(dmx, &dev->mem_frontend);
-	dmx->remove_frontend(dmx, &dev->hw_frontend);
-	dvb_dmxdev_release(&dev->dmxdev);
-	dvb_dmx_release(dvbdemux);
-	dvb_unregister_adapter(dvb_adapter);
-	if (&dev->i2c_adap)
-		i2c_del_adapter(&dev->i2c_adap);
-
-	dm1105_hw_exit(dev);
-	synchronize_irq(pdev->irq);
-	free_irq(pdev->irq, dev);
-	pci_iounmap(pdev, dev->io_mem);
-	pci_release_regions(pdev);
-	pci_disable_device(pdev);
-	pci_set_drvdata(pdev, NULL);
-	dm1105_devcount--;
-	kfree(dev);
-}
-
-static struct pci_device_id dm1105_id_table[] __devinitdata = {
-	{
-		.vendor = PCI_VENDOR_ID_TRIGEM,
-		.device = PCI_DEVICE_ID_DM1105,
-		.subvendor = PCI_ANY_ID,
-		.subdevice = PCI_ANY_ID,
-	}, {
-		.vendor = PCI_VENDOR_ID_AXESS,
-		.device = PCI_DEVICE_ID_DM05,
-		.subvendor = PCI_ANY_ID,
-		.subdevice = PCI_ANY_ID,
-	}, {
-		/* empty */
-	},
-};
-
-MODULE_DEVICE_TABLE(pci, dm1105_id_table);
-
-static struct pci_driver dm1105_driver = {
-	.name = DRIVER_NAME,
-	.id_table = dm1105_id_table,
-	.probe = dm1105_probe,
-	.remove = __devexit_p(dm1105_remove),
-};
-
-static int __init dm1105_init(void)
-{
-	return pci_register_driver(&dm1105_driver);
-}
-
-static void __exit dm1105_exit(void)
-{
-	pci_unregister_driver(&dm1105_driver);
-}
-
-module_init(dm1105_init);
-module_exit(dm1105_exit);
-
-MODULE_AUTHOR("Igor M. Liplianin <liplianin@me.by>");
-MODULE_DESCRIPTION("SDMC DM1105 DVB driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-core/Makefile b/drivers/media/dvb/dvb-core/Makefile
deleted file mode 100644
index 8f22bcd..0000000
--- a/drivers/media/dvb/dvb-core/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-#
-# Makefile for the kernel DVB device drivers.
-#
-
-dvb-net-$(CONFIG_DVB_NET) := dvb_net.o
-
-dvb-core-objs := dvbdev.o dmxdev.o dvb_demux.o dvb_filter.o 	\
-		 dvb_ca_en50221.o dvb_frontend.o 		\
-		 $(dvb-net-y) dvb_ringbuffer.o dvb_math.o
-
-obj-$(CONFIG_DVB_CORE) += dvb-core.o
diff --git a/drivers/media/dvb/dvb-core/demux.h b/drivers/media/dvb/dvb-core/demux.h
deleted file mode 100644
index eb91fd8..0000000
--- a/drivers/media/dvb/dvb-core/demux.h
+++ /dev/null
@@ -1,280 +0,0 @@
-/*
- * demux.h
- *
- * Copyright (c) 2002 Convergence GmbH
- *
- * based on code:
- * Copyright (c) 2000 Nokia Research Center
- *                    Tampere, FINLAND
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1
- * 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 Lesser General Public 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 __DEMUX_H
-#define __DEMUX_H
-
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/list.h>
-#include <linux/time.h>
-#include <linux/dvb/dmx.h>
-
-/*--------------------------------------------------------------------------*/
-/* Common definitions */
-/*--------------------------------------------------------------------------*/
-
-/*
- * DMX_MAX_FILTER_SIZE: Maximum length (in bytes) of a section/PES filter.
- */
-
-#ifndef DMX_MAX_FILTER_SIZE
-#define DMX_MAX_FILTER_SIZE 18
-#endif
-
-/*
- * DMX_MAX_SECFEED_SIZE: Maximum length (in bytes) of a private section feed filter.
- */
-
-#ifndef DMX_MAX_SECTION_SIZE
-#define DMX_MAX_SECTION_SIZE 4096
-#endif
-#ifndef DMX_MAX_SECFEED_SIZE
-#define DMX_MAX_SECFEED_SIZE (DMX_MAX_SECTION_SIZE + 188)
-#endif
-
-
-/*
- * enum dmx_success: Success codes for the Demux Callback API.
- */
-
-enum dmx_success {
-  DMX_OK = 0, /* Received Ok */
-  DMX_LENGTH_ERROR, /* Incorrect length */
-  DMX_OVERRUN_ERROR, /* Receiver ring buffer overrun */
-  DMX_CRC_ERROR, /* Incorrect CRC */
-  DMX_FRAME_ERROR, /* Frame alignment error */
-  DMX_FIFO_ERROR, /* Receiver FIFO overrun */
-  DMX_MISSED_ERROR /* Receiver missed packet */
-} ;
-
-/*--------------------------------------------------------------------------*/
-/* TS packet reception */
-/*--------------------------------------------------------------------------*/
-
-/* TS filter type for set() */
-
-#define TS_PACKET       1   /* send TS packets (188 bytes) to callback (default) */
-#define	TS_PAYLOAD_ONLY 2   /* in case TS_PACKET is set, only send the TS
-			       payload (<=184 bytes per packet) to callback */
-#define TS_DECODER      4   /* send stream to built-in decoder (if present) */
-#define TS_DEMUX        8   /* in case TS_PACKET is set, send the TS to
-			       the demux device, not to the dvr device */
-
-/* PES type for filters which write to built-in decoder */
-/* these should be kept identical to the types in dmx.h */
-
-enum dmx_ts_pes
-{  /* also send packets to decoder (if it exists) */
-	DMX_TS_PES_AUDIO0,
-	DMX_TS_PES_VIDEO0,
-	DMX_TS_PES_TELETEXT0,
-	DMX_TS_PES_SUBTITLE0,
-	DMX_TS_PES_PCR0,
-
-	DMX_TS_PES_AUDIO1,
-	DMX_TS_PES_VIDEO1,
-	DMX_TS_PES_TELETEXT1,
-	DMX_TS_PES_SUBTITLE1,
-	DMX_TS_PES_PCR1,
-
-	DMX_TS_PES_AUDIO2,
-	DMX_TS_PES_VIDEO2,
-	DMX_TS_PES_TELETEXT2,
-	DMX_TS_PES_SUBTITLE2,
-	DMX_TS_PES_PCR2,
-
-	DMX_TS_PES_AUDIO3,
-	DMX_TS_PES_VIDEO3,
-	DMX_TS_PES_TELETEXT3,
-	DMX_TS_PES_SUBTITLE3,
-	DMX_TS_PES_PCR3,
-
-	DMX_TS_PES_OTHER
-};
-
-#define DMX_TS_PES_AUDIO    DMX_TS_PES_AUDIO0
-#define DMX_TS_PES_VIDEO    DMX_TS_PES_VIDEO0
-#define DMX_TS_PES_TELETEXT DMX_TS_PES_TELETEXT0
-#define DMX_TS_PES_SUBTITLE DMX_TS_PES_SUBTITLE0
-#define DMX_TS_PES_PCR      DMX_TS_PES_PCR0
-
-
-struct dmx_ts_feed {
-	int is_filtering; /* Set to non-zero when filtering in progress */
-	struct dmx_demux *parent; /* Back-pointer */
-	void *priv; /* Pointer to private data of the API client */
-	int (*set) (struct dmx_ts_feed *feed,
-		    u16 pid,
-		    int type,
-		    enum dmx_ts_pes pes_type,
-		    size_t circular_buffer_size,
-		    struct timespec timeout);
-	int (*start_filtering) (struct dmx_ts_feed* feed);
-	int (*stop_filtering) (struct dmx_ts_feed* feed);
-};
-
-/*--------------------------------------------------------------------------*/
-/* Section reception */
-/*--------------------------------------------------------------------------*/
-
-struct dmx_section_filter {
-	u8 filter_value [DMX_MAX_FILTER_SIZE];
-	u8 filter_mask [DMX_MAX_FILTER_SIZE];
-	u8 filter_mode [DMX_MAX_FILTER_SIZE];
-	struct dmx_section_feed* parent; /* Back-pointer */
-	void* priv; /* Pointer to private data of the API client */
-};
-
-struct dmx_section_feed {
-	int is_filtering; /* Set to non-zero when filtering in progress */
-	struct dmx_demux* parent; /* Back-pointer */
-	void* priv; /* Pointer to private data of the API client */
-
-	int check_crc;
-	u32 crc_val;
-
-	u8 *secbuf;
-	u8 secbuf_base[DMX_MAX_SECFEED_SIZE];
-	u16 secbufp, seclen, tsfeedp;
-
-	int (*set) (struct dmx_section_feed* feed,
-		    u16 pid,
-		    size_t circular_buffer_size,
-		    int check_crc);
-	int (*allocate_filter) (struct dmx_section_feed* feed,
-				struct dmx_section_filter** filter);
-	int (*release_filter) (struct dmx_section_feed* feed,
-			       struct dmx_section_filter* filter);
-	int (*start_filtering) (struct dmx_section_feed* feed);
-	int (*stop_filtering) (struct dmx_section_feed* feed);
-};
-
-/*--------------------------------------------------------------------------*/
-/* Callback functions */
-/*--------------------------------------------------------------------------*/
-
-typedef int (*dmx_ts_cb) ( const u8 * buffer1,
-			   size_t buffer1_length,
-			   const u8 * buffer2,
-			   size_t buffer2_length,
-			   struct dmx_ts_feed* source,
-			   enum dmx_success success);
-
-typedef int (*dmx_section_cb) (	const u8 * buffer1,
-				size_t buffer1_len,
-				const u8 * buffer2,
-				size_t buffer2_len,
-				struct dmx_section_filter * source,
-				enum dmx_success success);
-
-/*--------------------------------------------------------------------------*/
-/* DVB Front-End */
-/*--------------------------------------------------------------------------*/
-
-enum dmx_frontend_source {
-	DMX_MEMORY_FE,
-	DMX_FRONTEND_0,
-	DMX_FRONTEND_1,
-	DMX_FRONTEND_2,
-	DMX_FRONTEND_3,
-	DMX_STREAM_0,    /* external stream input, e.g. LVDS */
-	DMX_STREAM_1,
-	DMX_STREAM_2,
-	DMX_STREAM_3
-};
-
-struct dmx_frontend {
-	struct list_head connectivity_list; /* List of front-ends that can
-					       be connected to a particular
-					       demux */
-	enum dmx_frontend_source source;
-};
-
-/*--------------------------------------------------------------------------*/
-/* MPEG-2 TS Demux */
-/*--------------------------------------------------------------------------*/
-
-/*
- * Flags OR'ed in the capabilities field of struct dmx_demux.
- */
-
-#define DMX_TS_FILTERING                        1
-#define DMX_PES_FILTERING                       2
-#define DMX_SECTION_FILTERING                   4
-#define DMX_MEMORY_BASED_FILTERING              8    /* write() available */
-#define DMX_CRC_CHECKING                        16
-#define DMX_TS_DESCRAMBLING                     32
-
-/*
- * Demux resource type identifier.
-*/
-
-/*
- * DMX_FE_ENTRY(): Casts elements in the list of registered
- * front-ends from the generic type struct list_head
- * to the type * struct dmx_frontend
- *.
-*/
-
-#define DMX_FE_ENTRY(list) list_entry(list, struct dmx_frontend, connectivity_list)
-
-struct dmx_demux {
-	u32 capabilities;            /* Bitfield of capability flags */
-	struct dmx_frontend* frontend;    /* Front-end connected to the demux */
-	void* priv;                  /* Pointer to private data of the API client */
-	int (*open) (struct dmx_demux* demux);
-	int (*close) (struct dmx_demux* demux);
-	int (*write) (struct dmx_demux* demux, const char __user *buf, size_t count);
-	int (*allocate_ts_feed) (struct dmx_demux* demux,
-				 struct dmx_ts_feed** feed,
-				 dmx_ts_cb callback);
-	int (*release_ts_feed) (struct dmx_demux* demux,
-				struct dmx_ts_feed* feed);
-	int (*allocate_section_feed) (struct dmx_demux* demux,
-				      struct dmx_section_feed** feed,
-				      dmx_section_cb callback);
-	int (*release_section_feed) (struct dmx_demux* demux,
-				     struct dmx_section_feed* feed);
-	int (*add_frontend) (struct dmx_demux* demux,
-			     struct dmx_frontend* frontend);
-	int (*remove_frontend) (struct dmx_demux* demux,
-				struct dmx_frontend* frontend);
-	struct list_head* (*get_frontends) (struct dmx_demux* demux);
-	int (*connect_frontend) (struct dmx_demux* demux,
-				 struct dmx_frontend* frontend);
-	int (*disconnect_frontend) (struct dmx_demux* demux);
-
-	int (*get_pes_pids) (struct dmx_demux* demux, u16 *pids);
-
-	int (*get_caps) (struct dmx_demux* demux, struct dmx_caps *caps);
-
-	int (*set_source) (struct dmx_demux* demux, const dmx_source_t *src);
-
-	int (*get_stc) (struct dmx_demux* demux, unsigned int num,
-			u64 *stc, unsigned int *base);
-};
-
-#endif /* #ifndef __DEMUX_H */
diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c
deleted file mode 100644
index 73970cd..0000000
--- a/drivers/media/dvb/dvb-core/dmxdev.c
+++ /dev/null
@@ -1,1277 +0,0 @@
-/*
- * dmxdev.c - DVB demultiplexer device
- *
- * Copyright (C) 2000 Ralph Metzler & Marcus Metzler
- *		      for convergence integrated media GmbH
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1
- * 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 Lesser General Public 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/sched.h>
-#include <linux/spinlock.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/module.h>
-#include <linux/poll.h>
-#include <linux/ioctl.h>
-#include <linux/wait.h>
-#include <asm/uaccess.h>
-#include "dmxdev.h"
-
-static int debug;
-
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
-
-#define dprintk	if (debug) printk
-
-static int dvb_dmxdev_buffer_write(struct dvb_ringbuffer *buf,
-				   const u8 *src, size_t len)
-{
-	ssize_t free;
-
-	if (!len)
-		return 0;
-	if (!buf->data)
-		return 0;
-
-	free = dvb_ringbuffer_free(buf);
-	if (len > free) {
-		dprintk("dmxdev: buffer overflow\n");
-		return -EOVERFLOW;
-	}
-
-	return dvb_ringbuffer_write(buf, src, len);
-}
-
-static ssize_t dvb_dmxdev_buffer_read(struct dvb_ringbuffer *src,
-				      int non_blocking, char __user *buf,
-				      size_t count, loff_t *ppos)
-{
-	size_t todo;
-	ssize_t avail;
-	ssize_t ret = 0;
-
-	if (!src->data)
-		return 0;
-
-	if (src->error) {
-		ret = src->error;
-		dvb_ringbuffer_flush(src);
-		return ret;
-	}
-
-	for (todo = count; todo > 0; todo -= ret) {
-		if (non_blocking && dvb_ringbuffer_empty(src)) {
-			ret = -EWOULDBLOCK;
-			break;
-		}
-
-		ret = wait_event_interruptible(src->queue,
-					       !dvb_ringbuffer_empty(src) ||
-					       (src->error != 0));
-		if (ret < 0)
-			break;
-
-		if (src->error) {
-			ret = src->error;
-			dvb_ringbuffer_flush(src);
-			break;
-		}
-
-		avail = dvb_ringbuffer_avail(src);
-		if (avail > todo)
-			avail = todo;
-
-		ret = dvb_ringbuffer_read_user(src, buf, avail);
-		if (ret < 0)
-			break;
-
-		buf += ret;
-	}
-
-	return (count - todo) ? (count - todo) : ret;
-}
-
-static struct dmx_frontend *get_fe(struct dmx_demux *demux, int type)
-{
-	struct list_head *head, *pos;
-
-	head = demux->get_frontends(demux);
-	if (!head)
-		return NULL;
-	list_for_each(pos, head)
-		if (DMX_FE_ENTRY(pos)->source == type)
-			return DMX_FE_ENTRY(pos);
-
-	return NULL;
-}
-
-static int dvb_dvr_open(struct inode *inode, struct file *file)
-{
-	struct dvb_device *dvbdev = file->private_data;
-	struct dmxdev *dmxdev = dvbdev->priv;
-	struct dmx_frontend *front;
-
-	dprintk("function : %s\n", __func__);
-
-	if (mutex_lock_interruptible(&dmxdev->mutex))
-		return -ERESTARTSYS;
-
-	if (dmxdev->exit) {
-		mutex_unlock(&dmxdev->mutex);
-		return -ENODEV;
-	}
-
-	if ((file->f_flags & O_ACCMODE) == O_RDWR) {
-		if (!(dmxdev->capabilities & DMXDEV_CAP_DUPLEX)) {
-			mutex_unlock(&dmxdev->mutex);
-			return -EOPNOTSUPP;
-		}
-	}
-
-	if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
-		void *mem;
-		if (!dvbdev->readers) {
-			mutex_unlock(&dmxdev->mutex);
-			return -EBUSY;
-		}
-		mem = vmalloc(DVR_BUFFER_SIZE);
-		if (!mem) {
-			mutex_unlock(&dmxdev->mutex);
-			return -ENOMEM;
-		}
-		dvb_ringbuffer_init(&dmxdev->dvr_buffer, mem, DVR_BUFFER_SIZE);
-		dvbdev->readers--;
-	}
-
-	if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
-		dmxdev->dvr_orig_fe = dmxdev->demux->frontend;
-
-		if (!dmxdev->demux->write) {
-			mutex_unlock(&dmxdev->mutex);
-			return -EOPNOTSUPP;
-		}
-
-		front = get_fe(dmxdev->demux, DMX_MEMORY_FE);
-
-		if (!front) {
-			mutex_unlock(&dmxdev->mutex);
-			return -EINVAL;
-		}
-		dmxdev->demux->disconnect_frontend(dmxdev->demux);
-		dmxdev->demux->connect_frontend(dmxdev->demux, front);
-	}
-	dvbdev->users++;
-	mutex_unlock(&dmxdev->mutex);
-	return 0;
-}
-
-static int dvb_dvr_release(struct inode *inode, struct file *file)
-{
-	struct dvb_device *dvbdev = file->private_data;
-	struct dmxdev *dmxdev = dvbdev->priv;
-
-	mutex_lock(&dmxdev->mutex);
-
-	if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
-		dmxdev->demux->disconnect_frontend(dmxdev->demux);
-		dmxdev->demux->connect_frontend(dmxdev->demux,
-						dmxdev->dvr_orig_fe);
-	}
-	if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
-		dvbdev->readers++;
-		if (dmxdev->dvr_buffer.data) {
-			void *mem = dmxdev->dvr_buffer.data;
-			mb();
-			spin_lock_irq(&dmxdev->lock);
-			dmxdev->dvr_buffer.data = NULL;
-			spin_unlock_irq(&dmxdev->lock);
-			vfree(mem);
-		}
-	}
-	/* TODO */
-	dvbdev->users--;
-	if (dvbdev->users == 1 && dmxdev->exit == 1) {
-		fops_put(file->f_op);
-		file->f_op = NULL;
-		mutex_unlock(&dmxdev->mutex);
-		wake_up(&dvbdev->wait_queue);
-	} else
-		mutex_unlock(&dmxdev->mutex);
-
-	return 0;
-}
-
-static ssize_t dvb_dvr_write(struct file *file, const char __user *buf,
-			     size_t count, loff_t *ppos)
-{
-	struct dvb_device *dvbdev = file->private_data;
-	struct dmxdev *dmxdev = dvbdev->priv;
-	int ret;
-
-	if (!dmxdev->demux->write)
-		return -EOPNOTSUPP;
-	if ((file->f_flags & O_ACCMODE) != O_WRONLY)
-		return -EINVAL;
-	if (mutex_lock_interruptible(&dmxdev->mutex))
-		return -ERESTARTSYS;
-
-	if (dmxdev->exit) {
-		mutex_unlock(&dmxdev->mutex);
-		return -ENODEV;
-	}
-	ret = dmxdev->demux->write(dmxdev->demux, buf, count);
-	mutex_unlock(&dmxdev->mutex);
-	return ret;
-}
-
-static ssize_t dvb_dvr_read(struct file *file, char __user *buf, size_t count,
-			    loff_t *ppos)
-{
-	struct dvb_device *dvbdev = file->private_data;
-	struct dmxdev *dmxdev = dvbdev->priv;
-
-	if (dmxdev->exit)
-		return -ENODEV;
-
-	return dvb_dmxdev_buffer_read(&dmxdev->dvr_buffer,
-				      file->f_flags & O_NONBLOCK,
-				      buf, count, ppos);
-}
-
-static int dvb_dvr_set_buffer_size(struct dmxdev *dmxdev,
-				      unsigned long size)
-{
-	struct dvb_ringbuffer *buf = &dmxdev->dvr_buffer;
-	void *newmem;
-	void *oldmem;
-
-	dprintk("function : %s\n", __func__);
-
-	if (buf->size == size)
-		return 0;
-	if (!size)
-		return -EINVAL;
-
-	newmem = vmalloc(size);
-	if (!newmem)
-		return -ENOMEM;
-
-	oldmem = buf->data;
-
-	spin_lock_irq(&dmxdev->lock);
-	buf->data = newmem;
-	buf->size = size;
-
-	/* reset and not flush in case the buffer shrinks */
-	dvb_ringbuffer_reset(buf);
-	spin_unlock_irq(&dmxdev->lock);
-
-	vfree(oldmem);
-
-	return 0;
-}
-
-static inline void dvb_dmxdev_filter_state_set(struct dmxdev_filter
-					       *dmxdevfilter, int state)
-{
-	spin_lock_irq(&dmxdevfilter->dev->lock);
-	dmxdevfilter->state = state;
-	spin_unlock_irq(&dmxdevfilter->dev->lock);
-}
-
-static int dvb_dmxdev_set_buffer_size(struct dmxdev_filter *dmxdevfilter,
-				      unsigned long size)
-{
-	struct dvb_ringbuffer *buf = &dmxdevfilter->buffer;
-	void *newmem;
-	void *oldmem;
-
-	if (buf->size == size)
-		return 0;
-	if (!size)
-		return -EINVAL;
-	if (dmxdevfilter->state >= DMXDEV_STATE_GO)
-		return -EBUSY;
-
-	newmem = vmalloc(size);
-	if (!newmem)
-		return -ENOMEM;
-
-	oldmem = buf->data;
-
-	spin_lock_irq(&dmxdevfilter->dev->lock);
-	buf->data = newmem;
-	buf->size = size;
-
-	/* reset and not flush in case the buffer shrinks */
-	dvb_ringbuffer_reset(buf);
-	spin_unlock_irq(&dmxdevfilter->dev->lock);
-
-	vfree(oldmem);
-
-	return 0;
-}
-
-static void dvb_dmxdev_filter_timeout(unsigned long data)
-{
-	struct dmxdev_filter *dmxdevfilter = (struct dmxdev_filter *)data;
-
-	dmxdevfilter->buffer.error = -ETIMEDOUT;
-	spin_lock_irq(&dmxdevfilter->dev->lock);
-	dmxdevfilter->state = DMXDEV_STATE_TIMEDOUT;
-	spin_unlock_irq(&dmxdevfilter->dev->lock);
-	wake_up(&dmxdevfilter->buffer.queue);
-}
-
-static void dvb_dmxdev_filter_timer(struct dmxdev_filter *dmxdevfilter)
-{
-	struct dmx_sct_filter_params *para = &dmxdevfilter->params.sec;
-
-	del_timer(&dmxdevfilter->timer);
-	if (para->timeout) {
-		dmxdevfilter->timer.function = dvb_dmxdev_filter_timeout;
-		dmxdevfilter->timer.data = (unsigned long)dmxdevfilter;
-		dmxdevfilter->timer.expires =
-		    jiffies + 1 + (HZ / 2 + HZ * para->timeout) / 1000;
-		add_timer(&dmxdevfilter->timer);
-	}
-}
-
-static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
-				       const u8 *buffer2, size_t buffer2_len,
-				       struct dmx_section_filter *filter,
-				       enum dmx_success success)
-{
-	struct dmxdev_filter *dmxdevfilter = filter->priv;
-	int ret;
-
-	if (dmxdevfilter->buffer.error) {
-		wake_up(&dmxdevfilter->buffer.queue);
-		return 0;
-	}
-	spin_lock(&dmxdevfilter->dev->lock);
-	if (dmxdevfilter->state != DMXDEV_STATE_GO) {
-		spin_unlock(&dmxdevfilter->dev->lock);
-		return 0;
-	}
-	del_timer(&dmxdevfilter->timer);
-	dprintk("dmxdev: section callback %02x %02x %02x %02x %02x %02x\n",
-		buffer1[0], buffer1[1],
-		buffer1[2], buffer1[3], buffer1[4], buffer1[5]);
-	ret = dvb_dmxdev_buffer_write(&dmxdevfilter->buffer, buffer1,
-				      buffer1_len);
-	if (ret == buffer1_len) {
-		ret = dvb_dmxdev_buffer_write(&dmxdevfilter->buffer, buffer2,
-					      buffer2_len);
-	}
-	if (ret < 0) {
-		dvb_ringbuffer_flush(&dmxdevfilter->buffer);
-		dmxdevfilter->buffer.error = ret;
-	}
-	if (dmxdevfilter->params.sec.flags & DMX_ONESHOT)
-		dmxdevfilter->state = DMXDEV_STATE_DONE;
-	spin_unlock(&dmxdevfilter->dev->lock);
-	wake_up(&dmxdevfilter->buffer.queue);
-	return 0;
-}
-
-static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
-				  const u8 *buffer2, size_t buffer2_len,
-				  struct dmx_ts_feed *feed,
-				  enum dmx_success success)
-{
-	struct dmxdev_filter *dmxdevfilter = feed->priv;
-	struct dvb_ringbuffer *buffer;
-	int ret;
-
-	spin_lock(&dmxdevfilter->dev->lock);
-	if (dmxdevfilter->params.pes.output == DMX_OUT_DECODER) {
-		spin_unlock(&dmxdevfilter->dev->lock);
-		return 0;
-	}
-
-	if (dmxdevfilter->params.pes.output == DMX_OUT_TAP
-	    || dmxdevfilter->params.pes.output == DMX_OUT_TSDEMUX_TAP)
-		buffer = &dmxdevfilter->buffer;
-	else
-		buffer = &dmxdevfilter->dev->dvr_buffer;
-	if (buffer->error) {
-		spin_unlock(&dmxdevfilter->dev->lock);
-		wake_up(&buffer->queue);
-		return 0;
-	}
-	ret = dvb_dmxdev_buffer_write(buffer, buffer1, buffer1_len);
-	if (ret == buffer1_len)
-		ret = dvb_dmxdev_buffer_write(buffer, buffer2, buffer2_len);
-	if (ret < 0) {
-		dvb_ringbuffer_flush(buffer);
-		buffer->error = ret;
-	}
-	spin_unlock(&dmxdevfilter->dev->lock);
-	wake_up(&buffer->queue);
-	return 0;
-}
-
-/* stop feed but only mark the specified filter as stopped (state set) */
-static int dvb_dmxdev_feed_stop(struct dmxdev_filter *dmxdevfilter)
-{
-	struct dmxdev_feed *feed;
-
-	dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_SET);
-
-	switch (dmxdevfilter->type) {
-	case DMXDEV_TYPE_SEC:
-		del_timer(&dmxdevfilter->timer);
-		dmxdevfilter->feed.sec->stop_filtering(dmxdevfilter->feed.sec);
-		break;
-	case DMXDEV_TYPE_PES:
-		list_for_each_entry(feed, &dmxdevfilter->feed.ts, next)
-			feed->ts->stop_filtering(feed->ts);
-		break;
-	default:
-		return -EINVAL;
-	}
-	return 0;
-}
-
-/* start feed associated with the specified filter */
-static int dvb_dmxdev_feed_start(struct dmxdev_filter *filter)
-{
-	struct dmxdev_feed *feed;
-	int ret;
-
-	dvb_dmxdev_filter_state_set(filter, DMXDEV_STATE_GO);
-
-	switch (filter->type) {
-	case DMXDEV_TYPE_SEC:
-		return filter->feed.sec->start_filtering(filter->feed.sec);
-	case DMXDEV_TYPE_PES:
-		list_for_each_entry(feed, &filter->feed.ts, next) {
-			ret = feed->ts->start_filtering(feed->ts);
-			if (ret < 0) {
-				dvb_dmxdev_feed_stop(filter);
-				return ret;
-			}
-		}
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-/* restart section feed if it has filters left associated with it,
-   otherwise release the feed */
-static int dvb_dmxdev_feed_restart(struct dmxdev_filter *filter)
-{
-	int i;
-	struct dmxdev *dmxdev = filter->dev;
-	u16 pid = filter->params.sec.pid;
-
-	for (i = 0; i < dmxdev->filternum; i++)
-		if (dmxdev->filter[i].state >= DMXDEV_STATE_GO &&
-		    dmxdev->filter[i].type == DMXDEV_TYPE_SEC &&
-		    dmxdev->filter[i].params.sec.pid == pid) {
-			dvb_dmxdev_feed_start(&dmxdev->filter[i]);
-			return 0;
-		}
-
-	filter->dev->demux->release_section_feed(dmxdev->demux,
-						 filter->feed.sec);
-
-	return 0;
-}
-
-static int dvb_dmxdev_filter_stop(struct dmxdev_filter *dmxdevfilter)
-{
-	struct dmxdev_feed *feed;
-	struct dmx_demux *demux;
-
-	if (dmxdevfilter->state < DMXDEV_STATE_GO)
-		return 0;
-
-	switch (dmxdevfilter->type) {
-	case DMXDEV_TYPE_SEC:
-		if (!dmxdevfilter->feed.sec)
-			break;
-		dvb_dmxdev_feed_stop(dmxdevfilter);
-		if (dmxdevfilter->filter.sec)
-			dmxdevfilter->feed.sec->
-			    release_filter(dmxdevfilter->feed.sec,
-					   dmxdevfilter->filter.sec);
-		dvb_dmxdev_feed_restart(dmxdevfilter);
-		dmxdevfilter->feed.sec = NULL;
-		break;
-	case DMXDEV_TYPE_PES:
-		dvb_dmxdev_feed_stop(dmxdevfilter);
-		demux = dmxdevfilter->dev->demux;
-		list_for_each_entry(feed, &dmxdevfilter->feed.ts, next) {
-			demux->release_ts_feed(demux, feed->ts);
-			feed->ts = NULL;
-		}
-		break;
-	default:
-		if (dmxdevfilter->state == DMXDEV_STATE_ALLOCATED)
-			return 0;
-		return -EINVAL;
-	}
-
-	dvb_ringbuffer_flush(&dmxdevfilter->buffer);
-	return 0;
-}
-
-static void dvb_dmxdev_delete_pids(struct dmxdev_filter *dmxdevfilter)
-{
-	struct dmxdev_feed *feed, *tmp;
-
-	/* delete all PIDs */
-	list_for_each_entry_safe(feed, tmp, &dmxdevfilter->feed.ts, next) {
-		list_del(&feed->next);
-		kfree(feed);
-	}
-
-	BUG_ON(!list_empty(&dmxdevfilter->feed.ts));
-}
-
-static inline int dvb_dmxdev_filter_reset(struct dmxdev_filter *dmxdevfilter)
-{
-	if (dmxdevfilter->state < DMXDEV_STATE_SET)
-		return 0;
-
-	if (dmxdevfilter->type == DMXDEV_TYPE_PES)
-		dvb_dmxdev_delete_pids(dmxdevfilter);
-
-	dmxdevfilter->type = DMXDEV_TYPE_NONE;
-	dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_ALLOCATED);
-	return 0;
-}
-
-static int dvb_dmxdev_start_feed(struct dmxdev *dmxdev,
-				 struct dmxdev_filter *filter,
-				 struct dmxdev_feed *feed)
-{
-	struct timespec timeout = { 0 };
-	struct dmx_pes_filter_params *para = &filter->params.pes;
-	dmx_output_t otype;
-	int ret;
-	int ts_type;
-	dmx_pes_type_t ts_pes;
-	struct dmx_ts_feed *tsfeed;
-
-	feed->ts = NULL;
-	otype = para->output;
-
-	ts_pes = para->pes_type;
-
-	if (ts_pes < DMX_PES_OTHER)
-		ts_type = TS_DECODER;
-	else
-		ts_type = 0;
-
-	if (otype == DMX_OUT_TS_TAP)
-		ts_type |= TS_PACKET;
-	else if (otype == DMX_OUT_TSDEMUX_TAP)
-		ts_type |= TS_PACKET | TS_DEMUX;
-	else if (otype == DMX_OUT_TAP)
-		ts_type |= TS_PACKET | TS_DEMUX | TS_PAYLOAD_ONLY;
-
-	ret = dmxdev->demux->allocate_ts_feed(dmxdev->demux, &feed->ts,
-					      dvb_dmxdev_ts_callback);
-	if (ret < 0)
-		return ret;
-
-	tsfeed = feed->ts;
-	tsfeed->priv = filter;
-
-	ret = tsfeed->set(tsfeed, feed->pid, ts_type, ts_pes, 32768, timeout);
-	if (ret < 0) {
-		dmxdev->demux->release_ts_feed(dmxdev->demux, tsfeed);
-		return ret;
-	}
-
-	ret = tsfeed->start_filtering(tsfeed);
-	if (ret < 0) {
-		dmxdev->demux->release_ts_feed(dmxdev->demux, tsfeed);
-		return ret;
-	}
-
-	return 0;
-}
-
-static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter)
-{
-	struct dmxdev *dmxdev = filter->dev;
-	struct dmxdev_feed *feed;
-	void *mem;
-	int ret, i;
-
-	if (filter->state < DMXDEV_STATE_SET)
-		return -EINVAL;
-
-	if (filter->state >= DMXDEV_STATE_GO)
-		dvb_dmxdev_filter_stop(filter);
-
-	if (!filter->buffer.data) {
-		mem = vmalloc(filter->buffer.size);
-		if (!mem)
-			return -ENOMEM;
-		spin_lock_irq(&filter->dev->lock);
-		filter->buffer.data = mem;
-		spin_unlock_irq(&filter->dev->lock);
-	}
-
-	dvb_ringbuffer_flush(&filter->buffer);
-
-	switch (filter->type) {
-	case DMXDEV_TYPE_SEC:
-	{
-		struct dmx_sct_filter_params *para = &filter->params.sec;
-		struct dmx_section_filter **secfilter = &filter->filter.sec;
-		struct dmx_section_feed **secfeed = &filter->feed.sec;
-
-		*secfilter = NULL;
-		*secfeed = NULL;
-
-
-		/* find active filter/feed with same PID */
-		for (i = 0; i < dmxdev->filternum; i++) {
-			if (dmxdev->filter[i].state >= DMXDEV_STATE_GO &&
-			    dmxdev->filter[i].type == DMXDEV_TYPE_SEC &&
-			    dmxdev->filter[i].params.sec.pid == para->pid) {
-				*secfeed = dmxdev->filter[i].feed.sec;
-				break;
-			}
-		}
-
-		/* if no feed found, try to allocate new one */
-		if (!*secfeed) {
-			ret = dmxdev->demux->allocate_section_feed(dmxdev->demux,
-								   secfeed,
-								   dvb_dmxdev_section_callback);
-			if (ret < 0) {
-				printk("DVB (%s): could not alloc feed\n",
-				       __func__);
-				return ret;
-			}
-
-			ret = (*secfeed)->set(*secfeed, para->pid, 32768,
-					      (para->flags & DMX_CHECK_CRC) ? 1 : 0);
-			if (ret < 0) {
-				printk("DVB (%s): could not set feed\n",
-				       __func__);
-				dvb_dmxdev_feed_restart(filter);
-				return ret;
-			}
-		} else {
-			dvb_dmxdev_feed_stop(filter);
-		}
-
-		ret = (*secfeed)->allocate_filter(*secfeed, secfilter);
-		if (ret < 0) {
-			dvb_dmxdev_feed_restart(filter);
-			filter->feed.sec->start_filtering(*secfeed);
-			dprintk("could not get filter\n");
-			return ret;
-		}
-
-		(*secfilter)->priv = filter;
-
-		memcpy(&((*secfilter)->filter_value[3]),
-		       &(para->filter.filter[1]), DMX_FILTER_SIZE - 1);
-		memcpy(&(*secfilter)->filter_mask[3],
-		       &para->filter.mask[1], DMX_FILTER_SIZE - 1);
-		memcpy(&(*secfilter)->filter_mode[3],
-		       &para->filter.mode[1], DMX_FILTER_SIZE - 1);
-
-		(*secfilter)->filter_value[0] = para->filter.filter[0];
-		(*secfilter)->filter_mask[0] = para->filter.mask[0];
-		(*secfilter)->filter_mode[0] = para->filter.mode[0];
-		(*secfilter)->filter_mask[1] = 0;
-		(*secfilter)->filter_mask[2] = 0;
-
-		filter->todo = 0;
-
-		ret = filter->feed.sec->start_filtering(filter->feed.sec);
-		if (ret < 0)
-			return ret;
-
-		dvb_dmxdev_filter_timer(filter);
-		break;
-	}
-	case DMXDEV_TYPE_PES:
-		list_for_each_entry(feed, &filter->feed.ts, next) {
-			ret = dvb_dmxdev_start_feed(dmxdev, filter, feed);
-			if (ret < 0) {
-				dvb_dmxdev_filter_stop(filter);
-				return ret;
-			}
-		}
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	dvb_dmxdev_filter_state_set(filter, DMXDEV_STATE_GO);
-	return 0;
-}
-
-static int dvb_demux_open(struct inode *inode, struct file *file)
-{
-	struct dvb_device *dvbdev = file->private_data;
-	struct dmxdev *dmxdev = dvbdev->priv;
-	int i;
-	struct dmxdev_filter *dmxdevfilter;
-
-	if (!dmxdev->filter)
-		return -EINVAL;
-
-	if (mutex_lock_interruptible(&dmxdev->mutex))
-		return -ERESTARTSYS;
-
-	for (i = 0; i < dmxdev->filternum; i++)
-		if (dmxdev->filter[i].state == DMXDEV_STATE_FREE)
-			break;
-
-	if (i == dmxdev->filternum) {
-		mutex_unlock(&dmxdev->mutex);
-		return -EMFILE;
-	}
-
-	dmxdevfilter = &dmxdev->filter[i];
-	mutex_init(&dmxdevfilter->mutex);
-	file->private_data = dmxdevfilter;
-
-	dvb_ringbuffer_init(&dmxdevfilter->buffer, NULL, 8192);
-	dmxdevfilter->type = DMXDEV_TYPE_NONE;
-	dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_ALLOCATED);
-	init_timer(&dmxdevfilter->timer);
-
-	dvbdev->users++;
-
-	mutex_unlock(&dmxdev->mutex);
-	return 0;
-}
-
-static int dvb_dmxdev_filter_free(struct dmxdev *dmxdev,
-				  struct dmxdev_filter *dmxdevfilter)
-{
-	mutex_lock(&dmxdev->mutex);
-	mutex_lock(&dmxdevfilter->mutex);
-
-	dvb_dmxdev_filter_stop(dmxdevfilter);
-	dvb_dmxdev_filter_reset(dmxdevfilter);
-
-	if (dmxdevfilter->buffer.data) {
-		void *mem = dmxdevfilter->buffer.data;
-
-		spin_lock_irq(&dmxdev->lock);
-		dmxdevfilter->buffer.data = NULL;
-		spin_unlock_irq(&dmxdev->lock);
-		vfree(mem);
-	}
-
-	dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_FREE);
-	wake_up(&dmxdevfilter->buffer.queue);
-	mutex_unlock(&dmxdevfilter->mutex);
-	mutex_unlock(&dmxdev->mutex);
-	return 0;
-}
-
-static inline void invert_mode(dmx_filter_t *filter)
-{
-	int i;
-
-	for (i = 0; i < DMX_FILTER_SIZE; i++)
-		filter->mode[i] ^= 0xff;
-}
-
-static int dvb_dmxdev_add_pid(struct dmxdev *dmxdev,
-			      struct dmxdev_filter *filter, u16 pid)
-{
-	struct dmxdev_feed *feed;
-
-	if ((filter->type != DMXDEV_TYPE_PES) ||
-	    (filter->state < DMXDEV_STATE_SET))
-		return -EINVAL;
-
-	/* only TS packet filters may have multiple PIDs */
-	if ((filter->params.pes.output != DMX_OUT_TSDEMUX_TAP) &&
-	    (!list_empty(&filter->feed.ts)))
-		return -EINVAL;
-
-	feed = kzalloc(sizeof(struct dmxdev_feed), GFP_KERNEL);
-	if (feed == NULL)
-		return -ENOMEM;
-
-	feed->pid = pid;
-	list_add(&feed->next, &filter->feed.ts);
-
-	if (filter->state >= DMXDEV_STATE_GO)
-		return dvb_dmxdev_start_feed(dmxdev, filter, feed);
-
-	return 0;
-}
-
-static int dvb_dmxdev_remove_pid(struct dmxdev *dmxdev,
-				  struct dmxdev_filter *filter, u16 pid)
-{
-	struct dmxdev_feed *feed, *tmp;
-
-	if ((filter->type != DMXDEV_TYPE_PES) ||
-	    (filter->state < DMXDEV_STATE_SET))
-		return -EINVAL;
-
-	list_for_each_entry_safe(feed, tmp, &filter->feed.ts, next) {
-		if ((feed->pid == pid) && (feed->ts != NULL)) {
-			feed->ts->stop_filtering(feed->ts);
-			filter->dev->demux->release_ts_feed(filter->dev->demux,
-							    feed->ts);
-			list_del(&feed->next);
-			kfree(feed);
-		}
-	}
-
-	return 0;
-}
-
-static int dvb_dmxdev_filter_set(struct dmxdev *dmxdev,
-				 struct dmxdev_filter *dmxdevfilter,
-				 struct dmx_sct_filter_params *params)
-{
-	dprintk("function : %s\n", __func__);
-
-	dvb_dmxdev_filter_stop(dmxdevfilter);
-
-	dmxdevfilter->type = DMXDEV_TYPE_SEC;
-	memcpy(&dmxdevfilter->params.sec,
-	       params, sizeof(struct dmx_sct_filter_params));
-	invert_mode(&dmxdevfilter->params.sec.filter);
-	dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_SET);
-
-	if (params->flags & DMX_IMMEDIATE_START)
-		return dvb_dmxdev_filter_start(dmxdevfilter);
-
-	return 0;
-}
-
-static int dvb_dmxdev_pes_filter_set(struct dmxdev *dmxdev,
-				     struct dmxdev_filter *dmxdevfilter,
-				     struct dmx_pes_filter_params *params)
-{
-	int ret;
-
-	dvb_dmxdev_filter_stop(dmxdevfilter);
-	dvb_dmxdev_filter_reset(dmxdevfilter);
-
-	if (params->pes_type > DMX_PES_OTHER || params->pes_type < 0)
-		return -EINVAL;
-
-	dmxdevfilter->type = DMXDEV_TYPE_PES;
-	memcpy(&dmxdevfilter->params, params,
-	       sizeof(struct dmx_pes_filter_params));
-	INIT_LIST_HEAD(&dmxdevfilter->feed.ts);
-
-	dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_SET);
-
-	ret = dvb_dmxdev_add_pid(dmxdev, dmxdevfilter,
-				 dmxdevfilter->params.pes.pid);
-	if (ret < 0)
-		return ret;
-
-	if (params->flags & DMX_IMMEDIATE_START)
-		return dvb_dmxdev_filter_start(dmxdevfilter);
-
-	return 0;
-}
-
-static ssize_t dvb_dmxdev_read_sec(struct dmxdev_filter *dfil,
-				   struct file *file, char __user *buf,
-				   size_t count, loff_t *ppos)
-{
-	int result, hcount;
-	int done = 0;
-
-	if (dfil->todo <= 0) {
-		hcount = 3 + dfil->todo;
-		if (hcount > count)
-			hcount = count;
-		result = dvb_dmxdev_buffer_read(&dfil->buffer,
-						file->f_flags & O_NONBLOCK,
-						buf, hcount, ppos);
-		if (result < 0) {
-			dfil->todo = 0;
-			return result;
-		}
-		if (copy_from_user(dfil->secheader - dfil->todo, buf, result))
-			return -EFAULT;
-		buf += result;
-		done = result;
-		count -= result;
-		dfil->todo -= result;
-		if (dfil->todo > -3)
-			return done;
-		dfil->todo = ((dfil->secheader[1] << 8) | dfil->secheader[2]) & 0xfff;
-		if (!count)
-			return done;
-	}
-	if (count > dfil->todo)
-		count = dfil->todo;
-	result = dvb_dmxdev_buffer_read(&dfil->buffer,
-					file->f_flags & O_NONBLOCK,
-					buf, count, ppos);
-	if (result < 0)
-		return result;
-	dfil->todo -= result;
-	return (result + done);
-}
-
-static ssize_t
-dvb_demux_read(struct file *file, char __user *buf, size_t count,
-	       loff_t *ppos)
-{
-	struct dmxdev_filter *dmxdevfilter = file->private_data;
-	int ret;
-
-	if (mutex_lock_interruptible(&dmxdevfilter->mutex))
-		return -ERESTARTSYS;
-
-	if (dmxdevfilter->type == DMXDEV_TYPE_SEC)
-		ret = dvb_dmxdev_read_sec(dmxdevfilter, file, buf, count, ppos);
-	else
-		ret = dvb_dmxdev_buffer_read(&dmxdevfilter->buffer,
-					     file->f_flags & O_NONBLOCK,
-					     buf, count, ppos);
-
-	mutex_unlock(&dmxdevfilter->mutex);
-	return ret;
-}
-
-static int dvb_demux_do_ioctl(struct file *file,
-			      unsigned int cmd, void *parg)
-{
-	struct dmxdev_filter *dmxdevfilter = file->private_data;
-	struct dmxdev *dmxdev = dmxdevfilter->dev;
-	unsigned long arg = (unsigned long)parg;
-	int ret = 0;
-
-	if (mutex_lock_interruptible(&dmxdev->mutex))
-		return -ERESTARTSYS;
-
-	switch (cmd) {
-	case DMX_START:
-		if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
-			mutex_unlock(&dmxdev->mutex);
-			return -ERESTARTSYS;
-		}
-		if (dmxdevfilter->state < DMXDEV_STATE_SET)
-			ret = -EINVAL;
-		else
-			ret = dvb_dmxdev_filter_start(dmxdevfilter);
-		mutex_unlock(&dmxdevfilter->mutex);
-		break;
-
-	case DMX_STOP:
-		if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
-			mutex_unlock(&dmxdev->mutex);
-			return -ERESTARTSYS;
-		}
-		ret = dvb_dmxdev_filter_stop(dmxdevfilter);
-		mutex_unlock(&dmxdevfilter->mutex);
-		break;
-
-	case DMX_SET_FILTER:
-		if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
-			mutex_unlock(&dmxdev->mutex);
-			return -ERESTARTSYS;
-		}
-		ret = dvb_dmxdev_filter_set(dmxdev, dmxdevfilter, parg);
-		mutex_unlock(&dmxdevfilter->mutex);
-		break;
-
-	case DMX_SET_PES_FILTER:
-		if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
-			mutex_unlock(&dmxdev->mutex);
-			return -ERESTARTSYS;
-		}
-		ret = dvb_dmxdev_pes_filter_set(dmxdev, dmxdevfilter, parg);
-		mutex_unlock(&dmxdevfilter->mutex);
-		break;
-
-	case DMX_SET_BUFFER_SIZE:
-		if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
-			mutex_unlock(&dmxdev->mutex);
-			return -ERESTARTSYS;
-		}
-		ret = dvb_dmxdev_set_buffer_size(dmxdevfilter, arg);
-		mutex_unlock(&dmxdevfilter->mutex);
-		break;
-
-	case DMX_GET_PES_PIDS:
-		if (!dmxdev->demux->get_pes_pids) {
-			ret = -EINVAL;
-			break;
-		}
-		dmxdev->demux->get_pes_pids(dmxdev->demux, parg);
-		break;
-
-	case DMX_GET_CAPS:
-		if (!dmxdev->demux->get_caps) {
-			ret = -EINVAL;
-			break;
-		}
-		ret = dmxdev->demux->get_caps(dmxdev->demux, parg);
-		break;
-
-	case DMX_SET_SOURCE:
-		if (!dmxdev->demux->set_source) {
-			ret = -EINVAL;
-			break;
-		}
-		ret = dmxdev->demux->set_source(dmxdev->demux, parg);
-		break;
-
-	case DMX_GET_STC:
-		if (!dmxdev->demux->get_stc) {
-			ret = -EINVAL;
-			break;
-		}
-		ret = dmxdev->demux->get_stc(dmxdev->demux,
-					     ((struct dmx_stc *)parg)->num,
-					     &((struct dmx_stc *)parg)->stc,
-					     &((struct dmx_stc *)parg)->base);
-		break;
-
-	case DMX_ADD_PID:
-		if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
-			ret = -ERESTARTSYS;
-			break;
-		}
-		ret = dvb_dmxdev_add_pid(dmxdev, dmxdevfilter, *(u16 *)parg);
-		mutex_unlock(&dmxdevfilter->mutex);
-		break;
-
-	case DMX_REMOVE_PID:
-		if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
-			ret = -ERESTARTSYS;
-			break;
-		}
-		ret = dvb_dmxdev_remove_pid(dmxdev, dmxdevfilter, *(u16 *)parg);
-		mutex_unlock(&dmxdevfilter->mutex);
-		break;
-
-	default:
-		ret = -EINVAL;
-		break;
-	}
-	mutex_unlock(&dmxdev->mutex);
-	return ret;
-}
-
-static long dvb_demux_ioctl(struct file *file, unsigned int cmd,
-			    unsigned long arg)
-{
-	return dvb_usercopy(file, cmd, arg, dvb_demux_do_ioctl);
-}
-
-static unsigned int dvb_demux_poll(struct file *file, poll_table *wait)
-{
-	struct dmxdev_filter *dmxdevfilter = file->private_data;
-	unsigned int mask = 0;
-
-	if (!dmxdevfilter)
-		return -EINVAL;
-
-	poll_wait(file, &dmxdevfilter->buffer.queue, wait);
-
-	if (dmxdevfilter->state != DMXDEV_STATE_GO &&
-	    dmxdevfilter->state != DMXDEV_STATE_DONE &&
-	    dmxdevfilter->state != DMXDEV_STATE_TIMEDOUT)
-		return 0;
-
-	if (dmxdevfilter->buffer.error)
-		mask |= (POLLIN | POLLRDNORM | POLLPRI | POLLERR);
-
-	if (!dvb_ringbuffer_empty(&dmxdevfilter->buffer))
-		mask |= (POLLIN | POLLRDNORM | POLLPRI);
-
-	return mask;
-}
-
-static int dvb_demux_release(struct inode *inode, struct file *file)
-{
-	struct dmxdev_filter *dmxdevfilter = file->private_data;
-	struct dmxdev *dmxdev = dmxdevfilter->dev;
-
-	int ret;
-
-	ret = dvb_dmxdev_filter_free(dmxdev, dmxdevfilter);
-
-	mutex_lock(&dmxdev->mutex);
-	dmxdev->dvbdev->users--;
-	if(dmxdev->dvbdev->users==1 && dmxdev->exit==1) {
-		fops_put(file->f_op);
-		file->f_op = NULL;
-		mutex_unlock(&dmxdev->mutex);
-		wake_up(&dmxdev->dvbdev->wait_queue);
-	} else
-		mutex_unlock(&dmxdev->mutex);
-
-	return ret;
-}
-
-static const struct file_operations dvb_demux_fops = {
-	.owner = THIS_MODULE,
-	.read = dvb_demux_read,
-	.unlocked_ioctl = dvb_demux_ioctl,
-	.open = dvb_demux_open,
-	.release = dvb_demux_release,
-	.poll = dvb_demux_poll,
-	.llseek = default_llseek,
-};
-
-static struct dvb_device dvbdev_demux = {
-	.priv = NULL,
-	.users = 1,
-	.writers = 1,
-	.fops = &dvb_demux_fops
-};
-
-static int dvb_dvr_do_ioctl(struct file *file,
-			    unsigned int cmd, void *parg)
-{
-	struct dvb_device *dvbdev = file->private_data;
-	struct dmxdev *dmxdev = dvbdev->priv;
-	unsigned long arg = (unsigned long)parg;
-	int ret;
-
-	if (mutex_lock_interruptible(&dmxdev->mutex))
-		return -ERESTARTSYS;
-
-	switch (cmd) {
-	case DMX_SET_BUFFER_SIZE:
-		ret = dvb_dvr_set_buffer_size(dmxdev, arg);
-		break;
-
-	default:
-		ret = -EINVAL;
-		break;
-	}
-	mutex_unlock(&dmxdev->mutex);
-	return ret;
-}
-
-static long dvb_dvr_ioctl(struct file *file,
-			 unsigned int cmd, unsigned long arg)
-{
-	return dvb_usercopy(file, cmd, arg, dvb_dvr_do_ioctl);
-}
-
-static unsigned int dvb_dvr_poll(struct file *file, poll_table *wait)
-{
-	struct dvb_device *dvbdev = file->private_data;
-	struct dmxdev *dmxdev = dvbdev->priv;
-	unsigned int mask = 0;
-
-	dprintk("function : %s\n", __func__);
-
-	poll_wait(file, &dmxdev->dvr_buffer.queue, wait);
-
-	if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
-		if (dmxdev->dvr_buffer.error)
-			mask |= (POLLIN | POLLRDNORM | POLLPRI | POLLERR);
-
-		if (!dvb_ringbuffer_empty(&dmxdev->dvr_buffer))
-			mask |= (POLLIN | POLLRDNORM | POLLPRI);
-	} else
-		mask |= (POLLOUT | POLLWRNORM | POLLPRI);
-
-	return mask;
-}
-
-static const struct file_operations dvb_dvr_fops = {
-	.owner = THIS_MODULE,
-	.read = dvb_dvr_read,
-	.write = dvb_dvr_write,
-	.unlocked_ioctl = dvb_dvr_ioctl,
-	.open = dvb_dvr_open,
-	.release = dvb_dvr_release,
-	.poll = dvb_dvr_poll,
-	.llseek = default_llseek,
-};
-
-static struct dvb_device dvbdev_dvr = {
-	.priv = NULL,
-	.readers = 1,
-	.users = 1,
-	.fops = &dvb_dvr_fops
-};
-
-int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *dvb_adapter)
-{
-	int i;
-
-	if (dmxdev->demux->open(dmxdev->demux) < 0)
-		return -EUSERS;
-
-	dmxdev->filter = vmalloc(dmxdev->filternum * sizeof(struct dmxdev_filter));
-	if (!dmxdev->filter)
-		return -ENOMEM;
-
-	mutex_init(&dmxdev->mutex);
-	spin_lock_init(&dmxdev->lock);
-	for (i = 0; i < dmxdev->filternum; i++) {
-		dmxdev->filter[i].dev = dmxdev;
-		dmxdev->filter[i].buffer.data = NULL;
-		dvb_dmxdev_filter_state_set(&dmxdev->filter[i],
-					    DMXDEV_STATE_FREE);
-	}
-
-	dvb_register_device(dvb_adapter, &dmxdev->dvbdev, &dvbdev_demux, dmxdev,
-			    DVB_DEVICE_DEMUX);
-	dvb_register_device(dvb_adapter, &dmxdev->dvr_dvbdev, &dvbdev_dvr,
-			    dmxdev, DVB_DEVICE_DVR);
-
-	dvb_ringbuffer_init(&dmxdev->dvr_buffer, NULL, 8192);
-
-	return 0;
-}
-
-EXPORT_SYMBOL(dvb_dmxdev_init);
-
-void dvb_dmxdev_release(struct dmxdev *dmxdev)
-{
-	dmxdev->exit=1;
-	if (dmxdev->dvbdev->users > 1) {
-		wait_event(dmxdev->dvbdev->wait_queue,
-				dmxdev->dvbdev->users==1);
-	}
-	if (dmxdev->dvr_dvbdev->users > 1) {
-		wait_event(dmxdev->dvr_dvbdev->wait_queue,
-				dmxdev->dvr_dvbdev->users==1);
-	}
-
-	dvb_unregister_device(dmxdev->dvbdev);
-	dvb_unregister_device(dmxdev->dvr_dvbdev);
-
-	vfree(dmxdev->filter);
-	dmxdev->filter = NULL;
-	dmxdev->demux->close(dmxdev->demux);
-}
-
-EXPORT_SYMBOL(dvb_dmxdev_release);
diff --git a/drivers/media/dvb/dvb-core/dmxdev.h b/drivers/media/dvb/dvb-core/dmxdev.h
deleted file mode 100644
index 02ebe28..0000000
--- a/drivers/media/dvb/dvb-core/dmxdev.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * dmxdev.h
- *
- * Copyright (C) 2000 Ralph Metzler & Marcus Metzler
- *                    for convergence integrated media GmbH
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1
- * 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 Lesser General Public 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 _DMXDEV_H_
-#define _DMXDEV_H_
-
-#include <linux/types.h>
-#include <linux/spinlock.h>
-#include <linux/kernel.h>
-#include <linux/timer.h>
-#include <linux/wait.h>
-#include <linux/fs.h>
-#include <linux/string.h>
-#include <linux/mutex.h>
-#include <linux/slab.h>
-
-#include <linux/dvb/dmx.h>
-
-#include "dvbdev.h"
-#include "demux.h"
-#include "dvb_ringbuffer.h"
-
-enum dmxdev_type {
-	DMXDEV_TYPE_NONE,
-	DMXDEV_TYPE_SEC,
-	DMXDEV_TYPE_PES,
-};
-
-enum dmxdev_state {
-	DMXDEV_STATE_FREE,
-	DMXDEV_STATE_ALLOCATED,
-	DMXDEV_STATE_SET,
-	DMXDEV_STATE_GO,
-	DMXDEV_STATE_DONE,
-	DMXDEV_STATE_TIMEDOUT
-};
-
-struct dmxdev_feed {
-	u16 pid;
-	struct dmx_ts_feed *ts;
-	struct list_head next;
-};
-
-struct dmxdev_filter {
-	union {
-		struct dmx_section_filter *sec;
-	} filter;
-
-	union {
-		/* list of TS and PES feeds (struct dmxdev_feed) */
-		struct list_head ts;
-		struct dmx_section_feed *sec;
-	} feed;
-
-	union {
-		struct dmx_sct_filter_params sec;
-		struct dmx_pes_filter_params pes;
-	} params;
-
-	enum dmxdev_type type;
-	enum dmxdev_state state;
-	struct dmxdev *dev;
-	struct dvb_ringbuffer buffer;
-
-	struct mutex mutex;
-
-	/* only for sections */
-	struct timer_list timer;
-	int todo;
-	u8 secheader[3];
-};
-
-
-struct dmxdev {
-	struct dvb_device *dvbdev;
-	struct dvb_device *dvr_dvbdev;
-
-	struct dmxdev_filter *filter;
-	struct dmx_demux *demux;
-
-	int filternum;
-	int capabilities;
-
-	unsigned int exit:1;
-#define DMXDEV_CAP_DUPLEX 1
-	struct dmx_frontend *dvr_orig_fe;
-
-	struct dvb_ringbuffer dvr_buffer;
-#define DVR_BUFFER_SIZE (10*188*1024)
-
-	struct mutex mutex;
-	spinlock_t lock;
-};
-
-
-int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *);
-void dvb_dmxdev_release(struct dmxdev *dmxdev);
-
-#endif /* _DMXDEV_H_ */
diff --git a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
deleted file mode 100644
index 9be65a3..0000000
--- a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
+++ /dev/null
@@ -1,1753 +0,0 @@
-/*
- * dvb_ca.c: generic DVB functions for EN50221 CAM interfaces
- *
- * Copyright (C) 2004 Andrew de Quincey
- *
- * Parts of this file were based on sources as follows:
- *
- * Copyright (C) 2003 Ralph Metzler <rjkm@metzlerbros.de>
- *
- * based on code:
- *
- * Copyright (C) 1999-2002 Ralph  Metzler
- *                       & Marcus Metzler for convergence integrated media GmbH
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the 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.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/list.h>
-#include <linux/module.h>
-#include <linux/vmalloc.h>
-#include <linux/delay.h>
-#include <linux/spinlock.h>
-#include <linux/sched.h>
-#include <linux/kthread.h>
-
-#include "dvb_ca_en50221.h"
-#include "dvb_ringbuffer.h"
-
-static int dvb_ca_en50221_debug;
-
-module_param_named(cam_debug, dvb_ca_en50221_debug, int, 0644);
-MODULE_PARM_DESC(cam_debug, "enable verbose debug messages");
-
-#define dprintk if (dvb_ca_en50221_debug) printk
-
-#define INIT_TIMEOUT_SECS 10
-
-#define HOST_LINK_BUF_SIZE 0x200
-
-#define RX_BUFFER_SIZE 65535
-
-#define MAX_RX_PACKETS_PER_ITERATION 10
-
-#define CTRLIF_DATA      0
-#define CTRLIF_COMMAND   1
-#define CTRLIF_STATUS    1
-#define CTRLIF_SIZE_LOW  2
-#define CTRLIF_SIZE_HIGH 3
-
-#define CMDREG_HC        1	/* Host control */
-#define CMDREG_SW        2	/* Size write */
-#define CMDREG_SR        4	/* Size read */
-#define CMDREG_RS        8	/* Reset interface */
-#define CMDREG_FRIE   0x40	/* Enable FR interrupt */
-#define CMDREG_DAIE   0x80	/* Enable DA interrupt */
-#define IRQEN (CMDREG_DAIE)
-
-#define STATUSREG_RE     1	/* read error */
-#define STATUSREG_WE     2	/* write error */
-#define STATUSREG_FR  0x40	/* module free */
-#define STATUSREG_DA  0x80	/* data available */
-#define STATUSREG_TXERR (STATUSREG_RE|STATUSREG_WE)	/* general transfer error */
-
-
-#define DVB_CA_SLOTSTATE_NONE           0
-#define DVB_CA_SLOTSTATE_UNINITIALISED  1
-#define DVB_CA_SLOTSTATE_RUNNING        2
-#define DVB_CA_SLOTSTATE_INVALID        3
-#define DVB_CA_SLOTSTATE_WAITREADY      4
-#define DVB_CA_SLOTSTATE_VALIDATE       5
-#define DVB_CA_SLOTSTATE_WAITFR         6
-#define DVB_CA_SLOTSTATE_LINKINIT       7
-
-
-/* Information on a CA slot */
-struct dvb_ca_slot {
-
-	/* current state of the CAM */
-	int slot_state;
-
-	/* mutex used for serializing access to one CI slot */
-	struct mutex slot_lock;
-
-	/* Number of CAMCHANGES that have occurred since last processing */
-	atomic_t camchange_count;
-
-	/* Type of last CAMCHANGE */
-	int camchange_type;
-
-	/* base address of CAM config */
-	u32 config_base;
-
-	/* value to write into Config Control register */
-	u8 config_option;
-
-	/* if 1, the CAM supports DA IRQs */
-	u8 da_irq_supported:1;
-
-	/* size of the buffer to use when talking to the CAM */
-	int link_buf_size;
-
-	/* buffer for incoming packets */
-	struct dvb_ringbuffer rx_buffer;
-
-	/* timer used during various states of the slot */
-	unsigned long timeout;
-};
-
-/* Private CA-interface information */
-struct dvb_ca_private {
-
-	/* pointer back to the public data structure */
-	struct dvb_ca_en50221 *pub;
-
-	/* the DVB device */
-	struct dvb_device *dvbdev;
-
-	/* Flags describing the interface (DVB_CA_FLAG_*) */
-	u32 flags;
-
-	/* number of slots supported by this CA interface */
-	unsigned int slot_count;
-
-	/* information on each slot */
-	struct dvb_ca_slot *slot_info;
-
-	/* wait queues for read() and write() operations */
-	wait_queue_head_t wait_queue;
-
-	/* PID of the monitoring thread */
-	struct task_struct *thread;
-
-	/* Flag indicating if the CA device is open */
-	unsigned int open:1;
-
-	/* Flag indicating the thread should wake up now */
-	unsigned int wakeup:1;
-
-	/* Delay the main thread should use */
-	unsigned long delay;
-
-	/* Slot to start looking for data to read from in the next user-space read operation */
-	int next_read_slot;
-};
-
-static void dvb_ca_en50221_thread_wakeup(struct dvb_ca_private *ca);
-static int dvb_ca_en50221_read_data(struct dvb_ca_private *ca, int slot, u8 * ebuf, int ecount);
-static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot, u8 * ebuf, int ecount);
-
-
-/**
- * Safely find needle in haystack.
- *
- * @param haystack Buffer to look in.
- * @param hlen Number of bytes in haystack.
- * @param needle Buffer to find.
- * @param nlen Number of bytes in needle.
- * @return Pointer into haystack needle was found at, or NULL if not found.
- */
-static char *findstr(char * haystack, int hlen, char * needle, int nlen)
-{
-	int i;
-
-	if (hlen < nlen)
-		return NULL;
-
-	for (i = 0; i <= hlen - nlen; i++) {
-		if (!strncmp(haystack + i, needle, nlen))
-			return haystack + i;
-	}
-
-	return NULL;
-}
-
-
-
-/* ******************************************************************************** */
-/* EN50221 physical interface functions */
-
-
-/**
- * Check CAM status.
- */
-static int dvb_ca_en50221_check_camstatus(struct dvb_ca_private *ca, int slot)
-{
-	int slot_status;
-	int cam_present_now;
-	int cam_changed;
-
-	/* IRQ mode */
-	if (ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE) {
-		return (atomic_read(&ca->slot_info[slot].camchange_count) != 0);
-	}
-
-	/* poll mode */
-	slot_status = ca->pub->poll_slot_status(ca->pub, slot, ca->open);
-
-	cam_present_now = (slot_status & DVB_CA_EN50221_POLL_CAM_PRESENT) ? 1 : 0;
-	cam_changed = (slot_status & DVB_CA_EN50221_POLL_CAM_CHANGED) ? 1 : 0;
-	if (!cam_changed) {
-		int cam_present_old = (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_NONE);
-		cam_changed = (cam_present_now != cam_present_old);
-	}
-
-	if (cam_changed) {
-		if (!cam_present_now) {
-			ca->slot_info[slot].camchange_type = DVB_CA_EN50221_CAMCHANGE_REMOVED;
-		} else {
-			ca->slot_info[slot].camchange_type = DVB_CA_EN50221_CAMCHANGE_INSERTED;
-		}
-		atomic_set(&ca->slot_info[slot].camchange_count, 1);
-	} else {
-		if ((ca->slot_info[slot].slot_state == DVB_CA_SLOTSTATE_WAITREADY) &&
-		    (slot_status & DVB_CA_EN50221_POLL_CAM_READY)) {
-			// move to validate state if reset is completed
-			ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_VALIDATE;
-		}
-	}
-
-	return cam_changed;
-}
-
-
-/**
- * Wait for flags to become set on the STATUS register on a CAM interface,
- * checking for errors and timeout.
- *
- * @param ca CA instance.
- * @param slot Slot on interface.
- * @param waitfor Flags to wait for.
- * @param timeout_ms Timeout in milliseconds.
- *
- * @return 0 on success, nonzero on error.
- */
-static int dvb_ca_en50221_wait_if_status(struct dvb_ca_private *ca, int slot,
-					 u8 waitfor, int timeout_hz)
-{
-	unsigned long timeout;
-	unsigned long start;
-
-	dprintk("%s\n", __func__);
-
-	/* loop until timeout elapsed */
-	start = jiffies;
-	timeout = jiffies + timeout_hz;
-	while (1) {
-		/* read the status and check for error */
-		int res = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS);
-		if (res < 0)
-			return -EIO;
-
-		/* if we got the flags, it was successful! */
-		if (res & waitfor) {
-			dprintk("%s succeeded timeout:%lu\n", __func__, jiffies - start);
-			return 0;
-		}
-
-		/* check for timeout */
-		if (time_after(jiffies, timeout)) {
-			break;
-		}
-
-		/* wait for a bit */
-		msleep(1);
-	}
-
-	dprintk("%s failed timeout:%lu\n", __func__, jiffies - start);
-
-	/* if we get here, we've timed out */
-	return -ETIMEDOUT;
-}
-
-
-/**
- * Initialise the link layer connection to a CAM.
- *
- * @param ca CA instance.
- * @param slot Slot id.
- *
- * @return 0 on success, nonzero on failure.
- */
-static int dvb_ca_en50221_link_init(struct dvb_ca_private *ca, int slot)
-{
-	int ret;
-	int buf_size;
-	u8 buf[2];
-
-	dprintk("%s\n", __func__);
-
-	/* we'll be determining these during this function */
-	ca->slot_info[slot].da_irq_supported = 0;
-
-	/* set the host link buffer size temporarily. it will be overwritten with the
-	 * real negotiated size later. */
-	ca->slot_info[slot].link_buf_size = 2;
-
-	/* read the buffer size from the CAM */
-	if ((ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN | CMDREG_SR)) != 0)
-		return ret;
-	if ((ret = dvb_ca_en50221_wait_if_status(ca, slot, STATUSREG_DA, HZ / 10)) != 0)
-		return ret;
-	if ((ret = dvb_ca_en50221_read_data(ca, slot, buf, 2)) != 2)
-		return -EIO;
-	if ((ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN)) != 0)
-		return ret;
-
-	/* store it, and choose the minimum of our buffer and the CAM's buffer size */
-	buf_size = (buf[0] << 8) | buf[1];
-	if (buf_size > HOST_LINK_BUF_SIZE)
-		buf_size = HOST_LINK_BUF_SIZE;
-	ca->slot_info[slot].link_buf_size = buf_size;
-	buf[0] = buf_size >> 8;
-	buf[1] = buf_size & 0xff;
-	dprintk("Chosen link buffer size of %i\n", buf_size);
-
-	/* write the buffer size to the CAM */
-	if ((ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN | CMDREG_SW)) != 0)
-		return ret;
-	if ((ret = dvb_ca_en50221_wait_if_status(ca, slot, STATUSREG_FR, HZ / 10)) != 0)
-		return ret;
-	if ((ret = dvb_ca_en50221_write_data(ca, slot, buf, 2)) != 2)
-		return -EIO;
-	if ((ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN)) != 0)
-		return ret;
-
-	/* success */
-	return 0;
-}
-
-/**
- * Read a tuple from attribute memory.
- *
- * @param ca CA instance.
- * @param slot Slot id.
- * @param address Address to read from. Updated.
- * @param tupleType Tuple id byte. Updated.
- * @param tupleLength Tuple length. Updated.
- * @param tuple Dest buffer for tuple (must be 256 bytes). Updated.
- *
- * @return 0 on success, nonzero on error.
- */
-static int dvb_ca_en50221_read_tuple(struct dvb_ca_private *ca, int slot,
-				     int *address, int *tupleType, int *tupleLength, u8 * tuple)
-{
-	int i;
-	int _tupleType;
-	int _tupleLength;
-	int _address = *address;
-
-	/* grab the next tuple length and type */
-	if ((_tupleType = ca->pub->read_attribute_mem(ca->pub, slot, _address)) < 0)
-		return _tupleType;
-	if (_tupleType == 0xff) {
-		dprintk("END OF CHAIN TUPLE type:0x%x\n", _tupleType);
-		*address += 2;
-		*tupleType = _tupleType;
-		*tupleLength = 0;
-		return 0;
-	}
-	if ((_tupleLength = ca->pub->read_attribute_mem(ca->pub, slot, _address + 2)) < 0)
-		return _tupleLength;
-	_address += 4;
-
-	dprintk("TUPLE type:0x%x length:%i\n", _tupleType, _tupleLength);
-
-	/* read in the whole tuple */
-	for (i = 0; i < _tupleLength; i++) {
-		tuple[i] = ca->pub->read_attribute_mem(ca->pub, slot, _address + (i * 2));
-		dprintk("  0x%02x: 0x%02x %c\n",
-			i, tuple[i] & 0xff,
-			((tuple[i] > 31) && (tuple[i] < 127)) ? tuple[i] : '.');
-	}
-	_address += (_tupleLength * 2);
-
-	// success
-	*tupleType = _tupleType;
-	*tupleLength = _tupleLength;
-	*address = _address;
-	return 0;
-}
-
-
-/**
- * Parse attribute memory of a CAM module, extracting Config register, and checking
- * it is a DVB CAM module.
- *
- * @param ca CA instance.
- * @param slot Slot id.
- *
- * @return 0 on success, <0 on failure.
- */
-static int dvb_ca_en50221_parse_attributes(struct dvb_ca_private *ca, int slot)
-{
-	int address = 0;
-	int tupleLength;
-	int tupleType;
-	u8 tuple[257];
-	char *dvb_str;
-	int rasz;
-	int status;
-	int got_cftableentry = 0;
-	int end_chain = 0;
-	int i;
-	u16 manfid = 0;
-	u16 devid = 0;
-
-
-	// CISTPL_DEVICE_0A
-	if ((status =
-	     dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType, &tupleLength, tuple)) < 0)
-		return status;
-	if (tupleType != 0x1D)
-		return -EINVAL;
-
-
-
-	// CISTPL_DEVICE_0C
-	if ((status =
-	     dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType, &tupleLength, tuple)) < 0)
-		return status;
-	if (tupleType != 0x1C)
-		return -EINVAL;
-
-
-
-	// CISTPL_VERS_1
-	if ((status =
-	     dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType, &tupleLength, tuple)) < 0)
-		return status;
-	if (tupleType != 0x15)
-		return -EINVAL;
-
-
-
-	// CISTPL_MANFID
-	if ((status = dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType,
-						&tupleLength, tuple)) < 0)
-		return status;
-	if (tupleType != 0x20)
-		return -EINVAL;
-	if (tupleLength != 4)
-		return -EINVAL;
-	manfid = (tuple[1] << 8) | tuple[0];
-	devid = (tuple[3] << 8) | tuple[2];
-
-
-
-	// CISTPL_CONFIG
-	if ((status = dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType,
-						&tupleLength, tuple)) < 0)
-		return status;
-	if (tupleType != 0x1A)
-		return -EINVAL;
-	if (tupleLength < 3)
-		return -EINVAL;
-
-	/* extract the configbase */
-	rasz = tuple[0] & 3;
-	if (tupleLength < (3 + rasz + 14))
-		return -EINVAL;
-	ca->slot_info[slot].config_base = 0;
-	for (i = 0; i < rasz + 1; i++) {
-		ca->slot_info[slot].config_base |= (tuple[2 + i] << (8 * i));
-	}
-
-	/* check it contains the correct DVB string */
-	dvb_str = findstr((char *)tuple, tupleLength, "DVB_CI_V", 8);
-	if (dvb_str == NULL)
-		return -EINVAL;
-	if (tupleLength < ((dvb_str - (char *) tuple) + 12))
-		return -EINVAL;
-
-	/* is it a version we support? */
-	if (strncmp(dvb_str + 8, "1.00", 4)) {
-		printk("dvb_ca adapter %d: Unsupported DVB CAM module version %c%c%c%c\n",
-		       ca->dvbdev->adapter->num, dvb_str[8], dvb_str[9], dvb_str[10], dvb_str[11]);
-		return -EINVAL;
-	}
-
-	/* process the CFTABLE_ENTRY tuples, and any after those */
-	while ((!end_chain) && (address < 0x1000)) {
-		if ((status = dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType,
-							&tupleLength, tuple)) < 0)
-			return status;
-		switch (tupleType) {
-		case 0x1B:	// CISTPL_CFTABLE_ENTRY
-			if (tupleLength < (2 + 11 + 17))
-				break;
-
-			/* if we've already parsed one, just use it */
-			if (got_cftableentry)
-				break;
-
-			/* get the config option */
-			ca->slot_info[slot].config_option = tuple[0] & 0x3f;
-
-			/* OK, check it contains the correct strings */
-			if ((findstr((char *)tuple, tupleLength, "DVB_HOST", 8) == NULL) ||
-			    (findstr((char *)tuple, tupleLength, "DVB_CI_MODULE", 13) == NULL))
-				break;
-
-			got_cftableentry = 1;
-			break;
-
-		case 0x14:	// CISTPL_NO_LINK
-			break;
-
-		case 0xFF:	// CISTPL_END
-			end_chain = 1;
-			break;
-
-		default:	/* Unknown tuple type - just skip this tuple and move to the next one */
-			dprintk("dvb_ca: Skipping unknown tuple type:0x%x length:0x%x\n", tupleType,
-				tupleLength);
-			break;
-		}
-	}
-
-	if ((address > 0x1000) || (!got_cftableentry))
-		return -EINVAL;
-
-	dprintk("Valid DVB CAM detected MANID:%x DEVID:%x CONFIGBASE:0x%x CONFIGOPTION:0x%x\n",
-		manfid, devid, ca->slot_info[slot].config_base, ca->slot_info[slot].config_option);
-
-	// success!
-	return 0;
-}
-
-
-/**
- * Set CAM's configoption correctly.
- *
- * @param ca CA instance.
- * @param slot Slot containing the CAM.
- */
-static int dvb_ca_en50221_set_configoption(struct dvb_ca_private *ca, int slot)
-{
-	int configoption;
-
-	dprintk("%s\n", __func__);
-
-	/* set the config option */
-	ca->pub->write_attribute_mem(ca->pub, slot,
-				     ca->slot_info[slot].config_base,
-				     ca->slot_info[slot].config_option);
-
-	/* check it */
-	configoption = ca->pub->read_attribute_mem(ca->pub, slot, ca->slot_info[slot].config_base);
-	dprintk("Set configoption 0x%x, read configoption 0x%x\n",
-		ca->slot_info[slot].config_option, configoption & 0x3f);
-
-	/* fine! */
-	return 0;
-
-}
-
-
-/**
- * This function talks to an EN50221 CAM control interface. It reads a buffer of
- * data from the CAM. The data can either be stored in a supplied buffer, or
- * automatically be added to the slot's rx_buffer.
- *
- * @param ca CA instance.
- * @param slot Slot to read from.
- * @param ebuf If non-NULL, the data will be written to this buffer. If NULL,
- * the data will be added into the buffering system as a normal fragment.
- * @param ecount Size of ebuf. Ignored if ebuf is NULL.
- *
- * @return Number of bytes read, or < 0 on error
- */
-static int dvb_ca_en50221_read_data(struct dvb_ca_private *ca, int slot, u8 * ebuf, int ecount)
-{
-	int bytes_read;
-	int status;
-	u8 buf[HOST_LINK_BUF_SIZE];
-	int i;
-
-	dprintk("%s\n", __func__);
-
-	/* check if we have space for a link buf in the rx_buffer */
-	if (ebuf == NULL) {
-		int buf_free;
-
-		if (ca->slot_info[slot].rx_buffer.data == NULL) {
-			status = -EIO;
-			goto exit;
-		}
-		buf_free = dvb_ringbuffer_free(&ca->slot_info[slot].rx_buffer);
-
-		if (buf_free < (ca->slot_info[slot].link_buf_size + DVB_RINGBUFFER_PKTHDRSIZE)) {
-			status = -EAGAIN;
-			goto exit;
-		}
-	}
-
-	/* check if there is data available */
-	if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0)
-		goto exit;
-	if (!(status & STATUSREG_DA)) {
-		/* no data */
-		status = 0;
-		goto exit;
-	}
-
-	/* read the amount of data */
-	if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_SIZE_HIGH)) < 0)
-		goto exit;
-	bytes_read = status << 8;
-	if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_SIZE_LOW)) < 0)
-		goto exit;
-	bytes_read |= status;
-
-	/* check it will fit */
-	if (ebuf == NULL) {
-		if (bytes_read > ca->slot_info[slot].link_buf_size) {
-			printk("dvb_ca adapter %d: CAM tried to send a buffer larger than the link buffer size (%i > %i)!\n",
-			       ca->dvbdev->adapter->num, bytes_read, ca->slot_info[slot].link_buf_size);
-			ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT;
-			status = -EIO;
-			goto exit;
-		}
-		if (bytes_read < 2) {
-			printk("dvb_ca adapter %d: CAM sent a buffer that was less than 2 bytes!\n",
-			       ca->dvbdev->adapter->num);
-			ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT;
-			status = -EIO;
-			goto exit;
-		}
-	} else {
-		if (bytes_read > ecount) {
-			printk("dvb_ca adapter %d: CAM tried to send a buffer larger than the ecount size!\n",
-			       ca->dvbdev->adapter->num);
-			status = -EIO;
-			goto exit;
-		}
-	}
-
-	/* fill the buffer */
-	for (i = 0; i < bytes_read; i++) {
-		/* read byte and check */
-		if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_DATA)) < 0)
-			goto exit;
-
-		/* OK, store it in the buffer */
-		buf[i] = status;
-	}
-
-	/* check for read error (RE should now be 0) */
-	if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0)
-		goto exit;
-	if (status & STATUSREG_RE) {
-		ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT;
-		status = -EIO;
-		goto exit;
-	}
-
-	/* OK, add it to the receive buffer, or copy into external buffer if supplied */
-	if (ebuf == NULL) {
-		if (ca->slot_info[slot].rx_buffer.data == NULL) {
-			status = -EIO;
-			goto exit;
-		}
-		dvb_ringbuffer_pkt_write(&ca->slot_info[slot].rx_buffer, buf, bytes_read);
-	} else {
-		memcpy(ebuf, buf, bytes_read);
-	}
-
-	dprintk("Received CA packet for slot %i connection id 0x%x last_frag:%i size:0x%x\n", slot,
-		buf[0], (buf[1] & 0x80) == 0, bytes_read);
-
-	/* wake up readers when a last_fragment is received */
-	if ((buf[1] & 0x80) == 0x00) {
-		wake_up_interruptible(&ca->wait_queue);
-	}
-	status = bytes_read;
-
-exit:
-	return status;
-}
-
-
-/**
- * This function talks to an EN50221 CAM control interface. It writes a buffer of data
- * to a CAM.
- *
- * @param ca CA instance.
- * @param slot Slot to write to.
- * @param ebuf The data in this buffer is treated as a complete link-level packet to
- * be written.
- * @param count Size of ebuf.
- *
- * @return Number of bytes written, or < 0 on error.
- */
-static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot, u8 * buf, int bytes_write)
-{
-	int status;
-	int i;
-
-	dprintk("%s\n", __func__);
-
-
-	/* sanity check */
-	if (bytes_write > ca->slot_info[slot].link_buf_size)
-		return -EINVAL;
-
-	/* it is possible we are dealing with a single buffer implementation,
-	   thus if there is data available for read or if there is even a read
-	   already in progress, we do nothing but awake the kernel thread to
-	   process the data if necessary. */
-	if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0)
-		goto exitnowrite;
-	if (status & (STATUSREG_DA | STATUSREG_RE)) {
-		if (status & STATUSREG_DA)
-			dvb_ca_en50221_thread_wakeup(ca);
-
-		status = -EAGAIN;
-		goto exitnowrite;
-	}
-
-	/* OK, set HC bit */
-	if ((status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND,
-						 IRQEN | CMDREG_HC)) != 0)
-		goto exit;
-
-	/* check if interface is still free */
-	if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0)
-		goto exit;
-	if (!(status & STATUSREG_FR)) {
-		/* it wasn't free => try again later */
-		status = -EAGAIN;
-		goto exit;
-	}
-
-	/* send the amount of data */
-	if ((status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_SIZE_HIGH, bytes_write >> 8)) != 0)
-		goto exit;
-	if ((status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_SIZE_LOW,
-						 bytes_write & 0xff)) != 0)
-		goto exit;
-
-	/* send the buffer */
-	for (i = 0; i < bytes_write; i++) {
-		if ((status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_DATA, buf[i])) != 0)
-			goto exit;
-	}
-
-	/* check for write error (WE should now be 0) */
-	if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0)
-		goto exit;
-	if (status & STATUSREG_WE) {
-		ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT;
-		status = -EIO;
-		goto exit;
-	}
-	status = bytes_write;
-
-	dprintk("Wrote CA packet for slot %i, connection id 0x%x last_frag:%i size:0x%x\n", slot,
-		buf[0], (buf[1] & 0x80) == 0, bytes_write);
-
-exit:
-	ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN);
-
-exitnowrite:
-	return status;
-}
-EXPORT_SYMBOL(dvb_ca_en50221_camchange_irq);
-
-
-
-/* ******************************************************************************** */
-/* EN50221 higher level functions */
-
-
-/**
- * A CAM has been removed => shut it down.
- *
- * @param ca CA instance.
- * @param slot Slot to shut down.
- */
-static int dvb_ca_en50221_slot_shutdown(struct dvb_ca_private *ca, int slot)
-{
-	dprintk("%s\n", __func__);
-
-	ca->pub->slot_shutdown(ca->pub, slot);
-	ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_NONE;
-
-	/* need to wake up all processes to check if they're now
-	   trying to write to a defunct CAM */
-	wake_up_interruptible(&ca->wait_queue);
-
-	dprintk("Slot %i shutdown\n", slot);
-
-	/* success */
-	return 0;
-}
-EXPORT_SYMBOL(dvb_ca_en50221_camready_irq);
-
-
-/**
- * A CAMCHANGE IRQ has occurred.
- *
- * @param ca CA instance.
- * @param slot Slot concerned.
- * @param change_type One of the DVB_CA_CAMCHANGE_* values.
- */
-void dvb_ca_en50221_camchange_irq(struct dvb_ca_en50221 *pubca, int slot, int change_type)
-{
-	struct dvb_ca_private *ca = pubca->private;
-
-	dprintk("CAMCHANGE IRQ slot:%i change_type:%i\n", slot, change_type);
-
-	switch (change_type) {
-	case DVB_CA_EN50221_CAMCHANGE_REMOVED:
-	case DVB_CA_EN50221_CAMCHANGE_INSERTED:
-		break;
-
-	default:
-		return;
-	}
-
-	ca->slot_info[slot].camchange_type = change_type;
-	atomic_inc(&ca->slot_info[slot].camchange_count);
-	dvb_ca_en50221_thread_wakeup(ca);
-}
-EXPORT_SYMBOL(dvb_ca_en50221_frda_irq);
-
-
-/**
- * A CAMREADY IRQ has occurred.
- *
- * @param ca CA instance.
- * @param slot Slot concerned.
- */
-void dvb_ca_en50221_camready_irq(struct dvb_ca_en50221 *pubca, int slot)
-{
-	struct dvb_ca_private *ca = pubca->private;
-
-	dprintk("CAMREADY IRQ slot:%i\n", slot);
-
-	if (ca->slot_info[slot].slot_state == DVB_CA_SLOTSTATE_WAITREADY) {
-		ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_VALIDATE;
-		dvb_ca_en50221_thread_wakeup(ca);
-	}
-}
-
-
-/**
- * An FR or DA IRQ has occurred.
- *
- * @param ca CA instance.
- * @param slot Slot concerned.
- */
-void dvb_ca_en50221_frda_irq(struct dvb_ca_en50221 *pubca, int slot)
-{
-	struct dvb_ca_private *ca = pubca->private;
-	int flags;
-
-	dprintk("FR/DA IRQ slot:%i\n", slot);
-
-	switch (ca->slot_info[slot].slot_state) {
-	case DVB_CA_SLOTSTATE_LINKINIT:
-		flags = ca->pub->read_cam_control(pubca, slot, CTRLIF_STATUS);
-		if (flags & STATUSREG_DA) {
-			dprintk("CAM supports DA IRQ\n");
-			ca->slot_info[slot].da_irq_supported = 1;
-		}
-		break;
-
-	case DVB_CA_SLOTSTATE_RUNNING:
-		if (ca->open)
-			dvb_ca_en50221_thread_wakeup(ca);
-		break;
-	}
-}
-
-
-
-/* ******************************************************************************** */
-/* EN50221 thread functions */
-
-/**
- * Wake up the DVB CA thread
- *
- * @param ca CA instance.
- */
-static void dvb_ca_en50221_thread_wakeup(struct dvb_ca_private *ca)
-{
-
-	dprintk("%s\n", __func__);
-
-	ca->wakeup = 1;
-	mb();
-	wake_up_process(ca->thread);
-}
-
-/**
- * Update the delay used by the thread.
- *
- * @param ca CA instance.
- */
-static void dvb_ca_en50221_thread_update_delay(struct dvb_ca_private *ca)
-{
-	int delay;
-	int curdelay = 100000000;
-	int slot;
-
-	/* Beware of too high polling frequency, because one polling
-	 * call might take several hundred milliseconds until timeout!
-	 */
-	for (slot = 0; slot < ca->slot_count; slot++) {
-		switch (ca->slot_info[slot].slot_state) {
-		default:
-		case DVB_CA_SLOTSTATE_NONE:
-			delay = HZ * 60;  /* 60s */
-			if (!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE))
-				delay = HZ * 5;  /* 5s */
-			break;
-		case DVB_CA_SLOTSTATE_INVALID:
-			delay = HZ * 60;  /* 60s */
-			if (!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE))
-				delay = HZ / 10;  /* 100ms */
-			break;
-
-		case DVB_CA_SLOTSTATE_UNINITIALISED:
-		case DVB_CA_SLOTSTATE_WAITREADY:
-		case DVB_CA_SLOTSTATE_VALIDATE:
-		case DVB_CA_SLOTSTATE_WAITFR:
-		case DVB_CA_SLOTSTATE_LINKINIT:
-			delay = HZ / 10;  /* 100ms */
-			break;
-
-		case DVB_CA_SLOTSTATE_RUNNING:
-			delay = HZ * 60;  /* 60s */
-			if (!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE))
-				delay = HZ / 10;  /* 100ms */
-			if (ca->open) {
-				if ((!ca->slot_info[slot].da_irq_supported) ||
-				    (!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_DA)))
-					delay = HZ / 10;  /* 100ms */
-			}
-			break;
-		}
-
-		if (delay < curdelay)
-			curdelay = delay;
-	}
-
-	ca->delay = curdelay;
-}
-
-
-
-/**
- * Kernel thread which monitors CA slots for CAM changes, and performs data transfers.
- */
-static int dvb_ca_en50221_thread(void *data)
-{
-	struct dvb_ca_private *ca = data;
-	int slot;
-	int flags;
-	int status;
-	int pktcount;
-	void *rxbuf;
-
-	dprintk("%s\n", __func__);
-
-	/* choose the correct initial delay */
-	dvb_ca_en50221_thread_update_delay(ca);
-
-	/* main loop */
-	while (!kthread_should_stop()) {
-		/* sleep for a bit */
-		if (!ca->wakeup) {
-			set_current_state(TASK_INTERRUPTIBLE);
-			schedule_timeout(ca->delay);
-			if (kthread_should_stop())
-				return 0;
-		}
-		ca->wakeup = 0;
-
-		/* go through all the slots processing them */
-		for (slot = 0; slot < ca->slot_count; slot++) {
-
-			mutex_lock(&ca->slot_info[slot].slot_lock);
-
-			// check the cam status + deal with CAMCHANGEs
-			while (dvb_ca_en50221_check_camstatus(ca, slot)) {
-				/* clear down an old CI slot if necessary */
-				if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_NONE)
-					dvb_ca_en50221_slot_shutdown(ca, slot);
-
-				/* if a CAM is NOW present, initialise it */
-				if (ca->slot_info[slot].camchange_type == DVB_CA_EN50221_CAMCHANGE_INSERTED) {
-					ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_UNINITIALISED;
-				}
-
-				/* we've handled one CAMCHANGE */
-				dvb_ca_en50221_thread_update_delay(ca);
-				atomic_dec(&ca->slot_info[slot].camchange_count);
-			}
-
-			// CAM state machine
-			switch (ca->slot_info[slot].slot_state) {
-			case DVB_CA_SLOTSTATE_NONE:
-			case DVB_CA_SLOTSTATE_INVALID:
-				// no action needed
-				break;
-
-			case DVB_CA_SLOTSTATE_UNINITIALISED:
-				ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_WAITREADY;
-				ca->pub->slot_reset(ca->pub, slot);
-				ca->slot_info[slot].timeout = jiffies + (INIT_TIMEOUT_SECS * HZ);
-				break;
-
-			case DVB_CA_SLOTSTATE_WAITREADY:
-				if (time_after(jiffies, ca->slot_info[slot].timeout)) {
-					printk("dvb_ca adaptor %d: PC card did not respond :(\n",
-					       ca->dvbdev->adapter->num);
-					ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
-					dvb_ca_en50221_thread_update_delay(ca);
-					break;
-				}
-				// no other action needed; will automatically change state when ready
-				break;
-
-			case DVB_CA_SLOTSTATE_VALIDATE:
-				if (dvb_ca_en50221_parse_attributes(ca, slot) != 0) {
-					/* we need this extra check for annoying interfaces like the budget-av */
-					if ((!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) &&
-					    (ca->pub->poll_slot_status)) {
-						status = ca->pub->poll_slot_status(ca->pub, slot, 0);
-						if (!(status & DVB_CA_EN50221_POLL_CAM_PRESENT)) {
-							ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_NONE;
-							dvb_ca_en50221_thread_update_delay(ca);
-							break;
-						}
-					}
-
-					printk("dvb_ca adapter %d: Invalid PC card inserted :(\n",
-					       ca->dvbdev->adapter->num);
-					ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
-					dvb_ca_en50221_thread_update_delay(ca);
-					break;
-				}
-				if (dvb_ca_en50221_set_configoption(ca, slot) != 0) {
-					printk("dvb_ca adapter %d: Unable to initialise CAM :(\n",
-					       ca->dvbdev->adapter->num);
-					ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
-					dvb_ca_en50221_thread_update_delay(ca);
-					break;
-				}
-				if (ca->pub->write_cam_control(ca->pub, slot,
-							       CTRLIF_COMMAND, CMDREG_RS) != 0) {
-					printk("dvb_ca adapter %d: Unable to reset CAM IF\n",
-					       ca->dvbdev->adapter->num);
-					ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
-					dvb_ca_en50221_thread_update_delay(ca);
-					break;
-				}
-				dprintk("DVB CAM validated successfully\n");
-
-				ca->slot_info[slot].timeout = jiffies + (INIT_TIMEOUT_SECS * HZ);
-				ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_WAITFR;
-				ca->wakeup = 1;
-				break;
-
-			case DVB_CA_SLOTSTATE_WAITFR:
-				if (time_after(jiffies, ca->slot_info[slot].timeout)) {
-					printk("dvb_ca adapter %d: DVB CAM did not respond :(\n",
-					       ca->dvbdev->adapter->num);
-					ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
-					dvb_ca_en50221_thread_update_delay(ca);
-					break;
-				}
-
-				flags = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS);
-				if (flags & STATUSREG_FR) {
-					ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT;
-					ca->wakeup = 1;
-				}
-				break;
-
-			case DVB_CA_SLOTSTATE_LINKINIT:
-				if (dvb_ca_en50221_link_init(ca, slot) != 0) {
-					/* we need this extra check for annoying interfaces like the budget-av */
-					if ((!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) &&
-					    (ca->pub->poll_slot_status)) {
-						status = ca->pub->poll_slot_status(ca->pub, slot, 0);
-						if (!(status & DVB_CA_EN50221_POLL_CAM_PRESENT)) {
-							ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_NONE;
-							dvb_ca_en50221_thread_update_delay(ca);
-							break;
-						}
-					}
-
-					printk("dvb_ca adapter %d: DVB CAM link initialisation failed :(\n", ca->dvbdev->adapter->num);
-					ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
-					dvb_ca_en50221_thread_update_delay(ca);
-					break;
-				}
-
-				if (ca->slot_info[slot].rx_buffer.data == NULL) {
-					rxbuf = vmalloc(RX_BUFFER_SIZE);
-					if (rxbuf == NULL) {
-						printk("dvb_ca adapter %d: Unable to allocate CAM rx buffer :(\n", ca->dvbdev->adapter->num);
-						ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
-						dvb_ca_en50221_thread_update_delay(ca);
-						break;
-					}
-					dvb_ringbuffer_init(&ca->slot_info[slot].rx_buffer, rxbuf, RX_BUFFER_SIZE);
-				}
-
-				ca->pub->slot_ts_enable(ca->pub, slot);
-				ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_RUNNING;
-				dvb_ca_en50221_thread_update_delay(ca);
-				printk("dvb_ca adapter %d: DVB CAM detected and initialised successfully\n", ca->dvbdev->adapter->num);
-				break;
-
-			case DVB_CA_SLOTSTATE_RUNNING:
-				if (!ca->open)
-					break;
-
-				// poll slots for data
-				pktcount = 0;
-				while ((status = dvb_ca_en50221_read_data(ca, slot, NULL, 0)) > 0) {
-					if (!ca->open)
-						break;
-
-					/* if a CAMCHANGE occurred at some point, do not do any more processing of this slot */
-					if (dvb_ca_en50221_check_camstatus(ca, slot)) {
-						// we dont want to sleep on the next iteration so we can handle the cam change
-						ca->wakeup = 1;
-						break;
-					}
-
-					/* check if we've hit our limit this time */
-					if (++pktcount >= MAX_RX_PACKETS_PER_ITERATION) {
-						// dont sleep; there is likely to be more data to read
-						ca->wakeup = 1;
-						break;
-					}
-				}
-				break;
-			}
-
-			mutex_unlock(&ca->slot_info[slot].slot_lock);
-		}
-	}
-
-	return 0;
-}
-
-
-
-/* ******************************************************************************** */
-/* EN50221 IO interface functions */
-
-/**
- * Real ioctl implementation.
- * NOTE: CA_SEND_MSG/CA_GET_MSG ioctls have userspace buffers passed to them.
- *
- * @param inode Inode concerned.
- * @param file File concerned.
- * @param cmd IOCTL command.
- * @param arg Associated argument.
- *
- * @return 0 on success, <0 on error.
- */
-static int dvb_ca_en50221_io_do_ioctl(struct file *file,
-				      unsigned int cmd, void *parg)
-{
-	struct dvb_device *dvbdev = file->private_data;
-	struct dvb_ca_private *ca = dvbdev->priv;
-	int err = 0;
-	int slot;
-
-	dprintk("%s\n", __func__);
-
-	switch (cmd) {
-	case CA_RESET:
-		for (slot = 0; slot < ca->slot_count; slot++) {
-			mutex_lock(&ca->slot_info[slot].slot_lock);
-			if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_NONE) {
-				dvb_ca_en50221_slot_shutdown(ca, slot);
-				if (ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)
-					dvb_ca_en50221_camchange_irq(ca->pub,
-								     slot,
-								     DVB_CA_EN50221_CAMCHANGE_INSERTED);
-			}
-			mutex_unlock(&ca->slot_info[slot].slot_lock);
-		}
-		ca->next_read_slot = 0;
-		dvb_ca_en50221_thread_wakeup(ca);
-		break;
-
-	case CA_GET_CAP: {
-		struct ca_caps *caps = parg;
-
-		caps->slot_num = ca->slot_count;
-		caps->slot_type = CA_CI_LINK;
-		caps->descr_num = 0;
-		caps->descr_type = 0;
-		break;
-	}
-
-	case CA_GET_SLOT_INFO: {
-		struct ca_slot_info *info = parg;
-
-		if ((info->num > ca->slot_count) || (info->num < 0))
-			return -EINVAL;
-
-		info->type = CA_CI_LINK;
-		info->flags = 0;
-		if ((ca->slot_info[info->num].slot_state != DVB_CA_SLOTSTATE_NONE)
-			&& (ca->slot_info[info->num].slot_state != DVB_CA_SLOTSTATE_INVALID)) {
-			info->flags = CA_CI_MODULE_PRESENT;
-		}
-		if (ca->slot_info[info->num].slot_state == DVB_CA_SLOTSTATE_RUNNING) {
-			info->flags |= CA_CI_MODULE_READY;
-		}
-		break;
-	}
-
-	default:
-		err = -EINVAL;
-		break;
-	}
-
-	return err;
-}
-
-
-/**
- * Wrapper for ioctl implementation.
- *
- * @param inode Inode concerned.
- * @param file File concerned.
- * @param cmd IOCTL command.
- * @param arg Associated argument.
- *
- * @return 0 on success, <0 on error.
- */
-static long dvb_ca_en50221_io_ioctl(struct file *file,
-				    unsigned int cmd, unsigned long arg)
-{
-	return dvb_usercopy(file, cmd, arg, dvb_ca_en50221_io_do_ioctl);
-}
-
-
-/**
- * Implementation of write() syscall.
- *
- * @param file File structure.
- * @param buf Source buffer.
- * @param count Size of source buffer.
- * @param ppos Position in file (ignored).
- *
- * @return Number of bytes read, or <0 on error.
- */
-static ssize_t dvb_ca_en50221_io_write(struct file *file,
-				       const char __user * buf, size_t count, loff_t * ppos)
-{
-	struct dvb_device *dvbdev = file->private_data;
-	struct dvb_ca_private *ca = dvbdev->priv;
-	u8 slot, connection_id;
-	int status;
-	u8 fragbuf[HOST_LINK_BUF_SIZE];
-	int fragpos = 0;
-	int fraglen;
-	unsigned long timeout;
-	int written;
-
-	dprintk("%s\n", __func__);
-
-	/* Incoming packet has a 2 byte header. hdr[0] = slot_id, hdr[1] = connection_id */
-	if (count < 2)
-		return -EINVAL;
-
-	/* extract slot & connection id */
-	if (copy_from_user(&slot, buf, 1))
-		return -EFAULT;
-	if (copy_from_user(&connection_id, buf + 1, 1))
-		return -EFAULT;
-	buf += 2;
-	count -= 2;
-
-	/* check if the slot is actually running */
-	if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_RUNNING)
-		return -EINVAL;
-
-	/* fragment the packets & store in the buffer */
-	while (fragpos < count) {
-		fraglen = ca->slot_info[slot].link_buf_size - 2;
-		if (fraglen < 0)
-			break;
-		if (fraglen > HOST_LINK_BUF_SIZE - 2)
-			fraglen = HOST_LINK_BUF_SIZE - 2;
-		if ((count - fragpos) < fraglen)
-			fraglen = count - fragpos;
-
-		fragbuf[0] = connection_id;
-		fragbuf[1] = ((fragpos + fraglen) < count) ? 0x80 : 0x00;
-		status = copy_from_user(fragbuf + 2, buf + fragpos, fraglen);
-		if (status) {
-			status = -EFAULT;
-			goto exit;
-		}
-
-		timeout = jiffies + HZ / 2;
-		written = 0;
-		while (!time_after(jiffies, timeout)) {
-			/* check the CAM hasn't been removed/reset in the meantime */
-			if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_RUNNING) {
-				status = -EIO;
-				goto exit;
-			}
-
-			mutex_lock(&ca->slot_info[slot].slot_lock);
-			status = dvb_ca_en50221_write_data(ca, slot, fragbuf, fraglen + 2);
-			mutex_unlock(&ca->slot_info[slot].slot_lock);
-			if (status == (fraglen + 2)) {
-				written = 1;
-				break;
-			}
-			if (status != -EAGAIN)
-				goto exit;
-
-			msleep(1);
-		}
-		if (!written) {
-			status = -EIO;
-			goto exit;
-		}
-
-		fragpos += fraglen;
-	}
-	status = count + 2;
-
-exit:
-	return status;
-}
-
-
-/**
- * Condition for waking up in dvb_ca_en50221_io_read_condition
- */
-static int dvb_ca_en50221_io_read_condition(struct dvb_ca_private *ca,
-					    int *result, int *_slot)
-{
-	int slot;
-	int slot_count = 0;
-	int idx;
-	size_t fraglen;
-	int connection_id = -1;
-	int found = 0;
-	u8 hdr[2];
-
-	slot = ca->next_read_slot;
-	while ((slot_count < ca->slot_count) && (!found)) {
-		if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_RUNNING)
-			goto nextslot;
-
-		if (ca->slot_info[slot].rx_buffer.data == NULL) {
-			return 0;
-		}
-
-		idx = dvb_ringbuffer_pkt_next(&ca->slot_info[slot].rx_buffer, -1, &fraglen);
-		while (idx != -1) {
-			dvb_ringbuffer_pkt_read(&ca->slot_info[slot].rx_buffer, idx, 0, hdr, 2);
-			if (connection_id == -1)
-				connection_id = hdr[0];
-			if ((hdr[0] == connection_id) && ((hdr[1] & 0x80) == 0)) {
-				*_slot = slot;
-				found = 1;
-				break;
-			}
-
-			idx = dvb_ringbuffer_pkt_next(&ca->slot_info[slot].rx_buffer, idx, &fraglen);
-		}
-
-nextslot:
-		slot = (slot + 1) % ca->slot_count;
-		slot_count++;
-	}
-
-	ca->next_read_slot = slot;
-	return found;
-}
-
-
-/**
- * Implementation of read() syscall.
- *
- * @param file File structure.
- * @param buf Destination buffer.
- * @param count Size of destination buffer.
- * @param ppos Position in file (ignored).
- *
- * @return Number of bytes read, or <0 on error.
- */
-static ssize_t dvb_ca_en50221_io_read(struct file *file, char __user * buf,
-				      size_t count, loff_t * ppos)
-{
-	struct dvb_device *dvbdev = file->private_data;
-	struct dvb_ca_private *ca = dvbdev->priv;
-	int status;
-	int result = 0;
-	u8 hdr[2];
-	int slot;
-	int connection_id = -1;
-	size_t idx, idx2;
-	int last_fragment = 0;
-	size_t fraglen;
-	int pktlen;
-	int dispose = 0;
-
-	dprintk("%s\n", __func__);
-
-	/* Outgoing packet has a 2 byte header. hdr[0] = slot_id, hdr[1] = connection_id */
-	if (count < 2)
-		return -EINVAL;
-
-	/* wait for some data */
-	if ((status = dvb_ca_en50221_io_read_condition(ca, &result, &slot)) == 0) {
-
-		/* if we're in nonblocking mode, exit immediately */
-		if (file->f_flags & O_NONBLOCK)
-			return -EWOULDBLOCK;
-
-		/* wait for some data */
-		status = wait_event_interruptible(ca->wait_queue,
-						  dvb_ca_en50221_io_read_condition
-						  (ca, &result, &slot));
-	}
-	if ((status < 0) || (result < 0)) {
-		if (result)
-			return result;
-		return status;
-	}
-
-	idx = dvb_ringbuffer_pkt_next(&ca->slot_info[slot].rx_buffer, -1, &fraglen);
-	pktlen = 2;
-	do {
-		if (idx == -1) {
-			printk("dvb_ca adapter %d: BUG: read packet ended before last_fragment encountered\n", ca->dvbdev->adapter->num);
-			status = -EIO;
-			goto exit;
-		}
-
-		dvb_ringbuffer_pkt_read(&ca->slot_info[slot].rx_buffer, idx, 0, hdr, 2);
-		if (connection_id == -1)
-			connection_id = hdr[0];
-		if (hdr[0] == connection_id) {
-			if (pktlen < count) {
-				if ((pktlen + fraglen - 2) > count) {
-					fraglen = count - pktlen;
-				} else {
-					fraglen -= 2;
-				}
-
-				if ((status = dvb_ringbuffer_pkt_read_user(&ca->slot_info[slot].rx_buffer, idx, 2,
-								      buf + pktlen, fraglen)) < 0) {
-					goto exit;
-				}
-				pktlen += fraglen;
-			}
-
-			if ((hdr[1] & 0x80) == 0)
-				last_fragment = 1;
-			dispose = 1;
-		}
-
-		idx2 = dvb_ringbuffer_pkt_next(&ca->slot_info[slot].rx_buffer, idx, &fraglen);
-		if (dispose)
-			dvb_ringbuffer_pkt_dispose(&ca->slot_info[slot].rx_buffer, idx);
-		idx = idx2;
-		dispose = 0;
-	} while (!last_fragment);
-
-	hdr[0] = slot;
-	hdr[1] = connection_id;
-	status = copy_to_user(buf, hdr, 2);
-	if (status) {
-		status = -EFAULT;
-		goto exit;
-	}
-	status = pktlen;
-
-exit:
-	return status;
-}
-
-
-/**
- * Implementation of file open syscall.
- *
- * @param inode Inode concerned.
- * @param file File concerned.
- *
- * @return 0 on success, <0 on failure.
- */
-static int dvb_ca_en50221_io_open(struct inode *inode, struct file *file)
-{
-	struct dvb_device *dvbdev = file->private_data;
-	struct dvb_ca_private *ca = dvbdev->priv;
-	int err;
-	int i;
-
-	dprintk("%s\n", __func__);
-
-	if (!try_module_get(ca->pub->owner))
-		return -EIO;
-
-	err = dvb_generic_open(inode, file);
-	if (err < 0) {
-		module_put(ca->pub->owner);
-		return err;
-	}
-
-	for (i = 0; i < ca->slot_count; i++) {
-
-		if (ca->slot_info[i].slot_state == DVB_CA_SLOTSTATE_RUNNING) {
-			if (ca->slot_info[i].rx_buffer.data != NULL) {
-				/* it is safe to call this here without locks because
-				 * ca->open == 0. Data is not read in this case */
-				dvb_ringbuffer_flush(&ca->slot_info[i].rx_buffer);
-			}
-		}
-	}
-
-	ca->open = 1;
-	dvb_ca_en50221_thread_update_delay(ca);
-	dvb_ca_en50221_thread_wakeup(ca);
-
-	return 0;
-}
-
-
-/**
- * Implementation of file close syscall.
- *
- * @param inode Inode concerned.
- * @param file File concerned.
- *
- * @return 0 on success, <0 on failure.
- */
-static int dvb_ca_en50221_io_release(struct inode *inode, struct file *file)
-{
-	struct dvb_device *dvbdev = file->private_data;
-	struct dvb_ca_private *ca = dvbdev->priv;
-	int err;
-
-	dprintk("%s\n", __func__);
-
-	/* mark the CA device as closed */
-	ca->open = 0;
-	dvb_ca_en50221_thread_update_delay(ca);
-
-	err = dvb_generic_release(inode, file);
-
-	module_put(ca->pub->owner);
-
-	return err;
-}
-
-
-/**
- * Implementation of poll() syscall.
- *
- * @param file File concerned.
- * @param wait poll wait table.
- *
- * @return Standard poll mask.
- */
-static unsigned int dvb_ca_en50221_io_poll(struct file *file, poll_table * wait)
-{
-	struct dvb_device *dvbdev = file->private_data;
-	struct dvb_ca_private *ca = dvbdev->priv;
-	unsigned int mask = 0;
-	int slot;
-	int result = 0;
-
-	dprintk("%s\n", __func__);
-
-	if (dvb_ca_en50221_io_read_condition(ca, &result, &slot) == 1) {
-		mask |= POLLIN;
-	}
-
-	/* if there is something, return now */
-	if (mask)
-		return mask;
-
-	/* wait for something to happen */
-	poll_wait(file, &ca->wait_queue, wait);
-
-	if (dvb_ca_en50221_io_read_condition(ca, &result, &slot) == 1) {
-		mask |= POLLIN;
-	}
-
-	return mask;
-}
-EXPORT_SYMBOL(dvb_ca_en50221_init);
-
-
-static const struct file_operations dvb_ca_fops = {
-	.owner = THIS_MODULE,
-	.read = dvb_ca_en50221_io_read,
-	.write = dvb_ca_en50221_io_write,
-	.unlocked_ioctl = dvb_ca_en50221_io_ioctl,
-	.open = dvb_ca_en50221_io_open,
-	.release = dvb_ca_en50221_io_release,
-	.poll = dvb_ca_en50221_io_poll,
-	.llseek = noop_llseek,
-};
-
-static struct dvb_device dvbdev_ca = {
-	.priv = NULL,
-	.users = 1,
-	.readers = 1,
-	.writers = 1,
-	.fops = &dvb_ca_fops,
-};
-
-
-/* ******************************************************************************** */
-/* Initialisation/shutdown functions */
-
-
-/**
- * Initialise a new DVB CA EN50221 interface device.
- *
- * @param dvb_adapter DVB adapter to attach the new CA device to.
- * @param ca The dvb_ca instance.
- * @param flags Flags describing the CA device (DVB_CA_FLAG_*).
- * @param slot_count Number of slots supported.
- *
- * @return 0 on success, nonzero on failure
- */
-int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter,
-			struct dvb_ca_en50221 *pubca, int flags, int slot_count)
-{
-	int ret;
-	struct dvb_ca_private *ca = NULL;
-	int i;
-
-	dprintk("%s\n", __func__);
-
-	if (slot_count < 1)
-		return -EINVAL;
-
-	/* initialise the system data */
-	if ((ca = kzalloc(sizeof(struct dvb_ca_private), GFP_KERNEL)) == NULL) {
-		ret = -ENOMEM;
-		goto error;
-	}
-	ca->pub = pubca;
-	ca->flags = flags;
-	ca->slot_count = slot_count;
-	if ((ca->slot_info = kcalloc(slot_count, sizeof(struct dvb_ca_slot), GFP_KERNEL)) == NULL) {
-		ret = -ENOMEM;
-		goto error;
-	}
-	init_waitqueue_head(&ca->wait_queue);
-	ca->open = 0;
-	ca->wakeup = 0;
-	ca->next_read_slot = 0;
-	pubca->private = ca;
-
-	/* register the DVB device */
-	ret = dvb_register_device(dvb_adapter, &ca->dvbdev, &dvbdev_ca, ca, DVB_DEVICE_CA);
-	if (ret)
-		goto error;
-
-	/* now initialise each slot */
-	for (i = 0; i < slot_count; i++) {
-		memset(&ca->slot_info[i], 0, sizeof(struct dvb_ca_slot));
-		ca->slot_info[i].slot_state = DVB_CA_SLOTSTATE_NONE;
-		atomic_set(&ca->slot_info[i].camchange_count, 0);
-		ca->slot_info[i].camchange_type = DVB_CA_EN50221_CAMCHANGE_REMOVED;
-		mutex_init(&ca->slot_info[i].slot_lock);
-	}
-
-	if (signal_pending(current)) {
-		ret = -EINTR;
-		goto error;
-	}
-	mb();
-
-	/* create a kthread for monitoring this CA device */
-	ca->thread = kthread_run(dvb_ca_en50221_thread, ca, "kdvb-ca-%i:%i",
-				 ca->dvbdev->adapter->num, ca->dvbdev->id);
-	if (IS_ERR(ca->thread)) {
-		ret = PTR_ERR(ca->thread);
-		printk("dvb_ca_init: failed to start kernel_thread (%d)\n",
-			ret);
-		goto error;
-	}
-	return 0;
-
-error:
-	if (ca != NULL) {
-		if (ca->dvbdev != NULL)
-			dvb_unregister_device(ca->dvbdev);
-		kfree(ca->slot_info);
-		kfree(ca);
-	}
-	pubca->private = NULL;
-	return ret;
-}
-EXPORT_SYMBOL(dvb_ca_en50221_release);
-
-
-
-/**
- * Release a DVB CA EN50221 interface device.
- *
- * @param ca_dev The dvb_device_t instance for the CA device.
- * @param ca The associated dvb_ca instance.
- */
-void dvb_ca_en50221_release(struct dvb_ca_en50221 *pubca)
-{
-	struct dvb_ca_private *ca = pubca->private;
-	int i;
-
-	dprintk("%s\n", __func__);
-
-	/* shutdown the thread if there was one */
-	kthread_stop(ca->thread);
-
-	for (i = 0; i < ca->slot_count; i++) {
-		dvb_ca_en50221_slot_shutdown(ca, i);
-		vfree(ca->slot_info[i].rx_buffer.data);
-	}
-	kfree(ca->slot_info);
-	dvb_unregister_device(ca->dvbdev);
-	kfree(ca);
-	pubca->private = NULL;
-}
diff --git a/drivers/media/dvb/dvb-core/dvb_ca_en50221.h b/drivers/media/dvb/dvb-core/dvb_ca_en50221.h
deleted file mode 100644
index 7df2e14..0000000
--- a/drivers/media/dvb/dvb-core/dvb_ca_en50221.h
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * dvb_ca.h: generic DVB functions for EN50221 CA interfaces
- *
- * Copyright (C) 2004 Andrew de Quincey
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1
- * 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 Lesser General Public 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 _DVB_CA_EN50221_H_
-#define _DVB_CA_EN50221_H_
-
-#include <linux/list.h>
-#include <linux/dvb/ca.h>
-
-#include "dvbdev.h"
-
-#define DVB_CA_EN50221_POLL_CAM_PRESENT	1
-#define DVB_CA_EN50221_POLL_CAM_CHANGED	2
-#define DVB_CA_EN50221_POLL_CAM_READY		4
-
-#define DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE	1
-#define DVB_CA_EN50221_FLAG_IRQ_FR		2
-#define DVB_CA_EN50221_FLAG_IRQ_DA		4
-
-#define DVB_CA_EN50221_CAMCHANGE_REMOVED		0
-#define DVB_CA_EN50221_CAMCHANGE_INSERTED		1
-
-
-
-/* Structure describing a CA interface */
-struct dvb_ca_en50221 {
-
-	/* the module owning this structure */
-	struct module* owner;
-
-	/* NOTE: the read_*, write_* and poll_slot_status functions will be
-	 * called for different slots concurrently and need to use locks where
-	 * and if appropriate. There will be no concurrent access to one slot.
-	 */
-
-	/* functions for accessing attribute memory on the CAM */
-	int (*read_attribute_mem)(struct dvb_ca_en50221* ca, int slot, int address);
-	int (*write_attribute_mem)(struct dvb_ca_en50221* ca, int slot, int address, u8 value);
-
-	/* functions for accessing the control interface on the CAM */
-	int (*read_cam_control)(struct dvb_ca_en50221* ca, int slot, u8 address);
-	int (*write_cam_control)(struct dvb_ca_en50221* ca, int slot, u8 address, u8 value);
-
-	/* Functions for controlling slots */
-	int (*slot_reset)(struct dvb_ca_en50221* ca, int slot);
-	int (*slot_shutdown)(struct dvb_ca_en50221* ca, int slot);
-	int (*slot_ts_enable)(struct dvb_ca_en50221* ca, int slot);
-
-	/*
-	* Poll slot status.
-	* Only necessary if DVB_CA_FLAG_EN50221_IRQ_CAMCHANGE is not set
-	*/
-	int (*poll_slot_status)(struct dvb_ca_en50221* ca, int slot, int open);
-
-	/* private data, used by caller */
-	void* data;
-
-	/* Opaque data used by the dvb_ca core. Do not modify! */
-	void* private;
-};
-
-
-
-
-/* ******************************************************************************** */
-/* Functions for reporting IRQ events */
-
-/**
- * A CAMCHANGE IRQ has occurred.
- *
- * @param ca CA instance.
- * @param slot Slot concerned.
- * @param change_type One of the DVB_CA_CAMCHANGE_* values
- */
-void dvb_ca_en50221_camchange_irq(struct dvb_ca_en50221* pubca, int slot, int change_type);
-
-/**
- * A CAMREADY IRQ has occurred.
- *
- * @param ca CA instance.
- * @param slot Slot concerned.
- */
-void dvb_ca_en50221_camready_irq(struct dvb_ca_en50221* pubca, int slot);
-
-/**
- * An FR or a DA IRQ has occurred.
- *
- * @param ca CA instance.
- * @param slot Slot concerned.
- */
-void dvb_ca_en50221_frda_irq(struct dvb_ca_en50221* ca, int slot);
-
-
-
-/* ******************************************************************************** */
-/* Initialisation/shutdown functions */
-
-/**
- * Initialise a new DVB CA device.
- *
- * @param dvb_adapter DVB adapter to attach the new CA device to.
- * @param ca The dvb_ca instance.
- * @param flags Flags describing the CA device (DVB_CA_EN50221_FLAG_*).
- * @param slot_count Number of slots supported.
- *
- * @return 0 on success, nonzero on failure
- */
-extern int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter, struct dvb_ca_en50221* ca, int flags, int slot_count);
-
-/**
- * Release a DVB CA device.
- *
- * @param ca The associated dvb_ca instance.
- */
-extern void dvb_ca_en50221_release(struct dvb_ca_en50221* ca);
-
-
-
-#endif
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c
deleted file mode 100644
index d82469f..0000000
--- a/drivers/media/dvb/dvb-core/dvb_demux.c
+++ /dev/null
@@ -1,1309 +0,0 @@
-/*
- * dvb_demux.c - DVB kernel demux API
- *
- * Copyright (C) 2000-2001 Ralph  Metzler <ralph@convergence.de>
- *		       & Marcus Metzler <marcus@convergence.de>
- *			 for convergence integrated media GmbH
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1
- * 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 Lesser General Public 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/sched.h>
-#include <linux/spinlock.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/module.h>
-#include <linux/poll.h>
-#include <linux/string.h>
-#include <linux/crc32.h>
-#include <asm/uaccess.h>
-#include <asm/div64.h>
-
-#include "dvb_demux.h"
-
-#define NOBUFS
-/*
-** #define DVB_DEMUX_SECTION_LOSS_LOG to monitor payload loss in the syslog
-*/
-// #define DVB_DEMUX_SECTION_LOSS_LOG
-
-static int dvb_demux_tscheck;
-module_param(dvb_demux_tscheck, int, 0644);
-MODULE_PARM_DESC(dvb_demux_tscheck,
-		"enable transport stream continuity and TEI check");
-
-static int dvb_demux_speedcheck;
-module_param(dvb_demux_speedcheck, int, 0644);
-MODULE_PARM_DESC(dvb_demux_speedcheck,
-		"enable transport stream speed check");
-
-#define dprintk_tscheck(x...) do {                              \
-		if (dvb_demux_tscheck && printk_ratelimit())    \
-			printk(x);                              \
-	} while (0)
-
-/******************************************************************************
- * static inlined helper functions
- ******************************************************************************/
-
-static inline u16 section_length(const u8 *buf)
-{
-	return 3 + ((buf[1] & 0x0f) << 8) + buf[2];
-}
-
-static inline u16 ts_pid(const u8 *buf)
-{
-	return ((buf[1] & 0x1f) << 8) + buf[2];
-}
-
-static inline u8 payload(const u8 *tsp)
-{
-	if (!(tsp[3] & 0x10))	// no payload?
-		return 0;
-
-	if (tsp[3] & 0x20) {	// adaptation field?
-		if (tsp[4] > 183)	// corrupted data?
-			return 0;
-		else
-			return 184 - 1 - tsp[4];
-	}
-
-	return 184;
-}
-
-static u32 dvb_dmx_crc32(struct dvb_demux_feed *f, const u8 *src, size_t len)
-{
-	return (f->feed.sec.crc_val = crc32_be(f->feed.sec.crc_val, src, len));
-}
-
-static void dvb_dmx_memcopy(struct dvb_demux_feed *f, u8 *d, const u8 *s,
-			    size_t len)
-{
-	memcpy(d, s, len);
-}
-
-/******************************************************************************
- * Software filter functions
- ******************************************************************************/
-
-static inline int dvb_dmx_swfilter_payload(struct dvb_demux_feed *feed,
-					   const u8 *buf)
-{
-	int count = payload(buf);
-	int p;
-	//int ccok;
-	//u8 cc;
-
-	if (count == 0)
-		return -1;
-
-	p = 188 - count;
-
-	/*
-	cc = buf[3] & 0x0f;
-	ccok = ((feed->cc + 1) & 0x0f) == cc;
-	feed->cc = cc;
-	if (!ccok)
-		printk("missed packet!\n");
-	*/
-
-	if (buf[1] & 0x40)	// PUSI ?
-		feed->peslen = 0xfffa;
-
-	feed->peslen += count;
-
-	return feed->cb.ts(&buf[p], count, NULL, 0, &feed->feed.ts, DMX_OK);
-}
-
-static int dvb_dmx_swfilter_sectionfilter(struct dvb_demux_feed *feed,
-					  struct dvb_demux_filter *f)
-{
-	u8 neq = 0;
-	int i;
-
-	for (i = 0; i < DVB_DEMUX_MASK_MAX; i++) {
-		u8 xor = f->filter.filter_value[i] ^ feed->feed.sec.secbuf[i];
-
-		if (f->maskandmode[i] & xor)
-			return 0;
-
-		neq |= f->maskandnotmode[i] & xor;
-	}
-
-	if (f->doneq && !neq)
-		return 0;
-
-	return feed->cb.sec(feed->feed.sec.secbuf, feed->feed.sec.seclen,
-			    NULL, 0, &f->filter, DMX_OK);
-}
-
-static inline int dvb_dmx_swfilter_section_feed(struct dvb_demux_feed *feed)
-{
-	struct dvb_demux *demux = feed->demux;
-	struct dvb_demux_filter *f = feed->filter;
-	struct dmx_section_feed *sec = &feed->feed.sec;
-	int section_syntax_indicator;
-
-	if (!sec->is_filtering)
-		return 0;
-
-	if (!f)
-		return 0;
-
-	if (sec->check_crc) {
-		section_syntax_indicator = ((sec->secbuf[1] & 0x80) != 0);
-		if (section_syntax_indicator &&
-		    demux->check_crc32(feed, sec->secbuf, sec->seclen))
-			return -1;
-	}
-
-	do {
-		if (dvb_dmx_swfilter_sectionfilter(feed, f) < 0)
-			return -1;
-	} while ((f = f->next) && sec->is_filtering);
-
-	sec->seclen = 0;
-
-	return 0;
-}
-
-static void dvb_dmx_swfilter_section_new(struct dvb_demux_feed *feed)
-{
-	struct dmx_section_feed *sec = &feed->feed.sec;
-
-#ifdef DVB_DEMUX_SECTION_LOSS_LOG
-	if (sec->secbufp < sec->tsfeedp) {
-		int i, n = sec->tsfeedp - sec->secbufp;
-
-		/*
-		 * Section padding is done with 0xff bytes entirely.
-		 * Due to speed reasons, we won't check all of them
-		 * but just first and last.
-		 */
-		if (sec->secbuf[0] != 0xff || sec->secbuf[n - 1] != 0xff) {
-			printk("dvb_demux.c section ts padding loss: %d/%d\n",
-			       n, sec->tsfeedp);
-			printk("dvb_demux.c pad data:");
-			for (i = 0; i < n; i++)
-				printk(" %02x", sec->secbuf[i]);
-			printk("\n");
-		}
-	}
-#endif
-
-	sec->tsfeedp = sec->secbufp = sec->seclen = 0;
-	sec->secbuf = sec->secbuf_base;
-}
-
-/*
- * Losless Section Demux 1.4.1 by Emard
- * Valsecchi Patrick:
- *  - middle of section A  (no PUSI)
- *  - end of section A and start of section B
- *    (with PUSI pointing to the start of the second section)
- *
- *  In this case, without feed->pusi_seen you'll receive a garbage section
- *  consisting of the end of section A. Basically because tsfeedp
- *  is incemented and the use=0 condition is not raised
- *  when the second packet arrives.
- *
- * Fix:
- * when demux is started, let feed->pusi_seen = 0 to
- * prevent initial feeding of garbage from the end of
- * previous section. When you for the first time see PUSI=1
- * then set feed->pusi_seen = 1
- */
-static int dvb_dmx_swfilter_section_copy_dump(struct dvb_demux_feed *feed,
-					      const u8 *buf, u8 len)
-{
-	struct dvb_demux *demux = feed->demux;
-	struct dmx_section_feed *sec = &feed->feed.sec;
-	u16 limit, seclen, n;
-
-	if (sec->tsfeedp >= DMX_MAX_SECFEED_SIZE)
-		return 0;
-
-	if (sec->tsfeedp + len > DMX_MAX_SECFEED_SIZE) {
-#ifdef DVB_DEMUX_SECTION_LOSS_LOG
-		printk("dvb_demux.c section buffer full loss: %d/%d\n",
-		       sec->tsfeedp + len - DMX_MAX_SECFEED_SIZE,
-		       DMX_MAX_SECFEED_SIZE);
-#endif
-		len = DMX_MAX_SECFEED_SIZE - sec->tsfeedp;
-	}
-
-	if (len <= 0)
-		return 0;
-
-	demux->memcopy(feed, sec->secbuf_base + sec->tsfeedp, buf, len);
-	sec->tsfeedp += len;
-
-	/*
-	 * Dump all the sections we can find in the data (Emard)
-	 */
-	limit = sec->tsfeedp;
-	if (limit > DMX_MAX_SECFEED_SIZE)
-		return -1;	/* internal error should never happen */
-
-	/* to be sure always set secbuf */
-	sec->secbuf = sec->secbuf_base + sec->secbufp;
-
-	for (n = 0; sec->secbufp + 2 < limit; n++) {
-		seclen = section_length(sec->secbuf);
-		if (seclen <= 0 || seclen > DMX_MAX_SECTION_SIZE
-		    || seclen + sec->secbufp > limit)
-			return 0;
-		sec->seclen = seclen;
-		sec->crc_val = ~0;
-		/* dump [secbuf .. secbuf+seclen) */
-		if (feed->pusi_seen)
-			dvb_dmx_swfilter_section_feed(feed);
-#ifdef DVB_DEMUX_SECTION_LOSS_LOG
-		else
-			printk("dvb_demux.c pusi not seen, discarding section data\n");
-#endif
-		sec->secbufp += seclen;	/* secbufp and secbuf moving together is */
-		sec->secbuf += seclen;	/* redundant but saves pointer arithmetic */
-	}
-
-	return 0;
-}
-
-static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed,
-					   const u8 *buf)
-{
-	u8 p, count;
-	int ccok, dc_i = 0;
-	u8 cc;
-
-	count = payload(buf);
-
-	if (count == 0)		/* count == 0 if no payload or out of range */
-		return -1;
-
-	p = 188 - count;	/* payload start */
-
-	cc = buf[3] & 0x0f;
-	ccok = ((feed->cc + 1) & 0x0f) == cc;
-	feed->cc = cc;
-
-	if (buf[3] & 0x20) {
-		/* adaption field present, check for discontinuity_indicator */
-		if ((buf[4] > 0) && (buf[5] & 0x80))
-			dc_i = 1;
-	}
-
-	if (!ccok || dc_i) {
-#ifdef DVB_DEMUX_SECTION_LOSS_LOG
-		printk("dvb_demux.c discontinuity detected %d bytes lost\n",
-		       count);
-		/*
-		 * those bytes under sume circumstances will again be reported
-		 * in the following dvb_dmx_swfilter_section_new
-		 */
-#endif
-		/*
-		 * Discontinuity detected. Reset pusi_seen = 0 to
-		 * stop feeding of suspicious data until next PUSI=1 arrives
-		 */
-		feed->pusi_seen = 0;
-		dvb_dmx_swfilter_section_new(feed);
-	}
-
-	if (buf[1] & 0x40) {
-		/* PUSI=1 (is set), section boundary is here */
-		if (count > 1 && buf[p] < count) {
-			const u8 *before = &buf[p + 1];
-			u8 before_len = buf[p];
-			const u8 *after = &before[before_len];
-			u8 after_len = count - 1 - before_len;
-
-			dvb_dmx_swfilter_section_copy_dump(feed, before,
-							   before_len);
-			/* before start of new section, set pusi_seen = 1 */
-			feed->pusi_seen = 1;
-			dvb_dmx_swfilter_section_new(feed);
-			dvb_dmx_swfilter_section_copy_dump(feed, after,
-							   after_len);
-		}
-#ifdef DVB_DEMUX_SECTION_LOSS_LOG
-		else if (count > 0)
-			printk("dvb_demux.c PUSI=1 but %d bytes lost\n", count);
-#endif
-	} else {
-		/* PUSI=0 (is not set), no section boundary */
-		dvb_dmx_swfilter_section_copy_dump(feed, &buf[p], count);
-	}
-
-	return 0;
-}
-
-static inline void dvb_dmx_swfilter_packet_type(struct dvb_demux_feed *feed,
-						const u8 *buf)
-{
-	switch (feed->type) {
-	case DMX_TYPE_TS:
-		if (!feed->feed.ts.is_filtering)
-			break;
-		if (feed->ts_type & TS_PACKET) {
-			if (feed->ts_type & TS_PAYLOAD_ONLY)
-				dvb_dmx_swfilter_payload(feed, buf);
-			else
-				feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts,
-					    DMX_OK);
-		}
-		if (feed->ts_type & TS_DECODER)
-			if (feed->demux->write_to_decoder)
-				feed->demux->write_to_decoder(feed, buf, 188);
-		break;
-
-	case DMX_TYPE_SEC:
-		if (!feed->feed.sec.is_filtering)
-			break;
-		if (dvb_dmx_swfilter_section_packet(feed, buf) < 0)
-			feed->feed.sec.seclen = feed->feed.sec.secbufp = 0;
-		break;
-
-	default:
-		break;
-	}
-}
-
-#define DVR_FEED(f)							\
-	(((f)->type == DMX_TYPE_TS) &&					\
-	((f)->feed.ts.is_filtering) &&					\
-	(((f)->ts_type & (TS_PACKET | TS_DEMUX)) == TS_PACKET))
-
-static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf)
-{
-	struct dvb_demux_feed *feed;
-	u16 pid = ts_pid(buf);
-	int dvr_done = 0;
-
-	if (dvb_demux_speedcheck) {
-		struct timespec cur_time, delta_time;
-		u64 speed_bytes, speed_timedelta;
-
-		demux->speed_pkts_cnt++;
-
-		/* show speed every SPEED_PKTS_INTERVAL packets */
-		if (!(demux->speed_pkts_cnt % SPEED_PKTS_INTERVAL)) {
-			cur_time = current_kernel_time();
-
-			if (demux->speed_last_time.tv_sec != 0 &&
-					demux->speed_last_time.tv_nsec != 0) {
-				delta_time = timespec_sub(cur_time,
-						demux->speed_last_time);
-				speed_bytes = (u64)demux->speed_pkts_cnt
-					* 188 * 8;
-				/* convert to 1024 basis */
-				speed_bytes = 1000 * div64_u64(speed_bytes,
-						1024);
-				speed_timedelta =
-					(u64)timespec_to_ns(&delta_time);
-				speed_timedelta = div64_u64(speed_timedelta,
-						1000000); /* nsec -> usec */
-				printk(KERN_INFO "TS speed %llu Kbits/sec \n",
-						div64_u64(speed_bytes,
-							speed_timedelta));
-			};
-
-			demux->speed_last_time = cur_time;
-			demux->speed_pkts_cnt = 0;
-		};
-	};
-
-	if (demux->cnt_storage && dvb_demux_tscheck) {
-		/* check pkt counter */
-		if (pid < MAX_PID) {
-			if (buf[1] & 0x80)
-				dprintk_tscheck("TEI detected. "
-						"PID=0x%x data1=0x%x\n",
-						pid, buf[1]);
-
-			if ((buf[3] & 0xf) != demux->cnt_storage[pid])
-				dprintk_tscheck("TS packet counter mismatch. "
-						"PID=0x%x expected 0x%x "
-						"got 0x%x\n",
-						pid, demux->cnt_storage[pid],
-						buf[3] & 0xf);
-
-			demux->cnt_storage[pid] = ((buf[3] & 0xf) + 1)&0xf;
-		};
-		/* end check */
-	};
-
-	list_for_each_entry(feed, &demux->feed_list, list_head) {
-		if ((feed->pid != pid) && (feed->pid != 0x2000))
-			continue;
-
-		/* copy each packet only once to the dvr device, even
-		 * if a PID is in multiple filters (e.g. video + PCR) */
-		if ((DVR_FEED(feed)) && (dvr_done++))
-			continue;
-
-		if (feed->pid == pid)
-			dvb_dmx_swfilter_packet_type(feed, buf);
-		else if (feed->pid == 0x2000)
-			feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts, DMX_OK);
-	}
-}
-
-void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf,
-			      size_t count)
-{
-	spin_lock(&demux->lock);
-
-	while (count--) {
-		if (buf[0] == 0x47)
-			dvb_dmx_swfilter_packet(demux, buf);
-		buf += 188;
-	}
-
-	spin_unlock(&demux->lock);
-}
-
-EXPORT_SYMBOL(dvb_dmx_swfilter_packets);
-
-static inline int find_next_packet(const u8 *buf, int pos, size_t count,
-				   const int pktsize)
-{
-	int start = pos, lost;
-
-	while (pos < count) {
-		if (buf[pos] == 0x47 ||
-		    (pktsize == 204 && buf[pos] == 0xB8))
-			break;
-		pos++;
-	}
-
-	lost = pos - start;
-	if (lost) {
-		/* This garbage is part of a valid packet? */
-		int backtrack = pos - pktsize;
-		if (backtrack >= 0 && (buf[backtrack] == 0x47 ||
-		    (pktsize == 204 && buf[backtrack] == 0xB8)))
-			return backtrack;
-	}
-
-	return pos;
-}
-
-/* Filter all pktsize= 188 or 204 sized packets and skip garbage. */
-static inline void _dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf,
-		size_t count, const int pktsize)
-{
-	int p = 0, i, j;
-	const u8 *q;
-
-	spin_lock(&demux->lock);
-
-	if (demux->tsbufp) { /* tsbuf[0] is now 0x47. */
-		i = demux->tsbufp;
-		j = pktsize - i;
-		if (count < j) {
-			memcpy(&demux->tsbuf[i], buf, count);
-			demux->tsbufp += count;
-			goto bailout;
-		}
-		memcpy(&demux->tsbuf[i], buf, j);
-		if (demux->tsbuf[0] == 0x47) /* double check */
-			dvb_dmx_swfilter_packet(demux, demux->tsbuf);
-		demux->tsbufp = 0;
-		p += j;
-	}
-
-	while (1) {
-		p = find_next_packet(buf, p, count, pktsize);
-		if (p >= count)
-			break;
-		if (count - p < pktsize)
-			break;
-
-		q = &buf[p];
-
-		if (pktsize == 204 && (*q == 0xB8)) {
-			memcpy(demux->tsbuf, q, 188);
-			demux->tsbuf[0] = 0x47;
-			q = demux->tsbuf;
-		}
-		dvb_dmx_swfilter_packet(demux, q);
-		p += pktsize;
-	}
-
-	i = count - p;
-	if (i) {
-		memcpy(demux->tsbuf, &buf[p], i);
-		demux->tsbufp = i;
-		if (pktsize == 204 && demux->tsbuf[0] == 0xB8)
-			demux->tsbuf[0] = 0x47;
-	}
-
-bailout:
-	spin_unlock(&demux->lock);
-}
-
-void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count)
-{
-	_dvb_dmx_swfilter(demux, buf, count, 188);
-}
-EXPORT_SYMBOL(dvb_dmx_swfilter);
-
-void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count)
-{
-	_dvb_dmx_swfilter(demux, buf, count, 204);
-}
-EXPORT_SYMBOL(dvb_dmx_swfilter_204);
-
-void dvb_dmx_swfilter_raw(struct dvb_demux *demux, const u8 *buf, size_t count)
-{
-	spin_lock(&demux->lock);
-
-	demux->feed->cb.ts(buf, count, NULL, 0, &demux->feed->feed.ts, DMX_OK);
-
-	spin_unlock(&demux->lock);
-}
-EXPORT_SYMBOL(dvb_dmx_swfilter_raw);
-
-static struct dvb_demux_filter *dvb_dmx_filter_alloc(struct dvb_demux *demux)
-{
-	int i;
-
-	for (i = 0; i < demux->filternum; i++)
-		if (demux->filter[i].state == DMX_STATE_FREE)
-			break;
-
-	if (i == demux->filternum)
-		return NULL;
-
-	demux->filter[i].state = DMX_STATE_ALLOCATED;
-
-	return &demux->filter[i];
-}
-
-static struct dvb_demux_feed *dvb_dmx_feed_alloc(struct dvb_demux *demux)
-{
-	int i;
-
-	for (i = 0; i < demux->feednum; i++)
-		if (demux->feed[i].state == DMX_STATE_FREE)
-			break;
-
-	if (i == demux->feednum)
-		return NULL;
-
-	demux->feed[i].state = DMX_STATE_ALLOCATED;
-
-	return &demux->feed[i];
-}
-
-static int dvb_demux_feed_find(struct dvb_demux_feed *feed)
-{
-	struct dvb_demux_feed *entry;
-
-	list_for_each_entry(entry, &feed->demux->feed_list, list_head)
-		if (entry == feed)
-			return 1;
-
-	return 0;
-}
-
-static void dvb_demux_feed_add(struct dvb_demux_feed *feed)
-{
-	spin_lock_irq(&feed->demux->lock);
-	if (dvb_demux_feed_find(feed)) {
-		printk(KERN_ERR "%s: feed already in list (type=%x state=%x pid=%x)\n",
-		       __func__, feed->type, feed->state, feed->pid);
-		goto out;
-	}
-
-	list_add(&feed->list_head, &feed->demux->feed_list);
-out:
-	spin_unlock_irq(&feed->demux->lock);
-}
-
-static void dvb_demux_feed_del(struct dvb_demux_feed *feed)
-{
-	spin_lock_irq(&feed->demux->lock);
-	if (!(dvb_demux_feed_find(feed))) {
-		printk(KERN_ERR "%s: feed not in list (type=%x state=%x pid=%x)\n",
-		       __func__, feed->type, feed->state, feed->pid);
-		goto out;
-	}
-
-	list_del(&feed->list_head);
-out:
-	spin_unlock_irq(&feed->demux->lock);
-}
-
-static int dmx_ts_feed_set(struct dmx_ts_feed *ts_feed, u16 pid, int ts_type,
-			   enum dmx_ts_pes pes_type,
-			   size_t circular_buffer_size, struct timespec timeout)
-{
-	struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed;
-	struct dvb_demux *demux = feed->demux;
-
-	if (pid > DMX_MAX_PID)
-		return -EINVAL;
-
-	if (mutex_lock_interruptible(&demux->mutex))
-		return -ERESTARTSYS;
-
-	if (ts_type & TS_DECODER) {
-		if (pes_type >= DMX_TS_PES_OTHER) {
-			mutex_unlock(&demux->mutex);
-			return -EINVAL;
-		}
-
-		if (demux->pesfilter[pes_type] &&
-		    demux->pesfilter[pes_type] != feed) {
-			mutex_unlock(&demux->mutex);
-			return -EINVAL;
-		}
-
-		demux->pesfilter[pes_type] = feed;
-		demux->pids[pes_type] = pid;
-	}
-
-	dvb_demux_feed_add(feed);
-
-	feed->pid = pid;
-	feed->buffer_size = circular_buffer_size;
-	feed->timeout = timeout;
-	feed->ts_type = ts_type;
-	feed->pes_type = pes_type;
-
-	if (feed->buffer_size) {
-#ifdef NOBUFS
-		feed->buffer = NULL;
-#else
-		feed->buffer = vmalloc(feed->buffer_size);
-		if (!feed->buffer) {
-			mutex_unlock(&demux->mutex);
-			return -ENOMEM;
-		}
-#endif
-	}
-
-	feed->state = DMX_STATE_READY;
-	mutex_unlock(&demux->mutex);
-
-	return 0;
-}
-
-static int dmx_ts_feed_start_filtering(struct dmx_ts_feed *ts_feed)
-{
-	struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed;
-	struct dvb_demux *demux = feed->demux;
-	int ret;
-
-	if (mutex_lock_interruptible(&demux->mutex))
-		return -ERESTARTSYS;
-
-	if (feed->state != DMX_STATE_READY || feed->type != DMX_TYPE_TS) {
-		mutex_unlock(&demux->mutex);
-		return -EINVAL;
-	}
-
-	if (!demux->start_feed) {
-		mutex_unlock(&demux->mutex);
-		return -ENODEV;
-	}
-
-	if ((ret = demux->start_feed(feed)) < 0) {
-		mutex_unlock(&demux->mutex);
-		return ret;
-	}
-
-	spin_lock_irq(&demux->lock);
-	ts_feed->is_filtering = 1;
-	feed->state = DMX_STATE_GO;
-	spin_unlock_irq(&demux->lock);
-	mutex_unlock(&demux->mutex);
-
-	return 0;
-}
-
-static int dmx_ts_feed_stop_filtering(struct dmx_ts_feed *ts_feed)
-{
-	struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed;
-	struct dvb_demux *demux = feed->demux;
-	int ret;
-
-	mutex_lock(&demux->mutex);
-
-	if (feed->state < DMX_STATE_GO) {
-		mutex_unlock(&demux->mutex);
-		return -EINVAL;
-	}
-
-	if (!demux->stop_feed) {
-		mutex_unlock(&demux->mutex);
-		return -ENODEV;
-	}
-
-	ret = demux->stop_feed(feed);
-
-	spin_lock_irq(&demux->lock);
-	ts_feed->is_filtering = 0;
-	feed->state = DMX_STATE_ALLOCATED;
-	spin_unlock_irq(&demux->lock);
-	mutex_unlock(&demux->mutex);
-
-	return ret;
-}
-
-static int dvbdmx_allocate_ts_feed(struct dmx_demux *dmx,
-				   struct dmx_ts_feed **ts_feed,
-				   dmx_ts_cb callback)
-{
-	struct dvb_demux *demux = (struct dvb_demux *)dmx;
-	struct dvb_demux_feed *feed;
-
-	if (mutex_lock_interruptible(&demux->mutex))
-		return -ERESTARTSYS;
-
-	if (!(feed = dvb_dmx_feed_alloc(demux))) {
-		mutex_unlock(&demux->mutex);
-		return -EBUSY;
-	}
-
-	feed->type = DMX_TYPE_TS;
-	feed->cb.ts = callback;
-	feed->demux = demux;
-	feed->pid = 0xffff;
-	feed->peslen = 0xfffa;
-	feed->buffer = NULL;
-
-	(*ts_feed) = &feed->feed.ts;
-	(*ts_feed)->parent = dmx;
-	(*ts_feed)->priv = NULL;
-	(*ts_feed)->is_filtering = 0;
-	(*ts_feed)->start_filtering = dmx_ts_feed_start_filtering;
-	(*ts_feed)->stop_filtering = dmx_ts_feed_stop_filtering;
-	(*ts_feed)->set = dmx_ts_feed_set;
-
-	if (!(feed->filter = dvb_dmx_filter_alloc(demux))) {
-		feed->state = DMX_STATE_FREE;
-		mutex_unlock(&demux->mutex);
-		return -EBUSY;
-	}
-
-	feed->filter->type = DMX_TYPE_TS;
-	feed->filter->feed = feed;
-	feed->filter->state = DMX_STATE_READY;
-
-	mutex_unlock(&demux->mutex);
-
-	return 0;
-}
-
-static int dvbdmx_release_ts_feed(struct dmx_demux *dmx,
-				  struct dmx_ts_feed *ts_feed)
-{
-	struct dvb_demux *demux = (struct dvb_demux *)dmx;
-	struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed;
-
-	mutex_lock(&demux->mutex);
-
-	if (feed->state == DMX_STATE_FREE) {
-		mutex_unlock(&demux->mutex);
-		return -EINVAL;
-	}
-#ifndef NOBUFS
-	vfree(feed->buffer);
-	feed->buffer = NULL;
-#endif
-
-	feed->state = DMX_STATE_FREE;
-	feed->filter->state = DMX_STATE_FREE;
-
-	dvb_demux_feed_del(feed);
-
-	feed->pid = 0xffff;
-
-	if (feed->ts_type & TS_DECODER && feed->pes_type < DMX_TS_PES_OTHER)
-		demux->pesfilter[feed->pes_type] = NULL;
-
-	mutex_unlock(&demux->mutex);
-	return 0;
-}
-
-/******************************************************************************
- * dmx_section_feed API calls
- ******************************************************************************/
-
-static int dmx_section_feed_allocate_filter(struct dmx_section_feed *feed,
-					    struct dmx_section_filter **filter)
-{
-	struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed;
-	struct dvb_demux *dvbdemux = dvbdmxfeed->demux;
-	struct dvb_demux_filter *dvbdmxfilter;
-
-	if (mutex_lock_interruptible(&dvbdemux->mutex))
-		return -ERESTARTSYS;
-
-	dvbdmxfilter = dvb_dmx_filter_alloc(dvbdemux);
-	if (!dvbdmxfilter) {
-		mutex_unlock(&dvbdemux->mutex);
-		return -EBUSY;
-	}
-
-	spin_lock_irq(&dvbdemux->lock);
-	*filter = &dvbdmxfilter->filter;
-	(*filter)->parent = feed;
-	(*filter)->priv = NULL;
-	dvbdmxfilter->feed = dvbdmxfeed;
-	dvbdmxfilter->type = DMX_TYPE_SEC;
-	dvbdmxfilter->state = DMX_STATE_READY;
-	dvbdmxfilter->next = dvbdmxfeed->filter;
-	dvbdmxfeed->filter = dvbdmxfilter;
-	spin_unlock_irq(&dvbdemux->lock);
-
-	mutex_unlock(&dvbdemux->mutex);
-	return 0;
-}
-
-static int dmx_section_feed_set(struct dmx_section_feed *feed,
-				u16 pid, size_t circular_buffer_size,
-				int check_crc)
-{
-	struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed;
-	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
-
-	if (pid > 0x1fff)
-		return -EINVAL;
-
-	if (mutex_lock_interruptible(&dvbdmx->mutex))
-		return -ERESTARTSYS;
-
-	dvb_demux_feed_add(dvbdmxfeed);
-
-	dvbdmxfeed->pid = pid;
-	dvbdmxfeed->buffer_size = circular_buffer_size;
-	dvbdmxfeed->feed.sec.check_crc = check_crc;
-
-#ifdef NOBUFS
-	dvbdmxfeed->buffer = NULL;
-#else
-	dvbdmxfeed->buffer = vmalloc(dvbdmxfeed->buffer_size);
-	if (!dvbdmxfeed->buffer) {
-		mutex_unlock(&dvbdmx->mutex);
-		return -ENOMEM;
-	}
-#endif
-
-	dvbdmxfeed->state = DMX_STATE_READY;
-	mutex_unlock(&dvbdmx->mutex);
-	return 0;
-}
-
-static void prepare_secfilters(struct dvb_demux_feed *dvbdmxfeed)
-{
-	int i;
-	struct dvb_demux_filter *f;
-	struct dmx_section_filter *sf;
-	u8 mask, mode, doneq;
-
-	if (!(f = dvbdmxfeed->filter))
-		return;
-	do {
-		sf = &f->filter;
-		doneq = 0;
-		for (i = 0; i < DVB_DEMUX_MASK_MAX; i++) {
-			mode = sf->filter_mode[i];
-			mask = sf->filter_mask[i];
-			f->maskandmode[i] = mask & mode;
-			doneq |= f->maskandnotmode[i] = mask & ~mode;
-		}
-		f->doneq = doneq ? 1 : 0;
-	} while ((f = f->next));
-}
-
-static int dmx_section_feed_start_filtering(struct dmx_section_feed *feed)
-{
-	struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed;
-	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
-	int ret;
-
-	if (mutex_lock_interruptible(&dvbdmx->mutex))
-		return -ERESTARTSYS;
-
-	if (feed->is_filtering) {
-		mutex_unlock(&dvbdmx->mutex);
-		return -EBUSY;
-	}
-
-	if (!dvbdmxfeed->filter) {
-		mutex_unlock(&dvbdmx->mutex);
-		return -EINVAL;
-	}
-
-	dvbdmxfeed->feed.sec.tsfeedp = 0;
-	dvbdmxfeed->feed.sec.secbuf = dvbdmxfeed->feed.sec.secbuf_base;
-	dvbdmxfeed->feed.sec.secbufp = 0;
-	dvbdmxfeed->feed.sec.seclen = 0;
-
-	if (!dvbdmx->start_feed) {
-		mutex_unlock(&dvbdmx->mutex);
-		return -ENODEV;
-	}
-
-	prepare_secfilters(dvbdmxfeed);
-
-	if ((ret = dvbdmx->start_feed(dvbdmxfeed)) < 0) {
-		mutex_unlock(&dvbdmx->mutex);
-		return ret;
-	}
-
-	spin_lock_irq(&dvbdmx->lock);
-	feed->is_filtering = 1;
-	dvbdmxfeed->state = DMX_STATE_GO;
-	spin_unlock_irq(&dvbdmx->lock);
-
-	mutex_unlock(&dvbdmx->mutex);
-	return 0;
-}
-
-static int dmx_section_feed_stop_filtering(struct dmx_section_feed *feed)
-{
-	struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed;
-	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
-	int ret;
-
-	mutex_lock(&dvbdmx->mutex);
-
-	if (!dvbdmx->stop_feed) {
-		mutex_unlock(&dvbdmx->mutex);
-		return -ENODEV;
-	}
-
-	ret = dvbdmx->stop_feed(dvbdmxfeed);
-
-	spin_lock_irq(&dvbdmx->lock);
-	dvbdmxfeed->state = DMX_STATE_READY;
-	feed->is_filtering = 0;
-	spin_unlock_irq(&dvbdmx->lock);
-
-	mutex_unlock(&dvbdmx->mutex);
-	return ret;
-}
-
-static int dmx_section_feed_release_filter(struct dmx_section_feed *feed,
-					   struct dmx_section_filter *filter)
-{
-	struct dvb_demux_filter *dvbdmxfilter = (struct dvb_demux_filter *)filter, *f;
-	struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed;
-	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
-
-	mutex_lock(&dvbdmx->mutex);
-
-	if (dvbdmxfilter->feed != dvbdmxfeed) {
-		mutex_unlock(&dvbdmx->mutex);
-		return -EINVAL;
-	}
-
-	if (feed->is_filtering)
-		feed->stop_filtering(feed);
-
-	spin_lock_irq(&dvbdmx->lock);
-	f = dvbdmxfeed->filter;
-
-	if (f == dvbdmxfilter) {
-		dvbdmxfeed->filter = dvbdmxfilter->next;
-	} else {
-		while (f->next != dvbdmxfilter)
-			f = f->next;
-		f->next = f->next->next;
-	}
-
-	dvbdmxfilter->state = DMX_STATE_FREE;
-	spin_unlock_irq(&dvbdmx->lock);
-	mutex_unlock(&dvbdmx->mutex);
-	return 0;
-}
-
-static int dvbdmx_allocate_section_feed(struct dmx_demux *demux,
-					struct dmx_section_feed **feed,
-					dmx_section_cb callback)
-{
-	struct dvb_demux *dvbdmx = (struct dvb_demux *)demux;
-	struct dvb_demux_feed *dvbdmxfeed;
-
-	if (mutex_lock_interruptible(&dvbdmx->mutex))
-		return -ERESTARTSYS;
-
-	if (!(dvbdmxfeed = dvb_dmx_feed_alloc(dvbdmx))) {
-		mutex_unlock(&dvbdmx->mutex);
-		return -EBUSY;
-	}
-
-	dvbdmxfeed->type = DMX_TYPE_SEC;
-	dvbdmxfeed->cb.sec = callback;
-	dvbdmxfeed->demux = dvbdmx;
-	dvbdmxfeed->pid = 0xffff;
-	dvbdmxfeed->feed.sec.secbuf = dvbdmxfeed->feed.sec.secbuf_base;
-	dvbdmxfeed->feed.sec.secbufp = dvbdmxfeed->feed.sec.seclen = 0;
-	dvbdmxfeed->feed.sec.tsfeedp = 0;
-	dvbdmxfeed->filter = NULL;
-	dvbdmxfeed->buffer = NULL;
-
-	(*feed) = &dvbdmxfeed->feed.sec;
-	(*feed)->is_filtering = 0;
-	(*feed)->parent = demux;
-	(*feed)->priv = NULL;
-
-	(*feed)->set = dmx_section_feed_set;
-	(*feed)->allocate_filter = dmx_section_feed_allocate_filter;
-	(*feed)->start_filtering = dmx_section_feed_start_filtering;
-	(*feed)->stop_filtering = dmx_section_feed_stop_filtering;
-	(*feed)->release_filter = dmx_section_feed_release_filter;
-
-	mutex_unlock(&dvbdmx->mutex);
-	return 0;
-}
-
-static int dvbdmx_release_section_feed(struct dmx_demux *demux,
-				       struct dmx_section_feed *feed)
-{
-	struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed;
-	struct dvb_demux *dvbdmx = (struct dvb_demux *)demux;
-
-	mutex_lock(&dvbdmx->mutex);
-
-	if (dvbdmxfeed->state == DMX_STATE_FREE) {
-		mutex_unlock(&dvbdmx->mutex);
-		return -EINVAL;
-	}
-#ifndef NOBUFS
-	vfree(dvbdmxfeed->buffer);
-	dvbdmxfeed->buffer = NULL;
-#endif
-	dvbdmxfeed->state = DMX_STATE_FREE;
-
-	dvb_demux_feed_del(dvbdmxfeed);
-
-	dvbdmxfeed->pid = 0xffff;
-
-	mutex_unlock(&dvbdmx->mutex);
-	return 0;
-}
-
-/******************************************************************************
- * dvb_demux kernel data API calls
- ******************************************************************************/
-
-static int dvbdmx_open(struct dmx_demux *demux)
-{
-	struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
-
-	if (dvbdemux->users >= MAX_DVB_DEMUX_USERS)
-		return -EUSERS;
-
-	dvbdemux->users++;
-	return 0;
-}
-
-static int dvbdmx_close(struct dmx_demux *demux)
-{
-	struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
-
-	if (dvbdemux->users == 0)
-		return -ENODEV;
-
-	dvbdemux->users--;
-	//FIXME: release any unneeded resources if users==0
-	return 0;
-}
-
-static int dvbdmx_write(struct dmx_demux *demux, const char __user *buf, size_t count)
-{
-	struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
-	void *p;
-
-	if ((!demux->frontend) || (demux->frontend->source != DMX_MEMORY_FE))
-		return -EINVAL;
-
-	p = memdup_user(buf, count);
-	if (IS_ERR(p))
-		return PTR_ERR(p);
-	if (mutex_lock_interruptible(&dvbdemux->mutex)) {
-		kfree(p);
-		return -ERESTARTSYS;
-	}
-	dvb_dmx_swfilter(dvbdemux, p, count);
-	kfree(p);
-	mutex_unlock(&dvbdemux->mutex);
-
-	if (signal_pending(current))
-		return -EINTR;
-	return count;
-}
-
-static int dvbdmx_add_frontend(struct dmx_demux *demux,
-			       struct dmx_frontend *frontend)
-{
-	struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
-	struct list_head *head = &dvbdemux->frontend_list;
-
-	list_add(&(frontend->connectivity_list), head);
-
-	return 0;
-}
-
-static int dvbdmx_remove_frontend(struct dmx_demux *demux,
-				  struct dmx_frontend *frontend)
-{
-	struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
-	struct list_head *pos, *n, *head = &dvbdemux->frontend_list;
-
-	list_for_each_safe(pos, n, head) {
-		if (DMX_FE_ENTRY(pos) == frontend) {
-			list_del(pos);
-			return 0;
-		}
-	}
-
-	return -ENODEV;
-}
-
-static struct list_head *dvbdmx_get_frontends(struct dmx_demux *demux)
-{
-	struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
-
-	if (list_empty(&dvbdemux->frontend_list))
-		return NULL;
-
-	return &dvbdemux->frontend_list;
-}
-
-static int dvbdmx_connect_frontend(struct dmx_demux *demux,
-				   struct dmx_frontend *frontend)
-{
-	struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
-
-	if (demux->frontend)
-		return -EINVAL;
-
-	mutex_lock(&dvbdemux->mutex);
-
-	demux->frontend = frontend;
-	mutex_unlock(&dvbdemux->mutex);
-	return 0;
-}
-
-static int dvbdmx_disconnect_frontend(struct dmx_demux *demux)
-{
-	struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
-
-	mutex_lock(&dvbdemux->mutex);
-
-	demux->frontend = NULL;
-	mutex_unlock(&dvbdemux->mutex);
-	return 0;
-}
-
-static int dvbdmx_get_pes_pids(struct dmx_demux *demux, u16 * pids)
-{
-	struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
-
-	memcpy(pids, dvbdemux->pids, 5 * sizeof(u16));
-	return 0;
-}
-
-int dvb_dmx_init(struct dvb_demux *dvbdemux)
-{
-	int i;
-	struct dmx_demux *dmx = &dvbdemux->dmx;
-
-	dvbdemux->cnt_storage = NULL;
-	dvbdemux->users = 0;
-	dvbdemux->filter = vmalloc(dvbdemux->filternum * sizeof(struct dvb_demux_filter));
-
-	if (!dvbdemux->filter)
-		return -ENOMEM;
-
-	dvbdemux->feed = vmalloc(dvbdemux->feednum * sizeof(struct dvb_demux_feed));
-	if (!dvbdemux->feed) {
-		vfree(dvbdemux->filter);
-		dvbdemux->filter = NULL;
-		return -ENOMEM;
-	}
-	for (i = 0; i < dvbdemux->filternum; i++) {
-		dvbdemux->filter[i].state = DMX_STATE_FREE;
-		dvbdemux->filter[i].index = i;
-	}
-	for (i = 0; i < dvbdemux->feednum; i++) {
-		dvbdemux->feed[i].state = DMX_STATE_FREE;
-		dvbdemux->feed[i].index = i;
-	}
-
-	dvbdemux->cnt_storage = vmalloc(MAX_PID + 1);
-	if (!dvbdemux->cnt_storage)
-		printk(KERN_WARNING "Couldn't allocate memory for TS/TEI check. Disabling it\n");
-
-	INIT_LIST_HEAD(&dvbdemux->frontend_list);
-
-	for (i = 0; i < DMX_TS_PES_OTHER; i++) {
-		dvbdemux->pesfilter[i] = NULL;
-		dvbdemux->pids[i] = 0xffff;
-	}
-
-	INIT_LIST_HEAD(&dvbdemux->feed_list);
-
-	dvbdemux->playing = 0;
-	dvbdemux->recording = 0;
-	dvbdemux->tsbufp = 0;
-
-	if (!dvbdemux->check_crc32)
-		dvbdemux->check_crc32 = dvb_dmx_crc32;
-
-	if (!dvbdemux->memcopy)
-		dvbdemux->memcopy = dvb_dmx_memcopy;
-
-	dmx->frontend = NULL;
-	dmx->priv = dvbdemux;
-	dmx->open = dvbdmx_open;
-	dmx->close = dvbdmx_close;
-	dmx->write = dvbdmx_write;
-	dmx->allocate_ts_feed = dvbdmx_allocate_ts_feed;
-	dmx->release_ts_feed = dvbdmx_release_ts_feed;
-	dmx->allocate_section_feed = dvbdmx_allocate_section_feed;
-	dmx->release_section_feed = dvbdmx_release_section_feed;
-
-	dmx->add_frontend = dvbdmx_add_frontend;
-	dmx->remove_frontend = dvbdmx_remove_frontend;
-	dmx->get_frontends = dvbdmx_get_frontends;
-	dmx->connect_frontend = dvbdmx_connect_frontend;
-	dmx->disconnect_frontend = dvbdmx_disconnect_frontend;
-	dmx->get_pes_pids = dvbdmx_get_pes_pids;
-
-	mutex_init(&dvbdemux->mutex);
-	spin_lock_init(&dvbdemux->lock);
-
-	return 0;
-}
-
-EXPORT_SYMBOL(dvb_dmx_init);
-
-void dvb_dmx_release(struct dvb_demux *dvbdemux)
-{
-	vfree(dvbdemux->cnt_storage);
-	vfree(dvbdemux->filter);
-	vfree(dvbdemux->feed);
-}
-
-EXPORT_SYMBOL(dvb_dmx_release);
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.h b/drivers/media/dvb/dvb-core/dvb_demux.h
deleted file mode 100644
index fa7188a..0000000
--- a/drivers/media/dvb/dvb-core/dvb_demux.h
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * dvb_demux.h: DVB kernel demux API
- *
- * Copyright (C) 2000-2001 Marcus Metzler & Ralph Metzler
- *                         for convergence integrated media GmbH
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1
- * 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 Lesser General Public 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 _DVB_DEMUX_H_
-#define _DVB_DEMUX_H_
-
-#include <linux/time.h>
-#include <linux/timer.h>
-#include <linux/spinlock.h>
-#include <linux/mutex.h>
-
-#include "demux.h"
-
-#define DMX_TYPE_TS  0
-#define DMX_TYPE_SEC 1
-#define DMX_TYPE_PES 2
-
-#define DMX_STATE_FREE      0
-#define DMX_STATE_ALLOCATED 1
-#define DMX_STATE_SET       2
-#define DMX_STATE_READY     3
-#define DMX_STATE_GO        4
-
-#define DVB_DEMUX_MASK_MAX 18
-
-#define MAX_PID 0x1fff
-
-#define SPEED_PKTS_INTERVAL 50000
-
-struct dvb_demux_filter {
-	struct dmx_section_filter filter;
-	u8 maskandmode[DMX_MAX_FILTER_SIZE];
-	u8 maskandnotmode[DMX_MAX_FILTER_SIZE];
-	int doneq;
-
-	struct dvb_demux_filter *next;
-	struct dvb_demux_feed *feed;
-	int index;
-	int state;
-	int type;
-
-	u16 hw_handle;
-	struct timer_list timer;
-};
-
-#define DMX_FEED_ENTRY(pos) list_entry(pos, struct dvb_demux_feed, list_head)
-
-struct dvb_demux_feed {
-	union {
-		struct dmx_ts_feed ts;
-		struct dmx_section_feed sec;
-	} feed;
-
-	union {
-		dmx_ts_cb ts;
-		dmx_section_cb sec;
-	} cb;
-
-	struct dvb_demux *demux;
-	void *priv;
-	int type;
-	int state;
-	u16 pid;
-	u8 *buffer;
-	int buffer_size;
-
-	struct timespec timeout;
-	struct dvb_demux_filter *filter;
-
-	int ts_type;
-	enum dmx_ts_pes pes_type;
-
-	int cc;
-	int pusi_seen;		/* prevents feeding of garbage from previous section */
-
-	u16 peslen;
-
-	struct list_head list_head;
-	unsigned int index;	/* a unique index for each feed (can be used as hardware pid filter index) */
-};
-
-struct dvb_demux {
-	struct dmx_demux dmx;
-	void *priv;
-	int filternum;
-	int feednum;
-	int (*start_feed)(struct dvb_demux_feed *feed);
-	int (*stop_feed)(struct dvb_demux_feed *feed);
-	int (*write_to_decoder)(struct dvb_demux_feed *feed,
-				 const u8 *buf, size_t len);
-	u32 (*check_crc32)(struct dvb_demux_feed *feed,
-			    const u8 *buf, size_t len);
-	void (*memcopy)(struct dvb_demux_feed *feed, u8 *dst,
-			 const u8 *src, size_t len);
-
-	int users;
-#define MAX_DVB_DEMUX_USERS 10
-	struct dvb_demux_filter *filter;
-	struct dvb_demux_feed *feed;
-
-	struct list_head frontend_list;
-
-	struct dvb_demux_feed *pesfilter[DMX_TS_PES_OTHER];
-	u16 pids[DMX_TS_PES_OTHER];
-	int playing;
-	int recording;
-
-#define DMX_MAX_PID 0x2000
-	struct list_head feed_list;
-	u8 tsbuf[204];
-	int tsbufp;
-
-	struct mutex mutex;
-	spinlock_t lock;
-
-	uint8_t *cnt_storage; /* for TS continuity check */
-
-	struct timespec speed_last_time; /* for TS speed check */
-	uint32_t speed_pkts_cnt; /* for TS speed check */
-};
-
-int dvb_dmx_init(struct dvb_demux *dvbdemux);
-void dvb_dmx_release(struct dvb_demux *dvbdemux);
-void dvb_dmx_swfilter_packets(struct dvb_demux *dvbdmx, const u8 *buf,
-			      size_t count);
-void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count);
-void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf,
-			  size_t count);
-void dvb_dmx_swfilter_raw(struct dvb_demux *demux, const u8 *buf,
-			  size_t count);
-
-#endif /* _DVB_DEMUX_H_ */
diff --git a/drivers/media/dvb/dvb-core/dvb_filter.c b/drivers/media/dvb/dvb-core/dvb_filter.c
deleted file mode 100644
index 772003f..0000000
--- a/drivers/media/dvb/dvb-core/dvb_filter.c
+++ /dev/null
@@ -1,603 +0,0 @@
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include "dvb_filter.h"
-
-#if 0
-static unsigned int bitrates[3][16] =
-{{0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,0},
- {0,32,48,56,64,80,96,112,128,160,192,224,256,320,384,0},
- {0,32,40,48,56,64,80,96,112,128,160,192,224,256,320,0}};
-#endif
-
-static u32 freq[4] = {480, 441, 320, 0};
-
-static unsigned int ac3_bitrates[32] =
-    {32,40,48,56,64,80,96,112,128,160,192,224,256,320,384,448,512,576,640,
-     0,0,0,0,0,0,0,0,0,0,0,0,0};
-
-static u32 ac3_frames[3][32] =
-    {{64,80,96,112,128,160,192,224,256,320,384,448,512,640,768,896,1024,
-      1152,1280,0,0,0,0,0,0,0,0,0,0,0,0,0},
-     {69,87,104,121,139,174,208,243,278,348,417,487,557,696,835,975,1114,
-      1253,1393,0,0,0,0,0,0,0,0,0,0,0,0,0},
-     {96,120,144,168,192,240,288,336,384,480,576,672,768,960,1152,1344,
-      1536,1728,1920,0,0,0,0,0,0,0,0,0,0,0,0,0}};
-
-
-
-#if 0
-static void setup_ts2pes(ipack *pa, ipack *pv, u16 *pida, u16 *pidv,
-		  void (*pes_write)(u8 *buf, int count, void *data),
-		  void *priv)
-{
-	dvb_filter_ipack_init(pa, IPACKS, pes_write);
-	dvb_filter_ipack_init(pv, IPACKS, pes_write);
-	pa->pid = pida;
-	pv->pid = pidv;
-	pa->data = priv;
-	pv->data = priv;
-}
-#endif
-
-#if 0
-static void ts_to_pes(ipack *p, u8 *buf) // don't need count (=188)
-{
-	u8 off = 0;
-
-	if (!buf || !p ){
-		printk("NULL POINTER IDIOT\n");
-		return;
-	}
-	if (buf[1]&PAY_START) {
-		if (p->plength == MMAX_PLENGTH-6 && p->found>6){
-			p->plength = p->found-6;
-			p->found = 0;
-			send_ipack(p);
-			dvb_filter_ipack_reset(p);
-		}
-	}
-	if (buf[3] & ADAPT_FIELD) {  // adaptation field?
-		off = buf[4] + 1;
-		if (off+4 > 187) return;
-	}
-	dvb_filter_instant_repack(buf+4+off, TS_SIZE-4-off, p);
-}
-#endif
-
-#if 0
-/* needs 5 byte input, returns picture coding type*/
-static int read_picture_header(u8 *headr, struct mpg_picture *pic, int field, int pr)
-{
-	u8 pct;
-
-	if (pr) printk( "Pic header: ");
-	pic->temporal_reference[field] = (( headr[0] << 2 ) |
-					  (headr[1] & 0x03) )& 0x03ff;
-	if (pr) printk( " temp ref: 0x%04x", pic->temporal_reference[field]);
-
-	pct = ( headr[1] >> 2 ) & 0x07;
-	pic->picture_coding_type[field] = pct;
-	if (pr) {
-		switch(pct){
-			case I_FRAME:
-				printk( "  I-FRAME");
-				break;
-			case B_FRAME:
-				printk( "  B-FRAME");
-				break;
-			case P_FRAME:
-				printk( "  P-FRAME");
-				break;
-		}
-	}
-
-
-	pic->vinfo.vbv_delay  = (( headr[1] >> 5 ) | ( headr[2] << 3) |
-				 ( (headr[3] & 0x1F) << 11) ) & 0xffff;
-
-	if (pr) printk( " vbv delay: 0x%04x", pic->vinfo.vbv_delay);
-
-	pic->picture_header_parameter = ( headr[3] & 0xe0 ) |
-		((headr[4] & 0x80) >> 3);
-
-	if ( pct == B_FRAME ){
-		pic->picture_header_parameter |= ( headr[4] >> 3 ) & 0x0f;
-	}
-	if (pr) printk( " pic head param: 0x%x",
-			pic->picture_header_parameter);
-
-	return pct;
-}
-#endif
-
-#if 0
-/* needs 4 byte input */
-static int read_gop_header(u8 *headr, struct mpg_picture *pic, int pr)
-{
-	if (pr) printk("GOP header: ");
-
-	pic->time_code  = (( headr[0] << 17 ) | ( headr[1] << 9) |
-			   ( headr[2] << 1 ) | (headr[3] &0x01)) & 0x1ffffff;
-
-	if (pr) printk(" time: %d:%d.%d ", (headr[0]>>2)& 0x1F,
-		       ((headr[0]<<4)& 0x30)| ((headr[1]>>4)& 0x0F),
-		       ((headr[1]<<3)& 0x38)| ((headr[2]>>5)& 0x0F));
-
-	if ( ( headr[3] & 0x40 ) != 0 ){
-		pic->closed_gop = 1;
-	} else {
-		pic->closed_gop = 0;
-	}
-	if (pr) printk("closed: %d", pic->closed_gop);
-
-	if ( ( headr[3] & 0x20 ) != 0 ){
-		pic->broken_link = 1;
-	} else {
-		pic->broken_link = 0;
-	}
-	if (pr) printk(" broken: %d\n", pic->broken_link);
-
-	return 0;
-}
-#endif
-
-#if 0
-/* needs 8 byte input */
-static int read_sequence_header(u8 *headr, struct dvb_video_info *vi, int pr)
-{
-	int sw;
-	int form = -1;
-
-	if (pr) printk("Reading sequence header\n");
-
-	vi->horizontal_size	= ((headr[1] &0xF0) >> 4) | (headr[0] << 4);
-	vi->vertical_size	= ((headr[1] &0x0F) << 8) | (headr[2]);
-
-	sw = (int)((headr[3]&0xF0) >> 4) ;
-
-	switch( sw ){
-	case 1:
-		if (pr)
-			printk("Videostream: ASPECT: 1:1");
-		vi->aspect_ratio = 100;
-		break;
-	case 2:
-		if (pr)
-			printk("Videostream: ASPECT: 4:3");
-		vi->aspect_ratio = 133;
-		break;
-	case 3:
-		if (pr)
-			printk("Videostream: ASPECT: 16:9");
-		vi->aspect_ratio = 177;
-		break;
-	case 4:
-		if (pr)
-			printk("Videostream: ASPECT: 2.21:1");
-		vi->aspect_ratio = 221;
-		break;
-
-	case 5 ... 15:
-		if (pr)
-			printk("Videostream: ASPECT: reserved");
-		vi->aspect_ratio = 0;
-		break;
-
-	default:
-		vi->aspect_ratio = 0;
-		return -1;
-	}
-
-	if (pr)
-		printk("  Size = %dx%d",vi->horizontal_size,vi->vertical_size);
-
-	sw = (int)(headr[3]&0x0F);
-
-	switch ( sw ) {
-	case 1:
-		if (pr)
-			printk("  FRate: 23.976 fps");
-		vi->framerate = 23976;
-		form = -1;
-		break;
-	case 2:
-		if (pr)
-			printk("  FRate: 24 fps");
-		vi->framerate = 24000;
-		form = -1;
-		break;
-	case 3:
-		if (pr)
-			printk("  FRate: 25 fps");
-		vi->framerate = 25000;
-		form = VIDEO_MODE_PAL;
-		break;
-	case 4:
-		if (pr)
-			printk("  FRate: 29.97 fps");
-		vi->framerate = 29970;
-		form = VIDEO_MODE_NTSC;
-		break;
-	case 5:
-		if (pr)
-			printk("  FRate: 30 fps");
-		vi->framerate = 30000;
-		form = VIDEO_MODE_NTSC;
-		break;
-	case 6:
-		if (pr)
-			printk("  FRate: 50 fps");
-		vi->framerate = 50000;
-		form = VIDEO_MODE_PAL;
-		break;
-	case 7:
-		if (pr)
-			printk("  FRate: 60 fps");
-		vi->framerate = 60000;
-		form = VIDEO_MODE_NTSC;
-		break;
-	}
-
-	vi->bit_rate = (headr[4] << 10) | (headr[5] << 2) | (headr[6] & 0x03);
-
-	vi->vbv_buffer_size
-		= (( headr[6] & 0xF8) >> 3 ) | (( headr[7] & 0x1F )<< 5);
-
-	if (pr){
-		printk("  BRate: %d Mbit/s",4*(vi->bit_rate)/10000);
-		printk("  vbvbuffer %d",16*1024*(vi->vbv_buffer_size));
-		printk("\n");
-	}
-
-	vi->video_format = form;
-
-	return 0;
-}
-#endif
-
-
-#if 0
-static int get_vinfo(u8 *mbuf, int count, struct dvb_video_info *vi, int pr)
-{
-	u8 *headr;
-	int found = 0;
-	int c = 0;
-
-	while (found < 4 && c+4 < count){
-		u8 *b;
-
-		b = mbuf+c;
-		if ( b[0] == 0x00 && b[1] == 0x00 && b[2] == 0x01
-		     && b[3] == 0xb3) found = 4;
-		else {
-			c++;
-		}
-	}
-
-	if (! found) return -1;
-	c += 4;
-	if (c+12 >= count) return -1;
-	headr = mbuf+c;
-	if (read_sequence_header(headr, vi, pr) < 0) return -1;
-	vi->off = c-4;
-	return 0;
-}
-#endif
-
-
-#if 0
-static int get_ainfo(u8 *mbuf, int count, struct dvb_audio_info *ai, int pr)
-{
-	u8 *headr;
-	int found = 0;
-	int c = 0;
-	int fr = 0;
-
-	while (found < 2 && c < count){
-		u8 b[2];
-		memcpy( b, mbuf+c, 2);
-
-		if ( b[0] == 0xff && (b[1] & 0xf8) == 0xf8)
-			found = 2;
-		else {
-			c++;
-		}
-	}
-
-	if (!found) return -1;
-
-	if (c+3 >= count) return -1;
-	headr = mbuf+c;
-
-	ai->layer = (headr[1] & 0x06) >> 1;
-
-	if (pr)
-		printk("Audiostream: Layer: %d", 4-ai->layer);
-
-
-	ai->bit_rate = bitrates[(3-ai->layer)][(headr[2] >> 4 )]*1000;
-
-	if (pr){
-		if (ai->bit_rate == 0)
-			printk("  Bit rate: free");
-		else if (ai->bit_rate == 0xf)
-			printk("  BRate: reserved");
-		else
-			printk("  BRate: %d kb/s", ai->bit_rate/1000);
-	}
-
-	fr = (headr[2] & 0x0c ) >> 2;
-	ai->frequency = freq[fr]*100;
-	if (pr){
-		if (ai->frequency == 3)
-			printk("  Freq: reserved\n");
-		else
-			printk("  Freq: %d kHz\n",ai->frequency);
-
-	}
-	ai->off = c;
-	return 0;
-}
-#endif
-
-
-int dvb_filter_get_ac3info(u8 *mbuf, int count, struct dvb_audio_info *ai, int pr)
-{
-	u8 *headr;
-	int found = 0;
-	int c = 0;
-	u8 frame = 0;
-	int fr = 0;
-
-	while ( !found  && c < count){
-		u8 *b = mbuf+c;
-
-		if ( b[0] == 0x0b &&  b[1] == 0x77 )
-			found = 1;
-		else {
-			c++;
-		}
-	}
-
-	if (!found) return -1;
-	if (pr)
-		printk("Audiostream: AC3");
-
-	ai->off = c;
-	if (c+5 >= count) return -1;
-
-	ai->layer = 0;  // 0 for AC3
-	headr = mbuf+c+2;
-
-	frame = (headr[2]&0x3f);
-	ai->bit_rate = ac3_bitrates[frame >> 1]*1000;
-
-	if (pr)
-		printk("  BRate: %d kb/s", (int) ai->bit_rate/1000);
-
-	ai->frequency = (headr[2] & 0xc0 ) >> 6;
-	fr = (headr[2] & 0xc0 ) >> 6;
-	ai->frequency = freq[fr]*100;
-	if (pr) printk ("  Freq: %d Hz\n", (int) ai->frequency);
-
-
-	ai->framesize = ac3_frames[fr][frame >> 1];
-	if ((frame & 1) &&  (fr == 1)) ai->framesize++;
-	ai->framesize = ai->framesize << 1;
-	if (pr) printk ("  Framesize %d\n",(int) ai->framesize);
-
-
-	return 0;
-}
-EXPORT_SYMBOL(dvb_filter_get_ac3info);
-
-
-#if 0
-static u8 *skip_pes_header(u8 **bufp)
-{
-	u8 *inbuf = *bufp;
-	u8 *buf = inbuf;
-	u8 *pts = NULL;
-	int skip = 0;
-
-	static const int mpeg1_skip_table[16] = {
-		1, 0xffff,      5,     10, 0xffff, 0xffff, 0xffff, 0xffff,
-		0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff
-	};
-
-
-	if ((inbuf[6] & 0xc0) == 0x80){ /* mpeg2 */
-		if (buf[7] & PTS_ONLY)
-			pts = buf+9;
-		else pts = NULL;
-		buf = inbuf + 9 + inbuf[8];
-	} else {        /* mpeg1 */
-		for (buf = inbuf + 6; *buf == 0xff; buf++)
-			if (buf == inbuf + 6 + 16) {
-				break;
-			}
-		if ((*buf & 0xc0) == 0x40)
-			buf += 2;
-		skip = mpeg1_skip_table [*buf >> 4];
-		if (skip == 5 || skip == 10) pts = buf;
-		else pts = NULL;
-
-		buf += mpeg1_skip_table [*buf >> 4];
-	}
-
-	*bufp = buf;
-	return pts;
-}
-#endif
-
-#if 0
-static void initialize_quant_matrix( u32 *matrix )
-{
-	int i;
-
-	matrix[0]  = 0x08101013;
-	matrix[1]  = 0x10131616;
-	matrix[2]  = 0x16161616;
-	matrix[3]  = 0x1a181a1b;
-	matrix[4]  = 0x1b1b1a1a;
-	matrix[5]  = 0x1a1a1b1b;
-	matrix[6]  = 0x1b1d1d1d;
-	matrix[7]  = 0x2222221d;
-	matrix[8]  = 0x1d1d1b1b;
-	matrix[9]  = 0x1d1d2020;
-	matrix[10] = 0x22222526;
-	matrix[11] = 0x25232322;
-	matrix[12] = 0x23262628;
-	matrix[13] = 0x28283030;
-	matrix[14] = 0x2e2e3838;
-	matrix[15] = 0x3a454553;
-
-	for ( i = 16 ; i < 32 ; i++ )
-		matrix[i] = 0x10101010;
-}
-#endif
-
-#if 0
-static void initialize_mpg_picture(struct mpg_picture *pic)
-{
-	int i;
-
-	/* set MPEG1 */
-	pic->mpeg1_flag = 1;
-	pic->profile_and_level = 0x4A ;        /* MP@LL */
-	pic->progressive_sequence = 1;
-	pic->low_delay = 0;
-
-	pic->sequence_display_extension_flag = 0;
-	for ( i = 0 ; i < 4 ; i++ ){
-		pic->frame_centre_horizontal_offset[i] = 0;
-		pic->frame_centre_vertical_offset[i] = 0;
-	}
-	pic->last_frame_centre_horizontal_offset = 0;
-	pic->last_frame_centre_vertical_offset = 0;
-
-	pic->picture_display_extension_flag[0] = 0;
-	pic->picture_display_extension_flag[1] = 0;
-	pic->sequence_header_flag = 0;
-	pic->gop_flag = 0;
-	pic->sequence_end_flag = 0;
-}
-#endif
-
-#if 0
-static void mpg_set_picture_parameter( int32_t field_type, struct mpg_picture *pic )
-{
-	int16_t last_h_offset;
-	int16_t last_v_offset;
-
-	int16_t *p_h_offset;
-	int16_t *p_v_offset;
-
-	if ( pic->mpeg1_flag ){
-		pic->picture_structure[field_type] = VIDEO_FRAME_PICTURE;
-		pic->top_field_first = 0;
-		pic->repeat_first_field = 0;
-		pic->progressive_frame = 1;
-		pic->picture_coding_parameter = 0x000010;
-	}
-
-	/* Reset flag */
-	pic->picture_display_extension_flag[field_type] = 0;
-
-	last_h_offset = pic->last_frame_centre_horizontal_offset;
-	last_v_offset = pic->last_frame_centre_vertical_offset;
-	if ( field_type == FIRST_FIELD ){
-		p_h_offset = pic->frame_centre_horizontal_offset;
-		p_v_offset = pic->frame_centre_vertical_offset;
-		*p_h_offset = last_h_offset;
-		*(p_h_offset + 1) = last_h_offset;
-		*(p_h_offset + 2) = last_h_offset;
-		*p_v_offset = last_v_offset;
-		*(p_v_offset + 1) = last_v_offset;
-		*(p_v_offset + 2) = last_v_offset;
-	} else {
-		pic->frame_centre_horizontal_offset[3] = last_h_offset;
-		pic->frame_centre_vertical_offset[3] = last_v_offset;
-	}
-}
-#endif
-
-#if 0
-static void init_mpg_picture( struct mpg_picture *pic, int chan, int32_t field_type)
-{
-	pic->picture_header = 0;
-	pic->sequence_header_data
-		= ( INIT_HORIZONTAL_SIZE << 20 )
-			| ( INIT_VERTICAL_SIZE << 8 )
-			| ( INIT_ASPECT_RATIO << 4 )
-			| ( INIT_FRAME_RATE );
-	pic->mpeg1_flag = 0;
-	pic->vinfo.horizontal_size
-		= INIT_DISP_HORIZONTAL_SIZE;
-	pic->vinfo.vertical_size
-		= INIT_DISP_VERTICAL_SIZE;
-	pic->picture_display_extension_flag[field_type]
-		= 0;
-	pic->pts_flag[field_type] = 0;
-
-	pic->sequence_gop_header = 0;
-	pic->picture_header = 0;
-	pic->sequence_header_flag = 0;
-	pic->gop_flag = 0;
-	pic->sequence_end_flag = 0;
-	pic->sequence_display_extension_flag = 0;
-	pic->last_frame_centre_horizontal_offset = 0;
-	pic->last_frame_centre_vertical_offset = 0;
-	pic->channel = chan;
-}
-#endif
-
-void dvb_filter_pes2ts_init(struct dvb_filter_pes2ts *p2ts, unsigned short pid,
-			    dvb_filter_pes2ts_cb_t *cb, void *priv)
-{
-	unsigned char *buf=p2ts->buf;
-
-	buf[0]=0x47;
-	buf[1]=(pid>>8);
-	buf[2]=pid&0xff;
-	p2ts->cc=0;
-	p2ts->cb=cb;
-	p2ts->priv=priv;
-}
-EXPORT_SYMBOL(dvb_filter_pes2ts_init);
-
-int dvb_filter_pes2ts(struct dvb_filter_pes2ts *p2ts, unsigned char *pes,
-		      int len, int payload_start)
-{
-	unsigned char *buf=p2ts->buf;
-	int ret=0, rest;
-
-	//len=6+((pes[4]<<8)|pes[5]);
-
-	if (payload_start)
-		buf[1]|=0x40;
-	else
-		buf[1]&=~0x40;
-	while (len>=184) {
-		buf[3]=0x10|((p2ts->cc++)&0x0f);
-		memcpy(buf+4, pes, 184);
-		if ((ret=p2ts->cb(p2ts->priv, buf)))
-			return ret;
-		len-=184; pes+=184;
-		buf[1]&=~0x40;
-	}
-	if (!len)
-		return 0;
-	buf[3]=0x30|((p2ts->cc++)&0x0f);
-	rest=183-len;
-	if (rest) {
-		buf[5]=0x00;
-		if (rest-1)
-			memset(buf+6, 0xff, rest-1);
-	}
-	buf[4]=rest;
-	memcpy(buf+5+rest, pes, len);
-	return p2ts->cb(p2ts->priv, buf);
-}
-EXPORT_SYMBOL(dvb_filter_pes2ts);
diff --git a/drivers/media/dvb/dvb-core/dvb_filter.h b/drivers/media/dvb/dvb-core/dvb_filter.h
deleted file mode 100644
index 375e3be..0000000
--- a/drivers/media/dvb/dvb-core/dvb_filter.h
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- * dvb_filter.h
- *
- * Copyright (C) 2003 Convergence GmbH
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1
- * 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 Lesser General Public 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 _DVB_FILTER_H_
-#define _DVB_FILTER_H_
-
-#include <linux/slab.h>
-
-#include "demux.h"
-
-typedef int (dvb_filter_pes2ts_cb_t) (void *, unsigned char *);
-
-struct dvb_filter_pes2ts {
-	unsigned char buf[188];
-	unsigned char cc;
-	dvb_filter_pes2ts_cb_t *cb;
-	void *priv;
-};
-
-void dvb_filter_pes2ts_init(struct dvb_filter_pes2ts *p2ts, unsigned short pid,
-			    dvb_filter_pes2ts_cb_t *cb, void *priv);
-
-int dvb_filter_pes2ts(struct dvb_filter_pes2ts *p2ts, unsigned char *pes,
-		      int len, int payload_start);
-
-
-#define PROG_STREAM_MAP  0xBC
-#define PRIVATE_STREAM1  0xBD
-#define PADDING_STREAM   0xBE
-#define PRIVATE_STREAM2  0xBF
-#define AUDIO_STREAM_S   0xC0
-#define AUDIO_STREAM_E   0xDF
-#define VIDEO_STREAM_S   0xE0
-#define VIDEO_STREAM_E   0xEF
-#define ECM_STREAM       0xF0
-#define EMM_STREAM       0xF1
-#define DSM_CC_STREAM    0xF2
-#define ISO13522_STREAM  0xF3
-#define PROG_STREAM_DIR  0xFF
-
-#define DVB_PICTURE_START    0x00
-#define DVB_USER_START       0xb2
-#define DVB_SEQUENCE_HEADER  0xb3
-#define DVB_SEQUENCE_ERROR   0xb4
-#define DVB_EXTENSION_START  0xb5
-#define DVB_SEQUENCE_END     0xb7
-#define DVB_GOP_START        0xb8
-#define DVB_EXCEPT_SLICE     0xb0
-
-#define SEQUENCE_EXTENSION           0x01
-#define SEQUENCE_DISPLAY_EXTENSION   0x02
-#define PICTURE_CODING_EXTENSION     0x08
-#define QUANT_MATRIX_EXTENSION       0x03
-#define PICTURE_DISPLAY_EXTENSION    0x07
-
-#define I_FRAME 0x01
-#define B_FRAME 0x02
-#define P_FRAME 0x03
-
-/* Initialize sequence_data */
-#define INIT_HORIZONTAL_SIZE        720
-#define INIT_VERTICAL_SIZE          576
-#define INIT_ASPECT_RATIO          0x02
-#define INIT_FRAME_RATE            0x03
-#define INIT_DISP_HORIZONTAL_SIZE   540
-#define INIT_DISP_VERTICAL_SIZE     576
-
-
-//flags2
-#define PTS_DTS_FLAGS    0xC0
-#define ESCR_FLAG        0x20
-#define ES_RATE_FLAG     0x10
-#define DSM_TRICK_FLAG   0x08
-#define ADD_CPY_FLAG     0x04
-#define PES_CRC_FLAG     0x02
-#define PES_EXT_FLAG     0x01
-
-//pts_dts flags
-#define PTS_ONLY         0x80
-#define PTS_DTS          0xC0
-
-#define TS_SIZE        188
-#define TRANS_ERROR    0x80
-#define PAY_START      0x40
-#define TRANS_PRIO     0x20
-#define PID_MASK_HI    0x1F
-//flags
-#define TRANS_SCRMBL1  0x80
-#define TRANS_SCRMBL2  0x40
-#define ADAPT_FIELD    0x20
-#define PAYLOAD        0x10
-#define COUNT_MASK     0x0F
-
-// adaptation flags
-#define DISCON_IND     0x80
-#define RAND_ACC_IND   0x40
-#define ES_PRI_IND     0x20
-#define PCR_FLAG       0x10
-#define OPCR_FLAG      0x08
-#define SPLICE_FLAG    0x04
-#define TRANS_PRIV     0x02
-#define ADAP_EXT_FLAG  0x01
-
-// adaptation extension flags
-#define LTW_FLAG       0x80
-#define PIECE_RATE     0x40
-#define SEAM_SPLICE    0x20
-
-
-#define MAX_PLENGTH 0xFFFF
-#define MMAX_PLENGTH (256*MAX_PLENGTH)
-
-#ifndef IPACKS
-#define IPACKS 2048
-#endif
-
-struct ipack {
-	int size;
-	int found;
-	u8 *buf;
-	u8 cid;
-	u32 plength;
-	u8 plen[2];
-	u8 flag1;
-	u8 flag2;
-	u8 hlength;
-	u8 pts[5];
-	u16 *pid;
-	int mpeg;
-	u8 check;
-	int which;
-	int done;
-	void *data;
-	void (*func)(u8 *buf,  int size, void *priv);
-	int count;
-	int repack_subids;
-};
-
-struct dvb_video_info {
-	u32 horizontal_size;
-	u32 vertical_size;
-	u32 aspect_ratio;
-	u32 framerate;
-	u32 video_format;
-	u32 bit_rate;
-	u32 comp_bit_rate;
-	u32 vbv_buffer_size;
-	s16 vbv_delay;
-	u32 CSPF;
-	u32 off;
-};
-
-#define OFF_SIZE 4
-#define FIRST_FIELD 0
-#define SECOND_FIELD 1
-#define VIDEO_FRAME_PICTURE 0x03
-
-struct mpg_picture {
-	int       channel;
-	struct dvb_video_info vinfo;
-	u32      *sequence_gop_header;
-	u32      *picture_header;
-	s32       time_code;
-	int       low_delay;
-	int       closed_gop;
-	int       broken_link;
-	int       sequence_header_flag;
-	int       gop_flag;
-	int       sequence_end_flag;
-
-	u8        profile_and_level;
-	s32       picture_coding_parameter;
-	u32       matrix[32];
-	s8        matrix_change_flag;
-
-	u8        picture_header_parameter;
-  /* bit 0 - 2: bwd f code
-     bit 3    : fpb vector
-     bit 4 - 6: fwd f code
-     bit 7    : fpf vector */
-
-	int       mpeg1_flag;
-	int       progressive_sequence;
-	int       sequence_display_extension_flag;
-	u32       sequence_header_data;
-	s16       last_frame_centre_horizontal_offset;
-	s16       last_frame_centre_vertical_offset;
-
-	u32       pts[2]; /* [0] 1st field, [1] 2nd field */
-	int       top_field_first;
-	int       repeat_first_field;
-	int       progressive_frame;
-	int       bank;
-	int       forward_bank;
-	int       backward_bank;
-	int       compress;
-	s16       frame_centre_horizontal_offset[OFF_SIZE];
-		  /* [0-2] 1st field, [3] 2nd field */
-	s16       frame_centre_vertical_offset[OFF_SIZE];
-		  /* [0-2] 1st field, [3] 2nd field */
-	s16       temporal_reference[2];
-		  /* [0] 1st field, [1] 2nd field */
-
-	s8        picture_coding_type[2];
-		  /* [0] 1st field, [1] 2nd field */
-	s8        picture_structure[2];
-		  /* [0] 1st field, [1] 2nd field */
-	s8        picture_display_extension_flag[2];
-		  /* [0] 1st field, [1] 2nd field */
-		  /* picture_display_extenion() 0:no 1:exit*/
-	s8        pts_flag[2];
-		  /* [0] 1st field, [1] 2nd field */
-};
-
-struct dvb_audio_info {
-	int layer;
-	u32 bit_rate;
-	u32 frequency;
-	u32 mode;
-	u32 mode_extension ;
-	u32 emphasis;
-	u32 framesize;
-	u32 off;
-};
-
-int dvb_filter_get_ac3info(u8 *mbuf, int count, struct dvb_audio_info *ai, int pr);
-
-
-#endif
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c
deleted file mode 100644
index aebcdf2..0000000
--- a/drivers/media/dvb/dvb-core/dvb_frontend.c
+++ /dev/null
@@ -1,2563 +0,0 @@
-/*
- * dvb_frontend.c: DVB frontend tuning interface/thread
- *
- *
- * Copyright (C) 1999-2001 Ralph  Metzler
- *			   Marcus Metzler
- *			   Holger Waechtler
- *				      for convergence integrated media GmbH
- *
- * Copyright (C) 2004 Andrew de Quincey (tuning thread cleanup)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the 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.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-/* Enables DVBv3 compatibility bits at the headers */
-#define __DVB_CORE__
-
-#include <linux/string.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/wait.h>
-#include <linux/slab.h>
-#include <linux/poll.h>
-#include <linux/semaphore.h>
-#include <linux/module.h>
-#include <linux/list.h>
-#include <linux/freezer.h>
-#include <linux/jiffies.h>
-#include <linux/kthread.h>
-#include <asm/processor.h>
-
-#include "dvb_frontend.h"
-#include "dvbdev.h"
-#include <linux/dvb/version.h>
-
-static int dvb_frontend_debug;
-static int dvb_shutdown_timeout;
-static int dvb_force_auto_inversion;
-static int dvb_override_tune_delay;
-static int dvb_powerdown_on_sleep = 1;
-static int dvb_mfe_wait_time = 5;
-
-module_param_named(frontend_debug, dvb_frontend_debug, int, 0644);
-MODULE_PARM_DESC(frontend_debug, "Turn on/off frontend core debugging (default:off).");
-module_param(dvb_shutdown_timeout, int, 0644);
-MODULE_PARM_DESC(dvb_shutdown_timeout, "wait <shutdown_timeout> seconds after close() before suspending hardware");
-module_param(dvb_force_auto_inversion, int, 0644);
-MODULE_PARM_DESC(dvb_force_auto_inversion, "0: normal (default), 1: INVERSION_AUTO forced always");
-module_param(dvb_override_tune_delay, int, 0644);
-MODULE_PARM_DESC(dvb_override_tune_delay, "0: normal (default), >0 => delay in milliseconds to wait for lock after a tune attempt");
-module_param(dvb_powerdown_on_sleep, int, 0644);
-MODULE_PARM_DESC(dvb_powerdown_on_sleep, "0: do not power down, 1: turn LNB voltage off on sleep (default)");
-module_param(dvb_mfe_wait_time, int, 0644);
-MODULE_PARM_DESC(dvb_mfe_wait_time, "Wait up to <mfe_wait_time> seconds on open() for multi-frontend to become available (default:5 seconds)");
-
-#define dprintk if (dvb_frontend_debug) printk
-
-#define FESTATE_IDLE 1
-#define FESTATE_RETUNE 2
-#define FESTATE_TUNING_FAST 4
-#define FESTATE_TUNING_SLOW 8
-#define FESTATE_TUNED 16
-#define FESTATE_ZIGZAG_FAST 32
-#define FESTATE_ZIGZAG_SLOW 64
-#define FESTATE_DISEQC 128
-#define FESTATE_ERROR 256
-#define FESTATE_WAITFORLOCK (FESTATE_TUNING_FAST | FESTATE_TUNING_SLOW | FESTATE_ZIGZAG_FAST | FESTATE_ZIGZAG_SLOW | FESTATE_DISEQC)
-#define FESTATE_SEARCHING_FAST (FESTATE_TUNING_FAST | FESTATE_ZIGZAG_FAST)
-#define FESTATE_SEARCHING_SLOW (FESTATE_TUNING_SLOW | FESTATE_ZIGZAG_SLOW)
-#define FESTATE_LOSTLOCK (FESTATE_ZIGZAG_FAST | FESTATE_ZIGZAG_SLOW)
-
-#define FE_ALGO_HW		1
-/*
- * FESTATE_IDLE. No tuning parameters have been supplied and the loop is idling.
- * FESTATE_RETUNE. Parameters have been supplied, but we have not yet performed the first tune.
- * FESTATE_TUNING_FAST. Tuning parameters have been supplied and fast zigzag scan is in progress.
- * FESTATE_TUNING_SLOW. Tuning parameters have been supplied. Fast zigzag failed, so we're trying again, but slower.
- * FESTATE_TUNED. The frontend has successfully locked on.
- * FESTATE_ZIGZAG_FAST. The lock has been lost, and a fast zigzag has been initiated to try and regain it.
- * FESTATE_ZIGZAG_SLOW. The lock has been lost. Fast zigzag has been failed, so we're trying again, but slower.
- * FESTATE_DISEQC. A DISEQC command has just been issued.
- * FESTATE_WAITFORLOCK. When we're waiting for a lock.
- * FESTATE_SEARCHING_FAST. When we're searching for a signal using a fast zigzag scan.
- * FESTATE_SEARCHING_SLOW. When we're searching for a signal using a slow zigzag scan.
- * FESTATE_LOSTLOCK. When the lock has been lost, and we're searching it again.
- */
-
-#define DVB_FE_NO_EXIT	0
-#define DVB_FE_NORMAL_EXIT	1
-#define DVB_FE_DEVICE_REMOVED	2
-
-static DEFINE_MUTEX(frontend_mutex);
-
-struct dvb_frontend_private {
-
-	/* thread/frontend values */
-	struct dvb_device *dvbdev;
-	struct dvb_frontend_parameters parameters_out;
-	struct dvb_fe_events events;
-	struct semaphore sem;
-	struct list_head list_head;
-	wait_queue_head_t wait_queue;
-	struct task_struct *thread;
-	unsigned long release_jiffies;
-	unsigned int exit;
-	unsigned int wakeup;
-	fe_status_t status;
-	unsigned long tune_mode_flags;
-	unsigned int delay;
-	unsigned int reinitialise;
-	int tone;
-	int voltage;
-
-	/* swzigzag values */
-	unsigned int state;
-	unsigned int bending;
-	int lnb_drift;
-	unsigned int inversion;
-	unsigned int auto_step;
-	unsigned int auto_sub_step;
-	unsigned int started_auto_step;
-	unsigned int min_delay;
-	unsigned int max_drift;
-	unsigned int step_size;
-	int quality;
-	unsigned int check_wrapped;
-	enum dvbfe_search algo_status;
-};
-
-static void dvb_frontend_wakeup(struct dvb_frontend *fe);
-static int dtv_get_frontend(struct dvb_frontend *fe,
-			    struct dvb_frontend_parameters *p_out);
-static int dtv_property_legacy_params_sync(struct dvb_frontend *fe,
-					   struct dvb_frontend_parameters *p);
-
-static bool has_get_frontend(struct dvb_frontend *fe)
-{
-	return fe->ops.get_frontend != NULL;
-}
-
-/*
- * Due to DVBv3 API calls, a delivery system should be mapped into one of
- * the 4 DVBv3 delivery systems (FE_QPSK, FE_QAM, FE_OFDM or FE_ATSC),
- * otherwise, a DVBv3 call will fail.
- */
-enum dvbv3_emulation_type {
-	DVBV3_UNKNOWN,
-	DVBV3_QPSK,
-	DVBV3_QAM,
-	DVBV3_OFDM,
-	DVBV3_ATSC,
-};
-
-static enum dvbv3_emulation_type dvbv3_type(u32 delivery_system)
-{
-	switch (delivery_system) {
-	case SYS_DVBC_ANNEX_A:
-	case SYS_DVBC_ANNEX_C:
-		return DVBV3_QAM;
-	case SYS_DVBS:
-	case SYS_DVBS2:
-	case SYS_TURBO:
-	case SYS_ISDBS:
-	case SYS_DSS:
-		return DVBV3_QPSK;
-	case SYS_DVBT:
-	case SYS_DVBT2:
-	case SYS_ISDBT:
-	case SYS_DMBTH:
-		return DVBV3_OFDM;
-	case SYS_ATSC:
-	case SYS_ATSCMH:
-	case SYS_DVBC_ANNEX_B:
-		return DVBV3_ATSC;
-	case SYS_UNDEFINED:
-	case SYS_ISDBC:
-	case SYS_DVBH:
-	case SYS_DAB:
-	default:
-		/*
-		 * Doesn't know how to emulate those types and/or
-		 * there's no frontend driver from this type yet
-		 * with some emulation code, so, we're not sure yet how
-		 * to handle them, or they're not compatible with a DVBv3 call.
-		 */
-		return DVBV3_UNKNOWN;
-	}
-}
-
-static void dvb_frontend_add_event(struct dvb_frontend *fe, fe_status_t status)
-{
-	struct dvb_frontend_private *fepriv = fe->frontend_priv;
-	struct dvb_fe_events *events = &fepriv->events;
-	struct dvb_frontend_event *e;
-	int wp;
-
-	dprintk ("%s\n", __func__);
-
-	if ((status & FE_HAS_LOCK) && has_get_frontend(fe))
-		dtv_get_frontend(fe, &fepriv->parameters_out);
-
-	mutex_lock(&events->mtx);
-
-	wp = (events->eventw + 1) % MAX_EVENT;
-	if (wp == events->eventr) {
-		events->overflow = 1;
-		events->eventr = (events->eventr + 1) % MAX_EVENT;
-	}
-
-	e = &events->events[events->eventw];
-	e->status = status;
-	e->parameters = fepriv->parameters_out;
-
-	events->eventw = wp;
-
-	mutex_unlock(&events->mtx);
-
-	wake_up_interruptible (&events->wait_queue);
-}
-
-static int dvb_frontend_get_event(struct dvb_frontend *fe,
-			    struct dvb_frontend_event *event, int flags)
-{
-	struct dvb_frontend_private *fepriv = fe->frontend_priv;
-	struct dvb_fe_events *events = &fepriv->events;
-
-	dprintk ("%s\n", __func__);
-
-	if (events->overflow) {
-		events->overflow = 0;
-		return -EOVERFLOW;
-	}
-
-	if (events->eventw == events->eventr) {
-		int ret;
-
-		if (flags & O_NONBLOCK)
-			return -EWOULDBLOCK;
-
-		up(&fepriv->sem);
-
-		ret = wait_event_interruptible (events->wait_queue,
-						events->eventw != events->eventr);
-
-		if (down_interruptible (&fepriv->sem))
-			return -ERESTARTSYS;
-
-		if (ret < 0)
-			return ret;
-	}
-
-	mutex_lock(&events->mtx);
-	*event = events->events[events->eventr];
-	events->eventr = (events->eventr + 1) % MAX_EVENT;
-	mutex_unlock(&events->mtx);
-
-	return 0;
-}
-
-static void dvb_frontend_clear_events(struct dvb_frontend *fe)
-{
-	struct dvb_frontend_private *fepriv = fe->frontend_priv;
-	struct dvb_fe_events *events = &fepriv->events;
-
-	mutex_lock(&events->mtx);
-	events->eventr = events->eventw;
-	mutex_unlock(&events->mtx);
-}
-
-static void dvb_frontend_init(struct dvb_frontend *fe)
-{
-	dprintk ("DVB: initialising adapter %i frontend %i (%s)...\n",
-		 fe->dvb->num,
-		 fe->id,
-		 fe->ops.info.name);
-
-	if (fe->ops.init)
-		fe->ops.init(fe);
-	if (fe->ops.tuner_ops.init) {
-		if (fe->ops.i2c_gate_ctrl)
-			fe->ops.i2c_gate_ctrl(fe, 1);
-		fe->ops.tuner_ops.init(fe);
-		if (fe->ops.i2c_gate_ctrl)
-			fe->ops.i2c_gate_ctrl(fe, 0);
-	}
-}
-
-void dvb_frontend_reinitialise(struct dvb_frontend *fe)
-{
-	struct dvb_frontend_private *fepriv = fe->frontend_priv;
-
-	fepriv->reinitialise = 1;
-	dvb_frontend_wakeup(fe);
-}
-EXPORT_SYMBOL(dvb_frontend_reinitialise);
-
-static void dvb_frontend_swzigzag_update_delay(struct dvb_frontend_private *fepriv, int locked)
-{
-	int q2;
-
-	dprintk ("%s\n", __func__);
-
-	if (locked)
-		(fepriv->quality) = (fepriv->quality * 220 + 36*256) / 256;
-	else
-		(fepriv->quality) = (fepriv->quality * 220 + 0) / 256;
-
-	q2 = fepriv->quality - 128;
-	q2 *= q2;
-
-	fepriv->delay = fepriv->min_delay + q2 * HZ / (128*128);
-}
-
-/**
- * Performs automatic twiddling of frontend parameters.
- *
- * @param fe The frontend concerned.
- * @param check_wrapped Checks if an iteration has completed. DO NOT SET ON THE FIRST ATTEMPT
- * @returns Number of complete iterations that have been performed.
- */
-static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wrapped)
-{
-	int autoinversion;
-	int ready = 0;
-	int fe_set_err = 0;
-	struct dvb_frontend_private *fepriv = fe->frontend_priv;
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache, tmp;
-	int original_inversion = c->inversion;
-	u32 original_frequency = c->frequency;
-
-	/* are we using autoinversion? */
-	autoinversion = ((!(fe->ops.info.caps & FE_CAN_INVERSION_AUTO)) &&
-			 (c->inversion == INVERSION_AUTO));
-
-	/* setup parameters correctly */
-	while(!ready) {
-		/* calculate the lnb_drift */
-		fepriv->lnb_drift = fepriv->auto_step * fepriv->step_size;
-
-		/* wrap the auto_step if we've exceeded the maximum drift */
-		if (fepriv->lnb_drift > fepriv->max_drift) {
-			fepriv->auto_step = 0;
-			fepriv->auto_sub_step = 0;
-			fepriv->lnb_drift = 0;
-		}
-
-		/* perform inversion and +/- zigzag */
-		switch(fepriv->auto_sub_step) {
-		case 0:
-			/* try with the current inversion and current drift setting */
-			ready = 1;
-			break;
-
-		case 1:
-			if (!autoinversion) break;
-
-			fepriv->inversion = (fepriv->inversion == INVERSION_OFF) ? INVERSION_ON : INVERSION_OFF;
-			ready = 1;
-			break;
-
-		case 2:
-			if (fepriv->lnb_drift == 0) break;
-
-			fepriv->lnb_drift = -fepriv->lnb_drift;
-			ready = 1;
-			break;
-
-		case 3:
-			if (fepriv->lnb_drift == 0) break;
-			if (!autoinversion) break;
-
-			fepriv->inversion = (fepriv->inversion == INVERSION_OFF) ? INVERSION_ON : INVERSION_OFF;
-			fepriv->lnb_drift = -fepriv->lnb_drift;
-			ready = 1;
-			break;
-
-		default:
-			fepriv->auto_step++;
-			fepriv->auto_sub_step = -1; /* it'll be incremented to 0 in a moment */
-			break;
-		}
-
-		if (!ready) fepriv->auto_sub_step++;
-	}
-
-	/* if this attempt would hit where we started, indicate a complete
-	 * iteration has occurred */
-	if ((fepriv->auto_step == fepriv->started_auto_step) &&
-	    (fepriv->auto_sub_step == 0) && check_wrapped) {
-		return 1;
-	}
-
-	dprintk("%s: drift:%i inversion:%i auto_step:%i "
-		"auto_sub_step:%i started_auto_step:%i\n",
-		__func__, fepriv->lnb_drift, fepriv->inversion,
-		fepriv->auto_step, fepriv->auto_sub_step, fepriv->started_auto_step);
-
-	/* set the frontend itself */
-	c->frequency += fepriv->lnb_drift;
-	if (autoinversion)
-		c->inversion = fepriv->inversion;
-	tmp = *c;
-	if (fe->ops.set_frontend)
-		fe_set_err = fe->ops.set_frontend(fe);
-	*c = tmp;
-	if (fe_set_err < 0) {
-		fepriv->state = FESTATE_ERROR;
-		return fe_set_err;
-	}
-
-	c->frequency = original_frequency;
-	c->inversion = original_inversion;
-
-	fepriv->auto_sub_step++;
-	return 0;
-}
-
-static void dvb_frontend_swzigzag(struct dvb_frontend *fe)
-{
-	fe_status_t s = 0;
-	int retval = 0;
-	struct dvb_frontend_private *fepriv = fe->frontend_priv;
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache, tmp;
-
-	/* if we've got no parameters, just keep idling */
-	if (fepriv->state & FESTATE_IDLE) {
-		fepriv->delay = 3*HZ;
-		fepriv->quality = 0;
-		return;
-	}
-
-	/* in SCAN mode, we just set the frontend when asked and leave it alone */
-	if (fepriv->tune_mode_flags & FE_TUNE_MODE_ONESHOT) {
-		if (fepriv->state & FESTATE_RETUNE) {
-			tmp = *c;
-			if (fe->ops.set_frontend)
-				retval = fe->ops.set_frontend(fe);
-			*c = tmp;
-			if (retval < 0)
-				fepriv->state = FESTATE_ERROR;
-			else
-				fepriv->state = FESTATE_TUNED;
-		}
-		fepriv->delay = 3*HZ;
-		fepriv->quality = 0;
-		return;
-	}
-
-	/* get the frontend status */
-	if (fepriv->state & FESTATE_RETUNE) {
-		s = 0;
-	} else {
-		if (fe->ops.read_status)
-			fe->ops.read_status(fe, &s);
-		if (s != fepriv->status) {
-			dvb_frontend_add_event(fe, s);
-			fepriv->status = s;
-		}
-	}
-
-	/* if we're not tuned, and we have a lock, move to the TUNED state */
-	if ((fepriv->state & FESTATE_WAITFORLOCK) && (s & FE_HAS_LOCK)) {
-		dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK);
-		fepriv->state = FESTATE_TUNED;
-
-		/* if we're tuned, then we have determined the correct inversion */
-		if ((!(fe->ops.info.caps & FE_CAN_INVERSION_AUTO)) &&
-		    (c->inversion == INVERSION_AUTO)) {
-			c->inversion = fepriv->inversion;
-		}
-		return;
-	}
-
-	/* if we are tuned already, check we're still locked */
-	if (fepriv->state & FESTATE_TUNED) {
-		dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK);
-
-		/* we're tuned, and the lock is still good... */
-		if (s & FE_HAS_LOCK) {
-			return;
-		} else { /* if we _WERE_ tuned, but now don't have a lock */
-			fepriv->state = FESTATE_ZIGZAG_FAST;
-			fepriv->started_auto_step = fepriv->auto_step;
-			fepriv->check_wrapped = 0;
-		}
-	}
-
-	/* don't actually do anything if we're in the LOSTLOCK state,
-	 * the frontend is set to FE_CAN_RECOVER, and the max_drift is 0 */
-	if ((fepriv->state & FESTATE_LOSTLOCK) &&
-	    (fe->ops.info.caps & FE_CAN_RECOVER) && (fepriv->max_drift == 0)) {
-		dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK);
-		return;
-	}
-
-	/* don't do anything if we're in the DISEQC state, since this
-	 * might be someone with a motorized dish controlled by DISEQC.
-	 * If its actually a re-tune, there will be a SET_FRONTEND soon enough.	*/
-	if (fepriv->state & FESTATE_DISEQC) {
-		dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK);
-		return;
-	}
-
-	/* if we're in the RETUNE state, set everything up for a brand
-	 * new scan, keeping the current inversion setting, as the next
-	 * tune is _very_ likely to require the same */
-	if (fepriv->state & FESTATE_RETUNE) {
-		fepriv->lnb_drift = 0;
-		fepriv->auto_step = 0;
-		fepriv->auto_sub_step = 0;
-		fepriv->started_auto_step = 0;
-		fepriv->check_wrapped = 0;
-	}
-
-	/* fast zigzag. */
-	if ((fepriv->state & FESTATE_SEARCHING_FAST) || (fepriv->state & FESTATE_RETUNE)) {
-		fepriv->delay = fepriv->min_delay;
-
-		/* perform a tune */
-		retval = dvb_frontend_swzigzag_autotune(fe,
-							fepriv->check_wrapped);
-		if (retval < 0) {
-			return;
-		} else if (retval) {
-			/* OK, if we've run out of trials at the fast speed.
-			 * Drop back to slow for the _next_ attempt */
-			fepriv->state = FESTATE_SEARCHING_SLOW;
-			fepriv->started_auto_step = fepriv->auto_step;
-			return;
-		}
-		fepriv->check_wrapped = 1;
-
-		/* if we've just retuned, enter the ZIGZAG_FAST state.
-		 * This ensures we cannot return from an
-		 * FE_SET_FRONTEND ioctl before the first frontend tune
-		 * occurs */
-		if (fepriv->state & FESTATE_RETUNE) {
-			fepriv->state = FESTATE_TUNING_FAST;
-		}
-	}
-
-	/* slow zigzag */
-	if (fepriv->state & FESTATE_SEARCHING_SLOW) {
-		dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK);
-
-		/* Note: don't bother checking for wrapping; we stay in this
-		 * state until we get a lock */
-		dvb_frontend_swzigzag_autotune(fe, 0);
-	}
-}
-
-static int dvb_frontend_is_exiting(struct dvb_frontend *fe)
-{
-	struct dvb_frontend_private *fepriv = fe->frontend_priv;
-
-	if (fepriv->exit != DVB_FE_NO_EXIT)
-		return 1;
-
-	if (fepriv->dvbdev->writers == 1)
-		if (time_after_eq(jiffies, fepriv->release_jiffies +
-				  dvb_shutdown_timeout * HZ))
-			return 1;
-
-	return 0;
-}
-
-static int dvb_frontend_should_wakeup(struct dvb_frontend *fe)
-{
-	struct dvb_frontend_private *fepriv = fe->frontend_priv;
-
-	if (fepriv->wakeup) {
-		fepriv->wakeup = 0;
-		return 1;
-	}
-	return dvb_frontend_is_exiting(fe);
-}
-
-static void dvb_frontend_wakeup(struct dvb_frontend *fe)
-{
-	struct dvb_frontend_private *fepriv = fe->frontend_priv;
-
-	fepriv->wakeup = 1;
-	wake_up_interruptible(&fepriv->wait_queue);
-}
-
-static int dvb_frontend_thread(void *data)
-{
-	struct dvb_frontend *fe = data;
-	struct dvb_frontend_private *fepriv = fe->frontend_priv;
-	fe_status_t s;
-	enum dvbfe_algo algo;
-
-	bool re_tune = false;
-
-	dprintk("%s\n", __func__);
-
-	fepriv->check_wrapped = 0;
-	fepriv->quality = 0;
-	fepriv->delay = 3*HZ;
-	fepriv->status = 0;
-	fepriv->wakeup = 0;
-	fepriv->reinitialise = 0;
-
-	dvb_frontend_init(fe);
-
-	set_freezable();
-	while (1) {
-		up(&fepriv->sem);	    /* is locked when we enter the thread... */
-restart:
-		wait_event_interruptible_timeout(fepriv->wait_queue,
-			dvb_frontend_should_wakeup(fe) || kthread_should_stop()
-				|| freezing(current),
-			fepriv->delay);
-
-		if (kthread_should_stop() || dvb_frontend_is_exiting(fe)) {
-			/* got signal or quitting */
-			fepriv->exit = DVB_FE_NORMAL_EXIT;
-			break;
-		}
-
-		if (try_to_freeze())
-			goto restart;
-
-		if (down_interruptible(&fepriv->sem))
-			break;
-
-		if (fepriv->reinitialise) {
-			dvb_frontend_init(fe);
-			if (fe->ops.set_tone && fepriv->tone != -1)
-				fe->ops.set_tone(fe, fepriv->tone);
-			if (fe->ops.set_voltage && fepriv->voltage != -1)
-				fe->ops.set_voltage(fe, fepriv->voltage);
-			fepriv->reinitialise = 0;
-		}
-
-		/* do an iteration of the tuning loop */
-		if (fe->ops.get_frontend_algo) {
-			algo = fe->ops.get_frontend_algo(fe);
-			switch (algo) {
-			case DVBFE_ALGO_HW:
-				dprintk("%s: Frontend ALGO = DVBFE_ALGO_HW\n", __func__);
-
-				if (fepriv->state & FESTATE_RETUNE) {
-					dprintk("%s: Retune requested, FESTATE_RETUNE\n", __func__);
-					re_tune = true;
-					fepriv->state = FESTATE_TUNED;
-				} else {
-					re_tune = false;
-				}
-
-				if (fe->ops.tune)
-					fe->ops.tune(fe, re_tune, fepriv->tune_mode_flags, &fepriv->delay, &s);
-
-				if (s != fepriv->status && !(fepriv->tune_mode_flags & FE_TUNE_MODE_ONESHOT)) {
-					dprintk("%s: state changed, adding current state\n", __func__);
-					dvb_frontend_add_event(fe, s);
-					fepriv->status = s;
-				}
-				break;
-			case DVBFE_ALGO_SW:
-				dprintk("%s: Frontend ALGO = DVBFE_ALGO_SW\n", __func__);
-				dvb_frontend_swzigzag(fe);
-				break;
-			case DVBFE_ALGO_CUSTOM:
-				dprintk("%s: Frontend ALGO = DVBFE_ALGO_CUSTOM, state=%d\n", __func__, fepriv->state);
-				if (fepriv->state & FESTATE_RETUNE) {
-					dprintk("%s: Retune requested, FESTAT_RETUNE\n", __func__);
-					fepriv->state = FESTATE_TUNED;
-				}
-				/* Case where we are going to search for a carrier
-				 * User asked us to retune again for some reason, possibly
-				 * requesting a search with a new set of parameters
-				 */
-				if (fepriv->algo_status & DVBFE_ALGO_SEARCH_AGAIN) {
-					if (fe->ops.search) {
-						fepriv->algo_status = fe->ops.search(fe);
-						/* We did do a search as was requested, the flags are
-						 * now unset as well and has the flags wrt to search.
-						 */
-					} else {
-						fepriv->algo_status &= ~DVBFE_ALGO_SEARCH_AGAIN;
-					}
-				}
-				/* Track the carrier if the search was successful */
-				if (fepriv->algo_status != DVBFE_ALGO_SEARCH_SUCCESS) {
-					fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN;
-					fepriv->delay = HZ / 2;
-				}
-				dtv_property_legacy_params_sync(fe, &fepriv->parameters_out);
-				fe->ops.read_status(fe, &s);
-				if (s != fepriv->status) {
-					dvb_frontend_add_event(fe, s); /* update event list */
-					fepriv->status = s;
-					if (!(s & FE_HAS_LOCK)) {
-						fepriv->delay = HZ / 10;
-						fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN;
-					} else {
-						fepriv->delay = 60 * HZ;
-					}
-				}
-				break;
-			default:
-				dprintk("%s: UNDEFINED ALGO !\n", __func__);
-				break;
-			}
-		} else {
-			dvb_frontend_swzigzag(fe);
-		}
-	}
-
-	if (dvb_powerdown_on_sleep) {
-		if (fe->ops.set_voltage)
-			fe->ops.set_voltage(fe, SEC_VOLTAGE_OFF);
-		if (fe->ops.tuner_ops.sleep) {
-			if (fe->ops.i2c_gate_ctrl)
-				fe->ops.i2c_gate_ctrl(fe, 1);
-			fe->ops.tuner_ops.sleep(fe);
-			if (fe->ops.i2c_gate_ctrl)
-				fe->ops.i2c_gate_ctrl(fe, 0);
-		}
-		if (fe->ops.sleep)
-			fe->ops.sleep(fe);
-	}
-
-	fepriv->thread = NULL;
-	if (kthread_should_stop())
-		fepriv->exit = DVB_FE_DEVICE_REMOVED;
-	else
-		fepriv->exit = DVB_FE_NO_EXIT;
-	mb();
-
-	dvb_frontend_wakeup(fe);
-	return 0;
-}
-
-static void dvb_frontend_stop(struct dvb_frontend *fe)
-{
-	struct dvb_frontend_private *fepriv = fe->frontend_priv;
-
-	dprintk ("%s\n", __func__);
-
-	fepriv->exit = DVB_FE_NORMAL_EXIT;
-	mb();
-
-	if (!fepriv->thread)
-		return;
-
-	kthread_stop(fepriv->thread);
-
-	sema_init(&fepriv->sem, 1);
-	fepriv->state = FESTATE_IDLE;
-
-	/* paranoia check in case a signal arrived */
-	if (fepriv->thread)
-		printk("dvb_frontend_stop: warning: thread %p won't exit\n",
-				fepriv->thread);
-}
-
-s32 timeval_usec_diff(struct timeval lasttime, struct timeval curtime)
-{
-	return ((curtime.tv_usec < lasttime.tv_usec) ?
-		1000000 - lasttime.tv_usec + curtime.tv_usec :
-		curtime.tv_usec - lasttime.tv_usec);
-}
-EXPORT_SYMBOL(timeval_usec_diff);
-
-static inline void timeval_usec_add(struct timeval *curtime, u32 add_usec)
-{
-	curtime->tv_usec += add_usec;
-	if (curtime->tv_usec >= 1000000) {
-		curtime->tv_usec -= 1000000;
-		curtime->tv_sec++;
-	}
-}
-
-/*
- * Sleep until gettimeofday() > waketime + add_usec
- * This needs to be as precise as possible, but as the delay is
- * usually between 2ms and 32ms, it is done using a scheduled msleep
- * followed by usleep (normally a busy-wait loop) for the remainder
- */
-void dvb_frontend_sleep_until(struct timeval *waketime, u32 add_usec)
-{
-	struct timeval lasttime;
-	s32 delta, newdelta;
-
-	timeval_usec_add(waketime, add_usec);
-
-	do_gettimeofday(&lasttime);
-	delta = timeval_usec_diff(lasttime, *waketime);
-	if (delta > 2500) {
-		msleep((delta - 1500) / 1000);
-		do_gettimeofday(&lasttime);
-		newdelta = timeval_usec_diff(lasttime, *waketime);
-		delta = (newdelta > delta) ? 0 : newdelta;
-	}
-	if (delta > 0)
-		udelay(delta);
-}
-EXPORT_SYMBOL(dvb_frontend_sleep_until);
-
-static int dvb_frontend_start(struct dvb_frontend *fe)
-{
-	int ret;
-	struct dvb_frontend_private *fepriv = fe->frontend_priv;
-	struct task_struct *fe_thread;
-
-	dprintk ("%s\n", __func__);
-
-	if (fepriv->thread) {
-		if (fepriv->exit == DVB_FE_NO_EXIT)
-			return 0;
-		else
-			dvb_frontend_stop (fe);
-	}
-
-	if (signal_pending(current))
-		return -EINTR;
-	if (down_interruptible (&fepriv->sem))
-		return -EINTR;
-
-	fepriv->state = FESTATE_IDLE;
-	fepriv->exit = DVB_FE_NO_EXIT;
-	fepriv->thread = NULL;
-	mb();
-
-	fe_thread = kthread_run(dvb_frontend_thread, fe,
-		"kdvb-ad-%i-fe-%i", fe->dvb->num,fe->id);
-	if (IS_ERR(fe_thread)) {
-		ret = PTR_ERR(fe_thread);
-		printk("dvb_frontend_start: failed to start kthread (%d)\n", ret);
-		up(&fepriv->sem);
-		return ret;
-	}
-	fepriv->thread = fe_thread;
-	return 0;
-}
-
-static void dvb_frontend_get_frequency_limits(struct dvb_frontend *fe,
-					u32 *freq_min, u32 *freq_max)
-{
-	*freq_min = max(fe->ops.info.frequency_min, fe->ops.tuner_ops.info.frequency_min);
-
-	if (fe->ops.info.frequency_max == 0)
-		*freq_max = fe->ops.tuner_ops.info.frequency_max;
-	else if (fe->ops.tuner_ops.info.frequency_max == 0)
-		*freq_max = fe->ops.info.frequency_max;
-	else
-		*freq_max = min(fe->ops.info.frequency_max, fe->ops.tuner_ops.info.frequency_max);
-
-	if (*freq_min == 0 || *freq_max == 0)
-		printk(KERN_WARNING "DVB: adapter %i frontend %u frequency limits undefined - fix the driver\n",
-		       fe->dvb->num,fe->id);
-}
-
-static int dvb_frontend_check_parameters(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	u32 freq_min;
-	u32 freq_max;
-
-	/* range check: frequency */
-	dvb_frontend_get_frequency_limits(fe, &freq_min, &freq_max);
-	if ((freq_min && c->frequency < freq_min) ||
-	    (freq_max && c->frequency > freq_max)) {
-		printk(KERN_WARNING "DVB: adapter %i frontend %i frequency %u out of range (%u..%u)\n",
-		       fe->dvb->num, fe->id, c->frequency, freq_min, freq_max);
-		return -EINVAL;
-	}
-
-	/* range check: symbol rate */
-	switch (c->delivery_system) {
-	case SYS_DVBS:
-	case SYS_DVBS2:
-	case SYS_TURBO:
-	case SYS_DVBC_ANNEX_A:
-	case SYS_DVBC_ANNEX_C:
-		if ((fe->ops.info.symbol_rate_min &&
-		     c->symbol_rate < fe->ops.info.symbol_rate_min) ||
-		    (fe->ops.info.symbol_rate_max &&
-		     c->symbol_rate > fe->ops.info.symbol_rate_max)) {
-			printk(KERN_WARNING "DVB: adapter %i frontend %i symbol rate %u out of range (%u..%u)\n",
-			       fe->dvb->num, fe->id, c->symbol_rate,
-			       fe->ops.info.symbol_rate_min,
-			       fe->ops.info.symbol_rate_max);
-			return -EINVAL;
-		}
-	default:
-		break;
-	}
-
-	return 0;
-}
-
-static int dvb_frontend_clear_cache(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	int i;
-	u32 delsys;
-
-	delsys = c->delivery_system;
-	memset(c, 0, sizeof(struct dtv_frontend_properties));
-	c->delivery_system = delsys;
-
-	c->state = DTV_CLEAR;
-
-	dprintk("%s() Clearing cache for delivery system %d\n", __func__,
-		c->delivery_system);
-
-	c->transmission_mode = TRANSMISSION_MODE_AUTO;
-	c->bandwidth_hz = 0;	/* AUTO */
-	c->guard_interval = GUARD_INTERVAL_AUTO;
-	c->hierarchy = HIERARCHY_AUTO;
-	c->symbol_rate = 0;
-	c->code_rate_HP = FEC_AUTO;
-	c->code_rate_LP = FEC_AUTO;
-	c->fec_inner = FEC_AUTO;
-	c->rolloff = ROLLOFF_AUTO;
-	c->voltage = SEC_VOLTAGE_OFF;
-	c->sectone = SEC_TONE_OFF;
-	c->pilot = PILOT_AUTO;
-
-	c->isdbt_partial_reception = 0;
-	c->isdbt_sb_mode = 0;
-	c->isdbt_sb_subchannel = 0;
-	c->isdbt_sb_segment_idx = 0;
-	c->isdbt_sb_segment_count = 0;
-	c->isdbt_layer_enabled = 0;
-	for (i = 0; i < 3; i++) {
-		c->layer[i].fec = FEC_AUTO;
-		c->layer[i].modulation = QAM_AUTO;
-		c->layer[i].interleaving = 0;
-		c->layer[i].segment_count = 0;
-	}
-
-	c->isdbs_ts_id = 0;
-	c->dvbt2_plp_id = 0;
-
-	switch (c->delivery_system) {
-	case SYS_DVBS:
-	case SYS_DVBS2:
-	case SYS_TURBO:
-		c->modulation = QPSK;   /* implied for DVB-S in legacy API */
-		c->rolloff = ROLLOFF_35;/* implied for DVB-S */
-		break;
-	case SYS_ATSC:
-		c->modulation = VSB_8;
-		break;
-	default:
-		c->modulation = QAM_AUTO;
-		break;
-	}
-
-	return 0;
-}
-
-#define _DTV_CMD(n, s, b) \
-[n] = { \
-	.name = #n, \
-	.cmd  = n, \
-	.set  = s,\
-	.buffer = b \
-}
-
-static struct dtv_cmds_h dtv_cmds[DTV_MAX_COMMAND + 1] = {
-	_DTV_CMD(DTV_TUNE, 1, 0),
-	_DTV_CMD(DTV_CLEAR, 1, 0),
-
-	/* Set */
-	_DTV_CMD(DTV_FREQUENCY, 1, 0),
-	_DTV_CMD(DTV_BANDWIDTH_HZ, 1, 0),
-	_DTV_CMD(DTV_MODULATION, 1, 0),
-	_DTV_CMD(DTV_INVERSION, 1, 0),
-	_DTV_CMD(DTV_DISEQC_MASTER, 1, 1),
-	_DTV_CMD(DTV_SYMBOL_RATE, 1, 0),
-	_DTV_CMD(DTV_INNER_FEC, 1, 0),
-	_DTV_CMD(DTV_VOLTAGE, 1, 0),
-	_DTV_CMD(DTV_TONE, 1, 0),
-	_DTV_CMD(DTV_PILOT, 1, 0),
-	_DTV_CMD(DTV_ROLLOFF, 1, 0),
-	_DTV_CMD(DTV_DELIVERY_SYSTEM, 1, 0),
-	_DTV_CMD(DTV_HIERARCHY, 1, 0),
-	_DTV_CMD(DTV_CODE_RATE_HP, 1, 0),
-	_DTV_CMD(DTV_CODE_RATE_LP, 1, 0),
-	_DTV_CMD(DTV_GUARD_INTERVAL, 1, 0),
-	_DTV_CMD(DTV_TRANSMISSION_MODE, 1, 0),
-
-	_DTV_CMD(DTV_ISDBT_PARTIAL_RECEPTION, 1, 0),
-	_DTV_CMD(DTV_ISDBT_SOUND_BROADCASTING, 1, 0),
-	_DTV_CMD(DTV_ISDBT_SB_SUBCHANNEL_ID, 1, 0),
-	_DTV_CMD(DTV_ISDBT_SB_SEGMENT_IDX, 1, 0),
-	_DTV_CMD(DTV_ISDBT_SB_SEGMENT_COUNT, 1, 0),
-	_DTV_CMD(DTV_ISDBT_LAYER_ENABLED, 1, 0),
-	_DTV_CMD(DTV_ISDBT_LAYERA_FEC, 1, 0),
-	_DTV_CMD(DTV_ISDBT_LAYERA_MODULATION, 1, 0),
-	_DTV_CMD(DTV_ISDBT_LAYERA_SEGMENT_COUNT, 1, 0),
-	_DTV_CMD(DTV_ISDBT_LAYERA_TIME_INTERLEAVING, 1, 0),
-	_DTV_CMD(DTV_ISDBT_LAYERB_FEC, 1, 0),
-	_DTV_CMD(DTV_ISDBT_LAYERB_MODULATION, 1, 0),
-	_DTV_CMD(DTV_ISDBT_LAYERB_SEGMENT_COUNT, 1, 0),
-	_DTV_CMD(DTV_ISDBT_LAYERB_TIME_INTERLEAVING, 1, 0),
-	_DTV_CMD(DTV_ISDBT_LAYERC_FEC, 1, 0),
-	_DTV_CMD(DTV_ISDBT_LAYERC_MODULATION, 1, 0),
-	_DTV_CMD(DTV_ISDBT_LAYERC_SEGMENT_COUNT, 1, 0),
-	_DTV_CMD(DTV_ISDBT_LAYERC_TIME_INTERLEAVING, 1, 0),
-
-	_DTV_CMD(DTV_ISDBS_TS_ID, 1, 0),
-	_DTV_CMD(DTV_DVBT2_PLP_ID, 1, 0),
-
-	/* Get */
-	_DTV_CMD(DTV_DISEQC_SLAVE_REPLY, 0, 1),
-	_DTV_CMD(DTV_API_VERSION, 0, 0),
-	_DTV_CMD(DTV_CODE_RATE_HP, 0, 0),
-	_DTV_CMD(DTV_CODE_RATE_LP, 0, 0),
-	_DTV_CMD(DTV_GUARD_INTERVAL, 0, 0),
-	_DTV_CMD(DTV_TRANSMISSION_MODE, 0, 0),
-	_DTV_CMD(DTV_HIERARCHY, 0, 0),
-
-	_DTV_CMD(DTV_ENUM_DELSYS, 0, 0),
-
-	_DTV_CMD(DTV_ATSCMH_PARADE_ID, 1, 0),
-	_DTV_CMD(DTV_ATSCMH_RS_FRAME_ENSEMBLE, 1, 0),
-
-	_DTV_CMD(DTV_ATSCMH_FIC_VER, 0, 0),
-	_DTV_CMD(DTV_ATSCMH_PARADE_ID, 0, 0),
-	_DTV_CMD(DTV_ATSCMH_NOG, 0, 0),
-	_DTV_CMD(DTV_ATSCMH_TNOG, 0, 0),
-	_DTV_CMD(DTV_ATSCMH_SGN, 0, 0),
-	_DTV_CMD(DTV_ATSCMH_PRC, 0, 0),
-	_DTV_CMD(DTV_ATSCMH_RS_FRAME_MODE, 0, 0),
-	_DTV_CMD(DTV_ATSCMH_RS_FRAME_ENSEMBLE, 0, 0),
-	_DTV_CMD(DTV_ATSCMH_RS_CODE_MODE_PRI, 0, 0),
-	_DTV_CMD(DTV_ATSCMH_RS_CODE_MODE_SEC, 0, 0),
-	_DTV_CMD(DTV_ATSCMH_SCCC_BLOCK_MODE, 0, 0),
-	_DTV_CMD(DTV_ATSCMH_SCCC_CODE_MODE_A, 0, 0),
-	_DTV_CMD(DTV_ATSCMH_SCCC_CODE_MODE_B, 0, 0),
-	_DTV_CMD(DTV_ATSCMH_SCCC_CODE_MODE_C, 0, 0),
-	_DTV_CMD(DTV_ATSCMH_SCCC_CODE_MODE_D, 0, 0),
-};
-
-static void dtv_property_dump(struct dtv_property *tvp)
-{
-	int i;
-
-	if (tvp->cmd <= 0 || tvp->cmd > DTV_MAX_COMMAND) {
-		printk(KERN_WARNING "%s: tvp.cmd = 0x%08x undefined\n",
-			__func__, tvp->cmd);
-		return;
-	}
-
-	dprintk("%s() tvp.cmd    = 0x%08x (%s)\n"
-		,__func__
-		,tvp->cmd
-		,dtv_cmds[ tvp->cmd ].name);
-
-	if(dtv_cmds[ tvp->cmd ].buffer) {
-
-		dprintk("%s() tvp.u.buffer.len = 0x%02x\n"
-			,__func__
-			,tvp->u.buffer.len);
-
-		for(i = 0; i < tvp->u.buffer.len; i++)
-			dprintk("%s() tvp.u.buffer.data[0x%02x] = 0x%02x\n"
-				,__func__
-				,i
-				,tvp->u.buffer.data[i]);
-
-	} else
-		dprintk("%s() tvp.u.data = 0x%08x\n", __func__, tvp->u.data);
-}
-
-/* Synchronise the legacy tuning parameters into the cache, so that demodulator
- * drivers can use a single set_frontend tuning function, regardless of whether
- * it's being used for the legacy or new API, reducing code and complexity.
- */
-static int dtv_property_cache_sync(struct dvb_frontend *fe,
-				   struct dtv_frontend_properties *c,
-				   const struct dvb_frontend_parameters *p)
-{
-	c->frequency = p->frequency;
-	c->inversion = p->inversion;
-
-	switch (dvbv3_type(c->delivery_system)) {
-	case DVBV3_QPSK:
-		dprintk("%s() Preparing QPSK req\n", __func__);
-		c->symbol_rate = p->u.qpsk.symbol_rate;
-		c->fec_inner = p->u.qpsk.fec_inner;
-		break;
-	case DVBV3_QAM:
-		dprintk("%s() Preparing QAM req\n", __func__);
-		c->symbol_rate = p->u.qam.symbol_rate;
-		c->fec_inner = p->u.qam.fec_inner;
-		c->modulation = p->u.qam.modulation;
-		break;
-	case DVBV3_OFDM:
-		dprintk("%s() Preparing OFDM req\n", __func__);
-		switch (p->u.ofdm.bandwidth) {
-		case BANDWIDTH_10_MHZ:
-			c->bandwidth_hz = 10000000;
-			break;
-		case BANDWIDTH_8_MHZ:
-			c->bandwidth_hz = 8000000;
-			break;
-		case BANDWIDTH_7_MHZ:
-			c->bandwidth_hz = 7000000;
-			break;
-		case BANDWIDTH_6_MHZ:
-			c->bandwidth_hz = 6000000;
-			break;
-		case BANDWIDTH_5_MHZ:
-			c->bandwidth_hz = 5000000;
-			break;
-		case BANDWIDTH_1_712_MHZ:
-			c->bandwidth_hz = 1712000;
-			break;
-		case BANDWIDTH_AUTO:
-			c->bandwidth_hz = 0;
-		}
-
-		c->code_rate_HP = p->u.ofdm.code_rate_HP;
-		c->code_rate_LP = p->u.ofdm.code_rate_LP;
-		c->modulation = p->u.ofdm.constellation;
-		c->transmission_mode = p->u.ofdm.transmission_mode;
-		c->guard_interval = p->u.ofdm.guard_interval;
-		c->hierarchy = p->u.ofdm.hierarchy_information;
-		break;
-	case DVBV3_ATSC:
-		dprintk("%s() Preparing ATSC req\n", __func__);
-		c->modulation = p->u.vsb.modulation;
-		if (c->delivery_system == SYS_ATSCMH)
-			break;
-		if ((c->modulation == VSB_8) || (c->modulation == VSB_16))
-			c->delivery_system = SYS_ATSC;
-		else
-			c->delivery_system = SYS_DVBC_ANNEX_B;
-		break;
-	case DVBV3_UNKNOWN:
-		printk(KERN_ERR
-		       "%s: doesn't know how to handle a DVBv3 call to delivery system %i\n",
-		       __func__, c->delivery_system);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-/* Ensure the cached values are set correctly in the frontend
- * legacy tuning structures, for the advanced tuning API.
- */
-static int dtv_property_legacy_params_sync(struct dvb_frontend *fe,
-					    struct dvb_frontend_parameters *p)
-{
-	const struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-
-	p->frequency = c->frequency;
-	p->inversion = c->inversion;
-
-	switch (dvbv3_type(c->delivery_system)) {
-	case DVBV3_UNKNOWN:
-		printk(KERN_ERR
-		       "%s: doesn't know how to handle a DVBv3 call to delivery system %i\n",
-		       __func__, c->delivery_system);
-		return -EINVAL;
-	case DVBV3_QPSK:
-		dprintk("%s() Preparing QPSK req\n", __func__);
-		p->u.qpsk.symbol_rate = c->symbol_rate;
-		p->u.qpsk.fec_inner = c->fec_inner;
-		break;
-	case DVBV3_QAM:
-		dprintk("%s() Preparing QAM req\n", __func__);
-		p->u.qam.symbol_rate = c->symbol_rate;
-		p->u.qam.fec_inner = c->fec_inner;
-		p->u.qam.modulation = c->modulation;
-		break;
-	case DVBV3_OFDM:
-		dprintk("%s() Preparing OFDM req\n", __func__);
-
-		switch (c->bandwidth_hz) {
-		case 10000000:
-			p->u.ofdm.bandwidth = BANDWIDTH_10_MHZ;
-			break;
-		case 8000000:
-			p->u.ofdm.bandwidth = BANDWIDTH_8_MHZ;
-			break;
-		case 7000000:
-			p->u.ofdm.bandwidth = BANDWIDTH_7_MHZ;
-			break;
-		case 6000000:
-			p->u.ofdm.bandwidth = BANDWIDTH_6_MHZ;
-			break;
-		case 5000000:
-			p->u.ofdm.bandwidth = BANDWIDTH_5_MHZ;
-			break;
-		case 1712000:
-			p->u.ofdm.bandwidth = BANDWIDTH_1_712_MHZ;
-			break;
-		case 0:
-		default:
-			p->u.ofdm.bandwidth = BANDWIDTH_AUTO;
-		}
-		p->u.ofdm.code_rate_HP = c->code_rate_HP;
-		p->u.ofdm.code_rate_LP = c->code_rate_LP;
-		p->u.ofdm.constellation = c->modulation;
-		p->u.ofdm.transmission_mode = c->transmission_mode;
-		p->u.ofdm.guard_interval = c->guard_interval;
-		p->u.ofdm.hierarchy_information = c->hierarchy;
-		break;
-	case DVBV3_ATSC:
-		dprintk("%s() Preparing VSB req\n", __func__);
-		p->u.vsb.modulation = c->modulation;
-		break;
-	}
-	return 0;
-}
-
-/**
- * dtv_get_frontend - calls a callback for retrieving DTV parameters
- * @fe:		struct dvb_frontend pointer
- * @c:		struct dtv_frontend_properties pointer (DVBv5 cache)
- * @p_out	struct dvb_frontend_parameters pointer (DVBv3 FE struct)
- *
- * This routine calls either the DVBv3 or DVBv5 get_frontend call.
- * If c is not null, it will update the DVBv5 cache struct pointed by it.
- * If p_out is not null, it will update the DVBv3 params pointed by it.
- */
-static int dtv_get_frontend(struct dvb_frontend *fe,
-			    struct dvb_frontend_parameters *p_out)
-{
-	int r;
-
-	if (fe->ops.get_frontend) {
-		r = fe->ops.get_frontend(fe);
-		if (unlikely(r < 0))
-			return r;
-		if (p_out)
-			dtv_property_legacy_params_sync(fe, p_out);
-		return 0;
-	}
-
-	/* As everything is in cache, get_frontend fops are always supported */
-	return 0;
-}
-
-static int dvb_frontend_ioctl_legacy(struct file *file,
-			unsigned int cmd, void *parg);
-static int dvb_frontend_ioctl_properties(struct file *file,
-			unsigned int cmd, void *parg);
-
-static int dtv_property_process_get(struct dvb_frontend *fe,
-				    const struct dtv_frontend_properties *c,
-				    struct dtv_property *tvp,
-				    struct file *file)
-{
-	int r, ncaps;
-
-	switch(tvp->cmd) {
-	case DTV_ENUM_DELSYS:
-		ncaps = 0;
-		while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) {
-			tvp->u.buffer.data[ncaps] = fe->ops.delsys[ncaps];
-			ncaps++;
-		}
-		tvp->u.buffer.len = ncaps;
-		break;
-	case DTV_FREQUENCY:
-		tvp->u.data = c->frequency;
-		break;
-	case DTV_MODULATION:
-		tvp->u.data = c->modulation;
-		break;
-	case DTV_BANDWIDTH_HZ:
-		tvp->u.data = c->bandwidth_hz;
-		break;
-	case DTV_INVERSION:
-		tvp->u.data = c->inversion;
-		break;
-	case DTV_SYMBOL_RATE:
-		tvp->u.data = c->symbol_rate;
-		break;
-	case DTV_INNER_FEC:
-		tvp->u.data = c->fec_inner;
-		break;
-	case DTV_PILOT:
-		tvp->u.data = c->pilot;
-		break;
-	case DTV_ROLLOFF:
-		tvp->u.data = c->rolloff;
-		break;
-	case DTV_DELIVERY_SYSTEM:
-		tvp->u.data = c->delivery_system;
-		break;
-	case DTV_VOLTAGE:
-		tvp->u.data = c->voltage;
-		break;
-	case DTV_TONE:
-		tvp->u.data = c->sectone;
-		break;
-	case DTV_API_VERSION:
-		tvp->u.data = (DVB_API_VERSION << 8) | DVB_API_VERSION_MINOR;
-		break;
-	case DTV_CODE_RATE_HP:
-		tvp->u.data = c->code_rate_HP;
-		break;
-	case DTV_CODE_RATE_LP:
-		tvp->u.data = c->code_rate_LP;
-		break;
-	case DTV_GUARD_INTERVAL:
-		tvp->u.data = c->guard_interval;
-		break;
-	case DTV_TRANSMISSION_MODE:
-		tvp->u.data = c->transmission_mode;
-		break;
-	case DTV_HIERARCHY:
-		tvp->u.data = c->hierarchy;
-		break;
-
-	/* ISDB-T Support here */
-	case DTV_ISDBT_PARTIAL_RECEPTION:
-		tvp->u.data = c->isdbt_partial_reception;
-		break;
-	case DTV_ISDBT_SOUND_BROADCASTING:
-		tvp->u.data = c->isdbt_sb_mode;
-		break;
-	case DTV_ISDBT_SB_SUBCHANNEL_ID:
-		tvp->u.data = c->isdbt_sb_subchannel;
-		break;
-	case DTV_ISDBT_SB_SEGMENT_IDX:
-		tvp->u.data = c->isdbt_sb_segment_idx;
-		break;
-	case DTV_ISDBT_SB_SEGMENT_COUNT:
-		tvp->u.data = c->isdbt_sb_segment_count;
-		break;
-	case DTV_ISDBT_LAYER_ENABLED:
-		tvp->u.data = c->isdbt_layer_enabled;
-		break;
-	case DTV_ISDBT_LAYERA_FEC:
-		tvp->u.data = c->layer[0].fec;
-		break;
-	case DTV_ISDBT_LAYERA_MODULATION:
-		tvp->u.data = c->layer[0].modulation;
-		break;
-	case DTV_ISDBT_LAYERA_SEGMENT_COUNT:
-		tvp->u.data = c->layer[0].segment_count;
-		break;
-	case DTV_ISDBT_LAYERA_TIME_INTERLEAVING:
-		tvp->u.data = c->layer[0].interleaving;
-		break;
-	case DTV_ISDBT_LAYERB_FEC:
-		tvp->u.data = c->layer[1].fec;
-		break;
-	case DTV_ISDBT_LAYERB_MODULATION:
-		tvp->u.data = c->layer[1].modulation;
-		break;
-	case DTV_ISDBT_LAYERB_SEGMENT_COUNT:
-		tvp->u.data = c->layer[1].segment_count;
-		break;
-	case DTV_ISDBT_LAYERB_TIME_INTERLEAVING:
-		tvp->u.data = c->layer[1].interleaving;
-		break;
-	case DTV_ISDBT_LAYERC_FEC:
-		tvp->u.data = c->layer[2].fec;
-		break;
-	case DTV_ISDBT_LAYERC_MODULATION:
-		tvp->u.data = c->layer[2].modulation;
-		break;
-	case DTV_ISDBT_LAYERC_SEGMENT_COUNT:
-		tvp->u.data = c->layer[2].segment_count;
-		break;
-	case DTV_ISDBT_LAYERC_TIME_INTERLEAVING:
-		tvp->u.data = c->layer[2].interleaving;
-		break;
-	case DTV_ISDBS_TS_ID:
-		tvp->u.data = c->isdbs_ts_id;
-		break;
-	case DTV_DVBT2_PLP_ID:
-		tvp->u.data = c->dvbt2_plp_id;
-		break;
-
-	/* ATSC-MH */
-	case DTV_ATSCMH_FIC_VER:
-		tvp->u.data = fe->dtv_property_cache.atscmh_fic_ver;
-		break;
-	case DTV_ATSCMH_PARADE_ID:
-		tvp->u.data = fe->dtv_property_cache.atscmh_parade_id;
-		break;
-	case DTV_ATSCMH_NOG:
-		tvp->u.data = fe->dtv_property_cache.atscmh_nog;
-		break;
-	case DTV_ATSCMH_TNOG:
-		tvp->u.data = fe->dtv_property_cache.atscmh_tnog;
-		break;
-	case DTV_ATSCMH_SGN:
-		tvp->u.data = fe->dtv_property_cache.atscmh_sgn;
-		break;
-	case DTV_ATSCMH_PRC:
-		tvp->u.data = fe->dtv_property_cache.atscmh_prc;
-		break;
-	case DTV_ATSCMH_RS_FRAME_MODE:
-		tvp->u.data = fe->dtv_property_cache.atscmh_rs_frame_mode;
-		break;
-	case DTV_ATSCMH_RS_FRAME_ENSEMBLE:
-		tvp->u.data = fe->dtv_property_cache.atscmh_rs_frame_ensemble;
-		break;
-	case DTV_ATSCMH_RS_CODE_MODE_PRI:
-		tvp->u.data = fe->dtv_property_cache.atscmh_rs_code_mode_pri;
-		break;
-	case DTV_ATSCMH_RS_CODE_MODE_SEC:
-		tvp->u.data = fe->dtv_property_cache.atscmh_rs_code_mode_sec;
-		break;
-	case DTV_ATSCMH_SCCC_BLOCK_MODE:
-		tvp->u.data = fe->dtv_property_cache.atscmh_sccc_block_mode;
-		break;
-	case DTV_ATSCMH_SCCC_CODE_MODE_A:
-		tvp->u.data = fe->dtv_property_cache.atscmh_sccc_code_mode_a;
-		break;
-	case DTV_ATSCMH_SCCC_CODE_MODE_B:
-		tvp->u.data = fe->dtv_property_cache.atscmh_sccc_code_mode_b;
-		break;
-	case DTV_ATSCMH_SCCC_CODE_MODE_C:
-		tvp->u.data = fe->dtv_property_cache.atscmh_sccc_code_mode_c;
-		break;
-	case DTV_ATSCMH_SCCC_CODE_MODE_D:
-		tvp->u.data = fe->dtv_property_cache.atscmh_sccc_code_mode_d;
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	/* Allow the frontend to override outgoing properties */
-	if (fe->ops.get_property) {
-		r = fe->ops.get_property(fe, tvp);
-		if (r < 0)
-			return r;
-	}
-
-	dtv_property_dump(tvp);
-
-	return 0;
-}
-
-static int dtv_set_frontend(struct dvb_frontend *fe);
-
-static bool is_dvbv3_delsys(u32 delsys)
-{
-	bool status;
-
-	status = (delsys == SYS_DVBT) || (delsys == SYS_DVBC_ANNEX_A) ||
-		 (delsys == SYS_DVBS) || (delsys == SYS_ATSC);
-
-	return status;
-}
-
-static int set_delivery_system(struct dvb_frontend *fe, u32 desired_system)
-{
-	int ncaps, i;
-	u32 delsys = SYS_UNDEFINED;
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	enum dvbv3_emulation_type type;
-
-	/*
-	 * It was reported that some old DVBv5 applications were
-	 * filling delivery_system with SYS_UNDEFINED. If this happens,
-	 * assume that the application wants to use the first supported
-	 * delivery system.
-	 */
-	if (c->delivery_system == SYS_UNDEFINED)
-	        c->delivery_system = fe->ops.delsys[0];
-
-	if (desired_system == SYS_UNDEFINED) {
-		/*
-		 * A DVBv3 call doesn't know what's the desired system.
-		 * Also, DVBv3 applications don't know that ops.info->type
-		 * could be changed, and they simply dies when it doesn't
-		 * match.
-		 * So, don't change the current delivery system, as it
-		 * may be trying to do the wrong thing, like setting an
-		 * ISDB-T frontend as DVB-T. Instead, find the closest
-		 * DVBv3 system that matches the delivery system.
-		 */
-		if (is_dvbv3_delsys(c->delivery_system)) {
-			dprintk("%s() Using delivery system to %d\n",
-				__func__, c->delivery_system);
-			return 0;
-		}
-		type = dvbv3_type(c->delivery_system);
-		switch (type) {
-		case DVBV3_QPSK:
-			desired_system = SYS_DVBS;
-			break;
-		case DVBV3_QAM:
-			desired_system = SYS_DVBC_ANNEX_A;
-			break;
-		case DVBV3_ATSC:
-			desired_system = SYS_ATSC;
-			break;
-		case DVBV3_OFDM:
-			desired_system = SYS_DVBT;
-			break;
-		default:
-			dprintk("%s(): This frontend doesn't support DVBv3 calls\n",
-				__func__);
-			return -EINVAL;
-		}
-		/*
-		 * Get a delivery system that is compatible with DVBv3
-		 * NOTE: in order for this to work with softwares like Kaffeine that
-		 *	uses a DVBv5 call for DVB-S2 and a DVBv3 call to go back to
-		 *	DVB-S, drivers that support both should put the SYS_DVBS entry
-		 *	before the SYS_DVBS2, otherwise it won't switch back to DVB-S.
-		 *	The real fix is that userspace applications should not use DVBv3
-		 *	and not trust on calling FE_SET_FRONTEND to switch the delivery
-		 *	system.
-		 */
-		ncaps = 0;
-		while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) {
-			if (fe->ops.delsys[ncaps] == desired_system) {
-				delsys = desired_system;
-				break;
-			}
-			ncaps++;
-		}
-		if (delsys == SYS_UNDEFINED) {
-			dprintk("%s() Couldn't find a delivery system that matches %d\n",
-				__func__, desired_system);
-		}
-	} else {
-		/*
-		 * This is a DVBv5 call. So, it likely knows the supported
-		 * delivery systems.
-		 */
-
-		/* Check if the desired delivery system is supported */
-		ncaps = 0;
-		while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) {
-			if (fe->ops.delsys[ncaps] == desired_system) {
-				c->delivery_system = desired_system;
-				dprintk("%s() Changing delivery system to %d\n",
-					__func__, desired_system);
-				return 0;
-			}
-			ncaps++;
-		}
-		type = dvbv3_type(desired_system);
-
-		/*
-		 * The delivery system is not supported. See if it can be
-		 * emulated.
-		 * The emulation only works if the desired system is one of the
-		 * DVBv3 delivery systems
-		 */
-		if (!is_dvbv3_delsys(desired_system)) {
-			dprintk("%s() can't use a DVBv3 FE_SET_FRONTEND call on this frontend\n",
-				__func__);
-			return -EINVAL;
-		}
-
-		/*
-		 * Get the last non-DVBv3 delivery system that has the same type
-		 * of the desired system
-		 */
-		ncaps = 0;
-		while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) {
-			if ((dvbv3_type(fe->ops.delsys[ncaps]) == type) &&
-			    !is_dvbv3_delsys(fe->ops.delsys[ncaps]))
-				delsys = fe->ops.delsys[ncaps];
-			ncaps++;
-		}
-		/* There's nothing compatible with the desired delivery system */
-		if (delsys == SYS_UNDEFINED) {
-			dprintk("%s() Incompatible DVBv3 FE_SET_FRONTEND call for this frontend\n",
-				__func__);
-			return -EINVAL;
-		}
-	}
-
-	c->delivery_system = delsys;
-
-	/*
-	 * The DVBv3 or DVBv5 call is requesting a different system. So,
-	 * emulation is needed.
-	 *
-	 * Emulate newer delivery systems like ISDBT, DVBT and DMBTH
-	 * for older DVBv5 applications. The emulation will try to use
-	 * the auto mode for most things, and will assume that the desired
-	 * delivery system is the last one at the ops.delsys[] array
-	 */
-	dprintk("%s() Using delivery system %d emulated as if it were a %d\n",
-		__func__, delsys, desired_system);
-
-	/*
-	 * For now, handles ISDB-T calls. More code may be needed here for the
-	 * other emulated stuff
-	 */
-	if (type == DVBV3_OFDM) {
-		if (c->delivery_system == SYS_ISDBT) {
-			dprintk("%s() Using defaults for SYS_ISDBT\n",
-				__func__);
-			if (!c->bandwidth_hz)
-				c->bandwidth_hz = 6000000;
-
-			c->isdbt_partial_reception = 0;
-			c->isdbt_sb_mode = 0;
-			c->isdbt_sb_subchannel = 0;
-			c->isdbt_sb_segment_idx = 0;
-			c->isdbt_sb_segment_count = 0;
-			c->isdbt_layer_enabled = 0;
-			for (i = 0; i < 3; i++) {
-				c->layer[i].fec = FEC_AUTO;
-				c->layer[i].modulation = QAM_AUTO;
-				c->layer[i].interleaving = 0;
-				c->layer[i].segment_count = 0;
-			}
-		}
-	}
-	dprintk("change delivery system on cache to %d\n", c->delivery_system);
-
-	return 0;
-}
-
-static int dtv_property_process_set(struct dvb_frontend *fe,
-				    struct dtv_property *tvp,
-				    struct file *file)
-{
-	int r = 0;
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-
-	/* Allow the frontend to validate incoming properties */
-	if (fe->ops.set_property) {
-		r = fe->ops.set_property(fe, tvp);
-		if (r < 0)
-			return r;
-	}
-
-	switch(tvp->cmd) {
-	case DTV_CLEAR:
-		/*
-		 * Reset a cache of data specific to the frontend here. This does
-		 * not effect hardware.
-		 */
-		dvb_frontend_clear_cache(fe);
-		break;
-	case DTV_TUNE:
-		/* interpret the cache of data, build either a traditional frontend
-		 * tunerequest so we can pass validation in the FE_SET_FRONTEND
-		 * ioctl.
-		 */
-		c->state = tvp->cmd;
-		dprintk("%s() Finalised property cache\n", __func__);
-
-		r = dtv_set_frontend(fe);
-		break;
-	case DTV_FREQUENCY:
-		c->frequency = tvp->u.data;
-		break;
-	case DTV_MODULATION:
-		c->modulation = tvp->u.data;
-		break;
-	case DTV_BANDWIDTH_HZ:
-		c->bandwidth_hz = tvp->u.data;
-		break;
-	case DTV_INVERSION:
-		c->inversion = tvp->u.data;
-		break;
-	case DTV_SYMBOL_RATE:
-		c->symbol_rate = tvp->u.data;
-		break;
-	case DTV_INNER_FEC:
-		c->fec_inner = tvp->u.data;
-		break;
-	case DTV_PILOT:
-		c->pilot = tvp->u.data;
-		break;
-	case DTV_ROLLOFF:
-		c->rolloff = tvp->u.data;
-		break;
-	case DTV_DELIVERY_SYSTEM:
-		r = set_delivery_system(fe, tvp->u.data);
-		break;
-	case DTV_VOLTAGE:
-		c->voltage = tvp->u.data;
-		r = dvb_frontend_ioctl_legacy(file, FE_SET_VOLTAGE,
-			(void *)c->voltage);
-		break;
-	case DTV_TONE:
-		c->sectone = tvp->u.data;
-		r = dvb_frontend_ioctl_legacy(file, FE_SET_TONE,
-			(void *)c->sectone);
-		break;
-	case DTV_CODE_RATE_HP:
-		c->code_rate_HP = tvp->u.data;
-		break;
-	case DTV_CODE_RATE_LP:
-		c->code_rate_LP = tvp->u.data;
-		break;
-	case DTV_GUARD_INTERVAL:
-		c->guard_interval = tvp->u.data;
-		break;
-	case DTV_TRANSMISSION_MODE:
-		c->transmission_mode = tvp->u.data;
-		break;
-	case DTV_HIERARCHY:
-		c->hierarchy = tvp->u.data;
-		break;
-
-	/* ISDB-T Support here */
-	case DTV_ISDBT_PARTIAL_RECEPTION:
-		c->isdbt_partial_reception = tvp->u.data;
-		break;
-	case DTV_ISDBT_SOUND_BROADCASTING:
-		c->isdbt_sb_mode = tvp->u.data;
-		break;
-	case DTV_ISDBT_SB_SUBCHANNEL_ID:
-		c->isdbt_sb_subchannel = tvp->u.data;
-		break;
-	case DTV_ISDBT_SB_SEGMENT_IDX:
-		c->isdbt_sb_segment_idx = tvp->u.data;
-		break;
-	case DTV_ISDBT_SB_SEGMENT_COUNT:
-		c->isdbt_sb_segment_count = tvp->u.data;
-		break;
-	case DTV_ISDBT_LAYER_ENABLED:
-		c->isdbt_layer_enabled = tvp->u.data;
-		break;
-	case DTV_ISDBT_LAYERA_FEC:
-		c->layer[0].fec = tvp->u.data;
-		break;
-	case DTV_ISDBT_LAYERA_MODULATION:
-		c->layer[0].modulation = tvp->u.data;
-		break;
-	case DTV_ISDBT_LAYERA_SEGMENT_COUNT:
-		c->layer[0].segment_count = tvp->u.data;
-		break;
-	case DTV_ISDBT_LAYERA_TIME_INTERLEAVING:
-		c->layer[0].interleaving = tvp->u.data;
-		break;
-	case DTV_ISDBT_LAYERB_FEC:
-		c->layer[1].fec = tvp->u.data;
-		break;
-	case DTV_ISDBT_LAYERB_MODULATION:
-		c->layer[1].modulation = tvp->u.data;
-		break;
-	case DTV_ISDBT_LAYERB_SEGMENT_COUNT:
-		c->layer[1].segment_count = tvp->u.data;
-		break;
-	case DTV_ISDBT_LAYERB_TIME_INTERLEAVING:
-		c->layer[1].interleaving = tvp->u.data;
-		break;
-	case DTV_ISDBT_LAYERC_FEC:
-		c->layer[2].fec = tvp->u.data;
-		break;
-	case DTV_ISDBT_LAYERC_MODULATION:
-		c->layer[2].modulation = tvp->u.data;
-		break;
-	case DTV_ISDBT_LAYERC_SEGMENT_COUNT:
-		c->layer[2].segment_count = tvp->u.data;
-		break;
-	case DTV_ISDBT_LAYERC_TIME_INTERLEAVING:
-		c->layer[2].interleaving = tvp->u.data;
-		break;
-	case DTV_ISDBS_TS_ID:
-		c->isdbs_ts_id = tvp->u.data;
-		break;
-	case DTV_DVBT2_PLP_ID:
-		c->dvbt2_plp_id = tvp->u.data;
-		break;
-
-	/* ATSC-MH */
-	case DTV_ATSCMH_PARADE_ID:
-		fe->dtv_property_cache.atscmh_parade_id = tvp->u.data;
-		break;
-	case DTV_ATSCMH_RS_FRAME_ENSEMBLE:
-		fe->dtv_property_cache.atscmh_rs_frame_ensemble = tvp->u.data;
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	return r;
-}
-
-static int dvb_frontend_ioctl(struct file *file,
-			unsigned int cmd, void *parg)
-{
-	struct dvb_device *dvbdev = file->private_data;
-	struct dvb_frontend *fe = dvbdev->priv;
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	struct dvb_frontend_private *fepriv = fe->frontend_priv;
-	int err = -EOPNOTSUPP;
-
-	dprintk("%s (%d)\n", __func__, _IOC_NR(cmd));
-
-	if (fepriv->exit != DVB_FE_NO_EXIT)
-		return -ENODEV;
-
-	if ((file->f_flags & O_ACCMODE) == O_RDONLY &&
-	    (_IOC_DIR(cmd) != _IOC_READ || cmd == FE_GET_EVENT ||
-	     cmd == FE_DISEQC_RECV_SLAVE_REPLY))
-		return -EPERM;
-
-	if (down_interruptible (&fepriv->sem))
-		return -ERESTARTSYS;
-
-	if ((cmd == FE_SET_PROPERTY) || (cmd == FE_GET_PROPERTY))
-		err = dvb_frontend_ioctl_properties(file, cmd, parg);
-	else {
-		c->state = DTV_UNDEFINED;
-		err = dvb_frontend_ioctl_legacy(file, cmd, parg);
-	}
-
-	up(&fepriv->sem);
-	return err;
-}
-
-static int dvb_frontend_ioctl_properties(struct file *file,
-			unsigned int cmd, void *parg)
-{
-	struct dvb_device *dvbdev = file->private_data;
-	struct dvb_frontend *fe = dvbdev->priv;
-	struct dvb_frontend_private *fepriv = fe->frontend_priv;
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	int err = 0;
-
-	struct dtv_properties *tvps = NULL;
-	struct dtv_property *tvp = NULL;
-	int i;
-
-	dprintk("%s\n", __func__);
-
-	if(cmd == FE_SET_PROPERTY) {
-		tvps = (struct dtv_properties __user *)parg;
-
-		dprintk("%s() properties.num = %d\n", __func__, tvps->num);
-		dprintk("%s() properties.props = %p\n", __func__, tvps->props);
-
-		/* Put an arbitrary limit on the number of messages that can
-		 * be sent at once */
-		if ((tvps->num == 0) || (tvps->num > DTV_IOCTL_MAX_MSGS))
-			return -EINVAL;
-
-		tvp = kmalloc(tvps->num * sizeof(struct dtv_property), GFP_KERNEL);
-		if (!tvp) {
-			err = -ENOMEM;
-			goto out;
-		}
-
-		if (copy_from_user(tvp, tvps->props, tvps->num * sizeof(struct dtv_property))) {
-			err = -EFAULT;
-			goto out;
-		}
-
-		for (i = 0; i < tvps->num; i++) {
-			err = dtv_property_process_set(fe, tvp + i, file);
-			if (err < 0)
-				goto out;
-			(tvp + i)->result = err;
-		}
-
-		if (c->state == DTV_TUNE)
-			dprintk("%s() Property cache is full, tuning\n", __func__);
-
-	} else
-	if(cmd == FE_GET_PROPERTY) {
-		tvps = (struct dtv_properties __user *)parg;
-
-		dprintk("%s() properties.num = %d\n", __func__, tvps->num);
-		dprintk("%s() properties.props = %p\n", __func__, tvps->props);
-
-		/* Put an arbitrary limit on the number of messages that can
-		 * be sent at once */
-		if ((tvps->num == 0) || (tvps->num > DTV_IOCTL_MAX_MSGS))
-			return -EINVAL;
-
-		tvp = kmalloc(tvps->num * sizeof(struct dtv_property), GFP_KERNEL);
-		if (!tvp) {
-			err = -ENOMEM;
-			goto out;
-		}
-
-		if (copy_from_user(tvp, tvps->props, tvps->num * sizeof(struct dtv_property))) {
-			err = -EFAULT;
-			goto out;
-		}
-
-		/*
-		 * Fills the cache out struct with the cache contents, plus
-		 * the data retrieved from get_frontend, if the frontend
-		 * is not idle. Otherwise, returns the cached content
-		 */
-		if (fepriv->state != FESTATE_IDLE) {
-			err = dtv_get_frontend(fe, NULL);
-			if (err < 0)
-				goto out;
-		}
-		for (i = 0; i < tvps->num; i++) {
-			err = dtv_property_process_get(fe, c, tvp + i, file);
-			if (err < 0)
-				goto out;
-			(tvp + i)->result = err;
-		}
-
-		if (copy_to_user(tvps->props, tvp, tvps->num * sizeof(struct dtv_property))) {
-			err = -EFAULT;
-			goto out;
-		}
-
-	} else
-		err = -EOPNOTSUPP;
-
-out:
-	kfree(tvp);
-	return err;
-}
-
-static int dtv_set_frontend(struct dvb_frontend *fe)
-{
-	struct dvb_frontend_private *fepriv = fe->frontend_priv;
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	struct dvb_frontend_tune_settings fetunesettings;
-	u32 rolloff = 0;
-
-	if (dvb_frontend_check_parameters(fe) < 0)
-		return -EINVAL;
-
-	/*
-	 * Initialize output parameters to match the values given by
-	 * the user. FE_SET_FRONTEND triggers an initial frontend event
-	 * with status = 0, which copies output parameters to userspace.
-	 */
-	dtv_property_legacy_params_sync(fe, &fepriv->parameters_out);
-
-	/*
-	 * Be sure that the bandwidth will be filled for all
-	 * non-satellite systems, as tuners need to know what
-	 * low pass/Nyquist half filter should be applied, in
-	 * order to avoid inter-channel noise.
-	 *
-	 * ISDB-T and DVB-T/T2 already sets bandwidth.
-	 * ATSC and DVB-C don't set, so, the core should fill it.
-	 *
-	 * On DVB-C Annex A and C, the bandwidth is a function of
-	 * the roll-off and symbol rate. Annex B defines different
-	 * roll-off factors depending on the modulation. Fortunately,
-	 * Annex B is only used with 6MHz, so there's no need to
-	 * calculate it.
-	 *
-	 * While not officially supported, a side effect of handling it at
-	 * the cache level is that a program could retrieve the bandwidth
-	 * via DTV_BANDWIDTH_HZ, which may be useful for test programs.
-	 */
-	switch (c->delivery_system) {
-	case SYS_ATSC:
-	case SYS_DVBC_ANNEX_B:
-		c->bandwidth_hz = 6000000;
-		break;
-	case SYS_DVBC_ANNEX_A:
-		rolloff = 115;
-		break;
-	case SYS_DVBC_ANNEX_C:
-		rolloff = 113;
-		break;
-	default:
-		break;
-	}
-	if (rolloff)
-		c->bandwidth_hz = (c->symbol_rate * rolloff) / 100;
-
-	/* force auto frequency inversion if requested */
-	if (dvb_force_auto_inversion)
-		c->inversion = INVERSION_AUTO;
-
-	/*
-	 * without hierarchical coding code_rate_LP is irrelevant,
-	 * so we tolerate the otherwise invalid FEC_NONE setting
-	 */
-	if (c->hierarchy == HIERARCHY_NONE && c->code_rate_LP == FEC_NONE)
-		c->code_rate_LP = FEC_AUTO;
-
-	/* get frontend-specific tuning settings */
-	memset(&fetunesettings, 0, sizeof(struct dvb_frontend_tune_settings));
-	if (fe->ops.get_tune_settings && (fe->ops.get_tune_settings(fe, &fetunesettings) == 0)) {
-		fepriv->min_delay = (fetunesettings.min_delay_ms * HZ) / 1000;
-		fepriv->max_drift = fetunesettings.max_drift;
-		fepriv->step_size = fetunesettings.step_size;
-	} else {
-		/* default values */
-		switch (c->delivery_system) {
-		case SYS_DVBS:
-		case SYS_DVBS2:
-		case SYS_ISDBS:
-		case SYS_TURBO:
-		case SYS_DVBC_ANNEX_A:
-		case SYS_DVBC_ANNEX_C:
-			fepriv->min_delay = HZ / 20;
-			fepriv->step_size = c->symbol_rate / 16000;
-			fepriv->max_drift = c->symbol_rate / 2000;
-			break;
-		case SYS_DVBT:
-		case SYS_DVBT2:
-		case SYS_ISDBT:
-		case SYS_DMBTH:
-			fepriv->min_delay = HZ / 20;
-			fepriv->step_size = fe->ops.info.frequency_stepsize * 2;
-			fepriv->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1;
-			break;
-		default:
-			/*
-			 * FIXME: This sounds wrong! if freqency_stepsize is
-			 * defined by the frontend, why not use it???
-			 */
-			fepriv->min_delay = HZ / 20;
-			fepriv->step_size = 0; /* no zigzag */
-			fepriv->max_drift = 0;
-			break;
-		}
-	}
-	if (dvb_override_tune_delay > 0)
-		fepriv->min_delay = (dvb_override_tune_delay * HZ) / 1000;
-
-	fepriv->state = FESTATE_RETUNE;
-
-	/* Request the search algorithm to search */
-	fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN;
-
-	dvb_frontend_clear_events(fe);
-	dvb_frontend_add_event(fe, 0);
-	dvb_frontend_wakeup(fe);
-	fepriv->status = 0;
-
-	return 0;
-}
-
-
-static int dvb_frontend_ioctl_legacy(struct file *file,
-			unsigned int cmd, void *parg)
-{
-	struct dvb_device *dvbdev = file->private_data;
-	struct dvb_frontend *fe = dvbdev->priv;
-	struct dvb_frontend_private *fepriv = fe->frontend_priv;
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	int cb_err, err = -EOPNOTSUPP;
-
-	if (fe->dvb->fe_ioctl_override) {
-		cb_err = fe->dvb->fe_ioctl_override(fe, cmd, parg,
-						    DVB_FE_IOCTL_PRE);
-		if (cb_err < 0)
-			return cb_err;
-		if (cb_err > 0)
-			return 0;
-		/* fe_ioctl_override returning 0 allows
-		 * dvb-core to continue handling the ioctl */
-	}
-
-	switch (cmd) {
-	case FE_GET_INFO: {
-		struct dvb_frontend_info* info = parg;
-
-		memcpy(info, &fe->ops.info, sizeof(struct dvb_frontend_info));
-		dvb_frontend_get_frequency_limits(fe, &info->frequency_min, &info->frequency_max);
-
-		/*
-		 * Associate the 4 delivery systems supported by DVBv3
-		 * API with their DVBv5 counterpart. For the other standards,
-		 * use the closest type, assuming that it would hopefully
-		 * work with a DVBv3 application.
-		 * It should be noticed that, on multi-frontend devices with
-		 * different types (terrestrial and cable, for example),
-		 * a pure DVBv3 application won't be able to use all delivery
-		 * systems. Yet, changing the DVBv5 cache to the other delivery
-		 * system should be enough for making it work.
-		 */
-		switch (dvbv3_type(c->delivery_system)) {
-		case DVBV3_QPSK:
-			info->type = FE_QPSK;
-			break;
-		case DVBV3_ATSC:
-			info->type = FE_ATSC;
-			break;
-		case DVBV3_QAM:
-			info->type = FE_QAM;
-			break;
-		case DVBV3_OFDM:
-			info->type = FE_OFDM;
-			break;
-		default:
-			printk(KERN_ERR
-			       "%s: doesn't know how to handle a DVBv3 call to delivery system %i\n",
-			       __func__, c->delivery_system);
-			fe->ops.info.type = FE_OFDM;
-		}
-		dprintk("current delivery system on cache: %d, V3 type: %d\n",
-			c->delivery_system, fe->ops.info.type);
-
-		/* Force the CAN_INVERSION_AUTO bit on. If the frontend doesn't
-		 * do it, it is done for it. */
-		info->caps |= FE_CAN_INVERSION_AUTO;
-		err = 0;
-		break;
-	}
-
-	case FE_READ_STATUS: {
-		fe_status_t* status = parg;
-
-		/* if retune was requested but hasn't occurred yet, prevent
-		 * that user get signal state from previous tuning */
-		if (fepriv->state == FESTATE_RETUNE ||
-		    fepriv->state == FESTATE_ERROR) {
-			err=0;
-			*status = 0;
-			break;
-		}
-
-		if (fe->ops.read_status)
-			err = fe->ops.read_status(fe, status);
-		break;
-	}
-	case FE_READ_BER:
-		if (fe->ops.read_ber)
-			err = fe->ops.read_ber(fe, (__u32*) parg);
-		break;
-
-	case FE_READ_SIGNAL_STRENGTH:
-		if (fe->ops.read_signal_strength)
-			err = fe->ops.read_signal_strength(fe, (__u16*) parg);
-		break;
-
-	case FE_READ_SNR:
-		if (fe->ops.read_snr)
-			err = fe->ops.read_snr(fe, (__u16*) parg);
-		break;
-
-	case FE_READ_UNCORRECTED_BLOCKS:
-		if (fe->ops.read_ucblocks)
-			err = fe->ops.read_ucblocks(fe, (__u32*) parg);
-		break;
-
-
-	case FE_DISEQC_RESET_OVERLOAD:
-		if (fe->ops.diseqc_reset_overload) {
-			err = fe->ops.diseqc_reset_overload(fe);
-			fepriv->state = FESTATE_DISEQC;
-			fepriv->status = 0;
-		}
-		break;
-
-	case FE_DISEQC_SEND_MASTER_CMD:
-		if (fe->ops.diseqc_send_master_cmd) {
-			err = fe->ops.diseqc_send_master_cmd(fe, (struct dvb_diseqc_master_cmd*) parg);
-			fepriv->state = FESTATE_DISEQC;
-			fepriv->status = 0;
-		}
-		break;
-
-	case FE_DISEQC_SEND_BURST:
-		if (fe->ops.diseqc_send_burst) {
-			err = fe->ops.diseqc_send_burst(fe, (fe_sec_mini_cmd_t) parg);
-			fepriv->state = FESTATE_DISEQC;
-			fepriv->status = 0;
-		}
-		break;
-
-	case FE_SET_TONE:
-		if (fe->ops.set_tone) {
-			err = fe->ops.set_tone(fe, (fe_sec_tone_mode_t) parg);
-			fepriv->tone = (fe_sec_tone_mode_t) parg;
-			fepriv->state = FESTATE_DISEQC;
-			fepriv->status = 0;
-		}
-		break;
-
-	case FE_SET_VOLTAGE:
-		if (fe->ops.set_voltage) {
-			err = fe->ops.set_voltage(fe, (fe_sec_voltage_t) parg);
-			fepriv->voltage = (fe_sec_voltage_t) parg;
-			fepriv->state = FESTATE_DISEQC;
-			fepriv->status = 0;
-		}
-		break;
-
-	case FE_DISHNETWORK_SEND_LEGACY_CMD:
-		if (fe->ops.dishnetwork_send_legacy_command) {
-			err = fe->ops.dishnetwork_send_legacy_command(fe, (unsigned long) parg);
-			fepriv->state = FESTATE_DISEQC;
-			fepriv->status = 0;
-		} else if (fe->ops.set_voltage) {
-			/*
-			 * NOTE: This is a fallback condition.  Some frontends
-			 * (stv0299 for instance) take longer than 8msec to
-			 * respond to a set_voltage command.  Those switches
-			 * need custom routines to switch properly.  For all
-			 * other frontends, the following should work ok.
-			 * Dish network legacy switches (as used by Dish500)
-			 * are controlled by sending 9-bit command words
-			 * spaced 8msec apart.
-			 * the actual command word is switch/port dependent
-			 * so it is up to the userspace application to send
-			 * the right command.
-			 * The command must always start with a '0' after
-			 * initialization, so parg is 8 bits and does not
-			 * include the initialization or start bit
-			 */
-			unsigned long swcmd = ((unsigned long) parg) << 1;
-			struct timeval nexttime;
-			struct timeval tv[10];
-			int i;
-			u8 last = 1;
-			if (dvb_frontend_debug)
-				printk("%s switch command: 0x%04lx\n", __func__, swcmd);
-			do_gettimeofday(&nexttime);
-			if (dvb_frontend_debug)
-				memcpy(&tv[0], &nexttime, sizeof(struct timeval));
-			/* before sending a command, initialize by sending
-			 * a 32ms 18V to the switch
-			 */
-			fe->ops.set_voltage(fe, SEC_VOLTAGE_18);
-			dvb_frontend_sleep_until(&nexttime, 32000);
-
-			for (i = 0; i < 9; i++) {
-				if (dvb_frontend_debug)
-					do_gettimeofday(&tv[i + 1]);
-				if ((swcmd & 0x01) != last) {
-					/* set voltage to (last ? 13V : 18V) */
-					fe->ops.set_voltage(fe, (last) ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18);
-					last = (last) ? 0 : 1;
-				}
-				swcmd = swcmd >> 1;
-				if (i != 8)
-					dvb_frontend_sleep_until(&nexttime, 8000);
-			}
-			if (dvb_frontend_debug) {
-				printk("%s(%d): switch delay (should be 32k followed by all 8k\n",
-					__func__, fe->dvb->num);
-				for (i = 1; i < 10; i++)
-					printk("%d: %d\n", i, timeval_usec_diff(tv[i-1] , tv[i]));
-			}
-			err = 0;
-			fepriv->state = FESTATE_DISEQC;
-			fepriv->status = 0;
-		}
-		break;
-
-	case FE_DISEQC_RECV_SLAVE_REPLY:
-		if (fe->ops.diseqc_recv_slave_reply)
-			err = fe->ops.diseqc_recv_slave_reply(fe, (struct dvb_diseqc_slave_reply*) parg);
-		break;
-
-	case FE_ENABLE_HIGH_LNB_VOLTAGE:
-		if (fe->ops.enable_high_lnb_voltage)
-			err = fe->ops.enable_high_lnb_voltage(fe, (long) parg);
-		break;
-
-	case FE_SET_FRONTEND:
-		err = set_delivery_system(fe, SYS_UNDEFINED);
-		if (err)
-			break;
-
-		err = dtv_property_cache_sync(fe, c, parg);
-		if (err)
-			break;
-		err = dtv_set_frontend(fe);
-		break;
-	case FE_GET_EVENT:
-		err = dvb_frontend_get_event (fe, parg, file->f_flags);
-		break;
-
-	case FE_GET_FRONTEND:
-		err = dtv_get_frontend(fe, parg);
-		break;
-
-	case FE_SET_FRONTEND_TUNE_MODE:
-		fepriv->tune_mode_flags = (unsigned long) parg;
-		err = 0;
-		break;
-	};
-
-	if (fe->dvb->fe_ioctl_override) {
-		cb_err = fe->dvb->fe_ioctl_override(fe, cmd, parg,
-						    DVB_FE_IOCTL_POST);
-		if (cb_err < 0)
-			return cb_err;
-	}
-
-	return err;
-}
-
-
-static unsigned int dvb_frontend_poll(struct file *file, struct poll_table_struct *wait)
-{
-	struct dvb_device *dvbdev = file->private_data;
-	struct dvb_frontend *fe = dvbdev->priv;
-	struct dvb_frontend_private *fepriv = fe->frontend_priv;
-
-	dprintk ("%s\n", __func__);
-
-	poll_wait (file, &fepriv->events.wait_queue, wait);
-
-	if (fepriv->events.eventw != fepriv->events.eventr)
-		return (POLLIN | POLLRDNORM | POLLPRI);
-
-	return 0;
-}
-
-static int dvb_frontend_open(struct inode *inode, struct file *file)
-{
-	struct dvb_device *dvbdev = file->private_data;
-	struct dvb_frontend *fe = dvbdev->priv;
-	struct dvb_frontend_private *fepriv = fe->frontend_priv;
-	struct dvb_adapter *adapter = fe->dvb;
-	int ret;
-
-	dprintk ("%s\n", __func__);
-	if (fepriv->exit == DVB_FE_DEVICE_REMOVED)
-		return -ENODEV;
-
-	if (adapter->mfe_shared) {
-		mutex_lock (&adapter->mfe_lock);
-
-		if (adapter->mfe_dvbdev == NULL)
-			adapter->mfe_dvbdev = dvbdev;
-
-		else if (adapter->mfe_dvbdev != dvbdev) {
-			struct dvb_device
-				*mfedev = adapter->mfe_dvbdev;
-			struct dvb_frontend
-				*mfe = mfedev->priv;
-			struct dvb_frontend_private
-				*mfepriv = mfe->frontend_priv;
-			int mferetry = (dvb_mfe_wait_time << 1);
-
-			mutex_unlock (&adapter->mfe_lock);
-			while (mferetry-- && (mfedev->users != -1 ||
-					mfepriv->thread != NULL)) {
-				if(msleep_interruptible(500)) {
-					if(signal_pending(current))
-						return -EINTR;
-				}
-			}
-
-			mutex_lock (&adapter->mfe_lock);
-			if(adapter->mfe_dvbdev != dvbdev) {
-				mfedev = adapter->mfe_dvbdev;
-				mfe = mfedev->priv;
-				mfepriv = mfe->frontend_priv;
-				if (mfedev->users != -1 ||
-						mfepriv->thread != NULL) {
-					mutex_unlock (&adapter->mfe_lock);
-					return -EBUSY;
-				}
-				adapter->mfe_dvbdev = dvbdev;
-			}
-		}
-	}
-
-	if (dvbdev->users == -1 && fe->ops.ts_bus_ctrl) {
-		if ((ret = fe->ops.ts_bus_ctrl(fe, 1)) < 0)
-			goto err0;
-
-		/* If we took control of the bus, we need to force
-		   reinitialization.  This is because many ts_bus_ctrl()
-		   functions strobe the RESET pin on the demod, and if the
-		   frontend thread already exists then the dvb_init() routine
-		   won't get called (which is what usually does initial
-		   register configuration). */
-		fepriv->reinitialise = 1;
-	}
-
-	if ((ret = dvb_generic_open (inode, file)) < 0)
-		goto err1;
-
-	if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
-		/* normal tune mode when opened R/W */
-		fepriv->tune_mode_flags &= ~FE_TUNE_MODE_ONESHOT;
-		fepriv->tone = -1;
-		fepriv->voltage = -1;
-
-		ret = dvb_frontend_start (fe);
-		if (ret)
-			goto err2;
-
-		/*  empty event queue */
-		fepriv->events.eventr = fepriv->events.eventw = 0;
-	}
-
-	if (adapter->mfe_shared)
-		mutex_unlock (&adapter->mfe_lock);
-	return ret;
-
-err2:
-	dvb_generic_release(inode, file);
-err1:
-	if (dvbdev->users == -1 && fe->ops.ts_bus_ctrl)
-		fe->ops.ts_bus_ctrl(fe, 0);
-err0:
-	if (adapter->mfe_shared)
-		mutex_unlock (&adapter->mfe_lock);
-	return ret;
-}
-
-static int dvb_frontend_release(struct inode *inode, struct file *file)
-{
-	struct dvb_device *dvbdev = file->private_data;
-	struct dvb_frontend *fe = dvbdev->priv;
-	struct dvb_frontend_private *fepriv = fe->frontend_priv;
-	int ret;
-
-	dprintk ("%s\n", __func__);
-
-	if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
-		fepriv->release_jiffies = jiffies;
-		mb();
-	}
-
-	ret = dvb_generic_release (inode, file);
-
-	if (dvbdev->users == -1) {
-		wake_up(&fepriv->wait_queue);
-		if (fepriv->exit != DVB_FE_NO_EXIT) {
-			fops_put(file->f_op);
-			file->f_op = NULL;
-			wake_up(&dvbdev->wait_queue);
-		}
-		if (fe->ops.ts_bus_ctrl)
-			fe->ops.ts_bus_ctrl(fe, 0);
-	}
-
-	return ret;
-}
-
-static const struct file_operations dvb_frontend_fops = {
-	.owner		= THIS_MODULE,
-	.unlocked_ioctl	= dvb_generic_ioctl,
-	.poll		= dvb_frontend_poll,
-	.open		= dvb_frontend_open,
-	.release	= dvb_frontend_release,
-	.llseek		= noop_llseek,
-};
-
-int dvb_register_frontend(struct dvb_adapter* dvb,
-			  struct dvb_frontend* fe)
-{
-	struct dvb_frontend_private *fepriv;
-	static const struct dvb_device dvbdev_template = {
-		.users = ~0,
-		.writers = 1,
-		.readers = (~0)-1,
-		.fops = &dvb_frontend_fops,
-		.kernel_ioctl = dvb_frontend_ioctl
-	};
-
-	dprintk ("%s\n", __func__);
-
-	if (mutex_lock_interruptible(&frontend_mutex))
-		return -ERESTARTSYS;
-
-	fe->frontend_priv = kzalloc(sizeof(struct dvb_frontend_private), GFP_KERNEL);
-	if (fe->frontend_priv == NULL) {
-		mutex_unlock(&frontend_mutex);
-		return -ENOMEM;
-	}
-	fepriv = fe->frontend_priv;
-
-	sema_init(&fepriv->sem, 1);
-	init_waitqueue_head (&fepriv->wait_queue);
-	init_waitqueue_head (&fepriv->events.wait_queue);
-	mutex_init(&fepriv->events.mtx);
-	fe->dvb = dvb;
-	fepriv->inversion = INVERSION_OFF;
-
-	printk ("DVB: registering adapter %i frontend %i (%s)...\n",
-		fe->dvb->num,
-		fe->id,
-		fe->ops.info.name);
-
-	dvb_register_device (fe->dvb, &fepriv->dvbdev, &dvbdev_template,
-			     fe, DVB_DEVICE_FRONTEND);
-
-	/*
-	 * Initialize the cache to the proper values according with the
-	 * first supported delivery system (ops->delsys[0])
-	 */
-
-        fe->dtv_property_cache.delivery_system = fe->ops.delsys[0];
-	dvb_frontend_clear_cache(fe);
-
-	mutex_unlock(&frontend_mutex);
-	return 0;
-}
-EXPORT_SYMBOL(dvb_register_frontend);
-
-int dvb_unregister_frontend(struct dvb_frontend* fe)
-{
-	struct dvb_frontend_private *fepriv = fe->frontend_priv;
-	dprintk ("%s\n", __func__);
-
-	mutex_lock(&frontend_mutex);
-	dvb_frontend_stop (fe);
-	mutex_unlock(&frontend_mutex);
-
-	if (fepriv->dvbdev->users < -1)
-		wait_event(fepriv->dvbdev->wait_queue,
-				fepriv->dvbdev->users==-1);
-
-	mutex_lock(&frontend_mutex);
-	dvb_unregister_device (fepriv->dvbdev);
-
-	/* fe is invalid now */
-	kfree(fepriv);
-	mutex_unlock(&frontend_mutex);
-	return 0;
-}
-EXPORT_SYMBOL(dvb_unregister_frontend);
-
-#ifdef CONFIG_MEDIA_ATTACH
-void dvb_frontend_detach(struct dvb_frontend* fe)
-{
-	void *ptr;
-
-	if (fe->ops.release_sec) {
-		fe->ops.release_sec(fe);
-		symbol_put_addr(fe->ops.release_sec);
-	}
-	if (fe->ops.tuner_ops.release) {
-		fe->ops.tuner_ops.release(fe);
-		symbol_put_addr(fe->ops.tuner_ops.release);
-	}
-	if (fe->ops.analog_ops.release) {
-		fe->ops.analog_ops.release(fe);
-		symbol_put_addr(fe->ops.analog_ops.release);
-	}
-	ptr = (void*)fe->ops.release;
-	if (ptr) {
-		fe->ops.release(fe);
-		symbol_put_addr(ptr);
-	}
-}
-#else
-void dvb_frontend_detach(struct dvb_frontend* fe)
-{
-	if (fe->ops.release_sec)
-		fe->ops.release_sec(fe);
-	if (fe->ops.tuner_ops.release)
-		fe->ops.tuner_ops.release(fe);
-	if (fe->ops.analog_ops.release)
-		fe->ops.analog_ops.release(fe);
-	if (fe->ops.release)
-		fe->ops.release(fe);
-}
-#endif
-EXPORT_SYMBOL(dvb_frontend_detach);
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.h b/drivers/media/dvb/dvb-core/dvb_frontend.h
deleted file mode 100644
index 7c64c09..0000000
--- a/drivers/media/dvb/dvb-core/dvb_frontend.h
+++ /dev/null
@@ -1,423 +0,0 @@
-/*
- * dvb_frontend.h
- *
- * Copyright (C) 2001 convergence integrated media GmbH
- * Copyright (C) 2004 convergence GmbH
- *
- * Written by Ralph Metzler
- * Overhauled by Holger Waechtler
- * Kernel I2C stuff by Michael Hunold <hunold@convergence.de>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1
- * 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 Lesser General Public 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 _DVB_FRONTEND_H_
-#define _DVB_FRONTEND_H_
-
-#include <linux/types.h>
-#include <linux/sched.h>
-#include <linux/ioctl.h>
-#include <linux/i2c.h>
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/delay.h>
-#include <linux/mutex.h>
-#include <linux/slab.h>
-
-#include <linux/dvb/frontend.h>
-
-#include "dvbdev.h"
-
-/*
- * Maximum number of Delivery systems per frontend. It
- * should be smaller or equal to 32
- */
-#define MAX_DELSYS	8
-
-struct dvb_frontend_tune_settings {
-	int min_delay_ms;
-	int step_size;
-	int max_drift;
-};
-
-struct dvb_frontend;
-
-struct dvb_tuner_info {
-	char name[128];
-
-	u32 frequency_min;
-	u32 frequency_max;
-	u32 frequency_step;
-
-	u32 bandwidth_min;
-	u32 bandwidth_max;
-	u32 bandwidth_step;
-};
-
-struct analog_parameters {
-	unsigned int frequency;
-	unsigned int mode;
-	unsigned int audmode;
-	u64 std;
-};
-
-enum dvbfe_modcod {
-	DVBFE_MODCOD_DUMMY_PLFRAME	= 0,
-	DVBFE_MODCOD_QPSK_1_4,
-	DVBFE_MODCOD_QPSK_1_3,
-	DVBFE_MODCOD_QPSK_2_5,
-	DVBFE_MODCOD_QPSK_1_2,
-	DVBFE_MODCOD_QPSK_3_5,
-	DVBFE_MODCOD_QPSK_2_3,
-	DVBFE_MODCOD_QPSK_3_4,
-	DVBFE_MODCOD_QPSK_4_5,
-	DVBFE_MODCOD_QPSK_5_6,
-	DVBFE_MODCOD_QPSK_8_9,
-	DVBFE_MODCOD_QPSK_9_10,
-	DVBFE_MODCOD_8PSK_3_5,
-	DVBFE_MODCOD_8PSK_2_3,
-	DVBFE_MODCOD_8PSK_3_4,
-	DVBFE_MODCOD_8PSK_5_6,
-	DVBFE_MODCOD_8PSK_8_9,
-	DVBFE_MODCOD_8PSK_9_10,
-	DVBFE_MODCOD_16APSK_2_3,
-	DVBFE_MODCOD_16APSK_3_4,
-	DVBFE_MODCOD_16APSK_4_5,
-	DVBFE_MODCOD_16APSK_5_6,
-	DVBFE_MODCOD_16APSK_8_9,
-	DVBFE_MODCOD_16APSK_9_10,
-	DVBFE_MODCOD_32APSK_3_4,
-	DVBFE_MODCOD_32APSK_4_5,
-	DVBFE_MODCOD_32APSK_5_6,
-	DVBFE_MODCOD_32APSK_8_9,
-	DVBFE_MODCOD_32APSK_9_10,
-	DVBFE_MODCOD_RESERVED_1,
-	DVBFE_MODCOD_BPSK_1_3,
-	DVBFE_MODCOD_BPSK_1_4,
-	DVBFE_MODCOD_RESERVED_2
-};
-
-enum tuner_param {
-	DVBFE_TUNER_FREQUENCY		= (1 <<  0),
-	DVBFE_TUNER_TUNERSTEP		= (1 <<  1),
-	DVBFE_TUNER_IFFREQ		= (1 <<  2),
-	DVBFE_TUNER_BANDWIDTH		= (1 <<  3),
-	DVBFE_TUNER_REFCLOCK		= (1 <<  4),
-	DVBFE_TUNER_IQSENSE		= (1 <<  5),
-	DVBFE_TUNER_DUMMY		= (1 << 31)
-};
-
-/*
- * ALGO_HW: (Hardware Algorithm)
- * ----------------------------------------------------------------
- * Devices that support this algorithm do everything in hardware
- * and no software support is needed to handle them.
- * Requesting these devices to LOCK is the only thing required,
- * device is supposed to do everything in the hardware.
- *
- * ALGO_SW: (Software Algorithm)
- * ----------------------------------------------------------------
- * These are dumb devices, that require software to do everything
- *
- * ALGO_CUSTOM: (Customizable Agorithm)
- * ----------------------------------------------------------------
- * Devices having this algorithm can be customized to have specific
- * algorithms in the frontend driver, rather than simply doing a
- * software zig-zag. In this case the zigzag maybe hardware assisted
- * or it maybe completely done in hardware. In all cases, usage of
- * this algorithm, in conjunction with the search and track
- * callbacks, utilizes the driver specific algorithm.
- *
- * ALGO_RECOVERY: (Recovery Algorithm)
- * ----------------------------------------------------------------
- * These devices have AUTO recovery capabilities from LOCK failure
- */
-enum dvbfe_algo {
-	DVBFE_ALGO_HW			= (1 <<  0),
-	DVBFE_ALGO_SW			= (1 <<  1),
-	DVBFE_ALGO_CUSTOM		= (1 <<  2),
-	DVBFE_ALGO_RECOVERY		= (1 << 31)
-};
-
-struct tuner_state {
-	u32 frequency;
-	u32 tunerstep;
-	u32 ifreq;
-	u32 bandwidth;
-	u32 iqsense;
-	u32 refclock;
-};
-
-/*
- * search callback possible return status
- *
- * DVBFE_ALGO_SEARCH_SUCCESS
- * The frontend search algorithm completed and returned successfully
- *
- * DVBFE_ALGO_SEARCH_ASLEEP
- * The frontend search algorithm is sleeping
- *
- * DVBFE_ALGO_SEARCH_FAILED
- * The frontend search for a signal failed
- *
- * DVBFE_ALGO_SEARCH_INVALID
- * The frontend search algorith was probably supplied with invalid
- * parameters and the search is an invalid one
- *
- * DVBFE_ALGO_SEARCH_ERROR
- * The frontend search algorithm failed due to some error
- *
- * DVBFE_ALGO_SEARCH_AGAIN
- * The frontend search algorithm was requested to search again
- */
-enum dvbfe_search {
-	DVBFE_ALGO_SEARCH_SUCCESS	= (1 <<  0),
-	DVBFE_ALGO_SEARCH_ASLEEP	= (1 <<  1),
-	DVBFE_ALGO_SEARCH_FAILED	= (1 <<  2),
-	DVBFE_ALGO_SEARCH_INVALID	= (1 <<  3),
-	DVBFE_ALGO_SEARCH_AGAIN		= (1 <<  4),
-	DVBFE_ALGO_SEARCH_ERROR		= (1 << 31),
-};
-
-
-struct dvb_tuner_ops {
-
-	struct dvb_tuner_info info;
-
-	int (*release)(struct dvb_frontend *fe);
-	int (*init)(struct dvb_frontend *fe);
-	int (*sleep)(struct dvb_frontend *fe);
-
-	/** This is for simple PLLs - set all parameters in one go. */
-	int (*set_params)(struct dvb_frontend *fe);
-	int (*set_analog_params)(struct dvb_frontend *fe, struct analog_parameters *p);
-
-	/** This is support for demods like the mt352 - fills out the supplied buffer with what to write. */
-	int (*calc_regs)(struct dvb_frontend *fe, u8 *buf, int buf_len);
-
-	/** This is to allow setting tuner-specific configs */
-	int (*set_config)(struct dvb_frontend *fe, void *priv_cfg);
-
-	int (*get_frequency)(struct dvb_frontend *fe, u32 *frequency);
-	int (*get_bandwidth)(struct dvb_frontend *fe, u32 *bandwidth);
-	int (*get_if_frequency)(struct dvb_frontend *fe, u32 *frequency);
-
-#define TUNER_STATUS_LOCKED 1
-#define TUNER_STATUS_STEREO 2
-	int (*get_status)(struct dvb_frontend *fe, u32 *status);
-	int (*get_rf_strength)(struct dvb_frontend *fe, u16 *strength);
-	int (*get_afc)(struct dvb_frontend *fe, s32 *afc);
-
-	/** These are provided separately from set_params in order to facilitate silicon
-	 * tuners which require sophisticated tuning loops, controlling each parameter separately. */
-	int (*set_frequency)(struct dvb_frontend *fe, u32 frequency);
-	int (*set_bandwidth)(struct dvb_frontend *fe, u32 bandwidth);
-
-	/*
-	 * These are provided separately from set_params in order to facilitate silicon
-	 * tuners which require sophisticated tuning loops, controlling each parameter separately.
-	 */
-	int (*set_state)(struct dvb_frontend *fe, enum tuner_param param, struct tuner_state *state);
-	int (*get_state)(struct dvb_frontend *fe, enum tuner_param param, struct tuner_state *state);
-};
-
-struct analog_demod_info {
-	char *name;
-};
-
-struct analog_demod_ops {
-
-	struct analog_demod_info info;
-
-	void (*set_params)(struct dvb_frontend *fe,
-			   struct analog_parameters *params);
-	int  (*has_signal)(struct dvb_frontend *fe);
-	int  (*get_afc)(struct dvb_frontend *fe);
-	void (*tuner_status)(struct dvb_frontend *fe);
-	void (*standby)(struct dvb_frontend *fe);
-	void (*release)(struct dvb_frontend *fe);
-	int  (*i2c_gate_ctrl)(struct dvb_frontend *fe, int enable);
-
-	/** This is to allow setting tuner-specific configuration */
-	int (*set_config)(struct dvb_frontend *fe, void *priv_cfg);
-};
-
-struct dtv_frontend_properties;
-
-struct dvb_frontend_ops {
-
-	struct dvb_frontend_info info;
-
-	u8 delsys[MAX_DELSYS];
-
-	void (*release)(struct dvb_frontend* fe);
-	void (*release_sec)(struct dvb_frontend* fe);
-
-	int (*init)(struct dvb_frontend* fe);
-	int (*sleep)(struct dvb_frontend* fe);
-
-	int (*write)(struct dvb_frontend* fe, const u8 buf[], int len);
-
-	/* if this is set, it overrides the default swzigzag */
-	int (*tune)(struct dvb_frontend* fe,
-		    bool re_tune,
-		    unsigned int mode_flags,
-		    unsigned int *delay,
-		    fe_status_t *status);
-	/* get frontend tuning algorithm from the module */
-	enum dvbfe_algo (*get_frontend_algo)(struct dvb_frontend *fe);
-
-	/* these two are only used for the swzigzag code */
-	int (*set_frontend)(struct dvb_frontend *fe);
-	int (*get_tune_settings)(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* settings);
-
-	int (*get_frontend)(struct dvb_frontend *fe);
-
-	int (*read_status)(struct dvb_frontend* fe, fe_status_t* status);
-	int (*read_ber)(struct dvb_frontend* fe, u32* ber);
-	int (*read_signal_strength)(struct dvb_frontend* fe, u16* strength);
-	int (*read_snr)(struct dvb_frontend* fe, u16* snr);
-	int (*read_ucblocks)(struct dvb_frontend* fe, u32* ucblocks);
-
-	int (*diseqc_reset_overload)(struct dvb_frontend* fe);
-	int (*diseqc_send_master_cmd)(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd);
-	int (*diseqc_recv_slave_reply)(struct dvb_frontend* fe, struct dvb_diseqc_slave_reply* reply);
-	int (*diseqc_send_burst)(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd);
-	int (*set_tone)(struct dvb_frontend* fe, fe_sec_tone_mode_t tone);
-	int (*set_voltage)(struct dvb_frontend* fe, fe_sec_voltage_t voltage);
-	int (*enable_high_lnb_voltage)(struct dvb_frontend* fe, long arg);
-	int (*dishnetwork_send_legacy_command)(struct dvb_frontend* fe, unsigned long cmd);
-	int (*i2c_gate_ctrl)(struct dvb_frontend* fe, int enable);
-	int (*ts_bus_ctrl)(struct dvb_frontend* fe, int acquire);
-
-	/* These callbacks are for devices that implement their own
-	 * tuning algorithms, rather than a simple swzigzag
-	 */
-	enum dvbfe_search (*search)(struct dvb_frontend *fe);
-
-	struct dvb_tuner_ops tuner_ops;
-	struct analog_demod_ops analog_ops;
-
-	int (*set_property)(struct dvb_frontend* fe, struct dtv_property* tvp);
-	int (*get_property)(struct dvb_frontend* fe, struct dtv_property* tvp);
-};
-
-#ifdef __DVB_CORE__
-#define MAX_EVENT 8
-
-struct dvb_fe_events {
-	struct dvb_frontend_event events[MAX_EVENT];
-	int			  eventw;
-	int			  eventr;
-	int			  overflow;
-	wait_queue_head_t	  wait_queue;
-	struct mutex		  mtx;
-};
-#endif
-
-struct dtv_frontend_properties {
-
-	/* Cache State */
-	u32			state;
-
-	u32			frequency;
-	fe_modulation_t		modulation;
-
-	fe_sec_voltage_t	voltage;
-	fe_sec_tone_mode_t	sectone;
-	fe_spectral_inversion_t	inversion;
-	fe_code_rate_t		fec_inner;
-	fe_transmit_mode_t	transmission_mode;
-	u32			bandwidth_hz;	/* 0 = AUTO */
-	fe_guard_interval_t	guard_interval;
-	fe_hierarchy_t		hierarchy;
-	u32			symbol_rate;
-	fe_code_rate_t		code_rate_HP;
-	fe_code_rate_t		code_rate_LP;
-
-	fe_pilot_t		pilot;
-	fe_rolloff_t		rolloff;
-
-	fe_delivery_system_t	delivery_system;
-
-	/* ISDB-T specifics */
-	u8			isdbt_partial_reception;
-	u8			isdbt_sb_mode;
-	u8			isdbt_sb_subchannel;
-	u32			isdbt_sb_segment_idx;
-	u32			isdbt_sb_segment_count;
-	u8			isdbt_layer_enabled;
-	struct {
-	    u8			segment_count;
-	    fe_code_rate_t	fec;
-	    fe_modulation_t	modulation;
-	    u8			interleaving;
-	} layer[3];
-
-	/* ISDB-T specifics */
-	u32			isdbs_ts_id;
-
-	/* DVB-T2 specifics */
-	u32                     dvbt2_plp_id;
-
-	/* ATSC-MH specifics */
-	u8			atscmh_fic_ver;
-	u8			atscmh_parade_id;
-	u8			atscmh_nog;
-	u8			atscmh_tnog;
-	u8			atscmh_sgn;
-	u8			atscmh_prc;
-
-	u8			atscmh_rs_frame_mode;
-	u8			atscmh_rs_frame_ensemble;
-	u8			atscmh_rs_code_mode_pri;
-	u8			atscmh_rs_code_mode_sec;
-	u8			atscmh_sccc_block_mode;
-	u8			atscmh_sccc_code_mode_a;
-	u8			atscmh_sccc_code_mode_b;
-	u8			atscmh_sccc_code_mode_c;
-	u8			atscmh_sccc_code_mode_d;
-};
-
-struct dvb_frontend {
-	struct dvb_frontend_ops ops;
-	struct dvb_adapter *dvb;
-	void *demodulator_priv;
-	void *tuner_priv;
-	void *frontend_priv;
-	void *sec_priv;
-	void *analog_demod_priv;
-	struct dtv_frontend_properties dtv_property_cache;
-#define DVB_FRONTEND_COMPONENT_TUNER 0
-#define DVB_FRONTEND_COMPONENT_DEMOD 1
-	int (*callback)(void *adapter_priv, int component, int cmd, int arg);
-	int id;
-};
-
-extern int dvb_register_frontend(struct dvb_adapter *dvb,
-				 struct dvb_frontend *fe);
-
-extern int dvb_unregister_frontend(struct dvb_frontend *fe);
-
-extern void dvb_frontend_detach(struct dvb_frontend *fe);
-
-extern void dvb_frontend_reinitialise(struct dvb_frontend *fe);
-
-extern void dvb_frontend_sleep_until(struct timeval *waketime, u32 add_usec);
-extern s32 timeval_usec_diff(struct timeval lasttime, struct timeval curtime);
-
-#endif
diff --git a/drivers/media/dvb/dvb-core/dvb_math.c b/drivers/media/dvb/dvb-core/dvb_math.c
deleted file mode 100644
index beb7c93..0000000
--- a/drivers/media/dvb/dvb-core/dvb_math.c
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * dvb-math provides some complex fixed-point math
- * operations shared between the dvb related stuff
- *
- * Copyright (C) 2006 Christoph Pfister (christophpfister@gmail.com)
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <linux/bitops.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <asm/bug.h>
-#include "dvb_math.h"
-
-static const unsigned short logtable[256] = {
-	0x0000, 0x0171, 0x02e0, 0x044e, 0x05ba, 0x0725, 0x088e, 0x09f7,
-	0x0b5d, 0x0cc3, 0x0e27, 0x0f8a, 0x10eb, 0x124b, 0x13aa, 0x1508,
-	0x1664, 0x17bf, 0x1919, 0x1a71, 0x1bc8, 0x1d1e, 0x1e73, 0x1fc6,
-	0x2119, 0x226a, 0x23ba, 0x2508, 0x2656, 0x27a2, 0x28ed, 0x2a37,
-	0x2b80, 0x2cc8, 0x2e0f, 0x2f54, 0x3098, 0x31dc, 0x331e, 0x345f,
-	0x359f, 0x36de, 0x381b, 0x3958, 0x3a94, 0x3bce, 0x3d08, 0x3e41,
-	0x3f78, 0x40af, 0x41e4, 0x4319, 0x444c, 0x457f, 0x46b0, 0x47e1,
-	0x4910, 0x4a3f, 0x4b6c, 0x4c99, 0x4dc5, 0x4eef, 0x5019, 0x5142,
-	0x526a, 0x5391, 0x54b7, 0x55dc, 0x5700, 0x5824, 0x5946, 0x5a68,
-	0x5b89, 0x5ca8, 0x5dc7, 0x5ee5, 0x6003, 0x611f, 0x623a, 0x6355,
-	0x646f, 0x6588, 0x66a0, 0x67b7, 0x68ce, 0x69e4, 0x6af8, 0x6c0c,
-	0x6d20, 0x6e32, 0x6f44, 0x7055, 0x7165, 0x7274, 0x7383, 0x7490,
-	0x759d, 0x76aa, 0x77b5, 0x78c0, 0x79ca, 0x7ad3, 0x7bdb, 0x7ce3,
-	0x7dea, 0x7ef0, 0x7ff6, 0x80fb, 0x81ff, 0x8302, 0x8405, 0x8507,
-	0x8608, 0x8709, 0x8809, 0x8908, 0x8a06, 0x8b04, 0x8c01, 0x8cfe,
-	0x8dfa, 0x8ef5, 0x8fef, 0x90e9, 0x91e2, 0x92db, 0x93d2, 0x94ca,
-	0x95c0, 0x96b6, 0x97ab, 0x98a0, 0x9994, 0x9a87, 0x9b7a, 0x9c6c,
-	0x9d5e, 0x9e4f, 0x9f3f, 0xa02e, 0xa11e, 0xa20c, 0xa2fa, 0xa3e7,
-	0xa4d4, 0xa5c0, 0xa6ab, 0xa796, 0xa881, 0xa96a, 0xaa53, 0xab3c,
-	0xac24, 0xad0c, 0xadf2, 0xaed9, 0xafbe, 0xb0a4, 0xb188, 0xb26c,
-	0xb350, 0xb433, 0xb515, 0xb5f7, 0xb6d9, 0xb7ba, 0xb89a, 0xb97a,
-	0xba59, 0xbb38, 0xbc16, 0xbcf4, 0xbdd1, 0xbead, 0xbf8a, 0xc065,
-	0xc140, 0xc21b, 0xc2f5, 0xc3cf, 0xc4a8, 0xc580, 0xc658, 0xc730,
-	0xc807, 0xc8de, 0xc9b4, 0xca8a, 0xcb5f, 0xcc34, 0xcd08, 0xcddc,
-	0xceaf, 0xcf82, 0xd054, 0xd126, 0xd1f7, 0xd2c8, 0xd399, 0xd469,
-	0xd538, 0xd607, 0xd6d6, 0xd7a4, 0xd872, 0xd93f, 0xda0c, 0xdad9,
-	0xdba5, 0xdc70, 0xdd3b, 0xde06, 0xded0, 0xdf9a, 0xe063, 0xe12c,
-	0xe1f5, 0xe2bd, 0xe385, 0xe44c, 0xe513, 0xe5d9, 0xe69f, 0xe765,
-	0xe82a, 0xe8ef, 0xe9b3, 0xea77, 0xeb3b, 0xebfe, 0xecc1, 0xed83,
-	0xee45, 0xef06, 0xefc8, 0xf088, 0xf149, 0xf209, 0xf2c8, 0xf387,
-	0xf446, 0xf505, 0xf5c3, 0xf680, 0xf73e, 0xf7fb, 0xf8b7, 0xf973,
-	0xfa2f, 0xfaea, 0xfba5, 0xfc60, 0xfd1a, 0xfdd4, 0xfe8e, 0xff47
-};
-
-unsigned int intlog2(u32 value)
-{
-	/**
-	 *	returns: log2(value) * 2^24
-	 *	wrong result if value = 0 (log2(0) is undefined)
-	 */
-	unsigned int msb;
-	unsigned int logentry;
-	unsigned int significand;
-	unsigned int interpolation;
-
-	if (unlikely(value == 0)) {
-		WARN_ON(1);
-		return 0;
-	}
-
-	/* first detect the msb (count begins at 0) */
-	msb = fls(value) - 1;
-
-	/**
-	 *	now we use a logtable after the following method:
-	 *
-	 *	log2(2^x * y) * 2^24 = x * 2^24 + log2(y) * 2^24
-	 *	where x = msb and therefore 1 <= y < 2
-	 *	first y is determined by shifting the value left
-	 *	so that msb is bit 31
-	 *		0x00231f56 -> 0x8C7D5800
-	 *	the result is y * 2^31 -> "significand"
-	 *	then the highest 9 bits are used for a table lookup
-	 *	the highest bit is discarded because it's always set
-	 *	the highest nine bits in our example are 100011000
-	 *	so we would use the entry 0x18
-	 */
-	significand = value << (31 - msb);
-	logentry = (significand >> 23) & 0xff;
-
-	/**
-	 *	last step we do is interpolation because of the
-	 *	limitations of the log table the error is that part of
-	 *	the significand which isn't used for lookup then we
-	 *	compute the ratio between the error and the next table entry
-	 *	and interpolate it between the log table entry used and the
-	 *	next one the biggest error possible is 0x7fffff
-	 *	(in our example it's 0x7D5800)
-	 *	needed value for next table entry is 0x800000
-	 *	so the interpolation is
-	 *	(error / 0x800000) * (logtable_next - logtable_current)
-	 *	in the implementation the division is moved to the end for
-	 *	better accuracy there is also an overflow correction if
-	 *	logtable_next is 256
-	 */
-	interpolation = ((significand & 0x7fffff) *
-			((logtable[(logentry + 1) & 0xff] -
-			  logtable[logentry]) & 0xffff)) >> 15;
-
-	/* now we return the result */
-	return ((msb << 24) + (logtable[logentry] << 8) + interpolation);
-}
-EXPORT_SYMBOL(intlog2);
-
-unsigned int intlog10(u32 value)
-{
-	/**
-	 *	returns: log10(value) * 2^24
-	 *	wrong result if value = 0 (log10(0) is undefined)
-	 */
-	u64 log;
-
-	if (unlikely(value == 0)) {
-		WARN_ON(1);
-		return 0;
-	}
-
-	log = intlog2(value);
-
-	/**
-	 *	we use the following method:
-	 *	log10(x) = log2(x) * log10(2)
-	 */
-
-	return (log * 646456993) >> 31;
-}
-EXPORT_SYMBOL(intlog10);
diff --git a/drivers/media/dvb/dvb-core/dvb_math.h b/drivers/media/dvb/dvb-core/dvb_math.h
deleted file mode 100644
index aecc867..0000000
--- a/drivers/media/dvb/dvb-core/dvb_math.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * dvb-math provides some complex fixed-point math
- * operations shared between the dvb related stuff
- *
- * Copyright (C) 2006 Christoph Pfister (christophpfister@gmail.com)
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef __DVB_MATH_H
-#define __DVB_MATH_H
-
-#include <linux/types.h>
-
-/**
- * computes log2 of a value; the result is shifted left by 24 bits
- *
- * to use rational values you can use the following method:
- *   intlog2(value) = intlog2(value * 2^x) - x * 2^24
- *
- * example: intlog2(8) will give 3 << 24 = 3 * 2^24
- * example: intlog2(9) will give 3 << 24 + ... = 3.16... * 2^24
- * example: intlog2(1.5) = intlog2(3) - 2^24 = 0.584... * 2^24
- *
- * @param value The value (must be != 0)
- * @return log2(value) * 2^24
- */
-extern unsigned int intlog2(u32 value);
-
-/**
- * computes log10 of a value; the result is shifted left by 24 bits
- *
- * to use rational values you can use the following method:
- *   intlog10(value) = intlog10(value * 10^x) - x * 2^24
- *
- * example: intlog10(1000) will give 3 << 24 = 3 * 2^24
- *   due to the implementation intlog10(1000) might be not exactly 3 * 2^24
- *
- * look at intlog2 for similar examples
- *
- * @param value The value (must be != 0)
- * @return log10(value) * 2^24
- */
-extern unsigned int intlog10(u32 value);
-
-#endif
diff --git a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c
deleted file mode 100644
index 8766ce8..0000000
--- a/drivers/media/dvb/dvb-core/dvb_net.c
+++ /dev/null
@@ -1,1516 +0,0 @@
-/*
- * dvb_net.c
- *
- * Copyright (C) 2001 Convergence integrated media GmbH
- *                    Ralph Metzler <ralph@convergence.de>
- * Copyright (C) 2002 Ralph Metzler <rjkm@metzlerbros.de>
- *
- * ULE Decapsulation code:
- * Copyright (C) 2003, 2004 gcs - Global Communication & Services GmbH.
- *                      and Department of Scientific Computing
- *                          Paris Lodron University of Salzburg.
- *                          Hilmar Linder <hlinder@cosy.sbg.ac.at>
- *                      and Wolfram Stering <wstering@cosy.sbg.ac.at>
- *
- * ULE Decaps according to RFC 4326.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the 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.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-/*
- * ULE ChangeLog:
- * Feb 2004: hl/ws v1: Implementing draft-fair-ipdvb-ule-01.txt
- *
- * Dec 2004: hl/ws v2: Implementing draft-ietf-ipdvb-ule-03.txt:
- *                       ULE Extension header handling.
- *                     Bugreports by Moritz Vieth and Hanno Tersteegen,
- *                       Fraunhofer Institute for Open Communication Systems
- *                       Competence Center for Advanced Satellite Communications.
- *                     Bugfixes and robustness improvements.
- *                     Filtering on dest MAC addresses, if present (D-Bit = 0)
- *                     ULE_DEBUG compile-time option.
- * Apr 2006: cp v3:    Bugfixes and compliency with RFC 4326 (ULE) by
- *                       Christian Praehauser <cpraehaus@cosy.sbg.ac.at>,
- *                       Paris Lodron University of Salzburg.
- */
-
-/*
- * FIXME / TODO (dvb_net.c):
- *
- * Unloading does not work for 2.6.9 kernels: a refcount doesn't go to zero.
- *
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/dvb/net.h>
-#include <linux/uio.h>
-#include <asm/uaccess.h>
-#include <linux/crc32.h>
-#include <linux/mutex.h>
-#include <linux/sched.h>
-
-#include "dvb_demux.h"
-#include "dvb_net.h"
-
-static int dvb_net_debug;
-module_param(dvb_net_debug, int, 0444);
-MODULE_PARM_DESC(dvb_net_debug, "enable debug messages");
-
-#define dprintk(x...) do { if (dvb_net_debug) printk(x); } while (0)
-
-
-static inline __u32 iov_crc32( __u32 c, struct kvec *iov, unsigned int cnt )
-{
-	unsigned int j;
-	for (j = 0; j < cnt; j++)
-		c = crc32_be( c, iov[j].iov_base, iov[j].iov_len );
-	return c;
-}
-
-
-#define DVB_NET_MULTICAST_MAX 10
-
-#undef ULE_DEBUG
-
-#ifdef ULE_DEBUG
-
-#define MAC_ADDR_PRINTFMT "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x"
-#define MAX_ADDR_PRINTFMT_ARGS(macap) (macap)[0],(macap)[1],(macap)[2],(macap)[3],(macap)[4],(macap)[5]
-
-#define isprint(c)	((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'))
-
-static void hexdump( const unsigned char *buf, unsigned short len )
-{
-	char str[80], octet[10];
-	int ofs, i, l;
-
-	for (ofs = 0; ofs < len; ofs += 16) {
-		sprintf( str, "%03d: ", ofs );
-
-		for (i = 0; i < 16; i++) {
-			if ((i + ofs) < len)
-				sprintf( octet, "%02x ", buf[ofs + i] );
-			else
-				strcpy( octet, "   " );
-
-			strcat( str, octet );
-		}
-		strcat( str, "  " );
-		l = strlen( str );
-
-		for (i = 0; (i < 16) && ((i + ofs) < len); i++)
-			str[l++] = isprint( buf[ofs + i] ) ? buf[ofs + i] : '.';
-
-		str[l] = '\0';
-		printk( KERN_WARNING "%s\n", str );
-	}
-}
-
-#endif
-
-struct dvb_net_priv {
-	int in_use;
-	u16 pid;
-	struct net_device *net;
-	struct dvb_net *host;
-	struct dmx_demux *demux;
-	struct dmx_section_feed *secfeed;
-	struct dmx_section_filter *secfilter;
-	struct dmx_ts_feed *tsfeed;
-	int multi_num;
-	struct dmx_section_filter *multi_secfilter[DVB_NET_MULTICAST_MAX];
-	unsigned char multi_macs[DVB_NET_MULTICAST_MAX][6];
-	int rx_mode;
-#define RX_MODE_UNI 0
-#define RX_MODE_MULTI 1
-#define RX_MODE_ALL_MULTI 2
-#define RX_MODE_PROMISC 3
-	struct work_struct set_multicast_list_wq;
-	struct work_struct restart_net_feed_wq;
-	unsigned char feedtype;			/* Either FEED_TYPE_ or FEED_TYPE_ULE */
-	int need_pusi;				/* Set to 1, if synchronization on PUSI required. */
-	unsigned char tscc;			/* TS continuity counter after sync on PUSI. */
-	struct sk_buff *ule_skb;		/* ULE SNDU decodes into this buffer. */
-	unsigned char *ule_next_hdr;		/* Pointer into skb to next ULE extension header. */
-	unsigned short ule_sndu_len;		/* ULE SNDU length in bytes, w/o D-Bit. */
-	unsigned short ule_sndu_type;		/* ULE SNDU type field, complete. */
-	unsigned char ule_sndu_type_1;		/* ULE SNDU type field, if split across 2 TS cells. */
-	unsigned char ule_dbit;			/* Whether the DestMAC address present
-						 * or not (bit is set). */
-	unsigned char ule_bridged;		/* Whether the ULE_BRIDGED extension header was found. */
-	int ule_sndu_remain;			/* Nr. of bytes still required for current ULE SNDU. */
-	unsigned long ts_count;			/* Current ts cell counter. */
-	struct mutex mutex;
-};
-
-
-/**
- *	Determine the packet's protocol ID. The rule here is that we
- *	assume 802.3 if the type field is short enough to be a length.
- *	This is normal practice and works for any 'now in use' protocol.
- *
- *  stolen from eth.c out of the linux kernel, hacked for dvb-device
- *  by Michael Holzt <kju@debian.org>
- */
-static __be16 dvb_net_eth_type_trans(struct sk_buff *skb,
-				      struct net_device *dev)
-{
-	struct ethhdr *eth;
-	unsigned char *rawp;
-
-	skb_reset_mac_header(skb);
-	skb_pull(skb,dev->hard_header_len);
-	eth = eth_hdr(skb);
-
-	if (*eth->h_dest & 1) {
-		if(memcmp(eth->h_dest,dev->broadcast, ETH_ALEN)==0)
-			skb->pkt_type=PACKET_BROADCAST;
-		else
-			skb->pkt_type=PACKET_MULTICAST;
-	}
-
-	if (ntohs(eth->h_proto) >= 1536)
-		return eth->h_proto;
-
-	rawp = skb->data;
-
-	/**
-	 *	This is a magic hack to spot IPX packets. Older Novell breaks
-	 *	the protocol design and runs IPX over 802.3 without an 802.2 LLC
-	 *	layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This
-	 *	won't work for fault tolerant netware but does for the rest.
-	 */
-	if (*(unsigned short *)rawp == 0xFFFF)
-		return htons(ETH_P_802_3);
-
-	/**
-	 *	Real 802.2 LLC
-	 */
-	return htons(ETH_P_802_2);
-}
-
-#define TS_SZ	188
-#define TS_SYNC	0x47
-#define TS_TEI	0x80
-#define TS_SC	0xC0
-#define TS_PUSI	0x40
-#define TS_AF_A	0x20
-#define TS_AF_D	0x10
-
-/* ULE Extension Header handlers. */
-
-#define ULE_TEST	0
-#define ULE_BRIDGED	1
-
-#define ULE_OPTEXTHDR_PADDING 0
-
-static int ule_test_sndu( struct dvb_net_priv *p )
-{
-	return -1;
-}
-
-static int ule_bridged_sndu( struct dvb_net_priv *p )
-{
-	struct ethhdr *hdr = (struct ethhdr*) p->ule_next_hdr;
-	if(ntohs(hdr->h_proto) < 1536) {
-		int framelen = p->ule_sndu_len - ((p->ule_next_hdr+sizeof(struct ethhdr)) - p->ule_skb->data);
-		/* A frame Type < 1536 for a bridged frame, introduces a LLC Length field. */
-		if(framelen != ntohs(hdr->h_proto)) {
-			return -1;
-		}
-	}
-	/* Note:
-	 * From RFC4326:
-	 *  "A bridged SNDU is a Mandatory Extension Header of Type 1.
-	 *   It must be the final (or only) extension header specified in the header chain of a SNDU."
-	 * The 'ule_bridged' flag will cause the extension header processing loop to terminate.
-	 */
-	p->ule_bridged = 1;
-	return 0;
-}
-
-static int ule_exthdr_padding(struct dvb_net_priv *p)
-{
-	return 0;
-}
-
-/** Handle ULE extension headers.
- *  Function is called after a successful CRC32 verification of an ULE SNDU to complete its decoding.
- *  Returns: >= 0: nr. of bytes consumed by next extension header
- *	     -1:   Mandatory extension header that is not recognized or TEST SNDU; discard.
- */
-static int handle_one_ule_extension( struct dvb_net_priv *p )
-{
-	/* Table of mandatory extension header handlers.  The header type is the index. */
-	static int (*ule_mandatory_ext_handlers[255])( struct dvb_net_priv *p ) =
-		{ [0] = ule_test_sndu, [1] = ule_bridged_sndu, [2] = NULL,  };
-
-	/* Table of optional extension header handlers.  The header type is the index. */
-	static int (*ule_optional_ext_handlers[255])( struct dvb_net_priv *p ) =
-		{ [0] = ule_exthdr_padding, [1] = NULL, };
-
-	int ext_len = 0;
-	unsigned char hlen = (p->ule_sndu_type & 0x0700) >> 8;
-	unsigned char htype = p->ule_sndu_type & 0x00FF;
-
-	/* Discriminate mandatory and optional extension headers. */
-	if (hlen == 0) {
-		/* Mandatory extension header */
-		if (ule_mandatory_ext_handlers[htype]) {
-			ext_len = ule_mandatory_ext_handlers[htype]( p );
-			if(ext_len >= 0) {
-				p->ule_next_hdr += ext_len;
-				if (!p->ule_bridged) {
-					p->ule_sndu_type = ntohs(*(__be16 *)p->ule_next_hdr);
-					p->ule_next_hdr += 2;
-				} else {
-					p->ule_sndu_type = ntohs(*(__be16 *)(p->ule_next_hdr + ((p->ule_dbit ? 2 : 3) * ETH_ALEN)));
-					/* This assures the extension handling loop will terminate. */
-				}
-			}
-			// else: extension handler failed or SNDU should be discarded
-		} else
-			ext_len = -1;	/* SNDU has to be discarded. */
-	} else {
-		/* Optional extension header.  Calculate the length. */
-		ext_len = hlen << 1;
-		/* Process the optional extension header according to its type. */
-		if (ule_optional_ext_handlers[htype])
-			(void)ule_optional_ext_handlers[htype]( p );
-		p->ule_next_hdr += ext_len;
-		p->ule_sndu_type = ntohs( *(__be16 *)(p->ule_next_hdr-2) );
-		/*
-		 * note: the length of the next header type is included in the
-		 * length of THIS optional extension header
-		 */
-	}
-
-	return ext_len;
-}
-
-static int handle_ule_extensions( struct dvb_net_priv *p )
-{
-	int total_ext_len = 0, l;
-
-	p->ule_next_hdr = p->ule_skb->data;
-	do {
-		l = handle_one_ule_extension( p );
-		if (l < 0)
-			return l;	/* Stop extension header processing and discard SNDU. */
-		total_ext_len += l;
-#ifdef ULE_DEBUG
-		dprintk("handle_ule_extensions: ule_next_hdr=%p, ule_sndu_type=%i, "
-			"l=%i, total_ext_len=%i\n", p->ule_next_hdr,
-			(int) p->ule_sndu_type, l, total_ext_len);
-#endif
-
-	} while (p->ule_sndu_type < 1536);
-
-	return total_ext_len;
-}
-
-
-/** Prepare for a new ULE SNDU: reset the decoder state. */
-static inline void reset_ule( struct dvb_net_priv *p )
-{
-	p->ule_skb = NULL;
-	p->ule_next_hdr = NULL;
-	p->ule_sndu_len = 0;
-	p->ule_sndu_type = 0;
-	p->ule_sndu_type_1 = 0;
-	p->ule_sndu_remain = 0;
-	p->ule_dbit = 0xFF;
-	p->ule_bridged = 0;
-}
-
-/**
- * Decode ULE SNDUs according to draft-ietf-ipdvb-ule-03.txt from a sequence of
- * TS cells of a single PID.
- */
-static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
-{
-	struct dvb_net_priv *priv = netdev_priv(dev);
-	unsigned long skipped = 0L;
-	const u8 *ts, *ts_end, *from_where = NULL;
-	u8 ts_remain = 0, how_much = 0, new_ts = 1;
-	struct ethhdr *ethh = NULL;
-	bool error = false;
-
-#ifdef ULE_DEBUG
-	/* The code inside ULE_DEBUG keeps a history of the last 100 TS cells processed. */
-	static unsigned char ule_hist[100*TS_SZ];
-	static unsigned char *ule_where = ule_hist, ule_dump;
-#endif
-
-	/* For all TS cells in current buffer.
-	 * Appearently, we are called for every single TS cell.
-	 */
-	for (ts = buf, ts_end = buf + buf_len; ts < ts_end; /* no default incr. */ ) {
-
-		if (new_ts) {
-			/* We are about to process a new TS cell. */
-
-#ifdef ULE_DEBUG
-			if (ule_where >= &ule_hist[100*TS_SZ]) ule_where = ule_hist;
-			memcpy( ule_where, ts, TS_SZ );
-			if (ule_dump) {
-				hexdump( ule_where, TS_SZ );
-				ule_dump = 0;
-			}
-			ule_where += TS_SZ;
-#endif
-
-			/* Check TS error conditions: sync_byte, transport_error_indicator, scrambling_control . */
-			if ((ts[0] != TS_SYNC) || (ts[1] & TS_TEI) || ((ts[3] & TS_SC) != 0)) {
-				printk(KERN_WARNING "%lu: Invalid TS cell: SYNC %#x, TEI %u, SC %#x.\n",
-				       priv->ts_count, ts[0], ts[1] & TS_TEI >> 7, ts[3] & 0xC0 >> 6);
-
-				/* Drop partly decoded SNDU, reset state, resync on PUSI. */
-				if (priv->ule_skb) {
-					dev_kfree_skb( priv->ule_skb );
-					/* Prepare for next SNDU. */
-					dev->stats.rx_errors++;
-					dev->stats.rx_frame_errors++;
-				}
-				reset_ule(priv);
-				priv->need_pusi = 1;
-
-				/* Continue with next TS cell. */
-				ts += TS_SZ;
-				priv->ts_count++;
-				continue;
-			}
-
-			ts_remain = 184;
-			from_where = ts + 4;
-		}
-		/* Synchronize on PUSI, if required. */
-		if (priv->need_pusi) {
-			if (ts[1] & TS_PUSI) {
-				/* Find beginning of first ULE SNDU in current TS cell. */
-				/* Synchronize continuity counter. */
-				priv->tscc = ts[3] & 0x0F;
-				/* There is a pointer field here. */
-				if (ts[4] > ts_remain) {
-					printk(KERN_ERR "%lu: Invalid ULE packet "
-					       "(pointer field %d)\n", priv->ts_count, ts[4]);
-					ts += TS_SZ;
-					priv->ts_count++;
-					continue;
-				}
-				/* Skip to destination of pointer field. */
-				from_where = &ts[5] + ts[4];
-				ts_remain -= 1 + ts[4];
-				skipped = 0;
-			} else {
-				skipped++;
-				ts += TS_SZ;
-				priv->ts_count++;
-				continue;
-			}
-		}
-
-		if (new_ts) {
-			/* Check continuity counter. */
-			if ((ts[3] & 0x0F) == priv->tscc)
-				priv->tscc = (priv->tscc + 1) & 0x0F;
-			else {
-				/* TS discontinuity handling: */
-				printk(KERN_WARNING "%lu: TS discontinuity: got %#x, "
-				       "expected %#x.\n", priv->ts_count, ts[3] & 0x0F, priv->tscc);
-				/* Drop partly decoded SNDU, reset state, resync on PUSI. */
-				if (priv->ule_skb) {
-					dev_kfree_skb( priv->ule_skb );
-					/* Prepare for next SNDU. */
-					// reset_ule(priv);  moved to below.
-					dev->stats.rx_errors++;
-					dev->stats.rx_frame_errors++;
-				}
-				reset_ule(priv);
-				/* skip to next PUSI. */
-				priv->need_pusi = 1;
-				continue;
-			}
-			/* If we still have an incomplete payload, but PUSI is
-			 * set; some TS cells are missing.
-			 * This is only possible here, if we missed exactly 16 TS
-			 * cells (continuity counter wrap). */
-			if (ts[1] & TS_PUSI) {
-				if (! priv->need_pusi) {
-					if (!(*from_where < (ts_remain-1)) || *from_where != priv->ule_sndu_remain) {
-						/* Pointer field is invalid.  Drop this TS cell and any started ULE SNDU. */
-						printk(KERN_WARNING "%lu: Invalid pointer "
-						       "field: %u.\n", priv->ts_count, *from_where);
-
-						/* Drop partly decoded SNDU, reset state, resync on PUSI. */
-						if (priv->ule_skb) {
-							error = true;
-							dev_kfree_skb(priv->ule_skb);
-						}
-
-						if (error || priv->ule_sndu_remain) {
-							dev->stats.rx_errors++;
-							dev->stats.rx_frame_errors++;
-							error = false;
-						}
-
-						reset_ule(priv);
-						priv->need_pusi = 1;
-						continue;
-					}
-					/* Skip pointer field (we're processing a
-					 * packed payload). */
-					from_where += 1;
-					ts_remain -= 1;
-				} else
-					priv->need_pusi = 0;
-
-				if (priv->ule_sndu_remain > 183) {
-					/* Current SNDU lacks more data than there could be available in the
-					 * current TS cell. */
-					dev->stats.rx_errors++;
-					dev->stats.rx_length_errors++;
-					printk(KERN_WARNING "%lu: Expected %d more SNDU bytes, but "
-					       "got PUSI (pf %d, ts_remain %d).  Flushing incomplete payload.\n",
-					       priv->ts_count, priv->ule_sndu_remain, ts[4], ts_remain);
-					dev_kfree_skb(priv->ule_skb);
-					/* Prepare for next SNDU. */
-					reset_ule(priv);
-					/* Resync: go to where pointer field points to: start of next ULE SNDU. */
-					from_where += ts[4];
-					ts_remain -= ts[4];
-				}
-			}
-		}
-
-		/* Check if new payload needs to be started. */
-		if (priv->ule_skb == NULL) {
-			/* Start a new payload with skb.
-			 * Find ULE header.  It is only guaranteed that the
-			 * length field (2 bytes) is contained in the current
-			 * TS.
-			 * Check ts_remain has to be >= 2 here. */
-			if (ts_remain < 2) {
-				printk(KERN_WARNING "Invalid payload packing: only %d "
-				       "bytes left in TS.  Resyncing.\n", ts_remain);
-				priv->ule_sndu_len = 0;
-				priv->need_pusi = 1;
-				ts += TS_SZ;
-				continue;
-			}
-
-			if (! priv->ule_sndu_len) {
-				/* Got at least two bytes, thus extrace the SNDU length. */
-				priv->ule_sndu_len = from_where[0] << 8 | from_where[1];
-				if (priv->ule_sndu_len & 0x8000) {
-					/* D-Bit is set: no dest mac present. */
-					priv->ule_sndu_len &= 0x7FFF;
-					priv->ule_dbit = 1;
-				} else
-					priv->ule_dbit = 0;
-
-				if (priv->ule_sndu_len < 5) {
-					printk(KERN_WARNING "%lu: Invalid ULE SNDU length %u. "
-					       "Resyncing.\n", priv->ts_count, priv->ule_sndu_len);
-					dev->stats.rx_errors++;
-					dev->stats.rx_length_errors++;
-					priv->ule_sndu_len = 0;
-					priv->need_pusi = 1;
-					new_ts = 1;
-					ts += TS_SZ;
-					priv->ts_count++;
-					continue;
-				}
-				ts_remain -= 2;	/* consume the 2 bytes SNDU length. */
-				from_where += 2;
-			}
-
-			priv->ule_sndu_remain = priv->ule_sndu_len + 2;
-			/*
-			 * State of current TS:
-			 *   ts_remain (remaining bytes in the current TS cell)
-			 *   0	ule_type is not available now, we need the next TS cell
-			 *   1	the first byte of the ule_type is present
-			 * >=2	full ULE header present, maybe some payload data as well.
-			 */
-			switch (ts_remain) {
-				case 1:
-					priv->ule_sndu_remain--;
-					priv->ule_sndu_type = from_where[0] << 8;
-					priv->ule_sndu_type_1 = 1; /* first byte of ule_type is set. */
-					ts_remain -= 1; from_where += 1;
-					/* Continue w/ next TS. */
-				case 0:
-					new_ts = 1;
-					ts += TS_SZ;
-					priv->ts_count++;
-					continue;
-
-				default: /* complete ULE header is present in current TS. */
-					/* Extract ULE type field. */
-					if (priv->ule_sndu_type_1) {
-						priv->ule_sndu_type_1 = 0;
-						priv->ule_sndu_type |= from_where[0];
-						from_where += 1; /* points to payload start. */
-						ts_remain -= 1;
-					} else {
-						/* Complete type is present in new TS. */
-						priv->ule_sndu_type = from_where[0] << 8 | from_where[1];
-						from_where += 2; /* points to payload start. */
-						ts_remain -= 2;
-					}
-					break;
-			}
-
-			/* Allocate the skb (decoder target buffer) with the correct size, as follows:
-			 * prepare for the largest case: bridged SNDU with MAC address (dbit = 0). */
-			priv->ule_skb = dev_alloc_skb( priv->ule_sndu_len + ETH_HLEN + ETH_ALEN );
-			if (priv->ule_skb == NULL) {
-				printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n",
-				       dev->name);
-				dev->stats.rx_dropped++;
-				return;
-			}
-
-			/* This includes the CRC32 _and_ dest mac, if !dbit. */
-			priv->ule_sndu_remain = priv->ule_sndu_len;
-			priv->ule_skb->dev = dev;
-			/* Leave space for Ethernet or bridged SNDU header (eth hdr plus one MAC addr). */
-			skb_reserve( priv->ule_skb, ETH_HLEN + ETH_ALEN );
-		}
-
-		/* Copy data into our current skb. */
-		how_much = min(priv->ule_sndu_remain, (int)ts_remain);
-		memcpy(skb_put(priv->ule_skb, how_much), from_where, how_much);
-		priv->ule_sndu_remain -= how_much;
-		ts_remain -= how_much;
-		from_where += how_much;
-
-		/* Check for complete payload. */
-		if (priv->ule_sndu_remain <= 0) {
-			/* Check CRC32, we've got it in our skb already. */
-			__be16 ulen = htons(priv->ule_sndu_len);
-			__be16 utype = htons(priv->ule_sndu_type);
-			const u8 *tail;
-			struct kvec iov[3] = {
-				{ &ulen, sizeof ulen },
-				{ &utype, sizeof utype },
-				{ priv->ule_skb->data, priv->ule_skb->len - 4 }
-			};
-			u32 ule_crc = ~0L, expected_crc;
-			if (priv->ule_dbit) {
-				/* Set D-bit for CRC32 verification,
-				 * if it was set originally. */
-				ulen |= htons(0x8000);
-			}
-
-			ule_crc = iov_crc32(ule_crc, iov, 3);
-			tail = skb_tail_pointer(priv->ule_skb);
-			expected_crc = *(tail - 4) << 24 |
-				       *(tail - 3) << 16 |
-				       *(tail - 2) << 8 |
-				       *(tail - 1);
-			if (ule_crc != expected_crc) {
-				printk(KERN_WARNING "%lu: CRC32 check FAILED: %08x / %08x, SNDU len %d type %#x, ts_remain %d, next 2: %x.\n",
-				       priv->ts_count, ule_crc, expected_crc, priv->ule_sndu_len, priv->ule_sndu_type, ts_remain, ts_remain > 2 ? *(unsigned short *)from_where : 0);
-
-#ifdef ULE_DEBUG
-				hexdump( iov[0].iov_base, iov[0].iov_len );
-				hexdump( iov[1].iov_base, iov[1].iov_len );
-				hexdump( iov[2].iov_base, iov[2].iov_len );
-
-				if (ule_where == ule_hist) {
-					hexdump( &ule_hist[98*TS_SZ], TS_SZ );
-					hexdump( &ule_hist[99*TS_SZ], TS_SZ );
-				} else if (ule_where == &ule_hist[TS_SZ]) {
-					hexdump( &ule_hist[99*TS_SZ], TS_SZ );
-					hexdump( ule_hist, TS_SZ );
-				} else {
-					hexdump( ule_where - TS_SZ - TS_SZ, TS_SZ );
-					hexdump( ule_where - TS_SZ, TS_SZ );
-				}
-				ule_dump = 1;
-#endif
-
-				dev->stats.rx_errors++;
-				dev->stats.rx_crc_errors++;
-				dev_kfree_skb(priv->ule_skb);
-			} else {
-				/* CRC32 verified OK. */
-				u8 dest_addr[ETH_ALEN];
-				static const u8 bc_addr[ETH_ALEN] =
-					{ [ 0 ... ETH_ALEN-1] = 0xff };
-
-				/* CRC32 was OK. Remove it from skb. */
-				priv->ule_skb->tail -= 4;
-				priv->ule_skb->len -= 4;
-
-				if (!priv->ule_dbit) {
-					/*
-					 * The destination MAC address is the
-					 * next data in the skb.  It comes
-					 * before any extension headers.
-					 *
-					 * Check if the payload of this SNDU
-					 * should be passed up the stack.
-					 */
-					register int drop = 0;
-					if (priv->rx_mode != RX_MODE_PROMISC) {
-						if (priv->ule_skb->data[0] & 0x01) {
-							/* multicast or broadcast */
-							if (memcmp(priv->ule_skb->data, bc_addr, ETH_ALEN)) {
-								/* multicast */
-								if (priv->rx_mode == RX_MODE_MULTI) {
-									int i;
-									for(i = 0; i < priv->multi_num && memcmp(priv->ule_skb->data, priv->multi_macs[i], ETH_ALEN); i++)
-										;
-									if (i == priv->multi_num)
-										drop = 1;
-								} else if (priv->rx_mode != RX_MODE_ALL_MULTI)
-									drop = 1; /* no broadcast; */
-								/* else: all multicast mode: accept all multicast packets */
-							}
-							/* else: broadcast */
-						}
-						else if (memcmp(priv->ule_skb->data, dev->dev_addr, ETH_ALEN))
-							drop = 1;
-						/* else: destination address matches the MAC address of our receiver device */
-					}
-					/* else: promiscuous mode; pass everything up the stack */
-
-					if (drop) {
-#ifdef ULE_DEBUG
-						dprintk("Dropping SNDU: MAC destination address does not match: dest addr: "MAC_ADDR_PRINTFMT", dev addr: "MAC_ADDR_PRINTFMT"\n",
-							MAX_ADDR_PRINTFMT_ARGS(priv->ule_skb->data), MAX_ADDR_PRINTFMT_ARGS(dev->dev_addr));
-#endif
-						dev_kfree_skb(priv->ule_skb);
-						goto sndu_done;
-					}
-					else
-					{
-						skb_copy_from_linear_data(priv->ule_skb,
-							      dest_addr,
-							      ETH_ALEN);
-						skb_pull(priv->ule_skb, ETH_ALEN);
-					}
-				}
-
-				/* Handle ULE Extension Headers. */
-				if (priv->ule_sndu_type < 1536) {
-					/* There is an extension header.  Handle it accordingly. */
-					int l = handle_ule_extensions(priv);
-					if (l < 0) {
-						/* Mandatory extension header unknown or TEST SNDU.  Drop it. */
-						// printk( KERN_WARNING "Dropping SNDU, extension headers.\n" );
-						dev_kfree_skb(priv->ule_skb);
-						goto sndu_done;
-					}
-					skb_pull(priv->ule_skb, l);
-				}
-
-				/*
-				 * Construct/assure correct ethernet header.
-				 * Note: in bridged mode (priv->ule_bridged !=
-				 * 0) we already have the (original) ethernet
-				 * header at the start of the payload (after
-				 * optional dest. address and any extension
-				 * headers).
-				 */
-
-				if (!priv->ule_bridged) {
-					skb_push(priv->ule_skb, ETH_HLEN);
-					ethh = (struct ethhdr *)priv->ule_skb->data;
-					if (!priv->ule_dbit) {
-						 /* dest_addr buffer is only valid if priv->ule_dbit == 0 */
-						memcpy(ethh->h_dest, dest_addr, ETH_ALEN);
-						memset(ethh->h_source, 0, ETH_ALEN);
-					}
-					else /* zeroize source and dest */
-						memset( ethh, 0, ETH_ALEN*2 );
-
-					ethh->h_proto = htons(priv->ule_sndu_type);
-				}
-				/* else:  skb is in correct state; nothing to do. */
-				priv->ule_bridged = 0;
-
-				/* Stuff into kernel's protocol stack. */
-				priv->ule_skb->protocol = dvb_net_eth_type_trans(priv->ule_skb, dev);
-				/* If D-bit is set (i.e. destination MAC address not present),
-				 * receive the packet anyhow. */
-				/* if (priv->ule_dbit && skb->pkt_type == PACKET_OTHERHOST)
-					priv->ule_skb->pkt_type = PACKET_HOST; */
-				dev->stats.rx_packets++;
-				dev->stats.rx_bytes += priv->ule_skb->len;
-				netif_rx(priv->ule_skb);
-			}
-			sndu_done:
-			/* Prepare for next SNDU. */
-			reset_ule(priv);
-		}
-
-		/* More data in current TS (look at the bytes following the CRC32)? */
-		if (ts_remain >= 2 && *((unsigned short *)from_where) != 0xFFFF) {
-			/* Next ULE SNDU starts right there. */
-			new_ts = 0;
-			priv->ule_skb = NULL;
-			priv->ule_sndu_type_1 = 0;
-			priv->ule_sndu_len = 0;
-			// printk(KERN_WARNING "More data in current TS: [%#x %#x %#x %#x]\n",
-			//	*(from_where + 0), *(from_where + 1),
-			//	*(from_where + 2), *(from_where + 3));
-			// printk(KERN_WARNING "ts @ %p, stopped @ %p:\n", ts, from_where + 0);
-			// hexdump(ts, 188);
-		} else {
-			new_ts = 1;
-			ts += TS_SZ;
-			priv->ts_count++;
-			if (priv->ule_skb == NULL) {
-				priv->need_pusi = 1;
-				priv->ule_sndu_type_1 = 0;
-				priv->ule_sndu_len = 0;
-			}
-		}
-	}	/* for all available TS cells */
-}
-
-static int dvb_net_ts_callback(const u8 *buffer1, size_t buffer1_len,
-			       const u8 *buffer2, size_t buffer2_len,
-			       struct dmx_ts_feed *feed, enum dmx_success success)
-{
-	struct net_device *dev = feed->priv;
-
-	if (buffer2)
-		printk(KERN_WARNING "buffer2 not NULL: %p.\n", buffer2);
-	if (buffer1_len > 32768)
-		printk(KERN_WARNING "length > 32k: %zu.\n", buffer1_len);
-	/* printk("TS callback: %u bytes, %u TS cells @ %p.\n",
-		  buffer1_len, buffer1_len / TS_SZ, buffer1); */
-	dvb_net_ule(dev, buffer1, buffer1_len);
-	return 0;
-}
-
-
-static void dvb_net_sec(struct net_device *dev,
-			const u8 *pkt, int pkt_len)
-{
-	u8 *eth;
-	struct sk_buff *skb;
-	struct net_device_stats *stats = &dev->stats;
-	int snap = 0;
-
-	/* note: pkt_len includes a 32bit checksum */
-	if (pkt_len < 16) {
-		printk("%s: IP/MPE packet length = %d too small.\n",
-			dev->name, pkt_len);
-		stats->rx_errors++;
-		stats->rx_length_errors++;
-		return;
-	}
-/* it seems some ISPs manage to screw up here, so we have to
- * relax the error checks... */
-#if 0
-	if ((pkt[5] & 0xfd) != 0xc1) {
-		/* drop scrambled or broken packets */
-#else
-	if ((pkt[5] & 0x3c) != 0x00) {
-		/* drop scrambled */
-#endif
-		stats->rx_errors++;
-		stats->rx_crc_errors++;
-		return;
-	}
-	if (pkt[5] & 0x02) {
-		/* handle LLC/SNAP, see rfc-1042 */
-		if (pkt_len < 24 || memcmp(&pkt[12], "\xaa\xaa\x03\0\0\0", 6)) {
-			stats->rx_dropped++;
-			return;
-		}
-		snap = 8;
-	}
-	if (pkt[7]) {
-		/* FIXME: assemble datagram from multiple sections */
-		stats->rx_errors++;
-		stats->rx_frame_errors++;
-		return;
-	}
-
-	/* we have 14 byte ethernet header (ip header follows);
-	 * 12 byte MPE header; 4 byte checksum; + 2 byte alignment, 8 byte LLC/SNAP
-	 */
-	if (!(skb = dev_alloc_skb(pkt_len - 4 - 12 + 14 + 2 - snap))) {
-		//printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name);
-		stats->rx_dropped++;
-		return;
-	}
-	skb_reserve(skb, 2);    /* longword align L3 header */
-	skb->dev = dev;
-
-	/* copy L3 payload */
-	eth = (u8 *) skb_put(skb, pkt_len - 12 - 4 + 14 - snap);
-	memcpy(eth + 14, pkt + 12 + snap, pkt_len - 12 - 4 - snap);
-
-	/* create ethernet header: */
-	eth[0]=pkt[0x0b];
-	eth[1]=pkt[0x0a];
-	eth[2]=pkt[0x09];
-	eth[3]=pkt[0x08];
-	eth[4]=pkt[0x04];
-	eth[5]=pkt[0x03];
-
-	eth[6]=eth[7]=eth[8]=eth[9]=eth[10]=eth[11]=0;
-
-	if (snap) {
-		eth[12] = pkt[18];
-		eth[13] = pkt[19];
-	} else {
-		/* protocol numbers are from rfc-1700 or
-		 * http://www.iana.org/assignments/ethernet-numbers
-		 */
-		if (pkt[12] >> 4 == 6) { /* version field from IP header */
-			eth[12] = 0x86;	/* IPv6 */
-			eth[13] = 0xdd;
-		} else {
-			eth[12] = 0x08;	/* IPv4 */
-			eth[13] = 0x00;
-		}
-	}
-
-	skb->protocol = dvb_net_eth_type_trans(skb, dev);
-
-	stats->rx_packets++;
-	stats->rx_bytes+=skb->len;
-	netif_rx(skb);
-}
-
-static int dvb_net_sec_callback(const u8 *buffer1, size_t buffer1_len,
-		 const u8 *buffer2, size_t buffer2_len,
-		 struct dmx_section_filter *filter,
-		 enum dmx_success success)
-{
-	struct net_device *dev = filter->priv;
-
-	/**
-	 * we rely on the DVB API definition where exactly one complete
-	 * section is delivered in buffer1
-	 */
-	dvb_net_sec (dev, buffer1, buffer1_len);
-	return 0;
-}
-
-static int dvb_net_tx(struct sk_buff *skb, struct net_device *dev)
-{
-	dev_kfree_skb(skb);
-	return NETDEV_TX_OK;
-}
-
-static u8 mask_normal[6]={0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
-static u8 mask_allmulti[6]={0xff, 0xff, 0xff, 0x00, 0x00, 0x00};
-static u8 mac_allmulti[6]={0x01, 0x00, 0x5e, 0x00, 0x00, 0x00};
-static u8 mask_promisc[6]={0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-
-static int dvb_net_filter_sec_set(struct net_device *dev,
-		   struct dmx_section_filter **secfilter,
-		   u8 *mac, u8 *mac_mask)
-{
-	struct dvb_net_priv *priv = netdev_priv(dev);
-	int ret;
-
-	*secfilter=NULL;
-	ret = priv->secfeed->allocate_filter(priv->secfeed, secfilter);
-	if (ret<0) {
-		printk("%s: could not get filter\n", dev->name);
-		return ret;
-	}
-
-	(*secfilter)->priv=(void *) dev;
-
-	memset((*secfilter)->filter_value, 0x00, DMX_MAX_FILTER_SIZE);
-	memset((*secfilter)->filter_mask,  0x00, DMX_MAX_FILTER_SIZE);
-	memset((*secfilter)->filter_mode,  0xff, DMX_MAX_FILTER_SIZE);
-
-	(*secfilter)->filter_value[0]=0x3e;
-	(*secfilter)->filter_value[3]=mac[5];
-	(*secfilter)->filter_value[4]=mac[4];
-	(*secfilter)->filter_value[8]=mac[3];
-	(*secfilter)->filter_value[9]=mac[2];
-	(*secfilter)->filter_value[10]=mac[1];
-	(*secfilter)->filter_value[11]=mac[0];
-
-	(*secfilter)->filter_mask[0] = 0xff;
-	(*secfilter)->filter_mask[3] = mac_mask[5];
-	(*secfilter)->filter_mask[4] = mac_mask[4];
-	(*secfilter)->filter_mask[8] = mac_mask[3];
-	(*secfilter)->filter_mask[9] = mac_mask[2];
-	(*secfilter)->filter_mask[10] = mac_mask[1];
-	(*secfilter)->filter_mask[11]=mac_mask[0];
-
-	dprintk("%s: filter mac=%pM\n", dev->name, mac);
-	dprintk("%s: filter mask=%pM\n", dev->name, mac_mask);
-
-	return 0;
-}
-
-static int dvb_net_feed_start(struct net_device *dev)
-{
-	int ret = 0, i;
-	struct dvb_net_priv *priv = netdev_priv(dev);
-	struct dmx_demux *demux = priv->demux;
-	unsigned char *mac = (unsigned char *) dev->dev_addr;
-
-	dprintk("%s: rx_mode %i\n", __func__, priv->rx_mode);
-	mutex_lock(&priv->mutex);
-	if (priv->tsfeed || priv->secfeed || priv->secfilter || priv->multi_secfilter[0])
-		printk("%s: BUG %d\n", __func__, __LINE__);
-
-	priv->secfeed=NULL;
-	priv->secfilter=NULL;
-	priv->tsfeed = NULL;
-
-	if (priv->feedtype == DVB_NET_FEEDTYPE_MPE) {
-		dprintk("%s: alloc secfeed\n", __func__);
-		ret=demux->allocate_section_feed(demux, &priv->secfeed,
-					 dvb_net_sec_callback);
-		if (ret<0) {
-			printk("%s: could not allocate section feed\n", dev->name);
-			goto error;
-		}
-
-		ret = priv->secfeed->set(priv->secfeed, priv->pid, 32768, 1);
-
-		if (ret<0) {
-			printk("%s: could not set section feed\n", dev->name);
-			priv->demux->release_section_feed(priv->demux, priv->secfeed);
-			priv->secfeed=NULL;
-			goto error;
-		}
-
-		if (priv->rx_mode != RX_MODE_PROMISC) {
-			dprintk("%s: set secfilter\n", __func__);
-			dvb_net_filter_sec_set(dev, &priv->secfilter, mac, mask_normal);
-		}
-
-		switch (priv->rx_mode) {
-		case RX_MODE_MULTI:
-			for (i = 0; i < priv->multi_num; i++) {
-				dprintk("%s: set multi_secfilter[%d]\n", __func__, i);
-				dvb_net_filter_sec_set(dev, &priv->multi_secfilter[i],
-						       priv->multi_macs[i], mask_normal);
-			}
-			break;
-		case RX_MODE_ALL_MULTI:
-			priv->multi_num=1;
-			dprintk("%s: set multi_secfilter[0]\n", __func__);
-			dvb_net_filter_sec_set(dev, &priv->multi_secfilter[0],
-					       mac_allmulti, mask_allmulti);
-			break;
-		case RX_MODE_PROMISC:
-			priv->multi_num=0;
-			dprintk("%s: set secfilter\n", __func__);
-			dvb_net_filter_sec_set(dev, &priv->secfilter, mac, mask_promisc);
-			break;
-		}
-
-		dprintk("%s: start filtering\n", __func__);
-		priv->secfeed->start_filtering(priv->secfeed);
-	} else if (priv->feedtype == DVB_NET_FEEDTYPE_ULE) {
-		struct timespec timeout = { 0, 10000000 }; // 10 msec
-
-		/* we have payloads encapsulated in TS */
-		dprintk("%s: alloc tsfeed\n", __func__);
-		ret = demux->allocate_ts_feed(demux, &priv->tsfeed, dvb_net_ts_callback);
-		if (ret < 0) {
-			printk("%s: could not allocate ts feed\n", dev->name);
-			goto error;
-		}
-
-		/* Set netdevice pointer for ts decaps callback. */
-		priv->tsfeed->priv = (void *)dev;
-		ret = priv->tsfeed->set(priv->tsfeed,
-					priv->pid, /* pid */
-					TS_PACKET, /* type */
-					DMX_TS_PES_OTHER, /* pes type */
-					32768,     /* circular buffer size */
-					timeout    /* timeout */
-					);
-
-		if (ret < 0) {
-			printk("%s: could not set ts feed\n", dev->name);
-			priv->demux->release_ts_feed(priv->demux, priv->tsfeed);
-			priv->tsfeed = NULL;
-			goto error;
-		}
-
-		dprintk("%s: start filtering\n", __func__);
-		priv->tsfeed->start_filtering(priv->tsfeed);
-	} else
-		ret = -EINVAL;
-
-error:
-	mutex_unlock(&priv->mutex);
-	return ret;
-}
-
-static int dvb_net_feed_stop(struct net_device *dev)
-{
-	struct dvb_net_priv *priv = netdev_priv(dev);
-	int i, ret = 0;
-
-	dprintk("%s\n", __func__);
-	mutex_lock(&priv->mutex);
-	if (priv->feedtype == DVB_NET_FEEDTYPE_MPE) {
-		if (priv->secfeed) {
-			if (priv->secfeed->is_filtering) {
-				dprintk("%s: stop secfeed\n", __func__);
-				priv->secfeed->stop_filtering(priv->secfeed);
-			}
-
-			if (priv->secfilter) {
-				dprintk("%s: release secfilter\n", __func__);
-				priv->secfeed->release_filter(priv->secfeed,
-							      priv->secfilter);
-				priv->secfilter=NULL;
-			}
-
-			for (i=0; i<priv->multi_num; i++) {
-				if (priv->multi_secfilter[i]) {
-					dprintk("%s: release multi_filter[%d]\n",
-						__func__, i);
-					priv->secfeed->release_filter(priv->secfeed,
-								      priv->multi_secfilter[i]);
-					priv->multi_secfilter[i] = NULL;
-				}
-			}
-
-			priv->demux->release_section_feed(priv->demux, priv->secfeed);
-			priv->secfeed = NULL;
-		} else
-			printk("%s: no feed to stop\n", dev->name);
-	} else if (priv->feedtype == DVB_NET_FEEDTYPE_ULE) {
-		if (priv->tsfeed) {
-			if (priv->tsfeed->is_filtering) {
-				dprintk("%s: stop tsfeed\n", __func__);
-				priv->tsfeed->stop_filtering(priv->tsfeed);
-			}
-			priv->demux->release_ts_feed(priv->demux, priv->tsfeed);
-			priv->tsfeed = NULL;
-		}
-		else
-			printk("%s: no ts feed to stop\n", dev->name);
-	} else
-		ret = -EINVAL;
-	mutex_unlock(&priv->mutex);
-	return ret;
-}
-
-
-static int dvb_set_mc_filter(struct net_device *dev, unsigned char *addr)
-{
-	struct dvb_net_priv *priv = netdev_priv(dev);
-
-	if (priv->multi_num == DVB_NET_MULTICAST_MAX)
-		return -ENOMEM;
-
-	memcpy(priv->multi_macs[priv->multi_num], addr, ETH_ALEN);
-
-	priv->multi_num++;
-	return 0;
-}
-
-
-static void wq_set_multicast_list (struct work_struct *work)
-{
-	struct dvb_net_priv *priv =
-		container_of(work, struct dvb_net_priv, set_multicast_list_wq);
-	struct net_device *dev = priv->net;
-
-	dvb_net_feed_stop(dev);
-	priv->rx_mode = RX_MODE_UNI;
-	netif_addr_lock_bh(dev);
-
-	if (dev->flags & IFF_PROMISC) {
-		dprintk("%s: promiscuous mode\n", dev->name);
-		priv->rx_mode = RX_MODE_PROMISC;
-	} else if ((dev->flags & IFF_ALLMULTI)) {
-		dprintk("%s: allmulti mode\n", dev->name);
-		priv->rx_mode = RX_MODE_ALL_MULTI;
-	} else if (!netdev_mc_empty(dev)) {
-		struct netdev_hw_addr *ha;
-
-		dprintk("%s: set_mc_list, %d entries\n",
-			dev->name, netdev_mc_count(dev));
-
-		priv->rx_mode = RX_MODE_MULTI;
-		priv->multi_num = 0;
-
-		netdev_for_each_mc_addr(ha, dev)
-			dvb_set_mc_filter(dev, ha->addr);
-	}
-
-	netif_addr_unlock_bh(dev);
-	dvb_net_feed_start(dev);
-}
-
-
-static void dvb_net_set_multicast_list (struct net_device *dev)
-{
-	struct dvb_net_priv *priv = netdev_priv(dev);
-	schedule_work(&priv->set_multicast_list_wq);
-}
-
-
-static void wq_restart_net_feed (struct work_struct *work)
-{
-	struct dvb_net_priv *priv =
-		container_of(work, struct dvb_net_priv, restart_net_feed_wq);
-	struct net_device *dev = priv->net;
-
-	if (netif_running(dev)) {
-		dvb_net_feed_stop(dev);
-		dvb_net_feed_start(dev);
-	}
-}
-
-
-static int dvb_net_set_mac (struct net_device *dev, void *p)
-{
-	struct dvb_net_priv *priv = netdev_priv(dev);
-	struct sockaddr *addr=p;
-
-	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
-
-	if (netif_running(dev))
-		schedule_work(&priv->restart_net_feed_wq);
-
-	return 0;
-}
-
-
-static int dvb_net_open(struct net_device *dev)
-{
-	struct dvb_net_priv *priv = netdev_priv(dev);
-
-	priv->in_use++;
-	dvb_net_feed_start(dev);
-	return 0;
-}
-
-
-static int dvb_net_stop(struct net_device *dev)
-{
-	struct dvb_net_priv *priv = netdev_priv(dev);
-
-	priv->in_use--;
-	return dvb_net_feed_stop(dev);
-}
-
-static const struct header_ops dvb_header_ops = {
-	.create		= eth_header,
-	.parse		= eth_header_parse,
-	.rebuild	= eth_rebuild_header,
-};
-
-
-static const struct net_device_ops dvb_netdev_ops = {
-	.ndo_open		= dvb_net_open,
-	.ndo_stop		= dvb_net_stop,
-	.ndo_start_xmit		= dvb_net_tx,
-	.ndo_set_rx_mode	= dvb_net_set_multicast_list,
-	.ndo_set_mac_address    = dvb_net_set_mac,
-	.ndo_change_mtu		= eth_change_mtu,
-	.ndo_validate_addr	= eth_validate_addr,
-};
-
-static void dvb_net_setup(struct net_device *dev)
-{
-	ether_setup(dev);
-
-	dev->header_ops		= &dvb_header_ops;
-	dev->netdev_ops		= &dvb_netdev_ops;
-	dev->mtu		= 4096;
-
-	dev->flags |= IFF_NOARP;
-}
-
-static int get_if(struct dvb_net *dvbnet)
-{
-	int i;
-
-	for (i=0; i<DVB_NET_DEVICES_MAX; i++)
-		if (!dvbnet->state[i])
-			break;
-
-	if (i == DVB_NET_DEVICES_MAX)
-		return -1;
-
-	dvbnet->state[i]=1;
-	return i;
-}
-
-static int dvb_net_add_if(struct dvb_net *dvbnet, u16 pid, u8 feedtype)
-{
-	struct net_device *net;
-	struct dvb_net_priv *priv;
-	int result;
-	int if_num;
-
-	if (feedtype != DVB_NET_FEEDTYPE_MPE && feedtype != DVB_NET_FEEDTYPE_ULE)
-		return -EINVAL;
-	if ((if_num = get_if(dvbnet)) < 0)
-		return -EINVAL;
-
-	net = alloc_netdev(sizeof(struct dvb_net_priv), "dvb", dvb_net_setup);
-	if (!net)
-		return -ENOMEM;
-
-	if (dvbnet->dvbdev->id)
-		snprintf(net->name, IFNAMSIZ, "dvb%d%u%d",
-			 dvbnet->dvbdev->adapter->num, dvbnet->dvbdev->id, if_num);
-	else
-		/* compatibility fix to keep dvb0_0 format */
-		snprintf(net->name, IFNAMSIZ, "dvb%d_%d",
-			 dvbnet->dvbdev->adapter->num, if_num);
-
-	net->addr_len = 6;
-	memcpy(net->dev_addr, dvbnet->dvbdev->adapter->proposed_mac, 6);
-
-	dvbnet->device[if_num] = net;
-
-	priv = netdev_priv(net);
-	priv->net = net;
-	priv->demux = dvbnet->demux;
-	priv->pid = pid;
-	priv->rx_mode = RX_MODE_UNI;
-	priv->need_pusi = 1;
-	priv->tscc = 0;
-	priv->feedtype = feedtype;
-	reset_ule(priv);
-
-	INIT_WORK(&priv->set_multicast_list_wq, wq_set_multicast_list);
-	INIT_WORK(&priv->restart_net_feed_wq, wq_restart_net_feed);
-	mutex_init(&priv->mutex);
-
-	net->base_addr = pid;
-
-	if ((result = register_netdev(net)) < 0) {
-		dvbnet->device[if_num] = NULL;
-		free_netdev(net);
-		return result;
-	}
-	printk("dvb_net: created network interface %s\n", net->name);
-
-	return if_num;
-}
-
-static int dvb_net_remove_if(struct dvb_net *dvbnet, unsigned long num)
-{
-	struct net_device *net = dvbnet->device[num];
-	struct dvb_net_priv *priv;
-
-	if (!dvbnet->state[num])
-		return -EINVAL;
-	priv = netdev_priv(net);
-	if (priv->in_use)
-		return -EBUSY;
-
-	dvb_net_stop(net);
-	flush_work_sync(&priv->set_multicast_list_wq);
-	flush_work_sync(&priv->restart_net_feed_wq);
-	printk("dvb_net: removed network interface %s\n", net->name);
-	unregister_netdev(net);
-	dvbnet->state[num]=0;
-	dvbnet->device[num] = NULL;
-	free_netdev(net);
-
-	return 0;
-}
-
-static int dvb_net_do_ioctl(struct file *file,
-		  unsigned int cmd, void *parg)
-{
-	struct dvb_device *dvbdev = file->private_data;
-	struct dvb_net *dvbnet = dvbdev->priv;
-
-	if (((file->f_flags&O_ACCMODE)==O_RDONLY))
-		return -EPERM;
-
-	switch (cmd) {
-	case NET_ADD_IF:
-	{
-		struct dvb_net_if *dvbnetif = parg;
-		int result;
-
-		if (!capable(CAP_SYS_ADMIN))
-			return -EPERM;
-
-		if (!try_module_get(dvbdev->adapter->module))
-			return -EPERM;
-
-		result=dvb_net_add_if(dvbnet, dvbnetif->pid, dvbnetif->feedtype);
-		if (result<0) {
-			module_put(dvbdev->adapter->module);
-			return result;
-		}
-		dvbnetif->if_num=result;
-		break;
-	}
-	case NET_GET_IF:
-	{
-		struct net_device *netdev;
-		struct dvb_net_priv *priv_data;
-		struct dvb_net_if *dvbnetif = parg;
-
-		if (dvbnetif->if_num >= DVB_NET_DEVICES_MAX ||
-		    !dvbnet->state[dvbnetif->if_num])
-			return -EINVAL;
-
-		netdev = dvbnet->device[dvbnetif->if_num];
-
-		priv_data = netdev_priv(netdev);
-		dvbnetif->pid=priv_data->pid;
-		dvbnetif->feedtype=priv_data->feedtype;
-		break;
-	}
-	case NET_REMOVE_IF:
-	{
-		int ret;
-
-		if (!capable(CAP_SYS_ADMIN))
-			return -EPERM;
-		if ((unsigned long) parg >= DVB_NET_DEVICES_MAX)
-			return -EINVAL;
-		ret = dvb_net_remove_if(dvbnet, (unsigned long) parg);
-		if (!ret)
-			module_put(dvbdev->adapter->module);
-		return ret;
-	}
-
-	/* binary compatibility cruft */
-	case __NET_ADD_IF_OLD:
-	{
-		struct __dvb_net_if_old *dvbnetif = parg;
-		int result;
-
-		if (!capable(CAP_SYS_ADMIN))
-			return -EPERM;
-
-		if (!try_module_get(dvbdev->adapter->module))
-			return -EPERM;
-
-		result=dvb_net_add_if(dvbnet, dvbnetif->pid, DVB_NET_FEEDTYPE_MPE);
-		if (result<0) {
-			module_put(dvbdev->adapter->module);
-			return result;
-		}
-		dvbnetif->if_num=result;
-		break;
-	}
-	case __NET_GET_IF_OLD:
-	{
-		struct net_device *netdev;
-		struct dvb_net_priv *priv_data;
-		struct __dvb_net_if_old *dvbnetif = parg;
-
-		if (dvbnetif->if_num >= DVB_NET_DEVICES_MAX ||
-		    !dvbnet->state[dvbnetif->if_num])
-			return -EINVAL;
-
-		netdev = dvbnet->device[dvbnetif->if_num];
-
-		priv_data = netdev_priv(netdev);
-		dvbnetif->pid=priv_data->pid;
-		break;
-	}
-	default:
-		return -ENOTTY;
-	}
-	return 0;
-}
-
-static long dvb_net_ioctl(struct file *file,
-	      unsigned int cmd, unsigned long arg)
-{
-	return dvb_usercopy(file, cmd, arg, dvb_net_do_ioctl);
-}
-
-static int dvb_net_close(struct inode *inode, struct file *file)
-{
-	struct dvb_device *dvbdev = file->private_data;
-	struct dvb_net *dvbnet = dvbdev->priv;
-
-	dvb_generic_release(inode, file);
-
-	if(dvbdev->users == 1 && dvbnet->exit == 1) {
-		fops_put(file->f_op);
-		file->f_op = NULL;
-		wake_up(&dvbdev->wait_queue);
-	}
-	return 0;
-}
-
-
-static const struct file_operations dvb_net_fops = {
-	.owner = THIS_MODULE,
-	.unlocked_ioctl = dvb_net_ioctl,
-	.open =	dvb_generic_open,
-	.release = dvb_net_close,
-	.llseek = noop_llseek,
-};
-
-static struct dvb_device dvbdev_net = {
-	.priv = NULL,
-	.users = 1,
-	.writers = 1,
-	.fops = &dvb_net_fops,
-};
-
-
-void dvb_net_release (struct dvb_net *dvbnet)
-{
-	int i;
-
-	dvbnet->exit = 1;
-	if (dvbnet->dvbdev->users < 1)
-		wait_event(dvbnet->dvbdev->wait_queue,
-				dvbnet->dvbdev->users==1);
-
-	dvb_unregister_device(dvbnet->dvbdev);
-
-	for (i=0; i<DVB_NET_DEVICES_MAX; i++) {
-		if (!dvbnet->state[i])
-			continue;
-		dvb_net_remove_if(dvbnet, i);
-	}
-}
-EXPORT_SYMBOL(dvb_net_release);
-
-
-int dvb_net_init (struct dvb_adapter *adap, struct dvb_net *dvbnet,
-		  struct dmx_demux *dmx)
-{
-	int i;
-
-	dvbnet->demux = dmx;
-
-	for (i=0; i<DVB_NET_DEVICES_MAX; i++)
-		dvbnet->state[i] = 0;
-
-	return dvb_register_device(adap, &dvbnet->dvbdev, &dvbdev_net,
-			     dvbnet, DVB_DEVICE_NET);
-}
-EXPORT_SYMBOL(dvb_net_init);
diff --git a/drivers/media/dvb/dvb-core/dvb_net.h b/drivers/media/dvb/dvb-core/dvb_net.h
deleted file mode 100644
index 1e53acd..0000000
--- a/drivers/media/dvb/dvb-core/dvb_net.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * dvb_net.h
- *
- * Copyright (C) 2001 Ralph Metzler for convergence integrated media GmbH
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1
- * 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 Lesser General Public 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 _DVB_NET_H_
-#define _DVB_NET_H_
-
-#include <linux/module.h>
-#include <linux/netdevice.h>
-#include <linux/inetdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-
-#include "dvbdev.h"
-
-#define DVB_NET_DEVICES_MAX 10
-
-#ifdef CONFIG_DVB_NET
-
-struct dvb_net {
-	struct dvb_device *dvbdev;
-	struct net_device *device[DVB_NET_DEVICES_MAX];
-	int state[DVB_NET_DEVICES_MAX];
-	unsigned int exit:1;
-	struct dmx_demux *demux;
-};
-
-void dvb_net_release(struct dvb_net *);
-int  dvb_net_init(struct dvb_adapter *, struct dvb_net *, struct dmx_demux *);
-
-#else
-
-struct dvb_net {
-	struct dvb_device *dvbdev;
-};
-
-static inline void dvb_net_release(struct dvb_net *dvbnet)
-{
-}
-
-static inline int dvb_net_init(struct dvb_adapter *adap,
-			       struct dvb_net *dvbnet, struct dmx_demux *dmx)
-{
-	return 0;
-}
-
-#endif /* ifdef CONFIG_DVB_NET */
-
-#endif
diff --git a/drivers/media/dvb/dvb-core/dvb_ringbuffer.c b/drivers/media/dvb/dvb-core/dvb_ringbuffer.c
deleted file mode 100644
index a5712cd..0000000
--- a/drivers/media/dvb/dvb-core/dvb_ringbuffer.c
+++ /dev/null
@@ -1,299 +0,0 @@
-/*
- *
- * dvb_ringbuffer.c: ring buffer implementation for the dvb driver
- *
- * Copyright (C) 2003 Oliver Endriss
- * Copyright (C) 2004 Andrew de Quincey
- *
- * based on code originally found in av7110.c & dvb_ci.c:
- * Copyright (C) 1999-2003 Ralph  Metzler
- *                       & Marcus Metzler for convergence integrated media GmbH
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1
- * 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public 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/errno.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <asm/uaccess.h>
-
-#include "dvb_ringbuffer.h"
-
-#define PKT_READY 0
-#define PKT_DISPOSED 1
-
-
-void dvb_ringbuffer_init(struct dvb_ringbuffer *rbuf, void *data, size_t len)
-{
-	rbuf->pread=rbuf->pwrite=0;
-	rbuf->data=data;
-	rbuf->size=len;
-	rbuf->error=0;
-
-	init_waitqueue_head(&rbuf->queue);
-
-	spin_lock_init(&(rbuf->lock));
-}
-
-
-
-int dvb_ringbuffer_empty(struct dvb_ringbuffer *rbuf)
-{
-	return (rbuf->pread==rbuf->pwrite);
-}
-
-
-
-ssize_t dvb_ringbuffer_free(struct dvb_ringbuffer *rbuf)
-{
-	ssize_t free;
-
-	free = rbuf->pread - rbuf->pwrite;
-	if (free <= 0)
-		free += rbuf->size;
-	return free-1;
-}
-
-
-
-ssize_t dvb_ringbuffer_avail(struct dvb_ringbuffer *rbuf)
-{
-	ssize_t avail;
-
-	avail = rbuf->pwrite - rbuf->pread;
-	if (avail < 0)
-		avail += rbuf->size;
-	return avail;
-}
-
-
-
-void dvb_ringbuffer_flush(struct dvb_ringbuffer *rbuf)
-{
-	rbuf->pread = rbuf->pwrite;
-	rbuf->error = 0;
-}
-EXPORT_SYMBOL(dvb_ringbuffer_flush);
-
-void dvb_ringbuffer_reset(struct dvb_ringbuffer *rbuf)
-{
-	rbuf->pread = rbuf->pwrite = 0;
-	rbuf->error = 0;
-}
-
-void dvb_ringbuffer_flush_spinlock_wakeup(struct dvb_ringbuffer *rbuf)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&rbuf->lock, flags);
-	dvb_ringbuffer_flush(rbuf);
-	spin_unlock_irqrestore(&rbuf->lock, flags);
-
-	wake_up(&rbuf->queue);
-}
-
-ssize_t dvb_ringbuffer_read_user(struct dvb_ringbuffer *rbuf, u8 __user *buf, size_t len)
-{
-	size_t todo = len;
-	size_t split;
-
-	split = (rbuf->pread + len > rbuf->size) ? rbuf->size - rbuf->pread : 0;
-	if (split > 0) {
-		if (copy_to_user(buf, rbuf->data+rbuf->pread, split))
-			return -EFAULT;
-		buf += split;
-		todo -= split;
-		rbuf->pread = 0;
-	}
-	if (copy_to_user(buf, rbuf->data+rbuf->pread, todo))
-		return -EFAULT;
-
-	rbuf->pread = (rbuf->pread + todo) % rbuf->size;
-
-	return len;
-}
-
-void dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf, u8 *buf, size_t len)
-{
-	size_t todo = len;
-	size_t split;
-
-	split = (rbuf->pread + len > rbuf->size) ? rbuf->size - rbuf->pread : 0;
-	if (split > 0) {
-		memcpy(buf, rbuf->data+rbuf->pread, split);
-		buf += split;
-		todo -= split;
-		rbuf->pread = 0;
-	}
-	memcpy(buf, rbuf->data+rbuf->pread, todo);
-
-	rbuf->pread = (rbuf->pread + todo) % rbuf->size;
-}
-
-
-ssize_t dvb_ringbuffer_write(struct dvb_ringbuffer *rbuf, const u8 *buf, size_t len)
-{
-	size_t todo = len;
-	size_t split;
-
-	split = (rbuf->pwrite + len > rbuf->size) ? rbuf->size - rbuf->pwrite : 0;
-
-	if (split > 0) {
-		memcpy(rbuf->data+rbuf->pwrite, buf, split);
-		buf += split;
-		todo -= split;
-		rbuf->pwrite = 0;
-	}
-	memcpy(rbuf->data+rbuf->pwrite, buf, todo);
-	rbuf->pwrite = (rbuf->pwrite + todo) % rbuf->size;
-
-	return len;
-}
-
-ssize_t dvb_ringbuffer_pkt_write(struct dvb_ringbuffer *rbuf, u8* buf, size_t len)
-{
-	int status;
-	ssize_t oldpwrite = rbuf->pwrite;
-
-	DVB_RINGBUFFER_WRITE_BYTE(rbuf, len >> 8);
-	DVB_RINGBUFFER_WRITE_BYTE(rbuf, len & 0xff);
-	DVB_RINGBUFFER_WRITE_BYTE(rbuf, PKT_READY);
-	status = dvb_ringbuffer_write(rbuf, buf, len);
-
-	if (status < 0) rbuf->pwrite = oldpwrite;
-	return status;
-}
-
-ssize_t dvb_ringbuffer_pkt_read_user(struct dvb_ringbuffer *rbuf, size_t idx,
-				int offset, u8 __user *buf, size_t len)
-{
-	size_t todo;
-	size_t split;
-	size_t pktlen;
-
-	pktlen = rbuf->data[idx] << 8;
-	pktlen |= rbuf->data[(idx + 1) % rbuf->size];
-	if (offset > pktlen) return -EINVAL;
-	if ((offset + len) > pktlen) len = pktlen - offset;
-
-	idx = (idx + DVB_RINGBUFFER_PKTHDRSIZE + offset) % rbuf->size;
-	todo = len;
-	split = ((idx + len) > rbuf->size) ? rbuf->size - idx : 0;
-	if (split > 0) {
-		if (copy_to_user(buf, rbuf->data+idx, split))
-			return -EFAULT;
-		buf += split;
-		todo -= split;
-		idx = 0;
-	}
-	if (copy_to_user(buf, rbuf->data+idx, todo))
-		return -EFAULT;
-
-	return len;
-}
-
-ssize_t dvb_ringbuffer_pkt_read(struct dvb_ringbuffer *rbuf, size_t idx,
-				int offset, u8* buf, size_t len)
-{
-	size_t todo;
-	size_t split;
-	size_t pktlen;
-
-	pktlen = rbuf->data[idx] << 8;
-	pktlen |= rbuf->data[(idx + 1) % rbuf->size];
-	if (offset > pktlen) return -EINVAL;
-	if ((offset + len) > pktlen) len = pktlen - offset;
-
-	idx = (idx + DVB_RINGBUFFER_PKTHDRSIZE + offset) % rbuf->size;
-	todo = len;
-	split = ((idx + len) > rbuf->size) ? rbuf->size - idx : 0;
-	if (split > 0) {
-		memcpy(buf, rbuf->data+idx, split);
-		buf += split;
-		todo -= split;
-		idx = 0;
-	}
-	memcpy(buf, rbuf->data+idx, todo);
-	return len;
-}
-
-void dvb_ringbuffer_pkt_dispose(struct dvb_ringbuffer *rbuf, size_t idx)
-{
-	size_t pktlen;
-
-	rbuf->data[(idx + 2) % rbuf->size] = PKT_DISPOSED;
-
-	// clean up disposed packets
-	while(dvb_ringbuffer_avail(rbuf) > DVB_RINGBUFFER_PKTHDRSIZE) {
-		if (DVB_RINGBUFFER_PEEK(rbuf, 2) == PKT_DISPOSED) {
-			pktlen = DVB_RINGBUFFER_PEEK(rbuf, 0) << 8;
-			pktlen |= DVB_RINGBUFFER_PEEK(rbuf, 1);
-			DVB_RINGBUFFER_SKIP(rbuf, pktlen + DVB_RINGBUFFER_PKTHDRSIZE);
-		} else {
-			// first packet is not disposed, so we stop cleaning now
-			break;
-		}
-	}
-}
-
-ssize_t dvb_ringbuffer_pkt_next(struct dvb_ringbuffer *rbuf, size_t idx, size_t* pktlen)
-{
-	int consumed;
-	int curpktlen;
-	int curpktstatus;
-
-	if (idx == -1) {
-	       idx = rbuf->pread;
-	} else {
-		curpktlen = rbuf->data[idx] << 8;
-		curpktlen |= rbuf->data[(idx + 1) % rbuf->size];
-		idx = (idx + curpktlen + DVB_RINGBUFFER_PKTHDRSIZE) % rbuf->size;
-	}
-
-	consumed = (idx - rbuf->pread) % rbuf->size;
-
-	while((dvb_ringbuffer_avail(rbuf) - consumed) > DVB_RINGBUFFER_PKTHDRSIZE) {
-
-		curpktlen = rbuf->data[idx] << 8;
-		curpktlen |= rbuf->data[(idx + 1) % rbuf->size];
-		curpktstatus = rbuf->data[(idx + 2) % rbuf->size];
-
-		if (curpktstatus == PKT_READY) {
-			*pktlen = curpktlen;
-			return idx;
-		}
-
-		consumed += curpktlen + DVB_RINGBUFFER_PKTHDRSIZE;
-		idx = (idx + curpktlen + DVB_RINGBUFFER_PKTHDRSIZE) % rbuf->size;
-	}
-
-	// no packets available
-	return -1;
-}
-
-
-
-EXPORT_SYMBOL(dvb_ringbuffer_init);
-EXPORT_SYMBOL(dvb_ringbuffer_empty);
-EXPORT_SYMBOL(dvb_ringbuffer_free);
-EXPORT_SYMBOL(dvb_ringbuffer_avail);
-EXPORT_SYMBOL(dvb_ringbuffer_flush_spinlock_wakeup);
-EXPORT_SYMBOL(dvb_ringbuffer_read_user);
-EXPORT_SYMBOL(dvb_ringbuffer_read);
-EXPORT_SYMBOL(dvb_ringbuffer_write);
diff --git a/drivers/media/dvb/dvb-core/dvb_ringbuffer.h b/drivers/media/dvb/dvb-core/dvb_ringbuffer.h
deleted file mode 100644
index 41f04da..0000000
--- a/drivers/media/dvb/dvb-core/dvb_ringbuffer.h
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- *
- * dvb_ringbuffer.h: ring buffer implementation for the dvb driver
- *
- * Copyright (C) 2003 Oliver Endriss
- * Copyright (C) 2004 Andrew de Quincey
- *
- * based on code originally found in av7110.c & dvb_ci.c:
- * Copyright (C) 1999-2003 Ralph Metzler & Marcus Metzler
- *                         for convergence integrated media GmbH
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1
- * 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public 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 _DVB_RINGBUFFER_H_
-#define _DVB_RINGBUFFER_H_
-
-#include <linux/spinlock.h>
-#include <linux/wait.h>
-
-struct dvb_ringbuffer {
-	u8               *data;
-	ssize_t           size;
-	ssize_t           pread;
-	ssize_t           pwrite;
-	int               error;
-
-	wait_queue_head_t queue;
-	spinlock_t        lock;
-};
-
-#define DVB_RINGBUFFER_PKTHDRSIZE 3
-
-
-/*
-** Notes:
-** ------
-** (1) For performance reasons read and write routines don't check buffer sizes
-**     and/or number of bytes free/available. This has to be done before these
-**     routines are called. For example:
-**
-**     *** write <buflen> bytes ***
-**     free = dvb_ringbuffer_free(rbuf);
-**     if (free >= buflen)
-**         count = dvb_ringbuffer_write(rbuf, buffer, buflen);
-**     else
-**         ...
-**
-**     *** read min. 1000, max. <bufsize> bytes ***
-**     avail = dvb_ringbuffer_avail(rbuf);
-**     if (avail >= 1000)
-**         count = dvb_ringbuffer_read(rbuf, buffer, min(avail, bufsize));
-**     else
-**         ...
-**
-** (2) If there is exactly one reader and one writer, there is no need
-**     to lock read or write operations.
-**     Two or more readers must be locked against each other.
-**     Flushing the buffer counts as a read operation.
-**     Resetting the buffer counts as a read and write operation.
-**     Two or more writers must be locked against each other.
-*/
-
-/* initialize ring buffer, lock and queue */
-extern void dvb_ringbuffer_init(struct dvb_ringbuffer *rbuf, void *data, size_t len);
-
-/* test whether buffer is empty */
-extern int dvb_ringbuffer_empty(struct dvb_ringbuffer *rbuf);
-
-/* return the number of free bytes in the buffer */
-extern ssize_t dvb_ringbuffer_free(struct dvb_ringbuffer *rbuf);
-
-/* return the number of bytes waiting in the buffer */
-extern ssize_t dvb_ringbuffer_avail(struct dvb_ringbuffer *rbuf);
-
-
-/*
-** Reset the read and write pointers to zero and flush the buffer
-** This counts as a read and write operation
-*/
-extern void dvb_ringbuffer_reset(struct dvb_ringbuffer *rbuf);
-
-
-/* read routines & macros */
-/* ---------------------- */
-/* flush buffer */
-extern void dvb_ringbuffer_flush(struct dvb_ringbuffer *rbuf);
-
-/* flush buffer protected by spinlock and wake-up waiting task(s) */
-extern void dvb_ringbuffer_flush_spinlock_wakeup(struct dvb_ringbuffer *rbuf);
-
-/* peek at byte <offs> in the buffer */
-#define DVB_RINGBUFFER_PEEK(rbuf,offs)	\
-			(rbuf)->data[((rbuf)->pread+(offs))%(rbuf)->size]
-
-/* advance read ptr by <num> bytes */
-#define DVB_RINGBUFFER_SKIP(rbuf,num)	\
-			(rbuf)->pread=((rbuf)->pread+(num))%(rbuf)->size
-
-/*
-** read <len> bytes from ring buffer into <buf>
-** <usermem> specifies whether <buf> resides in user space
-** returns number of bytes transferred or -EFAULT
-*/
-extern ssize_t dvb_ringbuffer_read_user(struct dvb_ringbuffer *rbuf,
-				   u8 __user *buf, size_t len);
-extern void dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf,
-				   u8 *buf, size_t len);
-
-
-/* write routines & macros */
-/* ----------------------- */
-/* write single byte to ring buffer */
-#define DVB_RINGBUFFER_WRITE_BYTE(rbuf,byte)	\
-			{ (rbuf)->data[(rbuf)->pwrite]=(byte); \
-			(rbuf)->pwrite=((rbuf)->pwrite+1)%(rbuf)->size; }
-/*
-** write <len> bytes to ring buffer
-** <usermem> specifies whether <buf> resides in user space
-** returns number of bytes transferred or -EFAULT
-*/
-extern ssize_t dvb_ringbuffer_write(struct dvb_ringbuffer *rbuf, const u8 *buf,
-				    size_t len);
-
-
-/**
- * Write a packet into the ringbuffer.
- *
- * <rbuf> Ringbuffer to write to.
- * <buf> Buffer to write.
- * <len> Length of buffer (currently limited to 65535 bytes max).
- * returns Number of bytes written, or -EFAULT, -ENOMEM, -EVINAL.
- */
-extern ssize_t dvb_ringbuffer_pkt_write(struct dvb_ringbuffer *rbuf, u8* buf,
-					size_t len);
-
-/**
- * Read from a packet in the ringbuffer. Note: unlike dvb_ringbuffer_read(), this
- * does NOT update the read pointer in the ringbuffer. You must use
- * dvb_ringbuffer_pkt_dispose() to mark a packet as no longer required.
- *
- * <rbuf> Ringbuffer concerned.
- * <idx> Packet index as returned by dvb_ringbuffer_pkt_next().
- * <offset> Offset into packet to read from.
- * <buf> Destination buffer for data.
- * <len> Size of destination buffer.
- * <usermem> Set to 1 if <buf> is in userspace.
- * returns Number of bytes read, or -EFAULT.
- */
-extern ssize_t dvb_ringbuffer_pkt_read_user(struct dvb_ringbuffer *rbuf, size_t idx,
-				       int offset, u8 __user *buf, size_t len);
-extern ssize_t dvb_ringbuffer_pkt_read(struct dvb_ringbuffer *rbuf, size_t idx,
-				       int offset, u8 *buf, size_t len);
-
-/**
- * Dispose of a packet in the ring buffer.
- *
- * <rbuf> Ring buffer concerned.
- * <idx> Packet index as returned by dvb_ringbuffer_pkt_next().
- */
-extern void dvb_ringbuffer_pkt_dispose(struct dvb_ringbuffer *rbuf, size_t idx);
-
-/**
- * Get the index of the next packet in a ringbuffer.
- *
- * <rbuf> Ringbuffer concerned.
- * <idx> Previous packet index, or -1 to return the first packet index.
- * <pktlen> On success, will be updated to contain the length of the packet in bytes.
- * returns Packet index (if >=0), or -1 if no packets available.
- */
-extern ssize_t dvb_ringbuffer_pkt_next(struct dvb_ringbuffer *rbuf, size_t idx, size_t* pktlen);
-
-
-#endif /* _DVB_RINGBUFFER_H_ */
diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c
deleted file mode 100644
index 39eab73..0000000
--- a/drivers/media/dvb/dvb-core/dvbdev.c
+++ /dev/null
@@ -1,507 +0,0 @@
-/*
- * dvbdev.c
- *
- * Copyright (C) 2000 Ralph  Metzler <ralph@convergence.de>
- *                  & Marcus Metzler <marcus@convergence.de>
- *                    for convergence integrated media GmbH
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1
- * 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 Lesser General Public 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/errno.h>
-#include <linux/string.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/device.h>
-#include <linux/fs.h>
-#include <linux/cdev.h>
-#include <linux/mutex.h>
-#include "dvbdev.h"
-
-static DEFINE_MUTEX(dvbdev_mutex);
-static int dvbdev_debug;
-
-module_param(dvbdev_debug, int, 0644);
-MODULE_PARM_DESC(dvbdev_debug, "Turn on/off device debugging (default:off).");
-
-#define dprintk if (dvbdev_debug) printk
-
-static LIST_HEAD(dvb_adapter_list);
-static DEFINE_MUTEX(dvbdev_register_lock);
-
-static const char * const dnames[] = {
-	"video", "audio", "sec", "frontend", "demux", "dvr", "ca",
-	"net", "osd"
-};
-
-#ifdef CONFIG_DVB_DYNAMIC_MINORS
-#define MAX_DVB_MINORS		256
-#define DVB_MAX_IDS		MAX_DVB_MINORS
-#else
-#define DVB_MAX_IDS		4
-#define nums2minor(num,type,id)	((num << 6) | (id << 4) | type)
-#define MAX_DVB_MINORS		(DVB_MAX_ADAPTERS*64)
-#endif
-
-static struct class *dvb_class;
-
-static struct dvb_device *dvb_minors[MAX_DVB_MINORS];
-static DECLARE_RWSEM(minor_rwsem);
-
-static int dvb_device_open(struct inode *inode, struct file *file)
-{
-	struct dvb_device *dvbdev;
-
-	mutex_lock(&dvbdev_mutex);
-	down_read(&minor_rwsem);
-	dvbdev = dvb_minors[iminor(inode)];
-
-	if (dvbdev && dvbdev->fops) {
-		int err = 0;
-		const struct file_operations *old_fops;
-
-		file->private_data = dvbdev;
-		old_fops = file->f_op;
-		file->f_op = fops_get(dvbdev->fops);
-		if (file->f_op == NULL) {
-			file->f_op = old_fops;
-			goto fail;
-		}
-		if(file->f_op->open)
-			err = file->f_op->open(inode,file);
-		if (err) {
-			fops_put(file->f_op);
-			file->f_op = fops_get(old_fops);
-		}
-		fops_put(old_fops);
-		up_read(&minor_rwsem);
-		mutex_unlock(&dvbdev_mutex);
-		return err;
-	}
-fail:
-	up_read(&minor_rwsem);
-	mutex_unlock(&dvbdev_mutex);
-	return -ENODEV;
-}
-
-
-static const struct file_operations dvb_device_fops =
-{
-	.owner =	THIS_MODULE,
-	.open =		dvb_device_open,
-	.llseek =	noop_llseek,
-};
-
-static struct cdev dvb_device_cdev;
-
-int dvb_generic_open(struct inode *inode, struct file *file)
-{
-	struct dvb_device *dvbdev = file->private_data;
-
-	if (!dvbdev)
-		return -ENODEV;
-
-	if (!dvbdev->users)
-		return -EBUSY;
-
-	if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
-		if (!dvbdev->readers)
-			return -EBUSY;
-		dvbdev->readers--;
-	} else {
-		if (!dvbdev->writers)
-			return -EBUSY;
-		dvbdev->writers--;
-	}
-
-	dvbdev->users--;
-	return 0;
-}
-EXPORT_SYMBOL(dvb_generic_open);
-
-
-int dvb_generic_release(struct inode *inode, struct file *file)
-{
-	struct dvb_device *dvbdev = file->private_data;
-
-	if (!dvbdev)
-		return -ENODEV;
-
-	if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
-		dvbdev->readers++;
-	} else {
-		dvbdev->writers++;
-	}
-
-	dvbdev->users++;
-	return 0;
-}
-EXPORT_SYMBOL(dvb_generic_release);
-
-
-long dvb_generic_ioctl(struct file *file,
-		       unsigned int cmd, unsigned long arg)
-{
-	struct dvb_device *dvbdev = file->private_data;
-
-	if (!dvbdev)
-		return -ENODEV;
-
-	if (!dvbdev->kernel_ioctl)
-		return -EINVAL;
-
-	return dvb_usercopy(file, cmd, arg, dvbdev->kernel_ioctl);
-}
-EXPORT_SYMBOL(dvb_generic_ioctl);
-
-
-static int dvbdev_get_free_id (struct dvb_adapter *adap, int type)
-{
-	u32 id = 0;
-
-	while (id < DVB_MAX_IDS) {
-		struct dvb_device *dev;
-		list_for_each_entry(dev, &adap->device_list, list_head)
-			if (dev->type == type && dev->id == id)
-				goto skip;
-		return id;
-skip:
-		id++;
-	}
-	return -ENFILE;
-}
-
-
-int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
-			const struct dvb_device *template, void *priv, int type)
-{
-	struct dvb_device *dvbdev;
-	struct file_operations *dvbdevfops;
-	struct device *clsdev;
-	int minor;
-	int id;
-
-	mutex_lock(&dvbdev_register_lock);
-
-	if ((id = dvbdev_get_free_id (adap, type)) < 0){
-		mutex_unlock(&dvbdev_register_lock);
-		*pdvbdev = NULL;
-		printk(KERN_ERR "%s: couldn't find free device id\n", __func__);
-		return -ENFILE;
-	}
-
-	*pdvbdev = dvbdev = kmalloc(sizeof(struct dvb_device), GFP_KERNEL);
-
-	if (!dvbdev){
-		mutex_unlock(&dvbdev_register_lock);
-		return -ENOMEM;
-	}
-
-	dvbdevfops = kzalloc(sizeof(struct file_operations), GFP_KERNEL);
-
-	if (!dvbdevfops){
-		kfree (dvbdev);
-		mutex_unlock(&dvbdev_register_lock);
-		return -ENOMEM;
-	}
-
-	memcpy(dvbdev, template, sizeof(struct dvb_device));
-	dvbdev->type = type;
-	dvbdev->id = id;
-	dvbdev->adapter = adap;
-	dvbdev->priv = priv;
-	dvbdev->fops = dvbdevfops;
-	init_waitqueue_head (&dvbdev->wait_queue);
-
-	memcpy(dvbdevfops, template->fops, sizeof(struct file_operations));
-	dvbdevfops->owner = adap->module;
-
-	list_add_tail (&dvbdev->list_head, &adap->device_list);
-
-	down_write(&minor_rwsem);
-#ifdef CONFIG_DVB_DYNAMIC_MINORS
-	for (minor = 0; minor < MAX_DVB_MINORS; minor++)
-		if (dvb_minors[minor] == NULL)
-			break;
-
-	if (minor == MAX_DVB_MINORS) {
-		kfree(dvbdevfops);
-		kfree(dvbdev);
-		up_write(&minor_rwsem);
-		mutex_unlock(&dvbdev_register_lock);
-		return -EINVAL;
-	}
-#else
-	minor = nums2minor(adap->num, type, id);
-#endif
-
-	dvbdev->minor = minor;
-	dvb_minors[minor] = dvbdev;
-	up_write(&minor_rwsem);
-
-	mutex_unlock(&dvbdev_register_lock);
-
-	clsdev = device_create(dvb_class, adap->device,
-			       MKDEV(DVB_MAJOR, minor),
-			       dvbdev, "dvb%d.%s%d", adap->num, dnames[type], id);
-	if (IS_ERR(clsdev)) {
-		printk(KERN_ERR "%s: failed to create device dvb%d.%s%d (%ld)\n",
-		       __func__, adap->num, dnames[type], id, PTR_ERR(clsdev));
-		return PTR_ERR(clsdev);
-	}
-
-	dprintk(KERN_DEBUG "DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n",
-		adap->num, dnames[type], id, minor, minor);
-
-	return 0;
-}
-EXPORT_SYMBOL(dvb_register_device);
-
-
-void dvb_unregister_device(struct dvb_device *dvbdev)
-{
-	if (!dvbdev)
-		return;
-
-	down_write(&minor_rwsem);
-	dvb_minors[dvbdev->minor] = NULL;
-	up_write(&minor_rwsem);
-
-	device_destroy(dvb_class, MKDEV(DVB_MAJOR, dvbdev->minor));
-
-	list_del (&dvbdev->list_head);
-	kfree (dvbdev->fops);
-	kfree (dvbdev);
-}
-EXPORT_SYMBOL(dvb_unregister_device);
-
-static int dvbdev_check_free_adapter_num(int num)
-{
-	struct list_head *entry;
-	list_for_each(entry, &dvb_adapter_list) {
-		struct dvb_adapter *adap;
-		adap = list_entry(entry, struct dvb_adapter, list_head);
-		if (adap->num == num)
-			return 0;
-	}
-	return 1;
-}
-
-static int dvbdev_get_free_adapter_num (void)
-{
-	int num = 0;
-
-	while (num < DVB_MAX_ADAPTERS) {
-		if (dvbdev_check_free_adapter_num(num))
-			return num;
-		num++;
-	}
-
-	return -ENFILE;
-}
-
-
-int dvb_register_adapter(struct dvb_adapter *adap, const char *name,
-			 struct module *module, struct device *device,
-			 short *adapter_nums)
-{
-	int i, num;
-
-	mutex_lock(&dvbdev_register_lock);
-
-	for (i = 0; i < DVB_MAX_ADAPTERS; ++i) {
-		num = adapter_nums[i];
-		if (num >= 0  &&  num < DVB_MAX_ADAPTERS) {
-		/* use the one the driver asked for */
-			if (dvbdev_check_free_adapter_num(num))
-				break;
-		} else {
-			num = dvbdev_get_free_adapter_num();
-			break;
-		}
-		num = -1;
-	}
-
-	if (num < 0) {
-		mutex_unlock(&dvbdev_register_lock);
-		return -ENFILE;
-	}
-
-	memset (adap, 0, sizeof(struct dvb_adapter));
-	INIT_LIST_HEAD (&adap->device_list);
-
-	printk(KERN_INFO "DVB: registering new adapter (%s)\n", name);
-
-	adap->num = num;
-	adap->name = name;
-	adap->module = module;
-	adap->device = device;
-	adap->mfe_shared = 0;
-	adap->mfe_dvbdev = NULL;
-	mutex_init (&adap->mfe_lock);
-
-	list_add_tail (&adap->list_head, &dvb_adapter_list);
-
-	mutex_unlock(&dvbdev_register_lock);
-
-	return num;
-}
-EXPORT_SYMBOL(dvb_register_adapter);
-
-
-int dvb_unregister_adapter(struct dvb_adapter *adap)
-{
-	mutex_lock(&dvbdev_register_lock);
-	list_del (&adap->list_head);
-	mutex_unlock(&dvbdev_register_lock);
-	return 0;
-}
-EXPORT_SYMBOL(dvb_unregister_adapter);
-
-/* if the miracle happens and "generic_usercopy()" is included into
-   the kernel, then this can vanish. please don't make the mistake and
-   define this as video_usercopy(). this will introduce a dependecy
-   to the v4l "videodev.o" module, which is unnecessary for some
-   cards (ie. the budget dvb-cards don't need the v4l module...) */
-int dvb_usercopy(struct file *file,
-		     unsigned int cmd, unsigned long arg,
-		     int (*func)(struct file *file,
-		     unsigned int cmd, void *arg))
-{
-	char    sbuf[128];
-	void    *mbuf = NULL;
-	void    *parg = NULL;
-	int     err  = -EINVAL;
-
-	/*  Copy arguments into temp kernel buffer  */
-	switch (_IOC_DIR(cmd)) {
-	case _IOC_NONE:
-		/*
-		 * For this command, the pointer is actually an integer
-		 * argument.
-		 */
-		parg = (void *) arg;
-		break;
-	case _IOC_READ: /* some v4l ioctls are marked wrong ... */
-	case _IOC_WRITE:
-	case (_IOC_WRITE | _IOC_READ):
-		if (_IOC_SIZE(cmd) <= sizeof(sbuf)) {
-			parg = sbuf;
-		} else {
-			/* too big to allocate from stack */
-			mbuf = kmalloc(_IOC_SIZE(cmd),GFP_KERNEL);
-			if (NULL == mbuf)
-				return -ENOMEM;
-			parg = mbuf;
-		}
-
-		err = -EFAULT;
-		if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd)))
-			goto out;
-		break;
-	}
-
-	/* call driver */
-	mutex_lock(&dvbdev_mutex);
-	if ((err = func(file, cmd, parg)) == -ENOIOCTLCMD)
-		err = -EINVAL;
-	mutex_unlock(&dvbdev_mutex);
-
-	if (err < 0)
-		goto out;
-
-	/*  Copy results into user buffer  */
-	switch (_IOC_DIR(cmd))
-	{
-	case _IOC_READ:
-	case (_IOC_WRITE | _IOC_READ):
-		if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd)))
-			err = -EFAULT;
-		break;
-	}
-
-out:
-	kfree(mbuf);
-	return err;
-}
-
-static int dvb_uevent(struct device *dev, struct kobj_uevent_env *env)
-{
-	struct dvb_device *dvbdev = dev_get_drvdata(dev);
-
-	add_uevent_var(env, "DVB_ADAPTER_NUM=%d", dvbdev->adapter->num);
-	add_uevent_var(env, "DVB_DEVICE_TYPE=%s", dnames[dvbdev->type]);
-	add_uevent_var(env, "DVB_DEVICE_NUM=%d", dvbdev->id);
-	return 0;
-}
-
-static char *dvb_devnode(struct device *dev, umode_t *mode)
-{
-	struct dvb_device *dvbdev = dev_get_drvdata(dev);
-
-	return kasprintf(GFP_KERNEL, "dvb/adapter%d/%s%d",
-		dvbdev->adapter->num, dnames[dvbdev->type], dvbdev->id);
-}
-
-
-static int __init init_dvbdev(void)
-{
-	int retval;
-	dev_t dev = MKDEV(DVB_MAJOR, 0);
-
-	if ((retval = register_chrdev_region(dev, MAX_DVB_MINORS, "DVB")) != 0) {
-		printk(KERN_ERR "dvb-core: unable to get major %d\n", DVB_MAJOR);
-		return retval;
-	}
-
-	cdev_init(&dvb_device_cdev, &dvb_device_fops);
-	if ((retval = cdev_add(&dvb_device_cdev, dev, MAX_DVB_MINORS)) != 0) {
-		printk(KERN_ERR "dvb-core: unable register character device\n");
-		goto error;
-	}
-
-	dvb_class = class_create(THIS_MODULE, "dvb");
-	if (IS_ERR(dvb_class)) {
-		retval = PTR_ERR(dvb_class);
-		goto error;
-	}
-	dvb_class->dev_uevent = dvb_uevent;
-	dvb_class->devnode = dvb_devnode;
-	return 0;
-
-error:
-	cdev_del(&dvb_device_cdev);
-	unregister_chrdev_region(dev, MAX_DVB_MINORS);
-	return retval;
-}
-
-
-static void __exit exit_dvbdev(void)
-{
-	class_destroy(dvb_class);
-	cdev_del(&dvb_device_cdev);
-	unregister_chrdev_region(MKDEV(DVB_MAJOR, 0), MAX_DVB_MINORS);
-}
-
-subsys_initcall(init_dvbdev);
-module_exit(exit_dvbdev);
-
-MODULE_DESCRIPTION("DVB Core Driver");
-MODULE_AUTHOR("Marcus Metzler, Ralph Metzler, Holger Waechtler");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-core/dvbdev.h b/drivers/media/dvb/dvb-core/dvbdev.h
deleted file mode 100644
index fcc6ae9..0000000
--- a/drivers/media/dvb/dvb-core/dvbdev.h
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * dvbdev.h
- *
- * Copyright (C) 2000 Ralph Metzler & Marcus Metzler
- *                    for convergence integrated media GmbH
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Lesser Public License
- * as published by the Free Software Foundation; either version 2.1
- * 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 Lesser General Public 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 _DVBDEV_H_
-#define _DVBDEV_H_
-
-#include <linux/types.h>
-#include <linux/poll.h>
-#include <linux/fs.h>
-#include <linux/list.h>
-
-#define DVB_MAJOR 212
-
-#if defined(CONFIG_DVB_MAX_ADAPTERS) && CONFIG_DVB_MAX_ADAPTERS > 0
-  #define DVB_MAX_ADAPTERS CONFIG_DVB_MAX_ADAPTERS
-#else
-  #define DVB_MAX_ADAPTERS 8
-#endif
-
-#define DVB_UNSET (-1)
-
-#define DVB_DEVICE_VIDEO      0
-#define DVB_DEVICE_AUDIO      1
-#define DVB_DEVICE_SEC        2
-#define DVB_DEVICE_FRONTEND   3
-#define DVB_DEVICE_DEMUX      4
-#define DVB_DEVICE_DVR        5
-#define DVB_DEVICE_CA         6
-#define DVB_DEVICE_NET        7
-#define DVB_DEVICE_OSD        8
-
-#define DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr) \
-	static short adapter_nr[] = \
-		{[0 ... (DVB_MAX_ADAPTERS - 1)] = DVB_UNSET }; \
-	module_param_array(adapter_nr, short, NULL, 0444); \
-	MODULE_PARM_DESC(adapter_nr, "DVB adapter numbers")
-
-struct dvb_frontend;
-
-struct dvb_adapter {
-	int num;
-	struct list_head list_head;
-	struct list_head device_list;
-	const char *name;
-	u8 proposed_mac [6];
-	void* priv;
-
-	struct device *device;
-
-	struct module *module;
-
-	int mfe_shared;			/* indicates mutually exclusive frontends */
-	struct dvb_device *mfe_dvbdev;	/* frontend device in use */
-	struct mutex mfe_lock;		/* access lock for thread creation */
-
-	/* Allow the adapter/bridge driver to perform an action before and/or
-	 * after the core handles an ioctl:
-	 *
-	 * DVB_FE_IOCTL_PRE indicates that the ioctl has not yet been handled.
-	 * DVB_FE_IOCTL_POST indicates that the ioctl has been handled.
-	 *
-	 * When DVB_FE_IOCTL_PRE is passed to the callback as the stage arg:
-	 *
-	 * return 0 to allow dvb-core to handle the ioctl.
-	 * return a positive int to prevent dvb-core from handling the ioctl,
-	 * 	and exit without error.
-	 * return a negative int to prevent dvb-core from handling the ioctl,
-	 * 	and return that value as an error.
-	 *
-	 * When DVB_FE_IOCTL_POST is passed to the callback as the stage arg:
-	 *
-	 * return 0 to allow the dvb_frontend ioctl handler to exit normally.
-	 * return a negative int to cause the dvb_frontend ioctl handler to
-	 * 	return that value as an error.
-	 */
-#define DVB_FE_IOCTL_PRE 0
-#define DVB_FE_IOCTL_POST 1
-	int (*fe_ioctl_override)(struct dvb_frontend *fe,
-				 unsigned int cmd, void *parg,
-				 unsigned int stage);
-};
-
-
-struct dvb_device {
-	struct list_head list_head;
-	const struct file_operations *fops;
-	struct dvb_adapter *adapter;
-	int type;
-	int minor;
-	u32 id;
-
-	/* in theory, 'users' can vanish now,
-	   but I don't want to change too much now... */
-	int readers;
-	int writers;
-	int users;
-
-	wait_queue_head_t	  wait_queue;
-	/* don't really need those !? -- FIXME: use video_usercopy  */
-	int (*kernel_ioctl)(struct file *file, unsigned int cmd, void *arg);
-
-	void *priv;
-};
-
-
-extern int dvb_register_adapter(struct dvb_adapter *adap, const char *name,
-				struct module *module, struct device *device,
-				short *adapter_nums);
-extern int dvb_unregister_adapter (struct dvb_adapter *adap);
-
-extern int dvb_register_device (struct dvb_adapter *adap,
-				struct dvb_device **pdvbdev,
-				const struct dvb_device *template,
-				void *priv,
-				int type);
-
-extern void dvb_unregister_device (struct dvb_device *dvbdev);
-
-extern int dvb_generic_open (struct inode *inode, struct file *file);
-extern int dvb_generic_release (struct inode *inode, struct file *file);
-extern long dvb_generic_ioctl (struct file *file,
-			      unsigned int cmd, unsigned long arg);
-
-/* we don't mess with video_usercopy() any more,
-we simply define out own dvb_usercopy(), which will hopefully become
-generic_usercopy()  someday... */
-
-extern int dvb_usercopy(struct file *file, unsigned int cmd, unsigned long arg,
-			    int (*func)(struct file *file, unsigned int cmd, void *arg));
-
-/** generic DVB attach function. */
-#ifdef CONFIG_MEDIA_ATTACH
-#define dvb_attach(FUNCTION, ARGS...) ({ \
-	void *__r = NULL; \
-	typeof(&FUNCTION) __a = symbol_request(FUNCTION); \
-	if (__a) { \
-		__r = (void *) __a(ARGS); \
-		if (__r == NULL) \
-			symbol_put(FUNCTION); \
-	} else { \
-		printk(KERN_ERR "DVB: Unable to find symbol "#FUNCTION"()\n"); \
-	} \
-	__r; \
-})
-
-#else
-#define dvb_attach(FUNCTION, ARGS...) ({ \
-	FUNCTION(ARGS); \
-})
-
-#endif
-
-#endif /* #ifndef _DVBDEV_H_ */
diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig
deleted file mode 100644
index c216156..0000000
--- a/drivers/media/dvb/dvb-usb/Kconfig
+++ /dev/null
@@ -1,440 +0,0 @@
-config DVB_USB
-	tristate "Support for various USB DVB devices"
-	depends on DVB_CORE && USB && I2C && RC_CORE
-	help
-	  By enabling this you will be able to choose the various supported
-	  USB1.1 and USB2.0 DVB devices.
-
-	  Almost every USB device needs a firmware, please look into
-	  <file:Documentation/dvb/README.dvb-usb>.
-
-	  For a complete list of supported USB devices see the LinuxTV DVB Wiki:
-	  <http://www.linuxtv.org/wiki/index.php/DVB_USB>
-
-	  Say Y if you own a USB DVB device.
-
-config DVB_USB_DEBUG
-	bool "Enable extended debug support for all DVB-USB devices"
-	depends on DVB_USB
-	help
-	  Say Y if you want to enable debugging. See modinfo dvb-usb (and the
-	  appropriate drivers) for debug levels.
-
-config DVB_USB_A800
-	tristate "AVerMedia AverTV DVB-T USB 2.0 (A800)"
-	depends on DVB_USB
-	select DVB_DIB3000MC
-	select DVB_PLL if !DVB_FE_CUSTOMISE
-	select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE
-	help
-	  Say Y here to support the AVerMedia AverTV DVB-T USB 2.0 (A800) receiver.
-
-config DVB_USB_DIBUSB_MB
-	tristate "DiBcom USB DVB-T devices (based on the DiB3000M-B) (see help for device list)"
-	depends on DVB_USB
-	select DVB_PLL if !DVB_FE_CUSTOMISE
-	select DVB_DIB3000MB
-	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.
-
-	  For an up-to-date list of devices supported by this driver, have a look
-	  on the Linux-DVB Wiki at www.linuxtv.org.
-
-	  Say Y if you own such a device and want to use it. You should build it as
-	  a module.
-
-config DVB_USB_DIBUSB_MB_FAULTY
-	bool "Support faulty USB IDs"
-	depends on DVB_USB_DIBUSB_MB
-	help
-	  Support for faulty USB IDs due to an invalid EEPROM on some Artec devices.
-
-config DVB_USB_DIBUSB_MC
-	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_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.
-
-	  For an up-to-date list of devices supported by this driver, have a look
-	  on the Linux-DVB Wiki at www.linuxtv.org.
-
-	  Say Y if you own such a device and want to use it. You should build it as
-	  a module.
-
-config DVB_USB_DIB0700
-	tristate "DiBcom DiB0700 USB DVB devices (see help for supported devices)"
-	depends on DVB_USB
-	select DVB_DIB7000P if !DVB_FE_CUSTOMISE
-	select DVB_DIB7000M if !DVB_FE_CUSTOMISE
-	select DVB_DIB8000 if !DVB_FE_CUSTOMISE
-	select DVB_DIB3000MC if !DVB_FE_CUSTOMISE
-	select DVB_S5H1411 if !DVB_FE_CUSTOMISE
-	select DVB_LGDT3305 if !DVB_FE_CUSTOMISE
-	select DVB_TUNER_DIB0070 if !DVB_FE_CUSTOMISE
-	select DVB_TUNER_DIB0090 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_XC4000 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
-	  silicon. This chip can be found in devices offered by Hauppauge,
-	  Avermedia and other big and small companies.
-
-	  For an up-to-date list of devices supported by this driver, have a look
-	  on the LinuxTV Wiki at www.linuxtv.org.
-
-	  Say Y if you own such a device and want to use it. You should build it as
-	  a module.
-
-config DVB_USB_UMT_010
-	tristate "HanfTek UMT-010 DVB-T USB2.0 support"
-	depends on DVB_USB
-	select DVB_PLL if !DVB_FE_CUSTOMISE
-	select DVB_DIB3000MC
-	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.
-
-config DVB_USB_CXUSB
-	tristate "Conexant USB2.0 hybrid reference design support"
-	depends on DVB_USB
-	select DVB_PLL if !DVB_FE_CUSTOMISE
-	select DVB_CX22702 if !DVB_FE_CUSTOMISE
-	select DVB_LGDT330X if !DVB_FE_CUSTOMISE
-	select DVB_MT352 if !DVB_FE_CUSTOMISE
-	select DVB_ZL10353 if !DVB_FE_CUSTOMISE
-	select DVB_DIB7000P if !DVB_FE_CUSTOMISE
-	select DVB_TUNER_DIB0070 if !DVB_FE_CUSTOMISE
-	select DVB_ATBM8830 if !DVB_FE_CUSTOMISE
-	select DVB_LGS8GXX if !DVB_FE_CUSTOMISE
-	select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE
-	select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMISE
-	select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE
-	select MEDIA_TUNER_MAX2165 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
-	  shall be added in the future. Devices that require this module:
-
-	  Medion MD95700 hybrid USB2.0 device.
-	  DViCO FusionHDTV (Bluebird) USB2.0 devices
-
-config DVB_USB_M920X
-	tristate "Uli m920x DVB-T USB2.0 support"
-	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_CUSTOMISE
-	select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMISE
-	select MEDIA_TUNER_SIMPLE 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
-	  "DTV USB MINI" (in cold state) are supported.
-	  Firmware required.
-
-config DVB_USB_GL861
-	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_CUSTOMISE
-	help
-	  Say Y here to support the MSI Megasky 580 (55801) DVB-T USB2.0
-	  receiver with USB ID 0db0:5581.
-
-config DVB_USB_AU6610
-	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_CUSTOMISE
-	help
-	  Say Y here to support the Sigmatek DVB-110 DVB-T USB2.0 receiver.
-
-config DVB_USB_DIGITV
-	tristate "Nebula Electronics uDigiTV DVB-T USB2.0 support"
-	depends on DVB_USB
-	select DVB_PLL if !DVB_FE_CUSTOMISE
-	select DVB_NXT6000 if !DVB_FE_CUSTOMISE
-	select DVB_MT352 if !DVB_FE_CUSTOMISE
-	help
-	  Say Y here to support the Nebula Electronics uDigitV USB2.0 DVB-T receiver.
-
-config DVB_USB_VP7045
-	tristate "TwinhanDTV Alpha/MagicBoxII, DNTV tinyUSB2, Beetle USB2.0 support"
-	depends on DVB_USB
-	help
-	  Say Y here to support the
-
-	    TwinhanDTV Alpha (stick) (VP-7045),
-		TwinhanDTV MagicBox II (VP-7046),
-		DigitalNow TinyUSB 2 DVB-t,
-		DigitalRise USB 2.0 Ter (Beetle) and
-		TYPHOON DVB-T USB DRIVE
-
-	  DVB-T USB2.0 receivers.
-
-config DVB_USB_VP702X
-	tristate "TwinhanDTV StarBox and clones DVB-S USB2.0 support"
-	depends on DVB_USB
-	help
-	  Say Y here to support the
-
-	    TwinhanDTV StarBox,
-		DigitalRise USB Starbox and
-		TYPHOON DVB-S USB 2.0 BOX
-
-	  DVB-S USB2.0 receivers.
-
-config DVB_USB_GP8PSK
-	tristate "GENPIX 8PSK->USB module support"
-	depends on DVB_USB
-	help
-	  Say Y here to support the
-	    GENPIX 8psk module
-
-	  DVB-S USB2.0 receivers.
-
-config DVB_USB_NOVA_T_USB2
-	tristate "Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 support"
-	depends on DVB_USB
-	select DVB_DIB3000MC
-	select DVB_PLL if !DVB_FE_CUSTOMISE
-	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.
-
-config DVB_USB_TTUSB2
-	tristate "Pinnacle 400e DVB-S USB2.0 support"
-	depends on DVB_USB
-	select DVB_TDA10086 if !DVB_FE_CUSTOMISE
-	select DVB_LNBP21 if !DVB_FE_CUSTOMISE
-	select DVB_TDA826X if !DVB_FE_CUSTOMISE
-	help
-	  Say Y here to support the Pinnacle 400e DVB-S USB2.0 receiver. The
-	  firmware protocol used by this module is similar to the one used by the
-	  old ttusb-driver - that's why the module is called dvb-usb-ttusb2.
-
-config DVB_USB_DTT200U
-	tristate "WideView WT-200U and WT-220U (pen) DVB-T USB2.0 support (Yakumo/Hama/Typhoon/Yuan)"
-	depends on DVB_USB
-	help
-	  Say Y here to support the WideView/Yakumo/Hama/Typhoon/Yuan DVB-T USB2.0 receiver.
-
-	  The receivers are also known as DTT200U (Yakumo) and UB300 (Yuan).
-
-	  The WT-220U and its clones are pen-sized.
-
-config DVB_USB_OPERA1
-	tristate "Opera1 DVB-S USB2.0 receiver"
-	depends on DVB_USB
-	select DVB_STV0299 if !DVB_FE_CUSTOMISE
-	select DVB_PLL if !DVB_FE_CUSTOMISE
-	help
-	  Say Y here to support the Opera DVB-S USB2.0 receiver.
-
-config DVB_USB_AF9005
-	tristate "Afatech AF9005 DVB-T USB1.1 support"
-	depends on DVB_USB && EXPERIMENTAL
-	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)
-
-config DVB_USB_AF9005_REMOTE
-	tristate "Afatech AF9005 default remote control support"
-	depends on DVB_USB_AF9005
-	help
-	  Say Y here to support the default remote control decoding for the
-	  Afatech AF9005 based receiver.
-
-config DVB_USB_PCTV452E
-	tristate "Pinnacle PCTV HDTV Pro USB device/TT Connect S2-3600"
-	depends on DVB_USB
-	select TTPCI_EEPROM
-	select DVB_LNBP22 if !DVB_FE_CUSTOMISE
-	select DVB_STB0899 if !DVB_FE_CUSTOMISE
-	select DVB_STB6100 if !DVB_FE_CUSTOMISE
-	help
-	  Support for external USB adapter designed by Pinnacle,
-	  shipped under the brand name 'PCTV HDTV Pro USB'.
-	  Also supports TT Connect S2-3600/3650 cards.
-	  Say Y if you own such a device and want to use it.
-
-config DVB_USB_DW2102
-	tristate "DvbWorld & TeVii DVB-S/S2 USB2.0 support"
-	depends on DVB_USB
-	select DVB_PLL if !DVB_FE_CUSTOMISE
-	select DVB_STV0299 if !DVB_FE_CUSTOMISE
-	select DVB_STV0288 if !DVB_FE_CUSTOMISE
-	select DVB_STB6000 if !DVB_FE_CUSTOMISE
-	select DVB_CX24116 if !DVB_FE_CUSTOMISE
-	select DVB_SI21XX if !DVB_FE_CUSTOMISE
-	select DVB_TDA10023 if !DVB_FE_CUSTOMISE
-	select DVB_MT312 if !DVB_FE_CUSTOMISE
-	select DVB_ZL10039 if !DVB_FE_CUSTOMISE
-	select DVB_DS3000 if !DVB_FE_CUSTOMISE
-	select DVB_STB6100 if !DVB_FE_CUSTOMISE
-	select DVB_STV6110 if !DVB_FE_CUSTOMISE
-	select DVB_STV0900 if !DVB_FE_CUSTOMISE
-	help
-	  Say Y here to support the DvbWorld, TeVii, Prof DVB-S/S2 USB2.0
-	  receivers.
-
-config DVB_USB_CINERGY_T2
-	tristate "Terratec CinergyT2/qanu USB 2.0 DVB-T receiver"
-	depends on DVB_USB
-	help
-	  Support for "TerraTec CinergyT2" USB2.0 Highspeed DVB Receivers
-
-	  Say Y if you own such a device and want to use it.
-
-config DVB_USB_ANYSEE
-	tristate "Anysee DVB-T/C USB2.0 support"
-	depends on DVB_USB
-	select DVB_PLL if !DVB_FE_CUSTOMISE
-	select DVB_MT352 if !DVB_FE_CUSTOMISE
-	select DVB_ZL10353 if !DVB_FE_CUSTOMISE
-	select DVB_TDA10023 if !DVB_FE_CUSTOMISE
-	select MEDIA_TUNER_TDA18212 if !MEDIA_TUNER_CUSTOMISE
-	select DVB_CX24116 if !DVB_FE_CUSTOMISE
-	select DVB_STV0900 if !DVB_FE_CUSTOMISE
-	select DVB_STV6110 if !DVB_FE_CUSTOMISE
-	select DVB_ISL6423 if !DVB_FE_CUSTOMISE
-	select DVB_CXD2820R if !DVB_FE_CUSTOMISE
-	help
-	  Say Y here to support the Anysee E30, Anysee E30 Plus or
-	  Anysee E30 C Plus DVB USB2.0 receiver.
-
-config DVB_USB_DTV5100
-	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_CUSTOMISE
-	help
-	  Say Y here to support the AME DTV-5100 USB2.0 DVB-T receiver.
-
-config DVB_USB_AF9015
-	tristate "Afatech AF9015 DVB-T USB2.0 support"
-	depends on DVB_USB
-	select DVB_AF9013
-	select DVB_PLL              if !DVB_FE_CUSTOMISE
-	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
-	select MEDIA_TUNER_TDA18218 if !MEDIA_TUNER_CUSTOMISE
-	select MEDIA_TUNER_MXL5007T 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
-	select DVB_ZL10353
-	select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE
-	help
-	  Say Y here to support the Intel CE6230 DVB-T USB2.0 receiver
-
-config DVB_USB_FRIIO
-	tristate "Friio ISDB-T USB2.0 Receiver support"
-	depends on DVB_USB
-	help
-	  Say Y here to support the Japanese DTV receiver Friio.
-
-config DVB_USB_EC168
-	tristate "E3C EC168 DVB-T USB2.0 support"
-	depends on DVB_USB
-	select DVB_EC100
-	select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE
-	help
-	  Say Y here to support the E3C EC168 DVB-T USB2.0 receiver.
-
-config DVB_USB_AZ6007
-	tristate "AzureWave 6007 and clones DVB-T/C USB2.0 support"
-	depends on DVB_USB
-	select DVB_DRXK if !DVB_FE_CUSTOMISE
-	select MEDIA_TUNER_MT2063 if !DVB_FE_CUSTOMISE
-	help
-	  Say Y here to support theAfatech AF9005 based DVB-T/DVB-C receivers.
-
-config DVB_USB_AZ6027
-	tristate "Azurewave DVB-S/S2 USB2.0 AZ6027 support"
-	depends on DVB_USB
-	select DVB_STB0899 if !DVB_FE_CUSTOMISE
-	select DVB_STB6100 if !DVB_FE_CUSTOMISE
-	help
-	  Say Y here to support the AZ6027 device
-
-config DVB_USB_LME2510
-	tristate "LME DM04/QQBOX DVB-S USB2.0 support"
-	depends on DVB_USB
-	select DVB_TDA10086 if !DVB_FE_CUSTOMISE
-	select DVB_TDA826X if !DVB_FE_CUSTOMISE
-	select DVB_STV0288 if !DVB_FE_CUSTOMISE
-	select DVB_IX2505V if !DVB_FE_CUSTOMISE
-	select DVB_STV0299 if !DVB_FE_CUSTOMISE
-	select DVB_PLL if !DVB_FE_CUSTOMISE
-	select DVB_M88RS2000 if !DVB_FE_CUSTOMISE
-	help
-	  Say Y here to support the LME DM04/QQBOX DVB-S USB2.0 .
-
-config DVB_USB_TECHNISAT_USB2
-	tristate "Technisat DVB-S/S2 USB2.0 support"
-	depends on DVB_USB
-	select DVB_STV090x if !DVB_FE_CUSTOMISE
-	select DVB_STV6110x if !DVB_FE_CUSTOMISE
-	help
-	  Say Y here to support the Technisat USB2 DVB-S/S2 device
-
-config DVB_USB_IT913X
-	tristate "it913x driver"
-	depends on DVB_USB
-	select DVB_IT913X_FE
-	help
-	  Say Y here to support the it913x device
-
-config DVB_USB_MXL111SF
-	tristate "MxL111SF DTV USB2.0 support"
-	depends on DVB_USB
-	select DVB_LGDT3305 if !DVB_FE_CUSTOMISE
-	select DVB_LG2160 if !DVB_FE_CUSTOMISE
-	select VIDEO_TVEEPROM
-	help
-	  Say Y here to support the MxL111SF USB2.0 DTV receiver.
-
-config DVB_USB_RTL28XXU
-	tristate "Realtek RTL28xxU DVB USB support"
-	depends on DVB_USB && EXPERIMENTAL
-	select DVB_RTL2830
-	select DVB_RTL2832
-	select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE
-	select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE
-	select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE
-	select MEDIA_TUNER_FC0012 if !MEDIA_TUNER_CUSTOMISE
-	select MEDIA_TUNER_FC0013 if !MEDIA_TUNER_CUSTOMISE
-	help
-	  Say Y here to support the Realtek RTL28xxU DVB USB receiver.
-
-config DVB_USB_AF9035
-	tristate "Afatech AF9035 DVB-T USB2.0 support"
-	depends on DVB_USB
-	select DVB_AF9033
-	select MEDIA_TUNER_TUA9001 if !MEDIA_TUNER_CUSTOMISE
-	select MEDIA_TUNER_FC0011 if !MEDIA_TUNER_CUSTOMISE
-	select MEDIA_TUNER_MXL5007T if !MEDIA_TUNER_CUSTOMISE
-	select MEDIA_TUNER_TDA18218 if !MEDIA_TUNER_CUSTOMISE
-	help
-	  Say Y here to support the Afatech AF9035 based DVB USB receiver.
-
diff --git a/drivers/media/dvb/dvb-usb/Makefile b/drivers/media/dvb/dvb-usb/Makefile
deleted file mode 100644
index b667ac3..0000000
--- a/drivers/media/dvb/dvb-usb/Makefile
+++ /dev/null
@@ -1,121 +0,0 @@
-dvb-usb-objs = dvb-usb-firmware.o dvb-usb-init.o dvb-usb-urb.o dvb-usb-i2c.o dvb-usb-dvb.o dvb-usb-remote.o usb-urb.o
-obj-$(CONFIG_DVB_USB) += dvb-usb.o
-
-dvb-usb-vp7045-objs = vp7045.o vp7045-fe.o
-obj-$(CONFIG_DVB_USB_VP7045) += dvb-usb-vp7045.o
-
-dvb-usb-vp702x-objs = vp702x.o vp702x-fe.o
-obj-$(CONFIG_DVB_USB_VP702X) += dvb-usb-vp702x.o
-
-dvb-usb-gp8psk-objs = gp8psk.o gp8psk-fe.o
-obj-$(CONFIG_DVB_USB_GP8PSK) += dvb-usb-gp8psk.o
-
-dvb-usb-dtt200u-objs = dtt200u.o dtt200u-fe.o
-obj-$(CONFIG_DVB_USB_DTT200U) += dvb-usb-dtt200u.o
-
-dvb-usb-dibusb-common-objs = dibusb-common.o
-
-dvb-usb-a800-objs = a800.o
-obj-$(CONFIG_DVB_USB_A800) += dvb-usb-dibusb-common.o dvb-usb-a800.o
-
-dvb-usb-dibusb-mb-objs = dibusb-mb.o
-obj-$(CONFIG_DVB_USB_DIBUSB_MB) += dvb-usb-dibusb-common.o dvb-usb-dibusb-mb.o
-
-dvb-usb-dibusb-mc-objs = dibusb-mc.o
-obj-$(CONFIG_DVB_USB_DIBUSB_MC) += dvb-usb-dibusb-common.o dvb-usb-dibusb-mc.o
-
-dvb-usb-nova-t-usb2-objs = nova-t-usb2.o
-obj-$(CONFIG_DVB_USB_NOVA_T_USB2) += dvb-usb-dibusb-common.o dvb-usb-nova-t-usb2.o
-
-dvb-usb-umt-010-objs = umt-010.o
-obj-$(CONFIG_DVB_USB_UMT_010) += dvb-usb-dibusb-common.o dvb-usb-umt-010.o
-
-dvb-usb-m920x-objs = m920x.o
-obj-$(CONFIG_DVB_USB_M920X) += dvb-usb-m920x.o
-
-dvb-usb-gl861-objs = gl861.o
-obj-$(CONFIG_DVB_USB_GL861) += dvb-usb-gl861.o
-
-dvb-usb-au6610-objs = au6610.o
-obj-$(CONFIG_DVB_USB_AU6610) += dvb-usb-au6610.o
-
-dvb-usb-digitv-objs = digitv.o
-obj-$(CONFIG_DVB_USB_DIGITV) += dvb-usb-digitv.o
-
-dvb-usb-cxusb-objs = cxusb.o
-obj-$(CONFIG_DVB_USB_CXUSB) += dvb-usb-cxusb.o
-
-dvb-usb-ttusb2-objs = ttusb2.o
-obj-$(CONFIG_DVB_USB_TTUSB2) += dvb-usb-ttusb2.o
-
-dvb-usb-dib0700-objs = dib0700_core.o dib0700_devices.o
-obj-$(CONFIG_DVB_USB_DIB0700) += dvb-usb-dib0700.o
-
-dvb-usb-opera-objs = opera1.o
-obj-$(CONFIG_DVB_USB_OPERA1) += dvb-usb-opera.o
-
-dvb-usb-af9005-objs = af9005.o af9005-fe.o
-obj-$(CONFIG_DVB_USB_AF9005) += dvb-usb-af9005.o
-
-dvb-usb-af9005-remote-objs = af9005-remote.o
-obj-$(CONFIG_DVB_USB_AF9005_REMOTE) += dvb-usb-af9005-remote.o
-
-dvb-usb-anysee-objs = anysee.o
-obj-$(CONFIG_DVB_USB_ANYSEE) += dvb-usb-anysee.o
-
-dvb-usb-pctv452e-objs = pctv452e.o
-obj-$(CONFIG_DVB_USB_PCTV452E) += dvb-usb-pctv452e.o
-
-dvb-usb-dw2102-objs = dw2102.o
-obj-$(CONFIG_DVB_USB_DW2102) += dvb-usb-dw2102.o
-
-dvb-usb-dtv5100-objs = dtv5100.o
-obj-$(CONFIG_DVB_USB_DTV5100) += dvb-usb-dtv5100.o
-
-dvb-usb-af9015-objs = af9015.o
-obj-$(CONFIG_DVB_USB_AF9015) += dvb-usb-af9015.o
-
-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
-
-dvb-usb-friio-objs = friio.o friio-fe.o
-obj-$(CONFIG_DVB_USB_FRIIO) += dvb-usb-friio.o
-
-dvb-usb-ec168-objs = ec168.o
-obj-$(CONFIG_DVB_USB_EC168) += dvb-usb-ec168.o
-
-dvb-usb-az6007-objs = az6007.o
-obj-$(CONFIG_DVB_USB_AZ6007) += dvb-usb-az6007.o
-
-dvb-usb-az6027-objs = az6027.o
-obj-$(CONFIG_DVB_USB_AZ6027) += dvb-usb-az6027.o
-
-dvb-usb-lmedm04-objs = lmedm04.o
-obj-$(CONFIG_DVB_USB_LME2510) += dvb-usb-lmedm04.o
-
-dvb-usb-technisat-usb2-objs = technisat-usb2.o
-obj-$(CONFIG_DVB_USB_TECHNISAT_USB2) += dvb-usb-technisat-usb2.o
-
-dvb-usb-it913x-objs := it913x.o
-obj-$(CONFIG_DVB_USB_IT913X) += dvb-usb-it913x.o
-
-dvb-usb-mxl111sf-objs = mxl111sf.o mxl111sf-phy.o mxl111sf-i2c.o mxl111sf-gpio.o
-obj-$(CONFIG_DVB_USB_MXL111SF) += dvb-usb-mxl111sf.o
-obj-$(CONFIG_DVB_USB_MXL111SF) += mxl111sf-demod.o
-obj-$(CONFIG_DVB_USB_MXL111SF) += mxl111sf-tuner.o
-
-dvb-usb-rtl28xxu-objs = rtl28xxu.o
-obj-$(CONFIG_DVB_USB_RTL28XXU) += dvb-usb-rtl28xxu.o
-
-dvb-usb-af9035-objs = af9035.o
-obj-$(CONFIG_DVB_USB_AF9035) += dvb-usb-af9035.o
-
-ccflags-y += -I$(srctree)/drivers/media/dvb/dvb-core
-ccflags-y += -I$(srctree)/drivers/media/dvb/frontends/
-# due to tuner-xc3028
-ccflags-y += -I$(srctree)/drivers/media/common/tuners
-ccflags-y += -I$(srctree)/drivers/media/dvb/ttpci
-
diff --git a/drivers/media/dvb/dvb-usb/a800.c b/drivers/media/dvb/dvb-usb/a800.c
deleted file mode 100644
index 8d7fef8..0000000
--- a/drivers/media/dvb/dvb-usb/a800.c
+++ /dev/null
@@ -1,191 +0,0 @@
-/* DVB USB framework compliant Linux driver for the AVerMedia AverTV DVB-T
- * USB2.0 (A800) DVB-T receiver.
- *
- * Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@desy.de)
- *
- * Thanks to
- *   - AVerMedia who kindly provided information and
- *   - Glen Harris who suffered from my mistakes during development.
- *
- *	This program is free software; 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.
- *
- * see Documentation/dvb/README.dvb-usb for more information
- */
-#include "dibusb.h"
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level (rc=1 (or-able))." DVB_USB_DEBUG_STATUS);
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-#define deb_rc(args...)   dprintk(debug,0x01,args)
-
-static int a800_power_ctrl(struct dvb_usb_device *d, int onoff)
-{
-	/* do nothing for the AVerMedia */
-	return 0;
-}
-
-/* assure to put cold to 0 for iManufacturer == 1 */
-static int a800_identify_state(struct usb_device *udev, struct dvb_usb_device_properties *props,
-	struct dvb_usb_device_description **desc, int *cold)
-{
-	*cold = udev->descriptor.iManufacturer != 1;
-	return 0;
-}
-
-static struct rc_map_table rc_map_a800_table[] = {
-	{ 0x0201, KEY_MODE },      /* SOURCE */
-	{ 0x0200, KEY_POWER2 },      /* POWER */
-	{ 0x0205, KEY_1 },           /* 1 */
-	{ 0x0206, KEY_2 },           /* 2 */
-	{ 0x0207, KEY_3 },           /* 3 */
-	{ 0x0209, KEY_4 },           /* 4 */
-	{ 0x020a, KEY_5 },           /* 5 */
-	{ 0x020b, KEY_6 },           /* 6 */
-	{ 0x020d, KEY_7 },           /* 7 */
-	{ 0x020e, KEY_8 },           /* 8 */
-	{ 0x020f, KEY_9 },           /* 9 */
-	{ 0x0212, KEY_LEFT },        /* L / DISPLAY */
-	{ 0x0211, KEY_0 },           /* 0 */
-	{ 0x0213, KEY_RIGHT },       /* R / CH RTN */
-	{ 0x0217, KEY_CAMERA },      /* SNAP SHOT */
-	{ 0x0210, KEY_LAST },        /* 16-CH PREV */
-	{ 0x021e, KEY_VOLUMEDOWN },  /* VOL DOWN */
-	{ 0x020c, KEY_ZOOM },        /* FULL SCREEN */
-	{ 0x021f, KEY_VOLUMEUP },    /* VOL UP */
-	{ 0x0214, KEY_MUTE },        /* MUTE */
-	{ 0x0208, KEY_AUDIO },       /* AUDIO */
-	{ 0x0219, KEY_RECORD },      /* RECORD */
-	{ 0x0218, KEY_PLAY },        /* PLAY */
-	{ 0x021b, KEY_STOP },        /* STOP */
-	{ 0x021a, KEY_PLAYPAUSE },   /* TIMESHIFT / PAUSE */
-	{ 0x021d, KEY_BACK },        /* << / RED */
-	{ 0x021c, KEY_FORWARD },     /* >> / YELLOW */
-	{ 0x0203, KEY_TEXT },        /* TELETEXT */
-	{ 0x0204, KEY_EPG },         /* EPG */
-	{ 0x0215, KEY_MENU },        /* MENU */
-
-	{ 0x0303, KEY_CHANNELUP },   /* CH UP */
-	{ 0x0302, KEY_CHANNELDOWN }, /* CH DOWN */
-	{ 0x0301, KEY_FIRST },       /* |<< / GREEN */
-	{ 0x0300, KEY_LAST },        /* >>| / BLUE */
-
-};
-
-static int a800_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
-{
-	int ret;
-	u8 *key = kmalloc(5, GFP_KERNEL);
-	if (!key)
-		return -ENOMEM;
-
-	if (usb_control_msg(d->udev,usb_rcvctrlpipe(d->udev,0),
-				0x04, USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, key, 5,
-				2000) != 5) {
-		ret = -ENODEV;
-		goto out;
-	}
-
-	/* call the universal NEC remote processor, to find out the key's state and event */
-	dvb_usb_nec_rc_key_to_event(d,key,event,state);
-	if (key[0] != 0)
-		deb_rc("key: %x %x %x %x %x\n",key[0],key[1],key[2],key[3],key[4]);
-	ret = 0;
-out:
-	kfree(key);
-	return ret;
-}
-
-/* USB Driver stuff */
-static struct dvb_usb_device_properties a800_properties;
-
-static int a800_probe(struct usb_interface *intf,
-		const struct usb_device_id *id)
-{
-	return dvb_usb_device_init(intf, &a800_properties,
-				   THIS_MODULE, NULL, adapter_nr);
-}
-
-/* do not change the order of the ID table */
-static struct usb_device_id a800_table [] = {
-/* 00 */	{ USB_DEVICE(USB_VID_AVERMEDIA,     USB_PID_AVERMEDIA_DVBT_USB2_COLD) },
-/* 01 */	{ USB_DEVICE(USB_VID_AVERMEDIA,     USB_PID_AVERMEDIA_DVBT_USB2_WARM) },
-			{ }		/* Terminating entry */
-};
-MODULE_DEVICE_TABLE (usb, a800_table);
-
-static struct dvb_usb_device_properties a800_properties = {
-	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
-
-	.usb_ctrl = CYPRESS_FX2,
-	.firmware = "dvb-usb-avertv-a800-02.fw",
-
-	.num_adapters = 1,
-	.adapter = {
-		{
-		.num_frontends = 1,
-		.fe = {{
-			.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
-			.pid_filter_count = 32,
-			.streaming_ctrl   = dibusb2_0_streaming_ctrl,
-			.pid_filter       = dibusb_pid_filter,
-			.pid_filter_ctrl  = dibusb_pid_filter_ctrl,
-
-			.frontend_attach  = dibusb_dib3000mc_frontend_attach,
-			.tuner_attach     = dibusb_dib3000mc_tuner_attach,
-
-			/* parameter for the MPEG2-data transfer */
-					.stream = {
-						.type = USB_BULK,
-				.count = 7,
-				.endpoint = 0x06,
-				.u = {
-					.bulk = {
-						.buffersize = 4096,
-					}
-				}
-			},
-		}},
-			.size_of_priv     = sizeof(struct dibusb_state),
-		},
-	},
-
-	.power_ctrl       = a800_power_ctrl,
-	.identify_state   = a800_identify_state,
-
-	.rc.legacy = {
-		.rc_interval      = DEFAULT_RC_INTERVAL,
-		.rc_map_table     = rc_map_a800_table,
-		.rc_map_size      = ARRAY_SIZE(rc_map_a800_table),
-		.rc_query         = a800_rc_query,
-	},
-
-	.i2c_algo         = &dibusb_i2c_algo,
-
-	.generic_bulk_ctrl_endpoint = 0x01,
-	.num_device_descs = 1,
-	.devices = {
-		{   "AVerMedia AverTV DVB-T USB 2.0 (A800)",
-			{ &a800_table[0], NULL },
-			{ &a800_table[1], NULL },
-		},
-	}
-};
-
-static struct usb_driver a800_driver = {
-	.name		= "dvb_usb_a800",
-	.probe		= a800_probe,
-	.disconnect = dvb_usb_device_exit,
-	.id_table	= a800_table,
-};
-
-module_usb_driver(a800_driver);
-
-MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
-MODULE_DESCRIPTION("AVerMedia AverTV DVB-T USB 2.0 (A800)");
-MODULE_VERSION("1.0");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/af9005-fe.c b/drivers/media/dvb/dvb-usb/af9005-fe.c
deleted file mode 100644
index 740f3f4..0000000
--- a/drivers/media/dvb/dvb-usb/af9005-fe.c
+++ /dev/null
@@ -1,1487 +0,0 @@
-/* Frontend part of the Linux driver for the Afatech 9005
- * USB1.1 DVB-T receiver.
- *
- * Copyright (C) 2007 Luca Olivetti (luca@ventoso.org)
- *
- * Thanks to Afatech who kindly provided information.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You 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.
- *
- * see Documentation/dvb/README.dvb-usb for more information
- */
-#include "af9005.h"
-#include "af9005-script.h"
-#include "mt2060.h"
-#include "qt1010.h"
-#include <asm/div64.h>
-
-struct af9005_fe_state {
-	struct dvb_usb_device *d;
-	fe_status_t stat;
-
-	/* retraining parameters */
-	u32 original_fcw;
-	u16 original_rf_top;
-	u16 original_if_top;
-	u16 original_if_min;
-	u16 original_aci0_if_top;
-	u16 original_aci1_if_top;
-	u16 original_aci0_if_min;
-	u8 original_if_unplug_th;
-	u8 original_rf_unplug_th;
-	u8 original_dtop_if_unplug_th;
-	u8 original_dtop_rf_unplug_th;
-
-	/* statistics */
-	u32 pre_vit_error_count;
-	u32 pre_vit_bit_count;
-	u32 ber;
-	u32 post_vit_error_count;
-	u32 post_vit_bit_count;
-	u32 unc;
-	u16 abort_count;
-
-	int opened;
-	int strong;
-	unsigned long next_status_check;
-	struct dvb_frontend frontend;
-};
-
-static int af9005_write_word_agc(struct dvb_usb_device *d, u16 reghi,
-				 u16 reglo, u8 pos, u8 len, u16 value)
-{
-	int ret;
-
-	if ((ret = af9005_write_ofdm_register(d, reglo, (u8) (value & 0xff))))
-		return ret;
-	return af9005_write_register_bits(d, reghi, pos, len,
-					  (u8) ((value & 0x300) >> 8));
-}
-
-static int af9005_read_word_agc(struct dvb_usb_device *d, u16 reghi,
-				u16 reglo, u8 pos, u8 len, u16 * value)
-{
-	int ret;
-	u8 temp0, temp1;
-
-	if ((ret = af9005_read_ofdm_register(d, reglo, &temp0)))
-		return ret;
-	if ((ret = af9005_read_ofdm_register(d, reghi, &temp1)))
-		return ret;
-	switch (pos) {
-	case 0:
-		*value = ((u16) (temp1 & 0x03) << 8) + (u16) temp0;
-		break;
-	case 2:
-		*value = ((u16) (temp1 & 0x0C) << 6) + (u16) temp0;
-		break;
-	case 4:
-		*value = ((u16) (temp1 & 0x30) << 4) + (u16) temp0;
-		break;
-	case 6:
-		*value = ((u16) (temp1 & 0xC0) << 2) + (u16) temp0;
-		break;
-	default:
-		err("invalid pos in read word agc");
-		return -EINVAL;
-	}
-	return 0;
-
-}
-
-static int af9005_is_fecmon_available(struct dvb_frontend *fe, int *available)
-{
-	struct af9005_fe_state *state = fe->demodulator_priv;
-	int ret;
-	u8 temp;
-
-	*available = false;
-
-	ret = af9005_read_register_bits(state->d, xd_p_fec_vtb_rsd_mon_en,
-					fec_vtb_rsd_mon_en_pos,
-					fec_vtb_rsd_mon_en_len, &temp);
-	if (ret)
-		return ret;
-	if (temp & 1) {
-		ret =
-		    af9005_read_register_bits(state->d,
-					      xd_p_reg_ofsm_read_rbc_en,
-					      reg_ofsm_read_rbc_en_pos,
-					      reg_ofsm_read_rbc_en_len, &temp);
-		if (ret)
-			return ret;
-		if ((temp & 1) == 0)
-			*available = true;
-
-	}
-	return 0;
-}
-
-static int af9005_get_post_vit_err_cw_count(struct dvb_frontend *fe,
-					    u32 * post_err_count,
-					    u32 * post_cw_count,
-					    u16 * abort_count)
-{
-	struct af9005_fe_state *state = fe->demodulator_priv;
-	int ret;
-	u32 err_count;
-	u32 cw_count;
-	u8 temp, temp0, temp1, temp2;
-	u16 loc_abort_count;
-
-	*post_err_count = 0;
-	*post_cw_count = 0;
-
-	/* check if error bit count is ready */
-	ret =
-	    af9005_read_register_bits(state->d, xd_r_fec_rsd_ber_rdy,
-				      fec_rsd_ber_rdy_pos, fec_rsd_ber_rdy_len,
-				      &temp);
-	if (ret)
-		return ret;
-	if (!temp) {
-		deb_info("rsd counter not ready\n");
-		return 100;
-	}
-	/* get abort count */
-	ret =
-	    af9005_read_ofdm_register(state->d,
-				      xd_r_fec_rsd_abort_packet_cnt_7_0,
-				      &temp0);
-	if (ret)
-		return ret;
-	ret =
-	    af9005_read_ofdm_register(state->d,
-				      xd_r_fec_rsd_abort_packet_cnt_15_8,
-				      &temp1);
-	if (ret)
-		return ret;
-	loc_abort_count = ((u16) temp1 << 8) + temp0;
-
-	/* get error count */
-	ret =
-	    af9005_read_ofdm_register(state->d, xd_r_fec_rsd_bit_err_cnt_7_0,
-				      &temp0);
-	if (ret)
-		return ret;
-	ret =
-	    af9005_read_ofdm_register(state->d, xd_r_fec_rsd_bit_err_cnt_15_8,
-				      &temp1);
-	if (ret)
-		return ret;
-	ret =
-	    af9005_read_ofdm_register(state->d, xd_r_fec_rsd_bit_err_cnt_23_16,
-				      &temp2);
-	if (ret)
-		return ret;
-	err_count = ((u32) temp2 << 16) + ((u32) temp1 << 8) + temp0;
-	*post_err_count = err_count - (u32) loc_abort_count *8 * 8;
-
-	/* get RSD packet number */
-	ret =
-	    af9005_read_ofdm_register(state->d, xd_p_fec_rsd_packet_unit_7_0,
-				      &temp0);
-	if (ret)
-		return ret;
-	ret =
-	    af9005_read_ofdm_register(state->d, xd_p_fec_rsd_packet_unit_15_8,
-				      &temp1);
-	if (ret)
-		return ret;
-	cw_count = ((u32) temp1 << 8) + temp0;
-	if (cw_count == 0) {
-		err("wrong RSD packet count");
-		return -EIO;
-	}
-	deb_info("POST abort count %d err count %d rsd packets %d\n",
-		 loc_abort_count, err_count, cw_count);
-	*post_cw_count = cw_count - (u32) loc_abort_count;
-	*abort_count = loc_abort_count;
-	return 0;
-
-}
-
-static int af9005_get_post_vit_ber(struct dvb_frontend *fe,
-				   u32 * post_err_count, u32 * post_cw_count,
-				   u16 * abort_count)
-{
-	u32 loc_cw_count = 0, loc_err_count;
-	u16 loc_abort_count = 0;
-	int ret;
-
-	ret =
-	    af9005_get_post_vit_err_cw_count(fe, &loc_err_count, &loc_cw_count,
-					     &loc_abort_count);
-	if (ret)
-		return ret;
-	*post_err_count = loc_err_count;
-	*post_cw_count = loc_cw_count * 204 * 8;
-	*abort_count = loc_abort_count;
-
-	return 0;
-}
-
-static int af9005_get_pre_vit_err_bit_count(struct dvb_frontend *fe,
-					    u32 * pre_err_count,
-					    u32 * pre_bit_count)
-{
-	struct af9005_fe_state *state = fe->demodulator_priv;
-	u8 temp, temp0, temp1, temp2;
-	u32 super_frame_count, x, bits;
-	int ret;
-
-	ret =
-	    af9005_read_register_bits(state->d, xd_r_fec_vtb_ber_rdy,
-				      fec_vtb_ber_rdy_pos, fec_vtb_ber_rdy_len,
-				      &temp);
-	if (ret)
-		return ret;
-	if (!temp) {
-		deb_info("viterbi counter not ready\n");
-		return 101;	/* ERR_APO_VTB_COUNTER_NOT_READY; */
-	}
-	ret =
-	    af9005_read_ofdm_register(state->d, xd_r_fec_vtb_err_bit_cnt_7_0,
-				      &temp0);
-	if (ret)
-		return ret;
-	ret =
-	    af9005_read_ofdm_register(state->d, xd_r_fec_vtb_err_bit_cnt_15_8,
-				      &temp1);
-	if (ret)
-		return ret;
-	ret =
-	    af9005_read_ofdm_register(state->d, xd_r_fec_vtb_err_bit_cnt_23_16,
-				      &temp2);
-	if (ret)
-		return ret;
-	*pre_err_count = ((u32) temp2 << 16) + ((u32) temp1 << 8) + temp0;
-
-	ret =
-	    af9005_read_ofdm_register(state->d, xd_p_fec_super_frm_unit_7_0,
-				      &temp0);
-	if (ret)
-		return ret;
-	ret =
-	    af9005_read_ofdm_register(state->d, xd_p_fec_super_frm_unit_15_8,
-				      &temp1);
-	if (ret)
-		return ret;
-	super_frame_count = ((u32) temp1 << 8) + temp0;
-	if (super_frame_count == 0) {
-		deb_info("super frame count 0\n");
-		return 102;
-	}
-
-	/* read fft mode */
-	ret =
-	    af9005_read_register_bits(state->d, xd_g_reg_tpsd_txmod,
-				      reg_tpsd_txmod_pos, reg_tpsd_txmod_len,
-				      &temp);
-	if (ret)
-		return ret;
-	if (temp == 0) {
-		/* 2K */
-		x = 1512;
-	} else if (temp == 1) {
-		/* 8k */
-		x = 6048;
-	} else {
-		err("Invalid fft mode");
-		return -EINVAL;
-	}
-
-	/* read modulation mode */
-	ret =
-	    af9005_read_register_bits(state->d, xd_g_reg_tpsd_const,
-				      reg_tpsd_const_pos, reg_tpsd_const_len,
-				      &temp);
-	if (ret)
-		return ret;
-	switch (temp) {
-	case 0:		/* QPSK */
-		bits = 2;
-		break;
-	case 1:		/* QAM_16 */
-		bits = 4;
-		break;
-	case 2:		/* QAM_64 */
-		bits = 6;
-		break;
-	default:
-		err("invalid modulation mode");
-		return -EINVAL;
-	}
-	*pre_bit_count = super_frame_count * 68 * 4 * x * bits;
-	deb_info("PRE err count %d frame count %d bit count %d\n",
-		 *pre_err_count, super_frame_count, *pre_bit_count);
-	return 0;
-}
-
-static int af9005_reset_pre_viterbi(struct dvb_frontend *fe)
-{
-	struct af9005_fe_state *state = fe->demodulator_priv;
-	int ret;
-
-	/* set super frame count to 1 */
-	ret =
-	    af9005_write_ofdm_register(state->d, xd_p_fec_super_frm_unit_7_0,
-				       1 & 0xff);
-	if (ret)
-		return ret;
-	ret = af9005_write_ofdm_register(state->d, xd_p_fec_super_frm_unit_15_8,
-					 1 >> 8);
-	if (ret)
-		return ret;
-	/* reset pre viterbi error count */
-	ret =
-	    af9005_write_register_bits(state->d, xd_p_fec_vtb_ber_rst,
-				       fec_vtb_ber_rst_pos, fec_vtb_ber_rst_len,
-				       1);
-
-	return ret;
-}
-
-static int af9005_reset_post_viterbi(struct dvb_frontend *fe)
-{
-	struct af9005_fe_state *state = fe->demodulator_priv;
-	int ret;
-
-	/* set packet unit */
-	ret =
-	    af9005_write_ofdm_register(state->d, xd_p_fec_rsd_packet_unit_7_0,
-				       10000 & 0xff);
-	if (ret)
-		return ret;
-	ret =
-	    af9005_write_ofdm_register(state->d, xd_p_fec_rsd_packet_unit_15_8,
-				       10000 >> 8);
-	if (ret)
-		return ret;
-	/* reset post viterbi error count */
-	ret =
-	    af9005_write_register_bits(state->d, xd_p_fec_rsd_ber_rst,
-				       fec_rsd_ber_rst_pos, fec_rsd_ber_rst_len,
-				       1);
-
-	return ret;
-}
-
-static int af9005_get_statistic(struct dvb_frontend *fe)
-{
-	struct af9005_fe_state *state = fe->demodulator_priv;
-	int ret, fecavailable;
-	u64 numerator, denominator;
-
-	deb_info("GET STATISTIC\n");
-	ret = af9005_is_fecmon_available(fe, &fecavailable);
-	if (ret)
-		return ret;
-	if (!fecavailable) {
-		deb_info("fecmon not available\n");
-		return 0;
-	}
-
-	ret = af9005_get_pre_vit_err_bit_count(fe, &state->pre_vit_error_count,
-					       &state->pre_vit_bit_count);
-	if (ret == 0) {
-		af9005_reset_pre_viterbi(fe);
-		if (state->pre_vit_bit_count > 0) {
-			/* according to v 0.0.4 of the dvb api ber should be a multiple
-			   of 10E-9 so we have to multiply the error count by
-			   10E9=1000000000 */
-			numerator =
-			    (u64) state->pre_vit_error_count * (u64) 1000000000;
-			denominator = (u64) state->pre_vit_bit_count;
-			state->ber = do_div(numerator, denominator);
-		} else {
-			state->ber = 0xffffffff;
-		}
-	}
-
-	ret = af9005_get_post_vit_ber(fe, &state->post_vit_error_count,
-				      &state->post_vit_bit_count,
-				      &state->abort_count);
-	if (ret == 0) {
-		ret = af9005_reset_post_viterbi(fe);
-		state->unc += state->abort_count;
-		if (ret)
-			return ret;
-	}
-	return 0;
-}
-
-static int af9005_fe_refresh_state(struct dvb_frontend *fe)
-{
-	struct af9005_fe_state *state = fe->demodulator_priv;
-	if (time_after(jiffies, state->next_status_check)) {
-		deb_info("REFRESH STATE\n");
-
-		/* statistics */
-		if (af9005_get_statistic(fe))
-			err("get_statistic_failed");
-		state->next_status_check = jiffies + 250 * HZ / 1000;
-	}
-	return 0;
-}
-
-static int af9005_fe_read_status(struct dvb_frontend *fe, fe_status_t * stat)
-{
-	struct af9005_fe_state *state = fe->demodulator_priv;
-	u8 temp;
-	int ret;
-
-	if (fe->ops.tuner_ops.release == NULL)
-		return -ENODEV;
-
-	*stat = 0;
-	ret = af9005_read_register_bits(state->d, xd_p_agc_lock,
-					agc_lock_pos, agc_lock_len, &temp);
-	if (ret)
-		return ret;
-	if (temp)
-		*stat |= FE_HAS_SIGNAL;
-
-	ret = af9005_read_register_bits(state->d, xd_p_fd_tpsd_lock,
-					fd_tpsd_lock_pos, fd_tpsd_lock_len,
-					&temp);
-	if (ret)
-		return ret;
-	if (temp)
-		*stat |= FE_HAS_CARRIER;
-
-	ret = af9005_read_register_bits(state->d,
-					xd_r_mp2if_sync_byte_locked,
-					mp2if_sync_byte_locked_pos,
-					mp2if_sync_byte_locked_pos, &temp);
-	if (ret)
-		return ret;
-	if (temp)
-		*stat |= FE_HAS_SYNC | FE_HAS_VITERBI | FE_HAS_LOCK;
-	if (state->opened)
-		af9005_led_control(state->d, *stat & FE_HAS_LOCK);
-
-	ret =
-	    af9005_read_register_bits(state->d, xd_p_reg_strong_sginal_detected,
-				      reg_strong_sginal_detected_pos,
-				      reg_strong_sginal_detected_len, &temp);
-	if (ret)
-		return ret;
-	if (temp != state->strong) {
-		deb_info("adjust for strong signal %d\n", temp);
-			state->strong = temp;
-	}
-	return 0;
-}
-
-static int af9005_fe_read_ber(struct dvb_frontend *fe, u32 * ber)
-{
-	struct af9005_fe_state *state = fe->demodulator_priv;
-	if (fe->ops.tuner_ops.release  == NULL)
-		return -ENODEV;
-	af9005_fe_refresh_state(fe);
-	*ber = state->ber;
-	return 0;
-}
-
-static int af9005_fe_read_unc_blocks(struct dvb_frontend *fe, u32 * unc)
-{
-	struct af9005_fe_state *state = fe->demodulator_priv;
-	if (fe->ops.tuner_ops.release == NULL)
-		return -ENODEV;
-	af9005_fe_refresh_state(fe);
-	*unc = state->unc;
-	return 0;
-}
-
-static int af9005_fe_read_signal_strength(struct dvb_frontend *fe,
-					  u16 * strength)
-{
-	struct af9005_fe_state *state = fe->demodulator_priv;
-	int ret;
-	u8 if_gain, rf_gain;
-
-	if (fe->ops.tuner_ops.release == NULL)
-		return -ENODEV;
-	ret =
-	    af9005_read_ofdm_register(state->d, xd_r_reg_aagc_rf_gain,
-				      &rf_gain);
-	if (ret)
-		return ret;
-	ret =
-	    af9005_read_ofdm_register(state->d, xd_r_reg_aagc_if_gain,
-				      &if_gain);
-	if (ret)
-		return ret;
-	/* this value has no real meaning, but i don't have the tables that relate
-	   the rf and if gain with the dbm, so I just scale the value */
-	*strength = (512 - rf_gain - if_gain) << 7;
-	return 0;
-}
-
-static int af9005_fe_read_snr(struct dvb_frontend *fe, u16 * snr)
-{
-	/* the snr can be derived from the ber and the modulation
-	   but I don't think this kind of complex calculations belong
-	   in the driver. I may be wrong.... */
-	return -ENOSYS;
-}
-
-static int af9005_fe_program_cfoe(struct dvb_usb_device *d, u32 bw)
-{
-	u8 temp0, temp1, temp2, temp3, buf[4];
-	int ret;
-	u32 NS_coeff1_2048Nu;
-	u32 NS_coeff1_8191Nu;
-	u32 NS_coeff1_8192Nu;
-	u32 NS_coeff1_8193Nu;
-	u32 NS_coeff2_2k;
-	u32 NS_coeff2_8k;
-
-	switch (bw) {
-	case 6000000:
-		NS_coeff1_2048Nu = 0x2ADB6DC;
-		NS_coeff1_8191Nu = 0xAB7313;
-		NS_coeff1_8192Nu = 0xAB6DB7;
-		NS_coeff1_8193Nu = 0xAB685C;
-		NS_coeff2_2k = 0x156DB6E;
-		NS_coeff2_8k = 0x55B6DC;
-		break;
-
-	case 7000000:
-		NS_coeff1_2048Nu = 0x3200001;
-		NS_coeff1_8191Nu = 0xC80640;
-		NS_coeff1_8192Nu = 0xC80000;
-		NS_coeff1_8193Nu = 0xC7F9C0;
-		NS_coeff2_2k = 0x1900000;
-		NS_coeff2_8k = 0x640000;
-		break;
-
-	case 8000000:
-		NS_coeff1_2048Nu = 0x3924926;
-		NS_coeff1_8191Nu = 0xE4996E;
-		NS_coeff1_8192Nu = 0xE49249;
-		NS_coeff1_8193Nu = 0xE48B25;
-		NS_coeff2_2k = 0x1C92493;
-		NS_coeff2_8k = 0x724925;
-		break;
-	default:
-		err("Invalid bandwidth %d.", bw);
-		return -EINVAL;
-	}
-
-	/*
-	 *  write NS_coeff1_2048Nu
-	 */
-
-	temp0 = (u8) (NS_coeff1_2048Nu & 0x000000FF);
-	temp1 = (u8) ((NS_coeff1_2048Nu & 0x0000FF00) >> 8);
-	temp2 = (u8) ((NS_coeff1_2048Nu & 0x00FF0000) >> 16);
-	temp3 = (u8) ((NS_coeff1_2048Nu & 0x03000000) >> 24);
-
-	/*  big endian to make 8051 happy */
-	buf[0] = temp3;
-	buf[1] = temp2;
-	buf[2] = temp1;
-	buf[3] = temp0;
-
-	/*  cfoe_NS_2k_coeff1_25_24 */
-	ret = af9005_write_ofdm_register(d, 0xAE00, buf[0]);
-	if (ret)
-		return ret;
-
-	/*  cfoe_NS_2k_coeff1_23_16 */
-	ret = af9005_write_ofdm_register(d, 0xAE01, buf[1]);
-	if (ret)
-		return ret;
-
-	/*  cfoe_NS_2k_coeff1_15_8 */
-	ret = af9005_write_ofdm_register(d, 0xAE02, buf[2]);
-	if (ret)
-		return ret;
-
-	/*  cfoe_NS_2k_coeff1_7_0 */
-	ret = af9005_write_ofdm_register(d, 0xAE03, buf[3]);
-	if (ret)
-		return ret;
-
-	/*
-	 *  write NS_coeff2_2k
-	 */
-
-	temp0 = (u8) ((NS_coeff2_2k & 0x0000003F));
-	temp1 = (u8) ((NS_coeff2_2k & 0x00003FC0) >> 6);
-	temp2 = (u8) ((NS_coeff2_2k & 0x003FC000) >> 14);
-	temp3 = (u8) ((NS_coeff2_2k & 0x01C00000) >> 22);
-
-	/*  big endian to make 8051 happy */
-	buf[0] = temp3;
-	buf[1] = temp2;
-	buf[2] = temp1;
-	buf[3] = temp0;
-
-	ret = af9005_write_ofdm_register(d, 0xAE04, buf[0]);
-	if (ret)
-		return ret;
-
-	ret = af9005_write_ofdm_register(d, 0xAE05, buf[1]);
-	if (ret)
-		return ret;
-
-	ret = af9005_write_ofdm_register(d, 0xAE06, buf[2]);
-	if (ret)
-		return ret;
-
-	ret = af9005_write_ofdm_register(d, 0xAE07, buf[3]);
-	if (ret)
-		return ret;
-
-	/*
-	 *  write NS_coeff1_8191Nu
-	 */
-
-	temp0 = (u8) ((NS_coeff1_8191Nu & 0x000000FF));
-	temp1 = (u8) ((NS_coeff1_8191Nu & 0x0000FF00) >> 8);
-	temp2 = (u8) ((NS_coeff1_8191Nu & 0x00FFC000) >> 16);
-	temp3 = (u8) ((NS_coeff1_8191Nu & 0x03000000) >> 24);
-
-	/*  big endian to make 8051 happy */
-	buf[0] = temp3;
-	buf[1] = temp2;
-	buf[2] = temp1;
-	buf[3] = temp0;
-
-	ret = af9005_write_ofdm_register(d, 0xAE08, buf[0]);
-	if (ret)
-		return ret;
-
-	ret = af9005_write_ofdm_register(d, 0xAE09, buf[1]);
-	if (ret)
-		return ret;
-
-	ret = af9005_write_ofdm_register(d, 0xAE0A, buf[2]);
-	if (ret)
-		return ret;
-
-	ret = af9005_write_ofdm_register(d, 0xAE0B, buf[3]);
-	if (ret)
-		return ret;
-
-	/*
-	 *  write NS_coeff1_8192Nu
-	 */
-
-	temp0 = (u8) (NS_coeff1_8192Nu & 0x000000FF);
-	temp1 = (u8) ((NS_coeff1_8192Nu & 0x0000FF00) >> 8);
-	temp2 = (u8) ((NS_coeff1_8192Nu & 0x00FFC000) >> 16);
-	temp3 = (u8) ((NS_coeff1_8192Nu & 0x03000000) >> 24);
-
-	/*  big endian to make 8051 happy */
-	buf[0] = temp3;
-	buf[1] = temp2;
-	buf[2] = temp1;
-	buf[3] = temp0;
-
-	ret = af9005_write_ofdm_register(d, 0xAE0C, buf[0]);
-	if (ret)
-		return ret;
-
-	ret = af9005_write_ofdm_register(d, 0xAE0D, buf[1]);
-	if (ret)
-		return ret;
-
-	ret = af9005_write_ofdm_register(d, 0xAE0E, buf[2]);
-	if (ret)
-		return ret;
-
-	ret = af9005_write_ofdm_register(d, 0xAE0F, buf[3]);
-	if (ret)
-		return ret;
-
-	/*
-	 *  write NS_coeff1_8193Nu
-	 */
-
-	temp0 = (u8) ((NS_coeff1_8193Nu & 0x000000FF));
-	temp1 = (u8) ((NS_coeff1_8193Nu & 0x0000FF00) >> 8);
-	temp2 = (u8) ((NS_coeff1_8193Nu & 0x00FFC000) >> 16);
-	temp3 = (u8) ((NS_coeff1_8193Nu & 0x03000000) >> 24);
-
-	/*  big endian to make 8051 happy */
-	buf[0] = temp3;
-	buf[1] = temp2;
-	buf[2] = temp1;
-	buf[3] = temp0;
-
-	ret = af9005_write_ofdm_register(d, 0xAE10, buf[0]);
-	if (ret)
-		return ret;
-
-	ret = af9005_write_ofdm_register(d, 0xAE11, buf[1]);
-	if (ret)
-		return ret;
-
-	ret = af9005_write_ofdm_register(d, 0xAE12, buf[2]);
-	if (ret)
-		return ret;
-
-	ret = af9005_write_ofdm_register(d, 0xAE13, buf[3]);
-	if (ret)
-		return ret;
-
-	/*
-	 *  write NS_coeff2_8k
-	 */
-
-	temp0 = (u8) ((NS_coeff2_8k & 0x0000003F));
-	temp1 = (u8) ((NS_coeff2_8k & 0x00003FC0) >> 6);
-	temp2 = (u8) ((NS_coeff2_8k & 0x003FC000) >> 14);
-	temp3 = (u8) ((NS_coeff2_8k & 0x01C00000) >> 22);
-
-	/*  big endian to make 8051 happy */
-	buf[0] = temp3;
-	buf[1] = temp2;
-	buf[2] = temp1;
-	buf[3] = temp0;
-
-	ret = af9005_write_ofdm_register(d, 0xAE14, buf[0]);
-	if (ret)
-		return ret;
-
-	ret = af9005_write_ofdm_register(d, 0xAE15, buf[1]);
-	if (ret)
-		return ret;
-
-	ret = af9005_write_ofdm_register(d, 0xAE16, buf[2]);
-	if (ret)
-		return ret;
-
-	ret = af9005_write_ofdm_register(d, 0xAE17, buf[3]);
-	return ret;
-
-}
-
-static int af9005_fe_select_bw(struct dvb_usb_device *d, u32 bw)
-{
-	u8 temp;
-	switch (bw) {
-	case 6000000:
-		temp = 0;
-		break;
-	case 7000000:
-		temp = 1;
-		break;
-	case 8000000:
-		temp = 2;
-		break;
-	default:
-		err("Invalid bandwidth %d.", bw);
-		return -EINVAL;
-	}
-	return af9005_write_register_bits(d, xd_g_reg_bw, reg_bw_pos,
-					  reg_bw_len, temp);
-}
-
-static int af9005_fe_power(struct dvb_frontend *fe, int on)
-{
-	struct af9005_fe_state *state = fe->demodulator_priv;
-	u8 temp = on;
-	int ret;
-	deb_info("power %s tuner\n", on ? "on" : "off");
-	ret = af9005_send_command(state->d, 0x03, &temp, 1, NULL, 0);
-	return ret;
-}
-
-static struct mt2060_config af9005_mt2060_config = {
-	0xC0
-};
-
-static struct qt1010_config af9005_qt1010_config = {
-	0xC4
-};
-
-static int af9005_fe_init(struct dvb_frontend *fe)
-{
-	struct af9005_fe_state *state = fe->demodulator_priv;
-	struct dvb_usb_adapter *adap = fe->dvb->priv;
-	int ret, i, scriptlen;
-	u8 temp, temp0 = 0, temp1 = 0, temp2 = 0;
-	u8 buf[2];
-	u16 if1;
-
-	deb_info("in af9005_fe_init\n");
-
-	/* reset */
-	deb_info("reset\n");
-	if ((ret =
-	     af9005_write_register_bits(state->d, xd_I2C_reg_ofdm_rst_en,
-					4, 1, 0x01)))
-		return ret;
-	if ((ret = af9005_write_ofdm_register(state->d, APO_REG_RESET, 0)))
-		return ret;
-	/* clear ofdm reset */
-	deb_info("clear ofdm reset\n");
-	for (i = 0; i < 150; i++) {
-		if ((ret =
-		     af9005_read_ofdm_register(state->d,
-					       xd_I2C_reg_ofdm_rst, &temp)))
-			return ret;
-		if (temp & (regmask[reg_ofdm_rst_len - 1] << reg_ofdm_rst_pos))
-			break;
-		msleep(10);
-	}
-	if (i == 150)
-		return -ETIMEDOUT;
-
-	/*FIXME in the dump
-	   write B200 A9
-	   write xd_g_reg_ofsm_clk 7
-	   read eepr c6 (2)
-	   read eepr c7 (2)
-	   misc ctrl 3 -> 1
-	   read eepr ca (6)
-	   write xd_g_reg_ofsm_clk 0
-	   write B200 a1
-	 */
-	ret = af9005_write_ofdm_register(state->d, 0xb200, 0xa9);
-	if (ret)
-		return ret;
-	ret = af9005_write_ofdm_register(state->d, xd_g_reg_ofsm_clk, 0x07);
-	if (ret)
-		return ret;
-	temp = 0x01;
-	ret = af9005_send_command(state->d, 0x03, &temp, 1, NULL, 0);
-	if (ret)
-		return ret;
-	ret = af9005_write_ofdm_register(state->d, xd_g_reg_ofsm_clk, 0x00);
-	if (ret)
-		return ret;
-	ret = af9005_write_ofdm_register(state->d, 0xb200, 0xa1);
-	if (ret)
-		return ret;
-
-	temp = regmask[reg_ofdm_rst_len - 1] << reg_ofdm_rst_pos;
-	if ((ret =
-	     af9005_write_register_bits(state->d, xd_I2C_reg_ofdm_rst,
-					reg_ofdm_rst_pos, reg_ofdm_rst_len, 1)))
-		return ret;
-	ret = af9005_write_register_bits(state->d, xd_I2C_reg_ofdm_rst,
-					 reg_ofdm_rst_pos, reg_ofdm_rst_len, 0);
-
-	if (ret)
-		return ret;
-	/* don't know what register aefc is, but this is what the windows driver does */
-	ret = af9005_write_ofdm_register(state->d, 0xaefc, 0);
-	if (ret)
-		return ret;
-
-	/* set stand alone chip */
-	deb_info("set stand alone chip\n");
-	if ((ret =
-	     af9005_write_register_bits(state->d, xd_p_reg_dca_stand_alone,
-					reg_dca_stand_alone_pos,
-					reg_dca_stand_alone_len, 1)))
-		return ret;
-
-	/* set dca upper & lower chip */
-	deb_info("set dca upper & lower chip\n");
-	if ((ret =
-	     af9005_write_register_bits(state->d, xd_p_reg_dca_upper_chip,
-					reg_dca_upper_chip_pos,
-					reg_dca_upper_chip_len, 0)))
-		return ret;
-	if ((ret =
-	     af9005_write_register_bits(state->d, xd_p_reg_dca_lower_chip,
-					reg_dca_lower_chip_pos,
-					reg_dca_lower_chip_len, 0)))
-		return ret;
-
-	/* set 2wire master clock to 0x14 (for 60KHz) */
-	deb_info("set 2wire master clock to 0x14 (for 60KHz)\n");
-	if ((ret =
-	     af9005_write_ofdm_register(state->d, xd_I2C_i2c_m_period, 0x14)))
-		return ret;
-
-	/* clear dca enable chip */
-	deb_info("clear dca enable chip\n");
-	if ((ret =
-	     af9005_write_register_bits(state->d, xd_p_reg_dca_en,
-					reg_dca_en_pos, reg_dca_en_len, 0)))
-		return ret;
-	/* FIXME these are register bits, but I don't know which ones */
-	ret = af9005_write_ofdm_register(state->d, 0xa16c, 1);
-	if (ret)
-		return ret;
-	ret = af9005_write_ofdm_register(state->d, 0xa3c1, 0);
-	if (ret)
-		return ret;
-
-	/* init other parameters: program cfoe and select bandwidth */
-	deb_info("program cfoe\n");
-	ret = af9005_fe_program_cfoe(state->d, 6000000);
-	if (ret)
-		return ret;
-	/* set read-update bit for modulation */
-	deb_info("set read-update bit for modulation\n");
-	if ((ret =
-	     af9005_write_register_bits(state->d, xd_p_reg_feq_read_update,
-					reg_feq_read_update_pos,
-					reg_feq_read_update_len, 1)))
-		return ret;
-
-	/* sample code has a set MPEG TS code here
-	   but sniffing reveals that it doesn't do it */
-
-	/* set read-update bit to 1 for DCA modulation */
-	deb_info("set read-update bit 1 for DCA modulation\n");
-	if ((ret =
-	     af9005_write_register_bits(state->d, xd_p_reg_dca_read_update,
-					reg_dca_read_update_pos,
-					reg_dca_read_update_len, 1)))
-		return ret;
-
-	/* enable fec monitor */
-	deb_info("enable fec monitor\n");
-	if ((ret =
-	     af9005_write_register_bits(state->d, xd_p_fec_vtb_rsd_mon_en,
-					fec_vtb_rsd_mon_en_pos,
-					fec_vtb_rsd_mon_en_len, 1)))
-		return ret;
-
-	/* FIXME should be register bits, I don't know which ones */
-	ret = af9005_write_ofdm_register(state->d, 0xa601, 0);
-
-	/* set api_retrain_never_freeze */
-	deb_info("set api_retrain_never_freeze\n");
-	if ((ret = af9005_write_ofdm_register(state->d, 0xaefb, 0x01)))
-		return ret;
-
-	/* load init script */
-	deb_info("load init script\n");
-	scriptlen = sizeof(script) / sizeof(RegDesc);
-	for (i = 0; i < scriptlen; i++) {
-		if ((ret =
-		     af9005_write_register_bits(state->d, script[i].reg,
-						script[i].pos,
-						script[i].len, script[i].val)))
-			return ret;
-		/* save 3 bytes of original fcw */
-		if (script[i].reg == 0xae18)
-			temp2 = script[i].val;
-		if (script[i].reg == 0xae19)
-			temp1 = script[i].val;
-		if (script[i].reg == 0xae1a)
-			temp0 = script[i].val;
-
-		/* save original unplug threshold */
-		if (script[i].reg == xd_p_reg_unplug_th)
-			state->original_if_unplug_th = script[i].val;
-		if (script[i].reg == xd_p_reg_unplug_rf_gain_th)
-			state->original_rf_unplug_th = script[i].val;
-		if (script[i].reg == xd_p_reg_unplug_dtop_if_gain_th)
-			state->original_dtop_if_unplug_th = script[i].val;
-		if (script[i].reg == xd_p_reg_unplug_dtop_rf_gain_th)
-			state->original_dtop_rf_unplug_th = script[i].val;
-
-	}
-	state->original_fcw =
-	    ((u32) temp2 << 16) + ((u32) temp1 << 8) + (u32) temp0;
-
-
-	/* save original TOPs */
-	deb_info("save original TOPs\n");
-
-	/*  RF TOP */
-	ret =
-	    af9005_read_word_agc(state->d,
-				 xd_p_reg_aagc_rf_top_numerator_9_8,
-				 xd_p_reg_aagc_rf_top_numerator_7_0, 0, 2,
-				 &state->original_rf_top);
-	if (ret)
-		return ret;
-
-	/*  IF TOP */
-	ret =
-	    af9005_read_word_agc(state->d,
-				 xd_p_reg_aagc_if_top_numerator_9_8,
-				 xd_p_reg_aagc_if_top_numerator_7_0, 0, 2,
-				 &state->original_if_top);
-	if (ret)
-		return ret;
-
-	/*  ACI 0 IF TOP */
-	ret =
-	    af9005_read_word_agc(state->d, 0xA60E, 0xA60A, 4, 2,
-				 &state->original_aci0_if_top);
-	if (ret)
-		return ret;
-
-	/*  ACI 1 IF TOP */
-	ret =
-	    af9005_read_word_agc(state->d, 0xA60E, 0xA60B, 6, 2,
-				 &state->original_aci1_if_top);
-	if (ret)
-		return ret;
-
-	/* attach tuner and init */
-	if (fe->ops.tuner_ops.release == NULL) {
-		/* read tuner and board id from eeprom */
-		ret = af9005_read_eeprom(adap->dev, 0xc6, buf, 2);
-		if (ret) {
-			err("Impossible to read EEPROM\n");
-			return ret;
-		}
-		deb_info("Tuner id %d, board id %d\n", buf[0], buf[1]);
-		switch (buf[0]) {
-		case 2:	/* MT2060 */
-			/* read if1 from eeprom */
-			ret = af9005_read_eeprom(adap->dev, 0xc8, buf, 2);
-			if (ret) {
-				err("Impossible to read EEPROM\n");
-				return ret;
-			}
-			if1 = (u16) (buf[0] << 8) + buf[1];
-			if (dvb_attach(mt2060_attach, fe, &adap->dev->i2c_adap,
-					 &af9005_mt2060_config, if1) == NULL) {
-				deb_info("MT2060 attach failed\n");
-				return -ENODEV;
-			}
-			break;
-		case 3:	/* QT1010 */
-		case 9:	/* QT1010B */
-			if (dvb_attach(qt1010_attach, fe, &adap->dev->i2c_adap,
-					&af9005_qt1010_config) ==NULL) {
-				deb_info("QT1010 attach failed\n");
-				return -ENODEV;
-			}
-			break;
-		default:
-			err("Unsupported tuner type %d", buf[0]);
-			return -ENODEV;
-		}
-		ret = fe->ops.tuner_ops.init(fe);
-		if (ret)
-			return ret;
-	}
-
-	deb_info("profit!\n");
-	return 0;
-}
-
-static int af9005_fe_sleep(struct dvb_frontend *fe)
-{
-	return af9005_fe_power(fe, 0);
-}
-
-static int af9005_ts_bus_ctrl(struct dvb_frontend *fe, int acquire)
-{
-	struct af9005_fe_state *state = fe->demodulator_priv;
-
-	if (acquire) {
-		state->opened++;
-	} else {
-
-		state->opened--;
-		if (!state->opened)
-			af9005_led_control(state->d, 0);
-	}
-	return 0;
-}
-
-static int af9005_fe_set_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
-	struct af9005_fe_state *state = fe->demodulator_priv;
-	int ret;
-	u8 temp, temp0, temp1, temp2;
-
-	deb_info("af9005_fe_set_frontend freq %d bw %d\n", fep->frequency,
-		 fep->bandwidth_hz);
-	if (fe->ops.tuner_ops.release == NULL) {
-		err("Tuner not attached");
-		return -ENODEV;
-	}
-
-	deb_info("turn off led\n");
-	/* not in the log */
-	ret = af9005_led_control(state->d, 0);
-	if (ret)
-		return ret;
-	/* not sure about the bits */
-	ret = af9005_write_register_bits(state->d, XD_MP2IF_MISC, 2, 1, 0);
-	if (ret)
-		return ret;
-
-	/* set FCW to default value */
-	deb_info("set FCW to default value\n");
-	temp0 = (u8) (state->original_fcw & 0x000000ff);
-	temp1 = (u8) ((state->original_fcw & 0x0000ff00) >> 8);
-	temp2 = (u8) ((state->original_fcw & 0x00ff0000) >> 16);
-	ret = af9005_write_ofdm_register(state->d, 0xae1a, temp0);
-	if (ret)
-		return ret;
-	ret = af9005_write_ofdm_register(state->d, 0xae19, temp1);
-	if (ret)
-		return ret;
-	ret = af9005_write_ofdm_register(state->d, 0xae18, temp2);
-	if (ret)
-		return ret;
-
-	/* restore original TOPs */
-	deb_info("restore original TOPs\n");
-	ret =
-	    af9005_write_word_agc(state->d,
-				  xd_p_reg_aagc_rf_top_numerator_9_8,
-				  xd_p_reg_aagc_rf_top_numerator_7_0, 0, 2,
-				  state->original_rf_top);
-	if (ret)
-		return ret;
-	ret =
-	    af9005_write_word_agc(state->d,
-				  xd_p_reg_aagc_if_top_numerator_9_8,
-				  xd_p_reg_aagc_if_top_numerator_7_0, 0, 2,
-				  state->original_if_top);
-	if (ret)
-		return ret;
-	ret =
-	    af9005_write_word_agc(state->d, 0xA60E, 0xA60A, 4, 2,
-				  state->original_aci0_if_top);
-	if (ret)
-		return ret;
-	ret =
-	    af9005_write_word_agc(state->d, 0xA60E, 0xA60B, 6, 2,
-				  state->original_aci1_if_top);
-	if (ret)
-		return ret;
-
-	/* select bandwidth */
-	deb_info("select bandwidth");
-	ret = af9005_fe_select_bw(state->d, fep->bandwidth_hz);
-	if (ret)
-		return ret;
-	ret = af9005_fe_program_cfoe(state->d, fep->bandwidth_hz);
-	if (ret)
-		return ret;
-
-	/* clear easy mode flag */
-	deb_info("clear easy mode flag\n");
-	ret = af9005_write_ofdm_register(state->d, 0xaefd, 0);
-	if (ret)
-		return ret;
-
-	/* set unplug threshold to original value */
-	deb_info("set unplug threshold to original value\n");
-	ret =
-	    af9005_write_ofdm_register(state->d, xd_p_reg_unplug_th,
-				       state->original_if_unplug_th);
-	if (ret)
-		return ret;
-	/* set tuner */
-	deb_info("set tuner\n");
-	ret = fe->ops.tuner_ops.set_params(fe);
-	if (ret)
-		return ret;
-
-	/* trigger ofsm */
-	deb_info("trigger ofsm\n");
-	temp = 0;
-	ret = af9005_write_tuner_registers(state->d, 0xffff, &temp, 1);
-	if (ret)
-		return ret;
-
-	/* clear retrain and freeze flag */
-	deb_info("clear retrain and freeze flag\n");
-	ret =
-	    af9005_write_register_bits(state->d,
-				       xd_p_reg_api_retrain_request,
-				       reg_api_retrain_request_pos, 2, 0);
-	if (ret)
-		return ret;
-
-	/* reset pre viterbi and post viterbi registers and statistics */
-	af9005_reset_pre_viterbi(fe);
-	af9005_reset_post_viterbi(fe);
-	state->pre_vit_error_count = 0;
-	state->pre_vit_bit_count = 0;
-	state->ber = 0;
-	state->post_vit_error_count = 0;
-	/* state->unc = 0; commented out since it should be ever increasing */
-	state->abort_count = 0;
-
-	state->next_status_check = jiffies;
-	state->strong = -1;
-
-	return 0;
-}
-
-static int af9005_fe_get_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
-	struct af9005_fe_state *state = fe->demodulator_priv;
-	int ret;
-	u8 temp;
-
-	/* mode */
-	ret =
-	    af9005_read_register_bits(state->d, xd_g_reg_tpsd_const,
-				      reg_tpsd_const_pos, reg_tpsd_const_len,
-				      &temp);
-	if (ret)
-		return ret;
-	deb_info("===== fe_get_frontend_legacy = =============\n");
-	deb_info("CONSTELLATION ");
-	switch (temp) {
-	case 0:
-		fep->modulation = QPSK;
-		deb_info("QPSK\n");
-		break;
-	case 1:
-		fep->modulation = QAM_16;
-		deb_info("QAM_16\n");
-		break;
-	case 2:
-		fep->modulation = QAM_64;
-		deb_info("QAM_64\n");
-		break;
-	}
-
-	/* tps hierarchy and alpha value */
-	ret =
-	    af9005_read_register_bits(state->d, xd_g_reg_tpsd_hier,
-				      reg_tpsd_hier_pos, reg_tpsd_hier_len,
-				      &temp);
-	if (ret)
-		return ret;
-	deb_info("HIERARCHY ");
-	switch (temp) {
-	case 0:
-		fep->hierarchy = HIERARCHY_NONE;
-		deb_info("NONE\n");
-		break;
-	case 1:
-		fep->hierarchy = HIERARCHY_1;
-		deb_info("1\n");
-		break;
-	case 2:
-		fep->hierarchy = HIERARCHY_2;
-		deb_info("2\n");
-		break;
-	case 3:
-		fep->hierarchy = HIERARCHY_4;
-		deb_info("4\n");
-		break;
-	}
-
-	/*  high/low priority     */
-	ret =
-	    af9005_read_register_bits(state->d, xd_g_reg_dec_pri,
-				      reg_dec_pri_pos, reg_dec_pri_len, &temp);
-	if (ret)
-		return ret;
-	/* if temp is set = high priority */
-	deb_info("PRIORITY %s\n", temp ? "high" : "low");
-
-	/* high coderate */
-	ret =
-	    af9005_read_register_bits(state->d, xd_g_reg_tpsd_hpcr,
-				      reg_tpsd_hpcr_pos, reg_tpsd_hpcr_len,
-				      &temp);
-	if (ret)
-		return ret;
-	deb_info("CODERATE HP ");
-	switch (temp) {
-	case 0:
-		fep->code_rate_HP = FEC_1_2;
-		deb_info("FEC_1_2\n");
-		break;
-	case 1:
-		fep->code_rate_HP = FEC_2_3;
-		deb_info("FEC_2_3\n");
-		break;
-	case 2:
-		fep->code_rate_HP = FEC_3_4;
-		deb_info("FEC_3_4\n");
-		break;
-	case 3:
-		fep->code_rate_HP = FEC_5_6;
-		deb_info("FEC_5_6\n");
-		break;
-	case 4:
-		fep->code_rate_HP = FEC_7_8;
-		deb_info("FEC_7_8\n");
-		break;
-	}
-
-	/* low coderate */
-	ret =
-	    af9005_read_register_bits(state->d, xd_g_reg_tpsd_lpcr,
-				      reg_tpsd_lpcr_pos, reg_tpsd_lpcr_len,
-				      &temp);
-	if (ret)
-		return ret;
-	deb_info("CODERATE LP ");
-	switch (temp) {
-	case 0:
-		fep->code_rate_LP = FEC_1_2;
-		deb_info("FEC_1_2\n");
-		break;
-	case 1:
-		fep->code_rate_LP = FEC_2_3;
-		deb_info("FEC_2_3\n");
-		break;
-	case 2:
-		fep->code_rate_LP = FEC_3_4;
-		deb_info("FEC_3_4\n");
-		break;
-	case 3:
-		fep->code_rate_LP = FEC_5_6;
-		deb_info("FEC_5_6\n");
-		break;
-	case 4:
-		fep->code_rate_LP = FEC_7_8;
-		deb_info("FEC_7_8\n");
-		break;
-	}
-
-	/* guard interval */
-	ret =
-	    af9005_read_register_bits(state->d, xd_g_reg_tpsd_gi,
-				      reg_tpsd_gi_pos, reg_tpsd_gi_len, &temp);
-	if (ret)
-		return ret;
-	deb_info("GUARD INTERVAL ");
-	switch (temp) {
-	case 0:
-		fep->guard_interval = GUARD_INTERVAL_1_32;
-		deb_info("1_32\n");
-		break;
-	case 1:
-		fep->guard_interval = GUARD_INTERVAL_1_16;
-		deb_info("1_16\n");
-		break;
-	case 2:
-		fep->guard_interval = GUARD_INTERVAL_1_8;
-		deb_info("1_8\n");
-		break;
-	case 3:
-		fep->guard_interval = GUARD_INTERVAL_1_4;
-		deb_info("1_4\n");
-		break;
-	}
-
-	/* fft */
-	ret =
-	    af9005_read_register_bits(state->d, xd_g_reg_tpsd_txmod,
-				      reg_tpsd_txmod_pos, reg_tpsd_txmod_len,
-				      &temp);
-	if (ret)
-		return ret;
-	deb_info("TRANSMISSION MODE ");
-	switch (temp) {
-	case 0:
-		fep->transmission_mode = TRANSMISSION_MODE_2K;
-		deb_info("2K\n");
-		break;
-	case 1:
-		fep->transmission_mode = TRANSMISSION_MODE_8K;
-		deb_info("8K\n");
-		break;
-	}
-
-	/* bandwidth      */
-	ret =
-	    af9005_read_register_bits(state->d, xd_g_reg_bw, reg_bw_pos,
-				      reg_bw_len, &temp);
-	deb_info("BANDWIDTH ");
-	switch (temp) {
-	case 0:
-		fep->bandwidth_hz = 6000000;
-		deb_info("6\n");
-		break;
-	case 1:
-		fep->bandwidth_hz = 7000000;
-		deb_info("7\n");
-		break;
-	case 2:
-		fep->bandwidth_hz = 8000000;
-		deb_info("8\n");
-		break;
-	}
-	return 0;
-}
-
-static void af9005_fe_release(struct dvb_frontend *fe)
-{
-	struct af9005_fe_state *state =
-	    (struct af9005_fe_state *)fe->demodulator_priv;
-	kfree(state);
-}
-
-static struct dvb_frontend_ops af9005_fe_ops;
-
-struct dvb_frontend *af9005_fe_attach(struct dvb_usb_device *d)
-{
-	struct af9005_fe_state *state = NULL;
-
-	/* allocate memory for the internal state */
-	state = kzalloc(sizeof(struct af9005_fe_state), GFP_KERNEL);
-	if (state == NULL)
-		goto error;
-
-	deb_info("attaching frontend af9005\n");
-
-	state->d = d;
-	state->opened = 0;
-
-	memcpy(&state->frontend.ops, &af9005_fe_ops,
-	       sizeof(struct dvb_frontend_ops));
-	state->frontend.demodulator_priv = state;
-
-	return &state->frontend;
-      error:
-	return NULL;
-}
-
-static struct dvb_frontend_ops af9005_fe_ops = {
-	.delsys = { SYS_DVBT },
-	.info = {
-		 .name = "AF9005 USB DVB-T",
-		 .frequency_min = 44250000,
-		 .frequency_max = 867250000,
-		 .frequency_stepsize = 250000,
-		 .caps = FE_CAN_INVERSION_AUTO |
-		 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_FEC_AUTO |
-		 FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 |
-		 FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO |
-		 FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_RECOVER |
-		 FE_CAN_HIERARCHY_AUTO,
-		 },
-
-	.release = af9005_fe_release,
-
-	.init = af9005_fe_init,
-	.sleep = af9005_fe_sleep,
-	.ts_bus_ctrl = af9005_ts_bus_ctrl,
-
-	.set_frontend = af9005_fe_set_frontend,
-	.get_frontend = af9005_fe_get_frontend,
-
-	.read_status = af9005_fe_read_status,
-	.read_ber = af9005_fe_read_ber,
-	.read_signal_strength = af9005_fe_read_signal_strength,
-	.read_snr = af9005_fe_read_snr,
-	.read_ucblocks = af9005_fe_read_unc_blocks,
-};
diff --git a/drivers/media/dvb/dvb-usb/af9005-remote.c b/drivers/media/dvb/dvb-usb/af9005-remote.c
deleted file mode 100644
index 7e3961d..0000000
--- a/drivers/media/dvb/dvb-usb/af9005-remote.c
+++ /dev/null
@@ -1,157 +0,0 @@
-/* DVB USB compliant Linux driver for the Afatech 9005
- * USB1.1 DVB-T receiver.
- *
- * Standard remote decode function
- *
- * Copyright (C) 2007 Luca Olivetti (luca@ventoso.org)
- *
- * Thanks to Afatech who kindly provided information.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You 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.
- *
- * see Documentation/dvb/README.dvb-usb for more information
- */
-#include "af9005.h"
-/* debug */
-static int dvb_usb_af9005_remote_debug;
-module_param_named(debug, dvb_usb_af9005_remote_debug, int, 0644);
-MODULE_PARM_DESC(debug,
-		 "enable (1) or disable (0) debug messages."
-		 DVB_USB_DEBUG_STATUS);
-
-#define deb_decode(args...)   dprintk(dvb_usb_af9005_remote_debug,0x01,args)
-
-struct rc_map_table rc_map_af9005_table[] = {
-
-	{0x01b7, KEY_POWER},
-	{0x01a7, KEY_VOLUMEUP},
-	{0x0187, KEY_CHANNELUP},
-	{0x017f, KEY_MUTE},
-	{0x01bf, KEY_VOLUMEDOWN},
-	{0x013f, KEY_CHANNELDOWN},
-	{0x01df, KEY_1},
-	{0x015f, KEY_2},
-	{0x019f, KEY_3},
-	{0x011f, KEY_4},
-	{0x01ef, KEY_5},
-	{0x016f, KEY_6},
-	{0x01af, KEY_7},
-	{0x0127, KEY_8},
-	{0x0107, KEY_9},
-	{0x01cf, KEY_ZOOM},
-	{0x014f, KEY_0},
-	{0x018f, KEY_GOTO},	/* marked jump on the remote */
-
-	{0x00bd, KEY_POWER},
-	{0x007d, KEY_VOLUMEUP},
-	{0x00fd, KEY_CHANNELUP},
-	{0x009d, KEY_MUTE},
-	{0x005d, KEY_VOLUMEDOWN},
-	{0x00dd, KEY_CHANNELDOWN},
-	{0x00ad, KEY_1},
-	{0x006d, KEY_2},
-	{0x00ed, KEY_3},
-	{0x008d, KEY_4},
-	{0x004d, KEY_5},
-	{0x00cd, KEY_6},
-	{0x00b5, KEY_7},
-	{0x0075, KEY_8},
-	{0x00f5, KEY_9},
-	{0x0095, KEY_ZOOM},
-	{0x0055, KEY_0},
-	{0x00d5, KEY_GOTO},	/* marked jump on the remote */
-};
-
-int rc_map_af9005_table_size = ARRAY_SIZE(rc_map_af9005_table);
-
-static int repeatable_keys[] = {
-	KEY_VOLUMEUP,
-	KEY_VOLUMEDOWN,
-	KEY_CHANNELUP,
-	KEY_CHANNELDOWN
-};
-
-int af9005_rc_decode(struct dvb_usb_device *d, u8 * data, int len, u32 * event,
-		     int *state)
-{
-	u16 mark, space;
-	u32 result;
-	u8 cust, dat, invdat;
-	int i;
-
-	if (len >= 6) {
-		mark = (u16) (data[0] << 8) + data[1];
-		space = (u16) (data[2] << 8) + data[3];
-		if (space * 3 < mark) {
-			for (i = 0; i < ARRAY_SIZE(repeatable_keys); i++) {
-				if (d->last_event == repeatable_keys[i]) {
-					*state = REMOTE_KEY_REPEAT;
-					*event = d->last_event;
-					deb_decode("repeat key, event %x\n",
-						   *event);
-					return 0;
-				}
-			}
-			deb_decode("repeated key ignored (non repeatable)\n");
-			return 0;
-		} else if (len >= 33 * 4) {	/*32 bits + start code */
-			result = 0;
-			for (i = 4; i < 4 + 32 * 4; i += 4) {
-				result <<= 1;
-				mark = (u16) (data[i] << 8) + data[i + 1];
-				mark >>= 1;
-				space = (u16) (data[i + 2] << 8) + data[i + 3];
-				space >>= 1;
-				if (mark * 2 > space)
-					result += 1;
-			}
-			deb_decode("key pressed, raw value %x\n", result);
-			if ((result & 0xff000000) != 0xfe000000) {
-				deb_decode
-				    ("doesn't start with 0xfe, ignored\n");
-				return 0;
-			}
-			cust = (result >> 16) & 0xff;
-			dat = (result >> 8) & 0xff;
-			invdat = (~result) & 0xff;
-			if (dat != invdat) {
-				deb_decode("code != inverted code\n");
-				return 0;
-			}
-			for (i = 0; i < rc_map_af9005_table_size; i++) {
-				if (rc5_custom(&rc_map_af9005_table[i]) == cust
-				    && rc5_data(&rc_map_af9005_table[i]) == dat) {
-					*event = rc_map_af9005_table[i].keycode;
-					*state = REMOTE_KEY_PRESSED;
-					deb_decode
-					    ("key pressed, event %x\n", *event);
-					return 0;
-				}
-			}
-			deb_decode("not found in table\n");
-		}
-	}
-	return 0;
-}
-
-EXPORT_SYMBOL(rc_map_af9005_table);
-EXPORT_SYMBOL(rc_map_af9005_table_size);
-EXPORT_SYMBOL(af9005_rc_decode);
-
-MODULE_AUTHOR("Luca Olivetti <luca@ventoso.org>");
-MODULE_DESCRIPTION
-    ("Standard remote control decoder for Afatech 9005 DVB-T USB1.1 stick");
-MODULE_VERSION("1.0");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/af9005-script.h b/drivers/media/dvb/dvb-usb/af9005-script.h
deleted file mode 100644
index 4d69045..0000000
--- a/drivers/media/dvb/dvb-usb/af9005-script.h
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
-File automatically generated by createinit.py using data
-extracted from AF05BDA.sys (windows driver):
-
-dd if=AF05BDA.sys of=initsequence bs=1 skip=88316 count=1110
-python createinit.py > af9005-script.h
-
-*/
-
-typedef struct {
-	u16 reg;
-	u8 pos;
-	u8 len;
-	u8 val;
-} RegDesc;
-
-static RegDesc script[] = {
-	{0xa180, 0x0, 0x8, 0xa},
-	{0xa181, 0x0, 0x8, 0xd7},
-	{0xa182, 0x0, 0x8, 0xa3},
-	{0xa0a0, 0x0, 0x8, 0x0},
-	{0xa0a1, 0x0, 0x5, 0x0},
-	{0xa0a1, 0x5, 0x1, 0x1},
-	{0xa0c0, 0x0, 0x4, 0x1},
-	{0xa20e, 0x4, 0x4, 0xa},
-	{0xa20f, 0x0, 0x8, 0x40},
-	{0xa210, 0x0, 0x8, 0x8},
-	{0xa32a, 0x0, 0x4, 0xa},
-	{0xa32c, 0x0, 0x8, 0x20},
-	{0xa32b, 0x0, 0x8, 0x15},
-	{0xa1a0, 0x1, 0x1, 0x1},
-	{0xa000, 0x0, 0x1, 0x1},
-	{0xa000, 0x1, 0x1, 0x0},
-	{0xa001, 0x1, 0x1, 0x1},
-	{0xa001, 0x0, 0x1, 0x0},
-	{0xa001, 0x5, 0x1, 0x0},
-	{0xa00e, 0x0, 0x5, 0x10},
-	{0xa00f, 0x0, 0x3, 0x4},
-	{0xa00f, 0x3, 0x3, 0x5},
-	{0xa010, 0x0, 0x3, 0x4},
-	{0xa010, 0x3, 0x3, 0x5},
-	{0xa016, 0x4, 0x4, 0x3},
-	{0xa01f, 0x0, 0x6, 0xa},
-	{0xa020, 0x0, 0x6, 0xa},
-	{0xa2bc, 0x0, 0x1, 0x1},
-	{0xa2bc, 0x5, 0x1, 0x1},
-	{0xa015, 0x0, 0x8, 0x50},
-	{0xa016, 0x0, 0x1, 0x0},
-	{0xa02a, 0x0, 0x8, 0x50},
-	{0xa029, 0x0, 0x8, 0x4b},
-	{0xa614, 0x0, 0x8, 0x46},
-	{0xa002, 0x0, 0x5, 0x19},
-	{0xa003, 0x0, 0x5, 0x1a},
-	{0xa004, 0x0, 0x5, 0x19},
-	{0xa005, 0x0, 0x5, 0x1a},
-	{0xa008, 0x0, 0x8, 0x69},
-	{0xa009, 0x0, 0x2, 0x2},
-	{0xae1b, 0x0, 0x8, 0x69},
-	{0xae1c, 0x0, 0x8, 0x2},
-	{0xae1d, 0x0, 0x8, 0x2a},
-	{0xa022, 0x0, 0x8, 0xaa},
-	{0xa006, 0x0, 0x8, 0xc8},
-	{0xa007, 0x0, 0x2, 0x0},
-	{0xa00c, 0x0, 0x8, 0xba},
-	{0xa00d, 0x0, 0x2, 0x2},
-	{0xa608, 0x0, 0x8, 0xba},
-	{0xa60e, 0x0, 0x2, 0x2},
-	{0xa609, 0x0, 0x8, 0x80},
-	{0xa60e, 0x2, 0x2, 0x3},
-	{0xa00a, 0x0, 0x8, 0xb6},
-	{0xa00b, 0x0, 0x2, 0x0},
-	{0xa011, 0x0, 0x8, 0xb9},
-	{0xa012, 0x0, 0x2, 0x0},
-	{0xa013, 0x0, 0x8, 0xbd},
-	{0xa014, 0x0, 0x2, 0x2},
-	{0xa366, 0x0, 0x1, 0x1},
-	{0xa2bc, 0x3, 0x1, 0x0},
-	{0xa2bd, 0x0, 0x8, 0xa},
-	{0xa2be, 0x0, 0x8, 0x14},
-	{0xa2bf, 0x0, 0x8, 0x8},
-	{0xa60a, 0x0, 0x8, 0xbd},
-	{0xa60e, 0x4, 0x2, 0x2},
-	{0xa60b, 0x0, 0x8, 0x86},
-	{0xa60e, 0x6, 0x2, 0x3},
-	{0xa001, 0x2, 0x2, 0x1},
-	{0xa1c7, 0x0, 0x8, 0xf5},
-	{0xa03d, 0x0, 0x8, 0xb1},
-	{0xa616, 0x0, 0x8, 0xff},
-	{0xa617, 0x0, 0x8, 0xad},
-	{0xa618, 0x0, 0x8, 0xad},
-	{0xa61e, 0x3, 0x1, 0x1},
-	{0xae1a, 0x0, 0x8, 0x0},
-	{0xae19, 0x0, 0x8, 0xc8},
-	{0xae18, 0x0, 0x8, 0x61},
-	{0xa140, 0x0, 0x8, 0x0},
-	{0xa141, 0x0, 0x8, 0xc8},
-	{0xa142, 0x0, 0x7, 0x61},
-	{0xa023, 0x0, 0x8, 0xff},
-	{0xa021, 0x0, 0x8, 0xad},
-	{0xa026, 0x0, 0x1, 0x0},
-	{0xa024, 0x0, 0x8, 0xff},
-	{0xa025, 0x0, 0x8, 0xff},
-	{0xa1c8, 0x0, 0x8, 0xf},
-	{0xa2bc, 0x1, 0x1, 0x0},
-	{0xa60c, 0x0, 0x4, 0x5},
-	{0xa60c, 0x4, 0x4, 0x6},
-	{0xa60d, 0x0, 0x8, 0xa},
-	{0xa371, 0x0, 0x1, 0x1},
-	{0xa366, 0x1, 0x3, 0x7},
-	{0xa338, 0x0, 0x8, 0x10},
-	{0xa339, 0x0, 0x6, 0x7},
-	{0xa33a, 0x0, 0x6, 0x1f},
-	{0xa33b, 0x0, 0x8, 0xf6},
-	{0xa33c, 0x3, 0x5, 0x4},
-	{0xa33d, 0x4, 0x4, 0x0},
-	{0xa33d, 0x1, 0x1, 0x1},
-	{0xa33d, 0x2, 0x1, 0x1},
-	{0xa33d, 0x3, 0x1, 0x1},
-	{0xa16d, 0x0, 0x4, 0xf},
-	{0xa161, 0x0, 0x5, 0x5},
-	{0xa162, 0x0, 0x4, 0x5},
-	{0xa165, 0x0, 0x8, 0xff},
-	{0xa166, 0x0, 0x8, 0x9c},
-	{0xa2c3, 0x0, 0x4, 0x5},
-	{0xa61a, 0x0, 0x6, 0xf},
-	{0xb200, 0x0, 0x8, 0xa1},
-	{0xb201, 0x0, 0x8, 0x7},
-	{0xa093, 0x0, 0x1, 0x0},
-	{0xa093, 0x1, 0x5, 0xf},
-	{0xa094, 0x0, 0x8, 0xff},
-	{0xa095, 0x0, 0x8, 0xf},
-	{0xa080, 0x2, 0x5, 0x3},
-	{0xa081, 0x0, 0x4, 0x0},
-	{0xa081, 0x4, 0x4, 0x9},
-	{0xa082, 0x0, 0x5, 0x1f},
-	{0xa08d, 0x0, 0x8, 0x1},
-	{0xa083, 0x0, 0x8, 0x32},
-	{0xa084, 0x0, 0x1, 0x0},
-	{0xa08e, 0x0, 0x8, 0x3},
-	{0xa085, 0x0, 0x8, 0x32},
-	{0xa086, 0x0, 0x3, 0x0},
-	{0xa087, 0x0, 0x8, 0x6e},
-	{0xa088, 0x0, 0x5, 0x15},
-	{0xa089, 0x0, 0x8, 0x0},
-	{0xa08a, 0x0, 0x5, 0x19},
-	{0xa08b, 0x0, 0x8, 0x92},
-	{0xa08c, 0x0, 0x5, 0x1c},
-	{0xa120, 0x0, 0x8, 0x0},
-	{0xa121, 0x0, 0x5, 0x10},
-	{0xa122, 0x0, 0x8, 0x0},
-	{0xa123, 0x0, 0x7, 0x40},
-	{0xa123, 0x7, 0x1, 0x0},
-	{0xa124, 0x0, 0x8, 0x13},
-	{0xa125, 0x0, 0x7, 0x10},
-	{0xa1c0, 0x0, 0x8, 0x0},
-	{0xa1c1, 0x0, 0x5, 0x4},
-	{0xa1c2, 0x0, 0x8, 0x0},
-	{0xa1c3, 0x0, 0x5, 0x10},
-	{0xa1c3, 0x5, 0x3, 0x0},
-	{0xa1c4, 0x0, 0x6, 0x0},
-	{0xa1c5, 0x0, 0x7, 0x10},
-	{0xa100, 0x0, 0x8, 0x0},
-	{0xa101, 0x0, 0x5, 0x10},
-	{0xa102, 0x0, 0x8, 0x0},
-	{0xa103, 0x0, 0x7, 0x40},
-	{0xa103, 0x7, 0x1, 0x0},
-	{0xa104, 0x0, 0x8, 0x18},
-	{0xa105, 0x0, 0x7, 0xa},
-	{0xa106, 0x0, 0x8, 0x20},
-	{0xa107, 0x0, 0x8, 0x40},
-	{0xa108, 0x0, 0x4, 0x0},
-	{0xa38c, 0x0, 0x8, 0xfc},
-	{0xa38d, 0x0, 0x8, 0x0},
-	{0xa38e, 0x0, 0x8, 0x7e},
-	{0xa38f, 0x0, 0x8, 0x0},
-	{0xa390, 0x0, 0x8, 0x2f},
-	{0xa60f, 0x5, 0x1, 0x1},
-	{0xa170, 0x0, 0x8, 0xdc},
-	{0xa171, 0x0, 0x2, 0x0},
-	{0xa2ae, 0x0, 0x1, 0x1},
-	{0xa2ae, 0x1, 0x1, 0x1},
-	{0xa392, 0x0, 0x1, 0x1},
-	{0xa391, 0x2, 0x1, 0x0},
-	{0xabc1, 0x0, 0x8, 0xff},
-	{0xabc2, 0x0, 0x8, 0x0},
-	{0xabc8, 0x0, 0x8, 0x8},
-	{0xabca, 0x0, 0x8, 0x10},
-	{0xabcb, 0x0, 0x1, 0x0},
-	{0xabc3, 0x5, 0x3, 0x7},
-	{0xabc0, 0x6, 0x1, 0x0},
-	{0xabc0, 0x4, 0x2, 0x0},
-	{0xa344, 0x4, 0x4, 0x1},
-	{0xabc0, 0x7, 0x1, 0x1},
-	{0xabc0, 0x2, 0x1, 0x1},
-	{0xa345, 0x0, 0x8, 0x66},
-	{0xa346, 0x0, 0x8, 0x66},
-	{0xa347, 0x0, 0x4, 0x0},
-	{0xa343, 0x0, 0x4, 0xa},
-	{0xa347, 0x4, 0x4, 0x2},
-	{0xa348, 0x0, 0x4, 0xc},
-	{0xa348, 0x4, 0x4, 0x7},
-	{0xa349, 0x0, 0x6, 0x2},
-};
diff --git a/drivers/media/dvb/dvb-usb/af9005.c b/drivers/media/dvb/dvb-usb/af9005.c
deleted file mode 100644
index af176b6..0000000
--- a/drivers/media/dvb/dvb-usb/af9005.c
+++ /dev/null
@@ -1,1117 +0,0 @@
-/* DVB USB compliant Linux driver for the Afatech 9005
- * USB1.1 DVB-T receiver.
- *
- * Copyright (C) 2007 Luca Olivetti (luca@ventoso.org)
- *
- * Thanks to Afatech who kindly provided information.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You 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.
- *
- * see Documentation/dvb/README.dvb-usb for more information
- */
-#include "af9005.h"
-
-/* debug */
-int dvb_usb_af9005_debug;
-module_param_named(debug, dvb_usb_af9005_debug, int, 0644);
-MODULE_PARM_DESC(debug,
-		 "set debugging level (1=info,xfer=2,rc=4,reg=8,i2c=16,fw=32 (or-able))."
-		 DVB_USB_DEBUG_STATUS);
-/* enable obnoxious led */
-bool dvb_usb_af9005_led = 1;
-module_param_named(led, dvb_usb_af9005_led, bool, 0644);
-MODULE_PARM_DESC(led, "enable led (default: 1).");
-
-/* eeprom dump */
-static int dvb_usb_af9005_dump_eeprom;
-module_param_named(dump_eeprom, dvb_usb_af9005_dump_eeprom, int, 0);
-MODULE_PARM_DESC(dump_eeprom, "dump contents of the eeprom.");
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-/* remote control decoder */
-static int (*rc_decode) (struct dvb_usb_device *d, u8 *data, int len,
-		u32 *event, int *state);
-static void *rc_keys;
-static int *rc_keys_size;
-
-u8 regmask[8] = { 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff };
-
-struct af9005_device_state {
-	u8 sequence;
-	int led_state;
-};
-
-static int af9005_generic_read_write(struct dvb_usb_device *d, u16 reg,
-			      int readwrite, int type, u8 * values, int len)
-{
-	struct af9005_device_state *st = d->priv;
-	u8 obuf[16] = { 0 };
-	u8 ibuf[17] = { 0 };
-	u8 command;
-	int i;
-	int ret;
-
-	if (len < 1) {
-		err("generic read/write, less than 1 byte. Makes no sense.");
-		return -EINVAL;
-	}
-	if (len > 8) {
-		err("generic read/write, more than 8 bytes. Not supported.");
-		return -EINVAL;
-	}
-
-	obuf[0] = 14;		/* rest of buffer length low */
-	obuf[1] = 0;		/* rest of buffer length high */
-
-	obuf[2] = AF9005_REGISTER_RW;	/* register operation */
-	obuf[3] = 12;		/* rest of buffer length */
-
-	obuf[4] = st->sequence++;	/* sequence number */
-
-	obuf[5] = (u8) (reg >> 8);	/* register address */
-	obuf[6] = (u8) (reg & 0xff);
-
-	if (type == AF9005_OFDM_REG) {
-		command = AF9005_CMD_OFDM_REG;
-	} else {
-		command = AF9005_CMD_TUNER;
-	}
-
-	if (len > 1)
-		command |=
-		    AF9005_CMD_BURST | AF9005_CMD_AUTOINC | (len - 1) << 3;
-	command |= readwrite;
-	if (readwrite == AF9005_CMD_WRITE)
-		for (i = 0; i < len; i++)
-			obuf[8 + i] = values[i];
-	else if (type == AF9005_TUNER_REG)
-		/* read command for tuner, the first byte contains the i2c address */
-		obuf[8] = values[0];
-	obuf[7] = command;
-
-	ret = dvb_usb_generic_rw(d, obuf, 16, ibuf, 17, 0);
-	if (ret)
-		return ret;
-
-	/* sanity check */
-	if (ibuf[2] != AF9005_REGISTER_RW_ACK) {
-		err("generic read/write, wrong reply code.");
-		return -EIO;
-	}
-	if (ibuf[3] != 0x0d) {
-		err("generic read/write, wrong length in reply.");
-		return -EIO;
-	}
-	if (ibuf[4] != obuf[4]) {
-		err("generic read/write, wrong sequence in reply.");
-		return -EIO;
-	}
-	/*
-	   Windows driver doesn't check these fields, in fact sometimes
-	   the register in the reply is different that what has been sent
-
-	   if (ibuf[5] != obuf[5] || ibuf[6] != obuf[6]) {
-	   err("generic read/write, wrong register in reply.");
-	   return -EIO;
-	   }
-	   if (ibuf[7] != command) {
-	   err("generic read/write wrong command in reply.");
-	   return -EIO;
-	   }
-	 */
-	if (ibuf[16] != 0x01) {
-		err("generic read/write wrong status code in reply.");
-		return -EIO;
-	}
-	if (readwrite == AF9005_CMD_READ)
-		for (i = 0; i < len; i++)
-			values[i] = ibuf[8 + i];
-
-	return 0;
-
-}
-
-int af9005_read_ofdm_register(struct dvb_usb_device *d, u16 reg, u8 * value)
-{
-	int ret;
-	deb_reg("read register %x ", reg);
-	ret = af9005_generic_read_write(d, reg,
-					AF9005_CMD_READ, AF9005_OFDM_REG,
-					value, 1);
-	if (ret)
-		deb_reg("failed\n");
-	else
-		deb_reg("value %x\n", *value);
-	return ret;
-}
-
-int af9005_read_ofdm_registers(struct dvb_usb_device *d, u16 reg,
-			       u8 * values, int len)
-{
-	int ret;
-	deb_reg("read %d registers %x ", len, reg);
-	ret = af9005_generic_read_write(d, reg,
-					AF9005_CMD_READ, AF9005_OFDM_REG,
-					values, len);
-	if (ret)
-		deb_reg("failed\n");
-	else
-		debug_dump(values, len, deb_reg);
-	return ret;
-}
-
-int af9005_write_ofdm_register(struct dvb_usb_device *d, u16 reg, u8 value)
-{
-	int ret;
-	u8 temp = value;
-	deb_reg("write register %x value %x ", reg, value);
-	ret = af9005_generic_read_write(d, reg,
-					AF9005_CMD_WRITE, AF9005_OFDM_REG,
-					&temp, 1);
-	if (ret)
-		deb_reg("failed\n");
-	else
-		deb_reg("ok\n");
-	return ret;
-}
-
-int af9005_write_ofdm_registers(struct dvb_usb_device *d, u16 reg,
-				u8 * values, int len)
-{
-	int ret;
-	deb_reg("write %d registers %x values ", len, reg);
-	debug_dump(values, len, deb_reg);
-
-	ret = af9005_generic_read_write(d, reg,
-					AF9005_CMD_WRITE, AF9005_OFDM_REG,
-					values, len);
-	if (ret)
-		deb_reg("failed\n");
-	else
-		deb_reg("ok\n");
-	return ret;
-}
-
-int af9005_read_register_bits(struct dvb_usb_device *d, u16 reg, u8 pos,
-			      u8 len, u8 * value)
-{
-	u8 temp;
-	int ret;
-	deb_reg("read bits %x %x %x", reg, pos, len);
-	ret = af9005_read_ofdm_register(d, reg, &temp);
-	if (ret) {
-		deb_reg(" failed\n");
-		return ret;
-	}
-	*value = (temp >> pos) & regmask[len - 1];
-	deb_reg(" value %x\n", *value);
-	return 0;
-
-}
-
-int af9005_write_register_bits(struct dvb_usb_device *d, u16 reg, u8 pos,
-			       u8 len, u8 value)
-{
-	u8 temp, mask;
-	int ret;
-	deb_reg("write bits %x %x %x value %x\n", reg, pos, len, value);
-	if (pos == 0 && len == 8)
-		return af9005_write_ofdm_register(d, reg, value);
-	ret = af9005_read_ofdm_register(d, reg, &temp);
-	if (ret)
-		return ret;
-	mask = regmask[len - 1] << pos;
-	temp = (temp & ~mask) | ((value << pos) & mask);
-	return af9005_write_ofdm_register(d, reg, temp);
-
-}
-
-static int af9005_usb_read_tuner_registers(struct dvb_usb_device *d,
-					   u16 reg, u8 * values, int len)
-{
-	return af9005_generic_read_write(d, reg,
-					 AF9005_CMD_READ, AF9005_TUNER_REG,
-					 values, len);
-}
-
-static int af9005_usb_write_tuner_registers(struct dvb_usb_device *d,
-					    u16 reg, u8 * values, int len)
-{
-	return af9005_generic_read_write(d, reg,
-					 AF9005_CMD_WRITE,
-					 AF9005_TUNER_REG, values, len);
-}
-
-int af9005_write_tuner_registers(struct dvb_usb_device *d, u16 reg,
-				 u8 * values, int len)
-{
-	/* don't let the name of this function mislead you: it's just used
-	   as an interface from the firmware to the i2c bus. The actual
-	   i2c addresses are contained in the data */
-	int ret, i, done = 0, fail = 0;
-	u8 temp;
-	ret = af9005_usb_write_tuner_registers(d, reg, values, len);
-	if (ret)
-		return ret;
-	if (reg != 0xffff) {
-		/* check if write done (0xa40d bit 1) or fail (0xa40d bit 2) */
-		for (i = 0; i < 200; i++) {
-			ret =
-			    af9005_read_ofdm_register(d,
-						      xd_I2C_i2c_m_status_wdat_done,
-						      &temp);
-			if (ret)
-				return ret;
-			done = temp & (regmask[i2c_m_status_wdat_done_len - 1]
-				       << i2c_m_status_wdat_done_pos);
-			if (done)
-				break;
-			fail = temp & (regmask[i2c_m_status_wdat_fail_len - 1]
-				       << i2c_m_status_wdat_fail_pos);
-			if (fail)
-				break;
-			msleep(50);
-		}
-		if (i == 200)
-			return -ETIMEDOUT;
-		if (fail) {
-			/* clear write fail bit */
-			af9005_write_register_bits(d,
-						   xd_I2C_i2c_m_status_wdat_fail,
-						   i2c_m_status_wdat_fail_pos,
-						   i2c_m_status_wdat_fail_len,
-						   1);
-			return -EIO;
-		}
-		/* clear write done bit */
-		ret =
-		    af9005_write_register_bits(d,
-					       xd_I2C_i2c_m_status_wdat_fail,
-					       i2c_m_status_wdat_done_pos,
-					       i2c_m_status_wdat_done_len, 1);
-		if (ret)
-			return ret;
-	}
-	return 0;
-}
-
-int af9005_read_tuner_registers(struct dvb_usb_device *d, u16 reg, u8 addr,
-				u8 * values, int len)
-{
-	/* don't let the name of this function mislead you: it's just used
-	   as an interface from the firmware to the i2c bus. The actual
-	   i2c addresses are contained in the data */
-	int ret, i;
-	u8 temp, buf[2];
-
-	buf[0] = addr;		/* tuner i2c address */
-	buf[1] = values[0];	/* tuner register */
-
-	values[0] = addr + 0x01;	/* i2c read address */
-
-	if (reg == APO_REG_I2C_RW_SILICON_TUNER) {
-		/* write tuner i2c address to tuner, 0c00c0 undocumented, found by sniffing */
-		ret = af9005_write_tuner_registers(d, 0x00c0, buf, 2);
-		if (ret)
-			return ret;
-	}
-
-	/* send read command to ofsm */
-	ret = af9005_usb_read_tuner_registers(d, reg, values, 1);
-	if (ret)
-		return ret;
-
-	/* check if read done */
-	for (i = 0; i < 200; i++) {
-		ret = af9005_read_ofdm_register(d, 0xa408, &temp);
-		if (ret)
-			return ret;
-		if (temp & 0x01)
-			break;
-		msleep(50);
-	}
-	if (i == 200)
-		return -ETIMEDOUT;
-
-	/* clear read done bit (by writing 1) */
-	ret = af9005_write_ofdm_register(d, xd_I2C_i2c_m_data8, 1);
-	if (ret)
-		return ret;
-
-	/* get read data (available from 0xa400) */
-	for (i = 0; i < len; i++) {
-		ret = af9005_read_ofdm_register(d, 0xa400 + i, &temp);
-		if (ret)
-			return ret;
-		values[i] = temp;
-	}
-	return 0;
-}
-
-static int af9005_i2c_write(struct dvb_usb_device *d, u8 i2caddr, u8 reg,
-			    u8 * data, int len)
-{
-	int ret, i;
-	u8 buf[3];
-	deb_i2c("i2c_write i2caddr %x, reg %x, len %d data ", i2caddr,
-		reg, len);
-	debug_dump(data, len, deb_i2c);
-
-	for (i = 0; i < len; i++) {
-		buf[0] = i2caddr;
-		buf[1] = reg + (u8) i;
-		buf[2] = data[i];
-		ret =
-		    af9005_write_tuner_registers(d,
-						 APO_REG_I2C_RW_SILICON_TUNER,
-						 buf, 3);
-		if (ret) {
-			deb_i2c("i2c_write failed\n");
-			return ret;
-		}
-	}
-	deb_i2c("i2c_write ok\n");
-	return 0;
-}
-
-static int af9005_i2c_read(struct dvb_usb_device *d, u8 i2caddr, u8 reg,
-			   u8 * data, int len)
-{
-	int ret, i;
-	u8 temp;
-	deb_i2c("i2c_read i2caddr %x, reg %x, len %d\n ", i2caddr, reg, len);
-	for (i = 0; i < len; i++) {
-		temp = reg + i;
-		ret =
-		    af9005_read_tuner_registers(d,
-						APO_REG_I2C_RW_SILICON_TUNER,
-						i2caddr, &temp, 1);
-		if (ret) {
-			deb_i2c("i2c_read failed\n");
-			return ret;
-		}
-		data[i] = temp;
-	}
-	deb_i2c("i2c data read: ");
-	debug_dump(data, len, deb_i2c);
-	return 0;
-}
-
-static int af9005_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
-			   int num)
-{
-	/* only implements what the mt2060 module does, don't know how
-	   to make it really generic */
-	struct dvb_usb_device *d = i2c_get_adapdata(adap);
-	int ret;
-	u8 reg, addr;
-	u8 *value;
-
-	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
-		return -EAGAIN;
-
-	if (num > 2)
-		warn("more than 2 i2c messages at a time is not handled yet. TODO.");
-
-	if (num == 2) {
-		/* reads a single register */
-		reg = *msg[0].buf;
-		addr = msg[0].addr;
-		value = msg[1].buf;
-		ret = af9005_i2c_read(d, addr, reg, value, 1);
-		if (ret == 0)
-			ret = 2;
-	} else {
-		/* write one or more registers */
-		reg = msg[0].buf[0];
-		addr = msg[0].addr;
-		value = &msg[0].buf[1];
-		ret = af9005_i2c_write(d, addr, reg, value, msg[0].len - 1);
-		if (ret == 0)
-			ret = 1;
-	}
-
-	mutex_unlock(&d->i2c_mutex);
-	return ret;
-}
-
-static u32 af9005_i2c_func(struct i2c_adapter *adapter)
-{
-	return I2C_FUNC_I2C;
-}
-
-static struct i2c_algorithm af9005_i2c_algo = {
-	.master_xfer = af9005_i2c_xfer,
-	.functionality = af9005_i2c_func,
-};
-
-int af9005_send_command(struct dvb_usb_device *d, u8 command, u8 * wbuf,
-			int wlen, u8 * rbuf, int rlen)
-{
-	struct af9005_device_state *st = d->priv;
-
-	int ret, i, packet_len;
-	u8 buf[64];
-	u8 ibuf[64];
-
-	if (wlen < 0) {
-		err("send command, wlen less than 0 bytes. Makes no sense.");
-		return -EINVAL;
-	}
-	if (wlen > 54) {
-		err("send command, wlen more than 54 bytes. Not supported.");
-		return -EINVAL;
-	}
-	if (rlen > 54) {
-		err("send command, rlen more than 54 bytes. Not supported.");
-		return -EINVAL;
-	}
-	packet_len = wlen + 5;
-	buf[0] = (u8) (packet_len & 0xff);
-	buf[1] = (u8) ((packet_len & 0xff00) >> 8);
-
-	buf[2] = 0x26;		/* packet type */
-	buf[3] = wlen + 3;
-	buf[4] = st->sequence++;
-	buf[5] = command;
-	buf[6] = wlen;
-	for (i = 0; i < wlen; i++)
-		buf[7 + i] = wbuf[i];
-	ret = dvb_usb_generic_rw(d, buf, wlen + 7, ibuf, rlen + 7, 0);
-	if (ret)
-		return ret;
-	if (ibuf[2] != 0x27) {
-		err("send command, wrong reply code.");
-		return -EIO;
-	}
-	if (ibuf[4] != buf[4]) {
-		err("send command, wrong sequence in reply.");
-		return -EIO;
-	}
-	if (ibuf[5] != 0x01) {
-		err("send command, wrong status code in reply.");
-		return -EIO;
-	}
-	if (ibuf[6] != rlen) {
-		err("send command, invalid data length in reply.");
-		return -EIO;
-	}
-	for (i = 0; i < rlen; i++)
-		rbuf[i] = ibuf[i + 7];
-	return 0;
-}
-
-int af9005_read_eeprom(struct dvb_usb_device *d, u8 address, u8 * values,
-		       int len)
-{
-	struct af9005_device_state *st = d->priv;
-	u8 obuf[16], ibuf[14];
-	int ret, i;
-
-	memset(obuf, 0, sizeof(obuf));
-	memset(ibuf, 0, sizeof(ibuf));
-
-	obuf[0] = 14;		/* length of rest of packet low */
-	obuf[1] = 0;		/* length of rest of packer high */
-
-	obuf[2] = 0x2a;		/* read/write eeprom */
-
-	obuf[3] = 12;		/* size */
-
-	obuf[4] = st->sequence++;
-
-	obuf[5] = 0;		/* read */
-
-	obuf[6] = len;
-	obuf[7] = address;
-	ret = dvb_usb_generic_rw(d, obuf, 16, ibuf, 14, 0);
-	if (ret)
-		return ret;
-	if (ibuf[2] != 0x2b) {
-		err("Read eeprom, invalid reply code");
-		return -EIO;
-	}
-	if (ibuf[3] != 10) {
-		err("Read eeprom, invalid reply length");
-		return -EIO;
-	}
-	if (ibuf[4] != obuf[4]) {
-		err("Read eeprom, wrong sequence in reply ");
-		return -EIO;
-	}
-	if (ibuf[5] != 1) {
-		err("Read eeprom, wrong status in reply ");
-		return -EIO;
-	}
-	for (i = 0; i < len; i++) {
-		values[i] = ibuf[6 + i];
-	}
-	return 0;
-}
-
-static int af9005_boot_packet(struct usb_device *udev, int type, u8 * reply)
-{
-	u8 buf[FW_BULKOUT_SIZE + 2];
-	u16 checksum;
-	int act_len, i, ret;
-	memset(buf, 0, sizeof(buf));
-	buf[0] = (u8) (FW_BULKOUT_SIZE & 0xff);
-	buf[1] = (u8) ((FW_BULKOUT_SIZE >> 8) & 0xff);
-	switch (type) {
-	case FW_CONFIG:
-		buf[2] = 0x11;
-		buf[3] = 0x04;
-		buf[4] = 0x00;	/* sequence number, original driver doesn't increment it here */
-		buf[5] = 0x03;
-		checksum = buf[4] + buf[5];
-		buf[6] = (u8) ((checksum >> 8) & 0xff);
-		buf[7] = (u8) (checksum & 0xff);
-		break;
-	case FW_CONFIRM:
-		buf[2] = 0x11;
-		buf[3] = 0x04;
-		buf[4] = 0x00;	/* sequence number, original driver doesn't increment it here */
-		buf[5] = 0x01;
-		checksum = buf[4] + buf[5];
-		buf[6] = (u8) ((checksum >> 8) & 0xff);
-		buf[7] = (u8) (checksum & 0xff);
-		break;
-	case FW_BOOT:
-		buf[2] = 0x10;
-		buf[3] = 0x08;
-		buf[4] = 0x00;	/* sequence number, original driver doesn't increment it here */
-		buf[5] = 0x97;
-		buf[6] = 0xaa;
-		buf[7] = 0x55;
-		buf[8] = 0xa5;
-		buf[9] = 0x5a;
-		checksum = 0;
-		for (i = 4; i <= 9; i++)
-			checksum += buf[i];
-		buf[10] = (u8) ((checksum >> 8) & 0xff);
-		buf[11] = (u8) (checksum & 0xff);
-		break;
-	default:
-		err("boot packet invalid boot packet type");
-		return -EINVAL;
-	}
-	deb_fw(">>> ");
-	debug_dump(buf, FW_BULKOUT_SIZE + 2, deb_fw);
-
-	ret = usb_bulk_msg(udev,
-			   usb_sndbulkpipe(udev, 0x02),
-			   buf, FW_BULKOUT_SIZE + 2, &act_len, 2000);
-	if (ret)
-		err("boot packet bulk message failed: %d (%d/%d)", ret,
-		    FW_BULKOUT_SIZE + 2, act_len);
-	else
-		ret = act_len != FW_BULKOUT_SIZE + 2 ? -1 : 0;
-	if (ret)
-		return ret;
-	memset(buf, 0, 9);
-	ret = usb_bulk_msg(udev,
-			   usb_rcvbulkpipe(udev, 0x01), buf, 9, &act_len, 2000);
-	if (ret) {
-		err("boot packet recv bulk message failed: %d", ret);
-		return ret;
-	}
-	deb_fw("<<< ");
-	debug_dump(buf, act_len, deb_fw);
-	checksum = 0;
-	switch (type) {
-	case FW_CONFIG:
-		if (buf[2] != 0x11) {
-			err("boot bad config header.");
-			return -EIO;
-		}
-		if (buf[3] != 0x05) {
-			err("boot bad config size.");
-			return -EIO;
-		}
-		if (buf[4] != 0x00) {
-			err("boot bad config sequence.");
-			return -EIO;
-		}
-		if (buf[5] != 0x04) {
-			err("boot bad config subtype.");
-			return -EIO;
-		}
-		for (i = 4; i <= 6; i++)
-			checksum += buf[i];
-		if (buf[7] * 256 + buf[8] != checksum) {
-			err("boot bad config checksum.");
-			return -EIO;
-		}
-		*reply = buf[6];
-		break;
-	case FW_CONFIRM:
-		if (buf[2] != 0x11) {
-			err("boot bad confirm header.");
-			return -EIO;
-		}
-		if (buf[3] != 0x05) {
-			err("boot bad confirm size.");
-			return -EIO;
-		}
-		if (buf[4] != 0x00) {
-			err("boot bad confirm sequence.");
-			return -EIO;
-		}
-		if (buf[5] != 0x02) {
-			err("boot bad confirm subtype.");
-			return -EIO;
-		}
-		for (i = 4; i <= 6; i++)
-			checksum += buf[i];
-		if (buf[7] * 256 + buf[8] != checksum) {
-			err("boot bad confirm checksum.");
-			return -EIO;
-		}
-		*reply = buf[6];
-		break;
-	case FW_BOOT:
-		if (buf[2] != 0x10) {
-			err("boot bad boot header.");
-			return -EIO;
-		}
-		if (buf[3] != 0x05) {
-			err("boot bad boot size.");
-			return -EIO;
-		}
-		if (buf[4] != 0x00) {
-			err("boot bad boot sequence.");
-			return -EIO;
-		}
-		if (buf[5] != 0x01) {
-			err("boot bad boot pattern 01.");
-			return -EIO;
-		}
-		if (buf[6] != 0x10) {
-			err("boot bad boot pattern 10.");
-			return -EIO;
-		}
-		for (i = 4; i <= 6; i++)
-			checksum += buf[i];
-		if (buf[7] * 256 + buf[8] != checksum) {
-			err("boot bad boot checksum.");
-			return -EIO;
-		}
-		break;
-
-	}
-
-	return 0;
-}
-
-static int af9005_download_firmware(struct usb_device *udev, const struct firmware *fw)
-{
-	int i, packets, ret, act_len;
-
-	u8 buf[FW_BULKOUT_SIZE + 2];
-	u8 reply;
-
-	ret = af9005_boot_packet(udev, FW_CONFIG, &reply);
-	if (ret)
-		return ret;
-	if (reply != 0x01) {
-		err("before downloading firmware, FW_CONFIG expected 0x01, received 0x%x", reply);
-		return -EIO;
-	}
-	packets = fw->size / FW_BULKOUT_SIZE;
-	buf[0] = (u8) (FW_BULKOUT_SIZE & 0xff);
-	buf[1] = (u8) ((FW_BULKOUT_SIZE >> 8) & 0xff);
-	for (i = 0; i < packets; i++) {
-		memcpy(&buf[2], fw->data + i * FW_BULKOUT_SIZE,
-		       FW_BULKOUT_SIZE);
-		deb_fw(">>> ");
-		debug_dump(buf, FW_BULKOUT_SIZE + 2, deb_fw);
-		ret = usb_bulk_msg(udev,
-				   usb_sndbulkpipe(udev, 0x02),
-				   buf, FW_BULKOUT_SIZE + 2, &act_len, 1000);
-		if (ret) {
-			err("firmware download failed at packet %d with code %d", i, ret);
-			return ret;
-		}
-	}
-	ret = af9005_boot_packet(udev, FW_CONFIRM, &reply);
-	if (ret)
-		return ret;
-	if (reply != (u8) (packets & 0xff)) {
-		err("after downloading firmware, FW_CONFIRM expected 0x%x, received 0x%x", packets & 0xff, reply);
-		return -EIO;
-	}
-	ret = af9005_boot_packet(udev, FW_BOOT, &reply);
-	if (ret)
-		return ret;
-	ret = af9005_boot_packet(udev, FW_CONFIG, &reply);
-	if (ret)
-		return ret;
-	if (reply != 0x02) {
-		err("after downloading firmware, FW_CONFIG expected 0x02, received 0x%x", reply);
-		return -EIO;
-	}
-
-	return 0;
-
-}
-
-int af9005_led_control(struct dvb_usb_device *d, int onoff)
-{
-	struct af9005_device_state *st = d->priv;
-	int temp, ret;
-
-	if (onoff && dvb_usb_af9005_led)
-		temp = 1;
-	else
-		temp = 0;
-	if (st->led_state != temp) {
-		ret =
-		    af9005_write_register_bits(d, xd_p_reg_top_locken1,
-					       reg_top_locken1_pos,
-					       reg_top_locken1_len, temp);
-		if (ret)
-			return ret;
-		ret =
-		    af9005_write_register_bits(d, xd_p_reg_top_lock1,
-					       reg_top_lock1_pos,
-					       reg_top_lock1_len, temp);
-		if (ret)
-			return ret;
-		st->led_state = temp;
-	}
-	return 0;
-}
-
-static int af9005_frontend_attach(struct dvb_usb_adapter *adap)
-{
-	u8 buf[8];
-	int i;
-
-	/* without these calls the first commands after downloading
-	   the firmware fail. I put these calls here to simulate
-	   what it is done in dvb-usb-init.c.
-	 */
-	struct usb_device *udev = adap->dev->udev;
-	usb_clear_halt(udev, usb_sndbulkpipe(udev, 2));
-	usb_clear_halt(udev, usb_rcvbulkpipe(udev, 1));
-	if (dvb_usb_af9005_dump_eeprom) {
-		printk("EEPROM DUMP\n");
-		for (i = 0; i < 255; i += 8) {
-			af9005_read_eeprom(adap->dev, i, buf, 8);
-			printk("ADDR %x ", i);
-			debug_dump(buf, 8, printk);
-		}
-	}
-	adap->fe_adap[0].fe = af9005_fe_attach(adap->dev);
-	return 0;
-}
-
-static int af9005_rc_query(struct dvb_usb_device *d, u32 * event, int *state)
-{
-	struct af9005_device_state *st = d->priv;
-	int ret, len;
-
-	u8 obuf[5];
-	u8 ibuf[256];
-
-	*state = REMOTE_NO_KEY_PRESSED;
-	if (rc_decode == NULL) {
-		/* it shouldn't never come here */
-		return 0;
-	}
-	/* deb_info("rc_query\n"); */
-	obuf[0] = 3;		/* rest of packet length low */
-	obuf[1] = 0;		/* rest of packet lentgh high */
-	obuf[2] = 0x40;		/* read remote */
-	obuf[3] = 1;		/* rest of packet length */
-	obuf[4] = st->sequence++;	/* sequence number */
-	ret = dvb_usb_generic_rw(d, obuf, 5, ibuf, 256, 0);
-	if (ret) {
-		err("rc query failed");
-		return ret;
-	}
-	if (ibuf[2] != 0x41) {
-		err("rc query bad header.");
-		return -EIO;
-	}
-	if (ibuf[4] != obuf[4]) {
-		err("rc query bad sequence.");
-		return -EIO;
-	}
-	len = ibuf[5];
-	if (len > 246) {
-		err("rc query invalid length");
-		return -EIO;
-	}
-	if (len > 0) {
-		deb_rc("rc data (%d) ", len);
-		debug_dump((ibuf + 6), len, deb_rc);
-		ret = rc_decode(d, &ibuf[6], len, event, state);
-		if (ret) {
-			err("rc_decode failed");
-			return ret;
-		} else {
-			deb_rc("rc_decode state %x event %x\n", *state, *event);
-			if (*state == REMOTE_KEY_REPEAT)
-				*event = d->last_event;
-		}
-	}
-	return 0;
-}
-
-static int af9005_power_ctrl(struct dvb_usb_device *d, int onoff)
-{
-
-	return 0;
-}
-
-static int af9005_pid_filter_control(struct dvb_usb_adapter *adap, int onoff)
-{
-	int ret;
-	deb_info("pid filter control  onoff %d\n", onoff);
-	if (onoff) {
-		ret =
-		    af9005_write_ofdm_register(adap->dev, XD_MP2IF_DMX_CTRL, 1);
-		if (ret)
-			return ret;
-		ret =
-		    af9005_write_register_bits(adap->dev,
-					       XD_MP2IF_DMX_CTRL, 1, 1, 1);
-		if (ret)
-			return ret;
-		ret =
-		    af9005_write_ofdm_register(adap->dev, XD_MP2IF_DMX_CTRL, 1);
-	} else
-		ret =
-		    af9005_write_ofdm_register(adap->dev, XD_MP2IF_DMX_CTRL, 0);
-	if (ret)
-		return ret;
-	deb_info("pid filter control ok\n");
-	return 0;
-}
-
-static int af9005_pid_filter(struct dvb_usb_adapter *adap, int index,
-			     u16 pid, int onoff)
-{
-	u8 cmd = index & 0x1f;
-	int ret;
-	deb_info("set pid filter, index %d, pid %x, onoff %d\n", index,
-		 pid, onoff);
-	if (onoff) {
-		/* cannot use it as pid_filter_ctrl since it has to be done
-		   before setting the first pid */
-		if (adap->feedcount == 1) {
-			deb_info("first pid set, enable pid table\n");
-			ret = af9005_pid_filter_control(adap, onoff);
-			if (ret)
-				return ret;
-		}
-		ret =
-		    af9005_write_ofdm_register(adap->dev,
-					       XD_MP2IF_PID_DATA_L,
-					       (u8) (pid & 0xff));
-		if (ret)
-			return ret;
-		ret =
-		    af9005_write_ofdm_register(adap->dev,
-					       XD_MP2IF_PID_DATA_H,
-					       (u8) (pid >> 8));
-		if (ret)
-			return ret;
-		cmd |= 0x20 | 0x40;
-	} else {
-		if (adap->feedcount == 0) {
-			deb_info("last pid unset, disable pid table\n");
-			ret = af9005_pid_filter_control(adap, onoff);
-			if (ret)
-				return ret;
-		}
-	}
-	ret = af9005_write_ofdm_register(adap->dev, XD_MP2IF_PID_IDX, cmd);
-	if (ret)
-		return ret;
-	deb_info("set pid ok\n");
-	return 0;
-}
-
-static int af9005_identify_state(struct usb_device *udev,
-				 struct dvb_usb_device_properties *props,
-				 struct dvb_usb_device_description **desc,
-				 int *cold)
-{
-	int ret;
-	u8 reply;
-	ret = af9005_boot_packet(udev, FW_CONFIG, &reply);
-	if (ret)
-		return ret;
-	deb_info("result of FW_CONFIG in identify state %d\n", reply);
-	if (reply == 0x01)
-		*cold = 1;
-	else if (reply == 0x02)
-		*cold = 0;
-	else
-		return -EIO;
-	deb_info("Identify state cold = %d\n", *cold);
-	return 0;
-}
-
-static struct dvb_usb_device_properties af9005_properties;
-
-static int af9005_usb_probe(struct usb_interface *intf,
-			    const struct usb_device_id *id)
-{
-	return dvb_usb_device_init(intf, &af9005_properties,
-				   THIS_MODULE, NULL, adapter_nr);
-}
-
-enum af9005_usb_table_entry {
-	AFATECH_AF9005,
-	TERRATEC_AF9005,
-	ANSONIC_AF9005,
-};
-
-static struct usb_device_id af9005_usb_table[] = {
-	[AFATECH_AF9005] = {USB_DEVICE(USB_VID_AFATECH,
-				USB_PID_AFATECH_AF9005)},
-	[TERRATEC_AF9005] = {USB_DEVICE(USB_VID_TERRATEC,
-				USB_PID_TERRATEC_CINERGY_T_USB_XE)},
-	[ANSONIC_AF9005] = {USB_DEVICE(USB_VID_ANSONIC,
-				USB_PID_ANSONIC_DVBT_USB)},
-	{ }
-};
-
-MODULE_DEVICE_TABLE(usb, af9005_usb_table);
-
-static struct dvb_usb_device_properties af9005_properties = {
-	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
-
-	.usb_ctrl = DEVICE_SPECIFIC,
-	.firmware = "af9005.fw",
-	.download_firmware = af9005_download_firmware,
-	.no_reconnect = 1,
-
-	.size_of_priv = sizeof(struct af9005_device_state),
-
-	.num_adapters = 1,
-	.adapter = {
-		    {
-		    .num_frontends = 1,
-		    .fe = {{
-		     .caps =
-		     DVB_USB_ADAP_HAS_PID_FILTER |
-		     DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
-		     .pid_filter_count = 32,
-		     .pid_filter = af9005_pid_filter,
-		     /* .pid_filter_ctrl = af9005_pid_filter_control, */
-		     .frontend_attach = af9005_frontend_attach,
-		     /* .tuner_attach     = af9005_tuner_attach, */
-		     /* parameter for the MPEG2-data transfer */
-		     .stream = {
-				.type = USB_BULK,
-				.count = 10,
-				.endpoint = 0x04,
-				.u = {
-				      .bulk = {
-					       .buffersize = 4096,	/* actual size seen is 3948 */
-					       }
-				      }
-				},
-		     }},
-		     }
-		    },
-	.power_ctrl = af9005_power_ctrl,
-	.identify_state = af9005_identify_state,
-
-	.i2c_algo = &af9005_i2c_algo,
-
-	.rc.legacy = {
-		.rc_interval = 200,
-		.rc_map_table = NULL,
-		.rc_map_size = 0,
-		.rc_query = af9005_rc_query,
-	},
-
-	.generic_bulk_ctrl_endpoint          = 2,
-	.generic_bulk_ctrl_endpoint_response = 1,
-
-	.num_device_descs = 3,
-	.devices = {
-		    {.name = "Afatech DVB-T USB1.1 stick",
-		     .cold_ids = {&af9005_usb_table[AFATECH_AF9005], NULL},
-		     .warm_ids = {NULL},
-		     },
-		    {.name = "TerraTec Cinergy T USB XE",
-		     .cold_ids = {&af9005_usb_table[TERRATEC_AF9005], NULL},
-		     .warm_ids = {NULL},
-		     },
-		    {.name = "Ansonic DVB-T USB1.1 stick",
-		     .cold_ids = {&af9005_usb_table[ANSONIC_AF9005], NULL},
-		     .warm_ids = {NULL},
-		     },
-		    {NULL},
-		    }
-};
-
-/* usb specific object needed to register this driver with the usb subsystem */
-static struct usb_driver af9005_usb_driver = {
-	.name = "dvb_usb_af9005",
-	.probe = af9005_usb_probe,
-	.disconnect = dvb_usb_device_exit,
-	.id_table = af9005_usb_table,
-};
-
-/* module stuff */
-static int __init af9005_usb_module_init(void)
-{
-	int result;
-	if ((result = usb_register(&af9005_usb_driver))) {
-		err("usb_register failed. (%d)", result);
-		return result;
-	}
-	rc_decode = symbol_request(af9005_rc_decode);
-	rc_keys = symbol_request(rc_map_af9005_table);
-	rc_keys_size = symbol_request(rc_map_af9005_table_size);
-	if (rc_decode == NULL || rc_keys == NULL || rc_keys_size == NULL) {
-		err("af9005_rc_decode function not found, disabling remote");
-		af9005_properties.rc.legacy.rc_query = NULL;
-	} else {
-		af9005_properties.rc.legacy.rc_map_table = rc_keys;
-		af9005_properties.rc.legacy.rc_map_size = *rc_keys_size;
-	}
-
-	return 0;
-}
-
-static void __exit af9005_usb_module_exit(void)
-{
-	/* release rc decode symbols */
-	if (rc_decode != NULL)
-		symbol_put(af9005_rc_decode);
-	if (rc_keys != NULL)
-		symbol_put(rc_map_af9005_table);
-	if (rc_keys_size != NULL)
-		symbol_put(rc_map_af9005_table_size);
-	/* deregister this driver from the USB subsystem */
-	usb_deregister(&af9005_usb_driver);
-}
-
-module_init(af9005_usb_module_init);
-module_exit(af9005_usb_module_exit);
-
-MODULE_AUTHOR("Luca Olivetti <luca@ventoso.org>");
-MODULE_DESCRIPTION("Driver for Afatech 9005 DVB-T USB1.1 stick");
-MODULE_VERSION("1.0");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/af9005.h b/drivers/media/dvb/dvb-usb/af9005.h
deleted file mode 100644
index 6a2bf3d..0000000
--- a/drivers/media/dvb/dvb-usb/af9005.h
+++ /dev/null
@@ -1,3496 +0,0 @@
-/* Common header-file of the Linux driver for the Afatech 9005
- * USB1.1 DVB-T receiver.
- *
- * Copyright (C) 2007 Luca Olivetti (luca@ventoso.org)
- *
- * Thanks to Afatech who kindly provided information.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You 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.
- *
- * see Documentation/dvb/README.dvb-usb for more information
- */
-#ifndef _DVB_USB_AF9005_H_
-#define _DVB_USB_AF9005_H_
-
-#define DVB_USB_LOG_PREFIX "af9005"
-#include "dvb-usb.h"
-
-extern int dvb_usb_af9005_debug;
-#define deb_info(args...) dprintk(dvb_usb_af9005_debug,0x01,args)
-#define deb_xfer(args...) dprintk(dvb_usb_af9005_debug,0x02,args)
-#define deb_rc(args...)   dprintk(dvb_usb_af9005_debug,0x04,args)
-#define deb_reg(args...)  dprintk(dvb_usb_af9005_debug,0x08,args)
-#define deb_i2c(args...)  dprintk(dvb_usb_af9005_debug,0x10,args)
-#define deb_fw(args...)   dprintk(dvb_usb_af9005_debug,0x20,args)
-
-extern bool dvb_usb_af9005_led;
-
-/* firmware */
-#define FW_BULKOUT_SIZE 250
-enum {
-	FW_CONFIG,
-	FW_CONFIRM,
-	FW_BOOT
-};
-
-/* af9005 commands */
-#define AF9005_OFDM_REG  0
-#define AF9005_TUNER_REG 1
-
-#define AF9005_REGISTER_RW     0x20
-#define AF9005_REGISTER_RW_ACK 0x21
-
-#define AF9005_CMD_OFDM_REG 0x00
-#define AF9005_CMD_TUNER    0x80
-#define AF9005_CMD_BURST    0x02
-#define AF9005_CMD_AUTOINC  0x04
-#define AF9005_CMD_READ     0x00
-#define AF9005_CMD_WRITE    0x01
-
-/* af9005 registers */
-#define APO_REG_RESET					0xAEFF
-
-#define APO_REG_I2C_RW_CAN_TUNER            0xF000
-#define APO_REG_I2C_RW_SILICON_TUNER        0xF001
-#define APO_REG_GPIO_RW_SILICON_TUNER       0xFFFE	/*  also for OFSM */
-#define APO_REG_TRIGGER_OFSM                0xFFFF	/*  also for OFSM */
-
-/***********************************************************************
- *  Apollo Registers from VLSI					       *
- ***********************************************************************/
-#define xd_p_reg_aagc_inverted_agc	0xA000
-#define	reg_aagc_inverted_agc_pos 0
-#define	reg_aagc_inverted_agc_len 1
-#define	reg_aagc_inverted_agc_lsb 0
-#define xd_p_reg_aagc_sign_only	0xA000
-#define	reg_aagc_sign_only_pos 1
-#define	reg_aagc_sign_only_len 1
-#define	reg_aagc_sign_only_lsb 0
-#define xd_p_reg_aagc_slow_adc_en	0xA000
-#define	reg_aagc_slow_adc_en_pos 2
-#define	reg_aagc_slow_adc_en_len 1
-#define	reg_aagc_slow_adc_en_lsb 0
-#define xd_p_reg_aagc_slow_adc_scale	0xA000
-#define	reg_aagc_slow_adc_scale_pos 3
-#define	reg_aagc_slow_adc_scale_len 5
-#define	reg_aagc_slow_adc_scale_lsb 0
-#define xd_p_reg_aagc_check_slow_adc_lock	0xA001
-#define	reg_aagc_check_slow_adc_lock_pos 0
-#define	reg_aagc_check_slow_adc_lock_len 1
-#define	reg_aagc_check_slow_adc_lock_lsb 0
-#define xd_p_reg_aagc_init_control	0xA001
-#define	reg_aagc_init_control_pos 1
-#define	reg_aagc_init_control_len 1
-#define	reg_aagc_init_control_lsb 0
-#define xd_p_reg_aagc_total_gain_sel	0xA001
-#define	reg_aagc_total_gain_sel_pos 2
-#define	reg_aagc_total_gain_sel_len 2
-#define	reg_aagc_total_gain_sel_lsb 0
-#define xd_p_reg_aagc_out_inv	0xA001
-#define	reg_aagc_out_inv_pos 5
-#define	reg_aagc_out_inv_len 1
-#define	reg_aagc_out_inv_lsb 0
-#define xd_p_reg_aagc_int_en	0xA001
-#define	reg_aagc_int_en_pos 6
-#define	reg_aagc_int_en_len 1
-#define	reg_aagc_int_en_lsb 0
-#define xd_p_reg_aagc_lock_change_flag	0xA001
-#define	reg_aagc_lock_change_flag_pos 7
-#define	reg_aagc_lock_change_flag_len 1
-#define	reg_aagc_lock_change_flag_lsb 0
-#define xd_p_reg_aagc_rf_loop_bw_scale_acquire	0xA002
-#define	reg_aagc_rf_loop_bw_scale_acquire_pos 0
-#define	reg_aagc_rf_loop_bw_scale_acquire_len 5
-#define	reg_aagc_rf_loop_bw_scale_acquire_lsb 0
-#define xd_p_reg_aagc_rf_loop_bw_scale_track	0xA003
-#define	reg_aagc_rf_loop_bw_scale_track_pos 0
-#define	reg_aagc_rf_loop_bw_scale_track_len 5
-#define	reg_aagc_rf_loop_bw_scale_track_lsb 0
-#define xd_p_reg_aagc_if_loop_bw_scale_acquire	0xA004
-#define	reg_aagc_if_loop_bw_scale_acquire_pos 0
-#define	reg_aagc_if_loop_bw_scale_acquire_len 5
-#define	reg_aagc_if_loop_bw_scale_acquire_lsb 0
-#define xd_p_reg_aagc_if_loop_bw_scale_track	0xA005
-#define	reg_aagc_if_loop_bw_scale_track_pos 0
-#define	reg_aagc_if_loop_bw_scale_track_len 5
-#define	reg_aagc_if_loop_bw_scale_track_lsb 0
-#define xd_p_reg_aagc_max_rf_agc_7_0	0xA006
-#define	reg_aagc_max_rf_agc_7_0_pos 0
-#define	reg_aagc_max_rf_agc_7_0_len 8
-#define	reg_aagc_max_rf_agc_7_0_lsb 0
-#define xd_p_reg_aagc_max_rf_agc_9_8	0xA007
-#define	reg_aagc_max_rf_agc_9_8_pos 0
-#define	reg_aagc_max_rf_agc_9_8_len 2
-#define	reg_aagc_max_rf_agc_9_8_lsb 8
-#define xd_p_reg_aagc_min_rf_agc_7_0	0xA008
-#define	reg_aagc_min_rf_agc_7_0_pos 0
-#define	reg_aagc_min_rf_agc_7_0_len 8
-#define	reg_aagc_min_rf_agc_7_0_lsb 0
-#define xd_p_reg_aagc_min_rf_agc_9_8	0xA009
-#define	reg_aagc_min_rf_agc_9_8_pos 0
-#define	reg_aagc_min_rf_agc_9_8_len 2
-#define	reg_aagc_min_rf_agc_9_8_lsb 8
-#define xd_p_reg_aagc_max_if_agc_7_0	0xA00A
-#define	reg_aagc_max_if_agc_7_0_pos 0
-#define	reg_aagc_max_if_agc_7_0_len 8
-#define	reg_aagc_max_if_agc_7_0_lsb 0
-#define xd_p_reg_aagc_max_if_agc_9_8	0xA00B
-#define	reg_aagc_max_if_agc_9_8_pos 0
-#define	reg_aagc_max_if_agc_9_8_len 2
-#define	reg_aagc_max_if_agc_9_8_lsb 8
-#define xd_p_reg_aagc_min_if_agc_7_0	0xA00C
-#define	reg_aagc_min_if_agc_7_0_pos 0
-#define	reg_aagc_min_if_agc_7_0_len 8
-#define	reg_aagc_min_if_agc_7_0_lsb 0
-#define xd_p_reg_aagc_min_if_agc_9_8	0xA00D
-#define	reg_aagc_min_if_agc_9_8_pos 0
-#define	reg_aagc_min_if_agc_9_8_len 2
-#define	reg_aagc_min_if_agc_9_8_lsb 8
-#define xd_p_reg_aagc_lock_sample_scale	0xA00E
-#define	reg_aagc_lock_sample_scale_pos 0
-#define	reg_aagc_lock_sample_scale_len 5
-#define	reg_aagc_lock_sample_scale_lsb 0
-#define xd_p_reg_aagc_rf_agc_lock_scale_acquire	0xA00F
-#define	reg_aagc_rf_agc_lock_scale_acquire_pos 0
-#define	reg_aagc_rf_agc_lock_scale_acquire_len 3
-#define	reg_aagc_rf_agc_lock_scale_acquire_lsb 0
-#define xd_p_reg_aagc_rf_agc_lock_scale_track	0xA00F
-#define	reg_aagc_rf_agc_lock_scale_track_pos 3
-#define	reg_aagc_rf_agc_lock_scale_track_len 3
-#define	reg_aagc_rf_agc_lock_scale_track_lsb 0
-#define xd_p_reg_aagc_if_agc_lock_scale_acquire	0xA010
-#define	reg_aagc_if_agc_lock_scale_acquire_pos 0
-#define	reg_aagc_if_agc_lock_scale_acquire_len 3
-#define	reg_aagc_if_agc_lock_scale_acquire_lsb 0
-#define xd_p_reg_aagc_if_agc_lock_scale_track	0xA010
-#define	reg_aagc_if_agc_lock_scale_track_pos 3
-#define	reg_aagc_if_agc_lock_scale_track_len 3
-#define	reg_aagc_if_agc_lock_scale_track_lsb 0
-#define xd_p_reg_aagc_rf_top_numerator_7_0	0xA011
-#define	reg_aagc_rf_top_numerator_7_0_pos 0
-#define	reg_aagc_rf_top_numerator_7_0_len 8
-#define	reg_aagc_rf_top_numerator_7_0_lsb 0
-#define xd_p_reg_aagc_rf_top_numerator_9_8	0xA012
-#define	reg_aagc_rf_top_numerator_9_8_pos 0
-#define	reg_aagc_rf_top_numerator_9_8_len 2
-#define	reg_aagc_rf_top_numerator_9_8_lsb 8
-#define xd_p_reg_aagc_if_top_numerator_7_0	0xA013
-#define	reg_aagc_if_top_numerator_7_0_pos 0
-#define	reg_aagc_if_top_numerator_7_0_len 8
-#define	reg_aagc_if_top_numerator_7_0_lsb 0
-#define xd_p_reg_aagc_if_top_numerator_9_8	0xA014
-#define	reg_aagc_if_top_numerator_9_8_pos 0
-#define	reg_aagc_if_top_numerator_9_8_len 2
-#define	reg_aagc_if_top_numerator_9_8_lsb 8
-#define xd_p_reg_aagc_adc_out_desired_7_0	0xA015
-#define	reg_aagc_adc_out_desired_7_0_pos 0
-#define	reg_aagc_adc_out_desired_7_0_len 8
-#define	reg_aagc_adc_out_desired_7_0_lsb 0
-#define xd_p_reg_aagc_adc_out_desired_8	0xA016
-#define	reg_aagc_adc_out_desired_8_pos 0
-#define	reg_aagc_adc_out_desired_8_len 1
-#define	reg_aagc_adc_out_desired_8_lsb 0
-#define xd_p_reg_aagc_fixed_gain	0xA016
-#define	reg_aagc_fixed_gain_pos 3
-#define	reg_aagc_fixed_gain_len 1
-#define	reg_aagc_fixed_gain_lsb 0
-#define xd_p_reg_aagc_lock_count_th	0xA016
-#define	reg_aagc_lock_count_th_pos 4
-#define	reg_aagc_lock_count_th_len 4
-#define	reg_aagc_lock_count_th_lsb 0
-#define xd_p_reg_aagc_fixed_rf_agc_control_7_0	0xA017
-#define	reg_aagc_fixed_rf_agc_control_7_0_pos 0
-#define	reg_aagc_fixed_rf_agc_control_7_0_len 8
-#define	reg_aagc_fixed_rf_agc_control_7_0_lsb 0
-#define xd_p_reg_aagc_fixed_rf_agc_control_15_8	0xA018
-#define	reg_aagc_fixed_rf_agc_control_15_8_pos 0
-#define	reg_aagc_fixed_rf_agc_control_15_8_len 8
-#define	reg_aagc_fixed_rf_agc_control_15_8_lsb 8
-#define xd_p_reg_aagc_fixed_rf_agc_control_23_16	0xA019
-#define	reg_aagc_fixed_rf_agc_control_23_16_pos 0
-#define	reg_aagc_fixed_rf_agc_control_23_16_len 8
-#define	reg_aagc_fixed_rf_agc_control_23_16_lsb 16
-#define xd_p_reg_aagc_fixed_rf_agc_control_30_24	0xA01A
-#define	reg_aagc_fixed_rf_agc_control_30_24_pos 0
-#define	reg_aagc_fixed_rf_agc_control_30_24_len 7
-#define	reg_aagc_fixed_rf_agc_control_30_24_lsb 24
-#define xd_p_reg_aagc_fixed_if_agc_control_7_0	0xA01B
-#define	reg_aagc_fixed_if_agc_control_7_0_pos 0
-#define	reg_aagc_fixed_if_agc_control_7_0_len 8
-#define	reg_aagc_fixed_if_agc_control_7_0_lsb 0
-#define xd_p_reg_aagc_fixed_if_agc_control_15_8	0xA01C
-#define	reg_aagc_fixed_if_agc_control_15_8_pos 0
-#define	reg_aagc_fixed_if_agc_control_15_8_len 8
-#define	reg_aagc_fixed_if_agc_control_15_8_lsb 8
-#define xd_p_reg_aagc_fixed_if_agc_control_23_16	0xA01D
-#define	reg_aagc_fixed_if_agc_control_23_16_pos 0
-#define	reg_aagc_fixed_if_agc_control_23_16_len 8
-#define	reg_aagc_fixed_if_agc_control_23_16_lsb 16
-#define xd_p_reg_aagc_fixed_if_agc_control_30_24	0xA01E
-#define	reg_aagc_fixed_if_agc_control_30_24_pos 0
-#define	reg_aagc_fixed_if_agc_control_30_24_len 7
-#define	reg_aagc_fixed_if_agc_control_30_24_lsb 24
-#define xd_p_reg_aagc_rf_agc_unlock_numerator	0xA01F
-#define	reg_aagc_rf_agc_unlock_numerator_pos 0
-#define	reg_aagc_rf_agc_unlock_numerator_len 6
-#define	reg_aagc_rf_agc_unlock_numerator_lsb 0
-#define xd_p_reg_aagc_if_agc_unlock_numerator	0xA020
-#define	reg_aagc_if_agc_unlock_numerator_pos 0
-#define	reg_aagc_if_agc_unlock_numerator_len 6
-#define	reg_aagc_if_agc_unlock_numerator_lsb 0
-#define xd_p_reg_unplug_th	0xA021
-#define	reg_unplug_th_pos 0
-#define	reg_unplug_th_len 8
-#define	reg_aagc_rf_x0_lsb 0
-#define xd_p_reg_weak_signal_rfagc_thr 0xA022
-#define	reg_weak_signal_rfagc_thr_pos 0
-#define	reg_weak_signal_rfagc_thr_len 8
-#define	reg_weak_signal_rfagc_thr_lsb 0
-#define xd_p_reg_unplug_rf_gain_th 0xA023
-#define	reg_unplug_rf_gain_th_pos 0
-#define	reg_unplug_rf_gain_th_len 8
-#define	reg_unplug_rf_gain_th_lsb 0
-#define xd_p_reg_unplug_dtop_rf_gain_th 0xA024
-#define	reg_unplug_dtop_rf_gain_th_pos 0
-#define	reg_unplug_dtop_rf_gain_th_len 8
-#define	reg_unplug_dtop_rf_gain_th_lsb 0
-#define xd_p_reg_unplug_dtop_if_gain_th 0xA025
-#define	reg_unplug_dtop_if_gain_th_pos 0
-#define	reg_unplug_dtop_if_gain_th_len 8
-#define	reg_unplug_dtop_if_gain_th_lsb 0
-#define xd_p_reg_top_recover_at_unplug_en 0xA026
-#define	reg_top_recover_at_unplug_en_pos 0
-#define	reg_top_recover_at_unplug_en_len 1
-#define	reg_top_recover_at_unplug_en_lsb 0
-#define xd_p_reg_aagc_rf_x6	0xA027
-#define	reg_aagc_rf_x6_pos 0
-#define	reg_aagc_rf_x6_len 8
-#define	reg_aagc_rf_x6_lsb 0
-#define xd_p_reg_aagc_rf_x7	0xA028
-#define	reg_aagc_rf_x7_pos 0
-#define	reg_aagc_rf_x7_len 8
-#define	reg_aagc_rf_x7_lsb 0
-#define xd_p_reg_aagc_rf_x8	0xA029
-#define	reg_aagc_rf_x8_pos 0
-#define	reg_aagc_rf_x8_len 8
-#define	reg_aagc_rf_x8_lsb 0
-#define xd_p_reg_aagc_rf_x9	0xA02A
-#define	reg_aagc_rf_x9_pos 0
-#define	reg_aagc_rf_x9_len 8
-#define	reg_aagc_rf_x9_lsb 0
-#define xd_p_reg_aagc_rf_x10	0xA02B
-#define	reg_aagc_rf_x10_pos 0
-#define	reg_aagc_rf_x10_len 8
-#define	reg_aagc_rf_x10_lsb 0
-#define xd_p_reg_aagc_rf_x11	0xA02C
-#define	reg_aagc_rf_x11_pos 0
-#define	reg_aagc_rf_x11_len 8
-#define	reg_aagc_rf_x11_lsb 0
-#define xd_p_reg_aagc_rf_x12	0xA02D
-#define	reg_aagc_rf_x12_pos 0
-#define	reg_aagc_rf_x12_len 8
-#define	reg_aagc_rf_x12_lsb 0
-#define xd_p_reg_aagc_rf_x13	0xA02E
-#define	reg_aagc_rf_x13_pos 0
-#define	reg_aagc_rf_x13_len 8
-#define	reg_aagc_rf_x13_lsb 0
-#define xd_p_reg_aagc_if_x0	0xA02F
-#define	reg_aagc_if_x0_pos 0
-#define	reg_aagc_if_x0_len 8
-#define	reg_aagc_if_x0_lsb 0
-#define xd_p_reg_aagc_if_x1	0xA030
-#define	reg_aagc_if_x1_pos 0
-#define	reg_aagc_if_x1_len 8
-#define	reg_aagc_if_x1_lsb 0
-#define xd_p_reg_aagc_if_x2	0xA031
-#define	reg_aagc_if_x2_pos 0
-#define	reg_aagc_if_x2_len 8
-#define	reg_aagc_if_x2_lsb 0
-#define xd_p_reg_aagc_if_x3	0xA032
-#define	reg_aagc_if_x3_pos 0
-#define	reg_aagc_if_x3_len 8
-#define	reg_aagc_if_x3_lsb 0
-#define xd_p_reg_aagc_if_x4	0xA033
-#define	reg_aagc_if_x4_pos 0
-#define	reg_aagc_if_x4_len 8
-#define	reg_aagc_if_x4_lsb 0
-#define xd_p_reg_aagc_if_x5	0xA034
-#define	reg_aagc_if_x5_pos 0
-#define	reg_aagc_if_x5_len 8
-#define	reg_aagc_if_x5_lsb 0
-#define xd_p_reg_aagc_if_x6	0xA035
-#define	reg_aagc_if_x6_pos 0
-#define	reg_aagc_if_x6_len 8
-#define	reg_aagc_if_x6_lsb 0
-#define xd_p_reg_aagc_if_x7	0xA036
-#define	reg_aagc_if_x7_pos 0
-#define	reg_aagc_if_x7_len 8
-#define	reg_aagc_if_x7_lsb 0
-#define xd_p_reg_aagc_if_x8	0xA037
-#define	reg_aagc_if_x8_pos 0
-#define	reg_aagc_if_x8_len 8
-#define	reg_aagc_if_x8_lsb 0
-#define xd_p_reg_aagc_if_x9	0xA038
-#define	reg_aagc_if_x9_pos 0
-#define	reg_aagc_if_x9_len 8
-#define	reg_aagc_if_x9_lsb 0
-#define xd_p_reg_aagc_if_x10	0xA039
-#define	reg_aagc_if_x10_pos 0
-#define	reg_aagc_if_x10_len 8
-#define	reg_aagc_if_x10_lsb 0
-#define xd_p_reg_aagc_if_x11	0xA03A
-#define	reg_aagc_if_x11_pos 0
-#define	reg_aagc_if_x11_len 8
-#define	reg_aagc_if_x11_lsb 0
-#define xd_p_reg_aagc_if_x12	0xA03B
-#define	reg_aagc_if_x12_pos 0
-#define	reg_aagc_if_x12_len 8
-#define	reg_aagc_if_x12_lsb 0
-#define xd_p_reg_aagc_if_x13	0xA03C
-#define	reg_aagc_if_x13_pos 0
-#define	reg_aagc_if_x13_len 8
-#define	reg_aagc_if_x13_lsb 0
-#define xd_p_reg_aagc_min_rf_ctl_8bit_for_dca	0xA03D
-#define	reg_aagc_min_rf_ctl_8bit_for_dca_pos 0
-#define	reg_aagc_min_rf_ctl_8bit_for_dca_len 8
-#define	reg_aagc_min_rf_ctl_8bit_for_dca_lsb 0
-#define xd_p_reg_aagc_min_if_ctl_8bit_for_dca	0xA03E
-#define	reg_aagc_min_if_ctl_8bit_for_dca_pos 0
-#define	reg_aagc_min_if_ctl_8bit_for_dca_len 8
-#define	reg_aagc_min_if_ctl_8bit_for_dca_lsb 0
-#define xd_r_reg_aagc_total_gain_7_0	0xA070
-#define	reg_aagc_total_gain_7_0_pos 0
-#define	reg_aagc_total_gain_7_0_len 8
-#define	reg_aagc_total_gain_7_0_lsb 0
-#define xd_r_reg_aagc_total_gain_15_8	0xA071
-#define	reg_aagc_total_gain_15_8_pos 0
-#define	reg_aagc_total_gain_15_8_len 8
-#define	reg_aagc_total_gain_15_8_lsb 8
-#define xd_p_reg_aagc_in_sat_cnt_7_0	0xA074
-#define	reg_aagc_in_sat_cnt_7_0_pos 0
-#define	reg_aagc_in_sat_cnt_7_0_len 8
-#define	reg_aagc_in_sat_cnt_7_0_lsb 0
-#define xd_p_reg_aagc_in_sat_cnt_15_8	0xA075
-#define	reg_aagc_in_sat_cnt_15_8_pos 0
-#define	reg_aagc_in_sat_cnt_15_8_len 8
-#define	reg_aagc_in_sat_cnt_15_8_lsb 8
-#define xd_p_reg_aagc_in_sat_cnt_23_16	0xA076
-#define	reg_aagc_in_sat_cnt_23_16_pos 0
-#define	reg_aagc_in_sat_cnt_23_16_len 8
-#define	reg_aagc_in_sat_cnt_23_16_lsb 16
-#define xd_p_reg_aagc_in_sat_cnt_31_24	0xA077
-#define	reg_aagc_in_sat_cnt_31_24_pos 0
-#define	reg_aagc_in_sat_cnt_31_24_len 8
-#define	reg_aagc_in_sat_cnt_31_24_lsb 24
-#define xd_r_reg_aagc_digital_rf_volt_7_0	0xA078
-#define	reg_aagc_digital_rf_volt_7_0_pos 0
-#define	reg_aagc_digital_rf_volt_7_0_len 8
-#define	reg_aagc_digital_rf_volt_7_0_lsb 0
-#define xd_r_reg_aagc_digital_rf_volt_9_8	0xA079
-#define	reg_aagc_digital_rf_volt_9_8_pos 0
-#define	reg_aagc_digital_rf_volt_9_8_len 2
-#define	reg_aagc_digital_rf_volt_9_8_lsb 8
-#define xd_r_reg_aagc_digital_if_volt_7_0	0xA07A
-#define	reg_aagc_digital_if_volt_7_0_pos 0
-#define	reg_aagc_digital_if_volt_7_0_len 8
-#define	reg_aagc_digital_if_volt_7_0_lsb 0
-#define xd_r_reg_aagc_digital_if_volt_9_8	0xA07B
-#define	reg_aagc_digital_if_volt_9_8_pos 0
-#define	reg_aagc_digital_if_volt_9_8_len 2
-#define	reg_aagc_digital_if_volt_9_8_lsb 8
-#define xd_r_reg_aagc_rf_gain	0xA07C
-#define	reg_aagc_rf_gain_pos 0
-#define	reg_aagc_rf_gain_len 8
-#define	reg_aagc_rf_gain_lsb 0
-#define xd_r_reg_aagc_if_gain	0xA07D
-#define	reg_aagc_if_gain_pos 0
-#define	reg_aagc_if_gain_len 8
-#define	reg_aagc_if_gain_lsb 0
-#define xd_p_tinr_imp_indicator	0xA080
-#define	tinr_imp_indicator_pos 0
-#define	tinr_imp_indicator_len 2
-#define	tinr_imp_indicator_lsb 0
-#define xd_p_reg_tinr_fifo_size	0xA080
-#define	reg_tinr_fifo_size_pos 2
-#define	reg_tinr_fifo_size_len 5
-#define	reg_tinr_fifo_size_lsb 0
-#define xd_p_reg_tinr_saturation_cnt_th	0xA081
-#define	reg_tinr_saturation_cnt_th_pos 0
-#define	reg_tinr_saturation_cnt_th_len 4
-#define	reg_tinr_saturation_cnt_th_lsb 0
-#define xd_p_reg_tinr_saturation_th_3_0	0xA081
-#define	reg_tinr_saturation_th_3_0_pos 4
-#define	reg_tinr_saturation_th_3_0_len 4
-#define	reg_tinr_saturation_th_3_0_lsb 0
-#define xd_p_reg_tinr_saturation_th_8_4	0xA082
-#define	reg_tinr_saturation_th_8_4_pos 0
-#define	reg_tinr_saturation_th_8_4_len 5
-#define	reg_tinr_saturation_th_8_4_lsb 4
-#define xd_p_reg_tinr_imp_duration_th_2k_7_0	0xA083
-#define	reg_tinr_imp_duration_th_2k_7_0_pos 0
-#define	reg_tinr_imp_duration_th_2k_7_0_len 8
-#define	reg_tinr_imp_duration_th_2k_7_0_lsb 0
-#define xd_p_reg_tinr_imp_duration_th_2k_8	0xA084
-#define	reg_tinr_imp_duration_th_2k_8_pos 0
-#define	reg_tinr_imp_duration_th_2k_8_len 1
-#define	reg_tinr_imp_duration_th_2k_8_lsb 0
-#define xd_p_reg_tinr_imp_duration_th_8k_7_0	0xA085
-#define	reg_tinr_imp_duration_th_8k_7_0_pos 0
-#define	reg_tinr_imp_duration_th_8k_7_0_len 8
-#define	reg_tinr_imp_duration_th_8k_7_0_lsb 0
-#define xd_p_reg_tinr_imp_duration_th_8k_10_8	0xA086
-#define	reg_tinr_imp_duration_th_8k_10_8_pos 0
-#define	reg_tinr_imp_duration_th_8k_10_8_len 3
-#define	reg_tinr_imp_duration_th_8k_10_8_lsb 8
-#define xd_p_reg_tinr_freq_ratio_6m_7_0	0xA087
-#define	reg_tinr_freq_ratio_6m_7_0_pos 0
-#define	reg_tinr_freq_ratio_6m_7_0_len 8
-#define	reg_tinr_freq_ratio_6m_7_0_lsb 0
-#define xd_p_reg_tinr_freq_ratio_6m_12_8	0xA088
-#define	reg_tinr_freq_ratio_6m_12_8_pos 0
-#define	reg_tinr_freq_ratio_6m_12_8_len 5
-#define	reg_tinr_freq_ratio_6m_12_8_lsb 8
-#define xd_p_reg_tinr_freq_ratio_7m_7_0	0xA089
-#define	reg_tinr_freq_ratio_7m_7_0_pos 0
-#define	reg_tinr_freq_ratio_7m_7_0_len 8
-#define	reg_tinr_freq_ratio_7m_7_0_lsb 0
-#define xd_p_reg_tinr_freq_ratio_7m_12_8	0xA08A
-#define	reg_tinr_freq_ratio_7m_12_8_pos 0
-#define	reg_tinr_freq_ratio_7m_12_8_len 5
-#define	reg_tinr_freq_ratio_7m_12_8_lsb 8
-#define xd_p_reg_tinr_freq_ratio_8m_7_0	0xA08B
-#define	reg_tinr_freq_ratio_8m_7_0_pos 0
-#define	reg_tinr_freq_ratio_8m_7_0_len 8
-#define	reg_tinr_freq_ratio_8m_7_0_lsb 0
-#define xd_p_reg_tinr_freq_ratio_8m_12_8	0xA08C
-#define	reg_tinr_freq_ratio_8m_12_8_pos 0
-#define	reg_tinr_freq_ratio_8m_12_8_len 5
-#define	reg_tinr_freq_ratio_8m_12_8_lsb 8
-#define xd_p_reg_tinr_imp_duration_th_low_2k	0xA08D
-#define	reg_tinr_imp_duration_th_low_2k_pos 0
-#define	reg_tinr_imp_duration_th_low_2k_len 8
-#define	reg_tinr_imp_duration_th_low_2k_lsb 0
-#define xd_p_reg_tinr_imp_duration_th_low_8k	0xA08E
-#define	reg_tinr_imp_duration_th_low_8k_pos 0
-#define	reg_tinr_imp_duration_th_low_8k_len 8
-#define	reg_tinr_imp_duration_th_low_8k_lsb 0
-#define xd_r_reg_tinr_counter_7_0	0xA090
-#define	reg_tinr_counter_7_0_pos 0
-#define	reg_tinr_counter_7_0_len 8
-#define	reg_tinr_counter_7_0_lsb 0
-#define xd_r_reg_tinr_counter_15_8	0xA091
-#define	reg_tinr_counter_15_8_pos 0
-#define	reg_tinr_counter_15_8_len 8
-#define	reg_tinr_counter_15_8_lsb 8
-#define xd_p_reg_tinr_adative_tinr_en	0xA093
-#define	reg_tinr_adative_tinr_en_pos 0
-#define	reg_tinr_adative_tinr_en_len 1
-#define	reg_tinr_adative_tinr_en_lsb 0
-#define xd_p_reg_tinr_peak_fifo_size	0xA093
-#define	reg_tinr_peak_fifo_size_pos 1
-#define	reg_tinr_peak_fifo_size_len 5
-#define	reg_tinr_peak_fifo_size_lsb 0
-#define xd_p_reg_tinr_counter_rst	0xA093
-#define	reg_tinr_counter_rst_pos 6
-#define	reg_tinr_counter_rst_len 1
-#define	reg_tinr_counter_rst_lsb 0
-#define xd_p_reg_tinr_search_period_7_0	0xA094
-#define	reg_tinr_search_period_7_0_pos 0
-#define	reg_tinr_search_period_7_0_len 8
-#define	reg_tinr_search_period_7_0_lsb 0
-#define xd_p_reg_tinr_search_period_15_8	0xA095
-#define	reg_tinr_search_period_15_8_pos 0
-#define	reg_tinr_search_period_15_8_len 8
-#define	reg_tinr_search_period_15_8_lsb 8
-#define xd_p_reg_ccifs_fcw_7_0	0xA0A0
-#define	reg_ccifs_fcw_7_0_pos 0
-#define	reg_ccifs_fcw_7_0_len 8
-#define	reg_ccifs_fcw_7_0_lsb 0
-#define xd_p_reg_ccifs_fcw_12_8	0xA0A1
-#define	reg_ccifs_fcw_12_8_pos 0
-#define	reg_ccifs_fcw_12_8_len 5
-#define	reg_ccifs_fcw_12_8_lsb 8
-#define xd_p_reg_ccifs_spec_inv	0xA0A1
-#define	reg_ccifs_spec_inv_pos 5
-#define	reg_ccifs_spec_inv_len 1
-#define	reg_ccifs_spec_inv_lsb 0
-#define xd_p_reg_gp_trigger	0xA0A2
-#define	reg_gp_trigger_pos 0
-#define	reg_gp_trigger_len 1
-#define	reg_gp_trigger_lsb 0
-#define xd_p_reg_trigger_sel	0xA0A2
-#define	reg_trigger_sel_pos 1
-#define	reg_trigger_sel_len 2
-#define	reg_trigger_sel_lsb 0
-#define xd_p_reg_debug_ofdm	0xA0A2
-#define	reg_debug_ofdm_pos 3
-#define	reg_debug_ofdm_len 2
-#define	reg_debug_ofdm_lsb 0
-#define xd_p_reg_trigger_module_sel	0xA0A3
-#define	reg_trigger_module_sel_pos 0
-#define	reg_trigger_module_sel_len 6
-#define	reg_trigger_module_sel_lsb 0
-#define xd_p_reg_trigger_set_sel	0xA0A4
-#define	reg_trigger_set_sel_pos 0
-#define	reg_trigger_set_sel_len 6
-#define	reg_trigger_set_sel_lsb 0
-#define xd_p_reg_fw_int_mask_n	0xA0A4
-#define	reg_fw_int_mask_n_pos 6
-#define	reg_fw_int_mask_n_len 1
-#define	reg_fw_int_mask_n_lsb 0
-#define xd_p_reg_debug_group	0xA0A5
-#define	reg_debug_group_pos 0
-#define	reg_debug_group_len 4
-#define	reg_debug_group_lsb 0
-#define xd_p_reg_odbg_clk_sel	0xA0A5
-#define	reg_odbg_clk_sel_pos 4
-#define	reg_odbg_clk_sel_len 2
-#define	reg_odbg_clk_sel_lsb 0
-#define xd_p_reg_ccif_sc	0xA0C0
-#define	reg_ccif_sc_pos 0
-#define	reg_ccif_sc_len 4
-#define	reg_ccif_sc_lsb 0
-#define xd_r_reg_ccif_saturate	0xA0C1
-#define	reg_ccif_saturate_pos 0
-#define	reg_ccif_saturate_len 2
-#define	reg_ccif_saturate_lsb 0
-#define xd_r_reg_antif_saturate	0xA0C1
-#define	reg_antif_saturate_pos 2
-#define	reg_antif_saturate_len 4
-#define	reg_antif_saturate_lsb 0
-#define xd_r_reg_acif_saturate	0xA0C2
-#define	reg_acif_saturate_pos 0
-#define	reg_acif_saturate_len 8
-#define	reg_acif_saturate_lsb 0
-#define xd_p_reg_tmr_timer0_threshold_7_0	0xA0C8
-#define	reg_tmr_timer0_threshold_7_0_pos 0
-#define	reg_tmr_timer0_threshold_7_0_len 8
-#define	reg_tmr_timer0_threshold_7_0_lsb 0
-#define xd_p_reg_tmr_timer0_threshold_15_8	0xA0C9
-#define	reg_tmr_timer0_threshold_15_8_pos 0
-#define	reg_tmr_timer0_threshold_15_8_len 8
-#define	reg_tmr_timer0_threshold_15_8_lsb 8
-#define xd_p_reg_tmr_timer0_enable	0xA0CA
-#define	reg_tmr_timer0_enable_pos 0
-#define	reg_tmr_timer0_enable_len 1
-#define	reg_tmr_timer0_enable_lsb 0
-#define xd_p_reg_tmr_timer0_clk_sel	0xA0CA
-#define	reg_tmr_timer0_clk_sel_pos 1
-#define	reg_tmr_timer0_clk_sel_len 1
-#define	reg_tmr_timer0_clk_sel_lsb 0
-#define xd_p_reg_tmr_timer0_int	0xA0CA
-#define	reg_tmr_timer0_int_pos 2
-#define	reg_tmr_timer0_int_len 1
-#define	reg_tmr_timer0_int_lsb 0
-#define xd_p_reg_tmr_timer0_rst	0xA0CA
-#define	reg_tmr_timer0_rst_pos 3
-#define	reg_tmr_timer0_rst_len 1
-#define	reg_tmr_timer0_rst_lsb 0
-#define xd_r_reg_tmr_timer0_count_7_0	0xA0CB
-#define	reg_tmr_timer0_count_7_0_pos 0
-#define	reg_tmr_timer0_count_7_0_len 8
-#define	reg_tmr_timer0_count_7_0_lsb 0
-#define xd_r_reg_tmr_timer0_count_15_8	0xA0CC
-#define	reg_tmr_timer0_count_15_8_pos 0
-#define	reg_tmr_timer0_count_15_8_len 8
-#define	reg_tmr_timer0_count_15_8_lsb 8
-#define xd_p_reg_suspend	0xA0CD
-#define	reg_suspend_pos 0
-#define	reg_suspend_len 1
-#define	reg_suspend_lsb 0
-#define xd_p_reg_suspend_rdy	0xA0CD
-#define	reg_suspend_rdy_pos 1
-#define	reg_suspend_rdy_len 1
-#define	reg_suspend_rdy_lsb 0
-#define xd_p_reg_resume	0xA0CD
-#define	reg_resume_pos 2
-#define	reg_resume_len 1
-#define	reg_resume_lsb 0
-#define xd_p_reg_resume_rdy	0xA0CD
-#define	reg_resume_rdy_pos 3
-#define	reg_resume_rdy_len 1
-#define	reg_resume_rdy_lsb 0
-#define xd_p_reg_fmf	0xA0CE
-#define	reg_fmf_pos 0
-#define	reg_fmf_len 8
-#define	reg_fmf_lsb 0
-#define xd_p_ccid_accumulate_num_2k_7_0	0xA100
-#define	ccid_accumulate_num_2k_7_0_pos 0
-#define	ccid_accumulate_num_2k_7_0_len 8
-#define	ccid_accumulate_num_2k_7_0_lsb 0
-#define xd_p_ccid_accumulate_num_2k_12_8	0xA101
-#define	ccid_accumulate_num_2k_12_8_pos 0
-#define	ccid_accumulate_num_2k_12_8_len 5
-#define	ccid_accumulate_num_2k_12_8_lsb 8
-#define xd_p_ccid_accumulate_num_8k_7_0	0xA102
-#define	ccid_accumulate_num_8k_7_0_pos 0
-#define	ccid_accumulate_num_8k_7_0_len 8
-#define	ccid_accumulate_num_8k_7_0_lsb 0
-#define xd_p_ccid_accumulate_num_8k_14_8	0xA103
-#define	ccid_accumulate_num_8k_14_8_pos 0
-#define	ccid_accumulate_num_8k_14_8_len 7
-#define	ccid_accumulate_num_8k_14_8_lsb 8
-#define xd_p_ccid_desired_level_0	0xA103
-#define	ccid_desired_level_0_pos 7
-#define	ccid_desired_level_0_len 1
-#define	ccid_desired_level_0_lsb 0
-#define xd_p_ccid_desired_level_8_1	0xA104
-#define	ccid_desired_level_8_1_pos 0
-#define	ccid_desired_level_8_1_len 8
-#define	ccid_desired_level_8_1_lsb 1
-#define xd_p_ccid_apply_delay	0xA105
-#define	ccid_apply_delay_pos 0
-#define	ccid_apply_delay_len 7
-#define	ccid_apply_delay_lsb 0
-#define xd_p_ccid_CCID_Threshold1	0xA106
-#define	ccid_CCID_Threshold1_pos 0
-#define	ccid_CCID_Threshold1_len 8
-#define	ccid_CCID_Threshold1_lsb 0
-#define xd_p_ccid_CCID_Threshold2	0xA107
-#define	ccid_CCID_Threshold2_pos 0
-#define	ccid_CCID_Threshold2_len 8
-#define	ccid_CCID_Threshold2_lsb 0
-#define xd_p_reg_ccid_gain_scale	0xA108
-#define	reg_ccid_gain_scale_pos 0
-#define	reg_ccid_gain_scale_len 4
-#define	reg_ccid_gain_scale_lsb 0
-#define xd_p_reg_ccid2_passband_gain_set	0xA108
-#define	reg_ccid2_passband_gain_set_pos 4
-#define	reg_ccid2_passband_gain_set_len 4
-#define	reg_ccid2_passband_gain_set_lsb 0
-#define xd_r_ccid_multiplier_7_0	0xA109
-#define	ccid_multiplier_7_0_pos 0
-#define	ccid_multiplier_7_0_len 8
-#define	ccid_multiplier_7_0_lsb 0
-#define xd_r_ccid_multiplier_15_8	0xA10A
-#define	ccid_multiplier_15_8_pos 0
-#define	ccid_multiplier_15_8_len 8
-#define	ccid_multiplier_15_8_lsb 8
-#define xd_r_ccid_right_shift_bits	0xA10B
-#define	ccid_right_shift_bits_pos 0
-#define	ccid_right_shift_bits_len 4
-#define	ccid_right_shift_bits_lsb 0
-#define xd_r_reg_ccid_sx_7_0	0xA10C
-#define	reg_ccid_sx_7_0_pos 0
-#define	reg_ccid_sx_7_0_len 8
-#define	reg_ccid_sx_7_0_lsb 0
-#define xd_r_reg_ccid_sx_15_8	0xA10D
-#define	reg_ccid_sx_15_8_pos 0
-#define	reg_ccid_sx_15_8_len 8
-#define	reg_ccid_sx_15_8_lsb 8
-#define xd_r_reg_ccid_sx_21_16	0xA10E
-#define	reg_ccid_sx_21_16_pos 0
-#define	reg_ccid_sx_21_16_len 6
-#define	reg_ccid_sx_21_16_lsb 16
-#define xd_r_reg_ccid_sy_7_0	0xA110
-#define	reg_ccid_sy_7_0_pos 0
-#define	reg_ccid_sy_7_0_len 8
-#define	reg_ccid_sy_7_0_lsb 0
-#define xd_r_reg_ccid_sy_15_8	0xA111
-#define	reg_ccid_sy_15_8_pos 0
-#define	reg_ccid_sy_15_8_len 8
-#define	reg_ccid_sy_15_8_lsb 8
-#define xd_r_reg_ccid_sy_23_16	0xA112
-#define	reg_ccid_sy_23_16_pos 0
-#define	reg_ccid_sy_23_16_len 8
-#define	reg_ccid_sy_23_16_lsb 16
-#define xd_r_reg_ccid2_sz_7_0	0xA114
-#define	reg_ccid2_sz_7_0_pos 0
-#define	reg_ccid2_sz_7_0_len 8
-#define	reg_ccid2_sz_7_0_lsb 0
-#define xd_r_reg_ccid2_sz_15_8	0xA115
-#define	reg_ccid2_sz_15_8_pos 0
-#define	reg_ccid2_sz_15_8_len 8
-#define	reg_ccid2_sz_15_8_lsb 8
-#define xd_r_reg_ccid2_sz_23_16	0xA116
-#define	reg_ccid2_sz_23_16_pos 0
-#define	reg_ccid2_sz_23_16_len 8
-#define	reg_ccid2_sz_23_16_lsb 16
-#define xd_r_reg_ccid2_sz_25_24	0xA117
-#define	reg_ccid2_sz_25_24_pos 0
-#define	reg_ccid2_sz_25_24_len 2
-#define	reg_ccid2_sz_25_24_lsb 24
-#define xd_r_reg_ccid2_sy_7_0	0xA118
-#define	reg_ccid2_sy_7_0_pos 0
-#define	reg_ccid2_sy_7_0_len 8
-#define	reg_ccid2_sy_7_0_lsb 0
-#define xd_r_reg_ccid2_sy_15_8	0xA119
-#define	reg_ccid2_sy_15_8_pos 0
-#define	reg_ccid2_sy_15_8_len 8
-#define	reg_ccid2_sy_15_8_lsb 8
-#define xd_r_reg_ccid2_sy_23_16	0xA11A
-#define	reg_ccid2_sy_23_16_pos 0
-#define	reg_ccid2_sy_23_16_len 8
-#define	reg_ccid2_sy_23_16_lsb 16
-#define xd_r_reg_ccid2_sy_25_24	0xA11B
-#define	reg_ccid2_sy_25_24_pos 0
-#define	reg_ccid2_sy_25_24_len 2
-#define	reg_ccid2_sy_25_24_lsb 24
-#define xd_p_dagc1_accumulate_num_2k_7_0	0xA120
-#define	dagc1_accumulate_num_2k_7_0_pos 0
-#define	dagc1_accumulate_num_2k_7_0_len 8
-#define	dagc1_accumulate_num_2k_7_0_lsb 0
-#define xd_p_dagc1_accumulate_num_2k_12_8	0xA121
-#define	dagc1_accumulate_num_2k_12_8_pos 0
-#define	dagc1_accumulate_num_2k_12_8_len 5
-#define	dagc1_accumulate_num_2k_12_8_lsb 8
-#define xd_p_dagc1_accumulate_num_8k_7_0	0xA122
-#define	dagc1_accumulate_num_8k_7_0_pos 0
-#define	dagc1_accumulate_num_8k_7_0_len 8
-#define	dagc1_accumulate_num_8k_7_0_lsb 0
-#define xd_p_dagc1_accumulate_num_8k_14_8	0xA123
-#define	dagc1_accumulate_num_8k_14_8_pos 0
-#define	dagc1_accumulate_num_8k_14_8_len 7
-#define	dagc1_accumulate_num_8k_14_8_lsb 8
-#define xd_p_dagc1_desired_level_0	0xA123
-#define	dagc1_desired_level_0_pos 7
-#define	dagc1_desired_level_0_len 1
-#define	dagc1_desired_level_0_lsb 0
-#define xd_p_dagc1_desired_level_8_1	0xA124
-#define	dagc1_desired_level_8_1_pos 0
-#define	dagc1_desired_level_8_1_len 8
-#define	dagc1_desired_level_8_1_lsb 1
-#define xd_p_dagc1_apply_delay	0xA125
-#define	dagc1_apply_delay_pos 0
-#define	dagc1_apply_delay_len 7
-#define	dagc1_apply_delay_lsb 0
-#define xd_p_dagc1_bypass_scale_ctl	0xA126
-#define	dagc1_bypass_scale_ctl_pos 0
-#define	dagc1_bypass_scale_ctl_len 2
-#define	dagc1_bypass_scale_ctl_lsb 0
-#define xd_p_reg_dagc1_in_sat_cnt_7_0	0xA127
-#define	reg_dagc1_in_sat_cnt_7_0_pos 0
-#define	reg_dagc1_in_sat_cnt_7_0_len 8
-#define	reg_dagc1_in_sat_cnt_7_0_lsb 0
-#define xd_p_reg_dagc1_in_sat_cnt_15_8	0xA128
-#define	reg_dagc1_in_sat_cnt_15_8_pos 0
-#define	reg_dagc1_in_sat_cnt_15_8_len 8
-#define	reg_dagc1_in_sat_cnt_15_8_lsb 8
-#define xd_p_reg_dagc1_in_sat_cnt_23_16	0xA129
-#define	reg_dagc1_in_sat_cnt_23_16_pos 0
-#define	reg_dagc1_in_sat_cnt_23_16_len 8
-#define	reg_dagc1_in_sat_cnt_23_16_lsb 16
-#define xd_p_reg_dagc1_in_sat_cnt_31_24	0xA12A
-#define	reg_dagc1_in_sat_cnt_31_24_pos 0
-#define	reg_dagc1_in_sat_cnt_31_24_len 8
-#define	reg_dagc1_in_sat_cnt_31_24_lsb 24
-#define xd_p_reg_dagc1_out_sat_cnt_7_0	0xA12B
-#define	reg_dagc1_out_sat_cnt_7_0_pos 0
-#define	reg_dagc1_out_sat_cnt_7_0_len 8
-#define	reg_dagc1_out_sat_cnt_7_0_lsb 0
-#define xd_p_reg_dagc1_out_sat_cnt_15_8	0xA12C
-#define	reg_dagc1_out_sat_cnt_15_8_pos 0
-#define	reg_dagc1_out_sat_cnt_15_8_len 8
-#define	reg_dagc1_out_sat_cnt_15_8_lsb 8
-#define xd_p_reg_dagc1_out_sat_cnt_23_16	0xA12D
-#define	reg_dagc1_out_sat_cnt_23_16_pos 0
-#define	reg_dagc1_out_sat_cnt_23_16_len 8
-#define	reg_dagc1_out_sat_cnt_23_16_lsb 16
-#define xd_p_reg_dagc1_out_sat_cnt_31_24	0xA12E
-#define	reg_dagc1_out_sat_cnt_31_24_pos 0
-#define	reg_dagc1_out_sat_cnt_31_24_len 8
-#define	reg_dagc1_out_sat_cnt_31_24_lsb 24
-#define xd_r_dagc1_multiplier_7_0	0xA136
-#define	dagc1_multiplier_7_0_pos 0
-#define	dagc1_multiplier_7_0_len 8
-#define	dagc1_multiplier_7_0_lsb 0
-#define xd_r_dagc1_multiplier_15_8	0xA137
-#define	dagc1_multiplier_15_8_pos 0
-#define	dagc1_multiplier_15_8_len 8
-#define	dagc1_multiplier_15_8_lsb 8
-#define xd_r_dagc1_right_shift_bits	0xA138
-#define	dagc1_right_shift_bits_pos 0
-#define	dagc1_right_shift_bits_len 4
-#define	dagc1_right_shift_bits_lsb 0
-#define xd_p_reg_bfs_fcw_7_0	0xA140
-#define	reg_bfs_fcw_7_0_pos 0
-#define	reg_bfs_fcw_7_0_len 8
-#define	reg_bfs_fcw_7_0_lsb 0
-#define xd_p_reg_bfs_fcw_15_8	0xA141
-#define	reg_bfs_fcw_15_8_pos 0
-#define	reg_bfs_fcw_15_8_len 8
-#define	reg_bfs_fcw_15_8_lsb 8
-#define xd_p_reg_bfs_fcw_22_16	0xA142
-#define	reg_bfs_fcw_22_16_pos 0
-#define	reg_bfs_fcw_22_16_len 7
-#define	reg_bfs_fcw_22_16_lsb 16
-#define xd_p_reg_antif_sf_7_0	0xA144
-#define	reg_antif_sf_7_0_pos 0
-#define	reg_antif_sf_7_0_len 8
-#define	reg_antif_sf_7_0_lsb 0
-#define xd_p_reg_antif_sf_11_8	0xA145
-#define	reg_antif_sf_11_8_pos 0
-#define	reg_antif_sf_11_8_len 4
-#define	reg_antif_sf_11_8_lsb 8
-#define xd_r_bfs_fcw_q_7_0	0xA150
-#define	bfs_fcw_q_7_0_pos 0
-#define	bfs_fcw_q_7_0_len 8
-#define	bfs_fcw_q_7_0_lsb 0
-#define xd_r_bfs_fcw_q_15_8	0xA151
-#define	bfs_fcw_q_15_8_pos 0
-#define	bfs_fcw_q_15_8_len 8
-#define	bfs_fcw_q_15_8_lsb 8
-#define xd_r_bfs_fcw_q_22_16	0xA152
-#define	bfs_fcw_q_22_16_pos 0
-#define	bfs_fcw_q_22_16_len 7
-#define	bfs_fcw_q_22_16_lsb 16
-#define xd_p_reg_dca_enu	0xA160
-#define	reg_dca_enu_pos 0
-#define	reg_dca_enu_len 1
-#define	reg_dca_enu_lsb 0
-#define xd_p_reg_dca_enl	0xA160
-#define	reg_dca_enl_pos 1
-#define	reg_dca_enl_len 1
-#define	reg_dca_enl_lsb 0
-#define xd_p_reg_dca_lower_chip	0xA160
-#define	reg_dca_lower_chip_pos 2
-#define	reg_dca_lower_chip_len 1
-#define	reg_dca_lower_chip_lsb 0
-#define xd_p_reg_dca_upper_chip	0xA160
-#define	reg_dca_upper_chip_pos 3
-#define	reg_dca_upper_chip_len 1
-#define	reg_dca_upper_chip_lsb 0
-#define xd_p_reg_dca_platch	0xA160
-#define	reg_dca_platch_pos 4
-#define	reg_dca_platch_len 1
-#define	reg_dca_platch_lsb 0
-#define xd_p_reg_dca_th	0xA161
-#define	reg_dca_th_pos 0
-#define	reg_dca_th_len 5
-#define	reg_dca_th_lsb 0
-#define xd_p_reg_dca_scale	0xA162
-#define	reg_dca_scale_pos 0
-#define	reg_dca_scale_len 4
-#define	reg_dca_scale_lsb 0
-#define xd_p_reg_dca_tone_7_0	0xA163
-#define	reg_dca_tone_7_0_pos 0
-#define	reg_dca_tone_7_0_len 8
-#define	reg_dca_tone_7_0_lsb 0
-#define xd_p_reg_dca_tone_12_8	0xA164
-#define	reg_dca_tone_12_8_pos 0
-#define	reg_dca_tone_12_8_len 5
-#define	reg_dca_tone_12_8_lsb 8
-#define xd_p_reg_dca_time_7_0	0xA165
-#define	reg_dca_time_7_0_pos 0
-#define	reg_dca_time_7_0_len 8
-#define	reg_dca_time_7_0_lsb 0
-#define xd_p_reg_dca_time_15_8	0xA166
-#define	reg_dca_time_15_8_pos 0
-#define	reg_dca_time_15_8_len 8
-#define	reg_dca_time_15_8_lsb 8
-#define xd_r_dcasm	0xA167
-#define	dcasm_pos 0
-#define	dcasm_len 3
-#define	dcasm_lsb 0
-#define xd_p_reg_qnt_valuew_7_0	0xA168
-#define	reg_qnt_valuew_7_0_pos 0
-#define	reg_qnt_valuew_7_0_len 8
-#define	reg_qnt_valuew_7_0_lsb 0
-#define xd_p_reg_qnt_valuew_10_8	0xA169
-#define	reg_qnt_valuew_10_8_pos 0
-#define	reg_qnt_valuew_10_8_len 3
-#define	reg_qnt_valuew_10_8_lsb 8
-#define xd_p_dca_sbx_gain_diff_7_0	0xA16A
-#define	dca_sbx_gain_diff_7_0_pos 0
-#define	dca_sbx_gain_diff_7_0_len 8
-#define	dca_sbx_gain_diff_7_0_lsb 0
-#define xd_p_dca_sbx_gain_diff_9_8	0xA16B
-#define	dca_sbx_gain_diff_9_8_pos 0
-#define	dca_sbx_gain_diff_9_8_len 2
-#define	dca_sbx_gain_diff_9_8_lsb 8
-#define xd_p_reg_dca_stand_alone	0xA16C
-#define	reg_dca_stand_alone_pos 0
-#define	reg_dca_stand_alone_len 1
-#define	reg_dca_stand_alone_lsb 0
-#define xd_p_reg_dca_upper_out_en	0xA16C
-#define	reg_dca_upper_out_en_pos 1
-#define	reg_dca_upper_out_en_len 1
-#define	reg_dca_upper_out_en_lsb 0
-#define xd_p_reg_dca_rc_en	0xA16C
-#define	reg_dca_rc_en_pos 2
-#define	reg_dca_rc_en_len 1
-#define	reg_dca_rc_en_lsb 0
-#define xd_p_reg_dca_retrain_send	0xA16C
-#define	reg_dca_retrain_send_pos 3
-#define	reg_dca_retrain_send_len 1
-#define	reg_dca_retrain_send_lsb 0
-#define xd_p_reg_dca_retrain_rec	0xA16C
-#define	reg_dca_retrain_rec_pos 4
-#define	reg_dca_retrain_rec_len 1
-#define	reg_dca_retrain_rec_lsb 0
-#define xd_p_reg_dca_api_tpsrdy	0xA16C
-#define	reg_dca_api_tpsrdy_pos 5
-#define	reg_dca_api_tpsrdy_len 1
-#define	reg_dca_api_tpsrdy_lsb 0
-#define xd_p_reg_dca_symbol_gap	0xA16D
-#define	reg_dca_symbol_gap_pos 0
-#define	reg_dca_symbol_gap_len 4
-#define	reg_dca_symbol_gap_lsb 0
-#define xd_p_reg_qnt_nfvaluew_7_0	0xA16E
-#define	reg_qnt_nfvaluew_7_0_pos 0
-#define	reg_qnt_nfvaluew_7_0_len 8
-#define	reg_qnt_nfvaluew_7_0_lsb 0
-#define xd_p_reg_qnt_nfvaluew_10_8	0xA16F
-#define	reg_qnt_nfvaluew_10_8_pos 0
-#define	reg_qnt_nfvaluew_10_8_len 3
-#define	reg_qnt_nfvaluew_10_8_lsb 8
-#define xd_p_reg_qnt_flatness_thr_7_0	0xA170
-#define	reg_qnt_flatness_thr_7_0_pos 0
-#define	reg_qnt_flatness_thr_7_0_len 8
-#define	reg_qnt_flatness_thr_7_0_lsb 0
-#define xd_p_reg_qnt_flatness_thr_9_8	0xA171
-#define	reg_qnt_flatness_thr_9_8_pos 0
-#define	reg_qnt_flatness_thr_9_8_len 2
-#define	reg_qnt_flatness_thr_9_8_lsb 8
-#define xd_p_reg_dca_tone_idx_5_0	0xA171
-#define	reg_dca_tone_idx_5_0_pos 2
-#define	reg_dca_tone_idx_5_0_len 6
-#define	reg_dca_tone_idx_5_0_lsb 0
-#define xd_p_reg_dca_tone_idx_12_6	0xA172
-#define	reg_dca_tone_idx_12_6_pos 0
-#define	reg_dca_tone_idx_12_6_len 7
-#define	reg_dca_tone_idx_12_6_lsb 6
-#define xd_p_reg_dca_data_vld	0xA173
-#define	reg_dca_data_vld_pos 0
-#define	reg_dca_data_vld_len 1
-#define	reg_dca_data_vld_lsb 0
-#define xd_p_reg_dca_read_update	0xA173
-#define	reg_dca_read_update_pos 1
-#define	reg_dca_read_update_len 1
-#define	reg_dca_read_update_lsb 0
-#define xd_r_reg_dca_data_re_5_0	0xA173
-#define	reg_dca_data_re_5_0_pos 2
-#define	reg_dca_data_re_5_0_len 6
-#define	reg_dca_data_re_5_0_lsb 0
-#define xd_r_reg_dca_data_re_10_6	0xA174
-#define	reg_dca_data_re_10_6_pos 0
-#define	reg_dca_data_re_10_6_len 5
-#define	reg_dca_data_re_10_6_lsb 6
-#define xd_r_reg_dca_data_im_7_0	0xA175
-#define	reg_dca_data_im_7_0_pos 0
-#define	reg_dca_data_im_7_0_len 8
-#define	reg_dca_data_im_7_0_lsb 0
-#define xd_r_reg_dca_data_im_10_8	0xA176
-#define	reg_dca_data_im_10_8_pos 0
-#define	reg_dca_data_im_10_8_len 3
-#define	reg_dca_data_im_10_8_lsb 8
-#define xd_r_reg_dca_data_h2_7_0	0xA178
-#define	reg_dca_data_h2_7_0_pos 0
-#define	reg_dca_data_h2_7_0_len 8
-#define	reg_dca_data_h2_7_0_lsb 0
-#define xd_r_reg_dca_data_h2_9_8	0xA179
-#define	reg_dca_data_h2_9_8_pos 0
-#define	reg_dca_data_h2_9_8_len 2
-#define	reg_dca_data_h2_9_8_lsb 8
-#define xd_p_reg_f_adc_7_0	0xA180
-#define	reg_f_adc_7_0_pos 0
-#define	reg_f_adc_7_0_len 8
-#define	reg_f_adc_7_0_lsb 0
-#define xd_p_reg_f_adc_15_8	0xA181
-#define	reg_f_adc_15_8_pos 0
-#define	reg_f_adc_15_8_len 8
-#define	reg_f_adc_15_8_lsb 8
-#define xd_p_reg_f_adc_23_16	0xA182
-#define	reg_f_adc_23_16_pos 0
-#define	reg_f_adc_23_16_len 8
-#define	reg_f_adc_23_16_lsb 16
-#define xd_r_intp_mu_7_0	0xA190
-#define	intp_mu_7_0_pos 0
-#define	intp_mu_7_0_len 8
-#define	intp_mu_7_0_lsb 0
-#define xd_r_intp_mu_15_8	0xA191
-#define	intp_mu_15_8_pos 0
-#define	intp_mu_15_8_len 8
-#define	intp_mu_15_8_lsb 8
-#define xd_r_intp_mu_19_16	0xA192
-#define	intp_mu_19_16_pos 0
-#define	intp_mu_19_16_len 4
-#define	intp_mu_19_16_lsb 16
-#define xd_p_reg_agc_rst	0xA1A0
-#define	reg_agc_rst_pos 0
-#define	reg_agc_rst_len 1
-#define	reg_agc_rst_lsb 0
-#define xd_p_rf_agc_en	0xA1A0
-#define	rf_agc_en_pos 1
-#define	rf_agc_en_len 1
-#define	rf_agc_en_lsb 0
-#define xd_p_rf_agc_dis	0xA1A0
-#define	rf_agc_dis_pos 2
-#define	rf_agc_dis_len 1
-#define	rf_agc_dis_lsb 0
-#define xd_p_if_agc_rst	0xA1A0
-#define	if_agc_rst_pos 3
-#define	if_agc_rst_len 1
-#define	if_agc_rst_lsb 0
-#define xd_p_if_agc_en	0xA1A0
-#define	if_agc_en_pos 4
-#define	if_agc_en_len 1
-#define	if_agc_en_lsb 0
-#define xd_p_if_agc_dis	0xA1A0
-#define	if_agc_dis_pos 5
-#define	if_agc_dis_len 1
-#define	if_agc_dis_lsb 0
-#define xd_p_agc_lock	0xA1A0
-#define	agc_lock_pos 6
-#define	agc_lock_len 1
-#define	agc_lock_lsb 0
-#define xd_p_reg_tinr_rst	0xA1A1
-#define	reg_tinr_rst_pos 0
-#define	reg_tinr_rst_len 1
-#define	reg_tinr_rst_lsb 0
-#define xd_p_reg_tinr_en	0xA1A1
-#define	reg_tinr_en_pos 1
-#define	reg_tinr_en_len 1
-#define	reg_tinr_en_lsb 0
-#define xd_p_reg_ccifs_en	0xA1A2
-#define	reg_ccifs_en_pos 0
-#define	reg_ccifs_en_len 1
-#define	reg_ccifs_en_lsb 0
-#define xd_p_reg_ccifs_dis	0xA1A2
-#define	reg_ccifs_dis_pos 1
-#define	reg_ccifs_dis_len 1
-#define	reg_ccifs_dis_lsb 0
-#define xd_p_reg_ccifs_rst	0xA1A2
-#define	reg_ccifs_rst_pos 2
-#define	reg_ccifs_rst_len 1
-#define	reg_ccifs_rst_lsb 0
-#define xd_p_reg_ccifs_byp	0xA1A2
-#define	reg_ccifs_byp_pos 3
-#define	reg_ccifs_byp_len 1
-#define	reg_ccifs_byp_lsb 0
-#define xd_p_reg_ccif_en	0xA1A3
-#define	reg_ccif_en_pos 0
-#define	reg_ccif_en_len 1
-#define	reg_ccif_en_lsb 0
-#define xd_p_reg_ccif_dis	0xA1A3
-#define	reg_ccif_dis_pos 1
-#define	reg_ccif_dis_len 1
-#define	reg_ccif_dis_lsb 0
-#define xd_p_reg_ccif_rst	0xA1A3
-#define	reg_ccif_rst_pos 2
-#define	reg_ccif_rst_len 1
-#define	reg_ccif_rst_lsb 0
-#define xd_p_reg_ccif_byp	0xA1A3
-#define	reg_ccif_byp_pos 3
-#define	reg_ccif_byp_len 1
-#define	reg_ccif_byp_lsb 0
-#define xd_p_dagc1_rst	0xA1A4
-#define	dagc1_rst_pos 0
-#define	dagc1_rst_len 1
-#define	dagc1_rst_lsb 0
-#define xd_p_dagc1_en	0xA1A4
-#define	dagc1_en_pos 1
-#define	dagc1_en_len 1
-#define	dagc1_en_lsb 0
-#define xd_p_dagc1_mode	0xA1A4
-#define	dagc1_mode_pos 2
-#define	dagc1_mode_len 2
-#define	dagc1_mode_lsb 0
-#define xd_p_dagc1_done	0xA1A4
-#define	dagc1_done_pos 4
-#define	dagc1_done_len 1
-#define	dagc1_done_lsb 0
-#define xd_p_ccid_rst	0xA1A5
-#define	ccid_rst_pos 0
-#define	ccid_rst_len 1
-#define	ccid_rst_lsb 0
-#define xd_p_ccid_en	0xA1A5
-#define	ccid_en_pos 1
-#define	ccid_en_len 1
-#define	ccid_en_lsb 0
-#define xd_p_ccid_mode	0xA1A5
-#define	ccid_mode_pos 2
-#define	ccid_mode_len 2
-#define	ccid_mode_lsb 0
-#define xd_p_ccid_done	0xA1A5
-#define	ccid_done_pos 4
-#define	ccid_done_len 1
-#define	ccid_done_lsb 0
-#define xd_r_ccid_deted	0xA1A5
-#define	ccid_deted_pos 5
-#define	ccid_deted_len 1
-#define	ccid_deted_lsb 0
-#define xd_p_ccid2_en	0xA1A5
-#define	ccid2_en_pos 6
-#define	ccid2_en_len 1
-#define	ccid2_en_lsb 0
-#define xd_p_ccid2_done	0xA1A5
-#define	ccid2_done_pos 7
-#define	ccid2_done_len 1
-#define	ccid2_done_lsb 0
-#define xd_p_reg_bfs_en	0xA1A6
-#define	reg_bfs_en_pos 0
-#define	reg_bfs_en_len 1
-#define	reg_bfs_en_lsb 0
-#define xd_p_reg_bfs_dis	0xA1A6
-#define	reg_bfs_dis_pos 1
-#define	reg_bfs_dis_len 1
-#define	reg_bfs_dis_lsb 0
-#define xd_p_reg_bfs_rst	0xA1A6
-#define	reg_bfs_rst_pos 2
-#define	reg_bfs_rst_len 1
-#define	reg_bfs_rst_lsb 0
-#define xd_p_reg_bfs_byp	0xA1A6
-#define	reg_bfs_byp_pos 3
-#define	reg_bfs_byp_len 1
-#define	reg_bfs_byp_lsb 0
-#define xd_p_reg_antif_en	0xA1A7
-#define	reg_antif_en_pos 0
-#define	reg_antif_en_len 1
-#define	reg_antif_en_lsb 0
-#define xd_p_reg_antif_dis	0xA1A7
-#define	reg_antif_dis_pos 1
-#define	reg_antif_dis_len 1
-#define	reg_antif_dis_lsb 0
-#define xd_p_reg_antif_rst	0xA1A7
-#define	reg_antif_rst_pos 2
-#define	reg_antif_rst_len 1
-#define	reg_antif_rst_lsb 0
-#define xd_p_reg_antif_byp	0xA1A7
-#define	reg_antif_byp_pos 3
-#define	reg_antif_byp_len 1
-#define	reg_antif_byp_lsb 0
-#define xd_p_intp_en	0xA1A8
-#define	intp_en_pos 0
-#define	intp_en_len 1
-#define	intp_en_lsb 0
-#define xd_p_intp_dis	0xA1A8
-#define	intp_dis_pos 1
-#define	intp_dis_len 1
-#define	intp_dis_lsb 0
-#define xd_p_intp_rst	0xA1A8
-#define	intp_rst_pos 2
-#define	intp_rst_len 1
-#define	intp_rst_lsb 0
-#define xd_p_intp_byp	0xA1A8
-#define	intp_byp_pos 3
-#define	intp_byp_len 1
-#define	intp_byp_lsb 0
-#define xd_p_reg_acif_en	0xA1A9
-#define	reg_acif_en_pos 0
-#define	reg_acif_en_len 1
-#define	reg_acif_en_lsb 0
-#define xd_p_reg_acif_dis	0xA1A9
-#define	reg_acif_dis_pos 1
-#define	reg_acif_dis_len 1
-#define	reg_acif_dis_lsb 0
-#define xd_p_reg_acif_rst	0xA1A9
-#define	reg_acif_rst_pos 2
-#define	reg_acif_rst_len 1
-#define	reg_acif_rst_lsb 0
-#define xd_p_reg_acif_byp	0xA1A9
-#define	reg_acif_byp_pos 3
-#define	reg_acif_byp_len 1
-#define	reg_acif_byp_lsb 0
-#define xd_p_reg_acif_sync_mode	0xA1A9
-#define	reg_acif_sync_mode_pos 4
-#define	reg_acif_sync_mode_len 1
-#define	reg_acif_sync_mode_lsb 0
-#define xd_p_dagc2_rst	0xA1AA
-#define	dagc2_rst_pos 0
-#define	dagc2_rst_len 1
-#define	dagc2_rst_lsb 0
-#define xd_p_dagc2_en	0xA1AA
-#define	dagc2_en_pos 1
-#define	dagc2_en_len 1
-#define	dagc2_en_lsb 0
-#define xd_p_dagc2_mode	0xA1AA
-#define	dagc2_mode_pos 2
-#define	dagc2_mode_len 2
-#define	dagc2_mode_lsb 0
-#define xd_p_dagc2_done	0xA1AA
-#define	dagc2_done_pos 4
-#define	dagc2_done_len 1
-#define	dagc2_done_lsb 0
-#define xd_p_reg_dca_en	0xA1AB
-#define	reg_dca_en_pos 0
-#define	reg_dca_en_len 1
-#define	reg_dca_en_lsb 0
-#define xd_p_dagc2_accumulate_num_2k_7_0	0xA1C0
-#define	dagc2_accumulate_num_2k_7_0_pos 0
-#define	dagc2_accumulate_num_2k_7_0_len 8
-#define	dagc2_accumulate_num_2k_7_0_lsb 0
-#define xd_p_dagc2_accumulate_num_2k_12_8	0xA1C1
-#define	dagc2_accumulate_num_2k_12_8_pos 0
-#define	dagc2_accumulate_num_2k_12_8_len 5
-#define	dagc2_accumulate_num_2k_12_8_lsb 8
-#define xd_p_dagc2_accumulate_num_8k_7_0	0xA1C2
-#define	dagc2_accumulate_num_8k_7_0_pos 0
-#define	dagc2_accumulate_num_8k_7_0_len 8
-#define	dagc2_accumulate_num_8k_7_0_lsb 0
-#define xd_p_dagc2_accumulate_num_8k_12_8	0xA1C3
-#define	dagc2_accumulate_num_8k_12_8_pos 0
-#define	dagc2_accumulate_num_8k_12_8_len 5
-#define	dagc2_accumulate_num_8k_12_8_lsb 8
-#define xd_p_dagc2_desired_level_2_0	0xA1C3
-#define	dagc2_desired_level_2_0_pos 5
-#define	dagc2_desired_level_2_0_len 3
-#define	dagc2_desired_level_2_0_lsb 0
-#define xd_p_dagc2_desired_level_8_3	0xA1C4
-#define	dagc2_desired_level_8_3_pos 0
-#define	dagc2_desired_level_8_3_len 6
-#define	dagc2_desired_level_8_3_lsb 3
-#define xd_p_dagc2_apply_delay	0xA1C5
-#define	dagc2_apply_delay_pos 0
-#define	dagc2_apply_delay_len 7
-#define	dagc2_apply_delay_lsb 0
-#define xd_p_dagc2_bypass_scale_ctl	0xA1C6
-#define	dagc2_bypass_scale_ctl_pos 0
-#define	dagc2_bypass_scale_ctl_len 3
-#define	dagc2_bypass_scale_ctl_lsb 0
-#define xd_p_dagc2_programmable_shift1	0xA1C7
-#define	dagc2_programmable_shift1_pos 0
-#define	dagc2_programmable_shift1_len 8
-#define	dagc2_programmable_shift1_lsb 0
-#define xd_p_dagc2_programmable_shift2	0xA1C8
-#define	dagc2_programmable_shift2_pos 0
-#define	dagc2_programmable_shift2_len 8
-#define	dagc2_programmable_shift2_lsb 0
-#define xd_p_reg_dagc2_in_sat_cnt_7_0	0xA1C9
-#define	reg_dagc2_in_sat_cnt_7_0_pos 0
-#define	reg_dagc2_in_sat_cnt_7_0_len 8
-#define	reg_dagc2_in_sat_cnt_7_0_lsb 0
-#define xd_p_reg_dagc2_in_sat_cnt_15_8	0xA1CA
-#define	reg_dagc2_in_sat_cnt_15_8_pos 0
-#define	reg_dagc2_in_sat_cnt_15_8_len 8
-#define	reg_dagc2_in_sat_cnt_15_8_lsb 8
-#define xd_p_reg_dagc2_in_sat_cnt_23_16	0xA1CB
-#define	reg_dagc2_in_sat_cnt_23_16_pos 0
-#define	reg_dagc2_in_sat_cnt_23_16_len 8
-#define	reg_dagc2_in_sat_cnt_23_16_lsb 16
-#define xd_p_reg_dagc2_in_sat_cnt_31_24	0xA1CC
-#define	reg_dagc2_in_sat_cnt_31_24_pos 0
-#define	reg_dagc2_in_sat_cnt_31_24_len 8
-#define	reg_dagc2_in_sat_cnt_31_24_lsb 24
-#define xd_p_reg_dagc2_out_sat_cnt_7_0	0xA1CD
-#define	reg_dagc2_out_sat_cnt_7_0_pos 0
-#define	reg_dagc2_out_sat_cnt_7_0_len 8
-#define	reg_dagc2_out_sat_cnt_7_0_lsb 0
-#define xd_p_reg_dagc2_out_sat_cnt_15_8	0xA1CE
-#define	reg_dagc2_out_sat_cnt_15_8_pos 0
-#define	reg_dagc2_out_sat_cnt_15_8_len 8
-#define	reg_dagc2_out_sat_cnt_15_8_lsb 8
-#define xd_p_reg_dagc2_out_sat_cnt_23_16	0xA1CF
-#define	reg_dagc2_out_sat_cnt_23_16_pos 0
-#define	reg_dagc2_out_sat_cnt_23_16_len 8
-#define	reg_dagc2_out_sat_cnt_23_16_lsb 16
-#define xd_p_reg_dagc2_out_sat_cnt_31_24	0xA1D0
-#define	reg_dagc2_out_sat_cnt_31_24_pos 0
-#define	reg_dagc2_out_sat_cnt_31_24_len 8
-#define	reg_dagc2_out_sat_cnt_31_24_lsb 24
-#define xd_r_dagc2_multiplier_7_0	0xA1D6
-#define	dagc2_multiplier_7_0_pos 0
-#define	dagc2_multiplier_7_0_len 8
-#define	dagc2_multiplier_7_0_lsb 0
-#define xd_r_dagc2_multiplier_15_8	0xA1D7
-#define	dagc2_multiplier_15_8_pos 0
-#define	dagc2_multiplier_15_8_len 8
-#define	dagc2_multiplier_15_8_lsb 8
-#define xd_r_dagc2_right_shift_bits	0xA1D8
-#define	dagc2_right_shift_bits_pos 0
-#define	dagc2_right_shift_bits_len 4
-#define	dagc2_right_shift_bits_lsb 0
-#define xd_p_cfoe_NS_coeff1_7_0	0xA200
-#define	cfoe_NS_coeff1_7_0_pos 0
-#define	cfoe_NS_coeff1_7_0_len 8
-#define	cfoe_NS_coeff1_7_0_lsb 0
-#define xd_p_cfoe_NS_coeff1_15_8	0xA201
-#define	cfoe_NS_coeff1_15_8_pos 0
-#define	cfoe_NS_coeff1_15_8_len 8
-#define	cfoe_NS_coeff1_15_8_lsb 8
-#define xd_p_cfoe_NS_coeff1_23_16	0xA202
-#define	cfoe_NS_coeff1_23_16_pos 0
-#define	cfoe_NS_coeff1_23_16_len 8
-#define	cfoe_NS_coeff1_23_16_lsb 16
-#define xd_p_cfoe_NS_coeff1_25_24	0xA203
-#define	cfoe_NS_coeff1_25_24_pos 0
-#define	cfoe_NS_coeff1_25_24_len 2
-#define	cfoe_NS_coeff1_25_24_lsb 24
-#define xd_p_cfoe_NS_coeff2_5_0	0xA203
-#define	cfoe_NS_coeff2_5_0_pos 2
-#define	cfoe_NS_coeff2_5_0_len 6
-#define	cfoe_NS_coeff2_5_0_lsb 0
-#define xd_p_cfoe_NS_coeff2_13_6	0xA204
-#define	cfoe_NS_coeff2_13_6_pos 0
-#define	cfoe_NS_coeff2_13_6_len 8
-#define	cfoe_NS_coeff2_13_6_lsb 6
-#define xd_p_cfoe_NS_coeff2_21_14	0xA205
-#define	cfoe_NS_coeff2_21_14_pos 0
-#define	cfoe_NS_coeff2_21_14_len 8
-#define	cfoe_NS_coeff2_21_14_lsb 14
-#define xd_p_cfoe_NS_coeff2_24_22	0xA206
-#define	cfoe_NS_coeff2_24_22_pos 0
-#define	cfoe_NS_coeff2_24_22_len 3
-#define	cfoe_NS_coeff2_24_22_lsb 22
-#define xd_p_cfoe_lf_c1_4_0	0xA206
-#define	cfoe_lf_c1_4_0_pos 3
-#define	cfoe_lf_c1_4_0_len 5
-#define	cfoe_lf_c1_4_0_lsb 0
-#define xd_p_cfoe_lf_c1_12_5	0xA207
-#define	cfoe_lf_c1_12_5_pos 0
-#define	cfoe_lf_c1_12_5_len 8
-#define	cfoe_lf_c1_12_5_lsb 5
-#define xd_p_cfoe_lf_c1_20_13	0xA208
-#define	cfoe_lf_c1_20_13_pos 0
-#define	cfoe_lf_c1_20_13_len 8
-#define	cfoe_lf_c1_20_13_lsb 13
-#define xd_p_cfoe_lf_c1_25_21	0xA209
-#define	cfoe_lf_c1_25_21_pos 0
-#define	cfoe_lf_c1_25_21_len 5
-#define	cfoe_lf_c1_25_21_lsb 21
-#define xd_p_cfoe_lf_c2_2_0	0xA209
-#define	cfoe_lf_c2_2_0_pos 5
-#define	cfoe_lf_c2_2_0_len 3
-#define	cfoe_lf_c2_2_0_lsb 0
-#define xd_p_cfoe_lf_c2_10_3	0xA20A
-#define	cfoe_lf_c2_10_3_pos 0
-#define	cfoe_lf_c2_10_3_len 8
-#define	cfoe_lf_c2_10_3_lsb 3
-#define xd_p_cfoe_lf_c2_18_11	0xA20B
-#define	cfoe_lf_c2_18_11_pos 0
-#define	cfoe_lf_c2_18_11_len 8
-#define	cfoe_lf_c2_18_11_lsb 11
-#define xd_p_cfoe_lf_c2_25_19	0xA20C
-#define	cfoe_lf_c2_25_19_pos 0
-#define	cfoe_lf_c2_25_19_len 7
-#define	cfoe_lf_c2_25_19_lsb 19
-#define xd_p_cfoe_ifod_7_0	0xA20D
-#define	cfoe_ifod_7_0_pos 0
-#define	cfoe_ifod_7_0_len 8
-#define	cfoe_ifod_7_0_lsb 0
-#define xd_p_cfoe_ifod_10_8	0xA20E
-#define	cfoe_ifod_10_8_pos 0
-#define	cfoe_ifod_10_8_len 3
-#define	cfoe_ifod_10_8_lsb 8
-#define xd_p_cfoe_Divg_ctr_th	0xA20E
-#define	cfoe_Divg_ctr_th_pos 4
-#define	cfoe_Divg_ctr_th_len 4
-#define	cfoe_Divg_ctr_th_lsb 0
-#define xd_p_cfoe_FOT_divg_th	0xA20F
-#define	cfoe_FOT_divg_th_pos 0
-#define	cfoe_FOT_divg_th_len 8
-#define	cfoe_FOT_divg_th_lsb 0
-#define xd_p_cfoe_FOT_cnvg_th	0xA210
-#define	cfoe_FOT_cnvg_th_pos 0
-#define	cfoe_FOT_cnvg_th_len 8
-#define	cfoe_FOT_cnvg_th_lsb 0
-#define xd_p_reg_cfoe_offset_7_0	0xA211
-#define	reg_cfoe_offset_7_0_pos 0
-#define	reg_cfoe_offset_7_0_len 8
-#define	reg_cfoe_offset_7_0_lsb 0
-#define xd_p_reg_cfoe_offset_9_8	0xA212
-#define	reg_cfoe_offset_9_8_pos 0
-#define	reg_cfoe_offset_9_8_len 2
-#define	reg_cfoe_offset_9_8_lsb 8
-#define xd_p_reg_cfoe_ifoe_sign_corr	0xA212
-#define	reg_cfoe_ifoe_sign_corr_pos 2
-#define	reg_cfoe_ifoe_sign_corr_len 1
-#define	reg_cfoe_ifoe_sign_corr_lsb 0
-#define xd_r_cfoe_fot_LF_output_7_0	0xA218
-#define	cfoe_fot_LF_output_7_0_pos 0
-#define	cfoe_fot_LF_output_7_0_len 8
-#define	cfoe_fot_LF_output_7_0_lsb 0
-#define xd_r_cfoe_fot_LF_output_15_8	0xA219
-#define	cfoe_fot_LF_output_15_8_pos 0
-#define	cfoe_fot_LF_output_15_8_len 8
-#define	cfoe_fot_LF_output_15_8_lsb 8
-#define xd_r_cfoe_ifo_metric_7_0	0xA21A
-#define	cfoe_ifo_metric_7_0_pos 0
-#define	cfoe_ifo_metric_7_0_len 8
-#define	cfoe_ifo_metric_7_0_lsb 0
-#define xd_r_cfoe_ifo_metric_15_8	0xA21B
-#define	cfoe_ifo_metric_15_8_pos 0
-#define	cfoe_ifo_metric_15_8_len 8
-#define	cfoe_ifo_metric_15_8_lsb 8
-#define xd_r_cfoe_ifo_metric_23_16	0xA21C
-#define	cfoe_ifo_metric_23_16_pos 0
-#define	cfoe_ifo_metric_23_16_len 8
-#define	cfoe_ifo_metric_23_16_lsb 16
-#define xd_p_ste_Nu	0xA220
-#define	ste_Nu_pos 0
-#define	ste_Nu_len 2
-#define	ste_Nu_lsb 0
-#define xd_p_ste_GI	0xA220
-#define	ste_GI_pos 2
-#define	ste_GI_len 3
-#define	ste_GI_lsb 0
-#define xd_p_ste_symbol_num	0xA221
-#define	ste_symbol_num_pos 0
-#define	ste_symbol_num_len 2
-#define	ste_symbol_num_lsb 0
-#define xd_p_ste_sample_num	0xA221
-#define	ste_sample_num_pos 2
-#define	ste_sample_num_len 2
-#define	ste_sample_num_lsb 0
-#define xd_p_reg_ste_buf_en	0xA221
-#define	reg_ste_buf_en_pos 7
-#define	reg_ste_buf_en_len 1
-#define	reg_ste_buf_en_lsb 0
-#define xd_p_ste_FFT_offset_7_0	0xA222
-#define	ste_FFT_offset_7_0_pos 0
-#define	ste_FFT_offset_7_0_len 8
-#define	ste_FFT_offset_7_0_lsb 0
-#define xd_p_ste_FFT_offset_11_8	0xA223
-#define	ste_FFT_offset_11_8_pos 0
-#define	ste_FFT_offset_11_8_len 4
-#define	ste_FFT_offset_11_8_lsb 8
-#define xd_p_reg_ste_tstmod	0xA223
-#define	reg_ste_tstmod_pos 5
-#define	reg_ste_tstmod_len 1
-#define	reg_ste_tstmod_lsb 0
-#define xd_p_ste_adv_start_7_0	0xA224
-#define	ste_adv_start_7_0_pos 0
-#define	ste_adv_start_7_0_len 8
-#define	ste_adv_start_7_0_lsb 0
-#define xd_p_ste_adv_start_10_8	0xA225
-#define	ste_adv_start_10_8_pos 0
-#define	ste_adv_start_10_8_len 3
-#define	ste_adv_start_10_8_lsb 8
-#define xd_p_ste_adv_stop	0xA226
-#define	ste_adv_stop_pos 0
-#define	ste_adv_stop_len 8
-#define	ste_adv_stop_lsb 0
-#define xd_r_ste_P_value_7_0	0xA228
-#define	ste_P_value_7_0_pos 0
-#define	ste_P_value_7_0_len 8
-#define	ste_P_value_7_0_lsb 0
-#define xd_r_ste_P_value_10_8	0xA229
-#define	ste_P_value_10_8_pos 0
-#define	ste_P_value_10_8_len 3
-#define	ste_P_value_10_8_lsb 8
-#define xd_r_ste_M_value_7_0	0xA22A
-#define	ste_M_value_7_0_pos 0
-#define	ste_M_value_7_0_len 8
-#define	ste_M_value_7_0_lsb 0
-#define xd_r_ste_M_value_10_8	0xA22B
-#define	ste_M_value_10_8_pos 0
-#define	ste_M_value_10_8_len 3
-#define	ste_M_value_10_8_lsb 8
-#define xd_r_ste_H1	0xA22C
-#define	ste_H1_pos 0
-#define	ste_H1_len 7
-#define	ste_H1_lsb 0
-#define xd_r_ste_H2	0xA22D
-#define	ste_H2_pos 0
-#define	ste_H2_len 7
-#define	ste_H2_lsb 0
-#define xd_r_ste_H3	0xA22E
-#define	ste_H3_pos 0
-#define	ste_H3_len 7
-#define	ste_H3_lsb 0
-#define xd_r_ste_H4	0xA22F
-#define	ste_H4_pos 0
-#define	ste_H4_len 7
-#define	ste_H4_lsb 0
-#define xd_r_ste_Corr_value_I_7_0	0xA230
-#define	ste_Corr_value_I_7_0_pos 0
-#define	ste_Corr_value_I_7_0_len 8
-#define	ste_Corr_value_I_7_0_lsb 0
-#define xd_r_ste_Corr_value_I_15_8	0xA231
-#define	ste_Corr_value_I_15_8_pos 0
-#define	ste_Corr_value_I_15_8_len 8
-#define	ste_Corr_value_I_15_8_lsb 8
-#define xd_r_ste_Corr_value_I_23_16	0xA232
-#define	ste_Corr_value_I_23_16_pos 0
-#define	ste_Corr_value_I_23_16_len 8
-#define	ste_Corr_value_I_23_16_lsb 16
-#define xd_r_ste_Corr_value_I_27_24	0xA233
-#define	ste_Corr_value_I_27_24_pos 0
-#define	ste_Corr_value_I_27_24_len 4
-#define	ste_Corr_value_I_27_24_lsb 24
-#define xd_r_ste_Corr_value_Q_7_0	0xA234
-#define	ste_Corr_value_Q_7_0_pos 0
-#define	ste_Corr_value_Q_7_0_len 8
-#define	ste_Corr_value_Q_7_0_lsb 0
-#define xd_r_ste_Corr_value_Q_15_8	0xA235
-#define	ste_Corr_value_Q_15_8_pos 0
-#define	ste_Corr_value_Q_15_8_len 8
-#define	ste_Corr_value_Q_15_8_lsb 8
-#define xd_r_ste_Corr_value_Q_23_16	0xA236
-#define	ste_Corr_value_Q_23_16_pos 0
-#define	ste_Corr_value_Q_23_16_len 8
-#define	ste_Corr_value_Q_23_16_lsb 16
-#define xd_r_ste_Corr_value_Q_27_24	0xA237
-#define	ste_Corr_value_Q_27_24_pos 0
-#define	ste_Corr_value_Q_27_24_len 4
-#define	ste_Corr_value_Q_27_24_lsb 24
-#define xd_r_ste_J_num_7_0	0xA238
-#define	ste_J_num_7_0_pos 0
-#define	ste_J_num_7_0_len 8
-#define	ste_J_num_7_0_lsb 0
-#define xd_r_ste_J_num_15_8	0xA239
-#define	ste_J_num_15_8_pos 0
-#define	ste_J_num_15_8_len 8
-#define	ste_J_num_15_8_lsb 8
-#define xd_r_ste_J_num_23_16	0xA23A
-#define	ste_J_num_23_16_pos 0
-#define	ste_J_num_23_16_len 8
-#define	ste_J_num_23_16_lsb 16
-#define xd_r_ste_J_num_31_24	0xA23B
-#define	ste_J_num_31_24_pos 0
-#define	ste_J_num_31_24_len 8
-#define	ste_J_num_31_24_lsb 24
-#define xd_r_ste_J_den_7_0	0xA23C
-#define	ste_J_den_7_0_pos 0
-#define	ste_J_den_7_0_len 8
-#define	ste_J_den_7_0_lsb 0
-#define xd_r_ste_J_den_15_8	0xA23D
-#define	ste_J_den_15_8_pos 0
-#define	ste_J_den_15_8_len 8
-#define	ste_J_den_15_8_lsb 8
-#define xd_r_ste_J_den_18_16	0xA23E
-#define	ste_J_den_18_16_pos 0
-#define	ste_J_den_18_16_len 3
-#define	ste_J_den_18_16_lsb 16
-#define xd_r_ste_Beacon_Indicator	0xA23E
-#define	ste_Beacon_Indicator_pos 4
-#define	ste_Beacon_Indicator_len 1
-#define	ste_Beacon_Indicator_lsb 0
-#define xd_r_tpsd_Frame_Num	0xA250
-#define	tpsd_Frame_Num_pos 0
-#define	tpsd_Frame_Num_len 2
-#define	tpsd_Frame_Num_lsb 0
-#define xd_r_tpsd_Constel	0xA250
-#define	tpsd_Constel_pos 2
-#define	tpsd_Constel_len 2
-#define	tpsd_Constel_lsb 0
-#define xd_r_tpsd_GI	0xA250
-#define	tpsd_GI_pos 4
-#define	tpsd_GI_len 2
-#define	tpsd_GI_lsb 0
-#define xd_r_tpsd_Mode	0xA250
-#define	tpsd_Mode_pos 6
-#define	tpsd_Mode_len 2
-#define	tpsd_Mode_lsb 0
-#define xd_r_tpsd_CR_HP	0xA251
-#define	tpsd_CR_HP_pos 0
-#define	tpsd_CR_HP_len 3
-#define	tpsd_CR_HP_lsb 0
-#define xd_r_tpsd_CR_LP	0xA251
-#define	tpsd_CR_LP_pos 3
-#define	tpsd_CR_LP_len 3
-#define	tpsd_CR_LP_lsb 0
-#define xd_r_tpsd_Hie	0xA252
-#define	tpsd_Hie_pos 0
-#define	tpsd_Hie_len 3
-#define	tpsd_Hie_lsb 0
-#define xd_r_tpsd_Res_Bits	0xA252
-#define	tpsd_Res_Bits_pos 3
-#define	tpsd_Res_Bits_len 5
-#define	tpsd_Res_Bits_lsb 0
-#define xd_r_tpsd_Res_Bits_0	0xA253
-#define	tpsd_Res_Bits_0_pos 0
-#define	tpsd_Res_Bits_0_len 1
-#define	tpsd_Res_Bits_0_lsb 0
-#define xd_r_tpsd_LengthInd	0xA253
-#define	tpsd_LengthInd_pos 1
-#define	tpsd_LengthInd_len 6
-#define	tpsd_LengthInd_lsb 0
-#define xd_r_tpsd_Cell_Id_7_0	0xA254
-#define	tpsd_Cell_Id_7_0_pos 0
-#define	tpsd_Cell_Id_7_0_len 8
-#define	tpsd_Cell_Id_7_0_lsb 0
-#define xd_r_tpsd_Cell_Id_15_8	0xA255
-#define	tpsd_Cell_Id_15_8_pos 0
-#define	tpsd_Cell_Id_15_8_len 8
-#define	tpsd_Cell_Id_15_8_lsb 0
-#define xd_p_reg_fft_mask_tone0_7_0	0xA260
-#define	reg_fft_mask_tone0_7_0_pos 0
-#define	reg_fft_mask_tone0_7_0_len 8
-#define	reg_fft_mask_tone0_7_0_lsb 0
-#define xd_p_reg_fft_mask_tone0_12_8	0xA261
-#define	reg_fft_mask_tone0_12_8_pos 0
-#define	reg_fft_mask_tone0_12_8_len 5
-#define	reg_fft_mask_tone0_12_8_lsb 8
-#define xd_p_reg_fft_mask_tone1_7_0	0xA262
-#define	reg_fft_mask_tone1_7_0_pos 0
-#define	reg_fft_mask_tone1_7_0_len 8
-#define	reg_fft_mask_tone1_7_0_lsb 0
-#define xd_p_reg_fft_mask_tone1_12_8	0xA263
-#define	reg_fft_mask_tone1_12_8_pos 0
-#define	reg_fft_mask_tone1_12_8_len 5
-#define	reg_fft_mask_tone1_12_8_lsb 8
-#define xd_p_reg_fft_mask_tone2_7_0	0xA264
-#define	reg_fft_mask_tone2_7_0_pos 0
-#define	reg_fft_mask_tone2_7_0_len 8
-#define	reg_fft_mask_tone2_7_0_lsb 0
-#define xd_p_reg_fft_mask_tone2_12_8	0xA265
-#define	reg_fft_mask_tone2_12_8_pos 0
-#define	reg_fft_mask_tone2_12_8_len 5
-#define	reg_fft_mask_tone2_12_8_lsb 8
-#define xd_p_reg_fft_mask_tone3_7_0	0xA266
-#define	reg_fft_mask_tone3_7_0_pos 0
-#define	reg_fft_mask_tone3_7_0_len 8
-#define	reg_fft_mask_tone3_7_0_lsb 0
-#define xd_p_reg_fft_mask_tone3_12_8	0xA267
-#define	reg_fft_mask_tone3_12_8_pos 0
-#define	reg_fft_mask_tone3_12_8_len 5
-#define	reg_fft_mask_tone3_12_8_lsb 8
-#define xd_p_reg_fft_mask_from0_7_0	0xA268
-#define	reg_fft_mask_from0_7_0_pos 0
-#define	reg_fft_mask_from0_7_0_len 8
-#define	reg_fft_mask_from0_7_0_lsb 0
-#define xd_p_reg_fft_mask_from0_12_8	0xA269
-#define	reg_fft_mask_from0_12_8_pos 0
-#define	reg_fft_mask_from0_12_8_len 5
-#define	reg_fft_mask_from0_12_8_lsb 8
-#define xd_p_reg_fft_mask_to0_7_0	0xA26A
-#define	reg_fft_mask_to0_7_0_pos 0
-#define	reg_fft_mask_to0_7_0_len 8
-#define	reg_fft_mask_to0_7_0_lsb 0
-#define xd_p_reg_fft_mask_to0_12_8	0xA26B
-#define	reg_fft_mask_to0_12_8_pos 0
-#define	reg_fft_mask_to0_12_8_len 5
-#define	reg_fft_mask_to0_12_8_lsb 8
-#define xd_p_reg_fft_mask_from1_7_0	0xA26C
-#define	reg_fft_mask_from1_7_0_pos 0
-#define	reg_fft_mask_from1_7_0_len 8
-#define	reg_fft_mask_from1_7_0_lsb 0
-#define xd_p_reg_fft_mask_from1_12_8	0xA26D
-#define	reg_fft_mask_from1_12_8_pos 0
-#define	reg_fft_mask_from1_12_8_len 5
-#define	reg_fft_mask_from1_12_8_lsb 8
-#define xd_p_reg_fft_mask_to1_7_0	0xA26E
-#define	reg_fft_mask_to1_7_0_pos 0
-#define	reg_fft_mask_to1_7_0_len 8
-#define	reg_fft_mask_to1_7_0_lsb 0
-#define xd_p_reg_fft_mask_to1_12_8	0xA26F
-#define	reg_fft_mask_to1_12_8_pos 0
-#define	reg_fft_mask_to1_12_8_len 5
-#define	reg_fft_mask_to1_12_8_lsb 8
-#define xd_p_reg_cge_idx0_7_0	0xA280
-#define	reg_cge_idx0_7_0_pos 0
-#define	reg_cge_idx0_7_0_len 8
-#define	reg_cge_idx0_7_0_lsb 0
-#define xd_p_reg_cge_idx0_12_8	0xA281
-#define	reg_cge_idx0_12_8_pos 0
-#define	reg_cge_idx0_12_8_len 5
-#define	reg_cge_idx0_12_8_lsb 8
-#define xd_p_reg_cge_idx1_7_0	0xA282
-#define	reg_cge_idx1_7_0_pos 0
-#define	reg_cge_idx1_7_0_len 8
-#define	reg_cge_idx1_7_0_lsb 0
-#define xd_p_reg_cge_idx1_12_8	0xA283
-#define	reg_cge_idx1_12_8_pos 0
-#define	reg_cge_idx1_12_8_len 5
-#define	reg_cge_idx1_12_8_lsb 8
-#define xd_p_reg_cge_idx2_7_0	0xA284
-#define	reg_cge_idx2_7_0_pos 0
-#define	reg_cge_idx2_7_0_len 8
-#define	reg_cge_idx2_7_0_lsb 0
-#define xd_p_reg_cge_idx2_12_8	0xA285
-#define	reg_cge_idx2_12_8_pos 0
-#define	reg_cge_idx2_12_8_len 5
-#define	reg_cge_idx2_12_8_lsb 8
-#define xd_p_reg_cge_idx3_7_0	0xA286
-#define	reg_cge_idx3_7_0_pos 0
-#define	reg_cge_idx3_7_0_len 8
-#define	reg_cge_idx3_7_0_lsb 0
-#define xd_p_reg_cge_idx3_12_8	0xA287
-#define	reg_cge_idx3_12_8_pos 0
-#define	reg_cge_idx3_12_8_len 5
-#define	reg_cge_idx3_12_8_lsb 8
-#define xd_p_reg_cge_idx4_7_0	0xA288
-#define	reg_cge_idx4_7_0_pos 0
-#define	reg_cge_idx4_7_0_len 8
-#define	reg_cge_idx4_7_0_lsb 0
-#define xd_p_reg_cge_idx4_12_8	0xA289
-#define	reg_cge_idx4_12_8_pos 0
-#define	reg_cge_idx4_12_8_len 5
-#define	reg_cge_idx4_12_8_lsb 8
-#define xd_p_reg_cge_idx5_7_0	0xA28A
-#define	reg_cge_idx5_7_0_pos 0
-#define	reg_cge_idx5_7_0_len 8
-#define	reg_cge_idx5_7_0_lsb 0
-#define xd_p_reg_cge_idx5_12_8	0xA28B
-#define	reg_cge_idx5_12_8_pos 0
-#define	reg_cge_idx5_12_8_len 5
-#define	reg_cge_idx5_12_8_lsb 8
-#define xd_p_reg_cge_idx6_7_0	0xA28C
-#define	reg_cge_idx6_7_0_pos 0
-#define	reg_cge_idx6_7_0_len 8
-#define	reg_cge_idx6_7_0_lsb 0
-#define xd_p_reg_cge_idx6_12_8	0xA28D
-#define	reg_cge_idx6_12_8_pos 0
-#define	reg_cge_idx6_12_8_len 5
-#define	reg_cge_idx6_12_8_lsb 8
-#define xd_p_reg_cge_idx7_7_0	0xA28E
-#define	reg_cge_idx7_7_0_pos 0
-#define	reg_cge_idx7_7_0_len 8
-#define	reg_cge_idx7_7_0_lsb 0
-#define xd_p_reg_cge_idx7_12_8	0xA28F
-#define	reg_cge_idx7_12_8_pos 0
-#define	reg_cge_idx7_12_8_len 5
-#define	reg_cge_idx7_12_8_lsb 8
-#define xd_p_reg_cge_idx8_7_0	0xA290
-#define	reg_cge_idx8_7_0_pos 0
-#define	reg_cge_idx8_7_0_len 8
-#define	reg_cge_idx8_7_0_lsb 0
-#define xd_p_reg_cge_idx8_12_8	0xA291
-#define	reg_cge_idx8_12_8_pos 0
-#define	reg_cge_idx8_12_8_len 5
-#define	reg_cge_idx8_12_8_lsb 8
-#define xd_p_reg_cge_idx9_7_0	0xA292
-#define	reg_cge_idx9_7_0_pos 0
-#define	reg_cge_idx9_7_0_len 8
-#define	reg_cge_idx9_7_0_lsb 0
-#define xd_p_reg_cge_idx9_12_8	0xA293
-#define	reg_cge_idx9_12_8_pos 0
-#define	reg_cge_idx9_12_8_len 5
-#define	reg_cge_idx9_12_8_lsb 8
-#define xd_p_reg_cge_idx10_7_0	0xA294
-#define	reg_cge_idx10_7_0_pos 0
-#define	reg_cge_idx10_7_0_len 8
-#define	reg_cge_idx10_7_0_lsb 0
-#define xd_p_reg_cge_idx10_12_8	0xA295
-#define	reg_cge_idx10_12_8_pos 0
-#define	reg_cge_idx10_12_8_len 5
-#define	reg_cge_idx10_12_8_lsb 8
-#define xd_p_reg_cge_idx11_7_0	0xA296
-#define	reg_cge_idx11_7_0_pos 0
-#define	reg_cge_idx11_7_0_len 8
-#define	reg_cge_idx11_7_0_lsb 0
-#define xd_p_reg_cge_idx11_12_8	0xA297
-#define	reg_cge_idx11_12_8_pos 0
-#define	reg_cge_idx11_12_8_len 5
-#define	reg_cge_idx11_12_8_lsb 8
-#define xd_p_reg_cge_idx12_7_0	0xA298
-#define	reg_cge_idx12_7_0_pos 0
-#define	reg_cge_idx12_7_0_len 8
-#define	reg_cge_idx12_7_0_lsb 0
-#define xd_p_reg_cge_idx12_12_8	0xA299
-#define	reg_cge_idx12_12_8_pos 0
-#define	reg_cge_idx12_12_8_len 5
-#define	reg_cge_idx12_12_8_lsb 8
-#define xd_p_reg_cge_idx13_7_0	0xA29A
-#define	reg_cge_idx13_7_0_pos 0
-#define	reg_cge_idx13_7_0_len 8
-#define	reg_cge_idx13_7_0_lsb 0
-#define xd_p_reg_cge_idx13_12_8	0xA29B
-#define	reg_cge_idx13_12_8_pos 0
-#define	reg_cge_idx13_12_8_len 5
-#define	reg_cge_idx13_12_8_lsb 8
-#define xd_p_reg_cge_idx14_7_0	0xA29C
-#define	reg_cge_idx14_7_0_pos 0
-#define	reg_cge_idx14_7_0_len 8
-#define	reg_cge_idx14_7_0_lsb 0
-#define xd_p_reg_cge_idx14_12_8	0xA29D
-#define	reg_cge_idx14_12_8_pos 0
-#define	reg_cge_idx14_12_8_len 5
-#define	reg_cge_idx14_12_8_lsb 8
-#define xd_p_reg_cge_idx15_7_0	0xA29E
-#define	reg_cge_idx15_7_0_pos 0
-#define	reg_cge_idx15_7_0_len 8
-#define	reg_cge_idx15_7_0_lsb 0
-#define xd_p_reg_cge_idx15_12_8	0xA29F
-#define	reg_cge_idx15_12_8_pos 0
-#define	reg_cge_idx15_12_8_len 5
-#define	reg_cge_idx15_12_8_lsb 8
-#define xd_r_reg_fft_crc	0xA2A8
-#define	reg_fft_crc_pos 0
-#define	reg_fft_crc_len 8
-#define	reg_fft_crc_lsb 0
-#define xd_p_fd_fft_shift_max	0xA2A9
-#define	fd_fft_shift_max_pos 0
-#define	fd_fft_shift_max_len 4
-#define	fd_fft_shift_max_lsb 0
-#define xd_r_fd_fft_shift	0xA2A9
-#define	fd_fft_shift_pos 4
-#define	fd_fft_shift_len 4
-#define	fd_fft_shift_lsb 0
-#define xd_r_fd_fft_frame_num	0xA2AA
-#define	fd_fft_frame_num_pos 0
-#define	fd_fft_frame_num_len 2
-#define	fd_fft_frame_num_lsb 0
-#define xd_r_fd_fft_symbol_count	0xA2AB
-#define	fd_fft_symbol_count_pos 0
-#define	fd_fft_symbol_count_len 7
-#define	fd_fft_symbol_count_lsb 0
-#define xd_r_reg_fft_idx_max_7_0	0xA2AC
-#define	reg_fft_idx_max_7_0_pos 0
-#define	reg_fft_idx_max_7_0_len 8
-#define	reg_fft_idx_max_7_0_lsb 0
-#define xd_r_reg_fft_idx_max_12_8	0xA2AD
-#define	reg_fft_idx_max_12_8_pos 0
-#define	reg_fft_idx_max_12_8_len 5
-#define	reg_fft_idx_max_12_8_lsb 8
-#define xd_p_reg_cge_program	0xA2AE
-#define	reg_cge_program_pos 0
-#define	reg_cge_program_len 1
-#define	reg_cge_program_lsb 0
-#define xd_p_reg_cge_fixed	0xA2AE
-#define	reg_cge_fixed_pos 1
-#define	reg_cge_fixed_len 1
-#define	reg_cge_fixed_lsb 0
-#define xd_p_reg_fft_rotate_en	0xA2AE
-#define	reg_fft_rotate_en_pos 2
-#define	reg_fft_rotate_en_len 1
-#define	reg_fft_rotate_en_lsb 0
-#define xd_p_reg_fft_rotate_base_4_0	0xA2AE
-#define	reg_fft_rotate_base_4_0_pos 3
-#define	reg_fft_rotate_base_4_0_len 5
-#define	reg_fft_rotate_base_4_0_lsb 0
-#define xd_p_reg_fft_rotate_base_12_5	0xA2AF
-#define	reg_fft_rotate_base_12_5_pos 0
-#define	reg_fft_rotate_base_12_5_len 8
-#define	reg_fft_rotate_base_12_5_lsb 5
-#define xd_p_reg_gp_trigger_fd	0xA2B8
-#define	reg_gp_trigger_fd_pos 0
-#define	reg_gp_trigger_fd_len 1
-#define	reg_gp_trigger_fd_lsb 0
-#define xd_p_reg_trigger_sel_fd	0xA2B8
-#define	reg_trigger_sel_fd_pos 1
-#define	reg_trigger_sel_fd_len 2
-#define	reg_trigger_sel_fd_lsb 0
-#define xd_p_reg_trigger_module_sel_fd	0xA2B9
-#define	reg_trigger_module_sel_fd_pos 0
-#define	reg_trigger_module_sel_fd_len 6
-#define	reg_trigger_module_sel_fd_lsb 0
-#define xd_p_reg_trigger_set_sel_fd	0xA2BA
-#define	reg_trigger_set_sel_fd_pos 0
-#define	reg_trigger_set_sel_fd_len 6
-#define	reg_trigger_set_sel_fd_lsb 0
-#define xd_p_reg_fd_noname_7_0	0xA2BC
-#define	reg_fd_noname_7_0_pos 0
-#define	reg_fd_noname_7_0_len 8
-#define	reg_fd_noname_7_0_lsb 0
-#define xd_p_reg_fd_noname_15_8	0xA2BD
-#define	reg_fd_noname_15_8_pos 0
-#define	reg_fd_noname_15_8_len 8
-#define	reg_fd_noname_15_8_lsb 8
-#define xd_p_reg_fd_noname_23_16	0xA2BE
-#define	reg_fd_noname_23_16_pos 0
-#define	reg_fd_noname_23_16_len 8
-#define	reg_fd_noname_23_16_lsb 16
-#define xd_p_reg_fd_noname_31_24	0xA2BF
-#define	reg_fd_noname_31_24_pos 0
-#define	reg_fd_noname_31_24_len 8
-#define	reg_fd_noname_31_24_lsb 24
-#define xd_r_fd_fpcc_cp_corr_signn	0xA2C0
-#define	fd_fpcc_cp_corr_signn_pos 0
-#define	fd_fpcc_cp_corr_signn_len 8
-#define	fd_fpcc_cp_corr_signn_lsb 0
-#define xd_p_reg_feq_s1	0xA2C1
-#define	reg_feq_s1_pos 0
-#define	reg_feq_s1_len 5
-#define	reg_feq_s1_lsb 0
-#define xd_p_fd_fpcc_cp_corr_tone_th	0xA2C2
-#define	fd_fpcc_cp_corr_tone_th_pos 0
-#define	fd_fpcc_cp_corr_tone_th_len 6
-#define	fd_fpcc_cp_corr_tone_th_lsb 0
-#define xd_p_fd_fpcc_cp_corr_symbol_log_th	0xA2C3
-#define	fd_fpcc_cp_corr_symbol_log_th_pos 0
-#define	fd_fpcc_cp_corr_symbol_log_th_len 4
-#define	fd_fpcc_cp_corr_symbol_log_th_lsb 0
-#define xd_p_fd_fpcc_cp_corr_int	0xA2C4
-#define	fd_fpcc_cp_corr_int_pos 0
-#define	fd_fpcc_cp_corr_int_len 1
-#define	fd_fpcc_cp_corr_int_lsb 0
-#define xd_p_reg_sfoe_ns_7_0	0xA320
-#define	reg_sfoe_ns_7_0_pos 0
-#define	reg_sfoe_ns_7_0_len 8
-#define	reg_sfoe_ns_7_0_lsb 0
-#define xd_p_reg_sfoe_ns_14_8	0xA321
-#define	reg_sfoe_ns_14_8_pos 0
-#define	reg_sfoe_ns_14_8_len 7
-#define	reg_sfoe_ns_14_8_lsb 8
-#define xd_p_reg_sfoe_c1_7_0	0xA322
-#define	reg_sfoe_c1_7_0_pos 0
-#define	reg_sfoe_c1_7_0_len 8
-#define	reg_sfoe_c1_7_0_lsb 0
-#define xd_p_reg_sfoe_c1_15_8	0xA323
-#define	reg_sfoe_c1_15_8_pos 0
-#define	reg_sfoe_c1_15_8_len 8
-#define	reg_sfoe_c1_15_8_lsb 8
-#define xd_p_reg_sfoe_c1_17_16	0xA324
-#define	reg_sfoe_c1_17_16_pos 0
-#define	reg_sfoe_c1_17_16_len 2
-#define	reg_sfoe_c1_17_16_lsb 16
-#define xd_p_reg_sfoe_c2_7_0	0xA325
-#define	reg_sfoe_c2_7_0_pos 0
-#define	reg_sfoe_c2_7_0_len 8
-#define	reg_sfoe_c2_7_0_lsb 0
-#define xd_p_reg_sfoe_c2_15_8	0xA326
-#define	reg_sfoe_c2_15_8_pos 0
-#define	reg_sfoe_c2_15_8_len 8
-#define	reg_sfoe_c2_15_8_lsb 8
-#define xd_p_reg_sfoe_c2_17_16	0xA327
-#define	reg_sfoe_c2_17_16_pos 0
-#define	reg_sfoe_c2_17_16_len 2
-#define	reg_sfoe_c2_17_16_lsb 16
-#define xd_r_reg_sfoe_out_9_2	0xA328
-#define	reg_sfoe_out_9_2_pos 0
-#define	reg_sfoe_out_9_2_len 8
-#define	reg_sfoe_out_9_2_lsb 0
-#define xd_r_reg_sfoe_out_1_0	0xA329
-#define	reg_sfoe_out_1_0_pos 0
-#define	reg_sfoe_out_1_0_len 2
-#define	reg_sfoe_out_1_0_lsb 0
-#define xd_p_reg_sfoe_lm_counter_th	0xA32A
-#define	reg_sfoe_lm_counter_th_pos 0
-#define	reg_sfoe_lm_counter_th_len 4
-#define	reg_sfoe_lm_counter_th_lsb 0
-#define xd_p_reg_sfoe_convg_th	0xA32B
-#define	reg_sfoe_convg_th_pos 0
-#define	reg_sfoe_convg_th_len 8
-#define	reg_sfoe_convg_th_lsb 0
-#define xd_p_reg_sfoe_divg_th	0xA32C
-#define	reg_sfoe_divg_th_pos 0
-#define	reg_sfoe_divg_th_len 8
-#define	reg_sfoe_divg_th_lsb 0
-#define xd_p_fd_tpsd_en	0xA330
-#define	fd_tpsd_en_pos 0
-#define	fd_tpsd_en_len 1
-#define	fd_tpsd_en_lsb 0
-#define xd_p_fd_tpsd_dis	0xA330
-#define	fd_tpsd_dis_pos 1
-#define	fd_tpsd_dis_len 1
-#define	fd_tpsd_dis_lsb 0
-#define xd_p_fd_tpsd_rst	0xA330
-#define	fd_tpsd_rst_pos 2
-#define	fd_tpsd_rst_len 1
-#define	fd_tpsd_rst_lsb 0
-#define xd_p_fd_tpsd_lock	0xA330
-#define	fd_tpsd_lock_pos 3
-#define	fd_tpsd_lock_len 1
-#define	fd_tpsd_lock_lsb 0
-#define xd_r_fd_tpsd_s19	0xA330
-#define	fd_tpsd_s19_pos 4
-#define	fd_tpsd_s19_len 1
-#define	fd_tpsd_s19_lsb 0
-#define xd_r_fd_tpsd_s17	0xA330
-#define	fd_tpsd_s17_pos 5
-#define	fd_tpsd_s17_len 1
-#define	fd_tpsd_s17_lsb 0
-#define xd_p_fd_sfr_ste_en	0xA331
-#define	fd_sfr_ste_en_pos 0
-#define	fd_sfr_ste_en_len 1
-#define	fd_sfr_ste_en_lsb 0
-#define xd_p_fd_sfr_ste_dis	0xA331
-#define	fd_sfr_ste_dis_pos 1
-#define	fd_sfr_ste_dis_len 1
-#define	fd_sfr_ste_dis_lsb 0
-#define xd_p_fd_sfr_ste_rst	0xA331
-#define	fd_sfr_ste_rst_pos 2
-#define	fd_sfr_ste_rst_len 1
-#define	fd_sfr_ste_rst_lsb 0
-#define xd_p_fd_sfr_ste_mode	0xA331
-#define	fd_sfr_ste_mode_pos 3
-#define	fd_sfr_ste_mode_len 1
-#define	fd_sfr_ste_mode_lsb 0
-#define xd_p_fd_sfr_ste_done	0xA331
-#define	fd_sfr_ste_done_pos 4
-#define	fd_sfr_ste_done_len 1
-#define	fd_sfr_ste_done_lsb 0
-#define xd_p_reg_cfoe_ffoe_en	0xA332
-#define	reg_cfoe_ffoe_en_pos 0
-#define	reg_cfoe_ffoe_en_len 1
-#define	reg_cfoe_ffoe_en_lsb 0
-#define xd_p_reg_cfoe_ffoe_dis	0xA332
-#define	reg_cfoe_ffoe_dis_pos 1
-#define	reg_cfoe_ffoe_dis_len 1
-#define	reg_cfoe_ffoe_dis_lsb 0
-#define xd_p_reg_cfoe_ffoe_rst	0xA332
-#define	reg_cfoe_ffoe_rst_pos 2
-#define	reg_cfoe_ffoe_rst_len 1
-#define	reg_cfoe_ffoe_rst_lsb 0
-#define xd_p_reg_cfoe_ifoe_en	0xA332
-#define	reg_cfoe_ifoe_en_pos 3
-#define	reg_cfoe_ifoe_en_len 1
-#define	reg_cfoe_ifoe_en_lsb 0
-#define xd_p_reg_cfoe_ifoe_dis	0xA332
-#define	reg_cfoe_ifoe_dis_pos 4
-#define	reg_cfoe_ifoe_dis_len 1
-#define	reg_cfoe_ifoe_dis_lsb 0
-#define xd_p_reg_cfoe_ifoe_rst	0xA332
-#define	reg_cfoe_ifoe_rst_pos 5
-#define	reg_cfoe_ifoe_rst_len 1
-#define	reg_cfoe_ifoe_rst_lsb 0
-#define xd_p_reg_cfoe_fot_en	0xA332
-#define	reg_cfoe_fot_en_pos 6
-#define	reg_cfoe_fot_en_len 1
-#define	reg_cfoe_fot_en_lsb 0
-#define xd_p_reg_cfoe_fot_lm_en	0xA332
-#define	reg_cfoe_fot_lm_en_pos 7
-#define	reg_cfoe_fot_lm_en_len 1
-#define	reg_cfoe_fot_lm_en_lsb 0
-#define xd_p_reg_cfoe_fot_rst	0xA333
-#define	reg_cfoe_fot_rst_pos 0
-#define	reg_cfoe_fot_rst_len 1
-#define	reg_cfoe_fot_rst_lsb 0
-#define xd_r_fd_cfoe_ffoe_done	0xA333
-#define	fd_cfoe_ffoe_done_pos 1
-#define	fd_cfoe_ffoe_done_len 1
-#define	fd_cfoe_ffoe_done_lsb 0
-#define xd_p_fd_cfoe_metric_vld	0xA333
-#define	fd_cfoe_metric_vld_pos 2
-#define	fd_cfoe_metric_vld_len 1
-#define	fd_cfoe_metric_vld_lsb 0
-#define xd_p_reg_cfoe_ifod_vld	0xA333
-#define	reg_cfoe_ifod_vld_pos 3
-#define	reg_cfoe_ifod_vld_len 1
-#define	reg_cfoe_ifod_vld_lsb 0
-#define xd_r_fd_cfoe_ifoe_done	0xA333
-#define	fd_cfoe_ifoe_done_pos 4
-#define	fd_cfoe_ifoe_done_len 1
-#define	fd_cfoe_ifoe_done_lsb 0
-#define xd_r_fd_cfoe_fot_valid	0xA333
-#define	fd_cfoe_fot_valid_pos 5
-#define	fd_cfoe_fot_valid_len 1
-#define	fd_cfoe_fot_valid_lsb 0
-#define xd_p_reg_cfoe_divg_int	0xA333
-#define	reg_cfoe_divg_int_pos 6
-#define	reg_cfoe_divg_int_len 1
-#define	reg_cfoe_divg_int_lsb 0
-#define xd_r_reg_cfoe_divg_flag	0xA333
-#define	reg_cfoe_divg_flag_pos 7
-#define	reg_cfoe_divg_flag_len 1
-#define	reg_cfoe_divg_flag_lsb 0
-#define xd_p_reg_sfoe_en	0xA334
-#define	reg_sfoe_en_pos 0
-#define	reg_sfoe_en_len 1
-#define	reg_sfoe_en_lsb 0
-#define xd_p_reg_sfoe_dis	0xA334
-#define	reg_sfoe_dis_pos 1
-#define	reg_sfoe_dis_len 1
-#define	reg_sfoe_dis_lsb 0
-#define xd_p_reg_sfoe_rst	0xA334
-#define	reg_sfoe_rst_pos 2
-#define	reg_sfoe_rst_len 1
-#define	reg_sfoe_rst_lsb 0
-#define xd_p_reg_sfoe_vld_int	0xA334
-#define	reg_sfoe_vld_int_pos 3
-#define	reg_sfoe_vld_int_len 1
-#define	reg_sfoe_vld_int_lsb 0
-#define xd_p_reg_sfoe_lm_en	0xA334
-#define	reg_sfoe_lm_en_pos 4
-#define	reg_sfoe_lm_en_len 1
-#define	reg_sfoe_lm_en_lsb 0
-#define xd_p_reg_sfoe_divg_int	0xA334
-#define	reg_sfoe_divg_int_pos 5
-#define	reg_sfoe_divg_int_len 1
-#define	reg_sfoe_divg_int_lsb 0
-#define xd_r_reg_sfoe_divg_flag	0xA334
-#define	reg_sfoe_divg_flag_pos 6
-#define	reg_sfoe_divg_flag_len 1
-#define	reg_sfoe_divg_flag_lsb 0
-#define xd_p_reg_fft_rst	0xA335
-#define	reg_fft_rst_pos 0
-#define	reg_fft_rst_len 1
-#define	reg_fft_rst_lsb 0
-#define xd_p_reg_fft_fast_beacon	0xA335
-#define	reg_fft_fast_beacon_pos 1
-#define	reg_fft_fast_beacon_len 1
-#define	reg_fft_fast_beacon_lsb 0
-#define xd_p_reg_fft_fast_valid	0xA335
-#define	reg_fft_fast_valid_pos 2
-#define	reg_fft_fast_valid_len 1
-#define	reg_fft_fast_valid_lsb 0
-#define xd_p_reg_fft_mask_en	0xA335
-#define	reg_fft_mask_en_pos 3
-#define	reg_fft_mask_en_len 1
-#define	reg_fft_mask_en_lsb 0
-#define xd_p_reg_fft_crc_en	0xA335
-#define	reg_fft_crc_en_pos 4
-#define	reg_fft_crc_en_len 1
-#define	reg_fft_crc_en_lsb 0
-#define xd_p_reg_finr_en	0xA336
-#define	reg_finr_en_pos 0
-#define	reg_finr_en_len 1
-#define	reg_finr_en_lsb 0
-#define xd_p_fd_fste_en	0xA337
-#define	fd_fste_en_pos 1
-#define	fd_fste_en_len 1
-#define	fd_fste_en_lsb 0
-#define xd_p_fd_sqi_tps_level_shift	0xA338
-#define	fd_sqi_tps_level_shift_pos 0
-#define	fd_sqi_tps_level_shift_len 8
-#define	fd_sqi_tps_level_shift_lsb 0
-#define xd_p_fd_pilot_ma_len	0xA339
-#define	fd_pilot_ma_len_pos 0
-#define	fd_pilot_ma_len_len 6
-#define	fd_pilot_ma_len_lsb 0
-#define xd_p_fd_tps_ma_len	0xA33A
-#define	fd_tps_ma_len_pos 0
-#define	fd_tps_ma_len_len 6
-#define	fd_tps_ma_len_lsb 0
-#define xd_p_fd_sqi_s3	0xA33B
-#define	fd_sqi_s3_pos 0
-#define	fd_sqi_s3_len 8
-#define	fd_sqi_s3_lsb 0
-#define xd_p_fd_sqi_dummy_reg_0	0xA33C
-#define	fd_sqi_dummy_reg_0_pos 0
-#define	fd_sqi_dummy_reg_0_len 1
-#define	fd_sqi_dummy_reg_0_lsb 0
-#define xd_p_fd_sqi_debug_sel	0xA33C
-#define	fd_sqi_debug_sel_pos 1
-#define	fd_sqi_debug_sel_len 2
-#define	fd_sqi_debug_sel_lsb 0
-#define xd_p_fd_sqi_s2	0xA33C
-#define	fd_sqi_s2_pos 3
-#define	fd_sqi_s2_len 5
-#define	fd_sqi_s2_lsb 0
-#define xd_p_fd_sqi_dummy_reg_1	0xA33D
-#define	fd_sqi_dummy_reg_1_pos 0
-#define	fd_sqi_dummy_reg_1_len 1
-#define	fd_sqi_dummy_reg_1_lsb 0
-#define xd_p_fd_inr_ignore	0xA33D
-#define	fd_inr_ignore_pos 1
-#define	fd_inr_ignore_len 1
-#define	fd_inr_ignore_lsb 0
-#define xd_p_fd_pilot_ignore	0xA33D
-#define	fd_pilot_ignore_pos 2
-#define	fd_pilot_ignore_len 1
-#define	fd_pilot_ignore_lsb 0
-#define xd_p_fd_etps_ignore	0xA33D
-#define	fd_etps_ignore_pos 3
-#define	fd_etps_ignore_len 1
-#define	fd_etps_ignore_lsb 0
-#define xd_p_fd_sqi_s1	0xA33D
-#define	fd_sqi_s1_pos 4
-#define	fd_sqi_s1_len 4
-#define	fd_sqi_s1_lsb 0
-#define xd_p_reg_fste_ehw_7_0	0xA33E
-#define	reg_fste_ehw_7_0_pos 0
-#define	reg_fste_ehw_7_0_len 8
-#define	reg_fste_ehw_7_0_lsb 0
-#define xd_p_reg_fste_ehw_9_8	0xA33F
-#define	reg_fste_ehw_9_8_pos 0
-#define	reg_fste_ehw_9_8_len 2
-#define	reg_fste_ehw_9_8_lsb 8
-#define xd_p_reg_fste_i_adj_vld	0xA33F
-#define	reg_fste_i_adj_vld_pos 2
-#define	reg_fste_i_adj_vld_len 1
-#define	reg_fste_i_adj_vld_lsb 0
-#define xd_p_reg_fste_phase_ini_7_0	0xA340
-#define	reg_fste_phase_ini_7_0_pos 0
-#define	reg_fste_phase_ini_7_0_len 8
-#define	reg_fste_phase_ini_7_0_lsb 0
-#define xd_p_reg_fste_phase_ini_11_8	0xA341
-#define	reg_fste_phase_ini_11_8_pos 0
-#define	reg_fste_phase_ini_11_8_len 4
-#define	reg_fste_phase_ini_11_8_lsb 8
-#define xd_p_reg_fste_phase_inc_3_0	0xA341
-#define	reg_fste_phase_inc_3_0_pos 4
-#define	reg_fste_phase_inc_3_0_len 4
-#define	reg_fste_phase_inc_3_0_lsb 0
-#define xd_p_reg_fste_phase_inc_11_4	0xA342
-#define	reg_fste_phase_inc_11_4_pos 0
-#define	reg_fste_phase_inc_11_4_len 8
-#define	reg_fste_phase_inc_11_4_lsb 4
-#define xd_p_reg_fste_acum_cost_cnt_max	0xA343
-#define	reg_fste_acum_cost_cnt_max_pos 0
-#define	reg_fste_acum_cost_cnt_max_len 4
-#define	reg_fste_acum_cost_cnt_max_lsb 0
-#define xd_p_reg_fste_step_size_std	0xA343
-#define	reg_fste_step_size_std_pos 4
-#define	reg_fste_step_size_std_len 4
-#define	reg_fste_step_size_std_lsb 0
-#define xd_p_reg_fste_step_size_max	0xA344
-#define	reg_fste_step_size_max_pos 0
-#define	reg_fste_step_size_max_len 4
-#define	reg_fste_step_size_max_lsb 0
-#define xd_p_reg_fste_step_size_min	0xA344
-#define	reg_fste_step_size_min_pos 4
-#define	reg_fste_step_size_min_len 4
-#define	reg_fste_step_size_min_lsb 0
-#define xd_p_reg_fste_frac_step_size_7_0	0xA345
-#define	reg_fste_frac_step_size_7_0_pos 0
-#define	reg_fste_frac_step_size_7_0_len 8
-#define	reg_fste_frac_step_size_7_0_lsb 0
-#define xd_p_reg_fste_frac_step_size_15_8	0xA346
-#define	reg_fste_frac_step_size_15_8_pos 0
-#define	reg_fste_frac_step_size_15_8_len 8
-#define	reg_fste_frac_step_size_15_8_lsb 8
-#define xd_p_reg_fste_frac_step_size_19_16	0xA347
-#define	reg_fste_frac_step_size_19_16_pos 0
-#define	reg_fste_frac_step_size_19_16_len 4
-#define	reg_fste_frac_step_size_19_16_lsb 16
-#define xd_p_reg_fste_rpd_dir_cnt_max	0xA347
-#define	reg_fste_rpd_dir_cnt_max_pos 4
-#define	reg_fste_rpd_dir_cnt_max_len 4
-#define	reg_fste_rpd_dir_cnt_max_lsb 0
-#define xd_p_reg_fste_ehs	0xA348
-#define	reg_fste_ehs_pos 0
-#define	reg_fste_ehs_len 4
-#define	reg_fste_ehs_lsb 0
-#define xd_p_reg_fste_frac_cost_cnt_max_3_0	0xA348
-#define	reg_fste_frac_cost_cnt_max_3_0_pos 4
-#define	reg_fste_frac_cost_cnt_max_3_0_len 4
-#define	reg_fste_frac_cost_cnt_max_3_0_lsb 0
-#define xd_p_reg_fste_frac_cost_cnt_max_9_4	0xA349
-#define	reg_fste_frac_cost_cnt_max_9_4_pos 0
-#define	reg_fste_frac_cost_cnt_max_9_4_len 6
-#define	reg_fste_frac_cost_cnt_max_9_4_lsb 4
-#define xd_p_reg_fste_w0_7_0	0xA34A
-#define	reg_fste_w0_7_0_pos 0
-#define	reg_fste_w0_7_0_len 8
-#define	reg_fste_w0_7_0_lsb 0
-#define xd_p_reg_fste_w0_11_8	0xA34B
-#define	reg_fste_w0_11_8_pos 0
-#define	reg_fste_w0_11_8_len 4
-#define	reg_fste_w0_11_8_lsb 8
-#define xd_p_reg_fste_w1_3_0	0xA34B
-#define	reg_fste_w1_3_0_pos 4
-#define	reg_fste_w1_3_0_len 4
-#define	reg_fste_w1_3_0_lsb 0
-#define xd_p_reg_fste_w1_11_4	0xA34C
-#define	reg_fste_w1_11_4_pos 0
-#define	reg_fste_w1_11_4_len 8
-#define	reg_fste_w1_11_4_lsb 4
-#define xd_p_reg_fste_w2_7_0	0xA34D
-#define	reg_fste_w2_7_0_pos 0
-#define	reg_fste_w2_7_0_len 8
-#define	reg_fste_w2_7_0_lsb 0
-#define xd_p_reg_fste_w2_11_8	0xA34E
-#define	reg_fste_w2_11_8_pos 0
-#define	reg_fste_w2_11_8_len 4
-#define	reg_fste_w2_11_8_lsb 8
-#define xd_p_reg_fste_w3_3_0	0xA34E
-#define	reg_fste_w3_3_0_pos 4
-#define	reg_fste_w3_3_0_len 4
-#define	reg_fste_w3_3_0_lsb 0
-#define xd_p_reg_fste_w3_11_4	0xA34F
-#define	reg_fste_w3_11_4_pos 0
-#define	reg_fste_w3_11_4_len 8
-#define	reg_fste_w3_11_4_lsb 4
-#define xd_p_reg_fste_w4_7_0	0xA350
-#define	reg_fste_w4_7_0_pos 0
-#define	reg_fste_w4_7_0_len 8
-#define	reg_fste_w4_7_0_lsb 0
-#define xd_p_reg_fste_w4_11_8	0xA351
-#define	reg_fste_w4_11_8_pos 0
-#define	reg_fste_w4_11_8_len 4
-#define	reg_fste_w4_11_8_lsb 8
-#define xd_p_reg_fste_w5_3_0	0xA351
-#define	reg_fste_w5_3_0_pos 4
-#define	reg_fste_w5_3_0_len 4
-#define	reg_fste_w5_3_0_lsb 0
-#define xd_p_reg_fste_w5_11_4	0xA352
-#define	reg_fste_w5_11_4_pos 0
-#define	reg_fste_w5_11_4_len 8
-#define	reg_fste_w5_11_4_lsb 4
-#define xd_p_reg_fste_w6_7_0	0xA353
-#define	reg_fste_w6_7_0_pos 0
-#define	reg_fste_w6_7_0_len 8
-#define	reg_fste_w6_7_0_lsb 0
-#define xd_p_reg_fste_w6_11_8	0xA354
-#define	reg_fste_w6_11_8_pos 0
-#define	reg_fste_w6_11_8_len 4
-#define	reg_fste_w6_11_8_lsb 8
-#define xd_p_reg_fste_w7_3_0	0xA354
-#define	reg_fste_w7_3_0_pos 4
-#define	reg_fste_w7_3_0_len 4
-#define	reg_fste_w7_3_0_lsb 0
-#define xd_p_reg_fste_w7_11_4	0xA355
-#define	reg_fste_w7_11_4_pos 0
-#define	reg_fste_w7_11_4_len 8
-#define	reg_fste_w7_11_4_lsb 4
-#define xd_p_reg_fste_w8_7_0	0xA356
-#define	reg_fste_w8_7_0_pos 0
-#define	reg_fste_w8_7_0_len 8
-#define	reg_fste_w8_7_0_lsb 0
-#define xd_p_reg_fste_w8_11_8	0xA357
-#define	reg_fste_w8_11_8_pos 0
-#define	reg_fste_w8_11_8_len 4
-#define	reg_fste_w8_11_8_lsb 8
-#define xd_p_reg_fste_w9_3_0	0xA357
-#define	reg_fste_w9_3_0_pos 4
-#define	reg_fste_w9_3_0_len 4
-#define	reg_fste_w9_3_0_lsb 0
-#define xd_p_reg_fste_w9_11_4	0xA358
-#define	reg_fste_w9_11_4_pos 0
-#define	reg_fste_w9_11_4_len 8
-#define	reg_fste_w9_11_4_lsb 4
-#define xd_p_reg_fste_wa_7_0	0xA359
-#define	reg_fste_wa_7_0_pos 0
-#define	reg_fste_wa_7_0_len 8
-#define	reg_fste_wa_7_0_lsb 0
-#define xd_p_reg_fste_wa_11_8	0xA35A
-#define	reg_fste_wa_11_8_pos 0
-#define	reg_fste_wa_11_8_len 4
-#define	reg_fste_wa_11_8_lsb 8
-#define xd_p_reg_fste_wb_3_0	0xA35A
-#define	reg_fste_wb_3_0_pos 4
-#define	reg_fste_wb_3_0_len 4
-#define	reg_fste_wb_3_0_lsb 0
-#define xd_p_reg_fste_wb_11_4	0xA35B
-#define	reg_fste_wb_11_4_pos 0
-#define	reg_fste_wb_11_4_len 8
-#define	reg_fste_wb_11_4_lsb 4
-#define xd_r_fd_fste_i_adj	0xA35C
-#define	fd_fste_i_adj_pos 0
-#define	fd_fste_i_adj_len 5
-#define	fd_fste_i_adj_lsb 0
-#define xd_r_fd_fste_f_adj_7_0	0xA35D
-#define	fd_fste_f_adj_7_0_pos 0
-#define	fd_fste_f_adj_7_0_len 8
-#define	fd_fste_f_adj_7_0_lsb 0
-#define xd_r_fd_fste_f_adj_15_8	0xA35E
-#define	fd_fste_f_adj_15_8_pos 0
-#define	fd_fste_f_adj_15_8_len 8
-#define	fd_fste_f_adj_15_8_lsb 8
-#define xd_r_fd_fste_f_adj_19_16	0xA35F
-#define	fd_fste_f_adj_19_16_pos 0
-#define	fd_fste_f_adj_19_16_len 4
-#define	fd_fste_f_adj_19_16_lsb 16
-#define xd_p_reg_feq_Leak_Bypass	0xA366
-#define	reg_feq_Leak_Bypass_pos 0
-#define	reg_feq_Leak_Bypass_len 1
-#define	reg_feq_Leak_Bypass_lsb 0
-#define xd_p_reg_feq_Leak_Mneg1	0xA366
-#define	reg_feq_Leak_Mneg1_pos 1
-#define	reg_feq_Leak_Mneg1_len 3
-#define	reg_feq_Leak_Mneg1_lsb 0
-#define xd_p_reg_feq_Leak_B_ShiftQ	0xA366
-#define	reg_feq_Leak_B_ShiftQ_pos 4
-#define	reg_feq_Leak_B_ShiftQ_len 4
-#define	reg_feq_Leak_B_ShiftQ_lsb 0
-#define xd_p_reg_feq_Leak_B_Float0	0xA367
-#define	reg_feq_Leak_B_Float0_pos 0
-#define	reg_feq_Leak_B_Float0_len 8
-#define	reg_feq_Leak_B_Float0_lsb 0
-#define xd_p_reg_feq_Leak_B_Float1	0xA368
-#define	reg_feq_Leak_B_Float1_pos 0
-#define	reg_feq_Leak_B_Float1_len 8
-#define	reg_feq_Leak_B_Float1_lsb 0
-#define xd_p_reg_feq_Leak_B_Float2	0xA369
-#define	reg_feq_Leak_B_Float2_pos 0
-#define	reg_feq_Leak_B_Float2_len 8
-#define	reg_feq_Leak_B_Float2_lsb 0
-#define xd_p_reg_feq_Leak_B_Float3	0xA36A
-#define	reg_feq_Leak_B_Float3_pos 0
-#define	reg_feq_Leak_B_Float3_len 8
-#define	reg_feq_Leak_B_Float3_lsb 0
-#define xd_p_reg_feq_Leak_B_Float4	0xA36B
-#define	reg_feq_Leak_B_Float4_pos 0
-#define	reg_feq_Leak_B_Float4_len 8
-#define	reg_feq_Leak_B_Float4_lsb 0
-#define xd_p_reg_feq_Leak_B_Float5	0xA36C
-#define	reg_feq_Leak_B_Float5_pos 0
-#define	reg_feq_Leak_B_Float5_len 8
-#define	reg_feq_Leak_B_Float5_lsb 0
-#define xd_p_reg_feq_Leak_B_Float6	0xA36D
-#define	reg_feq_Leak_B_Float6_pos 0
-#define	reg_feq_Leak_B_Float6_len 8
-#define	reg_feq_Leak_B_Float6_lsb 0
-#define xd_p_reg_feq_Leak_B_Float7	0xA36E
-#define	reg_feq_Leak_B_Float7_pos 0
-#define	reg_feq_Leak_B_Float7_len 8
-#define	reg_feq_Leak_B_Float7_lsb 0
-#define xd_r_reg_feq_data_h2_7_0	0xA36F
-#define	reg_feq_data_h2_7_0_pos 0
-#define	reg_feq_data_h2_7_0_len 8
-#define	reg_feq_data_h2_7_0_lsb 0
-#define xd_r_reg_feq_data_h2_9_8	0xA370
-#define	reg_feq_data_h2_9_8_pos 0
-#define	reg_feq_data_h2_9_8_len 2
-#define	reg_feq_data_h2_9_8_lsb 8
-#define xd_p_reg_feq_leak_use_slice_tps	0xA371
-#define	reg_feq_leak_use_slice_tps_pos 0
-#define	reg_feq_leak_use_slice_tps_len 1
-#define	reg_feq_leak_use_slice_tps_lsb 0
-#define xd_p_reg_feq_read_update	0xA371
-#define	reg_feq_read_update_pos 1
-#define	reg_feq_read_update_len 1
-#define	reg_feq_read_update_lsb 0
-#define xd_p_reg_feq_data_vld	0xA371
-#define	reg_feq_data_vld_pos 2
-#define	reg_feq_data_vld_len 1
-#define	reg_feq_data_vld_lsb 0
-#define xd_p_reg_feq_tone_idx_4_0	0xA371
-#define	reg_feq_tone_idx_4_0_pos 3
-#define	reg_feq_tone_idx_4_0_len 5
-#define	reg_feq_tone_idx_4_0_lsb 0
-#define xd_p_reg_feq_tone_idx_12_5	0xA372
-#define	reg_feq_tone_idx_12_5_pos 0
-#define	reg_feq_tone_idx_12_5_len 8
-#define	reg_feq_tone_idx_12_5_lsb 5
-#define xd_r_reg_feq_data_re_7_0	0xA373
-#define	reg_feq_data_re_7_0_pos 0
-#define	reg_feq_data_re_7_0_len 8
-#define	reg_feq_data_re_7_0_lsb 0
-#define xd_r_reg_feq_data_re_10_8	0xA374
-#define	reg_feq_data_re_10_8_pos 0
-#define	reg_feq_data_re_10_8_len 3
-#define	reg_feq_data_re_10_8_lsb 8
-#define xd_r_reg_feq_data_im_7_0	0xA375
-#define	reg_feq_data_im_7_0_pos 0
-#define	reg_feq_data_im_7_0_len 8
-#define	reg_feq_data_im_7_0_lsb 0
-#define xd_r_reg_feq_data_im_10_8	0xA376
-#define	reg_feq_data_im_10_8_pos 0
-#define	reg_feq_data_im_10_8_len 3
-#define	reg_feq_data_im_10_8_lsb 8
-#define xd_r_reg_feq_y_re	0xA377
-#define	reg_feq_y_re_pos 0
-#define	reg_feq_y_re_len 8
-#define	reg_feq_y_re_lsb 0
-#define xd_r_reg_feq_y_im	0xA378
-#define	reg_feq_y_im_pos 0
-#define	reg_feq_y_im_len 8
-#define	reg_feq_y_im_lsb 0
-#define xd_r_reg_feq_h_re_7_0	0xA379
-#define	reg_feq_h_re_7_0_pos 0
-#define	reg_feq_h_re_7_0_len 8
-#define	reg_feq_h_re_7_0_lsb 0
-#define xd_r_reg_feq_h_re_8	0xA37A
-#define	reg_feq_h_re_8_pos 0
-#define	reg_feq_h_re_8_len 1
-#define	reg_feq_h_re_8_lsb 0
-#define xd_r_reg_feq_h_im_7_0	0xA37B
-#define	reg_feq_h_im_7_0_pos 0
-#define	reg_feq_h_im_7_0_len 8
-#define	reg_feq_h_im_7_0_lsb 0
-#define xd_r_reg_feq_h_im_8	0xA37C
-#define	reg_feq_h_im_8_pos 0
-#define	reg_feq_h_im_8_len 1
-#define	reg_feq_h_im_8_lsb 0
-#define xd_p_fec_super_frm_unit_7_0	0xA380
-#define	fec_super_frm_unit_7_0_pos 0
-#define	fec_super_frm_unit_7_0_len 8
-#define	fec_super_frm_unit_7_0_lsb 0
-#define xd_p_fec_super_frm_unit_15_8	0xA381
-#define	fec_super_frm_unit_15_8_pos 0
-#define	fec_super_frm_unit_15_8_len 8
-#define	fec_super_frm_unit_15_8_lsb 8
-#define xd_r_fec_vtb_err_bit_cnt_7_0	0xA382
-#define	fec_vtb_err_bit_cnt_7_0_pos 0
-#define	fec_vtb_err_bit_cnt_7_0_len 8
-#define	fec_vtb_err_bit_cnt_7_0_lsb 0
-#define xd_r_fec_vtb_err_bit_cnt_15_8	0xA383
-#define	fec_vtb_err_bit_cnt_15_8_pos 0
-#define	fec_vtb_err_bit_cnt_15_8_len 8
-#define	fec_vtb_err_bit_cnt_15_8_lsb 8
-#define xd_r_fec_vtb_err_bit_cnt_23_16	0xA384
-#define	fec_vtb_err_bit_cnt_23_16_pos 0
-#define	fec_vtb_err_bit_cnt_23_16_len 8
-#define	fec_vtb_err_bit_cnt_23_16_lsb 16
-#define xd_p_fec_rsd_packet_unit_7_0	0xA385
-#define	fec_rsd_packet_unit_7_0_pos 0
-#define	fec_rsd_packet_unit_7_0_len 8
-#define	fec_rsd_packet_unit_7_0_lsb 0
-#define xd_p_fec_rsd_packet_unit_15_8	0xA386
-#define	fec_rsd_packet_unit_15_8_pos 0
-#define	fec_rsd_packet_unit_15_8_len 8
-#define	fec_rsd_packet_unit_15_8_lsb 8
-#define xd_r_fec_rsd_bit_err_cnt_7_0	0xA387
-#define	fec_rsd_bit_err_cnt_7_0_pos 0
-#define	fec_rsd_bit_err_cnt_7_0_len 8
-#define	fec_rsd_bit_err_cnt_7_0_lsb 0
-#define xd_r_fec_rsd_bit_err_cnt_15_8	0xA388
-#define	fec_rsd_bit_err_cnt_15_8_pos 0
-#define	fec_rsd_bit_err_cnt_15_8_len 8
-#define	fec_rsd_bit_err_cnt_15_8_lsb 8
-#define xd_r_fec_rsd_bit_err_cnt_23_16	0xA389
-#define	fec_rsd_bit_err_cnt_23_16_pos 0
-#define	fec_rsd_bit_err_cnt_23_16_len 8
-#define	fec_rsd_bit_err_cnt_23_16_lsb 16
-#define xd_r_fec_rsd_abort_packet_cnt_7_0	0xA38A
-#define	fec_rsd_abort_packet_cnt_7_0_pos 0
-#define	fec_rsd_abort_packet_cnt_7_0_len 8
-#define	fec_rsd_abort_packet_cnt_7_0_lsb 0
-#define xd_r_fec_rsd_abort_packet_cnt_15_8	0xA38B
-#define	fec_rsd_abort_packet_cnt_15_8_pos 0
-#define	fec_rsd_abort_packet_cnt_15_8_len 8
-#define	fec_rsd_abort_packet_cnt_15_8_lsb 8
-#define xd_p_fec_RSD_PKT_NUM_PER_UNIT_7_0	0xA38C
-#define	fec_RSD_PKT_NUM_PER_UNIT_7_0_pos 0
-#define	fec_RSD_PKT_NUM_PER_UNIT_7_0_len 8
-#define	fec_RSD_PKT_NUM_PER_UNIT_7_0_lsb 0
-#define xd_p_fec_RSD_PKT_NUM_PER_UNIT_15_8	0xA38D
-#define	fec_RSD_PKT_NUM_PER_UNIT_15_8_pos 0
-#define	fec_RSD_PKT_NUM_PER_UNIT_15_8_len 8
-#define	fec_RSD_PKT_NUM_PER_UNIT_15_8_lsb 8
-#define xd_p_fec_RS_TH_1_7_0	0xA38E
-#define	fec_RS_TH_1_7_0_pos 0
-#define	fec_RS_TH_1_7_0_len 8
-#define	fec_RS_TH_1_7_0_lsb 0
-#define xd_p_fec_RS_TH_1_15_8	0xA38F
-#define	fec_RS_TH_1_15_8_pos 0
-#define	fec_RS_TH_1_15_8_len 8
-#define	fec_RS_TH_1_15_8_lsb 8
-#define xd_p_fec_RS_TH_2	0xA390
-#define	fec_RS_TH_2_pos 0
-#define	fec_RS_TH_2_len 8
-#define	fec_RS_TH_2_lsb 0
-#define xd_p_fec_mon_en	0xA391
-#define	fec_mon_en_pos 0
-#define	fec_mon_en_len 1
-#define	fec_mon_en_lsb 0
-#define xd_p_reg_b8to47	0xA391
-#define	reg_b8to47_pos 1
-#define	reg_b8to47_len 1
-#define	reg_b8to47_lsb 0
-#define xd_p_reg_rsd_sync_rep	0xA391
-#define	reg_rsd_sync_rep_pos 2
-#define	reg_rsd_sync_rep_len 1
-#define	reg_rsd_sync_rep_lsb 0
-#define xd_p_fec_rsd_retrain_rst	0xA391
-#define	fec_rsd_retrain_rst_pos 3
-#define	fec_rsd_retrain_rst_len 1
-#define	fec_rsd_retrain_rst_lsb 0
-#define xd_r_fec_rsd_ber_rdy	0xA391
-#define	fec_rsd_ber_rdy_pos 4
-#define	fec_rsd_ber_rdy_len 1
-#define	fec_rsd_ber_rdy_lsb 0
-#define xd_p_fec_rsd_ber_rst	0xA391
-#define	fec_rsd_ber_rst_pos 5
-#define	fec_rsd_ber_rst_len 1
-#define	fec_rsd_ber_rst_lsb 0
-#define xd_r_fec_vtb_ber_rdy	0xA391
-#define	fec_vtb_ber_rdy_pos 6
-#define	fec_vtb_ber_rdy_len 1
-#define	fec_vtb_ber_rdy_lsb 0
-#define xd_p_fec_vtb_ber_rst	0xA391
-#define	fec_vtb_ber_rst_pos 7
-#define	fec_vtb_ber_rst_len 1
-#define	fec_vtb_ber_rst_lsb 0
-#define xd_p_reg_vtb_clk40en	0xA392
-#define	reg_vtb_clk40en_pos 0
-#define	reg_vtb_clk40en_len 1
-#define	reg_vtb_clk40en_lsb 0
-#define xd_p_fec_vtb_rsd_mon_en	0xA392
-#define	fec_vtb_rsd_mon_en_pos 1
-#define	fec_vtb_rsd_mon_en_len 1
-#define	fec_vtb_rsd_mon_en_lsb 0
-#define xd_p_reg_fec_data_en	0xA392
-#define	reg_fec_data_en_pos 2
-#define	reg_fec_data_en_len 1
-#define	reg_fec_data_en_lsb 0
-#define xd_p_fec_dummy_reg_2	0xA392
-#define	fec_dummy_reg_2_pos 3
-#define	fec_dummy_reg_2_len 3
-#define	fec_dummy_reg_2_lsb 0
-#define xd_p_reg_sync_chk	0xA392
-#define	reg_sync_chk_pos 6
-#define	reg_sync_chk_len 1
-#define	reg_sync_chk_lsb 0
-#define xd_p_fec_rsd_bypass	0xA392
-#define	fec_rsd_bypass_pos 7
-#define	fec_rsd_bypass_len 1
-#define	fec_rsd_bypass_lsb 0
-#define xd_p_fec_sw_rst	0xA393
-#define	fec_sw_rst_pos 0
-#define	fec_sw_rst_len 1
-#define	fec_sw_rst_lsb 0
-#define xd_r_fec_vtb_pm_crc	0xA394
-#define	fec_vtb_pm_crc_pos 0
-#define	fec_vtb_pm_crc_len 8
-#define	fec_vtb_pm_crc_lsb 0
-#define xd_r_fec_vtb_tb_7_crc	0xA395
-#define	fec_vtb_tb_7_crc_pos 0
-#define	fec_vtb_tb_7_crc_len 8
-#define	fec_vtb_tb_7_crc_lsb 0
-#define xd_r_fec_vtb_tb_6_crc	0xA396
-#define	fec_vtb_tb_6_crc_pos 0
-#define	fec_vtb_tb_6_crc_len 8
-#define	fec_vtb_tb_6_crc_lsb 0
-#define xd_r_fec_vtb_tb_5_crc	0xA397
-#define	fec_vtb_tb_5_crc_pos 0
-#define	fec_vtb_tb_5_crc_len 8
-#define	fec_vtb_tb_5_crc_lsb 0
-#define xd_r_fec_vtb_tb_4_crc	0xA398
-#define	fec_vtb_tb_4_crc_pos 0
-#define	fec_vtb_tb_4_crc_len 8
-#define	fec_vtb_tb_4_crc_lsb 0
-#define xd_r_fec_vtb_tb_3_crc	0xA399
-#define	fec_vtb_tb_3_crc_pos 0
-#define	fec_vtb_tb_3_crc_len 8
-#define	fec_vtb_tb_3_crc_lsb 0
-#define xd_r_fec_vtb_tb_2_crc	0xA39A
-#define	fec_vtb_tb_2_crc_pos 0
-#define	fec_vtb_tb_2_crc_len 8
-#define	fec_vtb_tb_2_crc_lsb 0
-#define xd_r_fec_vtb_tb_1_crc	0xA39B
-#define	fec_vtb_tb_1_crc_pos 0
-#define	fec_vtb_tb_1_crc_len 8
-#define	fec_vtb_tb_1_crc_lsb 0
-#define xd_r_fec_vtb_tb_0_crc	0xA39C
-#define	fec_vtb_tb_0_crc_pos 0
-#define	fec_vtb_tb_0_crc_len 8
-#define	fec_vtb_tb_0_crc_lsb 0
-#define xd_r_fec_rsd_bank0_crc	0xA39D
-#define	fec_rsd_bank0_crc_pos 0
-#define	fec_rsd_bank0_crc_len 8
-#define	fec_rsd_bank0_crc_lsb 0
-#define xd_r_fec_rsd_bank1_crc	0xA39E
-#define	fec_rsd_bank1_crc_pos 0
-#define	fec_rsd_bank1_crc_len 8
-#define	fec_rsd_bank1_crc_lsb 0
-#define xd_r_fec_idi_vtb_crc	0xA39F
-#define	fec_idi_vtb_crc_pos 0
-#define	fec_idi_vtb_crc_len 8
-#define	fec_idi_vtb_crc_lsb 0
-#define xd_g_reg_tpsd_txmod	0xA3C0
-#define	reg_tpsd_txmod_pos 0
-#define	reg_tpsd_txmod_len 2
-#define	reg_tpsd_txmod_lsb 0
-#define xd_g_reg_tpsd_gi	0xA3C0
-#define	reg_tpsd_gi_pos 2
-#define	reg_tpsd_gi_len 2
-#define	reg_tpsd_gi_lsb 0
-#define xd_g_reg_tpsd_hier	0xA3C0
-#define	reg_tpsd_hier_pos 4
-#define	reg_tpsd_hier_len 3
-#define	reg_tpsd_hier_lsb 0
-#define xd_g_reg_bw	0xA3C1
-#define	reg_bw_pos 2
-#define	reg_bw_len 2
-#define	reg_bw_lsb 0
-#define xd_g_reg_dec_pri	0xA3C1
-#define	reg_dec_pri_pos 4
-#define	reg_dec_pri_len 1
-#define	reg_dec_pri_lsb 0
-#define xd_g_reg_tpsd_const	0xA3C1
-#define	reg_tpsd_const_pos 6
-#define	reg_tpsd_const_len 2
-#define	reg_tpsd_const_lsb 0
-#define xd_g_reg_tpsd_hpcr	0xA3C2
-#define	reg_tpsd_hpcr_pos 0
-#define	reg_tpsd_hpcr_len 3
-#define	reg_tpsd_hpcr_lsb 0
-#define xd_g_reg_tpsd_lpcr	0xA3C2
-#define	reg_tpsd_lpcr_pos 3
-#define	reg_tpsd_lpcr_len 3
-#define	reg_tpsd_lpcr_lsb 0
-#define xd_g_reg_ofsm_clk	0xA3D0
-#define	reg_ofsm_clk_pos 0
-#define	reg_ofsm_clk_len 3
-#define	reg_ofsm_clk_lsb 0
-#define xd_g_reg_fclk_cfg	0xA3D1
-#define	reg_fclk_cfg_pos 0
-#define	reg_fclk_cfg_len 1
-#define	reg_fclk_cfg_lsb 0
-#define xd_g_reg_fclk_idi	0xA3D1
-#define	reg_fclk_idi_pos 1
-#define	reg_fclk_idi_len 1
-#define	reg_fclk_idi_lsb 0
-#define xd_g_reg_fclk_odi	0xA3D1
-#define	reg_fclk_odi_pos 2
-#define	reg_fclk_odi_len 1
-#define	reg_fclk_odi_lsb 0
-#define xd_g_reg_fclk_rsd	0xA3D1
-#define	reg_fclk_rsd_pos 3
-#define	reg_fclk_rsd_len 1
-#define	reg_fclk_rsd_lsb 0
-#define xd_g_reg_fclk_vtb	0xA3D1
-#define	reg_fclk_vtb_pos 4
-#define	reg_fclk_vtb_len 1
-#define	reg_fclk_vtb_lsb 0
-#define xd_g_reg_fclk_cste	0xA3D1
-#define	reg_fclk_cste_pos 5
-#define	reg_fclk_cste_len 1
-#define	reg_fclk_cste_lsb 0
-#define xd_g_reg_fclk_mp2if	0xA3D1
-#define	reg_fclk_mp2if_pos 6
-#define	reg_fclk_mp2if_len 1
-#define	reg_fclk_mp2if_lsb 0
-#define xd_I2C_i2c_m_slave_addr	0xA400
-#define	i2c_m_slave_addr_pos 0
-#define	i2c_m_slave_addr_len 8
-#define	i2c_m_slave_addr_lsb 0
-#define xd_I2C_i2c_m_data1	0xA401
-#define	i2c_m_data1_pos 0
-#define	i2c_m_data1_len 8
-#define	i2c_m_data1_lsb 0
-#define xd_I2C_i2c_m_data2	0xA402
-#define	i2c_m_data2_pos 0
-#define	i2c_m_data2_len 8
-#define	i2c_m_data2_lsb 0
-#define xd_I2C_i2c_m_data3	0xA403
-#define	i2c_m_data3_pos 0
-#define	i2c_m_data3_len 8
-#define	i2c_m_data3_lsb 0
-#define xd_I2C_i2c_m_data4	0xA404
-#define	i2c_m_data4_pos 0
-#define	i2c_m_data4_len 8
-#define	i2c_m_data4_lsb 0
-#define xd_I2C_i2c_m_data5	0xA405
-#define	i2c_m_data5_pos 0
-#define	i2c_m_data5_len 8
-#define	i2c_m_data5_lsb 0
-#define xd_I2C_i2c_m_data6	0xA406
-#define	i2c_m_data6_pos 0
-#define	i2c_m_data6_len 8
-#define	i2c_m_data6_lsb 0
-#define xd_I2C_i2c_m_data7	0xA407
-#define	i2c_m_data7_pos 0
-#define	i2c_m_data7_len 8
-#define	i2c_m_data7_lsb 0
-#define xd_I2C_i2c_m_data8	0xA408
-#define	i2c_m_data8_pos 0
-#define	i2c_m_data8_len 8
-#define	i2c_m_data8_lsb 0
-#define xd_I2C_i2c_m_data9	0xA409
-#define	i2c_m_data9_pos 0
-#define	i2c_m_data9_len 8
-#define	i2c_m_data9_lsb 0
-#define xd_I2C_i2c_m_data10	0xA40A
-#define	i2c_m_data10_pos 0
-#define	i2c_m_data10_len 8
-#define	i2c_m_data10_lsb 0
-#define xd_I2C_i2c_m_data11	0xA40B
-#define	i2c_m_data11_pos 0
-#define	i2c_m_data11_len 8
-#define	i2c_m_data11_lsb 0
-#define xd_I2C_i2c_m_cmd_rw	0xA40C
-#define	i2c_m_cmd_rw_pos 0
-#define	i2c_m_cmd_rw_len 1
-#define	i2c_m_cmd_rw_lsb 0
-#define xd_I2C_i2c_m_cmd_rwlen	0xA40C
-#define	i2c_m_cmd_rwlen_pos 3
-#define	i2c_m_cmd_rwlen_len 4
-#define	i2c_m_cmd_rwlen_lsb 0
-#define xd_I2C_i2c_m_status_cmd_exe	0xA40D
-#define	i2c_m_status_cmd_exe_pos 0
-#define	i2c_m_status_cmd_exe_len 1
-#define	i2c_m_status_cmd_exe_lsb 0
-#define xd_I2C_i2c_m_status_wdat_done	0xA40D
-#define	i2c_m_status_wdat_done_pos 1
-#define	i2c_m_status_wdat_done_len 1
-#define	i2c_m_status_wdat_done_lsb 0
-#define xd_I2C_i2c_m_status_wdat_fail	0xA40D
-#define	i2c_m_status_wdat_fail_pos 2
-#define	i2c_m_status_wdat_fail_len 1
-#define	i2c_m_status_wdat_fail_lsb 0
-#define xd_I2C_i2c_m_period	0xA40E
-#define	i2c_m_period_pos 0
-#define	i2c_m_period_len 8
-#define	i2c_m_period_lsb 0
-#define xd_I2C_i2c_m_reg_msb_lsb	0xA40F
-#define	i2c_m_reg_msb_lsb_pos 0
-#define	i2c_m_reg_msb_lsb_len 1
-#define	i2c_m_reg_msb_lsb_lsb 0
-#define xd_I2C_reg_ofdm_rst	0xA40F
-#define	reg_ofdm_rst_pos 1
-#define	reg_ofdm_rst_len 1
-#define	reg_ofdm_rst_lsb 0
-#define xd_I2C_reg_sample_period_on_tuner	0xA40F
-#define	reg_sample_period_on_tuner_pos 2
-#define	reg_sample_period_on_tuner_len 1
-#define	reg_sample_period_on_tuner_lsb 0
-#define xd_I2C_reg_rst_i2c	0xA40F
-#define	reg_rst_i2c_pos 3
-#define	reg_rst_i2c_len 1
-#define	reg_rst_i2c_lsb 0
-#define xd_I2C_reg_ofdm_rst_en	0xA40F
-#define	reg_ofdm_rst_en_pos 4
-#define	reg_ofdm_rst_en_len 1
-#define	reg_ofdm_rst_en_lsb 0
-#define xd_I2C_reg_tuner_sda_sync_on	0xA40F
-#define	reg_tuner_sda_sync_on_pos 5
-#define	reg_tuner_sda_sync_on_len 1
-#define	reg_tuner_sda_sync_on_lsb 0
-#define xd_p_mp2if_data_access_disable_ofsm	0xA500
-#define	mp2if_data_access_disable_ofsm_pos 0
-#define	mp2if_data_access_disable_ofsm_len 1
-#define	mp2if_data_access_disable_ofsm_lsb 0
-#define xd_p_reg_mp2_sw_rst_ofsm	0xA500
-#define	reg_mp2_sw_rst_ofsm_pos 1
-#define	reg_mp2_sw_rst_ofsm_len 1
-#define	reg_mp2_sw_rst_ofsm_lsb 0
-#define xd_p_reg_mp2if_clk_en_ofsm	0xA500
-#define	reg_mp2if_clk_en_ofsm_pos 2
-#define	reg_mp2if_clk_en_ofsm_len 1
-#define	reg_mp2if_clk_en_ofsm_lsb 0
-#define xd_r_mp2if_sync_byte_locked	0xA500
-#define	mp2if_sync_byte_locked_pos 3
-#define	mp2if_sync_byte_locked_len 1
-#define	mp2if_sync_byte_locked_lsb 0
-#define xd_r_mp2if_ts_not_188	0xA500
-#define	mp2if_ts_not_188_pos 4
-#define	mp2if_ts_not_188_len 1
-#define	mp2if_ts_not_188_lsb 0
-#define xd_r_mp2if_psb_empty	0xA500
-#define	mp2if_psb_empty_pos 5
-#define	mp2if_psb_empty_len 1
-#define	mp2if_psb_empty_lsb 0
-#define xd_r_mp2if_psb_overflow	0xA500
-#define	mp2if_psb_overflow_pos 6
-#define	mp2if_psb_overflow_len 1
-#define	mp2if_psb_overflow_lsb 0
-#define xd_p_mp2if_keep_sf_sync_byte_ofsm	0xA500
-#define	mp2if_keep_sf_sync_byte_ofsm_pos 7
-#define	mp2if_keep_sf_sync_byte_ofsm_len 1
-#define	mp2if_keep_sf_sync_byte_ofsm_lsb 0
-#define xd_r_mp2if_psb_mp2if_num_pkt	0xA501
-#define	mp2if_psb_mp2if_num_pkt_pos 0
-#define	mp2if_psb_mp2if_num_pkt_len 6
-#define	mp2if_psb_mp2if_num_pkt_lsb 0
-#define xd_p_reg_mpeg_full_speed_ofsm	0xA501
-#define	reg_mpeg_full_speed_ofsm_pos 6
-#define	reg_mpeg_full_speed_ofsm_len 1
-#define	reg_mpeg_full_speed_ofsm_lsb 0
-#define xd_p_mp2if_mpeg_ser_mode_ofsm	0xA501
-#define	mp2if_mpeg_ser_mode_ofsm_pos 7
-#define	mp2if_mpeg_ser_mode_ofsm_len 1
-#define	mp2if_mpeg_ser_mode_ofsm_lsb 0
-#define xd_p_reg_sw_mon51	0xA600
-#define	reg_sw_mon51_pos 0
-#define	reg_sw_mon51_len 8
-#define	reg_sw_mon51_lsb 0
-#define xd_p_reg_top_pcsel	0xA601
-#define	reg_top_pcsel_pos 0
-#define	reg_top_pcsel_len 1
-#define	reg_top_pcsel_lsb 0
-#define xd_p_reg_top_rs232	0xA601
-#define	reg_top_rs232_pos 1
-#define	reg_top_rs232_len 1
-#define	reg_top_rs232_lsb 0
-#define xd_p_reg_top_pcout	0xA601
-#define	reg_top_pcout_pos 2
-#define	reg_top_pcout_len 1
-#define	reg_top_pcout_lsb 0
-#define xd_p_reg_top_debug	0xA601
-#define	reg_top_debug_pos 3
-#define	reg_top_debug_len 1
-#define	reg_top_debug_lsb 0
-#define xd_p_reg_top_adcdly	0xA601
-#define	reg_top_adcdly_pos 4
-#define	reg_top_adcdly_len 2
-#define	reg_top_adcdly_lsb 0
-#define xd_p_reg_top_pwrdw	0xA601
-#define	reg_top_pwrdw_pos 6
-#define	reg_top_pwrdw_len 1
-#define	reg_top_pwrdw_lsb 0
-#define xd_p_reg_top_pwrdw_inv	0xA601
-#define	reg_top_pwrdw_inv_pos 7
-#define	reg_top_pwrdw_inv_len 1
-#define	reg_top_pwrdw_inv_lsb 0
-#define xd_p_reg_top_int_inv	0xA602
-#define	reg_top_int_inv_pos 0
-#define	reg_top_int_inv_len 1
-#define	reg_top_int_inv_lsb 0
-#define xd_p_reg_top_dio_sel	0xA602
-#define	reg_top_dio_sel_pos 1
-#define	reg_top_dio_sel_len 1
-#define	reg_top_dio_sel_lsb 0
-#define xd_p_reg_top_gpioon0	0xA603
-#define	reg_top_gpioon0_pos 0
-#define	reg_top_gpioon0_len 1
-#define	reg_top_gpioon0_lsb 0
-#define xd_p_reg_top_gpioon1	0xA603
-#define	reg_top_gpioon1_pos 1
-#define	reg_top_gpioon1_len 1
-#define	reg_top_gpioon1_lsb 0
-#define xd_p_reg_top_gpioon2	0xA603
-#define	reg_top_gpioon2_pos 2
-#define	reg_top_gpioon2_len 1
-#define	reg_top_gpioon2_lsb 0
-#define xd_p_reg_top_gpioon3	0xA603
-#define	reg_top_gpioon3_pos 3
-#define	reg_top_gpioon3_len 1
-#define	reg_top_gpioon3_lsb 0
-#define xd_p_reg_top_lockon1	0xA603
-#define	reg_top_lockon1_pos 4
-#define	reg_top_lockon1_len 1
-#define	reg_top_lockon1_lsb 0
-#define xd_p_reg_top_lockon2	0xA603
-#define	reg_top_lockon2_pos 5
-#define	reg_top_lockon2_len 1
-#define	reg_top_lockon2_lsb 0
-#define xd_p_reg_top_gpioo0	0xA604
-#define	reg_top_gpioo0_pos 0
-#define	reg_top_gpioo0_len 1
-#define	reg_top_gpioo0_lsb 0
-#define xd_p_reg_top_gpioo1	0xA604
-#define	reg_top_gpioo1_pos 1
-#define	reg_top_gpioo1_len 1
-#define	reg_top_gpioo1_lsb 0
-#define xd_p_reg_top_gpioo2	0xA604
-#define	reg_top_gpioo2_pos 2
-#define	reg_top_gpioo2_len 1
-#define	reg_top_gpioo2_lsb 0
-#define xd_p_reg_top_gpioo3	0xA604
-#define	reg_top_gpioo3_pos 3
-#define	reg_top_gpioo3_len 1
-#define	reg_top_gpioo3_lsb 0
-#define xd_p_reg_top_lock1	0xA604
-#define	reg_top_lock1_pos 4
-#define	reg_top_lock1_len 1
-#define	reg_top_lock1_lsb 0
-#define xd_p_reg_top_lock2	0xA604
-#define	reg_top_lock2_pos 5
-#define	reg_top_lock2_len 1
-#define	reg_top_lock2_lsb 0
-#define xd_p_reg_top_gpioen0	0xA605
-#define	reg_top_gpioen0_pos 0
-#define	reg_top_gpioen0_len 1
-#define	reg_top_gpioen0_lsb 0
-#define xd_p_reg_top_gpioen1	0xA605
-#define	reg_top_gpioen1_pos 1
-#define	reg_top_gpioen1_len 1
-#define	reg_top_gpioen1_lsb 0
-#define xd_p_reg_top_gpioen2	0xA605
-#define	reg_top_gpioen2_pos 2
-#define	reg_top_gpioen2_len 1
-#define	reg_top_gpioen2_lsb 0
-#define xd_p_reg_top_gpioen3	0xA605
-#define	reg_top_gpioen3_pos 3
-#define	reg_top_gpioen3_len 1
-#define	reg_top_gpioen3_lsb 0
-#define xd_p_reg_top_locken1	0xA605
-#define	reg_top_locken1_pos 4
-#define	reg_top_locken1_len 1
-#define	reg_top_locken1_lsb 0
-#define xd_p_reg_top_locken2	0xA605
-#define	reg_top_locken2_pos 5
-#define	reg_top_locken2_len 1
-#define	reg_top_locken2_lsb 0
-#define xd_r_reg_top_gpioi0	0xA606
-#define	reg_top_gpioi0_pos 0
-#define	reg_top_gpioi0_len 1
-#define	reg_top_gpioi0_lsb 0
-#define xd_r_reg_top_gpioi1	0xA606
-#define	reg_top_gpioi1_pos 1
-#define	reg_top_gpioi1_len 1
-#define	reg_top_gpioi1_lsb 0
-#define xd_r_reg_top_gpioi2	0xA606
-#define	reg_top_gpioi2_pos 2
-#define	reg_top_gpioi2_len 1
-#define	reg_top_gpioi2_lsb 0
-#define xd_r_reg_top_gpioi3	0xA606
-#define	reg_top_gpioi3_pos 3
-#define	reg_top_gpioi3_len 1
-#define	reg_top_gpioi3_lsb 0
-#define xd_r_reg_top_locki1	0xA606
-#define	reg_top_locki1_pos 4
-#define	reg_top_locki1_len 1
-#define	reg_top_locki1_lsb 0
-#define xd_r_reg_top_locki2	0xA606
-#define	reg_top_locki2_pos 5
-#define	reg_top_locki2_len 1
-#define	reg_top_locki2_lsb 0
-#define xd_p_reg_dummy_7_0	0xA608
-#define	reg_dummy_7_0_pos 0
-#define	reg_dummy_7_0_len 8
-#define	reg_dummy_7_0_lsb 0
-#define xd_p_reg_dummy_15_8	0xA609
-#define	reg_dummy_15_8_pos 0
-#define	reg_dummy_15_8_len 8
-#define	reg_dummy_15_8_lsb 8
-#define xd_p_reg_dummy_23_16	0xA60A
-#define	reg_dummy_23_16_pos 0
-#define	reg_dummy_23_16_len 8
-#define	reg_dummy_23_16_lsb 16
-#define xd_p_reg_dummy_31_24	0xA60B
-#define	reg_dummy_31_24_pos 0
-#define	reg_dummy_31_24_len 8
-#define	reg_dummy_31_24_lsb 24
-#define xd_p_reg_dummy_39_32	0xA60C
-#define	reg_dummy_39_32_pos 0
-#define	reg_dummy_39_32_len 8
-#define	reg_dummy_39_32_lsb 32
-#define xd_p_reg_dummy_47_40	0xA60D
-#define	reg_dummy_47_40_pos 0
-#define	reg_dummy_47_40_len 8
-#define	reg_dummy_47_40_lsb 40
-#define xd_p_reg_dummy_55_48	0xA60E
-#define	reg_dummy_55_48_pos 0
-#define	reg_dummy_55_48_len 8
-#define	reg_dummy_55_48_lsb 48
-#define xd_p_reg_dummy_63_56	0xA60F
-#define	reg_dummy_63_56_pos 0
-#define	reg_dummy_63_56_len 8
-#define	reg_dummy_63_56_lsb 56
-#define xd_p_reg_dummy_71_64	0xA610
-#define	reg_dummy_71_64_pos 0
-#define	reg_dummy_71_64_len 8
-#define	reg_dummy_71_64_lsb 64
-#define xd_p_reg_dummy_79_72	0xA611
-#define	reg_dummy_79_72_pos 0
-#define	reg_dummy_79_72_len 8
-#define	reg_dummy_79_72_lsb 72
-#define xd_p_reg_dummy_87_80	0xA612
-#define	reg_dummy_87_80_pos 0
-#define	reg_dummy_87_80_len 8
-#define	reg_dummy_87_80_lsb 80
-#define xd_p_reg_dummy_95_88	0xA613
-#define	reg_dummy_95_88_pos 0
-#define	reg_dummy_95_88_len 8
-#define	reg_dummy_95_88_lsb 88
-#define xd_p_reg_dummy_103_96	0xA614
-#define	reg_dummy_103_96_pos 0
-#define	reg_dummy_103_96_len 8
-#define	reg_dummy_103_96_lsb 96
-
-#define xd_p_reg_unplug_flag	0xA615
-#define	reg_unplug_flag_pos 0
-#define	reg_unplug_flag_len 1
-#define	reg_unplug_flag_lsb 104
-
-#define xd_p_reg_api_dca_stes_request   0xA615
-#define reg_api_dca_stes_request_pos 1
-#define reg_api_dca_stes_request_len 1
-#define reg_api_dca_stes_request_lsb 0
-
-#define xd_p_reg_back_to_dca_flag	0xA615
-#define	reg_back_to_dca_flag_pos 2
-#define	reg_back_to_dca_flag_len 1
-#define	reg_back_to_dca_flag_lsb 106
-
-#define xd_p_reg_api_retrain_request    0xA615
-#define reg_api_retrain_request_pos 3
-#define reg_api_retrain_request_len 1
-#define reg_api_retrain_request_lsb 0
-
-#define xd_p_reg_Dyn_Top_Try_flag	0xA615
-#define	reg_Dyn_Top_Try_flag_pos 3
-#define	reg_Dyn_Top_Try_flag_len 1
-#define	reg_Dyn_Top_Try_flag_lsb 107
-
-#define xd_p_reg_API_retrain_freeze_flag	0xA615
-#define	reg_API_retrain_freeze_flag_pos 4
-#define	reg_API_retrain_freeze_flag_len 1
-#define	reg_API_retrain_freeze_flag_lsb 108
-
-#define xd_p_reg_dummy_111_104	0xA615
-#define	reg_dummy_111_104_pos 0
-#define	reg_dummy_111_104_len 8
-#define	reg_dummy_111_104_lsb 104
-#define xd_p_reg_dummy_119_112	0xA616
-#define	reg_dummy_119_112_pos 0
-#define	reg_dummy_119_112_len 8
-#define	reg_dummy_119_112_lsb 112
-#define xd_p_reg_dummy_127_120	0xA617
-#define	reg_dummy_127_120_pos 0
-#define	reg_dummy_127_120_len 8
-#define	reg_dummy_127_120_lsb 120
-#define xd_p_reg_dummy_135_128	0xA618
-#define	reg_dummy_135_128_pos 0
-#define	reg_dummy_135_128_len 8
-#define	reg_dummy_135_128_lsb 128
-
-#define xd_p_reg_dummy_143_136	0xA619
-#define	reg_dummy_143_136_pos 0
-#define	reg_dummy_143_136_len 8
-#define	reg_dummy_143_136_lsb 136
-
-#define xd_p_reg_CCIR_dis	0xA619
-#define	reg_CCIR_dis_pos 0
-#define	reg_CCIR_dis_len 1
-#define	reg_CCIR_dis_lsb 0
-
-#define xd_p_reg_dummy_151_144	0xA61A
-#define	reg_dummy_151_144_pos 0
-#define	reg_dummy_151_144_len 8
-#define	reg_dummy_151_144_lsb 144
-
-#define xd_p_reg_dummy_159_152	0xA61B
-#define	reg_dummy_159_152_pos 0
-#define	reg_dummy_159_152_len 8
-#define	reg_dummy_159_152_lsb 152
-
-#define xd_p_reg_dummy_167_160	0xA61C
-#define	reg_dummy_167_160_pos 0
-#define	reg_dummy_167_160_len 8
-#define	reg_dummy_167_160_lsb 160
-
-#define xd_p_reg_dummy_175_168	0xA61D
-#define	reg_dummy_175_168_pos 0
-#define	reg_dummy_175_168_len 8
-#define	reg_dummy_175_168_lsb 168
-
-#define xd_p_reg_dummy_183_176	0xA61E
-#define	reg_dummy_183_176_pos 0
-#define	reg_dummy_183_176_len 8
-#define	reg_dummy_183_176_lsb 176
-
-#define xd_p_reg_ofsm_read_rbc_en  0xA61E
-#define reg_ofsm_read_rbc_en_pos 2
-#define reg_ofsm_read_rbc_en_len 1
-#define reg_ofsm_read_rbc_en_lsb 0
-
-#define xd_p_reg_ce_filter_selection_dis  0xA61E
-#define reg_ce_filter_selection_dis_pos 1
-#define reg_ce_filter_selection_dis_len 1
-#define reg_ce_filter_selection_dis_lsb 0
-
-#define xd_p_reg_OFSM_version_control_7_0  0xA611
-#define reg_OFSM_version_control_7_0_pos 0
-#define reg_OFSM_version_control_7_0_len 8
-#define reg_OFSM_version_control_7_0_lsb 0
-
-#define xd_p_reg_OFSM_version_control_15_8  0xA61F
-#define reg_OFSM_version_control_15_8_pos 0
-#define reg_OFSM_version_control_15_8_len 8
-#define reg_OFSM_version_control_15_8_lsb 0
-
-#define xd_p_reg_OFSM_version_control_23_16  0xA620
-#define reg_OFSM_version_control_23_16_pos 0
-#define reg_OFSM_version_control_23_16_len 8
-#define reg_OFSM_version_control_23_16_lsb 0
-
-#define xd_p_reg_dummy_191_184	0xA61F
-#define	reg_dummy_191_184_pos 0
-#define	reg_dummy_191_184_len 8
-#define	reg_dummy_191_184_lsb 184
-
-#define xd_p_reg_dummy_199_192	0xA620
-#define	reg_dummy_199_192_pos 0
-#define	reg_dummy_199_192_len 8
-#define	reg_dummy_199_192_lsb 192
-
-#define xd_p_reg_ce_en	0xABC0
-#define	reg_ce_en_pos 0
-#define	reg_ce_en_len 1
-#define	reg_ce_en_lsb 0
-#define xd_p_reg_ce_fctrl_en	0xABC0
-#define	reg_ce_fctrl_en_pos 1
-#define	reg_ce_fctrl_en_len 1
-#define	reg_ce_fctrl_en_lsb 0
-#define xd_p_reg_ce_fste_tdi	0xABC0
-#define	reg_ce_fste_tdi_pos 2
-#define	reg_ce_fste_tdi_len 1
-#define	reg_ce_fste_tdi_lsb 0
-#define xd_p_reg_ce_dynamic	0xABC0
-#define	reg_ce_dynamic_pos 3
-#define	reg_ce_dynamic_len 1
-#define	reg_ce_dynamic_lsb 0
-#define xd_p_reg_ce_conf	0xABC0
-#define	reg_ce_conf_pos 4
-#define	reg_ce_conf_len 2
-#define	reg_ce_conf_lsb 0
-#define xd_p_reg_ce_dyn12	0xABC0
-#define	reg_ce_dyn12_pos 6
-#define	reg_ce_dyn12_len 1
-#define	reg_ce_dyn12_lsb 0
-#define xd_p_reg_ce_derot_en	0xABC0
-#define	reg_ce_derot_en_pos 7
-#define	reg_ce_derot_en_len 1
-#define	reg_ce_derot_en_lsb 0
-#define xd_p_reg_ce_dynamic_th_7_0	0xABC1
-#define	reg_ce_dynamic_th_7_0_pos 0
-#define	reg_ce_dynamic_th_7_0_len 8
-#define	reg_ce_dynamic_th_7_0_lsb 0
-#define xd_p_reg_ce_dynamic_th_15_8	0xABC2
-#define	reg_ce_dynamic_th_15_8_pos 0
-#define	reg_ce_dynamic_th_15_8_len 8
-#define	reg_ce_dynamic_th_15_8_lsb 8
-#define xd_p_reg_ce_s1	0xABC3
-#define	reg_ce_s1_pos 0
-#define	reg_ce_s1_len 5
-#define	reg_ce_s1_lsb 0
-#define xd_p_reg_ce_var_forced_value	0xABC3
-#define	reg_ce_var_forced_value_pos 5
-#define	reg_ce_var_forced_value_len 3
-#define	reg_ce_var_forced_value_lsb 0
-#define xd_p_reg_ce_data_im_7_0	0xABC4
-#define	reg_ce_data_im_7_0_pos 0
-#define	reg_ce_data_im_7_0_len 8
-#define	reg_ce_data_im_7_0_lsb 0
-#define xd_p_reg_ce_data_im_8	0xABC5
-#define	reg_ce_data_im_8_pos 0
-#define	reg_ce_data_im_8_len 1
-#define	reg_ce_data_im_8_lsb 0
-#define xd_p_reg_ce_data_re_6_0	0xABC5
-#define	reg_ce_data_re_6_0_pos 1
-#define	reg_ce_data_re_6_0_len 7
-#define	reg_ce_data_re_6_0_lsb 0
-#define xd_p_reg_ce_data_re_8_7	0xABC6
-#define	reg_ce_data_re_8_7_pos 0
-#define	reg_ce_data_re_8_7_len 2
-#define	reg_ce_data_re_8_7_lsb 7
-#define xd_p_reg_ce_tone_5_0	0xABC6
-#define	reg_ce_tone_5_0_pos 2
-#define	reg_ce_tone_5_0_len 6
-#define	reg_ce_tone_5_0_lsb 0
-#define xd_p_reg_ce_tone_12_6	0xABC7
-#define	reg_ce_tone_12_6_pos 0
-#define	reg_ce_tone_12_6_len 7
-#define	reg_ce_tone_12_6_lsb 6
-#define xd_p_reg_ce_centroid_drift_th	0xABC8
-#define	reg_ce_centroid_drift_th_pos 0
-#define	reg_ce_centroid_drift_th_len 8
-#define	reg_ce_centroid_drift_th_lsb 0
-#define xd_p_reg_ce_centroid_count_max	0xABC9
-#define	reg_ce_centroid_count_max_pos 0
-#define	reg_ce_centroid_count_max_len 4
-#define	reg_ce_centroid_count_max_lsb 0
-#define xd_p_reg_ce_centroid_bias_inc_7_0	0xABCA
-#define	reg_ce_centroid_bias_inc_7_0_pos 0
-#define	reg_ce_centroid_bias_inc_7_0_len 8
-#define	reg_ce_centroid_bias_inc_7_0_lsb 0
-#define xd_p_reg_ce_centroid_bias_inc_8	0xABCB
-#define	reg_ce_centroid_bias_inc_8_pos 0
-#define	reg_ce_centroid_bias_inc_8_len 1
-#define	reg_ce_centroid_bias_inc_8_lsb 0
-#define xd_p_reg_ce_var_th0_7_0	0xABCC
-#define	reg_ce_var_th0_7_0_pos 0
-#define	reg_ce_var_th0_7_0_len 8
-#define	reg_ce_var_th0_7_0_lsb 0
-#define xd_p_reg_ce_var_th0_15_8	0xABCD
-#define	reg_ce_var_th0_15_8_pos 0
-#define	reg_ce_var_th0_15_8_len 8
-#define	reg_ce_var_th0_15_8_lsb 8
-#define xd_p_reg_ce_var_th1_7_0	0xABCE
-#define	reg_ce_var_th1_7_0_pos 0
-#define	reg_ce_var_th1_7_0_len 8
-#define	reg_ce_var_th1_7_0_lsb 0
-#define xd_p_reg_ce_var_th1_15_8	0xABCF
-#define	reg_ce_var_th1_15_8_pos 0
-#define	reg_ce_var_th1_15_8_len 8
-#define	reg_ce_var_th1_15_8_lsb 8
-#define xd_p_reg_ce_var_th2_7_0	0xABD0
-#define	reg_ce_var_th2_7_0_pos 0
-#define	reg_ce_var_th2_7_0_len 8
-#define	reg_ce_var_th2_7_0_lsb 0
-#define xd_p_reg_ce_var_th2_15_8	0xABD1
-#define	reg_ce_var_th2_15_8_pos 0
-#define	reg_ce_var_th2_15_8_len 8
-#define	reg_ce_var_th2_15_8_lsb 8
-#define xd_p_reg_ce_var_th3_7_0	0xABD2
-#define	reg_ce_var_th3_7_0_pos 0
-#define	reg_ce_var_th3_7_0_len 8
-#define	reg_ce_var_th3_7_0_lsb 0
-#define xd_p_reg_ce_var_th3_15_8	0xABD3
-#define	reg_ce_var_th3_15_8_pos 0
-#define	reg_ce_var_th3_15_8_len 8
-#define	reg_ce_var_th3_15_8_lsb 8
-#define xd_p_reg_ce_var_th4_7_0	0xABD4
-#define	reg_ce_var_th4_7_0_pos 0
-#define	reg_ce_var_th4_7_0_len 8
-#define	reg_ce_var_th4_7_0_lsb 0
-#define xd_p_reg_ce_var_th4_15_8	0xABD5
-#define	reg_ce_var_th4_15_8_pos 0
-#define	reg_ce_var_th4_15_8_len 8
-#define	reg_ce_var_th4_15_8_lsb 8
-#define xd_p_reg_ce_var_th5_7_0	0xABD6
-#define	reg_ce_var_th5_7_0_pos 0
-#define	reg_ce_var_th5_7_0_len 8
-#define	reg_ce_var_th5_7_0_lsb 0
-#define xd_p_reg_ce_var_th5_15_8	0xABD7
-#define	reg_ce_var_th5_15_8_pos 0
-#define	reg_ce_var_th5_15_8_len 8
-#define	reg_ce_var_th5_15_8_lsb 8
-#define xd_p_reg_ce_var_th6_7_0	0xABD8
-#define	reg_ce_var_th6_7_0_pos 0
-#define	reg_ce_var_th6_7_0_len 8
-#define	reg_ce_var_th6_7_0_lsb 0
-#define xd_p_reg_ce_var_th6_15_8	0xABD9
-#define	reg_ce_var_th6_15_8_pos 0
-#define	reg_ce_var_th6_15_8_len 8
-#define	reg_ce_var_th6_15_8_lsb 8
-#define xd_p_reg_ce_fctrl_reset	0xABDA
-#define	reg_ce_fctrl_reset_pos 0
-#define	reg_ce_fctrl_reset_len 1
-#define	reg_ce_fctrl_reset_lsb 0
-#define xd_p_reg_ce_cent_auto_clr_en	0xABDA
-#define	reg_ce_cent_auto_clr_en_pos 1
-#define	reg_ce_cent_auto_clr_en_len 1
-#define	reg_ce_cent_auto_clr_en_lsb 0
-#define xd_p_reg_ce_fctrl_auto_reset_en	0xABDA
-#define	reg_ce_fctrl_auto_reset_en_pos 2
-#define	reg_ce_fctrl_auto_reset_en_len 1
-#define	reg_ce_fctrl_auto_reset_en_lsb 0
-#define xd_p_reg_ce_var_forced_en	0xABDA
-#define	reg_ce_var_forced_en_pos 3
-#define	reg_ce_var_forced_en_len 1
-#define	reg_ce_var_forced_en_lsb 0
-#define xd_p_reg_ce_cent_forced_en	0xABDA
-#define	reg_ce_cent_forced_en_pos 4
-#define	reg_ce_cent_forced_en_len 1
-#define	reg_ce_cent_forced_en_lsb 0
-#define xd_p_reg_ce_var_max	0xABDA
-#define	reg_ce_var_max_pos 5
-#define	reg_ce_var_max_len 3
-#define	reg_ce_var_max_lsb 0
-#define xd_p_reg_ce_cent_forced_value_7_0	0xABDB
-#define	reg_ce_cent_forced_value_7_0_pos 0
-#define	reg_ce_cent_forced_value_7_0_len 8
-#define	reg_ce_cent_forced_value_7_0_lsb 0
-#define xd_p_reg_ce_cent_forced_value_11_8	0xABDC
-#define	reg_ce_cent_forced_value_11_8_pos 0
-#define	reg_ce_cent_forced_value_11_8_len 4
-#define	reg_ce_cent_forced_value_11_8_lsb 8
-#define xd_p_reg_ce_fctrl_rd	0xABDD
-#define	reg_ce_fctrl_rd_pos 0
-#define	reg_ce_fctrl_rd_len 1
-#define	reg_ce_fctrl_rd_lsb 0
-#define xd_p_reg_ce_centroid_max_6_0	0xABDD
-#define	reg_ce_centroid_max_6_0_pos 1
-#define	reg_ce_centroid_max_6_0_len 7
-#define	reg_ce_centroid_max_6_0_lsb 0
-#define xd_p_reg_ce_centroid_max_11_7	0xABDE
-#define	reg_ce_centroid_max_11_7_pos 0
-#define	reg_ce_centroid_max_11_7_len 5
-#define	reg_ce_centroid_max_11_7_lsb 7
-#define xd_p_reg_ce_var	0xABDF
-#define	reg_ce_var_pos 0
-#define	reg_ce_var_len 3
-#define	reg_ce_var_lsb 0
-#define xd_p_reg_ce_fctrl_rdy	0xABDF
-#define	reg_ce_fctrl_rdy_pos 3
-#define	reg_ce_fctrl_rdy_len 1
-#define	reg_ce_fctrl_rdy_lsb 0
-#define xd_p_reg_ce_centroid_out_3_0	0xABDF
-#define	reg_ce_centroid_out_3_0_pos 4
-#define	reg_ce_centroid_out_3_0_len 4
-#define	reg_ce_centroid_out_3_0_lsb 0
-#define xd_p_reg_ce_centroid_out_11_4	0xABE0
-#define	reg_ce_centroid_out_11_4_pos 0
-#define	reg_ce_centroid_out_11_4_len 8
-#define	reg_ce_centroid_out_11_4_lsb 4
-#define xd_p_reg_ce_bias_7_0	0xABE1
-#define	reg_ce_bias_7_0_pos 0
-#define	reg_ce_bias_7_0_len 8
-#define	reg_ce_bias_7_0_lsb 0
-#define xd_p_reg_ce_bias_11_8	0xABE2
-#define	reg_ce_bias_11_8_pos 0
-#define	reg_ce_bias_11_8_len 4
-#define	reg_ce_bias_11_8_lsb 8
-#define xd_p_reg_ce_m1_3_0	0xABE2
-#define	reg_ce_m1_3_0_pos 4
-#define	reg_ce_m1_3_0_len 4
-#define	reg_ce_m1_3_0_lsb 0
-#define xd_p_reg_ce_m1_11_4	0xABE3
-#define	reg_ce_m1_11_4_pos 0
-#define	reg_ce_m1_11_4_len 8
-#define	reg_ce_m1_11_4_lsb 4
-#define xd_p_reg_ce_rh0_7_0	0xABE4
-#define	reg_ce_rh0_7_0_pos 0
-#define	reg_ce_rh0_7_0_len 8
-#define	reg_ce_rh0_7_0_lsb 0
-#define xd_p_reg_ce_rh0_15_8	0xABE5
-#define	reg_ce_rh0_15_8_pos 0
-#define	reg_ce_rh0_15_8_len 8
-#define	reg_ce_rh0_15_8_lsb 8
-#define xd_p_reg_ce_rh0_23_16	0xABE6
-#define	reg_ce_rh0_23_16_pos 0
-#define	reg_ce_rh0_23_16_len 8
-#define	reg_ce_rh0_23_16_lsb 16
-#define xd_p_reg_ce_rh0_31_24	0xABE7
-#define	reg_ce_rh0_31_24_pos 0
-#define	reg_ce_rh0_31_24_len 8
-#define	reg_ce_rh0_31_24_lsb 24
-#define xd_p_reg_ce_rh3_real_7_0	0xABE8
-#define	reg_ce_rh3_real_7_0_pos 0
-#define	reg_ce_rh3_real_7_0_len 8
-#define	reg_ce_rh3_real_7_0_lsb 0
-#define xd_p_reg_ce_rh3_real_15_8	0xABE9
-#define	reg_ce_rh3_real_15_8_pos 0
-#define	reg_ce_rh3_real_15_8_len 8
-#define	reg_ce_rh3_real_15_8_lsb 8
-#define xd_p_reg_ce_rh3_real_23_16	0xABEA
-#define	reg_ce_rh3_real_23_16_pos 0
-#define	reg_ce_rh3_real_23_16_len 8
-#define	reg_ce_rh3_real_23_16_lsb 16
-#define xd_p_reg_ce_rh3_real_31_24	0xABEB
-#define	reg_ce_rh3_real_31_24_pos 0
-#define	reg_ce_rh3_real_31_24_len 8
-#define	reg_ce_rh3_real_31_24_lsb 24
-#define xd_p_reg_ce_rh3_imag_7_0	0xABEC
-#define	reg_ce_rh3_imag_7_0_pos 0
-#define	reg_ce_rh3_imag_7_0_len 8
-#define	reg_ce_rh3_imag_7_0_lsb 0
-#define xd_p_reg_ce_rh3_imag_15_8	0xABED
-#define	reg_ce_rh3_imag_15_8_pos 0
-#define	reg_ce_rh3_imag_15_8_len 8
-#define	reg_ce_rh3_imag_15_8_lsb 8
-#define xd_p_reg_ce_rh3_imag_23_16	0xABEE
-#define	reg_ce_rh3_imag_23_16_pos 0
-#define	reg_ce_rh3_imag_23_16_len 8
-#define	reg_ce_rh3_imag_23_16_lsb 16
-#define xd_p_reg_ce_rh3_imag_31_24	0xABEF
-#define	reg_ce_rh3_imag_31_24_pos 0
-#define	reg_ce_rh3_imag_31_24_len 8
-#define	reg_ce_rh3_imag_31_24_lsb 24
-#define xd_p_reg_feq_fix_eh2_7_0	0xABF0
-#define	reg_feq_fix_eh2_7_0_pos 0
-#define	reg_feq_fix_eh2_7_0_len 8
-#define	reg_feq_fix_eh2_7_0_lsb 0
-#define xd_p_reg_feq_fix_eh2_15_8	0xABF1
-#define	reg_feq_fix_eh2_15_8_pos 0
-#define	reg_feq_fix_eh2_15_8_len 8
-#define	reg_feq_fix_eh2_15_8_lsb 8
-#define xd_p_reg_feq_fix_eh2_23_16	0xABF2
-#define	reg_feq_fix_eh2_23_16_pos 0
-#define	reg_feq_fix_eh2_23_16_len 8
-#define	reg_feq_fix_eh2_23_16_lsb 16
-#define xd_p_reg_feq_fix_eh2_31_24	0xABF3
-#define	reg_feq_fix_eh2_31_24_pos 0
-#define	reg_feq_fix_eh2_31_24_len 8
-#define	reg_feq_fix_eh2_31_24_lsb 24
-#define xd_p_reg_ce_m2_central_7_0	0xABF4
-#define	reg_ce_m2_central_7_0_pos 0
-#define	reg_ce_m2_central_7_0_len 8
-#define	reg_ce_m2_central_7_0_lsb 0
-#define xd_p_reg_ce_m2_central_15_8	0xABF5
-#define	reg_ce_m2_central_15_8_pos 0
-#define	reg_ce_m2_central_15_8_len 8
-#define	reg_ce_m2_central_15_8_lsb 8
-#define xd_p_reg_ce_fftshift	0xABF6
-#define	reg_ce_fftshift_pos 0
-#define	reg_ce_fftshift_len 4
-#define	reg_ce_fftshift_lsb 0
-#define xd_p_reg_ce_fftshift1	0xABF6
-#define	reg_ce_fftshift1_pos 4
-#define	reg_ce_fftshift1_len 4
-#define	reg_ce_fftshift1_lsb 0
-#define xd_p_reg_ce_fftshift2	0xABF7
-#define	reg_ce_fftshift2_pos 0
-#define	reg_ce_fftshift2_len 4
-#define	reg_ce_fftshift2_lsb 0
-#define xd_p_reg_ce_top_mobile	0xABF7
-#define	reg_ce_top_mobile_pos 4
-#define	reg_ce_top_mobile_len 1
-#define	reg_ce_top_mobile_lsb 0
-#define xd_p_reg_strong_sginal_detected 0xA2BC
-#define reg_strong_sginal_detected_pos 2
-#define reg_strong_sginal_detected_len 1
-#define reg_strong_sginal_detected_lsb 0
-
-#define XD_MP2IF_BASE                           0xB000
-#define XD_MP2IF_CSR                        (0x00 + XD_MP2IF_BASE)
-#define XD_MP2IF_DMX_CTRL                       (0x03 + XD_MP2IF_BASE)
-#define XD_MP2IF_PID_IDX                        (0x04 + XD_MP2IF_BASE)
-#define XD_MP2IF_PID_DATA_L                     (0x05 + XD_MP2IF_BASE)
-#define XD_MP2IF_PID_DATA_H                     (0x06 + XD_MP2IF_BASE)
-#define XD_MP2IF_MISC                       (0x07 + XD_MP2IF_BASE)
-
-extern struct dvb_frontend *af9005_fe_attach(struct dvb_usb_device *d);
-extern int af9005_read_ofdm_register(struct dvb_usb_device *d, u16 reg,
-				     u8 * value);
-extern int af9005_read_ofdm_registers(struct dvb_usb_device *d, u16 reg,
-				      u8 * values, int len);
-extern int af9005_write_ofdm_register(struct dvb_usb_device *d, u16 reg,
-				      u8 value);
-extern int af9005_write_ofdm_registers(struct dvb_usb_device *d, u16 reg,
-				       u8 * values, int len);
-extern int af9005_read_tuner_registers(struct dvb_usb_device *d, u16 reg,
-				       u8 addr, u8 * values, int len);
-extern int af9005_write_tuner_registers(struct dvb_usb_device *d, u16 reg,
-					u8 * values, int len);
-extern int af9005_read_register_bits(struct dvb_usb_device *d, u16 reg,
-				     u8 pos, u8 len, u8 * value);
-extern int af9005_write_register_bits(struct dvb_usb_device *d, u16 reg,
-				      u8 pos, u8 len, u8 value);
-extern int af9005_send_command(struct dvb_usb_device *d, u8 command,
-			       u8 * wbuf, int wlen, u8 * rbuf, int rlen);
-extern int af9005_read_eeprom(struct dvb_usb_device *d, u8 address,
-			      u8 * values, int len);
-extern int af9005_tuner_attach(struct dvb_usb_adapter *adap);
-extern int af9005_led_control(struct dvb_usb_device *d, int onoff);
-
-extern u8 regmask[8];
-
-/* remote control decoder */
-extern int af9005_rc_decode(struct dvb_usb_device *d, u8 * data, int len,
-			    u32 * event, int *state);
-extern struct rc_map_table rc_map_af9005_table[];
-extern int rc_map_af9005_table_size;
-
-#endif
diff --git a/drivers/media/dvb/dvb-usb/af9015.c b/drivers/media/dvb/dvb-usb/af9015.c
deleted file mode 100644
index 677fed7..0000000
--- a/drivers/media/dvb/dvb-usb/af9015.c
+++ /dev/null
@@ -1,1952 +0,0 @@
-/*
- * DVB USB Linux driver for Afatech AF9015 DVB-T USB2.0 receiver
- *
- * Copyright (C) 2007 Antti Palosaari <crope@iki.fi>
- *
- * Thanks to Afatech who kindly provided information.
- *
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You 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/hash.h>
-#include <linux/slab.h>
-
-#include "af9015.h"
-#include "af9013.h"
-#include "mt2060.h"
-#include "qt1010.h"
-#include "tda18271.h"
-#include "mxl5005s.h"
-#include "mc44s803.h"
-#include "tda18218.h"
-#include "mxl5007t.h"
-
-static int dvb_usb_af9015_debug;
-module_param_named(debug, dvb_usb_af9015_debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS);
-static int dvb_usb_af9015_remote;
-module_param_named(remote, dvb_usb_af9015_remote, int, 0644);
-MODULE_PARM_DESC(remote, "select remote");
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-static DEFINE_MUTEX(af9015_usb_mutex);
-
-static struct af9015_config af9015_config;
-static struct dvb_usb_device_properties af9015_properties[3];
-static int af9015_properties_count = ARRAY_SIZE(af9015_properties);
-
-static struct af9013_config af9015_af9013_config[] = {
-	{
-		.i2c_addr = AF9015_I2C_DEMOD,
-		.ts_mode = AF9013_TS_USB,
-		.api_version = { 0, 1, 9, 0 },
-		.gpio[0] = AF9013_GPIO_HI,
-		.gpio[3] = AF9013_GPIO_TUNER_ON,
-
-	}, {
-		.ts_mode = AF9013_TS_SERIAL,
-		.api_version = { 0, 1, 9, 0 },
-		.gpio[0] = AF9013_GPIO_TUNER_ON,
-		.gpio[1] = AF9013_GPIO_LO,
-	}
-};
-
-static int af9015_rw_udev(struct usb_device *udev, struct req_t *req)
-{
-#define BUF_LEN 63
-#define REQ_HDR_LEN 8 /* send header size */
-#define ACK_HDR_LEN 2 /* rece header size */
-	int act_len, ret;
-	u8 buf[BUF_LEN];
-	u8 write = 1;
-	u8 msg_len = REQ_HDR_LEN;
-	static u8 seq; /* packet sequence number */
-
-	if (mutex_lock_interruptible(&af9015_usb_mutex) < 0)
-		return -EAGAIN;
-
-	buf[0] = req->cmd;
-	buf[1] = seq++;
-	buf[2] = req->i2c_addr;
-	buf[3] = req->addr >> 8;
-	buf[4] = req->addr & 0xff;
-	buf[5] = req->mbox;
-	buf[6] = req->addr_len;
-	buf[7] = req->data_len;
-
-	switch (req->cmd) {
-	case GET_CONFIG:
-	case READ_MEMORY:
-	case RECONNECT_USB:
-		write = 0;
-		break;
-	case READ_I2C:
-		write = 0;
-		buf[2] |= 0x01; /* set I2C direction */
-	case WRITE_I2C:
-		buf[0] = READ_WRITE_I2C;
-		break;
-	case WRITE_MEMORY:
-		if (((req->addr & 0xff00) == 0xff00) ||
-		    ((req->addr & 0xff00) == 0xae00))
-			buf[0] = WRITE_VIRTUAL_MEMORY;
-	case WRITE_VIRTUAL_MEMORY:
-	case COPY_FIRMWARE:
-	case DOWNLOAD_FIRMWARE:
-	case BOOT:
-		break;
-	default:
-		err("unknown command:%d", req->cmd);
-		ret = -1;
-		goto error_unlock;
-	}
-
-	/* buffer overflow check */
-	if ((write && (req->data_len > BUF_LEN - REQ_HDR_LEN)) ||
-		(!write && (req->data_len > BUF_LEN - ACK_HDR_LEN))) {
-		err("too much data; cmd:%d len:%d", req->cmd, req->data_len);
-		ret = -EINVAL;
-		goto error_unlock;
-	}
-
-	/* write requested */
-	if (write) {
-		memcpy(&buf[REQ_HDR_LEN], req->data, req->data_len);
-		msg_len += req->data_len;
-	}
-
-	deb_xfer(">>> ");
-	debug_dump(buf, msg_len, deb_xfer);
-
-	/* send req */
-	ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, 0x02), buf, msg_len,
-		&act_len, AF9015_USB_TIMEOUT);
-	if (ret)
-		err("bulk message failed:%d (%d/%d)", ret, msg_len, act_len);
-	else
-		if (act_len != msg_len)
-			ret = -1; /* all data is not send */
-	if (ret)
-		goto error_unlock;
-
-	/* no ack for those packets */
-	if (req->cmd == DOWNLOAD_FIRMWARE || req->cmd == RECONNECT_USB)
-		goto exit_unlock;
-
-	/* write receives seq + status = 2 bytes
-	   read receives seq + status + data = 2 + N bytes */
-	msg_len = ACK_HDR_LEN;
-	if (!write)
-		msg_len += req->data_len;
-
-	ret = usb_bulk_msg(udev, usb_rcvbulkpipe(udev, 0x81), buf, msg_len,
-		&act_len, AF9015_USB_TIMEOUT);
-	if (ret) {
-		err("recv bulk message failed:%d", ret);
-		ret = -1;
-		goto error_unlock;
-	}
-
-	deb_xfer("<<< ");
-	debug_dump(buf, act_len, deb_xfer);
-
-	/* check status */
-	if (buf[1]) {
-		err("command failed:%d", buf[1]);
-		ret = -1;
-		goto error_unlock;
-	}
-
-	/* read request, copy returned data to return buf */
-	if (!write)
-		memcpy(req->data, &buf[ACK_HDR_LEN], req->data_len);
-
-error_unlock:
-exit_unlock:
-	mutex_unlock(&af9015_usb_mutex);
-
-	return ret;
-}
-
-static int af9015_ctrl_msg(struct dvb_usb_device *d, struct req_t *req)
-{
-	return af9015_rw_udev(d->udev, req);
-}
-
-static int af9015_write_regs(struct dvb_usb_device *d, u16 addr, u8 *val,
-	u8 len)
-{
-	struct req_t req = {WRITE_MEMORY, AF9015_I2C_DEMOD, addr, 0, 0, len,
-		val};
-	return af9015_ctrl_msg(d, &req);
-}
-
-static int af9015_write_reg(struct dvb_usb_device *d, u16 addr, u8 val)
-{
-	return af9015_write_regs(d, addr, &val, 1);
-}
-
-static int af9015_read_regs(struct dvb_usb_device *d, u16 addr, u8 *val, u8 len)
-{
-	struct req_t req = {READ_MEMORY, AF9015_I2C_DEMOD, addr, 0, 0, len,
-		val};
-	return af9015_ctrl_msg(d, &req);
-}
-
-static int af9015_read_reg(struct dvb_usb_device *d, u16 addr, u8 *val)
-{
-	return af9015_read_regs(d, addr, val, 1);
-}
-
-static int af9015_write_reg_i2c(struct dvb_usb_device *d, u8 addr, u16 reg,
-	u8 val)
-{
-	struct req_t req = {WRITE_I2C, addr, reg, 1, 1, 1, &val};
-
-	if (addr == af9015_af9013_config[0].i2c_addr ||
-	    addr == af9015_af9013_config[1].i2c_addr)
-		req.addr_len = 3;
-
-	return af9015_ctrl_msg(d, &req);
-}
-
-static int af9015_read_reg_i2c(struct dvb_usb_device *d, u8 addr, u16 reg,
-	u8 *val)
-{
-	struct req_t req = {READ_I2C, addr, reg, 0, 1, 1, val};
-
-	if (addr == af9015_af9013_config[0].i2c_addr ||
-	    addr == af9015_af9013_config[1].i2c_addr)
-		req.addr_len = 3;
-
-	return af9015_ctrl_msg(d, &req);
-}
-
-static int af9015_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
-	int num)
-{
-	struct dvb_usb_device *d = i2c_get_adapdata(adap);
-	int ret = 0, i = 0;
-	u16 addr;
-	u8 uninitialized_var(mbox), addr_len;
-	struct req_t req;
-
-/*
-The bus lock is needed because there is two tuners both using same I2C-address.
-Due to that the only way to select correct tuner is use demodulator I2C-gate.
-
-................................................
-. AF9015 includes integrated AF9013 demodulator.
-. ____________                   ____________  .                ____________
-.|     uC     |                 |   demod    | .               |    tuner   |
-.|------------|                 |------------| .               |------------|
-.|   AF9015   |                 |  AF9013/5  | .               |   MXL5003  |
-.|            |--+----I2C-------|-----/ -----|-.-----I2C-------|            |
-.|            |  |              | addr 0x38  | .               |  addr 0xc6 |
-.|____________|  |              |____________| .               |____________|
-.................|..............................
-		 |               ____________                   ____________
-		 |              |   demod    |                 |    tuner   |
-		 |              |------------|                 |------------|
-		 |              |   AF9013   |                 |   MXL5003  |
-		 +----I2C-------|-----/ -----|-------I2C-------|            |
-				| addr 0x3a  |                 |  addr 0xc6 |
-				|____________|                 |____________|
-*/
-	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
-		return -EAGAIN;
-
-	while (i < num) {
-		if (msg[i].addr == af9015_af9013_config[0].i2c_addr ||
-		    msg[i].addr == af9015_af9013_config[1].i2c_addr) {
-			addr = msg[i].buf[0] << 8;
-			addr += msg[i].buf[1];
-			mbox = msg[i].buf[2];
-			addr_len = 3;
-		} else {
-			addr = msg[i].buf[0];
-			addr_len = 1;
-			/* mbox is don't care in that case */
-		}
-
-		if (num > i + 1 && (msg[i+1].flags & I2C_M_RD)) {
-			if (msg[i].len > 3 || msg[i+1].len > 61) {
-				ret = -EOPNOTSUPP;
-				goto error;
-			}
-			if (msg[i].addr == af9015_af9013_config[0].i2c_addr)
-				req.cmd = READ_MEMORY;
-			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+1].len;
-			req.data = &msg[i+1].buf[0];
-			ret = af9015_ctrl_msg(d, &req);
-			i += 2;
-		} else if (msg[i].flags & I2C_M_RD) {
-			if (msg[i].len > 61) {
-				ret = -EOPNOTSUPP;
-				goto error;
-			}
-			if (msg[i].addr ==
-				af9015_af9013_config[0].i2c_addr) {
-				ret = -EINVAL;
-				goto error;
-			}
-			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].len > 21) {
-				ret = -EOPNOTSUPP;
-				goto error;
-			}
-			if (msg[i].addr == af9015_af9013_config[0].i2c_addr)
-				req.cmd = WRITE_MEMORY;
-			else
-				req.cmd = WRITE_I2C;
-			req.i2c_addr = msg[i].addr;
-			req.addr = addr;
-			req.mbox = mbox;
-			req.addr_len = addr_len;
-			req.data_len = msg[i].len-addr_len;
-			req.data = &msg[i].buf[addr_len];
-			ret = af9015_ctrl_msg(d, &req);
-			i += 1;
-		}
-		if (ret)
-			goto error;
-
-	}
-	ret = i;
-
-error:
-	mutex_unlock(&d->i2c_mutex);
-
-	return ret;
-}
-
-static u32 af9015_i2c_func(struct i2c_adapter *adapter)
-{
-	return I2C_FUNC_I2C;
-}
-
-static struct i2c_algorithm af9015_i2c_algo = {
-	.master_xfer = af9015_i2c_xfer,
-	.functionality = af9015_i2c_func,
-};
-
-static int af9015_do_reg_bit(struct dvb_usb_device *d, u16 addr, u8 bit, u8 op)
-{
-	int ret;
-	u8 val, mask = 0x01;
-
-	ret = af9015_read_reg(d, addr, &val);
-	if (ret)
-		return ret;
-
-	mask <<= bit;
-	if (op) {
-		/* set bit */
-		val |= mask;
-	} else {
-		/* clear bit */
-		mask ^= 0xff;
-		val &= mask;
-	}
-
-	return af9015_write_reg(d, addr, val);
-}
-
-static int af9015_set_reg_bit(struct dvb_usb_device *d, u16 addr, u8 bit)
-{
-	return af9015_do_reg_bit(d, addr, bit, 1);
-}
-
-static int af9015_clear_reg_bit(struct dvb_usb_device *d, u16 addr, u8 bit)
-{
-	return af9015_do_reg_bit(d, addr, bit, 0);
-}
-
-static int af9015_init_endpoint(struct dvb_usb_device *d)
-{
-	int ret;
-	u16 frame_size;
-	u8  packet_size;
-	deb_info("%s: USB speed:%d\n", __func__, d->udev->speed);
-
-	/* Windows driver uses packet count 21 for USB1.1 and 348 for USB2.0.
-	   We use smaller - about 1/4 from the original, 5 and 87. */
-#define TS_PACKET_SIZE            188
-
-#define TS_USB20_PACKET_COUNT      87
-#define TS_USB20_FRAME_SIZE       (TS_PACKET_SIZE*TS_USB20_PACKET_COUNT)
-
-#define TS_USB11_PACKET_COUNT       5
-#define TS_USB11_FRAME_SIZE       (TS_PACKET_SIZE*TS_USB11_PACKET_COUNT)
-
-#define TS_USB20_MAX_PACKET_SIZE  512
-#define TS_USB11_MAX_PACKET_SIZE   64
-
-	if (d->udev->speed == USB_SPEED_FULL) {
-		frame_size = TS_USB11_FRAME_SIZE/4;
-		packet_size = TS_USB11_MAX_PACKET_SIZE/4;
-	} else {
-		frame_size = TS_USB20_FRAME_SIZE/4;
-		packet_size = TS_USB20_MAX_PACKET_SIZE/4;
-	}
-
-	ret = af9015_set_reg_bit(d, 0xd507, 2); /* assert EP4 reset */
-	if (ret)
-		goto error;
-	ret = af9015_set_reg_bit(d, 0xd50b, 1); /* assert EP5 reset */
-	if (ret)
-		goto error;
-	ret = af9015_clear_reg_bit(d, 0xdd11, 5); /* disable EP4 */
-	if (ret)
-		goto error;
-	ret = af9015_clear_reg_bit(d, 0xdd11, 6); /* disable EP5 */
-	if (ret)
-		goto error;
-	ret = af9015_set_reg_bit(d, 0xdd11, 5); /* enable EP4 */
-	if (ret)
-		goto error;
-	if (af9015_config.dual_mode) {
-		ret = af9015_set_reg_bit(d, 0xdd11, 6); /* enable EP5 */
-		if (ret)
-			goto error;
-	}
-	ret = af9015_clear_reg_bit(d, 0xdd13, 5); /* disable EP4 NAK */
-	if (ret)
-		goto error;
-	if (af9015_config.dual_mode) {
-		ret = af9015_clear_reg_bit(d, 0xdd13, 6); /* disable EP5 NAK */
-		if (ret)
-			goto error;
-	}
-	/* EP4 xfer length */
-	ret = af9015_write_reg(d, 0xdd88, frame_size & 0xff);
-	if (ret)
-		goto error;
-	ret = af9015_write_reg(d, 0xdd89, frame_size >> 8);
-	if (ret)
-		goto error;
-	/* EP5 xfer length */
-	ret = af9015_write_reg(d, 0xdd8a, frame_size & 0xff);
-	if (ret)
-		goto error;
-	ret = af9015_write_reg(d, 0xdd8b, frame_size >> 8);
-	if (ret)
-		goto error;
-	ret = af9015_write_reg(d, 0xdd0c, packet_size); /* EP4 packet size */
-	if (ret)
-		goto error;
-	ret = af9015_write_reg(d, 0xdd0d, packet_size); /* EP5 packet size */
-	if (ret)
-		goto error;
-	ret = af9015_clear_reg_bit(d, 0xd507, 2); /* negate EP4 reset */
-	if (ret)
-		goto error;
-	if (af9015_config.dual_mode) {
-		ret = af9015_clear_reg_bit(d, 0xd50b, 1); /* negate EP5 reset */
-		if (ret)
-			goto error;
-	}
-
-	/* enable / disable mp2if2 */
-	if (af9015_config.dual_mode)
-		ret = af9015_set_reg_bit(d, 0xd50b, 0);
-	else
-		ret = af9015_clear_reg_bit(d, 0xd50b, 0);
-
-error:
-	if (ret)
-		err("endpoint init failed:%d", ret);
-	return ret;
-}
-
-static int af9015_copy_firmware(struct dvb_usb_device *d)
-{
-	int ret;
-	u8 fw_params[4];
-	u8 val, i;
-	struct req_t req = {COPY_FIRMWARE, 0, 0x5100, 0, 0, sizeof(fw_params),
-		fw_params };
-	deb_info("%s:\n", __func__);
-
-	fw_params[0] = af9015_config.firmware_size >> 8;
-	fw_params[1] = af9015_config.firmware_size & 0xff;
-	fw_params[2] = af9015_config.firmware_checksum >> 8;
-	fw_params[3] = af9015_config.firmware_checksum & 0xff;
-
-	/* wait 2nd demodulator ready */
-	msleep(100);
-
-	ret = af9015_read_reg_i2c(d,
-		af9015_af9013_config[1].i2c_addr, 0x98be, &val);
-	if (ret)
-		goto error;
-	else
-		deb_info("%s: firmware status:%02x\n", __func__, val);
-
-	if (val == 0x0c) /* fw is running, no need for download */
-		goto exit;
-
-	/* set I2C master clock to fast (to speed up firmware copy) */
-	ret = af9015_write_reg(d, 0xd416, 0x04); /* 0x04 * 400ns */
-	if (ret)
-		goto error;
-
-	msleep(50);
-
-	/* copy firmware */
-	ret = af9015_ctrl_msg(d, &req);
-	if (ret)
-		err("firmware copy cmd failed:%d", ret);
-	deb_info("%s: firmware copy done\n", __func__);
-
-	/* set I2C master clock back to normal */
-	ret = af9015_write_reg(d, 0xd416, 0x14); /* 0x14 * 400ns */
-	if (ret)
-		goto error;
-
-	/* request boot firmware */
-	ret = af9015_write_reg_i2c(d, af9015_af9013_config[1].i2c_addr,
-		0xe205, 1);
-	deb_info("%s: firmware boot cmd status:%d\n", __func__, ret);
-	if (ret)
-		goto error;
-
-	for (i = 0; i < 15; i++) {
-		msleep(100);
-
-		/* check firmware status */
-		ret = af9015_read_reg_i2c(d,
-			af9015_af9013_config[1].i2c_addr, 0x98be, &val);
-		deb_info("%s: firmware status cmd status:%d fw status:%02x\n",
-			__func__, ret, val);
-		if (ret)
-			goto error;
-
-		if (val == 0x0c || val == 0x04) /* success or fail */
-			break;
-	}
-
-	if (val == 0x04) {
-		err("firmware did not run");
-		ret = -1;
-	} else if (val != 0x0c) {
-		err("firmware boot timeout");
-		ret = -1;
-	}
-
-error:
-exit:
-	return ret;
-}
-
-/* hash (and dump) eeprom */
-static int af9015_eeprom_hash(struct usb_device *udev)
-{
-	static const unsigned int eeprom_size = 256;
-	unsigned int reg;
-	int ret;
-	u8 val, *eeprom;
-	struct req_t req = {READ_I2C, AF9015_I2C_EEPROM, 0, 0, 1, 1, &val};
-
-	eeprom = kmalloc(eeprom_size, GFP_KERNEL);
-	if (eeprom == NULL)
-		return -ENOMEM;
-
-	for (reg = 0; reg < eeprom_size; reg++) {
-		req.addr = reg;
-		ret = af9015_rw_udev(udev, &req);
-		if (ret)
-			goto free;
-		eeprom[reg] = val;
-	}
-
-	if (dvb_usb_af9015_debug & 0x01)
-		print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, eeprom,
-				eeprom_size);
-
-	BUG_ON(eeprom_size % 4);
-
-	af9015_config.eeprom_sum = 0;
-	for (reg = 0; reg < eeprom_size / sizeof(u32); reg++) {
-		af9015_config.eeprom_sum *= GOLDEN_RATIO_PRIME_32;
-		af9015_config.eeprom_sum += le32_to_cpu(((u32 *)eeprom)[reg]);
-	}
-
-	deb_info("%s: eeprom sum=%.8x\n", __func__, af9015_config.eeprom_sum);
-
-	ret = 0;
-free:
-	kfree(eeprom);
-	return ret;
-}
-
-static int af9015_init(struct dvb_usb_device *d)
-{
-	int ret;
-	deb_info("%s:\n", __func__);
-
-	/* init RC canary */
-	ret = af9015_write_reg(d, 0x98e9, 0xff);
-	if (ret)
-		goto error;
-
-	ret = af9015_init_endpoint(d);
-	if (ret)
-		goto error;
-
-error:
-	return ret;
-}
-
-static int af9015_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff)
-{
-	int ret;
-	deb_info("%s: onoff:%d\n", __func__, onoff);
-
-	if (onoff)
-		ret = af9015_set_reg_bit(adap->dev, 0xd503, 0);
-	else
-		ret = af9015_clear_reg_bit(adap->dev, 0xd503, 0);
-
-	return ret;
-}
-
-static int af9015_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid,
-	int onoff)
-{
-	int ret;
-	u8 idx;
-
-	deb_info("%s: set pid filter, index %d, pid %x, onoff %d\n",
-		__func__, index, pid, onoff);
-
-	ret = af9015_write_reg(adap->dev, 0xd505, (pid & 0xff));
-	if (ret)
-		goto error;
-
-	ret = af9015_write_reg(adap->dev, 0xd506, (pid >> 8));
-	if (ret)
-		goto error;
-
-	idx = ((index & 0x1f) | (1 << 5));
-	ret = af9015_write_reg(adap->dev, 0xd504, idx);
-
-error:
-	return ret;
-}
-
-static int af9015_download_firmware(struct usb_device *udev,
-	const struct firmware *fw)
-{
-	int i, len, remaining, ret;
-	struct req_t req = {DOWNLOAD_FIRMWARE, 0, 0, 0, 0, 0, NULL};
-	u16 checksum = 0;
-
-	deb_info("%s:\n", __func__);
-
-	/* calc checksum */
-	for (i = 0; i < fw->size; i++)
-		checksum += fw->data[i];
-
-	af9015_config.firmware_size = fw->size;
-	af9015_config.firmware_checksum = checksum;
-
-	#define FW_ADDR 0x5100 /* firmware start address */
-	#define LEN_MAX 55 /* max packet size */
-	for (remaining = fw->size; remaining > 0; remaining -= LEN_MAX) {
-		len = remaining;
-		if (len > LEN_MAX)
-			len = LEN_MAX;
-
-		req.data_len = len;
-		req.data = (u8 *) &fw->data[fw->size - remaining];
-		req.addr = FW_ADDR + fw->size - remaining;
-
-		ret = af9015_rw_udev(udev, &req);
-		if (ret) {
-			err("firmware download failed:%d", ret);
-			goto error;
-		}
-	}
-
-	/* firmware loaded, request boot */
-	req.cmd = BOOT;
-	ret = af9015_rw_udev(udev, &req);
-	if (ret) {
-		err("firmware boot failed:%d", ret);
-		goto error;
-	}
-
-error:
-	return ret;
-}
-
-struct af9015_rc_setup {
-	unsigned int id;
-	char *rc_codes;
-};
-
-static char *af9015_rc_setup_match(unsigned int id,
-	const struct af9015_rc_setup *table)
-{
-	for (; table->rc_codes; table++)
-		if (table->id == id)
-			return table->rc_codes;
-	return NULL;
-}
-
-static const struct af9015_rc_setup af9015_rc_setup_modparam[] = {
-	{ AF9015_REMOTE_A_LINK_DTU_M, RC_MAP_ALINK_DTU_M },
-	{ AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3, RC_MAP_MSI_DIGIVOX_II },
-	{ AF9015_REMOTE_MYGICTV_U718, RC_MAP_TOTAL_MEDIA_IN_HAND },
-	{ AF9015_REMOTE_DIGITTRADE_DVB_T, RC_MAP_DIGITTRADE },
-	{ AF9015_REMOTE_AVERMEDIA_KS, RC_MAP_AVERMEDIA_RM_KS },
-	{ }
-};
-
-static const struct af9015_rc_setup af9015_rc_setup_hashes[] = {
-	{ 0xb8feb708, RC_MAP_MSI_DIGIVOX_II },
-	{ 0xa3703d00, RC_MAP_ALINK_DTU_M },
-	{ 0x9b7dc64e, RC_MAP_TOTAL_MEDIA_IN_HAND }, /* MYGICTV U718 */
-	{ 0x5d49e3db, RC_MAP_DIGITTRADE }, /* LC-Power LC-USB-DVBT */
-	{ }
-};
-
-static const struct af9015_rc_setup af9015_rc_setup_usbids[] = {
-	{ (USB_VID_TERRATEC << 16) | USB_PID_TERRATEC_CINERGY_T_STICK_RC,
-		RC_MAP_TERRATEC_SLIM_2 },
-	{ (USB_VID_TERRATEC << 16) | USB_PID_TERRATEC_CINERGY_T_STICK_DUAL_RC,
-		RC_MAP_TERRATEC_SLIM },
-	{ (USB_VID_VISIONPLUS << 16) | USB_PID_AZUREWAVE_AD_TU700,
-		RC_MAP_AZUREWAVE_AD_TU700 },
-	{ (USB_VID_VISIONPLUS << 16) | USB_PID_TINYTWIN,
-		RC_MAP_AZUREWAVE_AD_TU700 },
-	{ (USB_VID_MSI_2 << 16) | USB_PID_MSI_DIGI_VOX_MINI_III,
-		RC_MAP_MSI_DIGIVOX_III },
-	{ (USB_VID_MSI_2 << 16) | USB_PID_MSI_DIGIVOX_DUO,
-		RC_MAP_MSI_DIGIVOX_III },
-	{ (USB_VID_LEADTEK << 16) | USB_PID_WINFAST_DTV_DONGLE_GOLD,
-		RC_MAP_LEADTEK_Y04G0051 },
-	{ (USB_VID_LEADTEK << 16) | USB_PID_WINFAST_DTV2000DS,
-		RC_MAP_LEADTEK_Y04G0051 },
-	{ (USB_VID_AVERMEDIA << 16) | USB_PID_AVERMEDIA_VOLAR_X,
-		RC_MAP_AVERMEDIA_M135A },
-	{ (USB_VID_AFATECH << 16) | USB_PID_TREKSTOR_DVBT,
-		RC_MAP_TREKSTOR },
-	{ (USB_VID_KWORLD_2 << 16) | USB_PID_TINYTWIN_2,
-		RC_MAP_DIGITALNOW_TINYTWIN },
-	{ (USB_VID_GTEK << 16) | USB_PID_TINYTWIN_3,
-		RC_MAP_DIGITALNOW_TINYTWIN },
-	{ (USB_VID_KWORLD_2 << 16) | USB_PID_SVEON_STV22,
-		RC_MAP_MSI_DIGIVOX_III },
-	{ }
-};
-
-static void af9015_set_remote_config(struct usb_device *udev,
-		struct dvb_usb_device_properties *props)
-{
-	u16 vid = le16_to_cpu(udev->descriptor.idVendor);
-	u16 pid = le16_to_cpu(udev->descriptor.idProduct);
-
-	/* try to load remote based module param */
-	props->rc.core.rc_codes = af9015_rc_setup_match(
-		dvb_usb_af9015_remote, af9015_rc_setup_modparam);
-
-	/* try to load remote based eeprom hash */
-	if (!props->rc.core.rc_codes)
-		props->rc.core.rc_codes = af9015_rc_setup_match(
-			af9015_config.eeprom_sum, af9015_rc_setup_hashes);
-
-	/* try to load remote based USB ID */
-	if (!props->rc.core.rc_codes)
-		props->rc.core.rc_codes = af9015_rc_setup_match(
-			(vid << 16) | pid, af9015_rc_setup_usbids);
-
-	/* try to load remote based USB iManufacturer string */
-	if (!props->rc.core.rc_codes && vid == USB_VID_AFATECH) {
-		/* Check USB manufacturer and product strings and try
-		   to determine correct remote in case of chip vendor
-		   reference IDs are used.
-		   DO NOT ADD ANYTHING NEW HERE. Use hashes instead. */
-		char manufacturer[10];
-		memset(manufacturer, 0, sizeof(manufacturer));
-		usb_string(udev, udev->descriptor.iManufacturer,
-			manufacturer, sizeof(manufacturer));
-		if (!strcmp("MSI", manufacturer)) {
-			/* iManufacturer 1 MSI
-			   iProduct      2 MSI K-VOX */
-			props->rc.core.rc_codes = af9015_rc_setup_match(
-				AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3,
-				af9015_rc_setup_modparam);
-		}
-	}
-
-	/* finally load "empty" just for leaving IR receiver enabled */
-	if (!props->rc.core.rc_codes)
-		props->rc.core.rc_codes = RC_MAP_EMPTY;
-
-	return;
-}
-
-static int af9015_read_config(struct usb_device *udev)
-{
-	int ret;
-	u8 val, i, offset = 0;
-	struct req_t req = {READ_I2C, AF9015_I2C_EEPROM, 0, 0, 1, 1, &val};
-
-	/* IR remote controller */
-	req.addr = AF9015_EEPROM_IR_MODE;
-	/* first message will timeout often due to possible hw bug */
-	for (i = 0; i < 4; i++) {
-		ret = af9015_rw_udev(udev, &req);
-		if (!ret)
-			break;
-	}
-	if (ret)
-		goto error;
-
-	ret = af9015_eeprom_hash(udev);
-	if (ret)
-		goto error;
-
-	deb_info("%s: IR mode=%d\n", __func__, val);
-	for (i = 0; i < af9015_properties_count; i++) {
-		if (val == AF9015_IR_MODE_DISABLED)
-			af9015_properties[i].rc.core.rc_codes = NULL;
-		else
-			af9015_set_remote_config(udev, &af9015_properties[i]);
-	}
-
-	/* TS mode - one or two receivers */
-	req.addr = AF9015_EEPROM_TS_MODE;
-	ret = af9015_rw_udev(udev, &req);
-	if (ret)
-		goto error;
-	af9015_config.dual_mode = val;
-	deb_info("%s: TS mode=%d\n", __func__, af9015_config.dual_mode);
-
-	/* Set adapter0 buffer size according to USB port speed, adapter1 buffer
-	   size can be static because it is enabled only USB2.0 */
-	for (i = 0; i < af9015_properties_count; i++) {
-		/* USB1.1 set smaller buffersize and disable 2nd adapter */
-		if (udev->speed == USB_SPEED_FULL) {
-			af9015_properties[i].adapter[0].fe[0].stream.u.bulk.buffersize
-				= TS_USB11_FRAME_SIZE;
-			/* disable 2nd adapter because we don't have
-			   PID-filters */
-			af9015_config.dual_mode = 0;
-		} else {
-			af9015_properties[i].adapter[0].fe[0].stream.u.bulk.buffersize
-				= TS_USB20_FRAME_SIZE;
-		}
-	}
-
-	if (af9015_config.dual_mode) {
-		/* read 2nd demodulator I2C address */
-		req.addr = AF9015_EEPROM_DEMOD2_I2C;
-		ret = af9015_rw_udev(udev, &req);
-		if (ret)
-			goto error;
-		af9015_af9013_config[1].i2c_addr = val;
-
-		/* enable 2nd adapter */
-		for (i = 0; i < af9015_properties_count; i++)
-			af9015_properties[i].num_adapters = 2;
-
-	} else {
-		 /* disable 2nd adapter */
-		for (i = 0; i < af9015_properties_count; i++)
-			af9015_properties[i].num_adapters = 1;
-	}
-
-	for (i = 0; i < af9015_properties[0].num_adapters; i++) {
-		if (i == 1)
-			offset = AF9015_EEPROM_OFFSET;
-		/* xtal */
-		req.addr = AF9015_EEPROM_XTAL_TYPE1 + offset;
-		ret = af9015_rw_udev(udev, &req);
-		if (ret)
-			goto error;
-		switch (val) {
-		case 0:
-			af9015_af9013_config[i].clock = 28800000;
-			break;
-		case 1:
-			af9015_af9013_config[i].clock = 20480000;
-			break;
-		case 2:
-			af9015_af9013_config[i].clock = 28000000;
-			break;
-		case 3:
-			af9015_af9013_config[i].clock = 25000000;
-			break;
-		};
-		deb_info("%s: [%d] xtal=%d set clock=%d\n", __func__, i,
-			val, af9015_af9013_config[i].clock);
-
-		/* IF frequency */
-		req.addr = AF9015_EEPROM_IF1H + offset;
-		ret = af9015_rw_udev(udev, &req);
-		if (ret)
-			goto error;
-
-		af9015_af9013_config[i].if_frequency = val << 8;
-
-		req.addr = AF9015_EEPROM_IF1L + offset;
-		ret = af9015_rw_udev(udev, &req);
-		if (ret)
-			goto error;
-
-		af9015_af9013_config[i].if_frequency += val;
-		af9015_af9013_config[i].if_frequency *= 1000;
-		deb_info("%s: [%d] IF frequency=%d\n", __func__, i,
-			af9015_af9013_config[0].if_frequency);
-
-		/* MT2060 IF1 */
-		req.addr = AF9015_EEPROM_MT2060_IF1H  + offset;
-		ret = af9015_rw_udev(udev, &req);
-		if (ret)
-			goto error;
-		af9015_config.mt2060_if1[i] = val << 8;
-		req.addr = AF9015_EEPROM_MT2060_IF1L + offset;
-		ret = af9015_rw_udev(udev, &req);
-		if (ret)
-			goto error;
-		af9015_config.mt2060_if1[i] += val;
-		deb_info("%s: [%d] MT2060 IF1=%d\n", __func__, i,
-			af9015_config.mt2060_if1[i]);
-
-		/* tuner */
-		req.addr =  AF9015_EEPROM_TUNER_ID1 + offset;
-		ret = af9015_rw_udev(udev, &req);
-		if (ret)
-			goto error;
-		switch (val) {
-		case AF9013_TUNER_ENV77H11D5:
-		case AF9013_TUNER_MT2060:
-		case AF9013_TUNER_QT1010:
-		case AF9013_TUNER_UNKNOWN:
-		case AF9013_TUNER_MT2060_2:
-		case AF9013_TUNER_TDA18271:
-		case AF9013_TUNER_QT1010A:
-		case AF9013_TUNER_TDA18218:
-			af9015_af9013_config[i].spec_inv = 1;
-			break;
-		case AF9013_TUNER_MXL5003D:
-		case AF9013_TUNER_MXL5005D:
-		case AF9013_TUNER_MXL5005R:
-		case AF9013_TUNER_MXL5007T:
-			af9015_af9013_config[i].spec_inv = 0;
-			break;
-		case AF9013_TUNER_MC44S803:
-			af9015_af9013_config[i].gpio[1] = AF9013_GPIO_LO;
-			af9015_af9013_config[i].spec_inv = 1;
-			break;
-		default:
-			warn("tuner id=%d not supported, please report!", val);
-			return -ENODEV;
-		};
-
-		af9015_af9013_config[i].tuner = val;
-		deb_info("%s: [%d] tuner id=%d\n", __func__, i, val);
-	}
-
-error:
-	if (ret)
-		err("eeprom read failed=%d", ret);
-
-	/* AverMedia AVerTV Volar Black HD (A850) device have bad EEPROM
-	   content :-( Override some wrong values here. Ditto for the
-	   AVerTV Red HD+ (A850T) device. */
-	if (le16_to_cpu(udev->descriptor.idVendor) == USB_VID_AVERMEDIA &&
-		((le16_to_cpu(udev->descriptor.idProduct) ==
-			USB_PID_AVERMEDIA_A850) ||
-		(le16_to_cpu(udev->descriptor.idProduct) ==
-			USB_PID_AVERMEDIA_A850T))) {
-		deb_info("%s: AverMedia A850: overriding config\n", __func__);
-		/* disable dual mode */
-		af9015_config.dual_mode = 0;
-		 /* disable 2nd adapter */
-		for (i = 0; i < af9015_properties_count; i++)
-			af9015_properties[i].num_adapters = 1;
-
-		/* set correct IF */
-		af9015_af9013_config[0].if_frequency = 4570000;
-	}
-
-	return ret;
-}
-
-static int af9015_identify_state(struct usb_device *udev,
-				 struct dvb_usb_device_properties *props,
-				 struct dvb_usb_device_description **desc,
-				 int *cold)
-{
-	int ret;
-	u8 reply;
-	struct req_t req = {GET_CONFIG, 0, 0, 0, 0, 1, &reply};
-
-	ret = af9015_rw_udev(udev, &req);
-	if (ret)
-		return ret;
-
-	deb_info("%s: reply:%02x\n", __func__, reply);
-	if (reply == 0x02)
-		*cold = 0;
-	else
-		*cold = 1;
-
-	return ret;
-}
-
-static int af9015_rc_query(struct dvb_usb_device *d)
-{
-	struct af9015_state *priv = d->priv;
-	int ret;
-	u8 buf[17];
-
-	/* read registers needed to detect remote controller code */
-	ret = af9015_read_regs(d, 0x98d9, buf, sizeof(buf));
-	if (ret)
-		goto error;
-
-	/* If any of these are non-zero, assume invalid data */
-	if (buf[1] || buf[2] || buf[3])
-		return ret;
-
-	/* Check for repeat of previous code */
-	if ((priv->rc_repeat != buf[6] || buf[0]) &&
-					!memcmp(&buf[12], priv->rc_last, 4)) {
-		deb_rc("%s: key repeated\n", __func__);
-		rc_keydown(d->rc_dev, priv->rc_keycode, 0);
-		priv->rc_repeat = buf[6];
-		return ret;
-	}
-
-	/* Only process key if canary killed */
-	if (buf[16] != 0xff && buf[0] != 0x01) {
-		deb_rc("%s: key pressed %02x %02x %02x %02x\n", __func__,
-			buf[12], buf[13], buf[14], buf[15]);
-
-		/* Reset the canary */
-		ret = af9015_write_reg(d, 0x98e9, 0xff);
-		if (ret)
-			goto error;
-
-		/* Remember this key */
-		memcpy(priv->rc_last, &buf[12], 4);
-		if (buf[14] == (u8) ~buf[15]) {
-			if (buf[12] == (u8) ~buf[13]) {
-				/* NEC */
-				priv->rc_keycode = buf[12] << 8 | buf[14];
-			} else {
-				/* NEC extended*/
-				priv->rc_keycode = buf[12] << 16 |
-					buf[13] << 8 | buf[14];
-			}
-		} else {
-			/* 32 bit NEC */
-			priv->rc_keycode = buf[12] << 24 | buf[13] << 16 |
-					buf[14] << 8 | buf[15];
-		}
-		rc_keydown(d->rc_dev, priv->rc_keycode, 0);
-	} else {
-		deb_rc("%s: no key press\n", __func__);
-		/* Invalidate last keypress */
-		/* Not really needed, but helps with debug */
-		priv->rc_last[2] = priv->rc_last[3];
-	}
-
-	priv->rc_repeat = buf[6];
-
-error:
-	if (ret)
-		err("%s: failed:%d", __func__, ret);
-
-	return ret;
-}
-
-/* override demod callbacks for resource locking */
-static int af9015_af9013_set_frontend(struct dvb_frontend *fe)
-{
-	int ret;
-	struct dvb_usb_adapter *adap = fe->dvb->priv;
-	struct af9015_state *priv = adap->dev->priv;
-
-	if (mutex_lock_interruptible(&adap->dev->usb_mutex))
-		return -EAGAIN;
-
-	ret = priv->set_frontend[adap->id](fe);
-
-	mutex_unlock(&adap->dev->usb_mutex);
-
-	return ret;
-}
-
-/* override demod callbacks for resource locking */
-static int af9015_af9013_read_status(struct dvb_frontend *fe,
-	fe_status_t *status)
-{
-	int ret;
-	struct dvb_usb_adapter *adap = fe->dvb->priv;
-	struct af9015_state *priv = adap->dev->priv;
-
-	if (mutex_lock_interruptible(&adap->dev->usb_mutex))
-		return -EAGAIN;
-
-	ret = priv->read_status[adap->id](fe, status);
-
-	mutex_unlock(&adap->dev->usb_mutex);
-
-	return ret;
-}
-
-/* override demod callbacks for resource locking */
-static int af9015_af9013_init(struct dvb_frontend *fe)
-{
-	int ret;
-	struct dvb_usb_adapter *adap = fe->dvb->priv;
-	struct af9015_state *priv = adap->dev->priv;
-
-	if (mutex_lock_interruptible(&adap->dev->usb_mutex))
-		return -EAGAIN;
-
-	ret = priv->init[adap->id](fe);
-
-	mutex_unlock(&adap->dev->usb_mutex);
-
-	return ret;
-}
-
-/* override demod callbacks for resource locking */
-static int af9015_af9013_sleep(struct dvb_frontend *fe)
-{
-	int ret;
-	struct dvb_usb_adapter *adap = fe->dvb->priv;
-	struct af9015_state *priv = adap->dev->priv;
-
-	if (mutex_lock_interruptible(&adap->dev->usb_mutex))
-		return -EAGAIN;
-
-	ret = priv->sleep[adap->id](fe);
-
-	mutex_unlock(&adap->dev->usb_mutex);
-
-	return ret;
-}
-
-/* override tuner callbacks for resource locking */
-static int af9015_tuner_init(struct dvb_frontend *fe)
-{
-	int ret;
-	struct dvb_usb_adapter *adap = fe->dvb->priv;
-	struct af9015_state *priv = adap->dev->priv;
-
-	if (mutex_lock_interruptible(&adap->dev->usb_mutex))
-		return -EAGAIN;
-
-	ret = priv->tuner_init[adap->id](fe);
-
-	mutex_unlock(&adap->dev->usb_mutex);
-
-	return ret;
-}
-
-/* override tuner callbacks for resource locking */
-static int af9015_tuner_sleep(struct dvb_frontend *fe)
-{
-	int ret;
-	struct dvb_usb_adapter *adap = fe->dvb->priv;
-	struct af9015_state *priv = adap->dev->priv;
-
-	if (mutex_lock_interruptible(&adap->dev->usb_mutex))
-		return -EAGAIN;
-
-	ret = priv->tuner_sleep[adap->id](fe);
-
-	mutex_unlock(&adap->dev->usb_mutex);
-
-	return ret;
-}
-
-
-static int af9015_af9013_frontend_attach(struct dvb_usb_adapter *adap)
-{
-	int ret;
-	struct af9015_state *state = adap->dev->priv;
-
-	if (adap->id == 1) {
-		/* copy firmware to 2nd demodulator */
-		if (af9015_config.dual_mode) {
-			ret = af9015_copy_firmware(adap->dev);
-			if (ret) {
-				err("firmware copy to 2nd frontend " \
-					"failed, will disable it");
-				af9015_config.dual_mode = 0;
-				return -ENODEV;
-			}
-		} else {
-			return -ENODEV;
-		}
-	}
-
-	/* attach demodulator */
-	adap->fe_adap[0].fe = dvb_attach(af9013_attach,
-		&af9015_af9013_config[adap->id], &adap->dev->i2c_adap);
-
-	/*
-	 * AF9015 firmware does not like if it gets interrupted by I2C adapter
-	 * request on some critical phases. During normal operation I2C adapter
-	 * is used only 2nd demodulator and tuner on dual tuner devices.
-	 * Override demodulator callbacks and use mutex for limit access to
-	 * those "critical" paths to keep AF9015 happy.
-	 * Note: we abuse unused usb_mutex here.
-	 */
-	if (adap->fe_adap[0].fe) {
-		state->set_frontend[adap->id] =
-			adap->fe_adap[0].fe->ops.set_frontend;
-		adap->fe_adap[0].fe->ops.set_frontend =
-			af9015_af9013_set_frontend;
-
-		state->read_status[adap->id] =
-			adap->fe_adap[0].fe->ops.read_status;
-		adap->fe_adap[0].fe->ops.read_status =
-			af9015_af9013_read_status;
-
-		state->init[adap->id] = adap->fe_adap[0].fe->ops.init;
-		adap->fe_adap[0].fe->ops.init = af9015_af9013_init;
-
-		state->sleep[adap->id] = adap->fe_adap[0].fe->ops.sleep;
-		adap->fe_adap[0].fe->ops.sleep = af9015_af9013_sleep;
-	}
-
-	return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
-}
-
-static struct mt2060_config af9015_mt2060_config = {
-	.i2c_address = 0xc0,
-	.clock_out = 0,
-};
-
-static struct qt1010_config af9015_qt1010_config = {
-	.i2c_address = 0xc4,
-};
-
-static struct tda18271_config af9015_tda18271_config = {
-	.gate = TDA18271_GATE_DIGITAL,
-	.small_i2c = TDA18271_16_BYTE_CHUNK_INIT,
-};
-
-static struct mxl5005s_config af9015_mxl5003_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 struct mxl5005s_config af9015_mxl5005_config = {
-	.i2c_address     = 0xc6,
-	.if_freq         = IF_FREQ_4570000HZ,
-	.xtal_freq       = CRYSTAL_FREQ_16000000HZ,
-	.agc_mode        = MXL_SINGLE_AGC,
-	.tracking_filter = MXL_TF_OFF,
-	.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 struct mc44s803_config af9015_mc44s803_config = {
-	.i2c_address = 0xc0,
-	.dig_out = 1,
-};
-
-static struct tda18218_config af9015_tda18218_config = {
-	.i2c_address = 0xc0,
-	.i2c_wr_max = 21, /* max wr bytes AF9015 I2C adap can handle at once */
-};
-
-static struct mxl5007t_config af9015_mxl5007t_config = {
-	.xtal_freq_hz = MxL_XTAL_24_MHZ,
-	.if_freq_hz = MxL_IF_4_57_MHZ,
-};
-
-static int af9015_tuner_attach(struct dvb_usb_adapter *adap)
-{
-	int ret;
-	struct af9015_state *state = adap->dev->priv;
-	deb_info("%s:\n", __func__);
-
-	switch (af9015_af9013_config[adap->id].tuner) {
-	case AF9013_TUNER_MT2060:
-	case AF9013_TUNER_MT2060_2:
-		ret = dvb_attach(mt2060_attach, adap->fe_adap[0].fe,
-			&adap->dev->i2c_adap, &af9015_mt2060_config,
-			af9015_config.mt2060_if1[adap->id])
-			== NULL ? -ENODEV : 0;
-		break;
-	case AF9013_TUNER_QT1010:
-	case AF9013_TUNER_QT1010A:
-		ret = dvb_attach(qt1010_attach, adap->fe_adap[0].fe,
-			&adap->dev->i2c_adap,
-			&af9015_qt1010_config) == NULL ? -ENODEV : 0;
-		break;
-	case AF9013_TUNER_TDA18271:
-		ret = dvb_attach(tda18271_attach, adap->fe_adap[0].fe, 0xc0,
-			&adap->dev->i2c_adap,
-			&af9015_tda18271_config) == NULL ? -ENODEV : 0;
-		break;
-	case AF9013_TUNER_TDA18218:
-		ret = dvb_attach(tda18218_attach, adap->fe_adap[0].fe,
-			&adap->dev->i2c_adap,
-			&af9015_tda18218_config) == NULL ? -ENODEV : 0;
-		break;
-	case AF9013_TUNER_MXL5003D:
-		ret = dvb_attach(mxl5005s_attach, adap->fe_adap[0].fe,
-			&adap->dev->i2c_adap,
-			&af9015_mxl5003_config) == NULL ? -ENODEV : 0;
-		break;
-	case AF9013_TUNER_MXL5005D:
-	case AF9013_TUNER_MXL5005R:
-		ret = dvb_attach(mxl5005s_attach, adap->fe_adap[0].fe,
-			&adap->dev->i2c_adap,
-			&af9015_mxl5005_config) == NULL ? -ENODEV : 0;
-		break;
-	case AF9013_TUNER_ENV77H11D5:
-		ret = dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0xc0,
-			&adap->dev->i2c_adap,
-			DVB_PLL_TDA665X) == NULL ? -ENODEV : 0;
-		break;
-	case AF9013_TUNER_MC44S803:
-		ret = dvb_attach(mc44s803_attach, adap->fe_adap[0].fe,
-			&adap->dev->i2c_adap,
-			&af9015_mc44s803_config) == NULL ? -ENODEV : 0;
-		break;
-	case AF9013_TUNER_MXL5007T:
-		ret = dvb_attach(mxl5007t_attach, adap->fe_adap[0].fe,
-			&adap->dev->i2c_adap,
-			0xc0, &af9015_mxl5007t_config) == NULL ? -ENODEV : 0;
-		break;
-	case AF9013_TUNER_UNKNOWN:
-	default:
-		ret = -ENODEV;
-		err("Unknown tuner id:%d",
-			af9015_af9013_config[adap->id].tuner);
-	}
-
-	if (adap->fe_adap[0].fe->ops.tuner_ops.init) {
-		state->tuner_init[adap->id] =
-			adap->fe_adap[0].fe->ops.tuner_ops.init;
-		adap->fe_adap[0].fe->ops.tuner_ops.init = af9015_tuner_init;
-	}
-
-	if (adap->fe_adap[0].fe->ops.tuner_ops.sleep) {
-		state->tuner_sleep[adap->id] =
-			adap->fe_adap[0].fe->ops.tuner_ops.sleep;
-		adap->fe_adap[0].fe->ops.tuner_ops.sleep = af9015_tuner_sleep;
-	}
-
-	return ret;
-}
-
-enum af9015_usb_table_entry {
-	AFATECH_9015,
-	AFATECH_9016,
-	WINFAST_DTV_GOLD,
-	PINNACLE_PCTV_71E,
-	KWORLD_PLUSTV_399U,
-	TINYTWIN,
-	AZUREWAVE_TU700,
-	TERRATEC_AF9015,
-	KWORLD_PLUSTV_PC160,
-	AVERTV_VOLAR_X,
-	XTENSIONS_380U,
-	MSI_DIGIVOX_DUO,
-	AVERTV_VOLAR_X_REV2,
-	TELESTAR_STARSTICK_2,
-	AVERMEDIA_A309_USB,
-	MSI_DIGIVOX_MINI_III,
-	KWORLD_E396,
-	KWORLD_E39B,
-	KWORLD_E395,
-	TREKSTOR_DVBT,
-	AVERTV_A850,
-	AVERTV_A805,
-	CONCEPTRONIC_CTVDIGRCU,
-	KWORLD_MC810,
-	GENIUS_TVGO_DVB_T03,
-	KWORLD_399U_2,
-	KWORLD_PC160_T,
-	SVEON_STV20,
-	TINYTWIN_2,
-	WINFAST_DTV2000DS,
-	KWORLD_UB383_T,
-	KWORLD_E39A,
-	AVERMEDIA_A815M,
-	CINERGY_T_STICK_RC,
-	CINERGY_T_DUAL_RC,
-	AVERTV_A850T,
-	TINYTWIN_3,
-	SVEON_STV22,
-};
-
-static struct usb_device_id af9015_usb_table[] = {
-	[AFATECH_9015] = {
-		USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9015_9015)},
-	[AFATECH_9016] = {
-		USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9015_9016)},
-	[WINFAST_DTV_GOLD] = {
-		USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_GOLD)},
-	[PINNACLE_PCTV_71E] = {
-		USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV71E)},
-	[KWORLD_PLUSTV_399U] = {
-		USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_399U)},
-	[TINYTWIN] = {
-		USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TINYTWIN)},
-	[AZUREWAVE_TU700] = {
-		USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_AZUREWAVE_AD_TU700)},
-	[TERRATEC_AF9015] = {
-		USB_DEVICE(USB_VID_TERRATEC,
-				USB_PID_TERRATEC_CINERGY_T_USB_XE_REV2)},
-	[KWORLD_PLUSTV_PC160] = {
-		USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_PC160_2T)},
-	[AVERTV_VOLAR_X] = {
-		USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_X)},
-	[XTENSIONS_380U] = {
-		USB_DEVICE(USB_VID_XTENSIONS, USB_PID_XTENSIONS_XD_380)},
-	[MSI_DIGIVOX_DUO] = {
-		USB_DEVICE(USB_VID_MSI_2, USB_PID_MSI_DIGIVOX_DUO)},
-	[AVERTV_VOLAR_X_REV2] = {
-		USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_X_2)},
-	[TELESTAR_STARSTICK_2] = {
-		USB_DEVICE(USB_VID_TELESTAR,  USB_PID_TELESTAR_STARSTICK_2)},
-	[AVERMEDIA_A309_USB] = {
-		USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A309)},
-	[MSI_DIGIVOX_MINI_III] = {
-		USB_DEVICE(USB_VID_MSI_2, USB_PID_MSI_DIGI_VOX_MINI_III)},
-	[KWORLD_E396] = {
-		USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U)},
-	[KWORLD_E39B] = {
-		USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U_2)},
-	[KWORLD_E395] = {
-		USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U_3)},
-	[TREKSTOR_DVBT] = {
-		USB_DEVICE(USB_VID_AFATECH, USB_PID_TREKSTOR_DVBT)},
-	[AVERTV_A850] = {
-		USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A850)},
-	[AVERTV_A805] = {
-		USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A805)},
-	[CONCEPTRONIC_CTVDIGRCU] = {
-		USB_DEVICE(USB_VID_KWORLD_2, USB_PID_CONCEPTRONIC_CTVDIGRCU)},
-	[KWORLD_MC810] = {
-		USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_MC810)},
-	[GENIUS_TVGO_DVB_T03] = {
-		USB_DEVICE(USB_VID_KYE, USB_PID_GENIUS_TVGO_DVB_T03)},
-	[KWORLD_399U_2] = {
-		USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_399U_2)},
-	[KWORLD_PC160_T] = {
-		USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_PC160_T)},
-	[SVEON_STV20] = {
-		USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV20)},
-	[TINYTWIN_2] = {
-		USB_DEVICE(USB_VID_KWORLD_2, USB_PID_TINYTWIN_2)},
-	[WINFAST_DTV2000DS] = {
-		USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV2000DS)},
-	[KWORLD_UB383_T] = {
-		USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_UB383_T)},
-	[KWORLD_E39A] = {
-		USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U_4)},
-	[AVERMEDIA_A815M] = {
-		USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A815M)},
-	[CINERGY_T_STICK_RC] = {
-		USB_DEVICE(USB_VID_TERRATEC,
-				USB_PID_TERRATEC_CINERGY_T_STICK_RC)},
-	[CINERGY_T_DUAL_RC] = {
-		USB_DEVICE(USB_VID_TERRATEC,
-				USB_PID_TERRATEC_CINERGY_T_STICK_DUAL_RC)},
-	[AVERTV_A850T] = {
-		USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A850T)},
-	[TINYTWIN_3] = {
-		USB_DEVICE(USB_VID_GTEK, USB_PID_TINYTWIN_3)},
-	[SVEON_STV22] = {
-		USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV22)},
-	{ }
-};
-MODULE_DEVICE_TABLE(usb, af9015_usb_table);
-
-#define AF9015_RC_INTERVAL 500
-static struct dvb_usb_device_properties af9015_properties[] = {
-	{
-		.caps = DVB_USB_IS_AN_I2C_ADAPTER,
-
-		.usb_ctrl = DEVICE_SPECIFIC,
-		.download_firmware = af9015_download_firmware,
-		.firmware = "dvb-usb-af9015.fw",
-		.no_reconnect = 1,
-
-		.size_of_priv = sizeof(struct af9015_state),
-
-		.num_adapters = 2,
-		.adapter = {
-			{
-				.num_frontends = 1,
-				.fe = {
-					{
-						.caps = DVB_USB_ADAP_HAS_PID_FILTER |
-							DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
-
-						.pid_filter_count = 32,
-						.pid_filter       = af9015_pid_filter,
-						.pid_filter_ctrl  = af9015_pid_filter_ctrl,
-
-						.frontend_attach = af9015_af9013_frontend_attach,
-						.tuner_attach    = af9015_tuner_attach,
-						.stream = {
-							.type = USB_BULK,
-							.count = 6,
-							.endpoint = 0x84,
-						},
-					}
-				},
-			},
-			{
-				.num_frontends = 1,
-				.fe = {
-					{
-						.frontend_attach = af9015_af9013_frontend_attach,
-						.tuner_attach    = af9015_tuner_attach,
-						.stream = {
-							.type = USB_BULK,
-							.count = 6,
-							.endpoint = 0x85,
-							.u = {
-								.bulk = {
-									.buffersize = TS_USB20_FRAME_SIZE,
-								}
-							}
-						},
-					}
-				},
-			}
-		},
-
-		.identify_state = af9015_identify_state,
-
-		.rc.core = {
-			.protocol         = RC_TYPE_NEC,
-			.module_name      = "af9015",
-			.rc_query         = af9015_rc_query,
-			.rc_interval      = AF9015_RC_INTERVAL,
-			.allowed_protos   = RC_TYPE_NEC,
-		},
-
-		.i2c_algo = &af9015_i2c_algo,
-
-		.num_device_descs = 12, /* check max from dvb-usb.h */
-		.devices = {
-			{
-				.name = "Afatech AF9015 DVB-T USB2.0 stick",
-				.cold_ids = {
-					&af9015_usb_table[AFATECH_9015],
-					&af9015_usb_table[AFATECH_9016],
-				},
-			}, {
-				.name = "Leadtek WinFast DTV Dongle Gold",
-				.cold_ids = {
-					&af9015_usb_table[WINFAST_DTV_GOLD],
-				},
-			}, {
-				.name = "Pinnacle PCTV 71e",
-				.cold_ids = {
-					&af9015_usb_table[PINNACLE_PCTV_71E],
-				},
-			}, {
-				.name = "KWorld PlusTV Dual DVB-T Stick " \
-					"(DVB-T 399U)",
-				.cold_ids = {
-					&af9015_usb_table[KWORLD_PLUSTV_399U],
-					&af9015_usb_table[KWORLD_399U_2],
-				},
-			}, {
-				.name = "DigitalNow TinyTwin DVB-T Receiver",
-				.cold_ids = {
-					&af9015_usb_table[TINYTWIN],
-					&af9015_usb_table[TINYTWIN_2],
-					&af9015_usb_table[TINYTWIN_3],
-				},
-			}, {
-				.name = "TwinHan AzureWave AD-TU700(704J)",
-				.cold_ids = {
-					&af9015_usb_table[AZUREWAVE_TU700],
-				},
-			}, {
-				.name = "TerraTec Cinergy T USB XE",
-				.cold_ids = {
-					&af9015_usb_table[TERRATEC_AF9015],
-				},
-			}, {
-				.name = "KWorld PlusTV Dual DVB-T PCI " \
-					"(DVB-T PC160-2T)",
-				.cold_ids = {
-					&af9015_usb_table[KWORLD_PLUSTV_PC160],
-				},
-			}, {
-				.name = "AVerMedia AVerTV DVB-T Volar X",
-				.cold_ids = {
-					&af9015_usb_table[AVERTV_VOLAR_X],
-				},
-			}, {
-				.name = "TerraTec Cinergy T Stick RC",
-				.cold_ids = {
-					&af9015_usb_table[CINERGY_T_STICK_RC],
-				},
-			}, {
-				.name = "TerraTec Cinergy T Stick Dual RC",
-				.cold_ids = {
-					&af9015_usb_table[CINERGY_T_DUAL_RC],
-				},
-			}, {
-				.name = "AverMedia AVerTV Red HD+ (A850T)",
-				.cold_ids = {
-					&af9015_usb_table[AVERTV_A850T],
-				},
-			},
-		}
-	}, {
-		.caps = DVB_USB_IS_AN_I2C_ADAPTER,
-
-		.usb_ctrl = DEVICE_SPECIFIC,
-		.download_firmware = af9015_download_firmware,
-		.firmware = "dvb-usb-af9015.fw",
-		.no_reconnect = 1,
-
-		.size_of_priv = sizeof(struct af9015_state),
-
-		.num_adapters = 2,
-		.adapter = {
-			{
-				.num_frontends = 1,
-				.fe = {
-					{
-						.caps = DVB_USB_ADAP_HAS_PID_FILTER |
-							DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
-
-						.pid_filter_count = 32,
-						.pid_filter       = af9015_pid_filter,
-						.pid_filter_ctrl  = af9015_pid_filter_ctrl,
-
-						.frontend_attach = af9015_af9013_frontend_attach,
-						.tuner_attach    = af9015_tuner_attach,
-						.stream = {
-							.type = USB_BULK,
-							.count = 6,
-							.endpoint = 0x84,
-						},
-					}
-				},
-			},
-			{
-				.num_frontends = 1,
-				.fe = {
-					{
-						.frontend_attach = af9015_af9013_frontend_attach,
-						.tuner_attach    = af9015_tuner_attach,
-						.stream = {
-							.type = USB_BULK,
-							.count = 6,
-							.endpoint = 0x85,
-							.u = {
-								.bulk = {
-									.buffersize = TS_USB20_FRAME_SIZE,
-								}
-							}
-						},
-					}
-				},
-			}
-		},
-
-		.identify_state = af9015_identify_state,
-
-		.rc.core = {
-			.protocol         = RC_TYPE_NEC,
-			.module_name      = "af9015",
-			.rc_query         = af9015_rc_query,
-			.rc_interval      = AF9015_RC_INTERVAL,
-			.allowed_protos   = RC_TYPE_NEC,
-		},
-
-		.i2c_algo = &af9015_i2c_algo,
-
-		.num_device_descs = 10, /* check max from dvb-usb.h */
-		.devices = {
-			{
-				.name = "Xtensions XD-380",
-				.cold_ids = {
-					&af9015_usb_table[XTENSIONS_380U],
-				},
-			}, {
-				.name = "MSI DIGIVOX Duo",
-				.cold_ids = {
-					&af9015_usb_table[MSI_DIGIVOX_DUO],
-				},
-			}, {
-				.name = "Fujitsu-Siemens Slim Mobile USB DVB-T",
-				.cold_ids = {
-					&af9015_usb_table[AVERTV_VOLAR_X_REV2],
-				},
-			}, {
-				.name = "Telestar Starstick 2",
-				.cold_ids = {
-					&af9015_usb_table[TELESTAR_STARSTICK_2],
-				},
-			}, {
-				.name = "AVerMedia A309",
-				.cold_ids = {
-					&af9015_usb_table[AVERMEDIA_A309_USB],
-				},
-			}, {
-				.name = "MSI Digi VOX mini III",
-				.cold_ids = {
-					&af9015_usb_table[MSI_DIGIVOX_MINI_III],
-				},
-			}, {
-				.name = "KWorld USB DVB-T TV Stick II " \
-					"(VS-DVB-T 395U)",
-				.cold_ids = {
-					&af9015_usb_table[KWORLD_E396],
-					&af9015_usb_table[KWORLD_E39B],
-					&af9015_usb_table[KWORLD_E395],
-					&af9015_usb_table[KWORLD_E39A],
-				},
-			}, {
-				.name = "TrekStor DVB-T USB Stick",
-				.cold_ids = {
-					&af9015_usb_table[TREKSTOR_DVBT],
-				},
-			}, {
-				.name = "AverMedia AVerTV Volar Black HD " \
-					"(A850)",
-				.cold_ids = {
-					&af9015_usb_table[AVERTV_A850],
-				},
-			}, {
-				.name = "Sveon STV22 Dual USB DVB-T Tuner HDTV",
-				.cold_ids = {
-					&af9015_usb_table[SVEON_STV22],
-				},
-			},
-		}
-	}, {
-		.caps = DVB_USB_IS_AN_I2C_ADAPTER,
-
-		.usb_ctrl = DEVICE_SPECIFIC,
-		.download_firmware = af9015_download_firmware,
-		.firmware = "dvb-usb-af9015.fw",
-		.no_reconnect = 1,
-
-		.size_of_priv = sizeof(struct af9015_state),
-
-		.num_adapters = 2,
-		.adapter = {
-			{
-				.num_frontends = 1,
-				.fe = {
-					{
-						.caps = DVB_USB_ADAP_HAS_PID_FILTER |
-							DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
-
-						.pid_filter_count = 32,
-						.pid_filter       = af9015_pid_filter,
-						.pid_filter_ctrl  = af9015_pid_filter_ctrl,
-
-						.frontend_attach = af9015_af9013_frontend_attach,
-						.tuner_attach    = af9015_tuner_attach,
-						.stream = {
-							.type = USB_BULK,
-							.count = 6,
-							.endpoint = 0x84,
-						},
-					}
-				},
-			},
-			{
-				.num_frontends = 1,
-				.fe = {
-					{
-						.frontend_attach = af9015_af9013_frontend_attach,
-						.tuner_attach    = af9015_tuner_attach,
-						.stream = {
-							.type = USB_BULK,
-							.count = 6,
-							.endpoint = 0x85,
-							.u = {
-								.bulk = {
-									.buffersize = TS_USB20_FRAME_SIZE,
-								}
-							}
-						},
-					}
-				},
-			}
-		},
-
-		.identify_state = af9015_identify_state,
-
-		.rc.core = {
-			.protocol         = RC_TYPE_NEC,
-			.module_name      = "af9015",
-			.rc_query         = af9015_rc_query,
-			.rc_interval      = AF9015_RC_INTERVAL,
-			.allowed_protos   = RC_TYPE_NEC,
-		},
-
-		.i2c_algo = &af9015_i2c_algo,
-
-		.num_device_descs = 9, /* check max from dvb-usb.h */
-		.devices = {
-			{
-				.name = "AverMedia AVerTV Volar GPS 805 (A805)",
-				.cold_ids = {
-					&af9015_usb_table[AVERTV_A805],
-				},
-			}, {
-				.name = "Conceptronic USB2.0 DVB-T CTVDIGRCU " \
-					"V3.0",
-				.cold_ids = {
-					&af9015_usb_table[CONCEPTRONIC_CTVDIGRCU],
-				},
-			}, {
-				.name = "KWorld Digial MC-810",
-				.cold_ids = {
-					&af9015_usb_table[KWORLD_MC810],
-				},
-			}, {
-				.name = "Genius TVGo DVB-T03",
-				.cold_ids = {
-					&af9015_usb_table[GENIUS_TVGO_DVB_T03],
-				},
-			}, {
-				.name = "KWorld PlusTV DVB-T PCI Pro Card " \
-					"(DVB-T PC160-T)",
-				.cold_ids = {
-					&af9015_usb_table[KWORLD_PC160_T],
-				},
-			}, {
-				.name = "Sveon STV20 Tuner USB DVB-T HDTV",
-				.cold_ids = {
-					&af9015_usb_table[SVEON_STV20],
-				},
-			}, {
-				.name = "Leadtek WinFast DTV2000DS",
-				.cold_ids = {
-					&af9015_usb_table[WINFAST_DTV2000DS],
-				},
-			}, {
-				.name = "KWorld USB DVB-T Stick Mobile " \
-					"(UB383-T)",
-				.cold_ids = {
-					&af9015_usb_table[KWORLD_UB383_T],
-				},
-			}, {
-				.name = "AverMedia AVerTV Volar M (A815Mac)",
-				.cold_ids = {
-					&af9015_usb_table[AVERMEDIA_A815M],
-				},
-			},
-		}
-	},
-};
-
-static int af9015_usb_probe(struct usb_interface *intf,
-			    const struct usb_device_id *id)
-{
-	int ret = 0;
-	struct dvb_usb_device *d = NULL;
-	struct usb_device *udev = interface_to_usbdev(intf);
-	u8 i;
-
-	deb_info("%s: interface:%d\n", __func__,
-		intf->cur_altsetting->desc.bInterfaceNumber);
-
-	/* interface 0 is used by DVB-T receiver and
-	   interface 1 is for remote controller (HID) */
-	if (intf->cur_altsetting->desc.bInterfaceNumber == 0) {
-		ret = af9015_read_config(udev);
-		if (ret)
-			return ret;
-
-		for (i = 0; i < af9015_properties_count; i++) {
-			ret = dvb_usb_device_init(intf, &af9015_properties[i],
-				THIS_MODULE, &d, adapter_nr);
-			if (!ret)
-				break;
-			if (ret != -ENODEV)
-				return ret;
-		}
-		if (ret)
-			return ret;
-
-		if (d)
-			ret = af9015_init(d);
-	}
-
-	return ret;
-}
-
-/* usb specific object needed to register this driver with the usb subsystem */
-static struct usb_driver af9015_usb_driver = {
-	.name = "dvb_usb_af9015",
-	.probe = af9015_usb_probe,
-	.disconnect = dvb_usb_device_exit,
-	.id_table = af9015_usb_table,
-};
-
-module_usb_driver(af9015_usb_driver);
-
-MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
-MODULE_DESCRIPTION("Afatech AF9015 driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/af9015.h b/drivers/media/dvb/dvb-usb/af9015.h
deleted file mode 100644
index 2f68419..0000000
--- a/drivers/media/dvb/dvb-usb/af9015.h
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * DVB USB Linux driver for Afatech AF9015 DVB-T USB2.0 receiver
- *
- * Copyright (C) 2007 Antti Palosaari <crope@iki.fi>
- *
- * Thanks to Afatech who kindly provided information.
- *
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You 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_AF9015_H_
-#define _DVB_USB_AF9015_H_
-
-#define DVB_USB_LOG_PREFIX "af9015"
-#include "dvb-usb.h"
-
-#define deb_info(args...) dprintk(dvb_usb_af9015_debug, 0x01, args)
-#define deb_rc(args...)   dprintk(dvb_usb_af9015_debug, 0x02, args)
-#define deb_xfer(args...) dprintk(dvb_usb_af9015_debug, 0x04, args)
-#define deb_reg(args...)  dprintk(dvb_usb_af9015_debug, 0x08, args)
-#define deb_i2c(args...)  dprintk(dvb_usb_af9015_debug, 0x10, args)
-#define deb_fw(args...)   dprintk(dvb_usb_af9015_debug, 0x20, args)
-
-#define AF9015_I2C_EEPROM  0xa0
-#define AF9015_I2C_DEMOD   0x38
-#define AF9015_USB_TIMEOUT 2000
-
-/* EEPROM locations */
-#define AF9015_EEPROM_IR_MODE        0x18
-#define AF9015_EEPROM_IR_REMOTE_TYPE 0x34
-#define AF9015_EEPROM_TS_MODE        0x31
-#define AF9015_EEPROM_DEMOD2_I2C     0x32
-
-#define AF9015_EEPROM_SAW_BW1        0x35
-#define AF9015_EEPROM_XTAL_TYPE1     0x36
-#define AF9015_EEPROM_SPEC_INV1      0x37
-#define AF9015_EEPROM_IF1L           0x38
-#define AF9015_EEPROM_IF1H           0x39
-#define AF9015_EEPROM_MT2060_IF1L    0x3a
-#define AF9015_EEPROM_MT2060_IF1H    0x3b
-#define AF9015_EEPROM_TUNER_ID1      0x3c
-
-#define AF9015_EEPROM_SAW_BW2        0x45
-#define AF9015_EEPROM_XTAL_TYPE2     0x46
-#define AF9015_EEPROM_SPEC_INV2      0x47
-#define AF9015_EEPROM_IF2L           0x48
-#define AF9015_EEPROM_IF2H           0x49
-#define AF9015_EEPROM_MT2060_IF2L    0x4a
-#define AF9015_EEPROM_MT2060_IF2H    0x4b
-#define AF9015_EEPROM_TUNER_ID2      0x4c
-
-#define AF9015_EEPROM_OFFSET (AF9015_EEPROM_SAW_BW2 - AF9015_EEPROM_SAW_BW1)
-
-struct req_t {
-	u8  cmd;       /* [0] */
-	/*  seq */     /* [1] */
-	u8  i2c_addr;  /* [2] */
-	u16 addr;      /* [3|4] */
-	u8  mbox;      /* [5] */
-	u8  addr_len;  /* [6] */
-	u8  data_len;  /* [7] */
-	u8  *data;
-};
-
-enum af9015_cmd {
-	GET_CONFIG           = 0x10,
-	DOWNLOAD_FIRMWARE    = 0x11,
-	BOOT                 = 0x13,
-	READ_MEMORY          = 0x20,
-	WRITE_MEMORY         = 0x21,
-	READ_WRITE_I2C       = 0x22,
-	COPY_FIRMWARE        = 0x23,
-	RECONNECT_USB        = 0x5a,
-	WRITE_VIRTUAL_MEMORY = 0x26,
-	GET_IR_CODE          = 0x27,
-	READ_I2C,
-	WRITE_I2C,
-};
-
-enum af9015_ir_mode {
-	AF9015_IR_MODE_DISABLED = 0,
-	AF9015_IR_MODE_HID,
-	AF9015_IR_MODE_RLC,
-	AF9015_IR_MODE_RC6,
-	AF9015_IR_MODE_POLLING, /* just guess */
-};
-
-struct af9015_state {
-	u8 rc_repeat;
-	u32 rc_keycode;
-	u8 rc_last[4];
-
-	/* for demod callback override */
-	int (*set_frontend[2]) (struct dvb_frontend *fe);
-	int (*read_status[2]) (struct dvb_frontend *fe, fe_status_t *status);
-	int (*init[2]) (struct dvb_frontend *fe);
-	int (*sleep[2]) (struct dvb_frontend *fe);
-	int (*tuner_init[2]) (struct dvb_frontend *fe);
-	int (*tuner_sleep[2]) (struct dvb_frontend *fe);
-};
-
-struct af9015_config {
-	u8  dual_mode:1;
-	u16 mt2060_if1[2];
-	u16 firmware_size;
-	u16 firmware_checksum;
-	u32 eeprom_sum;
-};
-
-enum af9015_remote {
-	AF9015_REMOTE_NONE                    = 0,
-/* 1 */	AF9015_REMOTE_A_LINK_DTU_M,
-	AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3,
-	AF9015_REMOTE_MYGICTV_U718,
-	AF9015_REMOTE_DIGITTRADE_DVB_T,
-/* 5 */	AF9015_REMOTE_AVERMEDIA_KS,
-};
-
-#endif
diff --git a/drivers/media/dvb/dvb-usb/af9035.c b/drivers/media/dvb/dvb-usb/af9035.c
deleted file mode 100644
index e83b39d..0000000
--- a/drivers/media/dvb/dvb-usb/af9035.c
+++ /dev/null
@@ -1,1242 +0,0 @@
-/*
- * Afatech AF9035 DVB USB driver
- *
- * Copyright (C) 2009 Antti Palosaari <crope@iki.fi>
- * Copyright (C) 2012 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.,
- *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include "af9035.h"
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-static DEFINE_MUTEX(af9035_usb_mutex);
-static struct dvb_usb_device_properties af9035_properties[2];
-static int af9035_properties_count = ARRAY_SIZE(af9035_properties);
-
-static u16 af9035_checksum(const u8 *buf, size_t len)
-{
-	size_t i;
-	u16 checksum = 0;
-
-	for (i = 1; i < len; i++) {
-		if (i % 2)
-			checksum += buf[i] << 8;
-		else
-			checksum += buf[i];
-	}
-	checksum = ~checksum;
-
-	return checksum;
-}
-
-static int af9035_ctrl_msg(struct usb_device *udev, struct usb_req *req)
-{
-#define BUF_LEN 64
-#define REQ_HDR_LEN 4 /* send header size */
-#define ACK_HDR_LEN 3 /* rece header size */
-#define CHECKSUM_LEN 2
-#define USB_TIMEOUT 2000
-
-	int ret, msg_len, act_len;
-	u8 buf[BUF_LEN];
-	static u8 seq; /* packet sequence number */
-	u16 checksum, tmp_checksum;
-
-	/* buffer overflow check */
-	if (req->wlen > (BUF_LEN - REQ_HDR_LEN - CHECKSUM_LEN) ||
-		req->rlen > (BUF_LEN - ACK_HDR_LEN - CHECKSUM_LEN)) {
-		pr_debug("%s: too much data wlen=%d rlen=%d\n", __func__,
-				req->wlen, req->rlen);
-		return -EINVAL;
-	}
-
-	if (mutex_lock_interruptible(&af9035_usb_mutex) < 0)
-		return -EAGAIN;
-
-	buf[0] = REQ_HDR_LEN + req->wlen + CHECKSUM_LEN - 1;
-	buf[1] = req->mbox;
-	buf[2] = req->cmd;
-	buf[3] = seq++;
-	if (req->wlen)
-		memcpy(&buf[4], req->wbuf, req->wlen);
-
-	/* calc and add checksum */
-	checksum = af9035_checksum(buf, buf[0] - 1);
-	buf[buf[0] - 1] = (checksum >> 8);
-	buf[buf[0] - 0] = (checksum & 0xff);
-
-	msg_len = REQ_HDR_LEN + req->wlen + CHECKSUM_LEN ;
-
-	/* send req */
-	ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, 0x02), buf, msg_len,
-			&act_len, USB_TIMEOUT);
-	if (ret < 0)
-		err("bulk message failed=%d (%d/%d)", ret, msg_len, act_len);
-	else
-		if (act_len != msg_len)
-			ret = -EIO; /* all data is not send */
-	if (ret < 0)
-		goto err_mutex_unlock;
-
-	/* no ack for those packets */
-	if (req->cmd == CMD_FW_DL)
-		goto exit_mutex_unlock;
-
-	/* receive ack and data if read req */
-	msg_len = ACK_HDR_LEN + req->rlen + CHECKSUM_LEN;
-	ret = usb_bulk_msg(udev, usb_rcvbulkpipe(udev, 0x81), buf, msg_len,
-			&act_len, USB_TIMEOUT);
-	if (ret < 0) {
-		err("recv bulk message failed=%d", ret);
-		ret = -EIO;
-		goto err_mutex_unlock;
-	}
-
-	if (act_len != msg_len) {
-		err("recv bulk message truncated (%d != %d)", act_len, msg_len);
-		ret = -EIO;
-		goto err_mutex_unlock;
-	}
-
-	/* verify checksum */
-	checksum = af9035_checksum(buf, act_len - 2);
-	tmp_checksum = (buf[act_len - 2] << 8) | buf[act_len - 1];
-	if (tmp_checksum != checksum) {
-		err("%s: command=%02x checksum mismatch (%04x != %04x)",
-		    __func__, req->cmd, tmp_checksum, checksum);
-		ret = -EIO;
-		goto err_mutex_unlock;
-	}
-
-	/* check status */
-	if (buf[2]) {
-		pr_debug("%s: command=%02x failed fw error=%d\n", __func__,
-				req->cmd, buf[2]);
-		ret = -EIO;
-		goto err_mutex_unlock;
-	}
-
-	/* read request, copy returned data to return buf */
-	if (req->rlen)
-		memcpy(req->rbuf, &buf[ACK_HDR_LEN], req->rlen);
-
-err_mutex_unlock:
-exit_mutex_unlock:
-	mutex_unlock(&af9035_usb_mutex);
-
-	return ret;
-}
-
-/* write multiple registers */
-static int af9035_wr_regs(struct dvb_usb_device *d, u32 reg, u8 *val, int len)
-{
-	u8 wbuf[6 + len];
-	u8 mbox = (reg >> 16) & 0xff;
-	struct usb_req req = { CMD_MEM_WR, mbox, sizeof(wbuf), wbuf, 0, NULL };
-
-	wbuf[0] = len;
-	wbuf[1] = 2;
-	wbuf[2] = 0;
-	wbuf[3] = 0;
-	wbuf[4] = (reg >> 8) & 0xff;
-	wbuf[5] = (reg >> 0) & 0xff;
-	memcpy(&wbuf[6], val, len);
-
-	return af9035_ctrl_msg(d->udev, &req);
-}
-
-/* read multiple registers */
-static int af9035_rd_regs(struct dvb_usb_device *d, u32 reg, u8 *val, int len)
-{
-	u8 wbuf[] = { len, 2, 0, 0, (reg >> 8) & 0xff, reg & 0xff };
-	u8 mbox = (reg >> 16) & 0xff;
-	struct usb_req req = { CMD_MEM_RD, mbox, sizeof(wbuf), wbuf, len, val };
-
-	return af9035_ctrl_msg(d->udev, &req);
-}
-
-/* write single register */
-static int af9035_wr_reg(struct dvb_usb_device *d, u32 reg, u8 val)
-{
-	return af9035_wr_regs(d, reg, &val, 1);
-}
-
-/* read single register */
-static int af9035_rd_reg(struct dvb_usb_device *d, u32 reg, u8 *val)
-{
-	return af9035_rd_regs(d, reg, val, 1);
-}
-
-/* write single register with mask */
-static int af9035_wr_reg_mask(struct dvb_usb_device *d, u32 reg, u8 val,
-		u8 mask)
-{
-	int ret;
-	u8 tmp;
-
-	/* no need for read if whole reg is written */
-	if (mask != 0xff) {
-		ret = af9035_rd_regs(d, reg, &tmp, 1);
-		if (ret)
-			return ret;
-
-		val &= mask;
-		tmp &= ~mask;
-		val |= tmp;
-	}
-
-	return af9035_wr_regs(d, reg, &val, 1);
-}
-
-static int af9035_i2c_master_xfer(struct i2c_adapter *adap,
-		struct i2c_msg msg[], int num)
-{
-	struct dvb_usb_device *d = i2c_get_adapdata(adap);
-	struct state *state = d->priv;
-	int ret;
-
-	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
-		return -EAGAIN;
-
-	/*
-	 * I2C sub header is 5 bytes long. Meaning of those bytes are:
-	 * 0: data len
-	 * 1: I2C addr << 1
-	 * 2: reg addr len
-	 *    byte 3 and 4 can be used as reg addr
-	 * 3: reg addr MSB
-	 *    used when reg addr len is set to 2
-	 * 4: reg addr LSB
-	 *    used when reg addr len is set to 1 or 2
-	 *
-	 * For the simplify we do not use register addr at all.
-	 * NOTE: As a firmware knows tuner type there is very small possibility
-	 * there could be some tuner I2C hacks done by firmware and this may
-	 * lead problems if firmware expects those bytes are used.
-	 */
-	if (num == 2 && !(msg[0].flags & I2C_M_RD) &&
-			(msg[1].flags & I2C_M_RD)) {
-		if (msg[0].len > 40 || msg[1].len > 40) {
-			/* TODO: correct limits > 40 */
-			ret = -EOPNOTSUPP;
-		} else if (msg[0].addr == state->af9033_config[0].i2c_addr) {
-			/* integrated demod */
-			u32 reg = msg[0].buf[0] << 16 | msg[0].buf[1] << 8 |
-					msg[0].buf[2];
-			ret = af9035_rd_regs(d, reg, &msg[1].buf[0],
-					msg[1].len);
-		} else {
-			/* I2C */
-			u8 buf[5 + msg[0].len];
-			struct usb_req req = { CMD_I2C_RD, 0, sizeof(buf),
-					buf, msg[1].len, msg[1].buf };
-			buf[0] = msg[1].len;
-			buf[1] = msg[0].addr << 1;
-			buf[2] = 0x00; /* reg addr len */
-			buf[3] = 0x00; /* reg addr MSB */
-			buf[4] = 0x00; /* reg addr LSB */
-			memcpy(&buf[5], msg[0].buf, msg[0].len);
-			ret = af9035_ctrl_msg(d->udev, &req);
-		}
-	} else if (num == 1 && !(msg[0].flags & I2C_M_RD)) {
-		if (msg[0].len > 40) {
-			/* TODO: correct limits > 40 */
-			ret = -EOPNOTSUPP;
-		} else if (msg[0].addr == state->af9033_config[0].i2c_addr) {
-			/* integrated demod */
-			u32 reg = msg[0].buf[0] << 16 | msg[0].buf[1] << 8 |
-					msg[0].buf[2];
-			ret = af9035_wr_regs(d, reg, &msg[0].buf[3],
-					msg[0].len - 3);
-		} else {
-			/* I2C */
-			u8 buf[5 + msg[0].len];
-			struct usb_req req = { CMD_I2C_WR, 0, sizeof(buf), buf,
-					0, NULL };
-			buf[0] = msg[0].len;
-			buf[1] = msg[0].addr << 1;
-			buf[2] = 0x00; /* reg addr len */
-			buf[3] = 0x00; /* reg addr MSB */
-			buf[4] = 0x00; /* reg addr LSB */
-			memcpy(&buf[5], msg[0].buf, msg[0].len);
-			ret = af9035_ctrl_msg(d->udev, &req);
-		}
-	} else {
-		/*
-		 * We support only two kind of I2C transactions:
-		 * 1) 1 x read + 1 x write
-		 * 2) 1 x write
-		 */
-		ret = -EOPNOTSUPP;
-	}
-
-	mutex_unlock(&d->i2c_mutex);
-
-	if (ret < 0)
-		return ret;
-	else
-		return num;
-}
-
-static u32 af9035_i2c_functionality(struct i2c_adapter *adapter)
-{
-	return I2C_FUNC_I2C;
-}
-
-static struct i2c_algorithm af9035_i2c_algo = {
-	.master_xfer = af9035_i2c_master_xfer,
-	.functionality = af9035_i2c_functionality,
-};
-
-#define AF9035_POLL 250
-static int af9035_rc_query(struct dvb_usb_device *d)
-{
-	unsigned int key;
-	unsigned char b[4];
-	int ret;
-	struct usb_req req = { CMD_IR_GET, 0, 0, NULL, 4, b };
-
-	ret = af9035_ctrl_msg(d->udev, &req);
-	if (ret < 0)
-		goto err;
-
-	if ((b[2] + b[3]) == 0xff) {
-		if ((b[0] + b[1]) == 0xff) {
-			/* NEC */
-			key = b[0] << 8 | b[2];
-		} else {
-			/* ext. NEC */
-			key = b[0] << 16 | b[1] << 8 | b[2];
-		}
-	} else {
-		key = b[0] << 24 | b[1] << 16 | b[2] << 8 | b[3];
-	}
-
-	rc_keydown(d->rc_dev, key, 0);
-
-err:
-	/* ignore errors */
-	return 0;
-}
-
-static int af9035_init(struct dvb_usb_device *d)
-{
-	struct state *state = d->priv;
-	int ret, i;
-	u16 frame_size = 87 * 188 / 4;
-	u8  packet_size = 512 / 4;
-	struct reg_val_mask tab[] = {
-		{ 0x80f99d, 0x01, 0x01 },
-		{ 0x80f9a4, 0x01, 0x01 },
-		{ 0x00dd11, 0x00, 0x20 },
-		{ 0x00dd11, 0x00, 0x40 },
-		{ 0x00dd13, 0x00, 0x20 },
-		{ 0x00dd13, 0x00, 0x40 },
-		{ 0x00dd11, 0x20, 0x20 },
-		{ 0x00dd88, (frame_size >> 0) & 0xff, 0xff},
-		{ 0x00dd89, (frame_size >> 8) & 0xff, 0xff},
-		{ 0x00dd0c, packet_size, 0xff},
-		{ 0x00dd11, state->dual_mode << 6, 0x40 },
-		{ 0x00dd8a, (frame_size >> 0) & 0xff, 0xff},
-		{ 0x00dd8b, (frame_size >> 8) & 0xff, 0xff},
-		{ 0x00dd0d, packet_size, 0xff },
-		{ 0x80f9a3, 0x00, 0x01 },
-		{ 0x80f9cd, 0x00, 0x01 },
-		{ 0x80f99d, 0x00, 0x01 },
-		{ 0x80f9a4, 0x00, 0x01 },
-	};
-
-	pr_debug("%s: USB speed=%d frame_size=%04x packet_size=%02x\n",
-		__func__, d->udev->speed, frame_size, packet_size);
-
-	/* init endpoints */
-	for (i = 0; i < ARRAY_SIZE(tab); i++) {
-		ret = af9035_wr_reg_mask(d, tab[i].reg, tab[i].val,
-				tab[i].mask);
-		if (ret < 0)
-			goto err;
-	}
-
-	return 0;
-
-err:
-	pr_debug("%s: failed=%d\n", __func__, ret);
-
-	return ret;
-}
-
-static int af9035_identify_state(struct usb_device *udev,
-		struct dvb_usb_device_properties *props,
-		struct dvb_usb_device_description **desc,
-		int *cold)
-{
-	int ret;
-	u8 wbuf[1] = { 1 };
-	u8 rbuf[4];
-	struct usb_req req = { CMD_FW_QUERYINFO, 0, sizeof(wbuf), wbuf,
-			sizeof(rbuf), rbuf };
-
-	ret = af9035_ctrl_msg(udev, &req);
-	if (ret < 0)
-		goto err;
-
-	pr_debug("%s: reply=%02x %02x %02x %02x\n", __func__,
-		rbuf[0], rbuf[1], rbuf[2], rbuf[3]);
-	if (rbuf[0] || rbuf[1] || rbuf[2] || rbuf[3])
-		*cold = 0;
-	else
-		*cold = 1;
-
-	return 0;
-
-err:
-	pr_debug("%s: failed=%d\n", __func__, ret);
-
-	return ret;
-}
-
-static int af9035_download_firmware(struct usb_device *udev,
-		const struct firmware *fw)
-{
-	int ret, i, j, len;
-	u8 wbuf[1];
-	u8 rbuf[4];
-	struct usb_req req = { 0, 0, 0, NULL, 0, NULL };
-	struct usb_req req_fw_dl = { CMD_FW_DL, 0, 0, wbuf, 0, NULL };
-	struct usb_req req_fw_ver = { CMD_FW_QUERYINFO, 0, 1, wbuf, 4, rbuf } ;
-	u8 hdr_core;
-	u16 hdr_addr, hdr_data_len, hdr_checksum;
-	#define MAX_DATA 58
-	#define HDR_SIZE 7
-
-	/*
-	 * Thanks to Daniel Glöckner <daniel-gl@gmx.net> about that info!
-	 *
-	 * byte 0: MCS 51 core
-	 *  There are two inside the AF9035 (1=Link and 2=OFDM) with separate
-	 *  address spaces
-	 * byte 1-2: Big endian destination address
-	 * byte 3-4: Big endian number of data bytes following the header
-	 * byte 5-6: Big endian header checksum, apparently ignored by the chip
-	 *  Calculated as ~(h[0]*256+h[1]+h[2]*256+h[3]+h[4]*256)
-	 */
-
-	for (i = fw->size; i > HDR_SIZE;) {
-		hdr_core = fw->data[fw->size - i + 0];
-		hdr_addr = fw->data[fw->size - i + 1] << 8;
-		hdr_addr |= fw->data[fw->size - i + 2] << 0;
-		hdr_data_len = fw->data[fw->size - i + 3] << 8;
-		hdr_data_len |= fw->data[fw->size - i + 4] << 0;
-		hdr_checksum = fw->data[fw->size - i + 5] << 8;
-		hdr_checksum |= fw->data[fw->size - i + 6] << 0;
-
-		pr_debug("%s: core=%d addr=%04x data_len=%d checksum=%04x\n",
-				__func__, hdr_core, hdr_addr, hdr_data_len,
-				hdr_checksum);
-
-		if (((hdr_core != 1) && (hdr_core != 2)) ||
-				(hdr_data_len > i)) {
-			pr_debug("%s: bad firmware\n", __func__);
-			break;
-		}
-
-		/* download begin packet */
-		req.cmd = CMD_FW_DL_BEGIN;
-		ret = af9035_ctrl_msg(udev, &req);
-		if (ret < 0)
-			goto err;
-
-		/* download firmware packet(s) */
-		for (j = HDR_SIZE + hdr_data_len; j > 0; j -= MAX_DATA) {
-			len = j;
-			if (len > MAX_DATA)
-				len = MAX_DATA;
-			req_fw_dl.wlen = len;
-			req_fw_dl.wbuf = (u8 *) &fw->data[fw->size - i +
-					HDR_SIZE + hdr_data_len - j];
-			ret = af9035_ctrl_msg(udev, &req_fw_dl);
-			if (ret < 0)
-				goto err;
-		}
-
-		/* download end packet */
-		req.cmd = CMD_FW_DL_END;
-		ret = af9035_ctrl_msg(udev, &req);
-		if (ret < 0)
-			goto err;
-
-		i -= hdr_data_len + HDR_SIZE;
-
-		pr_debug("%s: data uploaded=%zu\n", __func__, fw->size - i);
-	}
-
-	/* firmware loaded, request boot */
-	req.cmd = CMD_FW_BOOT;
-	ret = af9035_ctrl_msg(udev, &req);
-	if (ret < 0)
-		goto err;
-
-	/* ensure firmware starts */
-	wbuf[0] = 1;
-	ret = af9035_ctrl_msg(udev, &req_fw_ver);
-	if (ret < 0)
-		goto err;
-
-	if (!(rbuf[0] || rbuf[1] || rbuf[2] || rbuf[3])) {
-		info("firmware did not run");
-		ret = -ENODEV;
-		goto err;
-	}
-
-	info("firmware version=%d.%d.%d.%d", rbuf[0], rbuf[1], rbuf[2],
-			rbuf[3]);
-
-	return 0;
-
-err:
-	pr_debug("%s: failed=%d\n", __func__, ret);
-
-	return ret;
-}
-
-static int af9035_download_firmware_it9135(struct usb_device *udev,
-		const struct firmware *fw)
-{
-	int ret, i, i_prev;
-	u8 wbuf[1];
-	u8 rbuf[4];
-	struct usb_req req = { 0, 0, 0, NULL, 0, NULL };
-	struct usb_req req_fw_dl = { CMD_FW_SCATTER_WR, 0, 0, NULL, 0, NULL };
-	struct usb_req req_fw_ver = { CMD_FW_QUERYINFO, 0, 1, wbuf, 4, rbuf } ;
-	#define HDR_SIZE 7
-
-	/*
-	 * There seems to be following firmware header. Meaning of bytes 0-3
-	 * is unknown.
-	 *
-	 * 0: 3
-	 * 1: 0, 1
-	 * 2: 0
-	 * 3: 1, 2, 3
-	 * 4: addr MSB
-	 * 5: addr LSB
-	 * 6: count of data bytes ?
-	 */
-
-	for (i = HDR_SIZE, i_prev = 0; i <= fw->size; i++) {
-		if (i == fw->size ||
-				(fw->data[i + 0] == 0x03 &&
-				(fw->data[i + 1] == 0x00 ||
-				fw->data[i + 1] == 0x01) &&
-				fw->data[i + 2] == 0x00)) {
-			req_fw_dl.wlen = i - i_prev;
-			req_fw_dl.wbuf = (u8 *) &fw->data[i_prev];
-			i_prev = i;
-			ret = af9035_ctrl_msg(udev, &req_fw_dl);
-			if (ret < 0)
-				goto err;
-
-			pr_debug("%s: data uploaded=%d\n", __func__, i);
-		}
-	}
-
-	/* firmware loaded, request boot */
-	req.cmd = CMD_FW_BOOT;
-	ret = af9035_ctrl_msg(udev, &req);
-	if (ret < 0)
-		goto err;
-
-	/* ensure firmware starts */
-	wbuf[0] = 1;
-	ret = af9035_ctrl_msg(udev, &req_fw_ver);
-	if (ret < 0)
-		goto err;
-
-	if (!(rbuf[0] || rbuf[1] || rbuf[2] || rbuf[3])) {
-		info("firmware did not run");
-		ret = -ENODEV;
-		goto err;
-	}
-
-	info("firmware version=%d.%d.%d.%d", rbuf[0], rbuf[1], rbuf[2],
-			rbuf[3]);
-
-	return 0;
-
-err:
-	pr_debug("%s: failed=%d\n", __func__, ret);
-
-	return ret;
-}
-
-/* abuse that callback as there is no better one for reading eeprom */
-static int af9035_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
-{
-	struct state *state = d->priv;
-	int ret, i, eeprom_shift = 0;
-	u8 tmp;
-	u16 tmp16;
-
-	/* check if there is dual tuners */
-	ret = af9035_rd_reg(d, EEPROM_DUAL_MODE, &tmp);
-	if (ret < 0)
-		goto err;
-
-	state->dual_mode = tmp;
-	pr_debug("%s: dual mode=%d\n", __func__, state->dual_mode);
-
-	for (i = 0; i < af9035_properties[0].num_adapters; i++) {
-		/* tuner */
-		ret = af9035_rd_reg(d, EEPROM_1_TUNER_ID + eeprom_shift, &tmp);
-		if (ret < 0)
-			goto err;
-
-		state->af9033_config[i].tuner = tmp;
-		pr_debug("%s: [%d]tuner=%02x\n", __func__, i, tmp);
-
-		switch (tmp) {
-		case AF9033_TUNER_TUA9001:
-		case AF9033_TUNER_FC0011:
-		case AF9033_TUNER_MXL5007T:
-		case AF9033_TUNER_TDA18218:
-			state->af9033_config[i].spec_inv = 1;
-			break;
-		default:
-			warn("tuner ID=%02x not supported, please report!",
-				tmp);
-		};
-
-		/* tuner IF frequency */
-		ret = af9035_rd_reg(d, EEPROM_1_IFFREQ_L + eeprom_shift, &tmp);
-		if (ret < 0)
-			goto err;
-
-		tmp16 = tmp;
-
-		ret = af9035_rd_reg(d, EEPROM_1_IFFREQ_H + eeprom_shift, &tmp);
-		if (ret < 0)
-			goto err;
-
-		tmp16 |= tmp << 8;
-
-		pr_debug("%s: [%d]IF=%d\n", __func__, i, tmp16);
-
-		eeprom_shift = 0x10; /* shift for the 2nd tuner params */
-	}
-
-	/* get demod clock */
-	ret = af9035_rd_reg(d, 0x00d800, &tmp);
-	if (ret < 0)
-		goto err;
-
-	tmp = (tmp >> 0) & 0x0f;
-
-	for (i = 0; i < af9035_properties[0].num_adapters; i++)
-		state->af9033_config[i].clock = clock_lut[tmp];
-
-	ret = af9035_rd_reg(d, EEPROM_IR_MODE, &tmp);
-	if (ret < 0)
-		goto err;
-	pr_debug("%s: ir_mode=%02x\n", __func__, tmp);
-
-	/* don't activate rc if in HID mode or if not available */
-	if (tmp == 5) {
-		ret = af9035_rd_reg(d, EEPROM_IR_TYPE, &tmp);
-		if (ret < 0)
-			goto err;
-		pr_debug("%s: ir_type=%02x\n", __func__, tmp);
-
-		switch (tmp) {
-		case 0: /* NEC */
-		default:
-			d->props.rc.core.protocol = RC_TYPE_NEC;
-			d->props.rc.core.allowed_protos = RC_TYPE_NEC;
-			break;
-		case 1: /* RC6 */
-			d->props.rc.core.protocol = RC_TYPE_RC6;
-			d->props.rc.core.allowed_protos = RC_TYPE_RC6;
-			break;
-		}
-		d->props.rc.core.rc_query = af9035_rc_query;
-	}
-
-	return 0;
-
-err:
-	pr_debug("%s: failed=%d\n", __func__, ret);
-
-	return ret;
-}
-
-/* abuse that callback as there is no better one for reading eeprom */
-static int af9035_read_mac_address_it9135(struct dvb_usb_device *d, u8 mac[6])
-{
-	struct state *state = d->priv;
-	int ret, i;
-	u8 tmp;
-
-	state->dual_mode = false;
-
-	/* get demod clock */
-	ret = af9035_rd_reg(d, 0x00d800, &tmp);
-	if (ret < 0)
-		goto err;
-
-	tmp = (tmp >> 0) & 0x0f;
-
-	for (i = 0; i < af9035_properties[0].num_adapters; i++)
-		state->af9033_config[i].clock = clock_lut_it9135[tmp];
-
-	return 0;
-
-err:
-	pr_debug("%s: failed=%d\n", __func__, ret);
-
-	return ret;
-}
-
-static int af9035_fc0011_tuner_callback(struct dvb_usb_device *d,
-		int cmd, int arg)
-{
-	int ret;
-
-	switch (cmd) {
-	case FC0011_FE_CALLBACK_POWER:
-		/* Tuner enable */
-		ret = af9035_wr_reg_mask(d, 0xd8eb, 1, 1);
-		if (ret < 0)
-			goto err;
-
-		ret = af9035_wr_reg_mask(d, 0xd8ec, 1, 1);
-		if (ret < 0)
-			goto err;
-
-		ret = af9035_wr_reg_mask(d, 0xd8ed, 1, 1);
-		if (ret < 0)
-			goto err;
-
-		/* LED */
-		ret = af9035_wr_reg_mask(d, 0xd8d0, 1, 1);
-		if (ret < 0)
-			goto err;
-
-		ret = af9035_wr_reg_mask(d, 0xd8d1, 1, 1);
-		if (ret < 0)
-			goto err;
-
-		usleep_range(10000, 50000);
-		break;
-	case FC0011_FE_CALLBACK_RESET:
-		ret = af9035_wr_reg(d, 0xd8e9, 1);
-		if (ret < 0)
-			goto err;
-
-		ret = af9035_wr_reg(d, 0xd8e8, 1);
-		if (ret < 0)
-			goto err;
-
-		ret = af9035_wr_reg(d, 0xd8e7, 1);
-		if (ret < 0)
-			goto err;
-
-		usleep_range(10000, 20000);
-
-		ret = af9035_wr_reg(d, 0xd8e7, 0);
-		if (ret < 0)
-			goto err;
-
-		usleep_range(10000, 20000);
-		break;
-	default:
-		ret = -EINVAL;
-		goto err;
-	}
-
-	return 0;
-
-err:
-	pr_debug("%s: failed=%d\n", __func__, ret);
-
-	return ret;
-}
-
-static int af9035_tuner_callback(struct dvb_usb_device *d, int cmd, int arg)
-{
-	struct state *state = d->priv;
-
-	switch (state->af9033_config[0].tuner) {
-	case AF9033_TUNER_FC0011:
-		return af9035_fc0011_tuner_callback(d, cmd, arg);
-	default:
-		break;
-	}
-
-	return -ENODEV;
-}
-
-static int af9035_frontend_callback(void *adapter_priv, int component,
-				    int cmd, int arg)
-{
-	struct i2c_adapter *adap = adapter_priv;
-	struct dvb_usb_device *d = i2c_get_adapdata(adap);
-
-	switch (component) {
-	case DVB_FRONTEND_COMPONENT_TUNER:
-		return af9035_tuner_callback(d, cmd, arg);
-	default:
-		break;
-	}
-
-	return -EINVAL;
-}
-
-static int af9035_frontend_attach(struct dvb_usb_adapter *adap)
-{
-	struct state *state = adap->dev->priv;
-	int ret;
-
-	if (!state->af9033_config[adap->id].tuner) {
-		/* unsupported tuner */
-		ret = -ENODEV;
-		goto err;
-	}
-
-	if (adap->id == 0) {
-		state->af9033_config[0].ts_mode = AF9033_TS_MODE_USB;
-		state->af9033_config[1].ts_mode = AF9033_TS_MODE_SERIAL;
-
-		ret = af9035_wr_reg(adap->dev, 0x00417f,
-				state->af9033_config[1].i2c_addr);
-		if (ret < 0)
-			goto err;
-
-		ret = af9035_wr_reg(adap->dev, 0x00d81a,
-				state->dual_mode);
-		if (ret < 0)
-			goto err;
-	}
-
-	/* attach demodulator */
-	adap->fe_adap[0].fe = dvb_attach(af9033_attach,
-			&state->af9033_config[adap->id], &adap->dev->i2c_adap);
-	if (adap->fe_adap[0].fe == NULL) {
-		ret = -ENODEV;
-		goto err;
-	}
-
-	/* disable I2C-gate */
-	adap->fe_adap[0].fe->ops.i2c_gate_ctrl = NULL;
-	adap->fe_adap[0].fe->callback = af9035_frontend_callback;
-
-	return 0;
-
-err:
-	pr_debug("%s: failed=%d\n", __func__, ret);
-
-	return ret;
-}
-
-static struct tua9001_config af9035_tua9001_config = {
-	.i2c_addr = 0x60,
-};
-
-static const struct fc0011_config af9035_fc0011_config = {
-	.i2c_address = 0x60,
-};
-
-static struct mxl5007t_config af9035_mxl5007t_config = {
-	.xtal_freq_hz = MxL_XTAL_24_MHZ,
-	.if_freq_hz = MxL_IF_4_57_MHZ,
-	.invert_if = 0,
-	.loop_thru_enable = 0,
-	.clk_out_enable = 0,
-	.clk_out_amp = MxL_CLKOUT_AMP_0_94V,
-};
-
-static struct tda18218_config af9035_tda18218_config = {
-	.i2c_address = 0x60,
-	.i2c_wr_max = 21,
-};
-
-static int af9035_tuner_attach(struct dvb_usb_adapter *adap)
-{
-	struct state *state = adap->dev->priv;
-	int ret;
-	struct dvb_frontend *fe;
-
-	switch (state->af9033_config[adap->id].tuner) {
-	case AF9033_TUNER_TUA9001:
-		/* AF9035 gpiot3 = TUA9001 RESETN
-		   AF9035 gpiot2 = TUA9001 RXEN */
-
-		/* configure gpiot2 and gpiot2 as output */
-		ret = af9035_wr_reg_mask(adap->dev, 0x00d8ec, 0x01, 0x01);
-		if (ret < 0)
-			goto err;
-
-		ret = af9035_wr_reg_mask(adap->dev, 0x00d8ed, 0x01, 0x01);
-		if (ret < 0)
-			goto err;
-
-		ret = af9035_wr_reg_mask(adap->dev, 0x00d8e8, 0x01, 0x01);
-		if (ret < 0)
-			goto err;
-
-		ret = af9035_wr_reg_mask(adap->dev, 0x00d8e9, 0x01, 0x01);
-		if (ret < 0)
-			goto err;
-
-		/* reset tuner */
-		ret = af9035_wr_reg_mask(adap->dev, 0x00d8e7, 0x00, 0x01);
-		if (ret < 0)
-			goto err;
-
-		usleep_range(2000, 20000);
-
-		ret = af9035_wr_reg_mask(adap->dev, 0x00d8e7, 0x01, 0x01);
-		if (ret < 0)
-			goto err;
-
-		/* activate tuner RX */
-		/* TODO: use callback for TUA9001 RXEN */
-		ret = af9035_wr_reg_mask(adap->dev, 0x00d8eb, 0x01, 0x01);
-		if (ret < 0)
-			goto err;
-
-		/* attach tuner */
-		fe = dvb_attach(tua9001_attach, adap->fe_adap[0].fe,
-				&adap->dev->i2c_adap, &af9035_tua9001_config);
-		break;
-	case AF9033_TUNER_FC0011:
-		fe = dvb_attach(fc0011_attach, adap->fe_adap[0].fe,
-				&adap->dev->i2c_adap, &af9035_fc0011_config);
-		break;
-	case AF9033_TUNER_MXL5007T:
-		ret = af9035_wr_reg(adap->dev, 0x00d8e0, 1);
-		if (ret < 0)
-			goto err;
-		ret = af9035_wr_reg(adap->dev, 0x00d8e1, 1);
-		if (ret < 0)
-			goto err;
-		ret = af9035_wr_reg(adap->dev, 0x00d8df, 0);
-		if (ret < 0)
-			goto err;
-
-		msleep(30);
-
-		ret = af9035_wr_reg(adap->dev, 0x00d8df, 1);
-		if (ret < 0)
-			goto err;
-
-		msleep(300);
-
-		ret = af9035_wr_reg(adap->dev, 0x00d8c0, 1);
-		if (ret < 0)
-			goto err;
-		ret = af9035_wr_reg(adap->dev, 0x00d8c1, 1);
-		if (ret < 0)
-			goto err;
-		ret = af9035_wr_reg(adap->dev, 0x00d8bf, 0);
-		if (ret < 0)
-			goto err;
-		ret = af9035_wr_reg(adap->dev, 0x00d8b4, 1);
-		if (ret < 0)
-			goto err;
-		ret = af9035_wr_reg(adap->dev, 0x00d8b5, 1);
-		if (ret < 0)
-			goto err;
-		ret = af9035_wr_reg(adap->dev, 0x00d8b3, 1);
-		if (ret < 0)
-			goto err;
-
-		/* attach tuner */
-		fe = dvb_attach(mxl5007t_attach, adap->fe_adap[0].fe,
-				&adap->dev->i2c_adap, 0x60, &af9035_mxl5007t_config);
-		break;
-	case AF9033_TUNER_TDA18218:
-		/* attach tuner */
-		fe = dvb_attach(tda18218_attach, adap->fe_adap[0].fe,
-				&adap->dev->i2c_adap, &af9035_tda18218_config);
-		break;
-	default:
-		fe = NULL;
-	}
-
-	if (fe == NULL) {
-		ret = -ENODEV;
-		goto err;
-	}
-
-	return 0;
-
-err:
-	pr_debug("%s: failed=%d\n", __func__, ret);
-
-	return ret;
-}
-
-enum af9035_id_entry {
-	AF9035_15A4_9035,
-	AF9035_15A4_1000,
-	AF9035_15A4_1001,
-	AF9035_15A4_1002,
-	AF9035_15A4_1003,
-	AF9035_0CCD_0093,
-	AF9035_07CA_A835,
-	AF9035_07CA_B835,
-	AF9035_07CA_1867,
-	AF9035_07CA_A867,
-	AF9035_07CA_0825,
-};
-
-static struct usb_device_id af9035_id[] = {
-	[AF9035_15A4_9035] = {
-		USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_9035)},
-	[AF9035_15A4_1000] = {
-		USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_1000)},
-	[AF9035_15A4_1001] = {
-		USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_1001)},
-	[AF9035_15A4_1002] = {
-		USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_1002)},
-	[AF9035_15A4_1003] = {
-		USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_1003)},
-	[AF9035_0CCD_0093] = {
-		USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_STICK)},
-	[AF9035_07CA_A835] = {
-		USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A835)},
-	[AF9035_07CA_B835] = {
-		USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_B835)},
-	[AF9035_07CA_1867] = {
-		USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_1867)},
-	[AF9035_07CA_A867] = {
-		USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A867)},
-	[AF9035_07CA_0825] = {
-		USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_TWINSTAR)},
-	{},
-};
-
-MODULE_DEVICE_TABLE(usb, af9035_id);
-
-static struct dvb_usb_device_properties af9035_properties[] = {
-	{
-		.caps = DVB_USB_IS_AN_I2C_ADAPTER,
-
-		.usb_ctrl = DEVICE_SPECIFIC,
-		.download_firmware = af9035_download_firmware,
-		.firmware = "dvb-usb-af9035-02.fw",
-		.no_reconnect = 1,
-
-		.size_of_priv = sizeof(struct state),
-
-		.num_adapters = 1,
-		.adapter = {
-			{
-				.num_frontends = 1,
-				.fe = {
-					{
-						.frontend_attach = af9035_frontend_attach,
-						.tuner_attach = af9035_tuner_attach,
-						.stream = {
-							.type = USB_BULK,
-							.count = 6,
-							.endpoint = 0x84,
-							.u = {
-								.bulk = {
-									.buffersize = (87 * 188),
-								}
-							}
-						}
-					}
-				}
-			}
-		},
-
-		.identify_state = af9035_identify_state,
-		.read_mac_address = af9035_read_mac_address,
-
-		.i2c_algo = &af9035_i2c_algo,
-
-		.rc.core = {
-			.protocol       = RC_TYPE_UNKNOWN,
-			.module_name    = "af9035",
-			.rc_query       = NULL,
-			.rc_interval    = AF9035_POLL,
-			.allowed_protos = RC_TYPE_UNKNOWN,
-			.rc_codes       = RC_MAP_EMPTY,
-		},
-		.num_device_descs = 5,
-		.devices = {
-			{
-				.name = "Afatech AF9035 reference design",
-				.cold_ids = {
-					&af9035_id[AF9035_15A4_9035],
-					&af9035_id[AF9035_15A4_1000],
-					&af9035_id[AF9035_15A4_1001],
-					&af9035_id[AF9035_15A4_1002],
-					&af9035_id[AF9035_15A4_1003],
-				},
-			}, {
-				.name = "TerraTec Cinergy T Stick",
-				.cold_ids = {
-					&af9035_id[AF9035_0CCD_0093],
-				},
-			}, {
-				.name = "AVerMedia AVerTV Volar HD/PRO (A835)",
-				.cold_ids = {
-					&af9035_id[AF9035_07CA_A835],
-					&af9035_id[AF9035_07CA_B835],
-				},
-			}, {
-				.name = "AVerMedia HD Volar (A867)",
-				.cold_ids = {
-					&af9035_id[AF9035_07CA_1867],
-					&af9035_id[AF9035_07CA_A867],
-				},
-			}, {
-				.name = "AVerMedia Twinstar (A825)",
-				.cold_ids = {
-					&af9035_id[AF9035_07CA_0825],
-				},
-			},
-		}
-	},
-	{
-		.caps = DVB_USB_IS_AN_I2C_ADAPTER,
-
-		.usb_ctrl = DEVICE_SPECIFIC,
-		.download_firmware = af9035_download_firmware_it9135,
-		.firmware = "dvb-usb-it9135-01.fw",
-		.no_reconnect = 1,
-
-		.size_of_priv = sizeof(struct state),
-
-		.num_adapters = 1,
-		.adapter = {
-			{
-				.num_frontends = 1,
-				.fe = {
-					{
-						.frontend_attach = af9035_frontend_attach,
-						.tuner_attach = af9035_tuner_attach,
-						.stream = {
-							.type = USB_BULK,
-							.count = 6,
-							.endpoint = 0x84,
-							.u = {
-								.bulk = {
-									.buffersize = (87 * 188),
-								}
-							}
-						}
-					}
-				}
-			}
-		},
-
-		.identify_state = af9035_identify_state,
-		.read_mac_address = af9035_read_mac_address_it9135,
-
-		.i2c_algo = &af9035_i2c_algo,
-
-		.num_device_descs = 0, /* disabled as no support for IT9135 */
-		.devices = {
-			{
-				.name = "ITE Tech. IT9135 reference design",
-			},
-		}
-	},
-};
-
-static int af9035_usb_probe(struct usb_interface *intf,
-			    const struct usb_device_id *id)
-{
-	int ret, i;
-	struct dvb_usb_device *d = NULL;
-	struct usb_device *udev;
-	bool found;
-
-	pr_debug("%s: interface=%d\n", __func__,
-			intf->cur_altsetting->desc.bInterfaceNumber);
-
-	/* interface 0 is used by DVB-T receiver and
-	   interface 1 is for remote controller (HID) */
-	if (intf->cur_altsetting->desc.bInterfaceNumber != 0)
-		return 0;
-
-	/* Dynamic USB ID support. Replaces first device ID with current one. */
-	udev = interface_to_usbdev(intf);
-
-	for (i = 0, found = false; i < ARRAY_SIZE(af9035_id) - 1; i++) {
-		if (af9035_id[i].idVendor ==
-				le16_to_cpu(udev->descriptor.idVendor) &&
-				af9035_id[i].idProduct ==
-				le16_to_cpu(udev->descriptor.idProduct)) {
-			found = true;
-			break;
-		}
-	}
-
-	if (!found) {
-		pr_debug("%s: using dynamic ID %04x:%04x\n", __func__,
-				le16_to_cpu(udev->descriptor.idVendor),
-				le16_to_cpu(udev->descriptor.idProduct));
-		af9035_properties[0].devices[0].cold_ids[0]->idVendor =
-				le16_to_cpu(udev->descriptor.idVendor);
-		af9035_properties[0].devices[0].cold_ids[0]->idProduct =
-				le16_to_cpu(udev->descriptor.idProduct);
-	}
-
-
-	for (i = 0; i < af9035_properties_count; i++) {
-		ret = dvb_usb_device_init(intf, &af9035_properties[i],
-				THIS_MODULE, &d, adapter_nr);
-
-		if (ret == -ENODEV)
-			continue;
-		else
-			break;
-	}
-
-	if (ret < 0)
-		goto err;
-
-	if (d) {
-		ret = af9035_init(d);
-		if (ret < 0)
-			goto err;
-	}
-
-	return 0;
-
-err:
-	pr_debug("%s: failed=%d\n", __func__, ret);
-
-	return ret;
-}
-
-/* usb specific object needed to register this driver with the usb subsystem */
-static struct usb_driver af9035_usb_driver = {
-	.name = "dvb_usb_af9035",
-	.probe = af9035_usb_probe,
-	.disconnect = dvb_usb_device_exit,
-	.id_table = af9035_id,
-};
-
-module_usb_driver(af9035_usb_driver);
-
-MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
-MODULE_DESCRIPTION("Afatech AF9035 driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/af9035.h b/drivers/media/dvb/dvb-usb/af9035.h
deleted file mode 100644
index 481a1a4..0000000
--- a/drivers/media/dvb/dvb-usb/af9035.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Afatech AF9035 DVB USB driver
- *
- * Copyright (C) 2009 Antti Palosaari <crope@iki.fi>
- * Copyright (C) 2012 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.,
- *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef AF9035_H
-#define AF9035_H
-
-/* prefix for dvb-usb log writings */
-#define DVB_USB_LOG_PREFIX "af9035"
-
-#include "dvb-usb.h"
-#include "af9033.h"
-#include "tua9001.h"
-#include "fc0011.h"
-#include "mxl5007t.h"
-#include "tda18218.h"
-
-struct reg_val {
-	u32 reg;
-	u8  val;
-};
-
-struct reg_val_mask {
-	u32 reg;
-	u8  val;
-	u8  mask;
-};
-
-struct usb_req {
-	u8  cmd;
-	u8  mbox;
-	u8  wlen;
-	u8  *wbuf;
-	u8  rlen;
-	u8  *rbuf;
-};
-
-struct state {
-	bool dual_mode;
-
-	struct af9033_config af9033_config[2];
-};
-
-u32 clock_lut[] = {
-	20480000, /*      FPGA */
-	16384000, /* 16.38 MHz */
-	20480000, /* 20.48 MHz */
-	36000000, /* 36.00 MHz */
-	30000000, /* 30.00 MHz */
-	26000000, /* 26.00 MHz */
-	28000000, /* 28.00 MHz */
-	32000000, /* 32.00 MHz */
-	34000000, /* 34.00 MHz */
-	24000000, /* 24.00 MHz */
-	22000000, /* 22.00 MHz */
-	12000000, /* 12.00 MHz */
-};
-
-u32 clock_lut_it9135[] = {
-	12000000, /* 12.00 MHz */
-	20480000, /* 20.48 MHz */
-	36000000, /* 36.00 MHz */
-	30000000, /* 30.00 MHz */
-	26000000, /* 26.00 MHz */
-	28000000, /* 28.00 MHz */
-	32000000, /* 32.00 MHz */
-	34000000, /* 34.00 MHz */
-	24000000, /* 24.00 MHz */
-	22000000, /* 22.00 MHz */
-};
-
-/* EEPROM locations */
-#define EEPROM_IR_MODE            0x430d
-#define EEPROM_DUAL_MODE          0x4326
-#define EEPROM_IR_TYPE            0x4329
-#define EEPROM_1_IFFREQ_L         0x432d
-#define EEPROM_1_IFFREQ_H         0x432e
-#define EEPROM_1_TUNER_ID         0x4331
-#define EEPROM_2_IFFREQ_L         0x433d
-#define EEPROM_2_IFFREQ_H         0x433e
-#define EEPROM_2_TUNER_ID         0x4341
-
-/* USB commands */
-#define CMD_MEM_RD                  0x00
-#define CMD_MEM_WR                  0x01
-#define CMD_I2C_RD                  0x02
-#define CMD_I2C_WR                  0x03
-#define CMD_IR_GET                  0x18
-#define CMD_FW_DL                   0x21
-#define CMD_FW_QUERYINFO            0x22
-#define CMD_FW_BOOT                 0x23
-#define CMD_FW_DL_BEGIN             0x24
-#define CMD_FW_DL_END               0x25
-#define CMD_FW_SCATTER_WR           0x29
-
-#endif
diff --git a/drivers/media/dvb/dvb-usb/anysee.c b/drivers/media/dvb/dvb-usb/anysee.c
deleted file mode 100644
index 03c2865..0000000
--- a/drivers/media/dvb/dvb-usb/anysee.c
+++ /dev/null
@@ -1,1406 +0,0 @@
-/*
- * DVB USB Linux driver for Anysee E30 DVB-C & DVB-T USB2.0 receiver
- *
- * Copyright (C) 2007 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.
- *
- * TODO:
- * - add smart card reader support for Conditional Access (CA)
- *
- * Card reader in Anysee is nothing more than ISO 7816 card reader.
- * There is no hardware CAM in any Anysee device sold.
- * In my understanding it should be implemented by making own module
- * for ISO 7816 card reader, like dvb_ca_en50221 is implemented. This
- * module registers serial interface that can be used to communicate
- * with any ISO 7816 smart card.
- *
- * Any help according to implement serial smart card reader support
- * is highly welcome!
- */
-
-#include "anysee.h"
-#include "tda1002x.h"
-#include "mt352.h"
-#include "mt352_priv.h"
-#include "zl10353.h"
-#include "tda18212.h"
-#include "cx24116.h"
-#include "stv0900.h"
-#include "stv6110.h"
-#include "isl6423.h"
-#include "cxd2820r.h"
-
-/* debug */
-static int dvb_usb_anysee_debug;
-module_param_named(debug, dvb_usb_anysee_debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS);
-static int dvb_usb_anysee_delsys;
-module_param_named(delsys, dvb_usb_anysee_delsys, int, 0644);
-MODULE_PARM_DESC(delsys, "select delivery mode (0=DVB-C, 1=DVB-T)");
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-static DEFINE_MUTEX(anysee_usb_mutex);
-
-static int anysee_ctrl_msg(struct dvb_usb_device *d, u8 *sbuf, u8 slen,
-	u8 *rbuf, u8 rlen)
-{
-	struct anysee_state *state = d->priv;
-	int act_len, ret, i;
-	u8 buf[64];
-
-	memcpy(&buf[0], sbuf, slen);
-	buf[60] = state->seq++;
-
-	if (mutex_lock_interruptible(&anysee_usb_mutex) < 0)
-		return -EAGAIN;
-
-	deb_xfer(">>> ");
-	debug_dump(buf, slen, deb_xfer);
-
-	/* We need receive one message more after dvb_usb_generic_rw due
-	   to weird transaction flow, which is 1 x send + 2 x receive. */
-	ret = dvb_usb_generic_rw(d, buf, sizeof(buf), buf, sizeof(buf), 0);
-	if (ret)
-		goto error_unlock;
-
-	/* TODO FIXME: dvb_usb_generic_rw() fails rarely with error code -32
-	 * (EPIPE, Broken pipe). Function supports currently msleep() as a
-	 * parameter but I would not like to use it, since according to
-	 * Documentation/timers/timers-howto.txt it should not be used such
-	 * short, under < 20ms, sleeps. Repeating failed message would be
-	 * better choice as not to add unwanted delays...
-	 * Fixing that correctly is one of those or both;
-	 * 1) use repeat if possible
-	 * 2) add suitable delay
-	 */
-
-	/* get answer, retry few times if error returned */
-	for (i = 0; i < 3; i++) {
-		/* receive 2nd answer */
-		ret = usb_bulk_msg(d->udev, usb_rcvbulkpipe(d->udev,
-			d->props.generic_bulk_ctrl_endpoint), buf, sizeof(buf),
-			&act_len, 2000);
-
-		if (ret) {
-			deb_info("%s: recv bulk message failed: %d",
-					__func__, ret);
-		} else {
-			deb_xfer("<<< ");
-			debug_dump(buf, rlen, deb_xfer);
-
-			if (buf[63] != 0x4f)
-				deb_info("%s: cmd failed\n", __func__);
-
-			break;
-		}
-	}
-
-	if (ret) {
-		/* all retries failed, it is fatal */
-		err("%s: recv bulk message failed: %d", __func__, ret);
-		goto error_unlock;
-	}
-
-	/* read request, copy returned data to return buf */
-	if (rbuf && rlen)
-		memcpy(rbuf, buf, rlen);
-
-error_unlock:
-	mutex_unlock(&anysee_usb_mutex);
-
-	return ret;
-}
-
-static int anysee_read_reg(struct dvb_usb_device *d, u16 reg, u8 *val)
-{
-	u8 buf[] = {CMD_REG_READ, reg >> 8, reg & 0xff, 0x01};
-	int ret;
-	ret = anysee_ctrl_msg(d, buf, sizeof(buf), val, 1);
-	deb_info("%s: reg:%04x val:%02x\n", __func__, reg, *val);
-	return ret;
-}
-
-static int anysee_write_reg(struct dvb_usb_device *d, u16 reg, u8 val)
-{
-	u8 buf[] = {CMD_REG_WRITE, reg >> 8, reg & 0xff, 0x01, val};
-	deb_info("%s: reg:%04x val:%02x\n", __func__, reg, val);
-	return anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0);
-}
-
-/* write single register with mask */
-static int anysee_wr_reg_mask(struct dvb_usb_device *d, u16 reg, u8 val,
-	u8 mask)
-{
-	int ret;
-	u8 tmp;
-
-	/* no need for read if whole reg is written */
-	if (mask != 0xff) {
-		ret = anysee_read_reg(d, reg, &tmp);
-		if (ret)
-			return ret;
-
-		val &= mask;
-		tmp &= ~mask;
-		val |= tmp;
-	}
-
-	return anysee_write_reg(d, reg, val);
-}
-
-/* read single register with mask */
-static int anysee_rd_reg_mask(struct dvb_usb_device *d, u16 reg, u8 *val,
-	u8 mask)
-{
-	int ret, i;
-	u8 tmp;
-
-	ret = anysee_read_reg(d, reg, &tmp);
-	if (ret)
-		return ret;
-
-	tmp &= mask;
-
-	/* find position of the first bit */
-	for (i = 0; i < 8; i++) {
-		if ((mask >> i) & 0x01)
-			break;
-	}
-	*val = tmp >> i;
-
-	return 0;
-}
-
-static int anysee_get_hw_info(struct dvb_usb_device *d, u8 *id)
-{
-	u8 buf[] = {CMD_GET_HW_INFO};
-	return anysee_ctrl_msg(d, buf, sizeof(buf), id, 3);
-}
-
-static int anysee_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
-{
-	u8 buf[] = {CMD_STREAMING_CTRL, (u8)onoff, 0x00};
-	deb_info("%s: onoff:%02x\n", __func__, onoff);
-	return anysee_ctrl_msg(adap->dev, buf, sizeof(buf), NULL, 0);
-}
-
-static int anysee_led_ctrl(struct dvb_usb_device *d, u8 mode, u8 interval)
-{
-	u8 buf[] = {CMD_LED_AND_IR_CTRL, 0x01, mode, interval};
-	deb_info("%s: state:%02x interval:%02x\n", __func__, mode, interval);
-	return anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0);
-}
-
-static int anysee_ir_ctrl(struct dvb_usb_device *d, u8 onoff)
-{
-	u8 buf[] = {CMD_LED_AND_IR_CTRL, 0x02, onoff};
-	deb_info("%s: onoff:%02x\n", __func__, onoff);
-	return anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0);
-}
-
-/* I2C */
-static int anysee_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msg,
-	int num)
-{
-	struct dvb_usb_device *d = i2c_get_adapdata(adap);
-	int ret = 0, inc, i = 0;
-	u8 buf[52]; /* 4 + 48 (I2C WR USB command header + I2C WR max) */
-
-	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].len > 2 || msg[i+1].len > 60) {
-				ret = -EOPNOTSUPP;
-				break;
-			}
-			buf[0] = CMD_I2C_READ;
-			buf[1] = (msg[i].addr << 1) | 0x01;
-			buf[2] = msg[i].buf[0];
-			buf[3] = msg[i].buf[1];
-			buf[4] = msg[i].len-1;
-			buf[5] = msg[i+1].len;
-			ret = anysee_ctrl_msg(d, buf, 6, msg[i+1].buf,
-				msg[i+1].len);
-			inc = 2;
-		} else {
-			if (msg[i].len > 48) {
-				ret = -EOPNOTSUPP;
-				break;
-			}
-			buf[0] = CMD_I2C_WRITE;
-			buf[1] = (msg[i].addr << 1);
-			buf[2] = msg[i].len;
-			buf[3] = 0x01;
-			memcpy(&buf[4], msg[i].buf, msg[i].len);
-			ret = anysee_ctrl_msg(d, buf, 4 + msg[i].len, NULL, 0);
-			inc = 1;
-		}
-		if (ret)
-			break;
-
-		i += inc;
-	}
-
-	mutex_unlock(&d->i2c_mutex);
-
-	return ret ? ret : i;
-}
-
-static u32 anysee_i2c_func(struct i2c_adapter *adapter)
-{
-	return I2C_FUNC_I2C;
-}
-
-static struct i2c_algorithm anysee_i2c_algo = {
-	.master_xfer   = anysee_master_xfer,
-	.functionality = anysee_i2c_func,
-};
-
-static int anysee_mt352_demod_init(struct dvb_frontend *fe)
-{
-	static u8 clock_config[]   = { CLOCK_CTL,  0x38, 0x28 };
-	static u8 reset[]          = { RESET,      0x80 };
-	static u8 adc_ctl_1_cfg[]  = { ADC_CTL_1,  0x40 };
-	static u8 agc_cfg[]        = { AGC_TARGET, 0x28, 0x20 };
-	static u8 gpp_ctl_cfg[]    = { GPP_CTL,    0x33 };
-	static u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 };
-
-	mt352_write(fe, clock_config,   sizeof(clock_config));
-	udelay(200);
-	mt352_write(fe, reset,          sizeof(reset));
-	mt352_write(fe, adc_ctl_1_cfg,  sizeof(adc_ctl_1_cfg));
-
-	mt352_write(fe, agc_cfg,        sizeof(agc_cfg));
-	mt352_write(fe, gpp_ctl_cfg,    sizeof(gpp_ctl_cfg));
-	mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
-
-	return 0;
-}
-
-/* Callbacks for DVB USB */
-static struct tda10023_config anysee_tda10023_config = {
-	.demod_address = (0x1a >> 1),
-	.invert = 0,
-	.xtal   = 16000000,
-	.pll_m  = 11,
-	.pll_p  = 3,
-	.pll_n  = 1,
-	.output_mode = TDA10023_OUTPUT_MODE_PARALLEL_C,
-	.deltaf = 0xfeeb,
-};
-
-static struct mt352_config anysee_mt352_config = {
-	.demod_address = (0x1e >> 1),
-	.demod_init    = anysee_mt352_demod_init,
-};
-
-static struct zl10353_config anysee_zl10353_config = {
-	.demod_address = (0x1e >> 1),
-	.parallel_ts = 1,
-};
-
-static struct zl10353_config anysee_zl10353_tda18212_config2 = {
-	.demod_address = (0x1e >> 1),
-	.parallel_ts = 1,
-	.disable_i2c_gate_ctrl = 1,
-	.no_tuner = 1,
-	.if2 = 41500,
-};
-
-static struct zl10353_config anysee_zl10353_tda18212_config = {
-	.demod_address = (0x18 >> 1),
-	.parallel_ts = 1,
-	.disable_i2c_gate_ctrl = 1,
-	.no_tuner = 1,
-	.if2 = 41500,
-};
-
-static struct tda10023_config anysee_tda10023_tda18212_config = {
-	.demod_address = (0x1a >> 1),
-	.xtal   = 16000000,
-	.pll_m  = 12,
-	.pll_p  = 3,
-	.pll_n  = 1,
-	.output_mode = TDA10023_OUTPUT_MODE_PARALLEL_B,
-	.deltaf = 0xba02,
-};
-
-static struct tda18212_config anysee_tda18212_config = {
-	.i2c_address = (0xc0 >> 1),
-	.if_dvbt_6 = 4150,
-	.if_dvbt_7 = 4150,
-	.if_dvbt_8 = 4150,
-	.if_dvbc = 5000,
-};
-
-static struct tda18212_config anysee_tda18212_config2 = {
-	.i2c_address = 0x60 /* (0xc0 >> 1) */,
-	.if_dvbt_6 = 3550,
-	.if_dvbt_7 = 3700,
-	.if_dvbt_8 = 4150,
-	.if_dvbt2_6 = 3250,
-	.if_dvbt2_7 = 4000,
-	.if_dvbt2_8 = 4000,
-	.if_dvbc = 5000,
-};
-
-static struct cx24116_config anysee_cx24116_config = {
-	.demod_address = (0xaa >> 1),
-	.mpg_clk_pos_pol = 0x00,
-	.i2c_wr_max = 48,
-};
-
-static struct stv0900_config anysee_stv0900_config = {
-	.demod_address = (0xd0 >> 1),
-	.demod_mode = 0,
-	.xtal = 8000000,
-	.clkmode = 3,
-	.diseqc_mode = 2,
-	.tun1_maddress = 0,
-	.tun1_adc = 1, /* 1 Vpp */
-	.path1_mode = 3,
-};
-
-static struct stv6110_config anysee_stv6110_config = {
-	.i2c_address = (0xc0 >> 1),
-	.mclk = 16000000,
-	.clk_div = 1,
-};
-
-static struct isl6423_config anysee_isl6423_config = {
-	.current_max = SEC_CURRENT_800m,
-	.curlim  = SEC_CURRENT_LIM_OFF,
-	.mod_extern = 1,
-	.addr = (0x10 >> 1),
-};
-
-static struct cxd2820r_config anysee_cxd2820r_config = {
-	.i2c_address = 0x6d, /* (0xda >> 1) */
-	.ts_mode = 0x38,
-};
-
-/*
- * New USB device strings: Mfr=1, Product=2, SerialNumber=0
- * Manufacturer: AMT.CO.KR
- *
- * E30 VID=04b4 PID=861f HW=2 FW=2.1 Product=????????
- * PCB: ?
- * parts: DNOS404ZH102A(MT352, DTT7579(?))
- *
- * E30 VID=04b4 PID=861f HW=2 FW=2.1 "anysee-T(LP)"
- * PCB: PCB 507T (rev1.61)
- * parts: DNOS404ZH103A(ZL10353, DTT7579(?))
- * OEA=0a OEB=00 OEC=00 OED=ff OEE=00
- * IOA=45 IOB=ff IOC=00 IOD=ff IOE=00
- *
- * E30 Plus VID=04b4 PID=861f HW=6 FW=1.0 "anysee"
- * PCB: 507CD (rev1.1)
- * parts: DNOS404ZH103A(ZL10353, DTT7579(?)), CST56I01
- * OEA=80 OEB=00 OEC=00 OED=ff OEE=fe
- * IOA=4f IOB=ff IOC=00 IOD=06 IOE=01
- * IOD[0] ZL10353 1=enabled
- * IOA[7] TS 0=enabled
- * tuner is not behind ZL10353 I2C-gate (no care if gate disabled or not)
- *
- * E30 C Plus VID=04b4 PID=861f HW=10 FW=1.0 "anysee-DC(LP)"
- * PCB: 507DC (rev0.2)
- * parts: TDA10023, DTOS403IH102B TM, CST56I01
- * OEA=80 OEB=00 OEC=00 OED=ff OEE=fe
- * IOA=4f IOB=ff IOC=00 IOD=26 IOE=01
- * IOD[0] TDA10023 1=enabled
- *
- * E30 S2 Plus VID=04b4 PID=861f HW=11 FW=0.1 "anysee-S2(LP)"
- * PCB: 507SI (rev2.1)
- * parts: BS2N10WCC01(CX24116, CX24118), ISL6423, TDA8024
- * OEA=80 OEB=00 OEC=ff OED=ff OEE=fe
- * IOA=4d IOB=ff IOC=00 IOD=26 IOE=01
- * IOD[0] CX24116 1=enabled
- *
- * E30 C Plus VID=1c73 PID=861f HW=15 FW=1.2 "anysee-FA(LP)"
- * PCB: 507FA (rev0.4)
- * parts: TDA10023, DTOS403IH102B TM, TDA8024
- * OEA=80 OEB=00 OEC=ff OED=ff OEE=ff
- * IOA=4d IOB=ff IOC=00 IOD=00 IOE=c0
- * IOD[5] TDA10023 1=enabled
- * IOE[0] tuner 1=enabled
- *
- * E30 Combo Plus VID=1c73 PID=861f HW=15 FW=1.2 "anysee-FA(LP)"
- * PCB: 507FA (rev1.1)
- * parts: ZL10353, TDA10023, DTOS403IH102B TM, TDA8024
- * OEA=80 OEB=00 OEC=ff OED=ff OEE=ff
- * IOA=4d IOB=ff IOC=00 IOD=00 IOE=c0
- * DVB-C:
- * IOD[5] TDA10023 1=enabled
- * IOE[0] tuner 1=enabled
- * DVB-T:
- * IOD[0] ZL10353 1=enabled
- * IOE[0] tuner 0=enabled
- * tuner is behind ZL10353 I2C-gate
- *
- * E7 TC VID=1c73 PID=861f HW=18 FW=0.7 AMTCI=0.5 "anysee-E7TC(LP)"
- * PCB: 508TC (rev0.6)
- * parts: ZL10353, TDA10023, DNOD44CDH086A(TDA18212)
- * OEA=80 OEB=00 OEC=03 OED=f7 OEE=ff
- * IOA=4d IOB=00 IOC=cc IOD=48 IOE=e4
- * IOA[7] TS 1=enabled
- * IOE[4] TDA18212 1=enabled
- * DVB-C:
- * IOD[6] ZL10353 0=disabled
- * IOD[5] TDA10023 1=enabled
- * IOE[0] IF 1=enabled
- * DVB-T:
- * IOD[5] TDA10023 0=disabled
- * IOD[6] ZL10353 1=enabled
- * IOE[0] IF 0=enabled
- *
- * E7 S2 VID=1c73 PID=861f HW=19 FW=0.4 AMTCI=0.5 "anysee-E7S2(LP)"
- * PCB: 508S2 (rev0.7)
- * parts: DNBU10512IST(STV0903, STV6110), ISL6423
- * OEA=80 OEB=00 OEC=03 OED=f7 OEE=ff
- * IOA=4d IOB=00 IOC=c4 IOD=08 IOE=e4
- * IOA[7] TS 1=enabled
- * IOE[5] STV0903 1=enabled
- *
- * E7 T2C VID=1c73 PID=861f HW=20 FW=0.1 AMTCI=0.5 "anysee-E7T2C(LP)"
- * PCB: 508T2C (rev0.3)
- * parts: DNOQ44QCH106A(CXD2820R, TDA18212), TDA8024
- * OEA=80 OEB=00 OEC=03 OED=f7 OEE=ff
- * IOA=4d IOB=00 IOC=cc IOD=48 IOE=e4
- * IOA[7] TS 1=enabled
- * IOE[5] CXD2820R 1=enabled
- *
- * E7 PTC VID=1c73 PID=861f HW=21 FW=0.1 AMTCI=?? "anysee-E7PTC(LP)"
- * PCB: 508PTC (rev0.5)
- * parts: ZL10353, TDA10023, DNOD44CDH086A(TDA18212)
- * OEA=80 OEB=00 OEC=03 OED=f7 OEE=ff
- * IOA=4d IOB=00 IOC=cc IOD=48 IOE=e4
- * IOA[7] TS 1=enabled
- * IOE[4] TDA18212 1=enabled
- * DVB-C:
- * IOD[6] ZL10353 0=disabled
- * IOD[5] TDA10023 1=enabled
- * IOE[0] IF 1=enabled
- * DVB-T:
- * IOD[5] TDA10023 0=disabled
- * IOD[6] ZL10353 1=enabled
- * IOE[0] IF 0=enabled
- *
- * E7 PS2 VID=1c73 PID=861f HW=22 FW=0.1 AMTCI=?? "anysee-E7PS2(LP)"
- * PCB: 508PS2 (rev0.4)
- * parts: DNBU10512IST(STV0903, STV6110), ISL6423
- * OEA=80 OEB=00 OEC=03 OED=f7 OEE=ff
- * IOA=4d IOB=00 IOC=c4 IOD=08 IOE=e4
- * IOA[7] TS 1=enabled
- * IOE[5] STV0903 1=enabled
- */
-
-
-/* external I2C gate used for DNOD44CDH086A(TDA18212) tuner module */
-static int anysee_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
-{
-	struct dvb_usb_adapter *adap = fe->dvb->priv;
-
-	/* enable / disable tuner access on IOE[4] */
-	return anysee_wr_reg_mask(adap->dev, REG_IOE, (enable << 4), 0x10);
-}
-
-static int anysee_frontend_ctrl(struct dvb_frontend *fe, int onoff)
-{
-	struct dvb_usb_adapter *adap = fe->dvb->priv;
-	struct anysee_state *state = adap->dev->priv;
-	int ret;
-
-	deb_info("%s: fe=%d onoff=%d\n", __func__, fe->id, onoff);
-
-	/* no frontend sleep control */
-	if (onoff == 0)
-		return 0;
-
-	switch (state->hw) {
-	case ANYSEE_HW_507FA: /* 15 */
-		/* E30 Combo Plus */
-		/* E30 C Plus */
-
-		if ((fe->id ^ dvb_usb_anysee_delsys) == 0)  {
-			/* disable DVB-T demod on IOD[0] */
-			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 0),
-				0x01);
-			if (ret)
-				goto error;
-
-			/* enable DVB-C demod on IOD[5] */
-			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 5),
-				0x20);
-			if (ret)
-				goto error;
-
-			/* enable DVB-C tuner on IOE[0] */
-			ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 0),
-				0x01);
-			if (ret)
-				goto error;
-		} else {
-			/* disable DVB-C demod on IOD[5] */
-			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 5),
-				0x20);
-			if (ret)
-				goto error;
-
-			/* enable DVB-T demod on IOD[0] */
-			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0),
-				0x01);
-			if (ret)
-				goto error;
-
-			/* enable DVB-T tuner on IOE[0] */
-			ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (0 << 0),
-				0x01);
-			if (ret)
-				goto error;
-		}
-
-		break;
-	case ANYSEE_HW_508TC: /* 18 */
-	case ANYSEE_HW_508PTC: /* 21 */
-		/* E7 TC */
-		/* E7 PTC */
-
-		if ((fe->id ^ dvb_usb_anysee_delsys) == 0)  {
-			/* disable DVB-T demod on IOD[6] */
-			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 6),
-				0x40);
-			if (ret)
-				goto error;
-
-			/* enable DVB-C demod on IOD[5] */
-			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 5),
-				0x20);
-			if (ret)
-				goto error;
-
-			/* enable IF route on IOE[0] */
-			ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 0),
-				0x01);
-			if (ret)
-				goto error;
-		} else {
-			/* disable DVB-C demod on IOD[5] */
-			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 5),
-				0x20);
-			if (ret)
-				goto error;
-
-			/* enable DVB-T demod on IOD[6] */
-			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 6),
-				0x40);
-			if (ret)
-				goto error;
-
-			/* enable IF route on IOE[0] */
-			ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (0 << 0),
-				0x01);
-			if (ret)
-				goto error;
-		}
-
-		break;
-	default:
-		ret = 0;
-	}
-
-error:
-	return ret;
-}
-
-static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
-{
-	int ret;
-	struct anysee_state *state = adap->dev->priv;
-	u8 hw_info[3];
-	u8 tmp;
-	struct i2c_msg msg[2] = {
-		{
-			.addr = anysee_tda18212_config.i2c_address,
-			.flags = 0,
-			.len = 1,
-			.buf = "\x00",
-		}, {
-			.addr = anysee_tda18212_config.i2c_address,
-			.flags = I2C_M_RD,
-			.len = 1,
-			.buf = &tmp,
-		}
-	};
-
-	/* detect hardware only once */
-	if (adap->fe_adap[0].fe == NULL) {
-		/* Check which hardware we have.
-		 * We must do this call two times to get reliable values
-		 * (hw/fw bug).
-		 */
-		ret = anysee_get_hw_info(adap->dev, hw_info);
-		if (ret)
-			goto error;
-
-		ret = anysee_get_hw_info(adap->dev, hw_info);
-		if (ret)
-			goto error;
-
-		/* Meaning of these info bytes are guessed. */
-		info("firmware version:%d.%d hardware id:%d",
-			hw_info[1], hw_info[2], hw_info[0]);
-
-		state->hw = hw_info[0];
-	}
-
-	/* set current frondend ID for devices having two frondends */
-	if (adap->fe_adap[0].fe)
-		state->fe_id++;
-
-	switch (state->hw) {
-	case ANYSEE_HW_507T: /* 2 */
-		/* E30 */
-
-		if (state->fe_id)
-			break;
-
-		/* attach demod */
-		adap->fe_adap[0].fe = dvb_attach(mt352_attach,
-			&anysee_mt352_config, &adap->dev->i2c_adap);
-		if (adap->fe_adap[0].fe)
-			break;
-
-		/* attach demod */
-		adap->fe_adap[0].fe = dvb_attach(zl10353_attach,
-			&anysee_zl10353_config, &adap->dev->i2c_adap);
-
-		break;
-	case ANYSEE_HW_507CD: /* 6 */
-		/* E30 Plus */
-
-		if (state->fe_id)
-			break;
-
-		/* enable DVB-T demod on IOD[0] */
-		ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0), 0x01);
-		if (ret)
-			goto error;
-
-		/* enable transport stream on IOA[7] */
-		ret = anysee_wr_reg_mask(adap->dev, REG_IOA, (0 << 7), 0x80);
-		if (ret)
-			goto error;
-
-		/* attach demod */
-		adap->fe_adap[0].fe = dvb_attach(zl10353_attach,
-			&anysee_zl10353_config, &adap->dev->i2c_adap);
-
-		break;
-	case ANYSEE_HW_507DC: /* 10 */
-		/* E30 C Plus */
-
-		if (state->fe_id)
-			break;
-
-		/* enable DVB-C demod on IOD[0] */
-		ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0), 0x01);
-		if (ret)
-			goto error;
-
-		/* attach demod */
-		adap->fe_adap[0].fe = dvb_attach(tda10023_attach,
-			&anysee_tda10023_config, &adap->dev->i2c_adap, 0x48);
-
-		break;
-	case ANYSEE_HW_507SI: /* 11 */
-		/* E30 S2 Plus */
-
-		if (state->fe_id)
-			break;
-
-		/* enable DVB-S/S2 demod on IOD[0] */
-		ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0), 0x01);
-		if (ret)
-			goto error;
-
-		/* attach demod */
-		adap->fe_adap[0].fe = dvb_attach(cx24116_attach,
-			&anysee_cx24116_config, &adap->dev->i2c_adap);
-
-		break;
-	case ANYSEE_HW_507FA: /* 15 */
-		/* E30 Combo Plus */
-		/* E30 C Plus */
-
-		/* enable tuner on IOE[4] */
-		ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 4), 0x10);
-		if (ret)
-			goto error;
-
-		/* probe TDA18212 */
-		tmp = 0;
-		ret = i2c_transfer(&adap->dev->i2c_adap, msg, 2);
-		if (ret == 2 && tmp == 0xc7)
-			deb_info("%s: TDA18212 found\n", __func__);
-		else
-			tmp = 0;
-
-		/* disable tuner on IOE[4] */
-		ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (0 << 4), 0x10);
-		if (ret)
-			goto error;
-
-		if ((state->fe_id ^ dvb_usb_anysee_delsys) == 0)  {
-			/* disable DVB-T demod on IOD[0] */
-			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 0),
-				0x01);
-			if (ret)
-				goto error;
-
-			/* enable DVB-C demod on IOD[5] */
-			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 5),
-				0x20);
-			if (ret)
-				goto error;
-
-			/* attach demod */
-			if (tmp == 0xc7) {
-				/* TDA18212 config */
-				adap->fe_adap[state->fe_id].fe = dvb_attach(
-					tda10023_attach,
-					&anysee_tda10023_tda18212_config,
-					&adap->dev->i2c_adap, 0x48);
-			} else {
-				/* PLL config */
-				adap->fe_adap[state->fe_id].fe = dvb_attach(
-					tda10023_attach,
-					&anysee_tda10023_config,
-					&adap->dev->i2c_adap, 0x48);
-			}
-		} else {
-			/* disable DVB-C demod on IOD[5] */
-			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 5),
-				0x20);
-			if (ret)
-				goto error;
-
-			/* enable DVB-T demod on IOD[0] */
-			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0),
-				0x01);
-			if (ret)
-				goto error;
-
-			/* attach demod */
-			if (tmp == 0xc7) {
-				/* TDA18212 config */
-				adap->fe_adap[state->fe_id].fe = dvb_attach(
-					zl10353_attach,
-					&anysee_zl10353_tda18212_config2,
-					&adap->dev->i2c_adap);
-			} else {
-				/* PLL config */
-				adap->fe_adap[state->fe_id].fe = dvb_attach(
-					zl10353_attach,
-					&anysee_zl10353_config,
-					&adap->dev->i2c_adap);
-			}
-		}
-
-		/* I2C gate for DNOD44CDH086A(TDA18212) tuner module */
-		if (tmp == 0xc7) {
-			if (adap->fe_adap[state->fe_id].fe)
-				adap->fe_adap[state->fe_id].fe->ops.i2c_gate_ctrl =
-					anysee_i2c_gate_ctrl;
-		}
-
-		break;
-	case ANYSEE_HW_508TC: /* 18 */
-	case ANYSEE_HW_508PTC: /* 21 */
-		/* E7 TC */
-		/* E7 PTC */
-
-		if ((state->fe_id ^ dvb_usb_anysee_delsys) == 0)  {
-			/* disable DVB-T demod on IOD[6] */
-			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 6),
-				0x40);
-			if (ret)
-				goto error;
-
-			/* enable DVB-C demod on IOD[5] */
-			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 5),
-				0x20);
-			if (ret)
-				goto error;
-
-			/* attach demod */
-			adap->fe_adap[state->fe_id].fe =
-				dvb_attach(tda10023_attach,
-				&anysee_tda10023_tda18212_config,
-				&adap->dev->i2c_adap, 0x48);
-		} else {
-			/* disable DVB-C demod on IOD[5] */
-			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 5),
-				0x20);
-			if (ret)
-				goto error;
-
-			/* enable DVB-T demod on IOD[6] */
-			ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 6),
-				0x40);
-			if (ret)
-				goto error;
-
-			/* attach demod */
-			adap->fe_adap[state->fe_id].fe =
-				dvb_attach(zl10353_attach,
-				&anysee_zl10353_tda18212_config,
-				&adap->dev->i2c_adap);
-		}
-
-		/* I2C gate for DNOD44CDH086A(TDA18212) tuner module */
-		if (adap->fe_adap[state->fe_id].fe)
-			adap->fe_adap[state->fe_id].fe->ops.i2c_gate_ctrl =
-				anysee_i2c_gate_ctrl;
-
-		state->has_ci = true;
-
-		break;
-	case ANYSEE_HW_508S2: /* 19 */
-	case ANYSEE_HW_508PS2: /* 22 */
-		/* E7 S2 */
-		/* E7 PS2 */
-
-		if (state->fe_id)
-			break;
-
-		/* enable DVB-S/S2 demod on IOE[5] */
-		ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 5), 0x20);
-		if (ret)
-			goto error;
-
-		/* attach demod */
-		adap->fe_adap[0].fe = dvb_attach(stv0900_attach,
-			&anysee_stv0900_config, &adap->dev->i2c_adap, 0);
-
-		state->has_ci = true;
-
-		break;
-	case ANYSEE_HW_508T2C: /* 20 */
-		/* E7 T2C */
-
-		if (state->fe_id)
-			break;
-
-		/* enable DVB-T/T2/C demod on IOE[5] */
-		ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 5), 0x20);
-		if (ret)
-			goto error;
-
-		/* attach demod */
-		adap->fe_adap[state->fe_id].fe = dvb_attach(cxd2820r_attach,
-				&anysee_cxd2820r_config, &adap->dev->i2c_adap);
-
-		state->has_ci = true;
-
-		break;
-	}
-
-	if (!adap->fe_adap[0].fe) {
-		/* we have no frontend :-( */
-		ret = -ENODEV;
-		err("Unsupported Anysee version. " \
-			"Please report the <linux-media@vger.kernel.org>.");
-	}
-error:
-	return ret;
-}
-
-static int anysee_tuner_attach(struct dvb_usb_adapter *adap)
-{
-	struct anysee_state *state = adap->dev->priv;
-	struct dvb_frontend *fe;
-	int ret;
-	deb_info("%s: fe=%d\n", __func__, state->fe_id);
-
-	switch (state->hw) {
-	case ANYSEE_HW_507T: /* 2 */
-		/* E30 */
-
-		/* attach tuner */
-		fe = dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe,
-			(0xc2 >> 1), NULL, DVB_PLL_THOMSON_DTT7579);
-
-		break;
-	case ANYSEE_HW_507CD: /* 6 */
-		/* E30 Plus */
-
-		/* attach tuner */
-		fe = dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe,
-			(0xc2 >> 1), &adap->dev->i2c_adap,
-			DVB_PLL_THOMSON_DTT7579);
-
-		break;
-	case ANYSEE_HW_507DC: /* 10 */
-		/* E30 C Plus */
-
-		/* attach tuner */
-		fe = dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe,
-			(0xc0 >> 1), &adap->dev->i2c_adap,
-			DVB_PLL_SAMSUNG_DTOS403IH102A);
-
-		break;
-	case ANYSEE_HW_507SI: /* 11 */
-		/* E30 S2 Plus */
-
-		/* attach LNB controller */
-		fe = dvb_attach(isl6423_attach, adap->fe_adap[0].fe,
-			&adap->dev->i2c_adap, &anysee_isl6423_config);
-
-		break;
-	case ANYSEE_HW_507FA: /* 15 */
-		/* E30 Combo Plus */
-		/* E30 C Plus */
-
-		/* Try first attach TDA18212 silicon tuner on IOE[4], if that
-		 * fails attach old simple PLL. */
-
-		/* attach tuner */
-		fe = dvb_attach(tda18212_attach, adap->fe_adap[state->fe_id].fe,
-			&adap->dev->i2c_adap, &anysee_tda18212_config);
-		if (fe)
-			break;
-
-		/* attach tuner */
-		fe = dvb_attach(dvb_pll_attach, adap->fe_adap[state->fe_id].fe,
-			(0xc0 >> 1), &adap->dev->i2c_adap,
-			DVB_PLL_SAMSUNG_DTOS403IH102A);
-
-		break;
-	case ANYSEE_HW_508TC: /* 18 */
-	case ANYSEE_HW_508PTC: /* 21 */
-		/* E7 TC */
-		/* E7 PTC */
-
-		/* attach tuner */
-		fe = dvb_attach(tda18212_attach, adap->fe_adap[state->fe_id].fe,
-			&adap->dev->i2c_adap, &anysee_tda18212_config);
-
-		break;
-	case ANYSEE_HW_508S2: /* 19 */
-	case ANYSEE_HW_508PS2: /* 22 */
-		/* E7 S2 */
-		/* E7 PS2 */
-
-		/* attach tuner */
-		fe = dvb_attach(stv6110_attach, adap->fe_adap[0].fe,
-			&anysee_stv6110_config, &adap->dev->i2c_adap);
-
-		if (fe) {
-			/* attach LNB controller */
-			fe = dvb_attach(isl6423_attach, adap->fe_adap[0].fe,
-				&adap->dev->i2c_adap, &anysee_isl6423_config);
-		}
-
-		break;
-
-	case ANYSEE_HW_508T2C: /* 20 */
-		/* E7 T2C */
-
-		/* attach tuner */
-		fe = dvb_attach(tda18212_attach, adap->fe_adap[state->fe_id].fe,
-			&adap->dev->i2c_adap, &anysee_tda18212_config2);
-
-		break;
-	default:
-		fe = NULL;
-	}
-
-	if (fe)
-		ret = 0;
-	else
-		ret = -ENODEV;
-
-	return ret;
-}
-
-static int anysee_rc_query(struct dvb_usb_device *d)
-{
-	u8 buf[] = {CMD_GET_IR_CODE};
-	u8 ircode[2];
-	int ret;
-
-	/* Remote controller is basic NEC using address byte 0x08.
-	   Anysee device RC query returns only two bytes, status and code,
-	   address byte is dropped. Also it does not return any value for
-	   NEC RCs having address byte other than 0x08. Due to that, we
-	   cannot use that device as standard NEC receiver.
-	   It could be possible make hack which reads whole code directly
-	   from device memory... */
-
-	ret = anysee_ctrl_msg(d, buf, sizeof(buf), ircode, sizeof(ircode));
-	if (ret)
-		return ret;
-
-	if (ircode[0]) {
-		deb_rc("%s: key pressed %02x\n", __func__, ircode[1]);
-		rc_keydown(d->rc_dev, 0x08 << 8 | ircode[1], 0);
-	}
-
-	return 0;
-}
-
-static int anysee_ci_read_attribute_mem(struct dvb_ca_en50221 *ci, int slot,
-	int addr)
-{
-	struct dvb_usb_device *d = ci->data;
-	int ret;
-	u8 buf[] = {CMD_CI, 0x02, 0x40 | addr >> 8, addr & 0xff, 0x00, 1};
-	u8 val;
-
-	ret = anysee_ctrl_msg(d, buf, sizeof(buf), &val, 1);
-	if (ret)
-		return ret;
-
-	return val;
-}
-
-static int anysee_ci_write_attribute_mem(struct dvb_ca_en50221 *ci, int slot,
-	int addr, u8 val)
-{
-	struct dvb_usb_device *d = ci->data;
-	int ret;
-	u8 buf[] = {CMD_CI, 0x03, 0x40 | addr >> 8, addr & 0xff, 0x00, 1, val};
-
-	ret = anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0);
-	if (ret)
-		return ret;
-
-	return 0;
-}
-
-static int anysee_ci_read_cam_control(struct dvb_ca_en50221 *ci, int slot,
-	u8 addr)
-{
-	struct dvb_usb_device *d = ci->data;
-	int ret;
-	u8 buf[] = {CMD_CI, 0x04, 0x40, addr, 0x00, 1};
-	u8 val;
-
-	ret = anysee_ctrl_msg(d, buf, sizeof(buf), &val, 1);
-	if (ret)
-		return ret;
-
-	return val;
-}
-
-static int anysee_ci_write_cam_control(struct dvb_ca_en50221 *ci, int slot,
-	u8 addr, u8 val)
-{
-	struct dvb_usb_device *d = ci->data;
-	int ret;
-	u8 buf[] = {CMD_CI, 0x05, 0x40, addr, 0x00, 1, val};
-
-	ret = anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0);
-	if (ret)
-		return ret;
-
-	return 0;
-}
-
-static int anysee_ci_slot_reset(struct dvb_ca_en50221 *ci, int slot)
-{
-	struct dvb_usb_device *d = ci->data;
-	int ret;
-	struct anysee_state *state = d->priv;
-
-	state->ci_cam_ready = jiffies + msecs_to_jiffies(1000);
-
-	ret = anysee_wr_reg_mask(d, REG_IOA, (0 << 7), 0x80);
-	if (ret)
-		return ret;
-
-	msleep(300);
-
-	ret = anysee_wr_reg_mask(d, REG_IOA, (1 << 7), 0x80);
-	if (ret)
-		return ret;
-
-	return 0;
-}
-
-static int anysee_ci_slot_shutdown(struct dvb_ca_en50221 *ci, int slot)
-{
-	struct dvb_usb_device *d = ci->data;
-	int ret;
-
-	ret = anysee_wr_reg_mask(d, REG_IOA, (0 << 7), 0x80);
-	if (ret)
-		return ret;
-
-	msleep(30);
-
-	ret = anysee_wr_reg_mask(d, REG_IOA, (1 << 7), 0x80);
-	if (ret)
-		return ret;
-
-	return 0;
-}
-
-static int anysee_ci_slot_ts_enable(struct dvb_ca_en50221 *ci, int slot)
-{
-	struct dvb_usb_device *d = ci->data;
-	int ret;
-
-	ret = anysee_wr_reg_mask(d, REG_IOD, (0 << 1), 0x02);
-	if (ret)
-		return ret;
-
-	return 0;
-}
-
-static int anysee_ci_poll_slot_status(struct dvb_ca_en50221 *ci, int slot,
-	int open)
-{
-	struct dvb_usb_device *d = ci->data;
-	struct anysee_state *state = d->priv;
-	int ret;
-	u8 tmp;
-
-	ret = anysee_rd_reg_mask(d, REG_IOC, &tmp, 0x40);
-	if (ret)
-		return ret;
-
-	if (tmp == 0) {
-		ret = DVB_CA_EN50221_POLL_CAM_PRESENT;
-		if (time_after(jiffies, state->ci_cam_ready))
-			ret |= DVB_CA_EN50221_POLL_CAM_READY;
-	}
-
-	return ret;
-}
-
-static int anysee_ci_init(struct dvb_usb_device *d)
-{
-	struct anysee_state *state = d->priv;
-	int ret;
-
-	state->ci.owner               = THIS_MODULE;
-	state->ci.read_attribute_mem  = anysee_ci_read_attribute_mem;
-	state->ci.write_attribute_mem = anysee_ci_write_attribute_mem;
-	state->ci.read_cam_control    = anysee_ci_read_cam_control;
-	state->ci.write_cam_control   = anysee_ci_write_cam_control;
-	state->ci.slot_reset          = anysee_ci_slot_reset;
-	state->ci.slot_shutdown       = anysee_ci_slot_shutdown;
-	state->ci.slot_ts_enable      = anysee_ci_slot_ts_enable;
-	state->ci.poll_slot_status    = anysee_ci_poll_slot_status;
-	state->ci.data                = d;
-
-	ret = anysee_wr_reg_mask(d, REG_IOA, (1 << 7), 0x80);
-	if (ret)
-		return ret;
-
-	ret = anysee_wr_reg_mask(d, REG_IOD, (0 << 2)|(0 << 1)|(0 << 0), 0x07);
-	if (ret)
-		return ret;
-
-	ret = anysee_wr_reg_mask(d, REG_IOD, (1 << 2)|(1 << 1)|(1 << 0), 0x07);
-	if (ret)
-		return ret;
-
-	ret = dvb_ca_en50221_init(&d->adapter[0].dvb_adap, &state->ci, 0, 1);
-	if (ret)
-		return ret;
-
-	return 0;
-}
-
-static void anysee_ci_release(struct dvb_usb_device *d)
-{
-	struct anysee_state *state = d->priv;
-
-	/* detach CI */
-	if (state->has_ci)
-		dvb_ca_en50221_release(&state->ci);
-
-	return;
-}
-
-static int anysee_init(struct dvb_usb_device *d)
-{
-	struct anysee_state *state = d->priv;
-	int ret;
-
-	/* LED light */
-	ret = anysee_led_ctrl(d, 0x01, 0x03);
-	if (ret)
-		return ret;
-
-	/* enable IR */
-	ret = anysee_ir_ctrl(d, 1);
-	if (ret)
-		return ret;
-
-	/* attach CI */
-	if (state->has_ci) {
-		ret = anysee_ci_init(d);
-		if (ret) {
-			state->has_ci = false;
-			return ret;
-		}
-	}
-
-	return 0;
-}
-
-/* DVB USB Driver stuff */
-static struct dvb_usb_device_properties anysee_properties;
-
-static int anysee_probe(struct usb_interface *intf,
-			const struct usb_device_id *id)
-{
-	struct dvb_usb_device *d;
-	struct usb_host_interface *alt;
-	int ret;
-
-	/* There is one interface with two alternate settings.
-	   Alternate setting 0 is for bulk transfer.
-	   Alternate setting 1 is for isochronous transfer.
-	   We use bulk transfer (alternate setting 0). */
-	if (intf->num_altsetting < 1)
-		return -ENODEV;
-
-	/*
-	 * Anysee is always warm (its USB-bridge, Cypress FX2, uploads
-	 * firmware from eeprom).  If dvb_usb_device_init() succeeds that
-	 * means d is a valid pointer.
-	 */
-	ret = dvb_usb_device_init(intf, &anysee_properties, THIS_MODULE, &d,
-		adapter_nr);
-	if (ret)
-		return ret;
-
-	alt = usb_altnum_to_altsetting(intf, 0);
-	if (alt == NULL) {
-		deb_info("%s: no alt found!\n", __func__);
-		return -ENODEV;
-	}
-
-	ret = usb_set_interface(d->udev, alt->desc.bInterfaceNumber,
-		alt->desc.bAlternateSetting);
-	if (ret)
-		return ret;
-
-	return anysee_init(d);
-}
-
-static void anysee_disconnect(struct usb_interface *intf)
-{
-	struct dvb_usb_device *d = usb_get_intfdata(intf);
-
-	anysee_ci_release(d);
-	dvb_usb_device_exit(intf);
-
-	return;
-}
-
-static struct usb_device_id anysee_table[] = {
-	{ USB_DEVICE(USB_VID_CYPRESS, USB_PID_ANYSEE) },
-	{ USB_DEVICE(USB_VID_AMT,     USB_PID_ANYSEE) },
-	{ }		/* Terminating entry */
-};
-MODULE_DEVICE_TABLE(usb, anysee_table);
-
-static struct dvb_usb_device_properties anysee_properties = {
-	.caps             = DVB_USB_IS_AN_I2C_ADAPTER,
-
-	.usb_ctrl         = DEVICE_SPECIFIC,
-
-	.size_of_priv     = sizeof(struct anysee_state),
-
-	.num_adapters = 1,
-	.adapter = {
-		{
-		.num_frontends    = 2,
-		.frontend_ctrl    = anysee_frontend_ctrl,
-		.fe = { {
-			.streaming_ctrl   = anysee_streaming_ctrl,
-			.frontend_attach  = anysee_frontend_attach,
-			.tuner_attach     = anysee_tuner_attach,
-			.stream = {
-				.type = USB_BULK,
-				.count = 8,
-				.endpoint = 0x82,
-				.u = {
-					.bulk = {
-						.buffersize = (16*512),
-					}
-				}
-			},
-		}, {
-			.streaming_ctrl   = anysee_streaming_ctrl,
-			.frontend_attach  = anysee_frontend_attach,
-			.tuner_attach     = anysee_tuner_attach,
-			.stream = {
-				.type = USB_BULK,
-				.count = 8,
-				.endpoint = 0x82,
-				.u = {
-					.bulk = {
-						.buffersize = (16*512),
-					}
-				}
-			},
-		} },
-		}
-	},
-
-	.rc.core = {
-		.rc_codes         = RC_MAP_ANYSEE,
-		.protocol         = RC_TYPE_OTHER,
-		.module_name      = "anysee",
-		.rc_query         = anysee_rc_query,
-		.rc_interval      = 250,  /* windows driver uses 500ms */
-	},
-
-	.i2c_algo         = &anysee_i2c_algo,
-
-	.generic_bulk_ctrl_endpoint = 1,
-
-	.num_device_descs = 1,
-	.devices = {
-		{
-			.name = "Anysee DVB USB2.0",
-			.cold_ids = {NULL},
-			.warm_ids = {&anysee_table[0],
-				     &anysee_table[1], NULL},
-		},
-	}
-};
-
-static struct usb_driver anysee_driver = {
-	.name       = "dvb_usb_anysee",
-	.probe      = anysee_probe,
-	.disconnect = anysee_disconnect,
-	.id_table   = anysee_table,
-};
-
-module_usb_driver(anysee_driver);
-
-MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
-MODULE_DESCRIPTION("Driver Anysee E30 DVB-C & DVB-T USB2.0");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/anysee.h b/drivers/media/dvb/dvb-usb/anysee.h
deleted file mode 100644
index 8ac8794..0000000
--- a/drivers/media/dvb/dvb-usb/anysee.h
+++ /dev/null
@@ -1,332 +0,0 @@
-/*
- * DVB USB Linux driver for Anysee E30 DVB-C & DVB-T USB2.0 receiver
- *
- * Copyright (C) 2007 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.
- *
- * TODO:
- * - add smart card reader support for Conditional Access (CA)
- *
- * Card reader in Anysee is nothing more than ISO 7816 card reader.
- * There is no hardware CAM in any Anysee device sold.
- * In my understanding it should be implemented by making own module
- * for ISO 7816 card reader, like dvb_ca_en50221 is implemented. This
- * module registers serial interface that can be used to communicate
- * with any ISO 7816 smart card.
- *
- * Any help according to implement serial smart card reader support
- * is highly welcome!
- */
-
-#ifndef _DVB_USB_ANYSEE_H_
-#define _DVB_USB_ANYSEE_H_
-
-#define DVB_USB_LOG_PREFIX "anysee"
-#include "dvb-usb.h"
-#include "dvb_ca_en50221.h"
-
-#define deb_info(args...) dprintk(dvb_usb_anysee_debug, 0x01, args)
-#define deb_xfer(args...) dprintk(dvb_usb_anysee_debug, 0x02, args)
-#define deb_rc(args...)   dprintk(dvb_usb_anysee_debug, 0x04, args)
-#define deb_reg(args...)  dprintk(dvb_usb_anysee_debug, 0x08, args)
-#define deb_i2c(args...)  dprintk(dvb_usb_anysee_debug, 0x10, args)
-#define deb_fw(args...)   dprintk(dvb_usb_anysee_debug, 0x20, args)
-
-enum cmd {
-	CMD_I2C_READ            = 0x33,
-	CMD_I2C_WRITE           = 0x31,
-	CMD_REG_READ            = 0xb0,
-	CMD_REG_WRITE           = 0xb1,
-	CMD_STREAMING_CTRL      = 0x12,
-	CMD_LED_AND_IR_CTRL     = 0x16,
-	CMD_GET_IR_CODE         = 0x41,
-	CMD_GET_HW_INFO         = 0x19,
-	CMD_SMARTCARD           = 0x34,
-	CMD_CI                  = 0x37,
-};
-
-struct anysee_state {
-	u8 hw; /* PCB ID */
-	u8 seq;
-	u8 fe_id:1; /* frondend ID */
-	u8 has_ci:1;
-	struct dvb_ca_en50221 ci;
-	unsigned long ci_cam_ready; /* jiffies */
-};
-
-#define ANYSEE_HW_507T    2 /* E30 */
-#define ANYSEE_HW_507CD   6 /* E30 Plus */
-#define ANYSEE_HW_507DC  10 /* E30 C Plus */
-#define ANYSEE_HW_507SI  11 /* E30 S2 Plus */
-#define ANYSEE_HW_507FA  15 /* E30 Combo Plus / E30 C Plus */
-#define ANYSEE_HW_508TC  18 /* E7 TC */
-#define ANYSEE_HW_508S2  19 /* E7 S2 */
-#define ANYSEE_HW_508T2C 20 /* E7 T2C */
-#define ANYSEE_HW_508PTC 21 /* E7 PTC Plus */
-#define ANYSEE_HW_508PS2 22 /* E7 PS2 Plus */
-
-#define REG_IOA       0x80 /* Port A (bit addressable) */
-#define REG_IOB       0x90 /* Port B (bit addressable) */
-#define REG_IOC       0xa0 /* Port C (bit addressable) */
-#define REG_IOD       0xb0 /* Port D (bit addressable) */
-#define REG_IOE       0xb1 /* Port E (NOT bit addressable) */
-#define REG_OEA       0xb2 /* Port A Output Enable */
-#define REG_OEB       0xb3 /* Port B Output Enable */
-#define REG_OEC       0xb4 /* Port C Output Enable */
-#define REG_OED       0xb5 /* Port D Output Enable */
-#define REG_OEE       0xb6 /* Port E Output Enable */
-
-#endif
-
-/***************************************************************************
- * USB API description (reverse engineered)
- ***************************************************************************
-
-Transaction flow:
-=================
-BULK[00001] >>> REQUEST PACKET 64 bytes
-BULK[00081] <<< REPLY PACKET #1 64 bytes (PREVIOUS TRANSACTION REPLY)
-BULK[00081] <<< REPLY PACKET #2 64 bytes (CURRENT TRANSACTION REPLY)
-
-General reply packet(s) are always used if not own reply defined.
-
-============================================================================
-| 00-63 | GENERAL REPLY PACKET #1 (PREVIOUS REPLY)
-============================================================================
-|    00 | reply data (if any) from previous transaction
-|       | Just same reply packet as returned during previous transaction.
-|       | Needed only if reply is missed in previous transaction.
-|       | Just skip normally.
-----------------------------------------------------------------------------
-| 01-59 | don't care
-----------------------------------------------------------------------------
-|    60 | packet sequence number
-----------------------------------------------------------------------------
-| 61-63 | don't care
-----------------------------------------------------------------------------
-
-============================================================================
-| 00-63 | GENERAL REPLY PACKET #2 (CURRENT REPLY)
-============================================================================
-|    00 | reply data (if any)
-----------------------------------------------------------------------------
-| 01-59 | don't care
-----------------------------------------------------------------------------
-|    60 | packet sequence number
-----------------------------------------------------------------------------
-| 61-63 | don't care
-----------------------------------------------------------------------------
-
-============================================================================
-| 00-63 | I2C WRITE REQUEST PACKET
-============================================================================
-|    00 | 0x31 I2C write command
-----------------------------------------------------------------------------
-|    01 | i2c address
-----------------------------------------------------------------------------
-|    02 | data length
-|       | 0x02 (for typical I2C reg / val pair)
-----------------------------------------------------------------------------
-|    03 | 0x01
-----------------------------------------------------------------------------
-| 04-   | data
-----------------------------------------------------------------------------
-|   -59 | don't care
-----------------------------------------------------------------------------
-|    60 | packet sequence number
-----------------------------------------------------------------------------
-| 61-63 | don't care
-----------------------------------------------------------------------------
-
-============================================================================
-| 00-63 | I2C READ REQUEST PACKET
-============================================================================
-|    00 | 0x33 I2C read command
-----------------------------------------------------------------------------
-|    01 | i2c address + 1
-----------------------------------------------------------------------------
-|    02 | register
-----------------------------------------------------------------------------
-|    03 | 0x00
-----------------------------------------------------------------------------
-|    04 | 0x00
-----------------------------------------------------------------------------
-|    05 | data length
-----------------------------------------------------------------------------
-| 06-59 | don't care
-----------------------------------------------------------------------------
-|    60 | packet sequence number
-----------------------------------------------------------------------------
-| 61-63 | don't care
-----------------------------------------------------------------------------
-
-============================================================================
-| 00-63 | USB CONTROLLER REGISTER WRITE REQUEST PACKET
-============================================================================
-|    00 | 0xb1 register write command
-----------------------------------------------------------------------------
-| 01-02 | register
-----------------------------------------------------------------------------
-|    03 | 0x01
-----------------------------------------------------------------------------
-|    04 | value
-----------------------------------------------------------------------------
-| 05-59 | don't care
-----------------------------------------------------------------------------
-|    60 | packet sequence number
-----------------------------------------------------------------------------
-| 61-63 | don't care
-----------------------------------------------------------------------------
-
-============================================================================
-| 00-63 | USB CONTROLLER REGISTER READ REQUEST PACKET
-============================================================================
-|    00 | 0xb0 register read command
-----------------------------------------------------------------------------
-| 01-02 | register
-----------------------------------------------------------------------------
-|    03 | 0x01
-----------------------------------------------------------------------------
-| 04-59 | don't care
-----------------------------------------------------------------------------
-|    60 | packet sequence number
-----------------------------------------------------------------------------
-| 61-63 | don't care
-----------------------------------------------------------------------------
-
-============================================================================
-| 00-63 | LED CONTROL REQUEST PACKET
-============================================================================
-|    00 | 0x16 LED and IR control command
-----------------------------------------------------------------------------
-|    01 | 0x01 (LED)
-----------------------------------------------------------------------------
-|    03 | 0x00 blink
-|       | 0x01 lights continuously
-----------------------------------------------------------------------------
-|    04 | blink interval
-|       | 0x00 fastest (looks like LED lights continuously)
-|       | 0xff slowest
-----------------------------------------------------------------------------
-| 05-59 | don't care
-----------------------------------------------------------------------------
-|    60 | packet sequence number
-----------------------------------------------------------------------------
-| 61-63 | don't care
-----------------------------------------------------------------------------
-
-============================================================================
-| 00-63 | IR CONTROL REQUEST PACKET
-============================================================================
-|    00 | 0x16 LED and IR control command
-----------------------------------------------------------------------------
-|    01 | 0x02 (IR)
-----------------------------------------------------------------------------
-|    03 | 0x00 IR disabled
-|       | 0x01 IR enabled
-----------------------------------------------------------------------------
-| 04-59 | don't care
-----------------------------------------------------------------------------
-|    60 | packet sequence number
-----------------------------------------------------------------------------
-| 61-63 | don't care
-----------------------------------------------------------------------------
-
-============================================================================
-| 00-63 | STREAMING CONTROL REQUEST PACKET
-============================================================================
-|    00 | 0x12 streaming control command
-----------------------------------------------------------------------------
-|    01 | 0x00 streaming disabled
-|       | 0x01 streaming enabled
-----------------------------------------------------------------------------
-|    02 | 0x00
-----------------------------------------------------------------------------
-| 03-59 | don't care
-----------------------------------------------------------------------------
-|    60 | packet sequence number
-----------------------------------------------------------------------------
-| 61-63 | don't care
-----------------------------------------------------------------------------
-
-============================================================================
-| 00-63 | REMOTE CONTROL REQUEST PACKET
-============================================================================
-|    00 | 0x41 remote control command
-----------------------------------------------------------------------------
-| 01-59 | don't care
-----------------------------------------------------------------------------
-|    60 | packet sequence number
-----------------------------------------------------------------------------
-| 61-63 | don't care
-----------------------------------------------------------------------------
-
-============================================================================
-| 00-63 | REMOTE CONTROL REPLY PACKET
-============================================================================
-|    00 | 0x00 code not received
-|       | 0x01 code received
-----------------------------------------------------------------------------
-|    01 | remote control code
-----------------------------------------------------------------------------
-| 02-59 | don't care
-----------------------------------------------------------------------------
-|    60 | packet sequence number
-----------------------------------------------------------------------------
-| 61-63 | don't care
-----------------------------------------------------------------------------
-
-============================================================================
-| 00-63 | GET HARDWARE INFO REQUEST PACKET
-============================================================================
-|    00 | 0x19 get hardware info command
-----------------------------------------------------------------------------
-| 01-59 | don't care
-----------------------------------------------------------------------------
-|    60 | packet sequence number
-----------------------------------------------------------------------------
-| 61-63 | don't care
-----------------------------------------------------------------------------
-
-============================================================================
-| 00-63 | GET HARDWARE INFO REPLY PACKET
-============================================================================
-|    00 | hardware id
-----------------------------------------------------------------------------
-| 01-02 | firmware version
-----------------------------------------------------------------------------
-| 03-59 | don't care
-----------------------------------------------------------------------------
-|    60 | packet sequence number
-----------------------------------------------------------------------------
-| 61-63 | don't care
-----------------------------------------------------------------------------
-
-============================================================================
-| 00-63 | SMART CARD READER PACKET
-============================================================================
-|    00 | 0x34 smart card reader command
-----------------------------------------------------------------------------
-|    xx |
-----------------------------------------------------------------------------
-| xx-59 | don't care
-----------------------------------------------------------------------------
-|    60 | packet sequence number
-----------------------------------------------------------------------------
-| 61-63 | don't care
-----------------------------------------------------------------------------
-
-*/
diff --git a/drivers/media/dvb/dvb-usb/au6610.c b/drivers/media/dvb/dvb-usb/au6610.c
deleted file mode 100644
index 16210c0..0000000
--- a/drivers/media/dvb/dvb-usb/au6610.c
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
- * DVB USB Linux driver for Alcor Micro AU6610 DVB-T USB2.0.
- *
- * Copyright (C) 2006 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 "au6610.h"
-#include "zl10353.h"
-#include "qt1010.h"
-
-/* debug */
-static int dvb_usb_au6610_debug;
-module_param_named(debug, dvb_usb_au6610_debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS);
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-static int au6610_usb_msg(struct dvb_usb_device *d, u8 operation, u8 addr,
-			  u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
-{
-	int ret;
-	u16 index;
-	u8 *usb_buf;
-
-	/*
-	 * allocate enough for all known requests,
-	 * read returns 5 and write 6 bytes
-	 */
-	usb_buf = kmalloc(6, GFP_KERNEL);
-	if (!usb_buf)
-		return -ENOMEM;
-
-	switch (wlen) {
-	case 1:
-		index = wbuf[0] << 8;
-		break;
-	case 2:
-		index = wbuf[0] << 8;
-		index += wbuf[1];
-		break;
-	default:
-		warn("wlen = %x, aborting.", wlen);
-		ret = -EINVAL;
-		goto error;
-	}
-
-	ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), operation,
-			      USB_TYPE_VENDOR|USB_DIR_IN, addr << 1, index,
-			      usb_buf, 6, AU6610_USB_TIMEOUT);
-	if (ret < 0)
-		goto error;
-
-	switch (operation) {
-	case AU6610_REQ_I2C_READ:
-	case AU6610_REQ_USB_READ:
-		/* requested value is always 5th byte in buffer */
-		rbuf[0] = usb_buf[4];
-	}
-error:
-	kfree(usb_buf);
-	return ret;
-}
-
-static int au6610_i2c_msg(struct dvb_usb_device *d, u8 addr,
-			  u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
-{
-	u8 request;
-	u8 wo = (rbuf == NULL || rlen == 0); /* write-only */
-
-	if (wo) {
-		request = AU6610_REQ_I2C_WRITE;
-	} else { /* rw */
-		request = AU6610_REQ_I2C_READ;
-	}
-
-	return au6610_usb_msg(d, request, addr, wbuf, wlen, rbuf, rlen);
-}
-
-
-/* I2C */
-static int au6610_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
-			   int num)
-{
-	struct dvb_usb_device *d = i2c_get_adapdata(adap);
-	int i;
-
-	if (num > 2)
-		return -EINVAL;
-
-	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
-		return -EAGAIN;
-
-	for (i = 0; i < num; i++) {
-		/* write/read request */
-		if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {
-			if (au6610_i2c_msg(d, msg[i].addr, msg[i].buf,
-					   msg[i].len, msg[i+1].buf,
-					   msg[i+1].len) < 0)
-				break;
-			i++;
-		} else if (au6610_i2c_msg(d, msg[i].addr, msg[i].buf,
-					       msg[i].len, NULL, 0) < 0)
-				break;
-	}
-
-	mutex_unlock(&d->i2c_mutex);
-	return i;
-}
-
-
-static u32 au6610_i2c_func(struct i2c_adapter *adapter)
-{
-	return I2C_FUNC_I2C;
-}
-
-static struct i2c_algorithm au6610_i2c_algo = {
-	.master_xfer   = au6610_i2c_xfer,
-	.functionality = au6610_i2c_func,
-};
-
-/* Callbacks for DVB USB */
-static struct zl10353_config au6610_zl10353_config = {
-	.demod_address = 0x0f,
-	.no_tuner = 1,
-	.parallel_ts = 1,
-};
-
-static int au6610_zl10353_frontend_attach(struct dvb_usb_adapter *adap)
-{
-	adap->fe_adap[0].fe = dvb_attach(zl10353_attach, &au6610_zl10353_config,
-		&adap->dev->i2c_adap);
-	if (adap->fe_adap[0].fe == NULL)
-		return -ENODEV;
-
-	return 0;
-}
-
-static struct qt1010_config au6610_qt1010_config = {
-	.i2c_address = 0x62
-};
-
-static int au6610_qt1010_tuner_attach(struct dvb_usb_adapter *adap)
-{
-	return dvb_attach(qt1010_attach,
-			  adap->fe_adap[0].fe, &adap->dev->i2c_adap,
-			  &au6610_qt1010_config) == NULL ? -ENODEV : 0;
-}
-
-/* DVB USB Driver stuff */
-static struct dvb_usb_device_properties au6610_properties;
-
-static int au6610_probe(struct usb_interface *intf,
-			const struct usb_device_id *id)
-{
-	struct dvb_usb_device *d;
-	struct usb_host_interface *alt;
-	int ret;
-
-	if (intf->num_altsetting < AU6610_ALTSETTING_COUNT)
-		return -ENODEV;
-
-	ret = dvb_usb_device_init(intf, &au6610_properties, THIS_MODULE, &d,
-				  adapter_nr);
-	if (ret == 0) {
-		alt = usb_altnum_to_altsetting(intf, AU6610_ALTSETTING);
-
-		if (alt == NULL) {
-			deb_info("%s: no alt found!\n", __func__);
-			return -ENODEV;
-		}
-		ret = usb_set_interface(d->udev, alt->desc.bInterfaceNumber,
-					alt->desc.bAlternateSetting);
-	}
-
-	return ret;
-}
-
-static struct usb_device_id au6610_table [] = {
-	{ USB_DEVICE(USB_VID_ALCOR_MICRO, USB_PID_SIGMATEK_DVB_110) },
-	{ }		/* Terminating entry */
-};
-MODULE_DEVICE_TABLE(usb, au6610_table);
-
-static struct dvb_usb_device_properties au6610_properties = {
-	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
-
-	.usb_ctrl = DEVICE_SPECIFIC,
-
-	.size_of_priv = 0,
-
-	.num_adapters = 1,
-	.adapter = {
-		{
-		.num_frontends = 1,
-		.fe = {{
-			.frontend_attach  = au6610_zl10353_frontend_attach,
-			.tuner_attach     = au6610_qt1010_tuner_attach,
-
-			.stream = {
-				.type = USB_ISOC,
-				.count = 5,
-				.endpoint = 0x82,
-				.u = {
-					.isoc = {
-						.framesperurb = 40,
-						.framesize = 942,
-						.interval = 1,
-					}
-				}
-			},
-		}},
-		}
-	},
-
-	.i2c_algo = &au6610_i2c_algo,
-
-	.num_device_descs = 1,
-	.devices = {
-		{
-			.name = "Sigmatek DVB-110 DVB-T USB2.0",
-			.cold_ids = {NULL},
-			.warm_ids = {&au6610_table[0], NULL},
-		},
-	}
-};
-
-static struct usb_driver au6610_driver = {
-	.name       = "dvb_usb_au6610",
-	.probe      = au6610_probe,
-	.disconnect = dvb_usb_device_exit,
-	.id_table   = au6610_table,
-};
-
-module_usb_driver(au6610_driver);
-
-MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
-MODULE_DESCRIPTION("Driver for Alcor Micro AU6610 DVB-T USB2.0");
-MODULE_VERSION("0.1");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/au6610.h b/drivers/media/dvb/dvb-usb/au6610.h
deleted file mode 100644
index 7849abe..0000000
--- a/drivers/media/dvb/dvb-usb/au6610.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * DVB USB Linux driver for Alcor Micro AU6610 DVB-T USB2.0.
- *
- * Copyright (C) 2006 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_AU6610_H_
-#define _DVB_USB_AU6610_H_
-
-#define DVB_USB_LOG_PREFIX "au6610"
-#include "dvb-usb.h"
-
-#define deb_info(args...)   dprintk(dvb_usb_au6610_debug, 0x01, args)
-
-#define AU6610_REQ_I2C_WRITE	0x14
-#define AU6610_REQ_I2C_READ	0x13
-#define AU6610_REQ_USB_WRITE	0x16
-#define AU6610_REQ_USB_READ	0x15
-
-#define AU6610_USB_TIMEOUT 1000
-
-#define AU6610_ALTSETTING_COUNT 6
-#define AU6610_ALTSETTING       5
-
-#endif
diff --git a/drivers/media/dvb/dvb-usb/az6007.c b/drivers/media/dvb/dvb-usb/az6007.c
deleted file mode 100644
index 86861e6..0000000
--- a/drivers/media/dvb/dvb-usb/az6007.c
+++ /dev/null
@@ -1,955 +0,0 @@
-/*
- * Driver for AzureWave 6007 DVB-C/T USB2.0 and clones
- *
- * Copyright (c) Henry Wang <Henry.wang@AzureWave.com>
- *
- * This driver was made publicly available by Terratec, at:
- *	http://linux.terratec.de/files/TERRATEC_H7/20110323_TERRATEC_H7_Linux.tar.gz
- * The original driver's license is GPL, as declared with MODULE_LICENSE()
- *
- * Copyright (c) 2010-2011 Mauro Carvalho Chehab <mchehab@redhat.com>
- *	Driver modified by in order to work with upstream drxk driver, and
- *	tons of bugs got fixed.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation under version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include "drxk.h"
-#include "mt2063.h"
-#include "dvb_ca_en50221.h"
-
-#define DVB_USB_LOG_PREFIX "az6007"
-#include "dvb-usb.h"
-
-/* debug */
-int dvb_usb_az6007_debug;
-module_param_named(debug, dvb_usb_az6007_debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))."
-		 DVB_USB_DEBUG_STATUS);
-
-#define deb_info(args...) dprintk(dvb_usb_az6007_debug, 0x01, args)
-#define deb_xfer(args...) dprintk(dvb_usb_az6007_debug, 0x02, args)
-#define deb_rc(args...)   dprintk(dvb_usb_az6007_debug, 0x04, args)
-#define deb_fe(args...)   dprintk(dvb_usb_az6007_debug, 0x08, args)
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-/* Known requests (Cypress FX2 firmware + az6007 "private" ones*/
-
-#define FX2_OED			0xb5
-#define AZ6007_READ_DATA	0xb7
-#define AZ6007_I2C_RD		0xb9
-#define AZ6007_POWER		0xbc
-#define AZ6007_I2C_WR		0xbd
-#define FX2_SCON1		0xc0
-#define AZ6007_TS_THROUGH	0xc7
-#define AZ6007_READ_IR		0xb4
-
-struct az6007_device_state {
-	struct mutex		mutex;
-	struct mutex		ca_mutex;
-	struct dvb_ca_en50221	ca;
-	unsigned		warm:1;
-	int			(*gate_ctrl) (struct dvb_frontend *, int);
-	unsigned char		data[4096];
-};
-
-static struct drxk_config terratec_h7_drxk = {
-	.adr = 0x29,
-	.parallel_ts = true,
-	.dynamic_clk = true,
-	.single_master = true,
-	.enable_merr_cfg = true,
-	.no_i2c_bridge = false,
-	.chunk_size = 64,
-	.mpeg_out_clk_strength = 0x02,
-	.microcode_name = "dvb-usb-terratec-h7-drxk.fw",
-};
-
-static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable)
-{
-	struct dvb_usb_adapter *adap = fe->sec_priv;
-	struct az6007_device_state *st;
-	int status = 0;
-
-	deb_info("%s: %s\n", __func__, enable ? "enable" : "disable");
-
-	if (!adap)
-		return -EINVAL;
-
-	st = adap->dev->priv;
-
-	if (!st)
-		return -EINVAL;
-
-	if (enable)
-		status = st->gate_ctrl(fe, 1);
-	else
-		status = st->gate_ctrl(fe, 0);
-
-	return status;
-}
-
-static struct mt2063_config az6007_mt2063_config = {
-	.tuner_address = 0x60,
-	.refclock = 36125000,
-};
-
-static int __az6007_read(struct usb_device *udev, u8 req, u16 value,
-			    u16 index, u8 *b, int blen)
-{
-	int ret;
-
-	ret = usb_control_msg(udev,
-			      usb_rcvctrlpipe(udev, 0),
-			      req,
-			      USB_TYPE_VENDOR | USB_DIR_IN,
-			      value, index, b, blen, 5000);
-	if (ret < 0) {
-		warn("usb read operation failed. (%d)", ret);
-		return -EIO;
-	}
-
-	deb_xfer("in: req. %02x, val: %04x, ind: %04x, buffer: ", req, value,
-		 index);
-	debug_dump(b, blen, deb_xfer);
-
-	return ret;
-}
-
-static int az6007_read(struct dvb_usb_device *d, u8 req, u16 value,
-			    u16 index, u8 *b, int blen)
-{
-	struct az6007_device_state *st = d->priv;
-	int ret;
-
-	if (mutex_lock_interruptible(&st->mutex) < 0)
-		return -EAGAIN;
-
-	ret = __az6007_read(d->udev, req, value, index, b, blen);
-
-	mutex_unlock(&st->mutex);
-
-	return ret;
-}
-
-static int __az6007_write(struct usb_device *udev, u8 req, u16 value,
-			     u16 index, u8 *b, int blen)
-{
-	int ret;
-
-	deb_xfer("out: req. %02x, val: %04x, ind: %04x, buffer: ", req, value,
-		 index);
-	debug_dump(b, blen, deb_xfer);
-
-	if (blen > 64) {
-		err("az6007: tried to write %d bytes, but I2C max size is 64 bytes\n",
-		    blen);
-		return -EOPNOTSUPP;
-	}
-
-	ret = usb_control_msg(udev,
-			      usb_sndctrlpipe(udev, 0),
-			      req,
-			      USB_TYPE_VENDOR | USB_DIR_OUT,
-			      value, index, b, blen, 5000);
-	if (ret != blen) {
-		err("usb write operation failed. (%d)", ret);
-		return -EIO;
-	}
-
-	return 0;
-}
-
-static int az6007_write(struct dvb_usb_device *d, u8 req, u16 value,
-			    u16 index, u8 *b, int blen)
-{
-	struct az6007_device_state *st = d->priv;
-	int ret;
-
-	if (mutex_lock_interruptible(&st->mutex) < 0)
-		return -EAGAIN;
-
-	ret = __az6007_write(d->udev, req, value, index, b, blen);
-
-	mutex_unlock(&st->mutex);
-
-	return ret;
-}
-
-static int az6007_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
-{
-	struct dvb_usb_device *d = adap->dev;
-
-	deb_info("%s: %s", __func__, onoff ? "enable" : "disable");
-
-	return az6007_write(d, 0xbc, onoff, 0, NULL, 0);
-}
-
-/* remote control stuff (does not work with my box) */
-static int az6007_rc_query(struct dvb_usb_device *d)
-{
-	struct az6007_device_state *st = d->priv;
-	unsigned code = 0;
-
-	az6007_read(d, AZ6007_READ_IR, 0, 0, st->data, 10);
-
-	if (st->data[1] == 0x44)
-		return 0;
-
-	if ((st->data[1] ^ st->data[2]) == 0xff)
-		code = st->data[1];
-	else
-		code = st->data[1] << 8 | st->data[2];
-
-	if ((st->data[3] ^ st->data[4]) == 0xff)
-		code = code << 8 | st->data[3];
-	else
-		code = code << 16 | st->data[3] << 8 | st->data[4];
-
-	rc_keydown(d->rc_dev, code, st->data[5]);
-
-	return 0;
-}
-
-static int az6007_ci_read_attribute_mem(struct dvb_ca_en50221 *ca,
-					int slot,
-					int address)
-{
-	struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
-	struct az6007_device_state *state = (struct az6007_device_state *)d->priv;
-
-	int ret;
-	u8 req;
-	u16 value;
-	u16 index;
-	int blen;
-	u8 *b;
-
-	if (slot != 0)
-		return -EINVAL;
-
-	b = kmalloc(12, GFP_KERNEL);
-	if (!b)
-		return -ENOMEM;
-
-	mutex_lock(&state->ca_mutex);
-
-	req = 0xC1;
-	value = address;
-	index = 0;
-	blen = 1;
-
-	ret = az6007_read(d, req, value, index, b, blen);
-	if (ret < 0) {
-		warn("usb in operation failed. (%d)", ret);
-		ret = -EINVAL;
-	} else {
-		ret = b[0];
-	}
-
-	mutex_unlock(&state->ca_mutex);
-	kfree(b);
-	return ret;
-}
-
-static int az6007_ci_write_attribute_mem(struct dvb_ca_en50221 *ca,
-					 int slot,
-					 int address,
-					 u8 value)
-{
-	struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
-	struct az6007_device_state *state = (struct az6007_device_state *)d->priv;
-
-	int ret;
-	u8 req;
-	u16 value1;
-	u16 index;
-	int blen;
-
-	deb_info("%s %d", __func__, slot);
-	if (slot != 0)
-		return -EINVAL;
-
-	mutex_lock(&state->ca_mutex);
-	req = 0xC2;
-	value1 = address;
-	index = value;
-	blen = 0;
-
-	ret = az6007_write(d, req, value1, index, NULL, blen);
-	if (ret != 0)
-		warn("usb out operation failed. (%d)", ret);
-
-	mutex_unlock(&state->ca_mutex);
-	return ret;
-}
-
-static int az6007_ci_read_cam_control(struct dvb_ca_en50221 *ca,
-				      int slot,
-				      u8 address)
-{
-	struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
-	struct az6007_device_state *state = (struct az6007_device_state *)d->priv;
-
-	int ret;
-	u8 req;
-	u16 value;
-	u16 index;
-	int blen;
-	u8 *b;
-
-	if (slot != 0)
-		return -EINVAL;
-
-	b = kmalloc(12, GFP_KERNEL);
-	if (!b)
-		return -ENOMEM;
-
-	mutex_lock(&state->ca_mutex);
-
-	req = 0xC3;
-	value = address;
-	index = 0;
-	blen = 2;
-
-	ret = az6007_read(d, req, value, index, b, blen);
-	if (ret < 0) {
-		warn("usb in operation failed. (%d)", ret);
-		ret = -EINVAL;
-	} else {
-		if (b[0] == 0)
-			warn("Read CI IO error");
-
-		ret = b[1];
-		deb_info("read cam data = %x from 0x%x", b[1], value);
-	}
-
-	mutex_unlock(&state->ca_mutex);
-	kfree(b);
-	return ret;
-}
-
-static int az6007_ci_write_cam_control(struct dvb_ca_en50221 *ca,
-				       int slot,
-				       u8 address,
-				       u8 value)
-{
-	struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
-	struct az6007_device_state *state = (struct az6007_device_state *)d->priv;
-
-	int ret;
-	u8 req;
-	u16 value1;
-	u16 index;
-	int blen;
-
-	if (slot != 0)
-		return -EINVAL;
-
-	mutex_lock(&state->ca_mutex);
-	req = 0xC4;
-	value1 = address;
-	index = value;
-	blen = 0;
-
-	ret = az6007_write(d, req, value1, index, NULL, blen);
-	if (ret != 0) {
-		warn("usb out operation failed. (%d)", ret);
-		goto failed;
-	}
-
-failed:
-	mutex_unlock(&state->ca_mutex);
-	return ret;
-}
-
-static int CI_CamReady(struct dvb_ca_en50221 *ca, int slot)
-{
-	struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
-
-	int ret;
-	u8 req;
-	u16 value;
-	u16 index;
-	int blen;
-	u8 *b;
-
-	b = kmalloc(12, GFP_KERNEL);
-	if (!b)
-		return -ENOMEM;
-
-	req = 0xC8;
-	value = 0;
-	index = 0;
-	blen = 1;
-
-	ret = az6007_read(d, req, value, index, b, blen);
-	if (ret < 0) {
-		warn("usb in operation failed. (%d)", ret);
-		ret = -EIO;
-	} else{
-		ret = b[0];
-	}
-	kfree(b);
-	return ret;
-}
-
-static int az6007_ci_slot_reset(struct dvb_ca_en50221 *ca, int slot)
-{
-	struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
-	struct az6007_device_state *state = (struct az6007_device_state *)d->priv;
-
-	int ret, i;
-	u8 req;
-	u16 value;
-	u16 index;
-	int blen;
-
-	mutex_lock(&state->ca_mutex);
-
-	req = 0xC6;
-	value = 1;
-	index = 0;
-	blen = 0;
-
-	ret = az6007_write(d, req, value, index, NULL, blen);
-	if (ret != 0) {
-		warn("usb out operation failed. (%d)", ret);
-		goto failed;
-	}
-
-	msleep(500);
-	req = 0xC6;
-	value = 0;
-	index = 0;
-	blen = 0;
-
-	ret = az6007_write(d, req, value, index, NULL, blen);
-	if (ret != 0) {
-		warn("usb out operation failed. (%d)", ret);
-		goto failed;
-	}
-
-	for (i = 0; i < 15; i++) {
-		msleep(100);
-
-		if (CI_CamReady(ca, slot)) {
-			deb_info("CAM Ready");
-			break;
-		}
-	}
-	msleep(5000);
-
-failed:
-	mutex_unlock(&state->ca_mutex);
-	return ret;
-}
-
-static int az6007_ci_slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
-{
-	return 0;
-}
-
-static int az6007_ci_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
-{
-	struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
-	struct az6007_device_state *state = (struct az6007_device_state *)d->priv;
-
-	int ret;
-	u8 req;
-	u16 value;
-	u16 index;
-	int blen;
-
-	deb_info("%s", __func__);
-	mutex_lock(&state->ca_mutex);
-	req = 0xC7;
-	value = 1;
-	index = 0;
-	blen = 0;
-
-	ret = az6007_write(d, req, value, index, NULL, blen);
-	if (ret != 0) {
-		warn("usb out operation failed. (%d)", ret);
-		goto failed;
-	}
-
-failed:
-	mutex_unlock(&state->ca_mutex);
-	return ret;
-}
-
-static int az6007_ci_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open)
-{
-	struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
-	struct az6007_device_state *state = (struct az6007_device_state *)d->priv;
-	int ret;
-	u8 req;
-	u16 value;
-	u16 index;
-	int blen;
-	u8 *b;
-
-	b = kmalloc(12, GFP_KERNEL);
-	if (!b)
-		return -ENOMEM;
-	mutex_lock(&state->ca_mutex);
-
-	req = 0xC5;
-	value = 0;
-	index = 0;
-	blen = 1;
-
-	ret = az6007_read(d, req, value, index, b, blen);
-	if (ret < 0) {
-		warn("usb in operation failed. (%d)", ret);
-		ret = -EIO;
-	} else
-		ret = 0;
-
-	if (!ret && b[0] == 1) {
-		ret = DVB_CA_EN50221_POLL_CAM_PRESENT |
-		      DVB_CA_EN50221_POLL_CAM_READY;
-	}
-
-	mutex_unlock(&state->ca_mutex);
-	kfree(b);
-	return ret;
-}
-
-
-static void az6007_ci_uninit(struct dvb_usb_device *d)
-{
-	struct az6007_device_state *state;
-
-	deb_info("%s", __func__);
-
-	if (NULL == d)
-		return;
-
-	state = (struct az6007_device_state *)d->priv;
-	if (NULL == state)
-		return;
-
-	if (NULL == state->ca.data)
-		return;
-
-	dvb_ca_en50221_release(&state->ca);
-
-	memset(&state->ca, 0, sizeof(state->ca));
-}
-
-
-static int az6007_ci_init(struct dvb_usb_adapter *a)
-{
-	struct dvb_usb_device *d = a->dev;
-	struct az6007_device_state *state = (struct az6007_device_state *)d->priv;
-	int ret;
-
-	deb_info("%s", __func__);
-
-	mutex_init(&state->ca_mutex);
-
-	state->ca.owner			= THIS_MODULE;
-	state->ca.read_attribute_mem	= az6007_ci_read_attribute_mem;
-	state->ca.write_attribute_mem	= az6007_ci_write_attribute_mem;
-	state->ca.read_cam_control	= az6007_ci_read_cam_control;
-	state->ca.write_cam_control	= az6007_ci_write_cam_control;
-	state->ca.slot_reset		= az6007_ci_slot_reset;
-	state->ca.slot_shutdown		= az6007_ci_slot_shutdown;
-	state->ca.slot_ts_enable	= az6007_ci_slot_ts_enable;
-	state->ca.poll_slot_status	= az6007_ci_poll_slot_status;
-	state->ca.data			= d;
-
-	ret = dvb_ca_en50221_init(&a->dvb_adap,
-				  &state->ca,
-				  0, /* flags */
-				  1);/* n_slots */
-	if (ret != 0) {
-		err("Cannot initialize CI: Error %d.", ret);
-		memset(&state->ca, 0, sizeof(state->ca));
-		return ret;
-	}
-
-	deb_info("CI initialized.");
-
-	return 0;
-}
-
-static int az6007_read_mac_addr(struct dvb_usb_device *d, u8 mac[6])
-{
-	struct az6007_device_state *st = d->priv;
-	int ret;
-
-	ret = az6007_read(d, AZ6007_READ_DATA, 6, 0, st->data, 6);
-	memcpy(mac, st->data, 6);
-
-	if (ret > 0)
-		deb_info("%s: mac is %pM\n", __func__, mac);
-
-	return ret;
-}
-
-static int az6007_frontend_attach(struct dvb_usb_adapter *adap)
-{
-	struct az6007_device_state *st = adap->dev->priv;
-
-	deb_info("attaching demod drxk");
-
-	adap->fe_adap[0].fe = dvb_attach(drxk_attach, &terratec_h7_drxk,
-					 &adap->dev->i2c_adap);
-	if (!adap->fe_adap[0].fe)
-		return -EINVAL;
-
-	adap->fe_adap[0].fe->sec_priv = adap;
-	st->gate_ctrl = adap->fe_adap[0].fe->ops.i2c_gate_ctrl;
-	adap->fe_adap[0].fe->ops.i2c_gate_ctrl = drxk_gate_ctrl;
-
-	az6007_ci_init(adap);
-
-	return 0;
-}
-
-static int az6007_tuner_attach(struct dvb_usb_adapter *adap)
-{
-	deb_info("attaching tuner mt2063");
-
-	/* Attach mt2063 to DVB-C frontend */
-	if (adap->fe_adap[0].fe->ops.i2c_gate_ctrl)
-		adap->fe_adap[0].fe->ops.i2c_gate_ctrl(adap->fe_adap[0].fe, 1);
-	if (!dvb_attach(mt2063_attach, adap->fe_adap[0].fe,
-			&az6007_mt2063_config,
-			&adap->dev->i2c_adap))
-		return -EINVAL;
-
-	if (adap->fe_adap[0].fe->ops.i2c_gate_ctrl)
-		adap->fe_adap[0].fe->ops.i2c_gate_ctrl(adap->fe_adap[0].fe, 0);
-
-	return 0;
-}
-
-int az6007_power_ctrl(struct dvb_usb_device *d, int onoff)
-{
-	struct az6007_device_state *st = d->priv;
-	int ret;
-
-	deb_info("%s()\n", __func__);
-
-	if (!st->warm) {
-		mutex_init(&st->mutex);
-
-		ret = az6007_write(d, AZ6007_POWER, 0, 2, NULL, 0);
-		if (ret < 0)
-			return ret;
-		msleep(60);
-		ret = az6007_write(d, AZ6007_POWER, 1, 4, NULL, 0);
-		if (ret < 0)
-			return ret;
-		msleep(100);
-		ret = az6007_write(d, AZ6007_POWER, 1, 3, NULL, 0);
-		if (ret < 0)
-			return ret;
-		msleep(20);
-		ret = az6007_write(d, AZ6007_POWER, 1, 4, NULL, 0);
-		if (ret < 0)
-			return ret;
-
-		msleep(400);
-		ret = az6007_write(d, FX2_SCON1, 0, 3, NULL, 0);
-		if (ret < 0)
-			return ret;
-		msleep(150);
-		ret = az6007_write(d, FX2_SCON1, 1, 3, NULL, 0);
-		if (ret < 0)
-			return ret;
-		msleep(430);
-		ret = az6007_write(d, AZ6007_POWER, 0, 0, NULL, 0);
-		if (ret < 0)
-			return ret;
-
-		st->warm = true;
-
-		return 0;
-	}
-
-	if (!onoff)
-		return 0;
-
-	az6007_write(d, AZ6007_POWER, 0, 0, NULL, 0);
-	az6007_write(d, AZ6007_TS_THROUGH, 0, 0, NULL, 0);
-
-	return 0;
-}
-
-/* I2C */
-static int az6007_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
-			   int num)
-{
-	struct dvb_usb_device *d = i2c_get_adapdata(adap);
-	struct az6007_device_state *st = d->priv;
-	int i, j, len;
-	int ret = 0;
-	u16 index;
-	u16 value;
-	int length;
-	u8 req, addr;
-
-	if (mutex_lock_interruptible(&st->mutex) < 0)
-		return -EAGAIN;
-
-	for (i = 0; i < num; i++) {
-		addr = msgs[i].addr << 1;
-		if (((i + 1) < num)
-		    && (msgs[i].len == 1)
-		    && (!msgs[i].flags & I2C_M_RD)
-		    && (msgs[i + 1].flags & I2C_M_RD)
-		    && (msgs[i].addr == msgs[i + 1].addr)) {
-			/*
-			 * A write + read xfer for the same address, where
-			 * the first xfer has just 1 byte length.
-			 * Need to join both into one operation
-			 */
-			if (dvb_usb_az6007_debug & 2)
-				printk(KERN_DEBUG
-				       "az6007 I2C xfer write+read addr=0x%x len=%d/%d: ",
-				       addr, msgs[i].len, msgs[i + 1].len);
-			req = AZ6007_I2C_RD;
-			index = msgs[i].buf[0];
-			value = addr | (1 << 8);
-			length = 6 + msgs[i + 1].len;
-			len = msgs[i + 1].len;
-			ret = __az6007_read(d->udev, req, value, index,
-					    st->data, length);
-			if (ret >= len) {
-				for (j = 0; j < len; j++) {
-					msgs[i + 1].buf[j] = st->data[j + 5];
-					if (dvb_usb_az6007_debug & 2)
-						printk(KERN_CONT
-						       "0x%02x ",
-						       msgs[i + 1].buf[j]);
-				}
-			} else
-				ret = -EIO;
-			i++;
-		} else if (!(msgs[i].flags & I2C_M_RD)) {
-			/* write bytes */
-			if (dvb_usb_az6007_debug & 2)
-				printk(KERN_DEBUG
-				       "az6007 I2C xfer write addr=0x%x len=%d: ",
-				       addr, msgs[i].len);
-			req = AZ6007_I2C_WR;
-			index = msgs[i].buf[0];
-			value = addr | (1 << 8);
-			length = msgs[i].len - 1;
-			len = msgs[i].len - 1;
-			if (dvb_usb_az6007_debug & 2)
-				printk(KERN_CONT "(0x%02x) ", msgs[i].buf[0]);
-			for (j = 0; j < len; j++) {
-				st->data[j] = msgs[i].buf[j + 1];
-				if (dvb_usb_az6007_debug & 2)
-					printk(KERN_CONT "0x%02x ",
-					       st->data[j]);
-			}
-			ret =  __az6007_write(d->udev, req, value, index,
-					      st->data, length);
-		} else {
-			/* read bytes */
-			if (dvb_usb_az6007_debug & 2)
-				printk(KERN_DEBUG
-				       "az6007 I2C xfer read addr=0x%x len=%d: ",
-				       addr, msgs[i].len);
-			req = AZ6007_I2C_RD;
-			index = msgs[i].buf[0];
-			value = addr;
-			length = msgs[i].len + 6;
-			len = msgs[i].len;
-			ret = __az6007_read(d->udev, req, value, index,
-					    st->data, length);
-			for (j = 0; j < len; j++) {
-				msgs[i].buf[j] = st->data[j + 5];
-				if (dvb_usb_az6007_debug & 2)
-					printk(KERN_CONT
-					       "0x%02x ", st->data[j + 5]);
-			}
-		}
-		if (dvb_usb_az6007_debug & 2)
-			printk(KERN_CONT "\n");
-		if (ret < 0)
-			goto err;
-	}
-err:
-	mutex_unlock(&st->mutex);
-
-	if (ret < 0) {
-		info("%s ERROR: %i", __func__, ret);
-		return ret;
-	}
-	return num;
-}
-
-static u32 az6007_i2c_func(struct i2c_adapter *adapter)
-{
-	return I2C_FUNC_I2C;
-}
-
-static struct i2c_algorithm az6007_i2c_algo = {
-	.master_xfer = az6007_i2c_xfer,
-	.functionality = az6007_i2c_func,
-};
-
-int az6007_identify_state(struct usb_device *udev,
-			  struct dvb_usb_device_properties *props,
-			  struct dvb_usb_device_description **desc, int *cold)
-{
-	int ret;
-	u8 *mac;
-
-	mac = kmalloc(6, GFP_ATOMIC);
-	if (!mac)
-		return -ENOMEM;
-
-	/* Try to read the mac address */
-	ret = __az6007_read(udev, AZ6007_READ_DATA, 6, 0, mac, 6);
-	if (ret == 6)
-		*cold = 0;
-	else
-		*cold = 1;
-
-	kfree(mac);
-
-	if (*cold) {
-		__az6007_write(udev, 0x09, 1, 0, NULL, 0);
-		__az6007_write(udev, 0x00, 0, 0, NULL, 0);
-		__az6007_write(udev, 0x00, 0, 0, NULL, 0);
-	}
-
-	deb_info("Device is on %s state\n", *cold ? "warm" : "cold");
-	return 0;
-}
-
-static struct dvb_usb_device_properties az6007_properties;
-
-static void az6007_usb_disconnect(struct usb_interface *intf)
-{
-	struct dvb_usb_device *d = usb_get_intfdata(intf);
-	az6007_ci_uninit(d);
-	dvb_usb_device_exit(intf);
-}
-
-static int az6007_usb_probe(struct usb_interface *intf,
-			    const struct usb_device_id *id)
-{
-	return dvb_usb_device_init(intf, &az6007_properties,
-				   THIS_MODULE, NULL, adapter_nr);
-}
-
-static struct usb_device_id az6007_usb_table[] = {
-	{USB_DEVICE(USB_VID_AZUREWAVE, USB_PID_AZUREWAVE_6007)},
-	{USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_H7)},
-	{USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_H7_2)},
-	{0},
-};
-
-MODULE_DEVICE_TABLE(usb, az6007_usb_table);
-
-static struct dvb_usb_device_properties az6007_properties = {
-	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
-	.usb_ctrl = CYPRESS_FX2,
-	.firmware            = "dvb-usb-terratec-h7-az6007.fw",
-	.no_reconnect        = 1,
-	.size_of_priv        = sizeof(struct az6007_device_state),
-	.identify_state	     = az6007_identify_state,
-	.num_adapters = 1,
-	.adapter = {
-		{
-		.num_frontends = 1,
-		.fe = {{
-			.streaming_ctrl   = az6007_streaming_ctrl,
-			.tuner_attach     = az6007_tuner_attach,
-			.frontend_attach  = az6007_frontend_attach,
-
-			/* parameter for the MPEG2-data transfer */
-			.stream = {
-				.type = USB_BULK,
-				.count = 10,
-				.endpoint = 0x02,
-				.u = {
-					.bulk = {
-						.buffersize = 4096,
-					}
-				}
-			},
-		} }
-	} },
-	.power_ctrl       = az6007_power_ctrl,
-	.read_mac_address = az6007_read_mac_addr,
-
-	.rc.core = {
-		.rc_interval      = 400,
-		.rc_codes         = RC_MAP_NEC_TERRATEC_CINERGY_XS,
-		.module_name	  = "az6007",
-		.rc_query         = az6007_rc_query,
-		.allowed_protos   = RC_TYPE_NEC,
-	},
-	.i2c_algo         = &az6007_i2c_algo,
-
-	.num_device_descs = 2,
-	.devices = {
-		{ .name = "AzureWave DTV StarBox DVB-T/C USB2.0 (az6007)",
-		  .cold_ids = { &az6007_usb_table[0], NULL },
-		  .warm_ids = { NULL },
-		},
-		{ .name = "TerraTec DTV StarBox DVB-T/C USB2.0 (az6007)",
-		  .cold_ids = { &az6007_usb_table[1], &az6007_usb_table[2], NULL },
-		  .warm_ids = { NULL },
-		},
-		{ NULL },
-	}
-};
-
-/* usb specific object needed to register this driver with the usb subsystem */
-static struct usb_driver az6007_usb_driver = {
-	.name		= "dvb_usb_az6007",
-	.probe		= az6007_usb_probe,
-	.disconnect	= az6007_usb_disconnect,
-	.id_table	= az6007_usb_table,
-};
-
-/* module stuff */
-static int __init az6007_usb_module_init(void)
-{
-	int result;
-	deb_info("az6007 usb module init\n");
-
-	result = usb_register(&az6007_usb_driver);
-	if (result) {
-		err("usb_register failed. (%d)", result);
-		return result;
-	}
-
-	return 0;
-}
-
-static void __exit az6007_usb_module_exit(void)
-{
-	/* deregister this driver from the USB subsystem */
-	deb_info("az6007 usb module exit\n");
-	usb_deregister(&az6007_usb_driver);
-}
-
-module_init(az6007_usb_module_init);
-module_exit(az6007_usb_module_exit);
-
-MODULE_AUTHOR("Henry Wang <Henry.wang@AzureWave.com>");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
-MODULE_DESCRIPTION("Driver for AzureWave 6007 DVB-C/T USB2.0 and clones");
-MODULE_VERSION("1.1");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/az6027.c b/drivers/media/dvb/dvb-usb/az6027.c
deleted file mode 100644
index 5e45ae6..0000000
--- a/drivers/media/dvb/dvb-usb/az6027.c
+++ /dev/null
@@ -1,1182 +0,0 @@
-/* DVB USB compliant Linux driver for the AZUREWAVE DVB-S/S2 USB2.0 (AZ6027)
- * receiver.
- *
- * Copyright (C) 2009 Adams.Xu <adams.xu@azwave.com.cn>
- *
- *	This program is free software; 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.
- *
- * see Documentation/dvb/README.dvb-usb for more information
- */
-#include "az6027.h"
-
-#include "stb0899_drv.h"
-#include "stb0899_reg.h"
-#include "stb0899_cfg.h"
-
-#include "stb6100.h"
-#include "stb6100_cfg.h"
-#include "dvb_ca_en50221.h"
-
-int dvb_usb_az6027_debug;
-module_param_named(debug, dvb_usb_az6027_debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS);
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-struct az6027_device_state {
-	struct dvb_ca_en50221 ca;
-	struct mutex ca_mutex;
-	u8 power_state;
-};
-
-static const struct stb0899_s1_reg az6027_stb0899_s1_init_1[] = {
-
-	/* 0x0000000b, SYSREG */
-	{ STB0899_DEV_ID		, 0x30 },
-	{ STB0899_DISCNTRL1		, 0x32 },
-	{ STB0899_DISCNTRL2     	, 0x80 },
-	{ STB0899_DISRX_ST0     	, 0x04 },
-	{ STB0899_DISRX_ST1     	, 0x00 },
-	{ STB0899_DISPARITY     	, 0x00 },
-	{ STB0899_DISSTATUS		, 0x20 },
-	{ STB0899_DISF22        	, 0x99 },
-	{ STB0899_DISF22RX      	, 0xa8 },
-	/* SYSREG ? */
-	{ STB0899_ACRPRESC      	, 0x11 },
-	{ STB0899_ACRDIV1       	, 0x0a },
-	{ STB0899_ACRDIV2       	, 0x05 },
-	{ STB0899_DACR1         	, 0x00 },
-	{ STB0899_DACR2         	, 0x00 },
-	{ STB0899_OUTCFG        	, 0x00 },
-	{ STB0899_MODECFG       	, 0x00 },
-	{ STB0899_IRQSTATUS_3		, 0xfe },
-	{ STB0899_IRQSTATUS_2		, 0x03 },
-	{ STB0899_IRQSTATUS_1		, 0x7c },
-	{ STB0899_IRQSTATUS_0		, 0xf4 },
-	{ STB0899_IRQMSK_3      	, 0xf3 },
-	{ STB0899_IRQMSK_2      	, 0xfc },
-	{ STB0899_IRQMSK_1      	, 0xff },
-	{ STB0899_IRQMSK_0		, 0xff },
-	{ STB0899_IRQCFG		, 0x00 },
-	{ STB0899_I2CCFG        	, 0x88 },
-	{ STB0899_I2CRPT        	, 0x58 },
-	{ STB0899_IOPVALUE5		, 0x00 },
-	{ STB0899_IOPVALUE4		, 0x33 },
-	{ STB0899_IOPVALUE3		, 0x6d },
-	{ STB0899_IOPVALUE2		, 0x90 },
-	{ STB0899_IOPVALUE1		, 0x60 },
-	{ STB0899_IOPVALUE0		, 0x00 },
-	{ STB0899_GPIO00CFG     	, 0x82 },
-	{ STB0899_GPIO01CFG     	, 0x82 },
-	{ STB0899_GPIO02CFG     	, 0x82 },
-	{ STB0899_GPIO03CFG     	, 0x82 },
-	{ STB0899_GPIO04CFG     	, 0x82 },
-	{ STB0899_GPIO05CFG     	, 0x82 },
-	{ STB0899_GPIO06CFG     	, 0x82 },
-	{ STB0899_GPIO07CFG     	, 0x82 },
-	{ STB0899_GPIO08CFG     	, 0x82 },
-	{ STB0899_GPIO09CFG     	, 0x82 },
-	{ STB0899_GPIO10CFG     	, 0x82 },
-	{ STB0899_GPIO11CFG     	, 0x82 },
-	{ STB0899_GPIO12CFG     	, 0x82 },
-	{ STB0899_GPIO13CFG     	, 0x82 },
-	{ STB0899_GPIO14CFG     	, 0x82 },
-	{ STB0899_GPIO15CFG     	, 0x82 },
-	{ STB0899_GPIO16CFG     	, 0x82 },
-	{ STB0899_GPIO17CFG     	, 0x82 },
-	{ STB0899_GPIO18CFG     	, 0x82 },
-	{ STB0899_GPIO19CFG     	, 0x82 },
-	{ STB0899_GPIO20CFG     	, 0x82 },
-	{ STB0899_SDATCFG       	, 0xb8 },
-	{ STB0899_SCLTCFG       	, 0xba },
-	{ STB0899_AGCRFCFG      	, 0x1c }, /* 0x11 */
-	{ STB0899_GPIO22        	, 0x82 }, /* AGCBB2CFG */
-	{ STB0899_GPIO21        	, 0x91 }, /* AGCBB1CFG */
-	{ STB0899_DIRCLKCFG     	, 0x82 },
-	{ STB0899_CLKOUT27CFG   	, 0x7e },
-	{ STB0899_STDBYCFG      	, 0x82 },
-	{ STB0899_CS0CFG        	, 0x82 },
-	{ STB0899_CS1CFG        	, 0x82 },
-	{ STB0899_DISEQCOCFG    	, 0x20 },
-	{ STB0899_GPIO32CFG		, 0x82 },
-	{ STB0899_GPIO33CFG		, 0x82 },
-	{ STB0899_GPIO34CFG		, 0x82 },
-	{ STB0899_GPIO35CFG		, 0x82 },
-	{ STB0899_GPIO36CFG		, 0x82 },
-	{ STB0899_GPIO37CFG		, 0x82 },
-	{ STB0899_GPIO38CFG		, 0x82 },
-	{ STB0899_GPIO39CFG		, 0x82 },
-	{ STB0899_NCOARSE       	, 0x17 }, /* 0x15 = 27 Mhz Clock, F/3 = 198MHz, F/6 = 99MHz */
-	{ STB0899_SYNTCTRL      	, 0x02 }, /* 0x00 = CLK from CLKI, 0x02 = CLK from XTALI */
-	{ STB0899_FILTCTRL      	, 0x00 },
-	{ STB0899_SYSCTRL       	, 0x01 },
-	{ STB0899_STOPCLK1      	, 0x20 },
-	{ STB0899_STOPCLK2      	, 0x00 },
-	{ STB0899_INTBUFSTATUS		, 0x00 },
-	{ STB0899_INTBUFCTRL    	, 0x0a },
-	{ 0xffff			, 0xff },
-};
-
-static const struct stb0899_s1_reg az6027_stb0899_s1_init_3[] = {
-	{ STB0899_DEMOD         	, 0x00 },
-	{ STB0899_RCOMPC        	, 0xc9 },
-	{ STB0899_AGC1CN        	, 0x01 },
-	{ STB0899_AGC1REF       	, 0x10 },
-	{ STB0899_RTC			, 0x23 },
-	{ STB0899_TMGCFG        	, 0x4e },
-	{ STB0899_AGC2REF       	, 0x34 },
-	{ STB0899_TLSR          	, 0x84 },
-	{ STB0899_CFD           	, 0xf7 },
-	{ STB0899_ACLC			, 0x87 },
-	{ STB0899_BCLC          	, 0x94 },
-	{ STB0899_EQON          	, 0x41 },
-	{ STB0899_LDT           	, 0xf1 },
-	{ STB0899_LDT2          	, 0xe3 },
-	{ STB0899_EQUALREF      	, 0xb4 },
-	{ STB0899_TMGRAMP       	, 0x10 },
-	{ STB0899_TMGTHD        	, 0x30 },
-	{ STB0899_IDCCOMP		, 0xfd },
-	{ STB0899_QDCCOMP		, 0xff },
-	{ STB0899_POWERI		, 0x0c },
-	{ STB0899_POWERQ		, 0x0f },
-	{ STB0899_RCOMP			, 0x6c },
-	{ STB0899_AGCIQIN		, 0x80 },
-	{ STB0899_AGC2I1		, 0x06 },
-	{ STB0899_AGC2I2		, 0x00 },
-	{ STB0899_TLIR			, 0x30 },
-	{ STB0899_RTF			, 0x7f },
-	{ STB0899_DSTATUS		, 0x00 },
-	{ STB0899_LDI			, 0xbc },
-	{ STB0899_CFRM			, 0xea },
-	{ STB0899_CFRL			, 0x31 },
-	{ STB0899_NIRM			, 0x2b },
-	{ STB0899_NIRL			, 0x80 },
-	{ STB0899_ISYMB			, 0x1d },
-	{ STB0899_QSYMB			, 0xa6 },
-	{ STB0899_SFRH          	, 0x2f },
-	{ STB0899_SFRM          	, 0x68 },
-	{ STB0899_SFRL          	, 0x40 },
-	{ STB0899_SFRUPH        	, 0x2f },
-	{ STB0899_SFRUPM        	, 0x68 },
-	{ STB0899_SFRUPL        	, 0x40 },
-	{ STB0899_EQUAI1		, 0x02 },
-	{ STB0899_EQUAQ1		, 0xff },
-	{ STB0899_EQUAI2		, 0x04 },
-	{ STB0899_EQUAQ2		, 0x05 },
-	{ STB0899_EQUAI3		, 0x02 },
-	{ STB0899_EQUAQ3		, 0xfd },
-	{ STB0899_EQUAI4		, 0x03 },
-	{ STB0899_EQUAQ4		, 0x07 },
-	{ STB0899_EQUAI5		, 0x08 },
-	{ STB0899_EQUAQ5		, 0xf5 },
-	{ STB0899_DSTATUS2		, 0x00 },
-	{ STB0899_VSTATUS       	, 0x00 },
-	{ STB0899_VERROR		, 0x86 },
-	{ STB0899_IQSWAP		, 0x2a },
-	{ STB0899_ECNT1M		, 0x00 },
-	{ STB0899_ECNT1L		, 0x00 },
-	{ STB0899_ECNT2M		, 0x00 },
-	{ STB0899_ECNT2L		, 0x00 },
-	{ STB0899_ECNT3M		, 0x0a },
-	{ STB0899_ECNT3L		, 0xad },
-	{ STB0899_FECAUTO1      	, 0x06 },
-	{ STB0899_FECM			, 0x01 },
-	{ STB0899_VTH12         	, 0xb0 },
-	{ STB0899_VTH23         	, 0x7a },
-	{ STB0899_VTH34			, 0x58 },
-	{ STB0899_VTH56         	, 0x38 },
-	{ STB0899_VTH67         	, 0x34 },
-	{ STB0899_VTH78         	, 0x24 },
-	{ STB0899_PRVIT         	, 0xff },
-	{ STB0899_VITSYNC       	, 0x19 },
-	{ STB0899_RSULC         	, 0xb1 }, /* DVB = 0xb1, DSS = 0xa1 */
-	{ STB0899_TSULC         	, 0x42 },
-	{ STB0899_RSLLC         	, 0x41 },
-	{ STB0899_TSLPL			, 0x12 },
-	{ STB0899_TSCFGH        	, 0x0c },
-	{ STB0899_TSCFGM        	, 0x00 },
-	{ STB0899_TSCFGL        	, 0x00 },
-	{ STB0899_TSOUT			, 0x69 }, /* 0x0d for CAM */
-	{ STB0899_RSSYNCDEL     	, 0x00 },
-	{ STB0899_TSINHDELH     	, 0x02 },
-	{ STB0899_TSINHDELM		, 0x00 },
-	{ STB0899_TSINHDELL		, 0x00 },
-	{ STB0899_TSLLSTKM		, 0x1b },
-	{ STB0899_TSLLSTKL		, 0xb3 },
-	{ STB0899_TSULSTKM		, 0x00 },
-	{ STB0899_TSULSTKL		, 0x00 },
-	{ STB0899_PCKLENUL		, 0xbc },
-	{ STB0899_PCKLENLL		, 0xcc },
-	{ STB0899_RSPCKLEN		, 0xbd },
-	{ STB0899_TSSTATUS		, 0x90 },
-	{ STB0899_ERRCTRL1      	, 0xb6 },
-	{ STB0899_ERRCTRL2      	, 0x95 },
-	{ STB0899_ERRCTRL3      	, 0x8d },
-	{ STB0899_DMONMSK1		, 0x27 },
-	{ STB0899_DMONMSK0		, 0x03 },
-	{ STB0899_DEMAPVIT      	, 0x5c },
-	{ STB0899_PLPARM		, 0x19 },
-	{ STB0899_PDELCTRL      	, 0x48 },
-	{ STB0899_PDELCTRL2     	, 0x00 },
-	{ STB0899_BBHCTRL1      	, 0x00 },
-	{ STB0899_BBHCTRL2      	, 0x00 },
-	{ STB0899_HYSTTHRESH    	, 0x77 },
-	{ STB0899_MATCSTM		, 0x00 },
-	{ STB0899_MATCSTL		, 0x00 },
-	{ STB0899_UPLCSTM		, 0x00 },
-	{ STB0899_UPLCSTL		, 0x00 },
-	{ STB0899_DFLCSTM		, 0x00 },
-	{ STB0899_DFLCSTL		, 0x00 },
-	{ STB0899_SYNCCST		, 0x00 },
-	{ STB0899_SYNCDCSTM		, 0x00 },
-	{ STB0899_SYNCDCSTL		, 0x00 },
-	{ STB0899_ISI_ENTRY		, 0x00 },
-	{ STB0899_ISI_BIT_EN		, 0x00 },
-	{ STB0899_MATSTRM		, 0xf0 },
-	{ STB0899_MATSTRL		, 0x02 },
-	{ STB0899_UPLSTRM		, 0x45 },
-	{ STB0899_UPLSTRL		, 0x60 },
-	{ STB0899_DFLSTRM		, 0xe3 },
-	{ STB0899_DFLSTRL		, 0x00 },
-	{ STB0899_SYNCSTR		, 0x47 },
-	{ STB0899_SYNCDSTRM		, 0x05 },
-	{ STB0899_SYNCDSTRL		, 0x18 },
-	{ STB0899_CFGPDELSTATUS1	, 0x19 },
-	{ STB0899_CFGPDELSTATUS2	, 0x2b },
-	{ STB0899_BBFERRORM		, 0x00 },
-	{ STB0899_BBFERRORL		, 0x01 },
-	{ STB0899_UPKTERRORM		, 0x00 },
-	{ STB0899_UPKTERRORL		, 0x00 },
-	{ 0xffff			, 0xff },
-};
-
-
-
-struct stb0899_config az6027_stb0899_config = {
-	.init_dev		= az6027_stb0899_s1_init_1,
-	.init_s2_demod		= stb0899_s2_init_2,
-	.init_s1_demod		= az6027_stb0899_s1_init_3,
-	.init_s2_fec		= stb0899_s2_init_4,
-	.init_tst		= stb0899_s1_init_5,
-
-	.demod_address 		= 0xd0, /* 0x68, 0xd0 >> 1 */
-
-	.xtal_freq		= 27000000,
-	.inversion		= IQ_SWAP_ON, /* 1 */
-
-	.lo_clk			= 76500000,
-	.hi_clk			= 99000000,
-
-	.esno_ave		= STB0899_DVBS2_ESNO_AVE,
-	.esno_quant		= STB0899_DVBS2_ESNO_QUANT,
-	.avframes_coarse	= STB0899_DVBS2_AVFRAMES_COARSE,
-	.avframes_fine		= STB0899_DVBS2_AVFRAMES_FINE,
-	.miss_threshold		= STB0899_DVBS2_MISS_THRESHOLD,
-	.uwp_threshold_acq	= STB0899_DVBS2_UWP_THRESHOLD_ACQ,
-	.uwp_threshold_track	= STB0899_DVBS2_UWP_THRESHOLD_TRACK,
-	.uwp_threshold_sof	= STB0899_DVBS2_UWP_THRESHOLD_SOF,
-	.sof_search_timeout	= STB0899_DVBS2_SOF_SEARCH_TIMEOUT,
-
-	.btr_nco_bits		= STB0899_DVBS2_BTR_NCO_BITS,
-	.btr_gain_shift_offset	= STB0899_DVBS2_BTR_GAIN_SHIFT_OFFSET,
-	.crl_nco_bits		= STB0899_DVBS2_CRL_NCO_BITS,
-	.ldpc_max_iter		= STB0899_DVBS2_LDPC_MAX_ITER,
-
-	.tuner_get_frequency	= stb6100_get_frequency,
-	.tuner_set_frequency	= stb6100_set_frequency,
-	.tuner_set_bandwidth	= stb6100_set_bandwidth,
-	.tuner_get_bandwidth	= stb6100_get_bandwidth,
-	.tuner_set_rfsiggain	= NULL,
-};
-
-struct stb6100_config az6027_stb6100_config = {
-	.tuner_address	= 0xc0,
-	.refclock	= 27000000,
-};
-
-
-/* check for mutex FIXME */
-int az6027_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen)
-{
-	int ret = -1;
-	if (mutex_lock_interruptible(&d->usb_mutex))
-		return -EAGAIN;
-
-	ret = usb_control_msg(d->udev,
-			      usb_rcvctrlpipe(d->udev, 0),
-			      req,
-			      USB_TYPE_VENDOR | USB_DIR_IN,
-			      value,
-			      index,
-			      b,
-			      blen,
-			      2000);
-
-	if (ret < 0) {
-		warn("usb in operation failed. (%d)", ret);
-		ret = -EIO;
-	} else
-		ret = 0;
-
-	deb_xfer("in: req. %02x, val: %04x, ind: %04x, buffer: ", req, value, index);
-	debug_dump(b, blen, deb_xfer);
-
-	mutex_unlock(&d->usb_mutex);
-	return ret;
-}
-
-static int az6027_usb_out_op(struct dvb_usb_device *d,
-			     u8 req,
-			     u16 value,
-			     u16 index,
-			     u8 *b,
-			     int blen)
-{
-	int ret;
-
-	deb_xfer("out: req. %02x, val: %04x, ind: %04x, buffer: ", req, value, index);
-	debug_dump(b, blen, deb_xfer);
-
-	if (mutex_lock_interruptible(&d->usb_mutex))
-		return -EAGAIN;
-
-	ret = usb_control_msg(d->udev,
-			      usb_sndctrlpipe(d->udev, 0),
-			      req,
-			      USB_TYPE_VENDOR | USB_DIR_OUT,
-			      value,
-			      index,
-			      b,
-			      blen,
-			      2000);
-
-	if (ret != blen) {
-		warn("usb out operation failed. (%d)", ret);
-		mutex_unlock(&d->usb_mutex);
-		return -EIO;
-	} else{
-		mutex_unlock(&d->usb_mutex);
-		return 0;
-	}
-}
-
-static int az6027_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
-{
-	int ret;
-	u8 req;
-	u16 value;
-	u16 index;
-	int blen;
-
-	deb_info("%s %d", __func__, onoff);
-
-	req = 0xBC;
-	value = onoff;
-	index = 0;
-	blen = 0;
-
-	ret = az6027_usb_out_op(adap->dev, req, value, index, NULL, blen);
-	if (ret != 0)
-		warn("usb out operation failed. (%d)", ret);
-
-	return ret;
-}
-
-/* keys for the enclosed remote control */
-static struct rc_map_table rc_map_az6027_table[] = {
-	{ 0x01, KEY_1 },
-	{ 0x02, KEY_2 },
-};
-
-/* remote control stuff (does not work with my box) */
-static int az6027_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
-{
-	return 0;
-}
-
-/*
-int az6027_power_ctrl(struct dvb_usb_device *d, int onoff)
-{
-	u8 v = onoff;
-	return az6027_usb_out_op(d,0xBC,v,3,NULL,1);
-}
-*/
-
-static int az6027_ci_read_attribute_mem(struct dvb_ca_en50221 *ca,
-					int slot,
-					int address)
-{
-	struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
-	struct az6027_device_state *state = (struct az6027_device_state *)d->priv;
-
-	int ret;
-	u8 req;
-	u16 value;
-	u16 index;
-	int blen;
-	u8 *b;
-
-	if (slot != 0)
-		return -EINVAL;
-
-	b = kmalloc(12, GFP_KERNEL);
-	if (!b)
-		return -ENOMEM;
-
-	mutex_lock(&state->ca_mutex);
-
-	req = 0xC1;
-	value = address;
-	index = 0;
-	blen = 1;
-
-	ret = az6027_usb_in_op(d, req, value, index, b, blen);
-	if (ret < 0) {
-		warn("usb in operation failed. (%d)", ret);
-		ret = -EINVAL;
-	} else {
-		ret = b[0];
-	}
-
-	mutex_unlock(&state->ca_mutex);
-	kfree(b);
-	return ret;
-}
-
-static int az6027_ci_write_attribute_mem(struct dvb_ca_en50221 *ca,
-					 int slot,
-					 int address,
-					 u8 value)
-{
-	struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
-	struct az6027_device_state *state = (struct az6027_device_state *)d->priv;
-
-	int ret;
-	u8 req;
-	u16 value1;
-	u16 index;
-	int blen;
-
-	deb_info("%s %d", __func__, slot);
-	if (slot != 0)
-		return -EINVAL;
-
-	mutex_lock(&state->ca_mutex);
-	req = 0xC2;
-	value1 = address;
-	index = value;
-	blen = 0;
-
-	ret = az6027_usb_out_op(d, req, value1, index, NULL, blen);
-	if (ret != 0)
-		warn("usb out operation failed. (%d)", ret);
-
-	mutex_unlock(&state->ca_mutex);
-	return ret;
-}
-
-static int az6027_ci_read_cam_control(struct dvb_ca_en50221 *ca,
-				      int slot,
-				      u8 address)
-{
-	struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
-	struct az6027_device_state *state = (struct az6027_device_state *)d->priv;
-
-	int ret;
-	u8 req;
-	u16 value;
-	u16 index;
-	int blen;
-	u8 *b;
-
-	if (slot != 0)
-		return -EINVAL;
-
-	b = kmalloc(12, GFP_KERNEL);
-	if (!b)
-		return -ENOMEM;
-
-	mutex_lock(&state->ca_mutex);
-
-	req = 0xC3;
-	value = address;
-	index = 0;
-	blen = 2;
-
-	ret = az6027_usb_in_op(d, req, value, index, b, blen);
-	if (ret < 0) {
-		warn("usb in operation failed. (%d)", ret);
-		ret = -EINVAL;
-	} else {
-		if (b[0] == 0)
-			warn("Read CI IO error");
-
-		ret = b[1];
-		deb_info("read cam data = %x from 0x%x", b[1], value);
-	}
-
-	mutex_unlock(&state->ca_mutex);
-	kfree(b);
-	return ret;
-}
-
-static int az6027_ci_write_cam_control(struct dvb_ca_en50221 *ca,
-				       int slot,
-				       u8 address,
-				       u8 value)
-{
-	struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
-	struct az6027_device_state *state = (struct az6027_device_state *)d->priv;
-
-	int ret;
-	u8 req;
-	u16 value1;
-	u16 index;
-	int blen;
-
-	if (slot != 0)
-		return -EINVAL;
-
-	mutex_lock(&state->ca_mutex);
-	req = 0xC4;
-	value1 = address;
-	index = value;
-	blen = 0;
-
-	ret = az6027_usb_out_op(d, req, value1, index, NULL, blen);
-	if (ret != 0) {
-		warn("usb out operation failed. (%d)", ret);
-		goto failed;
-	}
-
-failed:
-	mutex_unlock(&state->ca_mutex);
-	return ret;
-}
-
-static int CI_CamReady(struct dvb_ca_en50221 *ca, int slot)
-{
-	struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
-
-	int ret;
-	u8 req;
-	u16 value;
-	u16 index;
-	int blen;
-	u8 *b;
-
-	b = kmalloc(12, GFP_KERNEL);
-	if (!b)
-		return -ENOMEM;
-
-	req = 0xC8;
-	value = 0;
-	index = 0;
-	blen = 1;
-
-	ret = az6027_usb_in_op(d, req, value, index, b, blen);
-	if (ret < 0) {
-		warn("usb in operation failed. (%d)", ret);
-		ret = -EIO;
-	} else{
-		ret = b[0];
-	}
-	kfree(b);
-	return ret;
-}
-
-static int az6027_ci_slot_reset(struct dvb_ca_en50221 *ca, int slot)
-{
-	struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
-	struct az6027_device_state *state = (struct az6027_device_state *)d->priv;
-
-	int ret, i;
-	u8 req;
-	u16 value;
-	u16 index;
-	int blen;
-
-	mutex_lock(&state->ca_mutex);
-
-	req = 0xC6;
-	value = 1;
-	index = 0;
-	blen = 0;
-
-	ret = az6027_usb_out_op(d, req, value, index, NULL, blen);
-	if (ret != 0) {
-		warn("usb out operation failed. (%d)", ret);
-		goto failed;
-	}
-
-	msleep(500);
-	req = 0xC6;
-	value = 0;
-	index = 0;
-	blen = 0;
-
-	ret = az6027_usb_out_op(d, req, value, index, NULL, blen);
-	if (ret != 0) {
-		warn("usb out operation failed. (%d)", ret);
-		goto failed;
-	}
-
-	for (i = 0; i < 15; i++) {
-		msleep(100);
-
-		if (CI_CamReady(ca, slot)) {
-			deb_info("CAM Ready");
-			break;
-		}
-	}
-	msleep(5000);
-
-failed:
-	mutex_unlock(&state->ca_mutex);
-	return ret;
-}
-
-static int az6027_ci_slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
-{
-	return 0;
-}
-
-static int az6027_ci_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
-{
-	struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
-	struct az6027_device_state *state = (struct az6027_device_state *)d->priv;
-
-	int ret;
-	u8 req;
-	u16 value;
-	u16 index;
-	int blen;
-
-	deb_info("%s", __func__);
-	mutex_lock(&state->ca_mutex);
-	req = 0xC7;
-	value = 1;
-	index = 0;
-	blen = 0;
-
-	ret = az6027_usb_out_op(d, req, value, index, NULL, blen);
-	if (ret != 0) {
-		warn("usb out operation failed. (%d)", ret);
-		goto failed;
-	}
-
-failed:
-	mutex_unlock(&state->ca_mutex);
-	return ret;
-}
-
-static int az6027_ci_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open)
-{
-	struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
-	struct az6027_device_state *state = (struct az6027_device_state *)d->priv;
-	int ret;
-	u8 req;
-	u16 value;
-	u16 index;
-	int blen;
-	u8 *b;
-
-	b = kmalloc(12, GFP_KERNEL);
-	if (!b)
-		return -ENOMEM;
-	mutex_lock(&state->ca_mutex);
-
-	req = 0xC5;
-	value = 0;
-	index = 0;
-	blen = 1;
-
-	ret = az6027_usb_in_op(d, req, value, index, b, blen);
-	if (ret < 0) {
-		warn("usb in operation failed. (%d)", ret);
-		ret = -EIO;
-	} else
-		ret = 0;
-
-	if (!ret && b[0] == 1) {
-		ret = DVB_CA_EN50221_POLL_CAM_PRESENT |
-		      DVB_CA_EN50221_POLL_CAM_READY;
-	}
-
-	mutex_unlock(&state->ca_mutex);
-	kfree(b);
-	return ret;
-}
-
-
-static void az6027_ci_uninit(struct dvb_usb_device *d)
-{
-	struct az6027_device_state *state;
-
-	deb_info("%s", __func__);
-
-	if (NULL == d)
-		return;
-
-	state = (struct az6027_device_state *)d->priv;
-	if (NULL == state)
-		return;
-
-	if (NULL == state->ca.data)
-		return;
-
-	dvb_ca_en50221_release(&state->ca);
-
-	memset(&state->ca, 0, sizeof(state->ca));
-}
-
-
-static int az6027_ci_init(struct dvb_usb_adapter *a)
-{
-	struct dvb_usb_device *d = a->dev;
-	struct az6027_device_state *state = (struct az6027_device_state *)d->priv;
-	int ret;
-
-	deb_info("%s", __func__);
-
-	mutex_init(&state->ca_mutex);
-
-	state->ca.owner			= THIS_MODULE;
-	state->ca.read_attribute_mem	= az6027_ci_read_attribute_mem;
-	state->ca.write_attribute_mem	= az6027_ci_write_attribute_mem;
-	state->ca.read_cam_control	= az6027_ci_read_cam_control;
-	state->ca.write_cam_control	= az6027_ci_write_cam_control;
-	state->ca.slot_reset		= az6027_ci_slot_reset;
-	state->ca.slot_shutdown		= az6027_ci_slot_shutdown;
-	state->ca.slot_ts_enable	= az6027_ci_slot_ts_enable;
-	state->ca.poll_slot_status	= az6027_ci_poll_slot_status;
-	state->ca.data			= d;
-
-	ret = dvb_ca_en50221_init(&a->dvb_adap,
-				  &state->ca,
-				  0, /* flags */
-				  1);/* n_slots */
-	if (ret != 0) {
-		err("Cannot initialize CI: Error %d.", ret);
-		memset(&state->ca, 0, sizeof(state->ca));
-		return ret;
-	}
-
-	deb_info("CI initialized.");
-
-	return 0;
-}
-
-/*
-static int az6027_read_mac_addr(struct dvb_usb_device *d, u8 mac[6])
-{
-	az6027_usb_in_op(d, 0xb7, 6, 0, &mac[0], 6);
-	return 0;
-}
-*/
-
-static int az6027_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
-{
-
-	u8 buf;
-	struct dvb_usb_adapter *adap = fe->dvb->priv;
-
-	struct i2c_msg i2c_msg = {
-		.addr	= 0x99,
-		.flags	= 0,
-		.buf	= &buf,
-		.len	= 1
-	};
-
-	/*
-	 * 2   --18v
-	 * 1   --13v
-	 * 0   --off
-	 */
-	switch (voltage) {
-	case SEC_VOLTAGE_13:
-		buf = 1;
-		i2c_transfer(&adap->dev->i2c_adap, &i2c_msg, 1);
-		break;
-
-	case SEC_VOLTAGE_18:
-		buf = 2;
-		i2c_transfer(&adap->dev->i2c_adap, &i2c_msg, 1);
-		break;
-
-	case SEC_VOLTAGE_OFF:
-		buf = 0;
-		i2c_transfer(&adap->dev->i2c_adap, &i2c_msg, 1);
-		break;
-
-	default:
-		return -EINVAL;
-	}
-	return 0;
-}
-
-
-static int az6027_frontend_poweron(struct dvb_usb_adapter *adap)
-{
-	int ret;
-	u8 req;
-	u16 value;
-	u16 index;
-	int blen;
-
-	req = 0xBC;
-	value = 1; /* power on */
-	index = 3;
-	blen = 0;
-
-	ret = az6027_usb_out_op(adap->dev, req, value, index, NULL, blen);
-	if (ret != 0)
-		return -EIO;
-
-	return 0;
-}
-static int az6027_frontend_reset(struct dvb_usb_adapter *adap)
-{
-	int ret;
-	u8 req;
-	u16 value;
-	u16 index;
-	int blen;
-
-	/* reset demodulator */
-	req = 0xC0;
-	value = 1; /* high */
-	index = 3;
-	blen = 0;
-
-	ret = az6027_usb_out_op(adap->dev, req, value, index, NULL, blen);
-	if (ret != 0)
-		return -EIO;
-
-	req = 0xC0;
-	value = 0; /* low */
-	index = 3;
-	blen = 0;
-	msleep_interruptible(200);
-
-	ret = az6027_usb_out_op(adap->dev, req, value, index, NULL, blen);
-	if (ret != 0)
-		return -EIO;
-
-	msleep_interruptible(200);
-
-	req = 0xC0;
-	value = 1; /*high */
-	index = 3;
-	blen = 0;
-
-	ret = az6027_usb_out_op(adap->dev, req, value, index, NULL, blen);
-	if (ret != 0)
-		return -EIO;
-
-	msleep_interruptible(200);
-	return 0;
-}
-
-static int az6027_frontend_tsbypass(struct dvb_usb_adapter *adap, int onoff)
-{
-	int ret;
-	u8 req;
-	u16 value;
-	u16 index;
-	int blen;
-
-	/* TS passthrough */
-	req = 0xC7;
-	value = onoff;
-	index = 0;
-	blen = 0;
-
-	ret = az6027_usb_out_op(adap->dev, req, value, index, NULL, blen);
-	if (ret != 0)
-		return -EIO;
-
-	return 0;
-}
-
-static int az6027_frontend_attach(struct dvb_usb_adapter *adap)
-{
-
-	az6027_frontend_poweron(adap);
-	az6027_frontend_reset(adap);
-
-	deb_info("adap = %p, dev = %p\n", adap, adap->dev);
-	adap->fe_adap[0].fe = stb0899_attach(&az6027_stb0899_config, &adap->dev->i2c_adap);
-
-	if (adap->fe_adap[0].fe) {
-		deb_info("found STB0899 DVB-S/DVB-S2 frontend @0x%02x", az6027_stb0899_config.demod_address);
-		if (stb6100_attach(adap->fe_adap[0].fe, &az6027_stb6100_config, &adap->dev->i2c_adap)) {
-			deb_info("found STB6100 DVB-S/DVB-S2 frontend @0x%02x", az6027_stb6100_config.tuner_address);
-			adap->fe_adap[0].fe->ops.set_voltage = az6027_set_voltage;
-			az6027_ci_init(adap);
-		} else {
-			adap->fe_adap[0].fe = NULL;
-		}
-	} else
-		warn("no front-end attached\n");
-
-	az6027_frontend_tsbypass(adap, 0);
-
-	return 0;
-}
-
-static struct dvb_usb_device_properties az6027_properties;
-
-static void az6027_usb_disconnect(struct usb_interface *intf)
-{
-	struct dvb_usb_device *d = usb_get_intfdata(intf);
-	az6027_ci_uninit(d);
-	dvb_usb_device_exit(intf);
-}
-
-
-static int az6027_usb_probe(struct usb_interface *intf,
-			    const struct usb_device_id *id)
-{
-	return dvb_usb_device_init(intf,
-				   &az6027_properties,
-				   THIS_MODULE,
-				   NULL,
-				   adapter_nr);
-}
-
-/* I2C */
-static int az6027_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num)
-{
-	struct dvb_usb_device *d = i2c_get_adapdata(adap);
-	int i = 0, j = 0, len = 0;
-	u16 index;
-	u16 value;
-	int length;
-	u8 req;
-	u8 *data;
-
-	data = kmalloc(256, GFP_KERNEL);
-	if (!data)
-		return -ENOMEM;
-
-	if (mutex_lock_interruptible(&d->i2c_mutex) < 0) {
-		kfree(data);
-		return -EAGAIN;
-	}
-
-	if (num > 2)
-		warn("more than 2 i2c messages at a time is not handled yet. TODO.");
-
-	for (i = 0; i < num; i++) {
-
-		if (msg[i].addr == 0x99) {
-			req = 0xBE;
-			index = 0;
-			value = msg[i].buf[0] & 0x00ff;
-			length = 1;
-			az6027_usb_out_op(d, req, value, index, data, length);
-		}
-
-		if (msg[i].addr == 0xd0) {
-			/* write/read request */
-			if (i + 1 < num && (msg[i + 1].flags & I2C_M_RD)) {
-				req = 0xB9;
-				index = (((msg[i].buf[0] << 8) & 0xff00) | (msg[i].buf[1] & 0x00ff));
-				value = msg[i].addr + (msg[i].len << 8);
-				length = msg[i + 1].len + 6;
-				az6027_usb_in_op(d, req, value, index, data, length);
-				len = msg[i + 1].len;
-				for (j = 0; j < len; j++)
-					msg[i + 1].buf[j] = data[j + 5];
-
-				i++;
-			} else {
-
-				/* demod 16bit addr */
-				req = 0xBD;
-				index = (((msg[i].buf[0] << 8) & 0xff00) | (msg[i].buf[1] & 0x00ff));
-				value = msg[i].addr + (2 << 8);
-				length = msg[i].len - 2;
-				len = msg[i].len - 2;
-				for (j = 0; j < len; j++)
-					data[j] = msg[i].buf[j + 2];
-				az6027_usb_out_op(d, req, value, index, data, length);
-			}
-		}
-
-		if (msg[i].addr == 0xc0) {
-			if (msg[i].flags & I2C_M_RD) {
-
-				req = 0xB9;
-				index = 0x0;
-				value = msg[i].addr;
-				length = msg[i].len + 6;
-				az6027_usb_in_op(d, req, value, index, data, length);
-				len = msg[i].len;
-				for (j = 0; j < len; j++)
-					msg[i].buf[j] = data[j + 5];
-
-			} else {
-
-				req = 0xBD;
-				index = msg[i].buf[0] & 0x00FF;
-				value = msg[i].addr + (1 << 8);
-				length = msg[i].len - 1;
-				len = msg[i].len - 1;
-
-				for (j = 0; j < len; j++)
-					data[j] = msg[i].buf[j + 1];
-
-				az6027_usb_out_op(d, req, value, index, data, length);
-			}
-		}
-	}
-	mutex_unlock(&d->i2c_mutex);
-	kfree(data);
-
-	return i;
-}
-
-
-static u32 az6027_i2c_func(struct i2c_adapter *adapter)
-{
-	return I2C_FUNC_I2C;
-}
-
-static struct i2c_algorithm az6027_i2c_algo = {
-	.master_xfer   = az6027_i2c_xfer,
-	.functionality = az6027_i2c_func,
-};
-
-int az6027_identify_state(struct usb_device *udev,
-			  struct dvb_usb_device_properties *props,
-			  struct dvb_usb_device_description **desc,
-			  int *cold)
-{
-	u8 *b;
-	s16 ret;
-
-	b = kmalloc(16, GFP_KERNEL);
-	if (!b)
-		return -ENOMEM;
-
-	ret = usb_control_msg(udev,
-				  usb_rcvctrlpipe(udev, 0),
-				  0xb7,
-				  USB_TYPE_VENDOR | USB_DIR_IN,
-				  6,
-				  0,
-				  b,
-				  6,
-				  USB_CTRL_GET_TIMEOUT);
-
-	*cold = ret <= 0;
-	kfree(b);
-	deb_info("cold: %d\n", *cold);
-	return 0;
-}
-
-
-static struct usb_device_id az6027_usb_table[] = {
-	{ USB_DEVICE(USB_VID_AZUREWAVE, USB_PID_AZUREWAVE_AZ6027) },
-	{ USB_DEVICE(USB_VID_TERRATEC,  USB_PID_TERRATEC_DVBS2CI_V1) },
-	{ USB_DEVICE(USB_VID_TERRATEC,  USB_PID_TERRATEC_DVBS2CI_V2) },
-	{ USB_DEVICE(USB_VID_TECHNISAT, USB_PID_TECHNISAT_USB2_HDCI_V1) },
-	{ USB_DEVICE(USB_VID_TECHNISAT, USB_PID_TECHNISAT_USB2_HDCI_V2) },
-	{ USB_DEVICE(USB_VID_ELGATO, USB_PID_ELGATO_EYETV_SAT) },
-	{ },
-};
-
-MODULE_DEVICE_TABLE(usb, az6027_usb_table);
-
-static struct dvb_usb_device_properties az6027_properties = {
-	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
-	.usb_ctrl = CYPRESS_FX2,
-	.firmware            = "dvb-usb-az6027-03.fw",
-	.no_reconnect        = 1,
-
-	.size_of_priv     = sizeof(struct az6027_device_state),
-	.identify_state		= az6027_identify_state,
-	.num_adapters = 1,
-	.adapter = {
-		{
-		.num_frontends = 1,
-		.fe = {{
-			.streaming_ctrl   = az6027_streaming_ctrl,
-			.frontend_attach  = az6027_frontend_attach,
-
-			/* parameter for the MPEG2-data transfer */
-			.stream = {
-				.type = USB_BULK,
-				.count = 10,
-				.endpoint = 0x02,
-				.u = {
-					.bulk = {
-						.buffersize = 4096,
-					}
-				}
-			},
-		}},
-		}
-	},
-/*
-	.power_ctrl       = az6027_power_ctrl,
-	.read_mac_address = az6027_read_mac_addr,
- */
-	.rc.legacy = {
-		.rc_map_table     = rc_map_az6027_table,
-		.rc_map_size      = ARRAY_SIZE(rc_map_az6027_table),
-		.rc_interval      = 400,
-		.rc_query         = az6027_rc_query,
-	},
-
-	.i2c_algo         = &az6027_i2c_algo,
-
-	.num_device_descs = 6,
-	.devices = {
-		{
-			.name = "AZUREWAVE DVB-S/S2 USB2.0 (AZ6027)",
-			.cold_ids = { &az6027_usb_table[0], NULL },
-			.warm_ids = { NULL },
-		}, {
-			.name = "TERRATEC S7",
-			.cold_ids = { &az6027_usb_table[1], NULL },
-			.warm_ids = { NULL },
-		}, {
-			.name = "TERRATEC S7 MKII",
-			.cold_ids = { &az6027_usb_table[2], NULL },
-			.warm_ids = { NULL },
-		}, {
-			.name = "Technisat SkyStar USB 2 HD CI",
-			.cold_ids = { &az6027_usb_table[3], NULL },
-			.warm_ids = { NULL },
-		}, {
-			.name = "Technisat SkyStar USB 2 HD CI",
-			.cold_ids = { &az6027_usb_table[4], NULL },
-			.warm_ids = { NULL },
-		}, {
-			.name = "Elgato EyeTV Sat",
-			.cold_ids = { &az6027_usb_table[5], NULL },
-			.warm_ids = { NULL },
-		},
-		{ NULL },
-	}
-};
-
-/* usb specific object needed to register this driver with the usb subsystem */
-static struct usb_driver az6027_usb_driver = {
-	.name		= "dvb_usb_az6027",
-	.probe 		= az6027_usb_probe,
-	.disconnect 	= az6027_usb_disconnect,
-	.id_table 	= az6027_usb_table,
-};
-
-module_usb_driver(az6027_usb_driver);
-
-MODULE_AUTHOR("Adams Xu <Adams.xu@azwave.com.cn>");
-MODULE_DESCRIPTION("Driver for AZUREWAVE DVB-S/S2 USB2.0 (AZ6027)");
-MODULE_VERSION("1.0");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/az6027.h b/drivers/media/dvb/dvb-usb/az6027.h
deleted file mode 100644
index f3afe17..0000000
--- a/drivers/media/dvb/dvb-usb/az6027.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef _DVB_USB_VP6027_H_
-#define _DVB_USB_VP6027_H_
-
-#define DVB_USB_LOG_PREFIX "az6027"
-#include "dvb-usb.h"
-
-
-extern int dvb_usb_az6027_debug;
-#define deb_info(args...) dprintk(dvb_usb_az6027_debug, 0x01, args)
-#define deb_xfer(args...) dprintk(dvb_usb_az6027_debug, 0x02, args)
-#define deb_rc(args...)   dprintk(dvb_usb_az6027_debug, 0x04, args)
-#define deb_fe(args...)   dprintk(dvb_usb_az6027_debug, 0x08, args)
-
-#endif
diff --git a/drivers/media/dvb/dvb-usb/ce6230.c b/drivers/media/dvb/dvb-usb/ce6230.c
deleted file mode 100644
index fa63725..0000000
--- a/drivers/media/dvb/dvb-usb/ce6230.c
+++ /dev/null
@@ -1,324 +0,0 @@
-/*
- * 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;
-
-	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;
-	}
-
-	buf = kmalloc(req->data_len, GFP_KERNEL);
-	if (!buf) {
-		ret = -ENOMEM;
-		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, req->data_len, 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);
-
-	kfree(buf);
-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_adap[0].fe = dvb_attach(zl10353_attach, &ce6230_zl10353_config,
-		&adap->dev->i2c_adap);
-	if (adap->fe_adap[0].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[0].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) },
-	{ USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A310) },
-	{ } /* 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 = {
-		{
-		.num_frontends = 1,
-		.fe = {{
-			.frontend_attach  = ce6230_zl10353_frontend_attach,
-			.tuner_attach     = ce6230_mxl5003s_tuner_attach,
-			.stream = {
-				.type = USB_BULK,
-				.count = 6,
-				.endpoint = 0x82,
-				.u = {
-					.bulk = {
-						.buffersize = (16*512),
-					}
-				}
-			},
-		}},
-		}
-	},
-
-	.power_ctrl = ce6230_power_ctrl,
-
-	.i2c_algo = &ce6230_i2c_algo,
-
-	.num_device_descs = 2,
-	.devices = {
-		{
-			.name = "Intel CE9500 reference design",
-			.cold_ids = {NULL},
-			.warm_ids = {&ce6230_table[0], NULL},
-		},
-		{
-			.name = "AVerMedia A310 USB 2.0 DVB-T tuner",
-			.cold_ids = {NULL},
-			.warm_ids = {&ce6230_table[1], NULL},
-		},
-	}
-};
-
-static struct usb_driver ce6230_driver = {
-	.name       = "dvb_usb_ce6230",
-	.probe      = ce6230_probe,
-	.disconnect = dvb_usb_device_exit,
-	.id_table   = ce6230_table,
-};
-
-module_usb_driver(ce6230_driver);
-
-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
deleted file mode 100644
index 97c4248..0000000
--- a/drivers/media/dvb/dvb-usb/ce6230.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * 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/cinergyT2-core.c b/drivers/media/dvb/dvb-usb/cinergyT2-core.c
deleted file mode 100644
index 0a98548..0000000
--- a/drivers/media/dvb/dvb-usb/cinergyT2-core.c
+++ /dev/null
@@ -1,254 +0,0 @@
-/*
- * TerraTec Cinergy T2/qanu USB2 DVB-T adapter.
- *
- * Copyright (C) 2007 Tomi Orava (tomimo@ncircle.nullnet.fi)
- *
- * Based on the dvb-usb-framework code and the
- * original Terratec Cinergy T2 driver by:
- *
- * Copyright (C) 2004 Daniel Mack <daniel@qanu.de> and
- *		    Holger Waechtler <holger@qanu.de>
- *
- *  Protocol Spec published on http://qanu.de/specs/terratec_cinergyT2.pdf
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You 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 "cinergyT2.h"
-
-
-/* debug */
-int dvb_usb_cinergyt2_debug;
-
-module_param_named(debug, dvb_usb_cinergyt2_debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level (1=info, xfer=2, rc=4 "
-		"(or-able)).");
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-struct cinergyt2_state {
-	u8 rc_counter;
-};
-
-/* We are missing a release hook with usb_device data */
-static struct dvb_usb_device *cinergyt2_usb_device;
-
-static struct dvb_usb_device_properties cinergyt2_properties;
-
-static int cinergyt2_streaming_ctrl(struct dvb_usb_adapter *adap, int enable)
-{
-	char buf[] = { CINERGYT2_EP1_CONTROL_STREAM_TRANSFER, enable ? 1 : 0 };
-	char result[64];
-	return dvb_usb_generic_rw(adap->dev, buf, sizeof(buf), result,
-				sizeof(result), 0);
-}
-
-static int cinergyt2_power_ctrl(struct dvb_usb_device *d, int enable)
-{
-	char buf[] = { CINERGYT2_EP1_SLEEP_MODE, enable ? 0 : 1 };
-	char state[3];
-	return dvb_usb_generic_rw(d, buf, sizeof(buf), state, sizeof(state), 0);
-}
-
-static int cinergyt2_frontend_attach(struct dvb_usb_adapter *adap)
-{
-	char query[] = { CINERGYT2_EP1_GET_FIRMWARE_VERSION };
-	char state[3];
-	int ret;
-
-	adap->fe_adap[0].fe = cinergyt2_fe_attach(adap->dev);
-
-	ret = dvb_usb_generic_rw(adap->dev, query, sizeof(query), state,
-				sizeof(state), 0);
-	if (ret < 0) {
-		deb_rc("cinergyt2_power_ctrl() Failed to retrieve sleep "
-			"state info\n");
-	}
-
-	/* Copy this pointer as we are gonna need it in the release phase */
-	cinergyt2_usb_device = adap->dev;
-
-	return 0;
-}
-
-static struct rc_map_table rc_map_cinergyt2_table[] = {
-	{ 0x0401, KEY_POWER },
-	{ 0x0402, KEY_1 },
-	{ 0x0403, KEY_2 },
-	{ 0x0404, KEY_3 },
-	{ 0x0405, KEY_4 },
-	{ 0x0406, KEY_5 },
-	{ 0x0407, KEY_6 },
-	{ 0x0408, KEY_7 },
-	{ 0x0409, KEY_8 },
-	{ 0x040a, KEY_9 },
-	{ 0x040c, KEY_0 },
-	{ 0x040b, KEY_VIDEO },
-	{ 0x040d, KEY_REFRESH },
-	{ 0x040e, KEY_SELECT },
-	{ 0x040f, KEY_EPG },
-	{ 0x0410, KEY_UP },
-	{ 0x0414, KEY_DOWN },
-	{ 0x0411, KEY_LEFT },
-	{ 0x0413, KEY_RIGHT },
-	{ 0x0412, KEY_OK },
-	{ 0x0415, KEY_TEXT },
-	{ 0x0416, KEY_INFO },
-	{ 0x0417, KEY_RED },
-	{ 0x0418, KEY_GREEN },
-	{ 0x0419, KEY_YELLOW },
-	{ 0x041a, KEY_BLUE },
-	{ 0x041c, KEY_VOLUMEUP },
-	{ 0x041e, KEY_VOLUMEDOWN },
-	{ 0x041d, KEY_MUTE },
-	{ 0x041b, KEY_CHANNELUP },
-	{ 0x041f, KEY_CHANNELDOWN },
-	{ 0x0440, KEY_PAUSE },
-	{ 0x044c, KEY_PLAY },
-	{ 0x0458, KEY_RECORD },
-	{ 0x0454, KEY_PREVIOUS },
-	{ 0x0448, KEY_STOP },
-	{ 0x045c, KEY_NEXT }
-};
-
-/* Number of keypresses to ignore before detect repeating */
-#define RC_REPEAT_DELAY 3
-
-static int repeatable_keys[] = {
-	KEY_UP,
-	KEY_DOWN,
-	KEY_LEFT,
-	KEY_RIGHT,
-	KEY_VOLUMEUP,
-	KEY_VOLUMEDOWN,
-	KEY_CHANNELUP,
-	KEY_CHANNELDOWN
-};
-
-static int cinergyt2_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
-{
-	struct cinergyt2_state *st = d->priv;
-	u8 key[5] = {0, 0, 0, 0, 0}, cmd = CINERGYT2_EP1_GET_RC_EVENTS;
-	int i;
-
-	*state = REMOTE_NO_KEY_PRESSED;
-
-	dvb_usb_generic_rw(d, &cmd, 1, key, sizeof(key), 0);
-	if (key[4] == 0xff) {
-		/* key repeat */
-		st->rc_counter++;
-		if (st->rc_counter > RC_REPEAT_DELAY) {
-			for (i = 0; i < ARRAY_SIZE(repeatable_keys); i++) {
-				if (d->last_event == repeatable_keys[i]) {
-					*state = REMOTE_KEY_REPEAT;
-					*event = d->last_event;
-					deb_rc("repeat key, event %x\n",
-						   *event);
-					return 0;
-				}
-			}
-			deb_rc("repeated key (non repeatable)\n");
-		}
-		return 0;
-	}
-
-	/* hack to pass checksum on the custom field */
-	key[2] = ~key[1];
-	dvb_usb_nec_rc_key_to_event(d, key, event, state);
-	if (key[0] != 0) {
-		if (*event != d->last_event)
-			st->rc_counter = 0;
-
-		deb_rc("key: %x %x %x %x %x\n",
-		       key[0], key[1], key[2], key[3], key[4]);
-	}
-	return 0;
-}
-
-static int cinergyt2_usb_probe(struct usb_interface *intf,
-				const struct usb_device_id *id)
-{
-	return dvb_usb_device_init(intf, &cinergyt2_properties,
-					THIS_MODULE, NULL, adapter_nr);
-}
-
-
-static struct usb_device_id cinergyt2_usb_table[] = {
-	{ USB_DEVICE(USB_VID_TERRATEC, 0x0038) },
-	{ 0 }
-};
-
-MODULE_DEVICE_TABLE(usb, cinergyt2_usb_table);
-
-static struct dvb_usb_device_properties cinergyt2_properties = {
-	.size_of_priv = sizeof(struct cinergyt2_state),
-	.num_adapters = 1,
-	.adapter = {
-		{
-		.num_frontends = 1,
-		.fe = {{
-			.streaming_ctrl   = cinergyt2_streaming_ctrl,
-			.frontend_attach  = cinergyt2_frontend_attach,
-
-			/* parameter for the MPEG2-data transfer */
-			.stream = {
-				.type = USB_BULK,
-				.count = 5,
-				.endpoint = 0x02,
-				.u = {
-					.bulk = {
-						.buffersize = 512,
-					}
-				}
-			},
-		}},
-		}
-	},
-
-	.power_ctrl       = cinergyt2_power_ctrl,
-
-	.rc.legacy = {
-		.rc_interval      = 50,
-		.rc_map_table     = rc_map_cinergyt2_table,
-		.rc_map_size      = ARRAY_SIZE(rc_map_cinergyt2_table),
-		.rc_query         = cinergyt2_rc_query,
-	},
-
-	.generic_bulk_ctrl_endpoint = 1,
-
-	.num_device_descs = 1,
-	.devices = {
-		{ .name = "TerraTec/qanu USB2.0 Highspeed DVB-T Receiver",
-		  .cold_ids = {NULL},
-		  .warm_ids = { &cinergyt2_usb_table[0], NULL },
-		},
-		{ NULL },
-	}
-};
-
-
-static struct usb_driver cinergyt2_driver = {
-	.name		= "cinergyT2",
-	.probe		= cinergyt2_usb_probe,
-	.disconnect	= dvb_usb_device_exit,
-	.id_table	= cinergyt2_usb_table
-};
-
-module_usb_driver(cinergyt2_driver);
-
-MODULE_DESCRIPTION("Terratec Cinergy T2 DVB-T driver");
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Tomi Orava");
diff --git a/drivers/media/dvb/dvb-usb/cinergyT2-fe.c b/drivers/media/dvb/dvb-usb/cinergyT2-fe.c
deleted file mode 100644
index 1efc028..0000000
--- a/drivers/media/dvb/dvb-usb/cinergyT2-fe.c
+++ /dev/null
@@ -1,356 +0,0 @@
-/*
- * TerraTec Cinergy T2/qanu USB2 DVB-T adapter.
- *
- * Copyright (C) 2007 Tomi Orava (tomimo@ncircle.nullnet.fi)
- *
- * Based on the dvb-usb-framework code and the
- * original Terratec Cinergy T2 driver by:
- *
- * Copyright (C) 2004 Daniel Mack <daniel@qanu.de> and
- *                  Holger Waechtler <holger@qanu.de>
- *
- *  Protocol Spec published on http://qanu.de/specs/terratec_cinergyT2.pdf
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You 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 "cinergyT2.h"
-
-
-/**
- *  convert linux-dvb frontend parameter set into TPS.
- *  See ETSI ETS-300744, section 4.6.2, table 9 for details.
- *
- *  This function is probably reusable and may better get placed in a support
- *  library.
- *
- *  We replace errornous fields by default TPS fields (the ones with value 0).
- */
-
-static uint16_t compute_tps(struct dtv_frontend_properties *op)
-{
-	uint16_t tps = 0;
-
-	switch (op->code_rate_HP) {
-	case FEC_2_3:
-		tps |= (1 << 7);
-		break;
-	case FEC_3_4:
-		tps |= (2 << 7);
-		break;
-	case FEC_5_6:
-		tps |= (3 << 7);
-		break;
-	case FEC_7_8:
-		tps |= (4 << 7);
-		break;
-	case FEC_1_2:
-	case FEC_AUTO:
-	default:
-		/* tps |= (0 << 7) */;
-	}
-
-	switch (op->code_rate_LP) {
-	case FEC_2_3:
-		tps |= (1 << 4);
-		break;
-	case FEC_3_4:
-		tps |= (2 << 4);
-		break;
-	case FEC_5_6:
-		tps |= (3 << 4);
-		break;
-	case FEC_7_8:
-		tps |= (4 << 4);
-		break;
-	case FEC_1_2:
-	case FEC_AUTO:
-	default:
-		/* tps |= (0 << 4) */;
-	}
-
-	switch (op->modulation) {
-	case QAM_16:
-		tps |= (1 << 13);
-		break;
-	case QAM_64:
-		tps |= (2 << 13);
-		break;
-	case QPSK:
-	default:
-		/* tps |= (0 << 13) */;
-	}
-
-	switch (op->transmission_mode) {
-	case TRANSMISSION_MODE_8K:
-		tps |= (1 << 0);
-		break;
-	case TRANSMISSION_MODE_2K:
-	default:
-		/* tps |= (0 << 0) */;
-	}
-
-	switch (op->guard_interval) {
-	case GUARD_INTERVAL_1_16:
-		tps |= (1 << 2);
-		break;
-	case GUARD_INTERVAL_1_8:
-		tps |= (2 << 2);
-		break;
-	case GUARD_INTERVAL_1_4:
-		tps |= (3 << 2);
-		break;
-	case GUARD_INTERVAL_1_32:
-	default:
-		/* tps |= (0 << 2) */;
-	}
-
-	switch (op->hierarchy) {
-	case HIERARCHY_1:
-		tps |= (1 << 10);
-		break;
-	case HIERARCHY_2:
-		tps |= (2 << 10);
-		break;
-	case HIERARCHY_4:
-		tps |= (3 << 10);
-		break;
-	case HIERARCHY_NONE:
-	default:
-		/* tps |= (0 << 10) */;
-	}
-
-	return tps;
-}
-
-struct cinergyt2_fe_state {
-	struct dvb_frontend fe;
-	struct dvb_usb_device *d;
-};
-
-static int cinergyt2_fe_read_status(struct dvb_frontend *fe,
-					fe_status_t *status)
-{
-	struct cinergyt2_fe_state *state = fe->demodulator_priv;
-	struct dvbt_get_status_msg result;
-	u8 cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS };
-	int ret;
-
-	ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (u8 *)&result,
-			sizeof(result), 0);
-	if (ret < 0)
-		return ret;
-
-	*status = 0;
-
-	if (0xffff - le16_to_cpu(result.gain) > 30)
-		*status |= FE_HAS_SIGNAL;
-	if (result.lock_bits & (1 << 6))
-		*status |= FE_HAS_LOCK;
-	if (result.lock_bits & (1 << 5))
-		*status |= FE_HAS_SYNC;
-	if (result.lock_bits & (1 << 4))
-		*status |= FE_HAS_CARRIER;
-	if (result.lock_bits & (1 << 1))
-		*status |= FE_HAS_VITERBI;
-
-	if ((*status & (FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC)) !=
-			(FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC))
-		*status &= ~FE_HAS_LOCK;
-
-	return 0;
-}
-
-static int cinergyt2_fe_read_ber(struct dvb_frontend *fe, u32 *ber)
-{
-	struct cinergyt2_fe_state *state = fe->demodulator_priv;
-	struct dvbt_get_status_msg status;
-	char cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS };
-	int ret;
-
-	ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (char *)&status,
-				sizeof(status), 0);
-	if (ret < 0)
-		return ret;
-
-	*ber = le32_to_cpu(status.viterbi_error_rate);
-	return 0;
-}
-
-static int cinergyt2_fe_read_unc_blocks(struct dvb_frontend *fe, u32 *unc)
-{
-	struct cinergyt2_fe_state *state = fe->demodulator_priv;
-	struct dvbt_get_status_msg status;
-	u8 cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS };
-	int ret;
-
-	ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (u8 *)&status,
-				sizeof(status), 0);
-	if (ret < 0) {
-		err("cinergyt2_fe_read_unc_blocks() Failed! (Error=%d)\n",
-			ret);
-		return ret;
-	}
-	*unc = le32_to_cpu(status.uncorrected_block_count);
-	return 0;
-}
-
-static int cinergyt2_fe_read_signal_strength(struct dvb_frontend *fe,
-						u16 *strength)
-{
-	struct cinergyt2_fe_state *state = fe->demodulator_priv;
-	struct dvbt_get_status_msg status;
-	char cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS };
-	int ret;
-
-	ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (char *)&status,
-				sizeof(status), 0);
-	if (ret < 0) {
-		err("cinergyt2_fe_read_signal_strength() Failed!"
-			" (Error=%d)\n", ret);
-		return ret;
-	}
-	*strength = (0xffff - le16_to_cpu(status.gain));
-	return 0;
-}
-
-static int cinergyt2_fe_read_snr(struct dvb_frontend *fe, u16 *snr)
-{
-	struct cinergyt2_fe_state *state = fe->demodulator_priv;
-	struct dvbt_get_status_msg status;
-	char cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS };
-	int ret;
-
-	ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (char *)&status,
-				sizeof(status), 0);
-	if (ret < 0) {
-		err("cinergyt2_fe_read_snr() Failed! (Error=%d)\n", ret);
-		return ret;
-	}
-	*snr = (status.snr << 8) | status.snr;
-	return 0;
-}
-
-static int cinergyt2_fe_init(struct dvb_frontend *fe)
-{
-	return 0;
-}
-
-static int cinergyt2_fe_sleep(struct dvb_frontend *fe)
-{
-	deb_info("cinergyt2_fe_sleep() Called\n");
-	return 0;
-}
-
-static int cinergyt2_fe_get_tune_settings(struct dvb_frontend *fe,
-				struct dvb_frontend_tune_settings *tune)
-{
-	tune->min_delay_ms = 800;
-	return 0;
-}
-
-static int cinergyt2_fe_set_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
-	struct cinergyt2_fe_state *state = fe->demodulator_priv;
-	struct dvbt_set_parameters_msg param;
-	char result[2];
-	int err;
-
-	param.cmd = CINERGYT2_EP1_SET_TUNER_PARAMETERS;
-	param.tps = cpu_to_le16(compute_tps(fep));
-	param.freq = cpu_to_le32(fep->frequency / 1000);
-	param.flags = 0;
-
-	switch (fep->bandwidth_hz) {
-	default:
-	case 8000000:
-		param.bandwidth = 8;
-		break;
-	case 7000000:
-		param.bandwidth = 7;
-		break;
-	case 6000000:
-		param.bandwidth = 6;
-		break;
-	}
-
-	err = dvb_usb_generic_rw(state->d,
-			(char *)&param, sizeof(param),
-			result, sizeof(result), 0);
-	if (err < 0)
-		err("cinergyt2_fe_set_frontend() Failed! err=%d\n", err);
-
-	return (err < 0) ? err : 0;
-}
-
-static void cinergyt2_fe_release(struct dvb_frontend *fe)
-{
-	struct cinergyt2_fe_state *state = fe->demodulator_priv;
-	if (state != NULL)
-		kfree(state);
-}
-
-static struct dvb_frontend_ops cinergyt2_fe_ops;
-
-struct dvb_frontend *cinergyt2_fe_attach(struct dvb_usb_device *d)
-{
-	struct cinergyt2_fe_state *s = kzalloc(sizeof(
-					struct cinergyt2_fe_state), GFP_KERNEL);
-	if (s == NULL)
-		return NULL;
-
-	s->d = d;
-	memcpy(&s->fe.ops, &cinergyt2_fe_ops, sizeof(struct dvb_frontend_ops));
-	s->fe.demodulator_priv = s;
-	return &s->fe;
-}
-
-
-static struct dvb_frontend_ops cinergyt2_fe_ops = {
-	.delsys = { SYS_DVBT },
-	.info = {
-		.name			= DRIVER_NAME,
-		.frequency_min		= 174000000,
-		.frequency_max		= 862000000,
-		.frequency_stepsize	= 166667,
-		.caps = FE_CAN_INVERSION_AUTO | 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_FEC_AUTO | FE_CAN_QPSK
-			| FE_CAN_QAM_16 | FE_CAN_QAM_64
-			| FE_CAN_QAM_AUTO
-			| FE_CAN_TRANSMISSION_MODE_AUTO
-			| FE_CAN_GUARD_INTERVAL_AUTO
-			| FE_CAN_HIERARCHY_AUTO
-			| FE_CAN_RECOVER
-			| FE_CAN_MUTE_TS
-	},
-
-	.release		= cinergyt2_fe_release,
-
-	.init			= cinergyt2_fe_init,
-	.sleep			= cinergyt2_fe_sleep,
-
-	.set_frontend		= cinergyt2_fe_set_frontend,
-	.get_tune_settings	= cinergyt2_fe_get_tune_settings,
-
-	.read_status		= cinergyt2_fe_read_status,
-	.read_ber		= cinergyt2_fe_read_ber,
-	.read_signal_strength	= cinergyt2_fe_read_signal_strength,
-	.read_snr		= cinergyt2_fe_read_snr,
-	.read_ucblocks		= cinergyt2_fe_read_unc_blocks,
-};
diff --git a/drivers/media/dvb/dvb-usb/cinergyT2.h b/drivers/media/dvb/dvb-usb/cinergyT2.h
deleted file mode 100644
index 84efe03..0000000
--- a/drivers/media/dvb/dvb-usb/cinergyT2.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * TerraTec Cinergy T2/qanu USB2 DVB-T adapter.
- *
- * Copyright (C) 2007 Tomi Orava (tomimo@ncircle.nullnet.fi)
- *
- * Based on the dvb-usb-framework code and the
- * original Terratec Cinergy T2 driver by:
- *
- * Copyright (C) 2004 Daniel Mack <daniel@qanu.de> and
- *                  Holger Waechtler <holger@qanu.de>
- *
- *  Protocol Spec published on http://qanu.de/specs/terratec_cinergyT2.pdf
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License,  or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You 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_CINERGYT2_H_
-#define _DVB_USB_CINERGYT2_H_
-
-#include <linux/usb/input.h>
-
-#define DVB_USB_LOG_PREFIX "cinergyT2"
-#include "dvb-usb.h"
-
-#define DRIVER_NAME "TerraTec/qanu USB2.0 Highspeed DVB-T Receiver"
-
-extern int dvb_usb_cinergyt2_debug;
-
-#define deb_info(args...)  dprintk(dvb_usb_cinergyt2_debug,  0x001, args)
-#define deb_xfer(args...)  dprintk(dvb_usb_cinergyt2_debug,  0x002, args)
-#define deb_pll(args...)   dprintk(dvb_usb_cinergyt2_debug,  0x004, args)
-#define deb_ts(args...)    dprintk(dvb_usb_cinergyt2_debug,  0x008, args)
-#define deb_err(args...)   dprintk(dvb_usb_cinergyt2_debug,  0x010, args)
-#define deb_rc(args...)    dprintk(dvb_usb_cinergyt2_debug,  0x020, args)
-#define deb_fw(args...)    dprintk(dvb_usb_cinergyt2_debug,  0x040, args)
-#define deb_mem(args...)   dprintk(dvb_usb_cinergyt2_debug,  0x080, args)
-#define deb_uxfer(args...) dprintk(dvb_usb_cinergyt2_debug,  0x100, args)
-
-
-
-enum cinergyt2_ep1_cmd {
-	CINERGYT2_EP1_PID_TABLE_RESET		= 0x01,
-	CINERGYT2_EP1_PID_SETUP			= 0x02,
-	CINERGYT2_EP1_CONTROL_STREAM_TRANSFER	= 0x03,
-	CINERGYT2_EP1_SET_TUNER_PARAMETERS	= 0x04,
-	CINERGYT2_EP1_GET_TUNER_STATUS		= 0x05,
-	CINERGYT2_EP1_START_SCAN		= 0x06,
-	CINERGYT2_EP1_CONTINUE_SCAN		= 0x07,
-	CINERGYT2_EP1_GET_RC_EVENTS		= 0x08,
-	CINERGYT2_EP1_SLEEP_MODE		= 0x09,
-	CINERGYT2_EP1_GET_FIRMWARE_VERSION	= 0x0A
-};
-
-
-struct dvbt_get_status_msg {
-	uint32_t freq;
-	uint8_t bandwidth;
-	uint16_t tps;
-	uint8_t flags;
-	__le16 gain;
-	uint8_t snr;
-	__le32 viterbi_error_rate;
-	uint32_t rs_error_rate;
-	__le32 uncorrected_block_count;
-	uint8_t lock_bits;
-	uint8_t prev_lock_bits;
-} __attribute__((packed));
-
-
-struct dvbt_set_parameters_msg {
-	uint8_t cmd;
-	__le32 freq;
-	uint8_t bandwidth;
-	__le16 tps;
-	uint8_t flags;
-} __attribute__((packed));
-
-
-extern struct dvb_frontend *cinergyt2_fe_attach(struct dvb_usb_device *d);
-
-#endif /* _DVB_USB_CINERGYT2_H_ */
-
diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c
deleted file mode 100644
index 3940bb0..0000000
--- a/drivers/media/dvb/dvb-usb/cxusb.c
+++ /dev/null
@@ -1,2043 +0,0 @@
-/* DVB USB compliant linux driver for Conexant USB reference design.
- *
- * The Conexant reference design I saw on their website was only for analogue
- * capturing (using the cx25842). The box I took to write this driver (reverse
- * engineered) is the one labeled Medion MD95700. In addition to the cx25842
- * for analogue capturing it also has a cx22702 DVB-T demodulator on the main
- * board. Besides it has a atiremote (X10) and a USB2.0 hub onboard.
- *
- * Maybe it is a little bit premature to call this driver cxusb, but I assume
- * the USB protocol is identical or at least inherited from the reference
- * design, so it can be reused for the "analogue-only" device (if it will
- * appear at all).
- *
- * TODO: Use the cx25840-driver for the analogue part
- *
- * Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@desy.de)
- * Copyright (C) 2006 Michael Krufky (mkrufky@linuxtv.org)
- * Copyright (C) 2006, 2007 Chris Pascoe (c.pascoe@itee.uq.edu.au)
- *
- *   This program is free software; you can redistribute it and/or modify it
- *   under the terms of the GNU General Public License as published by the Free
- *   Software Foundation, version 2.
- *
- * see Documentation/dvb/README.dvb-usb for more information
- */
-#include <media/tuner.h>
-#include <linux/vmalloc.h>
-#include <linux/slab.h>
-
-#include "cxusb.h"
-
-#include "cx22702.h"
-#include "lgdt330x.h"
-#include "mt352.h"
-#include "mt352_priv.h"
-#include "zl10353.h"
-#include "tuner-xc2028.h"
-#include "tuner-simple.h"
-#include "mxl5005s.h"
-#include "max2165.h"
-#include "dib7000p.h"
-#include "dib0070.h"
-#include "lgs8gxx.h"
-#include "atbm8830.h"
-
-/* debug */
-static int dvb_usb_cxusb_debug;
-module_param_named(debug, dvb_usb_cxusb_debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS);
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-#define deb_info(args...)   dprintk(dvb_usb_cxusb_debug, 0x03, args)
-#define deb_i2c(args...)    dprintk(dvb_usb_cxusb_debug, 0x02, args)
-
-static int cxusb_ctrl_msg(struct dvb_usb_device *d,
-			  u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen)
-{
-	int wo = (rbuf == NULL || rlen == 0); /* write-only */
-	u8 sndbuf[1+wlen];
-	memset(sndbuf, 0, 1+wlen);
-
-	sndbuf[0] = cmd;
-	memcpy(&sndbuf[1], wbuf, wlen);
-	if (wo)
-		return dvb_usb_generic_write(d, sndbuf, 1+wlen);
-	else
-		return dvb_usb_generic_rw(d, sndbuf, 1+wlen, rbuf, rlen, 0);
-}
-
-/* GPIO */
-static void cxusb_gpio_tuner(struct dvb_usb_device *d, int onoff)
-{
-	struct cxusb_state *st = d->priv;
-	u8 o[2], i;
-
-	if (st->gpio_write_state[GPIO_TUNER] == onoff)
-		return;
-
-	o[0] = GPIO_TUNER;
-	o[1] = onoff;
-	cxusb_ctrl_msg(d, CMD_GPIO_WRITE, o, 2, &i, 1);
-
-	if (i != 0x01)
-		deb_info("gpio_write failed.\n");
-
-	st->gpio_write_state[GPIO_TUNER] = onoff;
-}
-
-static int cxusb_bluebird_gpio_rw(struct dvb_usb_device *d, u8 changemask,
-				 u8 newval)
-{
-	u8 o[2], gpio_state;
-	int rc;
-
-	o[0] = 0xff & ~changemask;	/* mask of bits to keep */
-	o[1] = newval & changemask;	/* new values for bits  */
-
-	rc = cxusb_ctrl_msg(d, CMD_BLUEBIRD_GPIO_RW, o, 2, &gpio_state, 1);
-	if (rc < 0 || (gpio_state & changemask) != (newval & changemask))
-		deb_info("bluebird_gpio_write failed.\n");
-
-	return rc < 0 ? rc : gpio_state;
-}
-
-static void cxusb_bluebird_gpio_pulse(struct dvb_usb_device *d, u8 pin, int low)
-{
-	cxusb_bluebird_gpio_rw(d, pin, low ? 0 : pin);
-	msleep(5);
-	cxusb_bluebird_gpio_rw(d, pin, low ? pin : 0);
-}
-
-static void cxusb_nano2_led(struct dvb_usb_device *d, int onoff)
-{
-	cxusb_bluebird_gpio_rw(d, 0x40, onoff ? 0 : 0x40);
-}
-
-static int cxusb_d680_dmb_gpio_tuner(struct dvb_usb_device *d,
-		u8 addr, int onoff)
-{
-	u8  o[2] = {addr, onoff};
-	u8  i;
-	int rc;
-
-	rc = cxusb_ctrl_msg(d, CMD_GPIO_WRITE, o, 2, &i, 1);
-
-	if (rc < 0)
-		return rc;
-	if (i == 0x01)
-		return 0;
-	else {
-		deb_info("gpio_write failed.\n");
-		return -EIO;
-	}
-}
-
-/* I2C */
-static int cxusb_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
-			  int num)
-{
-	struct dvb_usb_device *d = i2c_get_adapdata(adap);
-	int i;
-
-	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
-		return -EAGAIN;
-
-	for (i = 0; i < num; i++) {
-
-		if (d->udev->descriptor.idVendor == USB_VID_MEDION)
-			switch (msg[i].addr) {
-			case 0x63:
-				cxusb_gpio_tuner(d, 0);
-				break;
-			default:
-				cxusb_gpio_tuner(d, 1);
-				break;
-			}
-
-		if (msg[i].flags & I2C_M_RD) {
-			/* read only */
-			u8 obuf[3], ibuf[1+msg[i].len];
-			obuf[0] = 0;
-			obuf[1] = msg[i].len;
-			obuf[2] = msg[i].addr;
-			if (cxusb_ctrl_msg(d, CMD_I2C_READ,
-					   obuf, 3,
-					   ibuf, 1+msg[i].len) < 0) {
-				warn("i2c read failed");
-				break;
-			}
-			memcpy(msg[i].buf, &ibuf[1], msg[i].len);
-		} else if (i+1 < num && (msg[i+1].flags & I2C_M_RD) &&
-			   msg[i].addr == msg[i+1].addr) {
-			/* write to then read from same address */
-			u8 obuf[3+msg[i].len], ibuf[1+msg[i+1].len];
-			obuf[0] = msg[i].len;
-			obuf[1] = msg[i+1].len;
-			obuf[2] = msg[i].addr;
-			memcpy(&obuf[3], msg[i].buf, msg[i].len);
-
-			if (cxusb_ctrl_msg(d, CMD_I2C_READ,
-					   obuf, 3+msg[i].len,
-					   ibuf, 1+msg[i+1].len) < 0)
-				break;
-
-			if (ibuf[0] != 0x08)
-				deb_i2c("i2c read may have failed\n");
-
-			memcpy(msg[i+1].buf, &ibuf[1], msg[i+1].len);
-
-			i++;
-		} else {
-			/* write only */
-			u8 obuf[2+msg[i].len], ibuf;
-			obuf[0] = msg[i].addr;
-			obuf[1] = msg[i].len;
-			memcpy(&obuf[2], msg[i].buf, msg[i].len);
-
-			if (cxusb_ctrl_msg(d, CMD_I2C_WRITE, obuf,
-					   2+msg[i].len, &ibuf,1) < 0)
-				break;
-			if (ibuf != 0x08)
-				deb_i2c("i2c write may have failed\n");
-		}
-	}
-
-	mutex_unlock(&d->i2c_mutex);
-	return i == num ? num : -EREMOTEIO;
-}
-
-static u32 cxusb_i2c_func(struct i2c_adapter *adapter)
-{
-	return I2C_FUNC_I2C;
-}
-
-static struct i2c_algorithm cxusb_i2c_algo = {
-	.master_xfer   = cxusb_i2c_xfer,
-	.functionality = cxusb_i2c_func,
-};
-
-static int cxusb_power_ctrl(struct dvb_usb_device *d, int onoff)
-{
-	u8 b = 0;
-	if (onoff)
-		return cxusb_ctrl_msg(d, CMD_POWER_ON, &b, 1, NULL, 0);
-	else
-		return cxusb_ctrl_msg(d, CMD_POWER_OFF, &b, 1, NULL, 0);
-}
-
-static int cxusb_aver_power_ctrl(struct dvb_usb_device *d, int onoff)
-{
-	int ret;
-	if (!onoff)
-		return cxusb_ctrl_msg(d, CMD_POWER_OFF, NULL, 0, NULL, 0);
-	if (d->state == DVB_USB_STATE_INIT &&
-	    usb_set_interface(d->udev, 0, 0) < 0)
-		err("set interface failed");
-	do {} while (!(ret = cxusb_ctrl_msg(d, CMD_POWER_ON, NULL, 0, NULL, 0)) &&
-		   !(ret = cxusb_ctrl_msg(d, 0x15, NULL, 0, NULL, 0)) &&
-		   !(ret = cxusb_ctrl_msg(d, 0x17, NULL, 0, NULL, 0)) && 0);
-	if (!ret) {
-		/* FIXME: We don't know why, but we need to configure the
-		 * lgdt3303 with the register settings below on resume */
-		int i;
-		u8 buf, bufs[] = {
-			0x0e, 0x2, 0x00, 0x7f,
-			0x0e, 0x2, 0x02, 0xfe,
-			0x0e, 0x2, 0x02, 0x01,
-			0x0e, 0x2, 0x00, 0x03,
-			0x0e, 0x2, 0x0d, 0x40,
-			0x0e, 0x2, 0x0e, 0x87,
-			0x0e, 0x2, 0x0f, 0x8e,
-			0x0e, 0x2, 0x10, 0x01,
-			0x0e, 0x2, 0x14, 0xd7,
-			0x0e, 0x2, 0x47, 0x88,
-		};
-		msleep(20);
-		for (i = 0; i < sizeof(bufs)/sizeof(u8); i += 4/sizeof(u8)) {
-			ret = cxusb_ctrl_msg(d, CMD_I2C_WRITE,
-					     bufs+i, 4, &buf, 1);
-			if (ret)
-				break;
-			if (buf != 0x8)
-				return -EREMOTEIO;
-		}
-	}
-	return ret;
-}
-
-static int cxusb_bluebird_power_ctrl(struct dvb_usb_device *d, int onoff)
-{
-	u8 b = 0;
-	if (onoff)
-		return cxusb_ctrl_msg(d, CMD_POWER_ON, &b, 1, NULL, 0);
-	else
-		return 0;
-}
-
-static int cxusb_nano2_power_ctrl(struct dvb_usb_device *d, int onoff)
-{
-	int rc = 0;
-
-	rc = cxusb_power_ctrl(d, onoff);
-	if (!onoff)
-		cxusb_nano2_led(d, 0);
-
-	return rc;
-}
-
-static int cxusb_d680_dmb_power_ctrl(struct dvb_usb_device *d, int onoff)
-{
-	int ret;
-	u8  b;
-	ret = cxusb_power_ctrl(d, onoff);
-	if (!onoff)
-		return ret;
-
-	msleep(128);
-	cxusb_ctrl_msg(d, CMD_DIGITAL, NULL, 0, &b, 1);
-	msleep(100);
-	return ret;
-}
-
-static int cxusb_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
-{
-	u8 buf[2] = { 0x03, 0x00 };
-	if (onoff)
-		cxusb_ctrl_msg(adap->dev, CMD_STREAMING_ON, buf, 2, NULL, 0);
-	else
-		cxusb_ctrl_msg(adap->dev, CMD_STREAMING_OFF, NULL, 0, NULL, 0);
-
-	return 0;
-}
-
-static int cxusb_aver_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
-{
-	if (onoff)
-		cxusb_ctrl_msg(adap->dev, CMD_AVER_STREAM_ON, NULL, 0, NULL, 0);
-	else
-		cxusb_ctrl_msg(adap->dev, CMD_AVER_STREAM_OFF,
-			       NULL, 0, NULL, 0);
-	return 0;
-}
-
-static void cxusb_d680_dmb_drain_message(struct dvb_usb_device *d)
-{
-	int       ep = d->props.generic_bulk_ctrl_endpoint;
-	const int timeout = 100;
-	const int junk_len = 32;
-	u8        *junk;
-	int       rd_count;
-
-	/* Discard remaining data in video pipe */
-	junk = kmalloc(junk_len, GFP_KERNEL);
-	if (!junk)
-		return;
-	while (1) {
-		if (usb_bulk_msg(d->udev,
-			usb_rcvbulkpipe(d->udev, ep),
-			junk, junk_len, &rd_count, timeout) < 0)
-			break;
-		if (!rd_count)
-			break;
-	}
-	kfree(junk);
-}
-
-static void cxusb_d680_dmb_drain_video(struct dvb_usb_device *d)
-{
-	struct usb_data_stream_properties *p = &d->props.adapter[0].fe[0].stream;
-	const int timeout = 100;
-	const int junk_len = p->u.bulk.buffersize;
-	u8        *junk;
-	int       rd_count;
-
-	/* Discard remaining data in video pipe */
-	junk = kmalloc(junk_len, GFP_KERNEL);
-	if (!junk)
-		return;
-	while (1) {
-		if (usb_bulk_msg(d->udev,
-			usb_rcvbulkpipe(d->udev, p->endpoint),
-			junk, junk_len, &rd_count, timeout) < 0)
-			break;
-		if (!rd_count)
-			break;
-	}
-	kfree(junk);
-}
-
-static int cxusb_d680_dmb_streaming_ctrl(
-		struct dvb_usb_adapter *adap, int onoff)
-{
-	if (onoff) {
-		u8 buf[2] = { 0x03, 0x00 };
-		cxusb_d680_dmb_drain_video(adap->dev);
-		return cxusb_ctrl_msg(adap->dev, CMD_STREAMING_ON,
-			buf, sizeof(buf), NULL, 0);
-	} else {
-		int ret = cxusb_ctrl_msg(adap->dev,
-			CMD_STREAMING_OFF, NULL, 0, NULL, 0);
-		return ret;
-	}
-}
-
-static int cxusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
-{
-	struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table;
-	u8 ircode[4];
-	int i;
-
-	cxusb_ctrl_msg(d, CMD_GET_IR_CODE, NULL, 0, ircode, 4);
-
-	*event = 0;
-	*state = REMOTE_NO_KEY_PRESSED;
-
-	for (i = 0; i < d->props.rc.legacy.rc_map_size; i++) {
-		if (rc5_custom(&keymap[i]) == ircode[2] &&
-		    rc5_data(&keymap[i]) == ircode[3]) {
-			*event = keymap[i].keycode;
-			*state = REMOTE_KEY_PRESSED;
-
-			return 0;
-		}
-	}
-
-	return 0;
-}
-
-static int cxusb_bluebird2_rc_query(struct dvb_usb_device *d, u32 *event,
-				    int *state)
-{
-	struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table;
-	u8 ircode[4];
-	int i;
-	struct i2c_msg msg = { .addr = 0x6b, .flags = I2C_M_RD,
-			       .buf = ircode, .len = 4 };
-
-	*event = 0;
-	*state = REMOTE_NO_KEY_PRESSED;
-
-	if (cxusb_i2c_xfer(&d->i2c_adap, &msg, 1) != 1)
-		return 0;
-
-	for (i = 0; i < d->props.rc.legacy.rc_map_size; i++) {
-		if (rc5_custom(&keymap[i]) == ircode[1] &&
-		    rc5_data(&keymap[i]) == ircode[2]) {
-			*event = keymap[i].keycode;
-			*state = REMOTE_KEY_PRESSED;
-
-			return 0;
-		}
-	}
-
-	return 0;
-}
-
-static int cxusb_d680_dmb_rc_query(struct dvb_usb_device *d, u32 *event,
-		int *state)
-{
-	struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table;
-	u8 ircode[2];
-	int i;
-
-	*event = 0;
-	*state = REMOTE_NO_KEY_PRESSED;
-
-	if (cxusb_ctrl_msg(d, 0x10, NULL, 0, ircode, 2) < 0)
-		return 0;
-
-	for (i = 0; i < d->props.rc.legacy.rc_map_size; i++) {
-		if (rc5_custom(&keymap[i]) == ircode[0] &&
-		    rc5_data(&keymap[i]) == ircode[1]) {
-			*event = keymap[i].keycode;
-			*state = REMOTE_KEY_PRESSED;
-
-			return 0;
-		}
-	}
-
-	return 0;
-}
-
-static struct rc_map_table rc_map_dvico_mce_table[] = {
-	{ 0xfe02, KEY_TV },
-	{ 0xfe0e, KEY_MP3 },
-	{ 0xfe1a, KEY_DVD },
-	{ 0xfe1e, KEY_FAVORITES },
-	{ 0xfe16, KEY_SETUP },
-	{ 0xfe46, KEY_POWER2 },
-	{ 0xfe0a, KEY_EPG },
-	{ 0xfe49, KEY_BACK },
-	{ 0xfe4d, KEY_MENU },
-	{ 0xfe51, KEY_UP },
-	{ 0xfe5b, KEY_LEFT },
-	{ 0xfe5f, KEY_RIGHT },
-	{ 0xfe53, KEY_DOWN },
-	{ 0xfe5e, KEY_OK },
-	{ 0xfe59, KEY_INFO },
-	{ 0xfe55, KEY_TAB },
-	{ 0xfe0f, KEY_PREVIOUSSONG },/* Replay */
-	{ 0xfe12, KEY_NEXTSONG },	/* Skip */
-	{ 0xfe42, KEY_ENTER	 },	/* Windows/Start */
-	{ 0xfe15, KEY_VOLUMEUP },
-	{ 0xfe05, KEY_VOLUMEDOWN },
-	{ 0xfe11, KEY_CHANNELUP },
-	{ 0xfe09, KEY_CHANNELDOWN },
-	{ 0xfe52, KEY_CAMERA },
-	{ 0xfe5a, KEY_TUNER },	/* Live */
-	{ 0xfe19, KEY_OPEN },
-	{ 0xfe0b, KEY_1 },
-	{ 0xfe17, KEY_2 },
-	{ 0xfe1b, KEY_3 },
-	{ 0xfe07, KEY_4 },
-	{ 0xfe50, KEY_5 },
-	{ 0xfe54, KEY_6 },
-	{ 0xfe48, KEY_7 },
-	{ 0xfe4c, KEY_8 },
-	{ 0xfe58, KEY_9 },
-	{ 0xfe13, KEY_ANGLE },	/* Aspect */
-	{ 0xfe03, KEY_0 },
-	{ 0xfe1f, KEY_ZOOM },
-	{ 0xfe43, KEY_REWIND },
-	{ 0xfe47, KEY_PLAYPAUSE },
-	{ 0xfe4f, KEY_FASTFORWARD },
-	{ 0xfe57, KEY_MUTE },
-	{ 0xfe0d, KEY_STOP },
-	{ 0xfe01, KEY_RECORD },
-	{ 0xfe4e, KEY_POWER },
-};
-
-static struct rc_map_table rc_map_dvico_portable_table[] = {
-	{ 0xfc02, KEY_SETUP },       /* Profile */
-	{ 0xfc43, KEY_POWER2 },
-	{ 0xfc06, KEY_EPG },
-	{ 0xfc5a, KEY_BACK },
-	{ 0xfc05, KEY_MENU },
-	{ 0xfc47, KEY_INFO },
-	{ 0xfc01, KEY_TAB },
-	{ 0xfc42, KEY_PREVIOUSSONG },/* Replay */
-	{ 0xfc49, KEY_VOLUMEUP },
-	{ 0xfc09, KEY_VOLUMEDOWN },
-	{ 0xfc54, KEY_CHANNELUP },
-	{ 0xfc0b, KEY_CHANNELDOWN },
-	{ 0xfc16, KEY_CAMERA },
-	{ 0xfc40, KEY_TUNER },	/* ATV/DTV */
-	{ 0xfc45, KEY_OPEN },
-	{ 0xfc19, KEY_1 },
-	{ 0xfc18, KEY_2 },
-	{ 0xfc1b, KEY_3 },
-	{ 0xfc1a, KEY_4 },
-	{ 0xfc58, KEY_5 },
-	{ 0xfc59, KEY_6 },
-	{ 0xfc15, KEY_7 },
-	{ 0xfc14, KEY_8 },
-	{ 0xfc17, KEY_9 },
-	{ 0xfc44, KEY_ANGLE },	/* Aspect */
-	{ 0xfc55, KEY_0 },
-	{ 0xfc07, KEY_ZOOM },
-	{ 0xfc0a, KEY_REWIND },
-	{ 0xfc08, KEY_PLAYPAUSE },
-	{ 0xfc4b, KEY_FASTFORWARD },
-	{ 0xfc5b, KEY_MUTE },
-	{ 0xfc04, KEY_STOP },
-	{ 0xfc56, KEY_RECORD },
-	{ 0xfc57, KEY_POWER },
-	{ 0xfc41, KEY_UNKNOWN },    /* INPUT */
-	{ 0xfc00, KEY_UNKNOWN },    /* HD */
-};
-
-static struct rc_map_table rc_map_d680_dmb_table[] = {
-	{ 0x0038, KEY_UNKNOWN },	/* TV/AV */
-	{ 0x080c, KEY_ZOOM },
-	{ 0x0800, KEY_0 },
-	{ 0x0001, KEY_1 },
-	{ 0x0802, KEY_2 },
-	{ 0x0003, KEY_3 },
-	{ 0x0804, KEY_4 },
-	{ 0x0005, KEY_5 },
-	{ 0x0806, KEY_6 },
-	{ 0x0007, KEY_7 },
-	{ 0x0808, KEY_8 },
-	{ 0x0009, KEY_9 },
-	{ 0x000a, KEY_MUTE },
-	{ 0x0829, KEY_BACK },
-	{ 0x0012, KEY_CHANNELUP },
-	{ 0x0813, KEY_CHANNELDOWN },
-	{ 0x002b, KEY_VOLUMEUP },
-	{ 0x082c, KEY_VOLUMEDOWN },
-	{ 0x0020, KEY_UP },
-	{ 0x0821, KEY_DOWN },
-	{ 0x0011, KEY_LEFT },
-	{ 0x0810, KEY_RIGHT },
-	{ 0x000d, KEY_OK },
-	{ 0x081f, KEY_RECORD },
-	{ 0x0017, KEY_PLAYPAUSE },
-	{ 0x0816, KEY_PLAYPAUSE },
-	{ 0x000b, KEY_STOP },
-	{ 0x0827, KEY_FASTFORWARD },
-	{ 0x0026, KEY_REWIND },
-	{ 0x081e, KEY_UNKNOWN },    /* Time Shift */
-	{ 0x000e, KEY_UNKNOWN },    /* Snapshot */
-	{ 0x082d, KEY_UNKNOWN },    /* Mouse Cursor */
-	{ 0x000f, KEY_UNKNOWN },    /* Minimize/Maximize */
-	{ 0x0814, KEY_UNKNOWN },    /* Shuffle */
-	{ 0x0025, KEY_POWER },
-};
-
-static int cxusb_dee1601_demod_init(struct dvb_frontend* fe)
-{
-	static u8 clock_config []  = { CLOCK_CTL,  0x38, 0x28 };
-	static u8 reset []         = { RESET,      0x80 };
-	static u8 adc_ctl_1_cfg [] = { ADC_CTL_1,  0x40 };
-	static u8 agc_cfg []       = { AGC_TARGET, 0x28, 0x20 };
-	static u8 gpp_ctl_cfg []   = { GPP_CTL,    0x33 };
-	static u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 };
-
-	mt352_write(fe, clock_config,   sizeof(clock_config));
-	udelay(200);
-	mt352_write(fe, reset,          sizeof(reset));
-	mt352_write(fe, adc_ctl_1_cfg,  sizeof(adc_ctl_1_cfg));
-
-	mt352_write(fe, agc_cfg,        sizeof(agc_cfg));
-	mt352_write(fe, gpp_ctl_cfg,    sizeof(gpp_ctl_cfg));
-	mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
-
-	return 0;
-}
-
-static int cxusb_mt352_demod_init(struct dvb_frontend* fe)
-{	/* used in both lgz201 and th7579 */
-	static u8 clock_config []  = { CLOCK_CTL,  0x38, 0x29 };
-	static u8 reset []         = { RESET,      0x80 };
-	static u8 adc_ctl_1_cfg [] = { ADC_CTL_1,  0x40 };
-	static u8 agc_cfg []       = { AGC_TARGET, 0x24, 0x20 };
-	static u8 gpp_ctl_cfg []   = { GPP_CTL,    0x33 };
-	static u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 };
-
-	mt352_write(fe, clock_config,   sizeof(clock_config));
-	udelay(200);
-	mt352_write(fe, reset,          sizeof(reset));
-	mt352_write(fe, adc_ctl_1_cfg,  sizeof(adc_ctl_1_cfg));
-
-	mt352_write(fe, agc_cfg,        sizeof(agc_cfg));
-	mt352_write(fe, gpp_ctl_cfg,    sizeof(gpp_ctl_cfg));
-	mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
-	return 0;
-}
-
-static struct cx22702_config cxusb_cx22702_config = {
-	.demod_address = 0x63,
-	.output_mode = CX22702_PARALLEL_OUTPUT,
-};
-
-static struct lgdt330x_config cxusb_lgdt3303_config = {
-	.demod_address = 0x0e,
-	.demod_chip    = LGDT3303,
-};
-
-static struct lgdt330x_config cxusb_aver_lgdt3303_config = {
-	.demod_address       = 0x0e,
-	.demod_chip          = LGDT3303,
-	.clock_polarity_flip = 2,
-};
-
-static struct mt352_config cxusb_dee1601_config = {
-	.demod_address = 0x0f,
-	.demod_init    = cxusb_dee1601_demod_init,
-};
-
-static struct zl10353_config cxusb_zl10353_dee1601_config = {
-	.demod_address = 0x0f,
-	.parallel_ts = 1,
-};
-
-static struct mt352_config cxusb_mt352_config = {
-	/* used in both lgz201 and th7579 */
-	.demod_address = 0x0f,
-	.demod_init    = cxusb_mt352_demod_init,
-};
-
-static struct zl10353_config cxusb_zl10353_xc3028_config = {
-	.demod_address = 0x0f,
-	.if2 = 45600,
-	.no_tuner = 1,
-	.parallel_ts = 1,
-};
-
-static struct zl10353_config cxusb_zl10353_xc3028_config_no_i2c_gate = {
-	.demod_address = 0x0f,
-	.if2 = 45600,
-	.no_tuner = 1,
-	.parallel_ts = 1,
-	.disable_i2c_gate_ctrl = 1,
-};
-
-static struct mt352_config cxusb_mt352_xc3028_config = {
-	.demod_address = 0x0f,
-	.if2 = 4560,
-	.no_tuner = 1,
-	.demod_init = cxusb_mt352_demod_init,
-};
-
-/* FIXME: needs tweaking */
-static struct mxl5005s_config aver_a868r_tuner = {
-	.i2c_address     = 0x63,
-	.if_freq         = 6000000UL,
-	.xtal_freq       = CRYSTAL_FREQ_16000000HZ,
-	.agc_mode        = MXL_SINGLE_AGC,
-	.tracking_filter = MXL_TF_C,
-	.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,
-};
-
-/* FIXME: needs tweaking */
-static struct mxl5005s_config d680_dmb_tuner = {
-	.i2c_address     = 0x63,
-	.if_freq         = 36125000UL,
-	.xtal_freq       = CRYSTAL_FREQ_16000000HZ,
-	.agc_mode        = MXL_SINGLE_AGC,
-	.tracking_filter = MXL_TF_C,
-	.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 struct max2165_config mygica_d689_max2165_cfg = {
-	.i2c_address = 0x60,
-	.osc_clk = 20
-};
-
-/* Callbacks for DVB USB */
-static int cxusb_fmd1216me_tuner_attach(struct dvb_usb_adapter *adap)
-{
-	dvb_attach(simple_tuner_attach, adap->fe_adap[0].fe,
-		   &adap->dev->i2c_adap, 0x61,
-		   TUNER_PHILIPS_FMD1216ME_MK3);
-	return 0;
-}
-
-static int cxusb_dee1601_tuner_attach(struct dvb_usb_adapter *adap)
-{
-	dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x61,
-		   NULL, DVB_PLL_THOMSON_DTT7579);
-	return 0;
-}
-
-static int cxusb_lgz201_tuner_attach(struct dvb_usb_adapter *adap)
-{
-	dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x61, NULL, DVB_PLL_LG_Z201);
-	return 0;
-}
-
-static int cxusb_dtt7579_tuner_attach(struct dvb_usb_adapter *adap)
-{
-	dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x60,
-		   NULL, DVB_PLL_THOMSON_DTT7579);
-	return 0;
-}
-
-static int cxusb_lgh064f_tuner_attach(struct dvb_usb_adapter *adap)
-{
-	dvb_attach(simple_tuner_attach, adap->fe_adap[0].fe,
-		   &adap->dev->i2c_adap, 0x61, TUNER_LG_TDVS_H06XF);
-	return 0;
-}
-
-static int dvico_bluebird_xc2028_callback(void *ptr, int component,
-					  int command, int arg)
-{
-	struct dvb_usb_adapter *adap = ptr;
-	struct dvb_usb_device *d = adap->dev;
-
-	switch (command) {
-	case XC2028_TUNER_RESET:
-		deb_info("%s: XC2028_TUNER_RESET %d\n", __func__, arg);
-		cxusb_bluebird_gpio_pulse(d, 0x01, 1);
-		break;
-	case XC2028_RESET_CLK:
-		deb_info("%s: XC2028_RESET_CLK %d\n", __func__, arg);
-		break;
-	default:
-		deb_info("%s: unknown command %d, arg %d\n", __func__,
-			 command, arg);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int cxusb_dvico_xc3028_tuner_attach(struct dvb_usb_adapter *adap)
-{
-	struct dvb_frontend	 *fe;
-	struct xc2028_config	  cfg = {
-		.i2c_adap  = &adap->dev->i2c_adap,
-		.i2c_addr  = 0x61,
-	};
-	static struct xc2028_ctrl ctl = {
-		.fname       = XC2028_DEFAULT_FIRMWARE,
-		.max_len     = 64,
-		.demod       = XC3028_FE_ZARLINK456,
-	};
-
-	/* FIXME: generalize & move to common area */
-	adap->fe_adap[0].fe->callback = dvico_bluebird_xc2028_callback;
-
-	fe = dvb_attach(xc2028_attach, adap->fe_adap[0].fe, &cfg);
-	if (fe == NULL || fe->ops.tuner_ops.set_config == NULL)
-		return -EIO;
-
-	fe->ops.tuner_ops.set_config(fe, &ctl);
-
-	return 0;
-}
-
-static int cxusb_mxl5003s_tuner_attach(struct dvb_usb_adapter *adap)
-{
-	dvb_attach(mxl5005s_attach, adap->fe_adap[0].fe,
-		   &adap->dev->i2c_adap, &aver_a868r_tuner);
-	return 0;
-}
-
-static int cxusb_d680_dmb_tuner_attach(struct dvb_usb_adapter *adap)
-{
-	struct dvb_frontend *fe;
-	fe = dvb_attach(mxl5005s_attach, adap->fe_adap[0].fe,
-			&adap->dev->i2c_adap, &d680_dmb_tuner);
-	return (fe == NULL) ? -EIO : 0;
-}
-
-static int cxusb_mygica_d689_tuner_attach(struct dvb_usb_adapter *adap)
-{
-	struct dvb_frontend *fe;
-	fe = dvb_attach(max2165_attach, adap->fe_adap[0].fe,
-			&adap->dev->i2c_adap, &mygica_d689_max2165_cfg);
-	return (fe == NULL) ? -EIO : 0;
-}
-
-static int cxusb_cx22702_frontend_attach(struct dvb_usb_adapter *adap)
-{
-	u8 b;
-	if (usb_set_interface(adap->dev->udev, 0, 6) < 0)
-		err("set interface failed");
-
-	cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, &b, 1);
-
-	adap->fe_adap[0].fe = dvb_attach(cx22702_attach, &cxusb_cx22702_config,
-					 &adap->dev->i2c_adap);
-	if ((adap->fe_adap[0].fe) != NULL)
-		return 0;
-
-	return -EIO;
-}
-
-static int cxusb_lgdt3303_frontend_attach(struct dvb_usb_adapter *adap)
-{
-	if (usb_set_interface(adap->dev->udev, 0, 7) < 0)
-		err("set interface failed");
-
-	cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0);
-
-	adap->fe_adap[0].fe = dvb_attach(lgdt330x_attach,
-					 &cxusb_lgdt3303_config,
-					 &adap->dev->i2c_adap);
-	if ((adap->fe_adap[0].fe) != NULL)
-		return 0;
-
-	return -EIO;
-}
-
-static int cxusb_aver_lgdt3303_frontend_attach(struct dvb_usb_adapter *adap)
-{
-	adap->fe_adap[0].fe = dvb_attach(lgdt330x_attach, &cxusb_aver_lgdt3303_config,
-			      &adap->dev->i2c_adap);
-	if (adap->fe_adap[0].fe != NULL)
-		return 0;
-
-	return -EIO;
-}
-
-static int cxusb_mt352_frontend_attach(struct dvb_usb_adapter *adap)
-{
-	/* used in both lgz201 and th7579 */
-	if (usb_set_interface(adap->dev->udev, 0, 0) < 0)
-		err("set interface failed");
-
-	cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0);
-
-	adap->fe_adap[0].fe = dvb_attach(mt352_attach, &cxusb_mt352_config,
-					 &adap->dev->i2c_adap);
-	if ((adap->fe_adap[0].fe) != NULL)
-		return 0;
-
-	return -EIO;
-}
-
-static int cxusb_dee1601_frontend_attach(struct dvb_usb_adapter *adap)
-{
-	if (usb_set_interface(adap->dev->udev, 0, 0) < 0)
-		err("set interface failed");
-
-	cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0);
-
-	adap->fe_adap[0].fe = dvb_attach(mt352_attach, &cxusb_dee1601_config,
-					 &adap->dev->i2c_adap);
-	if ((adap->fe_adap[0].fe) != NULL)
-		return 0;
-
-	adap->fe_adap[0].fe = dvb_attach(zl10353_attach,
-					 &cxusb_zl10353_dee1601_config,
-					 &adap->dev->i2c_adap);
-	if ((adap->fe_adap[0].fe) != NULL)
-		return 0;
-
-	return -EIO;
-}
-
-static int cxusb_dualdig4_frontend_attach(struct dvb_usb_adapter *adap)
-{
-	u8 ircode[4];
-	int i;
-	struct i2c_msg msg = { .addr = 0x6b, .flags = I2C_M_RD,
-			       .buf = ircode, .len = 4 };
-
-	if (usb_set_interface(adap->dev->udev, 0, 1) < 0)
-		err("set interface failed");
-
-	cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0);
-
-	/* reset the tuner and demodulator */
-	cxusb_bluebird_gpio_rw(adap->dev, 0x04, 0);
-	cxusb_bluebird_gpio_pulse(adap->dev, 0x01, 1);
-	cxusb_bluebird_gpio_pulse(adap->dev, 0x02, 1);
-
-	adap->fe_adap[0].fe =
-		dvb_attach(zl10353_attach,
-			   &cxusb_zl10353_xc3028_config_no_i2c_gate,
-			   &adap->dev->i2c_adap);
-	if ((adap->fe_adap[0].fe) == NULL)
-		return -EIO;
-
-	/* try to determine if there is no IR decoder on the I2C bus */
-	for (i = 0; adap->dev->props.rc.legacy.rc_map_table != NULL && i < 5; i++) {
-		msleep(20);
-		if (cxusb_i2c_xfer(&adap->dev->i2c_adap, &msg, 1) != 1)
-			goto no_IR;
-		if (ircode[0] == 0 && ircode[1] == 0)
-			continue;
-		if (ircode[2] + ircode[3] != 0xff) {
-no_IR:
-			adap->dev->props.rc.legacy.rc_map_table = NULL;
-			info("No IR receiver detected on this device.");
-			break;
-		}
-	}
-
-	return 0;
-}
-
-static struct dibx000_agc_config dib7070_agc_config = {
-	.band_caps = BAND_UHF | BAND_VHF | BAND_LBAND | BAND_SBAND,
-
-	/*
-	 * P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=5,
-	 * P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, P_agc_inh_dc_rv_est=0,
-	 * P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, P_agc_write=0
-	 */
-	.setup = (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) |
-		 (0 << 8) | (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0),
-	.inv_gain = 600,
-	.time_stabiliz = 10,
-	.alpha_level = 0,
-	.thlock = 118,
-	.wbd_inv = 0,
-	.wbd_ref = 3530,
-	.wbd_sel = 1,
-	.wbd_alpha = 5,
-	.agc1_max = 65535,
-	.agc1_min = 0,
-	.agc2_max = 65535,
-	.agc2_min = 0,
-	.agc1_pt1 = 0,
-	.agc1_pt2 = 40,
-	.agc1_pt3 = 183,
-	.agc1_slope1 = 206,
-	.agc1_slope2 = 255,
-	.agc2_pt1 = 72,
-	.agc2_pt2 = 152,
-	.agc2_slope1 = 88,
-	.agc2_slope2 = 90,
-	.alpha_mant = 17,
-	.alpha_exp = 27,
-	.beta_mant = 23,
-	.beta_exp = 51,
-	.perform_agc_softsplit = 0,
-};
-
-static struct dibx000_bandwidth_config dib7070_bw_config_12_mhz = {
-	.internal = 60000,
-	.sampling = 15000,
-	.pll_prediv = 1,
-	.pll_ratio = 20,
-	.pll_range = 3,
-	.pll_reset = 1,
-	.pll_bypass = 0,
-	.enable_refdiv = 0,
-	.bypclk_div = 0,
-	.IO_CLK_en_core = 1,
-	.ADClkSrc = 1,
-	.modulo = 2,
-	/* refsel, sel, freq_15k */
-	.sad_cfg = (3 << 14) | (1 << 12) | (524 << 0),
-	.ifreq = (0 << 25) | 0,
-	.timf = 20452225,
-	.xtal_hz = 12000000,
-};
-
-static struct dib7000p_config cxusb_dualdig4_rev2_config = {
-	.output_mode = OUTMODE_MPEG2_PAR_GATED_CLK,
-	.output_mpeg2_in_188_bytes = 1,
-
-	.agc_config_count = 1,
-	.agc = &dib7070_agc_config,
-	.bw  = &dib7070_bw_config_12_mhz,
-	.tuner_is_baseband = 1,
-	.spur_protect = 1,
-
-	.gpio_dir = 0xfcef,
-	.gpio_val = 0x0110,
-
-	.gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS,
-
-	.hostbus_diversity = 1,
-};
-
-static int cxusb_dualdig4_rev2_frontend_attach(struct dvb_usb_adapter *adap)
-{
-	if (usb_set_interface(adap->dev->udev, 0, 1) < 0)
-		err("set interface failed");
-
-	cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0);
-
-	cxusb_bluebird_gpio_pulse(adap->dev, 0x02, 1);
-
-	if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
-				     &cxusb_dualdig4_rev2_config) < 0) {
-		printk(KERN_WARNING "Unable to enumerate dib7000p\n");
-		return -ENODEV;
-	}
-
-	adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
-			      &cxusb_dualdig4_rev2_config);
-	if (adap->fe_adap[0].fe == NULL)
-		return -EIO;
-
-	return 0;
-}
-
-static int dib7070_tuner_reset(struct dvb_frontend *fe, int onoff)
-{
-	return dib7000p_set_gpio(fe, 8, 0, !onoff);
-}
-
-static int dib7070_tuner_sleep(struct dvb_frontend *fe, int onoff)
-{
-	return 0;
-}
-
-static struct dib0070_config dib7070p_dib0070_config = {
-	.i2c_address = DEFAULT_DIB0070_I2C_ADDRESS,
-	.reset = dib7070_tuner_reset,
-	.sleep = dib7070_tuner_sleep,
-	.clock_khz = 12000,
-};
-
-struct dib0700_adapter_state {
-	int (*set_param_save) (struct dvb_frontend *);
-};
-
-static int dib7070_set_param_override(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct dvb_usb_adapter *adap = fe->dvb->priv;
-	struct dib0700_adapter_state *state = adap->priv;
-
-	u16 offset;
-	u8 band = BAND_OF_FREQUENCY(p->frequency/1000);
-	switch (band) {
-	case BAND_VHF: offset = 950; break;
-	default:
-	case BAND_UHF: offset = 550; break;
-	}
-
-	dib7000p_set_wbd_ref(fe, offset + dib0070_wbd_offset(fe));
-
-	return state->set_param_save(fe);
-}
-
-static int cxusb_dualdig4_rev2_tuner_attach(struct dvb_usb_adapter *adap)
-{
-	struct dib0700_adapter_state *st = adap->priv;
-	struct i2c_adapter *tun_i2c =
-		dib7000p_get_i2c_master(adap->fe_adap[0].fe,
-					DIBX000_I2C_INTERFACE_TUNER, 1);
-
-	if (dvb_attach(dib0070_attach, adap->fe_adap[0].fe, tun_i2c,
-	    &dib7070p_dib0070_config) == NULL)
-		return -ENODEV;
-
-	st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
-	adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7070_set_param_override;
-	return 0;
-}
-
-static int cxusb_nano2_frontend_attach(struct dvb_usb_adapter *adap)
-{
-	if (usb_set_interface(adap->dev->udev, 0, 1) < 0)
-		err("set interface failed");
-
-	cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0);
-
-	/* reset the tuner and demodulator */
-	cxusb_bluebird_gpio_rw(adap->dev, 0x04, 0);
-	cxusb_bluebird_gpio_pulse(adap->dev, 0x01, 1);
-	cxusb_bluebird_gpio_pulse(adap->dev, 0x02, 1);
-
-	adap->fe_adap[0].fe = dvb_attach(zl10353_attach,
-					 &cxusb_zl10353_xc3028_config,
-					 &adap->dev->i2c_adap);
-	if ((adap->fe_adap[0].fe) != NULL)
-		return 0;
-
-	adap->fe_adap[0].fe = dvb_attach(mt352_attach,
-					 &cxusb_mt352_xc3028_config,
-					 &adap->dev->i2c_adap);
-	if ((adap->fe_adap[0].fe) != NULL)
-		return 0;
-
-	return -EIO;
-}
-
-static struct lgs8gxx_config d680_lgs8gl5_cfg = {
-	.prod = LGS8GXX_PROD_LGS8GL5,
-	.demod_address = 0x19,
-	.serial_ts = 0,
-	.ts_clk_pol = 0,
-	.ts_clk_gated = 1,
-	.if_clk_freq = 30400, /* 30.4 MHz */
-	.if_freq = 5725, /* 5.725 MHz */
-	.if_neg_center = 0,
-	.ext_adc = 0,
-	.adc_signed = 0,
-	.if_neg_edge = 0,
-};
-
-static int cxusb_d680_dmb_frontend_attach(struct dvb_usb_adapter *adap)
-{
-	struct dvb_usb_device *d = adap->dev;
-	int n;
-
-	/* Select required USB configuration */
-	if (usb_set_interface(d->udev, 0, 0) < 0)
-		err("set interface failed");
-
-	/* Unblock all USB pipes */
-	usb_clear_halt(d->udev,
-		usb_sndbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint));
-	usb_clear_halt(d->udev,
-		usb_rcvbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint));
-	usb_clear_halt(d->udev,
-		usb_rcvbulkpipe(d->udev, d->props.adapter[0].fe[0].stream.endpoint));
-
-	/* Drain USB pipes to avoid hang after reboot */
-	for (n = 0;  n < 5;  n++) {
-		cxusb_d680_dmb_drain_message(d);
-		cxusb_d680_dmb_drain_video(d);
-		msleep(200);
-	}
-
-	/* Reset the tuner */
-	if (cxusb_d680_dmb_gpio_tuner(d, 0x07, 0) < 0) {
-		err("clear tuner gpio failed");
-		return -EIO;
-	}
-	msleep(100);
-	if (cxusb_d680_dmb_gpio_tuner(d, 0x07, 1) < 0) {
-		err("set tuner gpio failed");
-		return -EIO;
-	}
-	msleep(100);
-
-	/* Attach frontend */
-	adap->fe_adap[0].fe = dvb_attach(lgs8gxx_attach, &d680_lgs8gl5_cfg, &d->i2c_adap);
-	if (adap->fe_adap[0].fe == NULL)
-		return -EIO;
-
-	return 0;
-}
-
-static struct atbm8830_config mygica_d689_atbm8830_cfg = {
-	.prod = ATBM8830_PROD_8830,
-	.demod_address = 0x40,
-	.serial_ts = 0,
-	.ts_sampling_edge = 1,
-	.ts_clk_gated = 0,
-	.osc_clk_freq = 30400, /* in kHz */
-	.if_freq = 0, /* zero IF */
-	.zif_swap_iq = 1,
-	.agc_min = 0x2E,
-	.agc_max = 0x90,
-	.agc_hold_loop = 0,
-};
-
-static int cxusb_mygica_d689_frontend_attach(struct dvb_usb_adapter *adap)
-{
-	struct dvb_usb_device *d = adap->dev;
-
-	/* Select required USB configuration */
-	if (usb_set_interface(d->udev, 0, 0) < 0)
-		err("set interface failed");
-
-	/* Unblock all USB pipes */
-	usb_clear_halt(d->udev,
-		usb_sndbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint));
-	usb_clear_halt(d->udev,
-		usb_rcvbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint));
-	usb_clear_halt(d->udev,
-		usb_rcvbulkpipe(d->udev, d->props.adapter[0].fe[0].stream.endpoint));
-
-
-	/* Reset the tuner */
-	if (cxusb_d680_dmb_gpio_tuner(d, 0x07, 0) < 0) {
-		err("clear tuner gpio failed");
-		return -EIO;
-	}
-	msleep(100);
-	if (cxusb_d680_dmb_gpio_tuner(d, 0x07, 1) < 0) {
-		err("set tuner gpio failed");
-		return -EIO;
-	}
-	msleep(100);
-
-	/* Attach frontend */
-	adap->fe_adap[0].fe = dvb_attach(atbm8830_attach, &mygica_d689_atbm8830_cfg,
-		&d->i2c_adap);
-	if (adap->fe_adap[0].fe == NULL)
-		return -EIO;
-
-	return 0;
-}
-
-/*
- * DViCO has shipped two devices with the same USB ID, but only one of them
- * needs a firmware download.  Check the device class details to see if they
- * have non-default values to decide whether the device is actually cold or
- * not, and forget a match if it turns out we selected the wrong device.
- */
-static int bluebird_fx2_identify_state(struct usb_device *udev,
-				       struct dvb_usb_device_properties *props,
-				       struct dvb_usb_device_description **desc,
-				       int *cold)
-{
-	int wascold = *cold;
-
-	*cold = udev->descriptor.bDeviceClass == 0xff &&
-		udev->descriptor.bDeviceSubClass == 0xff &&
-		udev->descriptor.bDeviceProtocol == 0xff;
-
-	if (*cold && !wascold)
-		*desc = NULL;
-
-	return 0;
-}
-
-/*
- * DViCO bluebird firmware needs the "warm" product ID to be patched into the
- * firmware file before download.
- */
-
-static const int dvico_firmware_id_offsets[] = { 6638, 3204 };
-static int bluebird_patch_dvico_firmware_download(struct usb_device *udev,
-						  const struct firmware *fw)
-{
-	int pos;
-
-	for (pos = 0; pos < ARRAY_SIZE(dvico_firmware_id_offsets); pos++) {
-		int idoff = dvico_firmware_id_offsets[pos];
-
-		if (fw->size < idoff + 4)
-			continue;
-
-		if (fw->data[idoff] == (USB_VID_DVICO & 0xff) &&
-		    fw->data[idoff + 1] == USB_VID_DVICO >> 8) {
-			struct firmware new_fw;
-			u8 *new_fw_data = vmalloc(fw->size);
-			int ret;
-
-			if (!new_fw_data)
-				return -ENOMEM;
-
-			memcpy(new_fw_data, fw->data, fw->size);
-			new_fw.size = fw->size;
-			new_fw.data = new_fw_data;
-
-			new_fw_data[idoff + 2] =
-				le16_to_cpu(udev->descriptor.idProduct) + 1;
-			new_fw_data[idoff + 3] =
-				le16_to_cpu(udev->descriptor.idProduct) >> 8;
-
-			ret = usb_cypress_load_firmware(udev, &new_fw,
-							CYPRESS_FX2);
-			vfree(new_fw_data);
-			return ret;
-		}
-	}
-
-	return -EINVAL;
-}
-
-/* DVB USB Driver stuff */
-static struct dvb_usb_device_properties cxusb_medion_properties;
-static struct dvb_usb_device_properties cxusb_bluebird_lgh064f_properties;
-static struct dvb_usb_device_properties cxusb_bluebird_dee1601_properties;
-static struct dvb_usb_device_properties cxusb_bluebird_lgz201_properties;
-static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties;
-static struct dvb_usb_device_properties cxusb_bluebird_dualdig4_properties;
-static struct dvb_usb_device_properties cxusb_bluebird_dualdig4_rev2_properties;
-static struct dvb_usb_device_properties cxusb_bluebird_nano2_properties;
-static struct dvb_usb_device_properties cxusb_bluebird_nano2_needsfirmware_properties;
-static struct dvb_usb_device_properties cxusb_aver_a868r_properties;
-static struct dvb_usb_device_properties cxusb_d680_dmb_properties;
-static struct dvb_usb_device_properties cxusb_mygica_d689_properties;
-
-static int cxusb_probe(struct usb_interface *intf,
-		       const struct usb_device_id *id)
-{
-	if (0 == dvb_usb_device_init(intf, &cxusb_medion_properties,
-				     THIS_MODULE, NULL, adapter_nr) ||
-	    0 == dvb_usb_device_init(intf, &cxusb_bluebird_lgh064f_properties,
-				     THIS_MODULE, NULL, adapter_nr) ||
-	    0 == dvb_usb_device_init(intf, &cxusb_bluebird_dee1601_properties,
-				     THIS_MODULE, NULL, adapter_nr) ||
-	    0 == dvb_usb_device_init(intf, &cxusb_bluebird_lgz201_properties,
-				     THIS_MODULE, NULL, adapter_nr) ||
-	    0 == dvb_usb_device_init(intf, &cxusb_bluebird_dtt7579_properties,
-				     THIS_MODULE, NULL, adapter_nr) ||
-	    0 == dvb_usb_device_init(intf, &cxusb_bluebird_dualdig4_properties,
-				     THIS_MODULE, NULL, adapter_nr) ||
-	    0 == dvb_usb_device_init(intf, &cxusb_bluebird_nano2_properties,
-				     THIS_MODULE, NULL, adapter_nr) ||
-	    0 == dvb_usb_device_init(intf,
-				&cxusb_bluebird_nano2_needsfirmware_properties,
-				     THIS_MODULE, NULL, adapter_nr) ||
-	    0 == dvb_usb_device_init(intf, &cxusb_aver_a868r_properties,
-				     THIS_MODULE, NULL, adapter_nr) ||
-	    0 == dvb_usb_device_init(intf,
-				     &cxusb_bluebird_dualdig4_rev2_properties,
-				     THIS_MODULE, NULL, adapter_nr) ||
-	    0 == dvb_usb_device_init(intf, &cxusb_d680_dmb_properties,
-				     THIS_MODULE, NULL, adapter_nr) ||
-	    0 == dvb_usb_device_init(intf, &cxusb_mygica_d689_properties,
-				     THIS_MODULE, NULL, adapter_nr) ||
-	    0)
-		return 0;
-
-	return -EINVAL;
-}
-
-static struct usb_device_id cxusb_table [] = {
-	{ USB_DEVICE(USB_VID_MEDION, USB_PID_MEDION_MD95700) },
-	{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LG064F_COLD) },
-	{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LG064F_WARM) },
-	{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_1_COLD) },
-	{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_1_WARM) },
-	{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LGZ201_COLD) },
-	{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LGZ201_WARM) },
-	{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_TH7579_COLD) },
-	{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_TH7579_WARM) },
-	{ USB_DEVICE(USB_VID_DVICO, USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_COLD) },
-	{ USB_DEVICE(USB_VID_DVICO, USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_WARM) },
-	{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_2_COLD) },
-	{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_2_WARM) },
-	{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_4) },
-	{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2) },
-	{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2_NFW_WARM) },
-	{ USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_A868R) },
-	{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_4_REV_2) },
-	{ USB_DEVICE(USB_VID_CONEXANT, USB_PID_CONEXANT_D680_DMB) },
-	{ USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_D689) },
-	{}		/* Terminating entry */
-};
-MODULE_DEVICE_TABLE (usb, cxusb_table);
-
-static struct dvb_usb_device_properties cxusb_medion_properties = {
-	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
-
-	.usb_ctrl = CYPRESS_FX2,
-
-	.size_of_priv     = sizeof(struct cxusb_state),
-
-	.num_adapters = 1,
-	.adapter = {
-		{
-		.num_frontends = 1,
-		.fe = {{
-			.streaming_ctrl   = cxusb_streaming_ctrl,
-			.frontend_attach  = cxusb_cx22702_frontend_attach,
-			.tuner_attach     = cxusb_fmd1216me_tuner_attach,
-			/* parameter for the MPEG2-data transfer */
-					.stream = {
-						.type = USB_BULK,
-				.count = 5,
-				.endpoint = 0x02,
-				.u = {
-					.bulk = {
-						.buffersize = 8192,
-					}
-				}
-			},
-		}},
-		},
-	},
-	.power_ctrl       = cxusb_power_ctrl,
-
-	.i2c_algo         = &cxusb_i2c_algo,
-
-	.generic_bulk_ctrl_endpoint = 0x01,
-
-	.num_device_descs = 1,
-	.devices = {
-		{   "Medion MD95700 (MDUSBTV-HYBRID)",
-			{ NULL },
-			{ &cxusb_table[0], NULL },
-		},
-	}
-};
-
-static struct dvb_usb_device_properties cxusb_bluebird_lgh064f_properties = {
-	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
-
-	.usb_ctrl          = DEVICE_SPECIFIC,
-	.firmware          = "dvb-usb-bluebird-01.fw",
-	.download_firmware = bluebird_patch_dvico_firmware_download,
-	/* use usb alt setting 0 for EP4 transfer (dvb-t),
-	   use usb alt setting 7 for EP2 transfer (atsc) */
-
-	.size_of_priv     = sizeof(struct cxusb_state),
-
-	.num_adapters = 1,
-	.adapter = {
-		{
-		.num_frontends = 1,
-		.fe = {{
-			.streaming_ctrl   = cxusb_streaming_ctrl,
-			.frontend_attach  = cxusb_lgdt3303_frontend_attach,
-			.tuner_attach     = cxusb_lgh064f_tuner_attach,
-
-			/* parameter for the MPEG2-data transfer */
-					.stream = {
-						.type = USB_BULK,
-				.count = 5,
-				.endpoint = 0x02,
-				.u = {
-					.bulk = {
-						.buffersize = 8192,
-					}
-				}
-			},
-		}},
-		},
-	},
-
-	.power_ctrl       = cxusb_bluebird_power_ctrl,
-
-	.i2c_algo         = &cxusb_i2c_algo,
-
-	.rc.legacy = {
-		.rc_interval      = 100,
-		.rc_map_table     = rc_map_dvico_portable_table,
-		.rc_map_size      = ARRAY_SIZE(rc_map_dvico_portable_table),
-		.rc_query         = cxusb_rc_query,
-	},
-
-	.generic_bulk_ctrl_endpoint = 0x01,
-
-	.num_device_descs = 1,
-	.devices = {
-		{   "DViCO FusionHDTV5 USB Gold",
-			{ &cxusb_table[1], NULL },
-			{ &cxusb_table[2], NULL },
-		},
-	}
-};
-
-static struct dvb_usb_device_properties cxusb_bluebird_dee1601_properties = {
-	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
-
-	.usb_ctrl          = DEVICE_SPECIFIC,
-	.firmware          = "dvb-usb-bluebird-01.fw",
-	.download_firmware = bluebird_patch_dvico_firmware_download,
-	/* use usb alt setting 0 for EP4 transfer (dvb-t),
-	   use usb alt setting 7 for EP2 transfer (atsc) */
-
-	.size_of_priv     = sizeof(struct cxusb_state),
-
-	.num_adapters = 1,
-	.adapter = {
-		{
-		.num_frontends = 1,
-		.fe = {{
-			.streaming_ctrl   = cxusb_streaming_ctrl,
-			.frontend_attach  = cxusb_dee1601_frontend_attach,
-			.tuner_attach     = cxusb_dee1601_tuner_attach,
-			/* parameter for the MPEG2-data transfer */
-			.stream = {
-				.type = USB_BULK,
-				.count = 5,
-				.endpoint = 0x04,
-				.u = {
-					.bulk = {
-						.buffersize = 8192,
-					}
-				}
-			},
-		}},
-		},
-	},
-
-	.power_ctrl       = cxusb_bluebird_power_ctrl,
-
-	.i2c_algo         = &cxusb_i2c_algo,
-
-	.rc.legacy = {
-		.rc_interval      = 150,
-		.rc_map_table     = rc_map_dvico_mce_table,
-		.rc_map_size      = ARRAY_SIZE(rc_map_dvico_mce_table),
-		.rc_query         = cxusb_rc_query,
-	},
-
-	.generic_bulk_ctrl_endpoint = 0x01,
-
-	.num_device_descs = 3,
-	.devices = {
-		{   "DViCO FusionHDTV DVB-T Dual USB",
-			{ &cxusb_table[3], NULL },
-			{ &cxusb_table[4], NULL },
-		},
-		{   "DigitalNow DVB-T Dual USB",
-			{ &cxusb_table[9],  NULL },
-			{ &cxusb_table[10], NULL },
-		},
-		{   "DViCO FusionHDTV DVB-T Dual Digital 2",
-			{ &cxusb_table[11], NULL },
-			{ &cxusb_table[12], NULL },
-		},
-	}
-};
-
-static struct dvb_usb_device_properties cxusb_bluebird_lgz201_properties = {
-	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
-
-	.usb_ctrl          = DEVICE_SPECIFIC,
-	.firmware          = "dvb-usb-bluebird-01.fw",
-	.download_firmware = bluebird_patch_dvico_firmware_download,
-	/* use usb alt setting 0 for EP4 transfer (dvb-t),
-	   use usb alt setting 7 for EP2 transfer (atsc) */
-
-	.size_of_priv     = sizeof(struct cxusb_state),
-
-	.num_adapters = 2,
-	.adapter = {
-		{
-		.num_frontends = 1,
-		.fe = {{
-			.streaming_ctrl   = cxusb_streaming_ctrl,
-			.frontend_attach  = cxusb_mt352_frontend_attach,
-			.tuner_attach     = cxusb_lgz201_tuner_attach,
-
-			/* parameter for the MPEG2-data transfer */
-			.stream = {
-				.type = USB_BULK,
-				.count = 5,
-				.endpoint = 0x04,
-				.u = {
-					.bulk = {
-						.buffersize = 8192,
-					}
-				}
-			},
-		}},
-		},
-	},
-	.power_ctrl       = cxusb_bluebird_power_ctrl,
-
-	.i2c_algo         = &cxusb_i2c_algo,
-
-	.rc.legacy = {
-		.rc_interval      = 100,
-		.rc_map_table     = rc_map_dvico_portable_table,
-		.rc_map_size      = ARRAY_SIZE(rc_map_dvico_portable_table),
-		.rc_query         = cxusb_rc_query,
-	},
-
-	.generic_bulk_ctrl_endpoint = 0x01,
-	.num_device_descs = 1,
-	.devices = {
-		{   "DViCO FusionHDTV DVB-T USB (LGZ201)",
-			{ &cxusb_table[5], NULL },
-			{ &cxusb_table[6], NULL },
-		},
-	}
-};
-
-static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties = {
-	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
-
-	.usb_ctrl          = DEVICE_SPECIFIC,
-	.firmware          = "dvb-usb-bluebird-01.fw",
-	.download_firmware = bluebird_patch_dvico_firmware_download,
-	/* use usb alt setting 0 for EP4 transfer (dvb-t),
-	   use usb alt setting 7 for EP2 transfer (atsc) */
-
-	.size_of_priv     = sizeof(struct cxusb_state),
-
-	.num_adapters = 1,
-	.adapter = {
-		{
-		.num_frontends = 1,
-		.fe = {{
-			.streaming_ctrl   = cxusb_streaming_ctrl,
-			.frontend_attach  = cxusb_mt352_frontend_attach,
-			.tuner_attach     = cxusb_dtt7579_tuner_attach,
-
-			/* parameter for the MPEG2-data transfer */
-			.stream = {
-				.type = USB_BULK,
-				.count = 5,
-				.endpoint = 0x04,
-				.u = {
-					.bulk = {
-						.buffersize = 8192,
-					}
-				}
-			},
-		}},
-		},
-	},
-	.power_ctrl       = cxusb_bluebird_power_ctrl,
-
-	.i2c_algo         = &cxusb_i2c_algo,
-
-	.rc.legacy = {
-		.rc_interval      = 100,
-		.rc_map_table     = rc_map_dvico_portable_table,
-		.rc_map_size      = ARRAY_SIZE(rc_map_dvico_portable_table),
-		.rc_query         = cxusb_rc_query,
-	},
-
-	.generic_bulk_ctrl_endpoint = 0x01,
-
-	.num_device_descs = 1,
-	.devices = {
-		{   "DViCO FusionHDTV DVB-T USB (TH7579)",
-			{ &cxusb_table[7], NULL },
-			{ &cxusb_table[8], NULL },
-		},
-	}
-};
-
-static struct dvb_usb_device_properties cxusb_bluebird_dualdig4_properties = {
-	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
-
-	.usb_ctrl         = CYPRESS_FX2,
-
-	.size_of_priv     = sizeof(struct cxusb_state),
-
-	.num_adapters = 1,
-	.adapter = {
-		{
-		.num_frontends = 1,
-		.fe = {{
-			.streaming_ctrl   = cxusb_streaming_ctrl,
-			.frontend_attach  = cxusb_dualdig4_frontend_attach,
-			.tuner_attach     = cxusb_dvico_xc3028_tuner_attach,
-			/* parameter for the MPEG2-data transfer */
-			.stream = {
-				.type = USB_BULK,
-				.count = 5,
-				.endpoint = 0x02,
-				.u = {
-					.bulk = {
-						.buffersize = 8192,
-					}
-				}
-			},
-		}},
-		},
-	},
-
-	.power_ctrl       = cxusb_power_ctrl,
-
-	.i2c_algo         = &cxusb_i2c_algo,
-
-	.generic_bulk_ctrl_endpoint = 0x01,
-
-	.rc.legacy = {
-		.rc_interval      = 100,
-		.rc_map_table     = rc_map_dvico_mce_table,
-		.rc_map_size      = ARRAY_SIZE(rc_map_dvico_mce_table),
-		.rc_query         = cxusb_bluebird2_rc_query,
-	},
-
-	.num_device_descs = 1,
-	.devices = {
-		{   "DViCO FusionHDTV DVB-T Dual Digital 4",
-			{ NULL },
-			{ &cxusb_table[13], NULL },
-		},
-	}
-};
-
-static struct dvb_usb_device_properties cxusb_bluebird_nano2_properties = {
-	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
-
-	.usb_ctrl         = CYPRESS_FX2,
-	.identify_state   = bluebird_fx2_identify_state,
-
-	.size_of_priv     = sizeof(struct cxusb_state),
-
-	.num_adapters = 1,
-	.adapter = {
-		{
-		.num_frontends = 1,
-		.fe = {{
-			.streaming_ctrl   = cxusb_streaming_ctrl,
-			.frontend_attach  = cxusb_nano2_frontend_attach,
-			.tuner_attach     = cxusb_dvico_xc3028_tuner_attach,
-			/* parameter for the MPEG2-data transfer */
-			.stream = {
-				.type = USB_BULK,
-				.count = 5,
-				.endpoint = 0x02,
-				.u = {
-					.bulk = {
-						.buffersize = 8192,
-					}
-				}
-			},
-		}},
-		},
-	},
-
-	.power_ctrl       = cxusb_nano2_power_ctrl,
-
-	.i2c_algo         = &cxusb_i2c_algo,
-
-	.generic_bulk_ctrl_endpoint = 0x01,
-
-	.rc.legacy = {
-		.rc_interval      = 100,
-		.rc_map_table     = rc_map_dvico_portable_table,
-		.rc_map_size      = ARRAY_SIZE(rc_map_dvico_portable_table),
-		.rc_query         = cxusb_bluebird2_rc_query,
-	},
-
-	.num_device_descs = 1,
-	.devices = {
-		{   "DViCO FusionHDTV DVB-T NANO2",
-			{ NULL },
-			{ &cxusb_table[14], NULL },
-		},
-	}
-};
-
-static struct dvb_usb_device_properties cxusb_bluebird_nano2_needsfirmware_properties = {
-	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
-
-	.usb_ctrl          = DEVICE_SPECIFIC,
-	.firmware          = "dvb-usb-bluebird-02.fw",
-	.download_firmware = bluebird_patch_dvico_firmware_download,
-	.identify_state    = bluebird_fx2_identify_state,
-
-	.size_of_priv      = sizeof(struct cxusb_state),
-
-	.num_adapters = 1,
-	.adapter = {
-		{
-		.num_frontends = 1,
-		.fe = {{
-			.streaming_ctrl   = cxusb_streaming_ctrl,
-			.frontend_attach  = cxusb_nano2_frontend_attach,
-			.tuner_attach     = cxusb_dvico_xc3028_tuner_attach,
-			/* parameter for the MPEG2-data transfer */
-			.stream = {
-				.type = USB_BULK,
-				.count = 5,
-				.endpoint = 0x02,
-				.u = {
-					.bulk = {
-						.buffersize = 8192,
-					}
-				}
-			},
-		}},
-		},
-	},
-
-	.power_ctrl       = cxusb_nano2_power_ctrl,
-
-	.i2c_algo         = &cxusb_i2c_algo,
-
-	.generic_bulk_ctrl_endpoint = 0x01,
-
-	.rc.legacy = {
-		.rc_interval      = 100,
-		.rc_map_table     = rc_map_dvico_portable_table,
-		.rc_map_size      = ARRAY_SIZE(rc_map_dvico_portable_table),
-		.rc_query         = cxusb_rc_query,
-	},
-
-	.num_device_descs = 1,
-	.devices = {
-		{   "DViCO FusionHDTV DVB-T NANO2 w/o firmware",
-			{ &cxusb_table[14], NULL },
-			{ &cxusb_table[15], NULL },
-		},
-	}
-};
-
-static struct dvb_usb_device_properties cxusb_aver_a868r_properties = {
-	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
-
-	.usb_ctrl         = CYPRESS_FX2,
-
-	.size_of_priv     = sizeof(struct cxusb_state),
-
-	.num_adapters = 1,
-	.adapter = {
-		{
-		.num_frontends = 1,
-		.fe = {{
-			.streaming_ctrl   = cxusb_aver_streaming_ctrl,
-			.frontend_attach  = cxusb_aver_lgdt3303_frontend_attach,
-			.tuner_attach     = cxusb_mxl5003s_tuner_attach,
-			/* parameter for the MPEG2-data transfer */
-			.stream = {
-				.type = USB_BULK,
-				.count = 5,
-				.endpoint = 0x04,
-				.u = {
-					.bulk = {
-						.buffersize = 8192,
-					}
-				}
-			},
-		}},
-		},
-	},
-	.power_ctrl       = cxusb_aver_power_ctrl,
-
-	.i2c_algo         = &cxusb_i2c_algo,
-
-	.generic_bulk_ctrl_endpoint = 0x01,
-
-	.num_device_descs = 1,
-	.devices = {
-		{   "AVerMedia AVerTVHD Volar (A868R)",
-			{ NULL },
-			{ &cxusb_table[16], NULL },
-		},
-	}
-};
-
-static
-struct dvb_usb_device_properties cxusb_bluebird_dualdig4_rev2_properties = {
-	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
-
-	.usb_ctrl         = CYPRESS_FX2,
-
-	.size_of_priv     = sizeof(struct cxusb_state),
-
-	.num_adapters = 1,
-	.adapter = {
-		{
-		.size_of_priv    = sizeof(struct dib0700_adapter_state),
-		.num_frontends = 1,
-		.fe = {{
-			.streaming_ctrl  = cxusb_streaming_ctrl,
-			.frontend_attach = cxusb_dualdig4_rev2_frontend_attach,
-			.tuner_attach    = cxusb_dualdig4_rev2_tuner_attach,
-			/* parameter for the MPEG2-data transfer */
-			.stream = {
-				.type = USB_BULK,
-				.count = 7,
-				.endpoint = 0x02,
-				.u = {
-					.bulk = {
-						.buffersize = 4096,
-					}
-				}
-			},
-		}},
-		},
-	},
-
-	.power_ctrl       = cxusb_bluebird_power_ctrl,
-
-	.i2c_algo         = &cxusb_i2c_algo,
-
-	.generic_bulk_ctrl_endpoint = 0x01,
-
-	.rc.legacy = {
-		.rc_interval      = 100,
-		.rc_map_table     = rc_map_dvico_mce_table,
-		.rc_map_size      = ARRAY_SIZE(rc_map_dvico_mce_table),
-		.rc_query         = cxusb_rc_query,
-	},
-
-	.num_device_descs = 1,
-	.devices = {
-		{   "DViCO FusionHDTV DVB-T Dual Digital 4 (rev 2)",
-			{ NULL },
-			{ &cxusb_table[17], NULL },
-		},
-	}
-};
-
-static struct dvb_usb_device_properties cxusb_d680_dmb_properties = {
-	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
-
-	.usb_ctrl         = CYPRESS_FX2,
-
-	.size_of_priv     = sizeof(struct cxusb_state),
-
-	.num_adapters = 1,
-	.adapter = {
-		{
-		.num_frontends = 1,
-		.fe = {{
-			.streaming_ctrl   = cxusb_d680_dmb_streaming_ctrl,
-			.frontend_attach  = cxusb_d680_dmb_frontend_attach,
-			.tuner_attach     = cxusb_d680_dmb_tuner_attach,
-
-			/* parameter for the MPEG2-data transfer */
-			.stream = {
-				.type = USB_BULK,
-				.count = 5,
-				.endpoint = 0x02,
-				.u = {
-					.bulk = {
-						.buffersize = 8192,
-					}
-				}
-			},
-		}},
-		},
-	},
-
-	.power_ctrl       = cxusb_d680_dmb_power_ctrl,
-
-	.i2c_algo         = &cxusb_i2c_algo,
-
-	.generic_bulk_ctrl_endpoint = 0x01,
-
-	.rc.legacy = {
-		.rc_interval      = 100,
-		.rc_map_table     = rc_map_d680_dmb_table,
-		.rc_map_size      = ARRAY_SIZE(rc_map_d680_dmb_table),
-		.rc_query         = cxusb_d680_dmb_rc_query,
-	},
-
-	.num_device_descs = 1,
-	.devices = {
-		{
-			"Conexant DMB-TH Stick",
-			{ NULL },
-			{ &cxusb_table[18], NULL },
-		},
-	}
-};
-
-static struct dvb_usb_device_properties cxusb_mygica_d689_properties = {
-	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
-
-	.usb_ctrl         = CYPRESS_FX2,
-
-	.size_of_priv     = sizeof(struct cxusb_state),
-
-	.num_adapters = 1,
-	.adapter = {
-		{
-		.num_frontends = 1,
-		.fe = {{
-			.streaming_ctrl   = cxusb_d680_dmb_streaming_ctrl,
-			.frontend_attach  = cxusb_mygica_d689_frontend_attach,
-			.tuner_attach     = cxusb_mygica_d689_tuner_attach,
-
-			/* parameter for the MPEG2-data transfer */
-			.stream = {
-				.type = USB_BULK,
-				.count = 5,
-				.endpoint = 0x02,
-				.u = {
-					.bulk = {
-						.buffersize = 8192,
-					}
-				}
-			},
-		}},
-		},
-	},
-
-	.power_ctrl       = cxusb_d680_dmb_power_ctrl,
-
-	.i2c_algo         = &cxusb_i2c_algo,
-
-	.generic_bulk_ctrl_endpoint = 0x01,
-
-	.rc.legacy = {
-		.rc_interval      = 100,
-		.rc_map_table     = rc_map_d680_dmb_table,
-		.rc_map_size      = ARRAY_SIZE(rc_map_d680_dmb_table),
-		.rc_query         = cxusb_d680_dmb_rc_query,
-	},
-
-	.num_device_descs = 1,
-	.devices = {
-		{
-			"Mygica D689 DMB-TH",
-			{ NULL },
-			{ &cxusb_table[19], NULL },
-		},
-	}
-};
-
-static struct usb_driver cxusb_driver = {
-	.name		= "dvb_usb_cxusb",
-	.probe		= cxusb_probe,
-	.disconnect     = dvb_usb_device_exit,
-	.id_table	= cxusb_table,
-};
-
-module_usb_driver(cxusb_driver);
-
-MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
-MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
-MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>");
-MODULE_DESCRIPTION("Driver for Conexant USB2.0 hybrid reference design");
-MODULE_VERSION("1.0-alpha");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/cxusb.h b/drivers/media/dvb/dvb-usb/cxusb.h
deleted file mode 100644
index 1a51eaf..0000000
--- a/drivers/media/dvb/dvb-usb/cxusb.h
+++ /dev/null
@@ -1,35 +0,0 @@
-#ifndef _DVB_USB_CXUSB_H_
-#define _DVB_USB_CXUSB_H_
-
-#define DVB_USB_LOG_PREFIX "cxusb"
-#include "dvb-usb.h"
-
-/* usb commands - some of it are guesses, don't have a reference yet */
-#define CMD_BLUEBIRD_GPIO_RW 0x05
-
-#define CMD_I2C_WRITE     0x08
-#define CMD_I2C_READ      0x09
-
-#define CMD_GPIO_READ     0x0d
-#define CMD_GPIO_WRITE    0x0e
-#define     GPIO_TUNER         0x02
-
-#define CMD_POWER_OFF     0xdc
-#define CMD_POWER_ON      0xde
-
-#define CMD_STREAMING_ON  0x36
-#define CMD_STREAMING_OFF 0x37
-
-#define CMD_AVER_STREAM_ON  0x18
-#define CMD_AVER_STREAM_OFF 0x19
-
-#define CMD_GET_IR_CODE   0x47
-
-#define CMD_ANALOG        0x50
-#define CMD_DIGITAL       0x51
-
-struct cxusb_state {
-	u8 gpio_write_state[3];
-};
-
-#endif
diff --git a/drivers/media/dvb/dvb-usb/dib0700.h b/drivers/media/dvb/dvb-usb/dib0700.h
deleted file mode 100644
index 7de125c..0000000
--- a/drivers/media/dvb/dvb-usb/dib0700.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/* Linux driver for devices based on the DiBcom DiB0700 USB bridge
- *
- *	This program is free software; 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.
- *
- *  Copyright (C) 2005-6 DiBcom, SA
- */
-#ifndef _DIB0700_H_
-#define _DIB0700_H_
-
-#define DVB_USB_LOG_PREFIX "dib0700"
-#include "dvb-usb.h"
-
-#include "dib07x0.h"
-
-extern int dvb_usb_dib0700_debug;
-#define deb_info(args...)   dprintk(dvb_usb_dib0700_debug,0x01,args)
-#define deb_fw(args...)     dprintk(dvb_usb_dib0700_debug,0x02,args)
-#define deb_fwdata(args...) dprintk(dvb_usb_dib0700_debug,0x04,args)
-#define deb_data(args...)   dprintk(dvb_usb_dib0700_debug,0x08,args)
-
-#define REQUEST_SET_USB_XFER_LEN    0x0 /* valid only for firmware version */
-					/* higher than 1.21 */
-#define REQUEST_I2C_READ            0x2
-#define REQUEST_I2C_WRITE           0x3
-#define REQUEST_POLL_RC             0x4 /* deprecated in firmware v1.20 */
-#define REQUEST_JUMPRAM             0x8
-#define REQUEST_SET_CLOCK           0xB
-#define REQUEST_SET_GPIO            0xC
-#define REQUEST_ENABLE_VIDEO        0xF
-	// 1 Byte: 4MSB(1 = enable streaming, 0 = disable streaming) 4LSB(Video Mode: 0 = MPEG2 188Bytes, 1 = Analog)
-	// 2 Byte: MPEG2 mode:  4MSB(1 = Master Mode, 0 = Slave Mode) 4LSB(Channel 1 = bit0, Channel 2 = bit1)
-	// 2 Byte: Analog mode: 4MSB(0 = 625 lines, 1 = 525 lines)    4LSB(     "                "           )
-#define REQUEST_SET_I2C_PARAM       0x10
-#define REQUEST_SET_RC              0x11
-#define REQUEST_NEW_I2C_READ        0x12
-#define REQUEST_NEW_I2C_WRITE       0x13
-#define REQUEST_GET_VERSION         0x15
-
-struct dib0700_state {
-	u8 channel_state;
-	u16 mt2060_if1[2];
-	u8 rc_toggle;
-	u8 rc_counter;
-	u8 is_dib7000pc;
-	u8 fw_use_new_i2c_api;
-	u8 disable_streaming_master_mode;
-	u32 fw_version;
-	u32 nb_packet_buffer_size;
-	int (*read_status)(struct dvb_frontend *, fe_status_t *);
-	int (*sleep)(struct dvb_frontend* fe);
-	u8 buf[255];
-};
-
-extern int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion,
-			       u32 *romversion, u32 *ramversion, u32 *fwtype);
-extern int dib0700_set_gpio(struct dvb_usb_device *, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val);
-extern int dib0700_ctrl_clock(struct dvb_usb_device *d, u32 clk_MHz, u8 clock_out_gp3);
-extern int dib0700_ctrl_rd(struct dvb_usb_device *d, u8 *tx, u8 txlen, u8 *rx, u8 rxlen);
-extern int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw);
-extern int dib0700_rc_setup(struct dvb_usb_device *d);
-extern int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff);
-extern struct i2c_algorithm dib0700_i2c_algo;
-extern int dib0700_identify_state(struct usb_device *udev, struct dvb_usb_device_properties *props,
-			struct dvb_usb_device_description **desc, int *cold);
-extern int dib0700_change_protocol(struct rc_dev *dev, u64 rc_type);
-extern int dib0700_set_i2c_speed(struct dvb_usb_device *d, u16 scl_kHz);
-
-extern int dib0700_device_count;
-extern int dvb_usb_dib0700_ir_proto;
-extern struct dvb_usb_device_properties dib0700_devices[];
-extern struct usb_device_id dib0700_usb_id_table[];
-
-#endif
diff --git a/drivers/media/dvb/dvb-usb/dib0700_core.c b/drivers/media/dvb/dvb-usb/dib0700_core.c
deleted file mode 100644
index 7e9e00f..0000000
--- a/drivers/media/dvb/dvb-usb/dib0700_core.c
+++ /dev/null
@@ -1,845 +0,0 @@
-/* Linux driver for devices based on the DiBcom DiB0700 USB bridge
- *
- *	This program is free software; 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.
- *
- *  Copyright (C) 2005-6 DiBcom, SA
- */
-#include "dib0700.h"
-
-/* debug */
-int dvb_usb_dib0700_debug;
-module_param_named(debug,dvb_usb_dib0700_debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level (1=info,2=fw,4=fwdata,8=data (or-able))." DVB_USB_DEBUG_STATUS);
-
-static int nb_packet_buffer_size = 21;
-module_param(nb_packet_buffer_size, int, 0644);
-MODULE_PARM_DESC(nb_packet_buffer_size,
-	"Set the dib0700 driver data buffer size. This parameter "
-	"corresponds to the number of TS packets. The actual size of "
-	"the data buffer corresponds to this parameter "
-	"multiplied by 188 (default: 21)");
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-
-int dib0700_get_version(struct dvb_usb_device *d, u32 *hwversion,
-			u32 *romversion, u32 *ramversion, u32 *fwtype)
-{
-	struct dib0700_state *st = d->priv;
-	int ret;
-
-	if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
-		err("could not acquire lock");
-		return -EINTR;
-	}
-
-	ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0),
-				  REQUEST_GET_VERSION,
-				  USB_TYPE_VENDOR | USB_DIR_IN, 0, 0,
-				  st->buf, 16, USB_CTRL_GET_TIMEOUT);
-	if (hwversion != NULL)
-		*hwversion  = (st->buf[0] << 24)  | (st->buf[1] << 16)  |
-			(st->buf[2] << 8)  | st->buf[3];
-	if (romversion != NULL)
-		*romversion = (st->buf[4] << 24)  | (st->buf[5] << 16)  |
-			(st->buf[6] << 8)  | st->buf[7];
-	if (ramversion != NULL)
-		*ramversion = (st->buf[8] << 24)  | (st->buf[9] << 16)  |
-			(st->buf[10] << 8) | st->buf[11];
-	if (fwtype != NULL)
-		*fwtype     = (st->buf[12] << 24) | (st->buf[13] << 16) |
-			(st->buf[14] << 8) | st->buf[15];
-	mutex_unlock(&d->usb_mutex);
-	return ret;
-}
-
-/* expecting rx buffer: request data[0] data[1] ... data[2] */
-static int dib0700_ctrl_wr(struct dvb_usb_device *d, u8 *tx, u8 txlen)
-{
-	int status;
-
-	deb_data(">>> ");
-	debug_dump(tx, txlen, deb_data);
-
-	status = usb_control_msg(d->udev, usb_sndctrlpipe(d->udev,0),
-		tx[0], USB_TYPE_VENDOR | USB_DIR_OUT, 0, 0, tx, txlen,
-		USB_CTRL_GET_TIMEOUT);
-
-	if (status != txlen)
-		deb_data("ep 0 write error (status = %d, len: %d)\n",status,txlen);
-
-	return status < 0 ? status : 0;
-}
-
-/* expecting tx buffer: request data[0] ... data[n] (n <= 4) */
-int dib0700_ctrl_rd(struct dvb_usb_device *d, u8 *tx, u8 txlen, u8 *rx, u8 rxlen)
-{
-	u16 index, value;
-	int status;
-
-	if (txlen < 2) {
-		err("tx buffer length is smaller than 2. Makes no sense.");
-		return -EINVAL;
-	}
-	if (txlen > 4) {
-		err("tx buffer length is larger than 4. Not supported.");
-		return -EINVAL;
-	}
-
-	deb_data(">>> ");
-	debug_dump(tx,txlen,deb_data);
-
-	value = ((txlen - 2) << 8) | tx[1];
-	index = 0;
-	if (txlen > 2)
-		index |= (tx[2] << 8);
-	if (txlen > 3)
-		index |= tx[3];
-
-	status = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev,0), tx[0],
-			USB_TYPE_VENDOR | USB_DIR_IN, value, index, rx, rxlen,
-			USB_CTRL_GET_TIMEOUT);
-
-	if (status < 0)
-		deb_info("ep 0 read error (status = %d)\n",status);
-
-	deb_data("<<< ");
-	debug_dump(rx, rxlen, deb_data);
-
-	return status; /* length in case of success */
-}
-
-int dib0700_set_gpio(struct dvb_usb_device *d, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val)
-{
-	struct dib0700_state *st = d->priv;
-	int ret;
-
-	if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
-		err("could not acquire lock");
-		return -EINTR;
-	}
-
-	st->buf[0] = REQUEST_SET_GPIO;
-	st->buf[1] = gpio;
-	st->buf[2] = ((gpio_dir & 0x01) << 7) | ((gpio_val & 0x01) << 6);
-
-	ret = dib0700_ctrl_wr(d, st->buf, 3);
-
-	mutex_unlock(&d->usb_mutex);
-	return ret;
-}
-
-static int dib0700_set_usb_xfer_len(struct dvb_usb_device *d, u16 nb_ts_packets)
-{
-	struct dib0700_state *st = d->priv;
-	int ret;
-
-	if (st->fw_version >= 0x10201) {
-		if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
-			err("could not acquire lock");
-			return -EINTR;
-		}
-
-		st->buf[0] = REQUEST_SET_USB_XFER_LEN;
-		st->buf[1] = (nb_ts_packets >> 8) & 0xff;
-		st->buf[2] = nb_ts_packets & 0xff;
-
-		deb_info("set the USB xfer len to %i Ts packet\n", nb_ts_packets);
-
-		ret = dib0700_ctrl_wr(d, st->buf, 3);
-		mutex_unlock(&d->usb_mutex);
-	} else {
-		deb_info("this firmware does not allow to change the USB xfer len\n");
-		ret = -EIO;
-	}
-
-	return ret;
-}
-
-/*
- * I2C master xfer function (supported in 1.20 firmware)
- */
-static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg,
-				int num)
-{
-	/* The new i2c firmware messages are more reliable and in particular
-	   properly support i2c read calls not preceded by a write */
-
-	struct dvb_usb_device *d = i2c_get_adapdata(adap);
-	struct dib0700_state *st = d->priv;
-	uint8_t bus_mode = 1;  /* 0=eeprom bus, 1=frontend bus */
-	uint8_t gen_mode = 0; /* 0=master i2c, 1=gpio i2c */
-	uint8_t en_start = 0;
-	uint8_t en_stop = 0;
-	int result, i;
-
-	/* Ensure nobody else hits the i2c bus while we're sending our
-	   sequence of messages, (such as the remote control thread) */
-	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
-		return -EINTR;
-
-	for (i = 0; i < num; i++) {
-		if (i == 0) {
-			/* First message in the transaction */
-			en_start = 1;
-		} else if (!(msg[i].flags & I2C_M_NOSTART)) {
-			/* Device supports repeated-start */
-			en_start = 1;
-		} else {
-			/* Not the first packet and device doesn't support
-			   repeated start */
-			en_start = 0;
-		}
-		if (i == (num - 1)) {
-			/* Last message in the transaction */
-			en_stop = 1;
-		}
-
-		if (msg[i].flags & I2C_M_RD) {
-			/* Read request */
-			u16 index, value;
-			uint8_t i2c_dest;
-
-			i2c_dest = (msg[i].addr << 1);
-			value = ((en_start << 7) | (en_stop << 6) |
-				 (msg[i].len & 0x3F)) << 8 | i2c_dest;
-			/* I2C ctrl + FE bus; */
-			index = ((gen_mode << 6) & 0xC0) |
-				((bus_mode << 4) & 0x30);
-
-			result = usb_control_msg(d->udev,
-						 usb_rcvctrlpipe(d->udev, 0),
-						 REQUEST_NEW_I2C_READ,
-						 USB_TYPE_VENDOR | USB_DIR_IN,
-						 value, index, msg[i].buf,
-						 msg[i].len,
-						 USB_CTRL_GET_TIMEOUT);
-			if (result < 0) {
-				deb_info("i2c read error (status = %d)\n", result);
-				break;
-			}
-
-			deb_data("<<< ");
-			debug_dump(msg[i].buf, msg[i].len, deb_data);
-
-		} else {
-			/* Write request */
-			if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
-				err("could not acquire lock");
-				mutex_unlock(&d->i2c_mutex);
-				return -EINTR;
-			}
-			st->buf[0] = REQUEST_NEW_I2C_WRITE;
-			st->buf[1] = msg[i].addr << 1;
-			st->buf[2] = (en_start << 7) | (en_stop << 6) |
-				(msg[i].len & 0x3F);
-			/* I2C ctrl + FE bus; */
-			st->buf[3] = ((gen_mode << 6) & 0xC0) |
-				 ((bus_mode << 4) & 0x30);
-			/* The Actual i2c payload */
-			memcpy(&st->buf[4], msg[i].buf, msg[i].len);
-
-			deb_data(">>> ");
-			debug_dump(st->buf, msg[i].len + 4, deb_data);
-
-			result = usb_control_msg(d->udev,
-						 usb_sndctrlpipe(d->udev, 0),
-						 REQUEST_NEW_I2C_WRITE,
-						 USB_TYPE_VENDOR | USB_DIR_OUT,
-						 0, 0, st->buf, msg[i].len + 4,
-						 USB_CTRL_GET_TIMEOUT);
-			mutex_unlock(&d->usb_mutex);
-			if (result < 0) {
-				deb_info("i2c write error (status = %d)\n", result);
-				break;
-			}
-		}
-	}
-	mutex_unlock(&d->i2c_mutex);
-	return i;
-}
-
-/*
- * I2C master xfer function (pre-1.20 firmware)
- */
-static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap,
-				   struct i2c_msg *msg, int num)
-{
-	struct dvb_usb_device *d = i2c_get_adapdata(adap);
-	struct dib0700_state *st = d->priv;
-	int i,len;
-
-	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
-		return -EINTR;
-	if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
-		err("could not acquire lock");
-		mutex_unlock(&d->i2c_mutex);
-		return -EINTR;
-	}
-
-	for (i = 0; i < num; i++) {
-		/* fill in the address */
-		st->buf[1] = msg[i].addr << 1;
-		/* fill the buffer */
-		memcpy(&st->buf[2], msg[i].buf, msg[i].len);
-
-		/* write/read request */
-		if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {
-			st->buf[0] = REQUEST_I2C_READ;
-			st->buf[1] |= 1;
-
-			/* special thing in the current firmware: when length is zero the read-failed */
-			len = dib0700_ctrl_rd(d, st->buf, msg[i].len + 2,
-					msg[i+1].buf, msg[i+1].len);
-			if (len <= 0) {
-				deb_info("I2C read failed on address 0x%02x\n",
-						msg[i].addr);
-				break;
-			}
-
-			msg[i+1].len = len;
-
-			i++;
-		} else {
-			st->buf[0] = REQUEST_I2C_WRITE;
-			if (dib0700_ctrl_wr(d, st->buf, msg[i].len + 2) < 0)
-				break;
-		}
-	}
-	mutex_unlock(&d->usb_mutex);
-	mutex_unlock(&d->i2c_mutex);
-
-	return i;
-}
-
-static int dib0700_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msg,
-			    int num)
-{
-	struct dvb_usb_device *d = i2c_get_adapdata(adap);
-	struct dib0700_state *st = d->priv;
-
-	if (st->fw_use_new_i2c_api == 1) {
-		/* User running at least fw 1.20 */
-		return dib0700_i2c_xfer_new(adap, msg, num);
-	} else {
-		/* Use legacy calls */
-		return dib0700_i2c_xfer_legacy(adap, msg, num);
-	}
-}
-
-static u32 dib0700_i2c_func(struct i2c_adapter *adapter)
-{
-	return I2C_FUNC_I2C;
-}
-
-struct i2c_algorithm dib0700_i2c_algo = {
-	.master_xfer   = dib0700_i2c_xfer,
-	.functionality = dib0700_i2c_func,
-};
-
-int dib0700_identify_state(struct usb_device *udev, struct dvb_usb_device_properties *props,
-			struct dvb_usb_device_description **desc, int *cold)
-{
-	s16 ret;
-	u8 *b;
-
-	b = kmalloc(16, GFP_KERNEL);
-	if (!b)
-		return	-ENOMEM;
-
-
-	ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
-		REQUEST_GET_VERSION, USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, b, 16, USB_CTRL_GET_TIMEOUT);
-
-	deb_info("FW GET_VERSION length: %d\n",ret);
-
-	*cold = ret <= 0;
-	deb_info("cold: %d\n", *cold);
-
-	kfree(b);
-	return 0;
-}
-
-static int dib0700_set_clock(struct dvb_usb_device *d, u8 en_pll,
-	u8 pll_src, u8 pll_range, u8 clock_gpio3, u16 pll_prediv,
-	u16 pll_loopdiv, u16 free_div, u16 dsuScaler)
-{
-	struct dib0700_state *st = d->priv;
-	int ret;
-
-	if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
-		err("could not acquire lock");
-		return -EINTR;
-	}
-
-	st->buf[0] = REQUEST_SET_CLOCK;
-	st->buf[1] = (en_pll << 7) | (pll_src << 6) |
-		(pll_range << 5) | (clock_gpio3 << 4);
-	st->buf[2] = (pll_prediv >> 8)  & 0xff; /* MSB */
-	st->buf[3] =  pll_prediv        & 0xff; /* LSB */
-	st->buf[4] = (pll_loopdiv >> 8) & 0xff; /* MSB */
-	st->buf[5] =  pll_loopdiv       & 0xff; /* LSB */
-	st->buf[6] = (free_div >> 8)    & 0xff; /* MSB */
-	st->buf[7] =  free_div          & 0xff; /* LSB */
-	st->buf[8] = (dsuScaler >> 8)   & 0xff; /* MSB */
-	st->buf[9] =  dsuScaler         & 0xff; /* LSB */
-
-	ret = dib0700_ctrl_wr(d, st->buf, 10);
-	mutex_unlock(&d->usb_mutex);
-
-	return ret;
-}
-
-int dib0700_set_i2c_speed(struct dvb_usb_device *d, u16 scl_kHz)
-{
-	struct dib0700_state *st = d->priv;
-	u16 divider;
-	int ret;
-
-	if (scl_kHz == 0)
-		return -EINVAL;
-
-	if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
-		err("could not acquire lock");
-		return -EINTR;
-	}
-
-	st->buf[0] = REQUEST_SET_I2C_PARAM;
-	divider = (u16) (30000 / scl_kHz);
-	st->buf[1] = 0;
-	st->buf[2] = (u8) (divider >> 8);
-	st->buf[3] = (u8) (divider & 0xff);
-	divider = (u16) (72000 / scl_kHz);
-	st->buf[4] = (u8) (divider >> 8);
-	st->buf[5] = (u8) (divider & 0xff);
-	divider = (u16) (72000 / scl_kHz); /* clock: 72MHz */
-	st->buf[6] = (u8) (divider >> 8);
-	st->buf[7] = (u8) (divider & 0xff);
-
-	deb_info("setting I2C speed: %04x %04x %04x (%d kHz).",
-		(st->buf[2] << 8) | (st->buf[3]), (st->buf[4] << 8) |
-		st->buf[5], (st->buf[6] << 8) | st->buf[7], scl_kHz);
-
-	ret = dib0700_ctrl_wr(d, st->buf, 8);
-	mutex_unlock(&d->usb_mutex);
-
-	return ret;
-}
-
-
-int dib0700_ctrl_clock(struct dvb_usb_device *d, u32 clk_MHz, u8 clock_out_gp3)
-{
-	switch (clk_MHz) {
-		case 72: dib0700_set_clock(d, 1, 0, 1, clock_out_gp3, 2, 24, 0, 0x4c); break;
-		default: return -EINVAL;
-	}
-	return 0;
-}
-
-static int dib0700_jumpram(struct usb_device *udev, u32 address)
-{
-	int ret = 0, actlen;
-	u8 *buf;
-
-	buf = kmalloc(8, GFP_KERNEL);
-	if (!buf)
-		return -ENOMEM;
-	buf[0] = REQUEST_JUMPRAM;
-	buf[1] = 0;
-	buf[2] = 0;
-	buf[3] = 0;
-	buf[4] = (address >> 24) & 0xff;
-	buf[5] = (address >> 16) & 0xff;
-	buf[6] = (address >> 8)  & 0xff;
-	buf[7] =  address        & 0xff;
-
-	if ((ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, 0x01),buf,8,&actlen,1000)) < 0) {
-		deb_fw("jumpram to 0x%x failed\n",address);
-		goto out;
-	}
-	if (actlen != 8) {
-		deb_fw("jumpram to 0x%x failed\n",address);
-		ret = -EIO;
-		goto out;
-	}
-out:
-	kfree(buf);
-	return ret;
-}
-
-int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw)
-{
-	struct hexline hx;
-	int pos = 0, ret, act_len, i, adap_num;
-	u8 *buf;
-	u32 fw_version;
-
-	buf = kmalloc(260, GFP_KERNEL);
-	if (!buf)
-		return -ENOMEM;
-
-	while ((ret = dvb_usb_get_hexline(fw, &hx, &pos)) > 0) {
-		deb_fwdata("writing to address 0x%08x (buffer: 0x%02x %02x)\n",
-				hx.addr, hx.len, hx.chk);
-
-		buf[0] = hx.len;
-		buf[1] = (hx.addr >> 8) & 0xff;
-		buf[2] =  hx.addr       & 0xff;
-		buf[3] = hx.type;
-		memcpy(&buf[4],hx.data,hx.len);
-		buf[4+hx.len] = hx.chk;
-
-		ret = usb_bulk_msg(udev,
-			usb_sndbulkpipe(udev, 0x01),
-			buf,
-			hx.len + 5,
-			&act_len,
-			1000);
-
-		if (ret < 0) {
-			err("firmware download failed at %d with %d",pos,ret);
-			goto out;
-		}
-	}
-
-	if (ret == 0) {
-		/* start the firmware */
-		if ((ret = dib0700_jumpram(udev, 0x70000000)) == 0) {
-			info("firmware started successfully.");
-			msleep(500);
-		}
-	} else
-		ret = -EIO;
-
-	/* the number of ts packet has to be at least 1 */
-	if (nb_packet_buffer_size < 1)
-		nb_packet_buffer_size = 1;
-
-	/* get the fimware version */
-	usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
-				  REQUEST_GET_VERSION,
-				  USB_TYPE_VENDOR | USB_DIR_IN, 0, 0,
-				  buf, 16, USB_CTRL_GET_TIMEOUT);
-	fw_version = (buf[8] << 24) | (buf[9] << 16) | (buf[10] << 8) | buf[11];
-
-	/* set the buffer size - DVB-USB is allocating URB buffers
-	 * only after the firwmare download was successful */
-	for (i = 0; i < dib0700_device_count; i++) {
-		for (adap_num = 0; adap_num < dib0700_devices[i].num_adapters;
-				adap_num++) {
-			if (fw_version >= 0x10201) {
-				dib0700_devices[i].adapter[adap_num].fe[0].stream.u.bulk.buffersize = 188*nb_packet_buffer_size;
-			} else {
-				/* for fw version older than 1.20.1,
-				 * the buffersize has to be n times 512 */
-				dib0700_devices[i].adapter[adap_num].fe[0].stream.u.bulk.buffersize = ((188*nb_packet_buffer_size+188/2)/512)*512;
-				if (dib0700_devices[i].adapter[adap_num].fe[0].stream.u.bulk.buffersize < 512)
-					dib0700_devices[i].adapter[adap_num].fe[0].stream.u.bulk.buffersize = 512;
-			}
-		}
-	}
-out:
-	kfree(buf);
-	return ret;
-}
-
-int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
-{
-	struct dib0700_state *st = adap->dev->priv;
-	int ret;
-
-	if ((onoff != 0) && (st->fw_version >= 0x10201)) {
-		/* for firmware later than 1.20.1,
-		 * the USB xfer length can be set  */
-		ret = dib0700_set_usb_xfer_len(adap->dev,
-			st->nb_packet_buffer_size);
-		if (ret < 0) {
-			deb_info("can not set the USB xfer len\n");
-			return ret;
-		}
-	}
-
-	if (mutex_lock_interruptible(&adap->dev->usb_mutex) < 0) {
-		err("could not acquire lock");
-		return -EINTR;
-	}
-
-	st->buf[0] = REQUEST_ENABLE_VIDEO;
-	/* this bit gives a kind of command,
-	 * rather than enabling something or not */
-	st->buf[1] = (onoff << 4) | 0x00;
-
-	if (st->disable_streaming_master_mode == 1)
-		st->buf[2] = 0x00;
-	else
-		st->buf[2] = 0x01 << 4; /* Master mode */
-
-	st->buf[3] = 0x00;
-
-	deb_info("modifying (%d) streaming state for %d\n", onoff, adap->id);
-
-	st->channel_state &= ~0x3;
-	if ((adap->fe_adap[0].stream.props.endpoint != 2)
-			&& (adap->fe_adap[0].stream.props.endpoint != 3)) {
-		deb_info("the endpoint number (%i) is not correct, use the adapter id instead", adap->fe_adap[0].stream.props.endpoint);
-		if (onoff)
-			st->channel_state |=	1 << (adap->id);
-		else
-			st->channel_state |=	1 << ~(adap->id);
-	} else {
-		if (onoff)
-			st->channel_state |=	1 << (adap->fe_adap[0].stream.props.endpoint-2);
-		else
-			st->channel_state |=	1 << (3-adap->fe_adap[0].stream.props.endpoint);
-	}
-
-	st->buf[2] |= st->channel_state;
-
-	deb_info("data for streaming: %x %x\n", st->buf[1], st->buf[2]);
-
-	ret = dib0700_ctrl_wr(adap->dev, st->buf, 4);
-	mutex_unlock(&adap->dev->usb_mutex);
-
-	return ret;
-}
-
-int dib0700_change_protocol(struct rc_dev *rc, u64 rc_type)
-{
-	struct dvb_usb_device *d = rc->priv;
-	struct dib0700_state *st = d->priv;
-	int new_proto, ret;
-
-	if (mutex_lock_interruptible(&d->usb_mutex) < 0) {
-		err("could not acquire lock");
-		return -EINTR;
-	}
-
-	st->buf[0] = REQUEST_SET_RC;
-	st->buf[1] = 0;
-	st->buf[2] = 0;
-
-	/* Set the IR mode */
-	if (rc_type == RC_TYPE_RC5)
-		new_proto = 1;
-	else if (rc_type == RC_TYPE_NEC)
-		new_proto = 0;
-	else if (rc_type == RC_TYPE_RC6) {
-		if (st->fw_version < 0x10200) {
-			ret = -EINVAL;
-			goto out;
-		}
-
-		new_proto = 2;
-	} else {
-		ret = -EINVAL;
-		goto out;
-	}
-
-	st->buf[1] = new_proto;
-
-	ret = dib0700_ctrl_wr(d, st->buf, 3);
-	if (ret < 0) {
-		err("ir protocol setup failed");
-		goto out;
-	}
-
-	d->props.rc.core.protocol = rc_type;
-
-out:
-	mutex_unlock(&d->usb_mutex);
-	return ret;
-}
-
-/* Number of keypresses to ignore before start repeating */
-#define RC_REPEAT_DELAY_V1_20 10
-
-/* This is the structure of the RC response packet starting in firmware 1.20 */
-struct dib0700_rc_response {
-	u8 report_id;
-	u8 data_state;
-	union {
-		u16 system16;
-		struct {
-			u8 not_system;
-			u8 system;
-		};
-	};
-	u8 data;
-	u8 not_data;
-};
-#define RC_MSG_SIZE_V1_20 6
-
-static void dib0700_rc_urb_completion(struct urb *purb)
-{
-	struct dvb_usb_device *d = purb->context;
-	struct dib0700_rc_response *poll_reply;
-	u32 uninitialized_var(keycode);
-	u8 toggle;
-
-	deb_info("%s()\n", __func__);
-	if (d->rc_dev == NULL) {
-		/* This will occur if disable_rc_polling=1 */
-		kfree(purb->transfer_buffer);
-		usb_free_urb(purb);
-		return;
-	}
-
-	poll_reply = purb->transfer_buffer;
-
-	if (purb->status < 0) {
-		deb_info("discontinuing polling\n");
-		kfree(purb->transfer_buffer);
-		usb_free_urb(purb);
-		return;
-	}
-
-	if (purb->actual_length != RC_MSG_SIZE_V1_20) {
-		deb_info("malformed rc msg size=%d\n", purb->actual_length);
-		goto resubmit;
-	}
-
-	deb_data("IR ID = %02X state = %02X System = %02X %02X Cmd = %02X %02X (len %d)\n",
-		 poll_reply->report_id, poll_reply->data_state,
-		 poll_reply->system, poll_reply->not_system,
-		 poll_reply->data, poll_reply->not_data,
-		 purb->actual_length);
-
-	switch (d->props.rc.core.protocol) {
-	case RC_TYPE_NEC:
-		toggle = 0;
-
-		/* NEC protocol sends repeat code as 0 0 0 FF */
-		if ((poll_reply->system == 0x00) && (poll_reply->data == 0x00)
-		    && (poll_reply->not_data == 0xff)) {
-			poll_reply->data_state = 2;
-			break;
-		}
-
-		if ((poll_reply->system ^ poll_reply->not_system) != 0xff) {
-			deb_data("NEC extended protocol\n");
-			/* NEC extended code - 24 bits */
-			keycode = be16_to_cpu(poll_reply->system16) << 8 | poll_reply->data;
-		} else {
-			deb_data("NEC normal protocol\n");
-			/* normal NEC code - 16 bits */
-			keycode = poll_reply->system << 8 | poll_reply->data;
-		}
-
-		break;
-	default:
-		deb_data("RC5 protocol\n");
-		/* RC5 Protocol */
-		toggle = poll_reply->report_id;
-		keycode = poll_reply->system << 8 | poll_reply->data;
-
-		break;
-	}
-
-	if ((poll_reply->data + poll_reply->not_data) != 0xff) {
-		/* Key failed integrity check */
-		err("key failed integrity check: %04x %02x %02x",
-		    poll_reply->system,
-		    poll_reply->data, poll_reply->not_data);
-		goto resubmit;
-	}
-
-	rc_keydown(d->rc_dev, keycode, toggle);
-
-resubmit:
-	/* Clean the buffer before we requeue */
-	memset(purb->transfer_buffer, 0, RC_MSG_SIZE_V1_20);
-
-	/* Requeue URB */
-	usb_submit_urb(purb, GFP_ATOMIC);
-}
-
-int dib0700_rc_setup(struct dvb_usb_device *d)
-{
-	struct dib0700_state *st = d->priv;
-	struct urb *purb;
-	int ret;
-
-	/* Poll-based. Don't initialize bulk mode */
-	if (st->fw_version < 0x10200)
-		return 0;
-
-	/* Starting in firmware 1.20, the RC info is provided on a bulk pipe */
-	purb = usb_alloc_urb(0, GFP_KERNEL);
-	if (purb == NULL) {
-		err("rc usb alloc urb failed\n");
-		return -ENOMEM;
-	}
-
-	purb->transfer_buffer = kzalloc(RC_MSG_SIZE_V1_20, GFP_KERNEL);
-	if (purb->transfer_buffer == NULL) {
-		err("rc kzalloc failed\n");
-		usb_free_urb(purb);
-		return -ENOMEM;
-	}
-
-	purb->status = -EINPROGRESS;
-	usb_fill_bulk_urb(purb, d->udev, usb_rcvbulkpipe(d->udev, 1),
-			  purb->transfer_buffer, RC_MSG_SIZE_V1_20,
-			  dib0700_rc_urb_completion, d);
-
-	ret = usb_submit_urb(purb, GFP_ATOMIC);
-	if (ret) {
-		err("rc submit urb failed\n");
-		kfree(purb->transfer_buffer);
-		usb_free_urb(purb);
-	}
-
-	return ret;
-}
-
-static int dib0700_probe(struct usb_interface *intf,
-		const struct usb_device_id *id)
-{
-	int i;
-	struct dvb_usb_device *dev;
-
-	for (i = 0; i < dib0700_device_count; i++)
-		if (dvb_usb_device_init(intf, &dib0700_devices[i], THIS_MODULE,
-		    &dev, adapter_nr) == 0) {
-			struct dib0700_state *st = dev->priv;
-			u32 hwversion, romversion, fw_version, fwtype;
-
-			dib0700_get_version(dev, &hwversion, &romversion,
-				&fw_version, &fwtype);
-
-			deb_info("Firmware version: %x, %d, 0x%x, %d\n",
-				hwversion, romversion, fw_version, fwtype);
-
-			st->fw_version = fw_version;
-			st->nb_packet_buffer_size = (u32)nb_packet_buffer_size;
-
-			/* Disable polling mode on newer firmwares */
-			if (st->fw_version >= 0x10200)
-				dev->props.rc.core.bulk_mode = true;
-			else
-				dev->props.rc.core.bulk_mode = false;
-
-			dib0700_rc_setup(dev);
-
-			return 0;
-		}
-
-	return -ENODEV;
-}
-
-static struct usb_driver dib0700_driver = {
-	.name       = "dvb_usb_dib0700",
-	.probe      = dib0700_probe,
-	.disconnect = dvb_usb_device_exit,
-	.id_table   = dib0700_usb_id_table,
-};
-
-module_usb_driver(dib0700_driver);
-
-MODULE_FIRMWARE("dvb-usb-dib0700-1.20.fw");
-MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
-MODULE_DESCRIPTION("Driver for devices based on DiBcom DiB0700 - USB bridge");
-MODULE_VERSION("1.0");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c
deleted file mode 100644
index 510001d..0000000
--- a/drivers/media/dvb/dvb-usb/dib0700_devices.c
+++ /dev/null
@@ -1,4813 +0,0 @@
-/* Linux driver for devices based on the DiBcom DiB0700 USB bridge
- *
- *	This program is free software; 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.
- *
- *  Copyright (C) 2005-9 DiBcom, SA et al
- */
-#include "dib0700.h"
-
-#include "dib3000mc.h"
-#include "dib7000m.h"
-#include "dib7000p.h"
-#include "dib8000.h"
-#include "dib9000.h"
-#include "mt2060.h"
-#include "mt2266.h"
-#include "tuner-xc2028.h"
-#include "xc5000.h"
-#include "xc4000.h"
-#include "s5h1411.h"
-#include "dib0070.h"
-#include "dib0090.h"
-#include "lgdt3305.h"
-#include "mxl5007t.h"
-
-static int force_lna_activation;
-module_param(force_lna_activation, int, 0644);
-MODULE_PARM_DESC(force_lna_activation, "force the activation of Low-Noise-Amplifyer(s) (LNA), "
-		"if applicable for the device (default: 0=automatic/off).");
-
-struct dib0700_adapter_state {
-	int (*set_param_save) (struct dvb_frontend *);
-	const struct firmware *frontend_firmware;
-};
-
-/* Hauppauge Nova-T 500 (aka Bristol)
- *  has a LNA on GPIO0 which is enabled by setting 1 */
-static struct mt2060_config bristol_mt2060_config[2] = {
-	{
-		.i2c_address = 0x60,
-		.clock_out   = 3,
-	}, {
-		.i2c_address = 0x61,
-	}
-};
-
-
-static struct dibx000_agc_config bristol_dib3000p_mt2060_agc_config = {
-	.band_caps = BAND_VHF | BAND_UHF,
-	.setup     = (1 << 8) | (5 << 5) | (0 << 4) | (0 << 3) | (0 << 2) | (2 << 0),
-
-	.agc1_max = 42598,
-	.agc1_min = 17694,
-	.agc2_max = 45875,
-	.agc2_min = 0,
-
-	.agc1_pt1 = 0,
-	.agc1_pt2 = 59,
-
-	.agc1_slope1 = 0,
-	.agc1_slope2 = 69,
-
-	.agc2_pt1 = 0,
-	.agc2_pt2 = 59,
-
-	.agc2_slope1 = 111,
-	.agc2_slope2 = 28,
-};
-
-static struct dib3000mc_config bristol_dib3000mc_config[2] = {
-	{	.agc          = &bristol_dib3000p_mt2060_agc_config,
-		.max_time     = 0x196,
-		.ln_adc_level = 0x1cc7,
-		.output_mpeg2_in_188_bytes = 1,
-	},
-	{	.agc          = &bristol_dib3000p_mt2060_agc_config,
-		.max_time     = 0x196,
-		.ln_adc_level = 0x1cc7,
-		.output_mpeg2_in_188_bytes = 1,
-	}
-};
-
-static int bristol_frontend_attach(struct dvb_usb_adapter *adap)
-{
-	struct dib0700_state *st = adap->dev->priv;
-	if (adap->id == 0) {
-		dib0700_set_gpio(adap->dev, GPIO6,  GPIO_OUT, 0); msleep(10);
-		dib0700_set_gpio(adap->dev, GPIO6,  GPIO_OUT, 1); msleep(10);
-		dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); msleep(10);
-		dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); msleep(10);
-
-		if (force_lna_activation)
-			dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
-		else
-			dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 0);
-
-		if (dib3000mc_i2c_enumeration(&adap->dev->i2c_adap, 2, DEFAULT_DIB3000P_I2C_ADDRESS, bristol_dib3000mc_config) != 0) {
-			dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0); msleep(10);
-			return -ENODEV;
-		}
-	}
-	st->mt2060_if1[adap->id] = 1220;
-	return (adap->fe_adap[0].fe = dvb_attach(dib3000mc_attach, &adap->dev->i2c_adap,
-		(10 + adap->id) << 1, &bristol_dib3000mc_config[adap->id])) == NULL ? -ENODEV : 0;
-}
-
-static int eeprom_read(struct i2c_adapter *adap,u8 adrs,u8 *pval)
-{
-	struct i2c_msg msg[2] = {
-		{ .addr = 0x50, .flags = 0,        .buf = &adrs, .len = 1 },
-		{ .addr = 0x50, .flags = I2C_M_RD, .buf = pval,  .len = 1 },
-	};
-	if (i2c_transfer(adap, msg, 2) != 2) return -EREMOTEIO;
-	return 0;
-}
-
-static int bristol_tuner_attach(struct dvb_usb_adapter *adap)
-{
-	struct i2c_adapter *prim_i2c = &adap->dev->i2c_adap;
-	struct i2c_adapter *tun_i2c = dib3000mc_get_tuner_i2c_master(adap->fe_adap[0].fe, 1);
-	s8 a;
-	int if1=1220;
-	if (adap->dev->udev->descriptor.idVendor  == cpu_to_le16(USB_VID_HAUPPAUGE) &&
-		adap->dev->udev->descriptor.idProduct == cpu_to_le16(USB_PID_HAUPPAUGE_NOVA_T_500_2)) {
-		if (!eeprom_read(prim_i2c,0x59 + adap->id,&a)) if1=1220+a;
-	}
-	return dvb_attach(mt2060_attach, adap->fe_adap[0].fe, tun_i2c,
-			  &bristol_mt2060_config[adap->id], if1) == NULL ?
-			  -ENODEV : 0;
-}
-
-/* STK7700D: Pinnacle/Terratec/Hauppauge Dual DVB-T Diversity */
-
-/* MT226x */
-static struct dibx000_agc_config stk7700d_7000p_mt2266_agc_config[2] = {
-	{
-		BAND_UHF,
-
-		/* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=1, P_agc_inv_pwm1=1, P_agc_inv_pwm2=1,
-		* P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=2, P_agc_write=0 */
-		(0 << 15) | (0 << 14) | (1 << 11) | (1 << 10) | (1 << 9) | (0 << 8)
-	    | (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0),
-
-		1130,
-		21,
-
-		0,
-		118,
-
-		0,
-		3530,
-		1,
-		0,
-
-		65535,
-		33770,
-		65535,
-		23592,
-
-		0,
-		62,
-		255,
-		64,
-		64,
-		132,
-		192,
-		80,
-		80,
-
-		17,
-		27,
-		23,
-		51,
-
-		1,
-	}, {
-		BAND_VHF | BAND_LBAND,
-
-		/* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=1, P_agc_inv_pwm1=1, P_agc_inv_pwm2=1,
-		* P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=2, P_agc_write=0 */
-		(0 << 15) | (0 << 14) | (1 << 11) | (1 << 10) | (1 << 9) | (0 << 8)
-	    | (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0),
-
-		2372,
-		21,
-
-		0,
-		118,
-
-		0,
-		3530,
-		1,
-		0,
-
-		65535,
-		0,
-		65535,
-		23592,
-
-		0,
-		128,
-		128,
-		128,
-		0,
-		128,
-		253,
-		81,
-		0,
-
-		17,
-		27,
-		23,
-		51,
-
-		1,
-	}
-};
-
-static struct dibx000_bandwidth_config stk7700d_mt2266_pll_config = {
-	60000, 30000,
-	1, 8, 3, 1, 0,
-	0, 0, 1, 1, 2,
-	(3 << 14) | (1 << 12) | (524 << 0),
-	0,
-	20452225,
-};
-
-static struct dib7000p_config stk7700d_dib7000p_mt2266_config[] = {
-	{	.output_mpeg2_in_188_bytes = 1,
-		.hostbus_diversity = 1,
-		.tuner_is_baseband = 1,
-
-		.agc_config_count = 2,
-		.agc = stk7700d_7000p_mt2266_agc_config,
-		.bw  = &stk7700d_mt2266_pll_config,
-
-		.gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS,
-		.gpio_val = DIB7000P_GPIO_DEFAULT_VALUES,
-		.gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS,
-	},
-	{	.output_mpeg2_in_188_bytes = 1,
-		.hostbus_diversity = 1,
-		.tuner_is_baseband = 1,
-
-		.agc_config_count = 2,
-		.agc = stk7700d_7000p_mt2266_agc_config,
-		.bw  = &stk7700d_mt2266_pll_config,
-
-		.gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS,
-		.gpio_val = DIB7000P_GPIO_DEFAULT_VALUES,
-		.gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS,
-	}
-};
-
-static struct mt2266_config stk7700d_mt2266_config[2] = {
-	{	.i2c_address = 0x60
-	},
-	{	.i2c_address = 0x60
-	}
-};
-
-static int stk7700P2_frontend_attach(struct dvb_usb_adapter *adap)
-{
-	if (adap->id == 0) {
-		dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
-		msleep(10);
-		dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
-		dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1);
-		dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1);
-		dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0);
-		msleep(10);
-		dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
-		msleep(10);
-		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_adap[0].fe =
-		dvb_attach(dib7000p_attach, &adap->dev->i2c_adap,
-			   0x80 + (adap->id << 1),
-			   &stk7700d_dib7000p_mt2266_config[adap->id]);
-
-	return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
-}
-
-static int stk7700d_frontend_attach(struct dvb_usb_adapter *adap)
-{
-	if (adap->id == 0) {
-		dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
-		msleep(10);
-		dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
-		dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1);
-		dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1);
-		dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0);
-		msleep(10);
-		dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
-		msleep(10);
-		dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
-		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_adap[0].fe =
-		dvb_attach(dib7000p_attach, &adap->dev->i2c_adap,
-			   0x80 + (adap->id << 1),
-			   &stk7700d_dib7000p_mt2266_config[adap->id]);
-
-	return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
-}
-
-static int stk7700d_tuner_attach(struct dvb_usb_adapter *adap)
-{
-	struct i2c_adapter *tun_i2c;
-	tun_i2c = dib7000p_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1);
-	return dvb_attach(mt2266_attach, adap->fe_adap[0].fe, tun_i2c,
-		&stk7700d_mt2266_config[adap->id]) == NULL ? -ENODEV : 0;
-}
-
-/* STK7700-PH: Digital/Analog Hybrid Tuner, e.h. Cinergy HT USB HE */
-static struct dibx000_agc_config xc3028_agc_config = {
-	BAND_VHF | BAND_UHF,       /* band_caps */
-
-	/* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=0,
-	 * P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, P_agc_inh_dc_rv_est=0,
-	 * P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=2, P_agc_write=0 */
-	(0 << 15) | (0 << 14) | (0 << 11) | (0 << 10) | (0 << 9) | (0 << 8) |
-	(3 << 5) | (0 << 4) | (2 << 1) | (0 << 0), /* setup */
-
-	712,	/* inv_gain */
-	21,	/* time_stabiliz */
-
-	0,	/* alpha_level */
-	118,	/* thlock */
-
-	0,	/* wbd_inv */
-	2867,	/* wbd_ref */
-	0,	/* wbd_sel */
-	2,	/* wbd_alpha */
-
-	0,	/* agc1_max */
-	0,	/* agc1_min */
-	39718,	/* agc2_max */
-	9930,	/* agc2_min */
-	0,	/* agc1_pt1 */
-	0,	/* agc1_pt2 */
-	0,	/* agc1_pt3 */
-	0,	/* agc1_slope1 */
-	0,	/* agc1_slope2 */
-	0,	/* agc2_pt1 */
-	128,	/* agc2_pt2 */
-	29,	/* agc2_slope1 */
-	29,	/* agc2_slope2 */
-
-	17,	/* alpha_mant */
-	27,	/* alpha_exp */
-	23,	/* beta_mant */
-	51,	/* beta_exp */
-
-	1,	/* perform_agc_softsplit */
-};
-
-/* PLL Configuration for COFDM BW_MHz = 8.00 with external clock = 30.00 */
-static struct dibx000_bandwidth_config xc3028_bw_config = {
-	60000, 30000, /* internal, sampling */
-	1, 8, 3, 1, 0, /* pll_cfg: prediv, ratio, range, reset, bypass */
-	0, 0, 1, 1, 0, /* misc: refdiv, bypclk_div, IO_CLK_en_core, ADClkSrc,
-			  modulo */
-	(3 << 14) | (1 << 12) | (524 << 0), /* sad_cfg: refsel, sel, freq_15k */
-	(1 << 25) | 5816102, /* ifreq = 5.200000 MHz */
-	20452225, /* timf */
-	30000000, /* xtal_hz */
-};
-
-static struct dib7000p_config stk7700ph_dib7700_xc3028_config = {
-	.output_mpeg2_in_188_bytes = 1,
-	.tuner_is_baseband = 1,
-
-	.agc_config_count = 1,
-	.agc = &xc3028_agc_config,
-	.bw  = &xc3028_bw_config,
-
-	.gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS,
-	.gpio_val = DIB7000P_GPIO_DEFAULT_VALUES,
-	.gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS,
-};
-
-static int stk7700ph_xc3028_callback(void *ptr, int component,
-				     int command, int arg)
-{
-	struct dvb_usb_adapter *adap = ptr;
-
-	switch (command) {
-	case XC2028_TUNER_RESET:
-		/* Send the tuner in then out of reset */
-		dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 0); msleep(10);
-		dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
-		break;
-	case XC2028_RESET_CLK:
-		break;
-	default:
-		err("%s: unknown command %d, arg %d\n", __func__,
-			command, arg);
-		return -EINVAL;
-	}
-	return 0;
-}
-
-static struct xc2028_ctrl stk7700ph_xc3028_ctrl = {
-	.fname = XC2028_DEFAULT_FIRMWARE,
-	.max_len = 64,
-	.demod = XC3028_FE_DIBCOM52,
-};
-
-static struct xc2028_config stk7700ph_xc3028_config = {
-	.i2c_addr = 0x61,
-	.ctrl = &stk7700ph_xc3028_ctrl,
-};
-
-static int stk7700ph_frontend_attach(struct dvb_usb_adapter *adap)
-{
-	struct usb_device_descriptor *desc = &adap->dev->udev->descriptor;
-
-	if (desc->idVendor  == cpu_to_le16(USB_VID_PINNACLE) &&
-	    desc->idProduct == cpu_to_le16(USB_PID_PINNACLE_EXPRESSCARD_320CX))
-	dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0);
-	else
-	dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
-	msleep(20);
-	dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
-	dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1);
-	dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1);
-	dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0);
-	msleep(10);
-	dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
-	msleep(20);
-	dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
-	msleep(10);
-
-	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_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
-		&stk7700ph_dib7700_xc3028_config);
-
-	return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
-}
-
-static int stk7700ph_tuner_attach(struct dvb_usb_adapter *adap)
-{
-	struct i2c_adapter *tun_i2c;
-
-	tun_i2c = dib7000p_get_i2c_master(adap->fe_adap[0].fe,
-		DIBX000_I2C_INTERFACE_TUNER, 1);
-
-	stk7700ph_xc3028_config.i2c_adap = tun_i2c;
-
-	/* FIXME: generalize & move to common area */
-	adap->fe_adap[0].fe->callback = stk7700ph_xc3028_callback;
-
-	return dvb_attach(xc2028_attach, adap->fe_adap[0].fe, &stk7700ph_xc3028_config)
-		== NULL ? -ENODEV : 0;
-}
-
-#define DEFAULT_RC_INTERVAL 50
-
-static u8 rc_request[] = { REQUEST_POLL_RC, 0 };
-
-/* Number of keypresses to ignore before start repeating */
-#define RC_REPEAT_DELAY 6
-
-/*
- * This function is used only when firmware is < 1.20 version. Newer
- * firmwares use bulk mode, with functions implemented at dib0700_core,
- * at dib0700_rc_urb_completion()
- */
-static int dib0700_rc_query_old_firmware(struct dvb_usb_device *d)
-{
-	u8 key[4];
-	u32 keycode;
-	u8 toggle;
-	int i;
-	struct dib0700_state *st = d->priv;
-
-	if (st->fw_version >= 0x10200) {
-		/* For 1.20 firmware , We need to keep the RC polling
-		   callback so we can reuse the input device setup in
-		   dvb-usb-remote.c.  However, the actual work is being done
-		   in the bulk URB completion handler. */
-		return 0;
-	}
-
-	i = dib0700_ctrl_rd(d, rc_request, 2, key, 4);
-	if (i <= 0) {
-		err("RC Query Failed");
-		return -1;
-	}
-
-	/* losing half of KEY_0 events from Philipps rc5 remotes.. */
-	if (key[0] == 0 && key[1] == 0 && key[2] == 0 && key[3] == 0)
-		return 0;
-
-	/* info("%d: %2X %2X %2X %2X",dvb_usb_dib0700_ir_proto,(int)key[3-2],(int)key[3-3],(int)key[3-1],(int)key[3]);  */
-
-	dib0700_rc_setup(d); /* reset ir sensor data to prevent false events */
-
-	d->last_event = 0;
-	switch (d->props.rc.core.protocol) {
-	case RC_TYPE_NEC:
-		/* NEC protocol sends repeat code as 0 0 0 FF */
-		if ((key[3-2] == 0x00) && (key[3-3] == 0x00) &&
-		    (key[3] == 0xff))
-			keycode = d->last_event;
-		else {
-			keycode = key[3-2] << 8 | key[3-3];
-			d->last_event = keycode;
-		}
-
-		rc_keydown(d->rc_dev, keycode, 0);
-		break;
-	default:
-		/* RC-5 protocol changes toggle bit on new keypress */
-		keycode = key[3-2] << 8 | key[3-3];
-		toggle = key[3-1];
-		rc_keydown(d->rc_dev, keycode, toggle);
-
-		break;
-	}
-	return 0;
-}
-
-/* STK7700P: Hauppauge Nova-T Stick, AVerMedia Volar */
-static struct dibx000_agc_config stk7700p_7000m_mt2060_agc_config = {
-	BAND_UHF | BAND_VHF,
-
-	/* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=5, P_agc_inv_pwm1=0, P_agc_inv_pwm2=0,
-	 * P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=2, P_agc_write=0 */
-	(0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8)
-	| (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0),
-
-	712,
-	41,
-
-	0,
-	118,
-
-	0,
-	4095,
-	0,
-	0,
-
-	42598,
-	17694,
-	45875,
-	2621,
-	0,
-	76,
-	139,
-	52,
-	59,
-	107,
-	172,
-	57,
-	70,
-
-	21,
-	25,
-	28,
-	48,
-
-	1,
-	{  0,
-	   107,
-	   51800,
-	   24700
-	},
-};
-
-static struct dibx000_agc_config stk7700p_7000p_mt2060_agc_config = {
-	BAND_UHF | BAND_VHF,
-
-	/* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=5, P_agc_inv_pwm1=0, P_agc_inv_pwm2=0,
-	 * P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=2, P_agc_write=0 */
-	(0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8)
-	| (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0),
-
-	712,
-	41,
-
-	0,
-	118,
-
-	0,
-	4095,
-	0,
-	0,
-
-	42598,
-	16384,
-	42598,
-	    0,
-
-	  0,
-	137,
-	255,
-
-	  0,
-	255,
-
-	0,
-	0,
-
-	 0,
-	41,
-
-	15,
-	25,
-
-	28,
-	48,
-
-	0,
-};
-
-static struct dibx000_bandwidth_config stk7700p_pll_config = {
-	60000, 30000,
-	1, 8, 3, 1, 0,
-	0, 0, 1, 1, 0,
-	(3 << 14) | (1 << 12) | (524 << 0),
-	60258167,
-	20452225,
-	30000000,
-};
-
-static struct dib7000m_config stk7700p_dib7000m_config = {
-	.dvbt_mode = 1,
-	.output_mpeg2_in_188_bytes = 1,
-	.quartz_direct = 1,
-
-	.agc_config_count = 1,
-	.agc = &stk7700p_7000m_mt2060_agc_config,
-	.bw  = &stk7700p_pll_config,
-
-	.gpio_dir = DIB7000M_GPIO_DEFAULT_DIRECTIONS,
-	.gpio_val = DIB7000M_GPIO_DEFAULT_VALUES,
-	.gpio_pwm_pos = DIB7000M_GPIO_DEFAULT_PWM_POS,
-};
-
-static struct dib7000p_config stk7700p_dib7000p_config = {
-	.output_mpeg2_in_188_bytes = 1,
-
-	.agc_config_count = 1,
-	.agc = &stk7700p_7000p_mt2060_agc_config,
-	.bw  = &stk7700p_pll_config,
-
-	.gpio_dir = DIB7000M_GPIO_DEFAULT_DIRECTIONS,
-	.gpio_val = DIB7000M_GPIO_DEFAULT_VALUES,
-	.gpio_pwm_pos = DIB7000M_GPIO_DEFAULT_PWM_POS,
-};
-
-static int stk7700p_frontend_attach(struct dvb_usb_adapter *adap)
-{
-	struct dib0700_state *st = adap->dev->priv;
-	/* unless there is no real power management in DVB - we leave the device on GPIO6 */
-
-	dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0);
-	dib0700_set_gpio(adap->dev, GPIO6,  GPIO_OUT, 0); msleep(50);
-
-	dib0700_set_gpio(adap->dev, GPIO6,  GPIO_OUT, 1); msleep(10);
-	dib0700_set_gpio(adap->dev, GPIO9,  GPIO_OUT, 1);
-
-	dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); msleep(10);
-	dib0700_ctrl_clock(adap->dev, 72, 1);
-	dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); msleep(100);
-
-	dib0700_set_gpio(adap->dev,  GPIO0, GPIO_OUT, 1);
-
-	st->mt2060_if1[0] = 1220;
-
-	if (dib7000pc_detection(&adap->dev->i2c_adap)) {
-		adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 18, &stk7700p_dib7000p_config);
-		st->is_dib7000pc = 1;
-	} else
-		adap->fe_adap[0].fe = dvb_attach(dib7000m_attach, &adap->dev->i2c_adap, 18, &stk7700p_dib7000m_config);
-
-	return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
-}
-
-static struct mt2060_config stk7700p_mt2060_config = {
-	0x60
-};
-
-static int stk7700p_tuner_attach(struct dvb_usb_adapter *adap)
-{
-	struct i2c_adapter *prim_i2c = &adap->dev->i2c_adap;
-	struct dib0700_state *st = adap->dev->priv;
-	struct i2c_adapter *tun_i2c;
-	s8 a;
-	int if1=1220;
-	if (adap->dev->udev->descriptor.idVendor  == cpu_to_le16(USB_VID_HAUPPAUGE) &&
-		adap->dev->udev->descriptor.idProduct == cpu_to_le16(USB_PID_HAUPPAUGE_NOVA_T_STICK)) {
-		if (!eeprom_read(prim_i2c,0x58,&a)) if1=1220+a;
-	}
-	if (st->is_dib7000pc)
-		tun_i2c = dib7000p_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1);
-	else
-		tun_i2c = dib7000m_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1);
-
-	return dvb_attach(mt2060_attach, adap->fe_adap[0].fe, tun_i2c, &stk7700p_mt2060_config,
-		if1) == NULL ? -ENODEV : 0;
-}
-
-/* DIB7070 generic */
-static struct dibx000_agc_config dib7070_agc_config = {
-	BAND_UHF | BAND_VHF | BAND_LBAND | BAND_SBAND,
-	/* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=5, P_agc_inv_pwm1=0, P_agc_inv_pwm2=0,
-	 * P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, P_agc_write=0 */
-	(0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8)
-	| (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0),
-
-	600,
-	10,
-
-	0,
-	118,
-
-	0,
-	3530,
-	1,
-	5,
-
-	65535,
-		0,
-
-	65535,
-	0,
-
-	0,
-	40,
-	183,
-	206,
-	255,
-	72,
-	152,
-	88,
-	90,
-
-	17,
-	27,
-	23,
-	51,
-
-	0,
-};
-
-static int dib7070_tuner_reset(struct dvb_frontend *fe, int onoff)
-{
-	deb_info("reset: %d", onoff);
-	return dib7000p_set_gpio(fe, 8, 0, !onoff);
-}
-
-static int dib7070_tuner_sleep(struct dvb_frontend *fe, int onoff)
-{
-	deb_info("sleep: %d", onoff);
-	return dib7000p_set_gpio(fe, 9, 0, onoff);
-}
-
-static struct dib0070_config dib7070p_dib0070_config[2] = {
-	{
-		.i2c_address = DEFAULT_DIB0070_I2C_ADDRESS,
-		.reset = dib7070_tuner_reset,
-		.sleep = dib7070_tuner_sleep,
-		.clock_khz = 12000,
-		.clock_pad_drive = 4,
-		.charge_pump = 2,
-	}, {
-		.i2c_address = DEFAULT_DIB0070_I2C_ADDRESS,
-		.reset = dib7070_tuner_reset,
-		.sleep = dib7070_tuner_sleep,
-		.clock_khz = 12000,
-		.charge_pump = 2,
-	}
-};
-
-static struct dib0070_config dib7770p_dib0070_config = {
-	 .i2c_address = DEFAULT_DIB0070_I2C_ADDRESS,
-	 .reset = dib7070_tuner_reset,
-	 .sleep = dib7070_tuner_sleep,
-	 .clock_khz = 12000,
-	 .clock_pad_drive = 0,
-	 .flip_chip = 1,
-	 .charge_pump = 2,
-};
-
-static int dib7070_set_param_override(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct dvb_usb_adapter *adap = fe->dvb->priv;
-	struct dib0700_adapter_state *state = adap->priv;
-
-	u16 offset;
-	u8 band = BAND_OF_FREQUENCY(p->frequency/1000);
-	switch (band) {
-		case BAND_VHF: offset = 950; break;
-		case BAND_UHF:
-		default: offset = 550; break;
-	}
-	deb_info("WBD for DiB7000P: %d\n", offset + dib0070_wbd_offset(fe));
-	dib7000p_set_wbd_ref(fe, offset + dib0070_wbd_offset(fe));
-	return state->set_param_save(fe);
-}
-
-static int dib7770_set_param_override(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct dvb_usb_adapter *adap = fe->dvb->priv;
-	struct dib0700_adapter_state *state = adap->priv;
-
-	 u16 offset;
-	 u8 band = BAND_OF_FREQUENCY(p->frequency/1000);
-	 switch (band) {
-	 case BAND_VHF:
-		  dib7000p_set_gpio(fe, 0, 0, 1);
-		  offset = 850;
-		  break;
-	 case BAND_UHF:
-	 default:
-		  dib7000p_set_gpio(fe, 0, 0, 0);
-		  offset = 250;
-		  break;
-	 }
-	 deb_info("WBD for DiB7000P: %d\n", offset + dib0070_wbd_offset(fe));
-	 dib7000p_set_wbd_ref(fe, offset + dib0070_wbd_offset(fe));
-	 return state->set_param_save(fe);
-}
-
-static int dib7770p_tuner_attach(struct dvb_usb_adapter *adap)
-{
-	 struct dib0700_adapter_state *st = adap->priv;
-	 struct i2c_adapter *tun_i2c = dib7000p_get_i2c_master(adap->fe_adap[0].fe,
-			 DIBX000_I2C_INTERFACE_TUNER, 1);
-
-	 if (dvb_attach(dib0070_attach, adap->fe_adap[0].fe, tun_i2c,
-			&dib7770p_dib0070_config) == NULL)
-		 return -ENODEV;
-
-	 st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
-	 adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7770_set_param_override;
-	 return 0;
-}
-
-static int dib7070p_tuner_attach(struct dvb_usb_adapter *adap)
-{
-	struct dib0700_adapter_state *st = adap->priv;
-	struct i2c_adapter *tun_i2c = dib7000p_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1);
-
-	if (adap->id == 0) {
-		if (dvb_attach(dib0070_attach, adap->fe_adap[0].fe, tun_i2c, &dib7070p_dib0070_config[0]) == NULL)
-			return -ENODEV;
-	} else {
-		if (dvb_attach(dib0070_attach, adap->fe_adap[0].fe, tun_i2c, &dib7070p_dib0070_config[1]) == NULL)
-			return -ENODEV;
-	}
-
-	st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
-	adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7070_set_param_override;
-	return 0;
-}
-
-static int stk7700p_pid_filter(struct dvb_usb_adapter *adapter, int index,
-		u16 pid, int onoff)
-{
-	struct dib0700_state *st = adapter->dev->priv;
-	if (st->is_dib7000pc)
-		return dib7000p_pid_filter(adapter->fe_adap[0].fe, index, pid, onoff);
-	return dib7000m_pid_filter(adapter->fe_adap[0].fe, index, pid, onoff);
-}
-
-static int stk7700p_pid_filter_ctrl(struct dvb_usb_adapter *adapter, int onoff)
-{
-	struct dib0700_state *st = adapter->dev->priv;
-	if (st->is_dib7000pc)
-		return dib7000p_pid_filter_ctrl(adapter->fe_adap[0].fe, onoff);
-	return dib7000m_pid_filter_ctrl(adapter->fe_adap[0].fe, onoff);
-}
-
-static int stk70x0p_pid_filter(struct dvb_usb_adapter *adapter, int index, u16 pid, int onoff)
-{
-	return dib7000p_pid_filter(adapter->fe_adap[0].fe, index, pid, onoff);
-}
-
-static int stk70x0p_pid_filter_ctrl(struct dvb_usb_adapter *adapter, int onoff)
-{
-	return dib7000p_pid_filter_ctrl(adapter->fe_adap[0].fe, onoff);
-}
-
-static struct dibx000_bandwidth_config dib7070_bw_config_12_mhz = {
-	60000, 15000,
-	1, 20, 3, 1, 0,
-	0, 0, 1, 1, 2,
-	(3 << 14) | (1 << 12) | (524 << 0),
-	(0 << 25) | 0,
-	20452225,
-	12000000,
-};
-
-static struct dib7000p_config dib7070p_dib7000p_config = {
-	.output_mpeg2_in_188_bytes = 1,
-
-	.agc_config_count = 1,
-	.agc = &dib7070_agc_config,
-	.bw  = &dib7070_bw_config_12_mhz,
-	.tuner_is_baseband = 1,
-	.spur_protect = 1,
-
-	.gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS,
-	.gpio_val = DIB7000P_GPIO_DEFAULT_VALUES,
-	.gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS,
-
-	.hostbus_diversity = 1,
-};
-
-/* STK7070P */
-static int stk7070p_frontend_attach(struct dvb_usb_adapter *adap)
-{
-	struct usb_device_descriptor *p = &adap->dev->udev->descriptor;
-	if (p->idVendor  == cpu_to_le16(USB_VID_PINNACLE) &&
-	    p->idProduct == cpu_to_le16(USB_PID_PINNACLE_PCTV72E))
-		dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0);
-	else
-		dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
-	msleep(10);
-	dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
-	dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1);
-	dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1);
-	dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0);
-
-	dib0700_ctrl_clock(adap->dev, 72, 1);
-
-	msleep(10);
-	dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
-	msleep(10);
-	dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
-
-	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_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
-		&dib7070p_dib7000p_config);
-	return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
-}
-
-/* STK7770P */
-static struct dib7000p_config dib7770p_dib7000p_config = {
-	.output_mpeg2_in_188_bytes = 1,
-
-	.agc_config_count = 1,
-	.agc = &dib7070_agc_config,
-	.bw  = &dib7070_bw_config_12_mhz,
-	.tuner_is_baseband = 1,
-	.spur_protect = 1,
-
-	.gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS,
-	.gpio_val = DIB7000P_GPIO_DEFAULT_VALUES,
-	.gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS,
-
-	.hostbus_diversity = 1,
-	.enable_current_mirror = 1,
-	.disable_sample_and_hold = 0,
-};
-
-static int stk7770p_frontend_attach(struct dvb_usb_adapter *adap)
-{
-	struct usb_device_descriptor *p = &adap->dev->udev->descriptor;
-	if (p->idVendor  == cpu_to_le16(USB_VID_PINNACLE) &&
-	    p->idProduct == cpu_to_le16(USB_PID_PINNACLE_PCTV72E))
-		dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0);
-	else
-		dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
-	msleep(10);
-	dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
-	dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1);
-	dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1);
-	dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0);
-
-	dib0700_ctrl_clock(adap->dev, 72, 1);
-
-	msleep(10);
-	dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
-	msleep(10);
-	dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
-
-	if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
-				     &dib7770p_dib7000p_config) != 0) {
-		err("%s: dib7000p_i2c_enumeration failed.  Cannot continue\n",
-		    __func__);
-		return -ENODEV;
-	}
-
-	adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
-		&dib7770p_dib7000p_config);
-	return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
-}
-
-/* DIB807x generic */
-static struct dibx000_agc_config dib807x_agc_config[2] = {
-	{
-		BAND_VHF,
-		/* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0,
-		 * P_agc_freq_pwm_div=1, P_agc_inv_pwm1=0,
-		 * P_agc_inv_pwm2=0,P_agc_inh_dc_rv_est=0,
-		 * P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5,
-		 * P_agc_write=0 */
-		(0 << 15) | (0 << 14) | (7 << 11) | (0 << 10) | (0 << 9) |
-			(0 << 8) | (3 << 5) | (0 << 4) | (5 << 1) |
-			(0 << 0), /* setup*/
-
-		600, /* inv_gain*/
-		10,  /* time_stabiliz*/
-
-		0,  /* alpha_level*/
-		118,  /* thlock*/
-
-		0,     /* wbd_inv*/
-		3530,  /* wbd_ref*/
-		1,     /* wbd_sel*/
-		5,     /* wbd_alpha*/
-
-		65535,  /* agc1_max*/
-		0,  /* agc1_min*/
-
-		65535,  /* agc2_max*/
-		0,      /* agc2_min*/
-
-		0,      /* agc1_pt1*/
-		40,     /* agc1_pt2*/
-		183,    /* agc1_pt3*/
-		206,    /* agc1_slope1*/
-		255,    /* agc1_slope2*/
-		72,     /* agc2_pt1*/
-		152,    /* agc2_pt2*/
-		88,     /* agc2_slope1*/
-		90,     /* agc2_slope2*/
-
-		17,  /* alpha_mant*/
-		27,  /* alpha_exp*/
-		23,  /* beta_mant*/
-		51,  /* beta_exp*/
-
-		0,  /* perform_agc_softsplit*/
-	}, {
-		BAND_UHF,
-		/* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0,
-		 * P_agc_freq_pwm_div=1, P_agc_inv_pwm1=0,
-		 * P_agc_inv_pwm2=0, P_agc_inh_dc_rv_est=0,
-		 * P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5,
-		 * P_agc_write=0 */
-		(0 << 15) | (0 << 14) | (1 << 11) | (0 << 10) | (0 << 9) |
-			(0 << 8) | (3 << 5) | (0 << 4) | (5 << 1) |
-			(0 << 0), /* setup */
-
-		600, /* inv_gain*/
-		10,  /* time_stabiliz*/
-
-		0,  /* alpha_level*/
-		118,  /* thlock*/
-
-		0,     /* wbd_inv*/
-		3530,  /* wbd_ref*/
-		1,     /* wbd_sel*/
-		5,     /* wbd_alpha*/
-
-		65535,  /* agc1_max*/
-		0,  /* agc1_min*/
-
-		65535,  /* agc2_max*/
-		0,      /* agc2_min*/
-
-		0,      /* agc1_pt1*/
-		40,     /* agc1_pt2*/
-		183,    /* agc1_pt3*/
-		206,    /* agc1_slope1*/
-		255,    /* agc1_slope2*/
-		72,     /* agc2_pt1*/
-		152,    /* agc2_pt2*/
-		88,     /* agc2_slope1*/
-		90,     /* agc2_slope2*/
-
-		17,  /* alpha_mant*/
-		27,  /* alpha_exp*/
-		23,  /* beta_mant*/
-		51,  /* beta_exp*/
-
-		0,  /* perform_agc_softsplit*/
-	}
-};
-
-static struct dibx000_bandwidth_config dib807x_bw_config_12_mhz = {
-	60000, 15000, /* internal, sampling*/
-	1, 20, 3, 1, 0, /* pll_cfg: prediv, ratio, range, reset, bypass*/
-	0, 0, 1, 1, 2, /* misc: refdiv, bypclk_div, IO_CLK_en_core,
-			  ADClkSrc, modulo */
-	(3 << 14) | (1 << 12) | (599 << 0), /* sad_cfg: refsel, sel, freq_15k*/
-	(0 << 25) | 0, /* ifreq = 0.000000 MHz*/
-	18179755, /* timf*/
-	12000000, /* xtal_hz*/
-};
-
-static struct dib8000_config dib807x_dib8000_config[2] = {
-	{
-		.output_mpeg2_in_188_bytes = 1,
-
-		.agc_config_count = 2,
-		.agc = dib807x_agc_config,
-		.pll = &dib807x_bw_config_12_mhz,
-		.tuner_is_baseband = 1,
-
-		.gpio_dir = DIB8000_GPIO_DEFAULT_DIRECTIONS,
-		.gpio_val = DIB8000_GPIO_DEFAULT_VALUES,
-		.gpio_pwm_pos = DIB8000_GPIO_DEFAULT_PWM_POS,
-
-		.hostbus_diversity = 1,
-		.div_cfg = 1,
-		.agc_control = &dib0070_ctrl_agc_filter,
-		.output_mode = OUTMODE_MPEG2_FIFO,
-		.drives = 0x2d98,
-	}, {
-		.output_mpeg2_in_188_bytes = 1,
-
-		.agc_config_count = 2,
-		.agc = dib807x_agc_config,
-		.pll = &dib807x_bw_config_12_mhz,
-		.tuner_is_baseband = 1,
-
-		.gpio_dir = DIB8000_GPIO_DEFAULT_DIRECTIONS,
-		.gpio_val = DIB8000_GPIO_DEFAULT_VALUES,
-		.gpio_pwm_pos = DIB8000_GPIO_DEFAULT_PWM_POS,
-
-		.hostbus_diversity = 1,
-		.agc_control = &dib0070_ctrl_agc_filter,
-		.output_mode = OUTMODE_MPEG2_FIFO,
-		.drives = 0x2d98,
-	}
-};
-
-static int dib80xx_tuner_reset(struct dvb_frontend *fe, int onoff)
-{
-	return dib8000_set_gpio(fe, 5, 0, !onoff);
-}
-
-static int dib80xx_tuner_sleep(struct dvb_frontend *fe, int onoff)
-{
-	return dib8000_set_gpio(fe, 0, 0, onoff);
-}
-
-static const struct dib0070_wbd_gain_cfg dib8070_wbd_gain_cfg[] = {
-    { 240,      7},
-    { 0xffff,   6},
-};
-
-static struct dib0070_config dib807x_dib0070_config[2] = {
-	{
-		.i2c_address = DEFAULT_DIB0070_I2C_ADDRESS,
-		.reset = dib80xx_tuner_reset,
-		.sleep = dib80xx_tuner_sleep,
-		.clock_khz = 12000,
-		.clock_pad_drive = 4,
-		.vga_filter = 1,
-		.force_crystal_mode = 1,
-		.enable_third_order_filter = 1,
-		.charge_pump = 0,
-		.wbd_gain = dib8070_wbd_gain_cfg,
-		.osc_buffer_state = 0,
-		.freq_offset_khz_uhf = -100,
-		.freq_offset_khz_vhf = -100,
-	}, {
-		.i2c_address = DEFAULT_DIB0070_I2C_ADDRESS,
-		.reset = dib80xx_tuner_reset,
-		.sleep = dib80xx_tuner_sleep,
-		.clock_khz = 12000,
-		.clock_pad_drive = 2,
-		.vga_filter = 1,
-		.force_crystal_mode = 1,
-		.enable_third_order_filter = 1,
-		.charge_pump = 0,
-		.wbd_gain = dib8070_wbd_gain_cfg,
-		.osc_buffer_state = 0,
-		.freq_offset_khz_uhf = -25,
-		.freq_offset_khz_vhf = -25,
-	}
-};
-
-static int dib807x_set_param_override(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct dvb_usb_adapter *adap = fe->dvb->priv;
-	struct dib0700_adapter_state *state = adap->priv;
-
-	u16 offset = dib0070_wbd_offset(fe);
-	u8 band = BAND_OF_FREQUENCY(p->frequency/1000);
-	switch (band) {
-	case BAND_VHF:
-		offset += 750;
-		break;
-	case BAND_UHF:  /* fall-thru wanted */
-	default:
-		offset += 250; break;
-	}
-	deb_info("WBD for DiB8000: %d\n", offset);
-	dib8000_set_wbd_ref(fe, offset);
-
-	return state->set_param_save(fe);
-}
-
-static int dib807x_tuner_attach(struct dvb_usb_adapter *adap)
-{
-	struct dib0700_adapter_state *st = adap->priv;
-	struct i2c_adapter *tun_i2c = dib8000_get_i2c_master(adap->fe_adap[0].fe,
-			DIBX000_I2C_INTERFACE_TUNER, 1);
-
-	if (adap->id == 0) {
-		if (dvb_attach(dib0070_attach, adap->fe_adap[0].fe, tun_i2c,
-				&dib807x_dib0070_config[0]) == NULL)
-			return -ENODEV;
-	} else {
-		if (dvb_attach(dib0070_attach, adap->fe_adap[0].fe, tun_i2c,
-				&dib807x_dib0070_config[1]) == NULL)
-			return -ENODEV;
-	}
-
-	st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
-	adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib807x_set_param_override;
-	return 0;
-}
-
-static int stk80xx_pid_filter(struct dvb_usb_adapter *adapter, int index,
-	u16 pid, int onoff)
-{
-	return dib8000_pid_filter(adapter->fe_adap[0].fe, index, pid, onoff);
-}
-
-static int stk80xx_pid_filter_ctrl(struct dvb_usb_adapter *adapter,
-		int onoff)
-{
-	return dib8000_pid_filter_ctrl(adapter->fe_adap[0].fe, onoff);
-}
-
-/* STK807x */
-static int stk807x_frontend_attach(struct dvb_usb_adapter *adap)
-{
-	dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
-	msleep(10);
-	dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
-	dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1);
-	dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1);
-
-	dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0);
-
-	dib0700_ctrl_clock(adap->dev, 72, 1);
-
-	msleep(10);
-	dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
-	msleep(10);
-	dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
-
-	dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
-				0x80, 0);
-
-	adap->fe_adap[0].fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80,
-			      &dib807x_dib8000_config[0]);
-
-	return adap->fe_adap[0].fe == NULL ?  -ENODEV : 0;
-}
-
-/* STK807xPVR */
-static int stk807xpvr_frontend_attach0(struct dvb_usb_adapter *adap)
-{
-	dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0);
-	msleep(30);
-	dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
-	msleep(500);
-	dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
-	dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1);
-	dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1);
-
-	dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0);
-
-	dib0700_ctrl_clock(adap->dev, 72, 1);
-
-	msleep(10);
-	dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
-	msleep(10);
-	dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
-
-	/* initialize IC 0 */
-	dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x22, 0x80, 0);
-
-	adap->fe_adap[0].fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80,
-			      &dib807x_dib8000_config[0]);
-
-	return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
-}
-
-static int stk807xpvr_frontend_attach1(struct dvb_usb_adapter *adap)
-{
-	/* initialize IC 1 */
-	dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x12, 0x82, 0);
-
-	adap->fe_adap[0].fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x82,
-			      &dib807x_dib8000_config[1]);
-
-	return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
-}
-
-/* STK8096GP */
-static struct dibx000_agc_config dib8090_agc_config[2] = {
-	{
-	BAND_UHF | BAND_VHF | BAND_LBAND | BAND_SBAND,
-	/* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=1,
-	 * P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, P_agc_inh_dc_rv_est=0,
-	 * P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, P_agc_write=0 */
-	(0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8)
-	| (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0),
-
-	787,
-	10,
-
-	0,
-	118,
-
-	0,
-	3530,
-	1,
-	5,
-
-	65535,
-	0,
-
-	65535,
-	0,
-
-	0,
-	32,
-	114,
-	143,
-	144,
-	114,
-	227,
-	116,
-	117,
-
-	28,
-	26,
-	31,
-	51,
-
-	0,
-	},
-	{
-	BAND_CBAND,
-	/* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=1,
-	 * P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, P_agc_inh_dc_rv_est=0,
-	 * P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, P_agc_write=0 */
-	(0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8)
-	| (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0),
-
-	787,
-	10,
-
-	0,
-	118,
-
-	0,
-	3530,
-	1,
-	5,
-
-	0,
-	0,
-
-	65535,
-	0,
-
-	0,
-	32,
-	114,
-	143,
-	144,
-	114,
-	227,
-	116,
-	117,
-
-	28,
-	26,
-	31,
-	51,
-
-	0,
-	}
-};
-
-static struct dibx000_bandwidth_config dib8090_pll_config_12mhz = {
-	54000, 13500,
-	1, 18, 3, 1, 0,
-	0, 0, 1, 1, 2,
-	(3 << 14) | (1 << 12) | (599 << 0),
-	(0 << 25) | 0,
-	20199727,
-	12000000,
-};
-
-static int dib8090_get_adc_power(struct dvb_frontend *fe)
-{
-	return dib8000_get_adc_power(fe, 1);
-}
-
-static struct dib8000_config dib809x_dib8000_config[2] = {
-	{
-	.output_mpeg2_in_188_bytes = 1,
-
-	.agc_config_count = 2,
-	.agc = dib8090_agc_config,
-	.agc_control = dib0090_dcc_freq,
-	.pll = &dib8090_pll_config_12mhz,
-	.tuner_is_baseband = 1,
-
-	.gpio_dir = DIB8000_GPIO_DEFAULT_DIRECTIONS,
-	.gpio_val = DIB8000_GPIO_DEFAULT_VALUES,
-	.gpio_pwm_pos = DIB8000_GPIO_DEFAULT_PWM_POS,
-
-	.hostbus_diversity = 1,
-	.div_cfg = 0x31,
-	.output_mode = OUTMODE_MPEG2_FIFO,
-	.drives = 0x2d98,
-	.diversity_delay = 48,
-	.refclksel = 3,
-	}, {
-	.output_mpeg2_in_188_bytes = 1,
-
-	.agc_config_count = 2,
-	.agc = dib8090_agc_config,
-	.agc_control = dib0090_dcc_freq,
-	.pll = &dib8090_pll_config_12mhz,
-	.tuner_is_baseband = 1,
-
-	.gpio_dir = DIB8000_GPIO_DEFAULT_DIRECTIONS,
-	.gpio_val = DIB8000_GPIO_DEFAULT_VALUES,
-	.gpio_pwm_pos = DIB8000_GPIO_DEFAULT_PWM_POS,
-
-	.hostbus_diversity = 1,
-	.div_cfg = 0x31,
-	.output_mode = OUTMODE_DIVERSITY,
-	.drives = 0x2d08,
-	.diversity_delay = 1,
-	.refclksel = 3,
-	}
-};
-
-static struct dib0090_wbd_slope dib8090_wbd_table[] = {
-	/* max freq ; cold slope ; cold offset ; warm slope ; warm offset ; wbd gain */
-	{ 120,     0, 500,  0,   500, 4 }, /* CBAND */
-	{ 170,     0, 450,  0,   450, 4 }, /* CBAND */
-	{ 380,    48, 373, 28,   259, 6 }, /* VHF */
-	{ 860,    34, 700, 36,   616, 6 }, /* high UHF */
-	{ 0xFFFF, 34, 700, 36,   616, 6 }, /* default */
-};
-
-static struct dib0090_config dib809x_dib0090_config = {
-	.io.pll_bypass = 1,
-	.io.pll_range = 1,
-	.io.pll_prediv = 1,
-	.io.pll_loopdiv = 20,
-	.io.adc_clock_ratio = 8,
-	.io.pll_int_loop_filt = 0,
-	.io.clock_khz = 12000,
-	.reset = dib80xx_tuner_reset,
-	.sleep = dib80xx_tuner_sleep,
-	.clkouttobamse = 1,
-	.analog_output = 1,
-	.i2c_address = DEFAULT_DIB0090_I2C_ADDRESS,
-	.use_pwm_agc = 1,
-	.clkoutdrive = 1,
-	.get_adc_power = dib8090_get_adc_power,
-	.freq_offset_khz_uhf = -63,
-	.freq_offset_khz_vhf = -143,
-	.wbd = dib8090_wbd_table,
-	.fref_clock_ratio = 6,
-};
-
-static int dib8096_set_param_override(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct dvb_usb_adapter *adap = fe->dvb->priv;
-	struct dib0700_adapter_state *state = adap->priv;
-	u8 band = BAND_OF_FREQUENCY(p->frequency/1000);
-	u16 target;
-	int ret = 0;
-	enum frontend_tune_state tune_state = CT_SHUTDOWN;
-	u16 ltgain, rf_gain_limit;
-
-	ret = state->set_param_save(fe);
-	if (ret < 0)
-		return ret;
-
-	target = (dib0090_get_wbd_target(fe) * 8 * 18 / 33 + 1) / 2;
-	dib8000_set_wbd_ref(fe, target);
-
-
-	if (band == BAND_CBAND) {
-		deb_info("tuning in CBAND - soft-AGC startup\n");
-		dib0090_set_tune_state(fe, CT_AGC_START);
-		do {
-			ret = dib0090_gain_control(fe);
-			msleep(ret);
-			tune_state = dib0090_get_tune_state(fe);
-			if (tune_state == CT_AGC_STEP_0)
-				dib8000_set_gpio(fe, 6, 0, 1);
-			else if (tune_state == CT_AGC_STEP_1) {
-				dib0090_get_current_gain(fe, NULL, NULL, &rf_gain_limit, &ltgain);
-				if (rf_gain_limit == 0)
-					dib8000_set_gpio(fe, 6, 0, 0);
-			}
-		} while (tune_state < CT_AGC_STOP);
-		dib0090_pwm_gain_reset(fe);
-		dib8000_pwm_agc_reset(fe);
-		dib8000_set_tune_state(fe, CT_DEMOD_START);
-	} else {
-		deb_info("not tuning in CBAND - standard AGC startup\n");
-		dib0090_pwm_gain_reset(fe);
-	}
-
-	return 0;
-}
-
-static int dib809x_tuner_attach(struct dvb_usb_adapter *adap)
-{
-	struct dib0700_adapter_state *st = adap->priv;
-	struct i2c_adapter *tun_i2c = dib8000_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1);
-
-	if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, &dib809x_dib0090_config) == NULL)
-		return -ENODEV;
-
-	st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
-	adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib8096_set_param_override;
-	return 0;
-}
-
-static int stk809x_frontend_attach(struct dvb_usb_adapter *adap)
-{
-	dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
-	msleep(10);
-	dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
-	dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1);
-	dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1);
-
-	dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0);
-
-	dib0700_ctrl_clock(adap->dev, 72, 1);
-
-	msleep(10);
-	dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
-	msleep(10);
-	dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
-
-	dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 18, 0x80, 0);
-
-	adap->fe_adap[0].fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80, &dib809x_dib8000_config[0]);
-
-	return adap->fe_adap[0].fe == NULL ?  -ENODEV : 0;
-}
-
-static int nim8096md_tuner_attach(struct dvb_usb_adapter *adap)
-{
-	struct dib0700_adapter_state *st = adap->priv;
-	struct i2c_adapter *tun_i2c;
-	struct dvb_frontend *fe_slave  = dib8000_get_slave_frontend(adap->fe_adap[0].fe, 1);
-
-	if (fe_slave) {
-		tun_i2c = dib8000_get_i2c_master(fe_slave, DIBX000_I2C_INTERFACE_TUNER, 1);
-		if (dvb_attach(dib0090_register, fe_slave, tun_i2c, &dib809x_dib0090_config) == NULL)
-			return -ENODEV;
-		fe_slave->dvb = adap->fe_adap[0].fe->dvb;
-		fe_slave->ops.tuner_ops.set_params = dib8096_set_param_override;
-	}
-	tun_i2c = dib8000_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1);
-	if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, &dib809x_dib0090_config) == NULL)
-		return -ENODEV;
-
-	st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
-	adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib8096_set_param_override;
-
-	return 0;
-}
-
-static int nim8096md_frontend_attach(struct dvb_usb_adapter *adap)
-{
-	struct dvb_frontend *fe_slave;
-
-	dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0);
-	msleep(20);
-	dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
-	msleep(1000);
-	dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
-	dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1);
-	dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1);
-
-	dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0);
-
-	dib0700_ctrl_clock(adap->dev, 72, 1);
-
-	msleep(20);
-	dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
-	msleep(20);
-	dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
-
-	dib8000_i2c_enumeration(&adap->dev->i2c_adap, 2, 18, 0x80, 0);
-
-	adap->fe_adap[0].fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80, &dib809x_dib8000_config[0]);
-	if (adap->fe_adap[0].fe == NULL)
-		return -ENODEV;
-
-	fe_slave = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x82, &dib809x_dib8000_config[1]);
-	dib8000_set_slave_frontend(adap->fe_adap[0].fe, fe_slave);
-
-	return fe_slave == NULL ?  -ENODEV : 0;
-}
-
-/* TFE8096P */
-static struct dibx000_agc_config dib8096p_agc_config[2] = {
-	{
-		.band_caps		= BAND_UHF,
-		/* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0,
-		   P_agc_freq_pwm_div=1, P_agc_inv_pwm1=0,
-		   P_agc_inv_pwm2=0, P_agc_inh_dc_rv_est=0,
-		   P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5,
-		   P_agc_write=0 */
-		.setup			= (0 << 15) | (0 << 14) | (5 << 11)
-			| (0 << 10) | (0 << 9) | (0 << 8) | (3 << 5)
-			| (0 << 4) | (5 << 1) | (0 << 0),
-
-		.inv_gain		= 684,
-		.time_stabiliz	= 10,
-
-		.alpha_level	= 0,
-		.thlock			= 118,
-
-		.wbd_inv		= 0,
-		.wbd_ref		= 1200,
-		.wbd_sel		= 3,
-		.wbd_alpha		= 5,
-
-		.agc1_max		= 65535,
-		.agc1_min		= 0,
-
-		.agc2_max		= 32767,
-		.agc2_min		= 0,
-
-		.agc1_pt1		= 0,
-		.agc1_pt2		= 0,
-		.agc1_pt3		= 105,
-		.agc1_slope1	= 0,
-		.agc1_slope2	= 156,
-		.agc2_pt1		= 105,
-		.agc2_pt2		= 255,
-		.agc2_slope1	= 54,
-		.agc2_slope2	= 0,
-
-		.alpha_mant		= 28,
-		.alpha_exp		= 26,
-		.beta_mant		= 31,
-		.beta_exp		= 51,
-
-		.perform_agc_softsplit = 0,
-	} , {
-		.band_caps		= BAND_FM | BAND_VHF | BAND_CBAND,
-		/* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0,
-		   P_agc_freq_pwm_div=1, P_agc_inv_pwm1=0,
-		   P_agc_inv_pwm2=0, P_agc_inh_dc_rv_est=0,
-		   P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5,
-		   P_agc_write=0 */
-		.setup			= (0 << 15) | (0 << 14) | (5 << 11)
-			| (0 << 10) | (0 << 9) | (0 << 8) | (3 << 5)
-			| (0 << 4) | (5 << 1) | (0 << 0),
-
-		.inv_gain		= 732,
-		.time_stabiliz  = 10,
-
-		.alpha_level	= 0,
-		.thlock			= 118,
-
-		.wbd_inv		= 0,
-		.wbd_ref		= 1200,
-		.wbd_sel		= 3,
-		.wbd_alpha		= 5,
-
-		.agc1_max		= 65535,
-		.agc1_min		= 0,
-
-		.agc2_max		= 32767,
-		.agc2_min		= 0,
-
-		.agc1_pt1		= 0,
-		.agc1_pt2		= 0,
-		.agc1_pt3		= 98,
-		.agc1_slope1	= 0,
-		.agc1_slope2	= 167,
-		.agc2_pt1		= 98,
-		.agc2_pt2		= 255,
-		.agc2_slope1	= 52,
-		.agc2_slope2	= 0,
-
-		.alpha_mant		= 28,
-		.alpha_exp		= 26,
-		.beta_mant		= 31,
-		.beta_exp		= 51,
-
-		.perform_agc_softsplit = 0,
-	}
-};
-
-static struct dibx000_bandwidth_config dib8096p_clock_config_12_mhz = {
-	108000, 13500,
-	1, 9, 1, 0, 0,
-	0, 0, 0, 0, 2,
-	(3 << 14) | (1 << 12) | (524 << 0),
-	(0 << 25) | 0,
-	20199729,
-	12000000,
-};
-
-static struct dib8000_config tfe8096p_dib8000_config = {
-	.output_mpeg2_in_188_bytes	= 1,
-	.hostbus_diversity			= 1,
-	.update_lna					= NULL,
-
-	.agc_config_count			= 2,
-	.agc						= dib8096p_agc_config,
-	.pll						= &dib8096p_clock_config_12_mhz,
-
-	.gpio_dir					= DIB8000_GPIO_DEFAULT_DIRECTIONS,
-	.gpio_val					= DIB8000_GPIO_DEFAULT_VALUES,
-	.gpio_pwm_pos				= DIB8000_GPIO_DEFAULT_PWM_POS,
-
-	.agc_control				= NULL,
-	.diversity_delay			= 48,
-	.output_mode				= OUTMODE_MPEG2_FIFO,
-	.enMpegOutput				= 1,
-};
-
-static struct dib0090_wbd_slope dib8096p_wbd_table[] = {
-	{ 380, 81, 850, 64, 540, 4},
-	{ 860, 51, 866, 21, 375, 4},
-	{1700, 0, 250, 0, 100, 6},
-	{2600, 0, 250, 0, 100, 6},
-	{ 0xFFFF, 0, 0, 0, 0, 0},
-};
-
-static const struct dib0090_config tfe8096p_dib0090_config = {
-	.io.clock_khz			= 12000,
-	.io.pll_bypass			= 0,
-	.io.pll_range			= 0,
-	.io.pll_prediv			= 3,
-	.io.pll_loopdiv			= 6,
-	.io.adc_clock_ratio		= 0,
-	.io.pll_int_loop_filt	= 0,
-	.reset					= dib8096p_tuner_sleep,
-	.sleep					= dib8096p_tuner_sleep,
-
-	.freq_offset_khz_uhf	= -143,
-	.freq_offset_khz_vhf	= -143,
-
-	.get_adc_power			= dib8090_get_adc_power,
-
-	.clkouttobamse			= 1,
-	.analog_output			= 0,
-
-	.wbd_vhf_offset			= 0,
-	.wbd_cband_offset		= 0,
-	.use_pwm_agc			= 1,
-	.clkoutdrive			= 0,
-
-	.fref_clock_ratio		= 1,
-
-	.wbd					= dib8096p_wbd_table,
-
-	.ls_cfg_pad_drv			= 0,
-	.data_tx_drv			= 0,
-	.low_if					= NULL,
-	.in_soc					= 1,
-	.force_cband_input		= 0,
-};
-
-struct dibx090p_adc {
-	u32 freq;			/* RF freq MHz */
-	u32 timf;			/* New Timf */
-	u32 pll_loopdiv;	/* New prediv */
-	u32 pll_prediv;		/* New loopdiv */
-};
-
-struct dibx090p_adc dib8090p_adc_tab[] = {
-	{ 50000, 17043521, 16, 3}, /* 64 MHz */
-	{878000, 20199729, 9, 1}, /* 60 MHz */
-	{0xffffffff, 0, 0, 0}, /* 60 MHz */
-};
-
-static int dib8096p_agc_startup(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct dvb_usb_adapter *adap = fe->dvb->priv;
-	struct dib0700_adapter_state *state = adap->priv;
-	struct dibx000_bandwidth_config pll;
-	u16 target;
-	int better_sampling_freq = 0, ret;
-	struct dibx090p_adc *adc_table = &dib8090p_adc_tab[0];
-
-	ret = state->set_param_save(fe);
-	if (ret < 0)
-		return ret;
-	memset(&pll, 0, sizeof(struct dibx000_bandwidth_config));
-
-	dib0090_pwm_gain_reset(fe);
-	/* dib0090_get_wbd_target is returning any possible
-	   temperature compensated wbd-target */
-	target = (dib0090_get_wbd_target(fe) * 8  + 1) / 2;
-	dib8000_set_wbd_ref(fe, target);
-
-
-	while (p->frequency / 1000 > adc_table->freq) {
-		better_sampling_freq = 1;
-		adc_table++;
-	}
-
-	if ((adc_table->freq != 0xffffffff) && better_sampling_freq) {
-		pll.pll_ratio  = adc_table->pll_loopdiv;
-		pll.pll_prediv = adc_table->pll_prediv;
-		dib8000_update_pll(fe, &pll);
-		dib8000_ctrl_timf(fe, DEMOD_TIMF_SET, adc_table->timf);
-	}
-	return 0;
-}
-
-static int tfe8096p_frontend_attach(struct dvb_usb_adapter *adap)
-{
-	dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
-	msleep(20);
-	dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
-	dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1);
-	dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1);
-
-	dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0);
-
-	dib0700_ctrl_clock(adap->dev, 72, 1);
-
-	msleep(20);
-	dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
-	msleep(20);
-	dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
-
-	dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x10, 0x80, 1);
-
-	adap->fe_adap[0].fe = dvb_attach(dib8000_attach,
-			&adap->dev->i2c_adap, 0x80, &tfe8096p_dib8000_config);
-
-	return adap->fe_adap[0].fe == NULL ?  -ENODEV : 0;
-}
-
-static int tfe8096p_tuner_attach(struct dvb_usb_adapter *adap)
-{
-	struct dib0700_adapter_state *st = adap->priv;
-	struct i2c_adapter *tun_i2c = dib8096p_get_i2c_tuner(adap->fe_adap[0].fe);
-
-	if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c,
-				&tfe8096p_dib0090_config) == NULL)
-		return -ENODEV;
-
-	dib8000_set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
-
-	st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
-	adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib8096p_agc_startup;
-	return 0;
-}
-
-/* STK9090M */
-static int dib90x0_pid_filter(struct dvb_usb_adapter *adapter, int index, u16 pid, int onoff)
-{
-	return dib9000_fw_pid_filter(adapter->fe_adap[0].fe, index, pid, onoff);
-}
-
-static int dib90x0_pid_filter_ctrl(struct dvb_usb_adapter *adapter, int onoff)
-{
-	return dib9000_fw_pid_filter_ctrl(adapter->fe_adap[0].fe, onoff);
-}
-
-static int dib90x0_tuner_reset(struct dvb_frontend *fe, int onoff)
-{
-	return dib9000_set_gpio(fe, 5, 0, !onoff);
-}
-
-static int dib90x0_tuner_sleep(struct dvb_frontend *fe, int onoff)
-{
-	return dib9000_set_gpio(fe, 0, 0, onoff);
-}
-
-static int dib01x0_pmu_update(struct i2c_adapter *i2c, u16 *data, u8 len)
-{
-	u8 wb[4] = { 0xc >> 8, 0xc & 0xff, 0, 0 };
-	u8 rb[2];
-	struct i2c_msg msg[2] = {
-		{.addr = 0x1e >> 1, .flags = 0, .buf = wb, .len = 2},
-		{.addr = 0x1e >> 1, .flags = I2C_M_RD, .buf = rb, .len = 2},
-	};
-	u8 index_data;
-
-	dibx000_i2c_set_speed(i2c, 250);
-
-	if (i2c_transfer(i2c, msg, 2) != 2)
-		return -EIO;
-
-	switch (rb[0] << 8 | rb[1]) {
-	case 0:
-			deb_info("Found DiB0170 rev1: This version of DiB0170 is not supported any longer.\n");
-			return -EIO;
-	case 1:
-			deb_info("Found DiB0170 rev2");
-			break;
-	case 2:
-			deb_info("Found DiB0190 rev2");
-			break;
-	default:
-			deb_info("DiB01x0 not found");
-			return -EIO;
-	}
-
-	for (index_data = 0; index_data < len; index_data += 2) {
-		wb[2] = (data[index_data + 1] >> 8) & 0xff;
-		wb[3] = (data[index_data + 1]) & 0xff;
-
-		if (data[index_data] == 0) {
-			wb[0] = (data[index_data] >> 8) & 0xff;
-			wb[1] = (data[index_data]) & 0xff;
-			msg[0].len = 2;
-			if (i2c_transfer(i2c, msg, 2) != 2)
-				return -EIO;
-			wb[2] |= rb[0];
-			wb[3] |= rb[1] & ~(3 << 4);
-		}
-
-		wb[0] = (data[index_data] >> 8)&0xff;
-		wb[1] = (data[index_data])&0xff;
-		msg[0].len = 4;
-		if (i2c_transfer(i2c, &msg[0], 1) != 1)
-			return -EIO;
-	}
-	return 0;
-}
-
-static struct dib9000_config stk9090m_config = {
-	.output_mpeg2_in_188_bytes = 1,
-	.output_mode = OUTMODE_MPEG2_FIFO,
-	.vcxo_timer = 279620,
-	.timing_frequency = 20452225,
-	.demod_clock_khz = 60000,
-	.xtal_clock_khz = 30000,
-	.if_drives = (0 << 15) | (1 << 13) | (0 << 12) | (3 << 10) | (0 << 9) | (1 << 7) | (0 << 6) | (0 << 4) | (1 << 3) | (1 << 1) | (0),
-	.subband = {
-		2,
-		{
-			{ 240, { BOARD_GPIO_COMPONENT_DEMOD, BOARD_GPIO_FUNCTION_SUBBAND_GPIO, 0x0008, 0x0000, 0x0008 } }, /* GPIO 3 to 1 for VHF */
-			{ 890, { BOARD_GPIO_COMPONENT_DEMOD, BOARD_GPIO_FUNCTION_SUBBAND_GPIO, 0x0008, 0x0000, 0x0000 } }, /* GPIO 3 to 0 for UHF */
-			{ 0 },
-		},
-	},
-	.gpio_function = {
-		{ .component = BOARD_GPIO_COMPONENT_DEMOD, .function = BOARD_GPIO_FUNCTION_COMPONENT_ON, .mask = 0x10 | 0x21, .direction = 0 & ~0x21, .value = (0x10 & ~0x1) | 0x20 },
-		{ .component = BOARD_GPIO_COMPONENT_DEMOD, .function = BOARD_GPIO_FUNCTION_COMPONENT_OFF, .mask = 0x10 | 0x21, .direction = 0 & ~0x21, .value = 0 | 0x21 },
-	},
-};
-
-static struct dib9000_config nim9090md_config[2] = {
-	{
-		.output_mpeg2_in_188_bytes = 1,
-		.output_mode = OUTMODE_MPEG2_FIFO,
-		.vcxo_timer = 279620,
-		.timing_frequency = 20452225,
-		.demod_clock_khz = 60000,
-		.xtal_clock_khz = 30000,
-		.if_drives = (0 << 15) | (1 << 13) | (0 << 12) | (3 << 10) | (0 << 9) | (1 << 7) | (0 << 6) | (0 << 4) | (1 << 3) | (1 << 1) | (0),
-	}, {
-		.output_mpeg2_in_188_bytes = 1,
-		.output_mode = OUTMODE_DIVERSITY,
-		.vcxo_timer = 279620,
-		.timing_frequency = 20452225,
-		.demod_clock_khz = 60000,
-		.xtal_clock_khz = 30000,
-		.if_drives = (0 << 15) | (1 << 13) | (0 << 12) | (3 << 10) | (0 << 9) | (1 << 7) | (0 << 6) | (0 << 4) | (1 << 3) | (1 << 1) | (0),
-		.subband = {
-			2,
-			{
-				{ 240, { BOARD_GPIO_COMPONENT_DEMOD, BOARD_GPIO_FUNCTION_SUBBAND_GPIO, 0x0006, 0x0000, 0x0006 } }, /* GPIO 1 and 2 to 1 for VHF */
-				{ 890, { BOARD_GPIO_COMPONENT_DEMOD, BOARD_GPIO_FUNCTION_SUBBAND_GPIO, 0x0006, 0x0000, 0x0000 } }, /* GPIO 1 and 2 to 0 for UHF */
-				{ 0 },
-			},
-		},
-		.gpio_function = {
-			{ .component = BOARD_GPIO_COMPONENT_DEMOD, .function = BOARD_GPIO_FUNCTION_COMPONENT_ON, .mask = 0x10 | 0x21, .direction = 0 & ~0x21, .value = (0x10 & ~0x1) | 0x20 },
-			{ .component = BOARD_GPIO_COMPONENT_DEMOD, .function = BOARD_GPIO_FUNCTION_COMPONENT_OFF, .mask = 0x10 | 0x21, .direction = 0 & ~0x21, .value = 0 | 0x21 },
-		},
-	}
-};
-
-static struct dib0090_config dib9090_dib0090_config = {
-	.io.pll_bypass = 0,
-	.io.pll_range = 1,
-	.io.pll_prediv = 1,
-	.io.pll_loopdiv = 8,
-	.io.adc_clock_ratio = 8,
-	.io.pll_int_loop_filt = 0,
-	.io.clock_khz = 30000,
-	.reset = dib90x0_tuner_reset,
-	.sleep = dib90x0_tuner_sleep,
-	.clkouttobamse = 0,
-	.analog_output = 0,
-	.use_pwm_agc = 0,
-	.clkoutdrive = 0,
-	.freq_offset_khz_uhf = 0,
-	.freq_offset_khz_vhf = 0,
-};
-
-static struct dib0090_config nim9090md_dib0090_config[2] = {
-	{
-		.io.pll_bypass = 0,
-		.io.pll_range = 1,
-		.io.pll_prediv = 1,
-		.io.pll_loopdiv = 8,
-		.io.adc_clock_ratio = 8,
-		.io.pll_int_loop_filt = 0,
-		.io.clock_khz = 30000,
-		.reset = dib90x0_tuner_reset,
-		.sleep = dib90x0_tuner_sleep,
-		.clkouttobamse = 1,
-		.analog_output = 0,
-		.use_pwm_agc = 0,
-		.clkoutdrive = 0,
-		.freq_offset_khz_uhf = 0,
-		.freq_offset_khz_vhf = 0,
-	}, {
-		.io.pll_bypass = 0,
-		.io.pll_range = 1,
-		.io.pll_prediv = 1,
-		.io.pll_loopdiv = 8,
-		.io.adc_clock_ratio = 8,
-		.io.pll_int_loop_filt = 0,
-		.io.clock_khz = 30000,
-		.reset = dib90x0_tuner_reset,
-		.sleep = dib90x0_tuner_sleep,
-		.clkouttobamse = 0,
-		.analog_output = 0,
-		.use_pwm_agc = 0,
-		.clkoutdrive = 0,
-		.freq_offset_khz_uhf = 0,
-		.freq_offset_khz_vhf = 0,
-	}
-};
-
-
-static int stk9090m_frontend_attach(struct dvb_usb_adapter *adap)
-{
-	struct dib0700_adapter_state *state = adap->priv;
-	struct dib0700_state *st = adap->dev->priv;
-	u32 fw_version;
-
-	/* Make use of the new i2c functions from FW 1.20 */
-	dib0700_get_version(adap->dev, NULL, NULL, &fw_version, NULL);
-	if (fw_version >= 0x10200)
-		st->fw_use_new_i2c_api = 1;
-	dib0700_set_i2c_speed(adap->dev, 340);
-
-	dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
-	msleep(20);
-	dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
-	dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1);
-	dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1);
-	dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0);
-
-	dib0700_ctrl_clock(adap->dev, 72, 1);
-
-	msleep(20);
-	dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
-	msleep(20);
-	dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
-
-	dib9000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x10, 0x80);
-
-	if (request_firmware(&state->frontend_firmware, "dib9090.fw", &adap->dev->udev->dev)) {
-		deb_info("%s: Upload failed. (file not found?)\n", __func__);
-		return -ENODEV;
-	} else {
-		deb_info("%s: firmware read %Zu bytes.\n", __func__, state->frontend_firmware->size);
-	}
-	stk9090m_config.microcode_B_fe_size = state->frontend_firmware->size;
-	stk9090m_config.microcode_B_fe_buffer = state->frontend_firmware->data;
-
-	adap->fe_adap[0].fe = dvb_attach(dib9000_attach, &adap->dev->i2c_adap, 0x80, &stk9090m_config);
-
-	return adap->fe_adap[0].fe == NULL ?  -ENODEV : 0;
-}
-
-static int dib9090_tuner_attach(struct dvb_usb_adapter *adap)
-{
-	struct dib0700_adapter_state *state = adap->priv;
-	struct i2c_adapter *i2c = dib9000_get_tuner_interface(adap->fe_adap[0].fe);
-	u16 data_dib190[10] = {
-		1, 0x1374,
-		2, 0x01a2,
-		7, 0x0020,
-		0, 0x00ef,
-		8, 0x0486,
-	};
-
-	if (dvb_attach(dib0090_fw_register, adap->fe_adap[0].fe, i2c, &dib9090_dib0090_config) == NULL)
-		return -ENODEV;
-	i2c = dib9000_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_GPIO_1_2, 0);
-	if (dib01x0_pmu_update(i2c, data_dib190, 10) != 0)
-		return -ENODEV;
-	dib0700_set_i2c_speed(adap->dev, 1500);
-	if (dib9000_firmware_post_pll_init(adap->fe_adap[0].fe) < 0)
-		return -ENODEV;
-	release_firmware(state->frontend_firmware);
-	return 0;
-}
-
-static int nim9090md_frontend_attach(struct dvb_usb_adapter *adap)
-{
-	struct dib0700_adapter_state *state = adap->priv;
-	struct dib0700_state *st = adap->dev->priv;
-	struct i2c_adapter *i2c;
-	struct dvb_frontend *fe_slave;
-	u32 fw_version;
-
-	/* Make use of the new i2c functions from FW 1.20 */
-	dib0700_get_version(adap->dev, NULL, NULL, &fw_version, NULL);
-	if (fw_version >= 0x10200)
-		st->fw_use_new_i2c_api = 1;
-	dib0700_set_i2c_speed(adap->dev, 340);
-
-	dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
-	msleep(20);
-	dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
-	dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1);
-	dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1);
-	dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0);
-
-	dib0700_ctrl_clock(adap->dev, 72, 1);
-
-	msleep(20);
-	dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
-	msleep(20);
-	dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
-
-	if (request_firmware(&state->frontend_firmware, "dib9090.fw", &adap->dev->udev->dev)) {
-		deb_info("%s: Upload failed. (file not found?)\n", __func__);
-		return -EIO;
-	} else {
-		deb_info("%s: firmware read %Zu bytes.\n", __func__, state->frontend_firmware->size);
-	}
-	nim9090md_config[0].microcode_B_fe_size = state->frontend_firmware->size;
-	nim9090md_config[0].microcode_B_fe_buffer = state->frontend_firmware->data;
-	nim9090md_config[1].microcode_B_fe_size = state->frontend_firmware->size;
-	nim9090md_config[1].microcode_B_fe_buffer = state->frontend_firmware->data;
-
-	dib9000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x20, 0x80);
-	adap->fe_adap[0].fe = dvb_attach(dib9000_attach, &adap->dev->i2c_adap, 0x80, &nim9090md_config[0]);
-
-	if (adap->fe_adap[0].fe == NULL)
-		return -ENODEV;
-
-	i2c = dib9000_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_GPIO_3_4, 0);
-	dib9000_i2c_enumeration(i2c, 1, 0x12, 0x82);
-
-	fe_slave = dvb_attach(dib9000_attach, i2c, 0x82, &nim9090md_config[1]);
-	dib9000_set_slave_frontend(adap->fe_adap[0].fe, fe_slave);
-
-	return fe_slave == NULL ?  -ENODEV : 0;
-}
-
-static int nim9090md_tuner_attach(struct dvb_usb_adapter *adap)
-{
-	struct dib0700_adapter_state *state = adap->priv;
-	struct i2c_adapter *i2c;
-	struct dvb_frontend *fe_slave;
-	u16 data_dib190[10] = {
-		1, 0x5374,
-		2, 0x01ae,
-		7, 0x0020,
-		0, 0x00ef,
-		8, 0x0406,
-	};
-	i2c = dib9000_get_tuner_interface(adap->fe_adap[0].fe);
-	if (dvb_attach(dib0090_fw_register, adap->fe_adap[0].fe, i2c, &nim9090md_dib0090_config[0]) == NULL)
-		return -ENODEV;
-	i2c = dib9000_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_GPIO_1_2, 0);
-	if (dib01x0_pmu_update(i2c, data_dib190, 10) < 0)
-		return -ENODEV;
-
-	dib0700_set_i2c_speed(adap->dev, 1500);
-	if (dib9000_firmware_post_pll_init(adap->fe_adap[0].fe) < 0)
-		return -ENODEV;
-
-	fe_slave = dib9000_get_slave_frontend(adap->fe_adap[0].fe, 1);
-	if (fe_slave != NULL) {
-		i2c = dib9000_get_component_bus_interface(adap->fe_adap[0].fe);
-		dib9000_set_i2c_adapter(fe_slave, i2c);
-
-		i2c = dib9000_get_tuner_interface(fe_slave);
-		if (dvb_attach(dib0090_fw_register, fe_slave, i2c, &nim9090md_dib0090_config[1]) == NULL)
-			return -ENODEV;
-		fe_slave->dvb = adap->fe_adap[0].fe->dvb;
-		dib9000_fw_set_component_bus_speed(adap->fe_adap[0].fe, 1500);
-		if (dib9000_firmware_post_pll_init(fe_slave) < 0)
-			return -ENODEV;
-	}
-	release_firmware(state->frontend_firmware);
-
-	return 0;
-}
-
-/* NIM7090 */
-struct dib7090p_best_adc {
-	u32 timf;
-	u32 pll_loopdiv;
-	u32 pll_prediv;
-};
-
-static int dib7090p_get_best_sampling(struct dvb_frontend *fe , struct dib7090p_best_adc *adc)
-{
-	u8 spur = 0, prediv = 0, loopdiv = 0, min_prediv = 1, max_prediv = 1;
-
-	u16 xtal = 12000;
-	u32 fcp_min = 1900;  /* PLL Minimum Frequency comparator KHz */
-	u32 fcp_max = 20000; /* PLL Maximum Frequency comparator KHz */
-	u32 fdem_max = 76000;
-	u32 fdem_min = 69500;
-	u32 fcp = 0, fs = 0, fdem = 0;
-	u32 harmonic_id = 0;
-
-	adc->pll_loopdiv = loopdiv;
-	adc->pll_prediv = prediv;
-	adc->timf = 0;
-
-	deb_info("bandwidth = %d fdem_min =%d", fe->dtv_property_cache.bandwidth_hz, fdem_min);
-
-	/* Find Min and Max prediv */
-	while ((xtal/max_prediv) >= fcp_min)
-		max_prediv++;
-
-	max_prediv--;
-	min_prediv = max_prediv;
-	while ((xtal/min_prediv) <= fcp_max) {
-		min_prediv--;
-		if (min_prediv == 1)
-			break;
-	}
-	deb_info("MIN prediv = %d : MAX prediv = %d", min_prediv, max_prediv);
-
-	min_prediv = 2;
-
-	for (prediv = min_prediv ; prediv < max_prediv; prediv++) {
-		fcp = xtal / prediv;
-		if (fcp > fcp_min && fcp < fcp_max) {
-			for (loopdiv = 1 ; loopdiv < 64 ; loopdiv++) {
-				fdem = ((xtal/prediv) * loopdiv);
-				fs   = fdem / 4;
-				/* test min/max system restrictions */
-
-				if ((fdem >= fdem_min) && (fdem <= fdem_max) && (fs >= fe->dtv_property_cache.bandwidth_hz/1000)) {
-					spur = 0;
-					/* test fs harmonics positions */
-					for (harmonic_id = (fe->dtv_property_cache.frequency / (1000*fs)) ;  harmonic_id <= ((fe->dtv_property_cache.frequency / (1000*fs))+1) ; harmonic_id++) {
-						if (((fs*harmonic_id) >= ((fe->dtv_property_cache.frequency/1000) - (fe->dtv_property_cache.bandwidth_hz/2000))) &&  ((fs*harmonic_id) <= ((fe->dtv_property_cache.frequency/1000) + (fe->dtv_property_cache.bandwidth_hz/2000)))) {
-							spur = 1;
-							break;
-						}
-					}
-
-					if (!spur) {
-						adc->pll_loopdiv = loopdiv;
-						adc->pll_prediv = prediv;
-						adc->timf = 2396745143UL/fdem*(1 << 9);
-						adc->timf += ((2396745143UL%fdem) << 9)/fdem;
-						deb_info("loopdiv=%i prediv=%i timf=%i", loopdiv, prediv, adc->timf);
-						break;
-					}
-				}
-			}
-		}
-		if (!spur)
-			break;
-	}
-
-
-	if (adc->pll_loopdiv == 0 && adc->pll_prediv == 0)
-		return -EINVAL;
-	else
-		return 0;
-}
-
-static int dib7090_agc_startup(struct dvb_frontend *fe)
-{
-	struct dvb_usb_adapter *adap = fe->dvb->priv;
-	struct dib0700_adapter_state *state = adap->priv;
-	struct dibx000_bandwidth_config pll;
-	u16 target;
-	struct dib7090p_best_adc adc;
-	int ret;
-
-	ret = state->set_param_save(fe);
-	if (ret < 0)
-		return ret;
-
-	memset(&pll, 0, sizeof(struct dibx000_bandwidth_config));
-	dib0090_pwm_gain_reset(fe);
-	target = (dib0090_get_wbd_target(fe) * 8 + 1) / 2;
-	dib7000p_set_wbd_ref(fe, target);
-
-	if (dib7090p_get_best_sampling(fe, &adc) == 0) {
-		pll.pll_ratio  = adc.pll_loopdiv;
-		pll.pll_prediv = adc.pll_prediv;
-
-		dib7000p_update_pll(fe, &pll);
-		dib7000p_ctrl_timf(fe, DEMOD_TIMF_SET, adc.timf);
-	}
-	return 0;
-}
-
-static int dib7090_agc_restart(struct dvb_frontend *fe, u8 restart)
-{
-	deb_info("AGC restart callback: %d", restart);
-	if (restart == 0) /* before AGC startup */
-		dib0090_set_dc_servo(fe, 1);
-	return 0;
-}
-
-static int dib7090e_update_lna(struct dvb_frontend *fe, u16 agc_global)
-{
-	u16 agc1 = 0, agc2, wbd = 0, wbd_target, wbd_offset, threshold_agc1;
-	s16 wbd_delta;
-
-	if ((fe->dtv_property_cache.frequency) < 400000000)
-		threshold_agc1 = 25000;
-	else
-		threshold_agc1 = 30000;
-
-	wbd_target = (dib0090_get_wbd_target(fe)*8+1)/2;
-	wbd_offset = dib0090_get_wbd_offset(fe);
-	dib7000p_get_agc_values(fe, NULL, &agc1, &agc2, &wbd);
-	wbd_delta = (s16)wbd - (((s16)wbd_offset+10)*4) ;
-
-	deb_info("update lna, agc_global=%d agc1=%d agc2=%d",
-			agc_global, agc1, agc2);
-	deb_info("update lna, wbd=%d wbd target=%d wbd offset=%d wbd delta=%d",
-			wbd, wbd_target, wbd_offset, wbd_delta);
-
-	if ((agc1 < threshold_agc1) && (wbd_delta > 0)) {
-		dib0090_set_switch(fe, 1, 1, 1);
-		dib0090_set_vga(fe, 0);
-		dib0090_update_rframp_7090(fe, 0);
-		dib0090_update_tuning_table_7090(fe, 0);
-	} else {
-		dib0090_set_vga(fe, 1);
-		dib0090_update_rframp_7090(fe, 1);
-		dib0090_update_tuning_table_7090(fe, 1);
-		dib0090_set_switch(fe, 0, 0, 0);
-	}
-
-	return 0;
-}
-
-static struct dib0090_wbd_slope dib7090_wbd_table[] = {
-	{ 380,   81, 850, 64, 540,  4},
-	{ 860,   51, 866, 21,  375, 4},
-	{1700,    0, 250, 0,   100, 6},
-	{2600,    0, 250, 0,   100, 6},
-	{ 0xFFFF, 0,   0, 0,   0,   0},
-};
-
-static struct dib0090_wbd_slope dib7090e_wbd_table[] = {
-	{ 380,   81, 850, 64, 540,	4},
-	{ 700,   51, 866, 21,  320,	4},
-	{ 860,   48, 666, 18,  330,	6},
-	{1700,    0, 250, 0,   100, 6},
-	{2600,    0, 250, 0,   100, 6},
-	{ 0xFFFF, 0,   0, 0,   0,	0},
-};
-
-static struct dibx000_agc_config dib7090_agc_config[2] = {
-	{
-		.band_caps      = BAND_UHF,
-		/* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=1, P_agc_inv_pwm1=0, P_agc_inv_pwm2=0,
-		* P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, P_agc_write=0 */
-		.setup          = (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0),
-
-		.inv_gain       = 687,
-		.time_stabiliz  = 10,
-
-		.alpha_level    = 0,
-		.thlock         = 118,
-
-		.wbd_inv        = 0,
-		.wbd_ref        = 1200,
-		.wbd_sel        = 3,
-		.wbd_alpha      = 5,
-
-		.agc1_max       = 65535,
-		.agc1_min       = 0,
-
-		.agc2_max       = 65535,
-		.agc2_min       = 0,
-
-		.agc1_pt1       = 0,
-		.agc1_pt2       = 32,
-		.agc1_pt3       = 114,
-		.agc1_slope1    = 143,
-		.agc1_slope2    = 144,
-		.agc2_pt1       = 114,
-		.agc2_pt2       = 227,
-		.agc2_slope1    = 116,
-		.agc2_slope2    = 117,
-
-		.alpha_mant     = 18,
-		.alpha_exp      = 0,
-		.beta_mant      = 20,
-		.beta_exp       = 59,
-
-		.perform_agc_softsplit = 0,
-	} , {
-		.band_caps      = BAND_FM | BAND_VHF | BAND_CBAND,
-		/* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=1, P_agc_inv_pwm1=0, P_agc_inv_pwm2=0,
-		* P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, P_agc_write=0 */
-		.setup          = (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0),
-
-		.inv_gain       = 732,
-		.time_stabiliz  = 10,
-
-		.alpha_level    = 0,
-		.thlock         = 118,
-
-		.wbd_inv        = 0,
-		.wbd_ref        = 1200,
-		.wbd_sel        = 3,
-		.wbd_alpha      = 5,
-
-		.agc1_max       = 65535,
-		.agc1_min       = 0,
-
-		.agc2_max       = 65535,
-		.agc2_min       = 0,
-
-		.agc1_pt1       = 0,
-		.agc1_pt2       = 0,
-		.agc1_pt3       = 98,
-		.agc1_slope1    = 0,
-		.agc1_slope2    = 167,
-		.agc2_pt1       = 98,
-		.agc2_pt2       = 255,
-		.agc2_slope1    = 104,
-		.agc2_slope2    = 0,
-
-		.alpha_mant     = 18,
-		.alpha_exp      = 0,
-		.beta_mant      = 20,
-		.beta_exp       = 59,
-
-		.perform_agc_softsplit = 0,
-	}
-};
-
-static struct dibx000_bandwidth_config dib7090_clock_config_12_mhz = {
-	60000, 15000,
-	1, 5, 0, 0, 0,
-	0, 0, 1, 1, 2,
-	(3 << 14) | (1 << 12) | (524 << 0),
-	(0 << 25) | 0,
-	20452225,
-	15000000,
-};
-
-static struct dib7000p_config nim7090_dib7000p_config = {
-	.output_mpeg2_in_188_bytes  = 1,
-	.hostbus_diversity			= 1,
-	.tuner_is_baseband			= 1,
-	.update_lna					= NULL,
-
-	.agc_config_count			= 2,
-	.agc						= dib7090_agc_config,
-
-	.bw							= &dib7090_clock_config_12_mhz,
-
-	.gpio_dir					= DIB7000P_GPIO_DEFAULT_DIRECTIONS,
-	.gpio_val					= DIB7000P_GPIO_DEFAULT_VALUES,
-	.gpio_pwm_pos				= DIB7000P_GPIO_DEFAULT_PWM_POS,
-
-	.pwm_freq_div				= 0,
-
-	.agc_control				= dib7090_agc_restart,
-
-	.spur_protect				= 0,
-	.disable_sample_and_hold	= 0,
-	.enable_current_mirror		= 0,
-	.diversity_delay			= 0,
-
-	.output_mode				= OUTMODE_MPEG2_FIFO,
-	.enMpegOutput				= 1,
-};
-
-static struct dib7000p_config tfe7090pvr_dib7000p_config[2] = {
-	{
-		.output_mpeg2_in_188_bytes  = 1,
-		.hostbus_diversity			= 1,
-		.tuner_is_baseband			= 1,
-		.update_lna					= NULL,
-
-		.agc_config_count			= 2,
-		.agc						= dib7090_agc_config,
-
-		.bw							= &dib7090_clock_config_12_mhz,
-
-		.gpio_dir					= DIB7000P_GPIO_DEFAULT_DIRECTIONS,
-		.gpio_val					= DIB7000P_GPIO_DEFAULT_VALUES,
-		.gpio_pwm_pos				= DIB7000P_GPIO_DEFAULT_PWM_POS,
-
-		.pwm_freq_div				= 0,
-
-		.agc_control				= dib7090_agc_restart,
-
-		.spur_protect				= 0,
-		.disable_sample_and_hold	= 0,
-		.enable_current_mirror		= 0,
-		.diversity_delay			= 0,
-
-		.output_mode				= OUTMODE_MPEG2_PAR_GATED_CLK,
-		.default_i2c_addr			= 0x90,
-		.enMpegOutput				= 1,
-	}, {
-		.output_mpeg2_in_188_bytes  = 1,
-		.hostbus_diversity			= 1,
-		.tuner_is_baseband			= 1,
-		.update_lna					= NULL,
-
-		.agc_config_count			= 2,
-		.agc						= dib7090_agc_config,
-
-		.bw							= &dib7090_clock_config_12_mhz,
-
-		.gpio_dir					= DIB7000P_GPIO_DEFAULT_DIRECTIONS,
-		.gpio_val					= DIB7000P_GPIO_DEFAULT_VALUES,
-		.gpio_pwm_pos				= DIB7000P_GPIO_DEFAULT_PWM_POS,
-
-		.pwm_freq_div				= 0,
-
-		.agc_control				= dib7090_agc_restart,
-
-		.spur_protect				= 0,
-		.disable_sample_and_hold	= 0,
-		.enable_current_mirror		= 0,
-		.diversity_delay			= 0,
-
-		.output_mode				= OUTMODE_MPEG2_PAR_GATED_CLK,
-		.default_i2c_addr			= 0x92,
-		.enMpegOutput				= 0,
-	}
-};
-
-static struct dib7000p_config tfe7090e_dib7000p_config = {
-	.output_mpeg2_in_188_bytes  = 1,
-	.hostbus_diversity			= 1,
-	.tuner_is_baseband			= 1,
-	.update_lna					= dib7090e_update_lna,
-
-	.agc_config_count			= 2,
-	.agc						= dib7090_agc_config,
-
-	.bw							= &dib7090_clock_config_12_mhz,
-
-	.gpio_dir					= DIB7000P_GPIO_DEFAULT_DIRECTIONS,
-	.gpio_val					= DIB7000P_GPIO_DEFAULT_VALUES,
-	.gpio_pwm_pos				= DIB7000P_GPIO_DEFAULT_PWM_POS,
-
-	.pwm_freq_div				= 0,
-
-	.agc_control				= dib7090_agc_restart,
-
-	.spur_protect				= 0,
-	.disable_sample_and_hold	= 0,
-	.enable_current_mirror		= 0,
-	.diversity_delay			= 0,
-
-	.output_mode				= OUTMODE_MPEG2_FIFO,
-	.enMpegOutput				= 1,
-};
-
-static const struct dib0090_config nim7090_dib0090_config = {
-	.io.clock_khz = 12000,
-	.io.pll_bypass = 0,
-	.io.pll_range = 0,
-	.io.pll_prediv = 3,
-	.io.pll_loopdiv = 6,
-	.io.adc_clock_ratio = 0,
-	.io.pll_int_loop_filt = 0,
-	.reset = dib7090_tuner_sleep,
-	.sleep = dib7090_tuner_sleep,
-
-	.freq_offset_khz_uhf = 0,
-	.freq_offset_khz_vhf = 0,
-
-	.get_adc_power = dib7090_get_adc_power,
-
-	.clkouttobamse = 1,
-	.analog_output = 0,
-
-	.wbd_vhf_offset = 0,
-	.wbd_cband_offset = 0,
-	.use_pwm_agc = 1,
-	.clkoutdrive = 0,
-
-	.fref_clock_ratio = 0,
-
-	.wbd = dib7090_wbd_table,
-
-	.ls_cfg_pad_drv = 0,
-	.data_tx_drv = 0,
-	.low_if = NULL,
-	.in_soc = 1,
-};
-
-static const struct dib0090_config tfe7090e_dib0090_config = {
-	.io.clock_khz = 12000,
-	.io.pll_bypass = 0,
-	.io.pll_range = 0,
-	.io.pll_prediv = 3,
-	.io.pll_loopdiv = 6,
-	.io.adc_clock_ratio = 0,
-	.io.pll_int_loop_filt = 0,
-	.reset = dib7090_tuner_sleep,
-	.sleep = dib7090_tuner_sleep,
-
-	.freq_offset_khz_uhf = 0,
-	.freq_offset_khz_vhf = 0,
-
-	.get_adc_power = dib7090_get_adc_power,
-
-	.clkouttobamse = 1,
-	.analog_output = 0,
-
-	.wbd_vhf_offset = 0,
-	.wbd_cband_offset = 0,
-	.use_pwm_agc = 1,
-	.clkoutdrive = 0,
-
-	.fref_clock_ratio = 0,
-
-	.wbd = dib7090e_wbd_table,
-
-	.ls_cfg_pad_drv = 0,
-	.data_tx_drv = 0,
-	.low_if = NULL,
-	.in_soc = 1,
-	.force_cband_input = 1,
-	.is_dib7090e = 1,
-};
-
-static struct dib7000p_config tfe7790e_dib7000p_config = {
-	.output_mpeg2_in_188_bytes  = 1,
-	.hostbus_diversity			= 1,
-	.tuner_is_baseband			= 1,
-	.update_lna					= dib7090e_update_lna,
-
-	.agc_config_count			= 2,
-	.agc						= dib7090_agc_config,
-
-	.bw							= &dib7090_clock_config_12_mhz,
-
-	.gpio_dir					= DIB7000P_GPIO_DEFAULT_DIRECTIONS,
-	.gpio_val					= DIB7000P_GPIO_DEFAULT_VALUES,
-	.gpio_pwm_pos				= DIB7000P_GPIO_DEFAULT_PWM_POS,
-
-	.pwm_freq_div				= 0,
-
-	.agc_control				= dib7090_agc_restart,
-
-	.spur_protect				= 0,
-	.disable_sample_and_hold	= 0,
-	.enable_current_mirror		= 0,
-	.diversity_delay			= 0,
-
-	.output_mode				= OUTMODE_MPEG2_PAR_GATED_CLK,
-	.enMpegOutput				= 1,
-};
-
-static const struct dib0090_config tfe7790e_dib0090_config = {
-	.io.clock_khz = 12000,
-	.io.pll_bypass = 0,
-	.io.pll_range = 0,
-	.io.pll_prediv = 3,
-	.io.pll_loopdiv = 6,
-	.io.adc_clock_ratio = 0,
-	.io.pll_int_loop_filt = 0,
-	.reset = dib7090_tuner_sleep,
-	.sleep = dib7090_tuner_sleep,
-
-	.freq_offset_khz_uhf = 0,
-	.freq_offset_khz_vhf = 0,
-
-	.get_adc_power = dib7090_get_adc_power,
-
-	.clkouttobamse = 1,
-	.analog_output = 0,
-
-	.wbd_vhf_offset = 0,
-	.wbd_cband_offset = 0,
-	.use_pwm_agc = 1,
-	.clkoutdrive = 0,
-
-	.fref_clock_ratio = 0,
-
-	.wbd = dib7090e_wbd_table,
-
-	.ls_cfg_pad_drv = 0,
-	.data_tx_drv = 0,
-	.low_if = NULL,
-	.in_soc = 1,
-	.force_cband_input = 1,
-	.is_dib7090e = 1,
-	.force_crystal_mode = 1,
-};
-
-static const struct dib0090_config tfe7090pvr_dib0090_config[2] = {
-	{
-		.io.clock_khz = 12000,
-		.io.pll_bypass = 0,
-		.io.pll_range = 0,
-		.io.pll_prediv = 3,
-		.io.pll_loopdiv = 6,
-		.io.adc_clock_ratio = 0,
-		.io.pll_int_loop_filt = 0,
-		.reset = dib7090_tuner_sleep,
-		.sleep = dib7090_tuner_sleep,
-
-		.freq_offset_khz_uhf = 50,
-		.freq_offset_khz_vhf = 70,
-
-		.get_adc_power = dib7090_get_adc_power,
-
-		.clkouttobamse = 1,
-		.analog_output = 0,
-
-		.wbd_vhf_offset = 0,
-		.wbd_cband_offset = 0,
-		.use_pwm_agc = 1,
-		.clkoutdrive = 0,
-
-		.fref_clock_ratio = 0,
-
-		.wbd = dib7090_wbd_table,
-
-		.ls_cfg_pad_drv = 0,
-		.data_tx_drv = 0,
-		.low_if = NULL,
-		.in_soc = 1,
-	}, {
-		.io.clock_khz = 12000,
-		.io.pll_bypass = 0,
-		.io.pll_range = 0,
-		.io.pll_prediv = 3,
-		.io.pll_loopdiv = 6,
-		.io.adc_clock_ratio = 0,
-		.io.pll_int_loop_filt = 0,
-		.reset = dib7090_tuner_sleep,
-		.sleep = dib7090_tuner_sleep,
-
-		.freq_offset_khz_uhf = -50,
-		.freq_offset_khz_vhf = -70,
-
-		.get_adc_power = dib7090_get_adc_power,
-
-		.clkouttobamse = 1,
-		.analog_output = 0,
-
-		.wbd_vhf_offset = 0,
-		.wbd_cband_offset = 0,
-		.use_pwm_agc = 1,
-		.clkoutdrive = 0,
-
-		.fref_clock_ratio = 0,
-
-		.wbd = dib7090_wbd_table,
-
-		.ls_cfg_pad_drv = 0,
-		.data_tx_drv = 0,
-		.low_if = NULL,
-		.in_soc = 1,
-	}
-};
-
-static int nim7090_frontend_attach(struct dvb_usb_adapter *adap)
-{
-	dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
-	msleep(20);
-	dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
-	dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1);
-	dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1);
-	dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0);
-
-	msleep(20);
-	dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
-	msleep(20);
-	dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
-
-	if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x10, &nim7090_dib7000p_config) != 0) {
-		err("%s: dib7000p_i2c_enumeration failed.  Cannot continue\n", __func__);
-		return -ENODEV;
-	}
-	adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, &nim7090_dib7000p_config);
-
-	return adap->fe_adap[0].fe == NULL ?  -ENODEV : 0;
-}
-
-static int nim7090_tuner_attach(struct dvb_usb_adapter *adap)
-{
-	struct dib0700_adapter_state *st = adap->priv;
-	struct i2c_adapter *tun_i2c = dib7090_get_i2c_tuner(adap->fe_adap[0].fe);
-
-	if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, &nim7090_dib0090_config) == NULL)
-		return -ENODEV;
-
-	dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
-
-	st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
-	adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7090_agc_startup;
-	return 0;
-}
-
-static int tfe7090pvr_frontend0_attach(struct dvb_usb_adapter *adap)
-{
-	struct dib0700_state *st = adap->dev->priv;
-
-	/* The TFE7090 requires the dib0700 to not be in master mode */
-	st->disable_streaming_master_mode = 1;
-
-	dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
-	msleep(20);
-	dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
-	dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1);
-	dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1);
-	dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0);
-
-	msleep(20);
-	dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
-	msleep(20);
-	dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
-
-	/* initialize IC 0 */
-	if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x20, &tfe7090pvr_dib7000p_config[0]) != 0) {
-		err("%s: dib7000p_i2c_enumeration failed.  Cannot continue\n", __func__);
-		return -ENODEV;
-	}
-
-	dib0700_set_i2c_speed(adap->dev, 340);
-	adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x90, &tfe7090pvr_dib7000p_config[0]);
-	if (adap->fe_adap[0].fe == NULL)
-		return -ENODEV;
-
-	dib7090_slave_reset(adap->fe_adap[0].fe);
-
-	return 0;
-}
-
-static int tfe7090pvr_frontend1_attach(struct dvb_usb_adapter *adap)
-{
-	struct i2c_adapter *i2c;
-
-	if (adap->dev->adapter[0].fe_adap[0].fe == NULL) {
-		err("the master dib7090 has to be initialized first");
-		return -ENODEV; /* the master device has not been initialized */
-	}
-
-	i2c = dib7000p_get_i2c_master(adap->dev->adapter[0].fe_adap[0].fe, DIBX000_I2C_INTERFACE_GPIO_6_7, 1);
-	if (dib7000p_i2c_enumeration(i2c, 1, 0x10, &tfe7090pvr_dib7000p_config[1]) != 0) {
-		err("%s: dib7000p_i2c_enumeration failed.  Cannot continue\n", __func__);
-		return -ENODEV;
-	}
-
-	adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, i2c, 0x92, &tfe7090pvr_dib7000p_config[1]);
-	dib0700_set_i2c_speed(adap->dev, 200);
-
-	return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
-}
-
-static int tfe7090pvr_tuner0_attach(struct dvb_usb_adapter *adap)
-{
-	struct dib0700_adapter_state *st = adap->priv;
-	struct i2c_adapter *tun_i2c = dib7090_get_i2c_tuner(adap->fe_adap[0].fe);
-
-	if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, &tfe7090pvr_dib0090_config[0]) == NULL)
-		return -ENODEV;
-
-	dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
-
-	st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
-	adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7090_agc_startup;
-	return 0;
-}
-
-static int tfe7090pvr_tuner1_attach(struct dvb_usb_adapter *adap)
-{
-	struct dib0700_adapter_state *st = adap->priv;
-	struct i2c_adapter *tun_i2c = dib7090_get_i2c_tuner(adap->fe_adap[0].fe);
-
-	if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, &tfe7090pvr_dib0090_config[1]) == NULL)
-		return -ENODEV;
-
-	dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
-
-	st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
-	adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7090_agc_startup;
-	return 0;
-}
-
-static int tfe7090e_frontend_attach(struct dvb_usb_adapter *adap)
-{
-	dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
-	msleep(20);
-	dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
-	dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1);
-	dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1);
-	dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0);
-
-	msleep(20);
-	dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
-	msleep(20);
-	dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
-
-	if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap,
-				1, 0x10, &tfe7090e_dib7000p_config) != 0) {
-		err("%s: dib7000p_i2c_enumeration failed.  Cannot continue\n",
-				__func__);
-		return -ENODEV;
-	}
-	adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap,
-			0x80, &tfe7090e_dib7000p_config);
-
-	return adap->fe_adap[0].fe == NULL ?  -ENODEV : 0;
-}
-
-static int tfe7790e_frontend_attach(struct dvb_usb_adapter *adap)
-{
-	struct dib0700_state *st = adap->dev->priv;
-
-	/* The TFE7790E requires the dib0700 to not be in master mode */
-	st->disable_streaming_master_mode = 1;
-
-	dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
-	msleep(20);
-	dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
-	dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1);
-	dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1);
-	dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0);
-	msleep(20);
-	dib0700_ctrl_clock(adap->dev, 72, 1);
-	dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
-	msleep(20);
-	dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
-
-	if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap,
-				1, 0x10, &tfe7790e_dib7000p_config) != 0) {
-		err("%s: dib7000p_i2c_enumeration failed.  Cannot continue\n",
-				__func__);
-		return -ENODEV;
-	}
-	adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap,
-			0x80, &tfe7790e_dib7000p_config);
-
-	return adap->fe_adap[0].fe == NULL ?  -ENODEV : 0;
-}
-
-static int tfe7790e_tuner_attach(struct dvb_usb_adapter *adap)
-{
-	struct dib0700_adapter_state *st = adap->priv;
-	struct i2c_adapter *tun_i2c =
-		dib7090_get_i2c_tuner(adap->fe_adap[0].fe);
-
-	if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c,
-				&tfe7790e_dib0090_config) == NULL)
-		return -ENODEV;
-
-	dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
-
-	st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
-	adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7090_agc_startup;
-	return 0;
-}
-
-static int tfe7090e_tuner_attach(struct dvb_usb_adapter *adap)
-{
-	struct dib0700_adapter_state *st = adap->priv;
-	struct i2c_adapter *tun_i2c =
-		dib7090_get_i2c_tuner(adap->fe_adap[0].fe);
-
-	if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c,
-				&tfe7090e_dib0090_config) == NULL)
-		return -ENODEV;
-
-	dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
-
-	st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
-	adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7090_agc_startup;
-	return 0;
-}
-
-/* STK7070PD */
-static struct dib7000p_config stk7070pd_dib7000p_config[2] = {
-	{
-		.output_mpeg2_in_188_bytes = 1,
-
-		.agc_config_count = 1,
-		.agc = &dib7070_agc_config,
-		.bw  = &dib7070_bw_config_12_mhz,
-		.tuner_is_baseband = 1,
-		.spur_protect = 1,
-
-		.gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS,
-		.gpio_val = DIB7000P_GPIO_DEFAULT_VALUES,
-		.gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS,
-
-		.hostbus_diversity = 1,
-	}, {
-		.output_mpeg2_in_188_bytes = 1,
-
-		.agc_config_count = 1,
-		.agc = &dib7070_agc_config,
-		.bw  = &dib7070_bw_config_12_mhz,
-		.tuner_is_baseband = 1,
-		.spur_protect = 1,
-
-		.gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS,
-		.gpio_val = DIB7000P_GPIO_DEFAULT_VALUES,
-		.gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS,
-
-		.hostbus_diversity = 1,
-	}
-};
-
-static void stk7070pd_init(struct dvb_usb_device *dev)
-{
-	dib0700_set_gpio(dev, GPIO6, GPIO_OUT, 1);
-	msleep(10);
-	dib0700_set_gpio(dev, GPIO9, GPIO_OUT, 1);
-	dib0700_set_gpio(dev, GPIO4, GPIO_OUT, 1);
-	dib0700_set_gpio(dev, GPIO7, GPIO_OUT, 1);
-	dib0700_set_gpio(dev, GPIO10, GPIO_OUT, 0);
-
-	dib0700_ctrl_clock(dev, 72, 1);
-
-	msleep(10);
-	dib0700_set_gpio(dev, GPIO10, GPIO_OUT, 1);
-}
-
-static int stk7070pd_frontend_attach0(struct dvb_usb_adapter *adap)
-{
-	stk7070pd_init(adap->dev);
-
-	msleep(10);
-	dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
-
-	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_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, &stk7070pd_dib7000p_config[0]);
-	return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
-}
-
-static int stk7070pd_frontend_attach1(struct dvb_usb_adapter *adap)
-{
-	adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x82, &stk7070pd_dib7000p_config[1]);
-	return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
-}
-
-static int novatd_read_status_override(struct dvb_frontend *fe,
-		fe_status_t *stat)
-{
-	struct dvb_usb_adapter *adap = fe->dvb->priv;
-	struct dvb_usb_device *dev = adap->dev;
-	struct dib0700_state *state = dev->priv;
-	int ret;
-
-	ret = state->read_status(fe, stat);
-
-	if (!ret)
-		dib0700_set_gpio(dev, adap->id == 0 ? GPIO1 : GPIO0, GPIO_OUT,
-				!!(*stat & FE_HAS_LOCK));
-
-	return ret;
-}
-
-static int novatd_sleep_override(struct dvb_frontend* fe)
-{
-	struct dvb_usb_adapter *adap = fe->dvb->priv;
-	struct dvb_usb_device *dev = adap->dev;
-	struct dib0700_state *state = dev->priv;
-
-	/* turn off LED */
-	dib0700_set_gpio(dev, adap->id == 0 ? GPIO1 : GPIO0, GPIO_OUT, 0);
-
-	return state->sleep(fe);
-}
-
-/**
- * novatd_frontend_attach - Nova-TD specific attach
- *
- * Nova-TD has GPIO0, 1 and 2 for LEDs. So do not fiddle with them except for
- * information purposes.
- */
-static int novatd_frontend_attach(struct dvb_usb_adapter *adap)
-{
-	struct dvb_usb_device *dev = adap->dev;
-	struct dib0700_state *st = dev->priv;
-
-	if (adap->id == 0) {
-		stk7070pd_init(dev);
-
-		/* turn the power LED on, the other two off (just in case) */
-		dib0700_set_gpio(dev, GPIO0, GPIO_OUT, 0);
-		dib0700_set_gpio(dev, GPIO1, GPIO_OUT, 0);
-		dib0700_set_gpio(dev, GPIO2, GPIO_OUT, 1);
-
-		if (dib7000p_i2c_enumeration(&dev->i2c_adap, 2, 18,
-					     stk7070pd_dib7000p_config) != 0) {
-			err("%s: dib7000p_i2c_enumeration failed.  Cannot continue\n",
-			    __func__);
-			return -ENODEV;
-		}
-	}
-
-	adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &dev->i2c_adap,
-			adap->id == 0 ? 0x80 : 0x82,
-			&stk7070pd_dib7000p_config[adap->id]);
-
-	if (adap->fe_adap[0].fe == NULL)
-		return -ENODEV;
-
-	st->read_status = adap->fe_adap[0].fe->ops.read_status;
-	adap->fe_adap[0].fe->ops.read_status = novatd_read_status_override;
-	st->sleep = adap->fe_adap[0].fe->ops.sleep;
-	adap->fe_adap[0].fe->ops.sleep = novatd_sleep_override;
-
-	return 0;
-}
-
-/* S5H1411 */
-static struct s5h1411_config pinnacle_801e_config = {
-	.output_mode   = S5H1411_PARALLEL_OUTPUT,
-	.gpio          = S5H1411_GPIO_OFF,
-	.mpeg_timing   = S5H1411_MPEGTIMING_NONCONTINOUS_NONINVERTING_CLOCK,
-	.qam_if        = S5H1411_IF_44000,
-	.vsb_if        = S5H1411_IF_44000,
-	.inversion     = S5H1411_INVERSION_OFF,
-	.status_mode   = S5H1411_DEMODLOCKING
-};
-
-/* Pinnacle PCTV HD Pro 801e GPIOs map:
-   GPIO0  - currently unknown
-   GPIO1  - xc5000 tuner reset
-   GPIO2  - CX25843 sleep
-   GPIO3  - currently unknown
-   GPIO4  - currently unknown
-   GPIO6  - currently unknown
-   GPIO7  - currently unknown
-   GPIO9  - currently unknown
-   GPIO10 - CX25843 reset
- */
-static int s5h1411_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;
-
-	/* The s5h1411 requires the dib0700 to not be in master mode */
-	st->disable_streaming_master_mode = 1;
-
-	/* All msleep values taken from Windows USB trace */
-	dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 0);
-	dib0700_set_gpio(adap->dev, GPIO3, GPIO_OUT, 0);
-	dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
-	msleep(400);
-	dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0);
-	msleep(60);
-	dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
-	msleep(30);
-	dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
-	dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
-	dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1);
-	dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1);
-	dib0700_set_gpio(adap->dev, GPIO2, GPIO_OUT, 0);
-	msleep(30);
-
-	/* Put the CX25843 to sleep for now since we're in digital mode */
-	dib0700_set_gpio(adap->dev, GPIO2, GPIO_OUT, 1);
-
-	/* GPIOs are initialized, do the attach */
-	adap->fe_adap[0].fe = dvb_attach(s5h1411_attach, &pinnacle_801e_config,
-			      &adap->dev->i2c_adap);
-	return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
-}
-
-static int dib0700_xc5000_tuner_callback(void *priv, int component,
-					 int command, int arg)
-{
-	struct dvb_usb_adapter *adap = priv;
-
-	if (command == XC5000_TUNER_RESET) {
-		/* Reset the tuner */
-		dib0700_set_gpio(adap->dev, GPIO1, GPIO_OUT, 0);
-		msleep(10);
-		dib0700_set_gpio(adap->dev, GPIO1, GPIO_OUT, 1);
-		msleep(10);
-	} else {
-		err("xc5000: unknown tuner callback command: %d\n", command);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static struct xc5000_config s5h1411_xc5000_tunerconfig = {
-	.i2c_address      = 0x64,
-	.if_khz           = 5380,
-};
-
-static int xc5000_tuner_attach(struct dvb_usb_adapter *adap)
-{
-	/* FIXME: generalize & move to common area */
-	adap->fe_adap[0].fe->callback = dib0700_xc5000_tuner_callback;
-
-	return dvb_attach(xc5000_attach, adap->fe_adap[0].fe, &adap->dev->i2c_adap,
-			  &s5h1411_xc5000_tunerconfig)
-		== NULL ? -ENODEV : 0;
-}
-
-static int dib0700_xc4000_tuner_callback(void *priv, int component,
-					 int command, int arg)
-{
-	struct dvb_usb_adapter *adap = priv;
-
-	if (command == XC4000_TUNER_RESET) {
-		/* Reset the tuner */
-		dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 0);
-		msleep(10);
-		dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
-	} else {
-		err("xc4000: unknown tuner callback command: %d\n", command);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static struct dibx000_agc_config stk7700p_7000p_xc4000_agc_config = {
-	.band_caps = BAND_UHF | BAND_VHF,
-	.setup = 0x64,
-	.inv_gain = 0x02c8,
-	.time_stabiliz = 0x15,
-	.alpha_level = 0x00,
-	.thlock = 0x76,
-	.wbd_inv = 0x01,
-	.wbd_ref = 0x0b33,
-	.wbd_sel = 0x00,
-	.wbd_alpha = 0x02,
-	.agc1_max = 0x00,
-	.agc1_min = 0x00,
-	.agc2_max = 0x9b26,
-	.agc2_min = 0x26ca,
-	.agc1_pt1 = 0x00,
-	.agc1_pt2 = 0x00,
-	.agc1_pt3 = 0x00,
-	.agc1_slope1 = 0x00,
-	.agc1_slope2 = 0x00,
-	.agc2_pt1 = 0x00,
-	.agc2_pt2 = 0x80,
-	.agc2_slope1 = 0x1d,
-	.agc2_slope2 = 0x1d,
-	.alpha_mant = 0x11,
-	.alpha_exp = 0x1b,
-	.beta_mant = 0x17,
-	.beta_exp = 0x33,
-	.perform_agc_softsplit = 0x00,
-};
-
-static struct dibx000_bandwidth_config stk7700p_xc4000_pll_config = {
-	60000, 30000,	/* internal, sampling */
-	1, 8, 3, 1, 0,	/* pll_cfg: prediv, ratio, range, reset, bypass */
-	0, 0, 1, 1, 0,	/* misc: refdiv, bypclk_div, IO_CLK_en_core, */
-			/* ADClkSrc, modulo */
-	(3 << 14) | (1 << 12) | 524,	/* sad_cfg: refsel, sel, freq_15k */
-	39370534,	/* ifreq */
-	20452225,	/* timf */
-	30000000	/* xtal */
-};
-
-/* FIXME: none of these inputs are validated yet */
-static struct dib7000p_config pctv_340e_config = {
-	.output_mpeg2_in_188_bytes = 1,
-
-	.agc_config_count = 1,
-	.agc = &stk7700p_7000p_xc4000_agc_config,
-	.bw  = &stk7700p_xc4000_pll_config,
-
-	.gpio_dir = DIB7000M_GPIO_DEFAULT_DIRECTIONS,
-	.gpio_val = DIB7000M_GPIO_DEFAULT_VALUES,
-	.gpio_pwm_pos = DIB7000M_GPIO_DEFAULT_PWM_POS,
-};
-
-/* PCTV 340e GPIOs map:
-   dib0700:
-   GPIO2  - CX25843 sleep
-   GPIO3  - CS5340 reset
-   GPIO5  - IRD
-   GPIO6  - Power Supply
-   GPIO8  - LNA (1=off 0=on)
-   GPIO10 - CX25843 reset
-   dib7000:
-   GPIO8  - xc4000 reset
- */
-static int pctv340e_frontend_attach(struct dvb_usb_adapter *adap)
-{
-	struct dib0700_state *st = adap->dev->priv;
-
-	/* Power Supply on */
-	dib0700_set_gpio(adap->dev, GPIO6,  GPIO_OUT, 0);
-	msleep(50);
-	dib0700_set_gpio(adap->dev, GPIO6,  GPIO_OUT, 1);
-	msleep(100); /* Allow power supply to settle before probing */
-
-	/* cx25843 reset */
-	dib0700_set_gpio(adap->dev, GPIO10,  GPIO_OUT, 0);
-	msleep(1); /* cx25843 datasheet say 350us required */
-	dib0700_set_gpio(adap->dev, GPIO10,  GPIO_OUT, 1);
-
-	/* LNA off for now */
-	dib0700_set_gpio(adap->dev, GPIO8,  GPIO_OUT, 1);
-
-	/* Put the CX25843 to sleep for now since we're in digital mode */
-	dib0700_set_gpio(adap->dev, GPIO2, GPIO_OUT, 1);
-
-	/* FIXME: not verified yet */
-	dib0700_ctrl_clock(adap->dev, 72, 1);
-
-	msleep(500);
-
-	if (dib7000pc_detection(&adap->dev->i2c_adap) == 0) {
-		/* Demodulator not found for some reason? */
-		return -ENODEV;
-	}
-
-	adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x12,
-			      &pctv_340e_config);
-	st->is_dib7000pc = 1;
-
-	return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
-}
-
-static struct xc4000_config dib7000p_xc4000_tunerconfig = {
-	.i2c_address	  = 0x61,
-	.default_pm	  = 1,
-	.dvb_amplitude	  = 0,
-	.set_smoothedcvbs = 0,
-	.if_khz		  = 5400
-};
-
-static int xc4000_tuner_attach(struct dvb_usb_adapter *adap)
-{
-	struct i2c_adapter *tun_i2c;
-
-	/* The xc4000 is not on the main i2c bus */
-	tun_i2c = dib7000p_get_i2c_master(adap->fe_adap[0].fe,
-					  DIBX000_I2C_INTERFACE_TUNER, 1);
-	if (tun_i2c == NULL) {
-		printk(KERN_ERR "Could not reach tuner i2c bus\n");
-		return 0;
-	}
-
-	/* Setup the reset callback */
-	adap->fe_adap[0].fe->callback = dib0700_xc4000_tuner_callback;
-
-	return dvb_attach(xc4000_attach, adap->fe_adap[0].fe, tun_i2c,
-			  &dib7000p_xc4000_tunerconfig)
-		== 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_adap[0].fe = dvb_attach(lgdt3305_attach,
-			      &hcw_lgdt3305_config,
-			      &adap->dev->i2c_adap);
-
-	return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
-}
-
-static int mxl5007t_tuner_attach(struct dvb_usb_adapter *adap)
-{
-	return dvb_attach(mxl5007t_attach, adap->fe_adap[0].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) },
-	{ USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_STK7700P_PC) },
-	{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500) },
-	{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500_2) },
-	{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK) },
-/* 5 */	{ USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR) },
-	{ USB_DEVICE(USB_VID_COMPRO,    USB_PID_COMPRO_VIDEOMATE_U500) },
-	{ USB_DEVICE(USB_VID_UNIWILL,   USB_PID_UNIWILL_STK7700P) },
-	{ USB_DEVICE(USB_VID_LEADTEK,   USB_PID_WINFAST_DTV_DONGLE_STK7700P) },
-	{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK_2) },
-/* 10 */{ USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_2) },
-	{ USB_DEVICE(USB_VID_PINNACLE,  USB_PID_PINNACLE_PCTV2000E) },
-	{ USB_DEVICE(USB_VID_TERRATEC,
-			USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY) },
-	{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_TD_STICK) },
-	{ USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_STK7700D) },
-/* 15 */{ USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_STK7070P) },
-	{ USB_DEVICE(USB_VID_PINNACLE,  USB_PID_PINNACLE_PCTV_DVB_T_FLASH) },
-	{ USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_STK7070PD) },
-	{ USB_DEVICE(USB_VID_PINNACLE,
-			USB_PID_PINNACLE_PCTV_DUAL_DIVERSITY_DVB_T) },
-	{ USB_DEVICE(USB_VID_COMPRO,    USB_PID_COMPRO_VIDEOMATE_U500_PC) },
-/* 20 */{ USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_EXPRESS) },
-	{ USB_DEVICE(USB_VID_GIGABYTE,  USB_PID_GIGABYTE_U7000) },
-	{ USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ARTEC_T14BR) },
-	{ USB_DEVICE(USB_VID_ASUS,      USB_PID_ASUS_U3000) },
-	{ USB_DEVICE(USB_VID_ASUS,      USB_PID_ASUS_U3100) },
-/* 25 */{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK_3) },
-	{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_MYTV_T) },
-	{ USB_DEVICE(USB_VID_TERRATEC,  USB_PID_TERRATEC_CINERGY_HT_USB_XE) },
-	{ USB_DEVICE(USB_VID_PINNACLE,	USB_PID_PINNACLE_EXPRESSCARD_320CX) },
-	{ USB_DEVICE(USB_VID_PINNACLE,	USB_PID_PINNACLE_PCTV72E) },
-/* 30 */{ USB_DEVICE(USB_VID_PINNACLE,	USB_PID_PINNACLE_PCTV73E) },
-	{ USB_DEVICE(USB_VID_YUAN,	USB_PID_YUAN_EC372S) },
-	{ USB_DEVICE(USB_VID_TERRATEC,	USB_PID_TERRATEC_CINERGY_HT_EXPRESS) },
-	{ USB_DEVICE(USB_VID_TERRATEC,	USB_PID_TERRATEC_CINERGY_T_XXS) },
-	{ USB_DEVICE(USB_VID_LEADTEK,   USB_PID_WINFAST_DTV_DONGLE_STK7700P_2) },
-/* 35 */{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_TD_STICK_52009) },
-	{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500_3) },
-	{ USB_DEVICE(USB_VID_GIGABYTE,  USB_PID_GIGABYTE_U8000) },
-	{ USB_DEVICE(USB_VID_YUAN,      USB_PID_YUAN_STK7700PH) },
-	{ USB_DEVICE(USB_VID_ASUS,	USB_PID_ASUS_U3000H) },
-/* 40 */{ USB_DEVICE(USB_VID_PINNACLE,  USB_PID_PINNACLE_PCTV801E) },
-	{ USB_DEVICE(USB_VID_PINNACLE,  USB_PID_PINNACLE_PCTV801E_SE) },
-	{ 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) },
-/* 50 */{ USB_DEVICE(USB_VID_ELGATO,	USB_PID_ELGATO_EYETV_DTT_Dlx) },
-	{ USB_DEVICE(USB_VID_LEADTEK,   USB_PID_WINFAST_DTV_DONGLE_H) },
-	{ USB_DEVICE(USB_VID_TERRATEC,	USB_PID_TERRATEC_T3) },
-	{ USB_DEVICE(USB_VID_TERRATEC,	USB_PID_TERRATEC_T5) },
-	{ USB_DEVICE(USB_VID_YUAN,      USB_PID_YUAN_STK7700D) },
-/* 55 */{ USB_DEVICE(USB_VID_YUAN,	USB_PID_YUAN_STK7700D_2) },
-	{ USB_DEVICE(USB_VID_PINNACLE,	USB_PID_PINNACLE_PCTV73A) },
-	{ USB_DEVICE(USB_VID_PCTV,	USB_PID_PINNACLE_PCTV73ESE) },
-	{ USB_DEVICE(USB_VID_PCTV,	USB_PID_PINNACLE_PCTV282E) },
-	{ USB_DEVICE(USB_VID_DIBCOM,	USB_PID_DIBCOM_STK7770P) },
-/* 60 */{ USB_DEVICE(USB_VID_TERRATEC,	USB_PID_TERRATEC_CINERGY_T_XXS_2) },
-	{ USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_STK807XPVR) },
-	{ USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_STK807XP) },
-	{ USB_DEVICE_VER(USB_VID_PIXELVIEW, USB_PID_PIXELVIEW_SBTVD, 0x000, 0x3f00) },
-	{ USB_DEVICE(USB_VID_EVOLUTEPC, USB_PID_TVWAY_PLUS) },
-/* 65 */{ USB_DEVICE(USB_VID_PINNACLE,	USB_PID_PINNACLE_PCTV73ESE) },
-	{ USB_DEVICE(USB_VID_PINNACLE,	USB_PID_PINNACLE_PCTV282E) },
-	{ USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_STK8096GP) },
-	{ USB_DEVICE(USB_VID_ELGATO,    USB_PID_ELGATO_EYETV_DIVERSITY) },
-	{ USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_NIM9090M) },
-/* 70 */{ USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_NIM8096MD) },
-	{ USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_NIM9090MD) },
-	{ USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_NIM7090) },
-	{ USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_TFE7090PVR) },
-	{ USB_DEVICE(USB_VID_TECHNISAT, USB_PID_TECHNISAT_AIRSTAR_TELESTICK_2) },
-/* 75 */{ USB_DEVICE(USB_VID_MEDION,    USB_PID_CREATIX_CTX1921) },
-	{ USB_DEVICE(USB_VID_PINNACLE,  USB_PID_PINNACLE_PCTV340E) },
-	{ USB_DEVICE(USB_VID_PINNACLE,  USB_PID_PINNACLE_PCTV340E_SE) },
-	{ USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_TFE7090E) },
-	{ USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_TFE7790E) },
-/* 80 */{ USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_TFE8096P) },
-	{ USB_DEVICE(USB_VID_ELGATO,	USB_PID_ELGATO_EYETV_DTT_2) },
-	{ 0 }		/* Terminating entry */
-};
-MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table);
-
-#define DIB0700_DEFAULT_DEVICE_PROPERTIES \
-	.caps              = DVB_USB_IS_AN_I2C_ADAPTER, \
-	.usb_ctrl          = DEVICE_SPECIFIC, \
-	.firmware          = "dvb-usb-dib0700-1.20.fw", \
-	.download_firmware = dib0700_download_firmware, \
-	.no_reconnect      = 1, \
-	.size_of_priv      = sizeof(struct dib0700_state), \
-	.i2c_algo          = &dib0700_i2c_algo, \
-	.identify_state    = dib0700_identify_state
-
-#define DIB0700_DEFAULT_STREAMING_CONFIG(ep) \
-	.streaming_ctrl   = dib0700_streaming_ctrl, \
-	.stream = { \
-		.type = USB_BULK, \
-		.count = 4, \
-		.endpoint = ep, \
-		.u = { \
-			.bulk = { \
-				.buffersize = 39480, \
-			} \
-		} \
-	}
-
-struct dvb_usb_device_properties dib0700_devices[] = {
-	{
-		DIB0700_DEFAULT_DEVICE_PROPERTIES,
-
-		.num_adapters = 1,
-		.adapter = {
-			{
-			.num_frontends = 1,
-			.fe = {{
-				.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
-				.pid_filter_count = 32,
-				.pid_filter       = stk7700p_pid_filter,
-				.pid_filter_ctrl  = stk7700p_pid_filter_ctrl,
-				.frontend_attach  = stk7700p_frontend_attach,
-				.tuner_attach     = stk7700p_tuner_attach,
-
-				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-			}},
-			},
-		},
-
-		.num_device_descs = 8,
-		.devices = {
-			{   "DiBcom STK7700P reference design",
-				{ &dib0700_usb_id_table[0], &dib0700_usb_id_table[1] },
-				{ NULL },
-			},
-			{   "Hauppauge Nova-T Stick",
-				{ &dib0700_usb_id_table[4], &dib0700_usb_id_table[9], NULL },
-				{ NULL },
-			},
-			{   "AVerMedia AVerTV DVB-T Volar",
-				{ &dib0700_usb_id_table[5], &dib0700_usb_id_table[10] },
-				{ NULL },
-			},
-			{   "Compro Videomate U500",
-				{ &dib0700_usb_id_table[6], &dib0700_usb_id_table[19] },
-				{ NULL },
-			},
-			{   "Uniwill STK7700P based (Hama and others)",
-				{ &dib0700_usb_id_table[7], NULL },
-				{ NULL },
-			},
-			{   "Leadtek Winfast DTV Dongle (STK7700P based)",
-				{ &dib0700_usb_id_table[8], &dib0700_usb_id_table[34] },
-				{ NULL },
-			},
-			{   "AVerMedia AVerTV DVB-T Express",
-				{ &dib0700_usb_id_table[20] },
-				{ NULL },
-			},
-			{   "Gigabyte U7000",
-				{ &dib0700_usb_id_table[21], NULL },
-				{ NULL },
-			}
-		},
-
-		.rc.core = {
-			.rc_interval      = DEFAULT_RC_INTERVAL,
-			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
-			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
-			.change_protocol  = dib0700_change_protocol,
-		},
-	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
-
-		.num_adapters = 2,
-		.adapter = {
-			{
-			.num_frontends = 1,
-			.fe = {{
-				.frontend_attach  = bristol_frontend_attach,
-				.tuner_attach     = bristol_tuner_attach,
-
-				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-			}},
-			}, {
-			.num_frontends = 1,
-			.fe = {{
-				.frontend_attach  = bristol_frontend_attach,
-				.tuner_attach     = bristol_tuner_attach,
-
-				DIB0700_DEFAULT_STREAMING_CONFIG(0x03),
-			}},
-			}
-		},
-
-		.num_device_descs = 1,
-		.devices = {
-			{   "Hauppauge Nova-T 500 Dual DVB-T",
-				{ &dib0700_usb_id_table[2], &dib0700_usb_id_table[3], NULL },
-				{ NULL },
-			},
-		},
-
-		.rc.core = {
-			.rc_interval      = DEFAULT_RC_INTERVAL,
-			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
-			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
-			.change_protocol = dib0700_change_protocol,
-		},
-	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
-
-		.num_adapters = 2,
-		.adapter = {
-			{
-			.num_frontends = 1,
-			.fe = {{
-				.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
-				.pid_filter_count = 32,
-				.pid_filter       = stk70x0p_pid_filter,
-				.pid_filter_ctrl  = stk70x0p_pid_filter_ctrl,
-				.frontend_attach  = stk7700d_frontend_attach,
-				.tuner_attach     = stk7700d_tuner_attach,
-
-				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-			}},
-			}, {
-			.num_frontends = 1,
-			.fe = {{
-				.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
-				.pid_filter_count = 32,
-				.pid_filter       = stk70x0p_pid_filter,
-				.pid_filter_ctrl  = stk70x0p_pid_filter_ctrl,
-				.frontend_attach  = stk7700d_frontend_attach,
-				.tuner_attach     = stk7700d_tuner_attach,
-
-				DIB0700_DEFAULT_STREAMING_CONFIG(0x03),
-			}},
-			}
-		},
-
-		.num_device_descs = 5,
-		.devices = {
-			{   "Pinnacle PCTV 2000e",
-				{ &dib0700_usb_id_table[11], NULL },
-				{ NULL },
-			},
-			{   "Terratec Cinergy DT XS Diversity",
-				{ &dib0700_usb_id_table[12], NULL },
-				{ NULL },
-			},
-			{   "Hauppauge Nova-TD Stick/Elgato Eye-TV Diversity",
-				{ &dib0700_usb_id_table[13], NULL },
-				{ NULL },
-			},
-			{   "DiBcom STK7700D reference design",
-				{ &dib0700_usb_id_table[14], NULL },
-				{ NULL },
-			},
-			{   "YUAN High-Tech DiBcom STK7700D",
-				{ &dib0700_usb_id_table[55], NULL },
-				{ NULL },
-			},
-
-		},
-
-		.rc.core = {
-			.rc_interval      = DEFAULT_RC_INTERVAL,
-			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
-			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
-			.change_protocol = dib0700_change_protocol,
-		},
-	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
-
-		.num_adapters = 1,
-		.adapter = {
-			{
-			.num_frontends = 1,
-			.fe = {{
-				.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
-				.pid_filter_count = 32,
-				.pid_filter       = stk70x0p_pid_filter,
-				.pid_filter_ctrl  = stk70x0p_pid_filter_ctrl,
-				.frontend_attach  = stk7700P2_frontend_attach,
-				.tuner_attach     = stk7700d_tuner_attach,
-
-				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-			}},
-			},
-		},
-
-		.num_device_descs = 3,
-		.devices = {
-			{   "ASUS My Cinema U3000 Mini DVBT Tuner",
-				{ &dib0700_usb_id_table[23], NULL },
-				{ NULL },
-			},
-			{   "Yuan EC372S",
-				{ &dib0700_usb_id_table[31], NULL },
-				{ NULL },
-			},
-			{   "Terratec Cinergy T Express",
-				{ &dib0700_usb_id_table[42], NULL },
-				{ NULL },
-			}
-		},
-
-		.rc.core = {
-			.rc_interval      = DEFAULT_RC_INTERVAL,
-			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
-			.module_name	  = "dib0700",
-			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
-			.change_protocol = dib0700_change_protocol,
-		},
-	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
-
-		.num_adapters = 1,
-		.adapter = {
-			{
-			.num_frontends = 1,
-			.fe = {{
-				.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
-				.pid_filter_count = 32,
-				.pid_filter       = stk70x0p_pid_filter,
-				.pid_filter_ctrl  = stk70x0p_pid_filter_ctrl,
-				.frontend_attach  = stk7070p_frontend_attach,
-				.tuner_attach     = dib7070p_tuner_attach,
-
-				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-			}},
-				.size_of_priv     = sizeof(struct dib0700_adapter_state),
-			},
-		},
-
-		.num_device_descs = 12,
-		.devices = {
-			{   "DiBcom STK7070P reference design",
-				{ &dib0700_usb_id_table[15], NULL },
-				{ NULL },
-			},
-			{   "Pinnacle PCTV DVB-T Flash Stick",
-				{ &dib0700_usb_id_table[16], NULL },
-				{ NULL },
-			},
-			{   "Artec T14BR DVB-T",
-				{ &dib0700_usb_id_table[22], NULL },
-				{ NULL },
-			},
-			{   "ASUS My Cinema U3100 Mini DVBT Tuner",
-				{ &dib0700_usb_id_table[24], NULL },
-				{ NULL },
-			},
-			{   "Hauppauge Nova-T Stick",
-				{ &dib0700_usb_id_table[25], NULL },
-				{ NULL },
-			},
-			{   "Hauppauge Nova-T MyTV.t",
-				{ &dib0700_usb_id_table[26], NULL },
-				{ NULL },
-			},
-			{   "Pinnacle PCTV 72e",
-				{ &dib0700_usb_id_table[29], NULL },
-				{ NULL },
-			},
-			{   "Pinnacle PCTV 73e",
-				{ &dib0700_usb_id_table[30], NULL },
-				{ NULL },
-			},
-			{   "Elgato EyeTV DTT",
-				{ &dib0700_usb_id_table[49], NULL },
-				{ NULL },
-			},
-			{   "Yuan PD378S",
-				{ &dib0700_usb_id_table[45], NULL },
-				{ NULL },
-			},
-			{   "Elgato EyeTV Dtt Dlx PD378S",
-				{ &dib0700_usb_id_table[50], NULL },
-				{ NULL },
-			},
-			{   "Elgato EyeTV DTT rev. 2",
-				{ &dib0700_usb_id_table[81], NULL },
-				{ NULL },
-			},
-		},
-
-		.rc.core = {
-			.rc_interval      = DEFAULT_RC_INTERVAL,
-			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
-			.module_name	  = "dib0700",
-			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
-			.change_protocol  = dib0700_change_protocol,
-		},
-	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
-
-		.num_adapters = 1,
-		.adapter = {
-			{
-			.num_frontends = 1,
-			.fe = {{
-				.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
-				.pid_filter_count = 32,
-				.pid_filter       = stk70x0p_pid_filter,
-				.pid_filter_ctrl  = stk70x0p_pid_filter_ctrl,
-				.frontend_attach  = stk7070p_frontend_attach,
-				.tuner_attach     = dib7070p_tuner_attach,
-
-				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-			}},
-				.size_of_priv     = sizeof(struct dib0700_adapter_state),
-			},
-		},
-
-		.num_device_descs = 3,
-		.devices = {
-			{   "Pinnacle PCTV 73A",
-				{ &dib0700_usb_id_table[56], NULL },
-				{ NULL },
-			},
-			{   "Pinnacle PCTV 73e SE",
-				{ &dib0700_usb_id_table[57], &dib0700_usb_id_table[65], NULL },
-				{ NULL },
-			},
-			{   "Pinnacle PCTV 282e",
-				{ &dib0700_usb_id_table[58], &dib0700_usb_id_table[66], NULL },
-				{ NULL },
-			},
-		},
-
-		.rc.core = {
-			.rc_interval      = DEFAULT_RC_INTERVAL,
-			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
-			.module_name	  = "dib0700",
-			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
-			.change_protocol  = dib0700_change_protocol,
-		},
-	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
-
-		.num_adapters = 2,
-		.adapter = {
-			{
-			.num_frontends = 1,
-			.fe = {{
-				.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
-				.pid_filter_count = 32,
-				.pid_filter       = stk70x0p_pid_filter,
-				.pid_filter_ctrl  = stk70x0p_pid_filter_ctrl,
-				.frontend_attach  = novatd_frontend_attach,
-				.tuner_attach     = dib7070p_tuner_attach,
-
-				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-			}},
-				.size_of_priv     = sizeof(struct dib0700_adapter_state),
-			}, {
-			.num_frontends = 1,
-			.fe = {{
-				.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
-				.pid_filter_count = 32,
-				.pid_filter       = stk70x0p_pid_filter,
-				.pid_filter_ctrl  = stk70x0p_pid_filter_ctrl,
-				.frontend_attach  = novatd_frontend_attach,
-				.tuner_attach     = dib7070p_tuner_attach,
-
-				DIB0700_DEFAULT_STREAMING_CONFIG(0x03),
-			}},
-				.size_of_priv     = sizeof(struct dib0700_adapter_state),
-			}
-		},
-
-		.num_device_descs = 1,
-		.devices = {
-			{   "Hauppauge Nova-TD Stick (52009)",
-				{ &dib0700_usb_id_table[35], NULL },
-				{ NULL },
-			},
-		},
-
-		.rc.core = {
-			.rc_interval      = DEFAULT_RC_INTERVAL,
-			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
-			.module_name	  = "dib0700",
-			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
-			.change_protocol = dib0700_change_protocol,
-		},
-	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
-
-		.num_adapters = 2,
-		.adapter = {
-			{
-			.num_frontends = 1,
-			.fe = {{
-				.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
-				.pid_filter_count = 32,
-				.pid_filter       = stk70x0p_pid_filter,
-				.pid_filter_ctrl  = stk70x0p_pid_filter_ctrl,
-				.frontend_attach  = stk7070pd_frontend_attach0,
-				.tuner_attach     = dib7070p_tuner_attach,
-
-				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-			}},
-				.size_of_priv     = sizeof(struct dib0700_adapter_state),
-			}, {
-			.num_frontends = 1,
-			.fe = {{
-				.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
-				.pid_filter_count = 32,
-				.pid_filter       = stk70x0p_pid_filter,
-				.pid_filter_ctrl  = stk70x0p_pid_filter_ctrl,
-				.frontend_attach  = stk7070pd_frontend_attach1,
-				.tuner_attach     = dib7070p_tuner_attach,
-
-				DIB0700_DEFAULT_STREAMING_CONFIG(0x03),
-			}},
-				.size_of_priv     = sizeof(struct dib0700_adapter_state),
-			}
-		},
-
-		.num_device_descs = 5,
-		.devices = {
-			{   "DiBcom STK7070PD reference design",
-				{ &dib0700_usb_id_table[17], NULL },
-				{ NULL },
-			},
-			{   "Pinnacle PCTV Dual DVB-T Diversity Stick",
-				{ &dib0700_usb_id_table[18], NULL },
-				{ NULL },
-			},
-			{   "Hauppauge Nova-TD-500 (84xxx)",
-				{ &dib0700_usb_id_table[36], NULL },
-				{ NULL },
-			},
-			{  "Terratec Cinergy DT USB XS Diversity/ T5",
-				{ &dib0700_usb_id_table[43],
-					&dib0700_usb_id_table[53], NULL},
-				{ NULL },
-			},
-			{  "Sony PlayTV",
-				{ &dib0700_usb_id_table[44], NULL },
-				{ NULL },
-			},
-		},
-
-		.rc.core = {
-			.rc_interval      = DEFAULT_RC_INTERVAL,
-			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
-			.module_name	  = "dib0700",
-			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
-			.change_protocol = dib0700_change_protocol,
-		},
-	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
-
-		.num_adapters = 2,
-		.adapter = {
-			{
-			.num_frontends = 1,
-			.fe = {{
-				.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
-				.pid_filter_count = 32,
-				.pid_filter       = stk70x0p_pid_filter,
-				.pid_filter_ctrl  = stk70x0p_pid_filter_ctrl,
-				.frontend_attach  = stk7070pd_frontend_attach0,
-				.tuner_attach     = dib7070p_tuner_attach,
-
-				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-			}},
-				.size_of_priv     = sizeof(struct dib0700_adapter_state),
-			}, {
-			.num_frontends = 1,
-			.fe = {{
-				.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
-				.pid_filter_count = 32,
-				.pid_filter       = stk70x0p_pid_filter,
-				.pid_filter_ctrl  = stk70x0p_pid_filter_ctrl,
-				.frontend_attach  = stk7070pd_frontend_attach1,
-				.tuner_attach     = dib7070p_tuner_attach,
-
-				DIB0700_DEFAULT_STREAMING_CONFIG(0x03),
-			}},
-				.size_of_priv     = sizeof(struct dib0700_adapter_state),
-			}
-		},
-
-		.num_device_descs = 1,
-		.devices = {
-			{   "Elgato EyeTV Diversity",
-				{ &dib0700_usb_id_table[68], NULL },
-				{ NULL },
-			},
-		},
-
-		.rc.core = {
-			.rc_interval      = DEFAULT_RC_INTERVAL,
-			.rc_codes         = RC_MAP_DIB0700_NEC_TABLE,
-			.module_name	  = "dib0700",
-			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
-			.change_protocol  = dib0700_change_protocol,
-		},
-	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
-
-		.num_adapters = 1,
-		.adapter = {
-			{
-			.num_frontends = 1,
-			.fe = {{
-				.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
-				.pid_filter_count = 32,
-				.pid_filter       = stk70x0p_pid_filter,
-				.pid_filter_ctrl  = stk70x0p_pid_filter_ctrl,
-				.frontend_attach  = stk7700ph_frontend_attach,
-				.tuner_attach     = stk7700ph_tuner_attach,
-
-				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-			}},
-				.size_of_priv = sizeof(struct
-						dib0700_adapter_state),
-			},
-		},
-
-		.num_device_descs = 9,
-		.devices = {
-			{   "Terratec Cinergy HT USB XE",
-				{ &dib0700_usb_id_table[27], NULL },
-				{ NULL },
-			},
-			{   "Pinnacle Expresscard 320cx",
-				{ &dib0700_usb_id_table[28], NULL },
-				{ NULL },
-			},
-			{   "Terratec Cinergy HT Express",
-				{ &dib0700_usb_id_table[32], NULL },
-				{ NULL },
-			},
-			{   "Gigabyte U8000-RH",
-				{ &dib0700_usb_id_table[37], NULL },
-				{ NULL },
-			},
-			{   "YUAN High-Tech STK7700PH",
-				{ &dib0700_usb_id_table[38], NULL },
-				{ NULL },
-			},
-			{   "Asus My Cinema-U3000Hybrid",
-				{ &dib0700_usb_id_table[39], NULL },
-				{ NULL },
-			},
-			{   "YUAN High-Tech MC770",
-				{ &dib0700_usb_id_table[48], NULL },
-				{ NULL },
-			},
-			{   "Leadtek WinFast DTV Dongle H",
-				{ &dib0700_usb_id_table[51], NULL },
-				{ NULL },
-			},
-			{   "YUAN High-Tech STK7700D",
-				{ &dib0700_usb_id_table[54], NULL },
-				{ NULL },
-			},
-		},
-
-		.rc.core = {
-			.rc_interval      = DEFAULT_RC_INTERVAL,
-			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
-			.module_name	  = "dib0700",
-			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
-			.change_protocol  = dib0700_change_protocol,
-		},
-	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
-		.num_adapters = 1,
-		.adapter = {
-			{
-			.num_frontends = 1,
-			.fe = {{
-				.frontend_attach  = s5h1411_frontend_attach,
-				.tuner_attach     = xc5000_tuner_attach,
-
-				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-			}},
-				.size_of_priv = sizeof(struct
-						dib0700_adapter_state),
-			},
-		},
-
-		.num_device_descs = 2,
-		.devices = {
-			{   "Pinnacle PCTV HD Pro USB Stick",
-				{ &dib0700_usb_id_table[40], NULL },
-				{ NULL },
-			},
-			{   "Pinnacle PCTV HD USB Stick",
-				{ &dib0700_usb_id_table[41], NULL },
-				{ NULL },
-			},
-		},
-
-		.rc.core = {
-			.rc_interval      = DEFAULT_RC_INTERVAL,
-			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
-			.module_name	  = "dib0700",
-			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
-			.change_protocol  = dib0700_change_protocol,
-		},
-	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
-		.num_adapters = 1,
-		.adapter = {
-			{
-			.num_frontends = 1,
-			.fe = {{
-				.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 },
-			},
-		},
-	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
-
-		.num_adapters = 1,
-		.adapter = {
-			{
-			.num_frontends = 1,
-			.fe = {{
-				.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
-				.pid_filter_count = 32,
-				.pid_filter       = stk70x0p_pid_filter,
-				.pid_filter_ctrl  = stk70x0p_pid_filter_ctrl,
-				.frontend_attach  = stk7770p_frontend_attach,
-				.tuner_attach     = dib7770p_tuner_attach,
-
-				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-			}},
-				.size_of_priv =
-					sizeof(struct dib0700_adapter_state),
-			},
-		},
-
-		.num_device_descs = 4,
-		.devices = {
-			{   "DiBcom STK7770P reference design",
-				{ &dib0700_usb_id_table[59], NULL },
-				{ NULL },
-			},
-			{   "Terratec Cinergy T USB XXS (HD)/ T3",
-				{ &dib0700_usb_id_table[33],
-					&dib0700_usb_id_table[52],
-					&dib0700_usb_id_table[60], NULL},
-				{ NULL },
-			},
-			{   "TechniSat AirStar TeleStick 2",
-				{ &dib0700_usb_id_table[74], NULL },
-				{ NULL },
-			},
-			{   "Medion CTX1921 DVB-T USB",
-				{ &dib0700_usb_id_table[75], NULL },
-				{ NULL },
-			},
-		},
-
-		.rc.core = {
-			.rc_interval      = DEFAULT_RC_INTERVAL,
-			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
-			.module_name	  = "dib0700",
-			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
-			.change_protocol  = dib0700_change_protocol,
-		},
-	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
-		.num_adapters = 1,
-		.adapter = {
-			{
-			.num_frontends = 1,
-			.fe = {{
-				.caps  = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
-				.pid_filter_count = 32,
-				.pid_filter = stk80xx_pid_filter,
-				.pid_filter_ctrl = stk80xx_pid_filter_ctrl,
-				.frontend_attach  = stk807x_frontend_attach,
-				.tuner_attach     = dib807x_tuner_attach,
-
-				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-			}},
-				.size_of_priv =
-					sizeof(struct dib0700_adapter_state),
-			},
-		},
-
-		.num_device_descs = 3,
-		.devices = {
-			{   "DiBcom STK807xP reference design",
-				{ &dib0700_usb_id_table[62], NULL },
-				{ NULL },
-			},
-			{   "Prolink Pixelview SBTVD",
-				{ &dib0700_usb_id_table[63], NULL },
-				{ NULL },
-			},
-			{   "EvolutePC TVWay+",
-				{ &dib0700_usb_id_table[64], NULL },
-				{ NULL },
-			},
-		},
-
-		.rc.core = {
-			.rc_interval      = DEFAULT_RC_INTERVAL,
-			.rc_codes         = RC_MAP_DIB0700_NEC_TABLE,
-			.module_name	  = "dib0700",
-			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
-			.change_protocol  = dib0700_change_protocol,
-		},
-	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
-		.num_adapters = 2,
-		.adapter = {
-			{
-			.num_frontends = 1,
-			.fe = {{
-				.caps  = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
-				.pid_filter_count = 32,
-				.pid_filter = stk80xx_pid_filter,
-				.pid_filter_ctrl = stk80xx_pid_filter_ctrl,
-				.frontend_attach  = stk807xpvr_frontend_attach0,
-				.tuner_attach     = dib807x_tuner_attach,
-
-				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-			}},
-				.size_of_priv =
-					sizeof(struct dib0700_adapter_state),
-			},
-			{
-			.num_frontends = 1,
-			.fe = {{
-				.caps  = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
-				.pid_filter_count = 32,
-				.pid_filter = stk80xx_pid_filter,
-				.pid_filter_ctrl = stk80xx_pid_filter_ctrl,
-				.frontend_attach  = stk807xpvr_frontend_attach1,
-				.tuner_attach     = dib807x_tuner_attach,
-
-				DIB0700_DEFAULT_STREAMING_CONFIG(0x03),
-			}},
-				.size_of_priv =
-					sizeof(struct dib0700_adapter_state),
-			},
-		},
-
-		.num_device_descs = 1,
-		.devices = {
-			{   "DiBcom STK807xPVR reference design",
-				{ &dib0700_usb_id_table[61], NULL },
-				{ NULL },
-			},
-		},
-
-		.rc.core = {
-			.rc_interval      = DEFAULT_RC_INTERVAL,
-			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
-			.module_name	  = "dib0700",
-			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
-			.change_protocol  = dib0700_change_protocol,
-		},
-	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
-		.num_adapters = 1,
-		.adapter = {
-			{
-			.num_frontends = 1,
-			.fe = {{
-				.caps  = DVB_USB_ADAP_HAS_PID_FILTER |
-					DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
-				.pid_filter_count = 32,
-				.pid_filter = stk80xx_pid_filter,
-				.pid_filter_ctrl = stk80xx_pid_filter_ctrl,
-				.frontend_attach  = stk809x_frontend_attach,
-				.tuner_attach     = dib809x_tuner_attach,
-
-				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-			}},
-				.size_of_priv =
-					sizeof(struct dib0700_adapter_state),
-			},
-		},
-
-		.num_device_descs = 1,
-		.devices = {
-			{   "DiBcom STK8096GP reference design",
-				{ &dib0700_usb_id_table[67], NULL },
-				{ NULL },
-			},
-		},
-
-		.rc.core = {
-			.rc_interval      = DEFAULT_RC_INTERVAL,
-			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
-			.module_name	  = "dib0700",
-			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
-			.change_protocol  = dib0700_change_protocol,
-		},
-	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
-		.num_adapters = 1,
-		.adapter = {
-			{
-			.num_frontends = 1,
-			.fe = {{
-				.caps  = DVB_USB_ADAP_HAS_PID_FILTER |
-					DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
-				.pid_filter_count = 32,
-				.pid_filter = dib90x0_pid_filter,
-				.pid_filter_ctrl = dib90x0_pid_filter_ctrl,
-				.frontend_attach  = stk9090m_frontend_attach,
-				.tuner_attach     = dib9090_tuner_attach,
-
-				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-			}},
-				.size_of_priv =
-					sizeof(struct dib0700_adapter_state),
-			},
-		},
-
-		.num_device_descs = 1,
-		.devices = {
-			{   "DiBcom STK9090M reference design",
-				{ &dib0700_usb_id_table[69], NULL },
-				{ NULL },
-			},
-		},
-
-		.rc.core = {
-			.rc_interval      = DEFAULT_RC_INTERVAL,
-			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
-			.module_name	  = "dib0700",
-			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
-			.change_protocol  = dib0700_change_protocol,
-		},
-	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
-		.num_adapters = 1,
-		.adapter = {
-			{
-			.num_frontends = 1,
-			.fe = {{
-				.caps  = DVB_USB_ADAP_HAS_PID_FILTER |
-					DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
-				.pid_filter_count = 32,
-				.pid_filter = stk80xx_pid_filter,
-				.pid_filter_ctrl = stk80xx_pid_filter_ctrl,
-				.frontend_attach  = nim8096md_frontend_attach,
-				.tuner_attach     = nim8096md_tuner_attach,
-
-				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-			}},
-				.size_of_priv =
-					sizeof(struct dib0700_adapter_state),
-			},
-		},
-
-		.num_device_descs = 1,
-		.devices = {
-			{   "DiBcom NIM8096MD reference design",
-				{ &dib0700_usb_id_table[70], NULL },
-				{ NULL },
-			},
-		},
-
-		.rc.core = {
-			.rc_interval      = DEFAULT_RC_INTERVAL,
-			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
-			.module_name	  = "dib0700",
-			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
-			.change_protocol  = dib0700_change_protocol,
-		},
-	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
-		.num_adapters = 1,
-		.adapter = {
-			{
-			.num_frontends = 1,
-			.fe = {{
-				.caps  = DVB_USB_ADAP_HAS_PID_FILTER |
-					DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
-				.pid_filter_count = 32,
-				.pid_filter = dib90x0_pid_filter,
-				.pid_filter_ctrl = dib90x0_pid_filter_ctrl,
-				.frontend_attach  = nim9090md_frontend_attach,
-				.tuner_attach     = nim9090md_tuner_attach,
-
-				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-			}},
-				.size_of_priv =
-					sizeof(struct dib0700_adapter_state),
-			},
-		},
-
-		.num_device_descs = 1,
-		.devices = {
-			{   "DiBcom NIM9090MD reference design",
-				{ &dib0700_usb_id_table[71], NULL },
-				{ NULL },
-			},
-		},
-
-		.rc.core = {
-			.rc_interval      = DEFAULT_RC_INTERVAL,
-			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
-			.module_name	  = "dib0700",
-			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
-			.change_protocol  = dib0700_change_protocol,
-		},
-	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
-		.num_adapters = 1,
-		.adapter = {
-			{
-			.num_frontends = 1,
-			.fe = {{
-				.caps  = DVB_USB_ADAP_HAS_PID_FILTER |
-					DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
-				.pid_filter_count = 32,
-				.pid_filter = stk70x0p_pid_filter,
-				.pid_filter_ctrl = stk70x0p_pid_filter_ctrl,
-				.frontend_attach  = nim7090_frontend_attach,
-				.tuner_attach     = nim7090_tuner_attach,
-
-				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-			}},
-				.size_of_priv =
-					sizeof(struct dib0700_adapter_state),
-			},
-		},
-
-		.num_device_descs = 1,
-		.devices = {
-			{   "DiBcom NIM7090 reference design",
-				{ &dib0700_usb_id_table[72], NULL },
-				{ NULL },
-			},
-		},
-
-		.rc.core = {
-			.rc_interval      = DEFAULT_RC_INTERVAL,
-			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
-			.module_name	  = "dib0700",
-			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
-			.change_protocol  = dib0700_change_protocol,
-		},
-	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
-		.num_adapters = 2,
-		.adapter = {
-			{
-			.num_frontends = 1,
-			.fe = {{
-				.caps  = DVB_USB_ADAP_HAS_PID_FILTER |
-					DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
-				.pid_filter_count = 32,
-				.pid_filter = stk70x0p_pid_filter,
-				.pid_filter_ctrl = stk70x0p_pid_filter_ctrl,
-				.frontend_attach  = tfe7090pvr_frontend0_attach,
-				.tuner_attach     = tfe7090pvr_tuner0_attach,
-
-				DIB0700_DEFAULT_STREAMING_CONFIG(0x03),
-			}},
-				.size_of_priv =
-					sizeof(struct dib0700_adapter_state),
-			},
-			{
-			.num_frontends = 1,
-			.fe = {{
-				.caps  = DVB_USB_ADAP_HAS_PID_FILTER |
-					DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
-				.pid_filter_count = 32,
-				.pid_filter = stk70x0p_pid_filter,
-				.pid_filter_ctrl = stk70x0p_pid_filter_ctrl,
-				.frontend_attach  = tfe7090pvr_frontend1_attach,
-				.tuner_attach     = tfe7090pvr_tuner1_attach,
-
-				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-			}},
-				.size_of_priv =
-					sizeof(struct dib0700_adapter_state),
-			},
-		},
-
-		.num_device_descs = 1,
-		.devices = {
-			{   "DiBcom TFE7090PVR reference design",
-				{ &dib0700_usb_id_table[73], NULL },
-				{ NULL },
-			},
-		},
-
-		.rc.core = {
-			.rc_interval      = DEFAULT_RC_INTERVAL,
-			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
-			.module_name	  = "dib0700",
-			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
-			.change_protocol  = dib0700_change_protocol,
-		},
-	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
-		.num_adapters = 1,
-		.adapter = {
-			{
-			.num_frontends = 1,
-			.fe = {{
-				.frontend_attach  = pctv340e_frontend_attach,
-				.tuner_attach     = xc4000_tuner_attach,
-
-				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-			}},
-				.size_of_priv = sizeof(struct
-						dib0700_adapter_state),
-			},
-		},
-
-		.num_device_descs = 2,
-		.devices = {
-			{   "Pinnacle PCTV 340e HD Pro USB Stick",
-				{ &dib0700_usb_id_table[76], NULL },
-				{ NULL },
-			},
-			{   "Pinnacle PCTV Hybrid Stick Solo",
-				{ &dib0700_usb_id_table[77], NULL },
-				{ NULL },
-			},
-		},
-		.rc.core = {
-			.rc_interval      = DEFAULT_RC_INTERVAL,
-			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
-			.module_name	  = "dib0700",
-			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
-			.change_protocol  = dib0700_change_protocol,
-		},
-	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
-		.num_adapters = 1,
-		.adapter = {
-			{
-				.num_frontends = 1,
-				.fe = {{
-					.caps  = DVB_USB_ADAP_HAS_PID_FILTER |
-						DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
-					.pid_filter_count = 32,
-					.pid_filter = stk70x0p_pid_filter,
-					.pid_filter_ctrl = stk70x0p_pid_filter_ctrl,
-					.frontend_attach  = tfe7090e_frontend_attach,
-					.tuner_attach     = tfe7090e_tuner_attach,
-
-					DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-				} },
-
-				.size_of_priv =
-					sizeof(struct dib0700_adapter_state),
-			},
-		},
-
-		.num_device_descs = 1,
-		.devices = {
-			{   "DiBcom TFE7090E reference design",
-				{ &dib0700_usb_id_table[78], NULL },
-				{ NULL },
-			},
-		},
-
-		.rc.core = {
-			.rc_interval      = DEFAULT_RC_INTERVAL,
-			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
-			.module_name	  = "dib0700",
-			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
-			.change_protocol  = dib0700_change_protocol,
-		},
-	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
-		.num_adapters = 1,
-		.adapter = {
-			{
-				.num_frontends = 1,
-				.fe = {{
-					.caps  = DVB_USB_ADAP_HAS_PID_FILTER |
-						DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
-					.pid_filter_count = 32,
-					.pid_filter = stk70x0p_pid_filter,
-					.pid_filter_ctrl = stk70x0p_pid_filter_ctrl,
-					.frontend_attach  = tfe7790e_frontend_attach,
-					.tuner_attach     = tfe7790e_tuner_attach,
-
-					DIB0700_DEFAULT_STREAMING_CONFIG(0x03),
-				} },
-
-				.size_of_priv =
-					sizeof(struct dib0700_adapter_state),
-			},
-		},
-
-		.num_device_descs = 1,
-		.devices = {
-			{   "DiBcom TFE7790E reference design",
-				{ &dib0700_usb_id_table[79], NULL },
-				{ NULL },
-			},
-		},
-
-		.rc.core = {
-			.rc_interval      = DEFAULT_RC_INTERVAL,
-			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
-			.module_name	  = "dib0700",
-			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
-			.change_protocol  = dib0700_change_protocol,
-		},
-	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
-		.num_adapters = 1,
-		.adapter = {
-			{
-				.num_frontends = 1,
-				.fe = {{
-					.caps  = DVB_USB_ADAP_HAS_PID_FILTER |
-						DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
-					.pid_filter_count = 32,
-					.pid_filter = stk80xx_pid_filter,
-					.pid_filter_ctrl = stk80xx_pid_filter_ctrl,
-					.frontend_attach  = tfe8096p_frontend_attach,
-					.tuner_attach     = tfe8096p_tuner_attach,
-
-					DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
-
-				} },
-
-				.size_of_priv =
-					sizeof(struct dib0700_adapter_state),
-			},
-		},
-
-		.num_device_descs = 1,
-		.devices = {
-			{   "DiBcom TFE8096P reference design",
-				{ &dib0700_usb_id_table[80], NULL },
-				{ NULL },
-			},
-		},
-
-		.rc.core = {
-			.rc_interval      = DEFAULT_RC_INTERVAL,
-			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
-			.module_name	  = "dib0700",
-			.rc_query         = dib0700_rc_query_old_firmware,
-			.allowed_protos   = RC_TYPE_RC5 |
-					    RC_TYPE_RC6 |
-					    RC_TYPE_NEC,
-			.change_protocol  = dib0700_change_protocol,
-		},
-	},
-};
-
-int dib0700_device_count = ARRAY_SIZE(dib0700_devices);
diff --git a/drivers/media/dvb/dvb-usb/dib07x0.h b/drivers/media/dvb/dvb-usb/dib07x0.h
deleted file mode 100644
index 7e62c10..0000000
--- a/drivers/media/dvb/dvb-usb/dib07x0.h
+++ /dev/null
@@ -1,21 +0,0 @@
-#ifndef _DIB07X0_H_
-#define _DIB07X0_H_
-
-enum dib07x0_gpios {
-	GPIO0  =  0,
-	GPIO1  =  2,
-	GPIO2  =  3,
-	GPIO3  =  4,
-	GPIO4  =  5,
-	GPIO5  =  6,
-	GPIO6  =  8,
-	GPIO7  = 10,
-	GPIO8  = 11,
-	GPIO9  = 14,
-	GPIO10 = 15,
-};
-
-#define GPIO_IN  0
-#define GPIO_OUT 1
-
-#endif
diff --git a/drivers/media/dvb/dvb-usb/dibusb-common.c b/drivers/media/dvb/dvb-usb/dibusb-common.c
deleted file mode 100644
index a76bbb2..0000000
--- a/drivers/media/dvb/dvb-usb/dibusb-common.c
+++ /dev/null
@@ -1,479 +0,0 @@
-/* Common methods for dibusb-based-receivers.
- *
- * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
- *
- *	This program is free software; you can redistribute it and/or modify it
- *	under the terms of the GNU General Public License as published by the Free
- *	Software Foundation, version 2.
- *
- * see Documentation/dvb/README.dvb-usb for more information
- */
-#include "dibusb.h"
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level (1=info (|-able))." DVB_USB_DEBUG_STATUS);
-MODULE_LICENSE("GPL");
-
-#define deb_info(args...) dprintk(debug,0x01,args)
-
-/* common stuff used by the different dibusb modules */
-int dibusb_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
-{
-	if (adap->priv != NULL) {
-		struct dibusb_state *st = adap->priv;
-		if (st->ops.fifo_ctrl != NULL)
-			if (st->ops.fifo_ctrl(adap->fe_adap[0].fe, onoff)) {
-				err("error while controlling the fifo of the demod.");
-				return -ENODEV;
-			}
-	}
-	return 0;
-}
-EXPORT_SYMBOL(dibusb_streaming_ctrl);
-
-int dibusb_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, int onoff)
-{
-	if (adap->priv != NULL) {
-		struct dibusb_state *st = adap->priv;
-		if (st->ops.pid_ctrl != NULL)
-			st->ops.pid_ctrl(adap->fe_adap[0].fe,
-					 index, pid, onoff);
-	}
-	return 0;
-}
-EXPORT_SYMBOL(dibusb_pid_filter);
-
-int dibusb_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff)
-{
-	if (adap->priv != NULL) {
-		struct dibusb_state *st = adap->priv;
-		if (st->ops.pid_parse != NULL)
-			if (st->ops.pid_parse(adap->fe_adap[0].fe, onoff) < 0)
-				err("could not handle pid_parser");
-	}
-	return 0;
-}
-EXPORT_SYMBOL(dibusb_pid_filter_ctrl);
-
-int dibusb_power_ctrl(struct dvb_usb_device *d, int onoff)
-{
-	u8 b[3];
-	int ret;
-	b[0] = DIBUSB_REQ_SET_IOCTL;
-	b[1] = DIBUSB_IOCTL_CMD_POWER_MODE;
-	b[2] = onoff ? DIBUSB_IOCTL_POWER_WAKEUP : DIBUSB_IOCTL_POWER_SLEEP;
-	ret = dvb_usb_generic_write(d,b,3);
-	msleep(10);
-	return ret;
-}
-EXPORT_SYMBOL(dibusb_power_ctrl);
-
-int dibusb2_0_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
-{
-	u8 b[3] = { 0 };
-	int ret;
-
-	if ((ret = dibusb_streaming_ctrl(adap,onoff)) < 0)
-		return ret;
-
-	if (onoff) {
-		b[0] = DIBUSB_REQ_SET_STREAMING_MODE;
-		b[1] = 0x00;
-		if ((ret = dvb_usb_generic_write(adap->dev,b,2)) < 0)
-			return ret;
-	}
-
-	b[0] = DIBUSB_REQ_SET_IOCTL;
-	b[1] = onoff ? DIBUSB_IOCTL_CMD_ENABLE_STREAM : DIBUSB_IOCTL_CMD_DISABLE_STREAM;
-	return dvb_usb_generic_write(adap->dev,b,3);
-}
-EXPORT_SYMBOL(dibusb2_0_streaming_ctrl);
-
-int dibusb2_0_power_ctrl(struct dvb_usb_device *d, int onoff)
-{
-	if (onoff) {
-		u8 b[3] = { DIBUSB_REQ_SET_IOCTL, DIBUSB_IOCTL_CMD_POWER_MODE, DIBUSB_IOCTL_POWER_WAKEUP };
-		return dvb_usb_generic_write(d,b,3);
-	} else
-		return 0;
-}
-EXPORT_SYMBOL(dibusb2_0_power_ctrl);
-
-static int dibusb_i2c_msg(struct dvb_usb_device *d, u8 addr,
-			  u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
-{
-	u8 sndbuf[wlen+4]; /* lead(1) devaddr,direction(1) addr(2) data(wlen) (len(2) (when reading)) */
-	/* write only ? */
-	int wo = (rbuf == NULL || rlen == 0),
-		len = 2 + wlen + (wo ? 0 : 2);
-
-	sndbuf[0] = wo ? DIBUSB_REQ_I2C_WRITE : DIBUSB_REQ_I2C_READ;
-	sndbuf[1] = (addr << 1) | (wo ? 0 : 1);
-
-	memcpy(&sndbuf[2],wbuf,wlen);
-
-	if (!wo) {
-		sndbuf[wlen+2] = (rlen >> 8) & 0xff;
-		sndbuf[wlen+3] = rlen & 0xff;
-	}
-
-	return dvb_usb_generic_rw(d,sndbuf,len,rbuf,rlen,0);
-}
-
-/*
- * I2C master xfer function
- */
-static int dibusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num)
-{
-	struct dvb_usb_device *d = i2c_get_adapdata(adap);
-	int i;
-
-	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
-		return -EAGAIN;
-
-	for (i = 0; i < num; i++) {
-		/* write/read request */
-		if (i+1 < num && (msg[i].flags & I2C_M_RD) == 0
-					  && (msg[i+1].flags & I2C_M_RD)) {
-			if (dibusb_i2c_msg(d, msg[i].addr, msg[i].buf,msg[i].len,
-						msg[i+1].buf,msg[i+1].len) < 0)
-				break;
-			i++;
-		} else if ((msg[i].flags & I2C_M_RD) == 0) {
-			if (dibusb_i2c_msg(d, msg[i].addr, msg[i].buf,msg[i].len,NULL,0) < 0)
-				break;
-		} else if (msg[i].addr != 0x50) {
-			/* 0x50 is the address of the eeprom - we need to protect it
-			 * from dibusb's bad i2c implementation: reads without
-			 * writing the offset before are forbidden */
-			if (dibusb_i2c_msg(d, msg[i].addr, NULL, 0, msg[i].buf, msg[i].len) < 0)
-				break;
-		}
-	}
-
-	mutex_unlock(&d->i2c_mutex);
-	return i;
-}
-
-static u32 dibusb_i2c_func(struct i2c_adapter *adapter)
-{
-	return I2C_FUNC_I2C;
-}
-
-struct i2c_algorithm dibusb_i2c_algo = {
-	.master_xfer   = dibusb_i2c_xfer,
-	.functionality = dibusb_i2c_func,
-};
-EXPORT_SYMBOL(dibusb_i2c_algo);
-
-int dibusb_read_eeprom_byte(struct dvb_usb_device *d, u8 offs, u8 *val)
-{
-	u8 wbuf[1] = { offs };
-	return dibusb_i2c_msg(d, 0x50, wbuf, 1, val, 1);
-}
-EXPORT_SYMBOL(dibusb_read_eeprom_byte);
-
-/* 3000MC/P stuff */
-// Config Adjacent channels  Perf -cal22
-static struct dibx000_agc_config dib3000p_mt2060_agc_config = {
-	.band_caps = BAND_VHF | BAND_UHF,
-	.setup     = (1 << 8) | (5 << 5) | (1 << 4) | (1 << 3) | (0 << 2) | (2 << 0),
-
-	.agc1_max = 48497,
-	.agc1_min = 23593,
-	.agc2_max = 46531,
-	.agc2_min = 24904,
-
-	.agc1_pt1 = 0x65,
-	.agc1_pt2 = 0x69,
-
-	.agc1_slope1 = 0x51,
-	.agc1_slope2 = 0x27,
-
-	.agc2_pt1 = 0,
-	.agc2_pt2 = 0x33,
-
-	.agc2_slope1 = 0x35,
-	.agc2_slope2 = 0x37,
-};
-
-static struct dib3000mc_config stk3000p_dib3000p_config = {
-	&dib3000p_mt2060_agc_config,
-
-	.max_time     = 0x196,
-	.ln_adc_level = 0x1cc7,
-
-	.output_mpeg2_in_188_bytes = 1,
-
-	.agc_command1 = 1,
-	.agc_command2 = 1,
-};
-
-static struct dibx000_agc_config dib3000p_panasonic_agc_config = {
-	.band_caps = BAND_VHF | BAND_UHF,
-	.setup     = (1 << 8) | (5 << 5) | (1 << 4) | (1 << 3) | (0 << 2) | (2 << 0),
-
-	.agc1_max = 56361,
-	.agc1_min = 22282,
-	.agc2_max = 47841,
-	.agc2_min = 36045,
-
-	.agc1_pt1 = 0x3b,
-	.agc1_pt2 = 0x6b,
-
-	.agc1_slope1 = 0x55,
-	.agc1_slope2 = 0x1d,
-
-	.agc2_pt1 = 0,
-	.agc2_pt2 = 0x0a,
-
-	.agc2_slope1 = 0x95,
-	.agc2_slope2 = 0x1e,
-};
-
-#if defined(CONFIG_DVB_DIB3000MC) || 					\
-	(defined(CONFIG_DVB_DIB3000MC_MODULE) && defined(MODULE))
-
-static struct dib3000mc_config mod3000p_dib3000p_config = {
-	&dib3000p_panasonic_agc_config,
-
-	.max_time     = 0x51,
-	.ln_adc_level = 0x1cc7,
-
-	.output_mpeg2_in_188_bytes = 1,
-
-	.agc_command1 = 1,
-	.agc_command2 = 1,
-};
-
-int dibusb_dib3000mc_frontend_attach(struct dvb_usb_adapter *adap)
-{
-	if (adap->dev->udev->descriptor.idVendor  == USB_VID_LITEON &&
-			adap->dev->udev->descriptor.idProduct ==
-			USB_PID_LITEON_DVB_T_WARM) {
-		msleep(1000);
-	}
-
-	adap->fe_adap[0].fe = dvb_attach(dib3000mc_attach,
-					 &adap->dev->i2c_adap,
-					 DEFAULT_DIB3000P_I2C_ADDRESS,
-					 &mod3000p_dib3000p_config);
-	if ((adap->fe_adap[0].fe) == NULL)
-		adap->fe_adap[0].fe = dvb_attach(dib3000mc_attach,
-						 &adap->dev->i2c_adap,
-						 DEFAULT_DIB3000MC_I2C_ADDRESS,
-						 &mod3000p_dib3000p_config);
-	if ((adap->fe_adap[0].fe) != NULL) {
-		if (adap->priv != NULL) {
-			struct dibusb_state *st = adap->priv;
-			st->ops.pid_parse = dib3000mc_pid_parse;
-			st->ops.pid_ctrl  = dib3000mc_pid_control;
-		}
-		return 0;
-	}
-	return -ENODEV;
-}
-EXPORT_SYMBOL(dibusb_dib3000mc_frontend_attach);
-
-static struct mt2060_config stk3000p_mt2060_config = {
-	0x60
-};
-
-int dibusb_dib3000mc_tuner_attach(struct dvb_usb_adapter *adap)
-{
-	struct dibusb_state *st = adap->priv;
-	u8 a,b;
-	u16 if1 = 1220;
-	struct i2c_adapter *tun_i2c;
-
-	// First IF calibration for Liteon Sticks
-	if (adap->dev->udev->descriptor.idVendor  == USB_VID_LITEON &&
-		adap->dev->udev->descriptor.idProduct == USB_PID_LITEON_DVB_T_WARM) {
-
-		dibusb_read_eeprom_byte(adap->dev,0x7E,&a);
-		dibusb_read_eeprom_byte(adap->dev,0x7F,&b);
-
-		if (a == 0x00)
-			if1 += b;
-		else if (a == 0x80)
-			if1 -= b;
-		else
-			warn("LITE-ON DVB-T: Strange IF1 calibration :%2X %2X\n", a, b);
-
-	} else if (adap->dev->udev->descriptor.idVendor  == USB_VID_DIBCOM &&
-		   adap->dev->udev->descriptor.idProduct == USB_PID_DIBCOM_MOD3001_WARM) {
-		u8 desc;
-		dibusb_read_eeprom_byte(adap->dev, 7, &desc);
-		if (desc == 2) {
-			a = 127;
-			do {
-				dibusb_read_eeprom_byte(adap->dev, a, &desc);
-				a--;
-			} while (a > 7 && (desc == 0xff || desc == 0x00));
-			if (desc & 0x80)
-				if1 -= (0xff - desc);
-			else
-				if1 += desc;
-		}
-	}
-
-	tun_i2c = dib3000mc_get_tuner_i2c_master(adap->fe_adap[0].fe, 1);
-	if (dvb_attach(mt2060_attach, adap->fe_adap[0].fe, tun_i2c, &stk3000p_mt2060_config, if1) == NULL) {
-		/* not found - use panasonic pll parameters */
-		if (dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x60, tun_i2c, DVB_PLL_ENV57H1XD5) == NULL)
-			return -ENOMEM;
-	} else {
-		st->mt2060_present = 1;
-		/* set the correct parameters for the dib3000p */
-		dib3000mc_set_config(adap->fe_adap[0].fe, &stk3000p_dib3000p_config);
-	}
-	return 0;
-}
-EXPORT_SYMBOL(dibusb_dib3000mc_tuner_attach);
-#endif
-
-/*
- * common remote control stuff
- */
-struct rc_map_table rc_map_dibusb_table[] = {
-	/* Key codes for the little Artec T1/Twinhan/HAMA/ remote. */
-	{ 0x0016, KEY_POWER },
-	{ 0x0010, KEY_MUTE },
-	{ 0x0003, KEY_1 },
-	{ 0x0001, KEY_2 },
-	{ 0x0006, KEY_3 },
-	{ 0x0009, KEY_4 },
-	{ 0x001d, KEY_5 },
-	{ 0x001f, KEY_6 },
-	{ 0x000d, KEY_7 },
-	{ 0x0019, KEY_8 },
-	{ 0x001b, KEY_9 },
-	{ 0x0015, KEY_0 },
-	{ 0x0005, KEY_CHANNELUP },
-	{ 0x0002, KEY_CHANNELDOWN },
-	{ 0x001e, KEY_VOLUMEUP },
-	{ 0x000a, KEY_VOLUMEDOWN },
-	{ 0x0011, KEY_RECORD },
-	{ 0x0017, KEY_FAVORITES }, /* Heart symbol - Channel list. */
-	{ 0x0014, KEY_PLAY },
-	{ 0x001a, KEY_STOP },
-	{ 0x0040, KEY_REWIND },
-	{ 0x0012, KEY_FASTFORWARD },
-	{ 0x000e, KEY_PREVIOUS }, /* Recall - Previous channel. */
-	{ 0x004c, KEY_PAUSE },
-	{ 0x004d, KEY_SCREEN }, /* Full screen mode. */
-	{ 0x0054, KEY_AUDIO }, /* MTS - Switch to secondary audio. */
-	/* additional keys TwinHan VisionPlus, the Artec seemingly not have */
-	{ 0x000c, KEY_CANCEL }, /* Cancel */
-	{ 0x001c, KEY_EPG }, /* EPG */
-	{ 0x0000, KEY_TAB }, /* Tab */
-	{ 0x0048, KEY_INFO }, /* Preview */
-	{ 0x0004, KEY_LIST }, /* RecordList */
-	{ 0x000f, KEY_TEXT }, /* Teletext */
-	/* Key codes for the KWorld/ADSTech/JetWay remote. */
-	{ 0x8612, KEY_POWER },
-	{ 0x860f, KEY_SELECT }, /* source */
-	{ 0x860c, KEY_UNKNOWN }, /* scan */
-	{ 0x860b, KEY_EPG },
-	{ 0x8610, KEY_MUTE },
-	{ 0x8601, KEY_1 },
-	{ 0x8602, KEY_2 },
-	{ 0x8603, KEY_3 },
-	{ 0x8604, KEY_4 },
-	{ 0x8605, KEY_5 },
-	{ 0x8606, KEY_6 },
-	{ 0x8607, KEY_7 },
-	{ 0x8608, KEY_8 },
-	{ 0x8609, KEY_9 },
-	{ 0x860a, KEY_0 },
-	{ 0x8618, KEY_ZOOM },
-	{ 0x861c, KEY_UNKNOWN }, /* preview */
-	{ 0x8613, KEY_UNKNOWN }, /* snap */
-	{ 0x8600, KEY_UNDO },
-	{ 0x861d, KEY_RECORD },
-	{ 0x860d, KEY_STOP },
-	{ 0x860e, KEY_PAUSE },
-	{ 0x8616, KEY_PLAY },
-	{ 0x8611, KEY_BACK },
-	{ 0x8619, KEY_FORWARD },
-	{ 0x8614, KEY_UNKNOWN }, /* pip */
-	{ 0x8615, KEY_ESC },
-	{ 0x861a, KEY_UP },
-	{ 0x861e, KEY_DOWN },
-	{ 0x861f, KEY_LEFT },
-	{ 0x861b, KEY_RIGHT },
-
-	/* Key codes for the DiBcom MOD3000 remote. */
-	{ 0x8000, KEY_MUTE },
-	{ 0x8001, KEY_TEXT },
-	{ 0x8002, KEY_HOME },
-	{ 0x8003, KEY_POWER },
-
-	{ 0x8004, KEY_RED },
-	{ 0x8005, KEY_GREEN },
-	{ 0x8006, KEY_YELLOW },
-	{ 0x8007, KEY_BLUE },
-
-	{ 0x8008, KEY_DVD },
-	{ 0x8009, KEY_AUDIO },
-	{ 0x800a, KEY_IMAGES },      /* Pictures */
-	{ 0x800b, KEY_VIDEO },
-
-	{ 0x800c, KEY_BACK },
-	{ 0x800d, KEY_UP },
-	{ 0x800e, KEY_RADIO },
-	{ 0x800f, KEY_EPG },
-
-	{ 0x8010, KEY_LEFT },
-	{ 0x8011, KEY_OK },
-	{ 0x8012, KEY_RIGHT },
-	{ 0x8013, KEY_UNKNOWN },    /* SAP */
-
-	{ 0x8014, KEY_TV },
-	{ 0x8015, KEY_DOWN },
-	{ 0x8016, KEY_MENU },       /* DVD Menu */
-	{ 0x8017, KEY_LAST },
-
-	{ 0x8018, KEY_RECORD },
-	{ 0x8019, KEY_STOP },
-	{ 0x801a, KEY_PAUSE },
-	{ 0x801b, KEY_PLAY },
-
-	{ 0x801c, KEY_PREVIOUS },
-	{ 0x801d, KEY_REWIND },
-	{ 0x801e, KEY_FASTFORWARD },
-	{ 0x801f, KEY_NEXT},
-
-	{ 0x8040, KEY_1 },
-	{ 0x8041, KEY_2 },
-	{ 0x8042, KEY_3 },
-	{ 0x8043, KEY_CHANNELUP },
-
-	{ 0x8044, KEY_4 },
-	{ 0x8045, KEY_5 },
-	{ 0x8046, KEY_6 },
-	{ 0x8047, KEY_CHANNELDOWN },
-
-	{ 0x8048, KEY_7 },
-	{ 0x8049, KEY_8 },
-	{ 0x804a, KEY_9 },
-	{ 0x804b, KEY_VOLUMEUP },
-
-	{ 0x804c, KEY_CLEAR },
-	{ 0x804d, KEY_0 },
-	{ 0x804e, KEY_ENTER },
-	{ 0x804f, KEY_VOLUMEDOWN },
-};
-EXPORT_SYMBOL(rc_map_dibusb_table);
-
-int dibusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
-{
-	u8 key[5],cmd = DIBUSB_REQ_POLL_REMOTE;
-	dvb_usb_generic_rw(d,&cmd,1,key,5,0);
-	dvb_usb_nec_rc_key_to_event(d,key,event,state);
-	if (key[0] != 0)
-		deb_info("key: %x %x %x %x %x\n",key[0],key[1],key[2],key[3],key[4]);
-	return 0;
-}
-EXPORT_SYMBOL(dibusb_rc_query);
diff --git a/drivers/media/dvb/dvb-usb/dibusb-mb.c b/drivers/media/dvb/dvb-usb/dibusb-mb.c
deleted file mode 100644
index a4ac37e..0000000
--- a/drivers/media/dvb/dvb-usb/dibusb-mb.c
+++ /dev/null
@@ -1,471 +0,0 @@
-/* DVB USB compliant linux driver for mobile DVB-T USB devices based on
- * reference designs made by DiBcom (http://www.dibcom.fr/) (DiB3000M-B)
- *
- * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
- *
- * based on GPL code from DiBcom, which has
- * Copyright (C) 2004 Amaury Demol for DiBcom (ademol@dibcom.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, version 2.
- *
- * see Documentation/dvb/README.dvb-usb for more information
- */
-#include "dibusb.h"
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-static int dib3000mb_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
-{
-	struct dvb_usb_adapter *adap = fe->dvb->priv;
-	struct dibusb_state *st = adap->priv;
-
-	return st->ops.tuner_pass_ctrl(fe, enable, st->tuner_addr);
-}
-
-static int dibusb_dib3000mb_frontend_attach(struct dvb_usb_adapter *adap)
-{
-	struct dib3000_config demod_cfg;
-	struct dibusb_state *st = adap->priv;
-
-	demod_cfg.demod_address = 0x8;
-
-	adap->fe_adap[0].fe = dvb_attach(dib3000mb_attach, &demod_cfg,
-					 &adap->dev->i2c_adap, &st->ops);
-	if ((adap->fe_adap[0].fe) == NULL)
-		return -ENODEV;
-
-	adap->fe_adap[0].fe->ops.i2c_gate_ctrl = dib3000mb_i2c_gate_ctrl;
-
-	return 0;
-}
-
-static int dibusb_thomson_tuner_attach(struct dvb_usb_adapter *adap)
-{
-	struct dibusb_state *st = adap->priv;
-
-	st->tuner_addr = 0x61;
-
-	dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x61, &adap->dev->i2c_adap,
-		   DVB_PLL_TUA6010XS);
-	return 0;
-}
-
-static int dibusb_panasonic_tuner_attach(struct dvb_usb_adapter *adap)
-{
-	struct dibusb_state *st = adap->priv;
-
-	st->tuner_addr = 0x60;
-
-	dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x60, &adap->dev->i2c_adap,
-		   DVB_PLL_TDA665X);
-	return 0;
-}
-
-/* Some of the Artec 1.1 device aren't equipped with the default tuner
- * (Thomson Cable), but with a Panasonic ENV77H11D5.  This function figures
- * this out. */
-static int dibusb_tuner_probe_and_attach(struct dvb_usb_adapter *adap)
-{
-	u8 b[2] = { 0,0 }, b2[1];
-	int ret = 0;
-	struct i2c_msg msg[2] = {
-		{ .flags = 0,        .buf = b,  .len = 2 },
-		{ .flags = I2C_M_RD, .buf = b2, .len = 1 },
-	};
-	struct dibusb_state *st = adap->priv;
-
-	/* the Panasonic sits on I2C addrass 0x60, the Thomson on 0x61 */
-	msg[0].addr = msg[1].addr = st->tuner_addr = 0x60;
-
-	if (adap->fe_adap[0].fe->ops.i2c_gate_ctrl)
-		adap->fe_adap[0].fe->ops.i2c_gate_ctrl(adap->fe_adap[0].fe, 1);
-
-	if (i2c_transfer(&adap->dev->i2c_adap, msg, 2) != 2) {
-		err("tuner i2c write failed.");
-		ret = -EREMOTEIO;
-	}
-
-	if (adap->fe_adap[0].fe->ops.i2c_gate_ctrl)
-		adap->fe_adap[0].fe->ops.i2c_gate_ctrl(adap->fe_adap[0].fe, 0);
-
-	if (b2[0] == 0xfe) {
-		info("This device has the Thomson Cable onboard. Which is default.");
-		ret = dibusb_thomson_tuner_attach(adap);
-	} else {
-		info("This device has the Panasonic ENV77H11D5 onboard.");
-		ret = dibusb_panasonic_tuner_attach(adap);
-	}
-
-	return ret;
-}
-
-/* USB Driver stuff */
-static struct dvb_usb_device_properties dibusb1_1_properties;
-static struct dvb_usb_device_properties dibusb1_1_an2235_properties;
-static struct dvb_usb_device_properties dibusb2_0b_properties;
-static struct dvb_usb_device_properties artec_t1_usb2_properties;
-
-static int dibusb_probe(struct usb_interface *intf,
-		const struct usb_device_id *id)
-{
-	if (0 == dvb_usb_device_init(intf, &dibusb1_1_properties,
-				     THIS_MODULE, NULL, adapter_nr) ||
-	    0 == dvb_usb_device_init(intf, &dibusb1_1_an2235_properties,
-				     THIS_MODULE, NULL, adapter_nr) ||
-	    0 == dvb_usb_device_init(intf, &dibusb2_0b_properties,
-				     THIS_MODULE, NULL, adapter_nr) ||
-	    0 == dvb_usb_device_init(intf, &artec_t1_usb2_properties,
-				     THIS_MODULE, NULL, adapter_nr))
-		return 0;
-
-	return -EINVAL;
-}
-
-/* do not change the order of the ID table */
-static struct usb_device_id dibusb_dib3000mb_table [] = {
-/* 00 */	{ USB_DEVICE(USB_VID_WIDEVIEW,		USB_PID_AVERMEDIA_DVBT_USB_COLD) },
-/* 01 */	{ USB_DEVICE(USB_VID_WIDEVIEW,		USB_PID_AVERMEDIA_DVBT_USB_WARM) },
-/* 02 */	{ USB_DEVICE(USB_VID_COMPRO,		USB_PID_COMPRO_DVBU2000_COLD) },
-/* 03 */	{ USB_DEVICE(USB_VID_COMPRO,		USB_PID_COMPRO_DVBU2000_WARM) },
-/* 04 */	{ USB_DEVICE(USB_VID_COMPRO_UNK,	USB_PID_COMPRO_DVBU2000_UNK_COLD) },
-/* 05 */	{ USB_DEVICE(USB_VID_DIBCOM,		USB_PID_DIBCOM_MOD3000_COLD) },
-/* 06 */	{ USB_DEVICE(USB_VID_DIBCOM,		USB_PID_DIBCOM_MOD3000_WARM) },
-/* 07 */	{ USB_DEVICE(USB_VID_EMPIA,		USB_PID_KWORLD_VSTREAM_COLD) },
-/* 08 */	{ USB_DEVICE(USB_VID_EMPIA,		USB_PID_KWORLD_VSTREAM_WARM) },
-/* 09 */	{ USB_DEVICE(USB_VID_GRANDTEC,		USB_PID_GRANDTEC_DVBT_USB_COLD) },
-/* 10 */	{ USB_DEVICE(USB_VID_GRANDTEC,		USB_PID_GRANDTEC_DVBT_USB_WARM) },
-/* 11 */	{ USB_DEVICE(USB_VID_GRANDTEC,		USB_PID_DIBCOM_MOD3000_COLD) },
-/* 12 */	{ USB_DEVICE(USB_VID_GRANDTEC,		USB_PID_DIBCOM_MOD3000_WARM) },
-/* 13 */	{ USB_DEVICE(USB_VID_HYPER_PALTEK,	USB_PID_UNK_HYPER_PALTEK_COLD) },
-/* 14 */	{ USB_DEVICE(USB_VID_HYPER_PALTEK,	USB_PID_UNK_HYPER_PALTEK_WARM) },
-/* 15 */	{ USB_DEVICE(USB_VID_VISIONPLUS,	USB_PID_TWINHAN_VP7041_COLD) },
-/* 16 */	{ USB_DEVICE(USB_VID_VISIONPLUS,	USB_PID_TWINHAN_VP7041_WARM) },
-/* 17 */	{ USB_DEVICE(USB_VID_TWINHAN,		USB_PID_TWINHAN_VP7041_COLD) },
-/* 18 */	{ USB_DEVICE(USB_VID_TWINHAN,		USB_PID_TWINHAN_VP7041_WARM) },
-/* 19 */	{ USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC,	USB_PID_ULTIMA_TVBOX_COLD) },
-/* 20 */	{ USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC,	USB_PID_ULTIMA_TVBOX_WARM) },
-/* 21 */	{ USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC,	USB_PID_ULTIMA_TVBOX_AN2235_COLD) },
-/* 22 */	{ USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC,	USB_PID_ULTIMA_TVBOX_AN2235_WARM) },
-/* 23 */	{ USB_DEVICE(USB_VID_ADSTECH,		USB_PID_ADSTECH_USB2_COLD) },
-
-/* device ID with default DIBUSB2_0-firmware and with the hacked firmware */
-/* 24 */	{ USB_DEVICE(USB_VID_ADSTECH,		USB_PID_ADSTECH_USB2_WARM) },
-/* 25 */	{ USB_DEVICE(USB_VID_KYE,		USB_PID_KYE_DVB_T_COLD) },
-/* 26 */	{ USB_DEVICE(USB_VID_KYE,		USB_PID_KYE_DVB_T_WARM) },
-
-/* 27 */	{ USB_DEVICE(USB_VID_KWORLD,		USB_PID_KWORLD_VSTREAM_COLD) },
-
-/* 28 */	{ USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC,	USB_PID_ULTIMA_TVBOX_USB2_COLD) },
-/* 29 */	{ USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC,	USB_PID_ULTIMA_TVBOX_USB2_WARM) },
-
-/*
- * XXX: As Artec just 'forgot' to program the EEPROM on some Artec T1 devices
- *      we don't catch these faulty IDs (namely 'Cypress FX1 USB controller') that
- *      have been left on the device. If you don't have such a device but an Artec
- *      device that's supposed to work with this driver but is not detected by it,
- *      free to enable CONFIG_DVB_USB_DIBUSB_MB_FAULTY via your kernel config.
- */
-
-#ifdef CONFIG_DVB_USB_DIBUSB_MB_FAULTY
-/* 30 */	{ USB_DEVICE(USB_VID_ANCHOR,		USB_PID_ULTIMA_TVBOX_ANCHOR_COLD) },
-#endif
-
-			{ }		/* Terminating entry */
-};
-MODULE_DEVICE_TABLE (usb, dibusb_dib3000mb_table);
-
-static struct dvb_usb_device_properties dibusb1_1_properties = {
-	.caps =  DVB_USB_IS_AN_I2C_ADAPTER,
-
-	.usb_ctrl = CYPRESS_AN2135,
-
-	.firmware = "dvb-usb-dibusb-5.0.0.11.fw",
-
-	.num_adapters = 1,
-	.adapter = {
-		{
-		.num_frontends = 1,
-		.fe = {{
-			.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
-			.pid_filter_count = 16,
-
-			.streaming_ctrl   = dibusb_streaming_ctrl,
-			.pid_filter       = dibusb_pid_filter,
-			.pid_filter_ctrl  = dibusb_pid_filter_ctrl,
-			.frontend_attach  = dibusb_dib3000mb_frontend_attach,
-			.tuner_attach     = dibusb_tuner_probe_and_attach,
-
-			/* parameter for the MPEG2-data transfer */
-			.stream = {
-				.type = USB_BULK,
-				.count = 7,
-				.endpoint = 0x02,
-				.u = {
-					.bulk = {
-						.buffersize = 4096,
-					}
-				}
-			},
-		}},
-			.size_of_priv     = sizeof(struct dibusb_state),
-		}
-	},
-
-	.power_ctrl       = dibusb_power_ctrl,
-
-	.rc.legacy = {
-		.rc_interval      = DEFAULT_RC_INTERVAL,
-		.rc_map_table     = rc_map_dibusb_table,
-		.rc_map_size      = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */
-		.rc_query         = dibusb_rc_query,
-	},
-
-	.i2c_algo         = &dibusb_i2c_algo,
-
-	.generic_bulk_ctrl_endpoint = 0x01,
-
-	.num_device_descs = 9,
-	.devices = {
-		{	"AVerMedia AverTV DVBT USB1.1",
-			{ &dibusb_dib3000mb_table[0],  NULL },
-			{ &dibusb_dib3000mb_table[1],  NULL },
-		},
-		{	"Compro Videomate DVB-U2000 - DVB-T USB1.1 (please confirm to linux-dvb)",
-			{ &dibusb_dib3000mb_table[2], &dibusb_dib3000mb_table[4], NULL},
-			{ &dibusb_dib3000mb_table[3], NULL },
-		},
-		{	"DiBcom USB1.1 DVB-T reference design (MOD3000)",
-			{ &dibusb_dib3000mb_table[5],  NULL },
-			{ &dibusb_dib3000mb_table[6],  NULL },
-		},
-		{	"KWorld V-Stream XPERT DTV - DVB-T USB1.1",
-			{ &dibusb_dib3000mb_table[7], NULL },
-			{ &dibusb_dib3000mb_table[8], NULL },
-		},
-		{	"Grandtec USB1.1 DVB-T",
-			{ &dibusb_dib3000mb_table[9],  &dibusb_dib3000mb_table[11], NULL },
-			{ &dibusb_dib3000mb_table[10], &dibusb_dib3000mb_table[12], NULL },
-		},
-		{	"Unknown USB1.1 DVB-T device ???? please report the name to the author",
-			{ &dibusb_dib3000mb_table[13], NULL },
-			{ &dibusb_dib3000mb_table[14], NULL },
-		},
-		{	"TwinhanDTV USB-Ter USB1.1 / Magic Box I / HAMA USB1.1 DVB-T device",
-			{ &dibusb_dib3000mb_table[15], &dibusb_dib3000mb_table[17], NULL},
-			{ &dibusb_dib3000mb_table[16], &dibusb_dib3000mb_table[18], NULL},
-		},
-		{	"Artec T1 USB1.1 TVBOX with AN2135",
-			{ &dibusb_dib3000mb_table[19], NULL },
-			{ &dibusb_dib3000mb_table[20], NULL },
-		},
-		{	"VideoWalker DVB-T USB",
-			{ &dibusb_dib3000mb_table[25], NULL },
-			{ &dibusb_dib3000mb_table[26], NULL },
-		},
-	}
-};
-
-static struct dvb_usb_device_properties dibusb1_1_an2235_properties = {
-	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
-	.usb_ctrl = CYPRESS_AN2235,
-
-	.firmware = "dvb-usb-dibusb-an2235-01.fw",
-
-	.num_adapters = 1,
-	.adapter = {
-		{
-		.num_frontends = 1,
-		.fe = {{
-			.caps = DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_ADAP_HAS_PID_FILTER,
-			.pid_filter_count = 16,
-
-			.streaming_ctrl   = dibusb_streaming_ctrl,
-			.pid_filter       = dibusb_pid_filter,
-			.pid_filter_ctrl  = dibusb_pid_filter_ctrl,
-			.frontend_attach  = dibusb_dib3000mb_frontend_attach,
-			.tuner_attach     = dibusb_tuner_probe_and_attach,
-
-			/* parameter for the MPEG2-data transfer */
-			.stream = {
-				.type = USB_BULK,
-				.count = 7,
-				.endpoint = 0x02,
-				.u = {
-					.bulk = {
-						.buffersize = 4096,
-					}
-				}
-			},
-		}},
-			.size_of_priv     = sizeof(struct dibusb_state),
-		},
-	},
-	.power_ctrl       = dibusb_power_ctrl,
-
-	.rc.legacy = {
-		.rc_interval      = DEFAULT_RC_INTERVAL,
-		.rc_map_table     = rc_map_dibusb_table,
-		.rc_map_size      = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */
-		.rc_query         = dibusb_rc_query,
-	},
-
-	.i2c_algo         = &dibusb_i2c_algo,
-
-	.generic_bulk_ctrl_endpoint = 0x01,
-
-#ifdef CONFIG_DVB_USB_DIBUSB_MB_FAULTY
-	.num_device_descs = 2,
-#else
-	.num_device_descs = 1,
-#endif
-	.devices = {
-		{	"Artec T1 USB1.1 TVBOX with AN2235",
-			{ &dibusb_dib3000mb_table[21], NULL },
-			{ &dibusb_dib3000mb_table[22], NULL },
-		},
-#ifdef CONFIG_DVB_USB_DIBUSB_MB_FAULTY
-		{	"Artec T1 USB1.1 TVBOX with AN2235 (faulty USB IDs)",
-			{ &dibusb_dib3000mb_table[30], NULL },
-			{ NULL },
-		},
-		{ NULL },
-#endif
-	}
-};
-
-static struct dvb_usb_device_properties dibusb2_0b_properties = {
-	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
-
-	.usb_ctrl = CYPRESS_FX2,
-
-	.firmware = "dvb-usb-adstech-usb2-02.fw",
-
-	.num_adapters = 1,
-	.adapter = {
-		{
-		.num_frontends = 1,
-		.fe = {{
-			.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
-			.pid_filter_count = 16,
-
-			.streaming_ctrl   = dibusb2_0_streaming_ctrl,
-			.pid_filter       = dibusb_pid_filter,
-			.pid_filter_ctrl  = dibusb_pid_filter_ctrl,
-			.frontend_attach  = dibusb_dib3000mb_frontend_attach,
-			.tuner_attach     = dibusb_thomson_tuner_attach,
-
-			/* parameter for the MPEG2-data transfer */
-			.stream = {
-				.type = USB_BULK,
-				.count = 7,
-				.endpoint = 0x06,
-				.u = {
-					.bulk = {
-						.buffersize = 4096,
-					}
-				}
-			},
-		}},
-			.size_of_priv     = sizeof(struct dibusb_state),
-		}
-	},
-	.power_ctrl       = dibusb2_0_power_ctrl,
-
-	.rc.legacy = {
-		.rc_interval      = DEFAULT_RC_INTERVAL,
-		.rc_map_table     = rc_map_dibusb_table,
-		.rc_map_size      = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */
-		.rc_query         = dibusb_rc_query,
-	},
-
-	.i2c_algo         = &dibusb_i2c_algo,
-
-	.generic_bulk_ctrl_endpoint = 0x01,
-
-	.num_device_descs = 2,
-	.devices = {
-		{	"KWorld/ADSTech Instant DVB-T USB2.0",
-			{ &dibusb_dib3000mb_table[23], NULL },
-			{ &dibusb_dib3000mb_table[24], NULL },
-		},
-		{	"KWorld Xpert DVB-T USB2.0",
-			{ &dibusb_dib3000mb_table[27], NULL },
-			{ NULL }
-		},
-		{ NULL },
-	}
-};
-
-static struct dvb_usb_device_properties artec_t1_usb2_properties = {
-	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
-
-	.usb_ctrl = CYPRESS_FX2,
-
-	.firmware = "dvb-usb-dibusb-6.0.0.8.fw",
-
-	.num_adapters = 1,
-	.adapter = {
-		{
-		.num_frontends = 1,
-		.fe = {{
-			.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
-			.pid_filter_count = 16,
-
-			.streaming_ctrl   = dibusb2_0_streaming_ctrl,
-			.pid_filter       = dibusb_pid_filter,
-			.pid_filter_ctrl  = dibusb_pid_filter_ctrl,
-			.frontend_attach  = dibusb_dib3000mb_frontend_attach,
-			.tuner_attach     = dibusb_tuner_probe_and_attach,
-			/* parameter for the MPEG2-data transfer */
-			.stream = {
-				.type = USB_BULK,
-				.count = 7,
-				.endpoint = 0x06,
-				.u = {
-					.bulk = {
-						.buffersize = 4096,
-					}
-				}
-			},
-		}},
-			.size_of_priv     = sizeof(struct dibusb_state),
-		}
-	},
-	.power_ctrl       = dibusb2_0_power_ctrl,
-
-	.rc.legacy = {
-		.rc_interval      = DEFAULT_RC_INTERVAL,
-		.rc_map_table     = rc_map_dibusb_table,
-		.rc_map_size      = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */
-		.rc_query         = dibusb_rc_query,
-	},
-
-	.i2c_algo         = &dibusb_i2c_algo,
-
-	.generic_bulk_ctrl_endpoint = 0x01,
-
-	.num_device_descs = 1,
-	.devices = {
-		{	"Artec T1 USB2.0",
-			{ &dibusb_dib3000mb_table[28], NULL },
-			{ &dibusb_dib3000mb_table[29], NULL },
-		},
-		{ NULL },
-	}
-};
-
-static struct usb_driver dibusb_driver = {
-	.name		= "dvb_usb_dibusb_mb",
-	.probe		= dibusb_probe,
-	.disconnect = dvb_usb_device_exit,
-	.id_table	= dibusb_dib3000mb_table,
-};
-
-module_usb_driver(dibusb_driver);
-
-MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
-MODULE_DESCRIPTION("Driver for DiBcom USB DVB-T devices (DiB3000M-B based)");
-MODULE_VERSION("1.0");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/dibusb-mc.c b/drivers/media/dvb/dvb-usb/dibusb-mc.c
deleted file mode 100644
index 9d1a59d0..0000000
--- a/drivers/media/dvb/dvb-usb/dibusb-mc.c
+++ /dev/null
@@ -1,149 +0,0 @@
-/* DVB USB compliant linux driver for mobile DVB-T USB devices based on
- * reference designs made by DiBcom (http://www.dibcom.fr/) (DiB3000M-C/P)
- *
- * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
- *
- * based on GPL code from DiBcom, which has
- * Copyright (C) 2004 Amaury Demol for DiBcom (ademol@dibcom.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, version 2.
- *
- * see Documentation/dvb/README.dvb-usb for more information
- */
-#include "dibusb.h"
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-/* USB Driver stuff */
-static struct dvb_usb_device_properties dibusb_mc_properties;
-
-static int dibusb_mc_probe(struct usb_interface *intf,
-		const struct usb_device_id *id)
-{
-	return dvb_usb_device_init(intf, &dibusb_mc_properties, THIS_MODULE,
-				   NULL, adapter_nr);
-}
-
-/* do not change the order of the ID table */
-static struct usb_device_id dibusb_dib3000mc_table [] = {
-/* 00 */	{ USB_DEVICE(USB_VID_DIBCOM,		USB_PID_DIBCOM_MOD3001_COLD) },
-/* 01 */	{ USB_DEVICE(USB_VID_DIBCOM,		USB_PID_DIBCOM_MOD3001_WARM) },
-/* 02 */	{ USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC,	USB_PID_ULTIMA_TVBOX_USB2_COLD) },
-/* 03 */	{ USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC,	USB_PID_ULTIMA_TVBOX_USB2_WARM) }, // ( ? )
-/* 04 */	{ USB_DEVICE(USB_VID_LITEON,		USB_PID_LITEON_DVB_T_COLD) },
-/* 05 */	{ USB_DEVICE(USB_VID_LITEON,		USB_PID_LITEON_DVB_T_WARM) },
-/* 06 */	{ USB_DEVICE(USB_VID_EMPIA,		USB_PID_DIGIVOX_MINI_SL_COLD) },
-/* 07 */	{ USB_DEVICE(USB_VID_EMPIA,		USB_PID_DIGIVOX_MINI_SL_WARM) },
-/* 08 */	{ USB_DEVICE(USB_VID_GRANDTEC,          USB_PID_GRANDTEC_DVBT_USB2_COLD) },
-/* 09 */	{ USB_DEVICE(USB_VID_GRANDTEC,          USB_PID_GRANDTEC_DVBT_USB2_WARM) },
-/* 10 */	{ USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC,	USB_PID_ARTEC_T14_COLD) },
-/* 11 */	{ USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC,	USB_PID_ARTEC_T14_WARM) },
-/* 12 */	{ USB_DEVICE(USB_VID_LEADTEK,		USB_PID_WINFAST_DTV_DONGLE_COLD) },
-/* 13 */	{ USB_DEVICE(USB_VID_LEADTEK,		USB_PID_WINFAST_DTV_DONGLE_WARM) },
-/* 14 */	{ USB_DEVICE(USB_VID_HUMAX_COEX,	USB_PID_DVB_T_USB_STICK_HIGH_SPEED_COLD) },
-/* 15 */	{ USB_DEVICE(USB_VID_HUMAX_COEX,	USB_PID_DVB_T_USB_STICK_HIGH_SPEED_WARM) },
-			{ }		/* Terminating entry */
-};
-MODULE_DEVICE_TABLE (usb, dibusb_dib3000mc_table);
-
-static struct dvb_usb_device_properties dibusb_mc_properties = {
-	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
-
-	.usb_ctrl = CYPRESS_FX2,
-	.firmware = "dvb-usb-dibusb-6.0.0.8.fw",
-
-	.num_adapters = 1,
-	.adapter = {
-		{
-		.num_frontends = 1,
-		.fe = {{
-			.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
-			.pid_filter_count = 32,
-			.streaming_ctrl   = dibusb2_0_streaming_ctrl,
-			.pid_filter       = dibusb_pid_filter,
-			.pid_filter_ctrl  = dibusb_pid_filter_ctrl,
-			.frontend_attach  = dibusb_dib3000mc_frontend_attach,
-			.tuner_attach     = dibusb_dib3000mc_tuner_attach,
-
-	/* parameter for the MPEG2-data transfer */
-			.stream = {
-				.type = USB_BULK,
-				.count = 8,
-				.endpoint = 0x06,
-				.u = {
-					.bulk = {
-						.buffersize = 4096,
-					}
-				}
-			},
-		}},
-			.size_of_priv     = sizeof(struct dibusb_state),
-		}
-	},
-	.power_ctrl       = dibusb2_0_power_ctrl,
-
-	.rc.legacy = {
-		.rc_interval      = DEFAULT_RC_INTERVAL,
-		.rc_map_table     = rc_map_dibusb_table,
-		.rc_map_size      = 111, /* FIXME */
-		.rc_query         = dibusb_rc_query,
-	},
-
-	.i2c_algo         = &dibusb_i2c_algo,
-
-	.generic_bulk_ctrl_endpoint = 0x01,
-
-	.num_device_descs = 8,
-	.devices = {
-		{   "DiBcom USB2.0 DVB-T reference design (MOD3000P)",
-			{ &dibusb_dib3000mc_table[0], NULL },
-			{ &dibusb_dib3000mc_table[1], NULL },
-		},
-		{   "Artec T1 USB2.0 TVBOX (please check the warm ID)",
-			{ &dibusb_dib3000mc_table[2], NULL },
-			{ &dibusb_dib3000mc_table[3], NULL },
-		},
-		{   "LITE-ON USB2.0 DVB-T Tuner",
-		    /* Also rebranded as Intuix S800, Toshiba */
-			{ &dibusb_dib3000mc_table[4], NULL },
-			{ &dibusb_dib3000mc_table[5], NULL },
-		},
-		{   "MSI Digivox Mini SL",
-			{ &dibusb_dib3000mc_table[6], NULL },
-			{ &dibusb_dib3000mc_table[7], NULL },
-		},
-		{   "GRAND - USB2.0 DVB-T adapter",
-			{ &dibusb_dib3000mc_table[8], NULL },
-			{ &dibusb_dib3000mc_table[9], NULL },
-		},
-		{   "Artec T14 - USB2.0 DVB-T",
-			{ &dibusb_dib3000mc_table[10], NULL },
-			{ &dibusb_dib3000mc_table[11], NULL },
-		},
-		{   "Leadtek - USB2.0 Winfast DTV dongle",
-			{ &dibusb_dib3000mc_table[12], NULL },
-			{ &dibusb_dib3000mc_table[13], NULL },
-		},
-		{   "Humax/Coex DVB-T USB Stick 2.0 High Speed",
-			{ &dibusb_dib3000mc_table[14], NULL },
-			{ &dibusb_dib3000mc_table[15], NULL },
-		},
-		{ NULL },
-	}
-};
-
-static struct usb_driver dibusb_mc_driver = {
-	.name		= "dvb_usb_dibusb_mc",
-	.probe		= dibusb_mc_probe,
-	.disconnect = dvb_usb_device_exit,
-	.id_table	= dibusb_dib3000mc_table,
-};
-
-module_usb_driver(dibusb_mc_driver);
-
-MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
-MODULE_DESCRIPTION("Driver for DiBcom USB2.0 DVB-T (DiB3000M-C/P based) devices");
-MODULE_VERSION("1.0");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/dibusb.h b/drivers/media/dvb/dvb-usb/dibusb.h
deleted file mode 100644
index e47c321..0000000
--- a/drivers/media/dvb/dvb-usb/dibusb.h
+++ /dev/null
@@ -1,131 +0,0 @@
-/* Header file for all dibusb-based-receivers.
- *
- * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
- *
- *	This program is free software; you can redistribute it and/or modify it
- *	under the terms of the GNU General Public License as published by the Free
- *	Software Foundation, version 2.
- *
- * see Documentation/dvb/README.dvb-usb for more information
- */
-#ifndef _DVB_USB_DIBUSB_H_
-#define _DVB_USB_DIBUSB_H_
-
-#ifndef DVB_USB_LOG_PREFIX
- #define DVB_USB_LOG_PREFIX "dibusb"
-#endif
-#include "dvb-usb.h"
-
-#include "dib3000.h"
-#include "dib3000mc.h"
-#include "mt2060.h"
-
-/*
- * protocol of all dibusb related devices
- */
-
-/*
- * bulk msg to/from endpoint 0x01
- *
- * general structure:
- * request_byte parameter_bytes
- */
-
-#define DIBUSB_REQ_START_READ			0x00
-#define DIBUSB_REQ_START_DEMOD			0x01
-
-/*
- * i2c read
- * bulk write: 0x02 ((7bit i2c_addr << 1) & 0x01) register_bytes length_word
- * bulk read:  byte_buffer (length_word bytes)
- */
-#define DIBUSB_REQ_I2C_READ			0x02
-
-/*
- * i2c write
- * bulk write: 0x03 (7bit i2c_addr << 1) register_bytes value_bytes
- */
-#define DIBUSB_REQ_I2C_WRITE			0x03
-
-/*
- * polling the value of the remote control
- * bulk write: 0x04
- * bulk read:  byte_buffer (5 bytes)
- */
-#define DIBUSB_REQ_POLL_REMOTE       0x04
-
-/* additional status values for Hauppauge Remote Control Protocol */
-#define DIBUSB_RC_HAUPPAUGE_KEY_PRESSED	0x01
-#define DIBUSB_RC_HAUPPAUGE_KEY_EMPTY	0x03
-
-/* streaming mode:
- * bulk write: 0x05 mode_byte
- *
- * mode_byte is mostly 0x00
- */
-#define DIBUSB_REQ_SET_STREAMING_MODE	0x05
-
-/* interrupt the internal read loop, when blocking */
-#define DIBUSB_REQ_INTR_READ			0x06
-
-/* io control
- * 0x07 cmd_byte param_bytes
- *
- * param_bytes can be up to 32 bytes
- *
- * cmd_byte function    parameter name
- * 0x00     power mode
- *                      0x00      sleep
- *                      0x01      wakeup
- *
- * 0x01     enable streaming
- * 0x02     disable streaming
- *
- *
- */
-#define DIBUSB_REQ_SET_IOCTL			0x07
-
-/* IOCTL commands */
-
-/* change the power mode in firmware */
-#define DIBUSB_IOCTL_CMD_POWER_MODE		0x00
-#define DIBUSB_IOCTL_POWER_SLEEP			0x00
-#define DIBUSB_IOCTL_POWER_WAKEUP			0x01
-
-/* modify streaming of the FX2 */
-#define DIBUSB_IOCTL_CMD_ENABLE_STREAM	0x01
-#define DIBUSB_IOCTL_CMD_DISABLE_STREAM	0x02
-
-struct dibusb_state {
-	struct dib_fe_xfer_ops ops;
-	int mt2060_present;
-	u8 tuner_addr;
-};
-
-struct dibusb_device_state {
-	/* for RC5 remote control */
-	int old_toggle;
-	int last_repeat_count;
-};
-
-extern struct i2c_algorithm dibusb_i2c_algo;
-
-extern int dibusb_dib3000mc_frontend_attach(struct dvb_usb_adapter *);
-extern int dibusb_dib3000mc_tuner_attach (struct dvb_usb_adapter *);
-
-extern int dibusb_streaming_ctrl(struct dvb_usb_adapter *, int);
-extern int dibusb_pid_filter(struct dvb_usb_adapter *, int, u16, int);
-extern int dibusb_pid_filter_ctrl(struct dvb_usb_adapter *, int);
-extern int dibusb2_0_streaming_ctrl(struct dvb_usb_adapter *, int);
-
-extern int dibusb_power_ctrl(struct dvb_usb_device *, int);
-extern int dibusb2_0_power_ctrl(struct dvb_usb_device *, int);
-
-#define DEFAULT_RC_INTERVAL 150
-//#define DEFAULT_RC_INTERVAL 100000
-
-extern struct rc_map_table rc_map_dibusb_table[];
-extern int dibusb_rc_query(struct dvb_usb_device *, u32 *, int *);
-extern int dibusb_read_eeprom_byte(struct dvb_usb_device *, u8, u8 *);
-
-#endif
diff --git a/drivers/media/dvb/dvb-usb/digitv.c b/drivers/media/dvb/dvb-usb/digitv.c
deleted file mode 100644
index ff34419..0000000
--- a/drivers/media/dvb/dvb-usb/digitv.c
+++ /dev/null
@@ -1,354 +0,0 @@
-/* DVB USB compliant linux driver for Nebula Electronics uDigiTV DVB-T USB2.0
- * receiver
- *
- * Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@desy.de)
- *
- * partly based on the SDK published by Nebula Electronics
- *
- *	This program is free software; 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.
- *
- * see Documentation/dvb/README.dvb-usb for more information
- */
-#include "digitv.h"
-
-#include "mt352.h"
-#include "nxt6000.h"
-
-/* debug */
-static int dvb_usb_digitv_debug;
-module_param_named(debug,dvb_usb_digitv_debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS);
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-#define deb_rc(args...)   dprintk(dvb_usb_digitv_debug,0x01,args)
-
-static int digitv_ctrl_msg(struct dvb_usb_device *d,
-		u8 cmd, u8 vv, u8 *wbuf, int wlen, u8 *rbuf, int rlen)
-{
-	int wo = (rbuf == NULL || rlen == 0); /* write-only */
-	u8 sndbuf[7],rcvbuf[7];
-	memset(sndbuf,0,7); memset(rcvbuf,0,7);
-
-	sndbuf[0] = cmd;
-	sndbuf[1] = vv;
-	sndbuf[2] = wo ? wlen : rlen;
-
-	if (wo) {
-		memcpy(&sndbuf[3],wbuf,wlen);
-		dvb_usb_generic_write(d,sndbuf,7);
-	} else {
-		dvb_usb_generic_rw(d,sndbuf,7,rcvbuf,7,10);
-		memcpy(rbuf,&rcvbuf[3],rlen);
-	}
-	return 0;
-}
-
-/* I2C */
-static int digitv_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num)
-{
-	struct dvb_usb_device *d = i2c_get_adapdata(adap);
-	int i;
-
-	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
-		return -EAGAIN;
-
-	if (num > 2)
-		warn("more than 2 i2c messages at a time is not handled yet. TODO.");
-
-	for (i = 0; i < num; i++) {
-		/* write/read request */
-		if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {
-			if (digitv_ctrl_msg(d, USB_READ_COFDM, msg[i].buf[0], NULL, 0,
-						msg[i+1].buf,msg[i+1].len) < 0)
-				break;
-			i++;
-		} else
-			if (digitv_ctrl_msg(d,USB_WRITE_COFDM, msg[i].buf[0],
-						&msg[i].buf[1],msg[i].len-1,NULL,0) < 0)
-				break;
-	}
-
-	mutex_unlock(&d->i2c_mutex);
-	return i;
-}
-
-static u32 digitv_i2c_func(struct i2c_adapter *adapter)
-{
-	return I2C_FUNC_I2C;
-}
-
-static struct i2c_algorithm digitv_i2c_algo = {
-	.master_xfer   = digitv_i2c_xfer,
-	.functionality = digitv_i2c_func,
-};
-
-/* Callbacks for DVB USB */
-static int digitv_identify_state (struct usb_device *udev, struct
-		dvb_usb_device_properties *props, struct dvb_usb_device_description **desc,
-		int *cold)
-{
-	*cold = udev->descriptor.iManufacturer == 0 && udev->descriptor.iProduct == 0;
-	return 0;
-}
-
-static int digitv_mt352_demod_init(struct dvb_frontend *fe)
-{
-	static u8 reset_buf[] = { 0x89, 0x38,  0x8a, 0x2d, 0x50, 0x80 };
-	static u8 init_buf[] = { 0x68, 0xa0,  0x8e, 0x40,  0x53, 0x50,
-			0x67, 0x20,  0x7d, 0x01,  0x7c, 0x00,  0x7a, 0x00,
-			0x79, 0x20,  0x57, 0x05,  0x56, 0x31,  0x88, 0x0f,
-			0x75, 0x32 };
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(reset_buf); i += 2)
-		mt352_write(fe, &reset_buf[i], 2);
-
-	msleep(1);
-
-	for (i = 0; i < ARRAY_SIZE(init_buf); i += 2)
-		mt352_write(fe, &init_buf[i], 2);
-
-	return 0;
-}
-
-static struct mt352_config digitv_mt352_config = {
-	.demod_init = digitv_mt352_demod_init,
-};
-
-static int digitv_nxt6000_tuner_set_params(struct dvb_frontend *fe)
-{
-	struct dvb_usb_adapter *adap = fe->dvb->priv;
-	u8 b[5];
-
-	fe->ops.tuner_ops.calc_regs(fe, b, sizeof(b));
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	return digitv_ctrl_msg(adap->dev, USB_WRITE_TUNER, 0, &b[1], 4, NULL, 0);
-}
-
-static struct nxt6000_config digitv_nxt6000_config = {
-	.clock_inversion = 1,
-};
-
-static int digitv_frontend_attach(struct dvb_usb_adapter *adap)
-{
-	struct digitv_state *st = adap->dev->priv;
-
-	adap->fe_adap[0].fe = dvb_attach(mt352_attach, &digitv_mt352_config,
-					 &adap->dev->i2c_adap);
-	if ((adap->fe_adap[0].fe) != NULL) {
-		st->is_nxt6000 = 0;
-		return 0;
-	}
-	adap->fe_adap[0].fe = dvb_attach(nxt6000_attach,
-					 &digitv_nxt6000_config,
-					 &adap->dev->i2c_adap);
-	if ((adap->fe_adap[0].fe) != NULL) {
-		st->is_nxt6000 = 1;
-		return 0;
-	}
-	return -EIO;
-}
-
-static int digitv_tuner_attach(struct dvb_usb_adapter *adap)
-{
-	struct digitv_state *st = adap->dev->priv;
-
-	if (!dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x60, NULL, DVB_PLL_TDED4))
-		return -ENODEV;
-
-	if (st->is_nxt6000)
-		adap->fe_adap[0].fe->ops.tuner_ops.set_params = digitv_nxt6000_tuner_set_params;
-
-	return 0;
-}
-
-static struct rc_map_table rc_map_digitv_table[] = {
-	{ 0x5f55, KEY_0 },
-	{ 0x6f55, KEY_1 },
-	{ 0x9f55, KEY_2 },
-	{ 0xaf55, KEY_3 },
-	{ 0x5f56, KEY_4 },
-	{ 0x6f56, KEY_5 },
-	{ 0x9f56, KEY_6 },
-	{ 0xaf56, KEY_7 },
-	{ 0x5f59, KEY_8 },
-	{ 0x6f59, KEY_9 },
-	{ 0x9f59, KEY_TV },
-	{ 0xaf59, KEY_AUX },
-	{ 0x5f5a, KEY_DVD },
-	{ 0x6f5a, KEY_POWER },
-	{ 0x9f5a, KEY_CAMERA },     /* labelled 'Picture' */
-	{ 0xaf5a, KEY_AUDIO },
-	{ 0x5f65, KEY_INFO },
-	{ 0x6f65, KEY_F13 },     /* 16:9 */
-	{ 0x9f65, KEY_F14 },     /* 14:9 */
-	{ 0xaf65, KEY_EPG },
-	{ 0x5f66, KEY_EXIT },
-	{ 0x6f66, KEY_MENU },
-	{ 0x9f66, KEY_UP },
-	{ 0xaf66, KEY_DOWN },
-	{ 0x5f69, KEY_LEFT },
-	{ 0x6f69, KEY_RIGHT },
-	{ 0x9f69, KEY_ENTER },
-	{ 0xaf69, KEY_CHANNELUP },
-	{ 0x5f6a, KEY_CHANNELDOWN },
-	{ 0x6f6a, KEY_VOLUMEUP },
-	{ 0x9f6a, KEY_VOLUMEDOWN },
-	{ 0xaf6a, KEY_RED },
-	{ 0x5f95, KEY_GREEN },
-	{ 0x6f95, KEY_YELLOW },
-	{ 0x9f95, KEY_BLUE },
-	{ 0xaf95, KEY_SUBTITLE },
-	{ 0x5f96, KEY_F15 },     /* AD */
-	{ 0x6f96, KEY_TEXT },
-	{ 0x9f96, KEY_MUTE },
-	{ 0xaf96, KEY_REWIND },
-	{ 0x5f99, KEY_STOP },
-	{ 0x6f99, KEY_PLAY },
-	{ 0x9f99, KEY_FASTFORWARD },
-	{ 0xaf99, KEY_F16 },     /* chapter */
-	{ 0x5f9a, KEY_PAUSE },
-	{ 0x6f9a, KEY_PLAY },
-	{ 0x9f9a, KEY_RECORD },
-	{ 0xaf9a, KEY_F17 },     /* picture in picture */
-	{ 0x5fa5, KEY_KPPLUS },  /* zoom in */
-	{ 0x6fa5, KEY_KPMINUS }, /* zoom out */
-	{ 0x9fa5, KEY_F18 },     /* capture */
-	{ 0xafa5, KEY_F19 },     /* web */
-	{ 0x5fa6, KEY_EMAIL },
-	{ 0x6fa6, KEY_PHONE },
-	{ 0x9fa6, KEY_PC },
-};
-
-static int digitv_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
-{
-	int i;
-	u8 key[5];
-	u8 b[4] = { 0 };
-
-	*event = 0;
-	*state = REMOTE_NO_KEY_PRESSED;
-
-	digitv_ctrl_msg(d,USB_READ_REMOTE,0,NULL,0,&key[1],4);
-
-	/* Tell the device we've read the remote. Not sure how necessary
-	   this is, but the Nebula SDK does it. */
-	digitv_ctrl_msg(d,USB_WRITE_REMOTE,0,b,4,NULL,0);
-
-	/* if something is inside the buffer, simulate key press */
-	if (key[1] != 0)
-	{
-		  for (i = 0; i < d->props.rc.legacy.rc_map_size; i++) {
-			if (rc5_custom(&d->props.rc.legacy.rc_map_table[i]) == key[1] &&
-			    rc5_data(&d->props.rc.legacy.rc_map_table[i]) == key[2]) {
-				*event = d->props.rc.legacy.rc_map_table[i].keycode;
-				*state = REMOTE_KEY_PRESSED;
-				return 0;
-			}
-		}
-	}
-
-	if (key[0] != 0)
-		deb_rc("key: %x %x %x %x %x\n",key[0],key[1],key[2],key[3],key[4]);
-	return 0;
-}
-
-/* DVB USB Driver stuff */
-static struct dvb_usb_device_properties digitv_properties;
-
-static int digitv_probe(struct usb_interface *intf,
-		const struct usb_device_id *id)
-{
-	struct dvb_usb_device *d;
-	int ret = dvb_usb_device_init(intf, &digitv_properties, THIS_MODULE, &d,
-				      adapter_nr);
-	if (ret == 0) {
-		u8 b[4] = { 0 };
-
-		if (d != NULL) { /* do that only when the firmware is loaded */
-			b[0] = 1;
-			digitv_ctrl_msg(d,USB_WRITE_REMOTE_TYPE,0,b,4,NULL,0);
-
-			b[0] = 0;
-			digitv_ctrl_msg(d,USB_WRITE_REMOTE,0,b,4,NULL,0);
-		}
-	}
-	return ret;
-}
-
-static struct usb_device_id digitv_table [] = {
-		{ USB_DEVICE(USB_VID_ANCHOR, USB_PID_NEBULA_DIGITV) },
-		{ }		/* Terminating entry */
-};
-MODULE_DEVICE_TABLE (usb, digitv_table);
-
-static struct dvb_usb_device_properties digitv_properties = {
-	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
-
-	.usb_ctrl = CYPRESS_FX2,
-	.firmware = "dvb-usb-digitv-02.fw",
-
-	.size_of_priv = sizeof(struct digitv_state),
-
-	.num_adapters = 1,
-	.adapter = {
-		{
-		.num_frontends = 1,
-		.fe = {{
-			.frontend_attach  = digitv_frontend_attach,
-			.tuner_attach     = digitv_tuner_attach,
-
-			/* parameter for the MPEG2-data transfer */
-			.stream = {
-				.type = USB_BULK,
-				.count = 7,
-				.endpoint = 0x02,
-				.u = {
-					.bulk = {
-						.buffersize = 4096,
-					}
-				}
-			},
-		}},
-		}
-	},
-	.identify_state   = digitv_identify_state,
-
-	.rc.legacy = {
-		.rc_interval      = 1000,
-		.rc_map_table     = rc_map_digitv_table,
-		.rc_map_size      = ARRAY_SIZE(rc_map_digitv_table),
-		.rc_query         = digitv_rc_query,
-	},
-
-	.i2c_algo         = &digitv_i2c_algo,
-
-	.generic_bulk_ctrl_endpoint = 0x01,
-
-	.num_device_descs = 1,
-	.devices = {
-		{   "Nebula Electronics uDigiTV DVB-T USB2.0)",
-			{ &digitv_table[0], NULL },
-			{ NULL },
-		},
-		{ NULL },
-	}
-};
-
-static struct usb_driver digitv_driver = {
-	.name		= "dvb_usb_digitv",
-	.probe		= digitv_probe,
-	.disconnect = dvb_usb_device_exit,
-	.id_table	= digitv_table,
-};
-
-module_usb_driver(digitv_driver);
-
-MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
-MODULE_DESCRIPTION("Driver for Nebula Electronics uDigiTV DVB-T USB2.0");
-MODULE_VERSION("1.0-alpha");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/digitv.h b/drivers/media/dvb/dvb-usb/digitv.h
deleted file mode 100644
index 908c09f..0000000
--- a/drivers/media/dvb/dvb-usb/digitv.h
+++ /dev/null
@@ -1,66 +0,0 @@
-#ifndef _DVB_USB_DIGITV_H_
-#define _DVB_USB_DIGITV_H_
-
-#define DVB_USB_LOG_PREFIX "digitv"
-#include "dvb-usb.h"
-
-struct digitv_state {
-    int is_nxt6000;
-};
-
-/* protocol (from usblogging and the SDK:
- *
- * Always 7 bytes bulk message(s) for controlling
- *
- * First byte describes the command. Reads are 2 consecutive transfer (as always).
- *
- * General structure:
- *
- * write or first message of a read:
- * <cmdbyte> VV <len> B0 B1 B2 B3
- *
- * second message of a read
- * <cmdbyte> VV <len> R0 R1 R2 R3
- *
- * whereas 0 < len <= 4
- *
- * I2C address is stored somewhere inside the device.
- *
- * 0x01 read from EEPROM
- *  VV = offset; B* = 0; R* = value(s)
- *
- * 0x02 read register of the COFDM
- *  VV = register; B* = 0; R* = value(s)
- *
- * 0x05 write register of the COFDM
- *  VV = register; B* = value(s);
- *
- * 0x06 write to the tuner (only for NXT6000)
- *  VV = 0; B* = PLL data; len = 4;
- *
- * 0x03 read remote control
- *  VV = 0; B* = 0; len = 4; R* = key
- *
- * 0x07 write to the remote (don't know why one should this, resetting ?)
- *  VV = 0; B* = key; len = 4;
- *
- * 0x08 write remote type
- *  VV = 0; B[0] = 0x01, len = 4
- *
- * 0x09 write device init
- *  TODO
- */
-#define USB_READ_EEPROM         1
-
-#define USB_READ_COFDM          2
-#define USB_WRITE_COFDM         5
-
-#define USB_WRITE_TUNER         6
-
-#define USB_READ_REMOTE         3
-#define USB_WRITE_REMOTE        7
-#define USB_WRITE_REMOTE_TYPE   8
-
-#define USB_DEV_INIT            9
-
-#endif
diff --git a/drivers/media/dvb/dvb-usb/dtt200u-fe.c b/drivers/media/dvb/dvb-usb/dtt200u-fe.c
deleted file mode 100644
index 3d81daa..0000000
--- a/drivers/media/dvb/dvb-usb/dtt200u-fe.c
+++ /dev/null
@@ -1,210 +0,0 @@
-/* Frontend part of the Linux driver for the WideView/ Yakumo/ Hama/
- * Typhoon/ Yuan DVB-T USB2.0 receiver.
- *
- * Copyright (C) 2005 Patrick Boettcher <patrick.boettcher@desy.de>
- *
- *	This program is free software; you can redistribute it and/or modify it
- *	under the terms of the GNU General Public License as published by the Free
- *	Software Foundation, version 2.
- *
- * see Documentation/dvb/README.dvb-usb for more information
- */
-#include "dtt200u.h"
-
-struct dtt200u_fe_state {
-	struct dvb_usb_device *d;
-
-	fe_status_t stat;
-
-	struct dtv_frontend_properties fep;
-	struct dvb_frontend frontend;
-};
-
-static int dtt200u_fe_read_status(struct dvb_frontend* fe, fe_status_t *stat)
-{
-	struct dtt200u_fe_state *state = fe->demodulator_priv;
-	u8 st = GET_TUNE_STATUS, b[3];
-
-	dvb_usb_generic_rw(state->d,&st,1,b,3,0);
-
-	switch (b[0]) {
-		case 0x01:
-			*stat = FE_HAS_SIGNAL | FE_HAS_CARRIER |
-				FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
-			break;
-		case 0x00: /* pending */
-			*stat = FE_TIMEDOUT; /* during set_frontend */
-			break;
-		default:
-		case 0x02: /* failed */
-			*stat = 0;
-			break;
-	}
-	return 0;
-}
-
-static int dtt200u_fe_read_ber(struct dvb_frontend* fe, u32 *ber)
-{
-	struct dtt200u_fe_state *state = fe->demodulator_priv;
-	u8 bw = GET_VIT_ERR_CNT,b[3];
-	dvb_usb_generic_rw(state->d,&bw,1,b,3,0);
-	*ber = (b[0] << 16) | (b[1] << 8) | b[2];
-	return 0;
-}
-
-static int dtt200u_fe_read_unc_blocks(struct dvb_frontend* fe, u32 *unc)
-{
-	struct dtt200u_fe_state *state = fe->demodulator_priv;
-	u8 bw = GET_RS_UNCOR_BLK_CNT,b[2];
-
-	dvb_usb_generic_rw(state->d,&bw,1,b,2,0);
-	*unc = (b[0] << 8) | b[1];
-	return 0;
-}
-
-static int dtt200u_fe_read_signal_strength(struct dvb_frontend* fe, u16 *strength)
-{
-	struct dtt200u_fe_state *state = fe->demodulator_priv;
-	u8 bw = GET_AGC, b;
-	dvb_usb_generic_rw(state->d,&bw,1,&b,1,0);
-	*strength = (b << 8) | b;
-	return 0;
-}
-
-static int dtt200u_fe_read_snr(struct dvb_frontend* fe, u16 *snr)
-{
-	struct dtt200u_fe_state *state = fe->demodulator_priv;
-	u8 bw = GET_SNR,br;
-	dvb_usb_generic_rw(state->d,&bw,1,&br,1,0);
-	*snr = ~((br << 8) | br);
-	return 0;
-}
-
-static int dtt200u_fe_init(struct dvb_frontend* fe)
-{
-	struct dtt200u_fe_state *state = fe->demodulator_priv;
-	u8 b = SET_INIT;
-	return dvb_usb_generic_write(state->d,&b,1);
-}
-
-static int dtt200u_fe_sleep(struct dvb_frontend* fe)
-{
-	return dtt200u_fe_init(fe);
-}
-
-static int dtt200u_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
-{
-	tune->min_delay_ms = 1500;
-	tune->step_size = 0;
-	tune->max_drift = 0;
-	return 0;
-}
-
-static int dtt200u_fe_set_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
-	struct dtt200u_fe_state *state = fe->demodulator_priv;
-	int i;
-	fe_status_t st;
-	u16 freq = fep->frequency / 250000;
-	u8 bwbuf[2] = { SET_BANDWIDTH, 0 },freqbuf[3] = { SET_RF_FREQ, 0, 0 };
-
-	switch (fep->bandwidth_hz) {
-	case 8000000:
-		bwbuf[1] = 8;
-		break;
-	case 7000000:
-		bwbuf[1] = 7;
-		break;
-	case 6000000:
-		bwbuf[1] = 6;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	dvb_usb_generic_write(state->d,bwbuf,2);
-
-	freqbuf[1] = freq & 0xff;
-	freqbuf[2] = (freq >> 8) & 0xff;
-	dvb_usb_generic_write(state->d,freqbuf,3);
-
-	for (i = 0; i < 30; i++) {
-		msleep(20);
-		dtt200u_fe_read_status(fe, &st);
-		if (st & FE_TIMEDOUT)
-			continue;
-	}
-
-	return 0;
-}
-
-static int dtt200u_fe_get_frontend(struct dvb_frontend* fe)
-{
-	struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
-	struct dtt200u_fe_state *state = fe->demodulator_priv;
-	memcpy(fep, &state->fep, sizeof(struct dtv_frontend_properties));
-	return 0;
-}
-
-static void dtt200u_fe_release(struct dvb_frontend* fe)
-{
-	struct dtt200u_fe_state *state = (struct dtt200u_fe_state*) fe->demodulator_priv;
-	kfree(state);
-}
-
-static struct dvb_frontend_ops dtt200u_fe_ops;
-
-struct dvb_frontend* dtt200u_fe_attach(struct dvb_usb_device *d)
-{
-	struct dtt200u_fe_state* state = NULL;
-
-	/* allocate memory for the internal state */
-	state = kzalloc(sizeof(struct dtt200u_fe_state), GFP_KERNEL);
-	if (state == NULL)
-		goto error;
-
-	deb_info("attaching frontend dtt200u\n");
-
-	state->d = d;
-
-	memcpy(&state->frontend.ops,&dtt200u_fe_ops,sizeof(struct dvb_frontend_ops));
-	state->frontend.demodulator_priv = state;
-
-	return &state->frontend;
-error:
-	return NULL;
-}
-
-static struct dvb_frontend_ops dtt200u_fe_ops = {
-	.delsys = { SYS_DVBT },
-	.info = {
-		.name			= "WideView USB DVB-T",
-		.frequency_min		= 44250000,
-		.frequency_max		= 867250000,
-		.frequency_stepsize	= 250000,
-		.caps = FE_CAN_INVERSION_AUTO |
-				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_FEC_AUTO |
-				FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
-				FE_CAN_TRANSMISSION_MODE_AUTO |
-				FE_CAN_GUARD_INTERVAL_AUTO |
-				FE_CAN_RECOVER |
-				FE_CAN_HIERARCHY_AUTO,
-	},
-
-	.release = dtt200u_fe_release,
-
-	.init = dtt200u_fe_init,
-	.sleep = dtt200u_fe_sleep,
-
-	.set_frontend = dtt200u_fe_set_frontend,
-	.get_frontend = dtt200u_fe_get_frontend,
-	.get_tune_settings = dtt200u_fe_get_tune_settings,
-
-	.read_status = dtt200u_fe_read_status,
-	.read_ber = dtt200u_fe_read_ber,
-	.read_signal_strength = dtt200u_fe_read_signal_strength,
-	.read_snr = dtt200u_fe_read_snr,
-	.read_ucblocks = dtt200u_fe_read_unc_blocks,
-};
diff --git a/drivers/media/dvb/dvb-usb/dtt200u.c b/drivers/media/dvb/dvb-usb/dtt200u.c
deleted file mode 100644
index 66f205c..0000000
--- a/drivers/media/dvb/dvb-usb/dtt200u.c
+++ /dev/null
@@ -1,368 +0,0 @@
-/* DVB USB library compliant Linux driver for the WideView/ Yakumo/ Hama/
- * Typhoon/ Yuan/ Miglia DVB-T USB2.0 receiver.
- *
- * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
- *
- * Thanks to Steve Chang from WideView for providing support for the WT-220U.
- *
- *	This program is free software; 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.
- *
- * see Documentation/dvb/README.dvb-usb for more information
- */
-#include "dtt200u.h"
-
-/* debug */
-int dvb_usb_dtt200u_debug;
-module_param_named(debug,dvb_usb_dtt200u_debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2 (or-able))." DVB_USB_DEBUG_STATUS);
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-static int dtt200u_power_ctrl(struct dvb_usb_device *d, int onoff)
-{
-	u8 b = SET_INIT;
-
-	if (onoff)
-		dvb_usb_generic_write(d,&b,2);
-
-	return 0;
-}
-
-static int dtt200u_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
-{
-	u8 b_streaming[2] = { SET_STREAMING, onoff };
-	u8 b_rst_pid = RESET_PID_FILTER;
-
-	dvb_usb_generic_write(adap->dev, b_streaming, 2);
-
-	if (onoff == 0)
-		dvb_usb_generic_write(adap->dev, &b_rst_pid, 1);
-	return 0;
-}
-
-static int dtt200u_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, int onoff)
-{
-	u8 b_pid[4];
-	pid = onoff ? pid : 0;
-
-	b_pid[0] = SET_PID_FILTER;
-	b_pid[1] = index;
-	b_pid[2] = pid & 0xff;
-	b_pid[3] = (pid >> 8) & 0x1f;
-
-	return dvb_usb_generic_write(adap->dev, b_pid, 4);
-}
-
-/* remote control */
-/* key list for the tiny remote control (Yakumo, don't know about the others) */
-static struct rc_map_table rc_map_dtt200u_table[] = {
-	{ 0x8001, KEY_MUTE },
-	{ 0x8002, KEY_CHANNELDOWN },
-	{ 0x8003, KEY_VOLUMEDOWN },
-	{ 0x8004, KEY_1 },
-	{ 0x8005, KEY_2 },
-	{ 0x8006, KEY_3 },
-	{ 0x8007, KEY_4 },
-	{ 0x8008, KEY_5 },
-	{ 0x8009, KEY_6 },
-	{ 0x800a, KEY_7 },
-	{ 0x800c, KEY_ZOOM },
-	{ 0x800d, KEY_0 },
-	{ 0x800e, KEY_SELECT },
-	{ 0x8012, KEY_POWER },
-	{ 0x801a, KEY_CHANNELUP },
-	{ 0x801b, KEY_8 },
-	{ 0x801e, KEY_VOLUMEUP },
-	{ 0x801f, KEY_9 },
-};
-
-static int dtt200u_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
-{
-	u8 key[5],cmd = GET_RC_CODE;
-	dvb_usb_generic_rw(d,&cmd,1,key,5,0);
-	dvb_usb_nec_rc_key_to_event(d,key,event,state);
-	if (key[0] != 0)
-		deb_info("key: %x %x %x %x %x\n",key[0],key[1],key[2],key[3],key[4]);
-	return 0;
-}
-
-static int dtt200u_frontend_attach(struct dvb_usb_adapter *adap)
-{
-	adap->fe_adap[0].fe = dtt200u_fe_attach(adap->dev);
-	return 0;
-}
-
-static struct dvb_usb_device_properties dtt200u_properties;
-static struct dvb_usb_device_properties wt220u_fc_properties;
-static struct dvb_usb_device_properties wt220u_properties;
-static struct dvb_usb_device_properties wt220u_zl0353_properties;
-static struct dvb_usb_device_properties wt220u_miglia_properties;
-
-static int dtt200u_usb_probe(struct usb_interface *intf,
-		const struct usb_device_id *id)
-{
-	if (0 == dvb_usb_device_init(intf, &dtt200u_properties,
-				     THIS_MODULE, NULL, adapter_nr) ||
-	    0 == dvb_usb_device_init(intf, &wt220u_properties,
-				     THIS_MODULE, NULL, adapter_nr) ||
-	    0 == dvb_usb_device_init(intf, &wt220u_fc_properties,
-				     THIS_MODULE, NULL, adapter_nr) ||
-	    0 == dvb_usb_device_init(intf, &wt220u_zl0353_properties,
-				     THIS_MODULE, NULL, adapter_nr) ||
-	    0 == dvb_usb_device_init(intf, &wt220u_miglia_properties,
-				     THIS_MODULE, NULL, adapter_nr))
-		return 0;
-
-	return -ENODEV;
-}
-
-static struct usb_device_id dtt200u_usb_table [] = {
-	{ USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_DTT200U_COLD) },
-	{ USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_DTT200U_WARM) },
-	{ USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_COLD)  },
-	{ USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_WARM)  },
-	{ USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_ZL0353_COLD)  },
-	{ USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_ZL0353_WARM)  },
-	{ USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_FC_COLD)  },
-	{ USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_FC_WARM)  },
-	{ USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_ZAP250_COLD)  },
-	{ USB_DEVICE(USB_VID_MIGLIA, USB_PID_WT220U_ZAP250_COLD)  },
-	{ 0 },
-};
-MODULE_DEVICE_TABLE(usb, dtt200u_usb_table);
-
-static struct dvb_usb_device_properties dtt200u_properties = {
-	.usb_ctrl = CYPRESS_FX2,
-	.firmware = "dvb-usb-dtt200u-01.fw",
-
-	.num_adapters = 1,
-	.adapter = {
-		{
-		.num_frontends = 1,
-		.fe = {{
-			.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING,
-			.pid_filter_count = 15,
-
-	.streaming_ctrl  = dtt200u_streaming_ctrl,
-	.pid_filter      = dtt200u_pid_filter,
-	.frontend_attach = dtt200u_frontend_attach,
-	/* parameter for the MPEG2-data transfer */
-			.stream = {
-				.type = USB_BULK,
-		.count = 7,
-		.endpoint = 0x02,
-		.u = {
-			.bulk = {
-				.buffersize = 4096,
-			}
-		}
-	},
-		}},
-		}
-	},
-	.power_ctrl      = dtt200u_power_ctrl,
-
-	.rc.legacy = {
-		.rc_interval     = 300,
-		.rc_map_table    = rc_map_dtt200u_table,
-		.rc_map_size     = ARRAY_SIZE(rc_map_dtt200u_table),
-		.rc_query        = dtt200u_rc_query,
-	},
-
-	.generic_bulk_ctrl_endpoint = 0x01,
-
-	.num_device_descs = 1,
-	.devices = {
-		{ .name = "WideView/Yuan/Yakumo/Hama/Typhoon DVB-T USB2.0 (WT-200U)",
-		  .cold_ids = { &dtt200u_usb_table[0], NULL },
-		  .warm_ids = { &dtt200u_usb_table[1], NULL },
-		},
-		{ NULL },
-	}
-};
-
-static struct dvb_usb_device_properties wt220u_properties = {
-	.usb_ctrl = CYPRESS_FX2,
-	.firmware = "dvb-usb-wt220u-02.fw",
-
-	.num_adapters = 1,
-	.adapter = {
-		{
-		.num_frontends = 1,
-		.fe = {{
-			.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING,
-			.pid_filter_count = 15,
-
-	.streaming_ctrl  = dtt200u_streaming_ctrl,
-	.pid_filter      = dtt200u_pid_filter,
-	.frontend_attach = dtt200u_frontend_attach,
-	/* parameter for the MPEG2-data transfer */
-			.stream = {
-				.type = USB_BULK,
-		.count = 7,
-		.endpoint = 0x02,
-		.u = {
-			.bulk = {
-				.buffersize = 4096,
-			}
-		}
-	},
-		}},
-		}
-	},
-	.power_ctrl      = dtt200u_power_ctrl,
-
-	.rc.legacy = {
-		.rc_interval     = 300,
-		.rc_map_table      = rc_map_dtt200u_table,
-		.rc_map_size = ARRAY_SIZE(rc_map_dtt200u_table),
-		.rc_query        = dtt200u_rc_query,
-	},
-
-	.generic_bulk_ctrl_endpoint = 0x01,
-
-	.num_device_descs = 1,
-	.devices = {
-		{ .name = "WideView WT-220U PenType Receiver (Typhoon/Freecom)",
-		  .cold_ids = { &dtt200u_usb_table[2], &dtt200u_usb_table[8], NULL },
-		  .warm_ids = { &dtt200u_usb_table[3], NULL },
-		},
-		{ NULL },
-	}
-};
-
-static struct dvb_usb_device_properties wt220u_fc_properties = {
-	.usb_ctrl = CYPRESS_FX2,
-	.firmware = "dvb-usb-wt220u-fc03.fw",
-
-	.num_adapters = 1,
-	.adapter = {
-		{
-		.num_frontends = 1,
-		.fe = {{
-			.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING,
-			.pid_filter_count = 15,
-
-	.streaming_ctrl  = dtt200u_streaming_ctrl,
-	.pid_filter      = dtt200u_pid_filter,
-	.frontend_attach = dtt200u_frontend_attach,
-	/* parameter for the MPEG2-data transfer */
-			.stream = {
-				.type = USB_BULK,
-		.count = 7,
-				.endpoint = 0x06,
-		.u = {
-			.bulk = {
-				.buffersize = 4096,
-			}
-		}
-	},
-		}},
-		}
-	},
-	.power_ctrl      = dtt200u_power_ctrl,
-
-	.rc.legacy = {
-		.rc_interval     = 300,
-		.rc_map_table    = rc_map_dtt200u_table,
-		.rc_map_size     = ARRAY_SIZE(rc_map_dtt200u_table),
-		.rc_query        = dtt200u_rc_query,
-	},
-
-	.generic_bulk_ctrl_endpoint = 0x01,
-
-	.num_device_descs = 1,
-	.devices = {
-		{ .name = "WideView WT-220U PenType Receiver (Typhoon/Freecom)",
-		  .cold_ids = { &dtt200u_usb_table[6], NULL },
-		  .warm_ids = { &dtt200u_usb_table[7], NULL },
-		},
-		{ NULL },
-	}
-};
-
-static struct dvb_usb_device_properties wt220u_zl0353_properties = {
-	.usb_ctrl = CYPRESS_FX2,
-	.firmware = "dvb-usb-wt220u-zl0353-01.fw",
-
-	.num_adapters = 1,
-	.adapter = {
-		{
-		.num_frontends = 1,
-		.fe = {{
-			.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING,
-			.pid_filter_count = 15,
-
-			.streaming_ctrl  = dtt200u_streaming_ctrl,
-			.pid_filter      = dtt200u_pid_filter,
-			.frontend_attach = dtt200u_frontend_attach,
-			/* parameter for the MPEG2-data transfer */
-			.stream = {
-				.type = USB_BULK,
-				.count = 7,
-				.endpoint = 0x02,
-				.u = {
-					.bulk = {
-						.buffersize = 4096,
-					}
-				}
-			},
-		}},
-		}
-	},
-	.power_ctrl      = dtt200u_power_ctrl,
-
-	.rc.legacy = {
-		.rc_interval     = 300,
-		.rc_map_table    = rc_map_dtt200u_table,
-		.rc_map_size     = ARRAY_SIZE(rc_map_dtt200u_table),
-		.rc_query        = dtt200u_rc_query,
-	},
-
-	.generic_bulk_ctrl_endpoint = 0x01,
-
-	.num_device_descs = 1,
-	.devices = {
-		{ .name = "WideView WT-220U PenType Receiver (based on ZL353)",
-		  .cold_ids = { &dtt200u_usb_table[4], NULL },
-		  .warm_ids = { &dtt200u_usb_table[5], NULL },
-		},
-		{ NULL },
-	}
-};
-
-static struct dvb_usb_device_properties wt220u_miglia_properties = {
-	.usb_ctrl = CYPRESS_FX2,
-	.firmware = "dvb-usb-wt220u-miglia-01.fw",
-
-	.num_adapters = 1,
-	.generic_bulk_ctrl_endpoint = 0x01,
-
-	.num_device_descs = 1,
-	.devices = {
-		{ .name = "WideView WT-220U PenType Receiver (Miglia)",
-		  .cold_ids = { &dtt200u_usb_table[9], NULL },
-		  /* This device turns into WT220U_ZL0353_WARM when fw
-		     has been uploaded */
-		  .warm_ids = { NULL },
-		},
-		{ NULL },
-	}
-};
-
-/* usb specific object needed to register this driver with the usb subsystem */
-static struct usb_driver dtt200u_usb_driver = {
-	.name		= "dvb_usb_dtt200u",
-	.probe		= dtt200u_usb_probe,
-	.disconnect = dvb_usb_device_exit,
-	.id_table	= dtt200u_usb_table,
-};
-
-module_usb_driver(dtt200u_usb_driver);
-
-MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
-MODULE_DESCRIPTION("Driver for the WideView/Yakumo/Hama/Typhoon/Club3D/Miglia DVB-T USB2.0 devices");
-MODULE_VERSION("1.0");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/dtt200u.h b/drivers/media/dvb/dvb-usb/dtt200u.h
deleted file mode 100644
index 005b0a7..0000000
--- a/drivers/media/dvb/dvb-usb/dtt200u.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/* Common header file of Linux driver for the WideView/ Yakumo/ Hama/
- * Typhoon/ Yuan DVB-T USB2.0 receiver.
- *
- * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
- *
- *	This program is free software; you can redistribute it and/or modify it
- *	under the terms of the GNU General Public License as published by the Free
- *	Software Foundation, version 2.
- *
- * see Documentation/dvb/README.dvb-usb for more information
- */
-#ifndef _DVB_USB_DTT200U_H_
-#define _DVB_USB_DTT200U_H_
-
-#define DVB_USB_LOG_PREFIX "dtt200u"
-
-#include "dvb-usb.h"
-
-extern int dvb_usb_dtt200u_debug;
-#define deb_info(args...) dprintk(dvb_usb_dtt200u_debug,0x01,args)
-#define deb_xfer(args...) dprintk(dvb_usb_dtt200u_debug,0x02,args)
-
-/* guessed protocol description (reverse engineered):
- * read
- *  00 - USB type 0x02 for usb2.0, 0x01 for usb1.1
- *  88 - locking 2 bytes (0x80 0x40 == no signal, 0x89 0x20 == nice signal)
- */
-
-#define GET_SPEED		0x00
-#define GET_TUNE_STATUS		0x81
-#define GET_RC_CODE		0x84
-#define GET_CONFIGURATION	0x88
-#define GET_AGC			0x89
-#define GET_SNR			0x8a
-#define GET_VIT_ERR_CNT		0x8c
-#define GET_RS_ERR_CNT		0x8d
-#define GET_RS_UNCOR_BLK_CNT	0x8e
-
-/* write
- *  01 - init
- *  02 - frequency (divided by 250000)
- *  03 - bandwidth
- *  04 - pid table (index pid(7:0) pid(12:8))
- *  05 - reset the pid table
- *  08 - transfer switch
- */
-
-#define SET_INIT		0x01
-#define SET_RF_FREQ		0x02
-#define SET_BANDWIDTH		0x03
-#define SET_PID_FILTER		0x04
-#define RESET_PID_FILTER	0x05
-#define SET_STREAMING		0x08
-
-extern struct dvb_frontend * dtt200u_fe_attach(struct dvb_usb_device *d);
-
-#endif
diff --git a/drivers/media/dvb/dvb-usb/dtv5100.c b/drivers/media/dvb/dvb-usb/dtv5100.c
deleted file mode 100644
index 3d11df4..0000000
--- a/drivers/media/dvb/dvb-usb/dtv5100.c
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * DVB USB Linux driver for AME DTV-5100 USB2.0 DVB-T
- *
- * Copyright (C) 2008  Antoine Jacquet <royale@zerezo.com>
- * http://royale.zerezo.com/dtv5100/
- *
- * Inspired by gl861.c and au6610.c drivers
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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 "dtv5100.h"
-#include "zl10353.h"
-#include "qt1010.h"
-
-/* debug */
-static int dvb_usb_dtv5100_debug;
-module_param_named(debug, dvb_usb_dtv5100_debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS);
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-static int dtv5100_i2c_msg(struct dvb_usb_device *d, u8 addr,
-			   u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
-{
-	u8 request;
-	u8 type;
-	u16 value;
-	u16 index;
-
-	switch (wlen) {
-	case 1:
-		/* write { reg }, read { value } */
-		request = (addr == DTV5100_DEMOD_ADDR ? DTV5100_DEMOD_READ :
-							DTV5100_TUNER_READ);
-		type = USB_TYPE_VENDOR | USB_DIR_IN;
-		value = 0;
-		break;
-	case 2:
-		/* write { reg, value } */
-		request = (addr == DTV5100_DEMOD_ADDR ? DTV5100_DEMOD_WRITE :
-							DTV5100_TUNER_WRITE);
-		type = USB_TYPE_VENDOR | USB_DIR_OUT;
-		value = wbuf[1];
-		break;
-	default:
-		warn("wlen = %x, aborting.", wlen);
-		return -EINVAL;
-	}
-	index = (addr << 8) + wbuf[0];
-
-	msleep(1); /* avoid I2C errors */
-	return usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), request,
-			       type, value, index, rbuf, rlen,
-			       DTV5100_USB_TIMEOUT);
-}
-
-/* I2C */
-static int dtv5100_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
-			    int num)
-{
-	struct dvb_usb_device *d = i2c_get_adapdata(adap);
-	int i;
-
-	if (num > 2)
-		return -EINVAL;
-
-	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
-		return -EAGAIN;
-
-	for (i = 0; i < num; i++) {
-		/* write/read request */
-		if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {
-			if (dtv5100_i2c_msg(d, msg[i].addr, msg[i].buf,
-					    msg[i].len, msg[i+1].buf,
-					    msg[i+1].len) < 0)
-				break;
-			i++;
-		} else if (dtv5100_i2c_msg(d, msg[i].addr, msg[i].buf,
-					   msg[i].len, NULL, 0) < 0)
-				break;
-	}
-
-	mutex_unlock(&d->i2c_mutex);
-	return i;
-}
-
-static u32 dtv5100_i2c_func(struct i2c_adapter *adapter)
-{
-	return I2C_FUNC_I2C;
-}
-
-static struct i2c_algorithm dtv5100_i2c_algo = {
-	.master_xfer   = dtv5100_i2c_xfer,
-	.functionality = dtv5100_i2c_func,
-};
-
-/* Callbacks for DVB USB */
-static struct zl10353_config dtv5100_zl10353_config = {
-	.demod_address = DTV5100_DEMOD_ADDR,
-	.no_tuner = 1,
-	.parallel_ts = 1,
-};
-
-static int dtv5100_frontend_attach(struct dvb_usb_adapter *adap)
-{
-	adap->fe_adap[0].fe = dvb_attach(zl10353_attach, &dtv5100_zl10353_config,
-			      &adap->dev->i2c_adap);
-	if (adap->fe_adap[0].fe == NULL)
-		return -EIO;
-
-	/* disable i2c gate, or it won't work... is this safe? */
-	adap->fe_adap[0].fe->ops.i2c_gate_ctrl = NULL;
-
-	return 0;
-}
-
-static struct qt1010_config dtv5100_qt1010_config = {
-	.i2c_address = DTV5100_TUNER_ADDR
-};
-
-static int dtv5100_tuner_attach(struct dvb_usb_adapter *adap)
-{
-	return dvb_attach(qt1010_attach,
-			  adap->fe_adap[0].fe, &adap->dev->i2c_adap,
-			  &dtv5100_qt1010_config) == NULL ? -ENODEV : 0;
-}
-
-/* DVB USB Driver stuff */
-static struct dvb_usb_device_properties dtv5100_properties;
-
-static int dtv5100_probe(struct usb_interface *intf,
-			 const struct usb_device_id *id)
-{
-	int i, ret;
-	struct usb_device *udev = interface_to_usbdev(intf);
-
-	/* initialize non qt1010/zl10353 part? */
-	for (i = 0; dtv5100_init[i].request; i++) {
-		ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
-				      dtv5100_init[i].request,
-				      USB_TYPE_VENDOR | USB_DIR_OUT,
-				      dtv5100_init[i].value,
-				      dtv5100_init[i].index, NULL, 0,
-				      DTV5100_USB_TIMEOUT);
-		if (ret)
-			return ret;
-	}
-
-	ret = dvb_usb_device_init(intf, &dtv5100_properties,
-				  THIS_MODULE, NULL, adapter_nr);
-	if (ret)
-		return ret;
-
-	return 0;
-}
-
-static struct usb_device_id dtv5100_table[] = {
-	{ USB_DEVICE(0x06be, 0xa232) },
-	{ }		/* Terminating entry */
-};
-MODULE_DEVICE_TABLE(usb, dtv5100_table);
-
-static struct dvb_usb_device_properties dtv5100_properties = {
-	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
-	.usb_ctrl = DEVICE_SPECIFIC,
-
-	.size_of_priv = 0,
-
-	.num_adapters = 1,
-	.adapter = {{
-		.num_frontends = 1,
-		.fe = {{
-		.frontend_attach = dtv5100_frontend_attach,
-		.tuner_attach    = dtv5100_tuner_attach,
-
-		.stream = {
-			.type = USB_BULK,
-			.count = 8,
-			.endpoint = 0x82,
-			.u = {
-				.bulk = {
-					.buffersize = 4096,
-				}
-			}
-		},
-		}},
-	} },
-
-	.i2c_algo = &dtv5100_i2c_algo,
-
-	.num_device_descs = 1,
-	.devices = {
-		{
-			.name = "AME DTV-5100 USB2.0 DVB-T",
-			.cold_ids = { NULL },
-			.warm_ids = { &dtv5100_table[0], NULL },
-		},
-	}
-};
-
-static struct usb_driver dtv5100_driver = {
-	.name		= "dvb_usb_dtv5100",
-	.probe		= dtv5100_probe,
-	.disconnect	= dvb_usb_device_exit,
-	.id_table	= dtv5100_table,
-};
-
-module_usb_driver(dtv5100_driver);
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/dtv5100.h b/drivers/media/dvb/dvb-usb/dtv5100.h
deleted file mode 100644
index 93e96e0..0000000
--- a/drivers/media/dvb/dvb-usb/dtv5100.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * DVB USB Linux driver for AME DTV-5100 USB2.0 DVB-T
- *
- * Copyright (C) 2008  Antoine Jacquet <royale@zerezo.com>
- * http://royale.zerezo.com/dtv5100/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#ifndef _DVB_USB_DTV5100_H_
-#define _DVB_USB_DTV5100_H_
-
-#define DVB_USB_LOG_PREFIX "dtv5100"
-#include "dvb-usb.h"
-
-#define DTV5100_USB_TIMEOUT 500
-
-#define DTV5100_DEMOD_ADDR	0x00
-#define DTV5100_DEMOD_WRITE	0xc0
-#define DTV5100_DEMOD_READ	0xc1
-
-#define DTV5100_TUNER_ADDR	0xc4
-#define DTV5100_TUNER_WRITE	0xc7
-#define DTV5100_TUNER_READ	0xc8
-
-#define DRIVER_AUTHOR "Antoine Jacquet, http://royale.zerezo.com/"
-#define DRIVER_DESC "AME DTV-5100 USB2.0 DVB-T"
-
-static struct {
-	u8 request;
-	u8 value;
-	u16 index;
-} dtv5100_init[] = {
-	{ 0x000000c5, 0x00000000, 0x00000001 },
-	{ 0x000000c5, 0x00000001, 0x00000001 },
-	{ }		/* Terminating entry */
-};
-
-#endif
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-common.h b/drivers/media/dvb/dvb-usb/dvb-usb-common.h
deleted file mode 100644
index 6b7b2a8..0000000
--- a/drivers/media/dvb/dvb-usb/dvb-usb-common.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/* dvb-usb-common.h is part of the DVB USB library.
- *
- * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
- * see dvb-usb-init.c for copyright information.
- *
- * a header file containing prototypes and types for internal use of the dvb-usb-lib
- */
-#ifndef _DVB_USB_COMMON_H_
-#define _DVB_USB_COMMON_H_
-
-#define DVB_USB_LOG_PREFIX "dvb-usb"
-#include "dvb-usb.h"
-
-extern int dvb_usb_debug;
-extern int dvb_usb_disable_rc_polling;
-
-#define deb_info(args...)  dprintk(dvb_usb_debug,0x001,args)
-#define deb_xfer(args...)  dprintk(dvb_usb_debug,0x002,args)
-#define deb_pll(args...)   dprintk(dvb_usb_debug,0x004,args)
-#define deb_ts(args...)    dprintk(dvb_usb_debug,0x008,args)
-#define deb_err(args...)   dprintk(dvb_usb_debug,0x010,args)
-#define deb_rc(args...)    dprintk(dvb_usb_debug,0x020,args)
-#define deb_fw(args...)    dprintk(dvb_usb_debug,0x040,args)
-#define deb_mem(args...)   dprintk(dvb_usb_debug,0x080,args)
-#define deb_uxfer(args...) dprintk(dvb_usb_debug,0x100,args)
-
-/* commonly used  methods */
-extern int dvb_usb_download_firmware(struct usb_device *, struct dvb_usb_device_properties *);
-
-extern int dvb_usb_device_power_ctrl(struct dvb_usb_device *d, int onoff);
-
-extern int usb_urb_init(struct usb_data_stream *stream, struct usb_data_stream_properties *props);
-extern int usb_urb_exit(struct usb_data_stream *stream);
-extern int usb_urb_submit(struct usb_data_stream *stream);
-extern int usb_urb_kill(struct usb_data_stream *stream);
-
-extern int dvb_usb_adapter_stream_init(struct dvb_usb_adapter *adap);
-extern int dvb_usb_adapter_stream_exit(struct dvb_usb_adapter *adap);
-
-extern int dvb_usb_i2c_init(struct dvb_usb_device *);
-extern int dvb_usb_i2c_exit(struct dvb_usb_device *);
-
-extern int dvb_usb_adapter_dvb_init(struct dvb_usb_adapter *adap,
-				    short *adapter_nums);
-extern int dvb_usb_adapter_dvb_exit(struct dvb_usb_adapter *adap);
-extern int dvb_usb_adapter_frontend_init(struct dvb_usb_adapter *adap);
-extern int dvb_usb_adapter_frontend_exit(struct dvb_usb_adapter *adap);
-
-extern int dvb_usb_remote_init(struct dvb_usb_device *);
-extern int dvb_usb_remote_exit(struct dvb_usb_device *);
-
-#endif
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c b/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
deleted file mode 100644
index ddf282f..0000000
--- a/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
+++ /dev/null
@@ -1,289 +0,0 @@
-/* dvb-usb-dvb.c is part of the DVB USB library.
- *
- * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de)
- * see dvb-usb-init.c for copyright information.
- *
- * This file contains functions for initializing and handling the
- * linux-dvb API.
- */
-#include "dvb-usb-common.h"
-
-/* does the complete input transfer handling */
-static int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff)
-{
-	struct dvb_usb_adapter *adap = dvbdmxfeed->demux->priv;
-	int newfeedcount, ret;
-
-	if (adap == NULL)
-		return -ENODEV;
-
-	if ((adap->active_fe < 0) ||
-	    (adap->active_fe >= adap->num_frontends_initialized)) {
-		return -EINVAL;
-	}
-
-	newfeedcount = adap->feedcount + (onoff ? 1 : -1);
-
-	/* stop feed before setting a new pid if there will be no pid anymore */
-	if (newfeedcount == 0) {
-		deb_ts("stop feeding\n");
-		usb_urb_kill(&adap->fe_adap[adap->active_fe].stream);
-
-		if (adap->props.fe[adap->active_fe].streaming_ctrl != NULL) {
-			ret = adap->props.fe[adap->active_fe].streaming_ctrl(adap, 0);
-			if (ret < 0) {
-				err("error while stopping stream.");
-				return ret;
-			}
-		}
-	}
-
-	adap->feedcount = newfeedcount;
-
-	/* activate the pid on the device specific pid_filter */
-	deb_ts("setting pid (%s): %5d %04x at index %d '%s'\n",
-		adap->fe_adap[adap->active_fe].pid_filtering ?
-		"yes" : "no", dvbdmxfeed->pid, dvbdmxfeed->pid,
-		dvbdmxfeed->index, onoff ? "on" : "off");
-	if (adap->props.fe[adap->active_fe].caps & DVB_USB_ADAP_HAS_PID_FILTER &&
-		adap->fe_adap[adap->active_fe].pid_filtering &&
-		adap->props.fe[adap->active_fe].pid_filter != NULL)
-		adap->props.fe[adap->active_fe].pid_filter(adap, dvbdmxfeed->index, dvbdmxfeed->pid, onoff);
-
-	/* start the feed if this was the first feed and there is still a feed
-	 * for reception.
-	 */
-	if (adap->feedcount == onoff && adap->feedcount > 0) {
-		deb_ts("submitting all URBs\n");
-		usb_urb_submit(&adap->fe_adap[adap->active_fe].stream);
-
-		deb_ts("controlling pid parser\n");
-		if (adap->props.fe[adap->active_fe].caps & DVB_USB_ADAP_HAS_PID_FILTER &&
-			adap->props.fe[adap->active_fe].caps &
-			DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF &&
-			adap->props.fe[adap->active_fe].pid_filter_ctrl != NULL) {
-			ret = adap->props.fe[adap->active_fe].pid_filter_ctrl(adap,
-				adap->fe_adap[adap->active_fe].pid_filtering);
-			if (ret < 0) {
-				err("could not handle pid_parser");
-				return ret;
-			}
-		}
-		deb_ts("start feeding\n");
-		if (adap->props.fe[adap->active_fe].streaming_ctrl != NULL) {
-			ret = adap->props.fe[adap->active_fe].streaming_ctrl(adap, 1);
-			if (ret < 0) {
-				err("error while enabling fifo.");
-				return ret;
-			}
-		}
-
-	}
-	return 0;
-}
-
-static int dvb_usb_start_feed(struct dvb_demux_feed *dvbdmxfeed)
-{
-	deb_ts("start pid: 0x%04x, feedtype: %d\n", dvbdmxfeed->pid,dvbdmxfeed->type);
-	return dvb_usb_ctrl_feed(dvbdmxfeed,1);
-}
-
-static int dvb_usb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
-{
-	deb_ts("stop pid: 0x%04x, feedtype: %d\n", dvbdmxfeed->pid, dvbdmxfeed->type);
-	return dvb_usb_ctrl_feed(dvbdmxfeed,0);
-}
-
-int dvb_usb_adapter_dvb_init(struct dvb_usb_adapter *adap, short *adapter_nums)
-{
-	int i;
-	int ret = dvb_register_adapter(&adap->dvb_adap, adap->dev->desc->name,
-				       adap->dev->owner, &adap->dev->udev->dev,
-				       adapter_nums);
-
-	if (ret < 0) {
-		deb_info("dvb_register_adapter failed: error %d", ret);
-		goto err;
-	}
-	adap->dvb_adap.priv = adap;
-	adap->dvb_adap.fe_ioctl_override = adap->props.fe_ioctl_override;
-
-	if (adap->dev->props.read_mac_address) {
-		if (adap->dev->props.read_mac_address(adap->dev,adap->dvb_adap.proposed_mac) == 0)
-			info("MAC address: %pM",adap->dvb_adap.proposed_mac);
-		else
-			err("MAC address reading failed.");
-	}
-
-
-	adap->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING;
-	adap->demux.priv             = adap;
-
-	adap->demux.filternum        = 0;
-	for (i = 0; i < adap->props.num_frontends; i++) {
-		if (adap->demux.filternum < adap->fe_adap[i].max_feed_count)
-			adap->demux.filternum = adap->fe_adap[i].max_feed_count;
-	}
-	adap->demux.feednum          = adap->demux.filternum;
-	adap->demux.start_feed       = dvb_usb_start_feed;
-	adap->demux.stop_feed        = dvb_usb_stop_feed;
-	adap->demux.write_to_decoder = NULL;
-	if ((ret = dvb_dmx_init(&adap->demux)) < 0) {
-		err("dvb_dmx_init failed: error %d",ret);
-		goto err_dmx;
-	}
-
-	adap->dmxdev.filternum       = adap->demux.filternum;
-	adap->dmxdev.demux           = &adap->demux.dmx;
-	adap->dmxdev.capabilities    = 0;
-	if ((ret = dvb_dmxdev_init(&adap->dmxdev, &adap->dvb_adap)) < 0) {
-		err("dvb_dmxdev_init failed: error %d",ret);
-		goto err_dmx_dev;
-	}
-
-	if ((ret = dvb_net_init(&adap->dvb_adap, &adap->dvb_net,
-						&adap->demux.dmx)) < 0) {
-		err("dvb_net_init failed: error %d",ret);
-		goto err_net_init;
-	}
-
-	adap->state |= DVB_USB_ADAP_STATE_DVB;
-	return 0;
-
-err_net_init:
-	dvb_dmxdev_release(&adap->dmxdev);
-err_dmx_dev:
-	dvb_dmx_release(&adap->demux);
-err_dmx:
-	dvb_unregister_adapter(&adap->dvb_adap);
-err:
-	return ret;
-}
-
-int dvb_usb_adapter_dvb_exit(struct dvb_usb_adapter *adap)
-{
-	if (adap->state & DVB_USB_ADAP_STATE_DVB) {
-		deb_info("unregistering DVB part\n");
-		dvb_net_release(&adap->dvb_net);
-		adap->demux.dmx.close(&adap->demux.dmx);
-		dvb_dmxdev_release(&adap->dmxdev);
-		dvb_dmx_release(&adap->demux);
-		dvb_unregister_adapter(&adap->dvb_adap);
-		adap->state &= ~DVB_USB_ADAP_STATE_DVB;
-	}
-	return 0;
-}
-
-static int dvb_usb_set_active_fe(struct dvb_frontend *fe, int onoff)
-{
-	struct dvb_usb_adapter *adap = fe->dvb->priv;
-
-	int ret = (adap->props.frontend_ctrl) ?
-		adap->props.frontend_ctrl(fe, onoff) : 0;
-
-	if (ret < 0) {
-		err("frontend_ctrl request failed");
-		return ret;
-	}
-	if (onoff)
-		adap->active_fe = fe->id;
-
-	return 0;
-}
-
-static int dvb_usb_fe_wakeup(struct dvb_frontend *fe)
-{
-	struct dvb_usb_adapter *adap = fe->dvb->priv;
-
-	dvb_usb_device_power_ctrl(adap->dev, 1);
-
-	dvb_usb_set_active_fe(fe, 1);
-
-	if (adap->fe_adap[fe->id].fe_init)
-		adap->fe_adap[fe->id].fe_init(fe);
-
-	return 0;
-}
-
-static int dvb_usb_fe_sleep(struct dvb_frontend *fe)
-{
-	struct dvb_usb_adapter *adap = fe->dvb->priv;
-
-	if (adap->fe_adap[fe->id].fe_sleep)
-		adap->fe_adap[fe->id].fe_sleep(fe);
-
-	dvb_usb_set_active_fe(fe, 0);
-
-	return dvb_usb_device_power_ctrl(adap->dev, 0);
-}
-
-int dvb_usb_adapter_frontend_init(struct dvb_usb_adapter *adap)
-{
-	int ret, i;
-
-	/* register all given adapter frontends */
-	for (i = 0; i < adap->props.num_frontends; i++) {
-
-		if (adap->props.fe[i].frontend_attach == NULL) {
-			err("strange: '%s' #%d,%d "
-			    "doesn't want to attach a frontend.",
-			    adap->dev->desc->name, adap->id, i);
-
-			return 0;
-		}
-
-		ret = adap->props.fe[i].frontend_attach(adap);
-		if (ret || adap->fe_adap[i].fe == NULL) {
-			/* only print error when there is no FE at all */
-			if (i == 0)
-				err("no frontend was attached by '%s'",
-					adap->dev->desc->name);
-
-			return 0;
-		}
-
-		adap->fe_adap[i].fe->id = i;
-
-		/* re-assign sleep and wakeup functions */
-		adap->fe_adap[i].fe_init = adap->fe_adap[i].fe->ops.init;
-		adap->fe_adap[i].fe->ops.init  = dvb_usb_fe_wakeup;
-		adap->fe_adap[i].fe_sleep = adap->fe_adap[i].fe->ops.sleep;
-		adap->fe_adap[i].fe->ops.sleep = dvb_usb_fe_sleep;
-
-		if (dvb_register_frontend(&adap->dvb_adap, adap->fe_adap[i].fe)) {
-			err("Frontend %d registration failed.", i);
-			dvb_frontend_detach(adap->fe_adap[i].fe);
-			adap->fe_adap[i].fe = NULL;
-			/* In error case, do not try register more FEs,
-			 * still leaving already registered FEs alive. */
-			if (i == 0)
-				return -ENODEV;
-			else
-				return 0;
-		}
-
-		/* only attach the tuner if the demod is there */
-		if (adap->props.fe[i].tuner_attach != NULL)
-			adap->props.fe[i].tuner_attach(adap);
-
-		adap->num_frontends_initialized++;
-	}
-
-	return 0;
-}
-
-int dvb_usb_adapter_frontend_exit(struct dvb_usb_adapter *adap)
-{
-	int i = adap->num_frontends_initialized - 1;
-
-	/* unregister all given adapter frontends */
-	for (; i >= 0; i--) {
-		if (adap->fe_adap[i].fe != NULL) {
-			dvb_unregister_frontend(adap->fe_adap[i].fe);
-			dvb_frontend_detach(adap->fe_adap[i].fe);
-		}
-	}
-	adap->num_frontends_initialized = 0;
-
-	return 0;
-}
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c b/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c
deleted file mode 100644
index 733a7ff..0000000
--- a/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c
+++ /dev/null
@@ -1,146 +0,0 @@
-/* dvb-usb-firmware.c is part of the DVB USB library.
- *
- * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de)
- * see dvb-usb-init.c for copyright information.
- *
- * This file contains functions for downloading the firmware to Cypress FX 1 and 2 based devices.
- *
- * FIXME: This part does actually not belong to dvb-usb, but to the usb-subsystem.
- */
-#include "dvb-usb-common.h"
-
-#include <linux/usb.h>
-
-struct usb_cypress_controller {
-	int id;
-	const char *name;       /* name of the usb controller */
-	u16 cpu_cs_register;    /* needs to be restarted, when the firmware has been downloaded. */
-};
-
-static struct usb_cypress_controller cypress[] = {
-	{ .id = DEVICE_SPECIFIC, .name = "Device specific", .cpu_cs_register = 0 },
-	{ .id = CYPRESS_AN2135,  .name = "Cypress AN2135",  .cpu_cs_register = 0x7f92 },
-	{ .id = CYPRESS_AN2235,  .name = "Cypress AN2235",  .cpu_cs_register = 0x7f92 },
-	{ .id = CYPRESS_FX2,     .name = "Cypress FX2",     .cpu_cs_register = 0xe600 },
-};
-
-/*
- * load a firmware packet to the device
- */
-static int usb_cypress_writemem(struct usb_device *udev,u16 addr,u8 *data, u8 len)
-{
-	return usb_control_msg(udev, usb_sndctrlpipe(udev,0),
-			0xa0, USB_TYPE_VENDOR, addr, 0x00, data, len, 5000);
-}
-
-int usb_cypress_load_firmware(struct usb_device *udev, const struct firmware *fw, int type)
-{
-	struct hexline hx;
-	u8 reset;
-	int ret,pos=0;
-
-	/* stop the CPU */
-	reset = 1;
-	if ((ret = usb_cypress_writemem(udev,cypress[type].cpu_cs_register,&reset,1)) != 1)
-		err("could not stop the USB controller CPU.");
-
-	while ((ret = dvb_usb_get_hexline(fw,&hx,&pos)) > 0) {
-		deb_fw("writing to address 0x%04x (buffer: 0x%02x %02x)\n",hx.addr,hx.len,hx.chk);
-		ret = usb_cypress_writemem(udev,hx.addr,hx.data,hx.len);
-
-		if (ret != hx.len) {
-			err("error while transferring firmware "
-				"(transferred size: %d, block size: %d)",
-				ret,hx.len);
-			ret = -EINVAL;
-			break;
-		}
-	}
-	if (ret < 0) {
-		err("firmware download failed at %d with %d",pos,ret);
-		return ret;
-	}
-
-	if (ret == 0) {
-		/* restart the CPU */
-		reset = 0;
-		if (ret || usb_cypress_writemem(udev,cypress[type].cpu_cs_register,&reset,1) != 1) {
-			err("could not restart the USB controller CPU.");
-			ret = -EINVAL;
-		}
-	} else
-		ret = -EIO;
-
-	return ret;
-}
-EXPORT_SYMBOL(usb_cypress_load_firmware);
-
-int dvb_usb_download_firmware(struct usb_device *udev, struct dvb_usb_device_properties *props)
-{
-	int ret;
-	const struct firmware *fw = NULL;
-
-	if ((ret = request_firmware(&fw, props->firmware, &udev->dev)) != 0) {
-		err("did not find the firmware file. (%s) "
-			"Please see linux/Documentation/dvb/ for more details on firmware-problems. (%d)",
-			props->firmware,ret);
-		return ret;
-	}
-
-	info("downloading firmware from file '%s'",props->firmware);
-
-	switch (props->usb_ctrl) {
-		case CYPRESS_AN2135:
-		case CYPRESS_AN2235:
-		case CYPRESS_FX2:
-			ret = usb_cypress_load_firmware(udev, fw, props->usb_ctrl);
-			break;
-		case DEVICE_SPECIFIC:
-			if (props->download_firmware)
-				ret = props->download_firmware(udev,fw);
-			else {
-				err("BUG: driver didn't specified a download_firmware-callback, although it claims to have a DEVICE_SPECIFIC one.");
-				ret = -EINVAL;
-			}
-			break;
-		default:
-			ret = -EINVAL;
-			break;
-	}
-
-	release_firmware(fw);
-	return ret;
-}
-
-int dvb_usb_get_hexline(const struct firmware *fw, struct hexline *hx,
-			       int *pos)
-{
-	u8 *b = (u8 *) &fw->data[*pos];
-	int data_offs = 4;
-	if (*pos >= fw->size)
-		return 0;
-
-	memset(hx,0,sizeof(struct hexline));
-
-	hx->len  = b[0];
-
-	if ((*pos + hx->len + 4) >= fw->size)
-		return -EINVAL;
-
-	hx->addr = b[1] | (b[2] << 8);
-	hx->type = b[3];
-
-	if (hx->type == 0x04) {
-		/* b[4] and b[5] are the Extended linear address record data field */
-		hx->addr |= (b[4] << 24) | (b[5] << 16);
-/*		hx->len -= 2;
-		data_offs += 2; */
-	}
-	memcpy(hx->data,&b[data_offs],hx->len);
-	hx->chk = b[hx->len + data_offs];
-
-	*pos += hx->len + 5;
-
-	return *pos;
-}
-EXPORT_SYMBOL(dvb_usb_get_hexline);
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c b/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c
deleted file mode 100644
index 88e4a62..0000000
--- a/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c
+++ /dev/null
@@ -1,43 +0,0 @@
-/* dvb-usb-i2c.c is part of the DVB USB library.
- *
- * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de)
- * see dvb-usb-init.c for copyright information.
- *
- * This file contains functions for (de-)initializing an I2C adapter.
- */
-#include "dvb-usb-common.h"
-
-int dvb_usb_i2c_init(struct dvb_usb_device *d)
-{
-	int ret = 0;
-
-	if (!(d->props.caps & DVB_USB_IS_AN_I2C_ADAPTER))
-		return 0;
-
-	if (d->props.i2c_algo == NULL) {
-		err("no i2c algorithm specified");
-		return -EINVAL;
-	}
-
-	strlcpy(d->i2c_adap.name, d->desc->name, sizeof(d->i2c_adap.name));
-	d->i2c_adap.algo      = d->props.i2c_algo;
-	d->i2c_adap.algo_data = NULL;
-	d->i2c_adap.dev.parent = &d->udev->dev;
-
-	i2c_set_adapdata(&d->i2c_adap, d);
-
-	if ((ret = i2c_add_adapter(&d->i2c_adap)) < 0)
-		err("could not add i2c adapter");
-
-	d->state |= DVB_USB_STATE_I2C;
-
-	return ret;
-}
-
-int dvb_usb_i2c_exit(struct dvb_usb_device *d)
-{
-	if (d->state & DVB_USB_STATE_I2C)
-		i2c_del_adapter(&d->i2c_adap);
-	d->state &= ~DVB_USB_STATE_I2C;
-	return 0;
-}
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
deleted file mode 100644
index 26c4481..0000000
--- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
+++ /dev/null
@@ -1,361 +0,0 @@
-/* dvb-usb-ids.h is part of the DVB USB library.
- *
- * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) see
- * dvb-usb-init.c for copyright information.
- *
- * a header file containing define's for the USB device supported by the
- * various drivers.
- */
-#ifndef _DVB_USB_IDS_H_
-#define _DVB_USB_IDS_H_
-
-/* Vendor IDs */
-#define USB_VID_ADSTECH				0x06e1
-#define USB_VID_AFATECH				0x15a4
-#define USB_VID_ALCOR_MICRO			0x058f
-#define USB_VID_ALINK				0x05e3
-#define USB_VID_AMT				0x1c73
-#define USB_VID_ANCHOR				0x0547
-#define USB_VID_ANSONIC				0x10b9
-#define USB_VID_ANUBIS_ELECTRONIC		0x10fd
-#define USB_VID_ASUS				0x0b05
-#define USB_VID_AVERMEDIA			0x07ca
-#define USB_VID_COMPRO				0x185b
-#define USB_VID_COMPRO_UNK			0x145f
-#define USB_VID_CONEXANT			0x0572
-#define USB_VID_CYPRESS				0x04b4
-#define USB_VID_DIBCOM				0x10b8
-#define USB_VID_DPOSH				0x1498
-#define USB_VID_DVICO				0x0fe9
-#define USB_VID_E3C				0x18b4
-#define USB_VID_ELGATO				0x0fd9
-#define USB_VID_EMPIA				0xeb1a
-#define USB_VID_GENPIX				0x09c0
-#define USB_VID_GRANDTEC			0x5032
-#define USB_VID_GTEK				0x1f4d
-#define USB_VID_HANFTEK				0x15f4
-#define USB_VID_HAUPPAUGE			0x2040
-#define USB_VID_HYPER_PALTEK			0x1025
-#define USB_VID_INTEL				0x8086
-#define USB_VID_ITETECH				0x048d
-#define USB_VID_KWORLD				0xeb2a
-#define USB_VID_KWORLD_2			0x1b80
-#define USB_VID_KYE				0x0458
-#define USB_VID_LEADTEK				0x0413
-#define USB_VID_LITEON				0x04ca
-#define USB_VID_MEDION				0x1660
-#define USB_VID_MIGLIA				0x18f3
-#define USB_VID_MSI				0x0db0
-#define USB_VID_MSI_2				0x1462
-#define USB_VID_OPERA1				0x695c
-#define USB_VID_PINNACLE			0x2304
-#define USB_VID_PCTV				0x2013
-#define USB_VID_PIXELVIEW			0x1554
-#define USB_VID_REALTEK				0x0bda
-#define USB_VID_TECHNOTREND			0x0b48
-#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
-#define USB_VID_WIDEVIEW			0x14aa
-#define USB_VID_GIGABYTE			0x1044
-#define USB_VID_YUAN				0x1164
-#define USB_VID_XTENSIONS			0x1ae7
-#define USB_VID_HUMAX_COEX			0x10b9
-#define USB_VID_774				0x7a69
-#define USB_VID_EVOLUTEPC			0x1e59
-#define USB_VID_AZUREWAVE			0x13d3
-#define USB_VID_TECHNISAT			0x14f7
-
-/* Product IDs */
-#define USB_PID_ADSTECH_USB2_COLD			0xa333
-#define USB_PID_ADSTECH_USB2_WARM			0xa334
-#define USB_PID_AFATECH_AF9005				0x9020
-#define USB_PID_AFATECH_AF9015_9015			0x9015
-#define USB_PID_AFATECH_AF9015_9016			0x9016
-#define USB_PID_AFATECH_AF9035_1000			0x1000
-#define USB_PID_AFATECH_AF9035_1001			0x1001
-#define USB_PID_AFATECH_AF9035_1002			0x1002
-#define USB_PID_AFATECH_AF9035_1003			0x1003
-#define USB_PID_AFATECH_AF9035_9035			0x9035
-#define USB_PID_TREKSTOR_DVBT				0x901b
-#define USB_VID_ALINK_DTU				0xf170
-#define USB_PID_ANSONIC_DVBT_USB			0x6000
-#define USB_PID_ANYSEE					0x861f
-#define USB_PID_AZUREWAVE_AD_TU700			0x3237
-#define USB_PID_AZUREWAVE_6007				0x0ccd
-#define USB_PID_AVERMEDIA_DVBT_USB_COLD			0x0001
-#define USB_PID_AVERMEDIA_DVBT_USB_WARM			0x0002
-#define USB_PID_AVERMEDIA_DVBT_USB2_COLD		0xa800
-#define USB_PID_AVERMEDIA_DVBT_USB2_WARM		0xa801
-#define USB_PID_COMPRO_DVBU2000_COLD			0xd000
-#define USB_PID_COMPRO_DVBU2000_WARM			0xd001
-#define USB_PID_COMPRO_DVBU2000_UNK_COLD		0x010c
-#define USB_PID_COMPRO_DVBU2000_UNK_WARM		0x010d
-#define USB_PID_COMPRO_VIDEOMATE_U500			0x1e78
-#define USB_PID_COMPRO_VIDEOMATE_U500_PC		0x1e80
-#define USB_PID_CONCEPTRONIC_CTVDIGRCU			0xe397
-#define USB_PID_CONEXANT_D680_DMB			0x86d6
-#define USB_PID_CREATIX_CTX1921				0x1921
-#define USB_PID_DELOCK_USB2_DVBT			0xb803
-#define USB_PID_DIBCOM_HOOK_DEFAULT			0x0064
-#define USB_PID_DIBCOM_HOOK_DEFAULT_REENUM		0x0065
-#define USB_PID_DIBCOM_MOD3000_COLD			0x0bb8
-#define USB_PID_DIBCOM_MOD3000_WARM			0x0bb9
-#define USB_PID_DIBCOM_MOD3001_COLD			0x0bc6
-#define USB_PID_DIBCOM_MOD3001_WARM			0x0bc7
-#define USB_PID_DIBCOM_STK7700P				0x1e14
-#define USB_PID_DIBCOM_STK7700P_PC			0x1e78
-#define USB_PID_DIBCOM_STK7700D				0x1ef0
-#define USB_PID_DIBCOM_STK7700_U7000			0x7001
-#define USB_PID_DIBCOM_STK7070P				0x1ebc
-#define USB_PID_DIBCOM_STK7070PD			0x1ebe
-#define USB_PID_DIBCOM_STK807XP				0x1f90
-#define USB_PID_DIBCOM_STK807XPVR			0x1f98
-#define USB_PID_DIBCOM_STK8096GP                        0x1fa0
-#define USB_PID_DIBCOM_NIM8096MD                        0x1fa8
-#define USB_PID_DIBCOM_TFE8096P				0x1f9C
-#define USB_PID_DIBCOM_ANCHOR_2135_COLD			0x2131
-#define USB_PID_DIBCOM_STK7770P				0x1e80
-#define USB_PID_DIBCOM_NIM7090				0x1bb2
-#define USB_PID_DIBCOM_TFE7090PVR			0x1bb4
-#define USB_PID_DIBCOM_TFE7090E				0x1bb7
-#define USB_PID_DIBCOM_TFE7790E				0x1e6e
-#define USB_PID_DIBCOM_NIM9090M				0x2383
-#define USB_PID_DIBCOM_NIM9090MD			0x2384
-#define USB_PID_DPOSH_M9206_COLD			0x9206
-#define USB_PID_DPOSH_M9206_WARM			0xa090
-#define USB_PID_E3C_EC168				0x1689
-#define USB_PID_E3C_EC168_2				0xfffa
-#define USB_PID_E3C_EC168_3				0xfffb
-#define USB_PID_E3C_EC168_4				0x1001
-#define USB_PID_E3C_EC168_5				0x1002
-#define USB_PID_FREECOM_DVBT				0x0160
-#define USB_PID_FREECOM_DVBT_2				0x0161
-#define USB_PID_UNIWILL_STK7700P			0x6003
-#define USB_PID_GENIUS_TVGO_DVB_T03			0x4012
-#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_ITETECH_IT9135				0x9135
-#define USB_PID_ITETECH_IT9135_9005			0x9005
-#define USB_PID_ITETECH_IT9135_9006			0x9006
-#define USB_PID_KWORLD_399U				0xe399
-#define USB_PID_KWORLD_399U_2				0xe400
-#define USB_PID_KWORLD_395U				0xe396
-#define USB_PID_KWORLD_395U_2				0xe39b
-#define USB_PID_KWORLD_395U_3				0xe395
-#define USB_PID_KWORLD_395U_4				0xe39a
-#define USB_PID_KWORLD_MC810				0xc810
-#define USB_PID_KWORLD_PC160_2T				0xc160
-#define USB_PID_KWORLD_PC160_T				0xc161
-#define USB_PID_KWORLD_UB383_T				0xe383
-#define USB_PID_KWORLD_UB499_2T_T09			0xe409
-#define USB_PID_KWORLD_VSTREAM_COLD			0x17de
-#define USB_PID_KWORLD_VSTREAM_WARM			0x17df
-#define USB_PID_TERRATEC_CINERGY_T_USB_XE		0x0055
-#define USB_PID_TERRATEC_CINERGY_T_USB_XE_REV2		0x0069
-#define USB_PID_TERRATEC_CINERGY_T_STICK		0x0093
-#define USB_PID_TERRATEC_CINERGY_T_STICK_RC		0x0097
-#define USB_PID_TERRATEC_CINERGY_T_STICK_DUAL_RC	0x0099
-#define USB_PID_TERRATEC_CINERGY_T_STICK_BLACK_REV1	0x00a9
-#define USB_PID_TWINHAN_VP7041_COLD			0x3201
-#define USB_PID_TWINHAN_VP7041_WARM			0x3202
-#define USB_PID_TWINHAN_VP7020_COLD			0x3203
-#define USB_PID_TWINHAN_VP7020_WARM			0x3204
-#define USB_PID_TWINHAN_VP7045_COLD			0x3205
-#define USB_PID_TWINHAN_VP7045_WARM			0x3206
-#define USB_PID_TWINHAN_VP7021_COLD			0x3207
-#define USB_PID_TWINHAN_VP7021_WARM			0x3208
-#define USB_PID_TINYTWIN				0x3226
-#define USB_PID_TINYTWIN_2				0xe402
-#define USB_PID_TINYTWIN_3				0x9016
-#define USB_PID_DNTV_TINYUSB2_COLD			0x3223
-#define USB_PID_DNTV_TINYUSB2_WARM			0x3224
-#define USB_PID_ULTIMA_TVBOX_COLD			0x8105
-#define USB_PID_ULTIMA_TVBOX_WARM			0x8106
-#define USB_PID_ULTIMA_TVBOX_AN2235_COLD		0x8107
-#define USB_PID_ULTIMA_TVBOX_AN2235_WARM		0x8108
-#define USB_PID_ULTIMA_TVBOX_ANCHOR_COLD		0x2235
-#define USB_PID_ULTIMA_TVBOX_USB2_COLD			0x8109
-#define USB_PID_ULTIMA_TVBOX_USB2_WARM			0x810a
-#define USB_PID_ARTEC_T14_COLD				0x810b
-#define USB_PID_ARTEC_T14_WARM				0x810c
-#define USB_PID_ARTEC_T14BR				0x810f
-#define USB_PID_ULTIMA_TVBOX_USB2_FX_COLD		0x8613
-#define USB_PID_ULTIMA_TVBOX_USB2_FX_WARM		0x1002
-#define USB_PID_UNK_HYPER_PALTEK_COLD			0x005e
-#define USB_PID_UNK_HYPER_PALTEK_WARM			0x005f
-#define USB_PID_HANFTEK_UMT_010_COLD			0x0001
-#define USB_PID_HANFTEK_UMT_010_WARM			0x0015
-#define USB_PID_DTT200U_COLD				0x0201
-#define USB_PID_DTT200U_WARM				0x0301
-#define USB_PID_WT220U_ZAP250_COLD			0x0220
-#define USB_PID_WT220U_COLD				0x0222
-#define USB_PID_WT220U_WARM				0x0221
-#define USB_PID_WT220U_FC_COLD				0x0225
-#define USB_PID_WT220U_FC_WARM				0x0226
-#define USB_PID_WT220U_ZL0353_COLD			0x022a
-#define USB_PID_WT220U_ZL0353_WARM			0x022b
-#define USB_PID_WINTV_NOVA_T_USB2_COLD			0x9300
-#define USB_PID_WINTV_NOVA_T_USB2_WARM			0x9301
-#define USB_PID_HAUPPAUGE_NOVA_T_500			0x9941
-#define USB_PID_HAUPPAUGE_NOVA_T_500_2			0x9950
-#define USB_PID_HAUPPAUGE_NOVA_T_500_3			0x8400
-#define USB_PID_HAUPPAUGE_NOVA_T_STICK			0x7050
-#define USB_PID_HAUPPAUGE_NOVA_T_STICK_2		0x7060
-#define USB_PID_HAUPPAUGE_NOVA_T_STICK_3		0x7070
-#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
-#define USB_PID_AVERMEDIA_VOLAR_A868R			0xa868
-#define USB_PID_AVERMEDIA_MCE_USB_M038			0x1228
-#define USB_PID_AVERMEDIA_HYBRID_ULTRA_USB_M039R	0x0039
-#define USB_PID_AVERMEDIA_HYBRID_ULTRA_USB_M039R_ATSC	0x1039
-#define USB_PID_AVERMEDIA_HYBRID_ULTRA_USB_M039R_DVBT	0x2039
-#define USB_PID_AVERMEDIA_VOLAR_X			0xa815
-#define USB_PID_AVERMEDIA_VOLAR_X_2			0x8150
-#define USB_PID_AVERMEDIA_A309				0xa309
-#define USB_PID_AVERMEDIA_A310				0xa310
-#define USB_PID_AVERMEDIA_A850				0x850a
-#define USB_PID_AVERMEDIA_A850T				0x850b
-#define USB_PID_AVERMEDIA_A805				0xa805
-#define USB_PID_AVERMEDIA_A815M				0x815a
-#define USB_PID_AVERMEDIA_A835				0xa835
-#define USB_PID_AVERMEDIA_B835				0xb835
-#define USB_PID_AVERMEDIA_1867				0x1867
-#define USB_PID_AVERMEDIA_A867				0xa867
-#define USB_PID_AVERMEDIA_TWINSTAR			0x0825
-#define USB_PID_TECHNOTREND_CONNECT_S2400               0x3006
-#define USB_PID_TECHNOTREND_CONNECT_CT3650		0x300d
-#define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY	0x005a
-#define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY_2	0x0081
-#define USB_PID_TERRATEC_CINERGY_HT_USB_XE		0x0058
-#define USB_PID_TERRATEC_CINERGY_HT_EXPRESS		0x0060
-#define USB_PID_TERRATEC_CINERGY_T_EXPRESS		0x0062
-#define USB_PID_TERRATEC_CINERGY_T_XXS			0x0078
-#define USB_PID_TERRATEC_CINERGY_T_XXS_2		0x00ab
-#define USB_PID_TERRATEC_H7				0x10b4
-#define USB_PID_TERRATEC_H7_2				0x10a3
-#define USB_PID_TERRATEC_T3				0x10a0
-#define USB_PID_TERRATEC_T5				0x10a1
-#define USB_PID_NOXON_DAB_STICK				0x00b3
-#define USB_PID_PINNACLE_EXPRESSCARD_320CX		0x022e
-#define USB_PID_PINNACLE_PCTV2000E			0x022c
-#define USB_PID_PINNACLE_PCTV_DVB_T_FLASH		0x0228
-#define USB_PID_PINNACLE_PCTV_DUAL_DIVERSITY_DVB_T	0x0229
-#define USB_PID_PINNACLE_PCTV71E			0x022b
-#define USB_PID_PINNACLE_PCTV72E			0x0236
-#define USB_PID_PINNACLE_PCTV73E			0x0237
-#define USB_PID_PINNACLE_PCTV310E			0x3211
-#define USB_PID_PINNACLE_PCTV801E			0x023a
-#define USB_PID_PINNACLE_PCTV801E_SE			0x023b
-#define USB_PID_PINNACLE_PCTV340E			0x023d
-#define USB_PID_PINNACLE_PCTV340E_SE			0x023e
-#define USB_PID_PINNACLE_PCTV73A			0x0243
-#define USB_PID_PINNACLE_PCTV73ESE			0x0245
-#define USB_PID_PINNACLE_PCTV74E			0x0246
-#define USB_PID_PINNACLE_PCTV282E			0x0248
-#define USB_PID_PIXELVIEW_SBTVD				0x5010
-#define USB_PID_PCTV_200E				0x020e
-#define USB_PID_PCTV_400E				0x020f
-#define USB_PID_PCTV_450E				0x0222
-#define USB_PID_PCTV_452E				0x021f
-#define USB_PID_REALTEK_RTL2831U			0x2831
-#define USB_PID_REALTEK_RTL2832U			0x2832
-#define USB_PID_TECHNOTREND_CONNECT_S2_3600		0x3007
-#define USB_PID_TECHNOTREND_CONNECT_S2_3650_CI		0x300a
-#define USB_PID_NEBULA_DIGITV				0x0201
-#define USB_PID_DVICO_BLUEBIRD_LGDT			0xd820
-#define USB_PID_DVICO_BLUEBIRD_LG064F_COLD		0xd500
-#define USB_PID_DVICO_BLUEBIRD_LG064F_WARM		0xd501
-#define USB_PID_DVICO_BLUEBIRD_LGZ201_COLD		0xdb00
-#define USB_PID_DVICO_BLUEBIRD_LGZ201_WARM		0xdb01
-#define USB_PID_DVICO_BLUEBIRD_TH7579_COLD		0xdb10
-#define USB_PID_DVICO_BLUEBIRD_TH7579_WARM		0xdb11
-#define USB_PID_DVICO_BLUEBIRD_DUAL_1_COLD		0xdb50
-#define USB_PID_DVICO_BLUEBIRD_DUAL_1_WARM		0xdb51
-#define USB_PID_DVICO_BLUEBIRD_DUAL_2_COLD		0xdb58
-#define USB_PID_DVICO_BLUEBIRD_DUAL_2_WARM		0xdb59
-#define USB_PID_DVICO_BLUEBIRD_DUAL_4			0xdb78
-#define USB_PID_DVICO_BLUEBIRD_DUAL_4_REV_2		0xdb98
-#define USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2		0xdb70
-#define USB_PID_DVICO_BLUEBIRD_DVB_T_NANO_2_NFW_WARM	0xdb71
-#define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_COLD		0xdb54
-#define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_WARM		0xdb55
-#define USB_PID_MEDION_MD95700				0x0932
-#define USB_PID_MSI_MEGASKY580				0x5580
-#define USB_PID_MSI_MEGASKY580_55801			0x5581
-#define USB_PID_KYE_DVB_T_COLD				0x701e
-#define USB_PID_KYE_DVB_T_WARM				0x701f
-#define USB_PID_LITEON_DVB_T_COLD			0xf000
-#define USB_PID_LITEON_DVB_T_WARM			0xf001
-#define USB_PID_DIGIVOX_MINI_SL_COLD			0xe360
-#define USB_PID_DIGIVOX_MINI_SL_WARM			0xe361
-#define USB_PID_GRANDTEC_DVBT_USB2_COLD			0x0bc6
-#define USB_PID_GRANDTEC_DVBT_USB2_WARM			0x0bc7
-#define USB_PID_WINFAST_DTV2000DS			0x6a04
-#define USB_PID_WINFAST_DTV_DONGLE_COLD			0x6025
-#define USB_PID_WINFAST_DTV_DONGLE_WARM			0x6026
-#define USB_PID_WINFAST_DTV_DONGLE_STK7700P		0x6f00
-#define USB_PID_WINFAST_DTV_DONGLE_H			0x60f6
-#define USB_PID_WINFAST_DTV_DONGLE_STK7700P_2		0x6f01
-#define USB_PID_WINFAST_DTV_DONGLE_GOLD			0x6029
-#define USB_PID_GENPIX_8PSK_REV_1_COLD			0x0200
-#define USB_PID_GENPIX_8PSK_REV_1_WARM			0x0201
-#define USB_PID_GENPIX_8PSK_REV_2			0x0202
-#define USB_PID_GENPIX_SKYWALKER_1			0x0203
-#define USB_PID_GENPIX_SKYWALKER_CW3K			0x0204
-#define USB_PID_GENPIX_SKYWALKER_2			0x0206
-#define USB_PID_SIGMATEK_DVB_110			0x6610
-#define USB_PID_MSI_DIGI_VOX_MINI_II			0x1513
-#define USB_PID_MSI_DIGIVOX_DUO				0x8801
-#define USB_PID_OPERA1_COLD				0x2830
-#define USB_PID_OPERA1_WARM				0x3829
-#define USB_PID_LIFEVIEW_TV_WALKER_TWIN_COLD		0x0514
-#define USB_PID_LIFEVIEW_TV_WALKER_TWIN_WARM		0x0513
-#define USB_PID_GIGABYTE_U7000				0x7001
-#define USB_PID_GIGABYTE_U8000				0x7002
-#define USB_PID_ASUS_U3000				0x171f
-#define USB_PID_ASUS_U3000H				0x1736
-#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_YUAN_STK7700D				0x1efc
-#define USB_PID_YUAN_STK7700D_2				0x1e8c
-#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_MYGICA_D689				0xd811
-#define USB_PID_ELGATO_EYETV_DIVERSITY			0x0011
-#define USB_PID_ELGATO_EYETV_DTT			0x0021
-#define USB_PID_ELGATO_EYETV_DTT_2			0x003f
-#define USB_PID_ELGATO_EYETV_DTT_Dlx			0x0020
-#define USB_PID_ELGATO_EYETV_SAT			0x002a
-#define USB_PID_DVB_T_USB_STICK_HIGH_SPEED_COLD		0x5000
-#define USB_PID_DVB_T_USB_STICK_HIGH_SPEED_WARM		0x5001
-#define USB_PID_FRIIO_WHITE				0x0001
-#define USB_PID_TVWAY_PLUS				0x0002
-#define USB_PID_SVEON_STV20				0xe39d
-#define USB_PID_SVEON_STV22				0xe401
-#define USB_PID_SVEON_STV22_IT9137			0xe411
-#define USB_PID_AZUREWAVE_AZ6027			0x3275
-#define USB_PID_TERRATEC_DVBS2CI_V1			0x10a4
-#define USB_PID_TERRATEC_DVBS2CI_V2			0x10ac
-#define USB_PID_TECHNISAT_USB2_HDCI_V1			0x0001
-#define USB_PID_TECHNISAT_USB2_HDCI_V2			0x0002
-#define USB_PID_TECHNISAT_AIRSTAR_TELESTICK_2		0x0004
-#define USB_PID_TECHNISAT_USB2_DVB_S2			0x0500
-#endif
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-init.c b/drivers/media/dvb/dvb-usb/dvb-usb-init.c
deleted file mode 100644
index 169196e..0000000
--- a/drivers/media/dvb/dvb-usb/dvb-usb-init.c
+++ /dev/null
@@ -1,304 +0,0 @@
-/*
- * DVB USB library - provides a generic interface for a DVB USB device driver.
- *
- * dvb-usb-init.c
- *
- * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de)
- *
- *	This program is free software; you can redistribute it and/or modify it
- *	under the terms of the GNU General Public License as published by the Free
- *	Software Foundation, version 2.
- *
- * see Documentation/dvb/README.dvb-usb for more information
- */
-#include "dvb-usb-common.h"
-
-/* debug */
-int dvb_usb_debug;
-module_param_named(debug, dvb_usb_debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,pll=4,ts=8,err=16,rc=32,fw=64,mem=128,uxfer=256  (or-able))." DVB_USB_DEBUG_STATUS);
-
-int dvb_usb_disable_rc_polling;
-module_param_named(disable_rc_polling, dvb_usb_disable_rc_polling, int, 0644);
-MODULE_PARM_DESC(disable_rc_polling, "disable remote control polling (default: 0).");
-
-static int dvb_usb_force_pid_filter_usage;
-module_param_named(force_pid_filter_usage, dvb_usb_force_pid_filter_usage, int, 0444);
-MODULE_PARM_DESC(force_pid_filter_usage, "force all dvb-usb-devices to use a PID filter, if any (default: 0).");
-
-static int dvb_usb_adapter_init(struct dvb_usb_device *d, short *adapter_nrs)
-{
-	struct dvb_usb_adapter *adap;
-	int ret, n, o;
-
-	for (n = 0; n < d->props.num_adapters; n++) {
-		adap = &d->adapter[n];
-		adap->dev = d;
-		adap->id  = n;
-
-		memcpy(&adap->props, &d->props.adapter[n], sizeof(struct dvb_usb_adapter_properties));
-
-	for (o = 0; o < adap->props.num_frontends; o++) {
-		struct dvb_usb_adapter_fe_properties *props = &adap->props.fe[o];
-		/* speed - when running at FULL speed we need a HW PID filter */
-		if (d->udev->speed == USB_SPEED_FULL && !(props->caps & DVB_USB_ADAP_HAS_PID_FILTER)) {
-			err("This USB2.0 device cannot be run on a USB1.1 port. (it lacks a hardware PID filter)");
-			return -ENODEV;
-		}
-
-		if ((d->udev->speed == USB_SPEED_FULL && props->caps & DVB_USB_ADAP_HAS_PID_FILTER) ||
-			(props->caps & DVB_USB_ADAP_NEED_PID_FILTERING)) {
-			info("will use the device's hardware PID filter (table count: %d).", props->pid_filter_count);
-			adap->fe_adap[o].pid_filtering  = 1;
-			adap->fe_adap[o].max_feed_count = props->pid_filter_count;
-		} else {
-			info("will pass the complete MPEG2 transport stream to the software demuxer.");
-			adap->fe_adap[o].pid_filtering  = 0;
-			adap->fe_adap[o].max_feed_count = 255;
-		}
-
-		if (!adap->fe_adap[o].pid_filtering &&
-			dvb_usb_force_pid_filter_usage &&
-			props->caps & DVB_USB_ADAP_HAS_PID_FILTER) {
-			info("pid filter enabled by module option.");
-			adap->fe_adap[o].pid_filtering  = 1;
-			adap->fe_adap[o].max_feed_count = props->pid_filter_count;
-		}
-
-		if (props->size_of_priv > 0) {
-			adap->fe_adap[o].priv = kzalloc(props->size_of_priv, GFP_KERNEL);
-			if (adap->fe_adap[o].priv == NULL) {
-				err("no memory for priv for adapter %d fe %d.", n, o);
-				return -ENOMEM;
-			}
-		}
-	}
-
-		if (adap->props.size_of_priv > 0) {
-			adap->priv = kzalloc(adap->props.size_of_priv, GFP_KERNEL);
-			if (adap->priv == NULL) {
-				err("no memory for priv for adapter %d.", n);
-				return -ENOMEM;
-			}
-		}
-
-		if ((ret = dvb_usb_adapter_stream_init(adap)) ||
-			(ret = dvb_usb_adapter_dvb_init(adap, adapter_nrs)) ||
-			(ret = dvb_usb_adapter_frontend_init(adap))) {
-			return ret;
-		}
-
-		/* use exclusive FE lock if there is multiple shared FEs */
-		if (adap->fe_adap[1].fe)
-			adap->dvb_adap.mfe_shared = 1;
-
-		d->num_adapters_initialized++;
-		d->state |= DVB_USB_STATE_DVB;
-	}
-
-	/*
-	 * when reloading the driver w/o replugging the device
-	 * sometimes a timeout occures, this helps
-	 */
-	if (d->props.generic_bulk_ctrl_endpoint != 0) {
-		usb_clear_halt(d->udev, usb_sndbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint));
-		usb_clear_halt(d->udev, usb_rcvbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint));
-	}
-
-	return 0;
-}
-
-static int dvb_usb_adapter_exit(struct dvb_usb_device *d)
-{
-	int n;
-
-	for (n = 0; n < d->num_adapters_initialized; n++) {
-		dvb_usb_adapter_frontend_exit(&d->adapter[n]);
-		dvb_usb_adapter_dvb_exit(&d->adapter[n]);
-		dvb_usb_adapter_stream_exit(&d->adapter[n]);
-		kfree(d->adapter[n].priv);
-	}
-	d->num_adapters_initialized = 0;
-	d->state &= ~DVB_USB_STATE_DVB;
-	return 0;
-}
-
-
-/* general initialization functions */
-static int dvb_usb_exit(struct dvb_usb_device *d)
-{
-	deb_info("state before exiting everything: %x\n", d->state);
-	dvb_usb_remote_exit(d);
-	dvb_usb_adapter_exit(d);
-	dvb_usb_i2c_exit(d);
-	deb_info("state should be zero now: %x\n", d->state);
-	d->state = DVB_USB_STATE_INIT;
-	kfree(d->priv);
-	kfree(d);
-	return 0;
-}
-
-static int dvb_usb_init(struct dvb_usb_device *d, short *adapter_nums)
-{
-	int ret = 0;
-
-	mutex_init(&d->usb_mutex);
-	mutex_init(&d->i2c_mutex);
-
-	d->state = DVB_USB_STATE_INIT;
-
-	if (d->props.size_of_priv > 0) {
-		d->priv = kzalloc(d->props.size_of_priv, GFP_KERNEL);
-		if (d->priv == NULL) {
-			err("no memory for priv in 'struct dvb_usb_device'");
-			return -ENOMEM;
-		}
-	}
-
-	/* check the capabilities and set appropriate variables */
-	dvb_usb_device_power_ctrl(d, 1);
-
-	if ((ret = dvb_usb_i2c_init(d)) ||
-		(ret = dvb_usb_adapter_init(d, adapter_nums))) {
-		dvb_usb_exit(d);
-		return ret;
-	}
-
-	if ((ret = dvb_usb_remote_init(d)))
-		err("could not initialize remote control.");
-
-	dvb_usb_device_power_ctrl(d, 0);
-
-	return 0;
-}
-
-/* determine the name and the state of the just found USB device */
-static struct dvb_usb_device_description *dvb_usb_find_device(struct usb_device *udev, struct dvb_usb_device_properties *props, int *cold)
-{
-	int i, j;
-	struct dvb_usb_device_description *desc = NULL;
-
-	*cold = -1;
-
-	for (i = 0; i < props->num_device_descs; i++) {
-
-		for (j = 0; j < DVB_USB_ID_MAX_NUM && props->devices[i].cold_ids[j] != NULL; j++) {
-			deb_info("check for cold %x %x\n", props->devices[i].cold_ids[j]->idVendor, props->devices[i].cold_ids[j]->idProduct);
-			if (props->devices[i].cold_ids[j]->idVendor  == le16_to_cpu(udev->descriptor.idVendor) &&
-				props->devices[i].cold_ids[j]->idProduct == le16_to_cpu(udev->descriptor.idProduct)) {
-				*cold = 1;
-				desc = &props->devices[i];
-				break;
-			}
-		}
-
-		if (desc != NULL)
-			break;
-
-		for (j = 0; j < DVB_USB_ID_MAX_NUM && props->devices[i].warm_ids[j] != NULL; j++) {
-			deb_info("check for warm %x %x\n", props->devices[i].warm_ids[j]->idVendor, props->devices[i].warm_ids[j]->idProduct);
-			if (props->devices[i].warm_ids[j]->idVendor == le16_to_cpu(udev->descriptor.idVendor) &&
-				props->devices[i].warm_ids[j]->idProduct == le16_to_cpu(udev->descriptor.idProduct)) {
-				*cold = 0;
-				desc = &props->devices[i];
-				break;
-			}
-		}
-	}
-
-	if (desc != NULL && props->identify_state != NULL)
-		props->identify_state(udev, props, &desc, cold);
-
-	return desc;
-}
-
-int dvb_usb_device_power_ctrl(struct dvb_usb_device *d, int onoff)
-{
-	if (onoff)
-		d->powered++;
-	else
-		d->powered--;
-
-	if (d->powered == 0 || (onoff && d->powered == 1)) { /* when switching from 1 to 0 or from 0 to 1 */
-		deb_info("power control: %d\n", onoff);
-		if (d->props.power_ctrl)
-			return d->props.power_ctrl(d, onoff);
-	}
-	return 0;
-}
-
-/*
- * USB
- */
-int dvb_usb_device_init(struct usb_interface *intf,
-			struct dvb_usb_device_properties *props,
-			struct module *owner, struct dvb_usb_device **du,
-			short *adapter_nums)
-{
-	struct usb_device *udev = interface_to_usbdev(intf);
-	struct dvb_usb_device *d = NULL;
-	struct dvb_usb_device_description *desc = NULL;
-
-	int ret = -ENOMEM, cold = 0;
-
-	if (du != NULL)
-		*du = NULL;
-
-	if ((desc = dvb_usb_find_device(udev, props, &cold)) == NULL) {
-		deb_err("something went very wrong, device was not found in current device list - let's see what comes next.\n");
-		return -ENODEV;
-	}
-
-	if (cold) {
-		info("found a '%s' in cold state, will try to load a firmware", desc->name);
-		ret = dvb_usb_download_firmware(udev, props);
-		if (!props->no_reconnect || ret != 0)
-			return ret;
-	}
-
-	info("found a '%s' in warm state.", desc->name);
-	d = kzalloc(sizeof(struct dvb_usb_device), GFP_KERNEL);
-	if (d == NULL) {
-		err("no memory for 'struct dvb_usb_device'");
-		return -ENOMEM;
-	}
-
-	d->udev = udev;
-	memcpy(&d->props, props, sizeof(struct dvb_usb_device_properties));
-	d->desc = desc;
-	d->owner = owner;
-
-	usb_set_intfdata(intf, d);
-
-	if (du != NULL)
-		*du = d;
-
-	ret = dvb_usb_init(d, adapter_nums);
-
-	if (ret == 0)
-		info("%s successfully initialized and connected.", desc->name);
-	else
-		info("%s error while loading driver (%d)", desc->name, ret);
-	return ret;
-}
-EXPORT_SYMBOL(dvb_usb_device_init);
-
-void dvb_usb_device_exit(struct usb_interface *intf)
-{
-	struct dvb_usb_device *d = usb_get_intfdata(intf);
-	const char *name = "generic DVB-USB module";
-
-	usb_set_intfdata(intf, NULL);
-	if (d != NULL && d->desc != NULL) {
-		name = d->desc->name;
-		dvb_usb_exit(d);
-	}
-	info("%s successfully deinitialized and disconnected.", name);
-
-}
-EXPORT_SYMBOL(dvb_usb_device_exit);
-
-MODULE_VERSION("1.0");
-MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
-MODULE_DESCRIPTION("A library module containing commonly used USB and DVB function USB DVB devices");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c
deleted file mode 100644
index 41bacff..0000000
--- a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c
+++ /dev/null
@@ -1,391 +0,0 @@
-/* dvb-usb-remote.c is part of the DVB USB library.
- *
- * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de)
- * see dvb-usb-init.c for copyright information.
- *
- * This file contains functions for initializing the input-device and for handling remote-control-queries.
- */
-#include "dvb-usb-common.h"
-#include <linux/usb/input.h>
-
-static unsigned int
-legacy_dvb_usb_get_keymap_index(const struct input_keymap_entry *ke,
-				struct rc_map_table *keymap,
-				unsigned int keymap_size)
-{
-	unsigned int index;
-	unsigned int scancode;
-
-	if (ke->flags & INPUT_KEYMAP_BY_INDEX) {
-		index = ke->index;
-	} else {
-		if (input_scancode_to_scalar(ke, &scancode))
-			return keymap_size;
-
-		/* See if we can match the raw key code. */
-		for (index = 0; index < keymap_size; index++)
-			if (keymap[index].scancode == scancode)
-				break;
-
-		/* See if there is an unused hole in the map */
-		if (index >= keymap_size) {
-			for (index = 0; index < keymap_size; index++) {
-				if (keymap[index].keycode == KEY_RESERVED ||
-				    keymap[index].keycode == KEY_UNKNOWN) {
-					break;
-				}
-			}
-		}
-	}
-
-	return index;
-}
-
-static int legacy_dvb_usb_getkeycode(struct input_dev *dev,
-				     struct input_keymap_entry *ke)
-{
-	struct dvb_usb_device *d = input_get_drvdata(dev);
-	struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table;
-	unsigned int keymap_size = d->props.rc.legacy.rc_map_size;
-	unsigned int index;
-
-	index = legacy_dvb_usb_get_keymap_index(ke, keymap, keymap_size);
-	if (index >= keymap_size)
-		return -EINVAL;
-
-	ke->keycode = keymap[index].keycode;
-	if (ke->keycode == KEY_UNKNOWN)
-		ke->keycode = KEY_RESERVED;
-	ke->len = sizeof(keymap[index].scancode);
-	memcpy(&ke->scancode, &keymap[index].scancode, ke->len);
-	ke->index = index;
-
-	return 0;
-}
-
-static int legacy_dvb_usb_setkeycode(struct input_dev *dev,
-				     const struct input_keymap_entry *ke,
-				     unsigned int *old_keycode)
-{
-	struct dvb_usb_device *d = input_get_drvdata(dev);
-	struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table;
-	unsigned int keymap_size = d->props.rc.legacy.rc_map_size;
-	unsigned int index;
-
-	index = legacy_dvb_usb_get_keymap_index(ke, keymap, keymap_size);
-	/*
-	 * FIXME: Currently, it is not possible to increase the size of
-	 * scancode table. For it to happen, one possibility
-	 * would be to allocate a table with key_map_size + 1,
-	 * copying data, appending the new key on it, and freeing
-	 * the old one - or maybe just allocating some spare space
-	 */
-	if (index >= keymap_size)
-		return -EINVAL;
-
-	*old_keycode = keymap[index].keycode;
-	keymap->keycode = ke->keycode;
-	__set_bit(ke->keycode, dev->keybit);
-
-	if (*old_keycode != KEY_RESERVED) {
-		__clear_bit(*old_keycode, dev->keybit);
-		for (index = 0; index < keymap_size; index++) {
-			if (keymap[index].keycode == *old_keycode) {
-				__set_bit(*old_keycode, dev->keybit);
-				break;
-			}
-		}
-	}
-
-	return 0;
-}
-
-/* Remote-control poll function - called every dib->rc_query_interval ms to see
- * whether the remote control has received anything.
- *
- * TODO: Fix the repeat rate of the input device.
- */
-static void legacy_dvb_usb_read_remote_control(struct work_struct *work)
-{
-	struct dvb_usb_device *d =
-		container_of(work, struct dvb_usb_device, rc_query_work.work);
-	u32 event;
-	int state;
-
-	/* TODO: need a lock here.  We can simply skip checking for the remote control
-	   if we're busy. */
-
-	/* when the parameter has been set to 1 via sysfs while the driver was running */
-	if (dvb_usb_disable_rc_polling)
-		return;
-
-	if (d->props.rc.legacy.rc_query(d,&event,&state)) {
-		err("error while querying for an remote control event.");
-		goto schedule;
-	}
-
-
-	switch (state) {
-		case REMOTE_NO_KEY_PRESSED:
-			break;
-		case REMOTE_KEY_PRESSED:
-			deb_rc("key pressed\n");
-			d->last_event = event;
-		case REMOTE_KEY_REPEAT:
-			deb_rc("key repeated\n");
-			input_event(d->input_dev, EV_KEY, event, 1);
-			input_sync(d->input_dev);
-			input_event(d->input_dev, EV_KEY, d->last_event, 0);
-			input_sync(d->input_dev);
-			break;
-		default:
-			break;
-	}
-
-/* improved repeat handling ???
-	switch (state) {
-		case REMOTE_NO_KEY_PRESSED:
-			deb_rc("NO KEY PRESSED\n");
-			if (d->last_state != REMOTE_NO_KEY_PRESSED) {
-				deb_rc("releasing event %d\n",d->last_event);
-				input_event(d->rc_input_dev, EV_KEY, d->last_event, 0);
-				input_sync(d->rc_input_dev);
-			}
-			d->last_state = REMOTE_NO_KEY_PRESSED;
-			d->last_event = 0;
-			break;
-		case REMOTE_KEY_PRESSED:
-			deb_rc("KEY PRESSED\n");
-			deb_rc("pressing event %d\n",event);
-
-			input_event(d->rc_input_dev, EV_KEY, event, 1);
-			input_sync(d->rc_input_dev);
-
-			d->last_event = event;
-			d->last_state = REMOTE_KEY_PRESSED;
-			break;
-		case REMOTE_KEY_REPEAT:
-			deb_rc("KEY_REPEAT\n");
-			if (d->last_state != REMOTE_NO_KEY_PRESSED) {
-				deb_rc("repeating event %d\n",d->last_event);
-				input_event(d->rc_input_dev, EV_KEY, d->last_event, 2);
-				input_sync(d->rc_input_dev);
-				d->last_state = REMOTE_KEY_REPEAT;
-			}
-		default:
-			break;
-	}
-*/
-
-schedule:
-	schedule_delayed_work(&d->rc_query_work,msecs_to_jiffies(d->props.rc.legacy.rc_interval));
-}
-
-static int legacy_dvb_usb_remote_init(struct dvb_usb_device *d)
-{
-	int i, err, rc_interval;
-	struct input_dev *input_dev;
-
-	input_dev = input_allocate_device();
-	if (!input_dev)
-		return -ENOMEM;
-
-	input_dev->evbit[0] = BIT_MASK(EV_KEY);
-	input_dev->name = "IR-receiver inside an USB DVB receiver";
-	input_dev->phys = d->rc_phys;
-	usb_to_input_id(d->udev, &input_dev->id);
-	input_dev->dev.parent = &d->udev->dev;
-	d->input_dev = input_dev;
-	d->rc_dev = NULL;
-
-	input_dev->getkeycode = legacy_dvb_usb_getkeycode;
-	input_dev->setkeycode = legacy_dvb_usb_setkeycode;
-
-	/* set the bits for the keys */
-	deb_rc("key map size: %d\n", d->props.rc.legacy.rc_map_size);
-	for (i = 0; i < d->props.rc.legacy.rc_map_size; i++) {
-		deb_rc("setting bit for event %d item %d\n",
-			d->props.rc.legacy.rc_map_table[i].keycode, i);
-		set_bit(d->props.rc.legacy.rc_map_table[i].keycode, input_dev->keybit);
-	}
-
-	/* setting these two values to non-zero, we have to manage key repeats */
-	input_dev->rep[REP_PERIOD] = d->props.rc.legacy.rc_interval;
-	input_dev->rep[REP_DELAY]  = d->props.rc.legacy.rc_interval + 150;
-
-	input_set_drvdata(input_dev, d);
-
-	err = input_register_device(input_dev);
-	if (err)
-		input_free_device(input_dev);
-
-	rc_interval = d->props.rc.legacy.rc_interval;
-
-	INIT_DELAYED_WORK(&d->rc_query_work, legacy_dvb_usb_read_remote_control);
-
-	info("schedule remote query interval to %d msecs.", rc_interval);
-	schedule_delayed_work(&d->rc_query_work,
-			      msecs_to_jiffies(rc_interval));
-
-	d->state |= DVB_USB_STATE_REMOTE;
-
-	return err;
-}
-
-/* Remote-control poll function - called every dib->rc_query_interval ms to see
- * whether the remote control has received anything.
- *
- * TODO: Fix the repeat rate of the input device.
- */
-static void dvb_usb_read_remote_control(struct work_struct *work)
-{
-	struct dvb_usb_device *d =
-		container_of(work, struct dvb_usb_device, rc_query_work.work);
-	int err;
-
-	/* TODO: need a lock here.  We can simply skip checking for the remote control
-	   if we're busy. */
-
-	/* when the parameter has been set to 1 via sysfs while the
-	 * driver was running, or when bulk mode is enabled after IR init
-	 */
-	if (dvb_usb_disable_rc_polling || d->props.rc.core.bulk_mode)
-		return;
-
-	err = d->props.rc.core.rc_query(d);
-	if (err)
-		err("error %d while querying for an remote control event.", err);
-
-	schedule_delayed_work(&d->rc_query_work,
-			      msecs_to_jiffies(d->props.rc.core.rc_interval));
-}
-
-static int rc_core_dvb_usb_remote_init(struct dvb_usb_device *d)
-{
-	int err, rc_interval;
-	struct rc_dev *dev;
-
-	dev = rc_allocate_device();
-	if (!dev)
-		return -ENOMEM;
-
-	dev->driver_name = d->props.rc.core.module_name;
-	dev->map_name = d->props.rc.core.rc_codes;
-	dev->change_protocol = d->props.rc.core.change_protocol;
-	dev->allowed_protos = d->props.rc.core.allowed_protos;
-	dev->driver_type = d->props.rc.core.driver_type;
-	usb_to_input_id(d->udev, &dev->input_id);
-	dev->input_name = "IR-receiver inside an USB DVB receiver";
-	dev->input_phys = d->rc_phys;
-	dev->dev.parent = &d->udev->dev;
-	dev->priv = d;
-
-	err = rc_register_device(dev);
-	if (err < 0) {
-		rc_free_device(dev);
-		return err;
-	}
-
-	d->input_dev = NULL;
-	d->rc_dev = dev;
-
-	if (!d->props.rc.core.rc_query || d->props.rc.core.bulk_mode)
-		return 0;
-
-	/* Polling mode - initialize a work queue for handling it */
-	INIT_DELAYED_WORK(&d->rc_query_work, dvb_usb_read_remote_control);
-
-	rc_interval = d->props.rc.core.rc_interval;
-
-	info("schedule remote query interval to %d msecs.", rc_interval);
-	schedule_delayed_work(&d->rc_query_work,
-			      msecs_to_jiffies(rc_interval));
-
-	return 0;
-}
-
-int dvb_usb_remote_init(struct dvb_usb_device *d)
-{
-	int err;
-
-	if (dvb_usb_disable_rc_polling)
-		return 0;
-
-	if (d->props.rc.legacy.rc_map_table && d->props.rc.legacy.rc_query)
-		d->props.rc.mode = DVB_RC_LEGACY;
-	else if (d->props.rc.core.rc_codes)
-		d->props.rc.mode = DVB_RC_CORE;
-	else
-		return 0;
-
-	usb_make_path(d->udev, d->rc_phys, sizeof(d->rc_phys));
-	strlcat(d->rc_phys, "/ir0", sizeof(d->rc_phys));
-
-	/* Start the remote-control polling. */
-	if (d->props.rc.legacy.rc_interval < 40)
-		d->props.rc.legacy.rc_interval = 100; /* default */
-
-	if (d->props.rc.mode == DVB_RC_LEGACY)
-		err = legacy_dvb_usb_remote_init(d);
-	else
-		err = rc_core_dvb_usb_remote_init(d);
-	if (err)
-		return err;
-
-	d->state |= DVB_USB_STATE_REMOTE;
-
-	return 0;
-}
-
-int dvb_usb_remote_exit(struct dvb_usb_device *d)
-{
-	if (d->state & DVB_USB_STATE_REMOTE) {
-		cancel_delayed_work_sync(&d->rc_query_work);
-		if (d->props.rc.mode == DVB_RC_LEGACY)
-			input_unregister_device(d->input_dev);
-		else
-			rc_unregister_device(d->rc_dev);
-	}
-	d->state &= ~DVB_USB_STATE_REMOTE;
-	return 0;
-}
-
-#define DVB_USB_RC_NEC_EMPTY           0x00
-#define DVB_USB_RC_NEC_KEY_PRESSED     0x01
-#define DVB_USB_RC_NEC_KEY_REPEATED    0x02
-int dvb_usb_nec_rc_key_to_event(struct dvb_usb_device *d,
-		u8 keybuf[5], u32 *event, int *state)
-{
-	int i;
-	struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table;
-	*event = 0;
-	*state = REMOTE_NO_KEY_PRESSED;
-	switch (keybuf[0]) {
-		case DVB_USB_RC_NEC_EMPTY:
-			break;
-		case DVB_USB_RC_NEC_KEY_PRESSED:
-			if ((u8) ~keybuf[1] != keybuf[2] ||
-				(u8) ~keybuf[3] != keybuf[4]) {
-				deb_err("remote control checksum failed.\n");
-				break;
-			}
-			/* See if we can match the raw key code. */
-			for (i = 0; i < d->props.rc.legacy.rc_map_size; i++)
-				if (rc5_custom(&keymap[i]) == keybuf[1] &&
-					rc5_data(&keymap[i]) == keybuf[3]) {
-					*event = keymap[i].keycode;
-					*state = REMOTE_KEY_PRESSED;
-					return 0;
-				}
-			deb_err("key mapping failed - no appropriate key found in keymapping\n");
-			break;
-		case DVB_USB_RC_NEC_KEY_REPEATED:
-			*state = REMOTE_KEY_REPEAT;
-			break;
-		default:
-			deb_err("unknown type of remote status: %d\n",keybuf[0]);
-			break;
-	}
-	return 0;
-}
-EXPORT_SYMBOL(dvb_usb_nec_rc_key_to_event);
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-urb.c b/drivers/media/dvb/dvb-usb/dvb-usb-urb.c
deleted file mode 100644
index 5c8f651..0000000
--- a/drivers/media/dvb/dvb-usb/dvb-usb-urb.c
+++ /dev/null
@@ -1,121 +0,0 @@
-/* dvb-usb-urb.c is part of the DVB USB library.
- *
- * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de)
- * see dvb-usb-init.c for copyright information.
- *
- * This file keeps functions for initializing and handling the
- * USB and URB stuff.
- */
-#include "dvb-usb-common.h"
-
-int dvb_usb_generic_rw(struct dvb_usb_device *d, u8 *wbuf, u16 wlen, u8 *rbuf,
-	u16 rlen, int delay_ms)
-{
-	int actlen,ret = -ENOMEM;
-
-	if (!d || wbuf == NULL || wlen == 0)
-		return -EINVAL;
-
-	if (d->props.generic_bulk_ctrl_endpoint == 0) {
-		err("endpoint for generic control not specified.");
-		return -EINVAL;
-	}
-
-	if ((ret = mutex_lock_interruptible(&d->usb_mutex)))
-		return ret;
-
-	deb_xfer(">>> ");
-	debug_dump(wbuf,wlen,deb_xfer);
-
-	ret = usb_bulk_msg(d->udev,usb_sndbulkpipe(d->udev,
-			d->props.generic_bulk_ctrl_endpoint), wbuf,wlen,&actlen,
-			2000);
-
-	if (ret)
-		err("bulk message failed: %d (%d/%d)",ret,wlen,actlen);
-	else
-		ret = actlen != wlen ? -1 : 0;
-
-	/* an answer is expected, and no error before */
-	if (!ret && rbuf && rlen) {
-		if (delay_ms)
-			msleep(delay_ms);
-
-		ret = usb_bulk_msg(d->udev,usb_rcvbulkpipe(d->udev,
-				d->props.generic_bulk_ctrl_endpoint_response ?
-				d->props.generic_bulk_ctrl_endpoint_response :
-				d->props.generic_bulk_ctrl_endpoint),rbuf,rlen,&actlen,
-				2000);
-
-		if (ret)
-			err("recv bulk message failed: %d",ret);
-		else {
-			deb_xfer("<<< ");
-			debug_dump(rbuf,actlen,deb_xfer);
-		}
-	}
-
-	mutex_unlock(&d->usb_mutex);
-	return ret;
-}
-EXPORT_SYMBOL(dvb_usb_generic_rw);
-
-int dvb_usb_generic_write(struct dvb_usb_device *d, u8 *buf, u16 len)
-{
-	return dvb_usb_generic_rw(d,buf,len,NULL,0,0);
-}
-EXPORT_SYMBOL(dvb_usb_generic_write);
-
-static void dvb_usb_data_complete(struct usb_data_stream *stream, u8 *buffer, size_t length)
-{
-	struct dvb_usb_adapter *adap = stream->user_priv;
-	if (adap->feedcount > 0 && adap->state & DVB_USB_ADAP_STATE_DVB)
-		dvb_dmx_swfilter(&adap->demux, buffer, length);
-}
-
-static void dvb_usb_data_complete_204(struct usb_data_stream *stream, u8 *buffer, size_t length)
-{
-	struct dvb_usb_adapter *adap = stream->user_priv;
-	if (adap->feedcount > 0 && adap->state & DVB_USB_ADAP_STATE_DVB)
-		dvb_dmx_swfilter_204(&adap->demux, buffer, length);
-}
-
-static void dvb_usb_data_complete_raw(struct usb_data_stream *stream,
-				      u8 *buffer, size_t length)
-{
-	struct dvb_usb_adapter *adap = stream->user_priv;
-	if (adap->feedcount > 0 && adap->state & DVB_USB_ADAP_STATE_DVB)
-		dvb_dmx_swfilter_raw(&adap->demux, buffer, length);
-}
-
-int dvb_usb_adapter_stream_init(struct dvb_usb_adapter *adap)
-{
-	int i, ret = 0;
-	for (i = 0; i < adap->props.num_frontends; i++) {
-
-		adap->fe_adap[i].stream.udev      = adap->dev->udev;
-		if (adap->props.fe[i].caps & DVB_USB_ADAP_RECEIVES_204_BYTE_TS)
-			adap->fe_adap[i].stream.complete =
-				dvb_usb_data_complete_204;
-		else
-		if (adap->props.fe[i].caps & DVB_USB_ADAP_RECEIVES_RAW_PAYLOAD)
-			adap->fe_adap[i].stream.complete =
-				dvb_usb_data_complete_raw;
-		else
-		adap->fe_adap[i].stream.complete  = dvb_usb_data_complete;
-		adap->fe_adap[i].stream.user_priv = adap;
-		ret = usb_urb_init(&adap->fe_adap[i].stream,
-				   &adap->props.fe[i].stream);
-		if (ret < 0)
-			break;
-	}
-	return ret;
-}
-
-int dvb_usb_adapter_stream_exit(struct dvb_usb_adapter *adap)
-{
-	int i;
-	for (i = 0; i < adap->props.num_frontends; i++)
-		usb_urb_exit(&adap->fe_adap[i].stream);
-	return 0;
-}
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb.h b/drivers/media/dvb/dvb-usb/dvb-usb.h
deleted file mode 100644
index 99f9440..0000000
--- a/drivers/media/dvb/dvb-usb/dvb-usb.h
+++ /dev/null
@@ -1,485 +0,0 @@
-/* dvb-usb.h is part of the DVB USB library.
- *
- * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de)
- * see dvb-usb-init.c for copyright information.
- *
- * the headerfile, all dvb-usb-drivers have to include.
- *
- * TODO: clean-up the structures for unused fields and update the comments
- */
-#ifndef __DVB_USB_H__
-#define __DVB_USB_H__
-
-#include <linux/input.h>
-#include <linux/usb.h>
-#include <linux/firmware.h>
-#include <linux/mutex.h>
-#include <media/rc-core.h>
-
-#include "dvb_frontend.h"
-#include "dvb_demux.h"
-#include "dvb_net.h"
-#include "dmxdev.h"
-
-#include "dvb-pll.h"
-
-#include "dvb-usb-ids.h"
-
-/* debug */
-#ifdef CONFIG_DVB_USB_DEBUG
-#define dprintk(var,level,args...) \
-	    do { if ((var & level)) { printk(args); } } while (0)
-
-#define debug_dump(b,l,func) {\
-	int loop_; \
-	for (loop_ = 0; loop_ < l; loop_++) func("%02x ", b[loop_]); \
-	func("\n");\
-}
-#define DVB_USB_DEBUG_STATUS
-#else
-#define dprintk(args...)
-#define debug_dump(b,l,func)
-
-#define DVB_USB_DEBUG_STATUS " (debugging is not enabled)"
-
-#endif
-
-/* generic log methods - taken from usb.h */
-#ifndef DVB_USB_LOG_PREFIX
- #define DVB_USB_LOG_PREFIX "dvb-usb (please define a log prefix)"
-#endif
-
-#undef err
-#define err(format, arg...)  printk(KERN_ERR     DVB_USB_LOG_PREFIX ": " format "\n" , ## arg)
-#undef info
-#define info(format, arg...) printk(KERN_INFO    DVB_USB_LOG_PREFIX ": " format "\n" , ## arg)
-#undef warn
-#define warn(format, arg...) printk(KERN_WARNING DVB_USB_LOG_PREFIX ": " format "\n" , ## arg)
-
-/**
- * struct dvb_usb_device_description - name and its according USB IDs
- * @name: real name of the box, regardless which DVB USB device class is in use
- * @cold_ids: array of struct usb_device_id which describe the device in
- *  pre-firmware state
- * @warm_ids: array of struct usb_device_id which describe the device in
- *  post-firmware state
- *
- * Each DVB USB device class can have one or more actual devices, this struct
- * assigns a name to it.
- */
-struct dvb_usb_device_description {
-	const char *name;
-
-#define DVB_USB_ID_MAX_NUM 15
-	struct usb_device_id *cold_ids[DVB_USB_ID_MAX_NUM];
-	struct usb_device_id *warm_ids[DVB_USB_ID_MAX_NUM];
-};
-
-static inline u8 rc5_custom(struct rc_map_table *key)
-{
-	return (key->scancode >> 8) & 0xff;
-}
-
-static inline u8 rc5_data(struct rc_map_table *key)
-{
-	return key->scancode & 0xff;
-}
-
-static inline u16 rc5_scan(struct rc_map_table *key)
-{
-	return key->scancode & 0xffff;
-}
-
-struct dvb_usb_device;
-struct dvb_usb_adapter;
-struct usb_data_stream;
-
-/**
- * Properties of USB streaming - TODO this structure should be somewhere else
- * describes the kind of USB transfer used for data-streaming.
- *  (BULK or ISOC)
- */
-struct usb_data_stream_properties {
-#define USB_BULK  1
-#define USB_ISOC  2
-	int type;
-	int count;
-	int endpoint;
-
-	union {
-		struct {
-			int buffersize; /* per URB */
-		} bulk;
-		struct {
-			int framesperurb;
-			int framesize;
-			int interval;
-		} isoc;
-	} u;
-};
-
-/**
- * struct dvb_usb_adapter_properties - properties of a dvb-usb-adapter.
- *    A DVB-USB-Adapter is basically a dvb_adapter which is present on a USB-device.
- * @caps: capabilities of the DVB USB device.
- * @pid_filter_count: number of PID filter position in the optional hardware
- *  PID-filter.
- * @num_frontends: number of frontends of the DVB USB adapter.
- * @frontend_ctrl: called to power on/off active frontend.
- * @streaming_ctrl: called to start and stop the MPEG2-TS streaming of the
- *  device (not URB submitting/killing).
- * @pid_filter_ctrl: called to en/disable the PID filter, if any.
- * @pid_filter: called to set/unset a PID for filtering.
- * @frontend_attach: called to attach the possible frontends (fill fe-field
- *  of struct dvb_usb_device).
- * @tuner_attach: called to attach the correct tuner and to fill pll_addr,
- *  pll_desc and pll_init_buf of struct dvb_usb_device).
- * @stream: configuration of the USB streaming
- */
-struct dvb_usb_adapter_fe_properties {
-#define DVB_USB_ADAP_HAS_PID_FILTER               0x01
-#define DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF 0x02
-#define DVB_USB_ADAP_NEED_PID_FILTERING           0x04
-#define DVB_USB_ADAP_RECEIVES_204_BYTE_TS         0x08
-#define DVB_USB_ADAP_RECEIVES_RAW_PAYLOAD         0x10
-	int caps;
-	int pid_filter_count;
-
-	int (*streaming_ctrl)  (struct dvb_usb_adapter *, int);
-	int (*pid_filter_ctrl) (struct dvb_usb_adapter *, int);
-	int (*pid_filter)      (struct dvb_usb_adapter *, int, u16, int);
-
-	int (*frontend_attach) (struct dvb_usb_adapter *);
-	int (*tuner_attach)    (struct dvb_usb_adapter *);
-
-	struct usb_data_stream_properties stream;
-
-	int size_of_priv;
-};
-
-#define MAX_NO_OF_FE_PER_ADAP 3
-struct dvb_usb_adapter_properties {
-	int size_of_priv;
-
-	int (*frontend_ctrl)   (struct dvb_frontend *, int);
-	int (*fe_ioctl_override) (struct dvb_frontend *,
-				  unsigned int, void *, unsigned int);
-
-	int num_frontends;
-	struct dvb_usb_adapter_fe_properties fe[MAX_NO_OF_FE_PER_ADAP];
-};
-
-/**
- * struct dvb_rc_legacy - old properties of remote controller
- * @rc_map_table: a hard-wired array of struct rc_map_table (NULL to disable
- *  remote control handling).
- * @rc_map_size: number of items in @rc_map_table.
- * @rc_query: called to query an event event.
- * @rc_interval: time in ms between two queries.
- */
-struct dvb_rc_legacy {
-/* remote control properties */
-#define REMOTE_NO_KEY_PRESSED      0x00
-#define REMOTE_KEY_PRESSED         0x01
-#define REMOTE_KEY_REPEAT          0x02
-	struct rc_map_table  *rc_map_table;
-	int rc_map_size;
-	int (*rc_query) (struct dvb_usb_device *, u32 *, int *);
-	int rc_interval;
-};
-
-/**
- * struct dvb_rc properties of remote controller, using rc-core
- * @rc_codes: name of rc codes table
- * @protocol: type of protocol(s) currently used by the driver
- * @allowed_protos: protocol(s) supported by the driver
- * @driver_type: Used to point if a device supports raw mode
- * @change_protocol: callback to change protocol
- * @rc_query: called to query an event event.
- * @rc_interval: time in ms between two queries.
- * @bulk_mode: device supports bulk mode for RC (disable polling mode)
- */
-struct dvb_rc {
-	char *rc_codes;
-	u64 protocol;
-	u64 allowed_protos;
-	enum rc_driver_type driver_type;
-	int (*change_protocol)(struct rc_dev *dev, u64 rc_type);
-	char *module_name;
-	int (*rc_query) (struct dvb_usb_device *d);
-	int rc_interval;
-	bool bulk_mode;				/* uses bulk mode */
-};
-
-/**
- * enum dvb_usb_mode - Specifies if it is using a legacy driver or a new one
- *		       based on rc-core
- * This is initialized/used only inside dvb-usb-remote.c.
- * It shouldn't be set by the drivers.
- */
-enum dvb_usb_mode {
-	DVB_RC_LEGACY,
-	DVB_RC_CORE,
-};
-
-/**
- * struct dvb_usb_device_properties - properties of a dvb-usb-device
- * @usb_ctrl: which USB device-side controller is in use. Needed for firmware
- *  download.
- * @firmware: name of the firmware file.
- * @download_firmware: called to download the firmware when the usb_ctrl is
- *  DEVICE_SPECIFIC.
- * @no_reconnect: device doesn't do a reconnect after downloading the firmware,
- *  so do the warm initialization right after it
- *
- * @size_of_priv: how many bytes shall be allocated for the private field
- *  of struct dvb_usb_device.
- *
- * @power_ctrl: called to enable/disable power of the device.
- * @read_mac_address: called to read the MAC address of the device.
- * @identify_state: called to determine the state (cold or warm), when it
- *  is not distinguishable by the USB IDs.
- *
- * @rc: remote controller properties
- *
- * @i2c_algo: i2c_algorithm if the device has I2CoverUSB.
- *
- * @generic_bulk_ctrl_endpoint: most of the DVB USB devices have a generic
- *  endpoint which received control messages with bulk transfers. When this
- *  is non-zero, one can use dvb_usb_generic_rw and dvb_usb_generic_write-
- *  helper functions.
- *
- * @generic_bulk_ctrl_endpoint_response: some DVB USB devices use a separate
- *  endpoint for responses to control messages sent with bulk transfers via
- *  the generic_bulk_ctrl_endpoint. When this is non-zero, this will be used
- *  instead of the generic_bulk_ctrl_endpoint when reading usb responses in
- *  the dvb_usb_generic_rw helper function.
- *
- * @num_device_descs: number of struct dvb_usb_device_description in @devices
- * @devices: array of struct dvb_usb_device_description compatibles with these
- *  properties.
- */
-#define MAX_NO_OF_ADAPTER_PER_DEVICE 2
-struct dvb_usb_device_properties {
-
-#define DVB_USB_IS_AN_I2C_ADAPTER            0x01
-	int caps;
-
-#define DEVICE_SPECIFIC 0
-#define CYPRESS_AN2135  1
-#define CYPRESS_AN2235  2
-#define CYPRESS_FX2     3
-	int        usb_ctrl;
-	int        (*download_firmware) (struct usb_device *, const struct firmware *);
-	const char *firmware;
-	int        no_reconnect;
-
-	int size_of_priv;
-
-	int num_adapters;
-	struct dvb_usb_adapter_properties adapter[MAX_NO_OF_ADAPTER_PER_DEVICE];
-
-	int (*power_ctrl)       (struct dvb_usb_device *, int);
-	int (*read_mac_address) (struct dvb_usb_device *, u8 []);
-	int (*identify_state)   (struct usb_device *, struct dvb_usb_device_properties *,
-			struct dvb_usb_device_description **, int *);
-
-	struct {
-		enum dvb_usb_mode mode;	/* Drivers shouldn't touch on it */
-		struct dvb_rc_legacy legacy;
-		struct dvb_rc core;
-	} rc;
-
-	struct i2c_algorithm *i2c_algo;
-
-	int generic_bulk_ctrl_endpoint;
-	int generic_bulk_ctrl_endpoint_response;
-
-	int num_device_descs;
-	struct dvb_usb_device_description devices[12];
-};
-
-/**
- * struct usb_data_stream - generic object of an USB stream
- * @buf_num: number of buffer allocated.
- * @buf_size: size of each buffer in buf_list.
- * @buf_list: array containing all allocate buffers for streaming.
- * @dma_addr: list of dma_addr_t for each buffer in buf_list.
- *
- * @urbs_initialized: number of URBs initialized.
- * @urbs_submitted: number of URBs submitted.
- */
-#define MAX_NO_URBS_FOR_DATA_STREAM 10
-struct usb_data_stream {
-	struct usb_device                 *udev;
-	struct usb_data_stream_properties  props;
-
-#define USB_STATE_INIT    0x00
-#define USB_STATE_URB_BUF 0x01
-	int state;
-
-	void (*complete) (struct usb_data_stream *, u8 *, size_t);
-
-	struct urb    *urb_list[MAX_NO_URBS_FOR_DATA_STREAM];
-	int            buf_num;
-	unsigned long  buf_size;
-	u8            *buf_list[MAX_NO_URBS_FOR_DATA_STREAM];
-	dma_addr_t     dma_addr[MAX_NO_URBS_FOR_DATA_STREAM];
-
-	int urbs_initialized;
-	int urbs_submitted;
-
-	void *user_priv;
-};
-
-/**
- * struct dvb_usb_adapter - a DVB adapter on a USB device
- * @id: index of this adapter (starting with 0).
- *
- * @feedcount: number of reqested feeds (used for streaming-activation)
- * @pid_filtering: is hardware pid_filtering used or not.
- *
- * @pll_addr: I2C address of the tuner for programming
- * @pll_init: array containing the initialization buffer
- * @pll_desc: pointer to the appropriate struct dvb_pll_desc
- * @tuner_pass_ctrl: called to (de)activate tuner passthru of the demod or the board
- *
- * @dvb_adap: device's dvb_adapter.
- * @dmxdev: device's dmxdev.
- * @demux: device's software demuxer.
- * @dvb_net: device's dvb_net interfaces.
- * @dvb_frontend: device's frontend.
- * @max_feed_count: how many feeds can be handled simultaneously by this
- *  device
- *
- * @fe_init:  rerouted frontend-init (wakeup) function.
- * @fe_sleep: rerouted frontend-sleep function.
- *
- * @stream: the usb data stream.
- */
-struct dvb_usb_fe_adapter {
-	struct dvb_frontend *fe;
-
-	int (*fe_init)  (struct dvb_frontend *);
-	int (*fe_sleep) (struct dvb_frontend *);
-
-	struct usb_data_stream stream;
-
-	int pid_filtering;
-	int max_feed_count;
-
-	void *priv;
-};
-
-struct dvb_usb_adapter {
-	struct dvb_usb_device *dev;
-	struct dvb_usb_adapter_properties props;
-
-#define DVB_USB_ADAP_STATE_INIT 0x000
-#define DVB_USB_ADAP_STATE_DVB  0x001
-	int state;
-
-	u8  id;
-
-	int feedcount;
-
-	/* dvb */
-	struct dvb_adapter   dvb_adap;
-	struct dmxdev        dmxdev;
-	struct dvb_demux     demux;
-	struct dvb_net       dvb_net;
-
-	struct dvb_usb_fe_adapter fe_adap[MAX_NO_OF_FE_PER_ADAP];
-	int active_fe;
-	int num_frontends_initialized;
-
-	void *priv;
-};
-
-/**
- * struct dvb_usb_device - object of a DVB USB device
- * @props: copy of the struct dvb_usb_properties this device belongs to.
- * @desc: pointer to the device's struct dvb_usb_device_description.
- * @state: initialization and runtime state of the device.
- *
- * @powered: indicated whether the device is power or not.
- *  Powered is in/decremented for each call to modify the state.
- * @udev: pointer to the device's struct usb_device.
- *
- * @usb_mutex: semaphore of USB control messages (reading needs two messages)
- * @i2c_mutex: semaphore for i2c-transfers
- *
- * @i2c_adap: device's i2c_adapter if it uses I2CoverUSB
- *
- * @rc_dev: rc device for the remote control (rc-core mode)
- * @input_dev: input device for the remote control (legacy mode)
- * @rc_query_work: struct work_struct frequent rc queries
- * @last_event: last triggered event
- * @last_state: last state (no, pressed, repeat)
- * @owner: owner of the dvb_adapter
- * @priv: private data of the actual driver (allocate by dvb-usb, size defined
- *  in size_of_priv of dvb_usb_properties).
- */
-struct dvb_usb_device {
-	struct dvb_usb_device_properties props;
-	struct dvb_usb_device_description *desc;
-
-	struct usb_device *udev;
-
-#define DVB_USB_STATE_INIT        0x000
-#define DVB_USB_STATE_I2C         0x001
-#define DVB_USB_STATE_DVB         0x002
-#define DVB_USB_STATE_REMOTE      0x004
-	int state;
-
-	int powered;
-
-	/* locking */
-	struct mutex usb_mutex;
-
-	/* i2c */
-	struct mutex i2c_mutex;
-	struct i2c_adapter i2c_adap;
-
-	int                    num_adapters_initialized;
-	struct dvb_usb_adapter adapter[MAX_NO_OF_ADAPTER_PER_DEVICE];
-
-	/* remote control */
-	struct rc_dev *rc_dev;
-	struct input_dev *input_dev;
-	char rc_phys[64];
-	struct delayed_work rc_query_work;
-	u32 last_event;
-	int last_state;
-
-	struct module *owner;
-
-	void *priv;
-};
-
-extern int dvb_usb_device_init(struct usb_interface *,
-			       struct dvb_usb_device_properties *,
-			       struct module *, struct dvb_usb_device **,
-			       short *adapter_nums);
-extern void dvb_usb_device_exit(struct usb_interface *);
-
-/* the generic read/write method for device control */
-extern int dvb_usb_generic_rw(struct dvb_usb_device *, u8 *, u16, u8 *, u16,int);
-extern int dvb_usb_generic_write(struct dvb_usb_device *, u8 *, u16);
-
-/* commonly used remote control parsing */
-extern int dvb_usb_nec_rc_key_to_event(struct dvb_usb_device *, u8[], u32 *, int *);
-
-/* commonly used firmware download types and function */
-struct hexline {
-	u8 len;
-	u32 addr;
-	u8 type;
-	u8 data[255];
-	u8 chk;
-};
-extern int usb_cypress_load_firmware(struct usb_device *udev, const struct firmware *fw, int type);
-extern int dvb_usb_get_hexline(const struct firmware *fw, struct hexline *hx, int *pos);
-
-
-#endif
diff --git a/drivers/media/dvb/dvb-usb/dw2102.c b/drivers/media/dvb/dvb-usb/dw2102.c
deleted file mode 100644
index 9382895..0000000
--- a/drivers/media/dvb/dvb-usb/dw2102.c
+++ /dev/null
@@ -1,1951 +0,0 @@
-/* DVB USB framework compliant Linux driver for the
- *	DVBWorld DVB-S 2101, 2102, DVB-S2 2104, DVB-C 3101,
- *	TeVii S600, S630, S650, S660, S480,
- *	Prof 1100, 7500,
- *	Geniatech SU3000 Cards
- * Copyright (C) 2008-2011 Igor M. Liplianin (liplianin@me.by)
- *
- *	This program is free software; 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.
- *
- * see Documentation/dvb/README.dvb-usb for more information
- */
-#include "dw2102.h"
-#include "si21xx.h"
-#include "stv0299.h"
-#include "z0194a.h"
-#include "stv0288.h"
-#include "stb6000.h"
-#include "eds1547.h"
-#include "cx24116.h"
-#include "tda1002x.h"
-#include "mt312.h"
-#include "zl10039.h"
-#include "ds3000.h"
-#include "stv0900.h"
-#include "stv6110.h"
-#include "stb6100.h"
-#include "stb6100_proc.h"
-
-#ifndef USB_PID_DW2102
-#define USB_PID_DW2102 0x2102
-#endif
-
-#ifndef USB_PID_DW2104
-#define USB_PID_DW2104 0x2104
-#endif
-
-#ifndef USB_PID_DW3101
-#define USB_PID_DW3101 0x3101
-#endif
-
-#ifndef USB_PID_CINERGY_S
-#define USB_PID_CINERGY_S 0x0064
-#endif
-
-#ifndef USB_PID_TEVII_S630
-#define USB_PID_TEVII_S630 0xd630
-#endif
-
-#ifndef USB_PID_TEVII_S650
-#define USB_PID_TEVII_S650 0xd650
-#endif
-
-#ifndef USB_PID_TEVII_S660
-#define USB_PID_TEVII_S660 0xd660
-#endif
-
-#ifndef USB_PID_TEVII_S480_1
-#define USB_PID_TEVII_S480_1 0xd481
-#endif
-
-#ifndef USB_PID_TEVII_S480_2
-#define USB_PID_TEVII_S480_2 0xd482
-#endif
-
-#ifndef USB_PID_PROF_1100
-#define USB_PID_PROF_1100 0xb012
-#endif
-
-#define DW210X_READ_MSG 0
-#define DW210X_WRITE_MSG 1
-
-#define REG_1F_SYMBOLRATE_BYTE0 0x1f
-#define REG_20_SYMBOLRATE_BYTE1 0x20
-#define REG_21_SYMBOLRATE_BYTE2 0x21
-/* on my own*/
-#define DW2102_VOLTAGE_CTRL (0x1800)
-#define SU3000_STREAM_CTRL (0x1900)
-#define DW2102_RC_QUERY (0x1a00)
-#define DW2102_LED_CTRL (0x1b00)
-
-#define	err_str "did not find the firmware file. (%s) " \
-		"Please see linux/Documentation/dvb/ for more details " \
-		"on firmware-problems."
-
-struct rc_map_dvb_usb_table_table {
-	struct rc_map_table *rc_keys;
-	int rc_keys_size;
-};
-
-struct su3000_state {
-	u8 initialized;
-};
-
-struct s6x0_state {
-	int (*old_set_voltage)(struct dvb_frontend *f, fe_sec_voltage_t v);
-};
-
-/* debug */
-static int dvb_usb_dw2102_debug;
-module_param_named(debug, dvb_usb_dw2102_debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level (1=info 2=xfer 4=rc(or-able))."
-						DVB_USB_DEBUG_STATUS);
-
-/* keymaps */
-static int ir_keymap;
-module_param_named(keymap, ir_keymap, int, 0644);
-MODULE_PARM_DESC(keymap, "set keymap 0=default 1=dvbworld 2=tevii 3=tbs  ..."
-			" 256=none");
-
-/* demod probe */
-static int demod_probe = 1;
-module_param_named(demod, demod_probe, int, 0644);
-MODULE_PARM_DESC(demod, "demod to probe (1=cx24116 2=stv0903+stv6110 "
-			"4=stv0903+stb6100(or-able)).");
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-static int dw210x_op_rw(struct usb_device *dev, u8 request, u16 value,
-			u16 index, u8 * data, u16 len, int flags)
-{
-	int ret;
-	u8 *u8buf;
-	unsigned int pipe = (flags == DW210X_READ_MSG) ?
-				usb_rcvctrlpipe(dev, 0) : usb_sndctrlpipe(dev, 0);
-	u8 request_type = (flags == DW210X_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT;
-
-	u8buf = kmalloc(len, GFP_KERNEL);
-	if (!u8buf)
-		return -ENOMEM;
-
-
-	if (flags == DW210X_WRITE_MSG)
-		memcpy(u8buf, data, len);
-	ret = usb_control_msg(dev, pipe, request, request_type | USB_TYPE_VENDOR,
-				value, index , u8buf, len, 2000);
-
-	if (flags == DW210X_READ_MSG)
-		memcpy(data, u8buf, len);
-
-	kfree(u8buf);
-	return ret;
-}
-
-/* I2C */
-static int dw2102_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
-		int num)
-{
-	struct dvb_usb_device *d = i2c_get_adapdata(adap);
-	int i = 0;
-	u8 buf6[] = {0x2c, 0x05, 0xc0, 0, 0, 0, 0};
-	u16 value;
-
-	if (!d)
-		return -ENODEV;
-	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
-		return -EAGAIN;
-
-	switch (num) {
-	case 2:
-		/* read stv0299 register */
-		value = msg[0].buf[0];/* register */
-		for (i = 0; i < msg[1].len; i++) {
-			dw210x_op_rw(d->udev, 0xb5, value + i, 0,
-					buf6, 2, DW210X_READ_MSG);
-			msg[1].buf[i] = buf6[0];
-		}
-		break;
-	case 1:
-		switch (msg[0].addr) {
-		case 0x68:
-			/* write to stv0299 register */
-			buf6[0] = 0x2a;
-			buf6[1] = msg[0].buf[0];
-			buf6[2] = msg[0].buf[1];
-			dw210x_op_rw(d->udev, 0xb2, 0, 0,
-					buf6, 3, DW210X_WRITE_MSG);
-			break;
-		case 0x60:
-			if (msg[0].flags == 0) {
-			/* write to tuner pll */
-				buf6[0] = 0x2c;
-				buf6[1] = 5;
-				buf6[2] = 0xc0;
-				buf6[3] = msg[0].buf[0];
-				buf6[4] = msg[0].buf[1];
-				buf6[5] = msg[0].buf[2];
-				buf6[6] = msg[0].buf[3];
-				dw210x_op_rw(d->udev, 0xb2, 0, 0,
-						buf6, 7, DW210X_WRITE_MSG);
-			} else {
-			/* read from tuner */
-				dw210x_op_rw(d->udev, 0xb5, 0, 0,
-						buf6, 1, DW210X_READ_MSG);
-				msg[0].buf[0] = buf6[0];
-			}
-			break;
-		case (DW2102_RC_QUERY):
-			dw210x_op_rw(d->udev, 0xb8, 0, 0,
-					buf6, 2, DW210X_READ_MSG);
-			msg[0].buf[0] = buf6[0];
-			msg[0].buf[1] = buf6[1];
-			break;
-		case (DW2102_VOLTAGE_CTRL):
-			buf6[0] = 0x30;
-			buf6[1] = msg[0].buf[0];
-			dw210x_op_rw(d->udev, 0xb2, 0, 0,
-					buf6, 2, DW210X_WRITE_MSG);
-			break;
-		}
-
-		break;
-	}
-
-	mutex_unlock(&d->i2c_mutex);
-	return num;
-}
-
-static int dw2102_serit_i2c_transfer(struct i2c_adapter *adap,
-						struct i2c_msg msg[], int num)
-{
-	struct dvb_usb_device *d = i2c_get_adapdata(adap);
-	u8 buf6[] = {0, 0, 0, 0, 0, 0, 0};
-
-	if (!d)
-		return -ENODEV;
-	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
-		return -EAGAIN;
-
-	switch (num) {
-	case 2:
-		/* read si2109 register by number */
-		buf6[0] = msg[0].addr << 1;
-		buf6[1] = msg[0].len;
-		buf6[2] = msg[0].buf[0];
-		dw210x_op_rw(d->udev, 0xc2, 0, 0,
-				buf6, msg[0].len + 2, DW210X_WRITE_MSG);
-		/* read si2109 register */
-		dw210x_op_rw(d->udev, 0xc3, 0xd0, 0,
-				buf6, msg[1].len + 2, DW210X_READ_MSG);
-		memcpy(msg[1].buf, buf6 + 2, msg[1].len);
-
-		break;
-	case 1:
-		switch (msg[0].addr) {
-		case 0x68:
-			/* write to si2109 register */
-			buf6[0] = msg[0].addr << 1;
-			buf6[1] = msg[0].len;
-			memcpy(buf6 + 2, msg[0].buf, msg[0].len);
-			dw210x_op_rw(d->udev, 0xc2, 0, 0, buf6,
-					msg[0].len + 2, DW210X_WRITE_MSG);
-			break;
-		case(DW2102_RC_QUERY):
-			dw210x_op_rw(d->udev, 0xb8, 0, 0,
-					buf6, 2, DW210X_READ_MSG);
-			msg[0].buf[0] = buf6[0];
-			msg[0].buf[1] = buf6[1];
-			break;
-		case(DW2102_VOLTAGE_CTRL):
-			buf6[0] = 0x30;
-			buf6[1] = msg[0].buf[0];
-			dw210x_op_rw(d->udev, 0xb2, 0, 0,
-					buf6, 2, DW210X_WRITE_MSG);
-			break;
-		}
-		break;
-	}
-
-	mutex_unlock(&d->i2c_mutex);
-	return num;
-}
-
-static int dw2102_earda_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num)
-{
-	struct dvb_usb_device *d = i2c_get_adapdata(adap);
-
-	if (!d)
-		return -ENODEV;
-	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
-		return -EAGAIN;
-
-	switch (num) {
-	case 2: {
-		/* read */
-		/* first write first register number */
-		u8 ibuf[msg[1].len + 2], obuf[3];
-		obuf[0] = msg[0].addr << 1;
-		obuf[1] = msg[0].len;
-		obuf[2] = msg[0].buf[0];
-		dw210x_op_rw(d->udev, 0xc2, 0, 0,
-				obuf, msg[0].len + 2, DW210X_WRITE_MSG);
-		/* second read registers */
-		dw210x_op_rw(d->udev, 0xc3, 0xd1 , 0,
-				ibuf, msg[1].len + 2, DW210X_READ_MSG);
-		memcpy(msg[1].buf, ibuf + 2, msg[1].len);
-
-		break;
-	}
-	case 1:
-		switch (msg[0].addr) {
-		case 0x68: {
-			/* write to register */
-			u8 obuf[msg[0].len + 2];
-			obuf[0] = msg[0].addr << 1;
-			obuf[1] = msg[0].len;
-			memcpy(obuf + 2, msg[0].buf, msg[0].len);
-			dw210x_op_rw(d->udev, 0xc2, 0, 0,
-					obuf, msg[0].len + 2, DW210X_WRITE_MSG);
-			break;
-		}
-		case 0x61: {
-			/* write to tuner */
-			u8 obuf[msg[0].len + 2];
-			obuf[0] = msg[0].addr << 1;
-			obuf[1] = msg[0].len;
-			memcpy(obuf + 2, msg[0].buf, msg[0].len);
-			dw210x_op_rw(d->udev, 0xc2, 0, 0,
-					obuf, msg[0].len + 2, DW210X_WRITE_MSG);
-			break;
-		}
-		case(DW2102_RC_QUERY): {
-			u8 ibuf[2];
-			dw210x_op_rw(d->udev, 0xb8, 0, 0,
-					ibuf, 2, DW210X_READ_MSG);
-			memcpy(msg[0].buf, ibuf , 2);
-			break;
-		}
-		case(DW2102_VOLTAGE_CTRL): {
-			u8 obuf[2];
-			obuf[0] = 0x30;
-			obuf[1] = msg[0].buf[0];
-			dw210x_op_rw(d->udev, 0xb2, 0, 0,
-					obuf, 2, DW210X_WRITE_MSG);
-			break;
-		}
-		}
-
-		break;
-	}
-
-	mutex_unlock(&d->i2c_mutex);
-	return num;
-}
-
-static int dw2104_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num)
-{
-	struct dvb_usb_device *d = i2c_get_adapdata(adap);
-	int len, i, j;
-
-	if (!d)
-		return -ENODEV;
-	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
-		return -EAGAIN;
-
-	for (j = 0; j < num; j++) {
-		switch (msg[j].addr) {
-		case(DW2102_RC_QUERY): {
-			u8 ibuf[2];
-			dw210x_op_rw(d->udev, 0xb8, 0, 0,
-					ibuf, 2, DW210X_READ_MSG);
-			memcpy(msg[j].buf, ibuf , 2);
-			break;
-		}
-		case(DW2102_VOLTAGE_CTRL): {
-			u8 obuf[2];
-			obuf[0] = 0x30;
-			obuf[1] = msg[j].buf[0];
-			dw210x_op_rw(d->udev, 0xb2, 0, 0,
-					obuf, 2, DW210X_WRITE_MSG);
-			break;
-		}
-		/*case 0x55: cx24116
-		case 0x6a: stv0903
-		case 0x68: ds3000, stv0903
-		case 0x60: ts2020, stv6110, stb6100 */
-		default: {
-			if (msg[j].flags == I2C_M_RD) {
-				/* read registers */
-				u8  ibuf[msg[j].len + 2];
-				dw210x_op_rw(d->udev, 0xc3,
-						(msg[j].addr << 1) + 1, 0,
-						ibuf, msg[j].len + 2,
-						DW210X_READ_MSG);
-				memcpy(msg[j].buf, ibuf + 2, msg[j].len);
-			mdelay(10);
-			} else if (((msg[j].buf[0] == 0xb0) &&
-						(msg[j].addr == 0x68)) ||
-						((msg[j].buf[0] == 0xf7) &&
-						(msg[j].addr == 0x55))) {
-				/* write firmware */
-				u8 obuf[19];
-				obuf[0] = msg[j].addr << 1;
-				obuf[1] = (msg[j].len > 15 ? 17 : msg[j].len);
-				obuf[2] = msg[j].buf[0];
-				len = msg[j].len - 1;
-				i = 1;
-				do {
-					memcpy(obuf + 3, msg[j].buf + i,
-							(len > 16 ? 16 : len));
-					dw210x_op_rw(d->udev, 0xc2, 0, 0,
-						obuf, (len > 16 ? 16 : len) + 3,
-						DW210X_WRITE_MSG);
-					i += 16;
-					len -= 16;
-				} while (len > 0);
-			} else {
-				/* write registers */
-				u8 obuf[msg[j].len + 2];
-				obuf[0] = msg[j].addr << 1;
-				obuf[1] = msg[j].len;
-				memcpy(obuf + 2, msg[j].buf, msg[j].len);
-				dw210x_op_rw(d->udev, 0xc2, 0, 0,
-						obuf, msg[j].len + 2,
-						DW210X_WRITE_MSG);
-			}
-			break;
-		}
-		}
-
-	}
-
-	mutex_unlock(&d->i2c_mutex);
-	return num;
-}
-
-static int dw3101_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
-								int num)
-{
-	struct dvb_usb_device *d = i2c_get_adapdata(adap);
-	int i;
-
-	if (!d)
-		return -ENODEV;
-	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
-		return -EAGAIN;
-
-	switch (num) {
-	case 2: {
-		/* read */
-		/* first write first register number */
-		u8 ibuf[msg[1].len + 2], obuf[3];
-		obuf[0] = msg[0].addr << 1;
-		obuf[1] = msg[0].len;
-		obuf[2] = msg[0].buf[0];
-		dw210x_op_rw(d->udev, 0xc2, 0, 0,
-				obuf, msg[0].len + 2, DW210X_WRITE_MSG);
-		/* second read registers */
-		dw210x_op_rw(d->udev, 0xc3, 0x19 , 0,
-				ibuf, msg[1].len + 2, DW210X_READ_MSG);
-		memcpy(msg[1].buf, ibuf + 2, msg[1].len);
-
-		break;
-	}
-	case 1:
-		switch (msg[0].addr) {
-		case 0x60:
-		case 0x0c: {
-			/* write to register */
-			u8 obuf[msg[0].len + 2];
-			obuf[0] = msg[0].addr << 1;
-			obuf[1] = msg[0].len;
-			memcpy(obuf + 2, msg[0].buf, msg[0].len);
-			dw210x_op_rw(d->udev, 0xc2, 0, 0,
-					obuf, msg[0].len + 2, DW210X_WRITE_MSG);
-			break;
-		}
-		case(DW2102_RC_QUERY): {
-			u8 ibuf[2];
-			dw210x_op_rw(d->udev, 0xb8, 0, 0,
-					ibuf, 2, DW210X_READ_MSG);
-			memcpy(msg[0].buf, ibuf , 2);
-			break;
-		}
-		}
-
-		break;
-	}
-
-	for (i = 0; i < num; i++) {
-		deb_xfer("%02x:%02x: %s ", i, msg[i].addr,
-				msg[i].flags == 0 ? ">>>" : "<<<");
-		debug_dump(msg[i].buf, msg[i].len, deb_xfer);
-	}
-
-	mutex_unlock(&d->i2c_mutex);
-	return num;
-}
-
-static int s6x0_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
-								int num)
-{
-	struct dvb_usb_device *d = i2c_get_adapdata(adap);
-	struct usb_device *udev;
-	int len, i, j;
-
-	if (!d)
-		return -ENODEV;
-	udev = d->udev;
-	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
-		return -EAGAIN;
-
-	for (j = 0; j < num; j++) {
-		switch (msg[j].addr) {
-		case (DW2102_RC_QUERY): {
-			u8 ibuf[5];
-			dw210x_op_rw(d->udev, 0xb8, 0, 0,
-					ibuf, 5, DW210X_READ_MSG);
-			memcpy(msg[j].buf, ibuf + 3, 2);
-			break;
-		}
-		case (DW2102_VOLTAGE_CTRL): {
-			u8 obuf[2];
-
-			obuf[0] = 1;
-			obuf[1] = msg[j].buf[1];/* off-on */
-			dw210x_op_rw(d->udev, 0x8a, 0, 0,
-					obuf, 2, DW210X_WRITE_MSG);
-			obuf[0] = 3;
-			obuf[1] = msg[j].buf[0];/* 13v-18v */
-			dw210x_op_rw(d->udev, 0x8a, 0, 0,
-					obuf, 2, DW210X_WRITE_MSG);
-			break;
-		}
-		case (DW2102_LED_CTRL): {
-			u8 obuf[2];
-
-			obuf[0] = 5;
-			obuf[1] = msg[j].buf[0];
-			dw210x_op_rw(d->udev, 0x8a, 0, 0,
-					obuf, 2, DW210X_WRITE_MSG);
-			break;
-		}
-		/*case 0x55: cx24116
-		case 0x6a: stv0903
-		case 0x68: ds3000, stv0903
-		case 0x60: ts2020, stv6110, stb6100
-		case 0xa0: eeprom */
-		default: {
-			if (msg[j].flags == I2C_M_RD) {
-				/* read registers */
-				u8 ibuf[msg[j].len];
-				dw210x_op_rw(d->udev, 0x91, 0, 0,
-						ibuf, msg[j].len,
-						DW210X_READ_MSG);
-				memcpy(msg[j].buf, ibuf, msg[j].len);
-				break;
-			} else if ((msg[j].buf[0] == 0xb0) &&
-						(msg[j].addr == 0x68)) {
-				/* write firmware */
-				u8 obuf[19];
-				obuf[0] = (msg[j].len > 16 ?
-						18 : msg[j].len + 1);
-				obuf[1] = msg[j].addr << 1;
-				obuf[2] = msg[j].buf[0];
-				len = msg[j].len - 1;
-				i = 1;
-				do {
-					memcpy(obuf + 3, msg[j].buf + i,
-							(len > 16 ? 16 : len));
-					dw210x_op_rw(d->udev, 0x80, 0, 0,
-						obuf, (len > 16 ? 16 : len) + 3,
-						DW210X_WRITE_MSG);
-					i += 16;
-					len -= 16;
-				} while (len > 0);
-			} else if (j < (num - 1)) {
-				/* write register addr before read */
-				u8 obuf[msg[j].len + 2];
-				obuf[0] = msg[j + 1].len;
-				obuf[1] = (msg[j].addr << 1);
-				memcpy(obuf + 2, msg[j].buf, msg[j].len);
-				dw210x_op_rw(d->udev,
-						udev->descriptor.idProduct ==
-						0x7500 ? 0x92 : 0x90, 0, 0,
-						obuf, msg[j].len + 2,
-						DW210X_WRITE_MSG);
-				break;
-			} else {
-				/* write registers */
-				u8 obuf[msg[j].len + 2];
-				obuf[0] = msg[j].len + 1;
-				obuf[1] = (msg[j].addr << 1);
-				memcpy(obuf + 2, msg[j].buf, msg[j].len);
-				dw210x_op_rw(d->udev, 0x80, 0, 0,
-						obuf, msg[j].len + 2,
-						DW210X_WRITE_MSG);
-				break;
-			}
-			break;
-		}
-		}
-	}
-
-	mutex_unlock(&d->i2c_mutex);
-	return num;
-}
-
-static int su3000_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
-								int num)
-{
-	struct dvb_usb_device *d = i2c_get_adapdata(adap);
-	u8 obuf[0x40], ibuf[0x40];
-
-	if (!d)
-		return -ENODEV;
-	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
-		return -EAGAIN;
-
-	switch (num) {
-	case 1:
-		switch (msg[0].addr) {
-		case SU3000_STREAM_CTRL:
-			obuf[0] = msg[0].buf[0] + 0x36;
-			obuf[1] = 3;
-			obuf[2] = 0;
-			if (dvb_usb_generic_rw(d, obuf, 3, ibuf, 0, 0) < 0)
-				err("i2c transfer failed.");
-			break;
-		case DW2102_RC_QUERY:
-			obuf[0] = 0x10;
-			if (dvb_usb_generic_rw(d, obuf, 1, ibuf, 2, 0) < 0)
-				err("i2c transfer failed.");
-			msg[0].buf[1] = ibuf[0];
-			msg[0].buf[0] = ibuf[1];
-			break;
-		default:
-			/* always i2c write*/
-			obuf[0] = 0x08;
-			obuf[1] = msg[0].addr;
-			obuf[2] = msg[0].len;
-
-			memcpy(&obuf[3], msg[0].buf, msg[0].len);
-
-			if (dvb_usb_generic_rw(d, obuf, msg[0].len + 3,
-						ibuf, 1, 0) < 0)
-				err("i2c transfer failed.");
-
-		}
-		break;
-	case 2:
-		/* always i2c read */
-		obuf[0] = 0x09;
-		obuf[1] = msg[0].len;
-		obuf[2] = msg[1].len;
-		obuf[3] = msg[0].addr;
-		memcpy(&obuf[4], msg[0].buf, msg[0].len);
-
-		if (dvb_usb_generic_rw(d, obuf, msg[0].len + 4,
-					ibuf, msg[1].len + 1, 0) < 0)
-			err("i2c transfer failed.");
-
-		memcpy(msg[1].buf, &ibuf[1], msg[1].len);
-		break;
-	default:
-		warn("more than 2 i2c messages at a time is not handled yet.");
-		break;
-	}
-	mutex_unlock(&d->i2c_mutex);
-	return num;
-}
-
-static u32 dw210x_i2c_func(struct i2c_adapter *adapter)
-{
-	return I2C_FUNC_I2C;
-}
-
-static struct i2c_algorithm dw2102_i2c_algo = {
-	.master_xfer = dw2102_i2c_transfer,
-	.functionality = dw210x_i2c_func,
-};
-
-static struct i2c_algorithm dw2102_serit_i2c_algo = {
-	.master_xfer = dw2102_serit_i2c_transfer,
-	.functionality = dw210x_i2c_func,
-};
-
-static struct i2c_algorithm dw2102_earda_i2c_algo = {
-	.master_xfer = dw2102_earda_i2c_transfer,
-	.functionality = dw210x_i2c_func,
-};
-
-static struct i2c_algorithm dw2104_i2c_algo = {
-	.master_xfer = dw2104_i2c_transfer,
-	.functionality = dw210x_i2c_func,
-};
-
-static struct i2c_algorithm dw3101_i2c_algo = {
-	.master_xfer = dw3101_i2c_transfer,
-	.functionality = dw210x_i2c_func,
-};
-
-static struct i2c_algorithm s6x0_i2c_algo = {
-	.master_xfer = s6x0_i2c_transfer,
-	.functionality = dw210x_i2c_func,
-};
-
-static struct i2c_algorithm su3000_i2c_algo = {
-	.master_xfer = su3000_i2c_transfer,
-	.functionality = dw210x_i2c_func,
-};
-
-static int dw210x_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
-{
-	int i;
-	u8 ibuf[] = {0, 0};
-	u8 eeprom[256], eepromline[16];
-
-	for (i = 0; i < 256; i++) {
-		if (dw210x_op_rw(d->udev, 0xb6, 0xa0 , i, ibuf, 2, DW210X_READ_MSG) < 0) {
-			err("read eeprom failed.");
-			return -1;
-		} else {
-			eepromline[i%16] = ibuf[0];
-			eeprom[i] = ibuf[0];
-		}
-		if ((i % 16) == 15) {
-			deb_xfer("%02x: ", i - 15);
-			debug_dump(eepromline, 16, deb_xfer);
-		}
-	}
-
-	memcpy(mac, eeprom + 8, 6);
-	return 0;
-};
-
-static int s6x0_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
-{
-	int i, ret;
-	u8 ibuf[] = { 0 }, obuf[] = { 0 };
-	u8 eeprom[256], eepromline[16];
-	struct i2c_msg msg[] = {
-		{
-			.addr = 0xa0 >> 1,
-			.flags = 0,
-			.buf = obuf,
-			.len = 1,
-		}, {
-			.addr = 0xa0 >> 1,
-			.flags = I2C_M_RD,
-			.buf = ibuf,
-			.len = 1,
-		}
-	};
-
-	for (i = 0; i < 256; i++) {
-		obuf[0] = i;
-		ret = s6x0_i2c_transfer(&d->i2c_adap, msg, 2);
-		if (ret != 2) {
-			err("read eeprom failed.");
-			return -1;
-		} else {
-			eepromline[i % 16] = ibuf[0];
-			eeprom[i] = ibuf[0];
-		}
-
-		if ((i % 16) == 15) {
-			deb_xfer("%02x: ", i - 15);
-			debug_dump(eepromline, 16, deb_xfer);
-		}
-	}
-
-	memcpy(mac, eeprom + 16, 6);
-	return 0;
-};
-
-static int su3000_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
-{
-	static u8 command_start[] = {0x00};
-	static u8 command_stop[] = {0x01};
-	struct i2c_msg msg = {
-		.addr = SU3000_STREAM_CTRL,
-		.flags = 0,
-		.buf = onoff ? command_start : command_stop,
-		.len = 1
-	};
-
-	i2c_transfer(&adap->dev->i2c_adap, &msg, 1);
-
-	return 0;
-}
-
-static int su3000_power_ctrl(struct dvb_usb_device *d, int i)
-{
-	struct su3000_state *state = (struct su3000_state *)d->priv;
-	u8 obuf[] = {0xde, 0};
-
-	info("%s: %d, initialized %d\n", __func__, i, state->initialized);
-
-	if (i && !state->initialized) {
-		state->initialized = 1;
-		/* reset board */
-		dvb_usb_generic_rw(d, obuf, 2, NULL, 0, 0);
-	}
-
-	return 0;
-}
-
-static int su3000_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
-{
-	int i;
-	u8 obuf[] = { 0x1f, 0xf0 };
-	u8 ibuf[] = { 0 };
-	struct i2c_msg msg[] = {
-		{
-			.addr = 0x51,
-			.flags = 0,
-			.buf = obuf,
-			.len = 2,
-		}, {
-			.addr = 0x51,
-			.flags = I2C_M_RD,
-			.buf = ibuf,
-			.len = 1,
-
-		}
-	};
-
-	for (i = 0; i < 6; i++) {
-		obuf[1] = 0xf0 + i;
-		if (i2c_transfer(&d->i2c_adap, msg, 2) != 2)
-			break;
-		else
-			mac[i] = ibuf[0];
-
-		debug_dump(mac, 6, printk);
-	}
-
-	return 0;
-}
-
-static int su3000_identify_state(struct usb_device *udev,
-				 struct dvb_usb_device_properties *props,
-				 struct dvb_usb_device_description **desc,
-				 int *cold)
-{
-	info("%s\n", __func__);
-
-	*cold = 0;
-	return 0;
-}
-
-static int dw210x_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
-{
-	static u8 command_13v[] = {0x00, 0x01};
-	static u8 command_18v[] = {0x01, 0x01};
-	static u8 command_off[] = {0x00, 0x00};
-	struct i2c_msg msg = {
-		.addr = DW2102_VOLTAGE_CTRL,
-		.flags = 0,
-		.buf = command_off,
-		.len = 2,
-	};
-
-	struct dvb_usb_adapter *udev_adap =
-		(struct dvb_usb_adapter *)(fe->dvb->priv);
-	if (voltage == SEC_VOLTAGE_18)
-		msg.buf = command_18v;
-	else if (voltage == SEC_VOLTAGE_13)
-		msg.buf = command_13v;
-
-	i2c_transfer(&udev_adap->dev->i2c_adap, &msg, 1);
-
-	return 0;
-}
-
-static int s660_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
-{
-	struct dvb_usb_adapter *d =
-		(struct dvb_usb_adapter *)(fe->dvb->priv);
-	struct s6x0_state *st = (struct s6x0_state *)d->dev->priv;
-
-	dw210x_set_voltage(fe, voltage);
-	if (st->old_set_voltage)
-		st->old_set_voltage(fe, voltage);
-
-	return 0;
-}
-
-static void dw210x_led_ctrl(struct dvb_frontend *fe, int offon)
-{
-	static u8 led_off[] = { 0 };
-	static u8 led_on[] = { 1 };
-	struct i2c_msg msg = {
-		.addr = DW2102_LED_CTRL,
-		.flags = 0,
-		.buf = led_off,
-		.len = 1
-	};
-	struct dvb_usb_adapter *udev_adap =
-		(struct dvb_usb_adapter *)(fe->dvb->priv);
-
-	if (offon)
-		msg.buf = led_on;
-	i2c_transfer(&udev_adap->dev->i2c_adap, &msg, 1);
-}
-
-static struct stv0299_config sharp_z0194a_config = {
-	.demod_address = 0x68,
-	.inittab = sharp_z0194a_inittab,
-	.mclk = 88000000UL,
-	.invert = 1,
-	.skip_reinit = 0,
-	.lock_output = STV0299_LOCKOUTPUT_1,
-	.volt13_op0_op1 = STV0299_VOLT13_OP1,
-	.min_delay_ms = 100,
-	.set_symbol_rate = sharp_z0194a_set_symbol_rate,
-};
-
-static struct cx24116_config dw2104_config = {
-	.demod_address = 0x55,
-	.mpg_clk_pos_pol = 0x01,
-};
-
-static struct si21xx_config serit_sp1511lhb_config = {
-	.demod_address = 0x68,
-	.min_delay_ms = 100,
-
-};
-
-static struct tda10023_config dw3101_tda10023_config = {
-	.demod_address = 0x0c,
-	.invert = 1,
-};
-
-static struct mt312_config zl313_config = {
-	.demod_address = 0x0e,
-};
-
-static struct ds3000_config dw2104_ds3000_config = {
-	.demod_address = 0x68,
-};
-
-static struct stv0900_config dw2104a_stv0900_config = {
-	.demod_address = 0x6a,
-	.demod_mode = 0,
-	.xtal = 27000000,
-	.clkmode = 3,/* 0-CLKI, 2-XTALI, else AUTO */
-	.diseqc_mode = 2,/* 2/3 PWM */
-	.tun1_maddress = 0,/* 0x60 */
-	.tun1_adc = 0,/* 2 Vpp */
-	.path1_mode = 3,
-};
-
-static struct stb6100_config dw2104a_stb6100_config = {
-	.tuner_address = 0x60,
-	.refclock = 27000000,
-};
-
-static struct stv0900_config dw2104_stv0900_config = {
-	.demod_address = 0x68,
-	.demod_mode = 0,
-	.xtal = 8000000,
-	.clkmode = 3,
-	.diseqc_mode = 2,
-	.tun1_maddress = 0,
-	.tun1_adc = 1,/* 1 Vpp */
-	.path1_mode = 3,
-};
-
-static struct stv6110_config dw2104_stv6110_config = {
-	.i2c_address = 0x60,
-	.mclk = 16000000,
-	.clk_div = 1,
-};
-
-static struct stv0900_config prof_7500_stv0900_config = {
-	.demod_address = 0x6a,
-	.demod_mode = 0,
-	.xtal = 27000000,
-	.clkmode = 3,/* 0-CLKI, 2-XTALI, else AUTO */
-	.diseqc_mode = 2,/* 2/3 PWM */
-	.tun1_maddress = 0,/* 0x60 */
-	.tun1_adc = 0,/* 2 Vpp */
-	.path1_mode = 3,
-	.tun1_type = 3,
-	.set_lock_led = dw210x_led_ctrl,
-};
-
-static struct ds3000_config su3000_ds3000_config = {
-	.demod_address = 0x68,
-	.ci_mode = 1,
-};
-
-static int dw2104_frontend_attach(struct dvb_usb_adapter *d)
-{
-	struct dvb_tuner_ops *tuner_ops = NULL;
-
-	if (demod_probe & 4) {
-		d->fe_adap[0].fe = dvb_attach(stv0900_attach, &dw2104a_stv0900_config,
-				&d->dev->i2c_adap, 0);
-		if (d->fe_adap[0].fe != NULL) {
-			if (dvb_attach(stb6100_attach, d->fe_adap[0].fe,
-					&dw2104a_stb6100_config,
-					&d->dev->i2c_adap)) {
-				tuner_ops = &d->fe_adap[0].fe->ops.tuner_ops;
-				tuner_ops->set_frequency = stb6100_set_freq;
-				tuner_ops->get_frequency = stb6100_get_freq;
-				tuner_ops->set_bandwidth = stb6100_set_bandw;
-				tuner_ops->get_bandwidth = stb6100_get_bandw;
-				d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
-				info("Attached STV0900+STB6100!\n");
-				return 0;
-			}
-		}
-	}
-
-	if (demod_probe & 2) {
-		d->fe_adap[0].fe = dvb_attach(stv0900_attach, &dw2104_stv0900_config,
-				&d->dev->i2c_adap, 0);
-		if (d->fe_adap[0].fe != NULL) {
-			if (dvb_attach(stv6110_attach, d->fe_adap[0].fe,
-					&dw2104_stv6110_config,
-					&d->dev->i2c_adap)) {
-				d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
-				info("Attached STV0900+STV6110A!\n");
-				return 0;
-			}
-		}
-	}
-
-	if (demod_probe & 1) {
-		d->fe_adap[0].fe = dvb_attach(cx24116_attach, &dw2104_config,
-				&d->dev->i2c_adap);
-		if (d->fe_adap[0].fe != NULL) {
-			d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
-			info("Attached cx24116!\n");
-			return 0;
-		}
-	}
-
-	d->fe_adap[0].fe = dvb_attach(ds3000_attach, &dw2104_ds3000_config,
-			&d->dev->i2c_adap);
-	if (d->fe_adap[0].fe != NULL) {
-		d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
-		info("Attached DS3000!\n");
-		return 0;
-	}
-
-	return -EIO;
-}
-
-static struct dvb_usb_device_properties dw2102_properties;
-static struct dvb_usb_device_properties dw2104_properties;
-static struct dvb_usb_device_properties s6x0_properties;
-
-static int dw2102_frontend_attach(struct dvb_usb_adapter *d)
-{
-	if (dw2102_properties.i2c_algo == &dw2102_serit_i2c_algo) {
-		/*dw2102_properties.adapter->tuner_attach = NULL;*/
-		d->fe_adap[0].fe = dvb_attach(si21xx_attach, &serit_sp1511lhb_config,
-					&d->dev->i2c_adap);
-		if (d->fe_adap[0].fe != NULL) {
-			d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
-			info("Attached si21xx!\n");
-			return 0;
-		}
-	}
-
-	if (dw2102_properties.i2c_algo == &dw2102_earda_i2c_algo) {
-		d->fe_adap[0].fe = dvb_attach(stv0288_attach, &earda_config,
-					&d->dev->i2c_adap);
-		if (d->fe_adap[0].fe != NULL) {
-			if (dvb_attach(stb6000_attach, d->fe_adap[0].fe, 0x61,
-					&d->dev->i2c_adap)) {
-				d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
-				info("Attached stv0288!\n");
-				return 0;
-			}
-		}
-	}
-
-	if (dw2102_properties.i2c_algo == &dw2102_i2c_algo) {
-		/*dw2102_properties.adapter->tuner_attach = dw2102_tuner_attach;*/
-		d->fe_adap[0].fe = dvb_attach(stv0299_attach, &sharp_z0194a_config,
-					&d->dev->i2c_adap);
-		if (d->fe_adap[0].fe != NULL) {
-			d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
-			info("Attached stv0299!\n");
-			return 0;
-		}
-	}
-	return -EIO;
-}
-
-static int dw3101_frontend_attach(struct dvb_usb_adapter *d)
-{
-	d->fe_adap[0].fe = dvb_attach(tda10023_attach, &dw3101_tda10023_config,
-				&d->dev->i2c_adap, 0x48);
-	if (d->fe_adap[0].fe != NULL) {
-		info("Attached tda10023!\n");
-		return 0;
-	}
-	return -EIO;
-}
-
-static int zl100313_frontend_attach(struct dvb_usb_adapter *d)
-{
-	d->fe_adap[0].fe = dvb_attach(mt312_attach, &zl313_config,
-			&d->dev->i2c_adap);
-	if (d->fe_adap[0].fe != NULL) {
-		if (dvb_attach(zl10039_attach, d->fe_adap[0].fe, 0x60,
-				&d->dev->i2c_adap)) {
-			d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
-			info("Attached zl100313+zl10039!\n");
-			return 0;
-		}
-	}
-
-	return -EIO;
-}
-
-static int stv0288_frontend_attach(struct dvb_usb_adapter *d)
-{
-	u8 obuf[] = {7, 1};
-
-	d->fe_adap[0].fe = dvb_attach(stv0288_attach, &earda_config,
-			&d->dev->i2c_adap);
-
-	if (d->fe_adap[0].fe == NULL)
-		return -EIO;
-
-	if (NULL == dvb_attach(stb6000_attach, d->fe_adap[0].fe, 0x61, &d->dev->i2c_adap))
-		return -EIO;
-
-	d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
-
-	dw210x_op_rw(d->dev->udev, 0x8a, 0, 0, obuf, 2, DW210X_WRITE_MSG);
-
-	info("Attached stv0288+stb6000!\n");
-
-	return 0;
-
-}
-
-static int ds3000_frontend_attach(struct dvb_usb_adapter *d)
-{
-	struct s6x0_state *st = (struct s6x0_state *)d->dev->priv;
-	u8 obuf[] = {7, 1};
-
-	d->fe_adap[0].fe = dvb_attach(ds3000_attach, &dw2104_ds3000_config,
-			&d->dev->i2c_adap);
-
-	if (d->fe_adap[0].fe == NULL)
-		return -EIO;
-
-	st->old_set_voltage = d->fe_adap[0].fe->ops.set_voltage;
-	d->fe_adap[0].fe->ops.set_voltage = s660_set_voltage;
-
-	dw210x_op_rw(d->dev->udev, 0x8a, 0, 0, obuf, 2, DW210X_WRITE_MSG);
-
-	info("Attached ds3000+ds2020!\n");
-
-	return 0;
-}
-
-static int prof_7500_frontend_attach(struct dvb_usb_adapter *d)
-{
-	u8 obuf[] = {7, 1};
-
-	d->fe_adap[0].fe = dvb_attach(stv0900_attach, &prof_7500_stv0900_config,
-					&d->dev->i2c_adap, 0);
-	if (d->fe_adap[0].fe == NULL)
-		return -EIO;
-
-	d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage;
-
-	dw210x_op_rw(d->dev->udev, 0x8a, 0, 0, obuf, 2, DW210X_WRITE_MSG);
-
-	info("Attached STV0900+STB6100A!\n");
-
-	return 0;
-}
-
-static int su3000_frontend_attach(struct dvb_usb_adapter *d)
-{
-	u8 obuf[3] = { 0xe, 0x80, 0 };
-	u8 ibuf[] = { 0 };
-
-	if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0)
-		err("command 0x0e transfer failed.");
-
-	obuf[0] = 0xe;
-	obuf[1] = 0x83;
-	obuf[2] = 0;
-
-	if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0)
-		err("command 0x0e transfer failed.");
-
-	obuf[0] = 0xe;
-	obuf[1] = 0x83;
-	obuf[2] = 1;
-
-	if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0)
-		err("command 0x0e transfer failed.");
-
-	obuf[0] = 0x51;
-
-	if (dvb_usb_generic_rw(d->dev, obuf, 1, ibuf, 1, 0) < 0)
-		err("command 0x51 transfer failed.");
-
-	d->fe_adap[0].fe = dvb_attach(ds3000_attach, &su3000_ds3000_config,
-					&d->dev->i2c_adap);
-	if (d->fe_adap[0].fe == NULL)
-		return -EIO;
-
-	info("Attached DS3000!\n");
-
-	return 0;
-}
-
-static int dw2102_tuner_attach(struct dvb_usb_adapter *adap)
-{
-	dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x60,
-		&adap->dev->i2c_adap, DVB_PLL_OPERA1);
-	return 0;
-}
-
-static int dw3101_tuner_attach(struct dvb_usb_adapter *adap)
-{
-	dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x60,
-		&adap->dev->i2c_adap, DVB_PLL_TUA6034);
-
-	return 0;
-}
-
-static struct rc_map_table rc_map_dw210x_table[] = {
-	{ 0xf80a, KEY_POWER2 },		/*power*/
-	{ 0xf80c, KEY_MUTE },		/*mute*/
-	{ 0xf811, KEY_1 },
-	{ 0xf812, KEY_2 },
-	{ 0xf813, KEY_3 },
-	{ 0xf814, KEY_4 },
-	{ 0xf815, KEY_5 },
-	{ 0xf816, KEY_6 },
-	{ 0xf817, KEY_7 },
-	{ 0xf818, KEY_8 },
-	{ 0xf819, KEY_9 },
-	{ 0xf810, KEY_0 },
-	{ 0xf81c, KEY_CHANNELUP },	/*ch+*/
-	{ 0xf80f, KEY_CHANNELDOWN },	/*ch-*/
-	{ 0xf81a, KEY_VOLUMEUP },	/*vol+*/
-	{ 0xf80e, KEY_VOLUMEDOWN },	/*vol-*/
-	{ 0xf804, KEY_RECORD },		/*rec*/
-	{ 0xf809, KEY_FAVORITES },	/*fav*/
-	{ 0xf808, KEY_REWIND },		/*rewind*/
-	{ 0xf807, KEY_FASTFORWARD },	/*fast*/
-	{ 0xf80b, KEY_PAUSE },		/*pause*/
-	{ 0xf802, KEY_ESC },		/*cancel*/
-	{ 0xf803, KEY_TAB },		/*tab*/
-	{ 0xf800, KEY_UP },		/*up*/
-	{ 0xf81f, KEY_OK },		/*ok*/
-	{ 0xf801, KEY_DOWN },		/*down*/
-	{ 0xf805, KEY_CAMERA },		/*cap*/
-	{ 0xf806, KEY_STOP },		/*stop*/
-	{ 0xf840, KEY_ZOOM },		/*full*/
-	{ 0xf81e, KEY_TV },		/*tvmode*/
-	{ 0xf81b, KEY_LAST },		/*recall*/
-};
-
-static struct rc_map_table rc_map_tevii_table[] = {
-	{ 0xf80a, KEY_POWER },
-	{ 0xf80c, KEY_MUTE },
-	{ 0xf811, KEY_1 },
-	{ 0xf812, KEY_2 },
-	{ 0xf813, KEY_3 },
-	{ 0xf814, KEY_4 },
-	{ 0xf815, KEY_5 },
-	{ 0xf816, KEY_6 },
-	{ 0xf817, KEY_7 },
-	{ 0xf818, KEY_8 },
-	{ 0xf819, KEY_9 },
-	{ 0xf810, KEY_0 },
-	{ 0xf81c, KEY_MENU },
-	{ 0xf80f, KEY_VOLUMEDOWN },
-	{ 0xf81a, KEY_LAST },
-	{ 0xf80e, KEY_OPEN },
-	{ 0xf804, KEY_RECORD },
-	{ 0xf809, KEY_VOLUMEUP },
-	{ 0xf808, KEY_CHANNELUP },
-	{ 0xf807, KEY_PVR },
-	{ 0xf80b, KEY_TIME },
-	{ 0xf802, KEY_RIGHT },
-	{ 0xf803, KEY_LEFT },
-	{ 0xf800, KEY_UP },
-	{ 0xf81f, KEY_OK },
-	{ 0xf801, KEY_DOWN },
-	{ 0xf805, KEY_TUNER },
-	{ 0xf806, KEY_CHANNELDOWN },
-	{ 0xf840, KEY_PLAYPAUSE },
-	{ 0xf81e, KEY_REWIND },
-	{ 0xf81b, KEY_FAVORITES },
-	{ 0xf81d, KEY_BACK },
-	{ 0xf84d, KEY_FASTFORWARD },
-	{ 0xf844, KEY_EPG },
-	{ 0xf84c, KEY_INFO },
-	{ 0xf841, KEY_AB },
-	{ 0xf843, KEY_AUDIO },
-	{ 0xf845, KEY_SUBTITLE },
-	{ 0xf84a, KEY_LIST },
-	{ 0xf846, KEY_F1 },
-	{ 0xf847, KEY_F2 },
-	{ 0xf85e, KEY_F3 },
-	{ 0xf85c, KEY_F4 },
-	{ 0xf852, KEY_F5 },
-	{ 0xf85a, KEY_F6 },
-	{ 0xf856, KEY_MODE },
-	{ 0xf858, KEY_SWITCHVIDEOMODE },
-};
-
-static struct rc_map_table rc_map_tbs_table[] = {
-	{ 0xf884, KEY_POWER },
-	{ 0xf894, KEY_MUTE },
-	{ 0xf887, KEY_1 },
-	{ 0xf886, KEY_2 },
-	{ 0xf885, KEY_3 },
-	{ 0xf88b, KEY_4 },
-	{ 0xf88a, KEY_5 },
-	{ 0xf889, KEY_6 },
-	{ 0xf88f, KEY_7 },
-	{ 0xf88e, KEY_8 },
-	{ 0xf88d, KEY_9 },
-	{ 0xf892, KEY_0 },
-	{ 0xf896, KEY_CHANNELUP },
-	{ 0xf891, KEY_CHANNELDOWN },
-	{ 0xf893, KEY_VOLUMEUP },
-	{ 0xf88c, KEY_VOLUMEDOWN },
-	{ 0xf883, KEY_RECORD },
-	{ 0xf898, KEY_PAUSE  },
-	{ 0xf899, KEY_OK },
-	{ 0xf89a, KEY_SHUFFLE },
-	{ 0xf881, KEY_UP },
-	{ 0xf890, KEY_LEFT },
-	{ 0xf882, KEY_RIGHT },
-	{ 0xf888, KEY_DOWN },
-	{ 0xf895, KEY_FAVORITES },
-	{ 0xf897, KEY_SUBTITLE },
-	{ 0xf89d, KEY_ZOOM },
-	{ 0xf89f, KEY_EXIT },
-	{ 0xf89e, KEY_MENU },
-	{ 0xf89c, KEY_EPG },
-	{ 0xf880, KEY_PREVIOUS },
-	{ 0xf89b, KEY_MODE }
-};
-
-static struct rc_map_table rc_map_su3000_table[] = {
-	{ 0x25, KEY_POWER },	/* right-bottom Red */
-	{ 0x0a, KEY_MUTE },	/* -/-- */
-	{ 0x01, KEY_1 },
-	{ 0x02, KEY_2 },
-	{ 0x03, KEY_3 },
-	{ 0x04, KEY_4 },
-	{ 0x05, KEY_5 },
-	{ 0x06, KEY_6 },
-	{ 0x07, KEY_7 },
-	{ 0x08, KEY_8 },
-	{ 0x09, KEY_9 },
-	{ 0x00, KEY_0 },
-	{ 0x20, KEY_UP },	/* CH+ */
-	{ 0x21, KEY_DOWN },	/* CH+ */
-	{ 0x12, KEY_VOLUMEUP },	/* Brightness Up */
-	{ 0x13, KEY_VOLUMEDOWN },/* Brightness Down */
-	{ 0x1f, KEY_RECORD },
-	{ 0x17, KEY_PLAY },
-	{ 0x16, KEY_PAUSE },
-	{ 0x0b, KEY_STOP },
-	{ 0x27, KEY_FASTFORWARD },/* >> */
-	{ 0x26, KEY_REWIND },	/* << */
-	{ 0x0d, KEY_OK },	/* Mute */
-	{ 0x11, KEY_LEFT },	/* VOL- */
-	{ 0x10, KEY_RIGHT },	/* VOL+ */
-	{ 0x29, KEY_BACK },	/* button under 9 */
-	{ 0x2c, KEY_MENU },	/* TTX */
-	{ 0x2b, KEY_EPG },	/* EPG */
-	{ 0x1e, KEY_RED },	/* OSD */
-	{ 0x0e, KEY_GREEN },	/* Window */
-	{ 0x2d, KEY_YELLOW },	/* button under << */
-	{ 0x0f, KEY_BLUE },	/* bottom yellow button */
-	{ 0x14, KEY_AUDIO },	/* Snapshot */
-	{ 0x38, KEY_TV },	/* TV/Radio */
-	{ 0x0c, KEY_ESC }	/* upper Red button */
-};
-
-static struct rc_map_dvb_usb_table_table keys_tables[] = {
-	{ rc_map_dw210x_table, ARRAY_SIZE(rc_map_dw210x_table) },
-	{ rc_map_tevii_table, ARRAY_SIZE(rc_map_tevii_table) },
-	{ rc_map_tbs_table, ARRAY_SIZE(rc_map_tbs_table) },
-	{ rc_map_su3000_table, ARRAY_SIZE(rc_map_su3000_table) },
-};
-
-static int dw2102_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
-{
-	struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table;
-	int keymap_size = d->props.rc.legacy.rc_map_size;
-	u8 key[2];
-	struct i2c_msg msg = {
-		.addr = DW2102_RC_QUERY,
-		.flags = I2C_M_RD,
-		.buf = key,
-		.len = 2
-	};
-	int i;
-	/* override keymap */
-	if ((ir_keymap > 0) && (ir_keymap <= ARRAY_SIZE(keys_tables))) {
-		keymap = keys_tables[ir_keymap - 1].rc_keys ;
-		keymap_size = keys_tables[ir_keymap - 1].rc_keys_size;
-	} else if (ir_keymap > ARRAY_SIZE(keys_tables))
-		return 0; /* none */
-
-	*state = REMOTE_NO_KEY_PRESSED;
-	if (d->props.i2c_algo->master_xfer(&d->i2c_adap, &msg, 1) == 1) {
-		for (i = 0; i < keymap_size ; i++) {
-			if (rc5_data(&keymap[i]) == msg.buf[0]) {
-				*state = REMOTE_KEY_PRESSED;
-				*event = keymap[i].keycode;
-				break;
-			}
-
-		}
-
-		if ((*state) == REMOTE_KEY_PRESSED)
-			deb_rc("%s: found rc key: %x, %x, event: %x\n",
-					__func__, key[0], key[1], (*event));
-		else if (key[0] != 0xff)
-			deb_rc("%s: unknown rc key: %x, %x\n",
-					__func__, key[0], key[1]);
-
-	}
-
-	return 0;
-}
-
-enum dw2102_table_entry {
-	CYPRESS_DW2102,
-	CYPRESS_DW2101,
-	CYPRESS_DW2104,
-	TEVII_S650,
-	TERRATEC_CINERGY_S,
-	CYPRESS_DW3101,
-	TEVII_S630,
-	PROF_1100,
-	TEVII_S660,
-	PROF_7500,
-	GENIATECH_SU3000,
-	TERRATEC_CINERGY_S2,
-	TEVII_S480_1,
-	TEVII_S480_2,
-	X3M_SPC1400HD,
-};
-
-static struct usb_device_id dw2102_table[] = {
-	[CYPRESS_DW2102] = {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW2102)},
-	[CYPRESS_DW2101] = {USB_DEVICE(USB_VID_CYPRESS, 0x2101)},
-	[CYPRESS_DW2104] = {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW2104)},
-	[TEVII_S650] = {USB_DEVICE(0x9022, USB_PID_TEVII_S650)},
-	[TERRATEC_CINERGY_S] = {USB_DEVICE(USB_VID_TERRATEC, USB_PID_CINERGY_S)},
-	[CYPRESS_DW3101] = {USB_DEVICE(USB_VID_CYPRESS, USB_PID_DW3101)},
-	[TEVII_S630] = {USB_DEVICE(0x9022, USB_PID_TEVII_S630)},
-	[PROF_1100] = {USB_DEVICE(0x3011, USB_PID_PROF_1100)},
-	[TEVII_S660] = {USB_DEVICE(0x9022, USB_PID_TEVII_S660)},
-	[PROF_7500] = {USB_DEVICE(0x3034, 0x7500)},
-	[GENIATECH_SU3000] = {USB_DEVICE(0x1f4d, 0x3000)},
-	[TERRATEC_CINERGY_S2] = {USB_DEVICE(USB_VID_TERRATEC, 0x00a8)},
-	[TEVII_S480_1] = {USB_DEVICE(0x9022, USB_PID_TEVII_S480_1)},
-	[TEVII_S480_2] = {USB_DEVICE(0x9022, USB_PID_TEVII_S480_2)},
-	[X3M_SPC1400HD] = {USB_DEVICE(0x1f4d, 0x3100)},
-	{ }
-};
-
-MODULE_DEVICE_TABLE(usb, dw2102_table);
-
-static int dw2102_load_firmware(struct usb_device *dev,
-			const struct firmware *frmwr)
-{
-	u8 *b, *p;
-	int ret = 0, i;
-	u8 reset;
-	u8 reset16[] = {0, 0, 0, 0, 0, 0, 0};
-	const struct firmware *fw;
-	const char *fw_2101 = "dvb-usb-dw2101.fw";
-
-	switch (dev->descriptor.idProduct) {
-	case 0x2101:
-		ret = request_firmware(&fw, fw_2101, &dev->dev);
-		if (ret != 0) {
-			err(err_str, fw_2101);
-			return ret;
-		}
-		break;
-	default:
-		fw = frmwr;
-		break;
-	}
-	info("start downloading DW210X firmware");
-	p = kmalloc(fw->size, GFP_KERNEL);
-	reset = 1;
-	/*stop the CPU*/
-	dw210x_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, DW210X_WRITE_MSG);
-	dw210x_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, DW210X_WRITE_MSG);
-
-	if (p != NULL) {
-		memcpy(p, fw->data, fw->size);
-		for (i = 0; i < fw->size; i += 0x40) {
-			b = (u8 *) p + i;
-			if (dw210x_op_rw(dev, 0xa0, i, 0, b , 0x40,
-					DW210X_WRITE_MSG) != 0x40) {
-				err("error while transferring firmware");
-				ret = -EINVAL;
-				break;
-			}
-		}
-		/* restart the CPU */
-		reset = 0;
-		if (ret || dw210x_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1,
-					DW210X_WRITE_MSG) != 1) {
-			err("could not restart the USB controller CPU.");
-			ret = -EINVAL;
-		}
-		if (ret || dw210x_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1,
-					DW210X_WRITE_MSG) != 1) {
-			err("could not restart the USB controller CPU.");
-			ret = -EINVAL;
-		}
-		/* init registers */
-		switch (dev->descriptor.idProduct) {
-		case USB_PID_TEVII_S650:
-			dw2104_properties.rc.legacy.rc_map_table = rc_map_tevii_table;
-			dw2104_properties.rc.legacy.rc_map_size =
-					ARRAY_SIZE(rc_map_tevii_table);
-		case USB_PID_DW2104:
-			reset = 1;
-			dw210x_op_rw(dev, 0xc4, 0x0000, 0, &reset, 1,
-					DW210X_WRITE_MSG);
-			/* break omitted intentionally */
-		case USB_PID_DW3101:
-			reset = 0;
-			dw210x_op_rw(dev, 0xbf, 0x0040, 0, &reset, 0,
-					DW210X_WRITE_MSG);
-			break;
-		case USB_PID_CINERGY_S:
-		case USB_PID_DW2102:
-			dw210x_op_rw(dev, 0xbf, 0x0040, 0, &reset, 0,
-					DW210X_WRITE_MSG);
-			dw210x_op_rw(dev, 0xb9, 0x0000, 0, &reset16[0], 2,
-					DW210X_READ_MSG);
-			/* check STV0299 frontend  */
-			dw210x_op_rw(dev, 0xb5, 0, 0, &reset16[0], 2,
-					DW210X_READ_MSG);
-			if ((reset16[0] == 0xa1) || (reset16[0] == 0x80)) {
-				dw2102_properties.i2c_algo = &dw2102_i2c_algo;
-				dw2102_properties.adapter->fe[0].tuner_attach = &dw2102_tuner_attach;
-				break;
-			} else {
-				/* check STV0288 frontend  */
-				reset16[0] = 0xd0;
-				reset16[1] = 1;
-				reset16[2] = 0;
-				dw210x_op_rw(dev, 0xc2, 0, 0, &reset16[0], 3,
-						DW210X_WRITE_MSG);
-				dw210x_op_rw(dev, 0xc3, 0xd1, 0, &reset16[0], 3,
-						DW210X_READ_MSG);
-				if (reset16[2] == 0x11) {
-					dw2102_properties.i2c_algo = &dw2102_earda_i2c_algo;
-					break;
-				}
-			}
-		case 0x2101:
-			dw210x_op_rw(dev, 0xbc, 0x0030, 0, &reset16[0], 2,
-					DW210X_READ_MSG);
-			dw210x_op_rw(dev, 0xba, 0x0000, 0, &reset16[0], 7,
-					DW210X_READ_MSG);
-			dw210x_op_rw(dev, 0xba, 0x0000, 0, &reset16[0], 7,
-					DW210X_READ_MSG);
-			dw210x_op_rw(dev, 0xb9, 0x0000, 0, &reset16[0], 2,
-					DW210X_READ_MSG);
-			break;
-		}
-
-		msleep(100);
-		kfree(p);
-	}
-	return ret;
-}
-
-static struct dvb_usb_device_properties dw2102_properties = {
-	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
-	.usb_ctrl = DEVICE_SPECIFIC,
-	.firmware = "dvb-usb-dw2102.fw",
-	.no_reconnect = 1,
-
-	.i2c_algo = &dw2102_serit_i2c_algo,
-
-	.rc.legacy = {
-		.rc_map_table = rc_map_dw210x_table,
-		.rc_map_size = ARRAY_SIZE(rc_map_dw210x_table),
-		.rc_interval = 150,
-		.rc_query = dw2102_rc_query,
-	},
-
-	.generic_bulk_ctrl_endpoint = 0x81,
-	/* parameter for the MPEG2-data transfer */
-	.num_adapters = 1,
-	.download_firmware = dw2102_load_firmware,
-	.read_mac_address = dw210x_read_mac_address,
-	.adapter = {
-		{
-		.num_frontends = 1,
-		.fe = {{
-			.frontend_attach = dw2102_frontend_attach,
-			.stream = {
-				.type = USB_BULK,
-				.count = 8,
-				.endpoint = 0x82,
-				.u = {
-					.bulk = {
-						.buffersize = 4096,
-					}
-				}
-			},
-		}},
-		}
-	},
-	.num_device_descs = 3,
-	.devices = {
-		{"DVBWorld DVB-S 2102 USB2.0",
-			{&dw2102_table[CYPRESS_DW2102], NULL},
-			{NULL},
-		},
-		{"DVBWorld DVB-S 2101 USB2.0",
-			{&dw2102_table[CYPRESS_DW2101], NULL},
-			{NULL},
-		},
-		{"TerraTec Cinergy S USB",
-			{&dw2102_table[TERRATEC_CINERGY_S], NULL},
-			{NULL},
-		},
-	}
-};
-
-static struct dvb_usb_device_properties dw2104_properties = {
-	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
-	.usb_ctrl = DEVICE_SPECIFIC,
-	.firmware = "dvb-usb-dw2104.fw",
-	.no_reconnect = 1,
-
-	.i2c_algo = &dw2104_i2c_algo,
-	.rc.legacy = {
-		.rc_map_table = rc_map_dw210x_table,
-		.rc_map_size = ARRAY_SIZE(rc_map_dw210x_table),
-		.rc_interval = 150,
-		.rc_query = dw2102_rc_query,
-	},
-
-	.generic_bulk_ctrl_endpoint = 0x81,
-	/* parameter for the MPEG2-data transfer */
-	.num_adapters = 1,
-	.download_firmware = dw2102_load_firmware,
-	.read_mac_address = dw210x_read_mac_address,
-	.adapter = {
-		{
-		.num_frontends = 1,
-		.fe = {{
-			.frontend_attach = dw2104_frontend_attach,
-			.stream = {
-				.type = USB_BULK,
-				.count = 8,
-				.endpoint = 0x82,
-				.u = {
-					.bulk = {
-						.buffersize = 4096,
-					}
-				}
-			},
-		}},
-		}
-	},
-	.num_device_descs = 2,
-	.devices = {
-		{ "DVBWorld DW2104 USB2.0",
-			{&dw2102_table[CYPRESS_DW2104], NULL},
-			{NULL},
-		},
-		{ "TeVii S650 USB2.0",
-			{&dw2102_table[TEVII_S650], NULL},
-			{NULL},
-		},
-	}
-};
-
-static struct dvb_usb_device_properties dw3101_properties = {
-	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
-	.usb_ctrl = DEVICE_SPECIFIC,
-	.firmware = "dvb-usb-dw3101.fw",
-	.no_reconnect = 1,
-
-	.i2c_algo = &dw3101_i2c_algo,
-	.rc.legacy = {
-		.rc_map_table = rc_map_dw210x_table,
-		.rc_map_size = ARRAY_SIZE(rc_map_dw210x_table),
-		.rc_interval = 150,
-		.rc_query = dw2102_rc_query,
-	},
-
-	.generic_bulk_ctrl_endpoint = 0x81,
-	/* parameter for the MPEG2-data transfer */
-	.num_adapters = 1,
-	.download_firmware = dw2102_load_firmware,
-	.read_mac_address = dw210x_read_mac_address,
-	.adapter = {
-		{
-		.num_frontends = 1,
-		.fe = {{
-			.frontend_attach = dw3101_frontend_attach,
-			.tuner_attach = dw3101_tuner_attach,
-			.stream = {
-				.type = USB_BULK,
-				.count = 8,
-				.endpoint = 0x82,
-				.u = {
-					.bulk = {
-						.buffersize = 4096,
-					}
-				}
-			},
-		}},
-		}
-	},
-	.num_device_descs = 1,
-	.devices = {
-		{ "DVBWorld DVB-C 3101 USB2.0",
-			{&dw2102_table[CYPRESS_DW3101], NULL},
-			{NULL},
-		},
-	}
-};
-
-static struct dvb_usb_device_properties s6x0_properties = {
-	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
-	.usb_ctrl = DEVICE_SPECIFIC,
-	.size_of_priv = sizeof(struct s6x0_state),
-	.firmware = "dvb-usb-s630.fw",
-	.no_reconnect = 1,
-
-	.i2c_algo = &s6x0_i2c_algo,
-	.rc.legacy = {
-		.rc_map_table = rc_map_tevii_table,
-		.rc_map_size = ARRAY_SIZE(rc_map_tevii_table),
-		.rc_interval = 150,
-		.rc_query = dw2102_rc_query,
-	},
-
-	.generic_bulk_ctrl_endpoint = 0x81,
-	.num_adapters = 1,
-	.download_firmware = dw2102_load_firmware,
-	.read_mac_address = s6x0_read_mac_address,
-	.adapter = {
-		{
-		.num_frontends = 1,
-		.fe = {{
-			.frontend_attach = zl100313_frontend_attach,
-			.stream = {
-				.type = USB_BULK,
-				.count = 8,
-				.endpoint = 0x82,
-				.u = {
-					.bulk = {
-						.buffersize = 4096,
-					}
-				}
-			},
-		}},
-		}
-	},
-	.num_device_descs = 1,
-	.devices = {
-		{"TeVii S630 USB",
-			{&dw2102_table[TEVII_S630], NULL},
-			{NULL},
-		},
-	}
-};
-
-struct dvb_usb_device_properties *p1100;
-static struct dvb_usb_device_description d1100 = {
-	"Prof 1100 USB ",
-	{&dw2102_table[PROF_1100], NULL},
-	{NULL},
-};
-
-struct dvb_usb_device_properties *s660;
-static struct dvb_usb_device_description d660 = {
-	"TeVii S660 USB",
-	{&dw2102_table[TEVII_S660], NULL},
-	{NULL},
-};
-
-static struct dvb_usb_device_description d480_1 = {
-	"TeVii S480.1 USB",
-	{&dw2102_table[TEVII_S480_1], NULL},
-	{NULL},
-};
-
-static struct dvb_usb_device_description d480_2 = {
-	"TeVii S480.2 USB",
-	{&dw2102_table[TEVII_S480_2], NULL},
-	{NULL},
-};
-
-struct dvb_usb_device_properties *p7500;
-static struct dvb_usb_device_description d7500 = {
-	"Prof 7500 USB DVB-S2",
-	{&dw2102_table[PROF_7500], NULL},
-	{NULL},
-};
-
-static struct dvb_usb_device_properties su3000_properties = {
-	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
-	.usb_ctrl = DEVICE_SPECIFIC,
-	.size_of_priv = sizeof(struct su3000_state),
-	.power_ctrl = su3000_power_ctrl,
-	.num_adapters = 1,
-	.identify_state	= su3000_identify_state,
-	.i2c_algo = &su3000_i2c_algo,
-
-	.rc.legacy = {
-		.rc_map_table = rc_map_su3000_table,
-		.rc_map_size = ARRAY_SIZE(rc_map_su3000_table),
-		.rc_interval = 150,
-		.rc_query = dw2102_rc_query,
-	},
-
-	.read_mac_address = su3000_read_mac_address,
-
-	.generic_bulk_ctrl_endpoint = 0x01,
-
-	.adapter = {
-		{
-		.num_frontends = 1,
-		.fe = {{
-			.streaming_ctrl   = su3000_streaming_ctrl,
-			.frontend_attach  = su3000_frontend_attach,
-			.stream = {
-				.type = USB_BULK,
-				.count = 8,
-				.endpoint = 0x82,
-				.u = {
-					.bulk = {
-						.buffersize = 4096,
-					}
-				}
-			}
-		}},
-		}
-	},
-	.num_device_descs = 3,
-	.devices = {
-		{ "SU3000HD DVB-S USB2.0",
-			{ &dw2102_table[GENIATECH_SU3000], NULL },
-			{ NULL },
-		},
-		{ "Terratec Cinergy S2 USB HD",
-			{ &dw2102_table[TERRATEC_CINERGY_S2], NULL },
-			{ NULL },
-		},
-		{ "X3M TV SPC1400HD PCI",
-			{ &dw2102_table[X3M_SPC1400HD], NULL },
-			{ NULL },
-		},
-	}
-};
-
-static int dw2102_probe(struct usb_interface *intf,
-		const struct usb_device_id *id)
-{
-	p1100 = kmemdup(&s6x0_properties,
-			sizeof(struct dvb_usb_device_properties), GFP_KERNEL);
-	if (!p1100)
-		return -ENOMEM;
-	/* copy default structure */
-	/* fill only different fields */
-	p1100->firmware = "dvb-usb-p1100.fw";
-	p1100->devices[0] = d1100;
-	p1100->rc.legacy.rc_map_table = rc_map_tbs_table;
-	p1100->rc.legacy.rc_map_size = ARRAY_SIZE(rc_map_tbs_table);
-	p1100->adapter->fe[0].frontend_attach = stv0288_frontend_attach;
-
-	s660 = kmemdup(&s6x0_properties,
-		       sizeof(struct dvb_usb_device_properties), GFP_KERNEL);
-	if (!s660) {
-		kfree(p1100);
-		return -ENOMEM;
-	}
-	s660->firmware = "dvb-usb-s660.fw";
-	s660->num_device_descs = 3;
-	s660->devices[0] = d660;
-	s660->devices[1] = d480_1;
-	s660->devices[2] = d480_2;
-	s660->adapter->fe[0].frontend_attach = ds3000_frontend_attach;
-
-	p7500 = kmemdup(&s6x0_properties,
-			sizeof(struct dvb_usb_device_properties), GFP_KERNEL);
-	if (!p7500) {
-		kfree(p1100);
-		kfree(s660);
-		return -ENOMEM;
-	}
-	p7500->firmware = "dvb-usb-p7500.fw";
-	p7500->devices[0] = d7500;
-	p7500->rc.legacy.rc_map_table = rc_map_tbs_table;
-	p7500->rc.legacy.rc_map_size = ARRAY_SIZE(rc_map_tbs_table);
-	p7500->adapter->fe[0].frontend_attach = prof_7500_frontend_attach;
-
-	if (0 == dvb_usb_device_init(intf, &dw2102_properties,
-			THIS_MODULE, NULL, adapter_nr) ||
-	    0 == dvb_usb_device_init(intf, &dw2104_properties,
-			THIS_MODULE, NULL, adapter_nr) ||
-	    0 == dvb_usb_device_init(intf, &dw3101_properties,
-			THIS_MODULE, NULL, adapter_nr) ||
-	    0 == dvb_usb_device_init(intf, &s6x0_properties,
-			THIS_MODULE, NULL, adapter_nr) ||
-	    0 == dvb_usb_device_init(intf, p1100,
-			THIS_MODULE, NULL, adapter_nr) ||
-	    0 == dvb_usb_device_init(intf, s660,
-			THIS_MODULE, NULL, adapter_nr) ||
-	    0 == dvb_usb_device_init(intf, p7500,
-			THIS_MODULE, NULL, adapter_nr) ||
-	    0 == dvb_usb_device_init(intf, &su3000_properties,
-				     THIS_MODULE, NULL, adapter_nr))
-		return 0;
-
-	return -ENODEV;
-}
-
-static struct usb_driver dw2102_driver = {
-	.name = "dw2102",
-	.probe = dw2102_probe,
-	.disconnect = dvb_usb_device_exit,
-	.id_table = dw2102_table,
-};
-
-module_usb_driver(dw2102_driver);
-
-MODULE_AUTHOR("Igor M. Liplianin (c) liplianin@me.by");
-MODULE_DESCRIPTION("Driver for DVBWorld DVB-S 2101, 2102, DVB-S2 2104,"
-				" DVB-C 3101 USB2.0,"
-				" TeVii S600, S630, S650, S660, S480,"
-				" Prof 1100, 7500 USB2.0,"
-				" Geniatech SU3000 devices");
-MODULE_VERSION("0.1");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/dw2102.h b/drivers/media/dvb/dvb-usb/dw2102.h
deleted file mode 100644
index 5cd0b0e..0000000
--- a/drivers/media/dvb/dvb-usb/dw2102.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef _DW2102_H_
-#define _DW2102_H_
-
-#define DVB_USB_LOG_PREFIX "dw2102"
-#include "dvb-usb.h"
-
-#define deb_xfer(args...) dprintk(dvb_usb_dw2102_debug, 0x02, args)
-#define deb_rc(args...)   dprintk(dvb_usb_dw2102_debug, 0x04, args)
-#endif
diff --git a/drivers/media/dvb/dvb-usb/ec168.c b/drivers/media/dvb/dvb-usb/ec168.c
deleted file mode 100644
index b4989ba..0000000
--- a/drivers/media/dvb/dvb-usb/ec168.c
+++ /dev/null
@@ -1,435 +0,0 @@
-/*
- * E3C EC168 DVB USB driver
- *
- * 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 "ec168.h"
-#include "ec100.h"
-#include "mxl5005s.h"
-
-/* debug */
-static int dvb_usb_ec168_debug;
-module_param_named(debug, dvb_usb_ec168_debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS);
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-static struct ec100_config ec168_ec100_config;
-
-static int ec168_rw_udev(struct usb_device *udev, struct ec168_req *req)
-{
-	int ret;
-	unsigned int pipe;
-	u8 request, requesttype;
-	u8 *buf;
-
-
-
-	switch (req->cmd) {
-	case DOWNLOAD_FIRMWARE:
-	case GPIO:
-	case WRITE_I2C:
-	case STREAMING_CTRL:
-		requesttype = (USB_TYPE_VENDOR | USB_DIR_OUT);
-		request = req->cmd;
-		break;
-	case READ_I2C:
-		requesttype = (USB_TYPE_VENDOR | USB_DIR_IN);
-		request = req->cmd;
-		break;
-	case GET_CONFIG:
-		requesttype = (USB_TYPE_VENDOR | USB_DIR_IN);
-		request = CONFIG;
-		break;
-	case SET_CONFIG:
-		requesttype = (USB_TYPE_VENDOR | USB_DIR_OUT);
-		request = CONFIG;
-		break;
-	case WRITE_DEMOD:
-		requesttype = (USB_TYPE_VENDOR | USB_DIR_OUT);
-		request = DEMOD_RW;
-		break;
-	case READ_DEMOD:
-		requesttype = (USB_TYPE_VENDOR | USB_DIR_IN);
-		request = DEMOD_RW;
-		break;
-	default:
-		err("unknown command:%02x", req->cmd);
-		ret = -EPERM;
-		goto error;
-	}
-
-	buf = kmalloc(req->size, GFP_KERNEL);
-	if (!buf) {
-		ret = -ENOMEM;
-		goto error;
-	}
-
-	if (requesttype == (USB_TYPE_VENDOR | USB_DIR_OUT)) {
-		/* write */
-		memcpy(buf, req->data, req->size);
-		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, req->value,
-		req->index, buf, req->size, EC168_USB_TIMEOUT);
-
-	ec168_debug_dump(request, requesttype, req->value, req->index, buf,
-		req->size, deb_xfer);
-
-	if (ret < 0)
-		goto err_dealloc;
-	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->size);
-
-	kfree(buf);
-	return ret;
-
-err_dealloc:
-	kfree(buf);
-error:
-	deb_info("%s: failed:%d\n", __func__, ret);
-	return ret;
-}
-
-static int ec168_ctrl_msg(struct dvb_usb_device *d, struct ec168_req *req)
-{
-	return ec168_rw_udev(d->udev, req);
-}
-
-/* I2C */
-static int ec168_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
-	int num)
-{
-	struct dvb_usb_device *d = i2c_get_adapdata(adap);
-	struct ec168_req req;
-	int i = 0;
-	int ret;
-
-	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 == ec168_ec100_config.demod_address) {
-				req.cmd = READ_DEMOD;
-				req.value = 0;
-				req.index = 0xff00 + msg[i].buf[0]; /* reg */
-				req.size = msg[i+1].len; /* bytes to read */
-				req.data = &msg[i+1].buf[0];
-				ret = ec168_ctrl_msg(d, &req);
-				i += 2;
-			} else {
-				err("I2C read not implemented");
-				ret = -ENOSYS;
-				i += 2;
-			}
-		} else {
-			if (msg[i].addr == ec168_ec100_config.demod_address) {
-				req.cmd = WRITE_DEMOD;
-				req.value = msg[i].buf[1]; /* val */
-				req.index = 0xff00 + msg[i].buf[0]; /* reg */
-				req.size = 0;
-				req.data = NULL;
-				ret = ec168_ctrl_msg(d, &req);
-				i += 1;
-			} else {
-				req.cmd = WRITE_I2C;
-				req.value = msg[i].buf[0]; /* val */
-				req.index = 0x0100 + msg[i].addr; /* I2C addr */
-				req.size = msg[i].len-1;
-				req.data = &msg[i].buf[1];
-				ret = ec168_ctrl_msg(d, &req);
-				i += 1;
-			}
-		}
-		if (ret)
-			goto error;
-
-	}
-	ret = i;
-
-error:
-	mutex_unlock(&d->i2c_mutex);
-	return i;
-}
-
-
-static u32 ec168_i2c_func(struct i2c_adapter *adapter)
-{
-	return I2C_FUNC_I2C;
-}
-
-static struct i2c_algorithm ec168_i2c_algo = {
-	.master_xfer   = ec168_i2c_xfer,
-	.functionality = ec168_i2c_func,
-};
-
-/* Callbacks for DVB USB */
-static struct ec100_config ec168_ec100_config = {
-	.demod_address = 0xff, /* not real address, demod is integrated */
-};
-
-static int ec168_ec100_frontend_attach(struct dvb_usb_adapter *adap)
-{
-	deb_info("%s:\n", __func__);
-	adap->fe_adap[0].fe = dvb_attach(ec100_attach, &ec168_ec100_config,
-		&adap->dev->i2c_adap);
-	if (adap->fe_adap[0].fe == NULL)
-		return -ENODEV;
-
-	return 0;
-}
-
-static struct mxl5005s_config ec168_mxl5003s_config = {
-	.i2c_address     = 0xc6,
-	.if_freq         = IF_FREQ_4570000HZ,
-	.xtal_freq       = CRYSTAL_FREQ_16000000HZ,
-	.agc_mode        = MXL_SINGLE_AGC,
-	.tracking_filter = MXL_TF_OFF,
-	.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 ec168_mxl5003s_tuner_attach(struct dvb_usb_adapter *adap)
-{
-	deb_info("%s:\n", __func__);
-	return dvb_attach(mxl5005s_attach, adap->fe_adap[0].fe, &adap->dev->i2c_adap,
-		&ec168_mxl5003s_config) == NULL ? -ENODEV : 0;
-}
-
-static int ec168_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
-{
-	struct ec168_req req = {STREAMING_CTRL, 0x7f01, 0x0202, 0, NULL};
-	deb_info("%s: onoff:%d\n", __func__, onoff);
-	if (onoff)
-		req.index = 0x0102;
-	return ec168_ctrl_msg(adap->dev, &req);
-}
-
-static int ec168_download_firmware(struct usb_device *udev,
-	const struct firmware *fw)
-{
-	int i, len, packets, remainder, ret;
-	u16 addr = 0x0000; /* firmware start address */
-	struct ec168_req req = {DOWNLOAD_FIRMWARE, 0, 0, 0, NULL};
-	deb_info("%s:\n", __func__);
-
-	#define FW_PACKET_MAX_DATA  2048
-	packets = fw->size / FW_PACKET_MAX_DATA;
-	remainder = fw->size % FW_PACKET_MAX_DATA;
-	len = FW_PACKET_MAX_DATA;
-	for (i = 0; i <= packets; i++) {
-		if (i == packets)  /* set size of the last packet */
-			len = remainder;
-
-		req.size = len;
-		req.data = (u8 *)(fw->data + i * FW_PACKET_MAX_DATA);
-		req.index = addr;
-		addr += FW_PACKET_MAX_DATA;
-
-		ret = ec168_rw_udev(udev, &req);
-		if (ret) {
-			err("firmware download failed:%d packet:%d", ret, i);
-			goto error;
-		}
-	}
-	req.size = 0;
-
-	/* set "warm"? */
-	req.cmd = SET_CONFIG;
-	req.value = 0;
-	req.index = 0x0001;
-	ret = ec168_rw_udev(udev, &req);
-	if (ret)
-		goto error;
-
-	/* really needed - no idea what does */
-	req.cmd = GPIO;
-	req.value = 0;
-	req.index = 0x0206;
-	ret = ec168_rw_udev(udev, &req);
-	if (ret)
-		goto error;
-
-	/* activate tuner I2C? */
-	req.cmd = WRITE_I2C;
-	req.value = 0;
-	req.index = 0x00c6;
-	ret = ec168_rw_udev(udev, &req);
-	if (ret)
-		goto error;
-
-	return ret;
-error:
-	deb_info("%s: failed:%d\n", __func__, ret);
-	return ret;
-}
-
-static int ec168_identify_state(struct usb_device *udev,
-	struct dvb_usb_device_properties *props,
-	struct dvb_usb_device_description **desc, int *cold)
-{
-	int ret;
-	u8 reply;
-	struct ec168_req req = {GET_CONFIG, 0, 1, sizeof(reply), &reply};
-	deb_info("%s:\n", __func__);
-
-	ret = ec168_rw_udev(udev, &req);
-	if (ret)
-		goto error;
-
-	deb_info("%s: reply:%02x\n", __func__, reply);
-
-	if (reply == 0x01)
-		*cold = 0;
-	else
-		*cold = 1;
-
-	return ret;
-error:
-	deb_info("%s: failed:%d\n", __func__, ret);
-	return ret;
-}
-
-/* DVB USB Driver stuff */
-static struct dvb_usb_device_properties ec168_properties;
-
-static int ec168_probe(struct usb_interface *intf,
-	const struct usb_device_id *id)
-{
-	int ret;
-	deb_info("%s: interface:%d\n", __func__,
-		intf->cur_altsetting->desc.bInterfaceNumber);
-
-	ret = dvb_usb_device_init(intf, &ec168_properties, THIS_MODULE, NULL,
-		adapter_nr);
-	if (ret)
-		goto error;
-
-	return ret;
-error:
-	deb_info("%s: failed:%d\n", __func__, ret);
-	return ret;
-}
-
-#define E3C_EC168_1689                          0
-#define E3C_EC168_FFFA                          1
-#define E3C_EC168_FFFB                          2
-#define E3C_EC168_1001                          3
-#define E3C_EC168_1002                          4
-
-static struct usb_device_id ec168_id[] = {
-	[E3C_EC168_1689] =
-		{USB_DEVICE(USB_VID_E3C, USB_PID_E3C_EC168)},
-	[E3C_EC168_FFFA] =
-		{USB_DEVICE(USB_VID_E3C, USB_PID_E3C_EC168_2)},
-	[E3C_EC168_FFFB] =
-		{USB_DEVICE(USB_VID_E3C, USB_PID_E3C_EC168_3)},
-	[E3C_EC168_1001] =
-		{USB_DEVICE(USB_VID_E3C, USB_PID_E3C_EC168_4)},
-	[E3C_EC168_1002] =
-		{USB_DEVICE(USB_VID_E3C, USB_PID_E3C_EC168_5)},
-	{} /* terminating entry */
-};
-
-MODULE_DEVICE_TABLE(usb, ec168_id);
-
-static struct dvb_usb_device_properties ec168_properties = {
-	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
-
-	.usb_ctrl = DEVICE_SPECIFIC,
-	.download_firmware = ec168_download_firmware,
-	.firmware = "dvb-usb-ec168.fw",
-	.no_reconnect = 1,
-
-	.size_of_priv = 0,
-
-	.num_adapters = 1,
-	.adapter = {
-		{
-		.num_frontends = 1,
-		.fe = {{
-			.streaming_ctrl   = ec168_streaming_ctrl,
-			.frontend_attach  = ec168_ec100_frontend_attach,
-			.tuner_attach     = ec168_mxl5003s_tuner_attach,
-			.stream = {
-				.type = USB_BULK,
-				.count = 6,
-				.endpoint = 0x82,
-				.u = {
-					.bulk = {
-						.buffersize = (32*512),
-					}
-				}
-			},
-		}},
-		}
-	},
-
-	.identify_state = ec168_identify_state,
-
-	.i2c_algo = &ec168_i2c_algo,
-
-	.num_device_descs = 1,
-	.devices = {
-		{
-			.name = "E3C EC168 DVB-T USB2.0 reference design",
-			.cold_ids = {
-				&ec168_id[E3C_EC168_1689],
-				&ec168_id[E3C_EC168_FFFA],
-				&ec168_id[E3C_EC168_FFFB],
-				&ec168_id[E3C_EC168_1001],
-				&ec168_id[E3C_EC168_1002],
-				NULL},
-			.warm_ids = {NULL},
-		},
-	}
-};
-
-static struct usb_driver ec168_driver = {
-	.name       = "dvb_usb_ec168",
-	.probe      = ec168_probe,
-	.disconnect = dvb_usb_device_exit,
-	.id_table   = ec168_id,
-};
-
-module_usb_driver(ec168_driver);
-
-MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
-MODULE_DESCRIPTION("E3C EC168 DVB-T USB2.0 driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/ec168.h b/drivers/media/dvb/dvb-usb/ec168.h
deleted file mode 100644
index e7e0b83..0000000
--- a/drivers/media/dvb/dvb-usb/ec168.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * E3C EC168 DVB USB driver
- *
- * 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 EC168_H
-#define EC168_H
-
-#define DVB_USB_LOG_PREFIX "ec168"
-#include "dvb-usb.h"
-
-#define deb_info(args...) dprintk(dvb_usb_ec168_debug, 0x01, args)
-#define deb_rc(args...)   dprintk(dvb_usb_ec168_debug, 0x02, args)
-#define deb_xfer(args...) dprintk(dvb_usb_ec168_debug, 0x04, args)
-#define deb_reg(args...)  dprintk(dvb_usb_ec168_debug, 0x08, args)
-#define deb_i2c(args...)  dprintk(dvb_usb_ec168_debug, 0x10, args)
-#define deb_fw(args...)   dprintk(dvb_usb_ec168_debug, 0x20, args)
-
-#define ec168_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 EC168_USB_TIMEOUT 1000
-
-struct ec168_req {
-	u8  cmd;       /* [1] */
-	u16 value;     /* [2|3] */
-	u16 index;     /* [4|5] */
-	u16 size;      /* [6|7] */
-	u8  *data;
-};
-
-enum ec168_cmd {
-	DOWNLOAD_FIRMWARE    = 0x00,
-	CONFIG               = 0x01,
-	DEMOD_RW             = 0x03,
-	GPIO                 = 0x04,
-	STREAMING_CTRL       = 0x10,
-	READ_I2C             = 0x20,
-	WRITE_I2C            = 0x21,
-	HID_DOWNLOAD         = 0x30,
-	GET_CONFIG,
-	SET_CONFIG,
-	READ_DEMOD,
-	WRITE_DEMOD,
-};
-
-#endif
diff --git a/drivers/media/dvb/dvb-usb/friio-fe.c b/drivers/media/dvb/dvb-usb/friio-fe.c
deleted file mode 100644
index 90a70c6..0000000
--- a/drivers/media/dvb/dvb-usb/friio-fe.c
+++ /dev/null
@@ -1,473 +0,0 @@
-/* DVB USB compliant Linux driver for the Friio USB2.0 ISDB-T receiver.
- *
- * Copyright (C) 2009 Akihiro Tsukada <tskd2@yahoo.co.jp>
- *
- * This module is based off the the gl861 and vp702x modules.
- *
- * This program is free software; 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.
- *
- * see Documentation/dvb/README.dvb-usb for more information
- */
-#include <linux/init.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-
-#include "friio.h"
-
-struct jdvbt90502_state {
-	struct i2c_adapter *i2c;
-	struct dvb_frontend frontend;
-	struct jdvbt90502_config config;
-};
-
-/* NOTE: TC90502 has 16bit register-address? */
-/* register 0x0100 is used for reading PLL status, so reg is u16 here */
-static int jdvbt90502_reg_read(struct jdvbt90502_state *state,
-			       const u16 reg, u8 *buf, const size_t count)
-{
-	int ret;
-	u8 wbuf[3];
-	struct i2c_msg msg[2];
-
-	wbuf[0] = reg & 0xFF;
-	wbuf[1] = 0;
-	wbuf[2] = reg >> 8;
-
-	msg[0].addr = state->config.demod_address;
-	msg[0].flags = 0;
-	msg[0].buf = wbuf;
-	msg[0].len = sizeof(wbuf);
-
-	msg[1].addr = msg[0].addr;
-	msg[1].flags = I2C_M_RD;
-	msg[1].buf = buf;
-	msg[1].len = count;
-
-	ret = i2c_transfer(state->i2c, msg, 2);
-	if (ret != 2) {
-		deb_fe(" reg read failed.\n");
-		return -EREMOTEIO;
-	}
-	return 0;
-}
-
-/* currently 16bit register-address is not used, so reg is u8 here */
-static int jdvbt90502_single_reg_write(struct jdvbt90502_state *state,
-				       const u8 reg, const u8 val)
-{
-	struct i2c_msg msg;
-	u8 wbuf[2];
-
-	wbuf[0] = reg;
-	wbuf[1] = val;
-
-	msg.addr = state->config.demod_address;
-	msg.flags = 0;
-	msg.buf = wbuf;
-	msg.len = sizeof(wbuf);
-
-	if (i2c_transfer(state->i2c, &msg, 1) != 1) {
-		deb_fe(" reg write failed.");
-		return -EREMOTEIO;
-	}
-	return 0;
-}
-
-static int _jdvbt90502_write(struct dvb_frontend *fe, const u8 buf[], int len)
-{
-	struct jdvbt90502_state *state = fe->demodulator_priv;
-	int err, i;
-	for (i = 0; i < len - 1; i++) {
-		err = jdvbt90502_single_reg_write(state,
-						  buf[0] + i, buf[i + 1]);
-		if (err)
-			return err;
-	}
-
-	return 0;
-}
-
-/* read pll status byte via the demodulator's I2C register */
-/* note: Win box reads it by 8B block at the I2C addr 0x30 from reg:0x80 */
-static int jdvbt90502_pll_read(struct jdvbt90502_state *state, u8 *result)
-{
-	int ret;
-
-	/* +1 for reading */
-	u8 pll_addr_byte = (state->config.pll_address << 1) + 1;
-
-	*result = 0;
-
-	ret = jdvbt90502_single_reg_write(state, JDVBT90502_2ND_I2C_REG,
-					  pll_addr_byte);
-	if (ret)
-		goto error;
-
-	ret = jdvbt90502_reg_read(state, 0x0100, result, 1);
-	if (ret)
-		goto error;
-
-	deb_fe("PLL read val:%02x\n", *result);
-	return 0;
-
-error:
-	deb_fe("%s:ret == %d\n", __func__, ret);
-	return -EREMOTEIO;
-}
-
-
-/* set pll frequency via the demodulator's I2C register */
-static int jdvbt90502_pll_set_freq(struct jdvbt90502_state *state, u32 freq)
-{
-	int ret;
-	int retry;
-	u8 res1;
-	u8 res2[9];
-
-	u8 pll_freq_cmd[PLL_CMD_LEN];
-	u8 pll_agc_cmd[PLL_CMD_LEN];
-	struct i2c_msg msg[2];
-	u32 f;
-
-	deb_fe("%s: freq=%d, step=%d\n", __func__, freq,
-	       state->frontend.ops.info.frequency_stepsize);
-	/* freq -> oscilator frequency conversion. */
-	/* freq: 473,000,000 + n*6,000,000 [+ 142857 (center freq. shift)] */
-	f = freq / state->frontend.ops.info.frequency_stepsize;
-	/* add 399[1/7 MHZ] = 57MHz for the IF  */
-	f += 399;
-	/* add center frequency shift if necessary */
-	if (f % 7 == 0)
-		f++;
-	pll_freq_cmd[DEMOD_REDIRECT_REG] = JDVBT90502_2ND_I2C_REG; /* 0xFE */
-	pll_freq_cmd[ADDRESS_BYTE] = state->config.pll_address << 1;
-	pll_freq_cmd[DIVIDER_BYTE1] = (f >> 8) & 0x7F;
-	pll_freq_cmd[DIVIDER_BYTE2] = f & 0xFF;
-	pll_freq_cmd[CONTROL_BYTE] = 0xB2; /* ref.divider:28, 4MHz/28=1/7MHz */
-	pll_freq_cmd[BANDSWITCH_BYTE] = 0x08;	/* UHF band */
-
-	msg[0].addr = state->config.demod_address;
-	msg[0].flags = 0;
-	msg[0].buf = pll_freq_cmd;
-	msg[0].len = sizeof(pll_freq_cmd);
-
-	ret = i2c_transfer(state->i2c, &msg[0], 1);
-	if (ret != 1)
-		goto error;
-
-	udelay(50);
-
-	pll_agc_cmd[DEMOD_REDIRECT_REG] = pll_freq_cmd[DEMOD_REDIRECT_REG];
-	pll_agc_cmd[ADDRESS_BYTE] = pll_freq_cmd[ADDRESS_BYTE];
-	pll_agc_cmd[DIVIDER_BYTE1] = pll_freq_cmd[DIVIDER_BYTE1];
-	pll_agc_cmd[DIVIDER_BYTE2] = pll_freq_cmd[DIVIDER_BYTE2];
-	pll_agc_cmd[CONTROL_BYTE] = 0x9A; /*  AGC_CTRL instead of BANDSWITCH */
-	pll_agc_cmd[AGC_CTRL_BYTE] = 0x50;
-	/* AGC Time Constant 2s, AGC take-over point:103dBuV(lowest) */
-
-	msg[1].addr = msg[0].addr;
-	msg[1].flags = 0;
-	msg[1].buf = pll_agc_cmd;
-	msg[1].len = sizeof(pll_agc_cmd);
-
-	ret = i2c_transfer(state->i2c, &msg[1], 1);
-	if (ret != 1)
-		goto error;
-
-	/* I don't know what these cmds are for,  */
-	/* but the USB log on a windows box contains them */
-	ret = jdvbt90502_single_reg_write(state, 0x01, 0x40);
-	ret |= jdvbt90502_single_reg_write(state, 0x01, 0x00);
-	if (ret)
-		goto error;
-	udelay(100);
-
-	/* wait for the demod to be ready? */
-#define RETRY_COUNT 5
-	for (retry = 0; retry < RETRY_COUNT; retry++) {
-		ret = jdvbt90502_reg_read(state, 0x0096, &res1, 1);
-		if (ret)
-			goto error;
-		/* if (res1 != 0x00) goto error; */
-		ret = jdvbt90502_reg_read(state, 0x00B0, res2, sizeof(res2));
-		if (ret)
-			goto error;
-		if (res2[0] >= 0xA7)
-			break;
-		msleep(100);
-	}
-	if (retry >= RETRY_COUNT) {
-		deb_fe("%s: FE does not get ready after freq setting.\n",
-		       __func__);
-		return -EREMOTEIO;
-	}
-
-	return 0;
-error:
-	deb_fe("%s:ret == %d\n", __func__, ret);
-	return -EREMOTEIO;
-}
-
-static int jdvbt90502_read_status(struct dvb_frontend *fe, fe_status_t *state)
-{
-	u8 result;
-	int ret;
-
-	*state = FE_HAS_SIGNAL;
-
-	ret = jdvbt90502_pll_read(fe->demodulator_priv, &result);
-	if (ret) {
-		deb_fe("%s:ret == %d\n", __func__, ret);
-		return -EREMOTEIO;
-	}
-
-	*state = FE_HAS_SIGNAL
-		| FE_HAS_CARRIER
-		| FE_HAS_VITERBI
-		| FE_HAS_SYNC;
-
-	if (result & PLL_STATUS_LOCKED)
-		*state |= FE_HAS_LOCK;
-
-	return 0;
-}
-
-static int jdvbt90502_read_signal_strength(struct dvb_frontend *fe,
-					   u16 *strength)
-{
-	int ret;
-	u8 rbuf[37];
-
-	*strength = 0;
-
-	/* status register (incl. signal strength) : 0x89  */
-	/* TODO: read just the necessary registers [0x8B..0x8D]? */
-	ret = jdvbt90502_reg_read(fe->demodulator_priv, 0x0089,
-				  rbuf, sizeof(rbuf));
-
-	if (ret) {
-		deb_fe("%s:ret == %d\n", __func__, ret);
-		return -EREMOTEIO;
-	}
-
-	/* signal_strength: rbuf[2-4] (24bit BE), use lower 16bit for now. */
-	*strength = (rbuf[3] << 8) + rbuf[4];
-	if (rbuf[2])
-		*strength = 0xffff;
-
-	return 0;
-}
-
-
-/* filter out un-supported properties to notify users */
-static int jdvbt90502_set_property(struct dvb_frontend *fe,
-				   struct dtv_property *tvp)
-{
-	int r = 0;
-
-	switch (tvp->cmd) {
-	case DTV_DELIVERY_SYSTEM:
-		if (tvp->u.data != SYS_ISDBT)
-			r = -EINVAL;
-		break;
-	case DTV_CLEAR:
-	case DTV_TUNE:
-	case DTV_FREQUENCY:
-		break;
-	default:
-		r = -EINVAL;
-	}
-	return r;
-}
-
-static int jdvbt90502_get_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	p->inversion = INVERSION_AUTO;
-	p->bandwidth_hz = 6000000;
-	p->code_rate_HP = FEC_AUTO;
-	p->code_rate_LP = FEC_AUTO;
-	p->modulation = QAM_64;
-	p->transmission_mode = TRANSMISSION_MODE_AUTO;
-	p->guard_interval = GUARD_INTERVAL_AUTO;
-	p->hierarchy = HIERARCHY_AUTO;
-	return 0;
-}
-
-static int jdvbt90502_set_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-
-	/**
-	 * NOTE: ignore all the parameters except frequency.
-	 *       others should be fixed to the proper value for ISDB-T,
-	 *       but don't check here.
-	 */
-
-	struct jdvbt90502_state *state = fe->demodulator_priv;
-	int ret;
-
-	deb_fe("%s: Freq:%d\n", __func__, p->frequency);
-
-	/* for recovery from DTV_CLEAN */
-	fe->dtv_property_cache.delivery_system = SYS_ISDBT;
-
-	ret = jdvbt90502_pll_set_freq(state, p->frequency);
-	if (ret) {
-		deb_fe("%s:ret == %d\n", __func__, ret);
-		return -EREMOTEIO;
-	}
-
-	return 0;
-}
-
-
-/**
- * (reg, val) commad list to initialize this module.
- *  captured on a Windows box.
- */
-static u8 init_code[][2] = {
-	{0x01, 0x40},
-	{0x04, 0x38},
-	{0x05, 0x40},
-	{0x07, 0x40},
-	{0x0F, 0x4F},
-	{0x11, 0x21},
-	{0x12, 0x0B},
-	{0x13, 0x2F},
-	{0x14, 0x31},
-	{0x16, 0x02},
-	{0x21, 0xC4},
-	{0x22, 0x20},
-	{0x2C, 0x79},
-	{0x2D, 0x34},
-	{0x2F, 0x00},
-	{0x30, 0x28},
-	{0x31, 0x31},
-	{0x32, 0xDF},
-	{0x38, 0x01},
-	{0x39, 0x78},
-	{0x3B, 0x33},
-	{0x3C, 0x33},
-	{0x48, 0x90},
-	{0x51, 0x68},
-	{0x5E, 0x38},
-	{0x71, 0x00},
-	{0x72, 0x08},
-	{0x77, 0x00},
-	{0xC0, 0x21},
-	{0xC1, 0x10},
-	{0xE4, 0x1A},
-	{0xEA, 0x1F},
-	{0x77, 0x00},
-	{0x71, 0x00},
-	{0x71, 0x00},
-	{0x76, 0x0C},
-};
-
-static const int init_code_len = sizeof(init_code) / sizeof(u8[2]);
-
-static int jdvbt90502_init(struct dvb_frontend *fe)
-{
-	int i = -1;
-	int ret;
-	struct i2c_msg msg;
-
-	struct jdvbt90502_state *state = fe->demodulator_priv;
-
-	deb_fe("%s called.\n", __func__);
-
-	msg.addr = state->config.demod_address;
-	msg.flags = 0;
-	msg.len = 2;
-	for (i = 0; i < init_code_len; i++) {
-		msg.buf = init_code[i];
-		ret = i2c_transfer(state->i2c, &msg, 1);
-		if (ret != 1)
-			goto error;
-	}
-	fe->dtv_property_cache.delivery_system = SYS_ISDBT;
-	msleep(100);
-
-	return 0;
-
-error:
-	deb_fe("%s: init_code[%d] failed. ret==%d\n", __func__, i, ret);
-	return -EREMOTEIO;
-}
-
-
-static void jdvbt90502_release(struct dvb_frontend *fe)
-{
-	struct jdvbt90502_state *state = fe->demodulator_priv;
-	kfree(state);
-}
-
-
-static struct dvb_frontend_ops jdvbt90502_ops;
-
-struct dvb_frontend *jdvbt90502_attach(struct dvb_usb_device *d)
-{
-	struct jdvbt90502_state *state = NULL;
-
-	deb_info("%s called.\n", __func__);
-
-	/* allocate memory for the internal state */
-	state = kzalloc(sizeof(struct jdvbt90502_state), GFP_KERNEL);
-	if (state == NULL)
-		goto error;
-
-	/* setup the state */
-	state->i2c = &d->i2c_adap;
-	memcpy(&state->config, &friio_fe_config, sizeof(friio_fe_config));
-
-	/* create dvb_frontend */
-	memcpy(&state->frontend.ops, &jdvbt90502_ops,
-	       sizeof(jdvbt90502_ops));
-	state->frontend.demodulator_priv = state;
-
-	if (jdvbt90502_init(&state->frontend) < 0)
-		goto error;
-
-	return &state->frontend;
-
-error:
-	kfree(state);
-	return NULL;
-}
-
-static struct dvb_frontend_ops jdvbt90502_ops = {
-	.delsys = { SYS_ISDBT },
-	.info = {
-		.name			= "Comtech JDVBT90502 ISDB-T",
-		.frequency_min		= 473000000, /* UHF 13ch, center */
-		.frequency_max		= 767142857, /* UHF 62ch, center */
-		.frequency_stepsize	= JDVBT90502_PLL_CLK / JDVBT90502_PLL_DIVIDER,
-		.frequency_tolerance	= 0,
-
-		/* NOTE: this driver ignores all parameters but frequency. */
-		.caps = FE_CAN_INVERSION_AUTO |
-			FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
-			FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
-			FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO |
-			FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
-			FE_CAN_TRANSMISSION_MODE_AUTO |
-			FE_CAN_GUARD_INTERVAL_AUTO |
-			FE_CAN_HIERARCHY_AUTO,
-	},
-
-	.release = jdvbt90502_release,
-
-	.init = jdvbt90502_init,
-	.write = _jdvbt90502_write,
-
-	.set_property = jdvbt90502_set_property,
-
-	.set_frontend = jdvbt90502_set_frontend,
-	.get_frontend = jdvbt90502_get_frontend,
-
-	.read_status = jdvbt90502_read_status,
-	.read_signal_strength = jdvbt90502_read_signal_strength,
-};
diff --git a/drivers/media/dvb/dvb-usb/friio.c b/drivers/media/dvb/dvb-usb/friio.c
deleted file mode 100644
index 474a17e..0000000
--- a/drivers/media/dvb/dvb-usb/friio.c
+++ /dev/null
@@ -1,522 +0,0 @@
-/* DVB USB compliant Linux driver for the Friio USB2.0 ISDB-T receiver.
- *
- * Copyright (C) 2009 Akihiro Tsukada <tskd2@yahoo.co.jp>
- *
- * This module is based off the the gl861 and vp702x modules.
- *
- * This program is free software; 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.
- *
- * see Documentation/dvb/README.dvb-usb for more information
- */
-#include "friio.h"
-
-/* debug */
-int dvb_usb_friio_debug;
-module_param_named(debug, dvb_usb_friio_debug, int, 0644);
-MODULE_PARM_DESC(debug,
-		 "set debugging level (1=info,2=xfer,4=rc,8=fe (or-able))."
-		 DVB_USB_DEBUG_STATUS);
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-/**
- * Indirect I2C access to the PLL via FE.
- * whole I2C protocol data to the PLL is sent via the FE's I2C register.
- * This is done by a control msg to the FE with the I2C data accompanied, and
- * a specific USB request number is assigned for that purpose.
- *
- * this func sends wbuf[1..] to the I2C register wbuf[0] at addr (= at FE).
- * TODO: refoctored, smarter i2c functions.
- */
-static int gl861_i2c_ctrlmsg_data(struct dvb_usb_device *d, u8 addr,
-				  u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
-{
-	u16 index = wbuf[0];	/* must be JDVBT90502_2ND_I2C_REG(=0xFE) */
-	u16 value = addr << (8 + 1);
-	int wo = (rbuf == NULL || rlen == 0);	/* write only */
-	u8 req, type;
-
-	deb_xfer("write to PLL:0x%02x via FE reg:0x%02x, len:%d\n",
-		 wbuf[1], wbuf[0], wlen - 1);
-
-	if (wo && wlen >= 2) {
-		req = GL861_REQ_I2C_DATA_CTRL_WRITE;
-		type = GL861_WRITE;
-		udelay(20);
-		return usb_control_msg(d->udev, usb_sndctrlpipe(d->udev, 0),
-				       req, type, value, index,
-				       &wbuf[1], wlen - 1, 2000);
-	}
-
-	deb_xfer("not supported ctrl-msg, aborting.");
-	return -EINVAL;
-}
-
-/* normal I2C access (without extra data arguments).
- * write to the register wbuf[0] at I2C address addr with the value wbuf[1],
- *  or read from the register wbuf[0].
- * register address can be 16bit (wbuf[2]<<8 | wbuf[0]) if wlen==3
- */
-static int gl861_i2c_msg(struct dvb_usb_device *d, u8 addr,
-			 u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
-{
-	u16 index;
-	u16 value = addr << (8 + 1);
-	int wo = (rbuf == NULL || rlen == 0);	/* write-only */
-	u8 req, type;
-	unsigned int pipe;
-
-	/* special case for the indirect I2C access to the PLL via FE, */
-	if (addr == friio_fe_config.demod_address &&
-	    wbuf[0] == JDVBT90502_2ND_I2C_REG)
-		return gl861_i2c_ctrlmsg_data(d, addr, wbuf, wlen, rbuf, rlen);
-
-	if (wo) {
-		req = GL861_REQ_I2C_WRITE;
-		type = GL861_WRITE;
-		pipe = usb_sndctrlpipe(d->udev, 0);
-	} else {		/* rw */
-		req = GL861_REQ_I2C_READ;
-		type = GL861_READ;
-		pipe = usb_rcvctrlpipe(d->udev, 0);
-	}
-
-	switch (wlen) {
-	case 1:
-		index = wbuf[0];
-		break;
-	case 2:
-		index = wbuf[0];
-		value = value + wbuf[1];
-		break;
-	case 3:
-		/* special case for 16bit register-address */
-		index = (wbuf[2] << 8) | wbuf[0];
-		value = value + wbuf[1];
-		break;
-	default:
-		deb_xfer("wlen = %x, aborting.", wlen);
-		return -EINVAL;
-	}
-	msleep(1);
-	return usb_control_msg(d->udev, pipe, req, type,
-			       value, index, rbuf, rlen, 2000);
-}
-
-/* I2C */
-static int gl861_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
-			  int num)
-{
-	struct dvb_usb_device *d = i2c_get_adapdata(adap);
-	int i;
-
-
-	if (num > 2)
-		return -EINVAL;
-
-	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
-		return -EAGAIN;
-
-	for (i = 0; i < num; i++) {
-		/* write/read request */
-		if (i + 1 < num && (msg[i + 1].flags & I2C_M_RD)) {
-			if (gl861_i2c_msg(d, msg[i].addr,
-					  msg[i].buf, msg[i].len,
-					  msg[i + 1].buf, msg[i + 1].len) < 0)
-				break;
-			i++;
-		} else
-			if (gl861_i2c_msg(d, msg[i].addr, msg[i].buf,
-					  msg[i].len, NULL, 0) < 0)
-				break;
-	}
-
-	mutex_unlock(&d->i2c_mutex);
-	return i;
-}
-
-static u32 gl861_i2c_func(struct i2c_adapter *adapter)
-{
-	return I2C_FUNC_I2C;
-}
-
-static int friio_ext_ctl(struct dvb_usb_adapter *adap,
-			 u32 sat_color, int lnb_on)
-{
-	int i;
-	int ret;
-	struct i2c_msg msg;
-	u8 *buf;
-	u32 mask;
-	u8 lnb = (lnb_on) ? FRIIO_CTL_LNB : 0;
-
-	buf = kmalloc(2, GFP_KERNEL);
-	if (!buf)
-		return -ENOMEM;
-
-	msg.addr = 0x00;
-	msg.flags = 0;
-	msg.len = 2;
-	msg.buf = buf;
-
-	buf[0] = 0x00;
-
-	/* send 2bit header (&B10) */
-	buf[1] = lnb | FRIIO_CTL_LED | FRIIO_CTL_STROBE;
-	ret = gl861_i2c_xfer(&adap->dev->i2c_adap, &msg, 1);
-	buf[1] |= FRIIO_CTL_CLK;
-	ret += gl861_i2c_xfer(&adap->dev->i2c_adap, &msg, 1);
-
-	buf[1] = lnb | FRIIO_CTL_STROBE;
-	ret += gl861_i2c_xfer(&adap->dev->i2c_adap, &msg, 1);
-	buf[1] |= FRIIO_CTL_CLK;
-	ret += gl861_i2c_xfer(&adap->dev->i2c_adap, &msg, 1);
-
-	/* send 32bit(satur, R, G, B) data in serial */
-	mask = 1 << 31;
-	for (i = 0; i < 32; i++) {
-		buf[1] = lnb | FRIIO_CTL_STROBE;
-		if (sat_color & mask)
-			buf[1] |= FRIIO_CTL_LED;
-		ret += gl861_i2c_xfer(&adap->dev->i2c_adap, &msg, 1);
-		buf[1] |= FRIIO_CTL_CLK;
-		ret += gl861_i2c_xfer(&adap->dev->i2c_adap, &msg, 1);
-		mask >>= 1;
-	}
-
-	/* set the strobe off */
-	buf[1] = lnb;
-	ret += gl861_i2c_xfer(&adap->dev->i2c_adap, &msg, 1);
-	buf[1] |= FRIIO_CTL_CLK;
-	ret += gl861_i2c_xfer(&adap->dev->i2c_adap, &msg, 1);
-
-	kfree(buf);
-	return (ret == 70);
-}
-
-
-static int friio_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff);
-
-/* TODO: move these init cmds to the FE's init routine? */
-static u8 streaming_init_cmds[][2] = {
-	{0x33, 0x08},
-	{0x37, 0x40},
-	{0x3A, 0x1F},
-	{0x3B, 0xFF},
-	{0x3C, 0x1F},
-	{0x3D, 0xFF},
-	{0x38, 0x00},
-	{0x35, 0x00},
-	{0x39, 0x00},
-	{0x36, 0x00},
-};
-static int cmdlen = sizeof(streaming_init_cmds) / 2;
-
-/*
- * Command sequence in this init function is a replay
- *  of the captured USB commands from the Windows proprietary driver.
- */
-static int friio_initialize(struct dvb_usb_device *d)
-{
-	int ret;
-	int i;
-	int retry = 0;
-	u8 *rbuf, *wbuf;
-
-	deb_info("%s called.\n", __func__);
-
-	wbuf = kmalloc(3, GFP_KERNEL);
-	if (!wbuf)
-		return -ENOMEM;
-
-	rbuf = kmalloc(2, GFP_KERNEL);
-	if (!rbuf) {
-		kfree(wbuf);
-		return -ENOMEM;
-	}
-
-	/* use gl861_i2c_msg instead of gl861_i2c_xfer(), */
-	/* because the i2c device is not set up yet. */
-	wbuf[0] = 0x11;
-	wbuf[1] = 0x02;
-	ret = gl861_i2c_msg(d, 0x00, wbuf, 2, NULL, 0);
-	if (ret < 0)
-		goto error;
-	msleep(2);
-
-	wbuf[0] = 0x11;
-	wbuf[1] = 0x00;
-	ret = gl861_i2c_msg(d, 0x00, wbuf, 2, NULL, 0);
-	if (ret < 0)
-		goto error;
-	msleep(1);
-
-	/* following msgs should be in the FE's init code? */
-	/* cmd sequence to identify the device type? (friio black/white) */
-	wbuf[0] = 0x03;
-	wbuf[1] = 0x80;
-	/* can't use gl861_i2c_cmd, as the register-addr is 16bit(0x0100) */
-	ret = usb_control_msg(d->udev, usb_sndctrlpipe(d->udev, 0),
-			      GL861_REQ_I2C_DATA_CTRL_WRITE, GL861_WRITE,
-			      0x1200, 0x0100, wbuf, 2, 2000);
-	if (ret < 0)
-		goto error;
-
-	msleep(2);
-	wbuf[0] = 0x00;
-	wbuf[2] = 0x01;		/* reg.0x0100 */
-	wbuf[1] = 0x00;
-	ret = gl861_i2c_msg(d, 0x12 >> 1, wbuf, 3, rbuf, 2);
-	/* my Friio White returns 0xffff. */
-	if (ret < 0 || rbuf[0] != 0xff || rbuf[1] != 0xff)
-		goto error;
-
-	msleep(2);
-	wbuf[0] = 0x03;
-	wbuf[1] = 0x80;
-	ret = usb_control_msg(d->udev, usb_sndctrlpipe(d->udev, 0),
-			      GL861_REQ_I2C_DATA_CTRL_WRITE, GL861_WRITE,
-			      0x9000, 0x0100, wbuf, 2, 2000);
-	if (ret < 0)
-		goto error;
-
-	msleep(2);
-	wbuf[0] = 0x00;
-	wbuf[2] = 0x01;		/* reg.0x0100 */
-	wbuf[1] = 0x00;
-	ret = gl861_i2c_msg(d, 0x90 >> 1, wbuf, 3, rbuf, 2);
-	/* my Friio White returns 0xffff again. */
-	if (ret < 0 || rbuf[0] != 0xff || rbuf[1] != 0xff)
-		goto error;
-
-	msleep(1);
-
-restart:
-	/* ============ start DEMOD init cmds ================== */
-	/* read PLL status to clear the POR bit */
-	wbuf[0] = JDVBT90502_2ND_I2C_REG;
-	wbuf[1] = (FRIIO_PLL_ADDR << 1) + 1;	/* +1 for reading */
-	ret = gl861_i2c_msg(d, FRIIO_DEMOD_ADDR, wbuf, 2, NULL, 0);
-	if (ret < 0)
-		goto error;
-
-	msleep(5);
-	/* note: DEMODULATOR has 16bit register-address. */
-	wbuf[0] = 0x00;
-	wbuf[2] = 0x01;		/* reg addr: 0x0100 */
-	wbuf[1] = 0x00;		/* val: not used */
-	ret = gl861_i2c_msg(d, FRIIO_DEMOD_ADDR, wbuf, 3, rbuf, 1);
-	if (ret < 0)
-		goto error;
-/*
-	msleep(1);
-	wbuf[0] = 0x80;
-	wbuf[1] = 0x00;
-	ret = gl861_i2c_msg(d, FRIIO_DEMOD_ADDR, wbuf, 2, rbuf, 1);
-	if (ret < 0)
-		goto error;
- */
-	if (rbuf[0] & 0x80) {	/* still in PowerOnReset state? */
-		if (++retry > 3) {
-			deb_info("failed to get the correct"
-				 " FE demod status:0x%02x\n", rbuf[0]);
-			goto error;
-		}
-		msleep(100);
-		goto restart;
-	}
-
-	/* TODO: check return value in rbuf */
-	/* =========== end DEMOD init cmds ===================== */
-	msleep(1);
-
-	wbuf[0] = 0x30;
-	wbuf[1] = 0x04;
-	ret = gl861_i2c_msg(d, 0x00, wbuf, 2, NULL, 0);
-	if (ret < 0)
-		goto error;
-
-	msleep(2);
-	/* following 2 cmds unnecessary? */
-	wbuf[0] = 0x00;
-	wbuf[1] = 0x01;
-	ret = gl861_i2c_msg(d, 0x00, wbuf, 2, NULL, 0);
-	if (ret < 0)
-		goto error;
-
-	wbuf[0] = 0x06;
-	wbuf[1] = 0x0F;
-	ret = gl861_i2c_msg(d, 0x00, wbuf, 2, NULL, 0);
-	if (ret < 0)
-		goto error;
-
-	/* some streaming ctl cmds (maybe) */
-	msleep(10);
-	for (i = 0; i < cmdlen; i++) {
-		ret = gl861_i2c_msg(d, 0x00, streaming_init_cmds[i], 2,
-				    NULL, 0);
-		if (ret < 0)
-			goto error;
-		msleep(1);
-	}
-	msleep(20);
-
-	/* change the LED color etc. */
-	ret = friio_streaming_ctrl(&d->adapter[0], 0);
-	if (ret < 0)
-		goto error;
-
-	return 0;
-
-error:
-	kfree(wbuf);
-	kfree(rbuf);
-	deb_info("%s:ret == %d\n", __func__, ret);
-	return -EIO;
-}
-
-/* Callbacks for DVB USB */
-
-static int friio_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
-{
-	int ret;
-
-	deb_info("%s called.(%d)\n", __func__, onoff);
-
-	/* set the LED color and saturation (and LNB on) */
-	if (onoff)
-		ret = friio_ext_ctl(adap, 0x6400ff64, 1);
-	else
-		ret = friio_ext_ctl(adap, 0x96ff00ff, 1);
-
-	if (ret != 1) {
-		deb_info("%s failed to send cmdx. ret==%d\n", __func__, ret);
-		return -EREMOTEIO;
-	}
-	return 0;
-}
-
-static int friio_frontend_attach(struct dvb_usb_adapter *adap)
-{
-	if (friio_initialize(adap->dev) < 0)
-		return -EIO;
-
-	adap->fe_adap[0].fe = jdvbt90502_attach(adap->dev);
-	if (adap->fe_adap[0].fe == NULL)
-		return -EIO;
-
-	return 0;
-}
-
-/* DVB USB Driver stuff */
-static struct dvb_usb_device_properties friio_properties;
-
-static int friio_probe(struct usb_interface *intf,
-		       const struct usb_device_id *id)
-{
-	struct dvb_usb_device *d;
-	struct usb_host_interface *alt;
-	int ret;
-
-	if (intf->num_altsetting < GL861_ALTSETTING_COUNT)
-		return -ENODEV;
-
-	alt = usb_altnum_to_altsetting(intf, FRIIO_BULK_ALTSETTING);
-	if (alt == NULL) {
-		deb_rc("not alt found!\n");
-		return -ENODEV;
-	}
-	ret = usb_set_interface(interface_to_usbdev(intf),
-				alt->desc.bInterfaceNumber,
-				alt->desc.bAlternateSetting);
-	if (ret != 0) {
-		deb_rc("failed to set alt-setting!\n");
-		return ret;
-	}
-
-	ret = dvb_usb_device_init(intf, &friio_properties,
-				  THIS_MODULE, &d, adapter_nr);
-	if (ret == 0)
-		friio_streaming_ctrl(&d->adapter[0], 1);
-
-	return ret;
-}
-
-
-struct jdvbt90502_config friio_fe_config = {
-	.demod_address = FRIIO_DEMOD_ADDR,
-	.pll_address = FRIIO_PLL_ADDR,
-};
-
-static struct i2c_algorithm gl861_i2c_algo = {
-	.master_xfer   = gl861_i2c_xfer,
-	.functionality = gl861_i2c_func,
-};
-
-static struct usb_device_id friio_table[] = {
-	{ USB_DEVICE(USB_VID_774, USB_PID_FRIIO_WHITE) },
-	{ }		/* Terminating entry */
-};
-MODULE_DEVICE_TABLE(usb, friio_table);
-
-
-static struct dvb_usb_device_properties friio_properties = {
-	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
-	.usb_ctrl = DEVICE_SPECIFIC,
-
-	.size_of_priv = 0,
-
-	.num_adapters = 1,
-	.adapter = {
-		/* caps:0 =>  no pid filter, 188B TS packet */
-		/* GL861 has a HW pid filter, but no info available. */
-		{
-		.num_frontends = 1,
-		.fe = {{
-			.caps  = 0,
-
-			.frontend_attach  = friio_frontend_attach,
-			.streaming_ctrl = friio_streaming_ctrl,
-
-			.stream = {
-				.type = USB_BULK,
-				/* count <= MAX_NO_URBS_FOR_DATA_STREAM(10) */
-				.count = 8,
-				.endpoint = 0x01,
-				.u = {
-					/* GL861 has 6KB buf inside */
-					.bulk = {
-						.buffersize = 16384,
-					}
-				}
-			},
-		}},
-		}
-	},
-	.i2c_algo = &gl861_i2c_algo,
-
-	.num_device_descs = 1,
-	.devices = {
-		{
-			.name = "774 Friio ISDB-T USB2.0",
-			.cold_ids = { NULL },
-			.warm_ids = { &friio_table[0], NULL },
-		},
-	}
-};
-
-static struct usb_driver friio_driver = {
-	.name		= "dvb_usb_friio",
-	.probe		= friio_probe,
-	.disconnect	= dvb_usb_device_exit,
-	.id_table	= friio_table,
-};
-
-module_usb_driver(friio_driver);
-
-MODULE_AUTHOR("Akihiro Tsukada <tskd2@yahoo.co.jp>");
-MODULE_DESCRIPTION("Driver for Friio ISDB-T USB2.0 Receiver");
-MODULE_VERSION("0.2");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/friio.h b/drivers/media/dvb/dvb-usb/friio.h
deleted file mode 100644
index 0f461ca..0000000
--- a/drivers/media/dvb/dvb-usb/friio.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/* DVB USB compliant Linux driver for the Friio USB2.0 ISDB-T receiver.
- *
- * Copyright (C) 2009 Akihiro Tsukada <tskd2@yahoo.co.jp>
- *
- * This module is based off the the gl861 and vp702x modules.
- *
- * This program is free software; 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.
- *
- * see Documentation/dvb/README.dvb-usb for more information
- */
-#ifndef _DVB_USB_FRIIO_H_
-#define _DVB_USB_FRIIO_H_
-
-/**
- *      Friio Components
- *       USB hub:                                AU4254
- *         USB controller(+ TS dmx & streaming): GL861
- *         Frontend:                             comtech JDVBT-90502
- *             (tuner PLL:                       tua6034, I2C addr:(0xC0 >> 1))
- *             (OFDM demodulator:                TC90502, I2C addr:(0x30 >> 1))
- *         LED x3 (+LNB) control:                PIC 16F676
- *         EEPROM:                               24C08
- *
- *        (USB smart card reader:                AU9522)
- *
- */
-
-#define DVB_USB_LOG_PREFIX "friio"
-#include "dvb-usb.h"
-
-extern int dvb_usb_friio_debug;
-#define deb_info(args...) dprintk(dvb_usb_friio_debug, 0x01, args)
-#define deb_xfer(args...) dprintk(dvb_usb_friio_debug, 0x02, args)
-#define deb_rc(args...)   dprintk(dvb_usb_friio_debug, 0x04, args)
-#define deb_fe(args...)   dprintk(dvb_usb_friio_debug, 0x08, args)
-
-/* Vendor requests */
-#define GL861_WRITE		0x40
-#define GL861_READ		0xc0
-
-/* command bytes */
-#define GL861_REQ_I2C_WRITE	0x01
-#define GL861_REQ_I2C_READ	0x02
-/* For control msg with data argument */
-/* Used for accessing the PLL on the secondary I2C bus of FE via GL861 */
-#define GL861_REQ_I2C_DATA_CTRL_WRITE	0x03
-
-#define GL861_ALTSETTING_COUNT	2
-#define FRIIO_BULK_ALTSETTING	0
-#define FRIIO_ISOC_ALTSETTING	1
-
-/* LED & LNB control via PIC. */
-/* basically, it's serial control with clock and strobe. */
-/* write the below 4bit control data to the reg 0x00 at the I2C addr 0x00 */
-/* when controlling the LEDs, 32bit(saturation, R, G, B) is sent on the bit3*/
-#define FRIIO_CTL_LNB (1 << 0)
-#define FRIIO_CTL_STROBE (1 << 1)
-#define FRIIO_CTL_CLK (1 << 2)
-#define FRIIO_CTL_LED (1 << 3)
-
-/* Front End related */
-
-#define FRIIO_DEMOD_ADDR  (0x30 >> 1)
-#define FRIIO_PLL_ADDR  (0xC0 >> 1)
-
-#define JDVBT90502_PLL_CLK	4000000
-#define JDVBT90502_PLL_DIVIDER	28
-
-#define JDVBT90502_2ND_I2C_REG 0xFE
-
-/* byte index for pll i2c command data structure*/
-/* see datasheet for tua6034 */
-#define DEMOD_REDIRECT_REG 0
-#define ADDRESS_BYTE       1
-#define DIVIDER_BYTE1      2
-#define DIVIDER_BYTE2      3
-#define CONTROL_BYTE       4
-#define BANDSWITCH_BYTE    5
-#define AGC_CTRL_BYTE      5
-#define PLL_CMD_LEN        6
-
-/* bit masks for PLL STATUS response */
-#define PLL_STATUS_POR_MODE   0x80 /* 1: Power on Reset (test) Mode */
-#define PLL_STATUS_LOCKED     0x40 /* 1: locked */
-#define PLL_STATUS_AGC_ACTIVE 0x08 /* 1:active */
-#define PLL_STATUS_TESTMODE   0x07 /* digital output level (5 level) */
-  /* 0.15Vcc step   0x00: < 0.15Vcc, ..., 0x04: >= 0.6Vcc (<= 1Vcc) */
-
-
-struct jdvbt90502_config {
-	u8 demod_address; /* i2c addr for demodulator IC */
-	u8 pll_address;   /* PLL addr on the secondary i2c*/
-};
-extern struct jdvbt90502_config friio_fe_config;
-
-extern struct dvb_frontend *jdvbt90502_attach(struct dvb_usb_device *d);
-#endif
diff --git a/drivers/media/dvb/dvb-usb/gl861.c b/drivers/media/dvb/dvb-usb/gl861.c
deleted file mode 100644
index c1f5582..0000000
--- a/drivers/media/dvb/dvb-usb/gl861.c
+++ /dev/null
@@ -1,217 +0,0 @@
-/* DVB USB compliant linux driver for GL861 USB2.0 devices.
- *
- *	This program is free software; 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.
- *
- * see Documentation/dvb/README.dvb-usb for more information
- */
-#include "gl861.h"
-
-#include "zl10353.h"
-#include "qt1010.h"
-
-/* debug */
-static int dvb_usb_gl861_debug;
-module_param_named(debug, dvb_usb_gl861_debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))."
-	DVB_USB_DEBUG_STATUS);
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-static int gl861_i2c_msg(struct dvb_usb_device *d, u8 addr,
-			 u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
-{
-	u16 index;
-	u16 value = addr << (8 + 1);
-	int wo = (rbuf == NULL || rlen == 0); /* write-only */
-	u8 req, type;
-
-	if (wo) {
-		req = GL861_REQ_I2C_WRITE;
-		type = GL861_WRITE;
-	} else { /* rw */
-		req = GL861_REQ_I2C_READ;
-		type = GL861_READ;
-	}
-
-	switch (wlen) {
-	case 1:
-		index = wbuf[0];
-		break;
-	case 2:
-		index = wbuf[0];
-		value = value + wbuf[1];
-		break;
-	default:
-		warn("wlen = %x, aborting.", wlen);
-		return -EINVAL;
-	}
-
-	msleep(1); /* avoid I2C errors */
-
-	return usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), req, type,
-			       value, index, rbuf, rlen, 2000);
-}
-
-/* I2C */
-static int gl861_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
-			  int num)
-{
-	struct dvb_usb_device *d = i2c_get_adapdata(adap);
-	int i;
-
-	if (num > 2)
-		return -EINVAL;
-
-	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
-		return -EAGAIN;
-
-	for (i = 0; i < num; i++) {
-		/* write/read request */
-		if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {
-			if (gl861_i2c_msg(d, msg[i].addr, msg[i].buf,
-				msg[i].len, msg[i+1].buf, msg[i+1].len) < 0)
-				break;
-			i++;
-		} else
-			if (gl861_i2c_msg(d, msg[i].addr, msg[i].buf,
-					  msg[i].len, NULL, 0) < 0)
-				break;
-	}
-
-	mutex_unlock(&d->i2c_mutex);
-	return i;
-}
-
-static u32 gl861_i2c_func(struct i2c_adapter *adapter)
-{
-	return I2C_FUNC_I2C;
-}
-
-static struct i2c_algorithm gl861_i2c_algo = {
-	.master_xfer   = gl861_i2c_xfer,
-	.functionality = gl861_i2c_func,
-};
-
-/* Callbacks for DVB USB */
-static struct zl10353_config gl861_zl10353_config = {
-	.demod_address = 0x0f,
-	.no_tuner = 1,
-	.parallel_ts = 1,
-};
-
-static int gl861_frontend_attach(struct dvb_usb_adapter *adap)
-{
-
-	adap->fe_adap[0].fe = dvb_attach(zl10353_attach, &gl861_zl10353_config,
-		&adap->dev->i2c_adap);
-	if (adap->fe_adap[0].fe == NULL)
-		return -EIO;
-
-	return 0;
-}
-
-static struct qt1010_config gl861_qt1010_config = {
-	.i2c_address = 0x62
-};
-
-static int gl861_tuner_attach(struct dvb_usb_adapter *adap)
-{
-	return dvb_attach(qt1010_attach,
-			  adap->fe_adap[0].fe, &adap->dev->i2c_adap,
-			  &gl861_qt1010_config) == NULL ? -ENODEV : 0;
-}
-
-/* DVB USB Driver stuff */
-static struct dvb_usb_device_properties gl861_properties;
-
-static int gl861_probe(struct usb_interface *intf,
-		       const struct usb_device_id *id)
-{
-	struct dvb_usb_device *d;
-	struct usb_host_interface *alt;
-	int ret;
-
-	if (intf->num_altsetting < 2)
-		return -ENODEV;
-
-	ret = dvb_usb_device_init(intf, &gl861_properties, THIS_MODULE, &d,
-				  adapter_nr);
-	if (ret == 0) {
-		alt = usb_altnum_to_altsetting(intf, 0);
-
-		if (alt == NULL) {
-			deb_rc("not alt found!\n");
-			return -ENODEV;
-		}
-
-		ret = usb_set_interface(d->udev, alt->desc.bInterfaceNumber,
-					alt->desc.bAlternateSetting);
-	}
-
-	return ret;
-}
-
-static struct usb_device_id gl861_table [] = {
-		{ USB_DEVICE(USB_VID_MSI, USB_PID_MSI_MEGASKY580_55801) },
-		{ USB_DEVICE(USB_VID_ALINK, USB_VID_ALINK_DTU) },
-		{ }		/* Terminating entry */
-};
-MODULE_DEVICE_TABLE(usb, gl861_table);
-
-static struct dvb_usb_device_properties gl861_properties = {
-	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
-	.usb_ctrl = DEVICE_SPECIFIC,
-
-	.size_of_priv     = 0,
-
-	.num_adapters = 1,
-	.adapter = {{
-		.num_frontends = 1,
-		.fe = {{
-
-		.frontend_attach  = gl861_frontend_attach,
-		.tuner_attach     = gl861_tuner_attach,
-
-		.stream = {
-			.type = USB_BULK,
-			.count = 7,
-			.endpoint = 0x81,
-			.u = {
-				.bulk = {
-					.buffersize = 512,
-				}
-			}
-		},
-		}},
-	} },
-	.i2c_algo         = &gl861_i2c_algo,
-
-	.num_device_descs = 2,
-	.devices = {
-		{
-			.name = "MSI Mega Sky 55801 DVB-T USB2.0",
-			.cold_ids = { NULL },
-			.warm_ids = { &gl861_table[0], NULL },
-		},
-		{
-			.name = "A-LINK DTU DVB-T USB2.0",
-			.cold_ids = { NULL },
-			.warm_ids = { &gl861_table[1], NULL },
-		},
-	}
-};
-
-static struct usb_driver gl861_driver = {
-	.name		= "dvb_usb_gl861",
-	.probe		= gl861_probe,
-	.disconnect	= dvb_usb_device_exit,
-	.id_table	= gl861_table,
-};
-
-module_usb_driver(gl861_driver);
-
-MODULE_AUTHOR("Carl Lundqvist <comabug@gmail.com>");
-MODULE_DESCRIPTION("Driver MSI Mega Sky 580 DVB-T USB2.0 / GL861");
-MODULE_VERSION("0.1");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/gl861.h b/drivers/media/dvb/dvb-usb/gl861.h
deleted file mode 100644
index c54855e..0000000
--- a/drivers/media/dvb/dvb-usb/gl861.h
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifndef _DVB_USB_GL861_H_
-#define _DVB_USB_GL861_H_
-
-#define DVB_USB_LOG_PREFIX "gl861"
-#include "dvb-usb.h"
-
-#define deb_rc(args...)   dprintk(dvb_usb_gl861_debug, 0x01, args)
-
-#define GL861_WRITE		0x40
-#define GL861_READ		0xc0
-
-#define GL861_REQ_I2C_WRITE	0x01
-#define GL861_REQ_I2C_READ	0x02
-
-#endif
diff --git a/drivers/media/dvb/dvb-usb/gp8psk-fe.c b/drivers/media/dvb/dvb-usb/gp8psk-fe.c
deleted file mode 100644
index 67957dd..0000000
--- a/drivers/media/dvb/dvb-usb/gp8psk-fe.c
+++ /dev/null
@@ -1,369 +0,0 @@
-/* DVB USB compliant Linux driver for the
- *  - GENPIX 8pks/qpsk/DCII USB2.0 DVB-S module
- *
- * Copyright (C) 2006,2007 Alan Nisota (alannisota@gmail.com)
- * Copyright (C) 2006,2007 Genpix Electronics (genpix@genpix-electronics.com)
- *
- * Thanks to GENPIX for the sample code used to implement this module.
- *
- * This module is based off the vp7045 and vp702x modules
- *
- *	This program is free software; 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.
- *
- * see Documentation/dvb/README.dvb-usb for more information
- */
-#include "gp8psk.h"
-
-struct gp8psk_fe_state {
-	struct dvb_frontend fe;
-	struct dvb_usb_device *d;
-	u8 lock;
-	u16 snr;
-	unsigned long next_status_check;
-	unsigned long status_check_interval;
-};
-
-static int gp8psk_tuned_to_DCII(struct dvb_frontend *fe)
-{
-	struct gp8psk_fe_state *st = fe->demodulator_priv;
-	u8 status;
-	gp8psk_usb_in_op(st->d, GET_8PSK_CONFIG, 0, 0, &status, 1);
-	return status & bmDCtuned;
-}
-
-static int gp8psk_set_tuner_mode(struct dvb_frontend *fe, int mode)
-{
-	struct gp8psk_fe_state *state = fe->demodulator_priv;
-	return gp8psk_usb_out_op(state->d, SET_8PSK_CONFIG, mode, 0, NULL, 0);
-}
-
-static int gp8psk_fe_update_status(struct gp8psk_fe_state *st)
-{
-	u8 buf[6];
-	if (time_after(jiffies,st->next_status_check)) {
-		gp8psk_usb_in_op(st->d, GET_SIGNAL_LOCK, 0,0,&st->lock,1);
-		gp8psk_usb_in_op(st->d, GET_SIGNAL_STRENGTH, 0,0,buf,6);
-		st->snr = (buf[1]) << 8 | buf[0];
-		st->next_status_check = jiffies + (st->status_check_interval*HZ)/1000;
-	}
-	return 0;
-}
-
-static int gp8psk_fe_read_status(struct dvb_frontend* fe, fe_status_t *status)
-{
-	struct gp8psk_fe_state *st = fe->demodulator_priv;
-	gp8psk_fe_update_status(st);
-
-	if (st->lock)
-		*status = FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI | FE_HAS_SIGNAL | FE_HAS_CARRIER;
-	else
-		*status = 0;
-
-	if (*status & FE_HAS_LOCK)
-		st->status_check_interval = 1000;
-	else
-		st->status_check_interval = 100;
-	return 0;
-}
-
-/* not supported by this Frontend */
-static int gp8psk_fe_read_ber(struct dvb_frontend* fe, u32 *ber)
-{
-	(void) fe;
-	*ber = 0;
-	return 0;
-}
-
-/* not supported by this Frontend */
-static int gp8psk_fe_read_unc_blocks(struct dvb_frontend* fe, u32 *unc)
-{
-	(void) fe;
-	*unc = 0;
-	return 0;
-}
-
-static int gp8psk_fe_read_snr(struct dvb_frontend* fe, u16 *snr)
-{
-	struct gp8psk_fe_state *st = fe->demodulator_priv;
-	gp8psk_fe_update_status(st);
-	/* snr is reported in dBu*256 */
-	*snr = st->snr;
-	return 0;
-}
-
-static int gp8psk_fe_read_signal_strength(struct dvb_frontend* fe, u16 *strength)
-{
-	struct gp8psk_fe_state *st = fe->demodulator_priv;
-	gp8psk_fe_update_status(st);
-	/* snr is reported in dBu*256 */
-	/* snr / 38.4 ~= 100% strength */
-	/* snr * 17 returns 100% strength as 65535 */
-	if (st->snr > 0xf00)
-		*strength = 0xffff;
-	else
-		*strength = (st->snr << 4) + st->snr; /* snr*17 */
-	return 0;
-}
-
-static int gp8psk_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
-{
-	tune->min_delay_ms = 800;
-	return 0;
-}
-
-static int gp8psk_fe_set_frontend(struct dvb_frontend *fe)
-{
-	struct gp8psk_fe_state *state = fe->demodulator_priv;
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	u8 cmd[10];
-	u32 freq = c->frequency * 1000;
-	int gp_product_id = le16_to_cpu(state->d->udev->descriptor.idProduct);
-
-	deb_fe("%s()\n", __func__);
-
-	cmd[4] = freq         & 0xff;
-	cmd[5] = (freq >> 8)  & 0xff;
-	cmd[6] = (freq >> 16) & 0xff;
-	cmd[7] = (freq >> 24) & 0xff;
-
-	/* backwards compatibility: DVB-S + 8-PSK were used for Turbo-FEC */
-	if (c->delivery_system == SYS_DVBS && c->modulation == PSK_8)
-		c->delivery_system = SYS_TURBO;
-
-	switch (c->delivery_system) {
-	case SYS_DVBS:
-		if (c->modulation != QPSK) {
-			deb_fe("%s: unsupported modulation selected (%d)\n",
-				__func__, c->modulation);
-			return -EOPNOTSUPP;
-		}
-		c->fec_inner = FEC_AUTO;
-		break;
-	case SYS_DVBS2: /* kept for backwards compatibility */
-		deb_fe("%s: DVB-S2 delivery system selected\n", __func__);
-		break;
-	case SYS_TURBO:
-		deb_fe("%s: Turbo-FEC delivery system selected\n", __func__);
-		break;
-
-	default:
-		deb_fe("%s: unsupported delivery system selected (%d)\n",
-			__func__, c->delivery_system);
-		return -EOPNOTSUPP;
-	}
-
-	cmd[0] =  c->symbol_rate        & 0xff;
-	cmd[1] = (c->symbol_rate >>  8) & 0xff;
-	cmd[2] = (c->symbol_rate >> 16) & 0xff;
-	cmd[3] = (c->symbol_rate >> 24) & 0xff;
-	switch (c->modulation) {
-	case QPSK:
-		if (gp_product_id == USB_PID_GENPIX_8PSK_REV_1_WARM)
-			if (gp8psk_tuned_to_DCII(fe))
-				gp8psk_bcm4500_reload(state->d);
-		switch (c->fec_inner) {
-		case FEC_1_2:
-			cmd[9] = 0; break;
-		case FEC_2_3:
-			cmd[9] = 1; break;
-		case FEC_3_4:
-			cmd[9] = 2; break;
-		case FEC_5_6:
-			cmd[9] = 3; break;
-		case FEC_7_8:
-			cmd[9] = 4; break;
-		case FEC_AUTO:
-			cmd[9] = 5; break;
-		default:
-			cmd[9] = 5; break;
-		}
-		if (c->delivery_system == SYS_TURBO)
-			cmd[8] = ADV_MOD_TURBO_QPSK;
-		else
-			cmd[8] = ADV_MOD_DVB_QPSK;
-		break;
-	case PSK_8: /* PSK_8 is for compatibility with DN */
-		cmd[8] = ADV_MOD_TURBO_8PSK;
-		switch (c->fec_inner) {
-		case FEC_2_3:
-			cmd[9] = 0; break;
-		case FEC_3_4:
-			cmd[9] = 1; break;
-		case FEC_3_5:
-			cmd[9] = 2; break;
-		case FEC_5_6:
-			cmd[9] = 3; break;
-		case FEC_8_9:
-			cmd[9] = 4; break;
-		default:
-			cmd[9] = 0; break;
-		}
-		break;
-	case QAM_16: /* QAM_16 is for compatibility with DN */
-		cmd[8] = ADV_MOD_TURBO_16QAM;
-		cmd[9] = 0;
-		break;
-	default: /* Unknown modulation */
-		deb_fe("%s: unsupported modulation selected (%d)\n",
-			__func__, c->modulation);
-		return -EOPNOTSUPP;
-	}
-
-	if (gp_product_id == USB_PID_GENPIX_8PSK_REV_1_WARM)
-		gp8psk_set_tuner_mode(fe, 0);
-	gp8psk_usb_out_op(state->d, TUNE_8PSK, 0, 0, cmd, 10);
-
-	state->lock = 0;
-	state->next_status_check = jiffies;
-	state->status_check_interval = 200;
-
-	return 0;
-}
-
-static int gp8psk_fe_send_diseqc_msg (struct dvb_frontend* fe,
-				    struct dvb_diseqc_master_cmd *m)
-{
-	struct gp8psk_fe_state *st = fe->demodulator_priv;
-
-	deb_fe("%s\n",__func__);
-
-	if (gp8psk_usb_out_op(st->d,SEND_DISEQC_COMMAND, m->msg[0], 0,
-			m->msg, m->msg_len)) {
-		return -EINVAL;
-	}
-	return 0;
-}
-
-static int gp8psk_fe_send_diseqc_burst (struct dvb_frontend* fe,
-				    fe_sec_mini_cmd_t burst)
-{
-	struct gp8psk_fe_state *st = fe->demodulator_priv;
-	u8 cmd;
-
-	deb_fe("%s\n",__func__);
-
-	/* These commands are certainly wrong */
-	cmd = (burst == SEC_MINI_A) ? 0x00 : 0x01;
-
-	if (gp8psk_usb_out_op(st->d,SEND_DISEQC_COMMAND, cmd, 0,
-			&cmd, 0)) {
-		return -EINVAL;
-	}
-	return 0;
-}
-
-static int gp8psk_fe_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
-{
-	struct gp8psk_fe_state* state = fe->demodulator_priv;
-
-	if (gp8psk_usb_out_op(state->d,SET_22KHZ_TONE,
-		 (tone == SEC_TONE_ON), 0, NULL, 0)) {
-		return -EINVAL;
-	}
-	return 0;
-}
-
-static int gp8psk_fe_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltage)
-{
-	struct gp8psk_fe_state* state = fe->demodulator_priv;
-
-	if (gp8psk_usb_out_op(state->d,SET_LNB_VOLTAGE,
-			 voltage == SEC_VOLTAGE_18, 0, NULL, 0)) {
-		return -EINVAL;
-	}
-	return 0;
-}
-
-static int gp8psk_fe_enable_high_lnb_voltage(struct dvb_frontend* fe, long onoff)
-{
-	struct gp8psk_fe_state* state = fe->demodulator_priv;
-	return gp8psk_usb_out_op(state->d, USE_EXTRA_VOLT, onoff, 0,NULL,0);
-}
-
-static int gp8psk_fe_send_legacy_dish_cmd (struct dvb_frontend* fe, unsigned long sw_cmd)
-{
-	struct gp8psk_fe_state* state = fe->demodulator_priv;
-	u8 cmd = sw_cmd & 0x7f;
-
-	if (gp8psk_usb_out_op(state->d,SET_DN_SWITCH, cmd, 0,
-			NULL, 0)) {
-		return -EINVAL;
-	}
-	if (gp8psk_usb_out_op(state->d,SET_LNB_VOLTAGE, !!(sw_cmd & 0x80),
-			0, NULL, 0)) {
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static void gp8psk_fe_release(struct dvb_frontend* fe)
-{
-	struct gp8psk_fe_state *state = fe->demodulator_priv;
-	kfree(state);
-}
-
-static struct dvb_frontend_ops gp8psk_fe_ops;
-
-struct dvb_frontend * gp8psk_fe_attach(struct dvb_usb_device *d)
-{
-	struct gp8psk_fe_state *s = kzalloc(sizeof(struct gp8psk_fe_state), GFP_KERNEL);
-	if (s == NULL)
-		goto error;
-
-	s->d = d;
-	memcpy(&s->fe.ops, &gp8psk_fe_ops, sizeof(struct dvb_frontend_ops));
-	s->fe.demodulator_priv = s;
-
-	goto success;
-error:
-	return NULL;
-success:
-	return &s->fe;
-}
-
-
-static struct dvb_frontend_ops gp8psk_fe_ops = {
-	.delsys = { SYS_DVBS },
-	.info = {
-		.name			= "Genpix DVB-S",
-		.frequency_min		= 800000,
-		.frequency_max		= 2250000,
-		.frequency_stepsize	= 100,
-		.symbol_rate_min        = 1000000,
-		.symbol_rate_max        = 45000000,
-		.symbol_rate_tolerance  = 500,  /* ppm */
-		.caps = FE_CAN_INVERSION_AUTO |
-			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_FEC_AUTO |
-			/*
-			 * FE_CAN_QAM_16 is for compatibility
-			 * (Myth incorrectly detects Turbo-QPSK as plain QAM-16)
-			 */
-			FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_TURBO_FEC
-	},
-
-	.release = gp8psk_fe_release,
-
-	.init = NULL,
-	.sleep = NULL,
-
-	.set_frontend = gp8psk_fe_set_frontend,
-
-	.get_tune_settings = gp8psk_fe_get_tune_settings,
-
-	.read_status = gp8psk_fe_read_status,
-	.read_ber = gp8psk_fe_read_ber,
-	.read_signal_strength = gp8psk_fe_read_signal_strength,
-	.read_snr = gp8psk_fe_read_snr,
-	.read_ucblocks = gp8psk_fe_read_unc_blocks,
-
-	.diseqc_send_master_cmd = gp8psk_fe_send_diseqc_msg,
-	.diseqc_send_burst = gp8psk_fe_send_diseqc_burst,
-	.set_tone = gp8psk_fe_set_tone,
-	.set_voltage = gp8psk_fe_set_voltage,
-	.dishnetwork_send_legacy_command = gp8psk_fe_send_legacy_dish_cmd,
-	.enable_high_lnb_voltage = gp8psk_fe_enable_high_lnb_voltage
-};
diff --git a/drivers/media/dvb/dvb-usb/gp8psk.c b/drivers/media/dvb/dvb-usb/gp8psk.c
deleted file mode 100644
index 5d0384d..0000000
--- a/drivers/media/dvb/dvb-usb/gp8psk.c
+++ /dev/null
@@ -1,328 +0,0 @@
-/* DVB USB compliant Linux driver for the
- *  - GENPIX 8pks/qpsk/DCII USB2.0 DVB-S module
- *
- * Copyright (C) 2006,2007 Alan Nisota (alannisota@gmail.com)
- * Copyright (C) 2006,2007 Genpix Electronics (genpix@genpix-electronics.com)
- *
- * Thanks to GENPIX for the sample code used to implement this module.
- *
- * This module is based off the vp7045 and vp702x modules
- *
- *	This program is free software; 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.
- *
- * see Documentation/dvb/README.dvb-usb for more information
- */
-#include "gp8psk.h"
-
-/* debug */
-static char bcm4500_firmware[] = "dvb-usb-gp8psk-02.fw";
-int dvb_usb_gp8psk_debug;
-module_param_named(debug,dvb_usb_gp8psk_debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS);
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-static int gp8psk_get_fw_version(struct dvb_usb_device *d, u8 *fw_vers)
-{
-	return (gp8psk_usb_in_op(d, GET_FW_VERS, 0, 0, fw_vers, 6));
-}
-
-static int gp8psk_get_fpga_version(struct dvb_usb_device *d, u8 *fpga_vers)
-{
-	return (gp8psk_usb_in_op(d, GET_FPGA_VERS, 0, 0, fpga_vers, 1));
-}
-
-static void gp8psk_info(struct dvb_usb_device *d)
-{
-	u8 fpga_vers, fw_vers[6];
-
-	if (!gp8psk_get_fw_version(d, fw_vers))
-		info("FW Version = %i.%02i.%i (0x%x)  Build %4i/%02i/%02i",
-		fw_vers[2], fw_vers[1], fw_vers[0], GP8PSK_FW_VERS(fw_vers),
-		2000 + fw_vers[5], fw_vers[4], fw_vers[3]);
-	else
-		info("failed to get FW version");
-
-	if (!gp8psk_get_fpga_version(d, &fpga_vers))
-		info("FPGA Version = %i", fpga_vers);
-	else
-		info("failed to get FPGA version");
-}
-
-int gp8psk_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen)
-{
-	int ret = 0,try = 0;
-
-	if ((ret = mutex_lock_interruptible(&d->usb_mutex)))
-		return ret;
-
-	while (ret >= 0 && ret != blen && try < 3) {
-		ret = usb_control_msg(d->udev,
-			usb_rcvctrlpipe(d->udev,0),
-			req,
-			USB_TYPE_VENDOR | USB_DIR_IN,
-			value,index,b,blen,
-			2000);
-		deb_info("reading number %d (ret: %d)\n",try,ret);
-		try++;
-	}
-
-	if (ret < 0 || ret != blen) {
-		warn("usb in %d operation failed.", req);
-		ret = -EIO;
-	} else
-		ret = 0;
-
-	deb_xfer("in: req. %x, val: %x, ind: %x, buffer: ",req,value,index);
-	debug_dump(b,blen,deb_xfer);
-
-	mutex_unlock(&d->usb_mutex);
-
-	return ret;
-}
-
-int gp8psk_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value,
-			     u16 index, u8 *b, int blen)
-{
-	int ret;
-
-	deb_xfer("out: req. %x, val: %x, ind: %x, buffer: ",req,value,index);
-	debug_dump(b,blen,deb_xfer);
-
-	if ((ret = mutex_lock_interruptible(&d->usb_mutex)))
-		return ret;
-
-	if (usb_control_msg(d->udev,
-			usb_sndctrlpipe(d->udev,0),
-			req,
-			USB_TYPE_VENDOR | USB_DIR_OUT,
-			value,index,b,blen,
-			2000) != blen) {
-		warn("usb out operation failed.");
-		ret = -EIO;
-	} else
-		ret = 0;
-	mutex_unlock(&d->usb_mutex);
-
-	return ret;
-}
-
-static int gp8psk_load_bcm4500fw(struct dvb_usb_device *d)
-{
-	int ret;
-	const struct firmware *fw = NULL;
-	const u8 *ptr;
-	u8 *buf;
-	if ((ret = request_firmware(&fw, bcm4500_firmware,
-					&d->udev->dev)) != 0) {
-		err("did not find the bcm4500 firmware file. (%s) "
-			"Please see linux/Documentation/dvb/ for more details on firmware-problems. (%d)",
-			bcm4500_firmware,ret);
-		return ret;
-	}
-
-	ret = -EINVAL;
-
-	if (gp8psk_usb_out_op(d, LOAD_BCM4500,1,0,NULL, 0))
-		goto out_rel_fw;
-
-	info("downloading bcm4500 firmware from file '%s'",bcm4500_firmware);
-
-	ptr = fw->data;
-	buf = kmalloc(64, GFP_KERNEL | GFP_DMA);
-	if (!buf) {
-		ret = -ENOMEM;
-		goto out_rel_fw;
-	}
-
-	while (ptr[0] != 0xff) {
-		u16 buflen = ptr[0] + 4;
-		if (ptr + buflen >= fw->data + fw->size) {
-			err("failed to load bcm4500 firmware.");
-			goto out_free;
-		}
-		memcpy(buf, ptr, buflen);
-		if (dvb_usb_generic_write(d, buf, buflen)) {
-			err("failed to load bcm4500 firmware.");
-			goto out_free;
-		}
-		ptr += buflen;
-	}
-
-	ret = 0;
-
-out_free:
-	kfree(buf);
-out_rel_fw:
-	release_firmware(fw);
-
-	return ret;
-}
-
-static int gp8psk_power_ctrl(struct dvb_usb_device *d, int onoff)
-{
-	u8 status, buf;
-	int gp_product_id = le16_to_cpu(d->udev->descriptor.idProduct);
-
-	if (onoff) {
-		gp8psk_usb_in_op(d, GET_8PSK_CONFIG,0,0,&status,1);
-		if (! (status & bm8pskStarted)) {  /* started */
-			if(gp_product_id == USB_PID_GENPIX_SKYWALKER_CW3K)
-				gp8psk_usb_out_op(d, CW3K_INIT, 1, 0, NULL, 0);
-			if (gp8psk_usb_in_op(d, BOOT_8PSK, 1, 0, &buf, 1))
-				return -EINVAL;
-			gp8psk_info(d);
-		}
-
-		if (gp_product_id == USB_PID_GENPIX_8PSK_REV_1_WARM)
-			if (! (status & bm8pskFW_Loaded)) /* BCM4500 firmware loaded */
-				if(gp8psk_load_bcm4500fw(d))
-					return -EINVAL;
-
-		if (! (status & bmIntersilOn)) /* LNB Power */
-			if (gp8psk_usb_in_op(d, START_INTERSIL, 1, 0,
-					&buf, 1))
-				return -EINVAL;
-
-		/* Set DVB mode to 1 */
-		if (gp_product_id == USB_PID_GENPIX_8PSK_REV_1_WARM)
-			if (gp8psk_usb_out_op(d, SET_DVB_MODE, 1, 0, NULL, 0))
-				return -EINVAL;
-		/* Abort possible TS (if previous tune crashed) */
-		if (gp8psk_usb_out_op(d, ARM_TRANSFER, 0, 0, NULL, 0))
-			return -EINVAL;
-	} else {
-		/* Turn off LNB power */
-		if (gp8psk_usb_in_op(d, START_INTERSIL, 0, 0, &buf, 1))
-			return -EINVAL;
-		/* Turn off 8psk power */
-		if (gp8psk_usb_in_op(d, BOOT_8PSK, 0, 0, &buf, 1))
-			return -EINVAL;
-		if(gp_product_id == USB_PID_GENPIX_SKYWALKER_CW3K)
-			gp8psk_usb_out_op(d, CW3K_INIT, 0, 0, NULL, 0);
-	}
-	return 0;
-}
-
-int gp8psk_bcm4500_reload(struct dvb_usb_device *d)
-{
-	u8 buf;
-	int gp_product_id = le16_to_cpu(d->udev->descriptor.idProduct);
-	/* Turn off 8psk power */
-	if (gp8psk_usb_in_op(d, BOOT_8PSK, 0, 0, &buf, 1))
-		return -EINVAL;
-	/* Turn On 8psk power */
-	if (gp8psk_usb_in_op(d, BOOT_8PSK, 1, 0, &buf, 1))
-		return -EINVAL;
-	/* load BCM4500 firmware */
-	if (gp_product_id == USB_PID_GENPIX_8PSK_REV_1_WARM)
-		if (gp8psk_load_bcm4500fw(d))
-			return -EINVAL;
-	return 0;
-}
-
-static int gp8psk_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
-{
-	return gp8psk_usb_out_op(adap->dev, ARM_TRANSFER, onoff, 0 , NULL, 0);
-}
-
-static int gp8psk_frontend_attach(struct dvb_usb_adapter *adap)
-{
-	adap->fe_adap[0].fe = gp8psk_fe_attach(adap->dev);
-	return 0;
-}
-
-static struct dvb_usb_device_properties gp8psk_properties;
-
-static int gp8psk_usb_probe(struct usb_interface *intf,
-		const struct usb_device_id *id)
-{
-	int ret;
-	struct usb_device *udev = interface_to_usbdev(intf);
-	ret = dvb_usb_device_init(intf, &gp8psk_properties,
-				  THIS_MODULE, NULL, adapter_nr);
-	if (ret == 0) {
-		info("found Genpix USB device pID = %x (hex)",
-			le16_to_cpu(udev->descriptor.idProduct));
-	}
-	return ret;
-}
-
-static struct usb_device_id gp8psk_usb_table [] = {
-	    { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_8PSK_REV_1_COLD) },
-	    { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_8PSK_REV_1_WARM) },
-	    { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_8PSK_REV_2) },
-	    { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_SKYWALKER_1) },
-	    { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_SKYWALKER_2) },
-/*	    { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_SKYWALKER_CW3K) }, */
-	    { 0 },
-};
-MODULE_DEVICE_TABLE(usb, gp8psk_usb_table);
-
-static struct dvb_usb_device_properties gp8psk_properties = {
-	.usb_ctrl = CYPRESS_FX2,
-	.firmware = "dvb-usb-gp8psk-01.fw",
-
-	.num_adapters = 1,
-	.adapter = {
-		{
-		.num_frontends = 1,
-		.fe = {{
-			.streaming_ctrl   = gp8psk_streaming_ctrl,
-			.frontend_attach  = gp8psk_frontend_attach,
-			/* parameter for the MPEG2-data transfer */
-			.stream = {
-				.type = USB_BULK,
-				.count = 7,
-				.endpoint = 0x82,
-				.u = {
-					.bulk = {
-						.buffersize = 8192,
-					}
-				}
-			},
-		}},
-		}
-	},
-	.power_ctrl       = gp8psk_power_ctrl,
-
-	.generic_bulk_ctrl_endpoint = 0x01,
-
-	.num_device_descs = 4,
-	.devices = {
-		{ .name = "Genpix 8PSK-to-USB2 Rev.1 DVB-S receiver",
-		  .cold_ids = { &gp8psk_usb_table[0], NULL },
-		  .warm_ids = { &gp8psk_usb_table[1], NULL },
-		},
-		{ .name = "Genpix 8PSK-to-USB2 Rev.2 DVB-S receiver",
-		  .cold_ids = { NULL },
-		  .warm_ids = { &gp8psk_usb_table[2], NULL },
-		},
-		{ .name = "Genpix SkyWalker-1 DVB-S receiver",
-		  .cold_ids = { NULL },
-		  .warm_ids = { &gp8psk_usb_table[3], NULL },
-		},
-		{ .name = "Genpix SkyWalker-2 DVB-S receiver",
-		  .cold_ids = { NULL },
-		  .warm_ids = { &gp8psk_usb_table[4], NULL },
-		},
-		{ NULL },
-	}
-};
-
-/* usb specific object needed to register this driver with the usb subsystem */
-static struct usb_driver gp8psk_usb_driver = {
-	.name		= "dvb_usb_gp8psk",
-	.probe		= gp8psk_usb_probe,
-	.disconnect = dvb_usb_device_exit,
-	.id_table	= gp8psk_usb_table,
-};
-
-module_usb_driver(gp8psk_usb_driver);
-
-MODULE_AUTHOR("Alan Nisota <alannisota@gamil.com>");
-MODULE_DESCRIPTION("Driver for Genpix DVB-S");
-MODULE_VERSION("1.1");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/gp8psk.h b/drivers/media/dvb/dvb-usb/gp8psk.h
deleted file mode 100644
index ed32b9d..0000000
--- a/drivers/media/dvb/dvb-usb/gp8psk.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/* DVB USB compliant Linux driver for the
- *  - GENPIX 8pks/qpsk/DCII USB2.0 DVB-S module
- *
- * Copyright (C) 2006 Alan Nisota (alannisota@gmail.com)
- * Copyright (C) 2006,2007 Alan Nisota (alannisota@gmail.com)
- *
- * Thanks to GENPIX for the sample code used to implement this module.
- *
- * This module is based off the vp7045 and vp702x modules
- *
- *	This program is free software; 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.
- *
- * see Documentation/dvb/README.dvb-usb for more information
- */
-#ifndef _DVB_USB_GP8PSK_H_
-#define _DVB_USB_GP8PSK_H_
-
-#define DVB_USB_LOG_PREFIX "gp8psk"
-#include "dvb-usb.h"
-
-extern int dvb_usb_gp8psk_debug;
-#define deb_info(args...) dprintk(dvb_usb_gp8psk_debug,0x01,args)
-#define deb_xfer(args...) dprintk(dvb_usb_gp8psk_debug,0x02,args)
-#define deb_rc(args...)   dprintk(dvb_usb_gp8psk_debug,0x04,args)
-#define deb_fe(args...)   dprintk(dvb_usb_gp8psk_debug,0x08,args)
-
-/* Twinhan Vendor requests */
-#define TH_COMMAND_IN                     0xC0
-#define TH_COMMAND_OUT                    0xC1
-
-/* gp8psk commands */
-
-#define GET_8PSK_CONFIG                 0x80    /* in */
-#define SET_8PSK_CONFIG                 0x81
-#define I2C_WRITE			0x83
-#define I2C_READ			0x84
-#define ARM_TRANSFER                    0x85
-#define TUNE_8PSK                       0x86
-#define GET_SIGNAL_STRENGTH             0x87    /* in */
-#define LOAD_BCM4500                    0x88
-#define BOOT_8PSK                       0x89    /* in */
-#define START_INTERSIL                  0x8A    /* in */
-#define SET_LNB_VOLTAGE                 0x8B
-#define SET_22KHZ_TONE                  0x8C
-#define SEND_DISEQC_COMMAND             0x8D
-#define SET_DVB_MODE                    0x8E
-#define SET_DN_SWITCH                   0x8F
-#define GET_SIGNAL_LOCK                 0x90    /* in */
-#define GET_FW_VERS			0x92
-#define GET_SERIAL_NUMBER               0x93    /* in */
-#define USE_EXTRA_VOLT                  0x94
-#define GET_FPGA_VERS			0x95
-#define CW3K_INIT			0x9d
-
-/* PSK_configuration bits */
-#define bm8pskStarted                   0x01
-#define bm8pskFW_Loaded                 0x02
-#define bmIntersilOn                    0x04
-#define bmDVBmode                       0x08
-#define bm22kHz                         0x10
-#define bmSEL18V                        0x20
-#define bmDCtuned                       0x40
-#define bmArmed                         0x80
-
-/* Satellite modulation modes */
-#define ADV_MOD_DVB_QPSK 0     /* DVB-S QPSK */
-#define ADV_MOD_TURBO_QPSK 1   /* Turbo QPSK */
-#define ADV_MOD_TURBO_8PSK 2   /* Turbo 8PSK (also used for Trellis 8PSK) */
-#define ADV_MOD_TURBO_16QAM 3  /* Turbo 16QAM (also used for Trellis 8PSK) */
-
-#define ADV_MOD_DCII_C_QPSK 4  /* Digicipher II Combo */
-#define ADV_MOD_DCII_I_QPSK 5  /* Digicipher II I-stream */
-#define ADV_MOD_DCII_Q_QPSK 6  /* Digicipher II Q-stream */
-#define ADV_MOD_DCII_C_OQPSK 7 /* Digicipher II offset QPSK */
-#define ADV_MOD_DSS_QPSK 8     /* DSS (DIRECTV) QPSK */
-#define ADV_MOD_DVB_BPSK 9     /* DVB-S BPSK */
-
-#define GET_USB_SPEED                     0x07
-
-#define RESET_FX2                         0x13
-
-#define FW_VERSION_READ                   0x0B
-#define VENDOR_STRING_READ                0x0C
-#define PRODUCT_STRING_READ               0x0D
-#define FW_BCD_VERSION_READ               0x14
-
-/* firmware revision id's */
-#define GP8PSK_FW_REV1			0x020604
-#define GP8PSK_FW_REV2			0x020704
-#define GP8PSK_FW_VERS(_fw_vers)	((_fw_vers)[2]<<0x10 | (_fw_vers)[1]<<0x08 | (_fw_vers)[0])
-
-extern struct dvb_frontend * gp8psk_fe_attach(struct dvb_usb_device *d);
-extern int gp8psk_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen);
-extern int gp8psk_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value,
-			     u16 index, u8 *b, int blen);
-extern int gp8psk_bcm4500_reload(struct dvb_usb_device *d);
-
-#endif
diff --git a/drivers/media/dvb/dvb-usb/it913x.c b/drivers/media/dvb/dvb-usb/it913x.c
deleted file mode 100644
index 6244fe9..0000000
--- a/drivers/media/dvb/dvb-usb/it913x.c
+++ /dev/null
@@ -1,931 +0,0 @@
-/* DVB USB compliant linux driver for IT9137
- *
- * Copyright (C) 2011 Malcolm Priestley (tvboxspy@gmail.com)
- * IT9137 (C) ITE Tech Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License Version 2, as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *
- * see Documentation/dvb/README.dvb-usb for more information
- * see Documentation/dvb/it9137.txt for firmware information
- *
- */
-#define DVB_USB_LOG_PREFIX "it913x"
-
-#include <linux/usb.h>
-#include <linux/usb/input.h>
-#include <media/rc-core.h>
-
-#include "dvb-usb.h"
-#include "it913x-fe.h"
-
-/* debug */
-static int dvb_usb_it913x_debug;
-#define l_dprintk(var, level, args...) do { \
-	if ((var >= level)) \
-		printk(KERN_DEBUG DVB_USB_LOG_PREFIX ": " args); \
-} while (0)
-
-#define deb_info(level, args...) l_dprintk(dvb_usb_it913x_debug, level, args)
-#define debug_data_snipet(level, name, p) \
-	 deb_info(level, name" (%02x%02x%02x%02x%02x%02x%02x%02x)", \
-		*p, *(p+1), *(p+2), *(p+3), *(p+4), \
-			*(p+5), *(p+6), *(p+7));
-
-
-module_param_named(debug, dvb_usb_it913x_debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able))."
-			DVB_USB_DEBUG_STATUS);
-
-static int pid_filter;
-module_param_named(pid, pid_filter, int, 0644);
-MODULE_PARM_DESC(pid, "set default 0=on 1=off");
-
-static int dvb_usb_it913x_firmware;
-module_param_named(firmware, dvb_usb_it913x_firmware, int, 0644);
-MODULE_PARM_DESC(firmware, "set firmware 0=auto 1=IT9137 2=IT9135V1");
-
-
-int cmd_counter;
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-struct it913x_state {
-	u8 id;
-	struct ite_config it913x_config;
-	u8 pid_filter_onoff;
-};
-
-struct ite_config it913x_config;
-
-#define IT913X_RETRY	10
-#define IT913X_SND_TIMEOUT	100
-#define IT913X_RCV_TIMEOUT	200
-
-static int it913x_bulk_write(struct usb_device *dev,
-				u8 *snd, int len, u8 pipe)
-{
-	int ret, actual_l, i;
-
-	for (i = 0; i < IT913X_RETRY; i++) {
-		ret = usb_bulk_msg(dev, usb_sndbulkpipe(dev, pipe),
-				snd, len , &actual_l, IT913X_SND_TIMEOUT);
-		if (ret != -EBUSY && ret != -ETIMEDOUT)
-			break;
-	}
-
-	if (len != actual_l && ret == 0)
-		ret = -EAGAIN;
-
-	return ret;
-}
-
-static int it913x_bulk_read(struct usb_device *dev,
-				u8 *rev, int len, u8 pipe)
-{
-	int ret, actual_l, i;
-
-	for (i = 0; i < IT913X_RETRY; i++) {
-		ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, pipe),
-				 rev, len , &actual_l, IT913X_RCV_TIMEOUT);
-		if (ret != -EBUSY && ret != -ETIMEDOUT)
-			break;
-	}
-
-	if (len != actual_l && ret == 0)
-		ret = -EAGAIN;
-
-	return ret;
-}
-
-static u16 check_sum(u8 *p, u8 len)
-{
-	u16 sum = 0;
-	u8 i = 1;
-	while (i < len)
-		sum += (i++ & 1) ? (*p++) << 8 : *p++;
-	return ~sum;
-}
-
-static int it913x_usb_talk(struct usb_device *udev, u8 mode, u8 pro,
-			u8 cmd, u32 reg, u8 addr, u8 *data, u8 len)
-{
-	int ret = 0, i, buf_size = 1;
-	u8 *buff;
-	u8 rlen;
-	u16 chk_sum;
-
-	buff = kzalloc(256, GFP_KERNEL);
-	if (!buff) {
-		info("USB Buffer Failed");
-		return -ENOMEM;
-	}
-
-	buff[buf_size++] = pro;
-	buff[buf_size++] = cmd;
-	buff[buf_size++] = cmd_counter;
-
-	switch (mode) {
-	case READ_LONG:
-	case WRITE_LONG:
-		buff[buf_size++] = len;
-		buff[buf_size++] = 2;
-		buff[buf_size++] = (reg >> 24);
-		buff[buf_size++] = (reg >> 16) & 0xff;
-		buff[buf_size++] = (reg >> 8) & 0xff;
-		buff[buf_size++] = reg & 0xff;
-	break;
-	case READ_SHORT:
-		buff[buf_size++] = addr;
-		break;
-	case WRITE_SHORT:
-		buff[buf_size++] = len;
-		buff[buf_size++] = addr;
-		buff[buf_size++] = (reg >> 8) & 0xff;
-		buff[buf_size++] = reg & 0xff;
-	break;
-	case READ_DATA:
-	case WRITE_DATA:
-		break;
-	case WRITE_CMD:
-		mode = 7;
-		break;
-	default:
-		kfree(buff);
-		return -EINVAL;
-	}
-
-	if (mode & 1) {
-		for (i = 0; i < len ; i++)
-			buff[buf_size++] = data[i];
-	}
-	chk_sum = check_sum(&buff[1], buf_size);
-
-	buff[buf_size++] = chk_sum >> 8;
-	buff[0] = buf_size;
-	buff[buf_size++] = (chk_sum & 0xff);
-
-	ret = it913x_bulk_write(udev, buff, buf_size , 0x02);
-	if (ret < 0)
-		goto error;
-
-	ret = it913x_bulk_read(udev, buff, (mode & 1) ?
-			5 : len + 5 , 0x01);
-	if (ret < 0)
-		goto error;
-
-	rlen = (mode & 0x1) ? 0x1 : len;
-
-	if (mode & 1)
-		ret = buff[2];
-	else
-		memcpy(data, &buff[3], rlen);
-
-	cmd_counter++;
-
-error:	kfree(buff);
-
-	return ret;
-}
-
-static int it913x_io(struct usb_device *udev, u8 mode, u8 pro,
-			u8 cmd, u32 reg, u8 addr, u8 *data, u8 len)
-{
-	int ret, i;
-
-	for (i = 0; i < IT913X_RETRY; i++) {
-		ret = it913x_usb_talk(udev, mode, pro,
-			cmd, reg, addr, data, len);
-		if (ret != -EAGAIN)
-			break;
-	}
-
-	return ret;
-}
-
-static int it913x_wr_reg(struct usb_device *udev, u8 pro, u32 reg , u8 data)
-{
-	int ret;
-	u8 b[1];
-	b[0] = data;
-	ret = it913x_io(udev, WRITE_LONG, pro,
-			CMD_DEMOD_WRITE, reg, 0, b, sizeof(b));
-
-	return ret;
-}
-
-static int it913x_read_reg(struct usb_device *udev, u32 reg)
-{
-	int ret;
-	u8 data[1];
-
-	ret = it913x_io(udev, READ_LONG, DEV_0,
-			CMD_DEMOD_READ, reg, 0, &data[0], 1);
-
-	return (ret < 0) ? ret : data[0];
-}
-
-static u32 it913x_query(struct usb_device *udev, u8 pro)
-{
-	int ret, i;
-	u8 data[4];
-	u8 ver;
-
-	for (i = 0; i < 5; i++) {
-		ret = it913x_io(udev, READ_LONG, pro, CMD_DEMOD_READ,
-			0x1222, 0, &data[0], 3);
-		ver = data[0];
-		if (ver > 0 && ver < 3)
-			break;
-		msleep(100);
-	}
-
-	if (ver < 1 || ver > 2) {
-		info("Failed to identify chip version applying 1");
-		it913x_config.chip_ver = 0x1;
-		it913x_config.chip_type = 0x9135;
-		return 0;
-	}
-
-	it913x_config.chip_ver = ver;
-	it913x_config.chip_type = (u16)(data[2] << 8) + data[1];
-
-	info("Chip Version=%02x Chip Type=%04x", it913x_config.chip_ver,
-		it913x_config.chip_type);
-
-	ret |= it913x_io(udev, READ_SHORT, pro,
-			CMD_QUERYINFO, 0, 0x1, &data[0], 4);
-
-	it913x_config.firmware = (data[0] << 24) + (data[1] << 16) +
-			(data[2] << 8) + data[3];
-
-	return (ret < 0) ? 0 : it913x_config.firmware;
-}
-
-static int it913x_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff)
-{
-	struct it913x_state *st = adap->dev->priv;
-	struct usb_device *udev = adap->dev->udev;
-	int ret;
-	u8 pro = (adap->id == 0) ? DEV_0_DMOD : DEV_1_DMOD;
-
-	mutex_lock(&adap->dev->i2c_mutex);
-
-	deb_info(1, "PID_C  (%02x)", onoff);
-
-	ret = it913x_wr_reg(udev, pro, PID_EN, st->pid_filter_onoff);
-
-	mutex_unlock(&adap->dev->i2c_mutex);
-	return ret;
-}
-
-static int it913x_pid_filter(struct dvb_usb_adapter *adap,
-		int index, u16 pid, int onoff)
-{
-	struct it913x_state *st = adap->dev->priv;
-	struct usb_device *udev = adap->dev->udev;
-	int ret;
-	u8 pro = (adap->id == 0) ? DEV_0_DMOD : DEV_1_DMOD;
-
-	mutex_lock(&adap->dev->i2c_mutex);
-
-	deb_info(1, "PID_F  (%02x)", onoff);
-
-	ret = it913x_wr_reg(udev, pro, PID_LSB, (u8)(pid & 0xff));
-
-	ret |= it913x_wr_reg(udev, pro, PID_MSB, (u8)(pid >> 8));
-
-	ret |= it913x_wr_reg(udev, pro, PID_INX_EN, (u8)onoff);
-
-	ret |= it913x_wr_reg(udev, pro, PID_INX, (u8)(index & 0x1f));
-
-	if (udev->speed == USB_SPEED_HIGH && pid == 0x2000) {
-			ret |= it913x_wr_reg(udev, pro, PID_EN, !onoff);
-			st->pid_filter_onoff = !onoff;
-	} else
-		st->pid_filter_onoff =
-			adap->fe_adap[adap->active_fe].pid_filtering;
-
-	mutex_unlock(&adap->dev->i2c_mutex);
-	return 0;
-}
-
-
-static int it913x_return_status(struct usb_device *udev)
-{
-	u32 firm = 0;
-
-	firm = it913x_query(udev, DEV_0);
-	if (firm > 0)
-		info("Firmware Version %d", firm);
-
-	return (firm > 0) ? firm : 0;
-}
-
-static int it913x_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
-				 int num)
-{
-	struct dvb_usb_device *d = i2c_get_adapdata(adap);
-	static u8 data[256];
-	int ret;
-	u32 reg;
-	u8 pro;
-
-	mutex_lock(&d->i2c_mutex);
-
-	debug_data_snipet(1, "Message out", msg[0].buf);
-	deb_info(2, "num of messages %d address %02x", num, msg[0].addr);
-
-	pro = (msg[0].addr & 0x2) ?  DEV_0_DMOD : 0x0;
-	pro |= (msg[0].addr & 0x20) ? DEV_1 : DEV_0;
-	memcpy(data, msg[0].buf, msg[0].len);
-	reg = (data[0] << 24) + (data[1] << 16) +
-			(data[2] << 8) + data[3];
-	if (num == 2) {
-		ret = it913x_io(d->udev, READ_LONG, pro,
-			CMD_DEMOD_READ, reg, 0, data, msg[1].len);
-		memcpy(msg[1].buf, data, msg[1].len);
-	} else
-		ret = it913x_io(d->udev, WRITE_LONG, pro, CMD_DEMOD_WRITE,
-			reg, 0, &data[4], msg[0].len - 4);
-
-	mutex_unlock(&d->i2c_mutex);
-
-	return ret;
-}
-
-static u32 it913x_i2c_func(struct i2c_adapter *adapter)
-{
-	return I2C_FUNC_I2C;
-}
-
-static struct i2c_algorithm it913x_i2c_algo = {
-	.master_xfer   = it913x_i2c_xfer,
-	.functionality = it913x_i2c_func,
-};
-
-/* Callbacks for DVB USB */
-#define IT913X_POLL 250
-static int it913x_rc_query(struct dvb_usb_device *d)
-{
-	u8 ibuf[4];
-	int ret;
-	u32 key;
-	/* Avoid conflict with frontends*/
-	mutex_lock(&d->i2c_mutex);
-
-	ret = it913x_io(d->udev, READ_LONG, PRO_LINK, CMD_IR_GET,
-		0, 0, &ibuf[0], sizeof(ibuf));
-
-	if ((ibuf[2] + ibuf[3]) == 0xff) {
-		key = ibuf[2];
-		key += ibuf[0] << 16;
-		key += ibuf[1] << 8;
-		deb_info(1, "NEC Extended Key =%08x", key);
-		if (d->rc_dev != NULL)
-			rc_keydown(d->rc_dev, key, 0);
-	}
-
-	mutex_unlock(&d->i2c_mutex);
-
-	return ret;
-}
-
-/* Firmware sets raw */
-const char fw_it9135_v1[] = "dvb-usb-it9135-01.fw";
-const char fw_it9135_v2[] = "dvb-usb-it9135-02.fw";
-const char fw_it9137[] = "dvb-usb-it9137-01.fw";
-
-static int ite_firmware_select(struct usb_device *udev,
-	struct dvb_usb_device_properties *props)
-{
-	int sw;
-	/* auto switch */
-	if (le16_to_cpu(udev->descriptor.idVendor) == USB_VID_KWORLD_2)
-		sw = IT9137_FW;
-	else if (it913x_config.chip_ver == 1)
-		sw = IT9135_V1_FW;
-	else
-		sw = IT9135_V2_FW;
-
-	/* force switch */
-	if (dvb_usb_it913x_firmware != IT9135_AUTO)
-		sw = dvb_usb_it913x_firmware;
-
-	switch (sw) {
-	case IT9135_V1_FW:
-		it913x_config.firmware_ver = 1;
-		it913x_config.adc_x2 = 1;
-		it913x_config.read_slevel = false;
-		props->firmware = fw_it9135_v1;
-		break;
-	case IT9135_V2_FW:
-		it913x_config.firmware_ver = 1;
-		it913x_config.adc_x2 = 1;
-		it913x_config.read_slevel = false;
-		props->firmware = fw_it9135_v2;
-		switch (it913x_config.tuner_id_0) {
-		case IT9135_61:
-		case IT9135_62:
-			break;
-		default:
-			info("Unknown tuner ID applying default 0x60");
-		case IT9135_60:
-			it913x_config.tuner_id_0 = IT9135_60;
-		}
-		break;
-	case IT9137_FW:
-	default:
-		it913x_config.firmware_ver = 0;
-		it913x_config.adc_x2 = 0;
-		it913x_config.read_slevel = true;
-		props->firmware = fw_it9137;
-	}
-
-	return 0;
-}
-
-static void it913x_select_remote(struct usb_device *udev,
-	struct dvb_usb_device_properties *props)
-{
-	switch (le16_to_cpu(udev->descriptor.idProduct)) {
-	case USB_PID_ITETECH_IT9135_9005:
-		props->rc.core.rc_codes = RC_MAP_IT913X_V2;
-		return;
-	default:
-		props->rc.core.rc_codes = RC_MAP_IT913X_V1;
-	}
-	return;
-}
-
-#define TS_MPEG_PKT_SIZE	188
-#define EP_LOW			21
-#define TS_BUFFER_SIZE_PID	(EP_LOW*TS_MPEG_PKT_SIZE)
-#define EP_HIGH			348
-#define TS_BUFFER_SIZE_MAX	(EP_HIGH*TS_MPEG_PKT_SIZE)
-
-static int it913x_select_config(struct usb_device *udev,
-	struct dvb_usb_device_properties *props)
-{
-	int ret = 0, reg;
-	bool proprietary_ir = false;
-
-	if (it913x_config.chip_ver == 0x02
-			&& it913x_config.chip_type == 0x9135)
-		reg = it913x_read_reg(udev, 0x461d);
-	else
-		reg = it913x_read_reg(udev, 0x461b);
-
-	if (reg < 0)
-		return reg;
-
-	if (reg == 0) {
-		it913x_config.dual_mode = 0;
-		it913x_config.tuner_id_0 = IT9135_38;
-		proprietary_ir = true;
-	} else {
-		/* TS mode */
-		reg =  it913x_read_reg(udev, 0x49c5);
-		if (reg < 0)
-			return reg;
-		it913x_config.dual_mode = reg;
-
-		/* IR mode type */
-		reg = it913x_read_reg(udev, 0x49ac);
-		if (reg < 0)
-			return reg;
-		if (reg == 5) {
-			info("Remote propriety (raw) mode");
-			proprietary_ir = true;
-		} else if (reg == 1) {
-			info("Remote HID mode NOT SUPPORTED");
-			proprietary_ir = false;
-			props->rc.core.rc_codes = NULL;
-		} else
-			props->rc.core.rc_codes = NULL;
-
-		/* Tuner_id */
-		reg = it913x_read_reg(udev, 0x49d0);
-		if (reg < 0)
-			return reg;
-		it913x_config.tuner_id_0 = reg;
-	}
-
-	if (proprietary_ir)
-		it913x_select_remote(udev, props);
-
-	if (udev->speed != USB_SPEED_HIGH) {
-		props->adapter[0].fe[0].pid_filter_count = 5;
-		info("USB 1 low speed mode - connect to USB 2 port");
-		if (pid_filter > 0)
-			pid_filter = 0;
-		if (it913x_config.dual_mode) {
-			it913x_config.dual_mode = 0;
-			info("Dual mode not supported in USB 1");
-		}
-	} else /* For replugging */
-		if(props->adapter[0].fe[0].pid_filter_count == 5)
-			props->adapter[0].fe[0].pid_filter_count = 31;
-
-	/* Select Stream Buffer Size and pid filter option*/
-	if (pid_filter) {
-		props->adapter[0].fe[0].stream.u.bulk.buffersize =
-			TS_BUFFER_SIZE_MAX;
-		props->adapter[0].fe[0].caps &=
-			~DVB_USB_ADAP_NEED_PID_FILTERING;
-	} else
-		props->adapter[0].fe[0].stream.u.bulk.buffersize =
-			TS_BUFFER_SIZE_PID;
-
-	if (it913x_config.dual_mode) {
-		props->adapter[1].fe[0].stream.u.bulk.buffersize =
-			props->adapter[0].fe[0].stream.u.bulk.buffersize;
-		props->num_adapters = 2;
-		if (pid_filter)
-			props->adapter[1].fe[0].caps =
-				props->adapter[0].fe[0].caps;
-	} else
-		props->num_adapters = 1;
-
-	info("Dual mode=%x Tuner Type=%x", it913x_config.dual_mode,
-		it913x_config.tuner_id_0);
-
-	ret = ite_firmware_select(udev, props);
-
-	return ret;
-}
-
-static int it913x_identify_state(struct usb_device *udev,
-		struct dvb_usb_device_properties *props,
-		struct dvb_usb_device_description **desc,
-		int *cold)
-{
-	int ret = 0, firm_no;
-	u8 reg;
-
-	firm_no = it913x_return_status(udev);
-
-	/* Read and select config */
-	ret = it913x_select_config(udev, props);
-	if (ret < 0)
-		return ret;
-
-	if (firm_no > 0) {
-		*cold = 0;
-		return 0;
-	}
-
-	if (it913x_config.dual_mode) {
-		it913x_config.tuner_id_1 = it913x_read_reg(udev, 0x49e0);
-		ret = it913x_wr_reg(udev, DEV_0, GPIOH1_EN, 0x1);
-		ret |= it913x_wr_reg(udev, DEV_0, GPIOH1_ON, 0x1);
-		ret |= it913x_wr_reg(udev, DEV_0, GPIOH1_O, 0x1);
-		msleep(50);
-		ret |= it913x_wr_reg(udev, DEV_0, GPIOH1_O, 0x0);
-		msleep(50);
-		reg = it913x_read_reg(udev, GPIOH1_O);
-		if (reg == 0) {
-			ret |= it913x_wr_reg(udev, DEV_0,  GPIOH1_O, 0x1);
-			ret |= it913x_return_status(udev);
-			if (ret != 0)
-				ret = it913x_wr_reg(udev, DEV_0,
-					GPIOH1_O, 0x0);
-		}
-	}
-
-	reg = it913x_read_reg(udev, IO_MUX_POWER_CLK);
-
-	if (it913x_config.dual_mode) {
-		ret |= it913x_wr_reg(udev, DEV_0, 0x4bfb, CHIP2_I2C_ADDR);
-		if (it913x_config.firmware_ver == 1)
-			ret |= it913x_wr_reg(udev, DEV_0,  0xcfff, 0x1);
-		else
-			ret |= it913x_wr_reg(udev, DEV_0,  CLK_O_EN, 0x1);
-	} else {
-		ret |= it913x_wr_reg(udev, DEV_0, 0x4bfb, 0x0);
-		if (it913x_config.firmware_ver == 1)
-			ret |= it913x_wr_reg(udev, DEV_0,  0xcfff, 0x0);
-		else
-			ret |= it913x_wr_reg(udev, DEV_0,  CLK_O_EN, 0x0);
-	}
-
-	*cold = 1;
-
-	return (ret < 0) ? -ENODEV : 0;
-}
-
-static int it913x_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
-{
-	struct it913x_state *st = adap->dev->priv;
-	int ret = 0;
-	u8 pro = (adap->id == 0) ? DEV_0_DMOD : DEV_1_DMOD;
-
-	deb_info(1, "STM  (%02x)", onoff);
-
-	if (!onoff) {
-		mutex_lock(&adap->dev->i2c_mutex);
-
-		ret = it913x_wr_reg(adap->dev->udev, pro, PID_RST, 0x1);
-
-		mutex_unlock(&adap->dev->i2c_mutex);
-		st->pid_filter_onoff =
-			adap->fe_adap[adap->active_fe].pid_filtering;
-
-	}
-
-	return ret;
-}
-
-static int it913x_download_firmware(struct usb_device *udev,
-					const struct firmware *fw)
-{
-	int ret = 0, i = 0, pos = 0;
-	u8 packet_size, min_pkt;
-	u8 *fw_data;
-
-	ret = it913x_wr_reg(udev, DEV_0,  I2C_CLK, I2C_CLK_100);
-
-	info("FRM Starting Firmware Download");
-
-	/* Multi firmware loader */
-	/* This uses scatter write firmware headers */
-	/* The firmware must start with 03 XX 00 */
-	/* and be the extact firmware length */
-
-	if (it913x_config.chip_ver == 2)
-		min_pkt = 0x11;
-	else
-		min_pkt = 0x19;
-
-	while (i <= fw->size) {
-		if (((fw->data[i] == 0x3) && (fw->data[i + 2] == 0x0))
-			|| (i == fw->size)) {
-			packet_size = i - pos;
-			if ((packet_size > min_pkt) || (i == fw->size)) {
-				fw_data = (u8 *)(fw->data + pos);
-				pos += packet_size;
-				if (packet_size > 0) {
-					ret = it913x_io(udev, WRITE_DATA,
-						DEV_0, CMD_SCATTER_WRITE, 0,
-						0, fw_data, packet_size);
-					if (ret < 0)
-						break;
-				}
-				udelay(1000);
-			}
-		}
-		i++;
-	}
-
-	if (ret < 0)
-		info("FRM Firmware Download Failed (%d)" , ret);
-	else
-		info("FRM Firmware Download Completed - Resetting Device");
-
-	msleep(30);
-
-	ret = it913x_io(udev, WRITE_CMD, DEV_0, CMD_BOOT, 0, 0, NULL, 0);
-	if (ret < 0)
-		info("FRM Device not responding to reboot");
-
-	ret = it913x_return_status(udev);
-	if (ret == 0) {
-		info("FRM Failed to reboot device");
-		return -ENODEV;
-	}
-
-	msleep(30);
-
-	ret = it913x_wr_reg(udev, DEV_0,  I2C_CLK, I2C_CLK_400);
-
-	msleep(30);
-
-	/* Tuner function */
-	if (it913x_config.dual_mode)
-		ret |= it913x_wr_reg(udev, DEV_0_DMOD , 0xec4c, 0xa0);
-	else
-		ret |= it913x_wr_reg(udev, DEV_0_DMOD , 0xec4c, 0x68);
-
-	if ((it913x_config.chip_ver == 1) &&
-		(it913x_config.chip_type == 0x9135)) {
-		ret |= it913x_wr_reg(udev, DEV_0,  PADODPU, 0x0);
-		ret |= it913x_wr_reg(udev, DEV_0,  AGC_O_D, 0x0);
-		if (it913x_config.dual_mode) {
-			ret |= it913x_wr_reg(udev, DEV_1,  PADODPU, 0x0);
-			ret |= it913x_wr_reg(udev, DEV_1,  AGC_O_D, 0x0);
-		}
-	}
-
-	return (ret < 0) ? -ENODEV : 0;
-}
-
-static int it913x_name(struct dvb_usb_adapter *adap)
-{
-	const char *desc = adap->dev->desc->name;
-	char *fe_name[] = {"_1", "_2", "_3", "_4"};
-	char *name = adap->fe_adap[0].fe->ops.info.name;
-
-	strlcpy(name, desc, 128);
-	strlcat(name, fe_name[adap->id], 128);
-
-	return 0;
-}
-
-static int it913x_frontend_attach(struct dvb_usb_adapter *adap)
-{
-	struct usb_device *udev = adap->dev->udev;
-	struct it913x_state *st = adap->dev->priv;
-	int ret = 0;
-	u8 adap_addr = I2C_BASE_ADDR + (adap->id << 5);
-	u16 ep_size = adap->props.fe[0].stream.u.bulk.buffersize / 4;
-	u8 pkt_size = 0x80;
-
-	if (adap->dev->udev->speed != USB_SPEED_HIGH)
-		pkt_size = 0x10;
-
-	it913x_config.adf = it913x_read_reg(udev, IO_MUX_POWER_CLK);
-
-	if (adap->id == 0)
-		memcpy(&st->it913x_config, &it913x_config,
-			sizeof(struct ite_config));
-
-	adap->fe_adap[0].fe = dvb_attach(it913x_fe_attach,
-		&adap->dev->i2c_adap, adap_addr, &st->it913x_config);
-
-	if (adap->id == 0 && adap->fe_adap[0].fe) {
-		ret = it913x_wr_reg(udev, DEV_0_DMOD, MP2_SW_RST, 0x1);
-		ret = it913x_wr_reg(udev, DEV_0_DMOD, MP2IF2_SW_RST, 0x1);
-		ret = it913x_wr_reg(udev, DEV_0, EP0_TX_EN, 0x0f);
-		ret = it913x_wr_reg(udev, DEV_0, EP0_TX_NAK, 0x1b);
-		ret = it913x_wr_reg(udev, DEV_0, EP0_TX_EN, 0x2f);
-		ret = it913x_wr_reg(udev, DEV_0, EP4_TX_LEN_LSB,
-					ep_size & 0xff);
-		ret = it913x_wr_reg(udev, DEV_0, EP4_TX_LEN_MSB, ep_size >> 8);
-		ret = it913x_wr_reg(udev, DEV_0, EP4_MAX_PKT, pkt_size);
-	} else if (adap->id == 1 && adap->fe_adap[0].fe) {
-		ret = it913x_wr_reg(udev, DEV_0, EP0_TX_EN, 0x6f);
-		ret = it913x_wr_reg(udev, DEV_0, EP5_TX_LEN_LSB,
-					ep_size & 0xff);
-		ret = it913x_wr_reg(udev, DEV_0, EP5_TX_LEN_MSB, ep_size >> 8);
-		ret = it913x_wr_reg(udev, DEV_0, EP5_MAX_PKT, pkt_size);
-		ret = it913x_wr_reg(udev, DEV_0_DMOD, MP2IF2_EN, 0x1);
-		ret = it913x_wr_reg(udev, DEV_1_DMOD, MP2IF_SERIAL, 0x1);
-		ret = it913x_wr_reg(udev, DEV_1, TOP_HOSTB_SER_MODE, 0x1);
-		ret = it913x_wr_reg(udev, DEV_0_DMOD, TSIS_ENABLE, 0x1);
-		ret = it913x_wr_reg(udev, DEV_0_DMOD, MP2_SW_RST, 0x0);
-		ret = it913x_wr_reg(udev, DEV_0_DMOD, MP2IF2_SW_RST, 0x0);
-		ret = it913x_wr_reg(udev, DEV_0_DMOD, MP2IF2_HALF_PSB, 0x0);
-		ret = it913x_wr_reg(udev, DEV_0_DMOD, MP2IF_STOP_EN, 0x1);
-		ret = it913x_wr_reg(udev, DEV_1_DMOD, MPEG_FULL_SPEED, 0x0);
-		ret = it913x_wr_reg(udev, DEV_1_DMOD, MP2IF_STOP_EN, 0x0);
-	} else
-		return -ENODEV;
-
-	ret = it913x_name(adap);
-
-	return ret;
-}
-
-/* DVB USB Driver */
-static struct dvb_usb_device_properties it913x_properties;
-
-static int it913x_probe(struct usb_interface *intf,
-		const struct usb_device_id *id)
-{
-	cmd_counter = 0;
-	if (0 == dvb_usb_device_init(intf, &it913x_properties,
-				     THIS_MODULE, NULL, adapter_nr)) {
-		info("DEV registering device driver");
-		return 0;
-	}
-
-	info("DEV it913x Error");
-	return -ENODEV;
-
-}
-
-static struct usb_device_id it913x_table[] = {
-	{ USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_UB499_2T_T09) },
-	{ USB_DEVICE(USB_VID_ITETECH, USB_PID_ITETECH_IT9135) },
-	{ USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV22_IT9137) },
-	{ USB_DEVICE(USB_VID_ITETECH, USB_PID_ITETECH_IT9135_9005) },
-	{ USB_DEVICE(USB_VID_ITETECH, USB_PID_ITETECH_IT9135_9006) },
-	{}		/* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE(usb, it913x_table);
-
-static struct dvb_usb_device_properties it913x_properties = {
-	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
-	.usb_ctrl = DEVICE_SPECIFIC,
-	.download_firmware = it913x_download_firmware,
-	.firmware = "dvb-usb-it9137-01.fw",
-	.no_reconnect = 1,
-	.size_of_priv = sizeof(struct it913x_state),
-	.num_adapters = 2,
-	.adapter = {
-		{
-		.num_frontends = 1,
-		.fe = {{
-			.caps = DVB_USB_ADAP_HAS_PID_FILTER|
-				DVB_USB_ADAP_NEED_PID_FILTERING|
-				DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
-			.streaming_ctrl   = it913x_streaming_ctrl,
-			.pid_filter_count = 31,
-			.pid_filter = it913x_pid_filter,
-			.pid_filter_ctrl  = it913x_pid_filter_ctrl,
-			.frontend_attach  = it913x_frontend_attach,
-			/* parameter for the MPEG2-data transfer */
-			.stream = {
-				.type = USB_BULK,
-				.count = 10,
-				.endpoint = 0x04,
-				.u = {/* Keep Low if PID filter on */
-					.bulk = {
-					.buffersize =
-						TS_BUFFER_SIZE_PID,
-					}
-				}
-			}
-		}},
-		},
-			{
-		.num_frontends = 1,
-		.fe = {{
-			.caps = DVB_USB_ADAP_HAS_PID_FILTER|
-				DVB_USB_ADAP_NEED_PID_FILTERING|
-				DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
-			.streaming_ctrl   = it913x_streaming_ctrl,
-			.pid_filter_count = 31,
-			.pid_filter = it913x_pid_filter,
-			.pid_filter_ctrl  = it913x_pid_filter_ctrl,
-			.frontend_attach  = it913x_frontend_attach,
-			/* parameter for the MPEG2-data transfer */
-			.stream = {
-				.type = USB_BULK,
-				.count = 5,
-				.endpoint = 0x05,
-				.u = {
-					.bulk = {
-						.buffersize =
-							TS_BUFFER_SIZE_PID,
-					}
-				}
-			}
-		}},
-		}
-	},
-	.identify_state   = it913x_identify_state,
-	.rc.core = {
-		.protocol	= RC_TYPE_NEC,
-		.module_name	= "it913x",
-		.rc_query	= it913x_rc_query,
-		.rc_interval	= IT913X_POLL,
-		.allowed_protos	= RC_TYPE_NEC,
-		.rc_codes	= RC_MAP_IT913X_V1,
-	},
-	.i2c_algo         = &it913x_i2c_algo,
-	.num_device_descs = 5,
-	.devices = {
-		{   "Kworld UB499-2T T09(IT9137)",
-			{ &it913x_table[0], NULL },
-			},
-		{   "ITE 9135 Generic",
-			{ &it913x_table[1], NULL },
-			},
-		{   "Sveon STV22 Dual DVB-T HDTV(IT9137)",
-			{ &it913x_table[2], NULL },
-			},
-		{   "ITE 9135(9005) Generic",
-			{ &it913x_table[3], NULL },
-			},
-		{   "ITE 9135(9006) Generic",
-			{ &it913x_table[4], NULL },
-			},
-	}
-};
-
-static struct usb_driver it913x_driver = {
-	.name		= "it913x",
-	.probe		= it913x_probe,
-	.disconnect	= dvb_usb_device_exit,
-	.id_table	= it913x_table,
-};
-
-module_usb_driver(it913x_driver);
-
-MODULE_AUTHOR("Malcolm Priestley <tvboxspy@gmail.com>");
-MODULE_DESCRIPTION("it913x USB 2 Driver");
-MODULE_VERSION("1.28");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/lmedm04.c b/drivers/media/dvb/dvb-usb/lmedm04.c
deleted file mode 100644
index 25d1031..0000000
--- a/drivers/media/dvb/dvb-usb/lmedm04.c
+++ /dev/null
@@ -1,1407 +0,0 @@
-/* DVB USB compliant linux driver for
- *
- * DM04/QQBOX DVB-S USB BOX	LME2510C + SHARP:BS2F7HZ7395
- *				LME2510C + LG TDQY-P001F
- *				LME2510C + BS2F7HZ0194
- *				LME2510 + LG TDQY-P001F
- *				LME2510 + BS2F7HZ0194
- *
- * MVB7395 (LME2510C+SHARP:BS2F7HZ7395)
- * SHARP:BS2F7HZ7395 = (STV0288+Sharp IX2505V)
- *
- * MV001F (LME2510+LGTDQY-P001F)
- * LG TDQY - P001F =(TDA8263 + TDA10086H)
- *
- * MVB0001F (LME2510C+LGTDQT-P001F)
- *
- * MV0194 (LME2510+SHARP:BS2F7HZ0194)
- * SHARP:BS2F7HZ0194 = (STV0299+IX2410)
- *
- * MVB0194 (LME2510C+SHARP0194)
- *
- * For firmware see Documentation/dvb/lmedm04.txt
- *
- * I2C addresses:
- * 0xd0 - STV0288	- Demodulator
- * 0xc0 - Sharp IX2505V	- Tuner
- * --
- * 0x1c - TDA10086   - Demodulator
- * 0xc0 - TDA8263    - Tuner
- * --
- * 0xd0 - STV0299	- Demodulator
- * 0xc0 - IX2410	- Tuner
- *
- *
- * VID = 3344  PID LME2510=1122 LME2510C=1120
- *
- * Copyright (C) 2010 Malcolm Priestley (tvboxspy@gmail.com)
- * LME2510(C)(C) Leaguerme (Shenzhen) MicroElectronics Co., 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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You 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.
- *
- *
- * see Documentation/dvb/README.dvb-usb for more information
- *
- * Known Issues :
- *	LME2510: Non Intel USB chipsets fail to maintain High Speed on
- * Boot or Hot Plug.
- *
- * QQbox suffers from noise on LNB voltage.
- *
- *	LME2510: SHARP:BS2F7HZ0194(MV0194) cannot cold reset and share system
- * with other tuners. After a cold reset streaming will not start.
- *
- */
-#define DVB_USB_LOG_PREFIX "LME2510(C)"
-#include <linux/usb.h>
-#include <linux/usb/input.h>
-#include <media/rc-core.h>
-
-#include "dvb-usb.h"
-#include "lmedm04.h"
-#include "tda826x.h"
-#include "tda10086.h"
-#include "stv0288.h"
-#include "ix2505v.h"
-#include "stv0299.h"
-#include "dvb-pll.h"
-#include "z0194a.h"
-#include "m88rs2000.h"
-
-
-
-/* debug */
-static int dvb_usb_lme2510_debug;
-#define l_dprintk(var, level, args...) do { \
-	if ((var >= level)) \
-		printk(KERN_DEBUG DVB_USB_LOG_PREFIX ": " args); \
-} while (0)
-
-#define deb_info(level, args...) l_dprintk(dvb_usb_lme2510_debug, level, args)
-#define debug_data_snipet(level, name, p) \
-	 deb_info(level, name" (%02x%02x%02x%02x%02x%02x%02x%02x)", \
-		*p, *(p+1), *(p+2), *(p+3), *(p+4), \
-			*(p+5), *(p+6), *(p+7));
-
-
-module_param_named(debug, dvb_usb_lme2510_debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able))."
-			DVB_USB_DEBUG_STATUS);
-
-static int dvb_usb_lme2510_firmware;
-module_param_named(firmware, dvb_usb_lme2510_firmware, int, 0644);
-MODULE_PARM_DESC(firmware, "set default firmware 0=Sharp7395 1=LG");
-
-static int pid_filter;
-module_param_named(pid, pid_filter, int, 0644);
-MODULE_PARM_DESC(pid, "set default 0=default 1=off 2=on");
-
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-#define TUNER_DEFAULT	0x0
-#define TUNER_LG	0x1
-#define TUNER_S7395	0x2
-#define TUNER_S0194	0x3
-#define TUNER_RS2000	0x4
-
-struct lme2510_state {
-	u8 id;
-	u8 tuner_config;
-	u8 signal_lock;
-	u8 signal_level;
-	u8 signal_sn;
-	u8 time_key;
-	u8 last_key;
-	u8 key_timeout;
-	u8 i2c_talk_onoff;
-	u8 i2c_gate;
-	u8 i2c_tuner_gate_w;
-	u8 i2c_tuner_gate_r;
-	u8 i2c_tuner_addr;
-	u8 stream_on;
-	u8 pid_size;
-	u8 pid_off;
-	void *buffer;
-	struct urb *lme_urb;
-	void *usb_buffer;
-
-};
-
-static int lme2510_bulk_write(struct usb_device *dev,
-				u8 *snd, int len, u8 pipe)
-{
-	int ret, actual_l;
-
-	ret = usb_bulk_msg(dev, usb_sndbulkpipe(dev, pipe),
-				snd, len , &actual_l, 100);
-	return ret;
-}
-
-static int lme2510_bulk_read(struct usb_device *dev,
-				u8 *rev, int len, u8 pipe)
-{
-	int ret, actual_l;
-
-	ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, pipe),
-				 rev, len , &actual_l, 200);
-	return ret;
-}
-
-static int lme2510_usb_talk(struct dvb_usb_device *d,
-		u8 *wbuf, int wlen, u8 *rbuf, int rlen)
-{
-	struct lme2510_state *st = d->priv;
-	u8 *buff;
-	int ret = 0;
-
-	if (st->usb_buffer == NULL) {
-		st->usb_buffer = kmalloc(64, GFP_KERNEL);
-		if (st->usb_buffer == NULL) {
-			info("MEM Error no memory");
-			return -ENOMEM;
-		}
-	}
-	buff = st->usb_buffer;
-
-	ret = mutex_lock_interruptible(&d->usb_mutex);
-
-	if (ret < 0)
-		return -EAGAIN;
-
-	/* the read/write capped at 64 */
-	memcpy(buff, wbuf, (wlen < 64) ? wlen : 64);
-
-	ret |= lme2510_bulk_write(d->udev, buff, wlen , 0x01);
-
-	ret |= lme2510_bulk_read(d->udev, buff, (rlen < 64) ?
-			rlen : 64 , 0x01);
-
-	if (rlen > 0)
-		memcpy(rbuf, buff, rlen);
-
-	mutex_unlock(&d->usb_mutex);
-
-	return (ret < 0) ? -ENODEV : 0;
-}
-
-static int lme2510_stream_restart(struct dvb_usb_device *d)
-{
-	struct lme2510_state *st = d->priv;
-	u8 all_pids[] = LME_ALL_PIDS;
-	u8 stream_on[] = LME_ST_ON_W;
-	int ret;
-	u8 rbuff[1];
-	if (st->pid_off)
-		ret = lme2510_usb_talk(d, all_pids, sizeof(all_pids),
-			rbuff, sizeof(rbuff));
-	/*Restart Stream Command*/
-	ret = lme2510_usb_talk(d, stream_on, sizeof(stream_on),
-			rbuff, sizeof(rbuff));
-	return ret;
-}
-
-static int lme2510_enable_pid(struct dvb_usb_device *d, u8 index, u16 pid_out)
-{
-	struct lme2510_state *st = d->priv;
-	static u8 pid_buff[] = LME_ZERO_PID;
-	static u8 rbuf[1];
-	u8 pid_no = index * 2;
-	u8 pid_len = pid_no + 2;
-	int ret = 0;
-	deb_info(1, "PID Setting Pid %04x", pid_out);
-
-	if (st->pid_size == 0)
-		ret |= lme2510_stream_restart(d);
-
-	pid_buff[2] = pid_no;
-	pid_buff[3] = (u8)pid_out & 0xff;
-	pid_buff[4] = pid_no + 1;
-	pid_buff[5] = (u8)(pid_out >> 8);
-
-	if (pid_len > st->pid_size)
-		st->pid_size = pid_len;
-	pid_buff[7] = 0x80 + st->pid_size;
-
-	ret |= lme2510_usb_talk(d, pid_buff ,
-		sizeof(pid_buff) , rbuf, sizeof(rbuf));
-
-	if (st->stream_on)
-		ret |= lme2510_stream_restart(d);
-
-	return ret;
-}
-
-static void lme2510_int_response(struct urb *lme_urb)
-{
-	struct dvb_usb_adapter *adap = lme_urb->context;
-	struct lme2510_state *st = adap->dev->priv;
-	static u8 *ibuf, *rbuf;
-	int i = 0, offset;
-	u32 key;
-
-	switch (lme_urb->status) {
-	case 0:
-	case -ETIMEDOUT:
-		break;
-	case -ECONNRESET:
-	case -ENOENT:
-	case -ESHUTDOWN:
-		return;
-	default:
-		info("Error %x", lme_urb->status);
-		break;
-	}
-
-	rbuf = (u8 *) lme_urb->transfer_buffer;
-
-	offset = ((lme_urb->actual_length/8) > 4)
-			? 4 : (lme_urb->actual_length/8) ;
-
-	for (i = 0; i < offset; ++i) {
-		ibuf = (u8 *)&rbuf[i*8];
-		deb_info(5, "INT O/S C =%02x C/O=%02x Type =%02x%02x",
-		offset, i, ibuf[0], ibuf[1]);
-
-		switch (ibuf[0]) {
-		case 0xaa:
-			debug_data_snipet(1, "INT Remote data snipet", ibuf);
-			if ((ibuf[4] + ibuf[5]) == 0xff) {
-				key = ibuf[5];
-				key += (ibuf[3] > 0)
-					? (ibuf[3] ^ 0xff) << 8 : 0;
-				key += (ibuf[2] ^ 0xff) << 16;
-				deb_info(1, "INT Key =%08x", key);
-				if (adap->dev->rc_dev != NULL)
-					rc_keydown(adap->dev->rc_dev, key, 0);
-			}
-			break;
-		case 0xbb:
-			switch (st->tuner_config) {
-			case TUNER_LG:
-				if (ibuf[2] > 0)
-					st->signal_lock = ibuf[2];
-				st->signal_level = ibuf[4];
-				st->signal_sn = ibuf[3];
-				st->time_key = ibuf[7];
-				break;
-			case TUNER_S7395:
-			case TUNER_S0194:
-				/* Tweak for earlier firmware*/
-				if (ibuf[1] == 0x03) {
-					if (ibuf[2] > 1)
-						st->signal_lock = ibuf[2];
-					st->signal_level = ibuf[3];
-					st->signal_sn = ibuf[4];
-				} else {
-					st->signal_level = ibuf[4];
-					st->signal_sn = ibuf[5];
-					st->signal_lock =
-						(st->signal_lock & 0xf7) +
-						((ibuf[2] & 0x01) << 0x03);
-				}
-				break;
-			case TUNER_RS2000:
-				if (ibuf[2] > 0)
-					st->signal_lock = 0xff;
-				else
-					st->signal_lock = 0xf0;
-				st->signal_level = ibuf[4];
-				st->signal_sn = ibuf[5];
-				st->time_key = ibuf[7];
-			default:
-				break;
-			}
-			debug_data_snipet(5, "INT Remote data snipet in", ibuf);
-		break;
-		case 0xcc:
-			debug_data_snipet(1, "INT Control data snipet", ibuf);
-			break;
-		default:
-			debug_data_snipet(1, "INT Unknown data snipet", ibuf);
-		break;
-		}
-	}
-	usb_submit_urb(lme_urb, GFP_ATOMIC);
-}
-
-static int lme2510_int_read(struct dvb_usb_adapter *adap)
-{
-	struct lme2510_state *lme_int = adap->dev->priv;
-
-	lme_int->lme_urb = usb_alloc_urb(0, GFP_ATOMIC);
-
-	if (lme_int->lme_urb == NULL)
-			return -ENOMEM;
-
-	lme_int->buffer = usb_alloc_coherent(adap->dev->udev, 128, GFP_ATOMIC,
-					&lme_int->lme_urb->transfer_dma);
-
-	if (lme_int->buffer == NULL)
-			return -ENOMEM;
-
-	usb_fill_int_urb(lme_int->lme_urb,
-				adap->dev->udev,
-				usb_rcvintpipe(adap->dev->udev, 0xa),
-				lme_int->buffer,
-				128,
-				lme2510_int_response,
-				adap,
-				8);
-
-	lme_int->lme_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
-
-	usb_submit_urb(lme_int->lme_urb, GFP_ATOMIC);
-	info("INT Interrupt Service Started");
-
-	return 0;
-}
-
-static int lme2510_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff)
-{
-	struct lme2510_state *st = adap->dev->priv;
-	static u8 clear_pid_reg[] = LME_ALL_PIDS;
-	static u8 rbuf[1];
-	int ret = 0;
-
-	deb_info(1, "PID Clearing Filter");
-
-	mutex_lock(&adap->dev->i2c_mutex);
-
-	if (!onoff) {
-		ret |= lme2510_usb_talk(adap->dev, clear_pid_reg,
-			sizeof(clear_pid_reg), rbuf, sizeof(rbuf));
-		st->pid_off = true;
-	} else
-		st->pid_off = false;
-
-	st->pid_size = 0;
-
-	mutex_unlock(&adap->dev->i2c_mutex);
-
-	return 0;
-}
-
-static int lme2510_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid,
-	int onoff)
-{
-	int ret = 0;
-
-	deb_info(3, "%s PID=%04x Index=%04x onoff=%02x", __func__,
-		pid, index, onoff);
-
-	if (onoff) {
-		mutex_lock(&adap->dev->i2c_mutex);
-		ret |= lme2510_enable_pid(adap->dev, index, pid);
-		mutex_unlock(&adap->dev->i2c_mutex);
-	}
-
-
-	return ret;
-}
-
-
-static int lme2510_return_status(struct usb_device *dev)
-{
-	int ret = 0;
-	u8 *data;
-
-	data = kzalloc(10, GFP_KERNEL);
-	if (!data)
-		return -ENOMEM;
-
-	ret |= usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
-			0x06, 0x80, 0x0302, 0x00, data, 0x0006, 200);
-	info("Firmware Status: %x (%x)", ret , data[2]);
-
-	ret = (ret < 0) ? -ENODEV : data[2];
-	kfree(data);
-	return ret;
-}
-
-static int lme2510_msg(struct dvb_usb_device *d,
-		u8 *wbuf, int wlen, u8 *rbuf, int rlen)
-{
-	int ret = 0;
-	struct lme2510_state *st = d->priv;
-
-	if (st->i2c_talk_onoff == 1) {
-
-		ret = lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen);
-
-		switch (st->tuner_config) {
-		case TUNER_LG:
-			if (wbuf[2] == 0x1c) {
-				if (wbuf[3] == 0x0e) {
-					st->signal_lock = rbuf[1];
-					if ((st->stream_on & 1) &&
-						(st->signal_lock & 0x10)) {
-						lme2510_stream_restart(d);
-						st->i2c_talk_onoff = 0;
-					}
-					msleep(80);
-				}
-			}
-			break;
-		case TUNER_S7395:
-			if (wbuf[2] == 0xd0) {
-				if (wbuf[3] == 0x24) {
-					st->signal_lock = rbuf[1];
-					if ((st->stream_on & 1) &&
-						(st->signal_lock & 0x8)) {
-						lme2510_stream_restart(d);
-						st->i2c_talk_onoff = 0;
-					}
-				}
-			}
-			break;
-		case TUNER_S0194:
-			if (wbuf[2] == 0xd0) {
-				if (wbuf[3] == 0x1b) {
-					st->signal_lock = rbuf[1];
-					if ((st->stream_on & 1) &&
-						(st->signal_lock & 0x8)) {
-						lme2510_stream_restart(d);
-						st->i2c_talk_onoff = 0;
-					}
-				}
-			}
-			break;
-		case TUNER_RS2000:
-		default:
-			break;
-		}
-	} else {
-		/* TODO rewrite this section */
-		switch (st->tuner_config) {
-		case TUNER_LG:
-			switch (wbuf[3]) {
-			case 0x0e:
-				rbuf[0] = 0x55;
-				rbuf[1] = st->signal_lock;
-				break;
-			case 0x43:
-				rbuf[0] = 0x55;
-				rbuf[1] = st->signal_level;
-				break;
-			case 0x1c:
-				rbuf[0] = 0x55;
-				rbuf[1] = st->signal_sn;
-				break;
-			case 0x15:
-			case 0x16:
-			case 0x17:
-			case 0x18:
-				rbuf[0] = 0x55;
-				rbuf[1] = 0x00;
-				break;
-			default:
-				lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen);
-				st->i2c_talk_onoff = 1;
-				break;
-			}
-			break;
-		case TUNER_S7395:
-			switch (wbuf[3]) {
-			case 0x10:
-				rbuf[0] = 0x55;
-				rbuf[1] = (st->signal_level & 0x80)
-						? 0 : (st->signal_level * 2);
-				break;
-			case 0x2d:
-				rbuf[0] = 0x55;
-				rbuf[1] = st->signal_sn;
-				break;
-			case 0x24:
-				rbuf[0] = 0x55;
-				rbuf[1] = st->signal_lock;
-				break;
-			case 0x2e:
-			case 0x26:
-			case 0x27:
-				rbuf[0] = 0x55;
-				rbuf[1] = 0x00;
-				break;
-			default:
-				lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen);
-				st->i2c_talk_onoff = 1;
-				break;
-			}
-			break;
-		case TUNER_S0194:
-			switch (wbuf[3]) {
-			case 0x18:
-				rbuf[0] = 0x55;
-				rbuf[1] = (st->signal_level & 0x80)
-						? 0 : (st->signal_level * 2);
-				break;
-			case 0x24:
-				rbuf[0] = 0x55;
-				rbuf[1] = st->signal_sn;
-				break;
-			case 0x1b:
-				rbuf[0] = 0x55;
-				rbuf[1] = st->signal_lock;
-				break;
-			case 0x19:
-			case 0x25:
-			case 0x1e:
-			case 0x1d:
-				rbuf[0] = 0x55;
-				rbuf[1] = 0x00;
-				break;
-			default:
-				lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen);
-				st->i2c_talk_onoff = 1;
-				break;
-			}
-			break;
-		case TUNER_RS2000:
-			switch (wbuf[3]) {
-			case 0x8c:
-				rbuf[0] = 0x55;
-				rbuf[1] = 0xff;
-				if (st->last_key == st->time_key) {
-					st->key_timeout++;
-					if (st->key_timeout > 5)
-						rbuf[1] = 0;
-				} else
-					st->key_timeout = 0;
-				st->last_key = st->time_key;
-				break;
-			default:
-				lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen);
-				st->i2c_talk_onoff = 1;
-				break;
-			}
-		default:
-			break;
-		}
-
-		deb_info(4, "I2C From Interrupt Message out(%02x) in(%02x)",
-				wbuf[3], rbuf[1]);
-
-	}
-
-	return ret;
-}
-
-
-static int lme2510_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
-				 int num)
-{
-	struct dvb_usb_device *d = i2c_get_adapdata(adap);
-	struct lme2510_state *st = d->priv;
-	static u8 obuf[64], ibuf[64];
-	int i, read, read_o;
-	u16 len;
-	u8 gate = st->i2c_gate;
-
-	mutex_lock(&d->i2c_mutex);
-
-	if (gate == 0)
-		gate = 5;
-
-	if (num > 2)
-		warn("more than 2 i2c messages"
-			"at a time is not handled yet.	TODO.");
-
-	for (i = 0; i < num; i++) {
-		read_o = 1 & (msg[i].flags & I2C_M_RD);
-		read = i+1 < num && (msg[i+1].flags & I2C_M_RD);
-		read |= read_o;
-		gate = (msg[i].addr == st->i2c_tuner_addr)
-			? (read)	? st->i2c_tuner_gate_r
-					: st->i2c_tuner_gate_w
-			: st->i2c_gate;
-		obuf[0] = gate | (read << 7);
-
-		if (gate == 5)
-			obuf[1] = (read) ? 2 : msg[i].len + 1;
-		else
-			obuf[1] = msg[i].len + read + 1;
-
-		obuf[2] = msg[i].addr;
-		if (read) {
-			if (read_o)
-				len = 3;
-			else {
-				memcpy(&obuf[3], msg[i].buf, msg[i].len);
-				obuf[msg[i].len+3] = msg[i+1].len;
-				len = msg[i].len+4;
-			}
-		} else {
-			memcpy(&obuf[3], msg[i].buf, msg[i].len);
-			len = msg[i].len+3;
-		}
-
-		if (lme2510_msg(d, obuf, len, ibuf, 64) < 0) {
-			deb_info(1, "i2c transfer failed.");
-			mutex_unlock(&d->i2c_mutex);
-			return -EAGAIN;
-		}
-
-		if (read) {
-			if (read_o)
-				memcpy(msg[i].buf, &ibuf[1], msg[i].len);
-			else {
-				memcpy(msg[i+1].buf, &ibuf[1], msg[i+1].len);
-				i++;
-			}
-		}
-	}
-
-	mutex_unlock(&d->i2c_mutex);
-	return i;
-}
-
-static u32 lme2510_i2c_func(struct i2c_adapter *adapter)
-{
-	return I2C_FUNC_I2C;
-}
-
-static struct i2c_algorithm lme2510_i2c_algo = {
-	.master_xfer   = lme2510_i2c_xfer,
-	.functionality = lme2510_i2c_func,
-};
-
-/* Callbacks for DVB USB */
-static int lme2510_identify_state(struct usb_device *udev,
-		struct dvb_usb_device_properties *props,
-		struct dvb_usb_device_description **desc,
-		int *cold)
-{
-	if (pid_filter != 2)
-		props->adapter[0].fe[0].caps &=
-			~DVB_USB_ADAP_NEED_PID_FILTERING;
-	*cold = 0;
-	return 0;
-}
-
-static int lme2510_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
-{
-	struct lme2510_state *st = adap->dev->priv;
-	static u8 clear_reg_3[] = LME_ALL_PIDS;
-	static u8 rbuf[1];
-	int ret = 0, rlen = sizeof(rbuf);
-
-	deb_info(1, "STM  (%02x)", onoff);
-
-	/* Streaming is started by FE_HAS_LOCK */
-	if (onoff == 1)
-		st->stream_on = 1;
-	else {
-		deb_info(1, "STM Steam Off");
-		/* mutex is here only to avoid collision with I2C */
-		mutex_lock(&adap->dev->i2c_mutex);
-
-		ret = lme2510_usb_talk(adap->dev, clear_reg_3,
-				sizeof(clear_reg_3), rbuf, rlen);
-		st->stream_on = 0;
-		st->i2c_talk_onoff = 1;
-
-		mutex_unlock(&adap->dev->i2c_mutex);
-	}
-
-	return (ret < 0) ? -ENODEV : 0;
-}
-
-static u8 check_sum(u8 *p, u8 len)
-{
-	u8 sum = 0;
-	while (len--)
-		sum += *p++;
-	return sum;
-}
-
-static int lme2510_download_firmware(struct usb_device *dev,
-					const struct firmware *fw)
-{
-	int ret = 0;
-	u8 *data;
-	u16 j, wlen, len_in, start, end;
-	u8 packet_size, dlen, i;
-	u8 *fw_data;
-
-	packet_size = 0x31;
-	len_in = 1;
-
-	data = kzalloc(512, GFP_KERNEL);
-	if (!data) {
-		info("FRM Could not start Firmware Download (Buffer allocation failed)");
-		return -ENOMEM;
-	}
-
-	info("FRM Starting Firmware Download");
-
-	for (i = 1; i < 3; i++) {
-		start = (i == 1) ? 0 : 512;
-		end = (i == 1) ? 512 : fw->size;
-		for (j = start; j < end; j += (packet_size+1)) {
-			fw_data = (u8 *)(fw->data + j);
-			if ((end - j) > packet_size) {
-				data[0] = i;
-				dlen = packet_size;
-			} else {
-				data[0] = i | 0x80;
-				dlen = (u8)(end - j)-1;
-			}
-			data[1] = dlen;
-			memcpy(&data[2], fw_data, dlen+1);
-			wlen = (u8) dlen + 4;
-			data[wlen-1] = check_sum(fw_data, dlen+1);
-			deb_info(1, "Data S=%02x:E=%02x CS= %02x", data[3],
-				data[dlen+2], data[dlen+3]);
-			ret |= lme2510_bulk_write(dev, data,  wlen, 1);
-			ret |= lme2510_bulk_read(dev, data, len_in , 1);
-			ret |= (data[0] == 0x88) ? 0 : -1;
-		}
-	}
-
-	usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
-			0x06, 0x80, 0x0200, 0x00, data, 0x0109, 1000);
-
-
-	data[0] = 0x8a;
-	len_in = 1;
-	msleep(2000);
-	ret |= lme2510_bulk_write(dev, data , len_in, 1); /*Resetting*/
-	ret |= lme2510_bulk_read(dev, data, len_in, 1);
-	msleep(400);
-
-	if (ret < 0)
-		info("FRM Firmware Download Failed (%04x)" , ret);
-	else
-		info("FRM Firmware Download Completed - Resetting Device");
-
-	kfree(data);
-	return (ret < 0) ? -ENODEV : 0;
-}
-
-static void lme_coldreset(struct usb_device *dev)
-{
-	int ret = 0, len_in;
-	u8 data[512] = {0};
-
-	data[0] = 0x0a;
-	len_in = 1;
-	info("FRM Firmware Cold Reset");
-	ret |= lme2510_bulk_write(dev, data , len_in, 1); /*Cold Resetting*/
-	ret |= lme2510_bulk_read(dev, data, len_in, 1);
-
-	return;
-}
-
-static int lme_firmware_switch(struct usb_device *udev, int cold)
-{
-	const struct firmware *fw = NULL;
-	const char fw_c_s7395[] = "dvb-usb-lme2510c-s7395.fw";
-	const char fw_c_lg[] = "dvb-usb-lme2510c-lg.fw";
-	const char fw_c_s0194[] = "dvb-usb-lme2510c-s0194.fw";
-	const char fw_c_rs2000[] = "dvb-usb-lme2510c-rs2000.fw";
-	const char fw_lg[] = "dvb-usb-lme2510-lg.fw";
-	const char fw_s0194[] = "dvb-usb-lme2510-s0194.fw";
-	const char *fw_lme;
-	int ret = 0, cold_fw;
-
-	cold = (cold > 0) ? (cold & 1) : 0;
-
-	cold_fw = !cold;
-
-	switch (le16_to_cpu(udev->descriptor.idProduct)) {
-	case 0x1122:
-		switch (dvb_usb_lme2510_firmware) {
-		default:
-			dvb_usb_lme2510_firmware = TUNER_S0194;
-		case TUNER_S0194:
-			fw_lme = fw_s0194;
-			ret = request_firmware(&fw, fw_lme, &udev->dev);
-			if (ret == 0) {
-				cold = 0;
-				break;
-			}
-			dvb_usb_lme2510_firmware = TUNER_LG;
-		case TUNER_LG:
-			fw_lme = fw_lg;
-			ret = request_firmware(&fw, fw_lme, &udev->dev);
-			if (ret == 0)
-				break;
-			info("FRM No Firmware Found - please install");
-			dvb_usb_lme2510_firmware = TUNER_DEFAULT;
-			cold = 0;
-			cold_fw = 0;
-			break;
-		}
-		break;
-	case 0x1120:
-		switch (dvb_usb_lme2510_firmware) {
-		default:
-			dvb_usb_lme2510_firmware = TUNER_S7395;
-		case TUNER_S7395:
-			fw_lme = fw_c_s7395;
-			ret = request_firmware(&fw, fw_lme, &udev->dev);
-			if (ret == 0) {
-				cold = 0;
-				break;
-			}
-			dvb_usb_lme2510_firmware = TUNER_LG;
-		case TUNER_LG:
-			fw_lme = fw_c_lg;
-			ret = request_firmware(&fw, fw_lme, &udev->dev);
-			if (ret == 0)
-				break;
-			dvb_usb_lme2510_firmware = TUNER_S0194;
-		case TUNER_S0194:
-			fw_lme = fw_c_s0194;
-			ret = request_firmware(&fw, fw_lme, &udev->dev);
-			if (ret == 0)
-				break;
-			info("FRM No Firmware Found - please install");
-			dvb_usb_lme2510_firmware = TUNER_DEFAULT;
-			cold = 0;
-			cold_fw = 0;
-			break;
-		}
-		break;
-	case 0x22f0:
-		fw_lme = fw_c_rs2000;
-		ret = request_firmware(&fw, fw_lme, &udev->dev);
-		dvb_usb_lme2510_firmware = TUNER_RS2000;
-		break;
-	default:
-		fw_lme = fw_c_s7395;
-	}
-
-
-	if (cold_fw) {
-		info("FRM Loading %s file", fw_lme);
-		ret = lme2510_download_firmware(udev, fw);
-	}
-
-	release_firmware(fw);
-
-	if (cold) {
-		info("FRM Changing to %s firmware", fw_lme);
-		lme_coldreset(udev);
-		return -ENODEV;
-	}
-
-	return ret;
-}
-
-static int lme2510_kill_urb(struct usb_data_stream *stream)
-{
-	int i;
-
-	for (i = 0; i < stream->urbs_submitted; i++) {
-		deb_info(3, "killing URB no. %d.", i);
-		/* stop the URB */
-		usb_kill_urb(stream->urb_list[i]);
-	}
-	stream->urbs_submitted = 0;
-
-	return 0;
-}
-
-static struct tda10086_config tda10086_config = {
-	.demod_address = 0x1c,
-	.invert = 0,
-	.diseqc_tone = 1,
-	.xtal_freq = TDA10086_XTAL_16M,
-};
-
-static struct stv0288_config lme_config = {
-	.demod_address = 0xd0,
-	.min_delay_ms = 15,
-	.inittab = s7395_inittab,
-};
-
-static struct ix2505v_config lme_tuner = {
-	.tuner_address = 0xc0,
-	.min_delay_ms = 100,
-	.tuner_gain = 0x0,
-	.tuner_chargepump = 0x3,
-};
-
-static struct stv0299_config sharp_z0194_config = {
-	.demod_address = 0xd0,
-	.inittab = sharp_z0194a_inittab,
-	.mclk = 88000000UL,
-	.invert = 0,
-	.skip_reinit = 0,
-	.lock_output = STV0299_LOCKOUTPUT_1,
-	.volt13_op0_op1 = STV0299_VOLT13_OP1,
-	.min_delay_ms = 100,
-	.set_symbol_rate = sharp_z0194a_set_symbol_rate,
-};
-
-static int dm04_rs2000_set_ts_param(struct dvb_frontend *fe,
-	int caller)
-{
-	struct dvb_usb_adapter *adap = fe->dvb->priv;
-	struct dvb_usb_device *d = adap->dev;
-	struct lme2510_state *st = d->priv;
-
-	mutex_lock(&d->i2c_mutex);
-	if ((st->i2c_talk_onoff == 1) && (st->stream_on & 1)) {
-		st->i2c_talk_onoff = 0;
-		lme2510_stream_restart(d);
-	}
-	mutex_unlock(&d->i2c_mutex);
-
-	return 0;
-}
-
-static struct m88rs2000_config m88rs2000_config = {
-	.demod_addr = 0xd0,
-	.tuner_addr = 0xc0,
-	.set_ts_params = dm04_rs2000_set_ts_param,
-};
-
-static int dm04_lme2510_set_voltage(struct dvb_frontend *fe,
-					fe_sec_voltage_t voltage)
-{
-	struct dvb_usb_adapter *adap = fe->dvb->priv;
-	static u8 voltage_low[]	= LME_VOLTAGE_L;
-	static u8 voltage_high[] = LME_VOLTAGE_H;
-	static u8 rbuf[1];
-	int ret = 0, len = 3, rlen = 1;
-
-	mutex_lock(&adap->dev->i2c_mutex);
-
-	switch (voltage) {
-	case SEC_VOLTAGE_18:
-		ret |= lme2510_usb_talk(adap->dev,
-			voltage_high, len, rbuf, rlen);
-		break;
-
-	case SEC_VOLTAGE_OFF:
-	case SEC_VOLTAGE_13:
-	default:
-		ret |= lme2510_usb_talk(adap->dev,
-				voltage_low, len, rbuf, rlen);
-		break;
-	}
-
-	mutex_unlock(&adap->dev->i2c_mutex);
-
-	return (ret < 0) ? -ENODEV : 0;
-}
-
-static int dm04_rs2000_read_signal_strength(struct dvb_frontend *fe,
-	u16 *strength)
-{
-	struct dvb_usb_adapter *adap = fe->dvb->priv;
-	struct lme2510_state *st = adap->dev->priv;
-
-	*strength = (u16)((u32)st->signal_level * 0xffff / 0x7f);
-	return 0;
-}
-
-static int dm04_rs2000_read_snr(struct dvb_frontend *fe, u16 *snr)
-{
-	struct dvb_usb_adapter *adap = fe->dvb->priv;
-	struct lme2510_state *st = adap->dev->priv;
-
-	*snr = (u16)((u32)st->signal_sn * 0xffff / 0xff);
-	return 0;
-}
-
-static int lme_name(struct dvb_usb_adapter *adap)
-{
-	struct lme2510_state *st = adap->dev->priv;
-	const char *desc = adap->dev->desc->name;
-	char *fe_name[] = {"", " LG TDQY-P001F", " SHARP:BS2F7HZ7395",
-				" SHARP:BS2F7HZ0194", " RS2000"};
-	char *name = adap->fe_adap[0].fe->ops.info.name;
-
-	strlcpy(name, desc, 128);
-	strlcat(name, fe_name[st->tuner_config], 128);
-
-	return 0;
-}
-
-static int dm04_lme2510_frontend_attach(struct dvb_usb_adapter *adap)
-{
-	struct lme2510_state *st = adap->dev->priv;
-
-	int ret = 0;
-
-	st->i2c_talk_onoff = 1;
-	switch (le16_to_cpu(adap->dev->udev->descriptor.idProduct)) {
-	case 0x1122:
-	case 0x1120:
-		st->i2c_gate = 4;
-		adap->fe_adap[0].fe = dvb_attach(tda10086_attach,
-			&tda10086_config, &adap->dev->i2c_adap);
-		if (adap->fe_adap[0].fe) {
-			info("TUN Found Frontend TDA10086");
-			st->i2c_tuner_gate_w = 4;
-			st->i2c_tuner_gate_r = 4;
-			st->i2c_tuner_addr = 0xc0;
-			st->tuner_config = TUNER_LG;
-			if (dvb_usb_lme2510_firmware != TUNER_LG) {
-				dvb_usb_lme2510_firmware = TUNER_LG;
-				ret = lme_firmware_switch(adap->dev->udev, 1);
-			}
-			break;
-		}
-
-		st->i2c_gate = 4;
-		adap->fe_adap[0].fe = dvb_attach(stv0299_attach,
-				&sharp_z0194_config, &adap->dev->i2c_adap);
-		if (adap->fe_adap[0].fe) {
-			info("FE Found Stv0299");
-			st->i2c_tuner_gate_w = 4;
-			st->i2c_tuner_gate_r = 5;
-			st->i2c_tuner_addr = 0xc0;
-			st->tuner_config = TUNER_S0194;
-			if (dvb_usb_lme2510_firmware != TUNER_S0194) {
-				dvb_usb_lme2510_firmware = TUNER_S0194;
-				ret = lme_firmware_switch(adap->dev->udev, 1);
-			}
-			break;
-		}
-
-		st->i2c_gate = 5;
-		adap->fe_adap[0].fe = dvb_attach(stv0288_attach, &lme_config,
-			&adap->dev->i2c_adap);
-
-		if (adap->fe_adap[0].fe) {
-			info("FE Found Stv0288");
-			st->i2c_tuner_gate_w = 4;
-			st->i2c_tuner_gate_r = 5;
-			st->i2c_tuner_addr = 0xc0;
-			st->tuner_config = TUNER_S7395;
-			if (dvb_usb_lme2510_firmware != TUNER_S7395) {
-				dvb_usb_lme2510_firmware = TUNER_S7395;
-				ret = lme_firmware_switch(adap->dev->udev, 1);
-			}
-			break;
-		}
-	case 0x22f0:
-		st->i2c_gate = 5;
-		adap->fe_adap[0].fe = dvb_attach(m88rs2000_attach,
-			&m88rs2000_config, &adap->dev->i2c_adap);
-
-		if (adap->fe_adap[0].fe) {
-			info("FE Found M88RS2000");
-			st->i2c_tuner_gate_w = 5;
-			st->i2c_tuner_gate_r = 5;
-			st->i2c_tuner_addr = 0xc0;
-			st->tuner_config = TUNER_RS2000;
-			adap->fe_adap[0].fe->ops.read_signal_strength =
-				dm04_rs2000_read_signal_strength;
-			adap->fe_adap[0].fe->ops.read_snr =
-				dm04_rs2000_read_snr;
-		}
-		break;
-	}
-
-	if (adap->fe_adap[0].fe == NULL) {
-			info("DM04/QQBOX Not Powered up or not Supported");
-			return -ENODEV;
-	}
-
-	if (ret) {
-		if (adap->fe_adap[0].fe) {
-			dvb_frontend_detach(adap->fe_adap[0].fe);
-			adap->fe_adap[0].fe = NULL;
-		}
-		adap->dev->props.rc.core.rc_codes = NULL;
-		return -ENODEV;
-	}
-
-	adap->fe_adap[0].fe->ops.set_voltage = dm04_lme2510_set_voltage;
-	ret = lme_name(adap);
-	return ret;
-}
-
-static int dm04_lme2510_tuner(struct dvb_usb_adapter *adap)
-{
-	struct lme2510_state *st = adap->dev->priv;
-	char *tun_msg[] = {"", "TDA8263", "IX2505V", "DVB_PLL_OPERA", "RS2000"};
-	int ret = 0;
-
-	switch (st->tuner_config) {
-	case TUNER_LG:
-		if (dvb_attach(tda826x_attach, adap->fe_adap[0].fe, 0xc0,
-			&adap->dev->i2c_adap, 1))
-			ret = st->tuner_config;
-		break;
-	case TUNER_S7395:
-		if (dvb_attach(ix2505v_attach , adap->fe_adap[0].fe, &lme_tuner,
-			&adap->dev->i2c_adap))
-			ret = st->tuner_config;
-		break;
-	case TUNER_S0194:
-		if (dvb_attach(dvb_pll_attach , adap->fe_adap[0].fe, 0xc0,
-			&adap->dev->i2c_adap, DVB_PLL_OPERA1))
-			ret = st->tuner_config;
-		break;
-	case TUNER_RS2000:
-		ret = st->tuner_config;
-		break;
-	default:
-		break;
-	}
-
-	if (ret)
-		info("TUN Found %s tuner", tun_msg[ret]);
-	else {
-		info("TUN No tuner found --- resetting device");
-		lme_coldreset(adap->dev->udev);
-		return -ENODEV;
-	}
-
-	/* Start the Interrupt*/
-	ret = lme2510_int_read(adap);
-	if (ret < 0) {
-		info("INT Unable to start Interrupt Service");
-		return -ENODEV;
-	}
-
-	return ret;
-}
-
-static int lme2510_powerup(struct dvb_usb_device *d, int onoff)
-{
-	struct lme2510_state *st = d->priv;
-	static u8 lnb_on[] = LNB_ON;
-	static u8 lnb_off[] = LNB_OFF;
-	static u8 rbuf[1];
-	int ret = 0, len = 3, rlen = 1;
-
-	mutex_lock(&d->i2c_mutex);
-
-	if (onoff)
-		ret = lme2510_usb_talk(d, lnb_on, len, rbuf, rlen);
-	else
-		ret = lme2510_usb_talk(d, lnb_off, len, rbuf, rlen);
-
-	st->i2c_talk_onoff = 1;
-
-	mutex_unlock(&d->i2c_mutex);
-
-	return ret;
-}
-
-/* DVB USB Driver stuff */
-static struct dvb_usb_device_properties lme2510_properties;
-static struct dvb_usb_device_properties lme2510c_properties;
-
-static int lme2510_probe(struct usb_interface *intf,
-		const struct usb_device_id *id)
-{
-	struct usb_device *udev = interface_to_usbdev(intf);
-
-	usb_reset_configuration(udev);
-
-	usb_set_interface(udev, intf->cur_altsetting->desc.bInterfaceNumber, 1);
-
-	if (udev->speed != USB_SPEED_HIGH) {
-		usb_reset_device(udev);
-		info("DEV Failed to connect in HIGH SPEED mode");
-		return -ENODEV;
-	}
-
-	if (lme2510_return_status(udev) == 0x44) {
-		lme_firmware_switch(udev, 0);
-		return -ENODEV;
-	}
-
-	if (0 == dvb_usb_device_init(intf, &lme2510_properties,
-				     THIS_MODULE, NULL, adapter_nr)) {
-		info("DEV registering device driver");
-		return 0;
-	}
-	if (0 == dvb_usb_device_init(intf, &lme2510c_properties,
-				     THIS_MODULE, NULL, adapter_nr)) {
-		info("DEV registering device driver");
-		return 0;
-	}
-
-	info("DEV lme2510 Error");
-	return -ENODEV;
-
-}
-
-static struct usb_device_id lme2510_table[] = {
-	{ USB_DEVICE(0x3344, 0x1122) },  /* LME2510 */
-	{ USB_DEVICE(0x3344, 0x1120) },  /* LME2510C */
-	{ USB_DEVICE(0x3344, 0x22f0) },  /* LME2510C RS2000 */
-	{}		/* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE(usb, lme2510_table);
-
-static struct dvb_usb_device_properties lme2510_properties = {
-	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
-	.size_of_priv = sizeof(struct lme2510_state),
-	.num_adapters = 1,
-	.adapter = {
-		{
-		.num_frontends = 1,
-		.fe = {{
-			.caps = DVB_USB_ADAP_HAS_PID_FILTER|
-				DVB_USB_ADAP_NEED_PID_FILTERING|
-				DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
-			.streaming_ctrl   = lme2510_streaming_ctrl,
-			.pid_filter_count = 32,
-			.pid_filter = lme2510_pid_filter,
-			.pid_filter_ctrl  = lme2510_pid_filter_ctrl,
-			.frontend_attach  = dm04_lme2510_frontend_attach,
-			.tuner_attach = dm04_lme2510_tuner,
-			/* parameter for the MPEG2-data transfer */
-			.stream = {
-				.type = USB_BULK,
-				.count = 10,
-				.endpoint = 0x06,
-				.u = {
-					.bulk = {
-						.buffersize = 4096,
-
-					}
-				}
-			}
-		}},
-		}
-	},
-	.rc.core = {
-		.protocol	= RC_TYPE_NEC,
-		.module_name	= "LME2510 Remote Control",
-		.allowed_protos	= RC_TYPE_NEC,
-		.rc_codes	= RC_MAP_LME2510,
-	},
-	.power_ctrl       = lme2510_powerup,
-	.identify_state   = lme2510_identify_state,
-	.i2c_algo         = &lme2510_i2c_algo,
-	.generic_bulk_ctrl_endpoint = 0,
-	.num_device_descs = 1,
-	.devices = {
-		{   "DM04_LME2510_DVB-S",
-			{ &lme2510_table[0], NULL },
-			},
-
-	}
-};
-
-static struct dvb_usb_device_properties lme2510c_properties = {
-	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
-	.size_of_priv = sizeof(struct lme2510_state),
-	.num_adapters = 1,
-	.adapter = {
-		{
-		.num_frontends = 1,
-		.fe = {{
-			.caps = DVB_USB_ADAP_HAS_PID_FILTER|
-				DVB_USB_ADAP_NEED_PID_FILTERING|
-				DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
-			.streaming_ctrl   = lme2510_streaming_ctrl,
-			.pid_filter_count = 32,
-			.pid_filter = lme2510_pid_filter,
-			.pid_filter_ctrl  = lme2510_pid_filter_ctrl,
-			.frontend_attach  = dm04_lme2510_frontend_attach,
-			.tuner_attach = dm04_lme2510_tuner,
-			/* parameter for the MPEG2-data transfer */
-			.stream = {
-				.type = USB_BULK,
-				.count = 10,
-				.endpoint = 0x8,
-				.u = {
-					.bulk = {
-						.buffersize = 4096,
-
-					}
-				}
-			}
-		}},
-		}
-	},
-	.rc.core = {
-		.protocol	= RC_TYPE_NEC,
-		.module_name	= "LME2510 Remote Control",
-		.allowed_protos	= RC_TYPE_NEC,
-		.rc_codes	= RC_MAP_LME2510,
-	},
-	.power_ctrl       = lme2510_powerup,
-	.identify_state   = lme2510_identify_state,
-	.i2c_algo         = &lme2510_i2c_algo,
-	.generic_bulk_ctrl_endpoint = 0,
-	.num_device_descs = 2,
-	.devices = {
-		{   "DM04_LME2510C_DVB-S",
-			{ &lme2510_table[1], NULL },
-			},
-		{   "DM04_LME2510C_DVB-S RS2000",
-			{ &lme2510_table[2], NULL },
-			},
-	}
-};
-
-static void *lme2510_exit_int(struct dvb_usb_device *d)
-{
-	struct lme2510_state *st = d->priv;
-	struct dvb_usb_adapter *adap = &d->adapter[0];
-	void *buffer = NULL;
-
-	if (adap != NULL) {
-		lme2510_kill_urb(&adap->fe_adap[0].stream);
-		adap->feedcount = 0;
-	}
-
-	if (st->usb_buffer != NULL) {
-		st->i2c_talk_onoff = 1;
-		st->signal_lock = 0;
-		st->signal_level = 0;
-		st->signal_sn = 0;
-		buffer = st->usb_buffer;
-	}
-
-	if (st->lme_urb != NULL) {
-		usb_kill_urb(st->lme_urb);
-		usb_free_coherent(d->udev, 128, st->buffer,
-				  st->lme_urb->transfer_dma);
-		info("Interrupt Service Stopped");
-	}
-
-	return buffer;
-}
-
-static void lme2510_exit(struct usb_interface *intf)
-{
-	struct dvb_usb_device *d = usb_get_intfdata(intf);
-	void *usb_buffer;
-
-	if (d != NULL) {
-		usb_buffer = lme2510_exit_int(d);
-		dvb_usb_device_exit(intf);
-		if (usb_buffer != NULL)
-			kfree(usb_buffer);
-	}
-}
-
-static struct usb_driver lme2510_driver = {
-	.name		= "LME2510C_DVB-S",
-	.probe		= lme2510_probe,
-	.disconnect	= lme2510_exit,
-	.id_table	= lme2510_table,
-};
-
-module_usb_driver(lme2510_driver);
-
-MODULE_AUTHOR("Malcolm Priestley <tvboxspy@gmail.com>");
-MODULE_DESCRIPTION("LME2510(C) DVB-S USB2.0");
-MODULE_VERSION("1.99");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/lmedm04.h b/drivers/media/dvb/dvb-usb/lmedm04.h
deleted file mode 100644
index e9c2072..0000000
--- a/drivers/media/dvb/dvb-usb/lmedm04.h
+++ /dev/null
@@ -1,175 +0,0 @@
-/* DVB USB compliant linux driver for
- *
- * DM04/QQBOX DVB-S USB BOX	LME2510C + SHARP:BS2F7HZ7395
- *				LME2510C + LG TDQY-P001F
- *				LME2510 + LG TDQY-P001F
- *
- * MVB7395 (LME2510C+SHARP:BS2F7HZ7395)
- * SHARP:BS2F7HZ7395 = (STV0288+Sharp IX2505V)
- *
- * MVB001F (LME2510+LGTDQT-P001F)
- * LG TDQY - P001F =(TDA8263 + TDA10086H)
- *
- * MVB0001F (LME2510C+LGTDQT-P001F)
- *
- * This program is free software; 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.
- * *
- * see Documentation/dvb/README.dvb-usb for more information
- */
-#ifndef _DVB_USB_LME2510_H_
-#define _DVB_USB_LME2510_H_
-
-/* Streamer &  PID
- *
- * Note:	These commands do not actually stop the streaming
- *		but form some kind of packet filtering/stream count
- *		or tuning related functions.
- *  06 XX
- *  offset 1 = 00 Enable Streaming
- *
- *
- *  PID
- *  03 XX XX  ----> reg number ---> setting....20 XX
- *  offset 1 = length
- *  offset 2 = start of data
- *  end byte -1 = 20
- *  end byte = clear pid always a0, other wise 9c, 9a ??
- *
-*/
-#define LME_ST_ON_W	{0x06, 0x00}
-#define LME_CLEAR_PID   {0x03, 0x02, 0x20, 0xa0}
-#define LME_ZERO_PID	{0x03, 0x06, 0x00, 0x00, 0x01, 0x00, 0x20, 0x9c}
-#define LME_ALL_PIDS	{0x03, 0x06, 0x00, 0xff, 0x01, 0x1f, 0x20, 0x81}
-
-/*  LNB Voltage
- *  07 XX XX
- *  offset 1 = 01
- *  offset 2 = 00=Voltage low 01=Voltage high
- *
- *  LNB Power
- *  03 01 XX
- *  offset 2 = 00=ON 01=OFF
- */
-
-#define LME_VOLTAGE_L	{0x07, 0x01, 0x00}
-#define LME_VOLTAGE_H	{0x07, 0x01, 0x01}
-#define LNB_ON		{0x3a, 0x01, 0x00}
-#define LNB_OFF		{0x3a, 0x01, 0x01}
-
-/* Initial stv0288 settings for 7395 Frontend */
-static u8 s7395_inittab[] = {
-	0x01, 0x15,
-	0x02, 0x20,
-	0x03, 0xa0,
-	0x04, 0xa0,
-	0x05, 0x12,
-	0x06, 0x00,
-	0x09, 0x00,
-	0x0a, 0x04,
-	0x0b, 0x00,
-	0x0c, 0x00,
-	0x0d, 0x00,
-	0x0e, 0xc1,
-	0x0f, 0x54,
-	0x11, 0x7a,
-	0x12, 0x03,
-	0x13, 0x48,
-	0x14, 0x84,
-	0x15, 0xc5,
-	0x16, 0xb8,
-	0x17, 0x9c,
-	0x18, 0x00,
-	0x19, 0xa6,
-	0x1a, 0x88,
-	0x1b, 0x8f,
-	0x1c, 0xf0,
-	0x20, 0x0b,
-	0x21, 0x54,
-	0x22, 0xff,
-	0x23, 0x01,
-	0x28, 0x46,
-	0x29, 0x66,
-	0x2a, 0x90,
-	0x2b, 0xfa,
-	0x2c, 0xd9,
-	0x30, 0x0,
-	0x31, 0x1e,
-	0x32, 0x14,
-	0x33, 0x0f,
-	0x34, 0x09,
-	0x35, 0x0c,
-	0x36, 0x05,
-	0x37, 0x2f,
-	0x38, 0x16,
-	0x39, 0xbd,
-	0x3a, 0x0,
-	0x3b, 0x13,
-	0x3c, 0x11,
-	0x3d, 0x30,
-	0x40, 0x63,
-	0x41, 0x04,
-	0x42, 0x20,
-	0x43, 0x00,
-	0x44, 0x00,
-	0x45, 0x00,
-	0x46, 0x00,
-	0x47, 0x00,
-	0x4a, 0x00,
-	0x50, 0x10,
-	0x51, 0x36,
-	0x52, 0x21,
-	0x53, 0x94,
-	0x54, 0xb2,
-	0x55, 0x29,
-	0x56, 0x64,
-	0x57, 0x2b,
-	0x58, 0x54,
-	0x59, 0x86,
-	0x5a, 0x00,
-	0x5b, 0x9b,
-	0x5c, 0x08,
-	0x5d, 0x7f,
-	0x5e, 0xff,
-	0x5f, 0x8d,
-	0x70, 0x0,
-	0x71, 0x0,
-	0x72, 0x0,
-	0x74, 0x0,
-	0x75, 0x0,
-	0x76, 0x0,
-	0x81, 0x0,
-	0x82, 0x3f,
-	0x83, 0x3f,
-	0x84, 0x0,
-	0x85, 0x0,
-	0x88, 0x0,
-	0x89, 0x0,
-	0x8a, 0x0,
-	0x8b, 0x0,
-	0x8c, 0x0,
-	0x90, 0x0,
-	0x91, 0x0,
-	0x92, 0x0,
-	0x93, 0x0,
-	0x94, 0x1c,
-	0x97, 0x0,
-	0xa0, 0x48,
-	0xa1, 0x0,
-	0xb0, 0xb8,
-	0xb1, 0x3a,
-	0xb2, 0x10,
-	0xb3, 0x82,
-	0xb4, 0x80,
-	0xb5, 0x82,
-	0xb6, 0x82,
-	0xb7, 0x82,
-	0xb8, 0x20,
-	0xb9, 0x0,
-	0xf0, 0x0,
-	0xf1, 0x0,
-	0xf2, 0xc0,
-	0xff, 0xff,
-};
-#endif
diff --git a/drivers/media/dvb/dvb-usb/m920x.c b/drivers/media/dvb/dvb-usb/m920x.c
deleted file mode 100644
index 288af29..0000000
--- a/drivers/media/dvb/dvb-usb/m920x.c
+++ /dev/null
@@ -1,1099 +0,0 @@
-/* DVB USB compliant linux driver for MSI Mega Sky 580 DVB-T USB2.0 receiver
- *
- * Copyright (C) 2006 Aapo Tahkola (aet@rasterburn.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, version 2.
- *
- * see Documentation/dvb/README.dvb-usb for more information
- */
-
-#include "m920x.h"
-
-#include "mt352.h"
-#include "mt352_priv.h"
-#include "qt1010.h"
-#include "tda1004x.h"
-#include "tda827x.h"
-
-#include <media/tuner.h>
-#include "tuner-simple.h"
-#include <asm/unaligned.h>
-
-/* debug */
-static int dvb_usb_m920x_debug;
-module_param_named(debug,dvb_usb_m920x_debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS);
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-static int m920x_set_filter(struct dvb_usb_device *d, int type, int idx, int pid);
-
-static inline int m920x_read(struct usb_device *udev, u8 request, u16 value,
-			     u16 index, void *data, int size)
-{
-	int ret;
-
-	ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
-			      request, USB_TYPE_VENDOR | USB_DIR_IN,
-			      value, index, data, size, 2000);
-	if (ret < 0) {
-		printk(KERN_INFO "m920x_read = error: %d\n", ret);
-		return ret;
-	}
-
-	if (ret != size) {
-		deb("m920x_read = no data\n");
-		return -EIO;
-	}
-
-	return 0;
-}
-
-static inline int m920x_write(struct usb_device *udev, u8 request,
-			      u16 value, u16 index)
-{
-	int ret;
-
-	ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
-			      request, USB_TYPE_VENDOR | USB_DIR_OUT,
-			      value, index, NULL, 0, 2000);
-
-	return ret;
-}
-
-static int m920x_init(struct dvb_usb_device *d, struct m920x_inits *rc_seq)
-{
-	int ret = 0, i, epi, flags = 0;
-	int adap_enabled[M9206_MAX_ADAPTERS] = { 0 };
-
-	/* Remote controller init. */
-	if (d->props.rc.legacy.rc_query) {
-		deb("Initialising remote control\n");
-		while (rc_seq->address) {
-			if ((ret = m920x_write(d->udev, M9206_CORE,
-					       rc_seq->data,
-					       rc_seq->address)) != 0) {
-				deb("Initialising remote control failed\n");
-				return ret;
-			}
-
-			rc_seq++;
-		}
-
-		deb("Initialising remote control success\n");
-	}
-
-	for (i = 0; i < d->props.num_adapters; i++)
-		flags |= d->adapter[i].props.fe[0].caps;
-
-	/* Some devices(Dposh) might crash if we attempt touch at all. */
-	if (flags & DVB_USB_ADAP_HAS_PID_FILTER) {
-		for (i = 0; i < d->props.num_adapters; i++) {
-			epi = d->adapter[i].props.fe[0].stream.endpoint - 0x81;
-
-			if (epi < 0 || epi >= M9206_MAX_ADAPTERS) {
-				printk(KERN_INFO "m920x: Unexpected adapter endpoint!\n");
-				return -EINVAL;
-			}
-
-			adap_enabled[epi] = 1;
-		}
-
-		for (i = 0; i < M9206_MAX_ADAPTERS; i++) {
-			if (adap_enabled[i])
-				continue;
-
-			if ((ret = m920x_set_filter(d, 0x81 + i, 0, 0x0)) != 0)
-				return ret;
-
-			if ((ret = m920x_set_filter(d, 0x81 + i, 0, 0x02f5)) != 0)
-				return ret;
-		}
-	}
-
-	return ret;
-}
-
-static int m920x_init_ep(struct usb_interface *intf)
-{
-	struct usb_device *udev = interface_to_usbdev(intf);
-	struct usb_host_interface *alt;
-
-	if ((alt = usb_altnum_to_altsetting(intf, 1)) == NULL) {
-		deb("No alt found!\n");
-		return -ENODEV;
-	}
-
-	return usb_set_interface(udev, alt->desc.bInterfaceNumber,
-				 alt->desc.bAlternateSetting);
-}
-
-static int m920x_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
-{
-	struct m920x_state *m = d->priv;
-	int i, ret = 0;
-	u8 *rc_state;
-
-	rc_state = kmalloc(2, GFP_KERNEL);
-	if (!rc_state)
-		return -ENOMEM;
-
-	if ((ret = m920x_read(d->udev, M9206_CORE, 0x0, M9206_RC_STATE, rc_state, 1)) != 0)
-		goto out;
-
-	if ((ret = m920x_read(d->udev, M9206_CORE, 0x0, M9206_RC_KEY, rc_state + 1, 1)) != 0)
-		goto out;
-
-	for (i = 0; i < d->props.rc.legacy.rc_map_size; i++)
-		if (rc5_data(&d->props.rc.legacy.rc_map_table[i]) == rc_state[1]) {
-			*event = d->props.rc.legacy.rc_map_table[i].keycode;
-
-			switch(rc_state[0]) {
-			case 0x80:
-				*state = REMOTE_NO_KEY_PRESSED;
-				goto out;
-
-			case 0x88: /* framing error or "invalid code" */
-			case 0x99:
-			case 0xc0:
-			case 0xd8:
-				*state = REMOTE_NO_KEY_PRESSED;
-				m->rep_count = 0;
-				goto out;
-
-			case 0x93:
-			case 0x92:
-			case 0x83: /* pinnacle PCTV310e */
-			case 0x82:
-				m->rep_count = 0;
-				*state = REMOTE_KEY_PRESSED;
-				goto out;
-
-			case 0x91:
-			case 0x81: /* pinnacle PCTV310e */
-				/* prevent immediate auto-repeat */
-				if (++m->rep_count > 2)
-					*state = REMOTE_KEY_REPEAT;
-				else
-					*state = REMOTE_NO_KEY_PRESSED;
-				goto out;
-
-			default:
-				deb("Unexpected rc state %02x\n", rc_state[0]);
-				*state = REMOTE_NO_KEY_PRESSED;
-				goto out;
-			}
-		}
-
-	if (rc_state[1] != 0)
-		deb("Unknown rc key %02x\n", rc_state[1]);
-
-	*state = REMOTE_NO_KEY_PRESSED;
-
- out:
-	kfree(rc_state);
-	return ret;
-}
-
-/* I2C */
-static int m920x_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int num)
-{
-	struct dvb_usb_device *d = i2c_get_adapdata(adap);
-	int i, j;
-	int ret = 0;
-
-	if (!num)
-		return -EINVAL;
-
-	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
-		return -EAGAIN;
-
-	for (i = 0; i < num; i++) {
-		if (msg[i].flags & (I2C_M_NO_RD_ACK | I2C_M_IGNORE_NAK | I2C_M_TEN) || msg[i].len == 0) {
-			/* For a 0 byte message, I think sending the address
-			 * to index 0x80|0x40 would be the correct thing to
-			 * do.  However, zero byte messages are only used for
-			 * probing, and since we don't know how to get the
-			 * slave's ack, we can't probe. */
-			ret = -ENOTSUPP;
-			goto unlock;
-		}
-		/* Send START & address/RW bit */
-		if (!(msg[i].flags & I2C_M_NOSTART)) {
-			if ((ret = m920x_write(d->udev, M9206_I2C,
-					(msg[i].addr << 1) |
-					(msg[i].flags & I2C_M_RD ? 0x01 : 0), 0x80)) != 0)
-				goto unlock;
-			/* Should check for ack here, if we knew how. */
-		}
-		if (msg[i].flags & I2C_M_RD) {
-			for (j = 0; j < msg[i].len; j++) {
-				/* Last byte of transaction?
-				 * Send STOP, otherwise send ACK. */
-				int stop = (i+1 == num && j+1 == msg[i].len) ? 0x40 : 0x01;
-
-				if ((ret = m920x_read(d->udev, M9206_I2C, 0x0,
-						      0x20 | stop,
-						      &msg[i].buf[j], 1)) != 0)
-					goto unlock;
-			}
-		} else {
-			for (j = 0; j < msg[i].len; j++) {
-				/* Last byte of transaction? Then send STOP. */
-				int stop = (i+1 == num && j+1 == msg[i].len) ? 0x40 : 0x00;
-
-				if ((ret = m920x_write(d->udev, M9206_I2C, msg[i].buf[j], stop)) != 0)
-					goto unlock;
-				/* Should check for ack here too. */
-			}
-		}
-	}
-	ret = num;
-
- unlock:
-	mutex_unlock(&d->i2c_mutex);
-
-	return ret;
-}
-
-static u32 m920x_i2c_func(struct i2c_adapter *adapter)
-{
-	return I2C_FUNC_I2C;
-}
-
-static struct i2c_algorithm m920x_i2c_algo = {
-	.master_xfer   = m920x_i2c_xfer,
-	.functionality = m920x_i2c_func,
-};
-
-/* pid filter */
-static int m920x_set_filter(struct dvb_usb_device *d, int type, int idx, int pid)
-{
-	int ret = 0;
-
-	if (pid >= 0x8000)
-		return -EINVAL;
-
-	pid |= 0x8000;
-
-	if ((ret = m920x_write(d->udev, M9206_FILTER, pid, (type << 8) | (idx * 4) )) != 0)
-		return ret;
-
-	if ((ret = m920x_write(d->udev, M9206_FILTER, 0, (type << 8) | (idx * 4) )) != 0)
-		return ret;
-
-	return ret;
-}
-
-static int m920x_update_filters(struct dvb_usb_adapter *adap)
-{
-	struct m920x_state *m = adap->dev->priv;
-	int enabled = m->filtering_enabled[adap->id];
-	int i, ret = 0, filter = 0;
-	int ep = adap->props.fe[0].stream.endpoint;
-
-	for (i = 0; i < M9206_MAX_FILTERS; i++)
-		if (m->filters[adap->id][i] == 8192)
-			enabled = 0;
-
-	/* Disable all filters */
-	if ((ret = m920x_set_filter(adap->dev, ep, 1, enabled)) != 0)
-		return ret;
-
-	for (i = 0; i < M9206_MAX_FILTERS; i++)
-		if ((ret = m920x_set_filter(adap->dev, ep, i + 2, 0)) != 0)
-			return ret;
-
-	/* Set */
-	if (enabled) {
-		for (i = 0; i < M9206_MAX_FILTERS; i++) {
-			if (m->filters[adap->id][i] == 0)
-				continue;
-
-			if ((ret = m920x_set_filter(adap->dev, ep, filter + 2, m->filters[adap->id][i])) != 0)
-				return ret;
-
-			filter++;
-		}
-	}
-
-	return ret;
-}
-
-static int m920x_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff)
-{
-	struct m920x_state *m = adap->dev->priv;
-
-	m->filtering_enabled[adap->id] = onoff ? 1 : 0;
-
-	return m920x_update_filters(adap);
-}
-
-static int m920x_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, int onoff)
-{
-	struct m920x_state *m = adap->dev->priv;
-
-	m->filters[adap->id][index] = onoff ? pid : 0;
-
-	return m920x_update_filters(adap);
-}
-
-static int m920x_firmware_download(struct usb_device *udev, const struct firmware *fw)
-{
-	u16 value, index, size;
-	u8 *read, *buff;
-	int i, pass, ret = 0;
-
-	buff = kmalloc(65536, GFP_KERNEL);
-	if (buff == NULL)
-		return -ENOMEM;
-
-	read = kmalloc(4, GFP_KERNEL);
-	if (!read) {
-		kfree(buff);
-		return -ENOMEM;
-	}
-
-	if ((ret = m920x_read(udev, M9206_FILTER, 0x0, 0x8000, read, 4)) != 0)
-		goto done;
-	deb("%x %x %x %x\n", read[0], read[1], read[2], read[3]);
-
-	if ((ret = m920x_read(udev, M9206_FW, 0x0, 0x0, read, 1)) != 0)
-		goto done;
-	deb("%x\n", read[0]);
-
-	for (pass = 0; pass < 2; pass++) {
-		for (i = 0; i + (sizeof(u16) * 3) < fw->size;) {
-			value = get_unaligned_le16(fw->data + i);
-			i += sizeof(u16);
-
-			index = get_unaligned_le16(fw->data + i);
-			i += sizeof(u16);
-
-			size = get_unaligned_le16(fw->data + i);
-			i += sizeof(u16);
-
-			if (pass == 1) {
-				/* Will stall if using fw->data ... */
-				memcpy(buff, fw->data + i, size);
-
-				ret = usb_control_msg(udev, usb_sndctrlpipe(udev,0),
-						      M9206_FW,
-						      USB_TYPE_VENDOR | USB_DIR_OUT,
-						      value, index, buff, size, 20);
-				if (ret != size) {
-					deb("error while uploading fw!\n");
-					ret = -EIO;
-					goto done;
-				}
-				msleep(3);
-			}
-			i += size;
-		}
-		if (i != fw->size) {
-			deb("bad firmware file!\n");
-			ret = -EINVAL;
-			goto done;
-		}
-	}
-
-	msleep(36);
-
-	/* m920x will disconnect itself from the bus after this. */
-	(void) m920x_write(udev, M9206_CORE, 0x01, M9206_FW_GO);
-	deb("firmware uploaded!\n");
-
- done:
-	kfree(read);
-	kfree(buff);
-
-	return ret;
-}
-
-/* Callbacks for DVB USB */
-static int m920x_identify_state(struct usb_device *udev,
-				struct dvb_usb_device_properties *props,
-				struct dvb_usb_device_description **desc,
-				int *cold)
-{
-	struct usb_host_interface *alt;
-
-	alt = usb_altnum_to_altsetting(usb_ifnum_to_if(udev, 0), 1);
-	*cold = (alt == NULL) ? 1 : 0;
-
-	return 0;
-}
-
-/* demod configurations */
-static int m920x_mt352_demod_init(struct dvb_frontend *fe)
-{
-	int ret;
-	u8 config[] = { CONFIG, 0x3d };
-	u8 clock[] = { CLOCK_CTL, 0x30 };
-	u8 reset[] = { RESET, 0x80 };
-	u8 adc_ctl[] = { ADC_CTL_1, 0x40 };
-	u8 agc[] = { AGC_TARGET, 0x1c, 0x20 };
-	u8 sec_agc[] = { 0x69, 0x00, 0xff, 0xff, 0x40, 0xff, 0x00, 0x40, 0x40 };
-	u8 unk1[] = { 0x93, 0x1a };
-	u8 unk2[] = { 0xb5, 0x7a };
-
-	deb("Demod init!\n");
-
-	if ((ret = mt352_write(fe, config, ARRAY_SIZE(config))) != 0)
-		return ret;
-	if ((ret = mt352_write(fe, clock, ARRAY_SIZE(clock))) != 0)
-		return ret;
-	if ((ret = mt352_write(fe, reset, ARRAY_SIZE(reset))) != 0)
-		return ret;
-	if ((ret = mt352_write(fe, adc_ctl, ARRAY_SIZE(adc_ctl))) != 0)
-		return ret;
-	if ((ret = mt352_write(fe, agc, ARRAY_SIZE(agc))) != 0)
-		return ret;
-	if ((ret = mt352_write(fe, sec_agc, ARRAY_SIZE(sec_agc))) != 0)
-		return ret;
-	if ((ret = mt352_write(fe, unk1, ARRAY_SIZE(unk1))) != 0)
-		return ret;
-	if ((ret = mt352_write(fe, unk2, ARRAY_SIZE(unk2))) != 0)
-		return ret;
-
-	return 0;
-}
-
-static struct mt352_config m920x_mt352_config = {
-	.demod_address = 0x0f,
-	.no_tuner = 1,
-	.demod_init = m920x_mt352_demod_init,
-};
-
-static struct tda1004x_config m920x_tda10046_08_config = {
-	.demod_address = 0x08,
-	.invert = 0,
-	.invert_oclk = 0,
-	.ts_mode = TDA10046_TS_SERIAL,
-	.xtal_freq = TDA10046_XTAL_16M,
-	.if_freq = TDA10046_FREQ_045,
-	.agc_config = TDA10046_AGC_TDA827X,
-	.gpio_config = TDA10046_GPTRI,
-	.request_firmware = NULL,
-};
-
-static struct tda1004x_config m920x_tda10046_0b_config = {
-	.demod_address = 0x0b,
-	.invert = 0,
-	.invert_oclk = 0,
-	.ts_mode = TDA10046_TS_SERIAL,
-	.xtal_freq = TDA10046_XTAL_16M,
-	.if_freq = TDA10046_FREQ_045,
-	.agc_config = TDA10046_AGC_TDA827X,
-	.gpio_config = TDA10046_GPTRI,
-	.request_firmware = NULL, /* uses firmware EEPROM */
-};
-
-/* tuner configurations */
-static struct qt1010_config m920x_qt1010_config = {
-	.i2c_address = 0x62
-};
-
-/* Callbacks for DVB USB */
-static int m920x_mt352_frontend_attach(struct dvb_usb_adapter *adap)
-{
-	deb("%s\n",__func__);
-
-	adap->fe_adap[0].fe = dvb_attach(mt352_attach,
-					 &m920x_mt352_config,
-					 &adap->dev->i2c_adap);
-	if ((adap->fe_adap[0].fe) == NULL)
-		return -EIO;
-
-	return 0;
-}
-
-static int m920x_tda10046_08_frontend_attach(struct dvb_usb_adapter *adap)
-{
-	deb("%s\n",__func__);
-
-	adap->fe_adap[0].fe = dvb_attach(tda10046_attach,
-					 &m920x_tda10046_08_config,
-					 &adap->dev->i2c_adap);
-	if ((adap->fe_adap[0].fe) == NULL)
-		return -EIO;
-
-	return 0;
-}
-
-static int m920x_tda10046_0b_frontend_attach(struct dvb_usb_adapter *adap)
-{
-	deb("%s\n",__func__);
-
-	adap->fe_adap[0].fe = dvb_attach(tda10046_attach,
-					 &m920x_tda10046_0b_config,
-					 &adap->dev->i2c_adap);
-	if ((adap->fe_adap[0].fe) == NULL)
-		return -EIO;
-
-	return 0;
-}
-
-static int m920x_qt1010_tuner_attach(struct dvb_usb_adapter *adap)
-{
-	deb("%s\n",__func__);
-
-	if (dvb_attach(qt1010_attach, adap->fe_adap[0].fe, &adap->dev->i2c_adap, &m920x_qt1010_config) == NULL)
-		return -ENODEV;
-
-	return 0;
-}
-
-static int m920x_tda8275_60_tuner_attach(struct dvb_usb_adapter *adap)
-{
-	deb("%s\n",__func__);
-
-	if (dvb_attach(tda827x_attach, adap->fe_adap[0].fe, 0x60, &adap->dev->i2c_adap, NULL) == NULL)
-		return -ENODEV;
-
-	return 0;
-}
-
-static int m920x_tda8275_61_tuner_attach(struct dvb_usb_adapter *adap)
-{
-	deb("%s\n",__func__);
-
-	if (dvb_attach(tda827x_attach, adap->fe_adap[0].fe, 0x61, &adap->dev->i2c_adap, NULL) == NULL)
-		return -ENODEV;
-
-	return 0;
-}
-
-static int m920x_fmd1216me_tuner_attach(struct dvb_usb_adapter *adap)
-{
-	dvb_attach(simple_tuner_attach, adap->fe_adap[0].fe,
-		   &adap->dev->i2c_adap, 0x61,
-		   TUNER_PHILIPS_FMD1216ME_MK3);
-	return 0;
-}
-
-/* device-specific initialization */
-static struct m920x_inits megasky_rc_init [] = {
-	{ M9206_RC_INIT2, 0xa8 },
-	{ M9206_RC_INIT1, 0x51 },
-	{ } /* terminating entry */
-};
-
-static struct m920x_inits tvwalkertwin_rc_init [] = {
-	{ M9206_RC_INIT2, 0x00 },
-	{ M9206_RC_INIT1, 0xef },
-	{ 0xff28,         0x00 },
-	{ 0xff23,         0x00 },
-	{ 0xff21,         0x30 },
-	{ } /* terminating entry */
-};
-
-static struct m920x_inits pinnacle310e_init[] = {
-	/* without these the tuner don't work */
-	{ 0xff20,         0x9b },
-	{ 0xff22,         0x70 },
-
-	/* rc settings */
-	{ 0xff50,         0x80 },
-	{ M9206_RC_INIT1, 0x00 },
-	{ M9206_RC_INIT2, 0xff },
-	{ } /* terminating entry */
-};
-
-/* ir keymaps */
-static struct rc_map_table rc_map_megasky_table[] = {
-	{ 0x0012, KEY_POWER },
-	{ 0x001e, KEY_CYCLEWINDOWS }, /* min/max */
-	{ 0x0002, KEY_CHANNELUP },
-	{ 0x0005, KEY_CHANNELDOWN },
-	{ 0x0003, KEY_VOLUMEUP },
-	{ 0x0006, KEY_VOLUMEDOWN },
-	{ 0x0004, KEY_MUTE },
-	{ 0x0007, KEY_OK }, /* TS */
-	{ 0x0008, KEY_STOP },
-	{ 0x0009, KEY_MENU }, /* swap */
-	{ 0x000a, KEY_REWIND },
-	{ 0x001b, KEY_PAUSE },
-	{ 0x001f, KEY_FASTFORWARD },
-	{ 0x000c, KEY_RECORD },
-	{ 0x000d, KEY_CAMERA }, /* screenshot */
-	{ 0x000e, KEY_COFFEE }, /* "MTS" */
-};
-
-static struct rc_map_table rc_map_tvwalkertwin_table[] = {
-	{ 0x0001, KEY_ZOOM }, /* Full Screen */
-	{ 0x0002, KEY_CAMERA }, /* snapshot */
-	{ 0x0003, KEY_MUTE },
-	{ 0x0004, KEY_REWIND },
-	{ 0x0005, KEY_PLAYPAUSE }, /* Play/Pause */
-	{ 0x0006, KEY_FASTFORWARD },
-	{ 0x0007, KEY_RECORD },
-	{ 0x0008, KEY_STOP },
-	{ 0x0009, KEY_TIME }, /* Timeshift */
-	{ 0x000c, KEY_COFFEE }, /* Recall */
-	{ 0x000e, KEY_CHANNELUP },
-	{ 0x0012, KEY_POWER },
-	{ 0x0015, KEY_MENU }, /* source */
-	{ 0x0018, KEY_CYCLEWINDOWS }, /* TWIN PIP */
-	{ 0x001a, KEY_CHANNELDOWN },
-	{ 0x001b, KEY_VOLUMEDOWN },
-	{ 0x001e, KEY_VOLUMEUP },
-};
-
-static struct rc_map_table rc_map_pinnacle310e_table[] = {
-	{ 0x16, KEY_POWER },
-	{ 0x17, KEY_FAVORITES },
-	{ 0x0f, KEY_TEXT },
-	{ 0x48, KEY_PROGRAM },		/* preview */
-	{ 0x1c, KEY_EPG },
-	{ 0x04, KEY_LIST },		/* record list */
-	{ 0x03, KEY_1 },
-	{ 0x01, KEY_2 },
-	{ 0x06, KEY_3 },
-	{ 0x09, KEY_4 },
-	{ 0x1d, KEY_5 },
-	{ 0x1f, KEY_6 },
-	{ 0x0d, KEY_7 },
-	{ 0x19, KEY_8 },
-	{ 0x1b, KEY_9 },
-	{ 0x15, KEY_0 },
-	{ 0x0c, KEY_CANCEL },
-	{ 0x4a, KEY_CLEAR },
-	{ 0x13, KEY_BACK },
-	{ 0x00, KEY_TAB },
-	{ 0x4b, KEY_UP },
-	{ 0x4e, KEY_LEFT },
-	{ 0x52, KEY_RIGHT },
-	{ 0x51, KEY_DOWN },
-	{ 0x4f, KEY_ENTER },		/* could also be KEY_OK */
-	{ 0x1e, KEY_VOLUMEUP },
-	{ 0x0a, KEY_VOLUMEDOWN },
-	{ 0x05, KEY_CHANNELUP },
-	{ 0x02, KEY_CHANNELDOWN },
-	{ 0x11, KEY_RECORD },
-	{ 0x14, KEY_PLAY },
-	{ 0x4c, KEY_PAUSE },
-	{ 0x1a, KEY_STOP },
-	{ 0x40, KEY_REWIND },
-	{ 0x12, KEY_FASTFORWARD },
-	{ 0x41, KEY_PREVIOUSSONG },	/* Replay */
-	{ 0x42, KEY_NEXTSONG },		/* Skip */
-	{ 0x54, KEY_CAMERA },		/* Capture */
-/*	{ 0x50, KEY_SAP },	*/		/* Sap */
-	{ 0x47, KEY_CYCLEWINDOWS },	/* Pip */
-	{ 0x4d, KEY_SCREEN },		/* FullScreen */
-	{ 0x08, KEY_SUBTITLE },
-	{ 0x0e, KEY_MUTE },
-/*	{ 0x49, KEY_LR },	*/		/* L/R */
-	{ 0x07, KEY_SLEEP },		/* Hibernate */
-	{ 0x08, KEY_VIDEO },		/* A/V */
-	{ 0x0e, KEY_MENU },		/* Recall */
-	{ 0x45, KEY_ZOOMIN },
-	{ 0x46, KEY_ZOOMOUT },
-	{ 0x18, KEY_RED },		/* Red */
-	{ 0x53, KEY_GREEN },		/* Green */
-	{ 0x5e, KEY_YELLOW },		/* Yellow */
-	{ 0x5f, KEY_BLUE },		/* Blue */
-};
-
-/* DVB USB Driver stuff */
-static struct dvb_usb_device_properties megasky_properties;
-static struct dvb_usb_device_properties digivox_mini_ii_properties;
-static struct dvb_usb_device_properties tvwalkertwin_properties;
-static struct dvb_usb_device_properties dposh_properties;
-static struct dvb_usb_device_properties pinnacle_pctv310e_properties;
-
-static int m920x_probe(struct usb_interface *intf,
-		       const struct usb_device_id *id)
-{
-	struct dvb_usb_device *d = NULL;
-	int ret;
-	struct m920x_inits *rc_init_seq = NULL;
-	int bInterfaceNumber = intf->cur_altsetting->desc.bInterfaceNumber;
-
-	deb("Probing for m920x device at interface %d\n", bInterfaceNumber);
-
-	if (bInterfaceNumber == 0) {
-		/* Single-tuner device, or first interface on
-		 * multi-tuner device
-		 */
-
-		ret = dvb_usb_device_init(intf, &megasky_properties,
-					  THIS_MODULE, &d, adapter_nr);
-		if (ret == 0) {
-			rc_init_seq = megasky_rc_init;
-			goto found;
-		}
-
-		ret = dvb_usb_device_init(intf, &digivox_mini_ii_properties,
-					  THIS_MODULE, &d, adapter_nr);
-		if (ret == 0) {
-			/* No remote control, so no rc_init_seq */
-			goto found;
-		}
-
-		/* This configures both tuners on the TV Walker Twin */
-		ret = dvb_usb_device_init(intf, &tvwalkertwin_properties,
-					  THIS_MODULE, &d, adapter_nr);
-		if (ret == 0) {
-			rc_init_seq = tvwalkertwin_rc_init;
-			goto found;
-		}
-
-		ret = dvb_usb_device_init(intf, &dposh_properties,
-					  THIS_MODULE, &d, adapter_nr);
-		if (ret == 0) {
-			/* Remote controller not supported yet. */
-			goto found;
-		}
-
-		ret = dvb_usb_device_init(intf, &pinnacle_pctv310e_properties,
-					  THIS_MODULE, &d, adapter_nr);
-		if (ret == 0) {
-			rc_init_seq = pinnacle310e_init;
-			goto found;
-		}
-
-		return ret;
-	} else {
-		/* Another interface on a multi-tuner device */
-
-		/* The LifeView TV Walker Twin gets here, but struct
-		 * tvwalkertwin_properties already configured both
-		 * tuners, so there is nothing for us to do here
-		 */
-	}
-
- found:
-	if ((ret = m920x_init_ep(intf)) < 0)
-		return ret;
-
-	if (d && (ret = m920x_init(d, rc_init_seq)) != 0)
-		return ret;
-
-	return ret;
-}
-
-static struct usb_device_id m920x_table [] = {
-		{ USB_DEVICE(USB_VID_MSI, USB_PID_MSI_MEGASKY580) },
-		{ USB_DEVICE(USB_VID_ANUBIS_ELECTRONIC,
-			     USB_PID_MSI_DIGI_VOX_MINI_II) },
-		{ USB_DEVICE(USB_VID_ANUBIS_ELECTRONIC,
-			     USB_PID_LIFEVIEW_TV_WALKER_TWIN_COLD) },
-		{ USB_DEVICE(USB_VID_ANUBIS_ELECTRONIC,
-			     USB_PID_LIFEVIEW_TV_WALKER_TWIN_WARM) },
-		{ USB_DEVICE(USB_VID_DPOSH, USB_PID_DPOSH_M9206_COLD) },
-		{ USB_DEVICE(USB_VID_DPOSH, USB_PID_DPOSH_M9206_WARM) },
-		{ USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_PINNACLE_PCTV310E) },
-		{ }		/* Terminating entry */
-};
-MODULE_DEVICE_TABLE (usb, m920x_table);
-
-static struct dvb_usb_device_properties megasky_properties = {
-	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
-
-	.usb_ctrl = DEVICE_SPECIFIC,
-	.firmware = "dvb-usb-megasky-02.fw",
-	.download_firmware = m920x_firmware_download,
-
-	.rc.legacy = {
-		.rc_interval      = 100,
-		.rc_map_table     = rc_map_megasky_table,
-		.rc_map_size      = ARRAY_SIZE(rc_map_megasky_table),
-		.rc_query         = m920x_rc_query,
-	},
-
-	.size_of_priv     = sizeof(struct m920x_state),
-
-	.identify_state   = m920x_identify_state,
-	.num_adapters = 1,
-	.adapter = {{
-		.num_frontends = 1,
-		.fe = {{
-
-		.caps = DVB_USB_ADAP_HAS_PID_FILTER |
-			DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
-
-		.pid_filter_count = 8,
-		.pid_filter       = m920x_pid_filter,
-		.pid_filter_ctrl  = m920x_pid_filter_ctrl,
-
-		.frontend_attach  = m920x_mt352_frontend_attach,
-		.tuner_attach     = m920x_qt1010_tuner_attach,
-
-		.stream = {
-			.type = USB_BULK,
-			.count = 8,
-			.endpoint = 0x81,
-			.u = {
-				.bulk = {
-					.buffersize = 512,
-				}
-			}
-		},
-		}},
-	}},
-	.i2c_algo         = &m920x_i2c_algo,
-
-	.num_device_descs = 1,
-	.devices = {
-		{   "MSI Mega Sky 580 DVB-T USB2.0",
-			{ &m920x_table[0], NULL },
-			{ NULL },
-		}
-	}
-};
-
-static struct dvb_usb_device_properties digivox_mini_ii_properties = {
-	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
-
-	.usb_ctrl = DEVICE_SPECIFIC,
-	.firmware = "dvb-usb-digivox-02.fw",
-	.download_firmware = m920x_firmware_download,
-
-	.size_of_priv     = sizeof(struct m920x_state),
-
-	.identify_state   = m920x_identify_state,
-	.num_adapters = 1,
-	.adapter = {{
-		.num_frontends = 1,
-		.fe = {{
-
-		.caps = DVB_USB_ADAP_HAS_PID_FILTER |
-			DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
-
-		.pid_filter_count = 8,
-		.pid_filter       = m920x_pid_filter,
-		.pid_filter_ctrl  = m920x_pid_filter_ctrl,
-
-		.frontend_attach  = m920x_tda10046_08_frontend_attach,
-		.tuner_attach     = m920x_tda8275_60_tuner_attach,
-
-		.stream = {
-			.type = USB_BULK,
-			.count = 8,
-			.endpoint = 0x81,
-			.u = {
-				.bulk = {
-					.buffersize = 0x4000,
-				}
-			}
-		},
-		}},
-	}},
-	.i2c_algo         = &m920x_i2c_algo,
-
-	.num_device_descs = 1,
-	.devices = {
-		{   "MSI DIGI VOX mini II DVB-T USB2.0",
-			{ &m920x_table[1], NULL },
-			{ NULL },
-		},
-	}
-};
-
-/* LifeView TV Walker Twin support by Nick Andrew <nick@nick-andrew.net>
- *
- * LifeView TV Walker Twin has 1 x M9206, 2 x TDA10046, 2 x TDA8275A
- * TDA10046 #0 is located at i2c address 0x08
- * TDA10046 #1 is located at i2c address 0x0b
- * TDA8275A #0 is located at i2c address 0x60
- * TDA8275A #1 is located at i2c address 0x61
- */
-static struct dvb_usb_device_properties tvwalkertwin_properties = {
-	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
-
-	.usb_ctrl = DEVICE_SPECIFIC,
-	.firmware = "dvb-usb-tvwalkert.fw",
-	.download_firmware = m920x_firmware_download,
-
-	.rc.legacy = {
-		.rc_interval      = 100,
-		.rc_map_table     = rc_map_tvwalkertwin_table,
-		.rc_map_size      = ARRAY_SIZE(rc_map_tvwalkertwin_table),
-		.rc_query         = m920x_rc_query,
-	},
-
-	.size_of_priv     = sizeof(struct m920x_state),
-
-	.identify_state   = m920x_identify_state,
-	.num_adapters = 2,
-	.adapter = {{
-		.num_frontends = 1,
-		.fe = {{
-
-		.caps = DVB_USB_ADAP_HAS_PID_FILTER |
-			DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
-
-		.pid_filter_count = 8,
-		.pid_filter       = m920x_pid_filter,
-		.pid_filter_ctrl  = m920x_pid_filter_ctrl,
-
-		.frontend_attach  = m920x_tda10046_08_frontend_attach,
-		.tuner_attach     = m920x_tda8275_60_tuner_attach,
-
-		.stream = {
-			.type = USB_BULK,
-			.count = 8,
-			.endpoint = 0x81,
-			.u = {
-				 .bulk = {
-					 .buffersize = 512,
-				 }
-			}
-		}},
-		}},{
-		.num_frontends = 1,
-		.fe = {{
-
-		.caps = DVB_USB_ADAP_HAS_PID_FILTER |
-			DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
-
-		.pid_filter_count = 8,
-		.pid_filter       = m920x_pid_filter,
-		.pid_filter_ctrl  = m920x_pid_filter_ctrl,
-
-		.frontend_attach  = m920x_tda10046_0b_frontend_attach,
-		.tuner_attach     = m920x_tda8275_61_tuner_attach,
-
-		.stream = {
-			.type = USB_BULK,
-			.count = 8,
-			.endpoint = 0x82,
-			.u = {
-				 .bulk = {
-					 .buffersize = 512,
-				 }
-			}
-		}},
-		},
-	}},
-	.i2c_algo         = &m920x_i2c_algo,
-
-	.num_device_descs = 1,
-	.devices = {
-		{   .name = "LifeView TV Walker Twin DVB-T USB2.0",
-		    .cold_ids = { &m920x_table[2], NULL },
-		    .warm_ids = { &m920x_table[3], NULL },
-		},
-	}
-};
-
-static struct dvb_usb_device_properties dposh_properties = {
-	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
-
-	.usb_ctrl = DEVICE_SPECIFIC,
-	.firmware = "dvb-usb-dposh-01.fw",
-	.download_firmware = m920x_firmware_download,
-
-	.size_of_priv     = sizeof(struct m920x_state),
-
-	.identify_state   = m920x_identify_state,
-	.num_adapters = 1,
-	.adapter = {{
-		.num_frontends = 1,
-		.fe = {{
-		/* Hardware pid filters don't work with this device/firmware */
-
-		.frontend_attach  = m920x_mt352_frontend_attach,
-		.tuner_attach     = m920x_qt1010_tuner_attach,
-
-		.stream = {
-			.type = USB_BULK,
-			.count = 8,
-			.endpoint = 0x81,
-			.u = {
-				 .bulk = {
-					 .buffersize = 512,
-				 }
-			}
-		},
-		}},
-	}},
-	.i2c_algo         = &m920x_i2c_algo,
-
-	.num_device_descs = 1,
-	.devices = {
-		 {   .name = "Dposh DVB-T USB2.0",
-		     .cold_ids = { &m920x_table[4], NULL },
-		     .warm_ids = { &m920x_table[5], NULL },
-		 },
-	 }
-};
-
-static struct dvb_usb_device_properties pinnacle_pctv310e_properties = {
-	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
-
-	.usb_ctrl = DEVICE_SPECIFIC,
-	.download_firmware = NULL,
-
-	.rc.legacy = {
-		.rc_interval      = 100,
-		.rc_map_table     = rc_map_pinnacle310e_table,
-		.rc_map_size      = ARRAY_SIZE(rc_map_pinnacle310e_table),
-		.rc_query         = m920x_rc_query,
-	},
-
-	.size_of_priv     = sizeof(struct m920x_state),
-
-	.identify_state   = m920x_identify_state,
-	.num_adapters = 1,
-	.adapter = {{
-		.num_frontends = 1,
-		.fe = {{
-
-		.caps = DVB_USB_ADAP_HAS_PID_FILTER |
-			DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
-
-		.pid_filter_count = 8,
-		.pid_filter       = m920x_pid_filter,
-		.pid_filter_ctrl  = m920x_pid_filter_ctrl,
-
-		.frontend_attach  = m920x_mt352_frontend_attach,
-		.tuner_attach     = m920x_fmd1216me_tuner_attach,
-
-		.stream = {
-			.type = USB_ISOC,
-			.count = 5,
-			.endpoint = 0x84,
-			.u = {
-				.isoc = {
-					.framesperurb = 128,
-					.framesize = 564,
-					.interval = 1,
-				}
-			}
-		},
-		}},
-	} },
-	.i2c_algo         = &m920x_i2c_algo,
-
-	.num_device_descs = 1,
-	.devices = {
-		{   "Pinnacle PCTV 310e",
-			{ &m920x_table[6], NULL },
-			{ NULL },
-		}
-	}
-};
-
-static struct usb_driver m920x_driver = {
-	.name		= "dvb_usb_m920x",
-	.probe		= m920x_probe,
-	.disconnect	= dvb_usb_device_exit,
-	.id_table	= m920x_table,
-};
-
-module_usb_driver(m920x_driver);
-
-MODULE_AUTHOR("Aapo Tahkola <aet@rasterburn.org>");
-MODULE_DESCRIPTION("DVB Driver for ULI M920x");
-MODULE_VERSION("0.1");
-MODULE_LICENSE("GPL");
-
-/*
- * Local variables:
- * c-basic-offset: 8
- */
diff --git a/drivers/media/dvb/dvb-usb/m920x.h b/drivers/media/dvb/dvb-usb/m920x.h
deleted file mode 100644
index 3c06151..0000000
--- a/drivers/media/dvb/dvb-usb/m920x.h
+++ /dev/null
@@ -1,77 +0,0 @@
-#ifndef _DVB_USB_M920X_H_
-#define _DVB_USB_M920X_H_
-
-#define DVB_USB_LOG_PREFIX "m920x"
-#include "dvb-usb.h"
-
-#define deb(args...)   dprintk(dvb_usb_m920x_debug,0x01,args)
-
-#define M9206_CORE	0x22
-#define M9206_RC_STATE	0xff51
-#define M9206_RC_KEY	0xff52
-#define M9206_RC_INIT1	0xff54
-#define M9206_RC_INIT2	0xff55
-#define M9206_FW_GO	0xff69
-
-#define M9206_I2C	0x23
-#define M9206_FILTER	0x25
-#define M9206_FW	0x30
-
-#define M9206_MAX_FILTERS 8
-#define M9206_MAX_ADAPTERS 4
-
-/*
-sequences found in logs:
-[index value]
-0x80 write addr
-(0x00 out byte)*
-0x40 out byte
-
-0x80 write addr
-(0x00 out byte)*
-0x80 read addr
-(0x21 in byte)*
-0x60 in byte
-
-this sequence works:
-0x80 read addr
-(0x21 in byte)*
-0x60 in byte
-
-Guess at API of the I2C function:
-I2C operation is done one byte at a time with USB control messages.  The
-index the messages is sent to is made up of a set of flags that control
-the I2C bus state:
-0x80:  Send START condition.  After a START condition, one would normally
-       always send the 7-bit slave I2C address as the 7 MSB, followed by
-       the read/write bit as the LSB.
-0x40:  Send STOP condition.  This should be set on the last byte of an
-       I2C transaction.
-0x20:  Read a byte from the slave.  As opposed to writing a byte to the
-       slave.  The slave will normally not produce any data unless you
-       set the R/W bit to 1 when sending the slave's address after the
-       START condition.
-0x01:  Respond with ACK, as opposed to a NACK.  For a multi-byte read,
-       the master should send an ACK, that is pull SDA low during the 9th
-       clock cycle, after every byte but the last.  This flags only makes
-       sense when bit 0x20 is set, indicating a read.
-
-What any other bits might mean, or how to get the slave's ACK/NACK
-response to a write, is unknown.
-*/
-
-struct m920x_state {
-	u16 filters[M9206_MAX_ADAPTERS][M9206_MAX_FILTERS];
-	int filtering_enabled[M9206_MAX_ADAPTERS];
-	int rep_count;
-};
-
-/* Initialisation data for the m920x
- */
-
-struct m920x_inits {
-	u16 address;
-	u8  data;
-};
-
-#endif
diff --git a/drivers/media/dvb/dvb-usb/mxl111sf-demod.c b/drivers/media/dvb/dvb-usb/mxl111sf-demod.c
deleted file mode 100644
index d83df4b..0000000
--- a/drivers/media/dvb/dvb-usb/mxl111sf-demod.c
+++ /dev/null
@@ -1,612 +0,0 @@
-/*
- *  mxl111sf-demod.c - driver for the MaxLinear MXL111SF DVB-T demodulator
- *
- *  Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include "mxl111sf-demod.h"
-#include "mxl111sf-reg.h"
-
-/* debug */
-static int mxl111sf_demod_debug;
-module_param_named(debug, mxl111sf_demod_debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able)).");
-
-#define mxl_dbg(fmt, arg...) \
-	if (mxl111sf_demod_debug) \
-		mxl_printk(KERN_DEBUG, fmt, ##arg)
-
-/* ------------------------------------------------------------------------ */
-
-struct mxl111sf_demod_state {
-	struct mxl111sf_state *mxl_state;
-
-	struct mxl111sf_demod_config *cfg;
-
-	struct dvb_frontend fe;
-};
-
-/* ------------------------------------------------------------------------ */
-
-static int mxl111sf_demod_read_reg(struct mxl111sf_demod_state *state,
-				   u8 addr, u8 *data)
-{
-	return (state->cfg->read_reg) ?
-		state->cfg->read_reg(state->mxl_state, addr, data) :
-		-EINVAL;
-}
-
-static int mxl111sf_demod_write_reg(struct mxl111sf_demod_state *state,
-				    u8 addr, u8 data)
-{
-	return (state->cfg->write_reg) ?
-		state->cfg->write_reg(state->mxl_state, addr, data) :
-		-EINVAL;
-}
-
-static
-int mxl111sf_demod_program_regs(struct mxl111sf_demod_state *state,
-				struct mxl111sf_reg_ctrl_info *ctrl_reg_info)
-{
-	return (state->cfg->program_regs) ?
-		state->cfg->program_regs(state->mxl_state, ctrl_reg_info) :
-		-EINVAL;
-}
-
-/* ------------------------------------------------------------------------ */
-/* TPS */
-
-static
-int mxl1x1sf_demod_get_tps_code_rate(struct mxl111sf_demod_state *state,
-				     fe_code_rate_t *code_rate)
-{
-	u8 val;
-	int ret = mxl111sf_demod_read_reg(state, V6_CODE_RATE_TPS_REG, &val);
-	/* bit<2:0> - 000:1/2, 001:2/3, 010:3/4, 011:5/6, 100:7/8 */
-	if (mxl_fail(ret))
-		goto fail;
-
-	switch (val & V6_CODE_RATE_TPS_MASK) {
-	case 0:
-		*code_rate = FEC_1_2;
-		break;
-	case 1:
-		*code_rate = FEC_2_3;
-		break;
-	case 2:
-		*code_rate = FEC_3_4;
-		break;
-	case 3:
-		*code_rate = FEC_5_6;
-		break;
-	case 4:
-		*code_rate = FEC_7_8;
-		break;
-	}
-fail:
-	return ret;
-}
-
-static
-int mxl1x1sf_demod_get_tps_modulation(struct mxl111sf_demod_state *state,
-					 fe_modulation_t *modulation)
-{
-	u8 val;
-	int ret = mxl111sf_demod_read_reg(state, V6_MODORDER_TPS_REG, &val);
-	/* Constellation, 00 : QPSK, 01 : 16QAM, 10:64QAM */
-	if (mxl_fail(ret))
-		goto fail;
-
-	switch ((val & V6_PARAM_CONSTELLATION_MASK) >> 4) {
-	case 0:
-		*modulation = QPSK;
-		break;
-	case 1:
-		*modulation = QAM_16;
-		break;
-	case 2:
-		*modulation = QAM_64;
-		break;
-	}
-fail:
-	return ret;
-}
-
-static
-int mxl1x1sf_demod_get_tps_guard_fft_mode(struct mxl111sf_demod_state *state,
-					  fe_transmit_mode_t *fft_mode)
-{
-	u8 val;
-	int ret = mxl111sf_demod_read_reg(state, V6_MODE_TPS_REG, &val);
-	/* FFT Mode, 00:2K, 01:8K, 10:4K */
-	if (mxl_fail(ret))
-		goto fail;
-
-	switch ((val & V6_PARAM_FFT_MODE_MASK) >> 2) {
-	case 0:
-		*fft_mode = TRANSMISSION_MODE_2K;
-		break;
-	case 1:
-		*fft_mode = TRANSMISSION_MODE_8K;
-		break;
-	case 2:
-		*fft_mode = TRANSMISSION_MODE_4K;
-		break;
-	}
-fail:
-	return ret;
-}
-
-static
-int mxl1x1sf_demod_get_tps_guard_interval(struct mxl111sf_demod_state *state,
-					  fe_guard_interval_t *guard)
-{
-	u8 val;
-	int ret = mxl111sf_demod_read_reg(state, V6_CP_TPS_REG, &val);
-	/* 00:1/32, 01:1/16, 10:1/8, 11:1/4 */
-	if (mxl_fail(ret))
-		goto fail;
-
-	switch ((val & V6_PARAM_GI_MASK) >> 4) {
-	case 0:
-		*guard = GUARD_INTERVAL_1_32;
-		break;
-	case 1:
-		*guard = GUARD_INTERVAL_1_16;
-		break;
-	case 2:
-		*guard = GUARD_INTERVAL_1_8;
-		break;
-	case 3:
-		*guard = GUARD_INTERVAL_1_4;
-		break;
-	}
-fail:
-	return ret;
-}
-
-static
-int mxl1x1sf_demod_get_tps_hierarchy(struct mxl111sf_demod_state *state,
-				     fe_hierarchy_t *hierarchy)
-{
-	u8 val;
-	int ret = mxl111sf_demod_read_reg(state, V6_TPS_HIERACHY_REG, &val);
-	/* bit<6:4> - 000:Non hierarchy, 001:1, 010:2, 011:4 */
-	if (mxl_fail(ret))
-		goto fail;
-
-	switch ((val & V6_TPS_HIERARCHY_INFO_MASK) >> 6) {
-	case 0:
-		*hierarchy = HIERARCHY_NONE;
-		break;
-	case 1:
-		*hierarchy = HIERARCHY_1;
-		break;
-	case 2:
-		*hierarchy = HIERARCHY_2;
-		break;
-	case 3:
-		*hierarchy = HIERARCHY_4;
-		break;
-	}
-fail:
-	return ret;
-}
-
-/* ------------------------------------------------------------------------ */
-/* LOCKS */
-
-static
-int mxl1x1sf_demod_get_sync_lock_status(struct mxl111sf_demod_state *state,
-					int *sync_lock)
-{
-	u8 val = 0;
-	int ret = mxl111sf_demod_read_reg(state, V6_SYNC_LOCK_REG, &val);
-	if (mxl_fail(ret))
-		goto fail;
-	*sync_lock = (val & SYNC_LOCK_MASK) >> 4;
-fail:
-	return ret;
-}
-
-static
-int mxl1x1sf_demod_get_rs_lock_status(struct mxl111sf_demod_state *state,
-				      int *rs_lock)
-{
-	u8 val = 0;
-	int ret = mxl111sf_demod_read_reg(state, V6_RS_LOCK_DET_REG, &val);
-	if (mxl_fail(ret))
-		goto fail;
-	*rs_lock = (val & RS_LOCK_DET_MASK) >> 3;
-fail:
-	return ret;
-}
-
-static
-int mxl1x1sf_demod_get_tps_lock_status(struct mxl111sf_demod_state *state,
-				       int *tps_lock)
-{
-	u8 val = 0;
-	int ret = mxl111sf_demod_read_reg(state, V6_TPS_LOCK_REG, &val);
-	if (mxl_fail(ret))
-		goto fail;
-	*tps_lock = (val & V6_PARAM_TPS_LOCK_MASK) >> 6;
-fail:
-	return ret;
-}
-
-static
-int mxl1x1sf_demod_get_fec_lock_status(struct mxl111sf_demod_state *state,
-				       int *fec_lock)
-{
-	u8 val = 0;
-	int ret = mxl111sf_demod_read_reg(state, V6_IRQ_STATUS_REG, &val);
-	if (mxl_fail(ret))
-		goto fail;
-	*fec_lock = (val & IRQ_MASK_FEC_LOCK) >> 4;
-fail:
-	return ret;
-}
-
-#if 0
-static
-int mxl1x1sf_demod_get_cp_lock_status(struct mxl111sf_demod_state *state,
-				      int *cp_lock)
-{
-	u8 val = 0;
-	int ret = mxl111sf_demod_read_reg(state, V6_CP_LOCK_DET_REG, &val);
-	if (mxl_fail(ret))
-		goto fail;
-	*cp_lock = (val & V6_CP_LOCK_DET_MASK) >> 2;
-fail:
-	return ret;
-}
-#endif
-
-static int mxl1x1sf_demod_reset_irq_status(struct mxl111sf_demod_state *state)
-{
-	return mxl111sf_demod_write_reg(state, 0x0e, 0xff);
-}
-
-/* ------------------------------------------------------------------------ */
-
-static int mxl111sf_demod_set_frontend(struct dvb_frontend *fe)
-{
-	struct mxl111sf_demod_state *state = fe->demodulator_priv;
-	int ret = 0;
-
-	struct mxl111sf_reg_ctrl_info phy_pll_patch[] = {
-		{0x00, 0xff, 0x01}, /* change page to 1 */
-		{0x40, 0xff, 0x05},
-		{0x40, 0xff, 0x01},
-		{0x41, 0xff, 0xca},
-		{0x41, 0xff, 0xc0},
-		{0x00, 0xff, 0x00}, /* change page to 0 */
-		{0,    0,    0}
-	};
-
-	mxl_dbg("()");
-
-	if (fe->ops.tuner_ops.set_params) {
-		ret = fe->ops.tuner_ops.set_params(fe);
-		if (mxl_fail(ret))
-			goto fail;
-		msleep(50);
-	}
-	ret = mxl111sf_demod_program_regs(state, phy_pll_patch);
-	mxl_fail(ret);
-	msleep(50);
-	ret = mxl1x1sf_demod_reset_irq_status(state);
-	mxl_fail(ret);
-	msleep(100);
-fail:
-	return ret;
-}
-
-/* ------------------------------------------------------------------------ */
-
-#if 0
-/* resets TS Packet error count */
-/* After setting 7th bit of V5_PER_COUNT_RESET_REG, it should be reset to 0. */
-static
-int mxl1x1sf_demod_reset_packet_error_count(struct mxl111sf_demod_state *state)
-{
-	struct mxl111sf_reg_ctrl_info reset_per_count[] = {
-		{0x20, 0x01, 0x01},
-		{0x20, 0x01, 0x00},
-		{0,    0,    0}
-	};
-	return mxl111sf_demod_program_regs(state, reset_per_count);
-}
-#endif
-
-/* returns TS Packet error count */
-/* PER Count = FEC_PER_COUNT * (2 ** (FEC_PER_SCALE * 4)) */
-static int mxl111sf_demod_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
-{
-	struct mxl111sf_demod_state *state = fe->demodulator_priv;
-	u32 fec_per_count, fec_per_scale;
-	u8 val;
-	int ret;
-
-	*ucblocks = 0;
-
-	/* FEC_PER_COUNT Register */
-	ret = mxl111sf_demod_read_reg(state, V6_FEC_PER_COUNT_REG, &val);
-	if (mxl_fail(ret))
-		goto fail;
-
-	fec_per_count = val;
-
-	/* FEC_PER_SCALE Register */
-	ret = mxl111sf_demod_read_reg(state, V6_FEC_PER_SCALE_REG, &val);
-	if (mxl_fail(ret))
-		goto fail;
-
-	val &= V6_FEC_PER_SCALE_MASK;
-	val *= 4;
-
-	fec_per_scale = 1 << val;
-
-	fec_per_count *= fec_per_scale;
-
-	*ucblocks = fec_per_count;
-fail:
-	return ret;
-}
-
-#ifdef MXL111SF_DEMOD_ENABLE_CALCULATIONS
-/* FIXME: leaving this enabled breaks the build on some architectures,
- * and we shouldn't have any floating point math in the kernel, anyway.
- *
- * These macros need to be re-written, but it's harmless to simply
- * return zero for now. */
-#define CALCULATE_BER(avg_errors, count) \
-	((u32)(avg_errors * 4)/(count*64*188*8))
-#define CALCULATE_SNR(data) \
-	((u32)((10 * (u32)data / 64) - 2.5))
-#else
-#define CALCULATE_BER(avg_errors, count) 0
-#define CALCULATE_SNR(data) 0
-#endif
-
-static int mxl111sf_demod_read_ber(struct dvb_frontend *fe, u32 *ber)
-{
-	struct mxl111sf_demod_state *state = fe->demodulator_priv;
-	u8 val1, val2, val3;
-	int ret;
-
-	*ber = 0;
-
-	ret = mxl111sf_demod_read_reg(state, V6_RS_AVG_ERRORS_LSB_REG, &val1);
-	if (mxl_fail(ret))
-		goto fail;
-	ret = mxl111sf_demod_read_reg(state, V6_RS_AVG_ERRORS_MSB_REG, &val2);
-	if (mxl_fail(ret))
-		goto fail;
-	ret = mxl111sf_demod_read_reg(state, V6_N_ACCUMULATE_REG, &val3);
-	if (mxl_fail(ret))
-		goto fail;
-
-	*ber = CALCULATE_BER((val1 | (val2 << 8)), val3);
-fail:
-	return ret;
-}
-
-static int mxl111sf_demod_calc_snr(struct mxl111sf_demod_state *state,
-				   u16 *snr)
-{
-	u8 val1, val2;
-	int ret;
-
-	*snr = 0;
-
-	ret = mxl111sf_demod_read_reg(state, V6_SNR_RB_LSB_REG, &val1);
-	if (mxl_fail(ret))
-		goto fail;
-	ret = mxl111sf_demod_read_reg(state, V6_SNR_RB_MSB_REG, &val2);
-	if (mxl_fail(ret))
-		goto fail;
-
-	*snr = CALCULATE_SNR(val1 | ((val2 & 0x03) << 8));
-fail:
-	return ret;
-}
-
-static int mxl111sf_demod_read_snr(struct dvb_frontend *fe, u16 *snr)
-{
-	struct mxl111sf_demod_state *state = fe->demodulator_priv;
-
-	int ret = mxl111sf_demod_calc_snr(state, snr);
-	if (mxl_fail(ret))
-		goto fail;
-
-	*snr /= 10; /* 0.1 dB */
-fail:
-	return ret;
-}
-
-static int mxl111sf_demod_read_status(struct dvb_frontend *fe,
-				      fe_status_t *status)
-{
-	struct mxl111sf_demod_state *state = fe->demodulator_priv;
-	int ret, locked, cr_lock, sync_lock, fec_lock;
-
-	*status = 0;
-
-	ret = mxl1x1sf_demod_get_rs_lock_status(state, &locked);
-	if (mxl_fail(ret))
-		goto fail;
-	ret = mxl1x1sf_demod_get_tps_lock_status(state, &cr_lock);
-	if (mxl_fail(ret))
-		goto fail;
-	ret = mxl1x1sf_demod_get_sync_lock_status(state, &sync_lock);
-	if (mxl_fail(ret))
-		goto fail;
-	ret = mxl1x1sf_demod_get_fec_lock_status(state, &fec_lock);
-	if (mxl_fail(ret))
-		goto fail;
-
-	if (locked)
-		*status |= FE_HAS_SIGNAL;
-	if (cr_lock)
-		*status |= FE_HAS_CARRIER;
-	if (sync_lock)
-		*status |= FE_HAS_SYNC;
-	if (fec_lock) /* false positives? */
-		*status |= FE_HAS_VITERBI;
-
-	if ((locked) && (cr_lock) && (sync_lock))
-		*status |= FE_HAS_LOCK;
-fail:
-	return ret;
-}
-
-static int mxl111sf_demod_read_signal_strength(struct dvb_frontend *fe,
-					       u16 *signal_strength)
-{
-	struct mxl111sf_demod_state *state = fe->demodulator_priv;
-	fe_modulation_t modulation;
-	u16 snr;
-
-	mxl111sf_demod_calc_snr(state, &snr);
-	mxl1x1sf_demod_get_tps_modulation(state, &modulation);
-
-	switch (modulation) {
-	case QPSK:
-		*signal_strength = (snr >= 1300) ?
-			min(65535, snr * 44) : snr * 38;
-		break;
-	case QAM_16:
-		*signal_strength = (snr >= 1500) ?
-			min(65535, snr * 38) : snr * 33;
-		break;
-	case QAM_64:
-		*signal_strength = (snr >= 2000) ?
-			min(65535, snr * 29) : snr * 25;
-		break;
-	default:
-		*signal_strength = 0;
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int mxl111sf_demod_get_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct mxl111sf_demod_state *state = fe->demodulator_priv;
-
-	mxl_dbg("()");
-#if 0
-	p->inversion = /* FIXME */ ? INVERSION_ON : INVERSION_OFF;
-#endif
-	if (fe->ops.tuner_ops.get_bandwidth)
-		fe->ops.tuner_ops.get_bandwidth(fe, &p->bandwidth_hz);
-	if (fe->ops.tuner_ops.get_frequency)
-		fe->ops.tuner_ops.get_frequency(fe, &p->frequency);
-	mxl1x1sf_demod_get_tps_code_rate(state, &p->code_rate_HP);
-	mxl1x1sf_demod_get_tps_code_rate(state, &p->code_rate_LP);
-	mxl1x1sf_demod_get_tps_modulation(state, &p->modulation);
-	mxl1x1sf_demod_get_tps_guard_fft_mode(state,
-					      &p->transmission_mode);
-	mxl1x1sf_demod_get_tps_guard_interval(state,
-					      &p->guard_interval);
-	mxl1x1sf_demod_get_tps_hierarchy(state,
-					 &p->hierarchy);
-
-	return 0;
-}
-
-static
-int mxl111sf_demod_get_tune_settings(struct dvb_frontend *fe,
-				     struct dvb_frontend_tune_settings *tune)
-{
-	tune->min_delay_ms = 1000;
-	return 0;
-}
-
-static void mxl111sf_demod_release(struct dvb_frontend *fe)
-{
-	struct mxl111sf_demod_state *state = fe->demodulator_priv;
-	mxl_dbg("()");
-	kfree(state);
-	fe->demodulator_priv = NULL;
-}
-
-static struct dvb_frontend_ops mxl111sf_demod_ops = {
-	.delsys = { SYS_DVBT },
-	.info = {
-		.name               = "MaxLinear MxL111SF DVB-T demodulator",
-		.frequency_min      = 177000000,
-		.frequency_max      = 858000000,
-		.frequency_stepsize = 166666,
-		.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_FEC_AUTO |
-			FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 |
-			FE_CAN_QAM_AUTO |
-			FE_CAN_HIERARCHY_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |
-			FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_RECOVER
-	},
-	.release              = mxl111sf_demod_release,
-#if 0
-	.init                 = mxl111sf_init,
-	.i2c_gate_ctrl        = mxl111sf_i2c_gate_ctrl,
-#endif
-	.set_frontend         = mxl111sf_demod_set_frontend,
-	.get_frontend         = mxl111sf_demod_get_frontend,
-	.get_tune_settings    = mxl111sf_demod_get_tune_settings,
-	.read_status          = mxl111sf_demod_read_status,
-	.read_signal_strength = mxl111sf_demod_read_signal_strength,
-	.read_ber             = mxl111sf_demod_read_ber,
-	.read_snr             = mxl111sf_demod_read_snr,
-	.read_ucblocks        = mxl111sf_demod_read_ucblocks,
-};
-
-struct dvb_frontend *mxl111sf_demod_attach(struct mxl111sf_state *mxl_state,
-					   struct mxl111sf_demod_config *cfg)
-{
-	struct mxl111sf_demod_state *state = NULL;
-
-	mxl_dbg("()");
-
-	state = kzalloc(sizeof(struct mxl111sf_demod_state), GFP_KERNEL);
-	if (state == NULL)
-		return NULL;
-
-	state->mxl_state = mxl_state;
-	state->cfg = cfg;
-
-	memcpy(&state->fe.ops, &mxl111sf_demod_ops,
-	       sizeof(struct dvb_frontend_ops));
-
-	state->fe.demodulator_priv = state;
-	return &state->fe;
-}
-EXPORT_SYMBOL_GPL(mxl111sf_demod_attach);
-
-MODULE_DESCRIPTION("MaxLinear MxL111SF DVB-T demodulator driver");
-MODULE_AUTHOR("Michael Krufky <mkrufky@kernellabs.com>");
-MODULE_LICENSE("GPL");
-MODULE_VERSION("0.1");
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/dvb/dvb-usb/mxl111sf-demod.h b/drivers/media/dvb/dvb-usb/mxl111sf-demod.h
deleted file mode 100644
index 432706a..0000000
--- a/drivers/media/dvb/dvb-usb/mxl111sf-demod.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- *  mxl111sf-demod.h - driver for the MaxLinear MXL111SF DVB-T demodulator
- *
- *  Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef __MXL111SF_DEMOD_H__
-#define __MXL111SF_DEMOD_H__
-
-#include "dvb_frontend.h"
-#include "mxl111sf.h"
-
-struct mxl111sf_demod_config {
-	int (*read_reg)(struct mxl111sf_state *state, u8 addr, u8 *data);
-	int (*write_reg)(struct mxl111sf_state *state, u8 addr, u8 data);
-	int (*program_regs)(struct mxl111sf_state *state,
-			    struct mxl111sf_reg_ctrl_info *ctrl_reg_info);
-};
-
-#if defined(CONFIG_DVB_USB_MXL111SF) || \
-	(defined(CONFIG_DVB_USB_MXL111SF_MODULE) && defined(MODULE))
-extern
-struct dvb_frontend *mxl111sf_demod_attach(struct mxl111sf_state *mxl_state,
-					   struct mxl111sf_demod_config *cfg);
-#else
-static inline
-struct dvb_frontend *mxl111sf_demod_attach(struct mxl111sf_state *mxl_state,
-					   struct mxl111sf_demod_config *cfg)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif /* CONFIG_DVB_USB_MXL111SF */
-
-#endif /* __MXL111SF_DEMOD_H__ */
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/dvb/dvb-usb/mxl111sf-gpio.c b/drivers/media/dvb/dvb-usb/mxl111sf-gpio.c
deleted file mode 100644
index e4121cb..0000000
--- a/drivers/media/dvb/dvb-usb/mxl111sf-gpio.c
+++ /dev/null
@@ -1,763 +0,0 @@
-/*
- *  mxl111sf-gpio.c - driver for the MaxLinear MXL111SF
- *
- *  Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include "mxl111sf-gpio.h"
-#include "mxl111sf-i2c.h"
-#include "mxl111sf.h"
-
-/* ------------------------------------------------------------------------- */
-
-#define MXL_GPIO_MUX_REG_0 0x84
-#define MXL_GPIO_MUX_REG_1 0x89
-#define MXL_GPIO_MUX_REG_2 0x82
-
-#define MXL_GPIO_DIR_INPUT  0
-#define MXL_GPIO_DIR_OUTPUT 1
-
-
-static int mxl111sf_set_gpo_state(struct mxl111sf_state *state, u8 pin, u8 val)
-{
-	int ret;
-	u8 tmp;
-
-	mxl_debug_adv("(%d, %d)", pin, val);
-
-	if ((pin > 0) && (pin < 8)) {
-		ret = mxl111sf_read_reg(state, 0x19, &tmp);
-		if (mxl_fail(ret))
-			goto fail;
-		tmp &= ~(1 << (pin - 1));
-		tmp |= (val << (pin - 1));
-		ret = mxl111sf_write_reg(state, 0x19, tmp);
-		if (mxl_fail(ret))
-			goto fail;
-	} else if (pin <= 10) {
-		if (pin == 0)
-			pin += 7;
-		ret = mxl111sf_read_reg(state, 0x30, &tmp);
-		if (mxl_fail(ret))
-			goto fail;
-		tmp &= ~(1 << (pin - 3));
-		tmp |= (val << (pin - 3));
-		ret = mxl111sf_write_reg(state, 0x30, tmp);
-		if (mxl_fail(ret))
-			goto fail;
-	} else
-		ret = -EINVAL;
-fail:
-	return ret;
-}
-
-static int mxl111sf_get_gpi_state(struct mxl111sf_state *state, u8 pin, u8 *val)
-{
-	int ret;
-	u8 tmp;
-
-	mxl_debug("(0x%02x)", pin);
-
-	*val = 0;
-
-	switch (pin) {
-	case 0:
-	case 1:
-	case 2:
-	case 3:
-		ret = mxl111sf_read_reg(state, 0x23, &tmp);
-		if (mxl_fail(ret))
-			goto fail;
-		*val = (tmp >> (pin + 4)) & 0x01;
-		break;
-	case 4:
-	case 5:
-	case 6:
-	case 7:
-		ret = mxl111sf_read_reg(state, 0x2f, &tmp);
-		if (mxl_fail(ret))
-			goto fail;
-		*val = (tmp >> pin) & 0x01;
-		break;
-	case 8:
-	case 9:
-	case 10:
-		ret = mxl111sf_read_reg(state, 0x22, &tmp);
-		if (mxl_fail(ret))
-			goto fail;
-		*val = (tmp >> (pin - 3)) & 0x01;
-		break;
-	default:
-		return -EINVAL; /* invalid pin */
-	}
-fail:
-	return ret;
-}
-
-struct mxl_gpio_cfg {
-	u8 pin;
-	u8 dir;
-	u8 val;
-};
-
-static int mxl111sf_config_gpio_pins(struct mxl111sf_state *state,
-				     struct mxl_gpio_cfg *gpio_cfg)
-{
-	int ret;
-	u8 tmp;
-
-	mxl_debug_adv("(%d, %d)", gpio_cfg->pin, gpio_cfg->dir);
-
-	switch (gpio_cfg->pin) {
-	case 0:
-	case 1:
-	case 2:
-	case 3:
-		ret = mxl111sf_read_reg(state, MXL_GPIO_MUX_REG_0, &tmp);
-		if (mxl_fail(ret))
-			goto fail;
-		tmp &= ~(1 << (gpio_cfg->pin + 4));
-		tmp |= (gpio_cfg->dir << (gpio_cfg->pin + 4));
-		ret = mxl111sf_write_reg(state, MXL_GPIO_MUX_REG_0, tmp);
-		if (mxl_fail(ret))
-			goto fail;
-		break;
-	case 4:
-	case 5:
-	case 6:
-	case 7:
-		ret = mxl111sf_read_reg(state, MXL_GPIO_MUX_REG_1, &tmp);
-		if (mxl_fail(ret))
-			goto fail;
-		tmp &= ~(1 << gpio_cfg->pin);
-		tmp |= (gpio_cfg->dir << gpio_cfg->pin);
-		ret = mxl111sf_write_reg(state, MXL_GPIO_MUX_REG_1, tmp);
-		if (mxl_fail(ret))
-			goto fail;
-		break;
-	case 8:
-	case 9:
-	case 10:
-		ret = mxl111sf_read_reg(state, MXL_GPIO_MUX_REG_2, &tmp);
-		if (mxl_fail(ret))
-			goto fail;
-		tmp &= ~(1 << (gpio_cfg->pin - 3));
-		tmp |= (gpio_cfg->dir << (gpio_cfg->pin - 3));
-		ret = mxl111sf_write_reg(state, MXL_GPIO_MUX_REG_2, tmp);
-		if (mxl_fail(ret))
-			goto fail;
-		break;
-	default:
-		return -EINVAL; /* invalid pin */
-	}
-
-	ret = (MXL_GPIO_DIR_OUTPUT == gpio_cfg->dir) ?
-		mxl111sf_set_gpo_state(state,
-				       gpio_cfg->pin, gpio_cfg->val) :
-		mxl111sf_get_gpi_state(state,
-				       gpio_cfg->pin, &gpio_cfg->val);
-	mxl_fail(ret);
-fail:
-	return ret;
-}
-
-static int mxl111sf_hw_do_set_gpio(struct mxl111sf_state *state,
-				   int gpio, int direction, int val)
-{
-	struct mxl_gpio_cfg gpio_config = {
-		.pin = gpio,
-		.dir = direction,
-		.val = val,
-	};
-
-	mxl_debug("(%d, %d, %d)", gpio, direction, val);
-
-	return mxl111sf_config_gpio_pins(state, &gpio_config);
-}
-
-/* ------------------------------------------------------------------------- */
-
-#define PIN_MUX_MPEG_MODE_MASK          0x40   /* 0x17 <6> */
-#define PIN_MUX_MPEG_PAR_EN_MASK        0x01   /* 0x18 <0> */
-#define PIN_MUX_MPEG_SER_EN_MASK        0x02   /* 0x18 <1> */
-#define PIN_MUX_MPG_IN_MUX_MASK         0x80   /* 0x3D <7> */
-#define PIN_MUX_BT656_ENABLE_MASK       0x04   /* 0x12 <2> */
-#define PIN_MUX_I2S_ENABLE_MASK         0x40   /* 0x15 <6> */
-#define PIN_MUX_SPI_MODE_MASK           0x10   /* 0x3D <4> */
-#define PIN_MUX_MCLK_EN_CTRL_MASK       0x10   /* 0x82 <4> */
-#define PIN_MUX_MPSYN_EN_CTRL_MASK      0x20   /* 0x82 <5> */
-#define PIN_MUX_MDVAL_EN_CTRL_MASK      0x40   /* 0x82 <6> */
-#define PIN_MUX_MPERR_EN_CTRL_MASK      0x80   /* 0x82 <7> */
-#define PIN_MUX_MDAT_EN_0_MASK          0x10   /* 0x84 <4> */
-#define PIN_MUX_MDAT_EN_1_MASK          0x20   /* 0x84 <5> */
-#define PIN_MUX_MDAT_EN_2_MASK          0x40   /* 0x84 <6> */
-#define PIN_MUX_MDAT_EN_3_MASK          0x80   /* 0x84 <7> */
-#define PIN_MUX_MDAT_EN_4_MASK          0x10   /* 0x89 <4> */
-#define PIN_MUX_MDAT_EN_5_MASK          0x20   /* 0x89 <5> */
-#define PIN_MUX_MDAT_EN_6_MASK          0x40   /* 0x89 <6> */
-#define PIN_MUX_MDAT_EN_7_MASK          0x80   /* 0x89 <7> */
-
-int mxl111sf_config_pin_mux_modes(struct mxl111sf_state *state,
-				  enum mxl111sf_mux_config pin_mux_config)
-{
-	u8 r12, r15, r17, r18, r3D, r82, r84, r89;
-	int ret;
-
-	mxl_debug("(%d)", pin_mux_config);
-
-	ret = mxl111sf_read_reg(state, 0x17, &r17);
-	if (mxl_fail(ret))
-		goto fail;
-	ret = mxl111sf_read_reg(state, 0x18, &r18);
-	if (mxl_fail(ret))
-		goto fail;
-	ret = mxl111sf_read_reg(state, 0x12, &r12);
-	if (mxl_fail(ret))
-		goto fail;
-	ret = mxl111sf_read_reg(state, 0x15, &r15);
-	if (mxl_fail(ret))
-		goto fail;
-	ret = mxl111sf_read_reg(state, 0x82, &r82);
-	if (mxl_fail(ret))
-		goto fail;
-	ret = mxl111sf_read_reg(state, 0x84, &r84);
-	if (mxl_fail(ret))
-		goto fail;
-	ret = mxl111sf_read_reg(state, 0x89, &r89);
-	if (mxl_fail(ret))
-		goto fail;
-	ret = mxl111sf_read_reg(state, 0x3D, &r3D);
-	if (mxl_fail(ret))
-		goto fail;
-
-	switch (pin_mux_config) {
-	case PIN_MUX_TS_OUT_PARALLEL:
-		/* mpeg_mode = 1 */
-		r17 |= PIN_MUX_MPEG_MODE_MASK;
-		/* mpeg_par_en = 1 */
-		r18 |= PIN_MUX_MPEG_PAR_EN_MASK;
-		/* mpeg_ser_en = 0 */
-		r18 &= ~PIN_MUX_MPEG_SER_EN_MASK;
-		/* mpg_in_mux = 0 */
-		r3D &= ~PIN_MUX_MPG_IN_MUX_MASK;
-		/* bt656_enable = 0 */
-		r12 &= ~PIN_MUX_BT656_ENABLE_MASK;
-		/* i2s_enable = 0 */
-		r15 &= ~PIN_MUX_I2S_ENABLE_MASK;
-		/* spi_mode = 0 */
-		r3D &= ~PIN_MUX_SPI_MODE_MASK;
-		/* mclk_en_ctrl = 1 */
-		r82 |= PIN_MUX_MCLK_EN_CTRL_MASK;
-		/* mperr_en_ctrl = 1 */
-		r82 |= PIN_MUX_MPERR_EN_CTRL_MASK;
-		/* mdval_en_ctrl = 1 */
-		r82 |= PIN_MUX_MDVAL_EN_CTRL_MASK;
-		/* mpsyn_en_ctrl = 1 */
-		r82 |= PIN_MUX_MPSYN_EN_CTRL_MASK;
-		/* mdat_en_ctrl[3:0] = 0xF */
-		r84 |= 0xF0;
-		/* mdat_en_ctrl[7:4] = 0xF */
-		r89 |= 0xF0;
-		break;
-	case PIN_MUX_TS_OUT_SERIAL:
-		/* mpeg_mode = 1 */
-		r17 |= PIN_MUX_MPEG_MODE_MASK;
-		/* mpeg_par_en = 0 */
-		r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK;
-		/* mpeg_ser_en = 1 */
-		r18 |= PIN_MUX_MPEG_SER_EN_MASK;
-		/* mpg_in_mux = 0 */
-		r3D &= ~PIN_MUX_MPG_IN_MUX_MASK;
-		/* bt656_enable = 0 */
-		r12 &= ~PIN_MUX_BT656_ENABLE_MASK;
-		/* i2s_enable = 0 */
-		r15 &= ~PIN_MUX_I2S_ENABLE_MASK;
-		/* spi_mode = 0 */
-		r3D &= ~PIN_MUX_SPI_MODE_MASK;
-		/* mclk_en_ctrl = 1 */
-		r82 |= PIN_MUX_MCLK_EN_CTRL_MASK;
-		/* mperr_en_ctrl = 1 */
-		r82 |= PIN_MUX_MPERR_EN_CTRL_MASK;
-		/* mdval_en_ctrl = 1 */
-		r82 |= PIN_MUX_MDVAL_EN_CTRL_MASK;
-		/* mpsyn_en_ctrl = 1 */
-		r82 |= PIN_MUX_MPSYN_EN_CTRL_MASK;
-		/* mdat_en_ctrl[3:0] = 0xF */
-		r84 |= 0xF0;
-		/* mdat_en_ctrl[7:4] = 0xF */
-		r89 |= 0xF0;
-		break;
-	case PIN_MUX_GPIO_MODE:
-		/* mpeg_mode = 0 */
-		r17 &= ~PIN_MUX_MPEG_MODE_MASK;
-		/* mpeg_par_en = 0 */
-		r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK;
-		/* mpeg_ser_en = 0 */
-		r18 &= ~PIN_MUX_MPEG_SER_EN_MASK;
-		/* mpg_in_mux = 0 */
-		r3D &= ~PIN_MUX_MPG_IN_MUX_MASK;
-		/* bt656_enable = 0 */
-		r12 &= ~PIN_MUX_BT656_ENABLE_MASK;
-		/* i2s_enable = 0 */
-		r15 &= ~PIN_MUX_I2S_ENABLE_MASK;
-		/* spi_mode = 0 */
-		r3D &= ~PIN_MUX_SPI_MODE_MASK;
-		/* mclk_en_ctrl = 0 */
-		r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK;
-		/* mperr_en_ctrl = 0 */
-		r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK;
-		/* mdval_en_ctrl = 0 */
-		r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK;
-		/* mpsyn_en_ctrl = 0 */
-		r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK;
-		/* mdat_en_ctrl[3:0] = 0x0 */
-		r84 &= 0x0F;
-		/* mdat_en_ctrl[7:4] = 0x0 */
-		r89 &= 0x0F;
-		break;
-	case PIN_MUX_TS_SERIAL_IN_MODE_0:
-		/* mpeg_mode = 0 */
-		r17 &= ~PIN_MUX_MPEG_MODE_MASK;
-		/* mpeg_par_en = 0 */
-		r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK;
-		/* mpeg_ser_en = 1 */
-		r18 |= PIN_MUX_MPEG_SER_EN_MASK;
-		/* mpg_in_mux = 0 */
-		r3D &= ~PIN_MUX_MPG_IN_MUX_MASK;
-		/* bt656_enable = 0 */
-		r12 &= ~PIN_MUX_BT656_ENABLE_MASK;
-		/* i2s_enable = 0 */
-		r15 &= ~PIN_MUX_I2S_ENABLE_MASK;
-		/* spi_mode = 0 */
-		r3D &= ~PIN_MUX_SPI_MODE_MASK;
-		/* mclk_en_ctrl = 0 */
-		r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK;
-		/* mperr_en_ctrl = 0 */
-		r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK;
-		/* mdval_en_ctrl = 0 */
-		r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK;
-		/* mpsyn_en_ctrl = 0 */
-		r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK;
-		/* mdat_en_ctrl[3:0] = 0x0 */
-		r84 &= 0x0F;
-		/* mdat_en_ctrl[7:4] = 0x0 */
-		r89 &= 0x0F;
-		break;
-	case PIN_MUX_TS_SERIAL_IN_MODE_1:
-		/* mpeg_mode = 0 */
-		r17 &= ~PIN_MUX_MPEG_MODE_MASK;
-		/* mpeg_par_en = 0 */
-		r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK;
-		/* mpeg_ser_en = 1 */
-		r18 |= PIN_MUX_MPEG_SER_EN_MASK;
-		/* mpg_in_mux = 1 */
-		r3D |= PIN_MUX_MPG_IN_MUX_MASK;
-		/* bt656_enable = 0 */
-		r12 &= ~PIN_MUX_BT656_ENABLE_MASK;
-		/* i2s_enable = 0 */
-		r15 &= ~PIN_MUX_I2S_ENABLE_MASK;
-		/* spi_mode = 0 */
-		r3D &= ~PIN_MUX_SPI_MODE_MASK;
-		/* mclk_en_ctrl = 0 */
-		r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK;
-		/* mperr_en_ctrl = 0 */
-		r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK;
-		/* mdval_en_ctrl = 0 */
-		r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK;
-		/* mpsyn_en_ctrl = 0 */
-		r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK;
-		/* mdat_en_ctrl[3:0] = 0x0 */
-		r84 &= 0x0F;
-		/* mdat_en_ctrl[7:4] = 0x0 */
-		r89 &= 0x0F;
-		break;
-	case PIN_MUX_TS_SPI_IN_MODE_1:
-		/* mpeg_mode = 0 */
-		r17 &= ~PIN_MUX_MPEG_MODE_MASK;
-		/* mpeg_par_en = 0 */
-		r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK;
-		/* mpeg_ser_en = 1 */
-		r18 |= PIN_MUX_MPEG_SER_EN_MASK;
-		/* mpg_in_mux = 1 */
-		r3D |= PIN_MUX_MPG_IN_MUX_MASK;
-		/* bt656_enable = 0 */
-		r12 &= ~PIN_MUX_BT656_ENABLE_MASK;
-		/* i2s_enable = 1 */
-		r15 |= PIN_MUX_I2S_ENABLE_MASK;
-		/* spi_mode = 1 */
-		r3D |= PIN_MUX_SPI_MODE_MASK;
-		/* mclk_en_ctrl = 0 */
-		r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK;
-		/* mperr_en_ctrl = 0 */
-		r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK;
-		/* mdval_en_ctrl = 0 */
-		r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK;
-		/* mpsyn_en_ctrl = 0 */
-		r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK;
-		/* mdat_en_ctrl[3:0] = 0x0 */
-		r84 &= 0x0F;
-		/* mdat_en_ctrl[7:4] = 0x0 */
-		r89 &= 0x0F;
-		break;
-	case PIN_MUX_TS_SPI_IN_MODE_0:
-		/* mpeg_mode = 0 */
-		r17 &= ~PIN_MUX_MPEG_MODE_MASK;
-		/* mpeg_par_en = 0 */
-		r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK;
-		/* mpeg_ser_en = 1 */
-		r18 |= PIN_MUX_MPEG_SER_EN_MASK;
-		/* mpg_in_mux = 0 */
-		r3D &= ~PIN_MUX_MPG_IN_MUX_MASK;
-		/* bt656_enable = 0 */
-		r12 &= ~PIN_MUX_BT656_ENABLE_MASK;
-		/* i2s_enable = 1 */
-		r15 |= PIN_MUX_I2S_ENABLE_MASK;
-		/* spi_mode = 1 */
-		r3D |= PIN_MUX_SPI_MODE_MASK;
-		/* mclk_en_ctrl = 0 */
-		r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK;
-		/* mperr_en_ctrl = 0 */
-		r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK;
-		/* mdval_en_ctrl = 0 */
-		r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK;
-		/* mpsyn_en_ctrl = 0 */
-		r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK;
-		/* mdat_en_ctrl[3:0] = 0x0 */
-		r84 &= 0x0F;
-		/* mdat_en_ctrl[7:4] = 0x0 */
-		r89 &= 0x0F;
-		break;
-	case PIN_MUX_TS_PARALLEL_IN:
-		/* mpeg_mode = 0 */
-		r17 &= ~PIN_MUX_MPEG_MODE_MASK;
-		/* mpeg_par_en = 1 */
-		r18 |= PIN_MUX_MPEG_PAR_EN_MASK;
-		/* mpeg_ser_en = 0 */
-		r18 &= ~PIN_MUX_MPEG_SER_EN_MASK;
-		/* mpg_in_mux = 0 */
-		r3D &= ~PIN_MUX_MPG_IN_MUX_MASK;
-		/* bt656_enable = 0 */
-		r12 &= ~PIN_MUX_BT656_ENABLE_MASK;
-		/* i2s_enable = 0 */
-		r15 &= ~PIN_MUX_I2S_ENABLE_MASK;
-		/* spi_mode = 0 */
-		r3D &= ~PIN_MUX_SPI_MODE_MASK;
-		/* mclk_en_ctrl = 0 */
-		r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK;
-		/* mperr_en_ctrl = 0 */
-		r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK;
-		/* mdval_en_ctrl = 0 */
-		r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK;
-		/* mpsyn_en_ctrl = 0 */
-		r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK;
-		/* mdat_en_ctrl[3:0] = 0x0 */
-		r84 &= 0x0F;
-		/* mdat_en_ctrl[7:4] = 0x0 */
-		r89 &= 0x0F;
-		break;
-	case PIN_MUX_BT656_I2S_MODE:
-		/* mpeg_mode = 0 */
-		r17 &= ~PIN_MUX_MPEG_MODE_MASK;
-		/* mpeg_par_en = 0 */
-		r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK;
-		/* mpeg_ser_en = 0 */
-		r18 &= ~PIN_MUX_MPEG_SER_EN_MASK;
-		/* mpg_in_mux = 0 */
-		r3D &= ~PIN_MUX_MPG_IN_MUX_MASK;
-		/* bt656_enable = 1 */
-		r12 |= PIN_MUX_BT656_ENABLE_MASK;
-		/* i2s_enable = 1 */
-		r15 |= PIN_MUX_I2S_ENABLE_MASK;
-		/* spi_mode = 0 */
-		r3D &= ~PIN_MUX_SPI_MODE_MASK;
-		/* mclk_en_ctrl = 0 */
-		r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK;
-		/* mperr_en_ctrl = 0 */
-		r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK;
-		/* mdval_en_ctrl = 0 */
-		r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK;
-		/* mpsyn_en_ctrl = 0 */
-		r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK;
-		/* mdat_en_ctrl[3:0] = 0x0 */
-		r84 &= 0x0F;
-		/* mdat_en_ctrl[7:4] = 0x0 */
-		r89 &= 0x0F;
-		break;
-	case PIN_MUX_DEFAULT:
-	default:
-		/* mpeg_mode = 1 */
-		r17 |= PIN_MUX_MPEG_MODE_MASK;
-		/* mpeg_par_en = 0 */
-		r18 &= ~PIN_MUX_MPEG_PAR_EN_MASK;
-		/* mpeg_ser_en = 0 */
-		r18 &= ~PIN_MUX_MPEG_SER_EN_MASK;
-		/* mpg_in_mux = 0 */
-		r3D &= ~PIN_MUX_MPG_IN_MUX_MASK;
-		/* bt656_enable = 0 */
-		r12 &= ~PIN_MUX_BT656_ENABLE_MASK;
-		/* i2s_enable = 0 */
-		r15 &= ~PIN_MUX_I2S_ENABLE_MASK;
-		/* spi_mode = 0 */
-		r3D &= ~PIN_MUX_SPI_MODE_MASK;
-		/* mclk_en_ctrl = 0 */
-		r82 &= ~PIN_MUX_MCLK_EN_CTRL_MASK;
-		/* mperr_en_ctrl = 0 */
-		r82 &= ~PIN_MUX_MPERR_EN_CTRL_MASK;
-		/* mdval_en_ctrl = 0 */
-		r82 &= ~PIN_MUX_MDVAL_EN_CTRL_MASK;
-		/* mpsyn_en_ctrl = 0 */
-		r82 &= ~PIN_MUX_MPSYN_EN_CTRL_MASK;
-		/* mdat_en_ctrl[3:0] = 0x0 */
-		r84 &= 0x0F;
-		/* mdat_en_ctrl[7:4] = 0x0 */
-		r89 &= 0x0F;
-		break;
-	}
-
-	ret = mxl111sf_write_reg(state, 0x17, r17);
-	if (mxl_fail(ret))
-		goto fail;
-	ret = mxl111sf_write_reg(state, 0x18, r18);
-	if (mxl_fail(ret))
-		goto fail;
-	ret = mxl111sf_write_reg(state, 0x12, r12);
-	if (mxl_fail(ret))
-		goto fail;
-	ret = mxl111sf_write_reg(state, 0x15, r15);
-	if (mxl_fail(ret))
-		goto fail;
-	ret = mxl111sf_write_reg(state, 0x82, r82);
-	if (mxl_fail(ret))
-		goto fail;
-	ret = mxl111sf_write_reg(state, 0x84, r84);
-	if (mxl_fail(ret))
-		goto fail;
-	ret = mxl111sf_write_reg(state, 0x89, r89);
-	if (mxl_fail(ret))
-		goto fail;
-	ret = mxl111sf_write_reg(state, 0x3D, r3D);
-	if (mxl_fail(ret))
-		goto fail;
-fail:
-	return ret;
-}
-
-/* ------------------------------------------------------------------------- */
-
-static int mxl111sf_hw_set_gpio(struct mxl111sf_state *state, int gpio, int val)
-{
-	return mxl111sf_hw_do_set_gpio(state, gpio, MXL_GPIO_DIR_OUTPUT, val);
-}
-
-static int mxl111sf_hw_gpio_initialize(struct mxl111sf_state *state)
-{
-	u8 gpioval = 0x07; /* write protect enabled, signal LEDs off */
-	int i, ret;
-
-	mxl_debug("()");
-
-	for (i = 3; i < 8; i++) {
-		ret = mxl111sf_hw_set_gpio(state, i, (gpioval >> i) & 0x01);
-		if (mxl_fail(ret))
-			break;
-	}
-
-	return ret;
-}
-
-#define PCA9534_I2C_ADDR (0x40 >> 1)
-static int pca9534_set_gpio(struct mxl111sf_state *state, int gpio, int val)
-{
-	u8 w[2] = { 1, 0 };
-	u8 r = 0;
-	struct i2c_msg msg[] = {
-		{ .addr = PCA9534_I2C_ADDR,
-		  .flags = 0, .buf = w, .len = 1 },
-		{ .addr = PCA9534_I2C_ADDR,
-		  .flags = I2C_M_RD, .buf = &r, .len = 1 },
-	};
-
-	mxl_debug("(%d, %d)", gpio, val);
-
-	/* read current GPIO levels from flip-flop */
-	i2c_transfer(&state->d->i2c_adap, msg, 2);
-
-	/* prepare write buffer with current GPIO levels */
-	msg[0].len = 2;
-#if 0
-	w[0] = 1;
-#endif
-	w[1] = r;
-
-	/* clear the desired GPIO */
-	w[1] &= ~(1 << gpio);
-
-	/* set the desired GPIO value */
-	w[1] |= ((val ? 1 : 0) << gpio);
-
-	/* write new GPIO levels to flip-flop */
-	i2c_transfer(&state->d->i2c_adap, &msg[0], 1);
-
-	return 0;
-}
-
-static int pca9534_init_port_expander(struct mxl111sf_state *state)
-{
-	u8 w[2] = { 1, 0x07 }; /* write protect enabled, signal LEDs off */
-
-	struct i2c_msg msg = {
-		.addr = PCA9534_I2C_ADDR,
-		.flags = 0, .buf = w, .len = 2
-	};
-
-	mxl_debug("()");
-
-	i2c_transfer(&state->d->i2c_adap, &msg, 1);
-
-	/* configure all pins as outputs */
-	w[0] = 3;
-	w[1] = 0;
-
-	i2c_transfer(&state->d->i2c_adap, &msg, 1);
-
-	return 0;
-}
-
-int mxl111sf_set_gpio(struct mxl111sf_state *state, int gpio, int val)
-{
-	mxl_debug("(%d, %d)", gpio, val);
-
-	switch (state->gpio_port_expander) {
-	default:
-		mxl_printk(KERN_ERR,
-			   "gpio_port_expander undefined, assuming PCA9534");
-		/* fall-thru */
-	case mxl111sf_PCA9534:
-		return pca9534_set_gpio(state, gpio, val);
-	case mxl111sf_gpio_hw:
-		return mxl111sf_hw_set_gpio(state, gpio, val);
-	}
-}
-
-static int mxl111sf_probe_port_expander(struct mxl111sf_state *state)
-{
-	int ret;
-	u8 w = 1;
-	u8 r = 0;
-	struct i2c_msg msg[] = {
-		{ .flags = 0,        .buf = &w, .len = 1 },
-		{ .flags = I2C_M_RD, .buf = &r, .len = 1 },
-	};
-
-	mxl_debug("()");
-
-	msg[0].addr = 0x70 >> 1;
-	msg[1].addr = 0x70 >> 1;
-
-	/* read current GPIO levels from flip-flop */
-	ret = i2c_transfer(&state->d->i2c_adap, msg, 2);
-	if (ret == 2) {
-		state->port_expander_addr = msg[0].addr;
-		state->gpio_port_expander = mxl111sf_PCA9534;
-		mxl_debug("found port expander at 0x%02x",
-			  state->port_expander_addr);
-		return 0;
-	}
-
-	msg[0].addr = 0x40 >> 1;
-	msg[1].addr = 0x40 >> 1;
-
-	ret = i2c_transfer(&state->d->i2c_adap, msg, 2);
-	if (ret == 2) {
-		state->port_expander_addr = msg[0].addr;
-		state->gpio_port_expander = mxl111sf_PCA9534;
-		mxl_debug("found port expander at 0x%02x",
-			  state->port_expander_addr);
-		return 0;
-	}
-	state->port_expander_addr = 0xff;
-	state->gpio_port_expander = mxl111sf_gpio_hw;
-	mxl_debug("using hardware gpio");
-	return 0;
-}
-
-int mxl111sf_init_port_expander(struct mxl111sf_state *state)
-{
-	mxl_debug("()");
-
-	if (0x00 == state->port_expander_addr)
-		mxl111sf_probe_port_expander(state);
-
-	switch (state->gpio_port_expander) {
-	default:
-		mxl_printk(KERN_ERR,
-			   "gpio_port_expander undefined, assuming PCA9534");
-		/* fall-thru */
-	case mxl111sf_PCA9534:
-		return pca9534_init_port_expander(state);
-	case mxl111sf_gpio_hw:
-		return mxl111sf_hw_gpio_initialize(state);
-	}
-}
-
-/* ------------------------------------------------------------------------ */
-
-int mxl111sf_gpio_mode_switch(struct mxl111sf_state *state, unsigned int mode)
-{
-/*	GPO:
- *	3 - ATSC/MH#   | 1 = ATSC transport, 0 = MH transport      | default 0
- *	4 - ATSC_RST## | 1 = ATSC enable, 0 = ATSC Reset           | default 0
- *	5 - ATSC_EN    | 1 = ATSC power enable, 0 = ATSC power off | default 0
- *	6 - MH_RESET#  | 1 = MH enable, 0 = MH Reset               | default 0
- *	7 - MH_EN      | 1 = MH power enable, 0 = MH power off     | default 0
- */
-	mxl_debug("(%d)", mode);
-
-	switch (mode) {
-	case MXL111SF_GPIO_MOD_MH:
-		mxl111sf_set_gpio(state, 4, 0);
-		mxl111sf_set_gpio(state, 5, 0);
-		msleep(50);
-		mxl111sf_set_gpio(state, 7, 1);
-		msleep(50);
-		mxl111sf_set_gpio(state, 6, 1);
-		msleep(50);
-
-		mxl111sf_set_gpio(state, 3, 0);
-		break;
-	case MXL111SF_GPIO_MOD_ATSC:
-		mxl111sf_set_gpio(state, 6, 0);
-		mxl111sf_set_gpio(state, 7, 0);
-		msleep(50);
-		mxl111sf_set_gpio(state, 5, 1);
-		msleep(50);
-		mxl111sf_set_gpio(state, 4, 1);
-		msleep(50);
-		mxl111sf_set_gpio(state, 3, 1);
-		break;
-	default: /* DVBT / STANDBY */
-		mxl111sf_init_port_expander(state);
-		break;
-	}
-	return 0;
-}
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/dvb/dvb-usb/mxl111sf-gpio.h b/drivers/media/dvb/dvb-usb/mxl111sf-gpio.h
deleted file mode 100644
index 0220f54..0000000
--- a/drivers/media/dvb/dvb-usb/mxl111sf-gpio.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- *  mxl111sf-gpio.h - driver for the MaxLinear MXL111SF
- *
- *  Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef _DVB_USB_MXL111SF_GPIO_H_
-#define _DVB_USB_MXL111SF_GPIO_H_
-
-#include "mxl111sf.h"
-
-int mxl111sf_set_gpio(struct mxl111sf_state *state, int gpio, int val);
-int mxl111sf_init_port_expander(struct mxl111sf_state *state);
-
-#define MXL111SF_GPIO_MOD_DVBT	0
-#define MXL111SF_GPIO_MOD_MH	1
-#define MXL111SF_GPIO_MOD_ATSC	2
-int mxl111sf_gpio_mode_switch(struct mxl111sf_state *state, unsigned int mode);
-
-enum mxl111sf_mux_config {
-	PIN_MUX_DEFAULT = 0,
-	PIN_MUX_TS_OUT_PARALLEL,
-	PIN_MUX_TS_OUT_SERIAL,
-	PIN_MUX_GPIO_MODE,
-	PIN_MUX_TS_SERIAL_IN_MODE_0,
-	PIN_MUX_TS_SERIAL_IN_MODE_1,
-	PIN_MUX_TS_SPI_IN_MODE_0,
-	PIN_MUX_TS_SPI_IN_MODE_1,
-	PIN_MUX_TS_PARALLEL_IN,
-	PIN_MUX_BT656_I2S_MODE,
-};
-
-int mxl111sf_config_pin_mux_modes(struct mxl111sf_state *state,
-				  enum mxl111sf_mux_config pin_mux_config);
-
-#endif /* _DVB_USB_MXL111SF_GPIO_H_ */
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/dvb/dvb-usb/mxl111sf-i2c.c b/drivers/media/dvb/dvb-usb/mxl111sf-i2c.c
deleted file mode 100644
index 3443455..0000000
--- a/drivers/media/dvb/dvb-usb/mxl111sf-i2c.c
+++ /dev/null
@@ -1,850 +0,0 @@
-/*
- *  mxl111sf-i2c.c - driver for the MaxLinear MXL111SF
- *
- *  Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include "mxl111sf-i2c.h"
-#include "mxl111sf.h"
-
-/* SW-I2C ----------------------------------------------------------------- */
-
-#define SW_I2C_ADDR		0x1a
-#define SW_I2C_EN		0x02
-#define SW_SCL_OUT		0x04
-#define SW_SDA_OUT		0x08
-#define SW_SDA_IN		0x04
-
-#define SW_I2C_BUSY_ADDR	0x2f
-#define SW_I2C_BUSY		0x02
-
-static int mxl111sf_i2c_bitbang_sendbyte(struct mxl111sf_state *state,
-					 u8 byte)
-{
-	int i, ret;
-	u8 data = 0;
-
-	mxl_i2c("(0x%02x)", byte);
-
-	ret = mxl111sf_read_reg(state, SW_I2C_BUSY_ADDR, &data);
-	if (mxl_fail(ret))
-		goto fail;
-
-	for (i = 0; i < 8; i++) {
-
-		data = (byte & (0x80 >> i)) ? SW_SDA_OUT : 0;
-
-		ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
-					 0x10 | SW_I2C_EN | data);
-		if (mxl_fail(ret))
-			goto fail;
-
-		ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
-					 0x10 | SW_I2C_EN | data | SW_SCL_OUT);
-		if (mxl_fail(ret))
-			goto fail;
-
-		ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
-					 0x10 | SW_I2C_EN | data);
-		if (mxl_fail(ret))
-			goto fail;
-	}
-
-	/* last bit was 0 so we need to release SDA */
-	if (!(byte & 1)) {
-		ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
-					 0x10 | SW_I2C_EN | SW_SDA_OUT);
-		if (mxl_fail(ret))
-			goto fail;
-	}
-
-	/* CLK high for ACK readback */
-	ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
-				 0x10 | SW_I2C_EN | SW_SCL_OUT | SW_SDA_OUT);
-	if (mxl_fail(ret))
-		goto fail;
-
-	ret = mxl111sf_read_reg(state, SW_I2C_BUSY_ADDR, &data);
-	if (mxl_fail(ret))
-		goto fail;
-
-	/* drop the CLK after getting ACK, SDA will go high right away */
-	ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
-				 0x10 | SW_I2C_EN | SW_SDA_OUT);
-	if (mxl_fail(ret))
-		goto fail;
-
-	if (data & SW_SDA_IN)
-		ret = -EIO;
-fail:
-	return ret;
-}
-
-static int mxl111sf_i2c_bitbang_recvbyte(struct mxl111sf_state *state,
-					 u8 *pbyte)
-{
-	int i, ret;
-	u8 byte = 0;
-	u8 data = 0;
-
-	mxl_i2c("()");
-
-	*pbyte = 0;
-
-	ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
-				 0x10 | SW_I2C_EN | SW_SDA_OUT);
-	if (mxl_fail(ret))
-		goto fail;
-
-	for (i = 0; i < 8; i++) {
-		ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
-					 0x10 | SW_I2C_EN |
-					 SW_SCL_OUT | SW_SDA_OUT);
-		if (mxl_fail(ret))
-			goto fail;
-
-		ret = mxl111sf_read_reg(state, SW_I2C_BUSY_ADDR, &data);
-		if (mxl_fail(ret))
-			goto fail;
-
-		if (data & SW_SDA_IN)
-			byte |= (0x80 >> i);
-
-		ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
-					 0x10 | SW_I2C_EN | SW_SDA_OUT);
-		if (mxl_fail(ret))
-			goto fail;
-	}
-	*pbyte = byte;
-fail:
-	return ret;
-}
-
-static int mxl111sf_i2c_start(struct mxl111sf_state *state)
-{
-	int ret;
-
-	mxl_i2c("()");
-
-	ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
-				 0x10 | SW_I2C_EN | SW_SCL_OUT | SW_SDA_OUT);
-	if (mxl_fail(ret))
-		goto fail;
-
-	ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
-				 0x10 | SW_I2C_EN | SW_SCL_OUT);
-	if (mxl_fail(ret))
-		goto fail;
-
-	ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
-				 0x10 | SW_I2C_EN); /* start */
-	mxl_fail(ret);
-fail:
-	return ret;
-}
-
-static int mxl111sf_i2c_stop(struct mxl111sf_state *state)
-{
-	int ret;
-
-	mxl_i2c("()");
-
-	ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
-				 0x10 | SW_I2C_EN); /* stop */
-	if (mxl_fail(ret))
-		goto fail;
-
-	ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
-				 0x10 | SW_I2C_EN | SW_SCL_OUT);
-	if (mxl_fail(ret))
-		goto fail;
-
-	ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
-				 0x10 | SW_I2C_EN | SW_SCL_OUT | SW_SDA_OUT);
-	if (mxl_fail(ret))
-		goto fail;
-
-	ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
-				 0x10 | SW_SCL_OUT | SW_SDA_OUT);
-	mxl_fail(ret);
-fail:
-	return ret;
-}
-
-static int mxl111sf_i2c_ack(struct mxl111sf_state *state)
-{
-	int ret;
-	u8 b = 0;
-
-	mxl_i2c("()");
-
-	ret = mxl111sf_read_reg(state, SW_I2C_BUSY_ADDR, &b);
-	if (mxl_fail(ret))
-		goto fail;
-
-	ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
-				 0x10 | SW_I2C_EN);
-	if (mxl_fail(ret))
-		goto fail;
-
-	/* pull SDA low */
-	ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
-				 0x10 | SW_I2C_EN | SW_SCL_OUT);
-	if (mxl_fail(ret))
-		goto fail;
-
-	ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
-				 0x10 | SW_I2C_EN | SW_SDA_OUT);
-	mxl_fail(ret);
-fail:
-	return ret;
-}
-
-static int mxl111sf_i2c_nack(struct mxl111sf_state *state)
-{
-	int ret;
-
-	mxl_i2c("()");
-
-	/* SDA high to signal last byte read from slave */
-	ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
-				 0x10 | SW_I2C_EN | SW_SCL_OUT | SW_SDA_OUT);
-	if (mxl_fail(ret))
-		goto fail;
-
-	ret = mxl111sf_write_reg(state, SW_I2C_ADDR,
-				 0x10 | SW_I2C_EN | SW_SDA_OUT);
-	mxl_fail(ret);
-fail:
-	return ret;
-}
-
-/* ------------------------------------------------------------------------ */
-
-static int mxl111sf_i2c_sw_xfer_msg(struct mxl111sf_state *state,
-				    struct i2c_msg *msg)
-{
-	int i, ret;
-
-	mxl_i2c("()");
-
-	if (msg->flags & I2C_M_RD) {
-
-		ret = mxl111sf_i2c_start(state);
-		if (mxl_fail(ret))
-			goto fail;
-
-		ret = mxl111sf_i2c_bitbang_sendbyte(state,
-						    (msg->addr << 1) | 0x01);
-		if (mxl_fail(ret)) {
-			mxl111sf_i2c_stop(state);
-			goto fail;
-		}
-
-		for (i = 0; i < msg->len; i++) {
-			ret = mxl111sf_i2c_bitbang_recvbyte(state,
-							    &msg->buf[i]);
-			if (mxl_fail(ret)) {
-				mxl111sf_i2c_stop(state);
-				goto fail;
-			}
-
-			if (i < msg->len - 1)
-				mxl111sf_i2c_ack(state);
-		}
-
-		mxl111sf_i2c_nack(state);
-
-		ret = mxl111sf_i2c_stop(state);
-		if (mxl_fail(ret))
-			goto fail;
-
-	} else {
-
-		ret = mxl111sf_i2c_start(state);
-		if (mxl_fail(ret))
-			goto fail;
-
-		ret = mxl111sf_i2c_bitbang_sendbyte(state,
-						    (msg->addr << 1) & 0xfe);
-		if (mxl_fail(ret)) {
-			mxl111sf_i2c_stop(state);
-			goto fail;
-		}
-
-		for (i = 0; i < msg->len; i++) {
-			ret = mxl111sf_i2c_bitbang_sendbyte(state,
-							    msg->buf[i]);
-			if (mxl_fail(ret)) {
-				mxl111sf_i2c_stop(state);
-				goto fail;
-			}
-		}
-
-		/* FIXME: we only want to do this on the last transaction */
-		mxl111sf_i2c_stop(state);
-	}
-fail:
-	return ret;
-}
-
-/* HW-I2C ----------------------------------------------------------------- */
-
-#define USB_WRITE_I2C_CMD     0x99
-#define USB_READ_I2C_CMD      0xdd
-#define USB_END_I2C_CMD       0xfe
-
-#define USB_WRITE_I2C_CMD_LEN   26
-#define USB_READ_I2C_CMD_LEN    24
-
-#define I2C_MUX_REG           0x30
-#define I2C_CONTROL_REG       0x00
-#define I2C_SLAVE_ADDR_REG    0x08
-#define I2C_DATA_REG          0x0c
-#define I2C_INT_STATUS_REG    0x10
-
-static int mxl111sf_i2c_send_data(struct mxl111sf_state *state,
-				  u8 index, u8 *wdata)
-{
-	int ret = mxl111sf_ctrl_msg(state->d, wdata[0],
-				    &wdata[1], 25, NULL, 0);
-	mxl_fail(ret);
-
-	return ret;
-}
-
-static int mxl111sf_i2c_get_data(struct mxl111sf_state *state,
-				 u8 index, u8 *wdata, u8 *rdata)
-{
-	int ret = mxl111sf_ctrl_msg(state->d, wdata[0],
-				    &wdata[1], 25, rdata, 24);
-	mxl_fail(ret);
-
-	return ret;
-}
-
-static u8 mxl111sf_i2c_check_status(struct mxl111sf_state *state)
-{
-	u8 status = 0;
-	u8 buf[26];
-
-	mxl_i2c_adv("()");
-
-	buf[0] = USB_READ_I2C_CMD;
-	buf[1] = 0x00;
-
-	buf[2] = I2C_INT_STATUS_REG;
-	buf[3] = 0x00;
-	buf[4] = 0x00;
-
-	buf[5] = USB_END_I2C_CMD;
-
-	mxl111sf_i2c_get_data(state, 0, buf, buf);
-
-	if (buf[1] & 0x04)
-		status = 1;
-
-	return status;
-}
-
-static u8 mxl111sf_i2c_check_fifo(struct mxl111sf_state *state)
-{
-	u8 status = 0;
-	u8 buf[26];
-
-	mxl_i2c("()");
-
-	buf[0] = USB_READ_I2C_CMD;
-	buf[1] = 0x00;
-
-	buf[2] = I2C_MUX_REG;
-	buf[3] = 0x00;
-	buf[4] = 0x00;
-
-	buf[5] = I2C_INT_STATUS_REG;
-	buf[6] = 0x00;
-	buf[7] = 0x00;
-	buf[8] = USB_END_I2C_CMD;
-
-	mxl111sf_i2c_get_data(state, 0, buf, buf);
-
-	if (0x08 == (buf[1] & 0x08))
-		status = 1;
-
-	if ((buf[5] & 0x02) == 0x02)
-		mxl_i2c("(buf[5] & 0x02) == 0x02"); /* FIXME */
-
-	return status;
-}
-
-static int mxl111sf_i2c_readagain(struct mxl111sf_state *state,
-				  u8 count, u8 *rbuf)
-{
-	u8 i2c_w_data[26];
-	u8 i2c_r_data[24];
-	u8 i = 0;
-	u8 fifo_status = 0;
-	int status = 0;
-
-	mxl_i2c("read %d bytes", count);
-
-	while ((fifo_status == 0) && (i++ < 5))
-		fifo_status = mxl111sf_i2c_check_fifo(state);
-
-	i2c_w_data[0] = 0xDD;
-	i2c_w_data[1] = 0x00;
-
-	for (i = 2; i < 26; i++)
-		i2c_w_data[i] = 0xFE;
-
-	for (i = 0; i < count; i++) {
-		i2c_w_data[2+(i*3)] = 0x0C;
-		i2c_w_data[3+(i*3)] = 0x00;
-		i2c_w_data[4+(i*3)] = 0x00;
-	}
-
-	mxl111sf_i2c_get_data(state, 0, i2c_w_data, i2c_r_data);
-
-	/* Check for I2C NACK status */
-	if (mxl111sf_i2c_check_status(state) == 1) {
-		mxl_i2c("error!");
-	} else {
-		for (i = 0; i < count; i++) {
-			rbuf[i] = i2c_r_data[(i*3)+1];
-			mxl_i2c("%02x\t %02x",
-				i2c_r_data[(i*3)+1],
-				i2c_r_data[(i*3)+2]);
-		}
-
-		status = 1;
-	}
-
-	return status;
-}
-
-#define HWI2C400 1
-static int mxl111sf_i2c_hw_xfer_msg(struct mxl111sf_state *state,
-				    struct i2c_msg *msg)
-{
-	int i, k, ret = 0;
-	u16 index = 0;
-	u8 buf[26];
-	u8 i2c_r_data[24];
-	u16 block_len;
-	u16 left_over_len;
-	u8 rd_status[8];
-	u8 ret_status;
-	u8 readbuff[26];
-
-	mxl_i2c("addr: 0x%02x, read buff len: %d, write buff len: %d",
-		msg->addr, (msg->flags & I2C_M_RD) ? msg->len : 0,
-		(!(msg->flags & I2C_M_RD)) ? msg->len : 0);
-
-	for (index = 0; index < 26; index++)
-		buf[index] = USB_END_I2C_CMD;
-
-	/* command to indicate data payload is destined for I2C interface */
-	buf[0] = USB_WRITE_I2C_CMD;
-	buf[1] = 0x00;
-
-	/* enable I2C interface */
-	buf[2] = I2C_MUX_REG;
-	buf[3] = 0x80;
-	buf[4] = 0x00;
-
-	/* enable I2C interface */
-	buf[5] = I2C_MUX_REG;
-	buf[6] = 0x81;
-	buf[7] = 0x00;
-
-	/* set Timeout register on I2C interface */
-	buf[8] = 0x14;
-	buf[9] = 0xff;
-	buf[10] = 0x00;
-#if 0
-	/* enable Interrupts on I2C interface */
-	buf[8] = 0x24;
-	buf[9] = 0xF7;
-	buf[10] = 0x00;
-#endif
-	buf[11] = 0x24;
-	buf[12] = 0xF7;
-	buf[13] = 0x00;
-
-	ret = mxl111sf_i2c_send_data(state, 0, buf);
-
-	/* write data on I2C bus */
-	if (!(msg->flags & I2C_M_RD) && (msg->len > 0)) {
-		mxl_i2c("%d\t%02x", msg->len, msg->buf[0]);
-
-		/* control register on I2C interface to initialize I2C bus */
-		buf[2] = I2C_CONTROL_REG;
-		buf[3] = 0x5E;
-		buf[4] = (HWI2C400) ? 0x03 : 0x0D;
-
-		/* I2C Slave device Address */
-		buf[5] = I2C_SLAVE_ADDR_REG;
-		buf[6] = (msg->addr);
-		buf[7] = 0x00;
-		buf[8] = USB_END_I2C_CMD;
-		ret = mxl111sf_i2c_send_data(state, 0, buf);
-
-		/* check for slave device status */
-		if (mxl111sf_i2c_check_status(state) == 1) {
-			mxl_i2c("NACK writing slave address %02x",
-				msg->addr);
-			/* if NACK, stop I2C bus and exit */
-			buf[2] = I2C_CONTROL_REG;
-			buf[3] = 0x4E;
-			buf[4] = (HWI2C400) ? 0x03 : 0x0D;
-			ret = -EIO;
-			goto exit;
-		}
-
-		/* I2C interface can do I2C operations in block of 8 bytes of
-		   I2C data. calculation to figure out number of blocks of i2c
-		   data required to program */
-		block_len = (msg->len / 8);
-		left_over_len = (msg->len % 8);
-		index = 0;
-
-		mxl_i2c("block_len %d, left_over_len %d",
-			block_len, left_over_len);
-
-		for (index = 0; index < block_len; index++) {
-			for (i = 0; i < 8; i++) {
-				/* write data on I2C interface */
-				buf[2+(i*3)] = I2C_DATA_REG;
-				buf[3+(i*3)] = msg->buf[(index*8)+i];
-				buf[4+(i*3)] = 0x00;
-			}
-
-			ret = mxl111sf_i2c_send_data(state, 0, buf);
-
-			/* check for I2C NACK status */
-			if (mxl111sf_i2c_check_status(state) == 1) {
-				mxl_i2c("NACK writing slave address %02x",
-					msg->addr);
-
-				/* if NACK, stop I2C bus and exit */
-				buf[2] = I2C_CONTROL_REG;
-				buf[3] = 0x4E;
-				buf[4] = (HWI2C400) ? 0x03 : 0x0D;
-				ret = -EIO;
-				goto exit;
-			}
-
-		}
-
-		if (left_over_len) {
-			for (k = 0; k < 26; k++)
-				buf[k] = USB_END_I2C_CMD;
-
-			buf[0] = 0x99;
-			buf[1] = 0x00;
-
-			for (i = 0; i < left_over_len; i++) {
-				buf[2+(i*3)] = I2C_DATA_REG;
-				buf[3+(i*3)] = msg->buf[(index*8)+i];
-				mxl_i2c("index = %d %d data %d",
-					index, i, msg->buf[(index*8)+i]);
-				buf[4+(i*3)] = 0x00;
-			}
-			ret = mxl111sf_i2c_send_data(state, 0, buf);
-
-			/* check for I2C NACK status */
-			if (mxl111sf_i2c_check_status(state) == 1) {
-				mxl_i2c("NACK writing slave address %02x",
-					msg->addr);
-
-				/* if NACK, stop I2C bus and exit */
-				buf[2] = I2C_CONTROL_REG;
-				buf[3] = 0x4E;
-				buf[4] = (HWI2C400) ? 0x03 : 0x0D;
-				ret = -EIO;
-				goto exit;
-			}
-
-		}
-
-		/* issue I2C STOP after write */
-		buf[2] = I2C_CONTROL_REG;
-		buf[3] = 0x4E;
-		buf[4] = (HWI2C400) ? 0x03 : 0x0D;
-
-	}
-
-	/* read data from I2C bus */
-	if ((msg->flags & I2C_M_RD) && (msg->len > 0)) {
-		mxl_i2c("read buf len %d", msg->len);
-
-		/* command to indicate data payload is
-		   destined for I2C interface */
-		buf[2] = I2C_CONTROL_REG;
-		buf[3] = 0xDF;
-		buf[4] = (HWI2C400) ? 0x03 : 0x0D;
-
-		/* I2C xfer length */
-		buf[5] = 0x14;
-		buf[6] = (msg->len & 0xFF);
-		buf[7] = 0;
-
-		/* I2C slave device Address */
-		buf[8] = I2C_SLAVE_ADDR_REG;
-		buf[9] = msg->addr;
-		buf[10] = 0x00;
-		buf[11] = USB_END_I2C_CMD;
-		ret = mxl111sf_i2c_send_data(state, 0, buf);
-
-		/* check for I2C NACK status */
-		if (mxl111sf_i2c_check_status(state) == 1) {
-			mxl_i2c("NACK reading slave address %02x",
-				msg->addr);
-
-			/* if NACK, stop I2C bus and exit */
-			buf[2] = I2C_CONTROL_REG;
-			buf[3] = 0xC7;
-			buf[4] = (HWI2C400) ? 0x03 : 0x0D;
-			ret = -EIO;
-			goto exit;
-		}
-
-		/* I2C interface can do I2C operations in block of 8 bytes of
-		   I2C data. calculation to figure out number of blocks of
-		   i2c data required to program */
-		block_len = ((msg->len) / 8);
-		left_over_len = ((msg->len) % 8);
-		index = 0;
-
-		mxl_i2c("block_len %d, left_over_len %d",
-			block_len, left_over_len);
-
-		/* command to read data from I2C interface */
-		buf[0] = USB_READ_I2C_CMD;
-		buf[1] = 0x00;
-
-		for (index = 0; index < block_len; index++) {
-			/* setup I2C read request packet on I2C interface */
-			for (i = 0; i < 8; i++) {
-				buf[2+(i*3)] = I2C_DATA_REG;
-				buf[3+(i*3)] = 0x00;
-				buf[4+(i*3)] = 0x00;
-			}
-
-			ret = mxl111sf_i2c_get_data(state, 0, buf, i2c_r_data);
-
-			/* check for I2C NACK status */
-			if (mxl111sf_i2c_check_status(state) == 1) {
-				mxl_i2c("NACK reading slave address %02x",
-					msg->addr);
-
-				/* if NACK, stop I2C bus and exit */
-				buf[2] = I2C_CONTROL_REG;
-				buf[3] = 0xC7;
-				buf[4] = (HWI2C400) ? 0x03 : 0x0D;
-				ret = -EIO;
-				goto exit;
-			}
-
-			/* copy data from i2c data payload to read buffer */
-			for (i = 0; i < 8; i++) {
-				rd_status[i] = i2c_r_data[(i*3)+2];
-
-				if (rd_status[i] == 0x04) {
-					if (i < 7) {
-						mxl_i2c("i2c fifo empty!"
-							" @ %d", i);
-						msg->buf[(index*8)+i] =
-							i2c_r_data[(i*3)+1];
-						/* read again */
-						ret_status =
-							mxl111sf_i2c_readagain(
-								state, 8-(i+1),
-								readbuff);
-						if (ret_status == 1) {
-							for (k = 0;
-							     k < 8-(i+1);
-							     k++) {
-
-					msg->buf[(index*8)+(k+i+1)] =
-						readbuff[k];
-					mxl_i2c("read data: %02x\t %02x",
-						msg->buf[(index*8)+(k+i)],
-						(index*8)+(k+i));
-					mxl_i2c("read data: %02x\t %02x",
-						msg->buf[(index*8)+(k+i+1)],
-						readbuff[k]);
-
-							}
-							goto stop_copy;
-						} else {
-							mxl_i2c("readagain "
-								"ERROR!");
-						}
-					} else {
-						msg->buf[(index*8)+i] =
-							i2c_r_data[(i*3)+1];
-					}
-				} else {
-					msg->buf[(index*8)+i] =
-						i2c_r_data[(i*3)+1];
-				}
-			}
-stop_copy:
-			;
-
-		}
-
-		if (left_over_len) {
-			for (k = 0; k < 26; k++)
-				buf[k] = USB_END_I2C_CMD;
-
-			buf[0] = 0xDD;
-			buf[1] = 0x00;
-
-			for (i = 0; i < left_over_len; i++) {
-				buf[2+(i*3)] = I2C_DATA_REG;
-				buf[3+(i*3)] = 0x00;
-				buf[4+(i*3)] = 0x00;
-			}
-			ret = mxl111sf_i2c_get_data(state, 0, buf,
-						    i2c_r_data);
-
-			/* check for I2C NACK status */
-			if (mxl111sf_i2c_check_status(state) == 1) {
-				mxl_i2c("NACK reading slave address %02x",
-					msg->addr);
-
-				/* if NACK, stop I2C bus and exit */
-				buf[2] = I2C_CONTROL_REG;
-				buf[3] = 0xC7;
-				buf[4] = (HWI2C400) ? 0x03 : 0x0D;
-				ret = -EIO;
-				goto exit;
-			}
-
-			for (i = 0; i < left_over_len; i++) {
-				msg->buf[(block_len*8)+i] =
-					i2c_r_data[(i*3)+1];
-				mxl_i2c("read data: %02x\t %02x",
-					i2c_r_data[(i*3)+1],
-					i2c_r_data[(i*3)+2]);
-			}
-		}
-
-		/* indicate I2C interface to issue NACK
-		   after next I2C read op */
-		buf[0] = USB_WRITE_I2C_CMD;
-		buf[1] = 0x00;
-
-		/* control register */
-		buf[2] = I2C_CONTROL_REG;
-		buf[3] = 0x17;
-		buf[4] = (HWI2C400) ? 0x03 : 0x0D;
-
-		buf[5] = USB_END_I2C_CMD;
-		ret = mxl111sf_i2c_send_data(state, 0, buf);
-
-		/* control register */
-		buf[2] = I2C_CONTROL_REG;
-		buf[3] = 0xC7;
-		buf[4] = (HWI2C400) ? 0x03 : 0x0D;
-
-	}
-exit:
-	/* STOP and disable I2C MUX */
-	buf[0] = USB_WRITE_I2C_CMD;
-	buf[1] = 0x00;
-
-	/* de-initilize I2C BUS */
-	buf[5] = USB_END_I2C_CMD;
-	mxl111sf_i2c_send_data(state, 0, buf);
-
-	/* Control Register */
-	buf[2] = I2C_CONTROL_REG;
-	buf[3] = 0xDF;
-	buf[4] = 0x03;
-
-	/* disable I2C interface */
-	buf[5] = I2C_MUX_REG;
-	buf[6] = 0x00;
-	buf[7] = 0x00;
-
-	/* de-initilize I2C BUS */
-	buf[8] = USB_END_I2C_CMD;
-	mxl111sf_i2c_send_data(state, 0, buf);
-
-	/* disable I2C interface */
-	buf[2] = I2C_MUX_REG;
-	buf[3] = 0x81;
-	buf[4] = 0x00;
-
-	/* disable I2C interface */
-	buf[5] = I2C_MUX_REG;
-	buf[6] = 0x00;
-	buf[7] = 0x00;
-
-	/* disable I2C interface */
-	buf[8] = I2C_MUX_REG;
-	buf[9] = 0x00;
-	buf[10] = 0x00;
-
-	buf[11] = USB_END_I2C_CMD;
-	mxl111sf_i2c_send_data(state, 0, buf);
-
-	return ret;
-}
-
-/* ------------------------------------------------------------------------ */
-
-int mxl111sf_i2c_xfer(struct i2c_adapter *adap,
-		      struct i2c_msg msg[], int num)
-{
-	struct dvb_usb_device *d = i2c_get_adapdata(adap);
-	struct mxl111sf_state *state = d->priv;
-	int hwi2c = (state->chip_rev > MXL111SF_V6);
-	int i, ret;
-
-	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
-		return -EAGAIN;
-
-	for (i = 0; i < num; i++) {
-		ret = (hwi2c) ?
-			mxl111sf_i2c_hw_xfer_msg(state, &msg[i]) :
-			mxl111sf_i2c_sw_xfer_msg(state, &msg[i]);
-		if (mxl_fail(ret)) {
-			mxl_debug_adv("failed with error %d on i2c "
-				      "transaction %d of %d, %sing %d bytes "
-				      "to/from 0x%02x", ret, i+1, num,
-				      (msg[i].flags & I2C_M_RD) ?
-				      "read" : "writ",
-				      msg[i].len, msg[i].addr);
-
-			break;
-		}
-	}
-
-	mutex_unlock(&d->i2c_mutex);
-
-	return i == num ? num : -EREMOTEIO;
-}
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/dvb/dvb-usb/mxl111sf-i2c.h b/drivers/media/dvb/dvb-usb/mxl111sf-i2c.h
deleted file mode 100644
index a57a45f..0000000
--- a/drivers/media/dvb/dvb-usb/mxl111sf-i2c.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- *  mxl111sf-i2c.h - driver for the MaxLinear MXL111SF
- *
- *  Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef _DVB_USB_MXL111SF_I2C_H_
-#define _DVB_USB_MXL111SF_I2C_H_
-
-#include <linux/i2c.h>
-
-int mxl111sf_i2c_xfer(struct i2c_adapter *adap,
-		      struct i2c_msg msg[], int num);
-
-#endif /* _DVB_USB_MXL111SF_I2C_H_ */
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/dvb/dvb-usb/mxl111sf-phy.c b/drivers/media/dvb/dvb-usb/mxl111sf-phy.c
deleted file mode 100644
index b741b3a..0000000
--- a/drivers/media/dvb/dvb-usb/mxl111sf-phy.c
+++ /dev/null
@@ -1,343 +0,0 @@
-/*
- *  mxl111sf-phy.c - driver for the MaxLinear MXL111SF
- *
- *  Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include "mxl111sf-phy.h"
-#include "mxl111sf-reg.h"
-
-int mxl111sf_init_tuner_demod(struct mxl111sf_state *state)
-{
-	struct mxl111sf_reg_ctrl_info mxl_111_overwrite_default[] = {
-		{0x07, 0xff, 0x0c},
-		{0x58, 0xff, 0x9d},
-		{0x09, 0xff, 0x00},
-		{0x06, 0xff, 0x06},
-		{0xc8, 0xff, 0x40}, /* ED_LE_WIN_OLD = 0 */
-		{0x8d, 0x01, 0x01}, /* NEGATE_Q */
-		{0x32, 0xff, 0xac}, /* DIG_RFREFSELECT = 12 */
-		{0x42, 0xff, 0x43}, /* DIG_REG_AMP = 4 */
-		{0x74, 0xff, 0xc4}, /* SSPUR_FS_PRIO = 4 */
-		{0x71, 0xff, 0xe6}, /* SPUR_ROT_PRIO_VAL = 1 */
-		{0x83, 0xff, 0x64}, /* INF_FILT1_THD_SC = 100 */
-		{0x85, 0xff, 0x64}, /* INF_FILT2_THD_SC = 100 */
-		{0x88, 0xff, 0xf0}, /* INF_THD = 240 */
-		{0x6f, 0xf0, 0xb0}, /* DFE_DLY = 11 */
-		{0x00, 0xff, 0x01}, /* Change to page 1 */
-		{0x81, 0xff, 0x11}, /* DSM_FERR_BYPASS = 1 */
-		{0xf4, 0xff, 0x07}, /* DIG_FREQ_CORR = 1 */
-		{0xd4, 0x1f, 0x0f}, /* SPUR_TEST_NOISE_TH = 15 */
-		{0xd6, 0xff, 0x0c}, /* SPUR_TEST_NOISE_PAPR = 12 */
-		{0x00, 0xff, 0x00}, /* Change to page 0 */
-		{0,    0,    0}
-	};
-
-	mxl_debug("()");
-
-	return mxl111sf_ctrl_program_regs(state, mxl_111_overwrite_default);
-}
-
-int mxl1x1sf_soft_reset(struct mxl111sf_state *state)
-{
-	int ret;
-	mxl_debug("()");
-
-	ret = mxl111sf_write_reg(state, 0xff, 0x00); /* AIC */
-	if (mxl_fail(ret))
-		goto fail;
-	ret = mxl111sf_write_reg(state, 0x02, 0x01); /* get out of reset */
-	mxl_fail(ret);
-fail:
-	return ret;
-}
-
-int mxl1x1sf_set_device_mode(struct mxl111sf_state *state, int mode)
-{
-	int ret;
-
-	mxl_debug("(%s)", MXL_SOC_MODE == mode ?
-		"MXL_SOC_MODE" : "MXL_TUNER_MODE");
-
-	/* set device mode */
-	ret = mxl111sf_write_reg(state, 0x03,
-				 MXL_SOC_MODE == mode ? 0x01 : 0x00);
-	if (mxl_fail(ret))
-		goto fail;
-
-	ret = mxl111sf_write_reg_mask(state,
-				      0x7d, 0x40, MXL_SOC_MODE == mode ?
-				      0x00 : /* enable impulse noise filter,
-						INF_BYP = 0 */
-				      0x40); /* disable impulse noise filter,
-						INF_BYP = 1 */
-	if (mxl_fail(ret))
-		goto fail;
-
-	state->device_mode = mode;
-fail:
-	return ret;
-}
-
-/* power up tuner */
-int mxl1x1sf_top_master_ctrl(struct mxl111sf_state *state, int onoff)
-{
-	mxl_debug("(%d)", onoff);
-
-	return mxl111sf_write_reg(state, 0x01, onoff ? 0x01 : 0x00);
-}
-
-int mxl111sf_disable_656_port(struct mxl111sf_state *state)
-{
-	mxl_debug("()");
-
-	return mxl111sf_write_reg_mask(state, 0x12, 0x04, 0x00);
-}
-
-int mxl111sf_enable_usb_output(struct mxl111sf_state *state)
-{
-	mxl_debug("()");
-
-	return mxl111sf_write_reg_mask(state, 0x17, 0x40, 0x00);
-}
-
-/* initialize TSIF as input port of MxL1X1SF for MPEG2 data transfer */
-int mxl111sf_config_mpeg_in(struct mxl111sf_state *state,
-			    unsigned int parallel_serial,
-			    unsigned int msb_lsb_1st,
-			    unsigned int clock_phase,
-			    unsigned int mpeg_valid_pol,
-			    unsigned int mpeg_sync_pol)
-{
-	int ret;
-	u8 mode, tmp;
-
-	mxl_debug("(%u,%u,%u,%u,%u)", parallel_serial, msb_lsb_1st,
-		  clock_phase, mpeg_valid_pol, mpeg_sync_pol);
-
-	/* Enable PIN MUX */
-	ret = mxl111sf_write_reg(state, V6_PIN_MUX_MODE_REG, V6_ENABLE_PIN_MUX);
-	mxl_fail(ret);
-
-	/* Configure MPEG Clock phase */
-	mxl111sf_read_reg(state, V6_MPEG_IN_CLK_INV_REG, &mode);
-
-	if (clock_phase == TSIF_NORMAL)
-		mode &= ~V6_INVERTED_CLK_PHASE;
-	else
-		mode |= V6_INVERTED_CLK_PHASE;
-
-	ret = mxl111sf_write_reg(state, V6_MPEG_IN_CLK_INV_REG, mode);
-	mxl_fail(ret);
-
-	/* Configure data input mode, MPEG Valid polarity, MPEG Sync polarity
-	 * Get current configuration */
-	ret = mxl111sf_read_reg(state, V6_MPEG_IN_CTRL_REG, &mode);
-	mxl_fail(ret);
-
-	/* Data Input mode */
-	if (parallel_serial == TSIF_INPUT_PARALLEL) {
-		/* Disable serial mode */
-		mode &= ~V6_MPEG_IN_DATA_SERIAL;
-
-		/* Enable Parallel mode */
-		mode |= V6_MPEG_IN_DATA_PARALLEL;
-	} else {
-		/* Disable Parallel mode */
-		mode &= ~V6_MPEG_IN_DATA_PARALLEL;
-
-		/* Enable Serial Mode */
-		mode |= V6_MPEG_IN_DATA_SERIAL;
-
-		/* If serial interface is chosen, configure
-		   MSB or LSB order in transmission */
-		ret = mxl111sf_read_reg(state,
-					V6_MPEG_INOUT_BIT_ORDER_CTRL_REG,
-					&tmp);
-		mxl_fail(ret);
-
-		if (msb_lsb_1st == MPEG_SER_MSB_FIRST_ENABLED)
-			tmp |= V6_MPEG_SER_MSB_FIRST;
-		else
-			tmp &= ~V6_MPEG_SER_MSB_FIRST;
-
-		ret = mxl111sf_write_reg(state,
-					 V6_MPEG_INOUT_BIT_ORDER_CTRL_REG,
-					 tmp);
-		mxl_fail(ret);
-	}
-
-	/* MPEG Sync polarity */
-	if (mpeg_sync_pol == TSIF_NORMAL)
-		mode &= ~V6_INVERTED_MPEG_SYNC;
-	else
-		mode |= V6_INVERTED_MPEG_SYNC;
-
-	/* MPEG Valid polarity */
-	if (mpeg_valid_pol == 0)
-		mode &= ~V6_INVERTED_MPEG_VALID;
-	else
-		mode |= V6_INVERTED_MPEG_VALID;
-
-	ret = mxl111sf_write_reg(state, V6_MPEG_IN_CTRL_REG, mode);
-	mxl_fail(ret);
-
-	return ret;
-}
-
-int mxl111sf_init_i2s_port(struct mxl111sf_state *state, u8 sample_size)
-{
-	static struct mxl111sf_reg_ctrl_info init_i2s[] = {
-		{0x1b, 0xff, 0x1e}, /* pin mux mode, Choose 656/I2S input */
-		{0x15, 0x60, 0x60}, /* Enable I2S */
-		{0x17, 0xe0, 0x20}, /* Input, MPEG MODE USB,
-				       Inverted 656 Clock, I2S_SOFT_RESET,
-				       0 : Normal operation, 1 : Reset State */
-#if 0
-		{0x12, 0x01, 0x00}, /* AUDIO_IRQ_CLR (Overflow Indicator) */
-#endif
-		{0x00, 0xff, 0x02}, /* Change to Control Page */
-		{0x26, 0x0d, 0x0d}, /* I2S_MODE & BT656_SRC_SEL for FPGA only */
-		{0x00, 0xff, 0x00},
-		{0,    0,    0}
-	};
-	int ret;
-
-	mxl_debug("(0x%02x)", sample_size);
-
-	ret = mxl111sf_ctrl_program_regs(state, init_i2s);
-	if (mxl_fail(ret))
-		goto fail;
-
-	ret = mxl111sf_write_reg(state, V6_I2S_NUM_SAMPLES_REG, sample_size);
-	mxl_fail(ret);
-fail:
-	return ret;
-}
-
-int mxl111sf_disable_i2s_port(struct mxl111sf_state *state)
-{
-	static struct mxl111sf_reg_ctrl_info disable_i2s[] = {
-		{0x15, 0x40, 0x00},
-		{0,    0,    0}
-	};
-
-	mxl_debug("()");
-
-	return mxl111sf_ctrl_program_regs(state, disable_i2s);
-}
-
-int mxl111sf_config_i2s(struct mxl111sf_state *state,
-			u8 msb_start_pos, u8 data_width)
-{
-	int ret;
-	u8 tmp;
-
-	mxl_debug("(0x%02x, 0x%02x)", msb_start_pos, data_width);
-
-	ret = mxl111sf_read_reg(state, V6_I2S_STREAM_START_BIT_REG, &tmp);
-	if (mxl_fail(ret))
-		goto fail;
-
-	tmp &= 0xe0;
-	tmp |= msb_start_pos;
-	ret = mxl111sf_write_reg(state, V6_I2S_STREAM_START_BIT_REG, tmp);
-	if (mxl_fail(ret))
-		goto fail;
-
-	ret = mxl111sf_read_reg(state, V6_I2S_STREAM_END_BIT_REG, &tmp);
-	if (mxl_fail(ret))
-		goto fail;
-
-	tmp &= 0xe0;
-	tmp |= data_width;
-	ret = mxl111sf_write_reg(state, V6_I2S_STREAM_END_BIT_REG, tmp);
-	mxl_fail(ret);
-fail:
-	return ret;
-}
-
-int mxl111sf_config_spi(struct mxl111sf_state *state, int onoff)
-{
-	u8 val;
-	int ret;
-
-	mxl_debug("(%d)", onoff);
-
-	ret = mxl111sf_write_reg(state, 0x00, 0x02);
-	if (mxl_fail(ret))
-		goto fail;
-
-	ret = mxl111sf_read_reg(state, V8_SPI_MODE_REG, &val);
-	if (mxl_fail(ret))
-		goto fail;
-
-	if (onoff)
-		val |= 0x04;
-	else
-		val &= ~0x04;
-
-	ret = mxl111sf_write_reg(state, V8_SPI_MODE_REG, val);
-	if (mxl_fail(ret))
-		goto fail;
-
-	ret = mxl111sf_write_reg(state, 0x00, 0x00);
-	mxl_fail(ret);
-fail:
-	return ret;
-}
-
-int mxl111sf_idac_config(struct mxl111sf_state *state,
-			 u8 control_mode, u8 current_setting,
-			 u8 current_value, u8 hysteresis_value)
-{
-	int ret;
-	u8 val;
-	/* current value will be set for both automatic & manual IDAC control */
-	val = current_value;
-
-	if (control_mode == IDAC_MANUAL_CONTROL) {
-		/* enable manual control of IDAC */
-		val |= IDAC_MANUAL_CONTROL_BIT_MASK;
-
-		if (current_setting == IDAC_CURRENT_SINKING_ENABLE)
-			/* enable current sinking in manual mode */
-			val |= IDAC_CURRENT_SINKING_BIT_MASK;
-		else
-			/* disable current sinking in manual mode */
-			val &= ~IDAC_CURRENT_SINKING_BIT_MASK;
-	} else {
-		/* disable manual control of IDAC */
-		val &= ~IDAC_MANUAL_CONTROL_BIT_MASK;
-
-		/* set hysteresis value  reg: 0x0B<5:0> */
-		ret = mxl111sf_write_reg(state, V6_IDAC_HYSTERESIS_REG,
-					 (hysteresis_value & 0x3F));
-		mxl_fail(ret);
-	}
-
-	ret = mxl111sf_write_reg(state, V6_IDAC_SETTINGS_REG, val);
-	mxl_fail(ret);
-
-	return ret;
-}
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/dvb/dvb-usb/mxl111sf-phy.h b/drivers/media/dvb/dvb-usb/mxl111sf-phy.h
deleted file mode 100644
index f075607..0000000
--- a/drivers/media/dvb/dvb-usb/mxl111sf-phy.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- *  mxl111sf-phy.h - driver for the MaxLinear MXL111SF
- *
- *  Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef _DVB_USB_MXL111SF_PHY_H_
-#define _DVB_USB_MXL111SF_PHY_H_
-
-#include "mxl111sf.h"
-
-int mxl1x1sf_soft_reset(struct mxl111sf_state *state);
-int mxl1x1sf_set_device_mode(struct mxl111sf_state *state, int mode);
-int mxl1x1sf_top_master_ctrl(struct mxl111sf_state *state, int onoff);
-int mxl111sf_disable_656_port(struct mxl111sf_state *state);
-int mxl111sf_init_tuner_demod(struct mxl111sf_state *state);
-int mxl111sf_enable_usb_output(struct mxl111sf_state *state);
-int mxl111sf_config_mpeg_in(struct mxl111sf_state *state,
-			    unsigned int parallel_serial,
-			    unsigned int msb_lsb_1st,
-			    unsigned int clock_phase,
-			    unsigned int mpeg_valid_pol,
-			    unsigned int mpeg_sync_pol);
-int mxl111sf_config_i2s(struct mxl111sf_state *state,
-			u8 msb_start_pos, u8 data_width);
-int mxl111sf_init_i2s_port(struct mxl111sf_state *state, u8 sample_size);
-int mxl111sf_disable_i2s_port(struct mxl111sf_state *state);
-int mxl111sf_config_spi(struct mxl111sf_state *state, int onoff);
-int mxl111sf_idac_config(struct mxl111sf_state *state,
-			 u8 control_mode, u8 current_setting,
-			 u8 current_value, u8 hysteresis_value);
-
-#endif /* _DVB_USB_MXL111SF_PHY_H_ */
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/dvb/dvb-usb/mxl111sf-reg.h b/drivers/media/dvb/dvb-usb/mxl111sf-reg.h
deleted file mode 100644
index 17831b0..0000000
--- a/drivers/media/dvb/dvb-usb/mxl111sf-reg.h
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- *  mxl111sf-reg.h - driver for the MaxLinear MXL111SF
- *
- *  Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef _DVB_USB_MXL111SF_REG_H_
-#define _DVB_USB_MXL111SF_REG_H_
-
-#define CHIP_ID_REG                  0xFC
-#define TOP_CHIP_REV_ID_REG          0xFA
-
-#define V6_SNR_RB_LSB_REG            0x27
-#define V6_SNR_RB_MSB_REG            0x28
-
-#define V6_N_ACCUMULATE_REG          0x11
-#define V6_RS_AVG_ERRORS_LSB_REG     0x2C
-#define V6_RS_AVG_ERRORS_MSB_REG     0x2D
-
-#define V6_IRQ_STATUS_REG            0x24
-#define  IRQ_MASK_FEC_LOCK       0x10
-
-#define V6_SYNC_LOCK_REG             0x28
-#define SYNC_LOCK_MASK           0x10
-
-#define V6_RS_LOCK_DET_REG           0x28
-#define  RS_LOCK_DET_MASK        0x08
-
-#define V6_INITACQ_NODETECT_REG    0x20
-#define V6_FORCE_NFFT_CPSIZE_REG   0x20
-
-#define V6_CODE_RATE_TPS_REG       0x29
-#define V6_CODE_RATE_TPS_MASK      0x07
-
-
-#define V6_CP_LOCK_DET_REG        0x28
-#define V6_CP_LOCK_DET_MASK       0x04
-
-#define V6_TPS_HIERACHY_REG        0x29
-#define V6_TPS_HIERARCHY_INFO_MASK  0x40
-
-#define V6_MODORDER_TPS_REG        0x2A
-#define V6_PARAM_CONSTELLATION_MASK   0x30
-
-#define V6_MODE_TPS_REG            0x2A
-#define V6_PARAM_FFT_MODE_MASK        0x0C
-
-
-#define V6_CP_TPS_REG             0x29
-#define V6_PARAM_GI_MASK              0x30
-
-#define V6_TPS_LOCK_REG           0x2A
-#define V6_PARAM_TPS_LOCK_MASK        0x40
-
-#define V6_FEC_PER_COUNT_REG      0x2E
-#define V6_FEC_PER_SCALE_REG      0x2B
-#define V6_FEC_PER_SCALE_MASK        0x03
-#define V6_FEC_PER_CLR_REG        0x20
-#define V6_FEC_PER_CLR_MASK          0x01
-
-#define V6_PIN_MUX_MODE_REG       0x1B
-#define V6_ENABLE_PIN_MUX            0x1E
-
-#define V6_I2S_NUM_SAMPLES_REG    0x16
-
-#define V6_MPEG_IN_CLK_INV_REG    0x17
-#define V6_MPEG_IN_CTRL_REG       0x18
-
-#define V6_INVERTED_CLK_PHASE       0x20
-#define V6_MPEG_IN_DATA_PARALLEL    0x01
-#define V6_MPEG_IN_DATA_SERIAL      0x02
-
-#define V6_INVERTED_MPEG_SYNC       0x04
-#define V6_INVERTED_MPEG_VALID      0x08
-
-#define TSIF_INPUT_PARALLEL         0
-#define TSIF_INPUT_SERIAL           1
-#define TSIF_NORMAL                 0
-
-#define V6_MPEG_INOUT_BIT_ORDER_CTRL_REG  0x19
-#define V6_MPEG_SER_MSB_FIRST                0x80
-#define MPEG_SER_MSB_FIRST_ENABLED        0x01
-
-#define V6_656_I2S_BUFF_STATUS_REG   0x2F
-#define V6_656_OVERFLOW_MASK_BIT         0x08
-#define V6_I2S_OVERFLOW_MASK_BIT         0x01
-
-#define V6_I2S_STREAM_START_BIT_REG  0x14
-#define V6_I2S_STREAM_END_BIT_REG    0x15
-#define I2S_RIGHT_JUSTIFIED     0
-#define I2S_LEFT_JUSTIFIED      1
-#define I2S_DATA_FORMAT         2
-
-#define V6_TUNER_LOOP_THRU_CONTROL_REG  0x09
-#define V6_ENABLE_LOOP_THRU               0x01
-
-#define TOTAL_NUM_IF_OUTPUT_FREQ       16
-
-#define TUNER_NORMAL_IF_SPECTRUM       0x0
-#define TUNER_INVERT_IF_SPECTRUM       0x10
-
-#define V6_TUNER_IF_SEL_REG              0x06
-#define V6_TUNER_IF_FCW_REG              0x3C
-#define V6_TUNER_IF_FCW_BYP_REG          0x3D
-#define V6_RF_LOCK_STATUS_REG            0x23
-
-#define NUM_DIG_TV_CHANNEL     1000
-
-#define V6_DIG_CLK_FREQ_SEL_REG  0x07
-#define V6_REF_SYNTH_INT_REG     0x5C
-#define V6_REF_SYNTH_REMAIN_REG  0x58
-#define V6_DIG_RFREFSELECT_REG   0x32
-#define V6_XTAL_CLK_OUT_GAIN_REG   0x31
-#define V6_TUNER_LOOP_THRU_CTRL_REG      0x09
-#define V6_DIG_XTAL_ENABLE_REG  0x06
-#define V6_DIG_XTAL_BIAS_REG  0x66
-#define V6_XTAL_CAP_REG    0x08
-
-#define V6_GPO_CTRL_REG     0x18
-#define MXL_GPO_0           0x00
-#define MXL_GPO_1           0x01
-#define V6_GPO_0_MASK       0x10
-#define V6_GPO_1_MASK       0x20
-
-#define V6_111SF_GPO_CTRL_REG     0x19
-#define MXL_111SF_GPO_1               0x00
-#define MXL_111SF_GPO_2               0x01
-#define MXL_111SF_GPO_3               0x02
-#define MXL_111SF_GPO_4               0x03
-#define MXL_111SF_GPO_5               0x04
-#define MXL_111SF_GPO_6               0x05
-#define MXL_111SF_GPO_7               0x06
-
-#define MXL_111SF_GPO_0_MASK          0x01
-#define MXL_111SF_GPO_1_MASK          0x02
-#define MXL_111SF_GPO_2_MASK          0x04
-#define MXL_111SF_GPO_3_MASK          0x08
-#define MXL_111SF_GPO_4_MASK          0x10
-#define MXL_111SF_GPO_5_MASK          0x20
-#define MXL_111SF_GPO_6_MASK          0x40
-
-#define V6_ATSC_CONFIG_REG  0x0A
-
-#define MXL_MODE_REG    0x03
-#define START_TUNE_REG  0x1C
-
-#define V6_IDAC_HYSTERESIS_REG    0x0B
-#define V6_IDAC_SETTINGS_REG      0x0C
-#define IDAC_MANUAL_CONTROL             1
-#define IDAC_CURRENT_SINKING_ENABLE     1
-#define IDAC_MANUAL_CONTROL_BIT_MASK      0x80
-#define IDAC_CURRENT_SINKING_BIT_MASK     0x40
-
-#define V8_SPI_MODE_REG  0xE9
-
-#define V6_DIG_RF_PWR_LSB_REG  0x46
-#define V6_DIG_RF_PWR_MSB_REG  0x47
-
-#endif /* _DVB_USB_MXL111SF_REG_H_ */
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/dvb/dvb-usb/mxl111sf-tuner.c b/drivers/media/dvb/dvb-usb/mxl111sf-tuner.c
deleted file mode 100644
index 74da5bb1..0000000
--- a/drivers/media/dvb/dvb-usb/mxl111sf-tuner.c
+++ /dev/null
@@ -1,525 +0,0 @@
-/*
- *  mxl111sf-tuner.c - driver for the MaxLinear MXL111SF CMOS tuner
- *
- *  Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include "mxl111sf-tuner.h"
-#include "mxl111sf-phy.h"
-#include "mxl111sf-reg.h"
-
-/* debug */
-static int mxl111sf_tuner_debug;
-module_param_named(debug, mxl111sf_tuner_debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able)).");
-
-#define mxl_dbg(fmt, arg...) \
-	if (mxl111sf_tuner_debug) \
-		mxl_printk(KERN_DEBUG, fmt, ##arg)
-
-/* ------------------------------------------------------------------------ */
-
-struct mxl111sf_tuner_state {
-	struct mxl111sf_state *mxl_state;
-
-	struct mxl111sf_tuner_config *cfg;
-
-	enum mxl_if_freq if_freq;
-
-	u32 frequency;
-	u32 bandwidth;
-};
-
-static int mxl111sf_tuner_read_reg(struct mxl111sf_tuner_state *state,
-				   u8 addr, u8 *data)
-{
-	return (state->cfg->read_reg) ?
-		state->cfg->read_reg(state->mxl_state, addr, data) :
-		-EINVAL;
-}
-
-static int mxl111sf_tuner_write_reg(struct mxl111sf_tuner_state *state,
-				    u8 addr, u8 data)
-{
-	return (state->cfg->write_reg) ?
-		state->cfg->write_reg(state->mxl_state, addr, data) :
-		-EINVAL;
-}
-
-static int mxl111sf_tuner_program_regs(struct mxl111sf_tuner_state *state,
-			       struct mxl111sf_reg_ctrl_info *ctrl_reg_info)
-{
-	return (state->cfg->program_regs) ?
-		state->cfg->program_regs(state->mxl_state, ctrl_reg_info) :
-		-EINVAL;
-}
-
-static int mxl1x1sf_tuner_top_master_ctrl(struct mxl111sf_tuner_state *state,
-					  int onoff)
-{
-	return (state->cfg->top_master_ctrl) ?
-		state->cfg->top_master_ctrl(state->mxl_state, onoff) :
-		-EINVAL;
-}
-
-/* ------------------------------------------------------------------------ */
-
-static struct mxl111sf_reg_ctrl_info mxl_phy_tune_rf[] = {
-	{0x1d, 0x7f, 0x00}, /* channel bandwidth section 1/2/3,
-			       DIG_MODEINDEX, _A, _CSF, */
-	{0x1e, 0xff, 0x00}, /* channel frequency (lo and fractional) */
-	{0x1f, 0xff, 0x00}, /* channel frequency (hi for integer portion) */
-	{0,    0,    0}
-};
-
-/* ------------------------------------------------------------------------ */
-
-static struct mxl111sf_reg_ctrl_info *mxl111sf_calc_phy_tune_regs(u32 freq,
-								  u8 bw)
-{
-	u8 filt_bw;
-
-	/* set channel bandwidth */
-	switch (bw) {
-	case 0: /* ATSC */
-		filt_bw = 25;
-		break;
-	case 1: /* QAM */
-		filt_bw = 69;
-		break;
-	case 6:
-		filt_bw = 21;
-		break;
-	case 7:
-		filt_bw = 42;
-		break;
-	case 8:
-		filt_bw = 63;
-		break;
-	default:
-		err("%s: invalid bandwidth setting!", __func__);
-		return NULL;
-	}
-
-	/* calculate RF channel */
-	freq /= 1000000;
-
-	freq *= 64;
-#if 0
-	/* do round */
-	freq += 0.5;
-#endif
-	/* set bandwidth */
-	mxl_phy_tune_rf[0].data = filt_bw;
-
-	/* set RF */
-	mxl_phy_tune_rf[1].data = (freq & 0xff);
-	mxl_phy_tune_rf[2].data = (freq >> 8) & 0xff;
-
-	/* start tune */
-	return mxl_phy_tune_rf;
-}
-
-static int mxl1x1sf_tuner_set_if_output_freq(struct mxl111sf_tuner_state *state)
-{
-	int ret;
-	u8 ctrl;
-#if 0
-	u16 iffcw;
-	u32 if_freq;
-#endif
-	mxl_dbg("(IF polarity = %d, IF freq = 0x%02x)",
-		state->cfg->invert_spectrum, state->cfg->if_freq);
-
-	/* set IF polarity */
-	ctrl = state->cfg->invert_spectrum;
-
-	ctrl |= state->cfg->if_freq;
-
-	ret = mxl111sf_tuner_write_reg(state, V6_TUNER_IF_SEL_REG, ctrl);
-	if (mxl_fail(ret))
-		goto fail;
-
-#if 0
-	if_freq /= 1000000;
-
-	/* do round */
-	if_freq += 0.5;
-
-	if (MXL_IF_LO == state->cfg->if_freq) {
-		ctrl = 0x08;
-		iffcw = (u16)(if_freq / (108 * 4096));
-	} else if (MXL_IF_HI == state->cfg->if_freq) {
-		ctrl = 0x08;
-		iffcw = (u16)(if_freq / (216 * 4096));
-	} else {
-		ctrl = 0;
-		iffcw = 0;
-	}
-
-	ctrl |= (iffcw >> 8);
-#endif
-	ret = mxl111sf_tuner_read_reg(state, V6_TUNER_IF_FCW_BYP_REG, &ctrl);
-	if (mxl_fail(ret))
-		goto fail;
-
-	ctrl &= 0xf0;
-	ctrl |= 0x90;
-
-	ret = mxl111sf_tuner_write_reg(state, V6_TUNER_IF_FCW_BYP_REG, ctrl);
-	if (mxl_fail(ret))
-		goto fail;
-
-#if 0
-	ctrl = iffcw & 0x00ff;
-#endif
-	ret = mxl111sf_tuner_write_reg(state, V6_TUNER_IF_FCW_REG, ctrl);
-	if (mxl_fail(ret))
-		goto fail;
-
-	state->if_freq = state->cfg->if_freq;
-fail:
-	return ret;
-}
-
-static int mxl1x1sf_tune_rf(struct dvb_frontend *fe, u32 freq, u8 bw)
-{
-	struct mxl111sf_tuner_state *state = fe->tuner_priv;
-	static struct mxl111sf_reg_ctrl_info *reg_ctrl_array;
-	int ret;
-	u8 mxl_mode;
-
-	mxl_dbg("(freq = %d, bw = 0x%x)", freq, bw);
-
-	/* stop tune */
-	ret = mxl111sf_tuner_write_reg(state, START_TUNE_REG, 0);
-	if (mxl_fail(ret))
-		goto fail;
-
-	/* check device mode */
-	ret = mxl111sf_tuner_read_reg(state, MXL_MODE_REG, &mxl_mode);
-	if (mxl_fail(ret))
-		goto fail;
-
-	/* Fill out registers for channel tune */
-	reg_ctrl_array = mxl111sf_calc_phy_tune_regs(freq, bw);
-	if (!reg_ctrl_array)
-		return -EINVAL;
-
-	ret = mxl111sf_tuner_program_regs(state, reg_ctrl_array);
-	if (mxl_fail(ret))
-		goto fail;
-
-	if ((mxl_mode & MXL_DEV_MODE_MASK) == MXL_TUNER_MODE) {
-		/* IF tuner mode only */
-		mxl1x1sf_tuner_top_master_ctrl(state, 0);
-		mxl1x1sf_tuner_top_master_ctrl(state, 1);
-		mxl1x1sf_tuner_set_if_output_freq(state);
-	}
-
-	ret = mxl111sf_tuner_write_reg(state, START_TUNE_REG, 1);
-	if (mxl_fail(ret))
-		goto fail;
-
-	if (state->cfg->ant_hunt)
-		state->cfg->ant_hunt(fe);
-fail:
-	return ret;
-}
-
-static int mxl1x1sf_tuner_get_lock_status(struct mxl111sf_tuner_state *state,
-					  int *rf_synth_lock,
-					  int *ref_synth_lock)
-{
-	int ret;
-	u8 data;
-
-	*rf_synth_lock = 0;
-	*ref_synth_lock = 0;
-
-	ret = mxl111sf_tuner_read_reg(state, V6_RF_LOCK_STATUS_REG, &data);
-	if (mxl_fail(ret))
-		goto fail;
-
-	*ref_synth_lock = ((data & 0x03) == 0x03) ? 1 : 0;
-	*rf_synth_lock  = ((data & 0x0c) == 0x0c) ? 1 : 0;
-fail:
-	return ret;
-}
-
-#if 0
-static int mxl1x1sf_tuner_loop_thru_ctrl(struct mxl111sf_tuner_state *state,
-					 int onoff)
-{
-	return mxl111sf_tuner_write_reg(state, V6_TUNER_LOOP_THRU_CTRL_REG,
-					onoff ? 1 : 0);
-}
-#endif
-
-/* ------------------------------------------------------------------------ */
-
-static int mxl111sf_tuner_set_params(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	u32 delsys  = c->delivery_system;
-	struct mxl111sf_tuner_state *state = fe->tuner_priv;
-	int ret;
-	u8 bw;
-
-	mxl_dbg("()");
-
-	switch (delsys) {
-	case SYS_ATSC:
-	case SYS_ATSCMH:
-		bw = 0; /* ATSC */
-		break;
-	case SYS_DVBC_ANNEX_B:
-		bw = 1; /* US CABLE */
-		break;
-	case SYS_DVBT:
-		switch (c->bandwidth_hz) {
-		case 6000000:
-			bw = 6;
-			break;
-		case 7000000:
-			bw = 7;
-			break;
-		case 8000000:
-			bw = 8;
-			break;
-		default:
-			err("%s: bandwidth not set!", __func__);
-			return -EINVAL;
-		}
-		break;
-	default:
-		err("%s: modulation type not supported!", __func__);
-		return -EINVAL;
-	}
-	ret = mxl1x1sf_tune_rf(fe, c->frequency, bw);
-	if (mxl_fail(ret))
-		goto fail;
-
-	state->frequency = c->frequency;
-	state->bandwidth = c->bandwidth_hz;
-fail:
-	return ret;
-}
-
-/* ------------------------------------------------------------------------ */
-
-#if 0
-static int mxl111sf_tuner_init(struct dvb_frontend *fe)
-{
-	struct mxl111sf_tuner_state *state = fe->tuner_priv;
-	int ret;
-
-	/* wake from standby handled by usb driver */
-
-	return ret;
-}
-
-static int mxl111sf_tuner_sleep(struct dvb_frontend *fe)
-{
-	struct mxl111sf_tuner_state *state = fe->tuner_priv;
-	int ret;
-
-	/* enter standby mode handled by usb driver */
-
-	return ret;
-}
-#endif
-
-/* ------------------------------------------------------------------------ */
-
-static int mxl111sf_tuner_get_status(struct dvb_frontend *fe, u32 *status)
-{
-	struct mxl111sf_tuner_state *state = fe->tuner_priv;
-	int rf_locked, ref_locked, ret;
-
-	*status = 0;
-
-	ret = mxl1x1sf_tuner_get_lock_status(state, &rf_locked, &ref_locked);
-	if (mxl_fail(ret))
-		goto fail;
-	mxl_info("%s%s", rf_locked ? "rf locked " : "",
-		 ref_locked ? "ref locked" : "");
-
-	if ((rf_locked) || (ref_locked))
-		*status |= TUNER_STATUS_LOCKED;
-fail:
-	return ret;
-}
-
-static int mxl111sf_get_rf_strength(struct dvb_frontend *fe, u16 *strength)
-{
-	struct mxl111sf_tuner_state *state = fe->tuner_priv;
-	u8 val1, val2;
-	int ret;
-
-	*strength = 0;
-
-	ret = mxl111sf_tuner_write_reg(state, 0x00, 0x02);
-	if (mxl_fail(ret))
-		goto fail;
-	ret = mxl111sf_tuner_read_reg(state, V6_DIG_RF_PWR_LSB_REG, &val1);
-	if (mxl_fail(ret))
-		goto fail;
-	ret = mxl111sf_tuner_read_reg(state, V6_DIG_RF_PWR_MSB_REG, &val2);
-	if (mxl_fail(ret))
-		goto fail;
-
-	*strength = val1 | ((val2 & 0x07) << 8);
-fail:
-	ret = mxl111sf_tuner_write_reg(state, 0x00, 0x00);
-	mxl_fail(ret);
-
-	return ret;
-}
-
-/* ------------------------------------------------------------------------ */
-
-static int mxl111sf_tuner_get_frequency(struct dvb_frontend *fe, u32 *frequency)
-{
-	struct mxl111sf_tuner_state *state = fe->tuner_priv;
-	*frequency = state->frequency;
-	return 0;
-}
-
-static int mxl111sf_tuner_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
-{
-	struct mxl111sf_tuner_state *state = fe->tuner_priv;
-	*bandwidth = state->bandwidth;
-	return 0;
-}
-
-static int mxl111sf_tuner_get_if_frequency(struct dvb_frontend *fe,
-					   u32 *frequency)
-{
-	struct mxl111sf_tuner_state *state = fe->tuner_priv;
-
-	*frequency = 0;
-
-	switch (state->if_freq) {
-	case MXL_IF_4_0:   /* 4.0   MHz */
-		*frequency = 4000000;
-		break;
-	case MXL_IF_4_5:   /* 4.5   MHz */
-		*frequency = 4500000;
-		break;
-	case MXL_IF_4_57:  /* 4.57  MHz */
-		*frequency = 4570000;
-		break;
-	case MXL_IF_5_0:   /* 5.0   MHz */
-		*frequency = 5000000;
-		break;
-	case MXL_IF_5_38:  /* 5.38  MHz */
-		*frequency = 5380000;
-		break;
-	case MXL_IF_6_0:   /* 6.0   MHz */
-		*frequency = 6000000;
-		break;
-	case MXL_IF_6_28:  /* 6.28  MHz */
-		*frequency = 6280000;
-		break;
-	case MXL_IF_7_2:   /* 7.2   MHz */
-		*frequency = 7200000;
-		break;
-	case MXL_IF_35_25: /* 35.25 MHz */
-		*frequency = 35250000;
-		break;
-	case MXL_IF_36:    /* 36    MHz */
-		*frequency = 36000000;
-		break;
-	case MXL_IF_36_15: /* 36.15 MHz */
-		*frequency = 36150000;
-		break;
-	case MXL_IF_44:    /* 44    MHz */
-		*frequency = 44000000;
-		break;
-	}
-	return 0;
-}
-
-static int mxl111sf_tuner_release(struct dvb_frontend *fe)
-{
-	struct mxl111sf_tuner_state *state = fe->tuner_priv;
-	mxl_dbg("()");
-	kfree(state);
-	fe->tuner_priv = NULL;
-	return 0;
-}
-
-/* ------------------------------------------------------------------------- */
-
-static struct dvb_tuner_ops mxl111sf_tuner_tuner_ops = {
-	.info = {
-		.name = "MaxLinear MxL111SF",
-#if 0
-		.frequency_min  = ,
-		.frequency_max  = ,
-		.frequency_step = ,
-#endif
-	},
-#if 0
-	.init              = mxl111sf_tuner_init,
-	.sleep             = mxl111sf_tuner_sleep,
-#endif
-	.set_params        = mxl111sf_tuner_set_params,
-	.get_status        = mxl111sf_tuner_get_status,
-	.get_rf_strength   = mxl111sf_get_rf_strength,
-	.get_frequency     = mxl111sf_tuner_get_frequency,
-	.get_bandwidth     = mxl111sf_tuner_get_bandwidth,
-	.get_if_frequency  = mxl111sf_tuner_get_if_frequency,
-	.release           = mxl111sf_tuner_release,
-};
-
-struct dvb_frontend *mxl111sf_tuner_attach(struct dvb_frontend *fe,
-					   struct mxl111sf_state *mxl_state,
-					   struct mxl111sf_tuner_config *cfg)
-{
-	struct mxl111sf_tuner_state *state = NULL;
-
-	mxl_dbg("()");
-
-	state = kzalloc(sizeof(struct mxl111sf_tuner_state), GFP_KERNEL);
-	if (state == NULL)
-		return NULL;
-
-	state->mxl_state = mxl_state;
-	state->cfg = cfg;
-
-	memcpy(&fe->ops.tuner_ops, &mxl111sf_tuner_tuner_ops,
-	       sizeof(struct dvb_tuner_ops));
-
-	fe->tuner_priv = state;
-	return fe;
-}
-EXPORT_SYMBOL_GPL(mxl111sf_tuner_attach);
-
-MODULE_DESCRIPTION("MaxLinear MxL111SF CMOS tuner driver");
-MODULE_AUTHOR("Michael Krufky <mkrufky@kernellabs.com>");
-MODULE_LICENSE("GPL");
-MODULE_VERSION("0.1");
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/dvb/dvb-usb/mxl111sf-tuner.h b/drivers/media/dvb/dvb-usb/mxl111sf-tuner.h
deleted file mode 100644
index ff33396..0000000
--- a/drivers/media/dvb/dvb-usb/mxl111sf-tuner.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- *  mxl111sf-tuner.h - driver for the MaxLinear MXL111SF CMOS tuner
- *
- *  Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef __MXL111SF_TUNER_H__
-#define __MXL111SF_TUNER_H__
-
-#include "dvb_frontend.h"
-
-#include "mxl111sf.h"
-
-enum mxl_if_freq {
-#if 0
-	MXL_IF_LO    = 0x00, /* other IF < 9MHz */
-#endif
-	MXL_IF_4_0   = 0x01, /* 4.0   MHz */
-	MXL_IF_4_5   = 0x02, /* 4.5   MHz */
-	MXL_IF_4_57  = 0x03, /* 4.57  MHz */
-	MXL_IF_5_0   = 0x04, /* 5.0   MHz */
-	MXL_IF_5_38  = 0x05, /* 5.38  MHz */
-	MXL_IF_6_0   = 0x06, /* 6.0   MHz */
-	MXL_IF_6_28  = 0x07, /* 6.28  MHz */
-	MXL_IF_7_2   = 0x08, /* 7.2   MHz */
-	MXL_IF_35_25 = 0x09, /* 35.25 MHz */
-	MXL_IF_36    = 0x0a, /* 36    MHz */
-	MXL_IF_36_15 = 0x0b, /* 36.15 MHz */
-	MXL_IF_44    = 0x0c, /* 44    MHz */
-#if 0
-	MXL_IF_HI    = 0x0f, /* other IF > 35 MHz and < 45 MHz */
-#endif
-};
-
-struct mxl111sf_tuner_config {
-	enum mxl_if_freq if_freq;
-	unsigned int invert_spectrum:1;
-
-	int (*read_reg)(struct mxl111sf_state *state, u8 addr, u8 *data);
-	int (*write_reg)(struct mxl111sf_state *state, u8 addr, u8 data);
-	int (*program_regs)(struct mxl111sf_state *state,
-			    struct mxl111sf_reg_ctrl_info *ctrl_reg_info);
-	int (*top_master_ctrl)(struct mxl111sf_state *state, int onoff);
-	int (*ant_hunt)(struct dvb_frontend *fe);
-};
-
-/* ------------------------------------------------------------------------ */
-
-#if defined(CONFIG_DVB_USB_MXL111SF) || \
-	(defined(CONFIG_DVB_USB_MXL111SF_MODULE) && defined(MODULE))
-extern
-struct dvb_frontend *mxl111sf_tuner_attach(struct dvb_frontend *fe,
-					   struct mxl111sf_state *mxl_state,
-					   struct mxl111sf_tuner_config *cfg);
-#else
-static inline
-struct dvb_frontend *mxl111sf_tuner_attach(struct dvb_frontend *fe,
-					   struct mxl111sf_state *mxl_state
-					   struct mxl111sf_tuner_config *cfg)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif
-
-#endif /* __MXL111SF_TUNER_H__ */
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
-
diff --git a/drivers/media/dvb/dvb-usb/mxl111sf.c b/drivers/media/dvb/dvb-usb/mxl111sf.c
deleted file mode 100644
index cd84279..0000000
--- a/drivers/media/dvb/dvb-usb/mxl111sf.c
+++ /dev/null
@@ -1,1835 +0,0 @@
-/*
- * Copyright (C) 2010 Michael Krufky (mkrufky@kernellabs.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, version 2.
- *
- * see Documentation/dvb/README.dvb-usb for more information
- */
-
-#include <linux/vmalloc.h>
-#include <linux/i2c.h>
-
-#include "mxl111sf.h"
-#include "mxl111sf-reg.h"
-#include "mxl111sf-phy.h"
-#include "mxl111sf-i2c.h"
-#include "mxl111sf-gpio.h"
-
-#include "mxl111sf-demod.h"
-#include "mxl111sf-tuner.h"
-
-#include "lgdt3305.h"
-#include "lg2160.h"
-
-int dvb_usb_mxl111sf_debug;
-module_param_named(debug, dvb_usb_mxl111sf_debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level "
-		 "(1=info, 2=xfer, 4=i2c, 8=reg, 16=adv (or-able)).");
-
-int dvb_usb_mxl111sf_isoc;
-module_param_named(isoc, dvb_usb_mxl111sf_isoc, int, 0644);
-MODULE_PARM_DESC(isoc, "enable usb isoc xfer (0=bulk, 1=isoc).");
-
-int dvb_usb_mxl111sf_spi;
-module_param_named(spi, dvb_usb_mxl111sf_spi, int, 0644);
-MODULE_PARM_DESC(spi, "use spi rather than tp for data xfer (0=tp, 1=spi).");
-
-#define ANT_PATH_AUTO 0
-#define ANT_PATH_EXTERNAL 1
-#define ANT_PATH_INTERNAL 2
-
-int dvb_usb_mxl111sf_rfswitch =
-#if 0
-		ANT_PATH_AUTO;
-#else
-		ANT_PATH_EXTERNAL;
-#endif
-
-module_param_named(rfswitch, dvb_usb_mxl111sf_rfswitch, int, 0644);
-MODULE_PARM_DESC(rfswitch, "force rf switch position (0=auto, 1=ext, 2=int).");
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-#define deb_info(args...)   dprintk(dvb_usb_mxl111sf_debug, 0x13, args)
-#define deb_reg(args...)    dprintk(dvb_usb_mxl111sf_debug, 0x08, args)
-#define deb_adv(args...)    dprintk(dvb_usb_mxl111sf_debug, MXL_ADV_DBG, args)
-
-int mxl111sf_ctrl_msg(struct dvb_usb_device *d,
-		      u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen)
-{
-	int wo = (rbuf == NULL || rlen == 0); /* write-only */
-	int ret;
-	u8 sndbuf[1+wlen];
-
-	deb_adv("%s(wlen = %d, rlen = %d)\n", __func__, wlen, rlen);
-
-	memset(sndbuf, 0, 1+wlen);
-
-	sndbuf[0] = cmd;
-	memcpy(&sndbuf[1], wbuf, wlen);
-
-	ret = (wo) ? dvb_usb_generic_write(d, sndbuf, 1+wlen) :
-		dvb_usb_generic_rw(d, sndbuf, 1+wlen, rbuf, rlen, 0);
-	mxl_fail(ret);
-
-	return ret;
-}
-
-/* ------------------------------------------------------------------------ */
-
-#define MXL_CMD_REG_READ	0xaa
-#define MXL_CMD_REG_WRITE	0x55
-
-int mxl111sf_read_reg(struct mxl111sf_state *state, u8 addr, u8 *data)
-{
-	u8 buf[2];
-	int ret;
-
-	ret = mxl111sf_ctrl_msg(state->d, MXL_CMD_REG_READ, &addr, 1, buf, 2);
-	if (mxl_fail(ret)) {
-		mxl_debug("error reading reg: 0x%02x", addr);
-		goto fail;
-	}
-
-	if (buf[0] == addr)
-		*data = buf[1];
-	else {
-		err("invalid response reading reg: 0x%02x != 0x%02x, 0x%02x",
-		    addr, buf[0], buf[1]);
-		ret = -EINVAL;
-	}
-
-	deb_reg("R: (0x%02x, 0x%02x)\n", addr, *data);
-fail:
-	return ret;
-}
-
-int mxl111sf_write_reg(struct mxl111sf_state *state, u8 addr, u8 data)
-{
-	u8 buf[] = { addr, data };
-	int ret;
-
-	deb_reg("W: (0x%02x, 0x%02x)\n", addr, data);
-
-	ret = mxl111sf_ctrl_msg(state->d, MXL_CMD_REG_WRITE, buf, 2, NULL, 0);
-	if (mxl_fail(ret))
-		err("error writing reg: 0x%02x, val: 0x%02x", addr, data);
-	return ret;
-}
-
-/* ------------------------------------------------------------------------ */
-
-int mxl111sf_write_reg_mask(struct mxl111sf_state *state,
-				   u8 addr, u8 mask, u8 data)
-{
-	int ret;
-	u8 val;
-
-	if (mask != 0xff) {
-		ret = mxl111sf_read_reg(state, addr, &val);
-#if 1
-		/* dont know why this usually errors out on the first try */
-		if (mxl_fail(ret))
-			err("error writing addr: 0x%02x, mask: 0x%02x, "
-			    "data: 0x%02x, retrying...", addr, mask, data);
-
-		ret = mxl111sf_read_reg(state, addr, &val);
-#endif
-		if (mxl_fail(ret))
-			goto fail;
-	}
-	val &= ~mask;
-	val |= data;
-
-	ret = mxl111sf_write_reg(state, addr, val);
-	mxl_fail(ret);
-fail:
-	return ret;
-}
-
-/* ------------------------------------------------------------------------ */
-
-int mxl111sf_ctrl_program_regs(struct mxl111sf_state *state,
-			       struct mxl111sf_reg_ctrl_info *ctrl_reg_info)
-{
-	int i, ret = 0;
-
-	for (i = 0;  ctrl_reg_info[i].addr |
-		     ctrl_reg_info[i].mask |
-		     ctrl_reg_info[i].data;  i++) {
-
-		ret = mxl111sf_write_reg_mask(state,
-					      ctrl_reg_info[i].addr,
-					      ctrl_reg_info[i].mask,
-					      ctrl_reg_info[i].data);
-		if (mxl_fail(ret)) {
-			err("failed on reg #%d (0x%02x)", i,
-			    ctrl_reg_info[i].addr);
-			break;
-		}
-	}
-	return ret;
-}
-
-/* ------------------------------------------------------------------------ */
-
-static int mxl1x1sf_get_chip_info(struct mxl111sf_state *state)
-{
-	int ret;
-	u8 id, ver;
-	char *mxl_chip, *mxl_rev;
-
-	if ((state->chip_id) && (state->chip_ver))
-		return 0;
-
-	ret = mxl111sf_read_reg(state, CHIP_ID_REG, &id);
-	if (mxl_fail(ret))
-		goto fail;
-	state->chip_id = id;
-
-	ret = mxl111sf_read_reg(state, TOP_CHIP_REV_ID_REG, &ver);
-	if (mxl_fail(ret))
-		goto fail;
-	state->chip_ver = ver;
-
-	switch (id) {
-	case 0x61:
-		mxl_chip = "MxL101SF";
-		break;
-	case 0x63:
-		mxl_chip = "MxL111SF";
-		break;
-	default:
-		mxl_chip = "UNKNOWN MxL1X1";
-		break;
-	}
-	switch (ver) {
-	case 0x36:
-		state->chip_rev = MXL111SF_V6;
-		mxl_rev = "v6";
-		break;
-	case 0x08:
-		state->chip_rev = MXL111SF_V8_100;
-		mxl_rev = "v8_100";
-		break;
-	case 0x18:
-		state->chip_rev = MXL111SF_V8_200;
-		mxl_rev = "v8_200";
-		break;
-	default:
-		state->chip_rev = 0;
-		mxl_rev = "UNKNOWN REVISION";
-		break;
-	}
-	info("%s detected, %s (0x%x)", mxl_chip, mxl_rev, ver);
-fail:
-	return ret;
-}
-
-#define get_chip_info(state)						\
-({									\
-	int ___ret;							\
-	___ret = mxl1x1sf_get_chip_info(state);				\
-	if (mxl_fail(___ret)) {						\
-		mxl_debug("failed to get chip info"			\
-			  " on first probe attempt");			\
-		___ret = mxl1x1sf_get_chip_info(state);			\
-		if (mxl_fail(___ret))					\
-			err("failed to get chip info during probe");	\
-		else							\
-			mxl_debug("probe needed a retry "		\
-				  "in order to succeed.");		\
-	}								\
-	___ret;								\
-})
-
-/* ------------------------------------------------------------------------ */
-
-static int mxl111sf_power_ctrl(struct dvb_usb_device *d, int onoff)
-{
-	/* power control depends on which adapter is being woken:
-	 * save this for init, instead, via mxl111sf_adap_fe_init */
-	return 0;
-}
-
-static int mxl111sf_adap_fe_init(struct dvb_frontend *fe)
-{
-	struct dvb_usb_adapter *adap = fe->dvb->priv;
-	struct dvb_usb_device *d = adap->dev;
-	struct mxl111sf_state *state = d->priv;
-	struct mxl111sf_adap_state *adap_state = adap->fe_adap[fe->id].priv;
-
-	int err;
-
-	/* exit if we didnt initialize the driver yet */
-	if (!state->chip_id) {
-		mxl_debug("driver not yet initialized, exit.");
-		goto fail;
-	}
-
-	deb_info("%s()\n", __func__);
-
-	mutex_lock(&state->fe_lock);
-
-	state->alt_mode = adap_state->alt_mode;
-
-	if (usb_set_interface(adap->dev->udev, 0, state->alt_mode) < 0)
-		err("set interface failed");
-
-	err = mxl1x1sf_soft_reset(state);
-	mxl_fail(err);
-	err = mxl111sf_init_tuner_demod(state);
-	mxl_fail(err);
-	err = mxl1x1sf_set_device_mode(state, adap_state->device_mode);
-
-	mxl_fail(err);
-	mxl111sf_enable_usb_output(state);
-	mxl_fail(err);
-	mxl1x1sf_top_master_ctrl(state, 1);
-	mxl_fail(err);
-
-	if ((MXL111SF_GPIO_MOD_DVBT != adap_state->gpio_mode) &&
-	    (state->chip_rev > MXL111SF_V6)) {
-		mxl111sf_config_pin_mux_modes(state,
-					      PIN_MUX_TS_SPI_IN_MODE_1);
-		mxl_fail(err);
-	}
-	err = mxl111sf_init_port_expander(state);
-	if (!mxl_fail(err)) {
-		state->gpio_mode = adap_state->gpio_mode;
-		err = mxl111sf_gpio_mode_switch(state, state->gpio_mode);
-		mxl_fail(err);
-#if 0
-		err = fe->ops.init(fe);
-#endif
-		msleep(100); /* add short delay after enabling
-			      * the demod before touching it */
-	}
-
-	return (adap_state->fe_init) ? adap_state->fe_init(fe) : 0;
-fail:
-	return -ENODEV;
-}
-
-static int mxl111sf_adap_fe_sleep(struct dvb_frontend *fe)
-{
-	struct dvb_usb_adapter *adap = fe->dvb->priv;
-	struct dvb_usb_device *d = adap->dev;
-	struct mxl111sf_state *state = d->priv;
-	struct mxl111sf_adap_state *adap_state = adap->fe_adap[fe->id].priv;
-	int err;
-
-	/* exit if we didnt initialize the driver yet */
-	if (!state->chip_id) {
-		mxl_debug("driver not yet initialized, exit.");
-		goto fail;
-	}
-
-	deb_info("%s()\n", __func__);
-
-	err = (adap_state->fe_sleep) ? adap_state->fe_sleep(fe) : 0;
-
-	mutex_unlock(&state->fe_lock);
-
-	return err;
-fail:
-	return -ENODEV;
-}
-
-
-static int mxl111sf_ep6_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
-{
-	struct dvb_usb_device *d = adap->dev;
-	struct mxl111sf_state *state = d->priv;
-	struct mxl111sf_adap_state *adap_state = adap->fe_adap[adap->active_fe].priv;
-	int ret = 0;
-
-	deb_info("%s(%d)\n", __func__, onoff);
-
-	if (onoff) {
-		ret = mxl111sf_enable_usb_output(state);
-		mxl_fail(ret);
-		ret = mxl111sf_config_mpeg_in(state, 1, 1,
-					      adap_state->ep6_clockphase,
-					      0, 0);
-		mxl_fail(ret);
-#if 0
-	} else {
-		ret = mxl111sf_disable_656_port(state);
-		mxl_fail(ret);
-#endif
-	}
-
-	return ret;
-}
-
-static int mxl111sf_ep5_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
-{
-	struct dvb_usb_device *d = adap->dev;
-	struct mxl111sf_state *state = d->priv;
-	int ret = 0;
-
-	deb_info("%s(%d)\n", __func__, onoff);
-
-	if (onoff) {
-		ret = mxl111sf_enable_usb_output(state);
-		mxl_fail(ret);
-
-		ret = mxl111sf_init_i2s_port(state, 200);
-		mxl_fail(ret);
-		ret = mxl111sf_config_i2s(state, 0, 15);
-		mxl_fail(ret);
-	} else {
-		ret = mxl111sf_disable_i2s_port(state);
-		mxl_fail(ret);
-	}
-	if (state->chip_rev > MXL111SF_V6)
-		ret = mxl111sf_config_spi(state, onoff);
-	mxl_fail(ret);
-
-	return ret;
-}
-
-static int mxl111sf_ep4_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
-{
-	struct dvb_usb_device *d = adap->dev;
-	struct mxl111sf_state *state = d->priv;
-	int ret = 0;
-
-	deb_info("%s(%d)\n", __func__, onoff);
-
-	if (onoff) {
-		ret = mxl111sf_enable_usb_output(state);
-		mxl_fail(ret);
-	}
-
-	return ret;
-}
-
-/* ------------------------------------------------------------------------ */
-
-static struct lgdt3305_config hauppauge_lgdt3305_config = {
-	.i2c_addr           = 0xb2 >> 1,
-	.mpeg_mode          = LGDT3305_MPEG_SERIAL,
-	.tpclk_edge         = LGDT3305_TPCLK_RISING_EDGE,
-	.tpvalid_polarity   = LGDT3305_TP_VALID_HIGH,
-	.deny_i2c_rptr      = 1,
-	.spectral_inversion = 0,
-	.qam_if_khz         = 6000,
-	.vsb_if_khz         = 6000,
-};
-
-static int mxl111sf_lgdt3305_frontend_attach(struct dvb_usb_adapter *adap)
-{
-	struct dvb_usb_device *d = adap->dev;
-	struct mxl111sf_state *state = d->priv;
-	int fe_id = adap->num_frontends_initialized;
-	struct mxl111sf_adap_state *adap_state = adap->fe_adap[fe_id].priv;
-	int ret;
-
-	deb_adv("%s()\n", __func__);
-
-	/* save a pointer to the dvb_usb_device in device state */
-	state->d = d;
-	adap_state->alt_mode = (dvb_usb_mxl111sf_isoc) ? 2 : 1;
-	state->alt_mode = adap_state->alt_mode;
-
-	if (usb_set_interface(adap->dev->udev, 0, state->alt_mode) < 0)
-		err("set interface failed");
-
-	state->gpio_mode = MXL111SF_GPIO_MOD_ATSC;
-	adap_state->gpio_mode = state->gpio_mode;
-	adap_state->device_mode = MXL_TUNER_MODE;
-	adap_state->ep6_clockphase = 1;
-
-	ret = mxl1x1sf_soft_reset(state);
-	if (mxl_fail(ret))
-		goto fail;
-	ret = mxl111sf_init_tuner_demod(state);
-	if (mxl_fail(ret))
-		goto fail;
-
-	ret = mxl1x1sf_set_device_mode(state, adap_state->device_mode);
-	if (mxl_fail(ret))
-		goto fail;
-
-	ret = mxl111sf_enable_usb_output(state);
-	if (mxl_fail(ret))
-		goto fail;
-	ret = mxl1x1sf_top_master_ctrl(state, 1);
-	if (mxl_fail(ret))
-		goto fail;
-
-	ret = mxl111sf_init_port_expander(state);
-	if (mxl_fail(ret))
-		goto fail;
-	ret = mxl111sf_gpio_mode_switch(state, state->gpio_mode);
-	if (mxl_fail(ret))
-		goto fail;
-
-	adap->fe_adap[fe_id].fe = dvb_attach(lgdt3305_attach,
-				 &hauppauge_lgdt3305_config,
-				 &adap->dev->i2c_adap);
-	if (adap->fe_adap[fe_id].fe) {
-		adap_state->fe_init = adap->fe_adap[fe_id].fe->ops.init;
-		adap->fe_adap[fe_id].fe->ops.init = mxl111sf_adap_fe_init;
-		adap_state->fe_sleep = adap->fe_adap[fe_id].fe->ops.sleep;
-		adap->fe_adap[fe_id].fe->ops.sleep = mxl111sf_adap_fe_sleep;
-		return 0;
-	}
-	ret = -EIO;
-fail:
-	return ret;
-}
-
-static struct lg2160_config hauppauge_lg2160_config = {
-	.lg_chip            = LG2160,
-	.i2c_addr           = 0x1c >> 1,
-	.deny_i2c_rptr      = 1,
-	.spectral_inversion = 0,
-	.if_khz             = 6000,
-};
-
-static int mxl111sf_lg2160_frontend_attach(struct dvb_usb_adapter *adap)
-{
-	struct dvb_usb_device *d = adap->dev;
-	struct mxl111sf_state *state = d->priv;
-	int fe_id = adap->num_frontends_initialized;
-	struct mxl111sf_adap_state *adap_state = adap->fe_adap[fe_id].priv;
-	int ret;
-
-	deb_adv("%s()\n", __func__);
-
-	/* save a pointer to the dvb_usb_device in device state */
-	state->d = d;
-	adap_state->alt_mode = (dvb_usb_mxl111sf_isoc) ? 2 : 1;
-	state->alt_mode = adap_state->alt_mode;
-
-	if (usb_set_interface(adap->dev->udev, 0, state->alt_mode) < 0)
-		err("set interface failed");
-
-	state->gpio_mode = MXL111SF_GPIO_MOD_MH;
-	adap_state->gpio_mode = state->gpio_mode;
-	adap_state->device_mode = MXL_TUNER_MODE;
-	adap_state->ep6_clockphase = 1;
-
-	ret = mxl1x1sf_soft_reset(state);
-	if (mxl_fail(ret))
-		goto fail;
-	ret = mxl111sf_init_tuner_demod(state);
-	if (mxl_fail(ret))
-		goto fail;
-
-	ret = mxl1x1sf_set_device_mode(state, adap_state->device_mode);
-	if (mxl_fail(ret))
-		goto fail;
-
-	ret = mxl111sf_enable_usb_output(state);
-	if (mxl_fail(ret))
-		goto fail;
-	ret = mxl1x1sf_top_master_ctrl(state, 1);
-	if (mxl_fail(ret))
-		goto fail;
-
-	ret = mxl111sf_init_port_expander(state);
-	if (mxl_fail(ret))
-		goto fail;
-	ret = mxl111sf_gpio_mode_switch(state, state->gpio_mode);
-	if (mxl_fail(ret))
-		goto fail;
-
-	ret = get_chip_info(state);
-	if (mxl_fail(ret))
-		goto fail;
-
-	adap->fe_adap[fe_id].fe = dvb_attach(lg2160_attach,
-			      &hauppauge_lg2160_config,
-			      &adap->dev->i2c_adap);
-	if (adap->fe_adap[fe_id].fe) {
-		adap_state->fe_init = adap->fe_adap[fe_id].fe->ops.init;
-		adap->fe_adap[fe_id].fe->ops.init = mxl111sf_adap_fe_init;
-		adap_state->fe_sleep = adap->fe_adap[fe_id].fe->ops.sleep;
-		adap->fe_adap[fe_id].fe->ops.sleep = mxl111sf_adap_fe_sleep;
-		return 0;
-	}
-	ret = -EIO;
-fail:
-	return ret;
-}
-
-static struct lg2160_config hauppauge_lg2161_1019_config = {
-	.lg_chip            = LG2161_1019,
-	.i2c_addr           = 0x1c >> 1,
-	.deny_i2c_rptr      = 1,
-	.spectral_inversion = 0,
-	.if_khz             = 6000,
-	.output_if          = 2, /* LG2161_OIF_SPI_MAS */
-};
-
-static struct lg2160_config hauppauge_lg2161_1040_config = {
-	.lg_chip            = LG2161_1040,
-	.i2c_addr           = 0x1c >> 1,
-	.deny_i2c_rptr      = 1,
-	.spectral_inversion = 0,
-	.if_khz             = 6000,
-	.output_if          = 4, /* LG2161_OIF_SPI_MAS */
-};
-
-static int mxl111sf_lg2161_frontend_attach(struct dvb_usb_adapter *adap)
-{
-	struct dvb_usb_device *d = adap->dev;
-	struct mxl111sf_state *state = d->priv;
-	int fe_id = adap->num_frontends_initialized;
-	struct mxl111sf_adap_state *adap_state = adap->fe_adap[fe_id].priv;
-	int ret;
-
-	deb_adv("%s()\n", __func__);
-
-	/* save a pointer to the dvb_usb_device in device state */
-	state->d = d;
-	adap_state->alt_mode = (dvb_usb_mxl111sf_isoc) ? 2 : 1;
-	state->alt_mode = adap_state->alt_mode;
-
-	if (usb_set_interface(adap->dev->udev, 0, state->alt_mode) < 0)
-		err("set interface failed");
-
-	state->gpio_mode = MXL111SF_GPIO_MOD_MH;
-	adap_state->gpio_mode = state->gpio_mode;
-	adap_state->device_mode = MXL_TUNER_MODE;
-	adap_state->ep6_clockphase = 1;
-
-	ret = mxl1x1sf_soft_reset(state);
-	if (mxl_fail(ret))
-		goto fail;
-	ret = mxl111sf_init_tuner_demod(state);
-	if (mxl_fail(ret))
-		goto fail;
-
-	ret = mxl1x1sf_set_device_mode(state, adap_state->device_mode);
-	if (mxl_fail(ret))
-		goto fail;
-
-	ret = mxl111sf_enable_usb_output(state);
-	if (mxl_fail(ret))
-		goto fail;
-	ret = mxl1x1sf_top_master_ctrl(state, 1);
-	if (mxl_fail(ret))
-		goto fail;
-
-	ret = mxl111sf_init_port_expander(state);
-	if (mxl_fail(ret))
-		goto fail;
-	ret = mxl111sf_gpio_mode_switch(state, state->gpio_mode);
-	if (mxl_fail(ret))
-		goto fail;
-
-	ret = get_chip_info(state);
-	if (mxl_fail(ret))
-		goto fail;
-
-	adap->fe_adap[fe_id].fe = dvb_attach(lg2160_attach,
-			      (MXL111SF_V8_200 == state->chip_rev) ?
-			      &hauppauge_lg2161_1040_config :
-			      &hauppauge_lg2161_1019_config,
-			      &adap->dev->i2c_adap);
-	if (adap->fe_adap[fe_id].fe) {
-		adap_state->fe_init = adap->fe_adap[fe_id].fe->ops.init;
-		adap->fe_adap[fe_id].fe->ops.init = mxl111sf_adap_fe_init;
-		adap_state->fe_sleep = adap->fe_adap[fe_id].fe->ops.sleep;
-		adap->fe_adap[fe_id].fe->ops.sleep = mxl111sf_adap_fe_sleep;
-		return 0;
-	}
-	ret = -EIO;
-fail:
-	return ret;
-}
-
-static struct lg2160_config hauppauge_lg2161_1019_ep6_config = {
-	.lg_chip            = LG2161_1019,
-	.i2c_addr           = 0x1c >> 1,
-	.deny_i2c_rptr      = 1,
-	.spectral_inversion = 0,
-	.if_khz             = 6000,
-	.output_if          = 1, /* LG2161_OIF_SERIAL_TS */
-};
-
-static struct lg2160_config hauppauge_lg2161_1040_ep6_config = {
-	.lg_chip            = LG2161_1040,
-	.i2c_addr           = 0x1c >> 1,
-	.deny_i2c_rptr      = 1,
-	.spectral_inversion = 0,
-	.if_khz             = 6000,
-	.output_if          = 7, /* LG2161_OIF_SERIAL_TS */
-};
-
-static int mxl111sf_lg2161_ep6_frontend_attach(struct dvb_usb_adapter *adap)
-{
-	struct dvb_usb_device *d = adap->dev;
-	struct mxl111sf_state *state = d->priv;
-	int fe_id = adap->num_frontends_initialized;
-	struct mxl111sf_adap_state *adap_state = adap->fe_adap[fe_id].priv;
-	int ret;
-
-	deb_adv("%s()\n", __func__);
-
-	/* save a pointer to the dvb_usb_device in device state */
-	state->d = d;
-	adap_state->alt_mode = (dvb_usb_mxl111sf_isoc) ? 2 : 1;
-	state->alt_mode = adap_state->alt_mode;
-
-	if (usb_set_interface(adap->dev->udev, 0, state->alt_mode) < 0)
-		err("set interface failed");
-
-	state->gpio_mode = MXL111SF_GPIO_MOD_MH;
-	adap_state->gpio_mode = state->gpio_mode;
-	adap_state->device_mode = MXL_TUNER_MODE;
-	adap_state->ep6_clockphase = 0;
-
-	ret = mxl1x1sf_soft_reset(state);
-	if (mxl_fail(ret))
-		goto fail;
-	ret = mxl111sf_init_tuner_demod(state);
-	if (mxl_fail(ret))
-		goto fail;
-
-	ret = mxl1x1sf_set_device_mode(state, adap_state->device_mode);
-	if (mxl_fail(ret))
-		goto fail;
-
-	ret = mxl111sf_enable_usb_output(state);
-	if (mxl_fail(ret))
-		goto fail;
-	ret = mxl1x1sf_top_master_ctrl(state, 1);
-	if (mxl_fail(ret))
-		goto fail;
-
-	ret = mxl111sf_init_port_expander(state);
-	if (mxl_fail(ret))
-		goto fail;
-	ret = mxl111sf_gpio_mode_switch(state, state->gpio_mode);
-	if (mxl_fail(ret))
-		goto fail;
-
-	ret = get_chip_info(state);
-	if (mxl_fail(ret))
-		goto fail;
-
-	adap->fe_adap[fe_id].fe = dvb_attach(lg2160_attach,
-			      (MXL111SF_V8_200 == state->chip_rev) ?
-			      &hauppauge_lg2161_1040_ep6_config :
-			      &hauppauge_lg2161_1019_ep6_config,
-			      &adap->dev->i2c_adap);
-	if (adap->fe_adap[fe_id].fe) {
-		adap_state->fe_init = adap->fe_adap[fe_id].fe->ops.init;
-		adap->fe_adap[fe_id].fe->ops.init = mxl111sf_adap_fe_init;
-		adap_state->fe_sleep = adap->fe_adap[fe_id].fe->ops.sleep;
-		adap->fe_adap[fe_id].fe->ops.sleep = mxl111sf_adap_fe_sleep;
-		return 0;
-	}
-	ret = -EIO;
-fail:
-	return ret;
-}
-
-static struct mxl111sf_demod_config mxl_demod_config = {
-	.read_reg        = mxl111sf_read_reg,
-	.write_reg       = mxl111sf_write_reg,
-	.program_regs    = mxl111sf_ctrl_program_regs,
-};
-
-static int mxl111sf_attach_demod(struct dvb_usb_adapter *adap)
-{
-	struct dvb_usb_device *d = adap->dev;
-	struct mxl111sf_state *state = d->priv;
-	int fe_id = adap->num_frontends_initialized;
-	struct mxl111sf_adap_state *adap_state = adap->fe_adap[fe_id].priv;
-	int ret;
-
-	deb_adv("%s()\n", __func__);
-
-	/* save a pointer to the dvb_usb_device in device state */
-	state->d = d;
-	adap_state->alt_mode = (dvb_usb_mxl111sf_isoc) ? 1 : 2;
-	state->alt_mode = adap_state->alt_mode;
-
-	if (usb_set_interface(adap->dev->udev, 0, state->alt_mode) < 0)
-		err("set interface failed");
-
-	state->gpio_mode = MXL111SF_GPIO_MOD_DVBT;
-	adap_state->gpio_mode = state->gpio_mode;
-	adap_state->device_mode = MXL_SOC_MODE;
-	adap_state->ep6_clockphase = 1;
-
-	ret = mxl1x1sf_soft_reset(state);
-	if (mxl_fail(ret))
-		goto fail;
-	ret = mxl111sf_init_tuner_demod(state);
-	if (mxl_fail(ret))
-		goto fail;
-
-	ret = mxl1x1sf_set_device_mode(state, adap_state->device_mode);
-	if (mxl_fail(ret))
-		goto fail;
-
-	ret = mxl111sf_enable_usb_output(state);
-	if (mxl_fail(ret))
-		goto fail;
-	ret = mxl1x1sf_top_master_ctrl(state, 1);
-	if (mxl_fail(ret))
-		goto fail;
-
-	/* dont care if this fails */
-	mxl111sf_init_port_expander(state);
-
-	adap->fe_adap[fe_id].fe = dvb_attach(mxl111sf_demod_attach, state,
-			      &mxl_demod_config);
-	if (adap->fe_adap[fe_id].fe) {
-		adap_state->fe_init = adap->fe_adap[fe_id].fe->ops.init;
-		adap->fe_adap[fe_id].fe->ops.init = mxl111sf_adap_fe_init;
-		adap_state->fe_sleep = adap->fe_adap[fe_id].fe->ops.sleep;
-		adap->fe_adap[fe_id].fe->ops.sleep = mxl111sf_adap_fe_sleep;
-		return 0;
-	}
-	ret = -EIO;
-fail:
-	return ret;
-}
-
-static inline int mxl111sf_set_ant_path(struct mxl111sf_state *state,
-					int antpath)
-{
-	return mxl111sf_idac_config(state, 1, 1,
-				    (antpath == ANT_PATH_INTERNAL) ?
-				    0x3f : 0x00, 0);
-}
-
-#define DbgAntHunt(x, pwr0, pwr1, pwr2, pwr3) \
-	err("%s(%d) FINAL input set to %s rxPwr:%d|%d|%d|%d\n", \
-	    __func__, __LINE__, \
-	    (ANT_PATH_EXTERNAL == x) ? "EXTERNAL" : "INTERNAL", \
-	    pwr0, pwr1, pwr2, pwr3)
-
-#define ANT_HUNT_SLEEP 90
-#define ANT_EXT_TWEAK 0
-
-static int mxl111sf_ant_hunt(struct dvb_frontend *fe)
-{
-	struct dvb_usb_adapter *adap = fe->dvb->priv;
-	struct dvb_usb_device *d = adap->dev;
-	struct mxl111sf_state *state = d->priv;
-
-	int antctrl = dvb_usb_mxl111sf_rfswitch;
-
-	u16 rxPwrA, rxPwr0, rxPwr1, rxPwr2;
-
-	/* FIXME: must force EXTERNAL for QAM - done elsewhere */
-	mxl111sf_set_ant_path(state, antctrl == ANT_PATH_AUTO ?
-			      ANT_PATH_EXTERNAL : antctrl);
-
-	if (antctrl == ANT_PATH_AUTO) {
-#if 0
-		msleep(ANT_HUNT_SLEEP);
-#endif
-		fe->ops.tuner_ops.get_rf_strength(fe, &rxPwrA);
-
-		mxl111sf_set_ant_path(state, ANT_PATH_EXTERNAL);
-		msleep(ANT_HUNT_SLEEP);
-		fe->ops.tuner_ops.get_rf_strength(fe, &rxPwr0);
-
-		mxl111sf_set_ant_path(state, ANT_PATH_EXTERNAL);
-		msleep(ANT_HUNT_SLEEP);
-		fe->ops.tuner_ops.get_rf_strength(fe, &rxPwr1);
-
-		mxl111sf_set_ant_path(state, ANT_PATH_INTERNAL);
-		msleep(ANT_HUNT_SLEEP);
-		fe->ops.tuner_ops.get_rf_strength(fe, &rxPwr2);
-
-		if (rxPwr1+ANT_EXT_TWEAK >= rxPwr2) {
-			/* return with EXTERNAL enabled */
-			mxl111sf_set_ant_path(state, ANT_PATH_EXTERNAL);
-			DbgAntHunt(ANT_PATH_EXTERNAL, rxPwrA,
-				   rxPwr0, rxPwr1, rxPwr2);
-		} else {
-			/* return with INTERNAL enabled */
-			DbgAntHunt(ANT_PATH_INTERNAL, rxPwrA,
-				   rxPwr0, rxPwr1, rxPwr2);
-		}
-	}
-	return 0;
-}
-
-static struct mxl111sf_tuner_config mxl_tuner_config = {
-	.if_freq         = MXL_IF_6_0, /* applies to external IF output, only */
-	.invert_spectrum = 0,
-	.read_reg        = mxl111sf_read_reg,
-	.write_reg       = mxl111sf_write_reg,
-	.program_regs    = mxl111sf_ctrl_program_regs,
-	.top_master_ctrl = mxl1x1sf_top_master_ctrl,
-	.ant_hunt        = mxl111sf_ant_hunt,
-};
-
-static int mxl111sf_attach_tuner(struct dvb_usb_adapter *adap)
-{
-	struct dvb_usb_device *d = adap->dev;
-	struct mxl111sf_state *state = d->priv;
-	int fe_id = adap->num_frontends_initialized;
-
-	deb_adv("%s()\n", __func__);
-
-	if (NULL != dvb_attach(mxl111sf_tuner_attach,
-			       adap->fe_adap[fe_id].fe, state,
-			       &mxl_tuner_config))
-		return 0;
-
-	return -EIO;
-}
-
-static int mxl111sf_fe_ioctl_override(struct dvb_frontend *fe,
-				      unsigned int cmd, void *parg,
-				      unsigned int stage)
-{
-	int err = 0;
-
-	switch (stage) {
-	case DVB_FE_IOCTL_PRE:
-
-		switch (cmd) {
-		case FE_READ_SIGNAL_STRENGTH:
-			err = fe->ops.tuner_ops.get_rf_strength(fe, parg);
-			/* If no error occurs, prevent dvb-core from handling
-			 * this IOCTL, otherwise return the error */
-			if (0 == err)
-				err = 1;
-			break;
-		}
-		break;
-
-	case DVB_FE_IOCTL_POST:
-		/* no post-ioctl handling required */
-		break;
-	}
-	return err;
-};
-
-static u32 mxl111sf_i2c_func(struct i2c_adapter *adapter)
-{
-	return I2C_FUNC_I2C;
-}
-
-struct i2c_algorithm mxl111sf_i2c_algo = {
-	.master_xfer   = mxl111sf_i2c_xfer,
-	.functionality = mxl111sf_i2c_func,
-#ifdef NEED_ALGO_CONTROL
-	.algo_control = dummy_algo_control,
-#endif
-};
-
-static struct dvb_usb_device_properties mxl111sf_dvbt_bulk_properties;
-static struct dvb_usb_device_properties mxl111sf_dvbt_isoc_properties;
-static struct dvb_usb_device_properties mxl111sf_atsc_bulk_properties;
-static struct dvb_usb_device_properties mxl111sf_atsc_isoc_properties;
-static struct dvb_usb_device_properties mxl111sf_atsc_mh_bulk_properties;
-static struct dvb_usb_device_properties mxl111sf_atsc_mh_isoc_properties;
-static struct dvb_usb_device_properties mxl111sf_mh_bulk_properties;
-static struct dvb_usb_device_properties mxl111sf_mh_isoc_properties;
-static struct dvb_usb_device_properties mxl111sf_mercury_spi_bulk_properties;
-static struct dvb_usb_device_properties mxl111sf_mercury_spi_isoc_properties;
-static struct dvb_usb_device_properties mxl111sf_mercury_tp_bulk_properties;
-static struct dvb_usb_device_properties mxl111sf_mercury_tp_isoc_properties;
-static struct dvb_usb_device_properties mxl111sf_mercury_mh_spi_bulk_properties;
-static struct dvb_usb_device_properties mxl111sf_mercury_mh_spi_isoc_properties;
-static struct dvb_usb_device_properties mxl111sf_mercury_mh_tp_bulk_properties;
-static struct dvb_usb_device_properties mxl111sf_mercury_mh_tp_isoc_properties;
-
-static int mxl111sf_probe(struct usb_interface *intf,
-			  const struct usb_device_id *id)
-{
-	struct dvb_usb_device *d = NULL;
-
-	deb_adv("%s()\n", __func__);
-
-	if (((dvb_usb_mxl111sf_isoc) &&
-	     (0 == dvb_usb_device_init(intf,
-				       &mxl111sf_dvbt_isoc_properties,
-				       THIS_MODULE, &d, adapter_nr) ||
-	      0 == dvb_usb_device_init(intf,
-				       &mxl111sf_atsc_isoc_properties,
-				       THIS_MODULE, &d, adapter_nr) ||
-	      0 == dvb_usb_device_init(intf,
-				       &mxl111sf_atsc_mh_isoc_properties,
-				       THIS_MODULE, &d, adapter_nr) ||
-	      0 == dvb_usb_device_init(intf,
-				       &mxl111sf_mh_isoc_properties,
-				       THIS_MODULE, &d, adapter_nr) ||
-	      ((dvb_usb_mxl111sf_spi) &&
-	       (0 == dvb_usb_device_init(intf,
-					 &mxl111sf_mercury_spi_isoc_properties,
-					 THIS_MODULE, &d, adapter_nr) ||
-		0 == dvb_usb_device_init(intf,
-					 &mxl111sf_mercury_mh_spi_isoc_properties,
-					 THIS_MODULE, &d, adapter_nr))) ||
-	      0 == dvb_usb_device_init(intf,
-				       &mxl111sf_mercury_tp_isoc_properties,
-				       THIS_MODULE, &d, adapter_nr) ||
-	      0 == dvb_usb_device_init(intf,
-				       &mxl111sf_mercury_mh_tp_isoc_properties,
-				       THIS_MODULE, &d, adapter_nr))) ||
-	    0 == dvb_usb_device_init(intf,
-				     &mxl111sf_dvbt_bulk_properties,
-				     THIS_MODULE, &d, adapter_nr) ||
-	    0 == dvb_usb_device_init(intf,
-				     &mxl111sf_atsc_bulk_properties,
-				     THIS_MODULE, &d, adapter_nr) ||
-	    0 == dvb_usb_device_init(intf,
-				     &mxl111sf_atsc_mh_bulk_properties,
-				     THIS_MODULE, &d, adapter_nr) ||
-	    0 == dvb_usb_device_init(intf,
-				     &mxl111sf_mh_bulk_properties,
-				     THIS_MODULE, &d, adapter_nr) ||
-	    ((dvb_usb_mxl111sf_spi) &&
-	     (0 == dvb_usb_device_init(intf,
-				       &mxl111sf_mercury_spi_bulk_properties,
-				       THIS_MODULE, &d, adapter_nr) ||
-	      0 == dvb_usb_device_init(intf,
-				       &mxl111sf_mercury_mh_spi_bulk_properties,
-				       THIS_MODULE, &d, adapter_nr))) ||
-	    0 == dvb_usb_device_init(intf,
-				     &mxl111sf_mercury_tp_bulk_properties,
-				     THIS_MODULE, &d, adapter_nr) ||
-	    0 == dvb_usb_device_init(intf,
-				     &mxl111sf_mercury_mh_tp_bulk_properties,
-				     THIS_MODULE, &d, adapter_nr) || 0) {
-
-		struct mxl111sf_state *state = d->priv;
-		static u8 eeprom[256];
-		struct i2c_client c;
-		int ret;
-
-		ret = get_chip_info(state);
-		if (mxl_fail(ret))
-			err("failed to get chip info during probe");
-
-		mutex_init(&state->fe_lock);
-
-		if (state->chip_rev > MXL111SF_V6)
-			mxl111sf_config_pin_mux_modes(state,
-						      PIN_MUX_TS_SPI_IN_MODE_1);
-
-		c.adapter = &d->i2c_adap;
-		c.addr = 0xa0 >> 1;
-
-		ret = tveeprom_read(&c, eeprom, sizeof(eeprom));
-		if (mxl_fail(ret))
-			return 0;
-		tveeprom_hauppauge_analog(&c, &state->tv,
-					  (0x84 == eeprom[0xa0]) ?
-					  eeprom + 0xa0 : eeprom + 0x80);
-#if 0
-		switch (state->tv.model) {
-		case 117001:
-		case 126001:
-		case 138001:
-			break;
-		default:
-			printk(KERN_WARNING "%s: warning: "
-			       "unknown hauppauge model #%d\n",
-			       __func__, state->tv.model);
-		}
-#endif
-		return 0;
-	}
-	err("Your device is not yet supported by this driver. "
-	    "See kernellabs.com for more info");
-	return -EINVAL;
-}
-
-static struct usb_device_id mxl111sf_table[] = {
-/* 0 */	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc600) }, /* ATSC+ IR     */
-	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc601) }, /* ATSC         */
-	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc602) }, /*     +        */
-	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc603) }, /* ATSC+        */
-	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc604) }, /* DVBT         */
-/* 5 */	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc609) }, /* ATSC  IR     */
-	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc60a) }, /*     + IR     */
-	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc60b) }, /* ATSC+ IR     */
-	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc60c) }, /* DVBT  IR     */
-	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc653) }, /* ATSC+        */
-/*10 */	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc65b) }, /* ATSC+ IR     */
-	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xb700) }, /* ATSC+ sw     */
-	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xb701) }, /* ATSC  sw     */
-	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xb702) }, /*     + sw     */
-	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xb703) }, /* ATSC+ sw     */
-/*15 */	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xb704) }, /* DVBT  sw     */
-	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xb753) }, /* ATSC+ sw     */
-	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xb763) }, /* ATSC+ no     */
-	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xb764) }, /* DVBT  no     */
-	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xd853) }, /* ATSC+ sw     */
-/*20 */	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xd854) }, /* DVBT  sw     */
-	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xd863) }, /* ATSC+ no     */
-	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xd864) }, /* DVBT  no     */
-	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xd8d3) }, /* ATSC+ sw     */
-	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xd8d4) }, /* DVBT  sw     */
-/*25 */	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xd8e3) }, /* ATSC+ no     */
-	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xd8e4) }, /* DVBT  no     */
-	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xd8ff) }, /* ATSC+        */
-	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc612) }, /*     +        */
-	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc613) }, /* ATSC+        */
-/*30 */	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc61a) }, /*     + IR     */
-	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xc61b) }, /* ATSC+ IR     */
-	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xb757) }, /* ATSC+DVBT sw */
-	{ USB_DEVICE(USB_VID_HAUPPAUGE, 0xb767) }, /* ATSC+DVBT no */
-	{}		/* Terminating entry */
-};
-MODULE_DEVICE_TABLE(usb, mxl111sf_table);
-
-
-#define MXL111SF_EP4_BULK_STREAMING_CONFIG		\
-	.size_of_priv = sizeof(struct mxl111sf_adap_state), \
-	.streaming_ctrl = mxl111sf_ep4_streaming_ctrl,	\
-	.stream = {					\
-		.type = USB_BULK,			\
-		.count = 5,				\
-		.endpoint = 0x04,			\
-		.u = {					\
-			.bulk = {			\
-				.buffersize = 8192,	\
-			}				\
-		}					\
-	}
-
-/* FIXME: works for v6 but not v8 silicon */
-#define MXL111SF_EP4_ISOC_STREAMING_CONFIG		\
-	.size_of_priv = sizeof(struct mxl111sf_adap_state), \
-	.streaming_ctrl = mxl111sf_ep4_streaming_ctrl,	\
-	.stream = {					\
-		.type = USB_ISOC,			\
-		.count = 5,				\
-		.endpoint = 0x04,			\
-		.u = {					\
-			.isoc = {			\
-				.framesperurb = 96,	\
-				/* FIXME: v6 SILICON: */	\
-				.framesize = 564,	\
-				.interval = 1,		\
-			}				\
-		}					\
-	}
-
-#define MXL111SF_EP5_BULK_STREAMING_CONFIG		\
-	.size_of_priv = sizeof(struct mxl111sf_adap_state), \
-	.streaming_ctrl = mxl111sf_ep5_streaming_ctrl,	\
-	.stream = {					\
-		.type = USB_BULK,			\
-		.count = 5,				\
-		.endpoint = 0x05,			\
-		.u = {					\
-			.bulk = {			\
-				.buffersize = 8192,	\
-			}				\
-		}					\
-	}
-
-#define MXL111SF_EP5_ISOC_STREAMING_CONFIG		\
-	.size_of_priv = sizeof(struct mxl111sf_adap_state), \
-	.streaming_ctrl = mxl111sf_ep5_streaming_ctrl,	\
-	.stream = {					\
-		.type = USB_ISOC,			\
-		.count = 5,				\
-		.endpoint = 0x05,			\
-		.u = {					\
-			.isoc = {			\
-				.framesperurb = 96,	\
-				.framesize = 200,	\
-				.interval = 1,		\
-			}				\
-		}					\
-	}
-
-#define MXL111SF_EP6_BULK_STREAMING_CONFIG		\
-	.size_of_priv = sizeof(struct mxl111sf_adap_state), \
-	.streaming_ctrl = mxl111sf_ep6_streaming_ctrl,	\
-	.stream = {					\
-		.type = USB_BULK,			\
-		.count = 5,				\
-		.endpoint = 0x06,			\
-		.u = {					\
-			.bulk = {			\
-				.buffersize = 8192,	\
-			}				\
-		}					\
-	}
-
-/* FIXME */
-#define MXL111SF_EP6_ISOC_STREAMING_CONFIG		\
-	.size_of_priv = sizeof(struct mxl111sf_adap_state), \
-	.streaming_ctrl = mxl111sf_ep6_streaming_ctrl,	\
-	.stream = {					\
-		.type = USB_ISOC,			\
-		.count = 5,				\
-		.endpoint = 0x06,			\
-		.u = {					\
-			.isoc = {			\
-				.framesperurb = 24,	\
-				.framesize = 3072,	\
-				.interval = 1,		\
-			}				\
-		}					\
-	}
-
-#define MXL111SF_DEFAULT_DEVICE_PROPERTIES			\
-	.caps = DVB_USB_IS_AN_I2C_ADAPTER,			\
-	.usb_ctrl = DEVICE_SPECIFIC,				\
-	/* use usb alt setting 1 for EP4 ISOC transfer (dvb-t),	\
-				     EP6 BULK transfer (atsc/qam), \
-	   use usb alt setting 2 for EP4 BULK transfer (dvb-t),	\
-				     EP6 ISOC transfer (atsc/qam), \
-	*/							\
-	.power_ctrl       = mxl111sf_power_ctrl,		\
-	.i2c_algo         = &mxl111sf_i2c_algo,			\
-	.generic_bulk_ctrl_endpoint          = MXL_EP2_REG_WRITE, \
-	.generic_bulk_ctrl_endpoint_response = MXL_EP1_REG_READ, \
-	.size_of_priv     = sizeof(struct mxl111sf_state)
-
-static struct dvb_usb_device_properties mxl111sf_dvbt_bulk_properties = {
-	MXL111SF_DEFAULT_DEVICE_PROPERTIES,
-
-	.num_adapters = 1,
-	.adapter = {
-		{
-		.fe_ioctl_override = mxl111sf_fe_ioctl_override,
-		.num_frontends = 1,
-		.fe = {{
-			.frontend_attach  = mxl111sf_attach_demod,
-			.tuner_attach     = mxl111sf_attach_tuner,
-
-			MXL111SF_EP4_BULK_STREAMING_CONFIG,
-		} },
-		},
-	},
-	.num_device_descs = 3,
-	.devices = {
-		{   "Hauppauge 126xxx DVBT (bulk)",
-			{ NULL },
-			{ &mxl111sf_table[4], &mxl111sf_table[8],
-			  NULL },
-		},
-		{   "Hauppauge 117xxx DVBT (bulk)",
-			{ NULL },
-			{ &mxl111sf_table[15], &mxl111sf_table[18],
-			  NULL },
-		},
-		{   "Hauppauge 138xxx DVBT (bulk)",
-			{ NULL },
-			{ &mxl111sf_table[20], &mxl111sf_table[22],
-			  &mxl111sf_table[24], &mxl111sf_table[26],
-			  NULL },
-		},
-	}
-};
-
-static struct dvb_usb_device_properties mxl111sf_dvbt_isoc_properties = {
-	MXL111SF_DEFAULT_DEVICE_PROPERTIES,
-
-	.num_adapters = 1,
-	.adapter = {
-		{
-		.fe_ioctl_override = mxl111sf_fe_ioctl_override,
-		.num_frontends = 1,
-		.fe = {{
-			.frontend_attach  = mxl111sf_attach_demod,
-			.tuner_attach     = mxl111sf_attach_tuner,
-
-			MXL111SF_EP4_ISOC_STREAMING_CONFIG,
-		} },
-		},
-	},
-	.num_device_descs = 3,
-	.devices = {
-		{   "Hauppauge 126xxx DVBT (isoc)",
-			{ NULL },
-			{ &mxl111sf_table[4], &mxl111sf_table[8],
-			  NULL },
-		},
-		{   "Hauppauge 117xxx DVBT (isoc)",
-			{ NULL },
-			{ &mxl111sf_table[15], &mxl111sf_table[18],
-			  NULL },
-		},
-		{   "Hauppauge 138xxx DVBT (isoc)",
-			{ NULL },
-			{ &mxl111sf_table[20], &mxl111sf_table[22],
-			  &mxl111sf_table[24], &mxl111sf_table[26],
-			  NULL },
-		},
-	}
-};
-
-static struct dvb_usb_device_properties mxl111sf_atsc_bulk_properties = {
-	MXL111SF_DEFAULT_DEVICE_PROPERTIES,
-
-	.num_adapters = 1,
-	.adapter = {
-		{
-		.fe_ioctl_override = mxl111sf_fe_ioctl_override,
-		.num_frontends = 1,
-		.fe = {{
-			.frontend_attach  = mxl111sf_lgdt3305_frontend_attach,
-			.tuner_attach     = mxl111sf_attach_tuner,
-
-			MXL111SF_EP6_BULK_STREAMING_CONFIG,
-		}},
-		},
-	},
-	.num_device_descs = 2,
-	.devices = {
-		{   "Hauppauge 126xxx ATSC (bulk)",
-			{ NULL },
-			{ &mxl111sf_table[1], &mxl111sf_table[5],
-			  NULL },
-		},
-		{   "Hauppauge 117xxx ATSC (bulk)",
-			{ NULL },
-			{ &mxl111sf_table[12],
-			  NULL },
-		},
-	}
-};
-
-static struct dvb_usb_device_properties mxl111sf_atsc_isoc_properties = {
-	MXL111SF_DEFAULT_DEVICE_PROPERTIES,
-
-	.num_adapters = 1,
-	.adapter = {
-		{
-		.fe_ioctl_override = mxl111sf_fe_ioctl_override,
-		.num_frontends = 1,
-		.fe = {{
-			.frontend_attach  = mxl111sf_lgdt3305_frontend_attach,
-			.tuner_attach     = mxl111sf_attach_tuner,
-
-			MXL111SF_EP6_ISOC_STREAMING_CONFIG,
-		}},
-		},
-	},
-	.num_device_descs = 2,
-	.devices = {
-		{   "Hauppauge 126xxx ATSC (isoc)",
-			{ NULL },
-			{ &mxl111sf_table[1], &mxl111sf_table[5],
-			  NULL },
-		},
-		{   "Hauppauge 117xxx ATSC (isoc)",
-			{ NULL },
-			{ &mxl111sf_table[12],
-			  NULL },
-		},
-	}
-};
-
-static struct dvb_usb_device_properties mxl111sf_mh_bulk_properties = {
-	MXL111SF_DEFAULT_DEVICE_PROPERTIES,
-
-	.num_adapters = 1,
-	.adapter = {
-		{
-		.fe_ioctl_override = mxl111sf_fe_ioctl_override,
-		.num_frontends = 1,
-		.fe = {{
-			.caps = DVB_USB_ADAP_RECEIVES_RAW_PAYLOAD,
-
-			.frontend_attach  = mxl111sf_lg2160_frontend_attach,
-			.tuner_attach     = mxl111sf_attach_tuner,
-
-			MXL111SF_EP5_BULK_STREAMING_CONFIG,
-		}},
-		},
-	},
-	.num_device_descs = 2,
-	.devices = {
-		{   "HCW 126xxx (bulk)",
-			{ NULL },
-			{ &mxl111sf_table[2], &mxl111sf_table[6],
-			  NULL },
-		},
-		{   "HCW 117xxx (bulk)",
-			{ NULL },
-			{ &mxl111sf_table[13],
-			  NULL },
-		},
-	}
-};
-
-static struct dvb_usb_device_properties mxl111sf_mh_isoc_properties = {
-	MXL111SF_DEFAULT_DEVICE_PROPERTIES,
-
-	.num_adapters = 1,
-	.adapter = {
-		{
-		.fe_ioctl_override = mxl111sf_fe_ioctl_override,
-		.num_frontends = 1,
-		.fe = {{
-			.caps = DVB_USB_ADAP_RECEIVES_RAW_PAYLOAD,
-
-			.frontend_attach  = mxl111sf_lg2160_frontend_attach,
-			.tuner_attach     = mxl111sf_attach_tuner,
-
-			MXL111SF_EP5_ISOC_STREAMING_CONFIG,
-		}},
-		},
-	},
-	.num_device_descs = 2,
-	.devices = {
-		{   "HCW 126xxx (isoc)",
-			{ NULL },
-			{ &mxl111sf_table[2], &mxl111sf_table[6],
-			  NULL },
-		},
-		{   "HCW 117xxx (isoc)",
-			{ NULL },
-			{ &mxl111sf_table[13],
-			  NULL },
-		},
-	}
-};
-
-static struct dvb_usb_device_properties mxl111sf_atsc_mh_bulk_properties = {
-	MXL111SF_DEFAULT_DEVICE_PROPERTIES,
-
-	.num_adapters = 1,
-	.adapter = {
-		{
-		.fe_ioctl_override = mxl111sf_fe_ioctl_override,
-		.num_frontends = 3,
-		.fe = {{
-			.frontend_attach  = mxl111sf_lgdt3305_frontend_attach,
-			.tuner_attach     = mxl111sf_attach_tuner,
-
-			MXL111SF_EP6_BULK_STREAMING_CONFIG,
-		},
-		{
-			.frontend_attach  = mxl111sf_attach_demod,
-			.tuner_attach     = mxl111sf_attach_tuner,
-
-			MXL111SF_EP4_BULK_STREAMING_CONFIG,
-		},
-		{
-			.caps = DVB_USB_ADAP_RECEIVES_RAW_PAYLOAD,
-
-			.frontend_attach  = mxl111sf_lg2160_frontend_attach,
-			.tuner_attach     = mxl111sf_attach_tuner,
-
-			MXL111SF_EP5_BULK_STREAMING_CONFIG,
-		}},
-		},
-	},
-	.num_device_descs = 2,
-	.devices = {
-		{   "Hauppauge 126xxx ATSC+ (bulk)",
-			{ NULL },
-			{ &mxl111sf_table[0], &mxl111sf_table[3],
-			  &mxl111sf_table[7], &mxl111sf_table[9],
-			  &mxl111sf_table[10], NULL },
-		},
-		{   "Hauppauge 117xxx ATSC+ (bulk)",
-			{ NULL },
-			{ &mxl111sf_table[11], &mxl111sf_table[14],
-			  &mxl111sf_table[16], &mxl111sf_table[17],
-			  &mxl111sf_table[32], &mxl111sf_table[33],
-			  NULL },
-		},
-	}
-};
-
-static struct dvb_usb_device_properties mxl111sf_atsc_mh_isoc_properties = {
-	MXL111SF_DEFAULT_DEVICE_PROPERTIES,
-
-	.num_adapters = 1,
-	.adapter = {
-		{
-		.fe_ioctl_override = mxl111sf_fe_ioctl_override,
-		.num_frontends = 3,
-		.fe = {{
-			.frontend_attach  = mxl111sf_lgdt3305_frontend_attach,
-			.tuner_attach     = mxl111sf_attach_tuner,
-
-			MXL111SF_EP6_ISOC_STREAMING_CONFIG,
-		},
-		{
-			.frontend_attach  = mxl111sf_attach_demod,
-			.tuner_attach     = mxl111sf_attach_tuner,
-
-			MXL111SF_EP4_ISOC_STREAMING_CONFIG,
-		},
-		{
-			.caps = DVB_USB_ADAP_RECEIVES_RAW_PAYLOAD,
-
-			.frontend_attach  = mxl111sf_lg2160_frontend_attach,
-			.tuner_attach     = mxl111sf_attach_tuner,
-
-			MXL111SF_EP5_ISOC_STREAMING_CONFIG,
-		}},
-		},
-	},
-	.num_device_descs = 2,
-	.devices = {
-		{   "Hauppauge 126xxx ATSC+ (isoc)",
-			{ NULL },
-			{ &mxl111sf_table[0], &mxl111sf_table[3],
-			  &mxl111sf_table[7], &mxl111sf_table[9],
-			  &mxl111sf_table[10], NULL },
-		},
-		{   "Hauppauge 117xxx ATSC+ (isoc)",
-			{ NULL },
-			{ &mxl111sf_table[11], &mxl111sf_table[14],
-			  &mxl111sf_table[16], &mxl111sf_table[17],
-			  &mxl111sf_table[32], &mxl111sf_table[33],
-			  NULL },
-		},
-	}
-};
-
-static struct dvb_usb_device_properties mxl111sf_mercury_spi_bulk_properties = {
-	MXL111SF_DEFAULT_DEVICE_PROPERTIES,
-
-	.num_adapters = 1,
-	.adapter = {
-		{
-		.fe_ioctl_override = mxl111sf_fe_ioctl_override,
-		.num_frontends = 3,
-		.fe = {{
-			.frontend_attach  = mxl111sf_lgdt3305_frontend_attach,
-			.tuner_attach     = mxl111sf_attach_tuner,
-
-			MXL111SF_EP6_BULK_STREAMING_CONFIG,
-		},
-		{
-			.frontend_attach  = mxl111sf_attach_demod,
-			.tuner_attach     = mxl111sf_attach_tuner,
-
-			MXL111SF_EP4_BULK_STREAMING_CONFIG,
-		},
-		{
-			.caps = DVB_USB_ADAP_RECEIVES_RAW_PAYLOAD,
-
-			.frontend_attach  = mxl111sf_lg2161_frontend_attach,
-			.tuner_attach     = mxl111sf_attach_tuner,
-
-			MXL111SF_EP5_BULK_STREAMING_CONFIG,
-		}},
-		},
-	},
-	.num_device_descs = 2,
-	.devices = {
-		{   "Hauppauge Mercury (spi-bulk)",
-			{ NULL },
-			{ &mxl111sf_table[19], &mxl111sf_table[21],
-			  &mxl111sf_table[23], &mxl111sf_table[25],
-			  NULL },
-		},
-		{   "Hauppauge WinTV-Aero-M (spi-bulk)",
-			{ NULL },
-			{ &mxl111sf_table[29], &mxl111sf_table[31],
-			  NULL },
-		},
-	}
-};
-
-static struct dvb_usb_device_properties mxl111sf_mercury_spi_isoc_properties = {
-	MXL111SF_DEFAULT_DEVICE_PROPERTIES,
-
-	.num_adapters = 1,
-	.adapter = {
-		{
-		.fe_ioctl_override = mxl111sf_fe_ioctl_override,
-		.num_frontends = 3,
-		.fe = {{
-			.frontend_attach  = mxl111sf_lgdt3305_frontend_attach,
-			.tuner_attach     = mxl111sf_attach_tuner,
-
-			MXL111SF_EP6_ISOC_STREAMING_CONFIG,
-		},
-		{
-			.frontend_attach  = mxl111sf_attach_demod,
-			.tuner_attach     = mxl111sf_attach_tuner,
-
-			MXL111SF_EP4_ISOC_STREAMING_CONFIG,
-		},
-		{
-			.caps = DVB_USB_ADAP_RECEIVES_RAW_PAYLOAD,
-
-			.frontend_attach  = mxl111sf_lg2161_frontend_attach,
-			.tuner_attach     = mxl111sf_attach_tuner,
-
-			MXL111SF_EP5_ISOC_STREAMING_CONFIG,
-		}},
-		},
-	},
-	.num_device_descs = 2,
-	.devices = {
-		{   "Hauppauge Mercury (spi-isoc)",
-			{ NULL },
-			{ &mxl111sf_table[19], &mxl111sf_table[21],
-			  &mxl111sf_table[23], &mxl111sf_table[25],
-			  NULL },
-		},
-		{   "Hauppauge WinTV-Aero-M (spi-isoc)",
-			{ NULL },
-			{ &mxl111sf_table[29], &mxl111sf_table[31],
-			  NULL },
-		},
-	}
-};
-
-static struct dvb_usb_device_properties mxl111sf_mercury_tp_bulk_properties = {
-	MXL111SF_DEFAULT_DEVICE_PROPERTIES,
-
-	.num_adapters = 1,
-	.adapter = {
-		{
-		.fe_ioctl_override = mxl111sf_fe_ioctl_override,
-		.num_frontends = 3,
-		.fe = {{
-			.frontend_attach  = mxl111sf_lgdt3305_frontend_attach,
-			.tuner_attach     = mxl111sf_attach_tuner,
-
-			MXL111SF_EP6_BULK_STREAMING_CONFIG,
-		},
-		{
-			.frontend_attach  = mxl111sf_attach_demod,
-			.tuner_attach     = mxl111sf_attach_tuner,
-
-			MXL111SF_EP4_BULK_STREAMING_CONFIG,
-		},
-		{
-			.caps = DVB_USB_ADAP_RECEIVES_RAW_PAYLOAD,
-
-			.frontend_attach  = mxl111sf_lg2161_ep6_frontend_attach,
-			.tuner_attach     = mxl111sf_attach_tuner,
-
-			MXL111SF_EP6_BULK_STREAMING_CONFIG,
-		}},
-		},
-	},
-	.num_device_descs = 2,
-	.devices = {
-		{   "Hauppauge Mercury (tp-bulk)",
-			{ NULL },
-			{ &mxl111sf_table[19], &mxl111sf_table[21],
-			  &mxl111sf_table[23], &mxl111sf_table[25],
-			  &mxl111sf_table[27], NULL },
-		},
-		{   "Hauppauge WinTV-Aero-M",
-			{ NULL },
-			{ &mxl111sf_table[29], &mxl111sf_table[31],
-			  NULL },
-		},
-	}
-};
-
-static struct dvb_usb_device_properties mxl111sf_mercury_tp_isoc_properties = {
-	MXL111SF_DEFAULT_DEVICE_PROPERTIES,
-
-	.num_adapters = 1,
-	.adapter = {
-		{
-		.fe_ioctl_override = mxl111sf_fe_ioctl_override,
-		.num_frontends = 3,
-		.fe = {{
-			.frontend_attach  = mxl111sf_lgdt3305_frontend_attach,
-			.tuner_attach     = mxl111sf_attach_tuner,
-
-			MXL111SF_EP6_ISOC_STREAMING_CONFIG,
-		},
-		{
-			.frontend_attach  = mxl111sf_attach_demod,
-			.tuner_attach     = mxl111sf_attach_tuner,
-
-			MXL111SF_EP4_ISOC_STREAMING_CONFIG,
-		},
-		{
-			.caps = DVB_USB_ADAP_RECEIVES_RAW_PAYLOAD,
-
-			.frontend_attach  = mxl111sf_lg2161_ep6_frontend_attach,
-			.tuner_attach     = mxl111sf_attach_tuner,
-
-			MXL111SF_EP6_ISOC_STREAMING_CONFIG,
-		}},
-		},
-	},
-	.num_device_descs = 2,
-	.devices = {
-		{   "Hauppauge Mercury (tp-isoc)",
-			{ NULL },
-			{ &mxl111sf_table[19], &mxl111sf_table[21],
-			  &mxl111sf_table[23], &mxl111sf_table[25],
-			  &mxl111sf_table[27], NULL },
-		},
-		{   "Hauppauge WinTV-Aero-M (tp-isoc)",
-			{ NULL },
-			{ &mxl111sf_table[29], &mxl111sf_table[31],
-			  NULL },
-		},
-	}
-};
-
-static
-struct dvb_usb_device_properties mxl111sf_mercury_mh_tp_bulk_properties = {
-	MXL111SF_DEFAULT_DEVICE_PROPERTIES,
-
-	.num_adapters = 1,
-	.adapter = {
-		{
-		.fe_ioctl_override = mxl111sf_fe_ioctl_override,
-		.num_frontends = 2,
-		.fe = {{
-			.frontend_attach  = mxl111sf_attach_demod,
-			.tuner_attach     = mxl111sf_attach_tuner,
-
-			MXL111SF_EP4_BULK_STREAMING_CONFIG,
-		},
-		{
-			.caps = DVB_USB_ADAP_RECEIVES_RAW_PAYLOAD,
-
-			.frontend_attach  = mxl111sf_lg2161_ep6_frontend_attach,
-			.tuner_attach     = mxl111sf_attach_tuner,
-
-			MXL111SF_EP6_BULK_STREAMING_CONFIG,
-		}},
-		},
-	},
-	.num_device_descs = 1,
-	.devices = {
-		{   "Hauppauge 126xxx (tp-bulk)",
-			{ NULL },
-			{ &mxl111sf_table[28], &mxl111sf_table[30],
-			  NULL },
-		},
-	}
-};
-
-static
-struct dvb_usb_device_properties mxl111sf_mercury_mh_tp_isoc_properties = {
-	MXL111SF_DEFAULT_DEVICE_PROPERTIES,
-
-	.num_adapters = 1,
-	.adapter = {
-		{
-		.fe_ioctl_override = mxl111sf_fe_ioctl_override,
-		.num_frontends = 2,
-		.fe = {{
-			.frontend_attach  = mxl111sf_attach_demod,
-			.tuner_attach     = mxl111sf_attach_tuner,
-
-			MXL111SF_EP4_ISOC_STREAMING_CONFIG,
-		},
-		{
-			.caps = DVB_USB_ADAP_RECEIVES_RAW_PAYLOAD,
-
-			.frontend_attach  = mxl111sf_lg2161_ep6_frontend_attach,
-			.tuner_attach     = mxl111sf_attach_tuner,
-
-			MXL111SF_EP6_ISOC_STREAMING_CONFIG,
-		}},
-		},
-	},
-	.num_device_descs = 1,
-	.devices = {
-		{   "Hauppauge 126xxx (tp-isoc)",
-			{ NULL },
-			{ &mxl111sf_table[28], &mxl111sf_table[30],
-			  NULL },
-		},
-	}
-};
-
-static
-struct dvb_usb_device_properties mxl111sf_mercury_mh_spi_bulk_properties = {
-	MXL111SF_DEFAULT_DEVICE_PROPERTIES,
-
-	.num_adapters = 1,
-	.adapter = {
-		{
-		.fe_ioctl_override = mxl111sf_fe_ioctl_override,
-		.num_frontends = 2,
-		.fe = {{
-			.frontend_attach  = mxl111sf_attach_demod,
-			.tuner_attach     = mxl111sf_attach_tuner,
-
-			MXL111SF_EP4_BULK_STREAMING_CONFIG,
-		},
-		{
-			.caps = DVB_USB_ADAP_RECEIVES_RAW_PAYLOAD,
-
-			.frontend_attach  = mxl111sf_lg2161_frontend_attach,
-			.tuner_attach     = mxl111sf_attach_tuner,
-
-			MXL111SF_EP5_BULK_STREAMING_CONFIG,
-		}},
-		},
-	},
-	.num_device_descs = 1,
-	.devices = {
-		{   "Hauppauge 126xxx (spi-bulk)",
-			{ NULL },
-			{ &mxl111sf_table[28], &mxl111sf_table[30],
-			  NULL },
-		},
-	}
-};
-
-static
-struct dvb_usb_device_properties mxl111sf_mercury_mh_spi_isoc_properties = {
-	MXL111SF_DEFAULT_DEVICE_PROPERTIES,
-
-	.num_adapters = 1,
-	.adapter = {
-		{
-		.fe_ioctl_override = mxl111sf_fe_ioctl_override,
-		.num_frontends = 2,
-		.fe = {{
-			.frontend_attach  = mxl111sf_attach_demod,
-			.tuner_attach     = mxl111sf_attach_tuner,
-
-			MXL111SF_EP4_ISOC_STREAMING_CONFIG,
-		},
-		{
-			.caps = DVB_USB_ADAP_RECEIVES_RAW_PAYLOAD,
-
-			.frontend_attach  = mxl111sf_lg2161_frontend_attach,
-			.tuner_attach     = mxl111sf_attach_tuner,
-
-			MXL111SF_EP5_ISOC_STREAMING_CONFIG,
-		}},
-		},
-	},
-	.num_device_descs = 1,
-	.devices = {
-		{   "Hauppauge 126xxx (spi-isoc)",
-			{ NULL },
-			{ &mxl111sf_table[28], &mxl111sf_table[30],
-			  NULL },
-		},
-	}
-};
-
-static struct usb_driver mxl111sf_driver = {
-	.name		= "dvb_usb_mxl111sf",
-	.probe		= mxl111sf_probe,
-	.disconnect     = dvb_usb_device_exit,
-	.id_table	= mxl111sf_table,
-};
-
-module_usb_driver(mxl111sf_driver);
-
-MODULE_AUTHOR("Michael Krufky <mkrufky@kernellabs.com>");
-MODULE_DESCRIPTION("Driver for MaxLinear MxL111SF");
-MODULE_VERSION("1.0");
-MODULE_LICENSE("GPL");
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/dvb/dvb-usb/mxl111sf.h b/drivers/media/dvb/dvb-usb/mxl111sf.h
deleted file mode 100644
index 364d89f..0000000
--- a/drivers/media/dvb/dvb-usb/mxl111sf.h
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Copyright (C) 2010 Michael Krufky (mkrufky@kernellabs.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, version 2.
- *
- * see Documentation/dvb/README.dvb-usb for more information
- */
-
-#ifndef _DVB_USB_MXL111SF_H_
-#define _DVB_USB_MXL111SF_H_
-
-#ifdef DVB_USB_LOG_PREFIX
-#undef DVB_USB_LOG_PREFIX
-#endif
-#define DVB_USB_LOG_PREFIX "mxl111sf"
-#include "dvb-usb.h"
-#include <media/tveeprom.h>
-
-#define MXL_EP1_REG_READ     1
-#define MXL_EP2_REG_WRITE    2
-#define MXL_EP3_INTERRUPT    3
-#define MXL_EP4_MPEG2        4
-#define MXL_EP5_I2S          5
-#define MXL_EP6_656          6
-#define MXL_EP6_MPEG2        6
-
-#ifdef USING_ENUM_mxl111sf_current_mode
-enum mxl111sf_current_mode {
-	mxl_mode_dvbt = MXL_EP4_MPEG2,
-	mxl_mode_mh   = MXL_EP5_I2S,
-	mxl_mode_atsc = MXL_EP6_MPEG2,
-};
-#endif
-
-enum mxl111sf_gpio_port_expander {
-	mxl111sf_gpio_hw,
-	mxl111sf_PCA9534,
-};
-
-struct mxl111sf_state {
-	struct dvb_usb_device *d;
-
-	enum mxl111sf_gpio_port_expander gpio_port_expander;
-	u8 port_expander_addr;
-
-	u8 chip_id;
-	u8 chip_ver;
-#define MXL111SF_V6     1
-#define MXL111SF_V8_100 2
-#define MXL111SF_V8_200 3
-	u8 chip_rev;
-
-#ifdef USING_ENUM_mxl111sf_current_mode
-	enum mxl111sf_current_mode current_mode;
-#endif
-
-#define MXL_TUNER_MODE         0
-#define MXL_SOC_MODE           1
-#define MXL_DEV_MODE_MASK      0x01
-#if 1
-	int device_mode;
-#endif
-	/* use usb alt setting 1 for EP4 ISOC transfer (dvb-t),
-				     EP5 BULK transfer (atsc-mh),
-				     EP6 BULK transfer (atsc/qam),
-	   use usb alt setting 2 for EP4 BULK transfer (dvb-t),
-				     EP5 ISOC transfer (atsc-mh),
-				     EP6 ISOC transfer (atsc/qam),
-	 */
-	int alt_mode;
-	int gpio_mode;
-	struct tveeprom tv;
-
-	struct mutex fe_lock;
-};
-
-struct mxl111sf_adap_state {
-	int alt_mode;
-	int gpio_mode;
-	int device_mode;
-	int ep6_clockphase;
-	int (*fe_init)(struct dvb_frontend *);
-	int (*fe_sleep)(struct dvb_frontend *);
-};
-
-int mxl111sf_read_reg(struct mxl111sf_state *state, u8 addr, u8 *data);
-int mxl111sf_write_reg(struct mxl111sf_state *state, u8 addr, u8 data);
-
-struct mxl111sf_reg_ctrl_info {
-	u8 addr;
-	u8 mask;
-	u8 data;
-};
-
-int mxl111sf_write_reg_mask(struct mxl111sf_state *state,
-			    u8 addr, u8 mask, u8 data);
-int mxl111sf_ctrl_program_regs(struct mxl111sf_state *state,
-			       struct mxl111sf_reg_ctrl_info *ctrl_reg_info);
-
-/* needed for hardware i2c functions in mxl111sf-i2c.c:
- * mxl111sf_i2c_send_data / mxl111sf_i2c_get_data */
-int mxl111sf_ctrl_msg(struct dvb_usb_device *d,
-		      u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen);
-
-#define mxl_printk(kern, fmt, arg...) \
-	printk(kern "%s: " fmt "\n", __func__, ##arg)
-
-#define mxl_info(fmt, arg...) \
-	mxl_printk(KERN_INFO, fmt, ##arg)
-
-extern int dvb_usb_mxl111sf_debug;
-#define mxl_debug(fmt, arg...) \
-	if (dvb_usb_mxl111sf_debug) \
-		mxl_printk(KERN_DEBUG, fmt, ##arg)
-
-#define MXL_I2C_DBG 0x04
-#define MXL_ADV_DBG 0x10
-#define mxl_debug_adv(fmt, arg...) \
-	if (dvb_usb_mxl111sf_debug & MXL_ADV_DBG) \
-		mxl_printk(KERN_DEBUG, fmt, ##arg)
-
-#define mxl_i2c(fmt, arg...) \
-	if (dvb_usb_mxl111sf_debug & MXL_I2C_DBG) \
-		mxl_printk(KERN_DEBUG, fmt, ##arg)
-
-#define mxl_i2c_adv(fmt, arg...) \
-	if ((dvb_usb_mxl111sf_debug & (MXL_I2C_DBG | MXL_ADV_DBG)) == \
-		(MXL_I2C_DBG | MXL_ADV_DBG)) \
-			mxl_printk(KERN_DEBUG, fmt, ##arg)
-
-/* The following allows the mxl_fail() macro defined below to work
- * in externel modules, such as mxl111sf-tuner.ko, even though
- * dvb_usb_mxl111sf_debug is not defined within those modules */
-#if (defined(__MXL111SF_TUNER_H__)) || (defined(__MXL111SF_DEMOD_H__))
-#define MXL_ADV_DEBUG_ENABLED MXL_ADV_DBG
-#else
-#define MXL_ADV_DEBUG_ENABLED dvb_usb_mxl111sf_debug
-#endif
-
-#define mxl_fail(ret)							\
-({									\
-	int __ret;							\
-	__ret = (ret < 0);						\
-	if ((__ret) && (MXL_ADV_DEBUG_ENABLED & MXL_ADV_DBG))		\
-		mxl_printk(KERN_ERR, "error %d on line %d",		\
-			   ret, __LINE__);				\
-	__ret;								\
-})
-
-#endif /* _DVB_USB_MXL111SF_H_ */
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/dvb/dvb-usb/nova-t-usb2.c b/drivers/media/dvb/dvb-usb/nova-t-usb2.c
deleted file mode 100644
index 6c55384..0000000
--- a/drivers/media/dvb/dvb-usb/nova-t-usb2.c
+++ /dev/null
@@ -1,233 +0,0 @@
-/* DVB USB framework compliant Linux driver for the Hauppauge WinTV-NOVA-T usb2
- * DVB-T receiver.
- *
- * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
- *
- *	This program is free software; you can redistribute it and/or modify it
- *	under the terms of the GNU General Public License as published by the Free
- *	Software Foundation, version 2.
- *
- * see Documentation/dvb/README.dvb-usb for more information
- */
-#include "dibusb.h"
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level (1=rc,2=eeprom (|-able))." DVB_USB_DEBUG_STATUS);
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-#define deb_rc(args...) dprintk(debug,0x01,args)
-#define deb_ee(args...) dprintk(debug,0x02,args)
-
-/* Hauppauge NOVA-T USB2 keys */
-static struct rc_map_table rc_map_haupp_table[] = {
-	{ 0x1e00, KEY_0 },
-	{ 0x1e01, KEY_1 },
-	{ 0x1e02, KEY_2 },
-	{ 0x1e03, KEY_3 },
-	{ 0x1e04, KEY_4 },
-	{ 0x1e05, KEY_5 },
-	{ 0x1e06, KEY_6 },
-	{ 0x1e07, KEY_7 },
-	{ 0x1e08, KEY_8 },
-	{ 0x1e09, KEY_9 },
-	{ 0x1e0a, KEY_KPASTERISK },
-	{ 0x1e0b, KEY_RED },
-	{ 0x1e0c, KEY_RADIO },
-	{ 0x1e0d, KEY_MENU },
-	{ 0x1e0e, KEY_GRAVE }, /* # */
-	{ 0x1e0f, KEY_MUTE },
-	{ 0x1e10, KEY_VOLUMEUP },
-	{ 0x1e11, KEY_VOLUMEDOWN },
-	{ 0x1e12, KEY_CHANNEL },
-	{ 0x1e14, KEY_UP },
-	{ 0x1e15, KEY_DOWN },
-	{ 0x1e16, KEY_LEFT },
-	{ 0x1e17, KEY_RIGHT },
-	{ 0x1e18, KEY_VIDEO },
-	{ 0x1e19, KEY_AUDIO },
-	{ 0x1e1a, KEY_IMAGES },
-	{ 0x1e1b, KEY_EPG },
-	{ 0x1e1c, KEY_TV },
-	{ 0x1e1e, KEY_NEXT },
-	{ 0x1e1f, KEY_BACK },
-	{ 0x1e20, KEY_CHANNELUP },
-	{ 0x1e21, KEY_CHANNELDOWN },
-	{ 0x1e24, KEY_LAST }, /* Skip backwards */
-	{ 0x1e25, KEY_OK },
-	{ 0x1e29, KEY_BLUE},
-	{ 0x1e2e, KEY_GREEN },
-	{ 0x1e30, KEY_PAUSE },
-	{ 0x1e32, KEY_REWIND },
-	{ 0x1e34, KEY_FASTFORWARD },
-	{ 0x1e35, KEY_PLAY },
-	{ 0x1e36, KEY_STOP },
-	{ 0x1e37, KEY_RECORD },
-	{ 0x1e38, KEY_YELLOW },
-	{ 0x1e3b, KEY_GOTO },
-	{ 0x1e3d, KEY_POWER },
-};
-
-/* Firmware bug? sometimes, when a new key is pressed, the previous pressed key
- * is delivered. No workaround yet, maybe a new firmware.
- */
-static int nova_t_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
-{
-	u8 key[5],cmd[2] = { DIBUSB_REQ_POLL_REMOTE, 0x35 }, data,toggle,custom;
-	u16 raw;
-	int i;
-	struct dibusb_device_state *st = d->priv;
-
-	dvb_usb_generic_rw(d,cmd,2,key,5,0);
-
-	*state = REMOTE_NO_KEY_PRESSED;
-	switch (key[0]) {
-		case DIBUSB_RC_HAUPPAUGE_KEY_PRESSED:
-			raw = ((key[1] << 8) | key[2]) >> 3;
-			toggle = !!(raw & 0x800);
-			data = raw & 0x3f;
-			custom = (raw >> 6) & 0x1f;
-
-			deb_rc("raw key code 0x%02x, 0x%02x, 0x%02x to c: %02x d: %02x toggle: %d\n",key[1],key[2],key[3],custom,data,toggle);
-
-			for (i = 0; i < ARRAY_SIZE(rc_map_haupp_table); i++) {
-				if (rc5_data(&rc_map_haupp_table[i]) == data &&
-					rc5_custom(&rc_map_haupp_table[i]) == custom) {
-
-					deb_rc("c: %x, d: %x\n", rc5_data(&rc_map_haupp_table[i]),
-								 rc5_custom(&rc_map_haupp_table[i]));
-
-					*event = rc_map_haupp_table[i].keycode;
-					*state = REMOTE_KEY_PRESSED;
-					if (st->old_toggle == toggle) {
-						if (st->last_repeat_count++ < 2)
-							*state = REMOTE_NO_KEY_PRESSED;
-					} else {
-						st->last_repeat_count = 0;
-						st->old_toggle = toggle;
-					}
-					break;
-				}
-			}
-
-			break;
-		case DIBUSB_RC_HAUPPAUGE_KEY_EMPTY:
-		default:
-			break;
-	}
-
-	return 0;
-}
-
-static int nova_t_read_mac_address (struct dvb_usb_device *d, u8 mac[6])
-{
-	int i;
-	u8 b;
-
-	mac[0] = 0x00;
-	mac[1] = 0x0d;
-	mac[2] = 0xfe;
-
-	/* this is a complete guess, but works for my box */
-	for (i = 136; i < 139; i++) {
-		dibusb_read_eeprom_byte(d,i, &b);
-
-		mac[5 - (i - 136)] = b;
-	}
-
-	return 0;
-}
-
-/* USB Driver stuff */
-static struct dvb_usb_device_properties nova_t_properties;
-
-static int nova_t_probe(struct usb_interface *intf,
-		const struct usb_device_id *id)
-{
-	return dvb_usb_device_init(intf, &nova_t_properties,
-				   THIS_MODULE, NULL, adapter_nr);
-}
-
-/* do not change the order of the ID table */
-static struct usb_device_id nova_t_table [] = {
-/* 00 */	{ USB_DEVICE(USB_VID_HAUPPAUGE,     USB_PID_WINTV_NOVA_T_USB2_COLD) },
-/* 01 */	{ USB_DEVICE(USB_VID_HAUPPAUGE,     USB_PID_WINTV_NOVA_T_USB2_WARM) },
-			{ }		/* Terminating entry */
-};
-MODULE_DEVICE_TABLE(usb, nova_t_table);
-
-static struct dvb_usb_device_properties nova_t_properties = {
-	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
-
-	.usb_ctrl = CYPRESS_FX2,
-	.firmware = "dvb-usb-nova-t-usb2-02.fw",
-
-	.num_adapters     = 1,
-	.adapter          = {
-		{
-		.num_frontends = 1,
-		.fe = {{
-			.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
-			.pid_filter_count = 32,
-
-			.streaming_ctrl   = dibusb2_0_streaming_ctrl,
-			.pid_filter       = dibusb_pid_filter,
-			.pid_filter_ctrl  = dibusb_pid_filter_ctrl,
-			.frontend_attach  = dibusb_dib3000mc_frontend_attach,
-			.tuner_attach     = dibusb_dib3000mc_tuner_attach,
-
-			/* parameter for the MPEG2-data transfer */
-					.stream = {
-						.type = USB_BULK,
-				.count = 7,
-				.endpoint = 0x06,
-				.u = {
-					.bulk = {
-						.buffersize = 4096,
-					}
-				}
-			},
-		}},
-			.size_of_priv     = sizeof(struct dibusb_state),
-		}
-	},
-	.size_of_priv     = sizeof(struct dibusb_device_state),
-
-	.power_ctrl       = dibusb2_0_power_ctrl,
-	.read_mac_address = nova_t_read_mac_address,
-
-	.rc.legacy = {
-		.rc_interval      = 100,
-		.rc_map_table     = rc_map_haupp_table,
-		.rc_map_size      = ARRAY_SIZE(rc_map_haupp_table),
-		.rc_query         = nova_t_rc_query,
-	},
-
-	.i2c_algo         = &dibusb_i2c_algo,
-
-	.generic_bulk_ctrl_endpoint = 0x01,
-
-	.num_device_descs = 1,
-	.devices = {
-		{   "Hauppauge WinTV-NOVA-T usb2",
-			{ &nova_t_table[0], NULL },
-			{ &nova_t_table[1], NULL },
-		},
-		{ NULL },
-	}
-};
-
-static struct usb_driver nova_t_driver = {
-	.name		= "dvb_usb_nova_t_usb2",
-	.probe		= nova_t_probe,
-	.disconnect = dvb_usb_device_exit,
-	.id_table	= nova_t_table,
-};
-
-module_usb_driver(nova_t_driver);
-
-MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
-MODULE_DESCRIPTION("Hauppauge WinTV-NOVA-T usb2");
-MODULE_VERSION("1.0");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/opera1.c b/drivers/media/dvb/dvb-usb/opera1.c
deleted file mode 100644
index c8a9504..0000000
--- a/drivers/media/dvb/dvb-usb/opera1.c
+++ /dev/null
@@ -1,583 +0,0 @@
-/* DVB USB framework compliant Linux driver for the Opera1 DVB-S Card
-*
-* Copyright (C) 2006 Mario Hlawitschka (dh1pa@amsat.org)
-* Copyright (C) 2006 Marco Gittler (g.marco@freenet.de)
-*
-*	This program is free software; you can redistribute it and/or modify it
-*	under the terms of the GNU General Public License as published by the Free
-*	Software Foundation, version 2.
-*
-* see Documentation/dvb/README.dvb-usb for more information
-*/
-
-#define DVB_USB_LOG_PREFIX "opera"
-
-#include "dvb-usb.h"
-#include "stv0299.h"
-
-#define OPERA_READ_MSG 0
-#define OPERA_WRITE_MSG 1
-#define OPERA_I2C_TUNER 0xd1
-
-#define READ_FX2_REG_REQ  0xba
-#define READ_MAC_ADDR 0x08
-#define OPERA_WRITE_FX2 0xbb
-#define OPERA_TUNER_REQ 0xb1
-#define REG_1F_SYMBOLRATE_BYTE0 0x1f
-#define REG_20_SYMBOLRATE_BYTE1 0x20
-#define REG_21_SYMBOLRATE_BYTE2 0x21
-
-#define ADDR_B600_VOLTAGE_13V (0x02)
-#define ADDR_B601_VOLTAGE_18V (0x03)
-#define ADDR_B1A6_STREAM_CTRL (0x04)
-#define ADDR_B880_READ_REMOTE (0x05)
-
-struct opera1_state {
-	u32 last_key_pressed;
-};
-struct rc_map_opera_table {
-	u32 keycode;
-	u32 event;
-};
-
-static int dvb_usb_opera1_debug;
-module_param_named(debug, dvb_usb_opera1_debug, int, 0644);
-MODULE_PARM_DESC(debug,
-		 "set debugging level (1=info,xfer=2,pll=4,ts=8,err=16,rc=32,fw=64 (or-able))."
-		 DVB_USB_DEBUG_STATUS);
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-
-static int opera1_xilinx_rw(struct usb_device *dev, u8 request, u16 value,
-			    u8 * data, u16 len, int flags)
-{
-	int ret;
-	u8 tmp;
-	u8 *buf;
-	unsigned int pipe = (flags == OPERA_READ_MSG) ?
-		usb_rcvctrlpipe(dev,0) : usb_sndctrlpipe(dev, 0);
-	u8 request_type = (flags == OPERA_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT;
-
-	buf = kmalloc(len, GFP_KERNEL);
-	if (!buf)
-		return -ENOMEM;
-
-	if (flags == OPERA_WRITE_MSG)
-		memcpy(buf, data, len);
-	ret = usb_control_msg(dev, pipe, request,
-			request_type | USB_TYPE_VENDOR, value, 0x0,
-			buf, len, 2000);
-
-	if (request == OPERA_TUNER_REQ) {
-		tmp = buf[0];
-		if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
-			    OPERA_TUNER_REQ, USB_DIR_IN | USB_TYPE_VENDOR,
-			    0x01, 0x0, buf, 1, 2000) < 1 || buf[0] != 0x08) {
-			ret = 0;
-			goto out;
-		}
-		buf[0] = tmp;
-	}
-	if (flags == OPERA_READ_MSG)
-		memcpy(data, buf, len);
-out:
-	kfree(buf);
-	return ret;
-}
-
-/* I2C */
-
-static int opera1_usb_i2c_msgxfer(struct dvb_usb_device *dev, u16 addr,
-				  u8 * buf, u16 len)
-{
-	int ret = 0;
-	u8 request;
-	u16 value;
-
-	if (!dev) {
-		info("no usb_device");
-		return -EINVAL;
-	}
-	if (mutex_lock_interruptible(&dev->usb_mutex) < 0)
-		return -EAGAIN;
-
-	switch (addr>>1){
-		case ADDR_B600_VOLTAGE_13V:
-			request=0xb6;
-			value=0x00;
-			break;
-		case ADDR_B601_VOLTAGE_18V:
-			request=0xb6;
-			value=0x01;
-			break;
-		case ADDR_B1A6_STREAM_CTRL:
-			request=0xb1;
-			value=0xa6;
-			break;
-		case ADDR_B880_READ_REMOTE:
-			request=0xb8;
-			value=0x80;
-			break;
-		default:
-			request=0xb1;
-			value=addr;
-	}
-	ret = opera1_xilinx_rw(dev->udev, request,
-		value, buf, len,
-		addr&0x01?OPERA_READ_MSG:OPERA_WRITE_MSG);
-
-	mutex_unlock(&dev->usb_mutex);
-	return ret;
-}
-
-static int opera1_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
-			   int num)
-{
-	struct dvb_usb_device *d = i2c_get_adapdata(adap);
-	int i = 0, tmp = 0;
-
-	if (!d)
-		return -ENODEV;
-	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
-		return -EAGAIN;
-
-	for (i = 0; i < num; i++) {
-		if ((tmp = opera1_usb_i2c_msgxfer(d,
-					(msg[i].addr<<1)|(msg[i].flags&I2C_M_RD?0x01:0),
-					msg[i].buf,
-					msg[i].len
-					)) != msg[i].len) {
-			break;
-		}
-		if (dvb_usb_opera1_debug & 0x10)
-			info("sending i2c mesage %d %d", tmp, msg[i].len);
-	}
-	mutex_unlock(&d->i2c_mutex);
-	return num;
-}
-
-static u32 opera1_i2c_func(struct i2c_adapter *adapter)
-{
-	return I2C_FUNC_I2C;
-}
-
-static struct i2c_algorithm opera1_i2c_algo = {
-	.master_xfer = opera1_i2c_xfer,
-	.functionality = opera1_i2c_func,
-};
-
-static int opera1_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
-{
-	static u8 command_13v[1]={0x00};
-	static u8 command_18v[1]={0x01};
-	struct i2c_msg msg[] = {
-		{.addr = ADDR_B600_VOLTAGE_13V,.flags = 0,.buf = command_13v,.len = 1},
-	};
-	struct dvb_usb_adapter *udev_adap =
-	    (struct dvb_usb_adapter *)(fe->dvb->priv);
-	if (voltage == SEC_VOLTAGE_18) {
-		msg[0].addr = ADDR_B601_VOLTAGE_18V;
-		msg[0].buf = command_18v;
-	}
-	i2c_transfer(&udev_adap->dev->i2c_adap, msg, 1);
-	return 0;
-}
-
-static int opera1_stv0299_set_symbol_rate(struct dvb_frontend *fe, u32 srate,
-					  u32 ratio)
-{
-	stv0299_writereg(fe, 0x13, 0x98);
-	stv0299_writereg(fe, 0x14, 0x95);
-	stv0299_writereg(fe, REG_1F_SYMBOLRATE_BYTE0, (ratio >> 16) & 0xff);
-	stv0299_writereg(fe, REG_20_SYMBOLRATE_BYTE1, (ratio >> 8) & 0xff);
-	stv0299_writereg(fe, REG_21_SYMBOLRATE_BYTE2, (ratio) & 0xf0);
-	return 0;
-
-}
-static u8 opera1_inittab[] = {
-	0x00, 0xa1,
-	0x01, 0x15,
-	0x02, 0x30,
-	0x03, 0x00,
-	0x04, 0x7d,
-	0x05, 0x05,
-	0x06, 0x02,
-	0x07, 0x00,
-	0x0b, 0x00,
-	0x0c, 0x01,
-	0x0d, 0x81,
-	0x0e, 0x44,
-	0x0f, 0x19,
-	0x10, 0x3f,
-	0x11, 0x84,
-	0x12, 0xda,
-	0x13, 0x98,
-	0x14, 0x95,
-	0x15, 0xc9,
-	0x16, 0xeb,
-	0x17, 0x00,
-	0x18, 0x19,
-	0x19, 0x8b,
-	0x1a, 0x00,
-	0x1b, 0x82,
-	0x1c, 0x7f,
-	0x1d, 0x00,
-	0x1e, 0x00,
-	REG_1F_SYMBOLRATE_BYTE0, 0x06,
-	REG_20_SYMBOLRATE_BYTE1, 0x50,
-	REG_21_SYMBOLRATE_BYTE2, 0x10,
-	0x22, 0x00,
-	0x23, 0x00,
-	0x24, 0x37,
-	0x25, 0xbc,
-	0x26, 0x00,
-	0x27, 0x00,
-	0x28, 0x00,
-	0x29, 0x1e,
-	0x2a, 0x14,
-	0x2b, 0x1f,
-	0x2c, 0x09,
-	0x2d, 0x0a,
-	0x2e, 0x00,
-	0x2f, 0x00,
-	0x30, 0x00,
-	0x31, 0x1f,
-	0x32, 0x19,
-	0x33, 0xfc,
-	0x34, 0x13,
-	0xff, 0xff,
-};
-
-static struct stv0299_config opera1_stv0299_config = {
-	.demod_address = 0xd0>>1,
-	.min_delay_ms = 100,
-	.mclk = 88000000UL,
-	.invert = 1,
-	.skip_reinit = 0,
-	.lock_output = STV0299_LOCKOUTPUT_0,
-	.volt13_op0_op1 = STV0299_VOLT13_OP0,
-	.inittab = opera1_inittab,
-	.set_symbol_rate = opera1_stv0299_set_symbol_rate,
-};
-
-static int opera1_frontend_attach(struct dvb_usb_adapter *d)
-{
-	d->fe_adap[0].fe = dvb_attach(stv0299_attach, &opera1_stv0299_config,
-				      &d->dev->i2c_adap);
-	if ((d->fe_adap[0].fe) != NULL) {
-		d->fe_adap[0].fe->ops.set_voltage = opera1_set_voltage;
-		return 0;
-	}
-	info("not attached stv0299");
-	return -EIO;
-}
-
-static int opera1_tuner_attach(struct dvb_usb_adapter *adap)
-{
-	dvb_attach(
-		dvb_pll_attach, adap->fe_adap[0].fe, 0xc0>>1,
-		&adap->dev->i2c_adap, DVB_PLL_OPERA1
-	);
-	return 0;
-}
-
-static int opera1_power_ctrl(struct dvb_usb_device *d, int onoff)
-{
-	u8 val = onoff ? 0x01 : 0x00;
-
-	if (dvb_usb_opera1_debug)
-		info("power %s", onoff ? "on" : "off");
-	return opera1_xilinx_rw(d->udev, 0xb7, val,
-				&val, 1, OPERA_WRITE_MSG);
-}
-
-static int opera1_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
-{
-	static u8 buf_start[2] = { 0xff, 0x03 };
-	static u8 buf_stop[2] = { 0xff, 0x00 };
-	struct i2c_msg start_tuner[] = {
-		{.addr = ADDR_B1A6_STREAM_CTRL,.buf = onoff ? buf_start : buf_stop,.len = 2},
-	};
-	if (dvb_usb_opera1_debug)
-		info("streaming %s", onoff ? "on" : "off");
-	i2c_transfer(&adap->dev->i2c_adap, start_tuner, 1);
-	return 0;
-}
-
-static int opera1_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid,
-			     int onoff)
-{
-	u8 b_pid[3];
-	struct i2c_msg msg[] = {
-		{.addr = ADDR_B1A6_STREAM_CTRL,.buf = b_pid,.len = 3},
-	};
-	if (dvb_usb_opera1_debug)
-		info("pidfilter index: %d pid: %d %s", index, pid,
-			onoff ? "on" : "off");
-	b_pid[0] = (2 * index) + 4;
-	b_pid[1] = onoff ? (pid & 0xff) : (0x00);
-	b_pid[2] = onoff ? ((pid >> 8) & 0xff) : (0x00);
-	i2c_transfer(&adap->dev->i2c_adap, msg, 1);
-	return 0;
-}
-
-static int opera1_pid_filter_control(struct dvb_usb_adapter *adap, int onoff)
-{
-	int u = 0x04;
-	u8 b_pid[3];
-	struct i2c_msg msg[] = {
-		{.addr = ADDR_B1A6_STREAM_CTRL,.buf = b_pid,.len = 3},
-	};
-	if (dvb_usb_opera1_debug)
-		info("%s hw-pidfilter", onoff ? "enable" : "disable");
-	for (; u < 0x7e; u += 2) {
-		b_pid[0] = u;
-		b_pid[1] = 0;
-		b_pid[2] = 0x80;
-		i2c_transfer(&adap->dev->i2c_adap, msg, 1);
-	}
-	return 0;
-}
-
-static struct rc_map_table rc_map_opera1_table[] = {
-	{0x5fa0, KEY_1},
-	{0x51af, KEY_2},
-	{0x5da2, KEY_3},
-	{0x41be, KEY_4},
-	{0x0bf5, KEY_5},
-	{0x43bd, KEY_6},
-	{0x47b8, KEY_7},
-	{0x49b6, KEY_8},
-	{0x05fa, KEY_9},
-	{0x45ba, KEY_0},
-	{0x09f6, KEY_CHANNELUP},	/*chanup */
-	{0x1be5, KEY_CHANNELDOWN},	/*chandown */
-	{0x5da3, KEY_VOLUMEDOWN},	/*voldown */
-	{0x5fa1, KEY_VOLUMEUP},		/*volup */
-	{0x07f8, KEY_SPACE},		/*tab */
-	{0x1fe1, KEY_OK},		/*play ok */
-	{0x1be4, KEY_ZOOM},		/*zoom */
-	{0x59a6, KEY_MUTE},		/*mute */
-	{0x5ba5, KEY_RADIO},		/*tv/f */
-	{0x19e7, KEY_RECORD},		/*rec */
-	{0x01fe, KEY_STOP},		/*Stop */
-	{0x03fd, KEY_PAUSE},		/*pause */
-	{0x03fc, KEY_SCREEN},		/*<- -> */
-	{0x07f9, KEY_CAMERA},		/*capture */
-	{0x47b9, KEY_ESC},		/*exit */
-	{0x43bc, KEY_POWER2},		/*power */
-};
-
-static int opera1_rc_query(struct dvb_usb_device *dev, u32 * event, int *state)
-{
-	struct opera1_state *opst = dev->priv;
-	u8 rcbuffer[32];
-	const u16 startmarker1 = 0x10ed;
-	const u16 startmarker2 = 0x11ec;
-	struct i2c_msg read_remote[] = {
-		{.addr = ADDR_B880_READ_REMOTE,.buf = rcbuffer,.flags = I2C_M_RD,.len = 32},
-	};
-	int i = 0;
-	u32 send_key = 0;
-
-	if (i2c_transfer(&dev->i2c_adap, read_remote, 1) == 1) {
-		for (i = 0; i < 32; i++) {
-			if (rcbuffer[i])
-				send_key |= 1;
-			if (i < 31)
-				send_key = send_key << 1;
-		}
-		if (send_key & 0x8000)
-			send_key = (send_key << 1) | (send_key >> 15 & 0x01);
-
-		if (send_key == 0xffff && opst->last_key_pressed != 0) {
-			*state = REMOTE_KEY_REPEAT;
-			*event = opst->last_key_pressed;
-			return 0;
-		}
-		for (; send_key != 0;) {
-			if (send_key >> 16 == startmarker2) {
-				break;
-			} else if (send_key >> 16 == startmarker1) {
-				send_key =
-					(send_key & 0xfffeffff) | (startmarker1 << 16);
-				break;
-			} else
-				send_key >>= 1;
-		}
-
-		if (send_key == 0)
-			return 0;
-
-		send_key = (send_key & 0xffff) | 0x0100;
-
-		for (i = 0; i < ARRAY_SIZE(rc_map_opera1_table); i++) {
-			if (rc5_scan(&rc_map_opera1_table[i]) == (send_key & 0xffff)) {
-				*state = REMOTE_KEY_PRESSED;
-				*event = rc_map_opera1_table[i].keycode;
-				opst->last_key_pressed =
-					rc_map_opera1_table[i].keycode;
-				break;
-			}
-			opst->last_key_pressed = 0;
-		}
-	} else
-		*state = REMOTE_NO_KEY_PRESSED;
-	return 0;
-}
-
-static struct usb_device_id opera1_table[] = {
-	{USB_DEVICE(USB_VID_CYPRESS, USB_PID_OPERA1_COLD)},
-	{USB_DEVICE(USB_VID_OPERA1, USB_PID_OPERA1_WARM)},
-	{}
-};
-
-MODULE_DEVICE_TABLE(usb, opera1_table);
-
-static int opera1_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
-{
-	u8 command[] = { READ_MAC_ADDR };
-	opera1_xilinx_rw(d->udev, 0xb1, 0xa0, command, 1, OPERA_WRITE_MSG);
-	opera1_xilinx_rw(d->udev, 0xb1, 0xa1, mac, 6, OPERA_READ_MSG);
-	return 0;
-}
-static int opera1_xilinx_load_firmware(struct usb_device *dev,
-				       const char *filename)
-{
-	const struct firmware *fw = NULL;
-	u8 *b, *p;
-	int ret = 0, i,fpgasize=40;
-	u8 testval;
-	info("start downloading fpga firmware %s",filename);
-
-	if ((ret = request_firmware(&fw, filename, &dev->dev)) != 0) {
-		err("did not find the firmware file. (%s) "
-			"Please see linux/Documentation/dvb/ for more details on firmware-problems.",
-			filename);
-		return ret;
-	} else {
-		p = kmalloc(fw->size, GFP_KERNEL);
-		opera1_xilinx_rw(dev, 0xbc, 0x00, &testval, 1, OPERA_READ_MSG);
-		if (p != NULL && testval != 0x67) {
-
-			u8 reset = 0, fpga_command = 0;
-			memcpy(p, fw->data, fw->size);
-			/* clear fpga ? */
-			opera1_xilinx_rw(dev, 0xbc, 0xaa, &fpga_command, 1,
-					 OPERA_WRITE_MSG);
-			for (i = 0; i < fw->size;) {
-				if ( (fw->size - i) <fpgasize){
-				    fpgasize=fw->size-i;
-				}
-				b = (u8 *) p + i;
-				if (opera1_xilinx_rw
-					(dev, OPERA_WRITE_FX2, 0x0, b , fpgasize,
-						OPERA_WRITE_MSG) != fpgasize
-					) {
-					err("error while transferring firmware");
-					ret = -EINVAL;
-					break;
-				}
-				i = i + fpgasize;
-			}
-			/* restart the CPU */
-			if (ret || opera1_xilinx_rw
-					(dev, 0xa0, 0xe600, &reset, 1,
-					OPERA_WRITE_MSG) != 1) {
-				err("could not restart the USB controller CPU.");
-				ret = -EINVAL;
-			}
-		}
-	}
-	kfree(p);
-	release_firmware(fw);
-	return ret;
-}
-
-static struct dvb_usb_device_properties opera1_properties = {
-	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
-	.usb_ctrl = CYPRESS_FX2,
-	.firmware = "dvb-usb-opera-01.fw",
-	.size_of_priv = sizeof(struct opera1_state),
-
-	.power_ctrl = opera1_power_ctrl,
-	.i2c_algo = &opera1_i2c_algo,
-
-	.rc.legacy = {
-		.rc_map_table = rc_map_opera1_table,
-		.rc_map_size = ARRAY_SIZE(rc_map_opera1_table),
-		.rc_interval = 200,
-		.rc_query = opera1_rc_query,
-	},
-	.read_mac_address = opera1_read_mac_address,
-	.generic_bulk_ctrl_endpoint = 0x00,
-	/* parameter for the MPEG2-data transfer */
-	.num_adapters = 1,
-	.adapter = {
-		{
-		.num_frontends = 1,
-		.fe = {{
-			.frontend_attach = opera1_frontend_attach,
-			.streaming_ctrl = opera1_streaming_ctrl,
-			.tuner_attach = opera1_tuner_attach,
-			.caps =
-				DVB_USB_ADAP_HAS_PID_FILTER |
-				DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
-			.pid_filter = opera1_pid_filter,
-			.pid_filter_ctrl = opera1_pid_filter_control,
-			.pid_filter_count = 252,
-			.stream = {
-				.type = USB_BULK,
-				.count = 10,
-				.endpoint = 0x82,
-				.u = {
-					.bulk = {
-						.buffersize = 4096,
-					}
-				}
-			},
-		}},
-		}
-	},
-	.num_device_descs = 1,
-	.devices = {
-		{"Opera1 DVB-S USB2.0",
-			{&opera1_table[0], NULL},
-			{&opera1_table[1], NULL},
-		},
-	}
-};
-
-static int opera1_probe(struct usb_interface *intf,
-			const struct usb_device_id *id)
-{
-	struct usb_device *udev = interface_to_usbdev(intf);
-
-	if (udev->descriptor.idProduct == USB_PID_OPERA1_WARM &&
-		udev->descriptor.idVendor == USB_VID_OPERA1 &&
-		opera1_xilinx_load_firmware(udev, "dvb-usb-opera1-fpga-01.fw") != 0
-	    ) {
-		return -EINVAL;
-	}
-
-	if (0 != dvb_usb_device_init(intf, &opera1_properties,
-				     THIS_MODULE, NULL, adapter_nr))
-		return -EINVAL;
-	return 0;
-}
-
-static struct usb_driver opera1_driver = {
-	.name = "opera1",
-	.probe = opera1_probe,
-	.disconnect = dvb_usb_device_exit,
-	.id_table = opera1_table,
-};
-
-module_usb_driver(opera1_driver);
-
-MODULE_AUTHOR("Mario Hlawitschka (c) dh1pa@amsat.org");
-MODULE_AUTHOR("Marco Gittler (c) g.marco@freenet.de");
-MODULE_DESCRIPTION("Driver for Opera1 DVB-S device");
-MODULE_VERSION("0.1");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/pctv452e.c b/drivers/media/dvb/dvb-usb/pctv452e.c
deleted file mode 100644
index f526eb0..0000000
--- a/drivers/media/dvb/dvb-usb/pctv452e.c
+++ /dev/null
@@ -1,1064 +0,0 @@
-/*
- * PCTV 452e DVB driver
- *
- * Copyright (c) 2006-2008 Dominik Kuhlen <dkuhlen@gmx.net>
- *
- * TT connect S2-3650-CI Common Interface support, MAC readout
- * Copyright (C) 2008 Michael H. Schimek <mschimek@gmx.at>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- */
-
-/* dvb usb framework */
-#define DVB_USB_LOG_PREFIX "pctv452e"
-#include "dvb-usb.h"
-
-/* Demodulator */
-#include "stb0899_drv.h"
-#include "stb0899_reg.h"
-#include "stb0899_cfg.h"
-/* Tuner */
-#include "stb6100.h"
-#include "stb6100_cfg.h"
-/* FE Power */
-#include "lnbp22.h"
-
-#include "dvb_ca_en50221.h"
-#include "ttpci-eeprom.h"
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-#define ISOC_INTERFACE_ALTERNATIVE 3
-
-#define SYNC_BYTE_OUT 0xaa
-#define SYNC_BYTE_IN  0x55
-
-/* guessed: (copied from ttusb-budget) */
-#define PCTV_CMD_RESET 0x15
-/* command to poll IR receiver */
-#define PCTV_CMD_IR    0x1b
-/* command to send I2C  */
-#define PCTV_CMD_I2C   0x31
-
-#define I2C_ADDR_STB0899 (0xd0 >> 1)
-#define I2C_ADDR_STB6100 (0xc0 >> 1)
-#define I2C_ADDR_LNBP22  (0x10 >> 1)
-#define I2C_ADDR_24C16   (0xa0 >> 1)
-#define I2C_ADDR_24C64   (0xa2 >> 1)
-
-
-/* pctv452e sends us this amount of data for each issued usb-command */
-#define PCTV_ANSWER_LEN 64
-/* Wait up to 1000ms for device  */
-#define PCTV_TIMEOUT 1000
-
-
-#define PCTV_LED_GPIO   STB0899_GPIO01
-#define PCTV_LED_GREEN  0x82
-#define PCTV_LED_ORANGE 0x02
-
-#define ci_dbg(format, arg...)				\
-do {							\
-	if (0)						\
-		printk(KERN_DEBUG DVB_USB_LOG_PREFIX	\
-			": " format "\n" , ## arg);	\
-} while (0)
-
-enum {
-	TT3650_CMD_CI_TEST = 0x40,
-	TT3650_CMD_CI_RD_CTRL,
-	TT3650_CMD_CI_WR_CTRL,
-	TT3650_CMD_CI_RD_ATTR,
-	TT3650_CMD_CI_WR_ATTR,
-	TT3650_CMD_CI_RESET,
-	TT3650_CMD_CI_SET_VIDEO_PORT
-};
-
-
-static struct stb0899_postproc pctv45e_postproc[] = {
-	{ PCTV_LED_GPIO, STB0899_GPIOPULLUP },
-	{ 0, 0 }
-};
-
-/*
- * stores all private variables for communication with the PCTV452e DVB-S2
- */
-struct pctv452e_state {
-	struct dvb_ca_en50221 ca;
-	struct mutex ca_mutex;
-
-	u8 c;	   /* transaction counter, wraps around...  */
-	u8 initialized; /* set to 1 if 0x15 has been sent */
-	u16 last_rc_key;
-};
-
-static int tt3650_ci_msg(struct dvb_usb_device *d, u8 cmd, u8 *data,
-			 unsigned int write_len, unsigned int read_len)
-{
-	struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
-	u8 buf[64];
-	u8 id;
-	unsigned int rlen;
-	int ret;
-
-	BUG_ON(NULL == data && 0 != (write_len | read_len));
-	BUG_ON(write_len > 64 - 4);
-	BUG_ON(read_len > 64 - 4);
-
-	id = state->c++;
-
-	buf[0] = SYNC_BYTE_OUT;
-	buf[1] = id;
-	buf[2] = cmd;
-	buf[3] = write_len;
-
-	memcpy(buf + 4, data, write_len);
-
-	rlen = (read_len > 0) ? 64 : 0;
-	ret = dvb_usb_generic_rw(d, buf, 4 + write_len,
-				  buf, rlen, /* delay_ms */ 0);
-	if (0 != ret)
-		goto failed;
-
-	ret = -EIO;
-	if (SYNC_BYTE_IN != buf[0] || id != buf[1])
-		goto failed;
-
-	memcpy(data, buf + 4, read_len);
-
-	return 0;
-
-failed:
-	err("CI error %d; %02X %02X %02X -> %02X %02X %02X.",
-	     ret, SYNC_BYTE_OUT, id, cmd, buf[0], buf[1], buf[2]);
-
-	return ret;
-}
-
-static int tt3650_ci_msg_locked(struct dvb_ca_en50221 *ca,
-				u8 cmd, u8 *data, unsigned int write_len,
-				unsigned int read_len)
-{
-	struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
-	struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
-	int ret;
-
-	mutex_lock(&state->ca_mutex);
-	ret = tt3650_ci_msg(d, cmd, data, write_len, read_len);
-	mutex_unlock(&state->ca_mutex);
-
-	return ret;
-}
-
-static int tt3650_ci_read_attribute_mem(struct dvb_ca_en50221 *ca,
-				 int slot, int address)
-{
-	u8 buf[3];
-	int ret;
-
-	if (0 != slot)
-		return -EINVAL;
-
-	buf[0] = (address >> 8) & 0x0F;
-	buf[1] = address;
-
-	ret = tt3650_ci_msg_locked(ca, TT3650_CMD_CI_RD_ATTR, buf, 2, 3);
-
-	ci_dbg("%s %04x -> %d 0x%02x",
-		__func__, address, ret, buf[2]);
-
-	if (ret < 0)
-		return ret;
-
-	return buf[2];
-}
-
-static int tt3650_ci_write_attribute_mem(struct dvb_ca_en50221 *ca,
-				 int slot, int address, u8 value)
-{
-	u8 buf[3];
-
-	ci_dbg("%s %d 0x%04x 0x%02x",
-		__func__, slot, address, value);
-
-	if (0 != slot)
-		return -EINVAL;
-
-	buf[0] = (address >> 8) & 0x0F;
-	buf[1] = address;
-	buf[2] = value;
-
-	return tt3650_ci_msg_locked(ca, TT3650_CMD_CI_WR_ATTR, buf, 3, 3);
-}
-
-static int tt3650_ci_read_cam_control(struct dvb_ca_en50221 *ca,
-				 int			slot,
-				 u8			address)
-{
-	u8 buf[2];
-	int ret;
-
-	if (0 != slot)
-		return -EINVAL;
-
-	buf[0] = address & 3;
-
-	ret = tt3650_ci_msg_locked(ca, TT3650_CMD_CI_RD_CTRL, buf, 1, 2);
-
-	ci_dbg("%s 0x%02x -> %d 0x%02x",
-		__func__, address, ret, buf[1]);
-
-	if (ret < 0)
-		return ret;
-
-	return buf[1];
-}
-
-static int tt3650_ci_write_cam_control(struct dvb_ca_en50221 *ca,
-				 int			slot,
-				 u8			address,
-				 u8			value)
-{
-	u8 buf[2];
-
-	ci_dbg("%s %d 0x%02x 0x%02x",
-		__func__, slot, address, value);
-
-	if (0 != slot)
-		return -EINVAL;
-
-	buf[0] = address;
-	buf[1] = value;
-
-	return tt3650_ci_msg_locked(ca, TT3650_CMD_CI_WR_CTRL, buf, 2, 2);
-}
-
-static int tt3650_ci_set_video_port(struct dvb_ca_en50221 *ca,
-				 int			slot,
-				 int			enable)
-{
-	u8 buf[1];
-	int ret;
-
-	ci_dbg("%s %d %d", __func__, slot, enable);
-
-	if (0 != slot)
-		return -EINVAL;
-
-	enable = !!enable;
-	buf[0] = enable;
-
-	ret = tt3650_ci_msg_locked(ca, TT3650_CMD_CI_SET_VIDEO_PORT, buf, 1, 1);
-	if (ret < 0)
-		return ret;
-
-	if (enable != buf[0]) {
-		err("CI not %sabled.", enable ? "en" : "dis");
-		return -EIO;
-	}
-
-	return 0;
-}
-
-static int tt3650_ci_slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
-{
-	return tt3650_ci_set_video_port(ca, slot, /* enable */ 0);
-}
-
-static int tt3650_ci_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
-{
-	return tt3650_ci_set_video_port(ca, slot, /* enable */ 1);
-}
-
-static int tt3650_ci_slot_reset(struct dvb_ca_en50221 *ca, int slot)
-{
-	struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
-	struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
-	u8 buf[1];
-	int ret;
-
-	ci_dbg("%s %d", __func__, slot);
-
-	if (0 != slot)
-		return -EINVAL;
-
-	buf[0] = 0;
-
-	mutex_lock(&state->ca_mutex);
-
-	ret = tt3650_ci_msg(d, TT3650_CMD_CI_RESET, buf, 1, 1);
-	if (0 != ret)
-		goto failed;
-
-	msleep(500);
-
-	buf[0] = 1;
-
-	ret = tt3650_ci_msg(d, TT3650_CMD_CI_RESET, buf, 1, 1);
-	if (0 != ret)
-		goto failed;
-
-	msleep(500);
-
-	buf[0] = 0; /* FTA */
-
-	ret = tt3650_ci_msg(d, TT3650_CMD_CI_SET_VIDEO_PORT, buf, 1, 1);
-
- failed:
-	mutex_unlock(&state->ca_mutex);
-
-	return ret;
-}
-
-static int tt3650_ci_poll_slot_status(struct dvb_ca_en50221 *ca,
-				 int			slot,
-				 int			open)
-{
-	u8 buf[1];
-	int ret;
-
-	if (0 != slot)
-		return -EINVAL;
-
-	ret = tt3650_ci_msg_locked(ca, TT3650_CMD_CI_TEST, buf, 0, 1);
-	if (0 != ret)
-		return ret;
-
-	if (1 == buf[0])
-		return DVB_CA_EN50221_POLL_CAM_PRESENT |
-			DVB_CA_EN50221_POLL_CAM_READY;
-
-	return 0;
-
-}
-
-static void tt3650_ci_uninit(struct dvb_usb_device *d)
-{
-	struct pctv452e_state *state;
-
-	ci_dbg("%s", __func__);
-
-	if (NULL == d)
-		return;
-
-	state = (struct pctv452e_state *)d->priv;
-	if (NULL == state)
-		return;
-
-	if (NULL == state->ca.data)
-		return;
-
-	/* Error ignored. */
-	tt3650_ci_set_video_port(&state->ca, /* slot */ 0, /* enable */ 0);
-
-	dvb_ca_en50221_release(&state->ca);
-
-	memset(&state->ca, 0, sizeof(state->ca));
-}
-
-static int tt3650_ci_init(struct dvb_usb_adapter *a)
-{
-	struct dvb_usb_device *d = a->dev;
-	struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
-	int ret;
-
-	ci_dbg("%s", __func__);
-
-	mutex_init(&state->ca_mutex);
-
-	state->ca.owner = THIS_MODULE;
-	state->ca.read_attribute_mem = tt3650_ci_read_attribute_mem;
-	state->ca.write_attribute_mem = tt3650_ci_write_attribute_mem;
-	state->ca.read_cam_control = tt3650_ci_read_cam_control;
-	state->ca.write_cam_control = tt3650_ci_write_cam_control;
-	state->ca.slot_reset = tt3650_ci_slot_reset;
-	state->ca.slot_shutdown = tt3650_ci_slot_shutdown;
-	state->ca.slot_ts_enable = tt3650_ci_slot_ts_enable;
-	state->ca.poll_slot_status = tt3650_ci_poll_slot_status;
-	state->ca.data = d;
-
-	ret = dvb_ca_en50221_init(&a->dvb_adap,
-				   &state->ca,
-				   /* flags */ 0,
-				   /* n_slots */ 1);
-	if (0 != ret) {
-		err("Cannot initialize CI: Error %d.", ret);
-		memset(&state->ca, 0, sizeof(state->ca));
-		return ret;
-	}
-
-	info("CI initialized.");
-
-	return 0;
-}
-
-#define CMD_BUFFER_SIZE 0x28
-static int pctv452e_i2c_msg(struct dvb_usb_device *d, u8 addr,
-				const u8 *snd_buf, u8 snd_len,
-				u8 *rcv_buf, u8 rcv_len)
-{
-	struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
-	u8 buf[64];
-	u8 id;
-	int ret;
-
-	id = state->c++;
-
-	ret = -EINVAL;
-	if (snd_len > 64 - 7 || rcv_len > 64 - 7)
-		goto failed;
-
-	buf[0] = SYNC_BYTE_OUT;
-	buf[1] = id;
-	buf[2] = PCTV_CMD_I2C;
-	buf[3] = snd_len + 3;
-	buf[4] = addr << 1;
-	buf[5] = snd_len;
-	buf[6] = rcv_len;
-
-	memcpy(buf + 7, snd_buf, snd_len);
-
-	ret = dvb_usb_generic_rw(d, buf, 7 + snd_len,
-				  buf, /* rcv_len */ 64,
-				  /* delay_ms */ 0);
-	if (ret < 0)
-		goto failed;
-
-	/* TT USB protocol error. */
-	ret = -EIO;
-	if (SYNC_BYTE_IN != buf[0] || id != buf[1])
-		goto failed;
-
-	/* I2C device didn't respond as expected. */
-	ret = -EREMOTEIO;
-	if (buf[5] < snd_len || buf[6] < rcv_len)
-		goto failed;
-
-	memcpy(rcv_buf, buf + 7, rcv_len);
-
-	return rcv_len;
-
-failed:
-	err("I2C error %d; %02X %02X  %02X %02X %02X -> "
-	     "%02X %02X  %02X %02X %02X.",
-	     ret, SYNC_BYTE_OUT, id, addr << 1, snd_len, rcv_len,
-	     buf[0], buf[1], buf[4], buf[5], buf[6]);
-
-	return ret;
-}
-
-static int pctv452e_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msg,
-				int num)
-{
-	struct dvb_usb_device *d = i2c_get_adapdata(adapter);
-	int i;
-
-	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
-		return -EAGAIN;
-
-	for (i = 0; i < num; i++) {
-		u8 addr, snd_len, rcv_len, *snd_buf, *rcv_buf;
-		int ret;
-
-		if (msg[i].flags & I2C_M_RD) {
-			addr = msg[i].addr;
-			snd_buf = NULL;
-			snd_len = 0;
-			rcv_buf = msg[i].buf;
-			rcv_len = msg[i].len;
-		} else {
-			addr = msg[i].addr;
-			snd_buf = msg[i].buf;
-			snd_len = msg[i].len;
-			rcv_buf = NULL;
-			rcv_len = 0;
-		}
-
-		ret = pctv452e_i2c_msg(d, addr, snd_buf, snd_len, rcv_buf,
-					rcv_len);
-		if (ret < rcv_len)
-			break;
-	}
-
-	mutex_unlock(&d->i2c_mutex);
-	return i;
-}
-
-static u32 pctv452e_i2c_func(struct i2c_adapter *adapter)
-{
-	return I2C_FUNC_I2C;
-}
-
-static int pctv452e_power_ctrl(struct dvb_usb_device *d, int i)
-{
-	struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
-	u8 b0[] = { 0xaa, 0, PCTV_CMD_RESET, 1, 0 };
-	u8 rx[PCTV_ANSWER_LEN];
-	int ret;
-
-	info("%s: %d\n", __func__, i);
-
-	if (!i)
-		return 0;
-
-	if (state->initialized)
-		return 0;
-
-	/* hmm where shoud this should go? */
-	ret = usb_set_interface(d->udev, 0, ISOC_INTERFACE_ALTERNATIVE);
-	if (ret != 0)
-		info("%s: Warning set interface returned: %d\n",
-			__func__, ret);
-
-	/* this is a one-time initialization, dont know where to put */
-	b0[1] = state->c++;
-	/* reset board */
-	ret = dvb_usb_generic_rw(d, b0, sizeof(b0), rx, PCTV_ANSWER_LEN, 0);
-	if (ret)
-		return ret;
-
-	b0[1] = state->c++;
-	b0[4] = 1;
-	/* reset board (again?) */
-	ret = dvb_usb_generic_rw(d, b0, sizeof(b0), rx, PCTV_ANSWER_LEN, 0);
-	if (ret)
-		return ret;
-
-	state->initialized = 1;
-
-	return 0;
-}
-
-static int pctv452e_rc_query(struct dvb_usb_device *d)
-{
-	struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
-	u8 b[CMD_BUFFER_SIZE];
-	u8 rx[PCTV_ANSWER_LEN];
-	int ret, i;
-	u8 id = state->c++;
-
-	/* prepare command header  */
-	b[0] = SYNC_BYTE_OUT;
-	b[1] = id;
-	b[2] = PCTV_CMD_IR;
-	b[3] = 0;
-
-	/* send ir request */
-	ret = dvb_usb_generic_rw(d, b, 4, rx, PCTV_ANSWER_LEN, 0);
-	if (ret != 0)
-		return ret;
-
-	if (debug > 3) {
-		info("%s: read: %2d: %02x %02x %02x: ", __func__,
-				ret, rx[0], rx[1], rx[2]);
-		for (i = 0; (i < rx[3]) && ((i+3) < PCTV_ANSWER_LEN); i++)
-			info(" %02x", rx[i+3]);
-
-		info("\n");
-	}
-
-	if ((rx[3] == 9) &&  (rx[12] & 0x01)) {
-		/* got a "press" event */
-		state->last_rc_key = (rx[7] << 8) | rx[6];
-		if (debug > 2)
-			info("%s: cmd=0x%02x sys=0x%02x\n",
-				__func__, rx[6], rx[7]);
-
-		rc_keydown(d->rc_dev, state->last_rc_key, 0);
-	} else if (state->last_rc_key) {
-		rc_keyup(d->rc_dev);
-		state->last_rc_key = 0;
-	}
-
-	return 0;
-}
-
-static int pctv452e_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
-{
-	const u8 mem_addr[] = { 0x1f, 0xcc };
-	u8 encoded_mac[20];
-	int ret;
-
-	ret = -EAGAIN;
-	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
-		goto failed;
-
-	ret = pctv452e_i2c_msg(d, I2C_ADDR_24C16,
-				mem_addr + 1, /* snd_len */ 1,
-				encoded_mac, /* rcv_len */ 20);
-	if (-EREMOTEIO == ret)
-		/* Caution! A 24C16 interprets 0xA2 0x1F 0xCC as a
-		   byte write if /WC is low. */
-		ret = pctv452e_i2c_msg(d, I2C_ADDR_24C64,
-					mem_addr, 2,
-					encoded_mac, 20);
-
-	mutex_unlock(&d->i2c_mutex);
-
-	if (20 != ret)
-		goto failed;
-
-	ret = ttpci_eeprom_decode_mac(mac, encoded_mac);
-	if (0 != ret)
-		goto failed;
-
-	return 0;
-
-failed:
-	memset(mac, 0, 6);
-
-	return ret;
-}
-
-static const struct stb0899_s1_reg pctv452e_init_dev[] = {
-	{ STB0899_DISCNTRL1,	0x26 },
-	{ STB0899_DISCNTRL2,	0x80 },
-	{ STB0899_DISRX_ST0,	0x04 },
-	{ STB0899_DISRX_ST1,	0x20 },
-	{ STB0899_DISPARITY,	0x00 },
-	{ STB0899_DISFIFO,	0x00 },
-	{ STB0899_DISF22,	0x99 },
-	{ STB0899_DISF22RX,	0x85 }, /* 0xa8 */
-	{ STB0899_ACRPRESC,	0x11 },
-	{ STB0899_ACRDIV1,	0x0a },
-	{ STB0899_ACRDIV2,	0x05 },
-	{ STB0899_DACR1	,	0x00 },
-	{ STB0899_DACR2	,	0x00 },
-	{ STB0899_OUTCFG,	0x00 },
-	{ STB0899_MODECFG,	0x00 }, /* Inversion */
-	{ STB0899_IRQMSK_3,	0xf3 },
-	{ STB0899_IRQMSK_2,	0xfc },
-	{ STB0899_IRQMSK_1,	0xff },
-	{ STB0899_IRQMSK_0,	0xff },
-	{ STB0899_I2CCFG,	0x88 },
-	{ STB0899_I2CRPT,	0x58 },
-	{ STB0899_GPIO00CFG,	0x82 },
-	{ STB0899_GPIO01CFG,	0x82 }, /* LED: 0x02 green, 0x82 orange */
-	{ STB0899_GPIO02CFG,	0x82 },
-	{ STB0899_GPIO03CFG,	0x82 },
-	{ STB0899_GPIO04CFG,	0x82 },
-	{ STB0899_GPIO05CFG,	0x82 },
-	{ STB0899_GPIO06CFG,	0x82 },
-	{ STB0899_GPIO07CFG,	0x82 },
-	{ STB0899_GPIO08CFG,	0x82 },
-	{ STB0899_GPIO09CFG,	0x82 },
-	{ STB0899_GPIO10CFG,	0x82 },
-	{ STB0899_GPIO11CFG,	0x82 },
-	{ STB0899_GPIO12CFG,	0x82 },
-	{ STB0899_GPIO13CFG,	0x82 },
-	{ STB0899_GPIO14CFG,	0x82 },
-	{ STB0899_GPIO15CFG,	0x82 },
-	{ STB0899_GPIO16CFG,	0x82 },
-	{ STB0899_GPIO17CFG,	0x82 },
-	{ STB0899_GPIO18CFG,	0x82 },
-	{ STB0899_GPIO19CFG,	0x82 },
-	{ STB0899_GPIO20CFG,	0x82 },
-	{ STB0899_SDATCFG,	0xb8 },
-	{ STB0899_SCLTCFG,	0xba },
-	{ STB0899_AGCRFCFG,	0x1c }, /* 0x11 DVB-S; 0x1c DVB-S2 (1c, rjkm) */
-	{ STB0899_GPIO22,	0x82 },
-	{ STB0899_GPIO21,	0x91 },
-	{ STB0899_DIRCLKCFG,	0x82 },
-	{ STB0899_CLKOUT27CFG,	0x7e },
-	{ STB0899_STDBYCFG,	0x82 },
-	{ STB0899_CS0CFG,	0x82 },
-	{ STB0899_CS1CFG,	0x82 },
-	{ STB0899_DISEQCOCFG,	0x20 },
-	{ STB0899_NCOARSE,	0x15 }, /* 0x15 27Mhz, F/3 198MHz, F/6 108MHz */
-	{ STB0899_SYNTCTRL,	0x00 }, /* 0x00 CLKI, 0x02 XTALI */
-	{ STB0899_FILTCTRL,	0x00 },
-	{ STB0899_SYSCTRL,	0x00 },
-	{ STB0899_STOPCLK1,	0x20 }, /* orig: 0x00 budget-ci: 0x20 */
-	{ STB0899_STOPCLK2,	0x00 },
-	{ STB0899_INTBUFCTRL,	0x0a },
-	{ STB0899_AGC2I1,	0x00 },
-	{ STB0899_AGC2I2,	0x00 },
-	{ STB0899_AGCIQIN,	0x00 },
-	{ STB0899_TSTRES,	0x40 }, /* rjkm */
-	{ 0xffff,		0xff },
-};
-
-static const struct stb0899_s1_reg pctv452e_init_s1_demod[] = {
-	{ STB0899_DEMOD,	0x00 },
-	{ STB0899_RCOMPC,	0xc9 },
-	{ STB0899_AGC1CN,	0x01 },
-	{ STB0899_AGC1REF,	0x10 },
-	{ STB0899_RTC,		0x23 },
-	{ STB0899_TMGCFG,	0x4e },
-	{ STB0899_AGC2REF,	0x34 },
-	{ STB0899_TLSR,		0x84 },
-	{ STB0899_CFD,		0xf7 },
-	{ STB0899_ACLC,		0x87 },
-	{ STB0899_BCLC,		0x94 },
-	{ STB0899_EQON,		0x41 },
-	{ STB0899_LDT,		0xf1 },
-	{ STB0899_LDT2,		0xe3 },
-	{ STB0899_EQUALREF,	0xb4 },
-	{ STB0899_TMGRAMP,	0x10 },
-	{ STB0899_TMGTHD,	0x30 },
-	{ STB0899_IDCCOMP,	0xfd },
-	{ STB0899_QDCCOMP,	0xff },
-	{ STB0899_POWERI,	0x0c },
-	{ STB0899_POWERQ,	0x0f },
-	{ STB0899_RCOMP,	0x6c },
-	{ STB0899_AGCIQIN,	0x80 },
-	{ STB0899_AGC2I1,	0x06 },
-	{ STB0899_AGC2I2,	0x00 },
-	{ STB0899_TLIR,		0x30 },
-	{ STB0899_RTF,		0x7f },
-	{ STB0899_DSTATUS,	0x00 },
-	{ STB0899_LDI,		0xbc },
-	{ STB0899_CFRM,		0xea },
-	{ STB0899_CFRL,		0x31 },
-	{ STB0899_NIRM,		0x2b },
-	{ STB0899_NIRL,		0x80 },
-	{ STB0899_ISYMB,	0x1d },
-	{ STB0899_QSYMB,	0xa6 },
-	{ STB0899_SFRH,		0x2f },
-	{ STB0899_SFRM,		0x68 },
-	{ STB0899_SFRL,		0x40 },
-	{ STB0899_SFRUPH,	0x2f },
-	{ STB0899_SFRUPM,	0x68 },
-	{ STB0899_SFRUPL,	0x40 },
-	{ STB0899_EQUAI1,	0x02 },
-	{ STB0899_EQUAQ1,	0xff },
-	{ STB0899_EQUAI2,	0x04 },
-	{ STB0899_EQUAQ2,	0x05 },
-	{ STB0899_EQUAI3,	0x02 },
-	{ STB0899_EQUAQ3,	0xfd },
-	{ STB0899_EQUAI4,	0x03 },
-	{ STB0899_EQUAQ4,	0x07 },
-	{ STB0899_EQUAI5,	0x08 },
-	{ STB0899_EQUAQ5,	0xf5 },
-	{ STB0899_DSTATUS2,	0x00 },
-	{ STB0899_VSTATUS,	0x00 },
-	{ STB0899_VERROR,	0x86 },
-	{ STB0899_IQSWAP,	0x2a },
-	{ STB0899_ECNT1M,	0x00 },
-	{ STB0899_ECNT1L,	0x00 },
-	{ STB0899_ECNT2M,	0x00 },
-	{ STB0899_ECNT2L,	0x00 },
-	{ STB0899_ECNT3M,	0x0a },
-	{ STB0899_ECNT3L,	0xad },
-	{ STB0899_FECAUTO1,	0x06 },
-	{ STB0899_FECM,		0x01 },
-	{ STB0899_VTH12,	0xb0 },
-	{ STB0899_VTH23,	0x7a },
-	{ STB0899_VTH34,	0x58 },
-	{ STB0899_VTH56,	0x38 },
-	{ STB0899_VTH67,	0x34 },
-	{ STB0899_VTH78,	0x24 },
-	{ STB0899_PRVIT,	0xff },
-	{ STB0899_VITSYNC,	0x19 },
-	{ STB0899_RSULC,	0xb1 }, /* DVB = 0xb1, DSS = 0xa1 */
-	{ STB0899_TSULC,	0x42 },
-	{ STB0899_RSLLC,	0x41 },
-	{ STB0899_TSLPL,	0x12 },
-	{ STB0899_TSCFGH,	0x0c },
-	{ STB0899_TSCFGM,	0x00 },
-	{ STB0899_TSCFGL,	0x00 },
-	{ STB0899_TSOUT,	0x69 }, /* 0x0d for CAM */
-	{ STB0899_RSSYNCDEL,	0x00 },
-	{ STB0899_TSINHDELH,	0x02 },
-	{ STB0899_TSINHDELM,	0x00 },
-	{ STB0899_TSINHDELL,	0x00 },
-	{ STB0899_TSLLSTKM,	0x1b },
-	{ STB0899_TSLLSTKL,	0xb3 },
-	{ STB0899_TSULSTKM,	0x00 },
-	{ STB0899_TSULSTKL,	0x00 },
-	{ STB0899_PCKLENUL,	0xbc },
-	{ STB0899_PCKLENLL,	0xcc },
-	{ STB0899_RSPCKLEN,	0xbd },
-	{ STB0899_TSSTATUS,	0x90 },
-	{ STB0899_ERRCTRL1,	0xb6 },
-	{ STB0899_ERRCTRL2,	0x95 },
-	{ STB0899_ERRCTRL3,	0x8d },
-	{ STB0899_DMONMSK1,	0x27 },
-	{ STB0899_DMONMSK0,	0x03 },
-	{ STB0899_DEMAPVIT,	0x5c },
-	{ STB0899_PLPARM,	0x19 },
-	{ STB0899_PDELCTRL,	0x48 },
-	{ STB0899_PDELCTRL2,	0x00 },
-	{ STB0899_BBHCTRL1,	0x00 },
-	{ STB0899_BBHCTRL2,	0x00 },
-	{ STB0899_HYSTTHRESH,	0x77 },
-	{ STB0899_MATCSTM,	0x00 },
-	{ STB0899_MATCSTL,	0x00 },
-	{ STB0899_UPLCSTM,	0x00 },
-	{ STB0899_UPLCSTL,	0x00 },
-	{ STB0899_DFLCSTM,	0x00 },
-	{ STB0899_DFLCSTL,	0x00 },
-	{ STB0899_SYNCCST,	0x00 },
-	{ STB0899_SYNCDCSTM,	0x00 },
-	{ STB0899_SYNCDCSTL,	0x00 },
-	{ STB0899_ISI_ENTRY,	0x00 },
-	{ STB0899_ISI_BIT_EN,	0x00 },
-	{ STB0899_MATSTRM,	0xf0 },
-	{ STB0899_MATSTRL,	0x02 },
-	{ STB0899_UPLSTRM,	0x45 },
-	{ STB0899_UPLSTRL,	0x60 },
-	{ STB0899_DFLSTRM,	0xe3 },
-	{ STB0899_DFLSTRL,	0x00 },
-	{ STB0899_SYNCSTR,	0x47 },
-	{ STB0899_SYNCDSTRM,	0x05 },
-	{ STB0899_SYNCDSTRL,	0x18 },
-	{ STB0899_CFGPDELSTATUS1, 0x19 },
-	{ STB0899_CFGPDELSTATUS2, 0x2b },
-	{ STB0899_BBFERRORM,	0x00 },
-	{ STB0899_BBFERRORL,	0x01 },
-	{ STB0899_UPKTERRORM,	0x00 },
-	{ STB0899_UPKTERRORL,	0x00 },
-	{ 0xffff,		0xff },
-};
-
-static struct stb0899_config stb0899_config = {
-	.init_dev	= pctv452e_init_dev,
-	.init_s2_demod	= stb0899_s2_init_2,
-	.init_s1_demod	= pctv452e_init_s1_demod,
-	.init_s2_fec	= stb0899_s2_init_4,
-	.init_tst	= stb0899_s1_init_5,
-
-	.demod_address   = I2C_ADDR_STB0899, /* I2C Address */
-	.block_sync_mode = STB0899_SYNC_FORCED, /* ? */
-
-	.xtal_freq       = 27000000,	 /* Assume Hz ? */
-	.inversion       = IQ_SWAP_ON,       /* ? */
-
-	.lo_clk	  = 76500000,
-	.hi_clk	  = 99000000,
-
-	.ts_output_mode  = 0,	/* Use parallel mode */
-	.clock_polarity  = 0,
-	.data_clk_parity = 0,
-	.fec_mode	= 0,
-
-	.esno_ave	    = STB0899_DVBS2_ESNO_AVE,
-	.esno_quant	  = STB0899_DVBS2_ESNO_QUANT,
-	.avframes_coarse     = STB0899_DVBS2_AVFRAMES_COARSE,
-	.avframes_fine       = STB0899_DVBS2_AVFRAMES_FINE,
-	.miss_threshold      = STB0899_DVBS2_MISS_THRESHOLD,
-	.uwp_threshold_acq   = STB0899_DVBS2_UWP_THRESHOLD_ACQ,
-	.uwp_threshold_track = STB0899_DVBS2_UWP_THRESHOLD_TRACK,
-	.uwp_threshold_sof   = STB0899_DVBS2_UWP_THRESHOLD_SOF,
-	.sof_search_timeout  = STB0899_DVBS2_SOF_SEARCH_TIMEOUT,
-
-	.btr_nco_bits	  = STB0899_DVBS2_BTR_NCO_BITS,
-	.btr_gain_shift_offset = STB0899_DVBS2_BTR_GAIN_SHIFT_OFFSET,
-	.crl_nco_bits	  = STB0899_DVBS2_CRL_NCO_BITS,
-	.ldpc_max_iter	 = STB0899_DVBS2_LDPC_MAX_ITER,
-
-	.tuner_get_frequency	= stb6100_get_frequency,
-	.tuner_set_frequency	= stb6100_set_frequency,
-	.tuner_set_bandwidth	= stb6100_set_bandwidth,
-	.tuner_get_bandwidth	= stb6100_get_bandwidth,
-	.tuner_set_rfsiggain	= NULL,
-
-	/* helper for switching LED green/orange */
-	.postproc = pctv45e_postproc
-};
-
-static struct stb6100_config stb6100_config = {
-	.tuner_address = I2C_ADDR_STB6100,
-	.refclock      = 27000000
-};
-
-
-static struct i2c_algorithm pctv452e_i2c_algo = {
-	.master_xfer   = pctv452e_i2c_xfer,
-	.functionality = pctv452e_i2c_func
-};
-
-static int pctv452e_frontend_attach(struct dvb_usb_adapter *a)
-{
-	struct usb_device_id *id;
-
-	a->fe_adap[0].fe = dvb_attach(stb0899_attach, &stb0899_config,
-						&a->dev->i2c_adap);
-	if (!a->fe_adap[0].fe)
-		return -ENODEV;
-	if ((dvb_attach(lnbp22_attach, a->fe_adap[0].fe,
-					&a->dev->i2c_adap)) == 0)
-		err("Cannot attach lnbp22\n");
-
-	id = a->dev->desc->warm_ids[0];
-	if (USB_VID_TECHNOTREND == id->idVendor
-	    && USB_PID_TECHNOTREND_CONNECT_S2_3650_CI == id->idProduct)
-		/* Error ignored. */
-		tt3650_ci_init(a);
-
-	return 0;
-}
-
-static int pctv452e_tuner_attach(struct dvb_usb_adapter *a)
-{
-	if (!a->fe_adap[0].fe)
-		return -ENODEV;
-	if (dvb_attach(stb6100_attach, a->fe_adap[0].fe, &stb6100_config,
-					&a->dev->i2c_adap) == 0) {
-		err("%s failed\n", __func__);
-		return -ENODEV;
-	}
-
-	return 0;
-}
-
-static struct usb_device_id pctv452e_usb_table[] = {
-	{USB_DEVICE(USB_VID_PINNACLE, USB_PID_PCTV_452E)},
-	{USB_DEVICE(USB_VID_TECHNOTREND, USB_PID_TECHNOTREND_CONNECT_S2_3600)},
-	{USB_DEVICE(USB_VID_TECHNOTREND,
-				USB_PID_TECHNOTREND_CONNECT_S2_3650_CI)},
-	{}
-};
-MODULE_DEVICE_TABLE(usb, pctv452e_usb_table);
-
-static struct dvb_usb_device_properties pctv452e_properties = {
-	.caps = DVB_USB_IS_AN_I2C_ADAPTER, /* more ? */
-	.usb_ctrl = DEVICE_SPECIFIC,
-
-	.size_of_priv     = sizeof(struct pctv452e_state),
-
-	.power_ctrl       = pctv452e_power_ctrl,
-
-	.rc.core = {
-		.rc_codes	= RC_MAP_DIB0700_RC5_TABLE,
-		.allowed_protos	= RC_TYPE_UNKNOWN,
-		.rc_query	= pctv452e_rc_query,
-		.rc_interval	= 100,
-	},
-
-	.num_adapters     = 1,
-	.adapter = {{
-		.num_frontends = 1,
-		.fe = {{
-			.frontend_attach  = pctv452e_frontend_attach,
-			.tuner_attach     = pctv452e_tuner_attach,
-
-			/* parameter for the MPEG2-data transfer */
-			.stream = {
-				.type     = USB_ISOC,
-				.count    = 4,
-				.endpoint = 0x02,
-				.u = {
-					.isoc = {
-						.framesperurb = 4,
-						.framesize    = 940,
-						.interval     = 1
-					}
-				}
-			},
-		} },
-	} },
-
-	.i2c_algo = &pctv452e_i2c_algo,
-
-	.generic_bulk_ctrl_endpoint = 1, /* allow generice rw function */
-
-	.num_device_descs = 1,
-	.devices = {
-		{ .name = "PCTV HDTV USB",
-		  .cold_ids = { NULL, NULL }, /* this is a warm only device */
-		  .warm_ids = { &pctv452e_usb_table[0], NULL }
-		},
-		{ 0 },
-	}
-};
-
-static struct dvb_usb_device_properties tt_connect_s2_3600_properties = {
-	.caps = DVB_USB_IS_AN_I2C_ADAPTER, /* more ? */
-	.usb_ctrl = DEVICE_SPECIFIC,
-
-	.size_of_priv		= sizeof(struct pctv452e_state),
-
-	.power_ctrl		= pctv452e_power_ctrl,
-	.read_mac_address	= pctv452e_read_mac_address,
-
-	.rc.core = {
-		.rc_codes	= RC_MAP_TT_1500,
-		.allowed_protos	= RC_TYPE_UNKNOWN,
-		.rc_query	= pctv452e_rc_query,
-		.rc_interval	= 100,
-	},
-
-	.num_adapters		= 1,
-	.adapter = {{
-		.num_frontends = 1,
-		.fe = {{
-			.frontend_attach = pctv452e_frontend_attach,
-			.tuner_attach = pctv452e_tuner_attach,
-
-			/* parameter for the MPEG2-data transfer */
-			.stream = {
-				.type = USB_ISOC,
-				.count = 7,
-				.endpoint = 0x02,
-				.u = {
-					.isoc = {
-						.framesperurb = 4,
-						.framesize = 940,
-						.interval = 1
-					}
-				}
-			},
-
-		} },
-	} },
-
-	.i2c_algo = &pctv452e_i2c_algo,
-
-	.generic_bulk_ctrl_endpoint = 1, /* allow generic rw function*/
-
-	.num_device_descs = 2,
-	.devices = {
-		{ .name = "Technotrend TT Connect S2-3600",
-		  .cold_ids = { NULL, NULL }, /* this is a warm only device */
-		  .warm_ids = { &pctv452e_usb_table[1], NULL }
-		},
-		{ .name = "Technotrend TT Connect S2-3650-CI",
-		  .cold_ids = { NULL, NULL },
-		  .warm_ids = { &pctv452e_usb_table[2], NULL }
-		},
-		{ 0 },
-	}
-};
-
-static void pctv452e_usb_disconnect(struct usb_interface *intf)
-{
-	struct dvb_usb_device *d = usb_get_intfdata(intf);
-
-	tt3650_ci_uninit(d);
-	dvb_usb_device_exit(intf);
-}
-
-static int pctv452e_usb_probe(struct usb_interface *intf,
-				const struct usb_device_id *id)
-{
-	if (0 == dvb_usb_device_init(intf, &pctv452e_properties,
-					THIS_MODULE, NULL, adapter_nr) ||
-	    0 == dvb_usb_device_init(intf, &tt_connect_s2_3600_properties,
-					THIS_MODULE, NULL, adapter_nr))
-		return 0;
-
-	return -ENODEV;
-}
-
-static struct usb_driver pctv452e_usb_driver = {
-	.name       = "pctv452e",
-	.probe      = pctv452e_usb_probe,
-	.disconnect = pctv452e_usb_disconnect,
-	.id_table   = pctv452e_usb_table,
-};
-
-module_usb_driver(pctv452e_usb_driver);
-
-MODULE_AUTHOR("Dominik Kuhlen <dkuhlen@gmx.net>");
-MODULE_AUTHOR("Andre Weidemann <Andre.Weidemann@web.de>");
-MODULE_AUTHOR("Michael H. Schimek <mschimek@gmx.at>");
-MODULE_DESCRIPTION("Pinnacle PCTV HDTV USB DVB / TT connect S2-3600 Driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/rtl28xxu.c b/drivers/media/dvb/dvb-usb/rtl28xxu.c
deleted file mode 100644
index 6bd0bd7..0000000
--- a/drivers/media/dvb/dvb-usb/rtl28xxu.c
+++ /dev/null
@@ -1,1428 +0,0 @@
-/*
- * Realtek RTL28xxU DVB USB driver
- *
- * Copyright (C) 2009 Antti Palosaari <crope@iki.fi>
- * Copyright (C) 2011 Antti Palosaari <crope@iki.fi>
- * Copyright (C) 2012 Thomas Mair <thomas.mair86@googlemail.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 "rtl28xxu.h"
-
-#include "rtl2830.h"
-#include "rtl2832.h"
-
-#include "qt1010.h"
-#include "mt2060.h"
-#include "mxl5005s.h"
-#include "fc0012.h"
-#include "fc0013.h"
-
-/* debug */
-static int dvb_usb_rtl28xxu_debug;
-module_param_named(debug, dvb_usb_rtl28xxu_debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS);
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-static int rtl28xxu_ctrl_msg(struct dvb_usb_device *d, struct rtl28xxu_req *req)
-{
-	int ret;
-	unsigned int pipe;
-	u8 requesttype;
-	u8 *buf;
-
-	buf = kmalloc(req->size, GFP_KERNEL);
-	if (!buf) {
-		ret = -ENOMEM;
-		goto err;
-	}
-
-	if (req->index & CMD_WR_FLAG) {
-		/* write */
-		memcpy(buf, req->data, req->size);
-		requesttype = (USB_TYPE_VENDOR | USB_DIR_OUT);
-		pipe = usb_sndctrlpipe(d->udev, 0);
-	} else {
-		/* read */
-		requesttype = (USB_TYPE_VENDOR | USB_DIR_IN);
-		pipe = usb_rcvctrlpipe(d->udev, 0);
-	}
-
-	ret = usb_control_msg(d->udev, pipe, 0, requesttype, req->value,
-			req->index, buf, req->size, 1000);
-	if (ret > 0)
-		ret = 0;
-
-	deb_dump(0, requesttype, req->value, req->index, buf, req->size,
-			deb_xfer);
-
-	/* read request, copy returned data to return buf */
-	if (!ret && requesttype == (USB_TYPE_VENDOR | USB_DIR_IN))
-		memcpy(req->data, buf, req->size);
-
-	kfree(buf);
-
-	if (ret)
-		goto err;
-
-	return ret;
-err:
-	deb_info("%s: failed=%d\n", __func__, ret);
-	return ret;
-}
-
-static int rtl28xx_wr_regs(struct dvb_usb_device *d, u16 reg, u8 *val, int len)
-{
-	struct rtl28xxu_req req;
-
-	if (reg < 0x3000)
-		req.index = CMD_USB_WR;
-	else if (reg < 0x4000)
-		req.index = CMD_SYS_WR;
-	else
-		req.index = CMD_IR_WR;
-
-	req.value = reg;
-	req.size = len;
-	req.data = val;
-
-	return rtl28xxu_ctrl_msg(d, &req);
-}
-
-static int rtl2831_rd_regs(struct dvb_usb_device *d, u16 reg, u8 *val, int len)
-{
-	struct rtl28xxu_req req;
-
-	if (reg < 0x3000)
-		req.index = CMD_USB_RD;
-	else if (reg < 0x4000)
-		req.index = CMD_SYS_RD;
-	else
-		req.index = CMD_IR_RD;
-
-	req.value = reg;
-	req.size = len;
-	req.data = val;
-
-	return rtl28xxu_ctrl_msg(d, &req);
-}
-
-static int rtl28xx_wr_reg(struct dvb_usb_device *d, u16 reg, u8 val)
-{
-	return rtl28xx_wr_regs(d, reg, &val, 1);
-}
-
-static int rtl28xx_rd_reg(struct dvb_usb_device *d, u16 reg, u8 *val)
-{
-	return rtl2831_rd_regs(d, reg, val, 1);
-}
-
-/* I2C */
-static int rtl28xxu_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
-	int num)
-{
-	int ret;
-	struct dvb_usb_device *d = i2c_get_adapdata(adap);
-	struct rtl28xxu_priv *priv = d->priv;
-	struct rtl28xxu_req req;
-
-	/*
-	 * It is not known which are real I2C bus xfer limits, but testing
-	 * with RTL2831U + MT2060 gives max RD 24 and max WR 22 bytes.
-	 * TODO: find out RTL2832U lens
-	 */
-
-	/*
-	 * I2C adapter logic looks rather complicated due to fact it handles
-	 * three different access methods. Those methods are;
-	 * 1) integrated demod access
-	 * 2) old I2C access
-	 * 3) new I2C access
-	 *
-	 * Used method is selected in order 1, 2, 3. Method 3 can handle all
-	 * requests but there is two reasons why not use it always;
-	 * 1) It is most expensive, usually two USB messages are needed
-	 * 2) At least RTL2831U does not support it
-	 *
-	 * Method 3 is needed in case of I2C write+read (typical register read)
-	 * where write is more than one byte.
-	 */
-
-	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
-		return -EAGAIN;
-
-	if (num == 2 && !(msg[0].flags & I2C_M_RD) &&
-		(msg[1].flags & I2C_M_RD)) {
-		if (msg[0].len > 24 || msg[1].len > 24) {
-			/* TODO: check msg[0].len max */
-			ret = -EOPNOTSUPP;
-			goto err_mutex_unlock;
-		} else if (msg[0].addr == 0x10) {
-			/* method 1 - integrated demod */
-			req.value = (msg[0].buf[0] << 8) | (msg[0].addr << 1);
-			req.index = CMD_DEMOD_RD | priv->page;
-			req.size = msg[1].len;
-			req.data = &msg[1].buf[0];
-			ret = rtl28xxu_ctrl_msg(d, &req);
-		} else if (msg[0].len < 2) {
-			/* method 2 - old I2C */
-			req.value = (msg[0].buf[0] << 8) | (msg[0].addr << 1);
-			req.index = CMD_I2C_RD;
-			req.size = msg[1].len;
-			req.data = &msg[1].buf[0];
-			ret = rtl28xxu_ctrl_msg(d, &req);
-		} else {
-			/* method 3 - new I2C */
-			req.value = (msg[0].addr << 1);
-			req.index = CMD_I2C_DA_WR;
-			req.size = msg[0].len;
-			req.data = msg[0].buf;
-			ret = rtl28xxu_ctrl_msg(d, &req);
-			if (ret)
-				goto err_mutex_unlock;
-
-			req.value = (msg[0].addr << 1);
-			req.index = CMD_I2C_DA_RD;
-			req.size = msg[1].len;
-			req.data = msg[1].buf;
-			ret = rtl28xxu_ctrl_msg(d, &req);
-		}
-	} else if (num == 1 && !(msg[0].flags & I2C_M_RD)) {
-		if (msg[0].len > 22) {
-			/* TODO: check msg[0].len max */
-			ret = -EOPNOTSUPP;
-			goto err_mutex_unlock;
-		} else if (msg[0].addr == 0x10) {
-			/* method 1 - integrated demod */
-			if (msg[0].buf[0] == 0x00) {
-				/* save demod page for later demod access */
-				priv->page = msg[0].buf[1];
-				ret = 0;
-			} else {
-				req.value = (msg[0].buf[0] << 8) |
-					(msg[0].addr << 1);
-				req.index = CMD_DEMOD_WR | priv->page;
-				req.size = msg[0].len-1;
-				req.data = &msg[0].buf[1];
-				ret = rtl28xxu_ctrl_msg(d, &req);
-			}
-		} else if (msg[0].len < 23) {
-			/* method 2 - old I2C */
-			req.value = (msg[0].buf[0] << 8) | (msg[0].addr << 1);
-			req.index = CMD_I2C_WR;
-			req.size = msg[0].len-1;
-			req.data = &msg[0].buf[1];
-			ret = rtl28xxu_ctrl_msg(d, &req);
-		} else {
-			/* method 3 - new I2C */
-			req.value = (msg[0].addr << 1);
-			req.index = CMD_I2C_DA_WR;
-			req.size = msg[0].len;
-			req.data = msg[0].buf;
-			ret = rtl28xxu_ctrl_msg(d, &req);
-		}
-	} else {
-		ret = -EINVAL;
-	}
-
-err_mutex_unlock:
-	mutex_unlock(&d->i2c_mutex);
-
-	return ret ? ret : num;
-}
-
-static u32 rtl28xxu_i2c_func(struct i2c_adapter *adapter)
-{
-	return I2C_FUNC_I2C;
-}
-
-static struct i2c_algorithm rtl28xxu_i2c_algo = {
-	.master_xfer   = rtl28xxu_i2c_xfer,
-	.functionality = rtl28xxu_i2c_func,
-};
-
-static struct rtl2830_config rtl28xxu_rtl2830_mt2060_config = {
-	.i2c_addr = 0x10, /* 0x20 */
-	.xtal = 28800000,
-	.ts_mode = 0,
-	.spec_inv = 1,
-	.if_dvbt = 36150000,
-	.vtop = 0x20,
-	.krf = 0x04,
-	.agc_targ_val = 0x2d,
-
-};
-
-static struct rtl2830_config rtl28xxu_rtl2830_qt1010_config = {
-	.i2c_addr = 0x10, /* 0x20 */
-	.xtal = 28800000,
-	.ts_mode = 0,
-	.spec_inv = 1,
-	.if_dvbt = 36125000,
-	.vtop = 0x20,
-	.krf = 0x04,
-	.agc_targ_val = 0x2d,
-};
-
-static struct rtl2830_config rtl28xxu_rtl2830_mxl5005s_config = {
-	.i2c_addr = 0x10, /* 0x20 */
-	.xtal = 28800000,
-	.ts_mode = 0,
-	.spec_inv = 0,
-	.if_dvbt = 4570000,
-	.vtop = 0x3f,
-	.krf = 0x04,
-	.agc_targ_val = 0x3e,
-};
-
-static int rtl2831u_frontend_attach(struct dvb_usb_adapter *adap)
-{
-	int ret;
-	struct rtl28xxu_priv *priv = adap->dev->priv;
-	u8 buf[1];
-	struct rtl2830_config *rtl2830_config;
-	/* open RTL2831U/RTL2830 I2C gate */
-	struct rtl28xxu_req req_gate = { 0x0120, 0x0011, 0x0001, "\x08" };
-	/* for MT2060 tuner probe */
-	struct rtl28xxu_req req_mt2060 = { 0x00c0, CMD_I2C_RD, 1, buf };
-	/* for QT1010 tuner probe */
-	struct rtl28xxu_req req_qt1010 = { 0x0fc4, CMD_I2C_RD, 1, buf };
-
-	deb_info("%s:\n", __func__);
-
-	/*
-	 * RTL2831U GPIOs
-	 * =========================================================
-	 * GPIO0 | tuner#0 | 0 off | 1 on  | MXL5005S (?)
-	 * GPIO2 | LED     | 0 off | 1 on  |
-	 * GPIO4 | tuner#1 | 0 on  | 1 off | MT2060
-	 */
-
-	/* GPIO direction */
-	ret = rtl28xx_wr_reg(adap->dev, SYS_GPIO_DIR, 0x0a);
-	if (ret)
-		goto err;
-
-	/* enable as output GPIO0, GPIO2, GPIO4 */
-	ret = rtl28xx_wr_reg(adap->dev, SYS_GPIO_OUT_EN, 0x15);
-	if (ret)
-		goto err;
-
-	/*
-	 * Probe used tuner. We need to know used tuner before demod attach
-	 * since there is some demod params needed to set according to tuner.
-	 */
-
-	/* demod needs some time to wake up */
-	msleep(20);
-
-	/* open demod I2C gate */
-	ret = rtl28xxu_ctrl_msg(adap->dev, &req_gate);
-	if (ret)
-		goto err;
-
-	/* check QT1010 ID(?) register; reg=0f val=2c */
-	ret = rtl28xxu_ctrl_msg(adap->dev, &req_qt1010);
-	if (ret == 0 && buf[0] == 0x2c) {
-		priv->tuner = TUNER_RTL2830_QT1010;
-		rtl2830_config = &rtl28xxu_rtl2830_qt1010_config;
-		deb_info("%s: QT1010\n", __func__);
-		goto found;
-	} else {
-		deb_info("%s: QT1010 probe failed=%d - %02x\n",
-			__func__, ret, buf[0]);
-	}
-
-	/* open demod I2C gate */
-	ret = rtl28xxu_ctrl_msg(adap->dev, &req_gate);
-	if (ret)
-		goto err;
-
-	/* check MT2060 ID register; reg=00 val=63 */
-	ret = rtl28xxu_ctrl_msg(adap->dev, &req_mt2060);
-	if (ret == 0 && buf[0] == 0x63) {
-		priv->tuner = TUNER_RTL2830_MT2060;
-		rtl2830_config = &rtl28xxu_rtl2830_mt2060_config;
-		deb_info("%s: MT2060\n", __func__);
-		goto found;
-	} else {
-		deb_info("%s: MT2060 probe failed=%d - %02x\n",
-			__func__, ret, buf[0]);
-	}
-
-	/* assume MXL5005S */
-	ret = 0;
-	priv->tuner = TUNER_RTL2830_MXL5005S;
-	rtl2830_config = &rtl28xxu_rtl2830_mxl5005s_config;
-	deb_info("%s: MXL5005S\n", __func__);
-	goto found;
-
-found:
-	/* attach demodulator */
-	adap->fe_adap[0].fe = dvb_attach(rtl2830_attach, rtl2830_config,
-		&adap->dev->i2c_adap);
-	if (adap->fe_adap[0].fe == NULL) {
-		ret = -ENODEV;
-		goto err;
-	}
-
-	return ret;
-err:
-	deb_info("%s: failed=%d\n", __func__, ret);
-	return ret;
-}
-
-static struct rtl2832_config rtl28xxu_rtl2832_fc0012_config = {
-	.i2c_addr = 0x10, /* 0x20 */
-	.xtal = 28800000,
-	.if_dvbt = 0,
-	.tuner = TUNER_RTL2832_FC0012
-};
-
-static struct rtl2832_config rtl28xxu_rtl2832_fc0013_config = {
-	.i2c_addr = 0x10, /* 0x20 */
-	.xtal = 28800000,
-	.if_dvbt = 0,
-	.tuner = TUNER_RTL2832_FC0013
-};
-
-static int rtl2832u_fc0012_tuner_callback(struct dvb_usb_device *d,
-		int cmd, int arg)
-{
-	int ret;
-	u8 val;
-
-	deb_info("%s cmd=%d arg=%d\n", __func__, cmd, arg);
-	switch (cmd) {
-	case FC_FE_CALLBACK_VHF_ENABLE:
-		/* set output values */
-		ret = rtl28xx_rd_reg(d, SYS_GPIO_OUT_VAL, &val);
-		if (ret)
-			goto err;
-
-		if (arg)
-			val &= 0xbf; /* set GPIO6 low */
-		else
-			val |= 0x40; /* set GPIO6 high */
-
-
-		ret = rtl28xx_wr_reg(d, SYS_GPIO_OUT_VAL, val);
-		if (ret)
-			goto err;
-		break;
-	default:
-		ret = -EINVAL;
-		goto err;
-	}
-	return 0;
-
-err:
-	err("%s: failed=%d\n", __func__, ret);
-
-	return ret;
-}
-
-
-static int rtl2832u_fc0013_tuner_callback(struct dvb_usb_device *d,
-		int cmd, int arg)
-{
-	/* TODO implement*/
-	return 0;
-}
-
-static int rtl2832u_tuner_callback(struct dvb_usb_device *d, int cmd, int arg)
-{
-	struct rtl28xxu_priv *priv = d->priv;
-
-	switch (priv->tuner) {
-	case TUNER_RTL2832_FC0012:
-		return rtl2832u_fc0012_tuner_callback(d, cmd, arg);
-
-	case TUNER_RTL2832_FC0013:
-		return rtl2832u_fc0013_tuner_callback(d, cmd, arg);
-	default:
-		break;
-	}
-
-	return -ENODEV;
-}
-
-static int rtl2832u_frontend_callback(void *adapter_priv, int component,
-				    int cmd, int arg)
-{
-	struct i2c_adapter *adap = adapter_priv;
-	struct dvb_usb_device *d = i2c_get_adapdata(adap);
-
-	switch (component) {
-	case DVB_FRONTEND_COMPONENT_TUNER:
-		return rtl2832u_tuner_callback(d, cmd, arg);
-	default:
-		break;
-	}
-
-	return -EINVAL;
-}
-
-
-
-
-static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap)
-{
-	int ret;
-	struct rtl28xxu_priv *priv = adap->dev->priv;
-	struct rtl2832_config *rtl2832_config;
-
-	u8 buf[2], val;
-	/* open RTL2832U/RTL2832 I2C gate */
-	struct rtl28xxu_req req_gate_open = {0x0120, 0x0011, 0x0001, "\x18"};
-	/* close RTL2832U/RTL2832 I2C gate */
-	struct rtl28xxu_req req_gate_close = {0x0120, 0x0011, 0x0001, "\x10"};
-	/* for FC0012 tuner probe */
-	struct rtl28xxu_req req_fc0012 = {0x00c6, CMD_I2C_RD, 1, buf};
-	/* for FC0013 tuner probe */
-	struct rtl28xxu_req req_fc0013 = {0x00c6, CMD_I2C_RD, 1, buf};
-	/* for MT2266 tuner probe */
-	struct rtl28xxu_req req_mt2266 = {0x00c0, CMD_I2C_RD, 1, buf};
-	/* for FC2580 tuner probe */
-	struct rtl28xxu_req req_fc2580 = {0x01ac, CMD_I2C_RD, 1, buf};
-	/* for MT2063 tuner probe */
-	struct rtl28xxu_req req_mt2063 = {0x00c0, CMD_I2C_RD, 1, buf};
-	/* for MAX3543 tuner probe */
-	struct rtl28xxu_req req_max3543 = {0x00c0, CMD_I2C_RD, 1, buf};
-	/* for TUA9001 tuner probe */
-	struct rtl28xxu_req req_tua9001 = {0x7ec0, CMD_I2C_RD, 2, buf};
-	/* for MXL5007T tuner probe */
-	struct rtl28xxu_req req_mxl5007t = {0xd9c0, CMD_I2C_RD, 1, buf};
-	/* for E4000 tuner probe */
-	struct rtl28xxu_req req_e4000 = {0x02c8, CMD_I2C_RD, 1, buf};
-	/* for TDA18272 tuner probe */
-	struct rtl28xxu_req req_tda18272 = {0x00c0, CMD_I2C_RD, 2, buf};
-
-	deb_info("%s:\n", __func__);
-
-
-	ret = rtl28xx_rd_reg(adap->dev, SYS_GPIO_DIR, &val);
-	if (ret)
-		goto err;
-
-	val &= 0xbf;
-
-	ret = rtl28xx_wr_reg(adap->dev, SYS_GPIO_DIR, val);
-	if (ret)
-		goto err;
-
-
-	/* enable as output GPIO3 and GPIO6*/
-	ret = rtl28xx_rd_reg(adap->dev, SYS_GPIO_OUT_EN, &val);
-	if (ret)
-		goto err;
-
-	val |= 0x48;
-
-	ret = rtl28xx_wr_reg(adap->dev, SYS_GPIO_OUT_EN, val);
-	if (ret)
-		goto err;
-
-
-
-	/*
-	 * Probe used tuner. We need to know used tuner before demod attach
-	 * since there is some demod params needed to set according to tuner.
-	 */
-
-	/* open demod I2C gate */
-	ret = rtl28xxu_ctrl_msg(adap->dev, &req_gate_open);
-	if (ret)
-		goto err;
-
-	priv->tuner = TUNER_NONE;
-
-	/* check FC0012 ID register; reg=00 val=a1 */
-	ret = rtl28xxu_ctrl_msg(adap->dev, &req_fc0012);
-	if (ret == 0 && buf[0] == 0xa1) {
-		priv->tuner = TUNER_RTL2832_FC0012;
-		rtl2832_config = &rtl28xxu_rtl2832_fc0012_config;
-		info("%s: FC0012 tuner found", __func__);
-		goto found;
-	}
-
-	/* check FC0013 ID register; reg=00 val=a3 */
-	ret = rtl28xxu_ctrl_msg(adap->dev, &req_fc0013);
-	if (ret == 0 && buf[0] == 0xa3) {
-		priv->tuner = TUNER_RTL2832_FC0013;
-		rtl2832_config = &rtl28xxu_rtl2832_fc0013_config;
-		info("%s: FC0013 tuner found", __func__);
-		goto found;
-	}
-
-	/* check MT2266 ID register; reg=00 val=85 */
-	ret = rtl28xxu_ctrl_msg(adap->dev, &req_mt2266);
-	if (ret == 0 && buf[0] == 0x85) {
-		priv->tuner = TUNER_RTL2832_MT2266;
-		/* TODO implement tuner */
-		info("%s: MT2266 tuner found", __func__);
-		goto unsupported;
-	}
-
-	/* check FC2580 ID register; reg=01 val=56 */
-	ret = rtl28xxu_ctrl_msg(adap->dev, &req_fc2580);
-	if (ret == 0 && buf[0] == 0x56) {
-		priv->tuner = TUNER_RTL2832_FC2580;
-		/* TODO implement tuner */
-		info("%s: FC2580 tuner found", __func__);
-		goto unsupported;
-	}
-
-	/* check MT2063 ID register; reg=00 val=9e || 9c */
-	ret = rtl28xxu_ctrl_msg(adap->dev, &req_mt2063);
-	if (ret == 0 && (buf[0] == 0x9e || buf[0] == 0x9c)) {
-		priv->tuner = TUNER_RTL2832_MT2063;
-		/* TODO implement tuner */
-		info("%s: MT2063 tuner found", __func__);
-		goto unsupported;
-	}
-
-	/* check MAX3543 ID register; reg=00 val=38 */
-	ret = rtl28xxu_ctrl_msg(adap->dev, &req_max3543);
-	if (ret == 0 && buf[0] == 0x38) {
-		priv->tuner = TUNER_RTL2832_MAX3543;
-		/* TODO implement tuner */
-		info("%s: MAX3534 tuner found", __func__);
-		goto unsupported;
-	}
-
-	/* check TUA9001 ID register; reg=7e val=2328 */
-	ret = rtl28xxu_ctrl_msg(adap->dev, &req_tua9001);
-	if (ret == 0 && buf[0] == 0x23 && buf[1] == 0x28) {
-		priv->tuner = TUNER_RTL2832_TUA9001;
-		/* TODO implement tuner */
-		info("%s: TUA9001 tuner found", __func__);
-		goto unsupported;
-	}
-
-	/* check MXL5007R ID register; reg=d9 val=14 */
-	ret = rtl28xxu_ctrl_msg(adap->dev, &req_mxl5007t);
-	if (ret == 0 && buf[0] == 0x14) {
-		priv->tuner = TUNER_RTL2832_MXL5007T;
-		/* TODO implement tuner */
-		info("%s: MXL5007T tuner found", __func__);
-		goto unsupported;
-	}
-
-	/* check E4000 ID register; reg=02 val=40 */
-	ret = rtl28xxu_ctrl_msg(adap->dev, &req_e4000);
-	if (ret == 0 && buf[0] == 0x40) {
-		priv->tuner = TUNER_RTL2832_E4000;
-		/* TODO implement tuner */
-		info("%s: E4000 tuner found", __func__);
-		goto unsupported;
-	}
-
-	/* check TDA18272 ID register; reg=00 val=c760  */
-	ret = rtl28xxu_ctrl_msg(adap->dev, &req_tda18272);
-	if (ret == 0 && (buf[0] == 0xc7 || buf[1] == 0x60)) {
-		priv->tuner = TUNER_RTL2832_TDA18272;
-		/* TODO implement tuner */
-		info("%s: TDA18272 tuner found", __func__);
-		goto unsupported;
-	}
-
-unsupported:
-	/* close demod I2C gate */
-	ret = rtl28xxu_ctrl_msg(adap->dev, &req_gate_close);
-	if (ret)
-		goto err;
-
-	/* tuner not found */
-	deb_info("No compatible tuner found");
-	ret = -ENODEV;
-	return ret;
-
-found:
-	/* close demod I2C gate */
-	ret = rtl28xxu_ctrl_msg(adap->dev, &req_gate_close);
-	if (ret)
-		goto err;
-
-	/* attach demodulator */
-	adap->fe_adap[0].fe = dvb_attach(rtl2832_attach, rtl2832_config,
-		&adap->dev->i2c_adap);
-		if (adap->fe_adap[0].fe == NULL) {
-			ret = -ENODEV;
-			goto err;
-		}
-
-	/* set fe callbacks */
-	adap->fe_adap[0].fe->callback = rtl2832u_frontend_callback;
-
-	return ret;
-
-err:
-	deb_info("%s: failed=%d\n", __func__, ret);
-	return ret;
-}
-
-static struct qt1010_config rtl28xxu_qt1010_config = {
-	.i2c_address = 0x62, /* 0xc4 */
-};
-
-static struct mt2060_config rtl28xxu_mt2060_config = {
-	.i2c_address = 0x60, /* 0xc0 */
-	.clock_out = 0,
-};
-
-static struct mxl5005s_config rtl28xxu_mxl5005s_config = {
-	.i2c_address     = 0x63, /* 0xc6 */
-	.if_freq         = IF_FREQ_4570000HZ,
-	.xtal_freq       = CRYSTAL_FREQ_16000000HZ,
-	.agc_mode        = MXL_SINGLE_AGC,
-	.tracking_filter = MXL_TF_C_H,
-	.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 rtl2831u_tuner_attach(struct dvb_usb_adapter *adap)
-{
-	int ret;
-	struct rtl28xxu_priv *priv = adap->dev->priv;
-	struct i2c_adapter *rtl2830_tuner_i2c;
-	struct dvb_frontend *fe;
-
-	deb_info("%s:\n", __func__);
-
-	/* use rtl2830 driver I2C adapter, for more info see rtl2830 driver */
-	rtl2830_tuner_i2c = rtl2830_get_tuner_i2c_adapter(adap->fe_adap[0].fe);
-
-	switch (priv->tuner) {
-	case TUNER_RTL2830_QT1010:
-		fe = dvb_attach(qt1010_attach, adap->fe_adap[0].fe,
-				rtl2830_tuner_i2c, &rtl28xxu_qt1010_config);
-		break;
-	case TUNER_RTL2830_MT2060:
-		fe = dvb_attach(mt2060_attach, adap->fe_adap[0].fe,
-				rtl2830_tuner_i2c, &rtl28xxu_mt2060_config,
-				1220);
-		break;
-	case TUNER_RTL2830_MXL5005S:
-		fe = dvb_attach(mxl5005s_attach, adap->fe_adap[0].fe,
-				rtl2830_tuner_i2c, &rtl28xxu_mxl5005s_config);
-		break;
-	default:
-		fe = NULL;
-		err("unknown tuner=%d", priv->tuner);
-	}
-
-	if (fe == NULL) {
-		ret = -ENODEV;
-		goto err;
-	}
-
-	return 0;
-err:
-	deb_info("%s: failed=%d\n", __func__, ret);
-	return ret;
-}
-
-static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap)
-{
-	int ret;
-	struct rtl28xxu_priv *priv = adap->dev->priv;
-	struct dvb_frontend *fe;
-
-	deb_info("%s:\n", __func__);
-
-	switch (priv->tuner) {
-	case TUNER_RTL2832_FC0012:
-		fe = dvb_attach(fc0012_attach, adap->fe_adap[0].fe,
-			&adap->dev->i2c_adap, 0xc6>>1, 0, FC_XTAL_28_8_MHZ);
-
-		/* since fc0012 includs reading the signal strength delegate
-		 * that to the tuner driver */
-		adap->fe_adap[0].fe->ops.read_signal_strength = adap->fe_adap[0].
-				fe->ops.tuner_ops.get_rf_strength;
-		return 0;
-		break;
-	case TUNER_RTL2832_FC0013:
-		fe = dvb_attach(fc0013_attach, adap->fe_adap[0].fe,
-			&adap->dev->i2c_adap, 0xc6>>1, 0, FC_XTAL_28_8_MHZ);
-
-		/* fc0013 also supports signal strength reading */
-		adap->fe_adap[0].fe->ops.read_signal_strength = adap->fe_adap[0]
-			.fe->ops.tuner_ops.get_rf_strength;
-		return 0;
-	default:
-		fe = NULL;
-		err("unknown tuner=%d", priv->tuner);
-	}
-
-	if (fe == NULL) {
-		ret = -ENODEV;
-		goto err;
-	}
-
-	return 0;
-err:
-	deb_info("%s: failed=%d\n", __func__, ret);
-	return ret;
-}
-
-static int rtl2831u_streaming_ctrl(struct dvb_usb_adapter *adap , int onoff)
-{
-	int ret;
-	u8 buf[2], gpio;
-
-	deb_info("%s: onoff=%d\n", __func__, onoff);
-
-	ret = rtl28xx_rd_reg(adap->dev, SYS_GPIO_OUT_VAL, &gpio);
-	if (ret)
-		goto err;
-
-	if (onoff) {
-		buf[0] = 0x00;
-		buf[1] = 0x00;
-		gpio |= 0x04; /* LED on */
-	} else {
-		buf[0] = 0x10; /* stall EPA */
-		buf[1] = 0x02; /* reset EPA */
-		gpio &= (~0x04); /* LED off */
-	}
-
-	ret = rtl28xx_wr_reg(adap->dev, SYS_GPIO_OUT_VAL, gpio);
-	if (ret)
-		goto err;
-
-	ret = rtl28xx_wr_regs(adap->dev, USB_EPA_CTL, buf, 2);
-	if (ret)
-		goto err;
-
-	return ret;
-err:
-	deb_info("%s: failed=%d\n", __func__, ret);
-	return ret;
-}
-
-static int rtl2832u_streaming_ctrl(struct dvb_usb_adapter *adap , int onoff)
-{
-	int ret;
-	u8 buf[2];
-
-	deb_info("%s: onoff=%d\n", __func__, onoff);
-
-
-	if (onoff) {
-		buf[0] = 0x00;
-		buf[1] = 0x00;
-	} else {
-		buf[0] = 0x10; /* stall EPA */
-		buf[1] = 0x02; /* reset EPA */
-	}
-
-	ret = rtl28xx_wr_regs(adap->dev, USB_EPA_CTL, buf, 2);
-	if (ret)
-		goto err;
-
-	return ret;
-err:
-	deb_info("%s: failed=%d\n", __func__, ret);
-	return ret;
-}
-
-static int rtl2831u_power_ctrl(struct dvb_usb_device *d, int onoff)
-{
-	int ret;
-	u8 gpio, sys0;
-
-	deb_info("%s: onoff=%d\n", __func__, onoff);
-
-	/* demod adc */
-	ret = rtl28xx_rd_reg(d, SYS_SYS0, &sys0);
-	if (ret)
-		goto err;
-
-	/* tuner power, read GPIOs */
-	ret = rtl28xx_rd_reg(d, SYS_GPIO_OUT_VAL, &gpio);
-	if (ret)
-		goto err;
-
-	deb_info("%s: RD SYS0=%02x GPIO_OUT_VAL=%02x\n", __func__, sys0, gpio);
-
-	if (onoff) {
-		gpio |= 0x01; /* GPIO0 = 1 */
-		gpio &= (~0x10); /* GPIO4 = 0 */
-		sys0 = sys0 & 0x0f;
-		sys0 |= 0xe0;
-	} else {
-		gpio &= (~0x01); /* GPIO0 = 0 */
-		gpio |= 0x10; /* GPIO4 = 1 */
-		sys0 = sys0 & (~0xc0);
-	}
-
-	deb_info("%s: WR SYS0=%02x GPIO_OUT_VAL=%02x\n", __func__, sys0, gpio);
-
-	/* demod adc */
-	ret = rtl28xx_wr_reg(d, SYS_SYS0, sys0);
-	if (ret)
-		goto err;
-
-	/* tuner power, write GPIOs */
-	ret = rtl28xx_wr_reg(d, SYS_GPIO_OUT_VAL, gpio);
-	if (ret)
-		goto err;
-
-	return ret;
-err:
-	deb_info("%s: failed=%d\n", __func__, ret);
-	return ret;
-}
-
-static int rtl2832u_power_ctrl(struct dvb_usb_device *d, int onoff)
-{
-	int ret;
-	u8 val;
-
-	deb_info("%s: onoff=%d\n", __func__, onoff);
-
-	if (onoff) {
-		/* set output values */
-		ret = rtl28xx_rd_reg(d, SYS_GPIO_OUT_VAL, &val);
-		if (ret)
-			goto err;
-
-		val |= 0x08;
-		val &= 0xef;
-
-		ret = rtl28xx_wr_reg(d, SYS_GPIO_OUT_VAL, val);
-		if (ret)
-			goto err;
-
-		/* demod_ctl_1 */
-		ret = rtl28xx_rd_reg(d, SYS_DEMOD_CTL1, &val);
-		if (ret)
-			goto err;
-
-		val &= 0xef;
-
-		ret = rtl28xx_wr_reg(d, SYS_DEMOD_CTL1, val);
-		if (ret)
-			goto err;
-
-		/* demod control */
-		/* PLL enable */
-		ret = rtl28xx_rd_reg(d, SYS_DEMOD_CTL, &val);
-		if (ret)
-			goto err;
-
-		/* bit 7 to 1 */
-		val |= 0x80;
-
-		ret = rtl28xx_wr_reg(d, SYS_DEMOD_CTL, val);
-		if (ret)
-			goto err;
-
-		/* demod HW reset */
-		ret = rtl28xx_rd_reg(d, SYS_DEMOD_CTL, &val);
-		if (ret)
-			goto err;
-		/* bit 5 to 0 */
-		val &= 0xdf;
-
-		ret = rtl28xx_wr_reg(d, SYS_DEMOD_CTL, val);
-		if (ret)
-			goto err;
-
-		ret = rtl28xx_rd_reg(d, SYS_DEMOD_CTL, &val);
-		if (ret)
-			goto err;
-
-		val |= 0x20;
-
-		ret = rtl28xx_wr_reg(d, SYS_DEMOD_CTL, val);
-		if (ret)
-			goto err;
-
-		mdelay(5);
-
-		/*enable ADC_Q and ADC_I */
-		ret = rtl28xx_rd_reg(d, SYS_DEMOD_CTL, &val);
-		if (ret)
-			goto err;
-
-		val |= 0x48;
-
-		ret = rtl28xx_wr_reg(d, SYS_DEMOD_CTL, val);
-		if (ret)
-			goto err;
-
-
-	} else {
-		/* demod_ctl_1 */
-		ret = rtl28xx_rd_reg(d, SYS_DEMOD_CTL1, &val);
-		if (ret)
-			goto err;
-
-		val |= 0x0c;
-
-		ret = rtl28xx_wr_reg(d, SYS_DEMOD_CTL1, val);
-		if (ret)
-			goto err;
-
-		/* set output values */
-		ret = rtl28xx_rd_reg(d, SYS_GPIO_OUT_VAL, &val);
-		if (ret)
-				goto err;
-
-		val |= 0x10;
-
-		ret = rtl28xx_wr_reg(d, SYS_GPIO_OUT_VAL, val);
-		if (ret)
-			goto err;
-
-		/* demod control */
-		ret = rtl28xx_rd_reg(d, SYS_DEMOD_CTL, &val);
-		if (ret)
-			goto err;
-
-		val &= 0x37;
-
-		ret = rtl28xx_wr_reg(d, SYS_DEMOD_CTL, val);
-		if (ret)
-			goto err;
-
-	}
-
-	return ret;
-err:
-	deb_info("%s: failed=%d\n", __func__, ret);
-	return ret;
-}
-
-
-static int rtl2831u_rc_query(struct dvb_usb_device *d)
-{
-	int ret, i;
-	struct rtl28xxu_priv *priv = d->priv;
-	u8 buf[5];
-	u32 rc_code;
-	struct rtl28xxu_reg_val rc_nec_tab[] = {
-		{ 0x3033, 0x80 },
-		{ 0x3020, 0x43 },
-		{ 0x3021, 0x16 },
-		{ 0x3022, 0x16 },
-		{ 0x3023, 0x5a },
-		{ 0x3024, 0x2d },
-		{ 0x3025, 0x16 },
-		{ 0x3026, 0x01 },
-		{ 0x3028, 0xb0 },
-		{ 0x3029, 0x04 },
-		{ 0x302c, 0x88 },
-		{ 0x302e, 0x13 },
-		{ 0x3030, 0xdf },
-		{ 0x3031, 0x05 },
-	};
-
-	/* init remote controller */
-	if (!priv->rc_active) {
-		for (i = 0; i < ARRAY_SIZE(rc_nec_tab); i++) {
-			ret = rtl28xx_wr_reg(d, rc_nec_tab[i].reg,
-					rc_nec_tab[i].val);
-			if (ret)
-				goto err;
-		}
-		priv->rc_active = true;
-	}
-
-	ret = rtl2831_rd_regs(d, SYS_IRRC_RP, buf, 5);
-	if (ret)
-		goto err;
-
-	if (buf[4] & 0x01) {
-		if (buf[2] == (u8) ~buf[3]) {
-			if (buf[0] == (u8) ~buf[1]) {
-				/* NEC standard (16 bit) */
-				rc_code = buf[0] << 8 | buf[2];
-			} else {
-				/* NEC extended (24 bit) */
-				rc_code = buf[0] << 16 |
-						buf[1] << 8 | buf[2];
-			}
-		} else {
-			/* NEC full (32 bit) */
-			rc_code = buf[0] << 24 | buf[1] << 16 |
-					buf[2] << 8 | buf[3];
-		}
-
-		rc_keydown(d->rc_dev, rc_code, 0);
-
-		ret = rtl28xx_wr_reg(d, SYS_IRRC_SR, 1);
-		if (ret)
-			goto err;
-
-		/* repeated intentionally to avoid extra keypress */
-		ret = rtl28xx_wr_reg(d, SYS_IRRC_SR, 1);
-		if (ret)
-			goto err;
-	}
-
-	return ret;
-err:
-	deb_info("%s: failed=%d\n", __func__, ret);
-	return ret;
-}
-
-static int rtl2832u_rc_query(struct dvb_usb_device *d)
-{
-	int ret, i;
-	struct rtl28xxu_priv *priv = d->priv;
-	u8 buf[128];
-	int len;
-	struct rtl28xxu_reg_val rc_nec_tab[] = {
-		{ IR_RX_CTRL,             0x20 },
-		{ IR_RX_BUF_CTRL,         0x80 },
-		{ IR_RX_IF,               0xff },
-		{ IR_RX_IE,               0xff },
-		{ IR_MAX_DURATION0,       0xd0 },
-		{ IR_MAX_DURATION1,       0x07 },
-		{ IR_IDLE_LEN0,           0xc0 },
-		{ IR_IDLE_LEN1,           0x00 },
-		{ IR_GLITCH_LEN,          0x03 },
-		{ IR_RX_CLK,              0x09 },
-		{ IR_RX_CFG,              0x1c },
-		{ IR_MAX_H_TOL_LEN,       0x1e },
-		{ IR_MAX_L_TOL_LEN,       0x1e },
-		{ IR_RX_CTRL,             0x80 },
-	};
-
-	/* init remote controller */
-	if (!priv->rc_active) {
-		for (i = 0; i < ARRAY_SIZE(rc_nec_tab); i++) {
-			ret = rtl28xx_wr_reg(d, rc_nec_tab[i].reg,
-					rc_nec_tab[i].val);
-			if (ret)
-				goto err;
-		}
-		priv->rc_active = true;
-	}
-
-	ret = rtl28xx_rd_reg(d, IR_RX_IF, &buf[0]);
-	if (ret)
-		goto err;
-
-	if (buf[0] != 0x83)
-		goto exit;
-
-	ret = rtl28xx_rd_reg(d, IR_RX_BC, &buf[0]);
-	if (ret)
-		goto err;
-
-	len = buf[0];
-	ret = rtl2831_rd_regs(d, IR_RX_BUF, buf, len);
-
-	/* TODO: pass raw IR to Kernel IR decoder */
-
-	ret = rtl28xx_wr_reg(d, IR_RX_IF, 0x03);
-	ret = rtl28xx_wr_reg(d, IR_RX_BUF_CTRL, 0x80);
-	ret = rtl28xx_wr_reg(d, IR_RX_CTRL, 0x80);
-
-exit:
-	return ret;
-err:
-	deb_info("%s: failed=%d\n", __func__, ret);
-	return ret;
-}
-
-enum rtl28xxu_usb_table_entry {
-	RTL2831U_0BDA_2831,
-	RTL2831U_14AA_0160,
-	RTL2831U_14AA_0161,
-	RTL2832U_0CCD_00A9,
-	RTL2832U_1F4D_B803,
-	RTL2832U_0CCD_00B3,
-};
-
-static struct usb_device_id rtl28xxu_table[] = {
-	/* RTL2831U */
-	[RTL2831U_0BDA_2831] = {
-		USB_DEVICE(USB_VID_REALTEK, USB_PID_REALTEK_RTL2831U)},
-	[RTL2831U_14AA_0160] = {
-		USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_FREECOM_DVBT)},
-	[RTL2831U_14AA_0161] = {
-		USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_FREECOM_DVBT_2)},
-
-	/* RTL2832U */
-	[RTL2832U_0CCD_00A9] = {
-		USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_STICK_BLACK_REV1)},
-	[RTL2832U_1F4D_B803] = {
-		USB_DEVICE(USB_VID_GTEK, USB_PID_DELOCK_USB2_DVBT)},
-	[RTL2832U_0CCD_00B3] = {
-		USB_DEVICE(USB_VID_TERRATEC, USB_PID_NOXON_DAB_STICK)},
-	{} /* terminating entry */
-};
-
-MODULE_DEVICE_TABLE(usb, rtl28xxu_table);
-
-static struct dvb_usb_device_properties rtl28xxu_properties[] = {
-	{
-		.caps = DVB_USB_IS_AN_I2C_ADAPTER,
-
-		.usb_ctrl = DEVICE_SPECIFIC,
-		.no_reconnect = 1,
-
-		.size_of_priv = sizeof(struct rtl28xxu_priv),
-
-		.num_adapters = 1,
-		.adapter = {
-			{
-				.num_frontends = 1,
-				.fe = {
-					{
-						.frontend_attach = rtl2831u_frontend_attach,
-						.tuner_attach    = rtl2831u_tuner_attach,
-						.streaming_ctrl  = rtl2831u_streaming_ctrl,
-						.stream = {
-							.type = USB_BULK,
-							.count = 6,
-							.endpoint = 0x81,
-							.u = {
-								.bulk = {
-									.buffersize = 8*512,
-								}
-							}
-						}
-					}
-				}
-			}
-		},
-
-		.power_ctrl = rtl2831u_power_ctrl,
-
-		.rc.core = {
-			.protocol       = RC_TYPE_NEC,
-			.module_name    = "rtl28xxu",
-			.rc_query       = rtl2831u_rc_query,
-			.rc_interval    = 400,
-			.allowed_protos = RC_TYPE_NEC,
-			.rc_codes       = RC_MAP_EMPTY,
-		},
-
-		.i2c_algo = &rtl28xxu_i2c_algo,
-
-		.num_device_descs = 2,
-		.devices = {
-			{
-				.name = "Realtek RTL2831U reference design",
-				.warm_ids = {
-					&rtl28xxu_table[RTL2831U_0BDA_2831],
-				},
-			},
-			{
-				.name = "Freecom USB2.0 DVB-T",
-				.warm_ids = {
-					&rtl28xxu_table[RTL2831U_14AA_0160],
-					&rtl28xxu_table[RTL2831U_14AA_0161],
-				},
-			},
-		}
-	},
-	{
-		.caps = DVB_USB_IS_AN_I2C_ADAPTER,
-
-		.usb_ctrl = DEVICE_SPECIFIC,
-		.no_reconnect = 1,
-
-		.size_of_priv = sizeof(struct rtl28xxu_priv),
-
-		.num_adapters = 1,
-		.adapter = {
-			{
-				.num_frontends = 1,
-				.fe = {
-					{
-						.frontend_attach = rtl2832u_frontend_attach,
-						.tuner_attach    = rtl2832u_tuner_attach,
-						.streaming_ctrl  = rtl2832u_streaming_ctrl,
-						.stream = {
-							.type = USB_BULK,
-							.count = 6,
-							.endpoint = 0x81,
-							.u = {
-								.bulk = {
-									.buffersize = 8*512,
-								}
-							}
-						}
-					}
-				}
-			}
-		},
-
-		.power_ctrl = rtl2832u_power_ctrl,
-
-		.rc.core = {
-			.protocol       = RC_TYPE_NEC,
-			.module_name    = "rtl28xxu",
-			.rc_query       = rtl2832u_rc_query,
-			.rc_interval    = 400,
-			.allowed_protos = RC_TYPE_NEC,
-			.rc_codes       = RC_MAP_EMPTY,
-		},
-
-		.i2c_algo = &rtl28xxu_i2c_algo,
-
-		.num_device_descs = 3,
-		.devices = {
-			{
-				.name = "Terratec Cinergy T Stick Black",
-				.warm_ids = {
-					&rtl28xxu_table[RTL2832U_0CCD_00A9],
-				},
-			},
-			{
-				.name = "G-Tek Electronics Group Lifeview LV5TDLX DVB-T",
-				.warm_ids = {
-					&rtl28xxu_table[RTL2832U_1F4D_B803],
-				},
-			},
-			{
-				.name = "NOXON DAB/DAB+ USB dongle",
-				.warm_ids = {
-					&rtl28xxu_table[RTL2832U_0CCD_00B3],
-				},
-			},
-		}
-	},
-
-};
-
-static int rtl28xxu_probe(struct usb_interface *intf,
-		const struct usb_device_id *id)
-{
-	int ret, i;
-	u8 val;
-	int properties_count = ARRAY_SIZE(rtl28xxu_properties);
-	struct dvb_usb_device *d;
-	struct usb_device *udev;
-	bool found;
-
-	deb_info("%s: interface=%d\n", __func__,
-		intf->cur_altsetting->desc.bInterfaceNumber);
-
-	if (intf->cur_altsetting->desc.bInterfaceNumber != 0)
-		return 0;
-
-	/* Dynamic USB ID support. Replaces first device ID with current one .*/
-	udev = interface_to_usbdev(intf);
-
-	for (i = 0, found = false; i < ARRAY_SIZE(rtl28xxu_table) - 1; i++) {
-		if (rtl28xxu_table[i].idVendor ==
-				le16_to_cpu(udev->descriptor.idVendor) &&
-				rtl28xxu_table[i].idProduct ==
-				le16_to_cpu(udev->descriptor.idProduct)) {
-			found = true;
-			break;
-		}
-	}
-
-	if (!found) {
-		deb_info("%s: using dynamic ID %04x:%04x\n", __func__,
-				le16_to_cpu(udev->descriptor.idVendor),
-				le16_to_cpu(udev->descriptor.idProduct));
-		rtl28xxu_properties[0].devices[0].warm_ids[0]->idVendor =
-				le16_to_cpu(udev->descriptor.idVendor);
-		rtl28xxu_properties[0].devices[0].warm_ids[0]->idProduct =
-				le16_to_cpu(udev->descriptor.idProduct);
-	}
-
-	for (i = 0; i < properties_count; i++) {
-		ret = dvb_usb_device_init(intf, &rtl28xxu_properties[i],
-				THIS_MODULE, &d, adapter_nr);
-		if (ret == 0 || ret != -ENODEV)
-			break;
-	}
-
-	if (ret)
-		goto err;
-
-
-	/* init USB endpoints */
-	ret = rtl28xx_rd_reg(d, USB_SYSCTL_0, &val);
-	if (ret)
-			goto err;
-
-	/* enable DMA and Full Packet Mode*/
-	val |= 0x09;
-	ret = rtl28xx_wr_reg(d, USB_SYSCTL_0, val);
-	if (ret)
-		goto err;
-
-	/* set EPA maximum packet size to 0x0200 */
-	ret = rtl28xx_wr_regs(d, USB_EPA_MAXPKT, "\x00\x02\x00\x00", 4);
-	if (ret)
-		goto err;
-
-	/* change EPA FIFO length */
-	ret = rtl28xx_wr_regs(d, USB_EPA_FIFO_CFG, "\x14\x00\x00\x00", 4);
-	if (ret)
-		goto err;
-
-	return ret;
-err:
-	deb_info("%s: failed=%d\n", __func__, ret);
-	return ret;
-}
-
-static struct usb_driver rtl28xxu_driver = {
-	.name       = "dvb_usb_rtl28xxu",
-	.probe      = rtl28xxu_probe,
-	.disconnect = dvb_usb_device_exit,
-	.id_table   = rtl28xxu_table,
-};
-
-/* module stuff */
-static int __init rtl28xxu_module_init(void)
-{
-	int ret;
-
-	deb_info("%s:\n", __func__);
-
-	ret = usb_register(&rtl28xxu_driver);
-	if (ret)
-		err("usb_register failed=%d", ret);
-
-	return ret;
-}
-
-static void __exit rtl28xxu_module_exit(void)
-{
-	deb_info("%s:\n", __func__);
-
-	/* deregister this driver from the USB subsystem */
-	usb_deregister(&rtl28xxu_driver);
-}
-
-module_init(rtl28xxu_module_init);
-module_exit(rtl28xxu_module_exit);
-
-MODULE_DESCRIPTION("Realtek RTL28xxU DVB USB driver");
-MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
-MODULE_AUTHOR("Thomas Mair <thomas.mair86@googlemail.com>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/rtl28xxu.h b/drivers/media/dvb/dvb-usb/rtl28xxu.h
deleted file mode 100644
index 90f3bb4..0000000
--- a/drivers/media/dvb/dvb-usb/rtl28xxu.h
+++ /dev/null
@@ -1,264 +0,0 @@
-/*
- * Realtek RTL28xxU DVB USB driver
- *
- * Copyright (C) 2009 Antti Palosaari <crope@iki.fi>
- * Copyright (C) 2011 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.,
- *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef RTL28XXU_H
-#define RTL28XXU_H
-
-#define DVB_USB_LOG_PREFIX "rtl28xxu"
-#include "dvb-usb.h"
-
-#define deb_info(args...) dprintk(dvb_usb_rtl28xxu_debug, 0x01, args)
-#define deb_rc(args...)   dprintk(dvb_usb_rtl28xxu_debug, 0x02, args)
-#define deb_xfer(args...) dprintk(dvb_usb_rtl28xxu_debug, 0x04, args)
-#define deb_reg(args...)  dprintk(dvb_usb_rtl28xxu_debug, 0x08, args)
-#define deb_i2c(args...)  dprintk(dvb_usb_rtl28xxu_debug, 0x10, args)
-#define deb_fw(args...)   dprintk(dvb_usb_rtl28xxu_debug, 0x20, args)
-
-#define deb_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");\
-}
-
-/*
- * USB commands
- * (usb_control_msg() index parameter)
- */
-
-#define DEMOD            0x0000
-#define USB              0x0100
-#define SYS              0x0200
-#define I2C              0x0300
-#define I2C_DA           0x0600
-
-#define CMD_WR_FLAG      0x0010
-#define CMD_DEMOD_RD     0x0000
-#define CMD_DEMOD_WR     0x0010
-#define CMD_USB_RD       0x0100
-#define CMD_USB_WR       0x0110
-#define CMD_SYS_RD       0x0200
-#define CMD_IR_RD        0x0201
-#define CMD_IR_WR        0x0211
-#define CMD_SYS_WR       0x0210
-#define CMD_I2C_RD       0x0300
-#define CMD_I2C_WR       0x0310
-#define CMD_I2C_DA_RD    0x0600
-#define CMD_I2C_DA_WR    0x0610
-
-
-struct rtl28xxu_priv {
-	u8 chip_id;
-	u8 tuner;
-	u8 page; /* integrated demod active register page */
-	bool rc_active;
-};
-
-enum rtl28xxu_chip_id {
-	CHIP_ID_NONE,
-	CHIP_ID_RTL2831U,
-	CHIP_ID_RTL2832U,
-};
-
-enum rtl28xxu_tuner {
-	TUNER_NONE,
-
-	TUNER_RTL2830_QT1010,
-	TUNER_RTL2830_MT2060,
-	TUNER_RTL2830_MXL5005S,
-
-	TUNER_RTL2832_MT2266,
-	TUNER_RTL2832_FC2580,
-	TUNER_RTL2832_MT2063,
-	TUNER_RTL2832_MAX3543,
-	TUNER_RTL2832_TUA9001,
-	TUNER_RTL2832_MXL5007T,
-	TUNER_RTL2832_FC0012,
-	TUNER_RTL2832_E4000,
-	TUNER_RTL2832_TDA18272,
-	TUNER_RTL2832_FC0013,
-};
-
-struct rtl28xxu_req {
-	u16 value;
-	u16 index;
-	u16 size;
-	u8 *data;
-};
-
-struct rtl28xxu_reg_val {
-	u16 reg;
-	u8 val;
-};
-
-/*
- * memory map
- *
- * 0x0000 DEMOD : demodulator
- * 0x2000 USB   : SIE, USB endpoint, debug, DMA
- * 0x3000 SYS   : system
- * 0xfc00 RC    : remote controller (not RTL2831U)
- */
-
-/*
- * USB registers
- */
-/* SIE Control Registers */
-#define USB_SYSCTL         0x2000 /* USB system control */
-#define USB_SYSCTL_0       0x2000 /* USB system control */
-#define USB_SYSCTL_1       0x2001 /* USB system control */
-#define USB_SYSCTL_2       0x2002 /* USB system control */
-#define USB_SYSCTL_3       0x2003 /* USB system control */
-#define USB_IRQSTAT        0x2008 /* SIE interrupt status */
-#define USB_IRQEN          0x200C /* SIE interrupt enable */
-#define USB_CTRL           0x2010 /* USB control */
-#define USB_STAT           0x2014 /* USB status */
-#define USB_DEVADDR        0x2018 /* USB device address */
-#define USB_TEST           0x201C /* USB test mode */
-#define USB_FRAME_NUMBER   0x2020 /* frame number */
-#define USB_FIFO_ADDR      0x2028 /* address of SIE FIFO RAM */
-#define USB_FIFO_CMD       0x202A /* SIE FIFO RAM access command */
-#define USB_FIFO_DATA      0x2030 /* SIE FIFO RAM data */
-/* Endpoint Registers */
-#define EP0_SETUPA         0x20F8 /* EP 0 setup packet lower byte */
-#define EP0_SETUPB         0x20FC /* EP 0 setup packet higher byte */
-#define USB_EP0_CFG        0x2104 /* EP 0 configure */
-#define USB_EP0_CTL        0x2108 /* EP 0 control */
-#define USB_EP0_STAT       0x210C /* EP 0 status */
-#define USB_EP0_IRQSTAT    0x2110 /* EP 0 interrupt status */
-#define USB_EP0_IRQEN      0x2114 /* EP 0 interrupt enable */
-#define USB_EP0_MAXPKT     0x2118 /* EP 0 max packet size */
-#define USB_EP0_BC         0x2120 /* EP 0 FIFO byte counter */
-#define USB_EPA_CFG        0x2144 /* EP A configure */
-#define USB_EPA_CFG_0      0x2144 /* EP A configure */
-#define USB_EPA_CFG_1      0x2145 /* EP A configure */
-#define USB_EPA_CFG_2      0x2146 /* EP A configure */
-#define USB_EPA_CFG_3      0x2147 /* EP A configure */
-#define USB_EPA_CTL        0x2148 /* EP A control */
-#define USB_EPA_CTL_0      0x2148 /* EP A control */
-#define USB_EPA_CTL_1      0x2149 /* EP A control */
-#define USB_EPA_CTL_2      0x214A /* EP A control */
-#define USB_EPA_CTL_3      0x214B /* EP A control */
-#define USB_EPA_STAT       0x214C /* EP A status */
-#define USB_EPA_IRQSTAT    0x2150 /* EP A interrupt status */
-#define USB_EPA_IRQEN      0x2154 /* EP A interrupt enable */
-#define USB_EPA_MAXPKT     0x2158 /* EP A max packet size */
-#define USB_EPA_MAXPKT_0   0x2158 /* EP A max packet size */
-#define USB_EPA_MAXPKT_1   0x2159 /* EP A max packet size */
-#define USB_EPA_MAXPKT_2   0x215A /* EP A max packet size */
-#define USB_EPA_MAXPKT_3   0x215B /* EP A max packet size */
-#define USB_EPA_FIFO_CFG   0x2160 /* EP A FIFO configure */
-#define USB_EPA_FIFO_CFG_0 0x2160 /* EP A FIFO configure */
-#define USB_EPA_FIFO_CFG_1 0x2161 /* EP A FIFO configure */
-#define USB_EPA_FIFO_CFG_2 0x2162 /* EP A FIFO configure */
-#define USB_EPA_FIFO_CFG_3 0x2163 /* EP A FIFO configure */
-/* Debug Registers */
-#define USB_PHYTSTDIS      0x2F04 /* PHY test disable */
-#define USB_TOUT_VAL       0x2F08 /* USB time-out time */
-#define USB_VDRCTRL        0x2F10 /* UTMI vendor signal control */
-#define USB_VSTAIN         0x2F14 /* UTMI vendor signal status in */
-#define USB_VLOADM         0x2F18 /* UTMI load vendor signal status in */
-#define USB_VSTAOUT        0x2F1C /* UTMI vendor signal status out */
-#define USB_UTMI_TST       0x2F80 /* UTMI test */
-#define USB_UTMI_STATUS    0x2F84 /* UTMI status */
-#define USB_TSTCTL         0x2F88 /* test control */
-#define USB_TSTCTL2        0x2F8C /* test control 2 */
-#define USB_PID_FORCE      0x2F90 /* force PID */
-#define USB_PKTERR_CNT     0x2F94 /* packet error counter */
-#define USB_RXERR_CNT      0x2F98 /* RX error counter */
-#define USB_MEM_BIST       0x2F9C /* MEM BIST test */
-#define USB_SLBBIST        0x2FA0 /* self-loop-back BIST */
-#define USB_CNTTEST        0x2FA4 /* counter test */
-#define USB_PHYTST         0x2FC0 /* USB PHY test */
-#define USB_DBGIDX         0x2FF0 /* select individual block debug signal */
-#define USB_DBGMUX         0x2FF4 /* debug signal module mux */
-
-/*
- * SYS registers
- */
-/* demod control registers */
-#define SYS_SYS0           0x3000 /* include DEMOD_CTL, GPO, GPI, GPOE */
-#define SYS_DEMOD_CTL      0x3000 /* control register for DVB-T demodulator */
-/* GPIO registers */
-#define SYS_GPIO_OUT_VAL   0x3001 /* output value of GPIO */
-#define SYS_GPIO_IN_VAL    0x3002 /* input value of GPIO */
-#define SYS_GPIO_OUT_EN    0x3003 /* output enable of GPIO */
-#define SYS_SYS1           0x3004 /* include GPD, SYSINTE, SYSINTS, GP_CFG0 */
-#define SYS_GPIO_DIR       0x3004 /* direction control for GPIO */
-#define SYS_SYSINTE        0x3005 /* system interrupt enable */
-#define SYS_SYSINTS        0x3006 /* system interrupt status */
-#define SYS_GPIO_CFG0      0x3007 /* PAD configuration for GPIO0-GPIO3 */
-#define SYS_SYS2           0x3008 /* include GP_CFG1 and 3 reserved bytes */
-#define SYS_GPIO_CFG1      0x3008 /* PAD configuration for GPIO4 */
-#define SYS_DEMOD_CTL1     0x300B
-
-/* IrDA registers */
-#define SYS_IRRC_PSR       0x3020 /* IR protocol selection */
-#define SYS_IRRC_PER       0x3024 /* IR protocol extension */
-#define SYS_IRRC_SF        0x3028 /* IR sampling frequency */
-#define SYS_IRRC_DPIR      0x302C /* IR data package interval */
-#define SYS_IRRC_CR        0x3030 /* IR control */
-#define SYS_IRRC_RP        0x3034 /* IR read port */
-#define SYS_IRRC_SR        0x3038 /* IR status */
-/* I2C master registers */
-#define SYS_I2CCR          0x3040 /* I2C clock */
-#define SYS_I2CMCR         0x3044 /* I2C master control */
-#define SYS_I2CMSTR        0x3048 /* I2C master SCL timing */
-#define SYS_I2CMSR         0x304C /* I2C master status */
-#define SYS_I2CMFR         0x3050 /* I2C master FIFO */
-
-/*
- * IR registers
- */
-#define IR_RX_BUF          0xFC00
-#define IR_RX_IE           0xFD00
-#define IR_RX_IF           0xFD01
-#define IR_RX_CTRL         0xFD02
-#define IR_RX_CFG          0xFD03
-#define IR_MAX_DURATION0   0xFD04
-#define IR_MAX_DURATION1   0xFD05
-#define IR_IDLE_LEN0       0xFD06
-#define IR_IDLE_LEN1       0xFD07
-#define IR_GLITCH_LEN      0xFD08
-#define IR_RX_BUF_CTRL     0xFD09
-#define IR_RX_BUF_DATA     0xFD0A
-#define IR_RX_BC           0xFD0B
-#define IR_RX_CLK          0xFD0C
-#define IR_RX_C_COUNT_L    0xFD0D
-#define IR_RX_C_COUNT_H    0xFD0E
-#define IR_SUSPEND_CTRL    0xFD10
-#define IR_ERR_TOL_CTRL    0xFD11
-#define IR_UNIT_LEN        0xFD12
-#define IR_ERR_TOL_LEN     0xFD13
-#define IR_MAX_H_TOL_LEN   0xFD14
-#define IR_MAX_L_TOL_LEN   0xFD15
-#define IR_MASK_CTRL       0xFD16
-#define IR_MASK_DATA       0xFD17
-#define IR_RES_MASK_ADDR   0xFD18
-#define IR_RES_MASK_T_LEN  0xFD19
-
-#endif
diff --git a/drivers/media/dvb/dvb-usb/technisat-usb2.c b/drivers/media/dvb/dvb-usb/technisat-usb2.c
deleted file mode 100644
index acefaa8..0000000
--- a/drivers/media/dvb/dvb-usb/technisat-usb2.c
+++ /dev/null
@@ -1,789 +0,0 @@
-/*
- * Linux driver for Technisat DVB-S/S2 USB 2.0 device
- *
- * Copyright (C) 2010 Patrick Boettcher,
- *                    Kernel Labs Inc. PO Box 745, St James, NY 11780
- *
- * Development was sponsored by Technisat Digital UK Limited, whose
- * registered office is Witan Gate House 500 - 600 Witan Gate West,
- * Milton Keynes, MK9 1SH
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the 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.
- *
- * THIS PROGRAM IS PROVIDED "AS IS" AND BOTH THE COPYRIGHT HOLDER AND
- * TECHNISAT DIGITAL UK LTD DISCLAIM ALL WARRANTIES WITH REGARD TO
- * THIS PROGRAM INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY OR
- * FITNESS FOR A PARTICULAR PURPOSE.  NEITHER THE COPYRIGHT HOLDER
- * NOR TECHNISAT DIGITAL UK LIMITED SHALL BE LIABLE FOR ANY SPECIAL,
- * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
- * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
- * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS PROGRAM. See the
- * GNU General Public License for more details.
- */
-
-#define DVB_USB_LOG_PREFIX "technisat-usb2"
-#include "dvb-usb.h"
-
-#include "stv6110x.h"
-#include "stv090x.h"
-
-/* module parameters */
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug,
-		"set debugging level (bit-mask: 1=info,2=eeprom,4=i2c,8=rc)." \
-		DVB_USB_DEBUG_STATUS);
-
-/* disables all LED control command and
- * also does not start the signal polling thread */
-static int disable_led_control;
-module_param(disable_led_control, int, 0444);
-MODULE_PARM_DESC(disable_led_control,
-		"disable LED control of the device "
-		"(default: 0 - LED control is active).");
-
-/* device private data */
-struct technisat_usb2_state {
-	struct dvb_usb_device *dev;
-	struct delayed_work green_led_work;
-	u8 power_state;
-
-	u16 last_scan_code;
-};
-
-/* debug print helpers */
-#define deb_info(args...)    dprintk(debug, 0x01, args)
-#define deb_eeprom(args...)  dprintk(debug, 0x02, args)
-#define deb_i2c(args...)     dprintk(debug, 0x04, args)
-#define deb_rc(args...)      dprintk(debug, 0x08, args)
-
-/* vendor requests */
-#define SET_IFCLK_TO_EXTERNAL_TSCLK_VENDOR_REQUEST 0xB3
-#define SET_FRONT_END_RESET_VENDOR_REQUEST         0xB4
-#define GET_VERSION_INFO_VENDOR_REQUEST            0xB5
-#define SET_GREEN_LED_VENDOR_REQUEST               0xB6
-#define SET_RED_LED_VENDOR_REQUEST                 0xB7
-#define GET_IR_DATA_VENDOR_REQUEST                 0xB8
-#define SET_LED_TIMER_DIVIDER_VENDOR_REQUEST       0xB9
-#define SET_USB_REENUMERATION                      0xBA
-
-/* i2c-access methods */
-#define I2C_SPEED_100KHZ_BIT 0x40
-
-#define I2C_STATUS_NAK 7
-#define I2C_STATUS_OK 8
-
-static int technisat_usb2_i2c_access(struct usb_device *udev,
-		u8 device_addr, u8 *tx, u8 txlen, u8 *rx, u8 rxlen)
-{
-	u8 b[64];
-	int ret, actual_length;
-
-	deb_i2c("i2c-access: %02x, tx: ", device_addr);
-	debug_dump(tx, txlen, deb_i2c);
-	deb_i2c(" ");
-
-	if (txlen > 62) {
-		err("i2c TX buffer can't exceed 62 bytes (dev 0x%02x)",
-				device_addr);
-		txlen = 62;
-	}
-	if (rxlen > 62) {
-		err("i2c RX buffer can't exceed 62 bytes (dev 0x%02x)",
-				device_addr);
-		txlen = 62;
-	}
-
-	b[0] = I2C_SPEED_100KHZ_BIT;
-	b[1] = device_addr << 1;
-
-	if (rx != NULL) {
-		b[0] |= rxlen;
-		b[1] |= 1;
-	}
-
-	memcpy(&b[2], tx, txlen);
-	ret = usb_bulk_msg(udev,
-			usb_sndbulkpipe(udev, 0x01),
-			b, 2 + txlen,
-			NULL, 1000);
-
-	if (ret < 0) {
-		err("i2c-error: out failed %02x = %d", device_addr, ret);
-		return -ENODEV;
-	}
-
-	ret = usb_bulk_msg(udev,
-			usb_rcvbulkpipe(udev, 0x01),
-			b, 64, &actual_length, 1000);
-	if (ret < 0) {
-		err("i2c-error: in failed %02x = %d", device_addr, ret);
-		return -ENODEV;
-	}
-
-	if (b[0] != I2C_STATUS_OK) {
-		err("i2c-error: %02x = %d", device_addr, b[0]);
-		/* handle tuner-i2c-nak */
-		if (!(b[0] == I2C_STATUS_NAK &&
-				device_addr == 0x60
-				/* && device_is_technisat_usb2 */))
-			return -ENODEV;
-	}
-
-	deb_i2c("status: %d, ", b[0]);
-
-	if (rx != NULL) {
-		memcpy(rx, &b[2], rxlen);
-
-		deb_i2c("rx (%d): ", rxlen);
-		debug_dump(rx, rxlen, deb_i2c);
-	}
-
-	deb_i2c("\n");
-
-	return 0;
-}
-
-static int technisat_usb2_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msg,
-				int num)
-{
-	int ret = 0, i;
-	struct dvb_usb_device *d = i2c_get_adapdata(adap);
-
-	/* Ensure nobody else hits the i2c bus while we're sending our
-	   sequence of messages, (such as the remote control thread) */
-	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
-		return -EAGAIN;
-
-	for (i = 0; i < num; i++) {
-		if (i+1 < num && msg[i+1].flags & I2C_M_RD) {
-			ret = technisat_usb2_i2c_access(d->udev, msg[i+1].addr,
-						msg[i].buf, msg[i].len,
-						msg[i+1].buf, msg[i+1].len);
-			if (ret != 0)
-				break;
-			i++;
-		} else {
-			ret = technisat_usb2_i2c_access(d->udev, msg[i].addr,
-						msg[i].buf, msg[i].len,
-						NULL, 0);
-			if (ret != 0)
-				break;
-		}
-	}
-
-	if (ret == 0)
-		ret = i;
-
-	mutex_unlock(&d->i2c_mutex);
-
-	return ret;
-}
-
-static u32 technisat_usb2_i2c_func(struct i2c_adapter *adapter)
-{
-	return I2C_FUNC_I2C;
-}
-
-static struct i2c_algorithm technisat_usb2_i2c_algo = {
-	.master_xfer   = technisat_usb2_i2c_xfer,
-	.functionality = technisat_usb2_i2c_func,
-};
-
-#if 0
-static void technisat_usb2_frontend_reset(struct usb_device *udev)
-{
-	usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
-			SET_FRONT_END_RESET_VENDOR_REQUEST,
-			USB_TYPE_VENDOR | USB_DIR_OUT,
-			10, 0,
-			NULL, 0, 500);
-}
-#endif
-
-/* LED control */
-enum technisat_usb2_led_state {
-	LED_OFF,
-	LED_BLINK,
-	LED_ON,
-	LED_UNDEFINED
-};
-
-static int technisat_usb2_set_led(struct dvb_usb_device *d, int red, enum technisat_usb2_led_state state)
-{
-	int ret;
-
-	u8 led[8] = {
-		red ? SET_RED_LED_VENDOR_REQUEST : SET_GREEN_LED_VENDOR_REQUEST,
-		0
-	};
-
-	if (disable_led_control && state != LED_OFF)
-		return 0;
-
-	switch (state) {
-	case LED_ON:
-		led[1] = 0x82;
-		break;
-	case LED_BLINK:
-		led[1] = 0x82;
-		if (red) {
-			led[2] = 0x02;
-			led[3] = 10;
-			led[4] = 10;
-		} else {
-			led[2] = 0xff;
-			led[3] = 50;
-			led[4] = 50;
-		}
-		led[5] = 1;
-		break;
-
-	default:
-	case LED_OFF:
-		led[1] = 0x80;
-		break;
-	}
-
-	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
-		return -EAGAIN;
-
-	ret = usb_control_msg(d->udev, usb_sndctrlpipe(d->udev, 0),
-		red ? SET_RED_LED_VENDOR_REQUEST : SET_GREEN_LED_VENDOR_REQUEST,
-		USB_TYPE_VENDOR | USB_DIR_OUT,
-		0, 0,
-		led, sizeof(led), 500);
-
-	mutex_unlock(&d->i2c_mutex);
-	return ret;
-}
-
-static int technisat_usb2_set_led_timer(struct dvb_usb_device *d, u8 red, u8 green)
-{
-	int ret;
-	u8 b = 0;
-
-	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
-		return -EAGAIN;
-
-	ret = usb_control_msg(d->udev, usb_sndctrlpipe(d->udev, 0),
-		SET_LED_TIMER_DIVIDER_VENDOR_REQUEST,
-		USB_TYPE_VENDOR | USB_DIR_OUT,
-		(red << 8) | green, 0,
-		&b, 1, 500);
-
-	mutex_unlock(&d->i2c_mutex);
-
-	return ret;
-}
-
-static void technisat_usb2_green_led_control(struct work_struct *work)
-{
-	struct technisat_usb2_state *state =
-		container_of(work, struct technisat_usb2_state, green_led_work.work);
-	struct dvb_frontend *fe = state->dev->adapter[0].fe_adap[0].fe;
-
-	if (state->power_state == 0)
-		goto schedule;
-
-	if (fe != NULL) {
-		enum fe_status status;
-
-		if (fe->ops.read_status(fe, &status) != 0)
-			goto schedule;
-
-		if (status & FE_HAS_LOCK) {
-			u32 ber;
-
-			if (fe->ops.read_ber(fe, &ber) != 0)
-				goto schedule;
-
-			if (ber > 1000)
-				technisat_usb2_set_led(state->dev, 0, LED_BLINK);
-			else
-				technisat_usb2_set_led(state->dev, 0, LED_ON);
-		} else
-			technisat_usb2_set_led(state->dev, 0, LED_OFF);
-	}
-
-schedule:
-	schedule_delayed_work(&state->green_led_work,
-			msecs_to_jiffies(500));
-}
-
-/* method to find out whether the firmware has to be downloaded or not */
-static int technisat_usb2_identify_state(struct usb_device *udev,
-		struct dvb_usb_device_properties *props,
-		struct dvb_usb_device_description **desc, int *cold)
-{
-	int ret;
-	u8 version[3];
-
-	/* first select the interface */
-	if (usb_set_interface(udev, 0, 1) != 0)
-		err("could not set alternate setting to 0");
-	else
-		info("set alternate setting");
-
-	*cold = 0; /* by default do not download a firmware - just in case something is wrong */
-
-	ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
-		GET_VERSION_INFO_VENDOR_REQUEST,
-		USB_TYPE_VENDOR | USB_DIR_IN,
-		0, 0,
-		version, sizeof(version), 500);
-
-	if (ret < 0)
-		*cold = 1;
-	else {
-		info("firmware version: %d.%d", version[1], version[2]);
-		*cold = 0;
-	}
-
-	return 0;
-}
-
-/* power control */
-static int technisat_usb2_power_ctrl(struct dvb_usb_device *d, int level)
-{
-	struct technisat_usb2_state *state = d->priv;
-
-	state->power_state = level;
-
-	if (disable_led_control)
-		return 0;
-
-	/* green led is turned off in any case - will be turned on when tuning */
-	technisat_usb2_set_led(d, 0, LED_OFF);
-	/* red led is turned on all the time */
-	technisat_usb2_set_led(d, 1, LED_ON);
-	return 0;
-}
-
-/* mac address reading - from the eeprom */
-#if 0
-static void technisat_usb2_eeprom_dump(struct dvb_usb_device *d)
-{
-	u8 reg;
-	u8 b[16];
-	int i, j;
-
-	/* full EEPROM dump */
-	for (j = 0; j < 256 * 4; j += 16) {
-		reg = j;
-		if (technisat_usb2_i2c_access(d->udev, 0x50 + j / 256, &reg, 1, b, 16) != 0)
-			break;
-
-		deb_eeprom("EEPROM: %01x%02x: ", j / 256, reg);
-		for (i = 0; i < 16; i++)
-			deb_eeprom("%02x ", b[i]);
-		deb_eeprom("\n");
-	}
-}
-#endif
-
-static u8 technisat_usb2_calc_lrc(const u8 *b, u16 length)
-{
-	u8 lrc = 0;
-	while (--length)
-		lrc ^= *b++;
-	return lrc;
-}
-
-static int technisat_usb2_eeprom_lrc_read(struct dvb_usb_device *d,
-	u16 offset, u8 *b, u16 length, u8 tries)
-{
-	u8 bo = offset & 0xff;
-	struct i2c_msg msg[] = {
-		{
-			.addr = 0x50 | ((offset >> 8) & 0x3),
-			.buf = &bo,
-			.len = 1
-		}, {
-			.addr = 0x50 | ((offset >> 8) & 0x3),
-			.flags	= I2C_M_RD,
-			.buf = b,
-			.len = length
-		}
-	};
-
-	while (tries--) {
-		int status;
-
-		if (i2c_transfer(&d->i2c_adap, msg, 2) != 2)
-			break;
-
-		status =
-			technisat_usb2_calc_lrc(b, length - 1) == b[length - 1];
-
-		if (status)
-			return 0;
-	}
-
-	return -EREMOTEIO;
-}
-
-#define EEPROM_MAC_START 0x3f8
-#define EEPROM_MAC_TOTAL 8
-static int technisat_usb2_read_mac_address(struct dvb_usb_device *d,
-		u8 mac[])
-{
-	u8 buf[EEPROM_MAC_TOTAL];
-
-	if (technisat_usb2_eeprom_lrc_read(d, EEPROM_MAC_START,
-				buf, EEPROM_MAC_TOTAL, 4) != 0)
-		return -ENODEV;
-
-	memcpy(mac, buf, 6);
-	return 0;
-}
-
-/* frontend attach */
-static int technisat_usb2_set_voltage(struct dvb_frontend *fe,
-		fe_sec_voltage_t voltage)
-{
-	int i;
-	u8 gpio[3] = { 0 }; /* 0 = 2, 1 = 3, 2 = 4 */
-
-	gpio[2] = 1; /* high - voltage ? */
-
-	switch (voltage) {
-	case SEC_VOLTAGE_13:
-		gpio[0] = 1;
-		break;
-	case SEC_VOLTAGE_18:
-		gpio[0] = 1;
-		gpio[1] = 1;
-		break;
-	default:
-	case SEC_VOLTAGE_OFF:
-		break;
-	}
-
-	for (i = 0; i < 3; i++)
-		if (stv090x_set_gpio(fe, i+2, 0, gpio[i], 0) != 0)
-			return -EREMOTEIO;
-	return 0;
-}
-
-static struct stv090x_config technisat_usb2_stv090x_config = {
-	.device         = STV0903,
-	.demod_mode     = STV090x_SINGLE,
-	.clk_mode       = STV090x_CLK_EXT,
-
-	.xtal           = 8000000,
-	.address        = 0x68,
-
-	.ts1_mode       = STV090x_TSMODE_DVBCI,
-	.ts1_clk        = 13400000,
-	.ts1_tei        = 1,
-
-	.repeater_level = STV090x_RPTLEVEL_64,
-
-	.tuner_bbgain   = 6,
-};
-
-static struct stv6110x_config technisat_usb2_stv6110x_config = {
-	.addr           = 0x60,
-	.refclk         = 16000000,
-	.clk_div        = 2,
-};
-
-static int technisat_usb2_frontend_attach(struct dvb_usb_adapter *a)
-{
-	struct usb_device *udev = a->dev->udev;
-	int ret;
-
-	a->fe_adap[0].fe = dvb_attach(stv090x_attach, &technisat_usb2_stv090x_config,
-			&a->dev->i2c_adap, STV090x_DEMODULATOR_0);
-
-	if (a->fe_adap[0].fe) {
-		struct stv6110x_devctl *ctl;
-
-		ctl = dvb_attach(stv6110x_attach,
-				a->fe_adap[0].fe,
-				&technisat_usb2_stv6110x_config,
-				&a->dev->i2c_adap);
-
-		if (ctl) {
-			technisat_usb2_stv090x_config.tuner_init          = ctl->tuner_init;
-			technisat_usb2_stv090x_config.tuner_sleep         = ctl->tuner_sleep;
-			technisat_usb2_stv090x_config.tuner_set_mode      = ctl->tuner_set_mode;
-			technisat_usb2_stv090x_config.tuner_set_frequency = ctl->tuner_set_frequency;
-			technisat_usb2_stv090x_config.tuner_get_frequency = ctl->tuner_get_frequency;
-			technisat_usb2_stv090x_config.tuner_set_bandwidth = ctl->tuner_set_bandwidth;
-			technisat_usb2_stv090x_config.tuner_get_bandwidth = ctl->tuner_get_bandwidth;
-			technisat_usb2_stv090x_config.tuner_set_bbgain    = ctl->tuner_set_bbgain;
-			technisat_usb2_stv090x_config.tuner_get_bbgain    = ctl->tuner_get_bbgain;
-			technisat_usb2_stv090x_config.tuner_set_refclk    = ctl->tuner_set_refclk;
-			technisat_usb2_stv090x_config.tuner_get_status    = ctl->tuner_get_status;
-
-			/* call the init function once to initialize
-			   tuner's clock output divider and demod's
-			   master clock */
-			if (a->fe_adap[0].fe->ops.init)
-				a->fe_adap[0].fe->ops.init(a->fe_adap[0].fe);
-
-			if (mutex_lock_interruptible(&a->dev->i2c_mutex) < 0)
-				return -EAGAIN;
-
-			ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
-					SET_IFCLK_TO_EXTERNAL_TSCLK_VENDOR_REQUEST,
-					USB_TYPE_VENDOR | USB_DIR_OUT,
-					0, 0,
-					NULL, 0, 500);
-			mutex_unlock(&a->dev->i2c_mutex);
-
-			if (ret != 0)
-				err("could not set IF_CLK to external");
-
-			a->fe_adap[0].fe->ops.set_voltage = technisat_usb2_set_voltage;
-
-			/* if everything was successful assign a nice name to the frontend */
-			strlcpy(a->fe_adap[0].fe->ops.info.name, a->dev->desc->name,
-					sizeof(a->fe_adap[0].fe->ops.info.name));
-		} else {
-			dvb_frontend_detach(a->fe_adap[0].fe);
-			a->fe_adap[0].fe = NULL;
-		}
-	}
-
-	technisat_usb2_set_led_timer(a->dev, 1, 1);
-
-	return a->fe_adap[0].fe == NULL ? -ENODEV : 0;
-}
-
-/* Remote control */
-
-/* the device is giving providing raw IR-signals to the host mapping
- * it only to one remote control is just the default implementation
- */
-#define NOMINAL_IR_BIT_TRANSITION_TIME_US 889
-#define NOMINAL_IR_BIT_TIME_US (2 * NOMINAL_IR_BIT_TRANSITION_TIME_US)
-
-#define FIRMWARE_CLOCK_TICK 83333
-#define FIRMWARE_CLOCK_DIVISOR 256
-
-#define IR_PERCENT_TOLERANCE 15
-
-#define NOMINAL_IR_BIT_TRANSITION_TICKS ((NOMINAL_IR_BIT_TRANSITION_TIME_US * 1000 * 1000) / FIRMWARE_CLOCK_TICK)
-#define NOMINAL_IR_BIT_TRANSITION_TICK_COUNT (NOMINAL_IR_BIT_TRANSITION_TICKS / FIRMWARE_CLOCK_DIVISOR)
-
-#define NOMINAL_IR_BIT_TIME_TICKS ((NOMINAL_IR_BIT_TIME_US * 1000 * 1000) / FIRMWARE_CLOCK_TICK)
-#define NOMINAL_IR_BIT_TIME_TICK_COUNT (NOMINAL_IR_BIT_TIME_TICKS / FIRMWARE_CLOCK_DIVISOR)
-
-#define MINIMUM_IR_BIT_TRANSITION_TICK_COUNT (NOMINAL_IR_BIT_TRANSITION_TICK_COUNT - ((NOMINAL_IR_BIT_TRANSITION_TICK_COUNT * IR_PERCENT_TOLERANCE) / 100))
-#define MAXIMUM_IR_BIT_TRANSITION_TICK_COUNT (NOMINAL_IR_BIT_TRANSITION_TICK_COUNT + ((NOMINAL_IR_BIT_TRANSITION_TICK_COUNT * IR_PERCENT_TOLERANCE) / 100))
-
-#define MINIMUM_IR_BIT_TIME_TICK_COUNT (NOMINAL_IR_BIT_TIME_TICK_COUNT - ((NOMINAL_IR_BIT_TIME_TICK_COUNT * IR_PERCENT_TOLERANCE) / 100))
-#define MAXIMUM_IR_BIT_TIME_TICK_COUNT (NOMINAL_IR_BIT_TIME_TICK_COUNT + ((NOMINAL_IR_BIT_TIME_TICK_COUNT * IR_PERCENT_TOLERANCE) / 100))
-
-static int technisat_usb2_get_ir(struct dvb_usb_device *d)
-{
-	u8 buf[62], *b;
-	int ret;
-	struct ir_raw_event ev;
-
-	buf[0] = GET_IR_DATA_VENDOR_REQUEST;
-	buf[1] = 0x08;
-	buf[2] = 0x8f;
-	buf[3] = MINIMUM_IR_BIT_TRANSITION_TICK_COUNT;
-	buf[4] = MAXIMUM_IR_BIT_TIME_TICK_COUNT;
-
-	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
-		return -EAGAIN;
-	ret = usb_control_msg(d->udev, usb_sndctrlpipe(d->udev, 0),
-			GET_IR_DATA_VENDOR_REQUEST,
-			USB_TYPE_VENDOR | USB_DIR_OUT,
-			0, 0,
-			buf, 5, 500);
-	if (ret < 0)
-		goto unlock;
-
-	buf[1] = 0;
-	buf[2] = 0;
-	ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0),
-			GET_IR_DATA_VENDOR_REQUEST,
-			USB_TYPE_VENDOR | USB_DIR_IN,
-			0x8080, 0,
-			buf, sizeof(buf), 500);
-
-unlock:
-	mutex_unlock(&d->i2c_mutex);
-
-	if (ret < 0)
-		return ret;
-
-	if (ret == 1)
-		return 0; /* no key pressed */
-
-	/* decoding */
-	b = buf+1;
-
-#if 0
-	deb_rc("RC: %d ", ret);
-	debug_dump(b, ret, deb_rc);
-#endif
-
-	ev.pulse = 0;
-	while (1) {
-		ev.pulse = !ev.pulse;
-		ev.duration = (*b * FIRMWARE_CLOCK_DIVISOR * FIRMWARE_CLOCK_TICK) / 1000;
-		ir_raw_event_store(d->rc_dev, &ev);
-
-		b++;
-		if (*b == 0xff) {
-			ev.pulse = 0;
-			ev.duration = 888888*2;
-			ir_raw_event_store(d->rc_dev, &ev);
-			break;
-		}
-	}
-
-	ir_raw_event_handle(d->rc_dev);
-
-	return 1;
-}
-
-static int technisat_usb2_rc_query(struct dvb_usb_device *d)
-{
-	int ret = technisat_usb2_get_ir(d);
-
-	if (ret < 0)
-		return ret;
-
-	if (ret == 0)
-		return 0;
-
-	if (!disable_led_control)
-		technisat_usb2_set_led(d, 1, LED_BLINK);
-
-	return 0;
-}
-
-/* DVB-USB and USB stuff follows */
-static struct usb_device_id technisat_usb2_id_table[] = {
-	{ USB_DEVICE(USB_VID_TECHNISAT, USB_PID_TECHNISAT_USB2_DVB_S2) },
-	{ 0 }		/* Terminating entry */
-};
-
-/* device description */
-static struct dvb_usb_device_properties technisat_usb2_devices = {
-	.caps              = DVB_USB_IS_AN_I2C_ADAPTER,
-
-	.usb_ctrl          = CYPRESS_FX2,
-
-	.identify_state    = technisat_usb2_identify_state,
-	.firmware          = "dvb-usb-SkyStar_USB_HD_FW_v17_63.HEX.fw",
-
-	.size_of_priv      = sizeof(struct technisat_usb2_state),
-
-	.i2c_algo          = &technisat_usb2_i2c_algo,
-
-	.power_ctrl        = technisat_usb2_power_ctrl,
-	.read_mac_address  = technisat_usb2_read_mac_address,
-
-	.num_adapters = 1,
-	.adapter = {
-		{
-		.num_frontends = 1,
-		.fe = {{
-			.frontend_attach  = technisat_usb2_frontend_attach,
-
-			.stream = {
-				.type = USB_ISOC,
-				.count = 8,
-				.endpoint = 0x2,
-				.u = {
-					.isoc = {
-						.framesperurb = 32,
-						.framesize = 2048,
-						.interval = 3,
-					}
-				}
-			},
-		}},
-			.size_of_priv = 0,
-		},
-	},
-
-	.num_device_descs = 1,
-	.devices = {
-		{   "Technisat SkyStar USB HD (DVB-S/S2)",
-			{ &technisat_usb2_id_table[0], NULL },
-			{ NULL },
-		},
-	},
-
-	.rc.core = {
-		.rc_interval = 100,
-		.rc_codes    = RC_MAP_TECHNISAT_USB2,
-		.module_name = "technisat-usb2",
-		.rc_query    = technisat_usb2_rc_query,
-		.allowed_protos = RC_TYPE_ALL,
-		.driver_type    = RC_DRIVER_IR_RAW,
-	}
-};
-
-static int technisat_usb2_probe(struct usb_interface *intf,
-		const struct usb_device_id *id)
-{
-	struct dvb_usb_device *dev;
-
-	if (dvb_usb_device_init(intf, &technisat_usb2_devices, THIS_MODULE,
-				&dev, adapter_nr) != 0)
-		return -ENODEV;
-
-	if (dev) {
-		struct technisat_usb2_state *state = dev->priv;
-		state->dev = dev;
-
-		if (!disable_led_control) {
-			INIT_DELAYED_WORK(&state->green_led_work,
-					technisat_usb2_green_led_control);
-			schedule_delayed_work(&state->green_led_work,
-					msecs_to_jiffies(500));
-		}
-	}
-
-	return 0;
-}
-
-static void technisat_usb2_disconnect(struct usb_interface *intf)
-{
-	struct dvb_usb_device *dev = usb_get_intfdata(intf);
-
-	/* work and stuff was only created when the device is is hot-state */
-	if (dev != NULL) {
-		struct technisat_usb2_state *state = dev->priv;
-		if (state != NULL)
-			cancel_delayed_work_sync(&state->green_led_work);
-	}
-
-	dvb_usb_device_exit(intf);
-}
-
-static struct usb_driver technisat_usb2_driver = {
-	.name       = "dvb_usb_technisat_usb2",
-	.probe      = technisat_usb2_probe,
-	.disconnect = technisat_usb2_disconnect,
-	.id_table   = technisat_usb2_id_table,
-};
-
-module_usb_driver(technisat_usb2_driver);
-
-MODULE_AUTHOR("Patrick Boettcher <pboettcher@kernellabs.com>");
-MODULE_DESCRIPTION("Driver for Technisat DVB-S/S2 USB 2.0 device");
-MODULE_VERSION("1.0");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/ttusb2.c b/drivers/media/dvb/dvb-usb/ttusb2.c
deleted file mode 100644
index e53a106..0000000
--- a/drivers/media/dvb/dvb-usb/ttusb2.c
+++ /dev/null
@@ -1,820 +0,0 @@
-/* DVB USB compliant linux driver for Technotrend DVB USB boxes and clones
- * (e.g. Pinnacle 400e DVB-S USB2.0).
- *
- * The Pinnacle 400e uses the same protocol as the Technotrend USB1.1 boxes.
- *
- * TDA8263 + TDA10086
- *
- * I2C addresses:
- * 0x08 - LNBP21PD   - LNB power supply
- * 0x0e - TDA10086   - Demodulator
- * 0x50 - FX2 eeprom
- * 0x60 - TDA8263    - Tuner
- * 0x78 ???
- *
- * Copyright (c) 2002 Holger Waechtler <holger@convergence.de>
- * Copyright (c) 2003 Felix Domke <tmbinc@elitedvb.net>
- * Copyright (C) 2005-6 Patrick Boettcher <pb@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, version 2.
- *
- * see Documentation/dvb/README.dvb-usb for more information
- */
-#define DVB_USB_LOG_PREFIX "ttusb2"
-#include "dvb-usb.h"
-
-#include "ttusb2.h"
-
-#include "tda826x.h"
-#include "tda10086.h"
-#include "tda1002x.h"
-#include "tda10048.h"
-#include "tda827x.h"
-#include "lnbp21.h"
-/* CA */
-#include "dvb_ca_en50221.h"
-
-/* debug */
-static int dvb_usb_ttusb2_debug;
-#define deb_info(args...)   dprintk(dvb_usb_ttusb2_debug,0x01,args)
-module_param_named(debug,dvb_usb_ttusb2_debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able))." DVB_USB_DEBUG_STATUS);
-static int dvb_usb_ttusb2_debug_ci;
-module_param_named(debug_ci,dvb_usb_ttusb2_debug_ci, int, 0644);
-MODULE_PARM_DESC(debug_ci, "set debugging ci." DVB_USB_DEBUG_STATUS);
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-#define ci_dbg(format, arg...)                \
-do {                                          \
-	if (dvb_usb_ttusb2_debug_ci)                                    \
-		printk(KERN_DEBUG DVB_USB_LOG_PREFIX \
-			": %s " format "\n" , __func__, ## arg);       \
-} while (0)
-
-enum {
-	TT3650_CMD_CI_TEST = 0x40,
-	TT3650_CMD_CI_RD_CTRL,
-	TT3650_CMD_CI_WR_CTRL,
-	TT3650_CMD_CI_RD_ATTR,
-	TT3650_CMD_CI_WR_ATTR,
-	TT3650_CMD_CI_RESET,
-	TT3650_CMD_CI_SET_VIDEO_PORT
-};
-
-struct ttusb2_state {
-	struct dvb_ca_en50221 ca;
-	struct mutex ca_mutex;
-	u8 id;
-	u16 last_rc_key;
-};
-
-static int ttusb2_msg(struct dvb_usb_device *d, u8 cmd,
-		u8 *wbuf, int wlen, u8 *rbuf, int rlen)
-{
-	struct ttusb2_state *st = d->priv;
-	u8 *s, *r = NULL;
-	int ret = 0;
-
-	s = kzalloc(wlen+4, GFP_KERNEL);
-	if (!s)
-		return -ENOMEM;
-
-	r = kzalloc(64, GFP_KERNEL);
-	if (!r) {
-		kfree(s);
-		return -ENOMEM;
-	}
-
-	s[0] = 0xaa;
-	s[1] = ++st->id;
-	s[2] = cmd;
-	s[3] = wlen;
-	memcpy(&s[4],wbuf,wlen);
-
-	ret = dvb_usb_generic_rw(d, s, wlen+4, r, 64, 0);
-
-	if (ret  != 0 ||
-		r[0] != 0x55 ||
-		r[1] != s[1] ||
-		r[2] != cmd ||
-		(rlen > 0 && r[3] != rlen)) {
-		warn("there might have been an error during control message transfer. (rlen = %d, was %d)",rlen,r[3]);
-		kfree(s);
-		kfree(r);
-		return -EIO;
-	}
-
-	if (rlen > 0)
-		memcpy(rbuf, &r[4], rlen);
-
-	kfree(s);
-	kfree(r);
-
-	return 0;
-}
-
-/* ci */
-static int tt3650_ci_msg(struct dvb_usb_device *d, u8 cmd, u8 *data, unsigned int write_len, unsigned int read_len)
-{
-	int ret;
-	u8 rx[60];/* (64 -4) */
-	ret = ttusb2_msg(d, cmd, data, write_len, rx, read_len);
-	if (!ret)
-		memcpy(data, rx, read_len);
-	return ret;
-}
-
-static int tt3650_ci_msg_locked(struct dvb_ca_en50221 *ca, u8 cmd, u8 *data, unsigned int write_len, unsigned int read_len)
-{
-	struct dvb_usb_device *d = ca->data;
-	struct ttusb2_state *state = d->priv;
-	int ret;
-
-	mutex_lock(&state->ca_mutex);
-	ret = tt3650_ci_msg(d, cmd, data, write_len, read_len);
-	mutex_unlock(&state->ca_mutex);
-
-	return ret;
-}
-
-static int tt3650_ci_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address)
-{
-	u8 buf[3];
-	int ret = 0;
-
-	if (slot)
-		return -EINVAL;
-
-	buf[0] = (address >> 8) & 0x0F;
-	buf[1] = address;
-
-
-	ret = tt3650_ci_msg_locked(ca, TT3650_CMD_CI_RD_ATTR, buf, 2, 3);
-
-	ci_dbg("%04x -> %d 0x%02x", address, ret, buf[2]);
-
-	if (ret < 0)
-		return ret;
-
-	return buf[2];
-}
-
-static int tt3650_ci_write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address, u8 value)
-{
-	u8 buf[3];
-
-	ci_dbg("%d 0x%04x 0x%02x", slot, address, value);
-
-	if (slot)
-		return -EINVAL;
-
-	buf[0] = (address >> 8) & 0x0F;
-	buf[1] = address;
-	buf[2] = value;
-
-	return tt3650_ci_msg_locked(ca, TT3650_CMD_CI_WR_ATTR, buf, 3, 3);
-}
-
-static int tt3650_ci_read_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address)
-{
-	u8 buf[2];
-	int ret;
-
-	if (slot)
-		return -EINVAL;
-
-	buf[0] = address & 3;
-
-	ret = tt3650_ci_msg_locked(ca, TT3650_CMD_CI_RD_CTRL, buf, 1, 2);
-
-	ci_dbg("0x%02x -> %d 0x%02x", address, ret, buf[1]);
-
-	if (ret < 0)
-		return ret;
-
-	return buf[1];
-}
-
-static int tt3650_ci_write_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address, u8 value)
-{
-	u8 buf[2];
-
-	ci_dbg("%d 0x%02x 0x%02x", slot, address, value);
-
-	if (slot)
-		return -EINVAL;
-
-	buf[0] = address;
-	buf[1] = value;
-
-	return tt3650_ci_msg_locked(ca, TT3650_CMD_CI_WR_CTRL, buf, 2, 2);
-}
-
-static int tt3650_ci_set_video_port(struct dvb_ca_en50221 *ca, int slot, int enable)
-{
-	u8 buf[1];
-	int ret;
-
-	ci_dbg("%d %d", slot, enable);
-
-	if (slot)
-		return -EINVAL;
-
-	buf[0] = enable;
-
-	ret = tt3650_ci_msg_locked(ca, TT3650_CMD_CI_SET_VIDEO_PORT, buf, 1, 1);
-	if (ret < 0)
-		return ret;
-
-	if (enable != buf[0]) {
-		err("CI not %sabled.", enable ? "en" : "dis");
-		return -EIO;
-	}
-
-	return 0;
-}
-
-static int tt3650_ci_slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
-{
-	return tt3650_ci_set_video_port(ca, slot, 0);
-}
-
-static int tt3650_ci_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
-{
-	return tt3650_ci_set_video_port(ca, slot, 1);
-}
-
-static int tt3650_ci_slot_reset(struct dvb_ca_en50221 *ca, int slot)
-{
-	struct dvb_usb_device *d = ca->data;
-	struct ttusb2_state *state = d->priv;
-	u8 buf[1];
-	int ret;
-
-	ci_dbg("%d", slot);
-
-	if (slot)
-		return -EINVAL;
-
-	buf[0] = 0;
-
-	mutex_lock(&state->ca_mutex);
-
-	ret = tt3650_ci_msg(d, TT3650_CMD_CI_RESET, buf, 1, 1);
-	if (ret)
-		goto failed;
-
-	msleep(500);
-
-	buf[0] = 1;
-
-	ret = tt3650_ci_msg(d, TT3650_CMD_CI_RESET, buf, 1, 1);
-	if (ret)
-		goto failed;
-
-	msleep(500);
-
-	buf[0] = 0; /* FTA */
-
-	ret = tt3650_ci_msg(d, TT3650_CMD_CI_SET_VIDEO_PORT, buf, 1, 1);
-
-	msleep(1100);
-
- failed:
-	mutex_unlock(&state->ca_mutex);
-
-	return ret;
-}
-
-static int tt3650_ci_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open)
-{
-	u8 buf[1];
-	int ret;
-
-	if (slot)
-		return -EINVAL;
-
-	ret = tt3650_ci_msg_locked(ca, TT3650_CMD_CI_TEST, buf, 0, 1);
-	if (ret)
-		return ret;
-
-	if (1 == buf[0]) {
-		return DVB_CA_EN50221_POLL_CAM_PRESENT |
-			DVB_CA_EN50221_POLL_CAM_READY;
-	}
-	return 0;
-}
-
-static void tt3650_ci_uninit(struct dvb_usb_device *d)
-{
-	struct ttusb2_state *state;
-
-	ci_dbg("");
-
-	if (NULL == d)
-		return;
-
-	state = d->priv;
-	if (NULL == state)
-		return;
-
-	if (NULL == state->ca.data)
-		return;
-
-	dvb_ca_en50221_release(&state->ca);
-
-	memset(&state->ca, 0, sizeof(state->ca));
-}
-
-static int tt3650_ci_init(struct dvb_usb_adapter *a)
-{
-	struct dvb_usb_device *d = a->dev;
-	struct ttusb2_state *state = d->priv;
-	int ret;
-
-	ci_dbg("");
-
-	mutex_init(&state->ca_mutex);
-
-	state->ca.owner = THIS_MODULE;
-	state->ca.read_attribute_mem = tt3650_ci_read_attribute_mem;
-	state->ca.write_attribute_mem = tt3650_ci_write_attribute_mem;
-	state->ca.read_cam_control = tt3650_ci_read_cam_control;
-	state->ca.write_cam_control = tt3650_ci_write_cam_control;
-	state->ca.slot_reset = tt3650_ci_slot_reset;
-	state->ca.slot_shutdown = tt3650_ci_slot_shutdown;
-	state->ca.slot_ts_enable = tt3650_ci_slot_ts_enable;
-	state->ca.poll_slot_status = tt3650_ci_poll_slot_status;
-	state->ca.data = d;
-
-	ret = dvb_ca_en50221_init(&a->dvb_adap,
-				  &state->ca,
-				  /* flags */ 0,
-				  /* n_slots */ 1);
-	if (ret) {
-		err("Cannot initialize CI: Error %d.", ret);
-		memset(&state->ca, 0, sizeof(state->ca));
-		return ret;
-	}
-
-	info("CI initialized.");
-
-	return 0;
-}
-
-static int ttusb2_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num)
-{
-	struct dvb_usb_device *d = i2c_get_adapdata(adap);
-	static u8 obuf[60], ibuf[60];
-	int i, write_read, read;
-
-	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
-		return -EAGAIN;
-
-	if (num > 2)
-		warn("more than 2 i2c messages at a time is not handled yet. TODO.");
-
-	for (i = 0; i < num; i++) {
-		write_read = i+1 < num && (msg[i+1].flags & I2C_M_RD);
-		read = msg[i].flags & I2C_M_RD;
-
-		obuf[0] = (msg[i].addr << 1) | (write_read | read);
-		if (read)
-			obuf[1] = 0;
-		else
-			obuf[1] = msg[i].len;
-
-		/* read request */
-		if (write_read)
-			obuf[2] = msg[i+1].len;
-		else if (read)
-			obuf[2] = msg[i].len;
-		else
-			obuf[2] = 0;
-
-		memcpy(&obuf[3], msg[i].buf, msg[i].len);
-
-		if (ttusb2_msg(d, CMD_I2C_XFER, obuf, obuf[1]+3, ibuf, obuf[2] + 3) < 0) {
-			err("i2c transfer failed.");
-			break;
-		}
-
-		if (write_read) {
-			memcpy(msg[i+1].buf, &ibuf[3], msg[i+1].len);
-			i++;
-		} else if (read)
-			memcpy(msg[i].buf, &ibuf[3], msg[i].len);
-	}
-
-	mutex_unlock(&d->i2c_mutex);
-	return i;
-}
-
-static u32 ttusb2_i2c_func(struct i2c_adapter *adapter)
-{
-	return I2C_FUNC_I2C;
-}
-
-static struct i2c_algorithm ttusb2_i2c_algo = {
-	.master_xfer   = ttusb2_i2c_xfer,
-	.functionality = ttusb2_i2c_func,
-};
-
-/* command to poll IR receiver (copied from pctv452e.c) */
-#define CMD_GET_IR_CODE     0x1b
-
-/* IR */
-static int tt3650_rc_query(struct dvb_usb_device *d)
-{
-	int ret;
-	u8 rx[9]; /* A CMD_GET_IR_CODE reply is 9 bytes long */
-	struct ttusb2_state *st = d->priv;
-	ret = ttusb2_msg(d, CMD_GET_IR_CODE, NULL, 0, rx, sizeof(rx));
-	if (ret != 0)
-		return ret;
-
-	if (rx[8] & 0x01) {
-		/* got a "press" event */
-		st->last_rc_key = (rx[3] << 8) | rx[2];
-		deb_info("%s: cmd=0x%02x sys=0x%02x\n", __func__, rx[2], rx[3]);
-		rc_keydown(d->rc_dev, st->last_rc_key, 0);
-	} else if (st->last_rc_key) {
-		rc_keyup(d->rc_dev);
-		st->last_rc_key = 0;
-	}
-
-	return 0;
-}
-
-
-/* Callbacks for DVB USB */
-static int ttusb2_identify_state (struct usb_device *udev, struct
-		dvb_usb_device_properties *props, struct dvb_usb_device_description **desc,
-		int *cold)
-{
-	*cold = udev->descriptor.iManufacturer == 0 && udev->descriptor.iProduct == 0;
-	return 0;
-}
-
-static int ttusb2_power_ctrl(struct dvb_usb_device *d, int onoff)
-{
-	u8 b = onoff;
-	ttusb2_msg(d, CMD_POWER, &b, 0, NULL, 0);
-	return ttusb2_msg(d, CMD_POWER, &b, 1, NULL, 0);
-}
-
-
-static struct tda10086_config tda10086_config = {
-	.demod_address = 0x0e,
-	.invert = 0,
-	.diseqc_tone = 1,
-	.xtal_freq = TDA10086_XTAL_16M,
-};
-
-static struct tda10023_config tda10023_config = {
-	.demod_address = 0x0c,
-	.invert = 0,
-	.xtal = 16000000,
-	.pll_m = 11,
-	.pll_p = 3,
-	.pll_n = 1,
-	.deltaf = 0xa511,
-};
-
-static struct tda10048_config tda10048_config = {
-	.demod_address    = 0x10 >> 1,
-	.output_mode      = TDA10048_PARALLEL_OUTPUT,
-	.inversion        = TDA10048_INVERSION_ON,
-	.dtv6_if_freq_khz = TDA10048_IF_4000,
-	.dtv7_if_freq_khz = TDA10048_IF_4500,
-	.dtv8_if_freq_khz = TDA10048_IF_5000,
-	.clk_freq_khz     = TDA10048_CLK_16000,
-	.no_firmware      = 1,
-	.set_pll          = true ,
-	.pll_m            = 5,
-	.pll_n            = 3,
-	.pll_p            = 0,
-};
-
-static struct tda827x_config tda827x_config = {
-	.config = 0,
-};
-
-static int ttusb2_frontend_tda10086_attach(struct dvb_usb_adapter *adap)
-{
-	if (usb_set_interface(adap->dev->udev,0,3) < 0)
-		err("set interface to alts=3 failed");
-
-	if ((adap->fe_adap[0].fe = dvb_attach(tda10086_attach, &tda10086_config, &adap->dev->i2c_adap)) == NULL) {
-		deb_info("TDA10086 attach failed\n");
-		return -ENODEV;
-	}
-
-	return 0;
-}
-
-static int ttusb2_ct3650_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
-{
-	struct dvb_usb_adapter *adap = fe->dvb->priv;
-
-	return adap->fe_adap[0].fe->ops.i2c_gate_ctrl(adap->fe_adap[0].fe, enable);
-}
-
-static int ttusb2_frontend_tda10023_attach(struct dvb_usb_adapter *adap)
-{
-	if (usb_set_interface(adap->dev->udev, 0, 3) < 0)
-		err("set interface to alts=3 failed");
-
-	if (adap->fe_adap[0].fe == NULL) {
-		/* FE 0 DVB-C */
-		adap->fe_adap[0].fe = dvb_attach(tda10023_attach,
-			&tda10023_config, &adap->dev->i2c_adap, 0x48);
-
-		if (adap->fe_adap[0].fe == NULL) {
-			deb_info("TDA10023 attach failed\n");
-			return -ENODEV;
-		}
-		tt3650_ci_init(adap);
-	} else {
-		adap->fe_adap[1].fe = dvb_attach(tda10048_attach,
-			&tda10048_config, &adap->dev->i2c_adap);
-
-		if (adap->fe_adap[1].fe == NULL) {
-			deb_info("TDA10048 attach failed\n");
-			return -ENODEV;
-		}
-
-		/* tuner is behind TDA10023 I2C-gate */
-		adap->fe_adap[1].fe->ops.i2c_gate_ctrl = ttusb2_ct3650_i2c_gate_ctrl;
-
-	}
-
-	return 0;
-}
-
-static int ttusb2_tuner_tda827x_attach(struct dvb_usb_adapter *adap)
-{
-	struct dvb_frontend *fe;
-
-	/* MFE: select correct FE to attach tuner since that's called twice */
-	if (adap->fe_adap[1].fe == NULL)
-		fe = adap->fe_adap[0].fe;
-	else
-		fe = adap->fe_adap[1].fe;
-
-	/* attach tuner */
-	if (dvb_attach(tda827x_attach, fe, 0x61, &adap->dev->i2c_adap, &tda827x_config) == NULL) {
-		printk(KERN_ERR "%s: No tda827x found!\n", __func__);
-		return -ENODEV;
-	}
-	return 0;
-}
-
-static int ttusb2_tuner_tda826x_attach(struct dvb_usb_adapter *adap)
-{
-	if (dvb_attach(tda826x_attach, adap->fe_adap[0].fe, 0x60, &adap->dev->i2c_adap, 0) == NULL) {
-		deb_info("TDA8263 attach failed\n");
-		return -ENODEV;
-	}
-
-	if (dvb_attach(lnbp21_attach, adap->fe_adap[0].fe, &adap->dev->i2c_adap, 0, 0) == NULL) {
-		deb_info("LNBP21 attach failed\n");
-		return -ENODEV;
-	}
-	return 0;
-}
-
-/* DVB USB Driver stuff */
-static struct dvb_usb_device_properties ttusb2_properties;
-static struct dvb_usb_device_properties ttusb2_properties_s2400;
-static struct dvb_usb_device_properties ttusb2_properties_ct3650;
-
-static void ttusb2_usb_disconnect(struct usb_interface *intf)
-{
-	struct dvb_usb_device *d = usb_get_intfdata(intf);
-
-	tt3650_ci_uninit(d);
-	dvb_usb_device_exit(intf);
-}
-
-static int ttusb2_probe(struct usb_interface *intf,
-		const struct usb_device_id *id)
-{
-	if (0 == dvb_usb_device_init(intf, &ttusb2_properties,
-				     THIS_MODULE, NULL, adapter_nr) ||
-	    0 == dvb_usb_device_init(intf, &ttusb2_properties_s2400,
-				     THIS_MODULE, NULL, adapter_nr) ||
-	    0 == dvb_usb_device_init(intf, &ttusb2_properties_ct3650,
-				     THIS_MODULE, NULL, adapter_nr))
-		return 0;
-	return -ENODEV;
-}
-
-static struct usb_device_id ttusb2_table [] = {
-	{ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PCTV_400E) },
-	{ USB_DEVICE(USB_VID_PINNACLE, USB_PID_PCTV_450E) },
-	{ USB_DEVICE(USB_VID_TECHNOTREND,
-		USB_PID_TECHNOTREND_CONNECT_S2400) },
-	{ USB_DEVICE(USB_VID_TECHNOTREND,
-		USB_PID_TECHNOTREND_CONNECT_CT3650) },
-	{}		/* Terminating entry */
-};
-MODULE_DEVICE_TABLE (usb, ttusb2_table);
-
-static struct dvb_usb_device_properties ttusb2_properties = {
-	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
-
-	.usb_ctrl = CYPRESS_FX2,
-	.firmware = "dvb-usb-pctv-400e-01.fw",
-
-	.size_of_priv = sizeof(struct ttusb2_state),
-
-	.num_adapters = 1,
-	.adapter = {
-		{
-		.num_frontends = 1,
-		.fe = {{
-			.streaming_ctrl   = NULL, // ttusb2_streaming_ctrl,
-
-			.frontend_attach  = ttusb2_frontend_tda10086_attach,
-			.tuner_attach     = ttusb2_tuner_tda826x_attach,
-
-			/* parameter for the MPEG2-data transfer */
-			.stream = {
-				.type = USB_ISOC,
-				.count = 5,
-				.endpoint = 0x02,
-				.u = {
-					.isoc = {
-						.framesperurb = 4,
-						.framesize = 940,
-						.interval = 1,
-					}
-				}
-			}
-		}},
-		}
-	},
-
-	.power_ctrl       = ttusb2_power_ctrl,
-	.identify_state   = ttusb2_identify_state,
-
-	.i2c_algo         = &ttusb2_i2c_algo,
-
-	.generic_bulk_ctrl_endpoint = 0x01,
-
-	.num_device_descs = 2,
-	.devices = {
-		{   "Pinnacle 400e DVB-S USB2.0",
-			{ &ttusb2_table[0], NULL },
-			{ NULL },
-		},
-		{   "Pinnacle 450e DVB-S USB2.0",
-			{ &ttusb2_table[1], NULL },
-			{ NULL },
-		},
-	}
-};
-
-static struct dvb_usb_device_properties ttusb2_properties_s2400 = {
-	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
-
-	.usb_ctrl = CYPRESS_FX2,
-	.firmware = "dvb-usb-tt-s2400-01.fw",
-
-	.size_of_priv = sizeof(struct ttusb2_state),
-
-	.num_adapters = 1,
-	.adapter = {
-		{
-		.num_frontends = 1,
-		.fe = {{
-			.streaming_ctrl   = NULL,
-
-			.frontend_attach  = ttusb2_frontend_tda10086_attach,
-			.tuner_attach     = ttusb2_tuner_tda826x_attach,
-
-			/* parameter for the MPEG2-data transfer */
-			.stream = {
-				.type = USB_ISOC,
-				.count = 5,
-				.endpoint = 0x02,
-				.u = {
-					.isoc = {
-						.framesperurb = 4,
-						.framesize = 940,
-						.interval = 1,
-					}
-				}
-			}
-		}},
-		}
-	},
-
-	.power_ctrl       = ttusb2_power_ctrl,
-	.identify_state   = ttusb2_identify_state,
-
-	.i2c_algo         = &ttusb2_i2c_algo,
-
-	.generic_bulk_ctrl_endpoint = 0x01,
-
-	.num_device_descs = 1,
-	.devices = {
-		{   "Technotrend TT-connect S-2400",
-			{ &ttusb2_table[2], NULL },
-			{ NULL },
-		},
-	}
-};
-
-static struct dvb_usb_device_properties ttusb2_properties_ct3650 = {
-	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
-
-	.usb_ctrl = CYPRESS_FX2,
-
-	.size_of_priv = sizeof(struct ttusb2_state),
-
-	.rc.core = {
-		.rc_interval      = 150, /* Less than IR_KEYPRESS_TIMEOUT */
-		.rc_codes         = RC_MAP_TT_1500,
-		.rc_query         = tt3650_rc_query,
-		.allowed_protos   = RC_TYPE_UNKNOWN,
-	},
-
-	.num_adapters = 1,
-	.adapter = {
-		{
-		.num_frontends = 2,
-		.fe = {{
-			.streaming_ctrl   = NULL,
-
-			.frontend_attach  = ttusb2_frontend_tda10023_attach,
-			.tuner_attach = ttusb2_tuner_tda827x_attach,
-
-			/* parameter for the MPEG2-data transfer */
-			.stream = {
-				.type = USB_ISOC,
-				.count = 5,
-				.endpoint = 0x02,
-				.u = {
-					.isoc = {
-						.framesperurb = 4,
-						.framesize = 940,
-						.interval = 1,
-					}
-				}
-			}
-		}, {
-			.streaming_ctrl   = NULL,
-
-			.frontend_attach  = ttusb2_frontend_tda10023_attach,
-			.tuner_attach = ttusb2_tuner_tda827x_attach,
-
-			/* parameter for the MPEG2-data transfer */
-			.stream = {
-				.type = USB_ISOC,
-				.count = 5,
-				.endpoint = 0x02,
-				.u = {
-					.isoc = {
-						.framesperurb = 4,
-						.framesize = 940,
-						.interval = 1,
-					}
-				}
-			}
-		}},
-		},
-	},
-
-	.power_ctrl       = ttusb2_power_ctrl,
-	.identify_state   = ttusb2_identify_state,
-
-	.i2c_algo         = &ttusb2_i2c_algo,
-
-	.generic_bulk_ctrl_endpoint = 0x01,
-
-	.num_device_descs = 1,
-	.devices = {
-		{   "Technotrend TT-connect CT-3650",
-			.warm_ids = { &ttusb2_table[3], NULL },
-		},
-	}
-};
-
-static struct usb_driver ttusb2_driver = {
-	.name		= "dvb_usb_ttusb2",
-	.probe		= ttusb2_probe,
-	.disconnect	= ttusb2_usb_disconnect,
-	.id_table	= ttusb2_table,
-};
-
-module_usb_driver(ttusb2_driver);
-
-MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
-MODULE_DESCRIPTION("Driver for Pinnacle PCTV 400e DVB-S USB2.0");
-MODULE_VERSION("1.0");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/ttusb2.h b/drivers/media/dvb/dvb-usb/ttusb2.h
deleted file mode 100644
index 52a63af..0000000
--- a/drivers/media/dvb/dvb-usb/ttusb2.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/* DVB USB compliant linux driver for Technotrend DVB USB boxes and clones
- * (e.g. Pinnacle 400e DVB-S USB2.0).
- *
- * Copyright (c) 2002 Holger Waechtler <holger@convergence.de>
- * Copyright (c) 2003 Felix Domke <tmbinc@elitedvb.net>
- * Copyright (C) 2005-6 Patrick Boettcher <pb@linuxtv.de>
- *
- *	This program is free software; you can redistribute it and/or modify it
- *	under the terms of the GNU General Public License as published by the Free
- *	Software Foundation, version 2.
- *
- * see Documentation/dvb/README.dvb-usb for more information
- */
-#ifndef _DVB_USB_TTUSB2_H_
-#define _DVB_USB_TTUSB2_H_
-
-/* TTUSB protocol
- *
- * always to messages (out/in)
- * out message:
- * 0xaa <id> <cmdbyte> <datalen> <data...>
- *
- * in message (complete block is always 0x40 bytes long)
- * 0x55 <id> <cmdbyte> <datalen> <data...>
- *
- * id is incremented for each transaction
- */
-
-#define CMD_DSP_DOWNLOAD    0x13
-/* out data: <byte>[28]
- * last block must be empty */
-
-#define CMD_DSP_BOOT        0x14
-/* out data: nothing */
-
-#define CMD_POWER           0x15
-/* out data: <on=1/off=0> */
-
-#define CMD_LNB             0x16
-/* out data: <power=1> <18V=0,13V=1> <tone> <??=1> <??=1> */
-
-#define CMD_GET_VERSION     0x17
-/* in  data: <version_byte>[5] */
-
-#define CMD_DISEQC          0x18
-/* out data: <master=0xff/burst=??> <cmdlen> <cmdbytes>[cmdlen] */
-
-#define CMD_PID_ENABLE      0x22
-/* out data: <index> <type: ts=1/sec=2> <pid msb> <pid lsb> */
-
-#define CMD_PID_DISABLE     0x23
-/* out data: <index> */
-
-#define CMD_FILTER_ENABLE   0x24
-/* out data: <index> <pid_idx> <filter>[12] <mask>[12] */
-
-#define CMD_FILTER_DISABLE  0x25
-/* out data: <index> */
-
-#define CMD_GET_DSP_VERSION 0x26
-/* in  data: <version_byte>[28] */
-
-#define CMD_I2C_XFER        0x31
-/* out data: <addr << 1> <sndlen> <rcvlen> <data>[sndlen]
- * in  data: <addr << 1> <sndlen> <rcvlen> <data>[rcvlen] */
-
-#define CMD_I2C_BITRATE     0x32
-/* out data: <default=0> */
-
-#endif
diff --git a/drivers/media/dvb/dvb-usb/umt-010.c b/drivers/media/dvb/dvb-usb/umt-010.c
deleted file mode 100644
index 9b04229..0000000
--- a/drivers/media/dvb/dvb-usb/umt-010.c
+++ /dev/null
@@ -1,151 +0,0 @@
-/* DVB USB framework compliant Linux driver for the HanfTek UMT-010 USB2.0
- * DVB-T receiver.
- *
- * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
- *
- *	This program is free software; you can redistribute it and/or modify it
- *	under the terms of the GNU General Public License as published by the Free
- *	Software Foundation, version 2.
- *
- * see Documentation/dvb/README.dvb-usb for more information
- */
-#include "dibusb.h"
-
-#include "mt352.h"
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-static int umt_mt352_demod_init(struct dvb_frontend *fe)
-{
-	static u8 mt352_clock_config[] = { 0x89, 0xb8, 0x2d };
-	static u8 mt352_reset[] = { 0x50, 0x80 };
-	static u8 mt352_mclk_ratio[] = { 0x8b, 0x00 };
-	static u8 mt352_adc_ctl_1_cfg[] = { 0x8E, 0x40 };
-	static u8 mt352_agc_cfg[] = { 0x67, 0x10, 0xa0 };
-
-	static u8 mt352_sec_agc_cfg1[] = { 0x6a, 0xff };
-	static u8 mt352_sec_agc_cfg2[] = { 0x6d, 0xff };
-	static u8 mt352_sec_agc_cfg3[] = { 0x70, 0x40 };
-	static u8 mt352_sec_agc_cfg4[] = { 0x7b, 0x03 };
-	static u8 mt352_sec_agc_cfg5[] = { 0x7d, 0x0f };
-
-	static u8 mt352_acq_ctl[] = { 0x53, 0x50 };
-	static u8 mt352_input_freq_1[] = { 0x56, 0x31, 0x06 };
-
-	mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config));
-	udelay(2000);
-	mt352_write(fe, mt352_reset, sizeof(mt352_reset));
-	mt352_write(fe, mt352_mclk_ratio, sizeof(mt352_mclk_ratio));
-
-	mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg));
-	mt352_write(fe, mt352_agc_cfg, sizeof(mt352_agc_cfg));
-
-	mt352_write(fe, mt352_sec_agc_cfg1, sizeof(mt352_sec_agc_cfg1));
-	mt352_write(fe, mt352_sec_agc_cfg2, sizeof(mt352_sec_agc_cfg2));
-	mt352_write(fe, mt352_sec_agc_cfg3, sizeof(mt352_sec_agc_cfg3));
-	mt352_write(fe, mt352_sec_agc_cfg4, sizeof(mt352_sec_agc_cfg4));
-	mt352_write(fe, mt352_sec_agc_cfg5, sizeof(mt352_sec_agc_cfg5));
-
-	mt352_write(fe, mt352_acq_ctl, sizeof(mt352_acq_ctl));
-	mt352_write(fe, mt352_input_freq_1, sizeof(mt352_input_freq_1));
-
-	return 0;
-}
-
-static int umt_mt352_frontend_attach(struct dvb_usb_adapter *adap)
-{
-	struct mt352_config umt_config;
-
-	memset(&umt_config,0,sizeof(struct mt352_config));
-	umt_config.demod_init = umt_mt352_demod_init;
-	umt_config.demod_address = 0xf;
-
-	adap->fe_adap[0].fe = dvb_attach(mt352_attach, &umt_config, &adap->dev->i2c_adap);
-
-	return 0;
-}
-
-static int umt_tuner_attach (struct dvb_usb_adapter *adap)
-{
-	dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x61, NULL, DVB_PLL_TUA6034);
-	return 0;
-}
-
-/* USB Driver stuff */
-static struct dvb_usb_device_properties umt_properties;
-
-static int umt_probe(struct usb_interface *intf,
-		const struct usb_device_id *id)
-{
-	if (0 == dvb_usb_device_init(intf, &umt_properties,
-				     THIS_MODULE, NULL, adapter_nr))
-		return 0;
-	return -EINVAL;
-}
-
-/* do not change the order of the ID table */
-static struct usb_device_id umt_table [] = {
-/* 00 */	{ USB_DEVICE(USB_VID_HANFTEK, USB_PID_HANFTEK_UMT_010_COLD) },
-/* 01 */	{ USB_DEVICE(USB_VID_HANFTEK, USB_PID_HANFTEK_UMT_010_WARM) },
-			{ }		/* Terminating entry */
-};
-MODULE_DEVICE_TABLE (usb, umt_table);
-
-static struct dvb_usb_device_properties umt_properties = {
-	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
-
-	.usb_ctrl = CYPRESS_FX2,
-	.firmware = "dvb-usb-umt-010-02.fw",
-
-	.num_adapters = 1,
-	.adapter = {
-		{
-		.num_frontends = 1,
-		.fe = {{
-			.streaming_ctrl   = dibusb2_0_streaming_ctrl,
-			.frontend_attach  = umt_mt352_frontend_attach,
-			.tuner_attach     = umt_tuner_attach,
-
-			/* parameter for the MPEG2-data transfer */
-			.stream = {
-				.type = USB_BULK,
-				.count = MAX_NO_URBS_FOR_DATA_STREAM,
-				.endpoint = 0x06,
-				.u = {
-					.bulk = {
-						.buffersize = 512,
-					}
-				}
-			},
-		}},
-			.size_of_priv     = sizeof(struct dibusb_state),
-		}
-	},
-	.power_ctrl       = dibusb_power_ctrl,
-
-	.i2c_algo         = &dibusb_i2c_algo,
-
-	.generic_bulk_ctrl_endpoint = 0x01,
-
-	.num_device_descs = 1,
-	.devices = {
-		{	"Hanftek UMT-010 DVB-T USB2.0",
-			{ &umt_table[0], NULL },
-			{ &umt_table[1], NULL },
-		},
-	}
-};
-
-static struct usb_driver umt_driver = {
-	.name		= "dvb_usb_umt_010",
-	.probe		= umt_probe,
-	.disconnect = dvb_usb_device_exit,
-	.id_table	= umt_table,
-};
-
-module_usb_driver(umt_driver);
-
-MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
-MODULE_DESCRIPTION("Driver for HanfTek UMT 010 USB2.0 DVB-T device");
-MODULE_VERSION("1.0");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/usb-urb.c b/drivers/media/dvb/dvb-usb/usb-urb.c
deleted file mode 100644
index d62ee0f..0000000
--- a/drivers/media/dvb/dvb-usb/usb-urb.c
+++ /dev/null
@@ -1,254 +0,0 @@
-/* usb-urb.c is part of the DVB USB library.
- *
- * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de)
- * see dvb-usb-init.c for copyright information.
- *
- * This file keeps functions for initializing and handling the
- * BULK and ISOC USB data transfers in a generic way.
- * Can be used for DVB-only and also, that's the plan, for
- * Hybrid USB devices (analog and DVB).
- */
-#include "dvb-usb-common.h"
-
-/* URB stuff for streaming */
-static void usb_urb_complete(struct urb *urb)
-{
-	struct usb_data_stream *stream = urb->context;
-	int ptype = usb_pipetype(urb->pipe);
-	int i;
-	u8 *b;
-
-	deb_uxfer("'%s' urb completed. status: %d, length: %d/%d, pack_num: %d, errors: %d\n",
-		ptype == PIPE_ISOCHRONOUS ? "isoc" : "bulk",
-		urb->status,urb->actual_length,urb->transfer_buffer_length,
-		urb->number_of_packets,urb->error_count);
-
-	switch (urb->status) {
-		case 0:         /* success */
-		case -ETIMEDOUT:    /* NAK */
-			break;
-		case -ECONNRESET:   /* kill */
-		case -ENOENT:
-		case -ESHUTDOWN:
-			return;
-		default:        /* error */
-			deb_ts("urb completition error %d.\n", urb->status);
-			break;
-	}
-
-	b = (u8 *) urb->transfer_buffer;
-	switch (ptype) {
-		case PIPE_ISOCHRONOUS:
-			for (i = 0; i < urb->number_of_packets; i++) {
-
-				if (urb->iso_frame_desc[i].status != 0)
-					deb_ts("iso frame descriptor has an error: %d\n",urb->iso_frame_desc[i].status);
-				else if (urb->iso_frame_desc[i].actual_length > 0)
-					stream->complete(stream, b + 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;
-			}
-			debug_dump(b,20,deb_uxfer);
-			break;
-		case PIPE_BULK:
-			if (urb->actual_length > 0)
-				stream->complete(stream, b, urb->actual_length);
-			break;
-		default:
-			err("unknown endpoint type in completition handler.");
-			return;
-	}
-	usb_submit_urb(urb,GFP_ATOMIC);
-}
-
-int usb_urb_kill(struct usb_data_stream *stream)
-{
-	int i;
-	for (i = 0; i < stream->urbs_submitted; i++) {
-		deb_ts("killing URB no. %d.\n",i);
-
-		/* stop the URB */
-		usb_kill_urb(stream->urb_list[i]);
-	}
-	stream->urbs_submitted = 0;
-	return 0;
-}
-
-int usb_urb_submit(struct usb_data_stream *stream)
-{
-	int i,ret;
-	for (i = 0; i < stream->urbs_initialized; i++) {
-		deb_ts("submitting URB no. %d\n",i);
-		if ((ret = usb_submit_urb(stream->urb_list[i],GFP_ATOMIC))) {
-			err("could not submit URB no. %d - get them all back",i);
-			usb_urb_kill(stream);
-			return ret;
-		}
-		stream->urbs_submitted++;
-	}
-	return 0;
-}
-
-static int usb_free_stream_buffers(struct usb_data_stream *stream)
-{
-	if (stream->state & USB_STATE_URB_BUF) {
-		while (stream->buf_num) {
-			stream->buf_num--;
-			deb_mem("freeing buffer %d\n",stream->buf_num);
-			usb_free_coherent(stream->udev, stream->buf_size,
-					  stream->buf_list[stream->buf_num],
-					  stream->dma_addr[stream->buf_num]);
-		}
-	}
-
-	stream->state &= ~USB_STATE_URB_BUF;
-
-	return 0;
-}
-
-static int usb_allocate_stream_buffers(struct usb_data_stream *stream, int num, unsigned long size)
-{
-	stream->buf_num = 0;
-	stream->buf_size = size;
-
-	deb_mem("all in all I will use %lu bytes for streaming\n",num*size);
-
-	for (stream->buf_num = 0; stream->buf_num < num; stream->buf_num++) {
-		deb_mem("allocating buffer %d\n",stream->buf_num);
-		if (( stream->buf_list[stream->buf_num] =
-					usb_alloc_coherent(stream->udev, size, GFP_ATOMIC,
-					&stream->dma_addr[stream->buf_num]) ) == NULL) {
-			deb_mem("not enough memory for urb-buffer allocation.\n");
-			usb_free_stream_buffers(stream);
-			return -ENOMEM;
-		}
-		deb_mem("buffer %d: %p (dma: %Lu)\n",
-			stream->buf_num,
-stream->buf_list[stream->buf_num], (long long)stream->dma_addr[stream->buf_num]);
-		memset(stream->buf_list[stream->buf_num],0,size);
-		stream->state |= USB_STATE_URB_BUF;
-	}
-	deb_mem("allocation successful\n");
-
-	return 0;
-}
-
-static int usb_bulk_urb_init(struct usb_data_stream *stream)
-{
-	int i, j;
-
-	if ((i = usb_allocate_stream_buffers(stream,stream->props.count,
-					stream->props.u.bulk.buffersize)) < 0)
-		return i;
-
-	/* allocate the URBs */
-	for (i = 0; i < stream->props.count; i++) {
-		stream->urb_list[i] = usb_alloc_urb(0, GFP_ATOMIC);
-		if (!stream->urb_list[i]) {
-			deb_mem("not enough memory for urb_alloc_urb!.\n");
-			for (j = 0; j < i; j++)
-				usb_free_urb(stream->urb_list[j]);
-			return -ENOMEM;
-		}
-		usb_fill_bulk_urb( stream->urb_list[i], stream->udev,
-				usb_rcvbulkpipe(stream->udev,stream->props.endpoint),
-				stream->buf_list[i],
-				stream->props.u.bulk.buffersize,
-				usb_urb_complete, stream);
-
-		stream->urb_list[i]->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
-		stream->urb_list[i]->transfer_dma = stream->dma_addr[i];
-		stream->urbs_initialized++;
-	}
-	return 0;
-}
-
-static int usb_isoc_urb_init(struct usb_data_stream *stream)
-{
-	int i,j;
-
-	if ((i = usb_allocate_stream_buffers(stream,stream->props.count,
-					stream->props.u.isoc.framesize*stream->props.u.isoc.framesperurb)) < 0)
-		return i;
-
-	/* allocate the URBs */
-	for (i = 0; i < stream->props.count; i++) {
-		struct urb *urb;
-		int frame_offset = 0;
-
-		stream->urb_list[i] = usb_alloc_urb(stream->props.u.isoc.framesperurb, GFP_ATOMIC);
-		if (!stream->urb_list[i]) {
-			deb_mem("not enough memory for urb_alloc_urb!\n");
-			for (j = 0; j < i; j++)
-				usb_free_urb(stream->urb_list[j]);
-			return -ENOMEM;
-		}
-
-		urb = stream->urb_list[i];
-
-		urb->dev = stream->udev;
-		urb->context = stream;
-		urb->complete = usb_urb_complete;
-		urb->pipe = usb_rcvisocpipe(stream->udev,stream->props.endpoint);
-		urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
-		urb->interval = stream->props.u.isoc.interval;
-		urb->number_of_packets = stream->props.u.isoc.framesperurb;
-		urb->transfer_buffer_length = stream->buf_size;
-		urb->transfer_buffer = stream->buf_list[i];
-		urb->transfer_dma = stream->dma_addr[i];
-
-		for (j = 0; j < stream->props.u.isoc.framesperurb; j++) {
-			urb->iso_frame_desc[j].offset = frame_offset;
-			urb->iso_frame_desc[j].length = stream->props.u.isoc.framesize;
-			frame_offset += stream->props.u.isoc.framesize;
-		}
-
-		stream->urbs_initialized++;
-	}
-	return 0;
-}
-
-int usb_urb_init(struct usb_data_stream *stream, struct usb_data_stream_properties *props)
-{
-	if (stream == NULL || props == NULL)
-		return -EINVAL;
-
-	memcpy(&stream->props, props, sizeof(*props));
-
-	usb_clear_halt(stream->udev,usb_rcvbulkpipe(stream->udev,stream->props.endpoint));
-
-	if (stream->complete == NULL) {
-		err("there is no data callback - this doesn't make sense.");
-		return -EINVAL;
-	}
-
-	switch (stream->props.type) {
-		case USB_BULK:
-			return usb_bulk_urb_init(stream);
-		case USB_ISOC:
-			return usb_isoc_urb_init(stream);
-		default:
-			err("unknown URB-type for data transfer.");
-			return -EINVAL;
-	}
-}
-
-int usb_urb_exit(struct usb_data_stream *stream)
-{
-	int i;
-
-	usb_urb_kill(stream);
-
-	for (i = 0; i < stream->urbs_initialized; i++) {
-		if (stream->urb_list[i] != NULL) {
-			deb_mem("freeing URB no. %d.\n",i);
-			/* free the URBs */
-			usb_free_urb(stream->urb_list[i]);
-		}
-	}
-	stream->urbs_initialized = 0;
-
-	usb_free_stream_buffers(stream);
-	return 0;
-}
diff --git a/drivers/media/dvb/dvb-usb/vp702x-fe.c b/drivers/media/dvb/dvb-usb/vp702x-fe.c
deleted file mode 100644
index 5eab468..0000000
--- a/drivers/media/dvb/dvb-usb/vp702x-fe.c
+++ /dev/null
@@ -1,379 +0,0 @@
-/* DVB frontend part of the Linux driver for the TwinhanDTV StarBox USB2.0
- * DVB-S receiver.
- *
- * Copyright (C) 2005 Ralph Metzler <rjkm@metzlerbros.de>
- *                    Metzler Brothers Systementwicklung GbR
- *
- * Copyright (C) 2005 Patrick Boettcher <patrick.boettcher@desy.de>
- *
- * Thanks to Twinhan who kindly provided hardware and information.
- *
- * This file can be removed soon, after the DST-driver is rewritten to provice
- * the frontend-controlling separately.
- *
- *	This program is free software; 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.
- *
- * see Documentation/dvb/README.dvb-usb for more information
- *
- */
-#include "vp702x.h"
-
-struct vp702x_fe_state {
-	struct dvb_frontend fe;
-	struct dvb_usb_device *d;
-
-	struct dvb_frontend_ops ops;
-
-	fe_sec_voltage_t voltage;
-	fe_sec_tone_mode_t tone_mode;
-
-	u8 lnb_buf[8];
-
-	u8 lock;
-	u8 sig;
-	u8 snr;
-
-	unsigned long next_status_check;
-	unsigned long status_check_interval;
-};
-
-static int vp702x_fe_refresh_state(struct vp702x_fe_state *st)
-{
-	struct vp702x_device_state *dst = st->d->priv;
-	u8 *buf;
-
-	if (time_after(jiffies, st->next_status_check)) {
-		mutex_lock(&dst->buf_mutex);
-		buf = dst->buf;
-
-		vp702x_usb_in_op(st->d, READ_STATUS, 0, 0, buf, 10);
-		st->lock = buf[4];
-
-		vp702x_usb_in_op(st->d, READ_TUNER_REG_REQ, 0x11, 0, buf, 1);
-		st->snr = buf[0];
-
-		vp702x_usb_in_op(st->d, READ_TUNER_REG_REQ, 0x15, 0, buf, 1);
-		st->sig = buf[0];
-
-		mutex_unlock(&dst->buf_mutex);
-		st->next_status_check = jiffies + (st->status_check_interval*HZ)/1000;
-	}
-	return 0;
-}
-
-static u8 vp702x_chksum(u8 *buf,int f, int count)
-{
-	u8 s = 0;
-	int i;
-	for (i = f; i < f+count; i++)
-		s += buf[i];
-	return ~s+1;
-}
-
-static int vp702x_fe_read_status(struct dvb_frontend* fe, fe_status_t *status)
-{
-	struct vp702x_fe_state *st = fe->demodulator_priv;
-	vp702x_fe_refresh_state(st);
-	deb_fe("%s\n",__func__);
-
-	if (st->lock == 0)
-		*status = FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI | FE_HAS_SIGNAL | FE_HAS_CARRIER;
-	else
-		*status = 0;
-
-	if (*status & FE_HAS_LOCK)
-		st->status_check_interval = 1000;
-	else
-		st->status_check_interval = 250;
-	return 0;
-}
-
-/* not supported by this Frontend */
-static int vp702x_fe_read_ber(struct dvb_frontend* fe, u32 *ber)
-{
-	struct vp702x_fe_state *st = fe->demodulator_priv;
-	vp702x_fe_refresh_state(st);
-	*ber = 0;
-	return 0;
-}
-
-/* not supported by this Frontend */
-static int vp702x_fe_read_unc_blocks(struct dvb_frontend* fe, u32 *unc)
-{
-	struct vp702x_fe_state *st = fe->demodulator_priv;
-	vp702x_fe_refresh_state(st);
-	*unc = 0;
-	return 0;
-}
-
-static int vp702x_fe_read_signal_strength(struct dvb_frontend* fe, u16 *strength)
-{
-	struct vp702x_fe_state *st = fe->demodulator_priv;
-	vp702x_fe_refresh_state(st);
-
-	*strength = (st->sig << 8) | st->sig;
-	return 0;
-}
-
-static int vp702x_fe_read_snr(struct dvb_frontend* fe, u16 *snr)
-{
-	u8 _snr;
-	struct vp702x_fe_state *st = fe->demodulator_priv;
-	vp702x_fe_refresh_state(st);
-
-	_snr = (st->snr & 0x1f) * 0xff / 0x1f;
-	*snr = (_snr << 8) | _snr;
-	return 0;
-}
-
-static int vp702x_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
-{
-	deb_fe("%s\n",__func__);
-	tune->min_delay_ms = 2000;
-	return 0;
-}
-
-static int vp702x_fe_set_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
-	struct vp702x_fe_state *st = fe->demodulator_priv;
-	struct vp702x_device_state *dst = st->d->priv;
-	u32 freq = fep->frequency/1000;
-	/*CalFrequency*/
-/*	u16 frequencyRef[16] = { 2, 4, 8, 16, 32, 64, 128, 256, 24, 5, 10, 20, 40, 80, 160, 320 }; */
-	u64 sr;
-	u8 *cmd;
-
-	mutex_lock(&dst->buf_mutex);
-
-	cmd = dst->buf;
-	memset(cmd, 0, 10);
-
-	cmd[0] = (freq >> 8) & 0x7f;
-	cmd[1] =  freq       & 0xff;
-	cmd[2] = 1; /* divrate == 4 -> frequencyRef[1] -> 1 here */
-
-	sr = (u64) (fep->symbol_rate/1000) << 20;
-	do_div(sr,88000);
-	cmd[3] = (sr >> 12) & 0xff;
-	cmd[4] = (sr >> 4)  & 0xff;
-	cmd[5] = (sr << 4)  & 0xf0;
-
-	deb_fe("setting frontend to: %u -> %u (%x) LNB-based GHz, symbolrate: %d -> %lu (%lx)\n",
-			fep->frequency, freq, freq, fep->symbol_rate,
-			(unsigned long) sr, (unsigned long) sr);
-
-/*	if (fep->inversion == INVERSION_ON)
-		cmd[6] |= 0x80; */
-
-	if (st->voltage == SEC_VOLTAGE_18)
-		cmd[6] |= 0x40;
-
-/*	if (fep->symbol_rate > 8000000)
-		cmd[6] |= 0x20;
-
-	if (fep->frequency < 1531000)
-		cmd[6] |= 0x04;
-
-	if (st->tone_mode == SEC_TONE_ON)
-		cmd[6] |= 0x01;*/
-
-	cmd[7] = vp702x_chksum(cmd,0,7);
-
-	st->status_check_interval = 250;
-	st->next_status_check = jiffies;
-
-	vp702x_usb_inout_op(st->d, cmd, 8, cmd, 10, 100);
-
-	if (cmd[2] == 0 && cmd[3] == 0)
-		deb_fe("tuning failed.\n");
-	else
-		deb_fe("tuning succeeded.\n");
-
-	mutex_unlock(&dst->buf_mutex);
-
-	return 0;
-}
-
-static int vp702x_fe_init(struct dvb_frontend *fe)
-{
-	struct vp702x_fe_state *st = fe->demodulator_priv;
-	deb_fe("%s\n",__func__);
-	vp702x_usb_in_op(st->d, RESET_TUNER, 0, 0, NULL, 0);
-	return 0;
-}
-
-static int vp702x_fe_sleep(struct dvb_frontend *fe)
-{
-	deb_fe("%s\n",__func__);
-	return 0;
-}
-
-static int vp702x_fe_send_diseqc_msg (struct dvb_frontend* fe,
-				    struct dvb_diseqc_master_cmd *m)
-{
-	u8 *cmd;
-	struct vp702x_fe_state *st = fe->demodulator_priv;
-	struct vp702x_device_state *dst = st->d->priv;
-
-	deb_fe("%s\n",__func__);
-
-	if (m->msg_len > 4)
-		return -EINVAL;
-
-	mutex_lock(&dst->buf_mutex);
-
-	cmd = dst->buf;
-	cmd[1] = SET_DISEQC_CMD;
-	cmd[2] = m->msg_len;
-	memcpy(&cmd[3], m->msg, m->msg_len);
-	cmd[7] = vp702x_chksum(cmd, 0, 7);
-
-	vp702x_usb_inout_op(st->d, cmd, 8, cmd, 10, 100);
-
-	if (cmd[2] == 0 && cmd[3] == 0)
-		deb_fe("diseqc cmd failed.\n");
-	else
-		deb_fe("diseqc cmd succeeded.\n");
-
-	mutex_unlock(&dst->buf_mutex);
-
-	return 0;
-}
-
-static int vp702x_fe_send_diseqc_burst (struct dvb_frontend* fe, fe_sec_mini_cmd_t burst)
-{
-	deb_fe("%s\n",__func__);
-	return 0;
-}
-
-static int vp702x_fe_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
-{
-	struct vp702x_fe_state *st = fe->demodulator_priv;
-	struct vp702x_device_state *dst = st->d->priv;
-	u8 *buf;
-
-	deb_fe("%s\n",__func__);
-
-	st->tone_mode = tone;
-
-	if (tone == SEC_TONE_ON)
-		st->lnb_buf[2] = 0x02;
-	else
-		st->lnb_buf[2] = 0x00;
-
-	st->lnb_buf[7] = vp702x_chksum(st->lnb_buf, 0, 7);
-
-	mutex_lock(&dst->buf_mutex);
-
-	buf = dst->buf;
-	memcpy(buf, st->lnb_buf, 8);
-
-	vp702x_usb_inout_op(st->d, buf, 8, buf, 10, 100);
-	if (buf[2] == 0 && buf[3] == 0)
-		deb_fe("set_tone cmd failed.\n");
-	else
-		deb_fe("set_tone cmd succeeded.\n");
-
-	mutex_unlock(&dst->buf_mutex);
-
-	return 0;
-}
-
-static int vp702x_fe_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t
-		voltage)
-{
-	struct vp702x_fe_state *st = fe->demodulator_priv;
-	struct vp702x_device_state *dst = st->d->priv;
-	u8 *buf;
-	deb_fe("%s\n",__func__);
-
-	st->voltage = voltage;
-
-	if (voltage != SEC_VOLTAGE_OFF)
-		st->lnb_buf[4] = 0x01;
-	else
-		st->lnb_buf[4] = 0x00;
-
-	st->lnb_buf[7] = vp702x_chksum(st->lnb_buf, 0, 7);
-
-	mutex_lock(&dst->buf_mutex);
-
-	buf = dst->buf;
-	memcpy(buf, st->lnb_buf, 8);
-
-	vp702x_usb_inout_op(st->d, buf, 8, buf, 10, 100);
-	if (buf[2] == 0 && buf[3] == 0)
-		deb_fe("set_voltage cmd failed.\n");
-	else
-		deb_fe("set_voltage cmd succeeded.\n");
-
-	mutex_unlock(&dst->buf_mutex);
-	return 0;
-}
-
-static void vp702x_fe_release(struct dvb_frontend* fe)
-{
-	struct vp702x_fe_state *st = fe->demodulator_priv;
-	kfree(st);
-}
-
-static struct dvb_frontend_ops vp702x_fe_ops;
-
-struct dvb_frontend * vp702x_fe_attach(struct dvb_usb_device *d)
-{
-	struct vp702x_fe_state *s = kzalloc(sizeof(struct vp702x_fe_state), GFP_KERNEL);
-	if (s == NULL)
-		goto error;
-
-	s->d = d;
-
-	memcpy(&s->fe.ops,&vp702x_fe_ops,sizeof(struct dvb_frontend_ops));
-	s->fe.demodulator_priv = s;
-
-	s->lnb_buf[1] = SET_LNB_POWER;
-	s->lnb_buf[3] = 0xff; /* 0=tone burst, 2=data burst, ff=off */
-
-	return &s->fe;
-error:
-	return NULL;
-}
-
-
-static struct dvb_frontend_ops vp702x_fe_ops = {
-	.delsys = { SYS_DVBS },
-	.info = {
-		.name           = "Twinhan DST-like frontend (VP7021/VP7020) DVB-S",
-		.frequency_min       = 950000,
-		.frequency_max       = 2150000,
-		.frequency_stepsize  = 1000,   /* kHz for QPSK frontends */
-		.frequency_tolerance = 0,
-		.symbol_rate_min     = 1000000,
-		.symbol_rate_max     = 45000000,
-		.symbol_rate_tolerance = 500,  /* ppm */
-		.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_FEC_AUTO
-	},
-	.release = vp702x_fe_release,
-
-	.init  = vp702x_fe_init,
-	.sleep = vp702x_fe_sleep,
-
-	.set_frontend = vp702x_fe_set_frontend,
-	.get_tune_settings = vp702x_fe_get_tune_settings,
-
-	.read_status = vp702x_fe_read_status,
-	.read_ber = vp702x_fe_read_ber,
-	.read_signal_strength = vp702x_fe_read_signal_strength,
-	.read_snr = vp702x_fe_read_snr,
-	.read_ucblocks = vp702x_fe_read_unc_blocks,
-
-	.diseqc_send_master_cmd = vp702x_fe_send_diseqc_msg,
-	.diseqc_send_burst = vp702x_fe_send_diseqc_burst,
-	.set_tone = vp702x_fe_set_tone,
-	.set_voltage = vp702x_fe_set_voltage,
-};
diff --git a/drivers/media/dvb/dvb-usb/vp702x.c b/drivers/media/dvb/dvb-usb/vp702x.c
deleted file mode 100644
index 07c673a..0000000
--- a/drivers/media/dvb/dvb-usb/vp702x.c
+++ /dev/null
@@ -1,444 +0,0 @@
-/* DVB USB compliant Linux driver for the TwinhanDTV StarBox USB2.0 DVB-S
- * receiver.
- *
- * Copyright (C) 2005 Ralph Metzler <rjkm@metzlerbros.de>
- *                    Metzler Brothers Systementwicklung GbR
- *
- * Copyright (C) 2005 Patrick Boettcher <patrick.boettcher@desy.de>
- *
- * Thanks to Twinhan who kindly provided hardware and information.
- *
- *	This program is free software; you can redistribute it and/or modify it
- *	under the terms of the GNU General Public License as published by the Free
- *	Software Foundation, version 2.
- *
- * see Documentation/dvb/README.dvb-usb for more information
- */
-#include "vp702x.h"
-#include <linux/mutex.h>
-
-/* debug */
-int dvb_usb_vp702x_debug;
-module_param_named(debug,dvb_usb_vp702x_debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS);
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-struct vp702x_adapter_state {
-	int pid_filter_count;
-	int pid_filter_can_bypass;
-	u8  pid_filter_state;
-};
-
-static int vp702x_usb_in_op_unlocked(struct dvb_usb_device *d, u8 req,
-				     u16 value, u16 index, u8 *b, int blen)
-{
-	int ret;
-
-	ret = usb_control_msg(d->udev,
-		usb_rcvctrlpipe(d->udev, 0),
-		req,
-		USB_TYPE_VENDOR | USB_DIR_IN,
-		value, index, b, blen,
-		2000);
-
-	if (ret < 0) {
-		warn("usb in operation failed. (%d)", ret);
-		ret = -EIO;
-	} else
-		ret = 0;
-
-
-	deb_xfer("in: req. %02x, val: %04x, ind: %04x, buffer: ",req,value,index);
-	debug_dump(b,blen,deb_xfer);
-
-	return ret;
-}
-
-int vp702x_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value,
-			    u16 index, u8 *b, int blen)
-{
-	int ret;
-
-	mutex_lock(&d->usb_mutex);
-	ret = vp702x_usb_in_op_unlocked(d, req, value, index, b, blen);
-	mutex_unlock(&d->usb_mutex);
-
-	return ret;
-}
-
-int vp702x_usb_out_op_unlocked(struct dvb_usb_device *d, u8 req, u16 value,
-				      u16 index, u8 *b, int blen)
-{
-	int ret;
-	deb_xfer("out: req. %02x, val: %04x, ind: %04x, buffer: ",req,value,index);
-	debug_dump(b,blen,deb_xfer);
-
-	if ((ret = usb_control_msg(d->udev,
-			usb_sndctrlpipe(d->udev,0),
-			req,
-			USB_TYPE_VENDOR | USB_DIR_OUT,
-			value,index,b,blen,
-			2000)) != blen) {
-		warn("usb out operation failed. (%d)",ret);
-		return -EIO;
-	} else
-		return 0;
-}
-
-int vp702x_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value,
-			     u16 index, u8 *b, int blen)
-{
-	int ret;
-
-	mutex_lock(&d->usb_mutex);
-	ret = vp702x_usb_out_op_unlocked(d, req, value, index, b, blen);
-	mutex_unlock(&d->usb_mutex);
-
-	return ret;
-}
-
-int vp702x_usb_inout_op(struct dvb_usb_device *d, u8 *o, int olen, u8 *i, int ilen, int msec)
-{
-	int ret;
-
-	if ((ret = mutex_lock_interruptible(&d->usb_mutex)))
-		return ret;
-
-	ret = vp702x_usb_out_op_unlocked(d, REQUEST_OUT, 0, 0, o, olen);
-	msleep(msec);
-	ret = vp702x_usb_in_op_unlocked(d, REQUEST_IN, 0, 0, i, ilen);
-
-	mutex_unlock(&d->usb_mutex);
-	return ret;
-}
-
-static int vp702x_usb_inout_cmd(struct dvb_usb_device *d, u8 cmd, u8 *o,
-				int olen, u8 *i, int ilen, int msec)
-{
-	struct vp702x_device_state *st = d->priv;
-	int ret = 0;
-	u8 *buf;
-	int buflen = max(olen + 2, ilen + 1);
-
-	ret = mutex_lock_interruptible(&st->buf_mutex);
-	if (ret < 0)
-		return ret;
-
-	if (buflen > st->buf_len) {
-		buf = kmalloc(buflen, GFP_KERNEL);
-		if (!buf) {
-			mutex_unlock(&st->buf_mutex);
-			return -ENOMEM;
-		}
-		info("successfully reallocated a bigger buffer");
-		kfree(st->buf);
-		st->buf = buf;
-		st->buf_len = buflen;
-	} else {
-		buf = st->buf;
-	}
-
-	buf[0] = 0x00;
-	buf[1] = cmd;
-	memcpy(&buf[2], o, olen);
-
-	ret = vp702x_usb_inout_op(d, buf, olen+2, buf, ilen+1, msec);
-
-	if (ret == 0)
-		memcpy(i, &buf[1], ilen);
-	mutex_unlock(&st->buf_mutex);
-
-	return ret;
-}
-
-static int vp702x_set_pld_mode(struct dvb_usb_adapter *adap, u8 bypass)
-{
-	int ret;
-	struct vp702x_device_state *st = adap->dev->priv;
-	u8 *buf;
-
-	mutex_lock(&st->buf_mutex);
-
-	buf = st->buf;
-	memset(buf, 0, 16);
-
-	ret = vp702x_usb_in_op(adap->dev, 0xe0, (bypass << 8) | 0x0e,
-			0, buf, 16);
-	mutex_unlock(&st->buf_mutex);
-	return ret;
-}
-
-static int vp702x_set_pld_state(struct dvb_usb_adapter *adap, u8 state)
-{
-	int ret;
-	struct vp702x_device_state *st = adap->dev->priv;
-	u8 *buf;
-
-	mutex_lock(&st->buf_mutex);
-
-	buf = st->buf;
-	memset(buf, 0, 16);
-	ret = vp702x_usb_in_op(adap->dev, 0xe0, (state << 8) | 0x0f,
-			0, buf, 16);
-
-	mutex_unlock(&st->buf_mutex);
-
-	return ret;
-}
-
-static int vp702x_set_pid(struct dvb_usb_adapter *adap, u16 pid, u8 id, int onoff)
-{
-	struct vp702x_adapter_state *st = adap->priv;
-	struct vp702x_device_state *dst = adap->dev->priv;
-	u8 *buf;
-
-	if (onoff)
-		st->pid_filter_state |=  (1 << id);
-	else {
-		st->pid_filter_state &= ~(1 << id);
-		pid = 0xffff;
-	}
-
-	id = 0x10 + id*2;
-
-	vp702x_set_pld_state(adap, st->pid_filter_state);
-
-	mutex_lock(&dst->buf_mutex);
-
-	buf = dst->buf;
-	memset(buf, 0, 16);
-	vp702x_usb_in_op(adap->dev, 0xe0, (((pid >> 8) & 0xff) << 8) | (id), 0, buf, 16);
-	vp702x_usb_in_op(adap->dev, 0xe0, (((pid     ) & 0xff) << 8) | (id+1), 0, buf, 16);
-
-	mutex_unlock(&dst->buf_mutex);
-
-	return 0;
-}
-
-
-static int vp702x_init_pid_filter(struct dvb_usb_adapter *adap)
-{
-	struct vp702x_adapter_state *st = adap->priv;
-	struct vp702x_device_state *dst = adap->dev->priv;
-	int i;
-	u8 *b;
-
-	st->pid_filter_count = 8;
-	st->pid_filter_can_bypass = 1;
-	st->pid_filter_state = 0x00;
-
-	vp702x_set_pld_mode(adap, 1); /* bypass */
-
-	for (i = 0; i < st->pid_filter_count; i++)
-		vp702x_set_pid(adap, 0xffff, i, 1);
-
-	mutex_lock(&dst->buf_mutex);
-	b = dst->buf;
-	memset(b, 0, 10);
-	vp702x_usb_in_op(adap->dev, 0xb5, 3, 0, b, 10);
-	vp702x_usb_in_op(adap->dev, 0xb5, 0, 0, b, 10);
-	vp702x_usb_in_op(adap->dev, 0xb5, 1, 0, b, 10);
-	mutex_unlock(&dst->buf_mutex);
-	/*vp702x_set_pld_mode(d, 0); // filter */
-
-	return 0;
-}
-
-static int vp702x_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
-{
-	return 0;
-}
-
-/* keys for the enclosed remote control */
-static struct rc_map_table rc_map_vp702x_table[] = {
-	{ 0x0001, KEY_1 },
-	{ 0x0002, KEY_2 },
-};
-
-/* remote control stuff (does not work with my box) */
-static int vp702x_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
-{
-	u8 *key;
-	int i;
-
-/* remove the following return to enabled remote querying */
-	return 0;
-
-	key = kmalloc(10, GFP_KERNEL);
-	if (!key)
-		return -ENOMEM;
-
-	vp702x_usb_in_op(d,READ_REMOTE_REQ,0,0,key,10);
-
-	deb_rc("remote query key: %x %d\n",key[1],key[1]);
-
-	if (key[1] == 0x44) {
-		*state = REMOTE_NO_KEY_PRESSED;
-		kfree(key);
-		return 0;
-	}
-
-	for (i = 0; i < ARRAY_SIZE(rc_map_vp702x_table); i++)
-		if (rc5_custom(&rc_map_vp702x_table[i]) == key[1]) {
-			*state = REMOTE_KEY_PRESSED;
-			*event = rc_map_vp702x_table[i].keycode;
-			break;
-		}
-	kfree(key);
-	return 0;
-}
-
-
-static int vp702x_read_mac_addr(struct dvb_usb_device *d,u8 mac[6])
-{
-	u8 i, *buf;
-	struct vp702x_device_state *st = d->priv;
-
-	mutex_lock(&st->buf_mutex);
-	buf = st->buf;
-	for (i = 6; i < 12; i++)
-		vp702x_usb_in_op(d, READ_EEPROM_REQ, i, 1, &buf[i - 6], 1);
-
-	memcpy(mac, buf, 6);
-	mutex_unlock(&st->buf_mutex);
-	return 0;
-}
-
-static int vp702x_frontend_attach(struct dvb_usb_adapter *adap)
-{
-	u8 buf[10] = { 0 };
-
-	vp702x_usb_out_op(adap->dev, SET_TUNER_POWER_REQ, 0, 7, NULL, 0);
-
-	if (vp702x_usb_inout_cmd(adap->dev, GET_SYSTEM_STRING, NULL, 0,
-				   buf, 10, 10))
-		return -EIO;
-
-	buf[9] = '\0';
-	info("system string: %s",&buf[1]);
-
-	vp702x_init_pid_filter(adap);
-
-	adap->fe_adap[0].fe = vp702x_fe_attach(adap->dev);
-	vp702x_usb_out_op(adap->dev, SET_TUNER_POWER_REQ, 1, 7, NULL, 0);
-
-	return 0;
-}
-
-static struct dvb_usb_device_properties vp702x_properties;
-
-static int vp702x_usb_probe(struct usb_interface *intf,
-		const struct usb_device_id *id)
-{
-	struct dvb_usb_device *d;
-	struct vp702x_device_state *st;
-	int ret;
-
-	ret = dvb_usb_device_init(intf, &vp702x_properties,
-				   THIS_MODULE, &d, adapter_nr);
-	if (ret)
-		goto out;
-
-	st = d->priv;
-	st->buf_len = 16;
-	st->buf = kmalloc(st->buf_len, GFP_KERNEL);
-	if (!st->buf) {
-		ret = -ENOMEM;
-		dvb_usb_device_exit(intf);
-		goto out;
-	}
-	mutex_init(&st->buf_mutex);
-
-out:
-	return ret;
-
-}
-
-static void vp702x_usb_disconnect(struct usb_interface *intf)
-{
-	struct dvb_usb_device *d = usb_get_intfdata(intf);
-	struct vp702x_device_state *st = d->priv;
-	mutex_lock(&st->buf_mutex);
-	kfree(st->buf);
-	mutex_unlock(&st->buf_mutex);
-	dvb_usb_device_exit(intf);
-}
-
-static struct usb_device_id vp702x_usb_table [] = {
-	    { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7021_COLD) },
-//	    { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7020_COLD) },
-//	    { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7020_WARM) },
-	    { 0 },
-};
-MODULE_DEVICE_TABLE(usb, vp702x_usb_table);
-
-static struct dvb_usb_device_properties vp702x_properties = {
-	.usb_ctrl = CYPRESS_FX2,
-	.firmware            = "dvb-usb-vp702x-02.fw",
-	.no_reconnect        = 1,
-
-	.size_of_priv     = sizeof(struct vp702x_device_state),
-
-	.num_adapters = 1,
-	.adapter = {
-		{
-		.num_frontends = 1,
-		.fe = {{
-			.caps             = DVB_USB_ADAP_RECEIVES_204_BYTE_TS,
-
-			.streaming_ctrl   = vp702x_streaming_ctrl,
-			.frontend_attach  = vp702x_frontend_attach,
-
-			/* parameter for the MPEG2-data transfer */
-			.stream = {
-				.type = USB_BULK,
-				.count = 10,
-				.endpoint = 0x02,
-				.u = {
-					.bulk = {
-						.buffersize = 4096,
-					}
-				}
-			},
-		}},
-			.size_of_priv     = sizeof(struct vp702x_adapter_state),
-		}
-	},
-	.read_mac_address = vp702x_read_mac_addr,
-
-	.rc.legacy = {
-		.rc_map_table       = rc_map_vp702x_table,
-		.rc_map_size  = ARRAY_SIZE(rc_map_vp702x_table),
-		.rc_interval      = 400,
-		.rc_query         = vp702x_rc_query,
-	},
-
-	.num_device_descs = 1,
-	.devices = {
-		{ .name = "TwinhanDTV StarBox DVB-S USB2.0 (VP7021)",
-		  .cold_ids = { &vp702x_usb_table[0], NULL },
-		  .warm_ids = { NULL },
-		},
-/*		{ .name = "TwinhanDTV StarBox DVB-S USB2.0 (VP7020)",
-		  .cold_ids = { &vp702x_usb_table[2], NULL },
-		  .warm_ids = { &vp702x_usb_table[3], NULL },
-		},
-*/		{ NULL },
-	}
-};
-
-/* usb specific object needed to register this driver with the usb subsystem */
-static struct usb_driver vp702x_usb_driver = {
-	.name		= "dvb_usb_vp702x",
-	.probe		= vp702x_usb_probe,
-	.disconnect	= vp702x_usb_disconnect,
-	.id_table	= vp702x_usb_table,
-};
-
-module_usb_driver(vp702x_usb_driver);
-
-MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
-MODULE_DESCRIPTION("Driver for Twinhan StarBox DVB-S USB2.0 and clones");
-MODULE_VERSION("1.0");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/vp702x.h b/drivers/media/dvb/dvb-usb/vp702x.h
deleted file mode 100644
index 20b9005..0000000
--- a/drivers/media/dvb/dvb-usb/vp702x.h
+++ /dev/null
@@ -1,113 +0,0 @@
-#ifndef _DVB_USB_VP7021_H_
-#define _DVB_USB_VP7021_H_
-
-#define DVB_USB_LOG_PREFIX "vp702x"
-#include "dvb-usb.h"
-
-extern int dvb_usb_vp702x_debug;
-#define deb_info(args...) dprintk(dvb_usb_vp702x_debug,0x01,args)
-#define deb_xfer(args...) dprintk(dvb_usb_vp702x_debug,0x02,args)
-#define deb_rc(args...)   dprintk(dvb_usb_vp702x_debug,0x04,args)
-#define deb_fe(args...)   dprintk(dvb_usb_vp702x_debug,0x08,args)
-
-/* commands are read and written with USB control messages */
-
-/* consecutive read/write operation */
-#define REQUEST_OUT		0xB2
-#define REQUEST_IN		0xB3
-
-/* the out-buffer of these consecutive operations contain sub-commands when b[0] = 0
- * request: 0xB2; i: 0; v: 0; b[0] = 0, b[1] = subcmd, additional buffer
- * the returning buffer looks as follows
- * request: 0xB3; i: 0; v: 0; b[0] = 0xB3, additional buffer */
-
-#define GET_TUNER_STATUS	0x05
-/* additional in buffer:
- * 0   1   2    3              4   5   6               7       8
- * N/A N/A 0x05 signal-quality N/A N/A signal-strength lock==0 N/A */
-
-#define GET_SYSTEM_STRING	0x06
-/* additional in buffer:
- * 0   1   2   3   4   5   6   7   8
- * N/A 'U' 'S' 'B' '7' '0' '2' 'X' N/A */
-
-#define SET_DISEQC_CMD		0x08
-/* additional out buffer:
- * 0    1  2  3  4
- * len  X1 X2 X3 X4
- * additional in buffer:
- * 0   1 2
- * N/A 0 0   b[1] == b[2] == 0 -> success, failure otherwise */
-
-#define SET_LNB_POWER		0x09
-/* additional out buffer:
- * 0    1    2
- * 0x00 0xff 1 = on, 0 = off
- * additional in buffer:
- * 0   1 2
- * N/A 0 0   b[1] == b[2] == 0 -> success failure otherwise */
-
-#define GET_MAC_ADDRESS		0x0A
-/* #define GET_MAC_ADDRESS   0x0B */
-/* additional in buffer:
- * 0   1   2            3    4    5    6    7    8
- * N/A N/A 0x0A or 0x0B MAC0 MAC1 MAC2 MAC3 MAC4 MAC5 */
-
-#define SET_PID_FILTER		0x11
-/* additional in buffer:
- * 0        1        ... 14       15       16
- * PID0_MSB PID0_LSB ... PID7_MSB PID7_LSB PID_active (bits) */
-
-/* request: 0xB2; i: 0; v: 0;
- * b[0] != 0 -> tune and lock a channel
- * 0     1     2       3      4      5      6    7
- * freq0 freq1 divstep srate0 srate1 srate2 flag chksum
- */
-
-/* one direction requests */
-#define READ_REMOTE_REQ		0xB4
-/* IN  i: 0; v: 0; b[0] == request, b[1] == key */
-
-#define READ_PID_NUMBER_REQ	0xB5
-/* IN  i: 0; v: 0; b[0] == request, b[1] == 0, b[2] = pid number */
-
-#define WRITE_EEPROM_REQ	0xB6
-/* OUT i: offset; v: value to write; no extra buffer */
-
-#define READ_EEPROM_REQ		0xB7
-/* IN  i: bufferlen; v: offset; buffer with bufferlen bytes */
-
-#define READ_STATUS		0xB8
-/* IN  i: 0; v: 0; bufferlen 10 */
-
-#define READ_TUNER_REG_REQ	0xB9
-/* IN  i: 0; v: register; b[0] = value */
-
-#define READ_FX2_REG_REQ	0xBA
-/* IN  i: offset; v: 0; b[0] = value */
-
-#define WRITE_FX2_REG_REQ	0xBB
-/* OUT i: offset; v: value to write; 1 byte extra buffer */
-
-#define SET_TUNER_POWER_REQ	0xBC
-/* IN  i: 0 = power off, 1 = power on */
-
-#define WRITE_TUNER_REG_REQ	0xBD
-/* IN  i: register, v: value to write, no extra buffer */
-
-#define RESET_TUNER		0xBE
-/* IN  i: 0, v: 0, no extra buffer */
-
-struct vp702x_device_state {
-	struct mutex buf_mutex;
-	int buf_len;
-	u8 *buf;
-};
-
-
-extern struct dvb_frontend * vp702x_fe_attach(struct dvb_usb_device *d);
-
-extern int vp702x_usb_inout_op(struct dvb_usb_device *d, u8 *o, int olen, u8 *i, int ilen, int msec);
-extern int vp702x_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen);
-
-#endif
diff --git a/drivers/media/dvb/dvb-usb/vp7045-fe.c b/drivers/media/dvb/dvb-usb/vp7045-fe.c
deleted file mode 100644
index b8825b1..0000000
--- a/drivers/media/dvb/dvb-usb/vp7045-fe.c
+++ /dev/null
@@ -1,190 +0,0 @@
-/* DVB frontend part of the Linux driver for TwinhanDTV Alpha/MagicBoxII USB2.0
- * DVB-T receiver.
- *
- * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
- *
- * Thanks to Twinhan who kindly provided hardware and information.
- *
- *	This program is free software; you can redistribute it and/or modify it
- *	under the terms of the GNU General Public License as published by the Free
- *	Software Foundation, version 2.
- *
- * see Documentation/dvb/README.dvb-usb for more information
- *
- */
-#include "vp7045.h"
-
-/* It is a Zarlink MT352 within a Samsung Tuner (DNOS404ZH102A) - 040929 - AAT
- *
- * Programming is hidden inside the firmware, so set_frontend is very easy.
- * Even though there is a Firmware command that one can use to access the demod
- * via its registers. This is used for status information.
- */
-
-struct vp7045_fe_state {
-	struct dvb_frontend fe;
-	struct dvb_usb_device *d;
-};
-
-static int vp7045_fe_read_status(struct dvb_frontend* fe, fe_status_t *status)
-{
-	struct vp7045_fe_state *state = fe->demodulator_priv;
-	u8 s0 = vp7045_read_reg(state->d,0x00),
-	   s1 = vp7045_read_reg(state->d,0x01),
-	   s3 = vp7045_read_reg(state->d,0x03);
-
-	*status = 0;
-	if (s0 & (1 << 4))
-		*status |= FE_HAS_CARRIER;
-	if (s0 & (1 << 1))
-		*status |= FE_HAS_VITERBI;
-	if (s0 & (1 << 5))
-		*status |= FE_HAS_LOCK;
-	if (s1 & (1 << 1))
-		*status |= FE_HAS_SYNC;
-	if (s3 & (1 << 6))
-		*status |= FE_HAS_SIGNAL;
-
-	if ((*status & (FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC)) !=
-			(FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC))
-		*status &= ~FE_HAS_LOCK;
-
-	return 0;
-}
-
-static int vp7045_fe_read_ber(struct dvb_frontend* fe, u32 *ber)
-{
-	struct vp7045_fe_state *state = fe->demodulator_priv;
-	*ber = (vp7045_read_reg(state->d, 0x0D) << 16) |
-	       (vp7045_read_reg(state->d, 0x0E) << 8) |
-		vp7045_read_reg(state->d, 0x0F);
-	return 0;
-}
-
-static int vp7045_fe_read_unc_blocks(struct dvb_frontend* fe, u32 *unc)
-{
-	struct vp7045_fe_state *state = fe->demodulator_priv;
-	*unc = (vp7045_read_reg(state->d, 0x10) << 8) |
-		    vp7045_read_reg(state->d, 0x11);
-	return 0;
-}
-
-static int vp7045_fe_read_signal_strength(struct dvb_frontend* fe, u16 *strength)
-{
-	struct vp7045_fe_state *state = fe->demodulator_priv;
-	u16 signal = (vp7045_read_reg(state->d, 0x14) << 8) |
-		vp7045_read_reg(state->d, 0x15);
-
-	*strength = ~signal;
-	return 0;
-}
-
-static int vp7045_fe_read_snr(struct dvb_frontend* fe, u16 *snr)
-{
-	struct vp7045_fe_state *state = fe->demodulator_priv;
-	u8 _snr = vp7045_read_reg(state->d, 0x09);
-	*snr = (_snr << 8) | _snr;
-	return 0;
-}
-
-static int vp7045_fe_init(struct dvb_frontend* fe)
-{
-	return 0;
-}
-
-static int vp7045_fe_sleep(struct dvb_frontend* fe)
-{
-	return 0;
-}
-
-static int vp7045_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
-{
-	tune->min_delay_ms = 800;
-	return 0;
-}
-
-static int vp7045_fe_set_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
-	struct vp7045_fe_state *state = fe->demodulator_priv;
-	u8 buf[5];
-	u32 freq = fep->frequency / 1000;
-
-	buf[0] = (freq >> 16) & 0xff;
-	buf[1] = (freq >>  8) & 0xff;
-	buf[2] =  freq        & 0xff;
-	buf[3] = 0;
-
-	switch (fep->bandwidth_hz) {
-	case 8000000:
-		buf[4] = 8;
-		break;
-	case 7000000:
-		buf[4] = 7;
-		break;
-	case 6000000:
-		buf[4] = 6;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	vp7045_usb_op(state->d,LOCK_TUNER_COMMAND,buf,5,NULL,0,200);
-	return 0;
-}
-
-static void vp7045_fe_release(struct dvb_frontend* fe)
-{
-	struct vp7045_fe_state *state = fe->demodulator_priv;
-	kfree(state);
-}
-
-static struct dvb_frontend_ops vp7045_fe_ops;
-
-struct dvb_frontend * vp7045_fe_attach(struct dvb_usb_device *d)
-{
-	struct vp7045_fe_state *s = kzalloc(sizeof(struct vp7045_fe_state), GFP_KERNEL);
-	if (s == NULL)
-		goto error;
-
-	s->d = d;
-	memcpy(&s->fe.ops, &vp7045_fe_ops, sizeof(struct dvb_frontend_ops));
-	s->fe.demodulator_priv = s;
-
-	return &s->fe;
-error:
-	return NULL;
-}
-
-
-static struct dvb_frontend_ops vp7045_fe_ops = {
-	.delsys = { SYS_DVBT },
-	.info = {
-		.name			= "Twinhan VP7045/46 USB DVB-T",
-		.frequency_min		= 44250000,
-		.frequency_max		= 867250000,
-		.frequency_stepsize	= 1000,
-		.caps = FE_CAN_INVERSION_AUTO |
-				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_FEC_AUTO |
-				FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
-				FE_CAN_TRANSMISSION_MODE_AUTO |
-				FE_CAN_GUARD_INTERVAL_AUTO |
-				FE_CAN_RECOVER |
-				FE_CAN_HIERARCHY_AUTO,
-	},
-
-	.release = vp7045_fe_release,
-
-	.init = vp7045_fe_init,
-	.sleep = vp7045_fe_sleep,
-
-	.set_frontend = vp7045_fe_set_frontend,
-	.get_tune_settings = vp7045_fe_get_tune_settings,
-
-	.read_status = vp7045_fe_read_status,
-	.read_ber = vp7045_fe_read_ber,
-	.read_signal_strength = vp7045_fe_read_signal_strength,
-	.read_snr = vp7045_fe_read_snr,
-	.read_ucblocks = vp7045_fe_read_unc_blocks,
-};
diff --git a/drivers/media/dvb/dvb-usb/vp7045.c b/drivers/media/dvb/dvb-usb/vp7045.c
deleted file mode 100644
index d750724..0000000
--- a/drivers/media/dvb/dvb-usb/vp7045.c
+++ /dev/null
@@ -1,302 +0,0 @@
-/* DVB USB compliant Linux driver for the
- *  - TwinhanDTV Alpha/MagicBoxII USB2.0 DVB-T receiver
- *  - DigitalNow TinyUSB2 DVB-t receiver
- *
- * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
- *
- * Thanks to Twinhan who kindly provided hardware and information.
- *
- *	This program is free software; you can redistribute it and/or modify it
- *	under the terms of the GNU General Public License as published by the Free
- *	Software Foundation, version 2.
- *
- * see Documentation/dvb/README.dvb-usb for more information
- */
-#include "vp7045.h"
-
-/* debug */
-static int dvb_usb_vp7045_debug;
-module_param_named(debug,dvb_usb_vp7045_debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS);
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-#define deb_info(args...) dprintk(dvb_usb_vp7045_debug,0x01,args)
-#define deb_xfer(args...) dprintk(dvb_usb_vp7045_debug,0x02,args)
-#define deb_rc(args...)   dprintk(dvb_usb_vp7045_debug,0x04,args)
-
-int vp7045_usb_op(struct dvb_usb_device *d, u8 cmd, u8 *out, int outlen, u8 *in, int inlen, int msec)
-{
-	int ret = 0;
-	u8 *buf = d->priv;
-
-	buf[0] = cmd;
-
-	if (outlen > 19)
-		outlen = 19;
-
-	if (inlen > 11)
-		inlen = 11;
-
-	ret = mutex_lock_interruptible(&d->usb_mutex);
-	if (ret)
-		return ret;
-
-	if (out != NULL && outlen > 0)
-		memcpy(&buf[1], out, outlen);
-
-	deb_xfer("out buffer: ");
-	debug_dump(buf, outlen+1, deb_xfer);
-
-
-	if (usb_control_msg(d->udev,
-			usb_sndctrlpipe(d->udev,0),
-			TH_COMMAND_OUT, USB_TYPE_VENDOR | USB_DIR_OUT, 0, 0,
-			buf, 20, 2000) != 20) {
-		err("USB control message 'out' went wrong.");
-		ret = -EIO;
-		goto unlock;
-	}
-
-	msleep(msec);
-
-	if (usb_control_msg(d->udev,
-			usb_rcvctrlpipe(d->udev,0),
-			TH_COMMAND_IN, USB_TYPE_VENDOR | USB_DIR_IN, 0, 0,
-			buf, 12, 2000) != 12) {
-		err("USB control message 'in' went wrong.");
-		ret = -EIO;
-		goto unlock;
-	}
-
-	deb_xfer("in buffer: ");
-	debug_dump(buf, 12, deb_xfer);
-
-	if (in != NULL && inlen > 0)
-		memcpy(in, &buf[1], inlen);
-
-unlock:
-	mutex_unlock(&d->usb_mutex);
-
-	return ret;
-}
-
-u8 vp7045_read_reg(struct dvb_usb_device *d, u8 reg)
-{
-	u8 obuf[2] = { 0 },v;
-	obuf[1] = reg;
-
-	vp7045_usb_op(d,TUNER_REG_READ,obuf,2,&v,1,30);
-
-	return v;
-}
-
-static int vp7045_power_ctrl(struct dvb_usb_device *d, int onoff)
-{
-	u8 v = onoff;
-	return vp7045_usb_op(d,SET_TUNER_POWER,&v,1,NULL,0,150);
-}
-
-/* remote control stuff */
-
-/* The keymapping struct. Somehow this should be loaded to the driver, but
- * currently it is hardcoded. */
-static struct rc_map_table rc_map_vp7045_table[] = {
-	{ 0x0016, KEY_POWER },
-	{ 0x0010, KEY_MUTE },
-	{ 0x0003, KEY_1 },
-	{ 0x0001, KEY_2 },
-	{ 0x0006, KEY_3 },
-	{ 0x0009, KEY_4 },
-	{ 0x001d, KEY_5 },
-	{ 0x001f, KEY_6 },
-	{ 0x000d, KEY_7 },
-	{ 0x0019, KEY_8 },
-	{ 0x001b, KEY_9 },
-	{ 0x0015, KEY_0 },
-	{ 0x0005, KEY_CHANNELUP },
-	{ 0x0002, KEY_CHANNELDOWN },
-	{ 0x001e, KEY_VOLUMEUP },
-	{ 0x000a, KEY_VOLUMEDOWN },
-	{ 0x0011, KEY_RECORD },
-	{ 0x0017, KEY_FAVORITES }, /* Heart symbol - Channel list. */
-	{ 0x0014, KEY_PLAY },
-	{ 0x001a, KEY_STOP },
-	{ 0x0040, KEY_REWIND },
-	{ 0x0012, KEY_FASTFORWARD },
-	{ 0x000e, KEY_PREVIOUS }, /* Recall - Previous channel. */
-	{ 0x004c, KEY_PAUSE },
-	{ 0x004d, KEY_SCREEN }, /* Full screen mode. */
-	{ 0x0054, KEY_AUDIO }, /* MTS - Switch to secondary audio. */
-	{ 0x000c, KEY_CANCEL }, /* Cancel */
-	{ 0x001c, KEY_EPG }, /* EPG */
-	{ 0x0000, KEY_TAB }, /* Tab */
-	{ 0x0048, KEY_INFO }, /* Preview */
-	{ 0x0004, KEY_LIST }, /* RecordList */
-	{ 0x000f, KEY_TEXT }, /* Teletext */
-	{ 0x0041, KEY_PREVIOUSSONG },
-	{ 0x0042, KEY_NEXTSONG },
-	{ 0x004b, KEY_UP },
-	{ 0x0051, KEY_DOWN },
-	{ 0x004e, KEY_LEFT },
-	{ 0x0052, KEY_RIGHT },
-	{ 0x004f, KEY_ENTER },
-	{ 0x0013, KEY_CANCEL },
-	{ 0x004a, KEY_CLEAR },
-	{ 0x0054, KEY_PRINT }, /* Capture */
-	{ 0x0043, KEY_SUBTITLE }, /* Subtitle/CC */
-	{ 0x0008, KEY_VIDEO }, /* A/V */
-	{ 0x0007, KEY_SLEEP }, /* Hibernate */
-	{ 0x0045, KEY_ZOOM }, /* Zoom+ */
-	{ 0x0018, KEY_RED},
-	{ 0x0053, KEY_GREEN},
-	{ 0x005e, KEY_YELLOW},
-	{ 0x005f, KEY_BLUE}
-};
-
-static int vp7045_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
-{
-	u8 key;
-	int i;
-	vp7045_usb_op(d,RC_VAL_READ,NULL,0,&key,1,20);
-
-	deb_rc("remote query key: %x %d\n",key,key);
-
-	if (key == 0x44) {
-		*state = REMOTE_NO_KEY_PRESSED;
-		return 0;
-	}
-
-	for (i = 0; i < ARRAY_SIZE(rc_map_vp7045_table); i++)
-		if (rc5_data(&rc_map_vp7045_table[i]) == key) {
-			*state = REMOTE_KEY_PRESSED;
-			*event = rc_map_vp7045_table[i].keycode;
-			break;
-		}
-	return 0;
-}
-
-static int vp7045_read_eeprom(struct dvb_usb_device *d,u8 *buf, int len, int offset)
-{
-	int i = 0;
-	u8 v,br[2];
-	for (i=0; i < len; i++) {
-		v = offset + i;
-		vp7045_usb_op(d,GET_EE_VALUE,&v,1,br,2,5);
-		buf[i] = br[1];
-	}
-	deb_info("VP7045 EEPROM read (offs: %d, len: %d) : ",offset, i);
-	debug_dump(buf,i,deb_info);
-	return 0;
-}
-
-static int vp7045_read_mac_addr(struct dvb_usb_device *d,u8 mac[6])
-{
-	return vp7045_read_eeprom(d,mac, 6, MAC_0_ADDR);
-}
-
-static int vp7045_frontend_attach(struct dvb_usb_adapter *adap)
-{
-	u8 buf[255] = { 0 };
-
-	vp7045_usb_op(adap->dev,VENDOR_STRING_READ,NULL,0,buf,20,0);
-	buf[10] = '\0';
-	deb_info("firmware says: %s ",buf);
-
-	vp7045_usb_op(adap->dev,PRODUCT_STRING_READ,NULL,0,buf,20,0);
-	buf[10] = '\0';
-	deb_info("%s ",buf);
-
-	vp7045_usb_op(adap->dev,FW_VERSION_READ,NULL,0,buf,20,0);
-	buf[10] = '\0';
-	deb_info("v%s\n",buf);
-
-/*	Dump the EEPROM */
-/*	vp7045_read_eeprom(d,buf, 255, FX2_ID_ADDR); */
-
-	adap->fe_adap[0].fe = vp7045_fe_attach(adap->dev);
-
-	return 0;
-}
-
-static struct dvb_usb_device_properties vp7045_properties;
-
-static int vp7045_usb_probe(struct usb_interface *intf,
-		const struct usb_device_id *id)
-{
-	return dvb_usb_device_init(intf, &vp7045_properties,
-				   THIS_MODULE, NULL, adapter_nr);
-}
-
-static struct usb_device_id vp7045_usb_table [] = {
-	    { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7045_COLD) },
-	    { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7045_WARM) },
-	    { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_DNTV_TINYUSB2_COLD) },
-	    { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_DNTV_TINYUSB2_WARM) },
-	    { 0 },
-};
-MODULE_DEVICE_TABLE(usb, vp7045_usb_table);
-
-static struct dvb_usb_device_properties vp7045_properties = {
-	.usb_ctrl = CYPRESS_FX2,
-	.firmware = "dvb-usb-vp7045-01.fw",
-	.size_of_priv = 20,
-
-	.num_adapters = 1,
-	.adapter = {
-		{
-		.num_frontends = 1,
-		.fe = {{
-			.frontend_attach  = vp7045_frontend_attach,
-			/* parameter for the MPEG2-data transfer */
-			.stream = {
-				.type = USB_BULK,
-				.count = 7,
-				.endpoint = 0x02,
-				.u = {
-					.bulk = {
-						.buffersize = 4096,
-					}
-				}
-			},
-		}},
-		}
-	},
-	.power_ctrl       = vp7045_power_ctrl,
-	.read_mac_address = vp7045_read_mac_addr,
-
-	.rc.legacy = {
-		.rc_interval      = 400,
-		.rc_map_table       = rc_map_vp7045_table,
-		.rc_map_size  = ARRAY_SIZE(rc_map_vp7045_table),
-		.rc_query         = vp7045_rc_query,
-	},
-
-	.num_device_descs = 2,
-	.devices = {
-		{ .name = "Twinhan USB2.0 DVB-T receiver (TwinhanDTV Alpha/MagicBox II)",
-		  .cold_ids = { &vp7045_usb_table[0], NULL },
-		  .warm_ids = { &vp7045_usb_table[1], NULL },
-		},
-		{ .name = "DigitalNow TinyUSB 2 DVB-t Receiver",
-		  .cold_ids = { &vp7045_usb_table[2], NULL },
-		  .warm_ids = { &vp7045_usb_table[3], NULL },
-		},
-		{ NULL },
-	}
-};
-
-/* usb specific object needed to register this driver with the usb subsystem */
-static struct usb_driver vp7045_usb_driver = {
-	.name		= "dvb_usb_vp7045",
-	.probe		= vp7045_usb_probe,
-	.disconnect	= dvb_usb_device_exit,
-	.id_table	= vp7045_usb_table,
-};
-
-module_usb_driver(vp7045_usb_driver);
-
-MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
-MODULE_DESCRIPTION("Driver for Twinhan MagicBox/Alpha and DNTV tinyUSB2 DVB-T USB2.0");
-MODULE_VERSION("1.0");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/vp7045.h b/drivers/media/dvb/dvb-usb/vp7045.h
deleted file mode 100644
index cf5ec46..0000000
--- a/drivers/media/dvb/dvb-usb/vp7045.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/* Common header-file of the Linux driver for the TwinhanDTV Alpha/MagicBoxII
- * USB2.0 DVB-T receiver.
- *
- * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
- *
- * Thanks to Twinhan who kindly provided hardware and information.
- *
- *	This program is free software; you can redistribute it and/or modify it
- *	under the terms of the GNU General Public License as published by the Free
- *	Software Foundation, version 2.
- *
- * see Documentation/dvb/README.dvb-usb for more information
- */
-#ifndef _DVB_USB_VP7045_H_
-#define _DVB_USB_VP7045_H_
-
-#define DVB_USB_LOG_PREFIX "vp7045"
-#include "dvb-usb.h"
-
-/* vp7045 commands */
-
-/* Twinhan Vendor requests */
-#define TH_COMMAND_IN                     0xC0
-#define TH_COMMAND_OUT                    0xC1
-
-/* command bytes */
-#define TUNER_REG_READ                    0x03
-#define TUNER_REG_WRITE                   0x04
-
-#define RC_VAL_READ                       0x05
- #define RC_NO_KEY                        0x44
-
-#define SET_TUNER_POWER                   0x06
-#define CHECK_TUNER_POWER                 0x12
- #define Tuner_Power_ON                   1
- #define Tuner_Power_OFF                  0
-
-#define GET_USB_SPEED                     0x07
-
-#define LOCK_TUNER_COMMAND                0x09
-
-#define TUNER_SIGNAL_READ                 0x0A
-
-/* FX2 eeprom */
-#define SET_EE_VALUE                      0x10
-#define GET_EE_VALUE                      0x11
- #define FX2_ID_ADDR                      0x00
- #define VID_MSB_ADDR                     0x02
- #define VID_LSB_ADDR                     0x01
- #define PID_MSB_ADDR                     0x04
- #define PID_LSB_ADDR                     0x03
- #define MAC_0_ADDR                       0x07
- #define MAC_1_ADDR                       0x08
- #define MAC_2_ADDR                       0x09
- #define MAC_3_ADDR                       0x0a
- #define MAC_4_ADDR                       0x0b
- #define MAC_5_ADDR                       0x0c
-
-#define RESET_FX2                         0x13
-
-#define FW_VERSION_READ                   0x0B
-#define VENDOR_STRING_READ                0x0C
-#define PRODUCT_STRING_READ               0x0D
-#define FW_BCD_VERSION_READ               0x14
-
-extern struct dvb_frontend * vp7045_fe_attach(struct dvb_usb_device *d);
-extern int vp7045_usb_op(struct dvb_usb_device *d, u8 cmd, u8 *out, int outlen, u8 *in, int inlen,int msec);
-extern u8 vp7045_read_reg(struct dvb_usb_device *d, u8 reg);
-
-#endif
diff --git a/drivers/media/dvb/firewire/Kconfig b/drivers/media/dvb/firewire/Kconfig
deleted file mode 100644
index f3e9448..0000000
--- a/drivers/media/dvb/firewire/Kconfig
+++ /dev/null
@@ -1,19 +0,0 @@
-config DVB_FIREDTV
-	tristate "FireDTV and FloppyDTV"
-	depends on DVB_CORE && FIREWIRE
-	help
-	  Support for DVB receivers from Digital Everywhere
-	  which are connected via IEEE 1394 (FireWire).
-
-	  These devices don't have an MPEG decoder built in,
-	  so you need an external software decoder to watch TV.
-
-	  To compile this driver as a module, say M here:
-	  the module will be called firedtv.
-
-if DVB_FIREDTV
-
-config DVB_FIREDTV_INPUT
-	def_bool INPUT = y || (INPUT = m && DVB_FIREDTV = m)
-
-endif # DVB_FIREDTV
diff --git a/drivers/media/dvb/firewire/Makefile b/drivers/media/dvb/firewire/Makefile
deleted file mode 100644
index 357b3aa..0000000
--- a/drivers/media/dvb/firewire/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-obj-$(CONFIG_DVB_FIREDTV) += firedtv.o
-
-firedtv-y := firedtv-avc.o firedtv-ci.o firedtv-dvb.o firedtv-fe.o firedtv-fw.o
-firedtv-$(CONFIG_DVB_FIREDTV_INPUT)    += firedtv-rc.o
-
-ccflags-y += -Idrivers/media/dvb/dvb-core
diff --git a/drivers/media/dvb/firewire/firedtv-avc.c b/drivers/media/dvb/firewire/firedtv-avc.c
deleted file mode 100644
index d1a1a13..0000000
--- a/drivers/media/dvb/firewire/firedtv-avc.c
+++ /dev/null
@@ -1,1457 +0,0 @@
-/*
- * FireDTV driver (formerly known as FireSAT)
- *
- * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com>
- * Copyright (C) 2008 Ben Backx <ben@bbackx.com>
- * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se>
- *
- *	This program is free software; you can redistribute it and/or
- *	modify it under the terms of the 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/bug.h>
-#include <linux/crc32.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/jiffies.h>
-#include <linux/kernel.h>
-#include <linux/moduleparam.h>
-#include <linux/mutex.h>
-#include <linux/string.h>
-#include <linux/stringify.h>
-#include <linux/wait.h>
-#include <linux/workqueue.h>
-
-#include <dvb_frontend.h>
-
-#include "firedtv.h"
-
-#define FCP_COMMAND_REGISTER		0xfffff0000b00ULL
-
-#define AVC_CTYPE_CONTROL		0x0
-#define AVC_CTYPE_STATUS		0x1
-#define AVC_CTYPE_NOTIFY		0x3
-
-#define AVC_RESPONSE_ACCEPTED		0x9
-#define AVC_RESPONSE_STABLE		0xc
-#define AVC_RESPONSE_CHANGED		0xd
-#define AVC_RESPONSE_INTERIM		0xf
-
-#define AVC_SUBUNIT_TYPE_TUNER		(0x05 << 3)
-#define AVC_SUBUNIT_TYPE_UNIT		(0x1f << 3)
-
-#define AVC_OPCODE_VENDOR		0x00
-#define AVC_OPCODE_READ_DESCRIPTOR	0x09
-#define AVC_OPCODE_DSIT			0xc8
-#define AVC_OPCODE_DSD			0xcb
-
-#define DESCRIPTOR_TUNER_STATUS 	0x80
-#define DESCRIPTOR_SUBUNIT_IDENTIFIER	0x00
-
-#define SFE_VENDOR_DE_COMPANYID_0	0x00 /* OUI of Digital Everywhere */
-#define SFE_VENDOR_DE_COMPANYID_1	0x12
-#define SFE_VENDOR_DE_COMPANYID_2	0x87
-
-#define SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL 0x0a
-#define SFE_VENDOR_OPCODE_LNB_CONTROL		0x52
-#define SFE_VENDOR_OPCODE_TUNE_QPSK		0x58 /* for DVB-S */
-
-#define SFE_VENDOR_OPCODE_GET_FIRMWARE_VERSION	0x00
-#define SFE_VENDOR_OPCODE_HOST2CA		0x56
-#define SFE_VENDOR_OPCODE_CA2HOST		0x57
-#define SFE_VENDOR_OPCODE_CISTATUS		0x59
-#define SFE_VENDOR_OPCODE_TUNE_QPSK2		0x60 /* for DVB-S2 */
-
-#define SFE_VENDOR_TAG_CA_RESET			0x00
-#define SFE_VENDOR_TAG_CA_APPLICATION_INFO	0x01
-#define SFE_VENDOR_TAG_CA_PMT			0x02
-#define SFE_VENDOR_TAG_CA_DATE_TIME		0x04
-#define SFE_VENDOR_TAG_CA_MMI			0x05
-#define SFE_VENDOR_TAG_CA_ENTER_MENU		0x07
-
-#define EN50221_LIST_MANAGEMENT_ONLY	0x03
-#define EN50221_TAG_APP_INFO		0x9f8021
-#define EN50221_TAG_CA_INFO		0x9f8031
-
-struct avc_command_frame {
-	u8 ctype;
-	u8 subunit;
-	u8 opcode;
-	u8 operand[509];
-};
-
-struct avc_response_frame {
-	u8 response;
-	u8 subunit;
-	u8 opcode;
-	u8 operand[509];
-};
-
-#define LAST_OPERAND (509 - 1)
-
-static inline void clear_operands(struct avc_command_frame *c, int from, int to)
-{
-	memset(&c->operand[from], 0, to - from + 1);
-}
-
-static void pad_operands(struct avc_command_frame *c, int from)
-{
-	int to = ALIGN(from, 4);
-
-	if (from <= to && to <= LAST_OPERAND)
-		clear_operands(c, from, to);
-}
-
-#define AVC_DEBUG_READ_DESCRIPTOR              0x0001
-#define AVC_DEBUG_DSIT                         0x0002
-#define AVC_DEBUG_DSD                          0x0004
-#define AVC_DEBUG_REGISTER_REMOTE_CONTROL      0x0008
-#define AVC_DEBUG_LNB_CONTROL                  0x0010
-#define AVC_DEBUG_TUNE_QPSK                    0x0020
-#define AVC_DEBUG_TUNE_QPSK2                   0x0040
-#define AVC_DEBUG_HOST2CA                      0x0080
-#define AVC_DEBUG_CA2HOST                      0x0100
-#define AVC_DEBUG_APPLICATION_PMT              0x4000
-#define AVC_DEBUG_FCP_PAYLOADS                 0x8000
-
-static int avc_debug;
-module_param_named(debug, avc_debug, int, 0644);
-MODULE_PARM_DESC(debug, "Verbose logging (none = 0"
-	", FCP subactions"
-	": READ DESCRIPTOR = "		__stringify(AVC_DEBUG_READ_DESCRIPTOR)
-	", DSIT = "			__stringify(AVC_DEBUG_DSIT)
-	", REGISTER_REMOTE_CONTROL = "	__stringify(AVC_DEBUG_REGISTER_REMOTE_CONTROL)
-	", LNB CONTROL = "		__stringify(AVC_DEBUG_LNB_CONTROL)
-	", TUNE QPSK = "		__stringify(AVC_DEBUG_TUNE_QPSK)
-	", TUNE QPSK2 = "		__stringify(AVC_DEBUG_TUNE_QPSK2)
-	", HOST2CA = "			__stringify(AVC_DEBUG_HOST2CA)
-	", CA2HOST = "			__stringify(AVC_DEBUG_CA2HOST)
-	"; Application sent PMT = "	__stringify(AVC_DEBUG_APPLICATION_PMT)
-	", FCP payloads = "		__stringify(AVC_DEBUG_FCP_PAYLOADS)
-	", or a combination, or all = -1)");
-
-/*
- * This is a workaround since there is no vendor specific command to retrieve
- * ca_info using AVC. If this parameter is not used, ca_system_id will be
- * filled with application_manufacturer from ca_app_info.
- * Digital Everywhere have said that adding ca_info is on their TODO list.
- */
-static unsigned int num_fake_ca_system_ids;
-static int fake_ca_system_ids[4] = { -1, -1, -1, -1 };
-module_param_array(fake_ca_system_ids, int, &num_fake_ca_system_ids, 0644);
-MODULE_PARM_DESC(fake_ca_system_ids, "If your CAM application manufacturer "
-		 "does not have the same ca_system_id as your CAS, you can "
-		 "override what ca_system_ids are presented to the "
-		 "application by setting this field to an array of ids.");
-
-static const char *debug_fcp_ctype(unsigned int ctype)
-{
-	static const char *ctypes[] = {
-		[0x0] = "CONTROL",		[0x1] = "STATUS",
-		[0x2] = "SPECIFIC INQUIRY",	[0x3] = "NOTIFY",
-		[0x4] = "GENERAL INQUIRY",	[0x8] = "NOT IMPLEMENTED",
-		[0x9] = "ACCEPTED",		[0xa] = "REJECTED",
-		[0xb] = "IN TRANSITION",	[0xc] = "IMPLEMENTED/STABLE",
-		[0xd] = "CHANGED",		[0xf] = "INTERIM",
-	};
-	const char *ret = ctype < ARRAY_SIZE(ctypes) ? ctypes[ctype] : NULL;
-
-	return ret ? ret : "?";
-}
-
-static const char *debug_fcp_opcode(unsigned int opcode,
-				    const u8 *data, int length)
-{
-	switch (opcode) {
-	case AVC_OPCODE_VENDOR:
-		break;
-	case AVC_OPCODE_READ_DESCRIPTOR:
-		return avc_debug & AVC_DEBUG_READ_DESCRIPTOR ?
-				"ReadDescriptor" : NULL;
-	case AVC_OPCODE_DSIT:
-		return avc_debug & AVC_DEBUG_DSIT ?
-				"DirectSelectInfo.Type" : NULL;
-	case AVC_OPCODE_DSD:
-		return avc_debug & AVC_DEBUG_DSD ? "DirectSelectData" : NULL;
-	default:
-		return "Unknown";
-	}
-
-	if (length < 7 ||
-	    data[3] != SFE_VENDOR_DE_COMPANYID_0 ||
-	    data[4] != SFE_VENDOR_DE_COMPANYID_1 ||
-	    data[5] != SFE_VENDOR_DE_COMPANYID_2)
-		return "Vendor/Unknown";
-
-	switch (data[6]) {
-	case SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL:
-		return avc_debug & AVC_DEBUG_REGISTER_REMOTE_CONTROL ?
-				"RegisterRC" : NULL;
-	case SFE_VENDOR_OPCODE_LNB_CONTROL:
-		return avc_debug & AVC_DEBUG_LNB_CONTROL ? "LNBControl" : NULL;
-	case SFE_VENDOR_OPCODE_TUNE_QPSK:
-		return avc_debug & AVC_DEBUG_TUNE_QPSK ? "TuneQPSK" : NULL;
-	case SFE_VENDOR_OPCODE_TUNE_QPSK2:
-		return avc_debug & AVC_DEBUG_TUNE_QPSK2 ? "TuneQPSK2" : NULL;
-	case SFE_VENDOR_OPCODE_HOST2CA:
-		return avc_debug & AVC_DEBUG_HOST2CA ? "Host2CA" : NULL;
-	case SFE_VENDOR_OPCODE_CA2HOST:
-		return avc_debug & AVC_DEBUG_CA2HOST ? "CA2Host" : NULL;
-	}
-	return "Vendor/Unknown";
-}
-
-static void debug_fcp(const u8 *data, int length)
-{
-	unsigned int subunit_type, subunit_id, opcode;
-	const char *op, *prefix;
-
-	prefix       = data[0] > 7 ? "FCP <- " : "FCP -> ";
-	subunit_type = data[1] >> 3;
-	subunit_id   = data[1] & 7;
-	opcode       = subunit_type == 0x1e || subunit_id == 5 ? ~0 : data[2];
-	op           = debug_fcp_opcode(opcode, data, length);
-
-	if (op) {
-		printk(KERN_INFO "%ssu=%x.%x l=%d: %-8s - %s\n",
-		       prefix, subunit_type, subunit_id, length,
-		       debug_fcp_ctype(data[0]), op);
-		if (avc_debug & AVC_DEBUG_FCP_PAYLOADS)
-			print_hex_dump(KERN_INFO, prefix, DUMP_PREFIX_NONE,
-				       16, 1, data, length, false);
-	}
-}
-
-static void debug_pmt(char *msg, int length)
-{
-	printk(KERN_INFO "APP PMT -> l=%d\n", length);
-	print_hex_dump(KERN_INFO, "APP PMT -> ", DUMP_PREFIX_NONE,
-		       16, 1, msg, length, false);
-}
-
-static int avc_write(struct firedtv *fdtv)
-{
-	int err, retry;
-
-	fdtv->avc_reply_received = false;
-
-	for (retry = 0; retry < 6; retry++) {
-		if (unlikely(avc_debug))
-			debug_fcp(fdtv->avc_data, fdtv->avc_data_length);
-
-		err = fdtv_write(fdtv, FCP_COMMAND_REGISTER,
-				 fdtv->avc_data, fdtv->avc_data_length);
-		if (err) {
-			dev_err(fdtv->device, "FCP command write failed\n");
-
-			return err;
-		}
-
-		/*
-		 * AV/C specs say that answers should be sent within 150 ms.
-		 * Time out after 200 ms.
-		 */
-		if (wait_event_timeout(fdtv->avc_wait,
-				       fdtv->avc_reply_received,
-				       msecs_to_jiffies(200)) != 0)
-			return 0;
-	}
-	dev_err(fdtv->device, "FCP response timed out\n");
-
-	return -ETIMEDOUT;
-}
-
-static bool is_register_rc(struct avc_response_frame *r)
-{
-	return r->opcode     == AVC_OPCODE_VENDOR &&
-	       r->operand[0] == SFE_VENDOR_DE_COMPANYID_0 &&
-	       r->operand[1] == SFE_VENDOR_DE_COMPANYID_1 &&
-	       r->operand[2] == SFE_VENDOR_DE_COMPANYID_2 &&
-	       r->operand[3] == SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL;
-}
-
-int avc_recv(struct firedtv *fdtv, void *data, size_t length)
-{
-	struct avc_response_frame *r = data;
-
-	if (unlikely(avc_debug))
-		debug_fcp(data, length);
-
-	if (length >= 8 && is_register_rc(r)) {
-		switch (r->response) {
-		case AVC_RESPONSE_CHANGED:
-			fdtv_handle_rc(fdtv, r->operand[4] << 8 | r->operand[5]);
-			schedule_work(&fdtv->remote_ctrl_work);
-			break;
-		case AVC_RESPONSE_INTERIM:
-			if (is_register_rc((void *)fdtv->avc_data))
-				goto wake;
-			break;
-		default:
-			dev_info(fdtv->device,
-				 "remote control result = %d\n", r->response);
-		}
-		return 0;
-	}
-
-	if (fdtv->avc_reply_received) {
-		dev_err(fdtv->device, "out-of-order AVC response, ignored\n");
-		return -EIO;
-	}
-
-	memcpy(fdtv->avc_data, data, length);
-	fdtv->avc_data_length = length;
-wake:
-	fdtv->avc_reply_received = true;
-	wake_up(&fdtv->avc_wait);
-
-	return 0;
-}
-
-static int add_pid_filter(struct firedtv *fdtv, u8 *operand)
-{
-	int i, n, pos = 1;
-
-	for (i = 0, n = 0; i < 16; i++) {
-		if (test_bit(i, &fdtv->channel_active)) {
-			operand[pos++] = 0x13; /* flowfunction relay */
-			operand[pos++] = 0x80; /* dsd_sel_spec_valid_flags -> PID */
-			operand[pos++] = (fdtv->channel_pid[i] >> 8) & 0x1f;
-			operand[pos++] = fdtv->channel_pid[i] & 0xff;
-			operand[pos++] = 0x00; /* tableID */
-			operand[pos++] = 0x00; /* filter_length */
-			n++;
-		}
-	}
-	operand[0] = n;
-
-	return pos;
-}
-
-/*
- * tuning command for setting the relative LNB frequency
- * (not supported by the AVC standard)
- */
-static int avc_tuner_tuneqpsk(struct firedtv *fdtv,
-			      struct dtv_frontend_properties *p)
-{
-	struct avc_command_frame *c = (void *)fdtv->avc_data;
-
-	c->opcode = AVC_OPCODE_VENDOR;
-
-	c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
-	c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
-	c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
-	if (fdtv->type == FIREDTV_DVB_S2)
-		c->operand[3] = SFE_VENDOR_OPCODE_TUNE_QPSK2;
-	else
-		c->operand[3] = SFE_VENDOR_OPCODE_TUNE_QPSK;
-
-	c->operand[4] = (p->frequency >> 24) & 0xff;
-	c->operand[5] = (p->frequency >> 16) & 0xff;
-	c->operand[6] = (p->frequency >> 8) & 0xff;
-	c->operand[7] = p->frequency & 0xff;
-
-	c->operand[8] = ((p->symbol_rate / 1000) >> 8) & 0xff;
-	c->operand[9] = (p->symbol_rate / 1000) & 0xff;
-
-	switch (p->fec_inner) {
-	case FEC_1_2:	c->operand[10] = 0x1; break;
-	case FEC_2_3:	c->operand[10] = 0x2; break;
-	case FEC_3_4:	c->operand[10] = 0x3; break;
-	case FEC_5_6:	c->operand[10] = 0x4; break;
-	case FEC_7_8:	c->operand[10] = 0x5; break;
-	case FEC_4_5:
-	case FEC_8_9:
-	case FEC_AUTO:
-	default:	c->operand[10] = 0x0;
-	}
-
-	if (fdtv->voltage == 0xff)
-		c->operand[11] = 0xff;
-	else if (fdtv->voltage == SEC_VOLTAGE_18) /* polarisation */
-		c->operand[11] = 0;
-	else
-		c->operand[11] = 1;
-
-	if (fdtv->tone == 0xff)
-		c->operand[12] = 0xff;
-	else if (fdtv->tone == SEC_TONE_ON) /* band */
-		c->operand[12] = 1;
-	else
-		c->operand[12] = 0;
-
-	if (fdtv->type == FIREDTV_DVB_S2) {
-		if (fdtv->fe.dtv_property_cache.delivery_system == SYS_DVBS2) {
-			switch (fdtv->fe.dtv_property_cache.modulation) {
-			case QAM_16:		c->operand[13] = 0x1; break;
-			case QPSK:		c->operand[13] = 0x2; break;
-			case PSK_8:		c->operand[13] = 0x3; break;
-			default:		c->operand[13] = 0x2; break;
-			}
-			switch (fdtv->fe.dtv_property_cache.rolloff) {
-			case ROLLOFF_35:	c->operand[14] = 0x2; break;
-			case ROLLOFF_20:	c->operand[14] = 0x0; break;
-			case ROLLOFF_25:	c->operand[14] = 0x1; break;
-			case ROLLOFF_AUTO:
-			default:		c->operand[14] = 0x2; break;
-			/* case ROLLOFF_NONE:	c->operand[14] = 0xff; break; */
-			}
-			switch (fdtv->fe.dtv_property_cache.pilot) {
-			case PILOT_AUTO:	c->operand[15] = 0x0; break;
-			case PILOT_OFF:		c->operand[15] = 0x0; break;
-			case PILOT_ON:		c->operand[15] = 0x1; break;
-			}
-		} else {
-			c->operand[13] = 0x1;  /* auto modulation */
-			c->operand[14] = 0xff; /* disable rolloff */
-			c->operand[15] = 0xff; /* disable pilot */
-		}
-		return 16;
-	} else {
-		return 13;
-	}
-}
-
-static int avc_tuner_dsd_dvb_c(struct firedtv *fdtv,
-			       struct dtv_frontend_properties *p)
-{
-	struct avc_command_frame *c = (void *)fdtv->avc_data;
-
-	c->opcode = AVC_OPCODE_DSD;
-
-	c->operand[0] = 0;    /* source plug */
-	c->operand[1] = 0xd2; /* subfunction replace */
-	c->operand[2] = 0x20; /* system id = DVB */
-	c->operand[3] = 0x00; /* antenna number */
-	c->operand[4] = 0x11; /* system_specific_multiplex selection_length */
-
-	/* multiplex_valid_flags, high byte */
-	c->operand[5] =   0 << 7 /* reserved */
-			| 0 << 6 /* Polarisation */
-			| 0 << 5 /* Orbital_Pos */
-			| 1 << 4 /* Frequency */
-			| 1 << 3 /* Symbol_Rate */
-			| 0 << 2 /* FEC_outer */
-			| (p->fec_inner  != FEC_AUTO ? 1 << 1 : 0)
-			| (p->modulation != QAM_AUTO ? 1 << 0 : 0);
-
-	/* multiplex_valid_flags, low byte */
-	c->operand[6] =   0 << 7 /* NetworkID */
-			| 0 << 0 /* reserved */ ;
-
-	c->operand[7]  = 0x00;
-	c->operand[8]  = 0x00;
-	c->operand[9]  = 0x00;
-	c->operand[10] = 0x00;
-
-	c->operand[11] = (((p->frequency / 4000) >> 16) & 0xff) | (2 << 6);
-	c->operand[12] = ((p->frequency / 4000) >> 8) & 0xff;
-	c->operand[13] = (p->frequency / 4000) & 0xff;
-	c->operand[14] = ((p->symbol_rate / 1000) >> 12) & 0xff;
-	c->operand[15] = ((p->symbol_rate / 1000) >> 4) & 0xff;
-	c->operand[16] = ((p->symbol_rate / 1000) << 4) & 0xf0;
-	c->operand[17] = 0x00;
-
-	switch (p->fec_inner) {
-	case FEC_1_2:	c->operand[18] = 0x1; break;
-	case FEC_2_3:	c->operand[18] = 0x2; break;
-	case FEC_3_4:	c->operand[18] = 0x3; break;
-	case FEC_5_6:	c->operand[18] = 0x4; break;
-	case FEC_7_8:	c->operand[18] = 0x5; break;
-	case FEC_8_9:	c->operand[18] = 0x6; break;
-	case FEC_4_5:	c->operand[18] = 0x8; break;
-	case FEC_AUTO:
-	default:	c->operand[18] = 0x0;
-	}
-
-	switch (p->modulation) {
-	case QAM_16:	c->operand[19] = 0x08; break;
-	case QAM_32:	c->operand[19] = 0x10; break;
-	case QAM_64:	c->operand[19] = 0x18; break;
-	case QAM_128:	c->operand[19] = 0x20; break;
-	case QAM_256:	c->operand[19] = 0x28; break;
-	case QAM_AUTO:
-	default:	c->operand[19] = 0x00;
-	}
-
-	c->operand[20] = 0x00;
-	c->operand[21] = 0x00;
-
-	return 22 + add_pid_filter(fdtv, &c->operand[22]);
-}
-
-static int avc_tuner_dsd_dvb_t(struct firedtv *fdtv,
-			       struct dtv_frontend_properties *p)
-{
-	struct avc_command_frame *c = (void *)fdtv->avc_data;
-
-	c->opcode = AVC_OPCODE_DSD;
-
-	c->operand[0] = 0;    /* source plug */
-	c->operand[1] = 0xd2; /* subfunction replace */
-	c->operand[2] = 0x20; /* system id = DVB */
-	c->operand[3] = 0x00; /* antenna number */
-	c->operand[4] = 0x0c; /* system_specific_multiplex selection_length */
-
-	/* multiplex_valid_flags, high byte */
-	c->operand[5] =
-	      0 << 7 /* reserved */
-	    | 1 << 6 /* CenterFrequency */
-	    | (p->bandwidth_hz != 0        ? 1 << 5 : 0)
-	    | (p->modulation  != QAM_AUTO              ? 1 << 4 : 0)
-	    | (p->hierarchy != HIERARCHY_AUTO ? 1 << 3 : 0)
-	    | (p->code_rate_HP   != FEC_AUTO              ? 1 << 2 : 0)
-	    | (p->code_rate_LP   != FEC_AUTO              ? 1 << 1 : 0)
-	    | (p->guard_interval != GUARD_INTERVAL_AUTO   ? 1 << 0 : 0);
-
-	/* multiplex_valid_flags, low byte */
-	c->operand[6] =
-	      0 << 7 /* NetworkID */
-	    | (p->transmission_mode != TRANSMISSION_MODE_AUTO ? 1 << 6 : 0)
-	    | 0 << 5 /* OtherFrequencyFlag */
-	    | 0 << 0 /* reserved */ ;
-
-	c->operand[7]  = 0x0;
-	c->operand[8]  = (p->frequency / 10) >> 24;
-	c->operand[9]  = ((p->frequency / 10) >> 16) & 0xff;
-	c->operand[10] = ((p->frequency / 10) >>  8) & 0xff;
-	c->operand[11] = (p->frequency / 10) & 0xff;
-
-	switch (p->bandwidth_hz) {
-	case 7000000:	c->operand[12] = 0x20; break;
-	case 8000000:
-	case 6000000:	/* not defined by AVC spec */
-	case 0:
-	default:		c->operand[12] = 0x00;
-	}
-
-	switch (p->modulation) {
-	case QAM_16:	c->operand[13] = 1 << 6; break;
-	case QAM_64:	c->operand[13] = 2 << 6; break;
-	case QPSK:
-	default:	c->operand[13] = 0x00;
-	}
-
-	switch (p->hierarchy) {
-	case HIERARCHY_1:	c->operand[13] |= 1 << 3; break;
-	case HIERARCHY_2:	c->operand[13] |= 2 << 3; break;
-	case HIERARCHY_4:	c->operand[13] |= 3 << 3; break;
-	case HIERARCHY_AUTO:
-	case HIERARCHY_NONE:
-	default:		break;
-	}
-
-	switch (p->code_rate_HP) {
-	case FEC_2_3:	c->operand[13] |= 1; break;
-	case FEC_3_4:	c->operand[13] |= 2; break;
-	case FEC_5_6:	c->operand[13] |= 3; break;
-	case FEC_7_8:	c->operand[13] |= 4; break;
-	case FEC_1_2:
-	default:	break;
-	}
-
-	switch (p->code_rate_LP) {
-	case FEC_2_3:	c->operand[14] = 1 << 5; break;
-	case FEC_3_4:	c->operand[14] = 2 << 5; break;
-	case FEC_5_6:	c->operand[14] = 3 << 5; break;
-	case FEC_7_8:	c->operand[14] = 4 << 5; break;
-	case FEC_1_2:
-	default:	c->operand[14] = 0x00; break;
-	}
-
-	switch (p->guard_interval) {
-	case GUARD_INTERVAL_1_16:	c->operand[14] |= 1 << 3; break;
-	case GUARD_INTERVAL_1_8:	c->operand[14] |= 2 << 3; break;
-	case GUARD_INTERVAL_1_4:	c->operand[14] |= 3 << 3; break;
-	case GUARD_INTERVAL_1_32:
-	case GUARD_INTERVAL_AUTO:
-	default:			break;
-	}
-
-	switch (p->transmission_mode) {
-	case TRANSMISSION_MODE_8K:	c->operand[14] |= 1 << 1; break;
-	case TRANSMISSION_MODE_2K:
-	case TRANSMISSION_MODE_AUTO:
-	default:			break;
-	}
-
-	c->operand[15] = 0x00; /* network_ID[0] */
-	c->operand[16] = 0x00; /* network_ID[1] */
-
-	return 17 + add_pid_filter(fdtv, &c->operand[17]);
-}
-
-int avc_tuner_dsd(struct firedtv *fdtv,
-		  struct dtv_frontend_properties *p)
-{
-	struct avc_command_frame *c = (void *)fdtv->avc_data;
-	int pos, ret;
-
-	mutex_lock(&fdtv->avc_mutex);
-
-	c->ctype   = AVC_CTYPE_CONTROL;
-	c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
-
-	switch (fdtv->type) {
-	case FIREDTV_DVB_S:
-	case FIREDTV_DVB_S2: pos = avc_tuner_tuneqpsk(fdtv, p); break;
-	case FIREDTV_DVB_C: pos = avc_tuner_dsd_dvb_c(fdtv, p); break;
-	case FIREDTV_DVB_T: pos = avc_tuner_dsd_dvb_t(fdtv, p); break;
-	default:
-		BUG();
-	}
-	pad_operands(c, pos);
-
-	fdtv->avc_data_length = ALIGN(3 + pos, 4);
-	ret = avc_write(fdtv);
-#if 0
-	/*
-	 * FIXME:
-	 * u8 *status was an out-parameter of avc_tuner_dsd, unused by caller.
-	 * Check for AVC_RESPONSE_ACCEPTED here instead?
-	 */
-	if (status)
-		*status = r->operand[2];
-#endif
-	mutex_unlock(&fdtv->avc_mutex);
-
-	if (ret == 0)
-		msleep(500);
-
-	return ret;
-}
-
-int avc_tuner_set_pids(struct firedtv *fdtv, unsigned char pidc, u16 pid[])
-{
-	struct avc_command_frame *c = (void *)fdtv->avc_data;
-	int ret, pos, k;
-
-	if (pidc > 16 && pidc != 0xff)
-		return -EINVAL;
-
-	mutex_lock(&fdtv->avc_mutex);
-
-	c->ctype   = AVC_CTYPE_CONTROL;
-	c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
-	c->opcode  = AVC_OPCODE_DSD;
-
-	c->operand[0] = 0;	/* source plug */
-	c->operand[1] = 0xd2;	/* subfunction replace */
-	c->operand[2] = 0x20;	/* system id = DVB */
-	c->operand[3] = 0x00;	/* antenna number */
-	c->operand[4] = 0x00;	/* system_specific_multiplex selection_length */
-	c->operand[5] = pidc;	/* Nr_of_dsd_sel_specs */
-
-	pos = 6;
-	if (pidc != 0xff)
-		for (k = 0; k < pidc; k++) {
-			c->operand[pos++] = 0x13; /* flowfunction relay */
-			c->operand[pos++] = 0x80; /* dsd_sel_spec_valid_flags -> PID */
-			c->operand[pos++] = (pid[k] >> 8) & 0x1f;
-			c->operand[pos++] = pid[k] & 0xff;
-			c->operand[pos++] = 0x00; /* tableID */
-			c->operand[pos++] = 0x00; /* filter_length */
-		}
-	pad_operands(c, pos);
-
-	fdtv->avc_data_length = ALIGN(3 + pos, 4);
-	ret = avc_write(fdtv);
-
-	/* FIXME: check response code? */
-
-	mutex_unlock(&fdtv->avc_mutex);
-
-	if (ret == 0)
-		msleep(50);
-
-	return ret;
-}
-
-int avc_tuner_get_ts(struct firedtv *fdtv)
-{
-	struct avc_command_frame *c = (void *)fdtv->avc_data;
-	int ret, sl;
-
-	mutex_lock(&fdtv->avc_mutex);
-
-	c->ctype   = AVC_CTYPE_CONTROL;
-	c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
-	c->opcode  = AVC_OPCODE_DSIT;
-
-	sl = fdtv->type == FIREDTV_DVB_T ? 0x0c : 0x11;
-
-	c->operand[0] = 0;	/* source plug */
-	c->operand[1] = 0xd2;	/* subfunction replace */
-	c->operand[2] = 0xff;	/* status */
-	c->operand[3] = 0x20;	/* system id = DVB */
-	c->operand[4] = 0x00;	/* antenna number */
-	c->operand[5] = 0x0; 	/* system_specific_search_flags */
-	c->operand[6] = sl;	/* system_specific_multiplex selection_length */
-	/*
-	 * operand[7]: valid_flags[0]
-	 * operand[8]: valid_flags[1]
-	 * operand[7 + sl]: nr_of_dsit_sel_specs (always 0)
-	 */
-	clear_operands(c, 7, 24);
-
-	fdtv->avc_data_length = fdtv->type == FIREDTV_DVB_T ? 24 : 28;
-	ret = avc_write(fdtv);
-
-	/* FIXME: check response code? */
-
-	mutex_unlock(&fdtv->avc_mutex);
-
-	if (ret == 0)
-		msleep(250);
-
-	return ret;
-}
-
-int avc_identify_subunit(struct firedtv *fdtv)
-{
-	struct avc_command_frame *c = (void *)fdtv->avc_data;
-	struct avc_response_frame *r = (void *)fdtv->avc_data;
-	int ret;
-
-	mutex_lock(&fdtv->avc_mutex);
-
-	c->ctype   = AVC_CTYPE_CONTROL;
-	c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
-	c->opcode  = AVC_OPCODE_READ_DESCRIPTOR;
-
-	c->operand[0] = DESCRIPTOR_SUBUNIT_IDENTIFIER;
-	c->operand[1] = 0xff;
-	c->operand[2] = 0x00;
-	c->operand[3] = 0x00; /* length highbyte */
-	c->operand[4] = 0x08; /* length lowbyte  */
-	c->operand[5] = 0x00; /* offset highbyte */
-	c->operand[6] = 0x0d; /* offset lowbyte  */
-	clear_operands(c, 7, 8); /* padding */
-
-	fdtv->avc_data_length = 12;
-	ret = avc_write(fdtv);
-	if (ret < 0)
-		goto out;
-
-	if ((r->response != AVC_RESPONSE_STABLE &&
-	     r->response != AVC_RESPONSE_ACCEPTED) ||
-	    (r->operand[3] << 8) + r->operand[4] != 8) {
-		dev_err(fdtv->device, "cannot read subunit identifier\n");
-		ret = -EINVAL;
-	}
-out:
-	mutex_unlock(&fdtv->avc_mutex);
-
-	return ret;
-}
-
-#define SIZEOF_ANTENNA_INPUT_INFO 22
-
-int avc_tuner_status(struct firedtv *fdtv, struct firedtv_tuner_status *stat)
-{
-	struct avc_command_frame *c = (void *)fdtv->avc_data;
-	struct avc_response_frame *r = (void *)fdtv->avc_data;
-	int length, ret;
-
-	mutex_lock(&fdtv->avc_mutex);
-
-	c->ctype   = AVC_CTYPE_CONTROL;
-	c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
-	c->opcode  = AVC_OPCODE_READ_DESCRIPTOR;
-
-	c->operand[0] = DESCRIPTOR_TUNER_STATUS;
-	c->operand[1] = 0xff;	/* read_result_status */
-	/*
-	 * operand[2]: reserved
-	 * operand[3]: SIZEOF_ANTENNA_INPUT_INFO >> 8
-	 * operand[4]: SIZEOF_ANTENNA_INPUT_INFO & 0xff
-	 */
-	clear_operands(c, 2, 31);
-
-	fdtv->avc_data_length = 12;
-	ret = avc_write(fdtv);
-	if (ret < 0)
-		goto out;
-
-	if (r->response != AVC_RESPONSE_STABLE &&
-	    r->response != AVC_RESPONSE_ACCEPTED) {
-		dev_err(fdtv->device, "cannot read tuner status\n");
-		ret = -EINVAL;
-		goto out;
-	}
-
-	length = r->operand[9];
-	if (r->operand[1] != 0x10 || length != SIZEOF_ANTENNA_INPUT_INFO) {
-		dev_err(fdtv->device, "got invalid tuner status\n");
-		ret = -EINVAL;
-		goto out;
-	}
-
-	stat->active_system		= r->operand[10];
-	stat->searching			= r->operand[11] >> 7 & 1;
-	stat->moving			= r->operand[11] >> 6 & 1;
-	stat->no_rf			= r->operand[11] >> 5 & 1;
-	stat->input			= r->operand[12] >> 7 & 1;
-	stat->selected_antenna		= r->operand[12] & 0x7f;
-	stat->ber			= r->operand[13] << 24 |
-					  r->operand[14] << 16 |
-					  r->operand[15] << 8 |
-					  r->operand[16];
-	stat->signal_strength		= r->operand[17];
-	stat->raster_frequency		= r->operand[18] >> 6 & 2;
-	stat->rf_frequency		= (r->operand[18] & 0x3f) << 16 |
-					  r->operand[19] << 8 |
-					  r->operand[20];
-	stat->man_dep_info_length	= r->operand[21];
-	stat->front_end_error		= r->operand[22] >> 4 & 1;
-	stat->antenna_error		= r->operand[22] >> 3 & 1;
-	stat->front_end_power_status	= r->operand[22] >> 1 & 1;
-	stat->power_supply		= r->operand[22] & 1;
-	stat->carrier_noise_ratio	= r->operand[23] << 8 |
-					  r->operand[24];
-	stat->power_supply_voltage	= r->operand[27];
-	stat->antenna_voltage		= r->operand[28];
-	stat->firewire_bus_voltage	= r->operand[29];
-	stat->ca_mmi			= r->operand[30] & 1;
-	stat->ca_pmt_reply		= r->operand[31] >> 7 & 1;
-	stat->ca_date_time_request	= r->operand[31] >> 6 & 1;
-	stat->ca_application_info	= r->operand[31] >> 5 & 1;
-	stat->ca_module_present_status	= r->operand[31] >> 4 & 1;
-	stat->ca_dvb_flag		= r->operand[31] >> 3 & 1;
-	stat->ca_error_flag		= r->operand[31] >> 2 & 1;
-	stat->ca_initialization_status	= r->operand[31] >> 1 & 1;
-out:
-	mutex_unlock(&fdtv->avc_mutex);
-
-	return ret;
-}
-
-int avc_lnb_control(struct firedtv *fdtv, char voltage, char burst,
-		    char conttone, char nrdiseq,
-		    struct dvb_diseqc_master_cmd *diseqcmd)
-{
-	struct avc_command_frame *c = (void *)fdtv->avc_data;
-	struct avc_response_frame *r = (void *)fdtv->avc_data;
-	int pos, j, k, ret;
-
-	mutex_lock(&fdtv->avc_mutex);
-
-	c->ctype   = AVC_CTYPE_CONTROL;
-	c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
-	c->opcode  = AVC_OPCODE_VENDOR;
-
-	c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
-	c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
-	c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
-	c->operand[3] = SFE_VENDOR_OPCODE_LNB_CONTROL;
-	c->operand[4] = voltage;
-	c->operand[5] = nrdiseq;
-
-	pos = 6;
-	for (j = 0; j < nrdiseq; j++) {
-		c->operand[pos++] = diseqcmd[j].msg_len;
-
-		for (k = 0; k < diseqcmd[j].msg_len; k++)
-			c->operand[pos++] = diseqcmd[j].msg[k];
-	}
-	c->operand[pos++] = burst;
-	c->operand[pos++] = conttone;
-	pad_operands(c, pos);
-
-	fdtv->avc_data_length = ALIGN(3 + pos, 4);
-	ret = avc_write(fdtv);
-	if (ret < 0)
-		goto out;
-
-	if (r->response != AVC_RESPONSE_ACCEPTED) {
-		dev_err(fdtv->device, "LNB control failed\n");
-		ret = -EINVAL;
-	}
-out:
-	mutex_unlock(&fdtv->avc_mutex);
-
-	return ret;
-}
-
-int avc_register_remote_control(struct firedtv *fdtv)
-{
-	struct avc_command_frame *c = (void *)fdtv->avc_data;
-	int ret;
-
-	mutex_lock(&fdtv->avc_mutex);
-
-	c->ctype   = AVC_CTYPE_NOTIFY;
-	c->subunit = AVC_SUBUNIT_TYPE_UNIT | 7;
-	c->opcode  = AVC_OPCODE_VENDOR;
-
-	c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
-	c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
-	c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
-	c->operand[3] = SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL;
-	c->operand[4] = 0; /* padding */
-
-	fdtv->avc_data_length = 8;
-	ret = avc_write(fdtv);
-
-	/* FIXME: check response code? */
-
-	mutex_unlock(&fdtv->avc_mutex);
-
-	return ret;
-}
-
-void avc_remote_ctrl_work(struct work_struct *work)
-{
-	struct firedtv *fdtv =
-			container_of(work, struct firedtv, remote_ctrl_work);
-
-	/* Should it be rescheduled in failure cases? */
-	avc_register_remote_control(fdtv);
-}
-
-#if 0 /* FIXME: unused */
-int avc_tuner_host2ca(struct firedtv *fdtv)
-{
-	struct avc_command_frame *c = (void *)fdtv->avc_data;
-	int ret;
-
-	mutex_lock(&fdtv->avc_mutex);
-
-	c->ctype   = AVC_CTYPE_CONTROL;
-	c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
-	c->opcode  = AVC_OPCODE_VENDOR;
-
-	c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
-	c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
-	c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
-	c->operand[3] = SFE_VENDOR_OPCODE_HOST2CA;
-	c->operand[4] = 0; /* slot */
-	c->operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; /* ca tag */
-	clear_operands(c, 6, 8);
-
-	fdtv->avc_data_length = 12;
-	ret = avc_write(fdtv);
-
-	/* FIXME: check response code? */
-
-	mutex_unlock(&fdtv->avc_mutex);
-
-	return ret;
-}
-#endif
-
-static int get_ca_object_pos(struct avc_response_frame *r)
-{
-	int length = 1;
-
-	/* Check length of length field */
-	if (r->operand[7] & 0x80)
-		length = (r->operand[7] & 0x7f) + 1;
-	return length + 7;
-}
-
-static int get_ca_object_length(struct avc_response_frame *r)
-{
-#if 0 /* FIXME: unused */
-	int size = 0;
-	int i;
-
-	if (r->operand[7] & 0x80)
-		for (i = 0; i < (r->operand[7] & 0x7f); i++) {
-			size <<= 8;
-			size += r->operand[8 + i];
-		}
-#endif
-	return r->operand[7];
-}
-
-int avc_ca_app_info(struct firedtv *fdtv, char *app_info, unsigned int *len)
-{
-	struct avc_command_frame *c = (void *)fdtv->avc_data;
-	struct avc_response_frame *r = (void *)fdtv->avc_data;
-	int pos, ret;
-
-	mutex_lock(&fdtv->avc_mutex);
-
-	c->ctype   = AVC_CTYPE_STATUS;
-	c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
-	c->opcode  = AVC_OPCODE_VENDOR;
-
-	c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
-	c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
-	c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
-	c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST;
-	c->operand[4] = 0; /* slot */
-	c->operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; /* ca tag */
-	clear_operands(c, 6, LAST_OPERAND);
-
-	fdtv->avc_data_length = 12;
-	ret = avc_write(fdtv);
-	if (ret < 0)
-		goto out;
-
-	/* FIXME: check response code and validate response data */
-
-	pos = get_ca_object_pos(r);
-	app_info[0] = (EN50221_TAG_APP_INFO >> 16) & 0xff;
-	app_info[1] = (EN50221_TAG_APP_INFO >>  8) & 0xff;
-	app_info[2] = (EN50221_TAG_APP_INFO >>  0) & 0xff;
-	app_info[3] = 6 + r->operand[pos + 4];
-	app_info[4] = 0x01;
-	memcpy(&app_info[5], &r->operand[pos], 5 + r->operand[pos + 4]);
-	*len = app_info[3] + 4;
-out:
-	mutex_unlock(&fdtv->avc_mutex);
-
-	return ret;
-}
-
-int avc_ca_info(struct firedtv *fdtv, char *app_info, unsigned int *len)
-{
-	struct avc_command_frame *c = (void *)fdtv->avc_data;
-	struct avc_response_frame *r = (void *)fdtv->avc_data;
-	int i, pos, ret;
-
-	mutex_lock(&fdtv->avc_mutex);
-
-	c->ctype   = AVC_CTYPE_STATUS;
-	c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
-	c->opcode  = AVC_OPCODE_VENDOR;
-
-	c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
-	c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
-	c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
-	c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST;
-	c->operand[4] = 0; /* slot */
-	c->operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; /* ca tag */
-	clear_operands(c, 6, LAST_OPERAND);
-
-	fdtv->avc_data_length = 12;
-	ret = avc_write(fdtv);
-	if (ret < 0)
-		goto out;
-
-	/* FIXME: check response code and validate response data */
-
-	pos = get_ca_object_pos(r);
-	app_info[0] = (EN50221_TAG_CA_INFO >> 16) & 0xff;
-	app_info[1] = (EN50221_TAG_CA_INFO >>  8) & 0xff;
-	app_info[2] = (EN50221_TAG_CA_INFO >>  0) & 0xff;
-	if (num_fake_ca_system_ids == 0) {
-		app_info[3] = 2;
-		app_info[4] = r->operand[pos + 0];
-		app_info[5] = r->operand[pos + 1];
-	} else {
-		app_info[3] = num_fake_ca_system_ids * 2;
-		for (i = 0; i < num_fake_ca_system_ids; i++) {
-			app_info[4 + i * 2] =
-				(fake_ca_system_ids[i] >> 8) & 0xff;
-			app_info[5 + i * 2] = fake_ca_system_ids[i] & 0xff;
-		}
-	}
-	*len = app_info[3] + 4;
-out:
-	mutex_unlock(&fdtv->avc_mutex);
-
-	return ret;
-}
-
-int avc_ca_reset(struct firedtv *fdtv)
-{
-	struct avc_command_frame *c = (void *)fdtv->avc_data;
-	int ret;
-
-	mutex_lock(&fdtv->avc_mutex);
-
-	c->ctype   = AVC_CTYPE_CONTROL;
-	c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
-	c->opcode  = AVC_OPCODE_VENDOR;
-
-	c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
-	c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
-	c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
-	c->operand[3] = SFE_VENDOR_OPCODE_HOST2CA;
-	c->operand[4] = 0; /* slot */
-	c->operand[5] = SFE_VENDOR_TAG_CA_RESET; /* ca tag */
-	c->operand[6] = 0; /* more/last */
-	c->operand[7] = 1; /* length */
-	c->operand[8] = 0; /* force hardware reset */
-
-	fdtv->avc_data_length = 12;
-	ret = avc_write(fdtv);
-
-	/* FIXME: check response code? */
-
-	mutex_unlock(&fdtv->avc_mutex);
-
-	return ret;
-}
-
-int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length)
-{
-	struct avc_command_frame *c = (void *)fdtv->avc_data;
-	struct avc_response_frame *r = (void *)fdtv->avc_data;
-	int list_management;
-	int program_info_length;
-	int pmt_cmd_id;
-	int read_pos;
-	int write_pos;
-	int es_info_length;
-	int crc32_csum;
-	int ret;
-
-	if (unlikely(avc_debug & AVC_DEBUG_APPLICATION_PMT))
-		debug_pmt(msg, length);
-
-	mutex_lock(&fdtv->avc_mutex);
-
-	c->ctype   = AVC_CTYPE_CONTROL;
-	c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
-	c->opcode  = AVC_OPCODE_VENDOR;
-
-	if (msg[0] != EN50221_LIST_MANAGEMENT_ONLY) {
-		dev_info(fdtv->device, "forcing list_management to ONLY\n");
-		msg[0] = EN50221_LIST_MANAGEMENT_ONLY;
-	}
-	/* We take the cmd_id from the programme level only! */
-	list_management = msg[0];
-	program_info_length = ((msg[4] & 0x0f) << 8) + msg[5];
-	if (program_info_length > 0)
-		program_info_length--; /* Remove pmt_cmd_id */
-	pmt_cmd_id = msg[6];
-
-	c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
-	c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
-	c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
-	c->operand[3] = SFE_VENDOR_OPCODE_HOST2CA;
-	c->operand[4] = 0; /* slot */
-	c->operand[5] = SFE_VENDOR_TAG_CA_PMT; /* ca tag */
-	c->operand[6] = 0; /* more/last */
-	/* Use three bytes for length field in case length > 127 */
-	c->operand[10] = list_management;
-	c->operand[11] = 0x01; /* pmt_cmd=OK_descramble */
-
-	/* TS program map table */
-
-	c->operand[12] = 0x02; /* Table id=2 */
-	c->operand[13] = 0x80; /* Section syntax + length */
-
-	c->operand[15] = msg[1]; /* Program number */
-	c->operand[16] = msg[2];
-	c->operand[17] = msg[3]; /* Version number and current/next */
-	c->operand[18] = 0x00; /* Section number=0 */
-	c->operand[19] = 0x00; /* Last section number=0 */
-	c->operand[20] = 0x1f; /* PCR_PID=1FFF */
-	c->operand[21] = 0xff;
-	c->operand[22] = (program_info_length >> 8); /* Program info length */
-	c->operand[23] = (program_info_length & 0xff);
-
-	/* CA descriptors at programme level */
-	read_pos = 6;
-	write_pos = 24;
-	if (program_info_length > 0) {
-		pmt_cmd_id = msg[read_pos++];
-		if (pmt_cmd_id != 1 && pmt_cmd_id != 4)
-			dev_err(fdtv->device,
-				"invalid pmt_cmd_id %d\n", pmt_cmd_id);
-
-		memcpy(&c->operand[write_pos], &msg[read_pos],
-		       program_info_length);
-		read_pos += program_info_length;
-		write_pos += program_info_length;
-	}
-	while (read_pos < length) {
-		c->operand[write_pos++] = msg[read_pos++];
-		c->operand[write_pos++] = msg[read_pos++];
-		c->operand[write_pos++] = msg[read_pos++];
-		es_info_length =
-			((msg[read_pos] & 0x0f) << 8) + msg[read_pos + 1];
-		read_pos += 2;
-		if (es_info_length > 0)
-			es_info_length--; /* Remove pmt_cmd_id */
-		c->operand[write_pos++] = es_info_length >> 8;
-		c->operand[write_pos++] = es_info_length & 0xff;
-		if (es_info_length > 0) {
-			pmt_cmd_id = msg[read_pos++];
-			if (pmt_cmd_id != 1 && pmt_cmd_id != 4)
-				dev_err(fdtv->device, "invalid pmt_cmd_id %d "
-					"at stream level\n", pmt_cmd_id);
-
-			memcpy(&c->operand[write_pos], &msg[read_pos],
-			       es_info_length);
-			read_pos += es_info_length;
-			write_pos += es_info_length;
-		}
-	}
-	write_pos += 4; /* CRC */
-
-	c->operand[7] = 0x82;
-	c->operand[8] = (write_pos - 10) >> 8;
-	c->operand[9] = (write_pos - 10) & 0xff;
-	c->operand[14] = write_pos - 15;
-
-	crc32_csum = crc32_be(0, &c->operand[10], c->operand[12] - 1);
-	c->operand[write_pos - 4] = (crc32_csum >> 24) & 0xff;
-	c->operand[write_pos - 3] = (crc32_csum >> 16) & 0xff;
-	c->operand[write_pos - 2] = (crc32_csum >>  8) & 0xff;
-	c->operand[write_pos - 1] = (crc32_csum >>  0) & 0xff;
-	pad_operands(c, write_pos);
-
-	fdtv->avc_data_length = ALIGN(3 + write_pos, 4);
-	ret = avc_write(fdtv);
-	if (ret < 0)
-		goto out;
-
-	if (r->response != AVC_RESPONSE_ACCEPTED) {
-		dev_err(fdtv->device,
-			"CA PMT failed with response 0x%x\n", r->response);
-		ret = -EACCES;
-	}
-out:
-	mutex_unlock(&fdtv->avc_mutex);
-
-	return ret;
-}
-
-int avc_ca_get_time_date(struct firedtv *fdtv, int *interval)
-{
-	struct avc_command_frame *c = (void *)fdtv->avc_data;
-	struct avc_response_frame *r = (void *)fdtv->avc_data;
-	int ret;
-
-	mutex_lock(&fdtv->avc_mutex);
-
-	c->ctype   = AVC_CTYPE_STATUS;
-	c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
-	c->opcode  = AVC_OPCODE_VENDOR;
-
-	c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
-	c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
-	c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
-	c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST;
-	c->operand[4] = 0; /* slot */
-	c->operand[5] = SFE_VENDOR_TAG_CA_DATE_TIME; /* ca tag */
-	clear_operands(c, 6, LAST_OPERAND);
-
-	fdtv->avc_data_length = 12;
-	ret = avc_write(fdtv);
-	if (ret < 0)
-		goto out;
-
-	/* FIXME: check response code and validate response data */
-
-	*interval = r->operand[get_ca_object_pos(r)];
-out:
-	mutex_unlock(&fdtv->avc_mutex);
-
-	return ret;
-}
-
-int avc_ca_enter_menu(struct firedtv *fdtv)
-{
-	struct avc_command_frame *c = (void *)fdtv->avc_data;
-	int ret;
-
-	mutex_lock(&fdtv->avc_mutex);
-
-	c->ctype   = AVC_CTYPE_STATUS;
-	c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
-	c->opcode  = AVC_OPCODE_VENDOR;
-
-	c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
-	c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
-	c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
-	c->operand[3] = SFE_VENDOR_OPCODE_HOST2CA;
-	c->operand[4] = 0; /* slot */
-	c->operand[5] = SFE_VENDOR_TAG_CA_ENTER_MENU;
-	clear_operands(c, 6, 8);
-
-	fdtv->avc_data_length = 12;
-	ret = avc_write(fdtv);
-
-	/* FIXME: check response code? */
-
-	mutex_unlock(&fdtv->avc_mutex);
-
-	return ret;
-}
-
-int avc_ca_get_mmi(struct firedtv *fdtv, char *mmi_object, unsigned int *len)
-{
-	struct avc_command_frame *c = (void *)fdtv->avc_data;
-	struct avc_response_frame *r = (void *)fdtv->avc_data;
-	int ret;
-
-	mutex_lock(&fdtv->avc_mutex);
-
-	c->ctype   = AVC_CTYPE_STATUS;
-	c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
-	c->opcode  = AVC_OPCODE_VENDOR;
-
-	c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
-	c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
-	c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
-	c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST;
-	c->operand[4] = 0; /* slot */
-	c->operand[5] = SFE_VENDOR_TAG_CA_MMI;
-	clear_operands(c, 6, LAST_OPERAND);
-
-	fdtv->avc_data_length = 12;
-	ret = avc_write(fdtv);
-	if (ret < 0)
-		goto out;
-
-	/* FIXME: check response code and validate response data */
-
-	*len = get_ca_object_length(r);
-	memcpy(mmi_object, &r->operand[get_ca_object_pos(r)], *len);
-out:
-	mutex_unlock(&fdtv->avc_mutex);
-
-	return ret;
-}
-
-#define CMP_OUTPUT_PLUG_CONTROL_REG_0	0xfffff0000904ULL
-
-static int cmp_read(struct firedtv *fdtv, u64 addr, __be32 *data)
-{
-	int ret;
-
-	ret = fdtv_read(fdtv, addr, data);
-	if (ret < 0)
-		dev_err(fdtv->device, "CMP: read I/O error\n");
-
-	return ret;
-}
-
-static int cmp_lock(struct firedtv *fdtv, u64 addr, __be32 data[])
-{
-	int ret;
-
-	ret = fdtv_lock(fdtv, addr, data);
-	if (ret < 0)
-		dev_err(fdtv->device, "CMP: lock I/O error\n");
-
-	return ret;
-}
-
-static inline u32 get_opcr(__be32 opcr, u32 mask, u32 shift)
-{
-	return (be32_to_cpu(opcr) >> shift) & mask;
-}
-
-static inline void set_opcr(__be32 *opcr, u32 value, u32 mask, u32 shift)
-{
-	*opcr &= ~cpu_to_be32(mask << shift);
-	*opcr |= cpu_to_be32((value & mask) << shift);
-}
-
-#define get_opcr_online(v)		get_opcr((v), 0x1, 31)
-#define get_opcr_p2p_connections(v)	get_opcr((v), 0x3f, 24)
-#define get_opcr_channel(v)		get_opcr((v), 0x3f, 16)
-
-#define set_opcr_p2p_connections(p, v)	set_opcr((p), (v), 0x3f, 24)
-#define set_opcr_channel(p, v)		set_opcr((p), (v), 0x3f, 16)
-#define set_opcr_data_rate(p, v)	set_opcr((p), (v), 0x3, 14)
-#define set_opcr_overhead_id(p, v)	set_opcr((p), (v), 0xf, 10)
-
-int cmp_establish_pp_connection(struct firedtv *fdtv, int plug, int channel)
-{
-	__be32 old_opcr, opcr[2];
-	u64 opcr_address = CMP_OUTPUT_PLUG_CONTROL_REG_0 + (plug << 2);
-	int attempts = 0;
-	int ret;
-
-	ret = cmp_read(fdtv, opcr_address, opcr);
-	if (ret < 0)
-		return ret;
-
-repeat:
-	if (!get_opcr_online(*opcr)) {
-		dev_err(fdtv->device, "CMP: output offline\n");
-		return -EBUSY;
-	}
-
-	old_opcr = *opcr;
-
-	if (get_opcr_p2p_connections(*opcr)) {
-		if (get_opcr_channel(*opcr) != channel) {
-			dev_err(fdtv->device, "CMP: cannot change channel\n");
-			return -EBUSY;
-		}
-		dev_info(fdtv->device, "CMP: overlaying connection\n");
-
-		/* We don't allocate isochronous resources. */
-	} else {
-		set_opcr_channel(opcr, channel);
-		set_opcr_data_rate(opcr, 2); /* S400 */
-
-		/* FIXME: this is for the worst case - optimize */
-		set_opcr_overhead_id(opcr, 0);
-
-		/* FIXME: allocate isochronous channel and bandwidth at IRM */
-	}
-
-	set_opcr_p2p_connections(opcr, get_opcr_p2p_connections(*opcr) + 1);
-
-	opcr[1] = *opcr;
-	opcr[0] = old_opcr;
-
-	ret = cmp_lock(fdtv, opcr_address, opcr);
-	if (ret < 0)
-		return ret;
-
-	if (old_opcr != *opcr) {
-		/*
-		 * FIXME: if old_opcr.P2P_Connections > 0,
-		 * deallocate isochronous channel and bandwidth at IRM
-		 */
-
-		if (++attempts < 6) /* arbitrary limit */
-			goto repeat;
-		return -EBUSY;
-	}
-
-	return 0;
-}
-
-void cmp_break_pp_connection(struct firedtv *fdtv, int plug, int channel)
-{
-	__be32 old_opcr, opcr[2];
-	u64 opcr_address = CMP_OUTPUT_PLUG_CONTROL_REG_0 + (plug << 2);
-	int attempts = 0;
-
-	if (cmp_read(fdtv, opcr_address, opcr) < 0)
-		return;
-
-repeat:
-	if (!get_opcr_online(*opcr) || !get_opcr_p2p_connections(*opcr) ||
-	    get_opcr_channel(*opcr) != channel) {
-		dev_err(fdtv->device, "CMP: no connection to break\n");
-		return;
-	}
-
-	old_opcr = *opcr;
-	set_opcr_p2p_connections(opcr, get_opcr_p2p_connections(*opcr) - 1);
-
-	opcr[1] = *opcr;
-	opcr[0] = old_opcr;
-
-	if (cmp_lock(fdtv, opcr_address, opcr) < 0)
-		return;
-
-	if (old_opcr != *opcr) {
-		/*
-		 * FIXME: if old_opcr.P2P_Connections == 1, i.e. we were last
-		 * owner, deallocate isochronous channel and bandwidth at IRM
-		 * if (...)
-		 *	fdtv->backend->dealloc_resources(fdtv, channel, bw);
-		 */
-
-		if (++attempts < 6) /* arbitrary limit */
-			goto repeat;
-	}
-}
diff --git a/drivers/media/dvb/firewire/firedtv-ci.c b/drivers/media/dvb/firewire/firedtv-ci.c
deleted file mode 100644
index e5ebdbf..0000000
--- a/drivers/media/dvb/firewire/firedtv-ci.c
+++ /dev/null
@@ -1,258 +0,0 @@
-/*
- * FireDTV driver (formerly known as FireSAT)
- *
- * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com>
- * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se>
- *
- *	This program is free software; you can redistribute it and/or
- *	modify it under the terms of the GNU General Public License as
- *	published by the Free Software Foundation; either version 2 of
- *	the License, or (at your option) any later version.
- */
-
-#include <linux/device.h>
-#include <linux/dvb/ca.h>
-#include <linux/fs.h>
-#include <linux/module.h>
-
-#include <dvbdev.h>
-
-#include "firedtv.h"
-
-#define EN50221_TAG_APP_INFO_ENQUIRY	0x9f8020
-#define EN50221_TAG_CA_INFO_ENQUIRY	0x9f8030
-#define EN50221_TAG_CA_PMT		0x9f8032
-#define EN50221_TAG_ENTER_MENU		0x9f8022
-
-static int fdtv_ca_ready(struct firedtv_tuner_status *stat)
-{
-	return stat->ca_initialization_status	== 1 &&
-	       stat->ca_error_flag		== 0 &&
-	       stat->ca_dvb_flag		== 1 &&
-	       stat->ca_module_present_status	== 1;
-}
-
-static int fdtv_get_ca_flags(struct firedtv_tuner_status *stat)
-{
-	int flags = 0;
-
-	if (stat->ca_module_present_status == 1)
-		flags |= CA_CI_MODULE_PRESENT;
-	if (stat->ca_initialization_status == 1 &&
-	    stat->ca_error_flag            == 0 &&
-	    stat->ca_dvb_flag              == 1)
-		flags |= CA_CI_MODULE_READY;
-	return flags;
-}
-
-static int fdtv_ca_get_caps(void *arg)
-{
-	struct ca_caps *cap = arg;
-
-	cap->slot_num = 1;
-	cap->slot_type = CA_CI;
-	cap->descr_num = 1;
-	cap->descr_type = CA_ECD;
-	return 0;
-}
-
-static int fdtv_ca_get_slot_info(struct firedtv *fdtv, void *arg)
-{
-	struct firedtv_tuner_status stat;
-	struct ca_slot_info *slot = arg;
-	int err;
-
-	err = avc_tuner_status(fdtv, &stat);
-	if (err)
-		return err;
-
-	if (slot->num != 0)
-		return -EACCES;
-
-	slot->type = CA_CI;
-	slot->flags = fdtv_get_ca_flags(&stat);
-	return 0;
-}
-
-static int fdtv_ca_app_info(struct firedtv *fdtv, void *arg)
-{
-	struct ca_msg *reply = arg;
-
-	return avc_ca_app_info(fdtv, reply->msg, &reply->length);
-}
-
-static int fdtv_ca_info(struct firedtv *fdtv, void *arg)
-{
-	struct ca_msg *reply = arg;
-
-	return avc_ca_info(fdtv, reply->msg, &reply->length);
-}
-
-static int fdtv_ca_get_mmi(struct firedtv *fdtv, void *arg)
-{
-	struct ca_msg *reply = arg;
-
-	return avc_ca_get_mmi(fdtv, reply->msg, &reply->length);
-}
-
-static int fdtv_ca_get_msg(struct firedtv *fdtv, void *arg)
-{
-	struct firedtv_tuner_status stat;
-	int err;
-
-	switch (fdtv->ca_last_command) {
-	case EN50221_TAG_APP_INFO_ENQUIRY:
-		err = fdtv_ca_app_info(fdtv, arg);
-		break;
-	case EN50221_TAG_CA_INFO_ENQUIRY:
-		err = fdtv_ca_info(fdtv, arg);
-		break;
-	default:
-		err = avc_tuner_status(fdtv, &stat);
-		if (err)
-			break;
-		if (stat.ca_mmi == 1)
-			err = fdtv_ca_get_mmi(fdtv, arg);
-		else {
-			dev_info(fdtv->device, "unhandled CA message 0x%08x\n",
-				 fdtv->ca_last_command);
-			err = -EACCES;
-		}
-	}
-	fdtv->ca_last_command = 0;
-	return err;
-}
-
-static int fdtv_ca_pmt(struct firedtv *fdtv, void *arg)
-{
-	struct ca_msg *msg = arg;
-	int data_pos;
-	int data_length;
-	int i;
-
-	data_pos = 4;
-	if (msg->msg[3] & 0x80) {
-		data_length = 0;
-		for (i = 0; i < (msg->msg[3] & 0x7f); i++)
-			data_length = (data_length << 8) + msg->msg[data_pos++];
-	} else {
-		data_length = msg->msg[3];
-	}
-
-	return avc_ca_pmt(fdtv, &msg->msg[data_pos], data_length);
-}
-
-static int fdtv_ca_send_msg(struct firedtv *fdtv, void *arg)
-{
-	struct ca_msg *msg = arg;
-	int err;
-
-	/* Do we need a semaphore for this? */
-	fdtv->ca_last_command =
-		(msg->msg[0] << 16) + (msg->msg[1] << 8) + msg->msg[2];
-	switch (fdtv->ca_last_command) {
-	case EN50221_TAG_CA_PMT:
-		err = fdtv_ca_pmt(fdtv, arg);
-		break;
-	case EN50221_TAG_APP_INFO_ENQUIRY:
-		/* handled in ca_get_msg */
-		err = 0;
-		break;
-	case EN50221_TAG_CA_INFO_ENQUIRY:
-		/* handled in ca_get_msg */
-		err = 0;
-		break;
-	case EN50221_TAG_ENTER_MENU:
-		err = avc_ca_enter_menu(fdtv);
-		break;
-	default:
-		dev_err(fdtv->device, "unhandled CA message 0x%08x\n",
-			fdtv->ca_last_command);
-		err = -EACCES;
-	}
-	return err;
-}
-
-static int fdtv_ca_ioctl(struct file *file, unsigned int cmd, void *arg)
-{
-	struct dvb_device *dvbdev = file->private_data;
-	struct firedtv *fdtv = dvbdev->priv;
-	struct firedtv_tuner_status stat;
-	int err;
-
-	switch (cmd) {
-	case CA_RESET:
-		err = avc_ca_reset(fdtv);
-		break;
-	case CA_GET_CAP:
-		err = fdtv_ca_get_caps(arg);
-		break;
-	case CA_GET_SLOT_INFO:
-		err = fdtv_ca_get_slot_info(fdtv, arg);
-		break;
-	case CA_GET_MSG:
-		err = fdtv_ca_get_msg(fdtv, arg);
-		break;
-	case CA_SEND_MSG:
-		err = fdtv_ca_send_msg(fdtv, arg);
-		break;
-	default:
-		dev_info(fdtv->device, "unhandled CA ioctl %u\n", cmd);
-		err = -EOPNOTSUPP;
-	}
-
-	/* FIXME Is this necessary? */
-	avc_tuner_status(fdtv, &stat);
-
-	return err;
-}
-
-static unsigned int fdtv_ca_io_poll(struct file *file, poll_table *wait)
-{
-	return POLLIN;
-}
-
-static const struct file_operations fdtv_ca_fops = {
-	.owner		= THIS_MODULE,
-	.unlocked_ioctl	= dvb_generic_ioctl,
-	.open		= dvb_generic_open,
-	.release	= dvb_generic_release,
-	.poll		= fdtv_ca_io_poll,
-	.llseek		= noop_llseek,
-};
-
-static struct dvb_device fdtv_ca = {
-	.users		= 1,
-	.readers	= 1,
-	.writers	= 1,
-	.fops		= &fdtv_ca_fops,
-	.kernel_ioctl	= fdtv_ca_ioctl,
-};
-
-int fdtv_ca_register(struct firedtv *fdtv)
-{
-	struct firedtv_tuner_status stat;
-	int err;
-
-	if (avc_tuner_status(fdtv, &stat))
-		return -EINVAL;
-
-	if (!fdtv_ca_ready(&stat))
-		return -EFAULT;
-
-	err = dvb_register_device(&fdtv->adapter, &fdtv->cadev,
-				  &fdtv_ca, fdtv, DVB_DEVICE_CA);
-
-	if (stat.ca_application_info == 0)
-		dev_err(fdtv->device, "CaApplicationInfo is not set\n");
-	if (stat.ca_date_time_request == 1)
-		avc_ca_get_time_date(fdtv, &fdtv->ca_time_interval);
-
-	return err;
-}
-
-void fdtv_ca_release(struct firedtv *fdtv)
-{
-	if (fdtv->cadev)
-		dvb_unregister_device(fdtv->cadev);
-}
diff --git a/drivers/media/dvb/firewire/firedtv-dvb.c b/drivers/media/dvb/firewire/firedtv-dvb.c
deleted file mode 100644
index eb7496e..0000000
--- a/drivers/media/dvb/firewire/firedtv-dvb.c
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
- * FireDTV driver (formerly known as FireSAT)
- *
- * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com>
- * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se>
- *
- *	This program is free software; you can redistribute it and/or
- *	modify it under the terms of the 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/bitops.h>
-#include <linux/device.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/types.h>
-
-#include <dmxdev.h>
-#include <dvb_demux.h>
-#include <dvbdev.h>
-#include <dvb_frontend.h>
-
-#include "firedtv.h"
-
-static int alloc_channel(struct firedtv *fdtv)
-{
-	int i;
-
-	for (i = 0; i < 16; i++)
-		if (!__test_and_set_bit(i, &fdtv->channel_active))
-			break;
-	return i;
-}
-
-static void collect_channels(struct firedtv *fdtv, int *pidc, u16 pid[])
-{
-	int i, n;
-
-	for (i = 0, n = 0; i < 16; i++)
-		if (test_bit(i, &fdtv->channel_active))
-			pid[n++] = fdtv->channel_pid[i];
-	*pidc = n;
-}
-
-static inline void dealloc_channel(struct firedtv *fdtv, int i)
-{
-	__clear_bit(i, &fdtv->channel_active);
-}
-
-int fdtv_start_feed(struct dvb_demux_feed *dvbdmxfeed)
-{
-	struct firedtv *fdtv = dvbdmxfeed->demux->priv;
-	int pidc, c, ret;
-	u16 pids[16];
-
-	switch (dvbdmxfeed->type) {
-	case DMX_TYPE_TS:
-	case DMX_TYPE_SEC:
-		break;
-	default:
-		dev_err(fdtv->device, "can't start dmx feed: invalid type %u\n",
-			dvbdmxfeed->type);
-		return -EINVAL;
-	}
-
-	if (mutex_lock_interruptible(&fdtv->demux_mutex))
-		return -EINTR;
-
-	if (dvbdmxfeed->type == DMX_TYPE_TS) {
-		switch (dvbdmxfeed->pes_type) {
-		case DMX_TS_PES_VIDEO:
-		case DMX_TS_PES_AUDIO:
-		case DMX_TS_PES_TELETEXT:
-		case DMX_TS_PES_PCR:
-		case DMX_TS_PES_OTHER:
-			c = alloc_channel(fdtv);
-			break;
-		default:
-			dev_err(fdtv->device,
-				"can't start dmx feed: invalid pes type %u\n",
-				dvbdmxfeed->pes_type);
-			ret = -EINVAL;
-			goto out;
-		}
-	} else {
-		c = alloc_channel(fdtv);
-	}
-
-	if (c > 15) {
-		dev_err(fdtv->device, "can't start dmx feed: busy\n");
-		ret = -EBUSY;
-		goto out;
-	}
-
-	dvbdmxfeed->priv = (typeof(dvbdmxfeed->priv))(unsigned long)c;
-	fdtv->channel_pid[c] = dvbdmxfeed->pid;
-	collect_channels(fdtv, &pidc, pids);
-
-	if (dvbdmxfeed->pid == 8192) {
-		ret = avc_tuner_get_ts(fdtv);
-		if (ret) {
-			dealloc_channel(fdtv, c);
-			dev_err(fdtv->device, "can't get TS\n");
-			goto out;
-		}
-	} else {
-		ret = avc_tuner_set_pids(fdtv, pidc, pids);
-		if (ret) {
-			dealloc_channel(fdtv, c);
-			dev_err(fdtv->device, "can't set PIDs\n");
-			goto out;
-		}
-	}
-out:
-	mutex_unlock(&fdtv->demux_mutex);
-
-	return ret;
-}
-
-int fdtv_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
-{
-	struct dvb_demux *demux = dvbdmxfeed->demux;
-	struct firedtv *fdtv = demux->priv;
-	int pidc, c, ret;
-	u16 pids[16];
-
-	if (dvbdmxfeed->type == DMX_TYPE_TS &&
-	    !((dvbdmxfeed->ts_type & TS_PACKET) &&
-	      (demux->dmx.frontend->source != DMX_MEMORY_FE))) {
-
-		if (dvbdmxfeed->ts_type & TS_DECODER) {
-			if (dvbdmxfeed->pes_type >= DMX_TS_PES_OTHER ||
-			    !demux->pesfilter[dvbdmxfeed->pes_type])
-				return -EINVAL;
-
-			demux->pids[dvbdmxfeed->pes_type] |= 0x8000;
-			demux->pesfilter[dvbdmxfeed->pes_type] = NULL;
-		}
-
-		if (!(dvbdmxfeed->ts_type & TS_DECODER &&
-		      dvbdmxfeed->pes_type < DMX_TS_PES_OTHER))
-			return 0;
-	}
-
-	if (mutex_lock_interruptible(&fdtv->demux_mutex))
-		return -EINTR;
-
-	c = (unsigned long)dvbdmxfeed->priv;
-	dealloc_channel(fdtv, c);
-	collect_channels(fdtv, &pidc, pids);
-
-	ret = avc_tuner_set_pids(fdtv, pidc, pids);
-
-	mutex_unlock(&fdtv->demux_mutex);
-
-	return ret;
-}
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-int fdtv_dvb_register(struct firedtv *fdtv, const char *name)
-{
-	int err;
-
-	err = dvb_register_adapter(&fdtv->adapter, name,
-				   THIS_MODULE, fdtv->device, adapter_nr);
-	if (err < 0)
-		goto fail_log;
-
-	/*DMX_TS_FILTERING | DMX_SECTION_FILTERING*/
-	fdtv->demux.dmx.capabilities = 0;
-
-	fdtv->demux.priv	= fdtv;
-	fdtv->demux.filternum	= 16;
-	fdtv->demux.feednum	= 16;
-	fdtv->demux.start_feed	= fdtv_start_feed;
-	fdtv->demux.stop_feed	= fdtv_stop_feed;
-	fdtv->demux.write_to_decoder = NULL;
-
-	err = dvb_dmx_init(&fdtv->demux);
-	if (err)
-		goto fail_unreg_adapter;
-
-	fdtv->dmxdev.filternum    = 16;
-	fdtv->dmxdev.demux        = &fdtv->demux.dmx;
-	fdtv->dmxdev.capabilities = 0;
-
-	err = dvb_dmxdev_init(&fdtv->dmxdev, &fdtv->adapter);
-	if (err)
-		goto fail_dmx_release;
-
-	fdtv->frontend.source = DMX_FRONTEND_0;
-
-	err = fdtv->demux.dmx.add_frontend(&fdtv->demux.dmx, &fdtv->frontend);
-	if (err)
-		goto fail_dmxdev_release;
-
-	err = fdtv->demux.dmx.connect_frontend(&fdtv->demux.dmx,
-					       &fdtv->frontend);
-	if (err)
-		goto fail_rem_frontend;
-
-	err = dvb_net_init(&fdtv->adapter, &fdtv->dvbnet, &fdtv->demux.dmx);
-	if (err)
-		goto fail_disconnect_frontend;
-
-	fdtv_frontend_init(fdtv, name);
-	err = dvb_register_frontend(&fdtv->adapter, &fdtv->fe);
-	if (err)
-		goto fail_net_release;
-
-	err = fdtv_ca_register(fdtv);
-	if (err)
-		dev_info(fdtv->device,
-			 "Conditional Access Module not enabled\n");
-	return 0;
-
-fail_net_release:
-	dvb_net_release(&fdtv->dvbnet);
-fail_disconnect_frontend:
-	fdtv->demux.dmx.close(&fdtv->demux.dmx);
-fail_rem_frontend:
-	fdtv->demux.dmx.remove_frontend(&fdtv->demux.dmx, &fdtv->frontend);
-fail_dmxdev_release:
-	dvb_dmxdev_release(&fdtv->dmxdev);
-fail_dmx_release:
-	dvb_dmx_release(&fdtv->demux);
-fail_unreg_adapter:
-	dvb_unregister_adapter(&fdtv->adapter);
-fail_log:
-	dev_err(fdtv->device, "DVB initialization failed\n");
-	return err;
-}
-
-void fdtv_dvb_unregister(struct firedtv *fdtv)
-{
-	fdtv_ca_release(fdtv);
-	dvb_unregister_frontend(&fdtv->fe);
-	dvb_net_release(&fdtv->dvbnet);
-	fdtv->demux.dmx.close(&fdtv->demux.dmx);
-	fdtv->demux.dmx.remove_frontend(&fdtv->demux.dmx, &fdtv->frontend);
-	dvb_dmxdev_release(&fdtv->dmxdev);
-	dvb_dmx_release(&fdtv->demux);
-	dvb_unregister_adapter(&fdtv->adapter);
-}
diff --git a/drivers/media/dvb/firewire/firedtv-fe.c b/drivers/media/dvb/firewire/firedtv-fe.c
deleted file mode 100644
index 6fe9793..0000000
--- a/drivers/media/dvb/firewire/firedtv-fe.c
+++ /dev/null
@@ -1,254 +0,0 @@
-/*
- * FireDTV driver (formerly known as FireSAT)
- *
- * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com>
- * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se>
- *
- *	This program is free software; you can redistribute it and/or
- *	modify it under the terms of the GNU General Public License as
- *	published by the Free Software Foundation; either version 2 of
- *	the License, or (at your option) any later version.
- */
-
-#include <linux/device.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/types.h>
-
-#include <dvb_frontend.h>
-
-#include "firedtv.h"
-
-static int fdtv_dvb_init(struct dvb_frontend *fe)
-{
-	struct firedtv *fdtv = fe->sec_priv;
-	int err;
-
-	/* FIXME - allocate free channel at IRM */
-	fdtv->isochannel = fdtv->adapter.num;
-
-	err = cmp_establish_pp_connection(fdtv, fdtv->subunit,
-					  fdtv->isochannel);
-	if (err) {
-		dev_err(fdtv->device,
-			"could not establish point to point connection\n");
-		return err;
-	}
-
-	return fdtv_start_iso(fdtv);
-}
-
-static int fdtv_sleep(struct dvb_frontend *fe)
-{
-	struct firedtv *fdtv = fe->sec_priv;
-
-	fdtv_stop_iso(fdtv);
-	cmp_break_pp_connection(fdtv, fdtv->subunit, fdtv->isochannel);
-	fdtv->isochannel = -1;
-	return 0;
-}
-
-#define LNBCONTROL_DONTCARE 0xff
-
-static int fdtv_diseqc_send_master_cmd(struct dvb_frontend *fe,
-				       struct dvb_diseqc_master_cmd *cmd)
-{
-	struct firedtv *fdtv = fe->sec_priv;
-
-	return avc_lnb_control(fdtv, LNBCONTROL_DONTCARE, LNBCONTROL_DONTCARE,
-			       LNBCONTROL_DONTCARE, 1, cmd);
-}
-
-static int fdtv_diseqc_send_burst(struct dvb_frontend *fe,
-				  fe_sec_mini_cmd_t minicmd)
-{
-	return 0;
-}
-
-static int fdtv_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
-{
-	struct firedtv *fdtv = fe->sec_priv;
-
-	fdtv->tone = tone;
-	return 0;
-}
-
-static int fdtv_set_voltage(struct dvb_frontend *fe,
-			    fe_sec_voltage_t voltage)
-{
-	struct firedtv *fdtv = fe->sec_priv;
-
-	fdtv->voltage = voltage;
-	return 0;
-}
-
-static int fdtv_read_status(struct dvb_frontend *fe, fe_status_t *status)
-{
-	struct firedtv *fdtv = fe->sec_priv;
-	struct firedtv_tuner_status stat;
-
-	if (avc_tuner_status(fdtv, &stat))
-		return -EINVAL;
-
-	if (stat.no_rf)
-		*status = 0;
-	else
-		*status = FE_HAS_SIGNAL | FE_HAS_VITERBI | FE_HAS_SYNC |
-			  FE_HAS_CARRIER | FE_HAS_LOCK;
-	return 0;
-}
-
-static int fdtv_read_ber(struct dvb_frontend *fe, u32 *ber)
-{
-	struct firedtv *fdtv = fe->sec_priv;
-	struct firedtv_tuner_status stat;
-
-	if (avc_tuner_status(fdtv, &stat))
-		return -EINVAL;
-
-	*ber = stat.ber;
-	return 0;
-}
-
-static int fdtv_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
-{
-	struct firedtv *fdtv = fe->sec_priv;
-	struct firedtv_tuner_status stat;
-
-	if (avc_tuner_status(fdtv, &stat))
-		return -EINVAL;
-
-	*strength = stat.signal_strength << 8;
-	return 0;
-}
-
-static int fdtv_read_snr(struct dvb_frontend *fe, u16 *snr)
-{
-	struct firedtv *fdtv = fe->sec_priv;
-	struct firedtv_tuner_status stat;
-
-	if (avc_tuner_status(fdtv, &stat))
-		return -EINVAL;
-
-	/* C/N[dB] = -10 * log10(snr / 65535) */
-	*snr = stat.carrier_noise_ratio * 257;
-	return 0;
-}
-
-static int fdtv_read_uncorrected_blocks(struct dvb_frontend *fe, u32 *ucblocks)
-{
-	return -EOPNOTSUPP;
-}
-
-static int fdtv_set_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct firedtv *fdtv = fe->sec_priv;
-
-	return avc_tuner_dsd(fdtv, p);
-}
-
-void fdtv_frontend_init(struct firedtv *fdtv, const char *name)
-{
-	struct dvb_frontend_ops *ops = &fdtv->fe.ops;
-	struct dvb_frontend_info *fi = &ops->info;
-
-	ops->init			= fdtv_dvb_init;
-	ops->sleep			= fdtv_sleep;
-
-	ops->set_frontend		= fdtv_set_frontend;
-
-	ops->read_status		= fdtv_read_status;
-	ops->read_ber			= fdtv_read_ber;
-	ops->read_signal_strength	= fdtv_read_signal_strength;
-	ops->read_snr			= fdtv_read_snr;
-	ops->read_ucblocks		= fdtv_read_uncorrected_blocks;
-
-	ops->diseqc_send_master_cmd 	= fdtv_diseqc_send_master_cmd;
-	ops->diseqc_send_burst		= fdtv_diseqc_send_burst;
-	ops->set_tone			= fdtv_set_tone;
-	ops->set_voltage		= fdtv_set_voltage;
-
-	switch (fdtv->type) {
-	case FIREDTV_DVB_S:
-		ops->delsys[0]		= SYS_DVBS;
-
-		fi->frequency_min	= 950000;
-		fi->frequency_max	= 2150000;
-		fi->frequency_stepsize	= 125;
-		fi->symbol_rate_min	= 1000000;
-		fi->symbol_rate_max	= 40000000;
-
-		fi->caps		= FE_CAN_INVERSION_AUTO |
-					  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_FEC_AUTO	|
-					  FE_CAN_QPSK;
-		break;
-
-	case FIREDTV_DVB_S2:
-		ops->delsys[0]		= SYS_DVBS;
-		ops->delsys[1]		= SYS_DVBS2;
-
-		fi->frequency_min	= 950000;
-		fi->frequency_max	= 2150000;
-		fi->frequency_stepsize	= 125;
-		fi->symbol_rate_min	= 1000000;
-		fi->symbol_rate_max	= 40000000;
-
-		fi->caps		= FE_CAN_INVERSION_AUTO |
-					  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_FEC_AUTO       |
-					  FE_CAN_QPSK           |
-					  FE_CAN_2G_MODULATION;
-		break;
-
-	case FIREDTV_DVB_C:
-		ops->delsys[0]		= SYS_DVBC_ANNEX_A;
-
-		fi->frequency_min	= 47000000;
-		fi->frequency_max	= 866000000;
-		fi->frequency_stepsize	= 62500;
-		fi->symbol_rate_min	= 870000;
-		fi->symbol_rate_max	= 6900000;
-
-		fi->caps 		= FE_CAN_INVERSION_AUTO |
-					  FE_CAN_QAM_16		|
-					  FE_CAN_QAM_32		|
-					  FE_CAN_QAM_64		|
-					  FE_CAN_QAM_128	|
-					  FE_CAN_QAM_256	|
-					  FE_CAN_QAM_AUTO;
-		break;
-
-	case FIREDTV_DVB_T:
-		ops->delsys[0]		= SYS_DVBT;
-
-		fi->frequency_min	= 49000000;
-		fi->frequency_max	= 861000000;
-		fi->frequency_stepsize	= 62500;
-
-		fi->caps 		= FE_CAN_INVERSION_AUTO		|
-					  FE_CAN_FEC_2_3		|
-					  FE_CAN_TRANSMISSION_MODE_AUTO |
-					  FE_CAN_GUARD_INTERVAL_AUTO	|
-					  FE_CAN_HIERARCHY_AUTO;
-		break;
-
-	default:
-		dev_err(fdtv->device, "no frontend for model type %d\n",
-			fdtv->type);
-	}
-	strcpy(fi->name, name);
-
-	fdtv->fe.dvb = &fdtv->adapter;
-	fdtv->fe.sec_priv = fdtv;
-}
diff --git a/drivers/media/dvb/firewire/firedtv-fw.c b/drivers/media/dvb/firewire/firedtv-fw.c
deleted file mode 100644
index e24ec53..0000000
--- a/drivers/media/dvb/firewire/firedtv-fw.c
+++ /dev/null
@@ -1,429 +0,0 @@
-/*
- * FireDTV driver -- firewire I/O backend
- */
-
-#include <linux/device.h>
-#include <linux/errno.h>
-#include <linux/firewire.h>
-#include <linux/firewire-constants.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/mm.h>
-#include <linux/mod_devicetable.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/string.h>
-#include <linux/types.h>
-#include <linux/wait.h>
-#include <linux/workqueue.h>
-
-#include <asm/page.h>
-
-#include <dvb_demux.h>
-
-#include "firedtv.h"
-
-static LIST_HEAD(node_list);
-static DEFINE_SPINLOCK(node_list_lock);
-
-static inline struct fw_device *device_of(struct firedtv *fdtv)
-{
-	return fw_device(fdtv->device->parent);
-}
-
-static int node_req(struct firedtv *fdtv, u64 addr, void *data, size_t len,
-		    int tcode)
-{
-	struct fw_device *device = device_of(fdtv);
-	int rcode, generation = device->generation;
-
-	smp_rmb(); /* node_id vs. generation */
-
-	rcode = fw_run_transaction(device->card, tcode, device->node_id,
-			generation, device->max_speed, addr, data, len);
-
-	return rcode != RCODE_COMPLETE ? -EIO : 0;
-}
-
-int fdtv_lock(struct firedtv *fdtv, u64 addr, void *data)
-{
-	return node_req(fdtv, addr, data, 8, TCODE_LOCK_COMPARE_SWAP);
-}
-
-int fdtv_read(struct firedtv *fdtv, u64 addr, void *data)
-{
-	return node_req(fdtv, addr, data, 4, TCODE_READ_QUADLET_REQUEST);
-}
-
-int fdtv_write(struct firedtv *fdtv, u64 addr, void *data, size_t len)
-{
-	return node_req(fdtv, addr, data, len, TCODE_WRITE_BLOCK_REQUEST);
-}
-
-#define ISO_HEADER_SIZE			4
-#define CIP_HEADER_SIZE			8
-#define MPEG2_TS_HEADER_SIZE		4
-#define MPEG2_TS_SOURCE_PACKET_SIZE	(4 + 188)
-
-#define MAX_PACKET_SIZE		1024  /* 776, rounded up to 2^n */
-#define PACKETS_PER_PAGE	(PAGE_SIZE / MAX_PACKET_SIZE)
-#define N_PACKETS		64    /* buffer size */
-#define N_PAGES			DIV_ROUND_UP(N_PACKETS, PACKETS_PER_PAGE)
-#define IRQ_INTERVAL		16
-
-struct fdtv_ir_context {
-	struct fw_iso_context *context;
-	struct fw_iso_buffer buffer;
-	int interrupt_packet;
-	int current_packet;
-	char *pages[N_PAGES];
-};
-
-static int queue_iso(struct fdtv_ir_context *ctx, int index)
-{
-	struct fw_iso_packet p;
-
-	p.payload_length = MAX_PACKET_SIZE;
-	p.interrupt = !(++ctx->interrupt_packet & (IRQ_INTERVAL - 1));
-	p.skip = 0;
-	p.header_length = ISO_HEADER_SIZE;
-
-	return fw_iso_context_queue(ctx->context, &p, &ctx->buffer,
-				    index * MAX_PACKET_SIZE);
-}
-
-static void handle_iso(struct fw_iso_context *context, u32 cycle,
-		       size_t header_length, void *header, void *data)
-{
-	struct firedtv *fdtv = data;
-	struct fdtv_ir_context *ctx = fdtv->ir_context;
-	__be32 *h, *h_end;
-	int length, err, i = ctx->current_packet;
-	char *p, *p_end;
-
-	for (h = header, h_end = h + header_length / 4; h < h_end; h++) {
-		length = be32_to_cpup(h) >> 16;
-		if (unlikely(length > MAX_PACKET_SIZE)) {
-			dev_err(fdtv->device, "length = %d\n", length);
-			length = MAX_PACKET_SIZE;
-		}
-
-		p = ctx->pages[i / PACKETS_PER_PAGE]
-				+ (i % PACKETS_PER_PAGE) * MAX_PACKET_SIZE;
-		p_end = p + length;
-
-		for (p += CIP_HEADER_SIZE + MPEG2_TS_HEADER_SIZE; p < p_end;
-		     p += MPEG2_TS_SOURCE_PACKET_SIZE)
-			dvb_dmx_swfilter_packets(&fdtv->demux, p, 1);
-
-		err = queue_iso(ctx, i);
-		if (unlikely(err))
-			dev_err(fdtv->device, "requeue failed\n");
-
-		i = (i + 1) & (N_PACKETS - 1);
-	}
-	fw_iso_context_queue_flush(ctx->context);
-	ctx->current_packet = i;
-}
-
-int fdtv_start_iso(struct firedtv *fdtv)
-{
-	struct fdtv_ir_context *ctx;
-	struct fw_device *device = device_of(fdtv);
-	int i, err;
-
-	ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
-	if (!ctx)
-		return -ENOMEM;
-
-	ctx->context = fw_iso_context_create(device->card,
-			FW_ISO_CONTEXT_RECEIVE, fdtv->isochannel,
-			device->max_speed, ISO_HEADER_SIZE, handle_iso, fdtv);
-	if (IS_ERR(ctx->context)) {
-		err = PTR_ERR(ctx->context);
-		goto fail_free;
-	}
-
-	err = fw_iso_buffer_init(&ctx->buffer, device->card,
-				 N_PAGES, DMA_FROM_DEVICE);
-	if (err)
-		goto fail_context_destroy;
-
-	ctx->interrupt_packet = 0;
-	ctx->current_packet = 0;
-
-	for (i = 0; i < N_PAGES; i++)
-		ctx->pages[i] = page_address(ctx->buffer.pages[i]);
-
-	for (i = 0; i < N_PACKETS; i++) {
-		err = queue_iso(ctx, i);
-		if (err)
-			goto fail;
-	}
-
-	err = fw_iso_context_start(ctx->context, -1, 0,
-				   FW_ISO_CONTEXT_MATCH_ALL_TAGS);
-	if (err)
-		goto fail;
-
-	fdtv->ir_context = ctx;
-
-	return 0;
-fail:
-	fw_iso_buffer_destroy(&ctx->buffer, device->card);
-fail_context_destroy:
-	fw_iso_context_destroy(ctx->context);
-fail_free:
-	kfree(ctx);
-
-	return err;
-}
-
-void fdtv_stop_iso(struct firedtv *fdtv)
-{
-	struct fdtv_ir_context *ctx = fdtv->ir_context;
-
-	fw_iso_context_stop(ctx->context);
-	fw_iso_buffer_destroy(&ctx->buffer, device_of(fdtv)->card);
-	fw_iso_context_destroy(ctx->context);
-	kfree(ctx);
-}
-
-static void handle_fcp(struct fw_card *card, struct fw_request *request,
-		       int tcode, int destination, int source, int generation,
-		       unsigned long long offset, void *payload, size_t length,
-		       void *callback_data)
-{
-	struct firedtv *f, *fdtv = NULL;
-	struct fw_device *device;
-	unsigned long flags;
-	int su;
-
-	if (length < 2 || (((u8 *)payload)[0] & 0xf0) != 0)
-		return;
-
-	su = ((u8 *)payload)[1] & 0x7;
-
-	spin_lock_irqsave(&node_list_lock, flags);
-	list_for_each_entry(f, &node_list, list) {
-		device = device_of(f);
-		if (device->generation != generation)
-			continue;
-
-		smp_rmb(); /* node_id vs. generation */
-
-		if (device->card == card &&
-		    device->node_id == source &&
-		    (f->subunit == su || (f->subunit == 0 && su == 0x7))) {
-			fdtv = f;
-			break;
-		}
-	}
-	spin_unlock_irqrestore(&node_list_lock, flags);
-
-	if (fdtv)
-		avc_recv(fdtv, payload, length);
-}
-
-static struct fw_address_handler fcp_handler = {
-	.length           = CSR_FCP_END - CSR_FCP_RESPONSE,
-	.address_callback = handle_fcp,
-};
-
-static const struct fw_address_region fcp_region = {
-	.start	= CSR_REGISTER_BASE + CSR_FCP_RESPONSE,
-	.end	= CSR_REGISTER_BASE + CSR_FCP_END,
-};
-
-static const char * const model_names[] = {
-	[FIREDTV_UNKNOWN] = "unknown type",
-	[FIREDTV_DVB_S]   = "FireDTV S/CI",
-	[FIREDTV_DVB_C]   = "FireDTV C/CI",
-	[FIREDTV_DVB_T]   = "FireDTV T/CI",
-	[FIREDTV_DVB_S2]  = "FireDTV S2  ",
-};
-
-/* Adjust the template string if models with longer names appear. */
-#define MAX_MODEL_NAME_LEN sizeof("FireDTV ????")
-
-static int node_probe(struct device *dev)
-{
-	struct firedtv *fdtv;
-	char name[MAX_MODEL_NAME_LEN];
-	int name_len, i, err;
-
-	fdtv = kzalloc(sizeof(*fdtv), GFP_KERNEL);
-	if (!fdtv)
-		return -ENOMEM;
-
-	dev_set_drvdata(dev, fdtv);
-	fdtv->device		= dev;
-	fdtv->isochannel	= -1;
-	fdtv->voltage		= 0xff;
-	fdtv->tone		= 0xff;
-
-	mutex_init(&fdtv->avc_mutex);
-	init_waitqueue_head(&fdtv->avc_wait);
-	mutex_init(&fdtv->demux_mutex);
-	INIT_WORK(&fdtv->remote_ctrl_work, avc_remote_ctrl_work);
-
-	name_len = fw_csr_string(fw_unit(dev)->directory, CSR_MODEL,
-				 name, sizeof(name));
-	for (i = ARRAY_SIZE(model_names); --i; )
-		if (strlen(model_names[i]) <= name_len &&
-		    strncmp(name, model_names[i], name_len) == 0)
-			break;
-	fdtv->type = i;
-
-	err = fdtv_register_rc(fdtv, dev);
-	if (err)
-		goto fail_free;
-
-	spin_lock_irq(&node_list_lock);
-	list_add_tail(&fdtv->list, &node_list);
-	spin_unlock_irq(&node_list_lock);
-
-	err = avc_identify_subunit(fdtv);
-	if (err)
-		goto fail;
-
-	err = fdtv_dvb_register(fdtv, model_names[fdtv->type]);
-	if (err)
-		goto fail;
-
-	avc_register_remote_control(fdtv);
-
-	return 0;
-fail:
-	spin_lock_irq(&node_list_lock);
-	list_del(&fdtv->list);
-	spin_unlock_irq(&node_list_lock);
-	fdtv_unregister_rc(fdtv);
-fail_free:
-	kfree(fdtv);
-
-	return err;
-}
-
-static int node_remove(struct device *dev)
-{
-	struct firedtv *fdtv = dev_get_drvdata(dev);
-
-	fdtv_dvb_unregister(fdtv);
-
-	spin_lock_irq(&node_list_lock);
-	list_del(&fdtv->list);
-	spin_unlock_irq(&node_list_lock);
-
-	fdtv_unregister_rc(fdtv);
-
-	kfree(fdtv);
-	return 0;
-}
-
-static void node_update(struct fw_unit *unit)
-{
-	struct firedtv *fdtv = dev_get_drvdata(&unit->device);
-
-	if (fdtv->isochannel >= 0)
-		cmp_establish_pp_connection(fdtv, fdtv->subunit,
-					    fdtv->isochannel);
-}
-
-#define MATCH_FLAGS (IEEE1394_MATCH_VENDOR_ID | IEEE1394_MATCH_MODEL_ID | \
-		     IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION)
-
-#define DIGITAL_EVERYWHERE_OUI	0x001287
-#define AVC_UNIT_SPEC_ID_ENTRY	0x00a02d
-#define AVC_SW_VERSION_ENTRY	0x010001
-
-static const struct ieee1394_device_id fdtv_id_table[] = {
-	{
-		/* FloppyDTV S/CI and FloppyDTV S2 */
-		.match_flags	= MATCH_FLAGS,
-		.vendor_id	= DIGITAL_EVERYWHERE_OUI,
-		.model_id	= 0x000024,
-		.specifier_id	= AVC_UNIT_SPEC_ID_ENTRY,
-		.version	= AVC_SW_VERSION_ENTRY,
-	}, {
-		/* FloppyDTV T/CI */
-		.match_flags	= MATCH_FLAGS,
-		.vendor_id	= DIGITAL_EVERYWHERE_OUI,
-		.model_id	= 0x000025,
-		.specifier_id	= AVC_UNIT_SPEC_ID_ENTRY,
-		.version	= AVC_SW_VERSION_ENTRY,
-	}, {
-		/* FloppyDTV C/CI */
-		.match_flags	= MATCH_FLAGS,
-		.vendor_id	= DIGITAL_EVERYWHERE_OUI,
-		.model_id	= 0x000026,
-		.specifier_id	= AVC_UNIT_SPEC_ID_ENTRY,
-		.version	= AVC_SW_VERSION_ENTRY,
-	}, {
-		/* FireDTV S/CI and FloppyDTV S2 */
-		.match_flags	= MATCH_FLAGS,
-		.vendor_id	= DIGITAL_EVERYWHERE_OUI,
-		.model_id	= 0x000034,
-		.specifier_id	= AVC_UNIT_SPEC_ID_ENTRY,
-		.version	= AVC_SW_VERSION_ENTRY,
-	}, {
-		/* FireDTV T/CI */
-		.match_flags	= MATCH_FLAGS,
-		.vendor_id	= DIGITAL_EVERYWHERE_OUI,
-		.model_id	= 0x000035,
-		.specifier_id	= AVC_UNIT_SPEC_ID_ENTRY,
-		.version	= AVC_SW_VERSION_ENTRY,
-	}, {
-		/* FireDTV C/CI */
-		.match_flags	= MATCH_FLAGS,
-		.vendor_id	= DIGITAL_EVERYWHERE_OUI,
-		.model_id	= 0x000036,
-		.specifier_id	= AVC_UNIT_SPEC_ID_ENTRY,
-		.version	= AVC_SW_VERSION_ENTRY,
-	}, {}
-};
-MODULE_DEVICE_TABLE(ieee1394, fdtv_id_table);
-
-static struct fw_driver fdtv_driver = {
-	.driver   = {
-		.owner  = THIS_MODULE,
-		.name   = "firedtv",
-		.bus    = &fw_bus_type,
-		.probe  = node_probe,
-		.remove = node_remove,
-	},
-	.update   = node_update,
-	.id_table = fdtv_id_table,
-};
-
-static int __init fdtv_init(void)
-{
-	int ret;
-
-	ret = fw_core_add_address_handler(&fcp_handler, &fcp_region);
-	if (ret < 0)
-		return ret;
-
-	ret = driver_register(&fdtv_driver.driver);
-	if (ret < 0)
-		fw_core_remove_address_handler(&fcp_handler);
-
-	return ret;
-}
-
-static void __exit fdtv_exit(void)
-{
-	driver_unregister(&fdtv_driver.driver);
-	fw_core_remove_address_handler(&fcp_handler);
-}
-
-module_init(fdtv_init);
-module_exit(fdtv_exit);
-
-MODULE_AUTHOR("Andreas Monitzer <andy@monitzer.com>");
-MODULE_AUTHOR("Ben Backx <ben@bbackx.com>");
-MODULE_DESCRIPTION("FireDTV DVB Driver");
-MODULE_LICENSE("GPL");
-MODULE_SUPPORTED_DEVICE("FireDTV DVB");
diff --git a/drivers/media/dvb/firewire/firedtv-rc.c b/drivers/media/dvb/firewire/firedtv-rc.c
deleted file mode 100644
index f82d4a9..0000000
--- a/drivers/media/dvb/firewire/firedtv-rc.c
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * FireDTV driver (formerly known as FireSAT)
- *
- * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.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/bitops.h>
-#include <linux/input.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/types.h>
-#include <linux/workqueue.h>
-
-#include "firedtv.h"
-
-/* fixed table with older keycodes, geared towards MythTV */
-static const u16 oldtable[] = {
-
-	/* code from device: 0x4501...0x451f */
-
-	KEY_ESC,
-	KEY_F9,
-	KEY_1,
-	KEY_2,
-	KEY_3,
-	KEY_4,
-	KEY_5,
-	KEY_6,
-	KEY_7,
-	KEY_8,
-	KEY_9,
-	KEY_I,
-	KEY_0,
-	KEY_ENTER,
-	KEY_RED,
-	KEY_UP,
-	KEY_GREEN,
-	KEY_F10,
-	KEY_SPACE,
-	KEY_F11,
-	KEY_YELLOW,
-	KEY_DOWN,
-	KEY_BLUE,
-	KEY_Z,
-	KEY_P,
-	KEY_PAGEDOWN,
-	KEY_LEFT,
-	KEY_W,
-	KEY_RIGHT,
-	KEY_P,
-	KEY_M,
-
-	/* code from device: 0x4540...0x4542 */
-
-	KEY_R,
-	KEY_V,
-	KEY_C,
-};
-
-/* user-modifiable table for a remote as sold in 2008 */
-static const u16 keytable[] = {
-
-	/* code from device: 0x0300...0x031f */
-
-	[0x00] = KEY_POWER,
-	[0x01] = KEY_SLEEP,
-	[0x02] = KEY_STOP,
-	[0x03] = KEY_OK,
-	[0x04] = KEY_RIGHT,
-	[0x05] = KEY_1,
-	[0x06] = KEY_2,
-	[0x07] = KEY_3,
-	[0x08] = KEY_LEFT,
-	[0x09] = KEY_4,
-	[0x0a] = KEY_5,
-	[0x0b] = KEY_6,
-	[0x0c] = KEY_UP,
-	[0x0d] = KEY_7,
-	[0x0e] = KEY_8,
-	[0x0f] = KEY_9,
-	[0x10] = KEY_DOWN,
-	[0x11] = KEY_TITLE,	/* "OSD" - fixme */
-	[0x12] = KEY_0,
-	[0x13] = KEY_F20,	/* "16:9" - fixme */
-	[0x14] = KEY_SCREEN,	/* "FULL" - fixme */
-	[0x15] = KEY_MUTE,
-	[0x16] = KEY_SUBTITLE,
-	[0x17] = KEY_RECORD,
-	[0x18] = KEY_TEXT,
-	[0x19] = KEY_AUDIO,
-	[0x1a] = KEY_RED,
-	[0x1b] = KEY_PREVIOUS,
-	[0x1c] = KEY_REWIND,
-	[0x1d] = KEY_PLAYPAUSE,
-	[0x1e] = KEY_NEXT,
-	[0x1f] = KEY_VOLUMEUP,
-
-	/* code from device: 0x0340...0x0354 */
-
-	[0x20] = KEY_CHANNELUP,
-	[0x21] = KEY_F21,	/* "4:3" - fixme */
-	[0x22] = KEY_TV,
-	[0x23] = KEY_DVD,
-	[0x24] = KEY_VCR,
-	[0x25] = KEY_AUX,
-	[0x26] = KEY_GREEN,
-	[0x27] = KEY_YELLOW,
-	[0x28] = KEY_BLUE,
-	[0x29] = KEY_CHANNEL,	/* "CH.LIST" */
-	[0x2a] = KEY_VENDOR,	/* "CI" - fixme */
-	[0x2b] = KEY_VOLUMEDOWN,
-	[0x2c] = KEY_CHANNELDOWN,
-	[0x2d] = KEY_LAST,
-	[0x2e] = KEY_INFO,
-	[0x2f] = KEY_FORWARD,
-	[0x30] = KEY_LIST,
-	[0x31] = KEY_FAVORITES,
-	[0x32] = KEY_MENU,
-	[0x33] = KEY_EPG,
-	[0x34] = KEY_EXIT,
-};
-
-int fdtv_register_rc(struct firedtv *fdtv, struct device *dev)
-{
-	struct input_dev *idev;
-	int i, err;
-
-	idev = input_allocate_device();
-	if (!idev)
-		return -ENOMEM;
-
-	fdtv->remote_ctrl_dev = idev;
-	idev->name = "FireDTV remote control";
-	idev->dev.parent = dev;
-	idev->evbit[0] = BIT_MASK(EV_KEY);
-	idev->keycode = kmemdup(keytable, sizeof(keytable), GFP_KERNEL);
-	if (!idev->keycode) {
-		err = -ENOMEM;
-		goto fail;
-	}
-	idev->keycodesize = sizeof(keytable[0]);
-	idev->keycodemax = ARRAY_SIZE(keytable);
-
-	for (i = 0; i < ARRAY_SIZE(keytable); i++)
-		set_bit(keytable[i], idev->keybit);
-
-	err = input_register_device(idev);
-	if (err)
-		goto fail_free_keymap;
-
-	return 0;
-
-fail_free_keymap:
-	kfree(idev->keycode);
-fail:
-	input_free_device(idev);
-	return err;
-}
-
-void fdtv_unregister_rc(struct firedtv *fdtv)
-{
-	cancel_work_sync(&fdtv->remote_ctrl_work);
-	kfree(fdtv->remote_ctrl_dev->keycode);
-	input_unregister_device(fdtv->remote_ctrl_dev);
-}
-
-void fdtv_handle_rc(struct firedtv *fdtv, unsigned int code)
-{
-	struct input_dev *idev = fdtv->remote_ctrl_dev;
-	u16 *keycode = idev->keycode;
-
-	if (code >= 0x0300 && code <= 0x031f)
-		code = keycode[code - 0x0300];
-	else if (code >= 0x0340 && code <= 0x0354)
-		code = keycode[code - 0x0320];
-	else if (code >= 0x4501 && code <= 0x451f)
-		code = oldtable[code - 0x4501];
-	else if (code >= 0x4540 && code <= 0x4542)
-		code = oldtable[code - 0x4521];
-	else {
-		printk(KERN_DEBUG "firedtv: invalid key code 0x%04x "
-		       "from remote control\n", code);
-		return;
-	}
-
-	input_report_key(idev, code, 1);
-	input_sync(idev);
-	input_report_key(idev, code, 0);
-	input_sync(idev);
-}
diff --git a/drivers/media/dvb/firewire/firedtv.h b/drivers/media/dvb/firewire/firedtv.h
deleted file mode 100644
index 4fdcd8c..0000000
--- a/drivers/media/dvb/firewire/firedtv.h
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * FireDTV driver (formerly known as FireSAT)
- *
- * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com>
- * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se>
- *
- *	This program is free software; you can redistribute it and/or
- *	modify it under the terms of the 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 _FIREDTV_H
-#define _FIREDTV_H
-
-#include <linux/dvb/dmx.h>
-#include <linux/dvb/frontend.h>
-#include <linux/list.h>
-#include <linux/mod_devicetable.h>
-#include <linux/mutex.h>
-#include <linux/spinlock_types.h>
-#include <linux/types.h>
-#include <linux/wait.h>
-#include <linux/workqueue.h>
-
-#include <demux.h>
-#include <dmxdev.h>
-#include <dvb_demux.h>
-#include <dvb_frontend.h>
-#include <dvb_net.h>
-#include <dvbdev.h>
-
-struct firedtv_tuner_status {
-	unsigned active_system:8;
-	unsigned searching:1;
-	unsigned moving:1;
-	unsigned no_rf:1;
-	unsigned input:1;
-	unsigned selected_antenna:7;
-	unsigned ber:32;
-	unsigned signal_strength:8;
-	unsigned raster_frequency:2;
-	unsigned rf_frequency:22;
-	unsigned man_dep_info_length:8;
-	unsigned front_end_error:1;
-	unsigned antenna_error:1;
-	unsigned front_end_power_status:1;
-	unsigned power_supply:1;
-	unsigned carrier_noise_ratio:16;
-	unsigned power_supply_voltage:8;
-	unsigned antenna_voltage:8;
-	unsigned firewire_bus_voltage:8;
-	unsigned ca_mmi:1;
-	unsigned ca_pmt_reply:1;
-	unsigned ca_date_time_request:1;
-	unsigned ca_application_info:1;
-	unsigned ca_module_present_status:1;
-	unsigned ca_dvb_flag:1;
-	unsigned ca_error_flag:1;
-	unsigned ca_initialization_status:1;
-};
-
-enum model_type {
-	FIREDTV_UNKNOWN = 0,
-	FIREDTV_DVB_S   = 1,
-	FIREDTV_DVB_C   = 2,
-	FIREDTV_DVB_T   = 3,
-	FIREDTV_DVB_S2  = 4,
-};
-
-struct device;
-struct input_dev;
-struct fdtv_ir_context;
-
-struct firedtv {
-	struct device *device;
-	struct list_head list;
-
-	struct dvb_adapter	adapter;
-	struct dmxdev		dmxdev;
-	struct dvb_demux	demux;
-	struct dmx_frontend	frontend;
-	struct dvb_net		dvbnet;
-	struct dvb_frontend	fe;
-
-	struct dvb_device	*cadev;
-	int			ca_last_command;
-	int			ca_time_interval;
-
-	struct mutex		avc_mutex;
-	wait_queue_head_t	avc_wait;
-	bool			avc_reply_received;
-	struct work_struct	remote_ctrl_work;
-	struct input_dev	*remote_ctrl_dev;
-
-	enum model_type		type;
-	char			subunit;
-	char			isochannel;
-	struct fdtv_ir_context	*ir_context;
-
-	fe_sec_voltage_t	voltage;
-	fe_sec_tone_mode_t	tone;
-
-	struct mutex		demux_mutex;
-	unsigned long		channel_active;
-	u16			channel_pid[16];
-
-	int			avc_data_length;
-	u8			avc_data[512];
-};
-
-/* firedtv-avc.c */
-int avc_recv(struct firedtv *fdtv, void *data, size_t length);
-int avc_tuner_status(struct firedtv *fdtv, struct firedtv_tuner_status *stat);
-struct dtv_frontend_properties;
-int avc_tuner_dsd(struct firedtv *fdtv, struct dtv_frontend_properties *params);
-int avc_tuner_set_pids(struct firedtv *fdtv, unsigned char pidc, u16 pid[]);
-int avc_tuner_get_ts(struct firedtv *fdtv);
-int avc_identify_subunit(struct firedtv *fdtv);
-struct dvb_diseqc_master_cmd;
-int avc_lnb_control(struct firedtv *fdtv, char voltage, char burst,
-		    char conttone, char nrdiseq,
-		    struct dvb_diseqc_master_cmd *diseqcmd);
-void avc_remote_ctrl_work(struct work_struct *work);
-int avc_register_remote_control(struct firedtv *fdtv);
-int avc_ca_app_info(struct firedtv *fdtv, char *app_info, unsigned int *len);
-int avc_ca_info(struct firedtv *fdtv, char *app_info, unsigned int *len);
-int avc_ca_reset(struct firedtv *fdtv);
-int avc_ca_pmt(struct firedtv *fdtv, char *app_info, int length);
-int avc_ca_get_time_date(struct firedtv *fdtv, int *interval);
-int avc_ca_enter_menu(struct firedtv *fdtv);
-int avc_ca_get_mmi(struct firedtv *fdtv, char *mmi_object, unsigned int *len);
-int cmp_establish_pp_connection(struct firedtv *fdtv, int plug, int channel);
-void cmp_break_pp_connection(struct firedtv *fdtv, int plug, int channel);
-
-/* firedtv-ci.c */
-int fdtv_ca_register(struct firedtv *fdtv);
-void fdtv_ca_release(struct firedtv *fdtv);
-
-/* firedtv-dvb.c */
-int fdtv_start_feed(struct dvb_demux_feed *dvbdmxfeed);
-int fdtv_stop_feed(struct dvb_demux_feed *dvbdmxfeed);
-int fdtv_dvb_register(struct firedtv *fdtv, const char *name);
-void fdtv_dvb_unregister(struct firedtv *fdtv);
-
-/* firedtv-fe.c */
-void fdtv_frontend_init(struct firedtv *fdtv, const char *name);
-
-/* firedtv-fw.c */
-int fdtv_lock(struct firedtv *fdtv, u64 addr, void *data);
-int fdtv_read(struct firedtv *fdtv, u64 addr, void *data);
-int fdtv_write(struct firedtv *fdtv, u64 addr, void *data, size_t len);
-int fdtv_start_iso(struct firedtv *fdtv);
-void fdtv_stop_iso(struct firedtv *fdtv);
-
-/* firedtv-rc.c */
-#ifdef CONFIG_DVB_FIREDTV_INPUT
-int fdtv_register_rc(struct firedtv *fdtv, struct device *dev);
-void fdtv_unregister_rc(struct firedtv *fdtv);
-void fdtv_handle_rc(struct firedtv *fdtv, unsigned int code);
-#else
-static inline int fdtv_register_rc(struct firedtv *fdtv,
-				   struct device *dev) { return 0; }
-static inline void fdtv_unregister_rc(struct firedtv *fdtv) {}
-static inline void fdtv_handle_rc(struct firedtv *fdtv, unsigned int code) {}
-#endif
-
-#endif /* _FIREDTV_H */
diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig
deleted file mode 100644
index a08c215..0000000
--- a/drivers/media/dvb/frontends/Kconfig
+++ /dev/null
@@ -1,756 +0,0 @@
-config DVB_FE_CUSTOMISE
-	bool "Customise the frontend modules to build"
-	depends on DVB_CORE
-	depends on EXPERT
-	default y if EXPERT
-	help
-	  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.
-
-menu "Customise DVB Frontends"
-	visible if DVB_FE_CUSTOMISE
-
-comment "Multistandard (satellite) frontends"
-	depends on DVB_CORE
-
-config DVB_STB0899
-	tristate "STB0899 based"
-	depends on DVB_CORE && I2C
-	default m if DVB_FE_CUSTOMISE
-	help
-	  A DVB-S/S2/DSS Multistandard demodulator. Say Y when you want
-	  to support this demodulator based frontends
-
-config DVB_STB6100
-	tristate "STB6100 based tuners"
-	depends on DVB_CORE && I2C
-	default m if DVB_FE_CUSTOMISE
-	help
-	  A Silicon tuner from ST used in conjunction with the STB0899
-	  demodulator. Say Y when you want to support this tuner.
-
-config DVB_STV090x
-	tristate "STV0900/STV0903(A/B) based"
-	depends on DVB_CORE && I2C
-	default m if DVB_FE_CUSTOMISE
-	help
-	  DVB-S/S2/DSS Multistandard Professional/Broadcast demodulators.
-	  Say Y when you want to support these frontends.
-
-config DVB_STV6110x
-	tristate "STV6110/(A) based tuners"
-	depends on DVB_CORE && I2C
-	default m if DVB_FE_CUSTOMISE
-	help
-	  A Silicon tuner that supports DVB-S and DVB-S2 modes
-
-comment "Multistandard (cable + terrestrial) frontends"
-	depends on DVB_CORE
-
-config DVB_DRXK
-	tristate "Micronas DRXK based"
-	depends on DVB_CORE && I2C
-	default m if DVB_FE_CUSTOMISE
-	help
-	  Micronas DRX-K DVB-C/T demodulator.
-
-	  Say Y when you want to support this frontend.
-
-config DVB_TDA18271C2DD
-	tristate "NXP TDA18271C2 silicon tuner"
-	depends on DVB_CORE && I2C
-	default m if DVB_FE_CUSTOMISE
-	help
-	  NXP TDA18271 silicon tuner.
-
-	  Say Y when you want to support this tuner.
-
-comment "DVB-S (satellite) frontends"
-	depends on DVB_CORE
-
-config DVB_CX24110
-	tristate "Conexant CX24110 based"
-	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_CX24123
-	tristate "Conexant CX24123 based"
-	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_MT312
-	tristate "Zarlink VP310/MT312/ZL10313 based"
-	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_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_ZL10039
-	tristate "Zarlink ZL10039 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
-	default m if DVB_FE_CUSTOMISE
-	help
-	  A DVB-S tuner module. Say Y when you want to support this frontend.
-
-config DVB_STV0288
-	tristate "ST STV0288 based"
-	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_STB6000
-	tristate "ST STB6000 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_STV0299
-	tristate "ST STV0299 based"
-	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_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
-	default m if DVB_FE_CUSTOMISE
-	help
-	  A DVB-S tuner module. Say Y when you want to support this frontend.
-
-config DVB_TDA10086
-	tristate "Philips TDA10086 based"
-	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_TDA8261
-	tristate "Philips TDA8261 based"
-	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_VES1X93
-	tristate "VLSI VES1893 or VES1993 based"
-	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_TUNER_ITD1000
-	tristate "Integrant ITD1000 Zero IF tuner for DVB-S/DSS"
-	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_TUNER_CX24113
-	tristate "Conexant CX24113/CX24128 tuner for DVB-S/DSS"
-	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_TDA826X
-	tristate "Philips TDA826X 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_TUA6100
-	tristate "Infineon TUA6100 PLL"
-	depends on DVB_CORE && I2C
-	default m if DVB_FE_CUSTOMISE
-	help
-	  A DVB-S PLL chip.
-
-config DVB_CX24116
-	tristate "Conexant CX24116 based"
-	depends on DVB_CORE && I2C
-	default m if DVB_FE_CUSTOMISE
-	help
-	  A DVB-S/S2 tuner module. Say Y when you want to support this frontend.
-
-config DVB_SI21XX
-	tristate "Silicon Labs SI21XX based"
-	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_DS3000
-	tristate "Montage Tehnology DS3000 based"
-	depends on DVB_CORE && I2C
-	default m if DVB_FE_CUSTOMISE
-	help
-	  A DVB-S/S2 tuner module. Say Y when you want to support this frontend.
-
-config DVB_MB86A16
-	tristate "Fujitsu MB86A16 based"
-	depends on DVB_CORE && I2C
-	default m if DVB_FE_CUSTOMISE
-	help
-	  A DVB-S/DSS Direct Conversion reveiver.
-	  Say Y when you want to support this frontend.
-
-config DVB_TDA10071
-	tristate "NXP TDA10071"
-	depends on DVB_CORE && I2C
-	default m if DVB_FE_CUSTOMISE
-	help
-	  Say Y when you want to support this frontend.
-
-comment "DVB-T (terrestrial) frontends"
-	depends on DVB_CORE
-
-config DVB_SP8870
-	tristate "Spase sp8870 based"
-	depends on DVB_CORE && I2C
-	default m if DVB_FE_CUSTOMISE
-	help
-	  A DVB-T tuner module. Say Y when you want to support this frontend.
-
-	  This driver needs external firmware. Please use the command
-	  "<kerneldir>/Documentation/dvb/get_dvb_firmware sp8870" to
-	  download/extract it, and then copy it to /usr/lib/hotplug/firmware
-	  or /lib/firmware (depending on configuration of firmware hotplug).
-
-config DVB_SP887X
-	tristate "Spase sp887x based"
-	depends on DVB_CORE && I2C
-	default m if DVB_FE_CUSTOMISE
-	help
-	  A DVB-T tuner module. Say Y when you want to support this frontend.
-
-	  This driver needs external firmware. Please use the command
-	  "<kerneldir>/Documentation/dvb/get_dvb_firmware sp887x" to
-	  download/extract it, and then copy it to /usr/lib/hotplug/firmware
-	  or /lib/firmware (depending on configuration of firmware hotplug).
-
-config DVB_CX22700
-	tristate "Conexant CX22700 based"
-	depends on DVB_CORE && I2C
-	default m if DVB_FE_CUSTOMISE
-	help
-	  A DVB-T tuner module. Say Y when you want to support this frontend.
-
-config DVB_CX22702
-	tristate "Conexant cx22702 demodulator (OFDM)"
-	depends on DVB_CORE && I2C
-	default m if DVB_FE_CUSTOMISE
-	help
-	  A DVB-T tuner module. Say Y when you want to support this frontend.
-
-config DVB_S5H1432
-	tristate "Samsung s5h1432 demodulator (OFDM)"
-	depends on DVB_CORE && I2C
-	default m if DVB_FE_CUSTOMISE
-	help
-	  A DVB-T tuner module. Say Y when you want to support this frontend.
-
-config DVB_DRXD
-	tristate "Micronas DRXD driver"
-	depends on DVB_CORE && I2C
-	default m if DVB_FE_CUSTOMISE
-	help
-	  A DVB-T tuner module. Say Y when you want to support this frontend.
-
-	  Note: this driver was based on vendor driver reference code (released
-	  under the GPL) as opposed to the existing drx397xd driver, which
-	  was written via reverse engineering.
-
-config DVB_L64781
-	tristate "LSI L64781"
-	depends on DVB_CORE && I2C
-	default m if DVB_FE_CUSTOMISE
-	help
-	  A DVB-T tuner module. Say Y when you want to support this frontend.
-
-config DVB_TDA1004X
-	tristate "Philips TDA10045H/TDA10046H based"
-	depends on DVB_CORE && I2C
-	default m if DVB_FE_CUSTOMISE
-	help
-	  A DVB-T tuner module. Say Y when you want to support this frontend.
-
-	  This driver needs external firmware. Please use the commands
-	  "<kerneldir>/Documentation/dvb/get_dvb_firmware tda10045",
-	  "<kerneldir>/Documentation/dvb/get_dvb_firmware tda10046" to
-	  download/extract them, and then copy them to /usr/lib/hotplug/firmware
-	  or /lib/firmware (depending on configuration of firmware hotplug).
-
-config DVB_NXT6000
-	tristate "NxtWave Communications NXT6000 based"
-	depends on DVB_CORE && I2C
-	default m if DVB_FE_CUSTOMISE
-	help
-	  A DVB-T tuner module. Say Y when you want to support this frontend.
-
-config DVB_MT352
-	tristate "Zarlink MT352 based"
-	depends on DVB_CORE && I2C
-	default m if DVB_FE_CUSTOMISE
-	help
-	  A DVB-T tuner module. Say Y when you want to support this frontend.
-
-config DVB_ZL10353
-	tristate "Zarlink ZL10353 based"
-	depends on DVB_CORE && I2C
-	default m if DVB_FE_CUSTOMISE
-	help
-	  A DVB-T tuner module. Say Y when you want to support this frontend.
-
-config DVB_DIB3000MB
-	tristate "DiBcom 3000M-B"
-	depends on DVB_CORE && I2C
-	default m if DVB_FE_CUSTOMISE
-	help
-	  A DVB-T tuner module. Designed for mobile usage. Say Y when you want
-	  to support this frontend.
-
-config DVB_DIB3000MC
-	tristate "DiBcom 3000P/M-C"
-	depends on DVB_CORE && I2C
-	default m if DVB_FE_CUSTOMISE
-	help
-	  A DVB-T tuner module. Designed for mobile usage. Say Y when you want
-	  to support this frontend.
-
-config DVB_DIB7000M
-	tristate "DiBcom 7000MA/MB/PA/PB/MC"
-	depends on DVB_CORE && I2C
-	default m if DVB_FE_CUSTOMISE
-	help
-	  A DVB-T tuner module. Designed for mobile usage. Say Y when you want
-	  to support this frontend.
-
-config DVB_DIB7000P
-	tristate "DiBcom 7000PC"
-	depends on DVB_CORE && I2C
-	default m if DVB_FE_CUSTOMISE
-	help
-	  A DVB-T tuner module. Designed for mobile usage. Say Y when you want
-	  to support this frontend.
-
-config DVB_DIB9000
-	tristate "DiBcom 9000"
-	depends on DVB_CORE && I2C
-	default m if DVB_FE_CUSTOMISE
-	help
-	  A DVB-T tuner module. Designed for mobile usage. Say Y when you want
-	  to support this frontend.
-
-config DVB_TDA10048
-	tristate "Philips TDA10048HN based"
-	depends on DVB_CORE && I2C
-	default m if DVB_FE_CUSTOMISE
-	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.
-
-config DVB_EC100
-	tristate "E3C EC100"
-	depends on DVB_CORE && I2C
-	default m if DVB_FE_CUSTOMISE
-	help
-	  Say Y when you want to support this frontend.
-
-config DVB_HD29L2
-	tristate "HDIC HD29L2"
-	depends on DVB_CORE && I2C
-	default m if DVB_FE_CUSTOMISE
-	help
-	  Say Y when you want to support this frontend.
-
-config DVB_STV0367
-	tristate "ST STV0367 based"
-	depends on DVB_CORE && I2C
-	default m if DVB_FE_CUSTOMISE
-	help
-	  A DVB-T/C tuner module. Say Y when you want to support this frontend.
-
-config DVB_CXD2820R
-	tristate "Sony CXD2820R"
-	depends on DVB_CORE && I2C
-	default m if DVB_FE_CUSTOMISE
-	help
-	  Say Y when you want to support this frontend.
-
-config DVB_RTL2830
-	tristate "Realtek RTL2830 DVB-T"
-	depends on DVB_CORE && I2C
-	default m if DVB_FE_CUSTOMISE
-	help
-	  Say Y when you want to support this frontend.
-
-config DVB_RTL2832
-	tristate "Realtek RTL2832 DVB-T"
-	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
-
-config DVB_VES1820
-	tristate "VLSI VES1820 based"
-	depends on DVB_CORE && I2C
-	default m if DVB_FE_CUSTOMISE
-	help
-	  A DVB-C tuner module. Say Y when you want to support this frontend.
-
-config DVB_TDA10021
-	tristate "Philips TDA10021 based"
-	depends on DVB_CORE && I2C
-	default m if DVB_FE_CUSTOMISE
-	help
-	  A DVB-C tuner module. Say Y when you want to support this frontend.
-
-config DVB_TDA10023
-	tristate "Philips TDA10023 based"
-	depends on DVB_CORE && I2C
-	default m if DVB_FE_CUSTOMISE
-	help
-	  A DVB-C tuner module. Say Y when you want to support this frontend.
-
-config DVB_STV0297
-	tristate "ST STV0297 based"
-	depends on DVB_CORE && I2C
-	default m if DVB_FE_CUSTOMISE
-	help
-	  A DVB-C tuner module. Say Y when you want to support this frontend.
-
-comment "ATSC (North American/Korean Terrestrial/Cable DTV) frontends"
-	depends on DVB_CORE
-
-config DVB_NXT200X
-	tristate "NxtWave Communications NXT2002/NXT2004 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.
-
-	  This driver needs external firmware. Please use the commands
-	  "<kerneldir>/Documentation/dvb/get_dvb_firmware nxt2002" and
-	  "<kerneldir>/Documentation/dvb/get_dvb_firmware nxt2004" to
-	  download/extract them, and then copy them to /usr/lib/hotplug/firmware
-	  or /lib/firmware (depending on configuration of firmware hotplug).
-
-config DVB_OR51211
-	tristate "Oren OR51211 based"
-	depends on DVB_CORE && I2C
-	default m if DVB_FE_CUSTOMISE
-	help
-	  An ATSC 8VSB tuner module. Say Y when you want to support this frontend.
-
-	  This driver needs external firmware. Please use the command
-	  "<kerneldir>/Documentation/dvb/get_dvb_firmware or51211" to
-	  download it, and then copy it to /usr/lib/hotplug/firmware
-	  or /lib/firmware (depending on configuration of firmware hotplug).
-
-config DVB_OR51132
-	tristate "Oren OR51132 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.
-
-	  This driver needs external firmware. Please use the commands
-	  "<kerneldir>/Documentation/dvb/get_dvb_firmware or51132_vsb" and/or
-	  "<kerneldir>/Documentation/dvb/get_dvb_firmware or51132_qam" to
-	  download firmwares for 8VSB and QAM64/256, respectively. Copy them to
-	  /usr/lib/hotplug/firmware or /lib/firmware (depending on
-	  configuration of firmware hotplug).
-
-config DVB_BCM3510
-	tristate "Broadcom BCM3510"
-	depends on DVB_CORE && I2C
-	default m if DVB_FE_CUSTOMISE
-	help
-	  An ATSC 8VSB/16VSB and QAM64/256 tuner module. Say Y when you want to
-	  support this frontend.
-
-config DVB_LGDT330X
-	tristate "LG Electronics LGDT3302/LGDT3303 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_LGDT3305
-	tristate "LG Electronics LGDT3304 and 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_LG2160
-	tristate "LG Electronics LG216x based"
-	depends on DVB_CORE && I2C
-	default m if DVB_FE_CUSTOMISE
-	help
-	  An ATSC/MH demodulator module. Say Y when you want
-	  to support this frontend.
-
-config DVB_S5H1409
-	tristate "Samsung S5H1409 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_AU8522
-	depends on I2C
-	tristate
-
-config DVB_AU8522_DTV
-	tristate "Auvitek AU8522 based DTV demod"
-	depends on DVB_CORE && I2C
-	select DVB_AU8522
-	default m if DVB_FE_CUSTOMISE
-	help
-	  An ATSC 8VSB, QAM64/256 & NTSC demodulator module. Say Y when
-	  you want to enable DTV demodulation support for this frontend.
-
-config DVB_AU8522_V4L
-	tristate "Auvitek AU8522 based ATV demod"
-	depends on VIDEO_V4L2 && I2C
-	select DVB_AU8522
-	default m if DVB_FE_CUSTOMISE
-	help
-	  An ATSC 8VSB, QAM64/256 & NTSC demodulator module. Say Y when
-	  you want to enable ATV demodulation support for this frontend.
-
-config DVB_S5H1411
-	tristate "Samsung S5H1411 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.
-
-comment "ISDB-T (terrestrial) frontends"
-	depends on DVB_CORE
-
-config DVB_S921
-	tristate "Sharp S921 frontend"
-	depends on DVB_CORE && I2C
-	default m if DVB_FE_CUSTOMISE
-	help
-	  AN ISDB-T DQPSK, QPSK, 16QAM and 64QAM 1seg tuner module.
-	  Say Y when you want to support this frontend.
-
-config DVB_DIB8000
-	tristate "DiBcom 8000MB/MC"
-	depends on DVB_CORE && I2C
-	default m if DVB_FE_CUSTOMISE
-	help
-	  A driver for DiBcom's DiB8000 ISDB-T/ISDB-Tsb demodulator.
-	  Say Y when you want to support this frontend.
-
-config DVB_MB86A20S
-	tristate "Fujitsu mb86a20s"
-	depends on DVB_CORE && I2C
-	default m if DVB_FE_CUSTOMISE
-	help
-	  A driver for Fujitsu mb86a20s ISDB-T/ISDB-Tsb demodulator.
-	  Say Y when you want to support this frontend.
-
-comment "Digital terrestrial only tuners/PLL"
-	depends on DVB_CORE
-
-config DVB_PLL
-	tristate "Generic I2C PLL based tuners"
-	depends on DVB_CORE && I2C
-	default m if DVB_FE_CUSTOMISE
-	help
-	  This module drives a number of tuners based on PLL chips with a
-	  common I2C interface. Say Y when you want to support these tuners.
-
-config DVB_TUNER_DIB0070
-	tristate "DiBcom DiB0070 silicon base-band tuner"
-	depends on I2C
-	default m if DVB_FE_CUSTOMISE
-	help
-	  A driver for the silicon baseband tuner DiB0070 from DiBcom.
-	  This device is only used inside a SiP called together with a
-	  demodulator for now.
-
-config DVB_TUNER_DIB0090
-	tristate "DiBcom DiB0090 silicon base-band tuner"
-	depends on I2C
-	default m if DVB_FE_CUSTOMISE
-	help
-	  A driver for the silicon baseband tuner DiB0090 from DiBcom.
-	  This device is only used inside a SiP called together with a
-	  demodulator for now.
-
-comment "SEC control devices for DVB-S"
-	depends on DVB_CORE
-
-config DVB_LNBP21
-	tristate "LNBP21/LNBH24 SEC controllers"
-	depends on DVB_CORE && I2C
-	default m if DVB_FE_CUSTOMISE
-	help
-	  An SEC control chips.
-
-config DVB_LNBP22
-	tristate "LNBP22 SEC controllers"
-	depends on DVB_CORE && I2C
-	default m if DVB_FE_CUSTOMISE
-	help
-	  LNB power supply and control voltage
-	  regulator chip with step-up converter
-	  and I2C interface.
-	  Say Y when you want to support this chip.
-
-config DVB_ISL6405
-	tristate "ISL6405 SEC controller"
-	depends on DVB_CORE && I2C
-	default m if DVB_FE_CUSTOMISE
-	help
-	  An SEC control chip.
-
-config DVB_ISL6421
-	tristate "ISL6421 SEC controller"
-	depends on DVB_CORE && I2C
-	default m if DVB_FE_CUSTOMISE
-	help
-	  An SEC control chip.
-
-config DVB_ISL6423
-	tristate "ISL6423 SEC controller"
-	depends on DVB_CORE && I2C
-	default m if DVB_FE_CUSTOMISE
-	help
-	  A SEC controller chip from Intersil
-
-config DVB_A8293
-	tristate "Allegro A8293"
-	depends on DVB_CORE && I2C
-	default m if DVB_FE_CUSTOMISE
-
-config DVB_LGS8GL5
-	tristate "Silicon Legend LGS-8GL5 demodulator (OFDM)"
-	depends on DVB_CORE && I2C
-	default m if DVB_FE_CUSTOMISE
-	help
-	  A DMB-TH tuner module. Say Y when you want to support this frontend.
-
-config DVB_LGS8GXX
-	tristate "Legend Silicon LGS8913/LGS8GL5/LGS8GXX DMB-TH demodulator"
-	depends on DVB_CORE && I2C
-	select FW_LOADER
-	default m if DVB_FE_CUSTOMISE
-	help
-	  A DMB-TH tuner module. Say Y when you want to support this frontend.
-
-config DVB_ATBM8830
-	tristate "AltoBeam ATBM8830/8831 DMB-TH demodulator"
-	depends on DVB_CORE && I2C
-	default m if DVB_FE_CUSTOMISE
-	help
-	  A DMB-TH tuner module. Say Y when you want to support this frontend.
-
-config DVB_TDA665x
-	tristate "TDA665x tuner"
-	depends on DVB_CORE && I2C
-	default m if DVB_FE_CUSTOMISE
-	help
-	  Support for tuner modules based on Philips TDA6650/TDA6651 chips.
-	  Say Y when you want to support this chip.
-
-	  Currently supported tuners:
-	  * Panasonic ENV57H12D5 (ET-50DT)
-
-config DVB_IX2505V
-	tristate "Sharp IX2505V 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_IT913X_FE
-	tristate "it913x frontend and it9137 tuner"
-	depends on DVB_CORE && I2C
-	default m if DVB_FE_CUSTOMISE
-	help
-	  A DVB-T tuner module.
-	  Say Y when you want to support this frontend.
-
-config DVB_M88RS2000
-	tristate "M88RS2000 DVB-S demodulator and 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_AF9033
-	tristate "Afatech AF9033 DVB-T demodulator"
-	depends on DVB_CORE && I2C
-	default m if DVB_FE_CUSTOMISE
-
-comment "Tools to develop new frontends"
-
-config DVB_DUMMY_FE
-	tristate "Dummy frontend driver"
-	default n
-endmenu
diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile
deleted file mode 100644
index 185bb8b..0000000
--- a/drivers/media/dvb/frontends/Makefile
+++ /dev/null
@@ -1,105 +0,0 @@
-#
-# Makefile for the kernel DVB frontend device drivers.
-#
-
-ccflags-y += -I$(srctree)/drivers/media/dvb/dvb-core/
-ccflags-y += -I$(srctree)/drivers/media/common/tuners/
-
-stb0899-objs = stb0899_drv.o stb0899_algo.o
-stv0900-objs = stv0900_core.o stv0900_sw.o
-drxd-objs = drxd_firm.o drxd_hard.o
-cxd2820r-objs = cxd2820r_core.o cxd2820r_c.o cxd2820r_t.o cxd2820r_t2.o
-drxk-objs := drxk_hard.o
-
-obj-$(CONFIG_DVB_PLL) += dvb-pll.o
-obj-$(CONFIG_DVB_STV0299) += stv0299.o
-obj-$(CONFIG_DVB_STB0899) += stb0899.o
-obj-$(CONFIG_DVB_STB6100) += stb6100.o
-obj-$(CONFIG_DVB_SP8870) += sp8870.o
-obj-$(CONFIG_DVB_CX22700) += cx22700.o
-obj-$(CONFIG_DVB_S5H1432) += s5h1432.o
-obj-$(CONFIG_DVB_CX24110) += cx24110.o
-obj-$(CONFIG_DVB_TDA8083) += tda8083.o
-obj-$(CONFIG_DVB_L64781) += l64781.o
-obj-$(CONFIG_DVB_DIB3000MB) += dib3000mb.o
-obj-$(CONFIG_DVB_DIB3000MC) += dib3000mc.o dibx000_common.o
-obj-$(CONFIG_DVB_DIB7000M) += dib7000m.o dibx000_common.o
-obj-$(CONFIG_DVB_DIB7000P) += dib7000p.o dibx000_common.o
-obj-$(CONFIG_DVB_DIB8000) += dib8000.o dibx000_common.o
-obj-$(CONFIG_DVB_DIB9000) += dib9000.o dibx000_common.o
-obj-$(CONFIG_DVB_MT312) += mt312.o
-obj-$(CONFIG_DVB_VES1820) += ves1820.o
-obj-$(CONFIG_DVB_VES1X93) += ves1x93.o
-obj-$(CONFIG_DVB_TDA1004X) += tda1004x.o
-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_ZL10039) += zl10039.o
-obj-$(CONFIG_DVB_ZL10353) += zl10353.o
-obj-$(CONFIG_DVB_CX22702) += cx22702.o
-obj-$(CONFIG_DVB_DRXD) += drxd.o
-obj-$(CONFIG_DVB_TDA10021) += tda10021.o
-obj-$(CONFIG_DVB_TDA10023) += tda10023.o
-obj-$(CONFIG_DVB_STV0297) += stv0297.o
-obj-$(CONFIG_DVB_NXT200X) += nxt200x.o
-obj-$(CONFIG_DVB_OR51211) += or51211.o
-obj-$(CONFIG_DVB_OR51132) += or51132.o
-obj-$(CONFIG_DVB_BCM3510) += bcm3510.o
-obj-$(CONFIG_DVB_S5H1420) += s5h1420.o
-obj-$(CONFIG_DVB_LGDT330X) += lgdt330x.o
-obj-$(CONFIG_DVB_LGDT3305) += lgdt3305.o
-obj-$(CONFIG_DVB_LG2160) += lg2160.o
-obj-$(CONFIG_DVB_CX24123) += cx24123.o
-obj-$(CONFIG_DVB_LNBP21) += lnbp21.o
-obj-$(CONFIG_DVB_LNBP22) += lnbp22.o
-obj-$(CONFIG_DVB_ISL6405) += isl6405.o
-obj-$(CONFIG_DVB_ISL6421) += isl6421.o
-obj-$(CONFIG_DVB_TDA10086) += tda10086.o
-obj-$(CONFIG_DVB_TDA826X) += tda826x.o
-obj-$(CONFIG_DVB_TDA8261) += tda8261.o
-obj-$(CONFIG_DVB_TUNER_DIB0070) += dib0070.o
-obj-$(CONFIG_DVB_TUNER_DIB0090) += dib0090.o
-obj-$(CONFIG_DVB_TUA6100) += tua6100.o
-obj-$(CONFIG_DVB_S5H1409) += s5h1409.o
-obj-$(CONFIG_DVB_TUNER_ITD1000) += itd1000.o
-obj-$(CONFIG_DVB_AU8522) += au8522_common.o
-obj-$(CONFIG_DVB_AU8522_DTV) += au8522_dig.o
-obj-$(CONFIG_DVB_AU8522_V4L) += au8522_decoder.o
-obj-$(CONFIG_DVB_TDA10048) += tda10048.o
-obj-$(CONFIG_DVB_TUNER_CX24113) += cx24113.o
-obj-$(CONFIG_DVB_S5H1411) += s5h1411.o
-obj-$(CONFIG_DVB_LGS8GL5) += lgs8gl5.o
-obj-$(CONFIG_DVB_TDA665x) += tda665x.o
-obj-$(CONFIG_DVB_LGS8GXX) += lgs8gxx.o
-obj-$(CONFIG_DVB_ATBM8830) += atbm8830.o
-obj-$(CONFIG_DVB_DUMMY_FE) += dvb_dummy_fe.o
-obj-$(CONFIG_DVB_AF9013) += af9013.o
-obj-$(CONFIG_DVB_CX24116) += cx24116.o
-obj-$(CONFIG_DVB_SI21XX) += si21xx.o
-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
-obj-$(CONFIG_DVB_STV090x) += stv090x.o
-obj-$(CONFIG_DVB_STV6110x) += stv6110x.o
-obj-$(CONFIG_DVB_ISL6423) += isl6423.o
-obj-$(CONFIG_DVB_EC100) += ec100.o
-obj-$(CONFIG_DVB_HD29L2) += hd29l2.o
-obj-$(CONFIG_DVB_DS3000) += ds3000.o
-obj-$(CONFIG_DVB_MB86A16) += mb86a16.o
-obj-$(CONFIG_DVB_MB86A20S) += mb86a20s.o
-obj-$(CONFIG_DVB_IX2505V) += ix2505v.o
-obj-$(CONFIG_DVB_STV0367) += stv0367.o
-obj-$(CONFIG_DVB_CXD2820R) += cxd2820r.o
-obj-$(CONFIG_DVB_DRXK) += drxk.o
-obj-$(CONFIG_DVB_TDA18271C2DD) += tda18271c2dd.o
-obj-$(CONFIG_DVB_IT913X_FE) += it913x-fe.o
-obj-$(CONFIG_DVB_A8293) += a8293.o
-obj-$(CONFIG_DVB_TDA10071) += tda10071.o
-obj-$(CONFIG_DVB_RTL2830) += rtl2830.o
-obj-$(CONFIG_DVB_RTL2832) += rtl2832.o
-obj-$(CONFIG_DVB_M88RS2000) += m88rs2000.o
-obj-$(CONFIG_DVB_AF9033) += af9033.o
-
diff --git a/drivers/media/dvb/frontends/a8293.c b/drivers/media/dvb/frontends/a8293.c
deleted file mode 100644
index cff44a3..0000000
--- a/drivers/media/dvb/frontends/a8293.c
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Allegro A8293 SEC driver
- *
- * Copyright (C) 2011 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.,
- *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include "dvb_frontend.h"
-#include "a8293.h"
-
-struct a8293_priv {
-	struct i2c_adapter *i2c;
-	const struct a8293_config *cfg;
-	u8 reg[2];
-};
-
-static int a8293_i2c(struct a8293_priv *priv, u8 *val, int len, bool rd)
-{
-	int ret;
-	struct i2c_msg msg[1] = {
-		{
-			.addr = priv->cfg->i2c_addr,
-			.len = len,
-			.buf = val,
-		}
-	};
-
-	if (rd)
-		msg[0].flags = I2C_M_RD;
-	else
-		msg[0].flags = 0;
-
-	ret = i2c_transfer(priv->i2c, msg, 1);
-	if (ret == 1) {
-		ret = 0;
-	} else {
-		dev_warn(&priv->i2c->dev, "%s: i2c failed=%d rd=%d\n",
-				KBUILD_MODNAME, ret, rd);
-		ret = -EREMOTEIO;
-	}
-
-	return ret;
-}
-
-static int a8293_wr(struct a8293_priv *priv, u8 *val, int len)
-{
-	return a8293_i2c(priv, val, len, 0);
-}
-
-static int a8293_rd(struct a8293_priv *priv, u8 *val, int len)
-{
-	return a8293_i2c(priv, val, len, 1);
-}
-
-static int a8293_set_voltage(struct dvb_frontend *fe,
-	fe_sec_voltage_t fe_sec_voltage)
-{
-	struct a8293_priv *priv = fe->sec_priv;
-	int ret;
-
-	dev_dbg(&priv->i2c->dev, "%s: fe_sec_voltage=%d\n", __func__,
-			fe_sec_voltage);
-
-	switch (fe_sec_voltage) {
-	case SEC_VOLTAGE_OFF:
-		/* ENB=0 */
-		priv->reg[0] = 0x10;
-		break;
-	case SEC_VOLTAGE_13:
-		/* VSEL0=1, VSEL1=0, VSEL2=0, VSEL3=0, ENB=1*/
-		priv->reg[0] = 0x31;
-		break;
-	case SEC_VOLTAGE_18:
-		/* VSEL0=0, VSEL1=0, VSEL2=0, VSEL3=1, ENB=1*/
-		priv->reg[0] = 0x38;
-		break;
-	default:
-		ret = -EINVAL;
-		goto err;
-	};
-
-	ret = a8293_wr(priv, &priv->reg[0], 1);
-	if (ret)
-		goto err;
-
-	return ret;
-err:
-	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
-	return ret;
-}
-
-static void a8293_release_sec(struct dvb_frontend *fe)
-{
-	a8293_set_voltage(fe, SEC_VOLTAGE_OFF);
-
-	kfree(fe->sec_priv);
-	fe->sec_priv = NULL;
-}
-
-struct dvb_frontend *a8293_attach(struct dvb_frontend *fe,
-	struct i2c_adapter *i2c, const struct a8293_config *cfg)
-{
-	int ret;
-	struct a8293_priv *priv = NULL;
-	u8 buf[2];
-
-	/* allocate memory for the internal priv */
-	priv = kzalloc(sizeof(struct a8293_priv), GFP_KERNEL);
-	if (priv == NULL) {
-		ret = -ENOMEM;
-		goto err;
-	}
-
-	/* setup the priv */
-	priv->i2c = i2c;
-	priv->cfg = cfg;
-	fe->sec_priv = priv;
-
-	/* check if the SEC is there */
-	ret = a8293_rd(priv, buf, 2);
-	if (ret)
-		goto err;
-
-	/* ENB=0 */
-	priv->reg[0] = 0x10;
-	ret = a8293_wr(priv, &priv->reg[0], 1);
-	if (ret)
-		goto err;
-
-	/* TMODE=0, TGATE=1 */
-	priv->reg[1] = 0x82;
-	ret = a8293_wr(priv, &priv->reg[1], 1);
-	if (ret)
-		goto err;
-
-	fe->ops.release_sec = a8293_release_sec;
-
-	/* override frontend ops */
-	fe->ops.set_voltage = a8293_set_voltage;
-
-	dev_info(&priv->i2c->dev, "%s: Allegro A8293 SEC attached\n",
-			KBUILD_MODNAME);
-
-	return fe;
-err:
-	dev_dbg(&i2c->dev, "%s: failed=%d\n", __func__, ret);
-	kfree(priv);
-	return NULL;
-}
-EXPORT_SYMBOL(a8293_attach);
-
-MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
-MODULE_DESCRIPTION("Allegro A8293 SEC driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/a8293.h b/drivers/media/dvb/frontends/a8293.h
deleted file mode 100644
index ed29e55..0000000
--- a/drivers/media/dvb/frontends/a8293.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Allegro A8293 SEC driver
- *
- * Copyright (C) 2011 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.,
- *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef A8293_H
-#define A8293_H
-
-struct a8293_config {
-	u8 i2c_addr;
-};
-
-#if defined(CONFIG_DVB_A8293) || \
-	(defined(CONFIG_DVB_A8293_MODULE) && defined(MODULE))
-extern struct dvb_frontend *a8293_attach(struct dvb_frontend *fe,
-	struct i2c_adapter *i2c, const struct a8293_config *cfg);
-#else
-static inline struct dvb_frontend *a8293_attach(struct dvb_frontend *fe,
-	struct i2c_adapter *i2c, const struct a8293_config *cfg)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif
-
-#endif /* A8293_H */
diff --git a/drivers/media/dvb/frontends/af9013.c b/drivers/media/dvb/frontends/af9013.c
deleted file mode 100644
index 5bc570d..0000000
--- a/drivers/media/dvb/frontends/af9013.c
+++ /dev/null
@@ -1,1524 +0,0 @@
-/*
- * Afatech AF9013 demodulator driver
- *
- * Copyright (C) 2007 Antti Palosaari <crope@iki.fi>
- * Copyright (C) 2011 Antti Palosaari <crope@iki.fi>
- *
- * Thanks to Afatech who kindly provided information.
- *
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You 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 "af9013_priv.h"
-
-int af9013_debug;
-module_param_named(debug, af9013_debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
-
-struct af9013_state {
-	struct i2c_adapter *i2c;
-	struct dvb_frontend fe;
-	struct af9013_config config;
-
-	/* tuner/demod RF and IF AGC limits used for signal strength calc */
-	u8 signal_strength_en, rf_50, rf_80, if_50, if_80;
-	u16 signal_strength;
-	u32 ber;
-	u32 ucblocks;
-	u16 snr;
-	u32 bandwidth_hz;
-	fe_status_t fe_status;
-	unsigned long set_frontend_jiffies;
-	unsigned long read_status_jiffies;
-	bool first_tune;
-	bool i2c_gate_state;
-	unsigned int statistics_step:3;
-	struct delayed_work statistics_work;
-};
-
-/* write multiple registers */
-static int af9013_wr_regs_i2c(struct af9013_state *priv, u8 mbox, u16 reg,
-	const u8 *val, int len)
-{
-	int ret;
-	u8 buf[3+len];
-	struct i2c_msg msg[1] = {
-		{
-			.addr = priv->config.i2c_addr,
-			.flags = 0,
-			.len = sizeof(buf),
-			.buf = buf,
-		}
-	};
-
-	buf[0] = (reg >> 8) & 0xff;
-	buf[1] = (reg >> 0) & 0xff;
-	buf[2] = mbox;
-	memcpy(&buf[3], val, len);
-
-	ret = i2c_transfer(priv->i2c, msg, 1);
-	if (ret == 1) {
-		ret = 0;
-	} else {
-		warn("i2c wr failed=%d reg=%04x len=%d", ret, reg, len);
-		ret = -EREMOTEIO;
-	}
-	return ret;
-}
-
-/* read multiple registers */
-static int af9013_rd_regs_i2c(struct af9013_state *priv, u8 mbox, u16 reg,
-	u8 *val, int len)
-{
-	int ret;
-	u8 buf[3];
-	struct i2c_msg msg[2] = {
-		{
-			.addr = priv->config.i2c_addr,
-			.flags = 0,
-			.len = 3,
-			.buf = buf,
-		}, {
-			.addr = priv->config.i2c_addr,
-			.flags = I2C_M_RD,
-			.len = len,
-			.buf = val,
-		}
-	};
-
-	buf[0] = (reg >> 8) & 0xff;
-	buf[1] = (reg >> 0) & 0xff;
-	buf[2] = mbox;
-
-	ret = i2c_transfer(priv->i2c, msg, 2);
-	if (ret == 2) {
-		ret = 0;
-	} else {
-		warn("i2c rd failed=%d reg=%04x len=%d", ret, reg, len);
-		ret = -EREMOTEIO;
-	}
-	return ret;
-}
-
-/* write multiple registers */
-static int af9013_wr_regs(struct af9013_state *priv, u16 reg, const u8 *val,
-	int len)
-{
-	int ret, i;
-	u8 mbox = (0 << 7)|(0 << 6)|(1 << 1)|(1 << 0);
-
-	if ((priv->config.ts_mode == AF9013_TS_USB) &&
-		((reg & 0xff00) != 0xff00) && ((reg & 0xff00) != 0xae00)) {
-		mbox |= ((len - 1) << 2);
-		ret = af9013_wr_regs_i2c(priv, mbox, reg, val, len);
-	} else {
-		for (i = 0; i < len; i++) {
-			ret = af9013_wr_regs_i2c(priv, mbox, reg+i, val+i, 1);
-			if (ret)
-				goto err;
-		}
-	}
-
-err:
-	return 0;
-}
-
-/* read multiple registers */
-static int af9013_rd_regs(struct af9013_state *priv, u16 reg, u8 *val, int len)
-{
-	int ret, i;
-	u8 mbox = (0 << 7)|(0 << 6)|(1 << 1)|(0 << 0);
-
-	if ((priv->config.ts_mode == AF9013_TS_USB) &&
-		((reg & 0xff00) != 0xff00) && ((reg & 0xff00) != 0xae00)) {
-		mbox |= ((len - 1) << 2);
-		ret = af9013_rd_regs_i2c(priv, mbox, reg, val, len);
-	} else {
-		for (i = 0; i < len; i++) {
-			ret = af9013_rd_regs_i2c(priv, mbox, reg+i, val+i, 1);
-			if (ret)
-				goto err;
-		}
-	}
-
-err:
-	return 0;
-}
-
-/* write single register */
-static int af9013_wr_reg(struct af9013_state *priv, u16 reg, u8 val)
-{
-	return af9013_wr_regs(priv, reg, &val, 1);
-}
-
-/* read single register */
-static int af9013_rd_reg(struct af9013_state *priv, u16 reg, u8 *val)
-{
-	return af9013_rd_regs(priv, reg, val, 1);
-}
-
-static int af9013_write_ofsm_regs(struct af9013_state *state, u16 reg, u8 *val,
-	u8 len)
-{
-	u8 mbox = (1 << 7)|(1 << 6)|((len - 1) << 2)|(1 << 1)|(1 << 0);
-	return af9013_wr_regs_i2c(state, mbox, reg, val, len);
-}
-
-static int af9013_wr_reg_bits(struct af9013_state *state, u16 reg, int pos,
-	int len, u8 val)
-{
-	int ret;
-	u8 tmp, mask;
-
-	/* no need for read if whole reg is written */
-	if (len != 8) {
-		ret = af9013_rd_reg(state, reg, &tmp);
-		if (ret)
-			return ret;
-
-		mask = (0xff >> (8 - len)) << pos;
-		val <<= pos;
-		tmp &= ~mask;
-		val |= tmp;
-	}
-
-	return af9013_wr_reg(state, reg, val);
-}
-
-static int af9013_rd_reg_bits(struct af9013_state *state, u16 reg, int pos,
-	int len, u8 *val)
-{
-	int ret;
-	u8 tmp;
-
-	ret = af9013_rd_reg(state, reg, &tmp);
-	if (ret)
-		return ret;
-
-	*val = (tmp >> pos);
-	*val &= (0xff >> (8 - len));
-
-	return 0;
-}
-
-static int af9013_set_gpio(struct af9013_state *state, u8 gpio, u8 gpioval)
-{
-	int ret;
-	u8 pos;
-	u16 addr;
-
-	dbg("%s: gpio=%d gpioval=%02x", __func__, gpio, gpioval);
-
-	/*
-	 * GPIO0 & GPIO1 0xd735
-	 * GPIO2 & GPIO3 0xd736
-	 */
-
-	switch (gpio) {
-	case 0:
-	case 1:
-		addr = 0xd735;
-		break;
-	case 2:
-	case 3:
-		addr = 0xd736;
-		break;
-
-	default:
-		err("invalid gpio:%d\n", gpio);
-		ret = -EINVAL;
-		goto err;
-	};
-
-	switch (gpio) {
-	case 0:
-	case 2:
-		pos = 0;
-		break;
-	case 1:
-	case 3:
-	default:
-		pos = 4;
-		break;
-	};
-
-	ret = af9013_wr_reg_bits(state, addr, pos, 4, gpioval);
-	if (ret)
-		goto err;
-
-	return ret;
-err:
-	dbg("%s: failed=%d", __func__, ret);
-	return ret;
-}
-
-static u32 af913_div(u32 a, u32 b, u32 x)
-{
-	u32 r = 0, c = 0, i;
-
-	dbg("%s: a=%d b=%d x=%d", __func__, a, b, x);
-
-	if (a > b) {
-		c = a / b;
-		a = a - c * b;
-	}
-
-	for (i = 0; i < x; i++) {
-		if (a >= b) {
-			r += 1;
-			a -= b;
-		}
-		a <<= 1;
-		r <<= 1;
-	}
-	r = (c << (u32)x) + r;
-
-	dbg("%s: a=%d b=%d x=%d r=%x", __func__, a, b, x, r);
-	return r;
-}
-
-static int af9013_power_ctrl(struct af9013_state *state, u8 onoff)
-{
-	int ret, i;
-	u8 tmp;
-
-	dbg("%s: onoff=%d", __func__, onoff);
-
-	/* enable reset */
-	ret = af9013_wr_reg_bits(state, 0xd417, 4, 1, 1);
-	if (ret)
-		goto err;
-
-	/* start reset mechanism */
-	ret = af9013_wr_reg(state, 0xaeff, 1);
-	if (ret)
-		goto err;
-
-	/* wait reset performs */
-	for (i = 0; i < 150; i++) {
-		ret = af9013_rd_reg_bits(state, 0xd417, 1, 1, &tmp);
-		if (ret)
-			goto err;
-
-		if (tmp)
-			break; /* reset done */
-
-		usleep_range(5000, 25000);
-	}
-
-	if (!tmp)
-		return -ETIMEDOUT;
-
-	if (onoff) {
-		/* clear reset */
-		ret = af9013_wr_reg_bits(state, 0xd417, 1, 1, 0);
-		if (ret)
-			goto err;
-
-		/* disable reset */
-		ret = af9013_wr_reg_bits(state, 0xd417, 4, 1, 0);
-
-		/* power on */
-		ret = af9013_wr_reg_bits(state, 0xd73a, 3, 1, 0);
-	} else {
-		/* power off */
-		ret = af9013_wr_reg_bits(state, 0xd73a, 3, 1, 1);
-	}
-
-	return ret;
-err:
-	dbg("%s: failed=%d", __func__, ret);
-	return ret;
-}
-
-static int af9013_statistics_ber_unc_start(struct dvb_frontend *fe)
-{
-	struct af9013_state *state = fe->demodulator_priv;
-	int ret;
-
-	dbg("%s", __func__);
-
-	/* reset and start BER counter */
-	ret = af9013_wr_reg_bits(state, 0xd391, 4, 1, 1);
-	if (ret)
-		goto err;
-
-	return ret;
-err:
-	dbg("%s: failed=%d", __func__, ret);
-	return ret;
-}
-
-static int af9013_statistics_ber_unc_result(struct dvb_frontend *fe)
-{
-	struct af9013_state *state = fe->demodulator_priv;
-	int ret;
-	u8 buf[5];
-
-	dbg("%s", __func__);
-
-	/* check if error bit count is ready */
-	ret = af9013_rd_reg_bits(state, 0xd391, 4, 1, &buf[0]);
-	if (ret)
-		goto err;
-
-	if (!buf[0]) {
-		dbg("%s: not ready", __func__);
-		return 0;
-	}
-
-	ret = af9013_rd_regs(state, 0xd387, buf, 5);
-	if (ret)
-		goto err;
-
-	state->ber = (buf[2] << 16) | (buf[1] << 8) | buf[0];
-	state->ucblocks += (buf[4] << 8) | buf[3];
-
-	return ret;
-err:
-	dbg("%s: failed=%d", __func__, ret);
-	return ret;
-}
-
-static int af9013_statistics_snr_start(struct dvb_frontend *fe)
-{
-	struct af9013_state *state = fe->demodulator_priv;
-	int ret;
-
-	dbg("%s", __func__);
-
-	/* start SNR meas */
-	ret = af9013_wr_reg_bits(state, 0xd2e1, 3, 1, 1);
-	if (ret)
-		goto err;
-
-	return ret;
-err:
-	dbg("%s: failed=%d", __func__, ret);
-	return ret;
-}
-
-static int af9013_statistics_snr_result(struct dvb_frontend *fe)
-{
-	struct af9013_state *state = fe->demodulator_priv;
-	int ret, i, len;
-	u8 buf[3], tmp;
-	u32 snr_val;
-	const struct af9013_snr *uninitialized_var(snr_lut);
-
-	dbg("%s", __func__);
-
-	/* check if SNR ready */
-	ret = af9013_rd_reg_bits(state, 0xd2e1, 3, 1, &tmp);
-	if (ret)
-		goto err;
-
-	if (!tmp) {
-		dbg("%s: not ready", __func__);
-		return 0;
-	}
-
-	/* read value */
-	ret = af9013_rd_regs(state, 0xd2e3, buf, 3);
-	if (ret)
-		goto err;
-
-	snr_val = (buf[2] << 16) | (buf[1] << 8) | buf[0];
-
-	/* read current modulation */
-	ret = af9013_rd_reg(state, 0xd3c1, &tmp);
-	if (ret)
-		goto err;
-
-	switch ((tmp >> 6) & 3) {
-	case 0:
-		len = ARRAY_SIZE(qpsk_snr_lut);
-		snr_lut = qpsk_snr_lut;
-		break;
-	case 1:
-		len = ARRAY_SIZE(qam16_snr_lut);
-		snr_lut = qam16_snr_lut;
-		break;
-	case 2:
-		len = ARRAY_SIZE(qam64_snr_lut);
-		snr_lut = qam64_snr_lut;
-		break;
-	default:
-		goto err;
-		break;
-	}
-
-	for (i = 0; i < len; i++) {
-		tmp = snr_lut[i].snr;
-
-		if (snr_val < snr_lut[i].val)
-			break;
-	}
-	state->snr = tmp * 10; /* dB/10 */
-
-	return ret;
-err:
-	dbg("%s: failed=%d", __func__, ret);
-	return ret;
-}
-
-static int af9013_statistics_signal_strength(struct dvb_frontend *fe)
-{
-	struct af9013_state *state = fe->demodulator_priv;
-	int ret = 0;
-	u8 buf[2], rf_gain, if_gain;
-	int signal_strength;
-
-	dbg("%s", __func__);
-
-	if (!state->signal_strength_en)
-		return 0;
-
-	ret = af9013_rd_regs(state, 0xd07c, buf, 2);
-	if (ret)
-		goto err;
-
-	rf_gain = buf[0];
-	if_gain = buf[1];
-
-	signal_strength = (0xffff / \
-		(9 * (state->rf_50 + state->if_50) - \
-		11 * (state->rf_80 + state->if_80))) * \
-		(10 * (rf_gain + if_gain) - \
-		11 * (state->rf_80 + state->if_80));
-	if (signal_strength < 0)
-		signal_strength = 0;
-	else if (signal_strength > 0xffff)
-		signal_strength = 0xffff;
-
-	state->signal_strength = signal_strength;
-
-	return ret;
-err:
-	dbg("%s: failed=%d", __func__, ret);
-	return ret;
-}
-
-static void af9013_statistics_work(struct work_struct *work)
-{
-	struct af9013_state *state = container_of(work,
-		struct af9013_state, statistics_work.work);
-	unsigned int next_msec;
-
-	/* update only signal strength when demod is not locked */
-	if (!(state->fe_status & FE_HAS_LOCK)) {
-		state->statistics_step = 0;
-		state->ber = 0;
-		state->snr = 0;
-	}
-
-	switch (state->statistics_step) {
-	default:
-		state->statistics_step = 0;
-	case 0:
-		af9013_statistics_signal_strength(&state->fe);
-		state->statistics_step++;
-		next_msec = 300;
-		break;
-	case 1:
-		af9013_statistics_snr_start(&state->fe);
-		state->statistics_step++;
-		next_msec = 200;
-		break;
-	case 2:
-		af9013_statistics_ber_unc_start(&state->fe);
-		state->statistics_step++;
-		next_msec = 1000;
-		break;
-	case 3:
-		af9013_statistics_snr_result(&state->fe);
-		state->statistics_step++;
-		next_msec = 400;
-		break;
-	case 4:
-		af9013_statistics_ber_unc_result(&state->fe);
-		state->statistics_step++;
-		next_msec = 100;
-		break;
-	}
-
-	schedule_delayed_work(&state->statistics_work,
-		msecs_to_jiffies(next_msec));
-}
-
-static int af9013_get_tune_settings(struct dvb_frontend *fe,
-	struct dvb_frontend_tune_settings *fesettings)
-{
-	fesettings->min_delay_ms = 800;
-	fesettings->step_size = 0;
-	fesettings->max_drift = 0;
-
-	return 0;
-}
-
-static int af9013_set_frontend(struct dvb_frontend *fe)
-{
-	struct af9013_state *state = fe->demodulator_priv;
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	int ret, i, sampling_freq;
-	bool auto_mode, spec_inv;
-	u8 buf[6];
-	u32 if_frequency, freq_cw;
-
-	dbg("%s: frequency=%d bandwidth_hz=%d", __func__,
-		c->frequency, c->bandwidth_hz);
-
-	/* program tuner */
-	if (fe->ops.tuner_ops.set_params)
-		fe->ops.tuner_ops.set_params(fe);
-
-	/* program CFOE coefficients */
-	if (c->bandwidth_hz != state->bandwidth_hz) {
-		for (i = 0; i < ARRAY_SIZE(coeff_lut); i++) {
-			if (coeff_lut[i].clock == state->config.clock &&
-				coeff_lut[i].bandwidth_hz == c->bandwidth_hz) {
-				break;
-			}
-		}
-
-		ret = af9013_wr_regs(state, 0xae00, coeff_lut[i].val,
-			sizeof(coeff_lut[i].val));
-	}
-
-	/* program frequency control */
-	if (c->bandwidth_hz != state->bandwidth_hz || state->first_tune) {
-		/* get used IF frequency */
-		if (fe->ops.tuner_ops.get_if_frequency)
-			fe->ops.tuner_ops.get_if_frequency(fe, &if_frequency);
-		else
-			if_frequency = state->config.if_frequency;
-
-		sampling_freq = if_frequency;
-
-		while (sampling_freq > (state->config.clock / 2))
-			sampling_freq -= state->config.clock;
-
-		if (sampling_freq < 0) {
-			sampling_freq *= -1;
-			spec_inv = state->config.spec_inv;
-		} else {
-			spec_inv = !state->config.spec_inv;
-		}
-
-		freq_cw = af913_div(sampling_freq, state->config.clock, 23);
-
-		if (spec_inv)
-			freq_cw = 0x800000 - freq_cw;
-
-		buf[0] = (freq_cw >>  0) & 0xff;
-		buf[1] = (freq_cw >>  8) & 0xff;
-		buf[2] = (freq_cw >> 16) & 0x7f;
-
-		freq_cw = 0x800000 - freq_cw;
-
-		buf[3] = (freq_cw >>  0) & 0xff;
-		buf[4] = (freq_cw >>  8) & 0xff;
-		buf[5] = (freq_cw >> 16) & 0x7f;
-
-		ret = af9013_wr_regs(state, 0xd140, buf, 3);
-		if (ret)
-			goto err;
-
-		ret = af9013_wr_regs(state, 0x9be7, buf, 6);
-		if (ret)
-			goto err;
-	}
-
-	/* clear TPS lock flag */
-	ret = af9013_wr_reg_bits(state, 0xd330, 3, 1, 1);
-	if (ret)
-		goto err;
-
-	/* clear MPEG2 lock flag */
-	ret = af9013_wr_reg_bits(state, 0xd507, 6, 1, 0);
-	if (ret)
-		goto err;
-
-	/* empty channel function */
-	ret = af9013_wr_reg_bits(state, 0x9bfe, 0, 1, 0);
-	if (ret)
-		goto err;
-
-	/* empty DVB-T channel function */
-	ret = af9013_wr_reg_bits(state, 0x9bc2, 0, 1, 0);
-	if (ret)
-		goto err;
-
-	/* transmission parameters */
-	auto_mode = false;
-	memset(buf, 0, 3);
-
-	switch (c->transmission_mode) {
-	case TRANSMISSION_MODE_AUTO:
-		auto_mode = 1;
-		break;
-	case TRANSMISSION_MODE_2K:
-		break;
-	case TRANSMISSION_MODE_8K:
-		buf[0] |= (1 << 0);
-		break;
-	default:
-		dbg("%s: invalid transmission_mode", __func__);
-		auto_mode = 1;
-	}
-
-	switch (c->guard_interval) {
-	case GUARD_INTERVAL_AUTO:
-		auto_mode = 1;
-		break;
-	case GUARD_INTERVAL_1_32:
-		break;
-	case GUARD_INTERVAL_1_16:
-		buf[0] |= (1 << 2);
-		break;
-	case GUARD_INTERVAL_1_8:
-		buf[0] |= (2 << 2);
-		break;
-	case GUARD_INTERVAL_1_4:
-		buf[0] |= (3 << 2);
-		break;
-	default:
-		dbg("%s: invalid guard_interval", __func__);
-		auto_mode = 1;
-	}
-
-	switch (c->hierarchy) {
-	case HIERARCHY_AUTO:
-		auto_mode = 1;
-		break;
-	case HIERARCHY_NONE:
-		break;
-	case HIERARCHY_1:
-		buf[0] |= (1 << 4);
-		break;
-	case HIERARCHY_2:
-		buf[0] |= (2 << 4);
-		break;
-	case HIERARCHY_4:
-		buf[0] |= (3 << 4);
-		break;
-	default:
-		dbg("%s: invalid hierarchy", __func__);
-		auto_mode = 1;
-	};
-
-	switch (c->modulation) {
-	case QAM_AUTO:
-		auto_mode = 1;
-		break;
-	case QPSK:
-		break;
-	case QAM_16:
-		buf[1] |= (1 << 6);
-		break;
-	case QAM_64:
-		buf[1] |= (2 << 6);
-		break;
-	default:
-		dbg("%s: invalid modulation", __func__);
-		auto_mode = 1;
-	}
-
-	/* Use HP. How and which case we can switch to LP? */
-	buf[1] |= (1 << 4);
-
-	switch (c->code_rate_HP) {
-	case FEC_AUTO:
-		auto_mode = 1;
-		break;
-	case FEC_1_2:
-		break;
-	case FEC_2_3:
-		buf[2] |= (1 << 0);
-		break;
-	case FEC_3_4:
-		buf[2] |= (2 << 0);
-		break;
-	case FEC_5_6:
-		buf[2] |= (3 << 0);
-		break;
-	case FEC_7_8:
-		buf[2] |= (4 << 0);
-		break;
-	default:
-		dbg("%s: invalid code_rate_HP", __func__);
-		auto_mode = 1;
-	}
-
-	switch (c->code_rate_LP) {
-	case FEC_AUTO:
-		auto_mode = 1;
-		break;
-	case FEC_1_2:
-		break;
-	case FEC_2_3:
-		buf[2] |= (1 << 3);
-		break;
-	case FEC_3_4:
-		buf[2] |= (2 << 3);
-		break;
-	case FEC_5_6:
-		buf[2] |= (3 << 3);
-		break;
-	case FEC_7_8:
-		buf[2] |= (4 << 3);
-		break;
-	case FEC_NONE:
-		break;
-	default:
-		dbg("%s: invalid code_rate_LP", __func__);
-		auto_mode = 1;
-	}
-
-	switch (c->bandwidth_hz) {
-	case 6000000:
-		break;
-	case 7000000:
-		buf[1] |= (1 << 2);
-		break;
-	case 8000000:
-		buf[1] |= (2 << 2);
-		break;
-	default:
-		dbg("%s: invalid bandwidth_hz", __func__);
-		ret = -EINVAL;
-		goto err;
-	}
-
-	ret = af9013_wr_regs(state, 0xd3c0, buf, 3);
-	if (ret)
-		goto err;
-
-	if (auto_mode) {
-		/* clear easy mode flag */
-		ret = af9013_wr_reg(state, 0xaefd, 0);
-		if (ret)
-			goto err;
-
-		dbg("%s: auto params", __func__);
-	} else {
-		/* set easy mode flag */
-		ret = af9013_wr_reg(state, 0xaefd, 1);
-		if (ret)
-			goto err;
-
-		ret = af9013_wr_reg(state, 0xaefe, 0);
-		if (ret)
-			goto err;
-
-		dbg("%s: manual params", __func__);
-	}
-
-	/* tune */
-	ret = af9013_wr_reg(state, 0xffff, 0);
-	if (ret)
-		goto err;
-
-	state->bandwidth_hz = c->bandwidth_hz;
-	state->set_frontend_jiffies = jiffies;
-	state->first_tune = false;
-
-	return ret;
-err:
-	dbg("%s: failed=%d", __func__, ret);
-	return ret;
-}
-
-static int af9013_get_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	struct af9013_state *state = fe->demodulator_priv;
-	int ret;
-	u8 buf[3];
-
-	dbg("%s", __func__);
-
-	ret = af9013_rd_regs(state, 0xd3c0, buf, 3);
-	if (ret)
-		goto err;
-
-	switch ((buf[1] >> 6) & 3) {
-	case 0:
-		c->modulation = QPSK;
-		break;
-	case 1:
-		c->modulation = QAM_16;
-		break;
-	case 2:
-		c->modulation = QAM_64;
-		break;
-	}
-
-	switch ((buf[0] >> 0) & 3) {
-	case 0:
-		c->transmission_mode = TRANSMISSION_MODE_2K;
-		break;
-	case 1:
-		c->transmission_mode = TRANSMISSION_MODE_8K;
-	}
-
-	switch ((buf[0] >> 2) & 3) {
-	case 0:
-		c->guard_interval = GUARD_INTERVAL_1_32;
-		break;
-	case 1:
-		c->guard_interval = GUARD_INTERVAL_1_16;
-		break;
-	case 2:
-		c->guard_interval = GUARD_INTERVAL_1_8;
-		break;
-	case 3:
-		c->guard_interval = GUARD_INTERVAL_1_4;
-		break;
-	}
-
-	switch ((buf[0] >> 4) & 7) {
-	case 0:
-		c->hierarchy = HIERARCHY_NONE;
-		break;
-	case 1:
-		c->hierarchy = HIERARCHY_1;
-		break;
-	case 2:
-		c->hierarchy = HIERARCHY_2;
-		break;
-	case 3:
-		c->hierarchy = HIERARCHY_4;
-		break;
-	}
-
-	switch ((buf[2] >> 0) & 7) {
-	case 0:
-		c->code_rate_HP = FEC_1_2;
-		break;
-	case 1:
-		c->code_rate_HP = FEC_2_3;
-		break;
-	case 2:
-		c->code_rate_HP = FEC_3_4;
-		break;
-	case 3:
-		c->code_rate_HP = FEC_5_6;
-		break;
-	case 4:
-		c->code_rate_HP = FEC_7_8;
-		break;
-	}
-
-	switch ((buf[2] >> 3) & 7) {
-	case 0:
-		c->code_rate_LP = FEC_1_2;
-		break;
-	case 1:
-		c->code_rate_LP = FEC_2_3;
-		break;
-	case 2:
-		c->code_rate_LP = FEC_3_4;
-		break;
-	case 3:
-		c->code_rate_LP = FEC_5_6;
-		break;
-	case 4:
-		c->code_rate_LP = FEC_7_8;
-		break;
-	}
-
-	switch ((buf[1] >> 2) & 3) {
-	case 0:
-		c->bandwidth_hz = 6000000;
-		break;
-	case 1:
-		c->bandwidth_hz = 7000000;
-		break;
-	case 2:
-		c->bandwidth_hz = 8000000;
-		break;
-	}
-
-	return ret;
-err:
-	dbg("%s: failed=%d", __func__, ret);
-	return ret;
-}
-
-static int af9013_read_status(struct dvb_frontend *fe, fe_status_t *status)
-{
-	struct af9013_state *state = fe->demodulator_priv;
-	int ret;
-	u8 tmp;
-
-	/*
-	 * Return status from the cache if it is younger than 2000ms with the
-	 * exception of last tune is done during 4000ms.
-	 */
-	if (time_is_after_jiffies(
-		state->read_status_jiffies + msecs_to_jiffies(2000)) &&
-		time_is_before_jiffies(
-		state->set_frontend_jiffies + msecs_to_jiffies(4000))
-	) {
-			*status = state->fe_status;
-			return 0;
-	} else {
-		*status = 0;
-	}
-
-	/* MPEG2 lock */
-	ret = af9013_rd_reg_bits(state, 0xd507, 6, 1, &tmp);
-	if (ret)
-		goto err;
-
-	if (tmp)
-		*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI |
-			FE_HAS_SYNC | FE_HAS_LOCK;
-
-	if (!*status) {
-		/* TPS lock */
-		ret = af9013_rd_reg_bits(state, 0xd330, 3, 1, &tmp);
-		if (ret)
-			goto err;
-
-		if (tmp)
-			*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
-				FE_HAS_VITERBI;
-	}
-
-	state->fe_status = *status;
-	state->read_status_jiffies = jiffies;
-
-	return ret;
-err:
-	dbg("%s: failed=%d", __func__, ret);
-	return ret;
-}
-
-static int af9013_read_snr(struct dvb_frontend *fe, u16 *snr)
-{
-	struct af9013_state *state = fe->demodulator_priv;
-	*snr = state->snr;
-	return 0;
-}
-
-static int af9013_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
-{
-	struct af9013_state *state = fe->demodulator_priv;
-	*strength = state->signal_strength;
-	return 0;
-}
-
-static int af9013_read_ber(struct dvb_frontend *fe, u32 *ber)
-{
-	struct af9013_state *state = fe->demodulator_priv;
-	*ber = state->ber;
-	return 0;
-}
-
-static int af9013_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
-{
-	struct af9013_state *state = fe->demodulator_priv;
-	*ucblocks = state->ucblocks;
-	return 0;
-}
-
-static int af9013_init(struct dvb_frontend *fe)
-{
-	struct af9013_state *state = fe->demodulator_priv;
-	int ret, i, len;
-	u8 buf[3], tmp;
-	u32 adc_cw;
-	const struct af9013_reg_bit *init;
-
-	dbg("%s", __func__);
-
-	/* power on */
-	ret = af9013_power_ctrl(state, 1);
-	if (ret)
-		goto err;
-
-	/* enable ADC */
-	ret = af9013_wr_reg(state, 0xd73a, 0xa4);
-	if (ret)
-		goto err;
-
-	/* write API version to firmware */
-	ret = af9013_wr_regs(state, 0x9bf2, state->config.api_version, 4);
-	if (ret)
-		goto err;
-
-	/* program ADC control */
-	switch (state->config.clock) {
-	case 28800000: /* 28.800 MHz */
-		tmp = 0;
-		break;
-	case 20480000: /* 20.480 MHz */
-		tmp = 1;
-		break;
-	case 28000000: /* 28.000 MHz */
-		tmp = 2;
-		break;
-	case 25000000: /* 25.000 MHz */
-		tmp = 3;
-		break;
-	default:
-		err("invalid clock");
-		return -EINVAL;
-	}
-
-	adc_cw = af913_div(state->config.clock, 1000000ul, 19);
-	buf[0] = (adc_cw >>  0) & 0xff;
-	buf[1] = (adc_cw >>  8) & 0xff;
-	buf[2] = (adc_cw >> 16) & 0xff;
-
-	ret = af9013_wr_regs(state, 0xd180, buf, 3);
-	if (ret)
-		goto err;
-
-	ret = af9013_wr_reg_bits(state, 0x9bd2, 0, 4, tmp);
-	if (ret)
-		goto err;
-
-	/* set I2C master clock */
-	ret = af9013_wr_reg(state, 0xd416, 0x14);
-	if (ret)
-		goto err;
-
-	/* set 16 embx */
-	ret = af9013_wr_reg_bits(state, 0xd700, 1, 1, 1);
-	if (ret)
-		goto err;
-
-	/* set no trigger */
-	ret = af9013_wr_reg_bits(state, 0xd700, 2, 1, 0);
-	if (ret)
-		goto err;
-
-	/* set read-update bit for constellation */
-	ret = af9013_wr_reg_bits(state, 0xd371, 1, 1, 1);
-	if (ret)
-		goto err;
-
-	/* settings for mp2if */
-	if (state->config.ts_mode == AF9013_TS_USB) {
-		/* AF9015 split PSB to 1.5k + 0.5k */
-		ret = af9013_wr_reg_bits(state, 0xd50b, 2, 1, 1);
-		if (ret)
-			goto err;
-	} else {
-		/* AF9013 change the output bit to data7 */
-		ret = af9013_wr_reg_bits(state, 0xd500, 3, 1, 1);
-		if (ret)
-			goto err;
-
-		/* AF9013 set mpeg to full speed */
-		ret = af9013_wr_reg_bits(state, 0xd502, 4, 1, 1);
-		if (ret)
-			goto err;
-	}
-
-	ret = af9013_wr_reg_bits(state, 0xd520, 4, 1, 1);
-	if (ret)
-		goto err;
-
-	/* load OFSM settings */
-	dbg("%s: load ofsm settings", __func__);
-	len = ARRAY_SIZE(ofsm_init);
-	init = ofsm_init;
-	for (i = 0; i < len; i++) {
-		ret = af9013_wr_reg_bits(state, init[i].addr, init[i].pos,
-			init[i].len, init[i].val);
-		if (ret)
-			goto err;
-	}
-
-	/* load tuner specific settings */
-	dbg("%s: load tuner specific settings", __func__);
-	switch (state->config.tuner) {
-	case AF9013_TUNER_MXL5003D:
-		len = ARRAY_SIZE(tuner_init_mxl5003d);
-		init = tuner_init_mxl5003d;
-		break;
-	case AF9013_TUNER_MXL5005D:
-	case AF9013_TUNER_MXL5005R:
-	case AF9013_TUNER_MXL5007T:
-		len = ARRAY_SIZE(tuner_init_mxl5005);
-		init = tuner_init_mxl5005;
-		break;
-	case AF9013_TUNER_ENV77H11D5:
-		len = ARRAY_SIZE(tuner_init_env77h11d5);
-		init = tuner_init_env77h11d5;
-		break;
-	case AF9013_TUNER_MT2060:
-		len = ARRAY_SIZE(tuner_init_mt2060);
-		init = tuner_init_mt2060;
-		break;
-	case AF9013_TUNER_MC44S803:
-		len = ARRAY_SIZE(tuner_init_mc44s803);
-		init = tuner_init_mc44s803;
-		break;
-	case AF9013_TUNER_QT1010:
-	case AF9013_TUNER_QT1010A:
-		len = ARRAY_SIZE(tuner_init_qt1010);
-		init = tuner_init_qt1010;
-		break;
-	case AF9013_TUNER_MT2060_2:
-		len = ARRAY_SIZE(tuner_init_mt2060_2);
-		init = tuner_init_mt2060_2;
-		break;
-	case AF9013_TUNER_TDA18271:
-	case AF9013_TUNER_TDA18218:
-		len = ARRAY_SIZE(tuner_init_tda18271);
-		init = tuner_init_tda18271;
-		break;
-	case AF9013_TUNER_UNKNOWN:
-	default:
-		len = ARRAY_SIZE(tuner_init_unknown);
-		init = tuner_init_unknown;
-		break;
-	}
-
-	for (i = 0; i < len; i++) {
-		ret = af9013_wr_reg_bits(state, init[i].addr, init[i].pos,
-			init[i].len, init[i].val);
-		if (ret)
-			goto err;
-	}
-
-	/* TS mode */
-	ret = af9013_wr_reg_bits(state, 0xd500, 1, 2, state->config.ts_mode);
-	if (ret)
-		goto err;
-
-	/* enable lock led */
-	ret = af9013_wr_reg_bits(state, 0xd730, 0, 1, 1);
-	if (ret)
-		goto err;
-
-	/* check if we support signal strength */
-	if (!state->signal_strength_en) {
-		ret = af9013_rd_reg_bits(state, 0x9bee, 0, 1,
-			&state->signal_strength_en);
-		if (ret)
-			goto err;
-	}
-
-	/* read values needed for signal strength calculation */
-	if (state->signal_strength_en && !state->rf_50) {
-		ret = af9013_rd_reg(state, 0x9bbd, &state->rf_50);
-		if (ret)
-			goto err;
-
-		ret = af9013_rd_reg(state, 0x9bd0, &state->rf_80);
-		if (ret)
-			goto err;
-
-		ret = af9013_rd_reg(state, 0x9be2, &state->if_50);
-		if (ret)
-			goto err;
-
-		ret = af9013_rd_reg(state, 0x9be4, &state->if_80);
-		if (ret)
-			goto err;
-	}
-
-	/* SNR */
-	ret = af9013_wr_reg(state, 0xd2e2, 1);
-	if (ret)
-		goto err;
-
-	/* BER / UCB */
-	buf[0] = (10000 >> 0) & 0xff;
-	buf[1] = (10000 >> 8) & 0xff;
-	ret = af9013_wr_regs(state, 0xd385, buf, 2);
-	if (ret)
-		goto err;
-
-	/* enable FEC monitor */
-	ret = af9013_wr_reg_bits(state, 0xd392, 1, 1, 1);
-	if (ret)
-		goto err;
-
-	state->first_tune = true;
-	schedule_delayed_work(&state->statistics_work, msecs_to_jiffies(400));
-
-	return ret;
-err:
-	dbg("%s: failed=%d", __func__, ret);
-	return ret;
-}
-
-static int af9013_sleep(struct dvb_frontend *fe)
-{
-	struct af9013_state *state = fe->demodulator_priv;
-	int ret;
-
-	dbg("%s", __func__);
-
-	/* stop statistics polling */
-	cancel_delayed_work_sync(&state->statistics_work);
-
-	/* disable lock led */
-	ret = af9013_wr_reg_bits(state, 0xd730, 0, 1, 0);
-	if (ret)
-		goto err;
-
-	/* power off */
-	ret = af9013_power_ctrl(state, 0);
-	if (ret)
-		goto err;
-
-	return ret;
-err:
-	dbg("%s: failed=%d", __func__, ret);
-	return ret;
-}
-
-static int af9013_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
-{
-	int ret;
-	struct af9013_state *state = fe->demodulator_priv;
-
-	dbg("%s: enable=%d", __func__, enable);
-
-	/* gate already open or close */
-	if (state->i2c_gate_state == enable)
-		return 0;
-
-	if (state->config.ts_mode == AF9013_TS_USB)
-		ret = af9013_wr_reg_bits(state, 0xd417, 3, 1, enable);
-	else
-		ret = af9013_wr_reg_bits(state, 0xd607, 2, 1, enable);
-	if (ret)
-		goto err;
-
-	state->i2c_gate_state = enable;
-
-	return ret;
-err:
-	dbg("%s: failed=%d", __func__, ret);
-	return ret;
-}
-
-static void af9013_release(struct dvb_frontend *fe)
-{
-	struct af9013_state *state = fe->demodulator_priv;
-	kfree(state);
-}
-
-static struct dvb_frontend_ops af9013_ops;
-
-static int af9013_download_firmware(struct af9013_state *state)
-{
-	int i, len, remaining, ret;
-	const struct firmware *fw;
-	u16 checksum = 0;
-	u8 val;
-	u8 fw_params[4];
-	u8 *fw_file = AF9013_DEFAULT_FIRMWARE;
-
-	msleep(100);
-	/* check whether firmware is already running */
-	ret = af9013_rd_reg(state, 0x98be, &val);
-	if (ret)
-		goto err;
-	else
-		dbg("%s: firmware status=%02x", __func__, val);
-
-	if (val == 0x0c) /* fw is running, no need for download */
-		goto exit;
-
-	info("found a '%s' in cold state, will try to load a firmware",
-		af9013_ops.info.name);
-
-	/* request the firmware, this will block and timeout */
-	ret = request_firmware(&fw, fw_file, state->i2c->dev.parent);
-	if (ret) {
-		err("did not find the firmware file. (%s) "
-			"Please see linux/Documentation/dvb/ for more details" \
-			" on firmware-problems. (%d)",
-			fw_file, ret);
-		goto err;
-	}
-
-	info("downloading firmware from file '%s'", fw_file);
-
-	/* calc checksum */
-	for (i = 0; i < fw->size; i++)
-		checksum += fw->data[i];
-
-	fw_params[0] = checksum >> 8;
-	fw_params[1] = checksum & 0xff;
-	fw_params[2] = fw->size >> 8;
-	fw_params[3] = fw->size & 0xff;
-
-	/* write fw checksum & size */
-	ret = af9013_write_ofsm_regs(state, 0x50fc,
-		fw_params, sizeof(fw_params));
-	if (ret)
-		goto err_release;
-
-	#define FW_ADDR 0x5100 /* firmware start address */
-	#define LEN_MAX 16 /* max packet size */
-	for (remaining = fw->size; remaining > 0; remaining -= LEN_MAX) {
-		len = remaining;
-		if (len > LEN_MAX)
-			len = LEN_MAX;
-
-		ret = af9013_write_ofsm_regs(state,
-			FW_ADDR + fw->size - remaining,
-			(u8 *) &fw->data[fw->size - remaining], len);
-		if (ret) {
-			err("firmware download failed:%d", ret);
-			goto err_release;
-		}
-	}
-
-	/* request boot firmware */
-	ret = af9013_wr_reg(state, 0xe205, 1);
-	if (ret)
-		goto err_release;
-
-	for (i = 0; i < 15; i++) {
-		msleep(100);
-
-		/* check firmware status */
-		ret = af9013_rd_reg(state, 0x98be, &val);
-		if (ret)
-			goto err_release;
-
-		dbg("%s: firmware status=%02x", __func__, val);
-
-		if (val == 0x0c || val == 0x04) /* success or fail */
-			break;
-	}
-
-	if (val == 0x04) {
-		err("firmware did not run");
-		ret = -ENODEV;
-	} else if (val != 0x0c) {
-		err("firmware boot timeout");
-		ret = -ENODEV;
-	}
-
-err_release:
-	release_firmware(fw);
-err:
-exit:
-	if (!ret)
-		info("found a '%s' in warm state.", af9013_ops.info.name);
-	return ret;
-}
-
-struct dvb_frontend *af9013_attach(const struct af9013_config *config,
-	struct i2c_adapter *i2c)
-{
-	int ret;
-	struct af9013_state *state = NULL;
-	u8 buf[4], i;
-
-	/* allocate memory for the internal state */
-	state = kzalloc(sizeof(struct af9013_state), GFP_KERNEL);
-	if (state == NULL)
-		goto err;
-
-	/* setup the state */
-	state->i2c = i2c;
-	memcpy(&state->config, config, sizeof(struct af9013_config));
-
-	/* download firmware */
-	if (state->config.ts_mode != AF9013_TS_USB) {
-		ret = af9013_download_firmware(state);
-		if (ret)
-			goto err;
-	}
-
-	/* firmware version */
-	ret = af9013_rd_regs(state, 0x5103, buf, 4);
-	if (ret)
-		goto err;
-
-	info("firmware version %d.%d.%d.%d", buf[0], buf[1], buf[2], buf[3]);
-
-	/* set GPIOs */
-	for (i = 0; i < sizeof(state->config.gpio); i++) {
-		ret = af9013_set_gpio(state, i, state->config.gpio[i]);
-		if (ret)
-			goto err;
-	}
-
-	/* create dvb_frontend */
-	memcpy(&state->fe.ops, &af9013_ops,
-		sizeof(struct dvb_frontend_ops));
-	state->fe.demodulator_priv = state;
-
-	INIT_DELAYED_WORK(&state->statistics_work, af9013_statistics_work);
-
-	return &state->fe;
-err:
-	kfree(state);
-	return NULL;
-}
-EXPORT_SYMBOL(af9013_attach);
-
-static struct dvb_frontend_ops af9013_ops = {
-	.delsys = { SYS_DVBT },
-	.info = {
-		.name = "Afatech AF9013",
-		.frequency_min = 174000000,
-		.frequency_max = 862000000,
-		.frequency_stepsize = 250000,
-		.frequency_tolerance = 0,
-		.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_FEC_AUTO |
-			FE_CAN_QPSK |
-			FE_CAN_QAM_16 |
-			FE_CAN_QAM_64 |
-			FE_CAN_QAM_AUTO |
-			FE_CAN_TRANSMISSION_MODE_AUTO |
-			FE_CAN_GUARD_INTERVAL_AUTO |
-			FE_CAN_HIERARCHY_AUTO |
-			FE_CAN_RECOVER |
-			FE_CAN_MUTE_TS
-	},
-
-	.release = af9013_release,
-
-	.init = af9013_init,
-	.sleep = af9013_sleep,
-
-	.get_tune_settings = af9013_get_tune_settings,
-	.set_frontend = af9013_set_frontend,
-	.get_frontend = af9013_get_frontend,
-
-	.read_status = af9013_read_status,
-	.read_snr = af9013_read_snr,
-	.read_signal_strength = af9013_read_signal_strength,
-	.read_ber = af9013_read_ber,
-	.read_ucblocks = af9013_read_ucblocks,
-
-	.i2c_gate_ctrl = af9013_i2c_gate_ctrl,
-};
-
-MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
-MODULE_DESCRIPTION("Afatech AF9013 DVB-T demodulator driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/af9013.h b/drivers/media/dvb/frontends/af9013.h
deleted file mode 100644
index b973fc5..0000000
--- a/drivers/media/dvb/frontends/af9013.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Afatech AF9013 demodulator driver
- *
- * Copyright (C) 2007 Antti Palosaari <crope@iki.fi>
- * Copyright (C) 2011 Antti Palosaari <crope@iki.fi>
- *
- * Thanks to Afatech who kindly provided information.
- *
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You 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 AF9013_H
-#define AF9013_H
-
-#include <linux/dvb/frontend.h>
-
-/* AF9013/5 GPIOs (mostly guessed)
-   demod#1-gpio#0 - set demod#2 i2c-addr for dual devices
-   demod#1-gpio#1 - xtal setting (?)
-   demod#1-gpio#3 - tuner#1
-   demod#2-gpio#0 - tuner#2
-   demod#2-gpio#1 - xtal setting (?)
-*/
-
-struct af9013_config {
-	/*
-	 * I2C address
-	 */
-	u8 i2c_addr;
-
-	/*
-	 * clock
-	 * 20480000, 25000000, 28000000, 28800000
-	 */
-	u32 clock;
-
-	/*
-	 * tuner
-	 */
-#define AF9013_TUNER_MXL5003D      3 /* MaxLinear */
-#define AF9013_TUNER_MXL5005D     13 /* MaxLinear */
-#define AF9013_TUNER_MXL5005R     30 /* MaxLinear */
-#define AF9013_TUNER_ENV77H11D5  129 /* Panasonic */
-#define AF9013_TUNER_MT2060      130 /* Microtune */
-#define AF9013_TUNER_MC44S803    133 /* Freescale */
-#define AF9013_TUNER_QT1010      134 /* Quantek */
-#define AF9013_TUNER_UNKNOWN     140 /* for can tuners ? */
-#define AF9013_TUNER_MT2060_2    147 /* Microtune */
-#define AF9013_TUNER_TDA18271    156 /* NXP */
-#define AF9013_TUNER_QT1010A     162 /* Quantek */
-#define AF9013_TUNER_MXL5007T    177 /* MaxLinear */
-#define AF9013_TUNER_TDA18218    179 /* NXP */
-	u8 tuner;
-
-	/*
-	 * IF frequency
-	 */
-	u32 if_frequency;
-
-	/*
-	 * TS settings
-	 */
-#define AF9013_TS_USB       0
-#define AF9013_TS_PARALLEL  1
-#define AF9013_TS_SERIAL    2
-	u8 ts_mode:2;
-
-	/*
-	 * input spectrum inversion
-	 */
-	bool spec_inv;
-
-	/*
-	 * firmware API version
-	 */
-	u8 api_version[4];
-
-	/*
-	 * GPIOs
-	 */
-#define AF9013_GPIO_ON (1 << 0)
-#define AF9013_GPIO_EN (1 << 1)
-#define AF9013_GPIO_O  (1 << 2)
-#define AF9013_GPIO_I  (1 << 3)
-#define AF9013_GPIO_LO (AF9013_GPIO_ON|AF9013_GPIO_EN)
-#define AF9013_GPIO_HI (AF9013_GPIO_ON|AF9013_GPIO_EN|AF9013_GPIO_O)
-#define AF9013_GPIO_TUNER_ON  (AF9013_GPIO_ON|AF9013_GPIO_EN)
-#define AF9013_GPIO_TUNER_OFF (AF9013_GPIO_ON|AF9013_GPIO_EN|AF9013_GPIO_O)
-	u8 gpio[4];
-};
-
-#if defined(CONFIG_DVB_AF9013) || \
-	(defined(CONFIG_DVB_AF9013_MODULE) && defined(MODULE))
-extern struct dvb_frontend *af9013_attach(const struct af9013_config *config,
-	struct i2c_adapter *i2c);
-#else
-static inline struct dvb_frontend *af9013_attach(
-const struct af9013_config *config, struct i2c_adapter *i2c)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif /* CONFIG_DVB_AF9013 */
-
-#endif /* AF9013_H */
diff --git a/drivers/media/dvb/frontends/af9013_priv.h b/drivers/media/dvb/frontends/af9013_priv.h
deleted file mode 100644
index fa848af..0000000
--- a/drivers/media/dvb/frontends/af9013_priv.h
+++ /dev/null
@@ -1,922 +0,0 @@
-/*
- * Afatech AF9013 demodulator driver
- *
- * Copyright (C) 2007 Antti Palosaari <crope@iki.fi>
- * Copyright (C) 2011 Antti Palosaari <crope@iki.fi>
- *
- * Thanks to Afatech who kindly provided information.
- *
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You 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 AF9013_PRIV_H
-#define AF9013_PRIV_H
-
-#include "dvb_frontend.h"
-#include "af9013.h"
-#include <linux/firmware.h>
-
-#define LOG_PREFIX "af9013"
-
-#undef dbg
-#define dbg(f, arg...) \
-	if (af9013_debug) \
-		printk(KERN_INFO   LOG_PREFIX": " f "\n" , ## arg)
-#undef err
-#define err(f, arg...)  printk(KERN_ERR     LOG_PREFIX": " f "\n" , ## arg)
-#undef info
-#define info(f, arg...) printk(KERN_INFO    LOG_PREFIX": " f "\n" , ## arg)
-#undef warn
-#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg)
-
-#define AF9013_DEFAULT_FIRMWARE     "dvb-fe-af9013.fw"
-
-struct af9013_reg_bit {
-	u16 addr;
-	u8  pos:4;
-	u8  len:4;
-	u8  val;
-};
-
-struct af9013_snr {
-	u32 val;
-	u8 snr;
-};
-
-struct af9013_coeff {
-	u32 clock;
-	u32 bandwidth_hz;
-	u8 val[24];
-};
-
-/* pre-calculated coeff lookup table */
-static const struct af9013_coeff coeff_lut[] = {
-	/* 28.800 MHz */
-	{ 28800000, 8000000, { 0x02, 0x8a, 0x28, 0xa3, 0x05, 0x14,
-		0x51, 0x11, 0x00, 0xa2, 0x8f, 0x3d, 0x00, 0xa2, 0x8a,
-		0x29, 0x00, 0xa2, 0x85, 0x14, 0x01, 0x45, 0x14, 0x14 } },
-	{ 28800000, 7000000, { 0x02, 0x38, 0xe3, 0x8e, 0x04, 0x71,
-		0xc7, 0x07, 0x00, 0x8e, 0x3d, 0x55, 0x00, 0x8e, 0x38,
-		0xe4, 0x00, 0x8e, 0x34, 0x72, 0x01, 0x1c, 0x71, 0x32 } },
-	{ 28800000, 6000000, { 0x01, 0xe7, 0x9e, 0x7a, 0x03, 0xcf,
-		0x3c, 0x3d, 0x00, 0x79, 0xeb, 0x6e, 0x00, 0x79, 0xe7,
-		0x9e, 0x00, 0x79, 0xe3, 0xcf, 0x00, 0xf3, 0xcf, 0x0f } },
-	/* 20.480 MHz */
-	{ 20480000, 8000000, { 0x03, 0x92, 0x49, 0x26, 0x07, 0x24,
-		0x92, 0x13, 0x00, 0xe4, 0x99, 0x6e, 0x00, 0xe4, 0x92,
-		0x49, 0x00, 0xe4, 0x8b, 0x25, 0x01, 0xc9, 0x24, 0x25 } },
-	{ 20480000, 7000000, { 0x03, 0x20, 0x00, 0x01, 0x06, 0x40,
-		0x00, 0x00, 0x00, 0xc8, 0x06, 0x40, 0x00, 0xc8, 0x00,
-		0x00, 0x00, 0xc7, 0xf9, 0xc0, 0x01, 0x90, 0x00, 0x00 } },
-	{ 20480000, 6000000, { 0x02, 0xad, 0xb6, 0xdc, 0x05, 0x5b,
-		0x6d, 0x2e, 0x00, 0xab, 0x73, 0x13, 0x00, 0xab, 0x6d,
-		0xb7, 0x00, 0xab, 0x68, 0x5c, 0x01, 0x56, 0xdb, 0x1c } },
-	/* 28.000 MHz */
-	{ 28000000, 8000000, { 0x02, 0x9c, 0xbc, 0x15, 0x05, 0x39,
-		0x78, 0x0a, 0x00, 0xa7, 0x34, 0x3f, 0x00, 0xa7, 0x2f,
-		0x05, 0x00, 0xa7, 0x29, 0xcc, 0x01, 0x4e, 0x5e, 0x03 } },
-	{ 28000000, 7000000, { 0x02, 0x49, 0x24, 0x92, 0x04, 0x92,
-		0x49, 0x09, 0x00, 0x92, 0x4d, 0xb7, 0x00, 0x92, 0x49,
-		0x25, 0x00, 0x92, 0x44, 0x92, 0x01, 0x24, 0x92, 0x12 } },
-	{ 28000000, 6000000, { 0x01, 0xf5, 0x8d, 0x10, 0x03, 0xeb,
-		0x1a, 0x08, 0x00, 0x7d, 0x67, 0x2f, 0x00, 0x7d, 0x63,
-		0x44, 0x00, 0x7d, 0x5f, 0x59, 0x00, 0xfa, 0xc6, 0x22 } },
-	/* 25.000 MHz */
-	{ 25000000, 8000000, { 0x02, 0xec, 0xfb, 0x9d, 0x05, 0xd9,
-		0xf7, 0x0e, 0x00, 0xbb, 0x44, 0xc1, 0x00, 0xbb, 0x3e,
-		0xe7, 0x00, 0xbb, 0x39, 0x0d, 0x01, 0x76, 0x7d, 0x34 } },
-	{ 25000000, 7000000, { 0x02, 0x8f, 0x5c, 0x29, 0x05, 0x1e,
-		0xb8, 0x14, 0x00, 0xa3, 0xdc, 0x29, 0x00, 0xa3, 0xd7,
-		0x0a, 0x00, 0xa3, 0xd1, 0xec, 0x01, 0x47, 0xae, 0x05 } },
-	{ 25000000, 6000000, { 0x02, 0x31, 0xbc, 0xb5, 0x04, 0x63,
-		0x79, 0x1b, 0x00, 0x8c, 0x73, 0x91, 0x00, 0x8c, 0x6f,
-		0x2d, 0x00, 0x8c, 0x6a, 0xca, 0x01, 0x18, 0xde, 0x17 } },
-};
-
-/* QPSK SNR lookup table */
-static const struct af9013_snr qpsk_snr_lut[] = {
-	{ 0x000000,  0 },
-	{ 0x0b4771,  0 },
-	{ 0x0c1aed,  1 },
-	{ 0x0d0d27,  2 },
-	{ 0x0e4d19,  3 },
-	{ 0x0e5da8,  4 },
-	{ 0x107097,  5 },
-	{ 0x116975,  6 },
-	{ 0x1252d9,  7 },
-	{ 0x131fa4,  8 },
-	{ 0x13d5e1,  9 },
-	{ 0x148e53, 10 },
-	{ 0x15358b, 11 },
-	{ 0x15dd29, 12 },
-	{ 0x168112, 13 },
-	{ 0x170b61, 14 },
-	{ 0xffffff, 15 },
-};
-
-/* QAM16 SNR lookup table */
-static const struct af9013_snr qam16_snr_lut[] = {
-	{ 0x000000,  0 },
-	{ 0x05eb62,  5 },
-	{ 0x05fecf,  6 },
-	{ 0x060b80,  7 },
-	{ 0x062501,  8 },
-	{ 0x064865,  9 },
-	{ 0x069604, 10 },
-	{ 0x06f356, 11 },
-	{ 0x07706a, 12 },
-	{ 0x0804d3, 13 },
-	{ 0x089d1a, 14 },
-	{ 0x093e3d, 15 },
-	{ 0x09e35d, 16 },
-	{ 0x0a7c3c, 17 },
-	{ 0x0afaf8, 18 },
-	{ 0x0b719d, 19 },
-	{ 0xffffff, 20 },
-};
-
-/* QAM64 SNR lookup table */
-static const struct af9013_snr qam64_snr_lut[] = {
-	{ 0x000000,  0 },
-	{ 0x03109b, 12 },
-	{ 0x0310d4, 13 },
-	{ 0x031920, 14 },
-	{ 0x0322d0, 15 },
-	{ 0x0339fc, 16 },
-	{ 0x0364a1, 17 },
-	{ 0x038bcc, 18 },
-	{ 0x03c7d3, 19 },
-	{ 0x0408cc, 20 },
-	{ 0x043bed, 21 },
-	{ 0x048061, 22 },
-	{ 0x04be95, 23 },
-	{ 0x04fa7d, 24 },
-	{ 0x052405, 25 },
-	{ 0x05570d, 26 },
-	{ 0xffffff, 27 },
-};
-
-static const struct af9013_reg_bit ofsm_init[] = {
-	{ 0xd73a, 0, 8, 0xa1 },
-	{ 0xd73b, 0, 8, 0x1f },
-	{ 0xd73c, 4, 4, 0x0a },
-	{ 0xd732, 3, 1, 0x00 },
-	{ 0xd731, 4, 2, 0x03 },
-	{ 0xd73d, 7, 1, 0x01 },
-	{ 0xd740, 0, 1, 0x00 },
-	{ 0xd740, 1, 1, 0x00 },
-	{ 0xd740, 2, 1, 0x00 },
-	{ 0xd740, 3, 1, 0x01 },
-	{ 0xd3c1, 4, 1, 0x01 },
-	{ 0x9124, 0, 8, 0x58 },
-	{ 0x9125, 0, 2, 0x02 },
-	{ 0xd3a2, 0, 8, 0x00 },
-	{ 0xd3a3, 0, 8, 0x04 },
-	{ 0xd305, 0, 8, 0x32 },
-	{ 0xd306, 0, 8, 0x10 },
-	{ 0xd304, 0, 8, 0x04 },
-	{ 0x9112, 0, 1, 0x01 },
-	{ 0x911d, 0, 1, 0x01 },
-	{ 0x911a, 0, 1, 0x01 },
-	{ 0x911b, 0, 1, 0x01 },
-	{ 0x9bce, 0, 4, 0x02 },
-	{ 0x9116, 0, 1, 0x01 },
-	{ 0x9122, 0, 8, 0xd0 },
-	{ 0xd2e0, 0, 8, 0xd0 },
-	{ 0xd2e9, 0, 4, 0x0d },
-	{ 0xd38c, 0, 8, 0xfc },
-	{ 0xd38d, 0, 8, 0x00 },
-	{ 0xd38e, 0, 8, 0x7e },
-	{ 0xd38f, 0, 8, 0x00 },
-	{ 0xd390, 0, 8, 0x2f },
-	{ 0xd145, 4, 1, 0x01 },
-	{ 0xd1a9, 4, 1, 0x01 },
-	{ 0xd158, 5, 3, 0x01 },
-	{ 0xd159, 0, 6, 0x06 },
-	{ 0xd167, 0, 8, 0x00 },
-	{ 0xd168, 0, 4, 0x07 },
-	{ 0xd1c3, 5, 3, 0x00 },
-	{ 0xd1c4, 0, 6, 0x00 },
-	{ 0xd1c5, 0, 7, 0x10 },
-	{ 0xd1c6, 0, 3, 0x02 },
-	{ 0xd080, 2, 5, 0x03 },
-	{ 0xd081, 4, 4, 0x09 },
-	{ 0xd098, 4, 4, 0x0f },
-	{ 0xd098, 0, 4, 0x03 },
-	{ 0xdbc0, 4, 1, 0x01 },
-	{ 0xdbc7, 0, 8, 0x08 },
-	{ 0xdbc8, 4, 4, 0x00 },
-	{ 0xdbc9, 0, 5, 0x01 },
-	{ 0xd280, 0, 8, 0xe0 },
-	{ 0xd281, 0, 8, 0xff },
-	{ 0xd282, 0, 8, 0xff },
-	{ 0xd283, 0, 8, 0xc3 },
-	{ 0xd284, 0, 8, 0xff },
-	{ 0xd285, 0, 4, 0x01 },
-	{ 0xd0f0, 0, 7, 0x1a },
-	{ 0xd0f1, 4, 1, 0x01 },
-	{ 0xd0f2, 0, 8, 0x0c },
-	{ 0xd101, 5, 3, 0x06 },
-	{ 0xd103, 0, 4, 0x08 },
-	{ 0xd0f8, 0, 7, 0x20 },
-	{ 0xd111, 5, 1, 0x00 },
-	{ 0xd111, 6, 1, 0x00 },
-	{ 0x910b, 0, 8, 0x0a },
-	{ 0x9115, 0, 8, 0x02 },
-	{ 0x910c, 0, 8, 0x02 },
-	{ 0x910d, 0, 8, 0x08 },
-	{ 0x910e, 0, 8, 0x0a },
-	{ 0x9bf6, 0, 8, 0x06 },
-	{ 0x9bf8, 0, 8, 0x02 },
-	{ 0x9bf7, 0, 8, 0x05 },
-	{ 0x9bf9, 0, 8, 0x0f },
-	{ 0x9bfc, 0, 8, 0x13 },
-	{ 0x9bd3, 0, 8, 0xff },
-	{ 0x9bbe, 0, 1, 0x01 },
-	{ 0x9bcc, 0, 1, 0x01 },
-};
-
-/* Panasonic ENV77H11D5 tuner init
-   AF9013_TUNER_ENV77H11D5 = 129 */
-static const struct af9013_reg_bit tuner_init_env77h11d5[] = {
-	{ 0x9bd5, 0, 8, 0x01 },
-	{ 0x9bd6, 0, 8, 0x03 },
-	{ 0x9bbe, 0, 8, 0x01 },
-	{ 0xd1a0, 1, 1, 0x01 },
-	{ 0xd000, 0, 1, 0x01 },
-	{ 0xd000, 1, 1, 0x00 },
-	{ 0xd001, 1, 1, 0x01 },
-	{ 0xd001, 0, 1, 0x00 },
-	{ 0xd001, 5, 1, 0x00 },
-	{ 0xd002, 0, 5, 0x19 },
-	{ 0xd003, 0, 5, 0x1a },
-	{ 0xd004, 0, 5, 0x19 },
-	{ 0xd005, 0, 5, 0x1a },
-	{ 0xd00e, 0, 5, 0x10 },
-	{ 0xd00f, 0, 3, 0x04 },
-	{ 0xd00f, 3, 3, 0x05 },
-	{ 0xd010, 0, 3, 0x04 },
-	{ 0xd010, 3, 3, 0x05 },
-	{ 0xd016, 4, 4, 0x03 },
-	{ 0xd01f, 0, 6, 0x0a },
-	{ 0xd020, 0, 6, 0x0a },
-	{ 0x9bda, 0, 8, 0x00 },
-	{ 0x9be3, 0, 8, 0x00 },
-	{ 0xd015, 0, 8, 0x50 },
-	{ 0xd016, 0, 1, 0x00 },
-	{ 0xd044, 0, 8, 0x46 },
-	{ 0xd045, 0, 1, 0x00 },
-	{ 0xd008, 0, 8, 0xdf },
-	{ 0xd009, 0, 2, 0x02 },
-	{ 0xd006, 0, 8, 0x44 },
-	{ 0xd007, 0, 2, 0x01 },
-	{ 0xd00c, 0, 8, 0xeb },
-	{ 0xd00d, 0, 2, 0x02 },
-	{ 0xd00a, 0, 8, 0xf4 },
-	{ 0xd00b, 0, 2, 0x01 },
-	{ 0x9bba, 0, 8, 0xf9 },
-	{ 0x9bc3, 0, 8, 0xdf },
-	{ 0x9bc4, 0, 8, 0x02 },
-	{ 0x9bc5, 0, 8, 0xeb },
-	{ 0x9bc6, 0, 8, 0x02 },
-	{ 0x9bc9, 0, 8, 0x52 },
-	{ 0xd011, 0, 8, 0x3c },
-	{ 0xd012, 0, 2, 0x01 },
-	{ 0xd013, 0, 8, 0xf7 },
-	{ 0xd014, 0, 2, 0x02 },
-	{ 0xd040, 0, 8, 0x0b },
-	{ 0xd041, 0, 2, 0x02 },
-	{ 0xd042, 0, 8, 0x4d },
-	{ 0xd043, 0, 2, 0x00 },
-	{ 0xd045, 1, 1, 0x00 },
-	{ 0x9bcf, 0, 1, 0x01 },
-	{ 0xd045, 2, 1, 0x01 },
-	{ 0xd04f, 0, 8, 0x9a },
-	{ 0xd050, 0, 1, 0x01 },
-	{ 0xd051, 0, 8, 0x5a },
-	{ 0xd052, 0, 1, 0x01 },
-	{ 0xd053, 0, 8, 0x50 },
-	{ 0xd054, 0, 8, 0x46 },
-	{ 0x9bd7, 0, 8, 0x0a },
-	{ 0x9bd8, 0, 8, 0x14 },
-	{ 0x9bd9, 0, 8, 0x08 },
-};
-
-/* Microtune MT2060 tuner init
-   AF9013_TUNER_MT2060     = 130 */
-static const struct af9013_reg_bit tuner_init_mt2060[] = {
-	{ 0x9bd5, 0, 8, 0x01 },
-	{ 0x9bd6, 0, 8, 0x07 },
-	{ 0xd1a0, 1, 1, 0x01 },
-	{ 0xd000, 0, 1, 0x01 },
-	{ 0xd000, 1, 1, 0x00 },
-	{ 0xd001, 1, 1, 0x01 },
-	{ 0xd001, 0, 1, 0x00 },
-	{ 0xd001, 5, 1, 0x00 },
-	{ 0xd002, 0, 5, 0x19 },
-	{ 0xd003, 0, 5, 0x1a },
-	{ 0xd004, 0, 5, 0x19 },
-	{ 0xd005, 0, 5, 0x1a },
-	{ 0xd00e, 0, 5, 0x10 },
-	{ 0xd00f, 0, 3, 0x04 },
-	{ 0xd00f, 3, 3, 0x05 },
-	{ 0xd010, 0, 3, 0x04 },
-	{ 0xd010, 3, 3, 0x05 },
-	{ 0xd016, 4, 4, 0x03 },
-	{ 0xd01f, 0, 6, 0x0a },
-	{ 0xd020, 0, 6, 0x0a },
-	{ 0x9bda, 0, 8, 0x00 },
-	{ 0x9be3, 0, 8, 0x00 },
-	{ 0x9bbe, 0, 1, 0x00 },
-	{ 0x9bcc, 0, 1, 0x00 },
-	{ 0x9bb9, 0, 8, 0x75 },
-	{ 0x9bcd, 0, 8, 0x24 },
-	{ 0x9bff, 0, 8, 0x30 },
-	{ 0xd015, 0, 8, 0x46 },
-	{ 0xd016, 0, 1, 0x00 },
-	{ 0xd044, 0, 8, 0x46 },
-	{ 0xd045, 0, 1, 0x00 },
-	{ 0xd008, 0, 8, 0x0f },
-	{ 0xd009, 0, 2, 0x02 },
-	{ 0xd006, 0, 8, 0x32 },
-	{ 0xd007, 0, 2, 0x01 },
-	{ 0xd00c, 0, 8, 0x36 },
-	{ 0xd00d, 0, 2, 0x03 },
-	{ 0xd00a, 0, 8, 0x35 },
-	{ 0xd00b, 0, 2, 0x01 },
-	{ 0x9bc7, 0, 8, 0x07 },
-	{ 0x9bc8, 0, 8, 0x90 },
-	{ 0x9bc3, 0, 8, 0x0f },
-	{ 0x9bc4, 0, 8, 0x02 },
-	{ 0x9bc5, 0, 8, 0x36 },
-	{ 0x9bc6, 0, 8, 0x03 },
-	{ 0x9bba, 0, 8, 0xc9 },
-	{ 0x9bc9, 0, 8, 0x79 },
-	{ 0xd011, 0, 8, 0x10 },
-	{ 0xd012, 0, 2, 0x01 },
-	{ 0xd013, 0, 8, 0x45 },
-	{ 0xd014, 0, 2, 0x03 },
-	{ 0xd040, 0, 8, 0x98 },
-	{ 0xd041, 0, 2, 0x00 },
-	{ 0xd042, 0, 8, 0xcf },
-	{ 0xd043, 0, 2, 0x03 },
-	{ 0xd045, 1, 1, 0x00 },
-	{ 0x9bcf, 0, 1, 0x01 },
-	{ 0xd045, 2, 1, 0x01 },
-	{ 0xd04f, 0, 8, 0x9a },
-	{ 0xd050, 0, 1, 0x01 },
-	{ 0xd051, 0, 8, 0x5a },
-	{ 0xd052, 0, 1, 0x01 },
-	{ 0xd053, 0, 8, 0x50 },
-	{ 0xd054, 0, 8, 0x46 },
-	{ 0x9bd7, 0, 8, 0x0a },
-	{ 0x9bd8, 0, 8, 0x14 },
-	{ 0x9bd9, 0, 8, 0x08 },
-	{ 0x9bd0, 0, 8, 0xcc },
-	{ 0x9be4, 0, 8, 0xa0 },
-	{ 0x9bbd, 0, 8, 0x8e },
-	{ 0x9be2, 0, 8, 0x4d },
-	{ 0x9bee, 0, 1, 0x01 },
-};
-
-/* Microtune MT2060 tuner init
-   AF9013_TUNER_MT2060_2   = 147 */
-static const struct af9013_reg_bit tuner_init_mt2060_2[] = {
-	{ 0x9bd5, 0, 8, 0x01 },
-	{ 0x9bd6, 0, 8, 0x06 },
-	{ 0x9bbe, 0, 8, 0x01 },
-	{ 0xd1a0, 1, 1, 0x01 },
-	{ 0xd000, 0, 1, 0x01 },
-	{ 0xd000, 1, 1, 0x00 },
-	{ 0xd001, 1, 1, 0x01 },
-	{ 0xd001, 0, 1, 0x00 },
-	{ 0xd001, 5, 1, 0x00 },
-	{ 0xd002, 0, 5, 0x19 },
-	{ 0xd003, 0, 5, 0x1a },
-	{ 0xd004, 0, 5, 0x19 },
-	{ 0xd005, 0, 5, 0x1a },
-	{ 0xd00e, 0, 5, 0x10 },
-	{ 0xd00f, 0, 3, 0x04 },
-	{ 0xd00f, 3, 3, 0x05 },
-	{ 0xd010, 0, 3, 0x04 },
-	{ 0xd010, 3, 3, 0x05 },
-	{ 0xd016, 4, 4, 0x03 },
-	{ 0xd01f, 0, 6, 0x0a },
-	{ 0xd020, 0, 6, 0x0a },
-	{ 0xd015, 0, 8, 0x46 },
-	{ 0xd016, 0, 1, 0x00 },
-	{ 0xd044, 0, 8, 0x46 },
-	{ 0xd045, 0, 1, 0x00 },
-	{ 0xd008, 0, 8, 0x0f },
-	{ 0xd009, 0, 2, 0x02 },
-	{ 0xd006, 0, 8, 0x32 },
-	{ 0xd007, 0, 2, 0x01 },
-	{ 0xd00c, 0, 8, 0x36 },
-	{ 0xd00d, 0, 2, 0x03 },
-	{ 0xd00a, 0, 8, 0x35 },
-	{ 0xd00b, 0, 2, 0x01 },
-	{ 0x9bc7, 0, 8, 0x07 },
-	{ 0x9bc8, 0, 8, 0x90 },
-	{ 0x9bc3, 0, 8, 0x0f },
-	{ 0x9bc4, 0, 8, 0x02 },
-	{ 0x9bc5, 0, 8, 0x36 },
-	{ 0x9bc6, 0, 8, 0x03 },
-	{ 0x9bba, 0, 8, 0xc9 },
-	{ 0x9bc9, 0, 8, 0x79 },
-	{ 0xd011, 0, 8, 0x10 },
-	{ 0xd012, 0, 2, 0x01 },
-	{ 0xd013, 0, 8, 0x45 },
-	{ 0xd014, 0, 2, 0x03 },
-	{ 0xd040, 0, 8, 0x98 },
-	{ 0xd041, 0, 2, 0x00 },
-	{ 0xd042, 0, 8, 0xcf },
-	{ 0xd043, 0, 2, 0x03 },
-	{ 0xd045, 1, 1, 0x00 },
-	{ 0x9bcf, 0, 8, 0x01 },
-	{ 0xd045, 2, 1, 0x01 },
-	{ 0xd04f, 0, 8, 0x9a },
-	{ 0xd050, 0, 1, 0x01 },
-	{ 0xd051, 0, 8, 0x5a },
-	{ 0xd052, 0, 1, 0x01 },
-	{ 0xd053, 0, 8, 0x96 },
-	{ 0xd054, 0, 8, 0x46 },
-	{ 0xd045, 7, 1, 0x00 },
-	{ 0x9bd7, 0, 8, 0x0a },
-	{ 0x9bd8, 0, 8, 0x14 },
-	{ 0x9bd9, 0, 8, 0x08 },
-};
-
-/* MaxLinear MXL5003 tuner init
-   AF9013_TUNER_MXL5003D   =   3 */
-static const struct af9013_reg_bit tuner_init_mxl5003d[] = {
-	{ 0x9bd5, 0, 8, 0x01 },
-	{ 0x9bd6, 0, 8, 0x09 },
-	{ 0xd1a0, 1, 1, 0x01 },
-	{ 0xd000, 0, 1, 0x01 },
-	{ 0xd000, 1, 1, 0x00 },
-	{ 0xd001, 1, 1, 0x01 },
-	{ 0xd001, 0, 1, 0x00 },
-	{ 0xd001, 5, 1, 0x00 },
-	{ 0xd002, 0, 5, 0x19 },
-	{ 0xd003, 0, 5, 0x1a },
-	{ 0xd004, 0, 5, 0x19 },
-	{ 0xd005, 0, 5, 0x1a },
-	{ 0xd00e, 0, 5, 0x10 },
-	{ 0xd00f, 0, 3, 0x04 },
-	{ 0xd00f, 3, 3, 0x05 },
-	{ 0xd010, 0, 3, 0x04 },
-	{ 0xd010, 3, 3, 0x05 },
-	{ 0xd016, 4, 4, 0x03 },
-	{ 0xd01f, 0, 6, 0x0a },
-	{ 0xd020, 0, 6, 0x0a },
-	{ 0x9bda, 0, 8, 0x00 },
-	{ 0x9be3, 0, 8, 0x00 },
-	{ 0x9bfc, 0, 8, 0x0f },
-	{ 0x9bf6, 0, 8, 0x01 },
-	{ 0x9bbe, 0, 1, 0x01 },
-	{ 0xd015, 0, 8, 0x33 },
-	{ 0xd016, 0, 1, 0x00 },
-	{ 0xd044, 0, 8, 0x40 },
-	{ 0xd045, 0, 1, 0x00 },
-	{ 0xd008, 0, 8, 0x0f },
-	{ 0xd009, 0, 2, 0x02 },
-	{ 0xd006, 0, 8, 0x6c },
-	{ 0xd007, 0, 2, 0x00 },
-	{ 0xd00c, 0, 8, 0x3d },
-	{ 0xd00d, 0, 2, 0x00 },
-	{ 0xd00a, 0, 8, 0x45 },
-	{ 0xd00b, 0, 2, 0x01 },
-	{ 0x9bc7, 0, 8, 0x07 },
-	{ 0x9bc8, 0, 8, 0x52 },
-	{ 0x9bc3, 0, 8, 0x0f },
-	{ 0x9bc4, 0, 8, 0x02 },
-	{ 0x9bc5, 0, 8, 0x3d },
-	{ 0x9bc6, 0, 8, 0x00 },
-	{ 0x9bba, 0, 8, 0xa2 },
-	{ 0x9bc9, 0, 8, 0xa0 },
-	{ 0xd011, 0, 8, 0x56 },
-	{ 0xd012, 0, 2, 0x00 },
-	{ 0xd013, 0, 8, 0x50 },
-	{ 0xd014, 0, 2, 0x00 },
-	{ 0xd040, 0, 8, 0x56 },
-	{ 0xd041, 0, 2, 0x00 },
-	{ 0xd042, 0, 8, 0x50 },
-	{ 0xd043, 0, 2, 0x00 },
-	{ 0xd045, 1, 1, 0x00 },
-	{ 0x9bcf, 0, 8, 0x01 },
-	{ 0xd045, 2, 1, 0x01 },
-	{ 0xd04f, 0, 8, 0x9a },
-	{ 0xd050, 0, 1, 0x01 },
-	{ 0xd051, 0, 8, 0x5a },
-	{ 0xd052, 0, 1, 0x01 },
-	{ 0xd053, 0, 8, 0x50 },
-	{ 0xd054, 0, 8, 0x46 },
-	{ 0x9bd7, 0, 8, 0x0a },
-	{ 0x9bd8, 0, 8, 0x14 },
-	{ 0x9bd9, 0, 8, 0x08 },
-};
-
-/* MaxLinear MXL5005S & MXL5007T tuner init
-   AF9013_TUNER_MXL5005D   =  13
-   AF9013_TUNER_MXL5005R   =  30
-   AF9013_TUNER_MXL5007T   = 177 */
-static const struct af9013_reg_bit tuner_init_mxl5005[] = {
-	{ 0x9bd5, 0, 8, 0x01 },
-	{ 0x9bd6, 0, 8, 0x07 },
-	{ 0xd1a0, 1, 1, 0x01 },
-	{ 0xd000, 0, 1, 0x01 },
-	{ 0xd000, 1, 1, 0x00 },
-	{ 0xd001, 1, 1, 0x01 },
-	{ 0xd001, 0, 1, 0x00 },
-	{ 0xd001, 5, 1, 0x00 },
-	{ 0xd002, 0, 5, 0x19 },
-	{ 0xd003, 0, 5, 0x1a },
-	{ 0xd004, 0, 5, 0x19 },
-	{ 0xd005, 0, 5, 0x1a },
-	{ 0xd00e, 0, 5, 0x10 },
-	{ 0xd00f, 0, 3, 0x04 },
-	{ 0xd00f, 3, 3, 0x05 },
-	{ 0xd010, 0, 3, 0x04 },
-	{ 0xd010, 3, 3, 0x05 },
-	{ 0xd016, 4, 4, 0x03 },
-	{ 0xd01f, 0, 6, 0x0a },
-	{ 0xd020, 0, 6, 0x0a },
-	{ 0x9bda, 0, 8, 0x01 },
-	{ 0x9be3, 0, 8, 0x01 },
-	{ 0x9bbe, 0, 1, 0x01 },
-	{ 0x9bcc, 0, 1, 0x01 },
-	{ 0x9bb9, 0, 8, 0x00 },
-	{ 0x9bcd, 0, 8, 0x28 },
-	{ 0x9bff, 0, 8, 0x24 },
-	{ 0xd015, 0, 8, 0x40 },
-	{ 0xd016, 0, 1, 0x00 },
-	{ 0xd044, 0, 8, 0x40 },
-	{ 0xd045, 0, 1, 0x00 },
-	{ 0xd008, 0, 8, 0x0f },
-	{ 0xd009, 0, 2, 0x02 },
-	{ 0xd006, 0, 8, 0x73 },
-	{ 0xd007, 0, 2, 0x01 },
-	{ 0xd00c, 0, 8, 0xfa },
-	{ 0xd00d, 0, 2, 0x01 },
-	{ 0xd00a, 0, 8, 0xff },
-	{ 0xd00b, 0, 2, 0x01 },
-	{ 0x9bc7, 0, 8, 0x23 },
-	{ 0x9bc8, 0, 8, 0x55 },
-	{ 0x9bc3, 0, 8, 0x01 },
-	{ 0x9bc4, 0, 8, 0x02 },
-	{ 0x9bc5, 0, 8, 0xfa },
-	{ 0x9bc6, 0, 8, 0x01 },
-	{ 0x9bba, 0, 8, 0xff },
-	{ 0x9bc9, 0, 8, 0xff },
-	{ 0x9bd3, 0, 8, 0x95 },
-	{ 0xd011, 0, 8, 0x70 },
-	{ 0xd012, 0, 2, 0x01 },
-	{ 0xd013, 0, 8, 0xfb },
-	{ 0xd014, 0, 2, 0x01 },
-	{ 0xd040, 0, 8, 0x70 },
-	{ 0xd041, 0, 2, 0x01 },
-	{ 0xd042, 0, 8, 0xfb },
-	{ 0xd043, 0, 2, 0x01 },
-	{ 0xd045, 1, 1, 0x00 },
-	{ 0x9bcf, 0, 1, 0x01 },
-	{ 0xd045, 2, 1, 0x01 },
-	{ 0xd04f, 0, 8, 0x9a },
-	{ 0xd050, 0, 1, 0x01 },
-	{ 0xd051, 0, 8, 0x5a },
-	{ 0xd052, 0, 1, 0x01 },
-	{ 0xd053, 0, 8, 0x50 },
-	{ 0xd054, 0, 8, 0x46 },
-	{ 0x9bd7, 0, 8, 0x0a },
-	{ 0x9bd8, 0, 8, 0x14 },
-	{ 0x9bd9, 0, 8, 0x08 },
-	{ 0x9bd0, 0, 8, 0x93 },
-	{ 0x9be4, 0, 8, 0xfe },
-	{ 0x9bbd, 0, 8, 0x63 },
-	{ 0x9be2, 0, 8, 0xfe },
-	{ 0x9bee, 0, 1, 0x01 },
-};
-
-/* Quantek QT1010 tuner init
-   AF9013_TUNER_QT1010     = 134
-   AF9013_TUNER_QT1010A    = 162 */
-static const struct af9013_reg_bit tuner_init_qt1010[] = {
-	{ 0x9bd5, 0, 8, 0x01 },
-	{ 0x9bd6, 0, 8, 0x09 },
-	{ 0xd1a0, 1, 1, 0x01 },
-	{ 0xd000, 0, 1, 0x01 },
-	{ 0xd000, 1, 1, 0x00 },
-	{ 0xd001, 1, 1, 0x01 },
-	{ 0xd001, 0, 1, 0x00 },
-	{ 0xd001, 5, 1, 0x00 },
-	{ 0xd002, 0, 5, 0x19 },
-	{ 0xd003, 0, 5, 0x1a },
-	{ 0xd004, 0, 5, 0x19 },
-	{ 0xd005, 0, 5, 0x1a },
-	{ 0xd00e, 0, 5, 0x10 },
-	{ 0xd00f, 0, 3, 0x04 },
-	{ 0xd00f, 3, 3, 0x05 },
-	{ 0xd010, 0, 3, 0x04 },
-	{ 0xd010, 3, 3, 0x05 },
-	{ 0xd016, 4, 4, 0x03 },
-	{ 0xd01f, 0, 6, 0x0a },
-	{ 0xd020, 0, 6, 0x0a },
-	{ 0x9bda, 0, 8, 0x01 },
-	{ 0x9be3, 0, 8, 0x01 },
-	{ 0xd015, 0, 8, 0x46 },
-	{ 0xd016, 0, 1, 0x00 },
-	{ 0xd044, 0, 8, 0x46 },
-	{ 0xd045, 0, 1, 0x00 },
-	{ 0x9bbe, 0, 1, 0x01 },
-	{ 0x9bcc, 0, 1, 0x01 },
-	{ 0x9bb9, 0, 8, 0x00 },
-	{ 0x9bcd, 0, 8, 0x28 },
-	{ 0x9bff, 0, 8, 0x20 },
-	{ 0xd008, 0, 8, 0x0f },
-	{ 0xd009, 0, 2, 0x02 },
-	{ 0xd006, 0, 8, 0x99 },
-	{ 0xd007, 0, 2, 0x01 },
-	{ 0xd00c, 0, 8, 0x0f },
-	{ 0xd00d, 0, 2, 0x02 },
-	{ 0xd00a, 0, 8, 0x50 },
-	{ 0xd00b, 0, 2, 0x01 },
-	{ 0x9bc7, 0, 8, 0x00 },
-	{ 0x9bc8, 0, 8, 0x00 },
-	{ 0x9bc3, 0, 8, 0x0f },
-	{ 0x9bc4, 0, 8, 0x02 },
-	{ 0x9bc5, 0, 8, 0x0f },
-	{ 0x9bc6, 0, 8, 0x02 },
-	{ 0x9bba, 0, 8, 0xc5 },
-	{ 0x9bc9, 0, 8, 0xff },
-	{ 0xd011, 0, 8, 0x58 },
-	{ 0xd012, 0, 2, 0x02 },
-	{ 0xd013, 0, 8, 0x89 },
-	{ 0xd014, 0, 2, 0x01 },
-	{ 0xd040, 0, 8, 0x58 },
-	{ 0xd041, 0, 2, 0x02 },
-	{ 0xd042, 0, 8, 0x89 },
-	{ 0xd043, 0, 2, 0x01 },
-	{ 0xd045, 1, 1, 0x00 },
-	{ 0x9bcf, 0, 1, 0x01 },
-	{ 0xd045, 2, 1, 0x01 },
-	{ 0xd04f, 0, 8, 0x9a },
-	{ 0xd050, 0, 1, 0x01 },
-	{ 0xd051, 0, 8, 0x5a },
-	{ 0xd052, 0, 1, 0x01 },
-	{ 0xd053, 0, 8, 0x50 },
-	{ 0xd054, 0, 8, 0x46 },
-	{ 0x9bd7, 0, 8, 0x0a },
-	{ 0x9bd8, 0, 8, 0x14 },
-	{ 0x9bd9, 0, 8, 0x08 },
-	{ 0x9bd0, 0, 8, 0xcd },
-	{ 0x9be4, 0, 8, 0xbb },
-	{ 0x9bbd, 0, 8, 0x93 },
-	{ 0x9be2, 0, 8, 0x80 },
-	{ 0x9bee, 0, 1, 0x01 },
-};
-
-/* Freescale MC44S803 tuner init
-   AF9013_TUNER_MC44S803   = 133 */
-static const struct af9013_reg_bit tuner_init_mc44s803[] = {
-	{ 0x9bd5, 0, 8, 0x01 },
-	{ 0x9bd6, 0, 8, 0x06 },
-	{ 0xd1a0, 1, 1, 0x01 },
-	{ 0xd000, 0, 1, 0x01 },
-	{ 0xd000, 1, 1, 0x00 },
-	{ 0xd001, 1, 1, 0x01 },
-	{ 0xd001, 0, 1, 0x00 },
-	{ 0xd001, 5, 1, 0x00 },
-	{ 0xd002, 0, 5, 0x19 },
-	{ 0xd003, 0, 5, 0x1a },
-	{ 0xd004, 0, 5, 0x19 },
-	{ 0xd005, 0, 5, 0x1a },
-	{ 0xd00e, 0, 5, 0x10 },
-	{ 0xd00f, 0, 3, 0x04 },
-	{ 0xd00f, 3, 3, 0x05 },
-	{ 0xd010, 0, 3, 0x04 },
-	{ 0xd010, 3, 3, 0x05 },
-	{ 0xd016, 4, 4, 0x03 },
-	{ 0xd01f, 0, 6, 0x0a },
-	{ 0xd020, 0, 6, 0x0a },
-	{ 0x9bda, 0, 8, 0x00 },
-	{ 0x9be3, 0, 8, 0x00 },
-	{ 0x9bf6, 0, 8, 0x01 },
-	{ 0x9bf8, 0, 8, 0x02 },
-	{ 0x9bf9, 0, 8, 0x02 },
-	{ 0x9bfc, 0, 8, 0x1f },
-	{ 0x9bbe, 0, 1, 0x01 },
-	{ 0x9bcc, 0, 1, 0x01 },
-	{ 0x9bb9, 0, 8, 0x00 },
-	{ 0x9bcd, 0, 8, 0x24 },
-	{ 0x9bff, 0, 8, 0x24 },
-	{ 0xd015, 0, 8, 0x46 },
-	{ 0xd016, 0, 1, 0x00 },
-	{ 0xd044, 0, 8, 0x46 },
-	{ 0xd045, 0, 1, 0x00 },
-	{ 0xd008, 0, 8, 0x01 },
-	{ 0xd009, 0, 2, 0x02 },
-	{ 0xd006, 0, 8, 0x7b },
-	{ 0xd007, 0, 2, 0x00 },
-	{ 0xd00c, 0, 8, 0x7c },
-	{ 0xd00d, 0, 2, 0x02 },
-	{ 0xd00a, 0, 8, 0xfe },
-	{ 0xd00b, 0, 2, 0x01 },
-	{ 0x9bc7, 0, 8, 0x08 },
-	{ 0x9bc8, 0, 8, 0x9a },
-	{ 0x9bc3, 0, 8, 0x01 },
-	{ 0x9bc4, 0, 8, 0x02 },
-	{ 0x9bc5, 0, 8, 0x7c },
-	{ 0x9bc6, 0, 8, 0x02 },
-	{ 0x9bba, 0, 8, 0xfc },
-	{ 0x9bc9, 0, 8, 0xaa },
-	{ 0xd011, 0, 8, 0x6b },
-	{ 0xd012, 0, 2, 0x00 },
-	{ 0xd013, 0, 8, 0x88 },
-	{ 0xd014, 0, 2, 0x02 },
-	{ 0xd040, 0, 8, 0x6b },
-	{ 0xd041, 0, 2, 0x00 },
-	{ 0xd042, 0, 8, 0x7c },
-	{ 0xd043, 0, 2, 0x02 },
-	{ 0xd045, 1, 1, 0x00 },
-	{ 0x9bcf, 0, 1, 0x01 },
-	{ 0xd045, 2, 1, 0x01 },
-	{ 0xd04f, 0, 8, 0x9a },
-	{ 0xd050, 0, 1, 0x01 },
-	{ 0xd051, 0, 8, 0x5a },
-	{ 0xd052, 0, 1, 0x01 },
-	{ 0xd053, 0, 8, 0x50 },
-	{ 0xd054, 0, 8, 0x46 },
-	{ 0x9bd7, 0, 8, 0x0a },
-	{ 0x9bd8, 0, 8, 0x14 },
-	{ 0x9bd9, 0, 8, 0x08 },
-	{ 0x9bd0, 0, 8, 0x9e },
-	{ 0x9be4, 0, 8, 0xff },
-	{ 0x9bbd, 0, 8, 0x9e },
-	{ 0x9be2, 0, 8, 0x25 },
-	{ 0x9bee, 0, 1, 0x01 },
-	{ 0xd73b, 3, 1, 0x00 },
-};
-
-/* unknown, probably for tin can tuner, tuner init
-   AF9013_TUNER_UNKNOWN   = 140 */
-static const struct af9013_reg_bit tuner_init_unknown[] = {
-	{ 0x9bd5, 0, 8, 0x01 },
-	{ 0x9bd6, 0, 8, 0x02 },
-	{ 0xd1a0, 1, 1, 0x01 },
-	{ 0xd000, 0, 1, 0x01 },
-	{ 0xd000, 1, 1, 0x00 },
-	{ 0xd001, 1, 1, 0x01 },
-	{ 0xd001, 0, 1, 0x00 },
-	{ 0xd001, 5, 1, 0x00 },
-	{ 0xd002, 0, 5, 0x19 },
-	{ 0xd003, 0, 5, 0x1a },
-	{ 0xd004, 0, 5, 0x19 },
-	{ 0xd005, 0, 5, 0x1a },
-	{ 0xd00e, 0, 5, 0x10 },
-	{ 0xd00f, 0, 3, 0x04 },
-	{ 0xd00f, 3, 3, 0x05 },
-	{ 0xd010, 0, 3, 0x04 },
-	{ 0xd010, 3, 3, 0x05 },
-	{ 0xd016, 4, 4, 0x03 },
-	{ 0xd01f, 0, 6, 0x0a },
-	{ 0xd020, 0, 6, 0x0a },
-	{ 0x9bda, 0, 8, 0x01 },
-	{ 0x9be3, 0, 8, 0x01 },
-	{ 0xd1a0, 1, 1, 0x00 },
-	{ 0x9bbe, 0, 1, 0x01 },
-	{ 0x9bcc, 0, 1, 0x01 },
-	{ 0x9bb9, 0, 8, 0x00 },
-	{ 0x9bcd, 0, 8, 0x18 },
-	{ 0x9bff, 0, 8, 0x2c },
-	{ 0xd015, 0, 8, 0x46 },
-	{ 0xd016, 0, 1, 0x00 },
-	{ 0xd044, 0, 8, 0x46 },
-	{ 0xd045, 0, 1, 0x00 },
-	{ 0xd008, 0, 8, 0xdf },
-	{ 0xd009, 0, 2, 0x02 },
-	{ 0xd006, 0, 8, 0x44 },
-	{ 0xd007, 0, 2, 0x01 },
-	{ 0xd00c, 0, 8, 0x00 },
-	{ 0xd00d, 0, 2, 0x02 },
-	{ 0xd00a, 0, 8, 0xf6 },
-	{ 0xd00b, 0, 2, 0x01 },
-	{ 0x9bba, 0, 8, 0xf9 },
-	{ 0x9bc8, 0, 8, 0xaa },
-	{ 0x9bc3, 0, 8, 0xdf },
-	{ 0x9bc4, 0, 8, 0x02 },
-	{ 0x9bc5, 0, 8, 0x00 },
-	{ 0x9bc6, 0, 8, 0x02 },
-	{ 0x9bc9, 0, 8, 0xf0 },
-	{ 0xd011, 0, 8, 0x3c },
-	{ 0xd012, 0, 2, 0x01 },
-	{ 0xd013, 0, 8, 0xf7 },
-	{ 0xd014, 0, 2, 0x02 },
-	{ 0xd040, 0, 8, 0x0b },
-	{ 0xd041, 0, 2, 0x02 },
-	{ 0xd042, 0, 8, 0x4d },
-	{ 0xd043, 0, 2, 0x00 },
-	{ 0xd045, 1, 1, 0x00 },
-	{ 0x9bcf, 0, 1, 0x01 },
-	{ 0xd045, 2, 1, 0x01 },
-	{ 0xd04f, 0, 8, 0x9a },
-	{ 0xd050, 0, 1, 0x01 },
-	{ 0xd051, 0, 8, 0x5a },
-	{ 0xd052, 0, 1, 0x01 },
-	{ 0xd053, 0, 8, 0x50 },
-	{ 0xd054, 0, 8, 0x46 },
-	{ 0x9bd7, 0, 8, 0x0a },
-	{ 0x9bd8, 0, 8, 0x14 },
-	{ 0x9bd9, 0, 8, 0x08 },
-};
-
-/* NXP TDA18271 & TDA18218 tuner init
-   AF9013_TUNER_TDA18271   = 156
-   AF9013_TUNER_TDA18218   = 179 */
-static const struct af9013_reg_bit tuner_init_tda18271[] = {
-	{ 0x9bd5, 0, 8, 0x01 },
-	{ 0x9bd6, 0, 8, 0x04 },
-	{ 0xd1a0, 1, 1, 0x01 },
-	{ 0xd000, 0, 1, 0x01 },
-	{ 0xd000, 1, 1, 0x00 },
-	{ 0xd001, 1, 1, 0x01 },
-	{ 0xd001, 0, 1, 0x00 },
-	{ 0xd001, 5, 1, 0x00 },
-	{ 0xd002, 0, 5, 0x19 },
-	{ 0xd003, 0, 5, 0x1a },
-	{ 0xd004, 0, 5, 0x19 },
-	{ 0xd005, 0, 5, 0x1a },
-	{ 0xd00e, 0, 5, 0x10 },
-	{ 0xd00f, 0, 3, 0x04 },
-	{ 0xd00f, 3, 3, 0x05 },
-	{ 0xd010, 0, 3, 0x04 },
-	{ 0xd010, 3, 3, 0x05 },
-	{ 0xd016, 4, 4, 0x03 },
-	{ 0xd01f, 0, 6, 0x0a },
-	{ 0xd020, 0, 6, 0x0a },
-	{ 0x9bda, 0, 8, 0x01 },
-	{ 0x9be3, 0, 8, 0x01 },
-	{ 0xd1a0, 1, 1, 0x00 },
-	{ 0x9bbe, 0, 1, 0x01 },
-	{ 0x9bcc, 0, 1, 0x01 },
-	{ 0x9bb9, 0, 8, 0x00 },
-	{ 0x9bcd, 0, 8, 0x18 },
-	{ 0x9bff, 0, 8, 0x2c },
-	{ 0xd015, 0, 8, 0x46 },
-	{ 0xd016, 0, 1, 0x00 },
-	{ 0xd044, 0, 8, 0x46 },
-	{ 0xd045, 0, 1, 0x00 },
-	{ 0xd008, 0, 8, 0xdf },
-	{ 0xd009, 0, 2, 0x02 },
-	{ 0xd006, 0, 8, 0x44 },
-	{ 0xd007, 0, 2, 0x01 },
-	{ 0xd00c, 0, 8, 0x00 },
-	{ 0xd00d, 0, 2, 0x02 },
-	{ 0xd00a, 0, 8, 0xf6 },
-	{ 0xd00b, 0, 2, 0x01 },
-	{ 0x9bba, 0, 8, 0xf9 },
-	{ 0x9bc8, 0, 8, 0xaa },
-	{ 0x9bc3, 0, 8, 0xdf },
-	{ 0x9bc4, 0, 8, 0x02 },
-	{ 0x9bc5, 0, 8, 0x00 },
-	{ 0x9bc6, 0, 8, 0x02 },
-	{ 0x9bc9, 0, 8, 0xf0 },
-	{ 0xd011, 0, 8, 0x3c },
-	{ 0xd012, 0, 2, 0x01 },
-	{ 0xd013, 0, 8, 0xf7 },
-	{ 0xd014, 0, 2, 0x02 },
-	{ 0xd040, 0, 8, 0x0b },
-	{ 0xd041, 0, 2, 0x02 },
-	{ 0xd042, 0, 8, 0x4d },
-	{ 0xd043, 0, 2, 0x00 },
-	{ 0xd045, 1, 1, 0x00 },
-	{ 0x9bcf, 0, 1, 0x01 },
-	{ 0xd045, 2, 1, 0x01 },
-	{ 0xd04f, 0, 8, 0x9a },
-	{ 0xd050, 0, 1, 0x01 },
-	{ 0xd051, 0, 8, 0x5a },
-	{ 0xd052, 0, 1, 0x01 },
-	{ 0xd053, 0, 8, 0x50 },
-	{ 0xd054, 0, 8, 0x46 },
-	{ 0x9bd7, 0, 8, 0x0a },
-	{ 0x9bd8, 0, 8, 0x14 },
-	{ 0x9bd9, 0, 8, 0x08 },
-	{ 0x9bd0, 0, 8, 0xa8 },
-	{ 0x9be4, 0, 8, 0x7f },
-	{ 0x9bbd, 0, 8, 0xa8 },
-	{ 0x9be2, 0, 8, 0x20 },
-	{ 0x9bee, 0, 1, 0x01 },
-};
-
-#endif /* AF9013_PRIV_H */
diff --git a/drivers/media/dvb/frontends/af9033.c b/drivers/media/dvb/frontends/af9033.c
deleted file mode 100644
index a389982..0000000
--- a/drivers/media/dvb/frontends/af9033.c
+++ /dev/null
@@ -1,980 +0,0 @@
-/*
- * Afatech AF9033 demodulator driver
- *
- * Copyright (C) 2009 Antti Palosaari <crope@iki.fi>
- * Copyright (C) 2012 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.,
- *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include "af9033_priv.h"
-
-struct af9033_state {
-	struct i2c_adapter *i2c;
-	struct dvb_frontend fe;
-	struct af9033_config cfg;
-
-	u32 bandwidth_hz;
-	bool ts_mode_parallel;
-	bool ts_mode_serial;
-
-	u32 ber;
-	u32 ucb;
-	unsigned long last_stat_check;
-};
-
-/* write multiple registers */
-static int af9033_wr_regs(struct af9033_state *state, u32 reg, const u8 *val,
-		int len)
-{
-	int ret;
-	u8 buf[3 + len];
-	struct i2c_msg msg[1] = {
-		{
-			.addr = state->cfg.i2c_addr,
-			.flags = 0,
-			.len = sizeof(buf),
-			.buf = buf,
-		}
-	};
-
-	buf[0] = (reg >> 16) & 0xff;
-	buf[1] = (reg >>  8) & 0xff;
-	buf[2] = (reg >>  0) & 0xff;
-	memcpy(&buf[3], val, len);
-
-	ret = i2c_transfer(state->i2c, msg, 1);
-	if (ret == 1) {
-		ret = 0;
-	} else {
-		printk(KERN_WARNING "%s: i2c wr failed=%d reg=%06x len=%d\n",
-				__func__, ret, reg, len);
-		ret = -EREMOTEIO;
-	}
-
-	return ret;
-}
-
-/* read multiple registers */
-static int af9033_rd_regs(struct af9033_state *state, u32 reg, u8 *val, int len)
-{
-	int ret;
-	u8 buf[3] = { (reg >> 16) & 0xff, (reg >> 8) & 0xff,
-			(reg >> 0) & 0xff };
-	struct i2c_msg msg[2] = {
-		{
-			.addr = state->cfg.i2c_addr,
-			.flags = 0,
-			.len = sizeof(buf),
-			.buf = buf
-		}, {
-			.addr = state->cfg.i2c_addr,
-			.flags = I2C_M_RD,
-			.len = len,
-			.buf = val
-		}
-	};
-
-	ret = i2c_transfer(state->i2c, msg, 2);
-	if (ret == 2) {
-		ret = 0;
-	} else {
-		printk(KERN_WARNING "%s: i2c rd failed=%d reg=%06x len=%d\n",
-				__func__, ret, reg, len);
-		ret = -EREMOTEIO;
-	}
-
-	return ret;
-}
-
-
-/* write single register */
-static int af9033_wr_reg(struct af9033_state *state, u32 reg, u8 val)
-{
-	return af9033_wr_regs(state, reg, &val, 1);
-}
-
-/* read single register */
-static int af9033_rd_reg(struct af9033_state *state, u32 reg, u8 *val)
-{
-	return af9033_rd_regs(state, reg, val, 1);
-}
-
-/* write single register with mask */
-static int af9033_wr_reg_mask(struct af9033_state *state, u32 reg, u8 val,
-		u8 mask)
-{
-	int ret;
-	u8 tmp;
-
-	/* no need for read if whole reg is written */
-	if (mask != 0xff) {
-		ret = af9033_rd_regs(state, reg, &tmp, 1);
-		if (ret)
-			return ret;
-
-		val &= mask;
-		tmp &= ~mask;
-		val |= tmp;
-	}
-
-	return af9033_wr_regs(state, reg, &val, 1);
-}
-
-/* read single register with mask */
-static int af9033_rd_reg_mask(struct af9033_state *state, u32 reg, u8 *val,
-		u8 mask)
-{
-	int ret, i;
-	u8 tmp;
-
-	ret = af9033_rd_regs(state, reg, &tmp, 1);
-	if (ret)
-		return ret;
-
-	tmp &= mask;
-
-	/* find position of the first bit */
-	for (i = 0; i < 8; i++) {
-		if ((mask >> i) & 0x01)
-			break;
-	}
-	*val = tmp >> i;
-
-	return 0;
-}
-
-static u32 af9033_div(u32 a, u32 b, u32 x)
-{
-	u32 r = 0, c = 0, i;
-
-	pr_debug("%s: a=%d b=%d x=%d\n", __func__, a, b, x);
-
-	if (a > b) {
-		c = a / b;
-		a = a - c * b;
-	}
-
-	for (i = 0; i < x; i++) {
-		if (a >= b) {
-			r += 1;
-			a -= b;
-		}
-		a <<= 1;
-		r <<= 1;
-	}
-	r = (c << (u32)x) + r;
-
-	pr_debug("%s: a=%d b=%d x=%d r=%d r=%x\n", __func__, a, b, x, r, r);
-
-	return r;
-}
-
-static void af9033_release(struct dvb_frontend *fe)
-{
-	struct af9033_state *state = fe->demodulator_priv;
-
-	kfree(state);
-}
-
-static int af9033_init(struct dvb_frontend *fe)
-{
-	struct af9033_state *state = fe->demodulator_priv;
-	int ret, i, len;
-	const struct reg_val *init;
-	u8 buf[4];
-	u32 adc_cw, clock_cw;
-	struct reg_val_mask tab[] = {
-		{ 0x80fb24, 0x00, 0x08 },
-		{ 0x80004c, 0x00, 0xff },
-		{ 0x00f641, state->cfg.tuner, 0xff },
-		{ 0x80f5ca, 0x01, 0x01 },
-		{ 0x80f715, 0x01, 0x01 },
-		{ 0x00f41f, 0x04, 0x04 },
-		{ 0x00f41a, 0x01, 0x01 },
-		{ 0x80f731, 0x00, 0x01 },
-		{ 0x00d91e, 0x00, 0x01 },
-		{ 0x00d919, 0x00, 0x01 },
-		{ 0x80f732, 0x00, 0x01 },
-		{ 0x00d91f, 0x00, 0x01 },
-		{ 0x00d91a, 0x00, 0x01 },
-		{ 0x80f730, 0x00, 0x01 },
-		{ 0x80f778, 0x00, 0xff },
-		{ 0x80f73c, 0x01, 0x01 },
-		{ 0x80f776, 0x00, 0x01 },
-		{ 0x00d8fd, 0x01, 0xff },
-		{ 0x00d830, 0x01, 0xff },
-		{ 0x00d831, 0x00, 0xff },
-		{ 0x00d832, 0x00, 0xff },
-		{ 0x80f985, state->ts_mode_serial, 0x01 },
-		{ 0x80f986, state->ts_mode_parallel, 0x01 },
-		{ 0x00d827, 0x00, 0xff },
-		{ 0x00d829, 0x00, 0xff },
-	};
-
-	/* program clock control */
-	clock_cw = af9033_div(state->cfg.clock, 1000000ul, 19ul);
-	buf[0] = (clock_cw >>  0) & 0xff;
-	buf[1] = (clock_cw >>  8) & 0xff;
-	buf[2] = (clock_cw >> 16) & 0xff;
-	buf[3] = (clock_cw >> 24) & 0xff;
-
-	pr_debug("%s: clock=%d clock_cw=%08x\n", __func__, state->cfg.clock,
-			clock_cw);
-
-	ret = af9033_wr_regs(state, 0x800025, buf, 4);
-	if (ret < 0)
-		goto err;
-
-	/* program ADC control */
-	for (i = 0; i < ARRAY_SIZE(clock_adc_lut); i++) {
-		if (clock_adc_lut[i].clock == state->cfg.clock)
-			break;
-	}
-
-	adc_cw = af9033_div(clock_adc_lut[i].adc, 1000000ul, 19ul);
-	buf[0] = (adc_cw >>  0) & 0xff;
-	buf[1] = (adc_cw >>  8) & 0xff;
-	buf[2] = (adc_cw >> 16) & 0xff;
-
-	pr_debug("%s: adc=%d adc_cw=%06x\n", __func__, clock_adc_lut[i].adc,
-			adc_cw);
-
-	ret = af9033_wr_regs(state, 0x80f1cd, buf, 3);
-	if (ret < 0)
-		goto err;
-
-	/* program register table */
-	for (i = 0; i < ARRAY_SIZE(tab); i++) {
-		ret = af9033_wr_reg_mask(state, tab[i].reg, tab[i].val,
-				tab[i].mask);
-		if (ret < 0)
-			goto err;
-	}
-
-	/* settings for TS interface */
-	if (state->cfg.ts_mode == AF9033_TS_MODE_USB) {
-		ret = af9033_wr_reg_mask(state, 0x80f9a5, 0x00, 0x01);
-		if (ret < 0)
-			goto err;
-
-		ret = af9033_wr_reg_mask(state, 0x80f9b5, 0x01, 0x01);
-		if (ret < 0)
-			goto err;
-	} else {
-		ret = af9033_wr_reg_mask(state, 0x80f990, 0x00, 0x01);
-		if (ret < 0)
-			goto err;
-
-		ret = af9033_wr_reg_mask(state, 0x80f9b5, 0x00, 0x01);
-		if (ret < 0)
-			goto err;
-	}
-
-	/* load OFSM settings */
-	pr_debug("%s: load ofsm settings\n", __func__);
-	len = ARRAY_SIZE(ofsm_init);
-	init = ofsm_init;
-	for (i = 0; i < len; i++) {
-		ret = af9033_wr_reg(state, init[i].reg, init[i].val);
-		if (ret < 0)
-			goto err;
-	}
-
-	/* load tuner specific settings */
-	pr_debug("%s: load tuner specific settings\n",
-			__func__);
-	switch (state->cfg.tuner) {
-	case AF9033_TUNER_TUA9001:
-		len = ARRAY_SIZE(tuner_init_tua9001);
-		init = tuner_init_tua9001;
-		break;
-	case AF9033_TUNER_FC0011:
-		len = ARRAY_SIZE(tuner_init_fc0011);
-		init = tuner_init_fc0011;
-		break;
-	case AF9033_TUNER_MXL5007T:
-		len = ARRAY_SIZE(tuner_init_mxl5007t);
-		init = tuner_init_mxl5007t;
-		break;
-	case AF9033_TUNER_TDA18218:
-		len = ARRAY_SIZE(tuner_init_tda18218);
-		init = tuner_init_tda18218;
-		break;
-	default:
-		pr_debug("%s: unsupported tuner ID=%d\n", __func__,
-				state->cfg.tuner);
-		ret = -ENODEV;
-		goto err;
-	}
-
-	for (i = 0; i < len; i++) {
-		ret = af9033_wr_reg(state, init[i].reg, init[i].val);
-		if (ret < 0)
-			goto err;
-	}
-
-	state->bandwidth_hz = 0; /* force to program all parameters */
-
-	return 0;
-
-err:
-	pr_debug("%s: failed=%d\n", __func__, ret);
-
-	return ret;
-}
-
-static int af9033_sleep(struct dvb_frontend *fe)
-{
-	struct af9033_state *state = fe->demodulator_priv;
-	int ret, i;
-	u8 tmp;
-
-	ret = af9033_wr_reg(state, 0x80004c, 1);
-	if (ret < 0)
-		goto err;
-
-	ret = af9033_wr_reg(state, 0x800000, 0);
-	if (ret < 0)
-		goto err;
-
-	for (i = 100, tmp = 1; i && tmp; i--) {
-		ret = af9033_rd_reg(state, 0x80004c, &tmp);
-		if (ret < 0)
-			goto err;
-
-		usleep_range(200, 10000);
-	}
-
-	pr_debug("%s: loop=%d\n", __func__, i);
-
-	if (i == 0) {
-		ret = -ETIMEDOUT;
-		goto err;
-	}
-
-	ret = af9033_wr_reg_mask(state, 0x80fb24, 0x08, 0x08);
-	if (ret < 0)
-		goto err;
-
-	/* prevent current leak (?) */
-	if (state->cfg.ts_mode == AF9033_TS_MODE_SERIAL) {
-		/* enable parallel TS */
-		ret = af9033_wr_reg_mask(state, 0x00d917, 0x00, 0x01);
-		if (ret < 0)
-			goto err;
-
-		ret = af9033_wr_reg_mask(state, 0x00d916, 0x01, 0x01);
-		if (ret < 0)
-			goto err;
-	}
-
-	return 0;
-
-err:
-	pr_debug("%s: failed=%d\n", __func__, ret);
-
-	return ret;
-}
-
-static int af9033_get_tune_settings(struct dvb_frontend *fe,
-		struct dvb_frontend_tune_settings *fesettings)
-{
-	fesettings->min_delay_ms = 800;
-	fesettings->step_size = 0;
-	fesettings->max_drift = 0;
-
-	return 0;
-}
-
-static int af9033_set_frontend(struct dvb_frontend *fe)
-{
-	struct af9033_state *state = fe->demodulator_priv;
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	int ret, i, spec_inv;
-	u8 tmp, buf[3], bandwidth_reg_val;
-	u32 if_frequency, freq_cw, adc_freq;
-
-	pr_debug("%s: frequency=%d bandwidth_hz=%d\n", __func__, c->frequency,
-			c->bandwidth_hz);
-
-	/* check bandwidth */
-	switch (c->bandwidth_hz) {
-	case 6000000:
-		bandwidth_reg_val = 0x00;
-		break;
-	case 7000000:
-		bandwidth_reg_val = 0x01;
-		break;
-	case 8000000:
-		bandwidth_reg_val = 0x02;
-		break;
-	default:
-		pr_debug("%s: invalid bandwidth_hz\n", __func__);
-		ret = -EINVAL;
-		goto err;
-	}
-
-	/* program tuner */
-	if (fe->ops.tuner_ops.set_params)
-		fe->ops.tuner_ops.set_params(fe);
-
-	/* program CFOE coefficients */
-	if (c->bandwidth_hz != state->bandwidth_hz) {
-		for (i = 0; i < ARRAY_SIZE(coeff_lut); i++) {
-			if (coeff_lut[i].clock == state->cfg.clock &&
-				coeff_lut[i].bandwidth_hz == c->bandwidth_hz) {
-				break;
-			}
-		}
-		ret =  af9033_wr_regs(state, 0x800001,
-				coeff_lut[i].val, sizeof(coeff_lut[i].val));
-	}
-
-	/* program frequency control */
-	if (c->bandwidth_hz != state->bandwidth_hz) {
-		spec_inv = state->cfg.spec_inv ? -1 : 1;
-
-		for (i = 0; i < ARRAY_SIZE(clock_adc_lut); i++) {
-			if (clock_adc_lut[i].clock == state->cfg.clock)
-				break;
-		}
-		adc_freq = clock_adc_lut[i].adc;
-
-		/* get used IF frequency */
-		if (fe->ops.tuner_ops.get_if_frequency)
-			fe->ops.tuner_ops.get_if_frequency(fe, &if_frequency);
-		else
-			if_frequency = 0;
-
-		while (if_frequency > (adc_freq / 2))
-			if_frequency -= adc_freq;
-
-		if (if_frequency >= 0)
-			spec_inv *= -1;
-		else
-			if_frequency *= -1;
-
-		freq_cw = af9033_div(if_frequency, adc_freq, 23ul);
-
-		if (spec_inv == -1)
-			freq_cw *= -1;
-
-		/* get adc multiplies */
-		ret = af9033_rd_reg(state, 0x800045, &tmp);
-		if (ret < 0)
-			goto err;
-
-		if (tmp == 1)
-			freq_cw /= 2;
-
-		buf[0] = (freq_cw >>  0) & 0xff;
-		buf[1] = (freq_cw >>  8) & 0xff;
-		buf[2] = (freq_cw >> 16) & 0x7f;
-		ret = af9033_wr_regs(state, 0x800029, buf, 3);
-		if (ret < 0)
-			goto err;
-
-		state->bandwidth_hz = c->bandwidth_hz;
-	}
-
-	ret = af9033_wr_reg_mask(state, 0x80f904, bandwidth_reg_val, 0x03);
-	if (ret < 0)
-		goto err;
-
-	ret = af9033_wr_reg(state, 0x800040, 0x00);
-	if (ret < 0)
-		goto err;
-
-	ret = af9033_wr_reg(state, 0x800047, 0x00);
-	if (ret < 0)
-		goto err;
-
-	ret = af9033_wr_reg_mask(state, 0x80f999, 0x00, 0x01);
-	if (ret < 0)
-		goto err;
-
-	if (c->frequency <= 230000000)
-		tmp = 0x00; /* VHF */
-	else
-		tmp = 0x01; /* UHF */
-
-	ret = af9033_wr_reg(state, 0x80004b, tmp);
-	if (ret < 0)
-		goto err;
-
-	ret = af9033_wr_reg(state, 0x800000, 0x00);
-	if (ret < 0)
-		goto err;
-
-	return 0;
-
-err:
-	pr_debug("%s: failed=%d\n", __func__, ret);
-
-	return ret;
-}
-
-static int af9033_get_frontend(struct dvb_frontend *fe)
-{
-	struct af9033_state *state = fe->demodulator_priv;
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	int ret;
-	u8 buf[8];
-
-	pr_debug("%s\n", __func__);
-
-	/* read all needed registers */
-	ret = af9033_rd_regs(state, 0x80f900, buf, sizeof(buf));
-	if (ret < 0)
-		goto err;
-
-	switch ((buf[0] >> 0) & 3) {
-	case 0:
-		c->transmission_mode = TRANSMISSION_MODE_2K;
-		break;
-	case 1:
-		c->transmission_mode = TRANSMISSION_MODE_8K;
-		break;
-	}
-
-	switch ((buf[1] >> 0) & 3) {
-	case 0:
-		c->guard_interval = GUARD_INTERVAL_1_32;
-		break;
-	case 1:
-		c->guard_interval = GUARD_INTERVAL_1_16;
-		break;
-	case 2:
-		c->guard_interval = GUARD_INTERVAL_1_8;
-		break;
-	case 3:
-		c->guard_interval = GUARD_INTERVAL_1_4;
-		break;
-	}
-
-	switch ((buf[2] >> 0) & 7) {
-	case 0:
-		c->hierarchy = HIERARCHY_NONE;
-		break;
-	case 1:
-		c->hierarchy = HIERARCHY_1;
-		break;
-	case 2:
-		c->hierarchy = HIERARCHY_2;
-		break;
-	case 3:
-		c->hierarchy = HIERARCHY_4;
-		break;
-	}
-
-	switch ((buf[3] >> 0) & 3) {
-	case 0:
-		c->modulation = QPSK;
-		break;
-	case 1:
-		c->modulation = QAM_16;
-		break;
-	case 2:
-		c->modulation = QAM_64;
-		break;
-	}
-
-	switch ((buf[4] >> 0) & 3) {
-	case 0:
-		c->bandwidth_hz = 6000000;
-		break;
-	case 1:
-		c->bandwidth_hz = 7000000;
-		break;
-	case 2:
-		c->bandwidth_hz = 8000000;
-		break;
-	}
-
-	switch ((buf[6] >> 0) & 7) {
-	case 0:
-		c->code_rate_HP = FEC_1_2;
-		break;
-	case 1:
-		c->code_rate_HP = FEC_2_3;
-		break;
-	case 2:
-		c->code_rate_HP = FEC_3_4;
-		break;
-	case 3:
-		c->code_rate_HP = FEC_5_6;
-		break;
-	case 4:
-		c->code_rate_HP = FEC_7_8;
-		break;
-	case 5:
-		c->code_rate_HP = FEC_NONE;
-		break;
-	}
-
-	switch ((buf[7] >> 0) & 7) {
-	case 0:
-		c->code_rate_LP = FEC_1_2;
-		break;
-	case 1:
-		c->code_rate_LP = FEC_2_3;
-		break;
-	case 2:
-		c->code_rate_LP = FEC_3_4;
-		break;
-	case 3:
-		c->code_rate_LP = FEC_5_6;
-		break;
-	case 4:
-		c->code_rate_LP = FEC_7_8;
-		break;
-	case 5:
-		c->code_rate_LP = FEC_NONE;
-		break;
-	}
-
-	return 0;
-
-err:
-	pr_debug("%s: failed=%d\n", __func__, ret);
-
-	return ret;
-}
-
-static int af9033_read_status(struct dvb_frontend *fe, fe_status_t *status)
-{
-	struct af9033_state *state = fe->demodulator_priv;
-	int ret;
-	u8 tmp;
-
-	*status = 0;
-
-	/* radio channel status, 0=no result, 1=has signal, 2=no signal */
-	ret = af9033_rd_reg(state, 0x800047, &tmp);
-	if (ret < 0)
-		goto err;
-
-	/* has signal */
-	if (tmp == 0x01)
-		*status |= FE_HAS_SIGNAL;
-
-	if (tmp != 0x02) {
-		/* TPS lock */
-		ret = af9033_rd_reg_mask(state, 0x80f5a9, &tmp, 0x01);
-		if (ret < 0)
-			goto err;
-
-		if (tmp)
-			*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
-					FE_HAS_VITERBI;
-
-		/* full lock */
-		ret = af9033_rd_reg_mask(state, 0x80f999, &tmp, 0x01);
-		if (ret < 0)
-			goto err;
-
-		if (tmp)
-			*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
-					FE_HAS_VITERBI | FE_HAS_SYNC |
-					FE_HAS_LOCK;
-	}
-
-	return 0;
-
-err:
-	pr_debug("%s: failed=%d\n", __func__, ret);
-
-	return ret;
-}
-
-static int af9033_read_snr(struct dvb_frontend *fe, u16 *snr)
-{
-	struct af9033_state *state = fe->demodulator_priv;
-	int ret, i, len;
-	u8 buf[3], tmp;
-	u32 snr_val;
-	const struct val_snr *uninitialized_var(snr_lut);
-
-	/* read value */
-	ret = af9033_rd_regs(state, 0x80002c, buf, 3);
-	if (ret < 0)
-		goto err;
-
-	snr_val = (buf[2] << 16) | (buf[1] << 8) | buf[0];
-
-	/* read current modulation */
-	ret = af9033_rd_reg(state, 0x80f903, &tmp);
-	if (ret < 0)
-		goto err;
-
-	switch ((tmp >> 0) & 3) {
-	case 0:
-		len = ARRAY_SIZE(qpsk_snr_lut);
-		snr_lut = qpsk_snr_lut;
-		break;
-	case 1:
-		len = ARRAY_SIZE(qam16_snr_lut);
-		snr_lut = qam16_snr_lut;
-		break;
-	case 2:
-		len = ARRAY_SIZE(qam64_snr_lut);
-		snr_lut = qam64_snr_lut;
-		break;
-	default:
-		goto err;
-	}
-
-	for (i = 0; i < len; i++) {
-		tmp = snr_lut[i].snr;
-
-		if (snr_val < snr_lut[i].val)
-			break;
-	}
-
-	*snr = tmp * 10; /* dB/10 */
-
-	return 0;
-
-err:
-	pr_debug("%s: failed=%d\n", __func__, ret);
-
-	return ret;
-}
-
-static int af9033_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
-{
-	struct af9033_state *state = fe->demodulator_priv;
-	int ret;
-	u8 strength2;
-
-	/* read signal strength of 0-100 scale */
-	ret = af9033_rd_reg(state, 0x800048, &strength2);
-	if (ret < 0)
-		goto err;
-
-	/* scale value to 0x0000-0xffff */
-	*strength = strength2 * 0xffff / 100;
-
-	return 0;
-
-err:
-	pr_debug("%s: failed=%d\n", __func__, ret);
-
-	return ret;
-}
-
-static int af9033_update_ch_stat(struct af9033_state *state)
-{
-	int ret = 0;
-	u32 err_cnt, bit_cnt;
-	u16 abort_cnt;
-	u8 buf[7];
-
-	/* only update data every half second */
-	if (time_after(jiffies, state->last_stat_check + msecs_to_jiffies(500))) {
-		ret = af9033_rd_regs(state, 0x800032, buf, sizeof(buf));
-		if (ret < 0)
-			goto err;
-		/* in 8 byte packets? */
-		abort_cnt = (buf[1] << 8) + buf[0];
-		/* in bits */
-		err_cnt = (buf[4] << 16) + (buf[3] << 8) + buf[2];
-		/* in 8 byte packets? always(?) 0x2710 = 10000 */
-		bit_cnt = (buf[6] << 8) + buf[5];
-
-		if (bit_cnt < abort_cnt) {
-			abort_cnt = 1000;
-			state->ber = 0xffffffff;
-		} else {
-			/* 8 byte packets, that have not been rejected already */
-			bit_cnt -= (u32)abort_cnt;
-			if (bit_cnt == 0) {
-				state->ber = 0xffffffff;
-			} else {
-				err_cnt -= (u32)abort_cnt * 8 * 8;
-				bit_cnt *= 8 * 8;
-				state->ber = err_cnt * (0xffffffff / bit_cnt);
-			}
-		}
-		state->ucb += abort_cnt;
-		state->last_stat_check = jiffies;
-	}
-
-	return 0;
-err:
-	pr_debug("%s: failed=%d\n", __func__, ret);
-	return ret;
-}
-
-static int af9033_read_ber(struct dvb_frontend *fe, u32 *ber)
-{
-	struct af9033_state *state = fe->demodulator_priv;
-	int ret;
-
-	ret = af9033_update_ch_stat(state);
-	if (ret < 0)
-		return ret;
-
-	*ber = state->ber;
-
-	return 0;
-}
-
-static int af9033_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
-{
-	struct af9033_state *state = fe->demodulator_priv;
-	int ret;
-
-	ret = af9033_update_ch_stat(state);
-	if (ret < 0)
-		return ret;
-
-	*ucblocks = state->ucb;
-
-	return 0;
-}
-
-static int af9033_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
-{
-	struct af9033_state *state = fe->demodulator_priv;
-	int ret;
-
-	pr_debug("%s: enable=%d\n", __func__, enable);
-
-	ret = af9033_wr_reg_mask(state, 0x00fa04, enable, 0x01);
-	if (ret < 0)
-		goto err;
-
-	return 0;
-
-err:
-	pr_debug("%s: failed=%d\n", __func__, ret);
-
-	return ret;
-}
-
-static struct dvb_frontend_ops af9033_ops;
-
-struct dvb_frontend *af9033_attach(const struct af9033_config *config,
-		struct i2c_adapter *i2c)
-{
-	int ret;
-	struct af9033_state *state;
-	u8 buf[8];
-
-	pr_debug("%s:\n", __func__);
-
-	/* allocate memory for the internal state */
-	state = kzalloc(sizeof(struct af9033_state), GFP_KERNEL);
-	if (state == NULL)
-		goto err;
-
-	/* setup the state */
-	state->i2c = i2c;
-	memcpy(&state->cfg, config, sizeof(struct af9033_config));
-
-	if (state->cfg.clock != 12000000) {
-		printk(KERN_INFO "af9033: unsupported clock=%d, only " \
-				"12000000 Hz is supported currently\n",
-				state->cfg.clock);
-		goto err;
-	}
-
-	/* firmware version */
-	ret = af9033_rd_regs(state, 0x0083e9, &buf[0], 4);
-	if (ret < 0)
-		goto err;
-
-	ret = af9033_rd_regs(state, 0x804191, &buf[4], 4);
-	if (ret < 0)
-		goto err;
-
-	printk(KERN_INFO "af9033: firmware version: LINK=%d.%d.%d.%d " \
-			"OFDM=%d.%d.%d.%d\n", buf[0], buf[1], buf[2], buf[3],
-			buf[4], buf[5], buf[6], buf[7]);
-
-	/* configure internal TS mode */
-	switch (state->cfg.ts_mode) {
-	case AF9033_TS_MODE_PARALLEL:
-		state->ts_mode_parallel = true;
-		break;
-	case AF9033_TS_MODE_SERIAL:
-		state->ts_mode_serial = true;
-		break;
-	case AF9033_TS_MODE_USB:
-		/* usb mode for AF9035 */
-	default:
-		break;
-	}
-
-	/* create dvb_frontend */
-	memcpy(&state->fe.ops, &af9033_ops, sizeof(struct dvb_frontend_ops));
-	state->fe.demodulator_priv = state;
-
-	return &state->fe;
-
-err:
-	kfree(state);
-	return NULL;
-}
-EXPORT_SYMBOL(af9033_attach);
-
-static struct dvb_frontend_ops af9033_ops = {
-	.delsys = { SYS_DVBT },
-	.info = {
-		.name = "Afatech AF9033 (DVB-T)",
-		.frequency_min = 174000000,
-		.frequency_max = 862000000,
-		.frequency_stepsize = 250000,
-		.frequency_tolerance = 0,
-		.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_FEC_AUTO |
-			FE_CAN_QPSK |
-			FE_CAN_QAM_16 |
-			FE_CAN_QAM_64 |
-			FE_CAN_QAM_AUTO |
-			FE_CAN_TRANSMISSION_MODE_AUTO |
-			FE_CAN_GUARD_INTERVAL_AUTO |
-			FE_CAN_HIERARCHY_AUTO |
-			FE_CAN_RECOVER |
-			FE_CAN_MUTE_TS
-	},
-
-	.release = af9033_release,
-
-	.init = af9033_init,
-	.sleep = af9033_sleep,
-
-	.get_tune_settings = af9033_get_tune_settings,
-	.set_frontend = af9033_set_frontend,
-	.get_frontend = af9033_get_frontend,
-
-	.read_status = af9033_read_status,
-	.read_snr = af9033_read_snr,
-	.read_signal_strength = af9033_read_signal_strength,
-	.read_ber = af9033_read_ber,
-	.read_ucblocks = af9033_read_ucblocks,
-
-	.i2c_gate_ctrl = af9033_i2c_gate_ctrl,
-};
-
-MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
-MODULE_DESCRIPTION("Afatech AF9033 DVB-T demodulator driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/af9033.h b/drivers/media/dvb/frontends/af9033.h
deleted file mode 100644
index 9e302c3..0000000
--- a/drivers/media/dvb/frontends/af9033.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Afatech AF9033 demodulator driver
- *
- * Copyright (C) 2009 Antti Palosaari <crope@iki.fi>
- * Copyright (C) 2012 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.,
- *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef AF9033_H
-#define AF9033_H
-
-struct af9033_config {
-	/*
-	 * I2C address
-	 */
-	u8 i2c_addr;
-
-	/*
-	 * clock Hz
-	 * 12000000, 22000000, 24000000, 34000000, 32000000, 28000000, 26000000,
-	 * 30000000, 36000000, 20480000, 16384000
-	 */
-	u32 clock;
-
-	/*
-	 * tuner
-	 */
-#define AF9033_TUNER_TUA9001     0x27 /* Infineon TUA 9001 */
-#define AF9033_TUNER_FC0011      0x28 /* Fitipower FC0011 */
-#define AF9033_TUNER_MXL5007T    0xa0 /* MaxLinear MxL5007T */
-#define AF9033_TUNER_TDA18218    0xa1 /* NXP TDA 18218HN */
-	u8 tuner;
-
-	/*
-	 * TS settings
-	 */
-#define AF9033_TS_MODE_USB       0
-#define AF9033_TS_MODE_PARALLEL  1
-#define AF9033_TS_MODE_SERIAL    2
-	u8 ts_mode:2;
-
-	/*
-	 * input spectrum inversion
-	 */
-	bool spec_inv;
-};
-
-
-#if defined(CONFIG_DVB_AF9033) || \
-	(defined(CONFIG_DVB_AF9033_MODULE) && defined(MODULE))
-extern struct dvb_frontend *af9033_attach(const struct af9033_config *config,
-	struct i2c_adapter *i2c);
-#else
-static inline struct dvb_frontend *af9033_attach(
-	const struct af9033_config *config, struct i2c_adapter *i2c)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif
-
-#endif /* AF9033_H */
diff --git a/drivers/media/dvb/frontends/af9033_priv.h b/drivers/media/dvb/frontends/af9033_priv.h
deleted file mode 100644
index 0b783b9..0000000
--- a/drivers/media/dvb/frontends/af9033_priv.h
+++ /dev/null
@@ -1,470 +0,0 @@
-/*
- * Afatech AF9033 demodulator driver
- *
- * Copyright (C) 2009 Antti Palosaari <crope@iki.fi>
- * Copyright (C) 2012 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.,
- *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef AF9033_PRIV_H
-#define AF9033_PRIV_H
-
-#include "dvb_frontend.h"
-#include "af9033.h"
-
-struct reg_val {
-	u32 reg;
-	u8  val;
-};
-
-struct reg_val_mask {
-	u32 reg;
-	u8  val;
-	u8  mask;
-};
-
-struct coeff {
-	u32 clock;
-	u32 bandwidth_hz;
-	u8 val[36];
-};
-
-struct clock_adc {
-	u32 clock;
-	u32 adc;
-};
-
-struct val_snr {
-	u32 val;
-	u8 snr;
-};
-
-/* Xtal clock vs. ADC clock lookup table */
-static const struct clock_adc clock_adc_lut[] = {
-	{ 16384000, 20480000 },
-	{ 20480000, 20480000 },
-	{ 36000000, 20250000 },
-	{ 30000000, 20156250 },
-	{ 26000000, 20583333 },
-	{ 28000000, 20416667 },
-	{ 32000000, 20500000 },
-	{ 34000000, 20187500 },
-	{ 24000000, 20500000 },
-	{ 22000000, 20625000 },
-	{ 12000000, 20250000 },
-};
-
-/* pre-calculated coeff lookup table */
-static const struct coeff coeff_lut[] = {
-	/* 12.000 MHz */
-	{ 12000000, 8000000, {
-		0x01, 0xce, 0x55, 0xc9, 0x00, 0xe7, 0x2a, 0xe4, 0x00, 0x73,
-		0x99, 0x0f, 0x00, 0x73, 0x95, 0x72, 0x00, 0x73, 0x91, 0xd5,
-		0x00, 0x39, 0xca, 0xb9, 0x00, 0xe7, 0x2a, 0xe4, 0x00, 0x73,
-		0x95, 0x72, 0x37, 0x02, 0xce, 0x01 }
-	},
-	{ 12000000, 7000000, {
-		0x01, 0x94, 0x8b, 0x10, 0x00, 0xca, 0x45, 0x88, 0x00, 0x65,
-		0x25, 0xed, 0x00, 0x65, 0x22, 0xc4, 0x00, 0x65, 0x1f, 0x9b,
-		0x00, 0x32, 0x91, 0x62, 0x00, 0xca, 0x45, 0x88, 0x00, 0x65,
-		0x22, 0xc4, 0x88, 0x02, 0x95, 0x01 }
-	},
-	{ 12000000, 6000000, {
-		0x01, 0x5a, 0xc0, 0x56, 0x00, 0xad, 0x60, 0x2b, 0x00, 0x56,
-		0xb2, 0xcb, 0x00, 0x56, 0xb0, 0x15, 0x00, 0x56, 0xad, 0x60,
-		0x00, 0x2b, 0x58, 0x0b, 0x00, 0xad, 0x60, 0x2b, 0x00, 0x56,
-		0xb0, 0x15, 0xf4, 0x02, 0x5b, 0x01 }
-	},
-};
-
-/* QPSK SNR lookup table */
-static const struct val_snr qpsk_snr_lut[] = {
-	{ 0x0b4771,  0 },
-	{ 0x0c1aed,  1 },
-	{ 0x0d0d27,  2 },
-	{ 0x0e4d19,  3 },
-	{ 0x0e5da8,  4 },
-	{ 0x107097,  5 },
-	{ 0x116975,  6 },
-	{ 0x1252d9,  7 },
-	{ 0x131fa4,  8 },
-	{ 0x13d5e1,  9 },
-	{ 0x148e53, 10 },
-	{ 0x15358b, 11 },
-	{ 0x15dd29, 12 },
-	{ 0x168112, 13 },
-	{ 0x170b61, 14 },
-	{ 0x17a532, 15 },
-	{ 0x180f94, 16 },
-	{ 0x186ed2, 17 },
-	{ 0x18b271, 18 },
-	{ 0x18e118, 19 },
-	{ 0x18ff4b, 20 },
-	{ 0x190af1, 21 },
-	{ 0x191451, 22 },
-	{ 0xffffff, 23 },
-};
-
-/* QAM16 SNR lookup table */
-static const struct val_snr qam16_snr_lut[] = {
-	{ 0x04f0d5,  0 },
-	{ 0x05387a,  1 },
-	{ 0x0573a4,  2 },
-	{ 0x05a99e,  3 },
-	{ 0x05cc80,  4 },
-	{ 0x05eb62,  5 },
-	{ 0x05fecf,  6 },
-	{ 0x060b80,  7 },
-	{ 0x062501,  8 },
-	{ 0x064865,  9 },
-	{ 0x069604, 10 },
-	{ 0x06f356, 11 },
-	{ 0x07706a, 12 },
-	{ 0x0804d3, 13 },
-	{ 0x089d1a, 14 },
-	{ 0x093e3d, 15 },
-	{ 0x09e35d, 16 },
-	{ 0x0a7c3c, 17 },
-	{ 0x0afaf8, 18 },
-	{ 0x0b719d, 19 },
-	{ 0x0bda6a, 20 },
-	{ 0x0c0c75, 21 },
-	{ 0x0c3f7d, 22 },
-	{ 0x0c5e62, 23 },
-	{ 0x0c6c31, 24 },
-	{ 0x0c7925, 25 },
-	{ 0xffffff, 26 },
-};
-
-/* QAM64 SNR lookup table */
-static const struct val_snr qam64_snr_lut[] = {
-	{ 0x0256d0,  0 },
-	{ 0x027a65,  1 },
-	{ 0x029873,  2 },
-	{ 0x02b7fe,  3 },
-	{ 0x02cf1e,  4 },
-	{ 0x02e234,  5 },
-	{ 0x02f409,  6 },
-	{ 0x030046,  7 },
-	{ 0x030844,  8 },
-	{ 0x030a02,  9 },
-	{ 0x030cde, 10 },
-	{ 0x031031, 11 },
-	{ 0x03144c, 12 },
-	{ 0x0315dd, 13 },
-	{ 0x031920, 14 },
-	{ 0x0322d0, 15 },
-	{ 0x0339fc, 16 },
-	{ 0x0364a1, 17 },
-	{ 0x038bcc, 18 },
-	{ 0x03c7d3, 19 },
-	{ 0x0408cc, 20 },
-	{ 0x043bed, 21 },
-	{ 0x048061, 22 },
-	{ 0x04be95, 23 },
-	{ 0x04fa7d, 24 },
-	{ 0x052405, 25 },
-	{ 0x05570d, 26 },
-	{ 0x059feb, 27 },
-	{ 0x05bf38, 28 },
-	{ 0xffffff, 29 },
-};
-
-static const struct reg_val ofsm_init[] = {
-	{ 0x800051, 0x01 },
-	{ 0x800070, 0x0a },
-	{ 0x80007e, 0x04 },
-	{ 0x800081, 0x0a },
-	{ 0x80008a, 0x01 },
-	{ 0x80008e, 0x01 },
-	{ 0x800092, 0x06 },
-	{ 0x800099, 0x01 },
-	{ 0x80009f, 0xe1 },
-	{ 0x8000a0, 0xcf },
-	{ 0x8000a3, 0x01 },
-	{ 0x8000a5, 0x01 },
-	{ 0x8000a6, 0x01 },
-	{ 0x8000a9, 0x00 },
-	{ 0x8000aa, 0x01 },
-	{ 0x8000ab, 0x01 },
-	{ 0x8000b0, 0x01 },
-	{ 0x8000c0, 0x05 },
-	{ 0x8000c4, 0x19 },
-	{ 0x80f000, 0x0f },
-	{ 0x80f016, 0x10 },
-	{ 0x80f017, 0x04 },
-	{ 0x80f018, 0x05 },
-	{ 0x80f019, 0x04 },
-	{ 0x80f01a, 0x05 },
-	{ 0x80f021, 0x03 },
-	{ 0x80f022, 0x0a },
-	{ 0x80f023, 0x0a },
-	{ 0x80f02b, 0x00 },
-	{ 0x80f02c, 0x01 },
-	{ 0x80f064, 0x03 },
-	{ 0x80f065, 0xf9 },
-	{ 0x80f066, 0x03 },
-	{ 0x80f067, 0x01 },
-	{ 0x80f06f, 0xe0 },
-	{ 0x80f070, 0x03 },
-	{ 0x80f072, 0x0f },
-	{ 0x80f073, 0x03 },
-	{ 0x80f078, 0x00 },
-	{ 0x80f087, 0x00 },
-	{ 0x80f09b, 0x3f },
-	{ 0x80f09c, 0x00 },
-	{ 0x80f09d, 0x20 },
-	{ 0x80f09e, 0x00 },
-	{ 0x80f09f, 0x0c },
-	{ 0x80f0a0, 0x00 },
-	{ 0x80f130, 0x04 },
-	{ 0x80f132, 0x04 },
-	{ 0x80f144, 0x1a },
-	{ 0x80f146, 0x00 },
-	{ 0x80f14a, 0x01 },
-	{ 0x80f14c, 0x00 },
-	{ 0x80f14d, 0x00 },
-	{ 0x80f14f, 0x04 },
-	{ 0x80f158, 0x7f },
-	{ 0x80f15a, 0x00 },
-	{ 0x80f15b, 0x08 },
-	{ 0x80f15d, 0x03 },
-	{ 0x80f15e, 0x05 },
-	{ 0x80f163, 0x05 },
-	{ 0x80f166, 0x01 },
-	{ 0x80f167, 0x40 },
-	{ 0x80f168, 0x0f },
-	{ 0x80f17a, 0x00 },
-	{ 0x80f17b, 0x00 },
-	{ 0x80f183, 0x01 },
-	{ 0x80f19d, 0x40 },
-	{ 0x80f1bc, 0x36 },
-	{ 0x80f1bd, 0x00 },
-	{ 0x80f1cb, 0xa0 },
-	{ 0x80f1cc, 0x01 },
-	{ 0x80f204, 0x10 },
-	{ 0x80f214, 0x00 },
-	{ 0x80f40e, 0x0a },
-	{ 0x80f40f, 0x40 },
-	{ 0x80f410, 0x08 },
-	{ 0x80f55f, 0x0a },
-	{ 0x80f561, 0x15 },
-	{ 0x80f562, 0x20 },
-	{ 0x80f5df, 0xfb },
-	{ 0x80f5e0, 0x00 },
-	{ 0x80f5e3, 0x09 },
-	{ 0x80f5e4, 0x01 },
-	{ 0x80f5e5, 0x01 },
-	{ 0x80f5f8, 0x01 },
-	{ 0x80f5fd, 0x01 },
-	{ 0x80f600, 0x05 },
-	{ 0x80f601, 0x08 },
-	{ 0x80f602, 0x0b },
-	{ 0x80f603, 0x0e },
-	{ 0x80f604, 0x11 },
-	{ 0x80f605, 0x14 },
-	{ 0x80f606, 0x17 },
-	{ 0x80f607, 0x1f },
-	{ 0x80f60e, 0x00 },
-	{ 0x80f60f, 0x04 },
-	{ 0x80f610, 0x32 },
-	{ 0x80f611, 0x10 },
-	{ 0x80f707, 0xfc },
-	{ 0x80f708, 0x00 },
-	{ 0x80f709, 0x37 },
-	{ 0x80f70a, 0x00 },
-	{ 0x80f78b, 0x01 },
-	{ 0x80f80f, 0x40 },
-	{ 0x80f810, 0x54 },
-	{ 0x80f811, 0x5a },
-	{ 0x80f905, 0x01 },
-	{ 0x80fb06, 0x03 },
-	{ 0x80fd8b, 0x00 },
-};
-
-/* Infineon TUA 9001 tuner init
-   AF9033_TUNER_TUA9001    = 0x27 */
-static const struct reg_val tuner_init_tua9001[] = {
-	{ 0x800046, 0x27 },
-	{ 0x800057, 0x00 },
-	{ 0x800058, 0x01 },
-	{ 0x80005f, 0x00 },
-	{ 0x800060, 0x00 },
-	{ 0x80006d, 0x00 },
-	{ 0x800071, 0x05 },
-	{ 0x800072, 0x02 },
-	{ 0x800074, 0x01 },
-	{ 0x800075, 0x03 },
-	{ 0x800076, 0x02 },
-	{ 0x800077, 0x00 },
-	{ 0x800078, 0x01 },
-	{ 0x800079, 0x00 },
-	{ 0x80007a, 0x7e },
-	{ 0x80007b, 0x3e },
-	{ 0x800093, 0x00 },
-	{ 0x800094, 0x01 },
-	{ 0x800095, 0x02 },
-	{ 0x800096, 0x01 },
-	{ 0x800098, 0x0a },
-	{ 0x80009b, 0x05 },
-	{ 0x80009c, 0x80 },
-	{ 0x8000b3, 0x00 },
-	{ 0x8000c1, 0x01 },
-	{ 0x8000c2, 0x00 },
-	{ 0x80f007, 0x00 },
-	{ 0x80f01f, 0x82 },
-	{ 0x80f020, 0x00 },
-	{ 0x80f029, 0x82 },
-	{ 0x80f02a, 0x00 },
-	{ 0x80f047, 0x00 },
-	{ 0x80f054, 0x00 },
-	{ 0x80f055, 0x00 },
-	{ 0x80f077, 0x01 },
-	{ 0x80f1e6, 0x00 },
-};
-
-/* Fitipower fc0011 tuner init
-   AF9033_TUNER_FC0011    = 0x28 */
-static const struct reg_val tuner_init_fc0011[] = {
-	{ 0x800046, AF9033_TUNER_FC0011 },
-	{ 0x800057, 0x00 },
-	{ 0x800058, 0x01 },
-	{ 0x80005f, 0x00 },
-	{ 0x800060, 0x00 },
-	{ 0x800068, 0xa5 },
-	{ 0x80006e, 0x01 },
-	{ 0x800071, 0x0A },
-	{ 0x800072, 0x02 },
-	{ 0x800074, 0x01 },
-	{ 0x800079, 0x01 },
-	{ 0x800093, 0x00 },
-	{ 0x800094, 0x00 },
-	{ 0x800095, 0x00 },
-	{ 0x800096, 0x00 },
-	{ 0x80009b, 0x2D },
-	{ 0x80009c, 0x60 },
-	{ 0x80009d, 0x23 },
-	{ 0x8000a4, 0x50 },
-	{ 0x8000ad, 0x50 },
-	{ 0x8000b3, 0x01 },
-	{ 0x8000b7, 0x88 },
-	{ 0x8000b8, 0xa6 },
-	{ 0x8000c3, 0x01 },
-	{ 0x8000c4, 0x01 },
-	{ 0x8000c7, 0x69 },
-	{ 0x80F007, 0x00 },
-	{ 0x80F00A, 0x1B },
-	{ 0x80F00B, 0x1B },
-	{ 0x80F00C, 0x1B },
-	{ 0x80F00D, 0x1B },
-	{ 0x80F00E, 0xFF },
-	{ 0x80F00F, 0x01 },
-	{ 0x80F010, 0x00 },
-	{ 0x80F011, 0x02 },
-	{ 0x80F012, 0xFF },
-	{ 0x80F013, 0x01 },
-	{ 0x80F014, 0x00 },
-	{ 0x80F015, 0x02 },
-	{ 0x80F01B, 0xEF },
-	{ 0x80F01C, 0x01 },
-	{ 0x80F01D, 0x0f },
-	{ 0x80F01E, 0x02 },
-	{ 0x80F01F, 0x6E },
-	{ 0x80F020, 0x00 },
-	{ 0x80F025, 0xDE },
-	{ 0x80F026, 0x00 },
-	{ 0x80F027, 0x0A },
-	{ 0x80F028, 0x03 },
-	{ 0x80F029, 0x6E },
-	{ 0x80F02A, 0x00 },
-	{ 0x80F047, 0x00 },
-	{ 0x80F054, 0x00 },
-	{ 0x80F055, 0x00 },
-	{ 0x80F077, 0x01 },
-	{ 0x80F1E6, 0x00 },
-};
-
-/* MaxLinear MxL5007T tuner init
-   AF9033_TUNER_MXL5007T    = 0xa0 */
-static const struct reg_val tuner_init_mxl5007t[] = {
-	{ 0x800046, 0x1b },
-	{ 0x800057, 0x01 },
-	{ 0x800058, 0x01 },
-	{ 0x80005f, 0x00 },
-	{ 0x800060, 0x00 },
-	{ 0x800068, 0x96 },
-	{ 0x800071, 0x05 },
-	{ 0x800072, 0x02 },
-	{ 0x800074, 0x01 },
-	{ 0x800079, 0x01 },
-	{ 0x800093, 0x00 },
-	{ 0x800094, 0x00 },
-	{ 0x800095, 0x00 },
-	{ 0x800096, 0x00 },
-	{ 0x8000b3, 0x01 },
-	{ 0x8000c1, 0x01 },
-	{ 0x8000c2, 0x00 },
-	{ 0x80f007, 0x00 },
-	{ 0x80f00c, 0x19 },
-	{ 0x80f00d, 0x1a },
-	{ 0x80f012, 0xda },
-	{ 0x80f013, 0x00 },
-	{ 0x80f014, 0x00 },
-	{ 0x80f015, 0x02 },
-	{ 0x80f01f, 0x82 },
-	{ 0x80f020, 0x00 },
-	{ 0x80f029, 0x82 },
-	{ 0x80f02a, 0x00 },
-	{ 0x80f077, 0x02 },
-	{ 0x80f1e6, 0x00 },
-};
-
-/* NXP TDA 18218HN tuner init
-   AF9033_TUNER_TDA18218    = 0xa1 */
-static const struct reg_val tuner_init_tda18218[] = {
-	{0x800046, 0xa1},
-	{0x800057, 0x01},
-	{0x800058, 0x01},
-	{0x80005f, 0x00},
-	{0x800060, 0x00},
-	{0x800071, 0x05},
-	{0x800072, 0x02},
-	{0x800074, 0x01},
-	{0x800079, 0x01},
-	{0x800093, 0x00},
-	{0x800094, 0x00},
-	{0x800095, 0x00},
-	{0x800096, 0x00},
-	{0x8000b3, 0x01},
-	{0x8000c3, 0x01},
-	{0x8000c4, 0x00},
-	{0x80f007, 0x00},
-	{0x80f00c, 0x19},
-	{0x80f00d, 0x1a},
-	{0x80f012, 0xda},
-	{0x80f013, 0x00},
-	{0x80f014, 0x00},
-	{0x80f015, 0x02},
-	{0x80f01f, 0x82},
-	{0x80f020, 0x00},
-	{0x80f029, 0x82},
-	{0x80f02a, 0x00},
-	{0x80f077, 0x02},
-	{0x80f1e6, 0x00},
-};
-
-#endif /* AF9033_PRIV_H */
-
diff --git a/drivers/media/dvb/frontends/atbm8830.c b/drivers/media/dvb/frontends/atbm8830.c
deleted file mode 100644
index a2261ea..0000000
--- a/drivers/media/dvb/frontends/atbm8830.c
+++ /dev/null
@@ -1,508 +0,0 @@
-/*
- *    Support for AltoBeam GB20600 (a.k.a DMB-TH) demodulator
- *    ATBM8830, ATBM8831
- *
- *    Copyright (C) 2009 David T.L. Wong <davidtlwong@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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <asm/div64.h>
-#include "dvb_frontend.h"
-
-#include "atbm8830.h"
-#include "atbm8830_priv.h"
-
-#define dprintk(args...) \
-	do { \
-		if (debug) \
-			printk(KERN_DEBUG "atbm8830: " args); \
-	} while (0)
-
-static int debug;
-
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
-
-static int atbm8830_write_reg(struct atbm_state *priv, u16 reg, u8 data)
-{
-	int ret = 0;
-	u8 dev_addr;
-	u8 buf1[] = { reg >> 8, reg & 0xFF };
-	u8 buf2[] = { data };
-	struct i2c_msg msg1 = { .flags = 0, .buf = buf1, .len = 2 };
-	struct i2c_msg msg2 = { .flags = 0, .buf = buf2, .len = 1 };
-
-	dev_addr = priv->config->demod_address;
-	msg1.addr = dev_addr;
-	msg2.addr = dev_addr;
-
-	if (debug >= 2)
-		dprintk("%s: reg=0x%04X, data=0x%02X\n", __func__, reg, data);
-
-	ret = i2c_transfer(priv->i2c, &msg1, 1);
-	if (ret != 1)
-		return -EIO;
-
-	ret = i2c_transfer(priv->i2c, &msg2, 1);
-	return (ret != 1) ? -EIO : 0;
-}
-
-static int atbm8830_read_reg(struct atbm_state *priv, u16 reg, u8 *p_data)
-{
-	int ret;
-	u8 dev_addr;
-
-	u8 buf1[] = { reg >> 8, reg & 0xFF };
-	u8 buf2[] = { 0 };
-	struct i2c_msg msg1 = { .flags = 0, .buf = buf1, .len = 2 };
-	struct i2c_msg msg2 = { .flags = I2C_M_RD, .buf = buf2, .len = 1 };
-
-	dev_addr = priv->config->demod_address;
-	msg1.addr = dev_addr;
-	msg2.addr = dev_addr;
-
-	ret = i2c_transfer(priv->i2c, &msg1, 1);
-	if (ret != 1) {
-		dprintk("%s: error reg=0x%04x, ret=%i\n", __func__, reg, ret);
-		return -EIO;
-	}
-
-	ret = i2c_transfer(priv->i2c, &msg2, 1);
-	if (ret != 1)
-		return -EIO;
-
-	*p_data = buf2[0];
-	if (debug >= 2)
-		dprintk("%s: reg=0x%04X, data=0x%02X\n",
-			__func__, reg, buf2[0]);
-
-	return 0;
-}
-
-/* Lock register latch so that multi-register read is atomic */
-static inline int atbm8830_reglatch_lock(struct atbm_state *priv, int lock)
-{
-	return atbm8830_write_reg(priv, REG_READ_LATCH, lock ? 1 : 0);
-}
-
-static int set_osc_freq(struct atbm_state *priv, u32 freq /*in kHz*/)
-{
-	u32 val;
-	u64 t;
-
-	/* 0x100000 * freq / 30.4MHz */
-	t = (u64)0x100000 * freq;
-	do_div(t, 30400);
-	val = t;
-
-	atbm8830_write_reg(priv, REG_OSC_CLK, val);
-	atbm8830_write_reg(priv, REG_OSC_CLK + 1, val >> 8);
-	atbm8830_write_reg(priv, REG_OSC_CLK + 2, val >> 16);
-
-	return 0;
-}
-
-static int set_if_freq(struct atbm_state *priv, u32 freq /*in kHz*/)
-{
-
-	u32 fs = priv->config->osc_clk_freq;
-	u64 t;
-	u32 val;
-	u8 dat;
-
-	if (freq != 0) {
-		/* 2 * PI * (freq - fs) / fs * (2 ^ 22) */
-		t = (u64) 2 * 31416 * (freq - fs);
-		t <<= 22;
-		do_div(t, fs);
-		do_div(t, 1000);
-		val = t;
-
-		atbm8830_write_reg(priv, REG_TUNER_BASEBAND, 1);
-		atbm8830_write_reg(priv, REG_IF_FREQ, val);
-		atbm8830_write_reg(priv, REG_IF_FREQ+1, val >> 8);
-		atbm8830_write_reg(priv, REG_IF_FREQ+2, val >> 16);
-
-		atbm8830_read_reg(priv, REG_ADC_CONFIG, &dat);
-		dat &= 0xFC;
-		atbm8830_write_reg(priv, REG_ADC_CONFIG, dat);
-	} else {
-		/* Zero IF */
-		atbm8830_write_reg(priv, REG_TUNER_BASEBAND, 0);
-
-		atbm8830_read_reg(priv, REG_ADC_CONFIG, &dat);
-		dat &= 0xFC;
-		dat |= 0x02;
-		atbm8830_write_reg(priv, REG_ADC_CONFIG, dat);
-
-		if (priv->config->zif_swap_iq)
-			atbm8830_write_reg(priv, REG_SWAP_I_Q, 0x03);
-		else
-			atbm8830_write_reg(priv, REG_SWAP_I_Q, 0x01);
-	}
-
-	return 0;
-}
-
-static int is_locked(struct atbm_state *priv, u8 *locked)
-{
-	u8 status;
-
-	atbm8830_read_reg(priv, REG_LOCK_STATUS, &status);
-
-	if (locked != NULL)
-		*locked = (status == 1);
-	return 0;
-}
-
-static int set_agc_config(struct atbm_state *priv,
-	u8 min, u8 max, u8 hold_loop)
-{
-	/* no effect if both min and max are zero */
-	if (!min && !max)
-	    return 0;
-
-	atbm8830_write_reg(priv, REG_AGC_MIN, min);
-	atbm8830_write_reg(priv, REG_AGC_MAX, max);
-	atbm8830_write_reg(priv, REG_AGC_HOLD_LOOP, hold_loop);
-
-	return 0;
-}
-
-static int set_static_channel_mode(struct atbm_state *priv)
-{
-	int i;
-
-	for (i = 0; i < 5; i++)
-		atbm8830_write_reg(priv, 0x099B + i, 0x08);
-
-	atbm8830_write_reg(priv, 0x095B, 0x7F);
-	atbm8830_write_reg(priv, 0x09CB, 0x01);
-	atbm8830_write_reg(priv, 0x09CC, 0x7F);
-	atbm8830_write_reg(priv, 0x09CD, 0x7F);
-	atbm8830_write_reg(priv, 0x0E01, 0x20);
-
-	/* For single carrier */
-	atbm8830_write_reg(priv, 0x0B03, 0x0A);
-	atbm8830_write_reg(priv, 0x0935, 0x10);
-	atbm8830_write_reg(priv, 0x0936, 0x08);
-	atbm8830_write_reg(priv, 0x093E, 0x08);
-	atbm8830_write_reg(priv, 0x096E, 0x06);
-
-	/* frame_count_max0 */
-	atbm8830_write_reg(priv, 0x0B09, 0x00);
-	/* frame_count_max1 */
-	atbm8830_write_reg(priv, 0x0B0A, 0x08);
-
-	return 0;
-}
-
-static int set_ts_config(struct atbm_state *priv)
-{
-	const struct atbm8830_config *cfg = priv->config;
-
-	/*Set parallel/serial ts mode*/
-	atbm8830_write_reg(priv, REG_TS_SERIAL, cfg->serial_ts ? 1 : 0);
-	atbm8830_write_reg(priv, REG_TS_CLK_MODE, cfg->serial_ts ? 1 : 0);
-	/*Set ts sampling edge*/
-	atbm8830_write_reg(priv, REG_TS_SAMPLE_EDGE,
-		cfg->ts_sampling_edge ? 1 : 0);
-	/*Set ts clock freerun*/
-	atbm8830_write_reg(priv, REG_TS_CLK_FREERUN,
-		cfg->ts_clk_gated ? 0 : 1);
-
-	return 0;
-}
-
-static int atbm8830_init(struct dvb_frontend *fe)
-{
-	struct atbm_state *priv = fe->demodulator_priv;
-	const struct atbm8830_config *cfg = priv->config;
-
-	/*Set oscillator frequency*/
-	set_osc_freq(priv, cfg->osc_clk_freq);
-
-	/*Set IF frequency*/
-	set_if_freq(priv, cfg->if_freq);
-
-	/*Set AGC Config*/
-	set_agc_config(priv, cfg->agc_min, cfg->agc_max,
-		cfg->agc_hold_loop);
-
-	/*Set static channel mode*/
-	set_static_channel_mode(priv);
-
-	set_ts_config(priv);
-	/*Turn off DSP reset*/
-	atbm8830_write_reg(priv, 0x000A, 0);
-
-	/*SW version test*/
-	atbm8830_write_reg(priv, 0x020C, 11);
-
-	/* Run */
-	atbm8830_write_reg(priv, REG_DEMOD_RUN, 1);
-
-	return 0;
-}
-
-
-static void atbm8830_release(struct dvb_frontend *fe)
-{
-	struct atbm_state *state = fe->demodulator_priv;
-	dprintk("%s\n", __func__);
-
-	kfree(state);
-}
-
-static int atbm8830_set_fe(struct dvb_frontend *fe)
-{
-	struct atbm_state *priv = fe->demodulator_priv;
-	int i;
-	u8 locked = 0;
-	dprintk("%s\n", __func__);
-
-	/* set frequency */
-	if (fe->ops.tuner_ops.set_params) {
-		if (fe->ops.i2c_gate_ctrl)
-			fe->ops.i2c_gate_ctrl(fe, 1);
-		fe->ops.tuner_ops.set_params(fe);
-		if (fe->ops.i2c_gate_ctrl)
-			fe->ops.i2c_gate_ctrl(fe, 0);
-	}
-
-	/* start auto lock */
-	for (i = 0; i < 10; i++) {
-		mdelay(100);
-		dprintk("Try %d\n", i);
-		is_locked(priv, &locked);
-		if (locked != 0) {
-			dprintk("ATBM8830 locked!\n");
-			break;
-		}
-	}
-
-	return 0;
-}
-
-static int atbm8830_get_fe(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	dprintk("%s\n", __func__);
-
-	/* TODO: get real readings from device */
-	/* inversion status */
-	c->inversion = INVERSION_OFF;
-
-	/* bandwidth */
-	c->bandwidth_hz = 8000000;
-
-	c->code_rate_HP = FEC_AUTO;
-	c->code_rate_LP = FEC_AUTO;
-
-	c->modulation = QAM_AUTO;
-
-	/* transmission mode */
-	c->transmission_mode = TRANSMISSION_MODE_AUTO;
-
-	/* guard interval */
-	c->guard_interval = GUARD_INTERVAL_AUTO;
-
-	/* hierarchy */
-	c->hierarchy = HIERARCHY_NONE;
-
-	return 0;
-}
-
-static int atbm8830_get_tune_settings(struct dvb_frontend *fe,
-	struct dvb_frontend_tune_settings *fesettings)
-{
-	fesettings->min_delay_ms = 0;
-	fesettings->step_size = 0;
-	fesettings->max_drift = 0;
-	return 0;
-}
-
-static int atbm8830_read_status(struct dvb_frontend *fe, fe_status_t *fe_status)
-{
-	struct atbm_state *priv = fe->demodulator_priv;
-	u8 locked = 0;
-	u8 agc_locked = 0;
-
-	dprintk("%s\n", __func__);
-	*fe_status = 0;
-
-	is_locked(priv, &locked);
-	if (locked) {
-		*fe_status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
-			FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
-	}
-	dprintk("%s: fe_status=0x%x\n", __func__, *fe_status);
-
-	atbm8830_read_reg(priv, REG_AGC_LOCK, &agc_locked);
-	dprintk("AGC Lock: %d\n", agc_locked);
-
-	return 0;
-}
-
-static int atbm8830_read_ber(struct dvb_frontend *fe, u32 *ber)
-{
-	struct atbm_state *priv = fe->demodulator_priv;
-	u32 frame_err;
-	u8 t;
-
-	dprintk("%s\n", __func__);
-
-	atbm8830_reglatch_lock(priv, 1);
-
-	atbm8830_read_reg(priv, REG_FRAME_ERR_CNT + 1, &t);
-	frame_err = t & 0x7F;
-	frame_err <<= 8;
-	atbm8830_read_reg(priv, REG_FRAME_ERR_CNT, &t);
-	frame_err |= t;
-
-	atbm8830_reglatch_lock(priv, 0);
-
-	*ber = frame_err * 100 / 32767;
-
-	dprintk("%s: ber=0x%x\n", __func__, *ber);
-	return 0;
-}
-
-static int atbm8830_read_signal_strength(struct dvb_frontend *fe, u16 *signal)
-{
-	struct atbm_state *priv = fe->demodulator_priv;
-	u32 pwm;
-	u8 t;
-
-	dprintk("%s\n", __func__);
-	atbm8830_reglatch_lock(priv, 1);
-
-	atbm8830_read_reg(priv, REG_AGC_PWM_VAL + 1, &t);
-	pwm = t & 0x03;
-	pwm <<= 8;
-	atbm8830_read_reg(priv, REG_AGC_PWM_VAL, &t);
-	pwm |= t;
-
-	atbm8830_reglatch_lock(priv, 0);
-
-	dprintk("AGC PWM = 0x%02X\n", pwm);
-	pwm = 0x400 - pwm;
-
-	*signal = pwm * 0x10000 / 0x400;
-
-	return 0;
-}
-
-static int atbm8830_read_snr(struct dvb_frontend *fe, u16 *snr)
-{
-	dprintk("%s\n", __func__);
-	*snr = 0;
-	return 0;
-}
-
-static int atbm8830_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
-{
-	dprintk("%s\n", __func__);
-	*ucblocks = 0;
-	return 0;
-}
-
-static int atbm8830_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
-{
-	struct atbm_state *priv = fe->demodulator_priv;
-
-	return atbm8830_write_reg(priv, REG_I2C_GATE, enable ? 1 : 0);
-}
-
-static struct dvb_frontend_ops atbm8830_ops = {
-	.delsys = { SYS_DMBTH },
-	.info = {
-		.name = "AltoBeam ATBM8830/8831 DMB-TH",
-		.frequency_min = 474000000,
-		.frequency_max = 858000000,
-		.frequency_stepsize = 10000,
-		.caps =
-			FE_CAN_FEC_AUTO |
-			FE_CAN_QAM_AUTO |
-			FE_CAN_TRANSMISSION_MODE_AUTO |
-			FE_CAN_GUARD_INTERVAL_AUTO
-	},
-
-	.release = atbm8830_release,
-
-	.init = atbm8830_init,
-	.sleep = NULL,
-	.write = NULL,
-	.i2c_gate_ctrl = atbm8830_i2c_gate_ctrl,
-
-	.set_frontend = atbm8830_set_fe,
-	.get_frontend = atbm8830_get_fe,
-	.get_tune_settings = atbm8830_get_tune_settings,
-
-	.read_status = atbm8830_read_status,
-	.read_ber = atbm8830_read_ber,
-	.read_signal_strength = atbm8830_read_signal_strength,
-	.read_snr = atbm8830_read_snr,
-	.read_ucblocks = atbm8830_read_ucblocks,
-};
-
-struct dvb_frontend *atbm8830_attach(const struct atbm8830_config *config,
-	struct i2c_adapter *i2c)
-{
-	struct atbm_state *priv = NULL;
-	u8 data = 0;
-
-	dprintk("%s()\n", __func__);
-
-	if (config == NULL || i2c == NULL)
-		return NULL;
-
-	priv = kzalloc(sizeof(struct atbm_state), GFP_KERNEL);
-	if (priv == NULL)
-		goto error_out;
-
-	priv->config = config;
-	priv->i2c = i2c;
-
-	/* check if the demod is there */
-	if (atbm8830_read_reg(priv, REG_CHIP_ID, &data) != 0) {
-		dprintk("%s atbm8830/8831 not found at i2c addr 0x%02X\n",
-			__func__, priv->config->demod_address);
-		goto error_out;
-	}
-	dprintk("atbm8830 chip id: 0x%02X\n", data);
-
-	memcpy(&priv->frontend.ops, &atbm8830_ops,
-	       sizeof(struct dvb_frontend_ops));
-	priv->frontend.demodulator_priv = priv;
-
-	atbm8830_init(&priv->frontend);
-
-	atbm8830_i2c_gate_ctrl(&priv->frontend, 1);
-
-	return &priv->frontend;
-
-error_out:
-	dprintk("%s() error_out\n", __func__);
-	kfree(priv);
-	return NULL;
-
-}
-EXPORT_SYMBOL(atbm8830_attach);
-
-MODULE_DESCRIPTION("AltoBeam ATBM8830/8831 GB20600 demodulator driver");
-MODULE_AUTHOR("David T. L. Wong <davidtlwong@gmail.com>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/atbm8830.h b/drivers/media/dvb/frontends/atbm8830.h
deleted file mode 100644
index 0242733..0000000
--- a/drivers/media/dvb/frontends/atbm8830.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- *    Support for AltoBeam GB20600 (a.k.a DMB-TH) demodulator
- *    ATBM8830, ATBM8831
- *
- *    Copyright (C) 2009 David T.L. Wong <davidtlwong@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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef __ATBM8830_H__
-#define __ATBM8830_H__
-
-#include <linux/dvb/frontend.h>
-#include <linux/i2c.h>
-
-#define ATBM8830_PROD_8830 0
-#define ATBM8830_PROD_8831 1
-
-struct atbm8830_config {
-
-	/* product type */
-	u8 prod;
-
-	/* the demodulator's i2c address */
-	u8 demod_address;
-
-	/* parallel or serial transport stream */
-	u8 serial_ts;
-
-	/* transport stream clock output only when receiving valid stream */
-	u8 ts_clk_gated;
-
-	/* Decoder sample TS data at rising edge of clock */
-	u8 ts_sampling_edge;
-
-	/* Oscillator clock frequency */
-	u32 osc_clk_freq; /* in kHz */
-
-	/* IF frequency */
-	u32 if_freq; /* in kHz */
-
-	/* Swap I/Q for zero IF */
-	u8 zif_swap_iq;
-
-	/* Tuner AGC settings */
-	u8 agc_min;
-	u8 agc_max;
-	u8 agc_hold_loop;
-};
-
-#if defined(CONFIG_DVB_ATBM8830) || \
-	(defined(CONFIG_DVB_ATBM8830_MODULE) && defined(MODULE))
-extern struct dvb_frontend *atbm8830_attach(const struct atbm8830_config *config,
-		struct i2c_adapter *i2c);
-#else
-static inline
-struct dvb_frontend *atbm8830_attach(const struct atbm8830_config *config,
-		struct i2c_adapter *i2c) {
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif /* CONFIG_DVB_ATBM8830 */
-
-#endif /* __ATBM8830_H__ */
diff --git a/drivers/media/dvb/frontends/atbm8830_priv.h b/drivers/media/dvb/frontends/atbm8830_priv.h
deleted file mode 100644
index d460058..0000000
--- a/drivers/media/dvb/frontends/atbm8830_priv.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- *    Support for AltoBeam GB20600 (a.k.a DMB-TH) demodulator
- *    ATBM8830, ATBM8831
- *
- *    Copyright (C) 2009 David T.L. Wong <davidtlwong@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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef __ATBM8830_PRIV_H
-#define __ATBM8830_PRIV_H
-
-struct atbm_state {
-	struct i2c_adapter *i2c;
-	/* configuration settings */
-	const struct atbm8830_config *config;
-	struct dvb_frontend frontend;
-};
-
-#define REG_CHIP_ID	0x0000
-#define REG_TUNER_BASEBAND	0x0001
-#define REG_DEMOD_RUN	0x0004
-#define REG_DSP_RESET	0x0005
-#define REG_RAM_RESET	0x0006
-#define REG_ADC_RESET	0x0007
-#define REG_TSPORT_RESET	0x0008
-#define REG_BLKERR_POL	0x000C
-#define REG_I2C_GATE	0x0103
-#define REG_TS_SAMPLE_EDGE	0x0301
-#define REG_TS_PKT_LEN_204	0x0302
-#define REG_TS_PKT_LEN_AUTO	0x0303
-#define REG_TS_SERIAL	0x0305
-#define REG_TS_CLK_FREERUN	0x0306
-#define REG_TS_VALID_MODE	0x0307
-#define REG_TS_CLK_MODE	0x030B /* 1 for serial, 0 for parallel */
-
-#define REG_TS_ERRBIT_USE	0x030C
-#define REG_LOCK_STATUS	0x030D
-#define REG_ADC_CONFIG	0x0602
-#define REG_CARRIER_OFFSET	0x0827 /* 0x0827-0x0829 little endian */
-#define REG_DETECTED_PN_MODE	0x082D
-#define REG_READ_LATCH	0x084D
-#define REG_IF_FREQ	0x0A00 /* 0x0A00-0x0A02 little endian */
-#define REG_OSC_CLK	0x0A03 /* 0x0A03-0x0A05 little endian */
-#define REG_BYPASS_CCI	0x0A06
-#define REG_ANALOG_LUMA_DETECTED	0x0A25
-#define REG_ANALOG_AUDIO_DETECTED	0x0A26
-#define REG_ANALOG_CHROMA_DETECTED	0x0A39
-#define REG_FRAME_ERR_CNT	0x0B04
-#define REG_USE_EXT_ADC	0x0C00
-#define REG_SWAP_I_Q	0x0C01
-#define REG_TPS_MANUAL	0x0D01
-#define REG_TPS_CONFIG	0x0D02
-#define REG_BYPASS_DEINTERLEAVER	0x0E00
-#define REG_AGC_TARGET	0x1003 /* 0x1003-0x1005 little endian */
-#define REG_AGC_MIN	0x1020
-#define REG_AGC_MAX	0x1023
-#define REG_AGC_LOCK	0x1027
-#define REG_AGC_PWM_VAL	0x1028 /* 0x1028-0x1029 little endian */
-#define REG_AGC_HOLD_LOOP	0x1031
-
-#endif
-
diff --git a/drivers/media/dvb/frontends/au8522.h b/drivers/media/dvb/frontends/au8522.h
deleted file mode 100644
index 565dcf3..0000000
--- a/drivers/media/dvb/frontends/au8522.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
-    Auvitek AU8522 QAM/8VSB demodulator driver
-
-    Copyright (C) 2008 Steven Toth <stoth@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 __AU8522_H__
-#define __AU8522_H__
-
-#include <linux/dvb/frontend.h>
-
-enum au8522_if_freq {
-	AU8522_IF_6MHZ = 0,
-	AU8522_IF_4MHZ,
-	AU8522_IF_3_25MHZ,
-};
-
-struct au8522_led_config {
-	u16 vsb8_strong;
-	u16 qam64_strong;
-	u16 qam256_strong;
-
-	u16 gpio_output;
-	/* unset hi bits, set low bits */
-	u16 gpio_output_enable;
-	u16 gpio_output_disable;
-
-	u16 gpio_leds;
-	u8 *led_states;
-	unsigned int num_led_states;
-};
-
-struct au8522_config {
-	/* the demodulator's i2c address */
-	u8 demod_address;
-
-	/* Return lock status based on tuner lock, or demod lock */
-#define AU8522_TUNERLOCKING 0
-#define AU8522_DEMODLOCKING 1
-	u8 status_mode;
-
-	struct au8522_led_config *led_cfg;
-
-	enum au8522_if_freq vsb_if;
-	enum au8522_if_freq qam_if;
-};
-
-#if defined(CONFIG_DVB_AU8522) || 				\
-	    (defined(CONFIG_DVB_AU8522_MODULE) && defined(MODULE))
-extern struct dvb_frontend *au8522_attach(const struct au8522_config *config,
-					  struct i2c_adapter *i2c);
-#else
-static inline
-struct dvb_frontend *au8522_attach(const struct au8522_config *config,
-				   struct i2c_adapter *i2c)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#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__ */
-
-/*
- * Local variables:
- * c-basic-offset: 8
- */
diff --git a/drivers/media/dvb/frontends/au8522_common.c b/drivers/media/dvb/frontends/au8522_common.c
deleted file mode 100644
index 5cfe151..0000000
--- a/drivers/media/dvb/frontends/au8522_common.c
+++ /dev/null
@@ -1,259 +0,0 @@
-/*
-    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.
-    Copyright (C) 2012 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/i2c.h>
-#include "dvb_frontend.h"
-#include "au8522_priv.h"
-
-MODULE_LICENSE("GPL");
-
-static int debug;
-
-#define dprintk(arg...)\
-  do { if (debug)\
-	 printk(arg);\
-  } while (0)
-
-/* 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);
-
-/* 16 bit registers, 8 bit values */
-int au8522_writereg(struct au8522_state *state, u16 reg, u8 data)
-{
-	int ret;
-	u8 buf[] = { (reg >> 8) | 0x80, reg & 0xff, data };
-
-	struct i2c_msg msg = { .addr = state->config->demod_address,
-			       .flags = 0, .buf = buf, .len = 3 };
-
-	ret = i2c_transfer(state->i2c, &msg, 1);
-
-	if (ret != 1)
-		printk("%s: writereg error (reg == 0x%02x, val == 0x%04x, "
-		       "ret == %i)\n", __func__, reg, data, ret);
-
-	return (ret != 1) ? -1 : 0;
-}
-EXPORT_SYMBOL(au8522_writereg);
-
-u8 au8522_readreg(struct au8522_state *state, u16 reg)
-{
-	int ret;
-	u8 b0[] = { (reg >> 8) | 0x40, reg & 0xff };
-	u8 b1[] = { 0 };
-
-	struct i2c_msg msg[] = {
-		{ .addr = state->config->demod_address, .flags = 0,
-		  .buf = b0, .len = 2 },
-		{ .addr = state->config->demod_address, .flags = I2C_M_RD,
-		  .buf = b1, .len = 1 } };
-
-	ret = i2c_transfer(state->i2c, msg, 2);
-
-	if (ret != 2)
-		printk(KERN_ERR "%s: readreg error (ret == %i)\n",
-		       __func__, ret);
-	return b1[0];
-}
-EXPORT_SYMBOL(au8522_readreg);
-
-int au8522_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
-{
-	struct au8522_state *state = fe->demodulator_priv;
-
-	dprintk("%s(%d)\n", __func__, enable);
-
-	if (state->operational_mode == AU8522_ANALOG_MODE) {
-		/* We're being asked to manage the gate even though we're
-		   not in digital mode.  This can occur if we get switched
-		   over to analog mode before the dvb_frontend kernel thread
-		   has completely shutdown */
-		return 0;
-	}
-
-	if (enable)
-		return au8522_writereg(state, 0x106, 1);
-	else
-		return au8522_writereg(state, 0x106, 0);
-}
-EXPORT_SYMBOL(au8522_i2c_gate_ctrl);
-
-/* Reset the demod hardware and reset all of the configuration registers
-   to a default state. */
-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;
-}
-EXPORT_SYMBOL(au8522_get_state);
-
-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);
-}
-EXPORT_SYMBOL(au8522_release_state);
-
-static int au8522_led_gpio_enable(struct au8522_state *state, int onoff)
-{
-	struct au8522_led_config *led_config = state->config->led_cfg;
-	u8 val;
-
-	/* bail out if we can't control an LED */
-	if (!led_config || !led_config->gpio_output ||
-	    !led_config->gpio_output_enable || !led_config->gpio_output_disable)
-		return 0;
-
-	val = au8522_readreg(state, 0x4000 |
-			     (led_config->gpio_output & ~0xc000));
-	if (onoff) {
-		/* enable GPIO output */
-		val &= ~((led_config->gpio_output_enable >> 8) & 0xff);
-		val |=  (led_config->gpio_output_enable & 0xff);
-	} else {
-		/* disable GPIO output */
-		val &= ~((led_config->gpio_output_disable >> 8) & 0xff);
-		val |=  (led_config->gpio_output_disable & 0xff);
-	}
-	return au8522_writereg(state, 0x8000 |
-			       (led_config->gpio_output & ~0xc000), val);
-}
-
-/* led = 0 | off
- * led = 1 | signal ok
- * led = 2 | signal strong
- * led < 0 | only light led if leds are currently off
- */
-int au8522_led_ctrl(struct au8522_state *state, int led)
-{
-	struct au8522_led_config *led_config = state->config->led_cfg;
-	int i, ret = 0;
-
-	/* bail out if we can't control an LED */
-	if (!led_config || !led_config->gpio_leds ||
-	    !led_config->num_led_states || !led_config->led_states)
-		return 0;
-
-	if (led < 0) {
-		/* if LED is already lit, then leave it as-is */
-		if (state->led_state)
-			return 0;
-		else
-			led *= -1;
-	}
-
-	/* toggle LED if changing state */
-	if (state->led_state != led) {
-		u8 val;
-
-		dprintk("%s: %d\n", __func__, led);
-
-		au8522_led_gpio_enable(state, 1);
-
-		val = au8522_readreg(state, 0x4000 |
-				     (led_config->gpio_leds & ~0xc000));
-
-		/* start with all leds off */
-		for (i = 0; i < led_config->num_led_states; i++)
-			val &= ~led_config->led_states[i];
-
-		/* set selected LED state */
-		if (led < led_config->num_led_states)
-			val |= led_config->led_states[led];
-		else if (led_config->num_led_states)
-			val |=
-			led_config->led_states[led_config->num_led_states - 1];
-
-		ret = au8522_writereg(state, 0x8000 |
-				      (led_config->gpio_leds & ~0xc000), val);
-		if (ret < 0)
-			return ret;
-
-		state->led_state = led;
-
-		if (led == 0)
-			au8522_led_gpio_enable(state, 0);
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL(au8522_led_ctrl);
-
-int au8522_init(struct dvb_frontend *fe)
-{
-	struct au8522_state *state = fe->demodulator_priv;
-	dprintk("%s()\n", __func__);
-
-	state->operational_mode = AU8522_DIGITAL_MODE;
-
-	/* Clear out any state associated with the digital side of the
-	   chip, so that when it gets powered back up it won't think
-	   that it is already tuned */
-	state->current_frequency = 0;
-
-	au8522_writereg(state, 0xa4, 1 << 5);
-
-	au8522_i2c_gate_ctrl(fe, 1);
-
-	return 0;
-}
-EXPORT_SYMBOL(au8522_init);
-
-int au8522_sleep(struct dvb_frontend *fe)
-{
-	struct au8522_state *state = fe->demodulator_priv;
-	dprintk("%s()\n", __func__);
-
-	/* Only power down if the digital side is currently using the chip */
-	if (state->operational_mode == AU8522_ANALOG_MODE) {
-		/* We're not in one of the expected power modes, which means
-		   that the DVB thread is probably telling us to go to sleep
-		   even though the analog frontend has already started using
-		   the chip.  So ignore the request */
-		return 0;
-	}
-
-	/* turn off led */
-	au8522_led_ctrl(state, 0);
-
-	/* Power down the chip */
-	au8522_writereg(state, 0xa4, 1 << 5);
-
-	state->current_frequency = 0;
-
-	return 0;
-}
-EXPORT_SYMBOL(au8522_sleep);
diff --git a/drivers/media/dvb/frontends/au8522_decoder.c b/drivers/media/dvb/frontends/au8522_decoder.c
deleted file mode 100644
index 55b6390..0000000
--- a/drivers/media/dvb/frontends/au8522_decoder.c
+++ /dev/null
@@ -1,842 +0,0 @@
-/*
- * 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
- * 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-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"
-*/
-static const 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
-*/
-static const 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);
-	state->saturation = 0x80;
-	au8522_writereg(state, AU8522_TVDEC_HUE_H_REG00EH, 0x00);
-	au8522_writereg(state, AU8522_TVDEC_HUE_L_REG00FH, 0x00);
-	state->hue = 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);
-	if (input_mode == AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13 ||
-	    input_mode == AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH24) {
-		au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH,
-				AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH_SVIDEO);
-		au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH,
-				AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH_SVIDEO);
-	} else {
-		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 unknown). */
-		/* 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);
-
-	/* PGA in automatic mode */
-	au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x00);
-
-	/* Enable clamping control */
-	au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x00);
-
-	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 we have to have the PGA in automatic mode while
-	   enabling clamp control, but it's what Windows does */
-	au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x00);
-
-	/* Enable clamping control */
-	au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x0e);
-
-	/* Disable automatic PGA (since the CVBS is coming from the tuner) */
-	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);
-
-	/* PGA in automatic mode */
-	au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x00);
-
-	/* Enable clamping control */
-	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)
-{
-	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_SYSTEM_MODULE_CONTROL_1_REG0A5H, 0x04);
-	au8522_writereg(state, AU8522_I2S_CTRL_2_REG112H, 0x02);
-
-	au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
-			AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_SVIDEO);
-}
-
-/* 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:
-		state->saturation = ctrl->value;
-		au8522_writereg(state, AU8522_TVDEC_SATURATION_CB_REG00CH,
-				ctrl->value);
-		au8522_writereg(state, AU8522_TVDEC_SATURATION_CR_REG00DH,
-				ctrl->value);
-		break;
-	case V4L2_CID_HUE:
-		state->hue = ctrl->value;
-		au8522_writereg(state, AU8522_TVDEC_HUE_H_REG00EH,
-				ctrl->value >> 8);
-		au8522_writereg(state, AU8522_TVDEC_HUE_L_REG00FH,
-				ctrl->value & 0xFF);
-		break;
-	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:
-		ctrl->value = state->saturation;
-		break;
-	case V4L2_CID_HUE:
-		ctrl->value = state->hue;
-		break;
-	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;
-}
-
-/* ----------------------------------------------------------------------- */
-
-#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, 109);
-	case V4L2_CID_SATURATION:
-		return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128);
-	case V4L2_CID_HUE:
-		return v4l2_ctrl_query_fill(qc, -32768, 32768, 1, 0);
-	default:
-		break;
-	}
-
-	qc->type = 0;
-	return -EINVAL;
-}
-
-static int au8522_reset(struct v4l2_subdev *sd, u32 val)
-{
-	struct au8522_state *state = to_state(sd);
-
-	state->operational_mode = AU8522_ANALOG_MODE;
-
-	/* Clear out any state associated with the digital side of the
-	   chip, so that when it gets powered back up it won't think
-	   that it is already tuned */
-	state->current_frequency = 0;
-
-	au8522_writereg(state, 0xa4, 1 << 5);
-
-	return 0;
-}
-
-static int au8522_s_video_routing(struct v4l2_subdev *sd,
-					u32 input, u32 output, u32 config)
-{
-	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 (input == AU8522_COMPOSITE_CH1) {
-		au8522_setup_cvbs_mode(state);
-	} else if (input == AU8522_SVIDEO_CH13) {
-		au8522_setup_svideo_mode(state);
-	} else if (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,
-					u32 input, u32 output, u32 config)
-{
-	struct au8522_state *state = to_state(sd);
-	set_audio_input(state, 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 = 0xffff;
-	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,
-	.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);
-	if (demod_config == NULL) {
-		if (instance == 1)
-			kfree(state);
-		return -ENOMEM;
-	}
-	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 i2c_driver au8522_driver = {
-	.driver = {
-		.owner	= THIS_MODULE,
-		.name	= "au8522",
-	},
-	.probe		= au8522_probe,
-	.remove		= au8522_remove,
-	.id_table	= au8522_id,
-};
-
-module_i2c_driver(au8522_driver);
diff --git a/drivers/media/dvb/frontends/au8522_dig.c b/drivers/media/dvb/frontends/au8522_dig.c
deleted file mode 100644
index 5fc70d6..0000000
--- a/drivers/media/dvb/frontends/au8522_dig.c
+++ /dev/null
@@ -1,826 +0,0 @@
-/*
-    Auvitek AU8522 QAM/8VSB demodulator driver
-
-    Copyright (C) 2008 Steven Toth <stoth@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/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/delay.h>
-#include "dvb_frontend.h"
-#include "au8522.h"
-#include "au8522_priv.h"
-
-static int debug;
-
-#define dprintk(arg...)\
-	do { if (debug)\
-		printk(arg);\
-	} while (0)
-
-struct mse2snr_tab {
-	u16 val;
-	u16 data;
-};
-
-/* VSB SNR lookup table */
-static struct mse2snr_tab vsb_mse2snr_tab[] = {
-	{   0, 270 },
-	{   2, 250 },
-	{   3, 240 },
-	{   5, 230 },
-	{   7, 220 },
-	{   9, 210 },
-	{  12, 200 },
-	{  13, 195 },
-	{  15, 190 },
-	{  17, 185 },
-	{  19, 180 },
-	{  21, 175 },
-	{  24, 170 },
-	{  27, 165 },
-	{  31, 160 },
-	{  32, 158 },
-	{  33, 156 },
-	{  36, 152 },
-	{  37, 150 },
-	{  39, 148 },
-	{  40, 146 },
-	{  41, 144 },
-	{  43, 142 },
-	{  44, 140 },
-	{  48, 135 },
-	{  50, 130 },
-	{  43, 142 },
-	{  53, 125 },
-	{  56, 120 },
-	{ 256, 115 },
-};
-
-/* QAM64 SNR lookup table */
-static struct mse2snr_tab qam64_mse2snr_tab[] = {
-	{  15,   0 },
-	{  16, 290 },
-	{  17, 288 },
-	{  18, 286 },
-	{  19, 284 },
-	{  20, 282 },
-	{  21, 281 },
-	{  22, 279 },
-	{  23, 277 },
-	{  24, 275 },
-	{  25, 273 },
-	{  26, 271 },
-	{  27, 269 },
-	{  28, 268 },
-	{  29, 266 },
-	{  30, 264 },
-	{  31, 262 },
-	{  32, 260 },
-	{  33, 259 },
-	{  34, 258 },
-	{  35, 256 },
-	{  36, 255 },
-	{  37, 254 },
-	{  38, 252 },
-	{  39, 251 },
-	{  40, 250 },
-	{  41, 249 },
-	{  42, 248 },
-	{  43, 246 },
-	{  44, 245 },
-	{  45, 244 },
-	{  46, 242 },
-	{  47, 241 },
-	{  48, 240 },
-	{  50, 239 },
-	{  51, 238 },
-	{  53, 237 },
-	{  54, 236 },
-	{  56, 235 },
-	{  57, 234 },
-	{  59, 233 },
-	{  60, 232 },
-	{  62, 231 },
-	{  63, 230 },
-	{  65, 229 },
-	{  67, 228 },
-	{  68, 227 },
-	{  70, 226 },
-	{  71, 225 },
-	{  73, 224 },
-	{  74, 223 },
-	{  76, 222 },
-	{  78, 221 },
-	{  80, 220 },
-	{  82, 219 },
-	{  85, 218 },
-	{  88, 217 },
-	{  90, 216 },
-	{  92, 215 },
-	{  93, 214 },
-	{  94, 212 },
-	{  95, 211 },
-	{  97, 210 },
-	{  99, 209 },
-	{ 101, 208 },
-	{ 102, 207 },
-	{ 104, 206 },
-	{ 107, 205 },
-	{ 111, 204 },
-	{ 114, 203 },
-	{ 118, 202 },
-	{ 122, 201 },
-	{ 125, 200 },
-	{ 128, 199 },
-	{ 130, 198 },
-	{ 132, 197 },
-	{ 256, 190 },
-};
-
-/* QAM256 SNR lookup table */
-static struct mse2snr_tab qam256_mse2snr_tab[] = {
-	{  16,   0 },
-	{  17, 400 },
-	{  18, 398 },
-	{  19, 396 },
-	{  20, 394 },
-	{  21, 392 },
-	{  22, 390 },
-	{  23, 388 },
-	{  24, 386 },
-	{  25, 384 },
-	{  26, 382 },
-	{  27, 380 },
-	{  28, 379 },
-	{  29, 378 },
-	{  30, 377 },
-	{  31, 376 },
-	{  32, 375 },
-	{  33, 374 },
-	{  34, 373 },
-	{  35, 372 },
-	{  36, 371 },
-	{  37, 370 },
-	{  38, 362 },
-	{  39, 354 },
-	{  40, 346 },
-	{  41, 338 },
-	{  42, 330 },
-	{  43, 328 },
-	{  44, 326 },
-	{  45, 324 },
-	{  46, 322 },
-	{  47, 320 },
-	{  48, 319 },
-	{  49, 318 },
-	{  50, 317 },
-	{  51, 316 },
-	{  52, 315 },
-	{  53, 314 },
-	{  54, 313 },
-	{  55, 312 },
-	{  56, 311 },
-	{  57, 310 },
-	{  58, 308 },
-	{  59, 306 },
-	{  60, 304 },
-	{  61, 302 },
-	{  62, 300 },
-	{  63, 298 },
-	{  65, 295 },
-	{  68, 294 },
-	{  70, 293 },
-	{  73, 292 },
-	{  76, 291 },
-	{  78, 290 },
-	{  79, 289 },
-	{  81, 288 },
-	{  82, 287 },
-	{  83, 286 },
-	{  84, 285 },
-	{  85, 284 },
-	{  86, 283 },
-	{  88, 282 },
-	{  89, 281 },
-	{ 256, 280 },
-};
-
-static int au8522_mse2snr_lookup(struct mse2snr_tab *tab, int sz, int mse,
-				 u16 *snr)
-{
-	int i, ret = -EINVAL;
-	dprintk("%s()\n", __func__);
-
-	for (i = 0; i < sz; i++) {
-		if (mse < tab[i].val) {
-			*snr = tab[i].data;
-			ret = 0;
-			break;
-		}
-	}
-	dprintk("%s() snr=%d\n", __func__, *snr);
-	return ret;
-}
-
-static int au8522_set_if(struct dvb_frontend *fe, enum au8522_if_freq if_freq)
-{
-	struct au8522_state *state = fe->demodulator_priv;
-	u8 r0b5, r0b6, r0b7;
-	char *ifmhz;
-
-	switch (if_freq) {
-	case AU8522_IF_3_25MHZ:
-		ifmhz = "3.25";
-		r0b5 = 0x00;
-		r0b6 = 0x3d;
-		r0b7 = 0xa0;
-		break;
-	case AU8522_IF_4MHZ:
-		ifmhz = "4.00";
-		r0b5 = 0x00;
-		r0b6 = 0x4b;
-		r0b7 = 0xd9;
-		break;
-	case AU8522_IF_6MHZ:
-		ifmhz = "6.00";
-		r0b5 = 0xfb;
-		r0b6 = 0x8e;
-		r0b7 = 0x39;
-		break;
-	default:
-		dprintk("%s() IF Frequency not supported\n", __func__);
-		return -EINVAL;
-	}
-	dprintk("%s() %s MHz\n", __func__, ifmhz);
-	au8522_writereg(state, 0x80b5, r0b5);
-	au8522_writereg(state, 0x80b6, r0b6);
-	au8522_writereg(state, 0x80b7, r0b7);
-
-	return 0;
-}
-
-/* VSB Modulation table */
-static struct {
-	u16 reg;
-	u16 data;
-} VSB_mod_tab[] = {
-	{ 0x8090, 0x84 },
-	{ 0x4092, 0x11 },
-	{ 0x2005, 0x00 },
-	{ 0x8091, 0x80 },
-	{ 0x80a3, 0x0c },
-	{ 0x80a4, 0xe8 },
-	{ 0x8081, 0xc4 },
-	{ 0x80a5, 0x40 },
-	{ 0x80a7, 0x40 },
-	{ 0x80a6, 0x67 },
-	{ 0x8262, 0x20 },
-	{ 0x821c, 0x30 },
-	{ 0x80d8, 0x1a },
-	{ 0x8227, 0xa0 },
-	{ 0x8121, 0xff },
-	{ 0x80a8, 0xf0 },
-	{ 0x80a9, 0x05 },
-	{ 0x80aa, 0x77 },
-	{ 0x80ab, 0xf0 },
-	{ 0x80ac, 0x05 },
-	{ 0x80ad, 0x77 },
-	{ 0x80ae, 0x41 },
-	{ 0x80af, 0x66 },
-	{ 0x821b, 0xcc },
-	{ 0x821d, 0x80 },
-	{ 0x80a4, 0xe8 },
-	{ 0x8231, 0x13 },
-};
-
-/* QAM64 Modulation table */
-static struct {
-	u16 reg;
-	u16 data;
-} QAM64_mod_tab[] = {
-	{ 0x00a3, 0x09 },
-	{ 0x00a4, 0x00 },
-	{ 0x0081, 0xc4 },
-	{ 0x00a5, 0x40 },
-	{ 0x00aa, 0x77 },
-	{ 0x00ad, 0x77 },
-	{ 0x00a6, 0x67 },
-	{ 0x0262, 0x20 },
-	{ 0x021c, 0x30 },
-	{ 0x00b8, 0x3e },
-	{ 0x00b9, 0xf0 },
-	{ 0x00ba, 0x01 },
-	{ 0x00bb, 0x18 },
-	{ 0x00bc, 0x50 },
-	{ 0x00bd, 0x00 },
-	{ 0x00be, 0xea },
-	{ 0x00bf, 0xef },
-	{ 0x00c0, 0xfc },
-	{ 0x00c1, 0xbd },
-	{ 0x00c2, 0x1f },
-	{ 0x00c3, 0xfc },
-	{ 0x00c4, 0xdd },
-	{ 0x00c5, 0xaf },
-	{ 0x00c6, 0x00 },
-	{ 0x00c7, 0x38 },
-	{ 0x00c8, 0x30 },
-	{ 0x00c9, 0x05 },
-	{ 0x00ca, 0x4a },
-	{ 0x00cb, 0xd0 },
-	{ 0x00cc, 0x01 },
-	{ 0x00cd, 0xd9 },
-	{ 0x00ce, 0x6f },
-	{ 0x00cf, 0xf9 },
-	{ 0x00d0, 0x70 },
-	{ 0x00d1, 0xdf },
-	{ 0x00d2, 0xf7 },
-	{ 0x00d3, 0xc2 },
-	{ 0x00d4, 0xdf },
-	{ 0x00d5, 0x02 },
-	{ 0x00d6, 0x9a },
-	{ 0x00d7, 0xd0 },
-	{ 0x0250, 0x0d },
-	{ 0x0251, 0xcd },
-	{ 0x0252, 0xe0 },
-	{ 0x0253, 0x05 },
-	{ 0x0254, 0xa7 },
-	{ 0x0255, 0xff },
-	{ 0x0256, 0xed },
-	{ 0x0257, 0x5b },
-	{ 0x0258, 0xae },
-	{ 0x0259, 0xe6 },
-	{ 0x025a, 0x3d },
-	{ 0x025b, 0x0f },
-	{ 0x025c, 0x0d },
-	{ 0x025d, 0xea },
-	{ 0x025e, 0xf2 },
-	{ 0x025f, 0x51 },
-	{ 0x0260, 0xf5 },
-	{ 0x0261, 0x06 },
-	{ 0x021a, 0x00 },
-	{ 0x0546, 0x40 },
-	{ 0x0210, 0xc7 },
-	{ 0x0211, 0xaa },
-	{ 0x0212, 0xab },
-	{ 0x0213, 0x02 },
-	{ 0x0502, 0x00 },
-	{ 0x0121, 0x04 },
-	{ 0x0122, 0x04 },
-	{ 0x052e, 0x10 },
-	{ 0x00a4, 0xca },
-	{ 0x00a7, 0x40 },
-	{ 0x0526, 0x01 },
-};
-
-/* QAM256 Modulation table */
-static struct {
-	u16 reg;
-	u16 data;
-} QAM256_mod_tab[] = {
-	{ 0x80a3, 0x09 },
-	{ 0x80a4, 0x00 },
-	{ 0x8081, 0xc4 },
-	{ 0x80a5, 0x40 },
-	{ 0x80aa, 0x77 },
-	{ 0x80ad, 0x77 },
-	{ 0x80a6, 0x67 },
-	{ 0x8262, 0x20 },
-	{ 0x821c, 0x30 },
-	{ 0x80b8, 0x3e },
-	{ 0x80b9, 0xf0 },
-	{ 0x80ba, 0x01 },
-	{ 0x80bb, 0x18 },
-	{ 0x80bc, 0x50 },
-	{ 0x80bd, 0x00 },
-	{ 0x80be, 0xea },
-	{ 0x80bf, 0xef },
-	{ 0x80c0, 0xfc },
-	{ 0x80c1, 0xbd },
-	{ 0x80c2, 0x1f },
-	{ 0x80c3, 0xfc },
-	{ 0x80c4, 0xdd },
-	{ 0x80c5, 0xaf },
-	{ 0x80c6, 0x00 },
-	{ 0x80c7, 0x38 },
-	{ 0x80c8, 0x30 },
-	{ 0x80c9, 0x05 },
-	{ 0x80ca, 0x4a },
-	{ 0x80cb, 0xd0 },
-	{ 0x80cc, 0x01 },
-	{ 0x80cd, 0xd9 },
-	{ 0x80ce, 0x6f },
-	{ 0x80cf, 0xf9 },
-	{ 0x80d0, 0x70 },
-	{ 0x80d1, 0xdf },
-	{ 0x80d2, 0xf7 },
-	{ 0x80d3, 0xc2 },
-	{ 0x80d4, 0xdf },
-	{ 0x80d5, 0x02 },
-	{ 0x80d6, 0x9a },
-	{ 0x80d7, 0xd0 },
-	{ 0x8250, 0x0d },
-	{ 0x8251, 0xcd },
-	{ 0x8252, 0xe0 },
-	{ 0x8253, 0x05 },
-	{ 0x8254, 0xa7 },
-	{ 0x8255, 0xff },
-	{ 0x8256, 0xed },
-	{ 0x8257, 0x5b },
-	{ 0x8258, 0xae },
-	{ 0x8259, 0xe6 },
-	{ 0x825a, 0x3d },
-	{ 0x825b, 0x0f },
-	{ 0x825c, 0x0d },
-	{ 0x825d, 0xea },
-	{ 0x825e, 0xf2 },
-	{ 0x825f, 0x51 },
-	{ 0x8260, 0xf5 },
-	{ 0x8261, 0x06 },
-	{ 0x821a, 0x00 },
-	{ 0x8546, 0x40 },
-	{ 0x8210, 0x26 },
-	{ 0x8211, 0xf6 },
-	{ 0x8212, 0x84 },
-	{ 0x8213, 0x02 },
-	{ 0x8502, 0x01 },
-	{ 0x8121, 0x04 },
-	{ 0x8122, 0x04 },
-	{ 0x852e, 0x10 },
-	{ 0x80a4, 0xca },
-	{ 0x80a7, 0x40 },
-	{ 0x8526, 0x01 },
-};
-
-static int au8522_enable_modulation(struct dvb_frontend *fe,
-				    fe_modulation_t m)
-{
-	struct au8522_state *state = fe->demodulator_priv;
-	int i;
-
-	dprintk("%s(0x%08x)\n", __func__, m);
-
-	switch (m) {
-	case VSB_8:
-		dprintk("%s() VSB_8\n", __func__);
-		for (i = 0; i < ARRAY_SIZE(VSB_mod_tab); i++)
-			au8522_writereg(state,
-				VSB_mod_tab[i].reg,
-				VSB_mod_tab[i].data);
-		au8522_set_if(fe, state->config->vsb_if);
-		break;
-	case QAM_64:
-		dprintk("%s() QAM 64\n", __func__);
-		for (i = 0; i < ARRAY_SIZE(QAM64_mod_tab); i++)
-			au8522_writereg(state,
-				QAM64_mod_tab[i].reg,
-				QAM64_mod_tab[i].data);
-		au8522_set_if(fe, state->config->qam_if);
-		break;
-	case QAM_256:
-		dprintk("%s() QAM 256\n", __func__);
-		for (i = 0; i < ARRAY_SIZE(QAM256_mod_tab); i++)
-			au8522_writereg(state,
-				QAM256_mod_tab[i].reg,
-				QAM256_mod_tab[i].data);
-		au8522_set_if(fe, state->config->qam_if);
-		break;
-	default:
-		dprintk("%s() Invalid modulation\n", __func__);
-		return -EINVAL;
-	}
-
-	state->current_modulation = m;
-
-	return 0;
-}
-
-/* Talk to the demod, set the FEC, GUARD, QAM settings etc */
-static int au8522_set_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	struct au8522_state *state = fe->demodulator_priv;
-	int ret = -EINVAL;
-
-	dprintk("%s(frequency=%d)\n", __func__, c->frequency);
-
-	if ((state->current_frequency == c->frequency) &&
-	    (state->current_modulation == c->modulation))
-		return 0;
-
-	if (fe->ops.tuner_ops.set_params) {
-		if (fe->ops.i2c_gate_ctrl)
-			fe->ops.i2c_gate_ctrl(fe, 1);
-		ret = fe->ops.tuner_ops.set_params(fe);
-		if (fe->ops.i2c_gate_ctrl)
-			fe->ops.i2c_gate_ctrl(fe, 0);
-	}
-
-	if (ret < 0)
-		return ret;
-
-	/* Allow the tuner to settle */
-	msleep(100);
-
-	au8522_enable_modulation(fe, c->modulation);
-
-	state->current_frequency = c->frequency;
-
-	return 0;
-}
-
-static int au8522_read_status(struct dvb_frontend *fe, fe_status_t *status)
-{
-	struct au8522_state *state = fe->demodulator_priv;
-	u8 reg;
-	u32 tuner_status = 0;
-
-	*status = 0;
-
-	if (state->current_modulation == VSB_8) {
-		dprintk("%s() Checking VSB_8\n", __func__);
-		reg = au8522_readreg(state, 0x4088);
-		if ((reg & 0x03) == 0x03)
-			*status |= FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI;
-	} else {
-		dprintk("%s() Checking QAM\n", __func__);
-		reg = au8522_readreg(state, 0x4541);
-		if (reg & 0x80)
-			*status |= FE_HAS_VITERBI;
-		if (reg & 0x20)
-			*status |= FE_HAS_LOCK | FE_HAS_SYNC;
-	}
-
-	switch (state->config->status_mode) {
-	case AU8522_DEMODLOCKING:
-		dprintk("%s() DEMODLOCKING\n", __func__);
-		if (*status & FE_HAS_VITERBI)
-			*status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
-		break;
-	case AU8522_TUNERLOCKING:
-		/* Get the tuner status */
-		dprintk("%s() TUNERLOCKING\n", __func__);
-		if (fe->ops.tuner_ops.get_status) {
-			if (fe->ops.i2c_gate_ctrl)
-				fe->ops.i2c_gate_ctrl(fe, 1);
-
-			fe->ops.tuner_ops.get_status(fe, &tuner_status);
-
-			if (fe->ops.i2c_gate_ctrl)
-				fe->ops.i2c_gate_ctrl(fe, 0);
-		}
-		if (tuner_status)
-			*status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
-		break;
-	}
-	state->fe_status = *status;
-
-	if (*status & FE_HAS_LOCK)
-		/* turn on LED, if it isn't on already */
-		au8522_led_ctrl(state, -1);
-	else
-		/* turn off LED */
-		au8522_led_ctrl(state, 0);
-
-	dprintk("%s() status 0x%08x\n", __func__, *status);
-
-	return 0;
-}
-
-static int au8522_led_status(struct au8522_state *state, const u16 *snr)
-{
-	struct au8522_led_config *led_config = state->config->led_cfg;
-	int led;
-	u16 strong;
-
-	/* bail out if we can't control an LED */
-	if (!led_config)
-		return 0;
-
-	if (0 == (state->fe_status & FE_HAS_LOCK))
-		return au8522_led_ctrl(state, 0);
-	else if (state->current_modulation == QAM_256)
-		strong = led_config->qam256_strong;
-	else if (state->current_modulation == QAM_64)
-		strong = led_config->qam64_strong;
-	else /* (state->current_modulation == VSB_8) */
-		strong = led_config->vsb8_strong;
-
-	if (*snr >= strong)
-		led = 2;
-	else
-		led = 1;
-
-	if ((state->led_state) &&
-	    (((strong < *snr) ? (*snr - strong) : (strong - *snr)) <= 10))
-		/* snr didn't change enough to bother
-		 * changing the color of the led */
-		return 0;
-
-	return au8522_led_ctrl(state, led);
-}
-
-static int au8522_read_snr(struct dvb_frontend *fe, u16 *snr)
-{
-	struct au8522_state *state = fe->demodulator_priv;
-	int ret = -EINVAL;
-
-	dprintk("%s()\n", __func__);
-
-	if (state->current_modulation == QAM_256)
-		ret = au8522_mse2snr_lookup(qam256_mse2snr_tab,
-					    ARRAY_SIZE(qam256_mse2snr_tab),
-					    au8522_readreg(state, 0x4522),
-					    snr);
-	else if (state->current_modulation == QAM_64)
-		ret = au8522_mse2snr_lookup(qam64_mse2snr_tab,
-					    ARRAY_SIZE(qam64_mse2snr_tab),
-					    au8522_readreg(state, 0x4522),
-					    snr);
-	else /* VSB_8 */
-		ret = au8522_mse2snr_lookup(vsb_mse2snr_tab,
-					    ARRAY_SIZE(vsb_mse2snr_tab),
-					    au8522_readreg(state, 0x4311),
-					    snr);
-
-	if (state->config->led_cfg)
-		au8522_led_status(state, snr);
-
-	return ret;
-}
-
-static int au8522_read_signal_strength(struct dvb_frontend *fe,
-				       u16 *signal_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%
-	 */
-	u16 snr;
-	u32 tmp;
-	int ret = au8522_read_snr(fe, &snr);
-
-	*signal_strength = 0;
-
-	if (0 == ret) {
-		/* The following calculation method was chosen
-		 * purely for the sake of code re-use from the
-		 * other demod drivers that use this method */
-
-		/* Convert from SNR in dB * 10 to 8.24 fixed-point */
-		tmp = (snr * ((1 << 24) / 10));
-
-		/* Convert from 8.24 fixed-point to
-		 * scale the range 0 - 35*2^24 into 0 - 65535*/
-		if (tmp >= 8960 * 0x10000)
-			*signal_strength = 0xffff;
-		else
-			*signal_strength = tmp / 8960;
-	}
-
-	return ret;
-}
-
-static int au8522_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
-{
-	struct au8522_state *state = fe->demodulator_priv;
-
-	if (state->current_modulation == VSB_8)
-		*ucblocks = au8522_readreg(state, 0x4087);
-	else
-		*ucblocks = au8522_readreg(state, 0x4543);
-
-	return 0;
-}
-
-static int au8522_read_ber(struct dvb_frontend *fe, u32 *ber)
-{
-	return au8522_read_ucblocks(fe, ber);
-}
-
-static int au8522_get_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	struct au8522_state *state = fe->demodulator_priv;
-
-	c->frequency = state->current_frequency;
-	c->modulation = state->current_modulation;
-
-	return 0;
-}
-
-static int au8522_get_tune_settings(struct dvb_frontend *fe,
-				    struct dvb_frontend_tune_settings *tune)
-{
-	tune->min_delay_ms = 1000;
-	return 0;
-}
-
-static struct dvb_frontend_ops au8522_ops;
-
-
-static void au8522_release(struct dvb_frontend *fe)
-{
-	struct au8522_state *state = fe->demodulator_priv;
-	au8522_release_state(state);
-}
-
-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 */
-	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;
-	state->i2c = i2c;
-	state->operational_mode = AU8522_DIGITAL_MODE;
-
-	/* create dvb_frontend */
-	memcpy(&state->frontend.ops, &au8522_ops,
-	       sizeof(struct dvb_frontend_ops));
-	state->frontend.demodulator_priv = state;
-
-	if (au8522_init(&state->frontend) != 0) {
-		printk(KERN_ERR "%s: Failed to initialize correctly\n",
-			__func__);
-		goto error;
-	}
-
-	/* Note: Leaving the I2C gate open here. */
-	au8522_i2c_gate_ctrl(&state->frontend, 1);
-
-	return &state->frontend;
-
-error:
-	au8522_release_state(state);
-	return NULL;
-}
-EXPORT_SYMBOL(au8522_attach);
-
-static struct dvb_frontend_ops au8522_ops = {
-	.delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
-	.info = {
-		.name			= "Auvitek AU8522 QAM/8VSB Frontend",
-		.frequency_min		= 54000000,
-		.frequency_max		= 858000000,
-		.frequency_stepsize	= 62500,
-		.caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
-	},
-
-	.init                 = au8522_init,
-	.sleep                = au8522_sleep,
-	.i2c_gate_ctrl        = au8522_i2c_gate_ctrl,
-	.set_frontend         = au8522_set_frontend,
-	.get_frontend         = au8522_get_frontend,
-	.get_tune_settings    = au8522_get_tune_settings,
-	.read_status          = au8522_read_status,
-	.read_ber             = au8522_read_ber,
-	.read_signal_strength = au8522_read_signal_strength,
-	.read_snr             = au8522_read_snr,
-	.read_ucblocks        = au8522_read_ucblocks,
-	.release              = au8522_release,
-};
-
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Enable verbose debug messages");
-
-MODULE_DESCRIPTION("Auvitek AU8522 QAM-B/ATSC Demodulator driver");
-MODULE_AUTHOR("Steven Toth");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/au8522_priv.h b/drivers/media/dvb/frontends/au8522_priv.h
deleted file mode 100644
index 6e4a438..0000000
--- a/drivers/media/dvb/frontends/au8522_priv.h
+++ /dev/null
@@ -1,423 +0,0 @@
-/*
-    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"
-
-#define AU8522_ANALOG_MODE 0
-#define AU8522_DIGITAL_MODE 1
-
-struct au8522_state {
-	struct i2c_client *c;
-	struct i2c_adapter *i2c;
-
-	u8 operational_mode;
-
-	/* 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;
-	u8 saturation;
-	s16 hue;
-};
-
-/* 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);
-int au8522_i2c_gate_ctrl(struct dvb_frontend *fe, int enable);
-int au8522_led_ctrl(struct au8522_state *state, int led);
-
-/* 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_THR1_REG06CH_SVIDEO		0x2a
-#define AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH_CVBS		0x05
-#define AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH_SVIDEO		0x15
-#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/bcm3510.c b/drivers/media/dvb/frontends/bcm3510.c
deleted file mode 100644
index 033cd7a..0000000
--- a/drivers/media/dvb/frontends/bcm3510.c
+++ /dev/null
@@ -1,856 +0,0 @@
-/*
- * Support for the Broadcom BCM3510 ATSC demodulator (1st generation Air2PC)
- *
- *  Copyright (C) 2001-5, B2C2 inc.
- *
- *  GPL/Linux driver written by Patrick Boettcher <patrick.boettcher@desy.de>
- *
- *  This driver is "hard-coded" to be used with the 1st generation of
- *  Technisat/B2C2's Air2PC ATSC PCI/USB cards/boxes. The pll-programming
- *  (Panasonic CT10S) is located here, which is actually wrong. Unless there is
- *  another device with a BCM3510, this is no problem.
- *
- *  The driver works also with QAM64 DVB-C, but had an unreasonable high
- *  UNC. (Tested with the Air2PC ATSC 1st generation)
- *
- *  You'll need a firmware for this driver in order to get it running. It is
- *  called "dvb-fe-bcm3510-01.fw".
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the 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/init.h>
-#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/firmware.h>
-#include <linux/jiffies.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/mutex.h>
-
-#include "dvb_frontend.h"
-#include "bcm3510.h"
-#include "bcm3510_priv.h"
-
-struct bcm3510_state {
-
-	struct i2c_adapter* i2c;
-	const struct bcm3510_config* config;
-	struct dvb_frontend frontend;
-
-	/* demodulator private data */
-	struct mutex hab_mutex;
-	u8 firmware_loaded:1;
-
-	unsigned long next_status_check;
-	unsigned long status_check_interval;
-	struct bcm3510_hab_cmd_status1 status1;
-	struct bcm3510_hab_cmd_status2 status2;
-};
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level (1=info,2=i2c (|-able)).");
-
-#define dprintk(level,x...) if (level & debug) printk(x)
-#define dbufout(b,l,m) {\
-	    int i; \
-	    for (i = 0; i < l; i++) \
-		m("%02x ",b[i]); \
-}
-#define deb_info(args...) dprintk(0x01,args)
-#define deb_i2c(args...)  dprintk(0x02,args)
-#define deb_hab(args...)  dprintk(0x04,args)
-
-/* transfer functions */
-static int bcm3510_writebytes (struct bcm3510_state *state, u8 reg, u8 *buf, u8 len)
-{
-	u8 b[256];
-	int err;
-	struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = b, .len = len + 1 };
-
-	b[0] = reg;
-	memcpy(&b[1],buf,len);
-
-	deb_i2c("i2c wr %02x: ",reg);
-	dbufout(buf,len,deb_i2c);
-	deb_i2c("\n");
-
-	if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
-
-		deb_info("%s: i2c write error (addr %02x, reg %02x, err == %i)\n",
-			__func__, state->config->demod_address, reg,  err);
-		return -EREMOTEIO;
-	}
-
-	return 0;
-}
-
-static int bcm3510_readbytes (struct bcm3510_state *state, u8 reg, u8 *buf, u8 len)
-{
-	struct i2c_msg msg[] = {
-		{ .addr = state->config->demod_address, .flags = 0,        .buf = &reg, .len = 1 },
-		{ .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = buf,  .len = len }
-	};
-	int err;
-
-	memset(buf,0,len);
-
-	if ((err = i2c_transfer (state->i2c, msg, 2)) != 2) {
-		deb_info("%s: i2c read error (addr %02x, reg %02x, err == %i)\n",
-			__func__, state->config->demod_address, reg,  err);
-		return -EREMOTEIO;
-	}
-	deb_i2c("i2c rd %02x: ",reg);
-	dbufout(buf,len,deb_i2c);
-	deb_i2c("\n");
-
-	return 0;
-}
-
-static int bcm3510_writeB(struct bcm3510_state *state, u8 reg, bcm3510_register_value v)
-{
-	return bcm3510_writebytes(state,reg,&v.raw,1);
-}
-
-static int bcm3510_readB(struct bcm3510_state *state, u8 reg, bcm3510_register_value *v)
-{
-	return bcm3510_readbytes(state,reg,&v->raw,1);
-}
-
-/* Host Access Buffer transfers */
-static int bcm3510_hab_get_response(struct bcm3510_state *st, u8 *buf, int len)
-{
-	bcm3510_register_value v;
-	int ret,i;
-
-	v.HABADR_a6.HABADR = 0;
-	if ((ret = bcm3510_writeB(st,0xa6,v)) < 0)
-		return ret;
-
-	for (i = 0; i < len; i++) {
-		if ((ret = bcm3510_readB(st,0xa7,&v)) < 0)
-			return ret;
-		buf[i] = v.HABDATA_a7;
-	}
-	return 0;
-}
-
-static int bcm3510_hab_send_request(struct bcm3510_state *st, u8 *buf, int len)
-{
-	bcm3510_register_value v,hab;
-	int ret,i;
-	unsigned long t;
-
-/* Check if any previous HAB request still needs to be serviced by the
- * Acquisition Processor before sending new request */
-	if ((ret = bcm3510_readB(st,0xa8,&v)) < 0)
-		return ret;
-	if (v.HABSTAT_a8.HABR) {
-		deb_info("HAB is running already - clearing it.\n");
-		v.HABSTAT_a8.HABR = 0;
-		bcm3510_writeB(st,0xa8,v);
-//		return -EBUSY;
-	}
-
-/* Send the start HAB Address (automatically incremented after write of
- * HABDATA) and write the HAB Data */
-	hab.HABADR_a6.HABADR = 0;
-	if ((ret = bcm3510_writeB(st,0xa6,hab)) < 0)
-		return ret;
-
-	for (i = 0; i < len; i++) {
-		hab.HABDATA_a7 = buf[i];
-		if ((ret = bcm3510_writeB(st,0xa7,hab)) < 0)
-			return ret;
-	}
-
-/* Set the HABR bit to indicate AP request in progress (LBHABR allows HABR to
- * be written) */
-	v.raw = 0; v.HABSTAT_a8.HABR = 1; v.HABSTAT_a8.LDHABR = 1;
-	if ((ret = bcm3510_writeB(st,0xa8,v)) < 0)
-		return ret;
-
-/* Polling method: Wait until the AP finishes processing the HAB request */
-	t = jiffies + 1*HZ;
-	while (time_before(jiffies, t)) {
-		deb_info("waiting for HAB to complete\n");
-		msleep(10);
-		if ((ret = bcm3510_readB(st,0xa8,&v)) < 0)
-			return ret;
-
-		if (!v.HABSTAT_a8.HABR)
-			return 0;
-	}
-
-	deb_info("send_request execution timed out.\n");
-	return -ETIMEDOUT;
-}
-
-static int bcm3510_do_hab_cmd(struct bcm3510_state *st, u8 cmd, u8 msgid, u8 *obuf, u8 olen, u8 *ibuf, u8 ilen)
-{
-	u8 ob[olen+2],ib[ilen+2];
-	int ret = 0;
-
-	ob[0] = cmd;
-	ob[1] = msgid;
-	memcpy(&ob[2],obuf,olen);
-
-	deb_hab("hab snd: ");
-	dbufout(ob,olen+2,deb_hab);
-	deb_hab("\n");
-
-	if (mutex_lock_interruptible(&st->hab_mutex) < 0)
-		return -EAGAIN;
-
-	if ((ret = bcm3510_hab_send_request(st, ob, olen+2)) < 0 ||
-		(ret = bcm3510_hab_get_response(st, ib, ilen+2)) < 0)
-		goto error;
-
-	deb_hab("hab get: ");
-	dbufout(ib,ilen+2,deb_hab);
-	deb_hab("\n");
-
-	memcpy(ibuf,&ib[2],ilen);
-error:
-	mutex_unlock(&st->hab_mutex);
-	return ret;
-}
-
-#if 0
-/* not needed, we use a semaphore to prevent HAB races */
-static int bcm3510_is_ap_ready(struct bcm3510_state *st)
-{
-	bcm3510_register_value ap,hab;
-	int ret;
-
-	if ((ret = bcm3510_readB(st,0xa8,&hab)) < 0 ||
-		(ret = bcm3510_readB(st,0xa2,&ap) < 0))
-		return ret;
-
-	if (ap.APSTAT1_a2.RESET || ap.APSTAT1_a2.IDLE || ap.APSTAT1_a2.STOP || hab.HABSTAT_a8.HABR) {
-		deb_info("AP is busy\n");
-		return -EBUSY;
-	}
-
-	return 0;
-}
-#endif
-
-static int bcm3510_bert_reset(struct bcm3510_state *st)
-{
-	bcm3510_register_value b;
-	int ret;
-
-	if ((ret = bcm3510_readB(st,0xfa,&b)) < 0)
-		return ret;
-
-	b.BERCTL_fa.RESYNC = 0; bcm3510_writeB(st,0xfa,b);
-	b.BERCTL_fa.RESYNC = 1; bcm3510_writeB(st,0xfa,b);
-	b.BERCTL_fa.RESYNC = 0; bcm3510_writeB(st,0xfa,b);
-	b.BERCTL_fa.CNTCTL = 1; b.BERCTL_fa.BITCNT = 1; bcm3510_writeB(st,0xfa,b);
-
-	/* clear residual bit counter TODO  */
-	return 0;
-}
-
-static int bcm3510_refresh_state(struct bcm3510_state *st)
-{
-	if (time_after(jiffies,st->next_status_check)) {
-		bcm3510_do_hab_cmd(st, CMD_STATUS, MSGID_STATUS1, NULL,0, (u8 *)&st->status1, sizeof(st->status1));
-		bcm3510_do_hab_cmd(st, CMD_STATUS, MSGID_STATUS2, NULL,0, (u8 *)&st->status2, sizeof(st->status2));
-		st->next_status_check = jiffies + (st->status_check_interval*HZ)/1000;
-	}
-	return 0;
-}
-
-static int bcm3510_read_status(struct dvb_frontend *fe, fe_status_t *status)
-{
-	struct bcm3510_state* st = fe->demodulator_priv;
-	bcm3510_refresh_state(st);
-
-	*status = 0;
-	if (st->status1.STATUS1.RECEIVER_LOCK)
-		*status |= FE_HAS_LOCK | FE_HAS_SYNC;
-
-	if (st->status1.STATUS1.FEC_LOCK)
-		*status |= FE_HAS_VITERBI;
-
-	if (st->status1.STATUS1.OUT_PLL_LOCK)
-		*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER;
-
-	if (*status & FE_HAS_LOCK)
-		st->status_check_interval = 1500;
-	else /* more frequently checks if no lock has been achieved yet */
-		st->status_check_interval = 500;
-
-	deb_info("real_status: %02x\n",*status);
-	return 0;
-}
-
-static int bcm3510_read_ber(struct dvb_frontend* fe, u32* ber)
-{
-	struct bcm3510_state* st = fe->demodulator_priv;
-	bcm3510_refresh_state(st);
-
-	*ber = (st->status2.LDBER0 << 16) | (st->status2.LDBER1 << 8) | st->status2.LDBER2;
-	return 0;
-}
-
-static int bcm3510_read_unc(struct dvb_frontend* fe, u32* unc)
-{
-	struct bcm3510_state* st = fe->demodulator_priv;
-	bcm3510_refresh_state(st);
-	*unc = (st->status2.LDUERC0 << 8) | st->status2.LDUERC1;
-	return 0;
-}
-
-static int bcm3510_read_signal_strength(struct dvb_frontend* fe, u16* strength)
-{
-	struct bcm3510_state* st = fe->demodulator_priv;
-	s32 t;
-
-	bcm3510_refresh_state(st);
-	t = st->status2.SIGNAL;
-
-	if (t > 190)
-		t = 190;
-	if (t < 90)
-		t = 90;
-
-	t -= 90;
-	t = t * 0xff / 100;
-	/* normalize if necessary */
-	*strength = (t << 8) | t;
-	return 0;
-}
-
-static int bcm3510_read_snr(struct dvb_frontend* fe, u16* snr)
-{
-	struct bcm3510_state* st = fe->demodulator_priv;
-	bcm3510_refresh_state(st);
-
-	*snr = st->status1.SNR_EST0*1000 + ((st->status1.SNR_EST1*1000) >> 8);
-	return 0;
-}
-
-/* tuner frontend programming */
-static int bcm3510_tuner_cmd(struct bcm3510_state* st,u8 bc, u16 n, u8 a)
-{
-	struct bcm3510_hab_cmd_tune c;
-	memset(&c,0,sizeof(struct bcm3510_hab_cmd_tune));
-
-/* I2C Mode disabled,  set 16 control / Data pairs */
-	c.length = 0x10;
-	c.clock_width = 0;
-/* CS1, CS0, DATA, CLK bits control the tuner RF_AGC_SEL pin is set to
- * logic high (as Configuration) */
-	c.misc = 0x10;
-/* Set duration of the initial state of TUNCTL = 3.34 micro Sec */
-	c.TUNCTL_state = 0x40;
-
-/* PRESCALER DIVIDE RATIO | BC1_2_3_4; (band switch), 1stosc REFERENCE COUNTER REF_S12 and REF_S11 */
-	c.ctl_dat[0].ctrl.size = BITS_8;
-	c.ctl_dat[0].data      = 0x80 | bc;
-
-/* Control DATA pin, 1stosc REFERENCE COUNTER REF_S10 to REF_S3 */
-	c.ctl_dat[1].ctrl.size = BITS_8;
-	c.ctl_dat[1].data      = 4;
-
-/* set CONTROL BIT 1 to 1, 1stosc REFERENCE COUNTER REF_S2 to REF_S1 */
-	c.ctl_dat[2].ctrl.size = BITS_3;
-	c.ctl_dat[2].data      = 0x20;
-
-/* control CS0 pin, pulse byte ? */
-	c.ctl_dat[3].ctrl.size = BITS_3;
-	c.ctl_dat[3].ctrl.clk_off = 1;
-	c.ctl_dat[3].ctrl.cs0  = 1;
-	c.ctl_dat[3].data      = 0x40;
-
-/* PGM_S18 to PGM_S11 */
-	c.ctl_dat[4].ctrl.size = BITS_8;
-	c.ctl_dat[4].data      = n >> 3;
-
-/* PGM_S10 to PGM_S8, SWL_S7 to SWL_S3 */
-	c.ctl_dat[5].ctrl.size = BITS_8;
-	c.ctl_dat[5].data      = ((n & 0x7) << 5) | (a >> 2);
-
-/* SWL_S2 and SWL_S1, set CONTROL BIT 2 to 0 */
-	c.ctl_dat[6].ctrl.size = BITS_3;
-	c.ctl_dat[6].data      = (a << 6) & 0xdf;
-
-/* control CS0 pin, pulse byte ? */
-	c.ctl_dat[7].ctrl.size = BITS_3;
-	c.ctl_dat[7].ctrl.clk_off = 1;
-	c.ctl_dat[7].ctrl.cs0  = 1;
-	c.ctl_dat[7].data      = 0x40;
-
-/* PRESCALER DIVIDE RATIO, 2ndosc REFERENCE COUNTER REF_S12 and REF_S11 */
-	c.ctl_dat[8].ctrl.size = BITS_8;
-	c.ctl_dat[8].data      = 0x80;
-
-/* 2ndosc REFERENCE COUNTER REF_S10 to REF_S3 */
-	c.ctl_dat[9].ctrl.size = BITS_8;
-	c.ctl_dat[9].data      = 0x10;
-
-/* set CONTROL BIT 1 to 1, 2ndosc REFERENCE COUNTER REF_S2 to REF_S1 */
-	c.ctl_dat[10].ctrl.size = BITS_3;
-	c.ctl_dat[10].data      = 0x20;
-
-/* pulse byte */
-	c.ctl_dat[11].ctrl.size = BITS_3;
-	c.ctl_dat[11].ctrl.clk_off = 1;
-	c.ctl_dat[11].ctrl.cs1  = 1;
-	c.ctl_dat[11].data      = 0x40;
-
-/* PGM_S18 to PGM_S11 */
-	c.ctl_dat[12].ctrl.size = BITS_8;
-	c.ctl_dat[12].data      = 0x2a;
-
-/* PGM_S10 to PGM_S8 and SWL_S7 to SWL_S3 */
-	c.ctl_dat[13].ctrl.size = BITS_8;
-	c.ctl_dat[13].data      = 0x8e;
-
-/* SWL_S2 and SWL_S1 and set CONTROL BIT 2 to 0 */
-	c.ctl_dat[14].ctrl.size = BITS_3;
-	c.ctl_dat[14].data      = 0;
-
-/* Pulse Byte */
-	c.ctl_dat[15].ctrl.size = BITS_3;
-	c.ctl_dat[15].ctrl.clk_off = 1;
-	c.ctl_dat[15].ctrl.cs1  = 1;
-	c.ctl_dat[15].data      = 0x40;
-
-	return bcm3510_do_hab_cmd(st,CMD_TUNE, MSGID_TUNE,(u8 *) &c,sizeof(c), NULL, 0);
-}
-
-static int bcm3510_set_freq(struct bcm3510_state* st,u32 freq)
-{
-	u8 bc,a;
-	u16 n;
-	s32 YIntercept,Tfvco1;
-
-	freq /= 1000;
-
-	deb_info("%dkHz:",freq);
-	/* set Band Switch */
-	if (freq <= 168000)
-		bc = 0x1c;
-	else if (freq <= 378000)
-		bc = 0x2c;
-	else
-		bc = 0x30;
-
-	if (freq >= 470000) {
-		freq -= 470001;
-		YIntercept = 18805;
-	} else if (freq >= 90000) {
-		freq -= 90001;
-		YIntercept = 15005;
-	} else if (freq >= 76000){
-		freq -= 76001;
-		YIntercept = 14865;
-	} else {
-		freq -= 54001;
-		YIntercept = 14645;
-	}
-
-	Tfvco1 = (((freq/6000)*60 + YIntercept)*4)/10;
-
-	n = Tfvco1 >> 6;
-	a = Tfvco1 & 0x3f;
-
-	deb_info(" BC1_2_3_4: %x, N: %x A: %x\n", bc, n, a);
-	if (n >= 16 && n <= 2047)
-		return bcm3510_tuner_cmd(st,bc,n,a);
-
-	return -EINVAL;
-}
-
-static int bcm3510_set_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	struct bcm3510_state* st = fe->demodulator_priv;
-	struct bcm3510_hab_cmd_ext_acquire cmd;
-	struct bcm3510_hab_cmd_bert_control bert;
-	int ret;
-
-	memset(&cmd,0,sizeof(cmd));
-	switch (c->modulation) {
-		case QAM_256:
-			cmd.ACQUIRE0.MODE = 0x1;
-			cmd.ACQUIRE1.SYM_RATE = 0x1;
-			cmd.ACQUIRE1.IF_FREQ = 0x1;
-			break;
-		case QAM_64:
-			cmd.ACQUIRE0.MODE = 0x2;
-			cmd.ACQUIRE1.SYM_RATE = 0x2;
-			cmd.ACQUIRE1.IF_FREQ = 0x1;
-			break;
-#if 0
-		case QAM_256:
-			cmd.ACQUIRE0.MODE = 0x3;
-			break;
-		case QAM_128:
-			cmd.ACQUIRE0.MODE = 0x4;
-			break;
-		case QAM_64:
-			cmd.ACQUIRE0.MODE = 0x5;
-			break;
-		case QAM_32:
-			cmd.ACQUIRE0.MODE = 0x6;
-			break;
-		case QAM_16:
-			cmd.ACQUIRE0.MODE = 0x7;
-			break;
-#endif
-		case VSB_8:
-			cmd.ACQUIRE0.MODE = 0x8;
-			cmd.ACQUIRE1.SYM_RATE = 0x0;
-			cmd.ACQUIRE1.IF_FREQ = 0x0;
-			break;
-		case VSB_16:
-			cmd.ACQUIRE0.MODE = 0x9;
-			cmd.ACQUIRE1.SYM_RATE = 0x0;
-			cmd.ACQUIRE1.IF_FREQ = 0x0;
-		default:
-			return -EINVAL;
-	};
-	cmd.ACQUIRE0.OFFSET = 0;
-	cmd.ACQUIRE0.NTSCSWEEP = 1;
-	cmd.ACQUIRE0.FA = 1;
-	cmd.ACQUIRE0.BW = 0;
-
-/*	if (enableOffset) {
-		cmd.IF_OFFSET0 = xx;
-		cmd.IF_OFFSET1 = xx;
-
-		cmd.SYM_OFFSET0 = xx;
-		cmd.SYM_OFFSET1 = xx;
-		if (enableNtscSweep) {
-			cmd.NTSC_OFFSET0;
-			cmd.NTSC_OFFSET1;
-		}
-	} */
-	bcm3510_do_hab_cmd(st, CMD_ACQUIRE, MSGID_EXT_TUNER_ACQUIRE, (u8 *) &cmd, sizeof(cmd), NULL, 0);
-
-/* doing it with different MSGIDs, data book and source differs */
-	bert.BE = 0;
-	bert.unused = 0;
-	bcm3510_do_hab_cmd(st, CMD_STATE_CONTROL, MSGID_BERT_CONTROL, (u8 *) &bert, sizeof(bert), NULL, 0);
-	bcm3510_do_hab_cmd(st, CMD_STATE_CONTROL, MSGID_BERT_SET, (u8 *) &bert, sizeof(bert), NULL, 0);
-
-	bcm3510_bert_reset(st);
-
-	ret = bcm3510_set_freq(st, c->frequency);
-	if (ret < 0)
-		return ret;
-
-	memset(&st->status1,0,sizeof(st->status1));
-	memset(&st->status2,0,sizeof(st->status2));
-	st->status_check_interval = 500;
-
-/* Give the AP some time */
-	msleep(200);
-
-	return 0;
-}
-
-static int bcm3510_sleep(struct dvb_frontend* fe)
-{
-	return 0;
-}
-
-static int bcm3510_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings *s)
-{
-	s->min_delay_ms = 1000;
-	s->step_size = 0;
-	s->max_drift = 0;
-	return 0;
-}
-
-static void bcm3510_release(struct dvb_frontend* fe)
-{
-	struct bcm3510_state* state = fe->demodulator_priv;
-	kfree(state);
-}
-
-/* firmware download:
- * firmware file is build up like this:
- * 16bit addr, 16bit length, 8byte of length
- */
-#define BCM3510_DEFAULT_FIRMWARE "dvb-fe-bcm3510-01.fw"
-
-static int bcm3510_write_ram(struct bcm3510_state *st, u16 addr, const u8 *b,
-			     u16 len)
-{
-	int ret = 0,i;
-	bcm3510_register_value vH, vL,vD;
-
-	vH.MADRH_a9 = addr >> 8;
-	vL.MADRL_aa = addr;
-	if ((ret = bcm3510_writeB(st,0xa9,vH)) < 0) return ret;
-	if ((ret = bcm3510_writeB(st,0xaa,vL)) < 0) return ret;
-
-	for (i = 0; i < len; i++) {
-		vD.MDATA_ab = b[i];
-		if ((ret = bcm3510_writeB(st,0xab,vD)) < 0)
-			return ret;
-	}
-
-	return 0;
-}
-
-static int bcm3510_download_firmware(struct dvb_frontend* fe)
-{
-	struct bcm3510_state* st = fe->demodulator_priv;
-	const struct firmware *fw;
-	u16 addr,len;
-	const u8 *b;
-	int ret,i;
-
-	deb_info("requesting firmware\n");
-	if ((ret = st->config->request_firmware(fe, &fw, BCM3510_DEFAULT_FIRMWARE)) < 0) {
-		err("could not load firmware (%s): %d",BCM3510_DEFAULT_FIRMWARE,ret);
-		return ret;
-	}
-	deb_info("got firmware: %zd\n",fw->size);
-
-	b = fw->data;
-	for (i = 0; i < fw->size;) {
-		addr = le16_to_cpu( *( (u16 *)&b[i] ) );
-		len  = le16_to_cpu( *( (u16 *)&b[i+2] ) );
-		deb_info("firmware chunk, addr: 0x%04x, len: 0x%04x, total length: 0x%04zx\n",addr,len,fw->size);
-		if ((ret = bcm3510_write_ram(st,addr,&b[i+4],len)) < 0) {
-			err("firmware download failed: %d\n",ret);
-			return ret;
-		}
-		i += 4 + len;
-	}
-	release_firmware(fw);
-	deb_info("firmware download successfully completed\n");
-	return 0;
-}
-
-static int bcm3510_check_firmware_version(struct bcm3510_state *st)
-{
-	struct bcm3510_hab_cmd_get_version_info ver;
-	bcm3510_do_hab_cmd(st,CMD_GET_VERSION_INFO,MSGID_GET_VERSION_INFO,NULL,0,(u8*)&ver,sizeof(ver));
-
-	deb_info("Version information: 0x%02x 0x%02x 0x%02x 0x%02x\n",
-		ver.microcode_version, ver.script_version, ver.config_version, ver.demod_version);
-
-	if (ver.script_version == BCM3510_DEF_SCRIPT_VERSION &&
-		ver.config_version == BCM3510_DEF_CONFIG_VERSION &&
-		ver.demod_version  == BCM3510_DEF_DEMOD_VERSION)
-		return 0;
-
-	deb_info("version check failed\n");
-	return -ENODEV;
-}
-
-/* (un)resetting the AP */
-static int bcm3510_reset(struct bcm3510_state *st)
-{
-	int ret;
-	unsigned long  t;
-	bcm3510_register_value v;
-
-	bcm3510_readB(st,0xa0,&v); v.HCTL1_a0.RESET = 1;
-	if ((ret = bcm3510_writeB(st,0xa0,v)) < 0)
-		return ret;
-
-    t = jiffies + 3*HZ;
-	while (time_before(jiffies, t)) {
-		msleep(10);
-		if ((ret = bcm3510_readB(st,0xa2,&v)) < 0)
-			return ret;
-
-		if (v.APSTAT1_a2.RESET)
-			return 0;
-	}
-	deb_info("reset timed out\n");
-	return -ETIMEDOUT;
-}
-
-static int bcm3510_clear_reset(struct bcm3510_state *st)
-{
-	bcm3510_register_value v;
-	int ret;
-	unsigned long t;
-
-	v.raw = 0;
-	if ((ret = bcm3510_writeB(st,0xa0,v)) < 0)
-		return ret;
-
-    t = jiffies + 3*HZ;
-	while (time_before(jiffies, t)) {
-		msleep(10);
-		if ((ret = bcm3510_readB(st,0xa2,&v)) < 0)
-			return ret;
-
-		/* verify that reset is cleared */
-		if (!v.APSTAT1_a2.RESET)
-			return 0;
-	}
-	deb_info("reset clear timed out\n");
-	return -ETIMEDOUT;
-}
-
-static int bcm3510_init_cold(struct bcm3510_state *st)
-{
-	int ret;
-	bcm3510_register_value v;
-
-	/* read Acquisation Processor status register and check it is not in RUN mode */
-	if ((ret = bcm3510_readB(st,0xa2,&v)) < 0)
-		return ret;
-	if (v.APSTAT1_a2.RUN) {
-		deb_info("AP is already running - firmware already loaded.\n");
-		return 0;
-	}
-
-	deb_info("reset?\n");
-	if ((ret = bcm3510_reset(st)) < 0)
-		return ret;
-
-	deb_info("tristate?\n");
-	/* tri-state */
-	v.TSTCTL_2e.CTL = 0;
-	if ((ret = bcm3510_writeB(st,0x2e,v)) < 0)
-		return ret;
-
-	deb_info("firmware?\n");
-	if ((ret = bcm3510_download_firmware(&st->frontend)) < 0 ||
-		(ret = bcm3510_clear_reset(st)) < 0)
-		return ret;
-
-	/* anything left here to Let the acquisition processor begin execution at program counter 0000 ??? */
-
-	return 0;
-}
-
-static int bcm3510_init(struct dvb_frontend* fe)
-{
-	struct bcm3510_state* st = fe->demodulator_priv;
-	bcm3510_register_value j;
-	struct bcm3510_hab_cmd_set_agc c;
-	int ret;
-
-	if ((ret = bcm3510_readB(st,0xca,&j)) < 0)
-		return ret;
-
-	deb_info("JDEC: %02x\n",j.raw);
-
-	switch (j.JDEC_ca.JDEC) {
-		case JDEC_WAIT_AT_RAM:
-			deb_info("attempting to download firmware\n");
-			if ((ret = bcm3510_init_cold(st)) < 0)
-				return ret;
-		case JDEC_EEPROM_LOAD_WAIT: /* fall-through is wanted */
-			deb_info("firmware is loaded\n");
-			bcm3510_check_firmware_version(st);
-			break;
-		default:
-			return -ENODEV;
-	}
-
-	memset(&c,0,1);
-	c.SEL = 1;
-	bcm3510_do_hab_cmd(st,CMD_AUTO_PARAM,MSGID_SET_RF_AGC_SEL,(u8 *)&c,sizeof(c),NULL,0);
-
-	return 0;
-}
-
-
-static struct dvb_frontend_ops bcm3510_ops;
-
-struct dvb_frontend* bcm3510_attach(const struct bcm3510_config *config,
-				   struct i2c_adapter *i2c)
-{
-	struct bcm3510_state* state = NULL;
-	int ret;
-	bcm3510_register_value v;
-
-	/* allocate memory for the internal state */
-	state = kzalloc(sizeof(struct bcm3510_state), GFP_KERNEL);
-	if (state == NULL)
-		goto error;
-
-	/* setup the state */
-
-	state->config = config;
-	state->i2c = i2c;
-
-	/* create dvb_frontend */
-	memcpy(&state->frontend.ops, &bcm3510_ops, sizeof(struct dvb_frontend_ops));
-	state->frontend.demodulator_priv = state;
-
-	mutex_init(&state->hab_mutex);
-
-	if ((ret = bcm3510_readB(state,0xe0,&v)) < 0)
-		goto error;
-
-	deb_info("Revision: 0x%1x, Layer: 0x%1x.\n",v.REVID_e0.REV,v.REVID_e0.LAYER);
-
-	if ((v.REVID_e0.REV != 0x1 && v.REVID_e0.LAYER != 0xb) && /* cold */
-		(v.REVID_e0.REV != 0x8 && v.REVID_e0.LAYER != 0x0))   /* warm */
-		goto error;
-
-	info("Revision: 0x%1x, Layer: 0x%1x.",v.REVID_e0.REV,v.REVID_e0.LAYER);
-
-	bcm3510_reset(state);
-
-	return &state->frontend;
-
-error:
-	kfree(state);
-	return NULL;
-}
-EXPORT_SYMBOL(bcm3510_attach);
-
-static struct dvb_frontend_ops bcm3510_ops = {
-	.delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
-	.info = {
-		.name = "Broadcom BCM3510 VSB/QAM frontend",
-		.frequency_min =  54000000,
-		.frequency_max = 803000000,
-		/* stepsize is just a guess */
-		.frequency_stepsize = 0,
-		.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_FEC_AUTO |
-			FE_CAN_8VSB | FE_CAN_16VSB |
-			FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_128 | FE_CAN_QAM_256
-	},
-
-	.release = bcm3510_release,
-
-	.init = bcm3510_init,
-	.sleep = bcm3510_sleep,
-
-	.set_frontend = bcm3510_set_frontend,
-	.get_tune_settings = bcm3510_get_tune_settings,
-
-	.read_status = bcm3510_read_status,
-	.read_ber = bcm3510_read_ber,
-	.read_signal_strength = bcm3510_read_signal_strength,
-	.read_snr = bcm3510_read_snr,
-	.read_ucblocks = bcm3510_read_unc,
-};
-
-MODULE_DESCRIPTION("Broadcom BCM3510 ATSC (8VSB/16VSB & ITU J83 AnnexB FEC QAM64/256) demodulator driver");
-MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/bcm3510.h b/drivers/media/dvb/frontends/bcm3510.h
deleted file mode 100644
index f4575c0..0000000
--- a/drivers/media/dvb/frontends/bcm3510.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Support for the Broadcom BCM3510 ATSC demodulator (1st generation Air2PC)
- *
- *  Copyright (C) 2001-5, B2C2 inc.
- *
- *  GPL/Linux driver written by Patrick Boettcher <patrick.boettcher@desy.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 BCM3510_H
-#define BCM3510_H
-
-#include <linux/dvb/frontend.h>
-#include <linux/firmware.h>
-
-struct bcm3510_config
-{
-	/* the demodulator's i2c address */
-	u8 demod_address;
-
-	/* request firmware for device */
-	int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name);
-};
-
-#if defined(CONFIG_DVB_BCM3510) || (defined(CONFIG_DVB_BCM3510_MODULE) && defined(MODULE))
-extern struct dvb_frontend* bcm3510_attach(const struct bcm3510_config* config,
-					   struct i2c_adapter* i2c);
-#else
-static inline struct dvb_frontend* bcm3510_attach(const struct bcm3510_config* config,
-						  struct i2c_adapter* i2c)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif // CONFIG_DVB_BCM3510
-
-#endif
diff --git a/drivers/media/dvb/frontends/bcm3510_priv.h b/drivers/media/dvb/frontends/bcm3510_priv.h
deleted file mode 100644
index 3bb1bc2..0000000
--- a/drivers/media/dvb/frontends/bcm3510_priv.h
+++ /dev/null
@@ -1,460 +0,0 @@
-/*
- * Support for the Broadcom BCM3510 ATSC demodulator (1st generation Air2PC)
- *
- *  Copyright (C) 2001-5, B2C2 inc.
- *
- *  GPL/Linux driver written by Patrick Boettcher <patrick.boettcher@desy.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 __BCM3510_PRIV_H__
-#define __BCM3510_PRIV_H__
-
-#define PACKED __attribute__((packed))
-
-#undef err
-#define err(format, arg...)  printk(KERN_ERR     "bcm3510: " format "\n" , ## arg)
-#undef info
-#define info(format, arg...) printk(KERN_INFO    "bcm3510: " format "\n" , ## arg)
-#undef warn
-#define warn(format, arg...) printk(KERN_WARNING "bcm3510: " format "\n" , ## arg)
-
-
-#define PANASONIC_FIRST_IF_BASE_IN_KHz  1407500
-#define BCM3510_SYMBOL_RATE             5381000
-
-typedef union {
-	u8 raw;
-
-	struct {
-		u8 CTL   :8;
-	} TSTCTL_2e;
-
-	u8 LDCERC_4e;
-	u8 LDUERC_4f;
-	u8 LD_BER0_65;
-	u8 LD_BER1_66;
-	u8 LD_BER2_67;
-	u8 LD_BER3_68;
-
-	struct {
-		u8 RESET :1;
-		u8 IDLE  :1;
-		u8 STOP  :1;
-		u8 HIRQ0 :1;
-		u8 HIRQ1 :1;
-		u8 na0   :1;
-		u8 HABAV :1;
-		u8 na1   :1;
-	} HCTL1_a0;
-
-	struct {
-		u8 na0    :1;
-		u8 IDLMSK :1;
-		u8 STMSK  :1;
-		u8 I0MSK  :1;
-		u8 I1MSK  :1;
-		u8 na1    :1;
-		u8 HABMSK :1;
-		u8 na2    :1;
-	} HCTLMSK_a1;
-
-	struct {
-		u8 RESET  :1;
-		u8 IDLE   :1;
-		u8 STOP   :1;
-		u8 RUN    :1;
-		u8 HABAV  :1;
-		u8 MEMAV  :1;
-		u8 ALDONE :1;
-		u8 REIRQ  :1;
-	} APSTAT1_a2;
-
-	struct {
-		u8 RSTMSK :1;
-		u8 IMSK   :1;
-		u8 SMSK   :1;
-		u8 RMSK   :1;
-		u8 HABMSK :1;
-		u8 MAVMSK :1;
-		u8 ALDMSK :1;
-		u8 REMSK  :1;
-	} APMSK1_a3;
-
-	u8 APSTAT2_a4;
-	u8 APMSK2_a5;
-
-	struct {
-		u8 HABADR :7;
-		u8 na     :1;
-	} HABADR_a6;
-
-	u8 HABDATA_a7;
-
-	struct {
-		u8 HABR   :1;
-		u8 LDHABR :1;
-		u8 APMSK  :1;
-		u8 HMSK   :1;
-		u8 LDMSK  :1;
-		u8 na     :3;
-	} HABSTAT_a8;
-
-	u8 MADRH_a9;
-	u8 MADRL_aa;
-	u8 MDATA_ab;
-
-	struct {
-#define JDEC_WAIT_AT_RAM      0x7
-#define JDEC_EEPROM_LOAD_WAIT 0x4
-		u8 JDEC   :3;
-		u8 na     :5;
-	} JDEC_ca;
-
-	struct {
-		u8 REV   :4;
-		u8 LAYER :4;
-	} REVID_e0;
-
-	struct {
-		u8 unk0   :1;
-		u8 CNTCTL :1;
-		u8 BITCNT :1;
-		u8 unk1   :1;
-		u8 RESYNC :1;
-		u8 unk2   :3;
-	} BERCTL_fa;
-
-	struct {
-		u8 CSEL0  :1;
-		u8 CLKED0 :1;
-		u8 CSEL1  :1;
-		u8 CLKED1 :1;
-		u8 CLKLEV :1;
-		u8 SPIVAR :1;
-		u8 na     :2;
-	} TUNSET_fc;
-
-	struct {
-		u8 CLK    :1;
-		u8 DATA   :1;
-		u8 CS0    :1;
-		u8 CS1    :1;
-		u8 AGCSEL :1;
-		u8 na0    :1;
-		u8 TUNSEL :1;
-		u8 na1    :1;
-	} TUNCTL_fd;
-
-	u8 TUNSEL0_fe;
-	u8 TUNSEL1_ff;
-
-} bcm3510_register_value;
-
-/* HAB commands */
-
-/* version */
-#define CMD_GET_VERSION_INFO   0x3D
-#define MSGID_GET_VERSION_INFO 0x15
-struct bcm3510_hab_cmd_get_version_info {
-	u8 microcode_version;
-	u8 script_version;
-	u8 config_version;
-	u8 demod_version;
-} PACKED;
-
-#define BCM3510_DEF_MICROCODE_VERSION 0x0E
-#define BCM3510_DEF_SCRIPT_VERSION    0x06
-#define BCM3510_DEF_CONFIG_VERSION    0x01
-#define BCM3510_DEF_DEMOD_VERSION     0xB1
-
-/* acquire */
-#define CMD_ACQUIRE            0x38
-
-#define MSGID_EXT_TUNER_ACQUIRE 0x0A
-struct bcm3510_hab_cmd_ext_acquire {
-	struct {
-		u8 MODE      :4;
-		u8 BW        :1;
-		u8 FA        :1;
-		u8 NTSCSWEEP :1;
-		u8 OFFSET    :1;
-	} PACKED ACQUIRE0; /* control_byte */
-
-	struct {
-		u8 IF_FREQ  :3;
-		u8 zero0    :1;
-		u8 SYM_RATE :3;
-		u8 zero1    :1;
-	} PACKED ACQUIRE1; /* sym_if */
-
-	u8 IF_OFFSET0;   /* IF_Offset_10hz */
-	u8 IF_OFFSET1;
-	u8 SYM_OFFSET0;  /* SymbolRateOffset */
-	u8 SYM_OFFSET1;
-	u8 NTSC_OFFSET0; /* NTSC_Offset_10hz */
-	u8 NTSC_OFFSET1;
-} PACKED;
-
-#define MSGID_INT_TUNER_ACQUIRE 0x0B
-struct bcm3510_hab_cmd_int_acquire {
-	struct {
-		u8 MODE      :4;
-		u8 BW        :1;
-		u8 FA        :1;
-		u8 NTSCSWEEP :1;
-		u8 OFFSET    :1;
-	} PACKED ACQUIRE0; /* control_byte */
-
-	struct {
-		u8 IF_FREQ  :3;
-		u8 zero0    :1;
-		u8 SYM_RATE :3;
-		u8 zero1    :1;
-	} PACKED ACQUIRE1; /* sym_if */
-
-	u8 TUNER_FREQ0;
-	u8 TUNER_FREQ1;
-	u8 TUNER_FREQ2;
-	u8 TUNER_FREQ3;
-	u8 IF_OFFSET0;   /* IF_Offset_10hz */
-	u8 IF_OFFSET1;
-	u8 SYM_OFFSET0;  /* SymbolRateOffset */
-	u8 SYM_OFFSET1;
-	u8 NTSC_OFFSET0; /* NTSC_Offset_10hz */
-	u8 NTSC_OFFSET1;
-} PACKED;
-
-/* modes */
-#define BCM3510_QAM16           =   0x01
-#define BCM3510_QAM32           =   0x02
-#define BCM3510_QAM64           =   0x03
-#define BCM3510_QAM128          =   0x04
-#define BCM3510_QAM256          =   0x05
-#define BCM3510_8VSB            =   0x0B
-#define BCM3510_16VSB           =   0x0D
-
-/* IF_FREQS */
-#define BCM3510_IF_TERRESTRIAL 0x0
-#define BCM3510_IF_CABLE       0x1
-#define BCM3510_IF_USE_CMD     0x7
-
-/* SYM_RATE */
-#define BCM3510_SR_8VSB        0x0 /* 5381119 s/sec */
-#define BCM3510_SR_256QAM      0x1 /* 5360537 s/sec */
-#define BCM3510_SR_16QAM       0x2 /* 5056971 s/sec */
-#define BCM3510_SR_MISC        0x3 /* 5000000 s/sec */
-#define BCM3510_SR_USE_CMD     0x7
-
-/* special symbol rate */
-#define CMD_SET_VALUE_NOT_LISTED  0x2d
-#define MSGID_SET_SYMBOL_RATE_NOT_LISTED 0x0c
-struct bcm3510_hab_cmd_set_sr_not_listed {
-	u8 HOST_SYM_RATE0;
-	u8 HOST_SYM_RATE1;
-	u8 HOST_SYM_RATE2;
-	u8 HOST_SYM_RATE3;
-} PACKED;
-
-/* special IF */
-#define MSGID_SET_IF_FREQ_NOT_LISTED 0x0d
-struct bcm3510_hab_cmd_set_if_freq_not_listed {
-	u8 HOST_IF_FREQ0;
-	u8 HOST_IF_FREQ1;
-	u8 HOST_IF_FREQ2;
-	u8 HOST_IF_FREQ3;
-} PACKED;
-
-/* auto reacquire */
-#define CMD_AUTO_PARAM       0x2a
-#define MSGID_AUTO_REACQUIRE 0x0e
-struct bcm3510_hab_cmd_auto_reacquire {
-	u8 ACQ    :1; /* on/off*/
-	u8 unused :7;
-} PACKED;
-
-#define MSGID_SET_RF_AGC_SEL 0x12
-struct bcm3510_hab_cmd_set_agc {
-	u8 LVL    :1;
-	u8 unused :6;
-	u8 SEL    :1;
-} PACKED;
-
-#define MSGID_SET_AUTO_INVERSION 0x14
-struct bcm3510_hab_cmd_auto_inversion {
-	u8 AI     :1;
-	u8 unused :7;
-} PACKED;
-
-
-/* bert control */
-#define CMD_STATE_CONTROL  0x12
-#define MSGID_BERT_CONTROL 0x0e
-#define MSGID_BERT_SET     0xfa
-struct bcm3510_hab_cmd_bert_control {
-	u8 BE     :1;
-	u8 unused :7;
-} PACKED;
-
-#define MSGID_TRI_STATE 0x2e
-struct bcm3510_hab_cmd_tri_state {
-	u8 RE :1; /* a/d ram port pins */
-	u8 PE :1; /* baud clock pin */
-	u8 AC :1; /* a/d clock pin */
-	u8 BE :1; /* baud clock pin */
-	u8 unused :4;
-} PACKED;
-
-
-/* tune */
-#define CMD_TUNE   0x38
-#define MSGID_TUNE 0x16
-struct bcm3510_hab_cmd_tune_ctrl_data_pair {
-	struct {
-#define BITS_8 0x07
-#define BITS_7 0x06
-#define BITS_6 0x05
-#define BITS_5 0x04
-#define BITS_4 0x03
-#define BITS_3 0x02
-#define BITS_2 0x01
-#define BITS_1 0x00
-		u8 size    :3;
-		u8 unk     :2;
-		u8 clk_off :1;
-		u8 cs0     :1;
-		u8 cs1     :1;
-
-	} PACKED ctrl;
-
-	u8 data;
-} PACKED;
-
-struct bcm3510_hab_cmd_tune {
-	u8 length;
-	u8 clock_width;
-	u8 misc;
-	u8 TUNCTL_state;
-
-	struct bcm3510_hab_cmd_tune_ctrl_data_pair ctl_dat[16];
-} PACKED;
-
-#define CMD_STATUS    0x38
-#define MSGID_STATUS1 0x08
-struct bcm3510_hab_cmd_status1 {
-	struct {
-		u8 EQ_MODE       :4;
-		u8 reserved      :2;
-		u8 QRE           :1; /* if QSE and the spectrum is inversed */
-		u8 QSE           :1; /* automatic spectral inversion */
-	} PACKED STATUS0;
-
-	struct {
-		u8 RECEIVER_LOCK :1;
-		u8 FEC_LOCK      :1;
-		u8 OUT_PLL_LOCK  :1;
-		u8 reserved      :5;
-	} PACKED STATUS1;
-
-	struct {
-		u8 reserved      :2;
-		u8 BW            :1;
-		u8 NTE           :1; /* NTSC filter sweep enabled */
-		u8 AQI           :1; /* currently acquiring */
-		u8 FA            :1; /* fast acquisition */
-		u8 ARI           :1; /* auto reacquire */
-		u8 TI            :1; /* programming the tuner */
-	} PACKED STATUS2;
-	u8 STATUS3;
-	u8 SNR_EST0;
-	u8 SNR_EST1;
-	u8 TUNER_FREQ0;
-	u8 TUNER_FREQ1;
-	u8 TUNER_FREQ2;
-	u8 TUNER_FREQ3;
-	u8 SYM_RATE0;
-	u8 SYM_RATE1;
-	u8 SYM_RATE2;
-	u8 SYM_RATE3;
-	u8 SYM_OFFSET0;
-	u8 SYM_OFFSET1;
-	u8 SYM_ERROR0;
-	u8 SYM_ERROR1;
-	u8 IF_FREQ0;
-	u8 IF_FREQ1;
-	u8 IF_FREQ2;
-	u8 IF_FREQ3;
-	u8 IF_OFFSET0;
-	u8 IF_OFFSET1;
-	u8 IF_ERROR0;
-	u8 IF_ERROR1;
-	u8 NTSC_FILTER0;
-	u8 NTSC_FILTER1;
-	u8 NTSC_FILTER2;
-	u8 NTSC_FILTER3;
-	u8 NTSC_OFFSET0;
-	u8 NTSC_OFFSET1;
-	u8 NTSC_ERROR0;
-	u8 NTSC_ERROR1;
-	u8 INT_AGC_LEVEL0;
-	u8 INT_AGC_LEVEL1;
-	u8 EXT_AGC_LEVEL0;
-	u8 EXT_AGC_LEVEL1;
-} PACKED;
-
-#define MSGID_STATUS2 0x14
-struct bcm3510_hab_cmd_status2 {
-	struct {
-		u8 EQ_MODE  :4;
-		u8 reserved :2;
-		u8 QRE      :1;
-		u8 QSR      :1;
-	} PACKED STATUS0;
-	struct {
-		u8 RL       :1;
-		u8 FL       :1;
-		u8 OL       :1;
-		u8 reserved :5;
-	} PACKED STATUS1;
-	u8 SYMBOL_RATE0;
-	u8 SYMBOL_RATE1;
-	u8 SYMBOL_RATE2;
-	u8 SYMBOL_RATE3;
-	u8 LDCERC0;
-	u8 LDCERC1;
-	u8 LDCERC2;
-	u8 LDCERC3;
-	u8 LDUERC0;
-	u8 LDUERC1;
-	u8 LDUERC2;
-	u8 LDUERC3;
-	u8 LDBER0;
-	u8 LDBER1;
-	u8 LDBER2;
-	u8 LDBER3;
-	struct {
-		u8 MODE_TYPE :4; /* acquire mode 0 */
-		u8 reservd   :4;
-	} MODE_TYPE;
-	u8 SNR_EST0;
-	u8 SNR_EST1;
-	u8 SIGNAL;
-} PACKED;
-
-#define CMD_SET_RF_BW_NOT_LISTED   0x3f
-#define MSGID_SET_RF_BW_NOT_LISTED 0x11
-/* TODO */
-
-#endif
diff --git a/drivers/media/dvb/frontends/bsbe1-d01a.h b/drivers/media/dvb/frontends/bsbe1-d01a.h
deleted file mode 100644
index 7ed3c42..0000000
--- a/drivers/media/dvb/frontends/bsbe1-d01a.h
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * bsbe1-d01a.h - ALPS BSBE1-D01A tuner support
- *
- * Copyright (C) 2011 Oliver Endriss <o.endriss@gmx.de>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * 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.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- *
- *
- * the project's page is at http://www.linuxtv.org
- */
-
-#ifndef BSBE1_D01A_H
-#define BSBE1_D01A_H
-
-#include "stb6000.h"
-#include "stv0288.h"
-
-static u8 stv0288_bsbe1_d01a_inittab[] = {
-	0x01, 0x15,
-	0x02, 0x20,
-	0x09, 0x0,
-	0x0a, 0x4,
-	0x0b, 0x0,
-	0x0c, 0x0,
-	0x0d, 0x0,
-	0x0e, 0xd4,
-	0x0f, 0x30,
-	0x11, 0x80,
-	0x12, 0x03,
-	0x13, 0x48,
-	0x14, 0x84,
-	0x15, 0x45,
-	0x16, 0xb7,
-	0x17, 0x9c,
-	0x18, 0x0,
-	0x19, 0xa6,
-	0x1a, 0x88,
-	0x1b, 0x8f,
-	0x1c, 0xf0,
-	0x20, 0x0b,
-	0x21, 0x54,
-	0x22, 0x0,
-	0x23, 0x0,
-	0x2b, 0xff,
-	0x2c, 0xf7,
-	0x30, 0x0,
-	0x31, 0x1e,
-	0x32, 0x14,
-	0x33, 0x0f,
-	0x34, 0x09,
-	0x35, 0x0c,
-	0x36, 0x05,
-	0x37, 0x2f,
-	0x38, 0x16,
-	0x39, 0xbd,
-	0x3a, 0x03,
-	0x3b, 0x13,
-	0x3c, 0x11,
-	0x3d, 0x30,
-	0x40, 0x63,
-	0x41, 0x04,
-	0x42, 0x60,
-	0x43, 0x00,
-	0x44, 0x00,
-	0x45, 0x00,
-	0x46, 0x00,
-	0x47, 0x00,
-	0x4a, 0x00,
-	0x50, 0x10,
-	0x51, 0x36,
-	0x52, 0x09,
-	0x53, 0x94,
-	0x54, 0x62,
-	0x55, 0x29,
-	0x56, 0x64,
-	0x57, 0x2b,
-	0x58, 0x54,
-	0x59, 0x86,
-	0x5a, 0x0,
-	0x5b, 0x9b,
-	0x5c, 0x08,
-	0x5d, 0x7f,
-	0x5e, 0x0,
-	0x5f, 0xff,
-	0x70, 0x0,
-	0x71, 0x0,
-	0x72, 0x0,
-	0x74, 0x0,
-	0x75, 0x0,
-	0x76, 0x0,
-	0x81, 0x0,
-	0x82, 0x3f,
-	0x83, 0x3f,
-	0x84, 0x0,
-	0x85, 0x0,
-	0x88, 0x0,
-	0x89, 0x0,
-	0x8a, 0x0,
-	0x8b, 0x0,
-	0x8c, 0x0,
-	0x90, 0x0,
-	0x91, 0x0,
-	0x92, 0x0,
-	0x93, 0x0,
-	0x94, 0x1c,
-	0x97, 0x0,
-	0xa0, 0x48,
-	0xa1, 0x0,
-	0xb0, 0xb8,
-	0xb1, 0x3a,
-	0xb2, 0x10,
-	0xb3, 0x82,
-	0xb4, 0x80,
-	0xb5, 0x82,
-	0xb6, 0x82,
-	0xb7, 0x82,
-	0xb8, 0x20,
-	0xb9, 0x0,
-	0xf0, 0x0,
-	0xf1, 0x0,
-	0xf2, 0xc0,
-	0xff, 0xff,
-};
-
-static struct stv0288_config stv0288_bsbe1_d01a_config = {
-	.demod_address = 0x68,
-	.min_delay_ms = 100,
-	.inittab = stv0288_bsbe1_d01a_inittab,
-};
-
-#endif
diff --git a/drivers/media/dvb/frontends/bsbe1.h b/drivers/media/dvb/frontends/bsbe1.h
deleted file mode 100644
index 53e4d0d..0000000
--- a/drivers/media/dvb/frontends/bsbe1.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * bsbe1.h - ALPS BSBE1 tuner support
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- *
- *
- * the project's page is at http://www.linuxtv.org
- */
-
-#ifndef BSBE1_H
-#define BSBE1_H
-
-static u8 alps_bsbe1_inittab[] = {
-	0x01, 0x15,   /* XTAL = 4MHz, VCO = 352 MHz */
-	0x02, 0x30,   /* MCLK = 88 MHz */
-	0x03, 0x00,   /* ACR output 0 */
-	0x04, 0x7d,   /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */
-	0x05, 0x05,   /* I2CT = 0, SCLT = 1, SDAT = 1 */
-	0x06, 0x00,   /* DAC output 0 */
-	0x08, 0x40,   /* DiSEqC off, LNB power on OP2/LOCK pin on */
-	0x09, 0x00,   /* FIFO */
-	0x0c, 0x51,   /* OP1/OP0 normal, val = 1 (LNB power on) */
-	0x0d, 0x82,   /* DC offset compensation = on, beta_agc1 = 2 */
-	0x0f, 0x92,   /* AGC1R */
-	0x10, 0x34,   /* AGC2O */
-	0x11, 0x84,   /* TLSR */
-	0x12, 0xb9,   /* CFD */
-	0x15, 0xc9,   /* lock detector threshold */
-	0x28, 0x00,   /* out imp: normal, type: parallel, FEC mode: QPSK */
-	0x33, 0xfc,   /* RS control */
-	0x34, 0x93,   /* count viterbi bit errors per 2E18 bytes */
-	0xff, 0xff
-};
-
-
-static int alps_bsbe1_set_symbol_rate(struct dvb_frontend* fe, u32 srate, u32 ratio)
-{
-	u8 aclk = 0;
-	u8 bclk = 0;
-
-	if (srate < 1500000) { aclk = 0xb7; bclk = 0x47; }
-	else if (srate < 3000000) { aclk = 0xb7; bclk = 0x4b; }
-	else if (srate < 7000000) { aclk = 0xb7; bclk = 0x4f; }
-	else if (srate < 14000000) { aclk = 0xb7; bclk = 0x53; }
-	else if (srate < 30000000) { aclk = 0xb6; bclk = 0x53; }
-	else if (srate < 45000000) { aclk = 0xb4; bclk = 0x51; }
-
-	stv0299_writereg(fe, 0x13, aclk);
-	stv0299_writereg(fe, 0x14, bclk);
-	stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
-	stv0299_writereg(fe, 0x20, (ratio >>  8) & 0xff);
-	stv0299_writereg(fe, 0x21, (ratio      ) & 0xf0);
-
-	return 0;
-}
-
-static int alps_bsbe1_tuner_set_params(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	int ret;
-	u8 data[4];
-	u32 div;
-	struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
-	struct i2c_adapter *i2c = fe->tuner_priv;
-
-	if ((p->frequency < 950000) || (p->frequency > 2150000))
-		return -EINVAL;
-
-	div = p->frequency / 1000;
-	data[0] = (div >> 8) & 0x7f;
-	data[1] = div & 0xff;
-	data[2] = 0x80 | ((div & 0x18000) >> 10) | 0x1;
-	data[3] = 0xe0;
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	ret = i2c_transfer(i2c, &msg, 1);
-	return (ret != 1) ? -EIO : 0;
-}
-
-static struct stv0299_config alps_bsbe1_config = {
-	.demod_address = 0x68,
-	.inittab = alps_bsbe1_inittab,
-	.mclk = 88000000UL,
-	.invert = 1,
-	.skip_reinit = 0,
-	.min_delay_ms = 100,
-	.set_symbol_rate = alps_bsbe1_set_symbol_rate,
-};
-
-#endif
diff --git a/drivers/media/dvb/frontends/bsru6.h b/drivers/media/dvb/frontends/bsru6.h
deleted file mode 100644
index c2a578e..0000000
--- a/drivers/media/dvb/frontends/bsru6.h
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * bsru6.h - ALPS BSRU6 tuner support (moved from budget-ci.c)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- *
- *
- * the project's page is at http://www.linuxtv.org
- */
-
-#ifndef BSRU6_H
-#define BSRU6_H
-
-static u8 alps_bsru6_inittab[] = {
-	0x01, 0x15,
-	0x02, 0x30,
-	0x03, 0x00,
-	0x04, 0x7d,   /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */
-	0x05, 0x35,   /* I2CT = 0, SCLT = 1, SDAT = 1 */
-	0x06, 0x40,   /* DAC not used, set to high impendance mode */
-	0x07, 0x00,   /* DAC LSB */
-	0x08, 0x40,   /* DiSEqC off, LNB power on OP2/LOCK pin on */
-	0x09, 0x00,   /* FIFO */
-	0x0c, 0x51,   /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */
-	0x0d, 0x82,   /* DC offset compensation = ON, beta_agc1 = 2 */
-	0x0e, 0x23,   /* alpha_tmg = 2, beta_tmg = 3 */
-	0x10, 0x3f,   // AGC2  0x3d
-	0x11, 0x84,
-	0x12, 0xb9,
-	0x15, 0xc9,   // lock detector threshold
-	0x16, 0x00,
-	0x17, 0x00,
-	0x18, 0x00,
-	0x19, 0x00,
-	0x1a, 0x00,
-	0x1f, 0x50,
-	0x20, 0x00,
-	0x21, 0x00,
-	0x22, 0x00,
-	0x23, 0x00,
-	0x28, 0x00,  // out imp: normal  out type: parallel FEC mode:0
-	0x29, 0x1e,  // 1/2 threshold
-	0x2a, 0x14,  // 2/3 threshold
-	0x2b, 0x0f,  // 3/4 threshold
-	0x2c, 0x09,  // 5/6 threshold
-	0x2d, 0x05,  // 7/8 threshold
-	0x2e, 0x01,
-	0x31, 0x1f,  // test all FECs
-	0x32, 0x19,  // viterbi and synchro search
-	0x33, 0xfc,  // rs control
-	0x34, 0x93,  // error control
-	0x0f, 0x52,
-	0xff, 0xff
-};
-
-static int alps_bsru6_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ratio)
-{
-	u8 aclk = 0;
-	u8 bclk = 0;
-
-	if (srate < 1500000) {
-		aclk = 0xb7;
-		bclk = 0x47;
-	} else if (srate < 3000000) {
-		aclk = 0xb7;
-		bclk = 0x4b;
-	} else if (srate < 7000000) {
-		aclk = 0xb7;
-		bclk = 0x4f;
-	} else if (srate < 14000000) {
-		aclk = 0xb7;
-		bclk = 0x53;
-	} else if (srate < 30000000) {
-		aclk = 0xb6;
-		bclk = 0x53;
-	} else if (srate < 45000000) {
-		aclk = 0xb4;
-		bclk = 0x51;
-	}
-
-	stv0299_writereg(fe, 0x13, aclk);
-	stv0299_writereg(fe, 0x14, bclk);
-	stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
-	stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff);
-	stv0299_writereg(fe, 0x21, ratio & 0xf0);
-
-	return 0;
-}
-
-static int alps_bsru6_tuner_set_params(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	u8 buf[4];
-	u32 div;
-	struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
-	struct i2c_adapter *i2c = fe->tuner_priv;
-
-	if ((p->frequency < 950000) || (p->frequency > 2150000))
-		return -EINVAL;
-
-	div = (p->frequency + (125 - 1)) / 125;	/* round correctly */
-	buf[0] = (div >> 8) & 0x7f;
-	buf[1] = div & 0xff;
-	buf[2] = 0x80 | ((div & 0x18000) >> 10) | 4;
-	buf[3] = 0xC4;
-
-	if (p->frequency > 1530000)
-		buf[3] = 0xc0;
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	if (i2c_transfer(i2c, &msg, 1) != 1)
-		return -EIO;
-	return 0;
-}
-
-static struct stv0299_config alps_bsru6_config = {
-	.demod_address = 0x68,
-	.inittab = alps_bsru6_inittab,
-	.mclk = 88000000UL,
-	.invert = 1,
-	.skip_reinit = 0,
-	.lock_output = STV0299_LOCKOUTPUT_1,
-	.volt13_op0_op1 = STV0299_VOLT13_OP1,
-	.min_delay_ms = 100,
-	.set_symbol_rate = alps_bsru6_set_symbol_rate,
-};
-
-#endif
diff --git a/drivers/media/dvb/frontends/cx22700.c b/drivers/media/dvb/frontends/cx22700.c
deleted file mode 100644
index f2a90f9..0000000
--- a/drivers/media/dvb/frontends/cx22700.c
+++ /dev/null
@@ -1,443 +0,0 @@
-/*
-    Conexant cx22700 DVB OFDM demodulator driver
-
-    Copyright (C) 2001-2002 Convergence Integrated Media GmbH
-	Holger Waechtler <holger@convergence.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/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include "dvb_frontend.h"
-#include "cx22700.h"
-
-
-struct cx22700_state {
-
-	struct i2c_adapter* i2c;
-
-	const struct cx22700_config* config;
-
-	struct dvb_frontend frontend;
-};
-
-
-static int debug;
-#define dprintk(args...) \
-	do { \
-		if (debug) printk(KERN_DEBUG "cx22700: " args); \
-	} while (0)
-
-static u8 init_tab [] = {
-	0x04, 0x10,
-	0x05, 0x09,
-	0x06, 0x00,
-	0x08, 0x04,
-	0x09, 0x00,
-	0x0a, 0x01,
-	0x15, 0x40,
-	0x16, 0x10,
-	0x17, 0x87,
-	0x18, 0x17,
-	0x1a, 0x10,
-	0x25, 0x04,
-	0x2e, 0x00,
-	0x39, 0x00,
-	0x3a, 0x04,
-	0x45, 0x08,
-	0x46, 0x02,
-	0x47, 0x05,
-};
-
-
-static int cx22700_writereg (struct cx22700_state* state, u8 reg, u8 data)
-{
-	int ret;
-	u8 buf [] = { reg, data };
-	struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 };
-
-	dprintk ("%s\n", __func__);
-
-	ret = i2c_transfer (state->i2c, &msg, 1);
-
-	if (ret != 1)
-		printk("%s: writereg error (reg == 0x%02x, val == 0x%02x, ret == %i)\n",
-			__func__, reg, data, ret);
-
-	return (ret != 1) ? -1 : 0;
-}
-
-static int cx22700_readreg (struct cx22700_state* state, u8 reg)
-{
-	int ret;
-	u8 b0 [] = { reg };
-	u8 b1 [] = { 0 };
-	struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 },
-			   { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } };
-
-	dprintk ("%s\n", __func__);
-
-	ret = i2c_transfer (state->i2c, msg, 2);
-
-	if (ret != 2) return -EIO;
-
-	return b1[0];
-}
-
-static int cx22700_set_inversion (struct cx22700_state* state, int inversion)
-{
-	u8 val;
-
-	dprintk ("%s\n", __func__);
-
-	switch (inversion) {
-	case INVERSION_AUTO:
-		return -EOPNOTSUPP;
-	case INVERSION_ON:
-		val = cx22700_readreg (state, 0x09);
-		return cx22700_writereg (state, 0x09, val | 0x01);
-	case INVERSION_OFF:
-		val = cx22700_readreg (state, 0x09);
-		return cx22700_writereg (state, 0x09, val & 0xfe);
-	default:
-		return -EINVAL;
-	}
-}
-
-static int cx22700_set_tps(struct cx22700_state *state,
-			   struct dtv_frontend_properties *p)
-{
-	static const u8 qam_tab [4] = { 0, 1, 0, 2 };
-	static const u8 fec_tab [6] = { 0, 1, 2, 0, 3, 4 };
-	u8 val;
-
-	dprintk ("%s\n", __func__);
-
-	if (p->code_rate_HP < FEC_1_2 || p->code_rate_HP > FEC_7_8)
-		return -EINVAL;
-
-	if (p->code_rate_LP < FEC_1_2 || p->code_rate_LP > FEC_7_8)
-		return -EINVAL;
-
-	if (p->code_rate_HP == FEC_4_5 || p->code_rate_LP == FEC_4_5)
-		return -EINVAL;
-
-	if (p->guard_interval < GUARD_INTERVAL_1_32 ||
-	    p->guard_interval > GUARD_INTERVAL_1_4)
-		return -EINVAL;
-
-	if (p->transmission_mode != TRANSMISSION_MODE_2K &&
-	    p->transmission_mode != TRANSMISSION_MODE_8K)
-		return -EINVAL;
-
-	if (p->modulation != QPSK &&
-	    p->modulation != QAM_16 &&
-	    p->modulation != QAM_64)
-		return -EINVAL;
-
-	if (p->hierarchy < HIERARCHY_NONE ||
-	    p->hierarchy > HIERARCHY_4)
-		return -EINVAL;
-
-	if (p->bandwidth_hz > 8000000 || p->bandwidth_hz < 6000000)
-		return -EINVAL;
-
-	if (p->bandwidth_hz == 7000000)
-		cx22700_writereg (state, 0x09, cx22700_readreg (state, 0x09 | 0x10));
-	else
-		cx22700_writereg (state, 0x09, cx22700_readreg (state, 0x09 & ~0x10));
-
-	val = qam_tab[p->modulation - QPSK];
-	val |= p->hierarchy - HIERARCHY_NONE;
-
-	cx22700_writereg (state, 0x04, val);
-
-	val = fec_tab[p->code_rate_HP - FEC_1_2] << 3;
-	val |= fec_tab[p->code_rate_LP - FEC_1_2];
-
-	cx22700_writereg (state, 0x05, val);
-
-	val = (p->guard_interval - GUARD_INTERVAL_1_32) << 2;
-	val |= p->transmission_mode - TRANSMISSION_MODE_2K;
-
-	cx22700_writereg (state, 0x06, val);
-
-	cx22700_writereg (state, 0x08, 0x04 | 0x02);  /* use user tps parameters */
-	cx22700_writereg (state, 0x08, 0x04);         /* restart acquisition */
-
-	return 0;
-}
-
-static int cx22700_get_tps(struct cx22700_state *state,
-			   struct dtv_frontend_properties *p)
-{
-	static const fe_modulation_t qam_tab [3] = { QPSK, QAM_16, QAM_64 };
-	static const fe_code_rate_t fec_tab [5] = { FEC_1_2, FEC_2_3, FEC_3_4,
-						    FEC_5_6, FEC_7_8 };
-	u8 val;
-
-	dprintk ("%s\n", __func__);
-
-	if (!(cx22700_readreg(state, 0x07) & 0x20))  /*  tps valid? */
-		return -EAGAIN;
-
-	val = cx22700_readreg (state, 0x01);
-
-	if ((val & 0x7) > 4)
-		p->hierarchy = HIERARCHY_AUTO;
-	else
-		p->hierarchy = HIERARCHY_NONE + (val & 0x7);
-
-	if (((val >> 3) & 0x3) > 2)
-		p->modulation = QAM_AUTO;
-	else
-		p->modulation = qam_tab[(val >> 3) & 0x3];
-
-	val = cx22700_readreg (state, 0x02);
-
-	if (((val >> 3) & 0x07) > 4)
-		p->code_rate_HP = FEC_AUTO;
-	else
-		p->code_rate_HP = fec_tab[(val >> 3) & 0x07];
-
-	if ((val & 0x07) > 4)
-		p->code_rate_LP = FEC_AUTO;
-	else
-		p->code_rate_LP = fec_tab[val & 0x07];
-
-	val = cx22700_readreg (state, 0x03);
-
-	p->guard_interval = GUARD_INTERVAL_1_32 + ((val >> 6) & 0x3);
-	p->transmission_mode = TRANSMISSION_MODE_2K + ((val >> 5) & 0x1);
-
-	return 0;
-}
-
-static int cx22700_init (struct dvb_frontend* fe)
-
-{	struct cx22700_state* state = fe->demodulator_priv;
-	int i;
-
-	dprintk("cx22700_init: init chip\n");
-
-	cx22700_writereg (state, 0x00, 0x02);   /*  soft reset */
-	cx22700_writereg (state, 0x00, 0x00);
-
-	msleep(10);
-
-	for (i=0; i<sizeof(init_tab); i+=2)
-		cx22700_writereg (state, init_tab[i], init_tab[i+1]);
-
-	cx22700_writereg (state, 0x00, 0x01);
-
-	return 0;
-}
-
-static int cx22700_read_status(struct dvb_frontend* fe, fe_status_t* status)
-{
-	struct cx22700_state* state = fe->demodulator_priv;
-
-	u16 rs_ber = (cx22700_readreg (state, 0x0d) << 9)
-		   | (cx22700_readreg (state, 0x0e) << 1);
-	u8 sync = cx22700_readreg (state, 0x07);
-
-	*status = 0;
-
-	if (rs_ber < 0xff00)
-		*status |= FE_HAS_SIGNAL;
-
-	if (sync & 0x20)
-		*status |= FE_HAS_CARRIER;
-
-	if (sync & 0x10)
-		*status |= FE_HAS_VITERBI;
-
-	if (sync & 0x10)
-		*status |= FE_HAS_SYNC;
-
-	if (*status == 0x0f)
-		*status |= FE_HAS_LOCK;
-
-	return 0;
-}
-
-static int cx22700_read_ber(struct dvb_frontend* fe, u32* ber)
-{
-	struct cx22700_state* state = fe->demodulator_priv;
-
-	*ber = cx22700_readreg (state, 0x0c) & 0x7f;
-	cx22700_writereg (state, 0x0c, 0x00);
-
-	return 0;
-}
-
-static int cx22700_read_signal_strength(struct dvb_frontend* fe, u16* signal_strength)
-{
-	struct cx22700_state* state = fe->demodulator_priv;
-
-	u16 rs_ber = (cx22700_readreg (state, 0x0d) << 9)
-		   | (cx22700_readreg (state, 0x0e) << 1);
-	*signal_strength = ~rs_ber;
-
-	return 0;
-}
-
-static int cx22700_read_snr(struct dvb_frontend* fe, u16* snr)
-{
-	struct cx22700_state* state = fe->demodulator_priv;
-
-	u16 rs_ber = (cx22700_readreg (state, 0x0d) << 9)
-		   | (cx22700_readreg (state, 0x0e) << 1);
-	*snr = ~rs_ber;
-
-	return 0;
-}
-
-static int cx22700_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
-{
-	struct cx22700_state* state = fe->demodulator_priv;
-
-	*ucblocks = cx22700_readreg (state, 0x0f);
-	cx22700_writereg (state, 0x0f, 0x00);
-
-	return 0;
-}
-
-static int cx22700_set_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	struct cx22700_state* state = fe->demodulator_priv;
-
-	cx22700_writereg (state, 0x00, 0x02); /* XXX CHECKME: soft reset*/
-	cx22700_writereg (state, 0x00, 0x00);
-
-	if (fe->ops.tuner_ops.set_params) {
-		fe->ops.tuner_ops.set_params(fe);
-		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
-	}
-
-	cx22700_set_inversion(state, c->inversion);
-	cx22700_set_tps(state, c);
-	cx22700_writereg (state, 0x37, 0x01);  /* PAL loop filter off */
-	cx22700_writereg (state, 0x00, 0x01);  /* restart acquire */
-
-	return 0;
-}
-
-static int cx22700_get_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	struct cx22700_state* state = fe->demodulator_priv;
-	u8 reg09 = cx22700_readreg (state, 0x09);
-
-	c->inversion = reg09 & 0x1 ? INVERSION_ON : INVERSION_OFF;
-	return cx22700_get_tps(state, c);
-}
-
-static int cx22700_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
-{
-	struct cx22700_state* state = fe->demodulator_priv;
-
-	if (enable) {
-		return cx22700_writereg(state, 0x0a, 0x00);
-	} else {
-		return cx22700_writereg(state, 0x0a, 0x01);
-	}
-}
-
-static int cx22700_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings)
-{
-	fesettings->min_delay_ms = 150;
-	fesettings->step_size = 166667;
-	fesettings->max_drift = 166667*2;
-	return 0;
-}
-
-static void cx22700_release(struct dvb_frontend* fe)
-{
-	struct cx22700_state* state = fe->demodulator_priv;
-	kfree(state);
-}
-
-static struct dvb_frontend_ops cx22700_ops;
-
-struct dvb_frontend* cx22700_attach(const struct cx22700_config* config,
-				    struct i2c_adapter* i2c)
-{
-	struct cx22700_state* state = NULL;
-
-	/* allocate memory for the internal state */
-	state = kzalloc(sizeof(struct cx22700_state), GFP_KERNEL);
-	if (state == NULL) goto error;
-
-	/* setup the state */
-	state->config = config;
-	state->i2c = i2c;
-
-	/* check if the demod is there */
-	if (cx22700_readreg(state, 0x07) < 0) goto error;
-
-	/* create dvb_frontend */
-	memcpy(&state->frontend.ops, &cx22700_ops, sizeof(struct dvb_frontend_ops));
-	state->frontend.demodulator_priv = state;
-	return &state->frontend;
-
-error:
-	kfree(state);
-	return NULL;
-}
-
-static struct dvb_frontend_ops cx22700_ops = {
-	.delsys = { SYS_DVBT },
-	.info = {
-		.name			= "Conexant CX22700 DVB-T",
-		.frequency_min		= 470000000,
-		.frequency_max		= 860000000,
-		.frequency_stepsize	= 166667,
-		.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_FEC_AUTO |
-		      FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 |
-		      FE_CAN_RECOVER
-	},
-
-	.release = cx22700_release,
-
-	.init = cx22700_init,
-	.i2c_gate_ctrl = cx22700_i2c_gate_ctrl,
-
-	.set_frontend = cx22700_set_frontend,
-	.get_frontend = cx22700_get_frontend,
-	.get_tune_settings = cx22700_get_tune_settings,
-
-	.read_status = cx22700_read_status,
-	.read_ber = cx22700_read_ber,
-	.read_signal_strength = cx22700_read_signal_strength,
-	.read_snr = cx22700_read_snr,
-	.read_ucblocks = cx22700_read_ucblocks,
-};
-
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
-
-MODULE_DESCRIPTION("Conexant CX22700 DVB-T Demodulator driver");
-MODULE_AUTHOR("Holger Waechtler");
-MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(cx22700_attach);
diff --git a/drivers/media/dvb/frontends/cx22700.h b/drivers/media/dvb/frontends/cx22700.h
deleted file mode 100644
index 4757a93..0000000
--- a/drivers/media/dvb/frontends/cx22700.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
-    Conexant CX22700 DVB OFDM demodulator driver
-
-    Copyright (C) 2001-2002 Convergence Integrated Media GmbH
-	Holger Waechtler <holger@convergence.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 CX22700_H
-#define CX22700_H
-
-#include <linux/dvb/frontend.h>
-
-struct cx22700_config
-{
-	/* the demodulator's i2c address */
-	u8 demod_address;
-};
-
-#if defined(CONFIG_DVB_CX22700) || (defined(CONFIG_DVB_CX22700_MODULE) && defined(MODULE))
-extern struct dvb_frontend* cx22700_attach(const struct cx22700_config* config,
-					   struct i2c_adapter* i2c);
-#else
-static inline struct dvb_frontend* cx22700_attach(const struct cx22700_config* config,
-					   struct i2c_adapter* i2c)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif // CONFIG_DVB_CX22700
-
-#endif // CX22700_H
diff --git a/drivers/media/dvb/frontends/cx22702.c b/drivers/media/dvb/frontends/cx22702.c
deleted file mode 100644
index edc8eaf..0000000
--- a/drivers/media/dvb/frontends/cx22702.c
+++ /dev/null
@@ -1,653 +0,0 @@
-/*
-    Conexant 22702 DVB OFDM demodulator driver
-
-    based on:
-	Alps TDMB7 DVB OFDM demodulator driver
-
-    Copyright (C) 2001-2002 Convergence Integrated Media GmbH
-	  Holger Waechtler <holger@convergence.de>
-
-    Copyright (C) 2004 Steven Toth <stoth@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/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include "dvb_frontend.h"
-#include "cx22702.h"
-
-struct cx22702_state {
-
-	struct i2c_adapter *i2c;
-
-	/* configuration settings */
-	const struct cx22702_config *config;
-
-	struct dvb_frontend frontend;
-
-	/* previous uncorrected block counter */
-	u8 prevUCBlocks;
-};
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Enable verbose debug messages");
-
-#define dprintk	if (debug) printk
-
-/* Register values to initialise the demod */
-static const u8 init_tab[] = {
-	0x00, 0x00, /* Stop acquisition */
-	0x0B, 0x06,
-	0x09, 0x01,
-	0x0D, 0x41,
-	0x16, 0x32,
-	0x20, 0x0A,
-	0x21, 0x17,
-	0x24, 0x3e,
-	0x26, 0xff,
-	0x27, 0x10,
-	0x28, 0x00,
-	0x29, 0x00,
-	0x2a, 0x10,
-	0x2b, 0x00,
-	0x2c, 0x10,
-	0x2d, 0x00,
-	0x48, 0xd4,
-	0x49, 0x56,
-	0x6b, 0x1e,
-	0xc8, 0x02,
-	0xf9, 0x00,
-	0xfa, 0x00,
-	0xfb, 0x00,
-	0xfc, 0x00,
-	0xfd, 0x00,
-};
-
-static int cx22702_writereg(struct cx22702_state *state, u8 reg, u8 data)
-{
-	int ret;
-	u8 buf[] = { reg, data };
-	struct i2c_msg msg = {
-		.addr = state->config->demod_address, .flags = 0,
-			.buf = buf, .len = 2 };
-
-	ret = i2c_transfer(state->i2c, &msg, 1);
-
-	if (unlikely(ret != 1)) {
-		printk(KERN_ERR
-			"%s: error (reg == 0x%02x, val == 0x%02x, ret == %i)\n",
-			__func__, reg, data, ret);
-		return -1;
-	}
-
-	return 0;
-}
-
-static u8 cx22702_readreg(struct cx22702_state *state, u8 reg)
-{
-	int ret;
-	u8 data;
-
-	struct i2c_msg msg[] = {
-		{ .addr = state->config->demod_address, .flags = 0,
-			.buf = &reg, .len = 1 },
-		{ .addr = state->config->demod_address, .flags = I2C_M_RD,
-			.buf = &data, .len = 1 } };
-
-	ret = i2c_transfer(state->i2c, msg, 2);
-
-	if (unlikely(ret != 2)) {
-		printk(KERN_ERR "%s: error (reg == 0x%02x, ret == %i)\n",
-			__func__, reg, ret);
-		return 0;
-	}
-
-	return data;
-}
-
-static int cx22702_set_inversion(struct cx22702_state *state, int inversion)
-{
-	u8 val;
-
-	val = cx22702_readreg(state, 0x0C);
-	switch (inversion) {
-	case INVERSION_AUTO:
-		return -EOPNOTSUPP;
-	case INVERSION_ON:
-		val |= 0x01;
-		break;
-	case INVERSION_OFF:
-		val &= 0xfe;
-		break;
-	default:
-		return -EINVAL;
-	}
-	return cx22702_writereg(state, 0x0C, val);
-}
-
-/* Retrieve the demod settings */
-static int cx22702_get_tps(struct cx22702_state *state,
-			   struct dtv_frontend_properties *p)
-{
-	u8 val;
-
-	/* Make sure the TPS regs are valid */
-	if (!(cx22702_readreg(state, 0x0A) & 0x20))
-		return -EAGAIN;
-
-	val = cx22702_readreg(state, 0x01);
-	switch ((val & 0x18) >> 3) {
-	case 0:
-		p->modulation = QPSK;
-		break;
-	case 1:
-		p->modulation = QAM_16;
-		break;
-	case 2:
-		p->modulation = QAM_64;
-		break;
-	}
-	switch (val & 0x07) {
-	case 0:
-		p->hierarchy = HIERARCHY_NONE;
-		break;
-	case 1:
-		p->hierarchy = HIERARCHY_1;
-		break;
-	case 2:
-		p->hierarchy = HIERARCHY_2;
-		break;
-	case 3:
-		p->hierarchy = HIERARCHY_4;
-		break;
-	}
-
-
-	val = cx22702_readreg(state, 0x02);
-	switch ((val & 0x38) >> 3) {
-	case 0:
-		p->code_rate_HP = FEC_1_2;
-		break;
-	case 1:
-		p->code_rate_HP = FEC_2_3;
-		break;
-	case 2:
-		p->code_rate_HP = FEC_3_4;
-		break;
-	case 3:
-		p->code_rate_HP = FEC_5_6;
-		break;
-	case 4:
-		p->code_rate_HP = FEC_7_8;
-		break;
-	}
-	switch (val & 0x07) {
-	case 0:
-		p->code_rate_LP = FEC_1_2;
-		break;
-	case 1:
-		p->code_rate_LP = FEC_2_3;
-		break;
-	case 2:
-		p->code_rate_LP = FEC_3_4;
-		break;
-	case 3:
-		p->code_rate_LP = FEC_5_6;
-		break;
-	case 4:
-		p->code_rate_LP = FEC_7_8;
-		break;
-	}
-
-	val = cx22702_readreg(state, 0x03);
-	switch ((val & 0x0c) >> 2) {
-	case 0:
-		p->guard_interval = GUARD_INTERVAL_1_32;
-		break;
-	case 1:
-		p->guard_interval = GUARD_INTERVAL_1_16;
-		break;
-	case 2:
-		p->guard_interval = GUARD_INTERVAL_1_8;
-		break;
-	case 3:
-		p->guard_interval = GUARD_INTERVAL_1_4;
-		break;
-	}
-	switch (val & 0x03) {
-	case 0:
-		p->transmission_mode = TRANSMISSION_MODE_2K;
-		break;
-	case 1:
-		p->transmission_mode = TRANSMISSION_MODE_8K;
-		break;
-	}
-
-	return 0;
-}
-
-static int cx22702_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
-{
-	struct cx22702_state *state = fe->demodulator_priv;
-	u8 val;
-
-	dprintk("%s(%d)\n", __func__, enable);
-	val = cx22702_readreg(state, 0x0D);
-	if (enable)
-		val &= 0xfe;
-	else
-		val |= 0x01;
-	return cx22702_writereg(state, 0x0D, val);
-}
-
-/* Talk to the demod, set the FEC, GUARD, QAM settings etc */
-static int cx22702_set_tps(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	u8 val;
-	struct cx22702_state *state = fe->demodulator_priv;
-
-	if (fe->ops.tuner_ops.set_params) {
-		fe->ops.tuner_ops.set_params(fe);
-		if (fe->ops.i2c_gate_ctrl)
-			fe->ops.i2c_gate_ctrl(fe, 0);
-	}
-
-	/* set inversion */
-	cx22702_set_inversion(state, p->inversion);
-
-	/* set bandwidth */
-	val = cx22702_readreg(state, 0x0C) & 0xcf;
-	switch (p->bandwidth_hz) {
-	case 6000000:
-		val |= 0x20;
-		break;
-	case 7000000:
-		val |= 0x10;
-		break;
-	case 8000000:
-		break;
-	default:
-		dprintk("%s: invalid bandwidth\n", __func__);
-		return -EINVAL;
-	}
-	cx22702_writereg(state, 0x0C, val);
-
-	p->code_rate_LP = FEC_AUTO; /* temp hack as manual not working */
-
-	/* use auto configuration? */
-	if ((p->hierarchy == HIERARCHY_AUTO) ||
-	   (p->modulation == QAM_AUTO) ||
-	   (p->code_rate_HP == FEC_AUTO) ||
-	   (p->code_rate_LP == FEC_AUTO) ||
-	   (p->guard_interval == GUARD_INTERVAL_AUTO) ||
-	   (p->transmission_mode == TRANSMISSION_MODE_AUTO)) {
-
-		/* TPS Source - use hardware driven values */
-		cx22702_writereg(state, 0x06, 0x10);
-		cx22702_writereg(state, 0x07, 0x9);
-		cx22702_writereg(state, 0x08, 0xC1);
-		cx22702_writereg(state, 0x0B, cx22702_readreg(state, 0x0B)
-			& 0xfc);
-		cx22702_writereg(state, 0x0C,
-			(cx22702_readreg(state, 0x0C) & 0xBF) | 0x40);
-		cx22702_writereg(state, 0x00, 0x01); /* Begin acquisition */
-		dprintk("%s: Autodetecting\n", __func__);
-		return 0;
-	}
-
-	/* manually programmed values */
-	switch (p->modulation) {		/* mask 0x18 */
-	case QPSK:
-		val = 0x00;
-		break;
-	case QAM_16:
-		val = 0x08;
-		break;
-	case QAM_64:
-		val = 0x10;
-		break;
-	default:
-		dprintk("%s: invalid modulation\n", __func__);
-		return -EINVAL;
-	}
-	switch (p->hierarchy) {	/* mask 0x07 */
-	case HIERARCHY_NONE:
-		break;
-	case HIERARCHY_1:
-		val |= 0x01;
-		break;
-	case HIERARCHY_2:
-		val |= 0x02;
-		break;
-	case HIERARCHY_4:
-		val |= 0x03;
-		break;
-	default:
-		dprintk("%s: invalid hierarchy\n", __func__);
-		return -EINVAL;
-	}
-	cx22702_writereg(state, 0x06, val);
-
-	switch (p->code_rate_HP) {		/* mask 0x38 */
-	case FEC_NONE:
-	case FEC_1_2:
-		val = 0x00;
-		break;
-	case FEC_2_3:
-		val = 0x08;
-		break;
-	case FEC_3_4:
-		val = 0x10;
-		break;
-	case FEC_5_6:
-		val = 0x18;
-		break;
-	case FEC_7_8:
-		val = 0x20;
-		break;
-	default:
-		dprintk("%s: invalid code_rate_HP\n", __func__);
-		return -EINVAL;
-	}
-	switch (p->code_rate_LP) {		/* mask 0x07 */
-	case FEC_NONE:
-	case FEC_1_2:
-		break;
-	case FEC_2_3:
-		val |= 0x01;
-		break;
-	case FEC_3_4:
-		val |= 0x02;
-		break;
-	case FEC_5_6:
-		val |= 0x03;
-		break;
-	case FEC_7_8:
-		val |= 0x04;
-		break;
-	default:
-		dprintk("%s: invalid code_rate_LP\n", __func__);
-		return -EINVAL;
-	}
-	cx22702_writereg(state, 0x07, val);
-
-	switch (p->guard_interval) {		/* mask 0x0c */
-	case GUARD_INTERVAL_1_32:
-		val = 0x00;
-		break;
-	case GUARD_INTERVAL_1_16:
-		val = 0x04;
-		break;
-	case GUARD_INTERVAL_1_8:
-		val = 0x08;
-		break;
-	case GUARD_INTERVAL_1_4:
-		val = 0x0c;
-		break;
-	default:
-		dprintk("%s: invalid guard_interval\n", __func__);
-		return -EINVAL;
-	}
-	switch (p->transmission_mode) {		/* mask 0x03 */
-	case TRANSMISSION_MODE_2K:
-		break;
-	case TRANSMISSION_MODE_8K:
-		val |= 0x1;
-		break;
-	default:
-		dprintk("%s: invalid transmission_mode\n", __func__);
-		return -EINVAL;
-	}
-	cx22702_writereg(state, 0x08, val);
-	cx22702_writereg(state, 0x0B,
-		(cx22702_readreg(state, 0x0B) & 0xfc) | 0x02);
-	cx22702_writereg(state, 0x0C,
-		(cx22702_readreg(state, 0x0C) & 0xBF) | 0x40);
-
-	/* Begin channel acquisition */
-	cx22702_writereg(state, 0x00, 0x01);
-
-	return 0;
-}
-
-/* Reset the demod hardware and reset all of the configuration registers
-   to a default state. */
-static int cx22702_init(struct dvb_frontend *fe)
-{
-	int i;
-	struct cx22702_state *state = fe->demodulator_priv;
-
-	cx22702_writereg(state, 0x00, 0x02);
-
-	msleep(10);
-
-	for (i = 0; i < ARRAY_SIZE(init_tab); i += 2)
-		cx22702_writereg(state, init_tab[i], init_tab[i + 1]);
-
-	cx22702_writereg(state, 0xf8, (state->config->output_mode << 1)
-		& 0x02);
-
-	cx22702_i2c_gate_ctrl(fe, 0);
-
-	return 0;
-}
-
-static int cx22702_read_status(struct dvb_frontend *fe, fe_status_t *status)
-{
-	struct cx22702_state *state = fe->demodulator_priv;
-	u8 reg0A;
-	u8 reg23;
-
-	*status = 0;
-
-	reg0A = cx22702_readreg(state, 0x0A);
-	reg23 = cx22702_readreg(state, 0x23);
-
-	dprintk("%s: status demod=0x%02x agc=0x%02x\n"
-		, __func__, reg0A, reg23);
-
-	if (reg0A & 0x10) {
-		*status |= FE_HAS_LOCK;
-		*status |= FE_HAS_VITERBI;
-		*status |= FE_HAS_SYNC;
-	}
-
-	if (reg0A & 0x20)
-		*status |= FE_HAS_CARRIER;
-
-	if (reg23 < 0xf0)
-		*status |= FE_HAS_SIGNAL;
-
-	return 0;
-}
-
-static int cx22702_read_ber(struct dvb_frontend *fe, u32 *ber)
-{
-	struct cx22702_state *state = fe->demodulator_priv;
-
-	if (cx22702_readreg(state, 0xE4) & 0x02) {
-		/* Realtime statistics */
-		*ber = (cx22702_readreg(state, 0xDE) & 0x7F) << 7
-			| (cx22702_readreg(state, 0xDF) & 0x7F);
-	} else {
-		/* Averagtine statistics */
-		*ber = (cx22702_readreg(state, 0xDE) & 0x7F) << 7
-			| cx22702_readreg(state, 0xDF);
-	}
-
-	return 0;
-}
-
-static int cx22702_read_signal_strength(struct dvb_frontend *fe,
-	u16 *signal_strength)
-{
-	struct cx22702_state *state = fe->demodulator_priv;
-	u8 reg23;
-
-	/*
-	 * Experience suggests that the strength signal register works as
-	 * follows:
-	 * - In the absence of signal, value is 0xff.
-	 * - In the presence of a weak signal, bit 7 is set, not sure what
-	 *   the lower 7 bits mean.
-	 * - In the presence of a strong signal, the register holds a 7-bit
-	 *   value (bit 7 is cleared), with greater values standing for
-	 *   weaker signals.
-	 */
-	reg23 = cx22702_readreg(state, 0x23);
-	if (reg23 & 0x80) {
-		*signal_strength = 0;
-	} else {
-		reg23 = ~reg23 & 0x7f;
-		/* Scale to 16 bit */
-		*signal_strength = (reg23 << 9) | (reg23 << 2) | (reg23 >> 5);
-	}
-
-	return 0;
-}
-
-static int cx22702_read_snr(struct dvb_frontend *fe, u16 *snr)
-{
-	struct cx22702_state *state = fe->demodulator_priv;
-
-	u16 rs_ber;
-	if (cx22702_readreg(state, 0xE4) & 0x02) {
-		/* Realtime statistics */
-		rs_ber = (cx22702_readreg(state, 0xDE) & 0x7F) << 7
-			| (cx22702_readreg(state, 0xDF) & 0x7F);
-	} else {
-		/* Averagine statistics */
-		rs_ber = (cx22702_readreg(state, 0xDE) & 0x7F) << 8
-			| cx22702_readreg(state, 0xDF);
-	}
-	*snr = ~rs_ber;
-
-	return 0;
-}
-
-static int cx22702_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
-{
-	struct cx22702_state *state = fe->demodulator_priv;
-
-	u8 _ucblocks;
-
-	/* RS Uncorrectable Packet Count then reset */
-	_ucblocks = cx22702_readreg(state, 0xE3);
-	if (state->prevUCBlocks < _ucblocks)
-		*ucblocks = (_ucblocks - state->prevUCBlocks);
-	else
-		*ucblocks = state->prevUCBlocks - _ucblocks;
-	state->prevUCBlocks = _ucblocks;
-
-	return 0;
-}
-
-static int cx22702_get_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	struct cx22702_state *state = fe->demodulator_priv;
-
-	u8 reg0C = cx22702_readreg(state, 0x0C);
-
-	c->inversion = reg0C & 0x1 ? INVERSION_ON : INVERSION_OFF;
-	return cx22702_get_tps(state, c);
-}
-
-static int cx22702_get_tune_settings(struct dvb_frontend *fe,
-	struct dvb_frontend_tune_settings *tune)
-{
-	tune->min_delay_ms = 1000;
-	return 0;
-}
-
-static void cx22702_release(struct dvb_frontend *fe)
-{
-	struct cx22702_state *state = fe->demodulator_priv;
-	kfree(state);
-}
-
-static const struct dvb_frontend_ops cx22702_ops;
-
-struct dvb_frontend *cx22702_attach(const struct cx22702_config *config,
-	struct i2c_adapter *i2c)
-{
-	struct cx22702_state *state = NULL;
-
-	/* allocate memory for the internal state */
-	state = kzalloc(sizeof(struct cx22702_state), GFP_KERNEL);
-	if (state == NULL)
-		goto error;
-
-	/* setup the state */
-	state->config = config;
-	state->i2c = i2c;
-
-	/* check if the demod is there */
-	if (cx22702_readreg(state, 0x1f) != 0x3)
-		goto error;
-
-	/* create dvb_frontend */
-	memcpy(&state->frontend.ops, &cx22702_ops,
-		sizeof(struct dvb_frontend_ops));
-	state->frontend.demodulator_priv = state;
-	return &state->frontend;
-
-error:
-	kfree(state);
-	return NULL;
-}
-EXPORT_SYMBOL(cx22702_attach);
-
-static const struct dvb_frontend_ops cx22702_ops = {
-	.delsys = { SYS_DVBT },
-	.info = {
-		.name			= "Conexant CX22702 DVB-T",
-		.frequency_min		= 177000000,
-		.frequency_max		= 858000000,
-		.frequency_stepsize	= 166666,
-		.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_FEC_AUTO |
-		FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
-		FE_CAN_HIERARCHY_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |
-		FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_RECOVER
-	},
-
-	.release = cx22702_release,
-
-	.init = cx22702_init,
-	.i2c_gate_ctrl = cx22702_i2c_gate_ctrl,
-
-	.set_frontend = cx22702_set_tps,
-	.get_frontend = cx22702_get_frontend,
-	.get_tune_settings = cx22702_get_tune_settings,
-
-	.read_status = cx22702_read_status,
-	.read_ber = cx22702_read_ber,
-	.read_signal_strength = cx22702_read_signal_strength,
-	.read_snr = cx22702_read_snr,
-	.read_ucblocks = cx22702_read_ucblocks,
-};
-
-MODULE_DESCRIPTION("Conexant CX22702 DVB-T Demodulator driver");
-MODULE_AUTHOR("Steven Toth");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/cx22702.h b/drivers/media/dvb/frontends/cx22702.h
deleted file mode 100644
index f154e1f..0000000
--- a/drivers/media/dvb/frontends/cx22702.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
-    Conexant 22702 DVB OFDM demodulator driver
-
-    based on:
-	Alps TDMB7 DVB OFDM demodulator driver
-
-    Copyright (C) 2001-2002 Convergence Integrated Media GmbH
-	  Holger Waechtler <holger@convergence.de>
-
-    Copyright (C) 2004 Steven Toth <stoth@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 CX22702_H
-#define CX22702_H
-
-#include <linux/dvb/frontend.h>
-
-struct cx22702_config {
-	/* the demodulator's i2c address */
-	u8 demod_address;
-
-	/* serial/parallel output */
-#define CX22702_PARALLEL_OUTPUT 0
-#define CX22702_SERIAL_OUTPUT   1
-	u8 output_mode;
-};
-
-#if defined(CONFIG_DVB_CX22702) || (defined(CONFIG_DVB_CX22702_MODULE) \
-	&& defined(MODULE))
-extern struct dvb_frontend *cx22702_attach(
-	const struct cx22702_config *config,
-	struct i2c_adapter *i2c);
-#else
-static inline struct dvb_frontend *cx22702_attach(
-	const struct cx22702_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/cx24110.c b/drivers/media/dvb/frontends/cx24110.c
deleted file mode 100644
index 3180f5b..0000000
--- a/drivers/media/dvb/frontends/cx24110.c
+++ /dev/null
@@ -1,666 +0,0 @@
-/*
-    cx24110 - Single Chip Satellite Channel Receiver driver module
-
-    Copyright (C) 2002 Peter Hettkamp <peter.hettkamp@htp-tel.de> based on
-    work
-    Copyright (C) 1999 Convergence Integrated Media GmbH <ralph@convergence.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/slab.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-
-#include "dvb_frontend.h"
-#include "cx24110.h"
-
-
-struct cx24110_state {
-
-	struct i2c_adapter* i2c;
-
-	const struct cx24110_config* config;
-
-	struct dvb_frontend frontend;
-
-	u32 lastber;
-	u32 lastbler;
-	u32 lastesn0;
-};
-
-static int debug;
-#define dprintk(args...) \
-	do { \
-		if (debug) printk(KERN_DEBUG "cx24110: " args); \
-	} while (0)
-
-static struct {u8 reg; u8 data;} cx24110_regdata[]=
-		      /* Comments beginning with @ denote this value should
-			 be the default */
-	{{0x09,0x01}, /* SoftResetAll */
-	 {0x09,0x00}, /* release reset */
-	 {0x01,0xe8}, /* MSB of code rate 27.5MS/s */
-	 {0x02,0x17}, /* middle byte " */
-	 {0x03,0x29}, /* LSB         " */
-	 {0x05,0x03}, /* @ DVB mode, standard code rate 3/4 */
-	 {0x06,0xa5}, /* @ PLL 60MHz */
-	 {0x07,0x01}, /* @ Fclk, i.e. sampling clock, 60MHz */
-	 {0x0a,0x00}, /* @ partial chip disables, do not set */
-	 {0x0b,0x01}, /* set output clock in gapped mode, start signal low
-			 active for first byte */
-	 {0x0c,0x11}, /* no parity bytes, large hold time, serial data out */
-	 {0x0d,0x6f}, /* @ RS Sync/Unsync thresholds */
-	 {0x10,0x40}, /* chip doc is misleading here: write bit 6 as 1
-			 to avoid starting the BER counter. Reset the
-			 CRC test bit. Finite counting selected */
-	 {0x15,0xff}, /* @ size of the limited time window for RS BER
-			 estimation. It is <value>*256 RS blocks, this
-			 gives approx. 2.6 sec at 27.5MS/s, rate 3/4 */
-	 {0x16,0x00}, /* @ enable all RS output ports */
-	 {0x17,0x04}, /* @ time window allowed for the RS to sync */
-	 {0x18,0xae}, /* @ allow all standard DVB code rates to be scanned
-			 for automatically */
-		      /* leave the current code rate and normalization
-			 registers as they are after reset... */
-	 {0x21,0x10}, /* @ during AutoAcq, search each viterbi setting
-			 only once */
-	 {0x23,0x18}, /* @ size of the limited time window for Viterbi BER
-			 estimation. It is <value>*65536 channel bits, i.e.
-			 approx. 38ms at 27.5MS/s, rate 3/4 */
-	 {0x24,0x24}, /* do not trigger Viterbi CRC test. Finite count window */
-		      /* leave front-end AGC parameters at default values */
-		      /* leave decimation AGC parameters at default values */
-	 {0x35,0x40}, /* disable all interrupts. They are not connected anyway */
-	 {0x36,0xff}, /* clear all interrupt pending flags */
-	 {0x37,0x00}, /* @ fully enable AutoAcqq state machine */
-	 {0x38,0x07}, /* @ enable fade recovery, but not autostart AutoAcq */
-		      /* leave the equalizer parameters on their default values */
-		      /* leave the final AGC parameters on their default values */
-	 {0x41,0x00}, /* @ MSB of front-end derotator frequency */
-	 {0x42,0x00}, /* @ middle bytes " */
-	 {0x43,0x00}, /* @ LSB          " */
-		      /* leave the carrier tracking loop parameters on default */
-		      /* leave the bit timing loop parameters at default */
-	 {0x56,0x4d}, /* set the filtune voltage to 2.7V, as recommended by */
-		      /* the cx24108 data sheet for symbol rates above 15MS/s */
-	 {0x57,0x00}, /* @ Filter sigma delta enabled, positive */
-	 {0x61,0x95}, /* GPIO pins 1-4 have special function */
-	 {0x62,0x05}, /* GPIO pin 5 has special function, pin 6 is GPIO */
-	 {0x63,0x00}, /* All GPIO pins use CMOS output characteristics */
-	 {0x64,0x20}, /* GPIO 6 is input, all others are outputs */
-	 {0x6d,0x30}, /* tuner auto mode clock freq 62kHz */
-	 {0x70,0x15}, /* use auto mode, tuner word is 21 bits long */
-	 {0x73,0x00}, /* @ disable several demod bypasses */
-	 {0x74,0x00}, /* @  " */
-	 {0x75,0x00}  /* @  " */
-		      /* the remaining registers are for SEC */
-	};
-
-
-static int cx24110_writereg (struct cx24110_state* state, int reg, int data)
-{
-	u8 buf [] = { reg, data };
-	struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 };
-	int err;
-
-	if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
-		dprintk ("%s: writereg error (err == %i, reg == 0x%02x,"
-			 " data == 0x%02x)\n", __func__, err, reg, data);
-		return -EREMOTEIO;
-	}
-
-	return 0;
-}
-
-static int cx24110_readreg (struct cx24110_state* state, u8 reg)
-{
-	int ret;
-	u8 b0 [] = { reg };
-	u8 b1 [] = { 0 };
-	struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 },
-			   { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } };
-
-	ret = i2c_transfer(state->i2c, msg, 2);
-
-	if (ret != 2) return ret;
-
-	return b1[0];
-}
-
-static int cx24110_set_inversion (struct cx24110_state* state, fe_spectral_inversion_t inversion)
-{
-/* fixme (low): error handling */
-
-	switch (inversion) {
-	case INVERSION_OFF:
-		cx24110_writereg(state,0x37,cx24110_readreg(state,0x37)|0x1);
-		/* AcqSpectrInvDis on. No idea why someone should want this */
-		cx24110_writereg(state,0x5,cx24110_readreg(state,0x5)&0xf7);
-		/* Initial value 0 at start of acq */
-		cx24110_writereg(state,0x22,cx24110_readreg(state,0x22)&0xef);
-		/* current value 0 */
-		/* The cx24110 manual tells us this reg is read-only.
-		   But what the heck... set it ayways */
-		break;
-	case INVERSION_ON:
-		cx24110_writereg(state,0x37,cx24110_readreg(state,0x37)|0x1);
-		/* AcqSpectrInvDis on. No idea why someone should want this */
-		cx24110_writereg(state,0x5,cx24110_readreg(state,0x5)|0x08);
-		/* Initial value 1 at start of acq */
-		cx24110_writereg(state,0x22,cx24110_readreg(state,0x22)|0x10);
-		/* current value 1 */
-		break;
-	case INVERSION_AUTO:
-		cx24110_writereg(state,0x37,cx24110_readreg(state,0x37)&0xfe);
-		/* AcqSpectrInvDis off. Leave initial & current states as is */
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int cx24110_set_fec (struct cx24110_state* state, fe_code_rate_t fec)
-{
-/* fixme (low): error handling */
-
-	static const int rate[]={-1,1,2,3,5,7,-1};
-	static const int g1[]={-1,0x01,0x02,0x05,0x15,0x45,-1};
-	static const int g2[]={-1,0x01,0x03,0x06,0x1a,0x7a,-1};
-
-	/* Well, the AutoAcq engine of the cx24106 and 24110 automatically
-	   searches all enabled viterbi rates, and can handle non-standard
-	   rates as well. */
-
-	if (fec>FEC_AUTO)
-		fec=FEC_AUTO;
-
-	if (fec==FEC_AUTO) { /* (re-)establish AutoAcq behaviour */
-		cx24110_writereg(state,0x37,cx24110_readreg(state,0x37)&0xdf);
-		/* clear AcqVitDis bit */
-		cx24110_writereg(state,0x18,0xae);
-		/* allow all DVB standard code rates */
-		cx24110_writereg(state,0x05,(cx24110_readreg(state,0x05)&0xf0)|0x3);
-		/* set nominal Viterbi rate 3/4 */
-		cx24110_writereg(state,0x22,(cx24110_readreg(state,0x22)&0xf0)|0x3);
-		/* set current Viterbi rate 3/4 */
-		cx24110_writereg(state,0x1a,0x05); cx24110_writereg(state,0x1b,0x06);
-		/* set the puncture registers for code rate 3/4 */
-		return 0;
-	} else {
-		cx24110_writereg(state,0x37,cx24110_readreg(state,0x37)|0x20);
-		/* set AcqVitDis bit */
-		if(rate[fec]>0) {
-			cx24110_writereg(state,0x05,(cx24110_readreg(state,0x05)&0xf0)|rate[fec]);
-			/* set nominal Viterbi rate */
-			cx24110_writereg(state,0x22,(cx24110_readreg(state,0x22)&0xf0)|rate[fec]);
-			/* set current Viterbi rate */
-			cx24110_writereg(state,0x1a,g1[fec]);
-			cx24110_writereg(state,0x1b,g2[fec]);
-			/* not sure if this is the right way: I always used AutoAcq mode */
-	   } else
-		   return -EOPNOTSUPP;
-/* fixme (low): which is the correct return code? */
-	};
-	return 0;
-}
-
-static fe_code_rate_t cx24110_get_fec (struct cx24110_state* state)
-{
-	int i;
-
-	i=cx24110_readreg(state,0x22)&0x0f;
-	if(!(i&0x08)) {
-		return FEC_1_2 + i - 1;
-	} else {
-/* fixme (low): a special code rate has been selected. In theory, we need to
-   return a denominator value, a numerator value, and a pair of puncture
-   maps to correctly describe this mode. But this should never happen in
-   practice, because it cannot be set by cx24110_get_fec. */
-	   return FEC_NONE;
-	}
-}
-
-static int cx24110_set_symbolrate (struct cx24110_state* state, u32 srate)
-{
-/* fixme (low): add error handling */
-	u32 ratio;
-	u32 tmp, fclk, BDRI;
-
-	static const u32 bands[]={5000000UL,15000000UL,90999000UL/2};
-	int i;
-
-	dprintk("cx24110 debug: entering %s(%d)\n",__func__,srate);
-	if (srate>90999000UL/2)
-		srate=90999000UL/2;
-	if (srate<500000)
-		srate=500000;
-
-	for(i = 0; (i < ARRAY_SIZE(bands)) && (srate>bands[i]); i++)
-		;
-	/* first, check which sample rate is appropriate: 45, 60 80 or 90 MHz,
-	   and set the PLL accordingly (R07[1:0] Fclk, R06[7:4] PLLmult,
-	   R06[3:0] PLLphaseDetGain */
-	tmp=cx24110_readreg(state,0x07)&0xfc;
-	if(srate<90999000UL/4) { /* sample rate 45MHz*/
-		cx24110_writereg(state,0x07,tmp);
-		cx24110_writereg(state,0x06,0x78);
-		fclk=90999000UL/2;
-	} else if(srate<60666000UL/2) { /* sample rate 60MHz */
-		cx24110_writereg(state,0x07,tmp|0x1);
-		cx24110_writereg(state,0x06,0xa5);
-		fclk=60666000UL;
-	} else if(srate<80888000UL/2) { /* sample rate 80MHz */
-		cx24110_writereg(state,0x07,tmp|0x2);
-		cx24110_writereg(state,0x06,0x87);
-		fclk=80888000UL;
-	} else { /* sample rate 90MHz */
-		cx24110_writereg(state,0x07,tmp|0x3);
-		cx24110_writereg(state,0x06,0x78);
-		fclk=90999000UL;
-	};
-	dprintk("cx24110 debug: fclk %d Hz\n",fclk);
-	/* we need to divide two integers with approx. 27 bits in 32 bit
-	   arithmetic giving a 25 bit result */
-	/* the maximum dividend is 90999000/2, 0x02b6446c, this number is
-	   also the most complex divisor. Hence, the dividend has,
-	   assuming 32bit unsigned arithmetic, 6 clear bits on top, the
-	   divisor 2 unused bits at the bottom. Also, the quotient is
-	   always less than 1/2. Borrowed from VES1893.c, of course */
-
-	tmp=srate<<6;
-	BDRI=fclk>>2;
-	ratio=(tmp/BDRI);
-
-	tmp=(tmp%BDRI)<<8;
-	ratio=(ratio<<8)+(tmp/BDRI);
-
-	tmp=(tmp%BDRI)<<8;
-	ratio=(ratio<<8)+(tmp/BDRI);
-
-	tmp=(tmp%BDRI)<<1;
-	ratio=(ratio<<1)+(tmp/BDRI);
-
-	dprintk("srate= %d (range %d, up to %d)\n", srate,i,bands[i]);
-	dprintk("fclk = %d\n", fclk);
-	dprintk("ratio= %08x\n", ratio);
-
-	cx24110_writereg(state, 0x1, (ratio>>16)&0xff);
-	cx24110_writereg(state, 0x2, (ratio>>8)&0xff);
-	cx24110_writereg(state, 0x3, (ratio)&0xff);
-
-	return 0;
-
-}
-
-static int _cx24110_pll_write (struct dvb_frontend* fe, const u8 buf[], int len)
-{
-	struct cx24110_state *state = fe->demodulator_priv;
-
-	if (len != 3)
-		return -EINVAL;
-
-/* tuner data is 21 bits long, must be left-aligned in data */
-/* tuner cx24108 is written through a dedicated 3wire interface on the demod chip */
-/* FIXME (low): add error handling, avoid infinite loops if HW fails... */
-
-	cx24110_writereg(state,0x6d,0x30); /* auto mode at 62kHz */
-	cx24110_writereg(state,0x70,0x15); /* auto mode 21 bits */
-
-	/* if the auto tuner writer is still busy, clear it out */
-	while (cx24110_readreg(state,0x6d)&0x80)
-		cx24110_writereg(state,0x72,0);
-
-	/* write the topmost 8 bits */
-	cx24110_writereg(state,0x72,buf[0]);
-
-	/* wait for the send to be completed */
-	while ((cx24110_readreg(state,0x6d)&0xc0)==0x80)
-		;
-
-	/* send another 8 bytes */
-	cx24110_writereg(state,0x72,buf[1]);
-	while ((cx24110_readreg(state,0x6d)&0xc0)==0x80)
-		;
-
-	/* and the topmost 5 bits of this byte */
-	cx24110_writereg(state,0x72,buf[2]);
-	while ((cx24110_readreg(state,0x6d)&0xc0)==0x80)
-		;
-
-	/* now strobe the enable line once */
-	cx24110_writereg(state,0x6d,0x32);
-	cx24110_writereg(state,0x6d,0x30);
-
-	return 0;
-}
-
-static int cx24110_initfe(struct dvb_frontend* fe)
-{
-	struct cx24110_state *state = fe->demodulator_priv;
-/* fixme (low): error handling */
-	int i;
-
-	dprintk("%s: init chip\n", __func__);
-
-	for(i = 0; i < ARRAY_SIZE(cx24110_regdata); i++) {
-		cx24110_writereg(state, cx24110_regdata[i].reg, cx24110_regdata[i].data);
-	};
-
-	return 0;
-}
-
-static int cx24110_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltage)
-{
-	struct cx24110_state *state = fe->demodulator_priv;
-
-	switch (voltage) {
-	case SEC_VOLTAGE_13:
-		return cx24110_writereg(state,0x76,(cx24110_readreg(state,0x76)&0x3b)|0xc0);
-	case SEC_VOLTAGE_18:
-		return cx24110_writereg(state,0x76,(cx24110_readreg(state,0x76)&0x3b)|0x40);
-	default:
-		return -EINVAL;
-	};
-}
-
-static int cx24110_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t burst)
-{
-	int rv, bit;
-	struct cx24110_state *state = fe->demodulator_priv;
-	unsigned long timeout;
-
-	if (burst == SEC_MINI_A)
-		bit = 0x00;
-	else if (burst == SEC_MINI_B)
-		bit = 0x08;
-	else
-		return -EINVAL;
-
-	rv = cx24110_readreg(state, 0x77);
-	if (!(rv & 0x04))
-		cx24110_writereg(state, 0x77, rv | 0x04);
-
-	rv = cx24110_readreg(state, 0x76);
-	cx24110_writereg(state, 0x76, ((rv & 0x90) | 0x40 | bit));
-	timeout = jiffies + msecs_to_jiffies(100);
-	while (!time_after(jiffies, timeout) && !(cx24110_readreg(state, 0x76) & 0x40))
-		; /* wait for LNB ready */
-
-	return 0;
-}
-
-static int cx24110_send_diseqc_msg(struct dvb_frontend* fe,
-				   struct dvb_diseqc_master_cmd *cmd)
-{
-	int i, rv;
-	struct cx24110_state *state = fe->demodulator_priv;
-	unsigned long timeout;
-
-	if (cmd->msg_len < 3 || cmd->msg_len > 6)
-		return -EINVAL;  /* not implemented */
-
-	for (i = 0; i < cmd->msg_len; i++)
-		cx24110_writereg(state, 0x79 + i, cmd->msg[i]);
-
-	rv = cx24110_readreg(state, 0x77);
-	if (rv & 0x04) {
-		cx24110_writereg(state, 0x77, rv & ~0x04);
-		msleep(30); /* reportedly fixes switching problems */
-	}
-
-	rv = cx24110_readreg(state, 0x76);
-
-	cx24110_writereg(state, 0x76, ((rv & 0x90) | 0x40) | ((cmd->msg_len-3) & 3));
-	timeout = jiffies + msecs_to_jiffies(100);
-	while (!time_after(jiffies, timeout) && !(cx24110_readreg(state, 0x76) & 0x40))
-		; /* wait for LNB ready */
-
-	return 0;
-}
-
-static int cx24110_read_status(struct dvb_frontend* fe, fe_status_t* status)
-{
-	struct cx24110_state *state = fe->demodulator_priv;
-
-	int sync = cx24110_readreg (state, 0x55);
-
-	*status = 0;
-
-	if (sync & 0x10)
-		*status |= FE_HAS_SIGNAL;
-
-	if (sync & 0x08)
-		*status |= FE_HAS_CARRIER;
-
-	sync = cx24110_readreg (state, 0x08);
-
-	if (sync & 0x40)
-		*status |= FE_HAS_VITERBI;
-
-	if (sync & 0x20)
-		*status |= FE_HAS_SYNC;
-
-	if ((sync & 0x60) == 0x60)
-		*status |= FE_HAS_LOCK;
-
-	return 0;
-}
-
-static int cx24110_read_ber(struct dvb_frontend* fe, u32* ber)
-{
-	struct cx24110_state *state = fe->demodulator_priv;
-
-	/* fixme (maybe): value range is 16 bit. Scale? */
-	if(cx24110_readreg(state,0x24)&0x10) {
-		/* the Viterbi error counter has finished one counting window */
-		cx24110_writereg(state,0x24,0x04); /* select the ber reg */
-		state->lastber=cx24110_readreg(state,0x25)|
-			(cx24110_readreg(state,0x26)<<8);
-		cx24110_writereg(state,0x24,0x04); /* start new count window */
-		cx24110_writereg(state,0x24,0x14);
-	}
-	*ber = state->lastber;
-
-	return 0;
-}
-
-static int cx24110_read_signal_strength(struct dvb_frontend* fe, u16* signal_strength)
-{
-	struct cx24110_state *state = fe->demodulator_priv;
-
-/* no provision in hardware. Read the frontend AGC accumulator. No idea how to scale this, but I know it is 2s complement */
-	u8 signal = cx24110_readreg (state, 0x27)+128;
-	*signal_strength = (signal << 8) | signal;
-
-	return 0;
-}
-
-static int cx24110_read_snr(struct dvb_frontend* fe, u16* snr)
-{
-	struct cx24110_state *state = fe->demodulator_priv;
-
-	/* no provision in hardware. Can be computed from the Es/N0 estimator, but I don't know how. */
-	if(cx24110_readreg(state,0x6a)&0x80) {
-		/* the Es/N0 error counter has finished one counting window */
-		state->lastesn0=cx24110_readreg(state,0x69)|
-			(cx24110_readreg(state,0x68)<<8);
-		cx24110_writereg(state,0x6a,0x84); /* start new count window */
-	}
-	*snr = state->lastesn0;
-
-	return 0;
-}
-
-static int cx24110_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
-{
-	struct cx24110_state *state = fe->demodulator_priv;
-
-	if(cx24110_readreg(state,0x10)&0x40) {
-		/* the RS error counter has finished one counting window */
-		cx24110_writereg(state,0x10,0x60); /* select the byer reg */
-		(void)(cx24110_readreg(state, 0x12) |
-			(cx24110_readreg(state, 0x13) << 8) |
-			(cx24110_readreg(state, 0x14) << 16));
-		cx24110_writereg(state,0x10,0x70); /* select the bler reg */
-		state->lastbler=cx24110_readreg(state,0x12)|
-			(cx24110_readreg(state,0x13)<<8)|
-			(cx24110_readreg(state,0x14)<<16);
-		cx24110_writereg(state,0x10,0x20); /* start new count window */
-	}
-	*ucblocks = state->lastbler;
-
-	return 0;
-}
-
-static int cx24110_set_frontend(struct dvb_frontend *fe)
-{
-	struct cx24110_state *state = fe->demodulator_priv;
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-
-	if (fe->ops.tuner_ops.set_params) {
-		fe->ops.tuner_ops.set_params(fe);
-		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
-	}
-
-	cx24110_set_inversion(state, p->inversion);
-	cx24110_set_fec(state, p->fec_inner);
-	cx24110_set_symbolrate(state, p->symbol_rate);
-	cx24110_writereg(state,0x04,0x05); /* start acquisition */
-
-	return 0;
-}
-
-static int cx24110_get_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct cx24110_state *state = fe->demodulator_priv;
-	s32 afc; unsigned sclk;
-
-/* cannot read back tuner settings (freq). Need to have some private storage */
-
-	sclk = cx24110_readreg (state, 0x07) & 0x03;
-/* ok, real AFC (FEDR) freq. is afc/2^24*fsamp, fsamp=45/60/80/90MHz.
- * Need 64 bit arithmetic. Is thiss possible in the kernel? */
-	if (sclk==0) sclk=90999000L/2L;
-	else if (sclk==1) sclk=60666000L;
-	else if (sclk==2) sclk=80888000L;
-	else sclk=90999000L;
-	sclk>>=8;
-	afc = sclk*(cx24110_readreg (state, 0x44)&0x1f)+
-	      ((sclk*cx24110_readreg (state, 0x45))>>8)+
-	      ((sclk*cx24110_readreg (state, 0x46))>>16);
-
-	p->frequency += afc;
-	p->inversion = (cx24110_readreg (state, 0x22) & 0x10) ?
-				INVERSION_ON : INVERSION_OFF;
-	p->fec_inner = cx24110_get_fec(state);
-
-	return 0;
-}
-
-static int cx24110_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
-{
-	struct cx24110_state *state = fe->demodulator_priv;
-
-	return cx24110_writereg(state,0x76,(cx24110_readreg(state,0x76)&~0x10)|(((tone==SEC_TONE_ON))?0x10:0));
-}
-
-static void cx24110_release(struct dvb_frontend* fe)
-{
-	struct cx24110_state* state = fe->demodulator_priv;
-	kfree(state);
-}
-
-static struct dvb_frontend_ops cx24110_ops;
-
-struct dvb_frontend* cx24110_attach(const struct cx24110_config* config,
-				    struct i2c_adapter* i2c)
-{
-	struct cx24110_state* state = NULL;
-	int ret;
-
-	/* allocate memory for the internal state */
-	state = kzalloc(sizeof(struct cx24110_state), GFP_KERNEL);
-	if (state == NULL) goto error;
-
-	/* setup the state */
-	state->config = config;
-	state->i2c = i2c;
-	state->lastber = 0;
-	state->lastbler = 0;
-	state->lastesn0 = 0;
-
-	/* check if the demod is there */
-	ret = cx24110_readreg(state, 0x00);
-	if ((ret != 0x5a) && (ret != 0x69)) goto error;
-
-	/* create dvb_frontend */
-	memcpy(&state->frontend.ops, &cx24110_ops, sizeof(struct dvb_frontend_ops));
-	state->frontend.demodulator_priv = state;
-	return &state->frontend;
-
-error:
-	kfree(state);
-	return NULL;
-}
-
-static struct dvb_frontend_ops cx24110_ops = {
-	.delsys = { SYS_DVBS },
-	.info = {
-		.name = "Conexant CX24110 DVB-S",
-		.frequency_min = 950000,
-		.frequency_max = 2150000,
-		.frequency_stepsize = 1011,  /* kHz for QPSK frontends */
-		.frequency_tolerance = 29500,
-		.symbol_rate_min = 1000000,
-		.symbol_rate_max = 45000000,
-		.caps = FE_CAN_INVERSION_AUTO |
-			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_FEC_AUTO |
-			FE_CAN_QPSK | FE_CAN_RECOVER
-	},
-
-	.release = cx24110_release,
-
-	.init = cx24110_initfe,
-	.write = _cx24110_pll_write,
-	.set_frontend = cx24110_set_frontend,
-	.get_frontend = cx24110_get_frontend,
-	.read_status = cx24110_read_status,
-	.read_ber = cx24110_read_ber,
-	.read_signal_strength = cx24110_read_signal_strength,
-	.read_snr = cx24110_read_snr,
-	.read_ucblocks = cx24110_read_ucblocks,
-
-	.diseqc_send_master_cmd = cx24110_send_diseqc_msg,
-	.set_tone = cx24110_set_tone,
-	.set_voltage = cx24110_set_voltage,
-	.diseqc_send_burst = cx24110_diseqc_send_burst,
-};
-
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
-
-MODULE_DESCRIPTION("Conexant CX24110 DVB-S Demodulator driver");
-MODULE_AUTHOR("Peter Hettkamp");
-MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(cx24110_attach);
diff --git a/drivers/media/dvb/frontends/cx24110.h b/drivers/media/dvb/frontends/cx24110.h
deleted file mode 100644
index fdcceee..0000000
--- a/drivers/media/dvb/frontends/cx24110.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
-    cx24110 - Single Chip Satellite Channel Receiver driver module
-
-    Copyright (C) 2002 Peter Hettkamp <peter.hettkamp@htp-tel.de> based on
-    work
-    Copyright (C) 1999 Convergence Integrated Media GmbH <ralph@convergence.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 CX24110_H
-#define CX24110_H
-
-#include <linux/dvb/frontend.h>
-
-struct cx24110_config
-{
-	/* the demodulator's i2c address */
-	u8 demod_address;
-};
-
-static inline int cx24110_pll_write(struct dvb_frontend *fe, u32 val)
-{
-	u8 buf[] = {
-		(u8)((val >> 24) & 0xff),
-		(u8)((val >> 16) & 0xff),
-		(u8)((val >> 8) & 0xff)
-	};
-
-	if (fe->ops.write)
-		return fe->ops.write(fe, buf, 3);
-	return 0;
-}
-
-#if defined(CONFIG_DVB_CX24110) || (defined(CONFIG_DVB_CX24110_MODULE) && defined(MODULE))
-extern struct dvb_frontend* cx24110_attach(const struct cx24110_config* config,
-					   struct i2c_adapter* i2c);
-#else
-static inline struct dvb_frontend* cx24110_attach(const struct cx24110_config* config,
-						  struct i2c_adapter* i2c)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif // CONFIG_DVB_CX24110
-
-#endif // CX24110_H
diff --git a/drivers/media/dvb/frontends/cx24113.c b/drivers/media/dvb/frontends/cx24113.c
deleted file mode 100644
index 3883c3b..0000000
--- a/drivers/media/dvb/frontends/cx24113.c
+++ /dev/null
@@ -1,618 +0,0 @@
-/*
- *  Driver for Conexant CX24113/CX24128 Tuner (Satellite)
- *
- *  Copyright (C) 2007-8 Patrick Boettcher <pb@linuxtv.org>
- *
- *  Developed for BBTI / Technisat
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the 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/slab.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-
-#include "dvb_frontend.h"
-#include "cx24113.h"
-
-static int debug;
-
-#define cx_info(args...) do { printk(KERN_INFO "CX24113: " args); } while (0)
-#define cx_err(args...)  do { printk(KERN_ERR  "CX24113: " args); } while (0)
-
-#define dprintk(args...) \
-	do { \
-		if (debug) { \
-			printk(KERN_DEBUG "CX24113: %s: ", __func__); \
-			printk(args); \
-		} \
-	} while (0)
-
-struct cx24113_state {
-	struct i2c_adapter *i2c;
-	const struct cx24113_config *config;
-
-#define REV_CX24113 0x23
-	u8 rev;
-	u8 ver;
-
-	u8 icp_mode:1;
-
-#define ICP_LEVEL1 0
-#define ICP_LEVEL2 1
-#define ICP_LEVEL3 2
-#define ICP_LEVEL4 3
-	u8 icp_man:2;
-	u8 icp_auto_low:2;
-	u8 icp_auto_mlow:2;
-	u8 icp_auto_mhi:2;
-	u8 icp_auto_hi:2;
-	u8 icp_dig;
-
-#define LNA_MIN_GAIN 0
-#define LNA_MID_GAIN 1
-#define LNA_MAX_GAIN 2
-	u8 lna_gain:2;
-
-	u8 acp_on:1;
-
-	u8 vco_mode:2;
-	u8 vco_shift:1;
-#define VCOBANDSEL_6 0x80
-#define VCOBANDSEL_5 0x01
-#define VCOBANDSEL_4 0x02
-#define VCOBANDSEL_3 0x04
-#define VCOBANDSEL_2 0x08
-#define VCOBANDSEL_1 0x10
-	u8 vco_band;
-
-#define VCODIV4 4
-#define VCODIV2 2
-	u8 vcodiv;
-
-	u8 bs_delay:4;
-	u16 bs_freqcnt:13;
-	u16 bs_rdiv;
-	u8 prescaler_mode:1;
-
-	u8 rfvga_bias_ctrl;
-
-	s16 tuner_gain_thres;
-	u8  gain_level;
-
-	u32 frequency;
-
-	u8 refdiv;
-
-	u8 Fwindow_enabled;
-};
-
-static int cx24113_writereg(struct cx24113_state *state, int reg, int data)
-{
-	u8 buf[] = { reg, data };
-	struct i2c_msg msg = { .addr = state->config->i2c_addr,
-		.flags = 0, .buf = buf, .len = 2 };
-	int err = i2c_transfer(state->i2c, &msg, 1);
-	if (err != 1) {
-		printk(KERN_DEBUG "%s: writereg error(err == %i, reg == 0x%02x,"
-			 " data == 0x%02x)\n", __func__, err, reg, data);
-		return err;
-	}
-
-	return 0;
-}
-
-static int cx24113_readreg(struct cx24113_state *state, u8 reg)
-{
-	int ret;
-	u8 b;
-	struct i2c_msg msg[] = {
-		{ .addr = state->config->i2c_addr,
-			.flags = 0, .buf = &reg, .len = 1 },
-		{ .addr = state->config->i2c_addr,
-			.flags = I2C_M_RD, .buf = &b, .len = 1 }
-	};
-
-	ret = i2c_transfer(state->i2c, msg, 2);
-
-	if (ret != 2) {
-		printk(KERN_DEBUG "%s: reg=0x%x (error=%d)\n",
-			__func__, reg, ret);
-		return ret;
-	}
-
-	return b;
-}
-
-static void cx24113_set_parameters(struct cx24113_state *state)
-{
-	u8 r;
-
-	r = cx24113_readreg(state, 0x10) & 0x82;
-	r |= state->icp_mode;
-	r |= state->icp_man << 4;
-	r |= state->icp_dig << 2;
-	r |= state->prescaler_mode << 5;
-	cx24113_writereg(state, 0x10, r);
-
-	r = (state->icp_auto_low  << 0) | (state->icp_auto_mlow << 2)
-		| (state->icp_auto_mhi << 4) | (state->icp_auto_hi << 6);
-	cx24113_writereg(state, 0x11, r);
-
-	if (state->rev == REV_CX24113) {
-		r = cx24113_readreg(state, 0x20) & 0xec;
-		r |= state->lna_gain;
-		r |= state->rfvga_bias_ctrl << 4;
-		cx24113_writereg(state, 0x20, r);
-	}
-
-	r = cx24113_readreg(state, 0x12) & 0x03;
-	r |= state->acp_on << 2;
-	r |= state->bs_delay << 4;
-	cx24113_writereg(state, 0x12, r);
-
-	r = cx24113_readreg(state, 0x18) & 0x40;
-	r |= state->vco_shift;
-	if (state->vco_band == VCOBANDSEL_6)
-		r |= (1 << 7);
-	else
-		r |= (state->vco_band << 1);
-	cx24113_writereg(state, 0x18, r);
-
-	r  = cx24113_readreg(state, 0x14) & 0x20;
-	r |= (state->vco_mode << 6) | ((state->bs_freqcnt >> 8) & 0x1f);
-	cx24113_writereg(state, 0x14, r);
-	cx24113_writereg(state, 0x15, (state->bs_freqcnt        & 0xff));
-
-	cx24113_writereg(state, 0x16, (state->bs_rdiv >> 4) & 0xff);
-	r = (cx24113_readreg(state, 0x17) & 0x0f) |
-		((state->bs_rdiv & 0x0f) << 4);
-	cx24113_writereg(state, 0x17, r);
-}
-
-#define VGA_0 0x00
-#define VGA_1 0x04
-#define VGA_2 0x02
-#define VGA_3 0x06
-#define VGA_4 0x01
-#define VGA_5 0x05
-#define VGA_6 0x03
-#define VGA_7 0x07
-
-#define RFVGA_0 0x00
-#define RFVGA_1 0x01
-#define RFVGA_2 0x02
-#define RFVGA_3 0x03
-
-static int cx24113_set_gain_settings(struct cx24113_state *state,
-		s16 power_estimation)
-{
-	u8 ampout = cx24113_readreg(state, 0x1d) & 0xf0,
-	   vga    = cx24113_readreg(state, 0x1f) & 0x3f,
-	   rfvga  = cx24113_readreg(state, 0x20) & 0xf3;
-	u8 gain_level = power_estimation >= state->tuner_gain_thres;
-
-	dprintk("power estimation: %d, thres: %d, gain_level: %d/%d\n",
-			power_estimation, state->tuner_gain_thres,
-			state->gain_level, gain_level);
-
-	if (gain_level == state->gain_level)
-		return 0; /* nothing to be done */
-
-	ampout |= 0xf;
-
-	if (gain_level) {
-		rfvga |= RFVGA_0 << 2;
-		vga   |= (VGA_7 << 3) | VGA_7;
-	} else {
-		rfvga |= RFVGA_2 << 2;
-		vga  |= (VGA_6 << 3) | VGA_2;
-	}
-	state->gain_level = gain_level;
-
-	cx24113_writereg(state, 0x1d, ampout);
-	cx24113_writereg(state, 0x1f, vga);
-	cx24113_writereg(state, 0x20, rfvga);
-
-	return 1; /* did something */
-}
-
-static int cx24113_set_Fref(struct cx24113_state *state, u8 high)
-{
-	u8 xtal = cx24113_readreg(state, 0x02);
-	if (state->rev == 0x43 && state->vcodiv == VCODIV4)
-		high = 1;
-
-	xtal &= ~0x2;
-	if (high)
-		xtal |= high << 1;
-	return cx24113_writereg(state, 0x02, xtal);
-}
-
-static int cx24113_enable(struct cx24113_state *state, u8 enable)
-{
-	u8 r21 = (cx24113_readreg(state, 0x21) & 0xc0) | enable;
-	if (state->rev == REV_CX24113)
-		r21 |= (1 << 1);
-	return cx24113_writereg(state, 0x21, r21);
-}
-
-static int cx24113_set_bandwidth(struct cx24113_state *state, u32 bandwidth_khz)
-{
-	u8 r;
-
-	if (bandwidth_khz <= 19000)
-		r = 0x03 << 6;
-	else if (bandwidth_khz <= 25000)
-		r = 0x02 << 6;
-	else
-		r = 0x01 << 6;
-
-	dprintk("bandwidth to be set: %d\n", bandwidth_khz);
-	bandwidth_khz *= 10;
-	bandwidth_khz -= 10000;
-	bandwidth_khz /= 1000;
-	bandwidth_khz += 5;
-	bandwidth_khz /= 10;
-
-	dprintk("bandwidth: %d %d\n", r >> 6, bandwidth_khz);
-
-	r |= bandwidth_khz & 0x3f;
-
-	return cx24113_writereg(state, 0x1e, r);
-}
-
-static int cx24113_set_clk_inversion(struct cx24113_state *state, u8 on)
-{
-	u8 r = (cx24113_readreg(state, 0x10) & 0x7f) | ((on & 0x1) << 7);
-	return cx24113_writereg(state, 0x10, r);
-}
-
-static int cx24113_get_status(struct dvb_frontend *fe, u32 *status)
-{
-	struct cx24113_state *state = fe->tuner_priv;
-	u8 r = (cx24113_readreg(state, 0x10) & 0x02) >> 1;
-	if (r)
-		*status |= TUNER_STATUS_LOCKED;
-	dprintk("PLL locked: %d\n", r);
-	return 0;
-}
-
-static u8 cx24113_set_ref_div(struct cx24113_state *state, u8 refdiv)
-{
-	if (state->rev == 0x43 && state->vcodiv == VCODIV4)
-		refdiv = 2;
-	return state->refdiv = refdiv;
-}
-
-static void cx24113_calc_pll_nf(struct cx24113_state *state, u16 *n, s32 *f)
-{
-	s32 N;
-	s64 F;
-	u64 dividend;
-	u8 R, r;
-	u8 vcodiv;
-	u8 factor;
-	s32 freq_hz = state->frequency * 1000;
-
-	if (state->config->xtal_khz < 20000)
-		factor = 1;
-	else
-		factor = 2;
-
-	if (state->rev == REV_CX24113) {
-		if (state->frequency >= 1100000)
-			vcodiv = VCODIV2;
-		else
-			vcodiv = VCODIV4;
-	} else {
-		if (state->frequency >= 1165000)
-			vcodiv = VCODIV2;
-		else
-			vcodiv = VCODIV4;
-	}
-	state->vcodiv = vcodiv;
-
-	dprintk("calculating N/F for %dHz with vcodiv %d\n", freq_hz, vcodiv);
-	R = 0;
-	do {
-		R = cx24113_set_ref_div(state, R + 1);
-
-		/* calculate tuner PLL settings: */
-		N =  (freq_hz / 100 * vcodiv) * R;
-		N /= (state->config->xtal_khz) * factor * 2;
-		N += 5;     /* For round up. */
-		N /= 10;
-		N -= 32;
-	} while (N < 6 && R < 3);
-
-	if (N < 6) {
-		cx_err("strange frequency: N < 6\n");
-		return;
-	}
-	F = freq_hz;
-	F *= (u64) (R * vcodiv * 262144);
-	dprintk("1 N: %d, F: %lld, R: %d\n", N, (long long)F, R);
-	/* do_div needs an u64 as first argument */
-	dividend = F;
-	do_div(dividend, state->config->xtal_khz * 1000 * factor * 2);
-	F = dividend;
-	dprintk("2 N: %d, F: %lld, R: %d\n", N, (long long)F, R);
-	F -= (N + 32) * 262144;
-
-	dprintk("3 N: %d, F: %lld, R: %d\n", N, (long long)F, R);
-
-	if (state->Fwindow_enabled) {
-		if (F > (262144 / 2 - 1638))
-			F = 262144 / 2 - 1638;
-		if (F < (-262144 / 2 + 1638))
-			F = -262144 / 2 + 1638;
-		if ((F < 3277 && F > 0) || (F > -3277 && F < 0)) {
-			F = 0;
-			r = cx24113_readreg(state, 0x10);
-			cx24113_writereg(state, 0x10, r | (1 << 6));
-		}
-	}
-	dprintk("4 N: %d, F: %lld, R: %d\n", N, (long long)F, R);
-
-	*n = (u16) N;
-	*f = (s32) F;
-}
-
-
-static void cx24113_set_nfr(struct cx24113_state *state, u16 n, s32 f, u8 r)
-{
-	u8 reg;
-	cx24113_writereg(state, 0x19, (n >> 1) & 0xff);
-
-	reg = ((n & 0x1) << 7) | ((f >> 11) & 0x7f);
-	cx24113_writereg(state, 0x1a, reg);
-
-	cx24113_writereg(state, 0x1b, (f >> 3) & 0xff);
-
-	reg = cx24113_readreg(state, 0x1c) & 0x1f;
-	cx24113_writereg(state, 0x1c, reg | ((f & 0x7) << 5));
-
-	cx24113_set_Fref(state, r - 1);
-}
-
-static int cx24113_set_frequency(struct cx24113_state *state, u32 frequency)
-{
-	u8 r = 1; /* or 2 */
-	u16 n = 6;
-	s32 f = 0;
-
-	r = cx24113_readreg(state, 0x14);
-	cx24113_writereg(state, 0x14, r & 0x3f);
-
-	r = cx24113_readreg(state, 0x10);
-	cx24113_writereg(state, 0x10, r & 0xbf);
-
-	state->frequency = frequency;
-
-	dprintk("tuning to frequency: %d\n", frequency);
-
-	cx24113_calc_pll_nf(state, &n, &f);
-	cx24113_set_nfr(state, n, f, state->refdiv);
-
-	r = cx24113_readreg(state, 0x18) & 0xbf;
-	if (state->vcodiv != VCODIV2)
-		r |= 1 << 6;
-	cx24113_writereg(state, 0x18, r);
-
-	/* The need for this sleep is not clear. But helps in some cases */
-	msleep(5);
-
-	r = cx24113_readreg(state, 0x1c) & 0xef;
-	cx24113_writereg(state, 0x1c, r | (1 << 4));
-	return 0;
-}
-
-static int cx24113_init(struct dvb_frontend *fe)
-{
-	struct cx24113_state *state = fe->tuner_priv;
-	int ret;
-
-	state->tuner_gain_thres = -50;
-	state->gain_level = 255; /* to force a gain-setting initialization */
-	state->icp_mode = 0;
-
-	if (state->config->xtal_khz < 11000) {
-		state->icp_auto_hi  = ICP_LEVEL4;
-		state->icp_auto_mhi  = ICP_LEVEL4;
-		state->icp_auto_mlow = ICP_LEVEL3;
-		state->icp_auto_low = ICP_LEVEL3;
-	} else {
-		state->icp_auto_hi  = ICP_LEVEL4;
-		state->icp_auto_mhi  = ICP_LEVEL4;
-		state->icp_auto_mlow = ICP_LEVEL3;
-		state->icp_auto_low = ICP_LEVEL2;
-	}
-
-	state->icp_dig = ICP_LEVEL3;
-	state->icp_man = ICP_LEVEL1;
-	state->acp_on  = 1;
-	state->vco_mode = 0;
-	state->vco_shift = 0;
-	state->vco_band = VCOBANDSEL_1;
-	state->bs_delay = 8;
-	state->bs_freqcnt = 0x0fff;
-	state->bs_rdiv = 0x0fff;
-	state->prescaler_mode = 0;
-	state->lna_gain = LNA_MAX_GAIN;
-	state->rfvga_bias_ctrl = 1;
-	state->Fwindow_enabled = 1;
-
-	cx24113_set_Fref(state, 0);
-	cx24113_enable(state, 0x3d);
-	cx24113_set_parameters(state);
-
-	cx24113_set_gain_settings(state, -30);
-
-	cx24113_set_bandwidth(state, 18025);
-	cx24113_set_clk_inversion(state, 1);
-
-	if (state->config->xtal_khz >= 40000)
-		ret = cx24113_writereg(state, 0x02,
-			(cx24113_readreg(state, 0x02) & 0xfb) | (1 << 2));
-	else
-		ret = cx24113_writereg(state, 0x02,
-			(cx24113_readreg(state, 0x02) & 0xfb) | (0 << 2));
-
-	return ret;
-}
-
-static int cx24113_set_params(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	struct cx24113_state *state = fe->tuner_priv;
-	/* for a ROLL-OFF factor of 0.35, 0.2: 600, 0.25: 625 */
-	u32 roll_off = 675;
-	u32 bw;
-
-	bw  = ((c->symbol_rate/100) * roll_off) / 1000;
-	bw += (10000000/100) + 5;
-	bw /= 10;
-	bw += 1000;
-	cx24113_set_bandwidth(state, bw);
-
-	cx24113_set_frequency(state, c->frequency);
-	msleep(5);
-	return cx24113_get_status(fe, &bw);
-}
-
-static s8 cx24113_agc_table[2][10] = {
-	{-54, -41, -35, -30, -25, -21, -16, -10,  -6,  -2},
-	{-39, -35, -30, -25, -19, -15, -11,  -5,   1,   9},
-};
-
-void cx24113_agc_callback(struct dvb_frontend *fe)
-{
-	struct cx24113_state *state = fe->tuner_priv;
-	s16 s, i;
-	if (!fe->ops.read_signal_strength)
-		return;
-
-	do {
-		/* this only works with the current CX24123 implementation */
-		fe->ops.read_signal_strength(fe, (u16 *) &s);
-		s >>= 8;
-		dprintk("signal strength: %d\n", s);
-		for (i = 0; i < sizeof(cx24113_agc_table[0]); i++)
-			if (cx24113_agc_table[state->gain_level][i] > s)
-				break;
-		s = -25 - i*5;
-	} while (cx24113_set_gain_settings(state, s));
-}
-EXPORT_SYMBOL(cx24113_agc_callback);
-
-static int cx24113_get_frequency(struct dvb_frontend *fe, u32 *frequency)
-{
-	struct cx24113_state *state = fe->tuner_priv;
-	*frequency = state->frequency;
-	return 0;
-}
-
-static int cx24113_release(struct dvb_frontend *fe)
-{
-	struct cx24113_state *state = fe->tuner_priv;
-	dprintk("\n");
-	fe->tuner_priv = NULL;
-	kfree(state);
-	return 0;
-}
-
-static const struct dvb_tuner_ops cx24113_tuner_ops = {
-	.info = {
-		.name           = "Conexant CX24113",
-		.frequency_min  = 950000,
-		.frequency_max  = 2150000,
-		.frequency_step = 125,
-	},
-
-	.release       = cx24113_release,
-
-	.init          = cx24113_init,
-
-	.set_params    = cx24113_set_params,
-	.get_frequency = cx24113_get_frequency,
-	.get_status    = cx24113_get_status,
-};
-
-struct dvb_frontend *cx24113_attach(struct dvb_frontend *fe,
-		const struct cx24113_config *config, struct i2c_adapter *i2c)
-{
-	/* allocate memory for the internal state */
-	struct cx24113_state *state =
-		kzalloc(sizeof(struct cx24113_state), GFP_KERNEL);
-	int rc;
-	if (state == NULL) {
-		cx_err("Unable to kzalloc\n");
-		goto error;
-	}
-
-	/* setup the state */
-	state->config = config;
-	state->i2c = i2c;
-
-	cx_info("trying to detect myself\n");
-
-	/* making a dummy read, because of some expected troubles
-	 * after power on */
-	cx24113_readreg(state, 0x00);
-
-	rc = cx24113_readreg(state, 0x00);
-	if (rc < 0) {
-		cx_info("CX24113 not found.\n");
-		goto error;
-	}
-	state->rev = rc;
-
-	switch (rc) {
-	case 0x43:
-		cx_info("detected CX24113 variant\n");
-		break;
-	case REV_CX24113:
-		cx_info("successfully detected\n");
-		break;
-	default:
-		cx_err("unsupported device id: %x\n", state->rev);
-		goto error;
-	}
-	state->ver = cx24113_readreg(state, 0x01);
-	cx_info("version: %x\n", state->ver);
-
-	/* create dvb_frontend */
-	memcpy(&fe->ops.tuner_ops, &cx24113_tuner_ops,
-			sizeof(struct dvb_tuner_ops));
-	fe->tuner_priv = state;
-	return fe;
-
-error:
-	kfree(state);
-
-	return NULL;
-}
-EXPORT_SYMBOL(cx24113_attach);
-
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)");
-
-MODULE_AUTHOR("Patrick Boettcher <pb@linuxtv.org>");
-MODULE_DESCRIPTION("DVB Frontend module for Conexant CX24113/CX24128hardware");
-MODULE_LICENSE("GPL");
-
diff --git a/drivers/media/dvb/frontends/cx24113.h b/drivers/media/dvb/frontends/cx24113.h
deleted file mode 100644
index 01eb7b9..0000000
--- a/drivers/media/dvb/frontends/cx24113.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- *  Driver for Conexant CX24113/CX24128 Tuner (Satellite)
- *
- *  Copyright (C) 2007-8 Patrick Boettcher <pb@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 CX24113_H
-#define CX24113_H
-
-struct dvb_frontend;
-
-struct cx24113_config {
-	u8 i2c_addr; /* 0x14 or 0x54 */
-
-	u32 xtal_khz;
-};
-
-#if defined(CONFIG_DVB_TUNER_CX24113) || \
-	(defined(CONFIG_DVB_TUNER_CX24113_MODULE) && defined(MODULE))
-extern struct dvb_frontend *cx24113_attach(struct dvb_frontend *,
-	const struct cx24113_config *config, struct i2c_adapter *i2c);
-
-extern void cx24113_agc_callback(struct dvb_frontend *fe);
-#else
-static inline struct dvb_frontend *cx24113_attach(struct dvb_frontend *fe,
-	const struct cx24113_config *config, struct i2c_adapter *i2c)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-
-static inline void cx24113_agc_callback(struct dvb_frontend *fe)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-}
-#endif
-
-#endif /* CX24113_H */
diff --git a/drivers/media/dvb/frontends/cx24116.c b/drivers/media/dvb/frontends/cx24116.c
deleted file mode 100644
index b488791..0000000
--- a/drivers/media/dvb/frontends/cx24116.c
+++ /dev/null
@@ -1,1508 +0,0 @@
-/*
-    Conexant cx24116/cx24118 - DVBS/S2 Satellite demod/tuner driver
-
-    Copyright (C) 2006-2008 Steven Toth <stoth@hauppauge.com>
-    Copyright (C) 2006-2007 Georg Acher
-    Copyright (C) 2007-2008 Darron Broad
-	March 2007
-	    Fixed some bugs.
-	    Added diseqc support.
-	    Added corrected signal strength support.
-	August 2007
-	    Sync with legacy version.
-	    Some clean ups.
-    Copyright (C) 2008 Igor Liplianin
-	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
-    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/slab.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/init.h>
-#include <linux/firmware.h>
-
-#include "dvb_frontend.h"
-#include "cx24116.h"
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)");
-
-#define dprintk(args...) \
-	do { \
-		if (debug) \
-			printk(KERN_INFO "cx24116: " args); \
-	} while (0)
-
-#define CX24116_DEFAULT_FIRMWARE "dvb-fe-cx24116.fw"
-#define CX24116_SEARCH_RANGE_KHZ 5000
-
-/* known registers */
-#define CX24116_REG_COMMAND (0x00)      /* command args 0x00..0x1e */
-#define CX24116_REG_EXECUTE (0x1f)      /* execute command */
-#define CX24116_REG_MAILBOX (0x96)      /* FW or multipurpose mailbox? */
-#define CX24116_REG_RESET   (0x20)      /* reset status > 0     */
-#define CX24116_REG_SIGNAL  (0x9e)      /* signal low           */
-#define CX24116_REG_SSTATUS (0x9d)      /* signal high / status */
-#define CX24116_REG_QUALITY8 (0xa3)
-#define CX24116_REG_QSTATUS (0xbc)
-#define CX24116_REG_QUALITY0 (0xd5)
-#define CX24116_REG_BER0    (0xc9)
-#define CX24116_REG_BER8    (0xc8)
-#define CX24116_REG_BER16   (0xc7)
-#define CX24116_REG_BER24   (0xc6)
-#define CX24116_REG_UCB0    (0xcb)
-#define CX24116_REG_UCB8    (0xca)
-#define CX24116_REG_CLKDIV  (0xf3)
-#define CX24116_REG_RATEDIV (0xf9)
-
-/* configured fec (not tuned) or actual FEC (tuned) 1=1/2 2=2/3 etc */
-#define CX24116_REG_FECSTATUS (0x9c)
-
-/* FECSTATUS bits */
-/* mask to determine configured fec (not tuned) or actual fec (tuned) */
-#define CX24116_FEC_FECMASK   (0x1f)
-
-/* Select DVB-S demodulator, else DVB-S2 */
-#define CX24116_FEC_DVBS      (0x20)
-#define CX24116_FEC_UNKNOWN   (0x40)    /* Unknown/unused */
-
-/* Pilot mode requested when tuning else always reset when tuned */
-#define CX24116_FEC_PILOT     (0x80)
-
-/* arg buffer size */
-#define CX24116_ARGLEN (0x1e)
-
-/* rolloff */
-#define CX24116_ROLLOFF_020 (0x00)
-#define CX24116_ROLLOFF_025 (0x01)
-#define CX24116_ROLLOFF_035 (0x02)
-
-/* pilot bit */
-#define CX24116_PILOT_OFF (0x00)
-#define CX24116_PILOT_ON (0x40)
-
-/* signal status */
-#define CX24116_HAS_SIGNAL   (0x01)
-#define CX24116_HAS_CARRIER  (0x02)
-#define CX24116_HAS_VITERBI  (0x04)
-#define CX24116_HAS_SYNCLOCK (0x08)
-#define CX24116_HAS_UNKNOWN1 (0x10)
-#define CX24116_HAS_UNKNOWN2 (0x20)
-#define CX24116_STATUS_MASK  (0x0f)
-#define CX24116_SIGNAL_MASK  (0xc0)
-
-#define CX24116_DISEQC_TONEOFF   (0)    /* toneburst never sent */
-#define CX24116_DISEQC_TONECACHE (1)    /* toneburst cached     */
-#define CX24116_DISEQC_MESGCACHE (2)    /* message cached       */
-
-/* arg offset for DiSEqC */
-#define CX24116_DISEQC_BURST  (1)
-#define CX24116_DISEQC_ARG2_2 (2)   /* unknown value=2 */
-#define CX24116_DISEQC_ARG3_0 (3)   /* unknown value=0 */
-#define CX24116_DISEQC_ARG4_0 (4)   /* unknown value=0 */
-#define CX24116_DISEQC_MSGLEN (5)
-#define CX24116_DISEQC_MSGOFS (6)
-
-/* DiSEqC burst */
-#define CX24116_DISEQC_MINI_A (0)
-#define CX24116_DISEQC_MINI_B (1)
-
-/* DiSEqC tone burst */
-static int toneburst = 1;
-module_param(toneburst, int, 0644);
-MODULE_PARM_DESC(toneburst, "DiSEqC toneburst 0=OFF, 1=TONE CACHE, "\
-	"2=MESSAGE CACHE (default:1)");
-
-/* SNR measurements */
-static int esno_snr;
-module_param(esno_snr, int, 0644);
-MODULE_PARM_DESC(esno_snr, "SNR return units, 0=PERCENTAGE 0-100, "\
-	"1=ESNO(db * 10) (default:0)");
-
-enum cmds {
-	CMD_SET_VCO     = 0x10,
-	CMD_TUNEREQUEST = 0x11,
-	CMD_MPEGCONFIG  = 0x13,
-	CMD_TUNERINIT   = 0x14,
-	CMD_BANDWIDTH   = 0x15,
-	CMD_GETAGC      = 0x19,
-	CMD_LNBCONFIG   = 0x20,
-	CMD_LNBSEND     = 0x21, /* Formerly CMD_SEND_DISEQC */
-	CMD_LNBDCLEVEL  = 0x22,
-	CMD_SET_TONE    = 0x23,
-	CMD_UPDFWVERS   = 0x35,
-	CMD_TUNERSLEEP  = 0x36,
-	CMD_AGCCONTROL  = 0x3b, /* Unknown */
-};
-
-/* The Demod/Tuner can't easily provide these, we cache them */
-struct cx24116_tuning {
-	u32 frequency;
-	u32 symbol_rate;
-	fe_spectral_inversion_t inversion;
-	fe_code_rate_t fec;
-
-	fe_delivery_system_t delsys;
-	fe_modulation_t modulation;
-	fe_pilot_t pilot;
-	fe_rolloff_t rolloff;
-
-	/* Demod values */
-	u8 fec_val;
-	u8 fec_mask;
-	u8 inversion_val;
-	u8 pilot_val;
-	u8 rolloff_val;
-};
-
-/* Basic commands that are sent to the firmware */
-struct cx24116_cmd {
-	u8 len;
-	u8 args[CX24116_ARGLEN];
-};
-
-struct cx24116_state {
-	struct i2c_adapter *i2c;
-	const struct cx24116_config *config;
-
-	struct dvb_frontend frontend;
-
-	struct cx24116_tuning dcur;
-	struct cx24116_tuning dnxt;
-
-	u8 skip_fw_load;
-	u8 burst;
-	struct cx24116_cmd dsec_cmd;
-};
-
-static int cx24116_writereg(struct cx24116_state *state, int reg, int data)
-{
-	u8 buf[] = { reg, data };
-	struct i2c_msg msg = { .addr = state->config->demod_address,
-		.flags = 0, .buf = buf, .len = 2 };
-	int err;
-
-	if (debug > 1)
-		printk("cx24116: %s: write reg 0x%02x, value 0x%02x\n",
-			__func__, reg, data);
-
-	err = i2c_transfer(state->i2c, &msg, 1);
-	if (err != 1) {
-		printk(KERN_ERR "%s: writereg error(err == %i, reg == 0x%02x,"
-			 " value == 0x%02x)\n", __func__, err, reg, data);
-		return -EREMOTEIO;
-	}
-
-	return 0;
-}
-
-/* Bulk byte writes to a single I2C address, for 32k firmware load */
-static int cx24116_writeregN(struct cx24116_state *state, int reg,
-			     const u8 *data, u16 len)
-{
-	int ret = -EREMOTEIO;
-	struct i2c_msg msg;
-	u8 *buf;
-
-	buf = kmalloc(len + 1, GFP_KERNEL);
-	if (buf == NULL) {
-		printk("Unable to kmalloc\n");
-		ret = -ENOMEM;
-		goto error;
-	}
-
-	*(buf) = reg;
-	memcpy(buf + 1, data, len);
-
-	msg.addr = state->config->demod_address;
-	msg.flags = 0;
-	msg.buf = buf;
-	msg.len = len + 1;
-
-	if (debug > 1)
-		printk(KERN_INFO "cx24116: %s:  write regN 0x%02x, len = %d\n",
-			__func__, reg, len);
-
-	ret = i2c_transfer(state->i2c, &msg, 1);
-	if (ret != 1) {
-		printk(KERN_ERR "%s: writereg error(err == %i, reg == 0x%02x\n",
-			 __func__, ret, reg);
-		ret = -EREMOTEIO;
-	}
-
-error:
-	kfree(buf);
-
-	return ret;
-}
-
-static int cx24116_readreg(struct cx24116_state *state, u8 reg)
-{
-	int ret;
-	u8 b0[] = { reg };
-	u8 b1[] = { 0 };
-	struct i2c_msg msg[] = {
-		{ .addr = state->config->demod_address, .flags = 0,
-			.buf = b0, .len = 1 },
-		{ .addr = state->config->demod_address, .flags = I2C_M_RD,
-			.buf = b1, .len = 1 }
-	};
-
-	ret = i2c_transfer(state->i2c, msg, 2);
-
-	if (ret != 2) {
-		printk(KERN_ERR "%s: reg=0x%x (error=%d)\n",
-			__func__, reg, ret);
-		return ret;
-	}
-
-	if (debug > 1)
-		printk(KERN_INFO "cx24116: read reg 0x%02x, value 0x%02x\n",
-			reg, b1[0]);
-
-	return b1[0];
-}
-
-static int cx24116_set_inversion(struct cx24116_state *state,
-	fe_spectral_inversion_t inversion)
-{
-	dprintk("%s(%d)\n", __func__, inversion);
-
-	switch (inversion) {
-	case INVERSION_OFF:
-		state->dnxt.inversion_val = 0x00;
-		break;
-	case INVERSION_ON:
-		state->dnxt.inversion_val = 0x04;
-		break;
-	case INVERSION_AUTO:
-		state->dnxt.inversion_val = 0x0C;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	state->dnxt.inversion = inversion;
-
-	return 0;
-}
-
-/*
- * modfec (modulation and FEC)
- * ===========================
- *
- * MOD          FEC             mask/val    standard
- * ----         --------        ----------- --------
- * QPSK         FEC_1_2         0x02 0x02+X DVB-S
- * QPSK         FEC_2_3         0x04 0x02+X DVB-S
- * QPSK         FEC_3_4         0x08 0x02+X DVB-S
- * QPSK         FEC_4_5         0x10 0x02+X DVB-S (?)
- * QPSK         FEC_5_6         0x20 0x02+X DVB-S
- * QPSK         FEC_6_7         0x40 0x02+X DVB-S
- * QPSK         FEC_7_8         0x80 0x02+X DVB-S
- * QPSK         FEC_8_9         0x01 0x02+X DVB-S (?) (NOT SUPPORTED?)
- * QPSK         AUTO            0xff 0x02+X DVB-S
- *
- * For DVB-S high byte probably represents FEC
- * and low byte selects the modulator. The high
- * byte is search range mask. Bit 5 may turn
- * on DVB-S and remaining bits represent some
- * kind of calibration (how/what i do not know).
- *
- * Eg.(2/3) szap "Zone Horror"
- *
- * mask/val = 0x04, 0x20
- * status 1f | signal c3c0 | snr a333 | ber 00000098 | unc 0 | FE_HAS_LOCK
- *
- * mask/val = 0x04, 0x30
- * status 1f | signal c3c0 | snr a333 | ber 00000000 | unc 0 | FE_HAS_LOCK
- *
- * After tuning FECSTATUS contains actual FEC
- * in use numbered 1 through to 8 for 1/2 .. 2/3 etc
- *
- * NBC=NOT/NON BACKWARD COMPATIBLE WITH DVB-S (DVB-S2 only)
- *
- * NBC-QPSK     FEC_1_2         0x00, 0x04      DVB-S2
- * NBC-QPSK     FEC_3_5         0x00, 0x05      DVB-S2
- * NBC-QPSK     FEC_2_3         0x00, 0x06      DVB-S2
- * NBC-QPSK     FEC_3_4         0x00, 0x07      DVB-S2
- * NBC-QPSK     FEC_4_5         0x00, 0x08      DVB-S2
- * NBC-QPSK     FEC_5_6         0x00, 0x09      DVB-S2
- * NBC-QPSK     FEC_8_9         0x00, 0x0a      DVB-S2
- * NBC-QPSK     FEC_9_10        0x00, 0x0b      DVB-S2
- *
- * NBC-8PSK     FEC_3_5         0x00, 0x0c      DVB-S2
- * NBC-8PSK     FEC_2_3         0x00, 0x0d      DVB-S2
- * NBC-8PSK     FEC_3_4         0x00, 0x0e      DVB-S2
- * NBC-8PSK     FEC_5_6         0x00, 0x0f      DVB-S2
- * NBC-8PSK     FEC_8_9         0x00, 0x10      DVB-S2
- * NBC-8PSK     FEC_9_10        0x00, 0x11      DVB-S2
- *
- * For DVB-S2 low bytes selects both modulator
- * and FEC. High byte is meaningless here. To
- * set pilot, bit 6 (0x40) is set. When inspecting
- * FECSTATUS bit 7 (0x80) represents the pilot
- * selection whilst not tuned. When tuned, actual FEC
- * in use is found in FECSTATUS as per above. Pilot
- * value is reset.
- */
-
-/* A table of modulation, fec and configuration bytes for the demod.
- * Not all S2 mmodulation schemes are support and not all rates with
- * a scheme are support. Especially, no auto detect when in S2 mode.
- */
-static struct cx24116_modfec {
-	fe_delivery_system_t delivery_system;
-	fe_modulation_t modulation;
-	fe_code_rate_t fec;
-	u8 mask;	/* In DVBS mode this is used to autodetect */
-	u8 val;		/* Passed to the firmware to indicate mode selection */
-} CX24116_MODFEC_MODES[] = {
- /* QPSK. For unknown rates we set hardware to auto detect 0xfe 0x30 */
-
- /*mod   fec       mask  val */
- { SYS_DVBS, QPSK, FEC_NONE, 0xfe, 0x30 },
- { SYS_DVBS, QPSK, FEC_1_2,  0x02, 0x2e }, /* 00000010 00101110 */
- { SYS_DVBS, QPSK, FEC_2_3,  0x04, 0x2f }, /* 00000100 00101111 */
- { SYS_DVBS, QPSK, FEC_3_4,  0x08, 0x30 }, /* 00001000 00110000 */
- { SYS_DVBS, QPSK, FEC_4_5,  0xfe, 0x30 }, /* 000?0000 ?        */
- { SYS_DVBS, QPSK, FEC_5_6,  0x20, 0x31 }, /* 00100000 00110001 */
- { SYS_DVBS, QPSK, FEC_6_7,  0xfe, 0x30 }, /* 0?000000 ?        */
- { SYS_DVBS, QPSK, FEC_7_8,  0x80, 0x32 }, /* 10000000 00110010 */
- { SYS_DVBS, QPSK, FEC_8_9,  0xfe, 0x30 }, /* 0000000? ?        */
- { SYS_DVBS, QPSK, FEC_AUTO, 0xfe, 0x30 },
- /* NBC-QPSK */
- { SYS_DVBS2, QPSK, FEC_1_2,  0x00, 0x04 },
- { SYS_DVBS2, QPSK, FEC_3_5,  0x00, 0x05 },
- { SYS_DVBS2, QPSK, FEC_2_3,  0x00, 0x06 },
- { SYS_DVBS2, QPSK, FEC_3_4,  0x00, 0x07 },
- { SYS_DVBS2, QPSK, FEC_4_5,  0x00, 0x08 },
- { SYS_DVBS2, QPSK, FEC_5_6,  0x00, 0x09 },
- { SYS_DVBS2, QPSK, FEC_8_9,  0x00, 0x0a },
- { SYS_DVBS2, QPSK, FEC_9_10, 0x00, 0x0b },
- /* 8PSK */
- { SYS_DVBS2, PSK_8, FEC_3_5,  0x00, 0x0c },
- { SYS_DVBS2, PSK_8, FEC_2_3,  0x00, 0x0d },
- { SYS_DVBS2, PSK_8, FEC_3_4,  0x00, 0x0e },
- { SYS_DVBS2, PSK_8, FEC_5_6,  0x00, 0x0f },
- { SYS_DVBS2, PSK_8, FEC_8_9,  0x00, 0x10 },
- { SYS_DVBS2, PSK_8, FEC_9_10, 0x00, 0x11 },
- /*
-  * `val' can be found in the FECSTATUS register when tuning.
-  * FECSTATUS will give the actual FEC in use if tuning was successful.
-  */
-};
-
-static int cx24116_lookup_fecmod(struct cx24116_state *state,
-	fe_delivery_system_t d, fe_modulation_t m, fe_code_rate_t f)
-{
-	int i, ret = -EOPNOTSUPP;
-
-	dprintk("%s(0x%02x,0x%02x)\n", __func__, m, f);
-
-	for (i = 0; i < ARRAY_SIZE(CX24116_MODFEC_MODES); i++) {
-		if ((d == CX24116_MODFEC_MODES[i].delivery_system) &&
-			(m == CX24116_MODFEC_MODES[i].modulation) &&
-			(f == CX24116_MODFEC_MODES[i].fec)) {
-				ret = i;
-				break;
-			}
-	}
-
-	return ret;
-}
-
-static int cx24116_set_fec(struct cx24116_state *state,
-	fe_delivery_system_t delsys, fe_modulation_t mod, fe_code_rate_t fec)
-{
-	int ret = 0;
-
-	dprintk("%s(0x%02x,0x%02x)\n", __func__, mod, fec);
-
-	ret = cx24116_lookup_fecmod(state, delsys, mod, fec);
-
-	if (ret < 0)
-		return ret;
-
-	state->dnxt.fec = fec;
-	state->dnxt.fec_val = CX24116_MODFEC_MODES[ret].val;
-	state->dnxt.fec_mask = CX24116_MODFEC_MODES[ret].mask;
-	dprintk("%s() mask/val = 0x%02x/0x%02x\n", __func__,
-		state->dnxt.fec_mask, state->dnxt.fec_val);
-
-	return 0;
-}
-
-static int cx24116_set_symbolrate(struct cx24116_state *state, u32 rate)
-{
-	dprintk("%s(%d)\n", __func__, rate);
-
-	/*  check if symbol rate is within limits */
-	if ((rate > state->frontend.ops.info.symbol_rate_max) ||
-	    (rate < state->frontend.ops.info.symbol_rate_min)) {
-		dprintk("%s() unsupported symbol_rate = %d\n", __func__, rate);
-		return -EOPNOTSUPP;
-	}
-
-	state->dnxt.symbol_rate = rate;
-	dprintk("%s() symbol_rate = %d\n", __func__, rate);
-
-	return 0;
-}
-
-static int cx24116_load_firmware(struct dvb_frontend *fe,
-	const struct firmware *fw);
-
-static int cx24116_firmware_ondemand(struct dvb_frontend *fe)
-{
-	struct cx24116_state *state = fe->demodulator_priv;
-	const struct firmware *fw;
-	int ret = 0;
-
-	dprintk("%s()\n", __func__);
-
-	if (cx24116_readreg(state, 0x20) > 0) {
-
-		if (state->skip_fw_load)
-			return 0;
-
-		/* Load firmware */
-		/* request the firmware, this will block until loaded */
-		printk(KERN_INFO "%s: Waiting for firmware upload (%s)...\n",
-			__func__, CX24116_DEFAULT_FIRMWARE);
-		ret = request_firmware(&fw, CX24116_DEFAULT_FIRMWARE,
-			state->i2c->dev.parent);
-		printk(KERN_INFO "%s: Waiting for firmware upload(2)...\n",
-			__func__);
-		if (ret) {
-			printk(KERN_ERR "%s: No firmware uploaded "
-				"(timeout or file not found?)\n", __func__);
-			return ret;
-		}
-
-		/* Make sure we don't recurse back through here
-		 * during loading */
-		state->skip_fw_load = 1;
-
-		ret = cx24116_load_firmware(fe, fw);
-		if (ret)
-			printk(KERN_ERR "%s: Writing firmware to device failed\n",
-				__func__);
-
-		release_firmware(fw);
-
-		printk(KERN_INFO "%s: Firmware upload %s\n", __func__,
-			ret == 0 ? "complete" : "failed");
-
-		/* Ensure firmware is always loaded if required */
-		state->skip_fw_load = 0;
-	}
-
-	return ret;
-}
-
-/* Take a basic firmware command structure, format it
- * and forward it for processing
- */
-static int cx24116_cmd_execute(struct dvb_frontend *fe, struct cx24116_cmd *cmd)
-{
-	struct cx24116_state *state = fe->demodulator_priv;
-	int i, ret;
-
-	dprintk("%s()\n", __func__);
-
-	/* Load the firmware if required */
-	ret = cx24116_firmware_ondemand(fe);
-	if (ret != 0) {
-		printk(KERN_ERR "%s(): Unable initialise the firmware\n",
-			__func__);
-		return ret;
-	}
-
-	/* Write the command */
-	for (i = 0; i < cmd->len ; i++) {
-		dprintk("%s: 0x%02x == 0x%02x\n", __func__, i, cmd->args[i]);
-		cx24116_writereg(state, i, cmd->args[i]);
-	}
-
-	/* Start execution and wait for cmd to terminate */
-	cx24116_writereg(state, CX24116_REG_EXECUTE, 0x01);
-	while (cx24116_readreg(state, CX24116_REG_EXECUTE)) {
-		msleep(10);
-		if (i++ > 64) {
-			/* Avoid looping forever if the firmware does
-				not respond */
-			printk(KERN_WARNING "%s() Firmware not responding\n",
-				__func__);
-			return -EREMOTEIO;
-		}
-	}
-	return 0;
-}
-
-static int cx24116_load_firmware(struct dvb_frontend *fe,
-	const struct firmware *fw)
-{
-	struct cx24116_state *state = fe->demodulator_priv;
-	struct cx24116_cmd cmd;
-	int i, ret, len, max, remaining;
-	unsigned char vers[4];
-
-	dprintk("%s\n", __func__);
-	dprintk("Firmware is %zu bytes (%02x %02x .. %02x %02x)\n",
-			fw->size,
-			fw->data[0],
-			fw->data[1],
-			fw->data[fw->size-2],
-			fw->data[fw->size-1]);
-
-	/* Toggle 88x SRST pin to reset demod */
-	if (state->config->reset_device)
-		state->config->reset_device(fe);
-
-	/* Begin the firmware load process */
-	/* Prepare the demod, load the firmware, cleanup after load */
-
-	/* Init PLL */
-	cx24116_writereg(state, 0xE5, 0x00);
-	cx24116_writereg(state, 0xF1, 0x08);
-	cx24116_writereg(state, 0xF2, 0x13);
-
-	/* Start PLL */
-	cx24116_writereg(state, 0xe0, 0x03);
-	cx24116_writereg(state, 0xe0, 0x00);
-
-	/* Unknown */
-	cx24116_writereg(state, CX24116_REG_CLKDIV, 0x46);
-	cx24116_writereg(state, CX24116_REG_RATEDIV, 0x00);
-
-	/* Unknown */
-	cx24116_writereg(state, 0xF0, 0x03);
-	cx24116_writereg(state, 0xF4, 0x81);
-	cx24116_writereg(state, 0xF5, 0x00);
-	cx24116_writereg(state, 0xF6, 0x00);
-
-	/* Split firmware to the max I2C write len and write.
-	 * Writes whole firmware as one write when i2c_wr_max is set to 0. */
-	if (state->config->i2c_wr_max)
-		max = state->config->i2c_wr_max;
-	else
-		max = INT_MAX; /* enough for 32k firmware */
-
-	for (remaining = fw->size; remaining > 0; remaining -= max - 1) {
-		len = remaining;
-		if (len > max - 1)
-			len = max - 1;
-
-		cx24116_writeregN(state, 0xF7, &fw->data[fw->size - remaining],
-			len);
-	}
-
-	cx24116_writereg(state, 0xF4, 0x10);
-	cx24116_writereg(state, 0xF0, 0x00);
-	cx24116_writereg(state, 0xF8, 0x06);
-
-	/* Firmware CMD 10: VCO config */
-	cmd.args[0x00] = CMD_SET_VCO;
-	cmd.args[0x01] = 0x05;
-	cmd.args[0x02] = 0xdc;
-	cmd.args[0x03] = 0xda;
-	cmd.args[0x04] = 0xae;
-	cmd.args[0x05] = 0xaa;
-	cmd.args[0x06] = 0x04;
-	cmd.args[0x07] = 0x9d;
-	cmd.args[0x08] = 0xfc;
-	cmd.args[0x09] = 0x06;
-	cmd.len = 0x0a;
-	ret = cx24116_cmd_execute(fe, &cmd);
-	if (ret != 0)
-		return ret;
-
-	cx24116_writereg(state, CX24116_REG_SSTATUS, 0x00);
-
-	/* Firmware CMD 14: Tuner config */
-	cmd.args[0x00] = CMD_TUNERINIT;
-	cmd.args[0x01] = 0x00;
-	cmd.args[0x02] = 0x00;
-	cmd.len = 0x03;
-	ret = cx24116_cmd_execute(fe, &cmd);
-	if (ret != 0)
-		return ret;
-
-	cx24116_writereg(state, 0xe5, 0x00);
-
-	/* Firmware CMD 13: MPEG config */
-	cmd.args[0x00] = CMD_MPEGCONFIG;
-	cmd.args[0x01] = 0x01;
-	cmd.args[0x02] = 0x75;
-	cmd.args[0x03] = 0x00;
-	if (state->config->mpg_clk_pos_pol)
-		cmd.args[0x04] = state->config->mpg_clk_pos_pol;
-	else
-		cmd.args[0x04] = 0x02;
-	cmd.args[0x05] = 0x00;
-	cmd.len = 0x06;
-	ret = cx24116_cmd_execute(fe, &cmd);
-	if (ret != 0)
-		return ret;
-
-	/* Firmware CMD 35: Get firmware version */
-	cmd.args[0x00] = CMD_UPDFWVERS;
-	cmd.len = 0x02;
-	for (i = 0; i < 4; i++) {
-		cmd.args[0x01] = i;
-		ret = cx24116_cmd_execute(fe, &cmd);
-		if (ret != 0)
-			return ret;
-		vers[i] = cx24116_readreg(state, CX24116_REG_MAILBOX);
-	}
-	printk(KERN_INFO "%s: FW version %i.%i.%i.%i\n", __func__,
-		vers[0], vers[1], vers[2], vers[3]);
-
-	return 0;
-}
-
-static int cx24116_read_status(struct dvb_frontend *fe, fe_status_t *status)
-{
-	struct cx24116_state *state = fe->demodulator_priv;
-
-	int lock = cx24116_readreg(state, CX24116_REG_SSTATUS) &
-		CX24116_STATUS_MASK;
-
-	dprintk("%s: status = 0x%02x\n", __func__, lock);
-
-	*status = 0;
-
-	if (lock & CX24116_HAS_SIGNAL)
-		*status |= FE_HAS_SIGNAL;
-	if (lock & CX24116_HAS_CARRIER)
-		*status |= FE_HAS_CARRIER;
-	if (lock & CX24116_HAS_VITERBI)
-		*status |= FE_HAS_VITERBI;
-	if (lock & CX24116_HAS_SYNCLOCK)
-		*status |= FE_HAS_SYNC | FE_HAS_LOCK;
-
-	return 0;
-}
-
-static int cx24116_read_ber(struct dvb_frontend *fe, u32 *ber)
-{
-	struct cx24116_state *state = fe->demodulator_priv;
-
-	dprintk("%s()\n", __func__);
-
-	*ber =  (cx24116_readreg(state, CX24116_REG_BER24) << 24) |
-		(cx24116_readreg(state, CX24116_REG_BER16) << 16) |
-		(cx24116_readreg(state, CX24116_REG_BER8)  << 8)  |
-		 cx24116_readreg(state, CX24116_REG_BER0);
-
-	return 0;
-}
-
-/* TODO Determine function and scale appropriately */
-static int cx24116_read_signal_strength(struct dvb_frontend *fe,
-	u16 *signal_strength)
-{
-	struct cx24116_state *state = fe->demodulator_priv;
-	struct cx24116_cmd cmd;
-	int ret;
-	u16 sig_reading;
-
-	dprintk("%s()\n", __func__);
-
-	/* Firmware CMD 19: Get AGC */
-	cmd.args[0x00] = CMD_GETAGC;
-	cmd.len = 0x01;
-	ret = cx24116_cmd_execute(fe, &cmd);
-	if (ret != 0)
-		return ret;
-
-	sig_reading =
-		(cx24116_readreg(state,
-			CX24116_REG_SSTATUS) & CX24116_SIGNAL_MASK) |
-		(cx24116_readreg(state, CX24116_REG_SIGNAL) << 6);
-	*signal_strength = 0 - sig_reading;
-
-	dprintk("%s: raw / cooked = 0x%04x / 0x%04x\n",
-		__func__, sig_reading, *signal_strength);
-
-	return 0;
-}
-
-/* SNR (0..100)% = (sig & 0xf0) * 10 + (sig & 0x0f) * 10 / 16 */
-static int cx24116_read_snr_pct(struct dvb_frontend *fe, u16 *snr)
-{
-	struct cx24116_state *state = fe->demodulator_priv;
-	u8 snr_reading;
-	static const u32 snr_tab[] = { /* 10 x Table (rounded up) */
-		0x00000, 0x0199A, 0x03333, 0x04ccD, 0x06667,
-		0x08000, 0x0999A, 0x0b333, 0x0cccD, 0x0e667,
-		0x10000, 0x1199A, 0x13333, 0x14ccD, 0x16667,
-		0x18000 };
-
-	dprintk("%s()\n", __func__);
-
-	snr_reading = cx24116_readreg(state, CX24116_REG_QUALITY0);
-
-	if (snr_reading >= 0xa0 /* 100% */)
-		*snr = 0xffff;
-	else
-		*snr = snr_tab[(snr_reading & 0xf0) >> 4] +
-			(snr_tab[(snr_reading & 0x0f)] >> 4);
-
-	dprintk("%s: raw / cooked = 0x%02x / 0x%04x\n", __func__,
-		snr_reading, *snr);
-
-	return 0;
-}
-
-/* The reelbox patches show the value in the registers represents
- * ESNO, from 0->30db (values 0->300). We provide this value by
- * default.
- */
-static int cx24116_read_snr_esno(struct dvb_frontend *fe, u16 *snr)
-{
-	struct cx24116_state *state = fe->demodulator_priv;
-
-	dprintk("%s()\n", __func__);
-
-	*snr = cx24116_readreg(state, CX24116_REG_QUALITY8) << 8 |
-		cx24116_readreg(state, CX24116_REG_QUALITY0);
-
-	dprintk("%s: raw 0x%04x\n", __func__, *snr);
-
-	return 0;
-}
-
-static int cx24116_read_snr(struct dvb_frontend *fe, u16 *snr)
-{
-	if (esno_snr == 1)
-		return cx24116_read_snr_esno(fe, snr);
-	else
-		return cx24116_read_snr_pct(fe, snr);
-}
-
-static int cx24116_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
-{
-	struct cx24116_state *state = fe->demodulator_priv;
-
-	dprintk("%s()\n", __func__);
-
-	*ucblocks = (cx24116_readreg(state, CX24116_REG_UCB8) << 8) |
-		cx24116_readreg(state, CX24116_REG_UCB0);
-
-	return 0;
-}
-
-/* Overwrite the current tuning params, we are about to tune */
-static void cx24116_clone_params(struct dvb_frontend *fe)
-{
-	struct cx24116_state *state = fe->demodulator_priv;
-	memcpy(&state->dcur, &state->dnxt, sizeof(state->dcur));
-}
-
-/* Wait for LNB */
-static int cx24116_wait_for_lnb(struct dvb_frontend *fe)
-{
-	struct cx24116_state *state = fe->demodulator_priv;
-	int i;
-
-	dprintk("%s() qstatus = 0x%02x\n", __func__,
-		cx24116_readreg(state, CX24116_REG_QSTATUS));
-
-	/* Wait for up to 300 ms */
-	for (i = 0; i < 30 ; i++) {
-		if (cx24116_readreg(state, CX24116_REG_QSTATUS) & 0x20)
-			return 0;
-		msleep(10);
-	}
-
-	dprintk("%s(): LNB not ready\n", __func__);
-
-	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)
-{
-	struct cx24116_cmd cmd;
-	int ret;
-
-	dprintk("%s(%d)\n", __func__, tone);
-	if ((tone != SEC_TONE_ON) && (tone != SEC_TONE_OFF)) {
-		printk(KERN_ERR "%s: Invalid, tone=%d\n", __func__, tone);
-		return -EINVAL;
-	}
-
-	/* Wait for LNB ready */
-	ret = cx24116_wait_for_lnb(fe);
-	if (ret != 0)
-		return ret;
-
-	/* Min delay time after DiSEqC send */
-	msleep(15); /* XXX determine is FW does this, see send_diseqc/burst */
-
-	/* Now we set the tone */
-	cmd.args[0x00] = CMD_SET_TONE;
-	cmd.args[0x01] = 0x00;
-	cmd.args[0x02] = 0x00;
-
-	switch (tone) {
-	case SEC_TONE_ON:
-		dprintk("%s: setting tone on\n", __func__);
-		cmd.args[0x03] = 0x01;
-		break;
-	case SEC_TONE_OFF:
-		dprintk("%s: setting tone off\n", __func__);
-		cmd.args[0x03] = 0x00;
-		break;
-	}
-	cmd.len = 0x04;
-
-	/* Min delay time before DiSEqC send */
-	msleep(15); /* XXX determine is FW does this, see send_diseqc/burst */
-
-	return cx24116_cmd_execute(fe, &cmd);
-}
-
-/* Initialise DiSEqC */
-static int cx24116_diseqc_init(struct dvb_frontend *fe)
-{
-	struct cx24116_state *state = fe->demodulator_priv;
-	struct cx24116_cmd cmd;
-	int ret;
-
-	/* Firmware CMD 20: LNB/DiSEqC config */
-	cmd.args[0x00] = CMD_LNBCONFIG;
-	cmd.args[0x01] = 0x00;
-	cmd.args[0x02] = 0x10;
-	cmd.args[0x03] = 0x00;
-	cmd.args[0x04] = 0x8f;
-	cmd.args[0x05] = 0x28;
-	cmd.args[0x06] = (toneburst == CX24116_DISEQC_TONEOFF) ? 0x00 : 0x01;
-	cmd.args[0x07] = 0x01;
-	cmd.len = 0x08;
-	ret = cx24116_cmd_execute(fe, &cmd);
-	if (ret != 0)
-		return ret;
-
-	/* Prepare a DiSEqC command */
-	state->dsec_cmd.args[0x00] = CMD_LNBSEND;
-
-	/* DiSEqC burst */
-	state->dsec_cmd.args[CX24116_DISEQC_BURST]  = CX24116_DISEQC_MINI_A;
-
-	/* Unknown */
-	state->dsec_cmd.args[CX24116_DISEQC_ARG2_2] = 0x02;
-	state->dsec_cmd.args[CX24116_DISEQC_ARG3_0] = 0x00;
-	/* Continuation flag? */
-	state->dsec_cmd.args[CX24116_DISEQC_ARG4_0] = 0x00;
-
-	/* DiSEqC message length */
-	state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] = 0x00;
-
-	/* Command length */
-	state->dsec_cmd.len = CX24116_DISEQC_MSGOFS;
-
-	return 0;
-}
-
-/* Send DiSEqC message with derived burst (hack) || previous burst */
-static int cx24116_send_diseqc_msg(struct dvb_frontend *fe,
-	struct dvb_diseqc_master_cmd *d)
-{
-	struct cx24116_state *state = fe->demodulator_priv;
-	int i, ret;
-
-	/* Dump DiSEqC message */
-	if (debug) {
-		printk(KERN_INFO "cx24116: %s(", __func__);
-		for (i = 0 ; i < d->msg_len ;) {
-			printk(KERN_INFO "0x%02x", d->msg[i]);
-			if (++i < d->msg_len)
-				printk(KERN_INFO ", ");
-		}
-		printk(") toneburst=%d\n", toneburst);
-	}
-
-	/* Validate length */
-	if (d->msg_len > (CX24116_ARGLEN - CX24116_DISEQC_MSGOFS))
-		return -EINVAL;
-
-	/* DiSEqC message */
-	for (i = 0; i < d->msg_len; i++)
-		state->dsec_cmd.args[CX24116_DISEQC_MSGOFS + i] = d->msg[i];
-
-	/* DiSEqC message length */
-	state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] = d->msg_len;
-
-	/* Command length */
-	state->dsec_cmd.len = CX24116_DISEQC_MSGOFS +
-		state->dsec_cmd.args[CX24116_DISEQC_MSGLEN];
-
-	/* DiSEqC toneburst */
-	if (toneburst == CX24116_DISEQC_MESGCACHE)
-		/* Message is cached */
-		return 0;
-
-	else if (toneburst == CX24116_DISEQC_TONEOFF)
-		/* Message is sent without burst */
-		state->dsec_cmd.args[CX24116_DISEQC_BURST] = 0;
-
-	else if (toneburst == CX24116_DISEQC_TONECACHE) {
-		/*
-		 * Message is sent with derived else cached burst
-		 *
-		 * WRITE PORT GROUP COMMAND 38
-		 *
-		 * 0/A/A: E0 10 38 F0..F3
-		 * 1/B/B: E0 10 38 F4..F7
-		 * 2/C/A: E0 10 38 F8..FB
-		 * 3/D/B: E0 10 38 FC..FF
-		 *
-		 * databyte[3]= 8421:8421
-		 *              ABCD:WXYZ
-		 *              CLR :SET
-		 *
-		 *              WX= PORT SELECT 0..3    (X=TONEBURST)
-		 *              Y = VOLTAGE             (0=13V, 1=18V)
-		 *              Z = BAND                (0=LOW, 1=HIGH(22K))
-		 */
-		if (d->msg_len >= 4 && d->msg[2] == 0x38)
-			state->dsec_cmd.args[CX24116_DISEQC_BURST] =
-				((d->msg[3] & 4) >> 2);
-		if (debug)
-			dprintk("%s burst=%d\n", __func__,
-				state->dsec_cmd.args[CX24116_DISEQC_BURST]);
-	}
-
-	/* Wait for LNB ready */
-	ret = cx24116_wait_for_lnb(fe);
-	if (ret != 0)
-		return ret;
-
-	/* Wait for voltage/min repeat delay */
-	msleep(100);
-
-	/* Command */
-	ret = cx24116_cmd_execute(fe, &state->dsec_cmd);
-	if (ret != 0)
-		return ret;
-	/*
-	 * Wait for send
-	 *
-	 * Eutelsat spec:
-	 * >15ms delay          + (XXX determine if FW does this, see set_tone)
-	 *  13.5ms per byte     +
-	 * >15ms delay          +
-	 *  12.5ms burst        +
-	 * >15ms delay            (XXX determine if FW does this, see set_tone)
-	 */
-	msleep((state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] << 4) +
-		((toneburst == CX24116_DISEQC_TONEOFF) ? 30 : 60));
-
-	return 0;
-}
-
-/* Send DiSEqC burst */
-static int cx24116_diseqc_send_burst(struct dvb_frontend *fe,
-	fe_sec_mini_cmd_t burst)
-{
-	struct cx24116_state *state = fe->demodulator_priv;
-	int ret;
-
-	dprintk("%s(%d) toneburst=%d\n", __func__, burst, toneburst);
-
-	/* DiSEqC burst */
-	if (burst == SEC_MINI_A)
-		state->dsec_cmd.args[CX24116_DISEQC_BURST] =
-			CX24116_DISEQC_MINI_A;
-	else if (burst == SEC_MINI_B)
-		state->dsec_cmd.args[CX24116_DISEQC_BURST] =
-			CX24116_DISEQC_MINI_B;
-	else
-		return -EINVAL;
-
-	/* DiSEqC toneburst */
-	if (toneburst != CX24116_DISEQC_MESGCACHE)
-		/* Burst is cached */
-		return 0;
-
-	/* Burst is to be sent with cached message */
-
-	/* Wait for LNB ready */
-	ret = cx24116_wait_for_lnb(fe);
-	if (ret != 0)
-		return ret;
-
-	/* Wait for voltage/min repeat delay */
-	msleep(100);
-
-	/* Command */
-	ret = cx24116_cmd_execute(fe, &state->dsec_cmd);
-	if (ret != 0)
-		return ret;
-
-	/*
-	 * Wait for send
-	 *
-	 * Eutelsat spec:
-	 * >15ms delay          + (XXX determine if FW does this, see set_tone)
-	 *  13.5ms per byte     +
-	 * >15ms delay          +
-	 *  12.5ms burst        +
-	 * >15ms delay            (XXX determine if FW does this, see set_tone)
-	 */
-	msleep((state->dsec_cmd.args[CX24116_DISEQC_MSGLEN] << 4) + 60);
-
-	return 0;
-}
-
-static void cx24116_release(struct dvb_frontend *fe)
-{
-	struct cx24116_state *state = fe->demodulator_priv;
-	dprintk("%s\n", __func__);
-	kfree(state);
-}
-
-static struct dvb_frontend_ops cx24116_ops;
-
-struct dvb_frontend *cx24116_attach(const struct cx24116_config *config,
-	struct i2c_adapter *i2c)
-{
-	struct cx24116_state *state = NULL;
-	int ret;
-
-	dprintk("%s\n", __func__);
-
-	/* allocate memory for the internal state */
-	state = kzalloc(sizeof(struct cx24116_state), GFP_KERNEL);
-	if (state == NULL)
-		goto error1;
-
-	state->config = config;
-	state->i2c = i2c;
-
-	/* check if the demod is present */
-	ret = (cx24116_readreg(state, 0xFF) << 8) |
-		cx24116_readreg(state, 0xFE);
-	if (ret != 0x0501) {
-		printk(KERN_INFO "Invalid probe, probably not a CX24116 device\n");
-		goto error2;
-	}
-
-	/* create dvb_frontend */
-	memcpy(&state->frontend.ops, &cx24116_ops,
-		sizeof(struct dvb_frontend_ops));
-	state->frontend.demodulator_priv = state;
-	return &state->frontend;
-
-error2: kfree(state);
-error1: return NULL;
-}
-EXPORT_SYMBOL(cx24116_attach);
-
-/*
- * Initialise or wake up device
- *
- * Power config will reset and load initial firmware if required
- */
-static int cx24116_initfe(struct dvb_frontend *fe)
-{
-	struct cx24116_state *state = fe->demodulator_priv;
-	struct cx24116_cmd cmd;
-	int ret;
-
-	dprintk("%s()\n", __func__);
-
-	/* Power on */
-	cx24116_writereg(state, 0xe0, 0);
-	cx24116_writereg(state, 0xe1, 0);
-	cx24116_writereg(state, 0xea, 0);
-
-	/* Firmware CMD 36: Power config */
-	cmd.args[0x00] = CMD_TUNERSLEEP;
-	cmd.args[0x01] = 0;
-	cmd.len = 0x02;
-	ret = cx24116_cmd_execute(fe, &cmd);
-	if (ret != 0)
-		return ret;
-
-	ret = cx24116_diseqc_init(fe);
-	if (ret != 0)
-		return ret;
-
-	/* HVR-4000 needs this */
-	return cx24116_set_voltage(fe, SEC_VOLTAGE_13);
-}
-
-/*
- * Put device to sleep
- */
-static int cx24116_sleep(struct dvb_frontend *fe)
-{
-	struct cx24116_state *state = fe->demodulator_priv;
-	struct cx24116_cmd cmd;
-	int ret;
-
-	dprintk("%s()\n", __func__);
-
-	/* Firmware CMD 36: Power config */
-	cmd.args[0x00] = CMD_TUNERSLEEP;
-	cmd.args[0x01] = 1;
-	cmd.len = 0x02;
-	ret = cx24116_cmd_execute(fe, &cmd);
-	if (ret != 0)
-		return ret;
-
-	/* Power off (Shutdown clocks) */
-	cx24116_writereg(state, 0xea, 0xff);
-	cx24116_writereg(state, 0xe1, 1);
-	cx24116_writereg(state, 0xe0, 1);
-
-	return 0;
-}
-
-/* dvb-core told us to tune, the tv property cache will be complete,
- * it's safe for is to pull values and use them for tuning purposes.
- */
-static int cx24116_set_frontend(struct dvb_frontend *fe)
-{
-	struct cx24116_state *state = fe->demodulator_priv;
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	struct cx24116_cmd cmd;
-	fe_status_t tunerstat;
-	int i, status, ret, retune = 1;
-
-	dprintk("%s()\n", __func__);
-
-	switch (c->delivery_system) {
-	case SYS_DVBS:
-		dprintk("%s: DVB-S delivery system selected\n", __func__);
-
-		/* Only QPSK is supported for DVB-S */
-		if (c->modulation != QPSK) {
-			dprintk("%s: unsupported modulation selected (%d)\n",
-				__func__, c->modulation);
-			return -EOPNOTSUPP;
-		}
-
-		/* Pilot doesn't exist in DVB-S, turn bit off */
-		state->dnxt.pilot_val = CX24116_PILOT_OFF;
-
-		/* DVB-S only supports 0.35 */
-		if (c->rolloff != ROLLOFF_35) {
-			dprintk("%s: unsupported rolloff selected (%d)\n",
-				__func__, c->rolloff);
-			return -EOPNOTSUPP;
-		}
-		state->dnxt.rolloff_val = CX24116_ROLLOFF_035;
-		break;
-
-	case SYS_DVBS2:
-		dprintk("%s: DVB-S2 delivery system selected\n", __func__);
-
-		/*
-		 * NBC 8PSK/QPSK with DVB-S is supported for DVB-S2,
-		 * but not hardware auto detection
-		 */
-		if (c->modulation != PSK_8 && c->modulation != QPSK) {
-			dprintk("%s: unsupported modulation selected (%d)\n",
-				__func__, c->modulation);
-			return -EOPNOTSUPP;
-		}
-
-		switch (c->pilot) {
-		case PILOT_AUTO:	/* Not supported but emulated */
-			state->dnxt.pilot_val = (c->modulation == QPSK)
-				? CX24116_PILOT_OFF : CX24116_PILOT_ON;
-			retune++;
-			break;
-		case PILOT_OFF:
-			state->dnxt.pilot_val = CX24116_PILOT_OFF;
-			break;
-		case PILOT_ON:
-			state->dnxt.pilot_val = CX24116_PILOT_ON;
-			break;
-		default:
-			dprintk("%s: unsupported pilot mode selected (%d)\n",
-				__func__, c->pilot);
-			return -EOPNOTSUPP;
-		}
-
-		switch (c->rolloff) {
-		case ROLLOFF_20:
-			state->dnxt.rolloff_val = CX24116_ROLLOFF_020;
-			break;
-		case ROLLOFF_25:
-			state->dnxt.rolloff_val = CX24116_ROLLOFF_025;
-			break;
-		case ROLLOFF_35:
-			state->dnxt.rolloff_val = CX24116_ROLLOFF_035;
-			break;
-		case ROLLOFF_AUTO:	/* Rolloff must be explicit */
-		default:
-			dprintk("%s: unsupported rolloff selected (%d)\n",
-				__func__, c->rolloff);
-			return -EOPNOTSUPP;
-		}
-		break;
-
-	default:
-		dprintk("%s: unsupported delivery system selected (%d)\n",
-			__func__, c->delivery_system);
-		return -EOPNOTSUPP;
-	}
-	state->dnxt.delsys = c->delivery_system;
-	state->dnxt.modulation = c->modulation;
-	state->dnxt.frequency = c->frequency;
-	state->dnxt.pilot = c->pilot;
-	state->dnxt.rolloff = c->rolloff;
-
-	ret = cx24116_set_inversion(state, c->inversion);
-	if (ret !=  0)
-		return ret;
-
-	/* FEC_NONE/AUTO for DVB-S2 is not supported and detected here */
-	ret = cx24116_set_fec(state, c->delivery_system, c->modulation, c->fec_inner);
-	if (ret !=  0)
-		return ret;
-
-	ret = cx24116_set_symbolrate(state, c->symbol_rate);
-	if (ret !=  0)
-		return ret;
-
-	/* discard the 'current' tuning parameters and prepare to tune */
-	cx24116_clone_params(fe);
-
-	dprintk("%s:   delsys      = %d\n", __func__, state->dcur.delsys);
-	dprintk("%s:   modulation  = %d\n", __func__, state->dcur.modulation);
-	dprintk("%s:   frequency   = %d\n", __func__, state->dcur.frequency);
-	dprintk("%s:   pilot       = %d (val = 0x%02x)\n", __func__,
-		state->dcur.pilot, state->dcur.pilot_val);
-	dprintk("%s:   retune      = %d\n", __func__, retune);
-	dprintk("%s:   rolloff     = %d (val = 0x%02x)\n", __func__,
-		state->dcur.rolloff, state->dcur.rolloff_val);
-	dprintk("%s:   symbol_rate = %d\n", __func__, state->dcur.symbol_rate);
-	dprintk("%s:   FEC         = %d (mask/val = 0x%02x/0x%02x)\n", __func__,
-		state->dcur.fec, state->dcur.fec_mask, state->dcur.fec_val);
-	dprintk("%s:   Inversion   = %d (val = 0x%02x)\n", __func__,
-		state->dcur.inversion, state->dcur.inversion_val);
-
-	/* This is also done in advise/acquire on HVR4000 but not on LITE */
-	if (state->config->set_ts_params)
-		state->config->set_ts_params(fe, 0);
-
-	/* Set/Reset B/W */
-	cmd.args[0x00] = CMD_BANDWIDTH;
-	cmd.args[0x01] = 0x01;
-	cmd.len = 0x02;
-	ret = cx24116_cmd_execute(fe, &cmd);
-	if (ret != 0)
-		return ret;
-
-	/* Prepare a tune request */
-	cmd.args[0x00] = CMD_TUNEREQUEST;
-
-	/* Frequency */
-	cmd.args[0x01] = (state->dcur.frequency & 0xff0000) >> 16;
-	cmd.args[0x02] = (state->dcur.frequency & 0x00ff00) >> 8;
-	cmd.args[0x03] = (state->dcur.frequency & 0x0000ff);
-
-	/* Symbol Rate */
-	cmd.args[0x04] = ((state->dcur.symbol_rate / 1000) & 0xff00) >> 8;
-	cmd.args[0x05] = ((state->dcur.symbol_rate / 1000) & 0x00ff);
-
-	/* Automatic Inversion */
-	cmd.args[0x06] = state->dcur.inversion_val;
-
-	/* Modulation / FEC / Pilot */
-	cmd.args[0x07] = state->dcur.fec_val | state->dcur.pilot_val;
-
-	cmd.args[0x08] = CX24116_SEARCH_RANGE_KHZ >> 8;
-	cmd.args[0x09] = CX24116_SEARCH_RANGE_KHZ & 0xff;
-	cmd.args[0x0a] = 0x00;
-	cmd.args[0x0b] = 0x00;
-	cmd.args[0x0c] = state->dcur.rolloff_val;
-	cmd.args[0x0d] = state->dcur.fec_mask;
-
-	if (state->dcur.symbol_rate > 30000000) {
-		cmd.args[0x0e] = 0x04;
-		cmd.args[0x0f] = 0x00;
-		cmd.args[0x10] = 0x01;
-		cmd.args[0x11] = 0x77;
-		cmd.args[0x12] = 0x36;
-		cx24116_writereg(state, CX24116_REG_CLKDIV, 0x44);
-		cx24116_writereg(state, CX24116_REG_RATEDIV, 0x01);
-	} else {
-		cmd.args[0x0e] = 0x06;
-		cmd.args[0x0f] = 0x00;
-		cmd.args[0x10] = 0x00;
-		cmd.args[0x11] = 0xFA;
-		cmd.args[0x12] = 0x24;
-		cx24116_writereg(state, CX24116_REG_CLKDIV, 0x46);
-		cx24116_writereg(state, CX24116_REG_RATEDIV, 0x00);
-	}
-
-	cmd.len = 0x13;
-
-	/* We need to support pilot and non-pilot tuning in the
-	 * driver automatically. This is a workaround for because
-	 * the demod does not support autodetect.
-	 */
-	do {
-		/* Reset status register */
-		status = cx24116_readreg(state, CX24116_REG_SSTATUS)
-			& CX24116_SIGNAL_MASK;
-		cx24116_writereg(state, CX24116_REG_SSTATUS, status);
-
-		/* Tune */
-		ret = cx24116_cmd_execute(fe, &cmd);
-		if (ret != 0)
-			break;
-
-		/*
-		 * Wait for up to 500 ms before retrying
-		 *
-		 * If we are able to tune then generally it occurs within 100ms.
-		 * If it takes longer, try a different toneburst setting.
-		 */
-		for (i = 0; i < 50 ; i++) {
-			cx24116_read_status(fe, &tunerstat);
-			status = tunerstat & (FE_HAS_SIGNAL | FE_HAS_SYNC);
-			if (status == (FE_HAS_SIGNAL | FE_HAS_SYNC)) {
-				dprintk("%s: Tuned\n", __func__);
-				goto tuned;
-			}
-			msleep(10);
-		}
-
-		dprintk("%s: Not tuned\n", __func__);
-
-		/* Toggle pilot bit when in auto-pilot */
-		if (state->dcur.pilot == PILOT_AUTO)
-			cmd.args[0x07] ^= CX24116_PILOT_ON;
-	} while (--retune);
-
-tuned:  /* Set/Reset B/W */
-	cmd.args[0x00] = CMD_BANDWIDTH;
-	cmd.args[0x01] = 0x00;
-	cmd.len = 0x02;
-	return cx24116_cmd_execute(fe, &cmd);
-}
-
-static int cx24116_tune(struct dvb_frontend *fe, bool re_tune,
-	unsigned int mode_flags, unsigned int *delay, fe_status_t *status)
-{
-	/*
-	 * It is safe to discard "params" here, as the DVB core will sync
-	 * fe->dtv_property_cache with fepriv->parameters_in, where the
-	 * DVBv3 params are stored. The only practical usage for it indicate
-	 * that re-tuning is needed, e. g. (fepriv->state & FESTATE_RETUNE) is
-	 * true.
-	 */
-
-	*delay = HZ / 5;
-	if (re_tune) {
-		int ret = cx24116_set_frontend(fe);
-		if (ret)
-			return ret;
-	}
-	return cx24116_read_status(fe, status);
-}
-
-static int cx24116_get_algo(struct dvb_frontend *fe)
-{
-	return DVBFE_ALGO_HW;
-}
-
-static struct dvb_frontend_ops cx24116_ops = {
-	.delsys = { SYS_DVBS, SYS_DVBS2 },
-	.info = {
-		.name = "Conexant CX24116/CX24118",
-		.frequency_min = 950000,
-		.frequency_max = 2150000,
-		.frequency_stepsize = 1011, /* kHz for QPSK frontends */
-		.frequency_tolerance = 5000,
-		.symbol_rate_min = 1000000,
-		.symbol_rate_max = 45000000,
-		.caps = FE_CAN_INVERSION_AUTO |
-			FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
-			FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
-			FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
-			FE_CAN_2G_MODULATION |
-			FE_CAN_QPSK | FE_CAN_RECOVER
-	},
-
-	.release = cx24116_release,
-
-	.init = cx24116_initfe,
-	.sleep = cx24116_sleep,
-	.read_status = cx24116_read_status,
-	.read_ber = cx24116_read_ber,
-	.read_signal_strength = cx24116_read_signal_strength,
-	.read_snr = cx24116_read_snr,
-	.read_ucblocks = cx24116_read_ucblocks,
-	.set_tone = cx24116_set_tone,
-	.set_voltage = cx24116_set_voltage,
-	.diseqc_send_master_cmd = cx24116_send_diseqc_msg,
-	.diseqc_send_burst = cx24116_diseqc_send_burst,
-	.get_frontend_algo = cx24116_get_algo,
-	.tune = cx24116_tune,
-
-	.set_frontend = cx24116_set_frontend,
-};
-
-MODULE_DESCRIPTION("DVB Frontend module for Conexant cx24116/cx24118 hardware");
-MODULE_AUTHOR("Steven Toth");
-MODULE_LICENSE("GPL");
-
diff --git a/drivers/media/dvb/frontends/cx24116.h b/drivers/media/dvb/frontends/cx24116.h
deleted file mode 100644
index 7d90ab9..0000000
--- a/drivers/media/dvb/frontends/cx24116.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
-    Conexant cx24116/cx24118 - DVBS/S2 Satellite demod/tuner driver
-
-    Copyright (C) 2006 Steven Toth <stoth@linuxtv.com>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#ifndef CX24116_H
-#define CX24116_H
-
-#include <linux/dvb/frontend.h>
-
-struct cx24116_config {
-	/* the demodulator's i2c address */
-	u8 demod_address;
-
-	/* Need to set device param for start_dma */
-	int (*set_ts_params)(struct dvb_frontend *fe, int is_punctured);
-
-	/* Need to reset device during firmware loading */
-	int (*reset_device)(struct dvb_frontend *fe);
-
-	/* Need to set MPEG parameters */
-	u8 mpg_clk_pos_pol:0x02;
-
-	/* max bytes I2C provider can write at once */
-	u16 i2c_wr_max;
-};
-
-#if defined(CONFIG_DVB_CX24116) || \
-	(defined(CONFIG_DVB_CX24116_MODULE) && defined(MODULE))
-extern struct dvb_frontend *cx24116_attach(
-	const struct cx24116_config *config,
-	struct i2c_adapter *i2c);
-#else
-static inline struct dvb_frontend *cx24116_attach(
-	const struct cx24116_config *config,
-	struct i2c_adapter *i2c)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif
-
-#endif /* CX24116_H */
diff --git a/drivers/media/dvb/frontends/cx24123.c b/drivers/media/dvb/frontends/cx24123.c
deleted file mode 100644
index 7e28b4e..0000000
--- a/drivers/media/dvb/frontends/cx24123.c
+++ /dev/null
@@ -1,1165 +0,0 @@
-/*
- *   Conexant cx24123/cx24109 - DVB QPSK Satellite demod/tuner driver
- *
- *   Copyright (C) 2005 Steven Toth <stoth@linuxtv.org>
- *
- *   Support for KWorld DVB-S 100 by Vadim Catana <skystar@moldova.cc>
- *
- *   Support for CX24123/CX24113-NIM by Patrick Boettcher <pb@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/slab.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-
-#include "dvb_frontend.h"
-#include "cx24123.h"
-
-#define XTAL 10111000
-
-static int force_band;
-module_param(force_band, int, 0644);
-MODULE_PARM_DESC(force_band, "Force a specific band select "\
-	"(1-9, default:off).");
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)");
-
-#define info(args...) do { printk(KERN_INFO "CX24123: " args); } while (0)
-#define err(args...)  do { printk(KERN_ERR  "CX24123: " args); } while (0)
-
-#define dprintk(args...) \
-	do { \
-		if (debug) { \
-			printk(KERN_DEBUG "CX24123: %s: ", __func__); \
-			printk(args); \
-		} \
-	} while (0)
-
-struct cx24123_state {
-	struct i2c_adapter *i2c;
-	const struct cx24123_config *config;
-
-	struct dvb_frontend frontend;
-
-	/* Some PLL specifics for tuning */
-	u32 VCAarg;
-	u32 VGAarg;
-	u32 bandselectarg;
-	u32 pllarg;
-	u32 FILTune;
-
-	struct i2c_adapter tuner_i2c_adapter;
-
-	u8 demod_rev;
-
-	/* The Demod/Tuner can't easily provide these, we cache them */
-	u32 currentfreq;
-	u32 currentsymbolrate;
-};
-
-/* Various tuner defaults need to be established for a given symbol rate Sps */
-static struct cx24123_AGC_val {
-	u32 symbolrate_low;
-	u32 symbolrate_high;
-	u32 VCAprogdata;
-	u32 VGAprogdata;
-	u32 FILTune;
-} cx24123_AGC_vals[] =
-{
-	{
-		.symbolrate_low		= 1000000,
-		.symbolrate_high	= 4999999,
-		/* the specs recommend other values for VGA offsets,
-		   but tests show they are wrong */
-		.VGAprogdata		= (1 << 19) | (0x180 << 9) | 0x1e0,
-		.VCAprogdata		= (2 << 19) | (0x07 << 9) | 0x07,
-		.FILTune		= 0x27f /* 0.41 V */
-	},
-	{
-		.symbolrate_low		=  5000000,
-		.symbolrate_high	= 14999999,
-		.VGAprogdata		= (1 << 19) | (0x180 << 9) | 0x1e0,
-		.VCAprogdata		= (2 << 19) | (0x07 << 9) | 0x1f,
-		.FILTune		= 0x317 /* 0.90 V */
-	},
-	{
-		.symbolrate_low		= 15000000,
-		.symbolrate_high	= 45000000,
-		.VGAprogdata		= (1 << 19) | (0x100 << 9) | 0x180,
-		.VCAprogdata		= (2 << 19) | (0x07 << 9) | 0x3f,
-		.FILTune		= 0x145 /* 2.70 V */
-	},
-};
-
-/*
- * Various tuner defaults need to be established for a given frequency kHz.
- * fixme: The bounds on the bands do not match the doc in real life.
- * fixme: Some of them have been moved, other might need adjustment.
- */
-static struct cx24123_bandselect_val {
-	u32 freq_low;
-	u32 freq_high;
-	u32 VCOdivider;
-	u32 progdata;
-} cx24123_bandselect_vals[] =
-{
-	/* band 1 */
-	{
-		.freq_low	= 950000,
-		.freq_high	= 1074999,
-		.VCOdivider	= 4,
-		.progdata	= (0 << 19) | (0 << 9) | 0x40,
-	},
-
-	/* band 2 */
-	{
-		.freq_low	= 1075000,
-		.freq_high	= 1177999,
-		.VCOdivider	= 4,
-		.progdata	= (0 << 19) | (0 << 9) | 0x80,
-	},
-
-	/* band 3 */
-	{
-		.freq_low	= 1178000,
-		.freq_high	= 1295999,
-		.VCOdivider	= 2,
-		.progdata	= (0 << 19) | (1 << 9) | 0x01,
-	},
-
-	/* band 4 */
-	{
-		.freq_low	= 1296000,
-		.freq_high	= 1431999,
-		.VCOdivider	= 2,
-		.progdata	= (0 << 19) | (1 << 9) | 0x02,
-	},
-
-	/* band 5 */
-	{
-		.freq_low	= 1432000,
-		.freq_high	= 1575999,
-		.VCOdivider	= 2,
-		.progdata	= (0 << 19) | (1 << 9) | 0x04,
-	},
-
-	/* band 6 */
-	{
-		.freq_low	= 1576000,
-		.freq_high	= 1717999,
-		.VCOdivider	= 2,
-		.progdata	= (0 << 19) | (1 << 9) | 0x08,
-	},
-
-	/* band 7 */
-	{
-		.freq_low	= 1718000,
-		.freq_high	= 1855999,
-		.VCOdivider	= 2,
-		.progdata	= (0 << 19) | (1 << 9) | 0x10,
-	},
-
-	/* band 8 */
-	{
-		.freq_low	= 1856000,
-		.freq_high	= 2035999,
-		.VCOdivider	= 2,
-		.progdata	= (0 << 19) | (1 << 9) | 0x20,
-	},
-
-	/* band 9 */
-	{
-		.freq_low	= 2036000,
-		.freq_high	= 2150000,
-		.VCOdivider	= 2,
-		.progdata	= (0 << 19) | (1 << 9) | 0x40,
-	},
-};
-
-static struct {
-	u8 reg;
-	u8 data;
-} cx24123_regdata[] =
-{
-	{0x00, 0x03}, /* Reset system */
-	{0x00, 0x00}, /* Clear reset */
-	{0x03, 0x07}, /* QPSK, DVB, Auto Acquisition (default) */
-	{0x04, 0x10}, /* MPEG */
-	{0x05, 0x04}, /* MPEG */
-	{0x06, 0x31}, /* MPEG (default) */
-	{0x0b, 0x00}, /* Freq search start point (default) */
-	{0x0c, 0x00}, /* Demodulator sample gain (default) */
-	{0x0d, 0x7f}, /* Force driver to shift until the maximum (+-10 MHz) */
-	{0x0e, 0x03}, /* Default non-inverted, FEC 3/4 (default) */
-	{0x0f, 0xfe}, /* FEC search mask (all supported codes) */
-	{0x10, 0x01}, /* Default search inversion, no repeat (default) */
-	{0x16, 0x00}, /* Enable reading of frequency */
-	{0x17, 0x01}, /* Enable EsNO Ready Counter */
-	{0x1c, 0x80}, /* Enable error counter */
-	{0x20, 0x00}, /* Tuner burst clock rate = 500KHz */
-	{0x21, 0x15}, /* Tuner burst mode, word length = 0x15 */
-	{0x28, 0x00}, /* Enable FILTERV with positive pol., DiSEqC 2.x off */
-	{0x29, 0x00}, /* DiSEqC LNB_DC off */
-	{0x2a, 0xb0}, /* DiSEqC Parameters (default) */
-	{0x2b, 0x73}, /* DiSEqC Tone Frequency (default) */
-	{0x2c, 0x00}, /* DiSEqC Message (0x2c - 0x31) */
-	{0x2d, 0x00},
-	{0x2e, 0x00},
-	{0x2f, 0x00},
-	{0x30, 0x00},
-	{0x31, 0x00},
-	{0x32, 0x8c}, /* DiSEqC Parameters (default) */
-	{0x33, 0x00}, /* Interrupts off (0x33 - 0x34) */
-	{0x34, 0x00},
-	{0x35, 0x03}, /* DiSEqC Tone Amplitude (default) */
-	{0x36, 0x02}, /* DiSEqC Parameters (default) */
-	{0x37, 0x3a}, /* DiSEqC Parameters (default) */
-	{0x3a, 0x00}, /* Enable AGC accumulator (for signal strength) */
-	{0x44, 0x00}, /* Constellation (default) */
-	{0x45, 0x00}, /* Symbol count (default) */
-	{0x46, 0x0d}, /* Symbol rate estimator on (default) */
-	{0x56, 0xc1}, /* Error Counter = Viterbi BER */
-	{0x57, 0xff}, /* Error Counter Window (default) */
-	{0x5c, 0x20}, /* Acquisition AFC Expiration window (default is 0x10) */
-	{0x67, 0x83}, /* Non-DCII symbol clock */
-};
-
-static int cx24123_i2c_writereg(struct cx24123_state *state,
-	u8 i2c_addr, int reg, int data)
-{
-	u8 buf[] = { reg, data };
-	struct i2c_msg msg = {
-		.addr = i2c_addr, .flags = 0, .buf = buf, .len = 2
-	};
-	int err;
-
-	/* printk(KERN_DEBUG "wr(%02x): %02x %02x\n", i2c_addr, reg, data); */
-
-	err = i2c_transfer(state->i2c, &msg, 1);
-	if (err != 1) {
-		printk("%s: writereg error(err == %i, reg == 0x%02x,"
-			 " data == 0x%02x)\n", __func__, err, reg, data);
-		return err;
-	}
-
-	return 0;
-}
-
-static int cx24123_i2c_readreg(struct cx24123_state *state, u8 i2c_addr, u8 reg)
-{
-	int ret;
-	u8 b = 0;
-	struct i2c_msg msg[] = {
-		{ .addr = i2c_addr, .flags = 0, .buf = &reg, .len = 1 },
-		{ .addr = i2c_addr, .flags = I2C_M_RD, .buf = &b, .len = 1 }
-	};
-
-	ret = i2c_transfer(state->i2c, msg, 2);
-
-	if (ret != 2) {
-		err("%s: reg=0x%x (error=%d)\n", __func__, reg, ret);
-		return ret;
-	}
-
-	/* printk(KERN_DEBUG "rd(%02x): %02x %02x\n", i2c_addr, reg, b); */
-
-	return b;
-}
-
-#define cx24123_readreg(state, reg) \
-	cx24123_i2c_readreg(state, state->config->demod_address, reg)
-#define cx24123_writereg(state, reg, val) \
-	cx24123_i2c_writereg(state, state->config->demod_address, reg, val)
-
-static int cx24123_set_inversion(struct cx24123_state *state,
-	fe_spectral_inversion_t inversion)
-{
-	u8 nom_reg = cx24123_readreg(state, 0x0e);
-	u8 auto_reg = cx24123_readreg(state, 0x10);
-
-	switch (inversion) {
-	case INVERSION_OFF:
-		dprintk("inversion off\n");
-		cx24123_writereg(state, 0x0e, nom_reg & ~0x80);
-		cx24123_writereg(state, 0x10, auto_reg | 0x80);
-		break;
-	case INVERSION_ON:
-		dprintk("inversion on\n");
-		cx24123_writereg(state, 0x0e, nom_reg | 0x80);
-		cx24123_writereg(state, 0x10, auto_reg | 0x80);
-		break;
-	case INVERSION_AUTO:
-		dprintk("inversion auto\n");
-		cx24123_writereg(state, 0x10, auto_reg & ~0x80);
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int cx24123_get_inversion(struct cx24123_state *state,
-	fe_spectral_inversion_t *inversion)
-{
-	u8 val;
-
-	val = cx24123_readreg(state, 0x1b) >> 7;
-
-	if (val == 0) {
-		dprintk("read inversion off\n");
-		*inversion = INVERSION_OFF;
-	} else {
-		dprintk("read inversion on\n");
-		*inversion = INVERSION_ON;
-	}
-
-	return 0;
-}
-
-static int cx24123_set_fec(struct cx24123_state *state, fe_code_rate_t fec)
-{
-	u8 nom_reg = cx24123_readreg(state, 0x0e) & ~0x07;
-
-	if ((fec < FEC_NONE) || (fec > FEC_AUTO))
-		fec = FEC_AUTO;
-
-	/* Set the soft decision threshold */
-	if (fec == FEC_1_2)
-		cx24123_writereg(state, 0x43,
-			cx24123_readreg(state, 0x43) | 0x01);
-	else
-		cx24123_writereg(state, 0x43,
-			cx24123_readreg(state, 0x43) & ~0x01);
-
-	switch (fec) {
-	case FEC_1_2:
-		dprintk("set FEC to 1/2\n");
-		cx24123_writereg(state, 0x0e, nom_reg | 0x01);
-		cx24123_writereg(state, 0x0f, 0x02);
-		break;
-	case FEC_2_3:
-		dprintk("set FEC to 2/3\n");
-		cx24123_writereg(state, 0x0e, nom_reg | 0x02);
-		cx24123_writereg(state, 0x0f, 0x04);
-		break;
-	case FEC_3_4:
-		dprintk("set FEC to 3/4\n");
-		cx24123_writereg(state, 0x0e, nom_reg | 0x03);
-		cx24123_writereg(state, 0x0f, 0x08);
-		break;
-	case FEC_4_5:
-		dprintk("set FEC to 4/5\n");
-		cx24123_writereg(state, 0x0e, nom_reg | 0x04);
-		cx24123_writereg(state, 0x0f, 0x10);
-		break;
-	case FEC_5_6:
-		dprintk("set FEC to 5/6\n");
-		cx24123_writereg(state, 0x0e, nom_reg | 0x05);
-		cx24123_writereg(state, 0x0f, 0x20);
-		break;
-	case FEC_6_7:
-		dprintk("set FEC to 6/7\n");
-		cx24123_writereg(state, 0x0e, nom_reg | 0x06);
-		cx24123_writereg(state, 0x0f, 0x40);
-		break;
-	case FEC_7_8:
-		dprintk("set FEC to 7/8\n");
-		cx24123_writereg(state, 0x0e, nom_reg | 0x07);
-		cx24123_writereg(state, 0x0f, 0x80);
-		break;
-	case FEC_AUTO:
-		dprintk("set FEC to auto\n");
-		cx24123_writereg(state, 0x0f, 0xfe);
-		break;
-	default:
-		return -EOPNOTSUPP;
-	}
-
-	return 0;
-}
-
-static int cx24123_get_fec(struct cx24123_state *state, fe_code_rate_t *fec)
-{
-	int ret;
-
-	ret = cx24123_readreg(state, 0x1b);
-	if (ret < 0)
-		return ret;
-	ret = ret & 0x07;
-
-	switch (ret) {
-	case 1:
-		*fec = FEC_1_2;
-		break;
-	case 2:
-		*fec = FEC_2_3;
-		break;
-	case 3:
-		*fec = FEC_3_4;
-		break;
-	case 4:
-		*fec = FEC_4_5;
-		break;
-	case 5:
-		*fec = FEC_5_6;
-		break;
-	case 6:
-		*fec = FEC_6_7;
-		break;
-	case 7:
-		*fec = FEC_7_8;
-		break;
-	default:
-		/* this can happen when there's no lock */
-		*fec = FEC_NONE;
-	}
-
-	return 0;
-}
-
-/* Approximation of closest integer of log2(a/b). It actually gives the
-   lowest integer i such that 2^i >= round(a/b) */
-static u32 cx24123_int_log2(u32 a, u32 b)
-{
-	u32 exp, nearest = 0;
-	u32 div = a / b;
-	if (a % b >= b / 2)
-		++div;
-	if (div < (1 << 31)) {
-		for (exp = 1; div > exp; nearest++)
-			exp += exp;
-	}
-	return nearest;
-}
-
-static int cx24123_set_symbolrate(struct cx24123_state *state, u32 srate)
-{
-	u32 tmp, sample_rate, ratio, sample_gain;
-	u8 pll_mult;
-
-	/*  check if symbol rate is within limits */
-	if ((srate > state->frontend.ops.info.symbol_rate_max) ||
-	    (srate < state->frontend.ops.info.symbol_rate_min))
-		return -EOPNOTSUPP;
-
-	/* choose the sampling rate high enough for the required operation,
-	   while optimizing the power consumed by the demodulator */
-	if (srate < (XTAL*2)/2)
-		pll_mult = 2;
-	else if (srate < (XTAL*3)/2)
-		pll_mult = 3;
-	else if (srate < (XTAL*4)/2)
-		pll_mult = 4;
-	else if (srate < (XTAL*5)/2)
-		pll_mult = 5;
-	else if (srate < (XTAL*6)/2)
-		pll_mult = 6;
-	else if (srate < (XTAL*7)/2)
-		pll_mult = 7;
-	else if (srate < (XTAL*8)/2)
-		pll_mult = 8;
-	else
-		pll_mult = 9;
-
-
-	sample_rate = pll_mult * XTAL;
-
-	/*
-	    SYSSymbolRate[21:0] = (srate << 23) / sample_rate
-
-	    We have to use 32 bit unsigned arithmetic without precision loss.
-	    The maximum srate is 45000000 or 0x02AEA540. This number has
-	    only 6 clear bits on top, hence we can shift it left only 6 bits
-	    at a time. Borrowed from cx24110.c
-	*/
-
-	tmp = srate << 6;
-	ratio = tmp / sample_rate;
-
-	tmp = (tmp % sample_rate) << 6;
-	ratio = (ratio << 6) + (tmp / sample_rate);
-
-	tmp = (tmp % sample_rate) << 6;
-	ratio = (ratio << 6) + (tmp / sample_rate);
-
-	tmp = (tmp % sample_rate) << 5;
-	ratio = (ratio << 5) + (tmp / sample_rate);
-
-
-	cx24123_writereg(state, 0x01, pll_mult * 6);
-
-	cx24123_writereg(state, 0x08, (ratio >> 16) & 0x3f);
-	cx24123_writereg(state, 0x09, (ratio >> 8) & 0xff);
-	cx24123_writereg(state, 0x0a, ratio & 0xff);
-
-	/* also set the demodulator sample gain */
-	sample_gain = cx24123_int_log2(sample_rate, srate);
-	tmp = cx24123_readreg(state, 0x0c) & ~0xe0;
-	cx24123_writereg(state, 0x0c, tmp | sample_gain << 5);
-
-	dprintk("srate=%d, ratio=0x%08x, sample_rate=%i sample_gain=%d\n",
-		srate, ratio, sample_rate, sample_gain);
-
-	return 0;
-}
-
-/*
- * Based on the required frequency and symbolrate, the tuner AGC has
- * to be configured and the correct band selected.
- * Calculate those values.
- */
-static int cx24123_pll_calculate(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct cx24123_state *state = fe->demodulator_priv;
-	u32 ndiv = 0, adiv = 0, vco_div = 0;
-	int i = 0;
-	int pump = 2;
-	int band = 0;
-	int num_bands = ARRAY_SIZE(cx24123_bandselect_vals);
-	struct cx24123_bandselect_val *bsv = NULL;
-	struct cx24123_AGC_val *agcv = NULL;
-
-	/* Defaults for low freq, low rate */
-	state->VCAarg = cx24123_AGC_vals[0].VCAprogdata;
-	state->VGAarg = cx24123_AGC_vals[0].VGAprogdata;
-	state->bandselectarg = cx24123_bandselect_vals[0].progdata;
-	vco_div = cx24123_bandselect_vals[0].VCOdivider;
-
-	/* For the given symbol rate, determine the VCA, VGA and
-	 * FILTUNE programming bits */
-	for (i = 0; i < ARRAY_SIZE(cx24123_AGC_vals); i++) {
-		agcv = &cx24123_AGC_vals[i];
-		if ((agcv->symbolrate_low <= p->symbol_rate) &&
-		    (agcv->symbolrate_high >= p->symbol_rate)) {
-			state->VCAarg = agcv->VCAprogdata;
-			state->VGAarg = agcv->VGAprogdata;
-			state->FILTune = agcv->FILTune;
-		}
-	}
-
-	/* determine the band to use */
-	if (force_band < 1 || force_band > num_bands) {
-		for (i = 0; i < num_bands; i++) {
-			bsv = &cx24123_bandselect_vals[i];
-			if ((bsv->freq_low <= p->frequency) &&
-				(bsv->freq_high >= p->frequency))
-				band = i;
-		}
-	} else
-		band = force_band - 1;
-
-	state->bandselectarg = cx24123_bandselect_vals[band].progdata;
-	vco_div = cx24123_bandselect_vals[band].VCOdivider;
-
-	/* determine the charge pump current */
-	if (p->frequency < (cx24123_bandselect_vals[band].freq_low +
-		cx24123_bandselect_vals[band].freq_high) / 2)
-		pump = 0x01;
-	else
-		pump = 0x02;
-
-	/* Determine the N/A dividers for the requested lband freq (in kHz). */
-	/* Note: the reference divider R=10, frequency is in KHz,
-	 * XTAL is in Hz */
-	ndiv = (((p->frequency * vco_div * 10) /
-		(2 * XTAL / 1000)) / 32) & 0x1ff;
-	adiv = (((p->frequency * vco_div * 10) /
-		(2 * XTAL / 1000)) % 32) & 0x1f;
-
-	if (adiv == 0 && ndiv > 0)
-		ndiv--;
-
-	/* control bits 11, refdiv 11, charge pump polarity 1,
-	 * charge pump current, ndiv, adiv */
-	state->pllarg = (3 << 19) | (3 << 17) | (1 << 16) |
-		(pump << 14) | (ndiv << 5) | adiv;
-
-	return 0;
-}
-
-/*
- * Tuner data is 21 bits long, must be left-aligned in data.
- * Tuner cx24109 is written through a dedicated 3wire interface
- * on the demod chip.
- */
-static int cx24123_pll_writereg(struct dvb_frontend *fe, u32 data)
-{
-	struct cx24123_state *state = fe->demodulator_priv;
-	unsigned long timeout;
-
-	dprintk("pll writereg called, data=0x%08x\n", data);
-
-	/* align the 21 bytes into to bit23 boundary */
-	data = data << 3;
-
-	/* Reset the demod pll word length to 0x15 bits */
-	cx24123_writereg(state, 0x21, 0x15);
-
-	/* write the msb 8 bits, wait for the send to be completed */
-	timeout = jiffies + msecs_to_jiffies(40);
-	cx24123_writereg(state, 0x22, (data >> 16) & 0xff);
-	while ((cx24123_readreg(state, 0x20) & 0x40) == 0) {
-		if (time_after(jiffies, timeout)) {
-			err("%s:  demodulator is not responding, "\
-				"possibly hung, aborting.\n", __func__);
-			return -EREMOTEIO;
-		}
-		msleep(10);
-	}
-
-	/* send another 8 bytes, wait for the send to be completed */
-	timeout = jiffies + msecs_to_jiffies(40);
-	cx24123_writereg(state, 0x22, (data >> 8) & 0xff);
-	while ((cx24123_readreg(state, 0x20) & 0x40) == 0) {
-		if (time_after(jiffies, timeout)) {
-			err("%s:  demodulator is not responding, "\
-				"possibly hung, aborting.\n", __func__);
-			return -EREMOTEIO;
-		}
-		msleep(10);
-	}
-
-	/* send the lower 5 bits of this byte, padded with 3 LBB,
-	 * wait for the send to be completed */
-	timeout = jiffies + msecs_to_jiffies(40);
-	cx24123_writereg(state, 0x22, (data) & 0xff);
-	while ((cx24123_readreg(state, 0x20) & 0x80)) {
-		if (time_after(jiffies, timeout)) {
-			err("%s:  demodulator is not responding," \
-				"possibly hung, aborting.\n", __func__);
-			return -EREMOTEIO;
-		}
-		msleep(10);
-	}
-
-	/* Trigger the demod to configure the tuner */
-	cx24123_writereg(state, 0x20, cx24123_readreg(state, 0x20) | 2);
-	cx24123_writereg(state, 0x20, cx24123_readreg(state, 0x20) & 0xfd);
-
-	return 0;
-}
-
-static int cx24123_pll_tune(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct cx24123_state *state = fe->demodulator_priv;
-	u8 val;
-
-	dprintk("frequency=%i\n", p->frequency);
-
-	if (cx24123_pll_calculate(fe) != 0) {
-		err("%s: cx24123_pll_calcutate failed\n", __func__);
-		return -EINVAL;
-	}
-
-	/* Write the new VCO/VGA */
-	cx24123_pll_writereg(fe, state->VCAarg);
-	cx24123_pll_writereg(fe, state->VGAarg);
-
-	/* Write the new bandselect and pll args */
-	cx24123_pll_writereg(fe, state->bandselectarg);
-	cx24123_pll_writereg(fe, state->pllarg);
-
-	/* set the FILTUNE voltage */
-	val = cx24123_readreg(state, 0x28) & ~0x3;
-	cx24123_writereg(state, 0x27, state->FILTune >> 2);
-	cx24123_writereg(state, 0x28, val | (state->FILTune & 0x3));
-
-	dprintk("pll tune VCA=%d, band=%d, pll=%d\n", state->VCAarg,
-			state->bandselectarg, state->pllarg);
-
-	return 0;
-}
-
-
-/*
- * 0x23:
- *    [7:7] = BTI enabled
- *    [6:6] = I2C repeater enabled
- *    [5:5] = I2C repeater start
- *    [0:0] = BTI start
- */
-
-/* mode == 1 -> i2c-repeater, 0 -> bti */
-static int cx24123_repeater_mode(struct cx24123_state *state, u8 mode, u8 start)
-{
-	u8 r = cx24123_readreg(state, 0x23) & 0x1e;
-	if (mode)
-		r |= (1 << 6) | (start << 5);
-	else
-		r |= (1 << 7) | (start);
-	return cx24123_writereg(state, 0x23, r);
-}
-
-static int cx24123_initfe(struct dvb_frontend *fe)
-{
-	struct cx24123_state *state = fe->demodulator_priv;
-	int i;
-
-	dprintk("init frontend\n");
-
-	/* Configure the demod to a good set of defaults */
-	for (i = 0; i < ARRAY_SIZE(cx24123_regdata); i++)
-		cx24123_writereg(state, cx24123_regdata[i].reg,
-			cx24123_regdata[i].data);
-
-	/* Set the LNB polarity */
-	if (state->config->lnb_polarity)
-		cx24123_writereg(state, 0x32,
-			cx24123_readreg(state, 0x32) | 0x02);
-
-	if (state->config->dont_use_pll)
-		cx24123_repeater_mode(state, 1, 0);
-
-	return 0;
-}
-
-static int cx24123_set_voltage(struct dvb_frontend *fe,
-	fe_sec_voltage_t voltage)
-{
-	struct cx24123_state *state = fe->demodulator_priv;
-	u8 val;
-
-	val = cx24123_readreg(state, 0x29) & ~0x40;
-
-	switch (voltage) {
-	case SEC_VOLTAGE_13:
-		dprintk("setting voltage 13V\n");
-		return cx24123_writereg(state, 0x29, val & 0x7f);
-	case SEC_VOLTAGE_18:
-		dprintk("setting voltage 18V\n");
-		return cx24123_writereg(state, 0x29, val | 0x80);
-	case SEC_VOLTAGE_OFF:
-		/* already handled in cx88-dvb */
-		return 0;
-	default:
-		return -EINVAL;
-	};
-
-	return 0;
-}
-
-/* wait for diseqc queue to become ready (or timeout) */
-static void cx24123_wait_for_diseqc(struct cx24123_state *state)
-{
-	unsigned long timeout = jiffies + msecs_to_jiffies(200);
-	while (!(cx24123_readreg(state, 0x29) & 0x40)) {
-		if (time_after(jiffies, timeout)) {
-			err("%s: diseqc queue not ready, " \
-				"command may be lost.\n", __func__);
-			break;
-		}
-		msleep(10);
-	}
-}
-
-static int cx24123_send_diseqc_msg(struct dvb_frontend *fe,
-	struct dvb_diseqc_master_cmd *cmd)
-{
-	struct cx24123_state *state = fe->demodulator_priv;
-	int i, val, tone;
-
-	dprintk("\n");
-
-	/* stop continuous tone if enabled */
-	tone = cx24123_readreg(state, 0x29);
-	if (tone & 0x10)
-		cx24123_writereg(state, 0x29, tone & ~0x50);
-
-	/* wait for diseqc queue ready */
-	cx24123_wait_for_diseqc(state);
-
-	/* select tone mode */
-	cx24123_writereg(state, 0x2a, cx24123_readreg(state, 0x2a) & 0xfb);
-
-	for (i = 0; i < cmd->msg_len; i++)
-		cx24123_writereg(state, 0x2C + i, cmd->msg[i]);
-
-	val = cx24123_readreg(state, 0x29);
-	cx24123_writereg(state, 0x29, ((val & 0x90) | 0x40) |
-		((cmd->msg_len-3) & 3));
-
-	/* wait for diseqc message to finish sending */
-	cx24123_wait_for_diseqc(state);
-
-	/* restart continuous tone if enabled */
-	if (tone & 0x10)
-		cx24123_writereg(state, 0x29, tone & ~0x40);
-
-	return 0;
-}
-
-static int cx24123_diseqc_send_burst(struct dvb_frontend *fe,
-	fe_sec_mini_cmd_t burst)
-{
-	struct cx24123_state *state = fe->demodulator_priv;
-	int val, tone;
-
-	dprintk("\n");
-
-	/* stop continuous tone if enabled */
-	tone = cx24123_readreg(state, 0x29);
-	if (tone & 0x10)
-		cx24123_writereg(state, 0x29, tone & ~0x50);
-
-	/* wait for diseqc queue ready */
-	cx24123_wait_for_diseqc(state);
-
-	/* select tone mode */
-	cx24123_writereg(state, 0x2a, cx24123_readreg(state, 0x2a) | 0x4);
-	msleep(30);
-	val = cx24123_readreg(state, 0x29);
-	if (burst == SEC_MINI_A)
-		cx24123_writereg(state, 0x29, ((val & 0x90) | 0x40 | 0x00));
-	else if (burst == SEC_MINI_B)
-		cx24123_writereg(state, 0x29, ((val & 0x90) | 0x40 | 0x08));
-	else
-		return -EINVAL;
-
-	cx24123_wait_for_diseqc(state);
-	cx24123_writereg(state, 0x2a, cx24123_readreg(state, 0x2a) & 0xfb);
-
-	/* restart continuous tone if enabled */
-	if (tone & 0x10)
-		cx24123_writereg(state, 0x29, tone & ~0x40);
-
-	return 0;
-}
-
-static int cx24123_read_status(struct dvb_frontend *fe, fe_status_t *status)
-{
-	struct cx24123_state *state = fe->demodulator_priv;
-	int sync = cx24123_readreg(state, 0x14);
-
-	*status = 0;
-	if (state->config->dont_use_pll) {
-		u32 tun_status = 0;
-		if (fe->ops.tuner_ops.get_status)
-			fe->ops.tuner_ops.get_status(fe, &tun_status);
-		if (tun_status & TUNER_STATUS_LOCKED)
-			*status |= FE_HAS_SIGNAL;
-	} else {
-		int lock = cx24123_readreg(state, 0x20);
-		if (lock & 0x01)
-			*status |= FE_HAS_SIGNAL;
-	}
-
-	if (sync & 0x02)
-		*status |= FE_HAS_CARRIER;	/* Phase locked */
-	if (sync & 0x04)
-		*status |= FE_HAS_VITERBI;
-
-	/* Reed-Solomon Status */
-	if (sync & 0x08)
-		*status |= FE_HAS_SYNC;
-	if (sync & 0x80)
-		*status |= FE_HAS_LOCK;		/*Full Sync */
-
-	return 0;
-}
-
-/*
- * Configured to return the measurement of errors in blocks,
- * because no UCBLOCKS value is available, so this value doubles up
- * to satisfy both measurements.
- */
-static int cx24123_read_ber(struct dvb_frontend *fe, u32 *ber)
-{
-	struct cx24123_state *state = fe->demodulator_priv;
-
-	/* The true bit error rate is this value divided by
-	   the window size (set as 256 * 255) */
-	*ber = ((cx24123_readreg(state, 0x1c) & 0x3f) << 16) |
-		(cx24123_readreg(state, 0x1d) << 8 |
-		 cx24123_readreg(state, 0x1e));
-
-	dprintk("BER = %d\n", *ber);
-
-	return 0;
-}
-
-static int cx24123_read_signal_strength(struct dvb_frontend *fe,
-	u16 *signal_strength)
-{
-	struct cx24123_state *state = fe->demodulator_priv;
-
-	/* larger = better */
-	*signal_strength = cx24123_readreg(state, 0x3b) << 8;
-
-	dprintk("Signal strength = %d\n", *signal_strength);
-
-	return 0;
-}
-
-static int cx24123_read_snr(struct dvb_frontend *fe, u16 *snr)
-{
-	struct cx24123_state *state = fe->demodulator_priv;
-
-	/* Inverted raw Es/N0 count, totally bogus but better than the
-	   BER threshold. */
-	*snr = 65535 - (((u16)cx24123_readreg(state, 0x18) << 8) |
-			 (u16)cx24123_readreg(state, 0x19));
-
-	dprintk("read S/N index = %d\n", *snr);
-
-	return 0;
-}
-
-static int cx24123_set_frontend(struct dvb_frontend *fe)
-{
-	struct cx24123_state *state = fe->demodulator_priv;
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-
-	dprintk("\n");
-
-	if (state->config->set_ts_params)
-		state->config->set_ts_params(fe, 0);
-
-	state->currentfreq = p->frequency;
-	state->currentsymbolrate = p->symbol_rate;
-
-	cx24123_set_inversion(state, p->inversion);
-	cx24123_set_fec(state, p->fec_inner);
-	cx24123_set_symbolrate(state, p->symbol_rate);
-
-	if (!state->config->dont_use_pll)
-		cx24123_pll_tune(fe);
-	else if (fe->ops.tuner_ops.set_params)
-		fe->ops.tuner_ops.set_params(fe);
-	else
-		err("it seems I don't have a tuner...");
-
-	/* Enable automatic acquisition and reset cycle */
-	cx24123_writereg(state, 0x03, (cx24123_readreg(state, 0x03) | 0x07));
-	cx24123_writereg(state, 0x00, 0x10);
-	cx24123_writereg(state, 0x00, 0);
-
-	if (state->config->agc_callback)
-		state->config->agc_callback(fe);
-
-	return 0;
-}
-
-static int cx24123_get_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct cx24123_state *state = fe->demodulator_priv;
-
-	dprintk("\n");
-
-	if (cx24123_get_inversion(state, &p->inversion) != 0) {
-		err("%s: Failed to get inversion status\n", __func__);
-		return -EREMOTEIO;
-	}
-	if (cx24123_get_fec(state, &p->fec_inner) != 0) {
-		err("%s: Failed to get fec status\n", __func__);
-		return -EREMOTEIO;
-	}
-	p->frequency = state->currentfreq;
-	p->symbol_rate = state->currentsymbolrate;
-
-	return 0;
-}
-
-static int cx24123_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
-{
-	struct cx24123_state *state = fe->demodulator_priv;
-	u8 val;
-
-	/* wait for diseqc queue ready */
-	cx24123_wait_for_diseqc(state);
-
-	val = cx24123_readreg(state, 0x29) & ~0x40;
-
-	switch (tone) {
-	case SEC_TONE_ON:
-		dprintk("setting tone on\n");
-		return cx24123_writereg(state, 0x29, val | 0x10);
-	case SEC_TONE_OFF:
-		dprintk("setting tone off\n");
-		return cx24123_writereg(state, 0x29, val & 0xef);
-	default:
-		err("CASE reached default with tone=%d\n", tone);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int cx24123_tune(struct dvb_frontend *fe,
-			bool re_tune,
-			unsigned int mode_flags,
-			unsigned int *delay,
-			fe_status_t *status)
-{
-	int retval = 0;
-
-	if (re_tune)
-		retval = cx24123_set_frontend(fe);
-
-	if (!(mode_flags & FE_TUNE_MODE_ONESHOT))
-		cx24123_read_status(fe, status);
-	*delay = HZ/10;
-
-	return retval;
-}
-
-static int cx24123_get_algo(struct dvb_frontend *fe)
-{
-	return 1; /* FE_ALGO_HW */
-}
-
-static void cx24123_release(struct dvb_frontend *fe)
-{
-	struct cx24123_state *state = fe->demodulator_priv;
-	dprintk("\n");
-	i2c_del_adapter(&state->tuner_i2c_adapter);
-	kfree(state);
-}
-
-static int cx24123_tuner_i2c_tuner_xfer(struct i2c_adapter *i2c_adap,
-	struct i2c_msg msg[], int num)
-{
-	struct cx24123_state *state = i2c_get_adapdata(i2c_adap);
-	/* this repeater closes after the first stop */
-	cx24123_repeater_mode(state, 1, 1);
-	return i2c_transfer(state->i2c, msg, num);
-}
-
-static u32 cx24123_tuner_i2c_func(struct i2c_adapter *adapter)
-{
-	return I2C_FUNC_I2C;
-}
-
-static struct i2c_algorithm cx24123_tuner_i2c_algo = {
-	.master_xfer   = cx24123_tuner_i2c_tuner_xfer,
-	.functionality = cx24123_tuner_i2c_func,
-};
-
-struct i2c_adapter *
-	cx24123_get_tuner_i2c_adapter(struct dvb_frontend *fe)
-{
-	struct cx24123_state *state = fe->demodulator_priv;
-	return &state->tuner_i2c_adapter;
-}
-EXPORT_SYMBOL(cx24123_get_tuner_i2c_adapter);
-
-static struct dvb_frontend_ops cx24123_ops;
-
-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");
-	if (state == NULL) {
-		err("Unable to kzalloc\n");
-		goto error;
-	}
-
-	/* setup the state */
-	state->config = config;
-	state->i2c = i2c;
-
-	/* check if the demod is there */
-	state->demod_rev = cx24123_readreg(state, 0x00);
-	switch (state->demod_rev) {
-	case 0xe1:
-		info("detected CX24123C\n");
-		break;
-	case 0xd1:
-		info("detected CX24123\n");
-		break;
-	default:
-		err("wrong demod revision: %x\n", state->demod_rev);
-		goto error;
-	}
-
-	/* create dvb_frontend */
-	memcpy(&state->frontend.ops, &cx24123_ops,
-		sizeof(struct dvb_frontend_ops));
-	state->frontend.demodulator_priv = state;
-
-	/* create tuner i2c adapter */
-	if (config->dont_use_pll)
-		cx24123_repeater_mode(state, 1, 0);
-
-	strlcpy(state->tuner_i2c_adapter.name, "CX24123 tuner I2C bus",
-		sizeof(state->tuner_i2c_adapter.name));
-	state->tuner_i2c_adapter.algo      = &cx24123_tuner_i2c_algo;
-	state->tuner_i2c_adapter.algo_data = NULL;
-	i2c_set_adapdata(&state->tuner_i2c_adapter, state);
-	if (i2c_add_adapter(&state->tuner_i2c_adapter) < 0) {
-		err("tuner i2c bus could not be initialized\n");
-		goto error;
-	}
-
-	return &state->frontend;
-
-error:
-	kfree(state);
-
-	return NULL;
-}
-EXPORT_SYMBOL(cx24123_attach);
-
-static struct dvb_frontend_ops cx24123_ops = {
-	.delsys = { SYS_DVBS },
-	.info = {
-		.name = "Conexant CX24123/CX24109",
-		.frequency_min = 950000,
-		.frequency_max = 2150000,
-		.frequency_stepsize = 1011, /* kHz for QPSK frontends */
-		.frequency_tolerance = 5000,
-		.symbol_rate_min = 1000000,
-		.symbol_rate_max = 45000000,
-		.caps = FE_CAN_INVERSION_AUTO |
-			FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
-			FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
-			FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
-			FE_CAN_QPSK | FE_CAN_RECOVER
-	},
-
-	.release = cx24123_release,
-
-	.init = cx24123_initfe,
-	.set_frontend = cx24123_set_frontend,
-	.get_frontend = cx24123_get_frontend,
-	.read_status = cx24123_read_status,
-	.read_ber = cx24123_read_ber,
-	.read_signal_strength = cx24123_read_signal_strength,
-	.read_snr = cx24123_read_snr,
-	.diseqc_send_master_cmd = cx24123_send_diseqc_msg,
-	.diseqc_send_burst = cx24123_diseqc_send_burst,
-	.set_tone = cx24123_set_tone,
-	.set_voltage = cx24123_set_voltage,
-	.tune = cx24123_tune,
-	.get_frontend_algo = cx24123_get_algo,
-};
-
-MODULE_DESCRIPTION("DVB Frontend module for Conexant " \
-	"CX24123/CX24109/CX24113 hardware");
-MODULE_AUTHOR("Steven Toth");
-MODULE_LICENSE("GPL");
-
diff --git a/drivers/media/dvb/frontends/cx24123.h b/drivers/media/dvb/frontends/cx24123.h
deleted file mode 100644
index 51ae866..0000000
--- a/drivers/media/dvb/frontends/cx24123.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
-    Conexant cx24123/cx24109 - DVB QPSK Satellite demod/tuner driver
-
-    Copyright (C) 2005 Steven Toth <stoth@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 CX24123_H
-#define CX24123_H
-
-#include <linux/dvb/frontend.h>
-
-struct cx24123_config {
-	/* the demodulator's i2c address */
-	u8 demod_address;
-
-	/* Need to set device param for start_dma */
-	int (*set_ts_params)(struct dvb_frontend *fe, int is_punctured);
-
-	/* 0 = LNB voltage normal, 1 = LNB voltage inverted */
-	int lnb_polarity;
-
-	/* this device has another tuner */
-	u8 dont_use_pll;
-	void (*agc_callback) (struct dvb_frontend *);
-};
-
-#if defined(CONFIG_DVB_CX24123) || (defined(CONFIG_DVB_CX24123_MODULE) \
-	&& defined(MODULE))
-extern struct dvb_frontend *cx24123_attach(const struct cx24123_config *config,
-					   struct i2c_adapter *i2c);
-extern struct i2c_adapter *cx24123_get_tuner_i2c_adapter(struct dvb_frontend *);
-#else
-static inline struct dvb_frontend *cx24123_attach(
-	const struct cx24123_config *config, struct i2c_adapter *i2c)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-static struct i2c_adapter *
-	cx24123_get_tuner_i2c_adapter(struct dvb_frontend *fe)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif
-
-#endif /* CX24123_H */
diff --git a/drivers/media/dvb/frontends/cxd2820r.h b/drivers/media/dvb/frontends/cxd2820r.h
deleted file mode 100644
index 5aa306e..0000000
--- a/drivers/media/dvb/frontends/cxd2820r.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Sony CXD2820R demodulator driver
- *
- * Copyright (C) 2010 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.,
- *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-
-#ifndef CXD2820R_H
-#define CXD2820R_H
-
-#include <linux/dvb/frontend.h>
-
-#define CXD2820R_GPIO_D (0 << 0) /* disable */
-#define CXD2820R_GPIO_E (1 << 0) /* enable */
-#define CXD2820R_GPIO_O (0 << 1) /* output */
-#define CXD2820R_GPIO_I (1 << 1) /* input */
-#define CXD2820R_GPIO_L (0 << 2) /* output low */
-#define CXD2820R_GPIO_H (1 << 2) /* output high */
-
-#define CXD2820R_TS_SERIAL        0x08
-#define CXD2820R_TS_SERIAL_MSB    0x28
-#define CXD2820R_TS_PARALLEL      0x30
-#define CXD2820R_TS_PARALLEL_MSB  0x70
-
-struct cxd2820r_config {
-	/* Demodulator I2C address.
-	 * Driver determines DVB-C slave I2C address automatically from master
-	 * address.
-	 * Default: none, must set
-	 * Values: 0x6c, 0x6d
-	 */
-	u8 i2c_address;
-
-	/* TS output mode.
-	 * Default: none, must set.
-	 * Values:
-	 */
-	u8 ts_mode;
-
-	/* IF AGC polarity.
-	 * Default: 0
-	 * Values: 0, 1
-	 */
-	bool if_agc_polarity;
-
-	/* Spectrum inversion.
-	 * Default: 0
-	 * Values: 0, 1
-	 */
-	bool spec_inv;
-
-	/* GPIOs for all used modes.
-	 * Default: none, disabled
-	 * Values: <see above>
-	 */
-	u8 gpio_dvbt[3];
-	u8 gpio_dvbt2[3];
-	u8 gpio_dvbc[3];
-};
-
-
-#if defined(CONFIG_DVB_CXD2820R) || \
-	(defined(CONFIG_DVB_CXD2820R_MODULE) && defined(MODULE))
-extern struct dvb_frontend *cxd2820r_attach(
-	const struct cxd2820r_config *config,
-	struct i2c_adapter *i2c
-);
-#else
-static inline struct dvb_frontend *cxd2820r_attach(
-	const struct cxd2820r_config *config,
-	struct i2c_adapter *i2c
-)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-
-#endif
-
-#endif /* CXD2820R_H */
diff --git a/drivers/media/dvb/frontends/cxd2820r_c.c b/drivers/media/dvb/frontends/cxd2820r_c.c
deleted file mode 100644
index ed3b0ba6..0000000
--- a/drivers/media/dvb/frontends/cxd2820r_c.c
+++ /dev/null
@@ -1,346 +0,0 @@
-/*
- * Sony CXD2820R demodulator driver
- *
- * Copyright (C) 2010 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.,
- *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-
-#include "cxd2820r_priv.h"
-
-int cxd2820r_set_frontend_c(struct dvb_frontend *fe)
-{
-	struct cxd2820r_priv *priv = fe->demodulator_priv;
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	int ret, i;
-	u8 buf[2];
-	u32 if_freq;
-	u16 if_ctl;
-	u64 num;
-	struct reg_val_mask tab[] = {
-		{ 0x00080, 0x01, 0xff },
-		{ 0x00081, 0x05, 0xff },
-		{ 0x00085, 0x07, 0xff },
-		{ 0x00088, 0x01, 0xff },
-
-		{ 0x00082, 0x20, 0x60 },
-		{ 0x1016a, 0x48, 0xff },
-		{ 0x100a5, 0x00, 0x01 },
-		{ 0x10020, 0x06, 0x07 },
-		{ 0x10059, 0x50, 0xff },
-		{ 0x10087, 0x0c, 0x3c },
-		{ 0x1008b, 0x07, 0xff },
-		{ 0x1001f, priv->cfg.if_agc_polarity << 7, 0x80 },
-		{ 0x10070, priv->cfg.ts_mode, 0xff },
-	};
-
-	dbg("%s: RF=%d SR=%d", __func__, c->frequency, c->symbol_rate);
-
-	/* update GPIOs */
-	ret = cxd2820r_gpio(fe);
-	if (ret)
-		goto error;
-
-	/* program tuner */
-	if (fe->ops.tuner_ops.set_params)
-		fe->ops.tuner_ops.set_params(fe);
-
-	if (priv->delivery_system !=  SYS_DVBC_ANNEX_A) {
-		for (i = 0; i < ARRAY_SIZE(tab); i++) {
-			ret = cxd2820r_wr_reg_mask(priv, tab[i].reg,
-				tab[i].val, tab[i].mask);
-			if (ret)
-				goto error;
-		}
-	}
-
-	priv->delivery_system = SYS_DVBC_ANNEX_A;
-	priv->ber_running = 0; /* tune stops BER counter */
-
-	/* program IF frequency */
-	if (fe->ops.tuner_ops.get_if_frequency) {
-		ret = fe->ops.tuner_ops.get_if_frequency(fe, &if_freq);
-		if (ret)
-			goto error;
-	} else
-		if_freq = 0;
-
-	dbg("%s: if_freq=%d", __func__, if_freq);
-
-	num = if_freq / 1000; /* Hz => kHz */
-	num *= 0x4000;
-	if_ctl = cxd2820r_div_u64_round_closest(num, 41000);
-	buf[0] = (if_ctl >> 8) & 0x3f;
-	buf[1] = (if_ctl >> 0) & 0xff;
-
-	ret = cxd2820r_wr_regs(priv, 0x10042, buf, 2);
-	if (ret)
-		goto error;
-
-	ret = cxd2820r_wr_reg(priv, 0x000ff, 0x08);
-	if (ret)
-		goto error;
-
-	ret = cxd2820r_wr_reg(priv, 0x000fe, 0x01);
-	if (ret)
-		goto error;
-
-	return ret;
-error:
-	dbg("%s: failed:%d", __func__, ret);
-	return ret;
-}
-
-int cxd2820r_get_frontend_c(struct dvb_frontend *fe)
-{
-	struct cxd2820r_priv *priv = fe->demodulator_priv;
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	int ret;
-	u8 buf[2];
-
-	ret = cxd2820r_rd_regs(priv, 0x1001a, buf, 2);
-	if (ret)
-		goto error;
-
-	c->symbol_rate = 2500 * ((buf[0] & 0x0f) << 8 | buf[1]);
-
-	ret = cxd2820r_rd_reg(priv, 0x10019, &buf[0]);
-	if (ret)
-		goto error;
-
-	switch ((buf[0] >> 0) & 0x07) {
-	case 0:
-		c->modulation = QAM_16;
-		break;
-	case 1:
-		c->modulation = QAM_32;
-		break;
-	case 2:
-		c->modulation = QAM_64;
-		break;
-	case 3:
-		c->modulation = QAM_128;
-		break;
-	case 4:
-		c->modulation = QAM_256;
-		break;
-	}
-
-	switch ((buf[0] >> 7) & 0x01) {
-	case 0:
-		c->inversion = INVERSION_OFF;
-		break;
-	case 1:
-		c->inversion = INVERSION_ON;
-		break;
-	}
-
-	return ret;
-error:
-	dbg("%s: failed:%d", __func__, ret);
-	return ret;
-}
-
-int cxd2820r_read_ber_c(struct dvb_frontend *fe, u32 *ber)
-{
-	struct cxd2820r_priv *priv = fe->demodulator_priv;
-	int ret;
-	u8 buf[3], start_ber = 0;
-	*ber = 0;
-
-	if (priv->ber_running) {
-		ret = cxd2820r_rd_regs(priv, 0x10076, buf, sizeof(buf));
-		if (ret)
-			goto error;
-
-		if ((buf[2] >> 7) & 0x01 || (buf[2] >> 4) & 0x01) {
-			*ber = (buf[2] & 0x0f) << 16 | buf[1] << 8 | buf[0];
-			start_ber = 1;
-		}
-	} else {
-		priv->ber_running = 1;
-		start_ber = 1;
-	}
-
-	if (start_ber) {
-		/* (re)start BER */
-		ret = cxd2820r_wr_reg(priv, 0x10079, 0x01);
-		if (ret)
-			goto error;
-	}
-
-	return ret;
-error:
-	dbg("%s: failed:%d", __func__, ret);
-	return ret;
-}
-
-int cxd2820r_read_signal_strength_c(struct dvb_frontend *fe,
-	u16 *strength)
-{
-	struct cxd2820r_priv *priv = fe->demodulator_priv;
-	int ret;
-	u8 buf[2];
-	u16 tmp;
-
-	ret = cxd2820r_rd_regs(priv, 0x10049, buf, sizeof(buf));
-	if (ret)
-		goto error;
-
-	tmp = (buf[0] & 0x03) << 8 | buf[1];
-	tmp = (~tmp & 0x03ff);
-
-	if (tmp == 512)
-		/* ~no signal */
-		tmp = 0;
-	else if (tmp > 350)
-		tmp = 350;
-
-	/* scale value to 0x0000-0xffff */
-	*strength = tmp * 0xffff / (350-0);
-
-	return ret;
-error:
-	dbg("%s: failed:%d", __func__, ret);
-	return ret;
-}
-
-int cxd2820r_read_snr_c(struct dvb_frontend *fe, u16 *snr)
-{
-	struct cxd2820r_priv *priv = fe->demodulator_priv;
-	int ret;
-	u8 tmp;
-	unsigned int A, B;
-	/* report SNR in dB * 10 */
-
-	ret = cxd2820r_rd_reg(priv, 0x10019, &tmp);
-	if (ret)
-		goto error;
-
-	if (((tmp >> 0) & 0x03) % 2) {
-		A = 875;
-		B = 650;
-	} else {
-		A = 950;
-		B = 760;
-	}
-
-	ret = cxd2820r_rd_reg(priv, 0x1004d, &tmp);
-	if (ret)
-		goto error;
-
-	#define CXD2820R_LOG2_E_24 24204406 /* log2(e) << 24 */
-	if (tmp)
-		*snr = A * (intlog2(B / tmp) >> 5) / (CXD2820R_LOG2_E_24 >> 5)
-			/ 10;
-	else
-		*snr = 0;
-
-	return ret;
-error:
-	dbg("%s: failed:%d", __func__, ret);
-	return ret;
-}
-
-int cxd2820r_read_ucblocks_c(struct dvb_frontend *fe, u32 *ucblocks)
-{
-	*ucblocks = 0;
-	/* no way to read ? */
-	return 0;
-}
-
-int cxd2820r_read_status_c(struct dvb_frontend *fe, fe_status_t *status)
-{
-	struct cxd2820r_priv *priv = fe->demodulator_priv;
-	int ret;
-	u8 buf[2];
-	*status = 0;
-
-	ret = cxd2820r_rd_regs(priv, 0x10088, buf, sizeof(buf));
-	if (ret)
-		goto error;
-
-	if (((buf[0] >> 0) & 0x01) == 1) {
-		*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
-			FE_HAS_VITERBI | FE_HAS_SYNC;
-
-		if (((buf[1] >> 3) & 0x01) == 1) {
-			*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
-				FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
-		}
-	}
-
-	dbg("%s: lock=%02x %02x", __func__, buf[0], buf[1]);
-
-	return ret;
-error:
-	dbg("%s: failed:%d", __func__, ret);
-	return ret;
-}
-
-int cxd2820r_init_c(struct dvb_frontend *fe)
-{
-	struct cxd2820r_priv *priv = fe->demodulator_priv;
-	int ret;
-
-	ret = cxd2820r_wr_reg(priv, 0x00085, 0x07);
-	if (ret)
-		goto error;
-
-	return ret;
-error:
-	dbg("%s: failed:%d", __func__, ret);
-	return ret;
-}
-
-int cxd2820r_sleep_c(struct dvb_frontend *fe)
-{
-	struct cxd2820r_priv *priv = fe->demodulator_priv;
-	int ret, i;
-	struct reg_val_mask tab[] = {
-		{ 0x000ff, 0x1f, 0xff },
-		{ 0x00085, 0x00, 0xff },
-		{ 0x00088, 0x01, 0xff },
-		{ 0x00081, 0x00, 0xff },
-		{ 0x00080, 0x00, 0xff },
-	};
-
-	dbg("%s", __func__);
-
-	priv->delivery_system = SYS_UNDEFINED;
-
-	for (i = 0; i < ARRAY_SIZE(tab); i++) {
-		ret = cxd2820r_wr_reg_mask(priv, tab[i].reg, tab[i].val,
-			tab[i].mask);
-		if (ret)
-			goto error;
-	}
-
-	return ret;
-error:
-	dbg("%s: failed:%d", __func__, ret);
-	return ret;
-}
-
-int cxd2820r_get_tune_settings_c(struct dvb_frontend *fe,
-	struct dvb_frontend_tune_settings *s)
-{
-	s->min_delay_ms = 500;
-	s->step_size = 0; /* no zigzag */
-	s->max_drift = 0;
-
-	return 0;
-}
diff --git a/drivers/media/dvb/frontends/cxd2820r_core.c b/drivers/media/dvb/frontends/cxd2820r_core.c
deleted file mode 100644
index 3bba37d..0000000
--- a/drivers/media/dvb/frontends/cxd2820r_core.c
+++ /dev/null
@@ -1,646 +0,0 @@
-/*
- * Sony CXD2820R demodulator driver
- *
- * Copyright (C) 2010 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.,
- *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-
-#include "cxd2820r_priv.h"
-
-int cxd2820r_debug;
-module_param_named(debug, cxd2820r_debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
-
-/* write multiple registers */
-static int cxd2820r_wr_regs_i2c(struct cxd2820r_priv *priv, u8 i2c, u8 reg,
-	u8 *val, int len)
-{
-	int ret;
-	u8 buf[len+1];
-	struct i2c_msg msg[1] = {
-		{
-			.addr = i2c,
-			.flags = 0,
-			.len = sizeof(buf),
-			.buf = buf,
-		}
-	};
-
-	buf[0] = reg;
-	memcpy(&buf[1], val, len);
-
-	ret = i2c_transfer(priv->i2c, msg, 1);
-	if (ret == 1) {
-		ret = 0;
-	} else {
-		warn("i2c wr failed ret:%d reg:%02x len:%d", ret, reg, len);
-		ret = -EREMOTEIO;
-	}
-	return ret;
-}
-
-/* read multiple registers */
-static int cxd2820r_rd_regs_i2c(struct cxd2820r_priv *priv, u8 i2c, u8 reg,
-	u8 *val, int len)
-{
-	int ret;
-	u8 buf[len];
-	struct i2c_msg msg[2] = {
-		{
-			.addr = i2c,
-			.flags = 0,
-			.len = 1,
-			.buf = &reg,
-		}, {
-			.addr = i2c,
-			.flags = I2C_M_RD,
-			.len = sizeof(buf),
-			.buf = buf,
-		}
-	};
-
-	ret = i2c_transfer(priv->i2c, msg, 2);
-	if (ret == 2) {
-		memcpy(val, buf, len);
-		ret = 0;
-	} else {
-		warn("i2c rd failed ret:%d reg:%02x len:%d", ret, reg, len);
-		ret = -EREMOTEIO;
-	}
-
-	return ret;
-}
-
-/* write multiple registers */
-int cxd2820r_wr_regs(struct cxd2820r_priv *priv, u32 reginfo, u8 *val,
-	int len)
-{
-	int ret;
-	u8 i2c_addr;
-	u8 reg = (reginfo >> 0) & 0xff;
-	u8 bank = (reginfo >> 8) & 0xff;
-	u8 i2c = (reginfo >> 16) & 0x01;
-
-	/* select I2C */
-	if (i2c)
-		i2c_addr = priv->cfg.i2c_address | (1 << 1); /* DVB-C */
-	else
-		i2c_addr = priv->cfg.i2c_address; /* DVB-T/T2 */
-
-	/* switch bank if needed */
-	if (bank != priv->bank[i2c]) {
-		ret = cxd2820r_wr_regs_i2c(priv, i2c_addr, 0x00, &bank, 1);
-		if (ret)
-			return ret;
-		priv->bank[i2c] = bank;
-	}
-	return cxd2820r_wr_regs_i2c(priv, i2c_addr, reg, val, len);
-}
-
-/* read multiple registers */
-int cxd2820r_rd_regs(struct cxd2820r_priv *priv, u32 reginfo, u8 *val,
-	int len)
-{
-	int ret;
-	u8 i2c_addr;
-	u8 reg = (reginfo >> 0) & 0xff;
-	u8 bank = (reginfo >> 8) & 0xff;
-	u8 i2c = (reginfo >> 16) & 0x01;
-
-	/* select I2C */
-	if (i2c)
-		i2c_addr = priv->cfg.i2c_address | (1 << 1); /* DVB-C */
-	else
-		i2c_addr = priv->cfg.i2c_address; /* DVB-T/T2 */
-
-	/* switch bank if needed */
-	if (bank != priv->bank[i2c]) {
-		ret = cxd2820r_wr_regs_i2c(priv, i2c_addr, 0x00, &bank, 1);
-		if (ret)
-			return ret;
-		priv->bank[i2c] = bank;
-	}
-	return cxd2820r_rd_regs_i2c(priv, i2c_addr, reg, val, len);
-}
-
-/* write single register */
-int cxd2820r_wr_reg(struct cxd2820r_priv *priv, u32 reg, u8 val)
-{
-	return cxd2820r_wr_regs(priv, reg, &val, 1);
-}
-
-/* read single register */
-int cxd2820r_rd_reg(struct cxd2820r_priv *priv, u32 reg, u8 *val)
-{
-	return cxd2820r_rd_regs(priv, reg, val, 1);
-}
-
-/* write single register with mask */
-int cxd2820r_wr_reg_mask(struct cxd2820r_priv *priv, u32 reg, u8 val,
-	u8 mask)
-{
-	int ret;
-	u8 tmp;
-
-	/* no need for read if whole reg is written */
-	if (mask != 0xff) {
-		ret = cxd2820r_rd_reg(priv, reg, &tmp);
-		if (ret)
-			return ret;
-
-		val &= mask;
-		tmp &= ~mask;
-		val |= tmp;
-	}
-
-	return cxd2820r_wr_reg(priv, reg, val);
-}
-
-int cxd2820r_gpio(struct dvb_frontend *fe)
-{
-	struct cxd2820r_priv *priv = fe->demodulator_priv;
-	int ret, i;
-	u8 *gpio, tmp0, tmp1;
-	dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
-
-	switch (fe->dtv_property_cache.delivery_system) {
-	case SYS_DVBT:
-		gpio = priv->cfg.gpio_dvbt;
-		break;
-	case SYS_DVBT2:
-		gpio = priv->cfg.gpio_dvbt2;
-		break;
-	case SYS_DVBC_ANNEX_AC:
-		gpio = priv->cfg.gpio_dvbc;
-		break;
-	default:
-		ret = -EINVAL;
-		goto error;
-	}
-
-	/* update GPIOs only when needed */
-	if (!memcmp(gpio, priv->gpio, sizeof(priv->gpio)))
-		return 0;
-
-	tmp0 = 0x00;
-	tmp1 = 0x00;
-	for (i = 0; i < sizeof(priv->gpio); i++) {
-		/* enable / disable */
-		if (gpio[i] & CXD2820R_GPIO_E)
-			tmp0 |= (2 << 6) >> (2 * i);
-		else
-			tmp0 |= (1 << 6) >> (2 * i);
-
-		/* input / output */
-		if (gpio[i] & CXD2820R_GPIO_I)
-			tmp1 |= (1 << (3 + i));
-		else
-			tmp1 |= (0 << (3 + i));
-
-		/* high / low */
-		if (gpio[i] & CXD2820R_GPIO_H)
-			tmp1 |= (1 << (0 + i));
-		else
-			tmp1 |= (0 << (0 + i));
-
-		dbg("%s: GPIO i=%d %02x %02x", __func__, i, tmp0, tmp1);
-	}
-
-	dbg("%s: wr gpio=%02x %02x", __func__, tmp0, tmp1);
-
-	/* write bits [7:2] */
-	ret = cxd2820r_wr_reg_mask(priv, 0x00089, tmp0, 0xfc);
-	if (ret)
-		goto error;
-
-	/* write bits [5:0] */
-	ret = cxd2820r_wr_reg_mask(priv, 0x0008e, tmp1, 0x3f);
-	if (ret)
-		goto error;
-
-	memcpy(priv->gpio, gpio, sizeof(priv->gpio));
-
-	return ret;
-error:
-	dbg("%s: failed:%d", __func__, ret);
-	return ret;
-}
-
-/* 64 bit div with round closest, like DIV_ROUND_CLOSEST but 64 bit */
-u32 cxd2820r_div_u64_round_closest(u64 dividend, u32 divisor)
-{
-	return div_u64(dividend + (divisor / 2), divisor);
-}
-
-static int cxd2820r_set_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	int ret;
-
-	dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
-	switch (c->delivery_system) {
-	case SYS_DVBT:
-		ret = cxd2820r_init_t(fe);
-		if (ret < 0)
-			goto err;
-		ret = cxd2820r_set_frontend_t(fe);
-		if (ret < 0)
-			goto err;
-		break;
-	case SYS_DVBT2:
-		ret = cxd2820r_init_t(fe);
-		if (ret < 0)
-			goto err;
-		ret = cxd2820r_set_frontend_t2(fe);
-		if (ret < 0)
-			goto err;
-		break;
-	case SYS_DVBC_ANNEX_A:
-		ret = cxd2820r_init_c(fe);
-		if (ret < 0)
-			goto err;
-		ret = cxd2820r_set_frontend_c(fe);
-		if (ret < 0)
-			goto err;
-		break;
-	default:
-		dbg("%s: error state=%d", __func__, fe->dtv_property_cache.delivery_system);
-		ret = -EINVAL;
-		break;
-	}
-err:
-	return ret;
-}
-static int cxd2820r_read_status(struct dvb_frontend *fe, fe_status_t *status)
-{
-	int ret;
-
-	dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
-	switch (fe->dtv_property_cache.delivery_system) {
-	case SYS_DVBT:
-		ret = cxd2820r_read_status_t(fe, status);
-		break;
-	case SYS_DVBT2:
-		ret = cxd2820r_read_status_t2(fe, status);
-		break;
-	case SYS_DVBC_ANNEX_A:
-		ret = cxd2820r_read_status_c(fe, status);
-		break;
-	default:
-		ret = -EINVAL;
-		break;
-	}
-	return ret;
-}
-
-static int cxd2820r_get_frontend(struct dvb_frontend *fe)
-{
-	struct cxd2820r_priv *priv = fe->demodulator_priv;
-	int ret;
-
-	dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
-
-	if (priv->delivery_system == SYS_UNDEFINED)
-		return 0;
-
-	switch (fe->dtv_property_cache.delivery_system) {
-	case SYS_DVBT:
-		ret = cxd2820r_get_frontend_t(fe);
-		break;
-	case SYS_DVBT2:
-		ret = cxd2820r_get_frontend_t2(fe);
-		break;
-	case SYS_DVBC_ANNEX_A:
-		ret = cxd2820r_get_frontend_c(fe);
-		break;
-	default:
-		ret = -EINVAL;
-		break;
-	}
-	return ret;
-}
-
-static int cxd2820r_read_ber(struct dvb_frontend *fe, u32 *ber)
-{
-	int ret;
-
-	dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
-	switch (fe->dtv_property_cache.delivery_system) {
-	case SYS_DVBT:
-		ret = cxd2820r_read_ber_t(fe, ber);
-		break;
-	case SYS_DVBT2:
-		ret = cxd2820r_read_ber_t2(fe, ber);
-		break;
-	case SYS_DVBC_ANNEX_A:
-		ret = cxd2820r_read_ber_c(fe, ber);
-		break;
-	default:
-		ret = -EINVAL;
-		break;
-	}
-	return ret;
-}
-
-static int cxd2820r_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
-{
-	int ret;
-
-	dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
-	switch (fe->dtv_property_cache.delivery_system) {
-	case SYS_DVBT:
-		ret = cxd2820r_read_signal_strength_t(fe, strength);
-		break;
-	case SYS_DVBT2:
-		ret = cxd2820r_read_signal_strength_t2(fe, strength);
-		break;
-	case SYS_DVBC_ANNEX_A:
-		ret = cxd2820r_read_signal_strength_c(fe, strength);
-		break;
-	default:
-		ret = -EINVAL;
-		break;
-	}
-	return ret;
-}
-
-static int cxd2820r_read_snr(struct dvb_frontend *fe, u16 *snr)
-{
-	int ret;
-
-	dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
-	switch (fe->dtv_property_cache.delivery_system) {
-	case SYS_DVBT:
-		ret = cxd2820r_read_snr_t(fe, snr);
-		break;
-	case SYS_DVBT2:
-		ret = cxd2820r_read_snr_t2(fe, snr);
-		break;
-	case SYS_DVBC_ANNEX_A:
-		ret = cxd2820r_read_snr_c(fe, snr);
-		break;
-	default:
-		ret = -EINVAL;
-		break;
-	}
-	return ret;
-}
-
-static int cxd2820r_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
-{
-	int ret;
-
-	dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
-	switch (fe->dtv_property_cache.delivery_system) {
-	case SYS_DVBT:
-		ret = cxd2820r_read_ucblocks_t(fe, ucblocks);
-		break;
-	case SYS_DVBT2:
-		ret = cxd2820r_read_ucblocks_t2(fe, ucblocks);
-		break;
-	case SYS_DVBC_ANNEX_A:
-		ret = cxd2820r_read_ucblocks_c(fe, ucblocks);
-		break;
-	default:
-		ret = -EINVAL;
-		break;
-	}
-	return ret;
-}
-
-static int cxd2820r_init(struct dvb_frontend *fe)
-{
-	return 0;
-}
-
-static int cxd2820r_sleep(struct dvb_frontend *fe)
-{
-	int ret;
-
-	dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
-	switch (fe->dtv_property_cache.delivery_system) {
-	case SYS_DVBT:
-		ret = cxd2820r_sleep_t(fe);
-		break;
-	case SYS_DVBT2:
-		ret = cxd2820r_sleep_t2(fe);
-		break;
-	case SYS_DVBC_ANNEX_A:
-		ret = cxd2820r_sleep_c(fe);
-		break;
-	default:
-		ret = -EINVAL;
-		break;
-	}
-	return ret;
-}
-
-static int cxd2820r_get_tune_settings(struct dvb_frontend *fe,
-				      struct dvb_frontend_tune_settings *s)
-{
-	int ret;
-
-	dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
-	switch (fe->dtv_property_cache.delivery_system) {
-	case SYS_DVBT:
-		ret = cxd2820r_get_tune_settings_t(fe, s);
-		break;
-	case SYS_DVBT2:
-		ret = cxd2820r_get_tune_settings_t2(fe, s);
-		break;
-	case SYS_DVBC_ANNEX_A:
-		ret = cxd2820r_get_tune_settings_c(fe, s);
-		break;
-	default:
-		ret = -EINVAL;
-		break;
-	}
-	return ret;
-}
-
-static enum dvbfe_search cxd2820r_search(struct dvb_frontend *fe)
-{
-	struct cxd2820r_priv *priv = fe->demodulator_priv;
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	int ret, i;
-	fe_status_t status = 0;
-	dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
-
-	/* switch between DVB-T and DVB-T2 when tune fails */
-	if (priv->last_tune_failed) {
-		if (priv->delivery_system == SYS_DVBT) {
-			ret = cxd2820r_sleep_t(fe);
-			if (ret)
-				goto error;
-
-			c->delivery_system = SYS_DVBT2;
-		} else if (priv->delivery_system == SYS_DVBT2) {
-			ret = cxd2820r_sleep_t2(fe);
-			if (ret)
-				goto error;
-
-			c->delivery_system = SYS_DVBT;
-		}
-	}
-
-	/* set frontend */
-	ret = cxd2820r_set_frontend(fe);
-	if (ret)
-		goto error;
-
-
-	/* frontend lock wait loop count */
-	switch (priv->delivery_system) {
-	case SYS_DVBT:
-	case SYS_DVBC_ANNEX_A:
-		i = 20;
-		break;
-	case SYS_DVBT2:
-		i = 40;
-		break;
-	case SYS_UNDEFINED:
-	default:
-		i = 0;
-		break;
-	}
-
-	/* wait frontend lock */
-	for (; i > 0; i--) {
-		dbg("%s: LOOP=%d", __func__, i);
-		msleep(50);
-		ret = cxd2820r_read_status(fe, &status);
-		if (ret)
-			goto error;
-
-		if (status & FE_HAS_LOCK)
-			break;
-	}
-
-	/* check if we have a valid signal */
-	if (status & FE_HAS_LOCK) {
-		priv->last_tune_failed = 0;
-		return DVBFE_ALGO_SEARCH_SUCCESS;
-	} else {
-		priv->last_tune_failed = 1;
-		return DVBFE_ALGO_SEARCH_AGAIN;
-	}
-
-error:
-	dbg("%s: failed:%d", __func__, ret);
-	return DVBFE_ALGO_SEARCH_ERROR;
-}
-
-static int cxd2820r_get_frontend_algo(struct dvb_frontend *fe)
-{
-	return DVBFE_ALGO_CUSTOM;
-}
-
-static void cxd2820r_release(struct dvb_frontend *fe)
-{
-	struct cxd2820r_priv *priv = fe->demodulator_priv;
-	dbg("%s", __func__);
-
-	kfree(priv);
-	return;
-}
-
-static int cxd2820r_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
-{
-	struct cxd2820r_priv *priv = fe->demodulator_priv;
-	dbg("%s: %d", __func__, enable);
-
-	/* Bit 0 of reg 0xdb in bank 0x00 controls I2C repeater */
-	return cxd2820r_wr_reg_mask(priv, 0xdb, enable ? 1 : 0, 0x1);
-}
-
-static const struct dvb_frontend_ops cxd2820r_ops = {
-	.delsys = { SYS_DVBT, SYS_DVBT2, SYS_DVBC_ANNEX_A },
-	/* default: DVB-T/T2 */
-	.info = {
-		.name = "Sony CXD2820R",
-
-		.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_FEC_AUTO			|
-			FE_CAN_QPSK			|
-			FE_CAN_QAM_16			|
-			FE_CAN_QAM_32			|
-			FE_CAN_QAM_64			|
-			FE_CAN_QAM_128			|
-			FE_CAN_QAM_256			|
-			FE_CAN_QAM_AUTO			|
-			FE_CAN_TRANSMISSION_MODE_AUTO	|
-			FE_CAN_GUARD_INTERVAL_AUTO	|
-			FE_CAN_HIERARCHY_AUTO		|
-			FE_CAN_MUTE_TS			|
-			FE_CAN_2G_MODULATION
-		},
-
-	.release		= cxd2820r_release,
-	.init			= cxd2820r_init,
-	.sleep			= cxd2820r_sleep,
-
-	.get_tune_settings	= cxd2820r_get_tune_settings,
-	.i2c_gate_ctrl		= cxd2820r_i2c_gate_ctrl,
-
-	.get_frontend		= cxd2820r_get_frontend,
-
-	.get_frontend_algo	= cxd2820r_get_frontend_algo,
-	.search			= cxd2820r_search,
-
-	.read_status		= cxd2820r_read_status,
-	.read_snr		= cxd2820r_read_snr,
-	.read_ber		= cxd2820r_read_ber,
-	.read_ucblocks		= cxd2820r_read_ucblocks,
-	.read_signal_strength	= cxd2820r_read_signal_strength,
-};
-
-struct dvb_frontend *cxd2820r_attach(const struct cxd2820r_config *cfg,
-		struct i2c_adapter *i2c)
-{
-	struct cxd2820r_priv *priv = NULL;
-	int ret;
-	u8 tmp;
-
-	priv = kzalloc(sizeof (struct cxd2820r_priv), GFP_KERNEL);
-	if (!priv)
-		goto error;
-
-	priv->i2c = i2c;
-	memcpy(&priv->cfg, cfg, sizeof (struct cxd2820r_config));
-
-	priv->bank[0] = priv->bank[1] = 0xff;
-	ret = cxd2820r_rd_reg(priv, 0x000fd, &tmp);
-	dbg("%s: chip id=%02x", __func__, tmp);
-	if (ret || tmp != 0xe1)
-		goto error;
-
-	memcpy(&priv->fe.ops, &cxd2820r_ops, sizeof (struct dvb_frontend_ops));
-	priv->fe.demodulator_priv = priv;
-	return &priv->fe;
-error:
-	kfree(priv);
-	return NULL;
-}
-EXPORT_SYMBOL(cxd2820r_attach);
-
-MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
-MODULE_DESCRIPTION("Sony CXD2820R demodulator driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/cxd2820r_priv.h b/drivers/media/dvb/frontends/cxd2820r_priv.h
deleted file mode 100644
index 9a9822c..0000000
--- a/drivers/media/dvb/frontends/cxd2820r_priv.h
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Sony CXD2820R demodulator driver
- *
- * Copyright (C) 2010 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.,
- *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-
-#ifndef CXD2820R_PRIV_H
-#define CXD2820R_PRIV_H
-
-#include <linux/dvb/version.h>
-#include "dvb_frontend.h"
-#include "dvb_math.h"
-#include "cxd2820r.h"
-
-#define LOG_PREFIX "cxd2820r"
-
-#undef dbg
-#define dbg(f, arg...) \
-	if (cxd2820r_debug) \
-		printk(KERN_INFO   LOG_PREFIX": " f "\n" , ## arg)
-#undef err
-#define err(f, arg...)  printk(KERN_ERR     LOG_PREFIX": " f "\n" , ## arg)
-#undef info
-#define info(f, arg...) printk(KERN_INFO    LOG_PREFIX": " f "\n" , ## arg)
-#undef warn
-#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg)
-
-struct reg_val_mask {
-	u32 reg;
-	u8  val;
-	u8  mask;
-};
-
-struct cxd2820r_priv {
-	struct i2c_adapter *i2c;
-	struct dvb_frontend fe;
-	struct cxd2820r_config cfg;
-
-	bool ber_running;
-
-	u8 bank[2];
-	u8 gpio[3];
-
-	fe_delivery_system_t delivery_system;
-	bool last_tune_failed; /* for switch between T and T2 tune */
-};
-
-/* cxd2820r_core.c */
-
-extern int cxd2820r_debug;
-
-int cxd2820r_gpio(struct dvb_frontend *fe);
-
-int cxd2820r_wr_reg_mask(struct cxd2820r_priv *priv, u32 reg, u8 val,
-	u8 mask);
-
-int cxd2820r_wr_regs(struct cxd2820r_priv *priv, u32 reginfo, u8 *val,
-	int len);
-
-u32 cxd2820r_div_u64_round_closest(u64 dividend, u32 divisor);
-
-int cxd2820r_wr_regs(struct cxd2820r_priv *priv, u32 reginfo, u8 *val,
-	int len);
-
-int cxd2820r_rd_regs(struct cxd2820r_priv *priv, u32 reginfo, u8 *val,
-	int len);
-
-int cxd2820r_wr_reg(struct cxd2820r_priv *priv, u32 reg, u8 val);
-
-int cxd2820r_rd_reg(struct cxd2820r_priv *priv, u32 reg, u8 *val);
-
-/* cxd2820r_c.c */
-
-int cxd2820r_get_frontend_c(struct dvb_frontend *fe);
-
-int cxd2820r_set_frontend_c(struct dvb_frontend *fe);
-
-int cxd2820r_read_status_c(struct dvb_frontend *fe, fe_status_t *status);
-
-int cxd2820r_read_ber_c(struct dvb_frontend *fe, u32 *ber);
-
-int cxd2820r_read_signal_strength_c(struct dvb_frontend *fe, u16 *strength);
-
-int cxd2820r_read_snr_c(struct dvb_frontend *fe, u16 *snr);
-
-int cxd2820r_read_ucblocks_c(struct dvb_frontend *fe, u32 *ucblocks);
-
-int cxd2820r_init_c(struct dvb_frontend *fe);
-
-int cxd2820r_sleep_c(struct dvb_frontend *fe);
-
-int cxd2820r_get_tune_settings_c(struct dvb_frontend *fe,
-	struct dvb_frontend_tune_settings *s);
-
-/* cxd2820r_t.c */
-
-int cxd2820r_get_frontend_t(struct dvb_frontend *fe);
-
-int cxd2820r_set_frontend_t(struct dvb_frontend *fe);
-
-int cxd2820r_read_status_t(struct dvb_frontend *fe, fe_status_t *status);
-
-int cxd2820r_read_ber_t(struct dvb_frontend *fe, u32 *ber);
-
-int cxd2820r_read_signal_strength_t(struct dvb_frontend *fe, u16 *strength);
-
-int cxd2820r_read_snr_t(struct dvb_frontend *fe, u16 *snr);
-
-int cxd2820r_read_ucblocks_t(struct dvb_frontend *fe, u32 *ucblocks);
-
-int cxd2820r_init_t(struct dvb_frontend *fe);
-
-int cxd2820r_sleep_t(struct dvb_frontend *fe);
-
-int cxd2820r_get_tune_settings_t(struct dvb_frontend *fe,
-	struct dvb_frontend_tune_settings *s);
-
-/* cxd2820r_t2.c */
-
-int cxd2820r_get_frontend_t2(struct dvb_frontend *fe);
-
-int cxd2820r_set_frontend_t2(struct dvb_frontend *fe);
-
-int cxd2820r_read_status_t2(struct dvb_frontend *fe, fe_status_t *status);
-
-int cxd2820r_read_ber_t2(struct dvb_frontend *fe, u32 *ber);
-
-int cxd2820r_read_signal_strength_t2(struct dvb_frontend *fe, u16 *strength);
-
-int cxd2820r_read_snr_t2(struct dvb_frontend *fe, u16 *snr);
-
-int cxd2820r_read_ucblocks_t2(struct dvb_frontend *fe, u32 *ucblocks);
-
-int cxd2820r_init_t2(struct dvb_frontend *fe);
-
-int cxd2820r_sleep_t2(struct dvb_frontend *fe);
-
-int cxd2820r_get_tune_settings_t2(struct dvb_frontend *fe,
-	struct dvb_frontend_tune_settings *s);
-
-#endif /* CXD2820R_PRIV_H */
diff --git a/drivers/media/dvb/frontends/cxd2820r_t.c b/drivers/media/dvb/frontends/cxd2820r_t.c
deleted file mode 100644
index 1a02623..0000000
--- a/drivers/media/dvb/frontends/cxd2820r_t.c
+++ /dev/null
@@ -1,453 +0,0 @@
-/*
- * Sony CXD2820R demodulator driver
- *
- * Copyright (C) 2010 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.,
- *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-
-#include "cxd2820r_priv.h"
-
-int cxd2820r_set_frontend_t(struct dvb_frontend *fe)
-{
-	struct cxd2820r_priv *priv = fe->demodulator_priv;
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	int ret, i, bw_i;
-	u32 if_freq, if_ctl;
-	u64 num;
-	u8 buf[3], bw_param;
-	u8 bw_params1[][5] = {
-		{ 0x17, 0xea, 0xaa, 0xaa, 0xaa }, /* 6 MHz */
-		{ 0x14, 0x80, 0x00, 0x00, 0x00 }, /* 7 MHz */
-		{ 0x11, 0xf0, 0x00, 0x00, 0x00 }, /* 8 MHz */
-	};
-	u8 bw_params2[][2] = {
-		{ 0x1f, 0xdc }, /* 6 MHz */
-		{ 0x12, 0xf8 }, /* 7 MHz */
-		{ 0x01, 0xe0 }, /* 8 MHz */
-	};
-	struct reg_val_mask tab[] = {
-		{ 0x00080, 0x00, 0xff },
-		{ 0x00081, 0x03, 0xff },
-		{ 0x00085, 0x07, 0xff },
-		{ 0x00088, 0x01, 0xff },
-
-		{ 0x00070, priv->cfg.ts_mode, 0xff },
-		{ 0x000cb, priv->cfg.if_agc_polarity << 6, 0x40 },
-		{ 0x000a5, 0x00, 0x01 },
-		{ 0x00082, 0x20, 0x60 },
-		{ 0x000c2, 0xc3, 0xff },
-		{ 0x0016a, 0x50, 0xff },
-		{ 0x00427, 0x41, 0xff },
-	};
-
-	dbg("%s: RF=%d BW=%d", __func__, c->frequency, c->bandwidth_hz);
-
-	switch (c->bandwidth_hz) {
-	case 6000000:
-		bw_i = 0;
-		bw_param = 2;
-		break;
-	case 7000000:
-		bw_i = 1;
-		bw_param = 1;
-		break;
-	case 8000000:
-		bw_i = 2;
-		bw_param = 0;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	/* update GPIOs */
-	ret = cxd2820r_gpio(fe);
-	if (ret)
-		goto error;
-
-	/* program tuner */
-	if (fe->ops.tuner_ops.set_params)
-		fe->ops.tuner_ops.set_params(fe);
-
-	if (priv->delivery_system != SYS_DVBT) {
-		for (i = 0; i < ARRAY_SIZE(tab); i++) {
-			ret = cxd2820r_wr_reg_mask(priv, tab[i].reg,
-				tab[i].val, tab[i].mask);
-			if (ret)
-				goto error;
-		}
-	}
-
-	priv->delivery_system = SYS_DVBT;
-	priv->ber_running = 0; /* tune stops BER counter */
-
-	/* program IF frequency */
-	if (fe->ops.tuner_ops.get_if_frequency) {
-		ret = fe->ops.tuner_ops.get_if_frequency(fe, &if_freq);
-		if (ret)
-			goto error;
-	} else
-		if_freq = 0;
-
-	dbg("%s: if_freq=%d", __func__, if_freq);
-
-	num = if_freq / 1000; /* Hz => kHz */
-	num *= 0x1000000;
-	if_ctl = cxd2820r_div_u64_round_closest(num, 41000);
-	buf[0] = ((if_ctl >> 16) & 0xff);
-	buf[1] = ((if_ctl >>  8) & 0xff);
-	buf[2] = ((if_ctl >>  0) & 0xff);
-
-	ret = cxd2820r_wr_regs(priv, 0x000b6, buf, 3);
-	if (ret)
-		goto error;
-
-	ret = cxd2820r_wr_regs(priv, 0x0009f, bw_params1[bw_i], 5);
-	if (ret)
-		goto error;
-
-	ret = cxd2820r_wr_reg_mask(priv, 0x000d7, bw_param << 6, 0xc0);
-	if (ret)
-		goto error;
-
-	ret = cxd2820r_wr_regs(priv, 0x000d9, bw_params2[bw_i], 2);
-	if (ret)
-		goto error;
-
-	ret = cxd2820r_wr_reg(priv, 0x000ff, 0x08);
-	if (ret)
-		goto error;
-
-	ret = cxd2820r_wr_reg(priv, 0x000fe, 0x01);
-	if (ret)
-		goto error;
-
-	return ret;
-error:
-	dbg("%s: failed:%d", __func__, ret);
-	return ret;
-}
-
-int cxd2820r_get_frontend_t(struct dvb_frontend *fe)
-{
-	struct cxd2820r_priv *priv = fe->demodulator_priv;
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	int ret;
-	u8 buf[2];
-
-	ret = cxd2820r_rd_regs(priv, 0x0002f, buf, sizeof(buf));
-	if (ret)
-		goto error;
-
-	switch ((buf[0] >> 6) & 0x03) {
-	case 0:
-		c->modulation = QPSK;
-		break;
-	case 1:
-		c->modulation = QAM_16;
-		break;
-	case 2:
-		c->modulation = QAM_64;
-		break;
-	}
-
-	switch ((buf[1] >> 1) & 0x03) {
-	case 0:
-		c->transmission_mode = TRANSMISSION_MODE_2K;
-		break;
-	case 1:
-		c->transmission_mode = TRANSMISSION_MODE_8K;
-		break;
-	}
-
-	switch ((buf[1] >> 3) & 0x03) {
-	case 0:
-		c->guard_interval = GUARD_INTERVAL_1_32;
-		break;
-	case 1:
-		c->guard_interval = GUARD_INTERVAL_1_16;
-		break;
-	case 2:
-		c->guard_interval = GUARD_INTERVAL_1_8;
-		break;
-	case 3:
-		c->guard_interval = GUARD_INTERVAL_1_4;
-		break;
-	}
-
-	switch ((buf[0] >> 3) & 0x07) {
-	case 0:
-		c->hierarchy = HIERARCHY_NONE;
-		break;
-	case 1:
-		c->hierarchy = HIERARCHY_1;
-		break;
-	case 2:
-		c->hierarchy = HIERARCHY_2;
-		break;
-	case 3:
-		c->hierarchy = HIERARCHY_4;
-		break;
-	}
-
-	switch ((buf[0] >> 0) & 0x07) {
-	case 0:
-		c->code_rate_HP = FEC_1_2;
-		break;
-	case 1:
-		c->code_rate_HP = FEC_2_3;
-		break;
-	case 2:
-		c->code_rate_HP = FEC_3_4;
-		break;
-	case 3:
-		c->code_rate_HP = FEC_5_6;
-		break;
-	case 4:
-		c->code_rate_HP = FEC_7_8;
-		break;
-	}
-
-	switch ((buf[1] >> 5) & 0x07) {
-	case 0:
-		c->code_rate_LP = FEC_1_2;
-		break;
-	case 1:
-		c->code_rate_LP = FEC_2_3;
-		break;
-	case 2:
-		c->code_rate_LP = FEC_3_4;
-		break;
-	case 3:
-		c->code_rate_LP = FEC_5_6;
-		break;
-	case 4:
-		c->code_rate_LP = FEC_7_8;
-		break;
-	}
-
-	ret = cxd2820r_rd_reg(priv, 0x007c6, &buf[0]);
-	if (ret)
-		goto error;
-
-	switch ((buf[0] >> 0) & 0x01) {
-	case 0:
-		c->inversion = INVERSION_OFF;
-		break;
-	case 1:
-		c->inversion = INVERSION_ON;
-		break;
-	}
-
-	return ret;
-error:
-	dbg("%s: failed:%d", __func__, ret);
-	return ret;
-}
-
-int cxd2820r_read_ber_t(struct dvb_frontend *fe, u32 *ber)
-{
-	struct cxd2820r_priv *priv = fe->demodulator_priv;
-	int ret;
-	u8 buf[3], start_ber = 0;
-	*ber = 0;
-
-	if (priv->ber_running) {
-		ret = cxd2820r_rd_regs(priv, 0x00076, buf, sizeof(buf));
-		if (ret)
-			goto error;
-
-		if ((buf[2] >> 7) & 0x01 || (buf[2] >> 4) & 0x01) {
-			*ber = (buf[2] & 0x0f) << 16 | buf[1] << 8 | buf[0];
-			start_ber = 1;
-		}
-	} else {
-		priv->ber_running = 1;
-		start_ber = 1;
-	}
-
-	if (start_ber) {
-		/* (re)start BER */
-		ret = cxd2820r_wr_reg(priv, 0x00079, 0x01);
-		if (ret)
-			goto error;
-	}
-
-	return ret;
-error:
-	dbg("%s: failed:%d", __func__, ret);
-	return ret;
-}
-
-int cxd2820r_read_signal_strength_t(struct dvb_frontend *fe,
-	u16 *strength)
-{
-	struct cxd2820r_priv *priv = fe->demodulator_priv;
-	int ret;
-	u8 buf[2];
-	u16 tmp;
-
-	ret = cxd2820r_rd_regs(priv, 0x00026, buf, sizeof(buf));
-	if (ret)
-		goto error;
-
-	tmp = (buf[0] & 0x0f) << 8 | buf[1];
-	tmp = ~tmp & 0x0fff;
-
-	/* scale value to 0x0000-0xffff from 0x0000-0x0fff */
-	*strength = tmp * 0xffff / 0x0fff;
-
-	return ret;
-error:
-	dbg("%s: failed:%d", __func__, ret);
-	return ret;
-}
-
-int cxd2820r_read_snr_t(struct dvb_frontend *fe, u16 *snr)
-{
-	struct cxd2820r_priv *priv = fe->demodulator_priv;
-	int ret;
-	u8 buf[2];
-	u16 tmp;
-	/* report SNR in dB * 10 */
-
-	ret = cxd2820r_rd_regs(priv, 0x00028, buf, sizeof(buf));
-	if (ret)
-		goto error;
-
-	tmp = (buf[0] & 0x1f) << 8 | buf[1];
-	#define CXD2820R_LOG10_8_24 15151336 /* log10(8) << 24 */
-	if (tmp)
-		*snr = (intlog10(tmp) - CXD2820R_LOG10_8_24) / ((1 << 24)
-			/ 100);
-	else
-		*snr = 0;
-
-	dbg("%s: dBx10=%d val=%04x", __func__, *snr, tmp);
-
-	return ret;
-error:
-	dbg("%s: failed:%d", __func__, ret);
-	return ret;
-}
-
-int cxd2820r_read_ucblocks_t(struct dvb_frontend *fe, u32 *ucblocks)
-{
-	*ucblocks = 0;
-	/* no way to read ? */
-	return 0;
-}
-
-int cxd2820r_read_status_t(struct dvb_frontend *fe, fe_status_t *status)
-{
-	struct cxd2820r_priv *priv = fe->demodulator_priv;
-	int ret;
-	u8 buf[4];
-	*status = 0;
-
-	ret = cxd2820r_rd_reg(priv, 0x00010, &buf[0]);
-	if (ret)
-		goto error;
-
-	if ((buf[0] & 0x07) == 6) {
-		ret = cxd2820r_rd_reg(priv, 0x00073, &buf[1]);
-		if (ret)
-			goto error;
-
-		if (((buf[1] >> 3) & 0x01) == 1) {
-			*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
-				FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
-		} else {
-			*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
-				FE_HAS_VITERBI | FE_HAS_SYNC;
-		}
-	} else {
-		ret = cxd2820r_rd_reg(priv, 0x00014, &buf[2]);
-		if (ret)
-			goto error;
-
-		if ((buf[2] & 0x0f) >= 4) {
-			ret = cxd2820r_rd_reg(priv, 0x00a14, &buf[3]);
-			if (ret)
-				goto error;
-
-			if (((buf[3] >> 4) & 0x01) == 1)
-				*status |= FE_HAS_SIGNAL;
-		}
-	}
-
-	dbg("%s: lock=%02x %02x %02x %02x", __func__,
-		buf[0], buf[1], buf[2], buf[3]);
-
-	return ret;
-error:
-	dbg("%s: failed:%d", __func__, ret);
-	return ret;
-}
-
-int cxd2820r_init_t(struct dvb_frontend *fe)
-{
-	struct cxd2820r_priv *priv = fe->demodulator_priv;
-	int ret;
-
-	ret = cxd2820r_wr_reg(priv, 0x00085, 0x07);
-	if (ret)
-		goto error;
-
-	return ret;
-error:
-	dbg("%s: failed:%d", __func__, ret);
-	return ret;
-}
-
-int cxd2820r_sleep_t(struct dvb_frontend *fe)
-{
-	struct cxd2820r_priv *priv = fe->demodulator_priv;
-	int ret, i;
-	struct reg_val_mask tab[] = {
-		{ 0x000ff, 0x1f, 0xff },
-		{ 0x00085, 0x00, 0xff },
-		{ 0x00088, 0x01, 0xff },
-		{ 0x00081, 0x00, 0xff },
-		{ 0x00080, 0x00, 0xff },
-	};
-
-	dbg("%s", __func__);
-
-	priv->delivery_system = SYS_UNDEFINED;
-
-	for (i = 0; i < ARRAY_SIZE(tab); i++) {
-		ret = cxd2820r_wr_reg_mask(priv, tab[i].reg, tab[i].val,
-			tab[i].mask);
-		if (ret)
-			goto error;
-	}
-
-	return ret;
-error:
-	dbg("%s: failed:%d", __func__, ret);
-	return ret;
-}
-
-int cxd2820r_get_tune_settings_t(struct dvb_frontend *fe,
-	struct dvb_frontend_tune_settings *s)
-{
-	s->min_delay_ms = 500;
-	s->step_size = fe->ops.info.frequency_stepsize * 2;
-	s->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1;
-
-	return 0;
-}
diff --git a/drivers/media/dvb/frontends/cxd2820r_t2.c b/drivers/media/dvb/frontends/cxd2820r_t2.c
deleted file mode 100644
index 3a5759e..0000000
--- a/drivers/media/dvb/frontends/cxd2820r_t2.c
+++ /dev/null
@@ -1,426 +0,0 @@
-/*
- * Sony CXD2820R demodulator driver
- *
- * Copyright (C) 2010 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.,
- *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-
-#include "cxd2820r_priv.h"
-
-int cxd2820r_set_frontend_t2(struct dvb_frontend *fe)
-{
-	struct cxd2820r_priv *priv = fe->demodulator_priv;
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	int ret, i, bw_i;
-	u32 if_freq, if_ctl;
-	u64 num;
-	u8 buf[3], bw_param;
-	u8 bw_params1[][5] = {
-		{ 0x1c, 0xb3, 0x33, 0x33, 0x33 }, /* 5 MHz */
-		{ 0x17, 0xea, 0xaa, 0xaa, 0xaa }, /* 6 MHz */
-		{ 0x14, 0x80, 0x00, 0x00, 0x00 }, /* 7 MHz */
-		{ 0x11, 0xf0, 0x00, 0x00, 0x00 }, /* 8 MHz */
-	};
-	struct reg_val_mask tab[] = {
-		{ 0x00080, 0x02, 0xff },
-		{ 0x00081, 0x20, 0xff },
-		{ 0x00085, 0x07, 0xff },
-		{ 0x00088, 0x01, 0xff },
-		{ 0x02069, 0x01, 0xff },
-
-		{ 0x0207f, 0x2a, 0xff },
-		{ 0x02082, 0x0a, 0xff },
-		{ 0x02083, 0x0a, 0xff },
-		{ 0x020cb, priv->cfg.if_agc_polarity << 6, 0x40 },
-		{ 0x02070, priv->cfg.ts_mode, 0xff },
-		{ 0x020b5, priv->cfg.spec_inv << 4, 0x10 },
-		{ 0x02567, 0x07, 0x0f },
-		{ 0x02569, 0x03, 0x03 },
-		{ 0x02595, 0x1a, 0xff },
-		{ 0x02596, 0x50, 0xff },
-		{ 0x02a8c, 0x00, 0xff },
-		{ 0x02a8d, 0x34, 0xff },
-		{ 0x02a45, 0x06, 0x07 },
-		{ 0x03f10, 0x0d, 0xff },
-		{ 0x03f11, 0x02, 0xff },
-		{ 0x03f12, 0x01, 0xff },
-		{ 0x03f23, 0x2c, 0xff },
-		{ 0x03f51, 0x13, 0xff },
-		{ 0x03f52, 0x01, 0xff },
-		{ 0x03f53, 0x00, 0xff },
-		{ 0x027e6, 0x14, 0xff },
-		{ 0x02786, 0x02, 0x07 },
-		{ 0x02787, 0x40, 0xe0 },
-		{ 0x027ef, 0x10, 0x18 },
-	};
-
-	dbg("%s: RF=%d BW=%d", __func__, c->frequency, c->bandwidth_hz);
-
-	switch (c->bandwidth_hz) {
-	case 5000000:
-		bw_i = 0;
-		bw_param = 3;
-		break;
-	case 6000000:
-		bw_i = 1;
-		bw_param = 2;
-		break;
-	case 7000000:
-		bw_i = 2;
-		bw_param = 1;
-		break;
-	case 8000000:
-		bw_i = 3;
-		bw_param = 0;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	/* update GPIOs */
-	ret = cxd2820r_gpio(fe);
-	if (ret)
-		goto error;
-
-	/* program tuner */
-	if (fe->ops.tuner_ops.set_params)
-		fe->ops.tuner_ops.set_params(fe);
-
-	if (priv->delivery_system != SYS_DVBT2) {
-		for (i = 0; i < ARRAY_SIZE(tab); i++) {
-			ret = cxd2820r_wr_reg_mask(priv, tab[i].reg,
-				tab[i].val, tab[i].mask);
-			if (ret)
-				goto error;
-		}
-	}
-
-	priv->delivery_system = SYS_DVBT2;
-
-	/* program IF frequency */
-	if (fe->ops.tuner_ops.get_if_frequency) {
-		ret = fe->ops.tuner_ops.get_if_frequency(fe, &if_freq);
-		if (ret)
-			goto error;
-	} else
-		if_freq = 0;
-
-	dbg("%s: if_freq=%d", __func__, if_freq);
-
-	num = if_freq / 1000; /* Hz => kHz */
-	num *= 0x1000000;
-	if_ctl = cxd2820r_div_u64_round_closest(num, 41000);
-	buf[0] = ((if_ctl >> 16) & 0xff);
-	buf[1] = ((if_ctl >>  8) & 0xff);
-	buf[2] = ((if_ctl >>  0) & 0xff);
-
-	ret = cxd2820r_wr_regs(priv, 0x020b6, buf, 3);
-	if (ret)
-		goto error;
-
-	ret = cxd2820r_wr_regs(priv, 0x0209f, bw_params1[bw_i], 5);
-	if (ret)
-		goto error;
-
-	ret = cxd2820r_wr_reg_mask(priv, 0x020d7, bw_param << 6, 0xc0);
-	if (ret)
-		goto error;
-
-	ret = cxd2820r_wr_reg(priv, 0x000ff, 0x08);
-	if (ret)
-		goto error;
-
-	ret = cxd2820r_wr_reg(priv, 0x000fe, 0x01);
-	if (ret)
-		goto error;
-
-	return ret;
-error:
-	dbg("%s: failed:%d", __func__, ret);
-	return ret;
-
-}
-
-int cxd2820r_get_frontend_t2(struct dvb_frontend *fe)
-{
-	struct cxd2820r_priv *priv = fe->demodulator_priv;
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	int ret;
-	u8 buf[2];
-
-	ret = cxd2820r_rd_regs(priv, 0x0205c, buf, 2);
-	if (ret)
-		goto error;
-
-	switch ((buf[0] >> 0) & 0x07) {
-	case 0:
-		c->transmission_mode = TRANSMISSION_MODE_2K;
-		break;
-	case 1:
-		c->transmission_mode = TRANSMISSION_MODE_8K;
-		break;
-	case 2:
-		c->transmission_mode = TRANSMISSION_MODE_4K;
-		break;
-	case 3:
-		c->transmission_mode = TRANSMISSION_MODE_1K;
-		break;
-	case 4:
-		c->transmission_mode = TRANSMISSION_MODE_16K;
-		break;
-	case 5:
-		c->transmission_mode = TRANSMISSION_MODE_32K;
-		break;
-	}
-
-	switch ((buf[1] >> 4) & 0x07) {
-	case 0:
-		c->guard_interval = GUARD_INTERVAL_1_32;
-		break;
-	case 1:
-		c->guard_interval = GUARD_INTERVAL_1_16;
-		break;
-	case 2:
-		c->guard_interval = GUARD_INTERVAL_1_8;
-		break;
-	case 3:
-		c->guard_interval = GUARD_INTERVAL_1_4;
-		break;
-	case 4:
-		c->guard_interval = GUARD_INTERVAL_1_128;
-		break;
-	case 5:
-		c->guard_interval = GUARD_INTERVAL_19_128;
-		break;
-	case 6:
-		c->guard_interval = GUARD_INTERVAL_19_256;
-		break;
-	}
-
-	ret = cxd2820r_rd_regs(priv, 0x0225b, buf, 2);
-	if (ret)
-		goto error;
-
-	switch ((buf[0] >> 0) & 0x07) {
-	case 0:
-		c->fec_inner = FEC_1_2;
-		break;
-	case 1:
-		c->fec_inner = FEC_3_5;
-		break;
-	case 2:
-		c->fec_inner = FEC_2_3;
-		break;
-	case 3:
-		c->fec_inner = FEC_3_4;
-		break;
-	case 4:
-		c->fec_inner = FEC_4_5;
-		break;
-	case 5:
-		c->fec_inner = FEC_5_6;
-		break;
-	}
-
-	switch ((buf[1] >> 0) & 0x07) {
-	case 0:
-		c->modulation = QPSK;
-		break;
-	case 1:
-		c->modulation = QAM_16;
-		break;
-	case 2:
-		c->modulation = QAM_64;
-		break;
-	case 3:
-		c->modulation = QAM_256;
-		break;
-	}
-
-	ret = cxd2820r_rd_reg(priv, 0x020b5, &buf[0]);
-	if (ret)
-		goto error;
-
-	switch ((buf[0] >> 4) & 0x01) {
-	case 0:
-		c->inversion = INVERSION_OFF;
-		break;
-	case 1:
-		c->inversion = INVERSION_ON;
-		break;
-	}
-
-	return ret;
-error:
-	dbg("%s: failed:%d", __func__, ret);
-	return ret;
-}
-
-int cxd2820r_read_status_t2(struct dvb_frontend *fe, fe_status_t *status)
-{
-	struct cxd2820r_priv *priv = fe->demodulator_priv;
-	int ret;
-	u8 buf[1];
-	*status = 0;
-
-	ret = cxd2820r_rd_reg(priv, 0x02010 , &buf[0]);
-	if (ret)
-		goto error;
-
-	if ((buf[0] & 0x07) == 6) {
-		if (((buf[0] >> 5) & 0x01) == 1) {
-			*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
-				FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
-		} else {
-			*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
-				FE_HAS_VITERBI | FE_HAS_SYNC;
-		}
-	}
-
-	dbg("%s: lock=%02x", __func__, buf[0]);
-
-	return ret;
-error:
-	dbg("%s: failed:%d", __func__, ret);
-	return ret;
-}
-
-int cxd2820r_read_ber_t2(struct dvb_frontend *fe, u32 *ber)
-{
-	struct cxd2820r_priv *priv = fe->demodulator_priv;
-	int ret;
-	u8 buf[4];
-	unsigned int errbits;
-	*ber = 0;
-	/* FIXME: correct calculation */
-
-	ret = cxd2820r_rd_regs(priv, 0x02039, buf, sizeof(buf));
-	if (ret)
-		goto error;
-
-	if ((buf[0] >> 4) & 0x01) {
-		errbits = (buf[0] & 0x0f) << 24 | buf[1] << 16 |
-			buf[2] << 8 | buf[3];
-
-		if (errbits)
-			*ber = errbits * 64 / 16588800;
-	}
-
-	return ret;
-error:
-	dbg("%s: failed:%d", __func__, ret);
-	return ret;
-}
-
-int cxd2820r_read_signal_strength_t2(struct dvb_frontend *fe,
-	u16 *strength)
-{
-	struct cxd2820r_priv *priv = fe->demodulator_priv;
-	int ret;
-	u8 buf[2];
-	u16 tmp;
-
-	ret = cxd2820r_rd_regs(priv, 0x02026, buf, sizeof(buf));
-	if (ret)
-		goto error;
-
-	tmp = (buf[0] & 0x0f) << 8 | buf[1];
-	tmp = ~tmp & 0x0fff;
-
-	/* scale value to 0x0000-0xffff from 0x0000-0x0fff */
-	*strength = tmp * 0xffff / 0x0fff;
-
-	return ret;
-error:
-	dbg("%s: failed:%d", __func__, ret);
-	return ret;
-}
-
-int cxd2820r_read_snr_t2(struct dvb_frontend *fe, u16 *snr)
-{
-	struct cxd2820r_priv *priv = fe->demodulator_priv;
-	int ret;
-	u8 buf[2];
-	u16 tmp;
-	/* report SNR in dB * 10 */
-
-	ret = cxd2820r_rd_regs(priv, 0x02028, buf, sizeof(buf));
-	if (ret)
-		goto error;
-
-	tmp = (buf[0] & 0x0f) << 8 | buf[1];
-	#define CXD2820R_LOG10_8_24 15151336 /* log10(8) << 24 */
-	if (tmp)
-		*snr = (intlog10(tmp) - CXD2820R_LOG10_8_24) / ((1 << 24)
-			/ 100);
-	else
-		*snr = 0;
-
-	dbg("%s: dBx10=%d val=%04x", __func__, *snr, tmp);
-
-	return ret;
-error:
-	dbg("%s: failed:%d", __func__, ret);
-	return ret;
-}
-
-int cxd2820r_read_ucblocks_t2(struct dvb_frontend *fe, u32 *ucblocks)
-{
-	*ucblocks = 0;
-	/* no way to read ? */
-	return 0;
-}
-
-int cxd2820r_sleep_t2(struct dvb_frontend *fe)
-{
-	struct cxd2820r_priv *priv = fe->demodulator_priv;
-	int ret, i;
-	struct reg_val_mask tab[] = {
-		{ 0x000ff, 0x1f, 0xff },
-		{ 0x00085, 0x00, 0xff },
-		{ 0x00088, 0x01, 0xff },
-		{ 0x02069, 0x00, 0xff },
-		{ 0x00081, 0x00, 0xff },
-		{ 0x00080, 0x00, 0xff },
-	};
-
-	dbg("%s", __func__);
-
-	for (i = 0; i < ARRAY_SIZE(tab); i++) {
-		ret = cxd2820r_wr_reg_mask(priv, tab[i].reg, tab[i].val,
-			tab[i].mask);
-		if (ret)
-			goto error;
-	}
-
-	priv->delivery_system = SYS_UNDEFINED;
-
-	return ret;
-error:
-	dbg("%s: failed:%d", __func__, ret);
-	return ret;
-}
-
-int cxd2820r_get_tune_settings_t2(struct dvb_frontend *fe,
-	struct dvb_frontend_tune_settings *s)
-{
-	s->min_delay_ms = 1500;
-	s->step_size = fe->ops.info.frequency_stepsize * 2;
-	s->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1;
-
-	return 0;
-}
diff --git a/drivers/media/dvb/frontends/dib0070.c b/drivers/media/dvb/frontends/dib0070.c
deleted file mode 100644
index 3b024bf..0000000
--- a/drivers/media/dvb/frontends/dib0070.c
+++ /dev/null
@@ -1,780 +0,0 @@
-/*
- * Linux-DVB Driver for DiBcom's DiB0070 base-band RF Tuner.
- *
- * Copyright (C) 2005-9 DiBcom (http://www.dibcom.fr/)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *
- * This code is more or less generated from another driver, please
- * excuse some codingstyle oddities.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/i2c.h>
-#include <linux/mutex.h>
-
-#include "dvb_frontend.h"
-
-#include "dib0070.h"
-#include "dibx000_common.h"
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
-
-#define dprintk(args...) do { \
-	if (debug) { \
-		printk(KERN_DEBUG "DiB0070: "); \
-		printk(args); \
-		printk("\n"); \
-	} \
-} while (0)
-
-#define DIB0070_P1D  0x00
-#define DIB0070_P1F  0x01
-#define DIB0070_P1G  0x03
-#define DIB0070S_P1A 0x02
-
-struct dib0070_state {
-	struct i2c_adapter *i2c;
-	struct dvb_frontend *fe;
-	const struct dib0070_config *cfg;
-	u16 wbd_ff_offset;
-	u8 revision;
-
-    enum frontend_tune_state tune_state;
-    u32 current_rf;
-
-    /* for the captrim binary search */
-	s8 step;
-	u16 adc_diff;
-
-	s8 captrim;
-	s8 fcaptrim;
-	u16 lo4;
-
-	const struct dib0070_tuning *current_tune_table_index;
-	const struct dib0070_lna_match *lna_match;
-
-    u8  wbd_gain_current;
-	u16 wbd_offset_3_3[2];
-
-	/* for the I2C transfer */
-	struct i2c_msg msg[2];
-	u8 i2c_write_buffer[3];
-	u8 i2c_read_buffer[2];
-	struct mutex i2c_buffer_lock;
-};
-
-static u16 dib0070_read_reg(struct dib0070_state *state, u8 reg)
-{
-	u16 ret;
-
-	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
-		dprintk("could not acquire lock");
-		return 0;
-	}
-
-	state->i2c_write_buffer[0] = reg;
-
-	memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
-	state->msg[0].addr = state->cfg->i2c_address;
-	state->msg[0].flags = 0;
-	state->msg[0].buf = state->i2c_write_buffer;
-	state->msg[0].len = 1;
-	state->msg[1].addr = state->cfg->i2c_address;
-	state->msg[1].flags = I2C_M_RD;
-	state->msg[1].buf = state->i2c_read_buffer;
-	state->msg[1].len = 2;
-
-	if (i2c_transfer(state->i2c, state->msg, 2) != 2) {
-		printk(KERN_WARNING "DiB0070 I2C read failed\n");
-		ret = 0;
-	} else
-		ret = (state->i2c_read_buffer[0] << 8)
-			| state->i2c_read_buffer[1];
-
-	mutex_unlock(&state->i2c_buffer_lock);
-	return ret;
-}
-
-static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val)
-{
-	int ret;
-
-	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
-		dprintk("could not acquire lock");
-		return -EINVAL;
-	}
-	state->i2c_write_buffer[0] = reg;
-	state->i2c_write_buffer[1] = val >> 8;
-	state->i2c_write_buffer[2] = val & 0xff;
-
-	memset(state->msg, 0, sizeof(struct i2c_msg));
-	state->msg[0].addr = state->cfg->i2c_address;
-	state->msg[0].flags = 0;
-	state->msg[0].buf = state->i2c_write_buffer;
-	state->msg[0].len = 3;
-
-	if (i2c_transfer(state->i2c, state->msg, 1) != 1) {
-		printk(KERN_WARNING "DiB0070 I2C write failed\n");
-		ret = -EREMOTEIO;
-	} else
-		ret = 0;
-
-	mutex_unlock(&state->i2c_buffer_lock);
-	return ret;
-}
-
-#define HARD_RESET(state) do { \
-    state->cfg->sleep(state->fe, 0); \
-    if (state->cfg->reset) { \
-	state->cfg->reset(state->fe,1); msleep(10); \
-	state->cfg->reset(state->fe,0); msleep(10); \
-    } \
-} while (0)
-
-static int dib0070_set_bandwidth(struct dvb_frontend *fe)
-{
-    struct dib0070_state *state = fe->tuner_priv;
-    u16 tmp = dib0070_read_reg(state, 0x02) & 0x3fff;
-
-    if (state->fe->dtv_property_cache.bandwidth_hz/1000 > 7000)
-	tmp |= (0 << 14);
-    else if (state->fe->dtv_property_cache.bandwidth_hz/1000 > 6000)
-	tmp |= (1 << 14);
-    else if (state->fe->dtv_property_cache.bandwidth_hz/1000 > 5000)
-	tmp |= (2 << 14);
-    else
-	tmp |= (3 << 14);
-
-    dib0070_write_reg(state, 0x02, tmp);
-
-    /* sharpen the BB filter in ISDB-T to have higher immunity to adjacent channels */
-    if (state->fe->dtv_property_cache.delivery_system == SYS_ISDBT) {
-	u16 value = dib0070_read_reg(state, 0x17);
-
-	dib0070_write_reg(state, 0x17, value & 0xfffc);
-	tmp = dib0070_read_reg(state, 0x01) & 0x01ff;
-	dib0070_write_reg(state, 0x01, tmp | (60 << 9));
-
-	dib0070_write_reg(state, 0x17, value);
-    }
-	return 0;
-}
-
-static int dib0070_captrim(struct dib0070_state *state, enum frontend_tune_state *tune_state)
-{
-	int8_t step_sign;
-	u16 adc;
-	int ret = 0;
-
-	if (*tune_state == CT_TUNER_STEP_0) {
-
-		dib0070_write_reg(state, 0x0f, 0xed10);
-		dib0070_write_reg(state, 0x17,    0x0034);
-
-		dib0070_write_reg(state, 0x18, 0x0032);
-		state->step = state->captrim = state->fcaptrim = 64;
-		state->adc_diff = 3000;
-		ret = 20;
-
-	*tune_state = CT_TUNER_STEP_1;
-	} else if (*tune_state == CT_TUNER_STEP_1) {
-		state->step /= 2;
-		dib0070_write_reg(state, 0x14, state->lo4 | state->captrim);
-		ret = 15;
-
-		*tune_state = CT_TUNER_STEP_2;
-	} else if (*tune_state == CT_TUNER_STEP_2) {
-
-		adc = dib0070_read_reg(state, 0x19);
-
-		dprintk("CAPTRIM=%hd; ADC = %hd (ADC) & %dmV", state->captrim, adc, (u32) adc*(u32)1800/(u32)1024);
-
-		if (adc >= 400) {
-			adc -= 400;
-			step_sign = -1;
-		} else {
-			adc = 400 - adc;
-			step_sign = 1;
-		}
-
-		if (adc < state->adc_diff) {
-			dprintk("CAPTRIM=%hd is closer to target (%hd/%hd)", state->captrim, adc, state->adc_diff);
-			state->adc_diff = adc;
-			state->fcaptrim = state->captrim;
-
-
-
-		}
-		state->captrim += (step_sign * state->step);
-
-		if (state->step >= 1)
-			*tune_state = CT_TUNER_STEP_1;
-		else
-			*tune_state = CT_TUNER_STEP_3;
-
-	} else if (*tune_state == CT_TUNER_STEP_3) {
-		dib0070_write_reg(state, 0x14, state->lo4 | state->fcaptrim);
-		dib0070_write_reg(state, 0x18, 0x07ff);
-		*tune_state = CT_TUNER_STEP_4;
-	}
-
-	return ret;
-}
-
-static int dib0070_set_ctrl_lo5(struct dvb_frontend *fe, u8 vco_bias_trim, u8 hf_div_trim, u8 cp_current, u8 third_order_filt)
-{
-	struct dib0070_state *state = fe->tuner_priv;
-    u16 lo5 = (third_order_filt << 14) | (0 << 13) | (1 << 12) | (3 << 9) | (cp_current << 6) | (hf_div_trim << 3) | (vco_bias_trim << 0);
-	dprintk("CTRL_LO5: 0x%x", lo5);
-	return dib0070_write_reg(state, 0x15, lo5);
-}
-
-void dib0070_ctrl_agc_filter(struct dvb_frontend *fe, u8 open)
-{
-	struct dib0070_state *state = fe->tuner_priv;
-
-	if (open) {
-		dib0070_write_reg(state, 0x1b, 0xff00);
-		dib0070_write_reg(state, 0x1a, 0x0000);
-	} else {
-		dib0070_write_reg(state, 0x1b, 0x4112);
-	if (state->cfg->vga_filter != 0) {
-		dib0070_write_reg(state, 0x1a, state->cfg->vga_filter);
-		dprintk("vga filter register is set to %x", state->cfg->vga_filter);
-	} else
-		dib0070_write_reg(state, 0x1a, 0x0009);
-	}
-}
-
-EXPORT_SYMBOL(dib0070_ctrl_agc_filter);
-struct dib0070_tuning {
-    u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */
-    u8 switch_trim;
-    u8 vco_band;
-    u8 hfdiv;
-    u8 vco_multi;
-    u8 presc;
-    u8 wbdmux;
-    u16 tuner_enable;
-};
-
-struct dib0070_lna_match {
-    u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */
-    u8 lna_band;
-};
-
-static const struct dib0070_tuning dib0070s_tuning_table[] = {
-    {     570000, 2, 1, 3, 6, 6, 2, 0x4000 | 0x0800 }, /* UHF */
-    {     700000, 2, 0, 2, 4, 2, 2, 0x4000 | 0x0800 },
-    {     863999, 2, 1, 2, 4, 2, 2, 0x4000 | 0x0800 },
-    {    1500000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 }, /* LBAND */
-    {    1600000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 },
-    {    2000000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 },
-    { 0xffffffff, 0, 0, 8, 1, 2, 1, 0x8000 | 0x1000 }, /* SBAND */
-};
-
-static const struct dib0070_tuning dib0070_tuning_table[] = {
-    {     115000, 1, 0, 7, 24, 2, 1, 0x8000 | 0x1000 }, /* FM below 92MHz cannot be tuned */
-    {     179500, 1, 0, 3, 16, 2, 1, 0x8000 | 0x1000 }, /* VHF */
-    {     189999, 1, 1, 3, 16, 2, 1, 0x8000 | 0x1000 },
-    {     250000, 1, 0, 6, 12, 2, 1, 0x8000 | 0x1000 },
-    {     569999, 2, 1, 5,  6, 2, 2, 0x4000 | 0x0800 }, /* UHF */
-    {     699999, 2, 0, 1,  4, 2, 2, 0x4000 | 0x0800 },
-    {     863999, 2, 1, 1,  4, 2, 2, 0x4000 | 0x0800 },
-    { 0xffffffff, 0, 1, 0,  2, 2, 4, 0x2000 | 0x0400 }, /* LBAND or everything higher than UHF */
-};
-
-static const struct dib0070_lna_match dib0070_lna_flip_chip[] = {
-    {     180000, 0 }, /* VHF */
-    {     188000, 1 },
-    {     196400, 2 },
-    {     250000, 3 },
-    {     550000, 0 }, /* UHF */
-    {     590000, 1 },
-    {     666000, 3 },
-    {     864000, 5 },
-    {    1500000, 0 }, /* LBAND or everything higher than UHF */
-    {    1600000, 1 },
-    {    2000000, 3 },
-    { 0xffffffff, 7 },
-};
-
-static const struct dib0070_lna_match dib0070_lna[] = {
-    {     180000, 0 }, /* VHF */
-    {     188000, 1 },
-    {     196400, 2 },
-    {     250000, 3 },
-    {     550000, 2 }, /* UHF */
-    {     650000, 3 },
-    {     750000, 5 },
-    {     850000, 6 },
-    {     864000, 7 },
-    {    1500000, 0 }, /* LBAND or everything higher than UHF */
-    {    1600000, 1 },
-    {    2000000, 3 },
-    { 0xffffffff, 7 },
-};
-
-#define LPF	100
-static int dib0070_tune_digital(struct dvb_frontend *fe)
-{
-    struct dib0070_state *state = fe->tuner_priv;
-
-    const struct dib0070_tuning *tune;
-    const struct dib0070_lna_match *lna_match;
-
-    enum frontend_tune_state *tune_state = &state->tune_state;
-    int ret = 10; /* 1ms is the default delay most of the time */
-
-    u8  band = (u8)BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency/1000);
-    u32 freq = fe->dtv_property_cache.frequency/1000 + (band == BAND_VHF ? state->cfg->freq_offset_khz_vhf : state->cfg->freq_offset_khz_uhf);
-
-#ifdef CONFIG_SYS_ISDBT
-    if (state->fe->dtv_property_cache.delivery_system == SYS_ISDBT && state->fe->dtv_property_cache.isdbt_sb_mode == 1)
-		if (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2)
-		     && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == ((state->fe->dtv_property_cache.isdbt_sb_segment_count / 2) + 1)))
-		    || (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2) == 0)
-			&& (state->fe->dtv_property_cache.isdbt_sb_segment_idx == (state->fe->dtv_property_cache.isdbt_sb_segment_count / 2)))
-		    || (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2) == 0)
-			&& (state->fe->dtv_property_cache.isdbt_sb_segment_idx == ((state->fe->dtv_property_cache.isdbt_sb_segment_count / 2) + 1))))
-			freq += 850;
-#endif
-    if (state->current_rf != freq) {
-
-	switch (state->revision) {
-	case DIB0070S_P1A:
-	    tune = dib0070s_tuning_table;
-	    lna_match = dib0070_lna;
-	    break;
-	default:
-	    tune = dib0070_tuning_table;
-	    if (state->cfg->flip_chip)
-		lna_match = dib0070_lna_flip_chip;
-	    else
-		lna_match = dib0070_lna;
-	    break;
-	}
-	while (freq > tune->max_freq) /* find the right one */
-	    tune++;
-	while (freq > lna_match->max_freq) /* find the right one */
-	    lna_match++;
-
-	state->current_tune_table_index = tune;
-	state->lna_match = lna_match;
-    }
-
-    if (*tune_state == CT_TUNER_START) {
-	dprintk("Tuning for Band: %hd (%d kHz)", band, freq);
-	if (state->current_rf != freq) {
-		u8 REFDIV;
-		u32 FBDiv, Rest, FREF, VCOF_kHz;
-		u8 Den;
-
-		state->current_rf = freq;
-		state->lo4 = (state->current_tune_table_index->vco_band << 11) | (state->current_tune_table_index->hfdiv << 7);
-
-
-		dib0070_write_reg(state, 0x17, 0x30);
-
-
-		VCOF_kHz = state->current_tune_table_index->vco_multi * freq * 2;
-
-		switch (band) {
-		case BAND_VHF:
-			REFDIV = (u8) ((state->cfg->clock_khz + 9999) / 10000);
-			break;
-		case BAND_FM:
-			REFDIV = (u8) ((state->cfg->clock_khz) / 1000);
-			break;
-		default:
-			REFDIV = (u8) (state->cfg->clock_khz  / 10000);
-			break;
-		}
-		FREF = state->cfg->clock_khz / REFDIV;
-
-
-
-		switch (state->revision) {
-		case DIB0070S_P1A:
-			FBDiv = (VCOF_kHz / state->current_tune_table_index->presc / FREF);
-			Rest  = (VCOF_kHz / state->current_tune_table_index->presc) - FBDiv * FREF;
-			break;
-
-		case DIB0070_P1G:
-		case DIB0070_P1F:
-		default:
-			FBDiv = (freq / (FREF / 2));
-			Rest  = 2 * freq - FBDiv * FREF;
-			break;
-		}
-
-		if (Rest < LPF)
-			Rest = 0;
-		else if (Rest < 2 * LPF)
-			Rest = 2 * LPF;
-		else if (Rest > (FREF - LPF)) {
-			Rest = 0;
-			FBDiv += 1;
-		} else if (Rest > (FREF - 2 * LPF))
-			Rest = FREF - 2 * LPF;
-		Rest = (Rest * 6528) / (FREF / 10);
-
-		Den = 1;
-		if (Rest > 0) {
-			state->lo4 |= (1 << 14) | (1 << 12);
-			Den = 255;
-		}
-
-
-		dib0070_write_reg(state, 0x11, (u16)FBDiv);
-		dib0070_write_reg(state, 0x12, (Den << 8) | REFDIV);
-		dib0070_write_reg(state, 0x13, (u16) Rest);
-
-		if (state->revision == DIB0070S_P1A) {
-
-			if (band == BAND_SBAND) {
-				dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0);
-				dib0070_write_reg(state, 0x1d, 0xFFFF);
-			} else
-				dib0070_set_ctrl_lo5(fe, 5, 4, 3, 1);
-		}
-
-		dib0070_write_reg(state, 0x20,
-			0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001 | state->current_tune_table_index->tuner_enable);
-
-		dprintk("REFDIV: %hd, FREF: %d", REFDIV, FREF);
-		dprintk("FBDIV: %d, Rest: %d", FBDiv, Rest);
-		dprintk("Num: %hd, Den: %hd, SD: %hd", (u16) Rest, Den, (state->lo4 >> 12) & 0x1);
-		dprintk("HFDIV code: %hd", state->current_tune_table_index->hfdiv);
-		dprintk("VCO = %hd", state->current_tune_table_index->vco_band);
-		dprintk("VCOF: ((%hd*%d) << 1))", state->current_tune_table_index->vco_multi, freq);
-
-		*tune_state = CT_TUNER_STEP_0;
-	} else { /* we are already tuned to this frequency - the configuration is correct  */
-		ret = 50; /* wakeup time */
-		*tune_state = CT_TUNER_STEP_5;
-	}
-    } else if ((*tune_state > CT_TUNER_START) && (*tune_state < CT_TUNER_STEP_4)) {
-
-	ret = dib0070_captrim(state, tune_state);
-
-    } else if (*tune_state == CT_TUNER_STEP_4) {
-	const struct dib0070_wbd_gain_cfg *tmp = state->cfg->wbd_gain;
-	if (tmp != NULL) {
-		while (freq/1000 > tmp->freq) /* find the right one */
-			tmp++;
-		dib0070_write_reg(state, 0x0f,
-			(0 << 15) | (1 << 14) | (3 << 12)
-			| (tmp->wbd_gain_val << 9) | (0 << 8) | (1 << 7)
-			| (state->current_tune_table_index->wbdmux << 0));
-		state->wbd_gain_current = tmp->wbd_gain_val;
-	} else {
-			dib0070_write_reg(state, 0x0f,
-					  (0 << 15) | (1 << 14) | (3 << 12) | (6 << 9) | (0 << 8) | (1 << 7) | (state->current_tune_table_index->
-														wbdmux << 0));
-	    state->wbd_gain_current = 6;
-	}
-
-	dib0070_write_reg(state, 0x06, 0x3fff);
-		dib0070_write_reg(state, 0x07,
-				  (state->current_tune_table_index->switch_trim << 11) | (7 << 8) | (state->lna_match->lna_band << 3) | (3 << 0));
-	dib0070_write_reg(state, 0x08, (state->lna_match->lna_band << 10) | (3 << 7) | (127));
-	dib0070_write_reg(state, 0x0d, 0x0d80);
-
-
-	dib0070_write_reg(state, 0x18,   0x07ff);
-	dib0070_write_reg(state, 0x17, 0x0033);
-
-
-	*tune_state = CT_TUNER_STEP_5;
-    } else if (*tune_state == CT_TUNER_STEP_5) {
-	dib0070_set_bandwidth(fe);
-	*tune_state = CT_TUNER_STOP;
-    } else {
-	ret = FE_CALLBACK_TIME_NEVER; /* tuner finished, time to call again infinite */
-    }
-    return ret;
-}
-
-
-static int dib0070_tune(struct dvb_frontend *fe)
-{
-    struct dib0070_state *state = fe->tuner_priv;
-    uint32_t ret;
-
-    state->tune_state = CT_TUNER_START;
-
-    do {
-	ret = dib0070_tune_digital(fe);
-	if (ret != FE_CALLBACK_TIME_NEVER)
-		msleep(ret/10);
-	else
-	    break;
-    } while (state->tune_state != CT_TUNER_STOP);
-
-    return 0;
-}
-
-static int dib0070_wakeup(struct dvb_frontend *fe)
-{
-	struct dib0070_state *state = fe->tuner_priv;
-	if (state->cfg->sleep)
-		state->cfg->sleep(fe, 0);
-	return 0;
-}
-
-static int dib0070_sleep(struct dvb_frontend *fe)
-{
-	struct dib0070_state *state = fe->tuner_priv;
-	if (state->cfg->sleep)
-		state->cfg->sleep(fe, 1);
-	return 0;
-}
-
-u8 dib0070_get_rf_output(struct dvb_frontend *fe)
-{
-	struct dib0070_state *state = fe->tuner_priv;
-	return (dib0070_read_reg(state, 0x07) >> 11) & 0x3;
-}
-EXPORT_SYMBOL(dib0070_get_rf_output);
-
-int dib0070_set_rf_output(struct dvb_frontend *fe, u8 no)
-{
-	struct dib0070_state *state = fe->tuner_priv;
-	u16 rxrf2 = dib0070_read_reg(state, 0x07) & 0xfe7ff;
-	if (no > 3)
-		no = 3;
-	if (no < 1)
-		no = 1;
-	return dib0070_write_reg(state, 0x07, rxrf2 | (no << 11));
-}
-EXPORT_SYMBOL(dib0070_set_rf_output);
-
-static const u16 dib0070_p1f_defaults[] =
-
-{
-	7, 0x02,
-		0x0008,
-		0x0000,
-		0x0000,
-		0x0000,
-		0x0000,
-		0x0002,
-		0x0100,
-
-	3, 0x0d,
-		0x0d80,
-		0x0001,
-		0x0000,
-
-	4, 0x11,
-		0x0000,
-		0x0103,
-		0x0000,
-		0x0000,
-
-	3, 0x16,
-		0x0004 | 0x0040,
-		0x0030,
-		0x07ff,
-
-	6, 0x1b,
-		0x4112,
-		0xff00,
-		0xc07f,
-		0x0000,
-		0x0180,
-		0x4000 | 0x0800 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001,
-
-	0,
-};
-
-static u16 dib0070_read_wbd_offset(struct dib0070_state *state, u8 gain)
-{
-    u16 tuner_en = dib0070_read_reg(state, 0x20);
-    u16 offset;
-
-    dib0070_write_reg(state, 0x18, 0x07ff);
-    dib0070_write_reg(state, 0x20, 0x0800 | 0x4000 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001);
-    dib0070_write_reg(state, 0x0f, (1 << 14) | (2 << 12) | (gain << 9) | (1 << 8) | (1 << 7) | (0 << 0));
-    msleep(9);
-    offset = dib0070_read_reg(state, 0x19);
-    dib0070_write_reg(state, 0x20, tuner_en);
-    return offset;
-}
-
-static void dib0070_wbd_offset_calibration(struct dib0070_state *state)
-{
-    u8 gain;
-    for (gain = 6; gain < 8; gain++) {
-	state->wbd_offset_3_3[gain - 6] = ((dib0070_read_wbd_offset(state, gain) * 8 * 18 / 33 + 1) / 2);
-	dprintk("Gain: %d, WBDOffset (3.3V) = %hd", gain, state->wbd_offset_3_3[gain-6]);
-    }
-}
-
-u16 dib0070_wbd_offset(struct dvb_frontend *fe)
-{
-    struct dib0070_state *state = fe->tuner_priv;
-    const struct dib0070_wbd_gain_cfg *tmp = state->cfg->wbd_gain;
-    u32 freq = fe->dtv_property_cache.frequency/1000;
-
-    if (tmp != NULL) {
-	while (freq/1000 > tmp->freq) /* find the right one */
-	    tmp++;
-	state->wbd_gain_current = tmp->wbd_gain_val;
-	} else
-	state->wbd_gain_current = 6;
-
-    return state->wbd_offset_3_3[state->wbd_gain_current - 6];
-}
-EXPORT_SYMBOL(dib0070_wbd_offset);
-
-#define pgm_read_word(w) (*w)
-static int dib0070_reset(struct dvb_frontend *fe)
-{
-    struct dib0070_state *state = fe->tuner_priv;
-	u16 l, r, *n;
-
-	HARD_RESET(state);
-
-
-#ifndef FORCE_SBAND_TUNER
-	if ((dib0070_read_reg(state, 0x22) >> 9) & 0x1)
-		state->revision = (dib0070_read_reg(state, 0x1f) >> 8) & 0xff;
-	else
-#else
-#warning forcing SBAND
-#endif
-		state->revision = DIB0070S_P1A;
-
-	/* P1F or not */
-	dprintk("Revision: %x", state->revision);
-
-	if (state->revision == DIB0070_P1D) {
-		dprintk("Error: this driver is not to be used meant for P1D or earlier");
-		return -EINVAL;
-	}
-
-	n = (u16 *) dib0070_p1f_defaults;
-	l = pgm_read_word(n++);
-	while (l) {
-		r = pgm_read_word(n++);
-		do {
-			dib0070_write_reg(state, (u8)r, pgm_read_word(n++));
-			r++;
-		} while (--l);
-		l = pgm_read_word(n++);
-	}
-
-	if (state->cfg->force_crystal_mode != 0)
-		r = state->cfg->force_crystal_mode;
-	else if (state->cfg->clock_khz >= 24000)
-		r = 1;
-	else
-		r = 2;
-
-
-	r |= state->cfg->osc_buffer_state << 3;
-
-	dib0070_write_reg(state, 0x10, r);
-	dib0070_write_reg(state, 0x1f, (1 << 8) | ((state->cfg->clock_pad_drive & 0xf) << 5));
-
-	if (state->cfg->invert_iq) {
-		r = dib0070_read_reg(state, 0x02) & 0xffdf;
-		dib0070_write_reg(state, 0x02, r | (1 << 5));
-	}
-
-    if (state->revision == DIB0070S_P1A)
-	dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0);
-    else
-		dib0070_set_ctrl_lo5(fe, 5, 4, state->cfg->charge_pump, state->cfg->enable_third_order_filter);
-
-	dib0070_write_reg(state, 0x01, (54 << 9) | 0xc8);
-
-    dib0070_wbd_offset_calibration(state);
-
-    return 0;
-}
-
-static int dib0070_get_frequency(struct dvb_frontend *fe, u32 *frequency)
-{
-    struct dib0070_state *state = fe->tuner_priv;
-
-    *frequency = 1000 * state->current_rf;
-    return 0;
-}
-
-static int dib0070_release(struct dvb_frontend *fe)
-{
-	kfree(fe->tuner_priv);
-	fe->tuner_priv = NULL;
-	return 0;
-}
-
-static const struct dvb_tuner_ops dib0070_ops = {
-	.info = {
-		.name           = "DiBcom DiB0070",
-		.frequency_min  =  45000000,
-		.frequency_max  = 860000000,
-		.frequency_step =      1000,
-	},
-	.release       = dib0070_release,
-
-	.init          = dib0070_wakeup,
-	.sleep         = dib0070_sleep,
-	.set_params    = dib0070_tune,
-
-	.get_frequency = dib0070_get_frequency,
-//      .get_bandwidth = dib0070_get_bandwidth
-};
-
-struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg)
-{
-	struct dib0070_state *state = kzalloc(sizeof(struct dib0070_state), GFP_KERNEL);
-	if (state == NULL)
-		return NULL;
-
-	state->cfg = cfg;
-	state->i2c = i2c;
-	state->fe  = fe;
-	mutex_init(&state->i2c_buffer_lock);
-	fe->tuner_priv = state;
-
-	if (dib0070_reset(fe) != 0)
-		goto free_mem;
-
-	printk(KERN_INFO "DiB0070: successfully identified\n");
-	memcpy(&fe->ops.tuner_ops, &dib0070_ops, sizeof(struct dvb_tuner_ops));
-
-	fe->tuner_priv = state;
-	return fe;
-
-free_mem:
-	kfree(state);
-	fe->tuner_priv = NULL;
-	return NULL;
-}
-EXPORT_SYMBOL(dib0070_attach);
-
-MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
-MODULE_DESCRIPTION("Driver for the DiBcom 0070 base-band RF Tuner");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/dib0070.h b/drivers/media/dvb/frontends/dib0070.h
deleted file mode 100644
index 45c31fa..0000000
--- a/drivers/media/dvb/frontends/dib0070.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Linux-DVB Driver for DiBcom's DiB0070 base-band RF Tuner.
- *
- * Copyright (C) 2005-7 DiBcom (http://www.dibcom.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, version 2.
- */
-#ifndef DIB0070_H
-#define DIB0070_H
-
-struct dvb_frontend;
-struct i2c_adapter;
-
-#define DEFAULT_DIB0070_I2C_ADDRESS 0x60
-
-struct dib0070_wbd_gain_cfg {
-	u16 freq;
-	u16 wbd_gain_val;
-};
-
-struct dib0070_config {
-	u8 i2c_address;
-
-	/* tuner pins controlled externally */
-	int (*reset) (struct dvb_frontend *, int);
-	int (*sleep) (struct dvb_frontend *, int);
-
-	/*  offset in kHz */
-	int freq_offset_khz_uhf;
-	int freq_offset_khz_vhf;
-
-	u8 osc_buffer_state;	/* 0= normal, 1= tri-state */
-	u32 clock_khz;
-	u8 clock_pad_drive;	/* (Drive + 1) * 2mA */
-
-	u8 invert_iq;		/* invert Q - in case I or Q is inverted on the board */
-
-	u8 force_crystal_mode;	/* if == 0 -> decision is made in the driver default: <24 -> 2, >=24 -> 1 */
-
-	u8 flip_chip;
-	u8 enable_third_order_filter;
-	u8 charge_pump;
-
-	const struct dib0070_wbd_gain_cfg *wbd_gain;
-
-	u8 vga_filter;
-};
-
-#if defined(CONFIG_DVB_TUNER_DIB0070) || (defined(CONFIG_DVB_TUNER_DIB0070_MODULE) && defined(MODULE))
-extern struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg);
-extern u16 dib0070_wbd_offset(struct dvb_frontend *);
-extern void dib0070_ctrl_agc_filter(struct dvb_frontend *, u8 open);
-extern u8 dib0070_get_rf_output(struct dvb_frontend *fe);
-extern int dib0070_set_rf_output(struct dvb_frontend *fe, u8 no);
-#else
-static inline struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-
-static inline u16 dib0070_wbd_offset(struct dvb_frontend *fe)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return 0;
-}
-
-static inline void dib0070_ctrl_agc_filter(struct dvb_frontend *fe, u8 open)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-}
-#endif
-
-#endif
diff --git a/drivers/media/dvb/frontends/dib0090.c b/drivers/media/dvb/frontends/dib0090.c
deleted file mode 100644
index d9fe60b..0000000
--- a/drivers/media/dvb/frontends/dib0090.c
+++ /dev/null
@@ -1,2686 +0,0 @@
-/*
- * Linux-DVB Driver for DiBcom's DiB0090 base-band RF Tuner.
- *
- * Copyright (C) 2005-9 DiBcom (http://www.dibcom.fr/)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *
- * This code is more or less generated from another driver, please
- * excuse some codingstyle oddities.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/i2c.h>
-#include <linux/mutex.h>
-
-#include "dvb_frontend.h"
-
-#include "dib0090.h"
-#include "dibx000_common.h"
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
-
-#define dprintk(args...) do { \
-	if (debug) { \
-		printk(KERN_DEBUG "DiB0090: "); \
-		printk(args); \
-		printk("\n"); \
-	} \
-} while (0)
-
-#define CONFIG_SYS_DVBT
-#define CONFIG_SYS_ISDBT
-#define CONFIG_BAND_CBAND
-#define CONFIG_BAND_VHF
-#define CONFIG_BAND_UHF
-#define CONFIG_DIB0090_USE_PWM_AGC
-
-#define EN_LNA0      0x8000
-#define EN_LNA1      0x4000
-#define EN_LNA2      0x2000
-#define EN_LNA3      0x1000
-#define EN_MIX0      0x0800
-#define EN_MIX1      0x0400
-#define EN_MIX2      0x0200
-#define EN_MIX3      0x0100
-#define EN_IQADC     0x0040
-#define EN_PLL       0x0020
-#define EN_TX        0x0010
-#define EN_BB        0x0008
-#define EN_LO        0x0004
-#define EN_BIAS      0x0001
-
-#define EN_IQANA     0x0002
-#define EN_DIGCLK    0x0080	/* not in the 0x24 reg, only in 0x1b */
-#define EN_CRYSTAL   0x0002
-
-#define EN_UHF		 0x22E9
-#define EN_VHF		 0x44E9
-#define EN_LBD		 0x11E9
-#define EN_SBD		 0x44E9
-#define EN_CAB		 0x88E9
-
-/* Calibration defines */
-#define      DC_CAL 0x1
-#define     WBD_CAL 0x2
-#define    TEMP_CAL 0x4
-#define CAPTRIM_CAL 0x8
-
-#define KROSUS_PLL_LOCKED   0x800
-#define KROSUS              0x2
-
-/* Use those defines to identify SOC version */
-#define SOC               0x02
-#define SOC_7090_P1G_11R1 0x82
-#define SOC_7090_P1G_21R1 0x8a
-#define SOC_8090_P1G_11R1 0x86
-#define SOC_8090_P1G_21R1 0x8e
-
-/* else use thos ones to check */
-#define P1A_B      0x0
-#define P1C	   0x1
-#define P1D_E_F    0x3
-#define P1G	   0x7
-#define P1G_21R2   0xf
-
-#define MP001 0x1		/* Single 9090/8096 */
-#define MP005 0x4		/* Single Sband */
-#define MP008 0x6		/* Dual diversity VHF-UHF-LBAND */
-#define MP009 0x7		/* Dual diversity 29098 CBAND-UHF-LBAND-SBAND */
-
-#define pgm_read_word(w) (*w)
-
-struct dc_calibration;
-
-struct dib0090_tuning {
-	u32 max_freq;		/* for every frequency less than or equal to that field: this information is correct */
-	u8 switch_trim;
-	u8 lna_tune;
-	u16 lna_bias;
-	u16 v2i;
-	u16 mix;
-	u16 load;
-	u16 tuner_enable;
-};
-
-struct dib0090_pll {
-	u32 max_freq;		/* for every frequency less than or equal to that field: this information is correct */
-	u8 vco_band;
-	u8 hfdiv_code;
-	u8 hfdiv;
-	u8 topresc;
-};
-
-struct dib0090_identity {
-	u8 version;
-	u8 product;
-	u8 p1g;
-	u8 in_soc;
-};
-
-struct dib0090_state {
-	struct i2c_adapter *i2c;
-	struct dvb_frontend *fe;
-	const struct dib0090_config *config;
-
-	u8 current_band;
-	enum frontend_tune_state tune_state;
-	u32 current_rf;
-
-	u16 wbd_offset;
-	s16 wbd_target;		/* in dB */
-
-	s16 rf_gain_limit;	/* take-over-point: where to split between bb and rf gain */
-	s16 current_gain;	/* keeps the currently programmed gain */
-	u8 agc_step;		/* new binary search */
-
-	u16 gain[2];		/* for channel monitoring */
-
-	const u16 *rf_ramp;
-	const u16 *bb_ramp;
-
-	/* for the software AGC ramps */
-	u16 bb_1_def;
-	u16 rf_lt_def;
-	u16 gain_reg[4];
-
-	/* for the captrim/dc-offset search */
-	s8 step;
-	s16 adc_diff;
-	s16 min_adc_diff;
-
-	s8 captrim;
-	s8 fcaptrim;
-
-	const struct dc_calibration *dc;
-	u16 bb6, bb7;
-
-	const struct dib0090_tuning *current_tune_table_index;
-	const struct dib0090_pll *current_pll_table_index;
-
-	u8 tuner_is_tuned;
-	u8 agc_freeze;
-
-	struct dib0090_identity identity;
-
-	u32 rf_request;
-	u8 current_standard;
-
-	u8 calibrate;
-	u32 rest;
-	u16 bias;
-	s16 temperature;
-
-	u8 wbd_calibration_gain;
-	const struct dib0090_wbd_slope *current_wbd_table;
-	u16 wbdmux;
-
-	/* for the I2C transfer */
-	struct i2c_msg msg[2];
-	u8 i2c_write_buffer[3];
-	u8 i2c_read_buffer[2];
-	struct mutex i2c_buffer_lock;
-};
-
-struct dib0090_fw_state {
-	struct i2c_adapter *i2c;
-	struct dvb_frontend *fe;
-	struct dib0090_identity identity;
-	const struct dib0090_config *config;
-
-	/* for the I2C transfer */
-	struct i2c_msg msg;
-	u8 i2c_write_buffer[2];
-	u8 i2c_read_buffer[2];
-	struct mutex i2c_buffer_lock;
-};
-
-static u16 dib0090_read_reg(struct dib0090_state *state, u8 reg)
-{
-	u16 ret;
-
-	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
-		dprintk("could not acquire lock");
-		return 0;
-	}
-
-	state->i2c_write_buffer[0] = reg;
-
-	memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
-	state->msg[0].addr = state->config->i2c_address;
-	state->msg[0].flags = 0;
-	state->msg[0].buf = state->i2c_write_buffer;
-	state->msg[0].len = 1;
-	state->msg[1].addr = state->config->i2c_address;
-	state->msg[1].flags = I2C_M_RD;
-	state->msg[1].buf = state->i2c_read_buffer;
-	state->msg[1].len = 2;
-
-	if (i2c_transfer(state->i2c, state->msg, 2) != 2) {
-		printk(KERN_WARNING "DiB0090 I2C read failed\n");
-		ret = 0;
-	} else
-		ret = (state->i2c_read_buffer[0] << 8)
-			| state->i2c_read_buffer[1];
-
-	mutex_unlock(&state->i2c_buffer_lock);
-	return ret;
-}
-
-static int dib0090_write_reg(struct dib0090_state *state, u32 reg, u16 val)
-{
-	int ret;
-
-	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
-		dprintk("could not acquire lock");
-		return -EINVAL;
-	}
-
-	state->i2c_write_buffer[0] = reg & 0xff;
-	state->i2c_write_buffer[1] = val >> 8;
-	state->i2c_write_buffer[2] = val & 0xff;
-
-	memset(state->msg, 0, sizeof(struct i2c_msg));
-	state->msg[0].addr = state->config->i2c_address;
-	state->msg[0].flags = 0;
-	state->msg[0].buf = state->i2c_write_buffer;
-	state->msg[0].len = 3;
-
-	if (i2c_transfer(state->i2c, state->msg, 1) != 1) {
-		printk(KERN_WARNING "DiB0090 I2C write failed\n");
-		ret = -EREMOTEIO;
-	} else
-		ret = 0;
-
-	mutex_unlock(&state->i2c_buffer_lock);
-	return ret;
-}
-
-static u16 dib0090_fw_read_reg(struct dib0090_fw_state *state, u8 reg)
-{
-	u16 ret;
-
-	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
-		dprintk("could not acquire lock");
-		return 0;
-	}
-
-	state->i2c_write_buffer[0] = reg;
-
-	memset(&state->msg, 0, sizeof(struct i2c_msg));
-	state->msg.addr = reg;
-	state->msg.flags = I2C_M_RD;
-	state->msg.buf = state->i2c_read_buffer;
-	state->msg.len = 2;
-	if (i2c_transfer(state->i2c, &state->msg, 1) != 1) {
-		printk(KERN_WARNING "DiB0090 I2C read failed\n");
-		ret = 0;
-	} else
-		ret = (state->i2c_read_buffer[0] << 8)
-			| state->i2c_read_buffer[1];
-
-	mutex_unlock(&state->i2c_buffer_lock);
-	return ret;
-}
-
-static int dib0090_fw_write_reg(struct dib0090_fw_state *state, u8 reg, u16 val)
-{
-	int ret;
-
-	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
-		dprintk("could not acquire lock");
-		return -EINVAL;
-	}
-
-	state->i2c_write_buffer[0] = val >> 8;
-	state->i2c_write_buffer[1] = val & 0xff;
-
-	memset(&state->msg, 0, sizeof(struct i2c_msg));
-	state->msg.addr = reg;
-	state->msg.flags = 0;
-	state->msg.buf = state->i2c_write_buffer;
-	state->msg.len = 2;
-	if (i2c_transfer(state->i2c, &state->msg, 1) != 1) {
-		printk(KERN_WARNING "DiB0090 I2C write failed\n");
-		ret = -EREMOTEIO;
-	} else
-		ret = 0;
-
-	mutex_unlock(&state->i2c_buffer_lock);
-	return ret;
-}
-
-#define HARD_RESET(state) do {  if (cfg->reset) {  if (cfg->sleep) cfg->sleep(fe, 0); msleep(10);  cfg->reset(fe, 1); msleep(10);  cfg->reset(fe, 0); msleep(10);  }  } while (0)
-#define ADC_TARGET -220
-#define GAIN_ALPHA 5
-#define WBD_ALPHA 6
-#define LPF	100
-static void dib0090_write_regs(struct dib0090_state *state, u8 r, const u16 * b, u8 c)
-{
-	do {
-		dib0090_write_reg(state, r++, *b++);
-	} while (--c);
-}
-
-static int dib0090_identify(struct dvb_frontend *fe)
-{
-	struct dib0090_state *state = fe->tuner_priv;
-	u16 v;
-	struct dib0090_identity *identity = &state->identity;
-
-	v = dib0090_read_reg(state, 0x1a);
-
-	identity->p1g = 0;
-	identity->in_soc = 0;
-
-	dprintk("Tuner identification (Version = 0x%04x)", v);
-
-	/* without PLL lock info */
-	v &= ~KROSUS_PLL_LOCKED;
-
-	identity->version = v & 0xff;
-	identity->product = (v >> 8) & 0xf;
-
-	if (identity->product != KROSUS)
-		goto identification_error;
-
-	if ((identity->version & 0x3) == SOC) {
-		identity->in_soc = 1;
-		switch (identity->version) {
-		case SOC_8090_P1G_11R1:
-			dprintk("SOC 8090 P1-G11R1 Has been detected");
-			identity->p1g = 1;
-			break;
-		case SOC_8090_P1G_21R1:
-			dprintk("SOC 8090 P1-G21R1 Has been detected");
-			identity->p1g = 1;
-			break;
-		case SOC_7090_P1G_11R1:
-			dprintk("SOC 7090 P1-G11R1 Has been detected");
-			identity->p1g = 1;
-			break;
-		case SOC_7090_P1G_21R1:
-			dprintk("SOC 7090 P1-G21R1 Has been detected");
-			identity->p1g = 1;
-			break;
-		default:
-			goto identification_error;
-		}
-	} else {
-		switch ((identity->version >> 5) & 0x7) {
-		case MP001:
-			dprintk("MP001 : 9090/8096");
-			break;
-		case MP005:
-			dprintk("MP005 : Single Sband");
-			break;
-		case MP008:
-			dprintk("MP008 : diversity VHF-UHF-LBAND");
-			break;
-		case MP009:
-			dprintk("MP009 : diversity 29098 CBAND-UHF-LBAND-SBAND");
-			break;
-		default:
-			goto identification_error;
-		}
-
-		switch (identity->version & 0x1f) {
-		case P1G_21R2:
-			dprintk("P1G_21R2 detected");
-			identity->p1g = 1;
-			break;
-		case P1G:
-			dprintk("P1G detected");
-			identity->p1g = 1;
-			break;
-		case P1D_E_F:
-			dprintk("P1D/E/F detected");
-			break;
-		case P1C:
-			dprintk("P1C detected");
-			break;
-		case P1A_B:
-			dprintk("P1-A/B detected: driver is deactivated - not available");
-			goto identification_error;
-			break;
-		default:
-			goto identification_error;
-		}
-	}
-
-	return 0;
-
-identification_error:
-	return -EIO;
-}
-
-static int dib0090_fw_identify(struct dvb_frontend *fe)
-{
-	struct dib0090_fw_state *state = fe->tuner_priv;
-	struct dib0090_identity *identity = &state->identity;
-
-	u16 v = dib0090_fw_read_reg(state, 0x1a);
-	identity->p1g = 0;
-	identity->in_soc = 0;
-
-	dprintk("FE: Tuner identification (Version = 0x%04x)", v);
-
-	/* without PLL lock info */
-	v &= ~KROSUS_PLL_LOCKED;
-
-	identity->version = v & 0xff;
-	identity->product = (v >> 8) & 0xf;
-
-	if (identity->product != KROSUS)
-		goto identification_error;
-
-	if ((identity->version & 0x3) == SOC) {
-		identity->in_soc = 1;
-		switch (identity->version) {
-		case SOC_8090_P1G_11R1:
-			dprintk("SOC 8090 P1-G11R1 Has been detected");
-			identity->p1g = 1;
-			break;
-		case SOC_8090_P1G_21R1:
-			dprintk("SOC 8090 P1-G21R1 Has been detected");
-			identity->p1g = 1;
-			break;
-		case SOC_7090_P1G_11R1:
-			dprintk("SOC 7090 P1-G11R1 Has been detected");
-			identity->p1g = 1;
-			break;
-		case SOC_7090_P1G_21R1:
-			dprintk("SOC 7090 P1-G21R1 Has been detected");
-			identity->p1g = 1;
-			break;
-		default:
-			goto identification_error;
-		}
-	} else {
-		switch ((identity->version >> 5) & 0x7) {
-		case MP001:
-			dprintk("MP001 : 9090/8096");
-			break;
-		case MP005:
-			dprintk("MP005 : Single Sband");
-			break;
-		case MP008:
-			dprintk("MP008 : diversity VHF-UHF-LBAND");
-			break;
-		case MP009:
-			dprintk("MP009 : diversity 29098 CBAND-UHF-LBAND-SBAND");
-			break;
-		default:
-			goto identification_error;
-		}
-
-		switch (identity->version & 0x1f) {
-		case P1G_21R2:
-			dprintk("P1G_21R2 detected");
-			identity->p1g = 1;
-			break;
-		case P1G:
-			dprintk("P1G detected");
-			identity->p1g = 1;
-			break;
-		case P1D_E_F:
-			dprintk("P1D/E/F detected");
-			break;
-		case P1C:
-			dprintk("P1C detected");
-			break;
-		case P1A_B:
-			dprintk("P1-A/B detected: driver is deactivated - not available");
-			goto identification_error;
-			break;
-		default:
-			goto identification_error;
-		}
-	}
-
-	return 0;
-
-identification_error:
-	return -EIO;
-}
-
-static void dib0090_reset_digital(struct dvb_frontend *fe, const struct dib0090_config *cfg)
-{
-	struct dib0090_state *state = fe->tuner_priv;
-	u16 PllCfg, i, v;
-
-	HARD_RESET(state);
-
-	dib0090_write_reg(state, 0x24, EN_PLL | EN_CRYSTAL);
-	dib0090_write_reg(state, 0x1b, EN_DIGCLK | EN_PLL | EN_CRYSTAL);	/* PLL, DIG_CLK and CRYSTAL remain */
-
-	if (!cfg->in_soc) {
-		/* adcClkOutRatio=8->7, release reset */
-		dib0090_write_reg(state, 0x20, ((cfg->io.adc_clock_ratio - 1) << 11) | (0 << 10) | (1 << 9) | (1 << 8) | (0 << 4) | 0);
-		if (cfg->clkoutdrive != 0)
-			dib0090_write_reg(state, 0x23, (0 << 15) | ((!cfg->analog_output) << 14) | (2 << 10) | (1 << 9) | (0 << 8)
-					  | (cfg->clkoutdrive << 5) | (cfg->clkouttobamse << 4) | (0 << 2) | (0));
-		else
-			dib0090_write_reg(state, 0x23, (0 << 15) | ((!cfg->analog_output) << 14) | (2 << 10) | (1 << 9) | (0 << 8)
-					  | (7 << 5) | (cfg->clkouttobamse << 4) | (0 << 2) | (0));
-	}
-
-	/* Read Pll current config * */
-	PllCfg = dib0090_read_reg(state, 0x21);
-
-	/** Reconfigure PLL if current setting is different from default setting **/
-	if ((PllCfg & 0x1FFF) != ((cfg->io.pll_range << 12) | (cfg->io.pll_loopdiv << 6) | (cfg->io.pll_prediv)) && (!cfg->in_soc)
-			&& !cfg->io.pll_bypass) {
-
-		/* Set Bypass mode */
-		PllCfg |= (1 << 15);
-		dib0090_write_reg(state, 0x21, PllCfg);
-
-		/* Set Reset Pll */
-		PllCfg &= ~(1 << 13);
-		dib0090_write_reg(state, 0x21, PllCfg);
-
-	/*** Set new Pll configuration in bypass and reset state ***/
-		PllCfg = (1 << 15) | (0 << 13) | (cfg->io.pll_range << 12) | (cfg->io.pll_loopdiv << 6) | (cfg->io.pll_prediv);
-		dib0090_write_reg(state, 0x21, PllCfg);
-
-		/* Remove Reset Pll */
-		PllCfg |= (1 << 13);
-		dib0090_write_reg(state, 0x21, PllCfg);
-
-	/*** Wait for PLL lock ***/
-		i = 100;
-		do {
-			v = !!(dib0090_read_reg(state, 0x1a) & 0x800);
-			if (v)
-				break;
-		} while (--i);
-
-		if (i == 0) {
-			dprintk("Pll: Unable to lock Pll");
-			return;
-		}
-
-		/* Finally Remove Bypass mode */
-		PllCfg &= ~(1 << 15);
-		dib0090_write_reg(state, 0x21, PllCfg);
-	}
-
-	if (cfg->io.pll_bypass) {
-		PllCfg |= (cfg->io.pll_bypass << 15);
-		dib0090_write_reg(state, 0x21, PllCfg);
-	}
-}
-
-static int dib0090_fw_reset_digital(struct dvb_frontend *fe, const struct dib0090_config *cfg)
-{
-	struct dib0090_fw_state *state = fe->tuner_priv;
-	u16 PllCfg;
-	u16 v;
-	int i;
-
-	dprintk("fw reset digital");
-	HARD_RESET(state);
-
-	dib0090_fw_write_reg(state, 0x24, EN_PLL | EN_CRYSTAL);
-	dib0090_fw_write_reg(state, 0x1b, EN_DIGCLK | EN_PLL | EN_CRYSTAL);	/* PLL, DIG_CLK and CRYSTAL remain */
-
-	dib0090_fw_write_reg(state, 0x20,
-			((cfg->io.adc_clock_ratio - 1) << 11) | (0 << 10) | (1 << 9) | (1 << 8) | (cfg->data_tx_drv << 4) | cfg->ls_cfg_pad_drv);
-
-	v = (0 << 15) | ((!cfg->analog_output) << 14) | (1 << 9) | (0 << 8) | (cfg->clkouttobamse << 4) | (0 << 2) | (0);
-	if (cfg->clkoutdrive != 0)
-		v |= cfg->clkoutdrive << 5;
-	else
-		v |= 7 << 5;
-
-	v |= 2 << 10;
-	dib0090_fw_write_reg(state, 0x23, v);
-
-	/* Read Pll current config * */
-	PllCfg = dib0090_fw_read_reg(state, 0x21);
-
-	/** Reconfigure PLL if current setting is different from default setting **/
-	if ((PllCfg & 0x1FFF) != ((cfg->io.pll_range << 12) | (cfg->io.pll_loopdiv << 6) | (cfg->io.pll_prediv)) && !cfg->io.pll_bypass) {
-
-		/* Set Bypass mode */
-		PllCfg |= (1 << 15);
-		dib0090_fw_write_reg(state, 0x21, PllCfg);
-
-		/* Set Reset Pll */
-		PllCfg &= ~(1 << 13);
-		dib0090_fw_write_reg(state, 0x21, PllCfg);
-
-	/*** Set new Pll configuration in bypass and reset state ***/
-		PllCfg = (1 << 15) | (0 << 13) | (cfg->io.pll_range << 12) | (cfg->io.pll_loopdiv << 6) | (cfg->io.pll_prediv);
-		dib0090_fw_write_reg(state, 0x21, PllCfg);
-
-		/* Remove Reset Pll */
-		PllCfg |= (1 << 13);
-		dib0090_fw_write_reg(state, 0x21, PllCfg);
-
-	/*** Wait for PLL lock ***/
-		i = 100;
-		do {
-			v = !!(dib0090_fw_read_reg(state, 0x1a) & 0x800);
-			if (v)
-				break;
-		} while (--i);
-
-		if (i == 0) {
-			dprintk("Pll: Unable to lock Pll");
-			return -EIO;
-		}
-
-		/* Finally Remove Bypass mode */
-		PllCfg &= ~(1 << 15);
-		dib0090_fw_write_reg(state, 0x21, PllCfg);
-	}
-
-	if (cfg->io.pll_bypass) {
-		PllCfg |= (cfg->io.pll_bypass << 15);
-		dib0090_fw_write_reg(state, 0x21, PllCfg);
-	}
-
-	return dib0090_fw_identify(fe);
-}
-
-static int dib0090_wakeup(struct dvb_frontend *fe)
-{
-	struct dib0090_state *state = fe->tuner_priv;
-	if (state->config->sleep)
-		state->config->sleep(fe, 0);
-
-	/* enable dataTX in case we have been restarted in the wrong moment */
-	dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) | (1 << 14));
-	return 0;
-}
-
-static int dib0090_sleep(struct dvb_frontend *fe)
-{
-	struct dib0090_state *state = fe->tuner_priv;
-	if (state->config->sleep)
-		state->config->sleep(fe, 1);
-	return 0;
-}
-
-void dib0090_dcc_freq(struct dvb_frontend *fe, u8 fast)
-{
-	struct dib0090_state *state = fe->tuner_priv;
-	if (fast)
-		dib0090_write_reg(state, 0x04, 0);
-	else
-		dib0090_write_reg(state, 0x04, 1);
-}
-
-EXPORT_SYMBOL(dib0090_dcc_freq);
-
-static const u16 bb_ramp_pwm_normal_socs[] = {
-	550,			/* max BB gain in 10th of dB */
-	(1 << 9) | 8,		/* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> BB_RAMP2 */
-	440,
-	(4 << 9) | 0,		/* BB_RAMP3 = 26dB */
-	(0 << 9) | 208,		/* BB_RAMP4 */
-	(4 << 9) | 208,		/* BB_RAMP5 = 29dB */
-	(0 << 9) | 440,		/* BB_RAMP6 */
-};
-
-static const u16 rf_ramp_pwm_cband_7090[] = {
-	280,			/* max RF gain in 10th of dB */
-	18,			/* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
-	504,			/* ramp_max = maximum X used on the ramp */
-	(29 << 10) | 364,	/* RF_RAMP5, LNA 1 = 8dB */
-	(0 << 10) | 504,	/* RF_RAMP6, LNA 1 */
-	(60 << 10) | 228,	/* RF_RAMP7, LNA 2 = 7.7dB */
-	(0 << 10) | 364,	/* RF_RAMP8, LNA 2 */
-	(34 << 10) | 109,	/* GAIN_4_1, LNA 3 = 6.8dB */
-	(0 << 10) | 228,	/* GAIN_4_2, LNA 3 */
-	(37 << 10) | 0,		/* RF_RAMP3, LNA 4 = 6.2dB */
-	(0 << 10) | 109,	/* RF_RAMP4, LNA 4 */
-};
-
-static const uint16_t rf_ramp_pwm_cband_7090e_sensitivity[] = {
-	186,
-	40,
-	746,
-	(10 << 10) | 345,
-	(0  << 10) | 746,
-	(0 << 10) | 0,
-	(0  << 10) | 0,
-	(28 << 10) | 200,
-	(0  << 10) | 345,
-	(20 << 10) | 0,
-	(0  << 10) | 200,
-};
-
-static const uint16_t rf_ramp_pwm_cband_7090e_aci[] = {
-	86,
-	40,
-	345,
-	(0 << 10) | 0,
-	(0 << 10) | 0,
-	(0 << 10) | 0,
-	(0 << 10) | 0,
-	(28 << 10) | 200,
-	(0  << 10) | 345,
-	(20 << 10) | 0,
-	(0  << 10) | 200,
-};
-
-static const u16 rf_ramp_pwm_cband_8090[] = {
-	345,			/* max RF gain in 10th of dB */
-	29,			/* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
-	1000,			/* ramp_max = maximum X used on the ramp */
-	(35 << 10) | 772,	/* RF_RAMP3, LNA 1 = 8dB */
-	(0 << 10) | 1000,	/* RF_RAMP4, LNA 1 */
-	(58 << 10) | 496,	/* RF_RAMP5, LNA 2 = 9.5dB */
-	(0 << 10) | 772,	/* RF_RAMP6, LNA 2 */
-	(27 << 10) | 200,	/* RF_RAMP7, LNA 3 = 10.5dB */
-	(0 << 10) | 496,	/* RF_RAMP8, LNA 3 */
-	(40 << 10) | 0,		/* GAIN_4_1, LNA 4 = 7dB */
-	(0 << 10) | 200,	/* GAIN_4_2, LNA 4 */
-};
-
-static const u16 rf_ramp_pwm_uhf_7090[] = {
-	407,			/* max RF gain in 10th of dB */
-	13,			/* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
-	529,			/* ramp_max = maximum X used on the ramp */
-	(23 << 10) | 0,		/* RF_RAMP3, LNA 1 = 14.7dB */
-	(0 << 10) | 176,	/* RF_RAMP4, LNA 1 */
-	(63 << 10) | 400,	/* RF_RAMP5, LNA 2 = 8dB */
-	(0 << 10) | 529,	/* RF_RAMP6, LNA 2 */
-	(48 << 10) | 316,	/* RF_RAMP7, LNA 3 = 6.8dB */
-	(0 << 10) | 400,	/* RF_RAMP8, LNA 3 */
-	(29 << 10) | 176,	/* GAIN_4_1, LNA 4 = 11.5dB */
-	(0 << 10) | 316,	/* GAIN_4_2, LNA 4 */
-};
-
-static const u16 rf_ramp_pwm_uhf_8090[] = {
-	388,			/* max RF gain in 10th of dB */
-	26,			/* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
-	1008,			/* ramp_max = maximum X used on the ramp */
-	(11 << 10) | 0,		/* RF_RAMP3, LNA 1 = 14.7dB */
-	(0 << 10) | 369,	/* RF_RAMP4, LNA 1 */
-	(41 << 10) | 809,	/* RF_RAMP5, LNA 2 = 8dB */
-	(0 << 10) | 1008,	/* RF_RAMP6, LNA 2 */
-	(27 << 10) | 659,	/* RF_RAMP7, LNA 3 = 6dB */
-	(0 << 10) | 809,	/* RF_RAMP8, LNA 3 */
-	(14 << 10) | 369,	/* GAIN_4_1, LNA 4 = 11.5dB */
-	(0 << 10) | 659,	/* GAIN_4_2, LNA 4 */
-};
-
-static const u16 rf_ramp_pwm_cband[] = {
-	0,			/* max RF gain in 10th of dB */
-	0,			/* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> 0x2b */
-	0,			/* ramp_max = maximum X used on the ramp */
-	(0 << 10) | 0,		/* 0x2c, LNA 1 = 0dB */
-	(0 << 10) | 0,		/* 0x2d, LNA 1 */
-	(0 << 10) | 0,		/* 0x2e, LNA 2 = 0dB */
-	(0 << 10) | 0,		/* 0x2f, LNA 2 */
-	(0 << 10) | 0,		/* 0x30, LNA 3 = 0dB */
-	(0 << 10) | 0,		/* 0x31, LNA 3 */
-	(0 << 10) | 0,		/* GAIN_4_1, LNA 4 = 0dB */
-	(0 << 10) | 0,		/* GAIN_4_2, LNA 4 */
-};
-
-static const u16 rf_ramp_vhf[] = {
-	412,			/* max RF gain in 10th of dB */
-	132, 307, 127,		/* LNA1,  13.2dB */
-	105, 412, 255,		/* LNA2,  10.5dB */
-	50, 50, 127,		/* LNA3,  5dB */
-	125, 175, 127,		/* LNA4,  12.5dB */
-	0, 0, 127,		/* CBAND, 0dB */
-};
-
-static const u16 rf_ramp_uhf[] = {
-	412,			/* max RF gain in 10th of dB */
-	132, 307, 127,		/* LNA1  : total gain = 13.2dB, point on the ramp where this amp is full gain, value to write to get full gain */
-	105, 412, 255,		/* LNA2  : 10.5 dB */
-	50, 50, 127,		/* LNA3  :  5.0 dB */
-	125, 175, 127,		/* LNA4  : 12.5 dB */
-	0, 0, 127,		/* CBAND :  0.0 dB */
-};
-
-static const u16 rf_ramp_cband_broadmatching[] =	/* for p1G only */
-{
-	314,			/* Calibrated at 200MHz order has been changed g4-g3-g2-g1 */
-	84, 314, 127,		/* LNA1 */
-	80, 230, 255,		/* LNA2 */
-	80, 150, 127,		/* LNA3  It was measured 12dB, do not lock if 120 */
-	70, 70, 127,		/* LNA4 */
-	0, 0, 127,		/* CBAND */
-};
-
-static const u16 rf_ramp_cband[] = {
-	332,			/* max RF gain in 10th of dB */
-	132, 252, 127,		/* LNA1,  dB */
-	80, 332, 255,		/* LNA2,  dB */
-	0, 0, 127,		/* LNA3,  dB */
-	0, 0, 127,		/* LNA4,  dB */
-	120, 120, 127,		/* LT1 CBAND */
-};
-
-static const u16 rf_ramp_pwm_vhf[] = {
-	404,			/* max RF gain in 10th of dB */
-	25,			/* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> 0x2b */
-	1011,			/* ramp_max = maximum X used on the ramp */
-	(6 << 10) | 417,	/* 0x2c, LNA 1 = 13.2dB */
-	(0 << 10) | 756,	/* 0x2d, LNA 1 */
-	(16 << 10) | 756,	/* 0x2e, LNA 2 = 10.5dB */
-	(0 << 10) | 1011,	/* 0x2f, LNA 2 */
-	(16 << 10) | 290,	/* 0x30, LNA 3 = 5dB */
-	(0 << 10) | 417,	/* 0x31, LNA 3 */
-	(7 << 10) | 0,		/* GAIN_4_1, LNA 4 = 12.5dB */
-	(0 << 10) | 290,	/* GAIN_4_2, LNA 4 */
-};
-
-static const u16 rf_ramp_pwm_uhf[] = {
-	404,			/* max RF gain in 10th of dB */
-	25,			/* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> 0x2b */
-	1011,			/* ramp_max = maximum X used on the ramp */
-	(6 << 10) | 417,	/* 0x2c, LNA 1 = 13.2dB */
-	(0 << 10) | 756,	/* 0x2d, LNA 1 */
-	(16 << 10) | 756,	/* 0x2e, LNA 2 = 10.5dB */
-	(0 << 10) | 1011,	/* 0x2f, LNA 2 */
-	(16 << 10) | 0,		/* 0x30, LNA 3 = 5dB */
-	(0 << 10) | 127,	/* 0x31, LNA 3 */
-	(7 << 10) | 127,	/* GAIN_4_1, LNA 4 = 12.5dB */
-	(0 << 10) | 417,	/* GAIN_4_2, LNA 4 */
-};
-
-static const u16 bb_ramp_boost[] = {
-	550,			/* max BB gain in 10th of dB */
-	260, 260, 26,		/* BB1, 26dB */
-	290, 550, 29,		/* BB2, 29dB */
-};
-
-static const u16 bb_ramp_pwm_normal[] = {
-	500,			/* max RF gain in 10th of dB */
-	8,			/* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> 0x34 */
-	400,
-	(2 << 9) | 0,		/* 0x35 = 21dB */
-	(0 << 9) | 168,		/* 0x36 */
-	(2 << 9) | 168,		/* 0x37 = 29dB */
-	(0 << 9) | 400,		/* 0x38 */
-};
-
-struct slope {
-	s16 range;
-	s16 slope;
-};
-static u16 slopes_to_scale(const struct slope *slopes, u8 num, s16 val)
-{
-	u8 i;
-	u16 rest;
-	u16 ret = 0;
-	for (i = 0; i < num; i++) {
-		if (val > slopes[i].range)
-			rest = slopes[i].range;
-		else
-			rest = val;
-		ret += (rest * slopes[i].slope) / slopes[i].range;
-		val -= rest;
-	}
-	return ret;
-}
-
-static const struct slope dib0090_wbd_slopes[3] = {
-	{66, 120},		/* -64,-52: offset -   65 */
-	{600, 170},		/* -52,-35: 65     -  665 */
-	{170, 250},		/* -45,-10: 665    - 835 */
-};
-
-static s16 dib0090_wbd_to_db(struct dib0090_state *state, u16 wbd)
-{
-	wbd &= 0x3ff;
-	if (wbd < state->wbd_offset)
-		wbd = 0;
-	else
-		wbd -= state->wbd_offset;
-	/* -64dB is the floor */
-	return -640 + (s16) slopes_to_scale(dib0090_wbd_slopes, ARRAY_SIZE(dib0090_wbd_slopes), wbd);
-}
-
-static void dib0090_wbd_target(struct dib0090_state *state, u32 rf)
-{
-	u16 offset = 250;
-
-	/* TODO : DAB digital N+/-1 interferer perfs : offset = 10 */
-
-	if (state->current_band == BAND_VHF)
-		offset = 650;
-#ifndef FIRMWARE_FIREFLY
-	if (state->current_band == BAND_VHF)
-		offset = state->config->wbd_vhf_offset;
-	if (state->current_band == BAND_CBAND)
-		offset = state->config->wbd_cband_offset;
-#endif
-
-	state->wbd_target = dib0090_wbd_to_db(state, state->wbd_offset + offset);
-	dprintk("wbd-target: %d dB", (u32) state->wbd_target);
-}
-
-static const int gain_reg_addr[4] = {
-	0x08, 0x0a, 0x0f, 0x01
-};
-
-static void dib0090_gain_apply(struct dib0090_state *state, s16 gain_delta, s16 top_delta, u8 force)
-{
-	u16 rf, bb, ref;
-	u16 i, v, gain_reg[4] = { 0 }, gain;
-	const u16 *g;
-
-	if (top_delta < -511)
-		top_delta = -511;
-	if (top_delta > 511)
-		top_delta = 511;
-
-	if (force) {
-		top_delta *= (1 << WBD_ALPHA);
-		gain_delta *= (1 << GAIN_ALPHA);
-	}
-
-	if (top_delta >= ((s16) (state->rf_ramp[0] << WBD_ALPHA) - state->rf_gain_limit))	/* overflow */
-		state->rf_gain_limit = state->rf_ramp[0] << WBD_ALPHA;
-	else
-		state->rf_gain_limit += top_delta;
-
-	if (state->rf_gain_limit < 0)	/*underflow */
-		state->rf_gain_limit = 0;
-
-	/* use gain as a temporary variable and correct current_gain */
-	gain = ((state->rf_gain_limit >> WBD_ALPHA) + state->bb_ramp[0]) << GAIN_ALPHA;
-	if (gain_delta >= ((s16) gain - state->current_gain))	/* overflow */
-		state->current_gain = gain;
-	else
-		state->current_gain += gain_delta;
-	/* cannot be less than 0 (only if gain_delta is less than 0 we can have current_gain < 0) */
-	if (state->current_gain < 0)
-		state->current_gain = 0;
-
-	/* now split total gain to rf and bb gain */
-	gain = state->current_gain >> GAIN_ALPHA;
-
-	/* requested gain is bigger than rf gain limit - ACI/WBD adjustment */
-	if (gain > (state->rf_gain_limit >> WBD_ALPHA)) {
-		rf = state->rf_gain_limit >> WBD_ALPHA;
-		bb = gain - rf;
-		if (bb > state->bb_ramp[0])
-			bb = state->bb_ramp[0];
-	} else {		/* high signal level -> all gains put on RF */
-		rf = gain;
-		bb = 0;
-	}
-
-	state->gain[0] = rf;
-	state->gain[1] = bb;
-
-	/* software ramp */
-	/* Start with RF gains */
-	g = state->rf_ramp + 1;	/* point on RF LNA1 max gain */
-	ref = rf;
-	for (i = 0; i < 7; i++) {	/* Go over all amplifiers => 5RF amps + 2 BB amps = 7 amps */
-		if (g[0] == 0 || ref < (g[1] - g[0]))	/* if total gain of the current amp is null or this amp is not concerned because it starts to work from an higher gain value */
-			v = 0;	/* force the gain to write for the current amp to be null */
-		else if (ref >= g[1])	/* Gain to set is higher than the high working point of this amp */
-			v = g[2];	/* force this amp to be full gain */
-		else		/* compute the value to set to this amp because we are somewhere in his range */
-			v = ((ref - (g[1] - g[0])) * g[2]) / g[0];
-
-		if (i == 0)	/* LNA 1 reg mapping */
-			gain_reg[0] = v;
-		else if (i == 1)	/* LNA 2 reg mapping */
-			gain_reg[0] |= v << 7;
-		else if (i == 2)	/* LNA 3 reg mapping */
-			gain_reg[1] = v;
-		else if (i == 3)	/* LNA 4 reg mapping */
-			gain_reg[1] |= v << 7;
-		else if (i == 4)	/* CBAND LNA reg mapping */
-			gain_reg[2] = v | state->rf_lt_def;
-		else if (i == 5)	/* BB gain 1 reg mapping */
-			gain_reg[3] = v << 3;
-		else if (i == 6)	/* BB gain 2 reg mapping */
-			gain_reg[3] |= v << 8;
-
-		g += 3;		/* go to next gain bloc */
-
-		/* When RF is finished, start with BB */
-		if (i == 4) {
-			g = state->bb_ramp + 1;	/* point on BB gain 1 max gain */
-			ref = bb;
-		}
-	}
-	gain_reg[3] |= state->bb_1_def;
-	gain_reg[3] |= ((bb % 10) * 100) / 125;
-
-#ifdef DEBUG_AGC
-	dprintk("GA CALC: DB: %3d(rf) + %3d(bb) = %3d gain_reg[0]=%04x gain_reg[1]=%04x gain_reg[2]=%04x gain_reg[0]=%04x", rf, bb, rf + bb,
-		gain_reg[0], gain_reg[1], gain_reg[2], gain_reg[3]);
-#endif
-
-	/* Write the amplifier regs */
-	for (i = 0; i < 4; i++) {
-		v = gain_reg[i];
-		if (force || state->gain_reg[i] != v) {
-			state->gain_reg[i] = v;
-			dib0090_write_reg(state, gain_reg_addr[i], v);
-		}
-	}
-}
-
-static void dib0090_set_boost(struct dib0090_state *state, int onoff)
-{
-	state->bb_1_def &= 0xdfff;
-	state->bb_1_def |= onoff << 13;
-}
-
-static void dib0090_set_rframp(struct dib0090_state *state, const u16 * cfg)
-{
-	state->rf_ramp = cfg;
-}
-
-static void dib0090_set_rframp_pwm(struct dib0090_state *state, const u16 * cfg)
-{
-	state->rf_ramp = cfg;
-
-	dib0090_write_reg(state, 0x2a, 0xffff);
-
-	dprintk("total RF gain: %ddB, step: %d", (u32) cfg[0], dib0090_read_reg(state, 0x2a));
-
-	dib0090_write_regs(state, 0x2c, cfg + 3, 6);
-	dib0090_write_regs(state, 0x3e, cfg + 9, 2);
-}
-
-static void dib0090_set_bbramp(struct dib0090_state *state, const u16 * cfg)
-{
-	state->bb_ramp = cfg;
-	dib0090_set_boost(state, cfg[0] > 500);	/* we want the boost if the gain is higher that 50dB */
-}
-
-static void dib0090_set_bbramp_pwm(struct dib0090_state *state, const u16 * cfg)
-{
-	state->bb_ramp = cfg;
-
-	dib0090_set_boost(state, cfg[0] > 500);	/* we want the boost if the gain is higher that 50dB */
-
-	dib0090_write_reg(state, 0x33, 0xffff);
-	dprintk("total BB gain: %ddB, step: %d", (u32) cfg[0], dib0090_read_reg(state, 0x33));
-	dib0090_write_regs(state, 0x35, cfg + 3, 4);
-}
-
-void dib0090_pwm_gain_reset(struct dvb_frontend *fe)
-{
-	struct dib0090_state *state = fe->tuner_priv;
-	/* reset the AGC */
-
-	if (state->config->use_pwm_agc) {
-#ifdef CONFIG_BAND_SBAND
-		if (state->current_band == BAND_SBAND) {
-			dib0090_set_rframp_pwm(state, rf_ramp_pwm_sband);
-			dib0090_set_bbramp_pwm(state, bb_ramp_pwm_boost);
-		} else
-#endif
-#ifdef CONFIG_BAND_CBAND
-		if (state->current_band == BAND_CBAND) {
-			if (state->identity.in_soc) {
-				dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal_socs);
-				if (state->identity.version == SOC_8090_P1G_11R1 || state->identity.version == SOC_8090_P1G_21R1)
-					dib0090_set_rframp_pwm(state, rf_ramp_pwm_cband_8090);
-				else if (state->identity.version == SOC_7090_P1G_11R1
-						|| state->identity.version == SOC_7090_P1G_21R1) {
-					if (state->config->is_dib7090e) {
-						if (state->rf_ramp == NULL)
-							dib0090_set_rframp_pwm(state, rf_ramp_pwm_cband_7090e_sensitivity);
-						else
-							dib0090_set_rframp_pwm(state, state->rf_ramp);
-					} else
-						dib0090_set_rframp_pwm(state, rf_ramp_pwm_cband_7090);
-				}
-			} else {
-				dib0090_set_rframp_pwm(state, rf_ramp_pwm_cband);
-				dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal);
-			}
-		} else
-#endif
-#ifdef CONFIG_BAND_VHF
-		if (state->current_band == BAND_VHF) {
-			if (state->identity.in_soc) {
-				dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal_socs);
-			} else {
-				dib0090_set_rframp_pwm(state, rf_ramp_pwm_vhf);
-				dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal);
-			}
-		} else
-#endif
-		{
-			if (state->identity.in_soc) {
-				if (state->identity.version == SOC_8090_P1G_11R1 || state->identity.version == SOC_8090_P1G_21R1)
-					dib0090_set_rframp_pwm(state, rf_ramp_pwm_uhf_8090);
-				else if (state->identity.version == SOC_7090_P1G_11R1 || state->identity.version == SOC_7090_P1G_21R1)
-					dib0090_set_rframp_pwm(state, rf_ramp_pwm_uhf_7090);
-				dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal_socs);
-			} else {
-				dib0090_set_rframp_pwm(state, rf_ramp_pwm_uhf);
-				dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal);
-			}
-		}
-
-		if (state->rf_ramp[0] != 0)
-			dib0090_write_reg(state, 0x32, (3 << 11));
-		else
-			dib0090_write_reg(state, 0x32, (0 << 11));
-
-		dib0090_write_reg(state, 0x04, 0x03);
-		dib0090_write_reg(state, 0x39, (1 << 10));
-	}
-}
-
-EXPORT_SYMBOL(dib0090_pwm_gain_reset);
-
-void dib0090_set_dc_servo(struct dvb_frontend *fe, u8 DC_servo_cutoff)
-{
-	struct dib0090_state *state = fe->tuner_priv;
-	if (DC_servo_cutoff < 4)
-		dib0090_write_reg(state, 0x04, DC_servo_cutoff);
-}
-EXPORT_SYMBOL(dib0090_set_dc_servo);
-
-static u32 dib0090_get_slow_adc_val(struct dib0090_state *state)
-{
-	u16 adc_val = dib0090_read_reg(state, 0x1d);
-	if (state->identity.in_soc)
-		adc_val >>= 2;
-	return adc_val;
-}
-
-int dib0090_gain_control(struct dvb_frontend *fe)
-{
-	struct dib0090_state *state = fe->tuner_priv;
-	enum frontend_tune_state *tune_state = &state->tune_state;
-	int ret = 10;
-
-	u16 wbd_val = 0;
-	u8 apply_gain_immediatly = 1;
-	s16 wbd_error = 0, adc_error = 0;
-
-	if (*tune_state == CT_AGC_START) {
-		state->agc_freeze = 0;
-		dib0090_write_reg(state, 0x04, 0x0);
-
-#ifdef CONFIG_BAND_SBAND
-		if (state->current_band == BAND_SBAND) {
-			dib0090_set_rframp(state, rf_ramp_sband);
-			dib0090_set_bbramp(state, bb_ramp_boost);
-		} else
-#endif
-#ifdef CONFIG_BAND_VHF
-		if (state->current_band == BAND_VHF && !state->identity.p1g) {
-			dib0090_set_rframp(state, rf_ramp_vhf);
-			dib0090_set_bbramp(state, bb_ramp_boost);
-		} else
-#endif
-#ifdef CONFIG_BAND_CBAND
-		if (state->current_band == BAND_CBAND && !state->identity.p1g) {
-			dib0090_set_rframp(state, rf_ramp_cband);
-			dib0090_set_bbramp(state, bb_ramp_boost);
-		} else
-#endif
-		if ((state->current_band == BAND_CBAND || state->current_band == BAND_VHF) && state->identity.p1g) {
-			dib0090_set_rframp(state, rf_ramp_cband_broadmatching);
-			dib0090_set_bbramp(state, bb_ramp_boost);
-		} else {
-			dib0090_set_rframp(state, rf_ramp_uhf);
-			dib0090_set_bbramp(state, bb_ramp_boost);
-		}
-
-		dib0090_write_reg(state, 0x32, 0);
-		dib0090_write_reg(state, 0x39, 0);
-
-		dib0090_wbd_target(state, state->current_rf);
-
-		state->rf_gain_limit = state->rf_ramp[0] << WBD_ALPHA;
-		state->current_gain = ((state->rf_ramp[0] + state->bb_ramp[0]) / 2) << GAIN_ALPHA;
-
-		*tune_state = CT_AGC_STEP_0;
-	} else if (!state->agc_freeze) {
-		s16 wbd = 0, i, cnt;
-
-		int adc;
-		wbd_val = dib0090_get_slow_adc_val(state);
-
-		if (*tune_state == CT_AGC_STEP_0)
-			cnt = 5;
-		else
-			cnt = 1;
-
-		for (i = 0; i < cnt; i++) {
-			wbd_val = dib0090_get_slow_adc_val(state);
-			wbd += dib0090_wbd_to_db(state, wbd_val);
-		}
-		wbd /= cnt;
-		wbd_error = state->wbd_target - wbd;
-
-		if (*tune_state == CT_AGC_STEP_0) {
-			if (wbd_error < 0 && state->rf_gain_limit > 0 && !state->identity.p1g) {
-#ifdef CONFIG_BAND_CBAND
-				/* in case of CBAND tune reduce first the lt_gain2 before adjusting the RF gain */
-				u8 ltg2 = (state->rf_lt_def >> 10) & 0x7;
-				if (state->current_band == BAND_CBAND && ltg2) {
-					ltg2 >>= 1;
-					state->rf_lt_def &= ltg2 << 10;	/* reduce in 3 steps from 7 to 0 */
-				}
-#endif
-			} else {
-				state->agc_step = 0;
-				*tune_state = CT_AGC_STEP_1;
-			}
-		} else {
-			/* calc the adc power */
-			adc = state->config->get_adc_power(fe);
-			adc = (adc * ((s32) 355774) + (((s32) 1) << 20)) >> 21;	/* included in [0:-700] */
-
-			adc_error = (s16) (((s32) ADC_TARGET) - adc);
-#ifdef CONFIG_STANDARD_DAB
-			if (state->fe->dtv_property_cache.delivery_system == STANDARD_DAB)
-				adc_error -= 10;
-#endif
-#ifdef CONFIG_STANDARD_DVBT
-			if (state->fe->dtv_property_cache.delivery_system == STANDARD_DVBT &&
-					(state->fe->dtv_property_cache.modulation == QAM_64 || state->fe->dtv_property_cache.modulation == QAM_16))
-				adc_error += 60;
-#endif
-#ifdef CONFIG_SYS_ISDBT
-			if ((state->fe->dtv_property_cache.delivery_system == SYS_ISDBT) && (((state->fe->dtv_property_cache.layer[0].segment_count >
-								0)
-							&&
-							((state->fe->dtv_property_cache.layer[0].modulation ==
-							  QAM_64)
-							 || (state->fe->dtv_property_cache.
-								 layer[0].modulation == QAM_16)))
-						||
-						((state->fe->dtv_property_cache.layer[1].segment_count >
-						  0)
-						 &&
-						 ((state->fe->dtv_property_cache.layer[1].modulation ==
-						   QAM_64)
-						  || (state->fe->dtv_property_cache.
-							  layer[1].modulation == QAM_16)))
-						||
-						((state->fe->dtv_property_cache.layer[2].segment_count >
-						  0)
-						 &&
-						 ((state->fe->dtv_property_cache.layer[2].modulation ==
-						   QAM_64)
-						  || (state->fe->dtv_property_cache.
-							  layer[2].modulation == QAM_16)))
-						)
-				)
-				adc_error += 60;
-#endif
-
-			if (*tune_state == CT_AGC_STEP_1) {	/* quickly go to the correct range of the ADC power */
-				if (ABS(adc_error) < 50 || state->agc_step++ > 5) {
-
-#ifdef CONFIG_STANDARD_DAB
-					if (state->fe->dtv_property_cache.delivery_system == STANDARD_DAB) {
-						dib0090_write_reg(state, 0x02, (1 << 15) | (15 << 11) | (31 << 6) | (63));	/* cap value = 63 : narrow BB filter : Fc = 1.8MHz */
-						dib0090_write_reg(state, 0x04, 0x0);
-					} else
-#endif
-					{
-						dib0090_write_reg(state, 0x02, (1 << 15) | (3 << 11) | (6 << 6) | (32));
-						dib0090_write_reg(state, 0x04, 0x01);	/*0 = 1KHz ; 1 = 150Hz ; 2 = 50Hz ; 3 = 50KHz ; 4 = servo fast */
-					}
-
-					*tune_state = CT_AGC_STOP;
-				}
-			} else {
-				/* everything higher than or equal to CT_AGC_STOP means tracking */
-				ret = 100;	/* 10ms interval */
-				apply_gain_immediatly = 0;
-			}
-		}
-#ifdef DEBUG_AGC
-		dprintk
-			("tune state %d, ADC = %3ddB (ADC err %3d) WBD %3ddB (WBD err %3d, WBD val SADC: %4d), RFGainLimit (TOP): %3d, signal: %3ddBm",
-			 (u32) *tune_state, (u32) adc, (u32) adc_error, (u32) wbd, (u32) wbd_error, (u32) wbd_val,
-			 (u32) state->rf_gain_limit >> WBD_ALPHA, (s32) 200 + adc - (state->current_gain >> GAIN_ALPHA));
-#endif
-	}
-
-	/* apply gain */
-	if (!state->agc_freeze)
-		dib0090_gain_apply(state, adc_error, wbd_error, apply_gain_immediatly);
-	return ret;
-}
-
-EXPORT_SYMBOL(dib0090_gain_control);
-
-void dib0090_get_current_gain(struct dvb_frontend *fe, u16 * rf, u16 * bb, u16 * rf_gain_limit, u16 * rflt)
-{
-	struct dib0090_state *state = fe->tuner_priv;
-	if (rf)
-		*rf = state->gain[0];
-	if (bb)
-		*bb = state->gain[1];
-	if (rf_gain_limit)
-		*rf_gain_limit = state->rf_gain_limit;
-	if (rflt)
-		*rflt = (state->rf_lt_def >> 10) & 0x7;
-}
-
-EXPORT_SYMBOL(dib0090_get_current_gain);
-
-u16 dib0090_get_wbd_target(struct dvb_frontend *fe)
-{
-	struct dib0090_state *state = fe->tuner_priv;
-	u32 f_MHz = state->fe->dtv_property_cache.frequency / 1000000;
-	s32 current_temp = state->temperature;
-	s32 wbd_thot, wbd_tcold;
-	const struct dib0090_wbd_slope *wbd = state->current_wbd_table;
-
-	while (f_MHz > wbd->max_freq)
-		wbd++;
-
-	dprintk("using wbd-table-entry with max freq %d", wbd->max_freq);
-
-	if (current_temp < 0)
-		current_temp = 0;
-	if (current_temp > 128)
-		current_temp = 128;
-
-	state->wbdmux &= ~(7 << 13);
-	if (wbd->wbd_gain != 0)
-		state->wbdmux |= (wbd->wbd_gain << 13);
-	else
-		state->wbdmux |= (4 << 13);
-
-	dib0090_write_reg(state, 0x10, state->wbdmux);
-
-	wbd_thot = wbd->offset_hot - (((u32) wbd->slope_hot * f_MHz) >> 6);
-	wbd_tcold = wbd->offset_cold - (((u32) wbd->slope_cold * f_MHz) >> 6);
-
-	wbd_tcold += ((wbd_thot - wbd_tcold) * current_temp) >> 7;
-
-	state->wbd_target = dib0090_wbd_to_db(state, state->wbd_offset + wbd_tcold);
-	dprintk("wbd-target: %d dB", (u32) state->wbd_target);
-	dprintk("wbd offset applied is %d", wbd_tcold);
-
-	return state->wbd_offset + wbd_tcold;
-}
-EXPORT_SYMBOL(dib0090_get_wbd_target);
-
-u16 dib0090_get_wbd_offset(struct dvb_frontend *fe)
-{
-	struct dib0090_state *state = fe->tuner_priv;
-	return state->wbd_offset;
-}
-EXPORT_SYMBOL(dib0090_get_wbd_offset);
-
-int dib0090_set_switch(struct dvb_frontend *fe, u8 sw1, u8 sw2, u8 sw3)
-{
-	struct dib0090_state *state = fe->tuner_priv;
-
-	dib0090_write_reg(state, 0x0b, (dib0090_read_reg(state, 0x0b) & 0xfff8)
-			| ((sw3 & 1) << 2) | ((sw2 & 1) << 1) | (sw1 & 1));
-
-	return 0;
-}
-EXPORT_SYMBOL(dib0090_set_switch);
-
-int dib0090_set_vga(struct dvb_frontend *fe, u8 onoff)
-{
-	struct dib0090_state *state = fe->tuner_priv;
-
-	dib0090_write_reg(state, 0x09, (dib0090_read_reg(state, 0x09) & 0x7fff)
-			| ((onoff & 1) << 15));
-	return 0;
-}
-EXPORT_SYMBOL(dib0090_set_vga);
-
-int dib0090_update_rframp_7090(struct dvb_frontend *fe, u8 cfg_sensitivity)
-{
-	struct dib0090_state *state = fe->tuner_priv;
-
-	if ((!state->identity.p1g) || (!state->identity.in_soc)
-			|| ((state->identity.version != SOC_7090_P1G_21R1)
-				&& (state->identity.version != SOC_7090_P1G_11R1))) {
-		dprintk("%s() function can only be used for dib7090P", __func__);
-		return -ENODEV;
-	}
-
-	if (cfg_sensitivity)
-		state->rf_ramp = (const u16 *)&rf_ramp_pwm_cband_7090e_sensitivity;
-	else
-		state->rf_ramp = (const u16 *)&rf_ramp_pwm_cband_7090e_aci;
-	dib0090_pwm_gain_reset(fe);
-
-	return 0;
-}
-EXPORT_SYMBOL(dib0090_update_rframp_7090);
-
-static const u16 dib0090_defaults[] = {
-
-	25, 0x01,
-	0x0000,
-	0x99a0,
-	0x6008,
-	0x0000,
-	0x8bcb,
-	0x0000,
-	0x0405,
-	0x0000,
-	0x0000,
-	0x0000,
-	0xb802,
-	0x0300,
-	0x2d12,
-	0xbac0,
-	0x7c00,
-	0xdbb9,
-	0x0954,
-	0x0743,
-	0x8000,
-	0x0001,
-	0x0040,
-	0x0100,
-	0x0000,
-	0xe910,
-	0x149e,
-
-	1, 0x1c,
-	0xff2d,
-
-	1, 0x39,
-	0x0000,
-
-	2, 0x1e,
-	0x07FF,
-	0x0007,
-
-	1, 0x24,
-	EN_UHF | EN_CRYSTAL,
-
-	2, 0x3c,
-	0x3ff,
-	0x111,
-	0
-};
-
-static const u16 dib0090_p1g_additionnal_defaults[] = {
-	1, 0x05,
-	0xabcd,
-
-	1, 0x11,
-	0x00b4,
-
-	1, 0x1c,
-	0xfffd,
-
-	1, 0x40,
-	0x108,
-	0
-};
-
-static void dib0090_set_default_config(struct dib0090_state *state, const u16 * n)
-{
-	u16 l, r;
-
-	l = pgm_read_word(n++);
-	while (l) {
-		r = pgm_read_word(n++);
-		do {
-			dib0090_write_reg(state, r, pgm_read_word(n++));
-			r++;
-		} while (--l);
-		l = pgm_read_word(n++);
-	}
-}
-
-#define CAP_VALUE_MIN (u8)  9
-#define CAP_VALUE_MAX (u8) 40
-#define HR_MIN	      (u8) 25
-#define HR_MAX	      (u8) 40
-#define POLY_MIN      (u8)  0
-#define POLY_MAX      (u8)  8
-
-static void dib0090_set_EFUSE(struct dib0090_state *state)
-{
-	u8 c, h, n;
-	u16 e2, e4;
-	u16 cal;
-
-	e2 = dib0090_read_reg(state, 0x26);
-	e4 = dib0090_read_reg(state, 0x28);
-
-	if ((state->identity.version == P1D_E_F) ||
-			(state->identity.version == P1G) || (e2 == 0xffff)) {
-
-		dib0090_write_reg(state, 0x22, 0x10);
-		cal = (dib0090_read_reg(state, 0x22) >> 6) & 0x3ff;
-
-		if ((cal < 670) || (cal == 1023))
-			cal = 850;
-		n = 165 - ((cal * 10)>>6) ;
-		e2 = e4 = (3<<12) | (34<<6) | (n);
-	}
-
-	if (e2 != e4)
-		e2 &= e4; /* Remove the redundancy  */
-
-	if (e2 != 0xffff) {
-		c = e2 & 0x3f;
-		n = (e2 >> 12) & 0xf;
-		h = (e2 >> 6) & 0x3f;
-
-		if ((c >= CAP_VALUE_MAX) || (c <= CAP_VALUE_MIN))
-			c = 32;
-		if ((h >= HR_MAX) || (h <= HR_MIN))
-			h = 34;
-		if ((n >= POLY_MAX) || (n <= POLY_MIN))
-			n = 3;
-
-		dib0090_write_reg(state, 0x13, (h << 10)) ;
-		e2 = (n<<11) | ((h>>2)<<6) | (c);
-		dib0090_write_reg(state, 0x2, e2) ; /* Load the BB_2 */
-	}
-}
-
-static int dib0090_reset(struct dvb_frontend *fe)
-{
-	struct dib0090_state *state = fe->tuner_priv;
-
-	dib0090_reset_digital(fe, state->config);
-	if (dib0090_identify(fe) < 0)
-		return -EIO;
-
-#ifdef CONFIG_TUNER_DIB0090_P1B_SUPPORT
-	if (!(state->identity.version & 0x1))	/* it is P1B - reset is already done */
-		return 0;
-#endif
-
-	if (!state->identity.in_soc) {
-		if ((dib0090_read_reg(state, 0x1a) >> 5) & 0x2)
-			dib0090_write_reg(state, 0x1b, (EN_IQADC | EN_BB | EN_BIAS | EN_DIGCLK | EN_PLL | EN_CRYSTAL));
-		else
-			dib0090_write_reg(state, 0x1b, (EN_DIGCLK | EN_PLL | EN_CRYSTAL));
-	}
-
-	dib0090_set_default_config(state, dib0090_defaults);
-
-	if (state->identity.in_soc)
-		dib0090_write_reg(state, 0x18, 0x2910);  /* charge pump current = 0 */
-
-	if (state->identity.p1g)
-		dib0090_set_default_config(state, dib0090_p1g_additionnal_defaults);
-
-	/* Update the efuse : Only available for KROSUS > P1C  and SOC as well*/
-	if (((state->identity.version & 0x1f) >= P1D_E_F) || (state->identity.in_soc))
-		dib0090_set_EFUSE(state);
-
-	/* Congigure in function of the crystal */
-	if (state->config->force_crystal_mode != 0)
-		dib0090_write_reg(state, 0x14,
-				state->config->force_crystal_mode & 3);
-	else if (state->config->io.clock_khz >= 24000)
-		dib0090_write_reg(state, 0x14, 1);
-	else
-		dib0090_write_reg(state, 0x14, 2);
-	dprintk("Pll lock : %d", (dib0090_read_reg(state, 0x1a) >> 11) & 0x1);
-
-	state->calibrate = DC_CAL | WBD_CAL | TEMP_CAL;	/* enable iq-offset-calibration and wbd-calibration when tuning next time */
-
-	return 0;
-}
-
-#define steps(u) (((u) > 15) ? ((u)-16) : (u))
-#define INTERN_WAIT 10
-static int dib0090_get_offset(struct dib0090_state *state, enum frontend_tune_state *tune_state)
-{
-	int ret = INTERN_WAIT * 10;
-
-	switch (*tune_state) {
-	case CT_TUNER_STEP_2:
-		/* Turns to positive */
-		dib0090_write_reg(state, 0x1f, 0x7);
-		*tune_state = CT_TUNER_STEP_3;
-		break;
-
-	case CT_TUNER_STEP_3:
-		state->adc_diff = dib0090_read_reg(state, 0x1d);
-
-		/* Turns to negative */
-		dib0090_write_reg(state, 0x1f, 0x4);
-		*tune_state = CT_TUNER_STEP_4;
-		break;
-
-	case CT_TUNER_STEP_4:
-		state->adc_diff -= dib0090_read_reg(state, 0x1d);
-		*tune_state = CT_TUNER_STEP_5;
-		ret = 0;
-		break;
-
-	default:
-		break;
-	}
-
-	return ret;
-}
-
-struct dc_calibration {
-	u8 addr;
-	u8 offset;
-	u8 pga:1;
-	u16 bb1;
-	u8 i:1;
-};
-
-static const struct dc_calibration dc_table[] = {
-	/* Step1 BB gain1= 26 with boost 1, gain 2 = 0 */
-	{0x06, 5, 1, (1 << 13) | (0 << 8) | (26 << 3), 1},
-	{0x07, 11, 1, (1 << 13) | (0 << 8) | (26 << 3), 0},
-	/* Step 2 BB gain 1 = 26 with boost = 1 & gain 2 = 29 */
-	{0x06, 0, 0, (1 << 13) | (29 << 8) | (26 << 3), 1},
-	{0x06, 10, 0, (1 << 13) | (29 << 8) | (26 << 3), 0},
-	{0},
-};
-
-static const struct dc_calibration dc_p1g_table[] = {
-	/* Step1 BB gain1= 26 with boost 1, gain 2 = 0 */
-	/* addr ; trim reg offset ; pga ; CTRL_BB1 value ; i or q */
-	{0x06, 5, 1, (1 << 13) | (0 << 8) | (15 << 3), 1},
-	{0x07, 11, 1, (1 << 13) | (0 << 8) | (15 << 3), 0},
-	/* Step 2 BB gain 1 = 26 with boost = 1 & gain 2 = 29 */
-	{0x06, 0, 0, (1 << 13) | (29 << 8) | (15 << 3), 1},
-	{0x06, 10, 0, (1 << 13) | (29 << 8) | (15 << 3), 0},
-	{0},
-};
-
-static void dib0090_set_trim(struct dib0090_state *state)
-{
-	u16 *val;
-
-	if (state->dc->addr == 0x07)
-		val = &state->bb7;
-	else
-		val = &state->bb6;
-
-	*val &= ~(0x1f << state->dc->offset);
-	*val |= state->step << state->dc->offset;
-
-	dib0090_write_reg(state, state->dc->addr, *val);
-}
-
-static int dib0090_dc_offset_calibration(struct dib0090_state *state, enum frontend_tune_state *tune_state)
-{
-	int ret = 0;
-	u16 reg;
-
-	switch (*tune_state) {
-	case CT_TUNER_START:
-		dprintk("Start DC offset calibration");
-
-		/* force vcm2 = 0.8V */
-		state->bb6 = 0;
-		state->bb7 = 0x040d;
-
-		/* the LNA AND LO are off */
-		reg = dib0090_read_reg(state, 0x24) & 0x0ffb;	/* shutdown lna and lo */
-		dib0090_write_reg(state, 0x24, reg);
-
-		state->wbdmux = dib0090_read_reg(state, 0x10);
-		dib0090_write_reg(state, 0x10, (state->wbdmux & ~(0xff << 3)) | (0x7 << 3) | 0x3);
-		dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) & ~(1 << 14));
-
-		state->dc = dc_table;
-
-		if (state->identity.p1g)
-			state->dc = dc_p1g_table;
-		*tune_state = CT_TUNER_STEP_0;
-
-		/* fall through */
-
-	case CT_TUNER_STEP_0:
-		dprintk("Sart/continue DC calibration for %s path", (state->dc->i == 1) ? "I" : "Q");
-		dib0090_write_reg(state, 0x01, state->dc->bb1);
-		dib0090_write_reg(state, 0x07, state->bb7 | (state->dc->i << 7));
-
-		state->step = 0;
-		state->min_adc_diff = 1023;
-		*tune_state = CT_TUNER_STEP_1;
-		ret = 50;
-		break;
-
-	case CT_TUNER_STEP_1:
-		dib0090_set_trim(state);
-		*tune_state = CT_TUNER_STEP_2;
-		break;
-
-	case CT_TUNER_STEP_2:
-	case CT_TUNER_STEP_3:
-	case CT_TUNER_STEP_4:
-		ret = dib0090_get_offset(state, tune_state);
-		break;
-
-	case CT_TUNER_STEP_5:	/* found an offset */
-		dprintk("adc_diff = %d, current step= %d", (u32) state->adc_diff, state->step);
-		if (state->step == 0 && state->adc_diff < 0) {
-			state->min_adc_diff = -1023;
-			dprintk("Change of sign of the minimum adc diff");
-		}
-
-		dprintk("adc_diff = %d, min_adc_diff = %d current_step = %d", state->adc_diff, state->min_adc_diff, state->step);
-
-		/* first turn for this frequency */
-		if (state->step == 0) {
-			if (state->dc->pga && state->adc_diff < 0)
-				state->step = 0x10;
-			if (state->dc->pga == 0 && state->adc_diff > 0)
-				state->step = 0x10;
-		}
-
-		/* Look for a change of Sign in the Adc_diff.min_adc_diff is used to STORE the setp N-1 */
-		if ((state->adc_diff & 0x8000) == (state->min_adc_diff & 0x8000) && steps(state->step) < 15) {
-			/* stop search when the delta the sign is changing and Steps =15 and Step=0 is force for continuance */
-			state->step++;
-			state->min_adc_diff = state->adc_diff;
-			*tune_state = CT_TUNER_STEP_1;
-		} else {
-			/* the minimum was what we have seen in the step before */
-			if (ABS(state->adc_diff) > ABS(state->min_adc_diff)) {
-				dprintk("Since adc_diff N = %d  > adc_diff step N-1 = %d, Come back one step", state->adc_diff, state->min_adc_diff);
-				state->step--;
-			}
-
-			dib0090_set_trim(state);
-			dprintk("BB Offset Cal, BBreg=%hd,Offset=%hd,Value Set=%hd", state->dc->addr, state->adc_diff, state->step);
-
-			state->dc++;
-			if (state->dc->addr == 0)	/* done */
-				*tune_state = CT_TUNER_STEP_6;
-			else
-				*tune_state = CT_TUNER_STEP_0;
-
-		}
-		break;
-
-	case CT_TUNER_STEP_6:
-		dib0090_write_reg(state, 0x07, state->bb7 & ~0x0008);
-		dib0090_write_reg(state, 0x1f, 0x7);
-		*tune_state = CT_TUNER_START;	/* reset done -> real tuning can now begin */
-		state->calibrate &= ~DC_CAL;
-	default:
-		break;
-	}
-	return ret;
-}
-
-static int dib0090_wbd_calibration(struct dib0090_state *state, enum frontend_tune_state *tune_state)
-{
-	u8 wbd_gain;
-	const struct dib0090_wbd_slope *wbd = state->current_wbd_table;
-
-	switch (*tune_state) {
-	case CT_TUNER_START:
-		while (state->current_rf / 1000 > wbd->max_freq)
-			wbd++;
-		if (wbd->wbd_gain != 0)
-			wbd_gain = wbd->wbd_gain;
-		else {
-			wbd_gain = 4;
-#if defined(CONFIG_BAND_LBAND) || defined(CONFIG_BAND_SBAND)
-			if ((state->current_band == BAND_LBAND) || (state->current_band == BAND_SBAND))
-				wbd_gain = 2;
-#endif
-		}
-
-		if (wbd_gain == state->wbd_calibration_gain) {	/* the WBD calibration has already been done */
-			*tune_state = CT_TUNER_START;
-			state->calibrate &= ~WBD_CAL;
-			return 0;
-		}
-
-		dib0090_write_reg(state, 0x10, 0x1b81 | (1 << 10) | (wbd_gain << 13) | (1 << 3));
-
-		dib0090_write_reg(state, 0x24, ((EN_UHF & 0x0fff) | (1 << 1)));
-		*tune_state = CT_TUNER_STEP_0;
-		state->wbd_calibration_gain = wbd_gain;
-		return 90;	/* wait for the WBDMUX to switch and for the ADC to sample */
-
-	case CT_TUNER_STEP_0:
-		state->wbd_offset = dib0090_get_slow_adc_val(state);
-		dprintk("WBD calibration offset = %d", state->wbd_offset);
-		*tune_state = CT_TUNER_START;	/* reset done -> real tuning can now begin */
-		state->calibrate &= ~WBD_CAL;
-		break;
-
-	default:
-		break;
-	}
-	return 0;
-}
-
-static void dib0090_set_bandwidth(struct dib0090_state *state)
-{
-	u16 tmp;
-
-	if (state->fe->dtv_property_cache.bandwidth_hz / 1000 <= 5000)
-		tmp = (3 << 14);
-	else if (state->fe->dtv_property_cache.bandwidth_hz / 1000 <= 6000)
-		tmp = (2 << 14);
-	else if (state->fe->dtv_property_cache.bandwidth_hz / 1000 <= 7000)
-		tmp = (1 << 14);
-	else
-		tmp = (0 << 14);
-
-	state->bb_1_def &= 0x3fff;
-	state->bb_1_def |= tmp;
-
-	dib0090_write_reg(state, 0x01, state->bb_1_def);	/* be sure that we have the right bb-filter */
-
-	dib0090_write_reg(state, 0x03, 0x6008);	/* = 0x6008 : vcm3_trim = 1 ; filter2_gm1_trim = 8 ; filter2_cutoff_freq = 0 */
-	dib0090_write_reg(state, 0x04, 0x1);	/* 0 = 1KHz ; 1 = 50Hz ; 2 = 150Hz ; 3 = 50KHz ; 4 = servo fast */
-	if (state->identity.in_soc) {
-		dib0090_write_reg(state, 0x05, 0x9bcf); /* attenuator_ibias_tri = 2 ; input_stage_ibias_tr = 1 ; nc = 11 ; ext_gm_trim = 1 ; obuf_ibias_trim = 4 ; filter13_gm2_ibias_t = 15 */
-	} else {
-		dib0090_write_reg(state, 0x02, (5 << 11) | (8 << 6) | (22 & 0x3f));	/* 22 = cap_value */
-		dib0090_write_reg(state, 0x05, 0xabcd);	/* = 0xabcd : attenuator_ibias_tri = 2 ; input_stage_ibias_tr = 2 ; nc = 11 ; ext_gm_trim = 1 ; obuf_ibias_trim = 4 ; filter13_gm2_ibias_t = 13 */
-	}
-}
-
-static const struct dib0090_pll dib0090_pll_table[] = {
-#ifdef CONFIG_BAND_CBAND
-	{56000, 0, 9, 48, 6},
-	{70000, 1, 9, 48, 6},
-	{87000, 0, 8, 32, 4},
-	{105000, 1, 8, 32, 4},
-	{115000, 0, 7, 24, 6},
-	{140000, 1, 7, 24, 6},
-	{170000, 0, 6, 16, 4},
-#endif
-#ifdef CONFIG_BAND_VHF
-	{200000, 1, 6, 16, 4},
-	{230000, 0, 5, 12, 6},
-	{280000, 1, 5, 12, 6},
-	{340000, 0, 4, 8, 4},
-	{380000, 1, 4, 8, 4},
-	{450000, 0, 3, 6, 6},
-#endif
-#ifdef CONFIG_BAND_UHF
-	{580000, 1, 3, 6, 6},
-	{700000, 0, 2, 4, 4},
-	{860000, 1, 2, 4, 4},
-#endif
-#ifdef CONFIG_BAND_LBAND
-	{1800000, 1, 0, 2, 4},
-#endif
-#ifdef CONFIG_BAND_SBAND
-	{2900000, 0, 14, 1, 4},
-#endif
-};
-
-static const struct dib0090_tuning dib0090_tuning_table_fm_vhf_on_cband[] = {
-
-#ifdef CONFIG_BAND_CBAND
-	{184000, 4, 1, 15, 0x280, 0x2912, 0xb94e, EN_CAB},
-	{227000, 4, 3, 15, 0x280, 0x2912, 0xb94e, EN_CAB},
-	{380000, 4, 7, 15, 0x280, 0x2912, 0xb94e, EN_CAB},
-#endif
-#ifdef CONFIG_BAND_UHF
-	{520000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
-	{550000, 2, 2, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
-	{650000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
-	{750000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
-	{850000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
-	{900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
-#endif
-#ifdef CONFIG_BAND_LBAND
-	{1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
-	{1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
-	{1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
-#endif
-#ifdef CONFIG_BAND_SBAND
-	{2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD},
-	{2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD},
-#endif
-};
-
-static const struct dib0090_tuning dib0090_tuning_table[] = {
-
-#ifdef CONFIG_BAND_CBAND
-	{170000, 4, 1, 15, 0x280, 0x2912, 0xb94e, EN_CAB},
-#endif
-#ifdef CONFIG_BAND_VHF
-	{184000, 1, 1, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
-	{227000, 1, 3, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
-	{380000, 1, 7, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
-#endif
-#ifdef CONFIG_BAND_UHF
-	{520000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
-	{550000, 2, 2, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
-	{650000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
-	{750000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
-	{850000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
-	{900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
-#endif
-#ifdef CONFIG_BAND_LBAND
-	{1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
-	{1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
-	{1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
-#endif
-#ifdef CONFIG_BAND_SBAND
-	{2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD},
-	{2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD},
-#endif
-};
-
-static const struct dib0090_tuning dib0090_p1g_tuning_table[] = {
-#ifdef CONFIG_BAND_CBAND
-	{170000, 4, 1, 0x820f, 0x300, 0x2d22, 0x82cb, EN_CAB},
-#endif
-#ifdef CONFIG_BAND_VHF
-	{184000, 1, 1, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
-	{227000, 1, 3, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
-	{380000, 1, 7, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
-#endif
-#ifdef CONFIG_BAND_UHF
-	{510000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
-	{540000, 2, 1, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
-	{600000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
-	{630000, 2, 4, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
-	{680000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
-	{720000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
-	{900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
-#endif
-#ifdef CONFIG_BAND_LBAND
-	{1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
-	{1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
-	{1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
-#endif
-#ifdef CONFIG_BAND_SBAND
-	{2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD},
-	{2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD},
-#endif
-};
-
-static const struct dib0090_pll dib0090_p1g_pll_table[] = {
-#ifdef CONFIG_BAND_CBAND
-	{57000, 0, 11, 48, 6},
-	{70000, 1, 11, 48, 6},
-	{86000, 0, 10, 32, 4},
-	{105000, 1, 10, 32, 4},
-	{115000, 0, 9, 24, 6},
-	{140000, 1, 9, 24, 6},
-	{170000, 0, 8, 16, 4},
-#endif
-#ifdef CONFIG_BAND_VHF
-	{200000, 1, 8, 16, 4},
-	{230000, 0, 7, 12, 6},
-	{280000, 1, 7, 12, 6},
-	{340000, 0, 6, 8, 4},
-	{380000, 1, 6, 8, 4},
-	{455000, 0, 5, 6, 6},
-#endif
-#ifdef CONFIG_BAND_UHF
-	{580000, 1, 5, 6, 6},
-	{680000, 0, 4, 4, 4},
-	{860000, 1, 4, 4, 4},
-#endif
-#ifdef CONFIG_BAND_LBAND
-	{1800000, 1, 2, 2, 4},
-#endif
-#ifdef CONFIG_BAND_SBAND
-	{2900000, 0, 1, 1, 6},
-#endif
-};
-
-static const struct dib0090_tuning dib0090_p1g_tuning_table_fm_vhf_on_cband[] = {
-#ifdef CONFIG_BAND_CBAND
-	{184000, 4, 3, 0x4187, 0x2c0, 0x2d22, 0x81cb, EN_CAB},
-	{227000, 4, 3, 0x4187, 0x2c0, 0x2d22, 0x81cb, EN_CAB},
-	{380000, 4, 3, 0x4187, 0x2c0, 0x2d22, 0x81cb, EN_CAB},
-#endif
-#ifdef CONFIG_BAND_UHF
-	{520000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
-	{550000, 2, 2, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
-	{650000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
-	{750000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
-	{850000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
-	{900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
-#endif
-#ifdef CONFIG_BAND_LBAND
-	{1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
-	{1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
-	{1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
-#endif
-#ifdef CONFIG_BAND_SBAND
-	{2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD},
-	{2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD},
-#endif
-};
-
-static const struct dib0090_tuning dib0090_tuning_table_cband_7090[] = {
-#ifdef CONFIG_BAND_CBAND
-	{300000, 4, 3, 0x018F, 0x2c0, 0x2d22, 0xb9ce, EN_CAB},
-	{380000, 4, 10, 0x018F, 0x2c0, 0x2d22, 0xb9ce, EN_CAB},
-	{570000, 4, 10, 0x8190, 0x2c0, 0x2d22, 0xb9ce, EN_CAB},
-	{858000, 4, 5, 0x8190, 0x2c0, 0x2d22, 0xb9ce, EN_CAB},
-#endif
-};
-
-static const struct dib0090_tuning dib0090_tuning_table_cband_7090e_sensitivity[] = {
-#ifdef CONFIG_BAND_CBAND
-	{ 300000,  0 ,  3,  0x8105, 0x2c0, 0x2d12, 0xb84e, EN_CAB },
-	{ 380000,  0 ,  10, 0x810F, 0x2c0, 0x2d12, 0xb84e, EN_CAB },
-	{ 600000,  0 ,  10, 0x815E, 0x280, 0x2d12, 0xb84e, EN_CAB },
-	{ 660000,  0 ,  5,  0x85E3, 0x280, 0x2d12, 0xb84e, EN_CAB },
-	{ 720000,  0 ,  5,  0x852E, 0x280, 0x2d12, 0xb84e, EN_CAB },
-	{ 860000,  0 ,  4,  0x85E5, 0x280, 0x2d12, 0xb84e, EN_CAB },
-#endif
-};
-
-int dib0090_update_tuning_table_7090(struct dvb_frontend *fe,
-		u8 cfg_sensitivity)
-{
-	struct dib0090_state *state = fe->tuner_priv;
-	const struct dib0090_tuning *tune =
-		dib0090_tuning_table_cband_7090e_sensitivity;
-	const struct dib0090_tuning dib0090_tuning_table_cband_7090e_aci[] = {
-		{ 300000,  0 ,  3,  0x8165, 0x2c0, 0x2d12, 0xb84e, EN_CAB },
-		{ 650000,  0 ,  4,  0x815B, 0x280, 0x2d12, 0xb84e, EN_CAB },
-		{ 860000,  0 ,  5,  0x84EF, 0x280, 0x2d12, 0xb84e, EN_CAB },
-	};
-
-	if ((!state->identity.p1g) || (!state->identity.in_soc)
-			|| ((state->identity.version != SOC_7090_P1G_21R1)
-				&& (state->identity.version != SOC_7090_P1G_11R1))) {
-		dprintk("%s() function can only be used for dib7090", __func__);
-		return -ENODEV;
-	}
-
-	if (cfg_sensitivity)
-		tune = dib0090_tuning_table_cband_7090e_sensitivity;
-	else
-		tune = dib0090_tuning_table_cband_7090e_aci;
-
-	while (state->rf_request > tune->max_freq)
-		tune++;
-
-	dib0090_write_reg(state, 0x09, (dib0090_read_reg(state, 0x09) & 0x8000)
-			| (tune->lna_bias & 0x7fff));
-	dib0090_write_reg(state, 0x0b, (dib0090_read_reg(state, 0x0b) & 0xf83f)
-			| ((tune->lna_tune << 6) & 0x07c0));
-	return 0;
-}
-EXPORT_SYMBOL(dib0090_update_tuning_table_7090);
-
-static int dib0090_captrim_search(struct dib0090_state *state, enum frontend_tune_state *tune_state)
-{
-	int ret = 0;
-	u16 lo4 = 0xe900;
-
-	s16 adc_target;
-	u16 adc;
-	s8 step_sign;
-	u8 force_soft_search = 0;
-
-	if (state->identity.version == SOC_8090_P1G_11R1 || state->identity.version == SOC_8090_P1G_21R1)
-		force_soft_search = 1;
-
-	if (*tune_state == CT_TUNER_START) {
-		dprintk("Start Captrim search : %s", (force_soft_search == 1) ? "FORCE SOFT SEARCH" : "AUTO");
-		dib0090_write_reg(state, 0x10, 0x2B1);
-		dib0090_write_reg(state, 0x1e, 0x0032);
-
-		if (!state->tuner_is_tuned) {
-			/* prepare a complete captrim */
-			if (!state->identity.p1g || force_soft_search)
-				state->step = state->captrim = state->fcaptrim = 64;
-
-			state->current_rf = state->rf_request;
-		} else {	/* we are already tuned to this frequency - the configuration is correct  */
-			if (!state->identity.p1g || force_soft_search) {
-				/* do a minimal captrim even if the frequency has not changed */
-				state->step = 4;
-				state->captrim = state->fcaptrim = dib0090_read_reg(state, 0x18) & 0x7f;
-			}
-		}
-		state->adc_diff = 3000;
-		*tune_state = CT_TUNER_STEP_0;
-
-	} else if (*tune_state == CT_TUNER_STEP_0) {
-		if (state->identity.p1g && !force_soft_search) {
-			u8 ratio = 31;
-
-			dib0090_write_reg(state, 0x40, (3 << 7) | (ratio << 2) | (1 << 1) | 1);
-			dib0090_read_reg(state, 0x40);
-			ret = 50;
-		} else {
-			state->step /= 2;
-			dib0090_write_reg(state, 0x18, lo4 | state->captrim);
-
-			if (state->identity.in_soc)
-				ret = 25;
-		}
-		*tune_state = CT_TUNER_STEP_1;
-
-	} else if (*tune_state == CT_TUNER_STEP_1) {
-		if (state->identity.p1g && !force_soft_search) {
-			dib0090_write_reg(state, 0x40, 0x18c | (0 << 1) | 0);
-			dib0090_read_reg(state, 0x40);
-
-			state->fcaptrim = dib0090_read_reg(state, 0x18) & 0x7F;
-			dprintk("***Final Captrim= 0x%x", state->fcaptrim);
-			*tune_state = CT_TUNER_STEP_3;
-
-		} else {
-			/* MERGE for all krosus before P1G */
-			adc = dib0090_get_slow_adc_val(state);
-			dprintk("CAPTRIM=%d; ADC = %d (ADC) & %dmV", (u32) state->captrim, (u32) adc, (u32) (adc) * (u32) 1800 / (u32) 1024);
-
-			if (state->rest == 0 || state->identity.in_soc) {	/* Just for 8090P SOCS where auto captrim HW bug : TO CHECK IN ACI for SOCS !!! if 400 for 8090p SOC => tune issue !!! */
-				adc_target = 200;
-			} else
-				adc_target = 400;
-
-			if (adc >= adc_target) {
-				adc -= adc_target;
-				step_sign = -1;
-			} else {
-				adc = adc_target - adc;
-				step_sign = 1;
-			}
-
-			if (adc < state->adc_diff) {
-				dprintk("CAPTRIM=%d is closer to target (%d/%d)", (u32) state->captrim, (u32) adc, (u32) state->adc_diff);
-				state->adc_diff = adc;
-				state->fcaptrim = state->captrim;
-			}
-
-			state->captrim += step_sign * state->step;
-			if (state->step >= 1)
-				*tune_state = CT_TUNER_STEP_0;
-			else
-				*tune_state = CT_TUNER_STEP_2;
-
-			ret = 25;
-		}
-	} else if (*tune_state == CT_TUNER_STEP_2) {	/* this step is only used by krosus < P1G */
-		/*write the final cptrim config */
-		dib0090_write_reg(state, 0x18, lo4 | state->fcaptrim);
-
-		*tune_state = CT_TUNER_STEP_3;
-
-	} else if (*tune_state == CT_TUNER_STEP_3) {
-		state->calibrate &= ~CAPTRIM_CAL;
-		*tune_state = CT_TUNER_STEP_0;
-	}
-
-	return ret;
-}
-
-static int dib0090_get_temperature(struct dib0090_state *state, enum frontend_tune_state *tune_state)
-{
-	int ret = 15;
-	s16 val;
-
-	switch (*tune_state) {
-	case CT_TUNER_START:
-		state->wbdmux = dib0090_read_reg(state, 0x10);
-		dib0090_write_reg(state, 0x10, (state->wbdmux & ~(0xff << 3)) | (0x8 << 3));
-
-		state->bias = dib0090_read_reg(state, 0x13);
-		dib0090_write_reg(state, 0x13, state->bias | (0x3 << 8));
-
-		*tune_state = CT_TUNER_STEP_0;
-		/* wait for the WBDMUX to switch and for the ADC to sample */
-		break;
-
-	case CT_TUNER_STEP_0:
-		state->adc_diff = dib0090_get_slow_adc_val(state);
-		dib0090_write_reg(state, 0x13, (state->bias & ~(0x3 << 8)) | (0x2 << 8));
-		*tune_state = CT_TUNER_STEP_1;
-		break;
-
-	case CT_TUNER_STEP_1:
-		val = dib0090_get_slow_adc_val(state);
-		state->temperature = ((s16) ((val - state->adc_diff) * 180) >> 8) + 55;
-
-		dprintk("temperature: %d C", state->temperature - 30);
-
-		*tune_state = CT_TUNER_STEP_2;
-		break;
-
-	case CT_TUNER_STEP_2:
-		dib0090_write_reg(state, 0x13, state->bias);
-		dib0090_write_reg(state, 0x10, state->wbdmux);	/* write back original WBDMUX */
-
-		*tune_state = CT_TUNER_START;
-		state->calibrate &= ~TEMP_CAL;
-		if (state->config->analog_output == 0)
-			dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) | (1 << 14));
-
-		break;
-
-	default:
-		ret = 0;
-		break;
-	}
-	return ret;
-}
-
-#define WBD     0x781		/* 1 1 1 1 0000 0 0 1 */
-static int dib0090_tune(struct dvb_frontend *fe)
-{
-	struct dib0090_state *state = fe->tuner_priv;
-	const struct dib0090_tuning *tune = state->current_tune_table_index;
-	const struct dib0090_pll *pll = state->current_pll_table_index;
-	enum frontend_tune_state *tune_state = &state->tune_state;
-
-	u16 lo5, lo6, Den, tmp;
-	u32 FBDiv, Rest, FREF, VCOF_kHz = 0;
-	int ret = 10;		/* 1ms is the default delay most of the time */
-	u8 c, i;
-
-	/************************* VCO ***************************/
-	/* Default values for FG                                 */
-	/* from these are needed :                               */
-	/* Cp,HFdiv,VCOband,SD,Num,Den,FB and REFDiv             */
-
-	/* in any case we first need to do a calibration if needed */
-	if (*tune_state == CT_TUNER_START) {
-		/* deactivate DataTX before some calibrations */
-		if (state->calibrate & (DC_CAL | TEMP_CAL | WBD_CAL))
-			dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) & ~(1 << 14));
-		else
-			/* Activate DataTX in case a calibration has been done before */
-			if (state->config->analog_output == 0)
-				dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) | (1 << 14));
-	}
-
-	if (state->calibrate & DC_CAL)
-		return dib0090_dc_offset_calibration(state, tune_state);
-	else if (state->calibrate & WBD_CAL) {
-		if (state->current_rf == 0)
-			state->current_rf = state->fe->dtv_property_cache.frequency / 1000;
-		return dib0090_wbd_calibration(state, tune_state);
-	} else if (state->calibrate & TEMP_CAL)
-		return dib0090_get_temperature(state, tune_state);
-	else if (state->calibrate & CAPTRIM_CAL)
-		return dib0090_captrim_search(state, tune_state);
-
-	if (*tune_state == CT_TUNER_START) {
-		/* if soc and AGC pwm control, disengage mux to be able to R/W access to 0x01 register to set the right filter (cutoff_freq_select) during the tune sequence, otherwise, SOC SERPAR error when accessing to 0x01 */
-		if (state->config->use_pwm_agc && state->identity.in_soc) {
-			tmp = dib0090_read_reg(state, 0x39);
-			if ((tmp >> 10) & 0x1)
-				dib0090_write_reg(state, 0x39, tmp & ~(1 << 10));
-		}
-
-		state->current_band = (u8) BAND_OF_FREQUENCY(state->fe->dtv_property_cache.frequency / 1000);
-		state->rf_request =
-			state->fe->dtv_property_cache.frequency / 1000 + (state->current_band ==
-					BAND_UHF ? state->config->freq_offset_khz_uhf : state->config->
-					freq_offset_khz_vhf);
-
-		/* in ISDB-T 1seg we shift tuning frequency */
-		if ((state->fe->dtv_property_cache.delivery_system == SYS_ISDBT && state->fe->dtv_property_cache.isdbt_sb_mode == 1
-					&& state->fe->dtv_property_cache.isdbt_partial_reception == 0)) {
-			const struct dib0090_low_if_offset_table *LUT_offset = state->config->low_if;
-			u8 found_offset = 0;
-			u32 margin_khz = 100;
-
-			if (LUT_offset != NULL) {
-				while (LUT_offset->RF_freq != 0xffff) {
-					if (((state->rf_request > (LUT_offset->RF_freq - margin_khz))
-								&& (state->rf_request < (LUT_offset->RF_freq + margin_khz)))
-							&& LUT_offset->std == state->fe->dtv_property_cache.delivery_system) {
-						state->rf_request += LUT_offset->offset_khz;
-						found_offset = 1;
-						break;
-					}
-					LUT_offset++;
-				}
-			}
-
-			if (found_offset == 0)
-				state->rf_request += 400;
-		}
-		if (state->current_rf != state->rf_request || (state->current_standard != state->fe->dtv_property_cache.delivery_system)) {
-			state->tuner_is_tuned = 0;
-			state->current_rf = 0;
-			state->current_standard = 0;
-
-			tune = dib0090_tuning_table;
-			if (state->identity.p1g)
-				tune = dib0090_p1g_tuning_table;
-
-			tmp = (state->identity.version >> 5) & 0x7;
-
-			if (state->identity.in_soc) {
-				if (state->config->force_cband_input) {	/* Use the CBAND input for all band */
-					if (state->current_band & BAND_CBAND || state->current_band & BAND_FM || state->current_band & BAND_VHF
-							|| state->current_band & BAND_UHF) {
-						state->current_band = BAND_CBAND;
-						if (state->config->is_dib7090e)
-							tune = dib0090_tuning_table_cband_7090e_sensitivity;
-						else
-							tune = dib0090_tuning_table_cband_7090;
-					}
-				} else {	/* Use the CBAND input for all band under UHF */
-					if (state->current_band & BAND_CBAND || state->current_band & BAND_FM || state->current_band & BAND_VHF) {
-						state->current_band = BAND_CBAND;
-						if (state->config->is_dib7090e)
-							tune = dib0090_tuning_table_cband_7090e_sensitivity;
-						else
-							tune = dib0090_tuning_table_cband_7090;
-					}
-				}
-			} else
-			 if (tmp == 0x4 || tmp == 0x7) {
-				/* CBAND tuner version for VHF */
-				if (state->current_band == BAND_FM || state->current_band == BAND_CBAND || state->current_band == BAND_VHF) {
-					state->current_band = BAND_CBAND;	/* Force CBAND */
-
-					tune = dib0090_tuning_table_fm_vhf_on_cband;
-					if (state->identity.p1g)
-						tune = dib0090_p1g_tuning_table_fm_vhf_on_cband;
-				}
-			}
-
-			pll = dib0090_pll_table;
-			if (state->identity.p1g)
-				pll = dib0090_p1g_pll_table;
-
-			/* Look for the interval */
-			while (state->rf_request > tune->max_freq)
-				tune++;
-			while (state->rf_request > pll->max_freq)
-				pll++;
-
-			state->current_tune_table_index = tune;
-			state->current_pll_table_index = pll;
-
-			dib0090_write_reg(state, 0x0b, 0xb800 | (tune->switch_trim));
-
-			VCOF_kHz = (pll->hfdiv * state->rf_request) * 2;
-
-			FREF = state->config->io.clock_khz;
-			if (state->config->fref_clock_ratio != 0)
-				FREF /= state->config->fref_clock_ratio;
-
-			FBDiv = (VCOF_kHz / pll->topresc / FREF);
-			Rest = (VCOF_kHz / pll->topresc) - FBDiv * FREF;
-
-			if (Rest < LPF)
-				Rest = 0;
-			else if (Rest < 2 * LPF)
-				Rest = 2 * LPF;
-			else if (Rest > (FREF - LPF)) {
-				Rest = 0;
-				FBDiv += 1;
-			} else if (Rest > (FREF - 2 * LPF))
-				Rest = FREF - 2 * LPF;
-			Rest = (Rest * 6528) / (FREF / 10);
-			state->rest = Rest;
-
-			/* external loop filter, otherwise:
-			 * lo5 = (0 << 15) | (0 << 12) | (0 << 11) | (3 << 9) | (4 << 6) | (3 << 4) | 4;
-			 * lo6 = 0x0e34 */
-
-			if (Rest == 0) {
-				if (pll->vco_band)
-					lo5 = 0x049f;
-				else
-					lo5 = 0x041f;
-			} else {
-				if (pll->vco_band)
-					lo5 = 0x049e;
-				else if (state->config->analog_output)
-					lo5 = 0x041d;
-				else
-					lo5 = 0x041c;
-			}
-
-			if (state->identity.p1g) {	/* Bias is done automatically in P1G */
-				if (state->identity.in_soc) {
-					if (state->identity.version == SOC_8090_P1G_11R1)
-						lo5 = 0x46f;
-					else
-						lo5 = 0x42f;
-				} else
-					lo5 = 0x42c;
-			}
-
-			lo5 |= (pll->hfdiv_code << 11) | (pll->vco_band << 7);	/* bit 15 is the split to the slave, we do not do it here */
-
-			if (!state->config->io.pll_int_loop_filt) {
-				if (state->identity.in_soc)
-					lo6 = 0xff98;
-				else if (state->identity.p1g || (Rest == 0))
-					lo6 = 0xfff8;
-				else
-					lo6 = 0xff28;
-			} else
-				lo6 = (state->config->io.pll_int_loop_filt << 3);
-
-			Den = 1;
-
-			if (Rest > 0) {
-				if (state->config->analog_output)
-					lo6 |= (1 << 2) | 2;
-				else {
-					if (state->identity.in_soc)
-						lo6 |= (1 << 2) | 2;
-					else
-						lo6 |= (1 << 2) | 2;
-				}
-				Den = 255;
-			}
-			dib0090_write_reg(state, 0x15, (u16) FBDiv);
-			if (state->config->fref_clock_ratio != 0)
-				dib0090_write_reg(state, 0x16, (Den << 8) | state->config->fref_clock_ratio);
-			else
-				dib0090_write_reg(state, 0x16, (Den << 8) | 1);
-			dib0090_write_reg(state, 0x17, (u16) Rest);
-			dib0090_write_reg(state, 0x19, lo5);
-			dib0090_write_reg(state, 0x1c, lo6);
-
-			lo6 = tune->tuner_enable;
-			if (state->config->analog_output)
-				lo6 = (lo6 & 0xff9f) | 0x2;
-
-			dib0090_write_reg(state, 0x24, lo6 | EN_LO | state->config->use_pwm_agc * EN_CRYSTAL);
-
-		}
-
-		state->current_rf = state->rf_request;
-		state->current_standard = state->fe->dtv_property_cache.delivery_system;
-
-		ret = 20;
-		state->calibrate = CAPTRIM_CAL;	/* captrim serach now */
-	}
-
-	else if (*tune_state == CT_TUNER_STEP_0) {	/* Warning : because of captrim cal, if you change this step, change it also in _cal.c file because it is the step following captrim cal state machine */
-		const struct dib0090_wbd_slope *wbd = state->current_wbd_table;
-
-		while (state->current_rf / 1000 > wbd->max_freq)
-			wbd++;
-
-		dib0090_write_reg(state, 0x1e, 0x07ff);
-		dprintk("Final Captrim: %d", (u32) state->fcaptrim);
-		dprintk("HFDIV code: %d", (u32) pll->hfdiv_code);
-		dprintk("VCO = %d", (u32) pll->vco_band);
-		dprintk("VCOF in kHz: %d ((%d*%d) << 1))", (u32) ((pll->hfdiv * state->rf_request) * 2), (u32) pll->hfdiv, (u32) state->rf_request);
-		dprintk("REFDIV: %d, FREF: %d", (u32) 1, (u32) state->config->io.clock_khz);
-		dprintk("FBDIV: %d, Rest: %d", (u32) dib0090_read_reg(state, 0x15), (u32) dib0090_read_reg(state, 0x17));
-		dprintk("Num: %d, Den: %d, SD: %d", (u32) dib0090_read_reg(state, 0x17), (u32) (dib0090_read_reg(state, 0x16) >> 8),
-			(u32) dib0090_read_reg(state, 0x1c) & 0x3);
-
-#define WBD     0x781		/* 1 1 1 1 0000 0 0 1 */
-		c = 4;
-		i = 3;
-
-		if (wbd->wbd_gain != 0)
-			c = wbd->wbd_gain;
-
-		state->wbdmux = (c << 13) | (i << 11) | (WBD | (state->config->use_pwm_agc << 1));
-		dib0090_write_reg(state, 0x10, state->wbdmux);
-
-		if ((tune->tuner_enable == EN_CAB) && state->identity.p1g) {
-			dprintk("P1G : The cable band is selected and lna_tune = %d", tune->lna_tune);
-			dib0090_write_reg(state, 0x09, tune->lna_bias);
-			dib0090_write_reg(state, 0x0b, 0xb800 | (tune->lna_tune << 6) | (tune->switch_trim));
-		} else
-			dib0090_write_reg(state, 0x09, (tune->lna_tune << 5) | tune->lna_bias);
-
-		dib0090_write_reg(state, 0x0c, tune->v2i);
-		dib0090_write_reg(state, 0x0d, tune->mix);
-		dib0090_write_reg(state, 0x0e, tune->load);
-		*tune_state = CT_TUNER_STEP_1;
-
-	} else if (*tune_state == CT_TUNER_STEP_1) {
-		/* initialize the lt gain register */
-		state->rf_lt_def = 0x7c00;
-
-		dib0090_set_bandwidth(state);
-		state->tuner_is_tuned = 1;
-
-		state->calibrate |= WBD_CAL;
-		state->calibrate |= TEMP_CAL;
-		*tune_state = CT_TUNER_STOP;
-	} else
-		ret = FE_CALLBACK_TIME_NEVER;
-	return ret;
-}
-
-static int dib0090_release(struct dvb_frontend *fe)
-{
-	kfree(fe->tuner_priv);
-	fe->tuner_priv = NULL;
-	return 0;
-}
-
-enum frontend_tune_state dib0090_get_tune_state(struct dvb_frontend *fe)
-{
-	struct dib0090_state *state = fe->tuner_priv;
-
-	return state->tune_state;
-}
-
-EXPORT_SYMBOL(dib0090_get_tune_state);
-
-int dib0090_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state)
-{
-	struct dib0090_state *state = fe->tuner_priv;
-
-	state->tune_state = tune_state;
-	return 0;
-}
-
-EXPORT_SYMBOL(dib0090_set_tune_state);
-
-static int dib0090_get_frequency(struct dvb_frontend *fe, u32 * frequency)
-{
-	struct dib0090_state *state = fe->tuner_priv;
-
-	*frequency = 1000 * state->current_rf;
-	return 0;
-}
-
-static int dib0090_set_params(struct dvb_frontend *fe)
-{
-	struct dib0090_state *state = fe->tuner_priv;
-	u32 ret;
-
-	state->tune_state = CT_TUNER_START;
-
-	do {
-		ret = dib0090_tune(fe);
-		if (ret != FE_CALLBACK_TIME_NEVER)
-			msleep(ret / 10);
-		else
-			break;
-	} while (state->tune_state != CT_TUNER_STOP);
-
-	return 0;
-}
-
-static const struct dvb_tuner_ops dib0090_ops = {
-	.info = {
-		 .name = "DiBcom DiB0090",
-		 .frequency_min = 45000000,
-		 .frequency_max = 860000000,
-		 .frequency_step = 1000,
-		 },
-	.release = dib0090_release,
-
-	.init = dib0090_wakeup,
-	.sleep = dib0090_sleep,
-	.set_params = dib0090_set_params,
-	.get_frequency = dib0090_get_frequency,
-};
-
-static const struct dvb_tuner_ops dib0090_fw_ops = {
-	.info = {
-		 .name = "DiBcom DiB0090",
-		 .frequency_min = 45000000,
-		 .frequency_max = 860000000,
-		 .frequency_step = 1000,
-		 },
-	.release = dib0090_release,
-
-	.init = NULL,
-	.sleep = NULL,
-	.set_params = NULL,
-	.get_frequency = NULL,
-};
-
-static const struct dib0090_wbd_slope dib0090_wbd_table_default[] = {
-	{470, 0, 250, 0, 100, 4},
-	{860, 51, 866, 21, 375, 4},
-	{1700, 0, 800, 0, 850, 4},
-	{2900, 0, 250, 0, 100, 6},
-	{0xFFFF, 0, 0, 0, 0, 0},
-};
-
-struct dvb_frontend *dib0090_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config)
-{
-	struct dib0090_state *st = kzalloc(sizeof(struct dib0090_state), GFP_KERNEL);
-	if (st == NULL)
-		return NULL;
-
-	st->config = config;
-	st->i2c = i2c;
-	st->fe = fe;
-	mutex_init(&st->i2c_buffer_lock);
-	fe->tuner_priv = st;
-
-	if (config->wbd == NULL)
-		st->current_wbd_table = dib0090_wbd_table_default;
-	else
-		st->current_wbd_table = config->wbd;
-
-	if (dib0090_reset(fe) != 0)
-		goto free_mem;
-
-	printk(KERN_INFO "DiB0090: successfully identified\n");
-	memcpy(&fe->ops.tuner_ops, &dib0090_ops, sizeof(struct dvb_tuner_ops));
-
-	return fe;
- free_mem:
-	kfree(st);
-	fe->tuner_priv = NULL;
-	return NULL;
-}
-
-EXPORT_SYMBOL(dib0090_register);
-
-struct dvb_frontend *dib0090_fw_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config)
-{
-	struct dib0090_fw_state *st = kzalloc(sizeof(struct dib0090_fw_state), GFP_KERNEL);
-	if (st == NULL)
-		return NULL;
-
-	st->config = config;
-	st->i2c = i2c;
-	st->fe = fe;
-	mutex_init(&st->i2c_buffer_lock);
-	fe->tuner_priv = st;
-
-	if (dib0090_fw_reset_digital(fe, st->config) != 0)
-		goto free_mem;
-
-	dprintk("DiB0090 FW: successfully identified");
-	memcpy(&fe->ops.tuner_ops, &dib0090_fw_ops, sizeof(struct dvb_tuner_ops));
-
-	return fe;
-free_mem:
-	kfree(st);
-	fe->tuner_priv = NULL;
-	return NULL;
-}
-EXPORT_SYMBOL(dib0090_fw_register);
-
-MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
-MODULE_AUTHOR("Olivier Grenie <olivier.grenie@dibcom.fr>");
-MODULE_DESCRIPTION("Driver for the DiBcom 0090 base-band RF Tuner");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/dib0090.h b/drivers/media/dvb/frontends/dib0090.h
deleted file mode 100644
index 781dc49..0000000
--- a/drivers/media/dvb/frontends/dib0090.h
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * Linux-DVB Driver for DiBcom's DiB0090 base-band RF Tuner.
- *
- * Copyright (C) 2005-7 DiBcom (http://www.dibcom.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, version 2.
- */
-#ifndef DIB0090_H
-#define DIB0090_H
-
-struct dvb_frontend;
-struct i2c_adapter;
-
-#define DEFAULT_DIB0090_I2C_ADDRESS 0x60
-
-struct dib0090_io_config {
-	u32 clock_khz;
-
-	u8 pll_bypass:1;
-	u8 pll_range:1;
-	u8 pll_prediv:6;
-	u8 pll_loopdiv:6;
-
-	u8 adc_clock_ratio;	/* valid is 8, 7 ,6 */
-	u16 pll_int_loop_filt;
-};
-
-struct dib0090_wbd_slope {
-	u16 max_freq;		/* for every frequency less than or equal to that field: this information is correct */
-	u16 slope_cold;
-	u16 offset_cold;
-	u16 slope_hot;
-	u16 offset_hot;
-	u8 wbd_gain;
-};
-
-struct dib0090_low_if_offset_table {
-	int std;
-	u32 RF_freq;
-	s32 offset_khz;
-};
-
-struct dib0090_config {
-	struct dib0090_io_config io;
-	int (*reset) (struct dvb_frontend *, int);
-	int (*sleep) (struct dvb_frontend *, int);
-
-	/*  offset in kHz */
-	int freq_offset_khz_uhf;
-	int freq_offset_khz_vhf;
-
-	int (*get_adc_power) (struct dvb_frontend *);
-
-	u8 clkouttobamse:1;	/* activate or deactivate clock output */
-	u8 analog_output;
-
-	u8 i2c_address;
-	/* add drives and other things if necessary */
-	u16 wbd_vhf_offset;
-	u16 wbd_cband_offset;
-	u8 use_pwm_agc;
-	u8 clkoutdrive;
-
-	u8 ls_cfg_pad_drv;
-	u8 data_tx_drv;
-
-	u8 in_soc;
-	const struct dib0090_low_if_offset_table *low_if;
-	u8 fref_clock_ratio;
-	u16 force_cband_input;
-	struct dib0090_wbd_slope *wbd;
-	u8 is_dib7090e;
-	u8 force_crystal_mode;
-};
-
-#if defined(CONFIG_DVB_TUNER_DIB0090) || (defined(CONFIG_DVB_TUNER_DIB0090_MODULE) && defined(MODULE))
-extern struct dvb_frontend *dib0090_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config);
-extern struct dvb_frontend *dib0090_fw_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config);
-extern void dib0090_dcc_freq(struct dvb_frontend *fe, u8 fast);
-extern void dib0090_pwm_gain_reset(struct dvb_frontend *fe);
-extern u16 dib0090_get_wbd_target(struct dvb_frontend *tuner);
-extern u16 dib0090_get_wbd_offset(struct dvb_frontend *fe);
-extern int dib0090_gain_control(struct dvb_frontend *fe);
-extern enum frontend_tune_state dib0090_get_tune_state(struct dvb_frontend *fe);
-extern int dib0090_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state);
-extern void dib0090_get_current_gain(struct dvb_frontend *fe, u16 * rf, u16 * bb, u16 * rf_gain_limit, u16 * rflt);
-extern void dib0090_set_dc_servo(struct dvb_frontend *fe, u8 DC_servo_cutoff);
-extern int dib0090_set_switch(struct dvb_frontend *fe, u8 sw1, u8 sw2, u8 sw3);
-extern int dib0090_set_vga(struct dvb_frontend *fe, u8 onoff);
-extern int dib0090_update_rframp_7090(struct dvb_frontend *fe,
-		u8 cfg_sensitivity);
-extern int dib0090_update_tuning_table_7090(struct dvb_frontend *fe,
-		u8 cfg_sensitivity);
-#else
-static inline struct dvb_frontend *dib0090_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-
-static inline struct dvb_frontend *dib0090_fw_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0090_config *config)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-
-static inline void dib0090_dcc_freq(struct dvb_frontend *fe, u8 fast)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-}
-
-static inline void dib0090_pwm_gain_reset(struct dvb_frontend *fe)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-}
-
-static inline u16 dib0090_get_wbd_target(struct dvb_frontend *tuner)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return 0;
-}
-
-static inline u16 dib0090_get_wbd_offset(struct dvb_frontend *fe)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return 0;
-}
-
-static inline int dib0090_gain_control(struct dvb_frontend *fe)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return -ENODEV;
-}
-
-static inline enum frontend_tune_state dib0090_get_tune_state(struct dvb_frontend *fe)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return CT_DONE;
-}
-
-static inline int dib0090_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return -ENODEV;
-}
-
-static inline void dib0090_get_current_gain(struct dvb_frontend *fe, u16 * rf, u16 * bb, u16 * rf_gain_limit, u16 * rflt)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-}
-
-static inline void dib0090_set_dc_servo(struct dvb_frontend *fe, u8 DC_servo_cutoff)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-}
-
-static inline int dib0090_set_switch(struct dvb_frontend *fe,
-		u8 sw1, u8 sw2, u8 sw3)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return -ENODEV;
-}
-
-static inline int dib0090_set_vga(struct dvb_frontend *fe, u8 onoff)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return -ENODEV;
-}
-
-static inline int dib0090_update_rframp_7090(struct dvb_frontend *fe,
-		u8 cfg_sensitivity)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return -ENODEV;
-}
-
-static inline int dib0090_update_tuning_table_7090(struct dvb_frontend *fe,
-		u8 cfg_sensitivity)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return -ENODEV;
-}
-#endif
-
-#endif
diff --git a/drivers/media/dvb/frontends/dib3000.h b/drivers/media/dvb/frontends/dib3000.h
deleted file mode 100644
index 404f63a..0000000
--- a/drivers/media/dvb/frontends/dib3000.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * public header file of the frontend drivers for mobile DVB-T demodulators
- * DiBcom 3000M-B and DiBcom 3000P/M-C (http://www.dibcom.fr/)
- *
- * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
- *
- * based on GPL code from DibCom, which has
- *
- * Copyright (C) 2004 Amaury Demol for DiBcom (ademol@dibcom.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, version 2.
- *
- * Acknowledgements
- *
- *  Amaury Demol (ademol@dibcom.fr) from DiBcom for providing specs and driver
- *  sources, on which this driver (and the dvb-dibusb) are based.
- *
- * see Documentation/dvb/README.dvb-usb for more information
- *
- */
-
-#ifndef DIB3000_H
-#define DIB3000_H
-
-#include <linux/dvb/frontend.h>
-
-struct dib3000_config
-{
-	/* the demodulator's i2c address */
-	u8 demod_address;
-};
-
-struct dib_fe_xfer_ops
-{
-	/* pid and transfer handling is done in the demodulator */
-	int (*pid_parse)(struct dvb_frontend *fe, int onoff);
-	int (*fifo_ctrl)(struct dvb_frontend *fe, int onoff);
-	int (*pid_ctrl)(struct dvb_frontend *fe, int index, int pid, int onoff);
-	int (*tuner_pass_ctrl)(struct dvb_frontend *fe, int onoff, u8 pll_ctrl);
-};
-
-#if defined(CONFIG_DVB_DIB3000MB) || (defined(CONFIG_DVB_DIB3000MB_MODULE) && defined(MODULE))
-extern struct dvb_frontend* dib3000mb_attach(const struct dib3000_config* config,
-					     struct i2c_adapter* i2c, struct dib_fe_xfer_ops *xfer_ops);
-#else
-static inline struct dvb_frontend* dib3000mb_attach(const struct dib3000_config* config,
-					     struct i2c_adapter* i2c, struct dib_fe_xfer_ops *xfer_ops)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif // CONFIG_DVB_DIB3000MB
-
-#endif // DIB3000_H
diff --git a/drivers/media/dvb/frontends/dib3000mb.c b/drivers/media/dvb/frontends/dib3000mb.c
deleted file mode 100644
index af91e0c..0000000
--- a/drivers/media/dvb/frontends/dib3000mb.c
+++ /dev/null
@@ -1,829 +0,0 @@
-/*
- * Frontend driver for mobile DVB-T demodulator DiBcom 3000M-B
- * DiBcom (http://www.dibcom.fr/)
- *
- * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
- *
- * based on GPL code from DibCom, which has
- *
- * Copyright (C) 2004 Amaury Demol for DiBcom (ademol@dibcom.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, version 2.
- *
- * Acknowledgements
- *
- *  Amaury Demol (ademol@dibcom.fr) from DiBcom for providing specs and driver
- *  sources, on which this driver (and the dvb-dibusb) are based.
- *
- * see Documentation/dvb/README.dvb-usb for more information
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-
-#include "dvb_frontend.h"
-
-#include "dib3000.h"
-#include "dib3000mb_priv.h"
-
-/* Version information */
-#define DRIVER_VERSION "0.1"
-#define DRIVER_DESC "DiBcom 3000M-B DVB-T demodulator"
-#define DRIVER_AUTHOR "Patrick Boettcher, patrick.boettcher@desy.de"
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level (1=info,2=xfer,4=setfe,8=getfe (|-able)).");
-
-#define deb_info(args...) dprintk(0x01,args)
-#define deb_i2c(args...)  dprintk(0x02,args)
-#define deb_srch(args...) dprintk(0x04,args)
-#define deb_info(args...) dprintk(0x01,args)
-#define deb_xfer(args...) dprintk(0x02,args)
-#define deb_setf(args...) dprintk(0x04,args)
-#define deb_getf(args...) dprintk(0x08,args)
-
-static int dib3000_read_reg(struct dib3000_state *state, u16 reg)
-{
-	u8 wb[] = { ((reg >> 8) | 0x80) & 0xff, reg & 0xff };
-	u8 rb[2];
-	struct i2c_msg msg[] = {
-		{ .addr = state->config.demod_address, .flags = 0,        .buf = wb, .len = 2 },
-		{ .addr = state->config.demod_address, .flags = I2C_M_RD, .buf = rb, .len = 2 },
-	};
-
-	if (i2c_transfer(state->i2c, msg, 2) != 2)
-		deb_i2c("i2c read error\n");
-
-	deb_i2c("reading i2c bus (reg: %5d 0x%04x, val: %5d 0x%04x)\n",reg,reg,
-			(rb[0] << 8) | rb[1],(rb[0] << 8) | rb[1]);
-
-	return (rb[0] << 8) | rb[1];
-}
-
-static int dib3000_write_reg(struct dib3000_state *state, u16 reg, u16 val)
-{
-	u8 b[] = {
-		(reg >> 8) & 0xff, reg & 0xff,
-		(val >> 8) & 0xff, val & 0xff,
-	};
-	struct i2c_msg msg[] = {
-		{ .addr = state->config.demod_address, .flags = 0, .buf = b, .len = 4 }
-	};
-	deb_i2c("writing i2c bus (reg: %5d 0x%04x, val: %5d 0x%04x)\n",reg,reg,val,val);
-
-	return i2c_transfer(state->i2c,msg, 1) != 1 ? -EREMOTEIO : 0;
-}
-
-static int dib3000_search_status(u16 irq,u16 lock)
-{
-	if (irq & 0x02) {
-		if (lock & 0x01) {
-			deb_srch("auto search succeeded\n");
-			return 1; // auto search succeeded
-		} else {
-			deb_srch("auto search not successful\n");
-			return 0; // auto search failed
-		}
-	} else if (irq & 0x01)  {
-		deb_srch("auto search failed\n");
-		return 0; // auto search failed
-	}
-	return -1; // try again
-}
-
-/* for auto search */
-static u16 dib3000_seq[2][2][2] =     /* fft,gua,   inv   */
-	{ /* fft */
-		{ /* gua */
-			{ 0, 1 },                   /*  0   0   { 0,1 } */
-			{ 3, 9 },                   /*  0   1   { 0,1 } */
-		},
-		{
-			{ 2, 5 },                   /*  1   0   { 0,1 } */
-			{ 6, 11 },                  /*  1   1   { 0,1 } */
-		}
-	};
-
-static int dib3000mb_get_frontend(struct dvb_frontend* fe);
-
-static int dib3000mb_set_frontend(struct dvb_frontend *fe, int tuner)
-{
-	struct dib3000_state* state = fe->demodulator_priv;
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	fe_code_rate_t fe_cr = FEC_NONE;
-	int search_state, seq;
-
-	if (tuner && fe->ops.tuner_ops.set_params) {
-		fe->ops.tuner_ops.set_params(fe);
-		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
-
-		deb_setf("bandwidth: ");
-		switch (c->bandwidth_hz) {
-			case 8000000:
-				deb_setf("8 MHz\n");
-				wr_foreach(dib3000mb_reg_timing_freq, dib3000mb_timing_freq[2]);
-				wr_foreach(dib3000mb_reg_bandwidth, dib3000mb_bandwidth_8mhz);
-				break;
-			case 7000000:
-				deb_setf("7 MHz\n");
-				wr_foreach(dib3000mb_reg_timing_freq, dib3000mb_timing_freq[1]);
-				wr_foreach(dib3000mb_reg_bandwidth, dib3000mb_bandwidth_7mhz);
-				break;
-			case 6000000:
-				deb_setf("6 MHz\n");
-				wr_foreach(dib3000mb_reg_timing_freq, dib3000mb_timing_freq[0]);
-				wr_foreach(dib3000mb_reg_bandwidth, dib3000mb_bandwidth_6mhz);
-				break;
-			case 0:
-				return -EOPNOTSUPP;
-			default:
-				err("unknown bandwidth value.");
-				return -EINVAL;
-		}
-	}
-	wr(DIB3000MB_REG_LOCK1_MASK, DIB3000MB_LOCK1_SEARCH_4);
-
-	deb_setf("transmission mode: ");
-	switch (c->transmission_mode) {
-		case TRANSMISSION_MODE_2K:
-			deb_setf("2k\n");
-			wr(DIB3000MB_REG_FFT, DIB3000_TRANSMISSION_MODE_2K);
-			break;
-		case TRANSMISSION_MODE_8K:
-			deb_setf("8k\n");
-			wr(DIB3000MB_REG_FFT, DIB3000_TRANSMISSION_MODE_8K);
-			break;
-		case TRANSMISSION_MODE_AUTO:
-			deb_setf("auto\n");
-			break;
-		default:
-			return -EINVAL;
-	}
-
-	deb_setf("guard: ");
-	switch (c->guard_interval) {
-		case GUARD_INTERVAL_1_32:
-			deb_setf("1_32\n");
-			wr(DIB3000MB_REG_GUARD_TIME, DIB3000_GUARD_TIME_1_32);
-			break;
-		case GUARD_INTERVAL_1_16:
-			deb_setf("1_16\n");
-			wr(DIB3000MB_REG_GUARD_TIME, DIB3000_GUARD_TIME_1_16);
-			break;
-		case GUARD_INTERVAL_1_8:
-			deb_setf("1_8\n");
-			wr(DIB3000MB_REG_GUARD_TIME, DIB3000_GUARD_TIME_1_8);
-			break;
-		case GUARD_INTERVAL_1_4:
-			deb_setf("1_4\n");
-			wr(DIB3000MB_REG_GUARD_TIME, DIB3000_GUARD_TIME_1_4);
-			break;
-		case GUARD_INTERVAL_AUTO:
-			deb_setf("auto\n");
-			break;
-		default:
-			return -EINVAL;
-	}
-
-	deb_setf("inversion: ");
-	switch (c->inversion) {
-		case INVERSION_OFF:
-			deb_setf("off\n");
-			wr(DIB3000MB_REG_DDS_INV, DIB3000_DDS_INVERSION_OFF);
-			break;
-		case INVERSION_AUTO:
-			deb_setf("auto ");
-			break;
-		case INVERSION_ON:
-			deb_setf("on\n");
-			wr(DIB3000MB_REG_DDS_INV, DIB3000_DDS_INVERSION_ON);
-			break;
-		default:
-			return -EINVAL;
-	}
-
-	deb_setf("modulation: ");
-	switch (c->modulation) {
-		case QPSK:
-			deb_setf("qpsk\n");
-			wr(DIB3000MB_REG_QAM, DIB3000_CONSTELLATION_QPSK);
-			break;
-		case QAM_16:
-			deb_setf("qam16\n");
-			wr(DIB3000MB_REG_QAM, DIB3000_CONSTELLATION_16QAM);
-			break;
-		case QAM_64:
-			deb_setf("qam64\n");
-			wr(DIB3000MB_REG_QAM, DIB3000_CONSTELLATION_64QAM);
-			break;
-		case QAM_AUTO:
-			break;
-		default:
-			return -EINVAL;
-	}
-	deb_setf("hierarchy: ");
-	switch (c->hierarchy) {
-		case HIERARCHY_NONE:
-			deb_setf("none ");
-			/* fall through */
-		case HIERARCHY_1:
-			deb_setf("alpha=1\n");
-			wr(DIB3000MB_REG_VIT_ALPHA, DIB3000_ALPHA_1);
-			break;
-		case HIERARCHY_2:
-			deb_setf("alpha=2\n");
-			wr(DIB3000MB_REG_VIT_ALPHA, DIB3000_ALPHA_2);
-			break;
-		case HIERARCHY_4:
-			deb_setf("alpha=4\n");
-			wr(DIB3000MB_REG_VIT_ALPHA, DIB3000_ALPHA_4);
-			break;
-		case HIERARCHY_AUTO:
-			deb_setf("alpha=auto\n");
-			break;
-		default:
-			return -EINVAL;
-	}
-
-	deb_setf("hierarchy: ");
-	if (c->hierarchy == HIERARCHY_NONE) {
-		deb_setf("none\n");
-		wr(DIB3000MB_REG_VIT_HRCH, DIB3000_HRCH_OFF);
-		wr(DIB3000MB_REG_VIT_HP, DIB3000_SELECT_HP);
-		fe_cr = c->code_rate_HP;
-	} else if (c->hierarchy != HIERARCHY_AUTO) {
-		deb_setf("on\n");
-		wr(DIB3000MB_REG_VIT_HRCH, DIB3000_HRCH_ON);
-		wr(DIB3000MB_REG_VIT_HP, DIB3000_SELECT_LP);
-		fe_cr = c->code_rate_LP;
-	}
-	deb_setf("fec: ");
-	switch (fe_cr) {
-		case FEC_1_2:
-			deb_setf("1_2\n");
-			wr(DIB3000MB_REG_VIT_CODE_RATE, DIB3000_FEC_1_2);
-			break;
-		case FEC_2_3:
-			deb_setf("2_3\n");
-			wr(DIB3000MB_REG_VIT_CODE_RATE, DIB3000_FEC_2_3);
-			break;
-		case FEC_3_4:
-			deb_setf("3_4\n");
-			wr(DIB3000MB_REG_VIT_CODE_RATE, DIB3000_FEC_3_4);
-			break;
-		case FEC_5_6:
-			deb_setf("5_6\n");
-			wr(DIB3000MB_REG_VIT_CODE_RATE, DIB3000_FEC_5_6);
-			break;
-		case FEC_7_8:
-			deb_setf("7_8\n");
-			wr(DIB3000MB_REG_VIT_CODE_RATE, DIB3000_FEC_7_8);
-			break;
-		case FEC_NONE:
-			deb_setf("none ");
-			break;
-		case FEC_AUTO:
-			deb_setf("auto\n");
-			break;
-		default:
-			return -EINVAL;
-	}
-
-	seq = dib3000_seq
-		[c->transmission_mode == TRANSMISSION_MODE_AUTO]
-		[c->guard_interval == GUARD_INTERVAL_AUTO]
-		[c->inversion == INVERSION_AUTO];
-
-	deb_setf("seq? %d\n", seq);
-
-	wr(DIB3000MB_REG_SEQ, seq);
-
-	wr(DIB3000MB_REG_ISI, seq ? DIB3000MB_ISI_INHIBIT : DIB3000MB_ISI_ACTIVATE);
-
-	if (c->transmission_mode == TRANSMISSION_MODE_2K) {
-		if (c->guard_interval == GUARD_INTERVAL_1_8) {
-			wr(DIB3000MB_REG_SYNC_IMPROVEMENT, DIB3000MB_SYNC_IMPROVE_2K_1_8);
-		} else {
-			wr(DIB3000MB_REG_SYNC_IMPROVEMENT, DIB3000MB_SYNC_IMPROVE_DEFAULT);
-		}
-
-		wr(DIB3000MB_REG_UNK_121, DIB3000MB_UNK_121_2K);
-	} else {
-		wr(DIB3000MB_REG_UNK_121, DIB3000MB_UNK_121_DEFAULT);
-	}
-
-	wr(DIB3000MB_REG_MOBILE_ALGO, DIB3000MB_MOBILE_ALGO_OFF);
-	wr(DIB3000MB_REG_MOBILE_MODE_QAM, DIB3000MB_MOBILE_MODE_QAM_OFF);
-	wr(DIB3000MB_REG_MOBILE_MODE, DIB3000MB_MOBILE_MODE_OFF);
-
-	wr_foreach(dib3000mb_reg_agc_bandwidth, dib3000mb_agc_bandwidth_high);
-
-	wr(DIB3000MB_REG_ISI, DIB3000MB_ISI_ACTIVATE);
-
-	wr(DIB3000MB_REG_RESTART, DIB3000MB_RESTART_AGC + DIB3000MB_RESTART_CTRL);
-	wr(DIB3000MB_REG_RESTART, DIB3000MB_RESTART_OFF);
-
-	/* wait for AGC lock */
-	msleep(70);
-
-	wr_foreach(dib3000mb_reg_agc_bandwidth, dib3000mb_agc_bandwidth_low);
-
-	/* something has to be auto searched */
-	if (c->modulation == QAM_AUTO ||
-		c->hierarchy == HIERARCHY_AUTO ||
-		fe_cr == FEC_AUTO ||
-		c->inversion == INVERSION_AUTO) {
-		int as_count=0;
-
-		deb_setf("autosearch enabled.\n");
-
-		wr(DIB3000MB_REG_ISI, DIB3000MB_ISI_INHIBIT);
-
-		wr(DIB3000MB_REG_RESTART, DIB3000MB_RESTART_AUTO_SEARCH);
-		wr(DIB3000MB_REG_RESTART, DIB3000MB_RESTART_OFF);
-
-		while ((search_state =
-				dib3000_search_status(
-					rd(DIB3000MB_REG_AS_IRQ_PENDING),
-					rd(DIB3000MB_REG_LOCK2_VALUE))) < 0 && as_count++ < 100)
-			msleep(1);
-
-		deb_setf("search_state after autosearch %d after %d checks\n",search_state,as_count);
-
-		if (search_state == 1) {
-			if (dib3000mb_get_frontend(fe) == 0) {
-				deb_setf("reading tuning data from frontend succeeded.\n");
-				return dib3000mb_set_frontend(fe, 0);
-			}
-		}
-
-	} else {
-		wr(DIB3000MB_REG_RESTART, DIB3000MB_RESTART_CTRL);
-		wr(DIB3000MB_REG_RESTART, DIB3000MB_RESTART_OFF);
-	}
-
-	return 0;
-}
-
-static int dib3000mb_fe_init(struct dvb_frontend* fe, int mobile_mode)
-{
-	struct dib3000_state* state = fe->demodulator_priv;
-
-	deb_info("dib3000mb is getting up.\n");
-	wr(DIB3000MB_REG_POWER_CONTROL, DIB3000MB_POWER_UP);
-
-	wr(DIB3000MB_REG_RESTART, DIB3000MB_RESTART_AGC);
-
-	wr(DIB3000MB_REG_RESET_DEVICE, DIB3000MB_RESET_DEVICE);
-	wr(DIB3000MB_REG_RESET_DEVICE, DIB3000MB_RESET_DEVICE_RST);
-
-	wr(DIB3000MB_REG_CLOCK, DIB3000MB_CLOCK_DEFAULT);
-
-	wr(DIB3000MB_REG_ELECT_OUT_MODE, DIB3000MB_ELECT_OUT_MODE_ON);
-
-	wr(DIB3000MB_REG_DDS_FREQ_MSB, DIB3000MB_DDS_FREQ_MSB);
-	wr(DIB3000MB_REG_DDS_FREQ_LSB, DIB3000MB_DDS_FREQ_LSB);
-
-	wr_foreach(dib3000mb_reg_timing_freq, dib3000mb_timing_freq[2]);
-
-	wr_foreach(dib3000mb_reg_impulse_noise,
-			dib3000mb_impulse_noise_values[DIB3000MB_IMPNOISE_OFF]);
-
-	wr_foreach(dib3000mb_reg_agc_gain, dib3000mb_default_agc_gain);
-
-	wr(DIB3000MB_REG_PHASE_NOISE, DIB3000MB_PHASE_NOISE_DEFAULT);
-
-	wr_foreach(dib3000mb_reg_phase_noise, dib3000mb_default_noise_phase);
-
-	wr_foreach(dib3000mb_reg_lock_duration, dib3000mb_default_lock_duration);
-
-	wr_foreach(dib3000mb_reg_agc_bandwidth, dib3000mb_agc_bandwidth_low);
-
-	wr(DIB3000MB_REG_LOCK0_MASK, DIB3000MB_LOCK0_DEFAULT);
-	wr(DIB3000MB_REG_LOCK1_MASK, DIB3000MB_LOCK1_SEARCH_4);
-	wr(DIB3000MB_REG_LOCK2_MASK, DIB3000MB_LOCK2_DEFAULT);
-	wr(DIB3000MB_REG_SEQ, dib3000_seq[1][1][1]);
-
-	wr_foreach(dib3000mb_reg_bandwidth, dib3000mb_bandwidth_8mhz);
-
-	wr(DIB3000MB_REG_UNK_68, DIB3000MB_UNK_68);
-	wr(DIB3000MB_REG_UNK_69, DIB3000MB_UNK_69);
-	wr(DIB3000MB_REG_UNK_71, DIB3000MB_UNK_71);
-	wr(DIB3000MB_REG_UNK_77, DIB3000MB_UNK_77);
-	wr(DIB3000MB_REG_UNK_78, DIB3000MB_UNK_78);
-	wr(DIB3000MB_REG_ISI, DIB3000MB_ISI_INHIBIT);
-	wr(DIB3000MB_REG_UNK_92, DIB3000MB_UNK_92);
-	wr(DIB3000MB_REG_UNK_96, DIB3000MB_UNK_96);
-	wr(DIB3000MB_REG_UNK_97, DIB3000MB_UNK_97);
-	wr(DIB3000MB_REG_UNK_106, DIB3000MB_UNK_106);
-	wr(DIB3000MB_REG_UNK_107, DIB3000MB_UNK_107);
-	wr(DIB3000MB_REG_UNK_108, DIB3000MB_UNK_108);
-	wr(DIB3000MB_REG_UNK_122, DIB3000MB_UNK_122);
-	wr(DIB3000MB_REG_MOBILE_MODE_QAM, DIB3000MB_MOBILE_MODE_QAM_OFF);
-	wr(DIB3000MB_REG_BERLEN, DIB3000MB_BERLEN_DEFAULT);
-
-	wr_foreach(dib3000mb_reg_filter_coeffs, dib3000mb_filter_coeffs);
-
-	wr(DIB3000MB_REG_MOBILE_ALGO, DIB3000MB_MOBILE_ALGO_ON);
-	wr(DIB3000MB_REG_MULTI_DEMOD_MSB, DIB3000MB_MULTI_DEMOD_MSB);
-	wr(DIB3000MB_REG_MULTI_DEMOD_LSB, DIB3000MB_MULTI_DEMOD_LSB);
-
-	wr(DIB3000MB_REG_OUTPUT_MODE, DIB3000MB_OUTPUT_MODE_SLAVE);
-
-	wr(DIB3000MB_REG_FIFO_142, DIB3000MB_FIFO_142);
-	wr(DIB3000MB_REG_MPEG2_OUT_MODE, DIB3000MB_MPEG2_OUT_MODE_188);
-	wr(DIB3000MB_REG_PID_PARSE, DIB3000MB_PID_PARSE_ACTIVATE);
-	wr(DIB3000MB_REG_FIFO, DIB3000MB_FIFO_INHIBIT);
-	wr(DIB3000MB_REG_FIFO_146, DIB3000MB_FIFO_146);
-	wr(DIB3000MB_REG_FIFO_147, DIB3000MB_FIFO_147);
-
-	wr(DIB3000MB_REG_DATA_IN_DIVERSITY, DIB3000MB_DATA_DIVERSITY_IN_OFF);
-
-	return 0;
-}
-
-static int dib3000mb_get_frontend(struct dvb_frontend* fe)
-{
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	struct dib3000_state* state = fe->demodulator_priv;
-	fe_code_rate_t *cr;
-	u16 tps_val;
-	int inv_test1,inv_test2;
-	u32 dds_val, threshold = 0x800000;
-
-	if (!rd(DIB3000MB_REG_TPS_LOCK))
-		return 0;
-
-	dds_val = ((rd(DIB3000MB_REG_DDS_VALUE_MSB) & 0xff) << 16) + rd(DIB3000MB_REG_DDS_VALUE_LSB);
-	deb_getf("DDS_VAL: %x %x %x",dds_val, rd(DIB3000MB_REG_DDS_VALUE_MSB), rd(DIB3000MB_REG_DDS_VALUE_LSB));
-	if (dds_val < threshold)
-		inv_test1 = 0;
-	else if (dds_val == threshold)
-		inv_test1 = 1;
-	else
-		inv_test1 = 2;
-
-	dds_val = ((rd(DIB3000MB_REG_DDS_FREQ_MSB) & 0xff) << 16) + rd(DIB3000MB_REG_DDS_FREQ_LSB);
-	deb_getf("DDS_FREQ: %x %x %x",dds_val, rd(DIB3000MB_REG_DDS_FREQ_MSB), rd(DIB3000MB_REG_DDS_FREQ_LSB));
-	if (dds_val < threshold)
-		inv_test2 = 0;
-	else if (dds_val == threshold)
-		inv_test2 = 1;
-	else
-		inv_test2 = 2;
-
-	c->inversion =
-		((inv_test2 == 2) && (inv_test1==1 || inv_test1==0)) ||
-		((inv_test2 == 0) && (inv_test1==1 || inv_test1==2)) ?
-		INVERSION_ON : INVERSION_OFF;
-
-	deb_getf("inversion %d %d, %d\n", inv_test2, inv_test1, c->inversion);
-
-	switch ((tps_val = rd(DIB3000MB_REG_TPS_QAM))) {
-		case DIB3000_CONSTELLATION_QPSK:
-			deb_getf("QPSK ");
-			c->modulation = QPSK;
-			break;
-		case DIB3000_CONSTELLATION_16QAM:
-			deb_getf("QAM16 ");
-			c->modulation = QAM_16;
-			break;
-		case DIB3000_CONSTELLATION_64QAM:
-			deb_getf("QAM64 ");
-			c->modulation = QAM_64;
-			break;
-		default:
-			err("Unexpected constellation returned by TPS (%d)", tps_val);
-			break;
-	}
-	deb_getf("TPS: %d\n", tps_val);
-
-	if (rd(DIB3000MB_REG_TPS_HRCH)) {
-		deb_getf("HRCH ON\n");
-		cr = &c->code_rate_LP;
-		c->code_rate_HP = FEC_NONE;
-		switch ((tps_val = rd(DIB3000MB_REG_TPS_VIT_ALPHA))) {
-			case DIB3000_ALPHA_0:
-				deb_getf("HIERARCHY_NONE ");
-				c->hierarchy = HIERARCHY_NONE;
-				break;
-			case DIB3000_ALPHA_1:
-				deb_getf("HIERARCHY_1 ");
-				c->hierarchy = HIERARCHY_1;
-				break;
-			case DIB3000_ALPHA_2:
-				deb_getf("HIERARCHY_2 ");
-				c->hierarchy = HIERARCHY_2;
-				break;
-			case DIB3000_ALPHA_4:
-				deb_getf("HIERARCHY_4 ");
-				c->hierarchy = HIERARCHY_4;
-				break;
-			default:
-				err("Unexpected ALPHA value returned by TPS (%d)", tps_val);
-				break;
-		}
-		deb_getf("TPS: %d\n", tps_val);
-
-		tps_val = rd(DIB3000MB_REG_TPS_CODE_RATE_LP);
-	} else {
-		deb_getf("HRCH OFF\n");
-		cr = &c->code_rate_HP;
-		c->code_rate_LP = FEC_NONE;
-		c->hierarchy = HIERARCHY_NONE;
-
-		tps_val = rd(DIB3000MB_REG_TPS_CODE_RATE_HP);
-	}
-
-	switch (tps_val) {
-		case DIB3000_FEC_1_2:
-			deb_getf("FEC_1_2 ");
-			*cr = FEC_1_2;
-			break;
-		case DIB3000_FEC_2_3:
-			deb_getf("FEC_2_3 ");
-			*cr = FEC_2_3;
-			break;
-		case DIB3000_FEC_3_4:
-			deb_getf("FEC_3_4 ");
-			*cr = FEC_3_4;
-			break;
-		case DIB3000_FEC_5_6:
-			deb_getf("FEC_5_6 ");
-			*cr = FEC_4_5;
-			break;
-		case DIB3000_FEC_7_8:
-			deb_getf("FEC_7_8 ");
-			*cr = FEC_7_8;
-			break;
-		default:
-			err("Unexpected FEC returned by TPS (%d)", tps_val);
-			break;
-	}
-	deb_getf("TPS: %d\n",tps_val);
-
-	switch ((tps_val = rd(DIB3000MB_REG_TPS_GUARD_TIME))) {
-		case DIB3000_GUARD_TIME_1_32:
-			deb_getf("GUARD_INTERVAL_1_32 ");
-			c->guard_interval = GUARD_INTERVAL_1_32;
-			break;
-		case DIB3000_GUARD_TIME_1_16:
-			deb_getf("GUARD_INTERVAL_1_16 ");
-			c->guard_interval = GUARD_INTERVAL_1_16;
-			break;
-		case DIB3000_GUARD_TIME_1_8:
-			deb_getf("GUARD_INTERVAL_1_8 ");
-			c->guard_interval = GUARD_INTERVAL_1_8;
-			break;
-		case DIB3000_GUARD_TIME_1_4:
-			deb_getf("GUARD_INTERVAL_1_4 ");
-			c->guard_interval = GUARD_INTERVAL_1_4;
-			break;
-		default:
-			err("Unexpected Guard Time returned by TPS (%d)", tps_val);
-			break;
-	}
-	deb_getf("TPS: %d\n", tps_val);
-
-	switch ((tps_val = rd(DIB3000MB_REG_TPS_FFT))) {
-		case DIB3000_TRANSMISSION_MODE_2K:
-			deb_getf("TRANSMISSION_MODE_2K ");
-			c->transmission_mode = TRANSMISSION_MODE_2K;
-			break;
-		case DIB3000_TRANSMISSION_MODE_8K:
-			deb_getf("TRANSMISSION_MODE_8K ");
-			c->transmission_mode = TRANSMISSION_MODE_8K;
-			break;
-		default:
-			err("unexpected transmission mode return by TPS (%d)", tps_val);
-			break;
-	}
-	deb_getf("TPS: %d\n", tps_val);
-
-	return 0;
-}
-
-static int dib3000mb_read_status(struct dvb_frontend* fe, fe_status_t *stat)
-{
-	struct dib3000_state* state = fe->demodulator_priv;
-
-	*stat = 0;
-
-	if (rd(DIB3000MB_REG_AGC_LOCK))
-		*stat |= FE_HAS_SIGNAL;
-	if (rd(DIB3000MB_REG_CARRIER_LOCK))
-		*stat |= FE_HAS_CARRIER;
-	if (rd(DIB3000MB_REG_VIT_LCK))
-		*stat |= FE_HAS_VITERBI;
-	if (rd(DIB3000MB_REG_TS_SYNC_LOCK))
-		*stat |= (FE_HAS_SYNC | FE_HAS_LOCK);
-
-	deb_getf("actual status is %2x\n",*stat);
-
-	deb_getf("autoval: tps: %d, qam: %d, hrch: %d, alpha: %d, hp: %d, lp: %d, guard: %d, fft: %d cell: %d\n",
-			rd(DIB3000MB_REG_TPS_LOCK),
-			rd(DIB3000MB_REG_TPS_QAM),
-			rd(DIB3000MB_REG_TPS_HRCH),
-			rd(DIB3000MB_REG_TPS_VIT_ALPHA),
-			rd(DIB3000MB_REG_TPS_CODE_RATE_HP),
-			rd(DIB3000MB_REG_TPS_CODE_RATE_LP),
-			rd(DIB3000MB_REG_TPS_GUARD_TIME),
-			rd(DIB3000MB_REG_TPS_FFT),
-			rd(DIB3000MB_REG_TPS_CELL_ID));
-
-	//*stat = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
-	return 0;
-}
-
-static int dib3000mb_read_ber(struct dvb_frontend* fe, u32 *ber)
-{
-	struct dib3000_state* state = fe->demodulator_priv;
-
-	*ber = ((rd(DIB3000MB_REG_BER_MSB) << 16) | rd(DIB3000MB_REG_BER_LSB));
-	return 0;
-}
-
-/* see dib3000-watch dvb-apps for exact calcuations of signal_strength and snr */
-static int dib3000mb_read_signal_strength(struct dvb_frontend* fe, u16 *strength)
-{
-	struct dib3000_state* state = fe->demodulator_priv;
-
-	*strength = rd(DIB3000MB_REG_SIGNAL_POWER) * 0xffff / 0x170;
-	return 0;
-}
-
-static int dib3000mb_read_snr(struct dvb_frontend* fe, u16 *snr)
-{
-	struct dib3000_state* state = fe->demodulator_priv;
-	short sigpow = rd(DIB3000MB_REG_SIGNAL_POWER);
-	int icipow = ((rd(DIB3000MB_REG_NOISE_POWER_MSB) & 0xff) << 16) |
-		rd(DIB3000MB_REG_NOISE_POWER_LSB);
-	*snr = (sigpow << 8) / ((icipow > 0) ? icipow : 1);
-	return 0;
-}
-
-static int dib3000mb_read_unc_blocks(struct dvb_frontend* fe, u32 *unc)
-{
-	struct dib3000_state* state = fe->demodulator_priv;
-
-	*unc = rd(DIB3000MB_REG_PACKET_ERROR_RATE);
-	return 0;
-}
-
-static int dib3000mb_sleep(struct dvb_frontend* fe)
-{
-	struct dib3000_state* state = fe->demodulator_priv;
-	deb_info("dib3000mb is going to bed.\n");
-	wr(DIB3000MB_REG_POWER_CONTROL, DIB3000MB_POWER_DOWN);
-	return 0;
-}
-
-static int dib3000mb_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
-{
-	tune->min_delay_ms = 800;
-	return 0;
-}
-
-static int dib3000mb_fe_init_nonmobile(struct dvb_frontend* fe)
-{
-	return dib3000mb_fe_init(fe, 0);
-}
-
-static int dib3000mb_set_frontend_and_tuner(struct dvb_frontend *fe)
-{
-	return dib3000mb_set_frontend(fe, 1);
-}
-
-static void dib3000mb_release(struct dvb_frontend* fe)
-{
-	struct dib3000_state *state = fe->demodulator_priv;
-	kfree(state);
-}
-
-/* pid filter and transfer stuff */
-static int dib3000mb_pid_control(struct dvb_frontend *fe,int index, int pid,int onoff)
-{
-	struct dib3000_state *state = fe->demodulator_priv;
-	pid = (onoff ? pid | DIB3000_ACTIVATE_PID_FILTERING : 0);
-	wr(index+DIB3000MB_REG_FIRST_PID,pid);
-	return 0;
-}
-
-static int dib3000mb_fifo_control(struct dvb_frontend *fe, int onoff)
-{
-	struct dib3000_state *state = fe->demodulator_priv;
-
-	deb_xfer("%s fifo\n",onoff ? "enabling" : "disabling");
-	if (onoff) {
-		wr(DIB3000MB_REG_FIFO, DIB3000MB_FIFO_ACTIVATE);
-	} else {
-		wr(DIB3000MB_REG_FIFO, DIB3000MB_FIFO_INHIBIT);
-	}
-	return 0;
-}
-
-static int dib3000mb_pid_parse(struct dvb_frontend *fe, int onoff)
-{
-	struct dib3000_state *state = fe->demodulator_priv;
-	deb_xfer("%s pid parsing\n",onoff ? "enabling" : "disabling");
-	wr(DIB3000MB_REG_PID_PARSE,onoff);
-	return 0;
-}
-
-static int dib3000mb_tuner_pass_ctrl(struct dvb_frontend *fe, int onoff, u8 pll_addr)
-{
-	struct dib3000_state *state = fe->demodulator_priv;
-	if (onoff) {
-		wr(DIB3000MB_REG_TUNER, DIB3000_TUNER_WRITE_ENABLE(pll_addr));
-	} else {
-		wr(DIB3000MB_REG_TUNER, DIB3000_TUNER_WRITE_DISABLE(pll_addr));
-	}
-	return 0;
-}
-
-static struct dvb_frontend_ops dib3000mb_ops;
-
-struct dvb_frontend* dib3000mb_attach(const struct dib3000_config* config,
-				      struct i2c_adapter* i2c, struct dib_fe_xfer_ops *xfer_ops)
-{
-	struct dib3000_state* state = NULL;
-
-	/* allocate memory for the internal state */
-	state = kzalloc(sizeof(struct dib3000_state), GFP_KERNEL);
-	if (state == NULL)
-		goto error;
-
-	/* setup the state */
-	state->i2c = i2c;
-	memcpy(&state->config,config,sizeof(struct dib3000_config));
-
-	/* check for the correct demod */
-	if (rd(DIB3000_REG_MANUFACTOR_ID) != DIB3000_I2C_ID_DIBCOM)
-		goto error;
-
-	if (rd(DIB3000_REG_DEVICE_ID) != DIB3000MB_DEVICE_ID)
-		goto error;
-
-	/* create dvb_frontend */
-	memcpy(&state->frontend.ops, &dib3000mb_ops, sizeof(struct dvb_frontend_ops));
-	state->frontend.demodulator_priv = state;
-
-	/* set the xfer operations */
-	xfer_ops->pid_parse = dib3000mb_pid_parse;
-	xfer_ops->fifo_ctrl = dib3000mb_fifo_control;
-	xfer_ops->pid_ctrl = dib3000mb_pid_control;
-	xfer_ops->tuner_pass_ctrl = dib3000mb_tuner_pass_ctrl;
-
-	return &state->frontend;
-
-error:
-	kfree(state);
-	return NULL;
-}
-
-static struct dvb_frontend_ops dib3000mb_ops = {
-	.delsys = { SYS_DVBT },
-	.info = {
-		.name			= "DiBcom 3000M-B DVB-T",
-		.frequency_min		= 44250000,
-		.frequency_max		= 867250000,
-		.frequency_stepsize	= 62500,
-		.caps = FE_CAN_INVERSION_AUTO |
-				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_FEC_AUTO |
-				FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
-				FE_CAN_TRANSMISSION_MODE_AUTO |
-				FE_CAN_GUARD_INTERVAL_AUTO |
-				FE_CAN_RECOVER |
-				FE_CAN_HIERARCHY_AUTO,
-	},
-
-	.release = dib3000mb_release,
-
-	.init = dib3000mb_fe_init_nonmobile,
-	.sleep = dib3000mb_sleep,
-
-	.set_frontend = dib3000mb_set_frontend_and_tuner,
-	.get_frontend = dib3000mb_get_frontend,
-	.get_tune_settings = dib3000mb_fe_get_tune_settings,
-
-	.read_status = dib3000mb_read_status,
-	.read_ber = dib3000mb_read_ber,
-	.read_signal_strength = dib3000mb_read_signal_strength,
-	.read_snr = dib3000mb_read_snr,
-	.read_ucblocks = dib3000mb_read_unc_blocks,
-};
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(dib3000mb_attach);
diff --git a/drivers/media/dvb/frontends/dib3000mb_priv.h b/drivers/media/dvb/frontends/dib3000mb_priv.h
deleted file mode 100644
index 9dc235a..0000000
--- a/drivers/media/dvb/frontends/dib3000mb_priv.h
+++ /dev/null
@@ -1,556 +0,0 @@
-/*
- * dib3000mb_priv.h
- *
- * Copyright (C) 2004 Patrick Boettcher (patrick.boettcher@desy.de)
- *
- *	This program is free software; you can redistribute it and/or
- *	modify it under the terms of the GNU General Public License as
- *	published by the Free Software Foundation, version 2.
- *
- * for more information see dib3000mb.c .
- */
-
-#ifndef __DIB3000MB_PRIV_H_INCLUDED__
-#define __DIB3000MB_PRIV_H_INCLUDED__
-
-/* info and err, taken from usb.h, if there is anything available like by default. */
-#define err(format, arg...)  printk(KERN_ERR     "dib3000: " format "\n" , ## arg)
-#define info(format, arg...) printk(KERN_INFO    "dib3000: " format "\n" , ## arg)
-#define warn(format, arg...) printk(KERN_WARNING "dib3000: " format "\n" , ## arg)
-
-/* handy shortcuts */
-#define rd(reg) dib3000_read_reg(state,reg)
-
-#define wr(reg,val) if (dib3000_write_reg(state,reg,val)) \
-	{ err("while sending 0x%04x to 0x%04x.",val,reg); return -EREMOTEIO; }
-
-#define wr_foreach(a,v) { int i; \
-	if (sizeof(a) != sizeof(v)) \
-		err("sizeof: %zu %zu is different",sizeof(a),sizeof(v));\
-	for (i=0; i < sizeof(a)/sizeof(u16); i++) \
-		wr(a[i],v[i]); \
-	}
-
-#define set_or(reg,val) wr(reg,rd(reg) | val)
-
-#define set_and(reg,val) wr(reg,rd(reg) & val)
-
-/* debug */
-
-#define dprintk(level,args...) \
-    do { if ((debug & level)) { printk(args); } } while (0)
-
-/* mask for enabling a specific pid for the pid_filter */
-#define DIB3000_ACTIVATE_PID_FILTERING	(0x2000)
-
-/* common values for tuning */
-#define DIB3000_ALPHA_0					(     0)
-#define DIB3000_ALPHA_1					(     1)
-#define DIB3000_ALPHA_2					(     2)
-#define DIB3000_ALPHA_4					(     4)
-
-#define DIB3000_CONSTELLATION_QPSK		(     0)
-#define DIB3000_CONSTELLATION_16QAM		(     1)
-#define DIB3000_CONSTELLATION_64QAM		(     2)
-
-#define DIB3000_GUARD_TIME_1_32			(     0)
-#define DIB3000_GUARD_TIME_1_16			(     1)
-#define DIB3000_GUARD_TIME_1_8			(     2)
-#define DIB3000_GUARD_TIME_1_4			(     3)
-
-#define DIB3000_TRANSMISSION_MODE_2K	(     0)
-#define DIB3000_TRANSMISSION_MODE_8K	(     1)
-
-#define DIB3000_SELECT_LP				(     0)
-#define DIB3000_SELECT_HP				(     1)
-
-#define DIB3000_FEC_1_2					(     1)
-#define DIB3000_FEC_2_3					(     2)
-#define DIB3000_FEC_3_4					(     3)
-#define DIB3000_FEC_5_6					(     5)
-#define DIB3000_FEC_7_8					(     7)
-
-#define DIB3000_HRCH_OFF				(     0)
-#define DIB3000_HRCH_ON					(     1)
-
-#define DIB3000_DDS_INVERSION_OFF		(     0)
-#define DIB3000_DDS_INVERSION_ON		(     1)
-
-#define DIB3000_TUNER_WRITE_ENABLE(a)	(0xffff & (a << 8))
-#define DIB3000_TUNER_WRITE_DISABLE(a)	(0xffff & ((a << 8) | (1 << 7)))
-
-#define DIB3000_REG_MANUFACTOR_ID		(  1025)
-#define DIB3000_I2C_ID_DIBCOM			(0x01b3)
-
-#define DIB3000_REG_DEVICE_ID			(  1026)
-#define DIB3000MB_DEVICE_ID				(0x3000)
-#define DIB3000MC_DEVICE_ID				(0x3001)
-#define DIB3000P_DEVICE_ID				(0x3002)
-
-/* frontend state */
-struct dib3000_state {
-	struct i2c_adapter* i2c;
-
-/* configuration settings */
-	struct dib3000_config config;
-
-	struct dvb_frontend frontend;
-	int timing_offset;
-	int timing_offset_comp_done;
-
-	u32 last_tuned_bw;
-	u32 last_tuned_freq;
-};
-
-/* register addresses and some of their default values */
-
-/* restart subsystems */
-#define DIB3000MB_REG_RESTART			(     0)
-
-#define DIB3000MB_RESTART_OFF			(     0)
-#define DIB3000MB_RESTART_AUTO_SEARCH		(1 << 1)
-#define DIB3000MB_RESTART_CTRL				(1 << 2)
-#define DIB3000MB_RESTART_AGC				(1 << 3)
-
-/* FFT size */
-#define DIB3000MB_REG_FFT				(     1)
-
-/* Guard time */
-#define DIB3000MB_REG_GUARD_TIME		(     2)
-
-/* QAM */
-#define DIB3000MB_REG_QAM				(     3)
-
-/* Alpha coefficient high priority Viterbi algorithm */
-#define DIB3000MB_REG_VIT_ALPHA			(     4)
-
-/* spectrum inversion */
-#define DIB3000MB_REG_DDS_INV			(     5)
-
-/* DDS frequency value (IF position) ad ? values don't match reg_3000mb.txt */
-#define DIB3000MB_REG_DDS_FREQ_MSB		(     6)
-#define DIB3000MB_REG_DDS_FREQ_LSB		(     7)
-#define DIB3000MB_DDS_FREQ_MSB				(   178)
-#define DIB3000MB_DDS_FREQ_LSB				(  8990)
-
-/* timing frequency (carrier spacing) */
-static u16 dib3000mb_reg_timing_freq[] = { 8,9 };
-static u16 dib3000mb_timing_freq[][2] = {
-	{ 126 , 48873 }, /* 6 MHz */
-	{ 147 , 57019 }, /* 7 MHz */
-	{ 168 , 65164 }, /* 8 MHz */
-};
-
-/* impulse noise parameter */
-/* 36 ??? */
-
-static u16 dib3000mb_reg_impulse_noise[] = { 10,11,12,15,36 };
-
-enum dib3000mb_impulse_noise_type {
-	DIB3000MB_IMPNOISE_OFF,
-	DIB3000MB_IMPNOISE_MOBILE,
-	DIB3000MB_IMPNOISE_FIXED,
-	DIB3000MB_IMPNOISE_DEFAULT
-};
-
-static u16 dib3000mb_impulse_noise_values[][5] = {
-	{ 0x0000, 0x0004, 0x0014, 0x01ff, 0x0399 }, /* off */
-	{ 0x0001, 0x0004, 0x0014, 0x01ff, 0x037b }, /* mobile */
-	{ 0x0001, 0x0004, 0x0020, 0x01bd, 0x0399 }, /* fixed */
-	{ 0x0000, 0x0002, 0x000a, 0x01ff, 0x0399 }, /* default */
-};
-
-/*
- * Dual Automatic-Gain-Control
- * - gains RF in tuner (AGC1)
- * - gains IF after filtering (AGC2)
- */
-
-/* also from 16 to 18 */
-static u16 dib3000mb_reg_agc_gain[] = {
-	19,20,21,22,23,24,25,26,27,28,29,30,31,32
-};
-
-static u16 dib3000mb_default_agc_gain[] =
-	{ 0x0001, 52429,   623, 128, 166, 195, 61,   /* RF ??? */
-	  0x0001, 53766, 38011,   0,  90,  33, 23 }; /* IF ??? */
-
-/* phase noise */
-/* 36 is set when setting the impulse noise */
-static u16 dib3000mb_reg_phase_noise[] = { 33,34,35,37,38 };
-
-static u16 dib3000mb_default_noise_phase[] = { 2, 544, 0, 5, 4 };
-
-/* lock duration */
-static u16 dib3000mb_reg_lock_duration[] = { 39,40 };
-static u16 dib3000mb_default_lock_duration[] = { 135, 135 };
-
-/* AGC loop bandwidth */
-static u16 dib3000mb_reg_agc_bandwidth[] = { 43,44,45,46,47,48,49,50 };
-
-static u16 dib3000mb_agc_bandwidth_low[]  =
-	{ 2088, 10, 2088, 10, 3448, 5, 3448, 5 };
-static u16 dib3000mb_agc_bandwidth_high[] =
-	{ 2349,  5, 2349,  5, 2586, 2, 2586, 2 };
-
-/*
- * lock0 definition (coff_lock)
- */
-#define DIB3000MB_REG_LOCK0_MASK		(    51)
-#define DIB3000MB_LOCK0_DEFAULT				(     4)
-
-/*
- * lock1 definition (cpil_lock)
- * for auto search
- * which values hide behind the lock masks
- */
-#define DIB3000MB_REG_LOCK1_MASK		(    52)
-#define DIB3000MB_LOCK1_SEARCH_4			(0x0004)
-#define DIB3000MB_LOCK1_SEARCH_2048			(0x0800)
-#define DIB3000MB_LOCK1_DEFAULT				(0x0001)
-
-/*
- * lock2 definition (fec_lock) */
-#define DIB3000MB_REG_LOCK2_MASK		(    53)
-#define DIB3000MB_LOCK2_DEFAULT				(0x0080)
-
-/*
- * SEQ ? what was that again ... :)
- * changes when, inversion, guard time and fft is
- * either automatically detected or not
- */
-#define DIB3000MB_REG_SEQ				(    54)
-
-/* bandwidth */
-static u16 dib3000mb_reg_bandwidth[] = { 55,56,57,58,59,60,61,62,63,64,65,66,67 };
-static u16 dib3000mb_bandwidth_6mhz[] =
-	{ 0, 33, 53312, 112, 46635, 563, 36565, 0, 1000, 0, 1010, 1, 45264 };
-
-static u16 dib3000mb_bandwidth_7mhz[] =
-	{ 0, 28, 64421,  96, 39973, 483,  3255, 0, 1000, 0, 1010, 1, 45264 };
-
-static u16 dib3000mb_bandwidth_8mhz[] =
-	{ 0, 25, 23600,  84, 34976, 422, 43808, 0, 1000, 0, 1010, 1, 45264 };
-
-#define DIB3000MB_REG_UNK_68				(    68)
-#define DIB3000MB_UNK_68						(     0)
-
-#define DIB3000MB_REG_UNK_69				(    69)
-#define DIB3000MB_UNK_69						(     0)
-
-#define DIB3000MB_REG_UNK_71				(    71)
-#define DIB3000MB_UNK_71						(     0)
-
-#define DIB3000MB_REG_UNK_77				(    77)
-#define DIB3000MB_UNK_77						(     6)
-
-#define DIB3000MB_REG_UNK_78				(    78)
-#define DIB3000MB_UNK_78						(0x0080)
-
-/* isi */
-#define DIB3000MB_REG_ISI				(    79)
-#define DIB3000MB_ISI_ACTIVATE				(     0)
-#define DIB3000MB_ISI_INHIBIT				(     1)
-
-/* sync impovement */
-#define DIB3000MB_REG_SYNC_IMPROVEMENT	(    84)
-#define DIB3000MB_SYNC_IMPROVE_2K_1_8		(     3)
-#define DIB3000MB_SYNC_IMPROVE_DEFAULT		(     0)
-
-/* phase noise compensation inhibition */
-#define DIB3000MB_REG_PHASE_NOISE		(    87)
-#define DIB3000MB_PHASE_NOISE_DEFAULT	(     0)
-
-#define DIB3000MB_REG_UNK_92				(    92)
-#define DIB3000MB_UNK_92						(0x0080)
-
-#define DIB3000MB_REG_UNK_96				(    96)
-#define DIB3000MB_UNK_96						(0x0010)
-
-#define DIB3000MB_REG_UNK_97				(    97)
-#define DIB3000MB_UNK_97						(0x0009)
-
-/* mobile mode ??? */
-#define DIB3000MB_REG_MOBILE_MODE		(   101)
-#define DIB3000MB_MOBILE_MODE_ON			(     1)
-#define DIB3000MB_MOBILE_MODE_OFF			(     0)
-
-#define DIB3000MB_REG_UNK_106			(   106)
-#define DIB3000MB_UNK_106					(0x0080)
-
-#define DIB3000MB_REG_UNK_107			(   107)
-#define DIB3000MB_UNK_107					(0x0080)
-
-#define DIB3000MB_REG_UNK_108			(   108)
-#define DIB3000MB_UNK_108					(0x0080)
-
-/* fft */
-#define DIB3000MB_REG_UNK_121			(   121)
-#define DIB3000MB_UNK_121_2K				(     7)
-#define DIB3000MB_UNK_121_DEFAULT			(     5)
-
-#define DIB3000MB_REG_UNK_122			(   122)
-#define DIB3000MB_UNK_122					(  2867)
-
-/* QAM for mobile mode */
-#define DIB3000MB_REG_MOBILE_MODE_QAM	(   126)
-#define DIB3000MB_MOBILE_MODE_QAM_64		(     3)
-#define DIB3000MB_MOBILE_MODE_QAM_QPSK_16	(     1)
-#define DIB3000MB_MOBILE_MODE_QAM_OFF		(     0)
-
-/*
- * data diversity when having more than one chip on-board
- * see also DIB3000MB_OUTPUT_MODE_DATA_DIVERSITY
- */
-#define DIB3000MB_REG_DATA_IN_DIVERSITY		(   127)
-#define DIB3000MB_DATA_DIVERSITY_IN_OFF			(     0)
-#define DIB3000MB_DATA_DIVERSITY_IN_ON			(     2)
-
-/* vit hrch */
-#define DIB3000MB_REG_VIT_HRCH			(   128)
-
-/* vit code rate */
-#define DIB3000MB_REG_VIT_CODE_RATE		(   129)
-
-/* vit select hp */
-#define DIB3000MB_REG_VIT_HP			(   130)
-
-/* time frame for Bit-Error-Rate calculation */
-#define DIB3000MB_REG_BERLEN			(   135)
-#define DIB3000MB_BERLEN_LONG				(     0)
-#define DIB3000MB_BERLEN_DEFAULT			(     1)
-#define DIB3000MB_BERLEN_MEDIUM				(     2)
-#define DIB3000MB_BERLEN_SHORT				(     3)
-
-/* 142 - 152 FIFO parameters
- * which is what ?
- */
-
-#define DIB3000MB_REG_FIFO_142			(   142)
-#define DIB3000MB_FIFO_142					(     0)
-
-/* MPEG2 TS output mode */
-#define DIB3000MB_REG_MPEG2_OUT_MODE	(   143)
-#define DIB3000MB_MPEG2_OUT_MODE_204		(     0)
-#define DIB3000MB_MPEG2_OUT_MODE_188		(     1)
-
-#define DIB3000MB_REG_PID_PARSE			(   144)
-#define DIB3000MB_PID_PARSE_INHIBIT		(     0)
-#define DIB3000MB_PID_PARSE_ACTIVATE	(     1)
-
-#define DIB3000MB_REG_FIFO				(   145)
-#define DIB3000MB_FIFO_INHIBIT				(     1)
-#define DIB3000MB_FIFO_ACTIVATE				(     0)
-
-#define DIB3000MB_REG_FIFO_146			(   146)
-#define DIB3000MB_FIFO_146					(     3)
-
-#define DIB3000MB_REG_FIFO_147			(   147)
-#define DIB3000MB_FIFO_147					(0x0100)
-
-/*
- * pidfilter
- * it is not a hardware pidfilter but a filter which drops all pids
- * except the ones set. Necessary because of the limited USB1.1 bandwidth.
- * regs 153-168
- */
-
-#define DIB3000MB_REG_FIRST_PID			(   153)
-#define DIB3000MB_NUM_PIDS				(    16)
-
-/*
- * output mode
- * USB devices have to use 'slave'-mode
- * see also DIB3000MB_REG_ELECT_OUT_MODE
- */
-#define DIB3000MB_REG_OUTPUT_MODE		(   169)
-#define DIB3000MB_OUTPUT_MODE_GATED_CLK		(     0)
-#define DIB3000MB_OUTPUT_MODE_CONT_CLK		(     1)
-#define DIB3000MB_OUTPUT_MODE_SERIAL		(     2)
-#define DIB3000MB_OUTPUT_MODE_DATA_DIVERSITY	(     5)
-#define DIB3000MB_OUTPUT_MODE_SLAVE			(     6)
-
-/* irq event mask */
-#define DIB3000MB_REG_IRQ_EVENT_MASK		(   170)
-#define DIB3000MB_IRQ_EVENT_MASK				(     0)
-
-/* filter coefficients */
-static u16 dib3000mb_reg_filter_coeffs[] = {
-	171, 172, 173, 174, 175, 176, 177, 178,
-	179, 180, 181, 182, 183, 184, 185, 186,
-	188, 189, 190, 191, 192, 194
-};
-
-static u16 dib3000mb_filter_coeffs[] = {
-	 226,  160,   29,
-	 979,  998,   19,
-	  22, 1019, 1006,
-	1022,   12,    6,
-	1017, 1017,    3,
-	   6,       1019,
-	1021,    2,    3,
-	   1,          0,
-};
-
-/*
- * mobile algorithm (when you are moving with your device)
- * but not faster than 90 km/h
- */
-#define DIB3000MB_REG_MOBILE_ALGO		(   195)
-#define DIB3000MB_MOBILE_ALGO_ON			(     0)
-#define DIB3000MB_MOBILE_ALGO_OFF			(     1)
-
-/* multiple demodulators algorithm */
-#define DIB3000MB_REG_MULTI_DEMOD_MSB	(   206)
-#define DIB3000MB_REG_MULTI_DEMOD_LSB	(   207)
-
-/* terminator, no more demods */
-#define DIB3000MB_MULTI_DEMOD_MSB			( 32767)
-#define DIB3000MB_MULTI_DEMOD_LSB			(  4095)
-
-/* bring the device into a known  */
-#define DIB3000MB_REG_RESET_DEVICE		(  1024)
-#define DIB3000MB_RESET_DEVICE				(0x812c)
-#define DIB3000MB_RESET_DEVICE_RST			(     0)
-
-/* hardware clock configuration */
-#define DIB3000MB_REG_CLOCK				(  1027)
-#define DIB3000MB_CLOCK_DEFAULT				(0x9000)
-#define DIB3000MB_CLOCK_DIVERSITY			(0x92b0)
-
-/* power down config */
-#define DIB3000MB_REG_POWER_CONTROL		(  1028)
-#define DIB3000MB_POWER_DOWN				(     1)
-#define DIB3000MB_POWER_UP					(     0)
-
-/* electrical output mode */
-#define DIB3000MB_REG_ELECT_OUT_MODE	(  1029)
-#define DIB3000MB_ELECT_OUT_MODE_OFF		(     0)
-#define DIB3000MB_ELECT_OUT_MODE_ON			(     1)
-
-/* set the tuner i2c address */
-#define DIB3000MB_REG_TUNER				(  1089)
-
-/* monitoring registers (read only) */
-
-/* agc loop locked (size: 1) */
-#define DIB3000MB_REG_AGC_LOCK			(   324)
-
-/* agc power (size: 16) */
-#define DIB3000MB_REG_AGC_POWER			(   325)
-
-/* agc1 value (16) */
-#define DIB3000MB_REG_AGC1_VALUE		(   326)
-
-/* agc2 value (16) */
-#define DIB3000MB_REG_AGC2_VALUE		(   327)
-
-/* total RF power (16), can be used for signal strength */
-#define DIB3000MB_REG_RF_POWER			(   328)
-
-/* dds_frequency with offset (24) */
-#define DIB3000MB_REG_DDS_VALUE_MSB		(   339)
-#define DIB3000MB_REG_DDS_VALUE_LSB		(   340)
-
-/* timing offset signed (24) */
-#define DIB3000MB_REG_TIMING_OFFSET_MSB	(   341)
-#define DIB3000MB_REG_TIMING_OFFSET_LSB	(   342)
-
-/* fft start position (13) */
-#define DIB3000MB_REG_FFT_WINDOW_POS	(   353)
-
-/* carriers locked (1) */
-#define DIB3000MB_REG_CARRIER_LOCK		(   355)
-
-/* noise power (24) */
-#define DIB3000MB_REG_NOISE_POWER_MSB	(   372)
-#define DIB3000MB_REG_NOISE_POWER_LSB	(   373)
-
-#define DIB3000MB_REG_MOBILE_NOISE_MSB	(   374)
-#define DIB3000MB_REG_MOBILE_NOISE_LSB	(   375)
-
-/*
- * signal power (16), this and the above can be
- * used to calculate the signal/noise - ratio
- */
-#define DIB3000MB_REG_SIGNAL_POWER		(   380)
-
-/* mer (24) */
-#define DIB3000MB_REG_MER_MSB			(   381)
-#define DIB3000MB_REG_MER_LSB			(   382)
-
-/*
- * Transmission Parameter Signalling (TPS)
- * the following registers can be used to get TPS-information.
- * The values are according to the DVB-T standard.
- */
-
-/* TPS locked (1) */
-#define DIB3000MB_REG_TPS_LOCK			(   394)
-
-/* QAM from TPS (2) (values according to DIB3000MB_REG_QAM) */
-#define DIB3000MB_REG_TPS_QAM			(   398)
-
-/* hierarchy from TPS (1) */
-#define DIB3000MB_REG_TPS_HRCH			(   399)
-
-/* alpha from TPS (3) (values according to DIB3000MB_REG_VIT_ALPHA) */
-#define DIB3000MB_REG_TPS_VIT_ALPHA		(   400)
-
-/* code rate high priority from TPS (3) (values according to DIB3000MB_FEC_*) */
-#define DIB3000MB_REG_TPS_CODE_RATE_HP	(   401)
-
-/* code rate low priority from TPS (3) if DIB3000MB_REG_TPS_VIT_ALPHA */
-#define DIB3000MB_REG_TPS_CODE_RATE_LP	(   402)
-
-/* guard time from TPS (2) (values according to DIB3000MB_REG_GUARD_TIME */
-#define DIB3000MB_REG_TPS_GUARD_TIME	(   403)
-
-/* fft size from TPS (2) (values according to DIB3000MB_REG_FFT) */
-#define DIB3000MB_REG_TPS_FFT			(   404)
-
-/* cell id from TPS (16) */
-#define DIB3000MB_REG_TPS_CELL_ID		(   406)
-
-/* TPS (68) */
-#define DIB3000MB_REG_TPS_1				(   408)
-#define DIB3000MB_REG_TPS_2				(   409)
-#define DIB3000MB_REG_TPS_3				(   410)
-#define DIB3000MB_REG_TPS_4				(   411)
-#define DIB3000MB_REG_TPS_5				(   412)
-
-/* bit error rate (before RS correction) (21) */
-#define DIB3000MB_REG_BER_MSB			(   414)
-#define DIB3000MB_REG_BER_LSB			(   415)
-
-/* packet error rate (uncorrected TS packets) (16) */
-#define DIB3000MB_REG_PACKET_ERROR_RATE	(   417)
-
-/* uncorrected packet count (16) */
-#define DIB3000MB_REG_UNC				(   420)
-
-/* viterbi locked (1) */
-#define DIB3000MB_REG_VIT_LCK			(   421)
-
-/* viterbi inidcator (16) */
-#define DIB3000MB_REG_VIT_INDICATOR		(   422)
-
-/* transport stream sync lock (1) */
-#define DIB3000MB_REG_TS_SYNC_LOCK		(   423)
-
-/* transport stream RS lock (1) */
-#define DIB3000MB_REG_TS_RS_LOCK		(   424)
-
-/* lock mask 0 value (1) */
-#define DIB3000MB_REG_LOCK0_VALUE		(   425)
-
-/* lock mask 1 value (1) */
-#define DIB3000MB_REG_LOCK1_VALUE		(   426)
-
-/* lock mask 2 value (1) */
-#define DIB3000MB_REG_LOCK2_VALUE		(   427)
-
-/* interrupt pending for auto search */
-#define DIB3000MB_REG_AS_IRQ_PENDING	(   434)
-
-#endif
diff --git a/drivers/media/dvb/frontends/dib3000mc.c b/drivers/media/dvb/frontends/dib3000mc.c
deleted file mode 100644
index ffad181..0000000
--- a/drivers/media/dvb/frontends/dib3000mc.c
+++ /dev/null
@@ -1,940 +0,0 @@
-/*
- * Driver for DiBcom DiB3000MC/P-demodulator.
- *
- * Copyright (C) 2004-7 DiBcom (http://www.dibcom.fr/)
- * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
- *
- * This code is partially based on the previous dib3000mc.c .
- *
- * This program is free software; you can redistribute it and/or
- *	modify it under the terms of the GNU General Public License as
- *	published by the Free Software Foundation, version 2.
- */
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/i2c.h>
-
-#include "dvb_frontend.h"
-
-#include "dib3000mc.h"
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
-
-static int buggy_sfn_workaround;
-module_param(buggy_sfn_workaround, int, 0644);
-MODULE_PARM_DESC(buggy_sfn_workaround, "Enable work-around for buggy SFNs (default: 0)");
-
-#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB3000MC/P:"); printk(args); printk("\n"); } } while (0)
-
-struct dib3000mc_state {
-	struct dvb_frontend demod;
-	struct dib3000mc_config *cfg;
-
-	u8 i2c_addr;
-	struct i2c_adapter *i2c_adap;
-
-	struct dibx000_i2c_master i2c_master;
-
-	u32 timf;
-
-	u32 current_bandwidth;
-
-	u16 dev_id;
-
-	u8 sfn_workaround_active :1;
-};
-
-static u16 dib3000mc_read_word(struct dib3000mc_state *state, u16 reg)
-{
-	u8 wb[2] = { (reg >> 8) | 0x80, reg & 0xff };
-	u8 rb[2];
-	struct i2c_msg msg[2] = {
-		{ .addr = state->i2c_addr >> 1, .flags = 0,        .buf = wb, .len = 2 },
-		{ .addr = state->i2c_addr >> 1, .flags = I2C_M_RD, .buf = rb, .len = 2 },
-	};
-
-	if (i2c_transfer(state->i2c_adap, msg, 2) != 2)
-		dprintk("i2c read error on %d\n",reg);
-
-	return (rb[0] << 8) | rb[1];
-}
-
-static int dib3000mc_write_word(struct dib3000mc_state *state, u16 reg, u16 val)
-{
-	u8 b[4] = {
-		(reg >> 8) & 0xff, reg & 0xff,
-		(val >> 8) & 0xff, val & 0xff,
-	};
-	struct i2c_msg msg = {
-		.addr = state->i2c_addr >> 1, .flags = 0, .buf = b, .len = 4
-	};
-	return i2c_transfer(state->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
-}
-
-static int dib3000mc_identify(struct dib3000mc_state *state)
-{
-	u16 value;
-	if ((value = dib3000mc_read_word(state, 1025)) != 0x01b3) {
-		dprintk("-E-  DiB3000MC/P: wrong Vendor ID (read=0x%x)\n",value);
-		return -EREMOTEIO;
-	}
-
-	value = dib3000mc_read_word(state, 1026);
-	if (value != 0x3001 && value != 0x3002) {
-		dprintk("-E-  DiB3000MC/P: wrong Device ID (%x)\n",value);
-		return -EREMOTEIO;
-	}
-	state->dev_id = value;
-
-	dprintk("-I-  found DiB3000MC/P: %x\n",state->dev_id);
-
-	return 0;
-}
-
-static int dib3000mc_set_timing(struct dib3000mc_state *state, s16 nfft, u32 bw, u8 update_offset)
-{
-	u32 timf;
-
-	if (state->timf == 0) {
-		timf = 1384402; // default value for 8MHz
-		if (update_offset)
-			msleep(200); // first time we do an update
-	} else
-		timf = state->timf;
-
-	timf *= (bw / 1000);
-
-	if (update_offset) {
-		s16 tim_offs = dib3000mc_read_word(state, 416);
-
-		if (tim_offs &  0x2000)
-			tim_offs -= 0x4000;
-
-		if (nfft == TRANSMISSION_MODE_2K)
-			tim_offs *= 4;
-
-		timf += tim_offs;
-		state->timf = timf / (bw / 1000);
-	}
-
-	dprintk("timf: %d\n", timf);
-
-	dib3000mc_write_word(state, 23, (u16) (timf >> 16));
-	dib3000mc_write_word(state, 24, (u16) (timf      ) & 0xffff);
-
-	return 0;
-}
-
-static int dib3000mc_setup_pwm_state(struct dib3000mc_state *state)
-{
-	u16 reg_51, reg_52 = state->cfg->agc->setup & 0xfefb;
-    if (state->cfg->pwm3_inversion) {
-		reg_51 =  (2 << 14) | (0 << 10) | (7 << 6) | (2 << 2) | (2 << 0);
-		reg_52 |= (1 << 2);
-	} else {
-		reg_51 = (2 << 14) | (4 << 10) | (7 << 6) | (2 << 2) | (2 << 0);
-		reg_52 |= (1 << 8);
-	}
-	dib3000mc_write_word(state, 51, reg_51);
-	dib3000mc_write_word(state, 52, reg_52);
-
-    if (state->cfg->use_pwm3)
-		dib3000mc_write_word(state, 245, (1 << 3) | (1 << 0));
-	else
-		dib3000mc_write_word(state, 245, 0);
-
-    dib3000mc_write_word(state, 1040, 0x3);
-	return 0;
-}
-
-static int dib3000mc_set_output_mode(struct dib3000mc_state *state, int mode)
-{
-	int    ret = 0;
-	u16 fifo_threshold = 1792;
-	u16 outreg = 0;
-	u16 outmode = 0;
-	u16 elecout = 1;
-	u16 smo_reg = dib3000mc_read_word(state, 206) & 0x0010; /* keep the pid_parse bit */
-
-	dprintk("-I-  Setting output mode for demod %p to %d\n",
-			&state->demod, mode);
-
-	switch (mode) {
-		case OUTMODE_HIGH_Z:  // disable
-			elecout = 0;
-			break;
-		case OUTMODE_MPEG2_PAR_GATED_CLK:   // STBs with parallel gated clock
-			outmode = 0;
-			break;
-		case OUTMODE_MPEG2_PAR_CONT_CLK:    // STBs with parallel continues clock
-			outmode = 1;
-			break;
-		case OUTMODE_MPEG2_SERIAL:          // STBs with serial input
-			outmode = 2;
-			break;
-		case OUTMODE_MPEG2_FIFO:            // e.g. USB feeding
-			elecout = 3;
-			/*ADDR @ 206 :
-			P_smo_error_discard  [1;6:6] = 0
-			P_smo_rs_discard     [1;5:5] = 0
-			P_smo_pid_parse      [1;4:4] = 0
-			P_smo_fifo_flush     [1;3:3] = 0
-			P_smo_mode           [2;2:1] = 11
-			P_smo_ovf_prot       [1;0:0] = 0
-			*/
-			smo_reg |= 3 << 1;
-			fifo_threshold = 512;
-			outmode = 5;
-			break;
-		case OUTMODE_DIVERSITY:
-			outmode = 4;
-			elecout = 1;
-			break;
-		default:
-			dprintk("Unhandled output_mode passed to be set for demod %p\n",&state->demod);
-			outmode = 0;
-			break;
-	}
-
-	if ((state->cfg->output_mpeg2_in_188_bytes))
-		smo_reg |= (1 << 5); // P_smo_rs_discard     [1;5:5] = 1
-
-	outreg = dib3000mc_read_word(state, 244) & 0x07FF;
-	outreg |= (outmode << 11);
-	ret |= dib3000mc_write_word(state,  244, outreg);
-	ret |= dib3000mc_write_word(state,  206, smo_reg);   /*smo_ mode*/
-	ret |= dib3000mc_write_word(state,  207, fifo_threshold); /* synchronous fread */
-	ret |= dib3000mc_write_word(state, 1040, elecout);         /* P_out_cfg */
-	return ret;
-}
-
-static int dib3000mc_set_bandwidth(struct dib3000mc_state *state, u32 bw)
-{
-	u16 bw_cfg[6] = { 0 };
-	u16 imp_bw_cfg[3] = { 0 };
-	u16 reg;
-
-/* settings here are for 27.7MHz */
-	switch (bw) {
-		case 8000:
-			bw_cfg[0] = 0x0019; bw_cfg[1] = 0x5c30; bw_cfg[2] = 0x0054; bw_cfg[3] = 0x88a0; bw_cfg[4] = 0x01a6; bw_cfg[5] = 0xab20;
-			imp_bw_cfg[0] = 0x04db; imp_bw_cfg[1] = 0x00db; imp_bw_cfg[2] = 0x00b7;
-			break;
-
-		case 7000:
-			bw_cfg[0] = 0x001c; bw_cfg[1] = 0xfba5; bw_cfg[2] = 0x0060; bw_cfg[3] = 0x9c25; bw_cfg[4] = 0x01e3; bw_cfg[5] = 0x0cb7;
-			imp_bw_cfg[0] = 0x04c0; imp_bw_cfg[1] = 0x00c0; imp_bw_cfg[2] = 0x00a0;
-			break;
-
-		case 6000:
-			bw_cfg[0] = 0x0021; bw_cfg[1] = 0xd040; bw_cfg[2] = 0x0070; bw_cfg[3] = 0xb62b; bw_cfg[4] = 0x0233; bw_cfg[5] = 0x8ed5;
-			imp_bw_cfg[0] = 0x04a5; imp_bw_cfg[1] = 0x00a5; imp_bw_cfg[2] = 0x0089;
-			break;
-
-		case 5000:
-			bw_cfg[0] = 0x0028; bw_cfg[1] = 0x9380; bw_cfg[2] = 0x0087; bw_cfg[3] = 0x4100; bw_cfg[4] = 0x02a4; bw_cfg[5] = 0x4500;
-			imp_bw_cfg[0] = 0x0489; imp_bw_cfg[1] = 0x0089; imp_bw_cfg[2] = 0x0072;
-			break;
-
-		default: return -EINVAL;
-	}
-
-	for (reg = 6; reg < 12; reg++)
-		dib3000mc_write_word(state, reg, bw_cfg[reg - 6]);
-	dib3000mc_write_word(state, 12, 0x0000);
-	dib3000mc_write_word(state, 13, 0x03e8);
-	dib3000mc_write_word(state, 14, 0x0000);
-	dib3000mc_write_word(state, 15, 0x03f2);
-	dib3000mc_write_word(state, 16, 0x0001);
-	dib3000mc_write_word(state, 17, 0xb0d0);
-	// P_sec_len
-	dib3000mc_write_word(state, 18, 0x0393);
-	dib3000mc_write_word(state, 19, 0x8700);
-
-	for (reg = 55; reg < 58; reg++)
-		dib3000mc_write_word(state, reg, imp_bw_cfg[reg - 55]);
-
-	// Timing configuration
-	dib3000mc_set_timing(state, TRANSMISSION_MODE_2K, bw, 0);
-
-	return 0;
-}
-
-static u16 impulse_noise_val[29] =
-
-{
-	0x38, 0x6d9, 0x3f28, 0x7a7, 0x3a74, 0x196, 0x32a, 0x48c, 0x3ffe, 0x7f3,
-	0x2d94, 0x76, 0x53d, 0x3ff8, 0x7e3, 0x3320, 0x76, 0x5b3, 0x3feb, 0x7d2,
-	0x365e, 0x76, 0x48c, 0x3ffe, 0x5b3, 0x3feb, 0x76, 0x0000, 0xd
-};
-
-static void dib3000mc_set_impulse_noise(struct dib3000mc_state *state, u8 mode, s16 nfft)
-{
-	u16 i;
-	for (i = 58; i < 87; i++)
-		dib3000mc_write_word(state, i, impulse_noise_val[i-58]);
-
-	if (nfft == TRANSMISSION_MODE_8K) {
-		dib3000mc_write_word(state, 58, 0x3b);
-		dib3000mc_write_word(state, 84, 0x00);
-		dib3000mc_write_word(state, 85, 0x8200);
-	}
-
-	dib3000mc_write_word(state, 34, 0x1294);
-	dib3000mc_write_word(state, 35, 0x1ff8);
-	if (mode == 1)
-		dib3000mc_write_word(state, 55, dib3000mc_read_word(state, 55) | (1 << 10));
-}
-
-static int dib3000mc_init(struct dvb_frontend *demod)
-{
-	struct dib3000mc_state *state = demod->demodulator_priv;
-	struct dibx000_agc_config *agc = state->cfg->agc;
-
-	// Restart Configuration
-	dib3000mc_write_word(state, 1027, 0x8000);
-	dib3000mc_write_word(state, 1027, 0x0000);
-
-	// power up the demod + mobility configuration
-	dib3000mc_write_word(state, 140, 0x0000);
-	dib3000mc_write_word(state, 1031, 0);
-
-	if (state->cfg->mobile_mode) {
-		dib3000mc_write_word(state, 139,  0x0000);
-		dib3000mc_write_word(state, 141,  0x0000);
-		dib3000mc_write_word(state, 175,  0x0002);
-		dib3000mc_write_word(state, 1032, 0x0000);
-	} else {
-		dib3000mc_write_word(state, 139,  0x0001);
-		dib3000mc_write_word(state, 141,  0x0000);
-		dib3000mc_write_word(state, 175,  0x0000);
-		dib3000mc_write_word(state, 1032, 0x012C);
-	}
-	dib3000mc_write_word(state, 1033, 0x0000);
-
-	// P_clk_cfg
-	dib3000mc_write_word(state, 1037, 0x3130);
-
-	// other configurations
-
-	// P_ctrl_sfreq
-	dib3000mc_write_word(state, 33, (5 << 0));
-	dib3000mc_write_word(state, 88, (1 << 10) | (0x10 << 0));
-
-	// Phase noise control
-	// P_fft_phacor_inh, P_fft_phacor_cpe, P_fft_powrange
-	dib3000mc_write_word(state, 99, (1 << 9) | (0x20 << 0));
-
-	if (state->cfg->phase_noise_mode == 0)
-		dib3000mc_write_word(state, 111, 0x00);
-	else
-		dib3000mc_write_word(state, 111, 0x02);
-
-	// P_agc_global
-	dib3000mc_write_word(state, 50, 0x8000);
-
-	// agc setup misc
-	dib3000mc_setup_pwm_state(state);
-
-	// P_agc_counter_lock
-	dib3000mc_write_word(state, 53, 0x87);
-	// P_agc_counter_unlock
-	dib3000mc_write_word(state, 54, 0x87);
-
-	/* agc */
-	dib3000mc_write_word(state, 36, state->cfg->max_time);
-	dib3000mc_write_word(state, 37, (state->cfg->agc_command1 << 13) | (state->cfg->agc_command2 << 12) | (0x1d << 0));
-	dib3000mc_write_word(state, 38, state->cfg->pwm3_value);
-	dib3000mc_write_word(state, 39, state->cfg->ln_adc_level);
-
-	// set_agc_loop_Bw
-	dib3000mc_write_word(state, 40, 0x0179);
-	dib3000mc_write_word(state, 41, 0x03f0);
-
-	dib3000mc_write_word(state, 42, agc->agc1_max);
-	dib3000mc_write_word(state, 43, agc->agc1_min);
-	dib3000mc_write_word(state, 44, agc->agc2_max);
-	dib3000mc_write_word(state, 45, agc->agc2_min);
-	dib3000mc_write_word(state, 46, (agc->agc1_pt1 << 8) | agc->agc1_pt2);
-	dib3000mc_write_word(state, 47, (agc->agc1_slope1 << 8) | agc->agc1_slope2);
-	dib3000mc_write_word(state, 48, (agc->agc2_pt1 << 8) | agc->agc2_pt2);
-	dib3000mc_write_word(state, 49, (agc->agc2_slope1 << 8) | agc->agc2_slope2);
-
-// Begin: TimeOut registers
-	// P_pha3_thres
-	dib3000mc_write_word(state, 110, 3277);
-	// P_timf_alpha = 6, P_corm_alpha = 6, P_corm_thres = 0x80
-	dib3000mc_write_word(state,  26, 0x6680);
-	// lock_mask0
-	dib3000mc_write_word(state, 1, 4);
-	// lock_mask1
-	dib3000mc_write_word(state, 2, 4);
-	// lock_mask2
-	dib3000mc_write_word(state, 3, 0x1000);
-	// P_search_maxtrial=1
-	dib3000mc_write_word(state, 5, 1);
-
-	dib3000mc_set_bandwidth(state, 8000);
-
-	// div_lock_mask
-	dib3000mc_write_word(state,  4, 0x814);
-
-	dib3000mc_write_word(state, 21, (1 << 9) | 0x164);
-	dib3000mc_write_word(state, 22, 0x463d);
-
-	// Spurious rm cfg
-	// P_cspu_regul, P_cspu_win_cut
-	dib3000mc_write_word(state, 120, 0x200f);
-	// P_adp_selec_monit
-	dib3000mc_write_word(state, 134, 0);
-
-	// Fec cfg
-	dib3000mc_write_word(state, 195, 0x10);
-
-	// diversity register: P_dvsy_sync_wait..
-	dib3000mc_write_word(state, 180, 0x2FF0);
-
-	// Impulse noise configuration
-	dib3000mc_set_impulse_noise(state, 0, TRANSMISSION_MODE_8K);
-
-	// output mode set-up
-	dib3000mc_set_output_mode(state, OUTMODE_HIGH_Z);
-
-	/* close the i2c-gate */
-	dib3000mc_write_word(state, 769, (1 << 7) );
-
-	return 0;
-}
-
-static int dib3000mc_sleep(struct dvb_frontend *demod)
-{
-	struct dib3000mc_state *state = demod->demodulator_priv;
-
-	dib3000mc_write_word(state, 1031, 0xFFFF);
-	dib3000mc_write_word(state, 1032, 0xFFFF);
-	dib3000mc_write_word(state, 1033, 0xFFF0);
-
-    return 0;
-}
-
-static void dib3000mc_set_adp_cfg(struct dib3000mc_state *state, s16 qam)
-{
-	u16 cfg[4] = { 0 },reg;
-	switch (qam) {
-		case QPSK:
-			cfg[0] = 0x099a; cfg[1] = 0x7fae; cfg[2] = 0x0333; cfg[3] = 0x7ff0;
-			break;
-		case QAM_16:
-			cfg[0] = 0x023d; cfg[1] = 0x7fdf; cfg[2] = 0x00a4; cfg[3] = 0x7ff0;
-			break;
-		case QAM_64:
-			cfg[0] = 0x0148; cfg[1] = 0x7ff0; cfg[2] = 0x00a4; cfg[3] = 0x7ff8;
-			break;
-	}
-	for (reg = 129; reg < 133; reg++)
-		dib3000mc_write_word(state, reg, cfg[reg - 129]);
-}
-
-static void dib3000mc_set_channel_cfg(struct dib3000mc_state *state,
-				      struct dtv_frontend_properties *ch, u16 seq)
-{
-	u16 value;
-	u32 bw = BANDWIDTH_TO_KHZ(ch->bandwidth_hz);
-
-	dib3000mc_set_bandwidth(state, bw);
-	dib3000mc_set_timing(state, ch->transmission_mode, bw, 0);
-
-//	if (boost)
-//		dib3000mc_write_word(state, 100, (11 << 6) + 6);
-//	else
-		dib3000mc_write_word(state, 100, (16 << 6) + 9);
-
-	dib3000mc_write_word(state, 1027, 0x0800);
-	dib3000mc_write_word(state, 1027, 0x0000);
-
-	//Default cfg isi offset adp
-	dib3000mc_write_word(state, 26,  0x6680);
-	dib3000mc_write_word(state, 29,  0x1273);
-	dib3000mc_write_word(state, 33,       5);
-	dib3000mc_set_adp_cfg(state, QAM_16);
-	dib3000mc_write_word(state, 133,  15564);
-
-	dib3000mc_write_word(state, 12 , 0x0);
-	dib3000mc_write_word(state, 13 , 0x3e8);
-	dib3000mc_write_word(state, 14 , 0x0);
-	dib3000mc_write_word(state, 15 , 0x3f2);
-
-	dib3000mc_write_word(state, 93,0);
-	dib3000mc_write_word(state, 94,0);
-	dib3000mc_write_word(state, 95,0);
-	dib3000mc_write_word(state, 96,0);
-	dib3000mc_write_word(state, 97,0);
-	dib3000mc_write_word(state, 98,0);
-
-	dib3000mc_set_impulse_noise(state, 0, ch->transmission_mode);
-
-	value = 0;
-	switch (ch->transmission_mode) {
-		case TRANSMISSION_MODE_2K: value |= (0 << 7); break;
-		default:
-		case TRANSMISSION_MODE_8K: value |= (1 << 7); break;
-	}
-	switch (ch->guard_interval) {
-		case GUARD_INTERVAL_1_32: value |= (0 << 5); break;
-		case GUARD_INTERVAL_1_16: value |= (1 << 5); break;
-		case GUARD_INTERVAL_1_4:  value |= (3 << 5); break;
-		default:
-		case GUARD_INTERVAL_1_8:  value |= (2 << 5); break;
-	}
-	switch (ch->modulation) {
-		case QPSK:  value |= (0 << 3); break;
-		case QAM_16: value |= (1 << 3); break;
-		default:
-		case QAM_64: value |= (2 << 3); break;
-	}
-	switch (HIERARCHY_1) {
-		case HIERARCHY_2: value |= 2; break;
-		case HIERARCHY_4: value |= 4; break;
-		default:
-		case HIERARCHY_1: value |= 1; break;
-	}
-	dib3000mc_write_word(state, 0, value);
-	dib3000mc_write_word(state, 5, (1 << 8) | ((seq & 0xf) << 4));
-
-	value = 0;
-	if (ch->hierarchy == 1)
-		value |= (1 << 4);
-	if (1 == 1)
-		value |= 1;
-	switch ((ch->hierarchy == 0 || 1 == 1) ? ch->code_rate_HP : ch->code_rate_LP) {
-		case FEC_2_3: value |= (2 << 1); break;
-		case FEC_3_4: value |= (3 << 1); break;
-		case FEC_5_6: value |= (5 << 1); break;
-		case FEC_7_8: value |= (7 << 1); break;
-		default:
-		case FEC_1_2: value |= (1 << 1); break;
-	}
-	dib3000mc_write_word(state, 181, value);
-
-	// diversity synchro delay add 50% SFN margin
-	switch (ch->transmission_mode) {
-		case TRANSMISSION_MODE_8K: value = 256; break;
-		case TRANSMISSION_MODE_2K:
-		default: value = 64; break;
-	}
-	switch (ch->guard_interval) {
-		case GUARD_INTERVAL_1_16: value *= 2; break;
-		case GUARD_INTERVAL_1_8:  value *= 4; break;
-		case GUARD_INTERVAL_1_4:  value *= 8; break;
-		default:
-		case GUARD_INTERVAL_1_32: value *= 1; break;
-	}
-	value <<= 4;
-	value |= dib3000mc_read_word(state, 180) & 0x000f;
-	dib3000mc_write_word(state, 180, value);
-
-	// restart demod
-	value = dib3000mc_read_word(state, 0);
-	dib3000mc_write_word(state, 0, value | (1 << 9));
-	dib3000mc_write_word(state, 0, value);
-
-	msleep(30);
-
-	dib3000mc_set_impulse_noise(state, state->cfg->impulse_noise_mode, ch->transmission_mode);
-}
-
-static int dib3000mc_autosearch_start(struct dvb_frontend *demod)
-{
-	struct dtv_frontend_properties *chan = &demod->dtv_property_cache;
-	struct dib3000mc_state *state = demod->demodulator_priv;
-	u16 reg;
-//	u32 val;
-	struct dtv_frontend_properties schan;
-
-	schan = *chan;
-
-	/* TODO what is that ? */
-
-	/* a channel for autosearch */
-	schan.transmission_mode = TRANSMISSION_MODE_8K;
-	schan.guard_interval = GUARD_INTERVAL_1_32;
-	schan.modulation = QAM_64;
-	schan.code_rate_HP = FEC_2_3;
-	schan.code_rate_LP = FEC_2_3;
-	schan.hierarchy = 0;
-
-	dib3000mc_set_channel_cfg(state, &schan, 11);
-
-	reg = dib3000mc_read_word(state, 0);
-	dib3000mc_write_word(state, 0, reg | (1 << 8));
-	dib3000mc_read_word(state, 511);
-	dib3000mc_write_word(state, 0, reg);
-
-	return 0;
-}
-
-static int dib3000mc_autosearch_is_irq(struct dvb_frontend *demod)
-{
-	struct dib3000mc_state *state = demod->demodulator_priv;
-	u16 irq_pending = dib3000mc_read_word(state, 511);
-
-	if (irq_pending & 0x1) // failed
-		return 1;
-
-	if (irq_pending & 0x2) // succeeded
-		return 2;
-
-	return 0; // still pending
-}
-
-static int dib3000mc_tune(struct dvb_frontend *demod)
-{
-	struct dtv_frontend_properties *ch = &demod->dtv_property_cache;
-	struct dib3000mc_state *state = demod->demodulator_priv;
-
-	// ** configure demod **
-	dib3000mc_set_channel_cfg(state, ch, 0);
-
-	// activates isi
-	if (state->sfn_workaround_active) {
-		dprintk("SFN workaround is active\n");
-		dib3000mc_write_word(state, 29, 0x1273);
-		dib3000mc_write_word(state, 108, 0x4000); // P_pha3_force_pha_shift
-	} else {
-		dib3000mc_write_word(state, 29, 0x1073);
-		dib3000mc_write_word(state, 108, 0x0000); // P_pha3_force_pha_shift
-	}
-
-	dib3000mc_set_adp_cfg(state, (u8)ch->modulation);
-	if (ch->transmission_mode == TRANSMISSION_MODE_8K) {
-		dib3000mc_write_word(state, 26, 38528);
-		dib3000mc_write_word(state, 33, 8);
-	} else {
-		dib3000mc_write_word(state, 26, 30336);
-		dib3000mc_write_word(state, 33, 6);
-	}
-
-	if (dib3000mc_read_word(state, 509) & 0x80)
-		dib3000mc_set_timing(state, ch->transmission_mode,
-				     BANDWIDTH_TO_KHZ(ch->bandwidth_hz), 1);
-
-	return 0;
-}
-
-struct i2c_adapter * dib3000mc_get_tuner_i2c_master(struct dvb_frontend *demod, int gating)
-{
-	struct dib3000mc_state *st = demod->demodulator_priv;
-	return dibx000_get_i2c_adapter(&st->i2c_master, DIBX000_I2C_INTERFACE_TUNER, gating);
-}
-
-EXPORT_SYMBOL(dib3000mc_get_tuner_i2c_master);
-
-static int dib3000mc_get_frontend(struct dvb_frontend* fe)
-{
-	struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
-	struct dib3000mc_state *state = fe->demodulator_priv;
-	u16 tps = dib3000mc_read_word(state,458);
-
-	fep->inversion = INVERSION_AUTO;
-
-	fep->bandwidth_hz = state->current_bandwidth;
-
-	switch ((tps >> 8) & 0x1) {
-		case 0: fep->transmission_mode = TRANSMISSION_MODE_2K; break;
-		case 1: fep->transmission_mode = TRANSMISSION_MODE_8K; break;
-	}
-
-	switch (tps & 0x3) {
-		case 0: fep->guard_interval = GUARD_INTERVAL_1_32; break;
-		case 1: fep->guard_interval = GUARD_INTERVAL_1_16; break;
-		case 2: fep->guard_interval = GUARD_INTERVAL_1_8; break;
-		case 3: fep->guard_interval = GUARD_INTERVAL_1_4; break;
-	}
-
-	switch ((tps >> 13) & 0x3) {
-		case 0: fep->modulation = QPSK; break;
-		case 1: fep->modulation = QAM_16; break;
-		case 2:
-		default: fep->modulation = QAM_64; break;
-	}
-
-	/* as long as the frontend_param structure is fixed for hierarchical transmission I refuse to use it */
-	/* (tps >> 12) & 0x1 == hrch is used, (tps >> 9) & 0x7 == alpha */
-
-	fep->hierarchy = HIERARCHY_NONE;
-	switch ((tps >> 5) & 0x7) {
-		case 1: fep->code_rate_HP = FEC_1_2; break;
-		case 2: fep->code_rate_HP = FEC_2_3; break;
-		case 3: fep->code_rate_HP = FEC_3_4; break;
-		case 5: fep->code_rate_HP = FEC_5_6; break;
-		case 7:
-		default: fep->code_rate_HP = FEC_7_8; break;
-
-	}
-
-	switch ((tps >> 2) & 0x7) {
-		case 1: fep->code_rate_LP = FEC_1_2; break;
-		case 2: fep->code_rate_LP = FEC_2_3; break;
-		case 3: fep->code_rate_LP = FEC_3_4; break;
-		case 5: fep->code_rate_LP = FEC_5_6; break;
-		case 7:
-		default: fep->code_rate_LP = FEC_7_8; break;
-	}
-
-	return 0;
-}
-
-static int dib3000mc_set_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
-	struct dib3000mc_state *state = fe->demodulator_priv;
-	int ret;
-
-	dib3000mc_set_output_mode(state, OUTMODE_HIGH_Z);
-
-	state->current_bandwidth = fep->bandwidth_hz;
-	dib3000mc_set_bandwidth(state, BANDWIDTH_TO_KHZ(fep->bandwidth_hz));
-
-	/* maybe the parameter has been changed */
-	state->sfn_workaround_active = buggy_sfn_workaround;
-
-	if (fe->ops.tuner_ops.set_params) {
-		fe->ops.tuner_ops.set_params(fe);
-		msleep(100);
-	}
-
-	if (fep->transmission_mode  == TRANSMISSION_MODE_AUTO ||
-	    fep->guard_interval == GUARD_INTERVAL_AUTO ||
-	    fep->modulation     == QAM_AUTO ||
-	    fep->code_rate_HP   == FEC_AUTO) {
-		int i = 1000, found;
-
-		dib3000mc_autosearch_start(fe);
-		do {
-			msleep(1);
-			found = dib3000mc_autosearch_is_irq(fe);
-		} while (found == 0 && i--);
-
-		dprintk("autosearch returns: %d\n",found);
-		if (found == 0 || found == 1)
-			return 0; // no channel found
-
-		dib3000mc_get_frontend(fe);
-	}
-
-	ret = dib3000mc_tune(fe);
-
-	/* make this a config parameter */
-	dib3000mc_set_output_mode(state, OUTMODE_MPEG2_FIFO);
-	return ret;
-}
-
-static int dib3000mc_read_status(struct dvb_frontend *fe, fe_status_t *stat)
-{
-	struct dib3000mc_state *state = fe->demodulator_priv;
-	u16 lock = dib3000mc_read_word(state, 509);
-
-	*stat = 0;
-
-	if (lock & 0x8000)
-		*stat |= FE_HAS_SIGNAL;
-	if (lock & 0x3000)
-		*stat |= FE_HAS_CARRIER;
-	if (lock & 0x0100)
-		*stat |= FE_HAS_VITERBI;
-	if (lock & 0x0010)
-		*stat |= FE_HAS_SYNC;
-	if (lock & 0x0008)
-		*stat |= FE_HAS_LOCK;
-
-	return 0;
-}
-
-static int dib3000mc_read_ber(struct dvb_frontend *fe, u32 *ber)
-{
-	struct dib3000mc_state *state = fe->demodulator_priv;
-	*ber = (dib3000mc_read_word(state, 500) << 16) | dib3000mc_read_word(state, 501);
-	return 0;
-}
-
-static int dib3000mc_read_unc_blocks(struct dvb_frontend *fe, u32 *unc)
-{
-	struct dib3000mc_state *state = fe->demodulator_priv;
-	*unc = dib3000mc_read_word(state, 508);
-	return 0;
-}
-
-static int dib3000mc_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
-{
-	struct dib3000mc_state *state = fe->demodulator_priv;
-	u16 val = dib3000mc_read_word(state, 392);
-	*strength = 65535 - val;
-	return 0;
-}
-
-static int dib3000mc_read_snr(struct dvb_frontend* fe, u16 *snr)
-{
-	*snr = 0x0000;
-	return 0;
-}
-
-static int dib3000mc_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
-{
-	tune->min_delay_ms = 1000;
-	return 0;
-}
-
-static void dib3000mc_release(struct dvb_frontend *fe)
-{
-	struct dib3000mc_state *state = fe->demodulator_priv;
-	dibx000_exit_i2c_master(&state->i2c_master);
-	kfree(state);
-}
-
-int dib3000mc_pid_control(struct dvb_frontend *fe, int index, int pid,int onoff)
-{
-	struct dib3000mc_state *state = fe->demodulator_priv;
-	dib3000mc_write_word(state, 212 + index,  onoff ? (1 << 13) | pid : 0);
-	return 0;
-}
-EXPORT_SYMBOL(dib3000mc_pid_control);
-
-int dib3000mc_pid_parse(struct dvb_frontend *fe, int onoff)
-{
-	struct dib3000mc_state *state = fe->demodulator_priv;
-	u16 tmp = dib3000mc_read_word(state, 206) & ~(1 << 4);
-	tmp |= (onoff << 4);
-	return dib3000mc_write_word(state, 206, tmp);
-}
-EXPORT_SYMBOL(dib3000mc_pid_parse);
-
-void dib3000mc_set_config(struct dvb_frontend *fe, struct dib3000mc_config *cfg)
-{
-	struct dib3000mc_state *state = fe->demodulator_priv;
-	state->cfg = cfg;
-}
-EXPORT_SYMBOL(dib3000mc_set_config);
-
-int dib3000mc_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib3000mc_config cfg[])
-{
-	struct dib3000mc_state *dmcst;
-	int k;
-	u8 new_addr;
-
-	static u8 DIB3000MC_I2C_ADDRESS[] = {20,22,24,26};
-
-	dmcst = kzalloc(sizeof(struct dib3000mc_state), GFP_KERNEL);
-	if (dmcst == NULL)
-		return -ENOMEM;
-
-	dmcst->i2c_adap = i2c;
-
-	for (k = no_of_demods-1; k >= 0; k--) {
-		dmcst->cfg = &cfg[k];
-
-		/* designated i2c address */
-		new_addr          = DIB3000MC_I2C_ADDRESS[k];
-		dmcst->i2c_addr = new_addr;
-		if (dib3000mc_identify(dmcst) != 0) {
-			dmcst->i2c_addr = default_addr;
-			if (dib3000mc_identify(dmcst) != 0) {
-				dprintk("-E-  DiB3000P/MC #%d: not identified\n", k);
-				kfree(dmcst);
-				return -ENODEV;
-			}
-		}
-
-		dib3000mc_set_output_mode(dmcst, OUTMODE_MPEG2_PAR_CONT_CLK);
-
-		// set new i2c address and force divstr (Bit 1) to value 0 (Bit 0)
-		dib3000mc_write_word(dmcst, 1024, (new_addr << 3) | 0x1);
-		dmcst->i2c_addr = new_addr;
-	}
-
-	for (k = 0; k < no_of_demods; k++) {
-		dmcst->cfg = &cfg[k];
-		dmcst->i2c_addr = DIB3000MC_I2C_ADDRESS[k];
-
-		dib3000mc_write_word(dmcst, 1024, dmcst->i2c_addr << 3);
-
-		/* turn off data output */
-		dib3000mc_set_output_mode(dmcst, OUTMODE_HIGH_Z);
-	}
-
-	kfree(dmcst);
-	return 0;
-}
-EXPORT_SYMBOL(dib3000mc_i2c_enumeration);
-
-static struct dvb_frontend_ops dib3000mc_ops;
-
-struct dvb_frontend * dib3000mc_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib3000mc_config *cfg)
-{
-	struct dvb_frontend *demod;
-	struct dib3000mc_state *st;
-	st = kzalloc(sizeof(struct dib3000mc_state), GFP_KERNEL);
-	if (st == NULL)
-		return NULL;
-
-	st->cfg = cfg;
-	st->i2c_adap = i2c_adap;
-	st->i2c_addr = i2c_addr;
-
-	demod                   = &st->demod;
-	demod->demodulator_priv = st;
-	memcpy(&st->demod.ops, &dib3000mc_ops, sizeof(struct dvb_frontend_ops));
-
-	if (dib3000mc_identify(st) != 0)
-		goto error;
-
-	dibx000_init_i2c_master(&st->i2c_master, DIB3000MC, st->i2c_adap, st->i2c_addr);
-
-	dib3000mc_write_word(st, 1037, 0x3130);
-
-	return demod;
-
-error:
-	kfree(st);
-	return NULL;
-}
-EXPORT_SYMBOL(dib3000mc_attach);
-
-static struct dvb_frontend_ops dib3000mc_ops = {
-	.delsys = { SYS_DVBT },
-	.info = {
-		.name = "DiBcom 3000MC/P",
-		.frequency_min      = 44250000,
-		.frequency_max      = 867250000,
-		.frequency_stepsize = 62500,
-		.caps = FE_CAN_INVERSION_AUTO |
-			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_FEC_AUTO |
-			FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
-			FE_CAN_TRANSMISSION_MODE_AUTO |
-			FE_CAN_GUARD_INTERVAL_AUTO |
-			FE_CAN_RECOVER |
-			FE_CAN_HIERARCHY_AUTO,
-	},
-
-	.release              = dib3000mc_release,
-
-	.init                 = dib3000mc_init,
-	.sleep                = dib3000mc_sleep,
-
-	.set_frontend         = dib3000mc_set_frontend,
-	.get_tune_settings    = dib3000mc_fe_get_tune_settings,
-	.get_frontend         = dib3000mc_get_frontend,
-
-	.read_status          = dib3000mc_read_status,
-	.read_ber             = dib3000mc_read_ber,
-	.read_signal_strength = dib3000mc_read_signal_strength,
-	.read_snr             = dib3000mc_read_snr,
-	.read_ucblocks        = dib3000mc_read_unc_blocks,
-};
-
-MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
-MODULE_DESCRIPTION("Driver for the DiBcom 3000MC/P COFDM demodulator");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/dib3000mc.h b/drivers/media/dvb/frontends/dib3000mc.h
deleted file mode 100644
index d75ffad..0000000
--- a/drivers/media/dvb/frontends/dib3000mc.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Driver for DiBcom DiB3000MC/P-demodulator.
- *
- * Copyright (C) 2004-6 DiBcom (http://www.dibcom.fr/)
- * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher\@desy.de)
- *
- * This code is partially based on the previous dib3000mc.c .
- *
- * This program is free software; you can redistribute it and/or
- *	modify it under the terms of the GNU General Public License as
- *	published by the Free Software Foundation, version 2.
- */
-#ifndef DIB3000MC_H
-#define DIB3000MC_H
-
-#include "dibx000_common.h"
-
-struct dib3000mc_config {
-	struct dibx000_agc_config *agc;
-
-	u8 phase_noise_mode;
-	u8 impulse_noise_mode;
-
-	u8  pwm3_inversion;
-	u8  use_pwm3;
-	u16 pwm3_value;
-
-	u16 max_time;
-	u16 ln_adc_level;
-
-	u8 agc_command1 :1;
-	u8 agc_command2 :1;
-
-	u8 mobile_mode;
-
-	u8 output_mpeg2_in_188_bytes;
-};
-
-#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);
-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)
-{
-	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_pid_control(struct dvb_frontend *fe, int index, int pid,int onoff);
-extern int dib3000mc_pid_parse(struct dvb_frontend *fe, int onoff);
-
-extern void dib3000mc_set_config(struct dvb_frontend *, struct dib3000mc_config *);
-
-#endif
diff --git a/drivers/media/dvb/frontends/dib7000m.c b/drivers/media/dvb/frontends/dib7000m.c
deleted file mode 100644
index 148bf79..0000000
--- a/drivers/media/dvb/frontends/dib7000m.c
+++ /dev/null
@@ -1,1473 +0,0 @@
-/*
- * Linux-DVB Driver for DiBcom's DiB7000M and
- *              first generation DiB7000P-demodulator-family.
- *
- * Copyright (C) 2005-7 DiBcom (http://www.dibcom.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, version 2.
- */
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/i2c.h>
-#include <linux/mutex.h>
-
-#include "dvb_frontend.h"
-
-#include "dib7000m.h"
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
-
-#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB7000M: "); printk(args); printk("\n"); } } while (0)
-
-struct dib7000m_state {
-	struct dvb_frontend demod;
-    struct dib7000m_config cfg;
-
-	u8 i2c_addr;
-	struct i2c_adapter   *i2c_adap;
-
-	struct dibx000_i2c_master i2c_master;
-
-/* offset is 1 in case of the 7000MC */
-	u8 reg_offs;
-
-	u16 wbd_ref;
-
-	u8 current_band;
-	u32 current_bandwidth;
-	struct dibx000_agc_config *current_agc;
-	u32 timf;
-	u32 timf_default;
-	u32 internal_clk;
-
-	u8 div_force_off : 1;
-	u8 div_state : 1;
-	u16 div_sync_wait;
-
-	u16 revision;
-
-	u8 agc_state;
-
-	/* for the I2C transfer */
-	struct i2c_msg msg[2];
-	u8 i2c_write_buffer[4];
-	u8 i2c_read_buffer[2];
-	struct mutex i2c_buffer_lock;
-};
-
-enum dib7000m_power_mode {
-	DIB7000M_POWER_ALL = 0,
-
-	DIB7000M_POWER_NO,
-	DIB7000M_POWER_INTERF_ANALOG_AGC,
-	DIB7000M_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD,
-	DIB7000M_POWER_COR4_CRY_ESRAM_MOUT_NUD,
-	DIB7000M_POWER_INTERFACE_ONLY,
-};
-
-static u16 dib7000m_read_word(struct dib7000m_state *state, u16 reg)
-{
-	u16 ret;
-
-	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
-		dprintk("could not acquire lock");
-		return 0;
-	}
-
-	state->i2c_write_buffer[0] = (reg >> 8) | 0x80;
-	state->i2c_write_buffer[1] = reg & 0xff;
-
-	memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
-	state->msg[0].addr = state->i2c_addr >> 1;
-	state->msg[0].flags = 0;
-	state->msg[0].buf = state->i2c_write_buffer;
-	state->msg[0].len = 2;
-	state->msg[1].addr = state->i2c_addr >> 1;
-	state->msg[1].flags = I2C_M_RD;
-	state->msg[1].buf = state->i2c_read_buffer;
-	state->msg[1].len = 2;
-
-	if (i2c_transfer(state->i2c_adap, state->msg, 2) != 2)
-		dprintk("i2c read error on %d",reg);
-
-	ret = (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
-	mutex_unlock(&state->i2c_buffer_lock);
-
-	return ret;
-}
-
-static int dib7000m_write_word(struct dib7000m_state *state, u16 reg, u16 val)
-{
-	int ret;
-
-	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
-		dprintk("could not acquire lock");
-		return -EINVAL;
-	}
-
-	state->i2c_write_buffer[0] = (reg >> 8) & 0xff;
-	state->i2c_write_buffer[1] = reg & 0xff;
-	state->i2c_write_buffer[2] = (val >> 8) & 0xff;
-	state->i2c_write_buffer[3] = val & 0xff;
-
-	memset(&state->msg[0], 0, sizeof(struct i2c_msg));
-	state->msg[0].addr = state->i2c_addr >> 1;
-	state->msg[0].flags = 0;
-	state->msg[0].buf = state->i2c_write_buffer;
-	state->msg[0].len = 4;
-
-	ret = (i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ?
-			-EREMOTEIO : 0);
-	mutex_unlock(&state->i2c_buffer_lock);
-	return ret;
-}
-static void dib7000m_write_tab(struct dib7000m_state *state, u16 *buf)
-{
-	u16 l = 0, r, *n;
-	n = buf;
-	l = *n++;
-	while (l) {
-		r = *n++;
-
-		if (state->reg_offs && (r >= 112 && r <= 331)) // compensate for 7000MC
-			r++;
-
-		do {
-			dib7000m_write_word(state, r, *n++);
-			r++;
-		} while (--l);
-		l = *n++;
-	}
-}
-
-static int dib7000m_set_output_mode(struct dib7000m_state *state, int mode)
-{
-	int    ret = 0;
-	u16 outreg, fifo_threshold, smo_mode,
-		sram = 0x0005; /* by default SRAM output is disabled */
-
-	outreg = 0;
-	fifo_threshold = 1792;
-	smo_mode = (dib7000m_read_word(state, 294 + state->reg_offs) & 0x0010) | (1 << 1);
-
-	dprintk( "setting output mode for demod %p to %d", &state->demod, mode);
-
-	switch (mode) {
-		case OUTMODE_MPEG2_PAR_GATED_CLK:   // STBs with parallel gated clock
-			outreg = (1 << 10);  /* 0x0400 */
-			break;
-		case OUTMODE_MPEG2_PAR_CONT_CLK:    // STBs with parallel continues clock
-			outreg = (1 << 10) | (1 << 6); /* 0x0440 */
-			break;
-		case OUTMODE_MPEG2_SERIAL:          // STBs with serial input
-			outreg = (1 << 10) | (2 << 6) | (0 << 1); /* 0x0482 */
-			break;
-		case OUTMODE_DIVERSITY:
-			if (state->cfg.hostbus_diversity)
-				outreg = (1 << 10) | (4 << 6); /* 0x0500 */
-			else
-				sram   |= 0x0c00;
-			break;
-		case OUTMODE_MPEG2_FIFO:            // e.g. USB feeding
-			smo_mode |= (3 << 1);
-			fifo_threshold = 512;
-			outreg = (1 << 10) | (5 << 6);
-			break;
-		case OUTMODE_HIGH_Z:  // disable
-			outreg = 0;
-			break;
-		default:
-			dprintk( "Unhandled output_mode passed to be set for demod %p",&state->demod);
-			break;
-	}
-
-	if (state->cfg.output_mpeg2_in_188_bytes)
-		smo_mode |= (1 << 5) ;
-
-	ret |= dib7000m_write_word(state,  294 + state->reg_offs, smo_mode);
-	ret |= dib7000m_write_word(state,  295 + state->reg_offs, fifo_threshold); /* synchronous fread */
-	ret |= dib7000m_write_word(state, 1795, outreg);
-	ret |= dib7000m_write_word(state, 1805, sram);
-
-	if (state->revision == 0x4003) {
-		u16 clk_cfg1 = dib7000m_read_word(state, 909) & 0xfffd;
-		if (mode == OUTMODE_DIVERSITY)
-			clk_cfg1 |= (1 << 1); // P_O_CLK_en
-		dib7000m_write_word(state, 909, clk_cfg1);
-	}
-	return ret;
-}
-
-static void dib7000m_set_power_mode(struct dib7000m_state *state, enum dib7000m_power_mode mode)
-{
-	/* by default everything is going to be powered off */
-	u16 reg_903 = 0xffff, reg_904 = 0xffff, reg_905 = 0xffff, reg_906  = 0x3fff;
-	u8  offset = 0;
-
-	/* now, depending on the requested mode, we power on */
-	switch (mode) {
-		/* power up everything in the demod */
-		case DIB7000M_POWER_ALL:
-			reg_903 = 0x0000; reg_904 = 0x0000; reg_905 = 0x0000; reg_906 = 0x0000;
-			break;
-
-		/* just leave power on the control-interfaces: GPIO and (I2C or SDIO or SRAM) */
-		case DIB7000M_POWER_INTERFACE_ONLY: /* TODO power up either SDIO or I2C or SRAM */
-			reg_905 &= ~((1 << 7) | (1 << 6) | (1 << 5) | (1 << 2));
-			break;
-
-		case DIB7000M_POWER_INTERF_ANALOG_AGC:
-			reg_903 &= ~((1 << 15) | (1 << 14) | (1 << 11) | (1 << 10));
-			reg_905 &= ~((1 << 7) | (1 << 6) | (1 << 5) | (1 << 4) | (1 << 2));
-			reg_906 &= ~((1 << 0));
-			break;
-
-		case DIB7000M_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD:
-			reg_903 = 0x0000; reg_904 = 0x801f; reg_905 = 0x0000; reg_906 = 0x0000;
-			break;
-
-		case DIB7000M_POWER_COR4_CRY_ESRAM_MOUT_NUD:
-			reg_903 = 0x0000; reg_904 = 0x8000; reg_905 = 0x010b; reg_906 = 0x0000;
-			break;
-		case DIB7000M_POWER_NO:
-			break;
-	}
-
-	/* always power down unused parts */
-	if (!state->cfg.mobile_mode)
-		reg_904 |= (1 << 7) | (1 << 6) | (1 << 4) | (1 << 2) | (1 << 1);
-
-	/* P_sdio_select_clk = 0 on MC and after*/
-	if (state->revision != 0x4000)
-		reg_906 <<= 1;
-
-	if (state->revision == 0x4003)
-		offset = 1;
-
-	dib7000m_write_word(state, 903 + offset, reg_903);
-	dib7000m_write_word(state, 904 + offset, reg_904);
-	dib7000m_write_word(state, 905 + offset, reg_905);
-	dib7000m_write_word(state, 906 + offset, reg_906);
-}
-
-static int dib7000m_set_adc_state(struct dib7000m_state *state, enum dibx000_adc_states no)
-{
-	int ret = 0;
-	u16 reg_913 = dib7000m_read_word(state, 913),
-	       reg_914 = dib7000m_read_word(state, 914);
-
-	switch (no) {
-		case DIBX000_SLOW_ADC_ON:
-			reg_914 |= (1 << 1) | (1 << 0);
-			ret |= dib7000m_write_word(state, 914, reg_914);
-			reg_914 &= ~(1 << 1);
-			break;
-
-		case DIBX000_SLOW_ADC_OFF:
-			reg_914 |=  (1 << 1) | (1 << 0);
-			break;
-
-		case DIBX000_ADC_ON:
-			if (state->revision == 0x4000) { // workaround for PA/MA
-				// power-up ADC
-				dib7000m_write_word(state, 913, 0);
-				dib7000m_write_word(state, 914, reg_914 & 0x3);
-				// power-down bandgag
-				dib7000m_write_word(state, 913, (1 << 15));
-				dib7000m_write_word(state, 914, reg_914 & 0x3);
-			}
-
-			reg_913 &= 0x0fff;
-			reg_914 &= 0x0003;
-			break;
-
-		case DIBX000_ADC_OFF: // leave the VBG voltage on
-			reg_913 |= (1 << 14) | (1 << 13) | (1 << 12);
-			reg_914 |= (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2);
-			break;
-
-		case DIBX000_VBG_ENABLE:
-			reg_913 &= ~(1 << 15);
-			break;
-
-		case DIBX000_VBG_DISABLE:
-			reg_913 |= (1 << 15);
-			break;
-
-		default:
-			break;
-	}
-
-//	dprintk( "913: %x, 914: %x", reg_913, reg_914);
-	ret |= dib7000m_write_word(state, 913, reg_913);
-	ret |= dib7000m_write_word(state, 914, reg_914);
-
-	return ret;
-}
-
-static int dib7000m_set_bandwidth(struct dib7000m_state *state, u32 bw)
-{
-	u32 timf;
-
-	if (!bw)
-		bw = 8000;
-
-	// store the current bandwidth for later use
-	state->current_bandwidth = bw;
-
-	if (state->timf == 0) {
-		dprintk( "using default timf");
-		timf = state->timf_default;
-	} else {
-		dprintk( "using updated timf");
-		timf = state->timf;
-	}
-
-	timf = timf * (bw / 50) / 160;
-
-	dib7000m_write_word(state, 23, (u16) ((timf >> 16) & 0xffff));
-	dib7000m_write_word(state, 24, (u16) ((timf      ) & 0xffff));
-
-	return 0;
-}
-
-static int dib7000m_set_diversity_in(struct dvb_frontend *demod, int onoff)
-{
-	struct dib7000m_state *state = demod->demodulator_priv;
-
-	if (state->div_force_off) {
-		dprintk( "diversity combination deactivated - forced by COFDM parameters");
-		onoff = 0;
-	}
-	state->div_state = (u8)onoff;
-
-	if (onoff) {
-		dib7000m_write_word(state, 263 + state->reg_offs, 6);
-		dib7000m_write_word(state, 264 + state->reg_offs, 6);
-		dib7000m_write_word(state, 266 + state->reg_offs, (state->div_sync_wait << 4) | (1 << 2) | (2 << 0));
-	} else {
-		dib7000m_write_word(state, 263 + state->reg_offs, 1);
-		dib7000m_write_word(state, 264 + state->reg_offs, 0);
-		dib7000m_write_word(state, 266 + state->reg_offs, 0);
-	}
-
-	return 0;
-}
-
-static int dib7000m_sad_calib(struct dib7000m_state *state)
-{
-
-/* internal */
-//	dib7000m_write_word(state, 928, (3 << 14) | (1 << 12) | (524 << 0)); // sampling clock of the SAD is writting in set_bandwidth
-	dib7000m_write_word(state, 929, (0 << 1) | (0 << 0));
-	dib7000m_write_word(state, 930, 776); // 0.625*3.3 / 4096
-
-	/* do the calibration */
-	dib7000m_write_word(state, 929, (1 << 0));
-	dib7000m_write_word(state, 929, (0 << 0));
-
-	msleep(1);
-
-	return 0;
-}
-
-static void dib7000m_reset_pll_common(struct dib7000m_state *state, const struct dibx000_bandwidth_config *bw)
-{
-	dib7000m_write_word(state, 18, (u16) (((bw->internal*1000) >> 16) & 0xffff));
-	dib7000m_write_word(state, 19, (u16) ( (bw->internal*1000)        & 0xffff));
-	dib7000m_write_word(state, 21, (u16) ( (bw->ifreq          >> 16) & 0xffff));
-	dib7000m_write_word(state, 22, (u16) (  bw->ifreq                 & 0xffff));
-
-	dib7000m_write_word(state, 928, bw->sad_cfg);
-}
-
-static void dib7000m_reset_pll(struct dib7000m_state *state)
-{
-	const struct dibx000_bandwidth_config *bw = state->cfg.bw;
-	u16 reg_907,reg_910;
-
-	/* default */
-	reg_907 = (bw->pll_bypass << 15) | (bw->modulo << 7) |
-		(bw->ADClkSrc << 6) | (bw->IO_CLK_en_core << 5) | (bw->bypclk_div << 2) |
-		(bw->enable_refdiv << 1) | (0 << 0);
-	reg_910 = (((bw->pll_ratio >> 6) & 0x3) << 3) | (bw->pll_range << 1) | bw->pll_reset;
-
-	// for this oscillator frequency should be 30 MHz for the Master (default values in the board_parameters give that value)
-	// this is only working only for 30 MHz crystals
-	if (!state->cfg.quartz_direct) {
-		reg_910 |= (1 << 5);  // forcing the predivider to 1
-
-		// if the previous front-end is baseband, its output frequency is 15 MHz (prev freq divided by 2)
-		if(state->cfg.input_clk_is_div_2)
-			reg_907 |= (16 << 9);
-		else // otherwise the previous front-end puts out its input (default 30MHz) - no extra division necessary
-			reg_907 |= (8 << 9);
-	} else {
-		reg_907 |= (bw->pll_ratio & 0x3f) << 9;
-		reg_910 |= (bw->pll_prediv << 5);
-	}
-
-	dib7000m_write_word(state, 910, reg_910); // pll cfg
-	dib7000m_write_word(state, 907, reg_907); // clk cfg0
-	dib7000m_write_word(state, 908, 0x0006);  // clk_cfg1
-
-	dib7000m_reset_pll_common(state, bw);
-}
-
-static void dib7000mc_reset_pll(struct dib7000m_state *state)
-{
-	const struct dibx000_bandwidth_config *bw = state->cfg.bw;
-	u16 clk_cfg1;
-
-	// clk_cfg0
-	dib7000m_write_word(state, 907, (bw->pll_prediv << 8) | (bw->pll_ratio << 0));
-
-	// clk_cfg1
-	//dib7000m_write_word(state, 908, (1 << 14) | (3 << 12) |(0 << 11) |
-	clk_cfg1 = (0 << 14) | (3 << 12) |(0 << 11) |
-			(bw->IO_CLK_en_core << 10) | (bw->bypclk_div << 5) | (bw->enable_refdiv << 4) |
-			(1 << 3) | (bw->pll_range << 1) | (bw->pll_reset << 0);
-	dib7000m_write_word(state, 908, clk_cfg1);
-	clk_cfg1 = (clk_cfg1 & 0xfff7) | (bw->pll_bypass << 3);
-	dib7000m_write_word(state, 908, clk_cfg1);
-
-	// smpl_cfg
-	dib7000m_write_word(state, 910, (1 << 12) | (2 << 10) | (bw->modulo << 8) | (bw->ADClkSrc << 7));
-
-	dib7000m_reset_pll_common(state, bw);
-}
-
-static int dib7000m_reset_gpio(struct dib7000m_state *st)
-{
-	/* reset the GPIOs */
-	dib7000m_write_word(st, 773, st->cfg.gpio_dir);
-	dib7000m_write_word(st, 774, st->cfg.gpio_val);
-
-	/* TODO 782 is P_gpio_od */
-
-	dib7000m_write_word(st, 775, st->cfg.gpio_pwm_pos);
-
-	dib7000m_write_word(st, 780, st->cfg.pwm_freq_div);
-	return 0;
-}
-
-static u16 dib7000m_defaults_common[] =
-
-{
-	// auto search configuration
-	3, 2,
-		0x0004,
-		0x1000,
-		0x0814,
-
-	12, 6,
-		0x001b,
-		0x7740,
-		0x005b,
-		0x8d80,
-		0x01c9,
-		0xc380,
-		0x0000,
-		0x0080,
-		0x0000,
-		0x0090,
-		0x0001,
-		0xd4c0,
-
-	1, 26,
-		0x6680, // P_corm_thres Lock algorithms configuration
-
-	1, 170,
-		0x0410, // P_palf_alpha_regul, P_palf_filter_freeze, P_palf_filter_on
-
-	8, 173,
-		0,
-		0,
-		0,
-		0,
-		0,
-		0,
-		0,
-		0,
-
-	1, 182,
-		8192, // P_fft_nb_to_cut
-
-	2, 195,
-		0x0ccd, // P_pha3_thres
-		0,      // P_cti_use_cpe, P_cti_use_prog
-
-	1, 205,
-		0x200f, // P_cspu_regul, P_cspu_win_cut
-
-	5, 214,
-		0x023d, // P_adp_regul_cnt
-		0x00a4, // P_adp_noise_cnt
-		0x00a4, // P_adp_regul_ext
-		0x7ff0, // P_adp_noise_ext
-		0x3ccc, // P_adp_fil
-
-	1, 226,
-		0, // P_2d_byp_ti_num
-
-	1, 255,
-		0x800, // P_equal_thres_wgn
-
-	1, 263,
-		0x0001,
-
-	1, 281,
-		0x0010, // P_fec_*
-
-	1, 294,
-		0x0062, // P_smo_mode, P_smo_rs_discard, P_smo_fifo_flush, P_smo_pid_parse, P_smo_error_discard
-
-	0
-};
-
-static u16 dib7000m_defaults[] =
-
-{
-	/* set ADC level to -16 */
-	11, 76,
-		(1 << 13) - 825 - 117,
-		(1 << 13) - 837 - 117,
-		(1 << 13) - 811 - 117,
-		(1 << 13) - 766 - 117,
-		(1 << 13) - 737 - 117,
-		(1 << 13) - 693 - 117,
-		(1 << 13) - 648 - 117,
-		(1 << 13) - 619 - 117,
-		(1 << 13) - 575 - 117,
-		(1 << 13) - 531 - 117,
-		(1 << 13) - 501 - 117,
-
-	// Tuner IO bank: max drive (14mA)
-	1, 912,
-		0x2c8a,
-
-	1, 1817,
-		1,
-
-	0,
-};
-
-static int dib7000m_demod_reset(struct dib7000m_state *state)
-{
-	dib7000m_set_power_mode(state, DIB7000M_POWER_ALL);
-
-	/* always leave the VBG voltage on - it consumes almost nothing but takes a long time to start */
-	dib7000m_set_adc_state(state, DIBX000_VBG_ENABLE);
-
-	/* restart all parts */
-	dib7000m_write_word(state,  898, 0xffff);
-	dib7000m_write_word(state,  899, 0xffff);
-	dib7000m_write_word(state,  900, 0xff0f);
-	dib7000m_write_word(state,  901, 0xfffc);
-
-	dib7000m_write_word(state,  898, 0);
-	dib7000m_write_word(state,  899, 0);
-	dib7000m_write_word(state,  900, 0);
-	dib7000m_write_word(state,  901, 0);
-
-	if (state->revision == 0x4000)
-		dib7000m_reset_pll(state);
-	else
-		dib7000mc_reset_pll(state);
-
-	if (dib7000m_reset_gpio(state) != 0)
-		dprintk( "GPIO reset was not successful.");
-
-	if (dib7000m_set_output_mode(state, OUTMODE_HIGH_Z) != 0)
-		dprintk( "OUTPUT_MODE could not be reset.");
-
-	/* unforce divstr regardless whether i2c enumeration was done or not */
-	dib7000m_write_word(state, 1794, dib7000m_read_word(state, 1794) & ~(1 << 1) );
-
-	dib7000m_set_bandwidth(state, 8000);
-
-	dib7000m_set_adc_state(state, DIBX000_SLOW_ADC_ON);
-	dib7000m_sad_calib(state);
-	dib7000m_set_adc_state(state, DIBX000_SLOW_ADC_OFF);
-
-	if (state->cfg.dvbt_mode)
-		dib7000m_write_word(state, 1796, 0x0); // select DVB-T output
-
-	if (state->cfg.mobile_mode)
-		dib7000m_write_word(state, 261 + state->reg_offs, 2);
-	else
-		dib7000m_write_word(state, 224 + state->reg_offs, 1);
-
-	// P_iqc_alpha_pha, P_iqc_alpha_amp, P_iqc_dcc_alpha, ...
-	if(state->cfg.tuner_is_baseband)
-		dib7000m_write_word(state, 36, 0x0755);
-	else
-		dib7000m_write_word(state, 36, 0x1f55);
-
-	// P_divclksel=3 P_divbitsel=1
-	if (state->revision == 0x4000)
-		dib7000m_write_word(state, 909, (3 << 10) | (1 << 6));
-	else
-		dib7000m_write_word(state, 909, (3 << 4) | 1);
-
-	dib7000m_write_tab(state, dib7000m_defaults_common);
-	dib7000m_write_tab(state, dib7000m_defaults);
-
-	dib7000m_set_power_mode(state, DIB7000M_POWER_INTERFACE_ONLY);
-
-	state->internal_clk = state->cfg.bw->internal;
-
-	return 0;
-}
-
-static void dib7000m_restart_agc(struct dib7000m_state *state)
-{
-	// P_restart_iqc & P_restart_agc
-	dib7000m_write_word(state, 898, 0x0c00);
-	dib7000m_write_word(state, 898, 0x0000);
-}
-
-static int dib7000m_agc_soft_split(struct dib7000m_state *state)
-{
-	u16 agc,split_offset;
-
-	if(!state->current_agc || !state->current_agc->perform_agc_softsplit || state->current_agc->split.max == 0)
-		return 0;
-
-	// n_agc_global
-	agc = dib7000m_read_word(state, 390);
-
-	if (agc > state->current_agc->split.min_thres)
-		split_offset = state->current_agc->split.min;
-	else if (agc < state->current_agc->split.max_thres)
-		split_offset = state->current_agc->split.max;
-	else
-		split_offset = state->current_agc->split.max *
-			(agc - state->current_agc->split.min_thres) /
-			(state->current_agc->split.max_thres - state->current_agc->split.min_thres);
-
-	dprintk( "AGC split_offset: %d",split_offset);
-
-	// P_agc_force_split and P_agc_split_offset
-	return dib7000m_write_word(state, 103, (dib7000m_read_word(state, 103) & 0xff00) | split_offset);
-}
-
-static int dib7000m_update_lna(struct dib7000m_state *state)
-{
-	u16 dyn_gain;
-
-	if (state->cfg.update_lna) {
-		// read dyn_gain here (because it is demod-dependent and not fe)
-		dyn_gain = dib7000m_read_word(state, 390);
-
-		if (state->cfg.update_lna(&state->demod,dyn_gain)) { // LNA has changed
-			dib7000m_restart_agc(state);
-			return 1;
-		}
-	}
-	return 0;
-}
-
-static int dib7000m_set_agc_config(struct dib7000m_state *state, u8 band)
-{
-	struct dibx000_agc_config *agc = NULL;
-	int i;
-	if (state->current_band == band && state->current_agc != NULL)
-		return 0;
-	state->current_band = band;
-
-	for (i = 0; i < state->cfg.agc_config_count; i++)
-		if (state->cfg.agc[i].band_caps & band) {
-			agc = &state->cfg.agc[i];
-			break;
-		}
-
-	if (agc == NULL) {
-		dprintk( "no valid AGC configuration found for band 0x%02x",band);
-		return -EINVAL;
-	}
-
-	state->current_agc = agc;
-
-	/* AGC */
-	dib7000m_write_word(state, 72 ,  agc->setup);
-	dib7000m_write_word(state, 73 ,  agc->inv_gain);
-	dib7000m_write_word(state, 74 ,  agc->time_stabiliz);
-	dib7000m_write_word(state, 97 , (agc->alpha_level << 12) | agc->thlock);
-
-	// Demod AGC loop configuration
-	dib7000m_write_word(state, 98, (agc->alpha_mant << 5) | agc->alpha_exp);
-	dib7000m_write_word(state, 99, (agc->beta_mant  << 6) | agc->beta_exp);
-
-	dprintk( "WBD: ref: %d, sel: %d, active: %d, alpha: %d",
-		state->wbd_ref != 0 ? state->wbd_ref : agc->wbd_ref, agc->wbd_sel, !agc->perform_agc_softsplit, agc->wbd_sel);
-
-	/* AGC continued */
-	if (state->wbd_ref != 0)
-		dib7000m_write_word(state, 102, state->wbd_ref);
-	else // use default
-		dib7000m_write_word(state, 102, agc->wbd_ref);
-
-	dib7000m_write_word(state, 103, (agc->wbd_alpha << 9) | (agc->perform_agc_softsplit << 8) );
-	dib7000m_write_word(state, 104,  agc->agc1_max);
-	dib7000m_write_word(state, 105,  agc->agc1_min);
-	dib7000m_write_word(state, 106,  agc->agc2_max);
-	dib7000m_write_word(state, 107,  agc->agc2_min);
-	dib7000m_write_word(state, 108, (agc->agc1_pt1 << 8) | agc->agc1_pt2 );
-	dib7000m_write_word(state, 109, (agc->agc1_slope1 << 8) | agc->agc1_slope2);
-	dib7000m_write_word(state, 110, (agc->agc2_pt1 << 8) | agc->agc2_pt2);
-	dib7000m_write_word(state, 111, (agc->agc2_slope1 << 8) | agc->agc2_slope2);
-
-	if (state->revision > 0x4000) { // settings for the MC
-		dib7000m_write_word(state, 71,   agc->agc1_pt3);
-//		dprintk( "929: %x %d %d",
-//			(dib7000m_read_word(state, 929) & 0xffe3) | (agc->wbd_inv << 4) | (agc->wbd_sel << 2), agc->wbd_inv, agc->wbd_sel);
-		dib7000m_write_word(state, 929, (dib7000m_read_word(state, 929) & 0xffe3) | (agc->wbd_inv << 4) | (agc->wbd_sel << 2));
-	} else {
-		// wrong default values
-		u16 b[9] = { 676, 696, 717, 737, 758, 778, 799, 819, 840 };
-		for (i = 0; i < 9; i++)
-			dib7000m_write_word(state, 88 + i, b[i]);
-	}
-	return 0;
-}
-
-static void dib7000m_update_timf(struct dib7000m_state *state)
-{
-	u32 timf = (dib7000m_read_word(state, 436) << 16) | dib7000m_read_word(state, 437);
-	state->timf = timf * 160 / (state->current_bandwidth / 50);
-	dib7000m_write_word(state, 23, (u16) (timf >> 16));
-	dib7000m_write_word(state, 24, (u16) (timf & 0xffff));
-	dprintk( "updated timf_frequency: %d (default: %d)",state->timf, state->timf_default);
-}
-
-static int dib7000m_agc_startup(struct dvb_frontend *demod)
-{
-	struct dtv_frontend_properties *ch = &demod->dtv_property_cache;
-	struct dib7000m_state *state = demod->demodulator_priv;
-	u16 cfg_72 = dib7000m_read_word(state, 72);
-	int ret = -1;
-	u8 *agc_state = &state->agc_state;
-	u8 agc_split;
-
-	switch (state->agc_state) {
-		case 0:
-			// set power-up level: interf+analog+AGC
-			dib7000m_set_power_mode(state, DIB7000M_POWER_INTERF_ANALOG_AGC);
-			dib7000m_set_adc_state(state, DIBX000_ADC_ON);
-
-			if (dib7000m_set_agc_config(state, BAND_OF_FREQUENCY(ch->frequency/1000)) != 0)
-				return -1;
-
-			ret = 7; /* ADC power up */
-			(*agc_state)++;
-			break;
-
-		case 1:
-			/* AGC initialization */
-			if (state->cfg.agc_control)
-				state->cfg.agc_control(&state->demod, 1);
-
-			dib7000m_write_word(state, 75, 32768);
-			if (!state->current_agc->perform_agc_softsplit) {
-				/* we are using the wbd - so slow AGC startup */
-				dib7000m_write_word(state, 103, 1 << 8); /* force 0 split on WBD and restart AGC */
-				(*agc_state)++;
-				ret = 5;
-			} else {
-				/* default AGC startup */
-				(*agc_state) = 4;
-				/* wait AGC rough lock time */
-				ret = 7;
-			}
-
-			dib7000m_restart_agc(state);
-			break;
-
-		case 2: /* fast split search path after 5sec */
-			dib7000m_write_word(state,  72, cfg_72 | (1 << 4)); /* freeze AGC loop */
-			dib7000m_write_word(state, 103, 2 << 9);            /* fast split search 0.25kHz */
-			(*agc_state)++;
-			ret = 14;
-			break;
-
-	case 3: /* split search ended */
-			agc_split = (u8)dib7000m_read_word(state, 392); /* store the split value for the next time */
-			dib7000m_write_word(state, 75, dib7000m_read_word(state, 390)); /* set AGC gain start value */
-
-			dib7000m_write_word(state, 72,  cfg_72 & ~(1 << 4));   /* std AGC loop */
-			dib7000m_write_word(state, 103, (state->current_agc->wbd_alpha << 9) | agc_split); /* standard split search */
-
-			dib7000m_restart_agc(state);
-
-			dprintk( "SPLIT %p: %hd", demod, agc_split);
-
-			(*agc_state)++;
-			ret = 5;
-			break;
-
-		case 4: /* LNA startup */
-			/* wait AGC accurate lock time */
-			ret = 7;
-
-			if (dib7000m_update_lna(state))
-				// wait only AGC rough lock time
-				ret = 5;
-			else
-				(*agc_state)++;
-			break;
-
-		case 5:
-			dib7000m_agc_soft_split(state);
-
-			if (state->cfg.agc_control)
-				state->cfg.agc_control(&state->demod, 0);
-
-			(*agc_state)++;
-			break;
-
-		default:
-			break;
-	}
-	return ret;
-}
-
-static void dib7000m_set_channel(struct dib7000m_state *state, struct dtv_frontend_properties *ch,
-				 u8 seq)
-{
-	u16 value, est[4];
-
-	dib7000m_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->bandwidth_hz));
-
-	/* nfft, guard, qam, alpha */
-	value = 0;
-	switch (ch->transmission_mode) {
-		case TRANSMISSION_MODE_2K: value |= (0 << 7); break;
-		case TRANSMISSION_MODE_4K: value |= (2 << 7); break;
-		default:
-		case TRANSMISSION_MODE_8K: value |= (1 << 7); break;
-	}
-	switch (ch->guard_interval) {
-		case GUARD_INTERVAL_1_32: value |= (0 << 5); break;
-		case GUARD_INTERVAL_1_16: value |= (1 << 5); break;
-		case GUARD_INTERVAL_1_4:  value |= (3 << 5); break;
-		default:
-		case GUARD_INTERVAL_1_8:  value |= (2 << 5); break;
-	}
-	switch (ch->modulation) {
-		case QPSK:  value |= (0 << 3); break;
-		case QAM_16: value |= (1 << 3); break;
-		default:
-		case QAM_64: value |= (2 << 3); break;
-	}
-	switch (HIERARCHY_1) {
-		case HIERARCHY_2: value |= 2; break;
-		case HIERARCHY_4: value |= 4; break;
-		default:
-		case HIERARCHY_1: value |= 1; break;
-	}
-	dib7000m_write_word(state, 0, value);
-	dib7000m_write_word(state, 5, (seq << 4));
-
-	/* P_dintl_native, P_dintlv_inv, P_hrch, P_code_rate, P_select_hp */
-	value = 0;
-	if (1 != 0)
-		value |= (1 << 6);
-	if (ch->hierarchy == 1)
-		value |= (1 << 4);
-	if (1 == 1)
-		value |= 1;
-	switch ((ch->hierarchy == 0 || 1 == 1) ? ch->code_rate_HP : ch->code_rate_LP) {
-		case FEC_2_3: value |= (2 << 1); break;
-		case FEC_3_4: value |= (3 << 1); break;
-		case FEC_5_6: value |= (5 << 1); break;
-		case FEC_7_8: value |= (7 << 1); break;
-		default:
-		case FEC_1_2: value |= (1 << 1); break;
-	}
-	dib7000m_write_word(state, 267 + state->reg_offs, value);
-
-	/* offset loop parameters */
-
-	/* P_timf_alpha = 6, P_corm_alpha=6, P_corm_thres=0x80 */
-	dib7000m_write_word(state, 26, (6 << 12) | (6 << 8) | 0x80);
-
-	/* P_ctrl_inh_cor=0, P_ctrl_alpha_cor=4, P_ctrl_inh_isi=1, P_ctrl_alpha_isi=3, P_ctrl_inh_cor4=1, P_ctrl_alpha_cor4=3 */
-	dib7000m_write_word(state, 29, (0 << 14) | (4 << 10) | (1 << 9) | (3 << 5) | (1 << 4) | (0x3));
-
-	/* P_ctrl_freeze_pha_shift=0, P_ctrl_pha_off_max=3 */
-	dib7000m_write_word(state, 32, (0 << 4) | 0x3);
-
-	/* P_ctrl_sfreq_inh=0, P_ctrl_sfreq_step=5 */
-	dib7000m_write_word(state, 33, (0 << 4) | 0x5);
-
-	/* P_dvsy_sync_wait */
-	switch (ch->transmission_mode) {
-		case TRANSMISSION_MODE_8K: value = 256; break;
-		case TRANSMISSION_MODE_4K: value = 128; break;
-		case TRANSMISSION_MODE_2K:
-		default: value = 64; break;
-	}
-	switch (ch->guard_interval) {
-		case GUARD_INTERVAL_1_16: value *= 2; break;
-		case GUARD_INTERVAL_1_8:  value *= 4; break;
-		case GUARD_INTERVAL_1_4:  value *= 8; break;
-		default:
-		case GUARD_INTERVAL_1_32: value *= 1; break;
-	}
-	state->div_sync_wait = (value * 3) / 2 + 32; // add 50% SFN margin + compensate for one DVSY-fifo TODO
-
-	/* deactive the possibility of diversity reception if extended interleave - not for 7000MC */
-	/* P_dvsy_sync_mode = 0, P_dvsy_sync_enable=1, P_dvcb_comb_mode=2 */
-	if (1 == 1 || state->revision > 0x4000)
-		state->div_force_off = 0;
-	else
-		state->div_force_off = 1;
-	dib7000m_set_diversity_in(&state->demod, state->div_state);
-
-	/* channel estimation fine configuration */
-	switch (ch->modulation) {
-		case QAM_64:
-			est[0] = 0x0148;       /* P_adp_regul_cnt 0.04 */
-			est[1] = 0xfff0;       /* P_adp_noise_cnt -0.002 */
-			est[2] = 0x00a4;       /* P_adp_regul_ext 0.02 */
-			est[3] = 0xfff8;       /* P_adp_noise_ext -0.001 */
-			break;
-		case QAM_16:
-			est[0] = 0x023d;       /* P_adp_regul_cnt 0.07 */
-			est[1] = 0xffdf;       /* P_adp_noise_cnt -0.004 */
-			est[2] = 0x00a4;       /* P_adp_regul_ext 0.02 */
-			est[3] = 0xfff0;       /* P_adp_noise_ext -0.002 */
-			break;
-		default:
-			est[0] = 0x099a;       /* P_adp_regul_cnt 0.3 */
-			est[1] = 0xffae;       /* P_adp_noise_cnt -0.01 */
-			est[2] = 0x0333;       /* P_adp_regul_ext 0.1 */
-			est[3] = 0xfff8;       /* P_adp_noise_ext -0.002 */
-			break;
-	}
-	for (value = 0; value < 4; value++)
-		dib7000m_write_word(state, 214 + value + state->reg_offs, est[value]);
-
-	// set power-up level: autosearch
-	dib7000m_set_power_mode(state, DIB7000M_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD);
-}
-
-static int dib7000m_autosearch_start(struct dvb_frontend *demod)
-{
-	struct dtv_frontend_properties *ch = &demod->dtv_property_cache;
-	struct dib7000m_state *state = demod->demodulator_priv;
-	struct dtv_frontend_properties schan;
-	int ret = 0;
-	u32 value, factor;
-
-	schan = *ch;
-
-	schan.modulation = QAM_64;
-	schan.guard_interval        = GUARD_INTERVAL_1_32;
-	schan.transmission_mode         = TRANSMISSION_MODE_8K;
-	schan.code_rate_HP = FEC_2_3;
-	schan.code_rate_LP = FEC_3_4;
-	schan.hierarchy    = 0;
-
-	dib7000m_set_channel(state, &schan, 7);
-
-	factor = BANDWIDTH_TO_KHZ(schan.bandwidth_hz);
-	if (factor >= 5000)
-		factor = 1;
-	else
-		factor = 6;
-
-	// always use the setting for 8MHz here lock_time for 7,6 MHz are longer
-	value = 30 * state->internal_clk * factor;
-	ret |= dib7000m_write_word(state, 6,  (u16) ((value >> 16) & 0xffff)); // lock0 wait time
-	ret |= dib7000m_write_word(state, 7,  (u16)  (value        & 0xffff)); // lock0 wait time
-	value = 100 * state->internal_clk * factor;
-	ret |= dib7000m_write_word(state, 8,  (u16) ((value >> 16) & 0xffff)); // lock1 wait time
-	ret |= dib7000m_write_word(state, 9,  (u16)  (value        & 0xffff)); // lock1 wait time
-	value = 500 * state->internal_clk * factor;
-	ret |= dib7000m_write_word(state, 10, (u16) ((value >> 16) & 0xffff)); // lock2 wait time
-	ret |= dib7000m_write_word(state, 11, (u16)  (value        & 0xffff)); // lock2 wait time
-
-	// start search
-	value = dib7000m_read_word(state, 0);
-	ret |= dib7000m_write_word(state, 0, (u16) (value | (1 << 9)));
-
-	/* clear n_irq_pending */
-	if (state->revision == 0x4000)
-		dib7000m_write_word(state, 1793, 0);
-	else
-		dib7000m_read_word(state, 537);
-
-	ret |= dib7000m_write_word(state, 0, (u16) value);
-
-	return ret;
-}
-
-static int dib7000m_autosearch_irq(struct dib7000m_state *state, u16 reg)
-{
-	u16 irq_pending = dib7000m_read_word(state, reg);
-
-	if (irq_pending & 0x1) { // failed
-		dprintk( "autosearch failed");
-		return 1;
-	}
-
-	if (irq_pending & 0x2) { // succeeded
-		dprintk( "autosearch succeeded");
-		return 2;
-	}
-	return 0; // still pending
-}
-
-static int dib7000m_autosearch_is_irq(struct dvb_frontend *demod)
-{
-	struct dib7000m_state *state = demod->demodulator_priv;
-	if (state->revision == 0x4000)
-		return dib7000m_autosearch_irq(state, 1793);
-	else
-		return dib7000m_autosearch_irq(state, 537);
-}
-
-static int dib7000m_tune(struct dvb_frontend *demod)
-{
-	struct dtv_frontend_properties *ch = &demod->dtv_property_cache;
-	struct dib7000m_state *state = demod->demodulator_priv;
-	int ret = 0;
-	u16 value;
-
-	// we are already tuned - just resuming from suspend
-	if (ch != NULL)
-		dib7000m_set_channel(state, ch, 0);
-	else
-		return -EINVAL;
-
-	// restart demod
-	ret |= dib7000m_write_word(state, 898, 0x4000);
-	ret |= dib7000m_write_word(state, 898, 0x0000);
-	msleep(45);
-
-	dib7000m_set_power_mode(state, DIB7000M_POWER_COR4_CRY_ESRAM_MOUT_NUD);
-	/* P_ctrl_inh_cor=0, P_ctrl_alpha_cor=4, P_ctrl_inh_isi=0, P_ctrl_alpha_isi=3, P_ctrl_inh_cor4=1, P_ctrl_alpha_cor4=3 */
-	ret |= dib7000m_write_word(state, 29, (0 << 14) | (4 << 10) | (0 << 9) | (3 << 5) | (1 << 4) | (0x3));
-
-	// never achieved a lock before - wait for timfreq to update
-	if (state->timf == 0)
-		msleep(200);
-
-	//dump_reg(state);
-	/* P_timf_alpha, P_corm_alpha=6, P_corm_thres=0x80 */
-	value = (6 << 8) | 0x80;
-	switch (ch->transmission_mode) {
-		case TRANSMISSION_MODE_2K: value |= (7 << 12); break;
-		case TRANSMISSION_MODE_4K: value |= (8 << 12); break;
-		default:
-		case TRANSMISSION_MODE_8K: value |= (9 << 12); break;
-	}
-	ret |= dib7000m_write_word(state, 26, value);
-
-	/* P_ctrl_freeze_pha_shift=0, P_ctrl_pha_off_max */
-	value = (0 << 4);
-	switch (ch->transmission_mode) {
-		case TRANSMISSION_MODE_2K: value |= 0x6; break;
-		case TRANSMISSION_MODE_4K: value |= 0x7; break;
-		default:
-		case TRANSMISSION_MODE_8K: value |= 0x8; break;
-	}
-	ret |= dib7000m_write_word(state, 32, value);
-
-	/* P_ctrl_sfreq_inh=0, P_ctrl_sfreq_step */
-	value = (0 << 4);
-	switch (ch->transmission_mode) {
-		case TRANSMISSION_MODE_2K: value |= 0x6; break;
-		case TRANSMISSION_MODE_4K: value |= 0x7; break;
-		default:
-		case TRANSMISSION_MODE_8K: value |= 0x8; break;
-	}
-	ret |= dib7000m_write_word(state, 33,  value);
-
-	// we achieved a lock - it's time to update the timf freq
-	if ((dib7000m_read_word(state, 535) >> 6)  & 0x1)
-		dib7000m_update_timf(state);
-
-	dib7000m_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->bandwidth_hz));
-	return ret;
-}
-
-static int dib7000m_wakeup(struct dvb_frontend *demod)
-{
-	struct dib7000m_state *state = demod->demodulator_priv;
-
-	dib7000m_set_power_mode(state, DIB7000M_POWER_ALL);
-
-	if (dib7000m_set_adc_state(state, DIBX000_SLOW_ADC_ON) != 0)
-		dprintk( "could not start Slow ADC");
-
-	return 0;
-}
-
-static int dib7000m_sleep(struct dvb_frontend *demod)
-{
-	struct dib7000m_state *st = demod->demodulator_priv;
-	dib7000m_set_output_mode(st, OUTMODE_HIGH_Z);
-	dib7000m_set_power_mode(st, DIB7000M_POWER_INTERFACE_ONLY);
-	return dib7000m_set_adc_state(st, DIBX000_SLOW_ADC_OFF) |
-		dib7000m_set_adc_state(st, DIBX000_ADC_OFF);
-}
-
-static int dib7000m_identify(struct dib7000m_state *state)
-{
-	u16 value;
-
-	if ((value = dib7000m_read_word(state, 896)) != 0x01b3) {
-		dprintk( "wrong Vendor ID (0x%x)",value);
-		return -EREMOTEIO;
-	}
-
-	state->revision = dib7000m_read_word(state, 897);
-	if (state->revision != 0x4000 &&
-		state->revision != 0x4001 &&
-		state->revision != 0x4002 &&
-		state->revision != 0x4003) {
-		dprintk( "wrong Device ID (0x%x)",value);
-		return -EREMOTEIO;
-	}
-
-	/* protect this driver to be used with 7000PC */
-	if (state->revision == 0x4000 && dib7000m_read_word(state, 769) == 0x4000) {
-		dprintk( "this driver does not work with DiB7000PC");
-		return -EREMOTEIO;
-	}
-
-	switch (state->revision) {
-		case 0x4000: dprintk( "found DiB7000MA/PA/MB/PB"); break;
-		case 0x4001: state->reg_offs = 1; dprintk( "found DiB7000HC"); break;
-		case 0x4002: state->reg_offs = 1; dprintk( "found DiB7000MC"); break;
-		case 0x4003: state->reg_offs = 1; dprintk( "found DiB9000"); break;
-	}
-
-	return 0;
-}
-
-
-static int dib7000m_get_frontend(struct dvb_frontend* fe)
-{
-	struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
-	struct dib7000m_state *state = fe->demodulator_priv;
-	u16 tps = dib7000m_read_word(state,480);
-
-	fep->inversion = INVERSION_AUTO;
-
-	fep->bandwidth_hz = BANDWIDTH_TO_HZ(state->current_bandwidth);
-
-	switch ((tps >> 8) & 0x3) {
-		case 0: fep->transmission_mode = TRANSMISSION_MODE_2K; break;
-		case 1: fep->transmission_mode = TRANSMISSION_MODE_8K; break;
-		/* case 2: fep->transmission_mode = TRANSMISSION_MODE_4K; break; */
-	}
-
-	switch (tps & 0x3) {
-		case 0: fep->guard_interval = GUARD_INTERVAL_1_32; break;
-		case 1: fep->guard_interval = GUARD_INTERVAL_1_16; break;
-		case 2: fep->guard_interval = GUARD_INTERVAL_1_8; break;
-		case 3: fep->guard_interval = GUARD_INTERVAL_1_4; break;
-	}
-
-	switch ((tps >> 14) & 0x3) {
-		case 0: fep->modulation = QPSK; break;
-		case 1: fep->modulation = QAM_16; break;
-		case 2:
-		default: fep->modulation = QAM_64; break;
-	}
-
-	/* as long as the frontend_param structure is fixed for hierarchical transmission I refuse to use it */
-	/* (tps >> 13) & 0x1 == hrch is used, (tps >> 10) & 0x7 == alpha */
-
-	fep->hierarchy = HIERARCHY_NONE;
-	switch ((tps >> 5) & 0x7) {
-		case 1: fep->code_rate_HP = FEC_1_2; break;
-		case 2: fep->code_rate_HP = FEC_2_3; break;
-		case 3: fep->code_rate_HP = FEC_3_4; break;
-		case 5: fep->code_rate_HP = FEC_5_6; break;
-		case 7:
-		default: fep->code_rate_HP = FEC_7_8; break;
-
-	}
-
-	switch ((tps >> 2) & 0x7) {
-		case 1: fep->code_rate_LP = FEC_1_2; break;
-		case 2: fep->code_rate_LP = FEC_2_3; break;
-		case 3: fep->code_rate_LP = FEC_3_4; break;
-		case 5: fep->code_rate_LP = FEC_5_6; break;
-		case 7:
-		default: fep->code_rate_LP = FEC_7_8; break;
-	}
-
-	/* native interleaver: (dib7000m_read_word(state, 481) >>  5) & 0x1 */
-
-	return 0;
-}
-
-static int dib7000m_set_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
-	struct dib7000m_state *state = fe->demodulator_priv;
-	int time, ret;
-
-	dib7000m_set_output_mode(state, OUTMODE_HIGH_Z);
-
-	dib7000m_set_bandwidth(state, BANDWIDTH_TO_KHZ(fep->bandwidth_hz));
-
-	if (fe->ops.tuner_ops.set_params)
-		fe->ops.tuner_ops.set_params(fe);
-
-	/* start up the AGC */
-	state->agc_state = 0;
-	do {
-		time = dib7000m_agc_startup(fe);
-		if (time != -1)
-			msleep(time);
-	} while (time != -1);
-
-	if (fep->transmission_mode == TRANSMISSION_MODE_AUTO ||
-		fep->guard_interval    == GUARD_INTERVAL_AUTO ||
-		fep->modulation        == QAM_AUTO ||
-		fep->code_rate_HP      == FEC_AUTO) {
-		int i = 800, found;
-
-		dib7000m_autosearch_start(fe);
-		do {
-			msleep(1);
-			found = dib7000m_autosearch_is_irq(fe);
-		} while (found == 0 && i--);
-
-		dprintk("autosearch returns: %d",found);
-		if (found == 0 || found == 1)
-			return 0; // no channel found
-
-		dib7000m_get_frontend(fe);
-	}
-
-	ret = dib7000m_tune(fe);
-
-	/* make this a config parameter */
-	dib7000m_set_output_mode(state, OUTMODE_MPEG2_FIFO);
-	return ret;
-}
-
-static int dib7000m_read_status(struct dvb_frontend *fe, fe_status_t *stat)
-{
-	struct dib7000m_state *state = fe->demodulator_priv;
-	u16 lock = dib7000m_read_word(state, 535);
-
-	*stat = 0;
-
-	if (lock & 0x8000)
-		*stat |= FE_HAS_SIGNAL;
-	if (lock & 0x3000)
-		*stat |= FE_HAS_CARRIER;
-	if (lock & 0x0100)
-		*stat |= FE_HAS_VITERBI;
-	if (lock & 0x0010)
-		*stat |= FE_HAS_SYNC;
-	if (lock & 0x0008)
-		*stat |= FE_HAS_LOCK;
-
-	return 0;
-}
-
-static int dib7000m_read_ber(struct dvb_frontend *fe, u32 *ber)
-{
-	struct dib7000m_state *state = fe->demodulator_priv;
-	*ber = (dib7000m_read_word(state, 526) << 16) | dib7000m_read_word(state, 527);
-	return 0;
-}
-
-static int dib7000m_read_unc_blocks(struct dvb_frontend *fe, u32 *unc)
-{
-	struct dib7000m_state *state = fe->demodulator_priv;
-	*unc = dib7000m_read_word(state, 534);
-	return 0;
-}
-
-static int dib7000m_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
-{
-	struct dib7000m_state *state = fe->demodulator_priv;
-	u16 val = dib7000m_read_word(state, 390);
-	*strength = 65535 - val;
-	return 0;
-}
-
-static int dib7000m_read_snr(struct dvb_frontend* fe, u16 *snr)
-{
-	*snr = 0x0000;
-	return 0;
-}
-
-static int dib7000m_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
-{
-	tune->min_delay_ms = 1000;
-	return 0;
-}
-
-static void dib7000m_release(struct dvb_frontend *demod)
-{
-	struct dib7000m_state *st = demod->demodulator_priv;
-	dibx000_exit_i2c_master(&st->i2c_master);
-	kfree(st);
-}
-
-struct i2c_adapter * dib7000m_get_i2c_master(struct dvb_frontend *demod, enum dibx000_i2c_interface intf, int gating)
-{
-	struct dib7000m_state *st = demod->demodulator_priv;
-	return dibx000_get_i2c_adapter(&st->i2c_master, intf, gating);
-}
-EXPORT_SYMBOL(dib7000m_get_i2c_master);
-
-int dib7000m_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
-{
-	struct dib7000m_state *state = fe->demodulator_priv;
-	u16 val = dib7000m_read_word(state, 294 + state->reg_offs) & 0xffef;
-	val |= (onoff & 0x1) << 4;
-	dprintk("PID filter enabled %d", onoff);
-	return dib7000m_write_word(state, 294 + state->reg_offs, val);
-}
-EXPORT_SYMBOL(dib7000m_pid_filter_ctrl);
-
-int dib7000m_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
-{
-	struct dib7000m_state *state = fe->demodulator_priv;
-	dprintk("PID filter: index %x, PID %d, OnOff %d", id, pid, onoff);
-	return dib7000m_write_word(state, 300 + state->reg_offs + id,
-			onoff ? (1 << 13) | pid : 0);
-}
-EXPORT_SYMBOL(dib7000m_pid_filter);
-
-#if 0
-/* used with some prototype boards */
-int dib7000m_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods,
-		u8 default_addr, struct dib7000m_config cfg[])
-{
-	struct dib7000m_state st = { .i2c_adap = i2c };
-	int k = 0;
-	u8 new_addr = 0;
-
-	for (k = no_of_demods-1; k >= 0; k--) {
-		st.cfg = cfg[k];
-
-		/* designated i2c address */
-		new_addr          = (0x40 + k) << 1;
-		st.i2c_addr = new_addr;
-		if (dib7000m_identify(&st) != 0) {
-			st.i2c_addr = default_addr;
-			if (dib7000m_identify(&st) != 0) {
-				dprintk("DiB7000M #%d: not identified", k);
-				return -EIO;
-			}
-		}
-
-		/* start diversity to pull_down div_str - just for i2c-enumeration */
-		dib7000m_set_output_mode(&st, OUTMODE_DIVERSITY);
-
-		dib7000m_write_word(&st, 1796, 0x0); // select DVB-T output
-
-		/* set new i2c address and force divstart */
-		dib7000m_write_word(&st, 1794, (new_addr << 2) | 0x2);
-
-		dprintk("IC %d initialized (to i2c_address 0x%x)", k, new_addr);
-	}
-
-	for (k = 0; k < no_of_demods; k++) {
-		st.cfg = cfg[k];
-		st.i2c_addr = (0x40 + k) << 1;
-
-		// unforce divstr
-		dib7000m_write_word(&st,1794, st.i2c_addr << 2);
-
-		/* deactivate div - it was just for i2c-enumeration */
-		dib7000m_set_output_mode(&st, OUTMODE_HIGH_Z);
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL(dib7000m_i2c_enumeration);
-#endif
-
-static struct dvb_frontend_ops dib7000m_ops;
-struct dvb_frontend * dib7000m_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000m_config *cfg)
-{
-	struct dvb_frontend *demod;
-	struct dib7000m_state *st;
-	st = kzalloc(sizeof(struct dib7000m_state), GFP_KERNEL);
-	if (st == NULL)
-		return NULL;
-
-	memcpy(&st->cfg, cfg, sizeof(struct dib7000m_config));
-	st->i2c_adap = i2c_adap;
-	st->i2c_addr = i2c_addr;
-
-	demod                   = &st->demod;
-	demod->demodulator_priv = st;
-	memcpy(&st->demod.ops, &dib7000m_ops, sizeof(struct dvb_frontend_ops));
-	mutex_init(&st->i2c_buffer_lock);
-
-	st->timf_default = cfg->bw->timf;
-
-	if (dib7000m_identify(st) != 0)
-		goto error;
-
-	if (st->revision == 0x4000)
-		dibx000_init_i2c_master(&st->i2c_master, DIB7000, st->i2c_adap, st->i2c_addr);
-	else
-		dibx000_init_i2c_master(&st->i2c_master, DIB7000MC, st->i2c_adap, st->i2c_addr);
-
-	dib7000m_demod_reset(st);
-
-	return demod;
-
-error:
-	kfree(st);
-	return NULL;
-}
-EXPORT_SYMBOL(dib7000m_attach);
-
-static struct dvb_frontend_ops dib7000m_ops = {
-	.delsys = { SYS_DVBT },
-	.info = {
-		.name = "DiBcom 7000MA/MB/PA/PB/MC",
-		.frequency_min      = 44250000,
-		.frequency_max      = 867250000,
-		.frequency_stepsize = 62500,
-		.caps = FE_CAN_INVERSION_AUTO |
-			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_FEC_AUTO |
-			FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
-			FE_CAN_TRANSMISSION_MODE_AUTO |
-			FE_CAN_GUARD_INTERVAL_AUTO |
-			FE_CAN_RECOVER |
-			FE_CAN_HIERARCHY_AUTO,
-	},
-
-	.release              = dib7000m_release,
-
-	.init                 = dib7000m_wakeup,
-	.sleep                = dib7000m_sleep,
-
-	.set_frontend         = dib7000m_set_frontend,
-	.get_tune_settings    = dib7000m_fe_get_tune_settings,
-	.get_frontend         = dib7000m_get_frontend,
-
-	.read_status          = dib7000m_read_status,
-	.read_ber             = dib7000m_read_ber,
-	.read_signal_strength = dib7000m_read_signal_strength,
-	.read_snr             = dib7000m_read_snr,
-	.read_ucblocks        = dib7000m_read_unc_blocks,
-};
-
-MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
-MODULE_DESCRIPTION("Driver for the DiBcom 7000MA/MB/PA/PB/MC COFDM demodulator");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/dib7000m.h b/drivers/media/dvb/frontends/dib7000m.h
deleted file mode 100644
index 81fcf22..0000000
--- a/drivers/media/dvb/frontends/dib7000m.h
+++ /dev/null
@@ -1,90 +0,0 @@
-#ifndef DIB7000M_H
-#define DIB7000M_H
-
-#include "dibx000_common.h"
-
-struct dib7000m_config {
-	u8 dvbt_mode;
-	u8 output_mpeg2_in_188_bytes;
-	u8 hostbus_diversity;
-	u8 tuner_is_baseband;
-	u8 mobile_mode;
-	int (*update_lna) (struct dvb_frontend *, u16 agc_global);
-
-	u8 agc_config_count;
-	struct dibx000_agc_config *agc;
-
-	struct dibx000_bandwidth_config *bw;
-
-#define DIB7000M_GPIO_DEFAULT_DIRECTIONS 0xffff
-	u16 gpio_dir;
-#define DIB7000M_GPIO_DEFAULT_VALUES     0x0000
-	u16 gpio_val;
-#define DIB7000M_GPIO_PWM_POS0(v)        ((v & 0xf) << 12)
-#define DIB7000M_GPIO_PWM_POS1(v)        ((v & 0xf) << 8 )
-#define DIB7000M_GPIO_PWM_POS2(v)        ((v & 0xf) << 4 )
-#define DIB7000M_GPIO_PWM_POS3(v)         (v & 0xf)
-#define DIB7000M_GPIO_DEFAULT_PWM_POS    0xffff
-	u16 gpio_pwm_pos;
-
-	u16 pwm_freq_div;
-
-	u8 quartz_direct;
-
-	u8 input_clk_is_div_2;
-
-	int (*agc_control) (struct dvb_frontend *, u8 before);
-};
-
-#define DEFAULT_DIB7000M_I2C_ADDRESS 18
-
-#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);
-extern int dib7000m_pid_filter(struct dvb_frontend *, u8 id, u16 pid, u8 onoff);
-extern int dib7000m_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff);
-#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;
-}
-static inline int dib7000m_pid_filter(struct dvb_frontend *fe, u8 id,
-						u16 pid, u8 onoff)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return -ENODEV;
-}
-
-static inline int dib7000m_pid_filter_ctrl(struct dvb_frontend *fe,
-						uint8_t onoff)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return -ENODEV;
-}
-#endif
-
-/* TODO
-extern INT dib7000m_set_gpio(struct dibDemod *demod, UCHAR num, UCHAR dir, UCHAR val);
-extern INT dib7000m_enable_vbg_voltage(struct dibDemod *demod);
-extern void dib7000m_set_hostbus_diversity(struct dibDemod *demod, UCHAR onoff);
-extern USHORT dib7000m_get_current_agc_global(struct dibDemod *demod);
-*/
-
-#endif
diff --git a/drivers/media/dvb/frontends/dib7000p.c b/drivers/media/dvb/frontends/dib7000p.c
deleted file mode 100644
index 3e1eefa..0000000
--- a/drivers/media/dvb/frontends/dib7000p.c
+++ /dev/null
@@ -1,2457 +0,0 @@
-/*
- * Linux-DVB Driver for DiBcom's second generation DiB7000P (PC).
- *
- * Copyright (C) 2005-7 DiBcom (http://www.dibcom.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, version 2.
- */
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/i2c.h>
-#include <linux/mutex.h>
-
-#include "dvb_math.h"
-#include "dvb_frontend.h"
-
-#include "dib7000p.h"
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
-
-static int buggy_sfn_workaround;
-module_param(buggy_sfn_workaround, int, 0644);
-MODULE_PARM_DESC(buggy_sfn_workaround, "Enable work-around for buggy SFNs (default: 0)");
-
-#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB7000P: "); printk(args); printk("\n"); } } while (0)
-
-struct i2c_device {
-	struct i2c_adapter *i2c_adap;
-	u8 i2c_addr;
-};
-
-struct dib7000p_state {
-	struct dvb_frontend demod;
-	struct dib7000p_config cfg;
-
-	u8 i2c_addr;
-	struct i2c_adapter *i2c_adap;
-
-	struct dibx000_i2c_master i2c_master;
-
-	u16 wbd_ref;
-
-	u8 current_band;
-	u32 current_bandwidth;
-	struct dibx000_agc_config *current_agc;
-	u32 timf;
-
-	u8 div_force_off:1;
-	u8 div_state:1;
-	u16 div_sync_wait;
-
-	u8 agc_state;
-
-	u16 gpio_dir;
-	u16 gpio_val;
-
-	u8 sfn_workaround_active:1;
-
-#define SOC7090 0x7090
-	u16 version;
-
-	u16 tuner_enable;
-	struct i2c_adapter dib7090_tuner_adap;
-
-	/* for the I2C transfer */
-	struct i2c_msg msg[2];
-	u8 i2c_write_buffer[4];
-	u8 i2c_read_buffer[2];
-	struct mutex i2c_buffer_lock;
-
-	u8 input_mode_mpeg;
-};
-
-enum dib7000p_power_mode {
-	DIB7000P_POWER_ALL = 0,
-	DIB7000P_POWER_ANALOG_ADC,
-	DIB7000P_POWER_INTERFACE_ONLY,
-};
-
-/* dib7090 specific fonctions */
-static int dib7090_set_output_mode(struct dvb_frontend *fe, int mode);
-static int dib7090_set_diversity_in(struct dvb_frontend *fe, int onoff);
-static void dib7090_setDibTxMux(struct dib7000p_state *state, int mode);
-static void dib7090_setHostBusMux(struct dib7000p_state *state, int mode);
-
-static u16 dib7000p_read_word(struct dib7000p_state *state, u16 reg)
-{
-	u16 ret;
-
-	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
-		dprintk("could not acquire lock");
-		return 0;
-	}
-
-	state->i2c_write_buffer[0] = reg >> 8;
-	state->i2c_write_buffer[1] = reg & 0xff;
-
-	memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
-	state->msg[0].addr = state->i2c_addr >> 1;
-	state->msg[0].flags = 0;
-	state->msg[0].buf = state->i2c_write_buffer;
-	state->msg[0].len = 2;
-	state->msg[1].addr = state->i2c_addr >> 1;
-	state->msg[1].flags = I2C_M_RD;
-	state->msg[1].buf = state->i2c_read_buffer;
-	state->msg[1].len = 2;
-
-	if (i2c_transfer(state->i2c_adap, state->msg, 2) != 2)
-		dprintk("i2c read error on %d", reg);
-
-	ret = (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
-	mutex_unlock(&state->i2c_buffer_lock);
-	return ret;
-}
-
-static int dib7000p_write_word(struct dib7000p_state *state, u16 reg, u16 val)
-{
-	int ret;
-
-	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
-		dprintk("could not acquire lock");
-		return -EINVAL;
-	}
-
-	state->i2c_write_buffer[0] = (reg >> 8) & 0xff;
-	state->i2c_write_buffer[1] = reg & 0xff;
-	state->i2c_write_buffer[2] = (val >> 8) & 0xff;
-	state->i2c_write_buffer[3] = val & 0xff;
-
-	memset(&state->msg[0], 0, sizeof(struct i2c_msg));
-	state->msg[0].addr = state->i2c_addr >> 1;
-	state->msg[0].flags = 0;
-	state->msg[0].buf = state->i2c_write_buffer;
-	state->msg[0].len = 4;
-
-	ret = (i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ?
-			-EREMOTEIO : 0);
-	mutex_unlock(&state->i2c_buffer_lock);
-	return ret;
-}
-
-static void dib7000p_write_tab(struct dib7000p_state *state, u16 * buf)
-{
-	u16 l = 0, r, *n;
-	n = buf;
-	l = *n++;
-	while (l) {
-		r = *n++;
-
-		do {
-			dib7000p_write_word(state, r, *n++);
-			r++;
-		} while (--l);
-		l = *n++;
-	}
-}
-
-static int dib7000p_set_output_mode(struct dib7000p_state *state, int mode)
-{
-	int ret = 0;
-	u16 outreg, fifo_threshold, smo_mode;
-
-	outreg = 0;
-	fifo_threshold = 1792;
-	smo_mode = (dib7000p_read_word(state, 235) & 0x0050) | (1 << 1);
-
-	dprintk("setting output mode for demod %p to %d", &state->demod, mode);
-
-	switch (mode) {
-	case OUTMODE_MPEG2_PAR_GATED_CLK:
-		outreg = (1 << 10);	/* 0x0400 */
-		break;
-	case OUTMODE_MPEG2_PAR_CONT_CLK:
-		outreg = (1 << 10) | (1 << 6);	/* 0x0440 */
-		break;
-	case OUTMODE_MPEG2_SERIAL:
-		outreg = (1 << 10) | (2 << 6) | (0 << 1);	/* 0x0480 */
-		break;
-	case OUTMODE_DIVERSITY:
-		if (state->cfg.hostbus_diversity)
-			outreg = (1 << 10) | (4 << 6);	/* 0x0500 */
-		else
-			outreg = (1 << 11);
-		break;
-	case OUTMODE_MPEG2_FIFO:
-		smo_mode |= (3 << 1);
-		fifo_threshold = 512;
-		outreg = (1 << 10) | (5 << 6);
-		break;
-	case OUTMODE_ANALOG_ADC:
-		outreg = (1 << 10) | (3 << 6);
-		break;
-	case OUTMODE_HIGH_Z:
-		outreg = 0;
-		break;
-	default:
-		dprintk("Unhandled output_mode passed to be set for demod %p", &state->demod);
-		break;
-	}
-
-	if (state->cfg.output_mpeg2_in_188_bytes)
-		smo_mode |= (1 << 5);
-
-	ret |= dib7000p_write_word(state, 235, smo_mode);
-	ret |= dib7000p_write_word(state, 236, fifo_threshold);	/* synchronous fread */
-	if (state->version != SOC7090)
-		ret |= dib7000p_write_word(state, 1286, outreg);	/* P_Div_active */
-
-	return ret;
-}
-
-static int dib7000p_set_diversity_in(struct dvb_frontend *demod, int onoff)
-{
-	struct dib7000p_state *state = demod->demodulator_priv;
-
-	if (state->div_force_off) {
-		dprintk("diversity combination deactivated - forced by COFDM parameters");
-		onoff = 0;
-		dib7000p_write_word(state, 207, 0);
-	} else
-		dib7000p_write_word(state, 207, (state->div_sync_wait << 4) | (1 << 2) | (2 << 0));
-
-	state->div_state = (u8) onoff;
-
-	if (onoff) {
-		dib7000p_write_word(state, 204, 6);
-		dib7000p_write_word(state, 205, 16);
-		/* P_dvsy_sync_mode = 0, P_dvsy_sync_enable=1, P_dvcb_comb_mode=2 */
-	} else {
-		dib7000p_write_word(state, 204, 1);
-		dib7000p_write_word(state, 205, 0);
-	}
-
-	return 0;
-}
-
-static int dib7000p_set_power_mode(struct dib7000p_state *state, enum dib7000p_power_mode mode)
-{
-	/* by default everything is powered off */
-	u16 reg_774 = 0x3fff, reg_775 = 0xffff, reg_776 = 0x0007, reg_899 = 0x0003, reg_1280 = (0xfe00) | (dib7000p_read_word(state, 1280) & 0x01ff);
-
-	/* now, depending on the requested mode, we power on */
-	switch (mode) {
-		/* power up everything in the demod */
-	case DIB7000P_POWER_ALL:
-		reg_774 = 0x0000;
-		reg_775 = 0x0000;
-		reg_776 = 0x0;
-		reg_899 = 0x0;
-		if (state->version == SOC7090)
-			reg_1280 &= 0x001f;
-		else
-			reg_1280 &= 0x01ff;
-		break;
-
-	case DIB7000P_POWER_ANALOG_ADC:
-		/* dem, cfg, iqc, sad, agc */
-		reg_774 &= ~((1 << 15) | (1 << 14) | (1 << 11) | (1 << 10) | (1 << 9));
-		/* nud */
-		reg_776 &= ~((1 << 0));
-		/* Dout */
-		if (state->version != SOC7090)
-			reg_1280 &= ~((1 << 11));
-		reg_1280 &= ~(1 << 6);
-		/* fall through wanted to enable the interfaces */
-
-		/* just leave power on the control-interfaces: GPIO and (I2C or SDIO) */
-	case DIB7000P_POWER_INTERFACE_ONLY:	/* TODO power up either SDIO or I2C */
-		if (state->version == SOC7090)
-			reg_1280 &= ~((1 << 7) | (1 << 5));
-		else
-			reg_1280 &= ~((1 << 14) | (1 << 13) | (1 << 12) | (1 << 10));
-		break;
-
-/* TODO following stuff is just converted from the dib7000-driver - check when is used what */
-	}
-
-	dib7000p_write_word(state, 774, reg_774);
-	dib7000p_write_word(state, 775, reg_775);
-	dib7000p_write_word(state, 776, reg_776);
-	dib7000p_write_word(state, 1280, reg_1280);
-	if (state->version != SOC7090)
-		dib7000p_write_word(state, 899, reg_899);
-
-	return 0;
-}
-
-static void dib7000p_set_adc_state(struct dib7000p_state *state, enum dibx000_adc_states no)
-{
-	u16 reg_908 = 0, reg_909 = 0;
-	u16 reg;
-
-	if (state->version != SOC7090) {
-		reg_908 = dib7000p_read_word(state, 908);
-		reg_909 = dib7000p_read_word(state, 909);
-	}
-
-	switch (no) {
-	case DIBX000_SLOW_ADC_ON:
-		if (state->version == SOC7090) {
-			reg = dib7000p_read_word(state, 1925);
-
-			dib7000p_write_word(state, 1925, reg | (1 << 4) | (1 << 2));	/* en_slowAdc = 1 & reset_sladc = 1 */
-
-			reg = dib7000p_read_word(state, 1925);	/* read acces to make it works... strange ... */
-			msleep(200);
-			dib7000p_write_word(state, 1925, reg & ~(1 << 4));	/* en_slowAdc = 1 & reset_sladc = 0 */
-
-			reg = dib7000p_read_word(state, 72) & ~((0x3 << 14) | (0x3 << 12));
-			dib7000p_write_word(state, 72, reg | (1 << 14) | (3 << 12) | 524);	/* ref = Vin1 => Vbg ; sel = Vin0 or Vin3 ; (Vin2 = Vcm) */
-		} else {
-			reg_909 |= (1 << 1) | (1 << 0);
-			dib7000p_write_word(state, 909, reg_909);
-			reg_909 &= ~(1 << 1);
-		}
-		break;
-
-	case DIBX000_SLOW_ADC_OFF:
-		if (state->version == SOC7090) {
-			reg = dib7000p_read_word(state, 1925);
-			dib7000p_write_word(state, 1925, (reg & ~(1 << 2)) | (1 << 4));	/* reset_sladc = 1 en_slowAdc = 0 */
-		} else
-			reg_909 |= (1 << 1) | (1 << 0);
-		break;
-
-	case DIBX000_ADC_ON:
-		reg_908 &= 0x0fff;
-		reg_909 &= 0x0003;
-		break;
-
-	case DIBX000_ADC_OFF:
-		reg_908 |= (1 << 14) | (1 << 13) | (1 << 12);
-		reg_909 |= (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2);
-		break;
-
-	case DIBX000_VBG_ENABLE:
-		reg_908 &= ~(1 << 15);
-		break;
-
-	case DIBX000_VBG_DISABLE:
-		reg_908 |= (1 << 15);
-		break;
-
-	default:
-		break;
-	}
-
-//	dprintk( "908: %x, 909: %x\n", reg_908, reg_909);
-
-	reg_909 |= (state->cfg.disable_sample_and_hold & 1) << 4;
-	reg_908 |= (state->cfg.enable_current_mirror & 1) << 7;
-
-	if (state->version != SOC7090) {
-		dib7000p_write_word(state, 908, reg_908);
-		dib7000p_write_word(state, 909, reg_909);
-	}
-}
-
-static int dib7000p_set_bandwidth(struct dib7000p_state *state, u32 bw)
-{
-	u32 timf;
-
-	// store the current bandwidth for later use
-	state->current_bandwidth = bw;
-
-	if (state->timf == 0) {
-		dprintk("using default timf");
-		timf = state->cfg.bw->timf;
-	} else {
-		dprintk("using updated timf");
-		timf = state->timf;
-	}
-
-	timf = timf * (bw / 50) / 160;
-
-	dib7000p_write_word(state, 23, (u16) ((timf >> 16) & 0xffff));
-	dib7000p_write_word(state, 24, (u16) ((timf) & 0xffff));
-
-	return 0;
-}
-
-static int dib7000p_sad_calib(struct dib7000p_state *state)
-{
-/* internal */
-	dib7000p_write_word(state, 73, (0 << 1) | (0 << 0));
-
-	if (state->version == SOC7090)
-		dib7000p_write_word(state, 74, 2048);
-	else
-		dib7000p_write_word(state, 74, 776);
-
-	/* do the calibration */
-	dib7000p_write_word(state, 73, (1 << 0));
-	dib7000p_write_word(state, 73, (0 << 0));
-
-	msleep(1);
-
-	return 0;
-}
-
-int dib7000p_set_wbd_ref(struct dvb_frontend *demod, u16 value)
-{
-	struct dib7000p_state *state = demod->demodulator_priv;
-	if (value > 4095)
-		value = 4095;
-	state->wbd_ref = value;
-	return dib7000p_write_word(state, 105, (dib7000p_read_word(state, 105) & 0xf000) | value);
-}
-EXPORT_SYMBOL(dib7000p_set_wbd_ref);
-
-int dib7000p_get_agc_values(struct dvb_frontend *fe,
-		u16 *agc_global, u16 *agc1, u16 *agc2, u16 *wbd)
-{
-	struct dib7000p_state *state = fe->demodulator_priv;
-
-	if (agc_global != NULL)
-		*agc_global = dib7000p_read_word(state, 394);
-	if (agc1 != NULL)
-		*agc1 = dib7000p_read_word(state, 392);
-	if (agc2 != NULL)
-		*agc2 = dib7000p_read_word(state, 393);
-	if (wbd != NULL)
-		*wbd = dib7000p_read_word(state, 397);
-
-	return 0;
-}
-EXPORT_SYMBOL(dib7000p_get_agc_values);
-
-static void dib7000p_reset_pll(struct dib7000p_state *state)
-{
-	struct dibx000_bandwidth_config *bw = &state->cfg.bw[0];
-	u16 clk_cfg0;
-
-	if (state->version == SOC7090) {
-		dib7000p_write_word(state, 1856, (!bw->pll_reset << 13) | (bw->pll_range << 12) | (bw->pll_ratio << 6) | (bw->pll_prediv));
-
-		while (((dib7000p_read_word(state, 1856) >> 15) & 0x1) != 1)
-			;
-
-		dib7000p_write_word(state, 1857, dib7000p_read_word(state, 1857) | (!bw->pll_bypass << 15));
-	} else {
-		/* force PLL bypass */
-		clk_cfg0 = (1 << 15) | ((bw->pll_ratio & 0x3f) << 9) |
-			(bw->modulo << 7) | (bw->ADClkSrc << 6) | (bw->IO_CLK_en_core << 5) | (bw->bypclk_div << 2) | (bw->enable_refdiv << 1) | (0 << 0);
-
-		dib7000p_write_word(state, 900, clk_cfg0);
-
-		/* P_pll_cfg */
-		dib7000p_write_word(state, 903, (bw->pll_prediv << 5) | (((bw->pll_ratio >> 6) & 0x3) << 3) | (bw->pll_range << 1) | bw->pll_reset);
-		clk_cfg0 = (bw->pll_bypass << 15) | (clk_cfg0 & 0x7fff);
-		dib7000p_write_word(state, 900, clk_cfg0);
-	}
-
-	dib7000p_write_word(state, 18, (u16) (((bw->internal * 1000) >> 16) & 0xffff));
-	dib7000p_write_word(state, 19, (u16) ((bw->internal * 1000) & 0xffff));
-	dib7000p_write_word(state, 21, (u16) ((bw->ifreq >> 16) & 0xffff));
-	dib7000p_write_word(state, 22, (u16) ((bw->ifreq) & 0xffff));
-
-	dib7000p_write_word(state, 72, bw->sad_cfg);
-}
-
-static u32 dib7000p_get_internal_freq(struct dib7000p_state *state)
-{
-	u32 internal = (u32) dib7000p_read_word(state, 18) << 16;
-	internal |= (u32) dib7000p_read_word(state, 19);
-	internal /= 1000;
-
-	return internal;
-}
-
-int dib7000p_update_pll(struct dvb_frontend *fe, struct dibx000_bandwidth_config *bw)
-{
-	struct dib7000p_state *state = fe->demodulator_priv;
-	u16 reg_1857, reg_1856 = dib7000p_read_word(state, 1856);
-	u8 loopdiv, prediv;
-	u32 internal, xtal;
-
-	/* get back old values */
-	prediv = reg_1856 & 0x3f;
-	loopdiv = (reg_1856 >> 6) & 0x3f;
-
-	if ((bw != NULL) && (bw->pll_prediv != prediv || bw->pll_ratio != loopdiv)) {
-		dprintk("Updating pll (prediv: old =  %d new = %d ; loopdiv : old = %d new = %d)", prediv, bw->pll_prediv, loopdiv, bw->pll_ratio);
-		reg_1856 &= 0xf000;
-		reg_1857 = dib7000p_read_word(state, 1857);
-		dib7000p_write_word(state, 1857, reg_1857 & ~(1 << 15));
-
-		dib7000p_write_word(state, 1856, reg_1856 | ((bw->pll_ratio & 0x3f) << 6) | (bw->pll_prediv & 0x3f));
-
-		/* write new system clk into P_sec_len */
-		internal = dib7000p_get_internal_freq(state);
-		xtal = (internal / loopdiv) * prediv;
-		internal = 1000 * (xtal / bw->pll_prediv) * bw->pll_ratio;	/* new internal */
-		dib7000p_write_word(state, 18, (u16) ((internal >> 16) & 0xffff));
-		dib7000p_write_word(state, 19, (u16) (internal & 0xffff));
-
-		dib7000p_write_word(state, 1857, reg_1857 | (1 << 15));
-
-		while (((dib7000p_read_word(state, 1856) >> 15) & 0x1) != 1)
-			dprintk("Waiting for PLL to lock");
-
-		return 0;
-	}
-	return -EIO;
-}
-EXPORT_SYMBOL(dib7000p_update_pll);
-
-static int dib7000p_reset_gpio(struct dib7000p_state *st)
-{
-	/* reset the GPIOs */
-	dprintk("gpio dir: %x: val: %x, pwm_pos: %x", st->gpio_dir, st->gpio_val, st->cfg.gpio_pwm_pos);
-
-	dib7000p_write_word(st, 1029, st->gpio_dir);
-	dib7000p_write_word(st, 1030, st->gpio_val);
-
-	/* TODO 1031 is P_gpio_od */
-
-	dib7000p_write_word(st, 1032, st->cfg.gpio_pwm_pos);
-
-	dib7000p_write_word(st, 1037, st->cfg.pwm_freq_div);
-	return 0;
-}
-
-static int dib7000p_cfg_gpio(struct dib7000p_state *st, u8 num, u8 dir, u8 val)
-{
-	st->gpio_dir = dib7000p_read_word(st, 1029);
-	st->gpio_dir &= ~(1 << num);	/* reset the direction bit */
-	st->gpio_dir |= (dir & 0x1) << num;	/* set the new direction */
-	dib7000p_write_word(st, 1029, st->gpio_dir);
-
-	st->gpio_val = dib7000p_read_word(st, 1030);
-	st->gpio_val &= ~(1 << num);	/* reset the direction bit */
-	st->gpio_val |= (val & 0x01) << num;	/* set the new value */
-	dib7000p_write_word(st, 1030, st->gpio_val);
-
-	return 0;
-}
-
-int dib7000p_set_gpio(struct dvb_frontend *demod, u8 num, u8 dir, u8 val)
-{
-	struct dib7000p_state *state = demod->demodulator_priv;
-	return dib7000p_cfg_gpio(state, num, dir, val);
-}
-EXPORT_SYMBOL(dib7000p_set_gpio);
-
-static u16 dib7000p_defaults[] = {
-	// auto search configuration
-	3, 2,
-	0x0004,
-	(1<<3)|(1<<11)|(1<<12)|(1<<13),
-	0x0814,			/* Equal Lock */
-
-	12, 6,
-	0x001b,
-	0x7740,
-	0x005b,
-	0x8d80,
-	0x01c9,
-	0xc380,
-	0x0000,
-	0x0080,
-	0x0000,
-	0x0090,
-	0x0001,
-	0xd4c0,
-
-	1, 26,
-	0x6680,
-
-	/* set ADC level to -16 */
-	11, 79,
-	(1 << 13) - 825 - 117,
-	(1 << 13) - 837 - 117,
-	(1 << 13) - 811 - 117,
-	(1 << 13) - 766 - 117,
-	(1 << 13) - 737 - 117,
-	(1 << 13) - 693 - 117,
-	(1 << 13) - 648 - 117,
-	(1 << 13) - 619 - 117,
-	(1 << 13) - 575 - 117,
-	(1 << 13) - 531 - 117,
-	(1 << 13) - 501 - 117,
-
-	1, 142,
-	0x0410,
-
-	/* disable power smoothing */
-	8, 145,
-	0,
-	0,
-	0,
-	0,
-	0,
-	0,
-	0,
-	0,
-
-	1, 154,
-	1 << 13,
-
-	1, 168,
-	0x0ccd,
-
-	1, 183,
-	0x200f,
-
-	1, 212,
-		0x169,
-
-	5, 187,
-	0x023d,
-	0x00a4,
-	0x00a4,
-	0x7ff0,
-	0x3ccc,
-
-	1, 198,
-	0x800,
-
-	1, 222,
-	0x0010,
-
-	1, 235,
-	0x0062,
-
-	0,
-};
-
-static int dib7000p_demod_reset(struct dib7000p_state *state)
-{
-	dib7000p_set_power_mode(state, DIB7000P_POWER_ALL);
-
-	if (state->version == SOC7090)
-		dibx000_reset_i2c_master(&state->i2c_master);
-
-	dib7000p_set_adc_state(state, DIBX000_VBG_ENABLE);
-
-	/* restart all parts */
-	dib7000p_write_word(state, 770, 0xffff);
-	dib7000p_write_word(state, 771, 0xffff);
-	dib7000p_write_word(state, 772, 0x001f);
-	dib7000p_write_word(state, 1280, 0x001f - ((1 << 4) | (1 << 3)));
-
-	dib7000p_write_word(state, 770, 0);
-	dib7000p_write_word(state, 771, 0);
-	dib7000p_write_word(state, 772, 0);
-	dib7000p_write_word(state, 1280, 0);
-
-	if (state->version != SOC7090) {
-		dib7000p_write_word(state,  898, 0x0003);
-		dib7000p_write_word(state,  898, 0);
-	}
-
-	/* default */
-	dib7000p_reset_pll(state);
-
-	if (dib7000p_reset_gpio(state) != 0)
-		dprintk("GPIO reset was not successful.");
-
-	if (state->version == SOC7090) {
-		dib7000p_write_word(state, 899, 0);
-
-		/* impulse noise */
-		dib7000p_write_word(state, 42, (1<<5) | 3); /* P_iqc_thsat_ipc = 1 ; P_iqc_win2 = 3 */
-		dib7000p_write_word(state, 43, 0x2d4); /*-300 fag P_iqc_dect_min = -280 */
-		dib7000p_write_word(state, 44, 300); /* 300 fag P_iqc_dect_min = +280 */
-		dib7000p_write_word(state, 273, (0<<6) | 30);
-	}
-	if (dib7000p_set_output_mode(state, OUTMODE_HIGH_Z) != 0)
-		dprintk("OUTPUT_MODE could not be reset.");
-
-	dib7000p_set_adc_state(state, DIBX000_SLOW_ADC_ON);
-	dib7000p_sad_calib(state);
-	dib7000p_set_adc_state(state, DIBX000_SLOW_ADC_OFF);
-
-	/* unforce divstr regardless whether i2c enumeration was done or not */
-	dib7000p_write_word(state, 1285, dib7000p_read_word(state, 1285) & ~(1 << 1));
-
-	dib7000p_set_bandwidth(state, 8000);
-
-	if (state->version == SOC7090) {
-		dib7000p_write_word(state, 36, 0x0755);/* P_iqc_impnc_on =1 & P_iqc_corr_inh = 1 for impulsive noise */
-	} else {
-		if (state->cfg.tuner_is_baseband)
-			dib7000p_write_word(state, 36, 0x0755);
-		else
-			dib7000p_write_word(state, 36, 0x1f55);
-	}
-
-	dib7000p_write_tab(state, dib7000p_defaults);
-	if (state->version != SOC7090) {
-		dib7000p_write_word(state, 901, 0x0006);
-		dib7000p_write_word(state, 902, (3 << 10) | (1 << 6));
-		dib7000p_write_word(state, 905, 0x2c8e);
-	}
-
-	dib7000p_set_power_mode(state, DIB7000P_POWER_INTERFACE_ONLY);
-
-	return 0;
-}
-
-static void dib7000p_pll_clk_cfg(struct dib7000p_state *state)
-{
-	u16 tmp = 0;
-	tmp = dib7000p_read_word(state, 903);
-	dib7000p_write_word(state, 903, (tmp | 0x1));
-	tmp = dib7000p_read_word(state, 900);
-	dib7000p_write_word(state, 900, (tmp & 0x7fff) | (1 << 6));
-}
-
-static void dib7000p_restart_agc(struct dib7000p_state *state)
-{
-	// P_restart_iqc & P_restart_agc
-	dib7000p_write_word(state, 770, (1 << 11) | (1 << 9));
-	dib7000p_write_word(state, 770, 0x0000);
-}
-
-static int dib7000p_update_lna(struct dib7000p_state *state)
-{
-	u16 dyn_gain;
-
-	if (state->cfg.update_lna) {
-		dyn_gain = dib7000p_read_word(state, 394);
-		if (state->cfg.update_lna(&state->demod, dyn_gain)) {
-			dib7000p_restart_agc(state);
-			return 1;
-		}
-	}
-
-	return 0;
-}
-
-static int dib7000p_set_agc_config(struct dib7000p_state *state, u8 band)
-{
-	struct dibx000_agc_config *agc = NULL;
-	int i;
-	if (state->current_band == band && state->current_agc != NULL)
-		return 0;
-	state->current_band = band;
-
-	for (i = 0; i < state->cfg.agc_config_count; i++)
-		if (state->cfg.agc[i].band_caps & band) {
-			agc = &state->cfg.agc[i];
-			break;
-		}
-
-	if (agc == NULL) {
-		dprintk("no valid AGC configuration found for band 0x%02x", band);
-		return -EINVAL;
-	}
-
-	state->current_agc = agc;
-
-	/* AGC */
-	dib7000p_write_word(state, 75, agc->setup);
-	dib7000p_write_word(state, 76, agc->inv_gain);
-	dib7000p_write_word(state, 77, agc->time_stabiliz);
-	dib7000p_write_word(state, 100, (agc->alpha_level << 12) | agc->thlock);
-
-	// Demod AGC loop configuration
-	dib7000p_write_word(state, 101, (agc->alpha_mant << 5) | agc->alpha_exp);
-	dib7000p_write_word(state, 102, (agc->beta_mant << 6) | agc->beta_exp);
-
-	/* AGC continued */
-	dprintk("WBD: ref: %d, sel: %d, active: %d, alpha: %d",
-		state->wbd_ref != 0 ? state->wbd_ref : agc->wbd_ref, agc->wbd_sel, !agc->perform_agc_softsplit, agc->wbd_sel);
-
-	if (state->wbd_ref != 0)
-		dib7000p_write_word(state, 105, (agc->wbd_inv << 12) | state->wbd_ref);
-	else
-		dib7000p_write_word(state, 105, (agc->wbd_inv << 12) | agc->wbd_ref);
-
-	dib7000p_write_word(state, 106, (agc->wbd_sel << 13) | (agc->wbd_alpha << 9) | (agc->perform_agc_softsplit << 8));
-
-	dib7000p_write_word(state, 107, agc->agc1_max);
-	dib7000p_write_word(state, 108, agc->agc1_min);
-	dib7000p_write_word(state, 109, agc->agc2_max);
-	dib7000p_write_word(state, 110, agc->agc2_min);
-	dib7000p_write_word(state, 111, (agc->agc1_pt1 << 8) | agc->agc1_pt2);
-	dib7000p_write_word(state, 112, agc->agc1_pt3);
-	dib7000p_write_word(state, 113, (agc->agc1_slope1 << 8) | agc->agc1_slope2);
-	dib7000p_write_word(state, 114, (agc->agc2_pt1 << 8) | agc->agc2_pt2);
-	dib7000p_write_word(state, 115, (agc->agc2_slope1 << 8) | agc->agc2_slope2);
-	return 0;
-}
-
-static void dib7000p_set_dds(struct dib7000p_state *state, s32 offset_khz)
-{
-	u32 internal = dib7000p_get_internal_freq(state);
-	s32 unit_khz_dds_val = 67108864 / (internal);	/* 2**26 / Fsampling is the unit 1KHz offset */
-	u32 abs_offset_khz = ABS(offset_khz);
-	u32 dds = state->cfg.bw->ifreq & 0x1ffffff;
-	u8 invert = !!(state->cfg.bw->ifreq & (1 << 25));
-
-	dprintk("setting a frequency offset of %dkHz internal freq = %d invert = %d", offset_khz, internal, invert);
-
-	if (offset_khz < 0)
-		unit_khz_dds_val *= -1;
-
-	/* IF tuner */
-	if (invert)
-		dds -= (abs_offset_khz * unit_khz_dds_val);	/* /100 because of /100 on the unit_khz_dds_val line calc for better accuracy */
-	else
-		dds += (abs_offset_khz * unit_khz_dds_val);
-
-	if (abs_offset_khz <= (internal / 2)) {	/* Max dds offset is the half of the demod freq */
-		dib7000p_write_word(state, 21, (u16) (((dds >> 16) & 0x1ff) | (0 << 10) | (invert << 9)));
-		dib7000p_write_word(state, 22, (u16) (dds & 0xffff));
-	}
-}
-
-static int dib7000p_agc_startup(struct dvb_frontend *demod)
-{
-	struct dtv_frontend_properties *ch = &demod->dtv_property_cache;
-	struct dib7000p_state *state = demod->demodulator_priv;
-	int ret = -1;
-	u8 *agc_state = &state->agc_state;
-	u8 agc_split;
-	u16 reg;
-	u32 upd_demod_gain_period = 0x1000;
-
-	switch (state->agc_state) {
-	case 0:
-		dib7000p_set_power_mode(state, DIB7000P_POWER_ALL);
-		if (state->version == SOC7090) {
-			reg = dib7000p_read_word(state, 0x79b) & 0xff00;
-			dib7000p_write_word(state, 0x79a, upd_demod_gain_period & 0xFFFF);	/* lsb */
-			dib7000p_write_word(state, 0x79b, reg | (1 << 14) | ((upd_demod_gain_period >> 16) & 0xFF));
-
-			/* enable adc i & q */
-			reg = dib7000p_read_word(state, 0x780);
-			dib7000p_write_word(state, 0x780, (reg | (0x3)) & (~(1 << 7)));
-		} else {
-			dib7000p_set_adc_state(state, DIBX000_ADC_ON);
-			dib7000p_pll_clk_cfg(state);
-		}
-
-		if (dib7000p_set_agc_config(state, BAND_OF_FREQUENCY(ch->frequency / 1000)) != 0)
-			return -1;
-
-		dib7000p_set_dds(state, 0);
-		ret = 7;
-		(*agc_state)++;
-		break;
-
-	case 1:
-		if (state->cfg.agc_control)
-			state->cfg.agc_control(&state->demod, 1);
-
-		dib7000p_write_word(state, 78, 32768);
-		if (!state->current_agc->perform_agc_softsplit) {
-			/* we are using the wbd - so slow AGC startup */
-			/* force 0 split on WBD and restart AGC */
-			dib7000p_write_word(state, 106, (state->current_agc->wbd_sel << 13) | (state->current_agc->wbd_alpha << 9) | (1 << 8));
-			(*agc_state)++;
-			ret = 5;
-		} else {
-			/* default AGC startup */
-			(*agc_state) = 4;
-			/* wait AGC rough lock time */
-			ret = 7;
-		}
-
-		dib7000p_restart_agc(state);
-		break;
-
-	case 2:		/* fast split search path after 5sec */
-		dib7000p_write_word(state, 75, state->current_agc->setup | (1 << 4));	/* freeze AGC loop */
-		dib7000p_write_word(state, 106, (state->current_agc->wbd_sel << 13) | (2 << 9) | (0 << 8));	/* fast split search 0.25kHz */
-		(*agc_state)++;
-		ret = 14;
-		break;
-
-	case 3:		/* split search ended */
-		agc_split = (u8) dib7000p_read_word(state, 396);	/* store the split value for the next time */
-		dib7000p_write_word(state, 78, dib7000p_read_word(state, 394));	/* set AGC gain start value */
-
-		dib7000p_write_word(state, 75, state->current_agc->setup);	/* std AGC loop */
-		dib7000p_write_word(state, 106, (state->current_agc->wbd_sel << 13) | (state->current_agc->wbd_alpha << 9) | agc_split);	/* standard split search */
-
-		dib7000p_restart_agc(state);
-
-		dprintk("SPLIT %p: %hd", demod, agc_split);
-
-		(*agc_state)++;
-		ret = 5;
-		break;
-
-	case 4:		/* LNA startup */
-		ret = 7;
-
-		if (dib7000p_update_lna(state))
-			ret = 5;
-		else
-			(*agc_state)++;
-		break;
-
-	case 5:
-		if (state->cfg.agc_control)
-			state->cfg.agc_control(&state->demod, 0);
-		(*agc_state)++;
-		break;
-	default:
-		break;
-	}
-	return ret;
-}
-
-static void dib7000p_update_timf(struct dib7000p_state *state)
-{
-	u32 timf = (dib7000p_read_word(state, 427) << 16) | dib7000p_read_word(state, 428);
-	state->timf = timf * 160 / (state->current_bandwidth / 50);
-	dib7000p_write_word(state, 23, (u16) (timf >> 16));
-	dib7000p_write_word(state, 24, (u16) (timf & 0xffff));
-	dprintk("updated timf_frequency: %d (default: %d)", state->timf, state->cfg.bw->timf);
-
-}
-
-u32 dib7000p_ctrl_timf(struct dvb_frontend *fe, u8 op, u32 timf)
-{
-	struct dib7000p_state *state = fe->demodulator_priv;
-	switch (op) {
-	case DEMOD_TIMF_SET:
-		state->timf = timf;
-		break;
-	case DEMOD_TIMF_UPDATE:
-		dib7000p_update_timf(state);
-		break;
-	case DEMOD_TIMF_GET:
-		break;
-	}
-	dib7000p_set_bandwidth(state, state->current_bandwidth);
-	return state->timf;
-}
-EXPORT_SYMBOL(dib7000p_ctrl_timf);
-
-static void dib7000p_set_channel(struct dib7000p_state *state,
-				 struct dtv_frontend_properties *ch, u8 seq)
-{
-	u16 value, est[4];
-
-	dib7000p_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->bandwidth_hz));
-
-	/* nfft, guard, qam, alpha */
-	value = 0;
-	switch (ch->transmission_mode) {
-	case TRANSMISSION_MODE_2K:
-		value |= (0 << 7);
-		break;
-	case TRANSMISSION_MODE_4K:
-		value |= (2 << 7);
-		break;
-	default:
-	case TRANSMISSION_MODE_8K:
-		value |= (1 << 7);
-		break;
-	}
-	switch (ch->guard_interval) {
-	case GUARD_INTERVAL_1_32:
-		value |= (0 << 5);
-		break;
-	case GUARD_INTERVAL_1_16:
-		value |= (1 << 5);
-		break;
-	case GUARD_INTERVAL_1_4:
-		value |= (3 << 5);
-		break;
-	default:
-	case GUARD_INTERVAL_1_8:
-		value |= (2 << 5);
-		break;
-	}
-	switch (ch->modulation) {
-	case QPSK:
-		value |= (0 << 3);
-		break;
-	case QAM_16:
-		value |= (1 << 3);
-		break;
-	default:
-	case QAM_64:
-		value |= (2 << 3);
-		break;
-	}
-	switch (HIERARCHY_1) {
-	case HIERARCHY_2:
-		value |= 2;
-		break;
-	case HIERARCHY_4:
-		value |= 4;
-		break;
-	default:
-	case HIERARCHY_1:
-		value |= 1;
-		break;
-	}
-	dib7000p_write_word(state, 0, value);
-	dib7000p_write_word(state, 5, (seq << 4) | 1);	/* do not force tps, search list 0 */
-
-	/* P_dintl_native, P_dintlv_inv, P_hrch, P_code_rate, P_select_hp */
-	value = 0;
-	if (1 != 0)
-		value |= (1 << 6);
-	if (ch->hierarchy == 1)
-		value |= (1 << 4);
-	if (1 == 1)
-		value |= 1;
-	switch ((ch->hierarchy == 0 || 1 == 1) ? ch->code_rate_HP : ch->code_rate_LP) {
-	case FEC_2_3:
-		value |= (2 << 1);
-		break;
-	case FEC_3_4:
-		value |= (3 << 1);
-		break;
-	case FEC_5_6:
-		value |= (5 << 1);
-		break;
-	case FEC_7_8:
-		value |= (7 << 1);
-		break;
-	default:
-	case FEC_1_2:
-		value |= (1 << 1);
-		break;
-	}
-	dib7000p_write_word(state, 208, value);
-
-	/* offset loop parameters */
-	dib7000p_write_word(state, 26, 0x6680);
-	dib7000p_write_word(state, 32, 0x0003);
-	dib7000p_write_word(state, 29, 0x1273);
-	dib7000p_write_word(state, 33, 0x0005);
-
-	/* P_dvsy_sync_wait */
-	switch (ch->transmission_mode) {
-	case TRANSMISSION_MODE_8K:
-		value = 256;
-		break;
-	case TRANSMISSION_MODE_4K:
-		value = 128;
-		break;
-	case TRANSMISSION_MODE_2K:
-	default:
-		value = 64;
-		break;
-	}
-	switch (ch->guard_interval) {
-	case GUARD_INTERVAL_1_16:
-		value *= 2;
-		break;
-	case GUARD_INTERVAL_1_8:
-		value *= 4;
-		break;
-	case GUARD_INTERVAL_1_4:
-		value *= 8;
-		break;
-	default:
-	case GUARD_INTERVAL_1_32:
-		value *= 1;
-		break;
-	}
-	if (state->cfg.diversity_delay == 0)
-		state->div_sync_wait = (value * 3) / 2 + 48;
-	else
-		state->div_sync_wait = (value * 3) / 2 + state->cfg.diversity_delay;
-
-	/* deactive the possibility of diversity reception if extended interleaver */
-	state->div_force_off = !1 && ch->transmission_mode != TRANSMISSION_MODE_8K;
-	dib7000p_set_diversity_in(&state->demod, state->div_state);
-
-	/* channel estimation fine configuration */
-	switch (ch->modulation) {
-	case QAM_64:
-		est[0] = 0x0148;	/* P_adp_regul_cnt 0.04 */
-		est[1] = 0xfff0;	/* P_adp_noise_cnt -0.002 */
-		est[2] = 0x00a4;	/* P_adp_regul_ext 0.02 */
-		est[3] = 0xfff8;	/* P_adp_noise_ext -0.001 */
-		break;
-	case QAM_16:
-		est[0] = 0x023d;	/* P_adp_regul_cnt 0.07 */
-		est[1] = 0xffdf;	/* P_adp_noise_cnt -0.004 */
-		est[2] = 0x00a4;	/* P_adp_regul_ext 0.02 */
-		est[3] = 0xfff0;	/* P_adp_noise_ext -0.002 */
-		break;
-	default:
-		est[0] = 0x099a;	/* P_adp_regul_cnt 0.3 */
-		est[1] = 0xffae;	/* P_adp_noise_cnt -0.01 */
-		est[2] = 0x0333;	/* P_adp_regul_ext 0.1 */
-		est[3] = 0xfff8;	/* P_adp_noise_ext -0.002 */
-		break;
-	}
-	for (value = 0; value < 4; value++)
-		dib7000p_write_word(state, 187 + value, est[value]);
-}
-
-static int dib7000p_autosearch_start(struct dvb_frontend *demod)
-{
-	struct dtv_frontend_properties *ch = &demod->dtv_property_cache;
-	struct dib7000p_state *state = demod->demodulator_priv;
-	struct dtv_frontend_properties schan;
-	u32 value, factor;
-	u32 internal = dib7000p_get_internal_freq(state);
-
-	schan = *ch;
-	schan.modulation = QAM_64;
-	schan.guard_interval = GUARD_INTERVAL_1_32;
-	schan.transmission_mode = TRANSMISSION_MODE_8K;
-	schan.code_rate_HP = FEC_2_3;
-	schan.code_rate_LP = FEC_3_4;
-	schan.hierarchy = 0;
-
-	dib7000p_set_channel(state, &schan, 7);
-
-	factor = BANDWIDTH_TO_KHZ(ch->bandwidth_hz);
-	if (factor >= 5000) {
-		if (state->version == SOC7090)
-			factor = 2;
-		else
-			factor = 1;
-	} else
-		factor = 6;
-
-	value = 30 * internal * factor;
-	dib7000p_write_word(state, 6, (u16) ((value >> 16) & 0xffff));
-	dib7000p_write_word(state, 7, (u16) (value & 0xffff));
-	value = 100 * internal * factor;
-	dib7000p_write_word(state, 8, (u16) ((value >> 16) & 0xffff));
-	dib7000p_write_word(state, 9, (u16) (value & 0xffff));
-	value = 500 * internal * factor;
-	dib7000p_write_word(state, 10, (u16) ((value >> 16) & 0xffff));
-	dib7000p_write_word(state, 11, (u16) (value & 0xffff));
-
-	value = dib7000p_read_word(state, 0);
-	dib7000p_write_word(state, 0, (u16) ((1 << 9) | value));
-	dib7000p_read_word(state, 1284);
-	dib7000p_write_word(state, 0, (u16) value);
-
-	return 0;
-}
-
-static int dib7000p_autosearch_is_irq(struct dvb_frontend *demod)
-{
-	struct dib7000p_state *state = demod->demodulator_priv;
-	u16 irq_pending = dib7000p_read_word(state, 1284);
-
-	if (irq_pending & 0x1)
-		return 1;
-
-	if (irq_pending & 0x2)
-		return 2;
-
-	return 0;
-}
-
-static void dib7000p_spur_protect(struct dib7000p_state *state, u32 rf_khz, u32 bw)
-{
-	static s16 notch[] = { 16143, 14402, 12238, 9713, 6902, 3888, 759, -2392 };
-	static u8 sine[] = { 0, 2, 3, 5, 6, 8, 9, 11, 13, 14, 16, 17, 19, 20, 22,
-		24, 25, 27, 28, 30, 31, 33, 34, 36, 38, 39, 41, 42, 44, 45, 47, 48, 50, 51,
-		53, 55, 56, 58, 59, 61, 62, 64, 65, 67, 68, 70, 71, 73, 74, 76, 77, 79, 80,
-		82, 83, 85, 86, 88, 89, 91, 92, 94, 95, 97, 98, 99, 101, 102, 104, 105,
-		107, 108, 109, 111, 112, 114, 115, 117, 118, 119, 121, 122, 123, 125, 126,
-		128, 129, 130, 132, 133, 134, 136, 137, 138, 140, 141, 142, 144, 145, 146,
-		147, 149, 150, 151, 152, 154, 155, 156, 157, 159, 160, 161, 162, 164, 165,
-		166, 167, 168, 170, 171, 172, 173, 174, 175, 177, 178, 179, 180, 181, 182,
-		183, 184, 185, 186, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198,
-		199, 200, 201, 202, 203, 204, 205, 206, 207, 207, 208, 209, 210, 211, 212,
-		213, 214, 215, 215, 216, 217, 218, 219, 220, 220, 221, 222, 223, 224, 224,
-		225, 226, 227, 227, 228, 229, 229, 230, 231, 231, 232, 233, 233, 234, 235,
-		235, 236, 237, 237, 238, 238, 239, 239, 240, 241, 241, 242, 242, 243, 243,
-		244, 244, 245, 245, 245, 246, 246, 247, 247, 248, 248, 248, 249, 249, 249,
-		250, 250, 250, 251, 251, 251, 252, 252, 252, 252, 253, 253, 253, 253, 254,
-		254, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
-		255, 255, 255, 255, 255, 255
-	};
-
-	u32 xtal = state->cfg.bw->xtal_hz / 1000;
-	int f_rel = DIV_ROUND_CLOSEST(rf_khz, xtal) * xtal - rf_khz;
-	int k;
-	int coef_re[8], coef_im[8];
-	int bw_khz = bw;
-	u32 pha;
-
-	dprintk("relative position of the Spur: %dk (RF: %dk, XTAL: %dk)", f_rel, rf_khz, xtal);
-
-	if (f_rel < -bw_khz / 2 || f_rel > bw_khz / 2)
-		return;
-
-	bw_khz /= 100;
-
-	dib7000p_write_word(state, 142, 0x0610);
-
-	for (k = 0; k < 8; k++) {
-		pha = ((f_rel * (k + 1) * 112 * 80 / bw_khz) / 1000) & 0x3ff;
-
-		if (pha == 0) {
-			coef_re[k] = 256;
-			coef_im[k] = 0;
-		} else if (pha < 256) {
-			coef_re[k] = sine[256 - (pha & 0xff)];
-			coef_im[k] = sine[pha & 0xff];
-		} else if (pha == 256) {
-			coef_re[k] = 0;
-			coef_im[k] = 256;
-		} else if (pha < 512) {
-			coef_re[k] = -sine[pha & 0xff];
-			coef_im[k] = sine[256 - (pha & 0xff)];
-		} else if (pha == 512) {
-			coef_re[k] = -256;
-			coef_im[k] = 0;
-		} else if (pha < 768) {
-			coef_re[k] = -sine[256 - (pha & 0xff)];
-			coef_im[k] = -sine[pha & 0xff];
-		} else if (pha == 768) {
-			coef_re[k] = 0;
-			coef_im[k] = -256;
-		} else {
-			coef_re[k] = sine[pha & 0xff];
-			coef_im[k] = -sine[256 - (pha & 0xff)];
-		}
-
-		coef_re[k] *= notch[k];
-		coef_re[k] += (1 << 14);
-		if (coef_re[k] >= (1 << 24))
-			coef_re[k] = (1 << 24) - 1;
-		coef_re[k] /= (1 << 15);
-
-		coef_im[k] *= notch[k];
-		coef_im[k] += (1 << 14);
-		if (coef_im[k] >= (1 << 24))
-			coef_im[k] = (1 << 24) - 1;
-		coef_im[k] /= (1 << 15);
-
-		dprintk("PALF COEF: %d re: %d im: %d", k, coef_re[k], coef_im[k]);
-
-		dib7000p_write_word(state, 143, (0 << 14) | (k << 10) | (coef_re[k] & 0x3ff));
-		dib7000p_write_word(state, 144, coef_im[k] & 0x3ff);
-		dib7000p_write_word(state, 143, (1 << 14) | (k << 10) | (coef_re[k] & 0x3ff));
-	}
-	dib7000p_write_word(state, 143, 0);
-}
-
-static int dib7000p_tune(struct dvb_frontend *demod)
-{
-	struct dtv_frontend_properties *ch = &demod->dtv_property_cache;
-	struct dib7000p_state *state = demod->demodulator_priv;
-	u16 tmp = 0;
-
-	if (ch != NULL)
-		dib7000p_set_channel(state, ch, 0);
-	else
-		return -EINVAL;
-
-	// restart demod
-	dib7000p_write_word(state, 770, 0x4000);
-	dib7000p_write_word(state, 770, 0x0000);
-	msleep(45);
-
-	/* P_ctrl_inh_cor=0, P_ctrl_alpha_cor=4, P_ctrl_inh_isi=0, P_ctrl_alpha_isi=3, P_ctrl_inh_cor4=1, P_ctrl_alpha_cor4=3 */
-	tmp = (0 << 14) | (4 << 10) | (0 << 9) | (3 << 5) | (1 << 4) | (0x3);
-	if (state->sfn_workaround_active) {
-		dprintk("SFN workaround is active");
-		tmp |= (1 << 9);
-		dib7000p_write_word(state, 166, 0x4000);
-	} else {
-		dib7000p_write_word(state, 166, 0x0000);
-	}
-	dib7000p_write_word(state, 29, tmp);
-
-	// never achieved a lock with that bandwidth so far - wait for osc-freq to update
-	if (state->timf == 0)
-		msleep(200);
-
-	/* offset loop parameters */
-
-	/* P_timf_alpha, P_corm_alpha=6, P_corm_thres=0x80 */
-	tmp = (6 << 8) | 0x80;
-	switch (ch->transmission_mode) {
-	case TRANSMISSION_MODE_2K:
-		tmp |= (2 << 12);
-		break;
-	case TRANSMISSION_MODE_4K:
-		tmp |= (3 << 12);
-		break;
-	default:
-	case TRANSMISSION_MODE_8K:
-		tmp |= (4 << 12);
-		break;
-	}
-	dib7000p_write_word(state, 26, tmp);	/* timf_a(6xxx) */
-
-	/* P_ctrl_freeze_pha_shift=0, P_ctrl_pha_off_max */
-	tmp = (0 << 4);
-	switch (ch->transmission_mode) {
-	case TRANSMISSION_MODE_2K:
-		tmp |= 0x6;
-		break;
-	case TRANSMISSION_MODE_4K:
-		tmp |= 0x7;
-		break;
-	default:
-	case TRANSMISSION_MODE_8K:
-		tmp |= 0x8;
-		break;
-	}
-	dib7000p_write_word(state, 32, tmp);
-
-	/* P_ctrl_sfreq_inh=0, P_ctrl_sfreq_step */
-	tmp = (0 << 4);
-	switch (ch->transmission_mode) {
-	case TRANSMISSION_MODE_2K:
-		tmp |= 0x6;
-		break;
-	case TRANSMISSION_MODE_4K:
-		tmp |= 0x7;
-		break;
-	default:
-	case TRANSMISSION_MODE_8K:
-		tmp |= 0x8;
-		break;
-	}
-	dib7000p_write_word(state, 33, tmp);
-
-	tmp = dib7000p_read_word(state, 509);
-	if (!((tmp >> 6) & 0x1)) {
-		/* restart the fec */
-		tmp = dib7000p_read_word(state, 771);
-		dib7000p_write_word(state, 771, tmp | (1 << 1));
-		dib7000p_write_word(state, 771, tmp);
-		msleep(40);
-		tmp = dib7000p_read_word(state, 509);
-	}
-	// we achieved a lock - it's time to update the osc freq
-	if ((tmp >> 6) & 0x1) {
-		dib7000p_update_timf(state);
-		/* P_timf_alpha += 2 */
-		tmp = dib7000p_read_word(state, 26);
-		dib7000p_write_word(state, 26, (tmp & ~(0xf << 12)) | ((((tmp >> 12) & 0xf) + 5) << 12));
-	}
-
-	if (state->cfg.spur_protect)
-		dib7000p_spur_protect(state, ch->frequency / 1000, BANDWIDTH_TO_KHZ(ch->bandwidth_hz));
-
-	dib7000p_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->bandwidth_hz));
-	return 0;
-}
-
-static int dib7000p_wakeup(struct dvb_frontend *demod)
-{
-	struct dib7000p_state *state = demod->demodulator_priv;
-	dib7000p_set_power_mode(state, DIB7000P_POWER_ALL);
-	dib7000p_set_adc_state(state, DIBX000_SLOW_ADC_ON);
-	if (state->version == SOC7090)
-		dib7000p_sad_calib(state);
-	return 0;
-}
-
-static int dib7000p_sleep(struct dvb_frontend *demod)
-{
-	struct dib7000p_state *state = demod->demodulator_priv;
-	if (state->version == SOC7090)
-		return dib7000p_set_power_mode(state, DIB7000P_POWER_INTERFACE_ONLY);
-	return dib7000p_set_output_mode(state, OUTMODE_HIGH_Z) | dib7000p_set_power_mode(state, DIB7000P_POWER_INTERFACE_ONLY);
-}
-
-static int dib7000p_identify(struct dib7000p_state *st)
-{
-	u16 value;
-	dprintk("checking demod on I2C address: %d (%x)", st->i2c_addr, st->i2c_addr);
-
-	if ((value = dib7000p_read_word(st, 768)) != 0x01b3) {
-		dprintk("wrong Vendor ID (read=0x%x)", value);
-		return -EREMOTEIO;
-	}
-
-	if ((value = dib7000p_read_word(st, 769)) != 0x4000) {
-		dprintk("wrong Device ID (%x)", value);
-		return -EREMOTEIO;
-	}
-
-	return 0;
-}
-
-static int dib7000p_get_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
-	struct dib7000p_state *state = fe->demodulator_priv;
-	u16 tps = dib7000p_read_word(state, 463);
-
-	fep->inversion = INVERSION_AUTO;
-
-	fep->bandwidth_hz = BANDWIDTH_TO_HZ(state->current_bandwidth);
-
-	switch ((tps >> 8) & 0x3) {
-	case 0:
-		fep->transmission_mode = TRANSMISSION_MODE_2K;
-		break;
-	case 1:
-		fep->transmission_mode = TRANSMISSION_MODE_8K;
-		break;
-	/* case 2: fep->transmission_mode = TRANSMISSION_MODE_4K; break; */
-	}
-
-	switch (tps & 0x3) {
-	case 0:
-		fep->guard_interval = GUARD_INTERVAL_1_32;
-		break;
-	case 1:
-		fep->guard_interval = GUARD_INTERVAL_1_16;
-		break;
-	case 2:
-		fep->guard_interval = GUARD_INTERVAL_1_8;
-		break;
-	case 3:
-		fep->guard_interval = GUARD_INTERVAL_1_4;
-		break;
-	}
-
-	switch ((tps >> 14) & 0x3) {
-	case 0:
-		fep->modulation = QPSK;
-		break;
-	case 1:
-		fep->modulation = QAM_16;
-		break;
-	case 2:
-	default:
-		fep->modulation = QAM_64;
-		break;
-	}
-
-	/* as long as the frontend_param structure is fixed for hierarchical transmission I refuse to use it */
-	/* (tps >> 13) & 0x1 == hrch is used, (tps >> 10) & 0x7 == alpha */
-
-	fep->hierarchy = HIERARCHY_NONE;
-	switch ((tps >> 5) & 0x7) {
-	case 1:
-		fep->code_rate_HP = FEC_1_2;
-		break;
-	case 2:
-		fep->code_rate_HP = FEC_2_3;
-		break;
-	case 3:
-		fep->code_rate_HP = FEC_3_4;
-		break;
-	case 5:
-		fep->code_rate_HP = FEC_5_6;
-		break;
-	case 7:
-	default:
-		fep->code_rate_HP = FEC_7_8;
-		break;
-
-	}
-
-	switch ((tps >> 2) & 0x7) {
-	case 1:
-		fep->code_rate_LP = FEC_1_2;
-		break;
-	case 2:
-		fep->code_rate_LP = FEC_2_3;
-		break;
-	case 3:
-		fep->code_rate_LP = FEC_3_4;
-		break;
-	case 5:
-		fep->code_rate_LP = FEC_5_6;
-		break;
-	case 7:
-	default:
-		fep->code_rate_LP = FEC_7_8;
-		break;
-	}
-
-	/* native interleaver: (dib7000p_read_word(state, 464) >>  5) & 0x1 */
-
-	return 0;
-}
-
-static int dib7000p_set_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
-	struct dib7000p_state *state = fe->demodulator_priv;
-	int time, ret;
-
-	if (state->version == SOC7090)
-		dib7090_set_diversity_in(fe, 0);
-	else
-		dib7000p_set_output_mode(state, OUTMODE_HIGH_Z);
-
-	/* maybe the parameter has been changed */
-	state->sfn_workaround_active = buggy_sfn_workaround;
-
-	if (fe->ops.tuner_ops.set_params)
-		fe->ops.tuner_ops.set_params(fe);
-
-	/* start up the AGC */
-	state->agc_state = 0;
-	do {
-		time = dib7000p_agc_startup(fe);
-		if (time != -1)
-			msleep(time);
-	} while (time != -1);
-
-	if (fep->transmission_mode == TRANSMISSION_MODE_AUTO ||
-		fep->guard_interval == GUARD_INTERVAL_AUTO || fep->modulation == QAM_AUTO || fep->code_rate_HP == FEC_AUTO) {
-		int i = 800, found;
-
-		dib7000p_autosearch_start(fe);
-		do {
-			msleep(1);
-			found = dib7000p_autosearch_is_irq(fe);
-		} while (found == 0 && i--);
-
-		dprintk("autosearch returns: %d", found);
-		if (found == 0 || found == 1)
-			return 0;
-
-		dib7000p_get_frontend(fe);
-	}
-
-	ret = dib7000p_tune(fe);
-
-	/* make this a config parameter */
-	if (state->version == SOC7090) {
-		dib7090_set_output_mode(fe, state->cfg.output_mode);
-		if (state->cfg.enMpegOutput == 0) {
-			dib7090_setDibTxMux(state, MPEG_ON_DIBTX);
-			dib7090_setHostBusMux(state, DIBTX_ON_HOSTBUS);
-		}
-	} else
-		dib7000p_set_output_mode(state, state->cfg.output_mode);
-
-	return ret;
-}
-
-static int dib7000p_read_status(struct dvb_frontend *fe, fe_status_t * stat)
-{
-	struct dib7000p_state *state = fe->demodulator_priv;
-	u16 lock = dib7000p_read_word(state, 509);
-
-	*stat = 0;
-
-	if (lock & 0x8000)
-		*stat |= FE_HAS_SIGNAL;
-	if (lock & 0x3000)
-		*stat |= FE_HAS_CARRIER;
-	if (lock & 0x0100)
-		*stat |= FE_HAS_VITERBI;
-	if (lock & 0x0010)
-		*stat |= FE_HAS_SYNC;
-	if ((lock & 0x0038) == 0x38)
-		*stat |= FE_HAS_LOCK;
-
-	return 0;
-}
-
-static int dib7000p_read_ber(struct dvb_frontend *fe, u32 * ber)
-{
-	struct dib7000p_state *state = fe->demodulator_priv;
-	*ber = (dib7000p_read_word(state, 500) << 16) | dib7000p_read_word(state, 501);
-	return 0;
-}
-
-static int dib7000p_read_unc_blocks(struct dvb_frontend *fe, u32 * unc)
-{
-	struct dib7000p_state *state = fe->demodulator_priv;
-	*unc = dib7000p_read_word(state, 506);
-	return 0;
-}
-
-static int dib7000p_read_signal_strength(struct dvb_frontend *fe, u16 * strength)
-{
-	struct dib7000p_state *state = fe->demodulator_priv;
-	u16 val = dib7000p_read_word(state, 394);
-	*strength = 65535 - val;
-	return 0;
-}
-
-static int dib7000p_read_snr(struct dvb_frontend *fe, u16 * snr)
-{
-	struct dib7000p_state *state = fe->demodulator_priv;
-	u16 val;
-	s32 signal_mant, signal_exp, noise_mant, noise_exp;
-	u32 result = 0;
-
-	val = dib7000p_read_word(state, 479);
-	noise_mant = (val >> 4) & 0xff;
-	noise_exp = ((val & 0xf) << 2);
-	val = dib7000p_read_word(state, 480);
-	noise_exp += ((val >> 14) & 0x3);
-	if ((noise_exp & 0x20) != 0)
-		noise_exp -= 0x40;
-
-	signal_mant = (val >> 6) & 0xFF;
-	signal_exp = (val & 0x3F);
-	if ((signal_exp & 0x20) != 0)
-		signal_exp -= 0x40;
-
-	if (signal_mant != 0)
-		result = intlog10(2) * 10 * signal_exp + 10 * intlog10(signal_mant);
-	else
-		result = intlog10(2) * 10 * signal_exp - 100;
-
-	if (noise_mant != 0)
-		result -= intlog10(2) * 10 * noise_exp + 10 * intlog10(noise_mant);
-	else
-		result -= intlog10(2) * 10 * noise_exp - 100;
-
-	*snr = result / ((1 << 24) / 10);
-	return 0;
-}
-
-static int dib7000p_fe_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings *tune)
-{
-	tune->min_delay_ms = 1000;
-	return 0;
-}
-
-static void dib7000p_release(struct dvb_frontend *demod)
-{
-	struct dib7000p_state *st = demod->demodulator_priv;
-	dibx000_exit_i2c_master(&st->i2c_master);
-	i2c_del_adapter(&st->dib7090_tuner_adap);
-	kfree(st);
-}
-
-int dib7000pc_detection(struct i2c_adapter *i2c_adap)
-{
-	u8 *tx, *rx;
-	struct i2c_msg msg[2] = {
-		{.addr = 18 >> 1, .flags = 0, .len = 2},
-		{.addr = 18 >> 1, .flags = I2C_M_RD, .len = 2},
-	};
-	int ret = 0;
-
-	tx = kzalloc(2*sizeof(u8), GFP_KERNEL);
-	if (!tx)
-		return -ENOMEM;
-	rx = kzalloc(2*sizeof(u8), GFP_KERNEL);
-	if (!rx) {
-		ret = -ENOMEM;
-		goto rx_memory_error;
-	}
-
-	msg[0].buf = tx;
-	msg[1].buf = rx;
-
-	tx[0] = 0x03;
-	tx[1] = 0x00;
-
-	if (i2c_transfer(i2c_adap, msg, 2) == 2)
-		if (rx[0] == 0x01 && rx[1] == 0xb3) {
-			dprintk("-D-  DiB7000PC detected");
-			return 1;
-		}
-
-	msg[0].addr = msg[1].addr = 0x40;
-
-	if (i2c_transfer(i2c_adap, msg, 2) == 2)
-		if (rx[0] == 0x01 && rx[1] == 0xb3) {
-			dprintk("-D-  DiB7000PC detected");
-			return 1;
-		}
-
-	dprintk("-D-  DiB7000PC not detected");
-
-	kfree(rx);
-rx_memory_error:
-	kfree(tx);
-	return ret;
-}
-EXPORT_SYMBOL(dib7000pc_detection);
-
-struct i2c_adapter *dib7000p_get_i2c_master(struct dvb_frontend *demod, enum dibx000_i2c_interface intf, int gating)
-{
-	struct dib7000p_state *st = demod->demodulator_priv;
-	return dibx000_get_i2c_adapter(&st->i2c_master, intf, gating);
-}
-EXPORT_SYMBOL(dib7000p_get_i2c_master);
-
-int dib7000p_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
-{
-	struct dib7000p_state *state = fe->demodulator_priv;
-	u16 val = dib7000p_read_word(state, 235) & 0xffef;
-	val |= (onoff & 0x1) << 4;
-	dprintk("PID filter enabled %d", onoff);
-	return dib7000p_write_word(state, 235, val);
-}
-EXPORT_SYMBOL(dib7000p_pid_filter_ctrl);
-
-int dib7000p_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
-{
-	struct dib7000p_state *state = fe->demodulator_priv;
-	dprintk("PID filter: index %x, PID %d, OnOff %d", id, pid, onoff);
-	return dib7000p_write_word(state, 241 + id, onoff ? (1 << 13) | pid : 0);
-}
-EXPORT_SYMBOL(dib7000p_pid_filter);
-
-int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[])
-{
-	struct dib7000p_state *dpst;
-	int k = 0;
-	u8 new_addr = 0;
-
-	dpst = kzalloc(sizeof(struct dib7000p_state), GFP_KERNEL);
-	if (!dpst)
-		return -ENOMEM;
-
-	dpst->i2c_adap = i2c;
-	mutex_init(&dpst->i2c_buffer_lock);
-
-	for (k = no_of_demods - 1; k >= 0; k--) {
-		dpst->cfg = cfg[k];
-
-		/* designated i2c address */
-		if (cfg[k].default_i2c_addr != 0)
-			new_addr = cfg[k].default_i2c_addr + (k << 1);
-		else
-			new_addr = (0x40 + k) << 1;
-		dpst->i2c_addr = new_addr;
-		dib7000p_write_word(dpst, 1287, 0x0003);	/* sram lead in, rdy */
-		if (dib7000p_identify(dpst) != 0) {
-			dpst->i2c_addr = default_addr;
-			dib7000p_write_word(dpst, 1287, 0x0003);	/* sram lead in, rdy */
-			if (dib7000p_identify(dpst) != 0) {
-				dprintk("DiB7000P #%d: not identified\n", k);
-				kfree(dpst);
-				return -EIO;
-			}
-		}
-
-		/* start diversity to pull_down div_str - just for i2c-enumeration */
-		dib7000p_set_output_mode(dpst, OUTMODE_DIVERSITY);
-
-		/* set new i2c address and force divstart */
-		dib7000p_write_word(dpst, 1285, (new_addr << 2) | 0x2);
-
-		dprintk("IC %d initialized (to i2c_address 0x%x)", k, new_addr);
-	}
-
-	for (k = 0; k < no_of_demods; k++) {
-		dpst->cfg = cfg[k];
-		if (cfg[k].default_i2c_addr != 0)
-			dpst->i2c_addr = (cfg[k].default_i2c_addr + k) << 1;
-		else
-			dpst->i2c_addr = (0x40 + k) << 1;
-
-		// unforce divstr
-		dib7000p_write_word(dpst, 1285, dpst->i2c_addr << 2);
-
-		/* deactivate div - it was just for i2c-enumeration */
-		dib7000p_set_output_mode(dpst, OUTMODE_HIGH_Z);
-	}
-
-	kfree(dpst);
-	return 0;
-}
-EXPORT_SYMBOL(dib7000p_i2c_enumeration);
-
-static const s32 lut_1000ln_mant[] = {
-	6908, 6956, 7003, 7047, 7090, 7131, 7170, 7208, 7244, 7279, 7313, 7346, 7377, 7408, 7438, 7467, 7495, 7523, 7549, 7575, 7600
-};
-
-static s32 dib7000p_get_adc_power(struct dvb_frontend *fe)
-{
-	struct dib7000p_state *state = fe->demodulator_priv;
-	u32 tmp_val = 0, exp = 0, mant = 0;
-	s32 pow_i;
-	u16 buf[2];
-	u8 ix = 0;
-
-	buf[0] = dib7000p_read_word(state, 0x184);
-	buf[1] = dib7000p_read_word(state, 0x185);
-	pow_i = (buf[0] << 16) | buf[1];
-	dprintk("raw pow_i = %d", pow_i);
-
-	tmp_val = pow_i;
-	while (tmp_val >>= 1)
-		exp++;
-
-	mant = (pow_i * 1000 / (1 << exp));
-	dprintk(" mant = %d exp = %d", mant / 1000, exp);
-
-	ix = (u8) ((mant - 1000) / 100);	/* index of the LUT */
-	dprintk(" ix = %d", ix);
-
-	pow_i = (lut_1000ln_mant[ix] + 693 * (exp - 20) - 6908);
-	pow_i = (pow_i << 8) / 1000;
-	dprintk(" pow_i = %d", pow_i);
-
-	return pow_i;
-}
-
-static int map_addr_to_serpar_number(struct i2c_msg *msg)
-{
-	if ((msg->buf[0] <= 15))
-		msg->buf[0] -= 1;
-	else if (msg->buf[0] == 17)
-		msg->buf[0] = 15;
-	else if (msg->buf[0] == 16)
-		msg->buf[0] = 17;
-	else if (msg->buf[0] == 19)
-		msg->buf[0] = 16;
-	else if (msg->buf[0] >= 21 && msg->buf[0] <= 25)
-		msg->buf[0] -= 3;
-	else if (msg->buf[0] == 28)
-		msg->buf[0] = 23;
-	else
-		return -EINVAL;
-	return 0;
-}
-
-static int w7090p_tuner_write_serpar(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)
-{
-	struct dib7000p_state *state = i2c_get_adapdata(i2c_adap);
-	u8 n_overflow = 1;
-	u16 i = 1000;
-	u16 serpar_num = msg[0].buf[0];
-
-	while (n_overflow == 1 && i) {
-		n_overflow = (dib7000p_read_word(state, 1984) >> 1) & 0x1;
-		i--;
-		if (i == 0)
-			dprintk("Tuner ITF: write busy (overflow)");
-	}
-	dib7000p_write_word(state, 1985, (1 << 6) | (serpar_num & 0x3f));
-	dib7000p_write_word(state, 1986, (msg[0].buf[1] << 8) | msg[0].buf[2]);
-
-	return num;
-}
-
-static int w7090p_tuner_read_serpar(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)
-{
-	struct dib7000p_state *state = i2c_get_adapdata(i2c_adap);
-	u8 n_overflow = 1, n_empty = 1;
-	u16 i = 1000;
-	u16 serpar_num = msg[0].buf[0];
-	u16 read_word;
-
-	while (n_overflow == 1 && i) {
-		n_overflow = (dib7000p_read_word(state, 1984) >> 1) & 0x1;
-		i--;
-		if (i == 0)
-			dprintk("TunerITF: read busy (overflow)");
-	}
-	dib7000p_write_word(state, 1985, (0 << 6) | (serpar_num & 0x3f));
-
-	i = 1000;
-	while (n_empty == 1 && i) {
-		n_empty = dib7000p_read_word(state, 1984) & 0x1;
-		i--;
-		if (i == 0)
-			dprintk("TunerITF: read busy (empty)");
-	}
-	read_word = dib7000p_read_word(state, 1987);
-	msg[1].buf[0] = (read_word >> 8) & 0xff;
-	msg[1].buf[1] = (read_word) & 0xff;
-
-	return num;
-}
-
-static int w7090p_tuner_rw_serpar(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)
-{
-	if (map_addr_to_serpar_number(&msg[0]) == 0) {	/* else = Tuner regs to ignore : DIG_CFG, CTRL_RF_LT, PLL_CFG, PWM1_REG, ADCCLK, DIG_CFG_3; SLEEP_EN... */
-		if (num == 1) {	/* write */
-			return w7090p_tuner_write_serpar(i2c_adap, msg, 1);
-		} else {	/* read */
-			return w7090p_tuner_read_serpar(i2c_adap, msg, 2);
-		}
-	}
-	return num;
-}
-
-static int dib7090p_rw_on_apb(struct i2c_adapter *i2c_adap,
-		struct i2c_msg msg[], int num, u16 apb_address)
-{
-	struct dib7000p_state *state = i2c_get_adapdata(i2c_adap);
-	u16 word;
-
-	if (num == 1) {		/* write */
-		dib7000p_write_word(state, apb_address, ((msg[0].buf[1] << 8) | (msg[0].buf[2])));
-	} else {
-		word = dib7000p_read_word(state, apb_address);
-		msg[1].buf[0] = (word >> 8) & 0xff;
-		msg[1].buf[1] = (word) & 0xff;
-	}
-
-	return num;
-}
-
-static int dib7090_tuner_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)
-{
-	struct dib7000p_state *state = i2c_get_adapdata(i2c_adap);
-
-	u16 apb_address = 0, word;
-	int i = 0;
-	switch (msg[0].buf[0]) {
-	case 0x12:
-		apb_address = 1920;
-		break;
-	case 0x14:
-		apb_address = 1921;
-		break;
-	case 0x24:
-		apb_address = 1922;
-		break;
-	case 0x1a:
-		apb_address = 1923;
-		break;
-	case 0x22:
-		apb_address = 1924;
-		break;
-	case 0x33:
-		apb_address = 1926;
-		break;
-	case 0x34:
-		apb_address = 1927;
-		break;
-	case 0x35:
-		apb_address = 1928;
-		break;
-	case 0x36:
-		apb_address = 1929;
-		break;
-	case 0x37:
-		apb_address = 1930;
-		break;
-	case 0x38:
-		apb_address = 1931;
-		break;
-	case 0x39:
-		apb_address = 1932;
-		break;
-	case 0x2a:
-		apb_address = 1935;
-		break;
-	case 0x2b:
-		apb_address = 1936;
-		break;
-	case 0x2c:
-		apb_address = 1937;
-		break;
-	case 0x2d:
-		apb_address = 1938;
-		break;
-	case 0x2e:
-		apb_address = 1939;
-		break;
-	case 0x2f:
-		apb_address = 1940;
-		break;
-	case 0x30:
-		apb_address = 1941;
-		break;
-	case 0x31:
-		apb_address = 1942;
-		break;
-	case 0x32:
-		apb_address = 1943;
-		break;
-	case 0x3e:
-		apb_address = 1944;
-		break;
-	case 0x3f:
-		apb_address = 1945;
-		break;
-	case 0x40:
-		apb_address = 1948;
-		break;
-	case 0x25:
-		apb_address = 914;
-		break;
-	case 0x26:
-		apb_address = 915;
-		break;
-	case 0x27:
-		apb_address = 917;
-		break;
-	case 0x28:
-		apb_address = 916;
-		break;
-	case 0x1d:
-		i = ((dib7000p_read_word(state, 72) >> 12) & 0x3);
-		word = dib7000p_read_word(state, 384 + i);
-		msg[1].buf[0] = (word >> 8) & 0xff;
-		msg[1].buf[1] = (word) & 0xff;
-		return num;
-	case 0x1f:
-		if (num == 1) {	/* write */
-			word = (u16) ((msg[0].buf[1] << 8) | msg[0].buf[2]);
-			word &= 0x3;
-			word = (dib7000p_read_word(state, 72) & ~(3 << 12)) | (word << 12);
-			dib7000p_write_word(state, 72, word);	/* Set the proper input */
-			return num;
-		}
-	}
-
-	if (apb_address != 0)	/* R/W acces via APB */
-		return dib7090p_rw_on_apb(i2c_adap, msg, num, apb_address);
-	else			/* R/W access via SERPAR  */
-		return w7090p_tuner_rw_serpar(i2c_adap, msg, num);
-
-	return 0;
-}
-
-static u32 dib7000p_i2c_func(struct i2c_adapter *adapter)
-{
-	return I2C_FUNC_I2C;
-}
-
-static struct i2c_algorithm dib7090_tuner_xfer_algo = {
-	.master_xfer = dib7090_tuner_xfer,
-	.functionality = dib7000p_i2c_func,
-};
-
-struct i2c_adapter *dib7090_get_i2c_tuner(struct dvb_frontend *fe)
-{
-	struct dib7000p_state *st = fe->demodulator_priv;
-	return &st->dib7090_tuner_adap;
-}
-EXPORT_SYMBOL(dib7090_get_i2c_tuner);
-
-static int dib7090_host_bus_drive(struct dib7000p_state *state, u8 drive)
-{
-	u16 reg;
-
-	/* drive host bus 2, 3, 4 */
-	reg = dib7000p_read_word(state, 1798) & ~((0x7) | (0x7 << 6) | (0x7 << 12));
-	reg |= (drive << 12) | (drive << 6) | drive;
-	dib7000p_write_word(state, 1798, reg);
-
-	/* drive host bus 5,6 */
-	reg = dib7000p_read_word(state, 1799) & ~((0x7 << 2) | (0x7 << 8));
-	reg |= (drive << 8) | (drive << 2);
-	dib7000p_write_word(state, 1799, reg);
-
-	/* drive host bus 7, 8, 9 */
-	reg = dib7000p_read_word(state, 1800) & ~((0x7) | (0x7 << 6) | (0x7 << 12));
-	reg |= (drive << 12) | (drive << 6) | drive;
-	dib7000p_write_word(state, 1800, reg);
-
-	/* drive host bus 10, 11 */
-	reg = dib7000p_read_word(state, 1801) & ~((0x7 << 2) | (0x7 << 8));
-	reg |= (drive << 8) | (drive << 2);
-	dib7000p_write_word(state, 1801, reg);
-
-	/* drive host bus 12, 13, 14 */
-	reg = dib7000p_read_word(state, 1802) & ~((0x7) | (0x7 << 6) | (0x7 << 12));
-	reg |= (drive << 12) | (drive << 6) | drive;
-	dib7000p_write_word(state, 1802, reg);
-
-	return 0;
-}
-
-static u32 dib7090_calcSyncFreq(u32 P_Kin, u32 P_Kout, u32 insertExtSynchro, u32 syncSize)
-{
-	u32 quantif = 3;
-	u32 nom = (insertExtSynchro * P_Kin + syncSize);
-	u32 denom = P_Kout;
-	u32 syncFreq = ((nom << quantif) / denom);
-
-	if ((syncFreq & ((1 << quantif) - 1)) != 0)
-		syncFreq = (syncFreq >> quantif) + 1;
-	else
-		syncFreq = (syncFreq >> quantif);
-
-	if (syncFreq != 0)
-		syncFreq = syncFreq - 1;
-
-	return syncFreq;
-}
-
-static int dib7090_cfg_DibTx(struct dib7000p_state *state, u32 P_Kin, u32 P_Kout, u32 insertExtSynchro, u32 synchroMode, u32 syncWord, u32 syncSize)
-{
-	dprintk("Configure DibStream Tx");
-
-	dib7000p_write_word(state, 1615, 1);
-	dib7000p_write_word(state, 1603, P_Kin);
-	dib7000p_write_word(state, 1605, P_Kout);
-	dib7000p_write_word(state, 1606, insertExtSynchro);
-	dib7000p_write_word(state, 1608, synchroMode);
-	dib7000p_write_word(state, 1609, (syncWord >> 16) & 0xffff);
-	dib7000p_write_word(state, 1610, syncWord & 0xffff);
-	dib7000p_write_word(state, 1612, syncSize);
-	dib7000p_write_word(state, 1615, 0);
-
-	return 0;
-}
-
-static int dib7090_cfg_DibRx(struct dib7000p_state *state, u32 P_Kin, u32 P_Kout, u32 synchroMode, u32 insertExtSynchro, u32 syncWord, u32 syncSize,
-		u32 dataOutRate)
-{
-	u32 syncFreq;
-
-	dprintk("Configure DibStream Rx");
-	if ((P_Kin != 0) && (P_Kout != 0)) {
-		syncFreq = dib7090_calcSyncFreq(P_Kin, P_Kout, insertExtSynchro, syncSize);
-		dib7000p_write_word(state, 1542, syncFreq);
-	}
-	dib7000p_write_word(state, 1554, 1);
-	dib7000p_write_word(state, 1536, P_Kin);
-	dib7000p_write_word(state, 1537, P_Kout);
-	dib7000p_write_word(state, 1539, synchroMode);
-	dib7000p_write_word(state, 1540, (syncWord >> 16) & 0xffff);
-	dib7000p_write_word(state, 1541, syncWord & 0xffff);
-	dib7000p_write_word(state, 1543, syncSize);
-	dib7000p_write_word(state, 1544, dataOutRate);
-	dib7000p_write_word(state, 1554, 0);
-
-	return 0;
-}
-
-static void dib7090_enMpegMux(struct dib7000p_state *state, int onoff)
-{
-	u16 reg_1287 = dib7000p_read_word(state, 1287);
-
-	switch (onoff) {
-	case 1:
-			reg_1287 &= ~(1<<7);
-			break;
-	case 0:
-			reg_1287 |= (1<<7);
-			break;
-	}
-
-	dib7000p_write_word(state, 1287, reg_1287);
-}
-
-static void dib7090_configMpegMux(struct dib7000p_state *state,
-		u16 pulseWidth, u16 enSerialMode, u16 enSerialClkDiv2)
-{
-	dprintk("Enable Mpeg mux");
-
-	dib7090_enMpegMux(state, 0);
-
-	/* If the input mode is MPEG do not divide the serial clock */
-	if ((enSerialMode == 1) && (state->input_mode_mpeg == 1))
-		enSerialClkDiv2 = 0;
-
-	dib7000p_write_word(state, 1287, ((pulseWidth & 0x1f) << 2)
-			| ((enSerialMode & 0x1) << 1)
-			| (enSerialClkDiv2 & 0x1));
-
-	dib7090_enMpegMux(state, 1);
-}
-
-static void dib7090_setDibTxMux(struct dib7000p_state *state, int mode)
-{
-	u16 reg_1288 = dib7000p_read_word(state, 1288) & ~(0x7 << 7);
-
-	switch (mode) {
-	case MPEG_ON_DIBTX:
-			dprintk("SET MPEG ON DIBSTREAM TX");
-			dib7090_cfg_DibTx(state, 8, 5, 0, 0, 0, 0);
-			reg_1288 |= (1<<9);
-			break;
-	case DIV_ON_DIBTX:
-			dprintk("SET DIV_OUT ON DIBSTREAM TX");
-			dib7090_cfg_DibTx(state, 5, 5, 0, 0, 0, 0);
-			reg_1288 |= (1<<8);
-			break;
-	case ADC_ON_DIBTX:
-			dprintk("SET ADC_OUT ON DIBSTREAM TX");
-			dib7090_cfg_DibTx(state, 20, 5, 10, 0, 0, 0);
-			reg_1288 |= (1<<7);
-			break;
-	default:
-			break;
-	}
-	dib7000p_write_word(state, 1288, reg_1288);
-}
-
-static void dib7090_setHostBusMux(struct dib7000p_state *state, int mode)
-{
-	u16 reg_1288 = dib7000p_read_word(state, 1288) & ~(0x7 << 4);
-
-	switch (mode) {
-	case DEMOUT_ON_HOSTBUS:
-			dprintk("SET DEM OUT OLD INTERF ON HOST BUS");
-			dib7090_enMpegMux(state, 0);
-			reg_1288 |= (1<<6);
-			break;
-	case DIBTX_ON_HOSTBUS:
-			dprintk("SET DIBSTREAM TX ON HOST BUS");
-			dib7090_enMpegMux(state, 0);
-			reg_1288 |= (1<<5);
-			break;
-	case MPEG_ON_HOSTBUS:
-			dprintk("SET MPEG MUX ON HOST BUS");
-			reg_1288 |= (1<<4);
-			break;
-	default:
-			break;
-	}
-	dib7000p_write_word(state, 1288, reg_1288);
-}
-
-int dib7090_set_diversity_in(struct dvb_frontend *fe, int onoff)
-{
-	struct dib7000p_state *state = fe->demodulator_priv;
-	u16 reg_1287;
-
-	switch (onoff) {
-	case 0: /* only use the internal way - not the diversity input */
-			dprintk("%s mode OFF : by default Enable Mpeg INPUT", __func__);
-			dib7090_cfg_DibRx(state, 8, 5, 0, 0, 0, 8, 0);
-
-			/* Do not divide the serial clock of MPEG MUX */
-			/* in SERIAL MODE in case input mode MPEG is used */
-			reg_1287 = dib7000p_read_word(state, 1287);
-			/* enSerialClkDiv2 == 1 ? */
-			if ((reg_1287 & 0x1) == 1) {
-				/* force enSerialClkDiv2 = 0 */
-				reg_1287 &= ~0x1;
-				dib7000p_write_word(state, 1287, reg_1287);
-			}
-			state->input_mode_mpeg = 1;
-			break;
-	case 1: /* both ways */
-	case 2: /* only the diversity input */
-			dprintk("%s ON : Enable diversity INPUT", __func__);
-			dib7090_cfg_DibRx(state, 5, 5, 0, 0, 0, 0, 0);
-			state->input_mode_mpeg = 0;
-			break;
-	}
-
-	dib7000p_set_diversity_in(&state->demod, onoff);
-	return 0;
-}
-
-static int dib7090_set_output_mode(struct dvb_frontend *fe, int mode)
-{
-	struct dib7000p_state *state = fe->demodulator_priv;
-
-	u16 outreg, smo_mode, fifo_threshold;
-	u8 prefer_mpeg_mux_use = 1;
-	int ret = 0;
-
-	dib7090_host_bus_drive(state, 1);
-
-	fifo_threshold = 1792;
-	smo_mode = (dib7000p_read_word(state, 235) & 0x0050) | (1 << 1);
-	outreg = dib7000p_read_word(state, 1286) & ~((1 << 10) | (0x7 << 6) | (1 << 1));
-
-	switch (mode) {
-	case OUTMODE_HIGH_Z:
-		outreg = 0;
-		break;
-
-	case OUTMODE_MPEG2_SERIAL:
-		if (prefer_mpeg_mux_use) {
-			dprintk("setting output mode TS_SERIAL using Mpeg Mux");
-			dib7090_configMpegMux(state, 3, 1, 1);
-			dib7090_setHostBusMux(state, MPEG_ON_HOSTBUS);
-		} else {/* Use Smooth block */
-			dprintk("setting output mode TS_SERIAL using Smooth bloc");
-			dib7090_setHostBusMux(state, DEMOUT_ON_HOSTBUS);
-			outreg |= (2<<6) | (0 << 1);
-		}
-		break;
-
-	case OUTMODE_MPEG2_PAR_GATED_CLK:
-		if (prefer_mpeg_mux_use) {
-			dprintk("setting output mode TS_PARALLEL_GATED using Mpeg Mux");
-			dib7090_configMpegMux(state, 2, 0, 0);
-			dib7090_setHostBusMux(state, MPEG_ON_HOSTBUS);
-		} else { /* Use Smooth block */
-			dprintk("setting output mode TS_PARALLEL_GATED using Smooth block");
-			dib7090_setHostBusMux(state, DEMOUT_ON_HOSTBUS);
-			outreg |= (0<<6);
-		}
-		break;
-
-	case OUTMODE_MPEG2_PAR_CONT_CLK:	/* Using Smooth block only */
-		dprintk("setting output mode TS_PARALLEL_CONT using Smooth block");
-		dib7090_setHostBusMux(state, DEMOUT_ON_HOSTBUS);
-		outreg |= (1<<6);
-		break;
-
-	case OUTMODE_MPEG2_FIFO:	/* Using Smooth block because not supported by new Mpeg Mux bloc */
-		dprintk("setting output mode TS_FIFO using Smooth block");
-		dib7090_setHostBusMux(state, DEMOUT_ON_HOSTBUS);
-		outreg |= (5<<6);
-		smo_mode |= (3 << 1);
-		fifo_threshold = 512;
-		break;
-
-	case OUTMODE_DIVERSITY:
-		dprintk("setting output mode MODE_DIVERSITY");
-		dib7090_setDibTxMux(state, DIV_ON_DIBTX);
-		dib7090_setHostBusMux(state, DIBTX_ON_HOSTBUS);
-		break;
-
-	case OUTMODE_ANALOG_ADC:
-		dprintk("setting output mode MODE_ANALOG_ADC");
-		dib7090_setDibTxMux(state, ADC_ON_DIBTX);
-		dib7090_setHostBusMux(state, DIBTX_ON_HOSTBUS);
-		break;
-	}
-	if (mode != OUTMODE_HIGH_Z)
-		outreg |= (1 << 10);
-
-	if (state->cfg.output_mpeg2_in_188_bytes)
-		smo_mode |= (1 << 5);
-
-	ret |= dib7000p_write_word(state, 235, smo_mode);
-	ret |= dib7000p_write_word(state, 236, fifo_threshold);	/* synchronous fread */
-	ret |= dib7000p_write_word(state, 1286, outreg);
-
-	return ret;
-}
-
-int dib7090_tuner_sleep(struct dvb_frontend *fe, int onoff)
-{
-	struct dib7000p_state *state = fe->demodulator_priv;
-	u16 en_cur_state;
-
-	dprintk("sleep dib7090: %d", onoff);
-
-	en_cur_state = dib7000p_read_word(state, 1922);
-
-	if (en_cur_state > 0xff)
-		state->tuner_enable = en_cur_state;
-
-	if (onoff)
-		en_cur_state &= 0x00ff;
-	else {
-		if (state->tuner_enable != 0)
-			en_cur_state = state->tuner_enable;
-	}
-
-	dib7000p_write_word(state, 1922, en_cur_state);
-
-	return 0;
-}
-EXPORT_SYMBOL(dib7090_tuner_sleep);
-
-int dib7090_get_adc_power(struct dvb_frontend *fe)
-{
-	return dib7000p_get_adc_power(fe);
-}
-EXPORT_SYMBOL(dib7090_get_adc_power);
-
-int dib7090_slave_reset(struct dvb_frontend *fe)
-{
-	struct dib7000p_state *state = fe->demodulator_priv;
-	u16 reg;
-
-	reg = dib7000p_read_word(state, 1794);
-	dib7000p_write_word(state, 1794, reg | (4 << 12));
-
-	dib7000p_write_word(state, 1032, 0xffff);
-	return 0;
-}
-EXPORT_SYMBOL(dib7090_slave_reset);
-
-static struct dvb_frontend_ops dib7000p_ops;
-struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg)
-{
-	struct dvb_frontend *demod;
-	struct dib7000p_state *st;
-	st = kzalloc(sizeof(struct dib7000p_state), GFP_KERNEL);
-	if (st == NULL)
-		return NULL;
-
-	memcpy(&st->cfg, cfg, sizeof(struct dib7000p_config));
-	st->i2c_adap = i2c_adap;
-	st->i2c_addr = i2c_addr;
-	st->gpio_val = cfg->gpio_val;
-	st->gpio_dir = cfg->gpio_dir;
-
-	/* Ensure the output mode remains at the previous default if it's
-	 * not specifically set by the caller.
-	 */
-	if ((st->cfg.output_mode != OUTMODE_MPEG2_SERIAL) && (st->cfg.output_mode != OUTMODE_MPEG2_PAR_GATED_CLK))
-		st->cfg.output_mode = OUTMODE_MPEG2_FIFO;
-
-	demod = &st->demod;
-	demod->demodulator_priv = st;
-	memcpy(&st->demod.ops, &dib7000p_ops, sizeof(struct dvb_frontend_ops));
-	mutex_init(&st->i2c_buffer_lock);
-
-	dib7000p_write_word(st, 1287, 0x0003);	/* sram lead in, rdy */
-
-	if (dib7000p_identify(st) != 0)
-		goto error;
-
-	st->version = dib7000p_read_word(st, 897);
-
-	/* FIXME: make sure the dev.parent field is initialized, or else
-	   request_firmware() will hit an OOPS (this should be moved somewhere
-	   more common) */
-	st->i2c_master.gated_tuner_i2c_adap.dev.parent = i2c_adap->dev.parent;
-
-	dibx000_init_i2c_master(&st->i2c_master, DIB7000P, st->i2c_adap, st->i2c_addr);
-
-	/* init 7090 tuner adapter */
-	strncpy(st->dib7090_tuner_adap.name, "DiB7090 tuner interface", sizeof(st->dib7090_tuner_adap.name));
-	st->dib7090_tuner_adap.algo = &dib7090_tuner_xfer_algo;
-	st->dib7090_tuner_adap.algo_data = NULL;
-	st->dib7090_tuner_adap.dev.parent = st->i2c_adap->dev.parent;
-	i2c_set_adapdata(&st->dib7090_tuner_adap, st);
-	i2c_add_adapter(&st->dib7090_tuner_adap);
-
-	dib7000p_demod_reset(st);
-
-	if (st->version == SOC7090) {
-		dib7090_set_output_mode(demod, st->cfg.output_mode);
-		dib7090_set_diversity_in(demod, 0);
-	}
-
-	return demod;
-
-error:
-	kfree(st);
-	return NULL;
-}
-EXPORT_SYMBOL(dib7000p_attach);
-
-static struct dvb_frontend_ops dib7000p_ops = {
-	.delsys = { SYS_DVBT },
-	.info = {
-		 .name = "DiBcom 7000PC",
-		 .frequency_min = 44250000,
-		 .frequency_max = 867250000,
-		 .frequency_stepsize = 62500,
-		 .caps = FE_CAN_INVERSION_AUTO |
-		 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_FEC_AUTO |
-		 FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
-		 FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_RECOVER | FE_CAN_HIERARCHY_AUTO,
-		 },
-
-	.release = dib7000p_release,
-
-	.init = dib7000p_wakeup,
-	.sleep = dib7000p_sleep,
-
-	.set_frontend = dib7000p_set_frontend,
-	.get_tune_settings = dib7000p_fe_get_tune_settings,
-	.get_frontend = dib7000p_get_frontend,
-
-	.read_status = dib7000p_read_status,
-	.read_ber = dib7000p_read_ber,
-	.read_signal_strength = dib7000p_read_signal_strength,
-	.read_snr = dib7000p_read_snr,
-	.read_ucblocks = dib7000p_read_unc_blocks,
-};
-
-MODULE_AUTHOR("Olivier Grenie <ogrenie@dibcom.fr>");
-MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
-MODULE_DESCRIPTION("Driver for the DiBcom 7000PC COFDM demodulator");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/dib7000p.h b/drivers/media/dvb/frontends/dib7000p.h
deleted file mode 100644
index b61b03a..0000000
--- a/drivers/media/dvb/frontends/dib7000p.h
+++ /dev/null
@@ -1,158 +0,0 @@
-#ifndef DIB7000P_H
-#define DIB7000P_H
-
-#include "dibx000_common.h"
-
-struct dib7000p_config {
-	u8 output_mpeg2_in_188_bytes;
-	u8 hostbus_diversity;
-	u8 tuner_is_baseband;
-	int (*update_lna) (struct dvb_frontend *, u16 agc_global);
-
-	u8 agc_config_count;
-	struct dibx000_agc_config *agc;
-	struct dibx000_bandwidth_config *bw;
-
-#define DIB7000P_GPIO_DEFAULT_DIRECTIONS 0xffff
-	u16 gpio_dir;
-#define DIB7000P_GPIO_DEFAULT_VALUES     0x0000
-	u16 gpio_val;
-#define DIB7000P_GPIO_PWM_POS0(v)        ((v & 0xf) << 12)
-#define DIB7000P_GPIO_PWM_POS1(v)        ((v & 0xf) << 8 )
-#define DIB7000P_GPIO_PWM_POS2(v)        ((v & 0xf) << 4 )
-#define DIB7000P_GPIO_PWM_POS3(v)         (v & 0xf)
-#define DIB7000P_GPIO_DEFAULT_PWM_POS    0xffff
-	u16 gpio_pwm_pos;
-
-	u16 pwm_freq_div;
-
-	u8 quartz_direct;
-
-	u8 spur_protect;
-
-	int (*agc_control) (struct dvb_frontend *, u8 before);
-
-	u8 output_mode;
-	u8 disable_sample_and_hold:1;
-
-	u8 enable_current_mirror:1;
-	u16 diversity_delay;
-
-	u8 default_i2c_addr;
-	u8 enMpegOutput:1;
-};
-
-#define DEFAULT_DIB7000P_I2C_ADDRESS 18
-
-#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);
-extern struct i2c_adapter *dib7000p_get_i2c_master(struct dvb_frontend *, enum dibx000_i2c_interface, int);
-extern int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, 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);
-extern int dib7000p_pid_filter(struct dvb_frontend *, u8 id, u16 pid, u8 onoff);
-extern int dib7000p_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff);
-extern int dib7000p_update_pll(struct dvb_frontend *fe, struct dibx000_bandwidth_config *bw);
-extern u32 dib7000p_ctrl_timf(struct dvb_frontend *fe, u8 op, u32 timf);
-extern int dib7090_tuner_sleep(struct dvb_frontend *fe, int onoff);
-extern int dib7090_get_adc_power(struct dvb_frontend *fe);
-extern struct i2c_adapter *dib7090_get_i2c_tuner(struct dvb_frontend *fe);
-extern int dib7090_slave_reset(struct dvb_frontend *fe);
-extern int dib7000p_get_agc_values(struct dvb_frontend *fe,
-		u16 *agc_global, u16 *agc1, u16 *agc2, u16 *wbd);
-#else
-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;
-}
-
-static inline struct i2c_adapter *dib7000p_get_i2c_master(struct dvb_frontend *fe, 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[])
-{
-	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)
-{
-	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)
-{
-	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;
-}
-
-static inline int dib7000p_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return -ENODEV;
-}
-
-static inline int dib7000p_pid_filter_ctrl(struct dvb_frontend *fe, uint8_t onoff)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return -ENODEV;
-}
-
-static inline int dib7000p_update_pll(struct dvb_frontend *fe, struct dibx000_bandwidth_config *bw)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return -ENODEV;
-}
-
-static inline u32 dib7000p_ctrl_timf(struct dvb_frontend *fe, u8 op, u32 timf)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return 0;
-}
-
-static inline int dib7090_tuner_sleep(struct dvb_frontend *fe, int onoff)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return -ENODEV;
-}
-
-static inline int dib7090_get_adc_power(struct dvb_frontend *fe)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return -ENODEV;
-}
-
-static inline struct i2c_adapter *dib7090_get_i2c_tuner(struct dvb_frontend *fe)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-
-static inline int dib7090_slave_reset(struct dvb_frontend *fe)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return -ENODEV;
-}
-
-static inline int dib7000p_get_agc_values(struct dvb_frontend *fe,
-		u16 *agc_global, u16 *agc1, u16 *agc2, u16 *wbd)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return -ENODEV;
-}
-#endif
-
-#endif
diff --git a/drivers/media/dvb/frontends/dib8000.c b/drivers/media/dvb/frontends/dib8000.c
deleted file mode 100644
index 1f3bcb5..0000000
--- a/drivers/media/dvb/frontends/dib8000.c
+++ /dev/null
@@ -1,3560 +0,0 @@
-/*
- * Linux-DVB Driver for DiBcom's DiB8000 chip (ISDB-T).
- *
- * Copyright (C) 2009 DiBcom (http://www.dibcom.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, version 2.
- */
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/i2c.h>
-#include <linux/mutex.h>
-
-#include "dvb_math.h"
-
-#include "dvb_frontend.h"
-
-#include "dib8000.h"
-
-#define LAYER_ALL -1
-#define LAYER_A   1
-#define LAYER_B   2
-#define LAYER_C   3
-
-#define FE_CALLBACK_TIME_NEVER 0xffffffff
-#define MAX_NUMBER_OF_FRONTENDS 6
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
-
-#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB8000: "); printk(args); printk("\n"); } } while (0)
-
-#define FE_STATUS_TUNE_FAILED 0
-
-struct i2c_device {
-	struct i2c_adapter *adap;
-	u8 addr;
-	u8 *i2c_write_buffer;
-	u8 *i2c_read_buffer;
-	struct mutex *i2c_buffer_lock;
-};
-
-struct dib8000_state {
-	struct dib8000_config cfg;
-
-	struct i2c_device i2c;
-
-	struct dibx000_i2c_master i2c_master;
-
-	u16 wbd_ref;
-
-	u8 current_band;
-	u32 current_bandwidth;
-	struct dibx000_agc_config *current_agc;
-	u32 timf;
-	u32 timf_default;
-
-	u8 div_force_off:1;
-	u8 div_state:1;
-	u16 div_sync_wait;
-
-	u8 agc_state;
-	u8 differential_constellation;
-	u8 diversity_onoff;
-
-	s16 ber_monitored_layer;
-	u16 gpio_dir;
-	u16 gpio_val;
-
-	u16 revision;
-	u8 isdbt_cfg_loaded;
-	enum frontend_tune_state tune_state;
-	u32 status;
-
-	struct dvb_frontend *fe[MAX_NUMBER_OF_FRONTENDS];
-
-	/* for the I2C transfer */
-	struct i2c_msg msg[2];
-	u8 i2c_write_buffer[4];
-	u8 i2c_read_buffer[2];
-	struct mutex i2c_buffer_lock;
-	u8 input_mode_mpeg;
-
-	u16 tuner_enable;
-	struct i2c_adapter dib8096p_tuner_adap;
-};
-
-enum dib8000_power_mode {
-	DIB8000_POWER_ALL = 0,
-	DIB8000_POWER_INTERFACE_ONLY,
-};
-
-static u16 dib8000_i2c_read16(struct i2c_device *i2c, u16 reg)
-{
-	u16 ret;
-	struct i2c_msg msg[2] = {
-		{.addr = i2c->addr >> 1, .flags = 0, .len = 2},
-		{.addr = i2c->addr >> 1, .flags = I2C_M_RD, .len = 2},
-	};
-
-	if (mutex_lock_interruptible(i2c->i2c_buffer_lock) < 0) {
-		dprintk("could not acquire lock");
-		return 0;
-	}
-
-	msg[0].buf    = i2c->i2c_write_buffer;
-	msg[0].buf[0] = reg >> 8;
-	msg[0].buf[1] = reg & 0xff;
-	msg[1].buf    = i2c->i2c_read_buffer;
-
-	if (i2c_transfer(i2c->adap, msg, 2) != 2)
-		dprintk("i2c read error on %d", reg);
-
-	ret = (msg[1].buf[0] << 8) | msg[1].buf[1];
-	mutex_unlock(i2c->i2c_buffer_lock);
-	return ret;
-}
-
-static u16 dib8000_read_word(struct dib8000_state *state, u16 reg)
-{
-	u16 ret;
-
-	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
-		dprintk("could not acquire lock");
-		return 0;
-	}
-
-	state->i2c_write_buffer[0] = reg >> 8;
-	state->i2c_write_buffer[1] = reg & 0xff;
-
-	memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
-	state->msg[0].addr = state->i2c.addr >> 1;
-	state->msg[0].flags = 0;
-	state->msg[0].buf = state->i2c_write_buffer;
-	state->msg[0].len = 2;
-	state->msg[1].addr = state->i2c.addr >> 1;
-	state->msg[1].flags = I2C_M_RD;
-	state->msg[1].buf = state->i2c_read_buffer;
-	state->msg[1].len = 2;
-
-	if (i2c_transfer(state->i2c.adap, state->msg, 2) != 2)
-		dprintk("i2c read error on %d", reg);
-
-	ret = (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
-	mutex_unlock(&state->i2c_buffer_lock);
-
-	return ret;
-}
-
-static u32 dib8000_read32(struct dib8000_state *state, u16 reg)
-{
-	u16 rw[2];
-
-	rw[0] = dib8000_read_word(state, reg + 0);
-	rw[1] = dib8000_read_word(state, reg + 1);
-
-	return ((rw[0] << 16) | (rw[1]));
-}
-
-static int dib8000_i2c_write16(struct i2c_device *i2c, u16 reg, u16 val)
-{
-	struct i2c_msg msg = {.addr = i2c->addr >> 1, .flags = 0, .len = 4};
-	int ret = 0;
-
-	if (mutex_lock_interruptible(i2c->i2c_buffer_lock) < 0) {
-		dprintk("could not acquire lock");
-		return -EINVAL;
-	}
-
-	msg.buf    = i2c->i2c_write_buffer;
-	msg.buf[0] = (reg >> 8) & 0xff;
-	msg.buf[1] = reg & 0xff;
-	msg.buf[2] = (val >> 8) & 0xff;
-	msg.buf[3] = val & 0xff;
-
-	ret = i2c_transfer(i2c->adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
-	mutex_unlock(i2c->i2c_buffer_lock);
-
-	return ret;
-}
-
-static int dib8000_write_word(struct dib8000_state *state, u16 reg, u16 val)
-{
-	int ret;
-
-	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
-		dprintk("could not acquire lock");
-		return -EINVAL;
-	}
-
-	state->i2c_write_buffer[0] = (reg >> 8) & 0xff;
-	state->i2c_write_buffer[1] = reg & 0xff;
-	state->i2c_write_buffer[2] = (val >> 8) & 0xff;
-	state->i2c_write_buffer[3] = val & 0xff;
-
-	memset(&state->msg[0], 0, sizeof(struct i2c_msg));
-	state->msg[0].addr = state->i2c.addr >> 1;
-	state->msg[0].flags = 0;
-	state->msg[0].buf = state->i2c_write_buffer;
-	state->msg[0].len = 4;
-
-	ret = (i2c_transfer(state->i2c.adap, state->msg, 1) != 1 ?
-			-EREMOTEIO : 0);
-	mutex_unlock(&state->i2c_buffer_lock);
-
-	return ret;
-}
-
-static const s16 coeff_2k_sb_1seg_dqpsk[8] = {
-	(769 << 5) | 0x0a, (745 << 5) | 0x03, (595 << 5) | 0x0d, (769 << 5) | 0x0a, (920 << 5) | 0x09, (784 << 5) | 0x02, (519 << 5) | 0x0c,
-		(920 << 5) | 0x09
-};
-
-static const s16 coeff_2k_sb_1seg[8] = {
-	(692 << 5) | 0x0b, (683 << 5) | 0x01, (519 << 5) | 0x09, (692 << 5) | 0x0b, 0 | 0x1f, 0 | 0x1f, 0 | 0x1f, 0 | 0x1f
-};
-
-static const s16 coeff_2k_sb_3seg_0dqpsk_1dqpsk[8] = {
-	(832 << 5) | 0x10, (912 << 5) | 0x05, (900 << 5) | 0x12, (832 << 5) | 0x10, (-931 << 5) | 0x0f, (912 << 5) | 0x04, (807 << 5) | 0x11,
-		(-931 << 5) | 0x0f
-};
-
-static const s16 coeff_2k_sb_3seg_0dqpsk[8] = {
-	(622 << 5) | 0x0c, (941 << 5) | 0x04, (796 << 5) | 0x10, (622 << 5) | 0x0c, (982 << 5) | 0x0c, (519 << 5) | 0x02, (572 << 5) | 0x0e,
-		(982 << 5) | 0x0c
-};
-
-static const s16 coeff_2k_sb_3seg_1dqpsk[8] = {
-	(699 << 5) | 0x14, (607 << 5) | 0x04, (944 << 5) | 0x13, (699 << 5) | 0x14, (-720 << 5) | 0x0d, (640 << 5) | 0x03, (866 << 5) | 0x12,
-		(-720 << 5) | 0x0d
-};
-
-static const s16 coeff_2k_sb_3seg[8] = {
-	(664 << 5) | 0x0c, (925 << 5) | 0x03, (937 << 5) | 0x10, (664 << 5) | 0x0c, (-610 << 5) | 0x0a, (697 << 5) | 0x01, (836 << 5) | 0x0e,
-		(-610 << 5) | 0x0a
-};
-
-static const s16 coeff_4k_sb_1seg_dqpsk[8] = {
-	(-955 << 5) | 0x0e, (687 << 5) | 0x04, (818 << 5) | 0x10, (-955 << 5) | 0x0e, (-922 << 5) | 0x0d, (750 << 5) | 0x03, (665 << 5) | 0x0f,
-		(-922 << 5) | 0x0d
-};
-
-static const s16 coeff_4k_sb_1seg[8] = {
-	(638 << 5) | 0x0d, (683 << 5) | 0x02, (638 << 5) | 0x0d, (638 << 5) | 0x0d, (-655 << 5) | 0x0a, (517 << 5) | 0x00, (698 << 5) | 0x0d,
-		(-655 << 5) | 0x0a
-};
-
-static const s16 coeff_4k_sb_3seg_0dqpsk_1dqpsk[8] = {
-	(-707 << 5) | 0x14, (910 << 5) | 0x06, (889 << 5) | 0x16, (-707 << 5) | 0x14, (-958 << 5) | 0x13, (993 << 5) | 0x05, (523 << 5) | 0x14,
-		(-958 << 5) | 0x13
-};
-
-static const s16 coeff_4k_sb_3seg_0dqpsk[8] = {
-	(-723 << 5) | 0x13, (910 << 5) | 0x05, (777 << 5) | 0x14, (-723 << 5) | 0x13, (-568 << 5) | 0x0f, (547 << 5) | 0x03, (696 << 5) | 0x12,
-		(-568 << 5) | 0x0f
-};
-
-static const s16 coeff_4k_sb_3seg_1dqpsk[8] = {
-	(-940 << 5) | 0x15, (607 << 5) | 0x05, (915 << 5) | 0x16, (-940 << 5) | 0x15, (-848 << 5) | 0x13, (683 << 5) | 0x04, (543 << 5) | 0x14,
-		(-848 << 5) | 0x13
-};
-
-static const s16 coeff_4k_sb_3seg[8] = {
-	(612 << 5) | 0x12, (910 << 5) | 0x04, (864 << 5) | 0x14, (612 << 5) | 0x12, (-869 << 5) | 0x13, (683 << 5) | 0x02, (869 << 5) | 0x12,
-		(-869 << 5) | 0x13
-};
-
-static const s16 coeff_8k_sb_1seg_dqpsk[8] = {
-	(-835 << 5) | 0x12, (684 << 5) | 0x05, (735 << 5) | 0x14, (-835 << 5) | 0x12, (-598 << 5) | 0x10, (781 << 5) | 0x04, (739 << 5) | 0x13,
-		(-598 << 5) | 0x10
-};
-
-static const s16 coeff_8k_sb_1seg[8] = {
-	(673 << 5) | 0x0f, (683 << 5) | 0x03, (808 << 5) | 0x12, (673 << 5) | 0x0f, (585 << 5) | 0x0f, (512 << 5) | 0x01, (780 << 5) | 0x0f,
-		(585 << 5) | 0x0f
-};
-
-static const s16 coeff_8k_sb_3seg_0dqpsk_1dqpsk[8] = {
-	(863 << 5) | 0x17, (930 << 5) | 0x07, (878 << 5) | 0x19, (863 << 5) | 0x17, (0 << 5) | 0x14, (521 << 5) | 0x05, (980 << 5) | 0x18,
-		(0 << 5) | 0x14
-};
-
-static const s16 coeff_8k_sb_3seg_0dqpsk[8] = {
-	(-924 << 5) | 0x17, (910 << 5) | 0x06, (774 << 5) | 0x17, (-924 << 5) | 0x17, (-877 << 5) | 0x15, (565 << 5) | 0x04, (553 << 5) | 0x15,
-		(-877 << 5) | 0x15
-};
-
-static const s16 coeff_8k_sb_3seg_1dqpsk[8] = {
-	(-921 << 5) | 0x19, (607 << 5) | 0x06, (881 << 5) | 0x19, (-921 << 5) | 0x19, (-921 << 5) | 0x14, (713 << 5) | 0x05, (1018 << 5) | 0x18,
-		(-921 << 5) | 0x14
-};
-
-static const s16 coeff_8k_sb_3seg[8] = {
-	(514 << 5) | 0x14, (910 << 5) | 0x05, (861 << 5) | 0x17, (514 << 5) | 0x14, (690 << 5) | 0x14, (683 << 5) | 0x03, (662 << 5) | 0x15,
-		(690 << 5) | 0x14
-};
-
-static const s16 ana_fe_coeff_3seg[24] = {
-	81, 80, 78, 74, 68, 61, 54, 45, 37, 28, 19, 11, 4, 1022, 1017, 1013, 1010, 1008, 1008, 1008, 1008, 1010, 1014, 1017
-};
-
-static const s16 ana_fe_coeff_1seg[24] = {
-	249, 226, 164, 82, 5, 981, 970, 988, 1018, 20, 31, 26, 8, 1012, 1000, 1018, 1012, 8, 15, 14, 9, 3, 1017, 1003
-};
-
-static const s16 ana_fe_coeff_13seg[24] = {
-	396, 305, 105, -51, -77, -12, 41, 31, -11, -30, -11, 14, 15, -2, -13, -7, 5, 8, 1, -6, -7, -3, 0, 1
-};
-
-static u16 fft_to_mode(struct dib8000_state *state)
-{
-	u16 mode;
-	switch (state->fe[0]->dtv_property_cache.transmission_mode) {
-	case TRANSMISSION_MODE_2K:
-		mode = 1;
-		break;
-	case TRANSMISSION_MODE_4K:
-		mode = 2;
-		break;
-	default:
-	case TRANSMISSION_MODE_AUTO:
-	case TRANSMISSION_MODE_8K:
-		mode = 3;
-		break;
-	}
-	return mode;
-}
-
-static void dib8000_set_acquisition_mode(struct dib8000_state *state)
-{
-	u16 nud = dib8000_read_word(state, 298);
-	nud |= (1 << 3) | (1 << 0);
-	dprintk("acquisition mode activated");
-	dib8000_write_word(state, 298, nud);
-}
-static int dib8000_set_output_mode(struct dvb_frontend *fe, int mode)
-{
-	struct dib8000_state *state = fe->demodulator_priv;
-
-	u16 outreg, fifo_threshold, smo_mode, sram = 0x0205;	/* by default SDRAM deintlv is enabled */
-
-	outreg = 0;
-	fifo_threshold = 1792;
-	smo_mode = (dib8000_read_word(state, 299) & 0x0050) | (1 << 1);
-
-	dprintk("-I-	Setting output mode for demod %p to %d",
-			&state->fe[0], mode);
-
-	switch (mode) {
-	case OUTMODE_MPEG2_PAR_GATED_CLK:	// STBs with parallel gated clock
-		outreg = (1 << 10);	/* 0x0400 */
-		break;
-	case OUTMODE_MPEG2_PAR_CONT_CLK:	// STBs with parallel continues clock
-		outreg = (1 << 10) | (1 << 6);	/* 0x0440 */
-		break;
-	case OUTMODE_MPEG2_SERIAL:	// STBs with serial input
-		outreg = (1 << 10) | (2 << 6) | (0 << 1);	/* 0x0482 */
-		break;
-	case OUTMODE_DIVERSITY:
-		if (state->cfg.hostbus_diversity) {
-			outreg = (1 << 10) | (4 << 6);	/* 0x0500 */
-			sram &= 0xfdff;
-		} else
-			sram |= 0x0c00;
-		break;
-	case OUTMODE_MPEG2_FIFO:	// e.g. USB feeding
-		smo_mode |= (3 << 1);
-		fifo_threshold = 512;
-		outreg = (1 << 10) | (5 << 6);
-		break;
-	case OUTMODE_HIGH_Z:	// disable
-		outreg = 0;
-		break;
-
-	case OUTMODE_ANALOG_ADC:
-		outreg = (1 << 10) | (3 << 6);
-		dib8000_set_acquisition_mode(state);
-		break;
-
-	default:
-		dprintk("Unhandled output_mode passed to be set for demod %p",
-				&state->fe[0]);
-		return -EINVAL;
-	}
-
-	if (state->cfg.output_mpeg2_in_188_bytes)
-		smo_mode |= (1 << 5);
-
-	dib8000_write_word(state, 299, smo_mode);
-	dib8000_write_word(state, 300, fifo_threshold);	/* synchronous fread */
-	dib8000_write_word(state, 1286, outreg);
-	dib8000_write_word(state, 1291, sram);
-
-	return 0;
-}
-
-static int dib8000_set_diversity_in(struct dvb_frontend *fe, int onoff)
-{
-	struct dib8000_state *state = fe->demodulator_priv;
-	u16 sync_wait = dib8000_read_word(state, 273) & 0xfff0;
-
-	if (!state->differential_constellation) {
-		dib8000_write_word(state, 272, 1 << 9);	//dvsy_off_lmod4 = 1
-		dib8000_write_word(state, 273, sync_wait | (1 << 2) | 2);	// sync_enable = 1; comb_mode = 2
-	} else {
-		dib8000_write_word(state, 272, 0);	//dvsy_off_lmod4 = 0
-		dib8000_write_word(state, 273, sync_wait);	// sync_enable = 0; comb_mode = 0
-	}
-	state->diversity_onoff = onoff;
-
-	switch (onoff) {
-	case 0:		/* only use the internal way - not the diversity input */
-		dib8000_write_word(state, 270, 1);
-		dib8000_write_word(state, 271, 0);
-		break;
-	case 1:		/* both ways */
-		dib8000_write_word(state, 270, 6);
-		dib8000_write_word(state, 271, 6);
-		break;
-	case 2:		/* only the diversity input */
-		dib8000_write_word(state, 270, 0);
-		dib8000_write_word(state, 271, 1);
-		break;
-	}
-	return 0;
-}
-
-static void dib8000_set_power_mode(struct dib8000_state *state, enum dib8000_power_mode mode)
-{
-	/* by default everything is going to be powered off */
-	u16 reg_774 = 0x3fff, reg_775 = 0xffff, reg_776 = 0xffff,
-		reg_900 = (dib8000_read_word(state, 900) & 0xfffc) | 0x3,
-		reg_1280;
-
-	if (state->revision != 0x8090)
-		reg_1280 = (dib8000_read_word(state, 1280) & 0x00ff) | 0xff00;
-	else
-		reg_1280 = (dib8000_read_word(state, 1280) & 0x707f) | 0x8f80;
-
-	/* now, depending on the requested mode, we power on */
-	switch (mode) {
-		/* power up everything in the demod */
-	case DIB8000_POWER_ALL:
-		reg_774 = 0x0000;
-		reg_775 = 0x0000;
-		reg_776 = 0x0000;
-		reg_900 &= 0xfffc;
-		if (state->revision != 0x8090)
-			reg_1280 &= 0x00ff;
-		else
-			reg_1280 &= 0x707f;
-		break;
-	case DIB8000_POWER_INTERFACE_ONLY:
-		if (state->revision != 0x8090)
-			reg_1280 &= 0x00ff;
-		else
-			reg_1280 &= 0xfa7b;
-		break;
-	}
-
-	dprintk("powermode : 774 : %x ; 775 : %x; 776 : %x ; 900 : %x; 1280 : %x", reg_774, reg_775, reg_776, reg_900, reg_1280);
-	dib8000_write_word(state, 774, reg_774);
-	dib8000_write_word(state, 775, reg_775);
-	dib8000_write_word(state, 776, reg_776);
-	dib8000_write_word(state, 900, reg_900);
-	dib8000_write_word(state, 1280, reg_1280);
-}
-
-static int dib8000_init_sdram(struct dib8000_state *state)
-{
-	u16 reg = 0;
-	dprintk("Init sdram");
-
-	reg = dib8000_read_word(state, 274)&0xfff0;
-	/* P_dintlv_delay_ram = 7 because of MobileSdram */
-	dib8000_write_word(state, 274, reg | 0x7);
-
-	dib8000_write_word(state, 1803, (7<<2));
-
-	reg = dib8000_read_word(state, 1280);
-	/* force restart P_restart_sdram */
-	dib8000_write_word(state, 1280,  reg | (1<<2));
-
-	/* release restart P_restart_sdram */
-	dib8000_write_word(state, 1280,  reg);
-
-	return 0;
-}
-
-static int dib8000_set_adc_state(struct dib8000_state *state, enum dibx000_adc_states no)
-{
-	int ret = 0;
-	u16 reg, reg_907 = dib8000_read_word(state, 907);
-	u16 reg_908 = dib8000_read_word(state, 908);
-
-	switch (no) {
-	case DIBX000_SLOW_ADC_ON:
-		if (state->revision != 0x8090) {
-			reg_908 |= (1 << 1) | (1 << 0);
-			ret |= dib8000_write_word(state, 908, reg_908);
-			reg_908 &= ~(1 << 1);
-		} else {
-			reg = dib8000_read_word(state, 1925);
-			/* en_slowAdc = 1 & reset_sladc = 1 */
-			dib8000_write_word(state, 1925, reg |
-					(1<<4) | (1<<2));
-
-			/* read acces to make it works... strange ... */
-			reg = dib8000_read_word(state, 1925);
-			msleep(20);
-			/* en_slowAdc = 1 & reset_sladc = 0 */
-			dib8000_write_word(state, 1925, reg & ~(1<<4));
-
-			reg = dib8000_read_word(state, 921) & ~((0x3 << 14)
-					| (0x3 << 12));
-			/* ref = Vin1 => Vbg ; sel = Vin0 or Vin3 ;
-			   (Vin2 = Vcm) */
-			dib8000_write_word(state, 921, reg | (1 << 14)
-					| (3 << 12));
-		}
-		break;
-
-	case DIBX000_SLOW_ADC_OFF:
-		if (state->revision == 0x8090) {
-			reg = dib8000_read_word(state, 1925);
-			/* reset_sladc = 1 en_slowAdc = 0 */
-			dib8000_write_word(state, 1925,
-					(reg & ~(1<<2)) | (1<<4));
-		}
-		reg_908 |= (1 << 1) | (1 << 0);
-		break;
-
-	case DIBX000_ADC_ON:
-		reg_907 &= 0x0fff;
-		reg_908 &= 0x0003;
-		break;
-
-	case DIBX000_ADC_OFF:	// leave the VBG voltage on
-		reg_907 |= (1 << 14) | (1 << 13) | (1 << 12);
-		reg_908 |= (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2);
-		break;
-
-	case DIBX000_VBG_ENABLE:
-		reg_907 &= ~(1 << 15);
-		break;
-
-	case DIBX000_VBG_DISABLE:
-		reg_907 |= (1 << 15);
-		break;
-
-	default:
-		break;
-	}
-
-	ret |= dib8000_write_word(state, 907, reg_907);
-	ret |= dib8000_write_word(state, 908, reg_908);
-
-	return ret;
-}
-
-static int dib8000_set_bandwidth(struct dvb_frontend *fe, u32 bw)
-{
-	struct dib8000_state *state = fe->demodulator_priv;
-	u32 timf;
-
-	if (bw == 0)
-		bw = 6000;
-
-	if (state->timf == 0) {
-		dprintk("using default timf");
-		timf = state->timf_default;
-	} else {
-		dprintk("using updated timf");
-		timf = state->timf;
-	}
-
-	dib8000_write_word(state, 29, (u16) ((timf >> 16) & 0xffff));
-	dib8000_write_word(state, 30, (u16) ((timf) & 0xffff));
-
-	return 0;
-}
-
-static int dib8000_sad_calib(struct dib8000_state *state)
-{
-	if (state->revision == 0x8090) {
-		dprintk("%s: the sad calibration is not needed for the dib8096P",
-				__func__);
-		return 0;
-	}
-	/* internal */
-	dib8000_write_word(state, 923, (0 << 1) | (0 << 0));
-	dib8000_write_word(state, 924, 776);	// 0.625*3.3 / 4096
-
-	/* do the calibration */
-	dib8000_write_word(state, 923, (1 << 0));
-	dib8000_write_word(state, 923, (0 << 0));
-
-	msleep(1);
-	return 0;
-}
-
-int dib8000_set_wbd_ref(struct dvb_frontend *fe, u16 value)
-{
-	struct dib8000_state *state = fe->demodulator_priv;
-	if (value > 4095)
-		value = 4095;
-	state->wbd_ref = value;
-	return dib8000_write_word(state, 106, value);
-}
-
-EXPORT_SYMBOL(dib8000_set_wbd_ref);
-static void dib8000_reset_pll_common(struct dib8000_state *state, const struct dibx000_bandwidth_config *bw)
-{
-	dprintk("ifreq: %d %x, inversion: %d", bw->ifreq, bw->ifreq, bw->ifreq >> 25);
-	if (state->revision != 0x8090) {
-		dib8000_write_word(state, 23,
-				(u16) (((bw->internal * 1000) >> 16) & 0xffff));
-		dib8000_write_word(state, 24,
-				(u16) ((bw->internal * 1000) & 0xffff));
-	} else {
-		dib8000_write_word(state, 23, (u16) (((bw->internal / 2 * 1000) >> 16) & 0xffff));
-		dib8000_write_word(state, 24,
-				(u16) ((bw->internal  / 2 * 1000) & 0xffff));
-	}
-	dib8000_write_word(state, 27, (u16) ((bw->ifreq >> 16) & 0x01ff));
-	dib8000_write_word(state, 28, (u16) (bw->ifreq & 0xffff));
-	dib8000_write_word(state, 26, (u16) ((bw->ifreq >> 25) & 0x0003));
-
-	if (state->revision != 0x8090)
-		dib8000_write_word(state, 922, bw->sad_cfg);
-}
-
-static void dib8000_reset_pll(struct dib8000_state *state)
-{
-	const struct dibx000_bandwidth_config *pll = state->cfg.pll;
-	u16 clk_cfg1, reg;
-
-	if (state->revision != 0x8090) {
-		dib8000_write_word(state, 901,
-				(pll->pll_prediv << 8) | (pll->pll_ratio << 0));
-
-		clk_cfg1 = (1 << 10) | (0 << 9) | (pll->IO_CLK_en_core << 8) |
-			(pll->bypclk_div << 5) | (pll->enable_refdiv << 4) |
-			(1 << 3) | (pll->pll_range << 1) |
-			(pll->pll_reset << 0);
-
-		dib8000_write_word(state, 902, clk_cfg1);
-		clk_cfg1 = (clk_cfg1 & 0xfff7) | (pll->pll_bypass << 3);
-		dib8000_write_word(state, 902, clk_cfg1);
-
-		dprintk("clk_cfg1: 0x%04x", clk_cfg1);
-
-		/* smpl_cfg: P_refclksel=2, P_ensmplsel=1 nodivsmpl=1 */
-		if (state->cfg.pll->ADClkSrc == 0)
-			dib8000_write_word(state, 904,
-					(0 << 15) | (0 << 12) | (0 << 10) |
-					(pll->modulo << 8) |
-					(pll->ADClkSrc << 7) | (0 << 1));
-		else if (state->cfg.refclksel != 0)
-			dib8000_write_word(state, 904, (0 << 15) | (1 << 12) |
-					((state->cfg.refclksel & 0x3) << 10) |
-					(pll->modulo << 8) |
-					(pll->ADClkSrc << 7) | (0 << 1));
-		else
-			dib8000_write_word(state, 904, (0 << 15) | (1 << 12) |
-					(3 << 10) | (pll->modulo << 8) |
-					(pll->ADClkSrc << 7) | (0 << 1));
-	} else {
-		dib8000_write_word(state, 1856, (!pll->pll_reset<<13) |
-				(pll->pll_range<<12) | (pll->pll_ratio<<6) |
-				(pll->pll_prediv));
-
-		reg = dib8000_read_word(state, 1857);
-		dib8000_write_word(state, 1857, reg|(!pll->pll_bypass<<15));
-
-		reg = dib8000_read_word(state, 1858); /* Force clk out pll /2 */
-		dib8000_write_word(state, 1858, reg | 1);
-
-		dib8000_write_word(state, 904, (pll->modulo << 8));
-	}
-
-	dib8000_reset_pll_common(state, pll);
-}
-
-int dib8000_update_pll(struct dvb_frontend *fe,
-		struct dibx000_bandwidth_config *pll)
-{
-	struct dib8000_state *state = fe->demodulator_priv;
-	u16 reg_1857, reg_1856 = dib8000_read_word(state, 1856);
-	u8 loopdiv, prediv;
-	u32 internal, xtal;
-
-	/* get back old values */
-	prediv = reg_1856 & 0x3f;
-	loopdiv = (reg_1856 >> 6) & 0x3f;
-
-	if ((pll != NULL) && (pll->pll_prediv != prediv ||
-				pll->pll_ratio != loopdiv)) {
-		dprintk("Updating pll (prediv: old =  %d new = %d ; loopdiv : old = %d new = %d)", prediv, pll->pll_prediv, loopdiv, pll->pll_ratio);
-		reg_1856 &= 0xf000;
-		reg_1857 = dib8000_read_word(state, 1857);
-		/* disable PLL */
-		dib8000_write_word(state, 1857, reg_1857 & ~(1 << 15));
-
-		dib8000_write_word(state, 1856, reg_1856 |
-				((pll->pll_ratio & 0x3f) << 6) |
-				(pll->pll_prediv & 0x3f));
-
-		/* write new system clk into P_sec_len */
-		internal = dib8000_read32(state, 23) / 1000;
-		dprintk("Old Internal = %d", internal);
-		xtal = 2 * (internal / loopdiv) * prediv;
-		internal = 1000 * (xtal/pll->pll_prediv) * pll->pll_ratio;
-		dprintk("Xtal = %d , New Fmem = %d New Fdemod = %d, New Fsampling = %d", xtal, internal/1000, internal/2000, internal/8000);
-		dprintk("New Internal = %d", internal);
-
-		dib8000_write_word(state, 23,
-				(u16) (((internal / 2) >> 16) & 0xffff));
-		dib8000_write_word(state, 24, (u16) ((internal / 2) & 0xffff));
-		/* enable PLL */
-		dib8000_write_word(state, 1857, reg_1857 | (1 << 15));
-
-		while (((dib8000_read_word(state, 1856)>>15)&0x1) != 1)
-			dprintk("Waiting for PLL to lock");
-
-		/* verify */
-		reg_1856 = dib8000_read_word(state, 1856);
-		dprintk("PLL Updated with prediv = %d and loopdiv = %d",
-				reg_1856&0x3f, (reg_1856>>6)&0x3f);
-
-		return 0;
-	}
-	return -EINVAL;
-}
-EXPORT_SYMBOL(dib8000_update_pll);
-
-
-static int dib8000_reset_gpio(struct dib8000_state *st)
-{
-	/* reset the GPIOs */
-	dib8000_write_word(st, 1029, st->cfg.gpio_dir);
-	dib8000_write_word(st, 1030, st->cfg.gpio_val);
-
-	/* TODO 782 is P_gpio_od */
-
-	dib8000_write_word(st, 1032, st->cfg.gpio_pwm_pos);
-
-	dib8000_write_word(st, 1037, st->cfg.pwm_freq_div);
-	return 0;
-}
-
-static int dib8000_cfg_gpio(struct dib8000_state *st, u8 num, u8 dir, u8 val)
-{
-	st->cfg.gpio_dir = dib8000_read_word(st, 1029);
-	st->cfg.gpio_dir &= ~(1 << num);	/* reset the direction bit */
-	st->cfg.gpio_dir |= (dir & 0x1) << num;	/* set the new direction */
-	dib8000_write_word(st, 1029, st->cfg.gpio_dir);
-
-	st->cfg.gpio_val = dib8000_read_word(st, 1030);
-	st->cfg.gpio_val &= ~(1 << num);	/* reset the direction bit */
-	st->cfg.gpio_val |= (val & 0x01) << num;	/* set the new value */
-	dib8000_write_word(st, 1030, st->cfg.gpio_val);
-
-	dprintk("gpio dir: %x: gpio val: %x", st->cfg.gpio_dir, st->cfg.gpio_val);
-
-	return 0;
-}
-
-int dib8000_set_gpio(struct dvb_frontend *fe, u8 num, u8 dir, u8 val)
-{
-	struct dib8000_state *state = fe->demodulator_priv;
-	return dib8000_cfg_gpio(state, num, dir, val);
-}
-
-EXPORT_SYMBOL(dib8000_set_gpio);
-static const u16 dib8000_defaults[] = {
-	/* auto search configuration - lock0 by default waiting
-	 * for cpil_lock; lock1 cpil_lock; lock2 tmcc_sync_lock */
-	3, 7,
-	0x0004,
-	0x0400,
-	0x0814,
-
-	12, 11,
-	0x001b,
-	0x7740,
-	0x005b,
-	0x8d80,
-	0x01c9,
-	0xc380,
-	0x0000,
-	0x0080,
-	0x0000,
-	0x0090,
-	0x0001,
-	0xd4c0,
-
-	/*1, 32,
-		0x6680 // P_corm_thres Lock algorithms configuration */
-
-	11, 80,			/* set ADC level to -16 */
-	(1 << 13) - 825 - 117,
-	(1 << 13) - 837 - 117,
-	(1 << 13) - 811 - 117,
-	(1 << 13) - 766 - 117,
-	(1 << 13) - 737 - 117,
-	(1 << 13) - 693 - 117,
-	(1 << 13) - 648 - 117,
-	(1 << 13) - 619 - 117,
-	(1 << 13) - 575 - 117,
-	(1 << 13) - 531 - 117,
-	(1 << 13) - 501 - 117,
-
-	4, 108,
-	0,
-	0,
-	0,
-	0,
-
-	1, 175,
-	0x0410,
-	1, 179,
-	8192,			// P_fft_nb_to_cut
-
-	6, 181,
-	0x2800,			// P_coff_corthres_ ( 2k 4k 8k ) 0x2800
-	0x2800,
-	0x2800,
-	0x2800,			// P_coff_cpilthres_ ( 2k 4k 8k ) 0x2800
-	0x2800,
-	0x2800,
-
-	2, 193,
-	0x0666,			// P_pha3_thres
-	0x0000,			// P_cti_use_cpe, P_cti_use_prog
-
-	2, 205,
-	0x200f,			// P_cspu_regul, P_cspu_win_cut
-	0x000f,			// P_des_shift_work
-
-	5, 215,
-	0x023d,			// P_adp_regul_cnt
-	0x00a4,			// P_adp_noise_cnt
-	0x00a4,			// P_adp_regul_ext
-	0x7ff0,			// P_adp_noise_ext
-	0x3ccc,			// P_adp_fil
-
-	1, 230,
-	0x0000,			// P_2d_byp_ti_num
-
-	1, 263,
-	0x800,			//P_equal_thres_wgn
-
-	1, 268,
-	(2 << 9) | 39,		// P_equal_ctrl_synchro, P_equal_speedmode
-
-	1, 270,
-	0x0001,			// P_div_lock0_wait
-	1, 285,
-	0x0020,			//p_fec_
-	1, 299,
-	0x0062,			/* P_smo_mode, P_smo_rs_discard, P_smo_fifo_flush, P_smo_pid_parse, P_smo_error_discard */
-
-	1, 338,
-	(1 << 12) |		// P_ctrl_corm_thres4pre_freq_inh=1
-		(1 << 10) |
-		(0 << 9) |		/* P_ctrl_pre_freq_inh=0 */
-		(3 << 5) |		/* P_ctrl_pre_freq_step=3 */
-		(1 << 0),		/* P_pre_freq_win_len=1 */
-
-	0,
-};
-
-static u16 dib8000_identify(struct i2c_device *client)
-{
-	u16 value;
-
-	//because of glitches sometimes
-	value = dib8000_i2c_read16(client, 896);
-
-	if ((value = dib8000_i2c_read16(client, 896)) != 0x01b3) {
-		dprintk("wrong Vendor ID (read=0x%x)", value);
-		return 0;
-	}
-
-	value = dib8000_i2c_read16(client, 897);
-	if (value != 0x8000 && value != 0x8001 &&
-			value != 0x8002 && value != 0x8090) {
-		dprintk("wrong Device ID (%x)", value);
-		return 0;
-	}
-
-	switch (value) {
-	case 0x8000:
-		dprintk("found DiB8000A");
-		break;
-	case 0x8001:
-		dprintk("found DiB8000B");
-		break;
-	case 0x8002:
-		dprintk("found DiB8000C");
-		break;
-	case 0x8090:
-		dprintk("found DiB8096P");
-		break;
-	}
-	return value;
-}
-
-static int dib8000_reset(struct dvb_frontend *fe)
-{
-	struct dib8000_state *state = fe->demodulator_priv;
-
-	if ((state->revision = dib8000_identify(&state->i2c)) == 0)
-		return -EINVAL;
-
-	/* sram lead in, rdy */
-	if (state->revision != 0x8090)
-		dib8000_write_word(state, 1287, 0x0003);
-
-	if (state->revision == 0x8000)
-		dprintk("error : dib8000 MA not supported");
-
-	dibx000_reset_i2c_master(&state->i2c_master);
-
-	dib8000_set_power_mode(state, DIB8000_POWER_ALL);
-
-	/* always leave the VBG voltage on - it consumes almost nothing but takes a long time to start */
-	dib8000_set_adc_state(state, DIBX000_VBG_ENABLE);
-
-	/* restart all parts */
-	dib8000_write_word(state, 770, 0xffff);
-	dib8000_write_word(state, 771, 0xffff);
-	dib8000_write_word(state, 772, 0xfffc);
-	if (state->revision == 0x8090)
-		dib8000_write_word(state, 1280, 0x0045);
-	else
-		dib8000_write_word(state, 1280, 0x004d);
-	dib8000_write_word(state, 1281, 0x000c);
-
-	dib8000_write_word(state, 770, 0x0000);
-	dib8000_write_word(state, 771, 0x0000);
-	dib8000_write_word(state, 772, 0x0000);
-	dib8000_write_word(state, 898, 0x0004);	// sad
-	dib8000_write_word(state, 1280, 0x0000);
-	dib8000_write_word(state, 1281, 0x0000);
-
-	/* drives */
-	if (state->revision != 0x8090) {
-		if (state->cfg.drives)
-			dib8000_write_word(state, 906, state->cfg.drives);
-		else {
-			dprintk("using standard PAD-drive-settings, please adjust settings in config-struct to be optimal.");
-			/* min drive SDRAM - not optimal - adjust */
-			dib8000_write_word(state, 906, 0x2d98);
-		}
-	}
-
-	dib8000_reset_pll(state);
-	if (state->revision != 0x8090)
-		dib8000_write_word(state, 898, 0x0004);
-
-	if (dib8000_reset_gpio(state) != 0)
-		dprintk("GPIO reset was not successful.");
-
-	if ((state->revision != 0x8090) &&
-			(dib8000_set_output_mode(fe, OUTMODE_HIGH_Z) != 0))
-		dprintk("OUTPUT_MODE could not be resetted.");
-
-	state->current_agc = NULL;
-
-	// P_iqc_alpha_pha, P_iqc_alpha_amp, P_iqc_dcc_alpha, ...
-	/* P_iqc_ca2 = 0; P_iqc_impnc_on = 0; P_iqc_mode = 0; */
-	if (state->cfg.pll->ifreq == 0)
-		dib8000_write_word(state, 40, 0x0755);	/* P_iqc_corr_inh = 0 enable IQcorr block */
-	else
-		dib8000_write_word(state, 40, 0x1f55);	/* P_iqc_corr_inh = 1 disable IQcorr block */
-
-	{
-		u16 l = 0, r;
-		const u16 *n;
-		n = dib8000_defaults;
-		l = *n++;
-		while (l) {
-			r = *n++;
-			do {
-				dib8000_write_word(state, r, *n++);
-				r++;
-			} while (--l);
-			l = *n++;
-		}
-	}
-	if (state->revision != 0x8090)
-		dib8000_write_word(state, 903, (0 << 4) | 2);
-	state->isdbt_cfg_loaded = 0;
-
-	//div_cfg override for special configs
-	if (state->cfg.div_cfg != 0)
-		dib8000_write_word(state, 903, state->cfg.div_cfg);
-
-	/* unforce divstr regardless whether i2c enumeration was done or not */
-	dib8000_write_word(state, 1285, dib8000_read_word(state, 1285) & ~(1 << 1));
-
-	dib8000_set_bandwidth(fe, 6000);
-
-	dib8000_set_adc_state(state, DIBX000_SLOW_ADC_ON);
-	if (state->revision != 0x8090) {
-		dib8000_sad_calib(state);
-		dib8000_set_adc_state(state, DIBX000_SLOW_ADC_OFF);
-	}
-
-	dib8000_set_power_mode(state, DIB8000_POWER_INTERFACE_ONLY);
-
-	return 0;
-}
-
-static void dib8000_restart_agc(struct dib8000_state *state)
-{
-	// P_restart_iqc & P_restart_agc
-	dib8000_write_word(state, 770, 0x0a00);
-	dib8000_write_word(state, 770, 0x0000);
-}
-
-static int dib8000_update_lna(struct dib8000_state *state)
-{
-	u16 dyn_gain;
-
-	if (state->cfg.update_lna) {
-		// read dyn_gain here (because it is demod-dependent and not tuner)
-		dyn_gain = dib8000_read_word(state, 390);
-
-		if (state->cfg.update_lna(state->fe[0], dyn_gain)) {
-			dib8000_restart_agc(state);
-			return 1;
-		}
-	}
-	return 0;
-}
-
-static int dib8000_set_agc_config(struct dib8000_state *state, u8 band)
-{
-	struct dibx000_agc_config *agc = NULL;
-	int i;
-	u16 reg;
-
-	if (state->current_band == band && state->current_agc != NULL)
-		return 0;
-	state->current_band = band;
-
-	for (i = 0; i < state->cfg.agc_config_count; i++)
-		if (state->cfg.agc[i].band_caps & band) {
-			agc = &state->cfg.agc[i];
-			break;
-		}
-
-	if (agc == NULL) {
-		dprintk("no valid AGC configuration found for band 0x%02x", band);
-		return -EINVAL;
-	}
-
-	state->current_agc = agc;
-
-	/* AGC */
-	dib8000_write_word(state, 76, agc->setup);
-	dib8000_write_word(state, 77, agc->inv_gain);
-	dib8000_write_word(state, 78, agc->time_stabiliz);
-	dib8000_write_word(state, 101, (agc->alpha_level << 12) | agc->thlock);
-
-	// Demod AGC loop configuration
-	dib8000_write_word(state, 102, (agc->alpha_mant << 5) | agc->alpha_exp);
-	dib8000_write_word(state, 103, (agc->beta_mant << 6) | agc->beta_exp);
-
-	dprintk("WBD: ref: %d, sel: %d, active: %d, alpha: %d",
-		state->wbd_ref != 0 ? state->wbd_ref : agc->wbd_ref, agc->wbd_sel, !agc->perform_agc_softsplit, agc->wbd_sel);
-
-	/* AGC continued */
-	if (state->wbd_ref != 0)
-		dib8000_write_word(state, 106, state->wbd_ref);
-	else			// use default
-		dib8000_write_word(state, 106, agc->wbd_ref);
-
-	if (state->revision == 0x8090) {
-		reg = dib8000_read_word(state, 922) & (0x3 << 2);
-		dib8000_write_word(state, 922, reg | (agc->wbd_sel << 2));
-	}
-
-	dib8000_write_word(state, 107, (agc->wbd_alpha << 9) | (agc->perform_agc_softsplit << 8));
-	dib8000_write_word(state, 108, agc->agc1_max);
-	dib8000_write_word(state, 109, agc->agc1_min);
-	dib8000_write_word(state, 110, agc->agc2_max);
-	dib8000_write_word(state, 111, agc->agc2_min);
-	dib8000_write_word(state, 112, (agc->agc1_pt1 << 8) | agc->agc1_pt2);
-	dib8000_write_word(state, 113, (agc->agc1_slope1 << 8) | agc->agc1_slope2);
-	dib8000_write_word(state, 114, (agc->agc2_pt1 << 8) | agc->agc2_pt2);
-	dib8000_write_word(state, 115, (agc->agc2_slope1 << 8) | agc->agc2_slope2);
-
-	dib8000_write_word(state, 75, agc->agc1_pt3);
-	if (state->revision != 0x8090)
-		dib8000_write_word(state, 923,
-				(dib8000_read_word(state, 923) & 0xffe3) |
-				(agc->wbd_inv << 4) | (agc->wbd_sel << 2));
-
-	return 0;
-}
-
-void dib8000_pwm_agc_reset(struct dvb_frontend *fe)
-{
-	struct dib8000_state *state = fe->demodulator_priv;
-	dib8000_set_adc_state(state, DIBX000_ADC_ON);
-	dib8000_set_agc_config(state, (unsigned char)(BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency / 1000)));
-}
-EXPORT_SYMBOL(dib8000_pwm_agc_reset);
-
-static int dib8000_agc_soft_split(struct dib8000_state *state)
-{
-	u16 agc, split_offset;
-
-	if (!state->current_agc || !state->current_agc->perform_agc_softsplit || state->current_agc->split.max == 0)
-		return FE_CALLBACK_TIME_NEVER;
-
-	// n_agc_global
-	agc = dib8000_read_word(state, 390);
-
-	if (agc > state->current_agc->split.min_thres)
-		split_offset = state->current_agc->split.min;
-	else if (agc < state->current_agc->split.max_thres)
-		split_offset = state->current_agc->split.max;
-	else
-		split_offset = state->current_agc->split.max *
-			(agc - state->current_agc->split.min_thres) /
-			(state->current_agc->split.max_thres - state->current_agc->split.min_thres);
-
-	dprintk("AGC split_offset: %d", split_offset);
-
-	// P_agc_force_split and P_agc_split_offset
-	dib8000_write_word(state, 107, (dib8000_read_word(state, 107) & 0xff00) | split_offset);
-	return 5000;
-}
-
-static int dib8000_agc_startup(struct dvb_frontend *fe)
-{
-	struct dib8000_state *state = fe->demodulator_priv;
-	enum frontend_tune_state *tune_state = &state->tune_state;
-	int ret = 0;
-	u16 reg, upd_demod_gain_period = 0x8000;
-
-	switch (*tune_state) {
-	case CT_AGC_START:
-		// set power-up level: interf+analog+AGC
-
-		if (state->revision != 0x8090)
-			dib8000_set_adc_state(state, DIBX000_ADC_ON);
-		else {
-			dib8000_set_power_mode(state, DIB8000_POWER_ALL);
-
-			reg = dib8000_read_word(state, 1947)&0xff00;
-			dib8000_write_word(state, 1946,
-					upd_demod_gain_period & 0xFFFF);
-			/* bit 14 = enDemodGain */
-			dib8000_write_word(state, 1947, reg | (1<<14) |
-					((upd_demod_gain_period >> 16) & 0xFF));
-
-			/* enable adc i & q */
-			reg = dib8000_read_word(state, 1920);
-			dib8000_write_word(state, 1920, (reg | 0x3) &
-					(~(1 << 7)));
-		}
-
-		if (dib8000_set_agc_config(state, (unsigned char)(BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency / 1000))) != 0) {
-			*tune_state = CT_AGC_STOP;
-			state->status = FE_STATUS_TUNE_FAILED;
-			break;
-		}
-
-		ret = 70;
-		*tune_state = CT_AGC_STEP_0;
-		break;
-
-	case CT_AGC_STEP_0:
-		//AGC initialization
-		if (state->cfg.agc_control)
-			state->cfg.agc_control(fe, 1);
-
-		dib8000_restart_agc(state);
-
-		// wait AGC rough lock time
-		ret = 50;
-		*tune_state = CT_AGC_STEP_1;
-		break;
-
-	case CT_AGC_STEP_1:
-		// wait AGC accurate lock time
-		ret = 70;
-
-		if (dib8000_update_lna(state))
-			// wait only AGC rough lock time
-			ret = 50;
-		else
-			*tune_state = CT_AGC_STEP_2;
-		break;
-
-	case CT_AGC_STEP_2:
-		dib8000_agc_soft_split(state);
-
-		if (state->cfg.agc_control)
-			state->cfg.agc_control(fe, 0);
-
-		*tune_state = CT_AGC_STOP;
-		break;
-	default:
-		ret = dib8000_agc_soft_split(state);
-		break;
-	}
-	return ret;
-
-}
-
-static void dib8096p_host_bus_drive(struct dib8000_state *state, u8 drive)
-{
-	u16 reg;
-
-	drive &= 0x7;
-
-	/* drive host bus 2, 3, 4 */
-	reg = dib8000_read_word(state, 1798) &
-		~(0x7 | (0x7 << 6) | (0x7 << 12));
-	reg |= (drive<<12) | (drive<<6) | drive;
-	dib8000_write_word(state, 1798, reg);
-
-	/* drive host bus 5,6 */
-	reg = dib8000_read_word(state, 1799) & ~((0x7 << 2) | (0x7 << 8));
-	reg |= (drive<<8) | (drive<<2);
-	dib8000_write_word(state, 1799, reg);
-
-	/* drive host bus 7, 8, 9 */
-	reg = dib8000_read_word(state, 1800) &
-		~(0x7 | (0x7 << 6) | (0x7 << 12));
-	reg |= (drive<<12) | (drive<<6) | drive;
-	dib8000_write_word(state, 1800, reg);
-
-	/* drive host bus 10, 11 */
-	reg = dib8000_read_word(state, 1801) & ~((0x7 << 2) | (0x7 << 8));
-	reg |= (drive<<8) | (drive<<2);
-	dib8000_write_word(state, 1801, reg);
-
-	/* drive host bus 12, 13, 14 */
-	reg = dib8000_read_word(state, 1802) &
-		~(0x7 | (0x7 << 6) | (0x7 << 12));
-	reg |= (drive<<12) | (drive<<6) | drive;
-	dib8000_write_word(state, 1802, reg);
-}
-
-static u32 dib8096p_calcSyncFreq(u32 P_Kin, u32 P_Kout,
-		u32 insertExtSynchro, u32 syncSize)
-{
-	u32 quantif = 3;
-	u32 nom = (insertExtSynchro * P_Kin+syncSize);
-	u32 denom = P_Kout;
-	u32 syncFreq = ((nom << quantif) / denom);
-
-	if ((syncFreq & ((1 << quantif) - 1)) != 0)
-		syncFreq = (syncFreq >> quantif) + 1;
-	else
-		syncFreq = (syncFreq >> quantif);
-
-	if (syncFreq != 0)
-		syncFreq = syncFreq - 1;
-
-	return syncFreq;
-}
-
-static void dib8096p_cfg_DibTx(struct dib8000_state *state, u32 P_Kin,
-		u32 P_Kout, u32 insertExtSynchro, u32 synchroMode,
-		u32 syncWord, u32 syncSize)
-{
-	dprintk("Configure DibStream Tx");
-
-	dib8000_write_word(state, 1615, 1);
-	dib8000_write_word(state, 1603, P_Kin);
-	dib8000_write_word(state, 1605, P_Kout);
-	dib8000_write_word(state, 1606, insertExtSynchro);
-	dib8000_write_word(state, 1608, synchroMode);
-	dib8000_write_word(state, 1609, (syncWord >> 16) & 0xffff);
-	dib8000_write_word(state, 1610, syncWord & 0xffff);
-	dib8000_write_word(state, 1612, syncSize);
-	dib8000_write_word(state, 1615, 0);
-}
-
-static void dib8096p_cfg_DibRx(struct dib8000_state *state, u32 P_Kin,
-		u32 P_Kout, u32 synchroMode, u32 insertExtSynchro,
-		u32 syncWord, u32 syncSize, u32 dataOutRate)
-{
-	u32 syncFreq;
-
-	dprintk("Configure DibStream Rx synchroMode = %d", synchroMode);
-
-	if ((P_Kin != 0) && (P_Kout != 0)) {
-		syncFreq = dib8096p_calcSyncFreq(P_Kin, P_Kout,
-				insertExtSynchro, syncSize);
-		dib8000_write_word(state, 1542, syncFreq);
-	}
-
-	dib8000_write_word(state, 1554, 1);
-	dib8000_write_word(state, 1536, P_Kin);
-	dib8000_write_word(state, 1537, P_Kout);
-	dib8000_write_word(state, 1539, synchroMode);
-	dib8000_write_word(state, 1540, (syncWord >> 16) & 0xffff);
-	dib8000_write_word(state, 1541, syncWord & 0xffff);
-	dib8000_write_word(state, 1543, syncSize);
-	dib8000_write_word(state, 1544, dataOutRate);
-	dib8000_write_word(state, 1554, 0);
-}
-
-static void dib8096p_enMpegMux(struct dib8000_state *state, int onoff)
-{
-	u16 reg_1287;
-
-	reg_1287 = dib8000_read_word(state, 1287);
-
-	switch (onoff) {
-	case 1:
-			reg_1287 &= ~(1 << 8);
-			break;
-	case 0:
-			reg_1287 |= (1 << 8);
-			break;
-	}
-
-	dib8000_write_word(state, 1287, reg_1287);
-}
-
-static void dib8096p_configMpegMux(struct dib8000_state *state,
-		u16 pulseWidth, u16 enSerialMode, u16 enSerialClkDiv2)
-{
-	u16 reg_1287;
-
-	dprintk("Enable Mpeg mux");
-
-	dib8096p_enMpegMux(state, 0);
-
-	/* If the input mode is MPEG do not divide the serial clock */
-	if ((enSerialMode == 1) && (state->input_mode_mpeg == 1))
-		enSerialClkDiv2 = 0;
-
-	reg_1287 = ((pulseWidth & 0x1f) << 3) |
-		((enSerialMode & 0x1) << 2) | (enSerialClkDiv2 & 0x1);
-	dib8000_write_word(state, 1287, reg_1287);
-
-	dib8096p_enMpegMux(state, 1);
-}
-
-static void dib8096p_setDibTxMux(struct dib8000_state *state, int mode)
-{
-	u16 reg_1288 = dib8000_read_word(state, 1288) & ~(0x7 << 7);
-
-	switch (mode) {
-	case MPEG_ON_DIBTX:
-			dprintk("SET MPEG ON DIBSTREAM TX");
-			dib8096p_cfg_DibTx(state, 8, 5, 0, 0, 0, 0);
-			reg_1288 |= (1 << 9); break;
-	case DIV_ON_DIBTX:
-			dprintk("SET DIV_OUT ON DIBSTREAM TX");
-			dib8096p_cfg_DibTx(state, 5, 5, 0, 0, 0, 0);
-			reg_1288 |= (1 << 8); break;
-	case ADC_ON_DIBTX:
-			dprintk("SET ADC_OUT ON DIBSTREAM TX");
-			dib8096p_cfg_DibTx(state, 20, 5, 10, 0, 0, 0);
-			reg_1288 |= (1 << 7); break;
-	default:
-			break;
-	}
-	dib8000_write_word(state, 1288, reg_1288);
-}
-
-static void dib8096p_setHostBusMux(struct dib8000_state *state, int mode)
-{
-	u16 reg_1288 = dib8000_read_word(state, 1288) & ~(0x7 << 4);
-
-	switch (mode) {
-	case DEMOUT_ON_HOSTBUS:
-			dprintk("SET DEM OUT OLD INTERF ON HOST BUS");
-			dib8096p_enMpegMux(state, 0);
-			reg_1288 |= (1 << 6);
-			break;
-	case DIBTX_ON_HOSTBUS:
-			dprintk("SET DIBSTREAM TX ON HOST BUS");
-			dib8096p_enMpegMux(state, 0);
-			reg_1288 |= (1 << 5);
-			break;
-	case MPEG_ON_HOSTBUS:
-			dprintk("SET MPEG MUX ON HOST BUS");
-			reg_1288 |= (1 << 4);
-			break;
-	default:
-			break;
-	}
-	dib8000_write_word(state, 1288, reg_1288);
-}
-
-static int dib8096p_set_diversity_in(struct dvb_frontend *fe, int onoff)
-{
-	struct dib8000_state *state = fe->demodulator_priv;
-	u16 reg_1287;
-
-	switch (onoff) {
-	case 0: /* only use the internal way - not the diversity input */
-			dprintk("%s mode OFF : by default Enable Mpeg INPUT",
-					__func__);
-			/* outputRate = 8 */
-			dib8096p_cfg_DibRx(state, 8, 5, 0, 0, 0, 8, 0);
-
-			/* Do not divide the serial clock of MPEG MUX in
-			   SERIAL MODE in case input mode MPEG is used */
-			reg_1287 = dib8000_read_word(state, 1287);
-			/* enSerialClkDiv2 == 1 ? */
-			if ((reg_1287 & 0x1) == 1) {
-				/* force enSerialClkDiv2 = 0 */
-				reg_1287 &= ~0x1;
-				dib8000_write_word(state, 1287, reg_1287);
-			}
-			state->input_mode_mpeg = 1;
-			break;
-	case 1: /* both ways */
-	case 2: /* only the diversity input */
-			dprintk("%s ON : Enable diversity INPUT", __func__);
-			dib8096p_cfg_DibRx(state, 5, 5, 0, 0, 0, 0, 0);
-			state->input_mode_mpeg = 0;
-			break;
-	}
-
-	dib8000_set_diversity_in(state->fe[0], onoff);
-	return 0;
-}
-
-static int dib8096p_set_output_mode(struct dvb_frontend *fe, int mode)
-{
-	struct dib8000_state *state = fe->demodulator_priv;
-	u16 outreg, smo_mode, fifo_threshold;
-	u8 prefer_mpeg_mux_use = 1;
-	int ret = 0;
-
-	dib8096p_host_bus_drive(state, 1);
-
-	fifo_threshold = 1792;
-	smo_mode = (dib8000_read_word(state, 299) & 0x0050) | (1 << 1);
-	outreg   = dib8000_read_word(state, 1286) &
-		~((1 << 10) | (0x7 << 6) | (1 << 1));
-
-	switch (mode) {
-	case OUTMODE_HIGH_Z:
-			outreg = 0;
-			break;
-
-	case OUTMODE_MPEG2_SERIAL:
-			if (prefer_mpeg_mux_use) {
-				dprintk("dib8096P setting output mode TS_SERIAL using Mpeg Mux");
-				dib8096p_configMpegMux(state, 3, 1, 1);
-				dib8096p_setHostBusMux(state, MPEG_ON_HOSTBUS);
-			} else {/* Use Smooth block */
-				dprintk("dib8096P setting output mode TS_SERIAL using Smooth bloc");
-				dib8096p_setHostBusMux(state,
-						DEMOUT_ON_HOSTBUS);
-				outreg |= (2 << 6) | (0 << 1);
-			}
-			break;
-
-	case OUTMODE_MPEG2_PAR_GATED_CLK:
-			if (prefer_mpeg_mux_use) {
-				dprintk("dib8096P setting output mode TS_PARALLEL_GATED using Mpeg Mux");
-				dib8096p_configMpegMux(state, 2, 0, 0);
-				dib8096p_setHostBusMux(state, MPEG_ON_HOSTBUS);
-			} else { /* Use Smooth block */
-				dprintk("dib8096P setting output mode TS_PARALLEL_GATED using Smooth block");
-				dib8096p_setHostBusMux(state,
-						DEMOUT_ON_HOSTBUS);
-				outreg |= (0 << 6);
-			}
-			break;
-
-	case OUTMODE_MPEG2_PAR_CONT_CLK: /* Using Smooth block only */
-			dprintk("dib8096P setting output mode TS_PARALLEL_CONT using Smooth block");
-			dib8096p_setHostBusMux(state, DEMOUT_ON_HOSTBUS);
-			outreg |= (1 << 6);
-			break;
-
-	case OUTMODE_MPEG2_FIFO:
-			/* Using Smooth block because not supported
-			   by new Mpeg Mux bloc */
-			dprintk("dib8096P setting output mode TS_FIFO using Smooth block");
-			dib8096p_setHostBusMux(state, DEMOUT_ON_HOSTBUS);
-			outreg |= (5 << 6);
-			smo_mode |= (3 << 1);
-			fifo_threshold = 512;
-			break;
-
-	case OUTMODE_DIVERSITY:
-			dprintk("dib8096P setting output mode MODE_DIVERSITY");
-			dib8096p_setDibTxMux(state, DIV_ON_DIBTX);
-			dib8096p_setHostBusMux(state, DIBTX_ON_HOSTBUS);
-			break;
-
-	case OUTMODE_ANALOG_ADC:
-			dprintk("dib8096P setting output mode MODE_ANALOG_ADC");
-			dib8096p_setDibTxMux(state, ADC_ON_DIBTX);
-			dib8096p_setHostBusMux(state, DIBTX_ON_HOSTBUS);
-			break;
-	}
-
-	if (mode != OUTMODE_HIGH_Z)
-		outreg |= (1<<10);
-
-	dprintk("output_mpeg2_in_188_bytes = %d",
-			state->cfg.output_mpeg2_in_188_bytes);
-	if (state->cfg.output_mpeg2_in_188_bytes)
-		smo_mode |= (1 << 5);
-
-	ret |= dib8000_write_word(state, 299, smo_mode);
-	/* synchronous fread */
-	ret |= dib8000_write_word(state, 299 + 1, fifo_threshold);
-	ret |= dib8000_write_word(state, 1286, outreg);
-
-	return ret;
-}
-
-static int map_addr_to_serpar_number(struct i2c_msg *msg)
-{
-	if (msg->buf[0] <= 15)
-		msg->buf[0] -= 1;
-	else if (msg->buf[0] == 17)
-		msg->buf[0] = 15;
-	else if (msg->buf[0] == 16)
-		msg->buf[0] = 17;
-	else if (msg->buf[0] == 19)
-		msg->buf[0] = 16;
-	else if (msg->buf[0] >= 21 && msg->buf[0] <= 25)
-		msg->buf[0] -= 3;
-	else if (msg->buf[0] == 28)
-		msg->buf[0] = 23;
-	else if (msg->buf[0] == 99)
-		msg->buf[0] = 99;
-	else
-		return -EINVAL;
-	return 0;
-}
-
-static int dib8096p_tuner_write_serpar(struct i2c_adapter *i2c_adap,
-		struct i2c_msg msg[], int num)
-{
-	struct dib8000_state *state = i2c_get_adapdata(i2c_adap);
-	u8 n_overflow = 1;
-	u16 i = 1000;
-	u16 serpar_num = msg[0].buf[0];
-
-	while (n_overflow == 1 && i) {
-		n_overflow = (dib8000_read_word(state, 1984) >> 1) & 0x1;
-		i--;
-		if (i == 0)
-			dprintk("Tuner ITF: write busy (overflow)");
-	}
-	dib8000_write_word(state, 1985, (1 << 6) | (serpar_num & 0x3f));
-	dib8000_write_word(state, 1986, (msg[0].buf[1] << 8) | msg[0].buf[2]);
-
-	return num;
-}
-
-static int dib8096p_tuner_read_serpar(struct i2c_adapter *i2c_adap,
-		struct i2c_msg msg[], int num)
-{
-	struct dib8000_state *state = i2c_get_adapdata(i2c_adap);
-	u8 n_overflow = 1, n_empty = 1;
-	u16 i = 1000;
-	u16 serpar_num = msg[0].buf[0];
-	u16 read_word;
-
-	while (n_overflow == 1 && i) {
-		n_overflow = (dib8000_read_word(state, 1984) >> 1) & 0x1;
-		i--;
-		if (i == 0)
-			dprintk("TunerITF: read busy (overflow)");
-	}
-	dib8000_write_word(state, 1985, (0<<6) | (serpar_num&0x3f));
-
-	i = 1000;
-	while (n_empty == 1 && i) {
-		n_empty = dib8000_read_word(state, 1984)&0x1;
-		i--;
-		if (i == 0)
-			dprintk("TunerITF: read busy (empty)");
-	}
-
-	read_word = dib8000_read_word(state, 1987);
-	msg[1].buf[0] = (read_word >> 8) & 0xff;
-	msg[1].buf[1] = (read_word) & 0xff;
-
-	return num;
-}
-
-static int dib8096p_tuner_rw_serpar(struct i2c_adapter *i2c_adap,
-		struct i2c_msg msg[], int num)
-{
-	if (map_addr_to_serpar_number(&msg[0]) == 0) {
-		if (num == 1) /* write */
-			return dib8096p_tuner_write_serpar(i2c_adap, msg, 1);
-		else /* read */
-			return dib8096p_tuner_read_serpar(i2c_adap, msg, 2);
-	}
-	return num;
-}
-
-static int dib8096p_rw_on_apb(struct i2c_adapter *i2c_adap,
-		struct i2c_msg msg[], int num, u16 apb_address)
-{
-	struct dib8000_state *state = i2c_get_adapdata(i2c_adap);
-	u16 word;
-
-	if (num == 1) {		/* write */
-		dib8000_write_word(state, apb_address,
-				((msg[0].buf[1] << 8) | (msg[0].buf[2])));
-	} else {
-		word = dib8000_read_word(state, apb_address);
-		msg[1].buf[0] = (word >> 8) & 0xff;
-		msg[1].buf[1] = (word) & 0xff;
-	}
-	return num;
-}
-
-static int dib8096p_tuner_xfer(struct i2c_adapter *i2c_adap,
-		struct i2c_msg msg[], int num)
-{
-	struct dib8000_state *state = i2c_get_adapdata(i2c_adap);
-	u16 apb_address = 0, word;
-	int i = 0;
-
-	switch (msg[0].buf[0]) {
-	case 0x12:
-			apb_address = 1920;
-			break;
-	case 0x14:
-			apb_address = 1921;
-			break;
-	case 0x24:
-			apb_address = 1922;
-			break;
-	case 0x1a:
-			apb_address = 1923;
-			break;
-	case 0x22:
-			apb_address = 1924;
-			break;
-	case 0x33:
-			apb_address = 1926;
-			break;
-	case 0x34:
-			apb_address = 1927;
-			break;
-	case 0x35:
-			apb_address = 1928;
-			break;
-	case 0x36:
-			apb_address = 1929;
-			break;
-	case 0x37:
-			apb_address = 1930;
-			break;
-	case 0x38:
-			apb_address = 1931;
-			break;
-	case 0x39:
-			apb_address = 1932;
-			break;
-	case 0x2a:
-			apb_address = 1935;
-			break;
-	case 0x2b:
-			apb_address = 1936;
-			break;
-	case 0x2c:
-			apb_address = 1937;
-			break;
-	case 0x2d:
-			apb_address = 1938;
-			break;
-	case 0x2e:
-			apb_address = 1939;
-			break;
-	case 0x2f:
-			apb_address = 1940;
-			break;
-	case 0x30:
-			apb_address = 1941;
-			break;
-	case 0x31:
-			apb_address = 1942;
-			break;
-	case 0x32:
-			apb_address = 1943;
-			break;
-	case 0x3e:
-			apb_address = 1944;
-			break;
-	case 0x3f:
-			apb_address = 1945;
-			break;
-	case 0x40:
-			apb_address = 1948;
-			break;
-	case 0x25:
-			apb_address = 936;
-			break;
-	case 0x26:
-			apb_address = 937;
-			break;
-	case 0x27:
-			apb_address = 938;
-			break;
-	case 0x28:
-			apb_address = 939;
-			break;
-	case 0x1d:
-			/* get sad sel request */
-			i = ((dib8000_read_word(state, 921) >> 12)&0x3);
-			word = dib8000_read_word(state, 924+i);
-			msg[1].buf[0] = (word >> 8) & 0xff;
-			msg[1].buf[1] = (word) & 0xff;
-			return num;
-	case 0x1f:
-			if (num == 1) {	/* write */
-				word = (u16) ((msg[0].buf[1] << 8) |
-						msg[0].buf[2]);
-				/* in the VGAMODE Sel are located on bit 0/1 */
-				word &= 0x3;
-				word = (dib8000_read_word(state, 921) &
-						~(3<<12)) | (word<<12);
-				/* Set the proper input */
-				dib8000_write_word(state, 921, word);
-				return num;
-			}
-	}
-
-	if (apb_address != 0) /* R/W acces via APB */
-		return dib8096p_rw_on_apb(i2c_adap, msg, num, apb_address);
-	else  /* R/W access via SERPAR  */
-		return dib8096p_tuner_rw_serpar(i2c_adap, msg, num);
-
-	return 0;
-}
-
-static u32 dib8096p_i2c_func(struct i2c_adapter *adapter)
-{
-	return I2C_FUNC_I2C;
-}
-
-static struct i2c_algorithm dib8096p_tuner_xfer_algo = {
-	.master_xfer = dib8096p_tuner_xfer,
-	.functionality = dib8096p_i2c_func,
-};
-
-struct i2c_adapter *dib8096p_get_i2c_tuner(struct dvb_frontend *fe)
-{
-	struct dib8000_state *st = fe->demodulator_priv;
-	return &st->dib8096p_tuner_adap;
-}
-EXPORT_SYMBOL(dib8096p_get_i2c_tuner);
-
-int dib8096p_tuner_sleep(struct dvb_frontend *fe, int onoff)
-{
-	struct dib8000_state *state = fe->demodulator_priv;
-	u16 en_cur_state;
-
-	dprintk("sleep dib8096p: %d", onoff);
-
-	en_cur_state = dib8000_read_word(state, 1922);
-
-	/* LNAs and MIX are ON and therefore it is a valid configuration */
-	if (en_cur_state > 0xff)
-		state->tuner_enable = en_cur_state ;
-
-	if (onoff)
-		en_cur_state &= 0x00ff;
-	else {
-		if (state->tuner_enable != 0)
-			en_cur_state = state->tuner_enable;
-	}
-
-	dib8000_write_word(state, 1922, en_cur_state);
-
-	return 0;
-}
-EXPORT_SYMBOL(dib8096p_tuner_sleep);
-
-static const s32 lut_1000ln_mant[] =
-{
-	908, 7003, 7090, 7170, 7244, 7313, 7377, 7438, 7495, 7549, 7600
-};
-
-s32 dib8000_get_adc_power(struct dvb_frontend *fe, u8 mode)
-{
-	struct dib8000_state *state = fe->demodulator_priv;
-	u32 ix = 0, tmp_val = 0, exp = 0, mant = 0;
-	s32 val;
-
-	val = dib8000_read32(state, 384);
-	if (mode) {
-		tmp_val = val;
-		while (tmp_val >>= 1)
-			exp++;
-		mant = (val * 1000 / (1<<exp));
-		ix = (u8)((mant-1000)/100); /* index of the LUT */
-		val = (lut_1000ln_mant[ix] + 693*(exp-20) - 6908);
-		val = (val*256)/1000;
-	}
-	return val;
-}
-EXPORT_SYMBOL(dib8000_get_adc_power);
-
-int dib8090p_get_dc_power(struct dvb_frontend *fe, u8 IQ)
-{
-	struct dib8000_state *state = fe->demodulator_priv;
-	int val = 0;
-
-	switch (IQ) {
-	case 1:
-			val = dib8000_read_word(state, 403);
-			break;
-	case 0:
-			val = dib8000_read_word(state, 404);
-			break;
-	}
-	if (val  & 0x200)
-		val -= 1024;
-
-	return val;
-}
-EXPORT_SYMBOL(dib8090p_get_dc_power);
-
-static void dib8000_update_timf(struct dib8000_state *state)
-{
-	u32 timf = state->timf = dib8000_read32(state, 435);
-
-	dib8000_write_word(state, 29, (u16) (timf >> 16));
-	dib8000_write_word(state, 30, (u16) (timf & 0xffff));
-	dprintk("Updated timing frequency: %d (default: %d)", state->timf, state->timf_default);
-}
-
-u32 dib8000_ctrl_timf(struct dvb_frontend *fe, uint8_t op, uint32_t timf)
-{
-	struct dib8000_state *state = fe->demodulator_priv;
-
-	switch (op) {
-	case DEMOD_TIMF_SET:
-			state->timf = timf;
-			break;
-	case DEMOD_TIMF_UPDATE:
-			dib8000_update_timf(state);
-			break;
-	case DEMOD_TIMF_GET:
-			break;
-	}
-	dib8000_set_bandwidth(state->fe[0], 6000);
-
-	return state->timf;
-}
-EXPORT_SYMBOL(dib8000_ctrl_timf);
-
-static const u16 adc_target_16dB[11] = {
-	(1 << 13) - 825 - 117,
-	(1 << 13) - 837 - 117,
-	(1 << 13) - 811 - 117,
-	(1 << 13) - 766 - 117,
-	(1 << 13) - 737 - 117,
-	(1 << 13) - 693 - 117,
-	(1 << 13) - 648 - 117,
-	(1 << 13) - 619 - 117,
-	(1 << 13) - 575 - 117,
-	(1 << 13) - 531 - 117,
-	(1 << 13) - 501 - 117
-};
-static const u8 permu_seg[] = { 6, 5, 7, 4, 8, 3, 9, 2, 10, 1, 11, 0, 12 };
-
-static void dib8000_set_channel(struct dib8000_state *state, u8 seq, u8 autosearching)
-{
-	u16 mode, max_constellation, seg_diff_mask = 0, nbseg_diff = 0;
-	u8 guard, crate, constellation, timeI;
-	u16 i, coeff[4], P_cfr_left_edge = 0, P_cfr_right_edge = 0, seg_mask13 = 0x1fff;	// All 13 segments enabled
-	const s16 *ncoeff = NULL, *ana_fe;
-	u16 tmcc_pow = 0;
-	u16 coff_pow = 0x2800;
-	u16 init_prbs = 0xfff;
-	u16 ana_gain = 0;
-
-	if (state->revision == 0x8090)
-		dib8000_init_sdram(state);
-
-	if (state->ber_monitored_layer != LAYER_ALL)
-		dib8000_write_word(state, 285, (dib8000_read_word(state, 285) & 0x60) | state->ber_monitored_layer);
-	else
-		dib8000_write_word(state, 285, dib8000_read_word(state, 285) & 0x60);
-
-	i = dib8000_read_word(state, 26) & 1;	// P_dds_invspec
-	dib8000_write_word(state, 26, state->fe[0]->dtv_property_cache.inversion^i);
-
-	if (state->fe[0]->dtv_property_cache.isdbt_sb_mode) {
-		//compute new dds_freq for the seg and adjust prbs
-		int seg_offset =
-			state->fe[0]->dtv_property_cache.isdbt_sb_segment_idx -
-			(state->fe[0]->dtv_property_cache.isdbt_sb_segment_count / 2) -
-			(state->fe[0]->dtv_property_cache.isdbt_sb_segment_count % 2);
-		int clk = state->cfg.pll->internal;
-		u32 segtodds = ((u32) (430 << 23) / clk) << 3;	// segtodds = SegBW / Fclk * pow(2,26)
-		int dds_offset = seg_offset * segtodds;
-		int new_dds, sub_channel;
-		if ((state->fe[0]->dtv_property_cache.isdbt_sb_segment_count % 2) == 0)
-			dds_offset -= (int)(segtodds / 2);
-
-		if (state->cfg.pll->ifreq == 0) {
-			if ((state->fe[0]->dtv_property_cache.inversion ^ i) == 0) {
-				dib8000_write_word(state, 26, dib8000_read_word(state, 26) | 1);
-				new_dds = dds_offset;
-			} else
-				new_dds = dds_offset;
-
-			// We shift tuning frequency if the wanted segment is :
-			//  - the segment of center frequency with an odd total number of segments
-			//  - the segment to the left of center frequency with an even total number of segments
-			//  - the segment to the right of center frequency with an even total number of segments
-			if ((state->fe[0]->dtv_property_cache.delivery_system == SYS_ISDBT)
-				&& (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1)
-					&& (((state->fe[0]->dtv_property_cache.isdbt_sb_segment_count % 2)
-					  && (state->fe[0]->dtv_property_cache.isdbt_sb_segment_idx ==
-				  ((state->fe[0]->dtv_property_cache.isdbt_sb_segment_count / 2) + 1)))
-					 || (((state->fe[0]->dtv_property_cache.isdbt_sb_segment_count % 2) == 0)
-						 && (state->fe[0]->dtv_property_cache.isdbt_sb_segment_idx == (state->fe[0]->dtv_property_cache.isdbt_sb_segment_count / 2)))
-					 || (((state->fe[0]->dtv_property_cache.isdbt_sb_segment_count % 2) == 0)
-						 && (state->fe[0]->dtv_property_cache.isdbt_sb_segment_idx ==
-							 ((state->fe[0]->dtv_property_cache.isdbt_sb_segment_count / 2) + 1)))
-					)) {
-				new_dds -= ((u32) (850 << 22) / clk) << 4;	// new_dds = 850 (freq shift in KHz) / Fclk * pow(2,26)
-			}
-		} else {
-			if ((state->fe[0]->dtv_property_cache.inversion ^ i) == 0)
-				new_dds = state->cfg.pll->ifreq - dds_offset;
-			else
-				new_dds = state->cfg.pll->ifreq + dds_offset;
-		}
-		dib8000_write_word(state, 27, (u16) ((new_dds >> 16) & 0x01ff));
-		dib8000_write_word(state, 28, (u16) (new_dds & 0xffff));
-		if (state->fe[0]->dtv_property_cache.isdbt_sb_segment_count % 2)
-			sub_channel = ((state->fe[0]->dtv_property_cache.isdbt_sb_subchannel + (3 * seg_offset) + 1) % 41) / 3;
-		else
-			sub_channel = ((state->fe[0]->dtv_property_cache.isdbt_sb_subchannel + (3 * seg_offset)) % 41) / 3;
-		sub_channel -= 6;
-
-		if (state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_2K
-				|| state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_4K) {
-			dib8000_write_word(state, 219, dib8000_read_word(state, 219) | 0x1);	//adp_pass =1
-			dib8000_write_word(state, 190, dib8000_read_word(state, 190) | (0x1 << 14));	//pha3_force_pha_shift = 1
-		} else {
-			dib8000_write_word(state, 219, dib8000_read_word(state, 219) & 0xfffe);	//adp_pass =0
-			dib8000_write_word(state, 190, dib8000_read_word(state, 190) & 0xbfff);	//pha3_force_pha_shift = 0
-		}
-
-		switch (state->fe[0]->dtv_property_cache.transmission_mode) {
-		case TRANSMISSION_MODE_2K:
-			switch (sub_channel) {
-			case -6:
-				init_prbs = 0x0;
-				break;	// 41, 0, 1
-			case -5:
-				init_prbs = 0x423;
-				break;	// 02~04
-			case -4:
-				init_prbs = 0x9;
-				break;	// 05~07
-			case -3:
-				init_prbs = 0x5C7;
-				break;	// 08~10
-			case -2:
-				init_prbs = 0x7A6;
-				break;	// 11~13
-			case -1:
-				init_prbs = 0x3D8;
-				break;	// 14~16
-			case 0:
-				init_prbs = 0x527;
-				break;	// 17~19
-			case 1:
-				init_prbs = 0x7FF;
-				break;	// 20~22
-			case 2:
-				init_prbs = 0x79B;
-				break;	// 23~25
-			case 3:
-				init_prbs = 0x3D6;
-				break;	// 26~28
-			case 4:
-				init_prbs = 0x3A2;
-				break;	// 29~31
-			case 5:
-				init_prbs = 0x53B;
-				break;	// 32~34
-			case 6:
-				init_prbs = 0x2F4;
-				break;	// 35~37
-			default:
-			case 7:
-				init_prbs = 0x213;
-				break;	// 38~40
-			}
-			break;
-
-		case TRANSMISSION_MODE_4K:
-			switch (sub_channel) {
-			case -6:
-				init_prbs = 0x0;
-				break;	// 41, 0, 1
-			case -5:
-				init_prbs = 0x208;
-				break;	// 02~04
-			case -4:
-				init_prbs = 0xC3;
-				break;	// 05~07
-			case -3:
-				init_prbs = 0x7B9;
-				break;	// 08~10
-			case -2:
-				init_prbs = 0x423;
-				break;	// 11~13
-			case -1:
-				init_prbs = 0x5C7;
-				break;	// 14~16
-			case 0:
-				init_prbs = 0x3D8;
-				break;	// 17~19
-			case 1:
-				init_prbs = 0x7FF;
-				break;	// 20~22
-			case 2:
-				init_prbs = 0x3D6;
-				break;	// 23~25
-			case 3:
-				init_prbs = 0x53B;
-				break;	// 26~28
-			case 4:
-				init_prbs = 0x213;
-				break;	// 29~31
-			case 5:
-				init_prbs = 0x29;
-				break;	// 32~34
-			case 6:
-				init_prbs = 0xD0;
-				break;	// 35~37
-			default:
-			case 7:
-				init_prbs = 0x48E;
-				break;	// 38~40
-			}
-			break;
-
-		default:
-		case TRANSMISSION_MODE_8K:
-			switch (sub_channel) {
-			case -6:
-				init_prbs = 0x0;
-				break;	// 41, 0, 1
-			case -5:
-				init_prbs = 0x740;
-				break;	// 02~04
-			case -4:
-				init_prbs = 0x069;
-				break;	// 05~07
-			case -3:
-				init_prbs = 0x7DD;
-				break;	// 08~10
-			case -2:
-				init_prbs = 0x208;
-				break;	// 11~13
-			case -1:
-				init_prbs = 0x7B9;
-				break;	// 14~16
-			case 0:
-				init_prbs = 0x5C7;
-				break;	// 17~19
-			case 1:
-				init_prbs = 0x7FF;
-				break;	// 20~22
-			case 2:
-				init_prbs = 0x53B;
-				break;	// 23~25
-			case 3:
-				init_prbs = 0x29;
-				break;	// 26~28
-			case 4:
-				init_prbs = 0x48E;
-				break;	// 29~31
-			case 5:
-				init_prbs = 0x4C4;
-				break;	// 32~34
-			case 6:
-				init_prbs = 0x367;
-				break;	// 33~37
-			default:
-			case 7:
-				init_prbs = 0x684;
-				break;	// 38~40
-			}
-			break;
-		}
-	} else {
-		dib8000_write_word(state, 27, (u16) ((state->cfg.pll->ifreq >> 16) & 0x01ff));
-		dib8000_write_word(state, 28, (u16) (state->cfg.pll->ifreq & 0xffff));
-		dib8000_write_word(state, 26, (u16) ((state->cfg.pll->ifreq >> 25) & 0x0003));
-	}
-	/*P_mode == ?? */
-	dib8000_write_word(state, 10, (seq << 4));
-	//  dib8000_write_word(state, 287, (dib8000_read_word(state, 287) & 0xe000) | 0x1000);
-
-	switch (state->fe[0]->dtv_property_cache.guard_interval) {
-	case GUARD_INTERVAL_1_32:
-		guard = 0;
-		break;
-	case GUARD_INTERVAL_1_16:
-		guard = 1;
-		break;
-	case GUARD_INTERVAL_1_8:
-		guard = 2;
-		break;
-	case GUARD_INTERVAL_1_4:
-	default:
-		guard = 3;
-		break;
-	}
-
-	dib8000_write_word(state, 1, (init_prbs << 2) | (guard & 0x3));	// ADDR 1
-
-	max_constellation = DQPSK;
-	for (i = 0; i < 3; i++) {
-		switch (state->fe[0]->dtv_property_cache.layer[i].modulation) {
-		case DQPSK:
-			constellation = 0;
-			break;
-		case QPSK:
-			constellation = 1;
-			break;
-		case QAM_16:
-			constellation = 2;
-			break;
-		case QAM_64:
-		default:
-			constellation = 3;
-			break;
-		}
-
-		switch (state->fe[0]->dtv_property_cache.layer[i].fec) {
-		case FEC_1_2:
-			crate = 1;
-			break;
-		case FEC_2_3:
-			crate = 2;
-			break;
-		case FEC_3_4:
-			crate = 3;
-			break;
-		case FEC_5_6:
-			crate = 5;
-			break;
-		case FEC_7_8:
-		default:
-			crate = 7;
-			break;
-		}
-
-		if ((state->fe[0]->dtv_property_cache.layer[i].interleaving > 0) &&
-				((state->fe[0]->dtv_property_cache.layer[i].interleaving <= 3) ||
-				 (state->fe[0]->dtv_property_cache.layer[i].interleaving == 4 && state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1))
-			)
-			timeI = state->fe[0]->dtv_property_cache.layer[i].interleaving;
-		else
-			timeI = 0;
-		dib8000_write_word(state, 2 + i, (constellation << 10) | ((state->fe[0]->dtv_property_cache.layer[i].segment_count & 0xf) << 6) |
-					(crate << 3) | timeI);
-		if (state->fe[0]->dtv_property_cache.layer[i].segment_count > 0) {
-			switch (max_constellation) {
-			case DQPSK:
-			case QPSK:
-				if (state->fe[0]->dtv_property_cache.layer[i].modulation == QAM_16 ||
-					state->fe[0]->dtv_property_cache.layer[i].modulation == QAM_64)
-					max_constellation = state->fe[0]->dtv_property_cache.layer[i].modulation;
-				break;
-			case QAM_16:
-				if (state->fe[0]->dtv_property_cache.layer[i].modulation == QAM_64)
-					max_constellation = state->fe[0]->dtv_property_cache.layer[i].modulation;
-				break;
-			}
-		}
-	}
-
-	mode = fft_to_mode(state);
-
-	//dib8000_write_word(state, 5, 13); /*p_last_seg = 13*/
-
-	dib8000_write_word(state, 274, (dib8000_read_word(state, 274) & 0xffcf) |
-				((state->fe[0]->dtv_property_cache.isdbt_partial_reception & 1) << 5) | ((state->fe[0]->dtv_property_cache.
-												 isdbt_sb_mode & 1) << 4));
-
-	dprintk("mode = %d ; guard = %d", mode, state->fe[0]->dtv_property_cache.guard_interval);
-
-	/* signal optimization parameter */
-
-	if (state->fe[0]->dtv_property_cache.isdbt_partial_reception) {
-		seg_diff_mask = (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK) << permu_seg[0];
-		for (i = 1; i < 3; i++)
-			nbseg_diff +=
-				(state->fe[0]->dtv_property_cache.layer[i].modulation == DQPSK) * state->fe[0]->dtv_property_cache.layer[i].segment_count;
-		for (i = 0; i < nbseg_diff; i++)
-			seg_diff_mask |= 1 << permu_seg[i + 1];
-	} else {
-		for (i = 0; i < 3; i++)
-			nbseg_diff +=
-				(state->fe[0]->dtv_property_cache.layer[i].modulation == DQPSK) * state->fe[0]->dtv_property_cache.layer[i].segment_count;
-		for (i = 0; i < nbseg_diff; i++)
-			seg_diff_mask |= 1 << permu_seg[i];
-	}
-	dprintk("nbseg_diff = %X (%d)", seg_diff_mask, seg_diff_mask);
-
-	state->differential_constellation = (seg_diff_mask != 0);
-	if (state->revision != 0x8090)
-		dib8000_set_diversity_in(state->fe[0], state->diversity_onoff);
-	else
-		dib8096p_set_diversity_in(state->fe[0], state->diversity_onoff);
-
-	if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) {
-		if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 1)
-			seg_mask13 = 0x00E0;
-		else		// 1-segment
-			seg_mask13 = 0x0040;
-	} else
-		seg_mask13 = 0x1fff;
-
-	// WRITE: Mode & Diff mask
-	dib8000_write_word(state, 0, (mode << 13) | seg_diff_mask);
-
-	if ((seg_diff_mask) || (state->fe[0]->dtv_property_cache.isdbt_sb_mode))
-		dib8000_write_word(state, 268, (dib8000_read_word(state, 268) & 0xF9FF) | 0x0200);
-	else
-		dib8000_write_word(state, 268, (2 << 9) | 39);	//init value
-
-	// ---- SMALL ----
-	// P_small_seg_diff
-	dib8000_write_word(state, 352, seg_diff_mask);	// ADDR 352
-
-	dib8000_write_word(state, 353, seg_mask13);	// ADDR 353
-
-/*	// P_small_narrow_band=0, P_small_last_seg=13, P_small_offset_num_car=5 */
-
-	// ---- SMALL ----
-	if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) {
-		switch (state->fe[0]->dtv_property_cache.transmission_mode) {
-		case TRANSMISSION_MODE_2K:
-			if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) {
-				if (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK)
-					ncoeff = coeff_2k_sb_1seg_dqpsk;
-				else	// QPSK or QAM
-					ncoeff = coeff_2k_sb_1seg;
-			} else {	// 3-segments
-				if (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK) {
-					if (state->fe[0]->dtv_property_cache.layer[1].modulation == DQPSK)
-						ncoeff = coeff_2k_sb_3seg_0dqpsk_1dqpsk;
-					else	// QPSK or QAM on external segments
-						ncoeff = coeff_2k_sb_3seg_0dqpsk;
-				} else {	// QPSK or QAM on central segment
-					if (state->fe[0]->dtv_property_cache.layer[1].modulation == DQPSK)
-						ncoeff = coeff_2k_sb_3seg_1dqpsk;
-					else	// QPSK or QAM on external segments
-						ncoeff = coeff_2k_sb_3seg;
-				}
-			}
-			break;
-
-		case TRANSMISSION_MODE_4K:
-			if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) {
-				if (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK)
-					ncoeff = coeff_4k_sb_1seg_dqpsk;
-				else	// QPSK or QAM
-					ncoeff = coeff_4k_sb_1seg;
-			} else {	// 3-segments
-				if (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK) {
-					if (state->fe[0]->dtv_property_cache.layer[1].modulation == DQPSK) {
-						ncoeff = coeff_4k_sb_3seg_0dqpsk_1dqpsk;
-					} else {	// QPSK or QAM on external segments
-						ncoeff = coeff_4k_sb_3seg_0dqpsk;
-					}
-				} else {	// QPSK or QAM on central segment
-					if (state->fe[0]->dtv_property_cache.layer[1].modulation == DQPSK) {
-						ncoeff = coeff_4k_sb_3seg_1dqpsk;
-					} else	// QPSK or QAM on external segments
-						ncoeff = coeff_4k_sb_3seg;
-				}
-			}
-			break;
-
-		case TRANSMISSION_MODE_AUTO:
-		case TRANSMISSION_MODE_8K:
-		default:
-			if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) {
-				if (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK)
-					ncoeff = coeff_8k_sb_1seg_dqpsk;
-				else	// QPSK or QAM
-					ncoeff = coeff_8k_sb_1seg;
-			} else {	// 3-segments
-				if (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK) {
-					if (state->fe[0]->dtv_property_cache.layer[1].modulation == DQPSK) {
-						ncoeff = coeff_8k_sb_3seg_0dqpsk_1dqpsk;
-					} else {	// QPSK or QAM on external segments
-						ncoeff = coeff_8k_sb_3seg_0dqpsk;
-					}
-				} else {	// QPSK or QAM on central segment
-					if (state->fe[0]->dtv_property_cache.layer[1].modulation == DQPSK) {
-						ncoeff = coeff_8k_sb_3seg_1dqpsk;
-					} else	// QPSK or QAM on external segments
-						ncoeff = coeff_8k_sb_3seg;
-				}
-			}
-			break;
-		}
-		for (i = 0; i < 8; i++)
-			dib8000_write_word(state, 343 + i, ncoeff[i]);
-	}
-
-	// P_small_coef_ext_enable=ISDB-Tsb, P_small_narrow_band=ISDB-Tsb, P_small_last_seg=13, P_small_offset_num_car=5
-	dib8000_write_word(state, 351,
-				(state->fe[0]->dtv_property_cache.isdbt_sb_mode << 9) | (state->fe[0]->dtv_property_cache.isdbt_sb_mode << 8) | (13 << 4) | 5);
-
-	// ---- COFF ----
-	// Carloff, the most robust
-	if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) {
-
-		// P_coff_cpil_alpha=4, P_coff_inh=0, P_coff_cpil_winlen=64
-		// P_coff_narrow_band=1, P_coff_square_val=1, P_coff_one_seg=~partial_rcpt, P_coff_use_tmcc=1, P_coff_use_ac=1
-		dib8000_write_word(state, 187,
-					(4 << 12) | (0 << 11) | (63 << 5) | (0x3 << 3) | ((~state->fe[0]->dtv_property_cache.isdbt_partial_reception & 1) << 2)
-					| 0x3);
-
-/*		// P_small_coef_ext_enable = 1 */
-/*		dib8000_write_word(state, 351, dib8000_read_word(state, 351) | 0x200); */
-
-		if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) {
-
-			// P_coff_winlen=63, P_coff_thres_lock=15, P_coff_one_seg_width= (P_mode == 3) , P_coff_one_seg_sym= (P_mode-1)
-			if (mode == 3)
-				dib8000_write_word(state, 180, 0x1fcf | ((mode - 1) << 14));
-			else
-				dib8000_write_word(state, 180, 0x0fcf | ((mode - 1) << 14));
-			// P_ctrl_corm_thres4pre_freq_inh=1,P_ctrl_pre_freq_mode_sat=1,
-			// P_ctrl_pre_freq_inh=0, P_ctrl_pre_freq_step = 5, P_pre_freq_win_len=4
-			dib8000_write_word(state, 338, (1 << 12) | (1 << 10) | (0 << 9) | (5 << 5) | 4);
-			// P_ctrl_pre_freq_win_len=16, P_ctrl_pre_freq_thres_lockin=8
-			dib8000_write_word(state, 340, (16 << 6) | (8 << 0));
-			// P_ctrl_pre_freq_thres_lockout=6, P_small_use_tmcc/ac/cp=1
-			dib8000_write_word(state, 341, (6 << 3) | (1 << 2) | (1 << 1) | (1 << 0));
-
-			// P_coff_corthres_8k, 4k, 2k and P_coff_cpilthres_8k, 4k, 2k
-			dib8000_write_word(state, 181, 300);
-			dib8000_write_word(state, 182, 150);
-			dib8000_write_word(state, 183, 80);
-			dib8000_write_word(state, 184, 300);
-			dib8000_write_word(state, 185, 150);
-			dib8000_write_word(state, 186, 80);
-		} else {	// Sound Broadcasting mode 3 seg
-			// P_coff_one_seg_sym= 1, P_coff_one_seg_width= 1, P_coff_winlen=63, P_coff_thres_lock=15
-			/*	if (mode == 3) */
-			/*		dib8000_write_word(state, 180, 0x2fca | ((0) << 14)); */
-			/*	else */
-			/*		dib8000_write_word(state, 180, 0x2fca | ((1) << 14)); */
-			dib8000_write_word(state, 180, 0x1fcf | (1 << 14));
-
-			// P_ctrl_corm_thres4pre_freq_inh = 1, P_ctrl_pre_freq_mode_sat=1,
-			// P_ctrl_pre_freq_inh=0, P_ctrl_pre_freq_step = 4, P_pre_freq_win_len=4
-			dib8000_write_word(state, 338, (1 << 12) | (1 << 10) | (0 << 9) | (4 << 5) | 4);
-			// P_ctrl_pre_freq_win_len=16, P_ctrl_pre_freq_thres_lockin=8
-			dib8000_write_word(state, 340, (16 << 6) | (8 << 0));
-			//P_ctrl_pre_freq_thres_lockout=6, P_small_use_tmcc/ac/cp=1
-			dib8000_write_word(state, 341, (6 << 3) | (1 << 2) | (1 << 1) | (1 << 0));
-
-			// P_coff_corthres_8k, 4k, 2k and P_coff_cpilthres_8k, 4k, 2k
-			dib8000_write_word(state, 181, 350);
-			dib8000_write_word(state, 182, 300);
-			dib8000_write_word(state, 183, 250);
-			dib8000_write_word(state, 184, 350);
-			dib8000_write_word(state, 185, 300);
-			dib8000_write_word(state, 186, 250);
-		}
-
-	} else if (state->isdbt_cfg_loaded == 0) {	// if not Sound Broadcasting mode : put default values for 13 segments
-		dib8000_write_word(state, 180, (16 << 6) | 9);
-		dib8000_write_word(state, 187, (4 << 12) | (8 << 5) | 0x2);
-		coff_pow = 0x2800;
-		for (i = 0; i < 6; i++)
-			dib8000_write_word(state, 181 + i, coff_pow);
-
-		// P_ctrl_corm_thres4pre_freq_inh=1, P_ctrl_pre_freq_mode_sat=1,
-		// P_ctrl_pre_freq_mode_sat=1, P_ctrl_pre_freq_inh=0, P_ctrl_pre_freq_step = 3, P_pre_freq_win_len=1
-		dib8000_write_word(state, 338, (1 << 12) | (1 << 10) | (0 << 9) | (3 << 5) | 1);
-
-		// P_ctrl_pre_freq_win_len=8, P_ctrl_pre_freq_thres_lockin=6
-		dib8000_write_word(state, 340, (8 << 6) | (6 << 0));
-		// P_ctrl_pre_freq_thres_lockout=4, P_small_use_tmcc/ac/cp=1
-		dib8000_write_word(state, 341, (4 << 3) | (1 << 2) | (1 << 1) | (1 << 0));
-	}
-	// ---- FFT ----
-	if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1 && state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0)
-		dib8000_write_word(state, 178, 64);	// P_fft_powrange=64
-	else
-		dib8000_write_word(state, 178, 32);	// P_fft_powrange=32
-
-	/* make the cpil_coff_lock more robust but slower p_coff_winlen
-	 * 6bits; p_coff_thres_lock 6bits (for coff lock if needed)
-	 */
-	/* if ( ( nbseg_diff>0)&&(nbseg_diff<13))
-		dib8000_write_word(state, 187, (dib8000_read_word(state, 187) & 0xfffb) | (1 << 3)); */
-
-	dib8000_write_word(state, 189, ~seg_mask13 | seg_diff_mask);	/* P_lmod4_seg_inh       */
-	dib8000_write_word(state, 192, ~seg_mask13 | seg_diff_mask);	/* P_pha3_seg_inh        */
-	dib8000_write_word(state, 225, ~seg_mask13 | seg_diff_mask);	/* P_tac_seg_inh         */
-	if ((!state->fe[0]->dtv_property_cache.isdbt_sb_mode) && (state->cfg.pll->ifreq == 0))
-		dib8000_write_word(state, 266, ~seg_mask13 | seg_diff_mask | 0x40);	/* P_equal_noise_seg_inh */
-	else
-		dib8000_write_word(state, 266, ~seg_mask13 | seg_diff_mask);	/* P_equal_noise_seg_inh */
-	dib8000_write_word(state, 287, ~seg_mask13 | 0x1000);	/* P_tmcc_seg_inh        */
-	//dib8000_write_word(state, 288, ~seg_mask13 | seg_diff_mask); /* P_tmcc_seg_eq_inh */
-	if (!autosearching)
-		dib8000_write_word(state, 288, (~seg_mask13 | seg_diff_mask) & 0x1fff);	/* P_tmcc_seg_eq_inh */
-	else
-		dib8000_write_word(state, 288, 0x1fff);	//disable equalisation of the tmcc when autosearch to be able to find the DQPSK channels.
-	dprintk("287 = %X (%d)", ~seg_mask13 | 0x1000, ~seg_mask13 | 0x1000);
-
-	dib8000_write_word(state, 211, seg_mask13 & (~seg_diff_mask));	/* P_des_seg_enabled     */
-
-	/* offset loop parameters */
-	if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) {
-		if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0)
-			/* P_timf_alpha = (11-P_mode), P_corm_alpha=6, P_corm_thres=0x80 */
-			dib8000_write_word(state, 32, ((11 - mode) << 12) | (6 << 8) | 0x40);
-
-		else		// Sound Broadcasting mode 3 seg
-			/* P_timf_alpha = (10-P_mode), P_corm_alpha=6, P_corm_thres=0x80 */
-			dib8000_write_word(state, 32, ((10 - mode) << 12) | (6 << 8) | 0x60);
-	} else
-		// TODO in 13 seg, timf_alpha can always be the same or not ?
-		/* P_timf_alpha = (9-P_mode, P_corm_alpha=6, P_corm_thres=0x80 */
-		dib8000_write_word(state, 32, ((9 - mode) << 12) | (6 << 8) | 0x80);
-
-	if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) {
-		if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0)
-			/* P_ctrl_pha_off_max=3   P_ctrl_sfreq_inh =0  P_ctrl_sfreq_step = (11-P_mode)  */
-			dib8000_write_word(state, 37, (3 << 5) | (0 << 4) | (10 - mode));
-
-		else		// Sound Broadcasting mode 3 seg
-			/* P_ctrl_pha_off_max=3   P_ctrl_sfreq_inh =0  P_ctrl_sfreq_step = (10-P_mode)  */
-			dib8000_write_word(state, 37, (3 << 5) | (0 << 4) | (9 - mode));
-	} else
-		/* P_ctrl_pha_off_max=3   P_ctrl_sfreq_inh =0  P_ctrl_sfreq_step = 9  */
-		dib8000_write_word(state, 37, (3 << 5) | (0 << 4) | (8 - mode));
-
-	/* P_dvsy_sync_wait - reuse mode */
-	switch (state->fe[0]->dtv_property_cache.transmission_mode) {
-	case TRANSMISSION_MODE_8K:
-		mode = 256;
-		break;
-	case TRANSMISSION_MODE_4K:
-		mode = 128;
-		break;
-	default:
-	case TRANSMISSION_MODE_2K:
-		mode = 64;
-		break;
-	}
-	if (state->cfg.diversity_delay == 0)
-		mode = (mode * (1 << (guard)) * 3) / 2 + 48;	// add 50% SFN margin + compensate for one DVSY-fifo
-	else
-		mode = (mode * (1 << (guard)) * 3) / 2 + state->cfg.diversity_delay;	// add 50% SFN margin + compensate for DVSY-fifo
-	mode <<= 4;
-	dib8000_write_word(state, 273, (dib8000_read_word(state, 273) & 0x000f) | mode);
-
-	/* channel estimation fine configuration */
-	switch (max_constellation) {
-	case QAM_64:
-		ana_gain = 0x7;	// -1 : avoid def_est saturation when ADC target is -16dB
-		coeff[0] = 0x0148;	/* P_adp_regul_cnt 0.04 */
-		coeff[1] = 0xfff0;	/* P_adp_noise_cnt -0.002 */
-		coeff[2] = 0x00a4;	/* P_adp_regul_ext 0.02 */
-		coeff[3] = 0xfff8;	/* P_adp_noise_ext -0.001 */
-		//if (!state->cfg.hostbus_diversity) //if diversity, we should prehaps use the configuration of the max_constallation -1
-		break;
-	case QAM_16:
-		ana_gain = 0x7;	// -1 : avoid def_est saturation when ADC target is -16dB
-		coeff[0] = 0x023d;	/* P_adp_regul_cnt 0.07 */
-		coeff[1] = 0xffdf;	/* P_adp_noise_cnt -0.004 */
-		coeff[2] = 0x00a4;	/* P_adp_regul_ext 0.02 */
-		coeff[3] = 0xfff0;	/* P_adp_noise_ext -0.002 */
-		//if (!((state->cfg.hostbus_diversity) && (max_constellation == QAM_16)))
-		break;
-	default:
-		ana_gain = 0;	// 0 : goes along with ADC target at -22dB to keep good mobile performance and lock at sensitivity level
-		coeff[0] = 0x099a;	/* P_adp_regul_cnt 0.3 */
-		coeff[1] = 0xffae;	/* P_adp_noise_cnt -0.01 */
-		coeff[2] = 0x0333;	/* P_adp_regul_ext 0.1 */
-		coeff[3] = 0xfff8;	/* P_adp_noise_ext -0.002 */
-		break;
-	}
-	for (mode = 0; mode < 4; mode++)
-		dib8000_write_word(state, 215 + mode, coeff[mode]);
-
-	// update ana_gain depending on max constellation
-	dib8000_write_word(state, 116, ana_gain);
-	// update ADC target depending on ana_gain
-	if (ana_gain) {		// set -16dB ADC target for ana_gain=-1
-		for (i = 0; i < 10; i++)
-			dib8000_write_word(state, 80 + i, adc_target_16dB[i]);
-	} else {		// set -22dB ADC target for ana_gain=0
-		for (i = 0; i < 10; i++)
-			dib8000_write_word(state, 80 + i, adc_target_16dB[i] - 355);
-	}
-
-	// ---- ANA_FE ----
-	if (state->fe[0]->dtv_property_cache.isdbt_sb_mode) {
-		if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 1)
-			ana_fe = ana_fe_coeff_3seg;
-		else		// 1-segment
-			ana_fe = ana_fe_coeff_1seg;
-	} else
-		ana_fe = ana_fe_coeff_13seg;
-
-	if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1 || state->isdbt_cfg_loaded == 0)
-		for (mode = 0; mode < 24; mode++)
-			dib8000_write_word(state, 117 + mode, ana_fe[mode]);
-
-	// ---- CHAN_BLK ----
-	for (i = 0; i < 13; i++) {
-		if ((((~seg_diff_mask) >> i) & 1) == 1) {
-			P_cfr_left_edge += (1 << i) * ((i == 0) || ((((seg_mask13 & (~seg_diff_mask)) >> (i - 1)) & 1) == 0));
-			P_cfr_right_edge += (1 << i) * ((i == 12) || ((((seg_mask13 & (~seg_diff_mask)) >> (i + 1)) & 1) == 0));
-		}
-	}
-	dib8000_write_word(state, 222, P_cfr_left_edge);	// P_cfr_left_edge
-	dib8000_write_word(state, 223, P_cfr_right_edge);	// P_cfr_right_edge
-	// "P_cspu_left_edge"  not used => do not care
-	// "P_cspu_right_edge" not used => do not care
-
-	if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) {
-		dib8000_write_word(state, 228, 1);	// P_2d_mode_byp=1
-		dib8000_write_word(state, 205, dib8000_read_word(state, 205) & 0xfff0);	// P_cspu_win_cut = 0
-		if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0
-			&& state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_2K) {
-			//dib8000_write_word(state, 219, dib8000_read_word(state, 219) & 0xfffe); // P_adp_pass = 0
-			dib8000_write_word(state, 265, 15);	// P_equal_noise_sel = 15
-		}
-	} else if (state->isdbt_cfg_loaded == 0) {
-		dib8000_write_word(state, 228, 0);	// default value
-		dib8000_write_word(state, 265, 31);	// default value
-		dib8000_write_word(state, 205, 0x200f);	// init value
-	}
-	// ---- TMCC ----
-	for (i = 0; i < 3; i++)
-		tmcc_pow +=
-			(((state->fe[0]->dtv_property_cache.layer[i].modulation == DQPSK) * 4 + 1) * state->fe[0]->dtv_property_cache.layer[i].segment_count);
-	// Quantif of "P_tmcc_dec_thres_?k" is (0, 5+mode, 9);
-	// Threshold is set at 1/4 of max power.
-	tmcc_pow *= (1 << (9 - 2));
-
-	dib8000_write_word(state, 290, tmcc_pow);	// P_tmcc_dec_thres_2k
-	dib8000_write_word(state, 291, tmcc_pow);	// P_tmcc_dec_thres_4k
-	dib8000_write_word(state, 292, tmcc_pow);	// P_tmcc_dec_thres_8k
-	//dib8000_write_word(state, 287, (1 << 13) | 0x1000 );
-	// ---- PHA3 ----
-
-	if (state->isdbt_cfg_loaded == 0)
-		dib8000_write_word(state, 250, 3285);	/*p_2d_hspeed_thr0 */
-
-	if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1)
-		state->isdbt_cfg_loaded = 0;
-	else
-		state->isdbt_cfg_loaded = 1;
-
-}
-
-static int dib8000_autosearch_start(struct dvb_frontend *fe)
-{
-	u8 factor;
-	u32 value;
-	struct dib8000_state *state = fe->demodulator_priv;
-
-	int slist = 0;
-
-	state->fe[0]->dtv_property_cache.inversion = 0;
-	if (!state->fe[0]->dtv_property_cache.isdbt_sb_mode)
-		state->fe[0]->dtv_property_cache.layer[0].segment_count = 13;
-	state->fe[0]->dtv_property_cache.layer[0].modulation = QAM_64;
-	state->fe[0]->dtv_property_cache.layer[0].fec = FEC_2_3;
-	state->fe[0]->dtv_property_cache.layer[0].interleaving = 0;
-
-	//choose the right list, in sb, always do everything
-	if (state->fe[0]->dtv_property_cache.isdbt_sb_mode) {
-		state->fe[0]->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_8K;
-		state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_8;
-		slist = 7;
-		dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x9fff) | (1 << 13));
-	} else {
-		if (state->fe[0]->dtv_property_cache.guard_interval == GUARD_INTERVAL_AUTO) {
-			if (state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_AUTO) {
-				slist = 7;
-				dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x9fff) | (1 << 13));	// P_mode = 1 to have autosearch start ok with mode2
-			} else
-				slist = 3;
-		} else {
-			if (state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_AUTO) {
-				slist = 2;
-				dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x9fff) | (1 << 13));	// P_mode = 1
-			} else
-				slist = 0;
-		}
-
-		if (state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_AUTO)
-			state->fe[0]->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_8K;
-		if (state->fe[0]->dtv_property_cache.guard_interval == GUARD_INTERVAL_AUTO)
-			state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_8;
-
-		dprintk("using list for autosearch : %d", slist);
-		dib8000_set_channel(state, (unsigned char)slist, 1);
-		//dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x9fff) | (1 << 13));  // P_mode = 1
-
-		factor = 1;
-
-		//set lock_mask values
-		dib8000_write_word(state, 6, 0x4);
-		dib8000_write_word(state, 7, 0x8);
-		dib8000_write_word(state, 8, 0x1000);
-
-		//set lock_mask wait time values
-		value = 50 * state->cfg.pll->internal * factor;
-		dib8000_write_word(state, 11, (u16) ((value >> 16) & 0xffff));	// lock0 wait time
-		dib8000_write_word(state, 12, (u16) (value & 0xffff));	// lock0 wait time
-		value = 100 * state->cfg.pll->internal * factor;
-		dib8000_write_word(state, 13, (u16) ((value >> 16) & 0xffff));	// lock1 wait time
-		dib8000_write_word(state, 14, (u16) (value & 0xffff));	// lock1 wait time
-		value = 1000 * state->cfg.pll->internal * factor;
-		dib8000_write_word(state, 15, (u16) ((value >> 16) & 0xffff));	// lock2 wait time
-		dib8000_write_word(state, 16, (u16) (value & 0xffff));	// lock2 wait time
-
-		value = dib8000_read_word(state, 0);
-		dib8000_write_word(state, 0, (u16) ((1 << 15) | value));
-		dib8000_read_word(state, 1284);	// reset the INT. n_irq_pending
-		dib8000_write_word(state, 0, (u16) value);
-
-	}
-
-	return 0;
-}
-
-static int dib8000_autosearch_irq(struct dvb_frontend *fe)
-{
-	struct dib8000_state *state = fe->demodulator_priv;
-	u16 irq_pending = dib8000_read_word(state, 1284);
-
-	if (irq_pending & 0x1) {	// failed
-		dprintk("dib8000_autosearch_irq failed");
-		return 1;
-	}
-
-	if (irq_pending & 0x2) {	// succeeded
-		dprintk("dib8000_autosearch_irq succeeded");
-		return 2;
-	}
-
-	return 0;		// still pending
-}
-
-static int dib8000_tune(struct dvb_frontend *fe)
-{
-	struct dib8000_state *state = fe->demodulator_priv;
-	int ret = 0;
-	u16 lock, value, mode;
-
-	// we are already tuned - just resuming from suspend
-	if (state == NULL)
-		return -EINVAL;
-
-	mode = fft_to_mode(state);
-
-	dib8000_set_bandwidth(fe, state->fe[0]->dtv_property_cache.bandwidth_hz / 1000);
-	dib8000_set_channel(state, 0, 0);
-
-	// restart demod
-	ret |= dib8000_write_word(state, 770, 0x4000);
-	ret |= dib8000_write_word(state, 770, 0x0000);
-	msleep(45);
-
-	/* P_ctrl_inh_cor=0, P_ctrl_alpha_cor=4, P_ctrl_inh_isi=0, P_ctrl_alpha_isi=3 */
-	/*  ret |= dib8000_write_word(state, 29, (0 << 9) | (4 << 5) | (0 << 4) | (3 << 0) );  workaround inh_isi stays at 1 */
-
-	// never achieved a lock before - wait for timfreq to update
-	if (state->timf == 0) {
-		if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) {
-			if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0)
-				msleep(300);
-			else	// Sound Broadcasting mode 3 seg
-				msleep(500);
-		} else		// 13 seg
-			msleep(200);
-	}
-	if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) {
-		if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) {
-
-			/* P_timf_alpha = (13-P_mode) , P_corm_alpha=6, P_corm_thres=0x40  alpha to check on board */
-			dib8000_write_word(state, 32, ((13 - mode) << 12) | (6 << 8) | 0x40);
-			//dib8000_write_word(state, 32, (8 << 12) | (6 << 8) | 0x80);
-
-			/*  P_ctrl_sfreq_step= (12-P_mode)   P_ctrl_sfreq_inh =0     P_ctrl_pha_off_max  */
-			ret |= dib8000_write_word(state, 37, (12 - mode) | ((5 + mode) << 5));
-
-		} else {	// Sound Broadcasting mode 3 seg
-
-			/* P_timf_alpha = (12-P_mode) , P_corm_alpha=6, P_corm_thres=0x60  alpha to check on board */
-			dib8000_write_word(state, 32, ((12 - mode) << 12) | (6 << 8) | 0x60);
-
-			ret |= dib8000_write_word(state, 37, (11 - mode) | ((5 + mode) << 5));
-		}
-
-	} else {		// 13 seg
-		/* P_timf_alpha = 8 , P_corm_alpha=6, P_corm_thres=0x80  alpha to check on board */
-		dib8000_write_word(state, 32, ((11 - mode) << 12) | (6 << 8) | 0x80);
-
-		ret |= dib8000_write_word(state, 37, (10 - mode) | ((5 + mode) << 5));
-
-	}
-
-	// we achieved a coff_cpil_lock - it's time to update the timf
-	if (state->revision != 0x8090)
-		lock = dib8000_read_word(state, 568);
-	else
-		lock = dib8000_read_word(state, 570);
-	if ((lock >> 11) & 0x1)
-		dib8000_update_timf(state);
-
-	//now that tune is finished, lock0 should lock on fec_mpeg to output this lock on MP_LOCK. It's changed in autosearch start
-	dib8000_write_word(state, 6, 0x200);
-
-	if (state->revision == 0x8002) {
-		value = dib8000_read_word(state, 903);
-		dib8000_write_word(state, 903, value & ~(1 << 3));
-		msleep(1);
-		dib8000_write_word(state, 903, value | (1 << 3));
-	}
-
-	return ret;
-}
-
-static int dib8000_wakeup(struct dvb_frontend *fe)
-{
-	struct dib8000_state *state = fe->demodulator_priv;
-	u8 index_frontend;
-	int ret;
-
-	dib8000_set_power_mode(state, DIB8000_POWER_ALL);
-	dib8000_set_adc_state(state, DIBX000_ADC_ON);
-	if (dib8000_set_adc_state(state, DIBX000_SLOW_ADC_ON) != 0)
-		dprintk("could not start Slow ADC");
-
-	if (state->revision != 0x8090)
-		dib8000_sad_calib(state);
-
-	for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
-		ret = state->fe[index_frontend]->ops.init(state->fe[index_frontend]);
-		if (ret < 0)
-			return ret;
-	}
-
-	return 0;
-}
-
-static int dib8000_sleep(struct dvb_frontend *fe)
-{
-	struct dib8000_state *state = fe->demodulator_priv;
-	u8 index_frontend;
-	int ret;
-
-	for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
-		ret = state->fe[index_frontend]->ops.sleep(state->fe[index_frontend]);
-		if (ret < 0)
-			return ret;
-	}
-
-	if (state->revision != 0x8090)
-		dib8000_set_output_mode(fe, OUTMODE_HIGH_Z);
-	dib8000_set_power_mode(state, DIB8000_POWER_INTERFACE_ONLY);
-	return dib8000_set_adc_state(state, DIBX000_SLOW_ADC_OFF) | dib8000_set_adc_state(state, DIBX000_ADC_OFF);
-}
-
-enum frontend_tune_state dib8000_get_tune_state(struct dvb_frontend *fe)
-{
-	struct dib8000_state *state = fe->demodulator_priv;
-	return state->tune_state;
-}
-EXPORT_SYMBOL(dib8000_get_tune_state);
-
-int dib8000_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state)
-{
-	struct dib8000_state *state = fe->demodulator_priv;
-	state->tune_state = tune_state;
-	return 0;
-}
-EXPORT_SYMBOL(dib8000_set_tune_state);
-
-static int dib8000_get_frontend(struct dvb_frontend *fe)
-{
-	struct dib8000_state *state = fe->demodulator_priv;
-	u16 i, val = 0;
-	fe_status_t stat;
-	u8 index_frontend, sub_index_frontend;
-
-	fe->dtv_property_cache.bandwidth_hz = 6000000;
-
-	for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
-		state->fe[index_frontend]->ops.read_status(state->fe[index_frontend], &stat);
-		if (stat&FE_HAS_SYNC) {
-			dprintk("TMCC lock on the slave%i", index_frontend);
-			/* synchronize the cache with the other frontends */
-			state->fe[index_frontend]->ops.get_frontend(state->fe[index_frontend]);
-			for (sub_index_frontend = 0; (sub_index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[sub_index_frontend] != NULL); sub_index_frontend++) {
-				if (sub_index_frontend != index_frontend) {
-					state->fe[sub_index_frontend]->dtv_property_cache.isdbt_sb_mode = state->fe[index_frontend]->dtv_property_cache.isdbt_sb_mode;
-					state->fe[sub_index_frontend]->dtv_property_cache.inversion = state->fe[index_frontend]->dtv_property_cache.inversion;
-					state->fe[sub_index_frontend]->dtv_property_cache.transmission_mode = state->fe[index_frontend]->dtv_property_cache.transmission_mode;
-					state->fe[sub_index_frontend]->dtv_property_cache.guard_interval = state->fe[index_frontend]->dtv_property_cache.guard_interval;
-					state->fe[sub_index_frontend]->dtv_property_cache.isdbt_partial_reception = state->fe[index_frontend]->dtv_property_cache.isdbt_partial_reception;
-					for (i = 0; i < 3; i++) {
-						state->fe[sub_index_frontend]->dtv_property_cache.layer[i].segment_count = state->fe[index_frontend]->dtv_property_cache.layer[i].segment_count;
-						state->fe[sub_index_frontend]->dtv_property_cache.layer[i].interleaving = state->fe[index_frontend]->dtv_property_cache.layer[i].interleaving;
-						state->fe[sub_index_frontend]->dtv_property_cache.layer[i].fec = state->fe[index_frontend]->dtv_property_cache.layer[i].fec;
-						state->fe[sub_index_frontend]->dtv_property_cache.layer[i].modulation = state->fe[index_frontend]->dtv_property_cache.layer[i].modulation;
-					}
-				}
-			}
-			return 0;
-		}
-	}
-
-	fe->dtv_property_cache.isdbt_sb_mode = dib8000_read_word(state, 508) & 0x1;
-
-	if (state->revision == 0x8090)
-		val = dib8000_read_word(state, 572);
-	else
-		val = dib8000_read_word(state, 570);
-	fe->dtv_property_cache.inversion = (val & 0x40) >> 6;
-	switch ((val & 0x30) >> 4) {
-	case 1:
-		fe->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_2K;
-		break;
-	case 3:
-	default:
-		fe->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_8K;
-		break;
-	}
-
-	switch (val & 0x3) {
-	case 0:
-		fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_32;
-		dprintk("dib8000_get_frontend GI = 1/32 ");
-		break;
-	case 1:
-		fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_16;
-		dprintk("dib8000_get_frontend GI = 1/16 ");
-		break;
-	case 2:
-		dprintk("dib8000_get_frontend GI = 1/8 ");
-		fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_8;
-		break;
-	case 3:
-		dprintk("dib8000_get_frontend GI = 1/4 ");
-		fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_4;
-		break;
-	}
-
-	val = dib8000_read_word(state, 505);
-	fe->dtv_property_cache.isdbt_partial_reception = val & 1;
-	dprintk("dib8000_get_frontend : partial_reception = %d ", fe->dtv_property_cache.isdbt_partial_reception);
-
-	for (i = 0; i < 3; i++) {
-		val = dib8000_read_word(state, 493 + i);
-		fe->dtv_property_cache.layer[i].segment_count = val & 0x0F;
-		dprintk("dib8000_get_frontend : Layer %d segments = %d ", i, fe->dtv_property_cache.layer[i].segment_count);
-
-		val = dib8000_read_word(state, 499 + i);
-		fe->dtv_property_cache.layer[i].interleaving = val & 0x3;
-		dprintk("dib8000_get_frontend : Layer %d time_intlv = %d ", i, fe->dtv_property_cache.layer[i].interleaving);
-
-		val = dib8000_read_word(state, 481 + i);
-		switch (val & 0x7) {
-		case 1:
-			fe->dtv_property_cache.layer[i].fec = FEC_1_2;
-			dprintk("dib8000_get_frontend : Layer %d Code Rate = 1/2 ", i);
-			break;
-		case 2:
-			fe->dtv_property_cache.layer[i].fec = FEC_2_3;
-			dprintk("dib8000_get_frontend : Layer %d Code Rate = 2/3 ", i);
-			break;
-		case 3:
-			fe->dtv_property_cache.layer[i].fec = FEC_3_4;
-			dprintk("dib8000_get_frontend : Layer %d Code Rate = 3/4 ", i);
-			break;
-		case 5:
-			fe->dtv_property_cache.layer[i].fec = FEC_5_6;
-			dprintk("dib8000_get_frontend : Layer %d Code Rate = 5/6 ", i);
-			break;
-		default:
-			fe->dtv_property_cache.layer[i].fec = FEC_7_8;
-			dprintk("dib8000_get_frontend : Layer %d Code Rate = 7/8 ", i);
-			break;
-		}
-
-		val = dib8000_read_word(state, 487 + i);
-		switch (val & 0x3) {
-		case 0:
-			dprintk("dib8000_get_frontend : Layer %d DQPSK ", i);
-			fe->dtv_property_cache.layer[i].modulation = DQPSK;
-			break;
-		case 1:
-			fe->dtv_property_cache.layer[i].modulation = QPSK;
-			dprintk("dib8000_get_frontend : Layer %d QPSK ", i);
-			break;
-		case 2:
-			fe->dtv_property_cache.layer[i].modulation = QAM_16;
-			dprintk("dib8000_get_frontend : Layer %d QAM16 ", i);
-			break;
-		case 3:
-		default:
-			dprintk("dib8000_get_frontend : Layer %d QAM64 ", i);
-			fe->dtv_property_cache.layer[i].modulation = QAM_64;
-			break;
-		}
-	}
-
-	/* synchronize the cache with the other frontends */
-	for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
-		state->fe[index_frontend]->dtv_property_cache.isdbt_sb_mode = fe->dtv_property_cache.isdbt_sb_mode;
-		state->fe[index_frontend]->dtv_property_cache.inversion = fe->dtv_property_cache.inversion;
-		state->fe[index_frontend]->dtv_property_cache.transmission_mode = fe->dtv_property_cache.transmission_mode;
-		state->fe[index_frontend]->dtv_property_cache.guard_interval = fe->dtv_property_cache.guard_interval;
-		state->fe[index_frontend]->dtv_property_cache.isdbt_partial_reception = fe->dtv_property_cache.isdbt_partial_reception;
-		for (i = 0; i < 3; i++) {
-			state->fe[index_frontend]->dtv_property_cache.layer[i].segment_count = fe->dtv_property_cache.layer[i].segment_count;
-			state->fe[index_frontend]->dtv_property_cache.layer[i].interleaving = fe->dtv_property_cache.layer[i].interleaving;
-			state->fe[index_frontend]->dtv_property_cache.layer[i].fec = fe->dtv_property_cache.layer[i].fec;
-			state->fe[index_frontend]->dtv_property_cache.layer[i].modulation = fe->dtv_property_cache.layer[i].modulation;
-		}
-	}
-	return 0;
-}
-
-static int dib8000_set_frontend(struct dvb_frontend *fe)
-{
-	struct dib8000_state *state = fe->demodulator_priv;
-	u8 nbr_pending, exit_condition, index_frontend;
-	s8 index_frontend_success = -1;
-	int time, ret;
-	int  time_slave = FE_CALLBACK_TIME_NEVER;
-
-	if (state->fe[0]->dtv_property_cache.frequency == 0) {
-		dprintk("dib8000: must at least specify frequency ");
-		return 0;
-	}
-
-	if (state->fe[0]->dtv_property_cache.bandwidth_hz == 0) {
-		dprintk("dib8000: no bandwidth specified, set to default ");
-		state->fe[0]->dtv_property_cache.bandwidth_hz = 6000000;
-	}
-
-	for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
-		/* synchronization of the cache */
-		state->fe[index_frontend]->dtv_property_cache.delivery_system = SYS_ISDBT;
-		memcpy(&state->fe[index_frontend]->dtv_property_cache, &fe->dtv_property_cache, sizeof(struct dtv_frontend_properties));
-
-		if (state->revision != 0x8090)
-			dib8000_set_output_mode(state->fe[index_frontend],
-					OUTMODE_HIGH_Z);
-		else
-			dib8096p_set_output_mode(state->fe[index_frontend],
-					OUTMODE_HIGH_Z);
-		if (state->fe[index_frontend]->ops.tuner_ops.set_params)
-			state->fe[index_frontend]->ops.tuner_ops.set_params(state->fe[index_frontend]);
-
-		dib8000_set_tune_state(state->fe[index_frontend], CT_AGC_START);
-	}
-
-	/* start up the AGC */
-	do {
-		time = dib8000_agc_startup(state->fe[0]);
-		for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
-			time_slave = dib8000_agc_startup(state->fe[index_frontend]);
-			if (time == FE_CALLBACK_TIME_NEVER)
-				time = time_slave;
-			else if ((time_slave != FE_CALLBACK_TIME_NEVER) && (time_slave > time))
-				time = time_slave;
-		}
-		if (time != FE_CALLBACK_TIME_NEVER)
-			msleep(time / 10);
-		else
-			break;
-		exit_condition = 1;
-		for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
-			if (dib8000_get_tune_state(state->fe[index_frontend]) != CT_AGC_STOP) {
-				exit_condition = 0;
-				break;
-			}
-		}
-	} while (exit_condition == 0);
-
-	for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++)
-		dib8000_set_tune_state(state->fe[index_frontend], CT_DEMOD_START);
-
-	if ((state->fe[0]->dtv_property_cache.delivery_system != SYS_ISDBT) ||
-			(state->fe[0]->dtv_property_cache.inversion == INVERSION_AUTO) ||
-			(state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_AUTO) ||
-			(state->fe[0]->dtv_property_cache.guard_interval == GUARD_INTERVAL_AUTO) ||
-			(((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (1 << 0)) != 0) &&
-			 (state->fe[0]->dtv_property_cache.layer[0].segment_count != 0xff) &&
-			 (state->fe[0]->dtv_property_cache.layer[0].segment_count != 0) &&
-			 ((state->fe[0]->dtv_property_cache.layer[0].modulation == QAM_AUTO) ||
-			  (state->fe[0]->dtv_property_cache.layer[0].fec == FEC_AUTO))) ||
-			(((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (1 << 1)) != 0) &&
-			 (state->fe[0]->dtv_property_cache.layer[1].segment_count != 0xff) &&
-			 (state->fe[0]->dtv_property_cache.layer[1].segment_count != 0) &&
-			 ((state->fe[0]->dtv_property_cache.layer[1].modulation == QAM_AUTO) ||
-			  (state->fe[0]->dtv_property_cache.layer[1].fec == FEC_AUTO))) ||
-			(((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (1 << 2)) != 0) &&
-			 (state->fe[0]->dtv_property_cache.layer[2].segment_count != 0xff) &&
-			 (state->fe[0]->dtv_property_cache.layer[2].segment_count != 0) &&
-			 ((state->fe[0]->dtv_property_cache.layer[2].modulation == QAM_AUTO) ||
-			  (state->fe[0]->dtv_property_cache.layer[2].fec == FEC_AUTO))) ||
-			(((state->fe[0]->dtv_property_cache.layer[0].segment_count == 0) ||
-			  ((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (1 << 0)) == 0)) &&
-			 ((state->fe[0]->dtv_property_cache.layer[1].segment_count == 0) ||
-			  ((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (2 << 0)) == 0)) &&
-			 ((state->fe[0]->dtv_property_cache.layer[2].segment_count == 0) || ((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (3 << 0)) == 0)))) {
-		int i = 100;
-		u8 found = 0;
-		u8 tune_failed = 0;
-
-		for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
-			dib8000_set_bandwidth(state->fe[index_frontend], fe->dtv_property_cache.bandwidth_hz / 1000);
-			dib8000_autosearch_start(state->fe[index_frontend]);
-		}
-
-		do {
-			msleep(20);
-			nbr_pending = 0;
-			exit_condition = 0; /* 0: tune pending; 1: tune failed; 2:tune success */
-			for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
-				if (((tune_failed >> index_frontend) & 0x1) == 0) {
-					found = dib8000_autosearch_irq(state->fe[index_frontend]);
-					switch (found) {
-					case 0: /* tune pending */
-						 nbr_pending++;
-						 break;
-					case 2:
-						 dprintk("autosearch succeed on the frontend%i", index_frontend);
-						 exit_condition = 2;
-						 index_frontend_success = index_frontend;
-						 break;
-					default:
-						 dprintk("unhandled autosearch result");
-					case 1:
-						 tune_failed |= (1 << index_frontend);
-						 dprintk("autosearch failed for the frontend%i", index_frontend);
-						 break;
-					}
-				}
-			}
-
-			/* if all tune are done and no success, exit: tune failed */
-			if ((nbr_pending == 0) && (exit_condition == 0))
-				exit_condition = 1;
-		} while ((exit_condition == 0) && i--);
-
-		if (exit_condition == 1) { /* tune failed */
-			dprintk("tune failed");
-			return 0;
-		}
-
-		dprintk("tune success on frontend%i", index_frontend_success);
-
-		dib8000_get_frontend(fe);
-	}
-
-	for (index_frontend = 0, ret = 0; (ret >= 0) && (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++)
-		ret = dib8000_tune(state->fe[index_frontend]);
-
-	/* set output mode and diversity input */
-	if (state->revision != 0x8090) {
-		dib8000_set_output_mode(state->fe[0], state->cfg.output_mode);
-		for (index_frontend = 1;
-				(index_frontend < MAX_NUMBER_OF_FRONTENDS) &&
-				(state->fe[index_frontend] != NULL);
-				index_frontend++) {
-			dib8000_set_output_mode(state->fe[index_frontend],
-					OUTMODE_DIVERSITY);
-			dib8000_set_diversity_in(state->fe[index_frontend-1], 1);
-		}
-
-		/* turn off the diversity of the last chip */
-		dib8000_set_diversity_in(state->fe[index_frontend-1], 0);
-	} else {
-		dib8096p_set_output_mode(state->fe[0], state->cfg.output_mode);
-		if (state->cfg.enMpegOutput == 0) {
-			dib8096p_setDibTxMux(state, MPEG_ON_DIBTX);
-			dib8096p_setHostBusMux(state, DIBTX_ON_HOSTBUS);
-		}
-		for (index_frontend = 1;
-				(index_frontend < MAX_NUMBER_OF_FRONTENDS) &&
-				(state->fe[index_frontend] != NULL);
-				index_frontend++) {
-			dib8096p_set_output_mode(state->fe[index_frontend],
-					OUTMODE_DIVERSITY);
-			dib8096p_set_diversity_in(state->fe[index_frontend-1], 1);
-		}
-
-		/* turn off the diversity of the last chip */
-		dib8096p_set_diversity_in(state->fe[index_frontend-1], 0);
-	}
-
-	return ret;
-}
-
-static u16 dib8000_read_lock(struct dvb_frontend *fe)
-{
-	struct dib8000_state *state = fe->demodulator_priv;
-
-	if (state->revision == 0x8090)
-		return dib8000_read_word(state, 570);
-	return dib8000_read_word(state, 568);
-}
-
-static int dib8000_read_status(struct dvb_frontend *fe, fe_status_t * stat)
-{
-	struct dib8000_state *state = fe->demodulator_priv;
-	u16 lock_slave = 0, lock;
-	u8 index_frontend;
-
-	if (state->revision == 0x8090)
-		lock = dib8000_read_word(state, 570);
-	else
-		lock = dib8000_read_word(state, 568);
-
-	for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++)
-		lock_slave |= dib8000_read_lock(state->fe[index_frontend]);
-
-	*stat = 0;
-
-	if (((lock >> 13) & 1) || ((lock_slave >> 13) & 1))
-		*stat |= FE_HAS_SIGNAL;
-
-	if (((lock >> 8) & 1) || ((lock_slave >> 8) & 1)) /* Equal */
-		*stat |= FE_HAS_CARRIER;
-
-	if ((((lock >> 1) & 0xf) == 0xf) || (((lock_slave >> 1) & 0xf) == 0xf)) /* TMCC_SYNC */
-		*stat |= FE_HAS_SYNC;
-
-	if ((((lock >> 12) & 1) || ((lock_slave >> 12) & 1)) && ((lock >> 5) & 7)) /* FEC MPEG */
-		*stat |= FE_HAS_LOCK;
-
-	if (((lock >> 12) & 1) || ((lock_slave >> 12) & 1)) {
-		lock = dib8000_read_word(state, 554); /* Viterbi Layer A */
-		if (lock & 0x01)
-			*stat |= FE_HAS_VITERBI;
-
-		lock = dib8000_read_word(state, 555); /* Viterbi Layer B */
-		if (lock & 0x01)
-			*stat |= FE_HAS_VITERBI;
-
-		lock = dib8000_read_word(state, 556); /* Viterbi Layer C */
-		if (lock & 0x01)
-			*stat |= FE_HAS_VITERBI;
-	}
-
-	return 0;
-}
-
-static int dib8000_read_ber(struct dvb_frontend *fe, u32 * ber)
-{
-	struct dib8000_state *state = fe->demodulator_priv;
-
-	/* 13 segments */
-	if (state->revision == 0x8090)
-		*ber = (dib8000_read_word(state, 562) << 16) |
-			dib8000_read_word(state, 563);
-	else
-		*ber = (dib8000_read_word(state, 560) << 16) |
-			dib8000_read_word(state, 561);
-	return 0;
-}
-
-static int dib8000_read_unc_blocks(struct dvb_frontend *fe, u32 * unc)
-{
-	struct dib8000_state *state = fe->demodulator_priv;
-
-	/* packet error on 13 seg */
-	if (state->revision == 0x8090)
-		*unc = dib8000_read_word(state, 567);
-	else
-		*unc = dib8000_read_word(state, 565);
-	return 0;
-}
-
-static int dib8000_read_signal_strength(struct dvb_frontend *fe, u16 * strength)
-{
-	struct dib8000_state *state = fe->demodulator_priv;
-	u8 index_frontend;
-	u16 val;
-
-	*strength = 0;
-	for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
-		state->fe[index_frontend]->ops.read_signal_strength(state->fe[index_frontend], &val);
-		if (val > 65535 - *strength)
-			*strength = 65535;
-		else
-			*strength += val;
-	}
-
-	val = 65535 - dib8000_read_word(state, 390);
-	if (val > 65535 - *strength)
-		*strength = 65535;
-	else
-		*strength += val;
-	return 0;
-}
-
-static u32 dib8000_get_snr(struct dvb_frontend *fe)
-{
-	struct dib8000_state *state = fe->demodulator_priv;
-	u32 n, s, exp;
-	u16 val;
-
-	if (state->revision != 0x8090)
-		val = dib8000_read_word(state, 542);
-	else
-		val = dib8000_read_word(state, 544);
-	n = (val >> 6) & 0xff;
-	exp = (val & 0x3f);
-	if ((exp & 0x20) != 0)
-		exp -= 0x40;
-	n <<= exp+16;
-
-	if (state->revision != 0x8090)
-		val = dib8000_read_word(state, 543);
-	else
-		val = dib8000_read_word(state, 545);
-	s = (val >> 6) & 0xff;
-	exp = (val & 0x3f);
-	if ((exp & 0x20) != 0)
-		exp -= 0x40;
-	s <<= exp+16;
-
-	if (n > 0) {
-		u32 t = (s/n) << 16;
-		return t + ((s << 16) - n*t) / n;
-	}
-	return 0xffffffff;
-}
-
-static int dib8000_read_snr(struct dvb_frontend *fe, u16 * snr)
-{
-	struct dib8000_state *state = fe->demodulator_priv;
-	u8 index_frontend;
-	u32 snr_master;
-
-	snr_master = dib8000_get_snr(fe);
-	for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++)
-		snr_master += dib8000_get_snr(state->fe[index_frontend]);
-
-	if ((snr_master >> 16) != 0) {
-		snr_master = 10*intlog10(snr_master>>16);
-		*snr = snr_master / ((1 << 24) / 10);
-	}
-	else
-		*snr = 0;
-
-	return 0;
-}
-
-int dib8000_set_slave_frontend(struct dvb_frontend *fe, struct dvb_frontend *fe_slave)
-{
-	struct dib8000_state *state = fe->demodulator_priv;
-	u8 index_frontend = 1;
-
-	while ((index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL))
-		index_frontend++;
-	if (index_frontend < MAX_NUMBER_OF_FRONTENDS) {
-		dprintk("set slave fe %p to index %i", fe_slave, index_frontend);
-		state->fe[index_frontend] = fe_slave;
-		return 0;
-	}
-
-	dprintk("too many slave frontend");
-	return -ENOMEM;
-}
-EXPORT_SYMBOL(dib8000_set_slave_frontend);
-
-int dib8000_remove_slave_frontend(struct dvb_frontend *fe)
-{
-	struct dib8000_state *state = fe->demodulator_priv;
-	u8 index_frontend = 1;
-
-	while ((index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL))
-		index_frontend++;
-	if (index_frontend != 1) {
-		dprintk("remove slave fe %p (index %i)", state->fe[index_frontend-1], index_frontend-1);
-		state->fe[index_frontend] = NULL;
-		return 0;
-	}
-
-	dprintk("no frontend to be removed");
-	return -ENODEV;
-}
-EXPORT_SYMBOL(dib8000_remove_slave_frontend);
-
-struct dvb_frontend *dib8000_get_slave_frontend(struct dvb_frontend *fe, int slave_index)
-{
-	struct dib8000_state *state = fe->demodulator_priv;
-
-	if (slave_index >= MAX_NUMBER_OF_FRONTENDS)
-		return NULL;
-	return state->fe[slave_index];
-}
-EXPORT_SYMBOL(dib8000_get_slave_frontend);
-
-
-int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods,
-		u8 default_addr, u8 first_addr, u8 is_dib8096p)
-{
-	int k = 0, ret = 0;
-	u8 new_addr = 0;
-	struct i2c_device client = {.adap = host };
-
-	client.i2c_write_buffer = kzalloc(4 * sizeof(u8), GFP_KERNEL);
-	if (!client.i2c_write_buffer) {
-		dprintk("%s: not enough memory", __func__);
-		return -ENOMEM;
-	}
-	client.i2c_read_buffer = kzalloc(4 * sizeof(u8), GFP_KERNEL);
-	if (!client.i2c_read_buffer) {
-		dprintk("%s: not enough memory", __func__);
-		ret = -ENOMEM;
-		goto error_memory_read;
-	}
-	client.i2c_buffer_lock = kzalloc(sizeof(struct mutex), GFP_KERNEL);
-	if (!client.i2c_buffer_lock) {
-		dprintk("%s: not enough memory", __func__);
-		ret = -ENOMEM;
-		goto error_memory_lock;
-	}
-	mutex_init(client.i2c_buffer_lock);
-
-	for (k = no_of_demods - 1; k >= 0; k--) {
-		/* designated i2c address */
-		new_addr = first_addr + (k << 1);
-
-		client.addr = new_addr;
-		if (!is_dib8096p)
-			dib8000_i2c_write16(&client, 1287, 0x0003);	/* sram lead in, rdy */
-		if (dib8000_identify(&client) == 0) {
-			/* sram lead in, rdy */
-			if (!is_dib8096p)
-				dib8000_i2c_write16(&client, 1287, 0x0003);
-			client.addr = default_addr;
-			if (dib8000_identify(&client) == 0) {
-				dprintk("#%d: not identified", k);
-				ret  = -EINVAL;
-				goto error;
-			}
-		}
-
-		/* start diversity to pull_down div_str - just for i2c-enumeration */
-		dib8000_i2c_write16(&client, 1286, (1 << 10) | (4 << 6));
-
-		/* set new i2c address and force divstart */
-		dib8000_i2c_write16(&client, 1285, (new_addr << 2) | 0x2);
-		client.addr = new_addr;
-		dib8000_identify(&client);
-
-		dprintk("IC %d initialized (to i2c_address 0x%x)", k, new_addr);
-	}
-
-	for (k = 0; k < no_of_demods; k++) {
-		new_addr = first_addr | (k << 1);
-		client.addr = new_addr;
-
-		// unforce divstr
-		dib8000_i2c_write16(&client, 1285, new_addr << 2);
-
-		/* deactivate div - it was just for i2c-enumeration */
-		dib8000_i2c_write16(&client, 1286, 0);
-	}
-
-error:
-	kfree(client.i2c_buffer_lock);
-error_memory_lock:
-	kfree(client.i2c_read_buffer);
-error_memory_read:
-	kfree(client.i2c_write_buffer);
-
-	return ret;
-}
-
-EXPORT_SYMBOL(dib8000_i2c_enumeration);
-static int dib8000_fe_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings *tune)
-{
-	tune->min_delay_ms = 1000;
-	tune->step_size = 0;
-	tune->max_drift = 0;
-	return 0;
-}
-
-static void dib8000_release(struct dvb_frontend *fe)
-{
-	struct dib8000_state *st = fe->demodulator_priv;
-	u8 index_frontend;
-
-	for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (st->fe[index_frontend] != NULL); index_frontend++)
-		dvb_frontend_detach(st->fe[index_frontend]);
-
-	dibx000_exit_i2c_master(&st->i2c_master);
-	i2c_del_adapter(&st->dib8096p_tuner_adap);
-	kfree(st->fe[0]);
-	kfree(st);
-}
-
-struct i2c_adapter *dib8000_get_i2c_master(struct dvb_frontend *fe, enum dibx000_i2c_interface intf, int gating)
-{
-	struct dib8000_state *st = fe->demodulator_priv;
-	return dibx000_get_i2c_adapter(&st->i2c_master, intf, gating);
-}
-
-EXPORT_SYMBOL(dib8000_get_i2c_master);
-
-int dib8000_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
-{
-	struct dib8000_state *st = fe->demodulator_priv;
-	u16 val = dib8000_read_word(st, 299) & 0xffef;
-	val |= (onoff & 0x1) << 4;
-
-	dprintk("pid filter enabled %d", onoff);
-	return dib8000_write_word(st, 299, val);
-}
-EXPORT_SYMBOL(dib8000_pid_filter_ctrl);
-
-int dib8000_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
-{
-	struct dib8000_state *st = fe->demodulator_priv;
-	dprintk("Index %x, PID %d, OnOff %d", id, pid, onoff);
-	return dib8000_write_word(st, 305 + id, onoff ? (1 << 13) | pid : 0);
-}
-EXPORT_SYMBOL(dib8000_pid_filter);
-
-static const struct dvb_frontend_ops dib8000_ops = {
-	.delsys = { SYS_ISDBT },
-	.info = {
-		 .name = "DiBcom 8000 ISDB-T",
-		 .frequency_min = 44250000,
-		 .frequency_max = 867250000,
-		 .frequency_stepsize = 62500,
-		 .caps = FE_CAN_INVERSION_AUTO |
-		 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_FEC_AUTO |
-		 FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
-		 FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_RECOVER | FE_CAN_HIERARCHY_AUTO,
-		 },
-
-	.release = dib8000_release,
-
-	.init = dib8000_wakeup,
-	.sleep = dib8000_sleep,
-
-	.set_frontend = dib8000_set_frontend,
-	.get_tune_settings = dib8000_fe_get_tune_settings,
-	.get_frontend = dib8000_get_frontend,
-
-	.read_status = dib8000_read_status,
-	.read_ber = dib8000_read_ber,
-	.read_signal_strength = dib8000_read_signal_strength,
-	.read_snr = dib8000_read_snr,
-	.read_ucblocks = dib8000_read_unc_blocks,
-};
-
-struct dvb_frontend *dib8000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib8000_config *cfg)
-{
-	struct dvb_frontend *fe;
-	struct dib8000_state *state;
-
-	dprintk("dib8000_attach");
-
-	state = kzalloc(sizeof(struct dib8000_state), GFP_KERNEL);
-	if (state == NULL)
-		return NULL;
-	fe = kzalloc(sizeof(struct dvb_frontend), GFP_KERNEL);
-	if (fe == NULL)
-		goto error;
-
-	memcpy(&state->cfg, cfg, sizeof(struct dib8000_config));
-	state->i2c.adap = i2c_adap;
-	state->i2c.addr = i2c_addr;
-	state->i2c.i2c_write_buffer = state->i2c_write_buffer;
-	state->i2c.i2c_read_buffer = state->i2c_read_buffer;
-	mutex_init(&state->i2c_buffer_lock);
-	state->i2c.i2c_buffer_lock = &state->i2c_buffer_lock;
-	state->gpio_val = cfg->gpio_val;
-	state->gpio_dir = cfg->gpio_dir;
-
-	/* Ensure the output mode remains at the previous default if it's
-	 * not specifically set by the caller.
-	 */
-	if ((state->cfg.output_mode != OUTMODE_MPEG2_SERIAL) && (state->cfg.output_mode != OUTMODE_MPEG2_PAR_GATED_CLK))
-		state->cfg.output_mode = OUTMODE_MPEG2_FIFO;
-
-	state->fe[0] = fe;
-	fe->demodulator_priv = state;
-	memcpy(&state->fe[0]->ops, &dib8000_ops, sizeof(struct dvb_frontend_ops));
-
-	state->timf_default = cfg->pll->timf;
-
-	if (dib8000_identify(&state->i2c) == 0)
-		goto error;
-
-	dibx000_init_i2c_master(&state->i2c_master, DIB8000, state->i2c.adap, state->i2c.addr);
-
-	/* init 8096p tuner adapter */
-	strncpy(state->dib8096p_tuner_adap.name, "DiB8096P tuner interface",
-			sizeof(state->dib8096p_tuner_adap.name));
-	state->dib8096p_tuner_adap.algo = &dib8096p_tuner_xfer_algo;
-	state->dib8096p_tuner_adap.algo_data = NULL;
-	state->dib8096p_tuner_adap.dev.parent = state->i2c.adap->dev.parent;
-	i2c_set_adapdata(&state->dib8096p_tuner_adap, state);
-	i2c_add_adapter(&state->dib8096p_tuner_adap);
-
-	dib8000_reset(fe);
-
-	dib8000_write_word(state, 285, (dib8000_read_word(state, 285) & ~0x60) | (3 << 5));	/* ber_rs_len = 3 */
-
-	return fe;
-
- error:
-	kfree(state);
-	return NULL;
-}
-
-EXPORT_SYMBOL(dib8000_attach);
-
-MODULE_AUTHOR("Olivier Grenie <Olivier.Grenie@dibcom.fr, " "Patrick Boettcher <pboettcher@dibcom.fr>");
-MODULE_DESCRIPTION("Driver for the DiBcom 8000 ISDB-T demodulator");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/dib8000.h b/drivers/media/dvb/frontends/dib8000.h
deleted file mode 100644
index 39591bb..0000000
--- a/drivers/media/dvb/frontends/dib8000.h
+++ /dev/null
@@ -1,174 +0,0 @@
-#ifndef DIB8000_H
-#define DIB8000_H
-
-#include "dibx000_common.h"
-
-struct dib8000_config {
-	u8 output_mpeg2_in_188_bytes;
-	u8 hostbus_diversity;
-	u8 tuner_is_baseband;
-	int (*update_lna) (struct dvb_frontend *, u16 agc_global);
-
-	u8 agc_config_count;
-	struct dibx000_agc_config *agc;
-	struct dibx000_bandwidth_config *pll;
-
-#define DIB8000_GPIO_DEFAULT_DIRECTIONS 0xffff
-	u16 gpio_dir;
-#define DIB8000_GPIO_DEFAULT_VALUES     0x0000
-	u16 gpio_val;
-#define DIB8000_GPIO_PWM_POS0(v)        ((v & 0xf) << 12)
-#define DIB8000_GPIO_PWM_POS1(v)        ((v & 0xf) << 8 )
-#define DIB8000_GPIO_PWM_POS2(v)        ((v & 0xf) << 4 )
-#define DIB8000_GPIO_PWM_POS3(v)         (v & 0xf)
-#define DIB8000_GPIO_DEFAULT_PWM_POS    0xffff
-	u16 gpio_pwm_pos;
-	u16 pwm_freq_div;
-
-	void (*agc_control) (struct dvb_frontend *, u8 before);
-
-	u16 drives;
-	u16 diversity_delay;
-	u8 div_cfg;
-	u8 output_mode;
-	u8 refclksel;
-	u8 enMpegOutput:1;
-};
-
-#define DEFAULT_DIB8000_I2C_ADDRESS 18
-
-#if defined(CONFIG_DVB_DIB8000) || (defined(CONFIG_DVB_DIB8000_MODULE) && defined(MODULE))
-extern struct dvb_frontend *dib8000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib8000_config *cfg);
-extern struct i2c_adapter *dib8000_get_i2c_master(struct dvb_frontend *, enum dibx000_i2c_interface, int);
-
-extern int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods,
-		u8 default_addr, u8 first_addr, u8 is_dib8096p);
-
-extern int dib8000_set_gpio(struct dvb_frontend *, u8 num, u8 dir, u8 val);
-extern int dib8000_set_wbd_ref(struct dvb_frontend *, u16 value);
-extern int dib8000_pid_filter_ctrl(struct dvb_frontend *, u8 onoff);
-extern int dib8000_pid_filter(struct dvb_frontend *, u8 id, u16 pid, u8 onoff);
-extern int dib8000_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state);
-extern enum frontend_tune_state dib8000_get_tune_state(struct dvb_frontend *fe);
-extern void dib8000_pwm_agc_reset(struct dvb_frontend *fe);
-extern s32 dib8000_get_adc_power(struct dvb_frontend *fe, u8 mode);
-extern struct i2c_adapter *dib8096p_get_i2c_tuner(struct dvb_frontend *fe);
-extern int dib8096p_tuner_sleep(struct dvb_frontend *fe, int onoff);
-extern int dib8090p_get_dc_power(struct dvb_frontend *fe, u8 IQ);
-extern u32 dib8000_ctrl_timf(struct dvb_frontend *fe,
-		uint8_t op, uint32_t timf);
-extern int dib8000_update_pll(struct dvb_frontend *fe,
-		struct dibx000_bandwidth_config *pll);
-extern int dib8000_set_slave_frontend(struct dvb_frontend *fe, struct dvb_frontend *fe_slave);
-extern int dib8000_remove_slave_frontend(struct dvb_frontend *fe);
-extern struct dvb_frontend *dib8000_get_slave_frontend(struct dvb_frontend *fe, int slave_index);
-#else
-static inline struct dvb_frontend *dib8000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib8000_config *cfg)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-
-static inline struct i2c_adapter *dib8000_get_i2c_master(struct dvb_frontend *fe, enum dibx000_i2c_interface i, int x)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-
-static inline int dib8000_i2c_enumeration(struct i2c_adapter *host,
-		int no_of_demods, u8 default_addr, u8 first_addr,
-		u8 is_dib8096p)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return -ENODEV;
-}
-
-static inline int dib8000_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 dib8000_set_wbd_ref(struct dvb_frontend *fe, u16 value)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return -ENODEV;
-}
-
-static inline int dib8000_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return -ENODEV;
-}
-
-static inline int dib8000_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return -ENODEV;
-}
-static inline int dib8000_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return -ENODEV;
-}
-static inline enum frontend_tune_state dib8000_get_tune_state(struct dvb_frontend *fe)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return CT_SHUTDOWN;
-}
-static inline void dib8000_pwm_agc_reset(struct dvb_frontend *fe)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-}
-static inline struct i2c_adapter *dib8096p_get_i2c_tuner(struct dvb_frontend *fe)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-static inline int dib8096p_tuner_sleep(struct dvb_frontend *fe, int onoff)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return 0;
-}
-static inline s32 dib8000_get_adc_power(struct dvb_frontend *fe, u8 mode)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return 0;
-}
-static inline int dib8090p_get_dc_power(struct dvb_frontend *fe, u8 IQ)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return 0;
-}
-static inline u32 dib8000_ctrl_timf(struct dvb_frontend *fe,
-		uint8_t op, uint32_t timf)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return 0;
-}
-static inline int dib8000_update_pll(struct dvb_frontend *fe,
-		struct dibx000_bandwidth_config *pll)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return -ENODEV;
-}
-static inline int dib8000_set_slave_frontend(struct dvb_frontend *fe, struct dvb_frontend *fe_slave)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return -ENODEV;
-}
-
-int dib8000_remove_slave_frontend(struct dvb_frontend *fe)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return -ENODEV;
-}
-
-static inline struct dvb_frontend *dib8000_get_slave_frontend(struct dvb_frontend *fe, int slave_index)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif
-
-#endif
diff --git a/drivers/media/dvb/frontends/dib9000.c b/drivers/media/dvb/frontends/dib9000.c
deleted file mode 100644
index 6201c59..0000000
--- a/drivers/media/dvb/frontends/dib9000.c
+++ /dev/null
@@ -1,2590 +0,0 @@
-/*
- * Linux-DVB Driver for DiBcom's DiB9000 and demodulator-family.
- *
- * Copyright (C) 2005-10 DiBcom (http://www.dibcom.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, version 2.
- */
-#include <linux/kernel.h>
-#include <linux/i2c.h>
-#include <linux/mutex.h>
-
-#include "dvb_math.h"
-#include "dvb_frontend.h"
-
-#include "dib9000.h"
-#include "dibx000_common.h"
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
-
-#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB9000: "); printk(args); printk("\n"); } } while (0)
-#define MAX_NUMBER_OF_FRONTENDS 6
-
-struct i2c_device {
-	struct i2c_adapter *i2c_adap;
-	u8 i2c_addr;
-	u8 *i2c_read_buffer;
-	u8 *i2c_write_buffer;
-};
-
-struct dib9000_pid_ctrl {
-#define DIB9000_PID_FILTER_CTRL 0
-#define DIB9000_PID_FILTER      1
-	u8 cmd;
-	u8 id;
-	u16 pid;
-	u8 onoff;
-};
-
-struct dib9000_state {
-	struct i2c_device i2c;
-
-	struct dibx000_i2c_master i2c_master;
-	struct i2c_adapter tuner_adap;
-	struct i2c_adapter component_bus;
-
-	u16 revision;
-	u8 reg_offs;
-
-	enum frontend_tune_state tune_state;
-	u32 status;
-	struct dvb_frontend_parametersContext channel_status;
-
-	u8 fe_id;
-
-#define DIB9000_GPIO_DEFAULT_DIRECTIONS 0xffff
-	u16 gpio_dir;
-#define DIB9000_GPIO_DEFAULT_VALUES     0x0000
-	u16 gpio_val;
-#define DIB9000_GPIO_DEFAULT_PWM_POS    0xffff
-	u16 gpio_pwm_pos;
-
-	union {			/* common for all chips */
-		struct {
-			u8 mobile_mode:1;
-		} host;
-
-		struct {
-			struct dib9000_fe_memory_map {
-				u16 addr;
-				u16 size;
-			} fe_mm[18];
-			u8 memcmd;
-
-			struct mutex mbx_if_lock;	/* to protect read/write operations */
-			struct mutex mbx_lock;	/* to protect the whole mailbox handling */
-
-			struct mutex mem_lock;	/* to protect the memory accesses */
-			struct mutex mem_mbx_lock;	/* to protect the memory-based mailbox */
-
-#define MBX_MAX_WORDS (256 - 200 - 2)
-#define DIB9000_MSG_CACHE_SIZE 2
-			u16 message_cache[DIB9000_MSG_CACHE_SIZE][MBX_MAX_WORDS];
-			u8 fw_is_running;
-		} risc;
-	} platform;
-
-	union {			/* common for all platforms */
-		struct {
-			struct dib9000_config cfg;
-		} d9;
-	} chip;
-
-	struct dvb_frontend *fe[MAX_NUMBER_OF_FRONTENDS];
-	u16 component_bus_speed;
-
-	/* for the I2C transfer */
-	struct i2c_msg msg[2];
-	u8 i2c_write_buffer[255];
-	u8 i2c_read_buffer[255];
-	struct mutex demod_lock;
-	u8 get_frontend_internal;
-	struct dib9000_pid_ctrl pid_ctrl[10];
-	s8 pid_ctrl_index; /* -1: empty list; -2: do not use the list */
-};
-
-static const u32 fe_info[44] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0
-};
-
-enum dib9000_power_mode {
-	DIB9000_POWER_ALL = 0,
-
-	DIB9000_POWER_NO,
-	DIB9000_POWER_INTERF_ANALOG_AGC,
-	DIB9000_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD,
-	DIB9000_POWER_COR4_CRY_ESRAM_MOUT_NUD,
-	DIB9000_POWER_INTERFACE_ONLY,
-};
-
-enum dib9000_out_messages {
-	OUT_MSG_HBM_ACK,
-	OUT_MSG_HOST_BUF_FAIL,
-	OUT_MSG_REQ_VERSION,
-	OUT_MSG_BRIDGE_I2C_W,
-	OUT_MSG_BRIDGE_I2C_R,
-	OUT_MSG_BRIDGE_APB_W,
-	OUT_MSG_BRIDGE_APB_R,
-	OUT_MSG_SCAN_CHANNEL,
-	OUT_MSG_MONIT_DEMOD,
-	OUT_MSG_CONF_GPIO,
-	OUT_MSG_DEBUG_HELP,
-	OUT_MSG_SUBBAND_SEL,
-	OUT_MSG_ENABLE_TIME_SLICE,
-	OUT_MSG_FE_FW_DL,
-	OUT_MSG_FE_CHANNEL_SEARCH,
-	OUT_MSG_FE_CHANNEL_TUNE,
-	OUT_MSG_FE_SLEEP,
-	OUT_MSG_FE_SYNC,
-	OUT_MSG_CTL_MONIT,
-
-	OUT_MSG_CONF_SVC,
-	OUT_MSG_SET_HBM,
-	OUT_MSG_INIT_DEMOD,
-	OUT_MSG_ENABLE_DIVERSITY,
-	OUT_MSG_SET_OUTPUT_MODE,
-	OUT_MSG_SET_PRIORITARY_CHANNEL,
-	OUT_MSG_ACK_FRG,
-	OUT_MSG_INIT_PMU,
-};
-
-enum dib9000_in_messages {
-	IN_MSG_DATA,
-	IN_MSG_FRAME_INFO,
-	IN_MSG_CTL_MONIT,
-	IN_MSG_ACK_FREE_ITEM,
-	IN_MSG_DEBUG_BUF,
-	IN_MSG_MPE_MONITOR,
-	IN_MSG_RAWTS_MONITOR,
-	IN_MSG_END_BRIDGE_I2C_RW,
-	IN_MSG_END_BRIDGE_APB_RW,
-	IN_MSG_VERSION,
-	IN_MSG_END_OF_SCAN,
-	IN_MSG_MONIT_DEMOD,
-	IN_MSG_ERROR,
-	IN_MSG_FE_FW_DL_DONE,
-	IN_MSG_EVENT,
-	IN_MSG_ACK_CHANGE_SVC,
-	IN_MSG_HBM_PROF,
-};
-
-/* memory_access requests */
-#define FE_MM_W_CHANNEL                   0
-#define FE_MM_W_FE_INFO                   1
-#define FE_MM_RW_SYNC                     2
-
-#define FE_SYNC_CHANNEL          1
-#define FE_SYNC_W_GENERIC_MONIT	 2
-#define FE_SYNC_COMPONENT_ACCESS 3
-
-#define FE_MM_R_CHANNEL_SEARCH_STATE      3
-#define FE_MM_R_CHANNEL_UNION_CONTEXT     4
-#define FE_MM_R_FE_INFO                   5
-#define FE_MM_R_FE_MONITOR                6
-
-#define FE_MM_W_CHANNEL_HEAD              7
-#define FE_MM_W_CHANNEL_UNION             8
-#define FE_MM_W_CHANNEL_CONTEXT           9
-#define FE_MM_R_CHANNEL_UNION            10
-#define FE_MM_R_CHANNEL_CONTEXT          11
-#define FE_MM_R_CHANNEL_TUNE_STATE       12
-
-#define FE_MM_R_GENERIC_MONITORING_SIZE	 13
-#define FE_MM_W_GENERIC_MONITORING	     14
-#define FE_MM_R_GENERIC_MONITORING	     15
-
-#define FE_MM_W_COMPONENT_ACCESS         16
-#define FE_MM_RW_COMPONENT_ACCESS_BUFFER 17
-static int dib9000_risc_apb_access_read(struct dib9000_state *state, u32 address, u16 attribute, const u8 * tx, u32 txlen, u8 * b, u32 len);
-static int dib9000_risc_apb_access_write(struct dib9000_state *state, u32 address, u16 attribute, const u8 * b, u32 len);
-
-static u16 to_fw_output_mode(u16 mode)
-{
-	switch (mode) {
-	case OUTMODE_HIGH_Z:
-		return 0;
-	case OUTMODE_MPEG2_PAR_GATED_CLK:
-		return 4;
-	case OUTMODE_MPEG2_PAR_CONT_CLK:
-		return 8;
-	case OUTMODE_MPEG2_SERIAL:
-		return 16;
-	case OUTMODE_DIVERSITY:
-		return 128;
-	case OUTMODE_MPEG2_FIFO:
-		return 2;
-	case OUTMODE_ANALOG_ADC:
-		return 1;
-	default:
-		return 0;
-	}
-}
-
-static u16 dib9000_read16_attr(struct dib9000_state *state, u16 reg, u8 * b, u32 len, u16 attribute)
-{
-	u32 chunk_size = 126;
-	u32 l;
-	int ret;
-
-	if (state->platform.risc.fw_is_running && (reg < 1024))
-		return dib9000_risc_apb_access_read(state, reg, attribute, NULL, 0, b, len);
-
-	memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
-	state->msg[0].addr = state->i2c.i2c_addr >> 1;
-	state->msg[0].flags = 0;
-	state->msg[0].buf = state->i2c_write_buffer;
-	state->msg[0].len = 2;
-	state->msg[1].addr = state->i2c.i2c_addr >> 1;
-	state->msg[1].flags = I2C_M_RD;
-	state->msg[1].buf = b;
-	state->msg[1].len = len;
-
-	state->i2c_write_buffer[0] = reg >> 8;
-	state->i2c_write_buffer[1] = reg & 0xff;
-
-	if (attribute & DATA_BUS_ACCESS_MODE_8BIT)
-		state->i2c_write_buffer[0] |= (1 << 5);
-	if (attribute & DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT)
-		state->i2c_write_buffer[0] |= (1 << 4);
-
-	do {
-		l = len < chunk_size ? len : chunk_size;
-		state->msg[1].len = l;
-		state->msg[1].buf = b;
-		ret = i2c_transfer(state->i2c.i2c_adap, state->msg, 2) != 2 ? -EREMOTEIO : 0;
-		if (ret != 0) {
-			dprintk("i2c read error on %d", reg);
-			return -EREMOTEIO;
-		}
-
-		b += l;
-		len -= l;
-
-		if (!(attribute & DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT))
-			reg += l / 2;
-	} while ((ret == 0) && len);
-
-	return 0;
-}
-
-static u16 dib9000_i2c_read16(struct i2c_device *i2c, u16 reg)
-{
-	struct i2c_msg msg[2] = {
-		{.addr = i2c->i2c_addr >> 1, .flags = 0,
-			.buf = i2c->i2c_write_buffer, .len = 2},
-		{.addr = i2c->i2c_addr >> 1, .flags = I2C_M_RD,
-			.buf = i2c->i2c_read_buffer, .len = 2},
-	};
-
-	i2c->i2c_write_buffer[0] = reg >> 8;
-	i2c->i2c_write_buffer[1] = reg & 0xff;
-
-	if (i2c_transfer(i2c->i2c_adap, msg, 2) != 2) {
-		dprintk("read register %x error", reg);
-		return 0;
-	}
-
-	return (i2c->i2c_read_buffer[0] << 8) | i2c->i2c_read_buffer[1];
-}
-
-static inline u16 dib9000_read_word(struct dib9000_state *state, u16 reg)
-{
-	if (dib9000_read16_attr(state, reg, state->i2c_read_buffer, 2, 0) != 0)
-		return 0;
-	return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
-}
-
-static inline u16 dib9000_read_word_attr(struct dib9000_state *state, u16 reg, u16 attribute)
-{
-	if (dib9000_read16_attr(state, reg, state->i2c_read_buffer, 2,
-				attribute) != 0)
-		return 0;
-	return (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
-}
-
-#define dib9000_read16_noinc_attr(state, reg, b, len, attribute) dib9000_read16_attr(state, reg, b, len, (attribute) | DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT)
-
-static u16 dib9000_write16_attr(struct dib9000_state *state, u16 reg, const u8 * buf, u32 len, u16 attribute)
-{
-	u32 chunk_size = 126;
-	u32 l;
-	int ret;
-
-	if (state->platform.risc.fw_is_running && (reg < 1024)) {
-		if (dib9000_risc_apb_access_write
-		    (state, reg, DATA_BUS_ACCESS_MODE_16BIT | DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT | attribute, buf, len) != 0)
-			return -EINVAL;
-		return 0;
-	}
-
-	memset(&state->msg[0], 0, sizeof(struct i2c_msg));
-	state->msg[0].addr = state->i2c.i2c_addr >> 1;
-	state->msg[0].flags = 0;
-	state->msg[0].buf = state->i2c_write_buffer;
-	state->msg[0].len = len + 2;
-
-	state->i2c_write_buffer[0] = (reg >> 8) & 0xff;
-	state->i2c_write_buffer[1] = (reg) & 0xff;
-
-	if (attribute & DATA_BUS_ACCESS_MODE_8BIT)
-		state->i2c_write_buffer[0] |= (1 << 5);
-	if (attribute & DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT)
-		state->i2c_write_buffer[0] |= (1 << 4);
-
-	do {
-		l = len < chunk_size ? len : chunk_size;
-		state->msg[0].len = l + 2;
-		memcpy(&state->i2c_write_buffer[2], buf, l);
-
-		ret = i2c_transfer(state->i2c.i2c_adap, state->msg, 1) != 1 ? -EREMOTEIO : 0;
-
-		buf += l;
-		len -= l;
-
-		if (!(attribute & DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT))
-			reg += l / 2;
-	} while ((ret == 0) && len);
-
-	return ret;
-}
-
-static int dib9000_i2c_write16(struct i2c_device *i2c, u16 reg, u16 val)
-{
-	struct i2c_msg msg = {
-		.addr = i2c->i2c_addr >> 1, .flags = 0,
-		.buf = i2c->i2c_write_buffer, .len = 4
-	};
-
-	i2c->i2c_write_buffer[0] = (reg >> 8) & 0xff;
-	i2c->i2c_write_buffer[1] = reg & 0xff;
-	i2c->i2c_write_buffer[2] = (val >> 8) & 0xff;
-	i2c->i2c_write_buffer[3] = val & 0xff;
-
-	return i2c_transfer(i2c->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
-}
-
-static inline int dib9000_write_word(struct dib9000_state *state, u16 reg, u16 val)
-{
-	u8 b[2] = { val >> 8, val & 0xff };
-	return dib9000_write16_attr(state, reg, b, 2, 0);
-}
-
-static inline int dib9000_write_word_attr(struct dib9000_state *state, u16 reg, u16 val, u16 attribute)
-{
-	u8 b[2] = { val >> 8, val & 0xff };
-	return dib9000_write16_attr(state, reg, b, 2, attribute);
-}
-
-#define dib9000_write(state, reg, buf, len) dib9000_write16_attr(state, reg, buf, len, 0)
-#define dib9000_write16_noinc(state, reg, buf, len) dib9000_write16_attr(state, reg, buf, len, DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT)
-#define dib9000_write16_noinc_attr(state, reg, buf, len, attribute) dib9000_write16_attr(state, reg, buf, len, DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT | (attribute))
-
-#define dib9000_mbx_send(state, id, data, len) dib9000_mbx_send_attr(state, id, data, len, 0)
-#define dib9000_mbx_get_message(state, id, msg, len) dib9000_mbx_get_message_attr(state, id, msg, len, 0)
-
-#define MAC_IRQ      (1 << 1)
-#define IRQ_POL_MSK  (1 << 4)
-
-#define dib9000_risc_mem_read_chunks(state, b, len) dib9000_read16_attr(state, 1063, b, len, DATA_BUS_ACCESS_MODE_8BIT | DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT)
-#define dib9000_risc_mem_write_chunks(state, buf, len) dib9000_write16_attr(state, 1063, buf, len, DATA_BUS_ACCESS_MODE_8BIT | DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT)
-
-static void dib9000_risc_mem_setup_cmd(struct dib9000_state *state, u32 addr, u32 len, u8 reading)
-{
-	u8 b[14] = { 0 };
-
-/*      dprintk("%d memcmd: %d %d %d\n", state->fe_id, addr, addr+len, len); */
-/*      b[0] = 0 << 7; */
-	b[1] = 1;
-
-/*      b[2] = 0; */
-/*      b[3] = 0; */
-	b[4] = (u8) (addr >> 8);
-	b[5] = (u8) (addr & 0xff);
-
-/*      b[10] = 0; */
-/*      b[11] = 0; */
-	b[12] = (u8) (addr >> 8);
-	b[13] = (u8) (addr & 0xff);
-
-	addr += len;
-/*      b[6] = 0; */
-/*      b[7] = 0; */
-	b[8] = (u8) (addr >> 8);
-	b[9] = (u8) (addr & 0xff);
-
-	dib9000_write(state, 1056, b, 14);
-	if (reading)
-		dib9000_write_word(state, 1056, (1 << 15) | 1);
-	state->platform.risc.memcmd = -1;	/* if it was called directly reset it - to force a future setup-call to set it */
-}
-
-static void dib9000_risc_mem_setup(struct dib9000_state *state, u8 cmd)
-{
-	struct dib9000_fe_memory_map *m = &state->platform.risc.fe_mm[cmd & 0x7f];
-	/* decide whether we need to "refresh" the memory controller */
-	if (state->platform.risc.memcmd == cmd &&	/* same command */
-	    !(cmd & 0x80 && m->size < 67))	/* and we do not want to read something with less than 67 bytes looping - working around a bug in the memory controller */
-		return;
-	dib9000_risc_mem_setup_cmd(state, m->addr, m->size, cmd & 0x80);
-	state->platform.risc.memcmd = cmd;
-}
-
-static int dib9000_risc_mem_read(struct dib9000_state *state, u8 cmd, u8 * b, u16 len)
-{
-	if (!state->platform.risc.fw_is_running)
-		return -EIO;
-
-	if (mutex_lock_interruptible(&state->platform.risc.mem_lock) < 0) {
-		dprintk("could not get the lock");
-		return -EINTR;
-	}
-	dib9000_risc_mem_setup(state, cmd | 0x80);
-	dib9000_risc_mem_read_chunks(state, b, len);
-	mutex_unlock(&state->platform.risc.mem_lock);
-	return 0;
-}
-
-static int dib9000_risc_mem_write(struct dib9000_state *state, u8 cmd, const u8 * b)
-{
-	struct dib9000_fe_memory_map *m = &state->platform.risc.fe_mm[cmd];
-	if (!state->platform.risc.fw_is_running)
-		return -EIO;
-
-	if (mutex_lock_interruptible(&state->platform.risc.mem_lock) < 0) {
-		dprintk("could not get the lock");
-		return -EINTR;
-	}
-	dib9000_risc_mem_setup(state, cmd);
-	dib9000_risc_mem_write_chunks(state, b, m->size);
-	mutex_unlock(&state->platform.risc.mem_lock);
-	return 0;
-}
-
-static int dib9000_firmware_download(struct dib9000_state *state, u8 risc_id, u16 key, const u8 * code, u32 len)
-{
-	u16 offs;
-
-	if (risc_id == 1)
-		offs = 16;
-	else
-		offs = 0;
-
-	/* config crtl reg */
-	dib9000_write_word(state, 1024 + offs, 0x000f);
-	dib9000_write_word(state, 1025 + offs, 0);
-	dib9000_write_word(state, 1031 + offs, key);
-
-	dprintk("going to download %dB of microcode", len);
-	if (dib9000_write16_noinc(state, 1026 + offs, (u8 *) code, (u16) len) != 0) {
-		dprintk("error while downloading microcode for RISC %c", 'A' + risc_id);
-		return -EIO;
-	}
-
-	dprintk("Microcode for RISC %c loaded", 'A' + risc_id);
-
-	return 0;
-}
-
-static int dib9000_mbx_host_init(struct dib9000_state *state, u8 risc_id)
-{
-	u16 mbox_offs;
-	u16 reset_reg;
-	u16 tries = 1000;
-
-	if (risc_id == 1)
-		mbox_offs = 16;
-	else
-		mbox_offs = 0;
-
-	/* Reset mailbox  */
-	dib9000_write_word(state, 1027 + mbox_offs, 0x8000);
-
-	/* Read reset status */
-	do {
-		reset_reg = dib9000_read_word(state, 1027 + mbox_offs);
-		msleep(100);
-	} while ((reset_reg & 0x8000) && --tries);
-
-	if (reset_reg & 0x8000) {
-		dprintk("MBX: init ERROR, no response from RISC %c", 'A' + risc_id);
-		return -EIO;
-	}
-	dprintk("MBX: initialized");
-	return 0;
-}
-
-#define MAX_MAILBOX_TRY 100
-static int dib9000_mbx_send_attr(struct dib9000_state *state, u8 id, u16 * data, u8 len, u16 attr)
-{
-	u8 *d, b[2];
-	u16 tmp;
-	u16 size;
-	u32 i;
-	int ret = 0;
-
-	if (!state->platform.risc.fw_is_running)
-		return -EINVAL;
-
-	if (mutex_lock_interruptible(&state->platform.risc.mbx_if_lock) < 0) {
-		dprintk("could not get the lock");
-		return -EINTR;
-	}
-	tmp = MAX_MAILBOX_TRY;
-	do {
-		size = dib9000_read_word_attr(state, 1043, attr) & 0xff;
-		if ((size + len + 1) > MBX_MAX_WORDS && --tmp) {
-			dprintk("MBX: RISC mbx full, retrying");
-			msleep(100);
-		} else
-			break;
-	} while (1);
-
-	/*dprintk( "MBX: size: %d", size); */
-
-	if (tmp == 0) {
-		ret = -EINVAL;
-		goto out;
-	}
-#ifdef DUMP_MSG
-	dprintk("--> %02x %d ", id, len + 1);
-	for (i = 0; i < len; i++)
-		dprintk("%04x ", data[i]);
-	dprintk("\n");
-#endif
-
-	/* byte-order conversion - works on big (where it is not necessary) or little endian */
-	d = (u8 *) data;
-	for (i = 0; i < len; i++) {
-		tmp = data[i];
-		*d++ = tmp >> 8;
-		*d++ = tmp & 0xff;
-	}
-
-	/* write msg */
-	b[0] = id;
-	b[1] = len + 1;
-	if (dib9000_write16_noinc_attr(state, 1045, b, 2, attr) != 0 || dib9000_write16_noinc_attr(state, 1045, (u8 *) data, len * 2, attr) != 0) {
-		ret = -EIO;
-		goto out;
-	}
-
-	/* update register nb_mes_in_RX */
-	ret = (u8) dib9000_write_word_attr(state, 1043, 1 << 14, attr);
-
-out:
-	mutex_unlock(&state->platform.risc.mbx_if_lock);
-
-	return ret;
-}
-
-static u8 dib9000_mbx_read(struct dib9000_state *state, u16 * data, u8 risc_id, u16 attr)
-{
-#ifdef DUMP_MSG
-	u16 *d = data;
-#endif
-
-	u16 tmp, i;
-	u8 size;
-	u8 mc_base;
-
-	if (!state->platform.risc.fw_is_running)
-		return 0;
-
-	if (mutex_lock_interruptible(&state->platform.risc.mbx_if_lock) < 0) {
-		dprintk("could not get the lock");
-		return 0;
-	}
-	if (risc_id == 1)
-		mc_base = 16;
-	else
-		mc_base = 0;
-
-	/* Length and type in the first word */
-	*data = dib9000_read_word_attr(state, 1029 + mc_base, attr);
-
-	size = *data & 0xff;
-	if (size <= MBX_MAX_WORDS) {
-		data++;
-		size--;		/* Initial word already read */
-
-		dib9000_read16_noinc_attr(state, 1029 + mc_base, (u8 *) data, size * 2, attr);
-
-		/* to word conversion */
-		for (i = 0; i < size; i++) {
-			tmp = *data;
-			*data = (tmp >> 8) | (tmp << 8);
-			data++;
-		}
-
-#ifdef DUMP_MSG
-		dprintk("<-- ");
-		for (i = 0; i < size + 1; i++)
-			dprintk("%04x ", d[i]);
-		dprintk("\n");
-#endif
-	} else {
-		dprintk("MBX: message is too big for message cache (%d), flushing message", size);
-		size--;		/* Initial word already read */
-		while (size--)
-			dib9000_read16_noinc_attr(state, 1029 + mc_base, (u8 *) data, 2, attr);
-	}
-	/* Update register nb_mes_in_TX */
-	dib9000_write_word_attr(state, 1028 + mc_base, 1 << 14, attr);
-
-	mutex_unlock(&state->platform.risc.mbx_if_lock);
-
-	return size + 1;
-}
-
-static int dib9000_risc_debug_buf(struct dib9000_state *state, u16 * data, u8 size)
-{
-	u32 ts = data[1] << 16 | data[0];
-	char *b = (char *)&data[2];
-
-	b[2 * (size - 2) - 1] = '\0';	/* Bullet proof the buffer */
-	if (*b == '~') {
-		b++;
-		dprintk(b);
-	} else
-		dprintk("RISC%d: %d.%04d %s", state->fe_id, ts / 10000, ts % 10000, *b ? b : "<emtpy>");
-	return 1;
-}
-
-static int dib9000_mbx_fetch_to_cache(struct dib9000_state *state, u16 attr)
-{
-	int i;
-	u8 size;
-	u16 *block;
-	/* find a free slot */
-	for (i = 0; i < DIB9000_MSG_CACHE_SIZE; i++) {
-		block = state->platform.risc.message_cache[i];
-		if (*block == 0) {
-			size = dib9000_mbx_read(state, block, 1, attr);
-
-/*                      dprintk( "MBX: fetched %04x message to cache", *block); */
-
-			switch (*block >> 8) {
-			case IN_MSG_DEBUG_BUF:
-				dib9000_risc_debug_buf(state, block + 1, size);	/* debug-messages are going to be printed right away */
-				*block = 0;	/* free the block */
-				break;
-#if 0
-			case IN_MSG_DATA:	/* FE-TRACE */
-				dib9000_risc_data_process(state, block + 1, size);
-				*block = 0;
-				break;
-#endif
-			default:
-				break;
-			}
-
-			return 1;
-		}
-	}
-	dprintk("MBX: no free cache-slot found for new message...");
-	return -1;
-}
-
-static u8 dib9000_mbx_count(struct dib9000_state *state, u8 risc_id, u16 attr)
-{
-	if (risc_id == 0)
-		return (u8) (dib9000_read_word_attr(state, 1028, attr) >> 10) & 0x1f;	/* 5 bit field */
-	else
-		return (u8) (dib9000_read_word_attr(state, 1044, attr) >> 8) & 0x7f;	/* 7 bit field */
-}
-
-static int dib9000_mbx_process(struct dib9000_state *state, u16 attr)
-{
-	int ret = 0;
-
-	if (!state->platform.risc.fw_is_running)
-		return -1;
-
-	if (mutex_lock_interruptible(&state->platform.risc.mbx_lock) < 0) {
-		dprintk("could not get the lock");
-		return -1;
-	}
-
-	if (dib9000_mbx_count(state, 1, attr))	/* 1=RiscB */
-		ret = dib9000_mbx_fetch_to_cache(state, attr);
-
-	dib9000_read_word_attr(state, 1229, attr);	/* Clear the IRQ */
-/*      if (tmp) */
-/*              dprintk( "cleared IRQ: %x", tmp); */
-	mutex_unlock(&state->platform.risc.mbx_lock);
-
-	return ret;
-}
-
-static int dib9000_mbx_get_message_attr(struct dib9000_state *state, u16 id, u16 * msg, u8 * size, u16 attr)
-{
-	u8 i;
-	u16 *block;
-	u16 timeout = 30;
-
-	*msg = 0;
-	do {
-		/* dib9000_mbx_get_from_cache(); */
-		for (i = 0; i < DIB9000_MSG_CACHE_SIZE; i++) {
-			block = state->platform.risc.message_cache[i];
-			if ((*block >> 8) == id) {
-				*size = (*block & 0xff) - 1;
-				memcpy(msg, block + 1, (*size) * 2);
-				*block = 0;	/* free the block */
-				i = 0;	/* signal that we found a message */
-				break;
-			}
-		}
-
-		if (i == 0)
-			break;
-
-		if (dib9000_mbx_process(state, attr) == -1)	/* try to fetch one message - if any */
-			return -1;
-
-	} while (--timeout);
-
-	if (timeout == 0) {
-		dprintk("waiting for message %d timed out", id);
-		return -1;
-	}
-
-	return i == 0;
-}
-
-static int dib9000_risc_check_version(struct dib9000_state *state)
-{
-	u8 r[4];
-	u8 size;
-	u16 fw_version = 0;
-
-	if (dib9000_mbx_send(state, OUT_MSG_REQ_VERSION, &fw_version, 1) != 0)
-		return -EIO;
-
-	if (dib9000_mbx_get_message(state, IN_MSG_VERSION, (u16 *) r, &size) < 0)
-		return -EIO;
-
-	fw_version = (r[0] << 8) | r[1];
-	dprintk("RISC: ver: %d.%02d (IC: %d)", fw_version >> 10, fw_version & 0x3ff, (r[2] << 8) | r[3]);
-
-	if ((fw_version >> 10) != 7)
-		return -EINVAL;
-
-	switch (fw_version & 0x3ff) {
-	case 11:
-	case 12:
-	case 14:
-	case 15:
-	case 16:
-	case 17:
-		break;
-	default:
-		dprintk("RISC: invalid firmware version");
-		return -EINVAL;
-	}
-
-	dprintk("RISC: valid firmware version");
-	return 0;
-}
-
-static int dib9000_fw_boot(struct dib9000_state *state, const u8 * codeA, u32 lenA, const u8 * codeB, u32 lenB)
-{
-	/* Reconfig pool mac ram */
-	dib9000_write_word(state, 1225, 0x02);	/* A: 8k C, 4 k D - B: 32k C 6 k D - IRAM 96k */
-	dib9000_write_word(state, 1226, 0x05);
-
-	/* Toggles IP crypto to Host APB interface. */
-	dib9000_write_word(state, 1542, 1);
-
-	/* Set jump and no jump in the dma box */
-	dib9000_write_word(state, 1074, 0);
-	dib9000_write_word(state, 1075, 0);
-
-	/* Set MAC as APB Master. */
-	dib9000_write_word(state, 1237, 0);
-
-	/* Reset the RISCs */
-	if (codeA != NULL)
-		dib9000_write_word(state, 1024, 2);
-	else
-		dib9000_write_word(state, 1024, 15);
-	if (codeB != NULL)
-		dib9000_write_word(state, 1040, 2);
-
-	if (codeA != NULL)
-		dib9000_firmware_download(state, 0, 0x1234, codeA, lenA);
-	if (codeB != NULL)
-		dib9000_firmware_download(state, 1, 0x1234, codeB, lenB);
-
-	/* Run the RISCs */
-	if (codeA != NULL)
-		dib9000_write_word(state, 1024, 0);
-	if (codeB != NULL)
-		dib9000_write_word(state, 1040, 0);
-
-	if (codeA != NULL)
-		if (dib9000_mbx_host_init(state, 0) != 0)
-			return -EIO;
-	if (codeB != NULL)
-		if (dib9000_mbx_host_init(state, 1) != 0)
-			return -EIO;
-
-	msleep(100);
-	state->platform.risc.fw_is_running = 1;
-
-	if (dib9000_risc_check_version(state) != 0)
-		return -EINVAL;
-
-	state->platform.risc.memcmd = 0xff;
-	return 0;
-}
-
-static u16 dib9000_identify(struct i2c_device *client)
-{
-	u16 value;
-
-	value = dib9000_i2c_read16(client, 896);
-	if (value != 0x01b3) {
-		dprintk("wrong Vendor ID (0x%x)", value);
-		return 0;
-	}
-
-	value = dib9000_i2c_read16(client, 897);
-	if (value != 0x4000 && value != 0x4001 && value != 0x4002 && value != 0x4003 && value != 0x4004 && value != 0x4005) {
-		dprintk("wrong Device ID (0x%x)", value);
-		return 0;
-	}
-
-	/* protect this driver to be used with 7000PC */
-	if (value == 0x4000 && dib9000_i2c_read16(client, 769) == 0x4000) {
-		dprintk("this driver does not work with DiB7000PC");
-		return 0;
-	}
-
-	switch (value) {
-	case 0x4000:
-		dprintk("found DiB7000MA/PA/MB/PB");
-		break;
-	case 0x4001:
-		dprintk("found DiB7000HC");
-		break;
-	case 0x4002:
-		dprintk("found DiB7000MC");
-		break;
-	case 0x4003:
-		dprintk("found DiB9000A");
-		break;
-	case 0x4004:
-		dprintk("found DiB9000H");
-		break;
-	case 0x4005:
-		dprintk("found DiB9000M");
-		break;
-	}
-
-	return value;
-}
-
-static void dib9000_set_power_mode(struct dib9000_state *state, enum dib9000_power_mode mode)
-{
-	/* by default everything is going to be powered off */
-	u16 reg_903 = 0x3fff, reg_904 = 0xffff, reg_905 = 0xffff, reg_906;
-	u8 offset;
-
-	if (state->revision == 0x4003 || state->revision == 0x4004 || state->revision == 0x4005)
-		offset = 1;
-	else
-		offset = 0;
-
-	reg_906 = dib9000_read_word(state, 906 + offset) | 0x3;	/* keep settings for RISC */
-
-	/* now, depending on the requested mode, we power on */
-	switch (mode) {
-		/* power up everything in the demod */
-	case DIB9000_POWER_ALL:
-		reg_903 = 0x0000;
-		reg_904 = 0x0000;
-		reg_905 = 0x0000;
-		reg_906 = 0x0000;
-		break;
-
-		/* just leave power on the control-interfaces: GPIO and (I2C or SDIO or SRAM) */
-	case DIB9000_POWER_INTERFACE_ONLY:	/* TODO power up either SDIO or I2C or SRAM */
-		reg_905 &= ~((1 << 7) | (1 << 6) | (1 << 5) | (1 << 2));
-		break;
-
-	case DIB9000_POWER_INTERF_ANALOG_AGC:
-		reg_903 &= ~((1 << 15) | (1 << 14) | (1 << 11) | (1 << 10));
-		reg_905 &= ~((1 << 7) | (1 << 6) | (1 << 5) | (1 << 4) | (1 << 2));
-		reg_906 &= ~((1 << 0));
-		break;
-
-	case DIB9000_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD:
-		reg_903 = 0x0000;
-		reg_904 = 0x801f;
-		reg_905 = 0x0000;
-		reg_906 &= ~((1 << 0));
-		break;
-
-	case DIB9000_POWER_COR4_CRY_ESRAM_MOUT_NUD:
-		reg_903 = 0x0000;
-		reg_904 = 0x8000;
-		reg_905 = 0x010b;
-		reg_906 &= ~((1 << 0));
-		break;
-	default:
-	case DIB9000_POWER_NO:
-		break;
-	}
-
-	/* always power down unused parts */
-	if (!state->platform.host.mobile_mode)
-		reg_904 |= (1 << 7) | (1 << 6) | (1 << 4) | (1 << 2) | (1 << 1);
-
-	/* P_sdio_select_clk = 0 on MC and after */
-	if (state->revision != 0x4000)
-		reg_906 <<= 1;
-
-	dib9000_write_word(state, 903 + offset, reg_903);
-	dib9000_write_word(state, 904 + offset, reg_904);
-	dib9000_write_word(state, 905 + offset, reg_905);
-	dib9000_write_word(state, 906 + offset, reg_906);
-}
-
-static int dib9000_fw_reset(struct dvb_frontend *fe)
-{
-	struct dib9000_state *state = fe->demodulator_priv;
-
-	dib9000_write_word(state, 1817, 0x0003);
-
-	dib9000_write_word(state, 1227, 1);
-	dib9000_write_word(state, 1227, 0);
-
-	switch ((state->revision = dib9000_identify(&state->i2c))) {
-	case 0x4003:
-	case 0x4004:
-	case 0x4005:
-		state->reg_offs = 1;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	/* reset the i2c-master to use the host interface */
-	dibx000_reset_i2c_master(&state->i2c_master);
-
-	dib9000_set_power_mode(state, DIB9000_POWER_ALL);
-
-	/* unforce divstr regardless whether i2c enumeration was done or not */
-	dib9000_write_word(state, 1794, dib9000_read_word(state, 1794) & ~(1 << 1));
-	dib9000_write_word(state, 1796, 0);
-	dib9000_write_word(state, 1805, 0x805);
-
-	/* restart all parts */
-	dib9000_write_word(state, 898, 0xffff);
-	dib9000_write_word(state, 899, 0xffff);
-	dib9000_write_word(state, 900, 0x0001);
-	dib9000_write_word(state, 901, 0xff19);
-	dib9000_write_word(state, 902, 0x003c);
-
-	dib9000_write_word(state, 898, 0);
-	dib9000_write_word(state, 899, 0);
-	dib9000_write_word(state, 900, 0);
-	dib9000_write_word(state, 901, 0);
-	dib9000_write_word(state, 902, 0);
-
-	dib9000_write_word(state, 911, state->chip.d9.cfg.if_drives);
-
-	dib9000_set_power_mode(state, DIB9000_POWER_INTERFACE_ONLY);
-
-	return 0;
-}
-
-static int dib9000_risc_apb_access_read(struct dib9000_state *state, u32 address, u16 attribute, const u8 * tx, u32 txlen, u8 * b, u32 len)
-{
-	u16 mb[10];
-	u8 i, s;
-
-	if (address >= 1024 || !state->platform.risc.fw_is_running)
-		return -EINVAL;
-
-	/* dprintk( "APB access thru rd fw %d %x", address, attribute); */
-
-	mb[0] = (u16) address;
-	mb[1] = len / 2;
-	dib9000_mbx_send_attr(state, OUT_MSG_BRIDGE_APB_R, mb, 2, attribute);
-	switch (dib9000_mbx_get_message_attr(state, IN_MSG_END_BRIDGE_APB_RW, mb, &s, attribute)) {
-	case 1:
-		s--;
-		for (i = 0; i < s; i++) {
-			b[i * 2] = (mb[i + 1] >> 8) & 0xff;
-			b[i * 2 + 1] = (mb[i + 1]) & 0xff;
-		}
-		return 0;
-	default:
-		return -EIO;
-	}
-	return -EIO;
-}
-
-static int dib9000_risc_apb_access_write(struct dib9000_state *state, u32 address, u16 attribute, const u8 * b, u32 len)
-{
-	u16 mb[10];
-	u8 s, i;
-
-	if (address >= 1024 || !state->platform.risc.fw_is_running)
-		return -EINVAL;
-
-	/* dprintk( "APB access thru wr fw %d %x", address, attribute); */
-
-	mb[0] = (unsigned short)address;
-	for (i = 0; i < len && i < 20; i += 2)
-		mb[1 + (i / 2)] = (b[i] << 8 | b[i + 1]);
-
-	dib9000_mbx_send_attr(state, OUT_MSG_BRIDGE_APB_W, mb, 1 + len / 2, attribute);
-	return dib9000_mbx_get_message_attr(state, IN_MSG_END_BRIDGE_APB_RW, mb, &s, attribute) == 1 ? 0 : -EINVAL;
-}
-
-static int dib9000_fw_memmbx_sync(struct dib9000_state *state, u8 i)
-{
-	u8 index_loop = 10;
-
-	if (!state->platform.risc.fw_is_running)
-		return 0;
-	dib9000_risc_mem_write(state, FE_MM_RW_SYNC, &i);
-	do {
-		dib9000_risc_mem_read(state, FE_MM_RW_SYNC, state->i2c_read_buffer, 1);
-	} while (state->i2c_read_buffer[0] && index_loop--);
-
-	if (index_loop > 0)
-		return 0;
-	return -EIO;
-}
-
-static int dib9000_fw_init(struct dib9000_state *state)
-{
-	struct dibGPIOFunction *f;
-	u16 b[40] = { 0 };
-	u8 i;
-	u8 size;
-
-	if (dib9000_fw_boot(state, NULL, 0, state->chip.d9.cfg.microcode_B_fe_buffer, state->chip.d9.cfg.microcode_B_fe_size) != 0)
-		return -EIO;
-
-	/* initialize the firmware */
-	for (i = 0; i < ARRAY_SIZE(state->chip.d9.cfg.gpio_function); i++) {
-		f = &state->chip.d9.cfg.gpio_function[i];
-		if (f->mask) {
-			switch (f->function) {
-			case BOARD_GPIO_FUNCTION_COMPONENT_ON:
-				b[0] = (u16) f->mask;
-				b[1] = (u16) f->direction;
-				b[2] = (u16) f->value;
-				break;
-			case BOARD_GPIO_FUNCTION_COMPONENT_OFF:
-				b[3] = (u16) f->mask;
-				b[4] = (u16) f->direction;
-				b[5] = (u16) f->value;
-				break;
-			}
-		}
-	}
-	if (dib9000_mbx_send(state, OUT_MSG_CONF_GPIO, b, 15) != 0)
-		return -EIO;
-
-	/* subband */
-	b[0] = state->chip.d9.cfg.subband.size;	/* type == 0 -> GPIO - PWM not yet supported */
-	for (i = 0; i < state->chip.d9.cfg.subband.size; i++) {
-		b[1 + i * 4] = state->chip.d9.cfg.subband.subband[i].f_mhz;
-		b[2 + i * 4] = (u16) state->chip.d9.cfg.subband.subband[i].gpio.mask;
-		b[3 + i * 4] = (u16) state->chip.d9.cfg.subband.subband[i].gpio.direction;
-		b[4 + i * 4] = (u16) state->chip.d9.cfg.subband.subband[i].gpio.value;
-	}
-	b[1 + i * 4] = 0;	/* fe_id */
-	if (dib9000_mbx_send(state, OUT_MSG_SUBBAND_SEL, b, 2 + 4 * i) != 0)
-		return -EIO;
-
-	/* 0 - id, 1 - no_of_frontends */
-	b[0] = (0 << 8) | 1;
-	/* 0 = i2c-address demod, 0 = tuner */
-	b[1] = (0 << 8) | (0);
-	b[2] = (u16) (((state->chip.d9.cfg.xtal_clock_khz * 1000) >> 16) & 0xffff);
-	b[3] = (u16) (((state->chip.d9.cfg.xtal_clock_khz * 1000)) & 0xffff);
-	b[4] = (u16) ((state->chip.d9.cfg.vcxo_timer >> 16) & 0xffff);
-	b[5] = (u16) ((state->chip.d9.cfg.vcxo_timer) & 0xffff);
-	b[6] = (u16) ((state->chip.d9.cfg.timing_frequency >> 16) & 0xffff);
-	b[7] = (u16) ((state->chip.d9.cfg.timing_frequency) & 0xffff);
-	b[29] = state->chip.d9.cfg.if_drives;
-	if (dib9000_mbx_send(state, OUT_MSG_INIT_DEMOD, b, ARRAY_SIZE(b)) != 0)
-		return -EIO;
-
-	if (dib9000_mbx_send(state, OUT_MSG_FE_FW_DL, NULL, 0) != 0)
-		return -EIO;
-
-	if (dib9000_mbx_get_message(state, IN_MSG_FE_FW_DL_DONE, b, &size) < 0)
-		return -EIO;
-
-	if (size > ARRAY_SIZE(b)) {
-		dprintk("error : firmware returned %dbytes needed but the used buffer has only %dbytes\n Firmware init ABORTED", size,
-			(int)ARRAY_SIZE(b));
-		return -EINVAL;
-	}
-
-	for (i = 0; i < size; i += 2) {
-		state->platform.risc.fe_mm[i / 2].addr = b[i + 0];
-		state->platform.risc.fe_mm[i / 2].size = b[i + 1];
-	}
-
-	return 0;
-}
-
-static void dib9000_fw_set_channel_head(struct dib9000_state *state)
-{
-	u8 b[9];
-	u32 freq = state->fe[0]->dtv_property_cache.frequency / 1000;
-	if (state->fe_id % 2)
-		freq += 101;
-
-	b[0] = (u8) ((freq >> 0) & 0xff);
-	b[1] = (u8) ((freq >> 8) & 0xff);
-	b[2] = (u8) ((freq >> 16) & 0xff);
-	b[3] = (u8) ((freq >> 24) & 0xff);
-	b[4] = (u8) ((state->fe[0]->dtv_property_cache.bandwidth_hz / 1000 >> 0) & 0xff);
-	b[5] = (u8) ((state->fe[0]->dtv_property_cache.bandwidth_hz / 1000 >> 8) & 0xff);
-	b[6] = (u8) ((state->fe[0]->dtv_property_cache.bandwidth_hz / 1000 >> 16) & 0xff);
-	b[7] = (u8) ((state->fe[0]->dtv_property_cache.bandwidth_hz / 1000 >> 24) & 0xff);
-	b[8] = 0x80;		/* do not wait for CELL ID when doing autosearch */
-	if (state->fe[0]->dtv_property_cache.delivery_system == SYS_DVBT)
-		b[8] |= 1;
-	dib9000_risc_mem_write(state, FE_MM_W_CHANNEL_HEAD, b);
-}
-
-static int dib9000_fw_get_channel(struct dvb_frontend *fe)
-{
-	struct dib9000_state *state = fe->demodulator_priv;
-	struct dibDVBTChannel {
-		s8 spectrum_inversion;
-
-		s8 nfft;
-		s8 guard;
-		s8 constellation;
-
-		s8 hrch;
-		s8 alpha;
-		s8 code_rate_hp;
-		s8 code_rate_lp;
-		s8 select_hp;
-
-		s8 intlv_native;
-	};
-	struct dibDVBTChannel *ch;
-	int ret = 0;
-
-	if (mutex_lock_interruptible(&state->platform.risc.mem_mbx_lock) < 0) {
-		dprintk("could not get the lock");
-		return -EINTR;
-	}
-	if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) {
-		ret = -EIO;
-		goto error;
-	}
-
-	dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_UNION,
-			state->i2c_read_buffer, sizeof(struct dibDVBTChannel));
-	ch = (struct dibDVBTChannel *)state->i2c_read_buffer;
-
-
-	switch (ch->spectrum_inversion & 0x7) {
-	case 1:
-		state->fe[0]->dtv_property_cache.inversion = INVERSION_ON;
-		break;
-	case 0:
-		state->fe[0]->dtv_property_cache.inversion = INVERSION_OFF;
-		break;
-	default:
-	case -1:
-		state->fe[0]->dtv_property_cache.inversion = INVERSION_AUTO;
-		break;
-	}
-	switch (ch->nfft) {
-	case 0:
-		state->fe[0]->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_2K;
-		break;
-	case 2:
-		state->fe[0]->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_4K;
-		break;
-	case 1:
-		state->fe[0]->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_8K;
-		break;
-	default:
-	case -1:
-		state->fe[0]->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_AUTO;
-		break;
-	}
-	switch (ch->guard) {
-	case 0:
-		state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_32;
-		break;
-	case 1:
-		state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_16;
-		break;
-	case 2:
-		state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_8;
-		break;
-	case 3:
-		state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_4;
-		break;
-	default:
-	case -1:
-		state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_AUTO;
-		break;
-	}
-	switch (ch->constellation) {
-	case 2:
-		state->fe[0]->dtv_property_cache.modulation = QAM_64;
-		break;
-	case 1:
-		state->fe[0]->dtv_property_cache.modulation = QAM_16;
-		break;
-	case 0:
-		state->fe[0]->dtv_property_cache.modulation = QPSK;
-		break;
-	default:
-	case -1:
-		state->fe[0]->dtv_property_cache.modulation = QAM_AUTO;
-		break;
-	}
-	switch (ch->hrch) {
-	case 0:
-		state->fe[0]->dtv_property_cache.hierarchy = HIERARCHY_NONE;
-		break;
-	case 1:
-		state->fe[0]->dtv_property_cache.hierarchy = HIERARCHY_1;
-		break;
-	default:
-	case -1:
-		state->fe[0]->dtv_property_cache.hierarchy = HIERARCHY_AUTO;
-		break;
-	}
-	switch (ch->code_rate_hp) {
-	case 1:
-		state->fe[0]->dtv_property_cache.code_rate_HP = FEC_1_2;
-		break;
-	case 2:
-		state->fe[0]->dtv_property_cache.code_rate_HP = FEC_2_3;
-		break;
-	case 3:
-		state->fe[0]->dtv_property_cache.code_rate_HP = FEC_3_4;
-		break;
-	case 5:
-		state->fe[0]->dtv_property_cache.code_rate_HP = FEC_5_6;
-		break;
-	case 7:
-		state->fe[0]->dtv_property_cache.code_rate_HP = FEC_7_8;
-		break;
-	default:
-	case -1:
-		state->fe[0]->dtv_property_cache.code_rate_HP = FEC_AUTO;
-		break;
-	}
-	switch (ch->code_rate_lp) {
-	case 1:
-		state->fe[0]->dtv_property_cache.code_rate_LP = FEC_1_2;
-		break;
-	case 2:
-		state->fe[0]->dtv_property_cache.code_rate_LP = FEC_2_3;
-		break;
-	case 3:
-		state->fe[0]->dtv_property_cache.code_rate_LP = FEC_3_4;
-		break;
-	case 5:
-		state->fe[0]->dtv_property_cache.code_rate_LP = FEC_5_6;
-		break;
-	case 7:
-		state->fe[0]->dtv_property_cache.code_rate_LP = FEC_7_8;
-		break;
-	default:
-	case -1:
-		state->fe[0]->dtv_property_cache.code_rate_LP = FEC_AUTO;
-		break;
-	}
-
-error:
-	mutex_unlock(&state->platform.risc.mem_mbx_lock);
-	return ret;
-}
-
-static int dib9000_fw_set_channel_union(struct dvb_frontend *fe)
-{
-	struct dib9000_state *state = fe->demodulator_priv;
-	struct dibDVBTChannel {
-		s8 spectrum_inversion;
-
-		s8 nfft;
-		s8 guard;
-		s8 constellation;
-
-		s8 hrch;
-		s8 alpha;
-		s8 code_rate_hp;
-		s8 code_rate_lp;
-		s8 select_hp;
-
-		s8 intlv_native;
-	};
-	struct dibDVBTChannel ch;
-
-	switch (state->fe[0]->dtv_property_cache.inversion) {
-	case INVERSION_ON:
-		ch.spectrum_inversion = 1;
-		break;
-	case INVERSION_OFF:
-		ch.spectrum_inversion = 0;
-		break;
-	default:
-	case INVERSION_AUTO:
-		ch.spectrum_inversion = -1;
-		break;
-	}
-	switch (state->fe[0]->dtv_property_cache.transmission_mode) {
-	case TRANSMISSION_MODE_2K:
-		ch.nfft = 0;
-		break;
-	case TRANSMISSION_MODE_4K:
-		ch.nfft = 2;
-		break;
-	case TRANSMISSION_MODE_8K:
-		ch.nfft = 1;
-		break;
-	default:
-	case TRANSMISSION_MODE_AUTO:
-		ch.nfft = 1;
-		break;
-	}
-	switch (state->fe[0]->dtv_property_cache.guard_interval) {
-	case GUARD_INTERVAL_1_32:
-		ch.guard = 0;
-		break;
-	case GUARD_INTERVAL_1_16:
-		ch.guard = 1;
-		break;
-	case GUARD_INTERVAL_1_8:
-		ch.guard = 2;
-		break;
-	case GUARD_INTERVAL_1_4:
-		ch.guard = 3;
-		break;
-	default:
-	case GUARD_INTERVAL_AUTO:
-		ch.guard = -1;
-		break;
-	}
-	switch (state->fe[0]->dtv_property_cache.modulation) {
-	case QAM_64:
-		ch.constellation = 2;
-		break;
-	case QAM_16:
-		ch.constellation = 1;
-		break;
-	case QPSK:
-		ch.constellation = 0;
-		break;
-	default:
-	case QAM_AUTO:
-		ch.constellation = -1;
-		break;
-	}
-	switch (state->fe[0]->dtv_property_cache.hierarchy) {
-	case HIERARCHY_NONE:
-		ch.hrch = 0;
-		break;
-	case HIERARCHY_1:
-	case HIERARCHY_2:
-	case HIERARCHY_4:
-		ch.hrch = 1;
-		break;
-	default:
-	case HIERARCHY_AUTO:
-		ch.hrch = -1;
-		break;
-	}
-	ch.alpha = 1;
-	switch (state->fe[0]->dtv_property_cache.code_rate_HP) {
-	case FEC_1_2:
-		ch.code_rate_hp = 1;
-		break;
-	case FEC_2_3:
-		ch.code_rate_hp = 2;
-		break;
-	case FEC_3_4:
-		ch.code_rate_hp = 3;
-		break;
-	case FEC_5_6:
-		ch.code_rate_hp = 5;
-		break;
-	case FEC_7_8:
-		ch.code_rate_hp = 7;
-		break;
-	default:
-	case FEC_AUTO:
-		ch.code_rate_hp = -1;
-		break;
-	}
-	switch (state->fe[0]->dtv_property_cache.code_rate_LP) {
-	case FEC_1_2:
-		ch.code_rate_lp = 1;
-		break;
-	case FEC_2_3:
-		ch.code_rate_lp = 2;
-		break;
-	case FEC_3_4:
-		ch.code_rate_lp = 3;
-		break;
-	case FEC_5_6:
-		ch.code_rate_lp = 5;
-		break;
-	case FEC_7_8:
-		ch.code_rate_lp = 7;
-		break;
-	default:
-	case FEC_AUTO:
-		ch.code_rate_lp = -1;
-		break;
-	}
-	ch.select_hp = 1;
-	ch.intlv_native = 1;
-
-	dib9000_risc_mem_write(state, FE_MM_W_CHANNEL_UNION, (u8 *) &ch);
-
-	return 0;
-}
-
-static int dib9000_fw_tune(struct dvb_frontend *fe)
-{
-	struct dib9000_state *state = fe->demodulator_priv;
-	int ret = 10, search = state->channel_status.status == CHANNEL_STATUS_PARAMETERS_UNKNOWN;
-	s8 i;
-
-	switch (state->tune_state) {
-	case CT_DEMOD_START:
-		dib9000_fw_set_channel_head(state);
-
-		/* write the channel context - a channel is initialized to 0, so it is OK */
-		dib9000_risc_mem_write(state, FE_MM_W_CHANNEL_CONTEXT, (u8 *) fe_info);
-		dib9000_risc_mem_write(state, FE_MM_W_FE_INFO, (u8 *) fe_info);
-
-		if (search)
-			dib9000_mbx_send(state, OUT_MSG_FE_CHANNEL_SEARCH, NULL, 0);
-		else {
-			dib9000_fw_set_channel_union(fe);
-			dib9000_mbx_send(state, OUT_MSG_FE_CHANNEL_TUNE, NULL, 0);
-		}
-		state->tune_state = CT_DEMOD_STEP_1;
-		break;
-	case CT_DEMOD_STEP_1:
-		if (search)
-			dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_SEARCH_STATE, state->i2c_read_buffer, 1);
-		else
-			dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_TUNE_STATE, state->i2c_read_buffer, 1);
-		i = (s8)state->i2c_read_buffer[0];
-		switch (i) {	/* something happened */
-		case 0:
-			break;
-		case -2:	/* tps locks are "slower" than MPEG locks -> even in autosearch data is OK here */
-			if (search)
-				state->status = FE_STATUS_DEMOD_SUCCESS;
-			else {
-				state->tune_state = CT_DEMOD_STOP;
-				state->status = FE_STATUS_LOCKED;
-			}
-			break;
-		default:
-			state->status = FE_STATUS_TUNE_FAILED;
-			state->tune_state = CT_DEMOD_STOP;
-			break;
-		}
-		break;
-	default:
-		ret = FE_CALLBACK_TIME_NEVER;
-		break;
-	}
-
-	return ret;
-}
-
-static int dib9000_fw_set_diversity_in(struct dvb_frontend *fe, int onoff)
-{
-	struct dib9000_state *state = fe->demodulator_priv;
-	u16 mode = (u16) onoff;
-	return dib9000_mbx_send(state, OUT_MSG_ENABLE_DIVERSITY, &mode, 1);
-}
-
-static int dib9000_fw_set_output_mode(struct dvb_frontend *fe, int mode)
-{
-	struct dib9000_state *state = fe->demodulator_priv;
-	u16 outreg, smo_mode;
-
-	dprintk("setting output mode for demod %p to %d", fe, mode);
-
-	switch (mode) {
-	case OUTMODE_MPEG2_PAR_GATED_CLK:
-		outreg = (1 << 10);	/* 0x0400 */
-		break;
-	case OUTMODE_MPEG2_PAR_CONT_CLK:
-		outreg = (1 << 10) | (1 << 6);	/* 0x0440 */
-		break;
-	case OUTMODE_MPEG2_SERIAL:
-		outreg = (1 << 10) | (2 << 6) | (0 << 1);	/* 0x0482 */
-		break;
-	case OUTMODE_DIVERSITY:
-		outreg = (1 << 10) | (4 << 6);	/* 0x0500 */
-		break;
-	case OUTMODE_MPEG2_FIFO:
-		outreg = (1 << 10) | (5 << 6);
-		break;
-	case OUTMODE_HIGH_Z:
-		outreg = 0;
-		break;
-	default:
-		dprintk("Unhandled output_mode passed to be set for demod %p", &state->fe[0]);
-		return -EINVAL;
-	}
-
-	dib9000_write_word(state, 1795, outreg);
-
-	switch (mode) {
-	case OUTMODE_MPEG2_PAR_GATED_CLK:
-	case OUTMODE_MPEG2_PAR_CONT_CLK:
-	case OUTMODE_MPEG2_SERIAL:
-	case OUTMODE_MPEG2_FIFO:
-		smo_mode = (dib9000_read_word(state, 295) & 0x0010) | (1 << 1);
-		if (state->chip.d9.cfg.output_mpeg2_in_188_bytes)
-			smo_mode |= (1 << 5);
-		dib9000_write_word(state, 295, smo_mode);
-		break;
-	}
-
-	outreg = to_fw_output_mode(mode);
-	return dib9000_mbx_send(state, OUT_MSG_SET_OUTPUT_MODE, &outreg, 1);
-}
-
-static int dib9000_tuner_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)
-{
-	struct dib9000_state *state = i2c_get_adapdata(i2c_adap);
-	u16 i, len, t, index_msg;
-
-	for (index_msg = 0; index_msg < num; index_msg++) {
-		if (msg[index_msg].flags & I2C_M_RD) {	/* read */
-			len = msg[index_msg].len;
-			if (len > 16)
-				len = 16;
-
-			if (dib9000_read_word(state, 790) != 0)
-				dprintk("TunerITF: read busy");
-
-			dib9000_write_word(state, 784, (u16) (msg[index_msg].addr));
-			dib9000_write_word(state, 787, (len / 2) - 1);
-			dib9000_write_word(state, 786, 1);	/* start read */
-
-			i = 1000;
-			while (dib9000_read_word(state, 790) != (len / 2) && i)
-				i--;
-
-			if (i == 0)
-				dprintk("TunerITF: read failed");
-
-			for (i = 0; i < len; i += 2) {
-				t = dib9000_read_word(state, 785);
-				msg[index_msg].buf[i] = (t >> 8) & 0xff;
-				msg[index_msg].buf[i + 1] = (t) & 0xff;
-			}
-			if (dib9000_read_word(state, 790) != 0)
-				dprintk("TunerITF: read more data than expected");
-		} else {
-			i = 1000;
-			while (dib9000_read_word(state, 789) && i)
-				i--;
-			if (i == 0)
-				dprintk("TunerITF: write busy");
-
-			len = msg[index_msg].len;
-			if (len > 16)
-				len = 16;
-
-			for (i = 0; i < len; i += 2)
-				dib9000_write_word(state, 785, (msg[index_msg].buf[i] << 8) | msg[index_msg].buf[i + 1]);
-			dib9000_write_word(state, 784, (u16) msg[index_msg].addr);
-			dib9000_write_word(state, 787, (len / 2) - 1);
-			dib9000_write_word(state, 786, 0);	/* start write */
-
-			i = 1000;
-			while (dib9000_read_word(state, 791) > 0 && i)
-				i--;
-			if (i == 0)
-				dprintk("TunerITF: write failed");
-		}
-	}
-	return num;
-}
-
-int dib9000_fw_set_component_bus_speed(struct dvb_frontend *fe, u16 speed)
-{
-	struct dib9000_state *state = fe->demodulator_priv;
-
-	state->component_bus_speed = speed;
-	return 0;
-}
-EXPORT_SYMBOL(dib9000_fw_set_component_bus_speed);
-
-static int dib9000_fw_component_bus_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)
-{
-	struct dib9000_state *state = i2c_get_adapdata(i2c_adap);
-	u8 type = 0;		/* I2C */
-	u8 port = DIBX000_I2C_INTERFACE_GPIO_3_4;
-	u16 scl = state->component_bus_speed;	/* SCL frequency */
-	struct dib9000_fe_memory_map *m = &state->platform.risc.fe_mm[FE_MM_RW_COMPONENT_ACCESS_BUFFER];
-	u8 p[13] = { 0 };
-
-	p[0] = type;
-	p[1] = port;
-	p[2] = msg[0].addr << 1;
-
-	p[3] = (u8) scl & 0xff;	/* scl */
-	p[4] = (u8) (scl >> 8);
-
-	p[7] = 0;
-	p[8] = 0;
-
-	p[9] = (u8) (msg[0].len);
-	p[10] = (u8) (msg[0].len >> 8);
-	if ((num > 1) && (msg[1].flags & I2C_M_RD)) {
-		p[11] = (u8) (msg[1].len);
-		p[12] = (u8) (msg[1].len >> 8);
-	} else {
-		p[11] = 0;
-		p[12] = 0;
-	}
-
-	if (mutex_lock_interruptible(&state->platform.risc.mem_mbx_lock) < 0) {
-		dprintk("could not get the lock");
-		return 0;
-	}
-
-	dib9000_risc_mem_write(state, FE_MM_W_COMPONENT_ACCESS, p);
-
-	{			/* write-part */
-		dib9000_risc_mem_setup_cmd(state, m->addr, msg[0].len, 0);
-		dib9000_risc_mem_write_chunks(state, msg[0].buf, msg[0].len);
-	}
-
-	/* do the transaction */
-	if (dib9000_fw_memmbx_sync(state, FE_SYNC_COMPONENT_ACCESS) < 0) {
-		mutex_unlock(&state->platform.risc.mem_mbx_lock);
-		return 0;
-	}
-
-	/* read back any possible result */
-	if ((num > 1) && (msg[1].flags & I2C_M_RD))
-		dib9000_risc_mem_read(state, FE_MM_RW_COMPONENT_ACCESS_BUFFER, msg[1].buf, msg[1].len);
-
-	mutex_unlock(&state->platform.risc.mem_mbx_lock);
-
-	return num;
-}
-
-static u32 dib9000_i2c_func(struct i2c_adapter *adapter)
-{
-	return I2C_FUNC_I2C;
-}
-
-static struct i2c_algorithm dib9000_tuner_algo = {
-	.master_xfer = dib9000_tuner_xfer,
-	.functionality = dib9000_i2c_func,
-};
-
-static struct i2c_algorithm dib9000_component_bus_algo = {
-	.master_xfer = dib9000_fw_component_bus_xfer,
-	.functionality = dib9000_i2c_func,
-};
-
-struct i2c_adapter *dib9000_get_tuner_interface(struct dvb_frontend *fe)
-{
-	struct dib9000_state *st = fe->demodulator_priv;
-	return &st->tuner_adap;
-}
-EXPORT_SYMBOL(dib9000_get_tuner_interface);
-
-struct i2c_adapter *dib9000_get_component_bus_interface(struct dvb_frontend *fe)
-{
-	struct dib9000_state *st = fe->demodulator_priv;
-	return &st->component_bus;
-}
-EXPORT_SYMBOL(dib9000_get_component_bus_interface);
-
-struct i2c_adapter *dib9000_get_i2c_master(struct dvb_frontend *fe, enum dibx000_i2c_interface intf, int gating)
-{
-	struct dib9000_state *st = fe->demodulator_priv;
-	return dibx000_get_i2c_adapter(&st->i2c_master, intf, gating);
-}
-EXPORT_SYMBOL(dib9000_get_i2c_master);
-
-int dib9000_set_i2c_adapter(struct dvb_frontend *fe, struct i2c_adapter *i2c)
-{
-	struct dib9000_state *st = fe->demodulator_priv;
-
-	st->i2c.i2c_adap = i2c;
-	return 0;
-}
-EXPORT_SYMBOL(dib9000_set_i2c_adapter);
-
-static int dib9000_cfg_gpio(struct dib9000_state *st, u8 num, u8 dir, u8 val)
-{
-	st->gpio_dir = dib9000_read_word(st, 773);
-	st->gpio_dir &= ~(1 << num);	/* reset the direction bit */
-	st->gpio_dir |= (dir & 0x1) << num;	/* set the new direction */
-	dib9000_write_word(st, 773, st->gpio_dir);
-
-	st->gpio_val = dib9000_read_word(st, 774);
-	st->gpio_val &= ~(1 << num);	/* reset the direction bit */
-	st->gpio_val |= (val & 0x01) << num;	/* set the new value */
-	dib9000_write_word(st, 774, st->gpio_val);
-
-	dprintk("gpio dir: %04x: gpio val: %04x", st->gpio_dir, st->gpio_val);
-
-	return 0;
-}
-
-int dib9000_set_gpio(struct dvb_frontend *fe, u8 num, u8 dir, u8 val)
-{
-	struct dib9000_state *state = fe->demodulator_priv;
-	return dib9000_cfg_gpio(state, num, dir, val);
-}
-EXPORT_SYMBOL(dib9000_set_gpio);
-
-int dib9000_fw_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
-{
-	struct dib9000_state *state = fe->demodulator_priv;
-	u16 val;
-	int ret;
-
-	if ((state->pid_ctrl_index != -2) && (state->pid_ctrl_index < 9)) {
-		/* postpone the pid filtering cmd */
-		dprintk("pid filter cmd postpone");
-		state->pid_ctrl_index++;
-		state->pid_ctrl[state->pid_ctrl_index].cmd = DIB9000_PID_FILTER_CTRL;
-		state->pid_ctrl[state->pid_ctrl_index].onoff = onoff;
-		return 0;
-	}
-
-	if (mutex_lock_interruptible(&state->demod_lock) < 0) {
-		dprintk("could not get the lock");
-		return -EINTR;
-	}
-
-	val = dib9000_read_word(state, 294 + 1) & 0xffef;
-	val |= (onoff & 0x1) << 4;
-
-	dprintk("PID filter enabled %d", onoff);
-	ret = dib9000_write_word(state, 294 + 1, val);
-	mutex_unlock(&state->demod_lock);
-	return ret;
-
-}
-EXPORT_SYMBOL(dib9000_fw_pid_filter_ctrl);
-
-int dib9000_fw_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
-{
-	struct dib9000_state *state = fe->demodulator_priv;
-	int ret;
-
-	if (state->pid_ctrl_index != -2) {
-		/* postpone the pid filtering cmd */
-		dprintk("pid filter postpone");
-		if (state->pid_ctrl_index < 9) {
-			state->pid_ctrl_index++;
-			state->pid_ctrl[state->pid_ctrl_index].cmd = DIB9000_PID_FILTER;
-			state->pid_ctrl[state->pid_ctrl_index].id = id;
-			state->pid_ctrl[state->pid_ctrl_index].pid = pid;
-			state->pid_ctrl[state->pid_ctrl_index].onoff = onoff;
-		} else
-			dprintk("can not add any more pid ctrl cmd");
-		return 0;
-	}
-
-	if (mutex_lock_interruptible(&state->demod_lock) < 0) {
-		dprintk("could not get the lock");
-		return -EINTR;
-	}
-	dprintk("Index %x, PID %d, OnOff %d", id, pid, onoff);
-	ret = dib9000_write_word(state, 300 + 1 + id,
-			onoff ? (1 << 13) | pid : 0);
-	mutex_unlock(&state->demod_lock);
-	return ret;
-}
-EXPORT_SYMBOL(dib9000_fw_pid_filter);
-
-int dib9000_firmware_post_pll_init(struct dvb_frontend *fe)
-{
-	struct dib9000_state *state = fe->demodulator_priv;
-	return dib9000_fw_init(state);
-}
-EXPORT_SYMBOL(dib9000_firmware_post_pll_init);
-
-static void dib9000_release(struct dvb_frontend *demod)
-{
-	struct dib9000_state *st = demod->demodulator_priv;
-	u8 index_frontend;
-
-	for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (st->fe[index_frontend] != NULL); index_frontend++)
-		dvb_frontend_detach(st->fe[index_frontend]);
-
-	dibx000_exit_i2c_master(&st->i2c_master);
-
-	i2c_del_adapter(&st->tuner_adap);
-	i2c_del_adapter(&st->component_bus);
-	kfree(st->fe[0]);
-	kfree(st);
-}
-
-static int dib9000_wakeup(struct dvb_frontend *fe)
-{
-	return 0;
-}
-
-static int dib9000_sleep(struct dvb_frontend *fe)
-{
-	struct dib9000_state *state = fe->demodulator_priv;
-	u8 index_frontend;
-	int ret = 0;
-
-	if (mutex_lock_interruptible(&state->demod_lock) < 0) {
-		dprintk("could not get the lock");
-		return -EINTR;
-	}
-	for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
-		ret = state->fe[index_frontend]->ops.sleep(state->fe[index_frontend]);
-		if (ret < 0)
-			goto error;
-	}
-	ret = dib9000_mbx_send(state, OUT_MSG_FE_SLEEP, NULL, 0);
-
-error:
-	mutex_unlock(&state->demod_lock);
-	return ret;
-}
-
-static int dib9000_fe_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings *tune)
-{
-	tune->min_delay_ms = 1000;
-	return 0;
-}
-
-static int dib9000_get_frontend(struct dvb_frontend *fe)
-{
-	struct dib9000_state *state = fe->demodulator_priv;
-	u8 index_frontend, sub_index_frontend;
-	fe_status_t stat;
-	int ret = 0;
-
-	if (state->get_frontend_internal == 0) {
-		if (mutex_lock_interruptible(&state->demod_lock) < 0) {
-			dprintk("could not get the lock");
-			return -EINTR;
-		}
-	}
-
-	for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
-		state->fe[index_frontend]->ops.read_status(state->fe[index_frontend], &stat);
-		if (stat & FE_HAS_SYNC) {
-			dprintk("TPS lock on the slave%i", index_frontend);
-
-			/* synchronize the cache with the other frontends */
-			state->fe[index_frontend]->ops.get_frontend(state->fe[index_frontend]);
-			for (sub_index_frontend = 0; (sub_index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[sub_index_frontend] != NULL);
-			     sub_index_frontend++) {
-				if (sub_index_frontend != index_frontend) {
-					state->fe[sub_index_frontend]->dtv_property_cache.modulation =
-					    state->fe[index_frontend]->dtv_property_cache.modulation;
-					state->fe[sub_index_frontend]->dtv_property_cache.inversion =
-					    state->fe[index_frontend]->dtv_property_cache.inversion;
-					state->fe[sub_index_frontend]->dtv_property_cache.transmission_mode =
-					    state->fe[index_frontend]->dtv_property_cache.transmission_mode;
-					state->fe[sub_index_frontend]->dtv_property_cache.guard_interval =
-					    state->fe[index_frontend]->dtv_property_cache.guard_interval;
-					state->fe[sub_index_frontend]->dtv_property_cache.hierarchy =
-					    state->fe[index_frontend]->dtv_property_cache.hierarchy;
-					state->fe[sub_index_frontend]->dtv_property_cache.code_rate_HP =
-					    state->fe[index_frontend]->dtv_property_cache.code_rate_HP;
-					state->fe[sub_index_frontend]->dtv_property_cache.code_rate_LP =
-					    state->fe[index_frontend]->dtv_property_cache.code_rate_LP;
-					state->fe[sub_index_frontend]->dtv_property_cache.rolloff =
-					    state->fe[index_frontend]->dtv_property_cache.rolloff;
-				}
-			}
-			ret = 0;
-			goto return_value;
-		}
-	}
-
-	/* get the channel from master chip */
-	ret = dib9000_fw_get_channel(fe);
-	if (ret != 0)
-		goto return_value;
-
-	/* synchronize the cache with the other frontends */
-	for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
-		state->fe[index_frontend]->dtv_property_cache.inversion = fe->dtv_property_cache.inversion;
-		state->fe[index_frontend]->dtv_property_cache.transmission_mode = fe->dtv_property_cache.transmission_mode;
-		state->fe[index_frontend]->dtv_property_cache.guard_interval = fe->dtv_property_cache.guard_interval;
-		state->fe[index_frontend]->dtv_property_cache.modulation = fe->dtv_property_cache.modulation;
-		state->fe[index_frontend]->dtv_property_cache.hierarchy = fe->dtv_property_cache.hierarchy;
-		state->fe[index_frontend]->dtv_property_cache.code_rate_HP = fe->dtv_property_cache.code_rate_HP;
-		state->fe[index_frontend]->dtv_property_cache.code_rate_LP = fe->dtv_property_cache.code_rate_LP;
-		state->fe[index_frontend]->dtv_property_cache.rolloff = fe->dtv_property_cache.rolloff;
-	}
-	ret = 0;
-
-return_value:
-	if (state->get_frontend_internal == 0)
-		mutex_unlock(&state->demod_lock);
-	return ret;
-}
-
-static int dib9000_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state)
-{
-	struct dib9000_state *state = fe->demodulator_priv;
-	state->tune_state = tune_state;
-	if (tune_state == CT_DEMOD_START)
-		state->status = FE_STATUS_TUNE_PENDING;
-
-	return 0;
-}
-
-static u32 dib9000_get_status(struct dvb_frontend *fe)
-{
-	struct dib9000_state *state = fe->demodulator_priv;
-	return state->status;
-}
-
-static int dib9000_set_channel_status(struct dvb_frontend *fe, struct dvb_frontend_parametersContext *channel_status)
-{
-	struct dib9000_state *state = fe->demodulator_priv;
-
-	memcpy(&state->channel_status, channel_status, sizeof(struct dvb_frontend_parametersContext));
-	return 0;
-}
-
-static int dib9000_set_frontend(struct dvb_frontend *fe)
-{
-	struct dib9000_state *state = fe->demodulator_priv;
-	int sleep_time, sleep_time_slave;
-	u32 frontend_status;
-	u8 nbr_pending, exit_condition, index_frontend, index_frontend_success;
-	struct dvb_frontend_parametersContext channel_status;
-
-	/* check that the correct parameters are set */
-	if (state->fe[0]->dtv_property_cache.frequency == 0) {
-		dprintk("dib9000: must specify frequency ");
-		return 0;
-	}
-
-	if (state->fe[0]->dtv_property_cache.bandwidth_hz == 0) {
-		dprintk("dib9000: must specify bandwidth ");
-		return 0;
-	}
-
-	state->pid_ctrl_index = -1; /* postpone the pid filtering cmd */
-	if (mutex_lock_interruptible(&state->demod_lock) < 0) {
-		dprintk("could not get the lock");
-		return 0;
-	}
-
-	fe->dtv_property_cache.delivery_system = SYS_DVBT;
-
-	/* set the master status */
-	if (state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_AUTO ||
-	    state->fe[0]->dtv_property_cache.guard_interval == GUARD_INTERVAL_AUTO ||
-	    state->fe[0]->dtv_property_cache.modulation == QAM_AUTO ||
-	    state->fe[0]->dtv_property_cache.code_rate_HP == FEC_AUTO) {
-		/* no channel specified, autosearch the channel */
-		state->channel_status.status = CHANNEL_STATUS_PARAMETERS_UNKNOWN;
-	} else
-		state->channel_status.status = CHANNEL_STATUS_PARAMETERS_SET;
-
-	/* set mode and status for the different frontends */
-	for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
-		dib9000_fw_set_diversity_in(state->fe[index_frontend], 1);
-
-		/* synchronization of the cache */
-		memcpy(&state->fe[index_frontend]->dtv_property_cache, &fe->dtv_property_cache, sizeof(struct dtv_frontend_properties));
-
-		state->fe[index_frontend]->dtv_property_cache.delivery_system = SYS_DVBT;
-		dib9000_fw_set_output_mode(state->fe[index_frontend], OUTMODE_HIGH_Z);
-
-		dib9000_set_channel_status(state->fe[index_frontend], &state->channel_status);
-		dib9000_set_tune_state(state->fe[index_frontend], CT_DEMOD_START);
-	}
-
-	/* actual tune */
-	exit_condition = 0;	/* 0: tune pending; 1: tune failed; 2:tune success */
-	index_frontend_success = 0;
-	do {
-		sleep_time = dib9000_fw_tune(state->fe[0]);
-		for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
-			sleep_time_slave = dib9000_fw_tune(state->fe[index_frontend]);
-			if (sleep_time == FE_CALLBACK_TIME_NEVER)
-				sleep_time = sleep_time_slave;
-			else if ((sleep_time_slave != FE_CALLBACK_TIME_NEVER) && (sleep_time_slave > sleep_time))
-				sleep_time = sleep_time_slave;
-		}
-		if (sleep_time != FE_CALLBACK_TIME_NEVER)
-			msleep(sleep_time / 10);
-		else
-			break;
-
-		nbr_pending = 0;
-		exit_condition = 0;
-		index_frontend_success = 0;
-		for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
-			frontend_status = -dib9000_get_status(state->fe[index_frontend]);
-			if (frontend_status > -FE_STATUS_TUNE_PENDING) {
-				exit_condition = 2;	/* tune success */
-				index_frontend_success = index_frontend;
-				break;
-			}
-			if (frontend_status == -FE_STATUS_TUNE_PENDING)
-				nbr_pending++;	/* some frontends are still tuning */
-		}
-		if ((exit_condition != 2) && (nbr_pending == 0))
-			exit_condition = 1;	/* if all tune are done and no success, exit: tune failed */
-
-	} while (exit_condition == 0);
-
-	/* check the tune result */
-	if (exit_condition == 1) {	/* tune failed */
-		dprintk("tune failed");
-		mutex_unlock(&state->demod_lock);
-		/* tune failed; put all the pid filtering cmd to junk */
-		state->pid_ctrl_index = -1;
-		return 0;
-	}
-
-	dprintk("tune success on frontend%i", index_frontend_success);
-
-	/* synchronize all the channel cache */
-	state->get_frontend_internal = 1;
-	dib9000_get_frontend(state->fe[0]);
-	state->get_frontend_internal = 0;
-
-	/* retune the other frontends with the found channel */
-	channel_status.status = CHANNEL_STATUS_PARAMETERS_SET;
-	for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
-		/* only retune the frontends which was not tuned success */
-		if (index_frontend != index_frontend_success) {
-			dib9000_set_channel_status(state->fe[index_frontend], &channel_status);
-			dib9000_set_tune_state(state->fe[index_frontend], CT_DEMOD_START);
-		}
-	}
-	do {
-		sleep_time = FE_CALLBACK_TIME_NEVER;
-		for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
-			if (index_frontend != index_frontend_success) {
-				sleep_time_slave = dib9000_fw_tune(state->fe[index_frontend]);
-				if (sleep_time == FE_CALLBACK_TIME_NEVER)
-					sleep_time = sleep_time_slave;
-				else if ((sleep_time_slave != FE_CALLBACK_TIME_NEVER) && (sleep_time_slave > sleep_time))
-					sleep_time = sleep_time_slave;
-			}
-		}
-		if (sleep_time != FE_CALLBACK_TIME_NEVER)
-			msleep(sleep_time / 10);
-		else
-			break;
-
-		nbr_pending = 0;
-		for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
-			if (index_frontend != index_frontend_success) {
-				frontend_status = -dib9000_get_status(state->fe[index_frontend]);
-				if ((index_frontend != index_frontend_success) && (frontend_status == -FE_STATUS_TUNE_PENDING))
-					nbr_pending++;	/* some frontends are still tuning */
-			}
-		}
-	} while (nbr_pending != 0);
-
-	/* set the output mode */
-	dib9000_fw_set_output_mode(state->fe[0], state->chip.d9.cfg.output_mode);
-	for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++)
-		dib9000_fw_set_output_mode(state->fe[index_frontend], OUTMODE_DIVERSITY);
-
-	/* turn off the diversity for the last frontend */
-	dib9000_fw_set_diversity_in(state->fe[index_frontend - 1], 0);
-
-	mutex_unlock(&state->demod_lock);
-	if (state->pid_ctrl_index >= 0) {
-		u8 index_pid_filter_cmd;
-		u8 pid_ctrl_index = state->pid_ctrl_index;
-
-		state->pid_ctrl_index = -2;
-		for (index_pid_filter_cmd = 0;
-				index_pid_filter_cmd <= pid_ctrl_index;
-				index_pid_filter_cmd++) {
-			if (state->pid_ctrl[index_pid_filter_cmd].cmd == DIB9000_PID_FILTER_CTRL)
-				dib9000_fw_pid_filter_ctrl(state->fe[0],
-						state->pid_ctrl[index_pid_filter_cmd].onoff);
-			else if (state->pid_ctrl[index_pid_filter_cmd].cmd == DIB9000_PID_FILTER)
-				dib9000_fw_pid_filter(state->fe[0],
-						state->pid_ctrl[index_pid_filter_cmd].id,
-						state->pid_ctrl[index_pid_filter_cmd].pid,
-						state->pid_ctrl[index_pid_filter_cmd].onoff);
-		}
-	}
-	/* do not postpone any more the pid filtering */
-	state->pid_ctrl_index = -2;
-
-	return 0;
-}
-
-static u16 dib9000_read_lock(struct dvb_frontend *fe)
-{
-	struct dib9000_state *state = fe->demodulator_priv;
-
-	return dib9000_read_word(state, 535);
-}
-
-static int dib9000_read_status(struct dvb_frontend *fe, fe_status_t * stat)
-{
-	struct dib9000_state *state = fe->demodulator_priv;
-	u8 index_frontend;
-	u16 lock = 0, lock_slave = 0;
-
-	if (mutex_lock_interruptible(&state->demod_lock) < 0) {
-		dprintk("could not get the lock");
-		return -EINTR;
-	}
-	for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++)
-		lock_slave |= dib9000_read_lock(state->fe[index_frontend]);
-
-	lock = dib9000_read_word(state, 535);
-
-	*stat = 0;
-
-	if ((lock & 0x8000) || (lock_slave & 0x8000))
-		*stat |= FE_HAS_SIGNAL;
-	if ((lock & 0x3000) || (lock_slave & 0x3000))
-		*stat |= FE_HAS_CARRIER;
-	if ((lock & 0x0100) || (lock_slave & 0x0100))
-		*stat |= FE_HAS_VITERBI;
-	if (((lock & 0x0038) == 0x38) || ((lock_slave & 0x0038) == 0x38))
-		*stat |= FE_HAS_SYNC;
-	if ((lock & 0x0008) || (lock_slave & 0x0008))
-		*stat |= FE_HAS_LOCK;
-
-	mutex_unlock(&state->demod_lock);
-
-	return 0;
-}
-
-static int dib9000_read_ber(struct dvb_frontend *fe, u32 * ber)
-{
-	struct dib9000_state *state = fe->demodulator_priv;
-	u16 *c;
-	int ret = 0;
-
-	if (mutex_lock_interruptible(&state->demod_lock) < 0) {
-		dprintk("could not get the lock");
-		return -EINTR;
-	}
-	if (mutex_lock_interruptible(&state->platform.risc.mem_mbx_lock) < 0) {
-		dprintk("could not get the lock");
-		ret = -EINTR;
-		goto error;
-	}
-	if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) {
-		mutex_unlock(&state->platform.risc.mem_mbx_lock);
-		ret = -EIO;
-		goto error;
-	}
-	dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR,
-			state->i2c_read_buffer, 16 * 2);
-	mutex_unlock(&state->platform.risc.mem_mbx_lock);
-
-	c = (u16 *)state->i2c_read_buffer;
-
-	*ber = c[10] << 16 | c[11];
-
-error:
-	mutex_unlock(&state->demod_lock);
-	return ret;
-}
-
-static int dib9000_read_signal_strength(struct dvb_frontend *fe, u16 * strength)
-{
-	struct dib9000_state *state = fe->demodulator_priv;
-	u8 index_frontend;
-	u16 *c = (u16 *)state->i2c_read_buffer;
-	u16 val;
-	int ret = 0;
-
-	if (mutex_lock_interruptible(&state->demod_lock) < 0) {
-		dprintk("could not get the lock");
-		return -EINTR;
-	}
-	*strength = 0;
-	for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
-		state->fe[index_frontend]->ops.read_signal_strength(state->fe[index_frontend], &val);
-		if (val > 65535 - *strength)
-			*strength = 65535;
-		else
-			*strength += val;
-	}
-
-	if (mutex_lock_interruptible(&state->platform.risc.mem_mbx_lock) < 0) {
-		dprintk("could not get the lock");
-		ret = -EINTR;
-		goto error;
-	}
-	if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) {
-		mutex_unlock(&state->platform.risc.mem_mbx_lock);
-		ret = -EIO;
-		goto error;
-	}
-	dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2);
-	mutex_unlock(&state->platform.risc.mem_mbx_lock);
-
-	val = 65535 - c[4];
-	if (val > 65535 - *strength)
-		*strength = 65535;
-	else
-		*strength += val;
-
-error:
-	mutex_unlock(&state->demod_lock);
-	return ret;
-}
-
-static u32 dib9000_get_snr(struct dvb_frontend *fe)
-{
-	struct dib9000_state *state = fe->demodulator_priv;
-	u16 *c = (u16 *)state->i2c_read_buffer;
-	u32 n, s, exp;
-	u16 val;
-
-	if (mutex_lock_interruptible(&state->platform.risc.mem_mbx_lock) < 0) {
-		dprintk("could not get the lock");
-		return 0;
-	}
-	if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) {
-		mutex_unlock(&state->platform.risc.mem_mbx_lock);
-		return 0;
-	}
-	dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2);
-	mutex_unlock(&state->platform.risc.mem_mbx_lock);
-
-	val = c[7];
-	n = (val >> 4) & 0xff;
-	exp = ((val & 0xf) << 2);
-	val = c[8];
-	exp += ((val >> 14) & 0x3);
-	if ((exp & 0x20) != 0)
-		exp -= 0x40;
-	n <<= exp + 16;
-
-	s = (val >> 6) & 0xFF;
-	exp = (val & 0x3F);
-	if ((exp & 0x20) != 0)
-		exp -= 0x40;
-	s <<= exp + 16;
-
-	if (n > 0) {
-		u32 t = (s / n) << 16;
-		return t + ((s << 16) - n * t) / n;
-	}
-	return 0xffffffff;
-}
-
-static int dib9000_read_snr(struct dvb_frontend *fe, u16 * snr)
-{
-	struct dib9000_state *state = fe->demodulator_priv;
-	u8 index_frontend;
-	u32 snr_master;
-
-	if (mutex_lock_interruptible(&state->demod_lock) < 0) {
-		dprintk("could not get the lock");
-		return -EINTR;
-	}
-	snr_master = dib9000_get_snr(fe);
-	for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++)
-		snr_master += dib9000_get_snr(state->fe[index_frontend]);
-
-	if ((snr_master >> 16) != 0) {
-		snr_master = 10 * intlog10(snr_master >> 16);
-		*snr = snr_master / ((1 << 24) / 10);
-	} else
-		*snr = 0;
-
-	mutex_unlock(&state->demod_lock);
-
-	return 0;
-}
-
-static int dib9000_read_unc_blocks(struct dvb_frontend *fe, u32 * unc)
-{
-	struct dib9000_state *state = fe->demodulator_priv;
-	u16 *c = (u16 *)state->i2c_read_buffer;
-	int ret = 0;
-
-	if (mutex_lock_interruptible(&state->demod_lock) < 0) {
-		dprintk("could not get the lock");
-		return -EINTR;
-	}
-	if (mutex_lock_interruptible(&state->platform.risc.mem_mbx_lock) < 0) {
-		dprintk("could not get the lock");
-		ret = -EINTR;
-		goto error;
-	}
-	if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) {
-		mutex_unlock(&state->platform.risc.mem_mbx_lock);
-		ret = -EIO;
-		goto error;
-	}
-	dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, 16 * 2);
-	mutex_unlock(&state->platform.risc.mem_mbx_lock);
-
-	*unc = c[12];
-
-error:
-	mutex_unlock(&state->demod_lock);
-	return ret;
-}
-
-int dib9000_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, u8 first_addr)
-{
-	int k = 0, ret = 0;
-	u8 new_addr = 0;
-	struct i2c_device client = {.i2c_adap = i2c };
-
-	client.i2c_write_buffer = kzalloc(4 * sizeof(u8), GFP_KERNEL);
-	if (!client.i2c_write_buffer) {
-		dprintk("%s: not enough memory", __func__);
-		return -ENOMEM;
-	}
-	client.i2c_read_buffer = kzalloc(4 * sizeof(u8), GFP_KERNEL);
-	if (!client.i2c_read_buffer) {
-		dprintk("%s: not enough memory", __func__);
-		ret = -ENOMEM;
-		goto error_memory;
-	}
-
-	client.i2c_addr = default_addr + 16;
-	dib9000_i2c_write16(&client, 1796, 0x0);
-
-	for (k = no_of_demods - 1; k >= 0; k--) {
-		/* designated i2c address */
-		new_addr = first_addr + (k << 1);
-		client.i2c_addr = default_addr;
-
-		dib9000_i2c_write16(&client, 1817, 3);
-		dib9000_i2c_write16(&client, 1796, 0);
-		dib9000_i2c_write16(&client, 1227, 1);
-		dib9000_i2c_write16(&client, 1227, 0);
-
-		client.i2c_addr = new_addr;
-		dib9000_i2c_write16(&client, 1817, 3);
-		dib9000_i2c_write16(&client, 1796, 0);
-		dib9000_i2c_write16(&client, 1227, 1);
-		dib9000_i2c_write16(&client, 1227, 0);
-
-		if (dib9000_identify(&client) == 0) {
-			client.i2c_addr = default_addr;
-			if (dib9000_identify(&client) == 0) {
-				dprintk("DiB9000 #%d: not identified", k);
-				ret = -EIO;
-				goto error;
-			}
-		}
-
-		dib9000_i2c_write16(&client, 1795, (1 << 10) | (4 << 6));
-		dib9000_i2c_write16(&client, 1794, (new_addr << 2) | 2);
-
-		dprintk("IC %d initialized (to i2c_address 0x%x)", k, new_addr);
-	}
-
-	for (k = 0; k < no_of_demods; k++) {
-		new_addr = first_addr | (k << 1);
-		client.i2c_addr = new_addr;
-
-		dib9000_i2c_write16(&client, 1794, (new_addr << 2));
-		dib9000_i2c_write16(&client, 1795, 0);
-	}
-
-error:
-	kfree(client.i2c_read_buffer);
-error_memory:
-	kfree(client.i2c_write_buffer);
-
-	return ret;
-}
-EXPORT_SYMBOL(dib9000_i2c_enumeration);
-
-int dib9000_set_slave_frontend(struct dvb_frontend *fe, struct dvb_frontend *fe_slave)
-{
-	struct dib9000_state *state = fe->demodulator_priv;
-	u8 index_frontend = 1;
-
-	while ((index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL))
-		index_frontend++;
-	if (index_frontend < MAX_NUMBER_OF_FRONTENDS) {
-		dprintk("set slave fe %p to index %i", fe_slave, index_frontend);
-		state->fe[index_frontend] = fe_slave;
-		return 0;
-	}
-
-	dprintk("too many slave frontend");
-	return -ENOMEM;
-}
-EXPORT_SYMBOL(dib9000_set_slave_frontend);
-
-int dib9000_remove_slave_frontend(struct dvb_frontend *fe)
-{
-	struct dib9000_state *state = fe->demodulator_priv;
-	u8 index_frontend = 1;
-
-	while ((index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL))
-		index_frontend++;
-	if (index_frontend != 1) {
-		dprintk("remove slave fe %p (index %i)", state->fe[index_frontend - 1], index_frontend - 1);
-		state->fe[index_frontend] = NULL;
-		return 0;
-	}
-
-	dprintk("no frontend to be removed");
-	return -ENODEV;
-}
-EXPORT_SYMBOL(dib9000_remove_slave_frontend);
-
-struct dvb_frontend *dib9000_get_slave_frontend(struct dvb_frontend *fe, int slave_index)
-{
-	struct dib9000_state *state = fe->demodulator_priv;
-
-	if (slave_index >= MAX_NUMBER_OF_FRONTENDS)
-		return NULL;
-	return state->fe[slave_index];
-}
-EXPORT_SYMBOL(dib9000_get_slave_frontend);
-
-static struct dvb_frontend_ops dib9000_ops;
-struct dvb_frontend *dib9000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, const struct dib9000_config *cfg)
-{
-	struct dvb_frontend *fe;
-	struct dib9000_state *st;
-	st = kzalloc(sizeof(struct dib9000_state), GFP_KERNEL);
-	if (st == NULL)
-		return NULL;
-	fe = kzalloc(sizeof(struct dvb_frontend), GFP_KERNEL);
-	if (fe == NULL) {
-		kfree(st);
-		return NULL;
-	}
-
-	memcpy(&st->chip.d9.cfg, cfg, sizeof(struct dib9000_config));
-	st->i2c.i2c_adap = i2c_adap;
-	st->i2c.i2c_addr = i2c_addr;
-	st->i2c.i2c_write_buffer = st->i2c_write_buffer;
-	st->i2c.i2c_read_buffer = st->i2c_read_buffer;
-
-	st->gpio_dir = DIB9000_GPIO_DEFAULT_DIRECTIONS;
-	st->gpio_val = DIB9000_GPIO_DEFAULT_VALUES;
-	st->gpio_pwm_pos = DIB9000_GPIO_DEFAULT_PWM_POS;
-
-	mutex_init(&st->platform.risc.mbx_if_lock);
-	mutex_init(&st->platform.risc.mbx_lock);
-	mutex_init(&st->platform.risc.mem_lock);
-	mutex_init(&st->platform.risc.mem_mbx_lock);
-	mutex_init(&st->demod_lock);
-	st->get_frontend_internal = 0;
-
-	st->pid_ctrl_index = -2;
-
-	st->fe[0] = fe;
-	fe->demodulator_priv = st;
-	memcpy(&st->fe[0]->ops, &dib9000_ops, sizeof(struct dvb_frontend_ops));
-
-	/* Ensure the output mode remains at the previous default if it's
-	 * not specifically set by the caller.
-	 */
-	if ((st->chip.d9.cfg.output_mode != OUTMODE_MPEG2_SERIAL) && (st->chip.d9.cfg.output_mode != OUTMODE_MPEG2_PAR_GATED_CLK))
-		st->chip.d9.cfg.output_mode = OUTMODE_MPEG2_FIFO;
-
-	if (dib9000_identify(&st->i2c) == 0)
-		goto error;
-
-	dibx000_init_i2c_master(&st->i2c_master, DIB7000MC, st->i2c.i2c_adap, st->i2c.i2c_addr);
-
-	st->tuner_adap.dev.parent = i2c_adap->dev.parent;
-	strncpy(st->tuner_adap.name, "DIB9000_FW TUNER ACCESS", sizeof(st->tuner_adap.name));
-	st->tuner_adap.algo = &dib9000_tuner_algo;
-	st->tuner_adap.algo_data = NULL;
-	i2c_set_adapdata(&st->tuner_adap, st);
-	if (i2c_add_adapter(&st->tuner_adap) < 0)
-		goto error;
-
-	st->component_bus.dev.parent = i2c_adap->dev.parent;
-	strncpy(st->component_bus.name, "DIB9000_FW COMPONENT BUS ACCESS", sizeof(st->component_bus.name));
-	st->component_bus.algo = &dib9000_component_bus_algo;
-	st->component_bus.algo_data = NULL;
-	st->component_bus_speed = 340;
-	i2c_set_adapdata(&st->component_bus, st);
-	if (i2c_add_adapter(&st->component_bus) < 0)
-		goto component_bus_add_error;
-
-	dib9000_fw_reset(fe);
-
-	return fe;
-
-component_bus_add_error:
-	i2c_del_adapter(&st->tuner_adap);
-error:
-	kfree(st);
-	return NULL;
-}
-EXPORT_SYMBOL(dib9000_attach);
-
-static struct dvb_frontend_ops dib9000_ops = {
-	.delsys = { SYS_DVBT },
-	.info = {
-		 .name = "DiBcom 9000",
-		 .frequency_min = 44250000,
-		 .frequency_max = 867250000,
-		 .frequency_stepsize = 62500,
-		 .caps = FE_CAN_INVERSION_AUTO |
-		 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_FEC_AUTO |
-		 FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
-		 FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_RECOVER | FE_CAN_HIERARCHY_AUTO,
-		 },
-
-	.release = dib9000_release,
-
-	.init = dib9000_wakeup,
-	.sleep = dib9000_sleep,
-
-	.set_frontend = dib9000_set_frontend,
-	.get_tune_settings = dib9000_fe_get_tune_settings,
-	.get_frontend = dib9000_get_frontend,
-
-	.read_status = dib9000_read_status,
-	.read_ber = dib9000_read_ber,
-	.read_signal_strength = dib9000_read_signal_strength,
-	.read_snr = dib9000_read_snr,
-	.read_ucblocks = dib9000_read_unc_blocks,
-};
-
-MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
-MODULE_AUTHOR("Olivier Grenie <ogrenie@dibcom.fr>");
-MODULE_DESCRIPTION("Driver for the DiBcom 9000 COFDM demodulator");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/dib9000.h b/drivers/media/dvb/frontends/dib9000.h
deleted file mode 100644
index b5781a4..0000000
--- a/drivers/media/dvb/frontends/dib9000.h
+++ /dev/null
@@ -1,131 +0,0 @@
-#ifndef DIB9000_H
-#define DIB9000_H
-
-#include "dibx000_common.h"
-
-struct dib9000_config {
-	u8 dvbt_mode;
-	u8 output_mpeg2_in_188_bytes;
-	u8 hostbus_diversity;
-	struct dibx000_bandwidth_config *bw;
-
-	u16 if_drives;
-
-	u32 timing_frequency;
-	u32 xtal_clock_khz;
-	u32 vcxo_timer;
-	u32 demod_clock_khz;
-
-	const u8 *microcode_B_fe_buffer;
-	u32 microcode_B_fe_size;
-
-	struct dibGPIOFunction gpio_function[2];
-	struct dibSubbandSelection subband;
-
-	u8 output_mode;
-};
-
-#define DEFAULT_DIB9000_I2C_ADDRESS 18
-
-#if defined(CONFIG_DVB_DIB9000) || (defined(CONFIG_DVB_DIB9000_MODULE) && defined(MODULE))
-extern struct dvb_frontend *dib9000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, const struct dib9000_config *cfg);
-extern int dib9000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 default_addr, u8 first_addr);
-extern struct i2c_adapter *dib9000_get_tuner_interface(struct dvb_frontend *fe);
-extern struct i2c_adapter *dib9000_get_i2c_master(struct dvb_frontend *fe, enum dibx000_i2c_interface intf, int gating);
-extern int dib9000_set_gpio(struct dvb_frontend *fe, u8 num, u8 dir, u8 val);
-extern int dib9000_fw_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff);
-extern int dib9000_fw_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff);
-extern int dib9000_firmware_post_pll_init(struct dvb_frontend *fe);
-extern int dib9000_set_slave_frontend(struct dvb_frontend *fe, struct dvb_frontend *fe_slave);
-extern int dib9000_remove_slave_frontend(struct dvb_frontend *fe);
-extern struct dvb_frontend *dib9000_get_slave_frontend(struct dvb_frontend *fe, int slave_index);
-extern struct i2c_adapter *dib9000_get_component_bus_interface(struct dvb_frontend *fe);
-extern int dib9000_set_i2c_adapter(struct dvb_frontend *fe, struct i2c_adapter *i2c);
-extern int dib9000_fw_set_component_bus_speed(struct dvb_frontend *fe, u16 speed);
-#else
-static inline struct dvb_frontend *dib9000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib9000_config *cfg)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-
-static inline struct i2c_adapter *dib9000_get_i2c_master(struct dvb_frontend *fe, enum dibx000_i2c_interface intf, int gating)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-
-static inline int dib9000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 default_addr, u8 first_addr)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return -ENODEV;
-}
-
-static inline struct i2c_adapter *dib9000_get_tuner_interface(struct dvb_frontend *fe)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-
-static inline int dib9000_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 dib9000_fw_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return -ENODEV;
-}
-
-static inline int dib9000_fw_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return -ENODEV;
-}
-
-static inline int dib9000_firmware_post_pll_init(struct dvb_frontend *fe)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return -ENODEV;
-}
-
-static inline int dib9000_set_slave_frontend(struct dvb_frontend *fe, struct dvb_frontend *fe_slave)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return -ENODEV;
-}
-
-int dib9000_remove_slave_frontend(struct dvb_frontend *fe)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return -ENODEV;
-}
-
-static inline struct dvb_frontend *dib9000_get_slave_frontend(struct dvb_frontend *fe, int slave_index)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-
-static inline struct i2c_adapter *dib9000_get_component_bus_interface(struct dvb_frontend *fe)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-
-static inline int dib9000_set_i2c_adapter(struct dvb_frontend *fe, struct i2c_adapter *i2c)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return -ENODEV;
-}
-
-static inline int dib9000_fw_set_component_bus_speed(struct dvb_frontend *fe, u16 speed)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return -ENODEV;
-}
-#endif
-
-#endif
diff --git a/drivers/media/dvb/frontends/dibx000_common.c b/drivers/media/dvb/frontends/dibx000_common.c
deleted file mode 100644
index 43be723..0000000
--- a/drivers/media/dvb/frontends/dibx000_common.c
+++ /dev/null
@@ -1,515 +0,0 @@
-#include <linux/i2c.h>
-#include <linux/mutex.h>
-#include <linux/module.h>
-
-#include "dibx000_common.h"
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
-
-#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiBX000: "); printk(args); printk("\n"); } } while (0)
-
-static int dibx000_write_word(struct dibx000_i2c_master *mst, u16 reg, u16 val)
-{
-	int ret;
-
-	if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) {
-		dprintk("could not acquire lock");
-		return -EINVAL;
-	}
-
-	mst->i2c_write_buffer[0] = (reg >> 8) & 0xff;
-	mst->i2c_write_buffer[1] = reg & 0xff;
-	mst->i2c_write_buffer[2] = (val >> 8) & 0xff;
-	mst->i2c_write_buffer[3] = val & 0xff;
-
-	memset(mst->msg, 0, sizeof(struct i2c_msg));
-	mst->msg[0].addr = mst->i2c_addr;
-	mst->msg[0].flags = 0;
-	mst->msg[0].buf = mst->i2c_write_buffer;
-	mst->msg[0].len = 4;
-
-	ret = i2c_transfer(mst->i2c_adap, mst->msg, 1) != 1 ? -EREMOTEIO : 0;
-	mutex_unlock(&mst->i2c_buffer_lock);
-
-	return ret;
-}
-
-static u16 dibx000_read_word(struct dibx000_i2c_master *mst, u16 reg)
-{
-	u16 ret;
-
-	if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) {
-		dprintk("could not acquire lock");
-		return 0;
-	}
-
-	mst->i2c_write_buffer[0] = reg >> 8;
-	mst->i2c_write_buffer[1] = reg & 0xff;
-
-	memset(mst->msg, 0, 2 * sizeof(struct i2c_msg));
-	mst->msg[0].addr = mst->i2c_addr;
-	mst->msg[0].flags = 0;
-	mst->msg[0].buf = mst->i2c_write_buffer;
-	mst->msg[0].len = 2;
-	mst->msg[1].addr = mst->i2c_addr;
-	mst->msg[1].flags = I2C_M_RD;
-	mst->msg[1].buf = mst->i2c_read_buffer;
-	mst->msg[1].len = 2;
-
-	if (i2c_transfer(mst->i2c_adap, mst->msg, 2) != 2)
-		dprintk("i2c read error on %d", reg);
-
-	ret = (mst->i2c_read_buffer[0] << 8) | mst->i2c_read_buffer[1];
-	mutex_unlock(&mst->i2c_buffer_lock);
-
-	return ret;
-}
-
-static int dibx000_is_i2c_done(struct dibx000_i2c_master *mst)
-{
-	int i = 100;
-	u16 status;
-
-	while (((status = dibx000_read_word(mst, mst->base_reg + 2)) & 0x0100) == 0 && --i > 0)
-		;
-
-	/* i2c timed out */
-	if (i == 0)
-		return -EREMOTEIO;
-
-	/* no acknowledge */
-	if ((status & 0x0080) == 0)
-		return -EREMOTEIO;
-
-	return 0;
-}
-
-static int dibx000_master_i2c_write(struct dibx000_i2c_master *mst, struct i2c_msg *msg, u8 stop)
-{
-	u16 data;
-	u16 da;
-	u16 i;
-	u16 txlen = msg->len, len;
-	const u8 *b = msg->buf;
-
-	while (txlen) {
-		dibx000_read_word(mst, mst->base_reg + 2);
-
-		len = txlen > 8 ? 8 : txlen;
-		for (i = 0; i < len; i += 2) {
-			data = *b++ << 8;
-			if (i+1 < len)
-				data |= *b++;
-			dibx000_write_word(mst, mst->base_reg, data);
-		}
-		da = (((u8) (msg->addr))  << 9) |
-			(1           << 8) |
-			(1           << 7) |
-			(0           << 6) |
-			(0           << 5) |
-			((len & 0x7) << 2) |
-			(0           << 1) |
-			(0           << 0);
-
-		if (txlen == msg->len)
-			da |= 1 << 5; /* start */
-
-		if (txlen-len == 0 && stop)
-			da |= 1 << 6; /* stop */
-
-		dibx000_write_word(mst, mst->base_reg+1, da);
-
-		if (dibx000_is_i2c_done(mst) != 0)
-			return -EREMOTEIO;
-		txlen -= len;
-	}
-
-	return 0;
-}
-
-static int dibx000_master_i2c_read(struct dibx000_i2c_master *mst, struct i2c_msg *msg)
-{
-	u16 da;
-	u8 *b = msg->buf;
-	u16 rxlen = msg->len, len;
-
-	while (rxlen) {
-		len = rxlen > 8 ? 8 : rxlen;
-		da = (((u8) (msg->addr)) << 9) |
-			(1           << 8) |
-			(1           << 7) |
-			(0           << 6) |
-			(0           << 5) |
-			((len & 0x7) << 2) |
-			(1           << 1) |
-			(0           << 0);
-
-		if (rxlen == msg->len)
-			da |= 1 << 5; /* start */
-
-		if (rxlen-len == 0)
-			da |= 1 << 6; /* stop */
-		dibx000_write_word(mst, mst->base_reg+1, da);
-
-		if (dibx000_is_i2c_done(mst) != 0)
-			return -EREMOTEIO;
-
-		rxlen -= len;
-
-		while (len) {
-			da = dibx000_read_word(mst, mst->base_reg);
-			*b++ = (da >> 8) & 0xff;
-			len--;
-			if (len >= 1) {
-				*b++ =  da   & 0xff;
-				len--;
-			}
-		}
-	}
-
-	return 0;
-}
-
-int dibx000_i2c_set_speed(struct i2c_adapter *i2c_adap, u16 speed)
-{
-	struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap);
-
-	if (mst->device_rev < DIB7000MC && speed < 235)
-		speed = 235;
-	return dibx000_write_word(mst, mst->base_reg + 3, (u16)(60000 / speed));
-
-}
-EXPORT_SYMBOL(dibx000_i2c_set_speed);
-
-static u32 dibx000_i2c_func(struct i2c_adapter *adapter)
-{
-	return I2C_FUNC_I2C;
-}
-
-static int dibx000_i2c_select_interface(struct dibx000_i2c_master *mst,
-					enum dibx000_i2c_interface intf)
-{
-	if (mst->device_rev > DIB3000MC && mst->selected_interface != intf) {
-		dprintk("selecting interface: %d", intf);
-		mst->selected_interface = intf;
-		return dibx000_write_word(mst, mst->base_reg + 4, intf);
-	}
-	return 0;
-}
-
-static int dibx000_i2c_master_xfer_gpio12(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)
-{
-	struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap);
-	int msg_index;
-	int ret = 0;
-
-	dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_GPIO_1_2);
-	for (msg_index = 0; msg_index < num; msg_index++) {
-		if (msg[msg_index].flags & I2C_M_RD) {
-			ret = dibx000_master_i2c_read(mst, &msg[msg_index]);
-			if (ret != 0)
-				return 0;
-		} else {
-			ret = dibx000_master_i2c_write(mst, &msg[msg_index], 1);
-			if (ret != 0)
-				return 0;
-		}
-	}
-
-	return num;
-}
-
-static int dibx000_i2c_master_xfer_gpio34(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)
-{
-	struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap);
-	int msg_index;
-	int ret = 0;
-
-	dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_GPIO_3_4);
-	for (msg_index = 0; msg_index < num; msg_index++) {
-		if (msg[msg_index].flags & I2C_M_RD) {
-			ret = dibx000_master_i2c_read(mst, &msg[msg_index]);
-			if (ret != 0)
-				return 0;
-		} else {
-			ret = dibx000_master_i2c_write(mst, &msg[msg_index], 1);
-			if (ret != 0)
-				return 0;
-		}
-	}
-
-	return num;
-}
-
-static struct i2c_algorithm dibx000_i2c_master_gpio12_xfer_algo = {
-	.master_xfer = dibx000_i2c_master_xfer_gpio12,
-	.functionality = dibx000_i2c_func,
-};
-
-static struct i2c_algorithm dibx000_i2c_master_gpio34_xfer_algo = {
-	.master_xfer = dibx000_i2c_master_xfer_gpio34,
-	.functionality = dibx000_i2c_func,
-};
-
-static int dibx000_i2c_gate_ctrl(struct dibx000_i2c_master *mst, u8 tx[4],
-				 u8 addr, int onoff)
-{
-	u16 val;
-
-
-	if (onoff)
-		val = addr << 8;	// bit 7 = use master or not, if 0, the gate is open
-	else
-		val = 1 << 7;
-
-	if (mst->device_rev > DIB7000)
-		val <<= 1;
-
-	tx[0] = (((mst->base_reg + 1) >> 8) & 0xff);
-	tx[1] = ((mst->base_reg + 1) & 0xff);
-	tx[2] = val >> 8;
-	tx[3] = val & 0xff;
-
-	return 0;
-}
-
-static int dibx000_i2c_gated_gpio67_xfer(struct i2c_adapter *i2c_adap,
-					struct i2c_msg msg[], int num)
-{
-	struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap);
-	int ret;
-
-	if (num > 32) {
-		dprintk("%s: too much I2C message to be transmitted (%i).\
-				Maximum is 32", __func__, num);
-		return -ENOMEM;
-	}
-
-	dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_GPIO_6_7);
-
-	if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) {
-		dprintk("could not acquire lock");
-		return -EINVAL;
-	}
-
-	memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num));
-
-	/* open the gate */
-	dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[0], msg[0].addr, 1);
-	mst->msg[0].addr = mst->i2c_addr;
-	mst->msg[0].buf = &mst->i2c_write_buffer[0];
-	mst->msg[0].len = 4;
-
-	memcpy(&mst->msg[1], msg, sizeof(struct i2c_msg) * num);
-
-	/* close the gate */
-	dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[4], 0, 0);
-	mst->msg[num + 1].addr = mst->i2c_addr;
-	mst->msg[num + 1].buf = &mst->i2c_write_buffer[4];
-	mst->msg[num + 1].len = 4;
-
-	ret = (i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ?
-			num : -EIO);
-
-	mutex_unlock(&mst->i2c_buffer_lock);
-	return ret;
-}
-
-static struct i2c_algorithm dibx000_i2c_gated_gpio67_algo = {
-	.master_xfer = dibx000_i2c_gated_gpio67_xfer,
-	.functionality = dibx000_i2c_func,
-};
-
-static int dibx000_i2c_gated_tuner_xfer(struct i2c_adapter *i2c_adap,
-					struct i2c_msg msg[], int num)
-{
-	struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap);
-	int ret;
-
-	if (num > 32) {
-		dprintk("%s: too much I2C message to be transmitted (%i).\
-				Maximum is 32", __func__, num);
-		return -ENOMEM;
-	}
-
-	dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_TUNER);
-
-	if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) {
-		dprintk("could not acquire lock");
-		return -EINVAL;
-	}
-	memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num));
-
-	/* open the gate */
-	dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[0], msg[0].addr, 1);
-	mst->msg[0].addr = mst->i2c_addr;
-	mst->msg[0].buf = &mst->i2c_write_buffer[0];
-	mst->msg[0].len = 4;
-
-	memcpy(&mst->msg[1], msg, sizeof(struct i2c_msg) * num);
-
-	/* close the gate */
-	dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[4], 0, 0);
-	mst->msg[num + 1].addr = mst->i2c_addr;
-	mst->msg[num + 1].buf = &mst->i2c_write_buffer[4];
-	mst->msg[num + 1].len = 4;
-
-	ret = (i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ?
-			num : -EIO);
-	mutex_unlock(&mst->i2c_buffer_lock);
-	return ret;
-}
-
-static struct i2c_algorithm dibx000_i2c_gated_tuner_algo = {
-	.master_xfer = dibx000_i2c_gated_tuner_xfer,
-	.functionality = dibx000_i2c_func,
-};
-
-struct i2c_adapter *dibx000_get_i2c_adapter(struct dibx000_i2c_master *mst,
-						enum dibx000_i2c_interface intf,
-						int gating)
-{
-	struct i2c_adapter *i2c = NULL;
-
-	switch (intf) {
-	case DIBX000_I2C_INTERFACE_TUNER:
-		if (gating)
-			i2c = &mst->gated_tuner_i2c_adap;
-		break;
-	case DIBX000_I2C_INTERFACE_GPIO_1_2:
-		if (!gating)
-			i2c = &mst->master_i2c_adap_gpio12;
-		break;
-	case DIBX000_I2C_INTERFACE_GPIO_3_4:
-		if (!gating)
-			i2c = &mst->master_i2c_adap_gpio34;
-		break;
-	case DIBX000_I2C_INTERFACE_GPIO_6_7:
-		if (gating)
-			i2c = &mst->master_i2c_adap_gpio67;
-		break;
-	default:
-		printk(KERN_ERR "DiBX000: incorrect I2C interface selected\n");
-		break;
-	}
-
-	return i2c;
-}
-
-EXPORT_SYMBOL(dibx000_get_i2c_adapter);
-
-void dibx000_reset_i2c_master(struct dibx000_i2c_master *mst)
-{
-	/* initialize the i2c-master by closing the gate */
-	u8 tx[4];
-	struct i2c_msg m = {.addr = mst->i2c_addr,.buf = tx,.len = 4 };
-
-	dibx000_i2c_gate_ctrl(mst, tx, 0, 0);
-	i2c_transfer(mst->i2c_adap, &m, 1);
-	mst->selected_interface = 0xff;	// the first time force a select of the I2C
-	dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_TUNER);
-}
-
-EXPORT_SYMBOL(dibx000_reset_i2c_master);
-
-static int i2c_adapter_init(struct i2c_adapter *i2c_adap,
-				struct i2c_algorithm *algo, const char *name,
-				struct dibx000_i2c_master *mst)
-{
-	strncpy(i2c_adap->name, name, sizeof(i2c_adap->name));
-	i2c_adap->algo = algo;
-	i2c_adap->algo_data = NULL;
-	i2c_set_adapdata(i2c_adap, mst);
-	if (i2c_add_adapter(i2c_adap) < 0)
-		return -ENODEV;
-	return 0;
-}
-
-int dibx000_init_i2c_master(struct dibx000_i2c_master *mst, u16 device_rev,
-				struct i2c_adapter *i2c_adap, u8 i2c_addr)
-{
-	int ret;
-
-	mutex_init(&mst->i2c_buffer_lock);
-	if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) {
-		dprintk("could not acquire lock");
-		return -EINVAL;
-	}
-	memset(mst->msg, 0, sizeof(struct i2c_msg));
-	mst->msg[0].addr = i2c_addr >> 1;
-	mst->msg[0].flags = 0;
-	mst->msg[0].buf = mst->i2c_write_buffer;
-	mst->msg[0].len = 4;
-
-	mst->device_rev = device_rev;
-	mst->i2c_adap = i2c_adap;
-	mst->i2c_addr = i2c_addr >> 1;
-
-	if (device_rev == DIB7000P || device_rev == DIB8000)
-		mst->base_reg = 1024;
-	else
-		mst->base_reg = 768;
-
-	mst->gated_tuner_i2c_adap.dev.parent = mst->i2c_adap->dev.parent;
-	if (i2c_adapter_init
-			(&mst->gated_tuner_i2c_adap, &dibx000_i2c_gated_tuner_algo,
-			 "DiBX000 tuner I2C bus", mst) != 0)
-		printk(KERN_ERR
-				"DiBX000: could not initialize the tuner i2c_adapter\n");
-
-	mst->master_i2c_adap_gpio12.dev.parent = mst->i2c_adap->dev.parent;
-	if (i2c_adapter_init
-			(&mst->master_i2c_adap_gpio12, &dibx000_i2c_master_gpio12_xfer_algo,
-			 "DiBX000 master GPIO12 I2C bus", mst) != 0)
-		printk(KERN_ERR
-				"DiBX000: could not initialize the master i2c_adapter\n");
-
-	mst->master_i2c_adap_gpio34.dev.parent = mst->i2c_adap->dev.parent;
-	if (i2c_adapter_init
-			(&mst->master_i2c_adap_gpio34, &dibx000_i2c_master_gpio34_xfer_algo,
-			 "DiBX000 master GPIO34 I2C bus", mst) != 0)
-		printk(KERN_ERR
-				"DiBX000: could not initialize the master i2c_adapter\n");
-
-	mst->master_i2c_adap_gpio67.dev.parent = mst->i2c_adap->dev.parent;
-	if (i2c_adapter_init
-			(&mst->master_i2c_adap_gpio67, &dibx000_i2c_gated_gpio67_algo,
-			 "DiBX000 master GPIO67 I2C bus", mst) != 0)
-		printk(KERN_ERR
-				"DiBX000: could not initialize the master i2c_adapter\n");
-
-	/* initialize the i2c-master by closing the gate */
-	dibx000_i2c_gate_ctrl(mst, mst->i2c_write_buffer, 0, 0);
-
-	ret = (i2c_transfer(i2c_adap, mst->msg, 1) == 1);
-	mutex_unlock(&mst->i2c_buffer_lock);
-
-	return ret;
-}
-
-EXPORT_SYMBOL(dibx000_init_i2c_master);
-
-void dibx000_exit_i2c_master(struct dibx000_i2c_master *mst)
-{
-	i2c_del_adapter(&mst->gated_tuner_i2c_adap);
-	i2c_del_adapter(&mst->master_i2c_adap_gpio12);
-	i2c_del_adapter(&mst->master_i2c_adap_gpio34);
-	i2c_del_adapter(&mst->master_i2c_adap_gpio67);
-}
-EXPORT_SYMBOL(dibx000_exit_i2c_master);
-
-
-u32 systime(void)
-{
-	struct timespec t;
-
-	t = current_kernel_time();
-	return (t.tv_sec * 10000) + (t.tv_nsec / 100000);
-}
-EXPORT_SYMBOL(systime);
-
-MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
-MODULE_DESCRIPTION("Common function the DiBcom demodulator family");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/dibx000_common.h b/drivers/media/dvb/frontends/dibx000_common.h
deleted file mode 100644
index 5f48488..0000000
--- a/drivers/media/dvb/frontends/dibx000_common.h
+++ /dev/null
@@ -1,280 +0,0 @@
-#ifndef DIBX000_COMMON_H
-#define DIBX000_COMMON_H
-
-enum dibx000_i2c_interface {
-	DIBX000_I2C_INTERFACE_TUNER = 0,
-	DIBX000_I2C_INTERFACE_GPIO_1_2 = 1,
-	DIBX000_I2C_INTERFACE_GPIO_3_4 = 2,
-	DIBX000_I2C_INTERFACE_GPIO_6_7 = 3
-};
-
-struct dibx000_i2c_master {
-#define DIB3000MC 1
-#define DIB7000   2
-#define DIB7000P  11
-#define DIB7000MC 12
-#define DIB8000   13
-	u16 device_rev;
-
-	enum dibx000_i2c_interface selected_interface;
-
-/*	struct i2c_adapter  tuner_i2c_adap; */
-	struct i2c_adapter gated_tuner_i2c_adap;
-	struct i2c_adapter master_i2c_adap_gpio12;
-	struct i2c_adapter master_i2c_adap_gpio34;
-	struct i2c_adapter master_i2c_adap_gpio67;
-
-	struct i2c_adapter *i2c_adap;
-	u8 i2c_addr;
-
-	u16 base_reg;
-
-	/* for the I2C transfer */
-	struct i2c_msg msg[34];
-	u8 i2c_write_buffer[8];
-	u8 i2c_read_buffer[2];
-	struct mutex i2c_buffer_lock;
-};
-
-extern int dibx000_init_i2c_master(struct dibx000_i2c_master *mst,
-					u16 device_rev, struct i2c_adapter *i2c_adap,
-					u8 i2c_addr);
-extern struct i2c_adapter *dibx000_get_i2c_adapter(struct dibx000_i2c_master
-							*mst,
-							enum dibx000_i2c_interface
-							intf, int gating);
-extern void dibx000_exit_i2c_master(struct dibx000_i2c_master *mst);
-extern void dibx000_reset_i2c_master(struct dibx000_i2c_master *mst);
-extern int dibx000_i2c_set_speed(struct i2c_adapter *i2c_adap, u16 speed);
-
-extern u32 systime(void);
-
-#define BAND_LBAND 0x01
-#define BAND_UHF   0x02
-#define BAND_VHF   0x04
-#define BAND_SBAND 0x08
-#define BAND_FM	   0x10
-#define BAND_CBAND 0x20
-
-#define BAND_OF_FREQUENCY(freq_kHz) ((freq_kHz) <= 170000 ? BAND_CBAND : \
-									(freq_kHz) <= 115000 ? BAND_FM : \
-									(freq_kHz) <= 250000 ? BAND_VHF : \
-									(freq_kHz) <= 863000 ? BAND_UHF : \
-									(freq_kHz) <= 2000000 ? BAND_LBAND : BAND_SBAND )
-
-struct dibx000_agc_config {
-	/* defines the capabilities of this AGC-setting - using the BAND_-defines */
-	u8 band_caps;
-
-	u16 setup;
-
-	u16 inv_gain;
-	u16 time_stabiliz;
-
-	u8 alpha_level;
-	u16 thlock;
-
-	u8 wbd_inv;
-	u16 wbd_ref;
-	u8 wbd_sel;
-	u8 wbd_alpha;
-
-	u16 agc1_max;
-	u16 agc1_min;
-	u16 agc2_max;
-	u16 agc2_min;
-
-	u8 agc1_pt1;
-	u8 agc1_pt2;
-	u8 agc1_pt3;
-
-	u8 agc1_slope1;
-	u8 agc1_slope2;
-
-	u8 agc2_pt1;
-	u8 agc2_pt2;
-
-	u8 agc2_slope1;
-	u8 agc2_slope2;
-
-	u8 alpha_mant;
-	u8 alpha_exp;
-
-	u8 beta_mant;
-	u8 beta_exp;
-
-	u8 perform_agc_softsplit;
-
-	struct {
-		u16 min;
-		u16 max;
-		u16 min_thres;
-		u16 max_thres;
-	} split;
-};
-
-struct dibx000_bandwidth_config {
-	u32 internal;
-	u32 sampling;
-
-	u8 pll_prediv;
-	u8 pll_ratio;
-	u8 pll_range;
-	u8 pll_reset;
-	u8 pll_bypass;
-
-	u8 enable_refdiv;
-	u8 bypclk_div;
-	u8 IO_CLK_en_core;
-	u8 ADClkSrc;
-	u8 modulo;
-
-	u16 sad_cfg;
-
-	u32 ifreq;
-	u32 timf;
-
-	u32 xtal_hz;
-};
-
-enum dibx000_adc_states {
-	DIBX000_SLOW_ADC_ON = 0,
-	DIBX000_SLOW_ADC_OFF,
-	DIBX000_ADC_ON,
-	DIBX000_ADC_OFF,
-	DIBX000_VBG_ENABLE,
-	DIBX000_VBG_DISABLE,
-};
-
-#define BANDWIDTH_TO_KHZ(v)	((v) / 1000)
-#define BANDWIDTH_TO_HZ(v)	((v) * 1000)
-
-/* Chip output mode. */
-#define OUTMODE_HIGH_Z              0
-#define OUTMODE_MPEG2_PAR_GATED_CLK 1
-#define OUTMODE_MPEG2_PAR_CONT_CLK  2
-#define OUTMODE_MPEG2_SERIAL        7
-#define OUTMODE_DIVERSITY           4
-#define OUTMODE_MPEG2_FIFO          5
-#define OUTMODE_ANALOG_ADC          6
-
-#define INPUT_MODE_OFF                0x11
-#define INPUT_MODE_DIVERSITY          0x12
-#define INPUT_MODE_MPEG               0x13
-
-enum frontend_tune_state {
-	CT_TUNER_START = 10,
-	CT_TUNER_STEP_0,
-	CT_TUNER_STEP_1,
-	CT_TUNER_STEP_2,
-	CT_TUNER_STEP_3,
-	CT_TUNER_STEP_4,
-	CT_TUNER_STEP_5,
-	CT_TUNER_STEP_6,
-	CT_TUNER_STEP_7,
-	CT_TUNER_STOP,
-
-	CT_AGC_START = 20,
-	CT_AGC_STEP_0,
-	CT_AGC_STEP_1,
-	CT_AGC_STEP_2,
-	CT_AGC_STEP_3,
-	CT_AGC_STEP_4,
-	CT_AGC_STOP,
-
-	CT_DEMOD_START = 30,
-	CT_DEMOD_STEP_1,
-	CT_DEMOD_STEP_2,
-	CT_DEMOD_STEP_3,
-	CT_DEMOD_STEP_4,
-	CT_DEMOD_STEP_5,
-	CT_DEMOD_STEP_6,
-	CT_DEMOD_STEP_7,
-	CT_DEMOD_STEP_8,
-	CT_DEMOD_STEP_9,
-	CT_DEMOD_STEP_10,
-	CT_DEMOD_SEARCH_NEXT = 41,
-	CT_DEMOD_STEP_LOCKED,
-	CT_DEMOD_STOP,
-
-	CT_DONE = 100,
-	CT_SHUTDOWN,
-
-};
-
-struct dvb_frontend_parametersContext {
-#define CHANNEL_STATUS_PARAMETERS_UNKNOWN   0x01
-#define CHANNEL_STATUS_PARAMETERS_SET       0x02
-	u8 status;
-	u32 tune_time_estimation[2];
-	s32 tps_available;
-	u16 tps[9];
-};
-
-#define FE_STATUS_TUNE_FAILED          0
-#define FE_STATUS_TUNE_TIMED_OUT      -1
-#define FE_STATUS_TUNE_TIME_TOO_SHORT -2
-#define FE_STATUS_TUNE_PENDING        -3
-#define FE_STATUS_STD_SUCCESS         -4
-#define FE_STATUS_FFT_SUCCESS         -5
-#define FE_STATUS_DEMOD_SUCCESS       -6
-#define FE_STATUS_LOCKED              -7
-#define FE_STATUS_DATA_LOCKED         -8
-
-#define FE_CALLBACK_TIME_NEVER 0xffffffff
-
-#define ABS(x) ((x < 0) ? (-x) : (x))
-
-#define DATA_BUS_ACCESS_MODE_8BIT                 0x01
-#define DATA_BUS_ACCESS_MODE_16BIT                0x02
-#define DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT 0x10
-
-struct dibGPIOFunction {
-#define BOARD_GPIO_COMPONENT_BUS_ADAPTER 1
-#define BOARD_GPIO_COMPONENT_DEMOD       2
-	u8 component;
-
-#define BOARD_GPIO_FUNCTION_BOARD_ON      1
-#define BOARD_GPIO_FUNCTION_BOARD_OFF     2
-#define BOARD_GPIO_FUNCTION_COMPONENT_ON  3
-#define BOARD_GPIO_FUNCTION_COMPONENT_OFF 4
-#define BOARD_GPIO_FUNCTION_SUBBAND_PWM   5
-#define BOARD_GPIO_FUNCTION_SUBBAND_GPIO   6
-	u8 function;
-
-/* mask, direction and value are used specify which GPIO to change GPIO0
- * is LSB and possible GPIO31 is MSB.  The same bit-position as in the
- * mask is used for the direction and the value. Direction == 1 is OUT,
- * 0 == IN. For direction "OUT" value is either 1 or 0, for direction IN
- * value has no meaning.
- *
- * In case of BOARD_GPIO_FUNCTION_PWM mask is giving the GPIO to be
- * used to do the PWM. Direction gives the PWModulator to be used.
- * Value gives the PWM value in device-dependent scale.
- */
-	u32 mask;
-	u32 direction;
-	u32 value;
-};
-
-#define MAX_NB_SUBBANDS   8
-struct dibSubbandSelection {
-	u8  size; /* Actual number of subbands. */
-	struct {
-		u16 f_mhz;
-		struct dibGPIOFunction gpio;
-	} subband[MAX_NB_SUBBANDS];
-};
-
-#define DEMOD_TIMF_SET    0x00
-#define DEMOD_TIMF_GET    0x01
-#define DEMOD_TIMF_UPDATE 0x02
-
-#define MPEG_ON_DIBTX		1
-#define DIV_ON_DIBTX		2
-#define ADC_ON_DIBTX		3
-#define DEMOUT_ON_HOSTBUS	4
-#define DIBTX_ON_HOSTBUS	5
-#define MPEG_ON_HOSTBUS		6
-
-#endif
diff --git a/drivers/media/dvb/frontends/drxd.h b/drivers/media/dvb/frontends/drxd.h
deleted file mode 100644
index 216c8c3..0000000
--- a/drivers/media/dvb/frontends/drxd.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * drxd.h: DRXD DVB-T demodulator driver
- *
- * Copyright (C) 2005-2007 Micronas
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 only, as published by the Free Software Foundation.
- *
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#ifndef _DRXD_H_
-#define _DRXD_H_
-
-#include <linux/types.h>
-#include <linux/i2c.h>
-
-struct drxd_config {
-	u8 index;
-
-	u8 pll_address;
-	u8 pll_type;
-#define DRXD_PLL_NONE     0
-#define DRXD_PLL_DTT7520X 1
-#define DRXD_PLL_MT3X0823 2
-
-	u32 clock;
-	u8 insert_rs_byte;
-
-	u8 demod_address;
-	u8 demoda_address;
-	u8 demod_revision;
-
-	/* If the tuner is not behind an i2c gate, be sure to flip this bit
-	   or else the i2c bus could get wedged */
-	u8 disable_i2c_gate_ctrl;
-
-	u32 IF;
-	 s16(*osc_deviation) (void *priv, s16 dev, int flag);
-};
-
-#if defined(CONFIG_DVB_DRXD) || \
-			(defined(CONFIG_DVB_DRXD_MODULE) && defined(MODULE))
-extern
-struct dvb_frontend *drxd_attach(const struct drxd_config *config,
-				 void *priv, struct i2c_adapter *i2c,
-				 struct device *dev);
-#else
-static inline
-struct dvb_frontend *drxd_attach(const struct drxd_config *config,
-				 void *priv, struct i2c_adapter *i2c,
-				 struct device *dev)
-{
-	printk(KERN_INFO "%s: not probed - driver disabled by Kconfig\n",
-	       __func__);
-	return NULL;
-}
-#endif
-
-extern int drxd_config_i2c(struct dvb_frontend *, int);
-#endif
diff --git a/drivers/media/dvb/frontends/drxd_firm.c b/drivers/media/dvb/frontends/drxd_firm.c
deleted file mode 100644
index 5418b0b..0000000
--- a/drivers/media/dvb/frontends/drxd_firm.c
+++ /dev/null
@@ -1,929 +0,0 @@
-/*
- * drxd_firm.c : DRXD firmware tables
- *
- * Copyright (C) 2006-2007 Micronas
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 only, as published by the Free Software Foundation.
- *
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-/* TODO: generate this file with a script from a settings file */
-
-/* Contains A2 firmware version: 1.4.2
- * Contains B1 firmware version: 3.3.33
- * Contains settings from driver 1.4.23
-*/
-
-#include "drxd_firm.h"
-
-#define ADDRESS(x)     ((x) & 0xFF), (((x)>>8) & 0xFF), (((x)>>16) & 0xFF), (((x)>>24) & 0xFF)
-#define LENGTH(x)      ((x) & 0xFF), (((x)>>8) & 0xFF)
-
-/* Is written via block write, must be little endian */
-#define DATA16(x)      ((x) & 0xFF), (((x)>>8) & 0xFF)
-
-#define WRBLOCK(a, l) ADDRESS(a), LENGTH(l)
-#define WR16(a, d) ADDRESS(a), LENGTH(1), DATA16(d)
-
-#define END_OF_TABLE      0xFF, 0xFF, 0xFF, 0xFF
-
-/* HI firmware patches */
-
-#define HI_TR_FUNC_ADDR HI_IF_RAM_USR_BEGIN__A
-#define HI_TR_FUNC_SIZE 9	/* size of this function in instruction words */
-
-u8 DRXD_InitAtomicRead[] = {
-	WRBLOCK(HI_TR_FUNC_ADDR, HI_TR_FUNC_SIZE),
-	0x26, 0x00,		/* 0         -> ring.rdy;           */
-	0x60, 0x04,		/* r0rami.dt -> ring.xba;           */
-	0x61, 0x04,		/* r0rami.dt -> ring.xad;           */
-	0xE3, 0x07,		/* HI_RA_RAM_USR_BEGIN -> ring.iad; */
-	0x40, 0x00,		/* (long immediate)                 */
-	0x64, 0x04,		/* r0rami.dt -> ring.len;           */
-	0x65, 0x04,		/* r0rami.dt -> ring.ctl;           */
-	0x26, 0x00,		/* 0         -> ring.rdy;           */
-	0x38, 0x00,		/* 0         -> jumps.ad;           */
-	END_OF_TABLE
-};
-
-/* Pins D0 and D1 of the parallel MPEG output can be used
-   to set the I2C address of a device. */
-
-#define HI_RST_FUNC_ADDR (HI_IF_RAM_USR_BEGIN__A + HI_TR_FUNC_SIZE)
-#define HI_RST_FUNC_SIZE 54	/* size of this function in instruction words */
-
-/* D0 Version */
-u8 DRXD_HiI2cPatch_1[] = {
-	WRBLOCK(HI_RST_FUNC_ADDR, HI_RST_FUNC_SIZE),
-	0xC8, 0x07, 0x01, 0x00,	/* MASK      -> reg0.dt;                        */
-	0xE0, 0x07, 0x15, 0x02,	/* (EC__BLK << 6) + EC_OC_REG__BNK -> ring.xba; */
-	0xE1, 0x07, 0x12, 0x00,	/* EC_OC_REG_OC_MPG_SIO__A -> ring.xad;         */
-	0xA2, 0x00,		/* M_BNK_ID_DAT -> ring.iba;                    */
-	0x23, 0x00,		/* &data     -> ring.iad;                       */
-	0x24, 0x00,		/* 0         -> ring.len;                       */
-	0xA5, 0x02,		/* M_RC_CTR_SWAP | M_RC_CTR_READ -> ring.ctl;   */
-	0x26, 0x00,		/* 0         -> ring.rdy;                       */
-	0x42, 0x00,		/* &data+1   -> w0ram.ad;                       */
-	0xC0, 0x07, 0xFF, 0x0F,	/* -1        -> w0ram.dt;                       */
-	0x63, 0x00,		/* &data+1   -> ring.iad;                       */
-	0x65, 0x02,		/* M_RC_CTR_SWAP | M_RC_CTR_WRITE -> ring.ctl;  */
-	0x26, 0x00,		/* 0         -> ring.rdy;                       */
-	0xE1, 0x07, 0x38, 0x00,	/* EC_OC_REG_OCR_MPG_USR_DAT__A -> ring.xad;    */
-	0xA5, 0x02,		/* M_RC_CTR_SWAP | M_RC_CTR_READ -> ring.ctl;   */
-	0x26, 0x00,		/* 0         -> ring.rdy;                       */
-	0xE1, 0x07, 0x12, 0x00,	/* EC_OC_REG_OC_MPG_SIO__A -> ring.xad;         */
-	0x23, 0x00,		/* &data     -> ring.iad;                       */
-	0x65, 0x02,		/* M_RC_CTR_SWAP | M_RC_CTR_WRITE -> ring.ctl;  */
-	0x26, 0x00,		/* 0         -> ring.rdy;                       */
-	0x42, 0x00,		/* &data+1   -> w0ram.ad;                       */
-	0x0F, 0x04,		/* r0ram.dt  -> and.op;                         */
-	0x1C, 0x06,		/* reg0.dt   -> and.tr;                         */
-	0xCF, 0x04,		/* and.rs    -> add.op;                         */
-	0xD0, 0x07, 0x70, 0x00,	/* DEF_DEV_ID -> add.tr;                        */
-	0xD0, 0x04,		/* add.rs    -> add.tr;                         */
-	0xC8, 0x04,		/* add.rs    -> reg0.dt;                        */
-	0x60, 0x00,		/* reg0.dt   -> w0ram.dt;                       */
-	0xC2, 0x07, 0x10, 0x00,	/* SLV0_BASE -> w0rami.ad;                      */
-	0x01, 0x00,		/* 0         -> w0rami.dt;                      */
-	0x01, 0x06,		/* reg0.dt   -> w0rami.dt;                      */
-	0xC2, 0x07, 0x20, 0x00,	/* SLV1_BASE -> w0rami.ad;                      */
-	0x01, 0x00,		/* 0         -> w0rami.dt;                      */
-	0x01, 0x06,		/* reg0.dt   -> w0rami.dt;                      */
-	0xC2, 0x07, 0x30, 0x00,	/* CMD_BASE  -> w0rami.ad;                      */
-	0x01, 0x00,		/* 0         -> w0rami.dt;                      */
-	0x01, 0x00,		/* 0         -> w0rami.dt;                      */
-	0x01, 0x00,		/* 0         -> w0rami.dt;                      */
-	0x68, 0x00,		/* M_IC_SEL_PT1 -> i2c.sel;                     */
-	0x29, 0x00,		/* M_IC_CMD_RESET -> i2c.cmd;                   */
-	0x28, 0x00,		/* M_IC_SEL_PT0 -> i2c.sel;                     */
-	0x29, 0x00,		/* M_IC_CMD_RESET -> i2c.cmd;                   */
-	0xF8, 0x07, 0x2F, 0x00,	/* 0x2F      -> jumps.ad;                       */
-
-	WR16((B_HI_IF_RAM_TRP_BPT0__AX + ((2 * 0) + 1)),
-	     (u16) (HI_RST_FUNC_ADDR & 0x3FF)),
-	WR16((B_HI_IF_RAM_TRP_BPT0__AX + ((2 * 1) + 1)),
-	     (u16) (HI_RST_FUNC_ADDR & 0x3FF)),
-	WR16((B_HI_IF_RAM_TRP_BPT0__AX + ((2 * 2) + 1)),
-	     (u16) (HI_RST_FUNC_ADDR & 0x3FF)),
-	WR16((B_HI_IF_RAM_TRP_BPT0__AX + ((2 * 3) + 1)),
-	     (u16) (HI_RST_FUNC_ADDR & 0x3FF)),
-
-	/* Force quick and dirty reset */
-	WR16(B_HI_CT_REG_COMM_STATE__A, 0),
-	END_OF_TABLE
-};
-
-/* D0,D1 Version */
-u8 DRXD_HiI2cPatch_3[] = {
-	WRBLOCK(HI_RST_FUNC_ADDR, HI_RST_FUNC_SIZE),
-	0xC8, 0x07, 0x03, 0x00,	/* MASK      -> reg0.dt;                        */
-	0xE0, 0x07, 0x15, 0x02,	/* (EC__BLK << 6) + EC_OC_REG__BNK -> ring.xba; */
-	0xE1, 0x07, 0x12, 0x00,	/* EC_OC_REG_OC_MPG_SIO__A -> ring.xad;         */
-	0xA2, 0x00,		/* M_BNK_ID_DAT -> ring.iba;                    */
-	0x23, 0x00,		/* &data     -> ring.iad;                       */
-	0x24, 0x00,		/* 0         -> ring.len;                       */
-	0xA5, 0x02,		/* M_RC_CTR_SWAP | M_RC_CTR_READ -> ring.ctl;   */
-	0x26, 0x00,		/* 0         -> ring.rdy;                       */
-	0x42, 0x00,		/* &data+1   -> w0ram.ad;                       */
-	0xC0, 0x07, 0xFF, 0x0F,	/* -1        -> w0ram.dt;                       */
-	0x63, 0x00,		/* &data+1   -> ring.iad;                       */
-	0x65, 0x02,		/* M_RC_CTR_SWAP | M_RC_CTR_WRITE -> ring.ctl;  */
-	0x26, 0x00,		/* 0         -> ring.rdy;                       */
-	0xE1, 0x07, 0x38, 0x00,	/* EC_OC_REG_OCR_MPG_USR_DAT__A -> ring.xad;    */
-	0xA5, 0x02,		/* M_RC_CTR_SWAP | M_RC_CTR_READ -> ring.ctl;   */
-	0x26, 0x00,		/* 0         -> ring.rdy;                       */
-	0xE1, 0x07, 0x12, 0x00,	/* EC_OC_REG_OC_MPG_SIO__A -> ring.xad;         */
-	0x23, 0x00,		/* &data     -> ring.iad;                       */
-	0x65, 0x02,		/* M_RC_CTR_SWAP | M_RC_CTR_WRITE -> ring.ctl;  */
-	0x26, 0x00,		/* 0         -> ring.rdy;                       */
-	0x42, 0x00,		/* &data+1   -> w0ram.ad;                       */
-	0x0F, 0x04,		/* r0ram.dt  -> and.op;                         */
-	0x1C, 0x06,		/* reg0.dt   -> and.tr;                         */
-	0xCF, 0x04,		/* and.rs    -> add.op;                         */
-	0xD0, 0x07, 0x70, 0x00,	/* DEF_DEV_ID -> add.tr;                        */
-	0xD0, 0x04,		/* add.rs    -> add.tr;                         */
-	0xC8, 0x04,		/* add.rs    -> reg0.dt;                        */
-	0x60, 0x00,		/* reg0.dt   -> w0ram.dt;                       */
-	0xC2, 0x07, 0x10, 0x00,	/* SLV0_BASE -> w0rami.ad;                      */
-	0x01, 0x00,		/* 0         -> w0rami.dt;                      */
-	0x01, 0x06,		/* reg0.dt   -> w0rami.dt;                      */
-	0xC2, 0x07, 0x20, 0x00,	/* SLV1_BASE -> w0rami.ad;                      */
-	0x01, 0x00,		/* 0         -> w0rami.dt;                      */
-	0x01, 0x06,		/* reg0.dt   -> w0rami.dt;                      */
-	0xC2, 0x07, 0x30, 0x00,	/* CMD_BASE  -> w0rami.ad;                      */
-	0x01, 0x00,		/* 0         -> w0rami.dt;                      */
-	0x01, 0x00,		/* 0         -> w0rami.dt;                      */
-	0x01, 0x00,		/* 0         -> w0rami.dt;                      */
-	0x68, 0x00,		/* M_IC_SEL_PT1 -> i2c.sel;                     */
-	0x29, 0x00,		/* M_IC_CMD_RESET -> i2c.cmd;                   */
-	0x28, 0x00,		/* M_IC_SEL_PT0 -> i2c.sel;                     */
-	0x29, 0x00,		/* M_IC_CMD_RESET -> i2c.cmd;                   */
-	0xF8, 0x07, 0x2F, 0x00,	/* 0x2F      -> jumps.ad;                       */
-
-	WR16((B_HI_IF_RAM_TRP_BPT0__AX + ((2 * 0) + 1)),
-	     (u16) (HI_RST_FUNC_ADDR & 0x3FF)),
-	WR16((B_HI_IF_RAM_TRP_BPT0__AX + ((2 * 1) + 1)),
-	     (u16) (HI_RST_FUNC_ADDR & 0x3FF)),
-	WR16((B_HI_IF_RAM_TRP_BPT0__AX + ((2 * 2) + 1)),
-	     (u16) (HI_RST_FUNC_ADDR & 0x3FF)),
-	WR16((B_HI_IF_RAM_TRP_BPT0__AX + ((2 * 3) + 1)),
-	     (u16) (HI_RST_FUNC_ADDR & 0x3FF)),
-
-	/* Force quick and dirty reset */
-	WR16(B_HI_CT_REG_COMM_STATE__A, 0),
-	END_OF_TABLE
-};
-
-u8 DRXD_ResetCEFR[] = {
-	WRBLOCK(CE_REG_FR_TREAL00__A, 57),
-	0x52, 0x00,		/* CE_REG_FR_TREAL00__A */
-	0x00, 0x00,		/* CE_REG_FR_TIMAG00__A */
-	0x52, 0x00,		/* CE_REG_FR_TREAL01__A */
-	0x00, 0x00,		/* CE_REG_FR_TIMAG01__A */
-	0x52, 0x00,		/* CE_REG_FR_TREAL02__A */
-	0x00, 0x00,		/* CE_REG_FR_TIMAG02__A */
-	0x52, 0x00,		/* CE_REG_FR_TREAL03__A */
-	0x00, 0x00,		/* CE_REG_FR_TIMAG03__A */
-	0x52, 0x00,		/* CE_REG_FR_TREAL04__A */
-	0x00, 0x00,		/* CE_REG_FR_TIMAG04__A */
-	0x52, 0x00,		/* CE_REG_FR_TREAL05__A */
-	0x00, 0x00,		/* CE_REG_FR_TIMAG05__A */
-	0x52, 0x00,		/* CE_REG_FR_TREAL06__A */
-	0x00, 0x00,		/* CE_REG_FR_TIMAG06__A */
-	0x52, 0x00,		/* CE_REG_FR_TREAL07__A */
-	0x00, 0x00,		/* CE_REG_FR_TIMAG07__A */
-	0x52, 0x00,		/* CE_REG_FR_TREAL08__A */
-	0x00, 0x00,		/* CE_REG_FR_TIMAG08__A */
-	0x52, 0x00,		/* CE_REG_FR_TREAL09__A */
-	0x00, 0x00,		/* CE_REG_FR_TIMAG09__A */
-	0x52, 0x00,		/* CE_REG_FR_TREAL10__A */
-	0x00, 0x00,		/* CE_REG_FR_TIMAG10__A */
-	0x52, 0x00,		/* CE_REG_FR_TREAL11__A */
-	0x00, 0x00,		/* CE_REG_FR_TIMAG11__A */
-
-	0x52, 0x00,		/* CE_REG_FR_MID_TAP__A */
-
-	0x0B, 0x00,		/* CE_REG_FR_SQS_G00__A */
-	0x0B, 0x00,		/* CE_REG_FR_SQS_G01__A */
-	0x0B, 0x00,		/* CE_REG_FR_SQS_G02__A */
-	0x0B, 0x00,		/* CE_REG_FR_SQS_G03__A */
-	0x0B, 0x00,		/* CE_REG_FR_SQS_G04__A */
-	0x0B, 0x00,		/* CE_REG_FR_SQS_G05__A */
-	0x0B, 0x00,		/* CE_REG_FR_SQS_G06__A */
-	0x0B, 0x00,		/* CE_REG_FR_SQS_G07__A */
-	0x0B, 0x00,		/* CE_REG_FR_SQS_G08__A */
-	0x0B, 0x00,		/* CE_REG_FR_SQS_G09__A */
-	0x0B, 0x00,		/* CE_REG_FR_SQS_G10__A */
-	0x0B, 0x00,		/* CE_REG_FR_SQS_G11__A */
-	0x0B, 0x00,		/* CE_REG_FR_SQS_G12__A */
-
-	0xFF, 0x01,		/* CE_REG_FR_RIO_G00__A */
-	0x90, 0x01,		/* CE_REG_FR_RIO_G01__A */
-	0x0B, 0x01,		/* CE_REG_FR_RIO_G02__A */
-	0xC8, 0x00,		/* CE_REG_FR_RIO_G03__A */
-	0xA0, 0x00,		/* CE_REG_FR_RIO_G04__A */
-	0x85, 0x00,		/* CE_REG_FR_RIO_G05__A */
-	0x72, 0x00,		/* CE_REG_FR_RIO_G06__A */
-	0x64, 0x00,		/* CE_REG_FR_RIO_G07__A */
-	0x59, 0x00,		/* CE_REG_FR_RIO_G08__A */
-	0x50, 0x00,		/* CE_REG_FR_RIO_G09__A */
-	0x49, 0x00,		/* CE_REG_FR_RIO_G10__A */
-
-	0x10, 0x00,		/* CE_REG_FR_MODE__A     */
-	0x78, 0x00,		/* CE_REG_FR_SQS_TRH__A  */
-	0x00, 0x00,		/* CE_REG_FR_RIO_GAIN__A */
-	0x00, 0x02,		/* CE_REG_FR_BYPASS__A   */
-	0x0D, 0x00,		/* CE_REG_FR_PM_SET__A   */
-	0x07, 0x00,		/* CE_REG_FR_ERR_SH__A   */
-	0x04, 0x00,		/* CE_REG_FR_MAN_SH__A   */
-	0x06, 0x00,		/* CE_REG_FR_TAP_SH__A   */
-
-	END_OF_TABLE
-};
-
-u8 DRXD_InitFEA2_1[] = {
-	WRBLOCK(FE_AD_REG_PD__A, 3),
-	0x00, 0x00,		/* FE_AD_REG_PD__A          */
-	0x01, 0x00,		/* FE_AD_REG_INVEXT__A      */
-	0x00, 0x00,		/* FE_AD_REG_CLKNEG__A      */
-
-	WRBLOCK(FE_AG_REG_DCE_AUR_CNT__A, 2),
-	0x10, 0x00,		/* FE_AG_REG_DCE_AUR_CNT__A */
-	0x10, 0x00,		/* FE_AG_REG_DCE_RUR_CNT__A */
-
-	WRBLOCK(FE_AG_REG_ACE_AUR_CNT__A, 2),
-	0x0E, 0x00,		/* FE_AG_REG_ACE_AUR_CNT__A */
-	0x00, 0x00,		/* FE_AG_REG_ACE_RUR_CNT__A */
-
-	WRBLOCK(FE_AG_REG_EGC_FLA_RGN__A, 5),
-	0x04, 0x00,		/* FE_AG_REG_EGC_FLA_RGN__A */
-	0x1F, 0x00,		/* FE_AG_REG_EGC_SLO_RGN__A */
-	0x00, 0x00,		/* FE_AG_REG_EGC_JMP_PSN__A */
-	0x00, 0x00,		/* FE_AG_REG_EGC_FLA_INC__A */
-	0x00, 0x00,		/* FE_AG_REG_EGC_FLA_DEC__A */
-
-	WRBLOCK(FE_AG_REG_GC1_AGC_MAX__A, 2),
-	0xFF, 0x01,		/* FE_AG_REG_GC1_AGC_MAX__A */
-	0x00, 0xFE,		/* FE_AG_REG_GC1_AGC_MIN__A */
-
-	WRBLOCK(FE_AG_REG_IND_WIN__A, 29),
-	0x00, 0x00,		/* FE_AG_REG_IND_WIN__A     */
-	0x05, 0x00,		/* FE_AG_REG_IND_THD_LOL__A */
-	0x0F, 0x00,		/* FE_AG_REG_IND_THD_HIL__A */
-	0x00, 0x00,		/* FE_AG_REG_IND_DEL__A     don't care */
-	0x1E, 0x00,		/* FE_AG_REG_IND_PD1_WRI__A */
-	0x0C, 0x00,		/* FE_AG_REG_PDA_AUR_CNT__A */
-	0x00, 0x00,		/* FE_AG_REG_PDA_RUR_CNT__A */
-	0x00, 0x00,		/* FE_AG_REG_PDA_AVE_DAT__A don't care  */
-	0x00, 0x00,		/* FE_AG_REG_PDC_RUR_CNT__A */
-	0x01, 0x00,		/* FE_AG_REG_PDC_SET_LVL__A */
-	0x02, 0x00,		/* FE_AG_REG_PDC_FLA_RGN__A */
-	0x00, 0x00,		/* FE_AG_REG_PDC_JMP_PSN__A don't care  */
-	0xFF, 0xFF,		/* FE_AG_REG_PDC_FLA_STP__A */
-	0xFF, 0xFF,		/* FE_AG_REG_PDC_SLO_STP__A */
-	0x00, 0x1F,		/* FE_AG_REG_PDC_PD2_WRI__A don't care  */
-	0x00, 0x00,		/* FE_AG_REG_PDC_MAP_DAT__A don't care  */
-	0x02, 0x00,		/* FE_AG_REG_PDC_MAX__A     */
-	0x0C, 0x00,		/* FE_AG_REG_TGA_AUR_CNT__A */
-	0x00, 0x00,		/* FE_AG_REG_TGA_RUR_CNT__A */
-	0x00, 0x00,		/* FE_AG_REG_TGA_AVE_DAT__A don't care  */
-	0x00, 0x00,		/* FE_AG_REG_TGC_RUR_CNT__A */
-	0x22, 0x00,		/* FE_AG_REG_TGC_SET_LVL__A */
-	0x15, 0x00,		/* FE_AG_REG_TGC_FLA_RGN__A */
-	0x00, 0x00,		/* FE_AG_REG_TGC_JMP_PSN__A don't care  */
-	0x01, 0x00,		/* FE_AG_REG_TGC_FLA_STP__A */
-	0x0A, 0x00,		/* FE_AG_REG_TGC_SLO_STP__A */
-	0x00, 0x00,		/* FE_AG_REG_TGC_MAP_DAT__A don't care  */
-	0x10, 0x00,		/* FE_AG_REG_FGA_AUR_CNT__A */
-	0x10, 0x00,		/* FE_AG_REG_FGA_RUR_CNT__A */
-
-	WRBLOCK(FE_AG_REG_BGC_FGC_WRI__A, 2),
-	0x00, 0x00,		/* FE_AG_REG_BGC_FGC_WRI__A */
-	0x00, 0x00,		/* FE_AG_REG_BGC_CGC_WRI__A */
-
-	WRBLOCK(FE_FD_REG_SCL__A, 3),
-	0x05, 0x00,		/* FE_FD_REG_SCL__A         */
-	0x03, 0x00,		/* FE_FD_REG_MAX_LEV__A     */
-	0x05, 0x00,		/* FE_FD_REG_NR__A          */
-
-	WRBLOCK(FE_CF_REG_SCL__A, 5),
-	0x16, 0x00,		/* FE_CF_REG_SCL__A         */
-	0x04, 0x00,		/* FE_CF_REG_MAX_LEV__A     */
-	0x06, 0x00,		/* FE_CF_REG_NR__A          */
-	0x00, 0x00,		/* FE_CF_REG_IMP_VAL__A     */
-	0x01, 0x00,		/* FE_CF_REG_MEAS_VAL__A    */
-
-	WRBLOCK(FE_CU_REG_FRM_CNT_RST__A, 2),
-	0x00, 0x08,		/* FE_CU_REG_FRM_CNT_RST__A */
-	0x00, 0x00,		/* FE_CU_REG_FRM_CNT_STR__A */
-
-	END_OF_TABLE
-};
-
-   /* with PGA */
-/*   WR16COND( DRXD_WITH_PGA, FE_AG_REG_AG_PGA_MODE__A   , 0x0004), */
-   /* without PGA */
-/*   WR16COND( DRXD_WITHOUT_PGA, FE_AG_REG_AG_PGA_MODE__A   , 0x0001), */
-/*   WR16(FE_AG_REG_AG_AGC_SIO__A,  (extAttr -> FeAgRegAgAgcSio), 0x0000 );*/
-/*   WR16(FE_AG_REG_AG_PWD__A        ,(extAttr -> FeAgRegAgPwd), 0x0000 );*/
-
-u8 DRXD_InitFEA2_2[] = {
-	WR16(FE_AG_REG_CDR_RUR_CNT__A, 0x0010),
-	WR16(FE_AG_REG_FGM_WRI__A, 48),
-	/* Activate measurement, activate scale */
-	WR16(FE_FD_REG_MEAS_VAL__A, 0x0001),
-
-	WR16(FE_CU_REG_COMM_EXEC__A, 0x0001),
-	WR16(FE_CF_REG_COMM_EXEC__A, 0x0001),
-	WR16(FE_IF_REG_COMM_EXEC__A, 0x0001),
-	WR16(FE_FD_REG_COMM_EXEC__A, 0x0001),
-	WR16(FE_FS_REG_COMM_EXEC__A, 0x0001),
-	WR16(FE_AD_REG_COMM_EXEC__A, 0x0001),
-	WR16(FE_AG_REG_COMM_EXEC__A, 0x0001),
-	WR16(FE_AG_REG_AG_MODE_LOP__A, 0x895E),
-
-	END_OF_TABLE
-};
-
-u8 DRXD_InitFEB1_1[] = {
-	WR16(B_FE_AD_REG_PD__A, 0x0000),
-	WR16(B_FE_AD_REG_CLKNEG__A, 0x0000),
-	WR16(B_FE_AG_REG_BGC_FGC_WRI__A, 0x0000),
-	WR16(B_FE_AG_REG_BGC_CGC_WRI__A, 0x0000),
-	WR16(B_FE_AG_REG_AG_MODE_LOP__A, 0x000a),
-	WR16(B_FE_AG_REG_IND_PD1_WRI__A, 35),
-	WR16(B_FE_AG_REG_IND_WIN__A, 0),
-	WR16(B_FE_AG_REG_IND_THD_LOL__A, 8),
-	WR16(B_FE_AG_REG_IND_THD_HIL__A, 8),
-	WR16(B_FE_CF_REG_IMP_VAL__A, 1),
-	WR16(B_FE_AG_REG_EGC_FLA_RGN__A, 7),
-	END_OF_TABLE
-};
-
-	/* with PGA */
-/*      WR16(B_FE_AG_REG_AG_PGA_MODE__A   , 0x0000, 0x0000); */
-       /* without PGA */
-/*      WR16(B_FE_AG_REG_AG_PGA_MODE__A   ,
-	     B_FE_AG_REG_AG_PGA_MODE_PFN_PCN_AFY_REN, 0x0000);*/
-									     /*   WR16(B_FE_AG_REG_AG_AGC_SIO__A,(extAttr -> FeAgRegAgAgcSio), 0x0000 );*//*added HS 23-05-2005 */
-/*   WR16(B_FE_AG_REG_AG_PWD__A    ,(extAttr -> FeAgRegAgPwd), 0x0000 );*/
-
-u8 DRXD_InitFEB1_2[] = {
-	WR16(B_FE_COMM_EXEC__A, 0x0001),
-
-	/* RF-AGC setup */
-	WR16(B_FE_AG_REG_PDA_AUR_CNT__A, 0x0C),
-	WR16(B_FE_AG_REG_PDC_SET_LVL__A, 0x01),
-	WR16(B_FE_AG_REG_PDC_FLA_RGN__A, 0x02),
-	WR16(B_FE_AG_REG_PDC_FLA_STP__A, 0xFFFF),
-	WR16(B_FE_AG_REG_PDC_SLO_STP__A, 0xFFFF),
-	WR16(B_FE_AG_REG_PDC_MAX__A, 0x02),
-	WR16(B_FE_AG_REG_TGA_AUR_CNT__A, 0x0C),
-	WR16(B_FE_AG_REG_TGC_SET_LVL__A, 0x22),
-	WR16(B_FE_AG_REG_TGC_FLA_RGN__A, 0x15),
-	WR16(B_FE_AG_REG_TGC_FLA_STP__A, 0x01),
-	WR16(B_FE_AG_REG_TGC_SLO_STP__A, 0x0A),
-
-	WR16(B_FE_CU_REG_DIV_NFC_CLP__A, 0),
-	WR16(B_FE_CU_REG_CTR_NFC_OCR__A, 25000),
-	WR16(B_FE_CU_REG_CTR_NFC_ICR__A, 1),
-	END_OF_TABLE
-};
-
-u8 DRXD_InitCPA2[] = {
-	WRBLOCK(CP_REG_BR_SPL_OFFSET__A, 2),
-	0x07, 0x00,		/* CP_REG_BR_SPL_OFFSET__A  */
-	0x0A, 0x00,		/* CP_REG_BR_STR_DEL__A     */
-
-	WRBLOCK(CP_REG_RT_ANG_INC0__A, 4),
-	0x00, 0x00,		/* CP_REG_RT_ANG_INC0__A    */
-	0x00, 0x00,		/* CP_REG_RT_ANG_INC1__A    */
-	0x03, 0x00,		/* CP_REG_RT_DETECT_ENA__A  */
-	0x03, 0x00,		/* CP_REG_RT_DETECT_TRH__A  */
-
-	WRBLOCK(CP_REG_AC_NEXP_OFFS__A, 5),
-	0x32, 0x00,		/* CP_REG_AC_NEXP_OFFS__A   */
-	0x62, 0x00,		/* CP_REG_AC_AVER_POW__A    */
-	0x82, 0x00,		/* CP_REG_AC_MAX_POW__A     */
-	0x26, 0x00,		/* CP_REG_AC_WEIGHT_MAN__A  */
-	0x0F, 0x00,		/* CP_REG_AC_WEIGHT_EXP__A  */
-
-	WRBLOCK(CP_REG_AC_AMP_MODE__A, 2),
-	0x02, 0x00,		/* CP_REG_AC_AMP_MODE__A    */
-	0x01, 0x00,		/* CP_REG_AC_AMP_FIX__A     */
-
-	WR16(CP_REG_INTERVAL__A, 0x0005),
-	WR16(CP_REG_RT_EXP_MARG__A, 0x0004),
-	WR16(CP_REG_AC_ANG_MODE__A, 0x0003),
-
-	WR16(CP_REG_COMM_EXEC__A, 0x0001),
-	END_OF_TABLE
-};
-
-u8 DRXD_InitCPB1[] = {
-	WR16(B_CP_REG_BR_SPL_OFFSET__A, 0x0008),
-	WR16(B_CP_COMM_EXEC__A, 0x0001),
-	END_OF_TABLE
-};
-
-u8 DRXD_InitCEA2[] = {
-	WRBLOCK(CE_REG_AVG_POW__A, 4),
-	0x62, 0x00,		/* CE_REG_AVG_POW__A        */
-	0x78, 0x00,		/* CE_REG_MAX_POW__A        */
-	0x62, 0x00,		/* CE_REG_ATT__A            */
-	0x17, 0x00,		/* CE_REG_NRED__A           */
-
-	WRBLOCK(CE_REG_NE_ERR_SELECT__A, 2),
-	0x07, 0x00,		/* CE_REG_NE_ERR_SELECT__A  */
-	0xEB, 0xFF,		/* CE_REG_NE_TD_CAL__A      */
-
-	WRBLOCK(CE_REG_NE_MIXAVG__A, 2),
-	0x06, 0x00,		/* CE_REG_NE_MIXAVG__A      */
-	0x00, 0x00,		/* CE_REG_NE_NUPD_OFS__A    */
-
-	WRBLOCK(CE_REG_PE_NEXP_OFFS__A, 2),
-	0x00, 0x00,		/* CE_REG_PE_NEXP_OFFS__A   */
-	0x00, 0x00,		/* CE_REG_PE_TIMESHIFT__A   */
-
-	WRBLOCK(CE_REG_TP_A0_TAP_NEW__A, 3),
-	0x00, 0x01,		/* CE_REG_TP_A0_TAP_NEW__A       */
-	0x01, 0x00,		/* CE_REG_TP_A0_TAP_NEW_VALID__A */
-	0x0E, 0x00,		/* CE_REG_TP_A0_MU_LMS_STEP__A   */
-
-	WRBLOCK(CE_REG_TP_A1_TAP_NEW__A, 3),
-	0x00, 0x00,		/* CE_REG_TP_A1_TAP_NEW__A        */
-	0x01, 0x00,		/* CE_REG_TP_A1_TAP_NEW_VALID__A  */
-	0x0A, 0x00,		/* CE_REG_TP_A1_MU_LMS_STEP__A    */
-
-	WRBLOCK(CE_REG_FI_SHT_INCR__A, 2),
-	0x12, 0x00,		/* CE_REG_FI_SHT_INCR__A          */
-	0x0C, 0x00,		/* CE_REG_FI_EXP_NORM__A          */
-
-	WRBLOCK(CE_REG_IR_INPUTSEL__A, 3),
-	0x00, 0x00,		/* CE_REG_IR_INPUTSEL__A          */
-	0x00, 0x00,		/* CE_REG_IR_STARTPOS__A          */
-	0xFF, 0x00,		/* CE_REG_IR_NEXP_THRES__A        */
-
-	WR16(CE_REG_TI_NEXP_OFFS__A, 0x0000),
-
-	END_OF_TABLE
-};
-
-u8 DRXD_InitCEB1[] = {
-	WR16(B_CE_REG_TI_PHN_ENABLE__A, 0x0001),
-	WR16(B_CE_REG_FR_PM_SET__A, 0x000D),
-
-	END_OF_TABLE
-};
-
-u8 DRXD_InitEQA2[] = {
-	WRBLOCK(EQ_REG_OT_QNT_THRES0__A, 4),
-	0x1E, 0x00,		/* EQ_REG_OT_QNT_THRES0__A        */
-	0x1F, 0x00,		/* EQ_REG_OT_QNT_THRES1__A        */
-	0x06, 0x00,		/* EQ_REG_OT_CSI_STEP__A          */
-	0x02, 0x00,		/* EQ_REG_OT_CSI_OFFSET__A        */
-
-	WR16(EQ_REG_TD_REQ_SMB_CNT__A, 0x0200),
-	WR16(EQ_REG_IS_CLIP_EXP__A, 0x001F),
-	WR16(EQ_REG_SN_OFFSET__A, (u16) (-7)),
-	WR16(EQ_REG_RC_SEL_CAR__A, 0x0002),
-	WR16(EQ_REG_COMM_EXEC__A, 0x0001),
-	END_OF_TABLE
-};
-
-u8 DRXD_InitEQB1[] = {
-	WR16(B_EQ_REG_COMM_EXEC__A, 0x0001),
-	END_OF_TABLE
-};
-
-u8 DRXD_ResetECRAM[] = {
-	/* Reset packet sync bytes in EC_VD ram */
-	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (0 * 17), 0x0000),
-	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (1 * 17), 0x0000),
-	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (2 * 17), 0x0000),
-	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (3 * 17), 0x0000),
-	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (4 * 17), 0x0000),
-	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (5 * 17), 0x0000),
-	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (6 * 17), 0x0000),
-	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (7 * 17), 0x0000),
-	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (8 * 17), 0x0000),
-	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (9 * 17), 0x0000),
-	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (10 * 17), 0x0000),
-
-	/* Reset packet sync bytes in EC_RS ram */
-	WR16(EC_RS_EC_RAM__A, 0x0000),
-	WR16(EC_RS_EC_RAM__A + 204, 0x0000),
-	END_OF_TABLE
-};
-
-u8 DRXD_InitECA2[] = {
-	WRBLOCK(EC_SB_REG_CSI_HI__A, 6),
-	0x1F, 0x00,		/* EC_SB_REG_CSI_HI__A            */
-	0x1E, 0x00,		/* EC_SB_REG_CSI_LO__A            */
-	0x01, 0x00,		/* EC_SB_REG_SMB_TGL__A           */
-	0x7F, 0x00,		/* EC_SB_REG_SNR_HI__A            */
-	0x7F, 0x00,		/* EC_SB_REG_SNR_MID__A           */
-	0x7F, 0x00,		/* EC_SB_REG_SNR_LO__A            */
-
-	WRBLOCK(EC_RS_REG_REQ_PCK_CNT__A, 2),
-	0x00, 0x10,		/* EC_RS_REG_REQ_PCK_CNT__A       */
-	DATA16(EC_RS_REG_VAL_PCK),	/* EC_RS_REG_VAL__A               */
-
-	WRBLOCK(EC_OC_REG_TMD_TOP_MODE__A, 5),
-	0x03, 0x00,		/* EC_OC_REG_TMD_TOP_MODE__A      */
-	0xF4, 0x01,		/* EC_OC_REG_TMD_TOP_CNT__A       */
-	0xC0, 0x03,		/* EC_OC_REG_TMD_HIL_MAR__A       */
-	0x40, 0x00,		/* EC_OC_REG_TMD_LOL_MAR__A       */
-	0x03, 0x00,		/* EC_OC_REG_TMD_CUR_CNT__A       */
-
-	WRBLOCK(EC_OC_REG_AVR_ASH_CNT__A, 2),
-	0x06, 0x00,		/* EC_OC_REG_AVR_ASH_CNT__A       */
-	0x02, 0x00,		/* EC_OC_REG_AVR_BSH_CNT__A       */
-
-	WRBLOCK(EC_OC_REG_RCN_MODE__A, 7),
-	0x07, 0x00,		/* EC_OC_REG_RCN_MODE__A          */
-	0x00, 0x00,		/* EC_OC_REG_RCN_CRA_LOP__A       */
-	0xc0, 0x00,		/* EC_OC_REG_RCN_CRA_HIP__A       */
-	0x00, 0x10,		/* EC_OC_REG_RCN_CST_LOP__A       */
-	0x00, 0x00,		/* EC_OC_REG_RCN_CST_HIP__A       */
-	0xFF, 0x01,		/* EC_OC_REG_RCN_SET_LVL__A       */
-	0x0D, 0x00,		/* EC_OC_REG_RCN_GAI_LVL__A       */
-
-	WRBLOCK(EC_OC_REG_RCN_CLP_LOP__A, 2),
-	0x00, 0x00,		/* EC_OC_REG_RCN_CLP_LOP__A       */
-	0xC0, 0x00,		/* EC_OC_REG_RCN_CLP_HIP__A       */
-
-	WR16(EC_SB_REG_CSI_OFS__A, 0x0001),
-	WR16(EC_VD_REG_FORCE__A, 0x0002),
-	WR16(EC_VD_REG_REQ_SMB_CNT__A, 0x0001),
-	WR16(EC_VD_REG_RLK_ENA__A, 0x0001),
-	WR16(EC_OD_REG_SYNC__A, 0x0664),
-	WR16(EC_OC_REG_OC_MON_SIO__A, 0x0000),
-	WR16(EC_OC_REG_SNC_ISC_LVL__A, 0x0D0C),
-	/* Output zero on monitorbus pads, power saving */
-	WR16(EC_OC_REG_OCR_MON_UOS__A,
-	     (EC_OC_REG_OCR_MON_UOS_DAT_0_ENABLE |
-	      EC_OC_REG_OCR_MON_UOS_DAT_1_ENABLE |
-	      EC_OC_REG_OCR_MON_UOS_DAT_2_ENABLE |
-	      EC_OC_REG_OCR_MON_UOS_DAT_3_ENABLE |
-	      EC_OC_REG_OCR_MON_UOS_DAT_4_ENABLE |
-	      EC_OC_REG_OCR_MON_UOS_DAT_5_ENABLE |
-	      EC_OC_REG_OCR_MON_UOS_DAT_6_ENABLE |
-	      EC_OC_REG_OCR_MON_UOS_DAT_7_ENABLE |
-	      EC_OC_REG_OCR_MON_UOS_DAT_8_ENABLE |
-	      EC_OC_REG_OCR_MON_UOS_DAT_9_ENABLE |
-	      EC_OC_REG_OCR_MON_UOS_VAL_ENABLE |
-	      EC_OC_REG_OCR_MON_UOS_CLK_ENABLE)),
-	WR16(EC_OC_REG_OCR_MON_WRI__A,
-	     EC_OC_REG_OCR_MON_WRI_INIT),
-
-/*   CHK_ERROR(ResetECRAM(demod)); */
-	/* Reset packet sync bytes in EC_VD ram */
-	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (0 * 17), 0x0000),
-	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (1 * 17), 0x0000),
-	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (2 * 17), 0x0000),
-	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (3 * 17), 0x0000),
-	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (4 * 17), 0x0000),
-	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (5 * 17), 0x0000),
-	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (6 * 17), 0x0000),
-	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (7 * 17), 0x0000),
-	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (8 * 17), 0x0000),
-	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (9 * 17), 0x0000),
-	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (10 * 17), 0x0000),
-
-	/* Reset packet sync bytes in EC_RS ram */
-	WR16(EC_RS_EC_RAM__A, 0x0000),
-	WR16(EC_RS_EC_RAM__A + 204, 0x0000),
-
-	WR16(EC_SB_REG_COMM_EXEC__A, 0x0001),
-	WR16(EC_VD_REG_COMM_EXEC__A, 0x0001),
-	WR16(EC_OD_REG_COMM_EXEC__A, 0x0001),
-	WR16(EC_RS_REG_COMM_EXEC__A, 0x0001),
-	END_OF_TABLE
-};
-
-u8 DRXD_InitECB1[] = {
-	WR16(B_EC_SB_REG_CSI_OFS0__A, 0x0001),
-	WR16(B_EC_SB_REG_CSI_OFS1__A, 0x0001),
-	WR16(B_EC_SB_REG_CSI_OFS2__A, 0x0001),
-	WR16(B_EC_SB_REG_CSI_LO__A, 0x000c),
-	WR16(B_EC_SB_REG_CSI_HI__A, 0x0018),
-	WR16(B_EC_SB_REG_SNR_HI__A, 0x007f),
-	WR16(B_EC_SB_REG_SNR_MID__A, 0x007f),
-	WR16(B_EC_SB_REG_SNR_LO__A, 0x007f),
-
-	WR16(B_EC_OC_REG_DTO_CLKMODE__A, 0x0002),
-	WR16(B_EC_OC_REG_DTO_PER__A, 0x0006),
-	WR16(B_EC_OC_REG_DTO_BUR__A, 0x0001),
-	WR16(B_EC_OC_REG_RCR_CLKMODE__A, 0x0000),
-	WR16(B_EC_OC_REG_RCN_GAI_LVL__A, 0x000D),
-	WR16(B_EC_OC_REG_OC_MPG_SIO__A, 0x0000),
-
-	/* Needed because shadow registers do not have correct default value */
-	WR16(B_EC_OC_REG_RCN_CST_LOP__A, 0x1000),
-	WR16(B_EC_OC_REG_RCN_CST_HIP__A, 0x0000),
-	WR16(B_EC_OC_REG_RCN_CRA_LOP__A, 0x0000),
-	WR16(B_EC_OC_REG_RCN_CRA_HIP__A, 0x00C0),
-	WR16(B_EC_OC_REG_RCN_CLP_LOP__A, 0x0000),
-	WR16(B_EC_OC_REG_RCN_CLP_HIP__A, 0x00C0),
-	WR16(B_EC_OC_REG_DTO_INC_LOP__A, 0x0000),
-	WR16(B_EC_OC_REG_DTO_INC_HIP__A, 0x00C0),
-
-	WR16(B_EC_OD_REG_SYNC__A, 0x0664),
-	WR16(B_EC_RS_REG_REQ_PCK_CNT__A, 0x1000),
-
-/*   CHK_ERROR(ResetECRAM(demod)); */
-	/* Reset packet sync bytes in EC_VD ram */
-	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (0 * 17), 0x0000),
-	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (1 * 17), 0x0000),
-	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (2 * 17), 0x0000),
-	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (3 * 17), 0x0000),
-	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (4 * 17), 0x0000),
-	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (5 * 17), 0x0000),
-	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (6 * 17), 0x0000),
-	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (7 * 17), 0x0000),
-	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (8 * 17), 0x0000),
-	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (9 * 17), 0x0000),
-	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (10 * 17), 0x0000),
-
-	/* Reset packet sync bytes in EC_RS ram */
-	WR16(EC_RS_EC_RAM__A, 0x0000),
-	WR16(EC_RS_EC_RAM__A + 204, 0x0000),
-
-	WR16(B_EC_SB_REG_COMM_EXEC__A, 0x0001),
-	WR16(B_EC_VD_REG_COMM_EXEC__A, 0x0001),
-	WR16(B_EC_OD_REG_COMM_EXEC__A, 0x0001),
-	WR16(B_EC_RS_REG_COMM_EXEC__A, 0x0001),
-	END_OF_TABLE
-};
-
-u8 DRXD_ResetECA2[] = {
-
-	WR16(EC_OC_REG_COMM_EXEC__A, 0x0000),
-	WR16(EC_OD_REG_COMM_EXEC__A, 0x0000),
-
-	WRBLOCK(EC_OC_REG_TMD_TOP_MODE__A, 5),
-	0x03, 0x00,		/* EC_OC_REG_TMD_TOP_MODE__A      */
-	0xF4, 0x01,		/* EC_OC_REG_TMD_TOP_CNT__A       */
-	0xC0, 0x03,		/* EC_OC_REG_TMD_HIL_MAR__A       */
-	0x40, 0x00,		/* EC_OC_REG_TMD_LOL_MAR__A       */
-	0x03, 0x00,		/* EC_OC_REG_TMD_CUR_CNT__A       */
-
-	WRBLOCK(EC_OC_REG_AVR_ASH_CNT__A, 2),
-	0x06, 0x00,		/* EC_OC_REG_AVR_ASH_CNT__A       */
-	0x02, 0x00,		/* EC_OC_REG_AVR_BSH_CNT__A       */
-
-	WRBLOCK(EC_OC_REG_RCN_MODE__A, 7),
-	0x07, 0x00,		/* EC_OC_REG_RCN_MODE__A          */
-	0x00, 0x00,		/* EC_OC_REG_RCN_CRA_LOP__A       */
-	0xc0, 0x00,		/* EC_OC_REG_RCN_CRA_HIP__A       */
-	0x00, 0x10,		/* EC_OC_REG_RCN_CST_LOP__A       */
-	0x00, 0x00,		/* EC_OC_REG_RCN_CST_HIP__A       */
-	0xFF, 0x01,		/* EC_OC_REG_RCN_SET_LVL__A       */
-	0x0D, 0x00,		/* EC_OC_REG_RCN_GAI_LVL__A       */
-
-	WRBLOCK(EC_OC_REG_RCN_CLP_LOP__A, 2),
-	0x00, 0x00,		/* EC_OC_REG_RCN_CLP_LOP__A       */
-	0xC0, 0x00,		/* EC_OC_REG_RCN_CLP_HIP__A       */
-
-	WR16(EC_OD_REG_SYNC__A, 0x0664),
-	WR16(EC_OC_REG_OC_MON_SIO__A, 0x0000),
-	WR16(EC_OC_REG_SNC_ISC_LVL__A, 0x0D0C),
-	/* Output zero on monitorbus pads, power saving */
-	WR16(EC_OC_REG_OCR_MON_UOS__A,
-	     (EC_OC_REG_OCR_MON_UOS_DAT_0_ENABLE |
-	      EC_OC_REG_OCR_MON_UOS_DAT_1_ENABLE |
-	      EC_OC_REG_OCR_MON_UOS_DAT_2_ENABLE |
-	      EC_OC_REG_OCR_MON_UOS_DAT_3_ENABLE |
-	      EC_OC_REG_OCR_MON_UOS_DAT_4_ENABLE |
-	      EC_OC_REG_OCR_MON_UOS_DAT_5_ENABLE |
-	      EC_OC_REG_OCR_MON_UOS_DAT_6_ENABLE |
-	      EC_OC_REG_OCR_MON_UOS_DAT_7_ENABLE |
-	      EC_OC_REG_OCR_MON_UOS_DAT_8_ENABLE |
-	      EC_OC_REG_OCR_MON_UOS_DAT_9_ENABLE |
-	      EC_OC_REG_OCR_MON_UOS_VAL_ENABLE |
-	      EC_OC_REG_OCR_MON_UOS_CLK_ENABLE)),
-	WR16(EC_OC_REG_OCR_MON_WRI__A,
-	     EC_OC_REG_OCR_MON_WRI_INIT),
-
-/*   CHK_ERROR(ResetECRAM(demod)); */
-	/* Reset packet sync bytes in EC_VD ram */
-	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (0 * 17), 0x0000),
-	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (1 * 17), 0x0000),
-	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (2 * 17), 0x0000),
-	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (3 * 17), 0x0000),
-	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (4 * 17), 0x0000),
-	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (5 * 17), 0x0000),
-	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (6 * 17), 0x0000),
-	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (7 * 17), 0x0000),
-	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (8 * 17), 0x0000),
-	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (9 * 17), 0x0000),
-	WR16(EC_OD_DEINT_RAM__A + 0x3b7 + (10 * 17), 0x0000),
-
-	/* Reset packet sync bytes in EC_RS ram */
-	WR16(EC_RS_EC_RAM__A, 0x0000),
-	WR16(EC_RS_EC_RAM__A + 204, 0x0000),
-
-	WR16(EC_OD_REG_COMM_EXEC__A, 0x0001),
-	END_OF_TABLE
-};
-
-u8 DRXD_InitSC[] = {
-	WR16(SC_COMM_EXEC__A, 0),
-	WR16(SC_COMM_STATE__A, 0),
-
-#ifdef COMPILE_FOR_QT
-	WR16(SC_RA_RAM_BE_OPT_DELAY__A, 0x100),
-#endif
-
-	/* SC is not started, this is done in SetChannels() */
-	END_OF_TABLE
-};
-
-/* Diversity settings */
-
-u8 DRXD_InitDiversityFront[] = {
-	/* Start demod ********* RF in , diversity out **************************** */
-	WR16(B_SC_RA_RAM_CONFIG__A, B_SC_RA_RAM_CONFIG_FR_ENABLE__M |
-	     B_SC_RA_RAM_CONFIG_FREQSCAN__M),
-
-	WR16(B_SC_RA_RAM_LC_ABS_2K__A, 0x7),
-	WR16(B_SC_RA_RAM_LC_ABS_8K__A, 0x7),
-	WR16(B_SC_RA_RAM_IR_COARSE_8K_LENGTH__A, IRLEN_COARSE_8K),
-	WR16(B_SC_RA_RAM_IR_COARSE_8K_FREQINC__A, 1 << (11 - IRLEN_COARSE_8K)),
-	WR16(B_SC_RA_RAM_IR_COARSE_8K_KAISINC__A, 1 << (17 - IRLEN_COARSE_8K)),
-	WR16(B_SC_RA_RAM_IR_FINE_8K_LENGTH__A, IRLEN_FINE_8K),
-	WR16(B_SC_RA_RAM_IR_FINE_8K_FREQINC__A, 1 << (11 - IRLEN_FINE_8K)),
-	WR16(B_SC_RA_RAM_IR_FINE_8K_KAISINC__A, 1 << (17 - IRLEN_FINE_8K)),
-
-	WR16(B_SC_RA_RAM_IR_COARSE_2K_LENGTH__A, IRLEN_COARSE_2K),
-	WR16(B_SC_RA_RAM_IR_COARSE_2K_FREQINC__A, 1 << (11 - IRLEN_COARSE_2K)),
-	WR16(B_SC_RA_RAM_IR_COARSE_2K_KAISINC__A, 1 << (17 - IRLEN_COARSE_2K)),
-	WR16(B_SC_RA_RAM_IR_FINE_2K_LENGTH__A, IRLEN_FINE_2K),
-	WR16(B_SC_RA_RAM_IR_FINE_2K_FREQINC__A, 1 << (11 - IRLEN_FINE_2K)),
-	WR16(B_SC_RA_RAM_IR_FINE_2K_KAISINC__A, 1 << (17 - IRLEN_FINE_2K)),
-
-	WR16(B_LC_RA_RAM_FILTER_CRMM_A__A, 7),
-	WR16(B_LC_RA_RAM_FILTER_CRMM_B__A, 4),
-	WR16(B_LC_RA_RAM_FILTER_SRMM_A__A, 7),
-	WR16(B_LC_RA_RAM_FILTER_SRMM_B__A, 4),
-	WR16(B_LC_RA_RAM_FILTER_SYM_SET__A, 500),
-
-	WR16(B_CC_REG_DIVERSITY__A, 0x0001),
-	WR16(B_EC_OC_REG_OC_MODE_HIP__A, 0x0010),
-	WR16(B_EQ_REG_RC_SEL_CAR__A, B_EQ_REG_RC_SEL_CAR_PASS_B_CE |
-	     B_EQ_REG_RC_SEL_CAR_LOCAL_B_CE | B_EQ_REG_RC_SEL_CAR_MEAS_B_CE),
-
-	/*    0x2a ), *//* CE to PASS mux */
-
-	END_OF_TABLE
-};
-
-u8 DRXD_InitDiversityEnd[] = {
-	/* End demod *********** combining RF in and diversity in, MPEG TS out **** */
-	/* disable near/far; switch on timing slave mode */
-	WR16(B_SC_RA_RAM_CONFIG__A, B_SC_RA_RAM_CONFIG_FR_ENABLE__M |
-	     B_SC_RA_RAM_CONFIG_FREQSCAN__M |
-	     B_SC_RA_RAM_CONFIG_DIV_ECHO_ENABLE__M |
-	     B_SC_RA_RAM_CONFIG_SLAVE__M |
-	     B_SC_RA_RAM_CONFIG_DIV_BLANK_ENABLE__M
-/* MV from CtrlDiversity */
-	    ),
-#ifdef DRXDDIV_SRMM_SLAVING
-	WR16(SC_RA_RAM_LC_ABS_2K__A, 0x3c7),
-	WR16(SC_RA_RAM_LC_ABS_8K__A, 0x3c7),
-#else
-	WR16(SC_RA_RAM_LC_ABS_2K__A, 0x7),
-	WR16(SC_RA_RAM_LC_ABS_8K__A, 0x7),
-#endif
-
-	WR16(B_SC_RA_RAM_IR_COARSE_8K_LENGTH__A, IRLEN_COARSE_8K),
-	WR16(B_SC_RA_RAM_IR_COARSE_8K_FREQINC__A, 1 << (11 - IRLEN_COARSE_8K)),
-	WR16(B_SC_RA_RAM_IR_COARSE_8K_KAISINC__A, 1 << (17 - IRLEN_COARSE_8K)),
-	WR16(B_SC_RA_RAM_IR_FINE_8K_LENGTH__A, IRLEN_FINE_8K),
-	WR16(B_SC_RA_RAM_IR_FINE_8K_FREQINC__A, 1 << (11 - IRLEN_FINE_8K)),
-	WR16(B_SC_RA_RAM_IR_FINE_8K_KAISINC__A, 1 << (17 - IRLEN_FINE_8K)),
-
-	WR16(B_SC_RA_RAM_IR_COARSE_2K_LENGTH__A, IRLEN_COARSE_2K),
-	WR16(B_SC_RA_RAM_IR_COARSE_2K_FREQINC__A, 1 << (11 - IRLEN_COARSE_2K)),
-	WR16(B_SC_RA_RAM_IR_COARSE_2K_KAISINC__A, 1 << (17 - IRLEN_COARSE_2K)),
-	WR16(B_SC_RA_RAM_IR_FINE_2K_LENGTH__A, IRLEN_FINE_2K),
-	WR16(B_SC_RA_RAM_IR_FINE_2K_FREQINC__A, 1 << (11 - IRLEN_FINE_2K)),
-	WR16(B_SC_RA_RAM_IR_FINE_2K_KAISINC__A, 1 << (17 - IRLEN_FINE_2K)),
-
-	WR16(B_LC_RA_RAM_FILTER_CRMM_A__A, 7),
-	WR16(B_LC_RA_RAM_FILTER_CRMM_B__A, 4),
-	WR16(B_LC_RA_RAM_FILTER_SRMM_A__A, 7),
-	WR16(B_LC_RA_RAM_FILTER_SRMM_B__A, 4),
-	WR16(B_LC_RA_RAM_FILTER_SYM_SET__A, 500),
-
-	WR16(B_CC_REG_DIVERSITY__A, 0x0001),
-	END_OF_TABLE
-};
-
-u8 DRXD_DisableDiversity[] = {
-	WR16(B_SC_RA_RAM_LC_ABS_2K__A, B_SC_RA_RAM_LC_ABS_2K__PRE),
-	WR16(B_SC_RA_RAM_LC_ABS_8K__A, B_SC_RA_RAM_LC_ABS_8K__PRE),
-	WR16(B_SC_RA_RAM_IR_COARSE_8K_LENGTH__A,
-	     B_SC_RA_RAM_IR_COARSE_8K_LENGTH__PRE),
-	WR16(B_SC_RA_RAM_IR_COARSE_8K_FREQINC__A,
-	     B_SC_RA_RAM_IR_COARSE_8K_FREQINC__PRE),
-	WR16(B_SC_RA_RAM_IR_COARSE_8K_KAISINC__A,
-	     B_SC_RA_RAM_IR_COARSE_8K_KAISINC__PRE),
-	WR16(B_SC_RA_RAM_IR_FINE_8K_LENGTH__A,
-	     B_SC_RA_RAM_IR_FINE_8K_LENGTH__PRE),
-	WR16(B_SC_RA_RAM_IR_FINE_8K_FREQINC__A,
-	     B_SC_RA_RAM_IR_FINE_8K_FREQINC__PRE),
-	WR16(B_SC_RA_RAM_IR_FINE_8K_KAISINC__A,
-	     B_SC_RA_RAM_IR_FINE_8K_KAISINC__PRE),
-
-	WR16(B_SC_RA_RAM_IR_COARSE_2K_LENGTH__A,
-	     B_SC_RA_RAM_IR_COARSE_2K_LENGTH__PRE),
-	WR16(B_SC_RA_RAM_IR_COARSE_2K_FREQINC__A,
-	     B_SC_RA_RAM_IR_COARSE_2K_FREQINC__PRE),
-	WR16(B_SC_RA_RAM_IR_COARSE_2K_KAISINC__A,
-	     B_SC_RA_RAM_IR_COARSE_2K_KAISINC__PRE),
-	WR16(B_SC_RA_RAM_IR_FINE_2K_LENGTH__A,
-	     B_SC_RA_RAM_IR_FINE_2K_LENGTH__PRE),
-	WR16(B_SC_RA_RAM_IR_FINE_2K_FREQINC__A,
-	     B_SC_RA_RAM_IR_FINE_2K_FREQINC__PRE),
-	WR16(B_SC_RA_RAM_IR_FINE_2K_KAISINC__A,
-	     B_SC_RA_RAM_IR_FINE_2K_KAISINC__PRE),
-
-	WR16(B_LC_RA_RAM_FILTER_CRMM_A__A, B_LC_RA_RAM_FILTER_CRMM_A__PRE),
-	WR16(B_LC_RA_RAM_FILTER_CRMM_B__A, B_LC_RA_RAM_FILTER_CRMM_B__PRE),
-	WR16(B_LC_RA_RAM_FILTER_SRMM_A__A, B_LC_RA_RAM_FILTER_SRMM_A__PRE),
-	WR16(B_LC_RA_RAM_FILTER_SRMM_B__A, B_LC_RA_RAM_FILTER_SRMM_B__PRE),
-	WR16(B_LC_RA_RAM_FILTER_SYM_SET__A, B_LC_RA_RAM_FILTER_SYM_SET__PRE),
-
-	WR16(B_CC_REG_DIVERSITY__A, 0x0000),
-	WR16(B_EQ_REG_RC_SEL_CAR__A, B_EQ_REG_RC_SEL_CAR_INIT),	/* combining disabled */
-
-	END_OF_TABLE
-};
-
-u8 DRXD_StartDiversityFront[] = {
-	/* Start demod, RF in and diversity out, no combining */
-	WR16(B_FE_CF_REG_IMP_VAL__A, 0x0),
-	WR16(B_FE_AD_REG_FDB_IN__A, 0x0),
-	WR16(B_FE_AD_REG_INVEXT__A, 0x0),
-	WR16(B_EQ_REG_COMM_MB__A, 0x12),	/* EQ to MB out */
-	WR16(B_EQ_REG_RC_SEL_CAR__A, B_EQ_REG_RC_SEL_CAR_PASS_B_CE |	/* CE to PASS mux */
-	     B_EQ_REG_RC_SEL_CAR_LOCAL_B_CE | B_EQ_REG_RC_SEL_CAR_MEAS_B_CE),
-
-	WR16(SC_RA_RAM_ECHO_SHIFT_LIM__A, 2),
-
-	END_OF_TABLE
-};
-
-u8 DRXD_StartDiversityEnd[] = {
-	/* End demod, combining RF in and diversity in, MPEG TS out */
-	WR16(B_FE_CF_REG_IMP_VAL__A, 0x0),	/* disable impulse noise cruncher */
-	WR16(B_FE_AD_REG_INVEXT__A, 0x0),	/* clock inversion (for sohard board) */
-	WR16(B_CP_REG_BR_STR_DEL__A, 10),	/* apperently no mb delay matching is best */
-
-	WR16(B_EQ_REG_RC_SEL_CAR__A, B_EQ_REG_RC_SEL_CAR_DIV_ON |	/* org = 0x81 combining enabled */
-	     B_EQ_REG_RC_SEL_CAR_MEAS_A_CC |
-	     B_EQ_REG_RC_SEL_CAR_PASS_A_CC | B_EQ_REG_RC_SEL_CAR_LOCAL_A_CC),
-
-	END_OF_TABLE
-};
-
-u8 DRXD_DiversityDelay8MHZ[] = {
-	WR16(B_SC_RA_RAM_DIVERSITY_DELAY_2K_32__A, 1150 - 50),
-	WR16(B_SC_RA_RAM_DIVERSITY_DELAY_2K_16__A, 1100 - 50),
-	WR16(B_SC_RA_RAM_DIVERSITY_DELAY_2K_8__A, 1000 - 50),
-	WR16(B_SC_RA_RAM_DIVERSITY_DELAY_2K_4__A, 800 - 50),
-	WR16(B_SC_RA_RAM_DIVERSITY_DELAY_8K_32__A, 5420 - 50),
-	WR16(B_SC_RA_RAM_DIVERSITY_DELAY_8K_16__A, 5200 - 50),
-	WR16(B_SC_RA_RAM_DIVERSITY_DELAY_8K_8__A, 4800 - 50),
-	WR16(B_SC_RA_RAM_DIVERSITY_DELAY_8K_4__A, 4000 - 50),
-	END_OF_TABLE
-};
-
-u8 DRXD_DiversityDelay6MHZ[] =	/* also used ok for 7 MHz */
-{
-	WR16(B_SC_RA_RAM_DIVERSITY_DELAY_2K_32__A, 1100 - 50),
-	WR16(B_SC_RA_RAM_DIVERSITY_DELAY_2K_16__A, 1000 - 50),
-	WR16(B_SC_RA_RAM_DIVERSITY_DELAY_2K_8__A, 900 - 50),
-	WR16(B_SC_RA_RAM_DIVERSITY_DELAY_2K_4__A, 600 - 50),
-	WR16(B_SC_RA_RAM_DIVERSITY_DELAY_8K_32__A, 5300 - 50),
-	WR16(B_SC_RA_RAM_DIVERSITY_DELAY_8K_16__A, 5000 - 50),
-	WR16(B_SC_RA_RAM_DIVERSITY_DELAY_8K_8__A, 4500 - 50),
-	WR16(B_SC_RA_RAM_DIVERSITY_DELAY_8K_4__A, 3500 - 50),
-	END_OF_TABLE
-};
diff --git a/drivers/media/dvb/frontends/drxd_firm.h b/drivers/media/dvb/frontends/drxd_firm.h
deleted file mode 100644
index 41597e8..0000000
--- a/drivers/media/dvb/frontends/drxd_firm.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * drxd_firm.h
- *
- * Copyright (C) 2006-2007 Micronas
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 only, as published by the Free Software Foundation.
- *
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#ifndef _DRXD_FIRM_H_
-#define _DRXD_FIRM_H_
-
-#include <linux/types.h>
-#include "drxd_map_firm.h"
-
-#define VERSION_MAJOR 1
-#define VERSION_MINOR 4
-#define VERSION_PATCH 23
-
-#define HI_TR_FUNC_ADDR HI_IF_RAM_USR_BEGIN__A
-
-#define DRXD_MAX_RETRIES (1000)
-#define HI_I2C_DELAY     84
-#define HI_I2C_BRIDGE_DELAY   750
-
-#define EQ_TD_TPS_PWR_UNKNOWN          0x00C0	/* Unknown configurations */
-#define EQ_TD_TPS_PWR_QPSK             0x016a
-#define EQ_TD_TPS_PWR_QAM16_ALPHAN     0x0195
-#define EQ_TD_TPS_PWR_QAM16_ALPHA1     0x0195
-#define EQ_TD_TPS_PWR_QAM16_ALPHA2     0x011E
-#define EQ_TD_TPS_PWR_QAM16_ALPHA4     0x01CE
-#define EQ_TD_TPS_PWR_QAM64_ALPHAN     0x019F
-#define EQ_TD_TPS_PWR_QAM64_ALPHA1     0x019F
-#define EQ_TD_TPS_PWR_QAM64_ALPHA2     0x00F8
-#define EQ_TD_TPS_PWR_QAM64_ALPHA4     0x014D
-
-#define DRXD_DEF_AG_PWD_CONSUMER 0x000E
-#define DRXD_DEF_AG_PWD_PRO 0x0000
-#define DRXD_DEF_AG_AGC_SIO 0x0000
-
-#define DRXD_FE_CTRL_MAX 1023
-
-#define DRXD_OSCDEV_DO_SCAN  (16)
-
-#define DRXD_OSCDEV_DONT_SCAN  (0)
-
-#define DRXD_OSCDEV_STEP  (275)
-
-#define DRXD_SCAN_TIMEOUT    (650)
-
-#define DRXD_BANDWIDTH_8MHZ_IN_HZ  (0x8B8249L)
-#define DRXD_BANDWIDTH_7MHZ_IN_HZ  (0x7A1200L)
-#define DRXD_BANDWIDTH_6MHZ_IN_HZ  (0x68A1B6L)
-
-#define IRLEN_COARSE_8K       (10)
-#define IRLEN_FINE_8K         (10)
-#define IRLEN_COARSE_2K       (7)
-#define IRLEN_FINE_2K         (9)
-#define DIFF_INVALID          (511)
-#define DIFF_TARGET           (4)
-#define DIFF_MARGIN           (1)
-
-extern u8 DRXD_InitAtomicRead[];
-extern u8 DRXD_HiI2cPatch_1[];
-extern u8 DRXD_HiI2cPatch_3[];
-
-extern u8 DRXD_InitSC[];
-
-extern u8 DRXD_ResetCEFR[];
-extern u8 DRXD_InitFEA2_1[];
-extern u8 DRXD_InitFEA2_2[];
-extern u8 DRXD_InitCPA2[];
-extern u8 DRXD_InitCEA2[];
-extern u8 DRXD_InitEQA2[];
-extern u8 DRXD_InitECA2[];
-extern u8 DRXD_ResetECA2[];
-extern u8 DRXD_ResetECRAM[];
-
-extern u8 DRXD_A2_microcode[];
-extern u32 DRXD_A2_microcode_length;
-
-extern u8 DRXD_InitFEB1_1[];
-extern u8 DRXD_InitFEB1_2[];
-extern u8 DRXD_InitCPB1[];
-extern u8 DRXD_InitCEB1[];
-extern u8 DRXD_InitEQB1[];
-extern u8 DRXD_InitECB1[];
-
-extern u8 DRXD_InitDiversityFront[];
-extern u8 DRXD_InitDiversityEnd[];
-extern u8 DRXD_DisableDiversity[];
-extern u8 DRXD_StartDiversityFront[];
-extern u8 DRXD_StartDiversityEnd[];
-
-extern u8 DRXD_DiversityDelay8MHZ[];
-extern u8 DRXD_DiversityDelay6MHZ[];
-
-extern u8 DRXD_B1_microcode[];
-extern u32 DRXD_B1_microcode_length;
-
-#endif
diff --git a/drivers/media/dvb/frontends/drxd_hard.c b/drivers/media/dvb/frontends/drxd_hard.c
deleted file mode 100644
index f380eb4..0000000
--- a/drivers/media/dvb/frontends/drxd_hard.c
+++ /dev/null
@@ -1,2992 +0,0 @@
-/*
- * drxd_hard.c: DVB-T Demodulator Micronas DRX3975D-A2,DRX397xD-B1
- *
- * Copyright (C) 2003-2007 Micronas
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 only, as published by the Free Software Foundation.
- *
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/firmware.h>
-#include <linux/i2c.h>
-#include <asm/div64.h>
-
-#include "dvb_frontend.h"
-#include "drxd.h"
-#include "drxd_firm.h"
-
-#define DRX_FW_FILENAME_A2 "drxd-a2-1.1.fw"
-#define DRX_FW_FILENAME_B1 "drxd-b1-1.1.fw"
-
-#define CHUNK_SIZE 48
-
-#define DRX_I2C_RMW           0x10
-#define DRX_I2C_BROADCAST     0x20
-#define DRX_I2C_CLEARCRC      0x80
-#define DRX_I2C_SINGLE_MASTER 0xC0
-#define DRX_I2C_MODEFLAGS     0xC0
-#define DRX_I2C_FLAGS         0xF0
-
-#ifndef SIZEOF_ARRAY
-#define SIZEOF_ARRAY(array) (sizeof((array))/sizeof((array)[0]))
-#endif
-
-#define DEFAULT_LOCK_TIMEOUT    1100
-
-#define DRX_CHANNEL_AUTO 0
-#define DRX_CHANNEL_HIGH 1
-#define DRX_CHANNEL_LOW  2
-
-#define DRX_LOCK_MPEG  1
-#define DRX_LOCK_FEC   2
-#define DRX_LOCK_DEMOD 4
-
-/****************************************************************************/
-
-enum CSCDState {
-	CSCD_INIT = 0,
-	CSCD_SET,
-	CSCD_SAVED
-};
-
-enum CDrxdState {
-	DRXD_UNINITIALIZED = 0,
-	DRXD_STOPPED,
-	DRXD_STARTED
-};
-
-enum AGC_CTRL_MODE {
-	AGC_CTRL_AUTO = 0,
-	AGC_CTRL_USER,
-	AGC_CTRL_OFF
-};
-
-enum OperationMode {
-	OM_Default,
-	OM_DVBT_Diversity_Front,
-	OM_DVBT_Diversity_End
-};
-
-struct SCfgAgc {
-	enum AGC_CTRL_MODE ctrlMode;
-	u16 outputLevel;	/* range [0, ... , 1023], 1/n of fullscale range */
-	u16 settleLevel;	/* range [0, ... , 1023], 1/n of fullscale range */
-	u16 minOutputLevel;	/* range [0, ... , 1023], 1/n of fullscale range */
-	u16 maxOutputLevel;	/* range [0, ... , 1023], 1/n of fullscale range */
-	u16 speed;		/* range [0, ... , 1023], 1/n of fullscale range */
-
-	u16 R1;
-	u16 R2;
-	u16 R3;
-};
-
-struct SNoiseCal {
-	int cpOpt;
-	short cpNexpOfs;
-	short tdCal2k;
-	short tdCal8k;
-};
-
-enum app_env {
-	APPENV_STATIC = 0,
-	APPENV_PORTABLE = 1,
-	APPENV_MOBILE = 2
-};
-
-enum EIFFilter {
-	IFFILTER_SAW = 0,
-	IFFILTER_DISCRETE = 1
-};
-
-struct drxd_state {
-	struct dvb_frontend frontend;
-	struct dvb_frontend_ops ops;
-	struct dtv_frontend_properties props;
-
-	const struct firmware *fw;
-	struct device *dev;
-
-	struct i2c_adapter *i2c;
-	void *priv;
-	struct drxd_config config;
-
-	int i2c_access;
-	int init_done;
-	struct mutex mutex;
-
-	u8 chip_adr;
-	u16 hi_cfg_timing_div;
-	u16 hi_cfg_bridge_delay;
-	u16 hi_cfg_wakeup_key;
-	u16 hi_cfg_ctrl;
-
-	u16 intermediate_freq;
-	u16 osc_clock_freq;
-
-	enum CSCDState cscd_state;
-	enum CDrxdState drxd_state;
-
-	u16 sys_clock_freq;
-	s16 osc_clock_deviation;
-	u16 expected_sys_clock_freq;
-
-	u16 insert_rs_byte;
-	u16 enable_parallel;
-
-	int operation_mode;
-
-	struct SCfgAgc if_agc_cfg;
-	struct SCfgAgc rf_agc_cfg;
-
-	struct SNoiseCal noise_cal;
-
-	u32 fe_fs_add_incr;
-	u32 org_fe_fs_add_incr;
-	u16 current_fe_if_incr;
-
-	u16 m_FeAgRegAgPwd;
-	u16 m_FeAgRegAgAgcSio;
-
-	u16 m_EcOcRegOcModeLop;
-	u16 m_EcOcRegSncSncLvl;
-	u8 *m_InitAtomicRead;
-	u8 *m_HiI2cPatch;
-
-	u8 *m_ResetCEFR;
-	u8 *m_InitFE_1;
-	u8 *m_InitFE_2;
-	u8 *m_InitCP;
-	u8 *m_InitCE;
-	u8 *m_InitEQ;
-	u8 *m_InitSC;
-	u8 *m_InitEC;
-	u8 *m_ResetECRAM;
-	u8 *m_InitDiversityFront;
-	u8 *m_InitDiversityEnd;
-	u8 *m_DisableDiversity;
-	u8 *m_StartDiversityFront;
-	u8 *m_StartDiversityEnd;
-
-	u8 *m_DiversityDelay8MHZ;
-	u8 *m_DiversityDelay6MHZ;
-
-	u8 *microcode;
-	u32 microcode_length;
-
-	int type_A;
-	int PGA;
-	int diversity;
-	int tuner_mirrors;
-
-	enum app_env app_env_default;
-	enum app_env app_env_diversity;
-
-};
-
-/****************************************************************************/
-/* I2C **********************************************************************/
-/****************************************************************************/
-
-static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 * data, int len)
-{
-	struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = data, .len = len };
-
-	if (i2c_transfer(adap, &msg, 1) != 1)
-		return -1;
-	return 0;
-}
-
-static int i2c_read(struct i2c_adapter *adap,
-		    u8 adr, u8 *msg, int len, u8 *answ, int alen)
-{
-	struct i2c_msg msgs[2] = {
-		{
-			.addr = adr, .flags = 0,
-			.buf = msg, .len = len
-		}, {
-			.addr = adr, .flags = I2C_M_RD,
-			.buf = answ, .len = alen
-		}
-	};
-	if (i2c_transfer(adap, msgs, 2) != 2)
-		return -1;
-	return 0;
-}
-
-static inline u32 MulDiv32(u32 a, u32 b, u32 c)
-{
-	u64 tmp64;
-
-	tmp64 = (u64)a * (u64)b;
-	do_div(tmp64, c);
-
-	return (u32) tmp64;
-}
-
-static int Read16(struct drxd_state *state, u32 reg, u16 *data, u8 flags)
-{
-	u8 adr = state->config.demod_address;
-	u8 mm1[4] = { reg & 0xff, (reg >> 16) & 0xff,
-		flags | ((reg >> 24) & 0xff), (reg >> 8) & 0xff
-	};
-	u8 mm2[2];
-	if (i2c_read(state->i2c, adr, mm1, 4, mm2, 2) < 0)
-		return -1;
-	if (data)
-		*data = mm2[0] | (mm2[1] << 8);
-	return mm2[0] | (mm2[1] << 8);
-}
-
-static int Read32(struct drxd_state *state, u32 reg, u32 *data, u8 flags)
-{
-	u8 adr = state->config.demod_address;
-	u8 mm1[4] = { reg & 0xff, (reg >> 16) & 0xff,
-		flags | ((reg >> 24) & 0xff), (reg >> 8) & 0xff
-	};
-	u8 mm2[4];
-
-	if (i2c_read(state->i2c, adr, mm1, 4, mm2, 4) < 0)
-		return -1;
-	if (data)
-		*data =
-		    mm2[0] | (mm2[1] << 8) | (mm2[2] << 16) | (mm2[3] << 24);
-	return 0;
-}
-
-static int Write16(struct drxd_state *state, u32 reg, u16 data, u8 flags)
-{
-	u8 adr = state->config.demod_address;
-	u8 mm[6] = { reg & 0xff, (reg >> 16) & 0xff,
-		flags | ((reg >> 24) & 0xff), (reg >> 8) & 0xff,
-		data & 0xff, (data >> 8) & 0xff
-	};
-
-	if (i2c_write(state->i2c, adr, mm, 6) < 0)
-		return -1;
-	return 0;
-}
-
-static int Write32(struct drxd_state *state, u32 reg, u32 data, u8 flags)
-{
-	u8 adr = state->config.demod_address;
-	u8 mm[8] = { reg & 0xff, (reg >> 16) & 0xff,
-		flags | ((reg >> 24) & 0xff), (reg >> 8) & 0xff,
-		data & 0xff, (data >> 8) & 0xff,
-		(data >> 16) & 0xff, (data >> 24) & 0xff
-	};
-
-	if (i2c_write(state->i2c, adr, mm, 8) < 0)
-		return -1;
-	return 0;
-}
-
-static int write_chunk(struct drxd_state *state,
-		       u32 reg, u8 *data, u32 len, u8 flags)
-{
-	u8 adr = state->config.demod_address;
-	u8 mm[CHUNK_SIZE + 4] = { reg & 0xff, (reg >> 16) & 0xff,
-		flags | ((reg >> 24) & 0xff), (reg >> 8) & 0xff
-	};
-	int i;
-
-	for (i = 0; i < len; i++)
-		mm[4 + i] = data[i];
-	if (i2c_write(state->i2c, adr, mm, 4 + len) < 0) {
-		printk(KERN_ERR "error in write_chunk\n");
-		return -1;
-	}
-	return 0;
-}
-
-static int WriteBlock(struct drxd_state *state,
-		      u32 Address, u16 BlockSize, u8 *pBlock, u8 Flags)
-{
-	while (BlockSize > 0) {
-		u16 Chunk = BlockSize > CHUNK_SIZE ? CHUNK_SIZE : BlockSize;
-
-		if (write_chunk(state, Address, pBlock, Chunk, Flags) < 0)
-			return -1;
-		pBlock += Chunk;
-		Address += (Chunk >> 1);
-		BlockSize -= Chunk;
-	}
-	return 0;
-}
-
-static int WriteTable(struct drxd_state *state, u8 * pTable)
-{
-	int status = 0;
-
-	if (pTable == NULL)
-		return 0;
-
-	while (!status) {
-		u16 Length;
-		u32 Address = pTable[0] | (pTable[1] << 8) |
-		    (pTable[2] << 16) | (pTable[3] << 24);
-
-		if (Address == 0xFFFFFFFF)
-			break;
-		pTable += sizeof(u32);
-
-		Length = pTable[0] | (pTable[1] << 8);
-		pTable += sizeof(u16);
-		if (!Length)
-			break;
-		status = WriteBlock(state, Address, Length * 2, pTable, 0);
-		pTable += (Length * 2);
-	}
-	return status;
-}
-
-/****************************************************************************/
-/****************************************************************************/
-/****************************************************************************/
-
-static int ResetCEFR(struct drxd_state *state)
-{
-	return WriteTable(state, state->m_ResetCEFR);
-}
-
-static int InitCP(struct drxd_state *state)
-{
-	return WriteTable(state, state->m_InitCP);
-}
-
-static int InitCE(struct drxd_state *state)
-{
-	int status;
-	enum app_env AppEnv = state->app_env_default;
-
-	do {
-		status = WriteTable(state, state->m_InitCE);
-		if (status < 0)
-			break;
-
-		if (state->operation_mode == OM_DVBT_Diversity_Front ||
-		    state->operation_mode == OM_DVBT_Diversity_End) {
-			AppEnv = state->app_env_diversity;
-		}
-		if (AppEnv == APPENV_STATIC) {
-			status = Write16(state, CE_REG_TAPSET__A, 0x0000, 0);
-			if (status < 0)
-				break;
-		} else if (AppEnv == APPENV_PORTABLE) {
-			status = Write16(state, CE_REG_TAPSET__A, 0x0001, 0);
-			if (status < 0)
-				break;
-		} else if (AppEnv == APPENV_MOBILE && state->type_A) {
-			status = Write16(state, CE_REG_TAPSET__A, 0x0002, 0);
-			if (status < 0)
-				break;
-		} else if (AppEnv == APPENV_MOBILE && !state->type_A) {
-			status = Write16(state, CE_REG_TAPSET__A, 0x0006, 0);
-			if (status < 0)
-				break;
-		}
-
-		/* start ce */
-		status = Write16(state, B_CE_REG_COMM_EXEC__A, 0x0001, 0);
-		if (status < 0)
-			break;
-	} while (0);
-	return status;
-}
-
-static int StopOC(struct drxd_state *state)
-{
-	int status = 0;
-	u16 ocSyncLvl = 0;
-	u16 ocModeLop = state->m_EcOcRegOcModeLop;
-	u16 dtoIncLop = 0;
-	u16 dtoIncHip = 0;
-
-	do {
-		/* Store output configuration */
-		status = Read16(state, EC_OC_REG_SNC_ISC_LVL__A, &ocSyncLvl, 0);
-		if (status < 0)
-			break;
-		/* CHK_ERROR(Read16(EC_OC_REG_OC_MODE_LOP__A, &ocModeLop)); */
-		state->m_EcOcRegSncSncLvl = ocSyncLvl;
-		/* m_EcOcRegOcModeLop = ocModeLop; */
-
-		/* Flush FIFO (byte-boundary) at fixed rate */
-		status = Read16(state, EC_OC_REG_RCN_MAP_LOP__A, &dtoIncLop, 0);
-		if (status < 0)
-			break;
-		status = Read16(state, EC_OC_REG_RCN_MAP_HIP__A, &dtoIncHip, 0);
-		if (status < 0)
-			break;
-		status = Write16(state, EC_OC_REG_DTO_INC_LOP__A, dtoIncLop, 0);
-		if (status < 0)
-			break;
-		status = Write16(state, EC_OC_REG_DTO_INC_HIP__A, dtoIncHip, 0);
-		if (status < 0)
-			break;
-		ocModeLop &= ~(EC_OC_REG_OC_MODE_LOP_DTO_CTR_SRC__M);
-		ocModeLop |= EC_OC_REG_OC_MODE_LOP_DTO_CTR_SRC_STATIC;
-		status = Write16(state, EC_OC_REG_OC_MODE_LOP__A, ocModeLop, 0);
-		if (status < 0)
-			break;
-		status = Write16(state, EC_OC_REG_COMM_EXEC__A, EC_OC_REG_COMM_EXEC_CTL_HOLD, 0);
-		if (status < 0)
-			break;
-
-		msleep(1);
-		/* Output pins to '0' */
-		status = Write16(state, EC_OC_REG_OCR_MPG_UOS__A, EC_OC_REG_OCR_MPG_UOS__M, 0);
-		if (status < 0)
-			break;
-
-		/* Force the OC out of sync */
-		ocSyncLvl &= ~(EC_OC_REG_SNC_ISC_LVL_OSC__M);
-		status = Write16(state, EC_OC_REG_SNC_ISC_LVL__A, ocSyncLvl, 0);
-		if (status < 0)
-			break;
-		ocModeLop &= ~(EC_OC_REG_OC_MODE_LOP_PAR_ENA__M);
-		ocModeLop |= EC_OC_REG_OC_MODE_LOP_PAR_ENA_ENABLE;
-		ocModeLop |= 0x2;	/* Magically-out-of-sync */
-		status = Write16(state, EC_OC_REG_OC_MODE_LOP__A, ocModeLop, 0);
-		if (status < 0)
-			break;
-		status = Write16(state, EC_OC_REG_COMM_INT_STA__A, 0x0, 0);
-		if (status < 0)
-			break;
-		status = Write16(state, EC_OC_REG_COMM_EXEC__A, EC_OC_REG_COMM_EXEC_CTL_ACTIVE, 0);
-		if (status < 0)
-			break;
-	} while (0);
-
-	return status;
-}
-
-static int StartOC(struct drxd_state *state)
-{
-	int status = 0;
-
-	do {
-		/* Stop OC */
-		status = Write16(state, EC_OC_REG_COMM_EXEC__A, EC_OC_REG_COMM_EXEC_CTL_HOLD, 0);
-		if (status < 0)
-			break;
-
-		/* Restore output configuration */
-		status = Write16(state, EC_OC_REG_SNC_ISC_LVL__A, state->m_EcOcRegSncSncLvl, 0);
-		if (status < 0)
-			break;
-		status = Write16(state, EC_OC_REG_OC_MODE_LOP__A, state->m_EcOcRegOcModeLop, 0);
-		if (status < 0)
-			break;
-
-		/* Output pins active again */
-		status = Write16(state, EC_OC_REG_OCR_MPG_UOS__A, EC_OC_REG_OCR_MPG_UOS_INIT, 0);
-		if (status < 0)
-			break;
-
-		/* Start OC */
-		status = Write16(state, EC_OC_REG_COMM_EXEC__A, EC_OC_REG_COMM_EXEC_CTL_ACTIVE, 0);
-		if (status < 0)
-			break;
-	} while (0);
-	return status;
-}
-
-static int InitEQ(struct drxd_state *state)
-{
-	return WriteTable(state, state->m_InitEQ);
-}
-
-static int InitEC(struct drxd_state *state)
-{
-	return WriteTable(state, state->m_InitEC);
-}
-
-static int InitSC(struct drxd_state *state)
-{
-	return WriteTable(state, state->m_InitSC);
-}
-
-static int InitAtomicRead(struct drxd_state *state)
-{
-	return WriteTable(state, state->m_InitAtomicRead);
-}
-
-static int CorrectSysClockDeviation(struct drxd_state *state);
-
-static int DRX_GetLockStatus(struct drxd_state *state, u32 * pLockStatus)
-{
-	u16 ScRaRamLock = 0;
-	const u16 mpeg_lock_mask = (SC_RA_RAM_LOCK_MPEG__M |
-				    SC_RA_RAM_LOCK_FEC__M |
-				    SC_RA_RAM_LOCK_DEMOD__M);
-	const u16 fec_lock_mask = (SC_RA_RAM_LOCK_FEC__M |
-				   SC_RA_RAM_LOCK_DEMOD__M);
-	const u16 demod_lock_mask = SC_RA_RAM_LOCK_DEMOD__M;
-
-	int status;
-
-	*pLockStatus = 0;
-
-	status = Read16(state, SC_RA_RAM_LOCK__A, &ScRaRamLock, 0x0000);
-	if (status < 0) {
-		printk(KERN_ERR "Can't read SC_RA_RAM_LOCK__A status = %08x\n", status);
-		return status;
-	}
-
-	if (state->drxd_state != DRXD_STARTED)
-		return 0;
-
-	if ((ScRaRamLock & mpeg_lock_mask) == mpeg_lock_mask) {
-		*pLockStatus |= DRX_LOCK_MPEG;
-		CorrectSysClockDeviation(state);
-	}
-
-	if ((ScRaRamLock & fec_lock_mask) == fec_lock_mask)
-		*pLockStatus |= DRX_LOCK_FEC;
-
-	if ((ScRaRamLock & demod_lock_mask) == demod_lock_mask)
-		*pLockStatus |= DRX_LOCK_DEMOD;
-	return 0;
-}
-
-/****************************************************************************/
-
-static int SetCfgIfAgc(struct drxd_state *state, struct SCfgAgc *cfg)
-{
-	int status;
-
-	if (cfg->outputLevel > DRXD_FE_CTRL_MAX)
-		return -1;
-
-	if (cfg->ctrlMode == AGC_CTRL_USER) {
-		do {
-			u16 FeAgRegPm1AgcWri;
-			u16 FeAgRegAgModeLop;
-
-			status = Read16(state, FE_AG_REG_AG_MODE_LOP__A, &FeAgRegAgModeLop, 0);
-			if (status < 0)
-				break;
-			FeAgRegAgModeLop &= (~FE_AG_REG_AG_MODE_LOP_MODE_4__M);
-			FeAgRegAgModeLop |= FE_AG_REG_AG_MODE_LOP_MODE_4_STATIC;
-			status = Write16(state, FE_AG_REG_AG_MODE_LOP__A, FeAgRegAgModeLop, 0);
-			if (status < 0)
-				break;
-
-			FeAgRegPm1AgcWri = (u16) (cfg->outputLevel &
-						  FE_AG_REG_PM1_AGC_WRI__M);
-			status = Write16(state, FE_AG_REG_PM1_AGC_WRI__A, FeAgRegPm1AgcWri, 0);
-			if (status < 0)
-				break;
-		} while (0);
-	} else if (cfg->ctrlMode == AGC_CTRL_AUTO) {
-		if (((cfg->maxOutputLevel) < (cfg->minOutputLevel)) ||
-		    ((cfg->maxOutputLevel) > DRXD_FE_CTRL_MAX) ||
-		    ((cfg->speed) > DRXD_FE_CTRL_MAX) ||
-		    ((cfg->settleLevel) > DRXD_FE_CTRL_MAX)
-		    )
-			return -1;
-		do {
-			u16 FeAgRegAgModeLop;
-			u16 FeAgRegEgcSetLvl;
-			u16 slope, offset;
-
-			/* == Mode == */
-
-			status = Read16(state, FE_AG_REG_AG_MODE_LOP__A, &FeAgRegAgModeLop, 0);
-			if (status < 0)
-				break;
-			FeAgRegAgModeLop &= (~FE_AG_REG_AG_MODE_LOP_MODE_4__M);
-			FeAgRegAgModeLop |=
-			    FE_AG_REG_AG_MODE_LOP_MODE_4_DYNAMIC;
-			status = Write16(state, FE_AG_REG_AG_MODE_LOP__A, FeAgRegAgModeLop, 0);
-			if (status < 0)
-				break;
-
-			/* == Settle level == */
-
-			FeAgRegEgcSetLvl = (u16) ((cfg->settleLevel >> 1) &
-						  FE_AG_REG_EGC_SET_LVL__M);
-			status = Write16(state, FE_AG_REG_EGC_SET_LVL__A, FeAgRegEgcSetLvl, 0);
-			if (status < 0)
-				break;
-
-			/* == Min/Max == */
-
-			slope = (u16) ((cfg->maxOutputLevel -
-					cfg->minOutputLevel) / 2);
-			offset = (u16) ((cfg->maxOutputLevel +
-					 cfg->minOutputLevel) / 2 - 511);
-
-			status = Write16(state, FE_AG_REG_GC1_AGC_RIC__A, slope, 0);
-			if (status < 0)
-				break;
-			status = Write16(state, FE_AG_REG_GC1_AGC_OFF__A, offset, 0);
-			if (status < 0)
-				break;
-
-			/* == Speed == */
-			{
-				const u16 maxRur = 8;
-				const u16 slowIncrDecLUT[] = { 3, 4, 4, 5, 6 };
-				const u16 fastIncrDecLUT[] = { 14, 15, 15, 16,
-					17, 18, 18, 19,
-					20, 21, 22, 23,
-					24, 26, 27, 28,
-					29, 31
-				};
-
-				u16 fineSteps = (DRXD_FE_CTRL_MAX + 1) /
-				    (maxRur + 1);
-				u16 fineSpeed = (u16) (cfg->speed -
-						       ((cfg->speed /
-							 fineSteps) *
-							fineSteps));
-				u16 invRurCount = (u16) (cfg->speed /
-							 fineSteps);
-				u16 rurCount;
-				if (invRurCount > maxRur) {
-					rurCount = 0;
-					fineSpeed += fineSteps;
-				} else {
-					rurCount = maxRur - invRurCount;
-				}
-
-				/*
-				   fastInc = default *
-				   (2^(fineSpeed/fineSteps))
-				   => range[default...2*default>
-				   slowInc = default *
-				   (2^(fineSpeed/fineSteps))
-				 */
-				{
-					u16 fastIncrDec =
-					    fastIncrDecLUT[fineSpeed /
-							   ((fineSteps /
-							     (14 + 1)) + 1)];
-					u16 slowIncrDec =
-					    slowIncrDecLUT[fineSpeed /
-							   (fineSteps /
-							    (3 + 1))];
-
-					status = Write16(state, FE_AG_REG_EGC_RUR_CNT__A, rurCount, 0);
-					if (status < 0)
-						break;
-					status = Write16(state, FE_AG_REG_EGC_FAS_INC__A, fastIncrDec, 0);
-					if (status < 0)
-						break;
-					status = Write16(state, FE_AG_REG_EGC_FAS_DEC__A, fastIncrDec, 0);
-					if (status < 0)
-						break;
-					status = Write16(state, FE_AG_REG_EGC_SLO_INC__A, slowIncrDec, 0);
-					if (status < 0)
-						break;
-					status = Write16(state, FE_AG_REG_EGC_SLO_DEC__A, slowIncrDec, 0);
-					if (status < 0)
-						break;
-				}
-			}
-		} while (0);
-
-	} else {
-		/* No OFF mode for IF control */
-		return -1;
-	}
-	return status;
-}
-
-static int SetCfgRfAgc(struct drxd_state *state, struct SCfgAgc *cfg)
-{
-	int status = 0;
-
-	if (cfg->outputLevel > DRXD_FE_CTRL_MAX)
-		return -1;
-
-	if (cfg->ctrlMode == AGC_CTRL_USER) {
-		do {
-			u16 AgModeLop = 0;
-			u16 level = (cfg->outputLevel);
-
-			if (level == DRXD_FE_CTRL_MAX)
-				level++;
-
-			status = Write16(state, FE_AG_REG_PM2_AGC_WRI__A, level, 0x0000);
-			if (status < 0)
-				break;
-
-			/*==== Mode ====*/
-
-			/* Powerdown PD2, WRI source */
-			state->m_FeAgRegAgPwd &= ~(FE_AG_REG_AG_PWD_PWD_PD2__M);
-			state->m_FeAgRegAgPwd |=
-			    FE_AG_REG_AG_PWD_PWD_PD2_DISABLE;
-			status = Write16(state, FE_AG_REG_AG_PWD__A, state->m_FeAgRegAgPwd, 0x0000);
-			if (status < 0)
-				break;
-
-			status = Read16(state, FE_AG_REG_AG_MODE_LOP__A, &AgModeLop, 0x0000);
-			if (status < 0)
-				break;
-			AgModeLop &= (~(FE_AG_REG_AG_MODE_LOP_MODE_5__M |
-					FE_AG_REG_AG_MODE_LOP_MODE_E__M));
-			AgModeLop |= (FE_AG_REG_AG_MODE_LOP_MODE_5_STATIC |
-				      FE_AG_REG_AG_MODE_LOP_MODE_E_STATIC);
-			status = Write16(state, FE_AG_REG_AG_MODE_LOP__A, AgModeLop, 0x0000);
-			if (status < 0)
-				break;
-
-			/* enable AGC2 pin */
-			{
-				u16 FeAgRegAgAgcSio = 0;
-				status = Read16(state, FE_AG_REG_AG_AGC_SIO__A, &FeAgRegAgAgcSio, 0x0000);
-				if (status < 0)
-					break;
-				FeAgRegAgAgcSio &=
-				    ~(FE_AG_REG_AG_AGC_SIO_AGC_SIO_2__M);
-				FeAgRegAgAgcSio |=
-				    FE_AG_REG_AG_AGC_SIO_AGC_SIO_2_OUTPUT;
-				status = Write16(state, FE_AG_REG_AG_AGC_SIO__A, FeAgRegAgAgcSio, 0x0000);
-				if (status < 0)
-					break;
-			}
-
-		} while (0);
-	} else if (cfg->ctrlMode == AGC_CTRL_AUTO) {
-		u16 AgModeLop = 0;
-
-		do {
-			u16 level;
-			/* Automatic control */
-			/* Powerup PD2, AGC2 as output, TGC source */
-			(state->m_FeAgRegAgPwd) &=
-			    ~(FE_AG_REG_AG_PWD_PWD_PD2__M);
-			(state->m_FeAgRegAgPwd) |=
-			    FE_AG_REG_AG_PWD_PWD_PD2_DISABLE;
-			status = Write16(state, FE_AG_REG_AG_PWD__A, (state->m_FeAgRegAgPwd), 0x0000);
-			if (status < 0)
-				break;
-
-			status = Read16(state, FE_AG_REG_AG_MODE_LOP__A, &AgModeLop, 0x0000);
-			if (status < 0)
-				break;
-			AgModeLop &= (~(FE_AG_REG_AG_MODE_LOP_MODE_5__M |
-					FE_AG_REG_AG_MODE_LOP_MODE_E__M));
-			AgModeLop |= (FE_AG_REG_AG_MODE_LOP_MODE_5_STATIC |
-				      FE_AG_REG_AG_MODE_LOP_MODE_E_DYNAMIC);
-			status = Write16(state, FE_AG_REG_AG_MODE_LOP__A, AgModeLop, 0x0000);
-			if (status < 0)
-				break;
-			/* Settle level */
-			level = (((cfg->settleLevel) >> 4) &
-				 FE_AG_REG_TGC_SET_LVL__M);
-			status = Write16(state, FE_AG_REG_TGC_SET_LVL__A, level, 0x0000);
-			if (status < 0)
-				break;
-
-			/* Min/max: don't care */
-
-			/* Speed: TODO */
-
-			/* enable AGC2 pin */
-			{
-				u16 FeAgRegAgAgcSio = 0;
-				status = Read16(state, FE_AG_REG_AG_AGC_SIO__A, &FeAgRegAgAgcSio, 0x0000);
-				if (status < 0)
-					break;
-				FeAgRegAgAgcSio &=
-				    ~(FE_AG_REG_AG_AGC_SIO_AGC_SIO_2__M);
-				FeAgRegAgAgcSio |=
-				    FE_AG_REG_AG_AGC_SIO_AGC_SIO_2_OUTPUT;
-				status = Write16(state, FE_AG_REG_AG_AGC_SIO__A, FeAgRegAgAgcSio, 0x0000);
-				if (status < 0)
-					break;
-			}
-
-		} while (0);
-	} else {
-		u16 AgModeLop = 0;
-
-		do {
-			/* No RF AGC control */
-			/* Powerdown PD2, AGC2 as output, WRI source */
-			(state->m_FeAgRegAgPwd) &=
-			    ~(FE_AG_REG_AG_PWD_PWD_PD2__M);
-			(state->m_FeAgRegAgPwd) |=
-			    FE_AG_REG_AG_PWD_PWD_PD2_ENABLE;
-			status = Write16(state, FE_AG_REG_AG_PWD__A, (state->m_FeAgRegAgPwd), 0x0000);
-			if (status < 0)
-				break;
-
-			status = Read16(state, FE_AG_REG_AG_MODE_LOP__A, &AgModeLop, 0x0000);
-			if (status < 0)
-				break;
-			AgModeLop &= (~(FE_AG_REG_AG_MODE_LOP_MODE_5__M |
-					FE_AG_REG_AG_MODE_LOP_MODE_E__M));
-			AgModeLop |= (FE_AG_REG_AG_MODE_LOP_MODE_5_STATIC |
-				      FE_AG_REG_AG_MODE_LOP_MODE_E_STATIC);
-			status = Write16(state, FE_AG_REG_AG_MODE_LOP__A, AgModeLop, 0x0000);
-			if (status < 0)
-				break;
-
-			/* set FeAgRegAgAgcSio AGC2 (RF) as input */
-			{
-				u16 FeAgRegAgAgcSio = 0;
-				status = Read16(state, FE_AG_REG_AG_AGC_SIO__A, &FeAgRegAgAgcSio, 0x0000);
-				if (status < 0)
-					break;
-				FeAgRegAgAgcSio &=
-				    ~(FE_AG_REG_AG_AGC_SIO_AGC_SIO_2__M);
-				FeAgRegAgAgcSio |=
-				    FE_AG_REG_AG_AGC_SIO_AGC_SIO_2_INPUT;
-				status = Write16(state, FE_AG_REG_AG_AGC_SIO__A, FeAgRegAgAgcSio, 0x0000);
-				if (status < 0)
-					break;
-			}
-		} while (0);
-	}
-	return status;
-}
-
-static int ReadIFAgc(struct drxd_state *state, u32 * pValue)
-{
-	int status = 0;
-
-	*pValue = 0;
-	if (state->if_agc_cfg.ctrlMode != AGC_CTRL_OFF) {
-		u16 Value;
-		status = Read16(state, FE_AG_REG_GC1_AGC_DAT__A, &Value, 0);
-		Value &= FE_AG_REG_GC1_AGC_DAT__M;
-		if (status >= 0) {
-			/*           3.3V
-			   |
-			   R1
-			   |
-			   Vin - R3 - * -- Vout
-			   |
-			   R2
-			   |
-			   GND
-			 */
-			u32 R1 = state->if_agc_cfg.R1;
-			u32 R2 = state->if_agc_cfg.R2;
-			u32 R3 = state->if_agc_cfg.R3;
-
-			u32 Vmax, Rpar, Vmin, Vout;
-
-			if (R2 == 0 && (R1 == 0 || R3 == 0))
-				return 0;
-
-			Vmax = (3300 * R2) / (R1 + R2);
-			Rpar = (R2 * R3) / (R3 + R2);
-			Vmin = (3300 * Rpar) / (R1 + Rpar);
-			Vout = Vmin + ((Vmax - Vmin) * Value) / 1024;
-
-			*pValue = Vout;
-		}
-	}
-	return status;
-}
-
-static int load_firmware(struct drxd_state *state, const char *fw_name)
-{
-	const struct firmware *fw;
-
-	if (request_firmware(&fw, fw_name, state->dev) < 0) {
-		printk(KERN_ERR "drxd: firmware load failure [%s]\n", fw_name);
-		return -EIO;
-	}
-
-	state->microcode = kmemdup(fw->data, fw->size, GFP_KERNEL);
-	if (state->microcode == NULL) {
-		release_firmware(fw);
-		printk(KERN_ERR "drxd: firmware load failure: no memory\n");
-		return -ENOMEM;
-	}
-
-	state->microcode_length = fw->size;
-	release_firmware(fw);
-	return 0;
-}
-
-static int DownloadMicrocode(struct drxd_state *state,
-			     const u8 *pMCImage, u32 Length)
-{
-	u8 *pSrc;
-	u32 Address;
-	u16 nBlocks;
-	u16 BlockSize;
-	u32 offset = 0;
-	int i, status = 0;
-
-	pSrc = (u8 *) pMCImage;
-	/* We're not using Flags */
-	/* Flags = (pSrc[0] << 8) | pSrc[1]; */
-	pSrc += sizeof(u16);
-	offset += sizeof(u16);
-	nBlocks = (pSrc[0] << 8) | pSrc[1];
-	pSrc += sizeof(u16);
-	offset += sizeof(u16);
-
-	for (i = 0; i < nBlocks; i++) {
-		Address = (pSrc[0] << 24) | (pSrc[1] << 16) |
-		    (pSrc[2] << 8) | pSrc[3];
-		pSrc += sizeof(u32);
-		offset += sizeof(u32);
-
-		BlockSize = ((pSrc[0] << 8) | pSrc[1]) * sizeof(u16);
-		pSrc += sizeof(u16);
-		offset += sizeof(u16);
-
-		/* We're not using Flags */
-		/* u16 Flags = (pSrc[0] << 8) | pSrc[1]; */
-		pSrc += sizeof(u16);
-		offset += sizeof(u16);
-
-		/* We're not using BlockCRC */
-		/* u16 BlockCRC = (pSrc[0] << 8) | pSrc[1]; */
-		pSrc += sizeof(u16);
-		offset += sizeof(u16);
-
-		status = WriteBlock(state, Address, BlockSize,
-				    pSrc, DRX_I2C_CLEARCRC);
-		if (status < 0)
-			break;
-		pSrc += BlockSize;
-		offset += BlockSize;
-	}
-
-	return status;
-}
-
-static int HI_Command(struct drxd_state *state, u16 cmd, u16 * pResult)
-{
-	u32 nrRetries = 0;
-	u16 waitCmd;
-	int status;
-
-	status = Write16(state, HI_RA_RAM_SRV_CMD__A, cmd, 0);
-	if (status < 0)
-		return status;
-
-	do {
-		nrRetries += 1;
-		if (nrRetries > DRXD_MAX_RETRIES) {
-			status = -1;
-			break;
-		};
-		status = Read16(state, HI_RA_RAM_SRV_CMD__A, &waitCmd, 0);
-	} while (waitCmd != 0);
-
-	if (status >= 0)
-		status = Read16(state, HI_RA_RAM_SRV_RES__A, pResult, 0);
-	return status;
-}
-
-static int HI_CfgCommand(struct drxd_state *state)
-{
-	int status = 0;
-
-	mutex_lock(&state->mutex);
-	Write16(state, HI_RA_RAM_SRV_CFG_KEY__A, HI_RA_RAM_SRV_RST_KEY_ACT, 0);
-	Write16(state, HI_RA_RAM_SRV_CFG_DIV__A, state->hi_cfg_timing_div, 0);
-	Write16(state, HI_RA_RAM_SRV_CFG_BDL__A, state->hi_cfg_bridge_delay, 0);
-	Write16(state, HI_RA_RAM_SRV_CFG_WUP__A, state->hi_cfg_wakeup_key, 0);
-	Write16(state, HI_RA_RAM_SRV_CFG_ACT__A, state->hi_cfg_ctrl, 0);
-
-	Write16(state, HI_RA_RAM_SRV_CFG_KEY__A, HI_RA_RAM_SRV_RST_KEY_ACT, 0);
-
-	if ((state->hi_cfg_ctrl & HI_RA_RAM_SRV_CFG_ACT_PWD_EXE) ==
-	    HI_RA_RAM_SRV_CFG_ACT_PWD_EXE)
-		status = Write16(state, HI_RA_RAM_SRV_CMD__A,
-				 HI_RA_RAM_SRV_CMD_CONFIG, 0);
-	else
-		status = HI_Command(state, HI_RA_RAM_SRV_CMD_CONFIG, 0);
-	mutex_unlock(&state->mutex);
-	return status;
-}
-
-static int InitHI(struct drxd_state *state)
-{
-	state->hi_cfg_wakeup_key = (state->chip_adr);
-	/* port/bridge/power down ctrl */
-	state->hi_cfg_ctrl = HI_RA_RAM_SRV_CFG_ACT_SLV0_ON;
-	return HI_CfgCommand(state);
-}
-
-static int HI_ResetCommand(struct drxd_state *state)
-{
-	int status;
-
-	mutex_lock(&state->mutex);
-	status = Write16(state, HI_RA_RAM_SRV_RST_KEY__A,
-			 HI_RA_RAM_SRV_RST_KEY_ACT, 0);
-	if (status == 0)
-		status = HI_Command(state, HI_RA_RAM_SRV_CMD_RESET, 0);
-	mutex_unlock(&state->mutex);
-	msleep(1);
-	return status;
-}
-
-static int DRX_ConfigureI2CBridge(struct drxd_state *state, int bEnableBridge)
-{
-	state->hi_cfg_ctrl &= (~HI_RA_RAM_SRV_CFG_ACT_BRD__M);
-	if (bEnableBridge)
-		state->hi_cfg_ctrl |= HI_RA_RAM_SRV_CFG_ACT_BRD_ON;
-	else
-		state->hi_cfg_ctrl |= HI_RA_RAM_SRV_CFG_ACT_BRD_OFF;
-
-	return HI_CfgCommand(state);
-}
-
-#define HI_TR_WRITE      0x9
-#define HI_TR_READ       0xA
-#define HI_TR_READ_WRITE 0xB
-#define HI_TR_BROADCAST  0x4
-
-#if 0
-static int AtomicReadBlock(struct drxd_state *state,
-			   u32 Addr, u16 DataSize, u8 *pData, u8 Flags)
-{
-	int status;
-	int i = 0;
-
-	/* Parameter check */
-	if ((!pData) || ((DataSize & 1) != 0))
-		return -1;
-
-	mutex_lock(&state->mutex);
-
-	do {
-		/* Instruct HI to read n bytes */
-		/* TODO use proper names forthese egisters */
-		status = Write16(state, HI_RA_RAM_SRV_CFG_KEY__A, (HI_TR_FUNC_ADDR & 0xFFFF), 0);
-		if (status < 0)
-			break;
-		status = Write16(state, HI_RA_RAM_SRV_CFG_DIV__A, (u16) (Addr >> 16), 0);
-		if (status < 0)
-			break;
-		status = Write16(state, HI_RA_RAM_SRV_CFG_BDL__A, (u16) (Addr & 0xFFFF), 0);
-		if (status < 0)
-			break;
-		status = Write16(state, HI_RA_RAM_SRV_CFG_WUP__A, (u16) ((DataSize / 2) - 1), 0);
-		if (status < 0)
-			break;
-		status = Write16(state, HI_RA_RAM_SRV_CFG_ACT__A, HI_TR_READ, 0);
-		if (status < 0)
-			break;
-
-		status = HI_Command(state, HI_RA_RAM_SRV_CMD_EXECUTE, 0);
-		if (status < 0)
-			break;
-
-	} while (0);
-
-	if (status >= 0) {
-		for (i = 0; i < (DataSize / 2); i += 1) {
-			u16 word;
-
-			status = Read16(state, (HI_RA_RAM_USR_BEGIN__A + i),
-					&word, 0);
-			if (status < 0)
-				break;
-			pData[2 * i] = (u8) (word & 0xFF);
-			pData[(2 * i) + 1] = (u8) (word >> 8);
-		}
-	}
-	mutex_unlock(&state->mutex);
-	return status;
-}
-
-static int AtomicReadReg32(struct drxd_state *state,
-			   u32 Addr, u32 *pData, u8 Flags)
-{
-	u8 buf[sizeof(u32)];
-	int status;
-
-	if (!pData)
-		return -1;
-	status = AtomicReadBlock(state, Addr, sizeof(u32), buf, Flags);
-	*pData = (((u32) buf[0]) << 0) +
-	    (((u32) buf[1]) << 8) +
-	    (((u32) buf[2]) << 16) + (((u32) buf[3]) << 24);
-	return status;
-}
-#endif
-
-static int StopAllProcessors(struct drxd_state *state)
-{
-	return Write16(state, HI_COMM_EXEC__A,
-		       SC_COMM_EXEC_CTL_STOP, DRX_I2C_BROADCAST);
-}
-
-static int EnableAndResetMB(struct drxd_state *state)
-{
-	if (state->type_A) {
-		/* disable? monitor bus observe @ EC_OC */
-		Write16(state, EC_OC_REG_OC_MON_SIO__A, 0x0000, 0x0000);
-	}
-
-	/* do inverse broadcast, followed by explicit write to HI */
-	Write16(state, HI_COMM_MB__A, 0x0000, DRX_I2C_BROADCAST);
-	Write16(state, HI_COMM_MB__A, 0x0000, 0x0000);
-	return 0;
-}
-
-static int InitCC(struct drxd_state *state)
-{
-	if (state->osc_clock_freq == 0 ||
-	    state->osc_clock_freq > 20000 ||
-	    (state->osc_clock_freq % 4000) != 0) {
-		printk(KERN_ERR "invalid osc frequency %d\n", state->osc_clock_freq);
-		return -1;
-	}
-
-	Write16(state, CC_REG_OSC_MODE__A, CC_REG_OSC_MODE_M20, 0);
-	Write16(state, CC_REG_PLL_MODE__A, CC_REG_PLL_MODE_BYPASS_PLL |
-		CC_REG_PLL_MODE_PUMP_CUR_12, 0);
-	Write16(state, CC_REG_REF_DIVIDE__A, state->osc_clock_freq / 4000, 0);
-	Write16(state, CC_REG_PWD_MODE__A, CC_REG_PWD_MODE_DOWN_PLL, 0);
-	Write16(state, CC_REG_UPDATE__A, CC_REG_UPDATE_KEY, 0);
-
-	return 0;
-}
-
-static int ResetECOD(struct drxd_state *state)
-{
-	int status = 0;
-
-	if (state->type_A)
-		status = Write16(state, EC_OD_REG_SYNC__A, 0x0664, 0);
-	else
-		status = Write16(state, B_EC_OD_REG_SYNC__A, 0x0664, 0);
-
-	if (!(status < 0))
-		status = WriteTable(state, state->m_ResetECRAM);
-	if (!(status < 0))
-		status = Write16(state, EC_OD_REG_COMM_EXEC__A, 0x0001, 0);
-	return status;
-}
-
-/* Configure PGA switch */
-
-static int SetCfgPga(struct drxd_state *state, int pgaSwitch)
-{
-	int status;
-	u16 AgModeLop = 0;
-	u16 AgModeHip = 0;
-	do {
-		if (pgaSwitch) {
-			/* PGA on */
-			/* fine gain */
-			status = Read16(state, B_FE_AG_REG_AG_MODE_LOP__A, &AgModeLop, 0x0000);
-			if (status < 0)
-				break;
-			AgModeLop &= (~(B_FE_AG_REG_AG_MODE_LOP_MODE_C__M));
-			AgModeLop |= B_FE_AG_REG_AG_MODE_LOP_MODE_C_DYNAMIC;
-			status = Write16(state, B_FE_AG_REG_AG_MODE_LOP__A, AgModeLop, 0x0000);
-			if (status < 0)
-				break;
-
-			/* coarse gain */
-			status = Read16(state, B_FE_AG_REG_AG_MODE_HIP__A, &AgModeHip, 0x0000);
-			if (status < 0)
-				break;
-			AgModeHip &= (~(B_FE_AG_REG_AG_MODE_HIP_MODE_J__M));
-			AgModeHip |= B_FE_AG_REG_AG_MODE_HIP_MODE_J_DYNAMIC;
-			status = Write16(state, B_FE_AG_REG_AG_MODE_HIP__A, AgModeHip, 0x0000);
-			if (status < 0)
-				break;
-
-			/* enable fine and coarse gain, enable AAF,
-			   no ext resistor */
-			status = Write16(state, B_FE_AG_REG_AG_PGA_MODE__A, B_FE_AG_REG_AG_PGA_MODE_PFY_PCY_AFY_REN, 0x0000);
-			if (status < 0)
-				break;
-		} else {
-			/* PGA off, bypass */
-
-			/* fine gain */
-			status = Read16(state, B_FE_AG_REG_AG_MODE_LOP__A, &AgModeLop, 0x0000);
-			if (status < 0)
-				break;
-			AgModeLop &= (~(B_FE_AG_REG_AG_MODE_LOP_MODE_C__M));
-			AgModeLop |= B_FE_AG_REG_AG_MODE_LOP_MODE_C_STATIC;
-			status = Write16(state, B_FE_AG_REG_AG_MODE_LOP__A, AgModeLop, 0x0000);
-			if (status < 0)
-				break;
-
-			/* coarse gain */
-			status = Read16(state, B_FE_AG_REG_AG_MODE_HIP__A, &AgModeHip, 0x0000);
-			if (status < 0)
-				break;
-			AgModeHip &= (~(B_FE_AG_REG_AG_MODE_HIP_MODE_J__M));
-			AgModeHip |= B_FE_AG_REG_AG_MODE_HIP_MODE_J_STATIC;
-			status = Write16(state, B_FE_AG_REG_AG_MODE_HIP__A, AgModeHip, 0x0000);
-			if (status < 0)
-				break;
-
-			/* disable fine and coarse gain, enable AAF,
-			   no ext resistor */
-			status = Write16(state, B_FE_AG_REG_AG_PGA_MODE__A, B_FE_AG_REG_AG_PGA_MODE_PFN_PCN_AFY_REN, 0x0000);
-			if (status < 0)
-				break;
-		}
-	} while (0);
-	return status;
-}
-
-static int InitFE(struct drxd_state *state)
-{
-	int status;
-
-	do {
-		status = WriteTable(state, state->m_InitFE_1);
-		if (status < 0)
-			break;
-
-		if (state->type_A) {
-			status = Write16(state, FE_AG_REG_AG_PGA_MODE__A,
-					 FE_AG_REG_AG_PGA_MODE_PFN_PCN_AFY_REN,
-					 0);
-		} else {
-			if (state->PGA)
-				status = SetCfgPga(state, 0);
-			else
-				status =
-				    Write16(state, B_FE_AG_REG_AG_PGA_MODE__A,
-					    B_FE_AG_REG_AG_PGA_MODE_PFN_PCN_AFY_REN,
-					    0);
-		}
-
-		if (status < 0)
-			break;
-		status = Write16(state, FE_AG_REG_AG_AGC_SIO__A, state->m_FeAgRegAgAgcSio, 0x0000);
-		if (status < 0)
-			break;
-		status = Write16(state, FE_AG_REG_AG_PWD__A, state->m_FeAgRegAgPwd, 0x0000);
-		if (status < 0)
-			break;
-
-		status = WriteTable(state, state->m_InitFE_2);
-		if (status < 0)
-			break;
-
-	} while (0);
-
-	return status;
-}
-
-static int InitFT(struct drxd_state *state)
-{
-	/*
-	   norm OFFSET,  MB says =2 voor 8K en =3 voor 2K waarschijnlijk
-	   SC stuff
-	 */
-	return Write16(state, FT_REG_COMM_EXEC__A, 0x0001, 0x0000);
-}
-
-static int SC_WaitForReady(struct drxd_state *state)
-{
-	u16 curCmd;
-	int i;
-
-	for (i = 0; i < DRXD_MAX_RETRIES; i += 1) {
-		int status = Read16(state, SC_RA_RAM_CMD__A, &curCmd, 0);
-		if (status == 0 || curCmd == 0)
-			return status;
-	}
-	return -1;
-}
-
-static int SC_SendCommand(struct drxd_state *state, u16 cmd)
-{
-	int status = 0;
-	u16 errCode;
-
-	Write16(state, SC_RA_RAM_CMD__A, cmd, 0);
-	SC_WaitForReady(state);
-
-	Read16(state, SC_RA_RAM_CMD_ADDR__A, &errCode, 0);
-
-	if (errCode == 0xFFFF) {
-		printk(KERN_ERR "Command Error\n");
-		status = -1;
-	}
-
-	return status;
-}
-
-static int SC_ProcStartCommand(struct drxd_state *state,
-			       u16 subCmd, u16 param0, u16 param1)
-{
-	int status = 0;
-	u16 scExec;
-
-	mutex_lock(&state->mutex);
-	do {
-		Read16(state, SC_COMM_EXEC__A, &scExec, 0);
-		if (scExec != 1) {
-			status = -1;
-			break;
-		}
-		SC_WaitForReady(state);
-		Write16(state, SC_RA_RAM_CMD_ADDR__A, subCmd, 0);
-		Write16(state, SC_RA_RAM_PARAM1__A, param1, 0);
-		Write16(state, SC_RA_RAM_PARAM0__A, param0, 0);
-
-		SC_SendCommand(state, SC_RA_RAM_CMD_PROC_START);
-	} while (0);
-	mutex_unlock(&state->mutex);
-	return status;
-}
-
-static int SC_SetPrefParamCommand(struct drxd_state *state,
-				  u16 subCmd, u16 param0, u16 param1)
-{
-	int status;
-
-	mutex_lock(&state->mutex);
-	do {
-		status = SC_WaitForReady(state);
-		if (status < 0)
-			break;
-		status = Write16(state, SC_RA_RAM_CMD_ADDR__A, subCmd, 0);
-		if (status < 0)
-			break;
-		status = Write16(state, SC_RA_RAM_PARAM1__A, param1, 0);
-		if (status < 0)
-			break;
-		status = Write16(state, SC_RA_RAM_PARAM0__A, param0, 0);
-		if (status < 0)
-			break;
-
-		status = SC_SendCommand(state, SC_RA_RAM_CMD_SET_PREF_PARAM);
-		if (status < 0)
-			break;
-	} while (0);
-	mutex_unlock(&state->mutex);
-	return status;
-}
-
-#if 0
-static int SC_GetOpParamCommand(struct drxd_state *state, u16 * result)
-{
-	int status = 0;
-
-	mutex_lock(&state->mutex);
-	do {
-		status = SC_WaitForReady(state);
-		if (status < 0)
-			break;
-		status = SC_SendCommand(state, SC_RA_RAM_CMD_GET_OP_PARAM);
-		if (status < 0)
-			break;
-		status = Read16(state, SC_RA_RAM_PARAM0__A, result, 0);
-		if (status < 0)
-			break;
-	} while (0);
-	mutex_unlock(&state->mutex);
-	return status;
-}
-#endif
-
-static int ConfigureMPEGOutput(struct drxd_state *state, int bEnableOutput)
-{
-	int status;
-
-	do {
-		u16 EcOcRegIprInvMpg = 0;
-		u16 EcOcRegOcModeLop = 0;
-		u16 EcOcRegOcModeHip = 0;
-		u16 EcOcRegOcMpgSio = 0;
-
-		/*CHK_ERROR(Read16(state, EC_OC_REG_OC_MODE_LOP__A, &EcOcRegOcModeLop, 0)); */
-
-		if (state->operation_mode == OM_DVBT_Diversity_Front) {
-			if (bEnableOutput) {
-				EcOcRegOcModeHip |=
-				    B_EC_OC_REG_OC_MODE_HIP_MPG_BUS_SRC_MONITOR;
-			} else
-				EcOcRegOcMpgSio |= EC_OC_REG_OC_MPG_SIO__M;
-			EcOcRegOcModeLop |=
-			    EC_OC_REG_OC_MODE_LOP_PAR_ENA_DISABLE;
-		} else {
-			EcOcRegOcModeLop = state->m_EcOcRegOcModeLop;
-
-			if (bEnableOutput)
-				EcOcRegOcMpgSio &= (~(EC_OC_REG_OC_MPG_SIO__M));
-			else
-				EcOcRegOcMpgSio |= EC_OC_REG_OC_MPG_SIO__M;
-
-			/* Don't Insert RS Byte */
-			if (state->insert_rs_byte) {
-				EcOcRegOcModeLop &=
-				    (~(EC_OC_REG_OC_MODE_LOP_PAR_ENA__M));
-				EcOcRegOcModeHip &=
-				    (~EC_OC_REG_OC_MODE_HIP_MPG_PAR_VAL__M);
-				EcOcRegOcModeHip |=
-				    EC_OC_REG_OC_MODE_HIP_MPG_PAR_VAL_ENABLE;
-			} else {
-				EcOcRegOcModeLop |=
-				    EC_OC_REG_OC_MODE_LOP_PAR_ENA_DISABLE;
-				EcOcRegOcModeHip &=
-				    (~EC_OC_REG_OC_MODE_HIP_MPG_PAR_VAL__M);
-				EcOcRegOcModeHip |=
-				    EC_OC_REG_OC_MODE_HIP_MPG_PAR_VAL_DISABLE;
-			}
-
-			/* Mode = Parallel */
-			if (state->enable_parallel)
-				EcOcRegOcModeLop &=
-				    (~(EC_OC_REG_OC_MODE_LOP_MPG_TRM_MDE__M));
-			else
-				EcOcRegOcModeLop |=
-				    EC_OC_REG_OC_MODE_LOP_MPG_TRM_MDE_SERIAL;
-		}
-		/* Invert Data */
-		/* EcOcRegIprInvMpg |= 0x00FF; */
-		EcOcRegIprInvMpg &= (~(0x00FF));
-
-		/* Invert Error ( we don't use the pin ) */
-		/*  EcOcRegIprInvMpg |= 0x0100; */
-		EcOcRegIprInvMpg &= (~(0x0100));
-
-		/* Invert Start ( we don't use the pin ) */
-		/* EcOcRegIprInvMpg |= 0x0200; */
-		EcOcRegIprInvMpg &= (~(0x0200));
-
-		/* Invert Valid ( we don't use the pin ) */
-		/* EcOcRegIprInvMpg |= 0x0400; */
-		EcOcRegIprInvMpg &= (~(0x0400));
-
-		/* Invert Clock */
-		/* EcOcRegIprInvMpg |= 0x0800; */
-		EcOcRegIprInvMpg &= (~(0x0800));
-
-		/* EcOcRegOcModeLop =0x05; */
-		status = Write16(state, EC_OC_REG_IPR_INV_MPG__A, EcOcRegIprInvMpg, 0);
-		if (status < 0)
-			break;
-		status = Write16(state, EC_OC_REG_OC_MODE_LOP__A, EcOcRegOcModeLop, 0);
-		if (status < 0)
-			break;
-		status = Write16(state, EC_OC_REG_OC_MODE_HIP__A, EcOcRegOcModeHip, 0x0000);
-		if (status < 0)
-			break;
-		status = Write16(state, EC_OC_REG_OC_MPG_SIO__A, EcOcRegOcMpgSio, 0);
-		if (status < 0)
-			break;
-	} while (0);
-	return status;
-}
-
-static int SetDeviceTypeId(struct drxd_state *state)
-{
-	int status = 0;
-	u16 deviceId = 0;
-
-	do {
-		status = Read16(state, CC_REG_JTAGID_L__A, &deviceId, 0);
-		if (status < 0)
-			break;
-		/* TODO: why twice? */
-		status = Read16(state, CC_REG_JTAGID_L__A, &deviceId, 0);
-		if (status < 0)
-			break;
-		printk(KERN_INFO "drxd: deviceId = %04x\n", deviceId);
-
-		state->type_A = 0;
-		state->PGA = 0;
-		state->diversity = 0;
-		if (deviceId == 0) {	/* on A2 only 3975 available */
-			state->type_A = 1;
-			printk(KERN_INFO "DRX3975D-A2\n");
-		} else {
-			deviceId >>= 12;
-			printk(KERN_INFO "DRX397%dD-B1\n", deviceId);
-			switch (deviceId) {
-			case 4:
-				state->diversity = 1;
-			case 3:
-			case 7:
-				state->PGA = 1;
-				break;
-			case 6:
-				state->diversity = 1;
-			case 5:
-			case 8:
-				break;
-			default:
-				status = -1;
-				break;
-			}
-		}
-	} while (0);
-
-	if (status < 0)
-		return status;
-
-	/* Init Table selection */
-	state->m_InitAtomicRead = DRXD_InitAtomicRead;
-	state->m_InitSC = DRXD_InitSC;
-	state->m_ResetECRAM = DRXD_ResetECRAM;
-	if (state->type_A) {
-		state->m_ResetCEFR = DRXD_ResetCEFR;
-		state->m_InitFE_1 = DRXD_InitFEA2_1;
-		state->m_InitFE_2 = DRXD_InitFEA2_2;
-		state->m_InitCP = DRXD_InitCPA2;
-		state->m_InitCE = DRXD_InitCEA2;
-		state->m_InitEQ = DRXD_InitEQA2;
-		state->m_InitEC = DRXD_InitECA2;
-		if (load_firmware(state, DRX_FW_FILENAME_A2))
-			return -EIO;
-	} else {
-		state->m_ResetCEFR = NULL;
-		state->m_InitFE_1 = DRXD_InitFEB1_1;
-		state->m_InitFE_2 = DRXD_InitFEB1_2;
-		state->m_InitCP = DRXD_InitCPB1;
-		state->m_InitCE = DRXD_InitCEB1;
-		state->m_InitEQ = DRXD_InitEQB1;
-		state->m_InitEC = DRXD_InitECB1;
-		if (load_firmware(state, DRX_FW_FILENAME_B1))
-			return -EIO;
-	}
-	if (state->diversity) {
-		state->m_InitDiversityFront = DRXD_InitDiversityFront;
-		state->m_InitDiversityEnd = DRXD_InitDiversityEnd;
-		state->m_DisableDiversity = DRXD_DisableDiversity;
-		state->m_StartDiversityFront = DRXD_StartDiversityFront;
-		state->m_StartDiversityEnd = DRXD_StartDiversityEnd;
-		state->m_DiversityDelay8MHZ = DRXD_DiversityDelay8MHZ;
-		state->m_DiversityDelay6MHZ = DRXD_DiversityDelay6MHZ;
-	} else {
-		state->m_InitDiversityFront = NULL;
-		state->m_InitDiversityEnd = NULL;
-		state->m_DisableDiversity = NULL;
-		state->m_StartDiversityFront = NULL;
-		state->m_StartDiversityEnd = NULL;
-		state->m_DiversityDelay8MHZ = NULL;
-		state->m_DiversityDelay6MHZ = NULL;
-	}
-
-	return status;
-}
-
-static int CorrectSysClockDeviation(struct drxd_state *state)
-{
-	int status;
-	s32 incr = 0;
-	s32 nomincr = 0;
-	u32 bandwidth = 0;
-	u32 sysClockInHz = 0;
-	u32 sysClockFreq = 0;	/* in kHz */
-	s16 oscClockDeviation;
-	s16 Diff;
-
-	do {
-		/* Retrieve bandwidth and incr, sanity check */
-
-		/* These accesses should be AtomicReadReg32, but that
-		   causes trouble (at least for diversity */
-		status = Read32(state, LC_RA_RAM_IFINCR_NOM_L__A, ((u32 *) &nomincr), 0);
-		if (status < 0)
-			break;
-		status = Read32(state, FE_IF_REG_INCR0__A, (u32 *) &incr, 0);
-		if (status < 0)
-			break;
-
-		if (state->type_A) {
-			if ((nomincr - incr < -500) || (nomincr - incr > 500))
-				break;
-		} else {
-			if ((nomincr - incr < -2000) || (nomincr - incr > 2000))
-				break;
-		}
-
-		switch (state->props.bandwidth_hz) {
-		case 8000000:
-			bandwidth = DRXD_BANDWIDTH_8MHZ_IN_HZ;
-			break;
-		case 7000000:
-			bandwidth = DRXD_BANDWIDTH_7MHZ_IN_HZ;
-			break;
-		case 6000000:
-			bandwidth = DRXD_BANDWIDTH_6MHZ_IN_HZ;
-			break;
-		default:
-			return -1;
-			break;
-		}
-
-		/* Compute new sysclock value
-		   sysClockFreq = (((incr + 2^23)*bandwidth)/2^21)/1000 */
-		incr += (1 << 23);
-		sysClockInHz = MulDiv32(incr, bandwidth, 1 << 21);
-		sysClockFreq = (u32) (sysClockInHz / 1000);
-		/* rounding */
-		if ((sysClockInHz % 1000) > 500)
-			sysClockFreq++;
-
-		/* Compute clock deviation in ppm */
-		oscClockDeviation = (u16) ((((s32) (sysClockFreq) -
-					     (s32)
-					     (state->expected_sys_clock_freq)) *
-					    1000000L) /
-					   (s32)
-					   (state->expected_sys_clock_freq));
-
-		Diff = oscClockDeviation - state->osc_clock_deviation;
-		/*printk(KERN_INFO "sysclockdiff=%d\n", Diff); */
-		if (Diff >= -200 && Diff <= 200) {
-			state->sys_clock_freq = (u16) sysClockFreq;
-			if (oscClockDeviation != state->osc_clock_deviation) {
-				if (state->config.osc_deviation) {
-					state->config.osc_deviation(state->priv,
-								    oscClockDeviation,
-								    1);
-					state->osc_clock_deviation =
-					    oscClockDeviation;
-				}
-			}
-			/* switch OFF SRMM scan in SC */
-			status = Write16(state, SC_RA_RAM_SAMPLE_RATE_COUNT__A, DRXD_OSCDEV_DONT_SCAN, 0);
-			if (status < 0)
-				break;
-			/* overrule FE_IF internal value for
-			   proper re-locking */
-			status = Write16(state, SC_RA_RAM_IF_SAVE__AX, state->current_fe_if_incr, 0);
-			if (status < 0)
-				break;
-			state->cscd_state = CSCD_SAVED;
-		}
-	} while (0);
-
-	return status;
-}
-
-static int DRX_Stop(struct drxd_state *state)
-{
-	int status;
-
-	if (state->drxd_state != DRXD_STARTED)
-		return 0;
-
-	do {
-		if (state->cscd_state != CSCD_SAVED) {
-			u32 lock;
-			status = DRX_GetLockStatus(state, &lock);
-			if (status < 0)
-				break;
-		}
-
-		status = StopOC(state);
-		if (status < 0)
-			break;
-
-		state->drxd_state = DRXD_STOPPED;
-
-		status = ConfigureMPEGOutput(state, 0);
-		if (status < 0)
-			break;
-
-		if (state->type_A) {
-			/* Stop relevant processors off the device */
-			status = Write16(state, EC_OD_REG_COMM_EXEC__A, 0x0000, 0x0000);
-			if (status < 0)
-				break;
-
-			status = Write16(state, SC_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0);
-			if (status < 0)
-				break;
-			status = Write16(state, LC_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0);
-			if (status < 0)
-				break;
-		} else {
-			/* Stop all processors except HI & CC & FE */
-			status = Write16(state, B_SC_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0);
-			if (status < 0)
-				break;
-			status = Write16(state, B_LC_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0);
-			if (status < 0)
-				break;
-			status = Write16(state, B_FT_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0);
-			if (status < 0)
-				break;
-			status = Write16(state, B_CP_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0);
-			if (status < 0)
-				break;
-			status = Write16(state, B_CE_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0);
-			if (status < 0)
-				break;
-			status = Write16(state, B_EQ_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0);
-			if (status < 0)
-				break;
-			status = Write16(state, EC_OD_REG_COMM_EXEC__A, 0x0000, 0);
-			if (status < 0)
-				break;
-		}
-
-	} while (0);
-	return status;
-}
-
-int SetOperationMode(struct drxd_state *state, int oMode)
-{
-	int status;
-
-	do {
-		if (state->drxd_state != DRXD_STOPPED) {
-			status = -1;
-			break;
-		}
-
-		if (oMode == state->operation_mode) {
-			status = 0;
-			break;
-		}
-
-		if (oMode != OM_Default && !state->diversity) {
-			status = -1;
-			break;
-		}
-
-		switch (oMode) {
-		case OM_DVBT_Diversity_Front:
-			status = WriteTable(state, state->m_InitDiversityFront);
-			break;
-		case OM_DVBT_Diversity_End:
-			status = WriteTable(state, state->m_InitDiversityEnd);
-			break;
-		case OM_Default:
-			/* We need to check how to
-			   get DRXD out of diversity */
-		default:
-			status = WriteTable(state, state->m_DisableDiversity);
-			break;
-		}
-	} while (0);
-
-	if (!status)
-		state->operation_mode = oMode;
-	return status;
-}
-
-static int StartDiversity(struct drxd_state *state)
-{
-	int status = 0;
-	u16 rcControl;
-
-	do {
-		if (state->operation_mode == OM_DVBT_Diversity_Front) {
-			status = WriteTable(state, state->m_StartDiversityFront);
-			if (status < 0)
-				break;
-		} else if (state->operation_mode == OM_DVBT_Diversity_End) {
-			status = WriteTable(state, state->m_StartDiversityEnd);
-			if (status < 0)
-				break;
-			if (state->props.bandwidth_hz == 8000000) {
-				status = WriteTable(state, state->m_DiversityDelay8MHZ);
-				if (status < 0)
-					break;
-			} else {
-				status = WriteTable(state, state->m_DiversityDelay6MHZ);
-				if (status < 0)
-					break;
-			}
-
-			status = Read16(state, B_EQ_REG_RC_SEL_CAR__A, &rcControl, 0);
-			if (status < 0)
-				break;
-			rcControl &= ~(B_EQ_REG_RC_SEL_CAR_FFTMODE__M);
-			rcControl |= B_EQ_REG_RC_SEL_CAR_DIV_ON |
-			    /*  combining enabled */
-			    B_EQ_REG_RC_SEL_CAR_MEAS_A_CC |
-			    B_EQ_REG_RC_SEL_CAR_PASS_A_CC |
-			    B_EQ_REG_RC_SEL_CAR_LOCAL_A_CC;
-			status = Write16(state, B_EQ_REG_RC_SEL_CAR__A, rcControl, 0);
-			if (status < 0)
-				break;
-		}
-	} while (0);
-	return status;
-}
-
-static int SetFrequencyShift(struct drxd_state *state,
-			     u32 offsetFreq, int channelMirrored)
-{
-	int negativeShift = (state->tuner_mirrors == channelMirrored);
-
-	/* Handle all mirroring
-	 *
-	 * Note: ADC mirroring (aliasing) is implictly handled by limiting
-	 * feFsRegAddInc to 28 bits below
-	 * (if the result before masking is more than 28 bits, this means
-	 *  that the ADC is mirroring.
-	 * The masking is in fact the aliasing of the ADC)
-	 *
-	 */
-
-	/* Compute register value, unsigned computation */
-	state->fe_fs_add_incr = MulDiv32(state->intermediate_freq +
-					 offsetFreq,
-					 1 << 28, state->sys_clock_freq);
-	/* Remove integer part */
-	state->fe_fs_add_incr &= 0x0FFFFFFFL;
-	if (negativeShift)
-		state->fe_fs_add_incr = ((1 << 28) - state->fe_fs_add_incr);
-
-	/* Save the frequency shift without tunerOffset compensation
-	   for CtrlGetChannel. */
-	state->org_fe_fs_add_incr = MulDiv32(state->intermediate_freq,
-					     1 << 28, state->sys_clock_freq);
-	/* Remove integer part */
-	state->org_fe_fs_add_incr &= 0x0FFFFFFFL;
-	if (negativeShift)
-		state->org_fe_fs_add_incr = ((1L << 28) -
-					     state->org_fe_fs_add_incr);
-
-	return Write32(state, FE_FS_REG_ADD_INC_LOP__A,
-		       state->fe_fs_add_incr, 0);
-}
-
-static int SetCfgNoiseCalibration(struct drxd_state *state,
-				  struct SNoiseCal *noiseCal)
-{
-	u16 beOptEna;
-	int status = 0;
-
-	do {
-		status = Read16(state, SC_RA_RAM_BE_OPT_ENA__A, &beOptEna, 0);
-		if (status < 0)
-			break;
-		if (noiseCal->cpOpt) {
-			beOptEna |= (1 << SC_RA_RAM_BE_OPT_ENA_CP_OPT);
-		} else {
-			beOptEna &= ~(1 << SC_RA_RAM_BE_OPT_ENA_CP_OPT);
-			status = Write16(state, CP_REG_AC_NEXP_OFFS__A, noiseCal->cpNexpOfs, 0);
-			if (status < 0)
-				break;
-		}
-		status = Write16(state, SC_RA_RAM_BE_OPT_ENA__A, beOptEna, 0);
-		if (status < 0)
-			break;
-
-		if (!state->type_A) {
-			status = Write16(state, B_SC_RA_RAM_CO_TD_CAL_2K__A, noiseCal->tdCal2k, 0);
-			if (status < 0)
-				break;
-			status = Write16(state, B_SC_RA_RAM_CO_TD_CAL_8K__A, noiseCal->tdCal8k, 0);
-			if (status < 0)
-				break;
-		}
-	} while (0);
-
-	return status;
-}
-
-static int DRX_Start(struct drxd_state *state, s32 off)
-{
-	struct dtv_frontend_properties *p = &state->props;
-	int status;
-
-	u16 transmissionParams = 0;
-	u16 operationMode = 0;
-	u16 qpskTdTpsPwr = 0;
-	u16 qam16TdTpsPwr = 0;
-	u16 qam64TdTpsPwr = 0;
-	u32 feIfIncr = 0;
-	u32 bandwidth = 0;
-	int mirrorFreqSpect;
-
-	u16 qpskSnCeGain = 0;
-	u16 qam16SnCeGain = 0;
-	u16 qam64SnCeGain = 0;
-	u16 qpskIsGainMan = 0;
-	u16 qam16IsGainMan = 0;
-	u16 qam64IsGainMan = 0;
-	u16 qpskIsGainExp = 0;
-	u16 qam16IsGainExp = 0;
-	u16 qam64IsGainExp = 0;
-	u16 bandwidthParam = 0;
-
-	if (off < 0)
-		off = (off - 500) / 1000;
-	else
-		off = (off + 500) / 1000;
-
-	do {
-		if (state->drxd_state != DRXD_STOPPED)
-			return -1;
-		status = ResetECOD(state);
-		if (status < 0)
-			break;
-		if (state->type_A) {
-			status = InitSC(state);
-			if (status < 0)
-				break;
-		} else {
-			status = InitFT(state);
-			if (status < 0)
-				break;
-			status = InitCP(state);
-			if (status < 0)
-				break;
-			status = InitCE(state);
-			if (status < 0)
-				break;
-			status = InitEQ(state);
-			if (status < 0)
-				break;
-			status = InitSC(state);
-			if (status < 0)
-				break;
-		}
-
-		/* Restore current IF & RF AGC settings */
-
-		status = SetCfgIfAgc(state, &state->if_agc_cfg);
-		if (status < 0)
-			break;
-		status = SetCfgRfAgc(state, &state->rf_agc_cfg);
-		if (status < 0)
-			break;
-
-		mirrorFreqSpect = (state->props.inversion == INVERSION_ON);
-
-		switch (p->transmission_mode) {
-		default:	/* Not set, detect it automatically */
-			operationMode |= SC_RA_RAM_OP_AUTO_MODE__M;
-			/* fall through , try first guess DRX_FFTMODE_8K */
-		case TRANSMISSION_MODE_8K:
-			transmissionParams |= SC_RA_RAM_OP_PARAM_MODE_8K;
-			if (state->type_A) {
-				status = Write16(state, EC_SB_REG_TR_MODE__A, EC_SB_REG_TR_MODE_8K, 0x0000);
-				if (status < 0)
-					break;
-				qpskSnCeGain = 99;
-				qam16SnCeGain = 83;
-				qam64SnCeGain = 67;
-			}
-			break;
-		case TRANSMISSION_MODE_2K:
-			transmissionParams |= SC_RA_RAM_OP_PARAM_MODE_2K;
-			if (state->type_A) {
-				status = Write16(state, EC_SB_REG_TR_MODE__A, EC_SB_REG_TR_MODE_2K, 0x0000);
-				if (status < 0)
-					break;
-				qpskSnCeGain = 97;
-				qam16SnCeGain = 71;
-				qam64SnCeGain = 65;
-			}
-			break;
-		}
-
-		switch (p->guard_interval) {
-		case GUARD_INTERVAL_1_4:
-			transmissionParams |= SC_RA_RAM_OP_PARAM_GUARD_4;
-			break;
-		case GUARD_INTERVAL_1_8:
-			transmissionParams |= SC_RA_RAM_OP_PARAM_GUARD_8;
-			break;
-		case GUARD_INTERVAL_1_16:
-			transmissionParams |= SC_RA_RAM_OP_PARAM_GUARD_16;
-			break;
-		case GUARD_INTERVAL_1_32:
-			transmissionParams |= SC_RA_RAM_OP_PARAM_GUARD_32;
-			break;
-		default:	/* Not set, detect it automatically */
-			operationMode |= SC_RA_RAM_OP_AUTO_GUARD__M;
-			/* try first guess 1/4 */
-			transmissionParams |= SC_RA_RAM_OP_PARAM_GUARD_4;
-			break;
-		}
-
-		switch (p->hierarchy) {
-		case HIERARCHY_1:
-			transmissionParams |= SC_RA_RAM_OP_PARAM_HIER_A1;
-			if (state->type_A) {
-				status = Write16(state, EQ_REG_OT_ALPHA__A, 0x0001, 0x0000);
-				if (status < 0)
-					break;
-				status = Write16(state, EC_SB_REG_ALPHA__A, 0x0001, 0x0000);
-				if (status < 0)
-					break;
-
-				qpskTdTpsPwr = EQ_TD_TPS_PWR_UNKNOWN;
-				qam16TdTpsPwr = EQ_TD_TPS_PWR_QAM16_ALPHA1;
-				qam64TdTpsPwr = EQ_TD_TPS_PWR_QAM64_ALPHA1;
-
-				qpskIsGainMan =
-				    SC_RA_RAM_EQ_IS_GAIN_UNKNOWN_MAN__PRE;
-				qam16IsGainMan =
-				    SC_RA_RAM_EQ_IS_GAIN_16QAM_MAN__PRE;
-				qam64IsGainMan =
-				    SC_RA_RAM_EQ_IS_GAIN_64QAM_MAN__PRE;
-
-				qpskIsGainExp =
-				    SC_RA_RAM_EQ_IS_GAIN_UNKNOWN_EXP__PRE;
-				qam16IsGainExp =
-				    SC_RA_RAM_EQ_IS_GAIN_16QAM_EXP__PRE;
-				qam64IsGainExp =
-				    SC_RA_RAM_EQ_IS_GAIN_64QAM_EXP__PRE;
-			}
-			break;
-
-		case HIERARCHY_2:
-			transmissionParams |= SC_RA_RAM_OP_PARAM_HIER_A2;
-			if (state->type_A) {
-				status = Write16(state, EQ_REG_OT_ALPHA__A, 0x0002, 0x0000);
-				if (status < 0)
-					break;
-				status = Write16(state, EC_SB_REG_ALPHA__A, 0x0002, 0x0000);
-				if (status < 0)
-					break;
-
-				qpskTdTpsPwr = EQ_TD_TPS_PWR_UNKNOWN;
-				qam16TdTpsPwr = EQ_TD_TPS_PWR_QAM16_ALPHA2;
-				qam64TdTpsPwr = EQ_TD_TPS_PWR_QAM64_ALPHA2;
-
-				qpskIsGainMan =
-				    SC_RA_RAM_EQ_IS_GAIN_UNKNOWN_MAN__PRE;
-				qam16IsGainMan =
-				    SC_RA_RAM_EQ_IS_GAIN_16QAM_A2_MAN__PRE;
-				qam64IsGainMan =
-				    SC_RA_RAM_EQ_IS_GAIN_64QAM_A2_MAN__PRE;
-
-				qpskIsGainExp =
-				    SC_RA_RAM_EQ_IS_GAIN_UNKNOWN_EXP__PRE;
-				qam16IsGainExp =
-				    SC_RA_RAM_EQ_IS_GAIN_16QAM_A2_EXP__PRE;
-				qam64IsGainExp =
-				    SC_RA_RAM_EQ_IS_GAIN_64QAM_A2_EXP__PRE;
-			}
-			break;
-		case HIERARCHY_4:
-			transmissionParams |= SC_RA_RAM_OP_PARAM_HIER_A4;
-			if (state->type_A) {
-				status = Write16(state, EQ_REG_OT_ALPHA__A, 0x0003, 0x0000);
-				if (status < 0)
-					break;
-				status = Write16(state, EC_SB_REG_ALPHA__A, 0x0003, 0x0000);
-				if (status < 0)
-					break;
-
-				qpskTdTpsPwr = EQ_TD_TPS_PWR_UNKNOWN;
-				qam16TdTpsPwr = EQ_TD_TPS_PWR_QAM16_ALPHA4;
-				qam64TdTpsPwr = EQ_TD_TPS_PWR_QAM64_ALPHA4;
-
-				qpskIsGainMan =
-				    SC_RA_RAM_EQ_IS_GAIN_UNKNOWN_MAN__PRE;
-				qam16IsGainMan =
-				    SC_RA_RAM_EQ_IS_GAIN_16QAM_A4_MAN__PRE;
-				qam64IsGainMan =
-				    SC_RA_RAM_EQ_IS_GAIN_64QAM_A4_MAN__PRE;
-
-				qpskIsGainExp =
-				    SC_RA_RAM_EQ_IS_GAIN_UNKNOWN_EXP__PRE;
-				qam16IsGainExp =
-				    SC_RA_RAM_EQ_IS_GAIN_16QAM_A4_EXP__PRE;
-				qam64IsGainExp =
-				    SC_RA_RAM_EQ_IS_GAIN_64QAM_A4_EXP__PRE;
-			}
-			break;
-		case HIERARCHY_AUTO:
-		default:
-			/* Not set, detect it automatically, start with none */
-			operationMode |= SC_RA_RAM_OP_AUTO_HIER__M;
-			transmissionParams |= SC_RA_RAM_OP_PARAM_HIER_NO;
-			if (state->type_A) {
-				status = Write16(state, EQ_REG_OT_ALPHA__A, 0x0000, 0x0000);
-				if (status < 0)
-					break;
-				status = Write16(state, EC_SB_REG_ALPHA__A, 0x0000, 0x0000);
-				if (status < 0)
-					break;
-
-				qpskTdTpsPwr = EQ_TD_TPS_PWR_QPSK;
-				qam16TdTpsPwr = EQ_TD_TPS_PWR_QAM16_ALPHAN;
-				qam64TdTpsPwr = EQ_TD_TPS_PWR_QAM64_ALPHAN;
-
-				qpskIsGainMan =
-				    SC_RA_RAM_EQ_IS_GAIN_QPSK_MAN__PRE;
-				qam16IsGainMan =
-				    SC_RA_RAM_EQ_IS_GAIN_16QAM_MAN__PRE;
-				qam64IsGainMan =
-				    SC_RA_RAM_EQ_IS_GAIN_64QAM_MAN__PRE;
-
-				qpskIsGainExp =
-				    SC_RA_RAM_EQ_IS_GAIN_QPSK_EXP__PRE;
-				qam16IsGainExp =
-				    SC_RA_RAM_EQ_IS_GAIN_16QAM_EXP__PRE;
-				qam64IsGainExp =
-				    SC_RA_RAM_EQ_IS_GAIN_64QAM_EXP__PRE;
-			}
-			break;
-		}
-		status = status;
-		if (status < 0)
-			break;
-
-		switch (p->modulation) {
-		default:
-			operationMode |= SC_RA_RAM_OP_AUTO_CONST__M;
-			/* fall through , try first guess
-			   DRX_CONSTELLATION_QAM64 */
-		case QAM_64:
-			transmissionParams |= SC_RA_RAM_OP_PARAM_CONST_QAM64;
-			if (state->type_A) {
-				status = Write16(state, EQ_REG_OT_CONST__A, 0x0002, 0x0000);
-				if (status < 0)
-					break;
-				status = Write16(state, EC_SB_REG_CONST__A, EC_SB_REG_CONST_64QAM, 0x0000);
-				if (status < 0)
-					break;
-				status = Write16(state, EC_SB_REG_SCALE_MSB__A, 0x0020, 0x0000);
-				if (status < 0)
-					break;
-				status = Write16(state, EC_SB_REG_SCALE_BIT2__A, 0x0008, 0x0000);
-				if (status < 0)
-					break;
-				status = Write16(state, EC_SB_REG_SCALE_LSB__A, 0x0002, 0x0000);
-				if (status < 0)
-					break;
-
-				status = Write16(state, EQ_REG_TD_TPS_PWR_OFS__A, qam64TdTpsPwr, 0x0000);
-				if (status < 0)
-					break;
-				status = Write16(state, EQ_REG_SN_CEGAIN__A, qam64SnCeGain, 0x0000);
-				if (status < 0)
-					break;
-				status = Write16(state, EQ_REG_IS_GAIN_MAN__A, qam64IsGainMan, 0x0000);
-				if (status < 0)
-					break;
-				status = Write16(state, EQ_REG_IS_GAIN_EXP__A, qam64IsGainExp, 0x0000);
-				if (status < 0)
-					break;
-			}
-			break;
-		case QPSK:
-			transmissionParams |= SC_RA_RAM_OP_PARAM_CONST_QPSK;
-			if (state->type_A) {
-				status = Write16(state, EQ_REG_OT_CONST__A, 0x0000, 0x0000);
-				if (status < 0)
-					break;
-				status = Write16(state, EC_SB_REG_CONST__A, EC_SB_REG_CONST_QPSK, 0x0000);
-				if (status < 0)
-					break;
-				status = Write16(state, EC_SB_REG_SCALE_MSB__A, 0x0010, 0x0000);
-				if (status < 0)
-					break;
-				status = Write16(state, EC_SB_REG_SCALE_BIT2__A, 0x0000, 0x0000);
-				if (status < 0)
-					break;
-				status = Write16(state, EC_SB_REG_SCALE_LSB__A, 0x0000, 0x0000);
-				if (status < 0)
-					break;
-
-				status = Write16(state, EQ_REG_TD_TPS_PWR_OFS__A, qpskTdTpsPwr, 0x0000);
-				if (status < 0)
-					break;
-				status = Write16(state, EQ_REG_SN_CEGAIN__A, qpskSnCeGain, 0x0000);
-				if (status < 0)
-					break;
-				status = Write16(state, EQ_REG_IS_GAIN_MAN__A, qpskIsGainMan, 0x0000);
-				if (status < 0)
-					break;
-				status = Write16(state, EQ_REG_IS_GAIN_EXP__A, qpskIsGainExp, 0x0000);
-				if (status < 0)
-					break;
-			}
-			break;
-
-		case QAM_16:
-			transmissionParams |= SC_RA_RAM_OP_PARAM_CONST_QAM16;
-			if (state->type_A) {
-				status = Write16(state, EQ_REG_OT_CONST__A, 0x0001, 0x0000);
-				if (status < 0)
-					break;
-				status = Write16(state, EC_SB_REG_CONST__A, EC_SB_REG_CONST_16QAM, 0x0000);
-				if (status < 0)
-					break;
-				status = Write16(state, EC_SB_REG_SCALE_MSB__A, 0x0010, 0x0000);
-				if (status < 0)
-					break;
-				status = Write16(state, EC_SB_REG_SCALE_BIT2__A, 0x0004, 0x0000);
-				if (status < 0)
-					break;
-				status = Write16(state, EC_SB_REG_SCALE_LSB__A, 0x0000, 0x0000);
-				if (status < 0)
-					break;
-
-				status = Write16(state, EQ_REG_TD_TPS_PWR_OFS__A, qam16TdTpsPwr, 0x0000);
-				if (status < 0)
-					break;
-				status = Write16(state, EQ_REG_SN_CEGAIN__A, qam16SnCeGain, 0x0000);
-				if (status < 0)
-					break;
-				status = Write16(state, EQ_REG_IS_GAIN_MAN__A, qam16IsGainMan, 0x0000);
-				if (status < 0)
-					break;
-				status = Write16(state, EQ_REG_IS_GAIN_EXP__A, qam16IsGainExp, 0x0000);
-				if (status < 0)
-					break;
-			}
-			break;
-
-		}
-		status = status;
-		if (status < 0)
-			break;
-
-		switch (DRX_CHANNEL_HIGH) {
-		default:
-		case DRX_CHANNEL_AUTO:
-		case DRX_CHANNEL_LOW:
-			transmissionParams |= SC_RA_RAM_OP_PARAM_PRIO_LO;
-			status = Write16(state, EC_SB_REG_PRIOR__A, EC_SB_REG_PRIOR_LO, 0x0000);
-			if (status < 0)
-				break;
-			break;
-		case DRX_CHANNEL_HIGH:
-			transmissionParams |= SC_RA_RAM_OP_PARAM_PRIO_HI;
-			status = Write16(state, EC_SB_REG_PRIOR__A, EC_SB_REG_PRIOR_HI, 0x0000);
-			if (status < 0)
-				break;
-			break;
-
-		}
-
-		switch (p->code_rate_HP) {
-		case FEC_1_2:
-			transmissionParams |= SC_RA_RAM_OP_PARAM_RATE_1_2;
-			if (state->type_A) {
-				status = Write16(state, EC_VD_REG_SET_CODERATE__A, EC_VD_REG_SET_CODERATE_C1_2, 0x0000);
-				if (status < 0)
-					break;
-			}
-			break;
-		default:
-			operationMode |= SC_RA_RAM_OP_AUTO_RATE__M;
-		case FEC_2_3:
-			transmissionParams |= SC_RA_RAM_OP_PARAM_RATE_2_3;
-			if (state->type_A) {
-				status = Write16(state, EC_VD_REG_SET_CODERATE__A, EC_VD_REG_SET_CODERATE_C2_3, 0x0000);
-				if (status < 0)
-					break;
-			}
-			break;
-		case FEC_3_4:
-			transmissionParams |= SC_RA_RAM_OP_PARAM_RATE_3_4;
-			if (state->type_A) {
-				status = Write16(state, EC_VD_REG_SET_CODERATE__A, EC_VD_REG_SET_CODERATE_C3_4, 0x0000);
-				if (status < 0)
-					break;
-			}
-			break;
-		case FEC_5_6:
-			transmissionParams |= SC_RA_RAM_OP_PARAM_RATE_5_6;
-			if (state->type_A) {
-				status = Write16(state, EC_VD_REG_SET_CODERATE__A, EC_VD_REG_SET_CODERATE_C5_6, 0x0000);
-				if (status < 0)
-					break;
-			}
-			break;
-		case FEC_7_8:
-			transmissionParams |= SC_RA_RAM_OP_PARAM_RATE_7_8;
-			if (state->type_A) {
-				status = Write16(state, EC_VD_REG_SET_CODERATE__A, EC_VD_REG_SET_CODERATE_C7_8, 0x0000);
-				if (status < 0)
-					break;
-			}
-			break;
-		}
-		status = status;
-		if (status < 0)
-			break;
-
-		/* First determine real bandwidth (Hz) */
-		/* Also set delay for impulse noise cruncher (only A2) */
-		/* Also set parameters for EC_OC fix, note
-		   EC_OC_REG_TMD_HIL_MAR is changed
-		   by SC for fix for some 8K,1/8 guard but is restored by
-		   InitEC and ResetEC
-		   functions */
-		switch (p->bandwidth_hz) {
-		case 0:
-			p->bandwidth_hz = 8000000;
-			/* fall through */
-		case 8000000:
-			/* (64/7)*(8/8)*1000000 */
-			bandwidth = DRXD_BANDWIDTH_8MHZ_IN_HZ;
-
-			bandwidthParam = 0;
-			status = Write16(state,
-					 FE_AG_REG_IND_DEL__A, 50, 0x0000);
-			break;
-		case 7000000:
-			/* (64/7)*(7/8)*1000000 */
-			bandwidth = DRXD_BANDWIDTH_7MHZ_IN_HZ;
-			bandwidthParam = 0x4807;	/*binary:0100 1000 0000 0111 */
-			status = Write16(state,
-					 FE_AG_REG_IND_DEL__A, 59, 0x0000);
-			break;
-		case 6000000:
-			/* (64/7)*(6/8)*1000000 */
-			bandwidth = DRXD_BANDWIDTH_6MHZ_IN_HZ;
-			bandwidthParam = 0x0F07;	/*binary: 0000 1111 0000 0111 */
-			status = Write16(state,
-					 FE_AG_REG_IND_DEL__A, 71, 0x0000);
-			break;
-		default:
-			status = -EINVAL;
-		}
-		if (status < 0)
-			break;
-
-		status = Write16(state, SC_RA_RAM_BAND__A, bandwidthParam, 0x0000);
-		if (status < 0)
-			break;
-
-		{
-			u16 sc_config;
-			status = Read16(state, SC_RA_RAM_CONFIG__A, &sc_config, 0);
-			if (status < 0)
-				break;
-
-			/* enable SLAVE mode in 2k 1/32 to
-			   prevent timing change glitches */
-			if ((p->transmission_mode == TRANSMISSION_MODE_2K) &&
-			    (p->guard_interval == GUARD_INTERVAL_1_32)) {
-				/* enable slave */
-				sc_config |= SC_RA_RAM_CONFIG_SLAVE__M;
-			} else {
-				/* disable slave */
-				sc_config &= ~SC_RA_RAM_CONFIG_SLAVE__M;
-			}
-			status = Write16(state, SC_RA_RAM_CONFIG__A, sc_config, 0);
-			if (status < 0)
-				break;
-		}
-
-		status = SetCfgNoiseCalibration(state, &state->noise_cal);
-		if (status < 0)
-			break;
-
-		if (state->cscd_state == CSCD_INIT) {
-			/* switch on SRMM scan in SC */
-			status = Write16(state, SC_RA_RAM_SAMPLE_RATE_COUNT__A, DRXD_OSCDEV_DO_SCAN, 0x0000);
-			if (status < 0)
-				break;
-/*            CHK_ERROR(Write16(SC_RA_RAM_SAMPLE_RATE_STEP__A, DRXD_OSCDEV_STEP, 0x0000));*/
-			state->cscd_state = CSCD_SET;
-		}
-
-		/* Now compute FE_IF_REG_INCR */
-		/*((( SysFreq/BandWidth)/2)/2) -1) * 2^23) =>
-		   ((SysFreq / BandWidth) * (2^21) ) - (2^23) */
-		feIfIncr = MulDiv32(state->sys_clock_freq * 1000,
-				    (1ULL << 21), bandwidth) - (1 << 23);
-		status = Write16(state, FE_IF_REG_INCR0__A, (u16) (feIfIncr & FE_IF_REG_INCR0__M), 0x0000);
-		if (status < 0)
-			break;
-		status = Write16(state, FE_IF_REG_INCR1__A, (u16) ((feIfIncr >> FE_IF_REG_INCR0__W) & FE_IF_REG_INCR1__M), 0x0000);
-		if (status < 0)
-			break;
-		/* Bandwidth setting done */
-
-		/* Mirror & frequency offset */
-		SetFrequencyShift(state, off, mirrorFreqSpect);
-
-		/* Start SC, write channel settings to SC */
-
-		/* Enable SC after setting all other parameters */
-		status = Write16(state, SC_COMM_STATE__A, 0, 0x0000);
-		if (status < 0)
-			break;
-		status = Write16(state, SC_COMM_EXEC__A, 1, 0x0000);
-		if (status < 0)
-			break;
-
-		/* Write SC parameter registers, operation mode */
-#if 1
-		operationMode = (SC_RA_RAM_OP_AUTO_MODE__M |
-				 SC_RA_RAM_OP_AUTO_GUARD__M |
-				 SC_RA_RAM_OP_AUTO_CONST__M |
-				 SC_RA_RAM_OP_AUTO_HIER__M |
-				 SC_RA_RAM_OP_AUTO_RATE__M);
-#endif
-		status = SC_SetPrefParamCommand(state, 0x0000, transmissionParams, operationMode);
-		if (status < 0)
-			break;
-
-		/* Start correct processes to get in lock */
-		status = SC_ProcStartCommand(state, SC_RA_RAM_PROC_LOCKTRACK, SC_RA_RAM_SW_EVENT_RUN_NMASK__M, SC_RA_RAM_LOCKTRACK_MIN);
-		if (status < 0)
-			break;
-
-		status = StartOC(state);
-		if (status < 0)
-			break;
-
-		if (state->operation_mode != OM_Default) {
-			status = StartDiversity(state);
-			if (status < 0)
-				break;
-		}
-
-		state->drxd_state = DRXD_STARTED;
-	} while (0);
-
-	return status;
-}
-
-static int CDRXD(struct drxd_state *state, u32 IntermediateFrequency)
-{
-	u32 ulRfAgcOutputLevel = 0xffffffff;
-	u32 ulRfAgcSettleLevel = 528;	/* Optimum value for MT2060 */
-	u32 ulRfAgcMinLevel = 0;	/* Currently unused */
-	u32 ulRfAgcMaxLevel = DRXD_FE_CTRL_MAX;	/* Currently unused */
-	u32 ulRfAgcSpeed = 0;	/* Currently unused */
-	u32 ulRfAgcMode = 0;	/*2;   Off */
-	u32 ulRfAgcR1 = 820;
-	u32 ulRfAgcR2 = 2200;
-	u32 ulRfAgcR3 = 150;
-	u32 ulIfAgcMode = 0;	/* Auto */
-	u32 ulIfAgcOutputLevel = 0xffffffff;
-	u32 ulIfAgcSettleLevel = 0xffffffff;
-	u32 ulIfAgcMinLevel = 0xffffffff;
-	u32 ulIfAgcMaxLevel = 0xffffffff;
-	u32 ulIfAgcSpeed = 0xffffffff;
-	u32 ulIfAgcR1 = 820;
-	u32 ulIfAgcR2 = 2200;
-	u32 ulIfAgcR3 = 150;
-	u32 ulClock = state->config.clock;
-	u32 ulSerialMode = 0;
-	u32 ulEcOcRegOcModeLop = 4;	/* Dynamic DTO source */
-	u32 ulHiI2cDelay = HI_I2C_DELAY;
-	u32 ulHiI2cBridgeDelay = HI_I2C_BRIDGE_DELAY;
-	u32 ulHiI2cPatch = 0;
-	u32 ulEnvironment = APPENV_PORTABLE;
-	u32 ulEnvironmentDiversity = APPENV_MOBILE;
-	u32 ulIFFilter = IFFILTER_SAW;
-
-	state->if_agc_cfg.ctrlMode = AGC_CTRL_AUTO;
-	state->if_agc_cfg.outputLevel = 0;
-	state->if_agc_cfg.settleLevel = 140;
-	state->if_agc_cfg.minOutputLevel = 0;
-	state->if_agc_cfg.maxOutputLevel = 1023;
-	state->if_agc_cfg.speed = 904;
-
-	if (ulIfAgcMode == 1 && ulIfAgcOutputLevel <= DRXD_FE_CTRL_MAX) {
-		state->if_agc_cfg.ctrlMode = AGC_CTRL_USER;
-		state->if_agc_cfg.outputLevel = (u16) (ulIfAgcOutputLevel);
-	}
-
-	if (ulIfAgcMode == 0 &&
-	    ulIfAgcSettleLevel <= DRXD_FE_CTRL_MAX &&
-	    ulIfAgcMinLevel <= DRXD_FE_CTRL_MAX &&
-	    ulIfAgcMaxLevel <= DRXD_FE_CTRL_MAX &&
-	    ulIfAgcSpeed <= DRXD_FE_CTRL_MAX) {
-		state->if_agc_cfg.ctrlMode = AGC_CTRL_AUTO;
-		state->if_agc_cfg.settleLevel = (u16) (ulIfAgcSettleLevel);
-		state->if_agc_cfg.minOutputLevel = (u16) (ulIfAgcMinLevel);
-		state->if_agc_cfg.maxOutputLevel = (u16) (ulIfAgcMaxLevel);
-		state->if_agc_cfg.speed = (u16) (ulIfAgcSpeed);
-	}
-
-	state->if_agc_cfg.R1 = (u16) (ulIfAgcR1);
-	state->if_agc_cfg.R2 = (u16) (ulIfAgcR2);
-	state->if_agc_cfg.R3 = (u16) (ulIfAgcR3);
-
-	state->rf_agc_cfg.R1 = (u16) (ulRfAgcR1);
-	state->rf_agc_cfg.R2 = (u16) (ulRfAgcR2);
-	state->rf_agc_cfg.R3 = (u16) (ulRfAgcR3);
-
-	state->rf_agc_cfg.ctrlMode = AGC_CTRL_AUTO;
-	/* rest of the RFAgcCfg structure currently unused */
-	if (ulRfAgcMode == 1 && ulRfAgcOutputLevel <= DRXD_FE_CTRL_MAX) {
-		state->rf_agc_cfg.ctrlMode = AGC_CTRL_USER;
-		state->rf_agc_cfg.outputLevel = (u16) (ulRfAgcOutputLevel);
-	}
-
-	if (ulRfAgcMode == 0 &&
-	    ulRfAgcSettleLevel <= DRXD_FE_CTRL_MAX &&
-	    ulRfAgcMinLevel <= DRXD_FE_CTRL_MAX &&
-	    ulRfAgcMaxLevel <= DRXD_FE_CTRL_MAX &&
-	    ulRfAgcSpeed <= DRXD_FE_CTRL_MAX) {
-		state->rf_agc_cfg.ctrlMode = AGC_CTRL_AUTO;
-		state->rf_agc_cfg.settleLevel = (u16) (ulRfAgcSettleLevel);
-		state->rf_agc_cfg.minOutputLevel = (u16) (ulRfAgcMinLevel);
-		state->rf_agc_cfg.maxOutputLevel = (u16) (ulRfAgcMaxLevel);
-		state->rf_agc_cfg.speed = (u16) (ulRfAgcSpeed);
-	}
-
-	if (ulRfAgcMode == 2)
-		state->rf_agc_cfg.ctrlMode = AGC_CTRL_OFF;
-
-	if (ulEnvironment <= 2)
-		state->app_env_default = (enum app_env)
-		    (ulEnvironment);
-	if (ulEnvironmentDiversity <= 2)
-		state->app_env_diversity = (enum app_env)
-		    (ulEnvironmentDiversity);
-
-	if (ulIFFilter == IFFILTER_DISCRETE) {
-		/* discrete filter */
-		state->noise_cal.cpOpt = 0;
-		state->noise_cal.cpNexpOfs = 40;
-		state->noise_cal.tdCal2k = -40;
-		state->noise_cal.tdCal8k = -24;
-	} else {
-		/* SAW filter */
-		state->noise_cal.cpOpt = 1;
-		state->noise_cal.cpNexpOfs = 0;
-		state->noise_cal.tdCal2k = -21;
-		state->noise_cal.tdCal8k = -24;
-	}
-	state->m_EcOcRegOcModeLop = (u16) (ulEcOcRegOcModeLop);
-
-	state->chip_adr = (state->config.demod_address << 1) | 1;
-	switch (ulHiI2cPatch) {
-	case 1:
-		state->m_HiI2cPatch = DRXD_HiI2cPatch_1;
-		break;
-	case 3:
-		state->m_HiI2cPatch = DRXD_HiI2cPatch_3;
-		break;
-	default:
-		state->m_HiI2cPatch = NULL;
-	}
-
-	/* modify tuner and clock attributes */
-	state->intermediate_freq = (u16) (IntermediateFrequency / 1000);
-	/* expected system clock frequency in kHz */
-	state->expected_sys_clock_freq = 48000;
-	/* real system clock frequency in kHz */
-	state->sys_clock_freq = 48000;
-	state->osc_clock_freq = (u16) ulClock;
-	state->osc_clock_deviation = 0;
-	state->cscd_state = CSCD_INIT;
-	state->drxd_state = DRXD_UNINITIALIZED;
-
-	state->PGA = 0;
-	state->type_A = 0;
-	state->tuner_mirrors = 0;
-
-	/* modify MPEG output attributes */
-	state->insert_rs_byte = state->config.insert_rs_byte;
-	state->enable_parallel = (ulSerialMode != 1);
-
-	/* Timing div, 250ns/Psys */
-	/* Timing div, = ( delay (nano seconds) * sysclk (kHz) )/ 1000 */
-
-	state->hi_cfg_timing_div = (u16) ((state->sys_clock_freq / 1000) *
-					  ulHiI2cDelay) / 1000;
-	/* Bridge delay, uses oscilator clock */
-	/* Delay = ( delay (nano seconds) * oscclk (kHz) )/ 1000 */
-	state->hi_cfg_bridge_delay = (u16) ((state->osc_clock_freq / 1000) *
-					    ulHiI2cBridgeDelay) / 1000;
-
-	state->m_FeAgRegAgPwd = DRXD_DEF_AG_PWD_CONSUMER;
-	/* state->m_FeAgRegAgPwd = DRXD_DEF_AG_PWD_PRO; */
-	state->m_FeAgRegAgAgcSio = DRXD_DEF_AG_AGC_SIO;
-	return 0;
-}
-
-int DRXD_init(struct drxd_state *state, const u8 * fw, u32 fw_size)
-{
-	int status = 0;
-	u32 driverVersion;
-
-	if (state->init_done)
-		return 0;
-
-	CDRXD(state, state->config.IF ? state->config.IF : 36000000);
-
-	do {
-		state->operation_mode = OM_Default;
-
-		status = SetDeviceTypeId(state);
-		if (status < 0)
-			break;
-
-		/* Apply I2c address patch to B1 */
-		if (!state->type_A && state->m_HiI2cPatch != NULL)
-			status = WriteTable(state, state->m_HiI2cPatch);
-			if (status < 0)
-				break;
-
-		if (state->type_A) {
-			/* HI firmware patch for UIO readout,
-			   avoid clearing of result register */
-			status = Write16(state, 0x43012D, 0x047f, 0);
-			if (status < 0)
-				break;
-		}
-
-		status = HI_ResetCommand(state);
-		if (status < 0)
-			break;
-
-		status = StopAllProcessors(state);
-		if (status < 0)
-			break;
-		status = InitCC(state);
-		if (status < 0)
-			break;
-
-		state->osc_clock_deviation = 0;
-
-		if (state->config.osc_deviation)
-			state->osc_clock_deviation =
-			    state->config.osc_deviation(state->priv, 0, 0);
-		{
-			/* Handle clock deviation */
-			s32 devB;
-			s32 devA = (s32) (state->osc_clock_deviation) *
-			    (s32) (state->expected_sys_clock_freq);
-			/* deviation in kHz */
-			s32 deviation = (devA / (1000000L));
-			/* rounding, signed */
-			if (devA > 0)
-				devB = (2);
-			else
-				devB = (-2);
-			if ((devB * (devA % 1000000L) > 1000000L)) {
-				/* add +1 or -1 */
-				deviation += (devB / 2);
-			}
-
-			state->sys_clock_freq =
-			    (u16) ((state->expected_sys_clock_freq) +
-				   deviation);
-		}
-		status = InitHI(state);
-		if (status < 0)
-			break;
-		status = InitAtomicRead(state);
-		if (status < 0)
-			break;
-
-		status = EnableAndResetMB(state);
-		if (status < 0)
-			break;
-		if (state->type_A)
-			status = ResetCEFR(state);
-			if (status < 0)
-				break;
-
-		if (fw) {
-			status = DownloadMicrocode(state, fw, fw_size);
-			if (status < 0)
-				break;
-		} else {
-			status = DownloadMicrocode(state, state->microcode, state->microcode_length);
-			if (status < 0)
-				break;
-		}
-
-		if (state->PGA) {
-			state->m_FeAgRegAgPwd = DRXD_DEF_AG_PWD_PRO;
-			SetCfgPga(state, 0);	/* PGA = 0 dB */
-		} else {
-			state->m_FeAgRegAgPwd = DRXD_DEF_AG_PWD_CONSUMER;
-		}
-
-		state->m_FeAgRegAgAgcSio = DRXD_DEF_AG_AGC_SIO;
-
-		status = InitFE(state);
-		if (status < 0)
-			break;
-		status = InitFT(state);
-		if (status < 0)
-			break;
-		status = InitCP(state);
-		if (status < 0)
-			break;
-		status = InitCE(state);
-		if (status < 0)
-			break;
-		status = InitEQ(state);
-		if (status < 0)
-			break;
-		status = InitEC(state);
-		if (status < 0)
-			break;
-		status = InitSC(state);
-		if (status < 0)
-			break;
-
-		status = SetCfgIfAgc(state, &state->if_agc_cfg);
-		if (status < 0)
-			break;
-		status = SetCfgRfAgc(state, &state->rf_agc_cfg);
-		if (status < 0)
-			break;
-
-		state->cscd_state = CSCD_INIT;
-		status = Write16(state, SC_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0);
-		if (status < 0)
-			break;
-		status = Write16(state, LC_COMM_EXEC__A, SC_COMM_EXEC_CTL_STOP, 0);
-		if (status < 0)
-			break;
-
-		driverVersion = (((VERSION_MAJOR / 10) << 4) +
-				 (VERSION_MAJOR % 10)) << 24;
-		driverVersion += (((VERSION_MINOR / 10) << 4) +
-				  (VERSION_MINOR % 10)) << 16;
-		driverVersion += ((VERSION_PATCH / 1000) << 12) +
-		    ((VERSION_PATCH / 100) << 8) +
-		    ((VERSION_PATCH / 10) << 4) + (VERSION_PATCH % 10);
-
-		status = Write32(state, SC_RA_RAM_DRIVER_VERSION__AX, driverVersion, 0);
-		if (status < 0)
-			break;
-
-		status = StopOC(state);
-		if (status < 0)
-			break;
-
-		state->drxd_state = DRXD_STOPPED;
-		state->init_done = 1;
-		status = 0;
-	} while (0);
-	return status;
-}
-
-int DRXD_status(struct drxd_state *state, u32 * pLockStatus)
-{
-	DRX_GetLockStatus(state, pLockStatus);
-
-	/*if (*pLockStatus&DRX_LOCK_MPEG) */
-	if (*pLockStatus & DRX_LOCK_FEC) {
-		ConfigureMPEGOutput(state, 1);
-		/* Get status again, in case we have MPEG lock now */
-		/*DRX_GetLockStatus(state, pLockStatus); */
-	}
-
-	return 0;
-}
-
-/****************************************************************************/
-/****************************************************************************/
-/****************************************************************************/
-
-static int drxd_read_signal_strength(struct dvb_frontend *fe, u16 * strength)
-{
-	struct drxd_state *state = fe->demodulator_priv;
-	u32 value;
-	int res;
-
-	res = ReadIFAgc(state, &value);
-	if (res < 0)
-		*strength = 0;
-	else
-		*strength = 0xffff - (value << 4);
-	return 0;
-}
-
-static int drxd_read_status(struct dvb_frontend *fe, fe_status_t * status)
-{
-	struct drxd_state *state = fe->demodulator_priv;
-	u32 lock;
-
-	DRXD_status(state, &lock);
-	*status = 0;
-	/* No MPEG lock in V255 firmware, bug ? */
-#if 1
-	if (lock & DRX_LOCK_MPEG)
-		*status |= FE_HAS_LOCK;
-#else
-	if (lock & DRX_LOCK_FEC)
-		*status |= FE_HAS_LOCK;
-#endif
-	if (lock & DRX_LOCK_FEC)
-		*status |= FE_HAS_VITERBI | FE_HAS_SYNC;
-	if (lock & DRX_LOCK_DEMOD)
-		*status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
-
-	return 0;
-}
-
-static int drxd_init(struct dvb_frontend *fe)
-{
-	struct drxd_state *state = fe->demodulator_priv;
-	int err = 0;
-
-/*	if (request_firmware(&state->fw, "drxd.fw", state->dev)<0) */
-	return DRXD_init(state, 0, 0);
-
-	err = DRXD_init(state, state->fw->data, state->fw->size);
-	release_firmware(state->fw);
-	return err;
-}
-
-int drxd_config_i2c(struct dvb_frontend *fe, int onoff)
-{
-	struct drxd_state *state = fe->demodulator_priv;
-
-	if (state->config.disable_i2c_gate_ctrl == 1)
-		return 0;
-
-	return DRX_ConfigureI2CBridge(state, onoff);
-}
-EXPORT_SYMBOL(drxd_config_i2c);
-
-static int drxd_get_tune_settings(struct dvb_frontend *fe,
-				  struct dvb_frontend_tune_settings *sets)
-{
-	sets->min_delay_ms = 10000;
-	sets->max_drift = 0;
-	sets->step_size = 0;
-	return 0;
-}
-
-static int drxd_read_ber(struct dvb_frontend *fe, u32 * ber)
-{
-	*ber = 0;
-	return 0;
-}
-
-static int drxd_read_snr(struct dvb_frontend *fe, u16 * snr)
-{
-	*snr = 0;
-	return 0;
-}
-
-static int drxd_read_ucblocks(struct dvb_frontend *fe, u32 * ucblocks)
-{
-	*ucblocks = 0;
-	return 0;
-}
-
-static int drxd_sleep(struct dvb_frontend *fe)
-{
-	struct drxd_state *state = fe->demodulator_priv;
-
-	ConfigureMPEGOutput(state, 0);
-	return 0;
-}
-
-static int drxd_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
-{
-	return drxd_config_i2c(fe, enable);
-}
-
-static int drxd_set_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct drxd_state *state = fe->demodulator_priv;
-	s32 off = 0;
-
-	state->props = *p;
-	DRX_Stop(state);
-
-	if (fe->ops.tuner_ops.set_params) {
-		fe->ops.tuner_ops.set_params(fe);
-		if (fe->ops.i2c_gate_ctrl)
-			fe->ops.i2c_gate_ctrl(fe, 0);
-	}
-
-	msleep(200);
-
-	return DRX_Start(state, off);
-}
-
-static void drxd_release(struct dvb_frontend *fe)
-{
-	struct drxd_state *state = fe->demodulator_priv;
-
-	kfree(state);
-}
-
-static struct dvb_frontend_ops drxd_ops = {
-	.delsys = { SYS_DVBT},
-	.info = {
-		 .name = "Micronas DRXD DVB-T",
-		 .frequency_min = 47125000,
-		 .frequency_max = 855250000,
-		 .frequency_stepsize = 166667,
-		 .frequency_tolerance = 0,
-		 .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_FEC_AUTO |
-		 FE_CAN_QAM_16 | FE_CAN_QAM_64 |
-		 FE_CAN_QAM_AUTO |
-		 FE_CAN_TRANSMISSION_MODE_AUTO |
-		 FE_CAN_GUARD_INTERVAL_AUTO |
-		 FE_CAN_HIERARCHY_AUTO | FE_CAN_RECOVER | FE_CAN_MUTE_TS},
-
-	.release = drxd_release,
-	.init = drxd_init,
-	.sleep = drxd_sleep,
-	.i2c_gate_ctrl = drxd_i2c_gate_ctrl,
-
-	.set_frontend = drxd_set_frontend,
-	.get_tune_settings = drxd_get_tune_settings,
-
-	.read_status = drxd_read_status,
-	.read_ber = drxd_read_ber,
-	.read_signal_strength = drxd_read_signal_strength,
-	.read_snr = drxd_read_snr,
-	.read_ucblocks = drxd_read_ucblocks,
-};
-
-struct dvb_frontend *drxd_attach(const struct drxd_config *config,
-				 void *priv, struct i2c_adapter *i2c,
-				 struct device *dev)
-{
-	struct drxd_state *state = NULL;
-
-	state = kmalloc(sizeof(struct drxd_state), GFP_KERNEL);
-	if (!state)
-		return NULL;
-	memset(state, 0, sizeof(*state));
-
-	memcpy(&state->ops, &drxd_ops, sizeof(struct dvb_frontend_ops));
-	state->dev = dev;
-	state->config = *config;
-	state->i2c = i2c;
-	state->priv = priv;
-
-	mutex_init(&state->mutex);
-
-	if (Read16(state, 0, 0, 0) < 0)
-		goto error;
-
-	memcpy(&state->frontend.ops, &drxd_ops,
-	       sizeof(struct dvb_frontend_ops));
-	state->frontend.demodulator_priv = state;
-	ConfigureMPEGOutput(state, 0);
-	return &state->frontend;
-
-error:
-	printk(KERN_ERR "drxd: not found\n");
-	kfree(state);
-	return NULL;
-}
-EXPORT_SYMBOL(drxd_attach);
-
-MODULE_DESCRIPTION("DRXD driver");
-MODULE_AUTHOR("Micronas");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/drxd_map_firm.h b/drivers/media/dvb/frontends/drxd_map_firm.h
deleted file mode 100644
index 6bc553a..0000000
--- a/drivers/media/dvb/frontends/drxd_map_firm.h
+++ /dev/null
@@ -1,1013 +0,0 @@
-/*
- * drx3973d_map_firm.h
- *
- * Copyright (C) 2006-2007 Micronas
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 only, as published by the Free Software Foundation.
- *
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#ifndef __DRX3973D_MAP__H__
-#define __DRX3973D_MAP__H__
-
-/*
- * Note: originally, this file contained 12000+ lines of data
- * Probably a few lines for every firwmare assembler instruction. However,
- * only a few defines were actually used. So, removed all uneeded lines.
- * If ever needed, the other lines can be easily obtained via git history.
- */
-
-#define HI_COMM_EXEC__A                                              0x400000
-#define HI_COMM_MB__A                                                0x400002
-#define HI_CT_REG_COMM_STATE__A                                      0x410001
-#define HI_RA_RAM_SRV_RES__A                                         0x420031
-#define HI_RA_RAM_SRV_CMD__A                                         0x420032
-#define   HI_RA_RAM_SRV_CMD_RESET                                    0x2
-#define   HI_RA_RAM_SRV_CMD_CONFIG                                   0x3
-#define   HI_RA_RAM_SRV_CMD_EXECUTE                                  0x6
-#define HI_RA_RAM_SRV_RST_KEY__A                                     0x420033
-#define   HI_RA_RAM_SRV_RST_KEY_ACT                                  0x3973
-#define HI_RA_RAM_SRV_CFG_KEY__A                                     0x420033
-#define HI_RA_RAM_SRV_CFG_DIV__A                                     0x420034
-#define HI_RA_RAM_SRV_CFG_BDL__A                                     0x420035
-#define HI_RA_RAM_SRV_CFG_WUP__A                                     0x420036
-#define HI_RA_RAM_SRV_CFG_ACT__A                                     0x420037
-#define     HI_RA_RAM_SRV_CFG_ACT_SLV0_ON                            0x1
-#define   HI_RA_RAM_SRV_CFG_ACT_BRD__M                               0x4
-#define     HI_RA_RAM_SRV_CFG_ACT_BRD_OFF                            0x0
-#define     HI_RA_RAM_SRV_CFG_ACT_BRD_ON                             0x4
-#define     HI_RA_RAM_SRV_CFG_ACT_PWD_EXE                            0x8
-#define HI_RA_RAM_USR_BEGIN__A                                       0x420040
-#define HI_IF_RAM_TRP_BPT0__AX                                       0x430000
-#define HI_IF_RAM_USR_BEGIN__A                                       0x430200
-#define SC_COMM_EXEC__A                                              0x800000
-#define     SC_COMM_EXEC_CTL_STOP                                    0x0
-#define SC_COMM_STATE__A                                             0x800001
-#define SC_RA_RAM_PARAM0__A                                          0x820040
-#define SC_RA_RAM_PARAM1__A                                          0x820041
-#define SC_RA_RAM_CMD_ADDR__A                                        0x820042
-#define SC_RA_RAM_CMD__A                                             0x820043
-#define   SC_RA_RAM_CMD_PROC_START                                   0x1
-#define   SC_RA_RAM_CMD_SET_PREF_PARAM                               0x3
-#define   SC_RA_RAM_CMD_GET_OP_PARAM                                 0x5
-#define   SC_RA_RAM_SW_EVENT_RUN_NMASK__M                            0x1
-#define   SC_RA_RAM_LOCKTRACK_MIN                                    0x1
-#define     SC_RA_RAM_OP_PARAM_MODE_2K                               0x0
-#define     SC_RA_RAM_OP_PARAM_MODE_8K                               0x1
-#define     SC_RA_RAM_OP_PARAM_GUARD_32                              0x0
-#define     SC_RA_RAM_OP_PARAM_GUARD_16                              0x4
-#define     SC_RA_RAM_OP_PARAM_GUARD_8                               0x8
-#define     SC_RA_RAM_OP_PARAM_GUARD_4                               0xC
-#define     SC_RA_RAM_OP_PARAM_CONST_QPSK                            0x0
-#define     SC_RA_RAM_OP_PARAM_CONST_QAM16                           0x10
-#define     SC_RA_RAM_OP_PARAM_CONST_QAM64                           0x20
-#define     SC_RA_RAM_OP_PARAM_HIER_NO                               0x0
-#define     SC_RA_RAM_OP_PARAM_HIER_A1                               0x40
-#define     SC_RA_RAM_OP_PARAM_HIER_A2                               0x80
-#define     SC_RA_RAM_OP_PARAM_HIER_A4                               0xC0
-#define     SC_RA_RAM_OP_PARAM_RATE_1_2                              0x0
-#define     SC_RA_RAM_OP_PARAM_RATE_2_3                              0x200
-#define     SC_RA_RAM_OP_PARAM_RATE_3_4                              0x400
-#define     SC_RA_RAM_OP_PARAM_RATE_5_6                              0x600
-#define     SC_RA_RAM_OP_PARAM_RATE_7_8                              0x800
-#define     SC_RA_RAM_OP_PARAM_PRIO_HI                               0x0
-#define     SC_RA_RAM_OP_PARAM_PRIO_LO                               0x1000
-#define   SC_RA_RAM_OP_AUTO_MODE__M                                  0x1
-#define   SC_RA_RAM_OP_AUTO_GUARD__M                                 0x2
-#define   SC_RA_RAM_OP_AUTO_CONST__M                                 0x4
-#define   SC_RA_RAM_OP_AUTO_HIER__M                                  0x8
-#define   SC_RA_RAM_OP_AUTO_RATE__M                                  0x10
-#define SC_RA_RAM_LOCK__A                                            0x82004B
-#define   SC_RA_RAM_LOCK_DEMOD__M                                    0x1
-#define   SC_RA_RAM_LOCK_FEC__M                                      0x2
-#define   SC_RA_RAM_LOCK_MPEG__M                                     0x4
-#define SC_RA_RAM_BE_OPT_ENA__A                                      0x82004C
-#define   SC_RA_RAM_BE_OPT_ENA_CP_OPT                                0x1
-#define SC_RA_RAM_BE_OPT_DELAY__A                                    0x82004D
-#define SC_RA_RAM_CONFIG__A                                          0x820050
-#define   SC_RA_RAM_CONFIG_FR_ENABLE__M                              0x4
-#define   SC_RA_RAM_CONFIG_FREQSCAN__M                               0x10
-#define   SC_RA_RAM_CONFIG_SLAVE__M                                  0x20
-#define SC_RA_RAM_IF_SAVE__AX                                        0x82008E
-#define SC_RA_RAM_IR_COARSE_2K_LENGTH__A                             0x8200D1
-#define SC_RA_RAM_IR_COARSE_2K_LENGTH__PRE                           0x9
-#define SC_RA_RAM_IR_COARSE_2K_FREQINC__A                            0x8200D2
-#define SC_RA_RAM_IR_COARSE_2K_FREQINC__PRE                          0x4
-#define SC_RA_RAM_IR_COARSE_2K_KAISINC__A                            0x8200D3
-#define SC_RA_RAM_IR_COARSE_2K_KAISINC__PRE                          0x100
-#define SC_RA_RAM_IR_COARSE_8K_LENGTH__A                             0x8200D4
-#define SC_RA_RAM_IR_COARSE_8K_LENGTH__PRE                           0x8
-#define SC_RA_RAM_IR_COARSE_8K_FREQINC__A                            0x8200D5
-#define SC_RA_RAM_IR_COARSE_8K_FREQINC__PRE                          0x8
-#define SC_RA_RAM_IR_COARSE_8K_KAISINC__A                            0x8200D6
-#define SC_RA_RAM_IR_COARSE_8K_KAISINC__PRE                          0x200
-#define SC_RA_RAM_IR_FINE_2K_LENGTH__A                               0x8200D7
-#define SC_RA_RAM_IR_FINE_2K_LENGTH__PRE                             0x9
-#define SC_RA_RAM_IR_FINE_2K_FREQINC__A                              0x8200D8
-#define SC_RA_RAM_IR_FINE_2K_FREQINC__PRE                            0x4
-#define SC_RA_RAM_IR_FINE_2K_KAISINC__A                              0x8200D9
-#define SC_RA_RAM_IR_FINE_2K_KAISINC__PRE                            0x100
-#define SC_RA_RAM_IR_FINE_8K_LENGTH__A                               0x8200DA
-#define SC_RA_RAM_IR_FINE_8K_LENGTH__PRE                             0xB
-#define SC_RA_RAM_IR_FINE_8K_FREQINC__A                              0x8200DB
-#define SC_RA_RAM_IR_FINE_8K_FREQINC__PRE                            0x1
-#define SC_RA_RAM_IR_FINE_8K_KAISINC__A                              0x8200DC
-#define SC_RA_RAM_IR_FINE_8K_KAISINC__PRE                            0x40
-#define SC_RA_RAM_ECHO_SHIFT_LIM__A                                  0x8200DD
-#define SC_RA_RAM_SAMPLE_RATE_COUNT__A                               0x8200E8
-#define SC_RA_RAM_SAMPLE_RATE_STEP__A                                0x8200E9
-#define SC_RA_RAM_BAND__A                                            0x8200EC
-#define SC_RA_RAM_LC_ABS_2K__A                                       0x8200F4
-#define SC_RA_RAM_LC_ABS_2K__PRE                                     0x1F
-#define SC_RA_RAM_LC_ABS_8K__A                                       0x8200F5
-#define SC_RA_RAM_LC_ABS_8K__PRE                                     0x1F
-#define SC_RA_RAM_EQ_IS_GAIN_UNKNOWN_MAN__PRE                        0x1D6
-#define SC_RA_RAM_EQ_IS_GAIN_UNKNOWN_EXP__PRE                        0x4
-#define SC_RA_RAM_EQ_IS_GAIN_QPSK_MAN__PRE                           0x1BB
-#define SC_RA_RAM_EQ_IS_GAIN_QPSK_EXP__PRE                           0x5
-#define SC_RA_RAM_EQ_IS_GAIN_16QAM_MAN__PRE                          0x1EF
-#define SC_RA_RAM_EQ_IS_GAIN_16QAM_EXP__PRE                          0x5
-#define SC_RA_RAM_EQ_IS_GAIN_16QAM_A2_MAN__PRE                       0x15E
-#define SC_RA_RAM_EQ_IS_GAIN_16QAM_A2_EXP__PRE                       0x5
-#define SC_RA_RAM_EQ_IS_GAIN_16QAM_A4_MAN__PRE                       0x11A
-#define SC_RA_RAM_EQ_IS_GAIN_16QAM_A4_EXP__PRE                       0x6
-#define SC_RA_RAM_EQ_IS_GAIN_64QAM_MAN__PRE                          0x1FB
-#define SC_RA_RAM_EQ_IS_GAIN_64QAM_EXP__PRE                          0x5
-#define SC_RA_RAM_EQ_IS_GAIN_64QAM_A2_MAN__PRE                       0x12F
-#define SC_RA_RAM_EQ_IS_GAIN_64QAM_A2_EXP__PRE                       0x5
-#define SC_RA_RAM_EQ_IS_GAIN_64QAM_A4_MAN__PRE                       0x197
-#define SC_RA_RAM_EQ_IS_GAIN_64QAM_A4_EXP__PRE                       0x5
-#define SC_RA_RAM_DRIVER_VERSION__AX                                 0x8201FE
-#define   SC_RA_RAM_PROC_LOCKTRACK                                   0x0
-#define FE_COMM_EXEC__A                                              0xC00000
-#define FE_AD_REG_COMM_EXEC__A                                       0xC10000
-#define FE_AD_REG_FDB_IN__A                                          0xC10012
-#define FE_AD_REG_PD__A                                              0xC10013
-#define FE_AD_REG_INVEXT__A                                          0xC10014
-#define FE_AD_REG_CLKNEG__A                                          0xC10015
-#define FE_AG_REG_COMM_EXEC__A                                       0xC20000
-#define FE_AG_REG_AG_MODE_LOP__A                                     0xC20010
-#define   FE_AG_REG_AG_MODE_LOP_MODE_4__M                            0x10
-#define     FE_AG_REG_AG_MODE_LOP_MODE_4_STATIC                      0x0
-#define     FE_AG_REG_AG_MODE_LOP_MODE_4_DYNAMIC                     0x10
-#define   FE_AG_REG_AG_MODE_LOP_MODE_5__M                            0x20
-#define     FE_AG_REG_AG_MODE_LOP_MODE_5_STATIC                      0x0
-#define   FE_AG_REG_AG_MODE_LOP_MODE_C__M                            0x1000
-#define     FE_AG_REG_AG_MODE_LOP_MODE_C_STATIC                      0x0
-#define     FE_AG_REG_AG_MODE_LOP_MODE_C_DYNAMIC                     0x1000
-#define   FE_AG_REG_AG_MODE_LOP_MODE_E__M                            0x4000
-#define     FE_AG_REG_AG_MODE_LOP_MODE_E_STATIC                      0x0
-#define     FE_AG_REG_AG_MODE_LOP_MODE_E_DYNAMIC                     0x4000
-#define FE_AG_REG_AG_MODE_HIP__A                                     0xC20011
-#define FE_AG_REG_AG_PGA_MODE__A                                     0xC20012
-#define   FE_AG_REG_AG_PGA_MODE_PFY_PCY_AFY_REN                      0x0
-#define   FE_AG_REG_AG_PGA_MODE_PFN_PCN_AFY_REN                      0x1
-#define FE_AG_REG_AG_AGC_SIO__A                                      0xC20013
-#define   FE_AG_REG_AG_AGC_SIO_AGC_SIO_2__M                          0x2
-#define     FE_AG_REG_AG_AGC_SIO_AGC_SIO_2_OUTPUT                    0x0
-#define     FE_AG_REG_AG_AGC_SIO_AGC_SIO_2_INPUT                     0x2
-#define FE_AG_REG_AG_PWD__A                                          0xC20015
-#define   FE_AG_REG_AG_PWD_PWD_PD2__M                                0x2
-#define     FE_AG_REG_AG_PWD_PWD_PD2_DISABLE                         0x0
-#define     FE_AG_REG_AG_PWD_PWD_PD2_ENABLE                          0x2
-#define FE_AG_REG_DCE_AUR_CNT__A                                     0xC20016
-#define FE_AG_REG_DCE_RUR_CNT__A                                     0xC20017
-#define FE_AG_REG_ACE_AUR_CNT__A                                     0xC2001A
-#define FE_AG_REG_ACE_RUR_CNT__A                                     0xC2001B
-#define FE_AG_REG_CDR_RUR_CNT__A                                     0xC20020
-#define FE_AG_REG_EGC_RUR_CNT__A                                     0xC20024
-#define FE_AG_REG_EGC_SET_LVL__A                                     0xC20025
-#define FE_AG_REG_EGC_SET_LVL__M                                     0x1FF
-#define FE_AG_REG_EGC_FLA_RGN__A                                     0xC20026
-#define FE_AG_REG_EGC_SLO_RGN__A                                     0xC20027
-#define FE_AG_REG_EGC_JMP_PSN__A                                     0xC20028
-#define FE_AG_REG_EGC_FLA_INC__A                                     0xC20029
-#define FE_AG_REG_EGC_FLA_DEC__A                                     0xC2002A
-#define FE_AG_REG_EGC_SLO_INC__A                                     0xC2002B
-#define FE_AG_REG_EGC_SLO_DEC__A                                     0xC2002C
-#define FE_AG_REG_EGC_FAS_INC__A                                     0xC2002D
-#define FE_AG_REG_EGC_FAS_DEC__A                                     0xC2002E
-#define FE_AG_REG_PM1_AGC_WRI__A                                     0xC20030
-#define FE_AG_REG_PM1_AGC_WRI__M                                     0x7FF
-#define FE_AG_REG_GC1_AGC_RIC__A                                     0xC20031
-#define FE_AG_REG_GC1_AGC_OFF__A                                     0xC20032
-#define FE_AG_REG_GC1_AGC_MAX__A                                     0xC20033
-#define FE_AG_REG_GC1_AGC_MIN__A                                     0xC20034
-#define FE_AG_REG_GC1_AGC_DAT__A                                     0xC20035
-#define FE_AG_REG_GC1_AGC_DAT__M                                     0x3FF
-#define FE_AG_REG_PM2_AGC_WRI__A                                     0xC20036
-#define FE_AG_REG_IND_WIN__A                                         0xC2003C
-#define FE_AG_REG_IND_THD_LOL__A                                     0xC2003D
-#define FE_AG_REG_IND_THD_HIL__A                                     0xC2003E
-#define FE_AG_REG_IND_DEL__A                                         0xC2003F
-#define FE_AG_REG_IND_PD1_WRI__A                                     0xC20040
-#define FE_AG_REG_PDA_AUR_CNT__A                                     0xC20041
-#define FE_AG_REG_PDA_RUR_CNT__A                                     0xC20042
-#define FE_AG_REG_PDA_AVE_DAT__A                                     0xC20043
-#define FE_AG_REG_PDC_RUR_CNT__A                                     0xC20044
-#define FE_AG_REG_PDC_SET_LVL__A                                     0xC20045
-#define FE_AG_REG_PDC_FLA_RGN__A                                     0xC20046
-#define FE_AG_REG_PDC_JMP_PSN__A                                     0xC20047
-#define FE_AG_REG_PDC_FLA_STP__A                                     0xC20048
-#define FE_AG_REG_PDC_SLO_STP__A                                     0xC20049
-#define FE_AG_REG_PDC_PD2_WRI__A                                     0xC2004A
-#define FE_AG_REG_PDC_MAP_DAT__A                                     0xC2004B
-#define FE_AG_REG_PDC_MAX__A                                         0xC2004C
-#define FE_AG_REG_TGA_AUR_CNT__A                                     0xC2004D
-#define FE_AG_REG_TGA_RUR_CNT__A                                     0xC2004E
-#define FE_AG_REG_TGA_AVE_DAT__A                                     0xC2004F
-#define FE_AG_REG_TGC_RUR_CNT__A                                     0xC20050
-#define FE_AG_REG_TGC_SET_LVL__A                                     0xC20051
-#define FE_AG_REG_TGC_SET_LVL__M                                     0x3F
-#define FE_AG_REG_TGC_FLA_RGN__A                                     0xC20052
-#define FE_AG_REG_TGC_JMP_PSN__A                                     0xC20053
-#define FE_AG_REG_TGC_FLA_STP__A                                     0xC20054
-#define FE_AG_REG_TGC_SLO_STP__A                                     0xC20055
-#define FE_AG_REG_TGC_MAP_DAT__A                                     0xC20056
-#define FE_AG_REG_FGA_AUR_CNT__A                                     0xC20057
-#define FE_AG_REG_FGA_RUR_CNT__A                                     0xC20058
-#define FE_AG_REG_FGM_WRI__A                                         0xC20061
-#define FE_AG_REG_BGC_FGC_WRI__A                                     0xC20068
-#define FE_AG_REG_BGC_CGC_WRI__A                                     0xC20069
-#define FE_FS_REG_COMM_EXEC__A                                       0xC30000
-#define FE_FS_REG_ADD_INC_LOP__A                                     0xC30010
-#define FE_FD_REG_COMM_EXEC__A                                       0xC40000
-#define FE_FD_REG_SCL__A                                             0xC40010
-#define FE_FD_REG_MAX_LEV__A                                         0xC40011
-#define FE_FD_REG_NR__A                                              0xC40012
-#define FE_FD_REG_MEAS_VAL__A                                        0xC40014
-#define FE_IF_REG_COMM_EXEC__A                                       0xC50000
-#define FE_IF_REG_INCR0__A                                           0xC50010
-#define FE_IF_REG_INCR0__W                                           16
-#define FE_IF_REG_INCR0__M                                           0xFFFF
-#define FE_IF_REG_INCR1__A                                           0xC50011
-#define FE_IF_REG_INCR1__M                                           0xFF
-#define FE_CF_REG_COMM_EXEC__A                                       0xC60000
-#define FE_CF_REG_SCL__A                                             0xC60010
-#define FE_CF_REG_MAX_LEV__A                                         0xC60011
-#define FE_CF_REG_NR__A                                              0xC60012
-#define FE_CF_REG_IMP_VAL__A                                         0xC60013
-#define FE_CF_REG_MEAS_VAL__A                                        0xC60014
-#define FE_CU_REG_COMM_EXEC__A                                       0xC70000
-#define FE_CU_REG_FRM_CNT_RST__A                                     0xC70011
-#define FE_CU_REG_FRM_CNT_STR__A                                     0xC70012
-#define FT_COMM_EXEC__A                                              0x1000000
-#define FT_REG_COMM_EXEC__A                                          0x1010000
-#define CP_COMM_EXEC__A                                              0x1400000
-#define CP_REG_COMM_EXEC__A                                          0x1410000
-#define CP_REG_INTERVAL__A                                           0x1410011
-#define CP_REG_BR_SPL_OFFSET__A                                      0x1410023
-#define CP_REG_BR_STR_DEL__A                                         0x1410024
-#define CP_REG_RT_ANG_INC0__A                                        0x1410030
-#define CP_REG_RT_ANG_INC1__A                                        0x1410031
-#define CP_REG_RT_DETECT_ENA__A                                      0x1410032
-#define CP_REG_RT_DETECT_TRH__A                                      0x1410033
-#define CP_REG_RT_EXP_MARG__A                                        0x141003E
-#define CP_REG_AC_NEXP_OFFS__A                                       0x1410040
-#define CP_REG_AC_AVER_POW__A                                        0x1410041
-#define CP_REG_AC_MAX_POW__A                                         0x1410042
-#define CP_REG_AC_WEIGHT_MAN__A                                      0x1410043
-#define CP_REG_AC_WEIGHT_EXP__A                                      0x1410044
-#define CP_REG_AC_AMP_MODE__A                                        0x1410047
-#define CP_REG_AC_AMP_FIX__A                                         0x1410048
-#define CP_REG_AC_ANG_MODE__A                                        0x141004A
-#define CE_COMM_EXEC__A                                              0x1800000
-#define CE_REG_COMM_EXEC__A                                          0x1810000
-#define CE_REG_TAPSET__A                                             0x1810011
-#define CE_REG_AVG_POW__A                                            0x1810012
-#define CE_REG_MAX_POW__A                                            0x1810013
-#define CE_REG_ATT__A                                                0x1810014
-#define CE_REG_NRED__A                                               0x1810015
-#define CE_REG_NE_ERR_SELECT__A                                      0x1810043
-#define CE_REG_NE_TD_CAL__A                                          0x1810044
-#define CE_REG_NE_MIXAVG__A                                          0x1810046
-#define CE_REG_NE_NUPD_OFS__A                                        0x1810047
-#define CE_REG_PE_NEXP_OFFS__A                                       0x1810050
-#define CE_REG_PE_TIMESHIFT__A                                       0x1810051
-#define CE_REG_TP_A0_TAP_NEW__A                                      0x1810064
-#define CE_REG_TP_A0_TAP_NEW_VALID__A                                0x1810065
-#define CE_REG_TP_A0_MU_LMS_STEP__A                                  0x1810066
-#define CE_REG_TP_A1_TAP_NEW__A                                      0x1810068
-#define CE_REG_TP_A1_TAP_NEW_VALID__A                                0x1810069
-#define CE_REG_TP_A1_MU_LMS_STEP__A                                  0x181006A
-#define CE_REG_TI_NEXP_OFFS__A                                       0x1810070
-#define CE_REG_FI_SHT_INCR__A                                        0x1810090
-#define CE_REG_FI_EXP_NORM__A                                        0x1810091
-#define CE_REG_IR_INPUTSEL__A                                        0x18100A0
-#define CE_REG_IR_STARTPOS__A                                        0x18100A1
-#define CE_REG_IR_NEXP_THRES__A                                      0x18100A2
-#define CE_REG_FR_TREAL00__A                                         0x1820010
-#define CE_REG_FR_TIMAG00__A                                         0x1820011
-#define CE_REG_FR_TREAL01__A                                         0x1820012
-#define CE_REG_FR_TIMAG01__A                                         0x1820013
-#define CE_REG_FR_TREAL02__A                                         0x1820014
-#define CE_REG_FR_TIMAG02__A                                         0x1820015
-#define CE_REG_FR_TREAL03__A                                         0x1820016
-#define CE_REG_FR_TIMAG03__A                                         0x1820017
-#define CE_REG_FR_TREAL04__A                                         0x1820018
-#define CE_REG_FR_TIMAG04__A                                         0x1820019
-#define CE_REG_FR_TREAL05__A                                         0x182001A
-#define CE_REG_FR_TIMAG05__A                                         0x182001B
-#define CE_REG_FR_TREAL06__A                                         0x182001C
-#define CE_REG_FR_TIMAG06__A                                         0x182001D
-#define CE_REG_FR_TREAL07__A                                         0x182001E
-#define CE_REG_FR_TIMAG07__A                                         0x182001F
-#define CE_REG_FR_TREAL08__A                                         0x1820020
-#define CE_REG_FR_TIMAG08__A                                         0x1820021
-#define CE_REG_FR_TREAL09__A                                         0x1820022
-#define CE_REG_FR_TIMAG09__A                                         0x1820023
-#define CE_REG_FR_TREAL10__A                                         0x1820024
-#define CE_REG_FR_TIMAG10__A                                         0x1820025
-#define CE_REG_FR_TREAL11__A                                         0x1820026
-#define CE_REG_FR_TIMAG11__A                                         0x1820027
-#define CE_REG_FR_MID_TAP__A                                         0x1820028
-#define CE_REG_FR_SQS_G00__A                                         0x1820029
-#define CE_REG_FR_SQS_G01__A                                         0x182002A
-#define CE_REG_FR_SQS_G02__A                                         0x182002B
-#define CE_REG_FR_SQS_G03__A                                         0x182002C
-#define CE_REG_FR_SQS_G04__A                                         0x182002D
-#define CE_REG_FR_SQS_G05__A                                         0x182002E
-#define CE_REG_FR_SQS_G06__A                                         0x182002F
-#define CE_REG_FR_SQS_G07__A                                         0x1820030
-#define CE_REG_FR_SQS_G08__A                                         0x1820031
-#define CE_REG_FR_SQS_G09__A                                         0x1820032
-#define CE_REG_FR_SQS_G10__A                                         0x1820033
-#define CE_REG_FR_SQS_G11__A                                         0x1820034
-#define CE_REG_FR_SQS_G12__A                                         0x1820035
-#define CE_REG_FR_RIO_G00__A                                         0x1820036
-#define CE_REG_FR_RIO_G01__A                                         0x1820037
-#define CE_REG_FR_RIO_G02__A                                         0x1820038
-#define CE_REG_FR_RIO_G03__A                                         0x1820039
-#define CE_REG_FR_RIO_G04__A                                         0x182003A
-#define CE_REG_FR_RIO_G05__A                                         0x182003B
-#define CE_REG_FR_RIO_G06__A                                         0x182003C
-#define CE_REG_FR_RIO_G07__A                                         0x182003D
-#define CE_REG_FR_RIO_G08__A                                         0x182003E
-#define CE_REG_FR_RIO_G09__A                                         0x182003F
-#define CE_REG_FR_RIO_G10__A                                         0x1820040
-#define CE_REG_FR_MODE__A                                            0x1820041
-#define CE_REG_FR_SQS_TRH__A                                         0x1820042
-#define CE_REG_FR_RIO_GAIN__A                                        0x1820043
-#define CE_REG_FR_BYPASS__A                                          0x1820044
-#define CE_REG_FR_PM_SET__A                                          0x1820045
-#define CE_REG_FR_ERR_SH__A                                          0x1820046
-#define CE_REG_FR_MAN_SH__A                                          0x1820047
-#define CE_REG_FR_TAP_SH__A                                          0x1820048
-#define EQ_COMM_EXEC__A                                              0x1C00000
-#define EQ_REG_COMM_EXEC__A                                          0x1C10000
-#define EQ_REG_COMM_MB__A                                            0x1C10002
-#define EQ_REG_IS_GAIN_MAN__A                                        0x1C10015
-#define EQ_REG_IS_GAIN_EXP__A                                        0x1C10016
-#define EQ_REG_IS_CLIP_EXP__A                                        0x1C10017
-#define EQ_REG_SN_CEGAIN__A                                          0x1C1002A
-#define EQ_REG_SN_OFFSET__A                                          0x1C1002B
-#define EQ_REG_RC_SEL_CAR__A                                         0x1C10032
-#define   EQ_REG_RC_SEL_CAR_INIT                                     0x0
-#define     EQ_REG_RC_SEL_CAR_DIV_ON                                 0x1
-#define     EQ_REG_RC_SEL_CAR_PASS_A_CC                              0x0
-#define     EQ_REG_RC_SEL_CAR_PASS_B_CE                              0x2
-#define     EQ_REG_RC_SEL_CAR_LOCAL_A_CC                             0x0
-#define     EQ_REG_RC_SEL_CAR_LOCAL_B_CE                             0x8
-#define     EQ_REG_RC_SEL_CAR_MEAS_A_CC                              0x0
-#define     EQ_REG_RC_SEL_CAR_MEAS_B_CE                              0x20
-#define EQ_REG_OT_CONST__A                                           0x1C10046
-#define EQ_REG_OT_ALPHA__A                                           0x1C10047
-#define EQ_REG_OT_QNT_THRES0__A                                      0x1C10048
-#define EQ_REG_OT_QNT_THRES1__A                                      0x1C10049
-#define EQ_REG_OT_CSI_STEP__A                                        0x1C1004A
-#define EQ_REG_OT_CSI_OFFSET__A                                      0x1C1004B
-#define EQ_REG_TD_REQ_SMB_CNT__A                                     0x1C10061
-#define EQ_REG_TD_TPS_PWR_OFS__A                                     0x1C10062
-#define EC_SB_REG_COMM_EXEC__A                                       0x2010000
-#define EC_SB_REG_TR_MODE__A                                         0x2010010
-#define   EC_SB_REG_TR_MODE_8K                                       0x0
-#define   EC_SB_REG_TR_MODE_2K                                       0x1
-#define EC_SB_REG_CONST__A                                           0x2010011
-#define   EC_SB_REG_CONST_QPSK                                       0x0
-#define   EC_SB_REG_CONST_16QAM                                      0x1
-#define   EC_SB_REG_CONST_64QAM                                      0x2
-#define EC_SB_REG_ALPHA__A                                           0x2010012
-#define EC_SB_REG_PRIOR__A                                           0x2010013
-#define   EC_SB_REG_PRIOR_HI                                         0x0
-#define   EC_SB_REG_PRIOR_LO                                         0x1
-#define EC_SB_REG_CSI_HI__A                                          0x2010014
-#define EC_SB_REG_CSI_LO__A                                          0x2010015
-#define EC_SB_REG_SMB_TGL__A                                         0x2010016
-#define EC_SB_REG_SNR_HI__A                                          0x2010017
-#define EC_SB_REG_SNR_MID__A                                         0x2010018
-#define EC_SB_REG_SNR_LO__A                                          0x2010019
-#define EC_SB_REG_SCALE_MSB__A                                       0x201001A
-#define EC_SB_REG_SCALE_BIT2__A                                      0x201001B
-#define EC_SB_REG_SCALE_LSB__A                                       0x201001C
-#define EC_SB_REG_CSI_OFS__A                                         0x201001D
-#define EC_VD_REG_COMM_EXEC__A                                       0x2090000
-#define EC_VD_REG_FORCE__A                                           0x2090010
-#define EC_VD_REG_SET_CODERATE__A                                    0x2090011
-#define   EC_VD_REG_SET_CODERATE_C1_2                                0x0
-#define   EC_VD_REG_SET_CODERATE_C2_3                                0x1
-#define   EC_VD_REG_SET_CODERATE_C3_4                                0x2
-#define   EC_VD_REG_SET_CODERATE_C5_6                                0x3
-#define   EC_VD_REG_SET_CODERATE_C7_8                                0x4
-#define EC_VD_REG_REQ_SMB_CNT__A                                     0x2090012
-#define EC_VD_REG_RLK_ENA__A                                         0x2090014
-#define EC_OD_REG_COMM_EXEC__A                                       0x2110000
-#define EC_OD_REG_SYNC__A                                            0x2110010
-#define EC_OD_DEINT_RAM__A                                           0x2120000
-#define EC_RS_REG_COMM_EXEC__A                                       0x2130000
-#define EC_RS_REG_REQ_PCK_CNT__A                                     0x2130010
-#define EC_RS_REG_VAL__A                                             0x2130011
-#define   EC_RS_REG_VAL_PCK                                          0x1
-#define EC_RS_EC_RAM__A                                              0x2140000
-#define EC_OC_REG_COMM_EXEC__A                                       0x2150000
-#define     EC_OC_REG_COMM_EXEC_CTL_ACTIVE                           0x1
-#define     EC_OC_REG_COMM_EXEC_CTL_HOLD                             0x2
-#define EC_OC_REG_COMM_INT_STA__A                                    0x2150007
-#define EC_OC_REG_OC_MODE_LOP__A                                     0x2150010
-#define   EC_OC_REG_OC_MODE_LOP_PAR_ENA__M                           0x1
-#define     EC_OC_REG_OC_MODE_LOP_PAR_ENA_ENABLE                     0x0
-#define     EC_OC_REG_OC_MODE_LOP_PAR_ENA_DISABLE                    0x1
-#define   EC_OC_REG_OC_MODE_LOP_DTO_CTR_SRC__M                       0x4
-#define     EC_OC_REG_OC_MODE_LOP_DTO_CTR_SRC_STATIC                 0x0
-#define   EC_OC_REG_OC_MODE_LOP_MPG_TRM_MDE__M                       0x80
-#define     EC_OC_REG_OC_MODE_LOP_MPG_TRM_MDE_SERIAL                 0x80
-#define EC_OC_REG_OC_MODE_HIP__A                                     0x2150011
-#define     EC_OC_REG_OC_MODE_HIP_MPG_BUS_SRC_MONITOR                0x10
-#define   EC_OC_REG_OC_MODE_HIP_MPG_PAR_VAL__M                       0x200
-#define     EC_OC_REG_OC_MODE_HIP_MPG_PAR_VAL_DISABLE                0x0
-#define     EC_OC_REG_OC_MODE_HIP_MPG_PAR_VAL_ENABLE                 0x200
-#define EC_OC_REG_OC_MPG_SIO__A                                      0x2150012
-#define EC_OC_REG_OC_MPG_SIO__M                                      0xFFF
-#define EC_OC_REG_OC_MON_SIO__A                                      0x2150013
-#define EC_OC_REG_DTO_INC_LOP__A                                     0x2150014
-#define EC_OC_REG_DTO_INC_HIP__A                                     0x2150015
-#define EC_OC_REG_SNC_ISC_LVL__A                                     0x2150016
-#define   EC_OC_REG_SNC_ISC_LVL_OSC__M                               0xF0
-#define EC_OC_REG_TMD_TOP_MODE__A                                    0x215001D
-#define EC_OC_REG_TMD_TOP_CNT__A                                     0x215001E
-#define EC_OC_REG_TMD_HIL_MAR__A                                     0x215001F
-#define EC_OC_REG_TMD_LOL_MAR__A                                     0x2150020
-#define EC_OC_REG_TMD_CUR_CNT__A                                     0x2150021
-#define EC_OC_REG_AVR_ASH_CNT__A                                     0x2150023
-#define EC_OC_REG_AVR_BSH_CNT__A                                     0x2150024
-#define EC_OC_REG_RCN_MODE__A                                        0x2150027
-#define EC_OC_REG_RCN_CRA_LOP__A                                     0x2150028
-#define EC_OC_REG_RCN_CRA_HIP__A                                     0x2150029
-#define EC_OC_REG_RCN_CST_LOP__A                                     0x215002A
-#define EC_OC_REG_RCN_CST_HIP__A                                     0x215002B
-#define EC_OC_REG_RCN_SET_LVL__A                                     0x215002C
-#define EC_OC_REG_RCN_GAI_LVL__A                                     0x215002D
-#define EC_OC_REG_RCN_CLP_LOP__A                                     0x2150032
-#define EC_OC_REG_RCN_CLP_HIP__A                                     0x2150033
-#define EC_OC_REG_RCN_MAP_LOP__A                                     0x2150034
-#define EC_OC_REG_RCN_MAP_HIP__A                                     0x2150035
-#define EC_OC_REG_OCR_MPG_UOS__A                                     0x2150036
-#define EC_OC_REG_OCR_MPG_UOS__M                                     0xFFF
-#define   EC_OC_REG_OCR_MPG_UOS_INIT                                 0x0
-#define EC_OC_REG_OCR_MPG_USR_DAT__A                                 0x2150038
-#define EC_OC_REG_OCR_MON_UOS__A                                     0x2150039
-#define     EC_OC_REG_OCR_MON_UOS_DAT_0_ENABLE                       0x1
-#define     EC_OC_REG_OCR_MON_UOS_DAT_1_ENABLE                       0x2
-#define     EC_OC_REG_OCR_MON_UOS_DAT_2_ENABLE                       0x4
-#define     EC_OC_REG_OCR_MON_UOS_DAT_3_ENABLE                       0x8
-#define     EC_OC_REG_OCR_MON_UOS_DAT_4_ENABLE                       0x10
-#define     EC_OC_REG_OCR_MON_UOS_DAT_5_ENABLE                       0x20
-#define     EC_OC_REG_OCR_MON_UOS_DAT_6_ENABLE                       0x40
-#define     EC_OC_REG_OCR_MON_UOS_DAT_7_ENABLE                       0x80
-#define     EC_OC_REG_OCR_MON_UOS_DAT_8_ENABLE                       0x100
-#define     EC_OC_REG_OCR_MON_UOS_DAT_9_ENABLE                       0x200
-#define     EC_OC_REG_OCR_MON_UOS_VAL_ENABLE                         0x400
-#define     EC_OC_REG_OCR_MON_UOS_CLK_ENABLE                         0x800
-#define EC_OC_REG_OCR_MON_WRI__A                                     0x215003A
-#define   EC_OC_REG_OCR_MON_WRI_INIT                                 0x0
-#define EC_OC_REG_IPR_INV_MPG__A                                     0x2150045
-#define CC_REG_OSC_MODE__A                                           0x2410010
-#define   CC_REG_OSC_MODE_M20                                        0x1
-#define CC_REG_PLL_MODE__A                                           0x2410011
-#define     CC_REG_PLL_MODE_BYPASS_PLL                               0x1
-#define     CC_REG_PLL_MODE_PUMP_CUR_12                              0x14
-#define CC_REG_REF_DIVIDE__A                                         0x2410012
-#define CC_REG_PWD_MODE__A                                           0x2410015
-#define   CC_REG_PWD_MODE_DOWN_PLL                                   0x2
-#define CC_REG_UPDATE__A                                             0x2410017
-#define   CC_REG_UPDATE_KEY                                          0x3973
-#define CC_REG_JTAGID_L__A                                           0x2410019
-#define LC_COMM_EXEC__A                                              0x2800000
-#define LC_RA_RAM_IFINCR_NOM_L__A                                    0x282000C
-#define LC_RA_RAM_FILTER_SYM_SET__A                                  0x282001A
-#define LC_RA_RAM_FILTER_SYM_SET__PRE                                0x3E8
-#define LC_RA_RAM_FILTER_CRMM_A__A                                   0x2820060
-#define LC_RA_RAM_FILTER_CRMM_A__PRE                                 0x4
-#define LC_RA_RAM_FILTER_CRMM_B__A                                   0x2820061
-#define LC_RA_RAM_FILTER_CRMM_B__PRE                                 0x1
-#define LC_RA_RAM_FILTER_SRMM_A__A                                   0x2820068
-#define LC_RA_RAM_FILTER_SRMM_A__PRE                                 0x4
-#define LC_RA_RAM_FILTER_SRMM_B__A                                   0x2820069
-#define LC_RA_RAM_FILTER_SRMM_B__PRE                                 0x1
-#define B_HI_COMM_EXEC__A                                            0x400000
-#define B_HI_COMM_MB__A                                              0x400002
-#define B_HI_CT_REG_COMM_STATE__A                                    0x410001
-#define B_HI_RA_RAM_SRV_RES__A                                       0x420031
-#define B_HI_RA_RAM_SRV_CMD__A                                       0x420032
-#define   B_HI_RA_RAM_SRV_CMD_RESET                                  0x2
-#define   B_HI_RA_RAM_SRV_CMD_CONFIG                                 0x3
-#define   B_HI_RA_RAM_SRV_CMD_EXECUTE                                0x6
-#define B_HI_RA_RAM_SRV_RST_KEY__A                                   0x420033
-#define   B_HI_RA_RAM_SRV_RST_KEY_ACT                                0x3973
-#define B_HI_RA_RAM_SRV_CFG_KEY__A                                   0x420033
-#define B_HI_RA_RAM_SRV_CFG_DIV__A                                   0x420034
-#define B_HI_RA_RAM_SRV_CFG_BDL__A                                   0x420035
-#define B_HI_RA_RAM_SRV_CFG_WUP__A                                   0x420036
-#define B_HI_RA_RAM_SRV_CFG_ACT__A                                   0x420037
-#define     B_HI_RA_RAM_SRV_CFG_ACT_SLV0_ON                          0x1
-#define   B_HI_RA_RAM_SRV_CFG_ACT_BRD__M                             0x4
-#define     B_HI_RA_RAM_SRV_CFG_ACT_BRD_OFF                          0x0
-#define     B_HI_RA_RAM_SRV_CFG_ACT_BRD_ON                           0x4
-#define     B_HI_RA_RAM_SRV_CFG_ACT_PWD_EXE                          0x8
-#define B_HI_RA_RAM_USR_BEGIN__A                                     0x420040
-#define B_HI_IF_RAM_TRP_BPT0__AX                                     0x430000
-#define B_HI_IF_RAM_USR_BEGIN__A                                     0x430200
-#define B_SC_COMM_EXEC__A                                            0x800000
-#define     B_SC_COMM_EXEC_CTL_STOP                                  0x0
-#define B_SC_COMM_STATE__A                                           0x800001
-#define B_SC_RA_RAM_PARAM0__A                                        0x820040
-#define B_SC_RA_RAM_PARAM1__A                                        0x820041
-#define B_SC_RA_RAM_CMD_ADDR__A                                      0x820042
-#define B_SC_RA_RAM_CMD__A                                           0x820043
-#define   B_SC_RA_RAM_CMD_PROC_START                                 0x1
-#define   B_SC_RA_RAM_CMD_SET_PREF_PARAM                             0x3
-#define   B_SC_RA_RAM_CMD_GET_OP_PARAM                               0x5
-#define   B_SC_RA_RAM_SW_EVENT_RUN_NMASK__M                          0x1
-#define   B_SC_RA_RAM_LOCKTRACK_MIN                                  0x1
-#define     B_SC_RA_RAM_OP_PARAM_MODE_2K                             0x0
-#define     B_SC_RA_RAM_OP_PARAM_MODE_8K                             0x1
-#define     B_SC_RA_RAM_OP_PARAM_GUARD_32                            0x0
-#define     B_SC_RA_RAM_OP_PARAM_GUARD_16                            0x4
-#define     B_SC_RA_RAM_OP_PARAM_GUARD_8                             0x8
-#define     B_SC_RA_RAM_OP_PARAM_GUARD_4                             0xC
-#define     B_SC_RA_RAM_OP_PARAM_CONST_QPSK                          0x0
-#define     B_SC_RA_RAM_OP_PARAM_CONST_QAM16                         0x10
-#define     B_SC_RA_RAM_OP_PARAM_CONST_QAM64                         0x20
-#define     B_SC_RA_RAM_OP_PARAM_HIER_NO                             0x0
-#define     B_SC_RA_RAM_OP_PARAM_HIER_A1                             0x40
-#define     B_SC_RA_RAM_OP_PARAM_HIER_A2                             0x80
-#define     B_SC_RA_RAM_OP_PARAM_HIER_A4                             0xC0
-#define     B_SC_RA_RAM_OP_PARAM_RATE_1_2                            0x0
-#define     B_SC_RA_RAM_OP_PARAM_RATE_2_3                            0x200
-#define     B_SC_RA_RAM_OP_PARAM_RATE_3_4                            0x400
-#define     B_SC_RA_RAM_OP_PARAM_RATE_5_6                            0x600
-#define     B_SC_RA_RAM_OP_PARAM_RATE_7_8                            0x800
-#define     B_SC_RA_RAM_OP_PARAM_PRIO_HI                             0x0
-#define     B_SC_RA_RAM_OP_PARAM_PRIO_LO                             0x1000
-#define   B_SC_RA_RAM_OP_AUTO_MODE__M                                0x1
-#define   B_SC_RA_RAM_OP_AUTO_GUARD__M                               0x2
-#define   B_SC_RA_RAM_OP_AUTO_CONST__M                               0x4
-#define   B_SC_RA_RAM_OP_AUTO_HIER__M                                0x8
-#define   B_SC_RA_RAM_OP_AUTO_RATE__M                                0x10
-#define B_SC_RA_RAM_LOCK__A                                          0x82004B
-#define   B_SC_RA_RAM_LOCK_DEMOD__M                                  0x1
-#define   B_SC_RA_RAM_LOCK_FEC__M                                    0x2
-#define   B_SC_RA_RAM_LOCK_MPEG__M                                   0x4
-#define B_SC_RA_RAM_BE_OPT_ENA__A                                    0x82004C
-#define   B_SC_RA_RAM_BE_OPT_ENA_CP_OPT                              0x1
-#define B_SC_RA_RAM_BE_OPT_DELAY__A                                  0x82004D
-#define B_SC_RA_RAM_CONFIG__A                                        0x820050
-#define   B_SC_RA_RAM_CONFIG_FR_ENABLE__M                            0x4
-#define   B_SC_RA_RAM_CONFIG_FREQSCAN__M                             0x10
-#define   B_SC_RA_RAM_CONFIG_SLAVE__M                                0x20
-#define   B_SC_RA_RAM_CONFIG_DIV_BLANK_ENABLE__M                     0x200
-#define   B_SC_RA_RAM_CONFIG_DIV_ECHO_ENABLE__M                      0x400
-#define B_SC_RA_RAM_CO_TD_CAL_2K__A                                  0x82005D
-#define B_SC_RA_RAM_CO_TD_CAL_8K__A                                  0x82005E
-#define B_SC_RA_RAM_IF_SAVE__AX                                      0x82008E
-#define B_SC_RA_RAM_DIVERSITY_DELAY_2K_32__A                         0x820098
-#define B_SC_RA_RAM_DIVERSITY_DELAY_2K_16__A                         0x820099
-#define B_SC_RA_RAM_DIVERSITY_DELAY_2K_8__A                          0x82009A
-#define B_SC_RA_RAM_DIVERSITY_DELAY_2K_4__A                          0x82009B
-#define B_SC_RA_RAM_DIVERSITY_DELAY_8K_32__A                         0x82009C
-#define B_SC_RA_RAM_DIVERSITY_DELAY_8K_16__A                         0x82009D
-#define B_SC_RA_RAM_DIVERSITY_DELAY_8K_8__A                          0x82009E
-#define B_SC_RA_RAM_DIVERSITY_DELAY_8K_4__A                          0x82009F
-#define B_SC_RA_RAM_IR_COARSE_2K_LENGTH__A                           0x8200D1
-#define B_SC_RA_RAM_IR_COARSE_2K_LENGTH__PRE                         0x9
-#define B_SC_RA_RAM_IR_COARSE_2K_FREQINC__A                          0x8200D2
-#define B_SC_RA_RAM_IR_COARSE_2K_FREQINC__PRE                        0x4
-#define B_SC_RA_RAM_IR_COARSE_2K_KAISINC__A                          0x8200D3
-#define B_SC_RA_RAM_IR_COARSE_2K_KAISINC__PRE                        0x100
-#define B_SC_RA_RAM_IR_COARSE_8K_LENGTH__A                           0x8200D4
-#define B_SC_RA_RAM_IR_COARSE_8K_LENGTH__PRE                         0x8
-#define B_SC_RA_RAM_IR_COARSE_8K_FREQINC__A                          0x8200D5
-#define B_SC_RA_RAM_IR_COARSE_8K_FREQINC__PRE                        0x8
-#define B_SC_RA_RAM_IR_COARSE_8K_KAISINC__A                          0x8200D6
-#define B_SC_RA_RAM_IR_COARSE_8K_KAISINC__PRE                        0x200
-#define B_SC_RA_RAM_IR_FINE_2K_LENGTH__A                             0x8200D7
-#define B_SC_RA_RAM_IR_FINE_2K_LENGTH__PRE                           0x9
-#define B_SC_RA_RAM_IR_FINE_2K_FREQINC__A                            0x8200D8
-#define B_SC_RA_RAM_IR_FINE_2K_FREQINC__PRE                          0x4
-#define B_SC_RA_RAM_IR_FINE_2K_KAISINC__A                            0x8200D9
-#define B_SC_RA_RAM_IR_FINE_2K_KAISINC__PRE                          0x100
-#define B_SC_RA_RAM_IR_FINE_8K_LENGTH__A                             0x8200DA
-#define B_SC_RA_RAM_IR_FINE_8K_LENGTH__PRE                           0xB
-#define B_SC_RA_RAM_IR_FINE_8K_FREQINC__A                            0x8200DB
-#define B_SC_RA_RAM_IR_FINE_8K_FREQINC__PRE                          0x1
-#define B_SC_RA_RAM_IR_FINE_8K_KAISINC__A                            0x8200DC
-#define B_SC_RA_RAM_IR_FINE_8K_KAISINC__PRE                          0x40
-#define B_SC_RA_RAM_ECHO_SHIFT_LIM__A                                0x8200DD
-#define B_SC_RA_RAM_SAMPLE_RATE_COUNT__A                             0x8200E8
-#define B_SC_RA_RAM_SAMPLE_RATE_STEP__A                              0x8200E9
-#define B_SC_RA_RAM_BAND__A                                          0x8200EC
-#define B_SC_RA_RAM_LC_ABS_2K__A                                     0x8200F4
-#define B_SC_RA_RAM_LC_ABS_2K__PRE                                   0x1F
-#define B_SC_RA_RAM_LC_ABS_8K__A                                     0x8200F5
-#define B_SC_RA_RAM_LC_ABS_8K__PRE                                   0x1F
-#define B_SC_RA_RAM_EQ_IS_GAIN_UNKNOWN_MAN__PRE                      0x100
-#define B_SC_RA_RAM_EQ_IS_GAIN_UNKNOWN_EXP__PRE                      0x4
-#define B_SC_RA_RAM_EQ_IS_GAIN_QPSK_MAN__PRE                         0x1E2
-#define B_SC_RA_RAM_EQ_IS_GAIN_QPSK_EXP__PRE                         0x4
-#define B_SC_RA_RAM_EQ_IS_GAIN_16QAM_MAN__PRE                        0x10D
-#define B_SC_RA_RAM_EQ_IS_GAIN_16QAM_EXP__PRE                        0x5
-#define B_SC_RA_RAM_EQ_IS_GAIN_16QAM_A2_MAN__PRE                     0x17D
-#define B_SC_RA_RAM_EQ_IS_GAIN_16QAM_A2_EXP__PRE                     0x4
-#define B_SC_RA_RAM_EQ_IS_GAIN_16QAM_A4_MAN__PRE                     0x133
-#define B_SC_RA_RAM_EQ_IS_GAIN_16QAM_A4_EXP__PRE                     0x5
-#define B_SC_RA_RAM_EQ_IS_GAIN_64QAM_MAN__PRE                        0x114
-#define B_SC_RA_RAM_EQ_IS_GAIN_64QAM_EXP__PRE                        0x5
-#define B_SC_RA_RAM_EQ_IS_GAIN_64QAM_A2_MAN__PRE                     0x14A
-#define B_SC_RA_RAM_EQ_IS_GAIN_64QAM_A2_EXP__PRE                     0x4
-#define B_SC_RA_RAM_EQ_IS_GAIN_64QAM_A4_MAN__PRE                     0x1BB
-#define B_SC_RA_RAM_EQ_IS_GAIN_64QAM_A4_EXP__PRE                     0x4
-#define B_SC_RA_RAM_DRIVER_VERSION__AX                               0x8201FE
-#define   B_SC_RA_RAM_PROC_LOCKTRACK                                 0x0
-#define B_FE_COMM_EXEC__A                                            0xC00000
-#define B_FE_AD_REG_COMM_EXEC__A                                     0xC10000
-#define B_FE_AD_REG_FDB_IN__A                                        0xC10012
-#define B_FE_AD_REG_PD__A                                            0xC10013
-#define B_FE_AD_REG_INVEXT__A                                        0xC10014
-#define B_FE_AD_REG_CLKNEG__A                                        0xC10015
-#define B_FE_AG_REG_COMM_EXEC__A                                     0xC20000
-#define B_FE_AG_REG_AG_MODE_LOP__A                                   0xC20010
-#define   B_FE_AG_REG_AG_MODE_LOP_MODE_4__M                          0x10
-#define     B_FE_AG_REG_AG_MODE_LOP_MODE_4_STATIC                    0x0
-#define     B_FE_AG_REG_AG_MODE_LOP_MODE_4_DYNAMIC                   0x10
-#define   B_FE_AG_REG_AG_MODE_LOP_MODE_5__M                          0x20
-#define     B_FE_AG_REG_AG_MODE_LOP_MODE_5_STATIC                    0x0
-#define   B_FE_AG_REG_AG_MODE_LOP_MODE_C__M                          0x1000
-#define     B_FE_AG_REG_AG_MODE_LOP_MODE_C_STATIC                    0x0
-#define     B_FE_AG_REG_AG_MODE_LOP_MODE_C_DYNAMIC                   0x1000
-#define   B_FE_AG_REG_AG_MODE_LOP_MODE_E__M                          0x4000
-#define     B_FE_AG_REG_AG_MODE_LOP_MODE_E_STATIC                    0x0
-#define     B_FE_AG_REG_AG_MODE_LOP_MODE_E_DYNAMIC                   0x4000
-#define B_FE_AG_REG_AG_MODE_HIP__A                                   0xC20011
-#define   B_FE_AG_REG_AG_MODE_HIP_MODE_J__M                          0x8
-#define     B_FE_AG_REG_AG_MODE_HIP_MODE_J_STATIC                    0x0
-#define     B_FE_AG_REG_AG_MODE_HIP_MODE_J_DYNAMIC                   0x8
-#define B_FE_AG_REG_AG_PGA_MODE__A                                   0xC20012
-#define   B_FE_AG_REG_AG_PGA_MODE_PFY_PCY_AFY_REN                    0x0
-#define   B_FE_AG_REG_AG_PGA_MODE_PFN_PCN_AFY_REN                    0x1
-#define B_FE_AG_REG_AG_AGC_SIO__A                                    0xC20013
-#define   B_FE_AG_REG_AG_AGC_SIO_AGC_SIO_2__M                        0x2
-#define     B_FE_AG_REG_AG_AGC_SIO_AGC_SIO_2_OUTPUT                  0x0
-#define     B_FE_AG_REG_AG_AGC_SIO_AGC_SIO_2_INPUT                   0x2
-#define B_FE_AG_REG_AG_PWD__A                                        0xC20015
-#define   B_FE_AG_REG_AG_PWD_PWD_PD2__M                              0x2
-#define     B_FE_AG_REG_AG_PWD_PWD_PD2_DISABLE                       0x0
-#define     B_FE_AG_REG_AG_PWD_PWD_PD2_ENABLE                        0x2
-#define B_FE_AG_REG_DCE_AUR_CNT__A                                   0xC20016
-#define B_FE_AG_REG_DCE_RUR_CNT__A                                   0xC20017
-#define B_FE_AG_REG_ACE_AUR_CNT__A                                   0xC2001A
-#define B_FE_AG_REG_ACE_RUR_CNT__A                                   0xC2001B
-#define B_FE_AG_REG_CDR_RUR_CNT__A                                   0xC20020
-#define B_FE_AG_REG_EGC_RUR_CNT__A                                   0xC20024
-#define B_FE_AG_REG_EGC_SET_LVL__A                                   0xC20025
-#define B_FE_AG_REG_EGC_SET_LVL__M                                   0x1FF
-#define B_FE_AG_REG_EGC_FLA_RGN__A                                   0xC20026
-#define B_FE_AG_REG_EGC_SLO_RGN__A                                   0xC20027
-#define B_FE_AG_REG_EGC_JMP_PSN__A                                   0xC20028
-#define B_FE_AG_REG_EGC_FLA_INC__A                                   0xC20029
-#define B_FE_AG_REG_EGC_FLA_DEC__A                                   0xC2002A
-#define B_FE_AG_REG_EGC_SLO_INC__A                                   0xC2002B
-#define B_FE_AG_REG_EGC_SLO_DEC__A                                   0xC2002C
-#define B_FE_AG_REG_EGC_FAS_INC__A                                   0xC2002D
-#define B_FE_AG_REG_EGC_FAS_DEC__A                                   0xC2002E
-#define B_FE_AG_REG_PM1_AGC_WRI__A                                   0xC20030
-#define B_FE_AG_REG_PM1_AGC_WRI__M                                   0x7FF
-#define B_FE_AG_REG_GC1_AGC_RIC__A                                   0xC20031
-#define B_FE_AG_REG_GC1_AGC_OFF__A                                   0xC20032
-#define B_FE_AG_REG_GC1_AGC_MAX__A                                   0xC20033
-#define B_FE_AG_REG_GC1_AGC_MIN__A                                   0xC20034
-#define B_FE_AG_REG_GC1_AGC_DAT__A                                   0xC20035
-#define B_FE_AG_REG_GC1_AGC_DAT__M                                   0x3FF
-#define B_FE_AG_REG_PM2_AGC_WRI__A                                   0xC20036
-#define B_FE_AG_REG_IND_WIN__A                                       0xC2003C
-#define B_FE_AG_REG_IND_THD_LOL__A                                   0xC2003D
-#define B_FE_AG_REG_IND_THD_HIL__A                                   0xC2003E
-#define B_FE_AG_REG_IND_DEL__A                                       0xC2003F
-#define B_FE_AG_REG_IND_PD1_WRI__A                                   0xC20040
-#define B_FE_AG_REG_PDA_AUR_CNT__A                                   0xC20041
-#define B_FE_AG_REG_PDA_RUR_CNT__A                                   0xC20042
-#define B_FE_AG_REG_PDA_AVE_DAT__A                                   0xC20043
-#define B_FE_AG_REG_PDC_RUR_CNT__A                                   0xC20044
-#define B_FE_AG_REG_PDC_SET_LVL__A                                   0xC20045
-#define B_FE_AG_REG_PDC_FLA_RGN__A                                   0xC20046
-#define B_FE_AG_REG_PDC_JMP_PSN__A                                   0xC20047
-#define B_FE_AG_REG_PDC_FLA_STP__A                                   0xC20048
-#define B_FE_AG_REG_PDC_SLO_STP__A                                   0xC20049
-#define B_FE_AG_REG_PDC_PD2_WRI__A                                   0xC2004A
-#define B_FE_AG_REG_PDC_MAP_DAT__A                                   0xC2004B
-#define B_FE_AG_REG_PDC_MAX__A                                       0xC2004C
-#define B_FE_AG_REG_TGA_AUR_CNT__A                                   0xC2004D
-#define B_FE_AG_REG_TGA_RUR_CNT__A                                   0xC2004E
-#define B_FE_AG_REG_TGA_AVE_DAT__A                                   0xC2004F
-#define B_FE_AG_REG_TGC_RUR_CNT__A                                   0xC20050
-#define B_FE_AG_REG_TGC_SET_LVL__A                                   0xC20051
-#define B_FE_AG_REG_TGC_SET_LVL__M                                   0x3F
-#define B_FE_AG_REG_TGC_FLA_RGN__A                                   0xC20052
-#define B_FE_AG_REG_TGC_JMP_PSN__A                                   0xC20053
-#define B_FE_AG_REG_TGC_FLA_STP__A                                   0xC20054
-#define B_FE_AG_REG_TGC_SLO_STP__A                                   0xC20055
-#define B_FE_AG_REG_TGC_MAP_DAT__A                                   0xC20056
-#define B_FE_AG_REG_FGM_WRI__A                                       0xC20061
-#define B_FE_AG_REG_BGC_FGC_WRI__A                                   0xC20068
-#define B_FE_AG_REG_BGC_CGC_WRI__A                                   0xC20069
-#define B_FE_FS_REG_COMM_EXEC__A                                     0xC30000
-#define B_FE_FS_REG_ADD_INC_LOP__A                                   0xC30010
-#define B_FE_FD_REG_COMM_EXEC__A                                     0xC40000
-#define B_FE_FD_REG_SCL__A                                           0xC40010
-#define B_FE_FD_REG_MAX_LEV__A                                       0xC40011
-#define B_FE_FD_REG_NR__A                                            0xC40012
-#define B_FE_FD_REG_MEAS_VAL__A                                      0xC40014
-#define B_FE_IF_REG_COMM_EXEC__A                                     0xC50000
-#define B_FE_IF_REG_INCR0__A                                         0xC50010
-#define B_FE_IF_REG_INCR0__W                                         16
-#define B_FE_IF_REG_INCR0__M                                         0xFFFF
-#define B_FE_IF_REG_INCR1__A                                         0xC50011
-#define B_FE_IF_REG_INCR1__M                                         0xFF
-#define B_FE_CF_REG_COMM_EXEC__A                                     0xC60000
-#define B_FE_CF_REG_SCL__A                                           0xC60010
-#define B_FE_CF_REG_MAX_LEV__A                                       0xC60011
-#define B_FE_CF_REG_NR__A                                            0xC60012
-#define B_FE_CF_REG_IMP_VAL__A                                       0xC60013
-#define B_FE_CF_REG_MEAS_VAL__A                                      0xC60014
-#define B_FE_CU_REG_COMM_EXEC__A                                     0xC70000
-#define B_FE_CU_REG_FRM_CNT_RST__A                                   0xC70011
-#define B_FE_CU_REG_FRM_CNT_STR__A                                   0xC70012
-#define B_FE_CU_REG_CTR_NFC_ICR__A                                   0xC70020
-#define B_FE_CU_REG_CTR_NFC_OCR__A                                   0xC70021
-#define B_FE_CU_REG_DIV_NFC_CLP__A                                   0xC70027
-#define B_FT_COMM_EXEC__A                                            0x1000000
-#define B_FT_REG_COMM_EXEC__A                                        0x1010000
-#define B_CP_COMM_EXEC__A                                            0x1400000
-#define B_CP_REG_COMM_EXEC__A                                        0x1410000
-#define B_CP_REG_INTERVAL__A                                         0x1410011
-#define B_CP_REG_BR_SPL_OFFSET__A                                    0x1410023
-#define B_CP_REG_BR_STR_DEL__A                                       0x1410024
-#define B_CP_REG_RT_ANG_INC0__A                                      0x1410030
-#define B_CP_REG_RT_ANG_INC1__A                                      0x1410031
-#define B_CP_REG_RT_DETECT_TRH__A                                    0x1410033
-#define B_CP_REG_AC_NEXP_OFFS__A                                     0x1410040
-#define B_CP_REG_AC_AVER_POW__A                                      0x1410041
-#define B_CP_REG_AC_MAX_POW__A                                       0x1410042
-#define B_CP_REG_AC_WEIGHT_MAN__A                                    0x1410043
-#define B_CP_REG_AC_WEIGHT_EXP__A                                    0x1410044
-#define B_CP_REG_AC_AMP_MODE__A                                      0x1410047
-#define B_CP_REG_AC_AMP_FIX__A                                       0x1410048
-#define B_CP_REG_AC_ANG_MODE__A                                      0x141004A
-#define B_CE_COMM_EXEC__A                                            0x1800000
-#define B_CE_REG_COMM_EXEC__A                                        0x1810000
-#define B_CE_REG_TAPSET__A                                           0x1810011
-#define B_CE_REG_AVG_POW__A                                          0x1810012
-#define B_CE_REG_MAX_POW__A                                          0x1810013
-#define B_CE_REG_ATT__A                                              0x1810014
-#define B_CE_REG_NRED__A                                             0x1810015
-#define B_CE_REG_NE_ERR_SELECT__A                                    0x1810043
-#define B_CE_REG_NE_TD_CAL__A                                        0x1810044
-#define B_CE_REG_NE_MIXAVG__A                                        0x1810046
-#define B_CE_REG_NE_NUPD_OFS__A                                      0x1810047
-#define B_CE_REG_PE_NEXP_OFFS__A                                     0x1810050
-#define B_CE_REG_PE_TIMESHIFT__A                                     0x1810051
-#define B_CE_REG_TP_A0_TAP_NEW__A                                    0x1810064
-#define B_CE_REG_TP_A0_TAP_NEW_VALID__A                              0x1810065
-#define B_CE_REG_TP_A0_MU_LMS_STEP__A                                0x1810066
-#define B_CE_REG_TP_A1_TAP_NEW__A                                    0x1810068
-#define B_CE_REG_TP_A1_TAP_NEW_VALID__A                              0x1810069
-#define B_CE_REG_TP_A1_MU_LMS_STEP__A                                0x181006A
-#define B_CE_REG_TI_PHN_ENABLE__A                                    0x1810073
-#define B_CE_REG_FI_SHT_INCR__A                                      0x1810090
-#define B_CE_REG_FI_EXP_NORM__A                                      0x1810091
-#define B_CE_REG_IR_INPUTSEL__A                                      0x18100A0
-#define B_CE_REG_IR_STARTPOS__A                                      0x18100A1
-#define B_CE_REG_IR_NEXP_THRES__A                                    0x18100A2
-#define B_CE_REG_FR_TREAL00__A                                       0x1820010
-#define B_CE_REG_FR_TIMAG00__A                                       0x1820011
-#define B_CE_REG_FR_TREAL01__A                                       0x1820012
-#define B_CE_REG_FR_TIMAG01__A                                       0x1820013
-#define B_CE_REG_FR_TREAL02__A                                       0x1820014
-#define B_CE_REG_FR_TIMAG02__A                                       0x1820015
-#define B_CE_REG_FR_TREAL03__A                                       0x1820016
-#define B_CE_REG_FR_TIMAG03__A                                       0x1820017
-#define B_CE_REG_FR_TREAL04__A                                       0x1820018
-#define B_CE_REG_FR_TIMAG04__A                                       0x1820019
-#define B_CE_REG_FR_TREAL05__A                                       0x182001A
-#define B_CE_REG_FR_TIMAG05__A                                       0x182001B
-#define B_CE_REG_FR_TREAL06__A                                       0x182001C
-#define B_CE_REG_FR_TIMAG06__A                                       0x182001D
-#define B_CE_REG_FR_TREAL07__A                                       0x182001E
-#define B_CE_REG_FR_TIMAG07__A                                       0x182001F
-#define B_CE_REG_FR_TREAL08__A                                       0x1820020
-#define B_CE_REG_FR_TIMAG08__A                                       0x1820021
-#define B_CE_REG_FR_TREAL09__A                                       0x1820022
-#define B_CE_REG_FR_TIMAG09__A                                       0x1820023
-#define B_CE_REG_FR_TREAL10__A                                       0x1820024
-#define B_CE_REG_FR_TIMAG10__A                                       0x1820025
-#define B_CE_REG_FR_TREAL11__A                                       0x1820026
-#define B_CE_REG_FR_TIMAG11__A                                       0x1820027
-#define B_CE_REG_FR_MID_TAP__A                                       0x1820028
-#define B_CE_REG_FR_SQS_G00__A                                       0x1820029
-#define B_CE_REG_FR_SQS_G01__A                                       0x182002A
-#define B_CE_REG_FR_SQS_G02__A                                       0x182002B
-#define B_CE_REG_FR_SQS_G03__A                                       0x182002C
-#define B_CE_REG_FR_SQS_G04__A                                       0x182002D
-#define B_CE_REG_FR_SQS_G05__A                                       0x182002E
-#define B_CE_REG_FR_SQS_G06__A                                       0x182002F
-#define B_CE_REG_FR_SQS_G07__A                                       0x1820030
-#define B_CE_REG_FR_SQS_G08__A                                       0x1820031
-#define B_CE_REG_FR_SQS_G09__A                                       0x1820032
-#define B_CE_REG_FR_SQS_G10__A                                       0x1820033
-#define B_CE_REG_FR_SQS_G11__A                                       0x1820034
-#define B_CE_REG_FR_SQS_G12__A                                       0x1820035
-#define B_CE_REG_FR_RIO_G00__A                                       0x1820036
-#define B_CE_REG_FR_RIO_G01__A                                       0x1820037
-#define B_CE_REG_FR_RIO_G02__A                                       0x1820038
-#define B_CE_REG_FR_RIO_G03__A                                       0x1820039
-#define B_CE_REG_FR_RIO_G04__A                                       0x182003A
-#define B_CE_REG_FR_RIO_G05__A                                       0x182003B
-#define B_CE_REG_FR_RIO_G06__A                                       0x182003C
-#define B_CE_REG_FR_RIO_G07__A                                       0x182003D
-#define B_CE_REG_FR_RIO_G08__A                                       0x182003E
-#define B_CE_REG_FR_RIO_G09__A                                       0x182003F
-#define B_CE_REG_FR_RIO_G10__A                                       0x1820040
-#define B_CE_REG_FR_MODE__A                                          0x1820041
-#define B_CE_REG_FR_SQS_TRH__A                                       0x1820042
-#define B_CE_REG_FR_RIO_GAIN__A                                      0x1820043
-#define B_CE_REG_FR_BYPASS__A                                        0x1820044
-#define B_CE_REG_FR_PM_SET__A                                        0x1820045
-#define B_CE_REG_FR_ERR_SH__A                                        0x1820046
-#define B_CE_REG_FR_MAN_SH__A                                        0x1820047
-#define B_CE_REG_FR_TAP_SH__A                                        0x1820048
-#define B_EQ_COMM_EXEC__A                                            0x1C00000
-#define B_EQ_REG_COMM_EXEC__A                                        0x1C10000
-#define B_EQ_REG_COMM_MB__A                                          0x1C10002
-#define B_EQ_REG_IS_GAIN_MAN__A                                      0x1C10015
-#define B_EQ_REG_IS_GAIN_EXP__A                                      0x1C10016
-#define B_EQ_REG_IS_CLIP_EXP__A                                      0x1C10017
-#define B_EQ_REG_SN_CEGAIN__A                                        0x1C1002A
-#define B_EQ_REG_SN_OFFSET__A                                        0x1C1002B
-#define B_EQ_REG_RC_SEL_CAR__A                                       0x1C10032
-#define   B_EQ_REG_RC_SEL_CAR_INIT                                   0x2
-#define     B_EQ_REG_RC_SEL_CAR_DIV_ON                               0x1
-#define     B_EQ_REG_RC_SEL_CAR_PASS_A_CC                            0x0
-#define     B_EQ_REG_RC_SEL_CAR_PASS_B_CE                            0x2
-#define     B_EQ_REG_RC_SEL_CAR_LOCAL_A_CC                           0x0
-#define     B_EQ_REG_RC_SEL_CAR_LOCAL_B_CE                           0x8
-#define     B_EQ_REG_RC_SEL_CAR_MEAS_A_CC                            0x0
-#define     B_EQ_REG_RC_SEL_CAR_MEAS_B_CE                            0x20
-#define   B_EQ_REG_RC_SEL_CAR_FFTMODE__M                             0x80
-#define B_EQ_REG_OT_CONST__A                                         0x1C10046
-#define B_EQ_REG_OT_ALPHA__A                                         0x1C10047
-#define B_EQ_REG_OT_QNT_THRES0__A                                    0x1C10048
-#define B_EQ_REG_OT_QNT_THRES1__A                                    0x1C10049
-#define B_EQ_REG_OT_CSI_STEP__A                                      0x1C1004A
-#define B_EQ_REG_OT_CSI_OFFSET__A                                    0x1C1004B
-#define B_EQ_REG_TD_REQ_SMB_CNT__A                                   0x1C10061
-#define B_EQ_REG_TD_TPS_PWR_OFS__A                                   0x1C10062
-#define B_EC_SB_REG_COMM_EXEC__A                                     0x2010000
-#define B_EC_SB_REG_TR_MODE__A                                       0x2010010
-#define   B_EC_SB_REG_TR_MODE_8K                                     0x0
-#define   B_EC_SB_REG_TR_MODE_2K                                     0x1
-#define B_EC_SB_REG_CONST__A                                         0x2010011
-#define   B_EC_SB_REG_CONST_QPSK                                     0x0
-#define   B_EC_SB_REG_CONST_16QAM                                    0x1
-#define   B_EC_SB_REG_CONST_64QAM                                    0x2
-#define B_EC_SB_REG_ALPHA__A                                         0x2010012
-#define B_EC_SB_REG_PRIOR__A                                         0x2010013
-#define   B_EC_SB_REG_PRIOR_HI                                       0x0
-#define   B_EC_SB_REG_PRIOR_LO                                       0x1
-#define B_EC_SB_REG_CSI_HI__A                                        0x2010014
-#define B_EC_SB_REG_CSI_LO__A                                        0x2010015
-#define B_EC_SB_REG_SMB_TGL__A                                       0x2010016
-#define B_EC_SB_REG_SNR_HI__A                                        0x2010017
-#define B_EC_SB_REG_SNR_MID__A                                       0x2010018
-#define B_EC_SB_REG_SNR_LO__A                                        0x2010019
-#define B_EC_SB_REG_SCALE_MSB__A                                     0x201001A
-#define B_EC_SB_REG_SCALE_BIT2__A                                    0x201001B
-#define B_EC_SB_REG_SCALE_LSB__A                                     0x201001C
-#define B_EC_SB_REG_CSI_OFS0__A                                      0x201001D
-#define B_EC_SB_REG_CSI_OFS1__A                                      0x201001E
-#define B_EC_SB_REG_CSI_OFS2__A                                      0x201001F
-#define B_EC_VD_REG_COMM_EXEC__A                                     0x2090000
-#define B_EC_VD_REG_FORCE__A                                         0x2090010
-#define B_EC_VD_REG_SET_CODERATE__A                                  0x2090011
-#define   B_EC_VD_REG_SET_CODERATE_C1_2                              0x0
-#define   B_EC_VD_REG_SET_CODERATE_C2_3                              0x1
-#define   B_EC_VD_REG_SET_CODERATE_C3_4                              0x2
-#define   B_EC_VD_REG_SET_CODERATE_C5_6                              0x3
-#define   B_EC_VD_REG_SET_CODERATE_C7_8                              0x4
-#define B_EC_VD_REG_REQ_SMB_CNT__A                                   0x2090012
-#define B_EC_VD_REG_RLK_ENA__A                                       0x2090014
-#define B_EC_OD_REG_COMM_EXEC__A                                     0x2110000
-#define B_EC_OD_REG_SYNC__A                                          0x2110664
-#define B_EC_OD_DEINT_RAM__A                                         0x2120000
-#define B_EC_RS_REG_COMM_EXEC__A                                     0x2130000
-#define B_EC_RS_REG_REQ_PCK_CNT__A                                   0x2130010
-#define B_EC_RS_REG_VAL__A                                           0x2130011
-#define   B_EC_RS_REG_VAL_PCK                                        0x1
-#define B_EC_RS_EC_RAM__A                                            0x2140000
-#define B_EC_OC_REG_COMM_EXEC__A                                     0x2150000
-#define     B_EC_OC_REG_COMM_EXEC_CTL_ACTIVE                         0x1
-#define     B_EC_OC_REG_COMM_EXEC_CTL_HOLD                           0x2
-#define B_EC_OC_REG_COMM_INT_STA__A                                  0x2150007
-#define B_EC_OC_REG_OC_MODE_LOP__A                                   0x2150010
-#define   B_EC_OC_REG_OC_MODE_LOP_PAR_ENA__M                         0x1
-#define     B_EC_OC_REG_OC_MODE_LOP_PAR_ENA_ENABLE                   0x0
-#define     B_EC_OC_REG_OC_MODE_LOP_PAR_ENA_DISABLE                  0x1
-#define   B_EC_OC_REG_OC_MODE_LOP_DTO_CTR_SRC__M                     0x4
-#define     B_EC_OC_REG_OC_MODE_LOP_DTO_CTR_SRC_STATIC               0x0
-#define   B_EC_OC_REG_OC_MODE_LOP_MPG_TRM_MDE__M                     0x80
-#define     B_EC_OC_REG_OC_MODE_LOP_MPG_TRM_MDE_SERIAL               0x80
-#define B_EC_OC_REG_OC_MODE_HIP__A                                   0x2150011
-#define     B_EC_OC_REG_OC_MODE_HIP_MPG_BUS_SRC_MONITOR              0x10
-#define   B_EC_OC_REG_OC_MODE_HIP_MPG_PAR_VAL__M                     0x200
-#define     B_EC_OC_REG_OC_MODE_HIP_MPG_PAR_VAL_DISABLE              0x0
-#define     B_EC_OC_REG_OC_MODE_HIP_MPG_PAR_VAL_ENABLE               0x200
-#define B_EC_OC_REG_OC_MPG_SIO__A                                    0x2150012
-#define B_EC_OC_REG_OC_MPG_SIO__M                                    0xFFF
-#define B_EC_OC_REG_DTO_INC_LOP__A                                   0x2150014
-#define B_EC_OC_REG_DTO_INC_HIP__A                                   0x2150015
-#define B_EC_OC_REG_SNC_ISC_LVL__A                                   0x2150016
-#define   B_EC_OC_REG_SNC_ISC_LVL_OSC__M                             0xF0
-#define B_EC_OC_REG_TMD_TOP_MODE__A                                  0x215001D
-#define B_EC_OC_REG_TMD_TOP_CNT__A                                   0x215001E
-#define B_EC_OC_REG_TMD_HIL_MAR__A                                   0x215001F
-#define B_EC_OC_REG_TMD_LOL_MAR__A                                   0x2150020
-#define B_EC_OC_REG_TMD_CUR_CNT__A                                   0x2150021
-#define B_EC_OC_REG_AVR_ASH_CNT__A                                   0x2150023
-#define B_EC_OC_REG_AVR_BSH_CNT__A                                   0x2150024
-#define B_EC_OC_REG_RCN_MODE__A                                      0x2150027
-#define B_EC_OC_REG_RCN_CRA_LOP__A                                   0x2150028
-#define B_EC_OC_REG_RCN_CRA_HIP__A                                   0x2150029
-#define B_EC_OC_REG_RCN_CST_LOP__A                                   0x215002A
-#define B_EC_OC_REG_RCN_CST_HIP__A                                   0x215002B
-#define B_EC_OC_REG_RCN_SET_LVL__A                                   0x215002C
-#define B_EC_OC_REG_RCN_GAI_LVL__A                                   0x215002D
-#define B_EC_OC_REG_RCN_CLP_LOP__A                                   0x2150032
-#define B_EC_OC_REG_RCN_CLP_HIP__A                                   0x2150033
-#define B_EC_OC_REG_RCN_MAP_LOP__A                                   0x2150034
-#define B_EC_OC_REG_RCN_MAP_HIP__A                                   0x2150035
-#define B_EC_OC_REG_OCR_MPG_UOS__A                                   0x2150036
-#define B_EC_OC_REG_OCR_MPG_UOS__M                                   0xFFF
-#define   B_EC_OC_REG_OCR_MPG_UOS_INIT                               0x0
-#define B_EC_OC_REG_OCR_MPG_USR_DAT__A                               0x2150038
-#define B_EC_OC_REG_IPR_INV_MPG__A                                   0x2150045
-#define B_EC_OC_REG_DTO_CLKMODE__A                                   0x2150047
-#define B_EC_OC_REG_DTO_PER__A                                       0x2150048
-#define B_EC_OC_REG_DTO_BUR__A                                       0x2150049
-#define B_EC_OC_REG_RCR_CLKMODE__A                                   0x215004A
-#define B_CC_REG_OSC_MODE__A                                         0x2410010
-#define   B_CC_REG_OSC_MODE_M20                                      0x1
-#define B_CC_REG_PLL_MODE__A                                         0x2410011
-#define     B_CC_REG_PLL_MODE_BYPASS_PLL                             0x1
-#define     B_CC_REG_PLL_MODE_PUMP_CUR_12                            0x14
-#define B_CC_REG_REF_DIVIDE__A                                       0x2410012
-#define B_CC_REG_PWD_MODE__A                                         0x2410015
-#define   B_CC_REG_PWD_MODE_DOWN_PLL                                 0x2
-#define B_CC_REG_UPDATE__A                                           0x2410017
-#define   B_CC_REG_UPDATE_KEY                                        0x3973
-#define B_CC_REG_JTAGID_L__A                                         0x2410019
-#define B_CC_REG_DIVERSITY__A                                        0x241001B
-#define B_LC_COMM_EXEC__A                                            0x2800000
-#define B_LC_RA_RAM_IFINCR_NOM_L__A                                  0x282000C
-#define B_LC_RA_RAM_FILTER_SYM_SET__A                                0x282001A
-#define B_LC_RA_RAM_FILTER_SYM_SET__PRE                              0x3E8
-#define B_LC_RA_RAM_FILTER_CRMM_A__A                                 0x2820060
-#define B_LC_RA_RAM_FILTER_CRMM_A__PRE                               0x4
-#define B_LC_RA_RAM_FILTER_CRMM_B__A                                 0x2820061
-#define B_LC_RA_RAM_FILTER_CRMM_B__PRE                               0x1
-#define B_LC_RA_RAM_FILTER_SRMM_A__A                                 0x2820068
-#define B_LC_RA_RAM_FILTER_SRMM_A__PRE                               0x4
-#define B_LC_RA_RAM_FILTER_SRMM_B__A                                 0x2820069
-#define B_LC_RA_RAM_FILTER_SRMM_B__PRE                               0x1
-
-#endif
diff --git a/drivers/media/dvb/frontends/drxk.h b/drivers/media/dvb/frontends/drxk.h
deleted file mode 100644
index d615d7d..0000000
--- a/drivers/media/dvb/frontends/drxk.h
+++ /dev/null
@@ -1,66 +0,0 @@
-#ifndef _DRXK_H_
-#define _DRXK_H_
-
-#include <linux/types.h>
-#include <linux/i2c.h>
-
-/**
- * struct drxk_config - Configure the initial parameters for DRX-K
- *
- * @adr:		I2C Address of the DRX-K
- * @parallel_ts:	True means that the device uses parallel TS,
- * 			Serial otherwise.
- * @dynamic_clk:	True means that the clock will be dynamically
- *			adjusted. Static clock otherwise.
- * @enable_merr_cfg:	Enable SIO_PDR_PERR_CFG/SIO_PDR_MVAL_CFG.
- * @single_master:	Device is on the single master mode
- * @no_i2c_bridge:	Don't switch the I2C bridge to talk with tuner
- * @antenna_gpio:	GPIO bit used to control the antenna
- * @antenna_dvbt:	GPIO bit for changing antenna to DVB-C. A value of 1
- *			means that 1=DVBC, 0 = DVBT. Zero means the opposite.
- * @mpeg_out_clk_strength: DRXK Mpeg output clock drive strength.
- * @microcode_name:	Name of the firmware file with the microcode
- * @qam_demod_parameter_count:	The number of parameters used for the command
- *				to set the demodulator parameters. All
- *				firmwares are using the 2-parameter commmand.
- *				An exception is the "drxk_a3.mc" firmware,
- *				which uses the 4-parameter command.
- *				A value of 0 (default) or lower indicates that
- *				the correct number of parameters will be
- *				automatically detected.
- *
- * On the *_gpio vars, bit 0 is UIO-1, bit 1 is UIO-2 and bit 2 is
- * UIO-3.
- */
-struct drxk_config {
-	u8	adr;
-	bool	single_master;
-	bool	no_i2c_bridge;
-	bool	parallel_ts;
-	bool	dynamic_clk;
-	bool	enable_merr_cfg;
-
-	bool	antenna_dvbt;
-	u16	antenna_gpio;
-
-	u8	mpeg_out_clk_strength;
-	int	chunk_size;
-
-	const char	*microcode_name;
-	int		 qam_demod_parameter_count;
-};
-
-#if defined(CONFIG_DVB_DRXK) || (defined(CONFIG_DVB_DRXK_MODULE) \
-        && defined(MODULE))
-extern struct dvb_frontend *drxk_attach(const struct drxk_config *config,
-					struct i2c_adapter *i2c);
-#else
-static inline struct dvb_frontend *drxk_attach(const struct drxk_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/drxk_hard.c b/drivers/media/dvb/frontends/drxk_hard.c
deleted file mode 100644
index 1ab8154..0000000
--- a/drivers/media/dvb/frontends/drxk_hard.c
+++ /dev/null
@@ -1,6637 +0,0 @@
-/*
- * drxk_hard: DRX-K DVB-C/T demodulator driver
- *
- * Copyright (C) 2010-2011 Digital Devices GmbH
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 only, as published by the Free Software Foundation.
- *
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/firmware.h>
-#include <linux/i2c.h>
-#include <linux/hardirq.h>
-#include <asm/div64.h>
-
-#include "dvb_frontend.h"
-#include "drxk.h"
-#include "drxk_hard.h"
-
-static int PowerDownDVBT(struct drxk_state *state, bool setPowerMode);
-static int PowerDownQAM(struct drxk_state *state);
-static int SetDVBTStandard(struct drxk_state *state,
-			   enum OperationMode oMode);
-static int SetQAMStandard(struct drxk_state *state,
-			  enum OperationMode oMode);
-static int SetQAM(struct drxk_state *state, u16 IntermediateFreqkHz,
-		  s32 tunerFreqOffset);
-static int SetDVBTStandard(struct drxk_state *state,
-			   enum OperationMode oMode);
-static int DVBTStart(struct drxk_state *state);
-static int SetDVBT(struct drxk_state *state, u16 IntermediateFreqkHz,
-		   s32 tunerFreqOffset);
-static int GetQAMLockStatus(struct drxk_state *state, u32 *pLockStatus);
-static int GetDVBTLockStatus(struct drxk_state *state, u32 *pLockStatus);
-static int SwitchAntennaToQAM(struct drxk_state *state);
-static int SwitchAntennaToDVBT(struct drxk_state *state);
-
-static bool IsDVBT(struct drxk_state *state)
-{
-	return state->m_OperationMode == OM_DVBT;
-}
-
-static bool IsQAM(struct drxk_state *state)
-{
-	return state->m_OperationMode == OM_QAM_ITU_A ||
-	    state->m_OperationMode == OM_QAM_ITU_B ||
-	    state->m_OperationMode == OM_QAM_ITU_C;
-}
-
-bool IsA1WithPatchCode(struct drxk_state *state)
-{
-	return state->m_DRXK_A1_PATCH_CODE;
-}
-
-bool IsA1WithRomCode(struct drxk_state *state)
-{
-	return state->m_DRXK_A1_ROM_CODE;
-}
-
-#define NOA1ROM 0
-
-#define DRXDAP_FASI_SHORT_FORMAT(addr) (((addr) & 0xFC30FF80) == 0)
-#define DRXDAP_FASI_LONG_FORMAT(addr)  (((addr) & 0xFC30FF80) != 0)
-
-#define DEFAULT_MER_83  165
-#define DEFAULT_MER_93  250
-
-#ifndef DRXK_MPEG_SERIAL_OUTPUT_PIN_DRIVE_STRENGTH
-#define DRXK_MPEG_SERIAL_OUTPUT_PIN_DRIVE_STRENGTH (0x02)
-#endif
-
-#ifndef DRXK_MPEG_PARALLEL_OUTPUT_PIN_DRIVE_STRENGTH
-#define DRXK_MPEG_PARALLEL_OUTPUT_PIN_DRIVE_STRENGTH (0x03)
-#endif
-
-#define DEFAULT_DRXK_MPEG_LOCK_TIMEOUT 700
-#define DEFAULT_DRXK_DEMOD_LOCK_TIMEOUT 500
-
-#ifndef DRXK_KI_RAGC_ATV
-#define DRXK_KI_RAGC_ATV   4
-#endif
-#ifndef DRXK_KI_IAGC_ATV
-#define DRXK_KI_IAGC_ATV   6
-#endif
-#ifndef DRXK_KI_DAGC_ATV
-#define DRXK_KI_DAGC_ATV   7
-#endif
-
-#ifndef DRXK_KI_RAGC_QAM
-#define DRXK_KI_RAGC_QAM   3
-#endif
-#ifndef DRXK_KI_IAGC_QAM
-#define DRXK_KI_IAGC_QAM   4
-#endif
-#ifndef DRXK_KI_DAGC_QAM
-#define DRXK_KI_DAGC_QAM   7
-#endif
-#ifndef DRXK_KI_RAGC_DVBT
-#define DRXK_KI_RAGC_DVBT  (IsA1WithPatchCode(state) ? 3 : 2)
-#endif
-#ifndef DRXK_KI_IAGC_DVBT
-#define DRXK_KI_IAGC_DVBT  (IsA1WithPatchCode(state) ? 4 : 2)
-#endif
-#ifndef DRXK_KI_DAGC_DVBT
-#define DRXK_KI_DAGC_DVBT  (IsA1WithPatchCode(state) ? 10 : 7)
-#endif
-
-#ifndef DRXK_AGC_DAC_OFFSET
-#define DRXK_AGC_DAC_OFFSET (0x800)
-#endif
-
-#ifndef DRXK_BANDWIDTH_8MHZ_IN_HZ
-#define DRXK_BANDWIDTH_8MHZ_IN_HZ  (0x8B8249L)
-#endif
-
-#ifndef DRXK_BANDWIDTH_7MHZ_IN_HZ
-#define DRXK_BANDWIDTH_7MHZ_IN_HZ  (0x7A1200L)
-#endif
-
-#ifndef DRXK_BANDWIDTH_6MHZ_IN_HZ
-#define DRXK_BANDWIDTH_6MHZ_IN_HZ  (0x68A1B6L)
-#endif
-
-#ifndef DRXK_QAM_SYMBOLRATE_MAX
-#define DRXK_QAM_SYMBOLRATE_MAX         (7233000)
-#endif
-
-#define DRXK_BL_ROM_OFFSET_TAPS_DVBT    56
-#define DRXK_BL_ROM_OFFSET_TAPS_ITU_A   64
-#define DRXK_BL_ROM_OFFSET_TAPS_ITU_C   0x5FE0
-#define DRXK_BL_ROM_OFFSET_TAPS_BG      24
-#define DRXK_BL_ROM_OFFSET_TAPS_DKILLP  32
-#define DRXK_BL_ROM_OFFSET_TAPS_NTSC    40
-#define DRXK_BL_ROM_OFFSET_TAPS_FM      48
-#define DRXK_BL_ROM_OFFSET_UCODE        0
-
-#define DRXK_BLC_TIMEOUT                100
-
-#define DRXK_BLCC_NR_ELEMENTS_TAPS      2
-#define DRXK_BLCC_NR_ELEMENTS_UCODE     6
-
-#define DRXK_BLDC_NR_ELEMENTS_TAPS      28
-
-#ifndef DRXK_OFDM_NE_NOTCH_WIDTH
-#define DRXK_OFDM_NE_NOTCH_WIDTH             (4)
-#endif
-
-#define DRXK_QAM_SL_SIG_POWER_QAM16       (40960)
-#define DRXK_QAM_SL_SIG_POWER_QAM32       (20480)
-#define DRXK_QAM_SL_SIG_POWER_QAM64       (43008)
-#define DRXK_QAM_SL_SIG_POWER_QAM128      (20992)
-#define DRXK_QAM_SL_SIG_POWER_QAM256      (43520)
-
-static unsigned int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "enable debug messages");
-
-#define dprintk(level, fmt, arg...) do {			\
-if (debug >= level)						\
-	printk(KERN_DEBUG "drxk: %s" fmt, __func__, ## arg);	\
-} while (0)
-
-
-static inline u32 MulDiv32(u32 a, u32 b, u32 c)
-{
-	u64 tmp64;
-
-	tmp64 = (u64) a * (u64) b;
-	do_div(tmp64, c);
-
-	return (u32) tmp64;
-}
-
-inline u32 Frac28a(u32 a, u32 c)
-{
-	int i = 0;
-	u32 Q1 = 0;
-	u32 R0 = 0;
-
-	R0 = (a % c) << 4;	/* 32-28 == 4 shifts possible at max */
-	Q1 = a / c;		/* integer part, only the 4 least significant bits
-				   will be visible in the result */
-
-	/* division using radix 16, 7 nibbles in the result */
-	for (i = 0; i < 7; i++) {
-		Q1 = (Q1 << 4) | (R0 / c);
-		R0 = (R0 % c) << 4;
-	}
-	/* rounding */
-	if ((R0 >> 3) >= c)
-		Q1++;
-
-	return Q1;
-}
-
-static u32 Log10Times100(u32 x)
-{
-	static const u8 scale = 15;
-	static const u8 indexWidth = 5;
-	u8 i = 0;
-	u32 y = 0;
-	u32 d = 0;
-	u32 k = 0;
-	u32 r = 0;
-	/*
-	   log2lut[n] = (1<<scale) * 200 * log2(1.0 + ((1.0/(1<<INDEXWIDTH)) * n))
-	   0 <= n < ((1<<INDEXWIDTH)+1)
-	 */
-
-	static const u32 log2lut[] = {
-		0,		/* 0.000000 */
-		290941,		/* 290941.300628 */
-		573196,		/* 573196.476418 */
-		847269,		/* 847269.179851 */
-		1113620,	/* 1113620.489452 */
-		1372674,	/* 1372673.576986 */
-		1624818,	/* 1624817.752104 */
-		1870412,	/* 1870411.981536 */
-		2109788,	/* 2109787.962654 */
-		2343253,	/* 2343252.817465 */
-		2571091,	/* 2571091.461923 */
-		2793569,	/* 2793568.696416 */
-		3010931,	/* 3010931.055901 */
-		3223408,	/* 3223408.452106 */
-		3431216,	/* 3431215.635215 */
-		3634553,	/* 3634553.498355 */
-		3833610,	/* 3833610.244726 */
-		4028562,	/* 4028562.434393 */
-		4219576,	/* 4219575.925308 */
-		4406807,	/* 4406806.721144 */
-		4590402,	/* 4590401.736809 */
-		4770499,	/* 4770499.491025 */
-		4947231,	/* 4947230.734179 */
-		5120719,	/* 5120719.018555 */
-		5291081,	/* 5291081.217197 */
-		5458428,	/* 5458427.996830 */
-		5622864,	/* 5622864.249668 */
-		5784489,	/* 5784489.488298 */
-		5943398,	/* 5943398.207380 */
-		6099680,	/* 6099680.215452 */
-		6253421,	/* 6253420.939751 */
-		6404702,	/* 6404701.706649 */
-		6553600,	/* 6553600.000000 */
-	};
-
-
-	if (x == 0)
-		return 0;
-
-	/* Scale x (normalize) */
-	/* computing y in log(x/y) = log(x) - log(y) */
-	if ((x & ((0xffffffff) << (scale + 1))) == 0) {
-		for (k = scale; k > 0; k--) {
-			if (x & (((u32) 1) << scale))
-				break;
-			x <<= 1;
-		}
-	} else {
-		for (k = scale; k < 31; k++) {
-			if ((x & (((u32) (-1)) << (scale + 1))) == 0)
-				break;
-			x >>= 1;
-		}
-	}
-	/*
-	   Now x has binary point between bit[scale] and bit[scale-1]
-	   and 1.0 <= x < 2.0 */
-
-	/* correction for divison: log(x) = log(x/y)+log(y) */
-	y = k * ((((u32) 1) << scale) * 200);
-
-	/* remove integer part */
-	x &= ((((u32) 1) << scale) - 1);
-	/* get index */
-	i = (u8) (x >> (scale - indexWidth));
-	/* compute delta (x - a) */
-	d = x & ((((u32) 1) << (scale - indexWidth)) - 1);
-	/* compute log, multiplication (d* (..)) must be within range ! */
-	y += log2lut[i] +
-	    ((d * (log2lut[i + 1] - log2lut[i])) >> (scale - indexWidth));
-	/* Conver to log10() */
-	y /= 108853;		/* (log2(10) << scale) */
-	r = (y >> 1);
-	/* rounding */
-	if (y & ((u32) 1))
-		r++;
-	return r;
-}
-
-/****************************************************************************/
-/* I2C **********************************************************************/
-/****************************************************************************/
-
-static int drxk_i2c_lock(struct drxk_state *state)
-{
-	i2c_lock_adapter(state->i2c);
-	state->drxk_i2c_exclusive_lock = true;
-
-	return 0;
-}
-
-static void drxk_i2c_unlock(struct drxk_state *state)
-{
-	if (!state->drxk_i2c_exclusive_lock)
-		return;
-
-	i2c_unlock_adapter(state->i2c);
-	state->drxk_i2c_exclusive_lock = false;
-}
-
-static int drxk_i2c_transfer(struct drxk_state *state, struct i2c_msg *msgs,
-			     unsigned len)
-{
-	if (state->drxk_i2c_exclusive_lock)
-		return __i2c_transfer(state->i2c, msgs, len);
-	else
-		return i2c_transfer(state->i2c, msgs, len);
-}
-
-static int i2c_read1(struct drxk_state *state, u8 adr, u8 *val)
-{
-	struct i2c_msg msgs[1] = { {.addr = adr, .flags = I2C_M_RD,
-				    .buf = val, .len = 1}
-	};
-
-	return drxk_i2c_transfer(state, msgs, 1);
-}
-
-static int i2c_write(struct drxk_state *state, u8 adr, u8 *data, int len)
-{
-	int status;
-	struct i2c_msg msg = {
-	    .addr = adr, .flags = 0, .buf = data, .len = len };
-
-	dprintk(3, ":");
-	if (debug > 2) {
-		int i;
-		for (i = 0; i < len; i++)
-			printk(KERN_CONT " %02x", data[i]);
-		printk(KERN_CONT "\n");
-	}
-	status = drxk_i2c_transfer(state, &msg, 1);
-	if (status >= 0 && status != 1)
-		status = -EIO;
-
-	if (status < 0)
-		printk(KERN_ERR "drxk: i2c write error at addr 0x%02x\n", adr);
-
-	return status;
-}
-
-static int i2c_read(struct drxk_state *state,
-		    u8 adr, u8 *msg, int len, u8 *answ, int alen)
-{
-	int status;
-	struct i2c_msg msgs[2] = {
-		{.addr = adr, .flags = 0,
-				    .buf = msg, .len = len},
-		{.addr = adr, .flags = I2C_M_RD,
-		 .buf = answ, .len = alen}
-	};
-
-	status = drxk_i2c_transfer(state, msgs, 2);
-	if (status != 2) {
-		if (debug > 2)
-			printk(KERN_CONT ": ERROR!\n");
-		if (status >= 0)
-			status = -EIO;
-
-		printk(KERN_ERR "drxk: i2c read error at addr 0x%02x\n", adr);
-		return status;
-	}
-	if (debug > 2) {
-		int i;
-		dprintk(2, ": read from");
-		for (i = 0; i < len; i++)
-			printk(KERN_CONT " %02x", msg[i]);
-		printk(KERN_CONT ", value = ");
-		for (i = 0; i < alen; i++)
-			printk(KERN_CONT " %02x", answ[i]);
-		printk(KERN_CONT "\n");
-	}
-	return 0;
-}
-
-static int read16_flags(struct drxk_state *state, u32 reg, u16 *data, u8 flags)
-{
-	int status;
-	u8 adr = state->demod_address, mm1[4], mm2[2], len;
-
-	if (state->single_master)
-		flags |= 0xC0;
-
-	if (DRXDAP_FASI_LONG_FORMAT(reg) || (flags != 0)) {
-		mm1[0] = (((reg << 1) & 0xFF) | 0x01);
-		mm1[1] = ((reg >> 16) & 0xFF);
-		mm1[2] = ((reg >> 24) & 0xFF) | flags;
-		mm1[3] = ((reg >> 7) & 0xFF);
-		len = 4;
-	} else {
-		mm1[0] = ((reg << 1) & 0xFF);
-		mm1[1] = (((reg >> 16) & 0x0F) | ((reg >> 18) & 0xF0));
-		len = 2;
-	}
-	dprintk(2, "(0x%08x, 0x%02x)\n", reg, flags);
-	status = i2c_read(state, adr, mm1, len, mm2, 2);
-	if (status < 0)
-		return status;
-	if (data)
-		*data = mm2[0] | (mm2[1] << 8);
-
-	return 0;
-}
-
-static int read16(struct drxk_state *state, u32 reg, u16 *data)
-{
-	return read16_flags(state, reg, data, 0);
-}
-
-static int read32_flags(struct drxk_state *state, u32 reg, u32 *data, u8 flags)
-{
-	int status;
-	u8 adr = state->demod_address, mm1[4], mm2[4], len;
-
-	if (state->single_master)
-		flags |= 0xC0;
-
-	if (DRXDAP_FASI_LONG_FORMAT(reg) || (flags != 0)) {
-		mm1[0] = (((reg << 1) & 0xFF) | 0x01);
-		mm1[1] = ((reg >> 16) & 0xFF);
-		mm1[2] = ((reg >> 24) & 0xFF) | flags;
-		mm1[3] = ((reg >> 7) & 0xFF);
-		len = 4;
-	} else {
-		mm1[0] = ((reg << 1) & 0xFF);
-		mm1[1] = (((reg >> 16) & 0x0F) | ((reg >> 18) & 0xF0));
-		len = 2;
-	}
-	dprintk(2, "(0x%08x, 0x%02x)\n", reg, flags);
-	status = i2c_read(state, adr, mm1, len, mm2, 4);
-	if (status < 0)
-		return status;
-	if (data)
-		*data = mm2[0] | (mm2[1] << 8) |
-		    (mm2[2] << 16) | (mm2[3] << 24);
-
-	return 0;
-}
-
-static int read32(struct drxk_state *state, u32 reg, u32 *data)
-{
-	return read32_flags(state, reg, data, 0);
-}
-
-static int write16_flags(struct drxk_state *state, u32 reg, u16 data, u8 flags)
-{
-	u8 adr = state->demod_address, mm[6], len;
-
-	if (state->single_master)
-		flags |= 0xC0;
-	if (DRXDAP_FASI_LONG_FORMAT(reg) || (flags != 0)) {
-		mm[0] = (((reg << 1) & 0xFF) | 0x01);
-		mm[1] = ((reg >> 16) & 0xFF);
-		mm[2] = ((reg >> 24) & 0xFF) | flags;
-		mm[3] = ((reg >> 7) & 0xFF);
-		len = 4;
-	} else {
-		mm[0] = ((reg << 1) & 0xFF);
-		mm[1] = (((reg >> 16) & 0x0F) | ((reg >> 18) & 0xF0));
-		len = 2;
-	}
-	mm[len] = data & 0xff;
-	mm[len + 1] = (data >> 8) & 0xff;
-
-	dprintk(2, "(0x%08x, 0x%04x, 0x%02x)\n", reg, data, flags);
-	return i2c_write(state, adr, mm, len + 2);
-}
-
-static int write16(struct drxk_state *state, u32 reg, u16 data)
-{
-	return write16_flags(state, reg, data, 0);
-}
-
-static int write32_flags(struct drxk_state *state, u32 reg, u32 data, u8 flags)
-{
-	u8 adr = state->demod_address, mm[8], len;
-
-	if (state->single_master)
-		flags |= 0xC0;
-	if (DRXDAP_FASI_LONG_FORMAT(reg) || (flags != 0)) {
-		mm[0] = (((reg << 1) & 0xFF) | 0x01);
-		mm[1] = ((reg >> 16) & 0xFF);
-		mm[2] = ((reg >> 24) & 0xFF) | flags;
-		mm[3] = ((reg >> 7) & 0xFF);
-		len = 4;
-	} else {
-		mm[0] = ((reg << 1) & 0xFF);
-		mm[1] = (((reg >> 16) & 0x0F) | ((reg >> 18) & 0xF0));
-		len = 2;
-	}
-	mm[len] = data & 0xff;
-	mm[len + 1] = (data >> 8) & 0xff;
-	mm[len + 2] = (data >> 16) & 0xff;
-	mm[len + 3] = (data >> 24) & 0xff;
-	dprintk(2, "(0x%08x, 0x%08x, 0x%02x)\n", reg, data, flags);
-
-	return i2c_write(state, adr, mm, len + 4);
-}
-
-static int write32(struct drxk_state *state, u32 reg, u32 data)
-{
-	return write32_flags(state, reg, data, 0);
-}
-
-static int write_block(struct drxk_state *state, u32 Address,
-		      const int BlockSize, const u8 pBlock[])
-{
-	int status = 0, BlkSize = BlockSize;
-	u8 Flags = 0;
-
-	if (state->single_master)
-		Flags |= 0xC0;
-
-	while (BlkSize > 0) {
-		int Chunk = BlkSize > state->m_ChunkSize ?
-		    state->m_ChunkSize : BlkSize;
-		u8 *AdrBuf = &state->Chunk[0];
-		u32 AdrLength = 0;
-
-		if (DRXDAP_FASI_LONG_FORMAT(Address) || (Flags != 0)) {
-			AdrBuf[0] = (((Address << 1) & 0xFF) | 0x01);
-			AdrBuf[1] = ((Address >> 16) & 0xFF);
-			AdrBuf[2] = ((Address >> 24) & 0xFF);
-			AdrBuf[3] = ((Address >> 7) & 0xFF);
-			AdrBuf[2] |= Flags;
-			AdrLength = 4;
-			if (Chunk == state->m_ChunkSize)
-				Chunk -= 2;
-		} else {
-			AdrBuf[0] = ((Address << 1) & 0xFF);
-			AdrBuf[1] = (((Address >> 16) & 0x0F) |
-				     ((Address >> 18) & 0xF0));
-			AdrLength = 2;
-		}
-		memcpy(&state->Chunk[AdrLength], pBlock, Chunk);
-		dprintk(2, "(0x%08x, 0x%02x)\n", Address, Flags);
-		if (debug > 1) {
-			int i;
-			if (pBlock)
-				for (i = 0; i < Chunk; i++)
-					printk(KERN_CONT " %02x", pBlock[i]);
-			printk(KERN_CONT "\n");
-		}
-		status = i2c_write(state, state->demod_address,
-				   &state->Chunk[0], Chunk + AdrLength);
-		if (status < 0) {
-			printk(KERN_ERR "drxk: %s: i2c write error at addr 0x%02x\n",
-			       __func__, Address);
-			break;
-		}
-		pBlock += Chunk;
-		Address += (Chunk >> 1);
-		BlkSize -= Chunk;
-	}
-	return status;
-}
-
-#ifndef DRXK_MAX_RETRIES_POWERUP
-#define DRXK_MAX_RETRIES_POWERUP 20
-#endif
-
-int PowerUpDevice(struct drxk_state *state)
-{
-	int status;
-	u8 data = 0;
-	u16 retryCount = 0;
-
-	dprintk(1, "\n");
-
-	status = i2c_read1(state, state->demod_address, &data);
-	if (status < 0) {
-		do {
-			data = 0;
-			status = i2c_write(state, state->demod_address,
-					   &data, 1);
-			msleep(10);
-			retryCount++;
-			if (status < 0)
-				continue;
-			status = i2c_read1(state, state->demod_address,
-					   &data);
-		} while (status < 0 &&
-			 (retryCount < DRXK_MAX_RETRIES_POWERUP));
-		if (status < 0 && retryCount >= DRXK_MAX_RETRIES_POWERUP)
-			goto error;
-	}
-
-	/* Make sure all clk domains are active */
-	status = write16(state, SIO_CC_PWD_MODE__A, SIO_CC_PWD_MODE_LEVEL_NONE);
-	if (status < 0)
-		goto error;
-	status = write16(state, SIO_CC_UPDATE__A, SIO_CC_UPDATE_KEY);
-	if (status < 0)
-		goto error;
-	/* Enable pll lock tests */
-	status = write16(state, SIO_CC_PLL_LOCK__A, 1);
-	if (status < 0)
-		goto error;
-
-	state->m_currentPowerMode = DRX_POWER_UP;
-
-error:
-	if (status < 0)
-		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
-
-	return status;
-}
-
-
-static int init_state(struct drxk_state *state)
-{
-	/*
-	 * FIXME: most (all?) of the values bellow should be moved into
-	 * struct drxk_config, as they are probably board-specific
-	 */
-	u32 ulVSBIfAgcMode = DRXK_AGC_CTRL_AUTO;
-	u32 ulVSBIfAgcOutputLevel = 0;
-	u32 ulVSBIfAgcMinLevel = 0;
-	u32 ulVSBIfAgcMaxLevel = 0x7FFF;
-	u32 ulVSBIfAgcSpeed = 3;
-
-	u32 ulVSBRfAgcMode = DRXK_AGC_CTRL_AUTO;
-	u32 ulVSBRfAgcOutputLevel = 0;
-	u32 ulVSBRfAgcMinLevel = 0;
-	u32 ulVSBRfAgcMaxLevel = 0x7FFF;
-	u32 ulVSBRfAgcSpeed = 3;
-	u32 ulVSBRfAgcTop = 9500;
-	u32 ulVSBRfAgcCutOffCurrent = 4000;
-
-	u32 ulATVIfAgcMode = DRXK_AGC_CTRL_AUTO;
-	u32 ulATVIfAgcOutputLevel = 0;
-	u32 ulATVIfAgcMinLevel = 0;
-	u32 ulATVIfAgcMaxLevel = 0;
-	u32 ulATVIfAgcSpeed = 3;
-
-	u32 ulATVRfAgcMode = DRXK_AGC_CTRL_OFF;
-	u32 ulATVRfAgcOutputLevel = 0;
-	u32 ulATVRfAgcMinLevel = 0;
-	u32 ulATVRfAgcMaxLevel = 0;
-	u32 ulATVRfAgcTop = 9500;
-	u32 ulATVRfAgcCutOffCurrent = 4000;
-	u32 ulATVRfAgcSpeed = 3;
-
-	u32 ulQual83 = DEFAULT_MER_83;
-	u32 ulQual93 = DEFAULT_MER_93;
-
-	u32 ulMpegLockTimeOut = DEFAULT_DRXK_MPEG_LOCK_TIMEOUT;
-	u32 ulDemodLockTimeOut = DEFAULT_DRXK_DEMOD_LOCK_TIMEOUT;
-
-	/* io_pad_cfg register (8 bit reg.) MSB bit is 1 (default value) */
-	/* io_pad_cfg_mode output mode is drive always */
-	/* io_pad_cfg_drive is set to power 2 (23 mA) */
-	u32 ulGPIOCfg = 0x0113;
-	u32 ulInvertTSClock = 0;
-	u32 ulTSDataStrength = DRXK_MPEG_SERIAL_OUTPUT_PIN_DRIVE_STRENGTH;
-	u32 ulDVBTBitrate = 50000000;
-	u32 ulDVBCBitrate = DRXK_QAM_SYMBOLRATE_MAX * 8;
-
-	u32 ulInsertRSByte = 0;
-
-	u32 ulRfMirror = 1;
-	u32 ulPowerDown = 0;
-
-	dprintk(1, "\n");
-
-	state->m_hasLNA = false;
-	state->m_hasDVBT = false;
-	state->m_hasDVBC = false;
-	state->m_hasATV = false;
-	state->m_hasOOB = false;
-	state->m_hasAudio = false;
-
-	if (!state->m_ChunkSize)
-		state->m_ChunkSize = 124;
-
-	state->m_oscClockFreq = 0;
-	state->m_smartAntInverted = false;
-	state->m_bPDownOpenBridge = false;
-
-	/* real system clock frequency in kHz */
-	state->m_sysClockFreq = 151875;
-	/* Timing div, 250ns/Psys */
-	/* Timing div, = (delay (nano seconds) * sysclk (kHz))/ 1000 */
-	state->m_HICfgTimingDiv = ((state->m_sysClockFreq / 1000) *
-				   HI_I2C_DELAY) / 1000;
-	/* Clipping */
-	if (state->m_HICfgTimingDiv > SIO_HI_RA_RAM_PAR_2_CFG_DIV__M)
-		state->m_HICfgTimingDiv = SIO_HI_RA_RAM_PAR_2_CFG_DIV__M;
-	state->m_HICfgWakeUpKey = (state->demod_address << 1);
-	/* port/bridge/power down ctrl */
-	state->m_HICfgCtrl = SIO_HI_RA_RAM_PAR_5_CFG_SLV0_SLAVE;
-
-	state->m_bPowerDown = (ulPowerDown != 0);
-
-	state->m_DRXK_A1_PATCH_CODE = false;
-	state->m_DRXK_A1_ROM_CODE = false;
-	state->m_DRXK_A2_ROM_CODE = false;
-	state->m_DRXK_A3_ROM_CODE = false;
-	state->m_DRXK_A2_PATCH_CODE = false;
-	state->m_DRXK_A3_PATCH_CODE = false;
-
-	/* Init AGC and PGA parameters */
-	/* VSB IF */
-	state->m_vsbIfAgcCfg.ctrlMode = (ulVSBIfAgcMode);
-	state->m_vsbIfAgcCfg.outputLevel = (ulVSBIfAgcOutputLevel);
-	state->m_vsbIfAgcCfg.minOutputLevel = (ulVSBIfAgcMinLevel);
-	state->m_vsbIfAgcCfg.maxOutputLevel = (ulVSBIfAgcMaxLevel);
-	state->m_vsbIfAgcCfg.speed = (ulVSBIfAgcSpeed);
-	state->m_vsbPgaCfg = 140;
-
-	/* VSB RF */
-	state->m_vsbRfAgcCfg.ctrlMode = (ulVSBRfAgcMode);
-	state->m_vsbRfAgcCfg.outputLevel = (ulVSBRfAgcOutputLevel);
-	state->m_vsbRfAgcCfg.minOutputLevel = (ulVSBRfAgcMinLevel);
-	state->m_vsbRfAgcCfg.maxOutputLevel = (ulVSBRfAgcMaxLevel);
-	state->m_vsbRfAgcCfg.speed = (ulVSBRfAgcSpeed);
-	state->m_vsbRfAgcCfg.top = (ulVSBRfAgcTop);
-	state->m_vsbRfAgcCfg.cutOffCurrent = (ulVSBRfAgcCutOffCurrent);
-	state->m_vsbPreSawCfg.reference = 0x07;
-	state->m_vsbPreSawCfg.usePreSaw = true;
-
-	state->m_Quality83percent = DEFAULT_MER_83;
-	state->m_Quality93percent = DEFAULT_MER_93;
-	if (ulQual93 <= 500 && ulQual83 < ulQual93) {
-		state->m_Quality83percent = ulQual83;
-		state->m_Quality93percent = ulQual93;
-	}
-
-	/* ATV IF */
-	state->m_atvIfAgcCfg.ctrlMode = (ulATVIfAgcMode);
-	state->m_atvIfAgcCfg.outputLevel = (ulATVIfAgcOutputLevel);
-	state->m_atvIfAgcCfg.minOutputLevel = (ulATVIfAgcMinLevel);
-	state->m_atvIfAgcCfg.maxOutputLevel = (ulATVIfAgcMaxLevel);
-	state->m_atvIfAgcCfg.speed = (ulATVIfAgcSpeed);
-
-	/* ATV RF */
-	state->m_atvRfAgcCfg.ctrlMode = (ulATVRfAgcMode);
-	state->m_atvRfAgcCfg.outputLevel = (ulATVRfAgcOutputLevel);
-	state->m_atvRfAgcCfg.minOutputLevel = (ulATVRfAgcMinLevel);
-	state->m_atvRfAgcCfg.maxOutputLevel = (ulATVRfAgcMaxLevel);
-	state->m_atvRfAgcCfg.speed = (ulATVRfAgcSpeed);
-	state->m_atvRfAgcCfg.top = (ulATVRfAgcTop);
-	state->m_atvRfAgcCfg.cutOffCurrent = (ulATVRfAgcCutOffCurrent);
-	state->m_atvPreSawCfg.reference = 0x04;
-	state->m_atvPreSawCfg.usePreSaw = true;
-
-
-	/* DVBT RF */
-	state->m_dvbtRfAgcCfg.ctrlMode = DRXK_AGC_CTRL_OFF;
-	state->m_dvbtRfAgcCfg.outputLevel = 0;
-	state->m_dvbtRfAgcCfg.minOutputLevel = 0;
-	state->m_dvbtRfAgcCfg.maxOutputLevel = 0xFFFF;
-	state->m_dvbtRfAgcCfg.top = 0x2100;
-	state->m_dvbtRfAgcCfg.cutOffCurrent = 4000;
-	state->m_dvbtRfAgcCfg.speed = 1;
-
-
-	/* DVBT IF */
-	state->m_dvbtIfAgcCfg.ctrlMode = DRXK_AGC_CTRL_AUTO;
-	state->m_dvbtIfAgcCfg.outputLevel = 0;
-	state->m_dvbtIfAgcCfg.minOutputLevel = 0;
-	state->m_dvbtIfAgcCfg.maxOutputLevel = 9000;
-	state->m_dvbtIfAgcCfg.top = 13424;
-	state->m_dvbtIfAgcCfg.cutOffCurrent = 0;
-	state->m_dvbtIfAgcCfg.speed = 3;
-	state->m_dvbtIfAgcCfg.FastClipCtrlDelay = 30;
-	state->m_dvbtIfAgcCfg.IngainTgtMax = 30000;
-	/* state->m_dvbtPgaCfg = 140; */
-
-	state->m_dvbtPreSawCfg.reference = 4;
-	state->m_dvbtPreSawCfg.usePreSaw = false;
-
-	/* QAM RF */
-	state->m_qamRfAgcCfg.ctrlMode = DRXK_AGC_CTRL_OFF;
-	state->m_qamRfAgcCfg.outputLevel = 0;
-	state->m_qamRfAgcCfg.minOutputLevel = 6023;
-	state->m_qamRfAgcCfg.maxOutputLevel = 27000;
-	state->m_qamRfAgcCfg.top = 0x2380;
-	state->m_qamRfAgcCfg.cutOffCurrent = 4000;
-	state->m_qamRfAgcCfg.speed = 3;
-
-	/* QAM IF */
-	state->m_qamIfAgcCfg.ctrlMode = DRXK_AGC_CTRL_AUTO;
-	state->m_qamIfAgcCfg.outputLevel = 0;
-	state->m_qamIfAgcCfg.minOutputLevel = 0;
-	state->m_qamIfAgcCfg.maxOutputLevel = 9000;
-	state->m_qamIfAgcCfg.top = 0x0511;
-	state->m_qamIfAgcCfg.cutOffCurrent = 0;
-	state->m_qamIfAgcCfg.speed = 3;
-	state->m_qamIfAgcCfg.IngainTgtMax = 5119;
-	state->m_qamIfAgcCfg.FastClipCtrlDelay = 50;
-
-	state->m_qamPgaCfg = 140;
-	state->m_qamPreSawCfg.reference = 4;
-	state->m_qamPreSawCfg.usePreSaw = false;
-
-	state->m_OperationMode = OM_NONE;
-	state->m_DrxkState = DRXK_UNINITIALIZED;
-
-	/* MPEG output configuration */
-	state->m_enableMPEGOutput = true;	/* If TRUE; enable MPEG ouput */
-	state->m_insertRSByte = false;	/* If TRUE; insert RS byte */
-	state->m_invertDATA = false;	/* If TRUE; invert DATA signals */
-	state->m_invertERR = false;	/* If TRUE; invert ERR signal */
-	state->m_invertSTR = false;	/* If TRUE; invert STR signals */
-	state->m_invertVAL = false;	/* If TRUE; invert VAL signals */
-	state->m_invertCLK = (ulInvertTSClock != 0);	/* If TRUE; invert CLK signals */
-
-	/* If TRUE; static MPEG clockrate will be used;
-	   otherwise clockrate will adapt to the bitrate of the TS */
-
-	state->m_DVBTBitrate = ulDVBTBitrate;
-	state->m_DVBCBitrate = ulDVBCBitrate;
-
-	state->m_TSDataStrength = (ulTSDataStrength & 0x07);
-
-	/* Maximum bitrate in b/s in case static clockrate is selected */
-	state->m_mpegTsStaticBitrate = 19392658;
-	state->m_disableTEIhandling = false;
-
-	if (ulInsertRSByte)
-		state->m_insertRSByte = true;
-
-	state->m_MpegLockTimeOut = DEFAULT_DRXK_MPEG_LOCK_TIMEOUT;
-	if (ulMpegLockTimeOut < 10000)
-		state->m_MpegLockTimeOut = ulMpegLockTimeOut;
-	state->m_DemodLockTimeOut = DEFAULT_DRXK_DEMOD_LOCK_TIMEOUT;
-	if (ulDemodLockTimeOut < 10000)
-		state->m_DemodLockTimeOut = ulDemodLockTimeOut;
-
-	/* QAM defaults */
-	state->m_Constellation = DRX_CONSTELLATION_AUTO;
-	state->m_qamInterleaveMode = DRXK_QAM_I12_J17;
-	state->m_fecRsPlen = 204 * 8;	/* fecRsPlen  annex A */
-	state->m_fecRsPrescale = 1;
-
-	state->m_sqiSpeed = DRXK_DVBT_SQI_SPEED_MEDIUM;
-	state->m_agcFastClipCtrlDelay = 0;
-
-	state->m_GPIOCfg = (ulGPIOCfg);
-
-	state->m_bPowerDown = false;
-	state->m_currentPowerMode = DRX_POWER_DOWN;
-
-	state->m_rfmirror = (ulRfMirror == 0);
-	state->m_IfAgcPol = false;
-	return 0;
-}
-
-static int DRXX_Open(struct drxk_state *state)
-{
-	int status = 0;
-	u32 jtag = 0;
-	u16 bid = 0;
-	u16 key = 0;
-
-	dprintk(1, "\n");
-	/* stop lock indicator process */
-	status = write16(state, SCU_RAM_GPIO__A, SCU_RAM_GPIO_HW_LOCK_IND_DISABLE);
-	if (status < 0)
-		goto error;
-	/* Check device id */
-	status = read16(state, SIO_TOP_COMM_KEY__A, &key);
-	if (status < 0)
-		goto error;
-	status = write16(state, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY);
-	if (status < 0)
-		goto error;
-	status = read32(state, SIO_TOP_JTAGID_LO__A, &jtag);
-	if (status < 0)
-		goto error;
-	status = read16(state, SIO_PDR_UIO_IN_HI__A, &bid);
-	if (status < 0)
-		goto error;
-	status = write16(state, SIO_TOP_COMM_KEY__A, key);
-error:
-	if (status < 0)
-		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
-	return status;
-}
-
-static int GetDeviceCapabilities(struct drxk_state *state)
-{
-	u16 sioPdrOhwCfg = 0;
-	u32 sioTopJtagidLo = 0;
-	int status;
-	const char *spin = "";
-
-	dprintk(1, "\n");
-
-	/* driver 0.9.0 */
-	/* stop lock indicator process */
-	status = write16(state, SCU_RAM_GPIO__A, SCU_RAM_GPIO_HW_LOCK_IND_DISABLE);
-	if (status < 0)
-		goto error;
-	status = write16(state, SIO_TOP_COMM_KEY__A, 0xFABA);
-	if (status < 0)
-		goto error;
-	status = read16(state, SIO_PDR_OHW_CFG__A, &sioPdrOhwCfg);
-	if (status < 0)
-		goto error;
-	status = write16(state, SIO_TOP_COMM_KEY__A, 0x0000);
-	if (status < 0)
-		goto error;
-
-	switch ((sioPdrOhwCfg & SIO_PDR_OHW_CFG_FREF_SEL__M)) {
-	case 0:
-		/* ignore (bypass ?) */
-		break;
-	case 1:
-		/* 27 MHz */
-		state->m_oscClockFreq = 27000;
-		break;
-	case 2:
-		/* 20.25 MHz */
-		state->m_oscClockFreq = 20250;
-		break;
-	case 3:
-		/* 4 MHz */
-		state->m_oscClockFreq = 20250;
-		break;
-	default:
-		printk(KERN_ERR "drxk: Clock Frequency is unkonwn\n");
-		return -EINVAL;
-	}
-	/*
-		Determine device capabilities
-		Based on pinning v14
-		*/
-	status = read32(state, SIO_TOP_JTAGID_LO__A, &sioTopJtagidLo);
-	if (status < 0)
-		goto error;
-
-	printk(KERN_INFO "drxk: status = 0x%08x\n", sioTopJtagidLo);
-
-	/* driver 0.9.0 */
-	switch ((sioTopJtagidLo >> 29) & 0xF) {
-	case 0:
-		state->m_deviceSpin = DRXK_SPIN_A1;
-		spin = "A1";
-		break;
-	case 2:
-		state->m_deviceSpin = DRXK_SPIN_A2;
-		spin = "A2";
-		break;
-	case 3:
-		state->m_deviceSpin = DRXK_SPIN_A3;
-		spin = "A3";
-		break;
-	default:
-		state->m_deviceSpin = DRXK_SPIN_UNKNOWN;
-		status = -EINVAL;
-		printk(KERN_ERR "drxk: Spin %d unknown\n",
-		       (sioTopJtagidLo >> 29) & 0xF);
-		goto error2;
-	}
-	switch ((sioTopJtagidLo >> 12) & 0xFF) {
-	case 0x13:
-		/* typeId = DRX3913K_TYPE_ID */
-		state->m_hasLNA = false;
-		state->m_hasOOB = false;
-		state->m_hasATV = false;
-		state->m_hasAudio = false;
-		state->m_hasDVBT = true;
-		state->m_hasDVBC = true;
-		state->m_hasSAWSW = true;
-		state->m_hasGPIO2 = false;
-		state->m_hasGPIO1 = false;
-		state->m_hasIRQN = false;
-		break;
-	case 0x15:
-		/* typeId = DRX3915K_TYPE_ID */
-		state->m_hasLNA = false;
-		state->m_hasOOB = false;
-		state->m_hasATV = true;
-		state->m_hasAudio = false;
-		state->m_hasDVBT = true;
-		state->m_hasDVBC = false;
-		state->m_hasSAWSW = true;
-		state->m_hasGPIO2 = true;
-		state->m_hasGPIO1 = true;
-		state->m_hasIRQN = false;
-		break;
-	case 0x16:
-		/* typeId = DRX3916K_TYPE_ID */
-		state->m_hasLNA = false;
-		state->m_hasOOB = false;
-		state->m_hasATV = true;
-		state->m_hasAudio = false;
-		state->m_hasDVBT = true;
-		state->m_hasDVBC = false;
-		state->m_hasSAWSW = true;
-		state->m_hasGPIO2 = true;
-		state->m_hasGPIO1 = true;
-		state->m_hasIRQN = false;
-		break;
-	case 0x18:
-		/* typeId = DRX3918K_TYPE_ID */
-		state->m_hasLNA = false;
-		state->m_hasOOB = false;
-		state->m_hasATV = true;
-		state->m_hasAudio = true;
-		state->m_hasDVBT = true;
-		state->m_hasDVBC = false;
-		state->m_hasSAWSW = true;
-		state->m_hasGPIO2 = true;
-		state->m_hasGPIO1 = true;
-		state->m_hasIRQN = false;
-		break;
-	case 0x21:
-		/* typeId = DRX3921K_TYPE_ID */
-		state->m_hasLNA = false;
-		state->m_hasOOB = false;
-		state->m_hasATV = true;
-		state->m_hasAudio = true;
-		state->m_hasDVBT = true;
-		state->m_hasDVBC = true;
-		state->m_hasSAWSW = true;
-		state->m_hasGPIO2 = true;
-		state->m_hasGPIO1 = true;
-		state->m_hasIRQN = false;
-		break;
-	case 0x23:
-		/* typeId = DRX3923K_TYPE_ID */
-		state->m_hasLNA = false;
-		state->m_hasOOB = false;
-		state->m_hasATV = true;
-		state->m_hasAudio = true;
-		state->m_hasDVBT = true;
-		state->m_hasDVBC = true;
-		state->m_hasSAWSW = true;
-		state->m_hasGPIO2 = true;
-		state->m_hasGPIO1 = true;
-		state->m_hasIRQN = false;
-		break;
-	case 0x25:
-		/* typeId = DRX3925K_TYPE_ID */
-		state->m_hasLNA = false;
-		state->m_hasOOB = false;
-		state->m_hasATV = true;
-		state->m_hasAudio = true;
-		state->m_hasDVBT = true;
-		state->m_hasDVBC = true;
-		state->m_hasSAWSW = true;
-		state->m_hasGPIO2 = true;
-		state->m_hasGPIO1 = true;
-		state->m_hasIRQN = false;
-		break;
-	case 0x26:
-		/* typeId = DRX3926K_TYPE_ID */
-		state->m_hasLNA = false;
-		state->m_hasOOB = false;
-		state->m_hasATV = true;
-		state->m_hasAudio = false;
-		state->m_hasDVBT = true;
-		state->m_hasDVBC = true;
-		state->m_hasSAWSW = true;
-		state->m_hasGPIO2 = true;
-		state->m_hasGPIO1 = true;
-		state->m_hasIRQN = false;
-		break;
-	default:
-		printk(KERN_ERR "drxk: DeviceID 0x%02x not supported\n",
-			((sioTopJtagidLo >> 12) & 0xFF));
-		status = -EINVAL;
-		goto error2;
-	}
-
-	printk(KERN_INFO
-	       "drxk: detected a drx-39%02xk, spin %s, xtal %d.%03d MHz\n",
-	       ((sioTopJtagidLo >> 12) & 0xFF), spin,
-	       state->m_oscClockFreq / 1000,
-	       state->m_oscClockFreq % 1000);
-
-error:
-	if (status < 0)
-		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
-
-error2:
-	return status;
-}
-
-static int HI_Command(struct drxk_state *state, u16 cmd, u16 *pResult)
-{
-	int status;
-	bool powerdown_cmd;
-
-	dprintk(1, "\n");
-
-	/* Write command */
-	status = write16(state, SIO_HI_RA_RAM_CMD__A, cmd);
-	if (status < 0)
-		goto error;
-	if (cmd == SIO_HI_RA_RAM_CMD_RESET)
-		msleep(1);
-
-	powerdown_cmd =
-	    (bool) ((cmd == SIO_HI_RA_RAM_CMD_CONFIG) &&
-		    ((state->m_HICfgCtrl) &
-		     SIO_HI_RA_RAM_PAR_5_CFG_SLEEP__M) ==
-		    SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ);
-	if (powerdown_cmd == false) {
-		/* Wait until command rdy */
-		u32 retryCount = 0;
-		u16 waitCmd;
-
-		do {
-			msleep(1);
-			retryCount += 1;
-			status = read16(state, SIO_HI_RA_RAM_CMD__A,
-					  &waitCmd);
-		} while ((status < 0) && (retryCount < DRXK_MAX_RETRIES)
-			 && (waitCmd != 0));
-		if (status < 0)
-			goto error;
-		status = read16(state, SIO_HI_RA_RAM_RES__A, pResult);
-	}
-error:
-	if (status < 0)
-		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
-
-	return status;
-}
-
-static int HI_CfgCommand(struct drxk_state *state)
-{
-	int status;
-
-	dprintk(1, "\n");
-
-	mutex_lock(&state->mutex);
-
-	status = write16(state, SIO_HI_RA_RAM_PAR_6__A, state->m_HICfgTimeout);
-	if (status < 0)
-		goto error;
-	status = write16(state, SIO_HI_RA_RAM_PAR_5__A, state->m_HICfgCtrl);
-	if (status < 0)
-		goto error;
-	status = write16(state, SIO_HI_RA_RAM_PAR_4__A, state->m_HICfgWakeUpKey);
-	if (status < 0)
-		goto error;
-	status = write16(state, SIO_HI_RA_RAM_PAR_3__A, state->m_HICfgBridgeDelay);
-	if (status < 0)
-		goto error;
-	status = write16(state, SIO_HI_RA_RAM_PAR_2__A, state->m_HICfgTimingDiv);
-	if (status < 0)
-		goto error;
-	status = write16(state, SIO_HI_RA_RAM_PAR_1__A, SIO_HI_RA_RAM_PAR_1_PAR1_SEC_KEY);
-	if (status < 0)
-		goto error;
-	status = HI_Command(state, SIO_HI_RA_RAM_CMD_CONFIG, 0);
-	if (status < 0)
-		goto error;
-
-	state->m_HICfgCtrl &= ~SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ;
-error:
-	mutex_unlock(&state->mutex);
-	if (status < 0)
-		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
-	return status;
-}
-
-static int InitHI(struct drxk_state *state)
-{
-	dprintk(1, "\n");
-
-	state->m_HICfgWakeUpKey = (state->demod_address << 1);
-	state->m_HICfgTimeout = 0x96FF;
-	/* port/bridge/power down ctrl */
-	state->m_HICfgCtrl = SIO_HI_RA_RAM_PAR_5_CFG_SLV0_SLAVE;
-
-	return HI_CfgCommand(state);
-}
-
-static int MPEGTSConfigurePins(struct drxk_state *state, bool mpegEnable)
-{
-	int status = -1;
-	u16 sioPdrMclkCfg = 0;
-	u16 sioPdrMdxCfg = 0;
-	u16 err_cfg = 0;
-
-	dprintk(1, ": mpeg %s, %s mode\n",
-		mpegEnable ? "enable" : "disable",
-		state->m_enableParallel ? "parallel" : "serial");
-
-	/* stop lock indicator process */
-	status = write16(state, SCU_RAM_GPIO__A, SCU_RAM_GPIO_HW_LOCK_IND_DISABLE);
-	if (status < 0)
-		goto error;
-
-	/*  MPEG TS pad configuration */
-	status = write16(state, SIO_TOP_COMM_KEY__A, 0xFABA);
-	if (status < 0)
-		goto error;
-
-	if (mpegEnable == false) {
-		/*  Set MPEG TS pads to inputmode */
-		status = write16(state, SIO_PDR_MSTRT_CFG__A, 0x0000);
-		if (status < 0)
-			goto error;
-		status = write16(state, SIO_PDR_MERR_CFG__A, 0x0000);
-		if (status < 0)
-			goto error;
-		status = write16(state, SIO_PDR_MCLK_CFG__A, 0x0000);
-		if (status < 0)
-			goto error;
-		status = write16(state, SIO_PDR_MVAL_CFG__A, 0x0000);
-		if (status < 0)
-			goto error;
-		status = write16(state, SIO_PDR_MD0_CFG__A, 0x0000);
-		if (status < 0)
-			goto error;
-		status = write16(state, SIO_PDR_MD1_CFG__A, 0x0000);
-		if (status < 0)
-			goto error;
-		status = write16(state, SIO_PDR_MD2_CFG__A, 0x0000);
-		if (status < 0)
-			goto error;
-		status = write16(state, SIO_PDR_MD3_CFG__A, 0x0000);
-		if (status < 0)
-			goto error;
-		status = write16(state, SIO_PDR_MD4_CFG__A, 0x0000);
-		if (status < 0)
-			goto error;
-		status = write16(state, SIO_PDR_MD5_CFG__A, 0x0000);
-		if (status < 0)
-			goto error;
-		status = write16(state, SIO_PDR_MD6_CFG__A, 0x0000);
-		if (status < 0)
-			goto error;
-		status = write16(state, SIO_PDR_MD7_CFG__A, 0x0000);
-		if (status < 0)
-			goto error;
-	} else {
-		/* Enable MPEG output */
-		sioPdrMdxCfg =
-			((state->m_TSDataStrength <<
-			SIO_PDR_MD0_CFG_DRIVE__B) | 0x0003);
-		sioPdrMclkCfg = ((state->m_TSClockkStrength <<
-					SIO_PDR_MCLK_CFG_DRIVE__B) |
-					0x0003);
-
-		status = write16(state, SIO_PDR_MSTRT_CFG__A, sioPdrMdxCfg);
-		if (status < 0)
-			goto error;
-
-		if (state->enable_merr_cfg)
-			err_cfg = sioPdrMdxCfg;
-
-		status = write16(state, SIO_PDR_MERR_CFG__A, err_cfg);
-		if (status < 0)
-			goto error;
-		status = write16(state, SIO_PDR_MVAL_CFG__A, err_cfg);
-		if (status < 0)
-			goto error;
-
-		if (state->m_enableParallel == true) {
-			/* paralel -> enable MD1 to MD7 */
-			status = write16(state, SIO_PDR_MD1_CFG__A, sioPdrMdxCfg);
-			if (status < 0)
-				goto error;
-			status = write16(state, SIO_PDR_MD2_CFG__A, sioPdrMdxCfg);
-			if (status < 0)
-				goto error;
-			status = write16(state, SIO_PDR_MD3_CFG__A, sioPdrMdxCfg);
-			if (status < 0)
-				goto error;
-			status = write16(state, SIO_PDR_MD4_CFG__A, sioPdrMdxCfg);
-			if (status < 0)
-				goto error;
-			status = write16(state, SIO_PDR_MD5_CFG__A, sioPdrMdxCfg);
-			if (status < 0)
-				goto error;
-			status = write16(state, SIO_PDR_MD6_CFG__A, sioPdrMdxCfg);
-			if (status < 0)
-				goto error;
-			status = write16(state, SIO_PDR_MD7_CFG__A, sioPdrMdxCfg);
-			if (status < 0)
-				goto error;
-		} else {
-			sioPdrMdxCfg = ((state->m_TSDataStrength <<
-						SIO_PDR_MD0_CFG_DRIVE__B)
-					| 0x0003);
-			/* serial -> disable MD1 to MD7 */
-			status = write16(state, SIO_PDR_MD1_CFG__A, 0x0000);
-			if (status < 0)
-				goto error;
-			status = write16(state, SIO_PDR_MD2_CFG__A, 0x0000);
-			if (status < 0)
-				goto error;
-			status = write16(state, SIO_PDR_MD3_CFG__A, 0x0000);
-			if (status < 0)
-				goto error;
-			status = write16(state, SIO_PDR_MD4_CFG__A, 0x0000);
-			if (status < 0)
-				goto error;
-			status = write16(state, SIO_PDR_MD5_CFG__A, 0x0000);
-			if (status < 0)
-				goto error;
-			status = write16(state, SIO_PDR_MD6_CFG__A, 0x0000);
-			if (status < 0)
-				goto error;
-			status = write16(state, SIO_PDR_MD7_CFG__A, 0x0000);
-			if (status < 0)
-				goto error;
-		}
-		status = write16(state, SIO_PDR_MCLK_CFG__A, sioPdrMclkCfg);
-		if (status < 0)
-			goto error;
-		status = write16(state, SIO_PDR_MD0_CFG__A, sioPdrMdxCfg);
-		if (status < 0)
-			goto error;
-	}
-	/*  Enable MB output over MPEG pads and ctl input */
-	status = write16(state, SIO_PDR_MON_CFG__A, 0x0000);
-	if (status < 0)
-		goto error;
-	/*  Write nomagic word to enable pdr reg write */
-	status = write16(state, SIO_TOP_COMM_KEY__A, 0x0000);
-error:
-	if (status < 0)
-		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
-	return status;
-}
-
-static int MPEGTSDisable(struct drxk_state *state)
-{
-	dprintk(1, "\n");
-
-	return MPEGTSConfigurePins(state, false);
-}
-
-static int BLChainCmd(struct drxk_state *state,
-		      u16 romOffset, u16 nrOfElements, u32 timeOut)
-{
-	u16 blStatus = 0;
-	int status;
-	unsigned long end;
-
-	dprintk(1, "\n");
-	mutex_lock(&state->mutex);
-	status = write16(state, SIO_BL_MODE__A, SIO_BL_MODE_CHAIN);
-	if (status < 0)
-		goto error;
-	status = write16(state, SIO_BL_CHAIN_ADDR__A, romOffset);
-	if (status < 0)
-		goto error;
-	status = write16(state, SIO_BL_CHAIN_LEN__A, nrOfElements);
-	if (status < 0)
-		goto error;
-	status = write16(state, SIO_BL_ENABLE__A, SIO_BL_ENABLE_ON);
-	if (status < 0)
-		goto error;
-
-	end = jiffies + msecs_to_jiffies(timeOut);
-	do {
-		msleep(1);
-		status = read16(state, SIO_BL_STATUS__A, &blStatus);
-		if (status < 0)
-			goto error;
-	} while ((blStatus == 0x1) &&
-			((time_is_after_jiffies(end))));
-
-	if (blStatus == 0x1) {
-		printk(KERN_ERR "drxk: SIO not ready\n");
-		status = -EINVAL;
-		goto error2;
-	}
-error:
-	if (status < 0)
-		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
-error2:
-	mutex_unlock(&state->mutex);
-	return status;
-}
-
-
-static int DownloadMicrocode(struct drxk_state *state,
-			     const u8 pMCImage[], u32 Length)
-{
-	const u8 *pSrc = pMCImage;
-	u32 Address;
-	u16 nBlocks;
-	u16 BlockSize;
-	u32 offset = 0;
-	u32 i;
-	int status = 0;
-
-	dprintk(1, "\n");
-
-	/* down the drain (we don't care about MAGIC_WORD) */
-#if 0
-	/* For future reference */
-	Drain = (pSrc[0] << 8) | pSrc[1];
-#endif
-	pSrc += sizeof(u16);
-	offset += sizeof(u16);
-	nBlocks = (pSrc[0] << 8) | pSrc[1];
-	pSrc += sizeof(u16);
-	offset += sizeof(u16);
-
-	for (i = 0; i < nBlocks; i += 1) {
-		Address = (pSrc[0] << 24) | (pSrc[1] << 16) |
-		    (pSrc[2] << 8) | pSrc[3];
-		pSrc += sizeof(u32);
-		offset += sizeof(u32);
-
-		BlockSize = ((pSrc[0] << 8) | pSrc[1]) * sizeof(u16);
-		pSrc += sizeof(u16);
-		offset += sizeof(u16);
-
-#if 0
-		/* For future reference */
-		Flags = (pSrc[0] << 8) | pSrc[1];
-#endif
-		pSrc += sizeof(u16);
-		offset += sizeof(u16);
-
-#if 0
-		/* For future reference */
-		BlockCRC = (pSrc[0] << 8) | pSrc[1];
-#endif
-		pSrc += sizeof(u16);
-		offset += sizeof(u16);
-
-		if (offset + BlockSize > Length) {
-			printk(KERN_ERR "drxk: Firmware is corrupted.\n");
-			return -EINVAL;
-		}
-
-		status = write_block(state, Address, BlockSize, pSrc);
-		if (status < 0) {
-			printk(KERN_ERR "drxk: Error %d while loading firmware\n", status);
-			break;
-		}
-		pSrc += BlockSize;
-		offset += BlockSize;
-	}
-	return status;
-}
-
-static int DVBTEnableOFDMTokenRing(struct drxk_state *state, bool enable)
-{
-	int status;
-	u16 data = 0;
-	u16 desiredCtrl = SIO_OFDM_SH_OFDM_RING_ENABLE_ON;
-	u16 desiredStatus = SIO_OFDM_SH_OFDM_RING_STATUS_ENABLED;
-	unsigned long end;
-
-	dprintk(1, "\n");
-
-	if (enable == false) {
-		desiredCtrl = SIO_OFDM_SH_OFDM_RING_ENABLE_OFF;
-		desiredStatus = SIO_OFDM_SH_OFDM_RING_STATUS_DOWN;
-	}
-
-	status = read16(state, SIO_OFDM_SH_OFDM_RING_STATUS__A, &data);
-	if (status >= 0 && data == desiredStatus) {
-		/* tokenring already has correct status */
-		return status;
-	}
-	/* Disable/enable dvbt tokenring bridge   */
-	status = write16(state, SIO_OFDM_SH_OFDM_RING_ENABLE__A, desiredCtrl);
-
-	end = jiffies + msecs_to_jiffies(DRXK_OFDM_TR_SHUTDOWN_TIMEOUT);
-	do {
-		status = read16(state, SIO_OFDM_SH_OFDM_RING_STATUS__A, &data);
-		if ((status >= 0 && data == desiredStatus) || time_is_after_jiffies(end))
-			break;
-		msleep(1);
-	} while (1);
-	if (data != desiredStatus) {
-		printk(KERN_ERR "drxk: SIO not ready\n");
-		return -EINVAL;
-	}
-	return status;
-}
-
-static int MPEGTSStop(struct drxk_state *state)
-{
-	int status = 0;
-	u16 fecOcSncMode = 0;
-	u16 fecOcIprMode = 0;
-
-	dprintk(1, "\n");
-
-	/* Gracefull shutdown (byte boundaries) */
-	status = read16(state, FEC_OC_SNC_MODE__A, &fecOcSncMode);
-	if (status < 0)
-		goto error;
-	fecOcSncMode |= FEC_OC_SNC_MODE_SHUTDOWN__M;
-	status = write16(state, FEC_OC_SNC_MODE__A, fecOcSncMode);
-	if (status < 0)
-		goto error;
-
-	/* Suppress MCLK during absence of data */
-	status = read16(state, FEC_OC_IPR_MODE__A, &fecOcIprMode);
-	if (status < 0)
-		goto error;
-	fecOcIprMode |= FEC_OC_IPR_MODE_MCLK_DIS_DAT_ABS__M;
-	status = write16(state, FEC_OC_IPR_MODE__A, fecOcIprMode);
-
-error:
-	if (status < 0)
-		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
-
-	return status;
-}
-
-static int scu_command(struct drxk_state *state,
-		       u16 cmd, u8 parameterLen,
-		       u16 *parameter, u8 resultLen, u16 *result)
-{
-#if (SCU_RAM_PARAM_0__A - SCU_RAM_PARAM_15__A) != 15
-#error DRXK register mapping no longer compatible with this routine!
-#endif
-	u16 curCmd = 0;
-	int status = -EINVAL;
-	unsigned long end;
-	u8 buffer[34];
-	int cnt = 0, ii;
-	const char *p;
-	char errname[30];
-
-	dprintk(1, "\n");
-
-	if ((cmd == 0) || ((parameterLen > 0) && (parameter == NULL)) ||
-	    ((resultLen > 0) && (result == NULL))) {
-		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
-		return status;
-	}
-
-	mutex_lock(&state->mutex);
-
-	/* assume that the command register is ready
-		since it is checked afterwards */
-	for (ii = parameterLen - 1; ii >= 0; ii -= 1) {
-		buffer[cnt++] = (parameter[ii] & 0xFF);
-		buffer[cnt++] = ((parameter[ii] >> 8) & 0xFF);
-	}
-	buffer[cnt++] = (cmd & 0xFF);
-	buffer[cnt++] = ((cmd >> 8) & 0xFF);
-
-	write_block(state, SCU_RAM_PARAM_0__A -
-			(parameterLen - 1), cnt, buffer);
-	/* Wait until SCU has processed command */
-	end = jiffies + msecs_to_jiffies(DRXK_MAX_WAITTIME);
-	do {
-		msleep(1);
-		status = read16(state, SCU_RAM_COMMAND__A, &curCmd);
-		if (status < 0)
-			goto error;
-	} while (!(curCmd == DRX_SCU_READY) && (time_is_after_jiffies(end)));
-	if (curCmd != DRX_SCU_READY) {
-		printk(KERN_ERR "drxk: SCU not ready\n");
-		status = -EIO;
-		goto error2;
-	}
-	/* read results */
-	if ((resultLen > 0) && (result != NULL)) {
-		s16 err;
-		int ii;
-
-		for (ii = resultLen - 1; ii >= 0; ii -= 1) {
-			status = read16(state, SCU_RAM_PARAM_0__A - ii, &result[ii]);
-			if (status < 0)
-				goto error;
-		}
-
-		/* Check if an error was reported by SCU */
-		err = (s16)result[0];
-		if (err >= 0)
-			goto error;
-
-		/* check for the known error codes */
-		switch (err) {
-		case SCU_RESULT_UNKCMD:
-			p = "SCU_RESULT_UNKCMD";
-			break;
-		case SCU_RESULT_UNKSTD:
-			p = "SCU_RESULT_UNKSTD";
-			break;
-		case SCU_RESULT_SIZE:
-			p = "SCU_RESULT_SIZE";
-			break;
-		case SCU_RESULT_INVPAR:
-			p = "SCU_RESULT_INVPAR";
-			break;
-		default: /* Other negative values are errors */
-			sprintf(errname, "ERROR: %d\n", err);
-			p = errname;
-		}
-		printk(KERN_ERR "drxk: %s while sending cmd 0x%04x with params:", p, cmd);
-		print_hex_dump_bytes("drxk: ", DUMP_PREFIX_NONE, buffer, cnt);
-		status = -EINVAL;
-		goto error2;
-	}
-
-error:
-	if (status < 0)
-		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
-error2:
-	mutex_unlock(&state->mutex);
-	return status;
-}
-
-static int SetIqmAf(struct drxk_state *state, bool active)
-{
-	u16 data = 0;
-	int status;
-
-	dprintk(1, "\n");
-
-	/* Configure IQM */
-	status = read16(state, IQM_AF_STDBY__A, &data);
-	if (status < 0)
-		goto error;
-
-	if (!active) {
-		data |= (IQM_AF_STDBY_STDBY_ADC_STANDBY
-				| IQM_AF_STDBY_STDBY_AMP_STANDBY
-				| IQM_AF_STDBY_STDBY_PD_STANDBY
-				| IQM_AF_STDBY_STDBY_TAGC_IF_STANDBY
-				| IQM_AF_STDBY_STDBY_TAGC_RF_STANDBY);
-	} else {
-		data &= ((~IQM_AF_STDBY_STDBY_ADC_STANDBY)
-				& (~IQM_AF_STDBY_STDBY_AMP_STANDBY)
-				& (~IQM_AF_STDBY_STDBY_PD_STANDBY)
-				& (~IQM_AF_STDBY_STDBY_TAGC_IF_STANDBY)
-				& (~IQM_AF_STDBY_STDBY_TAGC_RF_STANDBY)
-			);
-	}
-	status = write16(state, IQM_AF_STDBY__A, data);
-
-error:
-	if (status < 0)
-		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
-	return status;
-}
-
-static int CtrlPowerMode(struct drxk_state *state, enum DRXPowerMode *mode)
-{
-	int status = 0;
-	u16 sioCcPwdMode = 0;
-
-	dprintk(1, "\n");
-
-	/* Check arguments */
-	if (mode == NULL)
-		return -EINVAL;
-
-	switch (*mode) {
-	case DRX_POWER_UP:
-		sioCcPwdMode = SIO_CC_PWD_MODE_LEVEL_NONE;
-		break;
-	case DRXK_POWER_DOWN_OFDM:
-		sioCcPwdMode = SIO_CC_PWD_MODE_LEVEL_OFDM;
-		break;
-	case DRXK_POWER_DOWN_CORE:
-		sioCcPwdMode = SIO_CC_PWD_MODE_LEVEL_CLOCK;
-		break;
-	case DRXK_POWER_DOWN_PLL:
-		sioCcPwdMode = SIO_CC_PWD_MODE_LEVEL_PLL;
-		break;
-	case DRX_POWER_DOWN:
-		sioCcPwdMode = SIO_CC_PWD_MODE_LEVEL_OSC;
-		break;
-	default:
-		/* Unknow sleep mode */
-		return -EINVAL;
-	}
-
-	/* If already in requested power mode, do nothing */
-	if (state->m_currentPowerMode == *mode)
-		return 0;
-
-	/* For next steps make sure to start from DRX_POWER_UP mode */
-	if (state->m_currentPowerMode != DRX_POWER_UP) {
-		status = PowerUpDevice(state);
-		if (status < 0)
-			goto error;
-		status = DVBTEnableOFDMTokenRing(state, true);
-		if (status < 0)
-			goto error;
-	}
-
-	if (*mode == DRX_POWER_UP) {
-		/* Restore analog & pin configuartion */
-	} else {
-		/* Power down to requested mode */
-		/* Backup some register settings */
-		/* Set pins with possible pull-ups connected
-		   to them in input mode */
-		/* Analog power down */
-		/* ADC power down */
-		/* Power down device */
-		/* stop all comm_exec */
-		/* Stop and power down previous standard */
-		switch (state->m_OperationMode) {
-		case OM_DVBT:
-			status = MPEGTSStop(state);
-			if (status < 0)
-				goto error;
-			status = PowerDownDVBT(state, false);
-			if (status < 0)
-				goto error;
-			break;
-		case OM_QAM_ITU_A:
-		case OM_QAM_ITU_C:
-			status = MPEGTSStop(state);
-			if (status < 0)
-				goto error;
-			status = PowerDownQAM(state);
-			if (status < 0)
-				goto error;
-			break;
-		default:
-			break;
-		}
-		status = DVBTEnableOFDMTokenRing(state, false);
-		if (status < 0)
-			goto error;
-		status = write16(state, SIO_CC_PWD_MODE__A, sioCcPwdMode);
-		if (status < 0)
-			goto error;
-		status = write16(state, SIO_CC_UPDATE__A, SIO_CC_UPDATE_KEY);
-		if (status < 0)
-			goto error;
-
-		if (*mode != DRXK_POWER_DOWN_OFDM) {
-			state->m_HICfgCtrl |=
-				SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ;
-			status = HI_CfgCommand(state);
-			if (status < 0)
-				goto error;
-		}
-	}
-	state->m_currentPowerMode = *mode;
-
-error:
-	if (status < 0)
-		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
-
-	return status;
-}
-
-static int PowerDownDVBT(struct drxk_state *state, bool setPowerMode)
-{
-	enum DRXPowerMode powerMode = DRXK_POWER_DOWN_OFDM;
-	u16 cmdResult = 0;
-	u16 data = 0;
-	int status;
-
-	dprintk(1, "\n");
-
-	status = read16(state, SCU_COMM_EXEC__A, &data);
-	if (status < 0)
-		goto error;
-	if (data == SCU_COMM_EXEC_ACTIVE) {
-		/* Send OFDM stop command */
-		status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM | SCU_RAM_COMMAND_CMD_DEMOD_STOP, 0, NULL, 1, &cmdResult);
-		if (status < 0)
-			goto error;
-		/* Send OFDM reset command */
-		status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM | SCU_RAM_COMMAND_CMD_DEMOD_RESET, 0, NULL, 1, &cmdResult);
-		if (status < 0)
-			goto error;
-	}
-
-	/* Reset datapath for OFDM, processors first */
-	status = write16(state, OFDM_SC_COMM_EXEC__A, OFDM_SC_COMM_EXEC_STOP);
-	if (status < 0)
-		goto error;
-	status = write16(state, OFDM_LC_COMM_EXEC__A, OFDM_LC_COMM_EXEC_STOP);
-	if (status < 0)
-		goto error;
-	status = write16(state, IQM_COMM_EXEC__A, IQM_COMM_EXEC_B_STOP);
-	if (status < 0)
-		goto error;
-
-	/* powerdown AFE                   */
-	status = SetIqmAf(state, false);
-	if (status < 0)
-		goto error;
-
-	/* powerdown to OFDM mode          */
-	if (setPowerMode) {
-		status = CtrlPowerMode(state, &powerMode);
-		if (status < 0)
-			goto error;
-	}
-error:
-	if (status < 0)
-		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
-	return status;
-}
-
-static int SetOperationMode(struct drxk_state *state,
-			    enum OperationMode oMode)
-{
-	int status = 0;
-
-	dprintk(1, "\n");
-	/*
-	   Stop and power down previous standard
-	   TODO investigate total power down instead of partial
-	   power down depending on "previous" standard.
-	 */
-
-	/* disable HW lock indicator */
-	status = write16(state, SCU_RAM_GPIO__A, SCU_RAM_GPIO_HW_LOCK_IND_DISABLE);
-	if (status < 0)
-		goto error;
-
-	/* Device is already at the required mode */
-	if (state->m_OperationMode == oMode)
-		return 0;
-
-	switch (state->m_OperationMode) {
-		/* OM_NONE was added for start up */
-	case OM_NONE:
-		break;
-	case OM_DVBT:
-		status = MPEGTSStop(state);
-		if (status < 0)
-			goto error;
-		status = PowerDownDVBT(state, true);
-		if (status < 0)
-			goto error;
-		state->m_OperationMode = OM_NONE;
-		break;
-	case OM_QAM_ITU_A:	/* fallthrough */
-	case OM_QAM_ITU_C:
-		status = MPEGTSStop(state);
-		if (status < 0)
-			goto error;
-		status = PowerDownQAM(state);
-		if (status < 0)
-			goto error;
-		state->m_OperationMode = OM_NONE;
-		break;
-	case OM_QAM_ITU_B:
-	default:
-		status = -EINVAL;
-		goto error;
-	}
-
-	/*
-		Power up new standard
-		*/
-	switch (oMode) {
-	case OM_DVBT:
-		dprintk(1, ": DVB-T\n");
-		state->m_OperationMode = oMode;
-		status = SetDVBTStandard(state, oMode);
-		if (status < 0)
-			goto error;
-		break;
-	case OM_QAM_ITU_A:	/* fallthrough */
-	case OM_QAM_ITU_C:
-		dprintk(1, ": DVB-C Annex %c\n",
-			(state->m_OperationMode == OM_QAM_ITU_A) ? 'A' : 'C');
-		state->m_OperationMode = oMode;
-		status = SetQAMStandard(state, oMode);
-		if (status < 0)
-			goto error;
-		break;
-	case OM_QAM_ITU_B:
-	default:
-		status = -EINVAL;
-	}
-error:
-	if (status < 0)
-		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
-	return status;
-}
-
-static int Start(struct drxk_state *state, s32 offsetFreq,
-		 s32 IntermediateFrequency)
-{
-	int status = -EINVAL;
-
-	u16 IFreqkHz;
-	s32 OffsetkHz = offsetFreq / 1000;
-
-	dprintk(1, "\n");
-	if (state->m_DrxkState != DRXK_STOPPED &&
-		state->m_DrxkState != DRXK_DTV_STARTED)
-		goto error;
-
-	state->m_bMirrorFreqSpect = (state->props.inversion == INVERSION_ON);
-
-	if (IntermediateFrequency < 0) {
-		state->m_bMirrorFreqSpect = !state->m_bMirrorFreqSpect;
-		IntermediateFrequency = -IntermediateFrequency;
-	}
-
-	switch (state->m_OperationMode) {
-	case OM_QAM_ITU_A:
-	case OM_QAM_ITU_C:
-		IFreqkHz = (IntermediateFrequency / 1000);
-		status = SetQAM(state, IFreqkHz, OffsetkHz);
-		if (status < 0)
-			goto error;
-		state->m_DrxkState = DRXK_DTV_STARTED;
-		break;
-	case OM_DVBT:
-		IFreqkHz = (IntermediateFrequency / 1000);
-		status = MPEGTSStop(state);
-		if (status < 0)
-			goto error;
-		status = SetDVBT(state, IFreqkHz, OffsetkHz);
-		if (status < 0)
-			goto error;
-		status = DVBTStart(state);
-		if (status < 0)
-			goto error;
-		state->m_DrxkState = DRXK_DTV_STARTED;
-		break;
-	default:
-		break;
-	}
-error:
-	if (status < 0)
-		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
-	return status;
-}
-
-static int ShutDown(struct drxk_state *state)
-{
-	dprintk(1, "\n");
-
-	MPEGTSStop(state);
-	return 0;
-}
-
-static int GetLockStatus(struct drxk_state *state, u32 *pLockStatus,
-			 u32 Time)
-{
-	int status = -EINVAL;
-
-	dprintk(1, "\n");
-
-	if (pLockStatus == NULL)
-		goto error;
-
-	*pLockStatus = NOT_LOCKED;
-
-	/* define the SCU command code */
-	switch (state->m_OperationMode) {
-	case OM_QAM_ITU_A:
-	case OM_QAM_ITU_B:
-	case OM_QAM_ITU_C:
-		status = GetQAMLockStatus(state, pLockStatus);
-		break;
-	case OM_DVBT:
-		status = GetDVBTLockStatus(state, pLockStatus);
-		break;
-	default:
-		break;
-	}
-error:
-	if (status < 0)
-		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
-	return status;
-}
-
-static int MPEGTSStart(struct drxk_state *state)
-{
-	int status;
-
-	u16 fecOcSncMode = 0;
-
-	/* Allow OC to sync again */
-	status = read16(state, FEC_OC_SNC_MODE__A, &fecOcSncMode);
-	if (status < 0)
-		goto error;
-	fecOcSncMode &= ~FEC_OC_SNC_MODE_SHUTDOWN__M;
-	status = write16(state, FEC_OC_SNC_MODE__A, fecOcSncMode);
-	if (status < 0)
-		goto error;
-	status = write16(state, FEC_OC_SNC_UNLOCK__A, 1);
-error:
-	if (status < 0)
-		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
-	return status;
-}
-
-static int MPEGTSDtoInit(struct drxk_state *state)
-{
-	int status;
-
-	dprintk(1, "\n");
-
-	/* Rate integration settings */
-	status = write16(state, FEC_OC_RCN_CTL_STEP_LO__A, 0x0000);
-	if (status < 0)
-		goto error;
-	status = write16(state, FEC_OC_RCN_CTL_STEP_HI__A, 0x000C);
-	if (status < 0)
-		goto error;
-	status = write16(state, FEC_OC_RCN_GAIN__A, 0x000A);
-	if (status < 0)
-		goto error;
-	status = write16(state, FEC_OC_AVR_PARM_A__A, 0x0008);
-	if (status < 0)
-		goto error;
-	status = write16(state, FEC_OC_AVR_PARM_B__A, 0x0006);
-	if (status < 0)
-		goto error;
-	status = write16(state, FEC_OC_TMD_HI_MARGIN__A, 0x0680);
-	if (status < 0)
-		goto error;
-	status = write16(state, FEC_OC_TMD_LO_MARGIN__A, 0x0080);
-	if (status < 0)
-		goto error;
-	status = write16(state, FEC_OC_TMD_COUNT__A, 0x03F4);
-	if (status < 0)
-		goto error;
-
-	/* Additional configuration */
-	status = write16(state, FEC_OC_OCR_INVERT__A, 0);
-	if (status < 0)
-		goto error;
-	status = write16(state, FEC_OC_SNC_LWM__A, 2);
-	if (status < 0)
-		goto error;
-	status = write16(state, FEC_OC_SNC_HWM__A, 12);
-error:
-	if (status < 0)
-		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
-
-	return status;
-}
-
-static int MPEGTSDtoSetup(struct drxk_state *state,
-			  enum OperationMode oMode)
-{
-	int status;
-
-	u16 fecOcRegMode = 0;	/* FEC_OC_MODE       register value */
-	u16 fecOcRegIprMode = 0;	/* FEC_OC_IPR_MODE   register value */
-	u16 fecOcDtoMode = 0;	/* FEC_OC_IPR_INVERT register value */
-	u16 fecOcFctMode = 0;	/* FEC_OC_IPR_INVERT register value */
-	u16 fecOcDtoPeriod = 2;	/* FEC_OC_IPR_INVERT register value */
-	u16 fecOcDtoBurstLen = 188;	/* FEC_OC_IPR_INVERT register value */
-	u32 fecOcRcnCtlRate = 0;	/* FEC_OC_IPR_INVERT register value */
-	u16 fecOcTmdMode = 0;
-	u16 fecOcTmdIntUpdRate = 0;
-	u32 maxBitRate = 0;
-	bool staticCLK = false;
-
-	dprintk(1, "\n");
-
-	/* Check insertion of the Reed-Solomon parity bytes */
-	status = read16(state, FEC_OC_MODE__A, &fecOcRegMode);
-	if (status < 0)
-		goto error;
-	status = read16(state, FEC_OC_IPR_MODE__A, &fecOcRegIprMode);
-	if (status < 0)
-		goto error;
-	fecOcRegMode &= (~FEC_OC_MODE_PARITY__M);
-	fecOcRegIprMode &= (~FEC_OC_IPR_MODE_MVAL_DIS_PAR__M);
-	if (state->m_insertRSByte == true) {
-		/* enable parity symbol forward */
-		fecOcRegMode |= FEC_OC_MODE_PARITY__M;
-		/* MVAL disable during parity bytes */
-		fecOcRegIprMode |= FEC_OC_IPR_MODE_MVAL_DIS_PAR__M;
-		/* TS burst length to 204 */
-		fecOcDtoBurstLen = 204;
-	}
-
-	/* Check serial or parrallel output */
-	fecOcRegIprMode &= (~(FEC_OC_IPR_MODE_SERIAL__M));
-	if (state->m_enableParallel == false) {
-		/* MPEG data output is serial -> set ipr_mode[0] */
-		fecOcRegIprMode |= FEC_OC_IPR_MODE_SERIAL__M;
-	}
-
-	switch (oMode) {
-	case OM_DVBT:
-		maxBitRate = state->m_DVBTBitrate;
-		fecOcTmdMode = 3;
-		fecOcRcnCtlRate = 0xC00000;
-		staticCLK = state->m_DVBTStaticCLK;
-		break;
-	case OM_QAM_ITU_A:	/* fallthrough */
-	case OM_QAM_ITU_C:
-		fecOcTmdMode = 0x0004;
-		fecOcRcnCtlRate = 0xD2B4EE;	/* good for >63 Mb/s */
-		maxBitRate = state->m_DVBCBitrate;
-		staticCLK = state->m_DVBCStaticCLK;
-		break;
-	default:
-		status = -EINVAL;
-	}		/* switch (standard) */
-	if (status < 0)
-		goto error;
-
-	/* Configure DTO's */
-	if (staticCLK) {
-		u32 bitRate = 0;
-
-		/* Rational DTO for MCLK source (static MCLK rate),
-			Dynamic DTO for optimal grouping
-			(avoid intra-packet gaps),
-			DTO offset enable to sync TS burst with MSTRT */
-		fecOcDtoMode = (FEC_OC_DTO_MODE_DYNAMIC__M |
-				FEC_OC_DTO_MODE_OFFSET_ENABLE__M);
-		fecOcFctMode = (FEC_OC_FCT_MODE_RAT_ENA__M |
-				FEC_OC_FCT_MODE_VIRT_ENA__M);
-
-		/* Check user defined bitrate */
-		bitRate = maxBitRate;
-		if (bitRate > 75900000UL) {	/* max is 75.9 Mb/s */
-			bitRate = 75900000UL;
-		}
-		/* Rational DTO period:
-			dto_period = (Fsys / bitrate) - 2
-
-			Result should be floored,
-			to make sure >= requested bitrate
-			*/
-		fecOcDtoPeriod = (u16) (((state->m_sysClockFreq)
-						* 1000) / bitRate);
-		if (fecOcDtoPeriod <= 2)
-			fecOcDtoPeriod = 0;
-		else
-			fecOcDtoPeriod -= 2;
-		fecOcTmdIntUpdRate = 8;
-	} else {
-		/* (commonAttr->staticCLK == false) => dynamic mode */
-		fecOcDtoMode = FEC_OC_DTO_MODE_DYNAMIC__M;
-		fecOcFctMode = FEC_OC_FCT_MODE__PRE;
-		fecOcTmdIntUpdRate = 5;
-	}
-
-	/* Write appropriate registers with requested configuration */
-	status = write16(state, FEC_OC_DTO_BURST_LEN__A, fecOcDtoBurstLen);
-	if (status < 0)
-		goto error;
-	status = write16(state, FEC_OC_DTO_PERIOD__A, fecOcDtoPeriod);
-	if (status < 0)
-		goto error;
-	status = write16(state, FEC_OC_DTO_MODE__A, fecOcDtoMode);
-	if (status < 0)
-		goto error;
-	status = write16(state, FEC_OC_FCT_MODE__A, fecOcFctMode);
-	if (status < 0)
-		goto error;
-	status = write16(state, FEC_OC_MODE__A, fecOcRegMode);
-	if (status < 0)
-		goto error;
-	status = write16(state, FEC_OC_IPR_MODE__A, fecOcRegIprMode);
-	if (status < 0)
-		goto error;
-
-	/* Rate integration settings */
-	status = write32(state, FEC_OC_RCN_CTL_RATE_LO__A, fecOcRcnCtlRate);
-	if (status < 0)
-		goto error;
-	status = write16(state, FEC_OC_TMD_INT_UPD_RATE__A, fecOcTmdIntUpdRate);
-	if (status < 0)
-		goto error;
-	status = write16(state, FEC_OC_TMD_MODE__A, fecOcTmdMode);
-error:
-	if (status < 0)
-		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
-	return status;
-}
-
-static int MPEGTSConfigurePolarity(struct drxk_state *state)
-{
-	u16 fecOcRegIprInvert = 0;
-
-	/* Data mask for the output data byte */
-	u16 InvertDataMask =
-	    FEC_OC_IPR_INVERT_MD7__M | FEC_OC_IPR_INVERT_MD6__M |
-	    FEC_OC_IPR_INVERT_MD5__M | FEC_OC_IPR_INVERT_MD4__M |
-	    FEC_OC_IPR_INVERT_MD3__M | FEC_OC_IPR_INVERT_MD2__M |
-	    FEC_OC_IPR_INVERT_MD1__M | FEC_OC_IPR_INVERT_MD0__M;
-
-	dprintk(1, "\n");
-
-	/* Control selective inversion of output bits */
-	fecOcRegIprInvert &= (~(InvertDataMask));
-	if (state->m_invertDATA == true)
-		fecOcRegIprInvert |= InvertDataMask;
-	fecOcRegIprInvert &= (~(FEC_OC_IPR_INVERT_MERR__M));
-	if (state->m_invertERR == true)
-		fecOcRegIprInvert |= FEC_OC_IPR_INVERT_MERR__M;
-	fecOcRegIprInvert &= (~(FEC_OC_IPR_INVERT_MSTRT__M));
-	if (state->m_invertSTR == true)
-		fecOcRegIprInvert |= FEC_OC_IPR_INVERT_MSTRT__M;
-	fecOcRegIprInvert &= (~(FEC_OC_IPR_INVERT_MVAL__M));
-	if (state->m_invertVAL == true)
-		fecOcRegIprInvert |= FEC_OC_IPR_INVERT_MVAL__M;
-	fecOcRegIprInvert &= (~(FEC_OC_IPR_INVERT_MCLK__M));
-	if (state->m_invertCLK == true)
-		fecOcRegIprInvert |= FEC_OC_IPR_INVERT_MCLK__M;
-
-	return write16(state, FEC_OC_IPR_INVERT__A, fecOcRegIprInvert);
-}
-
-#define   SCU_RAM_AGC_KI_INV_RF_POL__M 0x4000
-
-static int SetAgcRf(struct drxk_state *state,
-		    struct SCfgAgc *pAgcCfg, bool isDTV)
-{
-	int status = -EINVAL;
-	u16 data = 0;
-	struct SCfgAgc *pIfAgcSettings;
-
-	dprintk(1, "\n");
-
-	if (pAgcCfg == NULL)
-		goto error;
-
-	switch (pAgcCfg->ctrlMode) {
-	case DRXK_AGC_CTRL_AUTO:
-		/* Enable RF AGC DAC */
-		status = read16(state, IQM_AF_STDBY__A, &data);
-		if (status < 0)
-			goto error;
-		data &= ~IQM_AF_STDBY_STDBY_TAGC_RF_STANDBY;
-		status = write16(state, IQM_AF_STDBY__A, data);
-		if (status < 0)
-			goto error;
-		status = read16(state, SCU_RAM_AGC_CONFIG__A, &data);
-		if (status < 0)
-			goto error;
-
-		/* Enable SCU RF AGC loop */
-		data &= ~SCU_RAM_AGC_CONFIG_DISABLE_RF_AGC__M;
-
-		/* Polarity */
-		if (state->m_RfAgcPol)
-			data |= SCU_RAM_AGC_CONFIG_INV_RF_POL__M;
-		else
-			data &= ~SCU_RAM_AGC_CONFIG_INV_RF_POL__M;
-		status = write16(state, SCU_RAM_AGC_CONFIG__A, data);
-		if (status < 0)
-			goto error;
-
-		/* Set speed (using complementary reduction value) */
-		status = read16(state, SCU_RAM_AGC_KI_RED__A, &data);
-		if (status < 0)
-			goto error;
-
-		data &= ~SCU_RAM_AGC_KI_RED_RAGC_RED__M;
-		data |= (~(pAgcCfg->speed <<
-				SCU_RAM_AGC_KI_RED_RAGC_RED__B)
-				& SCU_RAM_AGC_KI_RED_RAGC_RED__M);
-
-		status = write16(state, SCU_RAM_AGC_KI_RED__A, data);
-		if (status < 0)
-			goto error;
-
-		if (IsDVBT(state))
-			pIfAgcSettings = &state->m_dvbtIfAgcCfg;
-		else if (IsQAM(state))
-			pIfAgcSettings = &state->m_qamIfAgcCfg;
-		else
-			pIfAgcSettings = &state->m_atvIfAgcCfg;
-		if (pIfAgcSettings == NULL) {
-			status = -EINVAL;
-			goto error;
-		}
-
-		/* Set TOP, only if IF-AGC is in AUTO mode */
-		if (pIfAgcSettings->ctrlMode == DRXK_AGC_CTRL_AUTO)
-			status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, pAgcCfg->top);
-			if (status < 0)
-				goto error;
-
-		/* Cut-Off current */
-		status = write16(state, SCU_RAM_AGC_RF_IACCU_HI_CO__A, pAgcCfg->cutOffCurrent);
-		if (status < 0)
-			goto error;
-
-		/* Max. output level */
-		status = write16(state, SCU_RAM_AGC_RF_MAX__A, pAgcCfg->maxOutputLevel);
-		if (status < 0)
-			goto error;
-
-		break;
-
-	case DRXK_AGC_CTRL_USER:
-		/* Enable RF AGC DAC */
-		status = read16(state, IQM_AF_STDBY__A, &data);
-		if (status < 0)
-			goto error;
-		data &= ~IQM_AF_STDBY_STDBY_TAGC_RF_STANDBY;
-		status = write16(state, IQM_AF_STDBY__A, data);
-		if (status < 0)
-			goto error;
-
-		/* Disable SCU RF AGC loop */
-		status = read16(state, SCU_RAM_AGC_CONFIG__A, &data);
-		if (status < 0)
-			goto error;
-		data |= SCU_RAM_AGC_CONFIG_DISABLE_RF_AGC__M;
-		if (state->m_RfAgcPol)
-			data |= SCU_RAM_AGC_CONFIG_INV_RF_POL__M;
-		else
-			data &= ~SCU_RAM_AGC_CONFIG_INV_RF_POL__M;
-		status = write16(state, SCU_RAM_AGC_CONFIG__A, data);
-		if (status < 0)
-			goto error;
-
-		/* SCU c.o.c. to 0, enabling full control range */
-		status = write16(state, SCU_RAM_AGC_RF_IACCU_HI_CO__A, 0);
-		if (status < 0)
-			goto error;
-
-		/* Write value to output pin */
-		status = write16(state, SCU_RAM_AGC_RF_IACCU_HI__A, pAgcCfg->outputLevel);
-		if (status < 0)
-			goto error;
-		break;
-
-	case DRXK_AGC_CTRL_OFF:
-		/* Disable RF AGC DAC */
-		status = read16(state, IQM_AF_STDBY__A, &data);
-		if (status < 0)
-			goto error;
-		data |= IQM_AF_STDBY_STDBY_TAGC_RF_STANDBY;
-		status = write16(state, IQM_AF_STDBY__A, data);
-		if (status < 0)
-			goto error;
-
-		/* Disable SCU RF AGC loop */
-		status = read16(state, SCU_RAM_AGC_CONFIG__A, &data);
-		if (status < 0)
-			goto error;
-		data |= SCU_RAM_AGC_CONFIG_DISABLE_RF_AGC__M;
-		status = write16(state, SCU_RAM_AGC_CONFIG__A, data);
-		if (status < 0)
-			goto error;
-		break;
-
-	default:
-		status = -EINVAL;
-
-	}
-error:
-	if (status < 0)
-		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
-	return status;
-}
-
-#define SCU_RAM_AGC_KI_INV_IF_POL__M 0x2000
-
-static int SetAgcIf(struct drxk_state *state,
-		    struct SCfgAgc *pAgcCfg, bool isDTV)
-{
-	u16 data = 0;
-	int status = 0;
-	struct SCfgAgc *pRfAgcSettings;
-
-	dprintk(1, "\n");
-
-	switch (pAgcCfg->ctrlMode) {
-	case DRXK_AGC_CTRL_AUTO:
-
-		/* Enable IF AGC DAC */
-		status = read16(state, IQM_AF_STDBY__A, &data);
-		if (status < 0)
-			goto error;
-		data &= ~IQM_AF_STDBY_STDBY_TAGC_IF_STANDBY;
-		status = write16(state, IQM_AF_STDBY__A, data);
-		if (status < 0)
-			goto error;
-
-		status = read16(state, SCU_RAM_AGC_CONFIG__A, &data);
-		if (status < 0)
-			goto error;
-
-		/* Enable SCU IF AGC loop */
-		data &= ~SCU_RAM_AGC_CONFIG_DISABLE_IF_AGC__M;
-
-		/* Polarity */
-		if (state->m_IfAgcPol)
-			data |= SCU_RAM_AGC_CONFIG_INV_IF_POL__M;
-		else
-			data &= ~SCU_RAM_AGC_CONFIG_INV_IF_POL__M;
-		status = write16(state, SCU_RAM_AGC_CONFIG__A, data);
-		if (status < 0)
-			goto error;
-
-		/* Set speed (using complementary reduction value) */
-		status = read16(state, SCU_RAM_AGC_KI_RED__A, &data);
-		if (status < 0)
-			goto error;
-		data &= ~SCU_RAM_AGC_KI_RED_IAGC_RED__M;
-		data |= (~(pAgcCfg->speed <<
-				SCU_RAM_AGC_KI_RED_IAGC_RED__B)
-				& SCU_RAM_AGC_KI_RED_IAGC_RED__M);
-
-		status = write16(state, SCU_RAM_AGC_KI_RED__A, data);
-		if (status < 0)
-			goto error;
-
-		if (IsQAM(state))
-			pRfAgcSettings = &state->m_qamRfAgcCfg;
-		else
-			pRfAgcSettings = &state->m_atvRfAgcCfg;
-		if (pRfAgcSettings == NULL)
-			return -1;
-		/* Restore TOP */
-		status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, pRfAgcSettings->top);
-		if (status < 0)
-			goto error;
-		break;
-
-	case DRXK_AGC_CTRL_USER:
-
-		/* Enable IF AGC DAC */
-		status = read16(state, IQM_AF_STDBY__A, &data);
-		if (status < 0)
-			goto error;
-		data &= ~IQM_AF_STDBY_STDBY_TAGC_IF_STANDBY;
-		status = write16(state, IQM_AF_STDBY__A, data);
-		if (status < 0)
-			goto error;
-
-		status = read16(state, SCU_RAM_AGC_CONFIG__A, &data);
-		if (status < 0)
-			goto error;
-
-		/* Disable SCU IF AGC loop */
-		data |= SCU_RAM_AGC_CONFIG_DISABLE_IF_AGC__M;
-
-		/* Polarity */
-		if (state->m_IfAgcPol)
-			data |= SCU_RAM_AGC_CONFIG_INV_IF_POL__M;
-		else
-			data &= ~SCU_RAM_AGC_CONFIG_INV_IF_POL__M;
-		status = write16(state, SCU_RAM_AGC_CONFIG__A, data);
-		if (status < 0)
-			goto error;
-
-		/* Write value to output pin */
-		status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, pAgcCfg->outputLevel);
-		if (status < 0)
-			goto error;
-		break;
-
-	case DRXK_AGC_CTRL_OFF:
-
-		/* Disable If AGC DAC */
-		status = read16(state, IQM_AF_STDBY__A, &data);
-		if (status < 0)
-			goto error;
-		data |= IQM_AF_STDBY_STDBY_TAGC_IF_STANDBY;
-		status = write16(state, IQM_AF_STDBY__A, data);
-		if (status < 0)
-			goto error;
-
-		/* Disable SCU IF AGC loop */
-		status = read16(state, SCU_RAM_AGC_CONFIG__A, &data);
-		if (status < 0)
-			goto error;
-		data |= SCU_RAM_AGC_CONFIG_DISABLE_IF_AGC__M;
-		status = write16(state, SCU_RAM_AGC_CONFIG__A, data);
-		if (status < 0)
-			goto error;
-		break;
-	}		/* switch (agcSettingsIf->ctrlMode) */
-
-	/* always set the top to support
-		configurations without if-loop */
-	status = write16(state, SCU_RAM_AGC_INGAIN_TGT_MIN__A, pAgcCfg->top);
-error:
-	if (status < 0)
-		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
-	return status;
-}
-
-static int ReadIFAgc(struct drxk_state *state, u32 *pValue)
-{
-	u16 agcDacLvl;
-	int status;
-	u16 Level = 0;
-
-	dprintk(1, "\n");
-
-	status = read16(state, IQM_AF_AGC_IF__A, &agcDacLvl);
-	if (status < 0) {
-		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
-		return status;
-	}
-
-	*pValue = 0;
-
-	if (agcDacLvl > DRXK_AGC_DAC_OFFSET)
-		Level = agcDacLvl - DRXK_AGC_DAC_OFFSET;
-	if (Level < 14000)
-		*pValue = (14000 - Level) / 4;
-	else
-		*pValue = 0;
-
-	return status;
-}
-
-static int GetQAMSignalToNoise(struct drxk_state *state,
-			       s32 *pSignalToNoise)
-{
-	int status = 0;
-	u16 qamSlErrPower = 0;	/* accum. error between
-					raw and sliced symbols */
-	u32 qamSlSigPower = 0;	/* used for MER, depends of
-					QAM modulation */
-	u32 qamSlMer = 0;	/* QAM MER */
-
-	dprintk(1, "\n");
-
-	/* MER calculation */
-
-	/* get the register value needed for MER */
-	status = read16(state, QAM_SL_ERR_POWER__A, &qamSlErrPower);
-	if (status < 0) {
-		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
-		return -EINVAL;
-	}
-
-	switch (state->props.modulation) {
-	case QAM_16:
-		qamSlSigPower = DRXK_QAM_SL_SIG_POWER_QAM16 << 2;
-		break;
-	case QAM_32:
-		qamSlSigPower = DRXK_QAM_SL_SIG_POWER_QAM32 << 2;
-		break;
-	case QAM_64:
-		qamSlSigPower = DRXK_QAM_SL_SIG_POWER_QAM64 << 2;
-		break;
-	case QAM_128:
-		qamSlSigPower = DRXK_QAM_SL_SIG_POWER_QAM128 << 2;
-		break;
-	default:
-	case QAM_256:
-		qamSlSigPower = DRXK_QAM_SL_SIG_POWER_QAM256 << 2;
-		break;
-	}
-
-	if (qamSlErrPower > 0) {
-		qamSlMer = Log10Times100(qamSlSigPower) -
-			Log10Times100((u32) qamSlErrPower);
-	}
-	*pSignalToNoise = qamSlMer;
-
-	return status;
-}
-
-static int GetDVBTSignalToNoise(struct drxk_state *state,
-				s32 *pSignalToNoise)
-{
-	int status;
-	u16 regData = 0;
-	u32 EqRegTdSqrErrI = 0;
-	u32 EqRegTdSqrErrQ = 0;
-	u16 EqRegTdSqrErrExp = 0;
-	u16 EqRegTdTpsPwrOfs = 0;
-	u16 EqRegTdReqSmbCnt = 0;
-	u32 tpsCnt = 0;
-	u32 SqrErrIQ = 0;
-	u32 a = 0;
-	u32 b = 0;
-	u32 c = 0;
-	u32 iMER = 0;
-	u16 transmissionParams = 0;
-
-	dprintk(1, "\n");
-
-	status = read16(state, OFDM_EQ_TOP_TD_TPS_PWR_OFS__A, &EqRegTdTpsPwrOfs);
-	if (status < 0)
-		goto error;
-	status = read16(state, OFDM_EQ_TOP_TD_REQ_SMB_CNT__A, &EqRegTdReqSmbCnt);
-	if (status < 0)
-		goto error;
-	status = read16(state, OFDM_EQ_TOP_TD_SQR_ERR_EXP__A, &EqRegTdSqrErrExp);
-	if (status < 0)
-		goto error;
-	status = read16(state, OFDM_EQ_TOP_TD_SQR_ERR_I__A, &regData);
-	if (status < 0)
-		goto error;
-	/* Extend SQR_ERR_I operational range */
-	EqRegTdSqrErrI = (u32) regData;
-	if ((EqRegTdSqrErrExp > 11) &&
-		(EqRegTdSqrErrI < 0x00000FFFUL)) {
-		EqRegTdSqrErrI += 0x00010000UL;
-	}
-	status = read16(state, OFDM_EQ_TOP_TD_SQR_ERR_Q__A, &regData);
-	if (status < 0)
-		goto error;
-	/* Extend SQR_ERR_Q operational range */
-	EqRegTdSqrErrQ = (u32) regData;
-	if ((EqRegTdSqrErrExp > 11) &&
-		(EqRegTdSqrErrQ < 0x00000FFFUL))
-		EqRegTdSqrErrQ += 0x00010000UL;
-
-	status = read16(state, OFDM_SC_RA_RAM_OP_PARAM__A, &transmissionParams);
-	if (status < 0)
-		goto error;
-
-	/* Check input data for MER */
-
-	/* MER calculation (in 0.1 dB) without math.h */
-	if ((EqRegTdTpsPwrOfs == 0) || (EqRegTdReqSmbCnt == 0))
-		iMER = 0;
-	else if ((EqRegTdSqrErrI + EqRegTdSqrErrQ) == 0) {
-		/* No error at all, this must be the HW reset value
-			* Apparently no first measurement yet
-			* Set MER to 0.0 */
-		iMER = 0;
-	} else {
-		SqrErrIQ = (EqRegTdSqrErrI + EqRegTdSqrErrQ) <<
-			EqRegTdSqrErrExp;
-		if ((transmissionParams &
-			OFDM_SC_RA_RAM_OP_PARAM_MODE__M)
-			== OFDM_SC_RA_RAM_OP_PARAM_MODE_2K)
-			tpsCnt = 17;
-		else
-			tpsCnt = 68;
-
-		/* IMER = 100 * log10 (x)
-			where x = (EqRegTdTpsPwrOfs^2 *
-			EqRegTdReqSmbCnt * tpsCnt)/SqrErrIQ
-
-			=> IMER = a + b -c
-			where a = 100 * log10 (EqRegTdTpsPwrOfs^2)
-			b = 100 * log10 (EqRegTdReqSmbCnt * tpsCnt)
-			c = 100 * log10 (SqrErrIQ)
-			*/
-
-		/* log(x) x = 9bits * 9bits->18 bits  */
-		a = Log10Times100(EqRegTdTpsPwrOfs *
-					EqRegTdTpsPwrOfs);
-		/* log(x) x = 16bits * 7bits->23 bits  */
-		b = Log10Times100(EqRegTdReqSmbCnt * tpsCnt);
-		/* log(x) x = (16bits + 16bits) << 15 ->32 bits  */
-		c = Log10Times100(SqrErrIQ);
-
-		iMER = a + b;
-		/* No negative MER, clip to zero */
-		if (iMER > c)
-			iMER -= c;
-		else
-			iMER = 0;
-	}
-	*pSignalToNoise = iMER;
-
-error:
-	if (status < 0)
-		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
-	return status;
-}
-
-static int GetSignalToNoise(struct drxk_state *state, s32 *pSignalToNoise)
-{
-	dprintk(1, "\n");
-
-	*pSignalToNoise = 0;
-	switch (state->m_OperationMode) {
-	case OM_DVBT:
-		return GetDVBTSignalToNoise(state, pSignalToNoise);
-	case OM_QAM_ITU_A:
-	case OM_QAM_ITU_C:
-		return GetQAMSignalToNoise(state, pSignalToNoise);
-	default:
-		break;
-	}
-	return 0;
-}
-
-#if 0
-static int GetDVBTQuality(struct drxk_state *state, s32 *pQuality)
-{
-	/* SNR Values for quasi errorfree reception rom Nordig 2.2 */
-	int status = 0;
-
-	dprintk(1, "\n");
-
-	static s32 QE_SN[] = {
-		51,		/* QPSK 1/2 */
-		69,		/* QPSK 2/3 */
-		79,		/* QPSK 3/4 */
-		89,		/* QPSK 5/6 */
-		97,		/* QPSK 7/8 */
-		108,		/* 16-QAM 1/2 */
-		131,		/* 16-QAM 2/3 */
-		146,		/* 16-QAM 3/4 */
-		156,		/* 16-QAM 5/6 */
-		160,		/* 16-QAM 7/8 */
-		165,		/* 64-QAM 1/2 */
-		187,		/* 64-QAM 2/3 */
-		202,		/* 64-QAM 3/4 */
-		216,		/* 64-QAM 5/6 */
-		225,		/* 64-QAM 7/8 */
-	};
-
-	*pQuality = 0;
-
-	do {
-		s32 SignalToNoise = 0;
-		u16 Constellation = 0;
-		u16 CodeRate = 0;
-		u32 SignalToNoiseRel;
-		u32 BERQuality;
-
-		status = GetDVBTSignalToNoise(state, &SignalToNoise);
-		if (status < 0)
-			break;
-		status = read16(state, OFDM_EQ_TOP_TD_TPS_CONST__A, &Constellation);
-		if (status < 0)
-			break;
-		Constellation &= OFDM_EQ_TOP_TD_TPS_CONST__M;
-
-		status = read16(state, OFDM_EQ_TOP_TD_TPS_CODE_HP__A, &CodeRate);
-		if (status < 0)
-			break;
-		CodeRate &= OFDM_EQ_TOP_TD_TPS_CODE_HP__M;
-
-		if (Constellation > OFDM_EQ_TOP_TD_TPS_CONST_64QAM ||
-		    CodeRate > OFDM_EQ_TOP_TD_TPS_CODE_LP_7_8)
-			break;
-		SignalToNoiseRel = SignalToNoise -
-		    QE_SN[Constellation * 5 + CodeRate];
-		BERQuality = 100;
-
-		if (SignalToNoiseRel < -70)
-			*pQuality = 0;
-		else if (SignalToNoiseRel < 30)
-			*pQuality = ((SignalToNoiseRel + 70) *
-				     BERQuality) / 100;
-		else
-			*pQuality = BERQuality;
-	} while (0);
-	return 0;
-};
-
-static int GetDVBCQuality(struct drxk_state *state, s32 *pQuality)
-{
-	int status = 0;
-	*pQuality = 0;
-
-	dprintk(1, "\n");
-
-	do {
-		u32 SignalToNoise = 0;
-		u32 BERQuality = 100;
-		u32 SignalToNoiseRel = 0;
-
-		status = GetQAMSignalToNoise(state, &SignalToNoise);
-		if (status < 0)
-			break;
-
-		switch (state->props.modulation) {
-		case QAM_16:
-			SignalToNoiseRel = SignalToNoise - 200;
-			break;
-		case QAM_32:
-			SignalToNoiseRel = SignalToNoise - 230;
-			break;	/* Not in NorDig */
-		case QAM_64:
-			SignalToNoiseRel = SignalToNoise - 260;
-			break;
-		case QAM_128:
-			SignalToNoiseRel = SignalToNoise - 290;
-			break;
-		default:
-		case QAM_256:
-			SignalToNoiseRel = SignalToNoise - 320;
-			break;
-		}
-
-		if (SignalToNoiseRel < -70)
-			*pQuality = 0;
-		else if (SignalToNoiseRel < 30)
-			*pQuality = ((SignalToNoiseRel + 70) *
-				     BERQuality) / 100;
-		else
-			*pQuality = BERQuality;
-	} while (0);
-
-	return status;
-}
-
-static int GetQuality(struct drxk_state *state, s32 *pQuality)
-{
-	dprintk(1, "\n");
-
-	switch (state->m_OperationMode) {
-	case OM_DVBT:
-		return GetDVBTQuality(state, pQuality);
-	case OM_QAM_ITU_A:
-		return GetDVBCQuality(state, pQuality);
-	default:
-		break;
-	}
-
-	return 0;
-}
-#endif
-
-/* Free data ram in SIO HI */
-#define SIO_HI_RA_RAM_USR_BEGIN__A 0x420040
-#define SIO_HI_RA_RAM_USR_END__A   0x420060
-
-#define DRXK_HI_ATOMIC_BUF_START (SIO_HI_RA_RAM_USR_BEGIN__A)
-#define DRXK_HI_ATOMIC_BUF_END   (SIO_HI_RA_RAM_USR_BEGIN__A + 7)
-#define DRXK_HI_ATOMIC_READ      SIO_HI_RA_RAM_PAR_3_ACP_RW_READ
-#define DRXK_HI_ATOMIC_WRITE     SIO_HI_RA_RAM_PAR_3_ACP_RW_WRITE
-
-#define DRXDAP_FASI_ADDR2BLOCK(addr)  (((addr) >> 22) & 0x3F)
-#define DRXDAP_FASI_ADDR2BANK(addr)   (((addr) >> 16) & 0x3F)
-#define DRXDAP_FASI_ADDR2OFFSET(addr) ((addr) & 0x7FFF)
-
-static int ConfigureI2CBridge(struct drxk_state *state, bool bEnableBridge)
-{
-	int status = -EINVAL;
-
-	dprintk(1, "\n");
-
-	if (state->m_DrxkState == DRXK_UNINITIALIZED)
-		return 0;
-	if (state->m_DrxkState == DRXK_POWERED_DOWN)
-		goto error;
-
-	if (state->no_i2c_bridge)
-		return 0;
-
-	status = write16(state, SIO_HI_RA_RAM_PAR_1__A, SIO_HI_RA_RAM_PAR_1_PAR1_SEC_KEY);
-	if (status < 0)
-		goto error;
-	if (bEnableBridge) {
-		status = write16(state, SIO_HI_RA_RAM_PAR_2__A, SIO_HI_RA_RAM_PAR_2_BRD_CFG_CLOSED);
-		if (status < 0)
-			goto error;
-	} else {
-		status = write16(state, SIO_HI_RA_RAM_PAR_2__A, SIO_HI_RA_RAM_PAR_2_BRD_CFG_OPEN);
-		if (status < 0)
-			goto error;
-	}
-
-	status = HI_Command(state, SIO_HI_RA_RAM_CMD_BRDCTRL, 0);
-
-error:
-	if (status < 0)
-		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
-	return status;
-}
-
-static int SetPreSaw(struct drxk_state *state,
-		     struct SCfgPreSaw *pPreSawCfg)
-{
-	int status = -EINVAL;
-
-	dprintk(1, "\n");
-
-	if ((pPreSawCfg == NULL)
-	    || (pPreSawCfg->reference > IQM_AF_PDREF__M))
-		goto error;
-
-	status = write16(state, IQM_AF_PDREF__A, pPreSawCfg->reference);
-error:
-	if (status < 0)
-		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
-	return status;
-}
-
-static int BLDirectCmd(struct drxk_state *state, u32 targetAddr,
-		       u16 romOffset, u16 nrOfElements, u32 timeOut)
-{
-	u16 blStatus = 0;
-	u16 offset = (u16) ((targetAddr >> 0) & 0x00FFFF);
-	u16 blockbank = (u16) ((targetAddr >> 16) & 0x000FFF);
-	int status;
-	unsigned long end;
-
-	dprintk(1, "\n");
-
-	mutex_lock(&state->mutex);
-	status = write16(state, SIO_BL_MODE__A, SIO_BL_MODE_DIRECT);
-	if (status < 0)
-		goto error;
-	status = write16(state, SIO_BL_TGT_HDR__A, blockbank);
-	if (status < 0)
-		goto error;
-	status = write16(state, SIO_BL_TGT_ADDR__A, offset);
-	if (status < 0)
-		goto error;
-	status = write16(state, SIO_BL_SRC_ADDR__A, romOffset);
-	if (status < 0)
-		goto error;
-	status = write16(state, SIO_BL_SRC_LEN__A, nrOfElements);
-	if (status < 0)
-		goto error;
-	status = write16(state, SIO_BL_ENABLE__A, SIO_BL_ENABLE_ON);
-	if (status < 0)
-		goto error;
-
-	end = jiffies + msecs_to_jiffies(timeOut);
-	do {
-		status = read16(state, SIO_BL_STATUS__A, &blStatus);
-		if (status < 0)
-			goto error;
-	} while ((blStatus == 0x1) && time_is_after_jiffies(end));
-	if (blStatus == 0x1) {
-		printk(KERN_ERR "drxk: SIO not ready\n");
-		status = -EINVAL;
-		goto error2;
-	}
-error:
-	if (status < 0)
-		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
-error2:
-	mutex_unlock(&state->mutex);
-	return status;
-
-}
-
-static int ADCSyncMeasurement(struct drxk_state *state, u16 *count)
-{
-	u16 data = 0;
-	int status;
-
-	dprintk(1, "\n");
-
-	/* Start measurement */
-	status = write16(state, IQM_AF_COMM_EXEC__A, IQM_AF_COMM_EXEC_ACTIVE);
-	if (status < 0)
-		goto error;
-	status = write16(state, IQM_AF_START_LOCK__A, 1);
-	if (status < 0)
-		goto error;
-
-	*count = 0;
-	status = read16(state, IQM_AF_PHASE0__A, &data);
-	if (status < 0)
-		goto error;
-	if (data == 127)
-		*count = *count + 1;
-	status = read16(state, IQM_AF_PHASE1__A, &data);
-	if (status < 0)
-		goto error;
-	if (data == 127)
-		*count = *count + 1;
-	status = read16(state, IQM_AF_PHASE2__A, &data);
-	if (status < 0)
-		goto error;
-	if (data == 127)
-		*count = *count + 1;
-
-error:
-	if (status < 0)
-		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
-	return status;
-}
-
-static int ADCSynchronization(struct drxk_state *state)
-{
-	u16 count = 0;
-	int status;
-
-	dprintk(1, "\n");
-
-	status = ADCSyncMeasurement(state, &count);
-	if (status < 0)
-		goto error;
-
-	if (count == 1) {
-		/* Try sampling on a diffrent edge */
-		u16 clkNeg = 0;
-
-		status = read16(state, IQM_AF_CLKNEG__A, &clkNeg);
-		if (status < 0)
-			goto error;
-		if ((clkNeg & IQM_AF_CLKNEG_CLKNEGDATA__M) ==
-			IQM_AF_CLKNEG_CLKNEGDATA_CLK_ADC_DATA_POS) {
-			clkNeg &= (~(IQM_AF_CLKNEG_CLKNEGDATA__M));
-			clkNeg |=
-				IQM_AF_CLKNEG_CLKNEGDATA_CLK_ADC_DATA_NEG;
-		} else {
-			clkNeg &= (~(IQM_AF_CLKNEG_CLKNEGDATA__M));
-			clkNeg |=
-				IQM_AF_CLKNEG_CLKNEGDATA_CLK_ADC_DATA_POS;
-		}
-		status = write16(state, IQM_AF_CLKNEG__A, clkNeg);
-		if (status < 0)
-			goto error;
-		status = ADCSyncMeasurement(state, &count);
-		if (status < 0)
-			goto error;
-	}
-
-	if (count < 2)
-		status = -EINVAL;
-error:
-	if (status < 0)
-		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
-	return status;
-}
-
-static int SetFrequencyShifter(struct drxk_state *state,
-			       u16 intermediateFreqkHz,
-			       s32 tunerFreqOffset, bool isDTV)
-{
-	bool selectPosImage = false;
-	u32 rfFreqResidual = tunerFreqOffset;
-	u32 fmFrequencyShift = 0;
-	bool tunerMirror = !state->m_bMirrorFreqSpect;
-	u32 adcFreq;
-	bool adcFlip;
-	int status;
-	u32 ifFreqActual;
-	u32 samplingFrequency = (u32) (state->m_sysClockFreq / 3);
-	u32 frequencyShift;
-	bool imageToSelect;
-
-	dprintk(1, "\n");
-
-	/*
-	   Program frequency shifter
-	   No need to account for mirroring on RF
-	 */
-	if (isDTV) {
-		if ((state->m_OperationMode == OM_QAM_ITU_A) ||
-		    (state->m_OperationMode == OM_QAM_ITU_C) ||
-		    (state->m_OperationMode == OM_DVBT))
-			selectPosImage = true;
-		else
-			selectPosImage = false;
-	}
-	if (tunerMirror)
-		/* tuner doesn't mirror */
-		ifFreqActual = intermediateFreqkHz +
-		    rfFreqResidual + fmFrequencyShift;
-	else
-		/* tuner mirrors */
-		ifFreqActual = intermediateFreqkHz -
-		    rfFreqResidual - fmFrequencyShift;
-	if (ifFreqActual > samplingFrequency / 2) {
-		/* adc mirrors */
-		adcFreq = samplingFrequency - ifFreqActual;
-		adcFlip = true;
-	} else {
-		/* adc doesn't mirror */
-		adcFreq = ifFreqActual;
-		adcFlip = false;
-	}
-
-	frequencyShift = adcFreq;
-	imageToSelect = state->m_rfmirror ^ tunerMirror ^
-	    adcFlip ^ selectPosImage;
-	state->m_IqmFsRateOfs =
-	    Frac28a((frequencyShift), samplingFrequency);
-
-	if (imageToSelect)
-		state->m_IqmFsRateOfs = ~state->m_IqmFsRateOfs + 1;
-
-	/* Program frequency shifter with tuner offset compensation */
-	/* frequencyShift += tunerFreqOffset; TODO */
-	status = write32(state, IQM_FS_RATE_OFS_LO__A,
-			 state->m_IqmFsRateOfs);
-	if (status < 0)
-		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
-	return status;
-}
-
-static int InitAGC(struct drxk_state *state, bool isDTV)
-{
-	u16 ingainTgt = 0;
-	u16 ingainTgtMin = 0;
-	u16 ingainTgtMax = 0;
-	u16 clpCyclen = 0;
-	u16 clpSumMin = 0;
-	u16 clpDirTo = 0;
-	u16 snsSumMin = 0;
-	u16 snsSumMax = 0;
-	u16 clpSumMax = 0;
-	u16 snsDirTo = 0;
-	u16 kiInnergainMin = 0;
-	u16 ifIaccuHiTgt = 0;
-	u16 ifIaccuHiTgtMin = 0;
-	u16 ifIaccuHiTgtMax = 0;
-	u16 data = 0;
-	u16 fastClpCtrlDelay = 0;
-	u16 clpCtrlMode = 0;
-	int status = 0;
-
-	dprintk(1, "\n");
-
-	/* Common settings */
-	snsSumMax = 1023;
-	ifIaccuHiTgtMin = 2047;
-	clpCyclen = 500;
-	clpSumMax = 1023;
-
-	/* AGCInit() not available for DVBT; init done in microcode */
-	if (!IsQAM(state)) {
-		printk(KERN_ERR "drxk: %s: mode %d is not DVB-C\n", __func__, state->m_OperationMode);
-		return -EINVAL;
-	}
-
-	/* FIXME: Analog TV AGC require different settings */
-
-	/* Standard specific settings */
-	clpSumMin = 8;
-	clpDirTo = (u16) -9;
-	clpCtrlMode = 0;
-	snsSumMin = 8;
-	snsDirTo = (u16) -9;
-	kiInnergainMin = (u16) -1030;
-	ifIaccuHiTgtMax = 0x2380;
-	ifIaccuHiTgt = 0x2380;
-	ingainTgtMin = 0x0511;
-	ingainTgt = 0x0511;
-	ingainTgtMax = 5119;
-	fastClpCtrlDelay = state->m_qamIfAgcCfg.FastClipCtrlDelay;
-
-	status = write16(state, SCU_RAM_AGC_FAST_CLP_CTRL_DELAY__A, fastClpCtrlDelay);
-	if (status < 0)
-		goto error;
-
-	status = write16(state, SCU_RAM_AGC_CLP_CTRL_MODE__A, clpCtrlMode);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_AGC_INGAIN_TGT__A, ingainTgt);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_AGC_INGAIN_TGT_MIN__A, ingainTgtMin);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_AGC_INGAIN_TGT_MAX__A, ingainTgtMax);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MIN__A, ifIaccuHiTgtMin);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A, ifIaccuHiTgtMax);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_AGC_IF_IACCU_HI__A, 0);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_AGC_IF_IACCU_LO__A, 0);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_AGC_RF_IACCU_HI__A, 0);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_AGC_RF_IACCU_LO__A, 0);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_AGC_CLP_SUM_MAX__A, clpSumMax);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_AGC_SNS_SUM_MAX__A, snsSumMax);
-	if (status < 0)
-		goto error;
-
-	status = write16(state, SCU_RAM_AGC_KI_INNERGAIN_MIN__A, kiInnergainMin);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_AGC_IF_IACCU_HI_TGT__A, ifIaccuHiTgt);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_AGC_CLP_CYCLEN__A, clpCyclen);
-	if (status < 0)
-		goto error;
-
-	status = write16(state, SCU_RAM_AGC_RF_SNS_DEV_MAX__A, 1023);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_AGC_RF_SNS_DEV_MIN__A, (u16) -1023);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_AGC_FAST_SNS_CTRL_DELAY__A, 50);
-	if (status < 0)
-		goto error;
-
-	status = write16(state, SCU_RAM_AGC_KI_MAXMINGAIN_TH__A, 20);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_AGC_CLP_SUM_MIN__A, clpSumMin);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_AGC_SNS_SUM_MIN__A, snsSumMin);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_AGC_CLP_DIR_TO__A, clpDirTo);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_AGC_SNS_DIR_TO__A, snsDirTo);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_AGC_KI_MINGAIN__A, 0x7fff);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_AGC_KI_MAXGAIN__A, 0x0);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_AGC_KI_MIN__A, 0x0117);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_AGC_KI_MAX__A, 0x0657);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_AGC_CLP_SUM__A, 0);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_AGC_CLP_CYCCNT__A, 0);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_AGC_CLP_DIR_WD__A, 0);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_AGC_CLP_DIR_STP__A, 1);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_AGC_SNS_SUM__A, 0);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_AGC_SNS_CYCCNT__A, 0);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_AGC_SNS_DIR_WD__A, 0);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_AGC_SNS_DIR_STP__A, 1);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_AGC_SNS_CYCLEN__A, 500);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_AGC_KI_CYCLEN__A, 500);
-	if (status < 0)
-		goto error;
-
-	/* Initialize inner-loop KI gain factors */
-	status = read16(state, SCU_RAM_AGC_KI__A, &data);
-	if (status < 0)
-		goto error;
-
-	data = 0x0657;
-	data &= ~SCU_RAM_AGC_KI_RF__M;
-	data |= (DRXK_KI_RAGC_QAM << SCU_RAM_AGC_KI_RF__B);
-	data &= ~SCU_RAM_AGC_KI_IF__M;
-	data |= (DRXK_KI_IAGC_QAM << SCU_RAM_AGC_KI_IF__B);
-
-	status = write16(state, SCU_RAM_AGC_KI__A, data);
-error:
-	if (status < 0)
-		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
-	return status;
-}
-
-static int DVBTQAMGetAccPktErr(struct drxk_state *state, u16 *packetErr)
-{
-	int status;
-
-	dprintk(1, "\n");
-	if (packetErr == NULL)
-		status = write16(state, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, 0);
-	else
-		status = read16(state, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, packetErr);
-	if (status < 0)
-		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
-	return status;
-}
-
-static int DVBTScCommand(struct drxk_state *state,
-			 u16 cmd, u16 subcmd,
-			 u16 param0, u16 param1, u16 param2,
-			 u16 param3, u16 param4)
-{
-	u16 curCmd = 0;
-	u16 errCode = 0;
-	u16 retryCnt = 0;
-	u16 scExec = 0;
-	int status;
-
-	dprintk(1, "\n");
-	status = read16(state, OFDM_SC_COMM_EXEC__A, &scExec);
-	if (scExec != 1) {
-		/* SC is not running */
-		status = -EINVAL;
-	}
-	if (status < 0)
-		goto error;
-
-	/* Wait until sc is ready to receive command */
-	retryCnt = 0;
-	do {
-		msleep(1);
-		status = read16(state, OFDM_SC_RA_RAM_CMD__A, &curCmd);
-		retryCnt++;
-	} while ((curCmd != 0) && (retryCnt < DRXK_MAX_RETRIES));
-	if (retryCnt >= DRXK_MAX_RETRIES && (status < 0))
-		goto error;
-
-	/* Write sub-command */
-	switch (cmd) {
-		/* All commands using sub-cmd */
-	case OFDM_SC_RA_RAM_CMD_PROC_START:
-	case OFDM_SC_RA_RAM_CMD_SET_PREF_PARAM:
-	case OFDM_SC_RA_RAM_CMD_PROGRAM_PARAM:
-		status = write16(state, OFDM_SC_RA_RAM_CMD_ADDR__A, subcmd);
-		if (status < 0)
-			goto error;
-		break;
-	default:
-		/* Do nothing */
-		break;
-	}
-
-	/* Write needed parameters and the command */
-	switch (cmd) {
-		/* All commands using 5 parameters */
-		/* All commands using 4 parameters */
-		/* All commands using 3 parameters */
-		/* All commands using 2 parameters */
-	case OFDM_SC_RA_RAM_CMD_PROC_START:
-	case OFDM_SC_RA_RAM_CMD_SET_PREF_PARAM:
-	case OFDM_SC_RA_RAM_CMD_PROGRAM_PARAM:
-		status = write16(state, OFDM_SC_RA_RAM_PARAM1__A, param1);
-		/* All commands using 1 parameters */
-	case OFDM_SC_RA_RAM_CMD_SET_ECHO_TIMING:
-	case OFDM_SC_RA_RAM_CMD_USER_IO:
-		status = write16(state, OFDM_SC_RA_RAM_PARAM0__A, param0);
-		/* All commands using 0 parameters */
-	case OFDM_SC_RA_RAM_CMD_GET_OP_PARAM:
-	case OFDM_SC_RA_RAM_CMD_NULL:
-		/* Write command */
-		status = write16(state, OFDM_SC_RA_RAM_CMD__A, cmd);
-		break;
-	default:
-		/* Unknown command */
-		status = -EINVAL;
-	}
-	if (status < 0)
-		goto error;
-
-	/* Wait until sc is ready processing command */
-	retryCnt = 0;
-	do {
-		msleep(1);
-		status = read16(state, OFDM_SC_RA_RAM_CMD__A, &curCmd);
-		retryCnt++;
-	} while ((curCmd != 0) && (retryCnt < DRXK_MAX_RETRIES));
-	if (retryCnt >= DRXK_MAX_RETRIES && (status < 0))
-		goto error;
-
-	/* Check for illegal cmd */
-	status = read16(state, OFDM_SC_RA_RAM_CMD_ADDR__A, &errCode);
-	if (errCode == 0xFFFF) {
-		/* illegal command */
-		status = -EINVAL;
-	}
-	if (status < 0)
-		goto error;
-
-	/* Retreive results parameters from SC */
-	switch (cmd) {
-		/* All commands yielding 5 results */
-		/* All commands yielding 4 results */
-		/* All commands yielding 3 results */
-		/* All commands yielding 2 results */
-		/* All commands yielding 1 result */
-	case OFDM_SC_RA_RAM_CMD_USER_IO:
-	case OFDM_SC_RA_RAM_CMD_GET_OP_PARAM:
-		status = read16(state, OFDM_SC_RA_RAM_PARAM0__A, &(param0));
-		/* All commands yielding 0 results */
-	case OFDM_SC_RA_RAM_CMD_SET_ECHO_TIMING:
-	case OFDM_SC_RA_RAM_CMD_SET_TIMER:
-	case OFDM_SC_RA_RAM_CMD_PROC_START:
-	case OFDM_SC_RA_RAM_CMD_SET_PREF_PARAM:
-	case OFDM_SC_RA_RAM_CMD_PROGRAM_PARAM:
-	case OFDM_SC_RA_RAM_CMD_NULL:
-		break;
-	default:
-		/* Unknown command */
-		status = -EINVAL;
-		break;
-	}			/* switch (cmd->cmd) */
-error:
-	if (status < 0)
-		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
-	return status;
-}
-
-static int PowerUpDVBT(struct drxk_state *state)
-{
-	enum DRXPowerMode powerMode = DRX_POWER_UP;
-	int status;
-
-	dprintk(1, "\n");
-	status = CtrlPowerMode(state, &powerMode);
-	if (status < 0)
-		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
-	return status;
-}
-
-static int DVBTCtrlSetIncEnable(struct drxk_state *state, bool *enabled)
-{
-	int status;
-
-	dprintk(1, "\n");
-	if (*enabled == true)
-		status = write16(state, IQM_CF_BYPASSDET__A, 0);
-	else
-		status = write16(state, IQM_CF_BYPASSDET__A, 1);
-	if (status < 0)
-		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
-	return status;
-}
-
-#define DEFAULT_FR_THRES_8K     4000
-static int DVBTCtrlSetFrEnable(struct drxk_state *state, bool *enabled)
-{
-
-	int status;
-
-	dprintk(1, "\n");
-	if (*enabled == true) {
-		/* write mask to 1 */
-		status = write16(state, OFDM_SC_RA_RAM_FR_THRES_8K__A,
-				   DEFAULT_FR_THRES_8K);
-	} else {
-		/* write mask to 0 */
-		status = write16(state, OFDM_SC_RA_RAM_FR_THRES_8K__A, 0);
-	}
-	if (status < 0)
-		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
-
-	return status;
-}
-
-static int DVBTCtrlSetEchoThreshold(struct drxk_state *state,
-				    struct DRXKCfgDvbtEchoThres_t *echoThres)
-{
-	u16 data = 0;
-	int status;
-
-	dprintk(1, "\n");
-	status = read16(state, OFDM_SC_RA_RAM_ECHO_THRES__A, &data);
-	if (status < 0)
-		goto error;
-
-	switch (echoThres->fftMode) {
-	case DRX_FFTMODE_2K:
-		data &= ~OFDM_SC_RA_RAM_ECHO_THRES_2K__M;
-		data |= ((echoThres->threshold <<
-			OFDM_SC_RA_RAM_ECHO_THRES_2K__B)
-			& (OFDM_SC_RA_RAM_ECHO_THRES_2K__M));
-		break;
-	case DRX_FFTMODE_8K:
-		data &= ~OFDM_SC_RA_RAM_ECHO_THRES_8K__M;
-		data |= ((echoThres->threshold <<
-			OFDM_SC_RA_RAM_ECHO_THRES_8K__B)
-			& (OFDM_SC_RA_RAM_ECHO_THRES_8K__M));
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	status = write16(state, OFDM_SC_RA_RAM_ECHO_THRES__A, data);
-error:
-	if (status < 0)
-		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
-	return status;
-}
-
-static int DVBTCtrlSetSqiSpeed(struct drxk_state *state,
-			       enum DRXKCfgDvbtSqiSpeed *speed)
-{
-	int status = -EINVAL;
-
-	dprintk(1, "\n");
-
-	switch (*speed) {
-	case DRXK_DVBT_SQI_SPEED_FAST:
-	case DRXK_DVBT_SQI_SPEED_MEDIUM:
-	case DRXK_DVBT_SQI_SPEED_SLOW:
-		break;
-	default:
-		goto error;
-	}
-	status = write16(state, SCU_RAM_FEC_PRE_RS_BER_FILTER_SH__A,
-			   (u16) *speed);
-error:
-	if (status < 0)
-		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
-	return status;
-}
-
-/*============================================================================*/
-
-/**
-* \brief Activate DVBT specific presets
-* \param demod instance of demodulator.
-* \return DRXStatus_t.
-*
-* Called in DVBTSetStandard
-*
-*/
-static int DVBTActivatePresets(struct drxk_state *state)
-{
-	int status;
-	bool setincenable = false;
-	bool setfrenable = true;
-
-	struct DRXKCfgDvbtEchoThres_t echoThres2k = { 0, DRX_FFTMODE_2K };
-	struct DRXKCfgDvbtEchoThres_t echoThres8k = { 0, DRX_FFTMODE_8K };
-
-	dprintk(1, "\n");
-	status = DVBTCtrlSetIncEnable(state, &setincenable);
-	if (status < 0)
-		goto error;
-	status = DVBTCtrlSetFrEnable(state, &setfrenable);
-	if (status < 0)
-		goto error;
-	status = DVBTCtrlSetEchoThreshold(state, &echoThres2k);
-	if (status < 0)
-		goto error;
-	status = DVBTCtrlSetEchoThreshold(state, &echoThres8k);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_AGC_INGAIN_TGT_MAX__A, state->m_dvbtIfAgcCfg.IngainTgtMax);
-error:
-	if (status < 0)
-		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
-	return status;
-}
-
-/*============================================================================*/
-
-/**
-* \brief Initialize channelswitch-independent settings for DVBT.
-* \param demod instance of demodulator.
-* \return DRXStatus_t.
-*
-* For ROM code channel filter taps are loaded from the bootloader. For microcode
-* the DVB-T taps from the drxk_filters.h are used.
-*/
-static int SetDVBTStandard(struct drxk_state *state,
-			   enum OperationMode oMode)
-{
-	u16 cmdResult = 0;
-	u16 data = 0;
-	int status;
-
-	dprintk(1, "\n");
-
-	PowerUpDVBT(state);
-	/* added antenna switch */
-	SwitchAntennaToDVBT(state);
-	/* send OFDM reset command */
-	status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM | SCU_RAM_COMMAND_CMD_DEMOD_RESET, 0, NULL, 1, &cmdResult);
-	if (status < 0)
-		goto error;
-
-	/* send OFDM setenv command */
-	status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM | SCU_RAM_COMMAND_CMD_DEMOD_SET_ENV, 0, NULL, 1, &cmdResult);
-	if (status < 0)
-		goto error;
-
-	/* reset datapath for OFDM, processors first */
-	status = write16(state, OFDM_SC_COMM_EXEC__A, OFDM_SC_COMM_EXEC_STOP);
-	if (status < 0)
-		goto error;
-	status = write16(state, OFDM_LC_COMM_EXEC__A, OFDM_LC_COMM_EXEC_STOP);
-	if (status < 0)
-		goto error;
-	status = write16(state, IQM_COMM_EXEC__A, IQM_COMM_EXEC_B_STOP);
-	if (status < 0)
-		goto error;
-
-	/* IQM setup */
-	/* synchronize on ofdstate->m_festart */
-	status = write16(state, IQM_AF_UPD_SEL__A, 1);
-	if (status < 0)
-		goto error;
-	/* window size for clipping ADC detection */
-	status = write16(state, IQM_AF_CLP_LEN__A, 0);
-	if (status < 0)
-		goto error;
-	/* window size for for sense pre-SAW detection */
-	status = write16(state, IQM_AF_SNS_LEN__A, 0);
-	if (status < 0)
-		goto error;
-	/* sense threshold for sense pre-SAW detection */
-	status = write16(state, IQM_AF_AMUX__A, IQM_AF_AMUX_SIGNAL2ADC);
-	if (status < 0)
-		goto error;
-	status = SetIqmAf(state, true);
-	if (status < 0)
-		goto error;
-
-	status = write16(state, IQM_AF_AGC_RF__A, 0);
-	if (status < 0)
-		goto error;
-
-	/* Impulse noise cruncher setup */
-	status = write16(state, IQM_AF_INC_LCT__A, 0);	/* crunch in IQM_CF */
-	if (status < 0)
-		goto error;
-	status = write16(state, IQM_CF_DET_LCT__A, 0);	/* detect in IQM_CF */
-	if (status < 0)
-		goto error;
-	status = write16(state, IQM_CF_WND_LEN__A, 3);	/* peak detector window length */
-	if (status < 0)
-		goto error;
-
-	status = write16(state, IQM_RC_STRETCH__A, 16);
-	if (status < 0)
-		goto error;
-	status = write16(state, IQM_CF_OUT_ENA__A, 0x4);	/* enable output 2 */
-	if (status < 0)
-		goto error;
-	status = write16(state, IQM_CF_DS_ENA__A, 0x4);	/* decimate output 2 */
-	if (status < 0)
-		goto error;
-	status = write16(state, IQM_CF_SCALE__A, 1600);
-	if (status < 0)
-		goto error;
-	status = write16(state, IQM_CF_SCALE_SH__A, 0);
-	if (status < 0)
-		goto error;
-
-	/* virtual clipping threshold for clipping ADC detection */
-	status = write16(state, IQM_AF_CLP_TH__A, 448);
-	if (status < 0)
-		goto error;
-	status = write16(state, IQM_CF_DATATH__A, 495);	/* crunching threshold */
-	if (status < 0)
-		goto error;
-
-	status = BLChainCmd(state, DRXK_BL_ROM_OFFSET_TAPS_DVBT, DRXK_BLCC_NR_ELEMENTS_TAPS, DRXK_BLC_TIMEOUT);
-	if (status < 0)
-		goto error;
-
-	status = write16(state, IQM_CF_PKDTH__A, 2);	/* peak detector threshold */
-	if (status < 0)
-		goto error;
-	status = write16(state, IQM_CF_POW_MEAS_LEN__A, 2);
-	if (status < 0)
-		goto error;
-	/* enable power measurement interrupt */
-	status = write16(state, IQM_CF_COMM_INT_MSK__A, 1);
-	if (status < 0)
-		goto error;
-	status = write16(state, IQM_COMM_EXEC__A, IQM_COMM_EXEC_B_ACTIVE);
-	if (status < 0)
-		goto error;
-
-	/* IQM will not be reset from here, sync ADC and update/init AGC */
-	status = ADCSynchronization(state);
-	if (status < 0)
-		goto error;
-	status = SetPreSaw(state, &state->m_dvbtPreSawCfg);
-	if (status < 0)
-		goto error;
-
-	/* Halt SCU to enable safe non-atomic accesses */
-	status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_HOLD);
-	if (status < 0)
-		goto error;
-
-	status = SetAgcRf(state, &state->m_dvbtRfAgcCfg, true);
-	if (status < 0)
-		goto error;
-	status = SetAgcIf(state, &state->m_dvbtIfAgcCfg, true);
-	if (status < 0)
-		goto error;
-
-	/* Set Noise Estimation notch width and enable DC fix */
-	status = read16(state, OFDM_SC_RA_RAM_CONFIG__A, &data);
-	if (status < 0)
-		goto error;
-	data |= OFDM_SC_RA_RAM_CONFIG_NE_FIX_ENABLE__M;
-	status = write16(state, OFDM_SC_RA_RAM_CONFIG__A, data);
-	if (status < 0)
-		goto error;
-
-	/* Activate SCU to enable SCU commands */
-	status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_ACTIVE);
-	if (status < 0)
-		goto error;
-
-	if (!state->m_DRXK_A3_ROM_CODE) {
-		/* AGCInit() is not done for DVBT, so set agcFastClipCtrlDelay  */
-		status = write16(state, SCU_RAM_AGC_FAST_CLP_CTRL_DELAY__A, state->m_dvbtIfAgcCfg.FastClipCtrlDelay);
-		if (status < 0)
-			goto error;
-	}
-
-	/* OFDM_SC setup */
-#ifdef COMPILE_FOR_NONRT
-	status = write16(state, OFDM_SC_RA_RAM_BE_OPT_DELAY__A, 1);
-	if (status < 0)
-		goto error;
-	status = write16(state, OFDM_SC_RA_RAM_BE_OPT_INIT_DELAY__A, 2);
-	if (status < 0)
-		goto error;
-#endif
-
-	/* FEC setup */
-	status = write16(state, FEC_DI_INPUT_CTL__A, 1);	/* OFDM input */
-	if (status < 0)
-		goto error;
-
-
-#ifdef COMPILE_FOR_NONRT
-	status = write16(state, FEC_RS_MEASUREMENT_PERIOD__A, 0x400);
-	if (status < 0)
-		goto error;
-#else
-	status = write16(state, FEC_RS_MEASUREMENT_PERIOD__A, 0x1000);
-	if (status < 0)
-		goto error;
-#endif
-	status = write16(state, FEC_RS_MEASUREMENT_PRESCALE__A, 0x0001);
-	if (status < 0)
-		goto error;
-
-	/* Setup MPEG bus */
-	status = MPEGTSDtoSetup(state, OM_DVBT);
-	if (status < 0)
-		goto error;
-	/* Set DVBT Presets */
-	status = DVBTActivatePresets(state);
-	if (status < 0)
-		goto error;
-
-error:
-	if (status < 0)
-		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
-	return status;
-}
-
-/*============================================================================*/
-/**
-* \brief Start dvbt demodulating for channel.
-* \param demod instance of demodulator.
-* \return DRXStatus_t.
-*/
-static int DVBTStart(struct drxk_state *state)
-{
-	u16 param1;
-	int status;
-	/* DRXKOfdmScCmd_t scCmd; */
-
-	dprintk(1, "\n");
-	/* Start correct processes to get in lock */
-	/* DRXK: OFDM_SC_RA_RAM_PROC_LOCKTRACK is no longer in mapfile! */
-	param1 = OFDM_SC_RA_RAM_LOCKTRACK_MIN;
-	status = DVBTScCommand(state, OFDM_SC_RA_RAM_CMD_PROC_START, 0, OFDM_SC_RA_RAM_SW_EVENT_RUN_NMASK__M, param1, 0, 0, 0);
-	if (status < 0)
-		goto error;
-	/* Start FEC OC */
-	status = MPEGTSStart(state);
-	if (status < 0)
-		goto error;
-	status = write16(state, FEC_COMM_EXEC__A, FEC_COMM_EXEC_ACTIVE);
-	if (status < 0)
-		goto error;
-error:
-	if (status < 0)
-		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
-	return status;
-}
-
-
-/*============================================================================*/
-
-/**
-* \brief Set up dvbt demodulator for channel.
-* \param demod instance of demodulator.
-* \return DRXStatus_t.
-* // original DVBTSetChannel()
-*/
-static int SetDVBT(struct drxk_state *state, u16 IntermediateFreqkHz,
-		   s32 tunerFreqOffset)
-{
-	u16 cmdResult = 0;
-	u16 transmissionParams = 0;
-	u16 operationMode = 0;
-	u32 iqmRcRateOfs = 0;
-	u32 bandwidth = 0;
-	u16 param1;
-	int status;
-
-	dprintk(1, "IF =%d, TFO = %d\n", IntermediateFreqkHz, tunerFreqOffset);
-
-	status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM | SCU_RAM_COMMAND_CMD_DEMOD_STOP, 0, NULL, 1, &cmdResult);
-	if (status < 0)
-		goto error;
-
-	/* Halt SCU to enable safe non-atomic accesses */
-	status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_HOLD);
-	if (status < 0)
-		goto error;
-
-	/* Stop processors */
-	status = write16(state, OFDM_SC_COMM_EXEC__A, OFDM_SC_COMM_EXEC_STOP);
-	if (status < 0)
-		goto error;
-	status = write16(state, OFDM_LC_COMM_EXEC__A, OFDM_LC_COMM_EXEC_STOP);
-	if (status < 0)
-		goto error;
-
-	/* Mandatory fix, always stop CP, required to set spl offset back to
-		hardware default (is set to 0 by ucode during pilot detection */
-	status = write16(state, OFDM_CP_COMM_EXEC__A, OFDM_CP_COMM_EXEC_STOP);
-	if (status < 0)
-		goto error;
-
-	/*== Write channel settings to device =====================================*/
-
-	/* mode */
-	switch (state->props.transmission_mode) {
-	case TRANSMISSION_MODE_AUTO:
-	default:
-		operationMode |= OFDM_SC_RA_RAM_OP_AUTO_MODE__M;
-		/* fall through , try first guess DRX_FFTMODE_8K */
-	case TRANSMISSION_MODE_8K:
-		transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_MODE_8K;
-		break;
-	case TRANSMISSION_MODE_2K:
-		transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_MODE_2K;
-		break;
-	}
-
-	/* guard */
-	switch (state->props.guard_interval) {
-	default:
-	case GUARD_INTERVAL_AUTO:
-		operationMode |= OFDM_SC_RA_RAM_OP_AUTO_GUARD__M;
-		/* fall through , try first guess DRX_GUARD_1DIV4 */
-	case GUARD_INTERVAL_1_4:
-		transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_4;
-		break;
-	case GUARD_INTERVAL_1_32:
-		transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_32;
-		break;
-	case GUARD_INTERVAL_1_16:
-		transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_16;
-		break;
-	case GUARD_INTERVAL_1_8:
-		transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_8;
-		break;
-	}
-
-	/* hierarchy */
-	switch (state->props.hierarchy) {
-	case HIERARCHY_AUTO:
-	case HIERARCHY_NONE:
-	default:
-		operationMode |= OFDM_SC_RA_RAM_OP_AUTO_HIER__M;
-		/* fall through , try first guess SC_RA_RAM_OP_PARAM_HIER_NO */
-		/* transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_HIER_NO; */
-		/* break; */
-	case HIERARCHY_1:
-		transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_HIER_A1;
-		break;
-	case HIERARCHY_2:
-		transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_HIER_A2;
-		break;
-	case HIERARCHY_4:
-		transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_HIER_A4;
-		break;
-	}
-
-
-	/* modulation */
-	switch (state->props.modulation) {
-	case QAM_AUTO:
-	default:
-		operationMode |= OFDM_SC_RA_RAM_OP_AUTO_CONST__M;
-		/* fall through , try first guess DRX_CONSTELLATION_QAM64 */
-	case QAM_64:
-		transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_CONST_QAM64;
-		break;
-	case QPSK:
-		transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_CONST_QPSK;
-		break;
-	case QAM_16:
-		transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_CONST_QAM16;
-		break;
-	}
-#if 0
-	/* No hierachical channels support in BDA */
-	/* Priority (only for hierarchical channels) */
-	switch (channel->priority) {
-	case DRX_PRIORITY_LOW:
-		transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_PRIO_LO;
-		WR16(devAddr, OFDM_EC_SB_PRIOR__A,
-			OFDM_EC_SB_PRIOR_LO);
-		break;
-	case DRX_PRIORITY_HIGH:
-		transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_PRIO_HI;
-		WR16(devAddr, OFDM_EC_SB_PRIOR__A,
-			OFDM_EC_SB_PRIOR_HI));
-		break;
-	case DRX_PRIORITY_UNKNOWN:	/* fall through */
-	default:
-		status = -EINVAL;
-		goto error;
-	}
-#else
-	/* Set Priorty high */
-	transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_PRIO_HI;
-	status = write16(state, OFDM_EC_SB_PRIOR__A, OFDM_EC_SB_PRIOR_HI);
-	if (status < 0)
-		goto error;
-#endif
-
-	/* coderate */
-	switch (state->props.code_rate_HP) {
-	case FEC_AUTO:
-	default:
-		operationMode |= OFDM_SC_RA_RAM_OP_AUTO_RATE__M;
-		/* fall through , try first guess DRX_CODERATE_2DIV3 */
-	case FEC_2_3:
-		transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_RATE_2_3;
-		break;
-	case FEC_1_2:
-		transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_RATE_1_2;
-		break;
-	case FEC_3_4:
-		transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_RATE_3_4;
-		break;
-	case FEC_5_6:
-		transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_RATE_5_6;
-		break;
-	case FEC_7_8:
-		transmissionParams |= OFDM_SC_RA_RAM_OP_PARAM_RATE_7_8;
-		break;
-	}
-
-	/* SAW filter selection: normaly not necesarry, but if wanted
-		the application can select a SAW filter via the driver by using UIOs */
-	/* First determine real bandwidth (Hz) */
-	/* Also set delay for impulse noise cruncher */
-	/* Also set parameters for EC_OC fix, note EC_OC_REG_TMD_HIL_MAR is changed
-		by SC for fix for some 8K,1/8 guard but is restored by InitEC and ResetEC
-		functions */
-	switch (state->props.bandwidth_hz) {
-	case 0:
-		state->props.bandwidth_hz = 8000000;
-		/* fall though */
-	case 8000000:
-		bandwidth = DRXK_BANDWIDTH_8MHZ_IN_HZ;
-		status = write16(state, OFDM_SC_RA_RAM_SRMM_FIX_FACT_8K__A, 3052);
-		if (status < 0)
-			goto error;
-		/* cochannel protection for PAL 8 MHz */
-		status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_LEFT__A, 7);
-		if (status < 0)
-			goto error;
-		status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_RIGHT__A, 7);
-		if (status < 0)
-			goto error;
-		status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_LEFT__A, 7);
-		if (status < 0)
-			goto error;
-		status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_RIGHT__A, 1);
-		if (status < 0)
-			goto error;
-		break;
-	case 7000000:
-		bandwidth = DRXK_BANDWIDTH_7MHZ_IN_HZ;
-		status = write16(state, OFDM_SC_RA_RAM_SRMM_FIX_FACT_8K__A, 3491);
-		if (status < 0)
-			goto error;
-		/* cochannel protection for PAL 7 MHz */
-		status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_LEFT__A, 8);
-		if (status < 0)
-			goto error;
-		status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_RIGHT__A, 8);
-		if (status < 0)
-			goto error;
-		status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_LEFT__A, 4);
-		if (status < 0)
-			goto error;
-		status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_RIGHT__A, 1);
-		if (status < 0)
-			goto error;
-		break;
-	case 6000000:
-		bandwidth = DRXK_BANDWIDTH_6MHZ_IN_HZ;
-		status = write16(state, OFDM_SC_RA_RAM_SRMM_FIX_FACT_8K__A, 4073);
-		if (status < 0)
-			goto error;
-		/* cochannel protection for NTSC 6 MHz */
-		status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_LEFT__A, 19);
-		if (status < 0)
-			goto error;
-		status = write16(state, OFDM_SC_RA_RAM_NI_INIT_8K_PER_RIGHT__A, 19);
-		if (status < 0)
-			goto error;
-		status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_LEFT__A, 14);
-		if (status < 0)
-			goto error;
-		status = write16(state, OFDM_SC_RA_RAM_NI_INIT_2K_PER_RIGHT__A, 1);
-		if (status < 0)
-			goto error;
-		break;
-	default:
-		status = -EINVAL;
-		goto error;
-	}
-
-	if (iqmRcRateOfs == 0) {
-		/* Now compute IQM_RC_RATE_OFS
-			(((SysFreq/BandWidth)/2)/2) -1) * 2^23)
-			=>
-			((SysFreq / BandWidth) * (2^21)) - (2^23)
-			*/
-		/* (SysFreq / BandWidth) * (2^28)  */
-		/* assert (MAX(sysClk)/MIN(bandwidth) < 16)
-			=> assert(MAX(sysClk) < 16*MIN(bandwidth))
-			=> assert(109714272 > 48000000) = true so Frac 28 can be used  */
-		iqmRcRateOfs = Frac28a((u32)
-					((state->m_sysClockFreq *
-						1000) / 3), bandwidth);
-		/* (SysFreq / BandWidth) * (2^21), rounding before truncating  */
-		if ((iqmRcRateOfs & 0x7fL) >= 0x40)
-			iqmRcRateOfs += 0x80L;
-		iqmRcRateOfs = iqmRcRateOfs >> 7;
-		/* ((SysFreq / BandWidth) * (2^21)) - (2^23)  */
-		iqmRcRateOfs = iqmRcRateOfs - (1 << 23);
-	}
-
-	iqmRcRateOfs &=
-		((((u32) IQM_RC_RATE_OFS_HI__M) <<
-		IQM_RC_RATE_OFS_LO__W) | IQM_RC_RATE_OFS_LO__M);
-	status = write32(state, IQM_RC_RATE_OFS_LO__A, iqmRcRateOfs);
-	if (status < 0)
-		goto error;
-
-	/* Bandwidth setting done */
-
-#if 0
-	status = DVBTSetFrequencyShift(demod, channel, tunerOffset);
-	if (status < 0)
-		goto error;
-#endif
-	status = SetFrequencyShifter(state, IntermediateFreqkHz, tunerFreqOffset, true);
-	if (status < 0)
-		goto error;
-
-	/*== Start SC, write channel settings to SC ===============================*/
-
-	/* Activate SCU to enable SCU commands */
-	status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_ACTIVE);
-	if (status < 0)
-		goto error;
-
-	/* Enable SC after setting all other parameters */
-	status = write16(state, OFDM_SC_COMM_STATE__A, 0);
-	if (status < 0)
-		goto error;
-	status = write16(state, OFDM_SC_COMM_EXEC__A, 1);
-	if (status < 0)
-		goto error;
-
-
-	status = scu_command(state, SCU_RAM_COMMAND_STANDARD_OFDM | SCU_RAM_COMMAND_CMD_DEMOD_START, 0, NULL, 1, &cmdResult);
-	if (status < 0)
-		goto error;
-
-	/* Write SC parameter registers, set all AUTO flags in operation mode */
-	param1 = (OFDM_SC_RA_RAM_OP_AUTO_MODE__M |
-			OFDM_SC_RA_RAM_OP_AUTO_GUARD__M |
-			OFDM_SC_RA_RAM_OP_AUTO_CONST__M |
-			OFDM_SC_RA_RAM_OP_AUTO_HIER__M |
-			OFDM_SC_RA_RAM_OP_AUTO_RATE__M);
-	status = DVBTScCommand(state, OFDM_SC_RA_RAM_CMD_SET_PREF_PARAM,
-				0, transmissionParams, param1, 0, 0, 0);
-	if (status < 0)
-		goto error;
-
-	if (!state->m_DRXK_A3_ROM_CODE)
-		status = DVBTCtrlSetSqiSpeed(state, &state->m_sqiSpeed);
-error:
-	if (status < 0)
-		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
-
-	return status;
-}
-
-
-/*============================================================================*/
-
-/**
-* \brief Retreive lock status .
-* \param demod    Pointer to demodulator instance.
-* \param lockStat Pointer to lock status structure.
-* \return DRXStatus_t.
-*
-*/
-static int GetDVBTLockStatus(struct drxk_state *state, u32 *pLockStatus)
-{
-	int status;
-	const u16 mpeg_lock_mask = (OFDM_SC_RA_RAM_LOCK_MPEG__M |
-				    OFDM_SC_RA_RAM_LOCK_FEC__M);
-	const u16 fec_lock_mask = (OFDM_SC_RA_RAM_LOCK_FEC__M);
-	const u16 demod_lock_mask = OFDM_SC_RA_RAM_LOCK_DEMOD__M;
-
-	u16 ScRaRamLock = 0;
-	u16 ScCommExec = 0;
-
-	dprintk(1, "\n");
-
-	*pLockStatus = NOT_LOCKED;
-	/* driver 0.9.0 */
-	/* Check if SC is running */
-	status = read16(state, OFDM_SC_COMM_EXEC__A, &ScCommExec);
-	if (status < 0)
-		goto end;
-	if (ScCommExec == OFDM_SC_COMM_EXEC_STOP)
-		goto end;
-
-	status = read16(state, OFDM_SC_RA_RAM_LOCK__A, &ScRaRamLock);
-	if (status < 0)
-		goto end;
-
-	if ((ScRaRamLock & mpeg_lock_mask) == mpeg_lock_mask)
-		*pLockStatus = MPEG_LOCK;
-	else if ((ScRaRamLock & fec_lock_mask) == fec_lock_mask)
-		*pLockStatus = FEC_LOCK;
-	else if ((ScRaRamLock & demod_lock_mask) == demod_lock_mask)
-		*pLockStatus = DEMOD_LOCK;
-	else if (ScRaRamLock & OFDM_SC_RA_RAM_LOCK_NODVBT__M)
-		*pLockStatus = NEVER_LOCK;
-end:
-	if (status < 0)
-		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
-
-	return status;
-}
-
-static int PowerUpQAM(struct drxk_state *state)
-{
-	enum DRXPowerMode powerMode = DRXK_POWER_DOWN_OFDM;
-	int status;
-
-	dprintk(1, "\n");
-	status = CtrlPowerMode(state, &powerMode);
-	if (status < 0)
-		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
-
-	return status;
-}
-
-
-/** Power Down QAM */
-static int PowerDownQAM(struct drxk_state *state)
-{
-	u16 data = 0;
-	u16 cmdResult;
-	int status = 0;
-
-	dprintk(1, "\n");
-	status = read16(state, SCU_COMM_EXEC__A, &data);
-	if (status < 0)
-		goto error;
-	if (data == SCU_COMM_EXEC_ACTIVE) {
-		/*
-			STOP demodulator
-			QAM and HW blocks
-			*/
-		/* stop all comstate->m_exec */
-		status = write16(state, QAM_COMM_EXEC__A, QAM_COMM_EXEC_STOP);
-		if (status < 0)
-			goto error;
-		status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_STOP, 0, NULL, 1, &cmdResult);
-		if (status < 0)
-			goto error;
-	}
-	/* powerdown AFE                   */
-	status = SetIqmAf(state, false);
-
-error:
-	if (status < 0)
-		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
-
-	return status;
-}
-
-/*============================================================================*/
-
-/**
-* \brief Setup of the QAM Measurement intervals for signal quality
-* \param demod instance of demod.
-* \param modulation current modulation.
-* \return DRXStatus_t.
-*
-*  NOTE:
-*  Take into account that for certain settings the errorcounters can overflow.
-*  The implementation does not check this.
-*
-*/
-static int SetQAMMeasurement(struct drxk_state *state,
-			     enum EDrxkConstellation modulation,
-			     u32 symbolRate)
-{
-	u32 fecBitsDesired = 0;	/* BER accounting period */
-	u32 fecRsPeriodTotal = 0;	/* Total period */
-	u16 fecRsPrescale = 0;	/* ReedSolomon Measurement Prescale */
-	u16 fecRsPeriod = 0;	/* Value for corresponding I2C register */
-	int status = 0;
-
-	dprintk(1, "\n");
-
-	fecRsPrescale = 1;
-	/* fecBitsDesired = symbolRate [kHz] *
-		FrameLenght [ms] *
-		(modulation + 1) *
-		SyncLoss (== 1) *
-		ViterbiLoss (==1)
-		*/
-	switch (modulation) {
-	case DRX_CONSTELLATION_QAM16:
-		fecBitsDesired = 4 * symbolRate;
-		break;
-	case DRX_CONSTELLATION_QAM32:
-		fecBitsDesired = 5 * symbolRate;
-		break;
-	case DRX_CONSTELLATION_QAM64:
-		fecBitsDesired = 6 * symbolRate;
-		break;
-	case DRX_CONSTELLATION_QAM128:
-		fecBitsDesired = 7 * symbolRate;
-		break;
-	case DRX_CONSTELLATION_QAM256:
-		fecBitsDesired = 8 * symbolRate;
-		break;
-	default:
-		status = -EINVAL;
-	}
-	if (status < 0)
-		goto error;
-
-	fecBitsDesired /= 1000;	/* symbolRate [Hz] -> symbolRate [kHz]  */
-	fecBitsDesired *= 500;	/* meas. period [ms] */
-
-	/* Annex A/C: bits/RsPeriod = 204 * 8 = 1632 */
-	/* fecRsPeriodTotal = fecBitsDesired / 1632 */
-	fecRsPeriodTotal = (fecBitsDesired / 1632UL) + 1;	/* roughly ceil */
-
-	/* fecRsPeriodTotal =  fecRsPrescale * fecRsPeriod  */
-	fecRsPrescale = 1 + (u16) (fecRsPeriodTotal >> 16);
-	if (fecRsPrescale == 0) {
-		/* Divide by zero (though impossible) */
-		status = -EINVAL;
-		if (status < 0)
-			goto error;
-	}
-	fecRsPeriod =
-		((u16) fecRsPeriodTotal +
-		(fecRsPrescale >> 1)) / fecRsPrescale;
-
-	/* write corresponding registers */
-	status = write16(state, FEC_RS_MEASUREMENT_PERIOD__A, fecRsPeriod);
-	if (status < 0)
-		goto error;
-	status = write16(state, FEC_RS_MEASUREMENT_PRESCALE__A, fecRsPrescale);
-	if (status < 0)
-		goto error;
-	status = write16(state, FEC_OC_SNC_FAIL_PERIOD__A, fecRsPeriod);
-error:
-	if (status < 0)
-		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
-	return status;
-}
-
-static int SetQAM16(struct drxk_state *state)
-{
-	int status = 0;
-
-	dprintk(1, "\n");
-	/* QAM Equalizer Setup */
-	/* Equalizer */
-	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD0__A, 13517);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD1__A, 13517);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD2__A, 13517);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD3__A, 13517);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD4__A, 13517);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD5__A, 13517);
-	if (status < 0)
-		goto error;
-	/* Decision Feedback Equalizer */
-	status = write16(state, QAM_DQ_QUAL_FUN0__A, 2);
-	if (status < 0)
-		goto error;
-	status = write16(state, QAM_DQ_QUAL_FUN1__A, 2);
-	if (status < 0)
-		goto error;
-	status = write16(state, QAM_DQ_QUAL_FUN2__A, 2);
-	if (status < 0)
-		goto error;
-	status = write16(state, QAM_DQ_QUAL_FUN3__A, 2);
-	if (status < 0)
-		goto error;
-	status = write16(state, QAM_DQ_QUAL_FUN4__A, 2);
-	if (status < 0)
-		goto error;
-	status = write16(state, QAM_DQ_QUAL_FUN5__A, 0);
-	if (status < 0)
-		goto error;
-
-	status = write16(state, QAM_SY_SYNC_HWM__A, 5);
-	if (status < 0)
-		goto error;
-	status = write16(state, QAM_SY_SYNC_AWM__A, 4);
-	if (status < 0)
-		goto error;
-	status = write16(state, QAM_SY_SYNC_LWM__A, 3);
-	if (status < 0)
-		goto error;
-
-	/* QAM Slicer Settings */
-	status = write16(state, SCU_RAM_QAM_SL_SIG_POWER__A, DRXK_QAM_SL_SIG_POWER_QAM16);
-	if (status < 0)
-		goto error;
-
-	/* QAM Loop Controller Coeficients */
-	status = write16(state, SCU_RAM_QAM_LC_CA_FINE__A, 15);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_CA_COARSE__A, 40);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_EP_FINE__A, 12);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_EP_MEDIUM__A, 24);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_EP_COARSE__A, 24);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_EI_FINE__A, 12);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_EI_MEDIUM__A, 16);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_EI_COARSE__A, 16);
-	if (status < 0)
-		goto error;
-
-	status = write16(state, SCU_RAM_QAM_LC_CP_FINE__A, 5);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_CP_MEDIUM__A, 20);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_CP_COARSE__A, 80);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_CI_FINE__A, 5);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_CI_MEDIUM__A, 20);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_CI_COARSE__A, 50);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_CF_FINE__A, 16);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_CF_MEDIUM__A, 16);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_CF_COARSE__A, 32);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_CF1_FINE__A, 5);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_CF1_MEDIUM__A, 10);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_CF1_COARSE__A, 10);
-	if (status < 0)
-		goto error;
-
-
-	/* QAM State Machine (FSM) Thresholds */
-
-	status = write16(state, SCU_RAM_QAM_FSM_RTH__A, 140);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_FSM_FTH__A, 50);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_FSM_CTH__A, 95);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_FSM_PTH__A, 120);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_FSM_QTH__A, 230);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_FSM_MTH__A, 105);
-	if (status < 0)
-		goto error;
-
-	status = write16(state, SCU_RAM_QAM_FSM_RATE_LIM__A, 40);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_FSM_COUNT_LIM__A, 4);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_FSM_FREQ_LIM__A, 24);
-	if (status < 0)
-		goto error;
-
-
-	/* QAM FSM Tracking Parameters */
-
-	status = write16(state, SCU_RAM_QAM_FSM_MEDIAN_AV_MULT__A, (u16) 16);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_FSM_RADIUS_AV_LIMIT__A, (u16) 220);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET1__A, (u16) 25);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET2__A, (u16) 6);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET3__A, (u16) -24);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET4__A, (u16) -65);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16) -127);
-	if (status < 0)
-		goto error;
-
-error:
-	if (status < 0)
-		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
-	return status;
-}
-
-/*============================================================================*/
-
-/**
-* \brief QAM32 specific setup
-* \param demod instance of demod.
-* \return DRXStatus_t.
-*/
-static int SetQAM32(struct drxk_state *state)
-{
-	int status = 0;
-
-	dprintk(1, "\n");
-
-	/* QAM Equalizer Setup */
-	/* Equalizer */
-	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD0__A, 6707);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD1__A, 6707);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD2__A, 6707);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD3__A, 6707);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD4__A, 6707);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD5__A, 6707);
-	if (status < 0)
-		goto error;
-
-	/* Decision Feedback Equalizer */
-	status = write16(state, QAM_DQ_QUAL_FUN0__A, 3);
-	if (status < 0)
-		goto error;
-	status = write16(state, QAM_DQ_QUAL_FUN1__A, 3);
-	if (status < 0)
-		goto error;
-	status = write16(state, QAM_DQ_QUAL_FUN2__A, 3);
-	if (status < 0)
-		goto error;
-	status = write16(state, QAM_DQ_QUAL_FUN3__A, 3);
-	if (status < 0)
-		goto error;
-	status = write16(state, QAM_DQ_QUAL_FUN4__A, 3);
-	if (status < 0)
-		goto error;
-	status = write16(state, QAM_DQ_QUAL_FUN5__A, 0);
-	if (status < 0)
-		goto error;
-
-	status = write16(state, QAM_SY_SYNC_HWM__A, 6);
-	if (status < 0)
-		goto error;
-	status = write16(state, QAM_SY_SYNC_AWM__A, 5);
-	if (status < 0)
-		goto error;
-	status = write16(state, QAM_SY_SYNC_LWM__A, 3);
-	if (status < 0)
-		goto error;
-
-	/* QAM Slicer Settings */
-
-	status = write16(state, SCU_RAM_QAM_SL_SIG_POWER__A, DRXK_QAM_SL_SIG_POWER_QAM32);
-	if (status < 0)
-		goto error;
-
-
-	/* QAM Loop Controller Coeficients */
-
-	status = write16(state, SCU_RAM_QAM_LC_CA_FINE__A, 15);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_CA_COARSE__A, 40);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_EP_FINE__A, 12);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_EP_MEDIUM__A, 24);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_EP_COARSE__A, 24);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_EI_FINE__A, 12);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_EI_MEDIUM__A, 16);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_EI_COARSE__A, 16);
-	if (status < 0)
-		goto error;
-
-	status = write16(state, SCU_RAM_QAM_LC_CP_FINE__A, 5);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_CP_MEDIUM__A, 20);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_CP_COARSE__A, 80);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_CI_FINE__A, 5);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_CI_MEDIUM__A, 20);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_CI_COARSE__A, 50);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_CF_FINE__A, 16);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_CF_MEDIUM__A, 16);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_CF_COARSE__A, 16);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_CF1_FINE__A, 5);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_CF1_MEDIUM__A, 10);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_CF1_COARSE__A, 0);
-	if (status < 0)
-		goto error;
-
-
-	/* QAM State Machine (FSM) Thresholds */
-
-	status = write16(state, SCU_RAM_QAM_FSM_RTH__A, 90);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_FSM_FTH__A, 50);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_FSM_CTH__A, 80);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_FSM_PTH__A, 100);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_FSM_QTH__A, 170);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_FSM_MTH__A, 100);
-	if (status < 0)
-		goto error;
-
-	status = write16(state, SCU_RAM_QAM_FSM_RATE_LIM__A, 40);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_FSM_COUNT_LIM__A, 4);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_FSM_FREQ_LIM__A, 10);
-	if (status < 0)
-		goto error;
-
-
-	/* QAM FSM Tracking Parameters */
-
-	status = write16(state, SCU_RAM_QAM_FSM_MEDIAN_AV_MULT__A, (u16) 12);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_FSM_RADIUS_AV_LIMIT__A, (u16) 140);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET1__A, (u16) -8);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET2__A, (u16) -16);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET3__A, (u16) -26);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET4__A, (u16) -56);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16) -86);
-error:
-	if (status < 0)
-		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
-	return status;
-}
-
-/*============================================================================*/
-
-/**
-* \brief QAM64 specific setup
-* \param demod instance of demod.
-* \return DRXStatus_t.
-*/
-static int SetQAM64(struct drxk_state *state)
-{
-	int status = 0;
-
-	dprintk(1, "\n");
-	/* QAM Equalizer Setup */
-	/* Equalizer */
-	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD0__A, 13336);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD1__A, 12618);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD2__A, 11988);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD3__A, 13809);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD4__A, 13809);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD5__A, 15609);
-	if (status < 0)
-		goto error;
-
-	/* Decision Feedback Equalizer */
-	status = write16(state, QAM_DQ_QUAL_FUN0__A, 4);
-	if (status < 0)
-		goto error;
-	status = write16(state, QAM_DQ_QUAL_FUN1__A, 4);
-	if (status < 0)
-		goto error;
-	status = write16(state, QAM_DQ_QUAL_FUN2__A, 4);
-	if (status < 0)
-		goto error;
-	status = write16(state, QAM_DQ_QUAL_FUN3__A, 4);
-	if (status < 0)
-		goto error;
-	status = write16(state, QAM_DQ_QUAL_FUN4__A, 3);
-	if (status < 0)
-		goto error;
-	status = write16(state, QAM_DQ_QUAL_FUN5__A, 0);
-	if (status < 0)
-		goto error;
-
-	status = write16(state, QAM_SY_SYNC_HWM__A, 5);
-	if (status < 0)
-		goto error;
-	status = write16(state, QAM_SY_SYNC_AWM__A, 4);
-	if (status < 0)
-		goto error;
-	status = write16(state, QAM_SY_SYNC_LWM__A, 3);
-	if (status < 0)
-		goto error;
-
-	/* QAM Slicer Settings */
-	status = write16(state, SCU_RAM_QAM_SL_SIG_POWER__A, DRXK_QAM_SL_SIG_POWER_QAM64);
-	if (status < 0)
-		goto error;
-
-
-	/* QAM Loop Controller Coeficients */
-
-	status = write16(state, SCU_RAM_QAM_LC_CA_FINE__A, 15);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_CA_COARSE__A, 40);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_EP_FINE__A, 12);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_EP_MEDIUM__A, 24);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_EP_COARSE__A, 24);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_EI_FINE__A, 12);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_EI_MEDIUM__A, 16);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_EI_COARSE__A, 16);
-	if (status < 0)
-		goto error;
-
-	status = write16(state, SCU_RAM_QAM_LC_CP_FINE__A, 5);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_CP_MEDIUM__A, 30);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_CP_COARSE__A, 100);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_CI_FINE__A, 5);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_CI_MEDIUM__A, 30);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_CI_COARSE__A, 50);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_CF_FINE__A, 16);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_CF_MEDIUM__A, 25);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_CF_COARSE__A, 48);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_CF1_FINE__A, 5);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_CF1_MEDIUM__A, 10);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_CF1_COARSE__A, 10);
-	if (status < 0)
-		goto error;
-
-
-	/* QAM State Machine (FSM) Thresholds */
-
-	status = write16(state, SCU_RAM_QAM_FSM_RTH__A, 100);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_FSM_FTH__A, 60);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_FSM_CTH__A, 80);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_FSM_PTH__A, 110);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_FSM_QTH__A, 200);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_FSM_MTH__A, 95);
-	if (status < 0)
-		goto error;
-
-	status = write16(state, SCU_RAM_QAM_FSM_RATE_LIM__A, 40);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_FSM_COUNT_LIM__A, 4);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_FSM_FREQ_LIM__A, 15);
-	if (status < 0)
-		goto error;
-
-
-	/* QAM FSM Tracking Parameters */
-
-	status = write16(state, SCU_RAM_QAM_FSM_MEDIAN_AV_MULT__A, (u16) 12);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_FSM_RADIUS_AV_LIMIT__A, (u16) 141);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET1__A, (u16) 7);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET2__A, (u16) 0);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET3__A, (u16) -15);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET4__A, (u16) -45);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16) -80);
-error:
-	if (status < 0)
-		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
-
-	return status;
-}
-
-/*============================================================================*/
-
-/**
-* \brief QAM128 specific setup
-* \param demod: instance of demod.
-* \return DRXStatus_t.
-*/
-static int SetQAM128(struct drxk_state *state)
-{
-	int status = 0;
-
-	dprintk(1, "\n");
-	/* QAM Equalizer Setup */
-	/* Equalizer */
-	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD0__A, 6564);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD1__A, 6598);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD2__A, 6394);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD3__A, 6409);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD4__A, 6656);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD5__A, 7238);
-	if (status < 0)
-		goto error;
-
-	/* Decision Feedback Equalizer */
-	status = write16(state, QAM_DQ_QUAL_FUN0__A, 6);
-	if (status < 0)
-		goto error;
-	status = write16(state, QAM_DQ_QUAL_FUN1__A, 6);
-	if (status < 0)
-		goto error;
-	status = write16(state, QAM_DQ_QUAL_FUN2__A, 6);
-	if (status < 0)
-		goto error;
-	status = write16(state, QAM_DQ_QUAL_FUN3__A, 6);
-	if (status < 0)
-		goto error;
-	status = write16(state, QAM_DQ_QUAL_FUN4__A, 5);
-	if (status < 0)
-		goto error;
-	status = write16(state, QAM_DQ_QUAL_FUN5__A, 0);
-	if (status < 0)
-		goto error;
-
-	status = write16(state, QAM_SY_SYNC_HWM__A, 6);
-	if (status < 0)
-		goto error;
-	status = write16(state, QAM_SY_SYNC_AWM__A, 5);
-	if (status < 0)
-		goto error;
-	status = write16(state, QAM_SY_SYNC_LWM__A, 3);
-	if (status < 0)
-		goto error;
-
-
-	/* QAM Slicer Settings */
-
-	status = write16(state, SCU_RAM_QAM_SL_SIG_POWER__A, DRXK_QAM_SL_SIG_POWER_QAM128);
-	if (status < 0)
-		goto error;
-
-
-	/* QAM Loop Controller Coeficients */
-
-	status = write16(state, SCU_RAM_QAM_LC_CA_FINE__A, 15);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_CA_COARSE__A, 40);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_EP_FINE__A, 12);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_EP_MEDIUM__A, 24);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_EP_COARSE__A, 24);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_EI_FINE__A, 12);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_EI_MEDIUM__A, 16);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_EI_COARSE__A, 16);
-	if (status < 0)
-		goto error;
-
-	status = write16(state, SCU_RAM_QAM_LC_CP_FINE__A, 5);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_CP_MEDIUM__A, 40);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_CP_COARSE__A, 120);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_CI_FINE__A, 5);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_CI_MEDIUM__A, 40);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_CI_COARSE__A, 60);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_CF_FINE__A, 16);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_CF_MEDIUM__A, 25);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_CF_COARSE__A, 64);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_CF1_FINE__A, 5);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_CF1_MEDIUM__A, 10);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_CF1_COARSE__A, 0);
-	if (status < 0)
-		goto error;
-
-
-	/* QAM State Machine (FSM) Thresholds */
-
-	status = write16(state, SCU_RAM_QAM_FSM_RTH__A, 50);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_FSM_FTH__A, 60);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_FSM_CTH__A, 80);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_FSM_PTH__A, 100);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_FSM_QTH__A, 140);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_FSM_MTH__A, 100);
-	if (status < 0)
-		goto error;
-
-	status = write16(state, SCU_RAM_QAM_FSM_RATE_LIM__A, 40);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_FSM_COUNT_LIM__A, 5);
-	if (status < 0)
-		goto error;
-
-	status = write16(state, SCU_RAM_QAM_FSM_FREQ_LIM__A, 12);
-	if (status < 0)
-		goto error;
-
-	/* QAM FSM Tracking Parameters */
-
-	status = write16(state, SCU_RAM_QAM_FSM_MEDIAN_AV_MULT__A, (u16) 8);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_FSM_RADIUS_AV_LIMIT__A, (u16) 65);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET1__A, (u16) 5);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET2__A, (u16) 3);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET3__A, (u16) -1);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET4__A, (u16) -12);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16) -23);
-error:
-	if (status < 0)
-		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
-
-	return status;
-}
-
-/*============================================================================*/
-
-/**
-* \brief QAM256 specific setup
-* \param demod: instance of demod.
-* \return DRXStatus_t.
-*/
-static int SetQAM256(struct drxk_state *state)
-{
-	int status = 0;
-
-	dprintk(1, "\n");
-	/* QAM Equalizer Setup */
-	/* Equalizer */
-	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD0__A, 11502);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD1__A, 12084);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD2__A, 12543);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD3__A, 12931);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD4__A, 13629);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_EQ_CMA_RAD5__A, 15385);
-	if (status < 0)
-		goto error;
-
-	/* Decision Feedback Equalizer */
-	status = write16(state, QAM_DQ_QUAL_FUN0__A, 8);
-	if (status < 0)
-		goto error;
-	status = write16(state, QAM_DQ_QUAL_FUN1__A, 8);
-	if (status < 0)
-		goto error;
-	status = write16(state, QAM_DQ_QUAL_FUN2__A, 8);
-	if (status < 0)
-		goto error;
-	status = write16(state, QAM_DQ_QUAL_FUN3__A, 8);
-	if (status < 0)
-		goto error;
-	status = write16(state, QAM_DQ_QUAL_FUN4__A, 6);
-	if (status < 0)
-		goto error;
-	status = write16(state, QAM_DQ_QUAL_FUN5__A, 0);
-	if (status < 0)
-		goto error;
-
-	status = write16(state, QAM_SY_SYNC_HWM__A, 5);
-	if (status < 0)
-		goto error;
-	status = write16(state, QAM_SY_SYNC_AWM__A, 4);
-	if (status < 0)
-		goto error;
-	status = write16(state, QAM_SY_SYNC_LWM__A, 3);
-	if (status < 0)
-		goto error;
-
-	/* QAM Slicer Settings */
-
-	status = write16(state, SCU_RAM_QAM_SL_SIG_POWER__A, DRXK_QAM_SL_SIG_POWER_QAM256);
-	if (status < 0)
-		goto error;
-
-
-	/* QAM Loop Controller Coeficients */
-
-	status = write16(state, SCU_RAM_QAM_LC_CA_FINE__A, 15);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_CA_COARSE__A, 40);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_EP_FINE__A, 12);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_EP_MEDIUM__A, 24);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_EP_COARSE__A, 24);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_EI_FINE__A, 12);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_EI_MEDIUM__A, 16);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_EI_COARSE__A, 16);
-	if (status < 0)
-		goto error;
-
-	status = write16(state, SCU_RAM_QAM_LC_CP_FINE__A, 5);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_CP_MEDIUM__A, 50);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_CP_COARSE__A, 250);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_CI_FINE__A, 5);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_CI_MEDIUM__A, 50);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_CI_COARSE__A, 125);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_CF_FINE__A, 16);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_CF_MEDIUM__A, 25);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_CF_COARSE__A, 48);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_CF1_FINE__A, 5);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_CF1_MEDIUM__A, 10);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_LC_CF1_COARSE__A, 10);
-	if (status < 0)
-		goto error;
-
-
-	/* QAM State Machine (FSM) Thresholds */
-
-	status = write16(state, SCU_RAM_QAM_FSM_RTH__A, 50);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_FSM_FTH__A, 60);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_FSM_CTH__A, 80);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_FSM_PTH__A, 100);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_FSM_QTH__A, 150);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_FSM_MTH__A, 110);
-	if (status < 0)
-		goto error;
-
-	status = write16(state, SCU_RAM_QAM_FSM_RATE_LIM__A, 40);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_FSM_COUNT_LIM__A, 4);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_FSM_FREQ_LIM__A, 12);
-	if (status < 0)
-		goto error;
-
-
-	/* QAM FSM Tracking Parameters */
-
-	status = write16(state, SCU_RAM_QAM_FSM_MEDIAN_AV_MULT__A, (u16) 8);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_FSM_RADIUS_AV_LIMIT__A, (u16) 74);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET1__A, (u16) 18);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET2__A, (u16) 13);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET3__A, (u16) 7);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET4__A, (u16) 0);
-	if (status < 0)
-		goto error;
-	status = write16(state, SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A, (u16) -8);
-error:
-	if (status < 0)
-		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
-	return status;
-}
-
-
-/*============================================================================*/
-/**
-* \brief Reset QAM block.
-* \param demod:   instance of demod.
-* \param channel: pointer to channel data.
-* \return DRXStatus_t.
-*/
-static int QAMResetQAM(struct drxk_state *state)
-{
-	int status;
-	u16 cmdResult;
-
-	dprintk(1, "\n");
-	/* Stop QAM comstate->m_exec */
-	status = write16(state, QAM_COMM_EXEC__A, QAM_COMM_EXEC_STOP);
-	if (status < 0)
-		goto error;
-
-	status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_RESET, 0, NULL, 1, &cmdResult);
-error:
-	if (status < 0)
-		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
-	return status;
-}
-
-/*============================================================================*/
-
-/**
-* \brief Set QAM symbolrate.
-* \param demod:   instance of demod.
-* \param channel: pointer to channel data.
-* \return DRXStatus_t.
-*/
-static int QAMSetSymbolrate(struct drxk_state *state)
-{
-	u32 adcFrequency = 0;
-	u32 symbFreq = 0;
-	u32 iqmRcRate = 0;
-	u16 ratesel = 0;
-	u32 lcSymbRate = 0;
-	int status;
-
-	dprintk(1, "\n");
-	/* Select & calculate correct IQM rate */
-	adcFrequency = (state->m_sysClockFreq * 1000) / 3;
-	ratesel = 0;
-	/* printk(KERN_DEBUG "drxk: SR %d\n", state->props.symbol_rate); */
-	if (state->props.symbol_rate <= 1188750)
-		ratesel = 3;
-	else if (state->props.symbol_rate <= 2377500)
-		ratesel = 2;
-	else if (state->props.symbol_rate <= 4755000)
-		ratesel = 1;
-	status = write16(state, IQM_FD_RATESEL__A, ratesel);
-	if (status < 0)
-		goto error;
-
-	/*
-		IqmRcRate = ((Fadc / (symbolrate * (4<<ratesel))) - 1) * (1<<23)
-		*/
-	symbFreq = state->props.symbol_rate * (1 << ratesel);
-	if (symbFreq == 0) {
-		/* Divide by zero */
-		status = -EINVAL;
-		goto error;
-	}
-	iqmRcRate = (adcFrequency / symbFreq) * (1 << 21) +
-		(Frac28a((adcFrequency % symbFreq), symbFreq) >> 7) -
-		(1 << 23);
-	status = write32(state, IQM_RC_RATE_OFS_LO__A, iqmRcRate);
-	if (status < 0)
-		goto error;
-	state->m_iqmRcRate = iqmRcRate;
-	/*
-		LcSymbFreq = round (.125 *  symbolrate / adcFreq * (1<<15))
-		*/
-	symbFreq = state->props.symbol_rate;
-	if (adcFrequency == 0) {
-		/* Divide by zero */
-		status = -EINVAL;
-		goto error;
-	}
-	lcSymbRate = (symbFreq / adcFrequency) * (1 << 12) +
-		(Frac28a((symbFreq % adcFrequency), adcFrequency) >>
-		16);
-	if (lcSymbRate > 511)
-		lcSymbRate = 511;
-	status = write16(state, QAM_LC_SYMBOL_FREQ__A, (u16) lcSymbRate);
-
-error:
-	if (status < 0)
-		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
-	return status;
-}
-
-/*============================================================================*/
-
-/**
-* \brief Get QAM lock status.
-* \param demod:   instance of demod.
-* \param channel: pointer to channel data.
-* \return DRXStatus_t.
-*/
-
-static int GetQAMLockStatus(struct drxk_state *state, u32 *pLockStatus)
-{
-	int status;
-	u16 Result[2] = { 0, 0 };
-
-	dprintk(1, "\n");
-	*pLockStatus = NOT_LOCKED;
-	status = scu_command(state,
-			SCU_RAM_COMMAND_STANDARD_QAM |
-			SCU_RAM_COMMAND_CMD_DEMOD_GET_LOCK, 0, NULL, 2,
-			Result);
-	if (status < 0)
-		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
-
-	if (Result[1] < SCU_RAM_QAM_LOCKED_LOCKED_DEMOD_LOCKED) {
-		/* 0x0000 NOT LOCKED */
-	} else if (Result[1] < SCU_RAM_QAM_LOCKED_LOCKED_LOCKED) {
-		/* 0x4000 DEMOD LOCKED */
-		*pLockStatus = DEMOD_LOCK;
-	} else if (Result[1] < SCU_RAM_QAM_LOCKED_LOCKED_NEVER_LOCK) {
-		/* 0x8000 DEMOD + FEC LOCKED (system lock) */
-		*pLockStatus = MPEG_LOCK;
-	} else {
-		/* 0xC000 NEVER LOCKED */
-		/* (system will never be able to lock to the signal) */
-		/* TODO: check this, intermediate & standard specific lock states are not
-		   taken into account here */
-		*pLockStatus = NEVER_LOCK;
-	}
-	return status;
-}
-
-#define QAM_MIRROR__M         0x03
-#define QAM_MIRROR_NORMAL     0x00
-#define QAM_MIRRORED          0x01
-#define QAM_MIRROR_AUTO_ON    0x02
-#define QAM_LOCKRANGE__M      0x10
-#define QAM_LOCKRANGE_NORMAL  0x10
-
-static int QAMDemodulatorCommand(struct drxk_state *state,
-				 int numberOfParameters)
-{
-	int status;
-	u16 cmdResult;
-	u16 setParamParameters[4] = { 0, 0, 0, 0 };
-
-	setParamParameters[0] = state->m_Constellation;	/* modulation     */
-	setParamParameters[1] = DRXK_QAM_I12_J17;	/* interleave mode   */
-
-	if (numberOfParameters == 2) {
-		u16 setEnvParameters[1] = { 0 };
-
-		if (state->m_OperationMode == OM_QAM_ITU_C)
-			setEnvParameters[0] = QAM_TOP_ANNEX_C;
-		else
-			setEnvParameters[0] = QAM_TOP_ANNEX_A;
-
-		status = scu_command(state,
-				     SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_SET_ENV,
-				     1, setEnvParameters, 1, &cmdResult);
-		if (status < 0)
-			goto error;
-
-		status = scu_command(state,
-				     SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_SET_PARAM,
-				     numberOfParameters, setParamParameters,
-				     1, &cmdResult);
-	} else if (numberOfParameters == 4) {
-		if (state->m_OperationMode == OM_QAM_ITU_C)
-			setParamParameters[2] = QAM_TOP_ANNEX_C;
-		else
-			setParamParameters[2] = QAM_TOP_ANNEX_A;
-
-		setParamParameters[3] |= (QAM_MIRROR_AUTO_ON);
-		/* Env parameters */
-		/* check for LOCKRANGE Extented */
-		/* setParamParameters[3] |= QAM_LOCKRANGE_NORMAL; */
-
-		status = scu_command(state,
-				     SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_SET_PARAM,
-				     numberOfParameters, setParamParameters,
-				     1, &cmdResult);
-	} else {
-		printk(KERN_WARNING "drxk: Unknown QAM demodulator parameter "
-			"count %d\n", numberOfParameters);
-	}
-
-error:
-	if (status < 0)
-		printk(KERN_WARNING "drxk: Warning %d on %s\n",
-		       status, __func__);
-	return status;
-}
-
-static int SetQAM(struct drxk_state *state, u16 IntermediateFreqkHz,
-		  s32 tunerFreqOffset)
-{
-	int status;
-	u16 cmdResult;
-	int qamDemodParamCount = state->qam_demod_parameter_count;
-
-	dprintk(1, "\n");
-	/*
-	 * STEP 1: reset demodulator
-	 *	resets FEC DI and FEC RS
-	 *	resets QAM block
-	 *	resets SCU variables
-	 */
-	status = write16(state, FEC_DI_COMM_EXEC__A, FEC_DI_COMM_EXEC_STOP);
-	if (status < 0)
-		goto error;
-	status = write16(state, FEC_RS_COMM_EXEC__A, FEC_RS_COMM_EXEC_STOP);
-	if (status < 0)
-		goto error;
-	status = QAMResetQAM(state);
-	if (status < 0)
-		goto error;
-
-	/*
-	 * STEP 2: configure demodulator
-	 *	-set params; resets IQM,QAM,FEC HW; initializes some
-	 *       SCU variables
-	 */
-	status = QAMSetSymbolrate(state);
-	if (status < 0)
-		goto error;
-
-	/* Set params */
-	switch (state->props.modulation) {
-	case QAM_256:
-		state->m_Constellation = DRX_CONSTELLATION_QAM256;
-		break;
-	case QAM_AUTO:
-	case QAM_64:
-		state->m_Constellation = DRX_CONSTELLATION_QAM64;
-		break;
-	case QAM_16:
-		state->m_Constellation = DRX_CONSTELLATION_QAM16;
-		break;
-	case QAM_32:
-		state->m_Constellation = DRX_CONSTELLATION_QAM32;
-		break;
-	case QAM_128:
-		state->m_Constellation = DRX_CONSTELLATION_QAM128;
-		break;
-	default:
-		status = -EINVAL;
-		break;
-	}
-	if (status < 0)
-		goto error;
-
-	/* Use the 4-parameter if it's requested or we're probing for
-	 * the correct command. */
-	if (state->qam_demod_parameter_count == 4
-		|| !state->qam_demod_parameter_count) {
-		qamDemodParamCount = 4;
-		status = QAMDemodulatorCommand(state, qamDemodParamCount);
-	}
-
-	/* Use the 2-parameter command if it was requested or if we're
-	 * probing for the correct command and the 4-parameter command
-	 * failed. */
-	if (state->qam_demod_parameter_count == 2
-		|| (!state->qam_demod_parameter_count && status < 0)) {
-		qamDemodParamCount = 2;
-		status = QAMDemodulatorCommand(state, qamDemodParamCount);
-	}
-
-	if (status < 0) {
-		dprintk(1, "Could not set demodulator parameters. Make "
-			"sure qam_demod_parameter_count (%d) is correct for "
-			"your firmware (%s).\n",
-			state->qam_demod_parameter_count,
-			state->microcode_name);
-		goto error;
-	} else if (!state->qam_demod_parameter_count) {
-		dprintk(1, "Auto-probing the correct QAM demodulator command "
-			"parameters was successful - using %d parameters.\n",
-			qamDemodParamCount);
-
-		/*
-		 * One of our commands was successful. We don't need to
-		 * auto-probe anymore, now that we got the correct command.
-		 */
-		state->qam_demod_parameter_count = qamDemodParamCount;
-	}
-
-	/*
-	 * STEP 3: enable the system in a mode where the ADC provides valid
-	 * signal setup modulation independent registers
-	 */
-#if 0
-	status = SetFrequency(channel, tunerFreqOffset));
-	if (status < 0)
-		goto error;
-#endif
-	status = SetFrequencyShifter(state, IntermediateFreqkHz, tunerFreqOffset, true);
-	if (status < 0)
-		goto error;
-
-	/* Setup BER measurement */
-	status = SetQAMMeasurement(state, state->m_Constellation, state->props.symbol_rate);
-	if (status < 0)
-		goto error;
-
-	/* Reset default values */
-	status = write16(state, IQM_CF_SCALE_SH__A, IQM_CF_SCALE_SH__PRE);
-	if (status < 0)
-		goto error;
-	status = write16(state, QAM_SY_TIMEOUT__A, QAM_SY_TIMEOUT__PRE);
-	if (status < 0)
-		goto error;
-
-	/* Reset default LC values */
-	status = write16(state, QAM_LC_RATE_LIMIT__A, 3);
-	if (status < 0)
-		goto error;
-	status = write16(state, QAM_LC_LPF_FACTORP__A, 4);
-	if (status < 0)
-		goto error;
-	status = write16(state, QAM_LC_LPF_FACTORI__A, 4);
-	if (status < 0)
-		goto error;
-	status = write16(state, QAM_LC_MODE__A, 7);
-	if (status < 0)
-		goto error;
-
-	status = write16(state, QAM_LC_QUAL_TAB0__A, 1);
-	if (status < 0)
-		goto error;
-	status = write16(state, QAM_LC_QUAL_TAB1__A, 1);
-	if (status < 0)
-		goto error;
-	status = write16(state, QAM_LC_QUAL_TAB2__A, 1);
-	if (status < 0)
-		goto error;
-	status = write16(state, QAM_LC_QUAL_TAB3__A, 1);
-	if (status < 0)
-		goto error;
-	status = write16(state, QAM_LC_QUAL_TAB4__A, 2);
-	if (status < 0)
-		goto error;
-	status = write16(state, QAM_LC_QUAL_TAB5__A, 2);
-	if (status < 0)
-		goto error;
-	status = write16(state, QAM_LC_QUAL_TAB6__A, 2);
-	if (status < 0)
-		goto error;
-	status = write16(state, QAM_LC_QUAL_TAB8__A, 2);
-	if (status < 0)
-		goto error;
-	status = write16(state, QAM_LC_QUAL_TAB9__A, 2);
-	if (status < 0)
-		goto error;
-	status = write16(state, QAM_LC_QUAL_TAB10__A, 2);
-	if (status < 0)
-		goto error;
-	status = write16(state, QAM_LC_QUAL_TAB12__A, 2);
-	if (status < 0)
-		goto error;
-	status = write16(state, QAM_LC_QUAL_TAB15__A, 3);
-	if (status < 0)
-		goto error;
-	status = write16(state, QAM_LC_QUAL_TAB16__A, 3);
-	if (status < 0)
-		goto error;
-	status = write16(state, QAM_LC_QUAL_TAB20__A, 4);
-	if (status < 0)
-		goto error;
-	status = write16(state, QAM_LC_QUAL_TAB25__A, 4);
-	if (status < 0)
-		goto error;
-
-	/* Mirroring, QAM-block starting point not inverted */
-	status = write16(state, QAM_SY_SP_INV__A, QAM_SY_SP_INV_SPECTRUM_INV_DIS);
-	if (status < 0)
-		goto error;
-
-	/* Halt SCU to enable safe non-atomic accesses */
-	status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_HOLD);
-	if (status < 0)
-		goto error;
-
-	/* STEP 4: modulation specific setup */
-	switch (state->props.modulation) {
-	case QAM_16:
-		status = SetQAM16(state);
-		break;
-	case QAM_32:
-		status = SetQAM32(state);
-		break;
-	case QAM_AUTO:
-	case QAM_64:
-		status = SetQAM64(state);
-		break;
-	case QAM_128:
-		status = SetQAM128(state);
-		break;
-	case QAM_256:
-		status = SetQAM256(state);
-		break;
-	default:
-		status = -EINVAL;
-		break;
-	}
-	if (status < 0)
-		goto error;
-
-	/* Activate SCU to enable SCU commands */
-	status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_ACTIVE);
-	if (status < 0)
-		goto error;
-
-	/* Re-configure MPEG output, requires knowledge of channel bitrate */
-	/* extAttr->currentChannel.modulation = channel->modulation; */
-	/* extAttr->currentChannel.symbolrate    = channel->symbolrate; */
-	status = MPEGTSDtoSetup(state, state->m_OperationMode);
-	if (status < 0)
-		goto error;
-
-	/* Start processes */
-	status = MPEGTSStart(state);
-	if (status < 0)
-		goto error;
-	status = write16(state, FEC_COMM_EXEC__A, FEC_COMM_EXEC_ACTIVE);
-	if (status < 0)
-		goto error;
-	status = write16(state, QAM_COMM_EXEC__A, QAM_COMM_EXEC_ACTIVE);
-	if (status < 0)
-		goto error;
-	status = write16(state, IQM_COMM_EXEC__A, IQM_COMM_EXEC_B_ACTIVE);
-	if (status < 0)
-		goto error;
-
-	/* STEP 5: start QAM demodulator (starts FEC, QAM and IQM HW) */
-	status = scu_command(state, SCU_RAM_COMMAND_STANDARD_QAM | SCU_RAM_COMMAND_CMD_DEMOD_START, 0, NULL, 1, &cmdResult);
-	if (status < 0)
-		goto error;
-
-	/* update global DRXK data container */
-/*?     extAttr->qamInterleaveMode = DRXK_QAM_I12_J17; */
-
-error:
-	if (status < 0)
-		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
-	return status;
-}
-
-static int SetQAMStandard(struct drxk_state *state,
-			  enum OperationMode oMode)
-{
-	int status;
-#ifdef DRXK_QAM_TAPS
-#define DRXK_QAMA_TAPS_SELECT
-#include "drxk_filters.h"
-#undef DRXK_QAMA_TAPS_SELECT
-#endif
-
-	dprintk(1, "\n");
-
-	/* added antenna switch */
-	SwitchAntennaToQAM(state);
-
-	/* Ensure correct power-up mode */
-	status = PowerUpQAM(state);
-	if (status < 0)
-		goto error;
-	/* Reset QAM block */
-	status = QAMResetQAM(state);
-	if (status < 0)
-		goto error;
-
-	/* Setup IQM */
-
-	status = write16(state, IQM_COMM_EXEC__A, IQM_COMM_EXEC_B_STOP);
-	if (status < 0)
-		goto error;
-	status = write16(state, IQM_AF_AMUX__A, IQM_AF_AMUX_SIGNAL2ADC);
-	if (status < 0)
-		goto error;
-
-	/* Upload IQM Channel Filter settings by
-		boot loader from ROM table */
-	switch (oMode) {
-	case OM_QAM_ITU_A:
-		status = BLChainCmd(state, DRXK_BL_ROM_OFFSET_TAPS_ITU_A, DRXK_BLCC_NR_ELEMENTS_TAPS, DRXK_BLC_TIMEOUT);
-		break;
-	case OM_QAM_ITU_C:
-		status = BLDirectCmd(state, IQM_CF_TAP_RE0__A, DRXK_BL_ROM_OFFSET_TAPS_ITU_C, DRXK_BLDC_NR_ELEMENTS_TAPS, DRXK_BLC_TIMEOUT);
-		if (status < 0)
-			goto error;
-		status = BLDirectCmd(state, IQM_CF_TAP_IM0__A, DRXK_BL_ROM_OFFSET_TAPS_ITU_C, DRXK_BLDC_NR_ELEMENTS_TAPS, DRXK_BLC_TIMEOUT);
-		break;
-	default:
-		status = -EINVAL;
-	}
-	if (status < 0)
-		goto error;
-
-	status = write16(state, IQM_CF_OUT_ENA__A, (1 << IQM_CF_OUT_ENA_QAM__B));
-	if (status < 0)
-		goto error;
-	status = write16(state, IQM_CF_SYMMETRIC__A, 0);
-	if (status < 0)
-		goto error;
-	status = write16(state, IQM_CF_MIDTAP__A, ((1 << IQM_CF_MIDTAP_RE__B) | (1 << IQM_CF_MIDTAP_IM__B)));
-	if (status < 0)
-		goto error;
-
-	status = write16(state, IQM_RC_STRETCH__A, 21);
-	if (status < 0)
-		goto error;
-	status = write16(state, IQM_AF_CLP_LEN__A, 0);
-	if (status < 0)
-		goto error;
-	status = write16(state, IQM_AF_CLP_TH__A, 448);
-	if (status < 0)
-		goto error;
-	status = write16(state, IQM_AF_SNS_LEN__A, 0);
-	if (status < 0)
-		goto error;
-	status = write16(state, IQM_CF_POW_MEAS_LEN__A, 0);
-	if (status < 0)
-		goto error;
-
-	status = write16(state, IQM_FS_ADJ_SEL__A, 1);
-	if (status < 0)
-		goto error;
-	status = write16(state, IQM_RC_ADJ_SEL__A, 1);
-	if (status < 0)
-		goto error;
-	status = write16(state, IQM_CF_ADJ_SEL__A, 1);
-	if (status < 0)
-		goto error;
-	status = write16(state, IQM_AF_UPD_SEL__A, 0);
-	if (status < 0)
-		goto error;
-
-	/* IQM Impulse Noise Processing Unit */
-	status = write16(state, IQM_CF_CLP_VAL__A, 500);
-	if (status < 0)
-		goto error;
-	status = write16(state, IQM_CF_DATATH__A, 1000);
-	if (status < 0)
-		goto error;
-	status = write16(state, IQM_CF_BYPASSDET__A, 1);
-	if (status < 0)
-		goto error;
-	status = write16(state, IQM_CF_DET_LCT__A, 0);
-	if (status < 0)
-		goto error;
-	status = write16(state, IQM_CF_WND_LEN__A, 1);
-	if (status < 0)
-		goto error;
-	status = write16(state, IQM_CF_PKDTH__A, 1);
-	if (status < 0)
-		goto error;
-	status = write16(state, IQM_AF_INC_BYPASS__A, 1);
-	if (status < 0)
-		goto error;
-
-	/* turn on IQMAF. Must be done before setAgc**() */
-	status = SetIqmAf(state, true);
-	if (status < 0)
-		goto error;
-	status = write16(state, IQM_AF_START_LOCK__A, 0x01);
-	if (status < 0)
-		goto error;
-
-	/* IQM will not be reset from here, sync ADC and update/init AGC */
-	status = ADCSynchronization(state);
-	if (status < 0)
-		goto error;
-
-	/* Set the FSM step period */
-	status = write16(state, SCU_RAM_QAM_FSM_STEP_PERIOD__A, 2000);
-	if (status < 0)
-		goto error;
-
-	/* Halt SCU to enable safe non-atomic accesses */
-	status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_HOLD);
-	if (status < 0)
-		goto error;
-
-	/* No more resets of the IQM, current standard correctly set =>
-		now AGCs can be configured. */
-
-	status = InitAGC(state, true);
-	if (status < 0)
-		goto error;
-	status = SetPreSaw(state, &(state->m_qamPreSawCfg));
-	if (status < 0)
-		goto error;
-
-	/* Configure AGC's */
-	status = SetAgcRf(state, &(state->m_qamRfAgcCfg), true);
-	if (status < 0)
-		goto error;
-	status = SetAgcIf(state, &(state->m_qamIfAgcCfg), true);
-	if (status < 0)
-		goto error;
-
-	/* Activate SCU to enable SCU commands */
-	status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_ACTIVE);
-error:
-	if (status < 0)
-		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
-	return status;
-}
-
-static int WriteGPIO(struct drxk_state *state)
-{
-	int status;
-	u16 value = 0;
-
-	dprintk(1, "\n");
-	/* stop lock indicator process */
-	status = write16(state, SCU_RAM_GPIO__A, SCU_RAM_GPIO_HW_LOCK_IND_DISABLE);
-	if (status < 0)
-		goto error;
-
-	/*  Write magic word to enable pdr reg write               */
-	status = write16(state, SIO_TOP_COMM_KEY__A, SIO_TOP_COMM_KEY_KEY);
-	if (status < 0)
-		goto error;
-
-	if (state->m_hasSAWSW) {
-		if (state->UIO_mask & 0x0001) { /* UIO-1 */
-			/* write to io pad configuration register - output mode */
-			status = write16(state, SIO_PDR_SMA_TX_CFG__A, state->m_GPIOCfg);
-			if (status < 0)
-				goto error;
-
-			/* use corresponding bit in io data output registar */
-			status = read16(state, SIO_PDR_UIO_OUT_LO__A, &value);
-			if (status < 0)
-				goto error;
-			if ((state->m_GPIO & 0x0001) == 0)
-				value &= 0x7FFF;	/* write zero to 15th bit - 1st UIO */
-			else
-				value |= 0x8000;	/* write one to 15th bit - 1st UIO */
-			/* write back to io data output register */
-			status = write16(state, SIO_PDR_UIO_OUT_LO__A, value);
-			if (status < 0)
-				goto error;
-		}
-		if (state->UIO_mask & 0x0002) { /* UIO-2 */
-			/* write to io pad configuration register - output mode */
-			status = write16(state, SIO_PDR_SMA_RX_CFG__A, state->m_GPIOCfg);
-			if (status < 0)
-				goto error;
-
-			/* use corresponding bit in io data output registar */
-			status = read16(state, SIO_PDR_UIO_OUT_LO__A, &value);
-			if (status < 0)
-				goto error;
-			if ((state->m_GPIO & 0x0002) == 0)
-				value &= 0xBFFF;	/* write zero to 14th bit - 2st UIO */
-			else
-				value |= 0x4000;	/* write one to 14th bit - 2st UIO */
-			/* write back to io data output register */
-			status = write16(state, SIO_PDR_UIO_OUT_LO__A, value);
-			if (status < 0)
-				goto error;
-		}
-		if (state->UIO_mask & 0x0004) { /* UIO-3 */
-			/* write to io pad configuration register - output mode */
-			status = write16(state, SIO_PDR_GPIO_CFG__A, state->m_GPIOCfg);
-			if (status < 0)
-				goto error;
-
-			/* use corresponding bit in io data output registar */
-			status = read16(state, SIO_PDR_UIO_OUT_LO__A, &value);
-			if (status < 0)
-				goto error;
-			if ((state->m_GPIO & 0x0004) == 0)
-				value &= 0xFFFB;            /* write zero to 2nd bit - 3rd UIO */
-			else
-				value |= 0x0004;            /* write one to 2nd bit - 3rd UIO */
-			/* write back to io data output register */
-			status = write16(state, SIO_PDR_UIO_OUT_LO__A, value);
-			if (status < 0)
-				goto error;
-		}
-	}
-	/*  Write magic word to disable pdr reg write               */
-	status = write16(state, SIO_TOP_COMM_KEY__A, 0x0000);
-error:
-	if (status < 0)
-		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
-	return status;
-}
-
-static int SwitchAntennaToQAM(struct drxk_state *state)
-{
-	int status = 0;
-	bool gpio_state;
-
-	dprintk(1, "\n");
-
-	if (!state->antenna_gpio)
-		return 0;
-
-	gpio_state = state->m_GPIO & state->antenna_gpio;
-
-	if (state->antenna_dvbt ^ gpio_state) {
-		/* Antenna is on DVB-T mode. Switch */
-		if (state->antenna_dvbt)
-			state->m_GPIO &= ~state->antenna_gpio;
-		else
-			state->m_GPIO |= state->antenna_gpio;
-		status = WriteGPIO(state);
-	}
-	if (status < 0)
-		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
-	return status;
-}
-
-static int SwitchAntennaToDVBT(struct drxk_state *state)
-{
-	int status = 0;
-	bool gpio_state;
-
-	dprintk(1, "\n");
-
-	if (!state->antenna_gpio)
-		return 0;
-
-	gpio_state = state->m_GPIO & state->antenna_gpio;
-
-	if (!(state->antenna_dvbt ^ gpio_state)) {
-		/* Antenna is on DVB-C mode. Switch */
-		if (state->antenna_dvbt)
-			state->m_GPIO |= state->antenna_gpio;
-		else
-			state->m_GPIO &= ~state->antenna_gpio;
-		status = WriteGPIO(state);
-	}
-	if (status < 0)
-		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
-	return status;
-}
-
-
-static int PowerDownDevice(struct drxk_state *state)
-{
-	/* Power down to requested mode */
-	/* Backup some register settings */
-	/* Set pins with possible pull-ups connected to them in input mode */
-	/* Analog power down */
-	/* ADC power down */
-	/* Power down device */
-	int status;
-
-	dprintk(1, "\n");
-	if (state->m_bPDownOpenBridge) {
-		/* Open I2C bridge before power down of DRXK */
-		status = ConfigureI2CBridge(state, true);
-		if (status < 0)
-			goto error;
-	}
-	/* driver 0.9.0 */
-	status = DVBTEnableOFDMTokenRing(state, false);
-	if (status < 0)
-		goto error;
-
-	status = write16(state, SIO_CC_PWD_MODE__A, SIO_CC_PWD_MODE_LEVEL_CLOCK);
-	if (status < 0)
-		goto error;
-	status = write16(state, SIO_CC_UPDATE__A, SIO_CC_UPDATE_KEY);
-	if (status < 0)
-		goto error;
-	state->m_HICfgCtrl |= SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ;
-	status = HI_CfgCommand(state);
-error:
-	if (status < 0)
-		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
-
-	return status;
-}
-
-static int init_drxk(struct drxk_state *state)
-{
-	int status = 0, n = 0;
-	enum DRXPowerMode powerMode = DRXK_POWER_DOWN_OFDM;
-	u16 driverVersion;
-
-	dprintk(1, "\n");
-	if ((state->m_DrxkState == DRXK_UNINITIALIZED)) {
-		drxk_i2c_lock(state);
-		status = PowerUpDevice(state);
-		if (status < 0)
-			goto error;
-		status = DRXX_Open(state);
-		if (status < 0)
-			goto error;
-		/* Soft reset of OFDM-, sys- and osc-clockdomain */
-		status = write16(state, SIO_CC_SOFT_RST__A, SIO_CC_SOFT_RST_OFDM__M | SIO_CC_SOFT_RST_SYS__M | SIO_CC_SOFT_RST_OSC__M);
-		if (status < 0)
-			goto error;
-		status = write16(state, SIO_CC_UPDATE__A, SIO_CC_UPDATE_KEY);
-		if (status < 0)
-			goto error;
-		/* TODO is this needed, if yes how much delay in worst case scenario */
-		msleep(1);
-		state->m_DRXK_A3_PATCH_CODE = true;
-		status = GetDeviceCapabilities(state);
-		if (status < 0)
-			goto error;
-
-		/* Bridge delay, uses oscilator clock */
-		/* Delay = (delay (nano seconds) * oscclk (kHz))/ 1000 */
-		/* SDA brdige delay */
-		state->m_HICfgBridgeDelay =
-			(u16) ((state->m_oscClockFreq / 1000) *
-				HI_I2C_BRIDGE_DELAY) / 1000;
-		/* Clipping */
-		if (state->m_HICfgBridgeDelay >
-			SIO_HI_RA_RAM_PAR_3_CFG_DBL_SDA__M) {
-			state->m_HICfgBridgeDelay =
-				SIO_HI_RA_RAM_PAR_3_CFG_DBL_SDA__M;
-		}
-		/* SCL bridge delay, same as SDA for now */
-		state->m_HICfgBridgeDelay +=
-			state->m_HICfgBridgeDelay <<
-			SIO_HI_RA_RAM_PAR_3_CFG_DBL_SCL__B;
-
-		status = InitHI(state);
-		if (status < 0)
-			goto error;
-		/* disable various processes */
-#if NOA1ROM
-		if (!(state->m_DRXK_A1_ROM_CODE)
-			&& !(state->m_DRXK_A2_ROM_CODE))
-#endif
-		{
-			status = write16(state, SCU_RAM_GPIO__A, SCU_RAM_GPIO_HW_LOCK_IND_DISABLE);
-			if (status < 0)
-				goto error;
-		}
-
-		/* disable MPEG port */
-		status = MPEGTSDisable(state);
-		if (status < 0)
-			goto error;
-
-		/* Stop AUD and SCU */
-		status = write16(state, AUD_COMM_EXEC__A, AUD_COMM_EXEC_STOP);
-		if (status < 0)
-			goto error;
-		status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_STOP);
-		if (status < 0)
-			goto error;
-
-		/* enable token-ring bus through OFDM block for possible ucode upload */
-		status = write16(state, SIO_OFDM_SH_OFDM_RING_ENABLE__A, SIO_OFDM_SH_OFDM_RING_ENABLE_ON);
-		if (status < 0)
-			goto error;
-
-		/* include boot loader section */
-		status = write16(state, SIO_BL_COMM_EXEC__A, SIO_BL_COMM_EXEC_ACTIVE);
-		if (status < 0)
-			goto error;
-		status = BLChainCmd(state, 0, 6, 100);
-		if (status < 0)
-			goto error;
-
-		if (state->fw) {
-			status = DownloadMicrocode(state, state->fw->data,
-						   state->fw->size);
-			if (status < 0)
-				goto error;
-		}
-
-		/* disable token-ring bus through OFDM block for possible ucode upload */
-		status = write16(state, SIO_OFDM_SH_OFDM_RING_ENABLE__A, SIO_OFDM_SH_OFDM_RING_ENABLE_OFF);
-		if (status < 0)
-			goto error;
-
-		/* Run SCU for a little while to initialize microcode version numbers */
-		status = write16(state, SCU_COMM_EXEC__A, SCU_COMM_EXEC_ACTIVE);
-		if (status < 0)
-			goto error;
-		status = DRXX_Open(state);
-		if (status < 0)
-			goto error;
-		/* added for test */
-		msleep(30);
-
-		powerMode = DRXK_POWER_DOWN_OFDM;
-		status = CtrlPowerMode(state, &powerMode);
-		if (status < 0)
-			goto error;
-
-		/* Stamp driver version number in SCU data RAM in BCD code
-			Done to enable field application engineers to retreive drxdriver version
-			via I2C from SCU RAM.
-			Not using SCU command interface for SCU register access since no
-			microcode may be present.
-			*/
-		driverVersion =
-			(((DRXK_VERSION_MAJOR / 100) % 10) << 12) +
-			(((DRXK_VERSION_MAJOR / 10) % 10) << 8) +
-			((DRXK_VERSION_MAJOR % 10) << 4) +
-			(DRXK_VERSION_MINOR % 10);
-		status = write16(state, SCU_RAM_DRIVER_VER_HI__A, driverVersion);
-		if (status < 0)
-			goto error;
-		driverVersion =
-			(((DRXK_VERSION_PATCH / 1000) % 10) << 12) +
-			(((DRXK_VERSION_PATCH / 100) % 10) << 8) +
-			(((DRXK_VERSION_PATCH / 10) % 10) << 4) +
-			(DRXK_VERSION_PATCH % 10);
-		status = write16(state, SCU_RAM_DRIVER_VER_LO__A, driverVersion);
-		if (status < 0)
-			goto error;
-
-		printk(KERN_INFO "DRXK driver version %d.%d.%d\n",
-			DRXK_VERSION_MAJOR, DRXK_VERSION_MINOR,
-			DRXK_VERSION_PATCH);
-
-		/* Dirty fix of default values for ROM/PATCH microcode
-			Dirty because this fix makes it impossible to setup suitable values
-			before calling DRX_Open. This solution requires changes to RF AGC speed
-			to be done via the CTRL function after calling DRX_Open */
-
-		/* m_dvbtRfAgcCfg.speed = 3; */
-
-		/* Reset driver debug flags to 0 */
-		status = write16(state, SCU_RAM_DRIVER_DEBUG__A, 0);
-		if (status < 0)
-			goto error;
-		/* driver 0.9.0 */
-		/* Setup FEC OC:
-			NOTE: No more full FEC resets allowed afterwards!! */
-		status = write16(state, FEC_COMM_EXEC__A, FEC_COMM_EXEC_STOP);
-		if (status < 0)
-			goto error;
-		/* MPEGTS functions are still the same */
-		status = MPEGTSDtoInit(state);
-		if (status < 0)
-			goto error;
-		status = MPEGTSStop(state);
-		if (status < 0)
-			goto error;
-		status = MPEGTSConfigurePolarity(state);
-		if (status < 0)
-			goto error;
-		status = MPEGTSConfigurePins(state, state->m_enableMPEGOutput);
-		if (status < 0)
-			goto error;
-		/* added: configure GPIO */
-		status = WriteGPIO(state);
-		if (status < 0)
-			goto error;
-
-		state->m_DrxkState = DRXK_STOPPED;
-
-		if (state->m_bPowerDown) {
-			status = PowerDownDevice(state);
-			if (status < 0)
-				goto error;
-			state->m_DrxkState = DRXK_POWERED_DOWN;
-		} else
-			state->m_DrxkState = DRXK_STOPPED;
-
-		/* Initialize the supported delivery systems */
-		n = 0;
-		if (state->m_hasDVBC) {
-			state->frontend.ops.delsys[n++] = SYS_DVBC_ANNEX_A;
-			state->frontend.ops.delsys[n++] = SYS_DVBC_ANNEX_C;
-			strlcat(state->frontend.ops.info.name, " DVB-C",
-				sizeof(state->frontend.ops.info.name));
-		}
-		if (state->m_hasDVBT) {
-			state->frontend.ops.delsys[n++] = SYS_DVBT;
-			strlcat(state->frontend.ops.info.name, " DVB-T",
-				sizeof(state->frontend.ops.info.name));
-		}
-		drxk_i2c_unlock(state);
-	}
-error:
-	if (status < 0) {
-		state->m_DrxkState = DRXK_NO_DEV;
-		drxk_i2c_unlock(state);
-		printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
-	}
-
-	return status;
-}
-
-static void load_firmware_cb(const struct firmware *fw,
-			     void *context)
-{
-	struct drxk_state *state = context;
-
-	dprintk(1, ": %s\n", fw ? "firmware loaded" : "firmware not loaded");
-	if (!fw) {
-		printk(KERN_ERR
-		       "drxk: Could not load firmware file %s.\n",
-			state->microcode_name);
-		printk(KERN_INFO
-		       "drxk: Copy %s to your hotplug directory!\n",
-			state->microcode_name);
-		state->microcode_name = NULL;
-
-		/*
-		 * As firmware is now load asynchronous, it is not possible
-		 * anymore to fail at frontend attach. We might silently
-		 * return here, and hope that the driver won't crash.
-		 * We might also change all DVB callbacks to return -ENODEV
-		 * if the device is not initialized.
-		 * As the DRX-K devices have their own internal firmware,
-		 * let's just hope that it will match a firmware revision
-		 * compatible with this driver and proceed.
-		 */
-	}
-	state->fw = fw;
-
-	init_drxk(state);
-}
-
-static void drxk_release(struct dvb_frontend *fe)
-{
-	struct drxk_state *state = fe->demodulator_priv;
-
-	dprintk(1, "\n");
-	if (state->fw)
-		release_firmware(state->fw);
-
-	kfree(state);
-}
-
-static int drxk_sleep(struct dvb_frontend *fe)
-{
-	struct drxk_state *state = fe->demodulator_priv;
-
-	dprintk(1, "\n");
-
-	if (state->m_DrxkState == DRXK_NO_DEV)
-		return -ENODEV;
-	if (state->m_DrxkState == DRXK_UNINITIALIZED)
-		return 0;
-
-	ShutDown(state);
-	return 0;
-}
-
-static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable)
-{
-	struct drxk_state *state = fe->demodulator_priv;
-
-	dprintk(1, ": %s\n", enable ? "enable" : "disable");
-
-	if (state->m_DrxkState == DRXK_NO_DEV)
-		return -ENODEV;
-
-	return ConfigureI2CBridge(state, enable ? true : false);
-}
-
-static int drxk_set_parameters(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	u32 delsys  = p->delivery_system, old_delsys;
-	struct drxk_state *state = fe->demodulator_priv;
-	u32 IF;
-
-	dprintk(1, "\n");
-
-	if (state->m_DrxkState == DRXK_NO_DEV)
-		return -ENODEV;
-
-	if (state->m_DrxkState == DRXK_UNINITIALIZED)
-		return -EAGAIN;
-
-	if (!fe->ops.tuner_ops.get_if_frequency) {
-		printk(KERN_ERR
-		       "drxk: Error: get_if_frequency() not defined at tuner. Can't work without it!\n");
-		return -EINVAL;
-	}
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	if (fe->ops.tuner_ops.set_params)
-		fe->ops.tuner_ops.set_params(fe);
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0);
-
-	old_delsys = state->props.delivery_system;
-	state->props = *p;
-
-	if (old_delsys != delsys) {
-		ShutDown(state);
-		switch (delsys) {
-		case SYS_DVBC_ANNEX_A:
-		case SYS_DVBC_ANNEX_C:
-			if (!state->m_hasDVBC)
-				return -EINVAL;
-			state->m_itut_annex_c = (delsys == SYS_DVBC_ANNEX_C) ? true : false;
-			if (state->m_itut_annex_c)
-				SetOperationMode(state, OM_QAM_ITU_C);
-			else
-				SetOperationMode(state, OM_QAM_ITU_A);
-			break;
-		case SYS_DVBT:
-			if (!state->m_hasDVBT)
-				return -EINVAL;
-			SetOperationMode(state, OM_DVBT);
-			break;
-		default:
-			return -EINVAL;
-		}
-	}
-
-	fe->ops.tuner_ops.get_if_frequency(fe, &IF);
-	Start(state, 0, IF);
-
-	/* printk(KERN_DEBUG "drxk: %s IF=%d done\n", __func__, IF); */
-
-	return 0;
-}
-
-static int drxk_read_status(struct dvb_frontend *fe, fe_status_t *status)
-{
-	struct drxk_state *state = fe->demodulator_priv;
-	u32 stat;
-
-	dprintk(1, "\n");
-
-	if (state->m_DrxkState == DRXK_NO_DEV)
-		return -ENODEV;
-	if (state->m_DrxkState == DRXK_UNINITIALIZED)
-		return -EAGAIN;
-
-	*status = 0;
-	GetLockStatus(state, &stat, 0);
-	if (stat == MPEG_LOCK)
-		*status |= 0x1f;
-	if (stat == FEC_LOCK)
-		*status |= 0x0f;
-	if (stat == DEMOD_LOCK)
-		*status |= 0x07;
-	return 0;
-}
-
-static int drxk_read_ber(struct dvb_frontend *fe, u32 *ber)
-{
-	struct drxk_state *state = fe->demodulator_priv;
-
-	dprintk(1, "\n");
-
-	if (state->m_DrxkState == DRXK_NO_DEV)
-		return -ENODEV;
-	if (state->m_DrxkState == DRXK_UNINITIALIZED)
-		return -EAGAIN;
-
-	*ber = 0;
-	return 0;
-}
-
-static int drxk_read_signal_strength(struct dvb_frontend *fe,
-				     u16 *strength)
-{
-	struct drxk_state *state = fe->demodulator_priv;
-	u32 val = 0;
-
-	dprintk(1, "\n");
-
-	if (state->m_DrxkState == DRXK_NO_DEV)
-		return -ENODEV;
-	if (state->m_DrxkState == DRXK_UNINITIALIZED)
-		return -EAGAIN;
-
-	ReadIFAgc(state, &val);
-	*strength = val & 0xffff;
-	return 0;
-}
-
-static int drxk_read_snr(struct dvb_frontend *fe, u16 *snr)
-{
-	struct drxk_state *state = fe->demodulator_priv;
-	s32 snr2;
-
-	dprintk(1, "\n");
-
-	if (state->m_DrxkState == DRXK_NO_DEV)
-		return -ENODEV;
-	if (state->m_DrxkState == DRXK_UNINITIALIZED)
-		return -EAGAIN;
-
-	GetSignalToNoise(state, &snr2);
-	*snr = snr2 & 0xffff;
-	return 0;
-}
-
-static int drxk_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
-{
-	struct drxk_state *state = fe->demodulator_priv;
-	u16 err;
-
-	dprintk(1, "\n");
-
-	if (state->m_DrxkState == DRXK_NO_DEV)
-		return -ENODEV;
-	if (state->m_DrxkState == DRXK_UNINITIALIZED)
-		return -EAGAIN;
-
-	DVBTQAMGetAccPktErr(state, &err);
-	*ucblocks = (u32) err;
-	return 0;
-}
-
-static int drxk_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings
-				    *sets)
-{
-	struct drxk_state *state = fe->demodulator_priv;
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-
-	dprintk(1, "\n");
-
-	if (state->m_DrxkState == DRXK_NO_DEV)
-		return -ENODEV;
-	if (state->m_DrxkState == DRXK_UNINITIALIZED)
-		return -EAGAIN;
-
-	switch (p->delivery_system) {
-	case SYS_DVBC_ANNEX_A:
-	case SYS_DVBC_ANNEX_C:
-	case SYS_DVBT:
-		sets->min_delay_ms = 3000;
-		sets->max_drift = 0;
-		sets->step_size = 0;
-		return 0;
-	default:
-		return -EINVAL;
-	}
-}
-
-static struct dvb_frontend_ops drxk_ops = {
-	/* .delsys will be filled dynamically */
-	.info = {
-		.name = "DRXK",
-		.frequency_min = 47000000,
-		.frequency_max = 865000000,
-		 /* For DVB-C */
-		.symbol_rate_min = 870000,
-		.symbol_rate_max = 11700000,
-		/* For DVB-T */
-		.frequency_stepsize = 166667,
-
-		.caps = FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 |
-			FE_CAN_QAM_128 | FE_CAN_QAM_256 | FE_CAN_FEC_AUTO |
-			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_MUTE_TS |
-			FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_RECOVER |
-			FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO
-	},
-
-	.release = drxk_release,
-	.sleep = drxk_sleep,
-	.i2c_gate_ctrl = drxk_gate_ctrl,
-
-	.set_frontend = drxk_set_parameters,
-	.get_tune_settings = drxk_get_tune_settings,
-
-	.read_status = drxk_read_status,
-	.read_ber = drxk_read_ber,
-	.read_signal_strength = drxk_read_signal_strength,
-	.read_snr = drxk_read_snr,
-	.read_ucblocks = drxk_read_ucblocks,
-};
-
-struct dvb_frontend *drxk_attach(const struct drxk_config *config,
-				 struct i2c_adapter *i2c)
-{
-	struct drxk_state *state = NULL;
-	u8 adr = config->adr;
-	int status;
-
-	dprintk(1, "\n");
-	state = kzalloc(sizeof(struct drxk_state), GFP_KERNEL);
-	if (!state)
-		return NULL;
-
-	state->i2c = i2c;
-	state->demod_address = adr;
-	state->single_master = config->single_master;
-	state->microcode_name = config->microcode_name;
-	state->qam_demod_parameter_count = config->qam_demod_parameter_count;
-	state->no_i2c_bridge = config->no_i2c_bridge;
-	state->antenna_gpio = config->antenna_gpio;
-	state->antenna_dvbt = config->antenna_dvbt;
-	state->m_ChunkSize = config->chunk_size;
-	state->enable_merr_cfg = config->enable_merr_cfg;
-
-	if (config->dynamic_clk) {
-		state->m_DVBTStaticCLK = 0;
-		state->m_DVBCStaticCLK = 0;
-	} else {
-		state->m_DVBTStaticCLK = 1;
-		state->m_DVBCStaticCLK = 1;
-	}
-
-
-	if (config->mpeg_out_clk_strength)
-		state->m_TSClockkStrength = config->mpeg_out_clk_strength & 0x07;
-	else
-		state->m_TSClockkStrength = 0x06;
-
-	if (config->parallel_ts)
-		state->m_enableParallel = true;
-	else
-		state->m_enableParallel = false;
-
-	/* NOTE: as more UIO bits will be used, add them to the mask */
-	state->UIO_mask = config->antenna_gpio;
-
-	/* Default gpio to DVB-C */
-	if (!state->antenna_dvbt && state->antenna_gpio)
-		state->m_GPIO |= state->antenna_gpio;
-	else
-		state->m_GPIO &= ~state->antenna_gpio;
-
-	mutex_init(&state->mutex);
-
-	memcpy(&state->frontend.ops, &drxk_ops, sizeof(drxk_ops));
-	state->frontend.demodulator_priv = state;
-
-	init_state(state);
-
-	/* Load firmware and initialize DRX-K */
-	if (state->microcode_name) {
-		status = request_firmware_nowait(THIS_MODULE, 1,
-					      state->microcode_name,
-					      state->i2c->dev.parent,
-					      GFP_KERNEL,
-					      state, load_firmware_cb);
-		if (status < 0) {
-			printk(KERN_ERR
-			"drxk: failed to request a firmware\n");
-			return NULL;
-		}
-	} else if (init_drxk(state) < 0)
-		goto error;
-
-	printk(KERN_INFO "drxk: frontend initialized.\n");
-	return &state->frontend;
-
-error:
-	printk(KERN_ERR "drxk: not found\n");
-	kfree(state);
-	return NULL;
-}
-EXPORT_SYMBOL(drxk_attach);
-
-MODULE_DESCRIPTION("DRX-K driver");
-MODULE_AUTHOR("Ralph Metzler");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/drxk_hard.h b/drivers/media/dvb/frontends/drxk_hard.h
deleted file mode 100644
index 6bb9fc4..0000000
--- a/drivers/media/dvb/frontends/drxk_hard.h
+++ /dev/null
@@ -1,364 +0,0 @@
-#include "drxk_map.h"
-
-#define DRXK_VERSION_MAJOR 0
-#define DRXK_VERSION_MINOR 9
-#define DRXK_VERSION_PATCH 4300
-
-#define HI_I2C_DELAY        42
-#define HI_I2C_BRIDGE_DELAY 350
-#define DRXK_MAX_RETRIES    100
-
-#define DRIVER_4400 1
-
-#define DRXX_JTAGID   0x039210D9
-#define DRXX_J_JTAGID 0x239310D9
-#define DRXX_K_JTAGID 0x039210D9
-
-#define DRX_UNKNOWN     254
-#define DRX_AUTO        255
-
-#define DRX_SCU_READY   0
-#define DRXK_MAX_WAITTIME (200)
-#define SCU_RESULT_OK      0
-#define SCU_RESULT_SIZE   -4
-#define SCU_RESULT_INVPAR -3
-#define SCU_RESULT_UNKSTD -2
-#define SCU_RESULT_UNKCMD -1
-
-#ifndef DRXK_OFDM_TR_SHUTDOWN_TIMEOUT
-#define DRXK_OFDM_TR_SHUTDOWN_TIMEOUT (200)
-#endif
-
-#define DRXK_8VSB_MPEG_BIT_RATE     19392658UL  /*bps*/
-#define DRXK_DVBT_MPEG_BIT_RATE     32000000UL  /*bps*/
-#define DRXK_QAM16_MPEG_BIT_RATE    27000000UL  /*bps*/
-#define DRXK_QAM32_MPEG_BIT_RATE    33000000UL  /*bps*/
-#define DRXK_QAM64_MPEG_BIT_RATE    40000000UL  /*bps*/
-#define DRXK_QAM128_MPEG_BIT_RATE   46000000UL  /*bps*/
-#define DRXK_QAM256_MPEG_BIT_RATE   52000000UL  /*bps*/
-#define DRXK_MAX_MPEG_BIT_RATE      52000000UL  /*bps*/
-
-#define   IQM_CF_OUT_ENA_OFDM__M                                            0x4
-#define     IQM_FS_ADJ_SEL_B_QAM                                            0x1
-#define     IQM_FS_ADJ_SEL_B_OFF                                            0x0
-#define     IQM_FS_ADJ_SEL_B_VSB                                            0x2
-#define     IQM_RC_ADJ_SEL_B_OFF                                            0x0
-#define     IQM_RC_ADJ_SEL_B_QAM                                            0x1
-#define     IQM_RC_ADJ_SEL_B_VSB                                            0x2
-
-enum OperationMode {
-	OM_NONE,
-	OM_QAM_ITU_A,
-	OM_QAM_ITU_B,
-	OM_QAM_ITU_C,
-	OM_DVBT
-};
-
-enum DRXPowerMode {
-	DRX_POWER_UP = 0,
-	DRX_POWER_MODE_1,
-	DRX_POWER_MODE_2,
-	DRX_POWER_MODE_3,
-	DRX_POWER_MODE_4,
-	DRX_POWER_MODE_5,
-	DRX_POWER_MODE_6,
-	DRX_POWER_MODE_7,
-	DRX_POWER_MODE_8,
-
-	DRX_POWER_MODE_9,
-	DRX_POWER_MODE_10,
-	DRX_POWER_MODE_11,
-	DRX_POWER_MODE_12,
-	DRX_POWER_MODE_13,
-	DRX_POWER_MODE_14,
-	DRX_POWER_MODE_15,
-	DRX_POWER_MODE_16,
-	DRX_POWER_DOWN = 255
-};
-
-
-/** /brief Intermediate power mode for DRXK, power down OFDM clock domain */
-#ifndef DRXK_POWER_DOWN_OFDM
-#define DRXK_POWER_DOWN_OFDM        DRX_POWER_MODE_1
-#endif
-
-/** /brief Intermediate power mode for DRXK, power down core (sysclk) */
-#ifndef DRXK_POWER_DOWN_CORE
-#define DRXK_POWER_DOWN_CORE        DRX_POWER_MODE_9
-#endif
-
-/** /brief Intermediate power mode for DRXK, power down pll (only osc runs) */
-#ifndef DRXK_POWER_DOWN_PLL
-#define DRXK_POWER_DOWN_PLL         DRX_POWER_MODE_10
-#endif
-
-
-enum AGC_CTRL_MODE { DRXK_AGC_CTRL_AUTO = 0, DRXK_AGC_CTRL_USER, DRXK_AGC_CTRL_OFF };
-enum EDrxkState {
-	DRXK_UNINITIALIZED = 0,
-	DRXK_STOPPED,
-	DRXK_DTV_STARTED,
-	DRXK_ATV_STARTED,
-	DRXK_POWERED_DOWN,
-	DRXK_NO_DEV			/* If drxk init failed */
-};
-
-enum EDrxkCoefArrayIndex {
-	DRXK_COEF_IDX_MN = 0,
-	DRXK_COEF_IDX_FM    ,
-	DRXK_COEF_IDX_L     ,
-	DRXK_COEF_IDX_LP    ,
-	DRXK_COEF_IDX_BG    ,
-	DRXK_COEF_IDX_DK    ,
-	DRXK_COEF_IDX_I     ,
-	DRXK_COEF_IDX_MAX
-};
-enum EDrxkSifAttenuation {
-	DRXK_SIF_ATTENUATION_0DB,
-	DRXK_SIF_ATTENUATION_3DB,
-	DRXK_SIF_ATTENUATION_6DB,
-	DRXK_SIF_ATTENUATION_9DB
-};
-enum EDrxkConstellation {
-	DRX_CONSTELLATION_BPSK = 0,
-	DRX_CONSTELLATION_QPSK,
-	DRX_CONSTELLATION_PSK8,
-	DRX_CONSTELLATION_QAM16,
-	DRX_CONSTELLATION_QAM32,
-	DRX_CONSTELLATION_QAM64,
-	DRX_CONSTELLATION_QAM128,
-	DRX_CONSTELLATION_QAM256,
-	DRX_CONSTELLATION_QAM512,
-	DRX_CONSTELLATION_QAM1024,
-	DRX_CONSTELLATION_UNKNOWN = DRX_UNKNOWN,
-	DRX_CONSTELLATION_AUTO    = DRX_AUTO
-};
-enum EDrxkInterleaveMode {
-	DRXK_QAM_I12_J17    = 16,
-	DRXK_QAM_I_UNKNOWN  = DRX_UNKNOWN
-};
-enum {
-	DRXK_SPIN_A1 = 0,
-	DRXK_SPIN_A2,
-	DRXK_SPIN_A3,
-	DRXK_SPIN_UNKNOWN
-};
-
-enum DRXKCfgDvbtSqiSpeed {
-	DRXK_DVBT_SQI_SPEED_FAST = 0,
-	DRXK_DVBT_SQI_SPEED_MEDIUM,
-	DRXK_DVBT_SQI_SPEED_SLOW,
-	DRXK_DVBT_SQI_SPEED_UNKNOWN = DRX_UNKNOWN
-} ;
-
-enum DRXFftmode_t {
-	DRX_FFTMODE_2K = 0,
-	DRX_FFTMODE_4K,
-	DRX_FFTMODE_8K,
-	DRX_FFTMODE_UNKNOWN = DRX_UNKNOWN,
-	DRX_FFTMODE_AUTO    = DRX_AUTO
-};
-
-enum DRXMPEGStrWidth_t {
-	DRX_MPEG_STR_WIDTH_1,
-	DRX_MPEG_STR_WIDTH_8
-};
-
-enum DRXQamLockRange_t {
-	DRX_QAM_LOCKRANGE_NORMAL,
-	DRX_QAM_LOCKRANGE_EXTENDED
-};
-
-struct DRXKCfgDvbtEchoThres_t {
-	u16             threshold;
-	enum DRXFftmode_t      fftMode;
-} ;
-
-struct SCfgAgc {
-	enum AGC_CTRL_MODE     ctrlMode;        /* off, user, auto */
-	u16            outputLevel;     /* range dependent on AGC */
-	u16            minOutputLevel;  /* range dependent on AGC */
-	u16            maxOutputLevel;  /* range dependent on AGC */
-	u16            speed;           /* range dependent on AGC */
-	u16            top;             /* rf-agc take over point */
-	u16            cutOffCurrent;   /* rf-agc is accelerated if output current
-					   is below cut-off current */
-	u16            IngainTgtMax;
-	u16            FastClipCtrlDelay;
-};
-
-struct SCfgPreSaw {
-	u16        reference; /* pre SAW reference value, range 0 .. 31 */
-	bool          usePreSaw; /* TRUE algorithms must use pre SAW sense */
-};
-
-struct DRXKOfdmScCmd_t {
-	u16 cmd;        /**< Command number */
-	u16 subcmd;     /**< Sub-command parameter*/
-	u16 param0;     /**< General purpous param */
-	u16 param1;     /**< General purpous param */
-	u16 param2;     /**< General purpous param */
-	u16 param3;     /**< General purpous param */
-	u16 param4;     /**< General purpous param */
-};
-
-struct drxk_state {
-	struct dvb_frontend frontend;
-	struct dtv_frontend_properties props;
-	struct device *dev;
-
-	struct i2c_adapter *i2c;
-	u8     demod_address;
-	void  *priv;
-
-	struct mutex mutex;
-
-	u32    m_Instance;           /**< Channel 1,2,3 or 4 */
-
-	int    m_ChunkSize;
-	u8 Chunk[256];
-
-	bool   m_hasLNA;
-	bool   m_hasDVBT;
-	bool   m_hasDVBC;
-	bool   m_hasAudio;
-	bool   m_hasATV;
-	bool   m_hasOOB;
-	bool   m_hasSAWSW;         /**< TRUE if mat_tx is available */
-	bool   m_hasGPIO1;         /**< TRUE if mat_rx is available */
-	bool   m_hasGPIO2;         /**< TRUE if GPIO is available */
-	bool   m_hasIRQN;          /**< TRUE if IRQN is available */
-	u16    m_oscClockFreq;
-	u16    m_HICfgTimingDiv;
-	u16    m_HICfgBridgeDelay;
-	u16    m_HICfgWakeUpKey;
-	u16    m_HICfgTimeout;
-	u16    m_HICfgCtrl;
-	s32    m_sysClockFreq;      /**< system clock frequency in kHz */
-
-	enum EDrxkState    m_DrxkState;      /**< State of Drxk (init,stopped,started) */
-	enum OperationMode m_OperationMode;  /**< digital standards */
-	struct SCfgAgc     m_vsbRfAgcCfg;    /**< settings for VSB RF-AGC */
-	struct SCfgAgc     m_vsbIfAgcCfg;    /**< settings for VSB IF-AGC */
-	u16                m_vsbPgaCfg;      /**< settings for VSB PGA */
-	struct SCfgPreSaw  m_vsbPreSawCfg;   /**< settings for pre SAW sense */
-	s32    m_Quality83percent;  /**< MER level (*0.1 dB) for 83% quality indication */
-	s32    m_Quality93percent;  /**< MER level (*0.1 dB) for 93% quality indication */
-	bool   m_smartAntInverted;
-	bool   m_bDebugEnableBridge;
-	bool   m_bPDownOpenBridge;  /**< only open DRXK bridge before power-down once it has been accessed */
-	bool   m_bPowerDown;        /**< Power down when not used */
-
-	u32    m_IqmFsRateOfs;      /**< frequency shift as written to DRXK register (28bit fixpoint) */
-
-	bool   m_enableMPEGOutput;  /**< If TRUE, enable MPEG output */
-	bool   m_insertRSByte;      /**< If TRUE, insert RS byte */
-	bool   m_enableParallel;    /**< If TRUE, parallel out otherwise serial */
-	bool   m_invertDATA;        /**< If TRUE, invert DATA signals */
-	bool   m_invertERR;         /**< If TRUE, invert ERR signal */
-	bool   m_invertSTR;         /**< If TRUE, invert STR signals */
-	bool   m_invertVAL;         /**< If TRUE, invert VAL signals */
-	bool   m_invertCLK;         /**< If TRUE, invert CLK signals */
-	bool   m_DVBCStaticCLK;
-	bool   m_DVBTStaticCLK;     /**< If TRUE, static MPEG clockrate will
-					 be used, otherwise clockrate will
-					 adapt to the bitrate of the TS */
-	u32    m_DVBTBitrate;
-	u32    m_DVBCBitrate;
-
-	u8     m_TSDataStrength;
-	u8     m_TSClockkStrength;
-
-	bool   m_itut_annex_c;      /* If true, uses ITU-T DVB-C Annex C, instead of Annex A */
-
-	enum DRXMPEGStrWidth_t  m_widthSTR;    /**< MPEG start width */
-	u32    m_mpegTsStaticBitrate;          /**< Maximum bitrate in b/s in case
-						    static clockrate is selected */
-
-	/* LARGE_INTEGER   m_StartTime; */     /**< Contains the time of the last demod start */
-	s32    m_MpegLockTimeOut;      /**< WaitForLockStatus Timeout (counts from start time) */
-	s32    m_DemodLockTimeOut;     /**< WaitForLockStatus Timeout (counts from start time) */
-
-	bool   m_disableTEIhandling;
-
-	bool   m_RfAgcPol;
-	bool   m_IfAgcPol;
-
-	struct SCfgAgc    m_atvRfAgcCfg;  /**< settings for ATV RF-AGC */
-	struct SCfgAgc    m_atvIfAgcCfg;  /**< settings for ATV IF-AGC */
-	struct SCfgPreSaw m_atvPreSawCfg; /**< settings for ATV pre SAW sense */
-	bool              m_phaseCorrectionBypass;
-	s16               m_atvTopVidPeak;
-	u16               m_atvTopNoiseTh;
-	enum EDrxkSifAttenuation m_sifAttenuation;
-	bool              m_enableCVBSOutput;
-	bool              m_enableSIFOutput;
-	bool              m_bMirrorFreqSpect;
-	enum EDrxkConstellation  m_Constellation; /**< Constellation type of the channel */
-	u32               m_CurrSymbolRate;       /**< Current QAM symbol rate */
-	struct SCfgAgc    m_qamRfAgcCfg;          /**< settings for QAM RF-AGC */
-	struct SCfgAgc    m_qamIfAgcCfg;          /**< settings for QAM IF-AGC */
-	u16               m_qamPgaCfg;            /**< settings for QAM PGA */
-	struct SCfgPreSaw m_qamPreSawCfg;         /**< settings for QAM pre SAW sense */
-	enum EDrxkInterleaveMode m_qamInterleaveMode; /**< QAM Interleave mode */
-	u16               m_fecRsPlen;
-	u16               m_fecRsPrescale;
-
-	enum DRXKCfgDvbtSqiSpeed m_sqiSpeed;
-
-	u16               m_GPIO;
-	u16               m_GPIOCfg;
-
-	struct SCfgAgc    m_dvbtRfAgcCfg;     /**< settings for QAM RF-AGC */
-	struct SCfgAgc    m_dvbtIfAgcCfg;     /**< settings for QAM IF-AGC */
-	struct SCfgPreSaw m_dvbtPreSawCfg;    /**< settings for QAM pre SAW sense */
-
-	u16               m_agcFastClipCtrlDelay;
-	bool              m_adcCompPassed;
-	u16               m_adcCompCoef[64];
-	u16               m_adcState;
-
-	u8               *m_microcode;
-	int               m_microcode_length;
-	bool              m_DRXK_A1_PATCH_CODE;
-	bool              m_DRXK_A1_ROM_CODE;
-	bool              m_DRXK_A2_ROM_CODE;
-	bool              m_DRXK_A3_ROM_CODE;
-	bool              m_DRXK_A2_PATCH_CODE;
-	bool              m_DRXK_A3_PATCH_CODE;
-
-	bool              m_rfmirror;
-	u8                m_deviceSpin;
-	u32               m_iqmRcRate;
-
-	enum DRXPowerMode m_currentPowerMode;
-
-	/* when true, avoids other devices to use the I2C bus */
-	bool		  drxk_i2c_exclusive_lock;
-
-	/*
-	 * Configurable parameters at the driver. They stores the values found
-	 * at struct drxk_config.
-	 */
-
-	u16	UIO_mask;	/* Bits used by UIO */
-
-	bool	enable_merr_cfg;
-	bool	single_master;
-	bool	no_i2c_bridge;
-	bool	antenna_dvbt;
-	u16	antenna_gpio;
-
-	/* Firmware */
-	const char *microcode_name;
-	struct completion fw_wait_load;
-	const struct firmware *fw;
-	int qam_demod_parameter_count;
-};
-
-#define NEVER_LOCK 0
-#define NOT_LOCKED 1
-#define DEMOD_LOCK 2
-#define FEC_LOCK   3
-#define MPEG_LOCK  4
-
diff --git a/drivers/media/dvb/frontends/drxk_map.h b/drivers/media/dvb/frontends/drxk_map.h
deleted file mode 100644
index 23e16c1..0000000
--- a/drivers/media/dvb/frontends/drxk_map.h
+++ /dev/null
@@ -1,451 +0,0 @@
-#define  AUD_COMM_EXEC__A                                                  0x1000000
-#define    AUD_COMM_EXEC_STOP                                              0x0
-#define  FEC_COMM_EXEC__A                                                  0x1C00000
-#define    FEC_COMM_EXEC_STOP                                              0x0
-#define    FEC_COMM_EXEC_ACTIVE                                            0x1
-#define  FEC_DI_COMM_EXEC__A                                               0x1C20000
-#define    FEC_DI_COMM_EXEC_STOP                                           0x0
-#define  FEC_DI_INPUT_CTL__A                                               0x1C20016
-#define  FEC_RS_COMM_EXEC__A                                               0x1C30000
-#define    FEC_RS_COMM_EXEC_STOP                                           0x0
-#define  FEC_RS_MEASUREMENT_PERIOD__A                                      0x1C30012
-#define  FEC_RS_MEASUREMENT_PRESCALE__A                                    0x1C30013
-#define  FEC_OC_MODE__A                                                    0x1C40011
-#define    FEC_OC_MODE_PARITY__M                                           0x1
-#define  FEC_OC_DTO_MODE__A                                                0x1C40014
-#define    FEC_OC_DTO_MODE_DYNAMIC__M                                      0x1
-#define    FEC_OC_DTO_MODE_OFFSET_ENABLE__M                                0x4
-#define  FEC_OC_DTO_PERIOD__A                                              0x1C40015
-#define  FEC_OC_DTO_BURST_LEN__A                                           0x1C40018
-#define  FEC_OC_FCT_MODE__A                                                0x1C4001A
-#define  FEC_OC_FCT_MODE__PRE                                              0x0
-#define    FEC_OC_FCT_MODE_RAT_ENA__M                                      0x1
-#define    FEC_OC_FCT_MODE_VIRT_ENA__M                                     0x2
-#define  FEC_OC_TMD_MODE__A                                                0x1C4001E
-#define  FEC_OC_TMD_COUNT__A                                               0x1C4001F
-#define  FEC_OC_TMD_HI_MARGIN__A                                           0x1C40020
-#define  FEC_OC_TMD_LO_MARGIN__A                                           0x1C40021
-#define  FEC_OC_TMD_INT_UPD_RATE__A                                        0x1C40023
-#define  FEC_OC_AVR_PARM_A__A                                              0x1C40026
-#define  FEC_OC_AVR_PARM_B__A                                              0x1C40027
-#define  FEC_OC_RCN_GAIN__A                                                0x1C4002E
-#define  FEC_OC_RCN_CTL_RATE_LO__A                                         0x1C40030
-#define  FEC_OC_RCN_CTL_STEP_LO__A                                         0x1C40032
-#define  FEC_OC_RCN_CTL_STEP_HI__A                                         0x1C40033
-#define  FEC_OC_SNC_MODE__A                                                0x1C40040
-#define    FEC_OC_SNC_MODE_SHUTDOWN__M                                     0x10
-#define  FEC_OC_SNC_LWM__A                                                 0x1C40041
-#define  FEC_OC_SNC_HWM__A                                                 0x1C40042
-#define  FEC_OC_SNC_UNLOCK__A                                              0x1C40043
-#define  FEC_OC_SNC_FAIL_PERIOD__A                                         0x1C40046
-#define  FEC_OC_IPR_MODE__A                                                0x1C40048
-#define    FEC_OC_IPR_MODE_SERIAL__M                                       0x1
-#define    FEC_OC_IPR_MODE_MCLK_DIS_DAT_ABS__M                             0x4
-#define    FEC_OC_IPR_MODE_MVAL_DIS_PAR__M                                 0x10
-#define  FEC_OC_IPR_INVERT__A                                              0x1C40049
-#define    FEC_OC_IPR_INVERT_MD0__M                                        0x1
-#define    FEC_OC_IPR_INVERT_MD1__M                                        0x2
-#define    FEC_OC_IPR_INVERT_MD2__M                                        0x4
-#define    FEC_OC_IPR_INVERT_MD3__M                                        0x8
-#define    FEC_OC_IPR_INVERT_MD4__M                                        0x10
-#define    FEC_OC_IPR_INVERT_MD5__M                                        0x20
-#define    FEC_OC_IPR_INVERT_MD6__M                                        0x40
-#define    FEC_OC_IPR_INVERT_MD7__M                                        0x80
-#define    FEC_OC_IPR_INVERT_MERR__M                                       0x100
-#define    FEC_OC_IPR_INVERT_MSTRT__M                                      0x200
-#define    FEC_OC_IPR_INVERT_MVAL__M                                       0x400
-#define    FEC_OC_IPR_INVERT_MCLK__M                                       0x800
-#define  FEC_OC_OCR_INVERT__A                                              0x1C40052
-#define  IQM_COMM_EXEC__A                                                  0x1800000
-#define      IQM_COMM_EXEC_B_STOP                                          0x0
-#define      IQM_COMM_EXEC_B_ACTIVE                                        0x1
-#define  IQM_FS_RATE_OFS_LO__A                                             0x1820010
-#define  IQM_FS_ADJ_SEL__A                                                 0x1820014
-#define      IQM_FS_ADJ_SEL_B_OFF                                          0x0
-#define      IQM_FS_ADJ_SEL_B_QAM                                          0x1
-#define      IQM_FS_ADJ_SEL_B_VSB                                          0x2
-#define  IQM_FD_RATESEL__A                                                 0x1830010
-#define  IQM_RC_RATE_OFS_LO__A                                             0x1840010
-#define  IQM_RC_RATE_OFS_LO__W                                             16
-#define  IQM_RC_RATE_OFS_LO__M                                             0xFFFF
-#define  IQM_RC_RATE_OFS_HI__M                                             0xFF
-#define  IQM_RC_ADJ_SEL__A                                                 0x1840014
-#define      IQM_RC_ADJ_SEL_B_OFF                                          0x0
-#define      IQM_RC_ADJ_SEL_B_QAM                                          0x1
-#define      IQM_RC_ADJ_SEL_B_VSB                                          0x2
-#define  IQM_RC_STRETCH__A                                                 0x1840016
-#define  IQM_CF_COMM_INT_MSK__A                                            0x1860006
-#define  IQM_CF_SYMMETRIC__A                                               0x1860010
-#define  IQM_CF_MIDTAP__A                                                  0x1860011
-#define    IQM_CF_MIDTAP_RE__B                                             0
-#define    IQM_CF_MIDTAP_IM__B                                             1
-#define  IQM_CF_OUT_ENA__A                                                 0x1860012
-#define    IQM_CF_OUT_ENA_QAM__B                                           1
-#define    IQM_CF_OUT_ENA_OFDM__M                                          0x4
-#define  IQM_CF_ADJ_SEL__A                                                 0x1860013
-#define  IQM_CF_SCALE__A                                                   0x1860014
-#define  IQM_CF_SCALE_SH__A                                                0x1860015
-#define  IQM_CF_SCALE_SH__PRE                                              0x0
-#define  IQM_CF_POW_MEAS_LEN__A                                            0x1860017
-#define  IQM_CF_DS_ENA__A                                                  0x1860019
-#define  IQM_CF_TAP_RE0__A                                                 0x1860020
-#define  IQM_CF_TAP_IM0__A                                                 0x1860040
-#define  IQM_CF_CLP_VAL__A                                                 0x1860060
-#define  IQM_CF_DATATH__A                                                  0x1860061
-#define  IQM_CF_PKDTH__A                                                   0x1860062
-#define  IQM_CF_WND_LEN__A                                                 0x1860063
-#define  IQM_CF_DET_LCT__A                                                 0x1860064
-#define  IQM_CF_BYPASSDET__A                                               0x1860067
-#define  IQM_AF_COMM_EXEC__A                                               0x1870000
-#define    IQM_AF_COMM_EXEC_ACTIVE                                         0x1
-#define  IQM_AF_CLKNEG__A                                                  0x1870012
-#define    IQM_AF_CLKNEG_CLKNEGDATA__M                                     0x2
-#define      IQM_AF_CLKNEG_CLKNEGDATA_CLK_ADC_DATA_POS                     0x0
-#define      IQM_AF_CLKNEG_CLKNEGDATA_CLK_ADC_DATA_NEG                     0x2
-#define  IQM_AF_START_LOCK__A                                              0x187001B
-#define  IQM_AF_PHASE0__A                                                  0x187001C
-#define  IQM_AF_PHASE1__A                                                  0x187001D
-#define  IQM_AF_PHASE2__A                                                  0x187001E
-#define  IQM_AF_CLP_LEN__A                                                 0x1870023
-#define  IQM_AF_CLP_TH__A                                                  0x1870024
-#define  IQM_AF_SNS_LEN__A                                                 0x1870026
-#define  IQM_AF_AGC_IF__A                                                  0x1870028
-#define  IQM_AF_AGC_RF__A                                                  0x1870029
-#define  IQM_AF_PDREF__A                                                   0x187002B
-#define  IQM_AF_PDREF__M                                                   0x1F
-#define  IQM_AF_STDBY__A                                                   0x187002C
-#define      IQM_AF_STDBY_STDBY_ADC_STANDBY                                0x2
-#define      IQM_AF_STDBY_STDBY_AMP_STANDBY                                0x4
-#define      IQM_AF_STDBY_STDBY_PD_STANDBY                                 0x8
-#define      IQM_AF_STDBY_STDBY_TAGC_IF_STANDBY                            0x10
-#define      IQM_AF_STDBY_STDBY_TAGC_RF_STANDBY                            0x20
-#define  IQM_AF_AMUX__A                                                    0x187002D
-#define    IQM_AF_AMUX_SIGNAL2ADC                                          0x1
-#define  IQM_AF_UPD_SEL__A                                                 0x187002F
-#define  IQM_AF_INC_LCT__A                                                 0x1870034
-#define  IQM_AF_INC_BYPASS__A                                              0x1870036
-#define  OFDM_CP_COMM_EXEC__A                                              0x2800000
-#define    OFDM_CP_COMM_EXEC_STOP                                          0x0
-#define  OFDM_EC_SB_PRIOR__A                                               0x3410013
-#define    OFDM_EC_SB_PRIOR_HI                                             0x0
-#define    OFDM_EC_SB_PRIOR_LO                                             0x1
-#define  OFDM_EQ_TOP_TD_TPS_CONST__A                                       0x3010054
-#define  OFDM_EQ_TOP_TD_TPS_CONST__M                                       0x3
-#define    OFDM_EQ_TOP_TD_TPS_CONST_64QAM                                  0x2
-#define  OFDM_EQ_TOP_TD_TPS_CODE_HP__A                                     0x3010056
-#define  OFDM_EQ_TOP_TD_TPS_CODE_HP__M                                     0x7
-#define    OFDM_EQ_TOP_TD_TPS_CODE_LP_7_8                                  0x4
-#define  OFDM_EQ_TOP_TD_SQR_ERR_I__A                                       0x301005E
-#define  OFDM_EQ_TOP_TD_SQR_ERR_Q__A                                       0x301005F
-#define  OFDM_EQ_TOP_TD_SQR_ERR_EXP__A                                     0x3010060
-#define  OFDM_EQ_TOP_TD_REQ_SMB_CNT__A                                     0x3010061
-#define  OFDM_EQ_TOP_TD_TPS_PWR_OFS__A                                     0x3010062
-#define  OFDM_LC_COMM_EXEC__A                                              0x3800000
-#define    OFDM_LC_COMM_EXEC_STOP                                          0x0
-#define  OFDM_SC_COMM_EXEC__A                                              0x3C00000
-#define    OFDM_SC_COMM_EXEC_STOP                                          0x0
-#define  OFDM_SC_COMM_STATE__A                                             0x3C00001
-#define  OFDM_SC_RA_RAM_PARAM0__A                                          0x3C20040
-#define  OFDM_SC_RA_RAM_PARAM1__A                                          0x3C20041
-#define  OFDM_SC_RA_RAM_CMD_ADDR__A                                        0x3C20042
-#define  OFDM_SC_RA_RAM_CMD__A                                             0x3C20043
-#define    OFDM_SC_RA_RAM_CMD_NULL                                         0x0
-#define    OFDM_SC_RA_RAM_CMD_PROC_START                                   0x1
-#define    OFDM_SC_RA_RAM_CMD_SET_PREF_PARAM                               0x3
-#define    OFDM_SC_RA_RAM_CMD_PROGRAM_PARAM                                0x4
-#define    OFDM_SC_RA_RAM_CMD_GET_OP_PARAM                                 0x5
-#define    OFDM_SC_RA_RAM_CMD_USER_IO                                      0x6
-#define    OFDM_SC_RA_RAM_CMD_SET_TIMER                                    0x7
-#define    OFDM_SC_RA_RAM_CMD_SET_ECHO_TIMING                              0x8
-#define    OFDM_SC_RA_RAM_SW_EVENT_RUN_NMASK__M                            0x1
-#define    OFDM_SC_RA_RAM_LOCKTRACK_MIN                                    0x1
-#define  OFDM_SC_RA_RAM_OP_PARAM__A                                        0x3C20048
-#define    OFDM_SC_RA_RAM_OP_PARAM_MODE__M                                 0x3
-#define      OFDM_SC_RA_RAM_OP_PARAM_MODE_2K                               0x0
-#define      OFDM_SC_RA_RAM_OP_PARAM_MODE_8K                               0x1
-#define      OFDM_SC_RA_RAM_OP_PARAM_GUARD_32                              0x0
-#define      OFDM_SC_RA_RAM_OP_PARAM_GUARD_16                              0x4
-#define      OFDM_SC_RA_RAM_OP_PARAM_GUARD_8                               0x8
-#define      OFDM_SC_RA_RAM_OP_PARAM_GUARD_4                               0xC
-#define      OFDM_SC_RA_RAM_OP_PARAM_CONST_QPSK                            0x0
-#define      OFDM_SC_RA_RAM_OP_PARAM_CONST_QAM16                           0x10
-#define      OFDM_SC_RA_RAM_OP_PARAM_CONST_QAM64                           0x20
-#define      OFDM_SC_RA_RAM_OP_PARAM_HIER_NO                               0x0
-#define      OFDM_SC_RA_RAM_OP_PARAM_HIER_A1                               0x40
-#define      OFDM_SC_RA_RAM_OP_PARAM_HIER_A2                               0x80
-#define      OFDM_SC_RA_RAM_OP_PARAM_HIER_A4                               0xC0
-#define      OFDM_SC_RA_RAM_OP_PARAM_RATE_1_2                              0x0
-#define      OFDM_SC_RA_RAM_OP_PARAM_RATE_2_3                              0x200
-#define      OFDM_SC_RA_RAM_OP_PARAM_RATE_3_4                              0x400
-#define      OFDM_SC_RA_RAM_OP_PARAM_RATE_5_6                              0x600
-#define      OFDM_SC_RA_RAM_OP_PARAM_RATE_7_8                              0x800
-#define      OFDM_SC_RA_RAM_OP_PARAM_PRIO_HI                               0x0
-#define      OFDM_SC_RA_RAM_OP_PARAM_PRIO_LO                               0x1000
-#define    OFDM_SC_RA_RAM_OP_AUTO_MODE__M                                  0x1
-#define    OFDM_SC_RA_RAM_OP_AUTO_GUARD__M                                 0x2
-#define    OFDM_SC_RA_RAM_OP_AUTO_CONST__M                                 0x4
-#define    OFDM_SC_RA_RAM_OP_AUTO_HIER__M                                  0x8
-#define    OFDM_SC_RA_RAM_OP_AUTO_RATE__M                                  0x10
-#define  OFDM_SC_RA_RAM_LOCK__A                                            0x3C2004B
-#define    OFDM_SC_RA_RAM_LOCK_DEMOD__M                                    0x1
-#define    OFDM_SC_RA_RAM_LOCK_FEC__M                                      0x2
-#define    OFDM_SC_RA_RAM_LOCK_MPEG__M                                     0x4
-#define    OFDM_SC_RA_RAM_LOCK_NODVBT__M                                   0x8
-#define  OFDM_SC_RA_RAM_BE_OPT_DELAY__A                                    0x3C2004D
-#define  OFDM_SC_RA_RAM_BE_OPT_INIT_DELAY__A                               0x3C2004E
-#define  OFDM_SC_RA_RAM_ECHO_THRES__A                                      0x3C2004F
-#define    OFDM_SC_RA_RAM_ECHO_THRES_8K__B                                 0
-#define    OFDM_SC_RA_RAM_ECHO_THRES_8K__M                                 0xFF
-#define    OFDM_SC_RA_RAM_ECHO_THRES_2K__B                                 8
-#define    OFDM_SC_RA_RAM_ECHO_THRES_2K__M                                 0xFF00
-#define  OFDM_SC_RA_RAM_CONFIG__A                                          0x3C20050
-#define    OFDM_SC_RA_RAM_CONFIG_NE_FIX_ENABLE__M                          0x800
-#define  OFDM_SC_RA_RAM_FR_THRES_8K__A                                     0x3C2007D
-#define  OFDM_SC_RA_RAM_NI_INIT_2K_PER_LEFT__A                             0x3C200E0
-#define  OFDM_SC_RA_RAM_NI_INIT_2K_PER_RIGHT__A                            0x3C200E1
-#define  OFDM_SC_RA_RAM_NI_INIT_8K_PER_LEFT__A                             0x3C200E3
-#define  OFDM_SC_RA_RAM_NI_INIT_8K_PER_RIGHT__A                            0x3C200E4
-#define  OFDM_SC_RA_RAM_SRMM_FIX_FACT_8K__A                                0x3C200F8
-#define  QAM_COMM_EXEC__A                                                  0x1400000
-#define    QAM_COMM_EXEC_STOP                                              0x0
-#define    QAM_COMM_EXEC_ACTIVE                                            0x1
-#define    QAM_TOP_ANNEX_A                                                 0x0
-#define    QAM_TOP_ANNEX_C                                                 0x2
-#define  QAM_SL_ERR_POWER__A                                               0x1430017
-#define  QAM_DQ_QUAL_FUN0__A                                               0x1440018
-#define  QAM_DQ_QUAL_FUN1__A                                               0x1440019
-#define  QAM_DQ_QUAL_FUN2__A                                               0x144001A
-#define  QAM_DQ_QUAL_FUN3__A                                               0x144001B
-#define  QAM_DQ_QUAL_FUN4__A                                               0x144001C
-#define  QAM_DQ_QUAL_FUN5__A                                               0x144001D
-#define  QAM_LC_MODE__A                                                    0x1450010
-#define  QAM_LC_QUAL_TAB0__A                                               0x1450018
-#define  QAM_LC_QUAL_TAB1__A                                               0x1450019
-#define  QAM_LC_QUAL_TAB2__A                                               0x145001A
-#define  QAM_LC_QUAL_TAB3__A                                               0x145001B
-#define  QAM_LC_QUAL_TAB4__A                                               0x145001C
-#define  QAM_LC_QUAL_TAB5__A                                               0x145001D
-#define  QAM_LC_QUAL_TAB6__A                                               0x145001E
-#define  QAM_LC_QUAL_TAB8__A                                               0x145001F
-#define  QAM_LC_QUAL_TAB9__A                                               0x1450020
-#define  QAM_LC_QUAL_TAB10__A                                              0x1450021
-#define  QAM_LC_QUAL_TAB12__A                                              0x1450022
-#define  QAM_LC_QUAL_TAB15__A                                              0x1450023
-#define  QAM_LC_QUAL_TAB16__A                                              0x1450024
-#define  QAM_LC_QUAL_TAB20__A                                              0x1450025
-#define  QAM_LC_QUAL_TAB25__A                                              0x1450026
-#define  QAM_LC_LPF_FACTORP__A                                             0x1450028
-#define  QAM_LC_LPF_FACTORI__A                                             0x1450029
-#define  QAM_LC_RATE_LIMIT__A                                              0x145002A
-#define  QAM_LC_SYMBOL_FREQ__A                                             0x145002B
-#define  QAM_SY_TIMEOUT__A                                                 0x1470011
-#define  QAM_SY_TIMEOUT__PRE                                               0x3A98
-#define  QAM_SY_SYNC_LWM__A                                                0x1470012
-#define  QAM_SY_SYNC_AWM__A                                                0x1470013
-#define  QAM_SY_SYNC_HWM__A                                                0x1470014
-#define  QAM_SY_SP_INV__A                                                  0x1470017
-#define    QAM_SY_SP_INV_SPECTRUM_INV_DIS                                  0x0
-#define  SCU_COMM_EXEC__A                                                  0x800000
-#define    SCU_COMM_EXEC_STOP                                              0x0
-#define    SCU_COMM_EXEC_ACTIVE                                            0x1
-#define    SCU_COMM_EXEC_HOLD                                              0x2
-#define  SCU_RAM_DRIVER_DEBUG__A                                           0x831EBF
-#define  SCU_RAM_QAM_FSM_STEP_PERIOD__A                                    0x831EC4
-#define  SCU_RAM_GPIO__A                                                   0x831EC7
-#define      SCU_RAM_GPIO_HW_LOCK_IND_DISABLE                              0x0
-#define  SCU_RAM_AGC_CLP_CTRL_MODE__A                                      0x831EC8
-#define  SCU_RAM_FEC_ACCUM_PKT_FAILURES__A                                 0x831ECB
-#define  SCU_RAM_FEC_PRE_RS_BER_FILTER_SH__A                               0x831F05
-#define  SCU_RAM_AGC_FAST_SNS_CTRL_DELAY__A                                0x831F15
-#define  SCU_RAM_AGC_KI_CYCLEN__A                                          0x831F17
-#define  SCU_RAM_AGC_SNS_CYCLEN__A                                         0x831F18
-#define  SCU_RAM_AGC_RF_SNS_DEV_MAX__A                                     0x831F19
-#define  SCU_RAM_AGC_RF_SNS_DEV_MIN__A                                     0x831F1A
-#define  SCU_RAM_AGC_RF_MAX__A                                             0x831F1B
-#define  SCU_RAM_AGC_CONFIG__A                                             0x831F24
-#define    SCU_RAM_AGC_CONFIG_DISABLE_RF_AGC__M                            0x1
-#define    SCU_RAM_AGC_CONFIG_DISABLE_IF_AGC__M                            0x2
-#define    SCU_RAM_AGC_CONFIG_INV_IF_POL__M                                0x100
-#define    SCU_RAM_AGC_CONFIG_INV_RF_POL__M                                0x200
-#define  SCU_RAM_AGC_KI__A                                                 0x831F25
-#define    SCU_RAM_AGC_KI_RF__B                                            4
-#define    SCU_RAM_AGC_KI_RF__M                                            0xF0
-#define    SCU_RAM_AGC_KI_IF__B                                            8
-#define    SCU_RAM_AGC_KI_IF__M                                            0xF00
-#define  SCU_RAM_AGC_KI_RED__A                                             0x831F26
-#define    SCU_RAM_AGC_KI_RED_RAGC_RED__B                                  2
-#define    SCU_RAM_AGC_KI_RED_RAGC_RED__M                                  0xC
-#define    SCU_RAM_AGC_KI_RED_IAGC_RED__B                                  4
-#define    SCU_RAM_AGC_KI_RED_IAGC_RED__M                                  0x30
-#define  SCU_RAM_AGC_KI_INNERGAIN_MIN__A                                   0x831F27
-#define  SCU_RAM_AGC_KI_MINGAIN__A                                         0x831F28
-#define  SCU_RAM_AGC_KI_MAXGAIN__A                                         0x831F29
-#define  SCU_RAM_AGC_KI_MAXMINGAIN_TH__A                                   0x831F2A
-#define  SCU_RAM_AGC_KI_MIN__A                                             0x831F2B
-#define  SCU_RAM_AGC_KI_MAX__A                                             0x831F2C
-#define  SCU_RAM_AGC_CLP_SUM__A                                            0x831F2D
-#define  SCU_RAM_AGC_CLP_SUM_MIN__A                                        0x831F2E
-#define  SCU_RAM_AGC_CLP_SUM_MAX__A                                        0x831F2F
-#define  SCU_RAM_AGC_CLP_CYCLEN__A                                         0x831F30
-#define  SCU_RAM_AGC_CLP_CYCCNT__A                                         0x831F31
-#define  SCU_RAM_AGC_CLP_DIR_TO__A                                         0x831F32
-#define  SCU_RAM_AGC_CLP_DIR_WD__A                                         0x831F33
-#define  SCU_RAM_AGC_CLP_DIR_STP__A                                        0x831F34
-#define  SCU_RAM_AGC_SNS_SUM__A                                            0x831F35
-#define  SCU_RAM_AGC_SNS_SUM_MIN__A                                        0x831F36
-#define  SCU_RAM_AGC_SNS_SUM_MAX__A                                        0x831F37
-#define  SCU_RAM_AGC_SNS_CYCCNT__A                                         0x831F38
-#define  SCU_RAM_AGC_SNS_DIR_TO__A                                         0x831F39
-#define  SCU_RAM_AGC_SNS_DIR_WD__A                                         0x831F3A
-#define  SCU_RAM_AGC_SNS_DIR_STP__A                                        0x831F3B
-#define  SCU_RAM_AGC_INGAIN_TGT__A                                         0x831F3D
-#define  SCU_RAM_AGC_INGAIN_TGT_MIN__A                                     0x831F3E
-#define  SCU_RAM_AGC_INGAIN_TGT_MAX__A                                     0x831F3F
-#define  SCU_RAM_AGC_IF_IACCU_HI__A                                        0x831F40
-#define  SCU_RAM_AGC_IF_IACCU_LO__A                                        0x831F41
-#define  SCU_RAM_AGC_IF_IACCU_HI_TGT__A                                    0x831F42
-#define  SCU_RAM_AGC_IF_IACCU_HI_TGT_MIN__A                                0x831F43
-#define  SCU_RAM_AGC_IF_IACCU_HI_TGT_MAX__A                                0x831F44
-#define  SCU_RAM_AGC_RF_IACCU_HI__A                                        0x831F45
-#define  SCU_RAM_AGC_RF_IACCU_LO__A                                        0x831F46
-#define  SCU_RAM_AGC_RF_IACCU_HI_CO__A                                     0x831F47
-#define  SCU_RAM_QAM_FSM_MEDIAN_AV_MULT__A                                 0x831F84
-#define  SCU_RAM_QAM_FSM_RADIUS_AV_LIMIT__A                                0x831F85
-#define  SCU_RAM_QAM_FSM_LCAVG_OFFSET1__A                                  0x831F86
-#define  SCU_RAM_QAM_FSM_LCAVG_OFFSET2__A                                  0x831F87
-#define  SCU_RAM_QAM_FSM_LCAVG_OFFSET3__A                                  0x831F88
-#define  SCU_RAM_QAM_FSM_LCAVG_OFFSET4__A                                  0x831F89
-#define  SCU_RAM_QAM_FSM_LCAVG_OFFSET5__A                                  0x831F8A
-#define  SCU_RAM_QAM_FSM_RTH__A                                            0x831F8E
-#define  SCU_RAM_QAM_FSM_FTH__A                                            0x831F8F
-#define  SCU_RAM_QAM_FSM_PTH__A                                            0x831F90
-#define  SCU_RAM_QAM_FSM_MTH__A                                            0x831F91
-#define  SCU_RAM_QAM_FSM_CTH__A                                            0x831F92
-#define  SCU_RAM_QAM_FSM_QTH__A                                            0x831F93
-#define  SCU_RAM_QAM_FSM_RATE_LIM__A                                       0x831F94
-#define  SCU_RAM_QAM_FSM_FREQ_LIM__A                                       0x831F95
-#define  SCU_RAM_QAM_FSM_COUNT_LIM__A                                      0x831F96
-#define  SCU_RAM_QAM_LC_CA_COARSE__A                                       0x831F97
-#define  SCU_RAM_QAM_LC_CA_FINE__A                                         0x831F99
-#define  SCU_RAM_QAM_LC_CP_COARSE__A                                       0x831F9A
-#define  SCU_RAM_QAM_LC_CP_MEDIUM__A                                       0x831F9B
-#define  SCU_RAM_QAM_LC_CP_FINE__A                                         0x831F9C
-#define  SCU_RAM_QAM_LC_CI_COARSE__A                                       0x831F9D
-#define  SCU_RAM_QAM_LC_CI_MEDIUM__A                                       0x831F9E
-#define  SCU_RAM_QAM_LC_CI_FINE__A                                         0x831F9F
-#define  SCU_RAM_QAM_LC_EP_COARSE__A                                       0x831FA0
-#define  SCU_RAM_QAM_LC_EP_MEDIUM__A                                       0x831FA1
-#define  SCU_RAM_QAM_LC_EP_FINE__A                                         0x831FA2
-#define  SCU_RAM_QAM_LC_EI_COARSE__A                                       0x831FA3
-#define  SCU_RAM_QAM_LC_EI_MEDIUM__A                                       0x831FA4
-#define  SCU_RAM_QAM_LC_EI_FINE__A                                         0x831FA5
-#define  SCU_RAM_QAM_LC_CF_COARSE__A                                       0x831FA6
-#define  SCU_RAM_QAM_LC_CF_MEDIUM__A                                       0x831FA7
-#define  SCU_RAM_QAM_LC_CF_FINE__A                                         0x831FA8
-#define  SCU_RAM_QAM_LC_CF1_COARSE__A                                      0x831FA9
-#define  SCU_RAM_QAM_LC_CF1_MEDIUM__A                                      0x831FAA
-#define  SCU_RAM_QAM_LC_CF1_FINE__A                                        0x831FAB
-#define  SCU_RAM_QAM_SL_SIG_POWER__A                                       0x831FAC
-#define  SCU_RAM_QAM_EQ_CMA_RAD0__A                                        0x831FAD
-#define  SCU_RAM_QAM_EQ_CMA_RAD1__A                                        0x831FAE
-#define  SCU_RAM_QAM_EQ_CMA_RAD2__A                                        0x831FAF
-#define  SCU_RAM_QAM_EQ_CMA_RAD3__A                                        0x831FB0
-#define  SCU_RAM_QAM_EQ_CMA_RAD4__A                                        0x831FB1
-#define  SCU_RAM_QAM_EQ_CMA_RAD5__A                                        0x831FB2
-#define      SCU_RAM_QAM_LOCKED_LOCKED_DEMOD_LOCKED                        0x4000
-#define      SCU_RAM_QAM_LOCKED_LOCKED_LOCKED                              0x8000
-#define      SCU_RAM_QAM_LOCKED_LOCKED_NEVER_LOCK                          0xC000
-#define  SCU_RAM_AGC_FAST_CLP_CTRL_DELAY__A                                0x831FEA
-#define  SCU_RAM_DRIVER_VER_HI__A                                          0x831FEB
-#define  SCU_RAM_DRIVER_VER_LO__A                                          0x831FEC
-#define  SCU_RAM_PARAM_15__A                                               0x831FED
-#define  SCU_RAM_PARAM_0__A                                                0x831FFC
-#define  SCU_RAM_COMMAND__A                                                0x831FFD
-#define    SCU_RAM_COMMAND_CMD_DEMOD_RESET                                 0x1
-#define    SCU_RAM_COMMAND_CMD_DEMOD_SET_ENV                               0x2
-#define    SCU_RAM_COMMAND_CMD_DEMOD_SET_PARAM                             0x3
-#define    SCU_RAM_COMMAND_CMD_DEMOD_START                                 0x4
-#define    SCU_RAM_COMMAND_CMD_DEMOD_GET_LOCK                              0x5
-#define    SCU_RAM_COMMAND_CMD_DEMOD_STOP                                  0x9
-#define      SCU_RAM_COMMAND_STANDARD_QAM                                  0x200
-#define      SCU_RAM_COMMAND_STANDARD_OFDM                                 0x400
-#define  SIO_TOP_COMM_KEY__A                                               0x41000F
-#define    SIO_TOP_COMM_KEY_KEY                                            0xFABA
-#define  SIO_TOP_JTAGID_LO__A                                              0x410012
-#define  SIO_HI_RA_RAM_RES__A                                              0x420031
-#define  SIO_HI_RA_RAM_CMD__A                                              0x420032
-#define    SIO_HI_RA_RAM_CMD_RESET                                         0x2
-#define    SIO_HI_RA_RAM_CMD_CONFIG                                        0x3
-#define    SIO_HI_RA_RAM_CMD_BRDCTRL                                       0x7
-#define  SIO_HI_RA_RAM_PAR_1__A                                            0x420033
-#define      SIO_HI_RA_RAM_PAR_1_PAR1_SEC_KEY                              0x3945
-#define  SIO_HI_RA_RAM_PAR_2__A                                            0x420034
-#define    SIO_HI_RA_RAM_PAR_2_CFG_DIV__M                                  0x7F
-#define      SIO_HI_RA_RAM_PAR_2_BRD_CFG_OPEN                              0x0
-#define      SIO_HI_RA_RAM_PAR_2_BRD_CFG_CLOSED                            0x4
-#define  SIO_HI_RA_RAM_PAR_3__A                                            0x420035
-#define    SIO_HI_RA_RAM_PAR_3_CFG_DBL_SDA__M                              0x7F
-#define    SIO_HI_RA_RAM_PAR_3_CFG_DBL_SCL__B                              7
-#define      SIO_HI_RA_RAM_PAR_3_ACP_RW_READ                               0x0
-#define      SIO_HI_RA_RAM_PAR_3_ACP_RW_WRITE                              0x8
-#define  SIO_HI_RA_RAM_PAR_4__A                                            0x420036
-#define  SIO_HI_RA_RAM_PAR_5__A                                            0x420037
-#define      SIO_HI_RA_RAM_PAR_5_CFG_SLV0_SLAVE                            0x1
-#define    SIO_HI_RA_RAM_PAR_5_CFG_SLEEP__M                                0x8
-#define      SIO_HI_RA_RAM_PAR_5_CFG_SLEEP_ZZZ                             0x8
-#define  SIO_HI_RA_RAM_PAR_6__A                                            0x420038
-#define  SIO_CC_PLL_LOCK__A                                                0x450012
-#define  SIO_CC_PWD_MODE__A                                                0x450015
-#define      SIO_CC_PWD_MODE_LEVEL_NONE                                    0x0
-#define      SIO_CC_PWD_MODE_LEVEL_OFDM                                    0x1
-#define      SIO_CC_PWD_MODE_LEVEL_CLOCK                                   0x2
-#define      SIO_CC_PWD_MODE_LEVEL_PLL                                     0x3
-#define      SIO_CC_PWD_MODE_LEVEL_OSC                                     0x4
-#define  SIO_CC_SOFT_RST__A                                                0x450016
-#define    SIO_CC_SOFT_RST_OFDM__M                                         0x1
-#define    SIO_CC_SOFT_RST_SYS__M                                          0x2
-#define    SIO_CC_SOFT_RST_OSC__M                                          0x4
-#define  SIO_CC_UPDATE__A                                                  0x450017
-#define    SIO_CC_UPDATE_KEY                                               0xFABA
-#define  SIO_OFDM_SH_OFDM_RING_ENABLE__A                                   0x470010
-#define    SIO_OFDM_SH_OFDM_RING_ENABLE_OFF                                0x0
-#define    SIO_OFDM_SH_OFDM_RING_ENABLE_ON                                 0x1
-#define  SIO_OFDM_SH_OFDM_RING_STATUS__A                                   0x470012
-#define    SIO_OFDM_SH_OFDM_RING_STATUS_DOWN                               0x0
-#define    SIO_OFDM_SH_OFDM_RING_STATUS_ENABLED                            0x1
-#define  SIO_BL_COMM_EXEC__A                                               0x480000
-#define    SIO_BL_COMM_EXEC_ACTIVE                                         0x1
-#define  SIO_BL_STATUS__A                                                  0x480010
-#define  SIO_BL_MODE__A                                                    0x480011
-#define    SIO_BL_MODE_DIRECT                                              0x0
-#define    SIO_BL_MODE_CHAIN                                               0x1
-#define  SIO_BL_ENABLE__A                                                  0x480012
-#define    SIO_BL_ENABLE_ON                                                0x1
-#define  SIO_BL_TGT_HDR__A                                                 0x480014
-#define  SIO_BL_TGT_ADDR__A                                                0x480015
-#define  SIO_BL_SRC_ADDR__A                                                0x480016
-#define  SIO_BL_SRC_LEN__A                                                 0x480017
-#define  SIO_BL_CHAIN_ADDR__A                                              0x480018
-#define  SIO_BL_CHAIN_LEN__A                                               0x480019
-#define  SIO_PDR_MON_CFG__A                                                0x7F0010
-#define  SIO_PDR_UIO_IN_HI__A                                              0x7F0015
-#define  SIO_PDR_UIO_OUT_LO__A                                             0x7F0016
-#define  SIO_PDR_OHW_CFG__A                                                0x7F001F
-#define    SIO_PDR_OHW_CFG_FREF_SEL__M                                     0x3
-#define  SIO_PDR_GPIO_CFG__A                                               0x7F0021
-#define  SIO_PDR_MSTRT_CFG__A                                              0x7F0025
-#define  SIO_PDR_MERR_CFG__A                                               0x7F0026
-#define  SIO_PDR_MCLK_CFG__A                                               0x7F0028
-#define    SIO_PDR_MCLK_CFG_DRIVE__B                                       3
-#define  SIO_PDR_MVAL_CFG__A                                               0x7F0029
-#define  SIO_PDR_MD0_CFG__A                                                0x7F002A
-#define    SIO_PDR_MD0_CFG_DRIVE__B                                        3
-#define  SIO_PDR_MD1_CFG__A                                                0x7F002B
-#define  SIO_PDR_MD2_CFG__A                                                0x7F002C
-#define  SIO_PDR_MD3_CFG__A                                                0x7F002D
-#define  SIO_PDR_MD4_CFG__A                                                0x7F002F
-#define  SIO_PDR_MD5_CFG__A                                                0x7F0030
-#define  SIO_PDR_MD6_CFG__A                                                0x7F0031
-#define  SIO_PDR_MD7_CFG__A                                                0x7F0032
-#define  SIO_PDR_SMA_RX_CFG__A                                             0x7F0037
-#define  SIO_PDR_SMA_TX_CFG__A                                             0x7F0038
diff --git a/drivers/media/dvb/frontends/ds3000.c b/drivers/media/dvb/frontends/ds3000.c
deleted file mode 100644
index 4c8ac26..0000000
--- a/drivers/media/dvb/frontends/ds3000.c
+++ /dev/null
@@ -1,1312 +0,0 @@
-/*
-    Montage Technology DS3000/TS2020 - DVBS/S2 Demodulator/Tuner driver
-    Copyright (C) 2009 Konstantin Dimitrov <kosio.dimitrov@gmail.com>
-
-    Copyright (C) 2009 TurboSight.com
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/slab.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/init.h>
-#include <linux/firmware.h>
-
-#include "dvb_frontend.h"
-#include "ds3000.h"
-
-static int debug;
-
-#define dprintk(args...) \
-	do { \
-		if (debug) \
-			printk(args); \
-	} while (0)
-
-/* as of March 2009 current DS3000 firmware version is 1.78 */
-/* DS3000 FW v1.78 MD5: a32d17910c4f370073f9346e71d34b80 */
-#define DS3000_DEFAULT_FIRMWARE "dvb-fe-ds3000.fw"
-
-#define DS3000_SAMPLE_RATE 96000 /* in kHz */
-#define DS3000_XTAL_FREQ   27000 /* in kHz */
-
-/* Register values to initialise the demod in DVB-S mode */
-static u8 ds3000_dvbs_init_tab[] = {
-	0x23, 0x05,
-	0x08, 0x03,
-	0x0c, 0x00,
-	0x21, 0x54,
-	0x25, 0x82,
-	0x27, 0x31,
-	0x30, 0x08,
-	0x31, 0x40,
-	0x32, 0x32,
-	0x33, 0x35,
-	0x35, 0xff,
-	0x3a, 0x00,
-	0x37, 0x10,
-	0x38, 0x10,
-	0x39, 0x02,
-	0x42, 0x60,
-	0x4a, 0x40,
-	0x4b, 0x04,
-	0x4d, 0x91,
-	0x5d, 0xc8,
-	0x50, 0x77,
-	0x51, 0x77,
-	0x52, 0x36,
-	0x53, 0x36,
-	0x56, 0x01,
-	0x63, 0x43,
-	0x64, 0x30,
-	0x65, 0x40,
-	0x68, 0x26,
-	0x69, 0x4c,
-	0x70, 0x20,
-	0x71, 0x70,
-	0x72, 0x04,
-	0x73, 0x00,
-	0x70, 0x40,
-	0x71, 0x70,
-	0x72, 0x04,
-	0x73, 0x00,
-	0x70, 0x60,
-	0x71, 0x70,
-	0x72, 0x04,
-	0x73, 0x00,
-	0x70, 0x80,
-	0x71, 0x70,
-	0x72, 0x04,
-	0x73, 0x00,
-	0x70, 0xa0,
-	0x71, 0x70,
-	0x72, 0x04,
-	0x73, 0x00,
-	0x70, 0x1f,
-	0x76, 0x00,
-	0x77, 0xd1,
-	0x78, 0x0c,
-	0x79, 0x80,
-	0x7f, 0x04,
-	0x7c, 0x00,
-	0x80, 0x86,
-	0x81, 0xa6,
-	0x85, 0x04,
-	0xcd, 0xf4,
-	0x90, 0x33,
-	0xa0, 0x44,
-	0xc0, 0x18,
-	0xc3, 0x10,
-	0xc4, 0x08,
-	0xc5, 0x80,
-	0xc6, 0x80,
-	0xc7, 0x0a,
-	0xc8, 0x1a,
-	0xc9, 0x80,
-	0xfe, 0x92,
-	0xe0, 0xf8,
-	0xe6, 0x8b,
-	0xd0, 0x40,
-	0xf8, 0x20,
-	0xfa, 0x0f,
-	0xfd, 0x20,
-	0xad, 0x20,
-	0xae, 0x07,
-	0xb8, 0x00,
-};
-
-/* Register values to initialise the demod in DVB-S2 mode */
-static u8 ds3000_dvbs2_init_tab[] = {
-	0x23, 0x0f,
-	0x08, 0x07,
-	0x0c, 0x00,
-	0x21, 0x54,
-	0x25, 0x82,
-	0x27, 0x31,
-	0x30, 0x08,
-	0x31, 0x32,
-	0x32, 0x32,
-	0x33, 0x35,
-	0x35, 0xff,
-	0x3a, 0x00,
-	0x37, 0x10,
-	0x38, 0x10,
-	0x39, 0x02,
-	0x42, 0x60,
-	0x4a, 0x80,
-	0x4b, 0x04,
-	0x4d, 0x81,
-	0x5d, 0x88,
-	0x50, 0x36,
-	0x51, 0x36,
-	0x52, 0x36,
-	0x53, 0x36,
-	0x63, 0x60,
-	0x64, 0x10,
-	0x65, 0x10,
-	0x68, 0x04,
-	0x69, 0x29,
-	0x70, 0x20,
-	0x71, 0x70,
-	0x72, 0x04,
-	0x73, 0x00,
-	0x70, 0x40,
-	0x71, 0x70,
-	0x72, 0x04,
-	0x73, 0x00,
-	0x70, 0x60,
-	0x71, 0x70,
-	0x72, 0x04,
-	0x73, 0x00,
-	0x70, 0x80,
-	0x71, 0x70,
-	0x72, 0x04,
-	0x73, 0x00,
-	0x70, 0xa0,
-	0x71, 0x70,
-	0x72, 0x04,
-	0x73, 0x00,
-	0x70, 0x1f,
-	0xa0, 0x44,
-	0xc0, 0x08,
-	0xc1, 0x10,
-	0xc2, 0x08,
-	0xc3, 0x10,
-	0xc4, 0x08,
-	0xc5, 0xf0,
-	0xc6, 0xf0,
-	0xc7, 0x0a,
-	0xc8, 0x1a,
-	0xc9, 0x80,
-	0xca, 0x23,
-	0xcb, 0x24,
-	0xce, 0x74,
-	0x90, 0x03,
-	0x76, 0x80,
-	0x77, 0x42,
-	0x78, 0x0a,
-	0x79, 0x80,
-	0xad, 0x40,
-	0xae, 0x07,
-	0x7f, 0xd4,
-	0x7c, 0x00,
-	0x80, 0xa8,
-	0x81, 0xda,
-	0x7c, 0x01,
-	0x80, 0xda,
-	0x81, 0xec,
-	0x7c, 0x02,
-	0x80, 0xca,
-	0x81, 0xeb,
-	0x7c, 0x03,
-	0x80, 0xba,
-	0x81, 0xdb,
-	0x85, 0x08,
-	0x86, 0x00,
-	0x87, 0x02,
-	0x89, 0x80,
-	0x8b, 0x44,
-	0x8c, 0xaa,
-	0x8a, 0x10,
-	0xba, 0x00,
-	0xf5, 0x04,
-	0xfe, 0x44,
-	0xd2, 0x32,
-	0xb8, 0x00,
-};
-
-struct ds3000_state {
-	struct i2c_adapter *i2c;
-	const struct ds3000_config *config;
-	struct dvb_frontend frontend;
-	u8 skip_fw_load;
-	/* previous uncorrected block counter for DVB-S2 */
-	u16 prevUCBS2;
-};
-
-static int ds3000_writereg(struct ds3000_state *state, int reg, int data)
-{
-	u8 buf[] = { reg, data };
-	struct i2c_msg msg = { .addr = state->config->demod_address,
-		.flags = 0, .buf = buf, .len = 2 };
-	int err;
-
-	dprintk("%s: write reg 0x%02x, value 0x%02x\n", __func__, reg, data);
-
-	err = i2c_transfer(state->i2c, &msg, 1);
-	if (err != 1) {
-		printk(KERN_ERR "%s: writereg error(err == %i, reg == 0x%02x,"
-			 " value == 0x%02x)\n", __func__, err, reg, data);
-		return -EREMOTEIO;
-	}
-
-	return 0;
-}
-
-static int ds3000_tuner_writereg(struct ds3000_state *state, int reg, int data)
-{
-	u8 buf[] = { reg, data };
-	struct i2c_msg msg = { .addr = 0x60,
-		.flags = 0, .buf = buf, .len = 2 };
-	int err;
-
-	dprintk("%s: write reg 0x%02x, value 0x%02x\n", __func__, reg, data);
-
-	ds3000_writereg(state, 0x03, 0x11);
-	err = i2c_transfer(state->i2c, &msg, 1);
-	if (err != 1) {
-		printk("%s: writereg error(err == %i, reg == 0x%02x,"
-			 " value == 0x%02x)\n", __func__, err, reg, data);
-		return -EREMOTEIO;
-	}
-
-	return 0;
-}
-
-/* I2C write for 8k firmware load */
-static int ds3000_writeFW(struct ds3000_state *state, int reg,
-				const u8 *data, u16 len)
-{
-	int i, ret = -EREMOTEIO;
-	struct i2c_msg msg;
-	u8 *buf;
-
-	buf = kmalloc(33, GFP_KERNEL);
-	if (buf == NULL) {
-		printk(KERN_ERR "Unable to kmalloc\n");
-		ret = -ENOMEM;
-		goto error;
-	}
-
-	*(buf) = reg;
-
-	msg.addr = state->config->demod_address;
-	msg.flags = 0;
-	msg.buf = buf;
-	msg.len = 33;
-
-	for (i = 0; i < len; i += 32) {
-		memcpy(buf + 1, data + i, 32);
-
-		dprintk("%s: write reg 0x%02x, len = %d\n", __func__, reg, len);
-
-		ret = i2c_transfer(state->i2c, &msg, 1);
-		if (ret != 1) {
-			printk(KERN_ERR "%s: write error(err == %i, "
-				"reg == 0x%02x\n", __func__, ret, reg);
-			ret = -EREMOTEIO;
-		}
-	}
-
-error:
-	kfree(buf);
-
-	return ret;
-}
-
-static int ds3000_readreg(struct ds3000_state *state, u8 reg)
-{
-	int ret;
-	u8 b0[] = { reg };
-	u8 b1[] = { 0 };
-	struct i2c_msg msg[] = {
-		{
-			.addr = state->config->demod_address,
-			.flags = 0,
-			.buf = b0,
-			.len = 1
-		}, {
-			.addr = state->config->demod_address,
-			.flags = I2C_M_RD,
-			.buf = b1,
-			.len = 1
-		}
-	};
-
-	ret = i2c_transfer(state->i2c, msg, 2);
-
-	if (ret != 2) {
-		printk(KERN_ERR "%s: reg=0x%x(error=%d)\n", __func__, reg, ret);
-		return ret;
-	}
-
-	dprintk("%s: read reg 0x%02x, value 0x%02x\n", __func__, reg, b1[0]);
-
-	return b1[0];
-}
-
-static int ds3000_tuner_readreg(struct ds3000_state *state, u8 reg)
-{
-	int ret;
-	u8 b0[] = { reg };
-	u8 b1[] = { 0 };
-	struct i2c_msg msg[] = {
-		{
-			.addr = 0x60,
-			.flags = 0,
-			.buf = b0,
-			.len = 1
-		}, {
-			.addr = 0x60,
-			.flags = I2C_M_RD,
-			.buf = b1,
-			.len = 1
-		}
-	};
-
-	ds3000_writereg(state, 0x03, 0x12);
-	ret = i2c_transfer(state->i2c, msg, 2);
-
-	if (ret != 2) {
-		printk(KERN_ERR "%s: reg=0x%x(error=%d)\n", __func__, reg, ret);
-		return ret;
-	}
-
-	dprintk("%s: read reg 0x%02x, value 0x%02x\n", __func__, reg, b1[0]);
-
-	return b1[0];
-}
-
-static int ds3000_load_firmware(struct dvb_frontend *fe,
-					const struct firmware *fw);
-
-static int ds3000_firmware_ondemand(struct dvb_frontend *fe)
-{
-	struct ds3000_state *state = fe->demodulator_priv;
-	const struct firmware *fw;
-	int ret = 0;
-
-	dprintk("%s()\n", __func__);
-
-	if (ds3000_readreg(state, 0xb2) <= 0)
-		return ret;
-
-	if (state->skip_fw_load)
-		return 0;
-	/* Load firmware */
-	/* request the firmware, this will block until someone uploads it */
-	printk(KERN_INFO "%s: Waiting for firmware upload (%s)...\n", __func__,
-				DS3000_DEFAULT_FIRMWARE);
-	ret = request_firmware(&fw, DS3000_DEFAULT_FIRMWARE,
-				state->i2c->dev.parent);
-	printk(KERN_INFO "%s: Waiting for firmware upload(2)...\n", __func__);
-	if (ret) {
-		printk(KERN_ERR "%s: No firmware uploaded (timeout or file not "
-				"found?)\n", __func__);
-		return ret;
-	}
-
-	/* Make sure we don't recurse back through here during loading */
-	state->skip_fw_load = 1;
-
-	ret = ds3000_load_firmware(fe, fw);
-	if (ret)
-		printk("%s: Writing firmware to device failed\n", __func__);
-
-	release_firmware(fw);
-
-	dprintk("%s: Firmware upload %s\n", __func__,
-			ret == 0 ? "complete" : "failed");
-
-	/* Ensure firmware is always loaded if required */
-	state->skip_fw_load = 0;
-
-	return ret;
-}
-
-static int ds3000_load_firmware(struct dvb_frontend *fe,
-					const struct firmware *fw)
-{
-	struct ds3000_state *state = fe->demodulator_priv;
-
-	dprintk("%s\n", __func__);
-	dprintk("Firmware is %zu bytes (%02x %02x .. %02x %02x)\n",
-			fw->size,
-			fw->data[0],
-			fw->data[1],
-			fw->data[fw->size - 2],
-			fw->data[fw->size - 1]);
-
-	/* Begin the firmware load process */
-	ds3000_writereg(state, 0xb2, 0x01);
-	/* write the entire firmware */
-	ds3000_writeFW(state, 0xb0, fw->data, fw->size);
-	ds3000_writereg(state, 0xb2, 0x00);
-
-	return 0;
-}
-
-static int ds3000_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
-{
-	struct ds3000_state *state = fe->demodulator_priv;
-	u8 data;
-
-	dprintk("%s(%d)\n", __func__, voltage);
-
-	data = ds3000_readreg(state, 0xa2);
-	data |= 0x03; /* bit0 V/H, bit1 off/on */
-
-	switch (voltage) {
-	case SEC_VOLTAGE_18:
-		data &= ~0x03;
-		break;
-	case SEC_VOLTAGE_13:
-		data &= ~0x03;
-		data |= 0x01;
-		break;
-	case SEC_VOLTAGE_OFF:
-		break;
-	}
-
-	ds3000_writereg(state, 0xa2, data);
-
-	return 0;
-}
-
-static int ds3000_read_status(struct dvb_frontend *fe, fe_status_t* status)
-{
-	struct ds3000_state *state = fe->demodulator_priv;
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	int lock;
-
-	*status = 0;
-
-	switch (c->delivery_system) {
-	case SYS_DVBS:
-		lock = ds3000_readreg(state, 0xd1);
-		if ((lock & 0x07) == 0x07)
-			*status = FE_HAS_SIGNAL | FE_HAS_CARRIER |
-				FE_HAS_VITERBI | FE_HAS_SYNC |
-				FE_HAS_LOCK;
-
-		break;
-	case SYS_DVBS2:
-		lock = ds3000_readreg(state, 0x0d);
-		if ((lock & 0x8f) == 0x8f)
-			*status = FE_HAS_SIGNAL | FE_HAS_CARRIER |
-				FE_HAS_VITERBI | FE_HAS_SYNC |
-				FE_HAS_LOCK;
-
-		break;
-	default:
-		return 1;
-	}
-
-	dprintk("%s: status = 0x%02x\n", __func__, lock);
-
-	return 0;
-}
-
-/* read DS3000 BER value */
-static int ds3000_read_ber(struct dvb_frontend *fe, u32* ber)
-{
-	struct ds3000_state *state = fe->demodulator_priv;
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	u8 data;
-	u32 ber_reading, lpdc_frames;
-
-	dprintk("%s()\n", __func__);
-
-	switch (c->delivery_system) {
-	case SYS_DVBS:
-		/* set the number of bytes checked during
-		BER estimation */
-		ds3000_writereg(state, 0xf9, 0x04);
-		/* read BER estimation status */
-		data = ds3000_readreg(state, 0xf8);
-		/* check if BER estimation is ready */
-		if ((data & 0x10) == 0) {
-			/* this is the number of error bits,
-			to calculate the bit error rate
-			divide to 8388608 */
-			*ber = (ds3000_readreg(state, 0xf7) << 8) |
-				ds3000_readreg(state, 0xf6);
-			/* start counting error bits */
-			/* need to be set twice
-			otherwise it fails sometimes */
-			data |= 0x10;
-			ds3000_writereg(state, 0xf8, data);
-			ds3000_writereg(state, 0xf8, data);
-		} else
-			/* used to indicate that BER estimation
-			is not ready, i.e. BER is unknown */
-			*ber = 0xffffffff;
-		break;
-	case SYS_DVBS2:
-		/* read the number of LPDC decoded frames */
-		lpdc_frames = (ds3000_readreg(state, 0xd7) << 16) |
-				(ds3000_readreg(state, 0xd6) << 8) |
-				ds3000_readreg(state, 0xd5);
-		/* read the number of packets with bad CRC */
-		ber_reading = (ds3000_readreg(state, 0xf8) << 8) |
-				ds3000_readreg(state, 0xf7);
-		if (lpdc_frames > 750) {
-			/* clear LPDC frame counters */
-			ds3000_writereg(state, 0xd1, 0x01);
-			/* clear bad packets counter */
-			ds3000_writereg(state, 0xf9, 0x01);
-			/* enable bad packets counter */
-			ds3000_writereg(state, 0xf9, 0x00);
-			/* enable LPDC frame counters */
-			ds3000_writereg(state, 0xd1, 0x00);
-			*ber = ber_reading;
-		} else
-			/* used to indicate that BER estimation is not ready,
-			i.e. BER is unknown */
-			*ber = 0xffffffff;
-		break;
-	default:
-		return 1;
-	}
-
-	return 0;
-}
-
-/* read TS2020 signal strength */
-static int ds3000_read_signal_strength(struct dvb_frontend *fe,
-						u16 *signal_strength)
-{
-	struct ds3000_state *state = fe->demodulator_priv;
-	u16 sig_reading, sig_strength;
-	u8 rfgain, bbgain;
-
-	dprintk("%s()\n", __func__);
-
-	rfgain = ds3000_tuner_readreg(state, 0x3d) & 0x1f;
-	bbgain = ds3000_tuner_readreg(state, 0x21) & 0x1f;
-
-	if (rfgain > 15)
-		rfgain = 15;
-	if (bbgain > 13)
-		bbgain = 13;
-
-	sig_reading = rfgain * 2 + bbgain * 3;
-
-	sig_strength = 40 + (64 - sig_reading) * 50 / 64 ;
-
-	/* cook the value to be suitable for szap-s2 human readable output */
-	*signal_strength = sig_strength * 1000;
-
-	dprintk("%s: raw / cooked = 0x%04x / 0x%04x\n", __func__,
-			sig_reading, *signal_strength);
-
-	return 0;
-}
-
-/* calculate DS3000 snr value in dB */
-static int ds3000_read_snr(struct dvb_frontend *fe, u16 *snr)
-{
-	struct ds3000_state *state = fe->demodulator_priv;
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	u8 snr_reading, snr_value;
-	u32 dvbs2_signal_reading, dvbs2_noise_reading, tmp;
-	static const u16 dvbs_snr_tab[] = { /* 20 x Table (rounded up) */
-		0x0000, 0x1b13, 0x2aea, 0x3627, 0x3ede, 0x45fe, 0x4c03,
-		0x513a, 0x55d4, 0x59f2, 0x5dab, 0x6111, 0x6431, 0x6717,
-		0x69c9, 0x6c4e, 0x6eac, 0x70e8, 0x7304, 0x7505
-	};
-	static const u16 dvbs2_snr_tab[] = { /* 80 x Table (rounded up) */
-		0x0000, 0x0bc2, 0x12a3, 0x1785, 0x1b4e, 0x1e65, 0x2103,
-		0x2347, 0x2546, 0x2710, 0x28ae, 0x2a28, 0x2b83, 0x2cc5,
-		0x2df1, 0x2f09, 0x3010, 0x3109, 0x31f4, 0x32d2, 0x33a6,
-		0x3470, 0x3531, 0x35ea, 0x369b, 0x3746, 0x37ea, 0x3888,
-		0x3920, 0x39b3, 0x3a42, 0x3acc, 0x3b51, 0x3bd3, 0x3c51,
-		0x3ccb, 0x3d42, 0x3db6, 0x3e27, 0x3e95, 0x3f00, 0x3f68,
-		0x3fcf, 0x4033, 0x4094, 0x40f4, 0x4151, 0x41ac, 0x4206,
-		0x425e, 0x42b4, 0x4308, 0x435b, 0x43ac, 0x43fc, 0x444a,
-		0x4497, 0x44e2, 0x452d, 0x4576, 0x45bd, 0x4604, 0x4649,
-		0x468e, 0x46d1, 0x4713, 0x4755, 0x4795, 0x47d4, 0x4813,
-		0x4851, 0x488d, 0x48c9, 0x4904, 0x493f, 0x4978, 0x49b1,
-		0x49e9, 0x4a20, 0x4a57
-	};
-
-	dprintk("%s()\n", __func__);
-
-	switch (c->delivery_system) {
-	case SYS_DVBS:
-		snr_reading = ds3000_readreg(state, 0xff);
-		snr_reading /= 8;
-		if (snr_reading == 0)
-			*snr = 0x0000;
-		else {
-			if (snr_reading > 20)
-				snr_reading = 20;
-			snr_value = dvbs_snr_tab[snr_reading - 1] * 10 / 23026;
-			/* cook the value to be suitable for szap-s2
-			human readable output */
-			*snr = snr_value * 8 * 655;
-		}
-		dprintk("%s: raw / cooked = 0x%02x / 0x%04x\n", __func__,
-				snr_reading, *snr);
-		break;
-	case SYS_DVBS2:
-		dvbs2_noise_reading = (ds3000_readreg(state, 0x8c) & 0x3f) +
-				(ds3000_readreg(state, 0x8d) << 4);
-		dvbs2_signal_reading = ds3000_readreg(state, 0x8e);
-		tmp = dvbs2_signal_reading * dvbs2_signal_reading >> 1;
-		if (tmp == 0) {
-			*snr = 0x0000;
-			return 0;
-		}
-		if (dvbs2_noise_reading == 0) {
-			snr_value = 0x0013;
-			/* cook the value to be suitable for szap-s2
-			human readable output */
-			*snr = 0xffff;
-			return 0;
-		}
-		if (tmp > dvbs2_noise_reading) {
-			snr_reading = tmp / dvbs2_noise_reading;
-			if (snr_reading > 80)
-				snr_reading = 80;
-			snr_value = dvbs2_snr_tab[snr_reading - 1] / 1000;
-			/* cook the value to be suitable for szap-s2
-			human readable output */
-			*snr = snr_value * 5 * 655;
-		} else {
-			snr_reading = dvbs2_noise_reading / tmp;
-			if (snr_reading > 80)
-				snr_reading = 80;
-			*snr = -(dvbs2_snr_tab[snr_reading] / 1000);
-		}
-		dprintk("%s: raw / cooked = 0x%02x / 0x%04x\n", __func__,
-				snr_reading, *snr);
-		break;
-	default:
-		return 1;
-	}
-
-	return 0;
-}
-
-/* read DS3000 uncorrected blocks */
-static int ds3000_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
-{
-	struct ds3000_state *state = fe->demodulator_priv;
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	u8 data;
-	u16 _ucblocks;
-
-	dprintk("%s()\n", __func__);
-
-	switch (c->delivery_system) {
-	case SYS_DVBS:
-		*ucblocks = (ds3000_readreg(state, 0xf5) << 8) |
-				ds3000_readreg(state, 0xf4);
-		data = ds3000_readreg(state, 0xf8);
-		/* clear packet counters */
-		data &= ~0x20;
-		ds3000_writereg(state, 0xf8, data);
-		/* enable packet counters */
-		data |= 0x20;
-		ds3000_writereg(state, 0xf8, data);
-		break;
-	case SYS_DVBS2:
-		_ucblocks = (ds3000_readreg(state, 0xe2) << 8) |
-				ds3000_readreg(state, 0xe1);
-		if (_ucblocks > state->prevUCBS2)
-			*ucblocks = _ucblocks - state->prevUCBS2;
-		else
-			*ucblocks = state->prevUCBS2 - _ucblocks;
-		state->prevUCBS2 = _ucblocks;
-		break;
-	default:
-		return 1;
-	}
-
-	return 0;
-}
-
-static int ds3000_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
-{
-	struct ds3000_state *state = fe->demodulator_priv;
-	u8 data;
-
-	dprintk("%s(%d)\n", __func__, tone);
-	if ((tone != SEC_TONE_ON) && (tone != SEC_TONE_OFF)) {
-		printk(KERN_ERR "%s: Invalid, tone=%d\n", __func__, tone);
-		return -EINVAL;
-	}
-
-	data = ds3000_readreg(state, 0xa2);
-	data &= ~0xc0;
-	ds3000_writereg(state, 0xa2, data);
-
-	switch (tone) {
-	case SEC_TONE_ON:
-		dprintk("%s: setting tone on\n", __func__);
-		data = ds3000_readreg(state, 0xa1);
-		data &= ~0x43;
-		data |= 0x04;
-		ds3000_writereg(state, 0xa1, data);
-		break;
-	case SEC_TONE_OFF:
-		dprintk("%s: setting tone off\n", __func__);
-		data = ds3000_readreg(state, 0xa2);
-		data |= 0x80;
-		ds3000_writereg(state, 0xa2, data);
-		break;
-	}
-
-	return 0;
-}
-
-static int ds3000_send_diseqc_msg(struct dvb_frontend *fe,
-				struct dvb_diseqc_master_cmd *d)
-{
-	struct ds3000_state *state = fe->demodulator_priv;
-	int i;
-	u8 data;
-
-	/* Dump DiSEqC message */
-	dprintk("%s(", __func__);
-	for (i = 0 ; i < d->msg_len;) {
-		dprintk("0x%02x", d->msg[i]);
-		if (++i < d->msg_len)
-			dprintk(", ");
-	}
-
-	/* enable DiSEqC message send pin */
-	data = ds3000_readreg(state, 0xa2);
-	data &= ~0xc0;
-	ds3000_writereg(state, 0xa2, data);
-
-	/* DiSEqC message */
-	for (i = 0; i < d->msg_len; i++)
-		ds3000_writereg(state, 0xa3 + i, d->msg[i]);
-
-	data = ds3000_readreg(state, 0xa1);
-	/* clear DiSEqC message length and status,
-	enable DiSEqC message send */
-	data &= ~0xf8;
-	/* set DiSEqC mode, modulation active during 33 pulses,
-	set DiSEqC message length */
-	data |= ((d->msg_len - 1) << 3) | 0x07;
-	ds3000_writereg(state, 0xa1, data);
-
-	/* wait up to 150ms for DiSEqC transmission to complete */
-	for (i = 0; i < 15; i++) {
-		data = ds3000_readreg(state, 0xa1);
-		if ((data & 0x40) == 0)
-			break;
-		msleep(10);
-	}
-
-	/* DiSEqC timeout after 150ms */
-	if (i == 15) {
-		data = ds3000_readreg(state, 0xa1);
-		data &= ~0x80;
-		data |= 0x40;
-		ds3000_writereg(state, 0xa1, data);
-
-		data = ds3000_readreg(state, 0xa2);
-		data &= ~0xc0;
-		data |= 0x80;
-		ds3000_writereg(state, 0xa2, data);
-
-		return 1;
-	}
-
-	data = ds3000_readreg(state, 0xa2);
-	data &= ~0xc0;
-	data |= 0x80;
-	ds3000_writereg(state, 0xa2, data);
-
-	return 0;
-}
-
-/* Send DiSEqC burst */
-static int ds3000_diseqc_send_burst(struct dvb_frontend *fe,
-					fe_sec_mini_cmd_t burst)
-{
-	struct ds3000_state *state = fe->demodulator_priv;
-	int i;
-	u8 data;
-
-	dprintk("%s()\n", __func__);
-
-	data = ds3000_readreg(state, 0xa2);
-	data &= ~0xc0;
-	ds3000_writereg(state, 0xa2, data);
-
-	/* DiSEqC burst */
-	if (burst == SEC_MINI_A)
-		/* Unmodulated tone burst */
-		ds3000_writereg(state, 0xa1, 0x02);
-	else if (burst == SEC_MINI_B)
-		/* Modulated tone burst */
-		ds3000_writereg(state, 0xa1, 0x01);
-	else
-		return -EINVAL;
-
-	msleep(13);
-	for (i = 0; i < 5; i++) {
-		data = ds3000_readreg(state, 0xa1);
-		if ((data & 0x40) == 0)
-			break;
-		msleep(1);
-	}
-
-	if (i == 5) {
-		data = ds3000_readreg(state, 0xa1);
-		data &= ~0x80;
-		data |= 0x40;
-		ds3000_writereg(state, 0xa1, data);
-
-		data = ds3000_readreg(state, 0xa2);
-		data &= ~0xc0;
-		data |= 0x80;
-		ds3000_writereg(state, 0xa2, data);
-
-		return 1;
-	}
-
-	data = ds3000_readreg(state, 0xa2);
-	data &= ~0xc0;
-	data |= 0x80;
-	ds3000_writereg(state, 0xa2, data);
-
-	return 0;
-}
-
-static void ds3000_release(struct dvb_frontend *fe)
-{
-	struct ds3000_state *state = fe->demodulator_priv;
-	dprintk("%s\n", __func__);
-	kfree(state);
-}
-
-static struct dvb_frontend_ops ds3000_ops;
-
-struct dvb_frontend *ds3000_attach(const struct ds3000_config *config,
-				    struct i2c_adapter *i2c)
-{
-	struct ds3000_state *state = NULL;
-	int ret;
-
-	dprintk("%s\n", __func__);
-
-	/* allocate memory for the internal state */
-	state = kzalloc(sizeof(struct ds3000_state), GFP_KERNEL);
-	if (state == NULL) {
-		printk(KERN_ERR "Unable to kmalloc\n");
-		goto error2;
-	}
-
-	state->config = config;
-	state->i2c = i2c;
-	state->prevUCBS2 = 0;
-
-	/* check if the demod is present */
-	ret = ds3000_readreg(state, 0x00) & 0xfe;
-	if (ret != 0xe0) {
-		printk(KERN_ERR "Invalid probe, probably not a DS3000\n");
-		goto error3;
-	}
-
-	printk(KERN_INFO "DS3000 chip version: %d.%d attached.\n",
-			ds3000_readreg(state, 0x02),
-			ds3000_readreg(state, 0x01));
-
-	memcpy(&state->frontend.ops, &ds3000_ops,
-			sizeof(struct dvb_frontend_ops));
-	state->frontend.demodulator_priv = state;
-	return &state->frontend;
-
-error3:
-	kfree(state);
-error2:
-	return NULL;
-}
-EXPORT_SYMBOL(ds3000_attach);
-
-static int ds3000_set_carrier_offset(struct dvb_frontend *fe,
-					s32 carrier_offset_khz)
-{
-	struct ds3000_state *state = fe->demodulator_priv;
-	s32 tmp;
-
-	tmp = carrier_offset_khz;
-	tmp *= 65536;
-	tmp = (2 * tmp + DS3000_SAMPLE_RATE) / (2 * DS3000_SAMPLE_RATE);
-
-	if (tmp < 0)
-		tmp += 65536;
-
-	ds3000_writereg(state, 0x5f, tmp >> 8);
-	ds3000_writereg(state, 0x5e, tmp & 0xff);
-
-	return 0;
-}
-
-static int ds3000_set_frontend(struct dvb_frontend *fe)
-{
-	struct ds3000_state *state = fe->demodulator_priv;
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-
-	int i;
-	fe_status_t status;
-	u8 mlpf, mlpf_new, mlpf_max, mlpf_min, nlpf, div4;
-	s32 offset_khz;
-	u16 value, ndiv;
-	u32 f3db;
-
-	dprintk("%s() ", __func__);
-
-	if (state->config->set_ts_params)
-		state->config->set_ts_params(fe, 0);
-	/* Tune */
-	/* unknown */
-	ds3000_tuner_writereg(state, 0x07, 0x02);
-	ds3000_tuner_writereg(state, 0x10, 0x00);
-	ds3000_tuner_writereg(state, 0x60, 0x79);
-	ds3000_tuner_writereg(state, 0x08, 0x01);
-	ds3000_tuner_writereg(state, 0x00, 0x01);
-	div4 = 0;
-
-	/* calculate and set freq divider */
-	if (c->frequency < 1146000) {
-		ds3000_tuner_writereg(state, 0x10, 0x11);
-		div4 = 1;
-		ndiv = ((c->frequency * (6 + 8) * 4) +
-				(DS3000_XTAL_FREQ / 2)) /
-				DS3000_XTAL_FREQ - 1024;
-	} else {
-		ds3000_tuner_writereg(state, 0x10, 0x01);
-		ndiv = ((c->frequency * (6 + 8) * 2) +
-				(DS3000_XTAL_FREQ / 2)) /
-				DS3000_XTAL_FREQ - 1024;
-	}
-
-	ds3000_tuner_writereg(state, 0x01, (ndiv & 0x0f00) >> 8);
-	ds3000_tuner_writereg(state, 0x02, ndiv & 0x00ff);
-
-	/* set pll */
-	ds3000_tuner_writereg(state, 0x03, 0x06);
-	ds3000_tuner_writereg(state, 0x51, 0x0f);
-	ds3000_tuner_writereg(state, 0x51, 0x1f);
-	ds3000_tuner_writereg(state, 0x50, 0x10);
-	ds3000_tuner_writereg(state, 0x50, 0x00);
-	msleep(5);
-
-	/* unknown */
-	ds3000_tuner_writereg(state, 0x51, 0x17);
-	ds3000_tuner_writereg(state, 0x51, 0x1f);
-	ds3000_tuner_writereg(state, 0x50, 0x08);
-	ds3000_tuner_writereg(state, 0x50, 0x00);
-	msleep(5);
-
-	value = ds3000_tuner_readreg(state, 0x3d);
-	value &= 0x0f;
-	if ((value > 4) && (value < 15)) {
-		value -= 3;
-		if (value < 4)
-			value = 4;
-		value = ((value << 3) | 0x01) & 0x79;
-	}
-
-	ds3000_tuner_writereg(state, 0x60, value);
-	ds3000_tuner_writereg(state, 0x51, 0x17);
-	ds3000_tuner_writereg(state, 0x51, 0x1f);
-	ds3000_tuner_writereg(state, 0x50, 0x08);
-	ds3000_tuner_writereg(state, 0x50, 0x00);
-
-	/* set low-pass filter period */
-	ds3000_tuner_writereg(state, 0x04, 0x2e);
-	ds3000_tuner_writereg(state, 0x51, 0x1b);
-	ds3000_tuner_writereg(state, 0x51, 0x1f);
-	ds3000_tuner_writereg(state, 0x50, 0x04);
-	ds3000_tuner_writereg(state, 0x50, 0x00);
-	msleep(5);
-
-	f3db = ((c->symbol_rate / 1000) << 2) / 5 + 2000;
-	if ((c->symbol_rate / 1000) < 5000)
-		f3db += 3000;
-	if (f3db < 7000)
-		f3db = 7000;
-	if (f3db > 40000)
-		f3db = 40000;
-
-	/* set low-pass filter baseband */
-	value = ds3000_tuner_readreg(state, 0x26);
-	mlpf = 0x2e * 207 / ((value << 1) + 151);
-	mlpf_max = mlpf * 135 / 100;
-	mlpf_min = mlpf * 78 / 100;
-	if (mlpf_max > 63)
-		mlpf_max = 63;
-
-	/* rounded to the closest integer */
-	nlpf = ((mlpf * f3db * 1000) + (2766 * DS3000_XTAL_FREQ / 2))
-			/ (2766 * DS3000_XTAL_FREQ);
-	if (nlpf > 23)
-		nlpf = 23;
-	if (nlpf < 1)
-		nlpf = 1;
-
-	/* rounded to the closest integer */
-	mlpf_new = ((DS3000_XTAL_FREQ * nlpf * 2766) +
-			(1000 * f3db / 2)) / (1000 * f3db);
-
-	if (mlpf_new < mlpf_min) {
-		nlpf++;
-		mlpf_new = ((DS3000_XTAL_FREQ * nlpf * 2766) +
-				(1000 * f3db / 2)) / (1000 * f3db);
-	}
-
-	if (mlpf_new > mlpf_max)
-		mlpf_new = mlpf_max;
-
-	ds3000_tuner_writereg(state, 0x04, mlpf_new);
-	ds3000_tuner_writereg(state, 0x06, nlpf);
-	ds3000_tuner_writereg(state, 0x51, 0x1b);
-	ds3000_tuner_writereg(state, 0x51, 0x1f);
-	ds3000_tuner_writereg(state, 0x50, 0x04);
-	ds3000_tuner_writereg(state, 0x50, 0x00);
-	msleep(5);
-
-	/* unknown */
-	ds3000_tuner_writereg(state, 0x51, 0x1e);
-	ds3000_tuner_writereg(state, 0x51, 0x1f);
-	ds3000_tuner_writereg(state, 0x50, 0x01);
-	ds3000_tuner_writereg(state, 0x50, 0x00);
-	msleep(60);
-
-	offset_khz = (ndiv - ndiv % 2 + 1024) * DS3000_XTAL_FREQ
-		/ (6 + 8) / (div4 + 1) / 2 - c->frequency;
-
-	/* ds3000 global reset */
-	ds3000_writereg(state, 0x07, 0x80);
-	ds3000_writereg(state, 0x07, 0x00);
-	/* ds3000 build-in uC reset */
-	ds3000_writereg(state, 0xb2, 0x01);
-	/* ds3000 software reset */
-	ds3000_writereg(state, 0x00, 0x01);
-
-	switch (c->delivery_system) {
-	case SYS_DVBS:
-		/* initialise the demod in DVB-S mode */
-		for (i = 0; i < sizeof(ds3000_dvbs_init_tab); i += 2)
-			ds3000_writereg(state,
-				ds3000_dvbs_init_tab[i],
-				ds3000_dvbs_init_tab[i + 1]);
-		value = ds3000_readreg(state, 0xfe);
-		value &= 0xc0;
-		value |= 0x1b;
-		ds3000_writereg(state, 0xfe, value);
-		break;
-	case SYS_DVBS2:
-		/* initialise the demod in DVB-S2 mode */
-		for (i = 0; i < sizeof(ds3000_dvbs2_init_tab); i += 2)
-			ds3000_writereg(state,
-				ds3000_dvbs2_init_tab[i],
-				ds3000_dvbs2_init_tab[i + 1]);
-		if (c->symbol_rate >= 30000000)
-			ds3000_writereg(state, 0xfe, 0x54);
-		else
-			ds3000_writereg(state, 0xfe, 0x98);
-		break;
-	default:
-		return 1;
-	}
-
-	/* enable 27MHz clock output */
-	ds3000_writereg(state, 0x29, 0x80);
-	/* enable ac coupling */
-	ds3000_writereg(state, 0x25, 0x8a);
-
-	/* enhance symbol rate performance */
-	if ((c->symbol_rate / 1000) <= 5000) {
-		value = 29777 / (c->symbol_rate / 1000) + 1;
-		if (value % 2 != 0)
-			value++;
-		ds3000_writereg(state, 0xc3, 0x0d);
-		ds3000_writereg(state, 0xc8, value);
-		ds3000_writereg(state, 0xc4, 0x10);
-		ds3000_writereg(state, 0xc7, 0x0e);
-	} else if ((c->symbol_rate / 1000) <= 10000) {
-		value = 92166 / (c->symbol_rate / 1000) + 1;
-		if (value % 2 != 0)
-			value++;
-		ds3000_writereg(state, 0xc3, 0x07);
-		ds3000_writereg(state, 0xc8, value);
-		ds3000_writereg(state, 0xc4, 0x09);
-		ds3000_writereg(state, 0xc7, 0x12);
-	} else if ((c->symbol_rate / 1000) <= 20000) {
-		value = 64516 / (c->symbol_rate / 1000) + 1;
-		ds3000_writereg(state, 0xc3, value);
-		ds3000_writereg(state, 0xc8, 0x0e);
-		ds3000_writereg(state, 0xc4, 0x07);
-		ds3000_writereg(state, 0xc7, 0x18);
-	} else {
-		value = 129032 / (c->symbol_rate / 1000) + 1;
-		ds3000_writereg(state, 0xc3, value);
-		ds3000_writereg(state, 0xc8, 0x0a);
-		ds3000_writereg(state, 0xc4, 0x05);
-		ds3000_writereg(state, 0xc7, 0x24);
-	}
-
-	/* normalized symbol rate rounded to the closest integer */
-	value = (((c->symbol_rate / 1000) << 16) +
-			(DS3000_SAMPLE_RATE / 2)) / DS3000_SAMPLE_RATE;
-	ds3000_writereg(state, 0x61, value & 0x00ff);
-	ds3000_writereg(state, 0x62, (value & 0xff00) >> 8);
-
-	/* co-channel interference cancellation disabled */
-	ds3000_writereg(state, 0x56, 0x00);
-
-	/* equalizer disabled */
-	ds3000_writereg(state, 0x76, 0x00);
-
-	/*ds3000_writereg(state, 0x08, 0x03);
-	ds3000_writereg(state, 0xfd, 0x22);
-	ds3000_writereg(state, 0x08, 0x07);
-	ds3000_writereg(state, 0xfd, 0x42);
-	ds3000_writereg(state, 0x08, 0x07);*/
-
-	if (state->config->ci_mode) {
-		switch (c->delivery_system) {
-		case SYS_DVBS:
-		default:
-			ds3000_writereg(state, 0xfd, 0x80);
-		break;
-		case SYS_DVBS2:
-			ds3000_writereg(state, 0xfd, 0x01);
-			break;
-		}
-	}
-
-	/* ds3000 out of software reset */
-	ds3000_writereg(state, 0x00, 0x00);
-	/* start ds3000 build-in uC */
-	ds3000_writereg(state, 0xb2, 0x00);
-
-	ds3000_set_carrier_offset(fe, offset_khz);
-
-	for (i = 0; i < 30 ; i++) {
-		ds3000_read_status(fe, &status);
-		if (status & FE_HAS_LOCK)
-			break;
-
-		msleep(10);
-	}
-
-	return 0;
-}
-
-static int ds3000_tune(struct dvb_frontend *fe,
-			bool re_tune,
-			unsigned int mode_flags,
-			unsigned int *delay,
-			fe_status_t *status)
-{
-	if (re_tune) {
-		int ret = ds3000_set_frontend(fe);
-		if (ret)
-			return ret;
-	}
-
-	*delay = HZ / 5;
-
-	return ds3000_read_status(fe, status);
-}
-
-static enum dvbfe_algo ds3000_get_algo(struct dvb_frontend *fe)
-{
-	dprintk("%s()\n", __func__);
-	return DVBFE_ALGO_HW;
-}
-
-/*
- * Initialise or wake up device
- *
- * Power config will reset and load initial firmware if required
- */
-static int ds3000_initfe(struct dvb_frontend *fe)
-{
-	struct ds3000_state *state = fe->demodulator_priv;
-	int ret;
-
-	dprintk("%s()\n", __func__);
-	/* hard reset */
-	ds3000_writereg(state, 0x08, 0x01 | ds3000_readreg(state, 0x08));
-	msleep(1);
-
-	/* TS2020 init */
-	ds3000_tuner_writereg(state, 0x42, 0x73);
-	ds3000_tuner_writereg(state, 0x05, 0x01);
-	ds3000_tuner_writereg(state, 0x62, 0xf5);
-	/* Load the firmware if required */
-	ret = ds3000_firmware_ondemand(fe);
-	if (ret != 0) {
-		printk(KERN_ERR "%s: Unable initialize firmware\n", __func__);
-		return ret;
-	}
-
-	return 0;
-}
-
-/* Put device to sleep */
-static int ds3000_sleep(struct dvb_frontend *fe)
-{
-	dprintk("%s()\n", __func__);
-	return 0;
-}
-
-static struct dvb_frontend_ops ds3000_ops = {
-	.delsys = { SYS_DVBS, SYS_DVBS2},
-	.info = {
-		.name = "Montage Technology DS3000/TS2020",
-		.frequency_min = 950000,
-		.frequency_max = 2150000,
-		.frequency_stepsize = 1011, /* kHz for QPSK frontends */
-		.frequency_tolerance = 5000,
-		.symbol_rate_min = 1000000,
-		.symbol_rate_max = 45000000,
-		.caps = FE_CAN_INVERSION_AUTO |
-			FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
-			FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
-			FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
-			FE_CAN_2G_MODULATION |
-			FE_CAN_QPSK | FE_CAN_RECOVER
-	},
-
-	.release = ds3000_release,
-
-	.init = ds3000_initfe,
-	.sleep = ds3000_sleep,
-	.read_status = ds3000_read_status,
-	.read_ber = ds3000_read_ber,
-	.read_signal_strength = ds3000_read_signal_strength,
-	.read_snr = ds3000_read_snr,
-	.read_ucblocks = ds3000_read_ucblocks,
-	.set_voltage = ds3000_set_voltage,
-	.set_tone = ds3000_set_tone,
-	.diseqc_send_master_cmd = ds3000_send_diseqc_msg,
-	.diseqc_send_burst = ds3000_diseqc_send_burst,
-	.get_frontend_algo = ds3000_get_algo,
-
-	.set_frontend = ds3000_set_frontend,
-	.tune = ds3000_tune,
-};
-
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)");
-
-MODULE_DESCRIPTION("DVB Frontend module for Montage Technology "
-			"DS3000/TS2020 hardware");
-MODULE_AUTHOR("Konstantin Dimitrov");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/ds3000.h b/drivers/media/dvb/frontends/ds3000.h
deleted file mode 100644
index 1b73688..0000000
--- a/drivers/media/dvb/frontends/ds3000.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
-    Montage Technology DS3000/TS2020 - DVBS/S2 Satellite demod/tuner driver
-    Copyright (C) 2009 Konstantin Dimitrov <kosio.dimitrov@gmail.com>
-
-    Copyright (C) 2009 TurboSight.com
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#ifndef DS3000_H
-#define DS3000_H
-
-#include <linux/dvb/frontend.h>
-
-struct ds3000_config {
-	/* the demodulator's i2c address */
-	u8 demod_address;
-	u8 ci_mode;
-	/* Set device param to start dma */
-	int (*set_ts_params)(struct dvb_frontend *fe, int is_punctured);
-};
-
-#if defined(CONFIG_DVB_DS3000) || \
-			(defined(CONFIG_DVB_DS3000_MODULE) && defined(MODULE))
-extern struct dvb_frontend *ds3000_attach(const struct ds3000_config *config,
-					struct i2c_adapter *i2c);
-#else
-static inline
-struct dvb_frontend *ds3000_attach(const struct ds3000_config *config,
-					struct i2c_adapter *i2c)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif /* CONFIG_DVB_DS3000 */
-#endif /* DS3000_H */
diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c
deleted file mode 100644
index 1ab3483..0000000
--- a/drivers/media/dvb/frontends/dvb-pll.c
+++ /dev/null
@@ -1,794 +0,0 @@
-/*
- * descriptions + helper functions for simple dvb plls.
- *
- * (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the 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/slab.h>
-#include <linux/module.h>
-#include <linux/dvb/frontend.h>
-#include <asm/types.h>
-
-#include "dvb-pll.h"
-
-struct dvb_pll_priv {
-	/* pll number */
-	int nr;
-
-	/* i2c details */
-	int pll_i2c_address;
-	struct i2c_adapter *i2c;
-
-	/* the PLL descriptor */
-	struct dvb_pll_desc *pll_desc;
-
-	/* cached frequency/bandwidth */
-	u32 frequency;
-	u32 bandwidth;
-};
-
-#define DVB_PLL_MAX 64
-
-static unsigned int dvb_pll_devcount;
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "enable verbose debug messages");
-
-static unsigned int id[DVB_PLL_MAX] =
-	{ [ 0 ... (DVB_PLL_MAX-1) ] = DVB_PLL_UNDEFINED };
-module_param_array(id, int, NULL, 0644);
-MODULE_PARM_DESC(id, "force pll id to use (DEBUG ONLY)");
-
-/* ----------------------------------------------------------- */
-
-struct dvb_pll_desc {
-	char *name;
-	u32  min;
-	u32  max;
-	u32  iffreq;
-	void (*set)(struct dvb_frontend *fe, u8 *buf);
-	u8   *initdata;
-	u8   *initdata2;
-	u8   *sleepdata;
-	int  count;
-	struct {
-		u32 limit;
-		u32 stepsize;
-		u8  config;
-		u8  cb;
-	} entries[12];
-};
-
-/* ----------------------------------------------------------- */
-/* descriptions                                                */
-
-static struct dvb_pll_desc dvb_pll_thomson_dtt7579 = {
-	.name  = "Thomson dtt7579",
-	.min   = 177000000,
-	.max   = 858000000,
-	.iffreq= 36166667,
-	.sleepdata = (u8[]){ 2, 0xb4, 0x03 },
-	.count = 4,
-	.entries = {
-		{  443250000, 166667, 0xb4, 0x02 },
-		{  542000000, 166667, 0xb4, 0x08 },
-		{  771000000, 166667, 0xbc, 0x08 },
-		{  999999999, 166667, 0xf4, 0x08 },
-	},
-};
-
-static void thomson_dtt759x_bw(struct dvb_frontend *fe, u8 *buf)
-{
-	u32 bw = fe->dtv_property_cache.bandwidth_hz;
-	if (bw == 7000000)
-		buf[3] |= 0x10;
-}
-
-static struct dvb_pll_desc dvb_pll_thomson_dtt759x = {
-	.name  = "Thomson dtt759x",
-	.min   = 177000000,
-	.max   = 896000000,
-	.set   = thomson_dtt759x_bw,
-	.iffreq= 36166667,
-	.sleepdata = (u8[]){ 2, 0x84, 0x03 },
-	.count = 5,
-	.entries = {
-		{  264000000, 166667, 0xb4, 0x02 },
-		{  470000000, 166667, 0xbc, 0x02 },
-		{  735000000, 166667, 0xbc, 0x08 },
-		{  835000000, 166667, 0xf4, 0x08 },
-		{  999999999, 166667, 0xfc, 0x08 },
-	},
-};
-
-static struct dvb_pll_desc dvb_pll_lg_z201 = {
-	.name  = "LG z201",
-	.min   = 174000000,
-	.max   = 862000000,
-	.iffreq= 36166667,
-	.sleepdata = (u8[]){ 2, 0xbc, 0x03 },
-	.count = 5,
-	.entries = {
-		{  157500000, 166667, 0xbc, 0x01 },
-		{  443250000, 166667, 0xbc, 0x02 },
-		{  542000000, 166667, 0xbc, 0x04 },
-		{  830000000, 166667, 0xf4, 0x04 },
-		{  999999999, 166667, 0xfc, 0x04 },
-	},
-};
-
-static struct dvb_pll_desc dvb_pll_unknown_1 = {
-	.name  = "unknown 1", /* used by dntv live dvb-t */
-	.min   = 174000000,
-	.max   = 862000000,
-	.iffreq= 36166667,
-	.count = 9,
-	.entries = {
-		{  150000000, 166667, 0xb4, 0x01 },
-		{  173000000, 166667, 0xbc, 0x01 },
-		{  250000000, 166667, 0xb4, 0x02 },
-		{  400000000, 166667, 0xbc, 0x02 },
-		{  420000000, 166667, 0xf4, 0x02 },
-		{  470000000, 166667, 0xfc, 0x02 },
-		{  600000000, 166667, 0xbc, 0x08 },
-		{  730000000, 166667, 0xf4, 0x08 },
-		{  999999999, 166667, 0xfc, 0x08 },
-	},
-};
-
-/* Infineon TUA6010XS
- * used in Thomson Cable Tuner
- */
-static struct dvb_pll_desc dvb_pll_tua6010xs = {
-	.name  = "Infineon TUA6010XS",
-	.min   =  44250000,
-	.max   = 858000000,
-	.iffreq= 36125000,
-	.count = 3,
-	.entries = {
-		{  115750000, 62500, 0x8e, 0x03 },
-		{  403250000, 62500, 0x8e, 0x06 },
-		{  999999999, 62500, 0x8e, 0x85 },
-	},
-};
-
-/* Panasonic env57h1xd5 (some Philips PLL ?) */
-static struct dvb_pll_desc dvb_pll_env57h1xd5 = {
-	.name  = "Panasonic ENV57H1XD5",
-	.min   =  44250000,
-	.max   = 858000000,
-	.iffreq= 36125000,
-	.count = 4,
-	.entries = {
-		{  153000000, 166667, 0xc2, 0x41 },
-		{  470000000, 166667, 0xc2, 0x42 },
-		{  526000000, 166667, 0xc2, 0x84 },
-		{  999999999, 166667, 0xc2, 0xa4 },
-	},
-};
-
-/* Philips TDA6650/TDA6651
- * used in Panasonic ENV77H11D5
- */
-static void tda665x_bw(struct dvb_frontend *fe, u8 *buf)
-{
-	u32 bw = fe->dtv_property_cache.bandwidth_hz;
-	if (bw == 8000000)
-		buf[3] |= 0x08;
-}
-
-static struct dvb_pll_desc dvb_pll_tda665x = {
-	.name  = "Philips TDA6650/TDA6651",
-	.min   =  44250000,
-	.max   = 858000000,
-	.set   = tda665x_bw,
-	.iffreq= 36166667,
-	.initdata = (u8[]){ 4, 0x0b, 0xf5, 0x85, 0xab },
-	.count = 12,
-	.entries = {
-		{   93834000, 166667, 0xca, 0x61 /* 011 0 0 0  01 */ },
-		{  123834000, 166667, 0xca, 0xa1 /* 101 0 0 0  01 */ },
-		{  161000000, 166667, 0xca, 0xa1 /* 101 0 0 0  01 */ },
-		{  163834000, 166667, 0xca, 0xc2 /* 110 0 0 0  10 */ },
-		{  253834000, 166667, 0xca, 0x62 /* 011 0 0 0  10 */ },
-		{  383834000, 166667, 0xca, 0xa2 /* 101 0 0 0  10 */ },
-		{  443834000, 166667, 0xca, 0xc2 /* 110 0 0 0  10 */ },
-		{  444000000, 166667, 0xca, 0xc4 /* 110 0 0 1  00 */ },
-		{  583834000, 166667, 0xca, 0x64 /* 011 0 0 1  00 */ },
-		{  793834000, 166667, 0xca, 0xa4 /* 101 0 0 1  00 */ },
-		{  444834000, 166667, 0xca, 0xc4 /* 110 0 0 1  00 */ },
-		{  861000000, 166667, 0xca, 0xe4 /* 111 0 0 1  00 */ },
-	}
-};
-
-/* Infineon TUA6034
- * used in LG TDTP E102P
- */
-static void tua6034_bw(struct dvb_frontend *fe, u8 *buf)
-{
-	u32 bw = fe->dtv_property_cache.bandwidth_hz;
-	if (bw == 7000000)
-		buf[3] |= 0x08;
-}
-
-static struct dvb_pll_desc dvb_pll_tua6034 = {
-	.name  = "Infineon TUA6034",
-	.min   =  44250000,
-	.max   = 858000000,
-	.iffreq= 36166667,
-	.count = 3,
-	.set   = tua6034_bw,
-	.entries = {
-		{  174500000, 62500, 0xce, 0x01 },
-		{  230000000, 62500, 0xce, 0x02 },
-		{  999999999, 62500, 0xce, 0x04 },
-	},
-};
-
-/* ALPS TDED4
- * used in Nebula-Cards and USB boxes
- */
-static void tded4_bw(struct dvb_frontend *fe, u8 *buf)
-{
-	u32 bw = fe->dtv_property_cache.bandwidth_hz;
-	if (bw == 8000000)
-		buf[3] |= 0x04;
-}
-
-static struct dvb_pll_desc dvb_pll_tded4 = {
-	.name = "ALPS TDED4",
-	.min = 47000000,
-	.max = 863000000,
-	.iffreq= 36166667,
-	.set   = tded4_bw,
-	.count = 4,
-	.entries = {
-		{ 153000000, 166667, 0x85, 0x01 },
-		{ 470000000, 166667, 0x85, 0x02 },
-		{ 823000000, 166667, 0x85, 0x08 },
-		{ 999999999, 166667, 0x85, 0x88 },
-	}
-};
-
-/* ALPS TDHU2
- * used in AverTVHD MCE A180
- */
-static struct dvb_pll_desc dvb_pll_tdhu2 = {
-	.name = "ALPS TDHU2",
-	.min = 54000000,
-	.max = 864000000,
-	.iffreq= 44000000,
-	.count = 4,
-	.entries = {
-		{ 162000000, 62500, 0x85, 0x01 },
-		{ 426000000, 62500, 0x85, 0x02 },
-		{ 782000000, 62500, 0x85, 0x08 },
-		{ 999999999, 62500, 0x85, 0x88 },
-	}
-};
-
-/* Samsung TBMV30111IN / TBMV30712IN1
- * used in Air2PC ATSC - 2nd generation (nxt2002)
- */
-static struct dvb_pll_desc dvb_pll_samsung_tbmv = {
-	.name = "Samsung TBMV30111IN / TBMV30712IN1",
-	.min = 54000000,
-	.max = 860000000,
-	.iffreq= 44000000,
-	.count = 6,
-	.entries = {
-		{ 172000000, 166667, 0xb4, 0x01 },
-		{ 214000000, 166667, 0xb4, 0x02 },
-		{ 467000000, 166667, 0xbc, 0x02 },
-		{ 721000000, 166667, 0xbc, 0x08 },
-		{ 841000000, 166667, 0xf4, 0x08 },
-		{ 999999999, 166667, 0xfc, 0x02 },
-	}
-};
-
-/*
- * Philips SD1878 Tuner.
- */
-static struct dvb_pll_desc dvb_pll_philips_sd1878_tda8261 = {
-	.name  = "Philips SD1878",
-	.min   =  950000,
-	.max   = 2150000,
-	.iffreq= 249, /* zero-IF, offset 249 is to round up */
-	.count = 4,
-	.entries = {
-		{ 1250000, 500, 0xc4, 0x00},
-		{ 1450000, 500, 0xc4, 0x40},
-		{ 2050000, 500, 0xc4, 0x80},
-		{ 2150000, 500, 0xc4, 0xc0},
-	},
-};
-
-static void opera1_bw(struct dvb_frontend *fe, u8 *buf)
-{
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	struct dvb_pll_priv *priv = fe->tuner_priv;
-	u32 b_w  = (c->symbol_rate * 27) / 32000;
-	struct i2c_msg msg = {
-		.addr = priv->pll_i2c_address,
-		.flags = 0,
-		.buf = buf,
-		.len = 4
-	};
-	int result;
-	u8 lpf;
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-
-	result = i2c_transfer(priv->i2c, &msg, 1);
-	if (result != 1)
-		printk(KERN_ERR "%s: i2c_transfer failed:%d",
-			__func__, result);
-
-	if (b_w <= 10000)
-		lpf = 0xc;
-	else if (b_w <= 12000)
-		lpf = 0x2;
-	else if (b_w <= 14000)
-		lpf = 0xa;
-	else if (b_w <= 16000)
-		lpf = 0x6;
-	else if (b_w <= 18000)
-		lpf = 0xe;
-	else if (b_w <= 20000)
-		lpf = 0x1;
-	else if (b_w <= 22000)
-		lpf = 0x9;
-	else if (b_w <= 24000)
-		lpf = 0x5;
-	else if (b_w <= 26000)
-		lpf = 0xd;
-	else if (b_w <= 28000)
-		lpf = 0x3;
-		else
-		lpf = 0xb;
-	buf[2] ^= 0x1c; /* Flip bits 3-5 */
-	/* Set lpf */
-	buf[2] |= ((lpf >> 2) & 0x3) << 3;
-	buf[3] |= (lpf & 0x3) << 2;
-
-	return;
-}
-
-static struct dvb_pll_desc dvb_pll_opera1 = {
-	.name  = "Opera Tuner",
-	.min   =  900000,
-	.max   = 2250000,
-	.initdata = (u8[]){ 4, 0x08, 0xe5, 0xe1, 0x00 },
-	.initdata2 = (u8[]){ 4, 0x08, 0xe5, 0xe5, 0x00 },
-	.iffreq= 0,
-	.set   = opera1_bw,
-	.count = 8,
-	.entries = {
-		{ 1064000, 500, 0xf9, 0xc2 },
-		{ 1169000, 500, 0xf9, 0xe2 },
-		{ 1299000, 500, 0xf9, 0x20 },
-		{ 1444000, 500, 0xf9, 0x40 },
-		{ 1606000, 500, 0xf9, 0x60 },
-		{ 1777000, 500, 0xf9, 0x80 },
-		{ 1941000, 500, 0xf9, 0xa0 },
-		{ 2250000, 500, 0xf9, 0xc0 },
-	}
-};
-
-static void samsung_dtos403ih102a_set(struct dvb_frontend *fe, u8 *buf)
-{
-	struct dvb_pll_priv *priv = fe->tuner_priv;
-	struct i2c_msg msg = {
-		.addr = priv->pll_i2c_address,
-		.flags = 0,
-		.buf = buf,
-		.len = 4
-	};
-	int result;
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-
-	result = i2c_transfer(priv->i2c, &msg, 1);
-	if (result != 1)
-		printk(KERN_ERR "%s: i2c_transfer failed:%d",
-			__func__, result);
-
-	buf[2] = 0x9e;
-	buf[3] = 0x90;
-
-	return;
-}
-
-/* unknown pll used in Samsung DTOS403IH102A DVB-C tuner */
-static struct dvb_pll_desc dvb_pll_samsung_dtos403ih102a = {
-	.name   = "Samsung DTOS403IH102A",
-	.min    =  44250000,
-	.max    = 858000000,
-	.iffreq =  36125000,
-	.count  = 8,
-	.set    = samsung_dtos403ih102a_set,
-	.entries = {
-		{ 135000000, 62500, 0xbe, 0x01 },
-		{ 177000000, 62500, 0xf6, 0x01 },
-		{ 370000000, 62500, 0xbe, 0x02 },
-		{ 450000000, 62500, 0xf6, 0x02 },
-		{ 466000000, 62500, 0xfe, 0x02 },
-		{ 538000000, 62500, 0xbe, 0x08 },
-		{ 826000000, 62500, 0xf6, 0x08 },
-		{ 999999999, 62500, 0xfe, 0x08 },
-	}
-};
-
-/* Samsung TDTC9251DH0 DVB-T NIM, as used on AirStar 2 */
-static struct dvb_pll_desc dvb_pll_samsung_tdtc9251dh0 = {
-	.name	= "Samsung TDTC9251DH0",
-	.min	=  48000000,
-	.max	= 863000000,
-	.iffreq	=  36166667,
-	.count	= 3,
-	.entries = {
-		{ 157500000, 166667, 0xcc, 0x09 },
-		{ 443000000, 166667, 0xcc, 0x0a },
-		{ 863000000, 166667, 0xcc, 0x08 },
-	}
-};
-
-/* Samsung TBDU18132 DVB-S NIM with TSA5059 PLL, used in SkyStar2 DVB-S 2.3 */
-static struct dvb_pll_desc dvb_pll_samsung_tbdu18132 = {
-	.name = "Samsung TBDU18132",
-	.min	=  950000,
-	.max	= 2150000, /* guesses */
-	.iffreq = 0,
-	.count = 2,
-	.entries = {
-		{ 1550000, 125, 0x84, 0x82 },
-		{ 4095937, 125, 0x84, 0x80 },
-	}
-	/* TSA5059 PLL has a 17 bit divisor rather than the 15 bits supported
-	 * by this driver.  The two extra bits are 0x60 in the third byte.  15
-	 * bits is enough for over 4 GHz, which is enough to cover the range
-	 * of this tuner.  We could use the additional divisor bits by adding
-	 * more entries, e.g.
-	 { 0x0ffff * 125 + 125/2, 125, 0x84 | 0x20, },
-	 { 0x17fff * 125 + 125/2, 125, 0x84 | 0x40, },
-	 { 0x1ffff * 125 + 125/2, 125, 0x84 | 0x60, }, */
-};
-
-/* Samsung TBMU24112 DVB-S NIM with SL1935 zero-IF tuner */
-static struct dvb_pll_desc dvb_pll_samsung_tbmu24112 = {
-	.name = "Samsung TBMU24112",
-	.min	=  950000,
-	.max	= 2150000, /* guesses */
-	.iffreq = 0,
-	.count = 2,
-	.entries = {
-		{ 1500000, 125, 0x84, 0x18 },
-		{ 9999999, 125, 0x84, 0x08 },
-	}
-};
-
-/* Alps TDEE4 DVB-C NIM, used on Cablestar 2 */
-/* byte 4 : 1  *   *   AGD R3  R2  R1  R0
- * byte 5 : C1 *   RE  RTS BS4 BS3 BS2 BS1
- * AGD = 1, R3 R2 R1 R0 = 0 1 0 1 => byte 4 = 1**10101 = 0x95
- * Range(MHz)  C1 *  RE RTS BS4 BS3 BS2 BS1  Byte 5
- *  47 - 153   0  *  0   0   0   0   0   1   0x01
- * 153 - 430   0  *  0   0   0   0   1   0   0x02
- * 430 - 822   0  *  0   0   1   0   0   0   0x08
- * 822 - 862   1  *  0   0   1   0   0   0   0x88 */
-static struct dvb_pll_desc dvb_pll_alps_tdee4 = {
-	.name = "ALPS TDEE4",
-	.min	=  47000000,
-	.max	= 862000000,
-	.iffreq	=  36125000,
-	.count = 4,
-	.entries = {
-		{ 153000000, 62500, 0x95, 0x01 },
-		{ 430000000, 62500, 0x95, 0x02 },
-		{ 822000000, 62500, 0x95, 0x08 },
-		{ 999999999, 62500, 0x95, 0x88 },
-	}
-};
-
-/* ----------------------------------------------------------- */
-
-static struct dvb_pll_desc *pll_list[] = {
-	[DVB_PLL_UNDEFINED]              = NULL,
-	[DVB_PLL_THOMSON_DTT7579]        = &dvb_pll_thomson_dtt7579,
-	[DVB_PLL_THOMSON_DTT759X]        = &dvb_pll_thomson_dtt759x,
-	[DVB_PLL_LG_Z201]                = &dvb_pll_lg_z201,
-	[DVB_PLL_UNKNOWN_1]              = &dvb_pll_unknown_1,
-	[DVB_PLL_TUA6010XS]              = &dvb_pll_tua6010xs,
-	[DVB_PLL_ENV57H1XD5]             = &dvb_pll_env57h1xd5,
-	[DVB_PLL_TUA6034]                = &dvb_pll_tua6034,
-	[DVB_PLL_TDA665X]                = &dvb_pll_tda665x,
-	[DVB_PLL_TDED4]                  = &dvb_pll_tded4,
-	[DVB_PLL_TDEE4]                  = &dvb_pll_alps_tdee4,
-	[DVB_PLL_TDHU2]                  = &dvb_pll_tdhu2,
-	[DVB_PLL_SAMSUNG_TBMV]           = &dvb_pll_samsung_tbmv,
-	[DVB_PLL_PHILIPS_SD1878_TDA8261] = &dvb_pll_philips_sd1878_tda8261,
-	[DVB_PLL_OPERA1]                 = &dvb_pll_opera1,
-	[DVB_PLL_SAMSUNG_DTOS403IH102A]  = &dvb_pll_samsung_dtos403ih102a,
-	[DVB_PLL_SAMSUNG_TDTC9251DH0]    = &dvb_pll_samsung_tdtc9251dh0,
-	[DVB_PLL_SAMSUNG_TBDU18132]	 = &dvb_pll_samsung_tbdu18132,
-	[DVB_PLL_SAMSUNG_TBMU24112]      = &dvb_pll_samsung_tbmu24112,
-};
-
-/* ----------------------------------------------------------- */
-/* code                                                        */
-
-static int dvb_pll_configure(struct dvb_frontend *fe, u8 *buf,
-			     const u32 frequency)
-{
-	struct dvb_pll_priv *priv = fe->tuner_priv;
-	struct dvb_pll_desc *desc = priv->pll_desc;
-	u32 div;
-	int i;
-
-	if (frequency && (frequency < desc->min || frequency > desc->max))
-		return -EINVAL;
-
-	for (i = 0; i < desc->count; i++) {
-		if (frequency > desc->entries[i].limit)
-			continue;
-		break;
-	}
-
-	if (debug)
-		printk("pll: %s: freq=%d | i=%d/%d\n", desc->name,
-		       frequency, i, desc->count);
-	if (i == desc->count)
-		return -EINVAL;
-
-	div = (frequency + desc->iffreq +
-	       desc->entries[i].stepsize/2) / desc->entries[i].stepsize;
-	buf[0] = div >> 8;
-	buf[1] = div & 0xff;
-	buf[2] = desc->entries[i].config;
-	buf[3] = desc->entries[i].cb;
-
-	if (desc->set)
-		desc->set(fe, buf);
-
-	if (debug)
-		printk("pll: %s: div=%d | buf=0x%02x,0x%02x,0x%02x,0x%02x\n",
-		       desc->name, div, buf[0], buf[1], buf[2], buf[3]);
-
-	// calculate the frequency we set it to
-	return (div * desc->entries[i].stepsize) - desc->iffreq;
-}
-
-static int dvb_pll_release(struct dvb_frontend *fe)
-{
-	kfree(fe->tuner_priv);
-	fe->tuner_priv = NULL;
-	return 0;
-}
-
-static int dvb_pll_sleep(struct dvb_frontend *fe)
-{
-	struct dvb_pll_priv *priv = fe->tuner_priv;
-
-	if (priv->i2c == NULL)
-		return -EINVAL;
-
-	if (priv->pll_desc->sleepdata) {
-		struct i2c_msg msg = { .flags = 0,
-			.addr = priv->pll_i2c_address,
-			.buf = priv->pll_desc->sleepdata + 1,
-			.len = priv->pll_desc->sleepdata[0] };
-
-		int result;
-
-		if (fe->ops.i2c_gate_ctrl)
-			fe->ops.i2c_gate_ctrl(fe, 1);
-		if ((result = i2c_transfer(priv->i2c, &msg, 1)) != 1) {
-			return result;
-		}
-		return 0;
-	}
-	/* Shouldn't be called when initdata is NULL, maybe BUG()? */
-	return -EINVAL;
-}
-
-static int dvb_pll_set_params(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	struct dvb_pll_priv *priv = fe->tuner_priv;
-	u8 buf[4];
-	struct i2c_msg msg =
-		{ .addr = priv->pll_i2c_address, .flags = 0,
-		  .buf = buf, .len = sizeof(buf) };
-	int result;
-	u32 frequency = 0;
-
-	if (priv->i2c == NULL)
-		return -EINVAL;
-
-	result = dvb_pll_configure(fe, buf, c->frequency);
-	if (result < 0)
-		return result;
-	else
-		frequency = result;
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	if ((result = i2c_transfer(priv->i2c, &msg, 1)) != 1) {
-		return result;
-	}
-
-	priv->frequency = frequency;
-	priv->bandwidth = c->bandwidth_hz;
-
-	return 0;
-}
-
-static int dvb_pll_calc_regs(struct dvb_frontend *fe,
-			     u8 *buf, int buf_len)
-{
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	struct dvb_pll_priv *priv = fe->tuner_priv;
-	int result;
-	u32 frequency = 0;
-
-	if (buf_len < 5)
-		return -EINVAL;
-
-	result = dvb_pll_configure(fe, buf + 1, c->frequency);
-	if (result < 0)
-		return result;
-	else
-		frequency = result;
-
-	buf[0] = priv->pll_i2c_address;
-
-	priv->frequency = frequency;
-	priv->bandwidth = c->bandwidth_hz;
-
-	return 5;
-}
-
-static int dvb_pll_get_frequency(struct dvb_frontend *fe, u32 *frequency)
-{
-	struct dvb_pll_priv *priv = fe->tuner_priv;
-	*frequency = priv->frequency;
-	return 0;
-}
-
-static int dvb_pll_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
-{
-	struct dvb_pll_priv *priv = fe->tuner_priv;
-	*bandwidth = priv->bandwidth;
-	return 0;
-}
-
-static int dvb_pll_init(struct dvb_frontend *fe)
-{
-	struct dvb_pll_priv *priv = fe->tuner_priv;
-
-	if (priv->i2c == NULL)
-		return -EINVAL;
-
-	if (priv->pll_desc->initdata) {
-		struct i2c_msg msg = { .flags = 0,
-			.addr = priv->pll_i2c_address,
-			.buf = priv->pll_desc->initdata + 1,
-			.len = priv->pll_desc->initdata[0] };
-
-		int result;
-		if (fe->ops.i2c_gate_ctrl)
-			fe->ops.i2c_gate_ctrl(fe, 1);
-		result = i2c_transfer(priv->i2c, &msg, 1);
-		if (result != 1)
-			return result;
-		if (priv->pll_desc->initdata2) {
-			msg.buf = priv->pll_desc->initdata2 + 1;
-			msg.len = priv->pll_desc->initdata2[0];
-			if (fe->ops.i2c_gate_ctrl)
-				fe->ops.i2c_gate_ctrl(fe, 1);
-			result = i2c_transfer(priv->i2c, &msg, 1);
-			if (result != 1)
-				return result;
-		}
-		return 0;
-	}
-	/* Shouldn't be called when initdata is NULL, maybe BUG()? */
-	return -EINVAL;
-}
-
-static struct dvb_tuner_ops dvb_pll_tuner_ops = {
-	.release = dvb_pll_release,
-	.sleep = dvb_pll_sleep,
-	.init = dvb_pll_init,
-	.set_params = dvb_pll_set_params,
-	.calc_regs = dvb_pll_calc_regs,
-	.get_frequency = dvb_pll_get_frequency,
-	.get_bandwidth = dvb_pll_get_bandwidth,
-};
-
-struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr,
-				    struct i2c_adapter *i2c,
-				    unsigned int pll_desc_id)
-{
-	u8 b1 [] = { 0 };
-	struct i2c_msg msg = { .addr = pll_addr, .flags = I2C_M_RD,
-			       .buf = b1, .len = 1 };
-	struct dvb_pll_priv *priv = NULL;
-	int ret;
-	struct dvb_pll_desc *desc;
-
-	if ((id[dvb_pll_devcount] > DVB_PLL_UNDEFINED) &&
-	    (id[dvb_pll_devcount] < ARRAY_SIZE(pll_list)))
-		pll_desc_id = id[dvb_pll_devcount];
-
-	BUG_ON(pll_desc_id < 1 || pll_desc_id >= ARRAY_SIZE(pll_list));
-
-	desc = pll_list[pll_desc_id];
-
-	if (i2c != NULL) {
-		if (fe->ops.i2c_gate_ctrl)
-			fe->ops.i2c_gate_ctrl(fe, 1);
-
-		ret = i2c_transfer (i2c, &msg, 1);
-		if (ret != 1)
-			return NULL;
-		if (fe->ops.i2c_gate_ctrl)
-			     fe->ops.i2c_gate_ctrl(fe, 0);
-	}
-
-	priv = kzalloc(sizeof(struct dvb_pll_priv), GFP_KERNEL);
-	if (priv == NULL)
-		return NULL;
-
-	priv->pll_i2c_address = pll_addr;
-	priv->i2c = i2c;
-	priv->pll_desc = desc;
-	priv->nr = dvb_pll_devcount++;
-
-	memcpy(&fe->ops.tuner_ops, &dvb_pll_tuner_ops,
-	       sizeof(struct dvb_tuner_ops));
-
-	strncpy(fe->ops.tuner_ops.info.name, desc->name,
-		sizeof(fe->ops.tuner_ops.info.name));
-	fe->ops.tuner_ops.info.frequency_min = desc->min;
-	fe->ops.tuner_ops.info.frequency_max = desc->max;
-	if (!desc->initdata)
-		fe->ops.tuner_ops.init = NULL;
-	if (!desc->sleepdata)
-		fe->ops.tuner_ops.sleep = NULL;
-
-	fe->tuner_priv = priv;
-
-	if ((debug) || (id[priv->nr] == pll_desc_id)) {
-		printk("dvb-pll[%d]", priv->nr);
-		if (i2c != NULL)
-			printk(" %d-%04x", i2c_adapter_id(i2c), pll_addr);
-		printk(": id# %d (%s) attached, %s\n", pll_desc_id, desc->name,
-		       id[priv->nr] == pll_desc_id ?
-				"insmod option" : "autodetected");
-	}
-
-	return fe;
-}
-EXPORT_SYMBOL(dvb_pll_attach);
-
-MODULE_DESCRIPTION("dvb pll library");
-MODULE_AUTHOR("Gerd Knorr");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/dvb-pll.h b/drivers/media/dvb/frontends/dvb-pll.h
deleted file mode 100644
index 0869643..0000000
--- a/drivers/media/dvb/frontends/dvb-pll.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * descriptions + helper functions for simple dvb plls.
- */
-
-#ifndef __DVB_PLL_H__
-#define __DVB_PLL_H__
-
-#include <linux/i2c.h>
-#include "dvb_frontend.h"
-
-#define DVB_PLL_UNDEFINED               0
-#define DVB_PLL_THOMSON_DTT7579         1
-#define DVB_PLL_THOMSON_DTT759X         2
-#define DVB_PLL_LG_Z201                 3
-#define DVB_PLL_UNKNOWN_1               4
-#define DVB_PLL_TUA6010XS               5
-#define DVB_PLL_ENV57H1XD5              6
-#define DVB_PLL_TUA6034                 7
-#define DVB_PLL_TDA665X                 8
-#define DVB_PLL_TDED4                   9
-#define DVB_PLL_TDHU2                  10
-#define DVB_PLL_SAMSUNG_TBMV           11
-#define DVB_PLL_PHILIPS_SD1878_TDA8261 12
-#define DVB_PLL_OPERA1                 13
-#define DVB_PLL_SAMSUNG_DTOS403IH102A  14
-#define DVB_PLL_SAMSUNG_TDTC9251DH0    15
-#define DVB_PLL_SAMSUNG_TBDU18132      16
-#define DVB_PLL_SAMSUNG_TBMU24112      17
-#define DVB_PLL_TDEE4		       18
-
-/**
- * Attach a dvb-pll to the supplied frontend structure.
- *
- * @param fe Frontend to attach to.
- * @param pll_addr i2c address of the PLL (if used).
- * @param i2c i2c adapter to use (set to NULL if not used).
- * @param pll_desc_id dvb_pll_desc to use.
- * @return Frontend pointer on success, NULL on failure
- */
-#if defined(CONFIG_DVB_PLL) || (defined(CONFIG_DVB_PLL_MODULE) && defined(MODULE))
-extern struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe,
-					   int pll_addr,
-					   struct i2c_adapter *i2c,
-					   unsigned int pll_desc_id);
-#else
-static inline struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe,
-					   int pll_addr,
-					   struct i2c_adapter *i2c,
-					   unsigned int pll_desc_id)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif
-
-#endif
diff --git a/drivers/media/dvb/frontends/dvb_dummy_fe.c b/drivers/media/dvb/frontends/dvb_dummy_fe.c
deleted file mode 100644
index dcfc902..0000000
--- a/drivers/media/dvb/frontends/dvb_dummy_fe.c
+++ /dev/null
@@ -1,276 +0,0 @@
-/*
- *  Driver for Dummy Frontend
- *
- *  Written by Emard <emard@softhome.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 program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *
- *  GNU General Public License for more details.
- *
- *  You 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/init.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-
-#include "dvb_frontend.h"
-#include "dvb_dummy_fe.h"
-
-
-struct dvb_dummy_fe_state {
-	struct dvb_frontend frontend;
-};
-
-
-static int dvb_dummy_fe_read_status(struct dvb_frontend* fe, fe_status_t* status)
-{
-	*status = FE_HAS_SIGNAL
-		| FE_HAS_CARRIER
-		| FE_HAS_VITERBI
-		| FE_HAS_SYNC
-		| FE_HAS_LOCK;
-
-	return 0;
-}
-
-static int dvb_dummy_fe_read_ber(struct dvb_frontend* fe, u32* ber)
-{
-	*ber = 0;
-	return 0;
-}
-
-static int dvb_dummy_fe_read_signal_strength(struct dvb_frontend* fe, u16* strength)
-{
-	*strength = 0;
-	return 0;
-}
-
-static int dvb_dummy_fe_read_snr(struct dvb_frontend* fe, u16* snr)
-{
-	*snr = 0;
-	return 0;
-}
-
-static int dvb_dummy_fe_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
-{
-	*ucblocks = 0;
-	return 0;
-}
-
-/*
- * Only needed if it actually reads something from the hardware
- */
-static int dvb_dummy_fe_get_frontend(struct dvb_frontend *fe)
-{
-	return 0;
-}
-
-static int dvb_dummy_fe_set_frontend(struct dvb_frontend *fe)
-{
-	if (fe->ops.tuner_ops.set_params) {
-		fe->ops.tuner_ops.set_params(fe);
-		if (fe->ops.i2c_gate_ctrl)
-			fe->ops.i2c_gate_ctrl(fe, 0);
-	}
-
-	return 0;
-}
-
-static int dvb_dummy_fe_sleep(struct dvb_frontend* fe)
-{
-	return 0;
-}
-
-static int dvb_dummy_fe_init(struct dvb_frontend* fe)
-{
-	return 0;
-}
-
-static int dvb_dummy_fe_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
-{
-	return 0;
-}
-
-static int dvb_dummy_fe_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
-{
-	return 0;
-}
-
-static void dvb_dummy_fe_release(struct dvb_frontend* fe)
-{
-	struct dvb_dummy_fe_state* state = fe->demodulator_priv;
-	kfree(state);
-}
-
-static struct dvb_frontend_ops dvb_dummy_fe_ofdm_ops;
-
-struct dvb_frontend* dvb_dummy_fe_ofdm_attach(void)
-{
-	struct dvb_dummy_fe_state* state = NULL;
-
-	/* allocate memory for the internal state */
-	state = kzalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL);
-	if (state == NULL) goto error;
-
-	/* create dvb_frontend */
-	memcpy(&state->frontend.ops, &dvb_dummy_fe_ofdm_ops, sizeof(struct dvb_frontend_ops));
-	state->frontend.demodulator_priv = state;
-	return &state->frontend;
-
-error:
-	kfree(state);
-	return NULL;
-}
-
-static struct dvb_frontend_ops dvb_dummy_fe_qpsk_ops;
-
-struct dvb_frontend *dvb_dummy_fe_qpsk_attach(void)
-{
-	struct dvb_dummy_fe_state* state = NULL;
-
-	/* allocate memory for the internal state */
-	state = kzalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL);
-	if (state == NULL) goto error;
-
-	/* create dvb_frontend */
-	memcpy(&state->frontend.ops, &dvb_dummy_fe_qpsk_ops, sizeof(struct dvb_frontend_ops));
-	state->frontend.demodulator_priv = state;
-	return &state->frontend;
-
-error:
-	kfree(state);
-	return NULL;
-}
-
-static struct dvb_frontend_ops dvb_dummy_fe_qam_ops;
-
-struct dvb_frontend *dvb_dummy_fe_qam_attach(void)
-{
-	struct dvb_dummy_fe_state* state = NULL;
-
-	/* allocate memory for the internal state */
-	state = kzalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL);
-	if (state == NULL) goto error;
-
-	/* create dvb_frontend */
-	memcpy(&state->frontend.ops, &dvb_dummy_fe_qam_ops, sizeof(struct dvb_frontend_ops));
-	state->frontend.demodulator_priv = state;
-	return &state->frontend;
-
-error:
-	kfree(state);
-	return NULL;
-}
-
-static struct dvb_frontend_ops dvb_dummy_fe_ofdm_ops = {
-	.delsys = { SYS_DVBT },
-	.info = {
-		.name			= "Dummy DVB-T",
-		.frequency_min		= 0,
-		.frequency_max		= 863250000,
-		.frequency_stepsize	= 62500,
-		.caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
-				FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
-				FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO |
-				FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
-				FE_CAN_TRANSMISSION_MODE_AUTO |
-				FE_CAN_GUARD_INTERVAL_AUTO |
-				FE_CAN_HIERARCHY_AUTO,
-	},
-
-	.release = dvb_dummy_fe_release,
-
-	.init = dvb_dummy_fe_init,
-	.sleep = dvb_dummy_fe_sleep,
-
-	.set_frontend = dvb_dummy_fe_set_frontend,
-	.get_frontend = dvb_dummy_fe_get_frontend,
-
-	.read_status = dvb_dummy_fe_read_status,
-	.read_ber = dvb_dummy_fe_read_ber,
-	.read_signal_strength = dvb_dummy_fe_read_signal_strength,
-	.read_snr = dvb_dummy_fe_read_snr,
-	.read_ucblocks = dvb_dummy_fe_read_ucblocks,
-};
-
-static struct dvb_frontend_ops dvb_dummy_fe_qam_ops = {
-	.delsys = { SYS_DVBC_ANNEX_A },
-	.info = {
-		.name			= "Dummy DVB-C",
-		.frequency_stepsize	= 62500,
-		.frequency_min		= 51000000,
-		.frequency_max		= 858000000,
-		.symbol_rate_min	= (57840000/2)/64,     /* SACLK/64 == (XIN/2)/64 */
-		.symbol_rate_max	= (57840000/2)/4,      /* SACLK/4 */
-		.caps = FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 |
-			FE_CAN_QAM_128 | FE_CAN_QAM_256 |
-			FE_CAN_FEC_AUTO | FE_CAN_INVERSION_AUTO
-	},
-
-	.release = dvb_dummy_fe_release,
-
-	.init = dvb_dummy_fe_init,
-	.sleep = dvb_dummy_fe_sleep,
-
-	.set_frontend = dvb_dummy_fe_set_frontend,
-	.get_frontend = dvb_dummy_fe_get_frontend,
-
-	.read_status = dvb_dummy_fe_read_status,
-	.read_ber = dvb_dummy_fe_read_ber,
-	.read_signal_strength = dvb_dummy_fe_read_signal_strength,
-	.read_snr = dvb_dummy_fe_read_snr,
-	.read_ucblocks = dvb_dummy_fe_read_ucblocks,
-};
-
-static struct dvb_frontend_ops dvb_dummy_fe_qpsk_ops = {
-	.delsys = { SYS_DVBS },
-	.info = {
-		.name			= "Dummy DVB-S",
-		.frequency_min		= 950000,
-		.frequency_max		= 2150000,
-		.frequency_stepsize	= 250,           /* kHz for QPSK frontends */
-		.frequency_tolerance	= 29500,
-		.symbol_rate_min	= 1000000,
-		.symbol_rate_max	= 45000000,
-		.caps = FE_CAN_INVERSION_AUTO |
-			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_FEC_AUTO |
-			FE_CAN_QPSK
-	},
-
-	.release = dvb_dummy_fe_release,
-
-	.init = dvb_dummy_fe_init,
-	.sleep = dvb_dummy_fe_sleep,
-
-	.set_frontend = dvb_dummy_fe_set_frontend,
-	.get_frontend = dvb_dummy_fe_get_frontend,
-
-	.read_status = dvb_dummy_fe_read_status,
-	.read_ber = dvb_dummy_fe_read_ber,
-	.read_signal_strength = dvb_dummy_fe_read_signal_strength,
-	.read_snr = dvb_dummy_fe_read_snr,
-	.read_ucblocks = dvb_dummy_fe_read_ucblocks,
-
-	.set_voltage = dvb_dummy_fe_set_voltage,
-	.set_tone = dvb_dummy_fe_set_tone,
-};
-
-MODULE_DESCRIPTION("DVB DUMMY Frontend");
-MODULE_AUTHOR("Emard");
-MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(dvb_dummy_fe_ofdm_attach);
-EXPORT_SYMBOL(dvb_dummy_fe_qam_attach);
-EXPORT_SYMBOL(dvb_dummy_fe_qpsk_attach);
diff --git a/drivers/media/dvb/frontends/dvb_dummy_fe.h b/drivers/media/dvb/frontends/dvb_dummy_fe.h
deleted file mode 100644
index 1fcb987..0000000
--- a/drivers/media/dvb/frontends/dvb_dummy_fe.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- *  Driver for Dummy Frontend
- *
- *  Written by Emard <emard@softhome.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 program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *
- *  GNU General Public License for more details.
- *
- *  You 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_DUMMY_FE_H
-#define DVB_DUMMY_FE_H
-
-#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/ec100.c b/drivers/media/dvb/frontends/ec100.c
deleted file mode 100644
index c56fddb..0000000
--- a/drivers/media/dvb/frontends/ec100.c
+++ /dev/null
@@ -1,335 +0,0 @@
-/*
- * E3C EC100 demodulator driver
- *
- * 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 "dvb_frontend.h"
-#include "ec100_priv.h"
-#include "ec100.h"
-
-int ec100_debug;
-module_param_named(debug, ec100_debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
-
-struct ec100_state {
-	struct i2c_adapter *i2c;
-	struct dvb_frontend frontend;
-	struct ec100_config config;
-
-	u16 ber;
-};
-
-/* write single register */
-static int ec100_write_reg(struct ec100_state *state, u8 reg, u8 val)
-{
-	u8 buf[2] = {reg, val};
-	struct i2c_msg msg = {
-		.addr = state->config.demod_address,
-		.flags = 0,
-		.len = 2,
-		.buf = buf};
-
-	if (i2c_transfer(state->i2c, &msg, 1) != 1) {
-		warn("I2C write failed reg:%02x", reg);
-		return -EREMOTEIO;
-	}
-	return 0;
-}
-
-/* read single register */
-static int ec100_read_reg(struct ec100_state *state, u8 reg, u8 *val)
-{
-	struct i2c_msg msg[2] = {
-		{
-			.addr = state->config.demod_address,
-			.flags = 0,
-			.len = 1,
-			.buf = &reg
-		}, {
-			.addr = state->config.demod_address,
-			.flags = I2C_M_RD,
-			.len = 1,
-			.buf = val
-		}
-	};
-
-	if (i2c_transfer(state->i2c, msg, 2) != 2) {
-		warn("I2C read failed reg:%02x", reg);
-		return -EREMOTEIO;
-	}
-	return 0;
-}
-
-static int ec100_set_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	struct ec100_state *state = fe->demodulator_priv;
-	int ret;
-	u8 tmp, tmp2;
-
-	deb_info("%s: freq:%d bw:%d\n", __func__, c->frequency,
-		c->bandwidth_hz);
-
-	/* program tuner */
-	if (fe->ops.tuner_ops.set_params)
-		fe->ops.tuner_ops.set_params(fe);
-
-	ret = ec100_write_reg(state, 0x04, 0x06);
-	if (ret)
-		goto error;
-	ret = ec100_write_reg(state, 0x67, 0x58);
-	if (ret)
-		goto error;
-	ret = ec100_write_reg(state, 0x05, 0x18);
-	if (ret)
-		goto error;
-
-	/* reg/bw |   6  |   7  |   8
-	   -------+------+------+------
-	   A 0x1b | 0xa1 | 0xe7 | 0x2c
-	   A 0x1c | 0x55 | 0x63 | 0x72
-	   -------+------+------+------
-	   B 0x1b | 0xb7 | 0x00 | 0x49
-	   B 0x1c | 0x55 | 0x64 | 0x72 */
-
-	switch (c->bandwidth_hz) {
-	case 6000000:
-		tmp = 0xb7;
-		tmp2 = 0x55;
-		break;
-	case 7000000:
-		tmp = 0x00;
-		tmp2 = 0x64;
-		break;
-	case 8000000:
-	default:
-		tmp = 0x49;
-		tmp2 = 0x72;
-	}
-
-	ret = ec100_write_reg(state, 0x1b, tmp);
-	if (ret)
-		goto error;
-	ret = ec100_write_reg(state, 0x1c, tmp2);
-	if (ret)
-		goto error;
-
-	ret = ec100_write_reg(state, 0x0c, 0xbb); /* if freq */
-	if (ret)
-		goto error;
-	ret = ec100_write_reg(state, 0x0d, 0x31); /* if freq */
-	if (ret)
-		goto error;
-
-	ret = ec100_write_reg(state, 0x08, 0x24);
-	if (ret)
-		goto error;
-
-	ret = ec100_write_reg(state, 0x00, 0x00); /* go */
-	if (ret)
-		goto error;
-	ret = ec100_write_reg(state, 0x00, 0x20); /* go */
-	if (ret)
-		goto error;
-
-	return ret;
-error:
-	deb_info("%s: failed:%d\n", __func__, ret);
-	return ret;
-}
-
-static int ec100_get_tune_settings(struct dvb_frontend *fe,
-	struct dvb_frontend_tune_settings *fesettings)
-{
-	fesettings->min_delay_ms = 300;
-	fesettings->step_size = 0;
-	fesettings->max_drift = 0;
-
-	return 0;
-}
-
-static int ec100_read_status(struct dvb_frontend *fe, fe_status_t *status)
-{
-	struct ec100_state *state = fe->demodulator_priv;
-	int ret;
-	u8 tmp;
-	*status = 0;
-
-	ret = ec100_read_reg(state, 0x42, &tmp);
-	if (ret)
-		goto error;
-
-	if (tmp & 0x80) {
-		/* bit7 set - have lock */
-		*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI |
-			FE_HAS_SYNC | FE_HAS_LOCK;
-	} else {
-		ret = ec100_read_reg(state, 0x01, &tmp);
-		if (ret)
-			goto error;
-
-		if (tmp & 0x10) {
-			/* bit4 set - have signal */
-			*status |= FE_HAS_SIGNAL;
-			if (!(tmp & 0x01)) {
-				/* bit0 clear - have ~valid signal */
-				*status |= FE_HAS_CARRIER |  FE_HAS_VITERBI;
-			}
-		}
-	}
-
-	return ret;
-error:
-	deb_info("%s: failed:%d\n", __func__, ret);
-	return ret;
-}
-
-static int ec100_read_ber(struct dvb_frontend *fe, u32 *ber)
-{
-	struct ec100_state *state = fe->demodulator_priv;
-	int ret;
-	u8 tmp, tmp2;
-	u16 ber2;
-
-	*ber = 0;
-
-	ret = ec100_read_reg(state, 0x65, &tmp);
-	if (ret)
-		goto error;
-	ret = ec100_read_reg(state, 0x66, &tmp2);
-	if (ret)
-		goto error;
-
-	ber2 = (tmp2 << 8) | tmp;
-
-	/* if counter overflow or clear */
-	if (ber2 < state->ber)
-		*ber = ber2;
-	else
-		*ber = ber2 - state->ber;
-
-	state->ber = ber2;
-
-	return ret;
-error:
-	deb_info("%s: failed:%d\n", __func__, ret);
-	return ret;
-}
-
-static int ec100_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
-{
-	struct ec100_state *state = fe->demodulator_priv;
-	int ret;
-	u8 tmp;
-
-	ret = ec100_read_reg(state, 0x24, &tmp);
-	if (ret) {
-		*strength = 0;
-		goto error;
-	}
-
-	*strength = ((tmp << 8) | tmp);
-
-	return ret;
-error:
-	deb_info("%s: failed:%d\n", __func__, ret);
-	return ret;
-}
-
-static int ec100_read_snr(struct dvb_frontend *fe, u16 *snr)
-{
-	*snr = 0;
-	return 0;
-}
-
-static int ec100_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
-{
-	*ucblocks = 0;
-	return 0;
-}
-
-static void ec100_release(struct dvb_frontend *fe)
-{
-	struct ec100_state *state = fe->demodulator_priv;
-	kfree(state);
-}
-
-static struct dvb_frontend_ops ec100_ops;
-
-struct dvb_frontend *ec100_attach(const struct ec100_config *config,
-	struct i2c_adapter *i2c)
-{
-	int ret;
-	struct ec100_state *state = NULL;
-	u8 tmp;
-
-	/* allocate memory for the internal state */
-	state = kzalloc(sizeof(struct ec100_state), GFP_KERNEL);
-	if (state == NULL)
-		goto error;
-
-	/* setup the state */
-	state->i2c = i2c;
-	memcpy(&state->config, config, sizeof(struct ec100_config));
-
-	/* check if the demod is there */
-	ret = ec100_read_reg(state, 0x33, &tmp);
-	if (ret || tmp != 0x0b)
-		goto error;
-
-	/* create dvb_frontend */
-	memcpy(&state->frontend.ops, &ec100_ops,
-		sizeof(struct dvb_frontend_ops));
-	state->frontend.demodulator_priv = state;
-
-	return &state->frontend;
-error:
-	kfree(state);
-	return NULL;
-}
-EXPORT_SYMBOL(ec100_attach);
-
-static struct dvb_frontend_ops ec100_ops = {
-	.delsys = { SYS_DVBT },
-	.info = {
-		.name = "E3C EC100 DVB-T",
-		.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_FEC_AUTO |
-			FE_CAN_QPSK | FE_CAN_QAM_16 |
-			FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
-			FE_CAN_TRANSMISSION_MODE_AUTO |
-			FE_CAN_GUARD_INTERVAL_AUTO |
-			FE_CAN_HIERARCHY_AUTO |
-			FE_CAN_MUTE_TS
-	},
-
-	.release = ec100_release,
-	.set_frontend = ec100_set_frontend,
-	.get_tune_settings = ec100_get_tune_settings,
-	.read_status = ec100_read_status,
-	.read_ber = ec100_read_ber,
-	.read_signal_strength = ec100_read_signal_strength,
-	.read_snr = ec100_read_snr,
-	.read_ucblocks = ec100_read_ucblocks,
-};
-
-MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
-MODULE_DESCRIPTION("E3C EC100 DVB-T demodulator driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/ec100.h b/drivers/media/dvb/frontends/ec100.h
deleted file mode 100644
index ee8e524..0000000
--- a/drivers/media/dvb/frontends/ec100.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * E3C EC100 demodulator driver
- *
- * 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 EC100_H
-#define EC100_H
-
-#include <linux/dvb/frontend.h>
-
-struct ec100_config {
-	/* demodulator's I2C address */
-	u8 demod_address;
-};
-
-
-#if defined(CONFIG_DVB_EC100) || \
-	(defined(CONFIG_DVB_EC100_MODULE) && defined(MODULE))
-extern struct dvb_frontend *ec100_attach(const struct ec100_config *config,
-	struct i2c_adapter *i2c);
-#else
-static inline struct dvb_frontend *ec100_attach(
-	const struct ec100_config *config, struct i2c_adapter *i2c)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif
-
-#endif /* EC100_H */
diff --git a/drivers/media/dvb/frontends/ec100_priv.h b/drivers/media/dvb/frontends/ec100_priv.h
deleted file mode 100644
index 5c99014..0000000
--- a/drivers/media/dvb/frontends/ec100_priv.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * E3C EC100 demodulator driver
- *
- * 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 EC100_PRIV
-#define EC100_PRIV
-
-#define LOG_PREFIX "ec100"
-
-#define dprintk(var, level, args...) \
-	do { if ((var & level)) printk(args); } while (0)
-
-#define deb_info(args...) dprintk(ec100_debug, 0x01, args)
-
-#undef err
-#define err(f, arg...)  printk(KERN_ERR     LOG_PREFIX": " f "\n" , ## arg)
-#undef info
-#define info(f, arg...) printk(KERN_INFO    LOG_PREFIX": " f "\n" , ## arg)
-#undef warn
-#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg)
-
-#endif /* EC100_PRIV */
diff --git a/drivers/media/dvb/frontends/eds1547.h b/drivers/media/dvb/frontends/eds1547.h
deleted file mode 100644
index c983f2f..0000000
--- a/drivers/media/dvb/frontends/eds1547.h
+++ /dev/null
@@ -1,133 +0,0 @@
-/* eds1547.h Earda EDS-1547 tuner support
-*
-* Copyright (C) 2008 Igor M. Liplianin (liplianin@me.by)
-*
-*	This program is free software; 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.
-*
-* see Documentation/dvb/README.dvb-usb for more information
-*/
-
-#ifndef EDS1547
-#define EDS1547
-
-static u8 stv0288_earda_inittab[] = {
-	0x01, 0x57,
-	0x02, 0x20,
-	0x03, 0x8e,
-	0x04, 0x8e,
-	0x05, 0x12,
-	0x06, 0x00,
-	0x07, 0x00,
-	0x09, 0x00,
-	0x0a, 0x04,
-	0x0b, 0x00,
-	0x0c, 0x00,
-	0x0d, 0x00,
-	0x0e, 0xd4,
-	0x0f, 0x30,
-	0x11, 0x44,
-	0x12, 0x03,
-	0x13, 0x48,
-	0x14, 0x84,
-	0x15, 0x45,
-	0x16, 0xb7,
-	0x17, 0x9c,
-	0x18, 0x00,
-	0x19, 0xa6,
-	0x1a, 0x88,
-	0x1b, 0x8f,
-	0x1c, 0xf0,
-	0x20, 0x0b,
-	0x21, 0x54,
-	0x22, 0x00,
-	0x23, 0x00,
-	0x2b, 0xff,
-	0x2c, 0xf7,
-	0x30, 0x00,
-	0x31, 0x1e,
-	0x32, 0x14,
-	0x33, 0x0f,
-	0x34, 0x09,
-	0x35, 0x0c,
-	0x36, 0x05,
-	0x37, 0x2f,
-	0x38, 0x16,
-	0x39, 0xbd,
-	0x3a, 0x00,
-	0x3b, 0x13,
-	0x3c, 0x11,
-	0x3d, 0x30,
-	0x40, 0x63,
-	0x41, 0x04,
-	0x42, 0x20,
-	0x43, 0x00,
-	0x44, 0x00,
-	0x45, 0x00,
-	0x46, 0x00,
-	0x47, 0x00,
-	0x4a, 0x00,
-	0x50, 0x10,
-	0x51, 0x36,
-	0x52, 0x09,
-	0x53, 0x94,
-	0x54, 0x62,
-	0x55, 0x29,
-	0x56, 0x64,
-	0x57, 0x2b,
-	0x58, 0x54,
-	0x59, 0x86,
-	0x5a, 0x00,
-	0x5b, 0x9b,
-	0x5c, 0x08,
-	0x5d, 0x7f,
-	0x5e, 0x00,
-	0x5f, 0xff,
-	0x70, 0x00,
-	0x71, 0x00,
-	0x72, 0x00,
-	0x74, 0x00,
-	0x75, 0x00,
-	0x76, 0x00,
-	0x81, 0x00,
-	0x82, 0x3f,
-	0x83, 0x3f,
-	0x84, 0x00,
-	0x85, 0x00,
-	0x88, 0x00,
-	0x89, 0x00,
-	0x8a, 0x00,
-	0x8b, 0x00,
-	0x8c, 0x00,
-	0x90, 0x00,
-	0x91, 0x00,
-	0x92, 0x00,
-	0x93, 0x00,
-	0x94, 0x1c,
-	0x97, 0x00,
-	0xa0, 0x48,
-	0xa1, 0x00,
-	0xb0, 0xb8,
-	0xb1, 0x3a,
-	0xb2, 0x10,
-	0xb3, 0x82,
-	0xb4, 0x80,
-	0xb5, 0x82,
-	0xb6, 0x82,
-	0xb7, 0x82,
-	0xb8, 0x20,
-	0xb9, 0x00,
-	0xf0, 0x00,
-	0xf1, 0x00,
-	0xf2, 0xc0,
-	0xff,0xff,
-};
-
-static struct stv0288_config earda_config = {
-	.demod_address = 0x68,
-	.min_delay_ms = 100,
-	.inittab = stv0288_earda_inittab,
-};
-
-#endif
diff --git a/drivers/media/dvb/frontends/hd29l2.c b/drivers/media/dvb/frontends/hd29l2.c
deleted file mode 100644
index a003181..0000000
--- a/drivers/media/dvb/frontends/hd29l2.c
+++ /dev/null
@@ -1,861 +0,0 @@
-/*
- * HDIC HD29L2 DMB-TH demodulator driver
- *
- * Copyright (C) 2011 Metropolia University of Applied Sciences, Electria R&D
- *
- * Author: 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 "hd29l2_priv.h"
-
-int hd29l2_debug;
-module_param_named(debug, hd29l2_debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
-
-/* write multiple registers */
-static int hd29l2_wr_regs(struct hd29l2_priv *priv, u8 reg, u8 *val, int len)
-{
-	int ret;
-	u8 buf[2 + len];
-	struct i2c_msg msg[1] = {
-		{
-			.addr = priv->cfg.i2c_addr,
-			.flags = 0,
-			.len = sizeof(buf),
-			.buf = buf,
-		}
-	};
-
-	buf[0] = 0x00;
-	buf[1] = reg;
-	memcpy(&buf[2], val, len);
-
-	ret = i2c_transfer(priv->i2c, msg, 1);
-	if (ret == 1) {
-		ret = 0;
-	} else {
-		warn("i2c wr failed=%d reg=%02x len=%d", ret, reg, len);
-		ret = -EREMOTEIO;
-	}
-
-	return ret;
-}
-
-/* read multiple registers */
-static int hd29l2_rd_regs(struct hd29l2_priv *priv, u8 reg, u8 *val, int len)
-{
-	int ret;
-	u8 buf[2] = { 0x00, reg };
-	struct i2c_msg msg[2] = {
-		{
-			.addr = priv->cfg.i2c_addr,
-			.flags = 0,
-			.len = 2,
-			.buf = buf,
-		}, {
-			.addr = priv->cfg.i2c_addr,
-			.flags = I2C_M_RD,
-			.len = len,
-			.buf = val,
-		}
-	};
-
-	ret = i2c_transfer(priv->i2c, msg, 2);
-	if (ret == 2) {
-		ret = 0;
-	} else {
-		warn("i2c rd failed=%d reg=%02x len=%d", ret, reg, len);
-		ret = -EREMOTEIO;
-	}
-
-	return ret;
-}
-
-/* write single register */
-static int hd29l2_wr_reg(struct hd29l2_priv *priv, u8 reg, u8 val)
-{
-	return hd29l2_wr_regs(priv, reg, &val, 1);
-}
-
-/* read single register */
-static int hd29l2_rd_reg(struct hd29l2_priv *priv, u8 reg, u8 *val)
-{
-	return hd29l2_rd_regs(priv, reg, val, 1);
-}
-
-/* write single register with mask */
-static int hd29l2_wr_reg_mask(struct hd29l2_priv *priv, u8 reg, u8 val, u8 mask)
-{
-	int ret;
-	u8 tmp;
-
-	/* no need for read if whole reg is written */
-	if (mask != 0xff) {
-		ret = hd29l2_rd_regs(priv, reg, &tmp, 1);
-		if (ret)
-			return ret;
-
-		val &= mask;
-		tmp &= ~mask;
-		val |= tmp;
-	}
-
-	return hd29l2_wr_regs(priv, reg, &val, 1);
-}
-
-/* read single register with mask */
-int hd29l2_rd_reg_mask(struct hd29l2_priv *priv, u8 reg, u8 *val, u8 mask)
-{
-	int ret, i;
-	u8 tmp;
-
-	ret = hd29l2_rd_regs(priv, reg, &tmp, 1);
-	if (ret)
-		return ret;
-
-	tmp &= mask;
-
-	/* find position of the first bit */
-	for (i = 0; i < 8; i++) {
-		if ((mask >> i) & 0x01)
-			break;
-	}
-	*val = tmp >> i;
-
-	return 0;
-}
-
-static int hd29l2_soft_reset(struct hd29l2_priv *priv)
-{
-	int ret;
-	u8 tmp;
-
-	ret = hd29l2_rd_reg(priv, 0x26, &tmp);
-	if (ret)
-		goto err;
-
-	ret = hd29l2_wr_reg(priv, 0x26, 0x0d);
-	if (ret)
-		goto err;
-
-	usleep_range(10000, 20000);
-
-	ret = hd29l2_wr_reg(priv, 0x26, tmp);
-	if (ret)
-		goto err;
-
-	return 0;
-err:
-	dbg("%s: failed=%d", __func__, ret);
-	return ret;
-}
-
-static int hd29l2_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
-{
-	int ret, i;
-	struct hd29l2_priv *priv = fe->demodulator_priv;
-	u8 tmp;
-
-	dbg("%s: enable=%d", __func__, enable);
-
-	/* set tuner address for demod */
-	if (!priv->tuner_i2c_addr_programmed && enable) {
-		/* no need to set tuner address every time, once is enough */
-		ret = hd29l2_wr_reg(priv, 0x9d, priv->cfg.tuner_i2c_addr << 1);
-		if (ret)
-			goto err;
-
-		priv->tuner_i2c_addr_programmed = true;
-	}
-
-	/* open / close gate */
-	ret = hd29l2_wr_reg(priv, 0x9f, enable);
-	if (ret)
-		goto err;
-
-	/* wait demod ready */
-	for (i = 10; i; i--) {
-		ret = hd29l2_rd_reg(priv, 0x9e, &tmp);
-		if (ret)
-			goto err;
-
-		if (tmp == enable)
-			break;
-
-		usleep_range(5000, 10000);
-	}
-
-	dbg("%s: loop=%d", __func__, i);
-
-	return ret;
-err:
-	dbg("%s: failed=%d", __func__, ret);
-	return ret;
-}
-
-static int hd29l2_read_status(struct dvb_frontend *fe, fe_status_t *status)
-{
-	int ret;
-	struct hd29l2_priv *priv = fe->demodulator_priv;
-	u8 buf[2];
-
-	*status = 0;
-
-	ret = hd29l2_rd_reg(priv, 0x05, &buf[0]);
-	if (ret)
-		goto err;
-
-	if (buf[0] & 0x01) {
-		/* full lock */
-		*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI |
-			FE_HAS_SYNC | FE_HAS_LOCK;
-	} else {
-		ret = hd29l2_rd_reg(priv, 0x0d, &buf[1]);
-		if (ret)
-			goto err;
-
-		if ((buf[1] & 0xfe) == 0x78)
-			/* partial lock */
-			*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
-				FE_HAS_VITERBI | FE_HAS_SYNC;
-	}
-
-	priv->fe_status = *status;
-
-	return 0;
-err:
-	dbg("%s: failed=%d", __func__, ret);
-	return ret;
-}
-
-static int hd29l2_read_snr(struct dvb_frontend *fe, u16 *snr)
-{
-	int ret;
-	struct hd29l2_priv *priv = fe->demodulator_priv;
-	u8 buf[2];
-	u16 tmp;
-
-	if (!(priv->fe_status & FE_HAS_LOCK)) {
-		*snr = 0;
-		ret = 0;
-		goto err;
-	}
-
-	ret = hd29l2_rd_regs(priv, 0x0b, buf, 2);
-	if (ret)
-		goto err;
-
-	tmp = (buf[0] << 8) | buf[1];
-
-	/* report SNR in dB * 10 */
-	#define LOG10_20736_24 72422627 /* log10(20736) << 24 */
-	if (tmp)
-		*snr = (LOG10_20736_24 - intlog10(tmp)) / ((1 << 24) / 100);
-	else
-		*snr = 0;
-
-	return 0;
-err:
-	dbg("%s: failed=%d", __func__, ret);
-	return ret;
-}
-
-static int hd29l2_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
-{
-	int ret;
-	struct hd29l2_priv *priv = fe->demodulator_priv;
-	u8 buf[2];
-	u16 tmp;
-
-	*strength = 0;
-
-	ret = hd29l2_rd_regs(priv, 0xd5, buf, 2);
-	if (ret)
-		goto err;
-
-	tmp = buf[0] << 8 | buf[1];
-	tmp = ~tmp & 0x0fff;
-
-	/* scale value to 0x0000-0xffff from 0x0000-0x0fff */
-	*strength = tmp * 0xffff / 0x0fff;
-
-	return 0;
-err:
-	dbg("%s: failed=%d", __func__, ret);
-	return ret;
-}
-
-static int hd29l2_read_ber(struct dvb_frontend *fe, u32 *ber)
-{
-	int ret;
-	struct hd29l2_priv *priv = fe->demodulator_priv;
-	u8 buf[2];
-
-	if (!(priv->fe_status & FE_HAS_SYNC)) {
-		*ber = 0;
-		ret = 0;
-		goto err;
-	}
-
-	ret = hd29l2_rd_regs(priv, 0xd9, buf, 2);
-	if (ret) {
-		*ber = 0;
-		goto err;
-	}
-
-	/* LDPC BER */
-	*ber = ((buf[0] & 0x0f) << 8) | buf[1];
-
-	return 0;
-err:
-	dbg("%s: failed=%d", __func__, ret);
-	return ret;
-}
-
-static int hd29l2_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
-{
-	/* no way to read? */
-	*ucblocks = 0;
-	return 0;
-}
-
-static enum dvbfe_search hd29l2_search(struct dvb_frontend *fe)
-{
-	int ret, i;
-	struct hd29l2_priv *priv = fe->demodulator_priv;
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	u8 tmp, buf[3];
-	u8 modulation, carrier, guard_interval, interleave, code_rate;
-	u64 num64;
-	u32 if_freq, if_ctl;
-	bool auto_mode;
-
-	dbg("%s: delivery_system=%d frequency=%d bandwidth_hz=%d " \
-		"modulation=%d inversion=%d fec_inner=%d guard_interval=%d",
-		 __func__,
-		c->delivery_system, c->frequency, c->bandwidth_hz,
-		c->modulation, c->inversion, c->fec_inner, c->guard_interval);
-
-	/* as for now we detect always params automatically */
-	auto_mode = true;
-
-	/* program tuner */
-	if (fe->ops.tuner_ops.set_params)
-		fe->ops.tuner_ops.set_params(fe);
-
-	/* get and program IF */
-	if (fe->ops.tuner_ops.get_if_frequency)
-		fe->ops.tuner_ops.get_if_frequency(fe, &if_freq);
-	else
-		if_freq = 0;
-
-	if (if_freq) {
-		/* normal IF */
-
-		/* calc IF control value */
-		num64 = if_freq;
-		num64 *= 0x800000;
-		num64 = div_u64(num64, HD29L2_XTAL);
-		num64 -= 0x800000;
-		if_ctl = num64;
-
-		tmp = 0xfc; /* tuner type normal */
-	} else {
-		/* zero IF */
-		if_ctl = 0;
-		tmp = 0xfe; /* tuner type Zero-IF */
-	}
-
-	buf[0] = ((if_ctl >>  0) & 0xff);
-	buf[1] = ((if_ctl >>  8) & 0xff);
-	buf[2] = ((if_ctl >> 16) & 0xff);
-
-	/* program IF control */
-	ret = hd29l2_wr_regs(priv, 0x14, buf, 3);
-	if (ret)
-		goto err;
-
-	/* program tuner type */
-	ret = hd29l2_wr_reg(priv, 0xab, tmp);
-	if (ret)
-		goto err;
-
-	dbg("%s: if_freq=%d if_ctl=%x", __func__, if_freq, if_ctl);
-
-	if (auto_mode) {
-		/*
-		 * use auto mode
-		 */
-
-		/* disable quick mode */
-		ret = hd29l2_wr_reg_mask(priv, 0xac, 0 << 7, 0x80);
-		if (ret)
-			goto err;
-
-		ret = hd29l2_wr_reg_mask(priv, 0x82, 1 << 1, 0x02);
-		if (ret)
-			goto err;
-
-		/* enable auto mode */
-		ret = hd29l2_wr_reg_mask(priv, 0x7d, 1 << 6, 0x40);
-		if (ret)
-			goto err;
-
-		ret = hd29l2_wr_reg_mask(priv, 0x81, 1 << 3, 0x08);
-		if (ret)
-			goto err;
-
-		/* soft reset */
-		ret = hd29l2_soft_reset(priv);
-		if (ret)
-			goto err;
-
-		/* detect modulation */
-		for (i = 30; i; i--) {
-			msleep(100);
-
-			ret = hd29l2_rd_reg(priv, 0x0d, &tmp);
-			if (ret)
-				goto err;
-
-			if ((((tmp & 0xf0) >= 0x10) &&
-				((tmp & 0x0f) == 0x08)) || (tmp >= 0x2c))
-				break;
-		}
-
-		dbg("%s: loop=%d", __func__, i);
-
-		if (i == 0)
-			/* detection failed */
-			return DVBFE_ALGO_SEARCH_FAILED;
-
-		/* read modulation */
-		ret = hd29l2_rd_reg_mask(priv, 0x7d, &modulation, 0x07);
-		if (ret)
-			goto err;
-	} else {
-		/*
-		 * use manual mode
-		 */
-
-		modulation = HD29L2_QAM64;
-		carrier = HD29L2_CARRIER_MULTI;
-		guard_interval = HD29L2_PN945;
-		interleave = HD29L2_INTERLEAVER_420;
-		code_rate = HD29L2_CODE_RATE_08;
-
-		tmp = (code_rate << 3) | modulation;
-		ret = hd29l2_wr_reg_mask(priv, 0x7d, tmp, 0x5f);
-		if (ret)
-			goto err;
-
-		tmp = (carrier << 2) | guard_interval;
-		ret = hd29l2_wr_reg_mask(priv, 0x81, tmp, 0x0f);
-		if (ret)
-			goto err;
-
-		tmp = interleave;
-		ret = hd29l2_wr_reg_mask(priv, 0x82, tmp, 0x03);
-		if (ret)
-			goto err;
-	}
-
-	/* ensure modulation validy */
-	/* 0=QAM4_NR, 1=QAM4, 2=QAM16, 3=QAM32, 4=QAM64 */
-	if (modulation > (ARRAY_SIZE(reg_mod_vals_tab[0].val) - 1)) {
-		dbg("%s: modulation=%d not valid", __func__, modulation);
-		goto err;
-	}
-
-	/* program registers according to modulation */
-	for (i = 0; i < ARRAY_SIZE(reg_mod_vals_tab); i++) {
-		ret = hd29l2_wr_reg(priv, reg_mod_vals_tab[i].reg,
-			reg_mod_vals_tab[i].val[modulation]);
-		if (ret)
-			goto err;
-	}
-
-	/* read guard interval */
-	ret = hd29l2_rd_reg_mask(priv, 0x81, &guard_interval, 0x03);
-	if (ret)
-		goto err;
-
-	/* read carrier mode */
-	ret = hd29l2_rd_reg_mask(priv, 0x81, &carrier, 0x04);
-	if (ret)
-		goto err;
-
-	dbg("%s: modulation=%d guard_interval=%d carrier=%d",
-		__func__, modulation, guard_interval, carrier);
-
-	if ((carrier == HD29L2_CARRIER_MULTI) && (modulation == HD29L2_QAM64) &&
-		(guard_interval == HD29L2_PN945)) {
-		dbg("%s: C=3780 && QAM64 && PN945", __func__);
-
-		ret = hd29l2_wr_reg(priv, 0x42, 0x33);
-		if (ret)
-			goto err;
-
-		ret = hd29l2_wr_reg(priv, 0xdd, 0x01);
-		if (ret)
-			goto err;
-	}
-
-	usleep_range(10000, 20000);
-
-	/* soft reset */
-	ret = hd29l2_soft_reset(priv);
-	if (ret)
-		goto err;
-
-	/* wait demod lock */
-	for (i = 30; i; i--) {
-		msleep(100);
-
-		/* read lock bit */
-		ret = hd29l2_rd_reg_mask(priv, 0x05, &tmp, 0x01);
-		if (ret)
-			goto err;
-
-		if (tmp)
-			break;
-	}
-
-	dbg("%s: loop=%d", __func__, i);
-
-	if (i == 0)
-		return DVBFE_ALGO_SEARCH_AGAIN;
-
-	return DVBFE_ALGO_SEARCH_SUCCESS;
-err:
-	dbg("%s: failed=%d", __func__, ret);
-	return DVBFE_ALGO_SEARCH_ERROR;
-}
-
-static int hd29l2_get_frontend_algo(struct dvb_frontend *fe)
-{
-	return DVBFE_ALGO_CUSTOM;
-}
-
-static int hd29l2_get_frontend(struct dvb_frontend *fe)
-{
-	int ret;
-	struct hd29l2_priv *priv = fe->demodulator_priv;
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	u8 buf[3];
-	u32 if_ctl;
-	char *str_constellation, *str_code_rate, *str_constellation_code_rate,
-		*str_guard_interval, *str_carrier, *str_guard_interval_carrier,
-		*str_interleave, *str_interleave_;
-
-	ret = hd29l2_rd_reg(priv, 0x7d, &buf[0]);
-	if (ret)
-		goto err;
-
-	ret = hd29l2_rd_regs(priv, 0x81, &buf[1], 2);
-	if (ret)
-		goto err;
-
-	/* constellation, 0x7d[2:0] */
-	switch ((buf[0] >> 0) & 0x07) {
-	case 0: /* QAM4NR */
-		str_constellation = "QAM4NR";
-		c->modulation = QAM_AUTO; /* FIXME */
-		break;
-	case 1: /* QAM4 */
-		str_constellation = "QAM4";
-		c->modulation = QPSK; /* FIXME */
-		break;
-	case 2:
-		str_constellation = "QAM16";
-		c->modulation = QAM_16;
-		break;
-	case 3:
-		str_constellation = "QAM32";
-		c->modulation = QAM_32;
-		break;
-	case 4:
-		str_constellation = "QAM64";
-		c->modulation = QAM_64;
-		break;
-	default:
-		str_constellation = "?";
-	}
-
-	/* LDPC code rate, 0x7d[4:3] */
-	switch ((buf[0] >> 3) & 0x03) {
-	case 0: /* 0.4 */
-		str_code_rate = "0.4";
-		c->fec_inner = FEC_AUTO; /* FIXME */
-		break;
-	case 1: /* 0.6 */
-		str_code_rate = "0.6";
-		c->fec_inner = FEC_3_5;
-		break;
-	case 2: /* 0.8 */
-		str_code_rate = "0.8";
-		c->fec_inner = FEC_4_5;
-		break;
-	default:
-		str_code_rate = "?";
-	}
-
-	/* constellation & code rate set, 0x7d[6] */
-	switch ((buf[0] >> 6) & 0x01) {
-	case 0:
-		str_constellation_code_rate = "manual";
-		break;
-	case 1:
-		str_constellation_code_rate = "auto";
-		break;
-	default:
-		str_constellation_code_rate = "?";
-	}
-
-	/* frame header, 0x81[1:0] */
-	switch ((buf[1] >> 0) & 0x03) {
-	case 0: /* PN945 */
-		str_guard_interval = "PN945";
-		c->guard_interval = GUARD_INTERVAL_AUTO; /* FIXME */
-		break;
-	case 1: /* PN595 */
-		str_guard_interval = "PN595";
-		c->guard_interval = GUARD_INTERVAL_AUTO; /* FIXME */
-		break;
-	case 2: /* PN420 */
-		str_guard_interval = "PN420";
-		c->guard_interval = GUARD_INTERVAL_AUTO; /* FIXME */
-		break;
-	default:
-		str_guard_interval = "?";
-	}
-
-	/* carrier, 0x81[2] */
-	switch ((buf[1] >> 2) & 0x01) {
-	case 0:
-		str_carrier = "C=1";
-		break;
-	case 1:
-		str_carrier = "C=3780";
-		break;
-	default:
-		str_carrier = "?";
-	}
-
-	/* frame header & carrier set, 0x81[3] */
-	switch ((buf[1] >> 3) & 0x01) {
-	case 0:
-		str_guard_interval_carrier = "manual";
-		break;
-	case 1:
-		str_guard_interval_carrier = "auto";
-		break;
-	default:
-		str_guard_interval_carrier = "?";
-	}
-
-	/* interleave, 0x82[0] */
-	switch ((buf[2] >> 0) & 0x01) {
-	case 0:
-		str_interleave = "M=720";
-		break;
-	case 1:
-		str_interleave = "M=240";
-		break;
-	default:
-		str_interleave = "?";
-	}
-
-	/* interleave set, 0x82[1] */
-	switch ((buf[2] >> 1) & 0x01) {
-	case 0:
-		str_interleave_ = "manual";
-		break;
-	case 1:
-		str_interleave_ = "auto";
-		break;
-	default:
-		str_interleave_ = "?";
-	}
-
-	/*
-	 * We can read out current detected NCO and use that value next
-	 * time instead of calculating new value from targed IF.
-	 * I think it will not effect receiver sensitivity but gaining lock
-	 * after tune could be easier...
-	 */
-	ret = hd29l2_rd_regs(priv, 0xb1, &buf[0], 3);
-	if (ret)
-		goto err;
-
-	if_ctl = (buf[0] << 16) | ((buf[1] - 7) << 8) | buf[2];
-
-	dbg("%s: %s %s %s | %s %s %s | %s %s | NCO=%06x", __func__,
-		str_constellation, str_code_rate, str_constellation_code_rate,
-		str_guard_interval, str_carrier, str_guard_interval_carrier,
-		str_interleave, str_interleave_, if_ctl);
-
-	return 0;
-err:
-	dbg("%s: failed=%d", __func__, ret);
-	return ret;
-}
-
-static int hd29l2_init(struct dvb_frontend *fe)
-{
-	int ret, i;
-	struct hd29l2_priv *priv = fe->demodulator_priv;
-	u8 tmp;
-	static const struct reg_val tab[] = {
-		{ 0x3a, 0x06 },
-		{ 0x3b, 0x03 },
-		{ 0x3c, 0x04 },
-		{ 0xaf, 0x06 },
-		{ 0xb0, 0x1b },
-		{ 0x80, 0x64 },
-		{ 0x10, 0x38 },
-	};
-
-	dbg("%s:", __func__);
-
-	/* reset demod */
-	/* it is recommended to HW reset chip using RST_N pin */
-	if (fe->callback) {
-		ret = fe->callback(fe, DVB_FRONTEND_COMPONENT_DEMOD, 0, 0);
-		if (ret)
-			goto err;
-
-		/* reprogramming needed because HW reset clears registers */
-		priv->tuner_i2c_addr_programmed = false;
-	}
-
-	/* init */
-	for (i = 0; i < ARRAY_SIZE(tab); i++) {
-		ret = hd29l2_wr_reg(priv, tab[i].reg, tab[i].val);
-		if (ret)
-			goto err;
-	}
-
-	/* TS params */
-	ret = hd29l2_rd_reg(priv, 0x36, &tmp);
-	if (ret)
-		goto err;
-
-	tmp &= 0x1b;
-	tmp |= priv->cfg.ts_mode;
-	ret = hd29l2_wr_reg(priv, 0x36, tmp);
-	if (ret)
-		goto err;
-
-	ret = hd29l2_rd_reg(priv, 0x31, &tmp);
-	tmp &= 0xef;
-
-	if (!(priv->cfg.ts_mode >> 7))
-		/* set b4 for serial TS */
-		tmp |= 0x10;
-
-	ret = hd29l2_wr_reg(priv, 0x31, tmp);
-	if (ret)
-		goto err;
-
-	return ret;
-err:
-	dbg("%s: failed=%d", __func__, ret);
-	return ret;
-}
-
-static void hd29l2_release(struct dvb_frontend *fe)
-{
-	struct hd29l2_priv *priv = fe->demodulator_priv;
-	kfree(priv);
-}
-
-static struct dvb_frontend_ops hd29l2_ops;
-
-struct dvb_frontend *hd29l2_attach(const struct hd29l2_config *config,
-	struct i2c_adapter *i2c)
-{
-	int ret;
-	struct hd29l2_priv *priv = NULL;
-	u8 tmp;
-
-	/* allocate memory for the internal state */
-	priv = kzalloc(sizeof(struct hd29l2_priv), GFP_KERNEL);
-	if (priv == NULL)
-		goto err;
-
-	/* setup the state */
-	priv->i2c = i2c;
-	memcpy(&priv->cfg, config, sizeof(struct hd29l2_config));
-
-
-	/* check if the demod is there */
-	ret = hd29l2_rd_reg(priv, 0x00, &tmp);
-	if (ret)
-		goto err;
-
-	/* create dvb_frontend */
-	memcpy(&priv->fe.ops, &hd29l2_ops, sizeof(struct dvb_frontend_ops));
-	priv->fe.demodulator_priv = priv;
-
-	return &priv->fe;
-err:
-	kfree(priv);
-	return NULL;
-}
-EXPORT_SYMBOL(hd29l2_attach);
-
-static struct dvb_frontend_ops hd29l2_ops = {
-	.delsys = { SYS_DVBT },
-	.info = {
-		.name = "HDIC HD29L2 DMB-TH",
-		.frequency_min = 474000000,
-		.frequency_max = 858000000,
-		.frequency_stepsize = 10000,
-		.caps = FE_CAN_FEC_AUTO |
-			FE_CAN_QPSK |
-			FE_CAN_QAM_16 |
-			FE_CAN_QAM_32 |
-			FE_CAN_QAM_64 |
-			FE_CAN_QAM_AUTO |
-			FE_CAN_TRANSMISSION_MODE_AUTO |
-			FE_CAN_BANDWIDTH_AUTO |
-			FE_CAN_GUARD_INTERVAL_AUTO |
-			FE_CAN_HIERARCHY_AUTO |
-			FE_CAN_RECOVER
-	},
-
-	.release = hd29l2_release,
-
-	.init = hd29l2_init,
-
-	.get_frontend_algo = hd29l2_get_frontend_algo,
-	.search = hd29l2_search,
-	.get_frontend = hd29l2_get_frontend,
-
-	.read_status = hd29l2_read_status,
-	.read_snr = hd29l2_read_snr,
-	.read_signal_strength = hd29l2_read_signal_strength,
-	.read_ber = hd29l2_read_ber,
-	.read_ucblocks = hd29l2_read_ucblocks,
-
-	.i2c_gate_ctrl = hd29l2_i2c_gate_ctrl,
-};
-
-MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
-MODULE_DESCRIPTION("HDIC HD29L2 DMB-TH demodulator driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/hd29l2.h b/drivers/media/dvb/frontends/hd29l2.h
deleted file mode 100644
index a7a6443..0000000
--- a/drivers/media/dvb/frontends/hd29l2.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * HDIC HD29L2 DMB-TH demodulator driver
- *
- * Copyright (C) 2011 Metropolia University of Applied Sciences, Electria R&D
- *
- * Author: 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 HD29L2_H
-#define HD29L2_H
-
-#include <linux/dvb/frontend.h>
-
-struct hd29l2_config {
-	/*
-	 * demodulator I2C address
-	 */
-	u8 i2c_addr;
-
-	/*
-	 * tuner I2C address
-	 * only needed when tuner is behind demod I2C-gate
-	 */
-	u8 tuner_i2c_addr;
-
-	/*
-	 * TS settings
-	 */
-#define HD29L2_TS_SERIAL            0x00
-#define HD29L2_TS_PARALLEL          0x80
-#define HD29L2_TS_CLK_NORMAL        0x40
-#define HD29L2_TS_CLK_INVERTED      0x00
-#define HD29L2_TS_CLK_GATED         0x20
-#define HD29L2_TS_CLK_FREE          0x00
-	u8 ts_mode;
-};
-
-
-#if defined(CONFIG_DVB_HD29L2) || \
-	(defined(CONFIG_DVB_HD29L2_MODULE) && defined(MODULE))
-extern struct dvb_frontend *hd29l2_attach(const struct hd29l2_config *config,
-	struct i2c_adapter *i2c);
-#else
-static inline struct dvb_frontend *hd29l2_attach(
-const struct hd29l2_config *config, struct i2c_adapter *i2c)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif
-
-#endif /* HD29L2_H */
diff --git a/drivers/media/dvb/frontends/hd29l2_priv.h b/drivers/media/dvb/frontends/hd29l2_priv.h
deleted file mode 100644
index ba16dc3..0000000
--- a/drivers/media/dvb/frontends/hd29l2_priv.h
+++ /dev/null
@@ -1,314 +0,0 @@
-/*
- * HDIC HD29L2 DMB-TH demodulator driver
- *
- * Copyright (C) 2011 Metropolia University of Applied Sciences, Electria R&D
- *
- * Author: 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 HD29L2_PRIV
-#define HD29L2_PRIV
-
-#include <linux/dvb/version.h>
-#include "dvb_frontend.h"
-#include "dvb_math.h"
-#include "hd29l2.h"
-
-#define LOG_PREFIX "hd29l2"
-
-#undef dbg
-#define dbg(f, arg...) \
-	if (hd29l2_debug) \
-		printk(KERN_INFO   LOG_PREFIX": " f "\n" , ## arg)
-#undef err
-#define err(f, arg...)  printk(KERN_ERR     LOG_PREFIX": " f "\n" , ## arg)
-#undef info
-#define info(f, arg...) printk(KERN_INFO    LOG_PREFIX": " f "\n" , ## arg)
-#undef warn
-#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg)
-
-#define HD29L2_XTAL 30400000 /* Hz */
-
-
-#define HD29L2_QAM4NR 0x00
-#define HD29L2_QAM4   0x01
-#define HD29L2_QAM16  0x02
-#define HD29L2_QAM32  0x03
-#define HD29L2_QAM64  0x04
-
-#define HD29L2_CODE_RATE_04 0x00
-#define HD29L2_CODE_RATE_06 0x08
-#define HD29L2_CODE_RATE_08 0x10
-
-#define HD29L2_PN945 0x00
-#define HD29L2_PN595 0x01
-#define HD29L2_PN420 0x02
-
-#define HD29L2_CARRIER_SINGLE 0x00
-#define HD29L2_CARRIER_MULTI  0x01
-
-#define HD29L2_INTERLEAVER_720 0x00
-#define HD29L2_INTERLEAVER_420 0x01
-
-struct reg_val {
-	u8 reg;
-	u8 val;
-};
-
-struct reg_mod_vals {
-	u8 reg;
-	u8 val[5];
-};
-
-struct hd29l2_priv {
-	struct i2c_adapter *i2c;
-	struct dvb_frontend fe;
-	struct hd29l2_config cfg;
-	u8 tuner_i2c_addr_programmed:1;
-
-	fe_status_t fe_status;
-};
-
-static const struct reg_mod_vals reg_mod_vals_tab[] = {
-	/* REG, QAM4NR, QAM4,QAM16,QAM32,QAM64 */
-	{ 0x01, { 0x10, 0x10, 0x10, 0x10, 0x10 } },
-	{ 0x02, { 0x07, 0x07, 0x07, 0x07, 0x07 } },
-	{ 0x03, { 0x10, 0x10, 0x10, 0x10, 0x10 } },
-	{ 0x04, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
-	{ 0x05, { 0x61, 0x60, 0x60, 0x61, 0x60 } },
-	{ 0x06, { 0xff, 0xff, 0xff, 0xff, 0xff } },
-	{ 0x07, { 0xff, 0xff, 0xff, 0xff, 0xff } },
-	{ 0x08, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
-	{ 0x09, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
-	{ 0x0a, { 0x15, 0x15, 0x03, 0x03, 0x03 } },
-	{ 0x0d, { 0x78, 0x78, 0x88, 0x78, 0x78 } },
-	{ 0x0e, { 0xa0, 0x90, 0xa0, 0xa0, 0xa0 } },
-	{ 0x0f, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
-	{ 0x10, { 0xa0, 0xa0, 0x58, 0x38, 0x38 } },
-	{ 0x11, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
-	{ 0x12, { 0x5a, 0x5a, 0x5a, 0x5a, 0x5a } },
-	{ 0x13, { 0xa2, 0xa2, 0xa2, 0xa2, 0xa2 } },
-	{ 0x17, { 0x40, 0x40, 0x40, 0x40, 0x40 } },
-	{ 0x18, { 0x21, 0x21, 0x42, 0x52, 0x42 } },
-	{ 0x19, { 0x21, 0x21, 0x62, 0x72, 0x62 } },
-	{ 0x1a, { 0x32, 0x43, 0xa9, 0xb9, 0xa9 } },
-	{ 0x1b, { 0x32, 0x43, 0xb9, 0xd8, 0xb9 } },
-	{ 0x1c, { 0x02, 0x02, 0x03, 0x02, 0x03 } },
-	{ 0x1d, { 0x0c, 0x0c, 0x01, 0x02, 0x02 } },
-	{ 0x1e, { 0x02, 0x02, 0x02, 0x01, 0x02 } },
-	{ 0x1f, { 0x02, 0x02, 0x01, 0x02, 0x04 } },
-	{ 0x20, { 0x01, 0x02, 0x01, 0x01, 0x01 } },
-	{ 0x21, { 0x08, 0x08, 0x0a, 0x0a, 0x0a } },
-	{ 0x22, { 0x06, 0x06, 0x04, 0x05, 0x05 } },
-	{ 0x23, { 0x06, 0x06, 0x05, 0x03, 0x05 } },
-	{ 0x24, { 0x08, 0x08, 0x05, 0x07, 0x07 } },
-	{ 0x25, { 0x16, 0x10, 0x10, 0x0a, 0x10 } },
-	{ 0x26, { 0x14, 0x14, 0x04, 0x04, 0x04 } },
-	{ 0x27, { 0x58, 0x58, 0x58, 0x5c, 0x58 } },
-	{ 0x28, { 0x0a, 0x0a, 0x0a, 0x0a, 0x0a } },
-	{ 0x29, { 0x0a, 0x0a, 0x0a, 0x0a, 0x0a } },
-	{ 0x2a, { 0x08, 0x0a, 0x08, 0x08, 0x08 } },
-	{ 0x2b, { 0x08, 0x08, 0x08, 0x08, 0x08 } },
-	{ 0x2c, { 0x06, 0x06, 0x06, 0x06, 0x06 } },
-	{ 0x2d, { 0x05, 0x06, 0x06, 0x06, 0x06 } },
-	{ 0x2e, { 0x21, 0x21, 0x21, 0x21, 0x21 } },
-	{ 0x2f, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
-	{ 0x30, { 0x14, 0x14, 0x14, 0x14, 0x14 } },
-	{ 0x33, { 0xb7, 0xb7, 0xb7, 0xb7, 0xb7 } },
-	{ 0x34, { 0x81, 0x81, 0x81, 0x81, 0x81 } },
-	{ 0x35, { 0x80, 0x80, 0x80, 0x80, 0x80 } },
-	{ 0x37, { 0x70, 0x70, 0x70, 0x70, 0x70 } },
-	{ 0x38, { 0x04, 0x04, 0x02, 0x02, 0x02 } },
-	{ 0x39, { 0x07, 0x07, 0x05, 0x05, 0x05 } },
-	{ 0x3a, { 0x06, 0x06, 0x06, 0x06, 0x06 } },
-	{ 0x3b, { 0x03, 0x03, 0x03, 0x03, 0x03 } },
-	{ 0x3c, { 0x07, 0x06, 0x04, 0x04, 0x04 } },
-	{ 0x3d, { 0xf0, 0xf0, 0xf0, 0xf0, 0x80 } },
-	{ 0x3e, { 0x60, 0x60, 0x60, 0x60, 0xff } },
-	{ 0x3f, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
-	{ 0x40, { 0x5b, 0x5b, 0x5b, 0x57, 0x50 } },
-	{ 0x41, { 0x30, 0x30, 0x30, 0x30, 0x18 } },
-	{ 0x42, { 0x20, 0x20, 0x20, 0x00, 0x30 } },
-	{ 0x43, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
-	{ 0x44, { 0x3f, 0x3f, 0x3f, 0x3f, 0x3f } },
-	{ 0x45, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
-	{ 0x46, { 0x0a, 0x0a, 0x0a, 0x0a, 0x0a } },
-	{ 0x47, { 0x00, 0x00, 0x95, 0x00, 0x95 } },
-	{ 0x48, { 0xc0, 0xc0, 0xc0, 0xc0, 0xc0 } },
-	{ 0x49, { 0xc0, 0xc0, 0xc0, 0xc0, 0xc0 } },
-	{ 0x4a, { 0x40, 0x40, 0x33, 0x11, 0x11 } },
-	{ 0x4b, { 0x40, 0x40, 0x00, 0x00, 0x00 } },
-	{ 0x4c, { 0x40, 0x40, 0x99, 0x11, 0x11 } },
-	{ 0x4d, { 0x40, 0x40, 0x00, 0x00, 0x00 } },
-	{ 0x4e, { 0x40, 0x40, 0x66, 0x77, 0x77 } },
-	{ 0x4f, { 0x40, 0x40, 0x00, 0x00, 0x00 } },
-	{ 0x50, { 0x40, 0x40, 0x88, 0x33, 0x11 } },
-	{ 0x51, { 0x40, 0x40, 0x00, 0x00, 0x00 } },
-	{ 0x52, { 0x40, 0x40, 0x88, 0x02, 0x02 } },
-	{ 0x53, { 0x40, 0x40, 0x00, 0x02, 0x02 } },
-	{ 0x54, { 0x00, 0x00, 0x88, 0x33, 0x33 } },
-	{ 0x55, { 0x40, 0x40, 0x00, 0x00, 0x00 } },
-	{ 0x56, { 0x00, 0x00, 0x00, 0x0b, 0x00 } },
-	{ 0x57, { 0x40, 0x40, 0x0a, 0x0b, 0x0a } },
-	{ 0x58, { 0xaa, 0x00, 0x00, 0x00, 0x00 } },
-	{ 0x59, { 0x7a, 0x40, 0x02, 0x02, 0x02 } },
-	{ 0x5a, { 0x18, 0x18, 0x01, 0x01, 0x01 } },
-	{ 0x5b, { 0x18, 0x18, 0x01, 0x01, 0x01 } },
-	{ 0x5c, { 0x18, 0x18, 0x01, 0x01, 0x01 } },
-	{ 0x5d, { 0x18, 0x18, 0x01, 0x01, 0x01 } },
-	{ 0x5e, { 0xc0, 0xc0, 0xc0, 0xff, 0xc0 } },
-	{ 0x5f, { 0xc0, 0xc0, 0xc0, 0xff, 0xc0 } },
-	{ 0x60, { 0x40, 0x40, 0x00, 0x30, 0x30 } },
-	{ 0x61, { 0x40, 0x40, 0x10, 0x30, 0x30 } },
-	{ 0x62, { 0x40, 0x40, 0x00, 0x30, 0x30 } },
-	{ 0x63, { 0x40, 0x40, 0x05, 0x30, 0x30 } },
-	{ 0x64, { 0x40, 0x40, 0x06, 0x00, 0x30 } },
-	{ 0x65, { 0x40, 0x40, 0x06, 0x08, 0x30 } },
-	{ 0x66, { 0x40, 0x40, 0x00, 0x00, 0x20 } },
-	{ 0x67, { 0x40, 0x40, 0x01, 0x04, 0x20 } },
-	{ 0x68, { 0x00, 0x00, 0x30, 0x00, 0x20 } },
-	{ 0x69, { 0xa0, 0xa0, 0x00, 0x08, 0x20 } },
-	{ 0x6a, { 0x00, 0x00, 0x30, 0x00, 0x25 } },
-	{ 0x6b, { 0xa0, 0xa0, 0x00, 0x06, 0x25 } },
-	{ 0x6c, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
-	{ 0x6d, { 0xa0, 0x60, 0x0c, 0x03, 0x0c } },
-	{ 0x6e, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
-	{ 0x6f, { 0xa0, 0x60, 0x04, 0x01, 0x04 } },
-	{ 0x70, { 0x58, 0x58, 0xaa, 0xaa, 0xaa } },
-	{ 0x71, { 0x58, 0x58, 0xaa, 0xaa, 0xaa } },
-	{ 0x72, { 0x58, 0x58, 0xff, 0xff, 0xff } },
-	{ 0x73, { 0x58, 0x58, 0xff, 0xff, 0xff } },
-	{ 0x74, { 0x06, 0x06, 0x09, 0x05, 0x05 } },
-	{ 0x75, { 0x06, 0x06, 0x0a, 0x10, 0x10 } },
-	{ 0x76, { 0x10, 0x10, 0x06, 0x0a, 0x0a } },
-	{ 0x77, { 0x12, 0x18, 0x28, 0x10, 0x28 } },
-	{ 0x78, { 0xf8, 0xf8, 0xf8, 0xf8, 0xf8 } },
-	{ 0x79, { 0x15, 0x15, 0x03, 0x03, 0x03 } },
-	{ 0x7a, { 0x02, 0x02, 0x01, 0x04, 0x03 } },
-	{ 0x7b, { 0x01, 0x02, 0x03, 0x03, 0x03 } },
-	{ 0x7c, { 0x28, 0x28, 0x28, 0x28, 0x28 } },
-	{ 0x7f, { 0x25, 0x92, 0x5f, 0x17, 0x2d } },
-	{ 0x80, { 0x64, 0x64, 0x64, 0x74, 0x64 } },
-	{ 0x83, { 0x06, 0x03, 0x04, 0x04, 0x04 } },
-	{ 0x84, { 0xff, 0xff, 0xff, 0xff, 0xff } },
-	{ 0x85, { 0x05, 0x05, 0x05, 0x05, 0x05 } },
-	{ 0x86, { 0x00, 0x00, 0x11, 0x11, 0x11 } },
-	{ 0x87, { 0x03, 0x03, 0x03, 0x03, 0x03 } },
-	{ 0x88, { 0x09, 0x09, 0x09, 0x09, 0x09 } },
-	{ 0x89, { 0x20, 0x20, 0x30, 0x20, 0x20 } },
-	{ 0x8a, { 0x03, 0x03, 0x02, 0x03, 0x02 } },
-	{ 0x8b, { 0x00, 0x07, 0x09, 0x00, 0x09 } },
-	{ 0x8c, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
-	{ 0x8d, { 0x4f, 0x4f, 0x4f, 0x3f, 0x4f } },
-	{ 0x8e, { 0xf0, 0xf0, 0x60, 0xf0, 0xa0 } },
-	{ 0x8f, { 0xe8, 0xe8, 0xe8, 0xe8, 0xe8 } },
-	{ 0x90, { 0x10, 0x10, 0x10, 0x10, 0x10 } },
-	{ 0x91, { 0x40, 0x40, 0x70, 0x70, 0x10 } },
-	{ 0x92, { 0x00, 0x00, 0x00, 0x00, 0x04 } },
-	{ 0x93, { 0x60, 0x60, 0x60, 0x60, 0x60 } },
-	{ 0x94, { 0x00, 0x00, 0x00, 0x00, 0x03 } },
-	{ 0x95, { 0x09, 0x09, 0x47, 0x47, 0x47 } },
-	{ 0x96, { 0x80, 0xa0, 0xa0, 0x40, 0xa0 } },
-	{ 0x97, { 0x60, 0x60, 0x60, 0x60, 0x60 } },
-	{ 0x98, { 0x50, 0x50, 0x50, 0x30, 0x50 } },
-	{ 0x99, { 0x10, 0x10, 0x10, 0x10, 0x10 } },
-	{ 0x9a, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
-	{ 0x9b, { 0x40, 0x40, 0x40, 0x30, 0x40 } },
-	{ 0x9c, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
-	{ 0xa0, { 0xf0, 0xf0, 0xf0, 0xf0, 0xf0 } },
-	{ 0xa1, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
-	{ 0xa2, { 0x30, 0x30, 0x00, 0x30, 0x00 } },
-	{ 0xa3, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
-	{ 0xa4, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
-	{ 0xa5, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
-	{ 0xa6, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
-	{ 0xa7, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
-	{ 0xa8, { 0x77, 0x77, 0x77, 0x77, 0x77 } },
-	{ 0xa9, { 0x02, 0x02, 0x02, 0x02, 0x02 } },
-	{ 0xaa, { 0x40, 0x40, 0x40, 0x40, 0x40 } },
-	{ 0xac, { 0x1f, 0x1f, 0x1f, 0x1f, 0x1f } },
-	{ 0xad, { 0x14, 0x14, 0x14, 0x14, 0x14 } },
-	{ 0xae, { 0x78, 0x78, 0x78, 0x78, 0x78 } },
-	{ 0xaf, { 0x06, 0x06, 0x06, 0x06, 0x07 } },
-	{ 0xb0, { 0x1b, 0x1b, 0x1b, 0x19, 0x1b } },
-	{ 0xb1, { 0x18, 0x17, 0x17, 0x18, 0x17 } },
-	{ 0xb2, { 0x35, 0x82, 0x82, 0x38, 0x82 } },
-	{ 0xb3, { 0xb6, 0xce, 0xc7, 0x5c, 0xb0 } },
-	{ 0xb4, { 0x3f, 0x3e, 0x3e, 0x3f, 0x3e } },
-	{ 0xb5, { 0x70, 0x58, 0x50, 0x68, 0x50 } },
-	{ 0xb6, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
-	{ 0xb7, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
-	{ 0xb8, { 0x03, 0x03, 0x01, 0x01, 0x01 } },
-	{ 0xb9, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
-	{ 0xba, { 0x06, 0x06, 0x0a, 0x05, 0x0a } },
-	{ 0xbb, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
-	{ 0xbc, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
-	{ 0xbd, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
-	{ 0xbe, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
-	{ 0xbf, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
-	{ 0xc0, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
-	{ 0xc1, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
-	{ 0xc2, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
-	{ 0xc3, { 0x00, 0x00, 0x88, 0x66, 0x88 } },
-	{ 0xc4, { 0x10, 0x10, 0x00, 0x00, 0x00 } },
-	{ 0xc5, { 0x00, 0x00, 0x44, 0x60, 0x44 } },
-	{ 0xc6, { 0x10, 0x0a, 0x00, 0x00, 0x00 } },
-	{ 0xc7, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
-	{ 0xc8, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
-	{ 0xc9, { 0x90, 0x04, 0x00, 0x00, 0x00 } },
-	{ 0xca, { 0x90, 0x08, 0x01, 0x01, 0x01 } },
-	{ 0xcb, { 0xa0, 0x04, 0x00, 0x44, 0x00 } },
-	{ 0xcc, { 0xa0, 0x10, 0x03, 0x00, 0x03 } },
-	{ 0xcd, { 0x06, 0x06, 0x06, 0x05, 0x06 } },
-	{ 0xce, { 0x05, 0x05, 0x01, 0x01, 0x01 } },
-	{ 0xcf, { 0x40, 0x20, 0x18, 0x18, 0x18 } },
-	{ 0xd0, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
-	{ 0xd1, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
-	{ 0xd2, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
-	{ 0xd3, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
-	{ 0xd4, { 0x05, 0x05, 0x05, 0x05, 0x05 } },
-	{ 0xd5, { 0x05, 0x05, 0x05, 0x03, 0x05 } },
-	{ 0xd6, { 0xac, 0x22, 0xca, 0x8f, 0xca } },
-	{ 0xd7, { 0x20, 0x20, 0x20, 0x20, 0x20 } },
-	{ 0xd8, { 0x01, 0x01, 0x01, 0x01, 0x01 } },
-	{ 0xd9, { 0x00, 0x00, 0x0f, 0x00, 0x0f } },
-	{ 0xda, { 0x00, 0xff, 0xff, 0x0e, 0xff } },
-	{ 0xdb, { 0x0a, 0x0a, 0x0a, 0x0a, 0x0a } },
-	{ 0xdc, { 0x0a, 0x0a, 0x0a, 0x0a, 0x0a } },
-	{ 0xdd, { 0x05, 0x05, 0x05, 0x05, 0x05 } },
-	{ 0xde, { 0x0a, 0x0a, 0x0a, 0x0a, 0x0a } },
-	{ 0xdf, { 0x42, 0x42, 0x44, 0x44, 0x04 } },
-	{ 0xe0, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
-	{ 0xe1, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
-	{ 0xe2, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
-	{ 0xe3, { 0x00, 0x00, 0x26, 0x06, 0x26 } },
-	{ 0xe4, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
-	{ 0xe5, { 0x01, 0x0a, 0x01, 0x01, 0x01 } },
-	{ 0xe6, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
-	{ 0xe7, { 0x08, 0x08, 0x08, 0x08, 0x08 } },
-	{ 0xe8, { 0x63, 0x63, 0x63, 0x63, 0x63 } },
-	{ 0xe9, { 0x59, 0x59, 0x59, 0x59, 0x59 } },
-	{ 0xea, { 0x80, 0x80, 0x20, 0x80, 0x80 } },
-	{ 0xeb, { 0x37, 0x37, 0x78, 0x37, 0x77 } },
-	{ 0xec, { 0x1f, 0x1f, 0x25, 0x25, 0x25 } },
-	{ 0xed, { 0x0a, 0x0a, 0x0a, 0x0a, 0x0a } },
-	{ 0xee, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
-	{ 0xef, { 0x70, 0x70, 0x58, 0x38, 0x58 } },
-	{ 0xf0, { 0x00, 0x00, 0x00, 0x00, 0x00 } },
-};
-
-#endif /* HD29L2_PRIV */
diff --git a/drivers/media/dvb/frontends/isl6405.c b/drivers/media/dvb/frontends/isl6405.c
deleted file mode 100644
index 33d33f4..0000000
--- a/drivers/media/dvb/frontends/isl6405.c
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * isl6405.c - driver for dual lnb supply and control ic ISL6405
- *
- * Copyright (C) 2008 Hartmut Hackmann
- * Copyright (C) 2006 Oliver Endriss
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the 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.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- *
- *
- * the project's page is at http://www.linuxtv.org
- */
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-
-#include "dvb_frontend.h"
-#include "isl6405.h"
-
-struct isl6405 {
-	u8			config;
-	u8			override_or;
-	u8			override_and;
-	struct i2c_adapter	*i2c;
-	u8			i2c_addr;
-};
-
-static int isl6405_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
-{
-	struct isl6405 *isl6405 = (struct isl6405 *) fe->sec_priv;
-	struct i2c_msg msg = {	.addr = isl6405->i2c_addr, .flags = 0,
-				.buf = &isl6405->config,
-				.len = sizeof(isl6405->config) };
-
-	if (isl6405->override_or & 0x80) {
-		isl6405->config &= ~(ISL6405_VSEL2 | ISL6405_EN2);
-		switch (voltage) {
-		case SEC_VOLTAGE_OFF:
-			break;
-		case SEC_VOLTAGE_13:
-			isl6405->config |= ISL6405_EN2;
-			break;
-		case SEC_VOLTAGE_18:
-			isl6405->config |= (ISL6405_EN2 | ISL6405_VSEL2);
-			break;
-		default:
-			return -EINVAL;
-		}
-	} else {
-		isl6405->config &= ~(ISL6405_VSEL1 | ISL6405_EN1);
-		switch (voltage) {
-		case SEC_VOLTAGE_OFF:
-			break;
-		case SEC_VOLTAGE_13:
-			isl6405->config |= ISL6405_EN1;
-			break;
-		case SEC_VOLTAGE_18:
-			isl6405->config |= (ISL6405_EN1 | ISL6405_VSEL1);
-			break;
-		default:
-			return -EINVAL;
-		};
-	}
-	isl6405->config |= isl6405->override_or;
-	isl6405->config &= isl6405->override_and;
-
-	return (i2c_transfer(isl6405->i2c, &msg, 1) == 1) ? 0 : -EIO;
-}
-
-static int isl6405_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
-{
-	struct isl6405 *isl6405 = (struct isl6405 *) fe->sec_priv;
-	struct i2c_msg msg = {	.addr = isl6405->i2c_addr, .flags = 0,
-				.buf = &isl6405->config,
-				.len = sizeof(isl6405->config) };
-
-	if (isl6405->override_or & 0x80) {
-		if (arg)
-			isl6405->config |= ISL6405_LLC2;
-		else
-			isl6405->config &= ~ISL6405_LLC2;
-	} else {
-		if (arg)
-			isl6405->config |= ISL6405_LLC1;
-		else
-			isl6405->config &= ~ISL6405_LLC1;
-	}
-	isl6405->config |= isl6405->override_or;
-	isl6405->config &= isl6405->override_and;
-
-	return (i2c_transfer(isl6405->i2c, &msg, 1) == 1) ? 0 : -EIO;
-}
-
-static void isl6405_release(struct dvb_frontend *fe)
-{
-	/* power off */
-	isl6405_set_voltage(fe, SEC_VOLTAGE_OFF);
-
-	/* free */
-	kfree(fe->sec_priv);
-	fe->sec_priv = NULL;
-}
-
-struct dvb_frontend *isl6405_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c,
-				    u8 i2c_addr, u8 override_set, u8 override_clear)
-{
-	struct isl6405 *isl6405 = kmalloc(sizeof(struct isl6405), GFP_KERNEL);
-	if (!isl6405)
-		return NULL;
-
-	/* default configuration */
-	if (override_set & 0x80)
-		isl6405->config = ISL6405_ISEL2;
-	else
-		isl6405->config = ISL6405_ISEL1;
-	isl6405->i2c = i2c;
-	isl6405->i2c_addr = i2c_addr;
-	fe->sec_priv = isl6405;
-
-	/* bits which should be forced to '1' */
-	isl6405->override_or = override_set;
-
-	/* bits which should be forced to '0' */
-	isl6405->override_and = ~override_clear;
-
-	/* detect if it is present or not */
-	if (isl6405_set_voltage(fe, SEC_VOLTAGE_OFF)) {
-		kfree(isl6405);
-		fe->sec_priv = NULL;
-		return NULL;
-	}
-
-	/* install release callback */
-	fe->ops.release_sec = isl6405_release;
-
-	/* override frontend ops */
-	fe->ops.set_voltage = isl6405_set_voltage;
-	fe->ops.enable_high_lnb_voltage = isl6405_enable_high_lnb_voltage;
-
-	return fe;
-}
-EXPORT_SYMBOL(isl6405_attach);
-
-MODULE_DESCRIPTION("Driver for lnb supply and control ic isl6405");
-MODULE_AUTHOR("Hartmut Hackmann & Oliver Endriss");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/isl6405.h b/drivers/media/dvb/frontends/isl6405.h
deleted file mode 100644
index 1c793d3..0000000
--- a/drivers/media/dvb/frontends/isl6405.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * isl6405.h - driver for dual lnb supply and control ic ISL6405
- *
- * Copyright (C) 2008 Hartmut Hackmann
- * Copyright (C) 2006 Oliver Endriss
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the 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.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- *
- *
- * the project's page is at http://www.linuxtv.org
- */
-
-#ifndef _ISL6405_H
-#define _ISL6405_H
-
-#include <linux/dvb/frontend.h>
-
-/* system register bits */
-
-/* this bit selects register (control) 1 or 2
-   note that the bit maps are different */
-
-#define ISL6405_SR	0x80
-
-/* SR = 0 */
-#define ISL6405_OLF1	0x01
-#define ISL6405_EN1	0x02
-#define ISL6405_VSEL1	0x04
-#define ISL6405_LLC1	0x08
-#define ISL6405_ENT1	0x10
-#define ISL6405_ISEL1	0x20
-#define ISL6405_DCL	0x40
-
-/* SR = 1 */
-#define ISL6405_OLF2	0x01
-#define ISL6405_OTF	0x02
-#define ISL6405_EN2	0x04
-#define ISL6405_VSEL2	0x08
-#define ISL6405_LLC2	0x10
-#define ISL6405_ENT2	0x20
-#define ISL6405_ISEL2	0x40
-
-#if defined(CONFIG_DVB_ISL6405) || (defined(CONFIG_DVB_ISL6405_MODULE) && defined(MODULE))
-/* override_set and override_clear control which system register bits (above)
- * to always set & clear
- */
-extern struct dvb_frontend *isl6405_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c,
-					   u8 i2c_addr, u8 override_set, u8 override_clear);
-#else
-static inline struct dvb_frontend *isl6405_attach(struct dvb_frontend *fe,
-						  struct i2c_adapter *i2c, u8 i2c_addr,
-						  u8 override_set, u8 override_clear)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif /* CONFIG_DVB_ISL6405 */
-
-#endif
diff --git a/drivers/media/dvb/frontends/isl6421.c b/drivers/media/dvb/frontends/isl6421.c
deleted file mode 100644
index 684c8ec..0000000
--- a/drivers/media/dvb/frontends/isl6421.c
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * isl6421.h - driver for lnb supply and control ic ISL6421
- *
- * Copyright (C) 2006 Andrew de Quincey
- * Copyright (C) 2006 Oliver Endriss
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the 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.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- *
- *
- * the project's page is at http://www.linuxtv.org
- */
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-
-#include "dvb_frontend.h"
-#include "isl6421.h"
-
-struct isl6421 {
-	u8			config;
-	u8			override_or;
-	u8			override_and;
-	struct i2c_adapter	*i2c;
-	u8			i2c_addr;
-};
-
-static int isl6421_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
-{
-	struct isl6421 *isl6421 = (struct isl6421 *) fe->sec_priv;
-	struct i2c_msg msg = {	.addr = isl6421->i2c_addr, .flags = 0,
-				.buf = &isl6421->config,
-				.len = sizeof(isl6421->config) };
-
-	isl6421->config &= ~(ISL6421_VSEL1 | ISL6421_EN1);
-
-	switch(voltage) {
-	case SEC_VOLTAGE_OFF:
-		break;
-	case SEC_VOLTAGE_13:
-		isl6421->config |= ISL6421_EN1;
-		break;
-	case SEC_VOLTAGE_18:
-		isl6421->config |= (ISL6421_EN1 | ISL6421_VSEL1);
-		break;
-	default:
-		return -EINVAL;
-	};
-
-	isl6421->config |= isl6421->override_or;
-	isl6421->config &= isl6421->override_and;
-
-	return (i2c_transfer(isl6421->i2c, &msg, 1) == 1) ? 0 : -EIO;
-}
-
-static int isl6421_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
-{
-	struct isl6421 *isl6421 = (struct isl6421 *) fe->sec_priv;
-	struct i2c_msg msg = {	.addr = isl6421->i2c_addr, .flags = 0,
-				.buf = &isl6421->config,
-				.len = sizeof(isl6421->config) };
-
-	if (arg)
-		isl6421->config |= ISL6421_LLC1;
-	else
-		isl6421->config &= ~ISL6421_LLC1;
-
-	isl6421->config |= isl6421->override_or;
-	isl6421->config &= isl6421->override_and;
-
-	return (i2c_transfer(isl6421->i2c, &msg, 1) == 1) ? 0 : -EIO;
-}
-
-static void isl6421_release(struct dvb_frontend *fe)
-{
-	/* power off */
-	isl6421_set_voltage(fe, SEC_VOLTAGE_OFF);
-
-	/* free */
-	kfree(fe->sec_priv);
-	fe->sec_priv = NULL;
-}
-
-struct dvb_frontend *isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr,
-		   u8 override_set, u8 override_clear)
-{
-	struct isl6421 *isl6421 = kmalloc(sizeof(struct isl6421), GFP_KERNEL);
-	if (!isl6421)
-		return NULL;
-
-	/* default configuration */
-	isl6421->config = ISL6421_ISEL1;
-	isl6421->i2c = i2c;
-	isl6421->i2c_addr = i2c_addr;
-	fe->sec_priv = isl6421;
-
-	/* bits which should be forced to '1' */
-	isl6421->override_or = override_set;
-
-	/* bits which should be forced to '0' */
-	isl6421->override_and = ~override_clear;
-
-	/* detect if it is present or not */
-	if (isl6421_set_voltage(fe, SEC_VOLTAGE_OFF)) {
-		kfree(isl6421);
-		fe->sec_priv = NULL;
-		return NULL;
-	}
-
-	/* install release callback */
-	fe->ops.release_sec = isl6421_release;
-
-	/* override frontend ops */
-	fe->ops.set_voltage = isl6421_set_voltage;
-	fe->ops.enable_high_lnb_voltage = isl6421_enable_high_lnb_voltage;
-
-	return fe;
-}
-EXPORT_SYMBOL(isl6421_attach);
-
-MODULE_DESCRIPTION("Driver for lnb supply and control ic isl6421");
-MODULE_AUTHOR("Andrew de Quincey & Oliver Endriss");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/isl6421.h b/drivers/media/dvb/frontends/isl6421.h
deleted file mode 100644
index 47e4518..0000000
--- a/drivers/media/dvb/frontends/isl6421.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * isl6421.h - driver for lnb supply and control ic ISL6421
- *
- * Copyright (C) 2006 Andrew de Quincey
- * Copyright (C) 2006 Oliver Endriss
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the 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.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- *
- *
- * the project's page is at http://www.linuxtv.org
- */
-
-#ifndef _ISL6421_H
-#define _ISL6421_H
-
-#include <linux/dvb/frontend.h>
-
-/* system register bits */
-#define ISL6421_OLF1	0x01
-#define ISL6421_EN1	0x02
-#define ISL6421_VSEL1	0x04
-#define ISL6421_LLC1	0x08
-#define ISL6421_ENT1	0x10
-#define ISL6421_ISEL1	0x20
-#define ISL6421_DCL	0x40
-
-#if defined(CONFIG_DVB_ISL6421) || (defined(CONFIG_DVB_ISL6421_MODULE) && defined(MODULE))
-/* override_set and override_clear control which system register bits (above) to always set & clear */
-extern struct dvb_frontend *isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr,
-			  u8 override_set, u8 override_clear);
-#else
-static inline struct dvb_frontend *isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr,
-						  u8 override_set, u8 override_clear)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif // CONFIG_DVB_ISL6421
-
-#endif
diff --git a/drivers/media/dvb/frontends/isl6423.c b/drivers/media/dvb/frontends/isl6423.c
deleted file mode 100644
index dca5beb..0000000
--- a/drivers/media/dvb/frontends/isl6423.c
+++ /dev/null
@@ -1,308 +0,0 @@
-/*
-	Intersil ISL6423 SEC and LNB Power supply controller
-
-	Copyright (C) Manu Abraham <abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-
-#include "dvb_frontend.h"
-#include "isl6423.h"
-
-static unsigned int verbose;
-module_param(verbose, int, 0644);
-MODULE_PARM_DESC(verbose, "Set Verbosity level");
-
-#define FE_ERROR				0
-#define FE_NOTICE				1
-#define FE_INFO					2
-#define FE_DEBUG				3
-#define FE_DEBUGREG				4
-
-#define dprintk(__y, __z, format, arg...) do {						\
-	if (__z) {									\
-		if	((verbose > FE_ERROR) && (verbose > __y))			\
-			printk(KERN_ERR "%s: " format "\n", __func__ , ##arg);		\
-		else if	((verbose > FE_NOTICE) && (verbose > __y))			\
-			printk(KERN_NOTICE "%s: " format "\n", __func__ , ##arg);	\
-		else if ((verbose > FE_INFO) && (verbose > __y))			\
-			printk(KERN_INFO "%s: " format "\n", __func__ , ##arg);		\
-		else if ((verbose > FE_DEBUG) && (verbose > __y))			\
-			printk(KERN_DEBUG "%s: " format "\n", __func__ , ##arg);	\
-	} else {									\
-		if (verbose > __y)							\
-			printk(format, ##arg);						\
-	}										\
-} while (0)
-
-struct isl6423_dev {
-	const struct isl6423_config	*config;
-	struct i2c_adapter		*i2c;
-
-	u8 reg_3;
-	u8 reg_4;
-
-	unsigned int verbose;
-};
-
-static int isl6423_write(struct isl6423_dev *isl6423, u8 reg)
-{
-	struct i2c_adapter *i2c = isl6423->i2c;
-	u8 addr			= isl6423->config->addr;
-	int err = 0;
-
-	struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = &reg, .len = 1 };
-
-	dprintk(FE_DEBUG, 1, "write reg %02X", reg);
-	err = i2c_transfer(i2c, &msg, 1);
-	if (err < 0)
-		goto exit;
-	return 0;
-
-exit:
-	dprintk(FE_ERROR, 1, "I/O error <%d>", err);
-	return err;
-}
-
-static int isl6423_set_modulation(struct dvb_frontend *fe)
-{
-	struct isl6423_dev *isl6423		= (struct isl6423_dev *) fe->sec_priv;
-	const struct isl6423_config *config	= isl6423->config;
-	int err = 0;
-	u8 reg_2 = 0;
-
-	reg_2 = 0x01 << 5;
-
-	if (config->mod_extern)
-		reg_2 |= (1 << 3);
-	else
-		reg_2 |= (1 << 4);
-
-	err = isl6423_write(isl6423, reg_2);
-	if (err < 0)
-		goto exit;
-	return 0;
-
-exit:
-	dprintk(FE_ERROR, 1, "I/O error <%d>", err);
-	return err;
-}
-
-static int isl6423_voltage_boost(struct dvb_frontend *fe, long arg)
-{
-	struct isl6423_dev *isl6423 = (struct isl6423_dev *) fe->sec_priv;
-	u8 reg_3 = isl6423->reg_3;
-	u8 reg_4 = isl6423->reg_4;
-	int err = 0;
-
-	if (arg) {
-		/* EN = 1, VSPEN = 1, VBOT = 1 */
-		reg_4 |= (1 << 4);
-		reg_4 |= 0x1;
-		reg_3 |= (1 << 3);
-	} else {
-		/* EN = 1, VSPEN = 1, VBOT = 0 */
-		reg_4 |= (1 << 4);
-		reg_4 &= ~0x1;
-		reg_3 |= (1 << 3);
-	}
-	err = isl6423_write(isl6423, reg_3);
-	if (err < 0)
-		goto exit;
-
-	err = isl6423_write(isl6423, reg_4);
-	if (err < 0)
-		goto exit;
-
-	isl6423->reg_3 = reg_3;
-	isl6423->reg_4 = reg_4;
-
-	return 0;
-exit:
-	dprintk(FE_ERROR, 1, "I/O error <%d>", err);
-	return err;
-}
-
-
-static int isl6423_set_voltage(struct dvb_frontend *fe,
-			       enum fe_sec_voltage voltage)
-{
-	struct isl6423_dev *isl6423 = (struct isl6423_dev *) fe->sec_priv;
-	u8 reg_3 = isl6423->reg_3;
-	u8 reg_4 = isl6423->reg_4;
-	int err = 0;
-
-	switch (voltage) {
-	case SEC_VOLTAGE_OFF:
-		/* EN = 0 */
-		reg_4 &= ~(1 << 4);
-		break;
-
-	case SEC_VOLTAGE_13:
-		/* EN = 1, VSPEN = 1, VTOP = 0, VBOT = 0 */
-		reg_4 |= (1 << 4);
-		reg_4 &= ~0x3;
-		reg_3 |= (1 << 3);
-		break;
-
-	case SEC_VOLTAGE_18:
-		/* EN = 1, VSPEN = 1, VTOP = 1, VBOT = 0 */
-		reg_4 |= (1 << 4);
-		reg_4 |=  0x2;
-		reg_4 &= ~0x1;
-		reg_3 |= (1 << 3);
-		break;
-
-	default:
-		break;
-	}
-	err = isl6423_write(isl6423, reg_3);
-	if (err < 0)
-		goto exit;
-
-	err = isl6423_write(isl6423, reg_4);
-	if (err < 0)
-		goto exit;
-
-	isl6423->reg_3 = reg_3;
-	isl6423->reg_4 = reg_4;
-
-	return 0;
-exit:
-	dprintk(FE_ERROR, 1, "I/O error <%d>", err);
-	return err;
-}
-
-static int isl6423_set_current(struct dvb_frontend *fe)
-{
-	struct isl6423_dev *isl6423		= (struct isl6423_dev *) fe->sec_priv;
-	u8 reg_3 = isl6423->reg_3;
-	const struct isl6423_config *config	= isl6423->config;
-	int err = 0;
-
-	switch (config->current_max) {
-	case SEC_CURRENT_275m:
-		/* 275mA */
-		/* ISELH = 0, ISELL = 0 */
-		reg_3 &= ~0x3;
-		break;
-
-	case SEC_CURRENT_515m:
-		/* 515mA */
-		/* ISELH = 0, ISELL = 1 */
-		reg_3 &= ~0x2;
-		reg_3 |=  0x1;
-		break;
-
-	case SEC_CURRENT_635m:
-		/* 635mA */
-		/* ISELH = 1, ISELL = 0 */
-		reg_3 &= ~0x1;
-		reg_3 |=  0x2;
-		break;
-
-	case SEC_CURRENT_800m:
-		/* 800mA */
-		/* ISELH = 1, ISELL = 1 */
-		reg_3 |= 0x3;
-		break;
-	}
-
-	err = isl6423_write(isl6423, reg_3);
-	if (err < 0)
-		goto exit;
-
-	switch (config->curlim) {
-	case SEC_CURRENT_LIM_ON:
-		/* DCL = 0 */
-		reg_3 &= ~0x10;
-		break;
-
-	case SEC_CURRENT_LIM_OFF:
-		/* DCL = 1 */
-		reg_3 |= 0x10;
-		break;
-	}
-
-	err = isl6423_write(isl6423, reg_3);
-	if (err < 0)
-		goto exit;
-
-	isl6423->reg_3 = reg_3;
-
-	return 0;
-exit:
-	dprintk(FE_ERROR, 1, "I/O error <%d>", err);
-	return err;
-}
-
-static void isl6423_release(struct dvb_frontend *fe)
-{
-	isl6423_set_voltage(fe, SEC_VOLTAGE_OFF);
-
-	kfree(fe->sec_priv);
-	fe->sec_priv = NULL;
-}
-
-struct dvb_frontend *isl6423_attach(struct dvb_frontend *fe,
-				    struct i2c_adapter *i2c,
-				    const struct isl6423_config *config)
-{
-	struct isl6423_dev *isl6423;
-
-	isl6423 = kzalloc(sizeof(struct isl6423_dev), GFP_KERNEL);
-	if (!isl6423)
-		return NULL;
-
-	isl6423->config	= config;
-	isl6423->i2c	= i2c;
-	fe->sec_priv	= isl6423;
-
-	/* SR3H = 0, SR3M = 1, SR3L = 0 */
-	isl6423->reg_3 = 0x02 << 5;
-	/* SR4H = 0, SR4M = 1, SR4L = 1 */
-	isl6423->reg_4 = 0x03 << 5;
-
-	if (isl6423_set_current(fe))
-		goto exit;
-
-	if (isl6423_set_modulation(fe))
-		goto exit;
-
-	fe->ops.release_sec		= isl6423_release;
-	fe->ops.set_voltage		= isl6423_set_voltage;
-	fe->ops.enable_high_lnb_voltage = isl6423_voltage_boost;
-	isl6423->verbose		= verbose;
-
-	return fe;
-
-exit:
-	kfree(isl6423);
-	fe->sec_priv = NULL;
-	return NULL;
-}
-EXPORT_SYMBOL(isl6423_attach);
-
-MODULE_DESCRIPTION("ISL6423 SEC");
-MODULE_AUTHOR("Manu Abraham");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/isl6423.h b/drivers/media/dvb/frontends/isl6423.h
deleted file mode 100644
index e1a37fb..0000000
--- a/drivers/media/dvb/frontends/isl6423.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
-	Intersil ISL6423 SEC and LNB Power supply controller
-
-	Copyright (C) Manu Abraham <abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#ifndef __ISL_6423_H
-#define __ISL_6423_H
-
-#include <linux/dvb/frontend.h>
-
-enum isl6423_current {
-	SEC_CURRENT_275m = 0,
-	SEC_CURRENT_515m,
-	SEC_CURRENT_635m,
-	SEC_CURRENT_800m,
-};
-
-enum isl6423_curlim {
-	SEC_CURRENT_LIM_ON = 1,
-	SEC_CURRENT_LIM_OFF
-};
-
-struct isl6423_config {
-	enum isl6423_current current_max;
-	enum isl6423_curlim curlim;
-	u8 addr;
-	u8 mod_extern;
-};
-
-#if defined(CONFIG_DVB_ISL6423) || (defined(CONFIG_DVB_ISL6423_MODULE) && defined(MODULE))
-
-
-extern struct dvb_frontend *isl6423_attach(struct dvb_frontend *fe,
-					   struct i2c_adapter *i2c,
-					   const struct isl6423_config *config);
-
-#else
-static inline struct dvb_frontend *isl6423_attach(struct dvb_frontend *fe,
-						  struct i2c_adapter *i2c,
-						  const struct isl6423_config *config)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-
-#endif /* CONFIG_DVB_ISL6423 */
-
-#endif /* __ISL_6423_H */
diff --git a/drivers/media/dvb/frontends/it913x-fe-priv.h b/drivers/media/dvb/frontends/it913x-fe-priv.h
deleted file mode 100644
index eb6fd8a..0000000
--- a/drivers/media/dvb/frontends/it913x-fe-priv.h
+++ /dev/null
@@ -1,1051 +0,0 @@
-
-struct it913xset {	u32 pro;
-			u32 address;
-			u8 reg[15];
-			u8 count;
-};
-
-struct adctable {	u32 adcFrequency;
-			u32 bandwidth;
-			u32 coeff_1_2048;
-			u32 coeff_1_4096;
-			u32 coeff_1_8191;
-			u32 coeff_1_8192;
-			u32 coeff_1_8193;
-			u32 coeff_2_2k;
-			u32 coeff_2_4k;
-			u32 coeff_2_8k;
-			u16 bfsfcw_fftinx_ratio;
-			u16 fftinx_bfsfcw_ratio;
-};
-
-/* clock and coeff tables only table 3 is used with IT9137*/
-/* TODO other tables relate AF9035 may be removed */
-static struct adctable tab1[] = {
-	{	20156250, 6000000,
-		0x02b8ba6e, 0x015c5d37, 0x00ae340d, 0x00ae2e9b, 0x00ae292a,
-		0x015c5d37, 0x00ae2e9b, 0x0057174e, 0x02f1, 0x015c	},
-	{	20156250, 7000000,
-		0x032cd980, 0x01966cc0, 0x00cb3cba, 0x00cb3660, 0x00cb3007,
-		0x01966cc0, 0x00cb3660, 0x00659b30, 0x0285, 0x0196	},
-	{	20156250, 8000000,
-		0x03a0f893, 0x01d07c49, 0x00e84567, 0x00e83e25, 0x00e836e3,
-		0x01d07c49, 0x00e83e25, 0x00741f12, 0x0234, 0x01d0	},
-	{	20156250, 5000000,
-		0x02449b5c, 0x01224dae, 0x00912b60, 0x009126d7, 0x0091224e,
-		0x01224dae, 0x009126d7, 0x0048936b, 0x0387, 0x0122	}
-};
-
-static struct adctable tab2[] = {
-	{	20187500, 6000000,
-		0x02b7a654, 0x015bd32a, 0x00adef04, 0x00ade995, 0x00ade426,
-		0x015bd32a, 0x00ade995, 0x0056f4ca, 0x02f2, 0x015c	},
-	{	20187500, 7000000,
-		0x032b9761, 0x0195cbb1, 0x00caec30, 0x00cae5d8, 0x00cadf81,
-		0x0195cbb1, 0x00cae5d8, 0x006572ec, 0x0286, 0x0196	},
-	{	20187500, 8000000,
-		0x039f886f, 0x01cfc438, 0x00e7e95b, 0x00e7e21c, 0x00e7dadd,
-		0x01cfc438, 0x00e7e21c, 0x0073f10e, 0x0235, 0x01d0	},
-	{	20187500, 5000000,
-		0x0243b546, 0x0121daa3, 0x0090f1d9, 0x0090ed51, 0x0090e8ca,
-		0x0121daa3, 0x0090ed51, 0x004876a9, 0x0388, 0x0122	}
-
-};
-
-static struct adctable tab3[] = {
-	{	20250000, 6000000,
-		0x02b580ad, 0x015ac057, 0x00ad6597, 0x00ad602b, 0x00ad5ac1,
-		0x015ac057, 0x00ad602b, 0x0056b016, 0x02f4, 0x015b	},
-	{	20250000, 7000000,
-		0x03291620, 0x01948b10, 0x00ca4bda, 0x00ca4588, 0x00ca3f36,
-		0x01948b10, 0x00ca4588, 0x006522c4, 0x0288, 0x0195	},
-	{	20250000, 8000000,
-		0x039cab92, 0x01ce55c9, 0x00e7321e, 0x00e72ae4, 0x00e723ab,
-		0x01ce55c9, 0x00e72ae4, 0x00739572, 0x0237, 0x01ce	},
-	{	20250000, 5000000,
-		0x0241eb3b, 0x0120f59e, 0x00907f53, 0x00907acf, 0x0090764b,
-		0x0120f59e, 0x00907acf, 0x00483d67, 0x038b, 0x0121	}
-
-};
-
-static struct adctable tab4[] = {
-	{	20583333, 6000000,
-		0x02aa4598, 0x015522cc, 0x00aa96bb, 0x00aa9166, 0x00aa8c12,
-		0x015522cc, 0x00aa9166, 0x005548b3, 0x0300, 0x0155	},
-	{	20583333, 7000000,
-		0x031bfbdc, 0x018dfdee, 0x00c7052f, 0x00c6fef7, 0x00c6f8bf,
-		0x018dfdee, 0x00c6fef7, 0x00637f7b, 0x0293, 0x018e	},
-	{	20583333, 8000000,
-		0x038db21f, 0x01c6d910, 0x00e373a3, 0x00e36c88, 0x00e3656d,
-		0x01c6d910, 0x00e36c88, 0x0071b644, 0x0240, 0x01c7	},
-	{	20583333, 5000000,
-		0x02388f54, 0x011c47aa, 0x008e2846, 0x008e23d5, 0x008e1f64,
-		0x011c47aa, 0x008e23d5, 0x004711ea, 0x039a, 0x011c	}
-
-};
-
-static struct adctable tab5[] = {
-	{	20416667, 6000000,
-		0x02afd765, 0x0157ebb3, 0x00abfb39, 0x00abf5d9, 0x00abf07a,
-		0x0157ebb3, 0x00abf5d9, 0x0055faed, 0x02fa, 0x0158	},
-	{	20416667, 7000000,
-		0x03227b4b, 0x01913da6, 0x00c8a518, 0x00c89ed3, 0x00c8988e,
-		0x01913da6, 0x00c89ed3, 0x00644f69, 0x028d, 0x0191	},
-	{	20416667, 8000000,
-		0x03951f32, 0x01ca8f99, 0x00e54ef7, 0x00e547cc, 0x00e540a2,
-		0x01ca8f99, 0x00e547cc, 0x0072a3e6, 0x023c, 0x01cb	},
-	{	20416667, 5000000,
-		0x023d337f, 0x011e99c0, 0x008f515a, 0x008f4ce0, 0x008f4865,
-		0x011e99c0, 0x008f4ce0, 0x0047a670, 0x0393, 0x011f	}
-
-};
-
-static struct adctable tab6[] = {
-	{	20480000, 6000000,
-		0x02adb6db, 0x0156db6e, 0x00ab7312, 0x00ab6db7, 0x00ab685c,
-		0x0156db6e, 0x00ab6db7, 0x0055b6db, 0x02fd, 0x0157	},
-	{	20480000, 7000000,
-		0x03200000, 0x01900000, 0x00c80640, 0x00c80000, 0x00c7f9c0,
-		0x01900000, 0x00c80000, 0x00640000, 0x028f, 0x0190	},
-	{	20480000, 8000000,
-		0x03924925, 0x01c92492, 0x00e4996e, 0x00e49249, 0x00e48b25,
-		0x01c92492, 0x00e49249, 0x00724925, 0x023d, 0x01c9	},
-	{	20480000, 5000000,
-		0x023b6db7, 0x011db6db, 0x008edfe5, 0x008edb6e, 0x008ed6f7,
-		0x011db6db, 0x008edb6e, 0x00476db7, 0x0396, 0x011e	}
-};
-
-static struct adctable tab7[] = {
-	{	20500000, 6000000,
-		0x02ad0b99, 0x015685cc, 0x00ab4840, 0x00ab42e6, 0x00ab3d8c,
-		0x015685cc, 0x00ab42e6, 0x0055a173, 0x02fd, 0x0157	},
-	{	20500000, 7000000,
-		0x031f3832, 0x018f9c19, 0x00c7d44b, 0x00c7ce0c, 0x00c7c7ce,
-		0x018f9c19, 0x00c7ce0c, 0x0063e706, 0x0290, 0x0190	},
-	{	20500000, 8000000,
-		0x039164cb, 0x01c8b266, 0x00e46056, 0x00e45933, 0x00e45210,
-		0x01c8b266, 0x00e45933, 0x00722c99, 0x023e, 0x01c9	},
-	{	20500000, 5000000,
-		0x023adeff, 0x011d6f80, 0x008ebc36, 0x008eb7c0, 0x008eb34a,
-		0x011d6f80, 0x008eb7c0, 0x00475be0, 0x0396, 0x011d	}
-
-};
-
-static struct adctable tab8[] = {
-	{	20625000, 6000000,
-		0x02a8e4bd, 0x0154725e, 0x00aa3e81, 0x00aa392f, 0x00aa33de,
-		0x0154725e, 0x00aa392f, 0x00551c98, 0x0302, 0x0154	},
-	{	20625000, 7000000,
-		0x031a6032, 0x018d3019, 0x00c69e41, 0x00c6980c, 0x00c691d8,
-		0x018d3019, 0x00c6980c, 0x00634c06, 0x0294, 0x018d	},
-	{	20625000, 8000000,
-		0x038bdba6, 0x01c5edd3, 0x00e2fe02, 0x00e2f6ea, 0x00e2efd2,
-		0x01c5edd3, 0x00e2f6ea, 0x00717b75, 0x0242, 0x01c6	},
-	{	20625000, 5000000,
-		0x02376948, 0x011bb4a4, 0x008ddec1, 0x008dda52, 0x008dd5e3,
-		0x011bb4a4, 0x008dda52, 0x0046ed29, 0x039c, 0x011c	}
-
-};
-
-struct table {
-		u32 xtal;
-		struct adctable *table;
-};
-
-static struct table fe_clockTable[] = {
-		{12000000, tab3},	/* 12.00MHz */
-		{20480000, tab6},	/* 20.48MHz */
-		{36000000, tab3},	/* 36.00MHz */
-		{30000000, tab1},	/* 30.00MHz */
-		{26000000, tab4},	/* 26.00MHz */
-		{28000000, tab5},	/* 28.00MHz */
-		{32000000, tab7},	/* 32.00MHz */
-		{34000000, tab2},	/* 34.00MHz */
-		{24000000, tab1},	/* 24.00MHz */
-		{22000000, tab8},	/* 22.00MHz */
-};
-
-/* fe get */
-fe_code_rate_t fe_code[] = {
-	FEC_1_2,
-	FEC_2_3,
-	FEC_3_4,
-	FEC_5_6,
-	FEC_7_8,
-	FEC_NONE,
-};
-
-fe_guard_interval_t fe_gi[] = {
-	GUARD_INTERVAL_1_32,
-	GUARD_INTERVAL_1_16,
-	GUARD_INTERVAL_1_8,
-	GUARD_INTERVAL_1_4,
-};
-
-fe_hierarchy_t fe_hi[] = {
-	HIERARCHY_NONE,
-	HIERARCHY_1,
-	HIERARCHY_2,
-	HIERARCHY_4,
-};
-
-fe_transmit_mode_t fe_mode[] = {
-	TRANSMISSION_MODE_2K,
-	TRANSMISSION_MODE_8K,
-	TRANSMISSION_MODE_4K,
-};
-
-fe_modulation_t fe_con[] = {
-	QPSK,
-	QAM_16,
-	QAM_64,
-};
-
-enum {
-	PRIORITY_HIGH = 0,	/* High-priority stream */
-	PRIORITY_LOW,	/* Low-priority stream */
-};
-
-/* Standard demodulator functions */
-static struct it913xset set_solo_fe[] = {
-	{PRO_LINK, GPIOH5_EN, {0x01}, 0x01},
-	{PRO_LINK, GPIOH5_ON, {0x01}, 0x01},
-	{PRO_LINK, GPIOH5_O, {0x00}, 0x01},
-	{PRO_LINK, GPIOH5_O, {0x01}, 0x01},
-	{PRO_LINK, DVBT_INTEN, {0x04}, 0x01},
-	{PRO_LINK, DVBT_ENABLE, {0x05}, 0x01},
-	{PRO_DMOD, MP2IF_MPEG_PAR_MODE, {0x00}, 0x01},
-	{PRO_LINK, HOSTB_MPEG_SER_MODE, {0x00}, 0x01},
-	{PRO_LINK, HOSTB_MPEG_PAR_MODE, {0x00}, 0x01},
-	{PRO_DMOD, DCA_UPPER_CHIP, {0x00}, 0x01},
-	{PRO_LINK, HOSTB_DCA_UPPER, {0x00}, 0x01},
-	{PRO_DMOD, DCA_LOWER_CHIP, {0x00}, 0x01},
-	{PRO_LINK, HOSTB_DCA_LOWER, {0x00}, 0x01},
-	{PRO_DMOD, DCA_PLATCH, {0x00}, 0x01},
-	{PRO_DMOD, DCA_FPGA_LATCH, {0x00}, 0x01},
-	{PRO_DMOD, DCA_STAND_ALONE, {0x01}, 0x01},
-	{PRO_DMOD, DCA_ENABLE, {0x00}, 0x01},
-	{PRO_DMOD, MP2IF_MPEG_PAR_MODE, {0x00}, 0x01},
-	{PRO_DMOD, BFS_FCW, {0x00, 0x00, 0x00}, 0x03},
-	{0xff, 0x0000, {0x00}, 0x00}, /* Terminating Entry */
-};
-
-
-static struct it913xset init_1[] = {
-	{PRO_LINK, LOCK3_OUT, {0x01}, 0x01},
-	{PRO_LINK, PADMISCDRSR, {0x01}, 0x01},
-	{PRO_LINK, PADMISCDR2, {0x00}, 0x01},
-	{PRO_DMOD, 0xec57, {0x00, 0x00}, 0x02},
-	{PRO_LINK, PADMISCDR4, {0x00}, 0x01}, /* Power up */
-	{PRO_LINK, PADMISCDR8, {0x00}, 0x01},
-	{0xff, 0x0000, {0x00}, 0x00} /* Terminating Entry */
-};
-
-
-/* Version 1 types */
-static struct it913xset it9135_v1[] = {
-	{PRO_DMOD, 0x0051, {0x01}, 0x01},
-	{PRO_DMOD, 0x0070, {0x0a}, 0x01},
-	{PRO_DMOD, 0x007e, {0x04}, 0x01},
-	{PRO_DMOD, 0x0081, {0x0a}, 0x01},
-	{PRO_DMOD, 0x008a, {0x01}, 0x01},
-	{PRO_DMOD, 0x008e, {0x01}, 0x01},
-	{PRO_DMOD, 0x0092, {0x06}, 0x01},
-	{PRO_DMOD, 0x0099, {0x01}, 0x01},
-	{PRO_DMOD, 0x009f, {0xe1}, 0x01},
-	{PRO_DMOD, 0x00a0, {0xcf}, 0x01},
-	{PRO_DMOD, 0x00a3, {0x01}, 0x01},
-	{PRO_DMOD, 0x00a5, {0x01}, 0x01},
-	{PRO_DMOD, 0x00a6, {0x01}, 0x01},
-	{PRO_DMOD, 0x00a9, {0x00}, 0x01},
-	{PRO_DMOD, 0x00aa, {0x01}, 0x01},
-	{PRO_DMOD, 0x00b0, {0x01}, 0x01},
-	{PRO_DMOD, 0x00c2, {0x05}, 0x01},
-	{PRO_DMOD, 0x00c6, {0x19}, 0x01},
-	{PRO_DMOD, 0xf000, {0x0f}, 0x01},
-	{PRO_DMOD, 0xf016, {0x10}, 0x01},
-	{PRO_DMOD, 0xf017, {0x04}, 0x01},
-	{PRO_DMOD, 0xf018, {0x05}, 0x01},
-	{PRO_DMOD, 0xf019, {0x04}, 0x01},
-	{PRO_DMOD, 0xf01a, {0x05}, 0x01},
-	{PRO_DMOD, 0xf021, {0x03}, 0x01},
-	{PRO_DMOD, 0xf022, {0x0a}, 0x01},
-	{PRO_DMOD, 0xf023, {0x0a}, 0x01},
-	{PRO_DMOD, 0xf02b, {0x00}, 0x01},
-	{PRO_DMOD, 0xf02c, {0x01}, 0x01},
-	{PRO_DMOD, 0xf064, {0x03}, 0x01},
-	{PRO_DMOD, 0xf065, {0xf9}, 0x01},
-	{PRO_DMOD, 0xf066, {0x03}, 0x01},
-	{PRO_DMOD, 0xf067, {0x01}, 0x01},
-	{PRO_DMOD, 0xf06f, {0xe0}, 0x01},
-	{PRO_DMOD, 0xf070, {0x03}, 0x01},
-	{PRO_DMOD, 0xf072, {0x0f}, 0x01},
-	{PRO_DMOD, 0xf073, {0x03}, 0x01},
-	{PRO_DMOD, 0xf078, {0x00}, 0x01},
-	{PRO_DMOD, 0xf087, {0x00}, 0x01},
-	{PRO_DMOD, 0xf09b, {0x3f}, 0x01},
-	{PRO_DMOD, 0xf09c, {0x00}, 0x01},
-	{PRO_DMOD, 0xf09d, {0x20}, 0x01},
-	{PRO_DMOD, 0xf09e, {0x00}, 0x01},
-	{PRO_DMOD, 0xf09f, {0x0c}, 0x01},
-	{PRO_DMOD, 0xf0a0, {0x00}, 0x01},
-	{PRO_DMOD, 0xf130, {0x04}, 0x01},
-	{PRO_DMOD, 0xf132, {0x04}, 0x01},
-	{PRO_DMOD, 0xf144, {0x1a}, 0x01},
-	{PRO_DMOD, 0xf146, {0x00}, 0x01},
-	{PRO_DMOD, 0xf14a, {0x01}, 0x01},
-	{PRO_DMOD, 0xf14c, {0x00}, 0x01},
-	{PRO_DMOD, 0xf14d, {0x00}, 0x01},
-	{PRO_DMOD, 0xf14f, {0x04}, 0x01},
-	{PRO_DMOD, 0xf158, {0x7f}, 0x01},
-	{PRO_DMOD, 0xf15a, {0x00}, 0x01},
-	{PRO_DMOD, 0xf15b, {0x08}, 0x01},
-	{PRO_DMOD, 0xf15d, {0x03}, 0x01},
-	{PRO_DMOD, 0xf15e, {0x05}, 0x01},
-	{PRO_DMOD, 0xf163, {0x05}, 0x01},
-	{PRO_DMOD, 0xf166, {0x01}, 0x01},
-	{PRO_DMOD, 0xf167, {0x40}, 0x01},
-	{PRO_DMOD, 0xf168, {0x0f}, 0x01},
-	{PRO_DMOD, 0xf17a, {0x00}, 0x01},
-	{PRO_DMOD, 0xf17b, {0x00}, 0x01},
-	{PRO_DMOD, 0xf183, {0x01}, 0x01},
-	{PRO_DMOD, 0xf19d, {0x40}, 0x01},
-	{PRO_DMOD, 0xf1bc, {0x36}, 0x01},
-	{PRO_DMOD, 0xf1bd, {0x00}, 0x01},
-	{PRO_DMOD, 0xf1cb, {0xa0}, 0x01},
-	{PRO_DMOD, 0xf1cc, {0x01}, 0x01},
-	{PRO_DMOD, 0xf204, {0x10}, 0x01},
-	{PRO_DMOD, 0xf214, {0x00}, 0x01},
-	{PRO_DMOD, 0xf40e, {0x0a}, 0x01},
-	{PRO_DMOD, 0xf40f, {0x40}, 0x01},
-	{PRO_DMOD, 0xf410, {0x08}, 0x01},
-	{PRO_DMOD, 0xf55f, {0x0a}, 0x01},
-	{PRO_DMOD, 0xf561, {0x15}, 0x01},
-	{PRO_DMOD, 0xf562, {0x20}, 0x01},
-	{PRO_DMOD, 0xf5df, {0xfb}, 0x01},
-	{PRO_DMOD, 0xf5e0, {0x00}, 0x01},
-	{PRO_DMOD, 0xf5e3, {0x09}, 0x01},
-	{PRO_DMOD, 0xf5e4, {0x01}, 0x01},
-	{PRO_DMOD, 0xf5e5, {0x01}, 0x01},
-	{PRO_DMOD, 0xf5f8, {0x01}, 0x01},
-	{PRO_DMOD, 0xf5fd, {0x01}, 0x01},
-	{PRO_DMOD, 0xf600, {0x05}, 0x01},
-	{PRO_DMOD, 0xf601, {0x08}, 0x01},
-	{PRO_DMOD, 0xf602, {0x0b}, 0x01},
-	{PRO_DMOD, 0xf603, {0x0e}, 0x01},
-	{PRO_DMOD, 0xf604, {0x11}, 0x01},
-	{PRO_DMOD, 0xf605, {0x14}, 0x01},
-	{PRO_DMOD, 0xf606, {0x17}, 0x01},
-	{PRO_DMOD, 0xf607, {0x1f}, 0x01},
-	{PRO_DMOD, 0xf60e, {0x00}, 0x01},
-	{PRO_DMOD, 0xf60f, {0x04}, 0x01},
-	{PRO_DMOD, 0xf610, {0x32}, 0x01},
-	{PRO_DMOD, 0xf611, {0x10}, 0x01},
-	{PRO_DMOD, 0xf707, {0xfc}, 0x01},
-	{PRO_DMOD, 0xf708, {0x00}, 0x01},
-	{PRO_DMOD, 0xf709, {0x37}, 0x01},
-	{PRO_DMOD, 0xf70a, {0x00}, 0x01},
-	{PRO_DMOD, 0xf78b, {0x01}, 0x01},
-	{PRO_DMOD, 0xf80f, {0x40}, 0x01},
-	{PRO_DMOD, 0xf810, {0x54}, 0x01},
-	{PRO_DMOD, 0xf811, {0x5a}, 0x01},
-	{PRO_DMOD, 0xf905, {0x01}, 0x01},
-	{PRO_DMOD, 0xfb06, {0x03}, 0x01},
-	{PRO_DMOD, 0xfd8b, {0x00}, 0x01},
-	{0xff, 0x0000, {0x00}, 0x00} /* Terminating Entry */
-};
-
-static struct it913xset it9135_38[] = {
-	{PRO_DMOD, 0x0043, {0x00}, 0x01},
-	{PRO_DMOD, 0x0046, {0x38}, 0x01},
-	{PRO_DMOD, 0x0051, {0x01}, 0x01},
-	{PRO_DMOD, 0x005f, {0x00, 0x00}, 0x02},
-	{PRO_DMOD, 0x0068, {0x0a}, 0x01},
-	{PRO_DMOD, 0x0070, {0x0a, 0x05, 0x02}, 0x03},
-	{PRO_DMOD, 0x0075, {0x8c, 0x8c, 0x8c, 0xc8, 0x01}, 0x05},
-	{PRO_DMOD, 0x007e, {0x04, 0x00}, 0x02},
-	{PRO_DMOD, 0x0081, {	0x0a, 0x12, 0x02, 0x0a, 0x03, 0xc8, 0xb8,
-				0xd0, 0xc3, 0x01}, 0x0a},
-	{PRO_DMOD, 0x008e, {0x01}, 0x01},
-	{PRO_DMOD, 0x0092, {0x06, 0x00, 0x00, 0x00, 0x00}, 0x05},
-	{PRO_DMOD, 0x0099, {0x01}, 0x01},
-	{PRO_DMOD, 0x009b, {0x3c, 0x28}, 0x02},
-	{PRO_DMOD, 0x009f, {0xe1, 0xcf}, 0x02},
-	{PRO_DMOD, 0x00a3, {0x01, 0x5a, 0x01, 0x01}, 0x04},
-	{PRO_DMOD, 0x00a9, {0x00, 0x01}, 0x02},
-	{PRO_DMOD, 0x00b0, {0x01}, 0x01},
-	{PRO_DMOD, 0x00b3, {0x02, 0x32}, 0x02},
-	{PRO_DMOD, 0x00b6, {0x14}, 0x01},
-	{PRO_DMOD, 0x00c0, {0x11, 0x00, 0x05}, 0x03},
-	{PRO_DMOD, 0x00c4, {0x00}, 0x01},
-	{PRO_DMOD, 0x00c6, {0x19, 0x00}, 0x02},
-	{PRO_DMOD, 0x00cc, {0x2e, 0x51, 0x33}, 0x03},
-	{PRO_DMOD, 0x00f3, {0x05, 0x8c, 0x8c}, 0x03},
-	{PRO_DMOD, 0x00f8, {0x03, 0x06, 0x06}, 0x03},
-	{PRO_DMOD, 0x00fc, {	0x02, 0x02, 0x02, 0x09, 0x50, 0x7b, 0x77,
-				0x00, 0x02, 0xc8, 0x05, 0x7b}, 0x0c},
-	{PRO_DMOD, 0x0109, {0x02}, 0x01},
-	{PRO_DMOD, 0x0115, {0x0a, 0x03, 0x02, 0x80}, 0x04},
-	{PRO_DMOD, 0x011a, {0xc8, 0x7b, 0x8a, 0xa0}, 0x04},
-	{PRO_DMOD, 0x0122, {0x02, 0x18, 0xc3}, 0x03},
-	{PRO_DMOD, 0x0127, {0x00, 0x07}, 0x02},
-	{PRO_DMOD, 0x012a, {0x53, 0x51, 0x4e, 0x43}, 0x04},
-	{PRO_DMOD, 0x0137, {0x01, 0x00, 0x07, 0x00, 0x06}, 0x05},
-	{PRO_DMOD, 0x013d, {0x00, 0x01, 0x5b, 0xc8, 0x59}, 0x05},
-	{PRO_DMOD, 0xf000, {0x0f}, 0x01},
-	{PRO_DMOD, 0xf016, {0x10, 0x04, 0x05, 0x04, 0x05}, 0x05},
-	{PRO_DMOD, 0xf01f, {0x8c, 0x00, 0x03, 0x0a, 0x0a}, 0x05},
-	{PRO_DMOD, 0xf029, {0x8c, 0x00, 0x00, 0x01}, 0x04},
-	{PRO_DMOD, 0xf064, {0x03, 0xf9, 0x03, 0x01}, 0x04},
-	{PRO_DMOD, 0xf06f, {0xe0, 0x03}, 0x02},
-	{PRO_DMOD, 0xf072, {0x0f, 0x03}, 0x02},
-	{PRO_DMOD, 0xf077, {0x01, 0x00}, 0x02},
-	{PRO_DMOD, 0xf085, {0x00, 0x02, 0x00}, 0x03},
-	{PRO_DMOD, 0xf09b, {0x3f, 0x00, 0x20, 0x00, 0x0c, 0x00}, 0x06},
-	{PRO_DMOD, 0xf130, {0x04}, 0x01},
-	{PRO_DMOD, 0xf132, {0x04}, 0x01},
-	{PRO_DMOD, 0xf144, {0x1a}, 0x01},
-	{PRO_DMOD, 0xf146, {0x00}, 0x01},
-	{PRO_DMOD, 0xf14a, {0x01}, 0x01},
-	{PRO_DMOD, 0xf14c, {0x00, 0x00}, 0x02},
-	{PRO_DMOD, 0xf14f, {0x04}, 0x01},
-	{PRO_DMOD, 0xf158, {0x7f}, 0x01},
-	{PRO_DMOD, 0xf15a, {0x00, 0x08}, 0x02},
-	{PRO_DMOD, 0xf15d, {0x03, 0x05}, 0x02},
-	{PRO_DMOD, 0xf163, {0x05}, 0x01},
-	{PRO_DMOD, 0xf166, {0x01, 0x40, 0x0f}, 0x03},
-	{PRO_DMOD, 0xf17a, {0x00, 0x00}, 0x02},
-	{PRO_DMOD, 0xf183, {0x01}, 0x01},
-	{PRO_DMOD, 0xf19d, {0x40}, 0x01},
-	{PRO_DMOD, 0xf1bc, {0x36, 0x00}, 0x02},
-	{PRO_DMOD, 0xf1cb, {0xa0, 0x01}, 0x02},
-	{PRO_DMOD, 0xf204, {0x10}, 0x01},
-	{PRO_DMOD, 0xf214, {0x00}, 0x01},
-	{PRO_DMOD, 0xf24c, {0x88, 0x95, 0x9a, 0x90}, 0x04},
-	{PRO_DMOD, 0xf25a, {0x07, 0xe8, 0x03, 0xb0, 0x04}, 0x05},
-	{PRO_DMOD, 0xf270, {0x01, 0x02, 0x01, 0x02}, 0x04},
-	{PRO_DMOD, 0xf40e, {0x0a, 0x40, 0x08}, 0x03},
-	{PRO_DMOD, 0xf55f, {0x0a}, 0x01},
-	{PRO_DMOD, 0xf561, {0x15, 0x20}, 0x02},
-	{PRO_DMOD, 0xf5df, {0xfb, 0x00}, 0x02},
-	{PRO_DMOD, 0xf5e3, {0x09, 0x01, 0x01}, 0x03},
-	{PRO_DMOD, 0xf5f8, {0x01}, 0x01},
-	{PRO_DMOD, 0xf5fd, {0x01}, 0x01},
-	{PRO_DMOD, 0xf600, {	0x05, 0x08, 0x0b, 0x0e, 0x11, 0x14, 0x17,
-				0x1f}, 0x08},
-	{PRO_DMOD, 0xf60e, {0x00, 0x04, 0x32, 0x10}, 0x04},
-	{PRO_DMOD, 0xf707, {0xfc, 0x00, 0x37, 0x00}, 0x04},
-	{PRO_DMOD, 0xf78b, {0x01}, 0x01},
-	{PRO_DMOD, 0xf80f, {0x40, 0x54, 0x5a}, 0x03},
-	{PRO_DMOD, 0xf905, {0x01}, 0x01},
-	{PRO_DMOD, 0xfb06, {0x03}, 0x01},
-	{PRO_DMOD, 0xfd8b, {0x00}, 0x01},
-	{0xff, 0x0000, {0x00}, 0x00} /* Terminating Entry */
-};
-
-static struct it913xset it9135_51[] = {
-	{PRO_DMOD, 0x0043, {0x00}, 0x01},
-	{PRO_DMOD, 0x0046, {0x51}, 0x01},
-	{PRO_DMOD, 0x0051, {0x01}, 0x01},
-	{PRO_DMOD, 0x005f, {0x00, 0x00}, 0x02},
-	{PRO_DMOD, 0x0068, {0x0a}, 0x01},
-	{PRO_DMOD, 0x0070, {0x0a, 0x06, 0x02}, 0x03},
-	{PRO_DMOD, 0x0075, {0x8c, 0x8c, 0x8c, 0xc8, 0x01}, 0x05},
-	{PRO_DMOD, 0x007e, {0x04, 0x00}, 0x02},
-	{PRO_DMOD, 0x0081, {	0x0a, 0x12, 0x02, 0x0a, 0x03, 0xc0, 0x96,
-				0xcf, 0xc3, 0x01}, 0x0a},
-	{PRO_DMOD, 0x008e, {0x01}, 0x01},
-	{PRO_DMOD, 0x0092, {0x06, 0x00, 0x00, 0x00, 0x00}, 0x05},
-	{PRO_DMOD, 0x0099, {0x01}, 0x01},
-	{PRO_DMOD, 0x009b, {0x3c, 0x28}, 0x02},
-	{PRO_DMOD, 0x009f, {0xe1, 0xcf}, 0x02},
-	{PRO_DMOD, 0x00a3, {0x01, 0x5a, 0x01, 0x01}, 0x04},
-	{PRO_DMOD, 0x00a9, {0x00, 0x01}, 0x02},
-	{PRO_DMOD, 0x00b0, {0x01}, 0x01},
-	{PRO_DMOD, 0x00b3, {0x02, 0x3c}, 0x02},
-	{PRO_DMOD, 0x00b6, {0x14}, 0x01},
-	{PRO_DMOD, 0x00c0, {0x11, 0x00, 0x05}, 0x03},
-	{PRO_DMOD, 0x00c4, {0x00}, 0x01},
-	{PRO_DMOD, 0x00c6, {0x19, 0x00}, 0x02},
-	{PRO_DMOD, 0x00cc, {0x2e, 0x51, 0x33}, 0x03},
-	{PRO_DMOD, 0x00f3, {0x05, 0x8c, 0x8c}, 0x03},
-	{PRO_DMOD, 0x00f8, {0x03, 0x06, 0x06}, 0x03},
-	{PRO_DMOD, 0x00fc, {	0x03, 0x02, 0x02, 0x09, 0x50, 0x7a, 0x77,
-				0x01, 0x02, 0xb0, 0x02, 0x7a}, 0x0c},
-	{PRO_DMOD, 0x0109, {0x02}, 0x01},
-	{PRO_DMOD, 0x0115, {0x0a, 0x03, 0x02, 0x80}, 0x04},
-	{PRO_DMOD, 0x011a, {0xc0, 0x7a, 0xac, 0x8c}, 0x04},
-	{PRO_DMOD, 0x0122, {0x02, 0x70, 0xa4}, 0x03},
-	{PRO_DMOD, 0x0127, {0x00, 0x07}, 0x02},
-	{PRO_DMOD, 0x012a, {0x53, 0x51, 0x4e, 0x43}, 0x04},
-	{PRO_DMOD, 0x0137, {0x01, 0x00, 0x07, 0x00, 0x06}, 0x05},
-	{PRO_DMOD, 0x013d, {0x00, 0x01, 0x5b, 0xc0, 0x59}, 0x05},
-	{PRO_DMOD, 0xf000, {0x0f}, 0x01},
-	{PRO_DMOD, 0xf016, {0x10, 0x04, 0x05, 0x04, 0x05}, 0x05},
-	{PRO_DMOD, 0xf01f, {0x8c, 0x00, 0x03, 0x0a, 0x0a}, 0x05},
-	{PRO_DMOD, 0xf029, {0x8c, 0x00, 0x00, 0x01}, 0x04},
-	{PRO_DMOD, 0xf064, {0x03, 0xf9, 0x03, 0x01}, 0x04},
-	{PRO_DMOD, 0xf06f, {0xe0, 0x03}, 0x02},
-	{PRO_DMOD, 0xf072, {0x0f, 0x03}, 0x02},
-	{PRO_DMOD, 0xf077, {0x01, 0x00}, 0x02},
-	{PRO_DMOD, 0xf085, {0xc0, 0x01, 0x00}, 0x03},
-	{PRO_DMOD, 0xf09b, {0x3f, 0x00, 0x20, 0x00, 0x0c, 0x00}, 0x06},
-	{PRO_DMOD, 0xf130, {0x04}, 0x01},
-	{PRO_DMOD, 0xf132, {0x04}, 0x01},
-	{PRO_DMOD, 0xf144, {0x1a}, 0x01},
-	{PRO_DMOD, 0xf146, {0x00}, 0x01},
-	{PRO_DMOD, 0xf14a, {0x01}, 0x01},
-	{PRO_DMOD, 0xf14c, {0x00, 0x00}, 0x02},
-	{PRO_DMOD, 0xf14f, {0x04}, 0x01},
-	{PRO_DMOD, 0xf158, {0x7f}, 0x01},
-	{PRO_DMOD, 0xf15a, {0x00, 0x08}, 0x02},
-	{PRO_DMOD, 0xf15d, {0x03, 0x05}, 0x02},
-	{PRO_DMOD, 0xf163, {0x05}, 0x01},
-	{PRO_DMOD, 0xf166, {0x01, 0x40, 0x0f}, 0x03},
-	{PRO_DMOD, 0xf17a, {0x00, 0x00}, 0x02},
-	{PRO_DMOD, 0xf183, {0x01}, 0x01},
-	{PRO_DMOD, 0xf19d, {0x40}, 0x01},
-	{PRO_DMOD, 0xf1bc, {0x36, 0x00}, 0x02},
-	{PRO_DMOD, 0xf1cb, {0xa0, 0x01}, 0x02},
-	{PRO_DMOD, 0xf204, {0x10}, 0x01},
-	{PRO_DMOD, 0xf214, {0x00}, 0x01},
-	{PRO_DMOD, 0xf24c, {0x88, 0x95, 0x9a, 0x90}, 0x04},
-	{PRO_DMOD, 0xf25a, {0x07, 0xe8, 0x03, 0xb0, 0x04}, 0x05},
-	{PRO_DMOD, 0xf270, {0x01, 0x02, 0x01, 0x02}, 0x04},
-	{PRO_DMOD, 0xf40e, {0x0a, 0x40, 0x08}, 0x03},
-	{PRO_DMOD, 0xf55f, {0x0a}, 0x01},
-	{PRO_DMOD, 0xf561, {0x15, 0x20}, 0x02},
-	{PRO_DMOD, 0xf5df, {0xfb, 0x00}, 0x02},
-	{PRO_DMOD, 0xf5e3, {0x09, 0x01, 0x01}, 0x03},
-	{PRO_DMOD, 0xf5f8, {0x01}, 0x01},
-	{PRO_DMOD, 0xf5fd, {0x01}, 0x01},
-	{PRO_DMOD, 0xf600, {	0x05, 0x08, 0x0b, 0x0e, 0x11, 0x14, 0x17,
-				0x1f}, 0x08},
-	{PRO_DMOD, 0xf60e, {0x00, 0x04, 0x32, 0x10}, 0x04},
-	{PRO_DMOD, 0xf707, {0xfc, 0x00, 0x37, 0x00}, 0x04},
-	{PRO_DMOD, 0xf78b, {0x01}, 0x01},
-	{PRO_DMOD, 0xf80f, {0x40, 0x54, 0x5a}, 0x03},
-	{PRO_DMOD, 0xf905, {0x01}, 0x01},
-	{PRO_DMOD, 0xfb06, {0x03}, 0x01},
-	{PRO_DMOD, 0xfd8b, {0x00}, 0x01},
-	{0xff, 0x0000, {0x00}, 0x00} /* Terminating Entry */
-};
-
-static struct it913xset it9135_52[] = {
-	{PRO_DMOD, 0x0043, {0x00}, 0x01},
-	{PRO_DMOD, 0x0046, {0x52}, 0x01},
-	{PRO_DMOD, 0x0051, {0x01}, 0x01},
-	{PRO_DMOD, 0x005f, {0x00, 0x00}, 0x02},
-	{PRO_DMOD, 0x0068, {0x10}, 0x01},
-	{PRO_DMOD, 0x0070, {0x0a, 0x05, 0x02}, 0x03},
-	{PRO_DMOD, 0x0075, {0x8c, 0x8c, 0x8c, 0xa0, 0x01}, 0x05},
-	{PRO_DMOD, 0x007e, {0x04, 0x00}, 0x02},
-	{PRO_DMOD, 0x0081, {	0x0a, 0x12, 0x03, 0x0a, 0x03, 0xb3, 0x97,
-				0xc0, 0x9e, 0x01}, 0x0a},
-	{PRO_DMOD, 0x008e, {0x01}, 0x01},
-	{PRO_DMOD, 0x0092, {0x06, 0x00, 0x00, 0x00, 0x00}, 0x05},
-	{PRO_DMOD, 0x0099, {0x01}, 0x01},
-	{PRO_DMOD, 0x009b, {0x3c, 0x28}, 0x02},
-	{PRO_DMOD, 0x009f, {0xe1, 0xcf}, 0x02},
-	{PRO_DMOD, 0x00a3, {0x01, 0x5c, 0x01, 0x01}, 0x04},
-	{PRO_DMOD, 0x00a9, {0x00, 0x01}, 0x02},
-	{PRO_DMOD, 0x00b0, {0x01}, 0x01},
-	{PRO_DMOD, 0x00b3, {0x02, 0x3c}, 0x02},
-	{PRO_DMOD, 0x00b6, {0x14}, 0x01},
-	{PRO_DMOD, 0x00c0, {0x11, 0x00, 0x05}, 0x03},
-	{PRO_DMOD, 0x00c4, {0x00}, 0x01},
-	{PRO_DMOD, 0x00c6, {0x19, 0x00}, 0x02},
-	{PRO_DMOD, 0x00cc, {0x2e, 0x51, 0x33}, 0x03},
-	{PRO_DMOD, 0x00f3, {0x05, 0x91, 0x8c}, 0x03},
-	{PRO_DMOD, 0x00f8, {0x03, 0x06, 0x06}, 0x03},
-	{PRO_DMOD, 0x00fc, {	0x03, 0x02, 0x02, 0x09, 0x50, 0x74, 0x77,
-				0x02, 0x02, 0xae, 0x02, 0x6e}, 0x0c},
-	{PRO_DMOD, 0x0109, {0x02}, 0x01},
-	{PRO_DMOD, 0x0115, {0x0a, 0x03, 0x02, 0x80}, 0x04},
-	{PRO_DMOD, 0x011a, {0xcd, 0x62, 0xa4, 0x8c}, 0x04},
-	{PRO_DMOD, 0x0122, {0x03, 0x18, 0x9e}, 0x03},
-	{PRO_DMOD, 0x0127, {0x00, 0x07}, 0x02},
-	{PRO_DMOD, 0x012a, {0x53, 0x51, 0x4e, 0x43}, 0x04},
-	{PRO_DMOD, 0x0137, {0x00, 0x00, 0x07, 0x00, 0x06}, 0x05},
-	{PRO_DMOD, 0x013d, {0x00, 0x01, 0x5b, 0xb6, 0x59}, 0x05},
-	{PRO_DMOD, 0xf000, {0x0f}, 0x01},
-	{PRO_DMOD, 0xf016, {0x10, 0x04, 0x05, 0x04, 0x05}, 0x05},
-	{PRO_DMOD, 0xf01f, {0x8c, 0x00, 0x03, 0x0a, 0x0a}, 0x05},
-	{PRO_DMOD, 0xf029, {0x8c, 0x00, 0x00, 0x01}, 0x04},
-	{PRO_DMOD, 0xf064, {0x03, 0xf9, 0x03, 0x01}, 0x04},
-	{PRO_DMOD, 0xf06f, {0xe0, 0x03}, 0x02},
-	{PRO_DMOD, 0xf072, {0x0f, 0x03}, 0x02},
-	{PRO_DMOD, 0xf077, {0x01, 0x00}, 0x02},
-	{PRO_DMOD, 0xf085, {0xc0, 0x01, 0x00}, 0x03},
-	{PRO_DMOD, 0xf09b, {0x3f, 0x00, 0x20, 0x00, 0x0c, 0x00}, 0x06},
-	{PRO_DMOD, 0xf130, {0x04}, 0x01},
-	{PRO_DMOD, 0xf132, {0x04}, 0x01},
-	{PRO_DMOD, 0xf144, {0x1a}, 0x01},
-	{PRO_DMOD, 0xf146, {0x00}, 0x01},
-	{PRO_DMOD, 0xf14a, {0x01}, 0x01},
-	{PRO_DMOD, 0xf14c, {0x00, 0x00}, 0x02},
-	{PRO_DMOD, 0xf14f, {0x04}, 0x01},
-	{PRO_DMOD, 0xf158, {0x7f}, 0x01},
-	{PRO_DMOD, 0xf15a, {0x00, 0x08}, 0x02},
-	{PRO_DMOD, 0xf15d, {0x03, 0x05}, 0x02},
-	{PRO_DMOD, 0xf163, {0x05}, 0x01},
-	{PRO_DMOD, 0xf166, {0x01, 0x40, 0x0f}, 0x03},
-	{PRO_DMOD, 0xf17a, {0x00, 0x00}, 0x02},
-	{PRO_DMOD, 0xf183, {0x01}, 0x01},
-	{PRO_DMOD, 0xf19d, {0x40}, 0x01},
-	{PRO_DMOD, 0xf1bc, {0x36, 0x00}, 0x02},
-	{PRO_DMOD, 0xf1cb, {0xa0, 0x01}, 0x02},
-	{PRO_DMOD, 0xf204, {0x10}, 0x01},
-	{PRO_DMOD, 0xf214, {0x00}, 0x01},
-	{PRO_DMOD, 0xf24c, {0x88, 0x95, 0x9a, 0x90}, 0x04},
-	{PRO_DMOD, 0xf25a, {0x07, 0xe8, 0x03, 0xb0, 0x04}, 0x05},
-	{PRO_DMOD, 0xf270, {0x01, 0x02, 0x01, 0x02}, 0x04},
-	{PRO_DMOD, 0xf40e, {0x0a, 0x40, 0x08}, 0x03},
-	{PRO_DMOD, 0xf55f, {0x0a}, 0x01},
-	{PRO_DMOD, 0xf561, {0x15, 0x20}, 0x02},
-	{PRO_DMOD, 0xf5df, {0xfb, 0x00}, 0x02},
-	{PRO_DMOD, 0xf5e3, {0x09, 0x01, 0x01}, 0x03},
-	{PRO_DMOD, 0xf5f8, {0x01}, 0x01},
-	{PRO_DMOD, 0xf5fd, {0x01}, 0x01},
-	{PRO_DMOD, 0xf600, {0x05, 0x08, 0x0b, 0x0e, 0x11, 0x14, 0x17,
-				0x1f}, 0x08},
-	{PRO_DMOD, 0xf60e, {0x00, 0x04, 0x32, 0x10}, 0x04},
-	{PRO_DMOD, 0xf707, {0xfc, 0x00, 0x37, 0x00}, 0x04},
-	{PRO_DMOD, 0xf78b, {0x01}, 0x01},
-	{PRO_DMOD, 0xf80f, {0x40, 0x54, 0x5a}, 0x03},
-	{PRO_DMOD, 0xf905, {0x01}, 0x01},
-	{PRO_DMOD, 0xfb06, {0x03}, 0x01},
-	{PRO_DMOD, 0xfd8b, {0x00}, 0x01},
-	{0xff, 0x0000, {0x00}, 0x00} /* Terminating Entry */
-};
-
-/* Version 2 types */
-static struct it913xset it9135_v2[] = {
-	{PRO_DMOD, 0x0051, {0x01}, 0x01},
-	{PRO_DMOD, 0x0070, {0x0a}, 0x01},
-	{PRO_DMOD, 0x007e, {0x04}, 0x01},
-	{PRO_DMOD, 0x0081, {0x0a}, 0x01},
-	{PRO_DMOD, 0x008a, {0x01}, 0x01},
-	{PRO_DMOD, 0x008e, {0x01}, 0x01},
-	{PRO_DMOD, 0x0092, {0x06}, 0x01},
-	{PRO_DMOD, 0x0099, {0x01}, 0x01},
-	{PRO_DMOD, 0x009f, {0xe1}, 0x01},
-	{PRO_DMOD, 0x00a0, {0xcf}, 0x01},
-	{PRO_DMOD, 0x00a3, {0x01}, 0x01},
-	{PRO_DMOD, 0x00a5, {0x01}, 0x01},
-	{PRO_DMOD, 0x00a6, {0x01}, 0x01},
-	{PRO_DMOD, 0x00a9, {0x00}, 0x01},
-	{PRO_DMOD, 0x00aa, {0x01}, 0x01},
-	{PRO_DMOD, 0x00b0, {0x01}, 0x01},
-	{PRO_DMOD, 0x00c2, {0x05}, 0x01},
-	{PRO_DMOD, 0x00c6, {0x19}, 0x01},
-	{PRO_DMOD, 0xf000, {0x0f}, 0x01},
-	{PRO_DMOD, 0xf02b, {0x00}, 0x01},
-	{PRO_DMOD, 0xf064, {0x03}, 0x01},
-	{PRO_DMOD, 0xf065, {0xf9}, 0x01},
-	{PRO_DMOD, 0xf066, {0x03}, 0x01},
-	{PRO_DMOD, 0xf067, {0x01}, 0x01},
-	{PRO_DMOD, 0xf06f, {0xe0}, 0x01},
-	{PRO_DMOD, 0xf070, {0x03}, 0x01},
-	{PRO_DMOD, 0xf072, {0x0f}, 0x01},
-	{PRO_DMOD, 0xf073, {0x03}, 0x01},
-	{PRO_DMOD, 0xf078, {0x00}, 0x01},
-	{PRO_DMOD, 0xf087, {0x00}, 0x01},
-	{PRO_DMOD, 0xf09b, {0x3f}, 0x01},
-	{PRO_DMOD, 0xf09c, {0x00}, 0x01},
-	{PRO_DMOD, 0xf09d, {0x20}, 0x01},
-	{PRO_DMOD, 0xf09e, {0x00}, 0x01},
-	{PRO_DMOD, 0xf09f, {0x0c}, 0x01},
-	{PRO_DMOD, 0xf0a0, {0x00}, 0x01},
-	{PRO_DMOD, 0xf130, {0x04}, 0x01},
-	{PRO_DMOD, 0xf132, {0x04}, 0x01},
-	{PRO_DMOD, 0xf144, {0x1a}, 0x01},
-	{PRO_DMOD, 0xf146, {0x00}, 0x01},
-	{PRO_DMOD, 0xf14a, {0x01}, 0x01},
-	{PRO_DMOD, 0xf14c, {0x00}, 0x01},
-	{PRO_DMOD, 0xf14d, {0x00}, 0x01},
-	{PRO_DMOD, 0xf14f, {0x04}, 0x01},
-	{PRO_DMOD, 0xf158, {0x7f}, 0x01},
-	{PRO_DMOD, 0xf15a, {0x00}, 0x01},
-	{PRO_DMOD, 0xf15b, {0x08}, 0x01},
-	{PRO_DMOD, 0xf15d, {0x03}, 0x01},
-	{PRO_DMOD, 0xf15e, {0x05}, 0x01},
-	{PRO_DMOD, 0xf163, {0x05}, 0x01},
-	{PRO_DMOD, 0xf166, {0x01}, 0x01},
-	{PRO_DMOD, 0xf167, {0x40}, 0x01},
-	{PRO_DMOD, 0xf168, {0x0f}, 0x01},
-	{PRO_DMOD, 0xf17a, {0x00}, 0x01},
-	{PRO_DMOD, 0xf17b, {0x00}, 0x01},
-	{PRO_DMOD, 0xf183, {0x01}, 0x01},
-	{PRO_DMOD, 0xf19d, {0x40}, 0x01},
-	{PRO_DMOD, 0xf1bc, {0x36}, 0x01},
-	{PRO_DMOD, 0xf1bd, {0x00}, 0x01},
-	{PRO_DMOD, 0xf1cb, {0xa0}, 0x01},
-	{PRO_DMOD, 0xf1cc, {0x01}, 0x01},
-	{PRO_DMOD, 0xf204, {0x10}, 0x01},
-	{PRO_DMOD, 0xf214, {0x00}, 0x01},
-	{PRO_DMOD, 0xf40e, {0x0a}, 0x01},
-	{PRO_DMOD, 0xf40f, {0x40}, 0x01},
-	{PRO_DMOD, 0xf410, {0x08}, 0x01},
-	{PRO_DMOD, 0xf55f, {0x0a}, 0x01},
-	{PRO_DMOD, 0xf561, {0x15}, 0x01},
-	{PRO_DMOD, 0xf562, {0x20}, 0x01},
-	{PRO_DMOD, 0xf5e3, {0x09}, 0x01},
-	{PRO_DMOD, 0xf5e4, {0x01}, 0x01},
-	{PRO_DMOD, 0xf5e5, {0x01}, 0x01},
-	{PRO_DMOD, 0xf600, {0x05}, 0x01},
-	{PRO_DMOD, 0xf601, {0x08}, 0x01},
-	{PRO_DMOD, 0xf602, {0x0b}, 0x01},
-	{PRO_DMOD, 0xf603, {0x0e}, 0x01},
-	{PRO_DMOD, 0xf604, {0x11}, 0x01},
-	{PRO_DMOD, 0xf605, {0x14}, 0x01},
-	{PRO_DMOD, 0xf606, {0x17}, 0x01},
-	{PRO_DMOD, 0xf607, {0x1f}, 0x01},
-	{PRO_DMOD, 0xf60e, {0x00}, 0x01},
-	{PRO_DMOD, 0xf60f, {0x04}, 0x01},
-	{PRO_DMOD, 0xf610, {0x32}, 0x01},
-	{PRO_DMOD, 0xf611, {0x10}, 0x01},
-	{PRO_DMOD, 0xf707, {0xfc}, 0x01},
-	{PRO_DMOD, 0xf708, {0x00}, 0x01},
-	{PRO_DMOD, 0xf709, {0x37}, 0x01},
-	{PRO_DMOD, 0xf70a, {0x00}, 0x01},
-	{PRO_DMOD, 0xf78b, {0x01}, 0x01},
-	{PRO_DMOD, 0xf80f, {0x40}, 0x01},
-	{PRO_DMOD, 0xf810, {0x54}, 0x01},
-	{PRO_DMOD, 0xf811, {0x5a}, 0x01},
-	{PRO_DMOD, 0xf905, {0x01}, 0x01},
-	{PRO_DMOD, 0xfb06, {0x03}, 0x01},
-	{PRO_DMOD, 0xfd8b, {0x00}, 0x01},
-	{0xff, 0x0000, {0x00}, 0x00} /* Terminating Entry */
-};
-
-static struct it913xset it9135_60[] = {
-	{PRO_DMOD, 0x0043, {0x00}, 0x01},
-	{PRO_DMOD, 0x0046, {0x60}, 0x01},
-	{PRO_DMOD, 0x0051, {0x01}, 0x01},
-	{PRO_DMOD, 0x005f, {0x00, 0x00}, 0x02},
-	{PRO_DMOD, 0x0068, {0x0a}, 0x01},
-	{PRO_DMOD, 0x006a, {0x03}, 0x01},
-	{PRO_DMOD, 0x0070, {0x0a, 0x05, 0x02}, 0x03},
-	{PRO_DMOD, 0x0075, {0x8c, 0x8c, 0x8c, 0x8c, 0x01}, 0x05},
-	{PRO_DMOD, 0x007e, {0x04}, 0x01},
-	{PRO_DMOD, 0x0081, {0x0a, 0x12}, 0x02},
-	{PRO_DMOD, 0x0084, {0x0a, 0x33, 0xbe, 0xa0, 0xc6, 0xb6, 0x01}, 0x07},
-	{PRO_DMOD, 0x008e, {0x01}, 0x01},
-	{PRO_DMOD, 0x0092, {0x06, 0x00, 0x00, 0x00, 0x00}, 0x05},
-	{PRO_DMOD, 0x0099, {0x01}, 0x01},
-	{PRO_DMOD, 0x009b, {0x3c, 0x28}, 0x02},
-	{PRO_DMOD, 0x009f, {0xe1, 0xcf}, 0x02},
-	{PRO_DMOD, 0x00a3, {0x01, 0x5a, 0x01, 0x01}, 0x04},
-	{PRO_DMOD, 0x00a9, {0x00, 0x01}, 0x02},
-	{PRO_DMOD, 0x00b0, {0x01}, 0x01},
-	{PRO_DMOD, 0x00b3, {0x02, 0x3a}, 0x02},
-	{PRO_DMOD, 0x00b6, {0x14}, 0x01},
-	{PRO_DMOD, 0x00c0, {0x11, 0x00, 0x05, 0x01, 0x00}, 0x05},
-	{PRO_DMOD, 0x00c6, {0x19, 0x00}, 0x02},
-	{PRO_DMOD, 0x00cb, {0x32, 0x2c, 0x4f, 0x30}, 0x04},
-	{PRO_DMOD, 0x00f3, {0x05, 0xa0, 0x8c}, 0x03},
-	{PRO_DMOD, 0x00f8, {0x03, 0x06, 0x06}, 0x03},
-	{PRO_DMOD, 0x00fc, {	0x03, 0x03, 0x02, 0x0a, 0x50, 0x7b, 0x8c,
-				0x00, 0x02, 0xbe, 0x00}, 0x0b},
-	{PRO_DMOD, 0x0109, {0x02}, 0x01},
-	{PRO_DMOD, 0x0115, {0x0a, 0x03}, 0x02},
-	{PRO_DMOD, 0x011a, {0xbe}, 0x01},
-	{PRO_DMOD, 0x0124, {0xae}, 0x01},
-	{PRO_DMOD, 0x0127, {0x00}, 0x01},
-	{PRO_DMOD, 0x012a, {0x56, 0x50, 0x47, 0x42}, 0x04},
-	{PRO_DMOD, 0x0137, {0x00}, 0x01},
-	{PRO_DMOD, 0x013b, {0x08}, 0x01},
-	{PRO_DMOD, 0x013f, {0x5b}, 0x01},
-	{PRO_DMOD, 0x0141, {	0x59, 0xf9, 0x19, 0x19, 0x8c, 0x8c, 0x8c,
-				0x6e, 0x8c, 0x50, 0x8c, 0x8c, 0xac, 0xc6,
-				0x33}, 0x0f},
-	{PRO_DMOD, 0x0151, {0x28}, 0x01},
-	{PRO_DMOD, 0x0153, {0xbc}, 0x01},
-	{PRO_DMOD, 0x0178, {0x09}, 0x01},
-	{PRO_DMOD, 0x0181, {0x94, 0x6e}, 0x02},
-	{PRO_DMOD, 0x0185, {0x24}, 0x01},
-	{PRO_DMOD, 0x0187, {0x00, 0x00, 0xbe, 0x02, 0x80}, 0x05},
-	{PRO_DMOD, 0xed02, {0xff}, 0x01},
-	{PRO_DMOD, 0xee42, {0xff}, 0x01},
-	{PRO_DMOD, 0xee82, {0xff}, 0x01},
-	{PRO_DMOD, 0xf000, {0x0f}, 0x01},
-	{PRO_DMOD, 0xf01f, {0x8c, 0x00}, 0x02},
-	{PRO_DMOD, 0xf029, {0x8c, 0x00, 0x00}, 0x03},
-	{PRO_DMOD, 0xf064, {0x03, 0xf9, 0x03, 0x01}, 0x04},
-	{PRO_DMOD, 0xf06f, {0xe0, 0x03}, 0x02},
-	{PRO_DMOD, 0xf072, {0x0f, 0x03}, 0x02},
-	{PRO_DMOD, 0xf077, {0x01, 0x00}, 0x02},
-	{PRO_DMOD, 0xf087, {0x00}, 0x01},
-	{PRO_DMOD, 0xf09b, {0x3f, 0x00, 0x20, 0x00, 0x0c, 0x00}, 0x06},
-	{PRO_DMOD, 0xf130, {0x04}, 0x01},
-	{PRO_DMOD, 0xf132, {0x04}, 0x01},
-	{PRO_DMOD, 0xf144, {0x1a}, 0x01},
-	{PRO_DMOD, 0xf146, {0x00}, 0x01},
-	{PRO_DMOD, 0xf14a, {0x01}, 0x01},
-	{PRO_DMOD, 0xf14c, {0x00, 0x00}, 0x02},
-	{PRO_DMOD, 0xf14f, {0x04}, 0x01},
-	{PRO_DMOD, 0xf158, {0x7f}, 0x01},
-	{PRO_DMOD, 0xf15a, {0x00, 0x08}, 0x02},
-	{PRO_DMOD, 0xf15d, {0x03, 0x05}, 0x02},
-	{PRO_DMOD, 0xf163, {0x05}, 0x01},
-	{PRO_DMOD, 0xf166, {0x01, 0x40, 0x0f}, 0x03},
-	{PRO_DMOD, 0xf17a, {0x00, 0x00}, 0x02},
-	{PRO_DMOD, 0xf183, {0x01}, 0x01},
-	{PRO_DMOD, 0xf19d, {0x40}, 0x01},
-	{PRO_DMOD, 0xf1bc, {0x36, 0x00}, 0x02},
-	{PRO_DMOD, 0xf1cb, {0xa0, 0x01}, 0x02},
-	{PRO_DMOD, 0xf204, {0x10}, 0x01},
-	{PRO_DMOD, 0xf214, {0x00}, 0x01},
-	{PRO_DMOD, 0xf24c, {0x88, 0x95, 0x9a, 0x90}, 0x04},
-	{PRO_DMOD, 0xf25a, {0x07, 0xe8, 0x03, 0xb0, 0x04}, 0x05},
-	{PRO_DMOD, 0xf270, {0x01, 0x02, 0x01, 0x02}, 0x04},
-	{PRO_DMOD, 0xf40e, {0x0a, 0x40, 0x08}, 0x03},
-	{PRO_DMOD, 0xf55f, {0x0a}, 0x01},
-	{PRO_DMOD, 0xf561, {0x15, 0x20}, 0x02},
-	{PRO_DMOD, 0xf5e3, {0x09, 0x01, 0x01}, 0x03},
-	{PRO_DMOD, 0xf600, {0x05, 0x08, 0x0b, 0x0e, 0x11, 0x14, 0x17
-		, 0x1f}, 0x08},
-	{PRO_DMOD, 0xf60e, {0x00, 0x04, 0x32, 0x10}, 0x04},
-	{PRO_DMOD, 0xf707, {0xfc, 0x00, 0x37, 0x00}, 0x04},
-	{PRO_DMOD, 0xf78b, {0x01}, 0x01},
-	{PRO_DMOD, 0xf80f, {0x40, 0x54, 0x5a}, 0x03},
-	{PRO_DMOD, 0xf905, {0x01}, 0x01},
-	{PRO_DMOD, 0xfb06, {0x03}, 0x01},
-	{PRO_DMOD, 0xfd8b, {0x00}, 0x01},
-	{0xff, 0x0000, {0x00}, 0x00} /* Terminating Entry */
-};
-
-static struct it913xset it9135_61[] = {
-	{PRO_DMOD, 0x0043, {0x00}, 0x01},
-	{PRO_DMOD, 0x0046, {0x61}, 0x01},
-	{PRO_DMOD, 0x0051, {0x01}, 0x01},
-	{PRO_DMOD, 0x005f, {0x00, 0x00}, 0x02},
-	{PRO_DMOD, 0x0068, {0x06}, 0x01},
-	{PRO_DMOD, 0x006a, {0x03}, 0x01},
-	{PRO_DMOD, 0x0070, {0x0a, 0x05, 0x02}, 0x03},
-	{PRO_DMOD, 0x0075, {0x8c, 0x8c, 0x8c, 0x90, 0x01}, 0x05},
-	{PRO_DMOD, 0x007e, {0x04}, 0x01},
-	{PRO_DMOD, 0x0081, {0x0a, 0x12}, 0x02},
-	{PRO_DMOD, 0x0084, {0x0a, 0x33, 0xbc, 0x9c, 0xcc, 0xa8, 0x01}, 0x07},
-	{PRO_DMOD, 0x008e, {0x01}, 0x01},
-	{PRO_DMOD, 0x0092, {0x06, 0x00, 0x00, 0x00, 0x00}, 0x05},
-	{PRO_DMOD, 0x0099, {0x01}, 0x01},
-	{PRO_DMOD, 0x009b, {0x3c, 0x28}, 0x02},
-	{PRO_DMOD, 0x009f, {0xe1, 0xcf}, 0x02},
-	{PRO_DMOD, 0x00a3, {0x01, 0x5c, 0x01, 0x01}, 0x04},
-	{PRO_DMOD, 0x00a9, {0x00, 0x01}, 0x02},
-	{PRO_DMOD, 0x00b0, {0x01}, 0x01},
-	{PRO_DMOD, 0x00b3, {0x02, 0x3a}, 0x02},
-	{PRO_DMOD, 0x00b6, {0x14}, 0x01},
-	{PRO_DMOD, 0x00c0, {0x11, 0x00, 0x05, 0x01, 0x00}, 0x05},
-	{PRO_DMOD, 0x00c6, {0x19, 0x00}, 0x02},
-	{PRO_DMOD, 0x00cb, {0x32, 0x2c, 0x4f, 0x30}, 0x04},
-	{PRO_DMOD, 0x00f3, {0x05, 0xa0, 0x8c}, 0x03},
-	{PRO_DMOD, 0x00f8, {0x03, 0x06, 0x06}, 0x03},
-	{PRO_DMOD, 0x00fc, {	0x03, 0x03, 0x02, 0x08, 0x50, 0x7b, 0x8c,
-				0x01, 0x02, 0xc8, 0x00}, 0x0b},
-	{PRO_DMOD, 0x0109, {0x02}, 0x01},
-	{PRO_DMOD, 0x0115, {0x0a, 0x03}, 0x02},
-	{PRO_DMOD, 0x011a, {0xc6}, 0x01},
-	{PRO_DMOD, 0x0124, {0xa8}, 0x01},
-	{PRO_DMOD, 0x0127, {0x00}, 0x01},
-	{PRO_DMOD, 0x012a, {0x59, 0x50, 0x47, 0x42}, 0x04},
-	{PRO_DMOD, 0x0137, {0x00}, 0x01},
-	{PRO_DMOD, 0x013b, {0x05}, 0x01},
-	{PRO_DMOD, 0x013f, {0x5b}, 0x01},
-	{PRO_DMOD, 0x0141, {	0x59, 0xf9, 0x59, 0x59, 0x8c, 0x8c, 0x8c,
-				0x7b, 0x8c, 0x50, 0x8c, 0x8c, 0xa8, 0xc6,
-				0x33}, 0x0f},
-	{PRO_DMOD, 0x0151, {0x28}, 0x01},
-	{PRO_DMOD, 0x0153, {0xcc}, 0x01},
-	{PRO_DMOD, 0x0178, {0x09}, 0x01},
-	{PRO_DMOD, 0x0181, {0x9c, 0x76}, 0x02},
-	{PRO_DMOD, 0x0185, {0x28}, 0x01},
-	{PRO_DMOD, 0x0187, {0x01, 0x00, 0xaa, 0x02, 0x80}, 0x05},
-	{PRO_DMOD, 0xed02, {0xff}, 0x01},
-	{PRO_DMOD, 0xee42, {0xff}, 0x01},
-	{PRO_DMOD, 0xee82, {0xff}, 0x01},
-	{PRO_DMOD, 0xf000, {0x0f}, 0x01},
-	{PRO_DMOD, 0xf01f, {0x8c, 0x00}, 0x02},
-	{PRO_DMOD, 0xf029, {0x8c, 0x00, 0x00}, 0x03},
-	{PRO_DMOD, 0xf064, {0x03, 0xf9, 0x03, 0x01}, 0x04},
-	{PRO_DMOD, 0xf06f, {0xe0, 0x03}, 0x02},
-	{PRO_DMOD, 0xf072, {0x0f, 0x03}, 0x02},
-	{PRO_DMOD, 0xf077, {0x01, 0x00}, 0x02},
-	{PRO_DMOD, 0xf087, {0x00}, 0x01},
-	{PRO_DMOD, 0xf09b, {0x3f, 0x00, 0x20, 0x00, 0x0c, 0x00}, 0x06},
-	{PRO_DMOD, 0xf130, {0x04}, 0x01},
-	{PRO_DMOD, 0xf132, {0x04}, 0x01},
-	{PRO_DMOD, 0xf144, {0x1a}, 0x01},
-	{PRO_DMOD, 0xf146, {0x00}, 0x01},
-	{PRO_DMOD, 0xf14a, {0x01}, 0x01},
-	{PRO_DMOD, 0xf14c, {0x00, 0x00}, 0x02},
-	{PRO_DMOD, 0xf14f, {0x04}, 0x01},
-	{PRO_DMOD, 0xf158, {0x7f}, 0x01},
-	{PRO_DMOD, 0xf15a, {0x00, 0x08}, 0x02},
-	{PRO_DMOD, 0xf15d, {0x03, 0x05}, 0x02},
-	{PRO_DMOD, 0xf163, {0x05}, 0x01},
-	{PRO_DMOD, 0xf166, {0x01, 0x40, 0x0f}, 0x03},
-	{PRO_DMOD, 0xf17a, {0x00, 0x00}, 0x02},
-	{PRO_DMOD, 0xf183, {0x01}, 0x01},
-	{PRO_DMOD, 0xf19d, {0x40}, 0x01},
-	{PRO_DMOD, 0xf1bc, {0x36, 0x00}, 0x02},
-	{PRO_DMOD, 0xf1cb, {0xa0, 0x01}, 0x02},
-	{PRO_DMOD, 0xf204, {0x10}, 0x01},
-	{PRO_DMOD, 0xf214, {0x00}, 0x01},
-	{PRO_DMOD, 0xf24c, {0x88, 0x95, 0x9a, 0x90}, 0x04},
-	{PRO_DMOD, 0xf25a, {0x07, 0xe8, 0x03, 0xb0, 0x04}, 0x05},
-	{PRO_DMOD, 0xf270, {0x01, 0x02, 0x01, 0x02}, 0x04},
-	{PRO_DMOD, 0xf40e, {0x0a, 0x40, 0x08}, 0x03},
-	{PRO_DMOD, 0xf55f, {0x0a}, 0x01},
-	{PRO_DMOD, 0xf561, {0x15, 0x20}, 0x02},
-	{PRO_DMOD, 0xf5e3, {0x09, 0x01, 0x01}, 0x03},
-	{PRO_DMOD, 0xf600, {	0x05, 0x08, 0x0b, 0x0e, 0x11, 0x14, 0x17,
-				0x1f}, 0x08},
-	{PRO_DMOD, 0xf60e, {0x00, 0x04, 0x32, 0x10}, 0x04},
-	{PRO_DMOD, 0xf707, {0xfc, 0x00, 0x37, 0x00}, 0x04},
-	{PRO_DMOD, 0xf78b, {0x01}, 0x01},
-	{PRO_DMOD, 0xf80f, {0x40, 0x54, 0x5a}, 0x03},
-	{PRO_DMOD, 0xf905, {0x01}, 0x01},
-	{PRO_DMOD, 0xfb06, {0x03}, 0x01},
-	{PRO_DMOD, 0xfd8b, {0x00}, 0x01},
-	{0xff, 0x0000, {0x00}, 0x00} /* Terminating Entry */
-};
-
-static struct it913xset it9135_62[] = {
-	{PRO_DMOD, 0x0043, {0x00}, 0x01},
-	{PRO_DMOD, 0x0046, {0x62}, 0x01},
-	{PRO_DMOD, 0x0051, {0x01}, 0x01},
-	{PRO_DMOD, 0x005f, {0x00, 0x00}, 0x02},
-	{PRO_DMOD, 0x0068, {0x0a}, 0x01},
-	{PRO_DMOD, 0x006a, {0x03}, 0x01},
-	{PRO_DMOD, 0x0070, {0x0a, 0x05, 0x02}, 0x03},
-	{PRO_DMOD, 0x0075, {0x8c, 0x8c, 0x8c, 0x8c, 0x01}, 0x05},
-	{PRO_DMOD, 0x007e, {0x04}, 0x01},
-	{PRO_DMOD, 0x0081, {0x0a, 0x12}, 0x02},
-	{PRO_DMOD, 0x0084, {	0x0a, 0x33, 0xb8, 0x9c, 0xb2, 0xa6, 0x01},
-				0x07},
-	{PRO_DMOD, 0x008e, {0x01}, 0x01},
-	{PRO_DMOD, 0x0092, {0x06, 0x00, 0x00, 0x00, 0x00}, 0x05},
-	{PRO_DMOD, 0x0099, {0x01}, 0x01},
-	{PRO_DMOD, 0x009b, {0x3c, 0x28}, 0x02},
-	{PRO_DMOD, 0x009f, {0xe1, 0xcf}, 0x02},
-	{PRO_DMOD, 0x00a3, {0x01, 0x5a, 0x01, 0x01}, 0x04},
-	{PRO_DMOD, 0x00a9, {0x00, 0x01}, 0x02},
-	{PRO_DMOD, 0x00b0, {0x01}, 0x01},
-	{PRO_DMOD, 0x00b3, {0x02, 0x3a}, 0x02},
-	{PRO_DMOD, 0x00b6, {0x14}, 0x01},
-	{PRO_DMOD, 0x00c0, {0x11, 0x00, 0x05, 0x01, 0x00}, 0x05},
-	{PRO_DMOD, 0x00c6, {0x19, 0x00}, 0x02},
-	{PRO_DMOD, 0x00cb, {0x32, 0x2c, 0x4f, 0x30}, 0x04},
-	{PRO_DMOD, 0x00f3, {0x05, 0x8c, 0x8c}, 0x03},
-	{PRO_DMOD, 0x00f8, {0x03, 0x06, 0x06}, 0x03},
-	{PRO_DMOD, 0x00fc, {	0x02, 0x03, 0x02, 0x09, 0x50, 0x6e, 0x8c,
-				0x02, 0x02, 0xc2, 0x00}, 0x0b},
-	{PRO_DMOD, 0x0109, {0x02}, 0x01},
-	{PRO_DMOD, 0x0115, {0x0a, 0x03}, 0x02},
-	{PRO_DMOD, 0x011a, {0xb8}, 0x01},
-	{PRO_DMOD, 0x0124, {0xa8}, 0x01},
-	{PRO_DMOD, 0x0127, {0x00}, 0x01},
-	{PRO_DMOD, 0x012a, {0x53, 0x51, 0x4e, 0x43}, 0x04},
-	{PRO_DMOD, 0x0137, {0x00}, 0x01},
-	{PRO_DMOD, 0x013b, {0x05}, 0x01},
-	{PRO_DMOD, 0x013f, {0x5b}, 0x01},
-	{PRO_DMOD, 0x0141, {	0x59, 0xf9, 0x59, 0x19, 0x8c, 0x8c, 0x8c,
-				0x7b, 0x8c, 0x50, 0x70, 0x8c, 0x96, 0xd0,
-				0x33}, 0x0f},
-	{PRO_DMOD, 0x0151, {0x28}, 0x01},
-	{PRO_DMOD, 0x0153, {0xb2}, 0x01},
-	{PRO_DMOD, 0x0178, {0x09}, 0x01},
-	{PRO_DMOD, 0x0181, {0x9c, 0x6e}, 0x02},
-	{PRO_DMOD, 0x0185, {0x24}, 0x01},
-	{PRO_DMOD, 0x0187, {0x00, 0x00, 0xb8, 0x02, 0x80}, 0x05},
-	{PRO_DMOD, 0xed02, {0xff}, 0x01},
-	{PRO_DMOD, 0xee42, {0xff}, 0x01},
-	{PRO_DMOD, 0xee82, {0xff}, 0x01},
-	{PRO_DMOD, 0xf000, {0x0f}, 0x01},
-	{PRO_DMOD, 0xf01f, {0x8c, 0x00}, 0x02},
-	{PRO_DMOD, 0xf029, {0x8c, 0x00, 0x00}, 0x03},
-	{PRO_DMOD, 0xf064, {0x03, 0xf9, 0x03, 0x01}, 0x04},
-	{PRO_DMOD, 0xf06f, {0xe0, 0x03}, 0x02},
-	{PRO_DMOD, 0xf072, {0x0f, 0x03}, 0x02},
-	{PRO_DMOD, 0xf077, {0x01, 0x00}, 0x02},
-	{PRO_DMOD, 0xf087, {0x00}, 0x01},
-	{PRO_DMOD, 0xf09b, {0x3f, 0x00, 0x20, 0x00, 0x0c, 0x00}, 0x06},
-	{PRO_DMOD, 0xf130, {0x04}, 0x01},
-	{PRO_DMOD, 0xf132, {0x04}, 0x01},
-	{PRO_DMOD, 0xf144, {0x1a}, 0x01},
-	{PRO_DMOD, 0xf146, {0x00}, 0x01},
-	{PRO_DMOD, 0xf14a, {0x01}, 0x01},
-	{PRO_DMOD, 0xf14c, {0x00, 0x00}, 0x02},
-	{PRO_DMOD, 0xf14f, {0x04}, 0x01},
-	{PRO_DMOD, 0xf158, {0x7f}, 0x01},
-	{PRO_DMOD, 0xf15a, {0x00, 0x08}, 0x02},
-	{PRO_DMOD, 0xf15d, {0x03, 0x05}, 0x02},
-	{PRO_DMOD, 0xf163, {0x05}, 0x01},
-	{PRO_DMOD, 0xf166, {0x01, 0x40, 0x0f}, 0x03},
-	{PRO_DMOD, 0xf17a, {0x00, 0x00}, 0x02},
-	{PRO_DMOD, 0xf183, {0x01}, 0x01},
-	{PRO_DMOD, 0xf19d, {0x40}, 0x01},
-	{PRO_DMOD, 0xf1bc, {0x36, 0x00}, 0x02},
-	{PRO_DMOD, 0xf1cb, {0xa0, 0x01}, 0x02},
-	{PRO_DMOD, 0xf204, {0x10}, 0x01},
-	{PRO_DMOD, 0xf214, {0x00}, 0x01},
-	{PRO_DMOD, 0xf24c, {0x88, 0x95, 0x9a, 0x90}, 0x04},
-	{PRO_DMOD, 0xf25a, {0x07, 0xe8, 0x03, 0xb0, 0x04}, 0x05},
-	{PRO_DMOD, 0xf270, {0x01, 0x02, 0x01, 0x02}, 0x04},
-	{PRO_DMOD, 0xf40e, {0x0a, 0x40, 0x08}, 0x03},
-	{PRO_DMOD, 0xf55f, {0x0a}, 0x01},
-	{PRO_DMOD, 0xf561, {0x15, 0x20}, 0x02},
-	{PRO_DMOD, 0xf5e3, {0x09, 0x01, 0x01}, 0x03},
-	{PRO_DMOD, 0xf600, {	0x05, 0x08, 0x0b, 0x0e, 0x11, 0x14, 0x17,
-				0x1f}, 0x08},
-	{PRO_DMOD, 0xf60e, {0x00, 0x04, 0x32, 0x10}, 0x04},
-	{PRO_DMOD, 0xf707, {0xfc, 0x00, 0x37, 0x00}, 0x04},
-	{PRO_DMOD, 0xf78b, {0x01}, 0x01},
-	{PRO_DMOD, 0xf80f, {0x40, 0x54, 0x5a}, 0x03},
-	{PRO_DMOD, 0xf905, {0x01}, 0x01},
-	{PRO_DMOD, 0xfb06, {0x03}, 0x01},
-	{PRO_DMOD, 0xfd8b, {0x00}, 0x01},
-	{0xff, 0x0000, {0x00}, 0x00} /* Terminating Entry */
-};
-
-/* Tuner setting scripts (still keeping it9137) */
-static struct it913xset it9137_tuner_off[] = {
-	{PRO_DMOD, 0xfba8, {0x01}, 0x01}, /* Tuner Clock Off  */
-	{PRO_DMOD, 0xec40, {0x00}, 0x01}, /* Power Down Tuner */
-	{PRO_DMOD, 0xec02, {0x3f, 0x1f, 0x3f, 0x3f}, 0x04},
-	{PRO_DMOD, 0xec06, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-				0x00, 0x00, 0x00, 0x00}, 0x0c},
-	{PRO_DMOD, 0xec12, {0x00, 0x00, 0x00, 0x00}, 0x04},
-	{PRO_DMOD, 0xec17, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-				0x00}, 0x09},
-	{PRO_DMOD, 0xec22, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-				0x00, 0x00}, 0x0a},
-	{PRO_DMOD, 0xec20, {0x00}, 0x01},
-	{PRO_DMOD, 0xec3f, {0x01}, 0x01},
-	{0xff, 0x0000, {0x00}, 0x00}, /* Terminating Entry */
-};
-
-static struct it913xset set_it9135_template[] = {
-	{PRO_DMOD, 0xee06, {0x00}, 0x01},
-	{PRO_DMOD, 0xec56, {0x00}, 0x01},
-	{PRO_DMOD, 0xec4c, {0x00}, 0x01},
-	{PRO_DMOD, 0xec4d, {0x00}, 0x01},
-	{PRO_DMOD, 0xec4e, {0x00}, 0x01},
-	{PRO_DMOD, 0x011e, {0x00}, 0x01}, /* Older Devices */
-	{PRO_DMOD, 0x011f, {0x00}, 0x01},
-	{0xff, 0x0000, {0x00}, 0x00}, /* Terminating Entry */
-};
-
-static struct it913xset set_it9137_template[] = {
-	{PRO_DMOD, 0xee06, {0x00}, 0x01},
-	{PRO_DMOD, 0xec56, {0x00}, 0x01},
-	{PRO_DMOD, 0xec4c, {0x00}, 0x01},
-	{PRO_DMOD, 0xec4d, {0x00}, 0x01},
-	{PRO_DMOD, 0xec4e, {0x00}, 0x01},
-	{PRO_DMOD, 0xec4f, {0x00}, 0x01},
-	{PRO_DMOD, 0xec50, {0x00}, 0x01},
-	{0xff, 0x0000, {0x00}, 0x00}, /* Terminating Entry */
-};
diff --git a/drivers/media/dvb/frontends/it913x-fe.c b/drivers/media/dvb/frontends/it913x-fe.c
deleted file mode 100644
index 708cbf1..0000000
--- a/drivers/media/dvb/frontends/it913x-fe.c
+++ /dev/null
@@ -1,1045 +0,0 @@
-/*
- *  Driver for it913x-fe Frontend
- *
- *  with support for on chip it9137 integral tuner
- *
- *  Copyright (C) 2011 Malcolm Priestley (tvboxspy@gmail.com)
- *  IT9137 Copyright (C) ITE Tech Inc.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.=
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/types.h>
-
-#include "dvb_frontend.h"
-#include "it913x-fe.h"
-#include "it913x-fe-priv.h"
-
-static int it913x_debug;
-
-module_param_named(debug, it913x_debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able)).");
-
-#define dprintk(level, args...) do { \
-	if (level & it913x_debug) \
-		printk(KERN_DEBUG "it913x-fe: " args); \
-} while (0)
-
-#define deb_info(args...)  dprintk(0x01, args)
-#define debug_data_snipet(level, name, p) \
-	  dprintk(level, name" (%02x%02x%02x%02x%02x%02x%02x%02x)", \
-		*p, *(p+1), *(p+2), *(p+3), *(p+4), \
-			*(p+5), *(p+6), *(p+7));
-#define info(format, arg...) \
-	printk(KERN_INFO "it913x-fe: " format "\n" , ## arg)
-
-struct it913x_fe_state {
-	struct dvb_frontend frontend;
-	struct i2c_adapter *i2c_adap;
-	struct ite_config *config;
-	u8 i2c_addr;
-	u32 frequency;
-	fe_modulation_t constellation;
-	fe_transmit_mode_t transmission_mode;
-	u8 priority;
-	u32 crystalFrequency;
-	u32 adcFrequency;
-	u8 tuner_type;
-	struct adctable *table;
-	fe_status_t it913x_status;
-	u16 tun_xtal;
-	u8 tun_fdiv;
-	u8 tun_clk_mode;
-	u32 tun_fn_min;
-	u32 ucblocks;
-};
-
-static int it913x_read_reg(struct it913x_fe_state *state,
-		u32 reg, u8 *data, u8 count)
-{
-	int ret;
-	u8 pro = PRO_DMOD; /* All reads from demodulator */
-	u8 b[4];
-	struct i2c_msg msg[2] = {
-		{ .addr = state->i2c_addr + (pro << 1), .flags = 0,
-			.buf = b, .len = sizeof(b) },
-		{ .addr = state->i2c_addr + (pro << 1), .flags = I2C_M_RD,
-			.buf = data, .len = count }
-	};
-	b[0] = (u8) reg >> 24;
-	b[1] = (u8)(reg >> 16) & 0xff;
-	b[2] = (u8)(reg >> 8) & 0xff;
-	b[3] = (u8) reg & 0xff;
-
-	ret = i2c_transfer(state->i2c_adap, msg, 2);
-
-	return ret;
-}
-
-static int it913x_read_reg_u8(struct it913x_fe_state *state, u32 reg)
-{
-	int ret;
-	u8 b[1];
-	ret = it913x_read_reg(state, reg, &b[0], sizeof(b));
-	return (ret < 0) ? -ENODEV : b[0];
-}
-
-static int it913x_write(struct it913x_fe_state *state,
-		u8 pro, u32 reg, u8 buf[], u8 count)
-{
-	u8 b[256];
-	struct i2c_msg msg[1] = {
-		{ .addr = state->i2c_addr + (pro << 1), .flags = 0,
-		  .buf = b, .len = count + 4 }
-	};
-	int ret;
-
-	b[0] = (u8) reg >> 24;
-	b[1] = (u8)(reg >> 16) & 0xff;
-	b[2] = (u8)(reg >> 8) & 0xff;
-	b[3] = (u8) reg & 0xff;
-	memcpy(&b[4], buf, count);
-
-	ret = i2c_transfer(state->i2c_adap, msg, 1);
-
-	if (ret < 0)
-		return -EIO;
-
-	return 0;
-}
-
-static int it913x_write_reg(struct it913x_fe_state *state,
-		u8 pro, u32 reg, u32 data)
-{
-	int ret;
-	u8 b[4];
-	u8 s;
-
-	b[0] = data >> 24;
-	b[1] = (data >> 16) & 0xff;
-	b[2] = (data >> 8) & 0xff;
-	b[3] = data & 0xff;
-	/* expand write as needed */
-	if (data < 0x100)
-		s = 3;
-	else if (data < 0x1000)
-		s = 2;
-	else if (data < 0x100000)
-		s = 1;
-	else
-		s = 0;
-
-	ret = it913x_write(state, pro, reg, &b[s], sizeof(b) - s);
-
-	return ret;
-}
-
-static int it913x_fe_script_loader(struct it913x_fe_state *state,
-		struct it913xset *loadscript)
-{
-	int ret, i;
-	if (loadscript == NULL)
-		return -EINVAL;
-
-	for (i = 0; i < 1000; ++i) {
-		if (loadscript[i].pro == 0xff)
-			break;
-		ret = it913x_write(state, loadscript[i].pro,
-			loadscript[i].address,
-			loadscript[i].reg, loadscript[i].count);
-		if (ret < 0)
-			return -ENODEV;
-	}
-	return 0;
-}
-
-static int it913x_init_tuner(struct it913x_fe_state *state)
-{
-	int ret, i, reg;
-	u8 val, nv_val;
-	u8 nv[] = {48, 32, 24, 16, 12, 8, 6, 4, 2};
-	u8 b[2];
-
-	reg = it913x_read_reg_u8(state, 0xec86);
-	switch (reg) {
-	case 0:
-		state->tun_clk_mode = reg;
-		state->tun_xtal = 2000;
-		state->tun_fdiv = 3;
-		val = 16;
-		break;
-	case -ENODEV:
-		return -ENODEV;
-	case 1:
-	default:
-		state->tun_clk_mode = reg;
-		state->tun_xtal = 640;
-		state->tun_fdiv = 1;
-		val = 6;
-		break;
-	}
-
-	reg = it913x_read_reg_u8(state, 0xed03);
-
-	if (reg < 0)
-		return -ENODEV;
-	else if (reg < sizeof(nv))
-		nv_val = nv[reg];
-	else
-		nv_val = 2;
-
-	for (i = 0; i < 50; i++) {
-		ret = it913x_read_reg(state, 0xed23, &b[0], sizeof(b));
-		reg = (b[1] << 8) + b[0];
-		if (reg > 0)
-			break;
-		if (ret < 0)
-			return -ENODEV;
-		udelay(2000);
-	}
-	state->tun_fn_min = state->tun_xtal * reg;
-	state->tun_fn_min /= (state->tun_fdiv * nv_val);
-	deb_info("Tuner fn_min %d", state->tun_fn_min);
-
-	if (state->config->chip_ver > 1)
-		msleep(50);
-	else {
-		for (i = 0; i < 50; i++) {
-			reg = it913x_read_reg_u8(state, 0xec82);
-			if (reg > 0)
-				break;
-			if (reg < 0)
-				return -ENODEV;
-			udelay(2000);
-		}
-	}
-
-	return it913x_write_reg(state, PRO_DMOD, 0xed81, val);
-}
-
-static int it9137_set_tuner(struct it913x_fe_state *state,
-		u32 bandwidth, u32 frequency_m)
-{
-	struct it913xset *set_tuner = set_it9137_template;
-	int ret, reg;
-	u32 frequency = frequency_m / 1000;
-	u32 freq, temp_f, tmp;
-	u16 iqik_m_cal;
-	u16 n_div;
-	u8 n;
-	u8 l_band;
-	u8 lna_band;
-	u8 bw;
-
-	if (state->config->firmware_ver == 1)
-		set_tuner = set_it9135_template;
-	else
-		set_tuner = set_it9137_template;
-
-	deb_info("Tuner Frequency %d Bandwidth %d", frequency, bandwidth);
-
-	if (frequency >= 51000 && frequency <= 440000) {
-		l_band = 0;
-		lna_band = 0;
-	} else if (frequency > 440000 && frequency <= 484000) {
-		l_band = 1;
-		lna_band = 1;
-	} else if (frequency > 484000 && frequency <= 533000) {
-		l_band = 1;
-		lna_band = 2;
-	} else if (frequency > 533000 && frequency <= 587000) {
-		l_band = 1;
-		lna_band = 3;
-	} else if (frequency > 587000 && frequency <= 645000) {
-		l_band = 1;
-		lna_band = 4;
-	} else if (frequency > 645000 && frequency <= 710000) {
-		l_band = 1;
-		lna_band = 5;
-	} else if (frequency > 710000 && frequency <= 782000) {
-		l_band = 1;
-		lna_band = 6;
-	} else if (frequency > 782000 && frequency <= 860000) {
-		l_band = 1;
-		lna_band = 7;
-	} else if (frequency > 1450000 && frequency <= 1492000) {
-		l_band = 1;
-		lna_band = 0;
-	} else if (frequency > 1660000 && frequency <= 1685000) {
-		l_band = 1;
-		lna_band = 1;
-	} else
-		return -EINVAL;
-	set_tuner[0].reg[0] = lna_band;
-
-	switch (bandwidth) {
-	case 5000000:
-		bw = 0;
-		break;
-	case 6000000:
-		bw = 2;
-		break;
-	case 7000000:
-		bw = 4;
-		break;
-	default:
-	case 8000000:
-		bw = 6;
-		break;
-	}
-
-	set_tuner[1].reg[0] = bw;
-	set_tuner[2].reg[0] = 0xa0 | (l_band << 3);
-
-	if (frequency > 53000 && frequency <= 74000) {
-		n_div = 48;
-		n = 0;
-	} else if (frequency > 74000 && frequency <= 111000) {
-		n_div = 32;
-		n = 1;
-	} else if (frequency > 111000 && frequency <= 148000) {
-		n_div = 24;
-		n = 2;
-	} else if (frequency > 148000 && frequency <= 222000) {
-		n_div = 16;
-		n = 3;
-	} else if (frequency > 222000 && frequency <= 296000) {
-		n_div = 12;
-		n = 4;
-	} else if (frequency > 296000 && frequency <= 445000) {
-		n_div = 8;
-		n = 5;
-	} else if (frequency > 445000 && frequency <= state->tun_fn_min) {
-		n_div = 6;
-		n = 6;
-	} else if (frequency > state->tun_fn_min && frequency <= 950000) {
-		n_div = 4;
-		n = 7;
-	} else if (frequency > 1450000 && frequency <= 1680000) {
-		n_div = 2;
-		n = 0;
-	} else
-		return -EINVAL;
-
-	reg = it913x_read_reg_u8(state, 0xed81);
-	iqik_m_cal = (u16)reg * n_div;
-
-	if (reg < 0x20) {
-		if (state->tun_clk_mode == 0)
-			iqik_m_cal = (iqik_m_cal * 9) >> 5;
-		else
-			iqik_m_cal >>= 1;
-	} else {
-		iqik_m_cal = 0x40 - iqik_m_cal;
-		if (state->tun_clk_mode == 0)
-			iqik_m_cal = ~((iqik_m_cal * 9) >> 5);
-		else
-			iqik_m_cal = ~(iqik_m_cal >> 1);
-	}
-
-	temp_f = frequency * (u32)n_div * (u32)state->tun_fdiv;
-	freq = temp_f / state->tun_xtal;
-	tmp = freq * state->tun_xtal;
-
-	if ((temp_f - tmp) >= (state->tun_xtal >> 1))
-		freq++;
-
-	freq += (u32) n << 13;
-	/* Frequency OMEGA_IQIK_M_CAL_MID*/
-	temp_f = freq + (u32)iqik_m_cal;
-
-	set_tuner[3].reg[0] =  temp_f & 0xff;
-	set_tuner[4].reg[0] =  (temp_f >> 8) & 0xff;
-
-	deb_info("High Frequency = %04x", temp_f);
-
-	/* Lower frequency */
-	set_tuner[5].reg[0] =  freq & 0xff;
-	set_tuner[6].reg[0] =  (freq >> 8) & 0xff;
-
-	deb_info("low Frequency = %04x", freq);
-
-	ret = it913x_fe_script_loader(state, set_tuner);
-
-	return (ret < 0) ? -ENODEV : 0;
-}
-
-static int it913x_fe_select_bw(struct it913x_fe_state *state,
-			u32 bandwidth, u32 adcFrequency)
-{
-	int ret, i;
-	u8 buffer[256];
-	u32 coeff[8];
-	u16 bfsfcw_fftinx_ratio;
-	u16 fftinx_bfsfcw_ratio;
-	u8 count;
-	u8 bw;
-	u8 adcmultiplier;
-
-	deb_info("Bandwidth %d Adc %d", bandwidth, adcFrequency);
-
-	switch (bandwidth) {
-	case 5000000:
-		bw = 3;
-		break;
-	case 6000000:
-		bw = 0;
-		break;
-	case 7000000:
-		bw = 1;
-		break;
-	default:
-	case 8000000:
-		bw = 2;
-		break;
-	}
-	ret = it913x_write_reg(state, PRO_DMOD, REG_BW, bw);
-
-	if (state->table == NULL)
-		return -EINVAL;
-
-	/* In write order */
-	coeff[0] = state->table[bw].coeff_1_2048;
-	coeff[1] = state->table[bw].coeff_2_2k;
-	coeff[2] = state->table[bw].coeff_1_8191;
-	coeff[3] = state->table[bw].coeff_1_8192;
-	coeff[4] = state->table[bw].coeff_1_8193;
-	coeff[5] = state->table[bw].coeff_2_8k;
-	coeff[6] = state->table[bw].coeff_1_4096;
-	coeff[7] = state->table[bw].coeff_2_4k;
-	bfsfcw_fftinx_ratio = state->table[bw].bfsfcw_fftinx_ratio;
-	fftinx_bfsfcw_ratio = state->table[bw].fftinx_bfsfcw_ratio;
-
-	/* ADC multiplier */
-	ret = it913x_read_reg_u8(state, ADC_X_2);
-	if (ret < 0)
-		return -EINVAL;
-
-	adcmultiplier = ret;
-
-	count = 0;
-
-	/*  Build Buffer for COEFF Registers */
-	for (i = 0; i < 8; i++) {
-		if (adcmultiplier == 1)
-			coeff[i] /= 2;
-		buffer[count++] = (coeff[i] >> 24) & 0x3;
-		buffer[count++] = (coeff[i] >> 16) & 0xff;
-		buffer[count++] = (coeff[i] >> 8) & 0xff;
-		buffer[count++] = coeff[i] & 0xff;
-	}
-
-	/* bfsfcw_fftinx_ratio register 0x21-0x22 */
-	buffer[count++] = bfsfcw_fftinx_ratio & 0xff;
-	buffer[count++] = (bfsfcw_fftinx_ratio >> 8) & 0xff;
-	/* fftinx_bfsfcw_ratio register 0x23-0x24 */
-	buffer[count++] = fftinx_bfsfcw_ratio & 0xff;
-	buffer[count++] = (fftinx_bfsfcw_ratio >> 8) & 0xff;
-	/* start at COEFF_1_2048 and write through to fftinx_bfsfcw_ratio*/
-	ret = it913x_write(state, PRO_DMOD, COEFF_1_2048, buffer, count);
-
-	for (i = 0; i < 42; i += 8)
-		debug_data_snipet(0x1, "Buffer", &buffer[i]);
-
-	return ret;
-}
-
-
-
-static int it913x_fe_read_status(struct dvb_frontend *fe, fe_status_t *status)
-{
-	struct it913x_fe_state *state = fe->demodulator_priv;
-	int ret, i;
-	fe_status_t old_status = state->it913x_status;
-	*status = 0;
-
-	if (state->it913x_status == 0) {
-		ret = it913x_read_reg_u8(state, EMPTY_CHANNEL_STATUS);
-		if (ret == 0x1) {
-			*status |= FE_HAS_SIGNAL;
-			for (i = 0; i < 40; i++) {
-				ret = it913x_read_reg_u8(state, MP2IF_SYNC_LK);
-				if (ret == 0x1)
-					break;
-				msleep(25);
-			}
-			if (ret == 0x1)
-				*status |= FE_HAS_CARRIER
-					| FE_HAS_VITERBI
-					| FE_HAS_SYNC;
-			state->it913x_status = *status;
-		}
-	}
-
-	if (state->it913x_status & FE_HAS_SYNC) {
-		ret = it913x_read_reg_u8(state, TPSD_LOCK);
-		if (ret == 0x1)
-			*status |= FE_HAS_LOCK
-				| state->it913x_status;
-		else
-			state->it913x_status = 0;
-		if (old_status != state->it913x_status)
-			ret = it913x_write_reg(state, PRO_LINK, GPIOH3_O, ret);
-	}
-
-	return 0;
-}
-
-/* FEC values based on fe_code_rate_t non supported values 0*/
-int it913x_qpsk_pval[] = {0, -93, -91, -90, 0, -89, -88};
-int it913x_16qam_pval[] = {0, -87, -85, -84, 0, -83, -82};
-int it913x_64qam_pval[] = {0, -82, -80, -78, 0, -77, -76};
-
-static int it913x_get_signal_strength(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct it913x_fe_state *state = fe->demodulator_priv;
-	u8 code_rate;
-	int ret, temp;
-	u8 lna_gain_os;
-
-	ret = it913x_read_reg_u8(state, VAR_P_INBAND);
-	if (ret < 0)
-		return ret;
-
-	/* VHF/UHF gain offset */
-	if (state->frequency < 300000000)
-		lna_gain_os = 7;
-	else
-		lna_gain_os = 14;
-
-	temp = (ret - 100) - lna_gain_os;
-
-	if (state->priority == PRIORITY_HIGH)
-		code_rate = p->code_rate_HP;
-	else
-		code_rate = p->code_rate_LP;
-
-	if (code_rate >= ARRAY_SIZE(it913x_qpsk_pval))
-		return -EINVAL;
-
-	deb_info("Reg VAR_P_INBAND:%d Calc Offset Value:%d", ret, temp);
-
-	/* Apply FEC offset values*/
-	switch (p->modulation) {
-	case QPSK:
-		temp -= it913x_qpsk_pval[code_rate];
-		break;
-	case QAM_16:
-		temp -= it913x_16qam_pval[code_rate];
-		break;
-	case QAM_64:
-		temp -= it913x_64qam_pval[code_rate];
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	if (temp < -15)
-		ret = 0;
-	else if ((-15 <= temp) && (temp < 0))
-		ret = (2 * (temp + 15)) / 3;
-	else if ((0 <= temp) && (temp < 20))
-		ret = 4 * temp + 10;
-	else if ((20 <= temp) && (temp < 35))
-		ret = (2 * (temp - 20)) / 3 + 90;
-	else if (temp >= 35)
-		ret = 100;
-
-	deb_info("Signal Strength :%d", ret);
-
-	return ret;
-}
-
-static int it913x_fe_read_signal_strength(struct dvb_frontend *fe,
-		u16 *strength)
-{
-	struct it913x_fe_state *state = fe->demodulator_priv;
-	int ret = 0;
-	if (state->config->read_slevel) {
-		if (state->it913x_status & FE_HAS_SIGNAL)
-			ret = it913x_read_reg_u8(state, SIGNAL_LEVEL);
-	} else
-		ret = it913x_get_signal_strength(fe);
-
-	if (ret >= 0)
-		*strength = (u16)((u32)ret * 0xffff / 0x64);
-
-	return (ret < 0) ? -ENODEV : 0;
-}
-
-static int it913x_fe_read_snr(struct dvb_frontend *fe, u16 *snr)
-{
-	struct it913x_fe_state *state = fe->demodulator_priv;
-	int ret;
-	u8 reg[3];
-	u32 snr_val, snr_min, snr_max;
-	u32 temp;
-
-	ret = it913x_read_reg(state, 0x2c, reg, sizeof(reg));
-
-	snr_val = (u32)(reg[2] << 16) | (reg[1] << 8) | reg[0];
-
-	ret |= it913x_read_reg(state, 0xf78b, reg, 1);
-	if (reg[0])
-		snr_val /= reg[0];
-
-	if (state->transmission_mode == TRANSMISSION_MODE_2K)
-		snr_val *= 4;
-	else if (state->transmission_mode == TRANSMISSION_MODE_4K)
-		snr_val *= 2;
-
-	if (state->constellation == QPSK) {
-		snr_min = 0xb4711;
-		snr_max = 0x191451;
-	} else if (state->constellation == QAM_16) {
-		snr_min = 0x4f0d5;
-		snr_max = 0xc7925;
-	} else if (state->constellation == QAM_64) {
-		snr_min = 0x256d0;
-		snr_max = 0x626be;
-	} else
-		return -EINVAL;
-
-	if (snr_val < snr_min)
-		*snr = 0;
-	else if (snr_val < snr_max) {
-		temp = (snr_val - snr_min) >> 5;
-		temp *= 0xffff;
-		temp /= (snr_max - snr_min) >> 5;
-		*snr = (u16)temp;
-	} else
-		*snr = 0xffff;
-
-	return (ret < 0) ? -ENODEV : 0;
-}
-
-static int it913x_fe_read_ber(struct dvb_frontend *fe, u32 *ber)
-{
-	struct it913x_fe_state *state = fe->demodulator_priv;
-	u8 reg[5];
-	/* Read Aborted Packets and Pre-Viterbi error rate 5 bytes */
-	it913x_read_reg(state, RSD_ABORT_PKT_LSB, reg, sizeof(reg));
-	state->ucblocks += (u32)(reg[1] << 8) | reg[0];
-	*ber = (u32)(reg[4] << 16) | (reg[3] << 8) | reg[2];
-	return 0;
-}
-
-static int it913x_fe_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
-{
-	struct it913x_fe_state *state = fe->demodulator_priv;
-	int ret;
-	u8 reg[2];
-	/* Aborted Packets */
-	ret = it913x_read_reg(state, RSD_ABORT_PKT_LSB, reg, sizeof(reg));
-	state->ucblocks += (u32)(reg[1] << 8) | reg[0];
-	*ucblocks = state->ucblocks;
-	return ret;
-}
-
-static int it913x_fe_get_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct it913x_fe_state *state = fe->demodulator_priv;
-	u8 reg[8];
-
-	it913x_read_reg(state, REG_TPSD_TX_MODE, reg, sizeof(reg));
-
-	if (reg[3] < 3)
-		p->modulation = fe_con[reg[3]];
-
-	if (reg[0] < 3)
-		p->transmission_mode = fe_mode[reg[0]];
-
-	if (reg[1] < 4)
-		p->guard_interval = fe_gi[reg[1]];
-
-	if (reg[2] < 4)
-		p->hierarchy = fe_hi[reg[2]];
-
-	state->priority = reg[5];
-
-	p->code_rate_HP = (reg[6] < 6) ? fe_code[reg[6]] : FEC_NONE;
-	p->code_rate_LP = (reg[7] < 6) ? fe_code[reg[7]] : FEC_NONE;
-
-	/* Update internal state to reflect the autodetected props */
-	state->constellation = p->modulation;
-	state->transmission_mode = p->transmission_mode;
-
-	return 0;
-}
-
-static int it913x_fe_set_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct it913x_fe_state *state = fe->demodulator_priv;
-	int i;
-	u8 empty_ch, last_ch;
-
-	state->it913x_status = 0;
-
-	/* Set bw*/
-	it913x_fe_select_bw(state, p->bandwidth_hz,
-		state->adcFrequency);
-
-	/* Training Mode Off */
-	it913x_write_reg(state, PRO_LINK, TRAINING_MODE, 0x0);
-
-	/* Clear Empty Channel */
-	it913x_write_reg(state, PRO_DMOD, EMPTY_CHANNEL_STATUS, 0x0);
-
-	/* Clear bits */
-	it913x_write_reg(state, PRO_DMOD, MP2IF_SYNC_LK, 0x0);
-	/* LED on */
-	it913x_write_reg(state, PRO_LINK, GPIOH3_O, 0x1);
-	/* Select Band*/
-	if ((p->frequency >= 51000000) && (p->frequency <= 230000000))
-		i = 0;
-	else if ((p->frequency >= 350000000) && (p->frequency <= 900000000))
-			i = 1;
-	else if ((p->frequency >= 1450000000) && (p->frequency <= 1680000000))
-			i = 2;
-	else
-		return -EOPNOTSUPP;
-
-	it913x_write_reg(state, PRO_DMOD, FREE_BAND, i);
-
-	deb_info("Frontend Set Tuner Type %02x", state->tuner_type);
-	switch (state->tuner_type) {
-	case IT9135_38:
-	case IT9135_51:
-	case IT9135_52:
-	case IT9135_60:
-	case IT9135_61:
-	case IT9135_62:
-		it9137_set_tuner(state,
-			p->bandwidth_hz, p->frequency);
-		break;
-	default:
-		if (fe->ops.tuner_ops.set_params) {
-			fe->ops.tuner_ops.set_params(fe);
-			if (fe->ops.i2c_gate_ctrl)
-				fe->ops.i2c_gate_ctrl(fe, 0);
-		}
-		break;
-	}
-	/* LED off */
-	it913x_write_reg(state, PRO_LINK, GPIOH3_O, 0x0);
-	/* Trigger ofsm */
-	it913x_write_reg(state, PRO_DMOD, TRIGGER_OFSM, 0x0);
-	last_ch = 2;
-	for (i = 0; i < 40; ++i) {
-		empty_ch = it913x_read_reg_u8(state, EMPTY_CHANNEL_STATUS);
-		if (last_ch == 1 && empty_ch == 1)
-			break;
-		if (last_ch == 2 && empty_ch == 2)
-			return 0;
-		last_ch = empty_ch;
-		msleep(25);
-	}
-	for (i = 0; i < 40; ++i) {
-		if (it913x_read_reg_u8(state, D_TPSD_LOCK) == 1)
-			break;
-		msleep(25);
-	}
-
-	state->frequency = p->frequency;
-	return 0;
-}
-
-static int it913x_fe_suspend(struct it913x_fe_state *state)
-{
-	int ret, i;
-	u8 b;
-
-	ret = it913x_write_reg(state, PRO_DMOD, SUSPEND_FLAG, 0x1);
-
-	ret |= it913x_write_reg(state, PRO_DMOD, TRIGGER_OFSM, 0x0);
-
-	for (i = 0; i < 128; i++) {
-		ret = it913x_read_reg(state, SUSPEND_FLAG, &b, 1);
-		if (ret < 0)
-			return -ENODEV;
-		if (b == 0)
-			break;
-
-	}
-
-	ret |= it913x_write_reg(state, PRO_DMOD, AFE_MEM0, 0x8);
-	/* Turn LED off */
-	ret |= it913x_write_reg(state, PRO_LINK, GPIOH3_O, 0x0);
-
-	ret |= it913x_fe_script_loader(state, it9137_tuner_off);
-
-	return (ret < 0) ? -ENODEV : 0;
-}
-
-/* Power sequence */
-/* Power Up	Tuner on -> Frontend suspend off -> Tuner clk on */
-/* Power Down	Frontend suspend on -> Tuner clk off -> Tuner off */
-
-static int it913x_fe_sleep(struct dvb_frontend *fe)
-{
-	struct it913x_fe_state *state = fe->demodulator_priv;
-	return it913x_fe_suspend(state);
-}
-
-static u32 compute_div(u32 a, u32 b, u32 x)
-{
-	u32 res = 0;
-	u32 c = 0;
-	u32 i = 0;
-
-	if (a > b) {
-		c = a / b;
-		a = a - c * b;
-	}
-
-	for (i = 0; i < x; i++) {
-		if (a >= b) {
-			res += 1;
-			a -= b;
-		}
-		a <<= 1;
-		res <<= 1;
-	}
-
-	res = (c << x) + res;
-
-	return res;
-}
-
-static int it913x_fe_start(struct it913x_fe_state *state)
-{
-	struct it913xset *set_lna;
-	struct it913xset *set_mode;
-	int ret;
-	u8 adf = (state->config->adf & 0xf);
-	u32 adc, xtal;
-	u8 b[4];
-
-	if (state->config->chip_ver == 1)
-		ret = it913x_init_tuner(state);
-
-	info("ADF table value	:%02x", adf);
-
-	if (adf < 10) {
-		state->crystalFrequency = fe_clockTable[adf].xtal ;
-		state->table = fe_clockTable[adf].table;
-		state->adcFrequency = state->table->adcFrequency;
-
-		adc = compute_div(state->adcFrequency, 1000000ul, 19ul);
-		xtal = compute_div(state->crystalFrequency, 1000000ul, 19ul);
-
-	} else
-		return -EINVAL;
-
-	/* Set LED indicator on GPIOH3 */
-	ret = it913x_write_reg(state, PRO_LINK, GPIOH3_EN, 0x1);
-	ret |= it913x_write_reg(state, PRO_LINK, GPIOH3_ON, 0x1);
-	ret |= it913x_write_reg(state, PRO_LINK, GPIOH3_O, 0x1);
-
-	ret |= it913x_write_reg(state, PRO_LINK, 0xf641, state->tuner_type);
-	ret |= it913x_write_reg(state, PRO_DMOD, 0xf5ca, 0x01);
-	ret |= it913x_write_reg(state, PRO_DMOD, 0xf715, 0x01);
-
-	b[0] = xtal & 0xff;
-	b[1] = (xtal >> 8) & 0xff;
-	b[2] = (xtal >> 16) & 0xff;
-	b[3] = (xtal >> 24);
-	ret |= it913x_write(state, PRO_DMOD, XTAL_CLK, b , 4);
-
-	b[0] = adc & 0xff;
-	b[1] = (adc >> 8) & 0xff;
-	b[2] = (adc >> 16) & 0xff;
-	ret |= it913x_write(state, PRO_DMOD, ADC_FREQ, b, 3);
-
-	if (state->config->adc_x2)
-		ret |= it913x_write_reg(state, PRO_DMOD, ADC_X_2, 0x01);
-	b[0] = 0;
-	b[1] = 0;
-	b[2] = 0;
-	ret |= it913x_write(state, PRO_DMOD, 0x0029, b, 3);
-
-	info("Crystal Frequency :%d Adc Frequency :%d ADC X2: %02x",
-		state->crystalFrequency, state->adcFrequency,
-			state->config->adc_x2);
-	deb_info("Xtal value :%04x Adc value :%04x", xtal, adc);
-
-	if (ret < 0)
-		return -ENODEV;
-
-	/* v1 or v2 tuner script */
-	if (state->config->chip_ver > 1)
-		ret = it913x_fe_script_loader(state, it9135_v2);
-	else
-		ret = it913x_fe_script_loader(state, it9135_v1);
-	if (ret < 0)
-		return ret;
-
-	/* LNA Scripts */
-	switch (state->tuner_type) {
-	case IT9135_51:
-		set_lna = it9135_51;
-		break;
-	case IT9135_52:
-		set_lna = it9135_52;
-		break;
-	case IT9135_60:
-		set_lna = it9135_60;
-		break;
-	case IT9135_61:
-		set_lna = it9135_61;
-		break;
-	case IT9135_62:
-		set_lna = it9135_62;
-		break;
-	case IT9135_38:
-	default:
-		set_lna = it9135_38;
-	}
-	info("Tuner LNA type :%02x", state->tuner_type);
-
-	ret = it913x_fe_script_loader(state, set_lna);
-	if (ret < 0)
-		return ret;
-
-	if (state->config->chip_ver == 2) {
-		ret = it913x_write_reg(state, PRO_DMOD, TRIGGER_OFSM, 0x1);
-		ret |= it913x_write_reg(state, PRO_LINK, PADODPU, 0x0);
-		ret |= it913x_write_reg(state, PRO_LINK, AGC_O_D, 0x0);
-		ret |= it913x_init_tuner(state);
-	}
-	if (ret < 0)
-		return -ENODEV;
-
-	/* Always solo frontend */
-	set_mode = set_solo_fe;
-	ret |= it913x_fe_script_loader(state, set_mode);
-
-	ret |= it913x_fe_suspend(state);
-	return (ret < 0) ? -ENODEV : 0;
-}
-
-static int it913x_fe_init(struct dvb_frontend *fe)
-{
-	struct it913x_fe_state *state = fe->demodulator_priv;
-	int ret = 0;
-	/* Power Up Tuner - common all versions */
-	ret = it913x_write_reg(state, PRO_DMOD, 0xec40, 0x1);
-
-	ret |= it913x_fe_script_loader(state, init_1);
-
-	ret |= it913x_write_reg(state, PRO_DMOD, AFE_MEM0, 0x0);
-
-	ret |= it913x_write_reg(state, PRO_DMOD, 0xfba8, 0x0);
-
-	return (ret < 0) ? -ENODEV : 0;
-}
-
-static void it913x_fe_release(struct dvb_frontend *fe)
-{
-	struct it913x_fe_state *state = fe->demodulator_priv;
-	kfree(state);
-}
-
-static struct dvb_frontend_ops it913x_fe_ofdm_ops;
-
-struct dvb_frontend *it913x_fe_attach(struct i2c_adapter *i2c_adap,
-		u8 i2c_addr, struct ite_config *config)
-{
-	struct it913x_fe_state *state = NULL;
-	int ret;
-
-	/* allocate memory for the internal state */
-	state = kzalloc(sizeof(struct it913x_fe_state), GFP_KERNEL);
-	if (state == NULL)
-		return NULL;
-	if (config == NULL)
-		goto error;
-
-	state->i2c_adap = i2c_adap;
-	state->i2c_addr = i2c_addr;
-	state->config = config;
-
-	switch (state->config->tuner_id_0) {
-	case IT9135_51:
-	case IT9135_52:
-	case IT9135_60:
-	case IT9135_61:
-	case IT9135_62:
-		state->tuner_type = state->config->tuner_id_0;
-		break;
-	default:
-	case IT9135_38:
-		state->tuner_type = IT9135_38;
-	}
-
-	ret = it913x_fe_start(state);
-	if (ret < 0)
-		goto error;
-
-
-	/* create dvb_frontend */
-	memcpy(&state->frontend.ops, &it913x_fe_ofdm_ops,
-			sizeof(struct dvb_frontend_ops));
-	state->frontend.demodulator_priv = state;
-
-	return &state->frontend;
-error:
-	kfree(state);
-	return NULL;
-}
-EXPORT_SYMBOL(it913x_fe_attach);
-
-static struct dvb_frontend_ops it913x_fe_ofdm_ops = {
-	.delsys = { SYS_DVBT },
-	.info = {
-		.name			= "it913x-fe DVB-T",
-		.frequency_min		= 51000000,
-		.frequency_max		= 1680000000,
-		.frequency_stepsize	= 62500,
-		.caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
-			FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
-			FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO |
-			FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
-			FE_CAN_TRANSMISSION_MODE_AUTO |
-			FE_CAN_GUARD_INTERVAL_AUTO |
-			FE_CAN_HIERARCHY_AUTO,
-	},
-
-	.release = it913x_fe_release,
-
-	.init = it913x_fe_init,
-	.sleep = it913x_fe_sleep,
-
-	.set_frontend = it913x_fe_set_frontend,
-	.get_frontend = it913x_fe_get_frontend,
-
-	.read_status = it913x_fe_read_status,
-	.read_signal_strength = it913x_fe_read_signal_strength,
-	.read_snr = it913x_fe_read_snr,
-	.read_ber = it913x_fe_read_ber,
-	.read_ucblocks = it913x_fe_read_ucblocks,
-};
-
-MODULE_DESCRIPTION("it913x Frontend and it9137 tuner");
-MODULE_AUTHOR("Malcolm Priestley tvboxspy@gmail.com");
-MODULE_VERSION("1.15");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/it913x-fe.h b/drivers/media/dvb/frontends/it913x-fe.h
deleted file mode 100644
index 07fa459..0000000
--- a/drivers/media/dvb/frontends/it913x-fe.h
+++ /dev/null
@@ -1,237 +0,0 @@
-/*
- *  Driver for it913x Frontend
- *
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the 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 IT913X_FE_H
-#define IT913X_FE_H
-
-#include <linux/dvb/frontend.h>
-#include "dvb_frontend.h"
-
-struct ite_config {
-	u8 chip_ver;
-	u16 chip_type;
-	u32 firmware;
-	u8 firmware_ver;
-	u8 adc_x2;
-	u8 tuner_id_0;
-	u8 tuner_id_1;
-	u8 dual_mode;
-	u8 adf;
-	/* option to read SIGNAL_LEVEL */
-	u8 read_slevel;
-};
-
-#if defined(CONFIG_DVB_IT913X_FE) || (defined(CONFIG_DVB_IT913X_FE_MODULE) && \
-defined(MODULE))
-extern struct dvb_frontend *it913x_fe_attach(struct i2c_adapter *i2c_adap,
-			u8 i2c_addr, struct ite_config *config);
-#else
-static inline struct dvb_frontend *it913x_fe_attach(
-		struct i2c_adapter *i2c_adap,
-			u8 i2c_addr, struct ite_config *config)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif /* CONFIG_IT913X_FE */
-#define I2C_BASE_ADDR		0x10
-#define DEV_0			0x0
-#define DEV_1			0x10
-#define PRO_LINK		0x0
-#define PRO_DMOD		0x1
-#define DEV_0_DMOD		(PRO_DMOD << 0x7)
-#define DEV_1_DMOD		(DEV_0_DMOD | DEV_1)
-#define CHIP2_I2C_ADDR		0x3a
-
-#define AFE_MEM0		0xfb24
-
-#define MP2_SW_RST		0xf99d
-#define MP2IF2_SW_RST		0xf9a4
-
-#define	PADODPU			0xd827
-#define THIRDODPU		0xd828
-#define AGC_O_D			0xd829
-
-#define EP0_TX_EN		0xdd11
-#define EP0_TX_NAK		0xdd13
-#define EP4_TX_LEN_LSB		0xdd88
-#define EP4_TX_LEN_MSB		0xdd89
-#define EP4_MAX_PKT		0xdd0c
-#define EP5_TX_LEN_LSB		0xdd8a
-#define EP5_TX_LEN_MSB		0xdd8b
-#define EP5_MAX_PKT		0xdd0d
-
-#define IO_MUX_POWER_CLK	0xd800
-#define CLK_O_EN		0xd81a
-#define I2C_CLK			0xf103
-#define I2C_CLK_100		0x7
-#define I2C_CLK_400		0x1a
-
-#define D_TPSD_LOCK		0xf5a9
-#define MP2IF2_EN		0xf9a3
-#define MP2IF_SERIAL		0xf985
-#define TSIS_ENABLE		0xf9cd
-#define MP2IF2_HALF_PSB		0xf9a5
-#define MP2IF_STOP_EN		0xf9b5
-#define MPEG_FULL_SPEED		0xf990
-#define TOP_HOSTB_SER_MODE	0xd91c
-
-#define PID_RST			0xf992
-#define PID_EN			0xf993
-#define PID_INX_EN		0xf994
-#define PID_INX			0xf995
-#define PID_LSB			0xf996
-#define PID_MSB			0xf997
-
-#define MP2IF_MPEG_PAR_MODE	0xf986
-#define DCA_UPPER_CHIP		0xf731
-#define DCA_LOWER_CHIP		0xf732
-#define DCA_PLATCH		0xf730
-#define DCA_FPGA_LATCH		0xf778
-#define DCA_STAND_ALONE		0xf73c
-#define DCA_ENABLE		0xf776
-
-#define DVBT_INTEN		0xf41f
-#define DVBT_ENABLE		0xf41a
-#define HOSTB_DCA_LOWER		0xd91f
-#define HOSTB_MPEG_PAR_MODE	0xd91b
-#define HOSTB_MPEG_SER_MODE	0xd91c
-#define HOSTB_MPEG_SER_DO7	0xd91d
-#define HOSTB_DCA_UPPER		0xd91e
-#define PADMISCDR2		0xd830
-#define PADMISCDR4		0xd831
-#define PADMISCDR8		0xd832
-#define PADMISCDRSR		0xd833
-#define LOCK3_OUT		0xd8fd
-
-#define GPIOH1_O		0xd8af
-#define GPIOH1_EN		0xd8b0
-#define GPIOH1_ON		0xd8b1
-#define GPIOH3_O		0xd8b3
-#define GPIOH3_EN		0xd8b4
-#define GPIOH3_ON		0xd8b5
-#define GPIOH5_O		0xd8bb
-#define GPIOH5_EN		0xd8bc
-#define GPIOH5_ON		0xd8bd
-
-#define AFE_MEM0		0xfb24
-
-#define REG_TPSD_TX_MODE	0xf900
-#define REG_TPSD_GI		0xf901
-#define REG_TPSD_HIER		0xf902
-#define REG_TPSD_CONST		0xf903
-#define REG_BW			0xf904
-#define REG_PRIV		0xf905
-#define REG_TPSD_HP_CODE	0xf906
-#define REG_TPSD_LP_CODE	0xf907
-
-#define MP2IF_SYNC_LK		0xf999
-#define ADC_FREQ		0xf1cd
-
-#define TRIGGER_OFSM		0x0000
-/* COEFF Registers start at 0x0001 to 0x0020 */
-#define COEFF_1_2048		0x0001
-#define XTAL_CLK		0x0025
-#define BFS_FCW			0x0029
-
-/* Error Regs */
-#define RSD_ABORT_PKT_LSB	0x0032
-#define RSD_ABORT_PKT_MSB	0x0033
-#define RSD_BIT_ERR_0_7		0x0034
-#define RSD_BIT_ERR_8_15	0x0035
-#define RSD_BIT_ERR_23_16	0x0036
-#define RSD_BIT_COUNT_LSB	0x0037
-#define RSD_BIT_COUNT_MSB	0x0038
-
-#define TPSD_LOCK		0x003c
-#define TRAINING_MODE		0x0040
-#define ADC_X_2			0x0045
-#define TUNER_ID		0x0046
-#define EMPTY_CHANNEL_STATUS	0x0047
-#define SIGNAL_LEVEL		0x0048
-#define SIGNAL_QUALITY		0x0049
-#define EST_SIGNAL_LEVEL	0x004a
-#define FREE_BAND		0x004b
-#define SUSPEND_FLAG		0x004c
-#define VAR_P_INBAND		0x00f7
-
-/* Build in tuner types */
-#define IT9137 0x38
-#define IT9135_38 0x38
-#define IT9135_51 0x51
-#define IT9135_52 0x52
-#define IT9135_60 0x60
-#define IT9135_61 0x61
-#define IT9135_62 0x62
-
-enum {
-	CMD_DEMOD_READ = 0,
-	CMD_DEMOD_WRITE,
-	CMD_TUNER_READ,
-	CMD_TUNER_WRITE,
-	CMD_REG_EEPROM_READ,
-	CMD_REG_EEPROM_WRITE,
-	CMD_DATA_READ,
-	CMD_VAR_READ = 8,
-	CMD_VAR_WRITE,
-	CMD_PLATFORM_GET,
-	CMD_PLATFORM_SET,
-	CMD_IP_CACHE,
-	CMD_IP_ADD,
-	CMD_IP_REMOVE,
-	CMD_PID_ADD,
-	CMD_PID_REMOVE,
-	CMD_SIPSI_GET,
-	CMD_SIPSI_MPE_RESET,
-	CMD_H_PID_ADD = 0x15,
-	CMD_H_PID_REMOVE,
-	CMD_ABORT,
-	CMD_IR_GET,
-	CMD_IR_SET,
-	CMD_FW_DOWNLOAD = 0x21,
-	CMD_QUERYINFO,
-	CMD_BOOT,
-	CMD_FW_DOWNLOAD_BEGIN,
-	CMD_FW_DOWNLOAD_END,
-	CMD_RUN_CODE,
-	CMD_SCATTER_READ = 0x28,
-	CMD_SCATTER_WRITE,
-	CMD_GENERIC_READ,
-	CMD_GENERIC_WRITE
-};
-
-enum {
-	READ_LONG,
-	WRITE_LONG,
-	READ_SHORT,
-	WRITE_SHORT,
-	READ_DATA,
-	WRITE_DATA,
-	WRITE_CMD,
-};
-
-enum {
-	IT9135_AUTO = 0,
-	IT9137_FW,
-	IT9135_V1_FW,
-	IT9135_V2_FW,
-};
-
-#endif /* IT913X_FE_H */
diff --git a/drivers/media/dvb/frontends/itd1000.c b/drivers/media/dvb/frontends/itd1000.c
deleted file mode 100644
index 3164575..0000000
--- a/drivers/media/dvb/frontends/itd1000.c
+++ /dev/null
@@ -1,399 +0,0 @@
-/*
- *  Driver for the Integrant ITD1000 "Zero-IF Tuner IC for Direct Broadcast Satellite"
- *
- *  Copyright (c) 2007-8 Patrick Boettcher <pb@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/module.h>
-#include <linux/moduleparam.h>
-#include <linux/delay.h>
-#include <linux/dvb/frontend.h>
-#include <linux/i2c.h>
-#include <linux/slab.h>
-
-#include "dvb_frontend.h"
-
-#include "itd1000.h"
-#include "itd1000_priv.h"
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
-
-#define itd_dbg(args...)  do { \
-	if (debug) { \
-		printk(KERN_DEBUG   "ITD1000: " args);\
-	} \
-} while (0)
-
-#define itd_warn(args...) do { \
-	printk(KERN_WARNING "ITD1000: " args); \
-} while (0)
-
-#define itd_info(args...) do { \
-	printk(KERN_INFO    "ITD1000: " args); \
-} while (0)
-
-/* don't write more than one byte with flexcop behind */
-static int itd1000_write_regs(struct itd1000_state *state, u8 reg, u8 v[], u8 len)
-{
-	u8 buf[1+len];
-	struct i2c_msg msg = {
-		.addr = state->cfg->i2c_address, .flags = 0, .buf = buf, .len = len+1
-	};
-	buf[0] = reg;
-	memcpy(&buf[1], v, len);
-
-	/* itd_dbg("wr %02x: %02x\n", reg, v[0]); */
-
-	if (i2c_transfer(state->i2c, &msg, 1) != 1) {
-		printk(KERN_WARNING "itd1000 I2C write failed\n");
-		return -EREMOTEIO;
-	}
-	return 0;
-}
-
-static int itd1000_read_reg(struct itd1000_state *state, u8 reg)
-{
-	u8 val;
-	struct i2c_msg msg[2] = {
-		{ .addr = state->cfg->i2c_address, .flags = 0,        .buf = &reg, .len = 1 },
-		{ .addr = state->cfg->i2c_address, .flags = I2C_M_RD, .buf = &val, .len = 1 },
-	};
-
-	/* ugly flexcop workaround */
-	itd1000_write_regs(state, (reg - 1) & 0xff, &state->shadow[(reg - 1) & 0xff], 1);
-
-	if (i2c_transfer(state->i2c, msg, 2) != 2) {
-		itd_warn("itd1000 I2C read failed\n");
-		return -EREMOTEIO;
-	}
-	return val;
-}
-
-static inline int itd1000_write_reg(struct itd1000_state *state, u8 r, u8 v)
-{
-	int ret = itd1000_write_regs(state, r, &v, 1);
-	state->shadow[r] = v;
-	return ret;
-}
-
-
-static struct {
-	u32 symbol_rate;
-	u8  pgaext  : 4; /* PLLFH */
-	u8  bbgvmin : 4; /* BBGVMIN */
-} itd1000_lpf_pga[] = {
-	{        0, 0x8, 0x3 },
-	{  5200000, 0x8, 0x3 },
-	{ 12200000, 0x4, 0x3 },
-	{ 15400000, 0x2, 0x3 },
-	{ 19800000, 0x2, 0x3 },
-	{ 21500000, 0x2, 0x3 },
-	{ 24500000, 0x2, 0x3 },
-	{ 28400000, 0x2, 0x3 },
-	{ 33400000, 0x2, 0x3 },
-	{ 34400000, 0x1, 0x4 },
-	{ 34400000, 0x1, 0x4 },
-	{ 38400000, 0x1, 0x4 },
-	{ 38400000, 0x1, 0x4 },
-	{ 40400000, 0x1, 0x4 },
-	{ 45400000, 0x1, 0x4 },
-};
-
-static void itd1000_set_lpf_bw(struct itd1000_state *state, u32 symbol_rate)
-{
-	u8 i;
-	u8 con1    = itd1000_read_reg(state, CON1)    & 0xfd;
-	u8 pllfh   = itd1000_read_reg(state, PLLFH)   & 0x0f;
-	u8 bbgvmin = itd1000_read_reg(state, BBGVMIN) & 0xf0;
-	u8 bw      = itd1000_read_reg(state, BW)      & 0xf0;
-
-	itd_dbg("symbol_rate = %d\n", symbol_rate);
-
-	/* not sure what is that ? - starting to download the table */
-	itd1000_write_reg(state, CON1, con1 | (1 << 1));
-
-	for (i = 0; i < ARRAY_SIZE(itd1000_lpf_pga); i++)
-		if (symbol_rate < itd1000_lpf_pga[i].symbol_rate) {
-			itd_dbg("symrate: index: %d pgaext: %x, bbgvmin: %x\n", i, itd1000_lpf_pga[i].pgaext, itd1000_lpf_pga[i].bbgvmin);
-			itd1000_write_reg(state, PLLFH,   pllfh | (itd1000_lpf_pga[i].pgaext << 4));
-			itd1000_write_reg(state, BBGVMIN, bbgvmin | (itd1000_lpf_pga[i].bbgvmin));
-			itd1000_write_reg(state, BW,      bw | (i & 0x0f));
-			break;
-		}
-
-	itd1000_write_reg(state, CON1, con1 | (0 << 1));
-}
-
-static struct {
-	u8 vcorg;
-	u32 fmax_rg;
-} itd1000_vcorg[] = {
-	{  1,  920000 },
-	{  2,  971000 },
-	{  3, 1031000 },
-	{  4, 1091000 },
-	{  5, 1171000 },
-	{  6, 1281000 },
-	{  7, 1381000 },
-	{  8,  500000 },	/* this is intentional. */
-	{  9, 1451000 },
-	{ 10, 1531000 },
-	{ 11, 1631000 },
-	{ 12, 1741000 },
-	{ 13, 1891000 },
-	{ 14, 2071000 },
-	{ 15, 2250000 },
-};
-
-static void itd1000_set_vco(struct itd1000_state *state, u32 freq_khz)
-{
-	u8 i;
-	u8 gvbb_i2c     = itd1000_read_reg(state, GVBB_I2C) & 0xbf;
-	u8 vco_chp1_i2c = itd1000_read_reg(state, VCO_CHP1_I2C) & 0x0f;
-	u8 adcout;
-
-	/* reserved bit again (reset ?) */
-	itd1000_write_reg(state, GVBB_I2C, gvbb_i2c | (1 << 6));
-
-	for (i = 0; i < ARRAY_SIZE(itd1000_vcorg); i++) {
-		if (freq_khz < itd1000_vcorg[i].fmax_rg) {
-			itd1000_write_reg(state, VCO_CHP1_I2C, vco_chp1_i2c | (itd1000_vcorg[i].vcorg << 4));
-			msleep(1);
-
-			adcout = itd1000_read_reg(state, PLLLOCK) & 0x0f;
-
-			itd_dbg("VCO: %dkHz: %d -> ADCOUT: %d %02x\n", freq_khz, itd1000_vcorg[i].vcorg, adcout, vco_chp1_i2c);
-
-			if (adcout > 13) {
-				if (!(itd1000_vcorg[i].vcorg == 7 || itd1000_vcorg[i].vcorg == 15))
-					itd1000_write_reg(state, VCO_CHP1_I2C, vco_chp1_i2c | ((itd1000_vcorg[i].vcorg + 1) << 4));
-			} else if (adcout < 2) {
-				if (!(itd1000_vcorg[i].vcorg == 1 || itd1000_vcorg[i].vcorg == 9))
-					itd1000_write_reg(state, VCO_CHP1_I2C, vco_chp1_i2c | ((itd1000_vcorg[i].vcorg - 1) << 4));
-			}
-			break;
-		}
-	}
-}
-
-static const struct {
-	u32 freq;
-	u8 values[10]; /* RFTR, RFST1 - RFST9 */
-} itd1000_fre_values[] = {
-	{ 1075000, { 0x59, 0x1d, 0x1c, 0x17, 0x16, 0x0f, 0x0e, 0x0c, 0x0b, 0x0a } },
-	{ 1250000, { 0x89, 0x1e, 0x1d, 0x17, 0x15, 0x0f, 0x0e, 0x0c, 0x0b, 0x0a } },
-	{ 1450000, { 0x89, 0x1e, 0x1d, 0x17, 0x15, 0x0f, 0x0e, 0x0c, 0x0b, 0x0a } },
-	{ 1650000, { 0x69, 0x1e, 0x1d, 0x17, 0x15, 0x0f, 0x0e, 0x0c, 0x0b, 0x0a } },
-	{ 1750000, { 0x69, 0x1e, 0x17, 0x15, 0x14, 0x0f, 0x0e, 0x0c, 0x0b, 0x0a } },
-	{ 1850000, { 0x69, 0x1d, 0x17, 0x16, 0x14, 0x0f, 0x0e, 0x0d, 0x0b, 0x0a } },
-	{ 1900000, { 0x69, 0x1d, 0x17, 0x15, 0x14, 0x0f, 0x0e, 0x0d, 0x0b, 0x0a } },
-	{ 1950000, { 0x69, 0x1d, 0x17, 0x16, 0x14, 0x13, 0x0e, 0x0d, 0x0b, 0x0a } },
-	{ 2050000, { 0x69, 0x1e, 0x1d, 0x17, 0x16, 0x14, 0x13, 0x0e, 0x0b, 0x0a } },
-	{ 2150000, { 0x69, 0x1d, 0x1c, 0x17, 0x15, 0x14, 0x13, 0x0f, 0x0e, 0x0b } }
-};
-
-
-#define FREF 16
-
-static void itd1000_set_lo(struct itd1000_state *state, u32 freq_khz)
-{
-	int i, j;
-	u32 plln, pllf;
-	u64 tmp;
-
-	plln = (freq_khz * 1000) / 2 / FREF;
-
-	/* Compute the factional part times 1000 */
-	tmp  = plln % 1000000;
-	plln /= 1000000;
-
-	tmp *= 1048576;
-	do_div(tmp, 1000000);
-	pllf = (u32) tmp;
-
-	state->frequency = ((plln * 1000) + (pllf * 1000)/1048576) * 2*FREF;
-	itd_dbg("frequency: %dkHz (wanted) %dkHz (set), PLLF = %d, PLLN = %d\n", freq_khz, state->frequency, pllf, plln);
-
-	itd1000_write_reg(state, PLLNH, 0x80); /* PLLNH */;
-	itd1000_write_reg(state, PLLNL, plln & 0xff);
-	itd1000_write_reg(state, PLLFH, (itd1000_read_reg(state, PLLFH) & 0xf0) | ((pllf >> 16) & 0x0f));
-	itd1000_write_reg(state, PLLFM, (pllf >> 8) & 0xff);
-	itd1000_write_reg(state, PLLFL, (pllf >> 0) & 0xff);
-
-	for (i = 0; i < ARRAY_SIZE(itd1000_fre_values); i++) {
-		if (freq_khz <= itd1000_fre_values[i].freq) {
-			itd_dbg("fre_values: %d\n", i);
-			itd1000_write_reg(state, RFTR, itd1000_fre_values[i].values[0]);
-			for (j = 0; j < 9; j++)
-				itd1000_write_reg(state, RFST1+j, itd1000_fre_values[i].values[j+1]);
-			break;
-		}
-	}
-
-	itd1000_set_vco(state, freq_khz);
-}
-
-static int itd1000_set_parameters(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	struct itd1000_state *state = fe->tuner_priv;
-	u8 pllcon1;
-
-	itd1000_set_lo(state, c->frequency);
-	itd1000_set_lpf_bw(state, c->symbol_rate);
-
-	pllcon1 = itd1000_read_reg(state, PLLCON1) & 0x7f;
-	itd1000_write_reg(state, PLLCON1, pllcon1 | (1 << 7));
-	itd1000_write_reg(state, PLLCON1, pllcon1);
-
-	return 0;
-}
-
-static int itd1000_get_frequency(struct dvb_frontend *fe, u32 *frequency)
-{
-	struct itd1000_state *state = fe->tuner_priv;
-	*frequency = state->frequency;
-	return 0;
-}
-
-static int itd1000_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
-{
-	return 0;
-}
-
-static u8 itd1000_init_tab[][2] = {
-	{ PLLCON1,       0x65 }, /* Register does not change */
-	{ PLLNH,         0x80 }, /* Bits [7:6] do not change */
-	{ RESERVED_0X6D, 0x3b },
-	{ VCO_CHP2_I2C,  0x12 },
-	{ 0x72,          0xf9 }, /* No such regsister defined */
-	{ RESERVED_0X73, 0xff },
-	{ RESERVED_0X74, 0xb2 },
-	{ RESERVED_0X75, 0xc7 },
-	{ EXTGVBBRF,     0xf0 },
-	{ DIVAGCCK,      0x80 },
-	{ BBTR,          0xa0 },
-	{ RESERVED_0X7E, 0x4f },
-	{ 0x82,          0x88 }, /* No such regsister defined */
-	{ 0x83,          0x80 }, /* No such regsister defined */
-	{ 0x84,          0x80 }, /* No such regsister defined */
-	{ RESERVED_0X85, 0x74 },
-	{ RESERVED_0X86, 0xff },
-	{ RESERVED_0X88, 0x02 },
-	{ RESERVED_0X89, 0x16 },
-	{ RFST0,         0x1f },
-	{ RESERVED_0X94, 0x66 },
-	{ RESERVED_0X95, 0x66 },
-	{ RESERVED_0X96, 0x77 },
-	{ RESERVED_0X97, 0x99 },
-	{ RESERVED_0X98, 0xff },
-	{ RESERVED_0X99, 0xfc },
-	{ RESERVED_0X9A, 0xba },
-	{ RESERVED_0X9B, 0xaa },
-};
-
-static u8 itd1000_reinit_tab[][2] = {
-	{ VCO_CHP1_I2C, 0x8a },
-	{ BW,           0x87 },
-	{ GVBB_I2C,     0x03 },
-	{ BBGVMIN,      0x03 },
-	{ CON1,         0x2e },
-};
-
-
-static int itd1000_init(struct dvb_frontend *fe)
-{
-	struct itd1000_state *state = fe->tuner_priv;
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(itd1000_init_tab); i++)
-		itd1000_write_reg(state, itd1000_init_tab[i][0], itd1000_init_tab[i][1]);
-
-	for (i = 0; i < ARRAY_SIZE(itd1000_reinit_tab); i++)
-		itd1000_write_reg(state, itd1000_reinit_tab[i][0], itd1000_reinit_tab[i][1]);
-
-	return 0;
-}
-
-static int itd1000_sleep(struct dvb_frontend *fe)
-{
-	return 0;
-}
-
-static int itd1000_release(struct dvb_frontend *fe)
-{
-	kfree(fe->tuner_priv);
-	fe->tuner_priv = NULL;
-	return 0;
-}
-
-static const struct dvb_tuner_ops itd1000_tuner_ops = {
-	.info = {
-		.name           = "Integrant ITD1000",
-		.frequency_min  = 950000,
-		.frequency_max  = 2150000,
-		.frequency_step = 125,     /* kHz for QPSK frontends */
-	},
-
-	.release       = itd1000_release,
-
-	.init          = itd1000_init,
-	.sleep         = itd1000_sleep,
-
-	.set_params    = itd1000_set_parameters,
-	.get_frequency = itd1000_get_frequency,
-	.get_bandwidth = itd1000_get_bandwidth
-};
-
-
-struct dvb_frontend *itd1000_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct itd1000_config *cfg)
-{
-	struct itd1000_state *state = NULL;
-	u8 i = 0;
-
-	state = kzalloc(sizeof(struct itd1000_state), GFP_KERNEL);
-	if (state == NULL)
-		return NULL;
-
-	state->cfg = cfg;
-	state->i2c = i2c;
-
-	i = itd1000_read_reg(state, 0);
-	if (i != 0) {
-		kfree(state);
-		return NULL;
-	}
-	itd_info("successfully identified (ID: %d)\n", i);
-
-	memset(state->shadow, 0xff, sizeof(state->shadow));
-	for (i = 0x65; i < 0x9c; i++)
-		state->shadow[i] = itd1000_read_reg(state, i);
-
-	memcpy(&fe->ops.tuner_ops, &itd1000_tuner_ops, sizeof(struct dvb_tuner_ops));
-
-	fe->tuner_priv = state;
-
-	return fe;
-}
-EXPORT_SYMBOL(itd1000_attach);
-
-MODULE_AUTHOR("Patrick Boettcher <pb@linuxtv.org>");
-MODULE_DESCRIPTION("Integrant ITD1000 driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/itd1000.h b/drivers/media/dvb/frontends/itd1000.h
deleted file mode 100644
index 5e18df0..0000000
--- a/drivers/media/dvb/frontends/itd1000.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- *  Driver for the Integrant ITD1000 "Zero-IF Tuner IC for Direct Broadcast Satellite"
- *
- *  Copyright (c) 2007 Patrick Boettcher <pb@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 ITD1000_H
-#define ITD1000_H
-
-struct dvb_frontend;
-struct i2c_adapter;
-
-struct itd1000_config {
-	u8 i2c_address;
-};
-
-#if defined(CONFIG_DVB_TUNER_ITD1000) || (defined(CONFIG_DVB_TUNER_ITD1000_MODULE) && defined(MODULE))
-extern struct dvb_frontend *itd1000_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct itd1000_config *cfg);
-#else
-static inline struct dvb_frontend *itd1000_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct itd1000_config *cfg)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif
-
-#endif
diff --git a/drivers/media/dvb/frontends/itd1000_priv.h b/drivers/media/dvb/frontends/itd1000_priv.h
deleted file mode 100644
index 08ca851..0000000
--- a/drivers/media/dvb/frontends/itd1000_priv.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- *  Driver for the Integrant ITD1000 "Zero-IF Tuner IC for Direct Broadcast Satellite"
- *
- *  Copyright (c) 2007 Patrick Boettcher <pb@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 ITD1000_PRIV_H
-#define ITD1000_PRIV_H
-
-struct itd1000_state {
-	struct itd1000_config *cfg;
-	struct i2c_adapter    *i2c;
-
-	u32 frequency; /* contains the value resulting from the LO-setting */
-
-	/* ugly workaround for flexcop's incapable i2c-controller
-	 * FIXME, if possible
-	 */
-	u8 shadow[256];
-};
-
-enum itd1000_register {
-	VCO_CHP1 = 0x65,
-	VCO_CHP2,
-	PLLCON1,
-	PLLNH,
-	PLLNL,
-	PLLFH,
-	PLLFM,
-	PLLFL,
-	RESERVED_0X6D,
-	PLLLOCK,
-	VCO_CHP2_I2C,
-	VCO_CHP1_I2C,
-	BW,
-	RESERVED_0X73 = 0x73,
-	RESERVED_0X74,
-	RESERVED_0X75,
-	GVBB,
-	GVRF,
-	GVBB_I2C,
-	EXTGVBBRF,
-	DIVAGCCK,
-	BBTR,
-	RFTR,
-	BBGVMIN,
-	RESERVED_0X7E,
-	RESERVED_0X85 = 0x85,
-	RESERVED_0X86,
-	CON1,
-	RESERVED_0X88,
-	RESERVED_0X89,
-	RFST0,
-	RFST1,
-	RFST2,
-	RFST3,
-	RFST4,
-	RFST5,
-	RFST6,
-	RFST7,
-	RFST8,
-	RFST9,
-	RESERVED_0X94,
-	RESERVED_0X95,
-	RESERVED_0X96,
-	RESERVED_0X97,
-	RESERVED_0X98,
-	RESERVED_0X99,
-	RESERVED_0X9A,
-	RESERVED_0X9B,
-};
-
-#endif
diff --git a/drivers/media/dvb/frontends/ix2505v.c b/drivers/media/dvb/frontends/ix2505v.c
deleted file mode 100644
index bc5a820..0000000
--- a/drivers/media/dvb/frontends/ix2505v.c
+++ /dev/null
@@ -1,325 +0,0 @@
-/**
- * Driver for Sharp IX2505V (marked B0017) DVB-S silicon tuner
- *
- * Copyright (C) 2010 Malcolm Priestley
- *
- * This program is free software; you can 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.
- *
- */
-
-#include <linux/module.h>
-#include <linux/dvb/frontend.h>
-#include <linux/slab.h>
-#include <linux/types.h>
-
-#include "ix2505v.h"
-
-static int ix2505v_debug;
-#define dprintk(level, args...) do { \
-	if (ix2505v_debug & level) \
-		printk(KERN_DEBUG "ix2505v: " args); \
-} while (0)
-
-#define deb_info(args...)  dprintk(0x01, args)
-#define deb_i2c(args...)  dprintk(0x02, args)
-
-struct ix2505v_state {
-	struct i2c_adapter *i2c;
-	const struct ix2505v_config *config;
-	u32 frequency;
-};
-
-/**
- *  Data read format of the Sharp IX2505V B0017
- *
- *  byte1:   1   |   1   |   0   |   0   |   0   |  MA1  |  MA0  |  1
- *  byte2:  POR  |   FL  |  RD2  |  RD1  |  RD0  |   X   |   X   |  X
- *
- *  byte1 = address
- *  byte2;
- *	POR = Power on Reset (VCC H=<2.2v L=>2.2v)
- *	FL  = Phase Lock (H=lock L=unlock)
- *	RD0-2 = Reserved internal operations
- *
- * Only POR can be used to check the tuner is present
- *
- * Caution: after byte2 the I2C reverts to write mode continuing to read
- *          may corrupt tuning data.
- *
- */
-
-static int ix2505v_read_status_reg(struct ix2505v_state *state)
-{
-	u8 addr = state->config->tuner_address;
-	u8 b2[] = {0};
-	int ret;
-
-	struct i2c_msg msg[1] = {
-		{ .addr = addr, .flags = I2C_M_RD, .buf = b2, .len = 1 }
-	};
-
-	ret = i2c_transfer(state->i2c, msg, 1);
-	deb_i2c("Read %s ", __func__);
-
-	return (ret == 1) ? (int) b2[0] : -1;
-}
-
-static int ix2505v_write(struct ix2505v_state *state, u8 buf[], u8 count)
-{
-	struct i2c_msg msg[1] = {
-		{ .addr = state->config->tuner_address, .flags = 0,
-		  .buf = buf, .len = count },
-	};
-
-	int ret;
-
-	ret = i2c_transfer(state->i2c, msg, 1);
-
-	if (ret != 1) {
-		deb_i2c("%s: i2c error, ret=%d\n", __func__, ret);
-		return -EIO;
-	}
-
-	return 0;
-}
-
-static int ix2505v_release(struct dvb_frontend *fe)
-{
-	struct ix2505v_state *state = fe->tuner_priv;
-
-	fe->tuner_priv = NULL;
-	kfree(state);
-
-	return 0;
-}
-
-/**
- *  Data write format of the Sharp IX2505V B0017
- *
- *  byte1:   1   |   1   |   0   |   0   |   0   | 0(MA1)| 0(MA0)|  0
- *  byte2:   0   |  BG1  |  BG2  |   N8  |   N7  |   N6  |  N5   |  N4
- *  byte3:   N3  |   N2  |   N1  |   A5  |   A4  |   A3  |   A2  |  A1
- *  byte4:   1   | 1(C1) | 1(C0) |  PD5  |  PD4  |   TM  | 0(RTS)| 1(REF)
- *  byte5:   BA2 |   BA1 |  BA0  |  PSC  |  PD3  |PD2/TS2|DIV/TS1|PD0/TS0
- *
- *  byte1 = address
- *
- *  Write order
- *  1) byte1 -> byte2 -> byte3 -> byte4 -> byte5
- *  2) byte1 -> byte4 -> byte5 -> byte2 -> byte3
- *  3) byte1 -> byte2 -> byte3 -> byte4
- *  4) byte1 -> byte4 -> byte5 -> byte2
- *  5) byte1 -> byte2 -> byte3
- *  6) byte1 -> byte4 -> byte5
- *  7) byte1 -> byte2
- *  8) byte1 -> byte4
- *
- *  Recommended Setup
- *  1 -> 8 -> 6
- */
-
-static int ix2505v_set_params(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	struct ix2505v_state *state = fe->tuner_priv;
-	u32 frequency = c->frequency;
-	u32 b_w  = (c->symbol_rate * 27) / 32000;
-	u32 div_factor, N , A, x;
-	int ret = 0, len;
-	u8 gain, cc, ref, psc, local_osc, lpf;
-	u8 data[4] = {0};
-
-	if ((frequency < fe->ops.info.frequency_min)
-	||  (frequency > fe->ops.info.frequency_max))
-		return -EINVAL;
-
-	if (state->config->tuner_gain)
-		gain = (state->config->tuner_gain < 4)
-			? state->config->tuner_gain : 0;
-	else
-		gain = 0x0;
-
-	if (state->config->tuner_chargepump)
-		cc = state->config->tuner_chargepump;
-	else
-		cc = 0x3;
-
-	ref = 8; /* REF =1 */
-	psc = 32; /* PSC = 0 */
-
-	div_factor = (frequency * ref) / 40; /* local osc = 4Mhz */
-	x = div_factor / psc;
-	N = x/100;
-	A = ((x - (N * 100)) * psc) / 100;
-
-	data[0] = ((gain & 0x3) << 5) | (N >> 3);
-	data[1] = (N << 5) | (A & 0x1f);
-	data[2] = 0x81 | ((cc & 0x3) << 5) ; /*PD5,PD4 & TM = 0|C1,C0|REF=1*/
-
-	deb_info("Frq=%d x=%d N=%d A=%d\n", frequency, x, N, A);
-
-	if (frequency <= 1065000)
-		local_osc = (6 << 5) | 2;
-	else if (frequency <= 1170000)
-		local_osc = (7 << 5) | 2;
-	else if (frequency <= 1300000)
-		local_osc = (1 << 5);
-	else if (frequency <= 1445000)
-		local_osc = (2 << 5);
-	else if (frequency <= 1607000)
-		local_osc = (3 << 5);
-	else if (frequency <= 1778000)
-		local_osc = (4 << 5);
-	else if (frequency <= 1942000)
-		local_osc = (5 << 5);
-	else		/*frequency up to 2150000*/
-		local_osc = (6 << 5);
-
-	data[3] = local_osc; /* all other bits set 0 */
-
-	if (b_w <= 10000)
-		lpf = 0xc;
-	else if (b_w <= 12000)
-		lpf = 0x2;
-	else if (b_w <= 14000)
-		lpf = 0xa;
-	else if (b_w <= 16000)
-		lpf = 0x6;
-	else if (b_w <= 18000)
-		lpf = 0xe;
-	else if (b_w <= 20000)
-		lpf = 0x1;
-	else if (b_w <= 22000)
-		lpf = 0x9;
-	else if (b_w <= 24000)
-		lpf = 0x5;
-	else if (b_w <= 26000)
-		lpf = 0xd;
-	else if (b_w <= 28000)
-		lpf = 0x3;
-		else
-		lpf = 0xb;
-
-	deb_info("Osc=%x b_w=%x lpf=%x\n", local_osc, b_w, lpf);
-	deb_info("Data 0=[%x%x%x%x]\n", data[0], data[1], data[2], data[3]);
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-
-	len = sizeof(data);
-	ret |= ix2505v_write(state, data, len);
-
-	data[2] |= 0x4; /* set TM = 1 other bits same */
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-
-	len = 1;
-	ret |= ix2505v_write(state, &data[2], len); /* write byte 4 only */
-
-	msleep(10);
-
-	data[2] |= ((lpf >> 2) & 0x3) << 3; /* lpf */
-	data[3] |= (lpf & 0x3) << 2;
-
-	deb_info("Data 2=[%x%x]\n", data[2], data[3]);
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-
-	len = 2;
-	ret |= ix2505v_write(state, &data[2], len); /* write byte 4 & 5 */
-
-	if (state->config->min_delay_ms)
-		msleep(state->config->min_delay_ms);
-
-	state->frequency = frequency;
-
-	return ret;
-}
-
-static int ix2505v_get_frequency(struct dvb_frontend *fe, u32 *frequency)
-{
-	struct ix2505v_state *state = fe->tuner_priv;
-
-	*frequency = state->frequency;
-
-	return 0;
-}
-
-static struct dvb_tuner_ops ix2505v_tuner_ops = {
-	.info = {
-		.name = "Sharp IX2505V (B0017)",
-		.frequency_min = 950000,
-		.frequency_max = 2175000
-	},
-	.release = ix2505v_release,
-	.set_params = ix2505v_set_params,
-	.get_frequency = ix2505v_get_frequency,
-};
-
-struct dvb_frontend *ix2505v_attach(struct dvb_frontend *fe,
-				    const struct ix2505v_config *config,
-				    struct i2c_adapter *i2c)
-{
-	struct ix2505v_state *state = NULL;
-	int ret;
-
-	if (NULL == config) {
-		deb_i2c("%s: no config ", __func__);
-		goto error;
-	}
-
-	state = kzalloc(sizeof(struct ix2505v_state), GFP_KERNEL);
-	if (NULL == state)
-		return NULL;
-
-	state->config = config;
-	state->i2c = i2c;
-
-	if (state->config->tuner_write_only) {
-		if (fe->ops.i2c_gate_ctrl)
-			fe->ops.i2c_gate_ctrl(fe, 1);
-
-		ret = ix2505v_read_status_reg(state);
-
-		if (ret & 0x80) {
-			deb_i2c("%s: No IX2505V found\n", __func__);
-			goto error;
-		}
-
-		if (fe->ops.i2c_gate_ctrl)
-			fe->ops.i2c_gate_ctrl(fe, 0);
-	}
-
-	fe->tuner_priv = state;
-
-	memcpy(&fe->ops.tuner_ops, &ix2505v_tuner_ops,
-		sizeof(struct dvb_tuner_ops));
-	deb_i2c("%s: initialization (%s addr=0x%02x) ok\n",
-		__func__, fe->ops.tuner_ops.info.name, config->tuner_address);
-
-	return fe;
-
-error:
-	kfree(state);
-	return NULL;
-}
-EXPORT_SYMBOL(ix2505v_attach);
-
-module_param_named(debug, ix2505v_debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
-MODULE_DESCRIPTION("DVB IX2505V tuner driver");
-MODULE_AUTHOR("Malcolm Priestley");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/ix2505v.h b/drivers/media/dvb/frontends/ix2505v.h
deleted file mode 100644
index 67e89d6..0000000
--- a/drivers/media/dvb/frontends/ix2505v.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/**
- * Driver for Sharp IX2505V (marked B0017) DVB-S silicon tuner
- *
- * Copyright (C) 2010 Malcolm Priestley
- *
- * This program is free software; you can 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_IX2505V_H
-#define DVB_IX2505V_H
-
-#include <linux/i2c.h>
-#include "dvb_frontend.h"
-
-/**
- * Attach a ix2505v tuner to the supplied frontend structure.
- *
- * @param fe Frontend to attach to.
- * @param config ix2505v_config structure
- * @return FE pointer on success, NULL on failure.
- */
-
-struct ix2505v_config {
-	u8 tuner_address;
-
-	/*Baseband AMP gain control 0/1=0dB(default) 2=-2bB 3=-4dB */
-	u8 tuner_gain;
-
-	/*Charge pump output +/- 0=120 1=260 2=555 3=1200(default) */
-	u8 tuner_chargepump;
-
-	/* delay after tune */
-	int min_delay_ms;
-
-	/* disables reads*/
-	u8 tuner_write_only;
-
-};
-
-#if defined(CONFIG_DVB_IX2505V) || \
-	(defined(CONFIG_DVB_IX2505V_MODULE) && defined(MODULE))
-extern struct dvb_frontend *ix2505v_attach(struct dvb_frontend *fe,
-	const struct ix2505v_config *config, struct i2c_adapter *i2c);
-#else
-static inline struct dvb_frontend *ix2505v_attach(struct dvb_frontend *fe,
-	const struct ix2505v_config *config, struct i2c_adapter *i2c)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif
-
-#endif /* DVB_IX2505V_H */
diff --git a/drivers/media/dvb/frontends/l64781.c b/drivers/media/dvb/frontends/l64781.c
deleted file mode 100644
index 36fcf55..0000000
--- a/drivers/media/dvb/frontends/l64781.c
+++ /dev/null
@@ -1,609 +0,0 @@
-/*
-    driver for LSI L64781 COFDM demodulator
-
-    Copyright (C) 2001 Holger Waechtler for Convergence Integrated Media GmbH
-		       Marko Kohtala <marko.kohtala@luukku.com>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include "dvb_frontend.h"
-#include "l64781.h"
-
-
-struct l64781_state {
-	struct i2c_adapter* i2c;
-	const struct l64781_config* config;
-	struct dvb_frontend frontend;
-
-	/* private demodulator data */
-	unsigned int first:1;
-};
-
-#define dprintk(args...) \
-	do { \
-		if (debug) printk(KERN_DEBUG "l64781: " args); \
-	} while (0)
-
-static int debug;
-
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
-
-
-static int l64781_writereg (struct l64781_state* state, u8 reg, u8 data)
-{
-	int ret;
-	u8 buf [] = { reg, data };
-	struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 };
-
-	if ((ret = i2c_transfer(state->i2c, &msg, 1)) != 1)
-		dprintk ("%s: write_reg error (reg == %02x) = %02x!\n",
-			 __func__, reg, ret);
-
-	return (ret != 1) ? -1 : 0;
-}
-
-static int l64781_readreg (struct l64781_state* state, u8 reg)
-{
-	int ret;
-	u8 b0 [] = { reg };
-	u8 b1 [] = { 0 };
-	struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 },
-			   { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } };
-
-	ret = i2c_transfer(state->i2c, msg, 2);
-
-	if (ret != 2) return ret;
-
-	return b1[0];
-}
-
-static void apply_tps (struct l64781_state* state)
-{
-	l64781_writereg (state, 0x2a, 0x00);
-	l64781_writereg (state, 0x2a, 0x01);
-
-	/* This here is a little bit questionable because it enables
-	   the automatic update of TPS registers. I think we'd need to
-	   handle the IRQ from FE to update some other registers as
-	   well, or at least implement some magic to tuning to correct
-	   to the TPS received from transmission. */
-	l64781_writereg (state, 0x2a, 0x02);
-}
-
-
-static void reset_afc (struct l64781_state* state)
-{
-	/* Set AFC stall for the AFC_INIT_FRQ setting, TIM_STALL for
-	   timing offset */
-	l64781_writereg (state, 0x07, 0x9e); /* stall AFC */
-	l64781_writereg (state, 0x08, 0);    /* AFC INIT FREQ */
-	l64781_writereg (state, 0x09, 0);
-	l64781_writereg (state, 0x0a, 0);
-	l64781_writereg (state, 0x07, 0x8e);
-	l64781_writereg (state, 0x0e, 0);    /* AGC gain to zero in beginning */
-	l64781_writereg (state, 0x11, 0x80); /* stall TIM */
-	l64781_writereg (state, 0x10, 0);    /* TIM_OFFSET_LSB */
-	l64781_writereg (state, 0x12, 0);
-	l64781_writereg (state, 0x13, 0);
-	l64781_writereg (state, 0x11, 0x00);
-}
-
-static int reset_and_configure (struct l64781_state* state)
-{
-	u8 buf [] = { 0x06 };
-	struct i2c_msg msg = { .addr = 0x00, .flags = 0, .buf = buf, .len = 1 };
-	// NOTE: this is correct in writing to address 0x00
-
-	return (i2c_transfer(state->i2c, &msg, 1) == 1) ? 0 : -ENODEV;
-}
-
-static int apply_frontend_param(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct l64781_state* state = fe->demodulator_priv;
-	/* The coderates for FEC_NONE, FEC_4_5 and FEC_FEC_6_7 are arbitrary */
-	static const u8 fec_tab[] = { 7, 0, 1, 2, 9, 3, 10, 4 };
-	/* QPSK, QAM_16, QAM_64 */
-	static const u8 qam_tab [] = { 2, 4, 0, 6 };
-	static const u8 guard_tab [] = { 1, 2, 4, 8 };
-	/* The Grundig 29504-401.04 Tuner comes with 18.432MHz crystal. */
-	static const u32 ppm = 8000;
-	u32 ddfs_offset_fixed;
-/*	u32 ddfs_offset_variable = 0x6000-((1000000UL+ppm)/ */
-/*			bw_tab[p->bandWidth]<<10)/15625; */
-	u32 init_freq;
-	u32 spi_bias;
-	u8 val0x04;
-	u8 val0x05;
-	u8 val0x06;
-	int bw;
-
-	switch (p->bandwidth_hz) {
-	case 8000000:
-		bw = 8;
-		break;
-	case 7000000:
-		bw = 7;
-		break;
-	case 6000000:
-		bw = 6;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	if (fe->ops.tuner_ops.set_params) {
-		fe->ops.tuner_ops.set_params(fe);
-		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
-	}
-
-	if (p->inversion != INVERSION_ON &&
-	    p->inversion != INVERSION_OFF)
-		return -EINVAL;
-
-	if (p->code_rate_HP != FEC_1_2 && p->code_rate_HP != FEC_2_3 &&
-	    p->code_rate_HP != FEC_3_4 && p->code_rate_HP != FEC_5_6 &&
-	    p->code_rate_HP != FEC_7_8)
-		return -EINVAL;
-
-	if (p->hierarchy != HIERARCHY_NONE &&
-	    (p->code_rate_LP != FEC_1_2 && p->code_rate_LP != FEC_2_3 &&
-	     p->code_rate_LP != FEC_3_4 && p->code_rate_LP != FEC_5_6 &&
-	     p->code_rate_LP != FEC_7_8))
-		return -EINVAL;
-
-	if (p->modulation != QPSK && p->modulation != QAM_16 &&
-	    p->modulation != QAM_64)
-		return -EINVAL;
-
-	if (p->transmission_mode != TRANSMISSION_MODE_2K &&
-	    p->transmission_mode != TRANSMISSION_MODE_8K)
-		return -EINVAL;
-
-	if (p->guard_interval < GUARD_INTERVAL_1_32 ||
-	    p->guard_interval > GUARD_INTERVAL_1_4)
-		return -EINVAL;
-
-	if (p->hierarchy < HIERARCHY_NONE ||
-	    p->hierarchy > HIERARCHY_4)
-		return -EINVAL;
-
-	ddfs_offset_fixed = 0x4000-(ppm<<16)/bw/1000000;
-
-	/* This works up to 20000 ppm, it overflows if too large ppm! */
-	init_freq = (((8UL<<25) + (8UL<<19) / 25*ppm / (15625/25)) /
-			bw & 0xFFFFFF);
-
-	/* SPI bias calculation is slightly modified to fit in 32bit */
-	/* will work for high ppm only... */
-	spi_bias = 378 * (1 << 10);
-	spi_bias *= 16;
-	spi_bias *= bw;
-	spi_bias *= qam_tab[p->modulation];
-	spi_bias /= p->code_rate_HP + 1;
-	spi_bias /= (guard_tab[p->guard_interval] + 32);
-	spi_bias *= 1000;
-	spi_bias /= 1000 + ppm/1000;
-	spi_bias *= p->code_rate_HP;
-
-	val0x04 = (p->transmission_mode << 2) | p->guard_interval;
-	val0x05 = fec_tab[p->code_rate_HP];
-
-	if (p->hierarchy != HIERARCHY_NONE)
-		val0x05 |= (p->code_rate_LP - FEC_1_2) << 3;
-
-	val0x06 = (p->hierarchy << 2) | p->modulation;
-
-	l64781_writereg (state, 0x04, val0x04);
-	l64781_writereg (state, 0x05, val0x05);
-	l64781_writereg (state, 0x06, val0x06);
-
-	reset_afc (state);
-
-	/* Technical manual section 2.6.1, TIM_IIR_GAIN optimal values */
-	l64781_writereg (state, 0x15,
-			 p->transmission_mode == TRANSMISSION_MODE_2K ? 1 : 3);
-	l64781_writereg (state, 0x16, init_freq & 0xff);
-	l64781_writereg (state, 0x17, (init_freq >> 8) & 0xff);
-	l64781_writereg (state, 0x18, (init_freq >> 16) & 0xff);
-
-	l64781_writereg (state, 0x1b, spi_bias & 0xff);
-	l64781_writereg (state, 0x1c, (spi_bias >> 8) & 0xff);
-	l64781_writereg (state, 0x1d, ((spi_bias >> 16) & 0x7f) |
-		(p->inversion == INVERSION_ON ? 0x80 : 0x00));
-
-	l64781_writereg (state, 0x22, ddfs_offset_fixed & 0xff);
-	l64781_writereg (state, 0x23, (ddfs_offset_fixed >> 8) & 0x3f);
-
-	l64781_readreg (state, 0x00);  /*  clear interrupt registers... */
-	l64781_readreg (state, 0x01);  /*  dto. */
-
-	apply_tps (state);
-
-	return 0;
-}
-
-static int get_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct l64781_state* state = fe->demodulator_priv;
-	int tmp;
-
-
-	tmp = l64781_readreg(state, 0x04);
-	switch(tmp & 3) {
-	case 0:
-		p->guard_interval = GUARD_INTERVAL_1_32;
-		break;
-	case 1:
-		p->guard_interval = GUARD_INTERVAL_1_16;
-		break;
-	case 2:
-		p->guard_interval = GUARD_INTERVAL_1_8;
-		break;
-	case 3:
-		p->guard_interval = GUARD_INTERVAL_1_4;
-		break;
-	}
-	switch((tmp >> 2) & 3) {
-	case 0:
-		p->transmission_mode = TRANSMISSION_MODE_2K;
-		break;
-	case 1:
-		p->transmission_mode = TRANSMISSION_MODE_8K;
-		break;
-	default:
-		printk(KERN_WARNING "Unexpected value for transmission_mode\n");
-	}
-
-	tmp = l64781_readreg(state, 0x05);
-	switch(tmp & 7) {
-	case 0:
-		p->code_rate_HP = FEC_1_2;
-		break;
-	case 1:
-		p->code_rate_HP = FEC_2_3;
-		break;
-	case 2:
-		p->code_rate_HP = FEC_3_4;
-		break;
-	case 3:
-		p->code_rate_HP = FEC_5_6;
-		break;
-	case 4:
-		p->code_rate_HP = FEC_7_8;
-		break;
-	default:
-		printk("Unexpected value for code_rate_HP\n");
-	}
-	switch((tmp >> 3) & 7) {
-	case 0:
-		p->code_rate_LP = FEC_1_2;
-		break;
-	case 1:
-		p->code_rate_LP = FEC_2_3;
-		break;
-	case 2:
-		p->code_rate_LP = FEC_3_4;
-		break;
-	case 3:
-		p->code_rate_LP = FEC_5_6;
-		break;
-	case 4:
-		p->code_rate_LP = FEC_7_8;
-		break;
-	default:
-		printk("Unexpected value for code_rate_LP\n");
-	}
-
-	tmp = l64781_readreg(state, 0x06);
-	switch(tmp & 3) {
-	case 0:
-		p->modulation = QPSK;
-		break;
-	case 1:
-		p->modulation = QAM_16;
-		break;
-	case 2:
-		p->modulation = QAM_64;
-		break;
-	default:
-		printk(KERN_WARNING "Unexpected value for modulation\n");
-	}
-	switch((tmp >> 2) & 7) {
-	case 0:
-		p->hierarchy = HIERARCHY_NONE;
-		break;
-	case 1:
-		p->hierarchy = HIERARCHY_1;
-		break;
-	case 2:
-		p->hierarchy = HIERARCHY_2;
-		break;
-	case 3:
-		p->hierarchy = HIERARCHY_4;
-		break;
-	default:
-		printk("Unexpected value for hierarchy\n");
-	}
-
-
-	tmp = l64781_readreg (state, 0x1d);
-	p->inversion = (tmp & 0x80) ? INVERSION_ON : INVERSION_OFF;
-
-	tmp = (int) (l64781_readreg (state, 0x08) |
-		     (l64781_readreg (state, 0x09) << 8) |
-		     (l64781_readreg (state, 0x0a) << 16));
-	p->frequency += tmp;
-
-	return 0;
-}
-
-static int l64781_read_status(struct dvb_frontend* fe, fe_status_t* status)
-{
-	struct l64781_state* state = fe->demodulator_priv;
-	int sync = l64781_readreg (state, 0x32);
-	int gain = l64781_readreg (state, 0x0e);
-
-	l64781_readreg (state, 0x00);  /*  clear interrupt registers... */
-	l64781_readreg (state, 0x01);  /*  dto. */
-
-	*status = 0;
-
-	if (gain > 5)
-		*status |= FE_HAS_SIGNAL;
-
-	if (sync & 0x02) /* VCXO locked, this criteria should be ok */
-		*status |= FE_HAS_CARRIER;
-
-	if (sync & 0x20)
-		*status |= FE_HAS_VITERBI;
-
-	if (sync & 0x40)
-		*status |= FE_HAS_SYNC;
-
-	if (sync == 0x7f)
-		*status |= FE_HAS_LOCK;
-
-	return 0;
-}
-
-static int l64781_read_ber(struct dvb_frontend* fe, u32* ber)
-{
-	struct l64781_state* state = fe->demodulator_priv;
-
-	/*   XXX FIXME: set up counting period (reg 0x26...0x28)
-	 */
-	*ber = l64781_readreg (state, 0x39)
-	    | (l64781_readreg (state, 0x3a) << 8);
-
-	return 0;
-}
-
-static int l64781_read_signal_strength(struct dvb_frontend* fe, u16* signal_strength)
-{
-	struct l64781_state* state = fe->demodulator_priv;
-
-	u8 gain = l64781_readreg (state, 0x0e);
-	*signal_strength = (gain << 8) | gain;
-
-	return 0;
-}
-
-static int l64781_read_snr(struct dvb_frontend* fe, u16* snr)
-{
-	struct l64781_state* state = fe->demodulator_priv;
-
-	u8 avg_quality = 0xff - l64781_readreg (state, 0x33);
-	*snr = (avg_quality << 8) | avg_quality; /* not exact, but...*/
-
-	return 0;
-}
-
-static int l64781_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
-{
-	struct l64781_state* state = fe->demodulator_priv;
-
-	*ucblocks = l64781_readreg (state, 0x37)
-	   | (l64781_readreg (state, 0x38) << 8);
-
-	return 0;
-}
-
-static int l64781_sleep(struct dvb_frontend* fe)
-{
-	struct l64781_state* state = fe->demodulator_priv;
-
-	/* Power down */
-	return l64781_writereg (state, 0x3e, 0x5a);
-}
-
-static int l64781_init(struct dvb_frontend* fe)
-{
-	struct l64781_state* state = fe->demodulator_priv;
-
-	reset_and_configure (state);
-
-	/* Power up */
-	l64781_writereg (state, 0x3e, 0xa5);
-
-	/* Reset hard */
-	l64781_writereg (state, 0x2a, 0x04);
-	l64781_writereg (state, 0x2a, 0x00);
-
-	/* Set tuner specific things */
-	/* AFC_POL, set also in reset_afc */
-	l64781_writereg (state, 0x07, 0x8e);
-
-	/* Use internal ADC */
-	l64781_writereg (state, 0x0b, 0x81);
-
-	/* AGC loop gain, and polarity is positive */
-	l64781_writereg (state, 0x0c, 0x84);
-
-	/* Internal ADC outputs two's complement */
-	l64781_writereg (state, 0x0d, 0x8c);
-
-	/* With ppm=8000, it seems the DTR_SENSITIVITY will result in
-	   value of 2 with all possible bandwidths and guard
-	   intervals, which is the initial value anyway. */
-	/*l64781_writereg (state, 0x19, 0x92);*/
-
-	/* Everything is two's complement, soft bit and CSI_OUT too */
-	l64781_writereg (state, 0x1e, 0x09);
-
-	/* delay a bit after first init attempt */
-	if (state->first) {
-		state->first = 0;
-		msleep(200);
-	}
-
-	return 0;
-}
-
-static int l64781_get_tune_settings(struct dvb_frontend* fe,
-				    struct dvb_frontend_tune_settings* fesettings)
-{
-	fesettings->min_delay_ms = 4000;
-	fesettings->step_size = 0;
-	fesettings->max_drift = 0;
-	return 0;
-}
-
-static void l64781_release(struct dvb_frontend* fe)
-{
-	struct l64781_state* state = fe->demodulator_priv;
-	kfree(state);
-}
-
-static struct dvb_frontend_ops l64781_ops;
-
-struct dvb_frontend* l64781_attach(const struct l64781_config* config,
-				   struct i2c_adapter* i2c)
-{
-	struct l64781_state* state = NULL;
-	int reg0x3e = -1;
-	u8 b0 [] = { 0x1a };
-	u8 b1 [] = { 0x00 };
-	struct i2c_msg msg [] = { { .addr = config->demod_address, .flags = 0, .buf = b0, .len = 1 },
-			   { .addr = config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } };
-
-	/* allocate memory for the internal state */
-	state = kzalloc(sizeof(struct l64781_state), GFP_KERNEL);
-	if (state == NULL) goto error;
-
-	/* setup the state */
-	state->config = config;
-	state->i2c = i2c;
-	state->first = 1;
-
-	/**
-	 *  the L64781 won't show up before we send the reset_and_configure()
-	 *  broadcast. If nothing responds there is no L64781 on the bus...
-	 */
-	if (reset_and_configure(state) < 0) {
-		dprintk("No response to reset and configure broadcast...\n");
-		goto error;
-	}
-
-	/* The chip always responds to reads */
-	if (i2c_transfer(state->i2c, msg, 2) != 2) {
-		dprintk("No response to read on I2C bus\n");
-		goto error;
-	}
-
-	/* Save current register contents for bailout */
-	reg0x3e = l64781_readreg(state, 0x3e);
-
-	/* Reading the POWER_DOWN register always returns 0 */
-	if (reg0x3e != 0) {
-		dprintk("Device doesn't look like L64781\n");
-		goto error;
-	}
-
-	/* Turn the chip off */
-	l64781_writereg (state, 0x3e, 0x5a);
-
-	/* Responds to all reads with 0 */
-	if (l64781_readreg(state, 0x1a) != 0) {
-		dprintk("Read 1 returned unexpcted value\n");
-		goto error;
-	}
-
-	/* Turn the chip on */
-	l64781_writereg (state, 0x3e, 0xa5);
-
-	/* Responds with register default value */
-	if (l64781_readreg(state, 0x1a) != 0xa1) {
-		dprintk("Read 2 returned unexpcted value\n");
-		goto error;
-	}
-
-	/* create dvb_frontend */
-	memcpy(&state->frontend.ops, &l64781_ops, sizeof(struct dvb_frontend_ops));
-	state->frontend.demodulator_priv = state;
-	return &state->frontend;
-
-error:
-	if (reg0x3e >= 0)
-		l64781_writereg (state, 0x3e, reg0x3e);  /* restore reg 0x3e */
-	kfree(state);
-	return NULL;
-}
-
-static struct dvb_frontend_ops l64781_ops = {
-	.delsys = { SYS_DVBT },
-	.info = {
-		.name = "LSI L64781 DVB-T",
-	/*	.frequency_min = ???,*/
-	/*	.frequency_max = ???,*/
-		.frequency_stepsize = 166666,
-	/*      .frequency_tolerance = ???,*/
-	/*      .symbol_rate_tolerance = ???,*/
-		.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_QAM_16 | FE_CAN_QAM_64 |
-		      FE_CAN_MUTE_TS
-	},
-
-	.release = l64781_release,
-
-	.init = l64781_init,
-	.sleep = l64781_sleep,
-
-	.set_frontend = apply_frontend_param,
-	.get_frontend = get_frontend,
-	.get_tune_settings = l64781_get_tune_settings,
-
-	.read_status = l64781_read_status,
-	.read_ber = l64781_read_ber,
-	.read_signal_strength = l64781_read_signal_strength,
-	.read_snr = l64781_read_snr,
-	.read_ucblocks = l64781_read_ucblocks,
-};
-
-MODULE_DESCRIPTION("LSI L64781 DVB-T Demodulator driver");
-MODULE_AUTHOR("Holger Waechtler, Marko Kohtala");
-MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(l64781_attach);
diff --git a/drivers/media/dvb/frontends/l64781.h b/drivers/media/dvb/frontends/l64781.h
deleted file mode 100644
index 1305a9e..0000000
--- a/drivers/media/dvb/frontends/l64781.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
-    driver for LSI L64781 COFDM demodulator
-
-    Copyright (C) 2001 Holger Waechtler for Convergence Integrated Media GmbH
-		       Marko Kohtala <marko.kohtala@luukku.com>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#ifndef L64781_H
-#define L64781_H
-
-#include <linux/dvb/frontend.h>
-
-struct l64781_config
-{
-	/* the demodulator's i2c address */
-	u8 demod_address;
-};
-
-#if defined(CONFIG_DVB_L64781) || (defined(CONFIG_DVB_L64781_MODULE) && defined(MODULE))
-extern struct dvb_frontend* l64781_attach(const struct l64781_config* config,
-					  struct i2c_adapter* i2c);
-#else
-static inline struct dvb_frontend* l64781_attach(const struct l64781_config* config,
-					  struct i2c_adapter* i2c)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif // CONFIG_DVB_L64781
-
-#endif // L64781_H
diff --git a/drivers/media/dvb/frontends/lg2160.c b/drivers/media/dvb/frontends/lg2160.c
deleted file mode 100644
index cc11260..0000000
--- a/drivers/media/dvb/frontends/lg2160.c
+++ /dev/null
@@ -1,1468 +0,0 @@
-/*
- *    Support for LG2160 - ATSC/MH
- *
- *    Copyright (C) 2010 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/jiffies.h>
-#include <linux/dvb/frontend.h>
-#include "lg2160.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 "lg2160: " 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 lg216x_state {
-	struct i2c_adapter *i2c_adap;
-	const struct lg2160_config *cfg;
-
-	struct dvb_frontend frontend;
-
-	u32 current_frequency;
-	u8 parade_id;
-	u8 fic_ver;
-	unsigned int last_reset;
-};
-
-/* ------------------------------------------------------------------------ */
-
-static int lg216x_write_reg(struct lg216x_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 lg216x_read_reg(struct lg216x_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;
-}
-
-struct lg216x_reg {
-	u16 reg;
-	u8 val;
-};
-
-static int lg216x_write_regs(struct lg216x_state *state,
-			     struct lg216x_reg *regs, int len)
-{
-	int i, ret;
-
-	lg_reg("writing %d registers...\n", len);
-
-	for (i = 0; i < len; i++) {
-		ret = lg216x_write_reg(state, regs[i].reg, regs[i].val);
-		if (lg_fail(ret))
-			return ret;
-	}
-	return 0;
-}
-
-static int lg216x_set_reg_bit(struct lg216x_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 = lg216x_read_reg(state, reg, &val);
-	if (lg_fail(ret))
-		goto fail;
-
-	val &= ~(1 << bit);
-	val |= (onoff & 1) << bit;
-
-	ret = lg216x_write_reg(state, reg, val);
-	lg_fail(ret);
-fail:
-	return ret;
-}
-
-/* ------------------------------------------------------------------------ */
-
-static int lg216x_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
-{
-	struct lg216x_state *state = fe->demodulator_priv;
-	int ret;
-
-	if (state->cfg->deny_i2c_rptr)
-		return 0;
-
-	lg_dbg("(%d)\n", enable);
-
-	ret = lg216x_set_reg_bit(state, 0x0000, 0, enable ? 0 : 1);
-
-	msleep(1);
-
-	return ret;
-}
-
-static int lg216x_soft_reset(struct lg216x_state *state)
-{
-	int ret;
-
-	lg_dbg("\n");
-
-	ret = lg216x_write_reg(state, 0x0002, 0x00);
-	if (lg_fail(ret))
-		goto fail;
-
-	msleep(20);
-	ret = lg216x_write_reg(state, 0x0002, 0x01);
-	if (lg_fail(ret))
-		goto fail;
-
-	state->last_reset = jiffies_to_msecs(jiffies);
-fail:
-	return ret;
-}
-
-static int lg216x_initialize(struct lg216x_state *state)
-{
-	int ret;
-
-	static struct lg216x_reg lg2160_init[] = {
-#if 0
-		{ .reg = 0x0015, .val = 0xe6 },
-#else
-		{ .reg = 0x0015, .val = 0xf7 },
-		{ .reg = 0x001b, .val = 0x52 },
-		{ .reg = 0x0208, .val = 0x00 },
-		{ .reg = 0x0209, .val = 0x82 },
-		{ .reg = 0x0210, .val = 0xf9 },
-		{ .reg = 0x020a, .val = 0x00 },
-		{ .reg = 0x020b, .val = 0x82 },
-		{ .reg = 0x020d, .val = 0x28 },
-		{ .reg = 0x020f, .val = 0x14 },
-#endif
-	};
-
-	static struct lg216x_reg lg2161_init[] = {
-		{ .reg = 0x0000, .val = 0x41 },
-		{ .reg = 0x0001, .val = 0xfb },
-		{ .reg = 0x0216, .val = 0x00 },
-		{ .reg = 0x0219, .val = 0x00 },
-		{ .reg = 0x021b, .val = 0x55 },
-		{ .reg = 0x0606, .val = 0x0a },
-	};
-
-	switch (state->cfg->lg_chip) {
-	case LG2160:
-		ret = lg216x_write_regs(state,
-					lg2160_init, ARRAY_SIZE(lg2160_init));
-		break;
-	case LG2161:
-		ret = lg216x_write_regs(state,
-					lg2161_init, ARRAY_SIZE(lg2161_init));
-		break;
-	default:
-		ret = -EINVAL;
-		break;
-	}
-	if (lg_fail(ret))
-		goto fail;
-
-	ret = lg216x_soft_reset(state);
-	lg_fail(ret);
-fail:
-	return ret;
-}
-
-/* ------------------------------------------------------------------------ */
-
-static int lg216x_set_if(struct lg216x_state *state)
-{
-	u8 val;
-	int ret;
-
-	lg_dbg("%d KHz\n", state->cfg->if_khz);
-
-	ret = lg216x_read_reg(state, 0x0132, &val);
-	if (lg_fail(ret))
-		goto fail;
-
-	val &= 0xfb;
-	val |= (0 == state->cfg->if_khz) ? 0x04 : 0x00;
-
-	ret = lg216x_write_reg(state, 0x0132, val);
-	lg_fail(ret);
-
-	/* if NOT zero IF, 6 MHz is the default */
-fail:
-	return ret;
-}
-
-/* ------------------------------------------------------------------------ */
-
-static int lg2160_agc_fix(struct lg216x_state *state,
-			  int if_agc_fix, int rf_agc_fix)
-{
-	u8 val;
-	int ret;
-
-	ret = lg216x_read_reg(state, 0x0100, &val);
-	if (lg_fail(ret))
-		goto fail;
-
-	val &= 0xf3;
-	val |= (if_agc_fix) ? 0x08 : 0x00;
-	val |= (rf_agc_fix) ? 0x04 : 0x00;
-
-	ret = lg216x_write_reg(state, 0x0100, val);
-	lg_fail(ret);
-fail:
-	return ret;
-}
-
-#if 0
-static int lg2160_agc_freeze(struct lg216x_state *state,
-			     int if_agc_freeze, int rf_agc_freeze)
-{
-	u8 val;
-	int ret;
-
-	ret = lg216x_read_reg(state, 0x0100, &val);
-	if (lg_fail(ret))
-		goto fail;
-
-	val &= 0xcf;
-	val |= (if_agc_freeze) ? 0x20 : 0x00;
-	val |= (rf_agc_freeze) ? 0x10 : 0x00;
-
-	ret = lg216x_write_reg(state, 0x0100, val);
-	lg_fail(ret);
-fail:
-	return ret;
-}
-#endif
-
-static int lg2160_agc_polarity(struct lg216x_state *state,
-			       int if_agc_polarity, int rf_agc_polarity)
-{
-	u8 val;
-	int ret;
-
-	ret = lg216x_read_reg(state, 0x0100, &val);
-	if (lg_fail(ret))
-		goto fail;
-
-	val &= 0xfc;
-	val |= (if_agc_polarity) ? 0x02 : 0x00;
-	val |= (rf_agc_polarity) ? 0x01 : 0x00;
-
-	ret = lg216x_write_reg(state, 0x0100, val);
-	lg_fail(ret);
-fail:
-	return ret;
-}
-
-static int lg2160_tuner_pwr_save_polarity(struct lg216x_state *state,
-					  int polarity)
-{
-	u8 val;
-	int ret;
-
-	ret = lg216x_read_reg(state, 0x0008, &val);
-	if (lg_fail(ret))
-		goto fail;
-
-	val &= 0xfe;
-	val |= (polarity) ? 0x01 : 0x00;
-
-	ret = lg216x_write_reg(state, 0x0008, val);
-	lg_fail(ret);
-fail:
-	return ret;
-}
-
-static int lg2160_spectrum_polarity(struct lg216x_state *state,
-				    int inverted)
-{
-	u8 val;
-	int ret;
-
-	ret = lg216x_read_reg(state, 0x0132, &val);
-	if (lg_fail(ret))
-		goto fail;
-
-	val &= 0xfd;
-	val |= (inverted) ? 0x02 : 0x00;
-
-	ret = lg216x_write_reg(state, 0x0132, val);
-	lg_fail(ret);
-fail:
-	return lg216x_soft_reset(state);
-}
-
-static int lg2160_tuner_pwr_save(struct lg216x_state *state, int onoff)
-{
-	u8 val;
-	int ret;
-
-	ret = lg216x_read_reg(state, 0x0007, &val);
-	if (lg_fail(ret))
-		goto fail;
-
-	val &= 0xbf;
-	val |= (onoff) ? 0x40 : 0x00;
-
-	ret = lg216x_write_reg(state, 0x0007, val);
-	lg_fail(ret);
-fail:
-	return ret;
-}
-
-static int lg216x_set_parade(struct lg216x_state *state, int id)
-{
-	int ret;
-
-	ret = lg216x_write_reg(state, 0x013e, id & 0x7f);
-	if (lg_fail(ret))
-		goto fail;
-
-	state->parade_id = id & 0x7f;
-fail:
-	return ret;
-}
-
-static int lg216x_set_ensemble(struct lg216x_state *state, int id)
-{
-	int ret;
-	u16 reg;
-	u8 val;
-
-	switch (state->cfg->lg_chip) {
-	case LG2160:
-		reg = 0x0400;
-		break;
-	case LG2161:
-	default:
-		reg = 0x0500;
-		break;
-	}
-
-	ret = lg216x_read_reg(state, reg, &val);
-	if (lg_fail(ret))
-		goto fail;
-
-	val &= 0xfe;
-	val |= (id) ? 0x01 : 0x00;
-
-	ret = lg216x_write_reg(state, reg, val);
-	lg_fail(ret);
-fail:
-	return ret;
-}
-
-static int lg2160_set_spi_clock(struct lg216x_state *state)
-{
-	u8 val;
-	int ret;
-
-	ret = lg216x_read_reg(state, 0x0014, &val);
-	if (lg_fail(ret))
-		goto fail;
-
-	val &= 0xf3;
-	val |= (state->cfg->spi_clock << 2);
-
-	ret = lg216x_write_reg(state, 0x0014, val);
-	lg_fail(ret);
-fail:
-	return ret;
-}
-
-static int lg2161_set_output_interface(struct lg216x_state *state)
-{
-	u8 val;
-	int ret;
-
-	ret = lg216x_read_reg(state, 0x0014, &val);
-	if (lg_fail(ret))
-		goto fail;
-
-	val &= ~0x07;
-	val |= state->cfg->output_if; /* FIXME: needs sanity check */
-
-	ret = lg216x_write_reg(state, 0x0014, val);
-	lg_fail(ret);
-fail:
-	return ret;
-}
-
-static int lg216x_enable_fic(struct lg216x_state *state, int onoff)
-{
-	int ret;
-
-	ret = lg216x_write_reg(state, 0x0017, 0x23);
-	if (lg_fail(ret))
-		goto fail;
-
-	ret = lg216x_write_reg(state, 0x0016, 0xfc);
-	if (lg_fail(ret))
-		goto fail;
-
-	switch (state->cfg->lg_chip) {
-	case LG2160:
-		ret = lg216x_write_reg(state, 0x0016,
-				       0xfc | ((onoff) ? 0x02 : 0x00));
-		break;
-	case LG2161:
-		ret = lg216x_write_reg(state, 0x0016, (onoff) ? 0x10 : 0x00);
-		break;
-	}
-	if (lg_fail(ret))
-		goto fail;
-
-	ret = lg216x_initialize(state);
-	if (lg_fail(ret))
-		goto fail;
-
-	if (onoff) {
-		ret = lg216x_write_reg(state, 0x0017, 0x03);
-		lg_fail(ret);
-	}
-fail:
-	return ret;
-}
-
-/* ------------------------------------------------------------------------ */
-
-static int lg216x_get_fic_version(struct lg216x_state *state, u8 *ficver)
-{
-	u8 val;
-	int ret;
-
-	*ficver = 0xff; /* invalid value */
-
-	ret = lg216x_read_reg(state, 0x0128, &val);
-	if (lg_fail(ret))
-		goto fail;
-
-	*ficver = (val >> 3) & 0x1f;
-fail:
-	return ret;
-}
-
-#if 0
-static int lg2160_get_parade_id(struct lg216x_state *state, u8 *id)
-{
-	u8 val;
-	int ret;
-
-	*id = 0xff; /* invalid value */
-
-	ret = lg216x_read_reg(state, 0x0123, &val);
-	if (lg_fail(ret))
-		goto fail;
-
-	*id = val & 0x7f;
-fail:
-	return ret;
-}
-#endif
-
-static int lg216x_get_nog(struct lg216x_state *state, u8 *nog)
-{
-	u8 val;
-	int ret;
-
-	*nog = 0xff; /* invalid value */
-
-	ret = lg216x_read_reg(state, 0x0124, &val);
-	if (lg_fail(ret))
-		goto fail;
-
-	*nog = ((val >> 4) & 0x07) + 1;
-fail:
-	return ret;
-}
-
-static int lg216x_get_tnog(struct lg216x_state *state, u8 *tnog)
-{
-	u8 val;
-	int ret;
-
-	*tnog = 0xff; /* invalid value */
-
-	ret = lg216x_read_reg(state, 0x0125, &val);
-	if (lg_fail(ret))
-		goto fail;
-
-	*tnog = val & 0x1f;
-fail:
-	return ret;
-}
-
-static int lg216x_get_sgn(struct lg216x_state *state, u8 *sgn)
-{
-	u8 val;
-	int ret;
-
-	*sgn = 0xff; /* invalid value */
-
-	ret = lg216x_read_reg(state, 0x0124, &val);
-	if (lg_fail(ret))
-		goto fail;
-
-	*sgn = val & 0x0f;
-fail:
-	return ret;
-}
-
-static int lg216x_get_prc(struct lg216x_state *state, u8 *prc)
-{
-	u8 val;
-	int ret;
-
-	*prc = 0xff; /* invalid value */
-
-	ret = lg216x_read_reg(state, 0x0125, &val);
-	if (lg_fail(ret))
-		goto fail;
-
-	*prc = ((val >> 5) & 0x07) + 1;
-fail:
-	return ret;
-}
-
-/* ------------------------------------------------------------------------ */
-
-static int lg216x_get_rs_frame_mode(struct lg216x_state *state,
-				    enum atscmh_rs_frame_mode *rs_framemode)
-{
-	u8 val;
-	int ret;
-
-	switch (state->cfg->lg_chip) {
-	case LG2160:
-		ret = lg216x_read_reg(state, 0x0410, &val);
-		break;
-	case LG2161:
-		ret = lg216x_read_reg(state, 0x0513, &val);
-		break;
-	default:
-		ret = -EINVAL;
-	}
-	if (lg_fail(ret))
-		goto fail;
-
-	switch ((val >> 4) & 0x03) {
-#if 1
-	default:
-#endif
-	case 0x00:
-		*rs_framemode = ATSCMH_RSFRAME_PRI_ONLY;
-		break;
-	case 0x01:
-		*rs_framemode = ATSCMH_RSFRAME_PRI_SEC;
-		break;
-#if 0
-	default:
-		*rs_framemode = ATSCMH_RSFRAME_RES;
-		break;
-#endif
-	}
-fail:
-	return ret;
-}
-
-static
-int lg216x_get_rs_frame_ensemble(struct lg216x_state *state,
-				 enum atscmh_rs_frame_ensemble *rs_frame_ens)
-{
-	u8 val;
-	int ret;
-
-	switch (state->cfg->lg_chip) {
-	case LG2160:
-		ret = lg216x_read_reg(state, 0x0400, &val);
-		break;
-	case LG2161:
-		ret = lg216x_read_reg(state, 0x0500, &val);
-		break;
-	default:
-		ret = -EINVAL;
-	}
-	if (lg_fail(ret))
-		goto fail;
-
-	val &= 0x01;
-	*rs_frame_ens = (enum atscmh_rs_frame_ensemble) val;
-fail:
-	return ret;
-}
-
-static int lg216x_get_rs_code_mode(struct lg216x_state *state,
-				   enum atscmh_rs_code_mode *rs_code_pri,
-				   enum atscmh_rs_code_mode *rs_code_sec)
-{
-	u8 val;
-	int ret;
-
-	switch (state->cfg->lg_chip) {
-	case LG2160:
-		ret = lg216x_read_reg(state, 0x0410, &val);
-		break;
-	case LG2161:
-		ret = lg216x_read_reg(state, 0x0513, &val);
-		break;
-	default:
-		ret = -EINVAL;
-	}
-	if (lg_fail(ret))
-		goto fail;
-
-	*rs_code_pri = (enum atscmh_rs_code_mode) ((val >> 2) & 0x03);
-	*rs_code_sec = (enum atscmh_rs_code_mode) (val & 0x03);
-fail:
-	return ret;
-}
-
-static int lg216x_get_sccc_block_mode(struct lg216x_state *state,
-				      enum atscmh_sccc_block_mode *sccc_block)
-{
-	u8 val;
-	int ret;
-
-	switch (state->cfg->lg_chip) {
-	case LG2160:
-		ret = lg216x_read_reg(state, 0x0315, &val);
-		break;
-	case LG2161:
-		ret = lg216x_read_reg(state, 0x0511, &val);
-		break;
-	default:
-		ret = -EINVAL;
-	}
-	if (lg_fail(ret))
-		goto fail;
-
-	switch (val & 0x03) {
-	case 0x00:
-		*sccc_block = ATSCMH_SCCC_BLK_SEP;
-		break;
-	case 0x01:
-		*sccc_block = ATSCMH_SCCC_BLK_COMB;
-		break;
-	default:
-		*sccc_block = ATSCMH_SCCC_BLK_RES;
-		break;
-	}
-fail:
-	return ret;
-}
-
-static int lg216x_get_sccc_code_mode(struct lg216x_state *state,
-				     enum atscmh_sccc_code_mode *mode_a,
-				     enum atscmh_sccc_code_mode *mode_b,
-				     enum atscmh_sccc_code_mode *mode_c,
-				     enum atscmh_sccc_code_mode *mode_d)
-{
-	u8 val;
-	int ret;
-
-	switch (state->cfg->lg_chip) {
-	case LG2160:
-		ret = lg216x_read_reg(state, 0x0316, &val);
-		break;
-	case LG2161:
-		ret = lg216x_read_reg(state, 0x0512, &val);
-		break;
-	default:
-		ret = -EINVAL;
-	}
-	if (lg_fail(ret))
-		goto fail;
-
-	switch ((val >> 6) & 0x03) {
-	case 0x00:
-		*mode_a = ATSCMH_SCCC_CODE_HLF;
-		break;
-	case 0x01:
-		*mode_a = ATSCMH_SCCC_CODE_QTR;
-		break;
-	default:
-		*mode_a = ATSCMH_SCCC_CODE_RES;
-		break;
-	}
-
-	switch ((val >> 4) & 0x03) {
-	case 0x00:
-		*mode_b = ATSCMH_SCCC_CODE_HLF;
-		break;
-	case 0x01:
-		*mode_b = ATSCMH_SCCC_CODE_QTR;
-		break;
-	default:
-		*mode_b = ATSCMH_SCCC_CODE_RES;
-		break;
-	}
-
-	switch ((val >> 2) & 0x03) {
-	case 0x00:
-		*mode_c = ATSCMH_SCCC_CODE_HLF;
-		break;
-	case 0x01:
-		*mode_c = ATSCMH_SCCC_CODE_QTR;
-		break;
-	default:
-		*mode_c = ATSCMH_SCCC_CODE_RES;
-		break;
-	}
-
-	switch (val & 0x03) {
-	case 0x00:
-		*mode_d = ATSCMH_SCCC_CODE_HLF;
-		break;
-	case 0x01:
-		*mode_d = ATSCMH_SCCC_CODE_QTR;
-		break;
-	default:
-		*mode_d = ATSCMH_SCCC_CODE_RES;
-		break;
-	}
-fail:
-	return ret;
-}
-
-/* ------------------------------------------------------------------------ */
-
-#if 0
-static int lg216x_read_fic_err_count(struct lg216x_state *state, u8 *err)
-{
-	u8 fic_err;
-	int ret;
-
-	*err = 0;
-
-	switch (state->cfg->lg_chip) {
-	case LG2160:
-		ret = lg216x_read_reg(state, 0x0012, &fic_err);
-		break;
-	case LG2161:
-		ret = lg216x_read_reg(state, 0x001e, &fic_err);
-		break;
-	}
-	if (lg_fail(ret))
-		goto fail;
-
-	*err = fic_err;
-fail:
-	return ret;
-}
-
-static int lg2160_read_crc_err_count(struct lg216x_state *state, u16 *err)
-{
-	u8 crc_err1, crc_err2;
-	int ret;
-
-	*err = 0;
-
-	ret = lg216x_read_reg(state, 0x0411, &crc_err1);
-	if (lg_fail(ret))
-		goto fail;
-
-	ret = lg216x_read_reg(state, 0x0412, &crc_err2);
-	if (lg_fail(ret))
-		goto fail;
-
-	*err = (u16)(((crc_err2 & 0x0f) << 8) | crc_err1);
-fail:
-	return ret;
-}
-
-static int lg2161_read_crc_err_count(struct lg216x_state *state, u16 *err)
-{
-	u8 crc_err;
-	int ret;
-
-	*err = 0;
-
-	ret = lg216x_read_reg(state, 0x0612, &crc_err);
-	if (lg_fail(ret))
-		goto fail;
-
-	*err = (u16)crc_err;
-fail:
-	return ret;
-}
-
-static int lg216x_read_crc_err_count(struct lg216x_state *state, u16 *err)
-{
-	int ret;
-	switch (state->cfg->lg_chip) {
-	case LG2160:
-		ret = lg2160_read_crc_err_count(state, err);
-		break;
-	case LG2161:
-		ret = lg2161_read_crc_err_count(state, err);
-		break;
-	default:
-		ret = -EINVAL;
-		break;
-	}
-	return ret;
-}
-
-static int lg2160_read_rs_err_count(struct lg216x_state *state, u16 *err)
-{
-	u8 rs_err1, rs_err2;
-	int ret;
-
-	*err = 0;
-
-	ret = lg216x_read_reg(state, 0x0413, &rs_err1);
-	if (lg_fail(ret))
-		goto fail;
-
-	ret = lg216x_read_reg(state, 0x0414, &rs_err2);
-	if (lg_fail(ret))
-		goto fail;
-
-	*err = (u16)(((rs_err2 & 0x0f) << 8) | rs_err1);
-fail:
-	return ret;
-}
-
-static int lg2161_read_rs_err_count(struct lg216x_state *state, u16 *err)
-{
-	u8 rs_err1, rs_err2;
-	int ret;
-
-	*err = 0;
-
-	ret = lg216x_read_reg(state, 0x0613, &rs_err1);
-	if (lg_fail(ret))
-		goto fail;
-
-	ret = lg216x_read_reg(state, 0x0614, &rs_err2);
-	if (lg_fail(ret))
-		goto fail;
-
-	*err = (u16)((rs_err1 << 8) | rs_err2);
-fail:
-	return ret;
-}
-
-static int lg216x_read_rs_err_count(struct lg216x_state *state, u16 *err)
-{
-	int ret;
-	switch (state->cfg->lg_chip) {
-	case LG2160:
-		ret = lg2160_read_rs_err_count(state, err);
-		break;
-	case LG2161:
-		ret = lg2161_read_rs_err_count(state, err);
-		break;
-	default:
-		ret = -EINVAL;
-		break;
-	}
-	return ret;
-}
-#endif
-
-/* ------------------------------------------------------------------------ */
-
-static int lg216x_get_frontend(struct dvb_frontend *fe)
-{
-	struct lg216x_state *state = fe->demodulator_priv;
-	int ret;
-
-	lg_dbg("\n");
-
-	fe->dtv_property_cache.modulation = VSB_8;
-	fe->dtv_property_cache.frequency = state->current_frequency;
-	fe->dtv_property_cache.delivery_system = SYS_ATSCMH;
-
-	ret = lg216x_get_fic_version(state,
-				     &fe->dtv_property_cache.atscmh_fic_ver);
-	if (lg_fail(ret))
-		goto fail;
-	if (state->fic_ver != fe->dtv_property_cache.atscmh_fic_ver) {
-		state->fic_ver = fe->dtv_property_cache.atscmh_fic_ver;
-
-#if 0
-		ret = lg2160_get_parade_id(state,
-				&fe->dtv_property_cache.atscmh_parade_id);
-		if (lg_fail(ret))
-			goto fail;
-/* #else */
-		fe->dtv_property_cache.atscmh_parade_id = state->parade_id;
-#endif
-		ret = lg216x_get_nog(state,
-				     &fe->dtv_property_cache.atscmh_nog);
-		if (lg_fail(ret))
-			goto fail;
-		ret = lg216x_get_tnog(state,
-				      &fe->dtv_property_cache.atscmh_tnog);
-		if (lg_fail(ret))
-			goto fail;
-		ret = lg216x_get_sgn(state,
-				     &fe->dtv_property_cache.atscmh_sgn);
-		if (lg_fail(ret))
-			goto fail;
-		ret = lg216x_get_prc(state,
-				     &fe->dtv_property_cache.atscmh_prc);
-		if (lg_fail(ret))
-			goto fail;
-
-		ret = lg216x_get_rs_frame_mode(state,
-			(enum atscmh_rs_frame_mode *)
-			&fe->dtv_property_cache.atscmh_rs_frame_mode);
-		if (lg_fail(ret))
-			goto fail;
-		ret = lg216x_get_rs_frame_ensemble(state,
-			(enum atscmh_rs_frame_ensemble *)
-			&fe->dtv_property_cache.atscmh_rs_frame_ensemble);
-		if (lg_fail(ret))
-			goto fail;
-		ret = lg216x_get_rs_code_mode(state,
-			(enum atscmh_rs_code_mode *)
-			&fe->dtv_property_cache.atscmh_rs_code_mode_pri,
-			(enum atscmh_rs_code_mode *)
-			&fe->dtv_property_cache.atscmh_rs_code_mode_sec);
-		if (lg_fail(ret))
-			goto fail;
-		ret = lg216x_get_sccc_block_mode(state,
-			(enum atscmh_sccc_block_mode *)
-			&fe->dtv_property_cache.atscmh_sccc_block_mode);
-		if (lg_fail(ret))
-			goto fail;
-		ret = lg216x_get_sccc_code_mode(state,
-			(enum atscmh_sccc_code_mode *)
-			&fe->dtv_property_cache.atscmh_sccc_code_mode_a,
-			(enum atscmh_sccc_code_mode *)
-			&fe->dtv_property_cache.atscmh_sccc_code_mode_b,
-			(enum atscmh_sccc_code_mode *)
-			&fe->dtv_property_cache.atscmh_sccc_code_mode_c,
-			(enum atscmh_sccc_code_mode *)
-			&fe->dtv_property_cache.atscmh_sccc_code_mode_d);
-		if (lg_fail(ret))
-			goto fail;
-	}
-#if 0
-	ret = lg216x_read_fic_err_count(state,
-				(u8 *)&fe->dtv_property_cache.atscmh_fic_err);
-	if (lg_fail(ret))
-		goto fail;
-	ret = lg216x_read_crc_err_count(state,
-				&fe->dtv_property_cache.atscmh_crc_err);
-	if (lg_fail(ret))
-		goto fail;
-	ret = lg216x_read_rs_err_count(state,
-				&fe->dtv_property_cache.atscmh_rs_err);
-	if (lg_fail(ret))
-		goto fail;
-
-	switch (state->cfg->lg_chip) {
-	case LG2160:
-		if (((fe->dtv_property_cache.atscmh_rs_err >= 240) &&
-		     (fe->dtv_property_cache.atscmh_crc_err >= 240)) &&
-		    ((jiffies_to_msecs(jiffies) - state->last_reset) > 6000))
-			ret = lg216x_soft_reset(state);
-		break;
-	case LG2161:
-		/* no fix needed here (as far as we know) */
-		ret = 0;
-		break;
-	}
-	lg_fail(ret);
-#endif
-fail:
-	return ret;
-}
-
-static int lg216x_get_property(struct dvb_frontend *fe,
-			       struct dtv_property *tvp)
-{
-	return (DTV_ATSCMH_FIC_VER == tvp->cmd) ?
-		lg216x_get_frontend(fe) : 0;
-}
-
-
-static int lg2160_set_frontend(struct dvb_frontend *fe)
-{
-	struct lg216x_state *state = fe->demodulator_priv;
-	int ret;
-
-	lg_dbg("(%d)\n", fe->dtv_property_cache.frequency);
-
-	if (fe->ops.tuner_ops.set_params) {
-		ret = fe->ops.tuner_ops.set_params(fe);
-		if (fe->ops.i2c_gate_ctrl)
-			fe->ops.i2c_gate_ctrl(fe, 0);
-		if (lg_fail(ret))
-			goto fail;
-		state->current_frequency = fe->dtv_property_cache.frequency;
-	}
-
-	ret = lg2160_agc_fix(state, 0, 0);
-	if (lg_fail(ret))
-		goto fail;
-	ret = lg2160_agc_polarity(state, 0, 0);
-	if (lg_fail(ret))
-		goto fail;
-	ret = lg2160_tuner_pwr_save_polarity(state, 1);
-	if (lg_fail(ret))
-		goto fail;
-	ret = lg216x_set_if(state);
-	if (lg_fail(ret))
-		goto fail;
-	ret = lg2160_spectrum_polarity(state, state->cfg->spectral_inversion);
-	if (lg_fail(ret))
-		goto fail;
-
-	/* be tuned before this point */
-	ret = lg216x_soft_reset(state);
-	if (lg_fail(ret))
-		goto fail;
-
-	ret = lg2160_tuner_pwr_save(state, 0);
-	if (lg_fail(ret))
-		goto fail;
-
-	switch (state->cfg->lg_chip) {
-	case LG2160:
-		ret = lg2160_set_spi_clock(state);
-		if (lg_fail(ret))
-			goto fail;
-		break;
-	case LG2161:
-		ret = lg2161_set_output_interface(state);
-		if (lg_fail(ret))
-			goto fail;
-		break;
-	}
-
-	ret = lg216x_set_parade(state, fe->dtv_property_cache.atscmh_parade_id);
-	if (lg_fail(ret))
-		goto fail;
-
-	ret = lg216x_set_ensemble(state,
-			fe->dtv_property_cache.atscmh_rs_frame_ensemble);
-	if (lg_fail(ret))
-		goto fail;
-
-	ret = lg216x_initialize(state);
-	if (lg_fail(ret))
-		goto fail;
-
-	ret = lg216x_enable_fic(state, 1);
-	lg_fail(ret);
-
-	lg216x_get_frontend(fe);
-fail:
-	return ret;
-}
-
-/* ------------------------------------------------------------------------ */
-
-static int lg2160_read_lock_status(struct lg216x_state *state,
-				   int *acq_lock, int *sync_lock)
-{
-	u8 val;
-	int ret;
-
-	*acq_lock = 0;
-	*sync_lock = 0;
-
-	ret = lg216x_read_reg(state, 0x011b, &val);
-	if (lg_fail(ret))
-		goto fail;
-
-	*sync_lock = (val & 0x20) ? 0 : 1;
-	*acq_lock  = (val & 0x40) ? 0 : 1;
-fail:
-	return ret;
-}
-
-#ifdef USE_LG2161_LOCK_BITS
-static int lg2161_read_lock_status(struct lg216x_state *state,
-				   int *acq_lock, int *sync_lock)
-{
-	u8 val;
-	int ret;
-
-	*acq_lock = 0;
-	*sync_lock = 0;
-
-	ret = lg216x_read_reg(state, 0x0304, &val);
-	if (lg_fail(ret))
-		goto fail;
-
-	*sync_lock = (val & 0x80) ? 0 : 1;
-
-	ret = lg216x_read_reg(state, 0x011b, &val);
-	if (lg_fail(ret))
-		goto fail;
-
-	*acq_lock  = (val & 0x40) ? 0 : 1;
-fail:
-	return ret;
-}
-#endif
-
-static int lg216x_read_lock_status(struct lg216x_state *state,
-				   int *acq_lock, int *sync_lock)
-{
-#ifdef USE_LG2161_LOCK_BITS
-	int ret;
-	switch (state->cfg->lg_chip) {
-	case LG2160:
-		ret = lg2160_read_lock_status(state, acq_lock, sync_lock);
-		break;
-	case LG2161:
-		ret = lg2161_read_lock_status(state, acq_lock, sync_lock);
-		break;
-	default:
-		ret = -EINVAL;
-		break;
-	}
-	return ret;
-#else
-	return lg2160_read_lock_status(state, acq_lock, sync_lock);
-#endif
-}
-
-static int lg216x_read_status(struct dvb_frontend *fe, fe_status_t *status)
-{
-	struct lg216x_state *state = fe->demodulator_priv;
-	int ret, acq_lock, sync_lock;
-
-	*status = 0;
-
-	ret = lg216x_read_lock_status(state, &acq_lock, &sync_lock);
-	if (lg_fail(ret))
-		goto fail;
-
-	lg_dbg("%s%s\n",
-	       acq_lock  ? "SIGNALEXIST " : "",
-	       sync_lock ? "SYNCLOCK"     : "");
-
-	if (acq_lock)
-		*status |= FE_HAS_SIGNAL;
-	if (sync_lock)
-		*status |= FE_HAS_SYNC;
-
-	if (*status)
-		*status |= FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_LOCK;
-
-fail:
-	return ret;
-}
-
-/* ------------------------------------------------------------------------ */
-
-static int lg2160_read_snr(struct dvb_frontend *fe, u16 *snr)
-{
-	struct lg216x_state *state = fe->demodulator_priv;
-	u8 snr1, snr2;
-	int ret;
-
-	*snr = 0;
-
-	ret = lg216x_read_reg(state, 0x0202, &snr1);
-	if (lg_fail(ret))
-		goto fail;
-
-	ret = lg216x_read_reg(state, 0x0203, &snr2);
-	if (lg_fail(ret))
-		goto fail;
-
-	if ((snr1 == 0xba) || (snr2 == 0xdf))
-		*snr = 0;
-	else
-#if 1
-	*snr =  ((snr1 >> 4) * 100) + ((snr1 & 0x0f) * 10) + (snr2 >> 4);
-#else /* BCD */
-	*snr =  (snr2 | (snr1 << 8));
-#endif
-fail:
-	return ret;
-}
-
-static int lg2161_read_snr(struct dvb_frontend *fe, u16 *snr)
-{
-	struct lg216x_state *state = fe->demodulator_priv;
-	u8 snr1, snr2;
-	int ret;
-
-	*snr = 0;
-
-	ret = lg216x_read_reg(state, 0x0302, &snr1);
-	if (lg_fail(ret))
-		goto fail;
-
-	ret = lg216x_read_reg(state, 0x0303, &snr2);
-	if (lg_fail(ret))
-		goto fail;
-
-	if ((snr1 == 0xba) || (snr2 == 0xfd))
-		*snr = 0;
-	else
-
-	*snr =  ((snr1 >> 4) * 100) + ((snr1 & 0x0f) * 10) + (snr2 & 0x0f);
-fail:
-	return ret;
-}
-
-static int lg216x_read_signal_strength(struct dvb_frontend *fe,
-				       u16 *strength)
-{
-#if 0
-	/* 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 lg216x_state *state = fe->demodulator_priv;
-	u16 snr;
-	int ret;
-#endif
-	*strength = 0;
-#if 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;
-#else
-	return 0;
-#endif
-}
-
-/* ------------------------------------------------------------------------ */
-
-static int lg216x_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
-{
-#if 0
-	struct lg216x_state *state = fe->demodulator_priv;
-	int ret;
-
-	ret = lg216x_read_rs_err_count(state,
-				       &fe->dtv_property_cache.atscmh_rs_err);
-	if (lg_fail(ret))
-		goto fail;
-
-	*ucblocks = fe->dtv_property_cache.atscmh_rs_err;
-fail:
-#else
-	*ucblocks = 0;
-#endif
-	return 0;
-}
-
-static int lg216x_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 lg216x_release(struct dvb_frontend *fe)
-{
-	struct lg216x_state *state = fe->demodulator_priv;
-	lg_dbg("\n");
-	kfree(state);
-}
-
-static struct dvb_frontend_ops lg2160_ops = {
-	.delsys = { SYS_ATSCMH },
-	.info = {
-		.name = "LG Electronics LG2160 ATSC/MH Frontend",
-		.frequency_min      = 54000000,
-		.frequency_max      = 858000000,
-		.frequency_stepsize = 62500,
-	},
-	.i2c_gate_ctrl        = lg216x_i2c_gate_ctrl,
-#if 0
-	.init                 = lg216x_init,
-	.sleep                = lg216x_sleep,
-#endif
-	.get_property         = lg216x_get_property,
-
-	.set_frontend         = lg2160_set_frontend,
-	.get_frontend         = lg216x_get_frontend,
-	.get_tune_settings    = lg216x_get_tune_settings,
-	.read_status          = lg216x_read_status,
-#if 0
-	.read_ber             = lg216x_read_ber,
-#endif
-	.read_signal_strength = lg216x_read_signal_strength,
-	.read_snr             = lg2160_read_snr,
-	.read_ucblocks        = lg216x_read_ucblocks,
-	.release              = lg216x_release,
-};
-
-static struct dvb_frontend_ops lg2161_ops = {
-	.delsys = { SYS_ATSCMH },
-	.info = {
-		.name = "LG Electronics LG2161 ATSC/MH Frontend",
-		.frequency_min      = 54000000,
-		.frequency_max      = 858000000,
-		.frequency_stepsize = 62500,
-	},
-	.i2c_gate_ctrl        = lg216x_i2c_gate_ctrl,
-#if 0
-	.init                 = lg216x_init,
-	.sleep                = lg216x_sleep,
-#endif
-	.get_property         = lg216x_get_property,
-
-	.set_frontend         = lg2160_set_frontend,
-	.get_frontend         = lg216x_get_frontend,
-	.get_tune_settings    = lg216x_get_tune_settings,
-	.read_status          = lg216x_read_status,
-#if 0
-	.read_ber             = lg216x_read_ber,
-#endif
-	.read_signal_strength = lg216x_read_signal_strength,
-	.read_snr             = lg2161_read_snr,
-	.read_ucblocks        = lg216x_read_ucblocks,
-	.release              = lg216x_release,
-};
-
-struct dvb_frontend *lg2160_attach(const struct lg2160_config *config,
-				   struct i2c_adapter *i2c_adap)
-{
-	struct lg216x_state *state = NULL;
-
-	lg_dbg("(%d-%04x)\n",
-	       i2c_adap ? i2c_adapter_id(i2c_adap) : 0,
-	       config ? config->i2c_addr : 0);
-
-	state = kzalloc(sizeof(struct lg216x_state), GFP_KERNEL);
-	if (state == NULL)
-		goto fail;
-
-	state->cfg = config;
-	state->i2c_adap = i2c_adap;
-	state->fic_ver = 0xff;
-	state->parade_id = 0xff;
-
-	switch (config->lg_chip) {
-	default:
-		lg_warn("invalid chip requested, defaulting to LG2160");
-		/* fall-thru */
-	case LG2160:
-		memcpy(&state->frontend.ops, &lg2160_ops,
-		       sizeof(struct dvb_frontend_ops));
-		break;
-	case LG2161:
-		memcpy(&state->frontend.ops, &lg2161_ops,
-		       sizeof(struct dvb_frontend_ops));
-		break;
-	}
-
-	state->frontend.demodulator_priv = state;
-	state->current_frequency = -1;
-	/* parade 1 by default */
-	state->frontend.dtv_property_cache.atscmh_parade_id = 1;
-
-	return &state->frontend;
-fail:
-	lg_warn("unable to detect LG216x hardware\n");
-	kfree(state);
-	return NULL;
-}
-EXPORT_SYMBOL(lg2160_attach);
-
-MODULE_DESCRIPTION("LG Electronics LG216x ATSC/MH Demodulator Driver");
-MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
-MODULE_LICENSE("GPL");
-MODULE_VERSION("0.3");
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/dvb/frontends/lg2160.h b/drivers/media/dvb/frontends/lg2160.h
deleted file mode 100644
index 9e2c0f4..0000000
--- a/drivers/media/dvb/frontends/lg2160.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- *    Support for LG2160 - ATSC/MH
- *
- *    Copyright (C) 2010 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 _LG2160_H_
-#define _LG2160_H_
-
-#include <linux/i2c.h>
-#include "dvb_frontend.h"
-
-enum lg_chip_type {
-	LG2160 = 0,
-	LG2161 = 1,
-};
-
-#define LG2161_1019 LG2161
-#define LG2161_1040 LG2161
-
-enum lg2160_spi_clock {
-	LG2160_SPI_3_125_MHZ = 0,
-	LG2160_SPI_6_25_MHZ = 1,
-	LG2160_SPI_12_5_MHZ = 2,
-};
-
-#if 0
-enum lg2161_oif {
-	LG2161_OIF_EBI2_SLA  = 1,
-	LG2161_OIF_SDIO_SLA  = 2,
-	LG2161_OIF_SPI_SLA   = 3,
-	LG2161_OIF_SPI_MAS   = 4,
-	LG2161_OIF_SERIAL_TS = 7,
-};
-#endif
-
-struct lg2160_config {
-	u8 i2c_addr;
-
-	/* user defined IF frequency in KHz */
-	u16 if_khz;
-
-	/* disable i2c repeater - 0:repeater enabled 1:repeater disabled */
-	int deny_i2c_rptr:1;
-
-	/* spectral inversion - 0:disabled 1:enabled */
-	int spectral_inversion:1;
-
-	unsigned int output_if;
-	enum lg2160_spi_clock spi_clock;
-	enum lg_chip_type lg_chip;
-};
-
-#if defined(CONFIG_DVB_LG2160) || (defined(CONFIG_DVB_LG2160_MODULE) && \
-				     defined(MODULE))
-extern
-struct dvb_frontend *lg2160_attach(const struct lg2160_config *config,
-				     struct i2c_adapter *i2c_adap);
-#else
-static inline
-struct dvb_frontend *lg2160_attach(const struct lg2160_config *config,
-				     struct i2c_adapter *i2c_adap)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif /* CONFIG_DVB_LG2160 */
-
-#endif /* _LG2160_H_ */
diff --git a/drivers/media/dvb/frontends/lgdt3305.c b/drivers/media/dvb/frontends/lgdt3305.c
deleted file mode 100644
index 1d2c473..0000000
--- a/drivers/media/dvb/frontends/lgdt3305.c
+++ /dev/null
@@ -1,1222 +0,0 @@
-/*
- *    Support for LG Electronics LGDT3304 and LGDT3305 - VSB/QAM
- *
- *    Copyright (C) 2008, 2009, 2010 Michael Krufky <mkrufky@linuxtv.org>
- *
- *    LGDT3304 support by Jarod Wilson <jarod@redhat.com>
- *
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#include <asm/div64.h>
-#include <linux/dvb/frontend.h>
-#include <linux/slab.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;
-};
-
-/* ------------------------------------------------------------------------ */
-
-/* FIXME: verify & document the LGDT3304 registers */
-
-#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 dtv_frontend_properties *p)
-{
-	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 (p->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 dtv_frontend_properties *p)
-{
-	int val;
-
-	switch (p->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 dtv_frontend_properties *p)
-{
-	u16 agc_ref;
-
-	switch (p->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 dtv_frontend_properties *p)
-{
-	u16 ifbw, rfbw, agcdelay;
-
-	switch (p->modulation) {
-	case VSB_8:
-		agcdelay = 0x04c0;
-		rfbw     = 0x8000;
-		ifbw     = 0x8000;
-		break;
-	case QAM_64:
-	case QAM_256:
-		agcdelay = 0x046b;
-		rfbw     = 0x8889;
-		/* FIXME: investigate optimal ifbw & rfbw values for the
-		 *        DT3304 and re-write this switch..case block */
-		if (state->cfg->demod_chip == LGDT3304)
-			ifbw = 0x6666;
-		else /* (state->cfg->demod_chip == LGDT3305) */
-			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 dtv_frontend_properties *p)
-{
-	int lockdten, acqen;
-
-	switch (p->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 */
-	switch (state->cfg->demod_chip) {
-	case LGDT3304:
-		lgdt3305_write_reg(state, 0x0314, 0xe1 | lockdten << 1);
-		lgdt3305_set_reg_bit(state, 0x030e, 2, acqen);
-		break;
-	case LGDT3305:
-		lgdt3305_write_reg(state, LGDT3305_AGC_CTRL_4, 0xe1 | lockdten << 1);
-		lgdt3305_set_reg_bit(state, LGDT3305_AGC_CTRL_1, 2, acqen);
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return lgdt3305_rfagc_loop(state, p);
-}
-
-static int lgdt3305_set_agc_power_ref(struct lgdt3305_state *state,
-				      struct dtv_frontend_properties *p)
-{
-	u16 usref = 0;
-
-	switch (p->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 dtv_frontend_properties *p,
-				       int inversion)
-{
-	int ret;
-
-	lg_dbg("(%d)\n", inversion);
-
-	switch (p->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 dtv_frontend_properties *p)
-{
-	u16 if_freq_khz;
-	u8 nco1, nco2, nco3, nco4;
-	u64 nco;
-
-	switch (p->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;
-
-	switch (p->modulation) {
-	case VSB_8:
-		nco <<= 24;
-		do_div(nco, 625);
-		break;
-	case QAM_64:
-	case QAM_256:
-		nco <<= 28;
-		do_div(nco, 625);
-		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 lgdt3304_init_data[] = {
-		{ .reg = LGDT3305_GEN_CTRL_1,           .val = 0x03, },
-		{ .reg = 0x000d,                        .val = 0x02, },
-		{ .reg = 0x000e,                        .val = 0x02, },
-		{ .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 = 0xf9, },
-		{ .reg = 0x0112,                        .val = 0x17, },
-		{ .reg = 0x0113,                        .val = 0x15, },
-		{ .reg = 0x0114,                        .val = 0x18, },
-		{ .reg = 0x0115,                        .val = 0xff, },
-		{ .reg = 0x0116,                        .val = 0x3c, },
-		{ .reg = 0x0214,                        .val = 0x67, },
-		{ .reg = 0x0424,                        .val = 0x8d, },
-		{ .reg = 0x0427,                        .val = 0x12, },
-		{ .reg = 0x0428,                        .val = 0x4f, },
-		{ .reg = LGDT3305_IFBW_1,               .val = 0x80, },
-		{ .reg = LGDT3305_IFBW_2,               .val = 0x00, },
-		{ .reg = 0x030a,                        .val = 0x08, },
-		{ .reg = 0x030b,                        .val = 0x9b, },
-		{ .reg = 0x030d,                        .val = 0x00, },
-		{ .reg = 0x030e,                        .val = 0x1c, },
-		{ .reg = 0x0314,                        .val = 0xe1, },
-		{ .reg = 0x000d,                        .val = 0x82, },
-		{ .reg = LGDT3305_TP_CTRL_1,            .val = 0x5b, },
-		{ .reg = LGDT3305_TP_CTRL_1,            .val = 0x5b, },
-	};
-
-	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");
-
-	switch (state->cfg->demod_chip) {
-	case LGDT3304:
-		ret = lgdt3305_write_regs(state, lgdt3304_init_data,
-					  ARRAY_SIZE(lgdt3304_init_data));
-		break;
-	case LGDT3305:
-		ret = lgdt3305_write_regs(state, lgdt3305_init_data,
-					  ARRAY_SIZE(lgdt3305_init_data));
-		break;
-	default:
-		ret = -EINVAL;
-	}
-	if (lg_fail(ret))
-		goto fail;
-
-	ret = lgdt3305_soft_reset(state);
-fail:
-	return ret;
-}
-
-static int lgdt3304_set_parameters(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct lgdt3305_state *state = fe->demodulator_priv;
-	int ret;
-
-	lg_dbg("(%d, %d)\n", p->frequency, p->modulation);
-
-	if (fe->ops.tuner_ops.set_params) {
-		ret = fe->ops.tuner_ops.set_params(fe);
-		if (fe->ops.i2c_gate_ctrl)
-			fe->ops.i2c_gate_ctrl(fe, 0);
-		if (lg_fail(ret))
-			goto fail;
-		state->current_frequency = p->frequency;
-	}
-
-	ret = lgdt3305_set_modulation(state, p);
-	if (lg_fail(ret))
-		goto fail;
-
-	ret = lgdt3305_passband_digital_agc(state, p);
-	if (lg_fail(ret))
-		goto fail;
-
-	ret = lgdt3305_agc_setup(state, p);
-	if (lg_fail(ret))
-		goto fail;
-
-	/* reg 0x030d is 3304-only... seen in vsb and qam usbsnoops... */
-	switch (p->modulation) {
-	case VSB_8:
-		lgdt3305_write_reg(state, 0x030d, 0x00);
-		lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_1, 0x4f);
-		lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_2, 0x0c);
-		lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_3, 0xac);
-		lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_4, 0xba);
-		break;
-	case QAM_64:
-	case QAM_256:
-		lgdt3305_write_reg(state, 0x030d, 0x14);
-		ret = lgdt3305_set_if(state, p);
-		if (lg_fail(ret))
-			goto fail;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-
-	ret = lgdt3305_spectral_inversion(state, p,
-					  state->cfg->spectral_inversion
-					  ? 1 : 0);
-	if (lg_fail(ret))
-		goto fail;
-
-	state->current_modulation = p->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_set_parameters(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct lgdt3305_state *state = fe->demodulator_priv;
-	int ret;
-
-	lg_dbg("(%d, %d)\n", p->frequency, p->modulation);
-
-	if (fe->ops.tuner_ops.set_params) {
-		ret = fe->ops.tuner_ops.set_params(fe);
-		if (fe->ops.i2c_gate_ctrl)
-			fe->ops.i2c_gate_ctrl(fe, 0);
-		if (lg_fail(ret))
-			goto fail;
-		state->current_frequency = p->frequency;
-	}
-
-	ret = lgdt3305_set_modulation(state, p);
-	if (lg_fail(ret))
-		goto fail;
-
-	ret = lgdt3305_passband_digital_agc(state, p);
-	if (lg_fail(ret))
-		goto fail;
-	ret = lgdt3305_set_agc_power_ref(state, p);
-	if (lg_fail(ret))
-		goto fail;
-	ret = lgdt3305_agc_setup(state, p);
-	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, p);
-	if (lg_fail(ret))
-		goto fail;
-	ret = lgdt3305_spectral_inversion(state, p,
-					  state->cfg->spectral_inversion
-					  ? 1 : 0);
-	if (lg_fail(ret))
-		goto fail;
-
-	ret = lgdt3305_set_filter_extension(state, p);
-	if (lg_fail(ret))
-		goto fail;
-
-	state->current_modulation = p->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 dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct lgdt3305_state *state = fe->demodulator_priv;
-
-	lg_dbg("\n");
-
-	p->modulation = state->current_modulation;
-	p->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:
-		/* signal bit is unreliable on the DT3304 in QAM mode */
-		if (((LGDT3304 == state->cfg->demod_chip)) && (cr_lock))
-			*status |= FE_HAS_SIGNAL;
-
-		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 lgdt3304_ops;
-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;
-
-	switch (config->demod_chip) {
-	case LGDT3304:
-		memcpy(&state->frontend.ops, &lgdt3304_ops,
-		       sizeof(struct dvb_frontend_ops));
-		break;
-	case LGDT3305:
-		memcpy(&state->frontend.ops, &lgdt3305_ops,
-		       sizeof(struct dvb_frontend_ops));
-		break;
-	default:
-		goto fail;
-	}
-	state->frontend.demodulator_priv = state;
-
-	/* verify that we're talking to a lg dt3304/5 */
-	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 %s hardware\n",
-		config->demod_chip ? "LGDT3304" : "LGDT3305");
-	kfree(state);
-	return NULL;
-}
-EXPORT_SYMBOL(lgdt3305_attach);
-
-static struct dvb_frontend_ops lgdt3304_ops = {
-	.delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
-	.info = {
-		.name = "LG Electronics LGDT3304 VSB/QAM Frontend",
-		.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,
-	.set_frontend         = lgdt3304_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,
-};
-
-static struct dvb_frontend_ops lgdt3305_ops = {
-	.delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
-	.info = {
-		.name = "LG Electronics LGDT3305 VSB/QAM Frontend",
-		.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 LGDT3304/5 ATSC/QAM-B Demodulator Driver");
-MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
-MODULE_LICENSE("GPL");
-MODULE_VERSION("0.2");
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/dvb/frontends/lgdt3305.h b/drivers/media/dvb/frontends/lgdt3305.h
deleted file mode 100644
index 02172ec..0000000
--- a/drivers/media/dvb/frontends/lgdt3305.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- *    Support for LG Electronics LGDT3304 and LGDT3305 - VSB/QAM
- *
- *    Copyright (C) 2008, 2009, 2010 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,
-};
-
-enum lgdt_demod_chip_type {
-	LGDT3305 = 0,
-	LGDT3304 = 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 */
-	unsigned int deny_i2c_rptr:1;
-
-	/* spectral inversion - 0:disabled 1:enabled */
-	unsigned int spectral_inversion:1;
-
-	/* use RF AGC loop - 0:disabled 1:enabled */
-	unsigned 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;
-	enum lgdt_demod_chip_type demod_chip;
-};
-
-#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/lgdt330x.c b/drivers/media/dvb/frontends/lgdt330x.c
deleted file mode 100644
index e046622..0000000
--- a/drivers/media/dvb/frontends/lgdt330x.c
+++ /dev/null
@@ -1,831 +0,0 @@
-/*
- *    Support for LGDT3302 and LGDT3303 - VSB/QAM
- *
- *    Copyright (C) 2005 Wilson Michaels <wilsonmichaels@earthlink.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 program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You 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.
- *
- */
-
-/*
- *                      NOTES ABOUT THIS DRIVER
- *
- * This Linux driver supports:
- *   DViCO FusionHDTV 3 Gold-Q
- *   DViCO FusionHDTV 3 Gold-T
- *   DViCO FusionHDTV 5 Gold
- *   DViCO FusionHDTV 5 Lite
- *   DViCO FusionHDTV 5 USB Gold
- *   Air2PC/AirStar 2 ATSC 3rd generation (HD5000)
- *   pcHDTV HD5500
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <asm/byteorder.h>
-
-#include "dvb_frontend.h"
-#include "dvb_math.h"
-#include "lgdt330x_priv.h"
-#include "lgdt330x.h"
-
-/* Use Equalizer Mean Squared Error instead of Phaser Tracker MSE */
-/* #define USE_EQMSE */
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug,"Turn on/off lgdt330x frontend debugging (default:off).");
-#define dprintk(args...) \
-do { \
-if (debug) printk(KERN_DEBUG "lgdt330x: " args); \
-} while (0)
-
-struct lgdt330x_state
-{
-	struct i2c_adapter* i2c;
-
-	/* Configuration settings */
-	const struct lgdt330x_config* config;
-
-	struct dvb_frontend frontend;
-
-	/* Demodulator private data */
-	fe_modulation_t current_modulation;
-	u32 snr; /* Result of last SNR calculation */
-
-	/* Tuner private data */
-	u32 current_frequency;
-};
-
-static int i2c_write_demod_bytes (struct lgdt330x_state* state,
-				  u8 *buf, /* data bytes to send */
-				  int len  /* number of bytes to send */ )
-{
-	struct i2c_msg msg =
-		{ .addr = state->config->demod_address,
-		  .flags = 0,
-		  .buf = buf,
-		  .len = 2 };
-	int i;
-	int err;
-
-	for (i=0; i<len-1; i+=2){
-		if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
-			printk(KERN_WARNING "lgdt330x: %s error (addr %02x <- %02x, err = %i)\n", __func__, msg.buf[0], msg.buf[1], err);
-			if (err < 0)
-				return err;
-			else
-				return -EREMOTEIO;
-		}
-		msg.buf += 2;
-	}
-	return 0;
-}
-
-/*
- * This routine writes the register (reg) to the demod bus
- * then reads the data returned for (len) bytes.
- */
-
-static int i2c_read_demod_bytes(struct lgdt330x_state *state,
-				enum I2C_REG reg, u8 *buf, int len)
-{
-	u8 wr [] = { reg };
-	struct i2c_msg msg [] = {
-		{ .addr = state->config->demod_address,
-		  .flags = 0, .buf = wr,  .len = 1 },
-		{ .addr = state->config->demod_address,
-		  .flags = I2C_M_RD, .buf = buf, .len = len },
-	};
-	int ret;
-	ret = i2c_transfer(state->i2c, msg, 2);
-	if (ret != 2) {
-		printk(KERN_WARNING "lgdt330x: %s: addr 0x%02x select 0x%02x error (ret == %i)\n", __func__, state->config->demod_address, reg, ret);
-		if (ret >= 0)
-			ret = -EIO;
-	} else {
-		ret = 0;
-	}
-	return ret;
-}
-
-/* Software reset */
-static int lgdt3302_SwReset(struct lgdt330x_state* state)
-{
-	u8 ret;
-	u8 reset[] = {
-		IRQ_MASK,
-		0x00 /* bit 6 is active low software reset
-		      *	bits 5-0 are 1 to mask interrupts */
-	};
-
-	ret = i2c_write_demod_bytes(state,
-				    reset, sizeof(reset));
-	if (ret == 0) {
-
-		/* force reset high (inactive) and unmask interrupts */
-		reset[1] = 0x7f;
-		ret = i2c_write_demod_bytes(state,
-					    reset, sizeof(reset));
-	}
-	return ret;
-}
-
-static int lgdt3303_SwReset(struct lgdt330x_state* state)
-{
-	u8 ret;
-	u8 reset[] = {
-		0x02,
-		0x00 /* bit 0 is active low software reset */
-	};
-
-	ret = i2c_write_demod_bytes(state,
-				    reset, sizeof(reset));
-	if (ret == 0) {
-
-		/* force reset high (inactive) */
-		reset[1] = 0x01;
-		ret = i2c_write_demod_bytes(state,
-					    reset, sizeof(reset));
-	}
-	return ret;
-}
-
-static int lgdt330x_SwReset(struct lgdt330x_state* state)
-{
-	switch (state->config->demod_chip) {
-	case LGDT3302:
-		return lgdt3302_SwReset(state);
-	case LGDT3303:
-		return lgdt3303_SwReset(state);
-	default:
-		return -ENODEV;
-	}
-}
-
-static int lgdt330x_init(struct dvb_frontend* fe)
-{
-	/* Hardware reset is done using gpio[0] of cx23880x chip.
-	 * I'd like to do it here, but don't know how to find chip address.
-	 * cx88-cards.c arranges for the reset bit to be inactive (high).
-	 * Maybe there needs to be a callable function in cx88-core or
-	 * the caller of this function needs to do it. */
-
-	/*
-	 * Array of byte pairs <address, value>
-	 * to initialize each different chip
-	 */
-	static u8 lgdt3302_init_data[] = {
-		/* Use 50MHz parameter values from spec sheet since xtal is 50 */
-		/* Change the value of NCOCTFV[25:0] of carrier
-		   recovery center frequency register */
-		VSB_CARRIER_FREQ0, 0x00,
-		VSB_CARRIER_FREQ1, 0x87,
-		VSB_CARRIER_FREQ2, 0x8e,
-		VSB_CARRIER_FREQ3, 0x01,
-		/* Change the TPCLK pin polarity
-		   data is valid on falling clock */
-		DEMUX_CONTROL, 0xfb,
-		/* Change the value of IFBW[11:0] of
-		   AGC IF/RF loop filter bandwidth register */
-		AGC_RF_BANDWIDTH0, 0x40,
-		AGC_RF_BANDWIDTH1, 0x93,
-		AGC_RF_BANDWIDTH2, 0x00,
-		/* Change the value of bit 6, 'nINAGCBY' and
-		   'NSSEL[1:0] of ACG function control register 2 */
-		AGC_FUNC_CTRL2, 0xc6,
-		/* Change the value of bit 6 'RFFIX'
-		   of AGC function control register 3 */
-		AGC_FUNC_CTRL3, 0x40,
-		/* Set the value of 'INLVTHD' register 0x2a/0x2c
-		   to 0x7fe */
-		AGC_DELAY0, 0x07,
-		AGC_DELAY2, 0xfe,
-		/* Change the value of IAGCBW[15:8]
-		   of inner AGC loop filter bandwidth */
-		AGC_LOOP_BANDWIDTH0, 0x08,
-		AGC_LOOP_BANDWIDTH1, 0x9a
-	};
-
-	static u8 lgdt3303_init_data[] = {
-		0x4c, 0x14
-	};
-
-	static u8 flip_1_lgdt3303_init_data[] = {
-		0x4c, 0x14,
-		0x87, 0xf3
-	};
-
-	static u8 flip_2_lgdt3303_init_data[] = {
-		0x4c, 0x14,
-		0x87, 0xda
-	};
-
-	struct lgdt330x_state* state = fe->demodulator_priv;
-	char  *chip_name;
-	int    err;
-
-	switch (state->config->demod_chip) {
-	case LGDT3302:
-		chip_name = "LGDT3302";
-		err = i2c_write_demod_bytes(state, lgdt3302_init_data,
-					    sizeof(lgdt3302_init_data));
-		break;
-	case LGDT3303:
-		chip_name = "LGDT3303";
-		switch (state->config->clock_polarity_flip) {
-		case 2:
-			err = i2c_write_demod_bytes(state,
-					flip_2_lgdt3303_init_data,
-					sizeof(flip_2_lgdt3303_init_data));
-			break;
-		case 1:
-			err = i2c_write_demod_bytes(state,
-					flip_1_lgdt3303_init_data,
-					sizeof(flip_1_lgdt3303_init_data));
-			break;
-		case 0:
-		default:
-			err = i2c_write_demod_bytes(state, lgdt3303_init_data,
-						    sizeof(lgdt3303_init_data));
-		}
-		break;
-	default:
-		chip_name = "undefined";
-		printk (KERN_WARNING "Only LGDT3302 and LGDT3303 are supported chips.\n");
-		err = -ENODEV;
-	}
-	dprintk("%s entered as %s\n", __func__, chip_name);
-	if (err < 0)
-		return err;
-	return lgdt330x_SwReset(state);
-}
-
-static int lgdt330x_read_ber(struct dvb_frontend* fe, u32* ber)
-{
-	*ber = 0; /* Not supplied by the demod chips */
-	return 0;
-}
-
-static int lgdt330x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
-{
-	struct lgdt330x_state* state = fe->demodulator_priv;
-	int err;
-	u8 buf[2];
-
-	*ucblocks = 0;
-
-	switch (state->config->demod_chip) {
-	case LGDT3302:
-		err = i2c_read_demod_bytes(state, LGDT3302_PACKET_ERR_COUNTER1,
-					   buf, sizeof(buf));
-		break;
-	case LGDT3303:
-		err = i2c_read_demod_bytes(state, LGDT3303_PACKET_ERR_COUNTER1,
-					   buf, sizeof(buf));
-		break;
-	default:
-		printk(KERN_WARNING
-		       "Only LGDT3302 and LGDT3303 are supported chips.\n");
-		err = -ENODEV;
-	}
-	if (err < 0)
-		return err;
-
-	*ucblocks = (buf[0] << 8) | buf[1];
-	return 0;
-}
-
-static int lgdt330x_set_parameters(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	/*
-	 * Array of byte pairs <address, value>
-	 * to initialize 8VSB for lgdt3303 chip 50 MHz IF
-	 */
-	static u8 lgdt3303_8vsb_44_data[] = {
-		0x04, 0x00,
-		0x0d, 0x40,
-		0x0e, 0x87,
-		0x0f, 0x8e,
-		0x10, 0x01,
-		0x47, 0x8b };
-
-	/*
-	 * Array of byte pairs <address, value>
-	 * to initialize QAM for lgdt3303 chip
-	 */
-	static u8 lgdt3303_qam_data[] = {
-		0x04, 0x00,
-		0x0d, 0x00,
-		0x0e, 0x00,
-		0x0f, 0x00,
-		0x10, 0x00,
-		0x51, 0x63,
-		0x47, 0x66,
-		0x48, 0x66,
-		0x4d, 0x1a,
-		0x49, 0x08,
-		0x4a, 0x9b };
-
-	struct lgdt330x_state* state = fe->demodulator_priv;
-
-	static u8 top_ctrl_cfg[]   = { TOP_CONTROL, 0x03 };
-
-	int err = 0;
-	/* Change only if we are actually changing the modulation */
-	if (state->current_modulation != p->modulation) {
-		switch (p->modulation) {
-		case VSB_8:
-			dprintk("%s: VSB_8 MODE\n", __func__);
-
-			/* Select VSB mode */
-			top_ctrl_cfg[1] = 0x03;
-
-			/* Select ANT connector if supported by card */
-			if (state->config->pll_rf_set)
-				state->config->pll_rf_set(fe, 1);
-
-			if (state->config->demod_chip == LGDT3303) {
-				err = i2c_write_demod_bytes(state, lgdt3303_8vsb_44_data,
-							    sizeof(lgdt3303_8vsb_44_data));
-			}
-			break;
-
-		case QAM_64:
-			dprintk("%s: QAM_64 MODE\n", __func__);
-
-			/* Select QAM_64 mode */
-			top_ctrl_cfg[1] = 0x00;
-
-			/* Select CABLE connector if supported by card */
-			if (state->config->pll_rf_set)
-				state->config->pll_rf_set(fe, 0);
-
-			if (state->config->demod_chip == LGDT3303) {
-				err = i2c_write_demod_bytes(state, lgdt3303_qam_data,
-											sizeof(lgdt3303_qam_data));
-			}
-			break;
-
-		case QAM_256:
-			dprintk("%s: QAM_256 MODE\n", __func__);
-
-			/* Select QAM_256 mode */
-			top_ctrl_cfg[1] = 0x01;
-
-			/* Select CABLE connector if supported by card */
-			if (state->config->pll_rf_set)
-				state->config->pll_rf_set(fe, 0);
-
-			if (state->config->demod_chip == LGDT3303) {
-				err = i2c_write_demod_bytes(state, lgdt3303_qam_data,
-											sizeof(lgdt3303_qam_data));
-			}
-			break;
-		default:
-			printk(KERN_WARNING "lgdt330x: %s: Modulation type(%d) UNSUPPORTED\n", __func__, p->modulation);
-			return -1;
-		}
-		if (err < 0)
-			printk(KERN_WARNING "lgdt330x: %s: error blasting "
-			       "bytes to lgdt3303 for modulation type(%d)\n",
-			       __func__, p->modulation);
-
-		/*
-		 * select serial or parallel MPEG harware interface
-		 * Serial:   0x04 for LGDT3302 or 0x40 for LGDT3303
-		 * Parallel: 0x00
-		 */
-		top_ctrl_cfg[1] |= state->config->serial_mpeg;
-
-		/* Select the requested mode */
-		i2c_write_demod_bytes(state, top_ctrl_cfg,
-				      sizeof(top_ctrl_cfg));
-		if (state->config->set_ts_params)
-			state->config->set_ts_params(fe, 0);
-		state->current_modulation = p->modulation;
-	}
-
-	/* Tune to the specified frequency */
-	if (fe->ops.tuner_ops.set_params) {
-		fe->ops.tuner_ops.set_params(fe);
-		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
-	}
-
-	/* Keep track of the new frequency */
-	/* FIXME this is the wrong way to do this...           */
-	/* The tuner is shared with the video4linux analog API */
-	state->current_frequency = p->frequency;
-
-	lgdt330x_SwReset(state);
-	return 0;
-}
-
-static int lgdt330x_get_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct lgdt330x_state *state = fe->demodulator_priv;
-	p->frequency = state->current_frequency;
-	return 0;
-}
-
-static int lgdt3302_read_status(struct dvb_frontend* fe, fe_status_t* status)
-{
-	struct lgdt330x_state* state = fe->demodulator_priv;
-	u8 buf[3];
-
-	*status = 0; /* Reset status result */
-
-	/* AGC status register */
-	i2c_read_demod_bytes(state, AGC_STATUS, buf, 1);
-	dprintk("%s: AGC_STATUS = 0x%02x\n", __func__, buf[0]);
-	if ((buf[0] & 0x0c) == 0x8){
-		/* Test signal does not exist flag */
-		/* as well as the AGC lock flag.   */
-		*status |= FE_HAS_SIGNAL;
-	}
-
-	/*
-	 * You must set the Mask bits to 1 in the IRQ_MASK in order
-	 * to see that status bit in the IRQ_STATUS register.
-	 * This is done in SwReset();
-	 */
-	/* signal status */
-	i2c_read_demod_bytes(state, TOP_CONTROL, buf, sizeof(buf));
-	dprintk("%s: TOP_CONTROL = 0x%02x, IRO_MASK = 0x%02x, IRQ_STATUS = 0x%02x\n", __func__, buf[0], buf[1], buf[2]);
-
-
-	/* sync status */
-	if ((buf[2] & 0x03) == 0x01) {
-		*status |= FE_HAS_SYNC;
-	}
-
-	/* FEC error status */
-	if ((buf[2] & 0x0c) == 0x08) {
-		*status |= FE_HAS_LOCK;
-		*status |= FE_HAS_VITERBI;
-	}
-
-	/* Carrier Recovery Lock Status Register */
-	i2c_read_demod_bytes(state, CARRIER_LOCK, buf, 1);
-	dprintk("%s: CARRIER_LOCK = 0x%02x\n", __func__, buf[0]);
-	switch (state->current_modulation) {
-	case QAM_256:
-	case QAM_64:
-		/* Need to understand why there are 3 lock levels here */
-		if ((buf[0] & 0x07) == 0x07)
-			*status |= FE_HAS_CARRIER;
-		break;
-	case VSB_8:
-		if ((buf[0] & 0x80) == 0x80)
-			*status |= FE_HAS_CARRIER;
-		break;
-	default:
-		printk(KERN_WARNING "lgdt330x: %s: Modulation set to unsupported value\n", __func__);
-	}
-
-	return 0;
-}
-
-static int lgdt3303_read_status(struct dvb_frontend* fe, fe_status_t* status)
-{
-	struct lgdt330x_state* state = fe->demodulator_priv;
-	int err;
-	u8 buf[3];
-
-	*status = 0; /* Reset status result */
-
-	/* lgdt3303 AGC status register */
-	err = i2c_read_demod_bytes(state, 0x58, buf, 1);
-	if (err < 0)
-		return err;
-
-	dprintk("%s: AGC_STATUS = 0x%02x\n", __func__, buf[0]);
-	if ((buf[0] & 0x21) == 0x01){
-		/* Test input signal does not exist flag */
-		/* as well as the AGC lock flag.   */
-		*status |= FE_HAS_SIGNAL;
-	}
-
-	/* Carrier Recovery Lock Status Register */
-	i2c_read_demod_bytes(state, CARRIER_LOCK, buf, 1);
-	dprintk("%s: CARRIER_LOCK = 0x%02x\n", __func__, buf[0]);
-	switch (state->current_modulation) {
-	case QAM_256:
-	case QAM_64:
-		/* Need to understand why there are 3 lock levels here */
-		if ((buf[0] & 0x07) == 0x07)
-			*status |= FE_HAS_CARRIER;
-		else
-			break;
-		i2c_read_demod_bytes(state, 0x8a, buf, 1);
-		if ((buf[0] & 0x04) == 0x04)
-			*status |= FE_HAS_SYNC;
-		if ((buf[0] & 0x01) == 0x01)
-			*status |= FE_HAS_LOCK;
-		if ((buf[0] & 0x08) == 0x08)
-			*status |= FE_HAS_VITERBI;
-		break;
-	case VSB_8:
-		if ((buf[0] & 0x80) == 0x80)
-			*status |= FE_HAS_CARRIER;
-		else
-			break;
-		i2c_read_demod_bytes(state, 0x38, buf, 1);
-		if ((buf[0] & 0x02) == 0x00)
-			*status |= FE_HAS_SYNC;
-		if ((buf[0] & 0x01) == 0x01) {
-			*status |= FE_HAS_LOCK;
-			*status |= FE_HAS_VITERBI;
-		}
-		break;
-	default:
-		printk(KERN_WARNING "lgdt330x: %s: Modulation set to unsupported value\n", __func__);
-	}
-	return 0;
-}
-
-/* Calculate SNR estimation (scaled by 2^24)
-
-   8-VSB SNR equations from LGDT3302 and LGDT3303 datasheets, QAM
-   equations from LGDT3303 datasheet.  VSB is the same between the '02
-   and '03, so maybe QAM is too?  Perhaps someone with a newer datasheet
-   that has QAM information could verify?
-
-   For 8-VSB: (two ways, take your pick)
-   LGDT3302:
-     SNR_EQ = 10 * log10(25 * 24^2 / EQ_MSE)
-   LGDT3303:
-     SNR_EQ = 10 * log10(25 * 32^2 / EQ_MSE)
-   LGDT3302 & LGDT3303:
-     SNR_PT = 10 * log10(25 * 32^2 / PT_MSE)  (we use this one)
-   For 64-QAM:
-     SNR    = 10 * log10( 688128   / MSEQAM)
-   For 256-QAM:
-     SNR    = 10 * log10( 696320   / MSEQAM)
-
-   We re-write the snr equation as:
-     SNR * 2^24 = 10*(c - intlog10(MSE))
-   Where for 256-QAM, c = log10(696320) * 2^24, and so on. */
-
-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 lgdt3302_read_snr(struct dvb_frontend* fe, u16* snr)
-{
-	struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv;
-	u8 buf[5];	/* read data buffer */
-	u32 noise;	/* noise value */
-	u32 c;		/* per-modulation SNR calculation constant */
-
-	switch(state->current_modulation) {
-	case VSB_8:
-		i2c_read_demod_bytes(state, LGDT3302_EQPH_ERR0, buf, 5);
-#ifdef USE_EQMSE
-		/* Use Equalizer Mean-Square Error Register */
-		/* SNR for ranges from -15.61 to +41.58 */
-		noise = ((buf[0] & 7) << 16) | (buf[1] << 8) | buf[2];
-		c = 69765745; /* log10(25*24^2)*2^24 */
-#else
-		/* Use Phase Tracker Mean-Square Error Register */
-		/* SNR for ranges from -13.11 to +44.08 */
-		noise = ((buf[0] & 7<<3) << 13) | (buf[3] << 8) | buf[4];
-		c = 73957994; /* log10(25*32^2)*2^24 */
-#endif
-		break;
-	case QAM_64:
-	case QAM_256:
-		i2c_read_demod_bytes(state, CARRIER_MSEQAM1, buf, 2);
-		noise = ((buf[0] & 3) << 8) | buf[1];
-		c = state->current_modulation == QAM_64 ? 97939837 : 98026066;
-		/* log10(688128)*2^24 and log10(696320)*2^24 */
-		break;
-	default:
-		printk(KERN_ERR "lgdt330x: %s: Modulation set to unsupported value\n",
-		       __func__);
-		return -EREMOTEIO; /* return -EDRIVER_IS_GIBBERED; */
-	}
-
-	state->snr = calculate_snr(noise, c);
-	*snr = (state->snr) >> 16; /* Convert from 8.24 fixed-point to 8.8 */
-
-	dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __func__, noise,
-		state->snr >> 24, (((state->snr>>8) & 0xffff) * 100) >> 16);
-
-	return 0;
-}
-
-static int lgdt3303_read_snr(struct dvb_frontend* fe, u16* snr)
-{
-	struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv;
-	u8 buf[5];	/* read data buffer */
-	u32 noise;	/* noise value */
-	u32 c;		/* per-modulation SNR calculation constant */
-
-	switch(state->current_modulation) {
-	case VSB_8:
-		i2c_read_demod_bytes(state, LGDT3303_EQPH_ERR0, buf, 5);
-#ifdef USE_EQMSE
-		/* Use Equalizer Mean-Square Error Register */
-		/* SNR for ranges from -16.12 to +44.08 */
-		noise = ((buf[0] & 0x78) << 13) | (buf[1] << 8) | buf[2];
-		c = 73957994; /* log10(25*32^2)*2^24 */
-#else
-		/* Use Phase Tracker Mean-Square Error Register */
-		/* SNR for ranges from -13.11 to +44.08 */
-		noise = ((buf[0] & 7) << 16) | (buf[3] << 8) | buf[4];
-		c = 73957994; /* log10(25*32^2)*2^24 */
-#endif
-		break;
-	case QAM_64:
-	case QAM_256:
-		i2c_read_demod_bytes(state, CARRIER_MSEQAM1, buf, 2);
-		noise = (buf[0] << 8) | buf[1];
-		c = state->current_modulation == QAM_64 ? 97939837 : 98026066;
-		/* log10(688128)*2^24 and log10(696320)*2^24 */
-		break;
-	default:
-		printk(KERN_ERR "lgdt330x: %s: Modulation set to unsupported value\n",
-		       __func__);
-		return -EREMOTEIO; /* return -EDRIVER_IS_GIBBERED; */
-	}
-
-	state->snr = calculate_snr(noise, c);
-	*snr = (state->snr) >> 16; /* Convert from 8.24 fixed-point to 8.8 */
-
-	dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __func__, noise,
-		state->snr >> 24, (((state->snr >> 8) & 0xffff) * 100) >> 16);
-
-	return 0;
-}
-
-static int lgdt330x_read_signal_strength(struct dvb_frontend* fe, u16* strength)
-{
-	/* 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 lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv;
-	u16 snr;
-	int ret;
-
-	ret = fe->ops.read_snr(fe, &snr);
-	if (ret != 0)
-		return ret;
-	/* 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;
-
-	return 0;
-}
-
-static int lgdt330x_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fe_tune_settings)
-{
-	/* I have no idea about this - it may not be needed */
-	fe_tune_settings->min_delay_ms = 500;
-	fe_tune_settings->step_size = 0;
-	fe_tune_settings->max_drift = 0;
-	return 0;
-}
-
-static void lgdt330x_release(struct dvb_frontend* fe)
-{
-	struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv;
-	kfree(state);
-}
-
-static struct dvb_frontend_ops lgdt3302_ops;
-static struct dvb_frontend_ops lgdt3303_ops;
-
-struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config,
-				     struct i2c_adapter* i2c)
-{
-	struct lgdt330x_state* state = NULL;
-	u8 buf[1];
-
-	/* Allocate memory for the internal state */
-	state = kzalloc(sizeof(struct lgdt330x_state), GFP_KERNEL);
-	if (state == NULL)
-		goto error;
-
-	/* Setup the state */
-	state->config = config;
-	state->i2c = i2c;
-
-	/* Create dvb_frontend */
-	switch (config->demod_chip) {
-	case LGDT3302:
-		memcpy(&state->frontend.ops, &lgdt3302_ops, sizeof(struct dvb_frontend_ops));
-		break;
-	case LGDT3303:
-		memcpy(&state->frontend.ops, &lgdt3303_ops, sizeof(struct dvb_frontend_ops));
-		break;
-	default:
-		goto error;
-	}
-	state->frontend.demodulator_priv = state;
-
-	/* Verify communication with demod chip */
-	if (i2c_read_demod_bytes(state, 2, buf, 1))
-		goto error;
-
-	state->current_frequency = -1;
-	state->current_modulation = -1;
-
-	return &state->frontend;
-
-error:
-	kfree(state);
-	dprintk("%s: ERROR\n",__func__);
-	return NULL;
-}
-
-static struct dvb_frontend_ops lgdt3302_ops = {
-	.delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
-	.info = {
-		.name= "LG Electronics LGDT3302 VSB/QAM Frontend",
-		.frequency_min= 54000000,
-		.frequency_max= 858000000,
-		.frequency_stepsize= 62500,
-		.symbol_rate_min    = 5056941,	/* QAM 64 */
-		.symbol_rate_max    = 10762000,	/* VSB 8  */
-		.caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
-	},
-	.init                 = lgdt330x_init,
-	.set_frontend         = lgdt330x_set_parameters,
-	.get_frontend         = lgdt330x_get_frontend,
-	.get_tune_settings    = lgdt330x_get_tune_settings,
-	.read_status          = lgdt3302_read_status,
-	.read_ber             = lgdt330x_read_ber,
-	.read_signal_strength = lgdt330x_read_signal_strength,
-	.read_snr             = lgdt3302_read_snr,
-	.read_ucblocks        = lgdt330x_read_ucblocks,
-	.release              = lgdt330x_release,
-};
-
-static struct dvb_frontend_ops lgdt3303_ops = {
-	.delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
-	.info = {
-		.name= "LG Electronics LGDT3303 VSB/QAM Frontend",
-		.frequency_min= 54000000,
-		.frequency_max= 858000000,
-		.frequency_stepsize= 62500,
-		.symbol_rate_min    = 5056941,	/* QAM 64 */
-		.symbol_rate_max    = 10762000,	/* VSB 8  */
-		.caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
-	},
-	.init                 = lgdt330x_init,
-	.set_frontend         = lgdt330x_set_parameters,
-	.get_frontend         = lgdt330x_get_frontend,
-	.get_tune_settings    = lgdt330x_get_tune_settings,
-	.read_status          = lgdt3303_read_status,
-	.read_ber             = lgdt330x_read_ber,
-	.read_signal_strength = lgdt330x_read_signal_strength,
-	.read_snr             = lgdt3303_read_snr,
-	.read_ucblocks        = lgdt330x_read_ucblocks,
-	.release              = lgdt330x_release,
-};
-
-MODULE_DESCRIPTION("LGDT330X (ATSC 8VSB & ITU-T J.83 AnnexB 64/256 QAM) Demodulator Driver");
-MODULE_AUTHOR("Wilson Michaels");
-MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(lgdt330x_attach);
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/dvb/frontends/lgdt330x.h b/drivers/media/dvb/frontends/lgdt330x.h
deleted file mode 100644
index 9012504..0000000
--- a/drivers/media/dvb/frontends/lgdt330x.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- *    Support for LGDT3302 and LGDT3303 - VSB/QAM
- *
- *    Copyright (C) 2005 Wilson Michaels <wilsonmichaels@earthlink.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 program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You 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 LGDT330X_H
-#define LGDT330X_H
-
-#include <linux/dvb/frontend.h>
-
-typedef enum lg_chip_t {
-		UNDEFINED,
-		LGDT3302,
-		LGDT3303
-}lg_chip_type;
-
-struct lgdt330x_config
-{
-	/* The demodulator's i2c address */
-	u8 demod_address;
-
-	/* LG demodulator chip LGDT3302 or LGDT3303 */
-	lg_chip_type demod_chip;
-
-	/* MPEG hardware interface - 0:parallel 1:serial */
-	int serial_mpeg;
-
-	/* PLL interface */
-	int (*pll_rf_set) (struct dvb_frontend* fe, int index);
-
-	/* Need to set device param for start_dma */
-	int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured);
-
-	/* Flip the polarity of the mpeg data transfer clock using alternate init data
-	 * This option applies ONLY to LGDT3303 - 0:disabled (default) 1:enabled */
-	int clock_polarity_flip;
-};
-
-#if defined(CONFIG_DVB_LGDT330X) || (defined(CONFIG_DVB_LGDT330X_MODULE) && defined(MODULE))
-extern struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config,
-					    struct i2c_adapter* i2c);
-#else
-static inline struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config,
-					    struct i2c_adapter* i2c)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif // CONFIG_DVB_LGDT330X
-
-#endif /* LGDT330X_H */
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/dvb/frontends/lgdt330x_priv.h b/drivers/media/dvb/frontends/lgdt330x_priv.h
deleted file mode 100644
index 38c7669..0000000
--- a/drivers/media/dvb/frontends/lgdt330x_priv.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- *    Support for LGDT3302 and LGDT3303 - VSB/QAM
- *
- *    Copyright (C) 2005 Wilson Michaels <wilsonmichaels@earthlink.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 program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You 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 _LGDT330X_PRIV_
-#define _LGDT330X_PRIV_
-
-/* i2c control register addresses */
-enum I2C_REG {
-	TOP_CONTROL= 0x00,
-	IRQ_MASK= 0x01,
-	IRQ_STATUS= 0x02,
-	VSB_CARRIER_FREQ0= 0x16,
-	VSB_CARRIER_FREQ1= 0x17,
-	VSB_CARRIER_FREQ2= 0x18,
-	VSB_CARRIER_FREQ3= 0x19,
-	CARRIER_MSEQAM1= 0x1a,
-	CARRIER_MSEQAM2= 0x1b,
-	CARRIER_LOCK= 0x1c,
-	TIMING_RECOVERY= 0x1d,
-	AGC_DELAY0= 0x2a,
-	AGC_DELAY1= 0x2b,
-	AGC_DELAY2= 0x2c,
-	AGC_RF_BANDWIDTH0= 0x2d,
-	AGC_RF_BANDWIDTH1= 0x2e,
-	AGC_RF_BANDWIDTH2= 0x2f,
-	AGC_LOOP_BANDWIDTH0= 0x30,
-	AGC_LOOP_BANDWIDTH1= 0x31,
-	AGC_FUNC_CTRL1= 0x32,
-	AGC_FUNC_CTRL2= 0x33,
-	AGC_FUNC_CTRL3= 0x34,
-	AGC_RFIF_ACC0= 0x39,
-	AGC_RFIF_ACC1= 0x3a,
-	AGC_RFIF_ACC2= 0x3b,
-	AGC_STATUS= 0x3f,
-	SYNC_STATUS_VSB= 0x43,
-	DEMUX_CONTROL= 0x66,
-	LGDT3302_EQPH_ERR0= 0x47,
-	LGDT3302_EQ_ERR1= 0x48,
-	LGDT3302_EQ_ERR2= 0x49,
-	LGDT3302_PH_ERR1= 0x4a,
-	LGDT3302_PH_ERR2= 0x4b,
-	LGDT3302_PACKET_ERR_COUNTER1= 0x6a,
-	LGDT3302_PACKET_ERR_COUNTER2= 0x6b,
-	LGDT3303_EQPH_ERR0= 0x6e,
-	LGDT3303_EQ_ERR1= 0x6f,
-	LGDT3303_EQ_ERR2= 0x70,
-	LGDT3303_PH_ERR1= 0x71,
-	LGDT3303_PH_ERR2= 0x72,
-	LGDT3303_PACKET_ERR_COUNTER1= 0x8b,
-	LGDT3303_PACKET_ERR_COUNTER2= 0x8c,
-};
-
-#endif /* _LGDT330X_PRIV_ */
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/dvb/frontends/lgs8gl5.c b/drivers/media/dvb/frontends/lgs8gl5.c
deleted file mode 100644
index 2cec804..0000000
--- a/drivers/media/dvb/frontends/lgs8gl5.c
+++ /dev/null
@@ -1,453 +0,0 @@
-/*
-    Legend Silicon LGS-8GL5 DMB-TH OFDM demodulator driver
-
-    Copyright (C) 2008 Sirius International (Hong Kong) Limited
-	Timothy Lee <timothy.lee@siriushk.com>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include "dvb_frontend.h"
-#include "lgs8gl5.h"
-
-
-#define REG_RESET		0x02
-#define REG_RESET_OFF			0x01
-#define REG_03			0x03
-#define REG_04			0x04
-#define REG_07			0x07
-#define REG_09			0x09
-#define REG_0A			0x0a
-#define REG_0B			0x0b
-#define REG_0C			0x0c
-#define REG_37			0x37
-#define REG_STRENGTH		0x4b
-#define REG_STRENGTH_MASK		0x7f
-#define REG_STRENGTH_CARRIER		0x80
-#define REG_INVERSION		0x7c
-#define REG_INVERSION_ON		0x80
-#define REG_7D			0x7d
-#define REG_7E			0x7e
-#define REG_A2			0xa2
-#define REG_STATUS		0xa4
-#define REG_STATUS_SYNC		0x04
-#define REG_STATUS_LOCK		0x01
-
-
-struct lgs8gl5_state {
-	struct i2c_adapter *i2c;
-	const struct lgs8gl5_config *config;
-	struct dvb_frontend frontend;
-};
-
-
-static int debug;
-#define dprintk(args...) \
-	do { \
-		if (debug) \
-			printk(KERN_DEBUG "lgs8gl5: " args); \
-	} while (0)
-
-
-/* Writes into demod's register */
-static int
-lgs8gl5_write_reg(struct lgs8gl5_state *state, u8 reg, u8 data)
-{
-	int ret;
-	u8 buf[] = {reg, data};
-	struct i2c_msg msg = {
-		.addr  = state->config->demod_address,
-		.flags = 0,
-		.buf   = buf,
-		.len   = 2
-	};
-
-	ret = i2c_transfer(state->i2c, &msg, 1);
-	if (ret != 1)
-		dprintk("%s: error (reg=0x%02x, val=0x%02x, ret=%i)\n",
-			__func__, reg, data, ret);
-	return (ret != 1) ? -1 : 0;
-}
-
-
-/* Reads from demod's register */
-static int
-lgs8gl5_read_reg(struct lgs8gl5_state *state, u8 reg)
-{
-	int ret;
-	u8 b0[] = {reg};
-	u8 b1[] = {0};
-	struct i2c_msg msg[2] = {
-		{
-			.addr  = state->config->demod_address,
-			.flags = 0,
-			.buf   = b0,
-			.len   = 1
-		},
-		{
-			.addr  = state->config->demod_address,
-			.flags = I2C_M_RD,
-			.buf   = b1,
-			.len   = 1
-		}
-	};
-
-	ret = i2c_transfer(state->i2c, msg, 2);
-	if (ret != 2)
-		return -EIO;
-
-	return b1[0];
-}
-
-
-static int
-lgs8gl5_update_reg(struct lgs8gl5_state *state, u8 reg, u8 data)
-{
-	lgs8gl5_read_reg(state, reg);
-	lgs8gl5_write_reg(state, reg, data);
-	return 0;
-}
-
-
-/* Writes into alternate device's register */
-/* TODO:  Find out what that device is for! */
-static int
-lgs8gl5_update_alt_reg(struct lgs8gl5_state *state, u8 reg, u8 data)
-{
-	int ret;
-	u8 b0[] = {reg};
-	u8 b1[] = {0};
-	u8 b2[] = {reg, data};
-	struct i2c_msg msg[3] = {
-		{
-			.addr  = state->config->demod_address + 2,
-			.flags = 0,
-			.buf   = b0,
-			.len   = 1
-		},
-		{
-			.addr  = state->config->demod_address + 2,
-			.flags = I2C_M_RD,
-			.buf   = b1,
-			.len   = 1
-		},
-		{
-			.addr  = state->config->demod_address + 2,
-			.flags = 0,
-			.buf   = b2,
-			.len   = 2
-		},
-	};
-
-	ret = i2c_transfer(state->i2c, msg, 3);
-	return (ret != 3) ? -1 : 0;
-}
-
-
-static void
-lgs8gl5_soft_reset(struct lgs8gl5_state *state)
-{
-	u8 val;
-
-	dprintk("%s\n", __func__);
-
-	val = lgs8gl5_read_reg(state, REG_RESET);
-	lgs8gl5_write_reg(state, REG_RESET, val & ~REG_RESET_OFF);
-	lgs8gl5_write_reg(state, REG_RESET, val | REG_RESET_OFF);
-	msleep(5);
-}
-
-
-/* Starts demodulation */
-static void
-lgs8gl5_start_demod(struct lgs8gl5_state *state)
-{
-	u8  val;
-	int n;
-
-	dprintk("%s\n", __func__);
-
-	lgs8gl5_update_alt_reg(state, 0xc2, 0x28);
-	lgs8gl5_soft_reset(state);
-	lgs8gl5_update_reg(state, REG_07, 0x10);
-	lgs8gl5_update_reg(state, REG_07, 0x10);
-	lgs8gl5_write_reg(state, REG_09, 0x0e);
-	lgs8gl5_write_reg(state, REG_0A, 0xe5);
-	lgs8gl5_write_reg(state, REG_0B, 0x35);
-	lgs8gl5_write_reg(state, REG_0C, 0x30);
-
-	lgs8gl5_update_reg(state, REG_03, 0x00);
-	lgs8gl5_update_reg(state, REG_7E, 0x01);
-	lgs8gl5_update_alt_reg(state, 0xc5, 0x00);
-	lgs8gl5_update_reg(state, REG_04, 0x02);
-	lgs8gl5_update_reg(state, REG_37, 0x01);
-	lgs8gl5_soft_reset(state);
-
-	/* Wait for carrier */
-	for (n = 0;  n < 10;  n++) {
-		val = lgs8gl5_read_reg(state, REG_STRENGTH);
-		dprintk("Wait for carrier[%d] 0x%02X\n", n, val);
-		if (val & REG_STRENGTH_CARRIER)
-			break;
-		msleep(4);
-	}
-	if (!(val & REG_STRENGTH_CARRIER))
-		return;
-
-	/* Wait for lock */
-	for (n = 0;  n < 20;  n++) {
-		val = lgs8gl5_read_reg(state, REG_STATUS);
-		dprintk("Wait for lock[%d] 0x%02X\n", n, val);
-		if (val & REG_STATUS_LOCK)
-			break;
-		msleep(12);
-	}
-	if (!(val & REG_STATUS_LOCK))
-		return;
-
-	lgs8gl5_write_reg(state, REG_7D, lgs8gl5_read_reg(state, REG_A2));
-	lgs8gl5_soft_reset(state);
-}
-
-
-static int
-lgs8gl5_init(struct dvb_frontend *fe)
-{
-	struct lgs8gl5_state *state = fe->demodulator_priv;
-
-	dprintk("%s\n", __func__);
-
-	lgs8gl5_update_alt_reg(state, 0xc2, 0x28);
-	lgs8gl5_soft_reset(state);
-	lgs8gl5_update_reg(state, REG_07, 0x10);
-	lgs8gl5_update_reg(state, REG_07, 0x10);
-	lgs8gl5_write_reg(state, REG_09, 0x0e);
-	lgs8gl5_write_reg(state, REG_0A, 0xe5);
-	lgs8gl5_write_reg(state, REG_0B, 0x35);
-	lgs8gl5_write_reg(state, REG_0C, 0x30);
-
-	return 0;
-}
-
-
-static int
-lgs8gl5_read_status(struct dvb_frontend *fe, fe_status_t *status)
-{
-	struct lgs8gl5_state *state = fe->demodulator_priv;
-	u8 level = lgs8gl5_read_reg(state, REG_STRENGTH);
-	u8 flags = lgs8gl5_read_reg(state, REG_STATUS);
-
-	*status = 0;
-
-	if ((level & REG_STRENGTH_MASK) > 0)
-		*status |= FE_HAS_SIGNAL;
-	if (level & REG_STRENGTH_CARRIER)
-		*status |= FE_HAS_CARRIER;
-	if (flags & REG_STATUS_SYNC)
-		*status |= FE_HAS_SYNC;
-	if (flags & REG_STATUS_LOCK)
-		*status |= FE_HAS_LOCK;
-
-	return 0;
-}
-
-
-static int
-lgs8gl5_read_ber(struct dvb_frontend *fe, u32 *ber)
-{
-	*ber = 0;
-
-	return 0;
-}
-
-
-static int
-lgs8gl5_read_signal_strength(struct dvb_frontend *fe, u16 *signal_strength)
-{
-	struct lgs8gl5_state *state = fe->demodulator_priv;
-	u8 level = lgs8gl5_read_reg(state, REG_STRENGTH);
-	*signal_strength = (level & REG_STRENGTH_MASK) << 8;
-
-	return 0;
-}
-
-
-static int
-lgs8gl5_read_snr(struct dvb_frontend *fe, u16 *snr)
-{
-	struct lgs8gl5_state *state = fe->demodulator_priv;
-	u8 level = lgs8gl5_read_reg(state, REG_STRENGTH);
-	*snr = (level & REG_STRENGTH_MASK) << 8;
-
-	return 0;
-}
-
-
-static int
-lgs8gl5_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
-{
-	*ucblocks = 0;
-
-	return 0;
-}
-
-
-static int
-lgs8gl5_set_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct lgs8gl5_state *state = fe->demodulator_priv;
-
-	dprintk("%s\n", __func__);
-
-	if (p->bandwidth_hz != 8000000)
-		return -EINVAL;
-
-	if (fe->ops.tuner_ops.set_params) {
-		fe->ops.tuner_ops.set_params(fe);
-		if (fe->ops.i2c_gate_ctrl)
-			fe->ops.i2c_gate_ctrl(fe, 0);
-	}
-
-	/* lgs8gl5_set_inversion(state, p->inversion); */
-
-	lgs8gl5_start_demod(state);
-
-	return 0;
-}
-
-
-static int
-lgs8gl5_get_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct lgs8gl5_state *state = fe->demodulator_priv;
-	u8 inv = lgs8gl5_read_reg(state, REG_INVERSION);
-
-	p->inversion = (inv & REG_INVERSION_ON) ? INVERSION_ON : INVERSION_OFF;
-
-	p->code_rate_HP = FEC_1_2;
-	p->code_rate_LP = FEC_7_8;
-	p->guard_interval = GUARD_INTERVAL_1_32;
-	p->transmission_mode = TRANSMISSION_MODE_2K;
-	p->modulation = QAM_64;
-	p->hierarchy = HIERARCHY_NONE;
-	p->bandwidth_hz = 8000000;
-
-	return 0;
-}
-
-
-static int
-lgs8gl5_get_tune_settings(struct dvb_frontend *fe,
-		struct dvb_frontend_tune_settings *fesettings)
-{
-	fesettings->min_delay_ms = 240;
-	fesettings->step_size    = 0;
-	fesettings->max_drift    = 0;
-	return 0;
-}
-
-
-static void
-lgs8gl5_release(struct dvb_frontend *fe)
-{
-	struct lgs8gl5_state *state = fe->demodulator_priv;
-	kfree(state);
-}
-
-
-static struct dvb_frontend_ops lgs8gl5_ops;
-
-
-struct dvb_frontend*
-lgs8gl5_attach(const struct lgs8gl5_config *config, struct i2c_adapter *i2c)
-{
-	struct lgs8gl5_state *state = NULL;
-
-	dprintk("%s\n", __func__);
-
-	/* Allocate memory for the internal state */
-	state = kzalloc(sizeof(struct lgs8gl5_state), GFP_KERNEL);
-	if (state == NULL)
-		goto error;
-
-	/* Setup the state */
-	state->config = config;
-	state->i2c    = i2c;
-
-	/* Check if the demod is there */
-	if (lgs8gl5_read_reg(state, REG_RESET) < 0)
-		goto error;
-
-	/* Create dvb_frontend */
-	memcpy(&state->frontend.ops, &lgs8gl5_ops,
-		sizeof(struct dvb_frontend_ops));
-	state->frontend.demodulator_priv = state;
-	return &state->frontend;
-
-error:
-	kfree(state);
-	return NULL;
-}
-EXPORT_SYMBOL(lgs8gl5_attach);
-
-
-static struct dvb_frontend_ops lgs8gl5_ops = {
-	.delsys = { SYS_DMBTH },
-	.info = {
-		.name			= "Legend Silicon LGS-8GL5 DMB-TH",
-		.frequency_min		= 474000000,
-		.frequency_max		= 858000000,
-		.frequency_stepsize	= 10000,
-		.frequency_tolerance	= 0,
-		.caps = FE_CAN_FEC_AUTO |
-			FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_32 |
-			FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
-			FE_CAN_TRANSMISSION_MODE_AUTO |
-			FE_CAN_BANDWIDTH_AUTO |
-			FE_CAN_GUARD_INTERVAL_AUTO |
-			FE_CAN_HIERARCHY_AUTO |
-			FE_CAN_RECOVER
-	},
-
-	.release = lgs8gl5_release,
-
-	.init = lgs8gl5_init,
-
-	.set_frontend = lgs8gl5_set_frontend,
-	.get_frontend = lgs8gl5_get_frontend,
-	.get_tune_settings = lgs8gl5_get_tune_settings,
-
-	.read_status = lgs8gl5_read_status,
-	.read_ber = lgs8gl5_read_ber,
-	.read_signal_strength = lgs8gl5_read_signal_strength,
-	.read_snr = lgs8gl5_read_snr,
-	.read_ucblocks = lgs8gl5_read_ucblocks,
-};
-
-
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
-
-MODULE_DESCRIPTION("Legend Silicon LGS-8GL5 DMB-TH Demodulator driver");
-MODULE_AUTHOR("Timothy Lee");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/lgs8gl5.h b/drivers/media/dvb/frontends/lgs8gl5.h
deleted file mode 100644
index d1417678..0000000
--- a/drivers/media/dvb/frontends/lgs8gl5.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
-    Legend Silicon LGS-8GL5 DMB-TH OFDM demodulator driver
-
-    Copyright (C) 2008 Sirius International (Hong Kong) Limited
-	Timothy Lee <timothy.lee@siriushk.com>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#ifndef LGS8GL5_H
-#define LGS8GL5_H
-
-#include <linux/dvb/frontend.h>
-
-struct lgs8gl5_config {
-	/* the demodulator's i2c address */
-	u8 demod_address;
-};
-
-#if defined(CONFIG_DVB_LGS8GL5) || \
-	(defined(CONFIG_DVB_LGS8GL5_MODULE) && defined(MODULE))
-extern struct dvb_frontend *lgs8gl5_attach(
-	const struct lgs8gl5_config *config, struct i2c_adapter *i2c);
-#else
-static inline struct dvb_frontend *lgs8gl5_attach(
-	const struct lgs8gl5_config *config, struct i2c_adapter *i2c) {
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif /* CONFIG_DVB_LGS8GL5 */
-
-#endif /* LGS8GL5_H */
diff --git a/drivers/media/dvb/frontends/lgs8gxx.c b/drivers/media/dvb/frontends/lgs8gxx.c
deleted file mode 100644
index c2ea274..0000000
--- a/drivers/media/dvb/frontends/lgs8gxx.c
+++ /dev/null
@@ -1,1075 +0,0 @@
-/*
- *    Support for Legend Silicon GB20600 (a.k.a DMB-TH) demodulator
- *    LGS8913, LGS8GL5, LGS8G75
- *    experimental support LGS8G42, LGS8G52
- *
- *    Copyright (C) 2007-2009 David T.L. Wong <davidtlwong@gmail.com>
- *    Copyright (C) 2008 Sirius International (Hong Kong) Limited
- *    Timothy Lee <timothy.lee@siriushk.com> (for initial work on LGS8GL5)
- *
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the 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 <asm/div64.h>
-#include <linux/firmware.h>
-
-#include "dvb_frontend.h"
-
-#include "lgs8gxx.h"
-#include "lgs8gxx_priv.h"
-
-#define dprintk(args...) \
-	do { \
-		if (debug) \
-			printk(KERN_DEBUG "lgs8gxx: " args); \
-	} while (0)
-
-static int debug;
-static int fake_signal_str = 1;
-
-#define LGS8GXX_FIRMWARE "lgs8g75.fw"
-
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
-
-module_param(fake_signal_str, int, 0644);
-MODULE_PARM_DESC(fake_signal_str, "fake signal strength for LGS8913."
-"Signal strength calculation is slow.(default:on).");
-
-/* LGS8GXX internal helper functions */
-
-static int lgs8gxx_write_reg(struct lgs8gxx_state *priv, u8 reg, u8 data)
-{
-	int ret;
-	u8 buf[] = { reg, data };
-	struct i2c_msg msg = { .flags = 0, .buf = buf, .len = 2 };
-
-	msg.addr = priv->config->demod_address;
-	if (priv->config->prod != LGS8GXX_PROD_LGS8G75 && reg >= 0xC0)
-		msg.addr += 0x02;
-
-	if (debug >= 2)
-		dprintk("%s: reg=0x%02X, data=0x%02X\n", __func__, reg, data);
-
-	ret = i2c_transfer(priv->i2c, &msg, 1);
-
-	if (ret != 1)
-		dprintk("%s: error reg=0x%x, data=0x%x, ret=%i\n",
-			__func__, reg, data, ret);
-
-	return (ret != 1) ? -1 : 0;
-}
-
-static int lgs8gxx_read_reg(struct lgs8gxx_state *priv, u8 reg, u8 *p_data)
-{
-	int ret;
-	u8 dev_addr;
-
-	u8 b0[] = { reg };
-	u8 b1[] = { 0 };
-	struct i2c_msg msg[] = {
-		{ .flags = 0, .buf = b0, .len = 1 },
-		{ .flags = I2C_M_RD, .buf = b1, .len = 1 },
-	};
-
-	dev_addr = priv->config->demod_address;
-	if (priv->config->prod != LGS8GXX_PROD_LGS8G75 && reg >= 0xC0)
-		dev_addr += 0x02;
-	msg[1].addr =  msg[0].addr = dev_addr;
-
-	ret = i2c_transfer(priv->i2c, msg, 2);
-	if (ret != 2) {
-		dprintk("%s: error reg=0x%x, ret=%i\n", __func__, reg, ret);
-		return -1;
-	}
-
-	*p_data = b1[0];
-	if (debug >= 2)
-		dprintk("%s: reg=0x%02X, data=0x%02X\n", __func__, reg, b1[0]);
-	return 0;
-}
-
-static int lgs8gxx_soft_reset(struct lgs8gxx_state *priv)
-{
-	lgs8gxx_write_reg(priv, 0x02, 0x00);
-	msleep(1);
-	lgs8gxx_write_reg(priv, 0x02, 0x01);
-	msleep(100);
-
-	return 0;
-}
-
-static int wait_reg_mask(struct lgs8gxx_state *priv, u8 reg, u8 mask,
-	u8 val, u8 delay, u8 tries)
-{
-	u8 t;
-	int i;
-
-	for (i = 0; i < tries; i++) {
-		lgs8gxx_read_reg(priv, reg, &t);
-
-		if ((t & mask) == val)
-			return 0;
-		msleep(delay);
-	}
-
-	return 1;
-}
-
-static int lgs8gxx_set_ad_mode(struct lgs8gxx_state *priv)
-{
-	const struct lgs8gxx_config *config = priv->config;
-	u8 if_conf;
-
-	if_conf = 0x10; /* AGC output on, RF_AGC output off; */
-
-	if_conf |=
-		((config->ext_adc) ? 0x80 : 0x00) |
-		((config->if_neg_center) ? 0x04 : 0x00) |
-		((config->if_freq == 0) ? 0x08 : 0x00) | /* Baseband */
-		((config->adc_signed) ? 0x02 : 0x00) |
-		((config->if_neg_edge) ? 0x01 : 0x00);
-
-	if (config->ext_adc &&
-		(config->prod == LGS8GXX_PROD_LGS8G52)) {
-		lgs8gxx_write_reg(priv, 0xBA, 0x40);
-	}
-
-	lgs8gxx_write_reg(priv, 0x07, if_conf);
-
-	return 0;
-}
-
-static int lgs8gxx_set_if_freq(struct lgs8gxx_state *priv, u32 freq /*in kHz*/)
-{
-	u64 val;
-	u32 v32;
-	u32 if_clk;
-
-	if_clk = priv->config->if_clk_freq;
-
-	val = freq;
-	if (freq != 0) {
-		val <<= 32;
-		if (if_clk != 0)
-			do_div(val, if_clk);
-		v32 = val & 0xFFFFFFFF;
-		dprintk("Set IF Freq to %dkHz\n", freq);
-	} else {
-		v32 = 0;
-		dprintk("Set IF Freq to baseband\n");
-	}
-	dprintk("AFC_INIT_FREQ = 0x%08X\n", v32);
-
-	if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
-		lgs8gxx_write_reg(priv, 0x08, 0xFF & (v32));
-		lgs8gxx_write_reg(priv, 0x09, 0xFF & (v32 >> 8));
-		lgs8gxx_write_reg(priv, 0x0A, 0xFF & (v32 >> 16));
-		lgs8gxx_write_reg(priv, 0x0B, 0xFF & (v32 >> 24));
-	} else {
-		lgs8gxx_write_reg(priv, 0x09, 0xFF & (v32));
-		lgs8gxx_write_reg(priv, 0x0A, 0xFF & (v32 >> 8));
-		lgs8gxx_write_reg(priv, 0x0B, 0xFF & (v32 >> 16));
-		lgs8gxx_write_reg(priv, 0x0C, 0xFF & (v32 >> 24));
-	}
-
-	return 0;
-}
-
-static int lgs8gxx_get_afc_phase(struct lgs8gxx_state *priv)
-{
-	u64 val;
-	u32 v32 = 0;
-	u8 reg_addr, t;
-	int i;
-
-	if (priv->config->prod == LGS8GXX_PROD_LGS8G75)
-		reg_addr = 0x23;
-	else
-		reg_addr = 0x48;
-
-	for (i = 0; i < 4; i++) {
-		lgs8gxx_read_reg(priv, reg_addr, &t);
-		v32 <<= 8;
-		v32 |= t;
-		reg_addr--;
-	}
-
-	val = v32;
-	val *= priv->config->if_clk_freq;
-	val >>= 32;
-	dprintk("AFC = %u kHz\n", (u32)val);
-	return 0;
-}
-
-static int lgs8gxx_set_mode_auto(struct lgs8gxx_state *priv)
-{
-	u8 t;
-	u8 prod = priv->config->prod;
-
-	if (prod == LGS8GXX_PROD_LGS8913)
-		lgs8gxx_write_reg(priv, 0xC6, 0x01);
-
-	if (prod == LGS8GXX_PROD_LGS8G75) {
-		lgs8gxx_read_reg(priv, 0x0C, &t);
-		t &= (~0x04);
-		lgs8gxx_write_reg(priv, 0x0C, t | 0x80);
-		lgs8gxx_write_reg(priv, 0x39, 0x00);
-		lgs8gxx_write_reg(priv, 0x3D, 0x04);
-	} else if (prod == LGS8GXX_PROD_LGS8913 ||
-		prod == LGS8GXX_PROD_LGS8GL5 ||
-		prod == LGS8GXX_PROD_LGS8G42 ||
-		prod == LGS8GXX_PROD_LGS8G52 ||
-		prod == LGS8GXX_PROD_LGS8G54) {
-		lgs8gxx_read_reg(priv, 0x7E, &t);
-		lgs8gxx_write_reg(priv, 0x7E, t | 0x01);
-
-		/* clear FEC self reset */
-		lgs8gxx_read_reg(priv, 0xC5, &t);
-		lgs8gxx_write_reg(priv, 0xC5, t & 0xE0);
-	}
-
-	if (prod == LGS8GXX_PROD_LGS8913) {
-		/* FEC auto detect */
-		lgs8gxx_write_reg(priv, 0xC1, 0x03);
-
-		lgs8gxx_read_reg(priv, 0x7C, &t);
-		t = (t & 0x8C) | 0x03;
-		lgs8gxx_write_reg(priv, 0x7C, t);
-
-		/* BER test mode */
-		lgs8gxx_read_reg(priv, 0xC3, &t);
-		t = (t & 0xEF) |  0x10;
-		lgs8gxx_write_reg(priv, 0xC3, t);
-	}
-
-	if (priv->config->prod == LGS8GXX_PROD_LGS8G52)
-		lgs8gxx_write_reg(priv, 0xD9, 0x40);
-
-	return 0;
-}
-
-static int lgs8gxx_set_mode_manual(struct lgs8gxx_state *priv)
-{
-	u8 t;
-
-	if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
-		u8 t2;
-		lgs8gxx_read_reg(priv, 0x0C, &t);
-		t &= (~0x80);
-		lgs8gxx_write_reg(priv, 0x0C, t);
-
-		lgs8gxx_read_reg(priv, 0x0C, &t);
-		lgs8gxx_read_reg(priv, 0x19, &t2);
-
-		if (((t&0x03) == 0x01) && (t2&0x01)) {
-			lgs8gxx_write_reg(priv, 0x6E, 0x05);
-			lgs8gxx_write_reg(priv, 0x39, 0x02);
-			lgs8gxx_write_reg(priv, 0x39, 0x03);
-			lgs8gxx_write_reg(priv, 0x3D, 0x05);
-			lgs8gxx_write_reg(priv, 0x3E, 0x28);
-			lgs8gxx_write_reg(priv, 0x53, 0x80);
-		} else {
-			lgs8gxx_write_reg(priv, 0x6E, 0x3F);
-			lgs8gxx_write_reg(priv, 0x39, 0x00);
-			lgs8gxx_write_reg(priv, 0x3D, 0x04);
-		}
-
-		lgs8gxx_soft_reset(priv);
-		return 0;
-	}
-
-	/* turn off auto-detect; manual settings */
-	lgs8gxx_write_reg(priv, 0x7E, 0);
-	if (priv->config->prod == LGS8GXX_PROD_LGS8913)
-		lgs8gxx_write_reg(priv, 0xC1, 0);
-
-	lgs8gxx_read_reg(priv, 0xC5, &t);
-	t = (t & 0xE0) | 0x06;
-	lgs8gxx_write_reg(priv, 0xC5, t);
-
-	lgs8gxx_soft_reset(priv);
-
-	return 0;
-}
-
-static int lgs8gxx_is_locked(struct lgs8gxx_state *priv, u8 *locked)
-{
-	int ret = 0;
-	u8 t;
-
-	if (priv->config->prod == LGS8GXX_PROD_LGS8G75)
-		ret = lgs8gxx_read_reg(priv, 0x13, &t);
-	else
-		ret = lgs8gxx_read_reg(priv, 0x4B, &t);
-	if (ret != 0)
-		return ret;
-
-	if (priv->config->prod == LGS8GXX_PROD_LGS8G75)
-		*locked = ((t & 0x80) == 0x80) ? 1 : 0;
-	else
-		*locked = ((t & 0xC0) == 0xC0) ? 1 : 0;
-	return 0;
-}
-
-/* Wait for Code Acquisition Lock */
-static int lgs8gxx_wait_ca_lock(struct lgs8gxx_state *priv, u8 *locked)
-{
-	int ret = 0;
-	u8 reg, mask, val;
-
-	if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
-		reg = 0x13;
-		mask = 0x80;
-		val = 0x80;
-	} else {
-		reg = 0x4B;
-		mask = 0xC0;
-		val = 0xC0;
-	}
-
-	ret = wait_reg_mask(priv, reg, mask, val, 50, 40);
-	*locked = (ret == 0) ? 1 : 0;
-
-	return 0;
-}
-
-static int lgs8gxx_is_autodetect_finished(struct lgs8gxx_state *priv,
-					  u8 *finished)
-{
-	int ret = 0;
-	u8 reg, mask, val;
-
-	if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
-		reg = 0x1f;
-		mask = 0xC0;
-		val = 0x80;
-	} else {
-		reg = 0xA4;
-		mask = 0x03;
-		val = 0x01;
-	}
-
-	ret = wait_reg_mask(priv, reg, mask, val, 10, 20);
-	*finished = (ret == 0) ? 1 : 0;
-
-	return 0;
-}
-
-static int lgs8gxx_autolock_gi(struct lgs8gxx_state *priv, u8 gi, u8 cpn,
-	u8 *locked)
-{
-	int err = 0;
-	u8 ad_fini = 0;
-	u8 t1, t2;
-
-	if (gi == GI_945)
-		dprintk("try GI 945\n");
-	else if (gi == GI_595)
-		dprintk("try GI 595\n");
-	else if (gi == GI_420)
-		dprintk("try GI 420\n");
-	if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
-		lgs8gxx_read_reg(priv, 0x0C, &t1);
-		lgs8gxx_read_reg(priv, 0x18, &t2);
-		t1 &= ~(GI_MASK);
-		t1 |= gi;
-		t2 &= 0xFE;
-		t2 |= cpn ? 0x01 : 0x00;
-		lgs8gxx_write_reg(priv, 0x0C, t1);
-		lgs8gxx_write_reg(priv, 0x18, t2);
-	} else {
-		lgs8gxx_write_reg(priv, 0x04, gi);
-	}
-	lgs8gxx_soft_reset(priv);
-	err = lgs8gxx_wait_ca_lock(priv, locked);
-	if (err || !(*locked))
-		return err;
-	err = lgs8gxx_is_autodetect_finished(priv, &ad_fini);
-	if (err != 0)
-		return err;
-	if (ad_fini) {
-		dprintk("auto detect finished\n");
-	} else
-		*locked = 0;
-
-	return 0;
-}
-
-static int lgs8gxx_auto_detect(struct lgs8gxx_state *priv,
-			       u8 *detected_param, u8 *gi)
-{
-	int i, j;
-	int err = 0;
-	u8 locked = 0, tmp_gi;
-
-	dprintk("%s\n", __func__);
-
-	lgs8gxx_set_mode_auto(priv);
-	if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
-		lgs8gxx_write_reg(priv, 0x67, 0xAA);
-		lgs8gxx_write_reg(priv, 0x6E, 0x3F);
-	} else {
-		/* Guard Interval */
-		lgs8gxx_write_reg(priv, 0x03, 00);
-	}
-
-	for (i = 0; i < 2; i++) {
-		for (j = 0; j < 2; j++) {
-			tmp_gi = GI_945;
-			err = lgs8gxx_autolock_gi(priv, GI_945, j, &locked);
-			if (err)
-				goto out;
-			if (locked)
-				goto locked;
-		}
-		for (j = 0; j < 2; j++) {
-			tmp_gi = GI_420;
-			err = lgs8gxx_autolock_gi(priv, GI_420, j, &locked);
-			if (err)
-				goto out;
-			if (locked)
-				goto locked;
-		}
-		tmp_gi = GI_595;
-		err = lgs8gxx_autolock_gi(priv, GI_595, 1, &locked);
-		if (err)
-			goto out;
-		if (locked)
-			goto locked;
-	}
-
-locked:
-	if ((err == 0) && (locked == 1)) {
-		u8 t;
-
-		if (priv->config->prod != LGS8GXX_PROD_LGS8G75) {
-			lgs8gxx_read_reg(priv, 0xA2, &t);
-			*detected_param = t;
-		} else {
-			lgs8gxx_read_reg(priv, 0x1F, &t);
-			*detected_param = t & 0x3F;
-		}
-
-		if (tmp_gi == GI_945)
-			dprintk("GI 945 locked\n");
-		else if (tmp_gi == GI_595)
-			dprintk("GI 595 locked\n");
-		else if (tmp_gi == GI_420)
-			dprintk("GI 420 locked\n");
-		*gi = tmp_gi;
-	}
-	if (!locked)
-		err = -1;
-
-out:
-	return err;
-}
-
-static void lgs8gxx_auto_lock(struct lgs8gxx_state *priv)
-{
-	s8 err;
-	u8 gi = 0x2;
-	u8 detected_param = 0;
-
-	err = lgs8gxx_auto_detect(priv, &detected_param, &gi);
-
-	if (err != 0) {
-		dprintk("lgs8gxx_auto_detect failed\n");
-	} else
-		dprintk("detected param = 0x%02X\n", detected_param);
-
-	/* Apply detected parameters */
-	if (priv->config->prod == LGS8GXX_PROD_LGS8913) {
-		u8 inter_leave_len = detected_param & TIM_MASK ;
-		/* Fix 8913 time interleaver detection bug */
-		inter_leave_len = (inter_leave_len == TIM_MIDDLE) ? 0x60 : 0x40;
-		detected_param &= CF_MASK | SC_MASK  | LGS_FEC_MASK;
-		detected_param |= inter_leave_len;
-	}
-	if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
-		u8 t;
-		lgs8gxx_read_reg(priv, 0x19, &t);
-		t &= 0x81;
-		t |= detected_param << 1;
-		lgs8gxx_write_reg(priv, 0x19, t);
-	} else {
-		lgs8gxx_write_reg(priv, 0x7D, detected_param);
-		if (priv->config->prod == LGS8GXX_PROD_LGS8913)
-			lgs8gxx_write_reg(priv, 0xC0, detected_param);
-	}
-	/* lgs8gxx_soft_reset(priv); */
-
-	/* Enter manual mode */
-	lgs8gxx_set_mode_manual(priv);
-
-	switch (gi) {
-	case GI_945:
-		priv->curr_gi = 945; break;
-	case GI_595:
-		priv->curr_gi = 595; break;
-	case GI_420:
-		priv->curr_gi = 420; break;
-	default:
-		priv->curr_gi = 945; break;
-	}
-}
-
-static int lgs8gxx_set_mpeg_mode(struct lgs8gxx_state *priv,
-	u8 serial, u8 clk_pol, u8 clk_gated)
-{
-	int ret = 0;
-	u8 t, reg_addr;
-
-	reg_addr = (priv->config->prod == LGS8GXX_PROD_LGS8G75) ? 0x30 : 0xC2;
-	ret = lgs8gxx_read_reg(priv, reg_addr, &t);
-	if (ret != 0)
-		return ret;
-
-	t &= 0xF8;
-	t |= serial ? TS_SERIAL : TS_PARALLEL;
-	t |= clk_pol ? TS_CLK_INVERTED : TS_CLK_NORMAL;
-	t |= clk_gated ? TS_CLK_GATED : TS_CLK_FREERUN;
-
-	ret = lgs8gxx_write_reg(priv, reg_addr, t);
-	if (ret != 0)
-		return ret;
-
-	return 0;
-}
-
-/* A/D input peak-to-peak voltage range */
-static int lgs8g75_set_adc_vpp(struct lgs8gxx_state *priv,
-	u8 sel)
-{
-	u8 r26 = 0x73, r27 = 0x90;
-
-	if (priv->config->prod != LGS8GXX_PROD_LGS8G75)
-		return 0;
-
-	r26 |= (sel & 0x01) << 7;
-	r27 |= (sel & 0x02) >> 1;
-	lgs8gxx_write_reg(priv, 0x26, r26);
-	lgs8gxx_write_reg(priv, 0x27, r27);
-
-	return 0;
-}
-
-/* LGS8913 demod frontend functions */
-
-static int lgs8913_init(struct lgs8gxx_state *priv)
-{
-	u8 t;
-
-	/* LGS8913 specific */
-	lgs8gxx_write_reg(priv, 0xc1, 0x3);
-
-	lgs8gxx_read_reg(priv, 0x7c, &t);
-	lgs8gxx_write_reg(priv, 0x7c, (t&0x8c) | 0x3);
-
-	/* LGS8913 specific */
-	lgs8gxx_read_reg(priv, 0xc3, &t);
-	lgs8gxx_write_reg(priv, 0xc3, t&0x10);
-
-
-	return 0;
-}
-
-static int lgs8g75_init_data(struct lgs8gxx_state *priv)
-{
-	const struct firmware *fw;
-	int rc;
-	int i;
-
-	rc = request_firmware(&fw, LGS8GXX_FIRMWARE, &priv->i2c->dev);
-	if (rc)
-		return rc;
-
-	lgs8gxx_write_reg(priv, 0xC6, 0x40);
-
-	lgs8gxx_write_reg(priv, 0x3D, 0x04);
-	lgs8gxx_write_reg(priv, 0x39, 0x00);
-
-	lgs8gxx_write_reg(priv, 0x3A, 0x00);
-	lgs8gxx_write_reg(priv, 0x38, 0x00);
-	lgs8gxx_write_reg(priv, 0x3B, 0x00);
-	lgs8gxx_write_reg(priv, 0x38, 0x00);
-
-	for (i = 0; i < fw->size; i++) {
-		lgs8gxx_write_reg(priv, 0x38, 0x00);
-		lgs8gxx_write_reg(priv, 0x3A, (u8)(i&0xff));
-		lgs8gxx_write_reg(priv, 0x3B, (u8)(i>>8));
-		lgs8gxx_write_reg(priv, 0x3C, fw->data[i]);
-	}
-
-	lgs8gxx_write_reg(priv, 0x38, 0x00);
-
-	release_firmware(fw);
-	return 0;
-}
-
-static int lgs8gxx_init(struct dvb_frontend *fe)
-{
-	struct lgs8gxx_state *priv =
-		(struct lgs8gxx_state *)fe->demodulator_priv;
-	const struct lgs8gxx_config *config = priv->config;
-	u8 data = 0;
-	s8 err;
-	dprintk("%s\n", __func__);
-
-	lgs8gxx_read_reg(priv, 0, &data);
-	dprintk("reg 0 = 0x%02X\n", data);
-
-	if (config->prod == LGS8GXX_PROD_LGS8G75)
-		lgs8g75_set_adc_vpp(priv, config->adc_vpp);
-
-	/* Setup MPEG output format */
-	err = lgs8gxx_set_mpeg_mode(priv, config->serial_ts,
-				    config->ts_clk_pol,
-				    config->ts_clk_gated);
-	if (err != 0)
-		return -EIO;
-
-	if (config->prod == LGS8GXX_PROD_LGS8913)
-		lgs8913_init(priv);
-	lgs8gxx_set_if_freq(priv, priv->config->if_freq);
-	lgs8gxx_set_ad_mode(priv);
-
-	return 0;
-}
-
-static void lgs8gxx_release(struct dvb_frontend *fe)
-{
-	struct lgs8gxx_state *state = fe->demodulator_priv;
-	dprintk("%s\n", __func__);
-
-	kfree(state);
-}
-
-
-static int lgs8gxx_write(struct dvb_frontend *fe, const u8 buf[], int len)
-{
-	struct lgs8gxx_state *priv = fe->demodulator_priv;
-
-	if (len != 2)
-		return -EINVAL;
-
-	return lgs8gxx_write_reg(priv, buf[0], buf[1]);
-}
-
-static int lgs8gxx_set_fe(struct dvb_frontend *fe)
-{
-
-	struct lgs8gxx_state *priv = fe->demodulator_priv;
-
-	dprintk("%s\n", __func__);
-
-	/* set frequency */
-	if (fe->ops.tuner_ops.set_params) {
-		fe->ops.tuner_ops.set_params(fe);
-		if (fe->ops.i2c_gate_ctrl)
-			fe->ops.i2c_gate_ctrl(fe, 0);
-	}
-
-	/* start auto lock */
-	lgs8gxx_auto_lock(priv);
-
-	msleep(10);
-
-	return 0;
-}
-
-static int lgs8gxx_get_fe(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *fe_params = &fe->dtv_property_cache;
-	dprintk("%s\n", __func__);
-
-	/* TODO: get real readings from device */
-	/* inversion status */
-	fe_params->inversion = INVERSION_OFF;
-
-	/* bandwidth */
-	fe_params->bandwidth_hz = 8000000;
-
-	fe_params->code_rate_HP = FEC_AUTO;
-	fe_params->code_rate_LP = FEC_AUTO;
-
-	fe_params->modulation = QAM_AUTO;
-
-	/* transmission mode */
-	fe_params->transmission_mode = TRANSMISSION_MODE_AUTO;
-
-	/* guard interval */
-	fe_params->guard_interval = GUARD_INTERVAL_AUTO;
-
-	/* hierarchy */
-	fe_params->hierarchy = HIERARCHY_NONE;
-
-	return 0;
-}
-
-static
-int lgs8gxx_get_tune_settings(struct dvb_frontend *fe,
-			      struct dvb_frontend_tune_settings *fesettings)
-{
-	/* FIXME: copy from tda1004x.c */
-	fesettings->min_delay_ms = 800;
-	fesettings->step_size = 0;
-	fesettings->max_drift = 0;
-	return 0;
-}
-
-static int lgs8gxx_read_status(struct dvb_frontend *fe, fe_status_t *fe_status)
-{
-	struct lgs8gxx_state *priv = fe->demodulator_priv;
-	s8 ret;
-	u8 t, locked = 0;
-
-	dprintk("%s\n", __func__);
-	*fe_status = 0;
-
-	lgs8gxx_get_afc_phase(priv);
-	lgs8gxx_is_locked(priv, &locked);
-	if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
-		if (locked)
-			*fe_status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
-				FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
-		return 0;
-	}
-
-	ret = lgs8gxx_read_reg(priv, 0x4B, &t);
-	if (ret != 0)
-		return -EIO;
-
-	dprintk("Reg 0x4B: 0x%02X\n", t);
-
-	*fe_status = 0;
-	if (priv->config->prod == LGS8GXX_PROD_LGS8913) {
-		if ((t & 0x40) == 0x40)
-			*fe_status |= FE_HAS_SIGNAL | FE_HAS_CARRIER;
-		if ((t & 0x80) == 0x80)
-			*fe_status |= FE_HAS_VITERBI | FE_HAS_SYNC |
-				FE_HAS_LOCK;
-	} else {
-		if ((t & 0x80) == 0x80)
-			*fe_status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
-				FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
-	}
-
-	/* success */
-	dprintk("%s: fe_status=0x%x\n", __func__, *fe_status);
-	return 0;
-}
-
-static int lgs8gxx_read_signal_agc(struct lgs8gxx_state *priv, u16 *signal)
-{
-	u16 v;
-	u8 agc_lvl[2], cat;
-
-	dprintk("%s()\n", __func__);
-	lgs8gxx_read_reg(priv, 0x3F, &agc_lvl[0]);
-	lgs8gxx_read_reg(priv, 0x3E, &agc_lvl[1]);
-
-	v = agc_lvl[0];
-	v <<= 8;
-	v |= agc_lvl[1];
-
-	dprintk("agc_lvl: 0x%04X\n", v);
-
-	if (v < 0x100)
-		cat = 0;
-	else if (v < 0x190)
-		cat = 5;
-	else if (v < 0x2A8)
-		cat = 4;
-	else if (v < 0x381)
-		cat = 3;
-	else if (v < 0x400)
-		cat = 2;
-	else if (v == 0x400)
-		cat = 1;
-	else
-		cat = 0;
-
-	*signal = cat * 65535 / 5;
-
-	return 0;
-}
-
-static int lgs8913_read_signal_strength(struct lgs8gxx_state *priv, u16 *signal)
-{
-	u8 t; s8 ret;
-	s16 max_strength = 0;
-	u8 str;
-	u16 i, gi = priv->curr_gi;
-
-	dprintk("%s\n", __func__);
-
-	ret = lgs8gxx_read_reg(priv, 0x4B, &t);
-	if (ret != 0)
-		return -EIO;
-
-	if (fake_signal_str) {
-		if ((t & 0xC0) == 0xC0) {
-			dprintk("Fake signal strength\n");
-			*signal = 0x7FFF;
-		} else
-			*signal = 0;
-		return 0;
-	}
-
-	dprintk("gi = %d\n", gi);
-	for (i = 0; i < gi; i++) {
-
-		if ((i & 0xFF) == 0)
-			lgs8gxx_write_reg(priv, 0x84, 0x03 & (i >> 8));
-		lgs8gxx_write_reg(priv, 0x83, i & 0xFF);
-
-		lgs8gxx_read_reg(priv, 0x94, &str);
-		if (max_strength < str)
-			max_strength = str;
-	}
-
-	*signal = max_strength;
-	dprintk("%s: signal=0x%02X\n", __func__, *signal);
-
-	lgs8gxx_read_reg(priv, 0x95, &t);
-	dprintk("%s: AVG Noise=0x%02X\n", __func__, t);
-
-	return 0;
-}
-
-static int lgs8g75_read_signal_strength(struct lgs8gxx_state *priv, u16 *signal)
-{
-	u8 t;
-	s16 v = 0;
-
-	dprintk("%s\n", __func__);
-
-	lgs8gxx_read_reg(priv, 0xB1, &t);
-	v |= t;
-	v <<= 8;
-	lgs8gxx_read_reg(priv, 0xB0, &t);
-	v |= t;
-
-	*signal = v;
-	dprintk("%s: signal=0x%02X\n", __func__, *signal);
-
-	return 0;
-}
-
-static int lgs8gxx_read_signal_strength(struct dvb_frontend *fe, u16 *signal)
-{
-	struct lgs8gxx_state *priv = fe->demodulator_priv;
-
-	if (priv->config->prod == LGS8GXX_PROD_LGS8913)
-		return lgs8913_read_signal_strength(priv, signal);
-	else if (priv->config->prod == LGS8GXX_PROD_LGS8G75)
-		return lgs8g75_read_signal_strength(priv, signal);
-	else
-		return lgs8gxx_read_signal_agc(priv, signal);
-}
-
-static int lgs8gxx_read_snr(struct dvb_frontend *fe, u16 *snr)
-{
-	struct lgs8gxx_state *priv = fe->demodulator_priv;
-	u8 t;
-	*snr = 0;
-
-	if (priv->config->prod == LGS8GXX_PROD_LGS8G75)
-		lgs8gxx_read_reg(priv, 0x34, &t);
-	else
-		lgs8gxx_read_reg(priv, 0x95, &t);
-	dprintk("AVG Noise=0x%02X\n", t);
-	*snr = 256 - t;
-	*snr <<= 8;
-	dprintk("snr=0x%x\n", *snr);
-
-	return 0;
-}
-
-static int lgs8gxx_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
-{
-	*ucblocks = 0;
-	dprintk("%s: ucblocks=0x%x\n", __func__, *ucblocks);
-	return 0;
-}
-
-static void packet_counter_start(struct lgs8gxx_state *priv)
-{
-	u8 orig, t;
-
-	if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
-		lgs8gxx_read_reg(priv, 0x30, &orig);
-		orig &= 0xE7;
-		t = orig | 0x10;
-		lgs8gxx_write_reg(priv, 0x30, t);
-		t = orig | 0x18;
-		lgs8gxx_write_reg(priv, 0x30, t);
-		t = orig | 0x10;
-		lgs8gxx_write_reg(priv, 0x30, t);
-	} else {
-		lgs8gxx_write_reg(priv, 0xC6, 0x01);
-		lgs8gxx_write_reg(priv, 0xC6, 0x41);
-		lgs8gxx_write_reg(priv, 0xC6, 0x01);
-	}
-}
-
-static void packet_counter_stop(struct lgs8gxx_state *priv)
-{
-	u8 t;
-
-	if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
-		lgs8gxx_read_reg(priv, 0x30, &t);
-		t &= 0xE7;
-		lgs8gxx_write_reg(priv, 0x30, t);
-	} else {
-		lgs8gxx_write_reg(priv, 0xC6, 0x81);
-	}
-}
-
-static int lgs8gxx_read_ber(struct dvb_frontend *fe, u32 *ber)
-{
-	struct lgs8gxx_state *priv = fe->demodulator_priv;
-	u8 reg_err, reg_total, t;
-	u32 total_cnt = 0, err_cnt = 0;
-	int i;
-
-	dprintk("%s\n", __func__);
-
-	packet_counter_start(priv);
-	msleep(200);
-	packet_counter_stop(priv);
-
-	if (priv->config->prod == LGS8GXX_PROD_LGS8G75) {
-		reg_total = 0x28; reg_err = 0x2C;
-	} else {
-		reg_total = 0xD0; reg_err = 0xD4;
-	}
-
-	for (i = 0; i < 4; i++) {
-		total_cnt <<= 8;
-		lgs8gxx_read_reg(priv, reg_total+3-i, &t);
-		total_cnt |= t;
-	}
-	for (i = 0; i < 4; i++) {
-		err_cnt <<= 8;
-		lgs8gxx_read_reg(priv, reg_err+3-i, &t);
-		err_cnt |= t;
-	}
-	dprintk("error=%d total=%d\n", err_cnt, total_cnt);
-
-	if (total_cnt == 0)
-		*ber = 0;
-	else
-		*ber = err_cnt * 100 / total_cnt;
-
-	dprintk("%s: ber=0x%x\n", __func__, *ber);
-	return 0;
-}
-
-static int lgs8gxx_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
-{
-	struct lgs8gxx_state *priv = fe->demodulator_priv;
-
-	if (priv->config->tuner_address == 0)
-		return 0;
-	if (enable) {
-		u8 v = 0x80 | priv->config->tuner_address;
-		return lgs8gxx_write_reg(priv, 0x01, v);
-	}
-	return lgs8gxx_write_reg(priv, 0x01, 0);
-}
-
-static struct dvb_frontend_ops lgs8gxx_ops = {
-	.delsys = { SYS_DMBTH },
-	.info = {
-		.name = "Legend Silicon LGS8913/LGS8GXX DMB-TH",
-		.frequency_min = 474000000,
-		.frequency_max = 858000000,
-		.frequency_stepsize = 10000,
-		.caps =
-			FE_CAN_FEC_AUTO |
-			FE_CAN_QAM_AUTO |
-			FE_CAN_TRANSMISSION_MODE_AUTO |
-			FE_CAN_GUARD_INTERVAL_AUTO
-	},
-
-	.release = lgs8gxx_release,
-
-	.init = lgs8gxx_init,
-	.write = lgs8gxx_write,
-	.i2c_gate_ctrl = lgs8gxx_i2c_gate_ctrl,
-
-	.set_frontend = lgs8gxx_set_fe,
-	.get_frontend = lgs8gxx_get_fe,
-	.get_tune_settings = lgs8gxx_get_tune_settings,
-
-	.read_status = lgs8gxx_read_status,
-	.read_ber = lgs8gxx_read_ber,
-	.read_signal_strength = lgs8gxx_read_signal_strength,
-	.read_snr = lgs8gxx_read_snr,
-	.read_ucblocks = lgs8gxx_read_ucblocks,
-};
-
-struct dvb_frontend *lgs8gxx_attach(const struct lgs8gxx_config *config,
-	struct i2c_adapter *i2c)
-{
-	struct lgs8gxx_state *priv = NULL;
-	u8 data = 0;
-
-	dprintk("%s()\n", __func__);
-
-	if (config == NULL || i2c == NULL)
-		return NULL;
-
-	priv = kzalloc(sizeof(struct lgs8gxx_state), GFP_KERNEL);
-	if (priv == NULL)
-		goto error_out;
-
-	priv->config = config;
-	priv->i2c = i2c;
-
-	/* check if the demod is there */
-	if (lgs8gxx_read_reg(priv, 0, &data) != 0) {
-		dprintk("%s lgs8gxx not found at i2c addr 0x%02X\n",
-			__func__, priv->config->demod_address);
-		goto error_out;
-	}
-
-	lgs8gxx_read_reg(priv, 1, &data);
-
-	memcpy(&priv->frontend.ops, &lgs8gxx_ops,
-	       sizeof(struct dvb_frontend_ops));
-	priv->frontend.demodulator_priv = priv;
-
-	if (config->prod == LGS8GXX_PROD_LGS8G75)
-		lgs8g75_init_data(priv);
-
-	return &priv->frontend;
-
-error_out:
-	dprintk("%s() error_out\n", __func__);
-	kfree(priv);
-	return NULL;
-
-}
-EXPORT_SYMBOL(lgs8gxx_attach);
-
-MODULE_DESCRIPTION("Legend Silicon LGS8913/LGS8GXX DMB-TH demodulator driver");
-MODULE_AUTHOR("David T. L. Wong <davidtlwong@gmail.com>");
-MODULE_LICENSE("GPL");
-MODULE_FIRMWARE(LGS8GXX_FIRMWARE);
diff --git a/drivers/media/dvb/frontends/lgs8gxx.h b/drivers/media/dvb/frontends/lgs8gxx.h
deleted file mode 100644
index 33c3c5e..0000000
--- a/drivers/media/dvb/frontends/lgs8gxx.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- *    Support for Legend Silicon GB20600 (a.k.a DMB-TH) demodulator
- *    LGS8913, LGS8GL5, LGS8G75
- *    experimental support LGS8G42, LGS8G52
- *
- *    Copyright (C) 2007-2009 David T.L. Wong <davidtlwong@gmail.com>
- *    Copyright (C) 2008 Sirius International (Hong Kong) Limited
- *    Timothy Lee <timothy.lee@siriushk.com> (for initial work on LGS8GL5)
- *
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the 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 __LGS8GXX_H__
-#define __LGS8GXX_H__
-
-#include <linux/dvb/frontend.h>
-#include <linux/i2c.h>
-
-#define LGS8GXX_PROD_LGS8913 0
-#define LGS8GXX_PROD_LGS8GL5 1
-#define LGS8GXX_PROD_LGS8G42 3
-#define LGS8GXX_PROD_LGS8G52 4
-#define LGS8GXX_PROD_LGS8G54 5
-#define LGS8GXX_PROD_LGS8G75 6
-
-struct lgs8gxx_config {
-
-	/* product type */
-	u8 prod;
-
-	/* the demodulator's i2c address */
-	u8 demod_address;
-
-	/* parallel or serial transport stream */
-	u8 serial_ts;
-
-	/* transport stream polarity*/
-	u8 ts_clk_pol;
-
-	/* transport stream clock gated by ts_valid */
-	u8 ts_clk_gated;
-
-	/* A/D Clock frequency */
-	u32 if_clk_freq; /* in kHz */
-
-	/* IF frequency */
-	u32 if_freq; /* in kHz */
-
-	/*Use External ADC*/
-	u8 ext_adc;
-
-	/*External ADC output two's complement*/
-	u8 adc_signed;
-
-	/*Sample IF data at falling edge of IF_CLK*/
-	u8 if_neg_edge;
-
-	/*IF use Negative center frequency*/
-	u8 if_neg_center;
-
-	/*8G75 internal ADC input range selection*/
-	/*0: 0.8Vpp, 1: 1.0Vpp, 2: 1.6Vpp, 3: 2.0Vpp*/
-	u8 adc_vpp;
-
-	/* slave address and configuration of the tuner */
-	u8 tuner_address;
-};
-
-#if defined(CONFIG_DVB_LGS8GXX) || \
-	(defined(CONFIG_DVB_LGS8GXX_MODULE) && defined(MODULE))
-extern struct dvb_frontend *lgs8gxx_attach(const struct lgs8gxx_config *config,
-					   struct i2c_adapter *i2c);
-#else
-static inline
-struct dvb_frontend *lgs8gxx_attach(const struct lgs8gxx_config *config,
-				    struct i2c_adapter *i2c) {
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif /* CONFIG_DVB_LGS8GXX */
-
-#endif /* __LGS8GXX_H__ */
diff --git a/drivers/media/dvb/frontends/lgs8gxx_priv.h b/drivers/media/dvb/frontends/lgs8gxx_priv.h
deleted file mode 100644
index 8ef376f..0000000
--- a/drivers/media/dvb/frontends/lgs8gxx_priv.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- *    Support for Legend Silicon GB20600 (a.k.a DMB-TH) demodulator
- *    LGS8913, LGS8GL5, LGS8G75
- *    experimental support LGS8G42, LGS8G52
- *
- *    Copyright (C) 2007-2009 David T.L. Wong <davidtlwong@gmail.com>
- *    Copyright (C) 2008 Sirius International (Hong Kong) Limited
- *    Timothy Lee <timothy.lee@siriushk.com> (for initial work on LGS8GL5)
- *
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the 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 LGS8913_PRIV_H
-#define LGS8913_PRIV_H
-
-struct lgs8gxx_state {
-	struct i2c_adapter *i2c;
-	/* configuration settings */
-	const struct lgs8gxx_config *config;
-	struct dvb_frontend frontend;
-	u16 curr_gi; /* current guard interval */
-};
-
-#define SC_MASK		0x1C	/* Sub-Carrier Modulation Mask */
-#define SC_QAM64	0x10	/* 64QAM modulation */
-#define SC_QAM32	0x0C	/* 32QAM modulation */
-#define SC_QAM16	0x08	/* 16QAM modulation */
-#define SC_QAM4NR	0x04	/* 4QAM-NR modulation */
-#define SC_QAM4		0x00	/* 4QAM modulation */
-
-#define LGS_FEC_MASK	0x03	/* FEC Rate Mask */
-#define LGS_FEC_0_4	0x00	/* FEC Rate 0.4 */
-#define LGS_FEC_0_6	0x01	/* FEC Rate 0.6 */
-#define LGS_FEC_0_8	0x02	/* FEC Rate 0.8 */
-
-#define TIM_MASK	  0x20	/* Time Interleave Length Mask */
-#define TIM_LONG	  0x20	/* Time Interleave Length = 720 */
-#define TIM_MIDDLE     0x00   /* Time Interleave Length = 240 */
-
-#define CF_MASK	0x80	/* Control Frame Mask */
-#define CF_EN	0x80	/* Control Frame On */
-
-#define GI_MASK	0x03	/* Guard Interval Mask */
-#define GI_420	0x00	/* 1/9 Guard Interval */
-#define GI_595	0x01	/* */
-#define GI_945	0x02	/* 1/4 Guard Interval */
-
-
-#define TS_PARALLEL	0x00	/* Parallel TS Output a.k.a. SPI */
-#define TS_SERIAL	0x01	/* Serial TS Output a.k.a. SSI */
-#define TS_CLK_NORMAL		0x00	/* MPEG Clock Normal */
-#define TS_CLK_INVERTED		0x02	/* MPEG Clock Inverted */
-#define TS_CLK_GATED		0x00	/* MPEG clock gated */
-#define TS_CLK_FREERUN		0x04	/* MPEG clock free running*/
-
-
-#endif
diff --git a/drivers/media/dvb/frontends/lnbh24.h b/drivers/media/dvb/frontends/lnbh24.h
deleted file mode 100644
index c059b16..0000000
--- a/drivers/media/dvb/frontends/lnbh24.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * 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
deleted file mode 100644
index 1343725..0000000
--- a/drivers/media/dvb/frontends/lnbp21.c
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * lnbp21.c - driver for lnb supply and control ic lnbp21
- *
- * Copyright (C) 2006, 2009 Oliver Endriss <o.endriss@gmx.de>
- * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- *
- *
- * the project's page is at http://www.linuxtv.org
- */
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-
-#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)
-{
-	struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->sec_priv;
-	struct i2c_msg msg = {	.addr = lnbp21->i2c_addr, .flags = 0,
-				.buf = &lnbp21->config,
-				.len = sizeof(lnbp21->config) };
-
-	lnbp21->config &= ~(LNBP21_VSEL | LNBP21_EN);
-
-	switch(voltage) {
-	case SEC_VOLTAGE_OFF:
-		break;
-	case SEC_VOLTAGE_13:
-		lnbp21->config |= LNBP21_EN;
-		break;
-	case SEC_VOLTAGE_18:
-		lnbp21->config |= (LNBP21_EN | LNBP21_VSEL);
-		break;
-	default:
-		return -EINVAL;
-	};
-
-	lnbp21->config |= lnbp21->override_or;
-	lnbp21->config &= lnbp21->override_and;
-
-	return (i2c_transfer(lnbp21->i2c, &msg, 1) == 1) ? 0 : -EIO;
-}
-
-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 = lnbp21->i2c_addr, .flags = 0,
-				.buf = &lnbp21->config,
-				.len = sizeof(lnbp21->config) };
-
-	if (arg)
-		lnbp21->config |= LNBP21_LLC;
-	else
-		lnbp21->config &= ~LNBP21_LLC;
-
-	lnbp21->config |= lnbp21->override_or;
-	lnbp21->config &= lnbp21->override_and;
-
-	return (i2c_transfer(lnbp21->i2c, &msg, 1) == 1) ? 0 : -EIO;
-}
-
-static int lnbp21_set_tone(struct dvb_frontend *fe,
-				fe_sec_tone_mode_t tone)
-{
-	struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->sec_priv;
-	struct i2c_msg msg = {	.addr = lnbp21->i2c_addr, .flags = 0,
-				.buf = &lnbp21->config,
-				.len = sizeof(lnbp21->config) };
-
-	switch (tone) {
-	case SEC_TONE_OFF:
-		lnbp21->config &= ~LNBP21_TEN;
-		break;
-	case SEC_TONE_ON:
-		lnbp21->config |= LNBP21_TEN;
-		break;
-	default:
-		return -EINVAL;
-	};
-
-	lnbp21->config |= lnbp21->override_or;
-	lnbp21->config &= lnbp21->override_and;
-
-	return (i2c_transfer(lnbp21->i2c, &msg, 1) == 1) ? 0 : -EIO;
-}
-
-static void lnbp21_release(struct dvb_frontend *fe)
-{
-	/* LNBP power off */
-	lnbp21_set_voltage(fe, SEC_VOLTAGE_OFF);
-
-	/* free data */
-	kfree(fe->sec_priv);
-	fe->sec_priv = NULL;
-}
-
-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 = config;
-	lnbp21->i2c = i2c;
-	lnbp21->i2c_addr = i2c_addr;
-	fe->sec_priv = lnbp21;
-
-	/* bits which should be forced to '1' */
-	lnbp21->override_or = override_set;
-
-	/* bits which should be forced to '0' */
-	lnbp21->override_and = ~override_clear;
-
-	/* detect if it is present or not */
-	if (lnbp21_set_voltage(fe, SEC_VOLTAGE_OFF)) {
-		kfree(lnbp21);
-		return NULL;
-	}
-
-	/* install release callback */
-	fe->ops.release_sec = lnbp21_release;
-
-	/* override frontend ops */
-	fe->ops.set_voltage = lnbp21_set_voltage;
-	fe->ops.enable_high_lnb_voltage = lnbp21_enable_high_lnb_voltage;
-	if (!(override_clear & LNBH24_TEN)) /*22kHz logic controlled by demod*/
-		fe->ops.set_tone = lnbp21_set_tone;
-	printk(KERN_INFO "LNBx2x attached on addr=%x\n", 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, 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
deleted file mode 100644
index fcdf1c6..0000000
--- a/drivers/media/dvb/frontends/lnbp21.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * lnbp21.h - driver for lnb supply and control ic lnbp21
- *
- * Copyright (C) 2006 Oliver Endriss
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the 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.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- *
- *
- * the project's page is at http://www.linuxtv.org
- */
-
-#ifndef _LNBP21_H
-#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);
-#else
-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
-
-#endif
diff --git a/drivers/media/dvb/frontends/lnbp22.c b/drivers/media/dvb/frontends/lnbp22.c
deleted file mode 100644
index 84ad039..0000000
--- a/drivers/media/dvb/frontends/lnbp22.c
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * lnbp22.h - driver for lnb supply and control ic lnbp22
- *
- * Copyright (C) 2006 Dominik Kuhlen
- * Based on lnbp21 driver
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- *
- *
- * the project's page is at http://www.linuxtv.org
- */
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-
-#include "dvb_frontend.h"
-#include "lnbp22.h"
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
-
-
-#define dprintk(lvl, arg...) if (debug >= (lvl)) printk(arg)
-
-struct lnbp22 {
-	u8		    config[4];
-	struct i2c_adapter *i2c;
-};
-
-static int lnbp22_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
-{
-	struct lnbp22 *lnbp22 = (struct lnbp22 *)fe->sec_priv;
-	struct i2c_msg msg = {
-		.addr = 0x08,
-		.flags = 0,
-		.buf = (char *)&lnbp22->config,
-		.len = sizeof(lnbp22->config),
-	};
-
-	dprintk(1, "%s: %d (18V=%d 13V=%d)\n", __func__, voltage,
-	       SEC_VOLTAGE_18, SEC_VOLTAGE_13);
-
-	lnbp22->config[3] = 0x60; /* Power down */
-	switch (voltage) {
-	case SEC_VOLTAGE_OFF:
-		break;
-	case SEC_VOLTAGE_13:
-		lnbp22->config[3] |= LNBP22_EN;
-		break;
-	case SEC_VOLTAGE_18:
-		lnbp22->config[3] |= (LNBP22_EN | LNBP22_VSEL);
-		break;
-	default:
-		return -EINVAL;
-	};
-
-	dprintk(1, "%s: 0x%02x)\n", __func__, lnbp22->config[3]);
-	return (i2c_transfer(lnbp22->i2c, &msg, 1) == 1) ? 0 : -EIO;
-}
-
-static int lnbp22_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
-{
-	struct lnbp22 *lnbp22 = (struct lnbp22 *) fe->sec_priv;
-	struct i2c_msg msg = {
-		.addr = 0x08,
-		.flags = 0,
-		.buf = (char *)&lnbp22->config,
-		.len = sizeof(lnbp22->config),
-	};
-
-	dprintk(1, "%s: %d\n", __func__, (int)arg);
-	if (arg)
-		lnbp22->config[3] |= LNBP22_LLC;
-	else
-		lnbp22->config[3] &= ~LNBP22_LLC;
-
-	return (i2c_transfer(lnbp22->i2c, &msg, 1) == 1) ? 0 : -EIO;
-}
-
-static void lnbp22_release(struct dvb_frontend *fe)
-{
-	dprintk(1, "%s\n", __func__);
-	/* LNBP power off */
-	lnbp22_set_voltage(fe, SEC_VOLTAGE_OFF);
-
-	/* free data */
-	kfree(fe->sec_priv);
-	fe->sec_priv = NULL;
-}
-
-struct dvb_frontend *lnbp22_attach(struct dvb_frontend *fe,
-					struct i2c_adapter *i2c)
-{
-	struct lnbp22 *lnbp22 = kmalloc(sizeof(struct lnbp22), GFP_KERNEL);
-	if (!lnbp22)
-		return NULL;
-
-	/* default configuration */
-	lnbp22->config[0] = 0x00; /* ? */
-	lnbp22->config[1] = 0x28; /* ? */
-	lnbp22->config[2] = 0x48; /* ? */
-	lnbp22->config[3] = 0x60; /* Power down */
-	lnbp22->i2c = i2c;
-	fe->sec_priv = lnbp22;
-
-	/* detect if it is present or not */
-	if (lnbp22_set_voltage(fe, SEC_VOLTAGE_OFF)) {
-		dprintk(0, "%s LNBP22 not found\n", __func__);
-		kfree(lnbp22);
-		fe->sec_priv = NULL;
-		return NULL;
-	}
-
-	/* install release callback */
-	fe->ops.release_sec = lnbp22_release;
-
-	/* override frontend ops */
-	fe->ops.set_voltage = lnbp22_set_voltage;
-	fe->ops.enable_high_lnb_voltage = lnbp22_enable_high_lnb_voltage;
-
-	return fe;
-}
-EXPORT_SYMBOL(lnbp22_attach);
-
-MODULE_DESCRIPTION("Driver for lnb supply and control ic lnbp22");
-MODULE_AUTHOR("Dominik Kuhlen");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/lnbp22.h b/drivers/media/dvb/frontends/lnbp22.h
deleted file mode 100644
index 63e2dec..0000000
--- a/drivers/media/dvb/frontends/lnbp22.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * lnbp22.h - driver for lnb supply and control ic lnbp22
- *
- * Copyright (C) 2006 Dominik Kuhlen
- * Based on lnbp21.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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- *
- *
- * the project's page is at http://www.linuxtv.org
- */
-
-#ifndef _LNBP22_H
-#define _LNBP22_H
-
-/* Enable */
-#define LNBP22_EN	  0x10
-/* Voltage selection */
-#define LNBP22_VSEL	0x02
-/* Plus 1 Volt Bit */
-#define LNBP22_LLC	0x01
-
-#include <linux/dvb/frontend.h>
-
-#if defined(CONFIG_DVB_LNBP22) || \
-		(defined(CONFIG_DVB_LNBP22_MODULE) && defined(MODULE))
-/*
- * override_set and override_clear control which system register bits (above)
- * to always set & clear
- */
-extern struct dvb_frontend *lnbp22_attach(struct dvb_frontend *fe,
-						struct i2c_adapter *i2c);
-#else
-static inline struct dvb_frontend *lnbp22_attach(struct dvb_frontend *fe,
-						struct i2c_adapter *i2c)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif /* CONFIG_DVB_LNBP22 */
-
-#endif /* _LNBP22_H */
diff --git a/drivers/media/dvb/frontends/m88rs2000.c b/drivers/media/dvb/frontends/m88rs2000.c
deleted file mode 100644
index 312588e..0000000
--- a/drivers/media/dvb/frontends/m88rs2000.c
+++ /dev/null
@@ -1,919 +0,0 @@
-/*
-	Driver for M88RS2000 demodulator and tuner
-
-	Copyright (C) 2012 Malcolm Priestley (tvboxspy@gmail.com)
-	Beta Driver
-
-	Include various calculation code from DS3000 driver.
-	Copyright (C) 2009 Konstantin Dimitrov.
-
-	This program is free software; you can redistribute it and/or modify
-	it under the terms of the 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/init.h>
-#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/jiffies.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/types.h>
-
-
-#include "dvb_frontend.h"
-#include "m88rs2000.h"
-
-struct m88rs2000_state {
-	struct i2c_adapter *i2c;
-	const struct m88rs2000_config *config;
-	struct dvb_frontend frontend;
-	u8 no_lock_count;
-	u32 tuner_frequency;
-	u32 symbol_rate;
-	fe_code_rate_t fec_inner;
-	u8 tuner_level;
-	int errmode;
-};
-
-static int m88rs2000_debug;
-
-module_param_named(debug, m88rs2000_debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able)).");
-
-#define dprintk(level, args...) do { \
-	if (level & m88rs2000_debug) \
-		printk(KERN_DEBUG "m88rs2000-fe: " args); \
-} while (0)
-
-#define deb_info(args...)  dprintk(0x01, args)
-#define info(format, arg...) \
-	printk(KERN_INFO "m88rs2000-fe: " format "\n" , ## arg)
-
-static int m88rs2000_writereg(struct m88rs2000_state *state, u8 tuner,
-	u8 reg, u8 data)
-{
-	int ret;
-	u8 addr = (tuner == 0) ? state->config->tuner_addr :
-		state->config->demod_addr;
-	u8 buf[] = { reg, data };
-	struct i2c_msg msg = {
-		.addr = addr,
-		.flags = 0,
-		.buf = buf,
-		.len = 2
-	};
-
-	ret = i2c_transfer(state->i2c, &msg, 1);
-
-	if (ret != 1)
-		deb_info("%s: writereg error (reg == 0x%02x, val == 0x%02x, "
-			"ret == %i)\n", __func__, reg, data, ret);
-
-	return (ret != 1) ? -EREMOTEIO : 0;
-}
-
-static int m88rs2000_demod_write(struct m88rs2000_state *state, u8 reg, u8 data)
-{
-	return m88rs2000_writereg(state, 1, reg, data);
-}
-
-static int m88rs2000_tuner_write(struct m88rs2000_state *state, u8 reg, u8 data)
-{
-	m88rs2000_demod_write(state, 0x81, 0x84);
-	udelay(10);
-	return m88rs2000_writereg(state, 0, reg, data);
-
-}
-
-static int m88rs2000_write(struct dvb_frontend *fe, const u8 buf[], int len)
-{
-	struct m88rs2000_state *state = fe->demodulator_priv;
-
-	if (len != 2)
-		return -EINVAL;
-
-	return m88rs2000_writereg(state, 1, buf[0], buf[1]);
-}
-
-static u8 m88rs2000_readreg(struct m88rs2000_state *state, u8 tuner, u8 reg)
-{
-	int ret;
-	u8 b0[] = { reg };
-	u8 b1[] = { 0 };
-	u8 addr = (tuner == 0) ? state->config->tuner_addr :
-		state->config->demod_addr;
-	struct i2c_msg msg[] = {
-		{
-			.addr = addr,
-			.flags = 0,
-			.buf = b0,
-			.len = 1
-		}, {
-			.addr = addr,
-			.flags = I2C_M_RD,
-			.buf = b1,
-			.len = 1
-		}
-	};
-
-	ret = i2c_transfer(state->i2c, msg, 2);
-
-	if (ret != 2)
-		deb_info("%s: readreg error (reg == 0x%02x, ret == %i)\n",
-				__func__, reg, ret);
-
-	return b1[0];
-}
-
-static u8 m88rs2000_demod_read(struct m88rs2000_state *state, u8 reg)
-{
-	return m88rs2000_readreg(state, 1, reg);
-}
-
-static u8 m88rs2000_tuner_read(struct m88rs2000_state *state, u8 reg)
-{
-	m88rs2000_demod_write(state, 0x81, 0x85);
-	udelay(10);
-	return m88rs2000_readreg(state, 0, reg);
-}
-
-static int m88rs2000_set_symbolrate(struct dvb_frontend *fe, u32 srate)
-{
-	struct m88rs2000_state *state = fe->demodulator_priv;
-	int ret;
-	u32 temp;
-	u8 b[3];
-
-	if ((srate < 1000000) || (srate > 45000000))
-		return -EINVAL;
-
-	temp = srate / 1000;
-	temp *= 11831;
-	temp /= 68;
-	temp -= 3;
-
-	b[0] = (u8) (temp >> 16) & 0xff;
-	b[1] = (u8) (temp >> 8) & 0xff;
-	b[2] = (u8) temp & 0xff;
-	ret = m88rs2000_demod_write(state, 0x93, b[2]);
-	ret |= m88rs2000_demod_write(state, 0x94, b[1]);
-	ret |= m88rs2000_demod_write(state, 0x95, b[0]);
-
-	deb_info("m88rs2000: m88rs2000_set_symbolrate\n");
-	return ret;
-}
-
-static int m88rs2000_send_diseqc_msg(struct dvb_frontend *fe,
-				    struct dvb_diseqc_master_cmd *m)
-{
-	struct m88rs2000_state *state = fe->demodulator_priv;
-
-	int i;
-	u8 reg;
-	deb_info("%s\n", __func__);
-	m88rs2000_demod_write(state, 0x9a, 0x30);
-	reg = m88rs2000_demod_read(state, 0xb2);
-	reg &= 0x3f;
-	m88rs2000_demod_write(state, 0xb2, reg);
-	for (i = 0; i <  m->msg_len; i++)
-		m88rs2000_demod_write(state, 0xb3 + i, m->msg[i]);
-
-	reg = m88rs2000_demod_read(state, 0xb1);
-	reg &= 0x87;
-	reg |= ((m->msg_len - 1) << 3) | 0x07;
-	reg &= 0x7f;
-	m88rs2000_demod_write(state, 0xb1, reg);
-
-	for (i = 0; i < 15; i++) {
-		if ((m88rs2000_demod_read(state, 0xb1) & 0x40) == 0x0)
-			break;
-		msleep(20);
-	}
-
-	reg = m88rs2000_demod_read(state, 0xb1);
-	if ((reg & 0x40) > 0x0) {
-		reg &= 0x7f;
-		reg |= 0x40;
-		m88rs2000_demod_write(state, 0xb1, reg);
-	}
-
-	reg = m88rs2000_demod_read(state, 0xb2);
-	reg &= 0x3f;
-	reg |= 0x80;
-	m88rs2000_demod_write(state, 0xb2, reg);
-	m88rs2000_demod_write(state, 0x9a, 0xb0);
-
-
-	return 0;
-}
-
-static int m88rs2000_send_diseqc_burst(struct dvb_frontend *fe,
-						fe_sec_mini_cmd_t burst)
-{
-	struct m88rs2000_state *state = fe->demodulator_priv;
-	u8 reg0, reg1;
-	deb_info("%s\n", __func__);
-	m88rs2000_demod_write(state, 0x9a, 0x30);
-	msleep(50);
-	reg0 = m88rs2000_demod_read(state, 0xb1);
-	reg1 = m88rs2000_demod_read(state, 0xb2);
-	/* TODO complete this section */
-	m88rs2000_demod_write(state, 0xb2, reg1);
-	m88rs2000_demod_write(state, 0xb1, reg0);
-	m88rs2000_demod_write(state, 0x9a, 0xb0);
-
-	return 0;
-}
-
-static int m88rs2000_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
-{
-	struct m88rs2000_state *state = fe->demodulator_priv;
-	u8 reg0, reg1;
-	m88rs2000_demod_write(state, 0x9a, 0x30);
-	reg0 = m88rs2000_demod_read(state, 0xb1);
-	reg1 = m88rs2000_demod_read(state, 0xb2);
-
-	reg1 &= 0x3f;
-
-	switch (tone) {
-	case SEC_TONE_ON:
-		reg0 |= 0x4;
-		reg0 &= 0xbc;
-		break;
-	case SEC_TONE_OFF:
-		reg1 |= 0x80;
-		break;
-	default:
-		break;
-	}
-	m88rs2000_demod_write(state, 0xb2, reg1);
-	m88rs2000_demod_write(state, 0xb1, reg0);
-	m88rs2000_demod_write(state, 0x9a, 0xb0);
-	return 0;
-}
-
-struct inittab {
-	u8 cmd;
-	u8 reg;
-	u8 val;
-};
-
-struct inittab m88rs2000_setup[] = {
-	{DEMOD_WRITE, 0x9a, 0x30},
-	{DEMOD_WRITE, 0x00, 0x01},
-	{WRITE_DELAY, 0x19, 0x00},
-	{DEMOD_WRITE, 0x00, 0x00},
-	{DEMOD_WRITE, 0x9a, 0xb0},
-	{DEMOD_WRITE, 0x81, 0xc1},
-	{TUNER_WRITE, 0x42, 0x73},
-	{TUNER_WRITE, 0x05, 0x07},
-	{TUNER_WRITE, 0x20, 0x27},
-	{TUNER_WRITE, 0x07, 0x02},
-	{TUNER_WRITE, 0x11, 0xff},
-	{TUNER_WRITE, 0x60, 0xf9},
-	{TUNER_WRITE, 0x08, 0x01},
-	{TUNER_WRITE, 0x00, 0x41},
-	{DEMOD_WRITE, 0x81, 0x81},
-	{DEMOD_WRITE, 0x86, 0xc6},
-	{DEMOD_WRITE, 0x9a, 0x30},
-	{DEMOD_WRITE, 0xf0, 0x22},
-	{DEMOD_WRITE, 0xf1, 0xbf},
-	{DEMOD_WRITE, 0xb0, 0x45},
-	{DEMOD_WRITE, 0xb2, 0x01}, /* set voltage pin always set 1*/
-	{DEMOD_WRITE, 0x9a, 0xb0},
-	{0xff, 0xaa, 0xff}
-};
-
-struct inittab m88rs2000_shutdown[] = {
-	{DEMOD_WRITE, 0x9a, 0x30},
-	{DEMOD_WRITE, 0xb0, 0x00},
-	{DEMOD_WRITE, 0xf1, 0x89},
-	{DEMOD_WRITE, 0x00, 0x01},
-	{DEMOD_WRITE, 0x9a, 0xb0},
-	{TUNER_WRITE, 0x00, 0x40},
-	{DEMOD_WRITE, 0x81, 0x81},
-	{0xff, 0xaa, 0xff}
-};
-
-struct inittab tuner_reset[] = {
-	{TUNER_WRITE, 0x42, 0x73},
-	{TUNER_WRITE, 0x05, 0x07},
-	{TUNER_WRITE, 0x20, 0x27},
-	{TUNER_WRITE, 0x07, 0x02},
-	{TUNER_WRITE, 0x11, 0xff},
-	{TUNER_WRITE, 0x60, 0xf9},
-	{TUNER_WRITE, 0x08, 0x01},
-	{TUNER_WRITE, 0x00, 0x41},
-	{0xff, 0xaa, 0xff}
-};
-
-struct inittab fe_reset[] = {
-	{DEMOD_WRITE, 0x00, 0x01},
-	{DEMOD_WRITE, 0xf1, 0xbf},
-	{DEMOD_WRITE, 0x00, 0x01},
-	{DEMOD_WRITE, 0x20, 0x81},
-	{DEMOD_WRITE, 0x21, 0x80},
-	{DEMOD_WRITE, 0x10, 0x33},
-	{DEMOD_WRITE, 0x11, 0x44},
-	{DEMOD_WRITE, 0x12, 0x07},
-	{DEMOD_WRITE, 0x18, 0x20},
-	{DEMOD_WRITE, 0x28, 0x04},
-	{DEMOD_WRITE, 0x29, 0x8e},
-	{DEMOD_WRITE, 0x3b, 0xff},
-	{DEMOD_WRITE, 0x32, 0x10},
-	{DEMOD_WRITE, 0x33, 0x02},
-	{DEMOD_WRITE, 0x34, 0x30},
-	{DEMOD_WRITE, 0x35, 0xff},
-	{DEMOD_WRITE, 0x38, 0x50},
-	{DEMOD_WRITE, 0x39, 0x68},
-	{DEMOD_WRITE, 0x3c, 0x7f},
-	{DEMOD_WRITE, 0x3d, 0x0f},
-	{DEMOD_WRITE, 0x45, 0x20},
-	{DEMOD_WRITE, 0x46, 0x24},
-	{DEMOD_WRITE, 0x47, 0x7c},
-	{DEMOD_WRITE, 0x48, 0x16},
-	{DEMOD_WRITE, 0x49, 0x04},
-	{DEMOD_WRITE, 0x4a, 0x01},
-	{DEMOD_WRITE, 0x4b, 0x78},
-	{DEMOD_WRITE, 0X4d, 0xd2},
-	{DEMOD_WRITE, 0x4e, 0x6d},
-	{DEMOD_WRITE, 0x50, 0x30},
-	{DEMOD_WRITE, 0x51, 0x30},
-	{DEMOD_WRITE, 0x54, 0x7b},
-	{DEMOD_WRITE, 0x56, 0x09},
-	{DEMOD_WRITE, 0x58, 0x59},
-	{DEMOD_WRITE, 0x59, 0x37},
-	{DEMOD_WRITE, 0x63, 0xfa},
-	{0xff, 0xaa, 0xff}
-};
-
-struct inittab fe_trigger[] = {
-	{DEMOD_WRITE, 0x97, 0x04},
-	{DEMOD_WRITE, 0x99, 0x77},
-	{DEMOD_WRITE, 0x9b, 0x64},
-	{DEMOD_WRITE, 0x9e, 0x00},
-	{DEMOD_WRITE, 0x9f, 0xf8},
-	{DEMOD_WRITE, 0xa0, 0x20},
-	{DEMOD_WRITE, 0xa1, 0xe0},
-	{DEMOD_WRITE, 0xa3, 0x38},
-	{DEMOD_WRITE, 0x98, 0xff},
-	{DEMOD_WRITE, 0xc0, 0x0f},
-	{DEMOD_WRITE, 0x89, 0x01},
-	{DEMOD_WRITE, 0x00, 0x00},
-	{WRITE_DELAY, 0x0a, 0x00},
-	{DEMOD_WRITE, 0x00, 0x01},
-	{DEMOD_WRITE, 0x00, 0x00},
-	{DEMOD_WRITE, 0x9a, 0xb0},
-	{0xff, 0xaa, 0xff}
-};
-
-static int m88rs2000_tab_set(struct m88rs2000_state *state,
-		struct inittab *tab)
-{
-	int ret = 0;
-	u8 i;
-	if (tab == NULL)
-		return -EINVAL;
-
-	for (i = 0; i < 255; i++) {
-		switch (tab[i].cmd) {
-		case 0x01:
-			ret = m88rs2000_demod_write(state, tab[i].reg,
-				tab[i].val);
-			break;
-		case 0x02:
-			ret = m88rs2000_tuner_write(state, tab[i].reg,
-				tab[i].val);
-			break;
-		case 0x10:
-			if (tab[i].reg > 0)
-				mdelay(tab[i].reg);
-			break;
-		case 0xff:
-			if (tab[i].reg == 0xaa && tab[i].val == 0xff)
-				return 0;
-		case 0x00:
-			break;
-		default:
-			return -EINVAL;
-		}
-		if (ret < 0)
-			return -ENODEV;
-	}
-	return 0;
-}
-
-static int m88rs2000_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t volt)
-{
-	struct m88rs2000_state *state = fe->demodulator_priv;
-	u8 data;
-
-	data = m88rs2000_demod_read(state, 0xb2);
-	data |= 0x03; /* bit0 V/H, bit1 off/on */
-
-	switch (volt) {
-	case SEC_VOLTAGE_18:
-		data &= ~0x03;
-		break;
-	case SEC_VOLTAGE_13:
-		data &= ~0x03;
-		data |= 0x01;
-		break;
-	case SEC_VOLTAGE_OFF:
-		break;
-	}
-
-	m88rs2000_demod_write(state, 0xb2, data);
-
-	return 0;
-}
-
-static int m88rs2000_startup(struct m88rs2000_state *state)
-{
-	int ret = 0;
-	u8 reg;
-
-	reg = m88rs2000_tuner_read(state, 0x00);
-	if ((reg & 0x40) == 0)
-		ret = -ENODEV;
-
-	return ret;
-}
-
-static int m88rs2000_init(struct dvb_frontend *fe)
-{
-	struct m88rs2000_state *state = fe->demodulator_priv;
-	int ret;
-
-	deb_info("m88rs2000: init chip\n");
-	/* Setup frontend from shutdown/cold */
-	ret = m88rs2000_tab_set(state, m88rs2000_setup);
-
-	return ret;
-}
-
-static int m88rs2000_sleep(struct dvb_frontend *fe)
-{
-	struct m88rs2000_state *state = fe->demodulator_priv;
-	int ret;
-	/* Shutdown the frondend */
-	ret = m88rs2000_tab_set(state, m88rs2000_shutdown);
-	return ret;
-}
-
-static int m88rs2000_read_status(struct dvb_frontend *fe, fe_status_t *status)
-{
-	struct m88rs2000_state *state = fe->demodulator_priv;
-	u8 reg = m88rs2000_demod_read(state, 0x8c);
-
-	*status = 0;
-
-	if ((reg & 0x7) == 0x7) {
-		*status = FE_HAS_CARRIER | FE_HAS_SIGNAL | FE_HAS_VITERBI
-			| FE_HAS_LOCK;
-		if (state->config->set_ts_params)
-			state->config->set_ts_params(fe, CALL_IS_READ);
-	}
-	return 0;
-}
-
-/* Extact code for these unknown but lmedm04 driver uses interupt callbacks */
-
-static int m88rs2000_read_ber(struct dvb_frontend *fe, u32 *ber)
-{
-	deb_info("m88rs2000_read_ber %d\n", *ber);
-	*ber = 0;
-	return 0;
-}
-
-static int m88rs2000_read_signal_strength(struct dvb_frontend *fe,
-	u16 *strength)
-{
-	*strength = 0;
-	return 0;
-}
-
-static int m88rs2000_read_snr(struct dvb_frontend *fe, u16 *snr)
-{
-	deb_info("m88rs2000_read_snr %d\n", *snr);
-	*snr = 0;
-	return 0;
-}
-
-static int m88rs2000_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
-{
-	deb_info("m88rs2000_read_ber %d\n", *ucblocks);
-	*ucblocks = 0;
-	return 0;
-}
-
-static int m88rs2000_tuner_gate_ctrl(struct m88rs2000_state *state, u8 offset)
-{
-	int ret;
-	ret = m88rs2000_tuner_write(state, 0x51, 0x1f - offset);
-	ret |= m88rs2000_tuner_write(state, 0x51, 0x1f);
-	ret |= m88rs2000_tuner_write(state, 0x50, offset);
-	ret |= m88rs2000_tuner_write(state, 0x50, 0x00);
-	msleep(20);
-	return ret;
-}
-
-static int m88rs2000_set_tuner_rf(struct dvb_frontend *fe)
-{
-	struct m88rs2000_state *state = fe->demodulator_priv;
-	int reg;
-	reg = m88rs2000_tuner_read(state, 0x3d);
-	reg &= 0x7f;
-	if (reg < 0x16)
-		reg = 0xa1;
-	else if (reg == 0x16)
-		reg = 0x99;
-	else
-		reg = 0xf9;
-
-	m88rs2000_tuner_write(state, 0x60, reg);
-	reg = m88rs2000_tuner_gate_ctrl(state, 0x08);
-
-	if (fe->ops.i2c_gate_ctrl)
-			fe->ops.i2c_gate_ctrl(fe, 0);
-	return reg;
-}
-
-static int m88rs2000_set_tuner(struct dvb_frontend *fe, u16 *offset)
-{
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	struct m88rs2000_state *state = fe->demodulator_priv;
-	int ret;
-	u32 frequency = c->frequency;
-	s32 offset_khz;
-	s32 tmp;
-	u32 symbol_rate = (c->symbol_rate / 1000);
-	u32 f3db, gdiv28;
-	u16 value, ndiv, lpf_coeff;
-	u8 lpf_mxdiv, mlpf_max, mlpf_min, nlpf;
-	u8 lo = 0x01, div4 = 0x0;
-
-	/* Reset Tuner */
-	ret = m88rs2000_tab_set(state, tuner_reset);
-
-	/* Calculate frequency divider */
-	if (frequency < 1060000) {
-		lo |= 0x10;
-		div4 = 0x1;
-		ndiv = (frequency * 14 * 4) / FE_CRYSTAL_KHZ;
-	} else
-		ndiv = (frequency * 14 * 2) / FE_CRYSTAL_KHZ;
-	ndiv = ndiv + ndiv % 2;
-	ndiv = ndiv - 1024;
-
-	ret = m88rs2000_tuner_write(state, 0x10, 0x80 | lo);
-
-	/* Set frequency divider */
-	ret |= m88rs2000_tuner_write(state, 0x01, (ndiv >> 8) & 0xf);
-	ret |= m88rs2000_tuner_write(state, 0x02, ndiv & 0xff);
-
-	ret |= m88rs2000_tuner_write(state, 0x03, 0x06);
-	ret |= m88rs2000_tuner_gate_ctrl(state, 0x10);
-	if (ret < 0)
-		return -ENODEV;
-
-	/* Tuner Frequency Range */
-	ret = m88rs2000_tuner_write(state, 0x10, lo);
-
-	ret |= m88rs2000_tuner_gate_ctrl(state, 0x08);
-
-	/* Tuner RF */
-	ret |= m88rs2000_set_tuner_rf(fe);
-
-	gdiv28 = (FE_CRYSTAL_KHZ / 1000 * 1694 + 500) / 1000;
-	ret |= m88rs2000_tuner_write(state, 0x04, gdiv28 & 0xff);
-	ret |= m88rs2000_tuner_gate_ctrl(state, 0x04);
-	if (ret < 0)
-		return -ENODEV;
-
-	value = m88rs2000_tuner_read(state, 0x26);
-
-	f3db = (symbol_rate * 135) / 200 + 2000;
-	f3db += FREQ_OFFSET_LOW_SYM_RATE;
-	if (f3db < 7000)
-		f3db = 7000;
-	if (f3db > 40000)
-		f3db = 40000;
-
-	gdiv28 = gdiv28 * 207 / (value * 2 + 151);
-	mlpf_max = gdiv28 * 135 / 100;
-	mlpf_min = gdiv28 * 78 / 100;
-	if (mlpf_max > 63)
-		mlpf_max = 63;
-
-	lpf_coeff = 2766;
-
-	nlpf = (f3db * gdiv28 * 2 / lpf_coeff /
-		(FE_CRYSTAL_KHZ / 1000)  + 1) / 2;
-	if (nlpf > 23)
-		nlpf = 23;
-	if (nlpf < 1)
-		nlpf = 1;
-
-	lpf_mxdiv = (nlpf * (FE_CRYSTAL_KHZ / 1000)
-		* lpf_coeff * 2  / f3db + 1) / 2;
-
-	if (lpf_mxdiv < mlpf_min) {
-		nlpf++;
-		lpf_mxdiv = (nlpf * (FE_CRYSTAL_KHZ / 1000)
-			* lpf_coeff * 2  / f3db + 1) / 2;
-	}
-
-	if (lpf_mxdiv > mlpf_max)
-		lpf_mxdiv = mlpf_max;
-
-	ret = m88rs2000_tuner_write(state, 0x04, lpf_mxdiv);
-	ret |= m88rs2000_tuner_write(state, 0x06, nlpf);
-
-	ret |= m88rs2000_tuner_gate_ctrl(state, 0x04);
-
-	ret |= m88rs2000_tuner_gate_ctrl(state, 0x01);
-
-	msleep(80);
-	/* calculate offset assuming 96000kHz*/
-	offset_khz = (ndiv - ndiv % 2 + 1024) * FE_CRYSTAL_KHZ
-		/ 14 / (div4 + 1) / 2;
-
-	offset_khz -= frequency;
-
-	tmp = offset_khz;
-	tmp *= 65536;
-
-	tmp = (2 * tmp + 96000) / (2 * 96000);
-	if (tmp < 0)
-		tmp += 65536;
-
-	*offset = tmp & 0xffff;
-
-	if (fe->ops.i2c_gate_ctrl)
-			fe->ops.i2c_gate_ctrl(fe, 0);
-
-	return (ret < 0) ? -EINVAL : 0;
-}
-
-static int m88rs2000_set_fec(struct m88rs2000_state *state,
-		fe_code_rate_t fec)
-{
-	u16 fec_set;
-	switch (fec) {
-	/* This is not confirmed kept for reference */
-/*	case FEC_1_2:
-		fec_set = 0x88;
-		break;
-	case FEC_2_3:
-		fec_set = 0x68;
-		break;
-	case FEC_3_4:
-		fec_set = 0x48;
-		break;
-	case FEC_5_6:
-		fec_set = 0x28;
-		break;
-	case FEC_7_8:
-		fec_set = 0x18;
-		break; */
-	case FEC_AUTO:
-	default:
-		fec_set = 0x08;
-	}
-	m88rs2000_demod_write(state, 0x76, fec_set);
-
-	return 0;
-}
-
-
-static fe_code_rate_t m88rs2000_get_fec(struct m88rs2000_state *state)
-{
-	u8 reg;
-	m88rs2000_demod_write(state, 0x9a, 0x30);
-	reg = m88rs2000_demod_read(state, 0x76);
-	m88rs2000_demod_write(state, 0x9a, 0xb0);
-
-	switch (reg) {
-	case 0x88:
-		return FEC_1_2;
-	case 0x68:
-		return FEC_2_3;
-	case 0x48:
-		return FEC_3_4;
-	case 0x28:
-		return FEC_5_6;
-	case 0x18:
-		return FEC_7_8;
-	case 0x08:
-	default:
-		break;
-	}
-
-	return FEC_AUTO;
-}
-
-static int m88rs2000_set_frontend(struct dvb_frontend *fe)
-{
-	struct m88rs2000_state *state = fe->demodulator_priv;
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	fe_status_t status;
-	int i, ret;
-	u16 offset = 0;
-	u8 reg;
-
-	state->no_lock_count = 0;
-
-	if (c->delivery_system != SYS_DVBS) {
-			deb_info("%s: unsupported delivery "
-				"system selected (%d)\n",
-				__func__, c->delivery_system);
-			return -EOPNOTSUPP;
-	}
-
-	/* Set Tuner */
-	ret = m88rs2000_set_tuner(fe, &offset);
-	if (ret < 0)
-		return -ENODEV;
-
-	ret = m88rs2000_demod_write(state, 0x9a, 0x30);
-	/* Unknown usually 0xc6 sometimes 0xc1 */
-	reg = m88rs2000_demod_read(state, 0x86);
-	ret |= m88rs2000_demod_write(state, 0x86, reg);
-	/* Offset lower nibble always 0 */
-	ret |= m88rs2000_demod_write(state, 0x9c, (offset >> 8));
-	ret |= m88rs2000_demod_write(state, 0x9d, offset & 0xf0);
-
-
-	/* Reset Demod */
-	ret = m88rs2000_tab_set(state, fe_reset);
-	if (ret < 0)
-		return -ENODEV;
-
-	/* Unknown */
-	reg = m88rs2000_demod_read(state, 0x70);
-	ret = m88rs2000_demod_write(state, 0x70, reg);
-
-	/* Set FEC */
-	ret |= m88rs2000_set_fec(state, c->fec_inner);
-	ret |= m88rs2000_demod_write(state, 0x85, 0x1);
-	ret |= m88rs2000_demod_write(state, 0x8a, 0xbf);
-	ret |= m88rs2000_demod_write(state, 0x8d, 0x1e);
-	ret |= m88rs2000_demod_write(state, 0x90, 0xf1);
-	ret |= m88rs2000_demod_write(state, 0x91, 0x08);
-
-	if (ret < 0)
-		return -ENODEV;
-
-	/* Set Symbol Rate */
-	ret = m88rs2000_set_symbolrate(fe, c->symbol_rate);
-	if (ret < 0)
-		return -ENODEV;
-
-	/* Set up Demod */
-	ret = m88rs2000_tab_set(state, fe_trigger);
-	if (ret < 0)
-		return -ENODEV;
-
-	for (i = 0; i < 25; i++) {
-		reg = m88rs2000_demod_read(state, 0x8c);
-		if ((reg & 0x7) == 0x7) {
-			status = FE_HAS_LOCK;
-			break;
-		}
-		state->no_lock_count++;
-		if (state->no_lock_count == 15) {
-			reg = m88rs2000_demod_read(state, 0x70);
-			reg ^= 0x4;
-			m88rs2000_demod_write(state, 0x70, reg);
-			state->no_lock_count = 0;
-		}
-		if (state->no_lock_count == 20)
-			m88rs2000_set_tuner_rf(fe);
-		msleep(20);
-	}
-
-	if (status & FE_HAS_LOCK) {
-		state->fec_inner = m88rs2000_get_fec(state);
-		/* Uknown suspect SNR level */
-		reg = m88rs2000_demod_read(state, 0x65);
-	}
-
-	state->tuner_frequency = c->frequency;
-	state->symbol_rate = c->symbol_rate;
-	return 0;
-}
-
-static int m88rs2000_get_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	struct m88rs2000_state *state = fe->demodulator_priv;
-	c->fec_inner = state->fec_inner;
-	c->frequency = state->tuner_frequency;
-	c->symbol_rate = state->symbol_rate;
-	return 0;
-}
-
-static int m88rs2000_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
-{
-	struct m88rs2000_state *state = fe->demodulator_priv;
-
-	if (enable)
-		m88rs2000_demod_write(state, 0x81, 0x84);
-	else
-		m88rs2000_demod_write(state, 0x81, 0x81);
-	udelay(10);
-	return 0;
-}
-
-static void m88rs2000_release(struct dvb_frontend *fe)
-{
-	struct m88rs2000_state *state = fe->demodulator_priv;
-	kfree(state);
-}
-
-static struct dvb_frontend_ops m88rs2000_ops = {
-	.delsys = { SYS_DVBS },
-	.info = {
-		.name			= "M88RS2000 DVB-S",
-		.frequency_min		= 950000,
-		.frequency_max		= 2150000,
-		.frequency_stepsize	= 1000,	 /* kHz for QPSK frontends */
-		.frequency_tolerance	= 5000,
-		.symbol_rate_min	= 1000000,
-		.symbol_rate_max	= 45000000,
-		.symbol_rate_tolerance	= 500,	/* ppm */
-		.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_FEC_AUTO
-	},
-
-	.release = m88rs2000_release,
-	.init = m88rs2000_init,
-	.sleep = m88rs2000_sleep,
-	.write = m88rs2000_write,
-	.i2c_gate_ctrl = m88rs2000_i2c_gate_ctrl,
-	.read_status = m88rs2000_read_status,
-	.read_ber = m88rs2000_read_ber,
-	.read_signal_strength = m88rs2000_read_signal_strength,
-	.read_snr = m88rs2000_read_snr,
-	.read_ucblocks = m88rs2000_read_ucblocks,
-	.diseqc_send_master_cmd = m88rs2000_send_diseqc_msg,
-	.diseqc_send_burst = m88rs2000_send_diseqc_burst,
-	.set_tone = m88rs2000_set_tone,
-	.set_voltage = m88rs2000_set_voltage,
-
-	.set_frontend = m88rs2000_set_frontend,
-	.get_frontend = m88rs2000_get_frontend,
-};
-
-struct dvb_frontend *m88rs2000_attach(const struct m88rs2000_config *config,
-				    struct i2c_adapter *i2c)
-{
-	struct m88rs2000_state *state = NULL;
-
-	/* allocate memory for the internal state */
-	state = kzalloc(sizeof(struct m88rs2000_state), GFP_KERNEL);
-	if (state == NULL)
-		goto error;
-
-	/* setup the state */
-	state->config = config;
-	state->i2c = i2c;
-	state->tuner_frequency = 0;
-	state->symbol_rate = 0;
-	state->fec_inner = 0;
-
-	if (m88rs2000_startup(state) < 0)
-		goto error;
-
-	/* create dvb_frontend */
-	memcpy(&state->frontend.ops, &m88rs2000_ops,
-			sizeof(struct dvb_frontend_ops));
-	state->frontend.demodulator_priv = state;
-	return &state->frontend;
-
-error:
-	kfree(state);
-
-	return NULL;
-}
-EXPORT_SYMBOL(m88rs2000_attach);
-
-MODULE_DESCRIPTION("M88RS2000 DVB-S Demodulator driver");
-MODULE_AUTHOR("Malcolm Priestley tvboxspy@gmail.com");
-MODULE_LICENSE("GPL");
-MODULE_VERSION("1.13");
-
diff --git a/drivers/media/dvb/frontends/m88rs2000.h b/drivers/media/dvb/frontends/m88rs2000.h
deleted file mode 100644
index 59acdb6..0000000
--- a/drivers/media/dvb/frontends/m88rs2000.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
-	Driver for M88RS2000 demodulator
-
-	This program is free software; you can redistribute it and/or modify
-	it under the terms of the 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 M88RS2000_H
-#define M88RS2000_H
-
-#include <linux/dvb/frontend.h>
-#include "dvb_frontend.h"
-
-struct m88rs2000_config {
-	/* Demodulator i2c address */
-	u8 demod_addr;
-	/* Tuner address */
-	u8 tuner_addr;
-
-	u8 *inittab;
-
-	/* minimum delay before retuning */
-	int min_delay_ms;
-
-	int (*set_ts_params)(struct dvb_frontend *, int);
-};
-
-enum {
-	CALL_IS_SET_FRONTEND = 0x0,
-	CALL_IS_READ,
-};
-
-#if defined(CONFIG_DVB_M88RS2000) || (defined(CONFIG_DVB_M88RS2000_MODULE) && \
-							defined(MODULE))
-extern struct dvb_frontend *m88rs2000_attach(
-	const struct m88rs2000_config *config, struct i2c_adapter *i2c);
-#else
-static inline struct dvb_frontend *m88rs2000_attach(
-	const struct m88rs2000_config *config, struct i2c_adapter *i2c)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif /* CONFIG_DVB_M88RS2000 */
-
-#define FE_CRYSTAL_KHZ 27000
-#define FREQ_OFFSET_LOW_SYM_RATE 3000
-
-enum {
-	DEMOD_WRITE = 0x1,
-	TUNER_WRITE,
-	WRITE_DELAY = 0x10,
-};
-#endif /* M88RS2000_H */
diff --git a/drivers/media/dvb/frontends/mb86a16.c b/drivers/media/dvb/frontends/mb86a16.c
deleted file mode 100644
index 9ae40ab..0000000
--- a/drivers/media/dvb/frontends/mb86a16.c
+++ /dev/null
@@ -1,1878 +0,0 @@
-/*
-	Fujitsu MB86A16 DVB-S/DSS DC Receiver driver
-
-	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/slab.h>
-
-#include "dvb_frontend.h"
-#include "mb86a16.h"
-#include "mb86a16_priv.h"
-
-unsigned int verbose = 5;
-module_param(verbose, int, 0644);
-
-#define ABS(x)		((x) < 0 ? (-x) : (x))
-
-struct mb86a16_state {
-	struct i2c_adapter		*i2c_adap;
-	const struct mb86a16_config	*config;
-	struct dvb_frontend		frontend;
-
-	/* tuning parameters */
-	int				frequency;
-	int				srate;
-
-	/* Internal stuff */
-	int				master_clk;
-	int				deci;
-	int				csel;
-	int				rsel;
-};
-
-#define MB86A16_ERROR		0
-#define MB86A16_NOTICE		1
-#define MB86A16_INFO		2
-#define MB86A16_DEBUG		3
-
-#define dprintk(x, y, z, format, arg...) do {						\
-	if (z) {									\
-		if	((x > MB86A16_ERROR) && (x > y))				\
-			printk(KERN_ERR "%s: " format "\n", __func__, ##arg);		\
-		else if ((x > MB86A16_NOTICE) && (x > y))				\
-			printk(KERN_NOTICE "%s: " format "\n", __func__, ##arg);	\
-		else if ((x > MB86A16_INFO) && (x > y))					\
-			printk(KERN_INFO "%s: " format "\n", __func__, ##arg);		\
-		else if ((x > MB86A16_DEBUG) && (x > y))				\
-			printk(KERN_DEBUG "%s: " format "\n", __func__, ##arg);		\
-	} else {									\
-		if (x > y)								\
-			printk(format, ##arg);						\
-	}										\
-} while (0)
-
-#define TRACE_IN	dprintk(verbose, MB86A16_DEBUG, 1, "-->()")
-#define TRACE_OUT	dprintk(verbose, MB86A16_DEBUG, 1, "()-->")
-
-static int mb86a16_write(struct mb86a16_state *state, u8 reg, u8 val)
-{
-	int ret;
-	u8 buf[] = { reg, val };
-
-	struct i2c_msg msg = {
-		.addr = state->config->demod_address,
-		.flags = 0,
-		.buf = buf,
-		.len = 2
-	};
-
-	dprintk(verbose, MB86A16_DEBUG, 1,
-		"writing to [0x%02x],Reg[0x%02x],Data[0x%02x]",
-		state->config->demod_address, buf[0], buf[1]);
-
-	ret = i2c_transfer(state->i2c_adap, &msg, 1);
-
-	return (ret != 1) ? -EREMOTEIO : 0;
-}
-
-static int mb86a16_read(struct mb86a16_state *state, u8 reg, u8 *val)
-{
-	int ret;
-	u8 b0[] = { reg };
-	u8 b1[] = { 0 };
-
-	struct i2c_msg msg[] = {
-		{
-			.addr = state->config->demod_address,
-			.flags = 0,
-			.buf = b0,
-			.len = 1
-		}, {
-			.addr = state->config->demod_address,
-			.flags = I2C_M_RD,
-			.buf = b1,
-			.len = 1
-		}
-	};
-	ret = i2c_transfer(state->i2c_adap, msg, 2);
-	if (ret != 2) {
-		dprintk(verbose, MB86A16_ERROR, 1, "read error(reg=0x%02x, ret=0x%i)",
-			reg, ret);
-
-		return -EREMOTEIO;
-	}
-	*val = b1[0];
-
-	return ret;
-}
-
-static int CNTM_set(struct mb86a16_state *state,
-		    unsigned char timint1,
-		    unsigned char timint2,
-		    unsigned char cnext)
-{
-	unsigned char val;
-
-	val = (timint1 << 4) | (timint2 << 2) | cnext;
-	if (mb86a16_write(state, MB86A16_CNTMR, val) < 0)
-		goto err;
-
-	return 0;
-
-err:
-	dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
-	return -EREMOTEIO;
-}
-
-static int smrt_set(struct mb86a16_state *state, int rate)
-{
-	int tmp ;
-	int m ;
-	unsigned char STOFS0, STOFS1;
-
-	m = 1 << state->deci;
-	tmp = (8192 * state->master_clk - 2 * m * rate * 8192 + state->master_clk / 2) / state->master_clk;
-
-	STOFS0 = tmp & 0x0ff;
-	STOFS1 = (tmp & 0xf00) >> 8;
-
-	if (mb86a16_write(state, MB86A16_SRATE1, (state->deci << 2) |
-				       (state->csel << 1) |
-					state->rsel) < 0)
-		goto err;
-	if (mb86a16_write(state, MB86A16_SRATE2, STOFS0) < 0)
-		goto err;
-	if (mb86a16_write(state, MB86A16_SRATE3, STOFS1) < 0)
-		goto err;
-
-	return 0;
-err:
-	dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
-	return -1;
-}
-
-static int srst(struct mb86a16_state *state)
-{
-	if (mb86a16_write(state, MB86A16_RESET, 0x04) < 0)
-		goto err;
-
-	return 0;
-err:
-	dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
-	return -EREMOTEIO;
-
-}
-
-static int afcex_data_set(struct mb86a16_state *state,
-			  unsigned char AFCEX_L,
-			  unsigned char AFCEX_H)
-{
-	if (mb86a16_write(state, MB86A16_AFCEXL, AFCEX_L) < 0)
-		goto err;
-	if (mb86a16_write(state, MB86A16_AFCEXH, AFCEX_H) < 0)
-		goto err;
-
-	return 0;
-err:
-	dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
-
-	return -1;
-}
-
-static int afcofs_data_set(struct mb86a16_state *state,
-			   unsigned char AFCEX_L,
-			   unsigned char AFCEX_H)
-{
-	if (mb86a16_write(state, 0x58, AFCEX_L) < 0)
-		goto err;
-	if (mb86a16_write(state, 0x59, AFCEX_H) < 0)
-		goto err;
-
-	return 0;
-err:
-	dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
-	return -EREMOTEIO;
-}
-
-static int stlp_set(struct mb86a16_state *state,
-		    unsigned char STRAS,
-		    unsigned char STRBS)
-{
-	if (mb86a16_write(state, MB86A16_STRFILTCOEF1, (STRBS << 3) | (STRAS)) < 0)
-		goto err;
-
-	return 0;
-err:
-	dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
-	return -EREMOTEIO;
-}
-
-static int Vi_set(struct mb86a16_state *state, unsigned char ETH, unsigned char VIA)
-{
-	if (mb86a16_write(state, MB86A16_VISET2, 0x04) < 0)
-		goto err;
-	if (mb86a16_write(state, MB86A16_VISET3, 0xf5) < 0)
-		goto err;
-
-	return 0;
-err:
-	dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
-	return -EREMOTEIO;
-}
-
-static int initial_set(struct mb86a16_state *state)
-{
-	if (stlp_set(state, 5, 7))
-		goto err;
-
-	udelay(100);
-	if (afcex_data_set(state, 0, 0))
-		goto err;
-
-	udelay(100);
-	if (afcofs_data_set(state, 0, 0))
-		goto err;
-
-	udelay(100);
-	if (mb86a16_write(state, MB86A16_CRLFILTCOEF1, 0x16) < 0)
-		goto err;
-	if (mb86a16_write(state, 0x2f, 0x21) < 0)
-		goto err;
-	if (mb86a16_write(state, MB86A16_VIMAG, 0x38) < 0)
-		goto err;
-	if (mb86a16_write(state, MB86A16_FAGCS1, 0x00) < 0)
-		goto err;
-	if (mb86a16_write(state, MB86A16_FAGCS2, 0x1c) < 0)
-		goto err;
-	if (mb86a16_write(state, MB86A16_FAGCS3, 0x20) < 0)
-		goto err;
-	if (mb86a16_write(state, MB86A16_FAGCS4, 0x1e) < 0)
-		goto err;
-	if (mb86a16_write(state, MB86A16_FAGCS5, 0x23) < 0)
-		goto err;
-	if (mb86a16_write(state, 0x54, 0xff) < 0)
-		goto err;
-	if (mb86a16_write(state, MB86A16_TSOUT, 0x00) < 0)
-		goto err;
-
-	return 0;
-
-err:
-	dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
-	return -EREMOTEIO;
-}
-
-static int S01T_set(struct mb86a16_state *state,
-		    unsigned char s1t,
-		    unsigned s0t)
-{
-	if (mb86a16_write(state, 0x33, (s1t << 3) | s0t) < 0)
-		goto err;
-
-	return 0;
-err:
-	dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
-	return -EREMOTEIO;
-}
-
-
-static int EN_set(struct mb86a16_state *state,
-		  int cren,
-		  int afcen)
-{
-	unsigned char val;
-
-	val = 0x7a | (cren << 7) | (afcen << 2);
-	if (mb86a16_write(state, 0x49, val) < 0)
-		goto err;
-
-	return 0;
-err:
-	dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
-	return -EREMOTEIO;
-}
-
-static int AFCEXEN_set(struct mb86a16_state *state,
-		       int afcexen,
-		       int smrt)
-{
-	unsigned char AFCA ;
-
-	if (smrt > 18875)
-		AFCA = 4;
-	else if (smrt > 9375)
-		AFCA = 3;
-	else if (smrt > 2250)
-		AFCA = 2;
-	else
-		AFCA = 1;
-
-	if (mb86a16_write(state, 0x2a, 0x02 | (afcexen << 5) | (AFCA << 2)) < 0)
-		goto err;
-
-	return 0;
-
-err:
-	dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
-	return -EREMOTEIO;
-}
-
-static int DAGC_data_set(struct mb86a16_state *state,
-			 unsigned char DAGCA,
-			 unsigned char DAGCW)
-{
-	if (mb86a16_write(state, 0x2d, (DAGCA << 3) | DAGCW) < 0)
-		goto err;
-
-	return 0;
-
-err:
-	dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
-	return -EREMOTEIO;
-}
-
-static void smrt_info_get(struct mb86a16_state *state, int rate)
-{
-	if (rate >= 37501) {
-		state->deci = 0; state->csel = 0; state->rsel = 0;
-	} else if (rate >= 30001) {
-		state->deci = 0; state->csel = 0; state->rsel = 1;
-	} else if (rate >= 26251) {
-		state->deci = 0; state->csel = 1; state->rsel = 0;
-	} else if (rate >= 22501) {
-		state->deci = 0; state->csel = 1; state->rsel = 1;
-	} else if (rate >= 18751) {
-		state->deci = 1; state->csel = 0; state->rsel = 0;
-	} else if (rate >= 15001) {
-		state->deci = 1; state->csel = 0; state->rsel = 1;
-	} else if (rate >= 13126) {
-		state->deci = 1; state->csel = 1; state->rsel = 0;
-	} else if (rate >= 11251) {
-		state->deci = 1; state->csel = 1; state->rsel = 1;
-	} else if (rate >= 9376) {
-		state->deci = 2; state->csel = 0; state->rsel = 0;
-	} else if (rate >= 7501) {
-		state->deci = 2; state->csel = 0; state->rsel = 1;
-	} else if (rate >= 6563) {
-		state->deci = 2; state->csel = 1; state->rsel = 0;
-	} else if (rate >= 5626) {
-		state->deci = 2; state->csel = 1; state->rsel = 1;
-	} else if (rate >= 4688) {
-		state->deci = 3; state->csel = 0; state->rsel = 0;
-	} else if (rate >= 3751) {
-		state->deci = 3; state->csel = 0; state->rsel = 1;
-	} else if (rate >= 3282) {
-		state->deci = 3; state->csel = 1; state->rsel = 0;
-	} else if (rate >= 2814) {
-		state->deci = 3; state->csel = 1; state->rsel = 1;
-	} else if (rate >= 2344) {
-		state->deci = 4; state->csel = 0; state->rsel = 0;
-	} else if (rate >= 1876) {
-		state->deci = 4; state->csel = 0; state->rsel = 1;
-	} else if (rate >= 1641) {
-		state->deci = 4; state->csel = 1; state->rsel = 0;
-	} else if (rate >= 1407) {
-		state->deci = 4; state->csel = 1; state->rsel = 1;
-	} else if (rate >= 1172) {
-		state->deci = 5; state->csel = 0; state->rsel = 0;
-	} else if (rate >=  939) {
-		state->deci = 5; state->csel = 0; state->rsel = 1;
-	} else if (rate >=  821) {
-		state->deci = 5; state->csel = 1; state->rsel = 0;
-	} else {
-		state->deci = 5; state->csel = 1; state->rsel = 1;
-	}
-
-	if (state->csel == 0)
-		state->master_clk = 92000;
-	else
-		state->master_clk = 61333;
-
-}
-
-static int signal_det(struct mb86a16_state *state,
-		      int smrt,
-		      unsigned char *SIG)
-{
-
-	int ret ;
-	int smrtd ;
-	int wait_sym ;
-
-	u32 wait_t;
-	unsigned char S[3] ;
-	int i ;
-
-	if (*SIG > 45) {
-		if (CNTM_set(state, 2, 1, 2) < 0) {
-			dprintk(verbose, MB86A16_ERROR, 1, "CNTM set Error");
-			return -1;
-		}
-		wait_sym = 40000;
-	} else {
-		if (CNTM_set(state, 3, 1, 2) < 0) {
-			dprintk(verbose, MB86A16_ERROR, 1, "CNTM set Error");
-			return -1;
-		}
-		wait_sym = 80000;
-	}
-	for (i = 0; i < 3; i++) {
-		if (i == 0)
-			smrtd = smrt * 98 / 100;
-		else if (i == 1)
-			smrtd = smrt;
-		else
-			smrtd = smrt * 102 / 100;
-		smrt_info_get(state, smrtd);
-		smrt_set(state, smrtd);
-		srst(state);
-		wait_t = (wait_sym + 99 * smrtd / 100) / smrtd;
-		if (wait_t == 0)
-			wait_t = 1;
-		msleep_interruptible(10);
-		if (mb86a16_read(state, 0x37, &(S[i])) != 2) {
-			dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
-			return -EREMOTEIO;
-		}
-	}
-	if ((S[1] > S[0] * 112 / 100) &&
-	    (S[1] > S[2] * 112 / 100)) {
-
-		ret = 1;
-	} else {
-		ret = 0;
-	}
-	*SIG = S[1];
-
-	if (CNTM_set(state, 0, 1, 2) < 0) {
-		dprintk(verbose, MB86A16_ERROR, 1, "CNTM set Error");
-		return -1;
-	}
-
-	return ret;
-}
-
-static int rf_val_set(struct mb86a16_state *state,
-		      int f,
-		      int smrt,
-		      unsigned char R)
-{
-	unsigned char C, F, B;
-	int M;
-	unsigned char rf_val[5];
-	int ack = -1;
-
-	if (smrt > 37750)
-		C = 1;
-	else if (smrt > 18875)
-		C = 2;
-	else if (smrt > 5500)
-		C = 3;
-	else
-		C = 4;
-
-	if (smrt > 30500)
-		F = 3;
-	else if (smrt > 9375)
-		F = 1;
-	else if (smrt > 4625)
-		F = 0;
-	else
-		F = 2;
-
-	if (f < 1060)
-		B = 0;
-	else if (f < 1175)
-		B = 1;
-	else if (f < 1305)
-		B = 2;
-	else if (f < 1435)
-		B = 3;
-	else if (f < 1570)
-		B = 4;
-	else if (f < 1715)
-		B = 5;
-	else if (f < 1845)
-		B = 6;
-	else if (f < 1980)
-		B = 7;
-	else if (f < 2080)
-		B = 8;
-	else
-		B = 9;
-
-	M = f * (1 << R) / 2;
-
-	rf_val[0] = 0x01 | (C << 3) | (F << 1);
-	rf_val[1] = (R << 5) | ((M & 0x1f000) >> 12);
-	rf_val[2] = (M & 0x00ff0) >> 4;
-	rf_val[3] = ((M & 0x0000f) << 4) | B;
-
-	/* Frequency Set */
-	if (mb86a16_write(state, 0x21, rf_val[0]) < 0)
-		ack = 0;
-	if (mb86a16_write(state, 0x22, rf_val[1]) < 0)
-		ack = 0;
-	if (mb86a16_write(state, 0x23, rf_val[2]) < 0)
-		ack = 0;
-	if (mb86a16_write(state, 0x24, rf_val[3]) < 0)
-		ack = 0;
-	if (mb86a16_write(state, 0x25, 0x01) < 0)
-		ack = 0;
-	if (ack == 0) {
-		dprintk(verbose, MB86A16_ERROR, 1, "RF Setup - I2C transfer error");
-		return -EREMOTEIO;
-	}
-
-	return 0;
-}
-
-static int afcerr_chk(struct mb86a16_state *state)
-{
-	unsigned char AFCM_L, AFCM_H ;
-	int AFCM ;
-	int afcm, afcerr ;
-
-	if (mb86a16_read(state, 0x0e, &AFCM_L) != 2)
-		goto err;
-	if (mb86a16_read(state, 0x0f, &AFCM_H) != 2)
-		goto err;
-
-	AFCM = (AFCM_H << 8) + AFCM_L;
-
-	if (AFCM > 2048)
-		afcm = AFCM - 4096;
-	else
-		afcm = AFCM;
-	afcerr = afcm * state->master_clk / 8192;
-
-	return afcerr;
-
-err:
-	dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
-	return -EREMOTEIO;
-}
-
-static int dagcm_val_get(struct mb86a16_state *state)
-{
-	int DAGCM;
-	unsigned char DAGCM_H, DAGCM_L;
-
-	if (mb86a16_read(state, 0x45, &DAGCM_L) != 2)
-		goto err;
-	if (mb86a16_read(state, 0x46, &DAGCM_H) != 2)
-		goto err;
-
-	DAGCM = (DAGCM_H << 8) + DAGCM_L;
-
-	return DAGCM;
-
-err:
-	dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
-	return -EREMOTEIO;
-}
-
-static int mb86a16_read_status(struct dvb_frontend *fe, fe_status_t *status)
-{
-	u8 stat, stat2;
-	struct mb86a16_state *state = fe->demodulator_priv;
-
-	*status = 0;
-
-	if (mb86a16_read(state, MB86A16_SIG1, &stat) != 2)
-		goto err;
-	if (mb86a16_read(state, MB86A16_SIG2, &stat2) != 2)
-		goto err;
-	if ((stat > 25) && (stat2 > 25))
-		*status |= FE_HAS_SIGNAL;
-	if ((stat > 45) && (stat2 > 45))
-		*status |= FE_HAS_CARRIER;
-
-	if (mb86a16_read(state, MB86A16_STATUS, &stat) != 2)
-		goto err;
-
-	if (stat & 0x01)
-		*status |= FE_HAS_SYNC;
-	if (stat & 0x01)
-		*status |= FE_HAS_VITERBI;
-
-	if (mb86a16_read(state, MB86A16_FRAMESYNC, &stat) != 2)
-		goto err;
-
-	if ((stat & 0x0f) && (*status & FE_HAS_VITERBI))
-		*status |= FE_HAS_LOCK;
-
-	return 0;
-
-err:
-	dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
-	return -EREMOTEIO;
-}
-
-static int sync_chk(struct mb86a16_state *state,
-		    unsigned char *VIRM)
-{
-	unsigned char val;
-	int sync;
-
-	if (mb86a16_read(state, 0x0d, &val) != 2)
-		goto err;
-
-	dprintk(verbose, MB86A16_INFO, 1, "Status = %02x,", val);
-	sync = val & 0x01;
-	*VIRM = (val & 0x1c) >> 2;
-
-	return sync;
-err:
-	dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
-	return -EREMOTEIO;
-
-}
-
-static int freqerr_chk(struct mb86a16_state *state,
-		       int fTP,
-		       int smrt,
-		       int unit)
-{
-	unsigned char CRM, AFCML, AFCMH;
-	unsigned char temp1, temp2, temp3;
-	int crm, afcm, AFCM;
-	int crrerr, afcerr;		/* kHz */
-	int frqerr;			/* MHz */
-	int afcen, afcexen = 0;
-	int R, M, fOSC, fOSC_OFS;
-
-	if (mb86a16_read(state, 0x43, &CRM) != 2)
-		goto err;
-
-	if (CRM > 127)
-		crm = CRM - 256;
-	else
-		crm = CRM;
-
-	crrerr = smrt * crm / 256;
-	if (mb86a16_read(state, 0x49, &temp1) != 2)
-		goto err;
-
-	afcen = (temp1 & 0x04) >> 2;
-	if (afcen == 0) {
-		if (mb86a16_read(state, 0x2a, &temp1) != 2)
-			goto err;
-		afcexen = (temp1 & 0x20) >> 5;
-	}
-
-	if (afcen == 1) {
-		if (mb86a16_read(state, 0x0e, &AFCML) != 2)
-			goto err;
-		if (mb86a16_read(state, 0x0f, &AFCMH) != 2)
-			goto err;
-	} else if (afcexen == 1) {
-		if (mb86a16_read(state, 0x2b, &AFCML) != 2)
-			goto err;
-		if (mb86a16_read(state, 0x2c, &AFCMH) != 2)
-			goto err;
-	}
-	if ((afcen == 1) || (afcexen == 1)) {
-		smrt_info_get(state, smrt);
-		AFCM = ((AFCMH & 0x01) << 8) + AFCML;
-		if (AFCM > 255)
-			afcm = AFCM - 512;
-		else
-			afcm = AFCM;
-
-		afcerr = afcm * state->master_clk / 8192;
-	} else
-		afcerr = 0;
-
-	if (mb86a16_read(state, 0x22, &temp1) != 2)
-		goto err;
-	if (mb86a16_read(state, 0x23, &temp2) != 2)
-		goto err;
-	if (mb86a16_read(state, 0x24, &temp3) != 2)
-		goto err;
-
-	R = (temp1 & 0xe0) >> 5;
-	M = ((temp1 & 0x1f) << 12) + (temp2 << 4) + (temp3 >> 4);
-	if (R == 0)
-		fOSC = 2 * M;
-	else
-		fOSC = M;
-
-	fOSC_OFS = fOSC - fTP;
-
-	if (unit == 0) {	/* MHz */
-		if (crrerr + afcerr + fOSC_OFS * 1000 >= 0)
-			frqerr = (crrerr + afcerr + fOSC_OFS * 1000 + 500) / 1000;
-		else
-			frqerr = (crrerr + afcerr + fOSC_OFS * 1000 - 500) / 1000;
-	} else {	/* kHz */
-		frqerr = crrerr + afcerr + fOSC_OFS * 1000;
-	}
-
-	return frqerr;
-err:
-	dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
-	return -EREMOTEIO;
-}
-
-static unsigned char vco_dev_get(struct mb86a16_state *state, int smrt)
-{
-	unsigned char R;
-
-	if (smrt > 9375)
-		R = 0;
-	else
-		R = 1;
-
-	return R;
-}
-
-static void swp_info_get(struct mb86a16_state *state,
-			 int fOSC_start,
-			 int smrt,
-			 int v, int R,
-			 int swp_ofs,
-			 int *fOSC,
-			 int *afcex_freq,
-			 unsigned char *AFCEX_L,
-			 unsigned char *AFCEX_H)
-{
-	int AFCEX ;
-	int crnt_swp_freq ;
-
-	crnt_swp_freq = fOSC_start * 1000 + v * swp_ofs;
-
-	if (R == 0)
-		*fOSC = (crnt_swp_freq + 1000) / 2000 * 2;
-	else
-		*fOSC = (crnt_swp_freq + 500) / 1000;
-
-	if (*fOSC >= crnt_swp_freq)
-		*afcex_freq = *fOSC * 1000 - crnt_swp_freq;
-	else
-		*afcex_freq = crnt_swp_freq - *fOSC * 1000;
-
-	AFCEX = *afcex_freq * 8192 / state->master_clk;
-	*AFCEX_L =  AFCEX & 0x00ff;
-	*AFCEX_H = (AFCEX & 0x0f00) >> 8;
-}
-
-
-static int swp_freq_calcuation(struct mb86a16_state *state, int i, int v, int *V,  int vmax, int vmin,
-			       int SIGMIN, int fOSC, int afcex_freq, int swp_ofs, unsigned char *SIG1)
-{
-	int swp_freq ;
-
-	if ((i % 2 == 1) && (v <= vmax)) {
-		/* positive v (case 1) */
-		if ((v - 1 == vmin)				&&
-		    (*(V + 30 + v) >= 0)			&&
-		    (*(V + 30 + v - 1) >= 0)			&&
-		    (*(V + 30 + v - 1) > *(V + 30 + v))		&&
-		    (*(V + 30 + v - 1) > SIGMIN)) {
-
-			swp_freq = fOSC * 1000 + afcex_freq - swp_ofs;
-			*SIG1 = *(V + 30 + v - 1);
-		} else if ((v == vmax)				&&
-			   (*(V + 30 + v) >= 0)			&&
-			   (*(V + 30 + v - 1) >= 0)		&&
-			   (*(V + 30 + v) > *(V + 30 + v - 1))	&&
-			   (*(V + 30 + v) > SIGMIN)) {
-			/* (case 2) */
-			swp_freq = fOSC * 1000 + afcex_freq;
-			*SIG1 = *(V + 30 + v);
-		} else if ((*(V + 30 + v) > 0)			&&
-			   (*(V + 30 + v - 1) > 0)		&&
-			   (*(V + 30 + v - 2) > 0)		&&
-			   (*(V + 30 + v - 3) > 0)		&&
-			   (*(V + 30 + v - 1) > *(V + 30 + v))	&&
-			   (*(V + 30 + v - 2) > *(V + 30 + v - 3)) &&
-			   ((*(V + 30 + v - 1) > SIGMIN)	||
-			   (*(V + 30 + v - 2) > SIGMIN))) {
-			/* (case 3) */
-			if (*(V + 30 + v - 1) >= *(V + 30 + v - 2)) {
-				swp_freq = fOSC * 1000 + afcex_freq - swp_ofs;
-				*SIG1 = *(V + 30 + v - 1);
-			} else {
-				swp_freq = fOSC * 1000 + afcex_freq - swp_ofs * 2;
-				*SIG1 = *(V + 30 + v - 2);
-			}
-		} else if ((v == vmax)				&&
-			   (*(V + 30 + v) >= 0)			&&
-			   (*(V + 30 + v - 1) >= 0)		&&
-			   (*(V + 30 + v - 2) >= 0)		&&
-			   (*(V + 30 + v) > *(V + 30 + v - 2))	&&
-			   (*(V + 30 + v - 1) > *(V + 30 + v - 2)) &&
-			   ((*(V + 30 + v) > SIGMIN)		||
-			   (*(V + 30 + v - 1) > SIGMIN))) {
-			/* (case 4) */
-			if (*(V + 30 + v) >= *(V + 30 + v - 1)) {
-				swp_freq = fOSC * 1000 + afcex_freq;
-				*SIG1 = *(V + 30 + v);
-			} else {
-				swp_freq = fOSC * 1000 + afcex_freq - swp_ofs;
-				*SIG1 = *(V + 30 + v - 1);
-			}
-		} else  {
-			swp_freq = -1 ;
-		}
-	} else if ((i % 2 == 0) && (v >= vmin)) {
-		/* Negative v (case 1) */
-		if ((*(V + 30 + v) > 0)				&&
-		    (*(V + 30 + v + 1) > 0)			&&
-		    (*(V + 30 + v + 2) > 0)			&&
-		    (*(V + 30 + v + 1) > *(V + 30 + v))		&&
-		    (*(V + 30 + v + 1) > *(V + 30 + v + 2))	&&
-		    (*(V + 30 + v + 1) > SIGMIN)) {
-
-			swp_freq = fOSC * 1000 + afcex_freq + swp_ofs;
-			*SIG1 = *(V + 30 + v + 1);
-		} else if ((v + 1 == vmax)			&&
-			   (*(V + 30 + v) >= 0)			&&
-			   (*(V + 30 + v + 1) >= 0)		&&
-			   (*(V + 30 + v + 1) > *(V + 30 + v))	&&
-			   (*(V + 30 + v + 1) > SIGMIN)) {
-			/* (case 2) */
-			swp_freq = fOSC * 1000 + afcex_freq + swp_ofs;
-			*SIG1 = *(V + 30 + v);
-		} else if ((v == vmin)				&&
-			   (*(V + 30 + v) > 0)			&&
-			   (*(V + 30 + v + 1) > 0)		&&
-			   (*(V + 30 + v + 2) > 0)		&&
-			   (*(V + 30 + v) > *(V + 30 + v + 1))	&&
-			   (*(V + 30 + v) > *(V + 30 + v + 2))	&&
-			   (*(V + 30 + v) > SIGMIN)) {
-			/* (case 3) */
-			swp_freq = fOSC * 1000 + afcex_freq;
-			*SIG1 = *(V + 30 + v);
-		} else if ((*(V + 30 + v) >= 0)			&&
-			   (*(V + 30 + v + 1) >= 0)		&&
-			   (*(V + 30 + v + 2) >= 0)		&&
-			   (*(V + 30 + v + 3) >= 0)		&&
-			   (*(V + 30 + v + 1) > *(V + 30 + v))	&&
-			   (*(V + 30 + v + 2) > *(V + 30 + v + 3)) &&
-			   ((*(V + 30 + v + 1) > SIGMIN)	||
-			    (*(V + 30 + v + 2) > SIGMIN))) {
-			/* (case 4) */
-			if (*(V + 30 + v + 1) >= *(V + 30 + v + 2)) {
-				swp_freq = fOSC * 1000 + afcex_freq + swp_ofs;
-				*SIG1 = *(V + 30 + v + 1);
-			} else {
-				swp_freq = fOSC * 1000 + afcex_freq + swp_ofs * 2;
-				*SIG1 = *(V + 30 + v + 2);
-			}
-		} else if ((*(V + 30 + v) >= 0)			&&
-			   (*(V + 30 + v + 1) >= 0)		&&
-			   (*(V + 30 + v + 2) >= 0)		&&
-			   (*(V + 30 + v + 3) >= 0)		&&
-			   (*(V + 30 + v) > *(V + 30 + v + 2))	&&
-			   (*(V + 30 + v + 1) > *(V + 30 + v + 2)) &&
-			   (*(V + 30 + v) > *(V + 30 + v + 3))	&&
-			   (*(V + 30 + v + 1) > *(V + 30 + v + 3)) &&
-			   ((*(V + 30 + v) > SIGMIN)		||
-			    (*(V + 30 + v + 1) > SIGMIN))) {
-			/* (case 5) */
-			if (*(V + 30 + v) >= *(V + 30 + v + 1)) {
-				swp_freq = fOSC * 1000 + afcex_freq;
-				*SIG1 = *(V + 30 + v);
-			} else {
-				swp_freq = fOSC * 1000 + afcex_freq + swp_ofs;
-				*SIG1 = *(V + 30 + v + 1);
-			}
-		} else if ((v + 2 == vmin)			&&
-			   (*(V + 30 + v) >= 0)			&&
-			   (*(V + 30 + v + 1) >= 0)		&&
-			   (*(V + 30 + v + 2) >= 0)		&&
-			   (*(V + 30 + v + 1) > *(V + 30 + v))	&&
-			   (*(V + 30 + v + 2) > *(V + 30 + v))	&&
-			   ((*(V + 30 + v + 1) > SIGMIN)	||
-			    (*(V + 30 + v + 2) > SIGMIN))) {
-			/* (case 6) */
-			if (*(V + 30 + v + 1) >= *(V + 30 + v + 2)) {
-				swp_freq = fOSC * 1000 + afcex_freq + swp_ofs;
-				*SIG1 = *(V + 30 + v + 1);
-			} else {
-				swp_freq = fOSC * 1000 + afcex_freq + swp_ofs * 2;
-				*SIG1 = *(V + 30 + v + 2);
-			}
-		} else if ((vmax == 0) && (vmin == 0) && (*(V + 30 + v) > SIGMIN)) {
-			swp_freq = fOSC * 1000;
-			*SIG1 = *(V + 30 + v);
-		} else
-			swp_freq = -1;
-	} else
-		swp_freq = -1;
-
-	return swp_freq;
-}
-
-static void swp_info_get2(struct mb86a16_state *state,
-			  int smrt,
-			  int R,
-			  int swp_freq,
-			  int *afcex_freq,
-			  int *fOSC,
-			  unsigned char *AFCEX_L,
-			  unsigned char *AFCEX_H)
-{
-	int AFCEX ;
-
-	if (R == 0)
-		*fOSC = (swp_freq + 1000) / 2000 * 2;
-	else
-		*fOSC = (swp_freq + 500) / 1000;
-
-	if (*fOSC >= swp_freq)
-		*afcex_freq = *fOSC * 1000 - swp_freq;
-	else
-		*afcex_freq = swp_freq - *fOSC * 1000;
-
-	AFCEX = *afcex_freq * 8192 / state->master_clk;
-	*AFCEX_L =  AFCEX & 0x00ff;
-	*AFCEX_H = (AFCEX & 0x0f00) >> 8;
-}
-
-static void afcex_info_get(struct mb86a16_state *state,
-			   int afcex_freq,
-			   unsigned char *AFCEX_L,
-			   unsigned char *AFCEX_H)
-{
-	int AFCEX ;
-
-	AFCEX = afcex_freq * 8192 / state->master_clk;
-	*AFCEX_L =  AFCEX & 0x00ff;
-	*AFCEX_H = (AFCEX & 0x0f00) >> 8;
-}
-
-static int SEQ_set(struct mb86a16_state *state, unsigned char loop)
-{
-	/* SLOCK0 = 0 */
-	if (mb86a16_write(state, 0x32, 0x02 | (loop << 2)) < 0) {
-		dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
-		return -EREMOTEIO;
-	}
-
-	return 0;
-}
-
-static int iq_vt_set(struct mb86a16_state *state, unsigned char IQINV)
-{
-	/* Viterbi Rate, IQ Settings */
-	if (mb86a16_write(state, 0x06, 0xdf | (IQINV << 5)) < 0) {
-		dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
-		return -EREMOTEIO;
-	}
-
-	return 0;
-}
-
-static int FEC_srst(struct mb86a16_state *state)
-{
-	if (mb86a16_write(state, MB86A16_RESET, 0x02) < 0) {
-		dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
-		return -EREMOTEIO;
-	}
-
-	return 0;
-}
-
-static int S2T_set(struct mb86a16_state *state, unsigned char S2T)
-{
-	if (mb86a16_write(state, 0x34, 0x70 | S2T) < 0) {
-		dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
-		return -EREMOTEIO;
-	}
-
-	return 0;
-}
-
-static int S45T_set(struct mb86a16_state *state, unsigned char S4T, unsigned char S5T)
-{
-	if (mb86a16_write(state, 0x35, 0x00 | (S5T << 4) | S4T) < 0) {
-		dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
-		return -EREMOTEIO;
-	}
-
-	return 0;
-}
-
-
-static int mb86a16_set_fe(struct mb86a16_state *state)
-{
-	u8 agcval, cnmval;
-
-	int i, j;
-	int fOSC = 0;
-	int fOSC_start = 0;
-	int wait_t;
-	int fcp;
-	int swp_ofs;
-	int V[60];
-	u8 SIG1MIN;
-
-	unsigned char CREN, AFCEN, AFCEXEN;
-	unsigned char SIG1;
-	unsigned char TIMINT1, TIMINT2, TIMEXT;
-	unsigned char S0T, S1T;
-	unsigned char S2T;
-/*	unsigned char S2T, S3T; */
-	unsigned char S4T, S5T;
-	unsigned char AFCEX_L, AFCEX_H;
-	unsigned char R;
-	unsigned char VIRM;
-	unsigned char ETH, VIA;
-	unsigned char junk;
-
-	int loop;
-	int ftemp;
-	int v, vmax, vmin;
-	int vmax_his, vmin_his;
-	int swp_freq, prev_swp_freq[20];
-	int prev_freq_num;
-	int signal_dupl;
-	int afcex_freq;
-	int signal;
-	int afcerr;
-	int temp_freq, delta_freq;
-	int dagcm[4];
-	int smrt_d;
-/*	int freq_err; */
-	int n;
-	int ret = -1;
-	int sync;
-
-	dprintk(verbose, MB86A16_INFO, 1, "freq=%d Mhz, symbrt=%d Ksps", state->frequency, state->srate);
-
-	fcp = 3000;
-	swp_ofs = state->srate / 4;
-
-	for (i = 0; i < 60; i++)
-		V[i] = -1;
-
-	for (i = 0; i < 20; i++)
-		prev_swp_freq[i] = 0;
-
-	SIG1MIN = 25;
-
-	for (n = 0; ((n < 3) && (ret == -1)); n++) {
-		SEQ_set(state, 0);
-		iq_vt_set(state, 0);
-
-		CREN = 0;
-		AFCEN = 0;
-		AFCEXEN = 1;
-		TIMINT1 = 0;
-		TIMINT2 = 1;
-		TIMEXT = 2;
-		S1T = 0;
-		S0T = 0;
-
-		if (initial_set(state) < 0) {
-			dprintk(verbose, MB86A16_ERROR, 1, "initial set failed");
-			return -1;
-		}
-		if (DAGC_data_set(state, 3, 2) < 0) {
-			dprintk(verbose, MB86A16_ERROR, 1, "DAGC data set error");
-			return -1;
-		}
-		if (EN_set(state, CREN, AFCEN) < 0) {
-			dprintk(verbose, MB86A16_ERROR, 1, "EN set error");
-			return -1; /* (0, 0) */
-		}
-		if (AFCEXEN_set(state, AFCEXEN, state->srate) < 0) {
-			dprintk(verbose, MB86A16_ERROR, 1, "AFCEXEN set error");
-			return -1; /* (1, smrt) = (1, symbolrate) */
-		}
-		if (CNTM_set(state, TIMINT1, TIMINT2, TIMEXT) < 0) {
-			dprintk(verbose, MB86A16_ERROR, 1, "CNTM set error");
-			return -1; /* (0, 1, 2) */
-		}
-		if (S01T_set(state, S1T, S0T) < 0) {
-			dprintk(verbose, MB86A16_ERROR, 1, "S01T set error");
-			return -1; /* (0, 0) */
-		}
-		smrt_info_get(state, state->srate);
-		if (smrt_set(state, state->srate) < 0) {
-			dprintk(verbose, MB86A16_ERROR, 1, "smrt info get error");
-			return -1;
-		}
-
-		R = vco_dev_get(state, state->srate);
-		if (R == 1)
-			fOSC_start = state->frequency;
-
-		else if (R == 0) {
-			if (state->frequency % 2 == 0) {
-				fOSC_start = state->frequency;
-			} else {
-				fOSC_start = state->frequency + 1;
-				if (fOSC_start > 2150)
-					fOSC_start = state->frequency - 1;
-			}
-		}
-		loop = 1;
-		ftemp = fOSC_start * 1000;
-		vmax = 0 ;
-		while (loop == 1) {
-			ftemp = ftemp + swp_ofs;
-			vmax++;
-
-			/* Upper bound */
-			if (ftemp > 2150000) {
-				loop = 0;
-				vmax--;
-			} else {
-				if ((ftemp == 2150000) ||
-				    (ftemp - state->frequency * 1000 >= fcp + state->srate / 4))
-					loop = 0;
-			}
-		}
-
-		loop = 1;
-		ftemp = fOSC_start * 1000;
-		vmin = 0 ;
-		while (loop == 1) {
-			ftemp = ftemp - swp_ofs;
-			vmin--;
-
-			/* Lower bound */
-			if (ftemp < 950000) {
-				loop = 0;
-				vmin++;
-			} else {
-				if ((ftemp == 950000) ||
-				    (state->frequency * 1000 - ftemp >= fcp + state->srate / 4))
-					loop = 0;
-			}
-		}
-
-		wait_t = (8000 + state->srate / 2) / state->srate;
-		if (wait_t == 0)
-			wait_t = 1;
-
-		i = 0;
-		j = 0;
-		prev_freq_num = 0;
-		loop = 1;
-		signal = 0;
-		vmax_his = 0;
-		vmin_his = 0;
-		v = 0;
-
-		while (loop == 1) {
-			swp_info_get(state, fOSC_start, state->srate,
-				     v, R, swp_ofs, &fOSC,
-				     &afcex_freq, &AFCEX_L, &AFCEX_H);
-
-			udelay(100);
-			if (rf_val_set(state, fOSC, state->srate, R) < 0) {
-				dprintk(verbose, MB86A16_ERROR, 1, "rf val set error");
-				return -1;
-			}
-			udelay(100);
-			if (afcex_data_set(state, AFCEX_L, AFCEX_H) < 0) {
-				dprintk(verbose, MB86A16_ERROR, 1, "afcex data set error");
-				return -1;
-			}
-			if (srst(state) < 0) {
-				dprintk(verbose, MB86A16_ERROR, 1, "srst error");
-				return -1;
-			}
-			msleep_interruptible(wait_t);
-
-			if (mb86a16_read(state, 0x37, &SIG1) != 2) {
-				dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
-				return -1;
-			}
-			V[30 + v] = SIG1 ;
-			swp_freq = swp_freq_calcuation(state, i, v, V, vmax, vmin,
-						      SIG1MIN, fOSC, afcex_freq,
-						      swp_ofs, &SIG1);	/* changed */
-
-			signal_dupl = 0;
-			for (j = 0; j < prev_freq_num; j++) {
-				if ((ABS(prev_swp_freq[j] - swp_freq)) < (swp_ofs * 3 / 2)) {
-					signal_dupl = 1;
-					dprintk(verbose, MB86A16_INFO, 1, "Probably Duplicate Signal, j = %d", j);
-				}
-			}
-			if ((signal_dupl == 0) && (swp_freq > 0) && (ABS(swp_freq - state->frequency * 1000) < fcp + state->srate / 6)) {
-				dprintk(verbose, MB86A16_DEBUG, 1, "------ Signal detect ------ [swp_freq=[%07d, srate=%05d]]", swp_freq, state->srate);
-				prev_swp_freq[prev_freq_num] = swp_freq;
-				prev_freq_num++;
-				swp_info_get2(state, state->srate, R, swp_freq,
-					      &afcex_freq, &fOSC,
-					      &AFCEX_L, &AFCEX_H);
-
-				if (rf_val_set(state, fOSC, state->srate, R) < 0) {
-					dprintk(verbose, MB86A16_ERROR, 1, "rf val set error");
-					return -1;
-				}
-				if (afcex_data_set(state, AFCEX_L, AFCEX_H) < 0) {
-					dprintk(verbose, MB86A16_ERROR, 1, "afcex data set error");
-					return -1;
-				}
-				signal = signal_det(state, state->srate, &SIG1);
-				if (signal == 1) {
-					dprintk(verbose, MB86A16_ERROR, 1, "***** Signal Found *****");
-					loop = 0;
-				} else {
-					dprintk(verbose, MB86A16_ERROR, 1, "!!!!! No signal !!!!!, try again...");
-					smrt_info_get(state, state->srate);
-					if (smrt_set(state, state->srate) < 0) {
-						dprintk(verbose, MB86A16_ERROR, 1, "smrt set error");
-						return -1;
-					}
-				}
-			}
-			if (v > vmax)
-				vmax_his = 1 ;
-			if (v < vmin)
-				vmin_his = 1 ;
-			i++;
-
-			if ((i % 2 == 1) && (vmax_his == 1))
-				i++;
-			if ((i % 2 == 0) && (vmin_his == 1))
-				i++;
-
-			if (i % 2 == 1)
-				v = (i + 1) / 2;
-			else
-				v = -i / 2;
-
-			if ((vmax_his == 1) && (vmin_his == 1))
-				loop = 0 ;
-		}
-
-		if (signal == 1) {
-			dprintk(verbose, MB86A16_INFO, 1, " Start Freq Error Check");
-			S1T = 7 ;
-			S0T = 1 ;
-			CREN = 0 ;
-			AFCEN = 1 ;
-			AFCEXEN = 0 ;
-
-			if (S01T_set(state, S1T, S0T) < 0) {
-				dprintk(verbose, MB86A16_ERROR, 1, "S01T set error");
-				return -1;
-			}
-			smrt_info_get(state, state->srate);
-			if (smrt_set(state, state->srate) < 0) {
-				dprintk(verbose, MB86A16_ERROR, 1, "smrt set error");
-				return -1;
-			}
-			if (EN_set(state, CREN, AFCEN) < 0) {
-				dprintk(verbose, MB86A16_ERROR, 1, "EN set error");
-				return -1;
-			}
-			if (AFCEXEN_set(state, AFCEXEN, state->srate) < 0) {
-				dprintk(verbose, MB86A16_ERROR, 1, "AFCEXEN set error");
-				return -1;
-			}
-			afcex_info_get(state, afcex_freq, &AFCEX_L, &AFCEX_H);
-			if (afcofs_data_set(state, AFCEX_L, AFCEX_H) < 0) {
-				dprintk(verbose, MB86A16_ERROR, 1, "AFCOFS data set error");
-				return -1;
-			}
-			if (srst(state) < 0) {
-				dprintk(verbose, MB86A16_ERROR, 1, "srst error");
-				return -1;
-			}
-			/* delay 4~200 */
-			wait_t = 200000 / state->master_clk + 200000 / state->srate;
-			msleep(wait_t);
-			afcerr = afcerr_chk(state);
-			if (afcerr == -1)
-				return -1;
-
-			swp_freq = fOSC * 1000 + afcerr ;
-			AFCEXEN = 1 ;
-			if (state->srate >= 1500)
-				smrt_d = state->srate / 3;
-			else
-				smrt_d = state->srate / 2;
-			smrt_info_get(state, smrt_d);
-			if (smrt_set(state, smrt_d) < 0) {
-				dprintk(verbose, MB86A16_ERROR, 1, "smrt set error");
-				return -1;
-			}
-			if (AFCEXEN_set(state, AFCEXEN, smrt_d) < 0) {
-				dprintk(verbose, MB86A16_ERROR, 1, "AFCEXEN set error");
-				return -1;
-			}
-			R = vco_dev_get(state, smrt_d);
-			if (DAGC_data_set(state, 2, 0) < 0) {
-				dprintk(verbose, MB86A16_ERROR, 1, "DAGC data set error");
-				return -1;
-			}
-			for (i = 0; i < 3; i++) {
-				temp_freq = swp_freq + (i - 1) * state->srate / 8;
-				swp_info_get2(state, smrt_d, R, temp_freq, &afcex_freq, &fOSC, &AFCEX_L, &AFCEX_H);
-				if (rf_val_set(state, fOSC, smrt_d, R) < 0) {
-					dprintk(verbose, MB86A16_ERROR, 1, "rf val set error");
-					return -1;
-				}
-				if (afcex_data_set(state, AFCEX_L, AFCEX_H) < 0) {
-					dprintk(verbose, MB86A16_ERROR, 1, "afcex data set error");
-					return -1;
-				}
-				wait_t = 200000 / state->master_clk + 40000 / smrt_d;
-				msleep(wait_t);
-				dagcm[i] = dagcm_val_get(state);
-			}
-			if ((dagcm[0] > dagcm[1]) &&
-			    (dagcm[0] > dagcm[2]) &&
-			    (dagcm[0] - dagcm[1] > 2 * (dagcm[2] - dagcm[1]))) {
-
-				temp_freq = swp_freq - 2 * state->srate / 8;
-				swp_info_get2(state, smrt_d, R, temp_freq, &afcex_freq, &fOSC, &AFCEX_L, &AFCEX_H);
-				if (rf_val_set(state, fOSC, smrt_d, R) < 0) {
-					dprintk(verbose, MB86A16_ERROR, 1, "rf val set error");
-					return -1;
-				}
-				if (afcex_data_set(state, AFCEX_L, AFCEX_H) < 0) {
-					dprintk(verbose, MB86A16_ERROR, 1, "afcex data set");
-					return -1;
-				}
-				wait_t = 200000 / state->master_clk + 40000 / smrt_d;
-				msleep(wait_t);
-				dagcm[3] = dagcm_val_get(state);
-				if (dagcm[3] > dagcm[1])
-					delta_freq = (dagcm[2] - dagcm[0] + dagcm[1] - dagcm[3]) * state->srate / 300;
-				else
-					delta_freq = 0;
-			} else if ((dagcm[2] > dagcm[1]) &&
-				   (dagcm[2] > dagcm[0]) &&
-				   (dagcm[2] - dagcm[1] > 2 * (dagcm[0] - dagcm[1]))) {
-
-				temp_freq = swp_freq + 2 * state->srate / 8;
-				swp_info_get2(state, smrt_d, R, temp_freq, &afcex_freq, &fOSC, &AFCEX_L, &AFCEX_H);
-				if (rf_val_set(state, fOSC, smrt_d, R) < 0) {
-					dprintk(verbose, MB86A16_ERROR, 1, "rf val set");
-					return -1;
-				}
-				if (afcex_data_set(state, AFCEX_L, AFCEX_H) < 0) {
-					dprintk(verbose, MB86A16_ERROR, 1, "afcex data set");
-					return -1;
-				}
-				wait_t = 200000 / state->master_clk + 40000 / smrt_d;
-				msleep(wait_t);
-				dagcm[3] = dagcm_val_get(state);
-				if (dagcm[3] > dagcm[1])
-					delta_freq = (dagcm[2] - dagcm[0] + dagcm[3] - dagcm[1]) * state->srate / 300;
-				else
-					delta_freq = 0 ;
-
-			} else {
-				delta_freq = 0 ;
-			}
-			dprintk(verbose, MB86A16_INFO, 1, "SWEEP Frequency = %d", swp_freq);
-			swp_freq += delta_freq;
-			dprintk(verbose, MB86A16_INFO, 1, "Adjusting .., DELTA Freq = %d, SWEEP Freq=%d", delta_freq, swp_freq);
-			if (ABS(state->frequency * 1000 - swp_freq) > 3800) {
-				dprintk(verbose, MB86A16_INFO, 1, "NO  --  SIGNAL !");
-			} else {
-
-				S1T = 0;
-				S0T = 3;
-				CREN = 1;
-				AFCEN = 0;
-				AFCEXEN = 1;
-
-				if (S01T_set(state, S1T, S0T) < 0) {
-					dprintk(verbose, MB86A16_ERROR, 1, "S01T set error");
-					return -1;
-				}
-				if (DAGC_data_set(state, 0, 0) < 0) {
-					dprintk(verbose, MB86A16_ERROR, 1, "DAGC data set error");
-					return -1;
-				}
-				R = vco_dev_get(state, state->srate);
-				smrt_info_get(state, state->srate);
-				if (smrt_set(state, state->srate) < 0) {
-					dprintk(verbose, MB86A16_ERROR, 1, "smrt set error");
-					return -1;
-				}
-				if (EN_set(state, CREN, AFCEN) < 0) {
-					dprintk(verbose, MB86A16_ERROR, 1, "EN set error");
-					return -1;
-				}
-				if (AFCEXEN_set(state, AFCEXEN, state->srate) < 0) {
-					dprintk(verbose, MB86A16_ERROR, 1, "AFCEXEN set error");
-					return -1;
-				}
-				swp_info_get2(state, state->srate, R, swp_freq, &afcex_freq, &fOSC, &AFCEX_L, &AFCEX_H);
-				if (rf_val_set(state, fOSC, state->srate, R) < 0) {
-					dprintk(verbose, MB86A16_ERROR, 1, "rf val set error");
-					return -1;
-				}
-				if (afcex_data_set(state, AFCEX_L, AFCEX_H) < 0) {
-					dprintk(verbose, MB86A16_ERROR, 1, "afcex data set error");
-					return -1;
-				}
-				if (srst(state) < 0) {
-					dprintk(verbose, MB86A16_ERROR, 1, "srst error");
-					return -1;
-				}
-				wait_t = 7 + (10000 + state->srate / 2) / state->srate;
-				if (wait_t == 0)
-					wait_t = 1;
-				msleep_interruptible(wait_t);
-				if (mb86a16_read(state, 0x37, &SIG1) != 2) {
-					dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
-					return -EREMOTEIO;
-				}
-
-				if (SIG1 > 110) {
-					S2T = 4; S4T = 1; S5T = 6; ETH = 4; VIA = 6;
-					wait_t = 7 + (917504 + state->srate / 2) / state->srate;
-				} else if (SIG1 > 105) {
-					S2T = 4; S4T = 2; S5T = 8; ETH = 7; VIA = 2;
-					wait_t = 7 + (1048576 + state->srate / 2) / state->srate;
-				} else if (SIG1 > 85) {
-					S2T = 5; S4T = 2; S5T = 8; ETH = 7; VIA = 2;
-					wait_t = 7 + (1310720 + state->srate / 2) / state->srate;
-				} else if (SIG1 > 65) {
-					S2T = 6; S4T = 2; S5T = 8; ETH = 7; VIA = 2;
-					wait_t = 7 + (1572864 + state->srate / 2) / state->srate;
-				} else {
-					S2T = 7; S4T = 2; S5T = 8; ETH = 7; VIA = 2;
-					wait_t = 7 + (2097152 + state->srate / 2) / state->srate;
-				}
-				wait_t *= 2; /* FOS */
-				S2T_set(state, S2T);
-				S45T_set(state, S4T, S5T);
-				Vi_set(state, ETH, VIA);
-				srst(state);
-				msleep_interruptible(wait_t);
-				sync = sync_chk(state, &VIRM);
-				dprintk(verbose, MB86A16_INFO, 1, "-------- Viterbi=[%d] SYNC=[%d] ---------", VIRM, sync);
-				if (VIRM) {
-					if (VIRM == 4) {
-						/* 5/6 */
-						if (SIG1 > 110)
-							wait_t = (786432 + state->srate / 2) / state->srate;
-						else
-							wait_t = (1572864 + state->srate / 2) / state->srate;
-						if (state->srate < 5000)
-							/* FIXME ! , should be a long wait ! */
-							msleep_interruptible(wait_t);
-						else
-							msleep_interruptible(wait_t);
-
-						if (sync_chk(state, &junk) == 0) {
-							iq_vt_set(state, 1);
-							FEC_srst(state);
-						}
-					}
-					/* 1/2, 2/3, 3/4, 7/8 */
-					if (SIG1 > 110)
-						wait_t = (786432 + state->srate / 2) / state->srate;
-					else
-						wait_t = (1572864 + state->srate / 2) / state->srate;
-					msleep_interruptible(wait_t);
-					SEQ_set(state, 1);
-				} else {
-					dprintk(verbose, MB86A16_INFO, 1, "NO  -- SYNC");
-					SEQ_set(state, 1);
-					ret = -1;
-				}
-			}
-		} else {
-			dprintk(verbose, MB86A16_INFO, 1, "NO  -- SIGNAL");
-			ret = -1;
-		}
-
-		sync = sync_chk(state, &junk);
-		if (sync) {
-			dprintk(verbose, MB86A16_INFO, 1, "******* SYNC *******");
-			freqerr_chk(state, state->frequency, state->srate, 1);
-			ret = 0;
-			break;
-		}
-	}
-
-	mb86a16_read(state, 0x15, &agcval);
-	mb86a16_read(state, 0x26, &cnmval);
-	dprintk(verbose, MB86A16_INFO, 1, "AGC = %02x CNM = %02x", agcval, cnmval);
-
-	return ret;
-}
-
-static int mb86a16_send_diseqc_msg(struct dvb_frontend *fe,
-				   struct dvb_diseqc_master_cmd *cmd)
-{
-	struct mb86a16_state *state = fe->demodulator_priv;
-	int i;
-	u8 regs;
-
-	if (mb86a16_write(state, MB86A16_DCC1, MB86A16_DCC1_DISTA) < 0)
-		goto err;
-	if (mb86a16_write(state, MB86A16_DCCOUT, 0x00) < 0)
-		goto err;
-	if (mb86a16_write(state, MB86A16_TONEOUT2, 0x04) < 0)
-		goto err;
-
-	regs = 0x18;
-
-	if (cmd->msg_len > 5 || cmd->msg_len < 4)
-		return -EINVAL;
-
-	for (i = 0; i < cmd->msg_len; i++) {
-		if (mb86a16_write(state, regs, cmd->msg[i]) < 0)
-			goto err;
-
-		regs++;
-	}
-	i += 0x90;
-
-	msleep_interruptible(10);
-
-	if (mb86a16_write(state, MB86A16_DCC1, i) < 0)
-		goto err;
-	if (mb86a16_write(state, MB86A16_DCCOUT, MB86A16_DCCOUT_DISEN) < 0)
-		goto err;
-
-	return 0;
-
-err:
-	dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
-	return -EREMOTEIO;
-}
-
-static int mb86a16_send_diseqc_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t burst)
-{
-	struct mb86a16_state *state = fe->demodulator_priv;
-
-	switch (burst) {
-	case SEC_MINI_A:
-		if (mb86a16_write(state, MB86A16_DCC1, MB86A16_DCC1_DISTA |
-						       MB86A16_DCC1_TBEN  |
-						       MB86A16_DCC1_TBO) < 0)
-			goto err;
-		if (mb86a16_write(state, MB86A16_DCCOUT, MB86A16_DCCOUT_DISEN) < 0)
-			goto err;
-		break;
-	case SEC_MINI_B:
-		if (mb86a16_write(state, MB86A16_DCC1, MB86A16_DCC1_DISTA |
-						       MB86A16_DCC1_TBEN) < 0)
-			goto err;
-		if (mb86a16_write(state, MB86A16_DCCOUT, MB86A16_DCCOUT_DISEN) < 0)
-			goto err;
-		break;
-	}
-
-	return 0;
-err:
-	dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
-	return -EREMOTEIO;
-}
-
-static int mb86a16_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
-{
-	struct mb86a16_state *state = fe->demodulator_priv;
-
-	switch (tone) {
-	case SEC_TONE_ON:
-		if (mb86a16_write(state, MB86A16_TONEOUT2, 0x00) < 0)
-			goto err;
-		if (mb86a16_write(state, MB86A16_DCC1, MB86A16_DCC1_DISTA |
-						       MB86A16_DCC1_CTOE) < 0)
-
-			goto err;
-		if (mb86a16_write(state, MB86A16_DCCOUT, MB86A16_DCCOUT_DISEN) < 0)
-			goto err;
-		break;
-	case SEC_TONE_OFF:
-		if (mb86a16_write(state, MB86A16_TONEOUT2, 0x04) < 0)
-			goto err;
-		if (mb86a16_write(state, MB86A16_DCC1, MB86A16_DCC1_DISTA) < 0)
-			goto err;
-		if (mb86a16_write(state, MB86A16_DCCOUT, 0x00) < 0)
-			goto err;
-		break;
-	default:
-		return -EINVAL;
-	}
-	return 0;
-
-err:
-	dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
-	return -EREMOTEIO;
-}
-
-static enum dvbfe_search mb86a16_search(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct mb86a16_state *state = fe->demodulator_priv;
-
-	state->frequency = p->frequency / 1000;
-	state->srate = p->symbol_rate / 1000;
-
-	if (!mb86a16_set_fe(state)) {
-		dprintk(verbose, MB86A16_ERROR, 1, "Successfully acquired LOCK");
-		return DVBFE_ALGO_SEARCH_SUCCESS;
-	}
-
-	dprintk(verbose, MB86A16_ERROR, 1, "Lock acquisition failed!");
-	return DVBFE_ALGO_SEARCH_FAILED;
-}
-
-static void mb86a16_release(struct dvb_frontend *fe)
-{
-	struct mb86a16_state *state = fe->demodulator_priv;
-	kfree(state);
-}
-
-static int mb86a16_init(struct dvb_frontend *fe)
-{
-	return 0;
-}
-
-static int mb86a16_sleep(struct dvb_frontend *fe)
-{
-	return 0;
-}
-
-static int mb86a16_read_ber(struct dvb_frontend *fe, u32 *ber)
-{
-	u8 ber_mon, ber_tab, ber_lsb, ber_mid, ber_msb, ber_tim, ber_rst;
-	u32 timer;
-
-	struct mb86a16_state *state = fe->demodulator_priv;
-
-	*ber = 0;
-	if (mb86a16_read(state, MB86A16_BERMON, &ber_mon) != 2)
-		goto err;
-	if (mb86a16_read(state, MB86A16_BERTAB, &ber_tab) != 2)
-		goto err;
-	if (mb86a16_read(state, MB86A16_BERLSB, &ber_lsb) != 2)
-		goto err;
-	if (mb86a16_read(state, MB86A16_BERMID, &ber_mid) != 2)
-		goto err;
-	if (mb86a16_read(state, MB86A16_BERMSB, &ber_msb) != 2)
-		goto err;
-	/* BER monitor invalid when BER_EN = 0	*/
-	if (ber_mon & 0x04) {
-		/* coarse, fast calculation	*/
-		*ber = ber_tab & 0x1f;
-		dprintk(verbose, MB86A16_DEBUG, 1, "BER coarse=[0x%02x]", *ber);
-		if (ber_mon & 0x01) {
-			/*
-			 * BER_SEL = 1, The monitored BER is the estimated
-			 * value with a Reed-Solomon decoder error amount at
-			 * the deinterleaver output.
-			 * monitored BER is expressed as a 20 bit output in total
-			 */
-			ber_rst = ber_mon >> 3;
-			*ber = (((ber_msb << 8) | ber_mid) << 8) | ber_lsb;
-			if (ber_rst == 0)
-				timer =  12500000;
-			if (ber_rst == 1)
-				timer =  25000000;
-			if (ber_rst == 2)
-				timer =  50000000;
-			if (ber_rst == 3)
-				timer = 100000000;
-
-			*ber /= timer;
-			dprintk(verbose, MB86A16_DEBUG, 1, "BER fine=[0x%02x]", *ber);
-		} else {
-			/*
-			 * BER_SEL = 0, The monitored BER is the estimated
-			 * value with a Viterbi decoder error amount at the
-			 * QPSK demodulator output.
-			 * monitored BER is expressed as a 24 bit output in total
-			 */
-			ber_tim = ber_mon >> 1;
-			*ber = (((ber_msb << 8) | ber_mid) << 8) | ber_lsb;
-			if (ber_tim == 0)
-				timer = 16;
-			if (ber_tim == 1)
-				timer = 24;
-
-			*ber /= 2 ^ timer;
-			dprintk(verbose, MB86A16_DEBUG, 1, "BER fine=[0x%02x]", *ber);
-		}
-	}
-	return 0;
-err:
-	dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
-	return -EREMOTEIO;
-}
-
-static int mb86a16_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
-{
-	u8 agcm = 0;
-	struct mb86a16_state *state = fe->demodulator_priv;
-
-	*strength = 0;
-	if (mb86a16_read(state, MB86A16_AGCM, &agcm) != 2) {
-		dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
-		return -EREMOTEIO;
-	}
-
-	*strength = ((0xff - agcm) * 100) / 256;
-	dprintk(verbose, MB86A16_DEBUG, 1, "Signal strength=[%d %%]", (u8) *strength);
-	*strength = (0xffff - 0xff) + agcm;
-
-	return 0;
-}
-
-struct cnr {
-	u8 cn_reg;
-	u8 cn_val;
-};
-
-static const struct cnr cnr_tab[] = {
-	{  35,  2 },
-	{  40,  3 },
-	{  50,  4 },
-	{  60,  5 },
-	{  70,  6 },
-	{  80,  7 },
-	{  92,  8 },
-	{ 103,  9 },
-	{ 115, 10 },
-	{ 138, 12 },
-	{ 162, 15 },
-	{ 180, 18 },
-	{ 185, 19 },
-	{ 189, 20 },
-	{ 195, 22 },
-	{ 199, 24 },
-	{ 201, 25 },
-	{ 202, 26 },
-	{ 203, 27 },
-	{ 205, 28 },
-	{ 208, 30 }
-};
-
-static int mb86a16_read_snr(struct dvb_frontend *fe, u16 *snr)
-{
-	struct mb86a16_state *state = fe->demodulator_priv;
-	int i = 0;
-	int low_tide = 2, high_tide = 30, q_level;
-	u8  cn;
-
-	*snr = 0;
-	if (mb86a16_read(state, 0x26, &cn) != 2) {
-		dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
-		return -EREMOTEIO;
-	}
-
-	for (i = 0; i < ARRAY_SIZE(cnr_tab); i++) {
-		if (cn < cnr_tab[i].cn_reg) {
-			*snr = cnr_tab[i].cn_val;
-			break;
-		}
-	}
-	q_level = (*snr * 100) / (high_tide - low_tide);
-	dprintk(verbose, MB86A16_ERROR, 1, "SNR (Quality) = [%d dB], Level=%d %%", *snr, q_level);
-	*snr = (0xffff - 0xff) + *snr;
-
-	return 0;
-}
-
-static int mb86a16_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
-{
-	u8 dist;
-	struct mb86a16_state *state = fe->demodulator_priv;
-
-	if (mb86a16_read(state, MB86A16_DISTMON, &dist) != 2) {
-		dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
-		return -EREMOTEIO;
-	}
-	*ucblocks = dist;
-
-	return 0;
-}
-
-static enum dvbfe_algo mb86a16_frontend_algo(struct dvb_frontend *fe)
-{
-	return DVBFE_ALGO_CUSTOM;
-}
-
-static struct dvb_frontend_ops mb86a16_ops = {
-	.delsys = { SYS_DVBS },
-	.info = {
-		.name			= "Fujitsu MB86A16 DVB-S",
-		.frequency_min		= 950000,
-		.frequency_max		= 2150000,
-		.frequency_stepsize	= 3000,
-		.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_FEC_AUTO
-	},
-	.release			= mb86a16_release,
-
-	.get_frontend_algo		= mb86a16_frontend_algo,
-	.search				= mb86a16_search,
-	.init				= mb86a16_init,
-	.sleep				= mb86a16_sleep,
-	.read_status			= mb86a16_read_status,
-
-	.read_ber			= mb86a16_read_ber,
-	.read_signal_strength		= mb86a16_read_signal_strength,
-	.read_snr			= mb86a16_read_snr,
-	.read_ucblocks			= mb86a16_read_ucblocks,
-
-	.diseqc_send_master_cmd		= mb86a16_send_diseqc_msg,
-	.diseqc_send_burst		= mb86a16_send_diseqc_burst,
-	.set_tone			= mb86a16_set_tone,
-};
-
-struct dvb_frontend *mb86a16_attach(const struct mb86a16_config *config,
-				    struct i2c_adapter *i2c_adap)
-{
-	u8 dev_id = 0;
-	struct mb86a16_state *state = NULL;
-
-	state = kmalloc(sizeof(struct mb86a16_state), GFP_KERNEL);
-	if (state == NULL)
-		goto error;
-
-	state->config = config;
-	state->i2c_adap = i2c_adap;
-
-	mb86a16_read(state, 0x7f, &dev_id);
-	if (dev_id != 0xfe)
-		goto error;
-
-	memcpy(&state->frontend.ops, &mb86a16_ops, sizeof(struct dvb_frontend_ops));
-	state->frontend.demodulator_priv = state;
-	state->frontend.ops.set_voltage = state->config->set_voltage;
-
-	return &state->frontend;
-error:
-	kfree(state);
-	return NULL;
-}
-EXPORT_SYMBOL(mb86a16_attach);
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Manu Abraham");
diff --git a/drivers/media/dvb/frontends/mb86a16.h b/drivers/media/dvb/frontends/mb86a16.h
deleted file mode 100644
index 6ea8c37..0000000
--- a/drivers/media/dvb/frontends/mb86a16.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
-	Fujitsu MB86A16 DVB-S/DSS DC Receiver driver
-
-	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#ifndef __MB86A16_H
-#define __MB86A16_H
-
-#include <linux/dvb/frontend.h>
-#include "dvb_frontend.h"
-
-
-struct mb86a16_config {
-	u8 demod_address;
-
-	int (*set_voltage)(struct dvb_frontend *fe, fe_sec_voltage_t voltage);
-};
-
-
-
-#if defined(CONFIG_DVB_MB86A16) || (defined(CONFIG_DVB_MB86A16_MODULE) && defined(MODULE))
-
-extern struct dvb_frontend *mb86a16_attach(const struct mb86a16_config *config,
-					   struct i2c_adapter *i2c_adap);
-
-#else
-
-static inline struct dvb_frontend *mb86a16_attach(const struct mb86a16_config *config,
-					   struct i2c_adapter *i2c_adap)
-{
-	printk(KERN_WARNING "%s: Driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-
-#endif /* CONFIG_DVB_MB86A16 */
-
-#endif /* __MB86A16_H */
diff --git a/drivers/media/dvb/frontends/mb86a16_priv.h b/drivers/media/dvb/frontends/mb86a16_priv.h
deleted file mode 100644
index 360a35a..0000000
--- a/drivers/media/dvb/frontends/mb86a16_priv.h
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
-	Fujitsu MB86A16 DVB-S/DSS DC Receiver driver
-
-	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#ifndef __MB86A16_PRIV_H
-#define __MB86A16_PRIV_H
-
-#define MB86A16_TSOUT		0x00
-#define MB86A16_TSOUT_HIZSEL	(0x01 << 5)
-#define MB86A16_TSOUT_HIZCNTI	(0x01 << 4)
-#define MB86A16_TSOUT_MODE	(0x01 << 3)
-#define MB86A16_TSOUT_ORDER	(0x01 << 2)
-#define MB86A16_TSOUT_ERROR	(0x01 << 1)
-#define Mb86A16_TSOUT_EDGE	(0x01 << 0)
-
-#define MB86A16_FEC		0x01
-#define MB86A16_FEC_FSYNC	(0x01 << 5)
-#define MB86A16_FEC_PCKB8	(0x01 << 4)
-#define MB86A16_FEC_DVDS	(0x01 << 3)
-#define MB86A16_FEC_EREN	(0x01 << 2)
-#define Mb86A16_FEC_RSEN	(0x01 << 1)
-#define MB86A16_FEC_DIEN	(0x01 << 0)
-
-#define MB86A16_AGC		0x02
-#define MB86A16_AGC_AGMD	(0x01 << 6)
-#define MB86A16_AGC_AGCW	(0x0f << 2)
-#define MB86A16_AGC_AGCP	(0x01 << 1)
-#define MB86A16_AGC_AGCR	(0x01 << 0)
-
-#define MB86A16_SRATE1		0x03
-#define MB86A16_SRATE1_DECI	(0x07 << 2)
-#define MB86A16_SRATE1_CSEL	(0x01 << 1)
-#define MB86A16_SRATE1_RSEL	(0x01 << 0)
-
-#define MB86A16_SRATE2		0x04
-#define MB86A16_SRATE2_STOFSL	(0xff << 0)
-
-#define MB86A16_SRATE3		0x05
-#define MB86A16_SRATE2_STOFSH	(0xff << 0)
-
-#define MB86A16_VITERBI		0x06
-#define MB86A16_FRAMESYNC	0x07
-#define MB86A16_CRLFILTCOEF1	0x08
-#define MB86A16_CRLFILTCOEF2	0x09
-#define MB86A16_STRFILTCOEF1	0x0a
-#define MB86A16_STRFILTCOEF2	0x0b
-#define MB86A16_RESET		0x0c
-#define MB86A16_STATUS		0x0d
-#define MB86A16_AFCML		0x0e
-#define MB86A16_AFCMH		0x0f
-#define MB86A16_BERMON		0x10
-#define MB86A16_BERTAB		0x11
-#define MB86A16_BERLSB		0x12
-#define MB86A16_BERMID		0x13
-#define MB86A16_BERMSB		0x14
-#define MB86A16_AGCM		0x15
-
-#define MB86A16_DCC1		0x16
-#define MB86A16_DCC1_DISTA	(0x01 << 7)
-#define MB86A16_DCC1_PRTY	(0x01 << 6)
-#define MB86A16_DCC1_CTOE	(0x01 << 5)
-#define MB86A16_DCC1_TBEN	(0x01 << 4)
-#define MB86A16_DCC1_TBO	(0x01 << 3)
-#define MB86A16_DCC1_NUM	(0x07 << 0)
-
-#define MB86A16_DCC2		0x17
-#define MB86A16_DCC2_DCBST	(0x01 << 0)
-
-#define MB86A16_DCC3		0x18
-#define MB86A16_DCC3_CODE0	(0xff << 0)
-
-#define MB86A16_DCC4		0x19
-#define MB86A16_DCC4_CODE1	(0xff << 0)
-
-#define MB86A16_DCC5		0x1a
-#define MB86A16_DCC5_CODE2	(0xff << 0)
-
-#define MB86A16_DCC6		0x1b
-#define MB86A16_DCC6_CODE3	(0xff << 0)
-
-#define MB86A16_DCC7		0x1c
-#define MB86A16_DCC7_CODE4	(0xff << 0)
-
-#define MB86A16_DCC8		0x1d
-#define MB86A16_DCC8_CODE5	(0xff << 0)
-
-#define MB86A16_DCCOUT		0x1e
-#define MB86A16_DCCOUT_DISEN	(0x01 << 0)
-
-#define MB86A16_TONEOUT1	0x1f
-#define MB86A16_TONE_TDIVL	(0xff << 0)
-
-#define MB86A16_TONEOUT2	0x20
-#define MB86A16_TONE_TMD	(0x03 << 2)
-#define MB86A16_TONE_TDIVH	(0x03 << 0)
-
-#define MB86A16_FREQ1		0x21
-#define MB86A16_FREQ2		0x22
-#define MB86A16_FREQ3		0x23
-#define MB86A16_FREQ4		0x24
-#define MB86A16_FREQSET		0x25
-#define MB86A16_CNM		0x26
-#define MB86A16_PORT0		0x27
-#define MB86A16_PORT1		0x28
-#define MB86A16_DRCFILT		0x29
-#define MB86A16_AFC		0x2a
-#define MB86A16_AFCEXL		0x2b
-#define MB86A16_AFCEXH		0x2c
-#define MB86A16_DAGC		0x2d
-#define MB86A16_SEQMODE		0x32
-#define MB86A16_S0S1T		0x33
-#define MB86A16_S2S3T		0x34
-#define MB86A16_S4S5T		0x35
-#define MB86A16_CNTMR		0x36
-#define MB86A16_SIG1		0x37
-#define MB86A16_SIG2		0x38
-#define MB86A16_VIMAG		0x39
-#define MB86A16_VISET1		0x3a
-#define MB86A16_VISET2		0x3b
-#define MB86A16_VISET3		0x3c
-#define MB86A16_FAGCS1		0x3d
-#define MB86A16_FAGCS2		0x3e
-#define MB86A16_FAGCS3		0x3f
-#define MB86A16_FAGCS4		0x40
-#define MB86A16_FAGCS5		0x41
-#define MB86A16_FAGCS6		0x42
-#define MB86A16_CRM		0x43
-#define MB86A16_STRM		0x44
-#define MB86A16_DAGCML		0x45
-#define MB86A16_DAGCMH		0x46
-#define MB86A16_QPSKTST		0x49
-#define MB86A16_DISTMON		0x52
-#define MB86A16_VERSION		0x7f
-
-#endif /* __MB86A16_PRIV_H */
diff --git a/drivers/media/dvb/frontends/mb86a20s.c b/drivers/media/dvb/frontends/mb86a20s.c
deleted file mode 100644
index fade566..0000000
--- a/drivers/media/dvb/frontends/mb86a20s.c
+++ /dev/null
@@ -1,701 +0,0 @@
-/*
- *   Fujitu mb86a20s ISDB-T/ISDB-Tsb Module driver
- *
- *   Copyright (C) 2010 Mauro Carvalho Chehab <mchehab@redhat.com>
- *   Copyright (C) 2009-2010 Douglas Landgraf <dougsland@redhat.com>
- *
- *   FIXME: Need to port to DVB v5.2 API
- *
- *   This program is free software; you can redistribute it and/or
- *   modify it under the terms of the GNU General Public License as
- *   published by the Free Software Foundation version 2.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *   General Public License for more details.
- */
-
-#include <linux/kernel.h>
-#include <asm/div64.h>
-
-#include "dvb_frontend.h"
-#include "mb86a20s.h"
-
-static int debug = 1;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)");
-
-#define rc(args...)  do {						\
-	printk(KERN_ERR  "mb86a20s: " args);				\
-} while (0)
-
-#define dprintk(args...)						\
-	do {								\
-		if (debug) {						\
-			printk(KERN_DEBUG "mb86a20s: %s: ", __func__);	\
-			printk(args);					\
-		}							\
-	} while (0)
-
-struct mb86a20s_state {
-	struct i2c_adapter *i2c;
-	const struct mb86a20s_config *config;
-
-	struct dvb_frontend frontend;
-
-	bool need_init;
-};
-
-struct regdata {
-	u8 reg;
-	u8 data;
-};
-
-/*
- * Initialization sequence: Use whatevere default values that PV SBTVD
- * does on its initialisation, obtained via USB snoop
- */
-static struct regdata mb86a20s_init[] = {
-	{ 0x70, 0x0f },
-	{ 0x70, 0xff },
-	{ 0x08, 0x01 },
-	{ 0x09, 0x3e },
-	{ 0x50, 0xd1 }, { 0x51, 0x22 },
-	{ 0x39, 0x01 },
-	{ 0x71, 0x00 },
-	{ 0x28, 0x2a }, { 0x29, 0x00 }, { 0x2a, 0xff }, { 0x2b, 0x80 },
-	{ 0x28, 0x20 }, { 0x29, 0x33 }, { 0x2a, 0xdf }, { 0x2b, 0xa9 },
-	{ 0x28, 0x22 }, { 0x29, 0x00 }, { 0x2a, 0x1f }, { 0x2b, 0xf0 },
-	{ 0x3b, 0x21 },
-	{ 0x3c, 0x3a },
-	{ 0x01, 0x0d },
-	{ 0x04, 0x08 }, { 0x05, 0x05 },
-	{ 0x04, 0x0e }, { 0x05, 0x00 },
-	{ 0x04, 0x0f }, { 0x05, 0x14 },
-	{ 0x04, 0x0b }, { 0x05, 0x8c },
-	{ 0x04, 0x00 }, { 0x05, 0x00 },
-	{ 0x04, 0x01 }, { 0x05, 0x07 },
-	{ 0x04, 0x02 }, { 0x05, 0x0f },
-	{ 0x04, 0x03 }, { 0x05, 0xa0 },
-	{ 0x04, 0x09 }, { 0x05, 0x00 },
-	{ 0x04, 0x0a }, { 0x05, 0xff },
-	{ 0x04, 0x27 }, { 0x05, 0x64 },
-	{ 0x04, 0x28 }, { 0x05, 0x00 },
-	{ 0x04, 0x1e }, { 0x05, 0xff },
-	{ 0x04, 0x29 }, { 0x05, 0x0a },
-	{ 0x04, 0x32 }, { 0x05, 0x0a },
-	{ 0x04, 0x14 }, { 0x05, 0x02 },
-	{ 0x04, 0x04 }, { 0x05, 0x00 },
-	{ 0x04, 0x05 }, { 0x05, 0x22 },
-	{ 0x04, 0x06 }, { 0x05, 0x0e },
-	{ 0x04, 0x07 }, { 0x05, 0xd8 },
-	{ 0x04, 0x12 }, { 0x05, 0x00 },
-	{ 0x04, 0x13 }, { 0x05, 0xff },
-	{ 0x04, 0x15 }, { 0x05, 0x4e },
-	{ 0x04, 0x16 }, { 0x05, 0x20 },
-	{ 0x52, 0x01 },
-	{ 0x50, 0xa7 }, { 0x51, 0xff },
-	{ 0x50, 0xa8 }, { 0x51, 0xff },
-	{ 0x50, 0xa9 }, { 0x51, 0xff },
-	{ 0x50, 0xaa }, { 0x51, 0xff },
-	{ 0x50, 0xab }, { 0x51, 0xff },
-	{ 0x50, 0xac }, { 0x51, 0xff },
-	{ 0x50, 0xad }, { 0x51, 0xff },
-	{ 0x50, 0xae }, { 0x51, 0xff },
-	{ 0x50, 0xaf }, { 0x51, 0xff },
-	{ 0x5e, 0x07 },
-	{ 0x50, 0xdc }, { 0x51, 0x01 },
-	{ 0x50, 0xdd }, { 0x51, 0xf4 },
-	{ 0x50, 0xde }, { 0x51, 0x01 },
-	{ 0x50, 0xdf }, { 0x51, 0xf4 },
-	{ 0x50, 0xe0 }, { 0x51, 0x01 },
-	{ 0x50, 0xe1 }, { 0x51, 0xf4 },
-	{ 0x50, 0xb0 }, { 0x51, 0x07 },
-	{ 0x50, 0xb2 }, { 0x51, 0xff },
-	{ 0x50, 0xb3 }, { 0x51, 0xff },
-	{ 0x50, 0xb4 }, { 0x51, 0xff },
-	{ 0x50, 0xb5 }, { 0x51, 0xff },
-	{ 0x50, 0xb6 }, { 0x51, 0xff },
-	{ 0x50, 0xb7 }, { 0x51, 0xff },
-	{ 0x50, 0x50 }, { 0x51, 0x02 },
-	{ 0x50, 0x51 }, { 0x51, 0x04 },
-	{ 0x45, 0x04 },
-	{ 0x48, 0x04 },
-	{ 0x50, 0xd5 }, { 0x51, 0x01 },		/* Serial */
-	{ 0x50, 0xd6 }, { 0x51, 0x1f },
-	{ 0x50, 0xd2 }, { 0x51, 0x03 },
-	{ 0x50, 0xd7 }, { 0x51, 0x3f },
-	{ 0x28, 0x74 }, { 0x29, 0x00 }, { 0x28, 0x74 }, { 0x29, 0x40 },
-	{ 0x28, 0x46 }, { 0x29, 0x2c }, { 0x28, 0x46 }, { 0x29, 0x0c },
-	{ 0x04, 0x40 }, { 0x05, 0x01 },
-	{ 0x28, 0x00 }, { 0x29, 0x10 },
-	{ 0x28, 0x05 }, { 0x29, 0x02 },
-	{ 0x1c, 0x01 },
-	{ 0x28, 0x06 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x03 },
-	{ 0x28, 0x07 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x0d },
-	{ 0x28, 0x08 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x02 },
-	{ 0x28, 0x09 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x01 },
-	{ 0x28, 0x0a }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x21 },
-	{ 0x28, 0x0b }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x29 },
-	{ 0x28, 0x0c }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x16 },
-	{ 0x28, 0x0d }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x31 },
-	{ 0x28, 0x0e }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x0e },
-	{ 0x28, 0x0f }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x4e },
-	{ 0x28, 0x10 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x46 },
-	{ 0x28, 0x11 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x0f },
-	{ 0x28, 0x12 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x56 },
-	{ 0x28, 0x13 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x35 },
-	{ 0x28, 0x14 }, { 0x29, 0x00 }, { 0x2a, 0x01 }, { 0x2b, 0xbe },
-	{ 0x28, 0x15 }, { 0x29, 0x00 }, { 0x2a, 0x01 }, { 0x2b, 0x84 },
-	{ 0x28, 0x16 }, { 0x29, 0x00 }, { 0x2a, 0x03 }, { 0x2b, 0xee },
-	{ 0x28, 0x17 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x98 },
-	{ 0x28, 0x18 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x9f },
-	{ 0x28, 0x19 }, { 0x29, 0x00 }, { 0x2a, 0x07 }, { 0x2b, 0xb2 },
-	{ 0x28, 0x1a }, { 0x29, 0x00 }, { 0x2a, 0x06 }, { 0x2b, 0xc2 },
-	{ 0x28, 0x1b }, { 0x29, 0x00 }, { 0x2a, 0x07 }, { 0x2b, 0x4a },
-	{ 0x28, 0x1c }, { 0x29, 0x00 }, { 0x2a, 0x01 }, { 0x2b, 0xbc },
-	{ 0x28, 0x1d }, { 0x29, 0x00 }, { 0x2a, 0x04 }, { 0x2b, 0xba },
-	{ 0x28, 0x1e }, { 0x29, 0x00 }, { 0x2a, 0x06 }, { 0x2b, 0x14 },
-	{ 0x50, 0x1e }, { 0x51, 0x5d },
-	{ 0x50, 0x22 }, { 0x51, 0x00 },
-	{ 0x50, 0x23 }, { 0x51, 0xc8 },
-	{ 0x50, 0x24 }, { 0x51, 0x00 },
-	{ 0x50, 0x25 }, { 0x51, 0xf0 },
-	{ 0x50, 0x26 }, { 0x51, 0x00 },
-	{ 0x50, 0x27 }, { 0x51, 0xc3 },
-	{ 0x50, 0x39 }, { 0x51, 0x02 },
-	{ 0x28, 0x6a }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x00 },
-	{ 0xd0, 0x00 },
-};
-
-static struct regdata mb86a20s_reset_reception[] = {
-	{ 0x70, 0xf0 },
-	{ 0x70, 0xff },
-	{ 0x08, 0x01 },
-	{ 0x08, 0x00 },
-};
-
-static int mb86a20s_i2c_writereg(struct mb86a20s_state *state,
-			     u8 i2c_addr, int reg, int data)
-{
-	u8 buf[] = { reg, data };
-	struct i2c_msg msg = {
-		.addr = i2c_addr, .flags = 0, .buf = buf, .len = 2
-	};
-	int rc;
-
-	rc = i2c_transfer(state->i2c, &msg, 1);
-	if (rc != 1) {
-		printk("%s: writereg error (rc == %i, reg == 0x%02x,"
-			 " data == 0x%02x)\n", __func__, rc, reg, data);
-		return rc;
-	}
-
-	return 0;
-}
-
-static int mb86a20s_i2c_writeregdata(struct mb86a20s_state *state,
-				     u8 i2c_addr, struct regdata *rd, int size)
-{
-	int i, rc;
-
-	for (i = 0; i < size; i++) {
-		rc = mb86a20s_i2c_writereg(state, i2c_addr, rd[i].reg,
-					   rd[i].data);
-		if (rc < 0)
-			return rc;
-	}
-	return 0;
-}
-
-static int mb86a20s_i2c_readreg(struct mb86a20s_state *state,
-				u8 i2c_addr, u8 reg)
-{
-	u8 val;
-	int rc;
-	struct i2c_msg msg[] = {
-		{ .addr = i2c_addr, .flags = 0, .buf = &reg, .len = 1 },
-		{ .addr = i2c_addr, .flags = I2C_M_RD, .buf = &val, .len = 1 }
-	};
-
-	rc = i2c_transfer(state->i2c, msg, 2);
-
-	if (rc != 2) {
-		rc("%s: reg=0x%x (error=%d)\n", __func__, reg, rc);
-		return rc;
-	}
-
-	return val;
-}
-
-#define mb86a20s_readreg(state, reg) \
-	mb86a20s_i2c_readreg(state, state->config->demod_address, reg)
-#define mb86a20s_writereg(state, reg, val) \
-	mb86a20s_i2c_writereg(state, state->config->demod_address, reg, val)
-#define mb86a20s_writeregdata(state, regdata) \
-	mb86a20s_i2c_writeregdata(state, state->config->demod_address, \
-	regdata, ARRAY_SIZE(regdata))
-
-static int mb86a20s_initfe(struct dvb_frontend *fe)
-{
-	struct mb86a20s_state *state = fe->demodulator_priv;
-	int rc;
-	u8  regD5 = 1;
-
-	dprintk("\n");
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0);
-
-	/* Initialize the frontend */
-	rc = mb86a20s_writeregdata(state, mb86a20s_init);
-	if (rc < 0)
-		goto err;
-
-	if (!state->config->is_serial) {
-		regD5 &= ~1;
-
-		rc = mb86a20s_writereg(state, 0x50, 0xd5);
-		if (rc < 0)
-			goto err;
-		rc = mb86a20s_writereg(state, 0x51, regD5);
-		if (rc < 0)
-			goto err;
-	}
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-
-err:
-	if (rc < 0) {
-		state->need_init = true;
-		printk(KERN_INFO "mb86a20s: Init failed. Will try again later\n");
-	} else {
-		state->need_init = false;
-		dprintk("Initialization succeeded.\n");
-	}
-	return rc;
-}
-
-static int mb86a20s_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
-{
-	struct mb86a20s_state *state = fe->demodulator_priv;
-	unsigned rf_max, rf_min, rf;
-	u8	 val;
-
-	dprintk("\n");
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0);
-
-	/* Does a binary search to get RF strength */
-	rf_max = 0xfff;
-	rf_min = 0;
-	do {
-		rf = (rf_max + rf_min) / 2;
-		mb86a20s_writereg(state, 0x04, 0x1f);
-		mb86a20s_writereg(state, 0x05, rf >> 8);
-		mb86a20s_writereg(state, 0x04, 0x20);
-		mb86a20s_writereg(state, 0x04, rf);
-
-		val = mb86a20s_readreg(state, 0x02);
-		if (val & 0x08)
-			rf_min = (rf_max + rf_min) / 2;
-		else
-			rf_max = (rf_max + rf_min) / 2;
-		if (rf_max - rf_min < 4) {
-			*strength = (((rf_max + rf_min) / 2) * 65535) / 4095;
-			break;
-		}
-	} while (1);
-
-	dprintk("signal strength = %d\n", *strength);
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-
-	return 0;
-}
-
-static int mb86a20s_read_status(struct dvb_frontend *fe, fe_status_t *status)
-{
-	struct mb86a20s_state *state = fe->demodulator_priv;
-	u8 val;
-
-	dprintk("\n");
-	*status = 0;
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0);
-	val = mb86a20s_readreg(state, 0x0a) & 0xf;
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-
-	if (val >= 2)
-		*status |= FE_HAS_SIGNAL;
-
-	if (val >= 4)
-		*status |= FE_HAS_CARRIER;
-
-	if (val >= 5)
-		*status |= FE_HAS_VITERBI;
-
-	if (val >= 7)
-		*status |= FE_HAS_SYNC;
-
-	if (val >= 8)				/* Maybe 9? */
-		*status |= FE_HAS_LOCK;
-
-	dprintk("val = %d, status = 0x%02x\n", val, *status);
-
-	return 0;
-}
-
-static int mb86a20s_set_frontend(struct dvb_frontend *fe)
-{
-	struct mb86a20s_state *state = fe->demodulator_priv;
-	int rc;
-#if 0
-	/*
-	 * FIXME: Properly implement the set frontend properties
-	 */
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-#endif
-
-	dprintk("\n");
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	dprintk("Calling tuner set parameters\n");
-	fe->ops.tuner_ops.set_params(fe);
-
-	/*
-	 * Make it more reliable: if, for some reason, the initial
-	 * device initialization doesn't happen, initialize it when
-	 * a SBTVD parameters are adjusted.
-	 *
-	 * Unfortunately, due to a hard to track bug at tda829x/tda18271,
-	 * the agc callback logic is not called during DVB attach time,
-	 * causing mb86a20s to not be initialized with Kworld SBTVD.
-	 * So, this hack is needed, in order to make Kworld SBTVD to work.
-	 */
-	if (state->need_init)
-		mb86a20s_initfe(fe);
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0);
-	rc = mb86a20s_writeregdata(state, mb86a20s_reset_reception);
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-
-	return rc;
-}
-
-static int mb86a20s_get_modulation(struct mb86a20s_state *state,
-				   unsigned layer)
-{
-	int rc;
-	static unsigned char reg[] = {
-		[0] = 0x86,	/* Layer A */
-		[1] = 0x8a,	/* Layer B */
-		[2] = 0x8e,	/* Layer C */
-	};
-
-	if (layer >= ARRAY_SIZE(reg))
-		return -EINVAL;
-	rc = mb86a20s_writereg(state, 0x6d, reg[layer]);
-	if (rc < 0)
-		return rc;
-	rc = mb86a20s_readreg(state, 0x6e);
-	if (rc < 0)
-		return rc;
-	switch ((rc & 0x70) >> 4) {
-	case 0:
-		return DQPSK;
-	case 1:
-		return QPSK;
-	case 2:
-		return QAM_16;
-	case 3:
-		return QAM_64;
-	default:
-		return QAM_AUTO;
-	}
-}
-
-static int mb86a20s_get_fec(struct mb86a20s_state *state,
-			    unsigned layer)
-{
-	int rc;
-
-	static unsigned char reg[] = {
-		[0] = 0x87,	/* Layer A */
-		[1] = 0x8b,	/* Layer B */
-		[2] = 0x8f,	/* Layer C */
-	};
-
-	if (layer >= ARRAY_SIZE(reg))
-		return -EINVAL;
-	rc = mb86a20s_writereg(state, 0x6d, reg[layer]);
-	if (rc < 0)
-		return rc;
-	rc = mb86a20s_readreg(state, 0x6e);
-	if (rc < 0)
-		return rc;
-	switch (rc) {
-	case 0:
-		return FEC_1_2;
-	case 1:
-		return FEC_2_3;
-	case 2:
-		return FEC_3_4;
-	case 3:
-		return FEC_5_6;
-	case 4:
-		return FEC_7_8;
-	default:
-		return FEC_AUTO;
-	}
-}
-
-static int mb86a20s_get_interleaving(struct mb86a20s_state *state,
-				     unsigned layer)
-{
-	int rc;
-
-	static unsigned char reg[] = {
-		[0] = 0x88,	/* Layer A */
-		[1] = 0x8c,	/* Layer B */
-		[2] = 0x90,	/* Layer C */
-	};
-
-	if (layer >= ARRAY_SIZE(reg))
-		return -EINVAL;
-	rc = mb86a20s_writereg(state, 0x6d, reg[layer]);
-	if (rc < 0)
-		return rc;
-	rc = mb86a20s_readreg(state, 0x6e);
-	if (rc < 0)
-		return rc;
-	if (rc > 3)
-		return -EINVAL;	/* Not used */
-	return rc;
-}
-
-static int mb86a20s_get_segment_count(struct mb86a20s_state *state,
-				      unsigned layer)
-{
-	int rc, count;
-
-	static unsigned char reg[] = {
-		[0] = 0x89,	/* Layer A */
-		[1] = 0x8d,	/* Layer B */
-		[2] = 0x91,	/* Layer C */
-	};
-
-	if (layer >= ARRAY_SIZE(reg))
-		return -EINVAL;
-	rc = mb86a20s_writereg(state, 0x6d, reg[layer]);
-	if (rc < 0)
-		return rc;
-	rc = mb86a20s_readreg(state, 0x6e);
-	if (rc < 0)
-		return rc;
-	count = (rc >> 4) & 0x0f;
-
-	return count;
-}
-
-static int mb86a20s_get_frontend(struct dvb_frontend *fe)
-{
-	struct mb86a20s_state *state = fe->demodulator_priv;
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	int i, rc;
-
-	/* Fixed parameters */
-	p->delivery_system = SYS_ISDBT;
-	p->bandwidth_hz = 6000000;
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0);
-
-	/* Check for partial reception */
-	rc = mb86a20s_writereg(state, 0x6d, 0x85);
-	if (rc >= 0)
-		rc = mb86a20s_readreg(state, 0x6e);
-	if (rc >= 0)
-		p->isdbt_partial_reception = (rc & 0x10) ? 1 : 0;
-
-	/* Get per-layer data */
-	p->isdbt_layer_enabled = 0;
-	for (i = 0; i < 3; i++) {
-		rc = mb86a20s_get_segment_count(state, i);
-			if (rc >= 0 && rc < 14)
-				p->layer[i].segment_count = rc;
-		if (rc == 0x0f)
-			continue;
-		p->isdbt_layer_enabled |= 1 << i;
-		rc = mb86a20s_get_modulation(state, i);
-			if (rc >= 0)
-				p->layer[i].modulation = rc;
-		rc = mb86a20s_get_fec(state, i);
-			if (rc >= 0)
-				p->layer[i].fec = rc;
-		rc = mb86a20s_get_interleaving(state, i);
-			if (rc >= 0)
-				p->layer[i].interleaving = rc;
-	}
-
-	p->isdbt_sb_mode = 0;
-	rc = mb86a20s_writereg(state, 0x6d, 0x84);
-	if ((rc >= 0) && ((rc & 0x60) == 0x20)) {
-		p->isdbt_sb_mode = 1;
-		/* At least, one segment should exist */
-		if (!p->isdbt_sb_segment_count)
-			p->isdbt_sb_segment_count = 1;
-	} else
-		p->isdbt_sb_segment_count = 0;
-
-	/* Get transmission mode and guard interval */
-	p->transmission_mode = TRANSMISSION_MODE_AUTO;
-	p->guard_interval = GUARD_INTERVAL_AUTO;
-	rc = mb86a20s_readreg(state, 0x07);
-	if (rc >= 0) {
-		if ((rc & 0x60) == 0x20) {
-			switch (rc & 0x0c >> 2) {
-			case 0:
-				p->transmission_mode = TRANSMISSION_MODE_2K;
-				break;
-			case 1:
-				p->transmission_mode = TRANSMISSION_MODE_4K;
-				break;
-			case 2:
-				p->transmission_mode = TRANSMISSION_MODE_8K;
-				break;
-			}
-		}
-		if (!(rc & 0x10)) {
-			switch (rc & 0x3) {
-			case 0:
-				p->guard_interval = GUARD_INTERVAL_1_4;
-				break;
-			case 1:
-				p->guard_interval = GUARD_INTERVAL_1_8;
-				break;
-			case 2:
-				p->guard_interval = GUARD_INTERVAL_1_16;
-				break;
-			}
-		}
-	}
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-
-	return 0;
-}
-
-static int mb86a20s_tune(struct dvb_frontend *fe,
-			bool re_tune,
-			unsigned int mode_flags,
-			unsigned int *delay,
-			fe_status_t *status)
-{
-	int rc = 0;
-
-	dprintk("\n");
-
-	if (re_tune)
-		rc = mb86a20s_set_frontend(fe);
-
-	if (!(mode_flags & FE_TUNE_MODE_ONESHOT))
-		mb86a20s_read_status(fe, status);
-
-	return rc;
-}
-
-static void mb86a20s_release(struct dvb_frontend *fe)
-{
-	struct mb86a20s_state *state = fe->demodulator_priv;
-
-	dprintk("\n");
-
-	kfree(state);
-}
-
-static struct dvb_frontend_ops mb86a20s_ops;
-
-struct dvb_frontend *mb86a20s_attach(const struct mb86a20s_config *config,
-				    struct i2c_adapter *i2c)
-{
-	u8	rev;
-
-	/* allocate memory for the internal state */
-	struct mb86a20s_state *state =
-		kzalloc(sizeof(struct mb86a20s_state), GFP_KERNEL);
-
-	dprintk("\n");
-	if (state == NULL) {
-		rc("Unable to kzalloc\n");
-		goto error;
-	}
-
-	/* setup the state */
-	state->config = config;
-	state->i2c = i2c;
-
-	/* create dvb_frontend */
-	memcpy(&state->frontend.ops, &mb86a20s_ops,
-		sizeof(struct dvb_frontend_ops));
-	state->frontend.demodulator_priv = state;
-
-	/* Check if it is a mb86a20s frontend */
-	rev = mb86a20s_readreg(state, 0);
-
-	if (rev == 0x13) {
-		printk(KERN_INFO "Detected a Fujitsu mb86a20s frontend\n");
-	} else {
-		printk(KERN_ERR "Frontend revision %d is unknown - aborting.\n",
-		       rev);
-		goto error;
-	}
-
-	return &state->frontend;
-
-error:
-	kfree(state);
-	return NULL;
-}
-EXPORT_SYMBOL(mb86a20s_attach);
-
-static struct dvb_frontend_ops mb86a20s_ops = {
-	.delsys = { SYS_ISDBT },
-	/* Use dib8000 values per default */
-	.info = {
-		.name = "Fujitsu mb86A20s",
-		.caps = FE_CAN_INVERSION_AUTO | FE_CAN_RECOVER |
-			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_FEC_AUTO |
-			FE_CAN_QPSK     | FE_CAN_QAM_16  | FE_CAN_QAM_64 |
-			FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_QAM_AUTO |
-			FE_CAN_GUARD_INTERVAL_AUTO    | FE_CAN_HIERARCHY_AUTO,
-		/* Actually, those values depend on the used tuner */
-		.frequency_min = 45000000,
-		.frequency_max = 864000000,
-		.frequency_stepsize = 62500,
-	},
-
-	.release = mb86a20s_release,
-
-	.init = mb86a20s_initfe,
-	.set_frontend = mb86a20s_set_frontend,
-	.get_frontend = mb86a20s_get_frontend,
-	.read_status = mb86a20s_read_status,
-	.read_signal_strength = mb86a20s_read_signal_strength,
-	.tune = mb86a20s_tune,
-};
-
-MODULE_DESCRIPTION("DVB Frontend module for Fujitsu mb86A20s hardware");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/mb86a20s.h b/drivers/media/dvb/frontends/mb86a20s.h
deleted file mode 100644
index bf22e77..0000000
--- a/drivers/media/dvb/frontends/mb86a20s.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- *   Fujitsu mb86a20s driver
- *
- *   Copyright (C) 2010 Mauro Carvalho Chehab <mchehab@redhat.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 version 2.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *   General Public License for more details.
- */
-
-#ifndef MB86A20S_H
-#define MB86A20S_H
-
-#include <linux/dvb/frontend.h>
-
-/**
- * struct mb86a20s_config - Define the per-device attributes of the frontend
- *
- * @demod_address:	the demodulator's i2c address
- */
-
-struct mb86a20s_config {
-	u8 demod_address;
-	bool is_serial;
-};
-
-#if defined(CONFIG_DVB_MB86A20S) || (defined(CONFIG_DVB_MB86A20S_MODULE) \
-	&& defined(MODULE))
-extern struct dvb_frontend *mb86a20s_attach(const struct mb86a20s_config *config,
-					   struct i2c_adapter *i2c);
-extern struct i2c_adapter *mb86a20s_get_tuner_i2c_adapter(struct dvb_frontend *);
-#else
-static inline struct dvb_frontend *mb86a20s_attach(
-	const struct mb86a20s_config *config, struct i2c_adapter *i2c)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-static struct i2c_adapter *
-	mb86a20s_get_tuner_i2c_adapter(struct dvb_frontend *fe)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif
-
-#endif /* MB86A20S */
diff --git a/drivers/media/dvb/frontends/mt312.c b/drivers/media/dvb/frontends/mt312.c
deleted file mode 100644
index e20bf13..0000000
--- a/drivers/media/dvb/frontends/mt312.c
+++ /dev/null
@@ -1,839 +0,0 @@
-/*
-    Driver for Zarlink VP310/MT312/ZL10313 Satellite Channel Decoder
-
-    Copyright (C) 2003 Andreas Oberritter <obi@linuxtv.org>
-    Copyright (C) 2008 Matthias Schwarzott <zzam@gentoo.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.
-
-    References:
-    http://products.zarlink.com/product_profiles/MT312.htm
-    http://products.zarlink.com/product_profiles/SL1935.htm
-*/
-
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-
-#include "dvb_frontend.h"
-#include "mt312_priv.h"
-#include "mt312.h"
-
-
-struct mt312_state {
-	struct i2c_adapter *i2c;
-	/* configuration settings */
-	const struct mt312_config *config;
-	struct dvb_frontend frontend;
-
-	u8 id;
-	unsigned long xtal;
-	u8 freq_mult;
-};
-
-static int debug;
-#define dprintk(args...) \
-	do { \
-		if (debug) \
-			printk(KERN_DEBUG "mt312: " args); \
-	} while (0)
-
-#define MT312_PLL_CLK		10000000UL	/* 10 MHz */
-#define MT312_PLL_CLK_10_111	10111000UL	/* 10.111 MHz */
-
-static int mt312_read(struct mt312_state *state, const enum mt312_reg_addr reg,
-		      u8 *buf, const size_t count)
-{
-	int ret;
-	struct i2c_msg msg[2];
-	u8 regbuf[1] = { reg };
-
-	msg[0].addr = state->config->demod_address;
-	msg[0].flags = 0;
-	msg[0].buf = regbuf;
-	msg[0].len = 1;
-	msg[1].addr = state->config->demod_address;
-	msg[1].flags = I2C_M_RD;
-	msg[1].buf = buf;
-	msg[1].len = count;
-
-	ret = i2c_transfer(state->i2c, msg, 2);
-
-	if (ret != 2) {
-		printk(KERN_DEBUG "%s: ret == %d\n", __func__, ret);
-		return -EREMOTEIO;
-	}
-
-	if (debug) {
-		int i;
-		dprintk("R(%d):", reg & 0x7f);
-		for (i = 0; i < count; i++)
-			printk(KERN_CONT " %02x", buf[i]);
-		printk("\n");
-	}
-
-	return 0;
-}
-
-static int mt312_write(struct mt312_state *state, const enum mt312_reg_addr reg,
-		       const u8 *src, const size_t count)
-{
-	int ret;
-	u8 buf[count + 1];
-	struct i2c_msg msg;
-
-	if (debug) {
-		int i;
-		dprintk("W(%d):", reg & 0x7f);
-		for (i = 0; i < count; i++)
-			printk(KERN_CONT " %02x", src[i]);
-		printk("\n");
-	}
-
-	buf[0] = reg;
-	memcpy(&buf[1], src, count);
-
-	msg.addr = state->config->demod_address;
-	msg.flags = 0;
-	msg.buf = buf;
-	msg.len = count + 1;
-
-	ret = i2c_transfer(state->i2c, &msg, 1);
-
-	if (ret != 1) {
-		dprintk("%s: ret == %d\n", __func__, ret);
-		return -EREMOTEIO;
-	}
-
-	return 0;
-}
-
-static inline int mt312_readreg(struct mt312_state *state,
-				const enum mt312_reg_addr reg, u8 *val)
-{
-	return mt312_read(state, reg, val, 1);
-}
-
-static inline int mt312_writereg(struct mt312_state *state,
-				 const enum mt312_reg_addr reg, const u8 val)
-{
-	return mt312_write(state, reg, &val, 1);
-}
-
-static inline u32 mt312_div(u32 a, u32 b)
-{
-	return (a + (b / 2)) / b;
-}
-
-static int mt312_reset(struct mt312_state *state, const u8 full)
-{
-	return mt312_writereg(state, RESET, full ? 0x80 : 0x40);
-}
-
-static int mt312_get_inversion(struct mt312_state *state,
-			       fe_spectral_inversion_t *i)
-{
-	int ret;
-	u8 vit_mode;
-
-	ret = mt312_readreg(state, VIT_MODE, &vit_mode);
-	if (ret < 0)
-		return ret;
-
-	if (vit_mode & 0x80)	/* auto inversion was used */
-		*i = (vit_mode & 0x40) ? INVERSION_ON : INVERSION_OFF;
-
-	return 0;
-}
-
-static int mt312_get_symbol_rate(struct mt312_state *state, u32 *sr)
-{
-	int ret;
-	u8 sym_rate_h;
-	u8 dec_ratio;
-	u16 sym_rat_op;
-	u16 monitor;
-	u8 buf[2];
-
-	ret = mt312_readreg(state, SYM_RATE_H, &sym_rate_h);
-	if (ret < 0)
-		return ret;
-
-	if (sym_rate_h & 0x80) {
-		/* symbol rate search was used */
-		ret = mt312_writereg(state, MON_CTRL, 0x03);
-		if (ret < 0)
-			return ret;
-
-		ret = mt312_read(state, MONITOR_H, buf, sizeof(buf));
-		if (ret < 0)
-			return ret;
-
-		monitor = (buf[0] << 8) | buf[1];
-
-		dprintk("sr(auto) = %u\n",
-		       mt312_div(monitor * 15625, 4));
-	} else {
-		ret = mt312_writereg(state, MON_CTRL, 0x05);
-		if (ret < 0)
-			return ret;
-
-		ret = mt312_read(state, MONITOR_H, buf, sizeof(buf));
-		if (ret < 0)
-			return ret;
-
-		dec_ratio = ((buf[0] >> 5) & 0x07) * 32;
-
-		ret = mt312_read(state, SYM_RAT_OP_H, buf, sizeof(buf));
-		if (ret < 0)
-			return ret;
-
-		sym_rat_op = (buf[0] << 8) | buf[1];
-
-		dprintk("sym_rat_op=%d dec_ratio=%d\n",
-		       sym_rat_op, dec_ratio);
-		dprintk("*sr(manual) = %lu\n",
-		       (((state->xtal * 8192) / (sym_rat_op + 8192)) *
-			2) - dec_ratio);
-	}
-
-	return 0;
-}
-
-static int mt312_get_code_rate(struct mt312_state *state, fe_code_rate_t *cr)
-{
-	const fe_code_rate_t fec_tab[8] =
-	    { FEC_1_2, FEC_2_3, FEC_3_4, FEC_5_6, FEC_6_7, FEC_7_8,
-		FEC_AUTO, FEC_AUTO };
-
-	int ret;
-	u8 fec_status;
-
-	ret = mt312_readreg(state, FEC_STATUS, &fec_status);
-	if (ret < 0)
-		return ret;
-
-	*cr = fec_tab[(fec_status >> 4) & 0x07];
-
-	return 0;
-}
-
-static int mt312_initfe(struct dvb_frontend *fe)
-{
-	struct mt312_state *state = fe->demodulator_priv;
-	int ret;
-	u8 buf[2];
-
-	/* wake up */
-	ret = mt312_writereg(state, CONFIG,
-			(state->freq_mult == 6 ? 0x88 : 0x8c));
-	if (ret < 0)
-		return ret;
-
-	/* wait at least 150 usec */
-	udelay(150);
-
-	/* full reset */
-	ret = mt312_reset(state, 1);
-	if (ret < 0)
-		return ret;
-
-/* Per datasheet, write correct values. 09/28/03 ACCJr.
- * If we don't do this, we won't get FE_HAS_VITERBI in the VP310. */
-	{
-		u8 buf_def[8] = { 0x14, 0x12, 0x03, 0x02,
-				  0x01, 0x00, 0x00, 0x00 };
-
-		ret = mt312_write(state, VIT_SETUP, buf_def, sizeof(buf_def));
-		if (ret < 0)
-			return ret;
-	}
-
-	switch (state->id) {
-	case ID_ZL10313:
-		/* enable ADC */
-		ret = mt312_writereg(state, GPP_CTRL, 0x80);
-		if (ret < 0)
-			return ret;
-
-		/* configure ZL10313 for optimal ADC performance */
-		buf[0] = 0x80;
-		buf[1] = 0xB0;
-		ret = mt312_write(state, HW_CTRL, buf, 2);
-		if (ret < 0)
-			return ret;
-
-		/* enable MPEG output and ADCs */
-		ret = mt312_writereg(state, HW_CTRL, 0x00);
-		if (ret < 0)
-			return ret;
-
-		ret = mt312_writereg(state, MPEG_CTRL, 0x00);
-		if (ret < 0)
-			return ret;
-
-		break;
-	}
-
-	/* SYS_CLK */
-	buf[0] = mt312_div(state->xtal * state->freq_mult * 2, 1000000);
-
-	/* DISEQC_RATIO */
-	buf[1] = mt312_div(state->xtal, 22000 * 4);
-
-	ret = mt312_write(state, SYS_CLK, buf, sizeof(buf));
-	if (ret < 0)
-		return ret;
-
-	ret = mt312_writereg(state, SNR_THS_HIGH, 0x32);
-	if (ret < 0)
-		return ret;
-
-	/* different MOCLK polarity */
-	switch (state->id) {
-	case ID_ZL10313:
-		buf[0] = 0x33;
-		break;
-	default:
-		buf[0] = 0x53;
-		break;
-	}
-
-	ret = mt312_writereg(state, OP_CTRL, buf[0]);
-	if (ret < 0)
-		return ret;
-
-	/* TS_SW_LIM */
-	buf[0] = 0x8c;
-	buf[1] = 0x98;
-
-	ret = mt312_write(state, TS_SW_LIM_L, buf, sizeof(buf));
-	if (ret < 0)
-		return ret;
-
-	ret = mt312_writereg(state, CS_SW_LIM, 0x69);
-	if (ret < 0)
-		return ret;
-
-	return 0;
-}
-
-static int mt312_send_master_cmd(struct dvb_frontend *fe,
-				 struct dvb_diseqc_master_cmd *c)
-{
-	struct mt312_state *state = fe->demodulator_priv;
-	int ret;
-	u8 diseqc_mode;
-
-	if ((c->msg_len == 0) || (c->msg_len > sizeof(c->msg)))
-		return -EINVAL;
-
-	ret = mt312_readreg(state, DISEQC_MODE, &diseqc_mode);
-	if (ret < 0)
-		return ret;
-
-	ret = mt312_write(state, (0x80 | DISEQC_INSTR), c->msg, c->msg_len);
-	if (ret < 0)
-		return ret;
-
-	ret = mt312_writereg(state, DISEQC_MODE,
-			     (diseqc_mode & 0x40) | ((c->msg_len - 1) << 3)
-			     | 0x04);
-	if (ret < 0)
-		return ret;
-
-	/* is there a better way to wait for message to be transmitted */
-	msleep(100);
-
-	/* set DISEQC_MODE[2:0] to zero if a return message is expected */
-	if (c->msg[0] & 0x02) {
-		ret = mt312_writereg(state, DISEQC_MODE, (diseqc_mode & 0x40));
-		if (ret < 0)
-			return ret;
-	}
-
-	return 0;
-}
-
-static int mt312_send_burst(struct dvb_frontend *fe, const fe_sec_mini_cmd_t c)
-{
-	struct mt312_state *state = fe->demodulator_priv;
-	const u8 mini_tab[2] = { 0x02, 0x03 };
-
-	int ret;
-	u8 diseqc_mode;
-
-	if (c > SEC_MINI_B)
-		return -EINVAL;
-
-	ret = mt312_readreg(state, DISEQC_MODE, &diseqc_mode);
-	if (ret < 0)
-		return ret;
-
-	ret = mt312_writereg(state, DISEQC_MODE,
-			     (diseqc_mode & 0x40) | mini_tab[c]);
-	if (ret < 0)
-		return ret;
-
-	return 0;
-}
-
-static int mt312_set_tone(struct dvb_frontend *fe, const fe_sec_tone_mode_t t)
-{
-	struct mt312_state *state = fe->demodulator_priv;
-	const u8 tone_tab[2] = { 0x01, 0x00 };
-
-	int ret;
-	u8 diseqc_mode;
-
-	if (t > SEC_TONE_OFF)
-		return -EINVAL;
-
-	ret = mt312_readreg(state, DISEQC_MODE, &diseqc_mode);
-	if (ret < 0)
-		return ret;
-
-	ret = mt312_writereg(state, DISEQC_MODE,
-			     (diseqc_mode & 0x40) | tone_tab[t]);
-	if (ret < 0)
-		return ret;
-
-	return 0;
-}
-
-static int mt312_set_voltage(struct dvb_frontend *fe, const fe_sec_voltage_t v)
-{
-	struct mt312_state *state = fe->demodulator_priv;
-	const u8 volt_tab[3] = { 0x00, 0x40, 0x00 };
-	u8 val;
-
-	if (v > SEC_VOLTAGE_OFF)
-		return -EINVAL;
-
-	val = volt_tab[v];
-	if (state->config->voltage_inverted)
-		val ^= 0x40;
-
-	return mt312_writereg(state, DISEQC_MODE, val);
-}
-
-static int mt312_read_status(struct dvb_frontend *fe, fe_status_t *s)
-{
-	struct mt312_state *state = fe->demodulator_priv;
-	int ret;
-	u8 status[3];
-
-	*s = 0;
-
-	ret = mt312_read(state, QPSK_STAT_H, status, sizeof(status));
-	if (ret < 0)
-		return ret;
-
-	dprintk("QPSK_STAT_H: 0x%02x, QPSK_STAT_L: 0x%02x,"
-		" FEC_STATUS: 0x%02x\n", status[0], status[1], status[2]);
-
-	if (status[0] & 0xc0)
-		*s |= FE_HAS_SIGNAL;	/* signal noise ratio */
-	if (status[0] & 0x04)
-		*s |= FE_HAS_CARRIER;	/* qpsk carrier lock */
-	if (status[2] & 0x02)
-		*s |= FE_HAS_VITERBI;	/* viterbi lock */
-	if (status[2] & 0x04)
-		*s |= FE_HAS_SYNC;	/* byte align lock */
-	if (status[0] & 0x01)
-		*s |= FE_HAS_LOCK;	/* qpsk lock */
-
-	return 0;
-}
-
-static int mt312_read_ber(struct dvb_frontend *fe, u32 *ber)
-{
-	struct mt312_state *state = fe->demodulator_priv;
-	int ret;
-	u8 buf[3];
-
-	ret = mt312_read(state, RS_BERCNT_H, buf, 3);
-	if (ret < 0)
-		return ret;
-
-	*ber = ((buf[0] << 16) | (buf[1] << 8) | buf[2]) * 64;
-
-	return 0;
-}
-
-static int mt312_read_signal_strength(struct dvb_frontend *fe,
-				      u16 *signal_strength)
-{
-	struct mt312_state *state = fe->demodulator_priv;
-	int ret;
-	u8 buf[3];
-	u16 agc;
-	s16 err_db;
-
-	ret = mt312_read(state, AGC_H, buf, sizeof(buf));
-	if (ret < 0)
-		return ret;
-
-	agc = (buf[0] << 6) | (buf[1] >> 2);
-	err_db = (s16) (((buf[1] & 0x03) << 14) | buf[2] << 6) >> 6;
-
-	*signal_strength = agc;
-
-	dprintk("agc=%08x err_db=%hd\n", agc, err_db);
-
-	return 0;
-}
-
-static int mt312_read_snr(struct dvb_frontend *fe, u16 *snr)
-{
-	struct mt312_state *state = fe->demodulator_priv;
-	int ret;
-	u8 buf[2];
-
-	ret = mt312_read(state, M_SNR_H, buf, sizeof(buf));
-	if (ret < 0)
-		return ret;
-
-	*snr = 0xFFFF - ((((buf[0] & 0x7f) << 8) | buf[1]) << 1);
-
-	return 0;
-}
-
-static int mt312_read_ucblocks(struct dvb_frontend *fe, u32 *ubc)
-{
-	struct mt312_state *state = fe->demodulator_priv;
-	int ret;
-	u8 buf[2];
-
-	ret = mt312_read(state, RS_UBC_H, buf, sizeof(buf));
-	if (ret < 0)
-		return ret;
-
-	*ubc = (buf[0] << 8) | buf[1];
-
-	return 0;
-}
-
-static int mt312_set_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct mt312_state *state = fe->demodulator_priv;
-	int ret;
-	u8 buf[5], config_val;
-	u16 sr;
-
-	const u8 fec_tab[10] =
-	    { 0x00, 0x01, 0x02, 0x04, 0x3f, 0x08, 0x10, 0x20, 0x3f, 0x3f };
-	const u8 inv_tab[3] = { 0x00, 0x40, 0x80 };
-
-	dprintk("%s: Freq %d\n", __func__, p->frequency);
-
-	if ((p->frequency < fe->ops.info.frequency_min)
-	    || (p->frequency > fe->ops.info.frequency_max))
-		return -EINVAL;
-
-	if ((p->inversion < INVERSION_OFF)
-	    || (p->inversion > INVERSION_ON))
-		return -EINVAL;
-
-	if ((p->symbol_rate < fe->ops.info.symbol_rate_min)
-	    || (p->symbol_rate > fe->ops.info.symbol_rate_max))
-		return -EINVAL;
-
-	if ((p->fec_inner < FEC_NONE)
-	    || (p->fec_inner > FEC_AUTO))
-		return -EINVAL;
-
-	if ((p->fec_inner == FEC_4_5)
-	    || (p->fec_inner == FEC_8_9))
-		return -EINVAL;
-
-	switch (state->id) {
-	case ID_VP310:
-	/* For now we will do this only for the VP310.
-	 * It should be better for the mt312 as well,
-	 * but tuning will be slower. ACCJr 09/29/03
-	 */
-		ret = mt312_readreg(state, CONFIG, &config_val);
-		if (ret < 0)
-			return ret;
-		if (p->symbol_rate >= 30000000) {
-			/* Note that 30MS/s should use 90MHz */
-			if (state->freq_mult == 6) {
-				/* We are running 60MHz */
-				state->freq_mult = 9;
-				ret = mt312_initfe(fe);
-				if (ret < 0)
-					return ret;
-			}
-		} else {
-			if (state->freq_mult == 9) {
-				/* We are running 90MHz */
-				state->freq_mult = 6;
-				ret = mt312_initfe(fe);
-				if (ret < 0)
-					return ret;
-			}
-		}
-		break;
-
-	case ID_MT312:
-	case ID_ZL10313:
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	if (fe->ops.tuner_ops.set_params) {
-		fe->ops.tuner_ops.set_params(fe);
-		if (fe->ops.i2c_gate_ctrl)
-			fe->ops.i2c_gate_ctrl(fe, 0);
-	}
-
-	/* sr = (u16)(sr * 256.0 / 1000000.0) */
-	sr = mt312_div(p->symbol_rate * 4, 15625);
-
-	/* SYM_RATE */
-	buf[0] = (sr >> 8) & 0x3f;
-	buf[1] = (sr >> 0) & 0xff;
-
-	/* VIT_MODE */
-	buf[2] = inv_tab[p->inversion] | fec_tab[p->fec_inner];
-
-	/* QPSK_CTRL */
-	buf[3] = 0x40;		/* swap I and Q before QPSK demodulation */
-
-	if (p->symbol_rate < 10000000)
-		buf[3] |= 0x04;	/* use afc mode */
-
-	/* GO */
-	buf[4] = 0x01;
-
-	ret = mt312_write(state, SYM_RATE_H, buf, sizeof(buf));
-	if (ret < 0)
-		return ret;
-
-	mt312_reset(state, 0);
-
-	return 0;
-}
-
-static int mt312_get_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct mt312_state *state = fe->demodulator_priv;
-	int ret;
-
-	ret = mt312_get_inversion(state, &p->inversion);
-	if (ret < 0)
-		return ret;
-
-	ret = mt312_get_symbol_rate(state, &p->symbol_rate);
-	if (ret < 0)
-		return ret;
-
-	ret = mt312_get_code_rate(state, &p->fec_inner);
-	if (ret < 0)
-		return ret;
-
-	return 0;
-}
-
-static int mt312_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
-{
-	struct mt312_state *state = fe->demodulator_priv;
-
-	u8 val = 0x00;
-	int ret;
-
-	switch (state->id) {
-	case ID_ZL10313:
-		ret = mt312_readreg(state, GPP_CTRL, &val);
-		if (ret < 0)
-			goto error;
-
-		/* preserve this bit to not accidentally shutdown ADC */
-		val &= 0x80;
-		break;
-	}
-
-	if (enable)
-		val |= 0x40;
-	else
-		val &= ~0x40;
-
-	ret = mt312_writereg(state, GPP_CTRL, val);
-
-error:
-	return ret;
-}
-
-static int mt312_sleep(struct dvb_frontend *fe)
-{
-	struct mt312_state *state = fe->demodulator_priv;
-	int ret;
-	u8 config;
-
-	/* reset all registers to defaults */
-	ret = mt312_reset(state, 1);
-	if (ret < 0)
-		return ret;
-
-	if (state->id == ID_ZL10313) {
-		/* reset ADC */
-		ret = mt312_writereg(state, GPP_CTRL, 0x00);
-		if (ret < 0)
-			return ret;
-
-		/* full shutdown of ADCs, mpeg bus tristated */
-		ret = mt312_writereg(state, HW_CTRL, 0x0d);
-		if (ret < 0)
-			return ret;
-	}
-
-	ret = mt312_readreg(state, CONFIG, &config);
-	if (ret < 0)
-		return ret;
-
-	/* enter standby */
-	ret = mt312_writereg(state, CONFIG, config & 0x7f);
-	if (ret < 0)
-		return ret;
-
-	return 0;
-}
-
-static int mt312_get_tune_settings(struct dvb_frontend *fe,
-		struct dvb_frontend_tune_settings *fesettings)
-{
-	fesettings->min_delay_ms = 50;
-	fesettings->step_size = 0;
-	fesettings->max_drift = 0;
-	return 0;
-}
-
-static void mt312_release(struct dvb_frontend *fe)
-{
-	struct mt312_state *state = fe->demodulator_priv;
-	kfree(state);
-}
-
-#define MT312_SYS_CLK		90000000UL	/* 90 MHz */
-static struct dvb_frontend_ops mt312_ops = {
-	.delsys = { SYS_DVBS },
-	.info = {
-		.name = "Zarlink ???? DVB-S",
-		.frequency_min = 950000,
-		.frequency_max = 2150000,
-		/* FIXME: adjust freq to real used xtal */
-		.frequency_stepsize = (MT312_PLL_CLK / 1000) / 128,
-		.symbol_rate_min = MT312_SYS_CLK / 128, /* FIXME as above */
-		.symbol_rate_max = MT312_SYS_CLK / 2,
-		.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_FEC_AUTO | FE_CAN_QPSK | FE_CAN_MUTE_TS |
-		    FE_CAN_RECOVER
-	},
-
-	.release = mt312_release,
-
-	.init = mt312_initfe,
-	.sleep = mt312_sleep,
-	.i2c_gate_ctrl = mt312_i2c_gate_ctrl,
-
-	.set_frontend = mt312_set_frontend,
-	.get_frontend = mt312_get_frontend,
-	.get_tune_settings = mt312_get_tune_settings,
-
-	.read_status = mt312_read_status,
-	.read_ber = mt312_read_ber,
-	.read_signal_strength = mt312_read_signal_strength,
-	.read_snr = mt312_read_snr,
-	.read_ucblocks = mt312_read_ucblocks,
-
-	.diseqc_send_master_cmd = mt312_send_master_cmd,
-	.diseqc_send_burst = mt312_send_burst,
-	.set_tone = mt312_set_tone,
-	.set_voltage = mt312_set_voltage,
-};
-
-struct dvb_frontend *mt312_attach(const struct mt312_config *config,
-					struct i2c_adapter *i2c)
-{
-	struct mt312_state *state = NULL;
-
-	/* allocate memory for the internal state */
-	state = kzalloc(sizeof(struct mt312_state), GFP_KERNEL);
-	if (state == NULL)
-		goto error;
-
-	/* setup the state */
-	state->config = config;
-	state->i2c = i2c;
-
-	/* check if the demod is there */
-	if (mt312_readreg(state, ID, &state->id) < 0)
-		goto error;
-
-	/* create dvb_frontend */
-	memcpy(&state->frontend.ops, &mt312_ops,
-		sizeof(struct dvb_frontend_ops));
-	state->frontend.demodulator_priv = state;
-
-	switch (state->id) {
-	case ID_VP310:
-		strcpy(state->frontend.ops.info.name, "Zarlink VP310 DVB-S");
-		state->xtal = MT312_PLL_CLK;
-		state->freq_mult = 9;
-		break;
-	case ID_MT312:
-		strcpy(state->frontend.ops.info.name, "Zarlink MT312 DVB-S");
-		state->xtal = MT312_PLL_CLK;
-		state->freq_mult = 6;
-		break;
-	case ID_ZL10313:
-		strcpy(state->frontend.ops.info.name, "Zarlink ZL10313 DVB-S");
-		state->xtal = MT312_PLL_CLK_10_111;
-		state->freq_mult = 9;
-		break;
-	default:
-		printk(KERN_WARNING "Only Zarlink VP310/MT312/ZL10313"
-			" are supported chips.\n");
-		goto error;
-	}
-
-	return &state->frontend;
-
-error:
-	kfree(state);
-	return NULL;
-}
-EXPORT_SYMBOL(mt312_attach);
-
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
-
-MODULE_DESCRIPTION("Zarlink VP310/MT312/ZL10313 DVB-S Demodulator driver");
-MODULE_AUTHOR("Andreas Oberritter <obi@linuxtv.org>");
-MODULE_AUTHOR("Matthias Schwarzott <zzam@gentoo.org>");
-MODULE_LICENSE("GPL");
-
diff --git a/drivers/media/dvb/frontends/mt312.h b/drivers/media/dvb/frontends/mt312.h
deleted file mode 100644
index 29e3bb5..0000000
--- a/drivers/media/dvb/frontends/mt312.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
-    Driver for Zarlink MT312 Satellite Channel Decoder
-
-    Copyright (C) 2003 Andreas Oberritter <obi@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.
-
-    References:
-    http://products.zarlink.com/product_profiles/MT312.htm
-    http://products.zarlink.com/product_profiles/SL1935.htm
-*/
-
-#ifndef MT312_H
-#define MT312_H
-
-#include <linux/dvb/frontend.h>
-
-struct mt312_config {
-	/* the demodulator's i2c address */
-	u8 demod_address;
-
-	/* inverted voltage setting */
-	unsigned int voltage_inverted:1;
-};
-
-#if defined(CONFIG_DVB_MT312) || (defined(CONFIG_DVB_MT312_MODULE) && defined(MODULE))
-struct dvb_frontend *mt312_attach(const struct mt312_config *config,
-					struct i2c_adapter *i2c);
-#else
-static inline struct dvb_frontend *mt312_attach(
-	const struct mt312_config *config, struct i2c_adapter *i2c)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif /* CONFIG_DVB_MT312 */
-
-#endif /* MT312_H */
diff --git a/drivers/media/dvb/frontends/mt312_priv.h b/drivers/media/dvb/frontends/mt312_priv.h
deleted file mode 100644
index a3959f9..0000000
--- a/drivers/media/dvb/frontends/mt312_priv.h
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
-    Driver for Zarlink MT312 QPSK Frontend
-
-    Copyright (C) 2003 Andreas Oberritter <obi@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 _DVB_FRONTENDS_MT312_PRIV
-#define _DVB_FRONTENDS_MT312_PRIV
-
-enum mt312_reg_addr {
-	QPSK_INT_H = 0,
-	QPSK_INT_M = 1,
-	QPSK_INT_L = 2,
-	FEC_INT = 3,
-	QPSK_STAT_H = 4,
-	QPSK_STAT_L = 5,
-	FEC_STATUS = 6,
-	LNB_FREQ_H = 7,
-	LNB_FREQ_L = 8,
-	M_SNR_H = 9,
-	M_SNR_L = 10,
-	VIT_ERRCNT_H = 11,
-	VIT_ERRCNT_M = 12,
-	VIT_ERRCNT_L = 13,
-	RS_BERCNT_H = 14,
-	RS_BERCNT_M = 15,
-	RS_BERCNT_L = 16,
-	RS_UBC_H = 17,
-	RS_UBC_L = 18,
-	SIG_LEVEL = 19,
-	GPP_CTRL = 20,
-	RESET = 21,
-	DISEQC_MODE = 22,
-	SYM_RATE_H = 23,
-	SYM_RATE_L = 24,
-	VIT_MODE = 25,
-	QPSK_CTRL = 26,
-	GO = 27,
-	IE_QPSK_H = 28,
-	IE_QPSK_M = 29,
-	IE_QPSK_L = 30,
-	IE_FEC = 31,
-	QPSK_STAT_EN = 32,
-	FEC_STAT_EN = 33,
-	SYS_CLK = 34,
-	DISEQC_RATIO = 35,
-	DISEQC_INSTR = 36,
-	FR_LIM = 37,
-	FR_OFF = 38,
-	AGC_CTRL = 39,
-	AGC_INIT = 40,
-	AGC_REF = 41,
-	AGC_MAX = 42,
-	AGC_MIN = 43,
-	AGC_LK_TH = 44,
-	TS_AGC_LK_TH = 45,
-	AGC_PWR_SET = 46,
-	QPSK_MISC = 47,
-	SNR_THS_LOW = 48,
-	SNR_THS_HIGH = 49,
-	TS_SW_RATE = 50,
-	TS_SW_LIM_L = 51,
-	TS_SW_LIM_H = 52,
-	CS_SW_RATE_1 = 53,
-	CS_SW_RATE_2 = 54,
-	CS_SW_RATE_3 = 55,
-	CS_SW_RATE_4 = 56,
-	CS_SW_LIM = 57,
-	TS_LPK = 58,
-	TS_LPK_M = 59,
-	TS_LPK_L = 60,
-	CS_KPROP_H = 61,
-	CS_KPROP_L = 62,
-	CS_KINT_H = 63,
-	CS_KINT_L = 64,
-	QPSK_SCALE = 65,
-	TLD_OUTCLK_TH = 66,
-	TLD_INCLK_TH = 67,
-	FLD_TH = 68,
-	PLD_OUTLK3 = 69,
-	PLD_OUTLK2 = 70,
-	PLD_OUTLK1 = 71,
-	PLD_OUTLK0 = 72,
-	PLD_INLK3 = 73,
-	PLD_INLK2 = 74,
-	PLD_INLK1 = 75,
-	PLD_INLK0 = 76,
-	PLD_ACC_TIME = 77,
-	SWEEP_PAR = 78,
-	STARTUP_TIME = 79,
-	LOSSLOCK_TH = 80,
-	FEC_LOCK_TM = 81,
-	LOSSLOCK_TM = 82,
-	VIT_ERRPER_H = 83,
-	VIT_ERRPER_M = 84,
-	VIT_ERRPER_L = 85,
-	HW_CTRL = 84,	/* ZL10313 only */
-	MPEG_CTRL = 85,	/* ZL10313 only */
-	VIT_SETUP = 86,
-	VIT_REF0 = 87,
-	VIT_REF1 = 88,
-	VIT_REF2 = 89,
-	VIT_REF3 = 90,
-	VIT_REF4 = 91,
-	VIT_REF5 = 92,
-	VIT_REF6 = 93,
-	VIT_MAXERR = 94,
-	BA_SETUPT = 95,
-	OP_CTRL = 96,
-	FEC_SETUP = 97,
-	PROG_SYNC = 98,
-	AFC_SEAR_TH = 99,
-	CSACC_DIF_TH = 100,
-	QPSK_LK_CT = 101,
-	QPSK_ST_CT = 102,
-	MON_CTRL = 103,
-	QPSK_RESET = 104,
-	QPSK_TST_CT = 105,
-	QPSK_TST_ST = 106,
-	TEST_R = 107,
-	AGC_H = 108,
-	AGC_M = 109,
-	AGC_L = 110,
-	FREQ_ERR1_H = 111,
-	FREQ_ERR1_M = 112,
-	FREQ_ERR1_L = 113,
-	FREQ_ERR2_H = 114,
-	FREQ_ERR2_L = 115,
-	SYM_RAT_OP_H = 116,
-	SYM_RAT_OP_L = 117,
-	DESEQC2_INT = 118,
-	DISEQC2_STAT = 119,
-	DISEQC2_FIFO = 120,
-	DISEQC2_CTRL1 = 121,
-	DISEQC2_CTRL2 = 122,
-	MONITOR_H = 123,
-	MONITOR_L = 124,
-	TEST_MODE = 125,
-	ID = 126,
-	CONFIG = 127
-};
-
-enum mt312_model_id {
-	ID_VP310 = 1,
-	ID_MT312 = 3,
-	ID_ZL10313 = 5,
-};
-
-#endif				/* DVB_FRONTENDS_MT312_PRIV */
diff --git a/drivers/media/dvb/frontends/mt352.c b/drivers/media/dvb/frontends/mt352.c
deleted file mode 100644
index 2c3b50e..0000000
--- a/drivers/media/dvb/frontends/mt352.c
+++ /dev/null
@@ -1,610 +0,0 @@
-/*
- *  Driver for Zarlink DVB-T MT352 demodulator
- *
- *  Written by Holger Waechtler <holger@qanu.de>
- *	 and Daniel Mack <daniel@qanu.de>
- *
- *  AVerMedia AVerTV DVB-T 771 support by
- *       Wolfram Joost <dbox2@frokaschwei.de>
- *
- *  Support for Samsung TDTC9251DH01C(M) tuner
- *  Copyright (C) 2004 Antonio Mancuso <antonio.mancuso@digitaltelevision.it>
- *                     Amauri  Celani  <acelani@essegi.net>
- *
- *  DVICO FusionHDTV DVB-T1 and DVICO FusionHDTV DVB-T Lite support by
- *       Christopher Pascoe <c.pascoe@itee.uq.edu.au>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *
- *  GNU General Public License for more details.
- *
- *  You 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/init.h>
-#include <linux/delay.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-
-#include "dvb_frontend.h"
-#include "mt352_priv.h"
-#include "mt352.h"
-
-struct mt352_state {
-	struct i2c_adapter* i2c;
-	struct dvb_frontend frontend;
-
-	/* configuration settings */
-	struct mt352_config config;
-};
-
-static int debug;
-#define dprintk(args...) \
-	do { \
-		if (debug) printk(KERN_DEBUG "mt352: " args); \
-	} while (0)
-
-static int mt352_single_write(struct dvb_frontend *fe, u8 reg, u8 val)
-{
-	struct mt352_state* state = fe->demodulator_priv;
-	u8 buf[2] = { reg, val };
-	struct i2c_msg msg = { .addr = state->config.demod_address, .flags = 0,
-			       .buf = buf, .len = 2 };
-	int err = i2c_transfer(state->i2c, &msg, 1);
-	if (err != 1) {
-		printk("mt352_write() to reg %x failed (err = %d)!\n", reg, err);
-		return err;
-	}
-	return 0;
-}
-
-static int _mt352_write(struct dvb_frontend* fe, const u8 ibuf[], int ilen)
-{
-	int err,i;
-	for (i=0; i < ilen-1; i++)
-		if ((err = mt352_single_write(fe,ibuf[0]+i,ibuf[i+1])))
-			return err;
-
-	return 0;
-}
-
-static int mt352_read_register(struct mt352_state* state, u8 reg)
-{
-	int ret;
-	u8 b0 [] = { reg };
-	u8 b1 [] = { 0 };
-	struct i2c_msg msg [] = { { .addr = state->config.demod_address,
-				    .flags = 0,
-				    .buf = b0, .len = 1 },
-				  { .addr = state->config.demod_address,
-				    .flags = I2C_M_RD,
-				    .buf = b1, .len = 1 } };
-
-	ret = i2c_transfer(state->i2c, msg, 2);
-
-	if (ret != 2) {
-		printk("%s: readreg error (reg=%d, ret==%i)\n",
-		       __func__, reg, ret);
-		return ret;
-	}
-
-	return b1[0];
-}
-
-static int mt352_sleep(struct dvb_frontend* fe)
-{
-	static u8 mt352_softdown[] = { CLOCK_CTL, 0x20, 0x08 };
-
-	_mt352_write(fe, mt352_softdown, sizeof(mt352_softdown));
-	return 0;
-}
-
-static void mt352_calc_nominal_rate(struct mt352_state* state,
-				    u32 bandwidth,
-				    unsigned char *buf)
-{
-	u32 adc_clock = 20480; /* 20.340 MHz */
-	u32 bw,value;
-
-	switch (bandwidth) {
-	case 6000000:
-		bw = 6;
-		break;
-	case 7000000:
-		bw = 7;
-		break;
-	case 8000000:
-	default:
-		bw = 8;
-		break;
-	}
-	if (state->config.adc_clock)
-		adc_clock = state->config.adc_clock;
-
-	value = 64 * bw * (1<<16) / (7 * 8);
-	value = value * 1000 / adc_clock;
-	dprintk("%s: bw %d, adc_clock %d => 0x%x\n",
-		__func__, bw, adc_clock, value);
-	buf[0] = msb(value);
-	buf[1] = lsb(value);
-}
-
-static void mt352_calc_input_freq(struct mt352_state* state,
-				  unsigned char *buf)
-{
-	int adc_clock = 20480; /* 20.480000 MHz */
-	int if2       = 36167; /* 36.166667 MHz */
-	int ife,value;
-
-	if (state->config.adc_clock)
-		adc_clock = state->config.adc_clock;
-	if (state->config.if2)
-		if2 = state->config.if2;
-
-	if (adc_clock >= if2 * 2)
-		ife = if2;
-	else {
-		ife = adc_clock - (if2 % adc_clock);
-		if (ife > adc_clock / 2)
-			ife = adc_clock - ife;
-	}
-	value = -16374 * ife / adc_clock;
-	dprintk("%s: if2 %d, ife %d, adc_clock %d => %d / 0x%x\n",
-		__func__, if2, ife, adc_clock, value, value & 0x3fff);
-	buf[0] = msb(value);
-	buf[1] = lsb(value);
-}
-
-static int mt352_set_parameters(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *op = &fe->dtv_property_cache;
-	struct mt352_state* state = fe->demodulator_priv;
-	unsigned char buf[13];
-	static unsigned char tuner_go[] = { 0x5d, 0x01 };
-	static unsigned char fsm_go[]   = { 0x5e, 0x01 };
-	unsigned int tps = 0;
-
-	switch (op->code_rate_HP) {
-		case FEC_2_3:
-			tps |= (1 << 7);
-			break;
-		case FEC_3_4:
-			tps |= (2 << 7);
-			break;
-		case FEC_5_6:
-			tps |= (3 << 7);
-			break;
-		case FEC_7_8:
-			tps |= (4 << 7);
-			break;
-		case FEC_1_2:
-		case FEC_AUTO:
-			break;
-		default:
-			return -EINVAL;
-	}
-
-	switch (op->code_rate_LP) {
-		case FEC_2_3:
-			tps |= (1 << 4);
-			break;
-		case FEC_3_4:
-			tps |= (2 << 4);
-			break;
-		case FEC_5_6:
-			tps |= (3 << 4);
-			break;
-		case FEC_7_8:
-			tps |= (4 << 4);
-			break;
-		case FEC_1_2:
-		case FEC_AUTO:
-			break;
-		case FEC_NONE:
-			if (op->hierarchy == HIERARCHY_AUTO ||
-			    op->hierarchy == HIERARCHY_NONE)
-				break;
-		default:
-			return -EINVAL;
-	}
-
-	switch (op->modulation) {
-		case QPSK:
-			break;
-		case QAM_AUTO:
-		case QAM_16:
-			tps |= (1 << 13);
-			break;
-		case QAM_64:
-			tps |= (2 << 13);
-			break;
-		default:
-			return -EINVAL;
-	}
-
-	switch (op->transmission_mode) {
-		case TRANSMISSION_MODE_2K:
-		case TRANSMISSION_MODE_AUTO:
-			break;
-		case TRANSMISSION_MODE_8K:
-			tps |= (1 << 0);
-			break;
-		default:
-			return -EINVAL;
-	}
-
-	switch (op->guard_interval) {
-		case GUARD_INTERVAL_1_32:
-		case GUARD_INTERVAL_AUTO:
-			break;
-		case GUARD_INTERVAL_1_16:
-			tps |= (1 << 2);
-			break;
-		case GUARD_INTERVAL_1_8:
-			tps |= (2 << 2);
-			break;
-		case GUARD_INTERVAL_1_4:
-			tps |= (3 << 2);
-			break;
-		default:
-			return -EINVAL;
-	}
-
-	switch (op->hierarchy) {
-		case HIERARCHY_AUTO:
-		case HIERARCHY_NONE:
-			break;
-		case HIERARCHY_1:
-			tps |= (1 << 10);
-			break;
-		case HIERARCHY_2:
-			tps |= (2 << 10);
-			break;
-		case HIERARCHY_4:
-			tps |= (3 << 10);
-			break;
-		default:
-			return -EINVAL;
-	}
-
-
-	buf[0] = TPS_GIVEN_1; /* TPS_GIVEN_1 and following registers */
-
-	buf[1] = msb(tps);      /* TPS_GIVEN_(1|0) */
-	buf[2] = lsb(tps);
-
-	buf[3] = 0x50;  // old
-//	buf[3] = 0xf4;  // pinnacle
-
-	mt352_calc_nominal_rate(state, op->bandwidth_hz, buf+4);
-	mt352_calc_input_freq(state, buf+6);
-
-	if (state->config.no_tuner) {
-		if (fe->ops.tuner_ops.set_params) {
-			fe->ops.tuner_ops.set_params(fe);
-			if (fe->ops.i2c_gate_ctrl)
-				fe->ops.i2c_gate_ctrl(fe, 0);
-		}
-
-		_mt352_write(fe, buf, 8);
-		_mt352_write(fe, fsm_go, 2);
-	} else {
-		if (fe->ops.tuner_ops.calc_regs) {
-			fe->ops.tuner_ops.calc_regs(fe, buf+8, 5);
-			buf[8] <<= 1;
-			_mt352_write(fe, buf, sizeof(buf));
-			_mt352_write(fe, tuner_go, 2);
-		}
-	}
-
-	return 0;
-}
-
-static int mt352_get_parameters(struct dvb_frontend* fe)
-{
-	struct dtv_frontend_properties *op = &fe->dtv_property_cache;
-	struct mt352_state* state = fe->demodulator_priv;
-	u16 tps;
-	u16 div;
-	u8 trl;
-	static const u8 tps_fec_to_api[8] =
-	{
-		FEC_1_2,
-		FEC_2_3,
-		FEC_3_4,
-		FEC_5_6,
-		FEC_7_8,
-		FEC_AUTO,
-		FEC_AUTO,
-		FEC_AUTO
-	};
-
-	if ( (mt352_read_register(state,0x00) & 0xC0) != 0xC0 )
-		return -EINVAL;
-
-	/* Use TPS_RECEIVED-registers, not the TPS_CURRENT-registers because
-	 * the mt352 sometimes works with the wrong parameters
-	 */
-	tps = (mt352_read_register(state, TPS_RECEIVED_1) << 8) | mt352_read_register(state, TPS_RECEIVED_0);
-	div = (mt352_read_register(state, CHAN_START_1) << 8) | mt352_read_register(state, CHAN_START_0);
-	trl = mt352_read_register(state, TRL_NOMINAL_RATE_1);
-
-	op->code_rate_HP = tps_fec_to_api[(tps >> 7) & 7];
-	op->code_rate_LP = tps_fec_to_api[(tps >> 4) & 7];
-
-	switch ( (tps >> 13) & 3)
-	{
-		case 0:
-			op->modulation = QPSK;
-			break;
-		case 1:
-			op->modulation = QAM_16;
-			break;
-		case 2:
-			op->modulation = QAM_64;
-			break;
-		default:
-			op->modulation = QAM_AUTO;
-			break;
-	}
-
-	op->transmission_mode = (tps & 0x01) ? TRANSMISSION_MODE_8K : TRANSMISSION_MODE_2K;
-
-	switch ( (tps >> 2) & 3)
-	{
-		case 0:
-			op->guard_interval = GUARD_INTERVAL_1_32;
-			break;
-		case 1:
-			op->guard_interval = GUARD_INTERVAL_1_16;
-			break;
-		case 2:
-			op->guard_interval = GUARD_INTERVAL_1_8;
-			break;
-		case 3:
-			op->guard_interval = GUARD_INTERVAL_1_4;
-			break;
-		default:
-			op->guard_interval = GUARD_INTERVAL_AUTO;
-			break;
-	}
-
-	switch ( (tps >> 10) & 7)
-	{
-		case 0:
-			op->hierarchy = HIERARCHY_NONE;
-			break;
-		case 1:
-			op->hierarchy = HIERARCHY_1;
-			break;
-		case 2:
-			op->hierarchy = HIERARCHY_2;
-			break;
-		case 3:
-			op->hierarchy = HIERARCHY_4;
-			break;
-		default:
-			op->hierarchy = HIERARCHY_AUTO;
-			break;
-	}
-
-	op->frequency = (500 * (div - IF_FREQUENCYx6)) / 3 * 1000;
-
-	if (trl == 0x72)
-		op->bandwidth_hz = 8000000;
-	else if (trl == 0x64)
-		op->bandwidth_hz = 7000000;
-	else
-		op->bandwidth_hz = 6000000;
-
-
-	if (mt352_read_register(state, STATUS_2) & 0x02)
-		op->inversion = INVERSION_OFF;
-	else
-		op->inversion = INVERSION_ON;
-
-	return 0;
-}
-
-static int mt352_read_status(struct dvb_frontend* fe, fe_status_t* status)
-{
-	struct mt352_state* state = fe->demodulator_priv;
-	int s0, s1, s3;
-
-	/* FIXME:
-	 *
-	 * The MT352 design manual from Zarlink states (page 46-47):
-	 *
-	 * Notes about the TUNER_GO register:
-	 *
-	 * If the Read_Tuner_Byte (bit-1) is activated, then the tuner status
-	 * byte is copied from the tuner to the STATUS_3 register and
-	 * completion of the read operation is indicated by bit-5 of the
-	 * INTERRUPT_3 register.
-	 */
-
-	if ((s0 = mt352_read_register(state, STATUS_0)) < 0)
-		return -EREMOTEIO;
-	if ((s1 = mt352_read_register(state, STATUS_1)) < 0)
-		return -EREMOTEIO;
-	if ((s3 = mt352_read_register(state, STATUS_3)) < 0)
-		return -EREMOTEIO;
-
-	*status = 0;
-	if (s0 & (1 << 4))
-		*status |= FE_HAS_CARRIER;
-	if (s0 & (1 << 1))
-		*status |= FE_HAS_VITERBI;
-	if (s0 & (1 << 5))
-		*status |= FE_HAS_LOCK;
-	if (s1 & (1 << 1))
-		*status |= FE_HAS_SYNC;
-	if (s3 & (1 << 6))
-		*status |= FE_HAS_SIGNAL;
-
-	if ((*status & (FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC)) !=
-		      (FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC))
-		*status &= ~FE_HAS_LOCK;
-
-	return 0;
-}
-
-static int mt352_read_ber(struct dvb_frontend* fe, u32* ber)
-{
-	struct mt352_state* state = fe->demodulator_priv;
-
-	*ber = (mt352_read_register (state, RS_ERR_CNT_2) << 16) |
-	       (mt352_read_register (state, RS_ERR_CNT_1) << 8) |
-	       (mt352_read_register (state, RS_ERR_CNT_0));
-
-	return 0;
-}
-
-static int mt352_read_signal_strength(struct dvb_frontend* fe, u16* strength)
-{
-	struct mt352_state* state = fe->demodulator_priv;
-
-	/* align the 12 bit AGC gain with the most significant bits */
-	u16 signal = ((mt352_read_register(state, AGC_GAIN_1) & 0x0f) << 12) |
-		(mt352_read_register(state, AGC_GAIN_0) << 4);
-
-	/* inverse of gain is signal strength */
-	*strength = ~signal;
-	return 0;
-}
-
-static int mt352_read_snr(struct dvb_frontend* fe, u16* snr)
-{
-	struct mt352_state* state = fe->demodulator_priv;
-
-	u8 _snr = mt352_read_register (state, SNR);
-	*snr = (_snr << 8) | _snr;
-
-	return 0;
-}
-
-static int mt352_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
-{
-	struct mt352_state* state = fe->demodulator_priv;
-
-	*ucblocks = (mt352_read_register (state,  RS_UBC_1) << 8) |
-		    (mt352_read_register (state,  RS_UBC_0));
-
-	return 0;
-}
-
-static int mt352_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fe_tune_settings)
-{
-	fe_tune_settings->min_delay_ms = 800;
-	fe_tune_settings->step_size = 0;
-	fe_tune_settings->max_drift = 0;
-
-	return 0;
-}
-
-static int mt352_init(struct dvb_frontend* fe)
-{
-	struct mt352_state* state = fe->demodulator_priv;
-
-	static u8 mt352_reset_attach [] = { RESET, 0xC0 };
-
-	dprintk("%s: hello\n",__func__);
-
-	if ((mt352_read_register(state, CLOCK_CTL) & 0x10) == 0 ||
-	    (mt352_read_register(state, CONFIG) & 0x20) == 0) {
-
-		/* Do a "hard" reset */
-		_mt352_write(fe, mt352_reset_attach, sizeof(mt352_reset_attach));
-		return state->config.demod_init(fe);
-	}
-
-	return 0;
-}
-
-static void mt352_release(struct dvb_frontend* fe)
-{
-	struct mt352_state* state = fe->demodulator_priv;
-	kfree(state);
-}
-
-static struct dvb_frontend_ops mt352_ops;
-
-struct dvb_frontend* mt352_attach(const struct mt352_config* config,
-				  struct i2c_adapter* i2c)
-{
-	struct mt352_state* state = NULL;
-
-	/* allocate memory for the internal state */
-	state = kzalloc(sizeof(struct mt352_state), GFP_KERNEL);
-	if (state == NULL) goto error;
-
-	/* setup the state */
-	state->i2c = i2c;
-	memcpy(&state->config,config,sizeof(struct mt352_config));
-
-	/* check if the demod is there */
-	if (mt352_read_register(state, CHIP_ID) != ID_MT352) goto error;
-
-	/* create dvb_frontend */
-	memcpy(&state->frontend.ops, &mt352_ops, sizeof(struct dvb_frontend_ops));
-	state->frontend.demodulator_priv = state;
-	return &state->frontend;
-
-error:
-	kfree(state);
-	return NULL;
-}
-
-static struct dvb_frontend_ops mt352_ops = {
-	.delsys = { SYS_DVBT },
-	.info = {
-		.name			= "Zarlink MT352 DVB-T",
-		.frequency_min		= 174000000,
-		.frequency_max		= 862000000,
-		.frequency_stepsize	= 166667,
-		.frequency_tolerance	= 0,
-		.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_FEC_AUTO |
-			FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
-			FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |
-			FE_CAN_HIERARCHY_AUTO | FE_CAN_RECOVER |
-			FE_CAN_MUTE_TS
-	},
-
-	.release = mt352_release,
-
-	.init = mt352_init,
-	.sleep = mt352_sleep,
-	.write = _mt352_write,
-
-	.set_frontend = mt352_set_parameters,
-	.get_frontend = mt352_get_parameters,
-	.get_tune_settings = mt352_get_tune_settings,
-
-	.read_status = mt352_read_status,
-	.read_ber = mt352_read_ber,
-	.read_signal_strength = mt352_read_signal_strength,
-	.read_snr = mt352_read_snr,
-	.read_ucblocks = mt352_read_ucblocks,
-};
-
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
-
-MODULE_DESCRIPTION("Zarlink MT352 DVB-T Demodulator driver");
-MODULE_AUTHOR("Holger Waechtler, Daniel Mack, Antonio Mancuso");
-MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(mt352_attach);
diff --git a/drivers/media/dvb/frontends/mt352.h b/drivers/media/dvb/frontends/mt352.h
deleted file mode 100644
index ca2562d..0000000
--- a/drivers/media/dvb/frontends/mt352.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- *  Driver for Zarlink DVB-T MT352 demodulator
- *
- *  Written by Holger Waechtler <holger@qanu.de>
- *	 and Daniel Mack <daniel@qanu.de>
- *
- *  AVerMedia AVerTV DVB-T 771 support by
- *       Wolfram Joost <dbox2@frokaschwei.de>
- *
- *  Support for Samsung TDTC9251DH01C(M) tuner
- *  Copyright (C) 2004 Antonio Mancuso <antonio.mancuso@digitaltelevision.it>
- *                     Amauri  Celani  <acelani@essegi.net>
- *
- *  DVICO FusionHDTV DVB-T1 and DVICO FusionHDTV DVB-T Lite support by
- *       Christopher Pascoe <c.pascoe@itee.uq.edu.au>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *
- *  GNU General Public License for more details.
- *
- *  You 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 MT352_H
-#define MT352_H
-
-#include <linux/dvb/frontend.h>
-
-struct mt352_config
-{
-	/* the demodulator's i2c address */
-	u8 demod_address;
-
-	/* frequencies in kHz */
-	int adc_clock;  // default: 20480
-	int if2;        // default: 36166
-
-	/* set if no pll is connected to the secondary i2c bus */
-	int no_tuner;
-
-	/* Initialise the demodulator and PLL. Cannot be NULL */
-	int (*demod_init)(struct dvb_frontend* fe);
-};
-
-#if defined(CONFIG_DVB_MT352) || (defined(CONFIG_DVB_MT352_MODULE) && defined(MODULE))
-extern struct dvb_frontend* mt352_attach(const struct mt352_config* config,
-					 struct i2c_adapter* i2c);
-#else
-static inline struct dvb_frontend* mt352_attach(const struct mt352_config* config,
-					 struct i2c_adapter* i2c)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif // CONFIG_DVB_MT352
-
-static inline int mt352_write(struct dvb_frontend *fe, const u8 buf[], int len) {
-	int r = 0;
-	if (fe->ops.write)
-		r = fe->ops.write(fe, buf, len);
-	return r;
-}
-
-#endif // MT352_H
diff --git a/drivers/media/dvb/frontends/mt352_priv.h b/drivers/media/dvb/frontends/mt352_priv.h
deleted file mode 100644
index 44ad0d4..0000000
--- a/drivers/media/dvb/frontends/mt352_priv.h
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- *  Driver for Zarlink DVB-T MT352 demodulator
- *
- *  Written by Holger Waechtler <holger@qanu.de>
- *	 and Daniel Mack <daniel@qanu.de>
- *
- *  AVerMedia AVerTV DVB-T 771 support by
- *       Wolfram Joost <dbox2@frokaschwei.de>
- *
- *  Support for Samsung TDTC9251DH01C(M) tuner
- *  Copyright (C) 2004 Antonio Mancuso <antonio.mancuso@digitaltelevision.it>
- *                     Amauri  Celani  <acelani@essegi.net>
- *
- *  DVICO FusionHDTV DVB-T1 and DVICO FusionHDTV DVB-T Lite support by
- *       Christopher Pascoe <c.pascoe@itee.uq.edu.au>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *
- *  GNU General Public License for more details.
- *
- *  You 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 _MT352_PRIV_
-#define _MT352_PRIV_
-
-#define ID_MT352        0x13
-
-#define msb(x) (((x) >> 8) & 0xff)
-#define lsb(x) ((x) & 0xff)
-
-enum mt352_reg_addr {
-	STATUS_0           = 0x00,
-	STATUS_1           = 0x01,
-	STATUS_2           = 0x02,
-	STATUS_3           = 0x03,
-	STATUS_4           = 0x04,
-	INTERRUPT_0        = 0x05,
-	INTERRUPT_1        = 0x06,
-	INTERRUPT_2        = 0x07,
-	INTERRUPT_3        = 0x08,
-	SNR                = 0x09,
-	VIT_ERR_CNT_2      = 0x0A,
-	VIT_ERR_CNT_1      = 0x0B,
-	VIT_ERR_CNT_0      = 0x0C,
-	RS_ERR_CNT_2       = 0x0D,
-	RS_ERR_CNT_1       = 0x0E,
-	RS_ERR_CNT_0       = 0x0F,
-	RS_UBC_1           = 0x10,
-	RS_UBC_0           = 0x11,
-	AGC_GAIN_3         = 0x12,
-	AGC_GAIN_2         = 0x13,
-	AGC_GAIN_1         = 0x14,
-	AGC_GAIN_0         = 0x15,
-	FREQ_OFFSET_2      = 0x17,
-	FREQ_OFFSET_1      = 0x18,
-	FREQ_OFFSET_0      = 0x19,
-	TIMING_OFFSET_1    = 0x1A,
-	TIMING_OFFSET_0    = 0x1B,
-	CHAN_FREQ_1        = 0x1C,
-	CHAN_FREQ_0        = 0x1D,
-	TPS_RECEIVED_1     = 0x1E,
-	TPS_RECEIVED_0     = 0x1F,
-	TPS_CURRENT_1      = 0x20,
-	TPS_CURRENT_0      = 0x21,
-	TPS_CELL_ID_1      = 0x22,
-	TPS_CELL_ID_0      = 0x23,
-	TPS_MISC_DATA_2    = 0x24,
-	TPS_MISC_DATA_1    = 0x25,
-	TPS_MISC_DATA_0    = 0x26,
-	RESET              = 0x50,
-	TPS_GIVEN_1        = 0x51,
-	TPS_GIVEN_0        = 0x52,
-	ACQ_CTL            = 0x53,
-	TRL_NOMINAL_RATE_1 = 0x54,
-	TRL_NOMINAL_RATE_0 = 0x55,
-	INPUT_FREQ_1       = 0x56,
-	INPUT_FREQ_0       = 0x57,
-	TUNER_ADDR         = 0x58,
-	CHAN_START_1       = 0x59,
-	CHAN_START_0       = 0x5A,
-	CONT_1             = 0x5B,
-	CONT_0             = 0x5C,
-	TUNER_GO           = 0x5D,
-	STATUS_EN_0        = 0x5F,
-	STATUS_EN_1        = 0x60,
-	INTERRUPT_EN_0     = 0x61,
-	INTERRUPT_EN_1     = 0x62,
-	INTERRUPT_EN_2     = 0x63,
-	INTERRUPT_EN_3     = 0x64,
-	AGC_TARGET         = 0x67,
-	AGC_CTL            = 0x68,
-	CAPT_RANGE         = 0x75,
-	SNR_SELECT_1       = 0x79,
-	SNR_SELECT_0       = 0x7A,
-	RS_ERR_PER_1       = 0x7C,
-	RS_ERR_PER_0       = 0x7D,
-	CHIP_ID            = 0x7F,
-	CHAN_STOP_1        = 0x80,
-	CHAN_STOP_0        = 0x81,
-	CHAN_STEP_1        = 0x82,
-	CHAN_STEP_0        = 0x83,
-	FEC_LOCK_TIME      = 0x85,
-	OFDM_LOCK_TIME     = 0x86,
-	ACQ_DELAY          = 0x87,
-	SCAN_CTL           = 0x88,
-	CLOCK_CTL          = 0x89,
-	CONFIG             = 0x8A,
-	MCLK_RATIO         = 0x8B,
-	GPP_CTL            = 0x8C,
-	ADC_CTL_1          = 0x8E,
-	ADC_CTL_0          = 0x8F
-};
-
-/* here we assume 1/6MHz == 166.66kHz stepsize */
-#define IF_FREQUENCYx6 217    /* 6 * 36.16666666667MHz */
-
-#endif                          /* _MT352_PRIV_ */
diff --git a/drivers/media/dvb/frontends/nxt200x.c b/drivers/media/dvb/frontends/nxt200x.c
deleted file mode 100644
index 49ca78d..0000000
--- a/drivers/media/dvb/frontends/nxt200x.c
+++ /dev/null
@@ -1,1240 +0,0 @@
-/*
- *    Support for NXT2002 and NXT2004 - VSB/QAM
- *
- *    Copyright (C) 2005 Kirk Lapray <kirk.lapray@gmail.com>
- *    Copyright (C) 2006 Michael Krufky <mkrufky@m1k.net>
- *    based on nxt2002 by Taylor Jacob <rtjacob@earthlink.net>
- *    and nxt2004 by Jean-Francois Thibert <jeanfrancois@sagetv.com>
- *
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
-*/
-
-/*
- *                      NOTES ABOUT THIS DRIVER
- *
- * This Linux driver supports:
- *   B2C2/BBTI Technisat Air2PC - ATSC (NXT2002)
- *   AverTVHD MCE A180 (NXT2004)
- *   ATI HDTV Wonder (NXT2004)
- *
- * This driver needs external firmware. Please use the command
- * "<kerneldir>/Documentation/dvb/get_dvb_firmware nxt2002" or
- * "<kerneldir>/Documentation/dvb/get_dvb_firmware nxt2004" to
- * download/extract the appropriate firmware, and then copy it to
- * /usr/lib/hotplug/firmware/ or /lib/firmware/
- * (depending on configuration of firmware hotplug).
- */
-#define NXT2002_DEFAULT_FIRMWARE "dvb-fe-nxt2002.fw"
-#define NXT2004_DEFAULT_FIRMWARE "dvb-fe-nxt2004.fw"
-#define CRC_CCIT_MASK 0x1021
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-
-#include "dvb_frontend.h"
-#include "nxt200x.h"
-
-struct nxt200x_state {
-
-	struct i2c_adapter* i2c;
-	const struct nxt200x_config* config;
-	struct dvb_frontend frontend;
-
-	/* demodulator private data */
-	nxt_chip_type demod_chip;
-	u8 initialised:1;
-};
-
-static int debug;
-#define dprintk(args...) \
-	do { \
-		if (debug) printk(KERN_DEBUG "nxt200x: " args); \
-	} while (0)
-
-static int i2c_writebytes (struct nxt200x_state* state, u8 addr, u8 *buf, u8 len)
-{
-	int err;
-	struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = buf, .len = len };
-
-	if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
-		printk (KERN_WARNING "nxt200x: %s: i2c write error (addr 0x%02x, err == %i)\n",
-			__func__, addr, err);
-		return -EREMOTEIO;
-	}
-	return 0;
-}
-
-static int i2c_readbytes(struct nxt200x_state *state, u8 addr, u8 *buf, u8 len)
-{
-	int err;
-	struct i2c_msg msg = { .addr = addr, .flags = I2C_M_RD, .buf = buf, .len = len };
-
-	if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
-		printk (KERN_WARNING "nxt200x: %s: i2c read error (addr 0x%02x, err == %i)\n",
-			__func__, addr, err);
-		return -EREMOTEIO;
-	}
-	return 0;
-}
-
-static int nxt200x_writebytes (struct nxt200x_state* state, u8 reg,
-			       const u8 *buf, u8 len)
-{
-	u8 buf2 [len+1];
-	int err;
-	struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf2, .len = len + 1 };
-
-	buf2[0] = reg;
-	memcpy(&buf2[1], buf, len);
-
-	if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
-		printk (KERN_WARNING "nxt200x: %s: i2c write error (addr 0x%02x, err == %i)\n",
-			__func__, state->config->demod_address, err);
-		return -EREMOTEIO;
-	}
-	return 0;
-}
-
-static int nxt200x_readbytes(struct nxt200x_state *state, u8 reg, u8 *buf, u8 len)
-{
-	u8 reg2 [] = { reg };
-
-	struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = reg2, .len = 1 },
-			{ .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = buf, .len = len } };
-
-	int err;
-
-	if ((err = i2c_transfer (state->i2c, msg, 2)) != 2) {
-		printk (KERN_WARNING "nxt200x: %s: i2c read error (addr 0x%02x, err == %i)\n",
-			__func__, state->config->demod_address, err);
-		return -EREMOTEIO;
-	}
-	return 0;
-}
-
-static u16 nxt200x_crc(u16 crc, u8 c)
-{
-	u8 i;
-	u16 input = (u16) c & 0xFF;
-
-	input<<=8;
-	for(i=0; i<8; i++) {
-		if((crc^input) & 0x8000)
-			crc=(crc<<1)^CRC_CCIT_MASK;
-		else
-			crc<<=1;
-		input<<=1;
-	}
-	return crc;
-}
-
-static int nxt200x_writereg_multibyte (struct nxt200x_state* state, u8 reg, u8* data, u8 len)
-{
-	u8 attr, len2, buf;
-	dprintk("%s\n", __func__);
-
-	/* set mutli register register */
-	nxt200x_writebytes(state, 0x35, &reg, 1);
-
-	/* send the actual data */
-	nxt200x_writebytes(state, 0x36, data, len);
-
-	switch (state->demod_chip) {
-		case NXT2002:
-			len2 = len;
-			buf = 0x02;
-			break;
-		case NXT2004:
-			/* probably not right, but gives correct values */
-			attr = 0x02;
-			if (reg & 0x80) {
-				attr = attr << 1;
-				if (reg & 0x04)
-					attr = attr >> 1;
-			}
-			/* set write bit */
-			len2 = ((attr << 4) | 0x10) | len;
-			buf = 0x80;
-			break;
-		default:
-			return -EINVAL;
-			break;
-	}
-
-	/* set multi register length */
-	nxt200x_writebytes(state, 0x34, &len2, 1);
-
-	/* toggle the multireg write bit */
-	nxt200x_writebytes(state, 0x21, &buf, 1);
-
-	nxt200x_readbytes(state, 0x21, &buf, 1);
-
-	switch (state->demod_chip) {
-		case NXT2002:
-			if ((buf & 0x02) == 0)
-				return 0;
-			break;
-		case NXT2004:
-			if (buf == 0)
-				return 0;
-			break;
-		default:
-			return -EINVAL;
-			break;
-	}
-
-	printk(KERN_WARNING "nxt200x: Error writing multireg register 0x%02X\n",reg);
-
-	return 0;
-}
-
-static int nxt200x_readreg_multibyte (struct nxt200x_state* state, u8 reg, u8* data, u8 len)
-{
-	int i;
-	u8 buf, len2, attr;
-	dprintk("%s\n", __func__);
-
-	/* set mutli register register */
-	nxt200x_writebytes(state, 0x35, &reg, 1);
-
-	switch (state->demod_chip) {
-		case NXT2002:
-			/* set multi register length */
-			len2 = len & 0x80;
-			nxt200x_writebytes(state, 0x34, &len2, 1);
-
-			/* read the actual data */
-			nxt200x_readbytes(state, reg, data, len);
-			return 0;
-			break;
-		case NXT2004:
-			/* probably not right, but gives correct values */
-			attr = 0x02;
-			if (reg & 0x80) {
-				attr = attr << 1;
-				if (reg & 0x04)
-					attr = attr >> 1;
-			}
-
-			/* set multi register length */
-			len2 = (attr << 4) | len;
-			nxt200x_writebytes(state, 0x34, &len2, 1);
-
-			/* toggle the multireg bit*/
-			buf = 0x80;
-			nxt200x_writebytes(state, 0x21, &buf, 1);
-
-			/* read the actual data */
-			for(i = 0; i < len; i++) {
-				nxt200x_readbytes(state, 0x36 + i, &data[i], 1);
-			}
-			return 0;
-			break;
-		default:
-			return -EINVAL;
-			break;
-	}
-}
-
-static void nxt200x_microcontroller_stop (struct nxt200x_state* state)
-{
-	u8 buf, stopval, counter = 0;
-	dprintk("%s\n", __func__);
-
-	/* set correct stop value */
-	switch (state->demod_chip) {
-		case NXT2002:
-			stopval = 0x40;
-			break;
-		case NXT2004:
-			stopval = 0x10;
-			break;
-		default:
-			stopval = 0;
-			break;
-	}
-
-	buf = 0x80;
-	nxt200x_writebytes(state, 0x22, &buf, 1);
-
-	while (counter < 20) {
-		nxt200x_readbytes(state, 0x31, &buf, 1);
-		if (buf & stopval)
-			return;
-		msleep(10);
-		counter++;
-	}
-
-	printk(KERN_WARNING "nxt200x: Timeout waiting for nxt200x to stop. This is ok after firmware upload.\n");
-	return;
-}
-
-static void nxt200x_microcontroller_start (struct nxt200x_state* state)
-{
-	u8 buf;
-	dprintk("%s\n", __func__);
-
-	buf = 0x00;
-	nxt200x_writebytes(state, 0x22, &buf, 1);
-}
-
-static void nxt2004_microcontroller_init (struct nxt200x_state* state)
-{
-	u8 buf[9];
-	u8 counter = 0;
-	dprintk("%s\n", __func__);
-
-	buf[0] = 0x00;
-	nxt200x_writebytes(state, 0x2b, buf, 1);
-	buf[0] = 0x70;
-	nxt200x_writebytes(state, 0x34, buf, 1);
-	buf[0] = 0x04;
-	nxt200x_writebytes(state, 0x35, buf, 1);
-	buf[0] = 0x01; buf[1] = 0x23; buf[2] = 0x45; buf[3] = 0x67; buf[4] = 0x89;
-	buf[5] = 0xAB; buf[6] = 0xCD; buf[7] = 0xEF; buf[8] = 0xC0;
-	nxt200x_writebytes(state, 0x36, buf, 9);
-	buf[0] = 0x80;
-	nxt200x_writebytes(state, 0x21, buf, 1);
-
-	while (counter < 20) {
-		nxt200x_readbytes(state, 0x21, buf, 1);
-		if (buf[0] == 0)
-			return;
-		msleep(10);
-		counter++;
-	}
-
-	printk(KERN_WARNING "nxt200x: Timeout waiting for nxt2004 to init.\n");
-
-	return;
-}
-
-static int nxt200x_writetuner (struct nxt200x_state* state, u8* data)
-{
-	u8 buf, count = 0;
-
-	dprintk("%s\n", __func__);
-
-	dprintk("Tuner Bytes: %02X %02X %02X %02X\n", data[1], data[2], data[3], data[4]);
-
-	/* if NXT2004, write directly to tuner. if NXT2002, write through NXT chip.
-	 * direct write is required for Philips TUV1236D and ALPS TDHU2 */
-	switch (state->demod_chip) {
-		case NXT2004:
-			if (i2c_writebytes(state, data[0], data+1, 4))
-				printk(KERN_WARNING "nxt200x: error writing to tuner\n");
-			/* wait until we have a lock */
-			while (count < 20) {
-				i2c_readbytes(state, data[0], &buf, 1);
-				if (buf & 0x40)
-					return 0;
-				msleep(100);
-				count++;
-			}
-			printk("nxt2004: timeout waiting for tuner lock\n");
-			break;
-		case NXT2002:
-			/* set the i2c transfer speed to the tuner */
-			buf = 0x03;
-			nxt200x_writebytes(state, 0x20, &buf, 1);
-
-			/* setup to transfer 4 bytes via i2c */
-			buf = 0x04;
-			nxt200x_writebytes(state, 0x34, &buf, 1);
-
-			/* write actual tuner bytes */
-			nxt200x_writebytes(state, 0x36, data+1, 4);
-
-			/* set tuner i2c address */
-			buf = data[0] << 1;
-			nxt200x_writebytes(state, 0x35, &buf, 1);
-
-			/* write UC Opmode to begin transfer */
-			buf = 0x80;
-			nxt200x_writebytes(state, 0x21, &buf, 1);
-
-			while (count < 20) {
-				nxt200x_readbytes(state, 0x21, &buf, 1);
-				if ((buf & 0x80)== 0x00)
-					return 0;
-				msleep(100);
-				count++;
-			}
-			printk("nxt2002: timeout error writing tuner\n");
-			break;
-		default:
-			return -EINVAL;
-			break;
-	}
-	return 0;
-}
-
-static void nxt200x_agc_reset(struct nxt200x_state* state)
-{
-	u8 buf;
-	dprintk("%s\n", __func__);
-
-	switch (state->demod_chip) {
-		case NXT2002:
-			buf = 0x08;
-			nxt200x_writebytes(state, 0x08, &buf, 1);
-			buf = 0x00;
-			nxt200x_writebytes(state, 0x08, &buf, 1);
-			break;
-		case NXT2004:
-			nxt200x_readreg_multibyte(state, 0x08, &buf, 1);
-			buf = 0x08;
-			nxt200x_writereg_multibyte(state, 0x08, &buf, 1);
-			buf = 0x00;
-			nxt200x_writereg_multibyte(state, 0x08, &buf, 1);
-			break;
-		default:
-			break;
-	}
-	return;
-}
-
-static int nxt2002_load_firmware (struct dvb_frontend* fe, const struct firmware *fw)
-{
-
-	struct nxt200x_state* state = fe->demodulator_priv;
-	u8 buf[3], written = 0, chunkpos = 0;
-	u16 rambase, position, crc = 0;
-
-	dprintk("%s\n", __func__);
-	dprintk("Firmware is %zu bytes\n", fw->size);
-
-	/* Get the RAM base for this nxt2002 */
-	nxt200x_readbytes(state, 0x10, buf, 1);
-
-	if (buf[0] & 0x10)
-		rambase = 0x1000;
-	else
-		rambase = 0x0000;
-
-	dprintk("rambase on this nxt2002 is %04X\n", rambase);
-
-	/* Hold the micro in reset while loading firmware */
-	buf[0] = 0x80;
-	nxt200x_writebytes(state, 0x2B, buf, 1);
-
-	for (position = 0; position < fw->size; position++) {
-		if (written == 0) {
-			crc = 0;
-			chunkpos = 0x28;
-			buf[0] = ((rambase + position) >> 8);
-			buf[1] = (rambase + position) & 0xFF;
-			buf[2] = 0x81;
-			/* write starting address */
-			nxt200x_writebytes(state, 0x29, buf, 3);
-		}
-		written++;
-		chunkpos++;
-
-		if ((written % 4) == 0)
-			nxt200x_writebytes(state, chunkpos, &fw->data[position-3], 4);
-
-		crc = nxt200x_crc(crc, fw->data[position]);
-
-		if ((written == 255) || (position+1 == fw->size)) {
-			/* write remaining bytes of firmware */
-			nxt200x_writebytes(state, chunkpos+4-(written %4),
-				&fw->data[position-(written %4) + 1],
-				written %4);
-			buf[0] = crc << 8;
-			buf[1] = crc & 0xFF;
-
-			/* write crc */
-			nxt200x_writebytes(state, 0x2C, buf, 2);
-
-			/* do a read to stop things */
-			nxt200x_readbytes(state, 0x2A, buf, 1);
-
-			/* set transfer mode to complete */
-			buf[0] = 0x80;
-			nxt200x_writebytes(state, 0x2B, buf, 1);
-
-			written = 0;
-		}
-	}
-
-	return 0;
-};
-
-static int nxt2004_load_firmware (struct dvb_frontend* fe, const struct firmware *fw)
-{
-
-	struct nxt200x_state* state = fe->demodulator_priv;
-	u8 buf[3];
-	u16 rambase, position, crc=0;
-
-	dprintk("%s\n", __func__);
-	dprintk("Firmware is %zu bytes\n", fw->size);
-
-	/* set rambase */
-	rambase = 0x1000;
-
-	/* hold the micro in reset while loading firmware */
-	buf[0] = 0x80;
-	nxt200x_writebytes(state, 0x2B, buf,1);
-
-	/* calculate firmware CRC */
-	for (position = 0; position < fw->size; position++) {
-		crc = nxt200x_crc(crc, fw->data[position]);
-	}
-
-	buf[0] = rambase >> 8;
-	buf[1] = rambase & 0xFF;
-	buf[2] = 0x81;
-	/* write starting address */
-	nxt200x_writebytes(state,0x29,buf,3);
-
-	for (position = 0; position < fw->size;) {
-		nxt200x_writebytes(state, 0x2C, &fw->data[position],
-			fw->size-position > 255 ? 255 : fw->size-position);
-		position += (fw->size-position > 255 ? 255 : fw->size-position);
-	}
-	buf[0] = crc >> 8;
-	buf[1] = crc & 0xFF;
-
-	dprintk("firmware crc is 0x%02X 0x%02X\n", buf[0], buf[1]);
-
-	/* write crc */
-	nxt200x_writebytes(state, 0x2C, buf,2);
-
-	/* do a read to stop things */
-	nxt200x_readbytes(state, 0x2C, buf, 1);
-
-	/* set transfer mode to complete */
-	buf[0] = 0x80;
-	nxt200x_writebytes(state, 0x2B, buf,1);
-
-	return 0;
-};
-
-static int nxt200x_setup_frontend_parameters(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct nxt200x_state* state = fe->demodulator_priv;
-	u8 buf[5];
-
-	/* stop the micro first */
-	nxt200x_microcontroller_stop(state);
-
-	if (state->demod_chip == NXT2004) {
-		/* make sure demod is set to digital */
-		buf[0] = 0x04;
-		nxt200x_writebytes(state, 0x14, buf, 1);
-		buf[0] = 0x00;
-		nxt200x_writebytes(state, 0x17, buf, 1);
-	}
-
-	/* set additional params */
-	switch (p->modulation) {
-		case QAM_64:
-		case QAM_256:
-			/* Set punctured clock for QAM */
-			/* This is just a guess since I am unable to test it */
-			if (state->config->set_ts_params)
-				state->config->set_ts_params(fe, 1);
-			break;
-		case VSB_8:
-			/* Set non-punctured clock for VSB */
-			if (state->config->set_ts_params)
-				state->config->set_ts_params(fe, 0);
-			break;
-		default:
-			return -EINVAL;
-			break;
-	}
-
-	if (fe->ops.tuner_ops.calc_regs) {
-		/* get tuning information */
-		fe->ops.tuner_ops.calc_regs(fe, buf, 5);
-
-		/* write frequency information */
-		nxt200x_writetuner(state, buf);
-	}
-
-	/* reset the agc now that tuning has been completed */
-	nxt200x_agc_reset(state);
-
-	/* set target power level */
-	switch (p->modulation) {
-		case QAM_64:
-		case QAM_256:
-			buf[0] = 0x74;
-			break;
-		case VSB_8:
-			buf[0] = 0x70;
-			break;
-		default:
-			return -EINVAL;
-			break;
-	}
-	nxt200x_writebytes(state, 0x42, buf, 1);
-
-	/* configure sdm */
-	switch (state->demod_chip) {
-		case NXT2002:
-			buf[0] = 0x87;
-			break;
-		case NXT2004:
-			buf[0] = 0x07;
-			break;
-		default:
-			return -EINVAL;
-			break;
-	}
-	nxt200x_writebytes(state, 0x57, buf, 1);
-
-	/* write sdm1 input */
-	buf[0] = 0x10;
-	buf[1] = 0x00;
-	switch (state->demod_chip) {
-		case NXT2002:
-			nxt200x_writereg_multibyte(state, 0x58, buf, 2);
-			break;
-		case NXT2004:
-			nxt200x_writebytes(state, 0x58, buf, 2);
-			break;
-		default:
-			return -EINVAL;
-			break;
-	}
-
-	/* write sdmx input */
-	switch (p->modulation) {
-		case QAM_64:
-				buf[0] = 0x68;
-				break;
-		case QAM_256:
-				buf[0] = 0x64;
-				break;
-		case VSB_8:
-				buf[0] = 0x60;
-				break;
-		default:
-				return -EINVAL;
-				break;
-	}
-	buf[1] = 0x00;
-	switch (state->demod_chip) {
-		case NXT2002:
-			nxt200x_writereg_multibyte(state, 0x5C, buf, 2);
-			break;
-		case NXT2004:
-			nxt200x_writebytes(state, 0x5C, buf, 2);
-			break;
-		default:
-			return -EINVAL;
-			break;
-	}
-
-	/* write adc power lpf fc */
-	buf[0] = 0x05;
-	nxt200x_writebytes(state, 0x43, buf, 1);
-
-	if (state->demod_chip == NXT2004) {
-		/* write ??? */
-		buf[0] = 0x00;
-		buf[1] = 0x00;
-		nxt200x_writebytes(state, 0x46, buf, 2);
-	}
-
-	/* write accumulator2 input */
-	buf[0] = 0x80;
-	buf[1] = 0x00;
-	switch (state->demod_chip) {
-		case NXT2002:
-			nxt200x_writereg_multibyte(state, 0x4B, buf, 2);
-			break;
-		case NXT2004:
-			nxt200x_writebytes(state, 0x4B, buf, 2);
-			break;
-		default:
-			return -EINVAL;
-			break;
-	}
-
-	/* write kg1 */
-	buf[0] = 0x00;
-	nxt200x_writebytes(state, 0x4D, buf, 1);
-
-	/* write sdm12 lpf fc */
-	buf[0] = 0x44;
-	nxt200x_writebytes(state, 0x55, buf, 1);
-
-	/* write agc control reg */
-	buf[0] = 0x04;
-	nxt200x_writebytes(state, 0x41, buf, 1);
-
-	if (state->demod_chip == NXT2004) {
-		nxt200x_readreg_multibyte(state, 0x80, buf, 1);
-		buf[0] = 0x24;
-		nxt200x_writereg_multibyte(state, 0x80, buf, 1);
-
-		/* soft reset? */
-		nxt200x_readreg_multibyte(state, 0x08, buf, 1);
-		buf[0] = 0x10;
-		nxt200x_writereg_multibyte(state, 0x08, buf, 1);
-		nxt200x_readreg_multibyte(state, 0x08, buf, 1);
-		buf[0] = 0x00;
-		nxt200x_writereg_multibyte(state, 0x08, buf, 1);
-
-		nxt200x_readreg_multibyte(state, 0x80, buf, 1);
-		buf[0] = 0x04;
-		nxt200x_writereg_multibyte(state, 0x80, buf, 1);
-		buf[0] = 0x00;
-		nxt200x_writereg_multibyte(state, 0x81, buf, 1);
-		buf[0] = 0x80; buf[1] = 0x00; buf[2] = 0x00;
-		nxt200x_writereg_multibyte(state, 0x82, buf, 3);
-		nxt200x_readreg_multibyte(state, 0x88, buf, 1);
-		buf[0] = 0x11;
-		nxt200x_writereg_multibyte(state, 0x88, buf, 1);
-		nxt200x_readreg_multibyte(state, 0x80, buf, 1);
-		buf[0] = 0x44;
-		nxt200x_writereg_multibyte(state, 0x80, buf, 1);
-	}
-
-	/* write agc ucgp0 */
-	switch (p->modulation) {
-		case QAM_64:
-				buf[0] = 0x02;
-				break;
-		case QAM_256:
-				buf[0] = 0x03;
-				break;
-		case VSB_8:
-				buf[0] = 0x00;
-				break;
-		default:
-				return -EINVAL;
-				break;
-	}
-	nxt200x_writebytes(state, 0x30, buf, 1);
-
-	/* write agc control reg */
-	buf[0] = 0x00;
-	nxt200x_writebytes(state, 0x41, buf, 1);
-
-	/* write accumulator2 input */
-	buf[0] = 0x80;
-	buf[1] = 0x00;
-	switch (state->demod_chip) {
-		case NXT2002:
-			nxt200x_writereg_multibyte(state, 0x49, buf, 2);
-			nxt200x_writereg_multibyte(state, 0x4B, buf, 2);
-			break;
-		case NXT2004:
-			nxt200x_writebytes(state, 0x49, buf, 2);
-			nxt200x_writebytes(state, 0x4B, buf, 2);
-			break;
-		default:
-			return -EINVAL;
-			break;
-	}
-
-	/* write agc control reg */
-	buf[0] = 0x04;
-	nxt200x_writebytes(state, 0x41, buf, 1);
-
-	nxt200x_microcontroller_start(state);
-
-	if (state->demod_chip == NXT2004) {
-		nxt2004_microcontroller_init(state);
-
-		/* ???? */
-		buf[0] = 0xF0;
-		buf[1] = 0x00;
-		nxt200x_writebytes(state, 0x5C, buf, 2);
-	}
-
-	/* adjacent channel detection should be done here, but I don't
-	have any stations with this need so I cannot test it */
-
-	return 0;
-}
-
-static int nxt200x_read_status(struct dvb_frontend* fe, fe_status_t* status)
-{
-	struct nxt200x_state* state = fe->demodulator_priv;
-	u8 lock;
-	nxt200x_readbytes(state, 0x31, &lock, 1);
-
-	*status = 0;
-	if (lock & 0x20) {
-		*status |= FE_HAS_SIGNAL;
-		*status |= FE_HAS_CARRIER;
-		*status |= FE_HAS_VITERBI;
-		*status |= FE_HAS_SYNC;
-		*status |= FE_HAS_LOCK;
-	}
-	return 0;
-}
-
-static int nxt200x_read_ber(struct dvb_frontend* fe, u32* ber)
-{
-	struct nxt200x_state* state = fe->demodulator_priv;
-	u8 b[3];
-
-	nxt200x_readreg_multibyte(state, 0xE6, b, 3);
-
-	*ber = ((b[0] << 8) + b[1]) * 8;
-
-	return 0;
-}
-
-static int nxt200x_read_signal_strength(struct dvb_frontend* fe, u16* strength)
-{
-	struct nxt200x_state* state = fe->demodulator_priv;
-	u8 b[2];
-	u16 temp = 0;
-
-	/* setup to read cluster variance */
-	b[0] = 0x00;
-	nxt200x_writebytes(state, 0xA1, b, 1);
-
-	/* get multreg val */
-	nxt200x_readreg_multibyte(state, 0xA6, b, 2);
-
-	temp = (b[0] << 8) | b[1];
-	*strength = ((0x7FFF - temp) & 0x0FFF) * 16;
-
-	return 0;
-}
-
-static int nxt200x_read_snr(struct dvb_frontend* fe, u16* snr)
-{
-
-	struct nxt200x_state* state = fe->demodulator_priv;
-	u8 b[2];
-	u16 temp = 0, temp2;
-	u32 snrdb = 0;
-
-	/* setup to read cluster variance */
-	b[0] = 0x00;
-	nxt200x_writebytes(state, 0xA1, b, 1);
-
-	/* get multreg val from 0xA6 */
-	nxt200x_readreg_multibyte(state, 0xA6, b, 2);
-
-	temp = (b[0] << 8) | b[1];
-	temp2 = 0x7FFF - temp;
-
-	/* snr will be in db */
-	if (temp2 > 0x7F00)
-		snrdb = 1000*24 + ( 1000*(30-24) * ( temp2 - 0x7F00 ) / ( 0x7FFF - 0x7F00 ) );
-	else if (temp2 > 0x7EC0)
-		snrdb = 1000*18 + ( 1000*(24-18) * ( temp2 - 0x7EC0 ) / ( 0x7F00 - 0x7EC0 ) );
-	else if (temp2 > 0x7C00)
-		snrdb = 1000*12 + ( 1000*(18-12) * ( temp2 - 0x7C00 ) / ( 0x7EC0 - 0x7C00 ) );
-	else
-		snrdb = 1000*0 + ( 1000*(12-0) * ( temp2 - 0 ) / ( 0x7C00 - 0 ) );
-
-	/* the value reported back from the frontend will be FFFF=32db 0000=0db */
-	*snr = snrdb * (0xFFFF/32000);
-
-	return 0;
-}
-
-static int nxt200x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
-{
-	struct nxt200x_state* state = fe->demodulator_priv;
-	u8 b[3];
-
-	nxt200x_readreg_multibyte(state, 0xE6, b, 3);
-	*ucblocks = b[2];
-
-	return 0;
-}
-
-static int nxt200x_sleep(struct dvb_frontend* fe)
-{
-	return 0;
-}
-
-static int nxt2002_init(struct dvb_frontend* fe)
-{
-	struct nxt200x_state* state = fe->demodulator_priv;
-	const struct firmware *fw;
-	int ret;
-	u8 buf[2];
-
-	/* request the firmware, this will block until someone uploads it */
-	printk("nxt2002: Waiting for firmware upload (%s)...\n", NXT2002_DEFAULT_FIRMWARE);
-	ret = request_firmware(&fw, NXT2002_DEFAULT_FIRMWARE,
-			       state->i2c->dev.parent);
-	printk("nxt2002: Waiting for firmware upload(2)...\n");
-	if (ret) {
-		printk("nxt2002: No firmware uploaded (timeout or file not found?)\n");
-		return ret;
-	}
-
-	ret = nxt2002_load_firmware(fe, fw);
-	release_firmware(fw);
-	if (ret) {
-		printk("nxt2002: Writing firmware to device failed\n");
-		return ret;
-	}
-	printk("nxt2002: Firmware upload complete\n");
-
-	/* Put the micro into reset */
-	nxt200x_microcontroller_stop(state);
-
-	/* ensure transfer is complete */
-	buf[0]=0x00;
-	nxt200x_writebytes(state, 0x2B, buf, 1);
-
-	/* Put the micro into reset for real this time */
-	nxt200x_microcontroller_stop(state);
-
-	/* soft reset everything (agc,frontend,eq,fec)*/
-	buf[0] = 0x0F;
-	nxt200x_writebytes(state, 0x08, buf, 1);
-	buf[0] = 0x00;
-	nxt200x_writebytes(state, 0x08, buf, 1);
-
-	/* write agc sdm configure */
-	buf[0] = 0xF1;
-	nxt200x_writebytes(state, 0x57, buf, 1);
-
-	/* write mod output format */
-	buf[0] = 0x20;
-	nxt200x_writebytes(state, 0x09, buf, 1);
-
-	/* write fec mpeg mode */
-	buf[0] = 0x7E;
-	buf[1] = 0x00;
-	nxt200x_writebytes(state, 0xE9, buf, 2);
-
-	/* write mux selection */
-	buf[0] = 0x00;
-	nxt200x_writebytes(state, 0xCC, buf, 1);
-
-	return 0;
-}
-
-static int nxt2004_init(struct dvb_frontend* fe)
-{
-	struct nxt200x_state* state = fe->demodulator_priv;
-	const struct firmware *fw;
-	int ret;
-	u8 buf[3];
-
-	/* ??? */
-	buf[0]=0x00;
-	nxt200x_writebytes(state, 0x1E, buf, 1);
-
-	/* request the firmware, this will block until someone uploads it */
-	printk("nxt2004: Waiting for firmware upload (%s)...\n", NXT2004_DEFAULT_FIRMWARE);
-	ret = request_firmware(&fw, NXT2004_DEFAULT_FIRMWARE,
-			       state->i2c->dev.parent);
-	printk("nxt2004: Waiting for firmware upload(2)...\n");
-	if (ret) {
-		printk("nxt2004: No firmware uploaded (timeout or file not found?)\n");
-		return ret;
-	}
-
-	ret = nxt2004_load_firmware(fe, fw);
-	release_firmware(fw);
-	if (ret) {
-		printk("nxt2004: Writing firmware to device failed\n");
-		return ret;
-	}
-	printk("nxt2004: Firmware upload complete\n");
-
-	/* ensure transfer is complete */
-	buf[0] = 0x01;
-	nxt200x_writebytes(state, 0x19, buf, 1);
-
-	nxt2004_microcontroller_init(state);
-	nxt200x_microcontroller_stop(state);
-	nxt200x_microcontroller_stop(state);
-	nxt2004_microcontroller_init(state);
-	nxt200x_microcontroller_stop(state);
-
-	/* soft reset everything (agc,frontend,eq,fec)*/
-	buf[0] = 0xFF;
-	nxt200x_writereg_multibyte(state, 0x08, buf, 1);
-	buf[0] = 0x00;
-	nxt200x_writereg_multibyte(state, 0x08, buf, 1);
-
-	/* write agc sdm configure */
-	buf[0] = 0xD7;
-	nxt200x_writebytes(state, 0x57, buf, 1);
-
-	/* ???*/
-	buf[0] = 0x07;
-	buf[1] = 0xfe;
-	nxt200x_writebytes(state, 0x35, buf, 2);
-	buf[0] = 0x12;
-	nxt200x_writebytes(state, 0x34, buf, 1);
-	buf[0] = 0x80;
-	nxt200x_writebytes(state, 0x21, buf, 1);
-
-	/* ???*/
-	buf[0] = 0x21;
-	nxt200x_writebytes(state, 0x0A, buf, 1);
-
-	/* ???*/
-	buf[0] = 0x01;
-	nxt200x_writereg_multibyte(state, 0x80, buf, 1);
-
-	/* write fec mpeg mode */
-	buf[0] = 0x7E;
-	buf[1] = 0x00;
-	nxt200x_writebytes(state, 0xE9, buf, 2);
-
-	/* write mux selection */
-	buf[0] = 0x00;
-	nxt200x_writebytes(state, 0xCC, buf, 1);
-
-	/* ???*/
-	nxt200x_readreg_multibyte(state, 0x80, buf, 1);
-	buf[0] = 0x00;
-	nxt200x_writereg_multibyte(state, 0x80, buf, 1);
-
-	/* soft reset? */
-	nxt200x_readreg_multibyte(state, 0x08, buf, 1);
-	buf[0] = 0x10;
-	nxt200x_writereg_multibyte(state, 0x08, buf, 1);
-	nxt200x_readreg_multibyte(state, 0x08, buf, 1);
-	buf[0] = 0x00;
-	nxt200x_writereg_multibyte(state, 0x08, buf, 1);
-
-	/* ???*/
-	nxt200x_readreg_multibyte(state, 0x80, buf, 1);
-	buf[0] = 0x01;
-	nxt200x_writereg_multibyte(state, 0x80, buf, 1);
-	buf[0] = 0x70;
-	nxt200x_writereg_multibyte(state, 0x81, buf, 1);
-	buf[0] = 0x31; buf[1] = 0x5E; buf[2] = 0x66;
-	nxt200x_writereg_multibyte(state, 0x82, buf, 3);
-
-	nxt200x_readreg_multibyte(state, 0x88, buf, 1);
-	buf[0] = 0x11;
-	nxt200x_writereg_multibyte(state, 0x88, buf, 1);
-	nxt200x_readreg_multibyte(state, 0x80, buf, 1);
-	buf[0] = 0x40;
-	nxt200x_writereg_multibyte(state, 0x80, buf, 1);
-
-	nxt200x_readbytes(state, 0x10, buf, 1);
-	buf[0] = 0x10;
-	nxt200x_writebytes(state, 0x10, buf, 1);
-	nxt200x_readbytes(state, 0x0A, buf, 1);
-	buf[0] = 0x21;
-	nxt200x_writebytes(state, 0x0A, buf, 1);
-
-	nxt2004_microcontroller_init(state);
-
-	buf[0] = 0x21;
-	nxt200x_writebytes(state, 0x0A, buf, 1);
-	buf[0] = 0x7E;
-	nxt200x_writebytes(state, 0xE9, buf, 1);
-	buf[0] = 0x00;
-	nxt200x_writebytes(state, 0xEA, buf, 1);
-
-	nxt200x_readreg_multibyte(state, 0x80, buf, 1);
-	buf[0] = 0x00;
-	nxt200x_writereg_multibyte(state, 0x80, buf, 1);
-	nxt200x_readreg_multibyte(state, 0x80, buf, 1);
-	buf[0] = 0x00;
-	nxt200x_writereg_multibyte(state, 0x80, buf, 1);
-
-	/* soft reset? */
-	nxt200x_readreg_multibyte(state, 0x08, buf, 1);
-	buf[0] = 0x10;
-	nxt200x_writereg_multibyte(state, 0x08, buf, 1);
-	nxt200x_readreg_multibyte(state, 0x08, buf, 1);
-	buf[0] = 0x00;
-	nxt200x_writereg_multibyte(state, 0x08, buf, 1);
-
-	nxt200x_readreg_multibyte(state, 0x80, buf, 1);
-	buf[0] = 0x04;
-	nxt200x_writereg_multibyte(state, 0x80, buf, 1);
-	buf[0] = 0x00;
-	nxt200x_writereg_multibyte(state, 0x81, buf, 1);
-	buf[0] = 0x80; buf[1] = 0x00; buf[2] = 0x00;
-	nxt200x_writereg_multibyte(state, 0x82, buf, 3);
-
-	nxt200x_readreg_multibyte(state, 0x88, buf, 1);
-	buf[0] = 0x11;
-	nxt200x_writereg_multibyte(state, 0x88, buf, 1);
-
-	nxt200x_readreg_multibyte(state, 0x80, buf, 1);
-	buf[0] = 0x44;
-	nxt200x_writereg_multibyte(state, 0x80, buf, 1);
-
-	/* initialize tuner */
-	nxt200x_readbytes(state, 0x10, buf, 1);
-	buf[0] = 0x12;
-	nxt200x_writebytes(state, 0x10, buf, 1);
-	buf[0] = 0x04;
-	nxt200x_writebytes(state, 0x13, buf, 1);
-	buf[0] = 0x00;
-	nxt200x_writebytes(state, 0x16, buf, 1);
-	buf[0] = 0x04;
-	nxt200x_writebytes(state, 0x14, buf, 1);
-	buf[0] = 0x00;
-	nxt200x_writebytes(state, 0x14, buf, 1);
-	nxt200x_writebytes(state, 0x17, buf, 1);
-	nxt200x_writebytes(state, 0x14, buf, 1);
-	nxt200x_writebytes(state, 0x17, buf, 1);
-
-	return 0;
-}
-
-static int nxt200x_init(struct dvb_frontend* fe)
-{
-	struct nxt200x_state* state = fe->demodulator_priv;
-	int ret = 0;
-
-	if (!state->initialised) {
-		switch (state->demod_chip) {
-			case NXT2002:
-				ret = nxt2002_init(fe);
-				break;
-			case NXT2004:
-				ret = nxt2004_init(fe);
-				break;
-			default:
-				return -EINVAL;
-				break;
-		}
-		state->initialised = 1;
-	}
-	return ret;
-}
-
-static int nxt200x_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings)
-{
-	fesettings->min_delay_ms = 500;
-	fesettings->step_size = 0;
-	fesettings->max_drift = 0;
-	return 0;
-}
-
-static void nxt200x_release(struct dvb_frontend* fe)
-{
-	struct nxt200x_state* state = fe->demodulator_priv;
-	kfree(state);
-}
-
-static struct dvb_frontend_ops nxt200x_ops;
-
-struct dvb_frontend* nxt200x_attach(const struct nxt200x_config* config,
-				   struct i2c_adapter* i2c)
-{
-	struct nxt200x_state* state = NULL;
-	u8 buf [] = {0,0,0,0,0};
-
-	/* allocate memory for the internal state */
-	state = kzalloc(sizeof(struct nxt200x_state), GFP_KERNEL);
-	if (state == NULL)
-		goto error;
-
-	/* setup the state */
-	state->config = config;
-	state->i2c = i2c;
-	state->initialised = 0;
-
-	/* read card id */
-	nxt200x_readbytes(state, 0x00, buf, 5);
-	dprintk("NXT info: %02X %02X %02X %02X %02X\n",
-		buf[0], buf[1], buf[2],	buf[3], buf[4]);
-
-	/* set demod chip */
-	switch (buf[0]) {
-		case 0x04:
-			state->demod_chip = NXT2002;
-			printk("nxt200x: NXT2002 Detected\n");
-			break;
-		case 0x05:
-			state->demod_chip = NXT2004;
-			printk("nxt200x: NXT2004 Detected\n");
-			break;
-		default:
-			goto error;
-	}
-
-	/* make sure demod chip is supported */
-	switch (state->demod_chip) {
-		case NXT2002:
-			if (buf[0] != 0x04) goto error;		/* device id */
-			if (buf[1] != 0x02) goto error;		/* fab id */
-			if (buf[2] != 0x11) goto error;		/* month */
-			if (buf[3] != 0x20) goto error;		/* year msb */
-			if (buf[4] != 0x00) goto error;		/* year lsb */
-			break;
-		case NXT2004:
-			if (buf[0] != 0x05) goto error;		/* device id */
-			break;
-		default:
-			goto error;
-	}
-
-	/* create dvb_frontend */
-	memcpy(&state->frontend.ops, &nxt200x_ops, sizeof(struct dvb_frontend_ops));
-	state->frontend.demodulator_priv = state;
-	return &state->frontend;
-
-error:
-	kfree(state);
-	printk("Unknown/Unsupported NXT chip: %02X %02X %02X %02X %02X\n",
-		buf[0], buf[1], buf[2], buf[3], buf[4]);
-	return NULL;
-}
-
-static struct dvb_frontend_ops nxt200x_ops = {
-	.delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
-	.info = {
-		.name = "Nextwave NXT200X VSB/QAM frontend",
-		.frequency_min =  54000000,
-		.frequency_max = 860000000,
-		.frequency_stepsize = 166666,	/* stepsize is just a guess */
-		.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_FEC_AUTO |
-			FE_CAN_8VSB | FE_CAN_QAM_64 | FE_CAN_QAM_256
-	},
-
-	.release = nxt200x_release,
-
-	.init = nxt200x_init,
-	.sleep = nxt200x_sleep,
-
-	.set_frontend = nxt200x_setup_frontend_parameters,
-	.get_tune_settings = nxt200x_get_tune_settings,
-
-	.read_status = nxt200x_read_status,
-	.read_ber = nxt200x_read_ber,
-	.read_signal_strength = nxt200x_read_signal_strength,
-	.read_snr = nxt200x_read_snr,
-	.read_ucblocks = nxt200x_read_ucblocks,
-};
-
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
-
-MODULE_DESCRIPTION("NXT200X (ATSC 8VSB & ITU-T J.83 AnnexB 64/256 QAM) Demodulator Driver");
-MODULE_AUTHOR("Kirk Lapray, Michael Krufky, Jean-Francois Thibert, and Taylor Jacob");
-MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(nxt200x_attach);
-
diff --git a/drivers/media/dvb/frontends/nxt200x.h b/drivers/media/dvb/frontends/nxt200x.h
deleted file mode 100644
index f3c8458..0000000
--- a/drivers/media/dvb/frontends/nxt200x.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- *    Support for NXT2002 and NXT2004 - VSB/QAM
- *
- *    Copyright (C) 2005 Kirk Lapray (kirk.lapray@gmail.com)
- *    based on nxt2002 by Taylor Jacob <rtjacob@earthlink.net>
- *    and nxt2004 by Jean-Francois Thibert (jeanfrancois@sagetv.com)
- *
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
-*/
-
-#ifndef NXT200X_H
-#define NXT200X_H
-
-#include <linux/dvb/frontend.h>
-#include <linux/firmware.h>
-
-typedef enum nxt_chip_t {
-		NXTUNDEFINED,
-		NXT2002,
-		NXT2004
-}nxt_chip_type;
-
-struct nxt200x_config
-{
-	/* the demodulator's i2c address */
-	u8 demod_address;
-
-	/* need to set device param for start_dma */
-	int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured);
-};
-
-#if defined(CONFIG_DVB_NXT200X) || (defined(CONFIG_DVB_NXT200X_MODULE) && defined(MODULE))
-extern struct dvb_frontend* nxt200x_attach(const struct nxt200x_config* config,
-					   struct i2c_adapter* i2c);
-#else
-static inline struct dvb_frontend* nxt200x_attach(const struct nxt200x_config* config,
-					   struct i2c_adapter* i2c)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif // CONFIG_DVB_NXT200X
-
-#endif /* NXT200X_H */
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/dvb/frontends/nxt6000.c b/drivers/media/dvb/frontends/nxt6000.c
deleted file mode 100644
index 90ae6c7..0000000
--- a/drivers/media/dvb/frontends/nxt6000.c
+++ /dev/null
@@ -1,616 +0,0 @@
-/*
-	NxtWave Communications - NXT6000 demodulator driver
-
-    Copyright (C) 2002-2003 Florian Schirmer <jolt@tuxbox.org>
-    Copyright (C) 2003 Paul Andreassen <paul@andreassen.com.au>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You 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/kernel.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-
-#include "dvb_frontend.h"
-#include "nxt6000_priv.h"
-#include "nxt6000.h"
-
-
-
-struct nxt6000_state {
-	struct i2c_adapter* i2c;
-	/* configuration settings */
-	const struct nxt6000_config* config;
-	struct dvb_frontend frontend;
-};
-
-static int debug;
-#define dprintk if (debug) printk
-
-static int nxt6000_writereg(struct nxt6000_state* state, u8 reg, u8 data)
-{
-	u8 buf[] = { reg, data };
-	struct i2c_msg msg = {.addr = state->config->demod_address,.flags = 0,.buf = buf,.len = 2 };
-	int ret;
-
-	if ((ret = i2c_transfer(state->i2c, &msg, 1)) != 1)
-		dprintk("nxt6000: nxt6000_write error (reg: 0x%02X, data: 0x%02X, ret: %d)\n", reg, data, ret);
-
-	return (ret != 1) ? -EIO : 0;
-}
-
-static u8 nxt6000_readreg(struct nxt6000_state* state, u8 reg)
-{
-	int ret;
-	u8 b0[] = { reg };
-	u8 b1[] = { 0 };
-	struct i2c_msg msgs[] = {
-		{.addr = state->config->demod_address,.flags = 0,.buf = b0,.len = 1},
-		{.addr = state->config->demod_address,.flags = I2C_M_RD,.buf = b1,.len = 1}
-	};
-
-	ret = i2c_transfer(state->i2c, msgs, 2);
-
-	if (ret != 2)
-		dprintk("nxt6000: nxt6000_read error (reg: 0x%02X, ret: %d)\n", reg, ret);
-
-	return b1[0];
-}
-
-static void nxt6000_reset(struct nxt6000_state* state)
-{
-	u8 val;
-
-	val = nxt6000_readreg(state, OFDM_COR_CTL);
-
-	nxt6000_writereg(state, OFDM_COR_CTL, val & ~COREACT);
-	nxt6000_writereg(state, OFDM_COR_CTL, val | COREACT);
-}
-
-static int nxt6000_set_bandwidth(struct nxt6000_state *state, u32 bandwidth)
-{
-	u16 nominal_rate;
-	int result;
-
-	switch (bandwidth) {
-	case 6000000:
-		nominal_rate = 0x55B7;
-		break;
-
-	case 7000000:
-		nominal_rate = 0x6400;
-		break;
-
-	case 8000000:
-		nominal_rate = 0x7249;
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	if ((result = nxt6000_writereg(state, OFDM_TRL_NOMINALRATE_1, nominal_rate & 0xFF)) < 0)
-		return result;
-
-	return nxt6000_writereg(state, OFDM_TRL_NOMINALRATE_2, (nominal_rate >> 8) & 0xFF);
-}
-
-static int nxt6000_set_guard_interval(struct nxt6000_state* state, fe_guard_interval_t guard_interval)
-{
-	switch (guard_interval) {
-
-	case GUARD_INTERVAL_1_32:
-		return nxt6000_writereg(state, OFDM_COR_MODEGUARD, 0x00 | (nxt6000_readreg(state, OFDM_COR_MODEGUARD) & ~0x03));
-
-	case GUARD_INTERVAL_1_16:
-		return nxt6000_writereg(state, OFDM_COR_MODEGUARD, 0x01 | (nxt6000_readreg(state, OFDM_COR_MODEGUARD) & ~0x03));
-
-	case GUARD_INTERVAL_AUTO:
-	case GUARD_INTERVAL_1_8:
-		return nxt6000_writereg(state, OFDM_COR_MODEGUARD, 0x02 | (nxt6000_readreg(state, OFDM_COR_MODEGUARD) & ~0x03));
-
-	case GUARD_INTERVAL_1_4:
-		return nxt6000_writereg(state, OFDM_COR_MODEGUARD, 0x03 | (nxt6000_readreg(state, OFDM_COR_MODEGUARD) & ~0x03));
-
-	default:
-		return -EINVAL;
-	}
-}
-
-static int nxt6000_set_inversion(struct nxt6000_state* state, fe_spectral_inversion_t inversion)
-{
-	switch (inversion) {
-
-	case INVERSION_OFF:
-		return nxt6000_writereg(state, OFDM_ITB_CTL, 0x00);
-
-	case INVERSION_ON:
-		return nxt6000_writereg(state, OFDM_ITB_CTL, ITBINV);
-
-	default:
-		return -EINVAL;
-
-	}
-}
-
-static int nxt6000_set_transmission_mode(struct nxt6000_state* state, fe_transmit_mode_t transmission_mode)
-{
-	int result;
-
-	switch (transmission_mode) {
-
-	case TRANSMISSION_MODE_2K:
-		if ((result = nxt6000_writereg(state, EN_DMD_RACQ, 0x00 | (nxt6000_readreg(state, EN_DMD_RACQ) & ~0x03))) < 0)
-			return result;
-
-		return nxt6000_writereg(state, OFDM_COR_MODEGUARD, (0x00 << 2) | (nxt6000_readreg(state, OFDM_COR_MODEGUARD) & ~0x04));
-
-	case TRANSMISSION_MODE_8K:
-	case TRANSMISSION_MODE_AUTO:
-		if ((result = nxt6000_writereg(state, EN_DMD_RACQ, 0x02 | (nxt6000_readreg(state, EN_DMD_RACQ) & ~0x03))) < 0)
-			return result;
-
-		return nxt6000_writereg(state, OFDM_COR_MODEGUARD, (0x01 << 2) | (nxt6000_readreg(state, OFDM_COR_MODEGUARD) & ~0x04));
-
-	default:
-		return -EINVAL;
-
-	}
-}
-
-static void nxt6000_setup(struct dvb_frontend* fe)
-{
-	struct nxt6000_state* state = fe->demodulator_priv;
-
-	nxt6000_writereg(state, RS_COR_SYNC_PARAM, SYNC_PARAM);
-	nxt6000_writereg(state, BER_CTRL, /*(1 << 2) | */ (0x01 << 1) | 0x01);
-	nxt6000_writereg(state, VIT_BERTIME_2, 0x00);  // BER Timer = 0x000200 * 256 = 131072 bits
-	nxt6000_writereg(state, VIT_BERTIME_1, 0x02);  //
-	nxt6000_writereg(state, VIT_BERTIME_0, 0x00);  //
-	nxt6000_writereg(state, VIT_COR_INTEN, 0x98); // Enable BER interrupts
-	nxt6000_writereg(state, VIT_COR_CTL, 0x82);   // Enable BER measurement
-	nxt6000_writereg(state, VIT_COR_CTL, VIT_COR_RESYNC | 0x02 );
-	nxt6000_writereg(state, OFDM_COR_CTL, (0x01 << 5) | (nxt6000_readreg(state, OFDM_COR_CTL) & 0x0F));
-	nxt6000_writereg(state, OFDM_COR_MODEGUARD, FORCEMODE8K | 0x02);
-	nxt6000_writereg(state, OFDM_AGC_CTL, AGCLAST | INITIAL_AGC_BW);
-	nxt6000_writereg(state, OFDM_ITB_FREQ_1, 0x06);
-	nxt6000_writereg(state, OFDM_ITB_FREQ_2, 0x31);
-	nxt6000_writereg(state, OFDM_CAS_CTL, (0x01 << 7) | (0x02 << 3) | 0x04);
-	nxt6000_writereg(state, CAS_FREQ, 0xBB);	/* CHECKME */
-	nxt6000_writereg(state, OFDM_SYR_CTL, 1 << 2);
-	nxt6000_writereg(state, OFDM_PPM_CTL_1, PPM256);
-	nxt6000_writereg(state, OFDM_TRL_NOMINALRATE_1, 0x49);
-	nxt6000_writereg(state, OFDM_TRL_NOMINALRATE_2, 0x72);
-	nxt6000_writereg(state, ANALOG_CONTROL_0, 1 << 5);
-	nxt6000_writereg(state, EN_DMD_RACQ, (1 << 7) | (3 << 4) | 2);
-	nxt6000_writereg(state, DIAG_CONFIG, TB_SET);
-
-	if (state->config->clock_inversion)
-		nxt6000_writereg(state, SUB_DIAG_MODE_SEL, CLKINVERSION);
-	else
-		nxt6000_writereg(state, SUB_DIAG_MODE_SEL, 0);
-
-	nxt6000_writereg(state, TS_FORMAT, 0);
-}
-
-static void nxt6000_dump_status(struct nxt6000_state *state)
-{
-	u8 val;
-
-/*
-	printk("RS_COR_STAT: 0x%02X\n", nxt6000_readreg(fe, RS_COR_STAT));
-	printk("VIT_SYNC_STATUS: 0x%02X\n", nxt6000_readreg(fe, VIT_SYNC_STATUS));
-	printk("OFDM_COR_STAT: 0x%02X\n", nxt6000_readreg(fe, OFDM_COR_STAT));
-	printk("OFDM_SYR_STAT: 0x%02X\n", nxt6000_readreg(fe, OFDM_SYR_STAT));
-	printk("OFDM_TPS_RCVD_1: 0x%02X\n", nxt6000_readreg(fe, OFDM_TPS_RCVD_1));
-	printk("OFDM_TPS_RCVD_2: 0x%02X\n", nxt6000_readreg(fe, OFDM_TPS_RCVD_2));
-	printk("OFDM_TPS_RCVD_3: 0x%02X\n", nxt6000_readreg(fe, OFDM_TPS_RCVD_3));
-	printk("OFDM_TPS_RCVD_4: 0x%02X\n", nxt6000_readreg(fe, OFDM_TPS_RCVD_4));
-	printk("OFDM_TPS_RESERVED_1: 0x%02X\n", nxt6000_readreg(fe, OFDM_TPS_RESERVED_1));
-	printk("OFDM_TPS_RESERVED_2: 0x%02X\n", nxt6000_readreg(fe, OFDM_TPS_RESERVED_2));
-*/
-	printk("NXT6000 status:");
-
-	val = nxt6000_readreg(state, RS_COR_STAT);
-
-	printk(" DATA DESCR LOCK: %d,", val & 0x01);
-	printk(" DATA SYNC LOCK: %d,", (val >> 1) & 0x01);
-
-	val = nxt6000_readreg(state, VIT_SYNC_STATUS);
-
-	printk(" VITERBI LOCK: %d,", (val >> 7) & 0x01);
-
-	switch ((val >> 4) & 0x07) {
-
-	case 0x00:
-		printk(" VITERBI CODERATE: 1/2,");
-		break;
-
-	case 0x01:
-		printk(" VITERBI CODERATE: 2/3,");
-		break;
-
-	case 0x02:
-		printk(" VITERBI CODERATE: 3/4,");
-		break;
-
-	case 0x03:
-		printk(" VITERBI CODERATE: 5/6,");
-		break;
-
-	case 0x04:
-		printk(" VITERBI CODERATE: 7/8,");
-		break;
-
-	default:
-		printk(" VITERBI CODERATE: Reserved,");
-
-	}
-
-	val = nxt6000_readreg(state, OFDM_COR_STAT);
-
-	printk(" CHCTrack: %d,", (val >> 7) & 0x01);
-	printk(" TPSLock: %d,", (val >> 6) & 0x01);
-	printk(" SYRLock: %d,", (val >> 5) & 0x01);
-	printk(" AGCLock: %d,", (val >> 4) & 0x01);
-
-	switch (val & 0x0F) {
-
-	case 0x00:
-		printk(" CoreState: IDLE,");
-		break;
-
-	case 0x02:
-		printk(" CoreState: WAIT_AGC,");
-		break;
-
-	case 0x03:
-		printk(" CoreState: WAIT_SYR,");
-		break;
-
-	case 0x04:
-		printk(" CoreState: WAIT_PPM,");
-		break;
-
-	case 0x01:
-		printk(" CoreState: WAIT_TRL,");
-		break;
-
-	case 0x05:
-		printk(" CoreState: WAIT_TPS,");
-		break;
-
-	case 0x06:
-		printk(" CoreState: MONITOR_TPS,");
-		break;
-
-	default:
-		printk(" CoreState: Reserved,");
-
-	}
-
-	val = nxt6000_readreg(state, OFDM_SYR_STAT);
-
-	printk(" SYRLock: %d,", (val >> 4) & 0x01);
-	printk(" SYRMode: %s,", (val >> 2) & 0x01 ? "8K" : "2K");
-
-	switch ((val >> 4) & 0x03) {
-
-	case 0x00:
-		printk(" SYRGuard: 1/32,");
-		break;
-
-	case 0x01:
-		printk(" SYRGuard: 1/16,");
-		break;
-
-	case 0x02:
-		printk(" SYRGuard: 1/8,");
-		break;
-
-	case 0x03:
-		printk(" SYRGuard: 1/4,");
-		break;
-	}
-
-	val = nxt6000_readreg(state, OFDM_TPS_RCVD_3);
-
-	switch ((val >> 4) & 0x07) {
-
-	case 0x00:
-		printk(" TPSLP: 1/2,");
-		break;
-
-	case 0x01:
-		printk(" TPSLP: 2/3,");
-		break;
-
-	case 0x02:
-		printk(" TPSLP: 3/4,");
-		break;
-
-	case 0x03:
-		printk(" TPSLP: 5/6,");
-		break;
-
-	case 0x04:
-		printk(" TPSLP: 7/8,");
-		break;
-
-	default:
-		printk(" TPSLP: Reserved,");
-
-	}
-
-	switch (val & 0x07) {
-
-	case 0x00:
-		printk(" TPSHP: 1/2,");
-		break;
-
-	case 0x01:
-		printk(" TPSHP: 2/3,");
-		break;
-
-	case 0x02:
-		printk(" TPSHP: 3/4,");
-		break;
-
-	case 0x03:
-		printk(" TPSHP: 5/6,");
-		break;
-
-	case 0x04:
-		printk(" TPSHP: 7/8,");
-		break;
-
-	default:
-		printk(" TPSHP: Reserved,");
-
-	}
-
-	val = nxt6000_readreg(state, OFDM_TPS_RCVD_4);
-
-	printk(" TPSMode: %s,", val & 0x01 ? "8K" : "2K");
-
-	switch ((val >> 4) & 0x03) {
-
-	case 0x00:
-		printk(" TPSGuard: 1/32,");
-		break;
-
-	case 0x01:
-		printk(" TPSGuard: 1/16,");
-		break;
-
-	case 0x02:
-		printk(" TPSGuard: 1/8,");
-		break;
-
-	case 0x03:
-		printk(" TPSGuard: 1/4,");
-		break;
-
-	}
-
-	/* Strange magic required to gain access to RF_AGC_STATUS */
-	nxt6000_readreg(state, RF_AGC_VAL_1);
-	val = nxt6000_readreg(state, RF_AGC_STATUS);
-	val = nxt6000_readreg(state, RF_AGC_STATUS);
-
-	printk(" RF AGC LOCK: %d,", (val >> 4) & 0x01);
-	printk("\n");
-}
-
-static int nxt6000_read_status(struct dvb_frontend* fe, fe_status_t* status)
-{
-	u8 core_status;
-	struct nxt6000_state* state = fe->demodulator_priv;
-
-	*status = 0;
-
-	core_status = nxt6000_readreg(state, OFDM_COR_STAT);
-
-	if (core_status & AGCLOCKED)
-		*status |= FE_HAS_SIGNAL;
-
-	if (nxt6000_readreg(state, OFDM_SYR_STAT) & GI14_SYR_LOCK)
-		*status |= FE_HAS_CARRIER;
-
-	if (nxt6000_readreg(state, VIT_SYNC_STATUS) & VITINSYNC)
-		*status |= FE_HAS_VITERBI;
-
-	if (nxt6000_readreg(state, RS_COR_STAT) & RSCORESTATUS)
-		*status |= FE_HAS_SYNC;
-
-	if ((core_status & TPSLOCKED) && (*status == (FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC)))
-		*status |= FE_HAS_LOCK;
-
-	if (debug)
-		nxt6000_dump_status(state);
-
-	return 0;
-}
-
-static int nxt6000_init(struct dvb_frontend* fe)
-{
-	struct nxt6000_state* state = fe->demodulator_priv;
-
-	nxt6000_reset(state);
-	nxt6000_setup(fe);
-
-	return 0;
-}
-
-static int nxt6000_set_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct nxt6000_state* state = fe->demodulator_priv;
-	int result;
-
-	if (fe->ops.tuner_ops.set_params) {
-		fe->ops.tuner_ops.set_params(fe);
-		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
-	}
-
-	result = nxt6000_set_bandwidth(state, p->bandwidth_hz);
-	if (result < 0)
-		return result;
-
-	result = nxt6000_set_guard_interval(state, p->guard_interval);
-	if (result < 0)
-		return result;
-
-	result = nxt6000_set_transmission_mode(state, p->transmission_mode);
-	if (result < 0)
-		return result;
-
-	result = nxt6000_set_inversion(state, p->inversion);
-	if (result < 0)
-		return result;
-
-	msleep(500);
-	return 0;
-}
-
-static void nxt6000_release(struct dvb_frontend* fe)
-{
-	struct nxt6000_state* state = fe->demodulator_priv;
-	kfree(state);
-}
-
-static int nxt6000_read_snr(struct dvb_frontend* fe, u16* snr)
-{
-	struct nxt6000_state* state = fe->demodulator_priv;
-
-	*snr = nxt6000_readreg( state, OFDM_CHC_SNR) / 8;
-
-	return 0;
-}
-
-static int nxt6000_read_ber(struct dvb_frontend* fe, u32* ber)
-{
-	struct nxt6000_state* state = fe->demodulator_priv;
-
-	nxt6000_writereg( state, VIT_COR_INTSTAT, 0x18 );
-
-	*ber = (nxt6000_readreg( state, VIT_BER_1 ) << 8 ) |
-		nxt6000_readreg( state, VIT_BER_0 );
-
-	nxt6000_writereg( state, VIT_COR_INTSTAT, 0x18); // Clear BER Done interrupts
-
-	return 0;
-}
-
-static int nxt6000_read_signal_strength(struct dvb_frontend* fe, u16* signal_strength)
-{
-	struct nxt6000_state* state = fe->demodulator_priv;
-
-	*signal_strength = (short) (511 -
-		(nxt6000_readreg(state, AGC_GAIN_1) +
-		((nxt6000_readreg(state, AGC_GAIN_2) & 0x03) << 8)));
-
-	return 0;
-}
-
-static int nxt6000_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
-{
-	tune->min_delay_ms = 500;
-	return 0;
-}
-
-static int nxt6000_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
-{
-	struct nxt6000_state* state = fe->demodulator_priv;
-
-	if (enable) {
-		return nxt6000_writereg(state, ENABLE_TUNER_IIC, 0x01);
-	} else {
-		return nxt6000_writereg(state, ENABLE_TUNER_IIC, 0x00);
-	}
-}
-
-static struct dvb_frontend_ops nxt6000_ops;
-
-struct dvb_frontend* nxt6000_attach(const struct nxt6000_config* config,
-				    struct i2c_adapter* i2c)
-{
-	struct nxt6000_state* state = NULL;
-
-	/* allocate memory for the internal state */
-	state = kzalloc(sizeof(struct nxt6000_state), GFP_KERNEL);
-	if (state == NULL) goto error;
-
-	/* setup the state */
-	state->config = config;
-	state->i2c = i2c;
-
-	/* check if the demod is there */
-	if (nxt6000_readreg(state, OFDM_MSC_REV) != NXT6000ASICDEVICE) goto error;
-
-	/* create dvb_frontend */
-	memcpy(&state->frontend.ops, &nxt6000_ops, sizeof(struct dvb_frontend_ops));
-	state->frontend.demodulator_priv = state;
-	return &state->frontend;
-
-error:
-	kfree(state);
-	return NULL;
-}
-
-static struct dvb_frontend_ops nxt6000_ops = {
-	.delsys = { SYS_DVBT },
-	.info = {
-		.name = "NxtWave NXT6000 DVB-T",
-		.frequency_min = 0,
-		.frequency_max = 863250000,
-		.frequency_stepsize = 62500,
-		/*.frequency_tolerance = *//* FIXME: 12% of SR */
-		.symbol_rate_min = 0,	/* FIXME */
-		.symbol_rate_max = 9360000,	/* FIXME */
-		.symbol_rate_tolerance = 4000,
-		.caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
-			FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
-			FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO |
-			FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
-			FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |
-			FE_CAN_HIERARCHY_AUTO,
-	},
-
-	.release = nxt6000_release,
-
-	.init = nxt6000_init,
-	.i2c_gate_ctrl = nxt6000_i2c_gate_ctrl,
-
-	.get_tune_settings = nxt6000_fe_get_tune_settings,
-
-	.set_frontend = nxt6000_set_frontend,
-
-	.read_status = nxt6000_read_status,
-	.read_ber = nxt6000_read_ber,
-	.read_signal_strength = nxt6000_read_signal_strength,
-	.read_snr = nxt6000_read_snr,
-};
-
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
-
-MODULE_DESCRIPTION("NxtWave NXT6000 DVB-T demodulator driver");
-MODULE_AUTHOR("Florian Schirmer");
-MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(nxt6000_attach);
diff --git a/drivers/media/dvb/frontends/nxt6000.h b/drivers/media/dvb/frontends/nxt6000.h
deleted file mode 100644
index 878eb38..0000000
--- a/drivers/media/dvb/frontends/nxt6000.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
-	NxtWave Communications - NXT6000 demodulator driver
-
-    Copyright (C) 2002-2003 Florian Schirmer <jolt@tuxbox.org>
-    Copyright (C) 2003 Paul Andreassen <paul@andreassen.com.au>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You 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 NXT6000_H
-#define NXT6000_H
-
-#include <linux/dvb/frontend.h>
-
-struct nxt6000_config
-{
-	/* the demodulator's i2c address */
-	u8 demod_address;
-
-	/* should clock inversion be used? */
-	u8 clock_inversion:1;
-};
-
-#if defined(CONFIG_DVB_NXT6000) || (defined(CONFIG_DVB_NXT6000_MODULE) && defined(MODULE))
-extern struct dvb_frontend* nxt6000_attach(const struct nxt6000_config* config,
-					   struct i2c_adapter* i2c);
-#else
-static inline struct dvb_frontend* nxt6000_attach(const struct nxt6000_config* config,
-					   struct i2c_adapter* i2c)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif // CONFIG_DVB_NXT6000
-
-#endif // NXT6000_H
diff --git a/drivers/media/dvb/frontends/nxt6000_priv.h b/drivers/media/dvb/frontends/nxt6000_priv.h
deleted file mode 100644
index 0422e58..0000000
--- a/drivers/media/dvb/frontends/nxt6000_priv.h
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- * Public Include File for DRV6000 users
- * (ie. NxtWave Communications - NXT6000 demodulator driver)
- *
- * Copyright (C) 2001 NxtWave Communications, Inc.
- *
- */
-
-/*  Nxt6000 Register Addresses and Bit Masks */
-
-/* Maximum Register Number */
-#define MAXNXT6000REG          (0x9A)
-
-/* 0x1B A_VIT_BER_0  aka 0x3A */
-#define A_VIT_BER_0            (0x1B)
-
-/* 0x1D A_VIT_BER_TIMER_0 aka 0x38 */
-#define A_VIT_BER_TIMER_0      (0x1D)
-
-/* 0x21 RS_COR_STAT */
-#define RS_COR_STAT            (0x21)
-#define RSCORESTATUS           (0x03)
-
-/* 0x22 RS_COR_INTEN */
-#define RS_COR_INTEN           (0x22)
-
-/* 0x23 RS_COR_INSTAT */
-#define RS_COR_INSTAT          (0x23)
-#define INSTAT_ERROR           (0x04)
-#define LOCK_LOSS_BITS         (0x03)
-
-/* 0x24 RS_COR_SYNC_PARAM */
-#define RS_COR_SYNC_PARAM      (0x24)
-#define SYNC_PARAM             (0x03)
-
-/* 0x25 BER_CTRL */
-#define BER_CTRL               (0x25)
-#define BER_ENABLE             (0x02)
-#define BER_RESET              (0x01)
-
-/* 0x26 BER_PAY */
-#define BER_PAY                (0x26)
-
-/* 0x27 BER_PKT_L */
-#define BER_PKT_L              (0x27)
-#define BER_PKTOVERFLOW        (0x80)
-
-/* 0x30 VIT_COR_CTL */
-#define VIT_COR_CTL            (0x30)
-#define BER_CONTROL            (0x02)
-#define VIT_COR_MASK           (0x82)
-#define VIT_COR_RESYNC         (0x80)
-
-
-/* 0x32 VIT_SYNC_STATUS */
-#define VIT_SYNC_STATUS        (0x32)
-#define VITINSYNC              (0x80)
-
-/* 0x33 VIT_COR_INTEN */
-#define VIT_COR_INTEN          (0x33)
-#define GLOBAL_ENABLE          (0x80)
-
-/* 0x34 VIT_COR_INTSTAT */
-#define VIT_COR_INTSTAT        (0x34)
-#define BER_DONE               (0x08)
-#define BER_OVERFLOW           (0x10)
-
-/* 0x38 VIT_BERTIME_2 */
-#define VIT_BERTIME_2      (0x38)
-
-/* 0x39 VIT_BERTIME_1 */
-#define VIT_BERTIME_1      (0x39)
-
-/* 0x3A VIT_BERTIME_0 */
-#define VIT_BERTIME_0      (0x3a)
-
-			     /* 0x38 OFDM_BERTimer *//* Use the alias registers */
-#define A_VIT_BER_TIMER_0      (0x1D)
-
-			     /* 0x3A VIT_BER_TIMER_0 *//* Use the alias registers */
-#define A_VIT_BER_0            (0x1B)
-
-/* 0x3B VIT_BER_1 */
-#define VIT_BER_1              (0x3b)
-
-/* 0x3C VIT_BER_0 */
-#define VIT_BER_0              (0x3c)
-
-/* 0x40 OFDM_COR_CTL */
-#define OFDM_COR_CTL           (0x40)
-#define COREACT                (0x20)
-#define HOLDSM                 (0x10)
-#define WAIT_AGC               (0x02)
-#define WAIT_SYR               (0x03)
-
-/* 0x41 OFDM_COR_STAT */
-#define OFDM_COR_STAT          (0x41)
-#define COR_STATUS             (0x0F)
-#define MONITOR_TPS            (0x06)
-#define TPSLOCKED              (0x40)
-#define AGCLOCKED              (0x10)
-
-/* 0x42 OFDM_COR_INTEN */
-#define OFDM_COR_INTEN         (0x42)
-#define TPSRCVBAD              (0x04)
-#define TPSRCVCHANGED         (0x02)
-#define TPSRCVUPDATE           (0x01)
-
-/* 0x43 OFDM_COR_INSTAT */
-#define OFDM_COR_INSTAT        (0x43)
-
-/* 0x44 OFDM_COR_MODEGUARD */
-#define OFDM_COR_MODEGUARD     (0x44)
-#define FORCEMODE              (0x08)
-#define FORCEMODE8K			   (0x04)
-
-/* 0x45 OFDM_AGC_CTL */
-#define OFDM_AGC_CTL           (0x45)
-#define INITIAL_AGC_BW		   (0x08)
-#define AGCNEG                 (0x02)
-#define AGCLAST				   (0x10)
-
-/* 0x48 OFDM_AGC_TARGET */
-#define OFDM_AGC_TARGET		   (0x48)
-#define OFDM_AGC_TARGET_DEFAULT (0x28)
-#define OFDM_AGC_TARGET_IMPULSE (0x38)
-
-/* 0x49 OFDM_AGC_GAIN_1 */
-#define OFDM_AGC_GAIN_1        (0x49)
-
-/* 0x4B OFDM_ITB_CTL */
-#define OFDM_ITB_CTL           (0x4B)
-#define ITBINV                 (0x01)
-
-/* 0x49 AGC_GAIN_1 */
-#define AGC_GAIN_1             (0x49)
-
-/* 0x4A AGC_GAIN_2 */
-#define AGC_GAIN_2             (0x4A)
-
-/* 0x4C OFDM_ITB_FREQ_1 */
-#define OFDM_ITB_FREQ_1        (0x4C)
-
-/* 0x4D OFDM_ITB_FREQ_2 */
-#define OFDM_ITB_FREQ_2        (0x4D)
-
-/* 0x4E  OFDM_CAS_CTL */
-#define OFDM_CAS_CTL           (0x4E)
-#define ACSDIS                 (0x40)
-#define CCSEN                  (0x80)
-
-/* 0x4F CAS_FREQ */
-#define CAS_FREQ               (0x4F)
-
-/* 0x51 OFDM_SYR_CTL */
-#define OFDM_SYR_CTL           (0x51)
-#define SIXTH_ENABLE           (0x80)
-#define SYR_TRACKING_DISABLE   (0x01)
-
-/* 0x52 OFDM_SYR_STAT */
-#define OFDM_SYR_STAT		   (0x52)
-#define GI14_2K_SYR_LOCK	   (0x13)
-#define GI14_8K_SYR_LOCK	   (0x17)
-#define GI14_SYR_LOCK		   (0x10)
-
-/* 0x55 OFDM_SYR_OFFSET_1 */
-#define OFDM_SYR_OFFSET_1      (0x55)
-
-/* 0x56 OFDM_SYR_OFFSET_2 */
-#define OFDM_SYR_OFFSET_2      (0x56)
-
-/* 0x58 OFDM_SCR_CTL */
-#define OFDM_SCR_CTL           (0x58)
-#define SYR_ADJ_DECAY_MASK     (0x70)
-#define SYR_ADJ_DECAY          (0x30)
-
-/* 0x59 OFDM_PPM_CTL_1 */
-#define OFDM_PPM_CTL_1         (0x59)
-#define PPMMAX_MASK            (0x30)
-#define PPM256				   (0x30)
-
-/* 0x5B OFDM_TRL_NOMINALRATE_1 */
-#define OFDM_TRL_NOMINALRATE_1 (0x5B)
-
-/* 0x5C OFDM_TRL_NOMINALRATE_2 */
-#define OFDM_TRL_NOMINALRATE_2 (0x5C)
-
-/* 0x5D OFDM_TRL_TIME_1 */
-#define OFDM_TRL_TIME_1        (0x5D)
-
-/* 0x60 OFDM_CRL_FREQ_1 */
-#define OFDM_CRL_FREQ_1        (0x60)
-
-/* 0x63 OFDM_CHC_CTL_1 */
-#define OFDM_CHC_CTL_1         (0x63)
-#define MANMEAN1               (0xF0);
-#define CHCFIR                 (0x01)
-
-/* 0x64 OFDM_CHC_SNR */
-#define OFDM_CHC_SNR           (0x64)
-
-/* 0x65 OFDM_BDI_CTL */
-#define OFDM_BDI_CTL           (0x65)
-#define LP_SELECT              (0x02)
-
-/* 0x67 OFDM_TPS_RCVD_1 */
-#define OFDM_TPS_RCVD_1        (0x67)
-#define TPSFRAME               (0x03)
-
-/* 0x68 OFDM_TPS_RCVD_2 */
-#define OFDM_TPS_RCVD_2        (0x68)
-
-/* 0x69 OFDM_TPS_RCVD_3 */
-#define OFDM_TPS_RCVD_3        (0x69)
-
-/* 0x6A OFDM_TPS_RCVD_4 */
-#define OFDM_TPS_RCVD_4        (0x6A)
-
-/* 0x6B OFDM_TPS_RESERVED_1 */
-#define OFDM_TPS_RESERVED_1    (0x6B)
-
-/* 0x6C OFDM_TPS_RESERVED_2 */
-#define OFDM_TPS_RESERVED_2    (0x6C)
-
-/* 0x73 OFDM_MSC_REV */
-#define OFDM_MSC_REV           (0x73)
-
-/* 0x76 OFDM_SNR_CARRIER_2 */
-#define OFDM_SNR_CARRIER_2     (0x76)
-#define MEAN_MASK              (0x80)
-#define MEANBIT                (0x80)
-
-/* 0x80 ANALOG_CONTROL_0 */
-#define ANALOG_CONTROL_0       (0x80)
-#define POWER_DOWN_ADC         (0x40)
-
-/* 0x81 ENABLE_TUNER_IIC */
-#define ENABLE_TUNER_IIC       (0x81)
-#define ENABLE_TUNER_BIT       (0x01)
-
-/* 0x82 EN_DMD_RACQ */
-#define EN_DMD_RACQ            (0x82)
-#define EN_DMD_RACQ_REG_VAL    (0x81)
-#define EN_DMD_RACQ_REG_VAL_14 (0x01)
-
-/* 0x84 SNR_COMMAND */
-#define SNR_COMMAND            (0x84)
-#define SNRStat                (0x80)
-
-/* 0x85 SNRCARRIERNUMBER_LSB */
-#define SNRCARRIERNUMBER_LSB   (0x85)
-
-/* 0x87 SNRMINTHRESHOLD_LSB */
-#define SNRMINTHRESHOLD_LSB    (0x87)
-
-/* 0x89 SNR_PER_CARRIER_LSB */
-#define SNR_PER_CARRIER_LSB    (0x89)
-
-/* 0x8B SNRBELOWTHRESHOLD_LSB */
-#define SNRBELOWTHRESHOLD_LSB  (0x8B)
-
-/* 0x91 RF_AGC_VAL_1 */
-#define RF_AGC_VAL_1           (0x91)
-
-/* 0x92 RF_AGC_STATUS */
-#define RF_AGC_STATUS          (0x92)
-
-/* 0x98 DIAG_CONFIG */
-#define DIAG_CONFIG            (0x98)
-#define DIAG_MASK              (0x70)
-#define TB_SET                 (0x10)
-#define TRAN_SELECT            (0x07)
-#define SERIAL_SELECT          (0x01)
-
-/* 0x99 SUB_DIAG_MODE_SEL */
-#define SUB_DIAG_MODE_SEL      (0x99)
-#define CLKINVERSION           (0x01)
-
-/* 0x9A TS_FORMAT */
-#define TS_FORMAT              (0x9A)
-#define ERROR_SENSE            (0x08)
-#define VALID_SENSE            (0x04)
-#define SYNC_SENSE             (0x02)
-#define GATED_CLOCK            (0x01)
-
-#define NXT6000ASICDEVICE      (0x0b)
diff --git a/drivers/media/dvb/frontends/or51132.c b/drivers/media/dvb/frontends/or51132.c
deleted file mode 100644
index 5ef9218..0000000
--- a/drivers/media/dvb/frontends/or51132.c
+++ /dev/null
@@ -1,631 +0,0 @@
-/*
- *    Support for OR51132 (pcHDTV HD-3000) - VSB/QAM
- *
- *
- *    Copyright (C) 2007 Trent Piepho <xyzzy@speakeasy.org>
- *
- *    Copyright (C) 2005 Kirk Lapray <kirk_lapray@bigfoot.com>
- *
- *    Based on code from Jack Kelliher (kelliher@xmission.com)
- *                           Copyright (C) 2002 & pcHDTV, inc.
- *
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
-*/
-
-/*
- * This driver needs two external firmware files. Please copy
- * "dvb-fe-or51132-vsb.fw" and "dvb-fe-or51132-qam.fw" to
- * /usr/lib/hotplug/firmware/ or /lib/firmware/
- * (depending on configuration of firmware hotplug).
- */
-#define OR51132_VSB_FIRMWARE "dvb-fe-or51132-vsb.fw"
-#define OR51132_QAM_FIRMWARE "dvb-fe-or51132-qam.fw"
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <asm/byteorder.h>
-
-#include "dvb_math.h"
-#include "dvb_frontend.h"
-#include "or51132.h"
-
-static int debug;
-#define dprintk(args...) \
-	do { \
-		if (debug) printk(KERN_DEBUG "or51132: " args); \
-	} while (0)
-
-
-struct or51132_state
-{
-	struct i2c_adapter* i2c;
-
-	/* Configuration settings */
-	const struct or51132_config* config;
-
-	struct dvb_frontend frontend;
-
-	/* Demodulator private data */
-	fe_modulation_t current_modulation;
-	u32 snr; /* Result of last SNR calculation */
-
-	/* Tuner private data */
-	u32 current_frequency;
-};
-
-
-/* Write buffer to demod */
-static int or51132_writebuf(struct or51132_state *state, const u8 *buf, int len)
-{
-	int err;
-	struct i2c_msg msg = { .addr = state->config->demod_address,
-			       .flags = 0, .buf = (u8*)buf, .len = len };
-
-	/* msleep(20); */ /* doesn't appear to be necessary */
-	if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
-		printk(KERN_WARNING "or51132: I2C write (addr 0x%02x len %d) error: %d\n",
-		       msg.addr, msg.len, err);
-		return -EREMOTEIO;
-	}
-	return 0;
-}
-
-/* Write constant bytes, e.g. or51132_writebytes(state, 0x04, 0x42, 0x00);
-   Less code and more efficient that loading a buffer on the stack with
-   the bytes to send and then calling or51132_writebuf() on that. */
-#define or51132_writebytes(state, data...)  \
-	({ static const u8 _data[] = {data}; \
-	or51132_writebuf(state, _data, sizeof(_data)); })
-
-/* Read data from demod into buffer.  Returns 0 on success. */
-static int or51132_readbuf(struct or51132_state *state, u8 *buf, int len)
-{
-	int err;
-	struct i2c_msg msg = { .addr = state->config->demod_address,
-			       .flags = I2C_M_RD, .buf = buf, .len = len };
-
-	/* msleep(20); */ /* doesn't appear to be necessary */
-	if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
-		printk(KERN_WARNING "or51132: I2C read (addr 0x%02x len %d) error: %d\n",
-		       msg.addr, msg.len, err);
-		return -EREMOTEIO;
-	}
-	return 0;
-}
-
-/* Reads a 16-bit demod register.  Returns <0 on error. */
-static int or51132_readreg(struct or51132_state *state, u8 reg)
-{
-	u8 buf[2] = { 0x04, reg };
-	struct i2c_msg msg[2] = {
-		{.addr = state->config->demod_address, .flags = 0,
-		 .buf = buf, .len = 2 },
-		{.addr = state->config->demod_address, .flags = I2C_M_RD,
-		 .buf = buf, .len = 2 }};
-	int err;
-
-	if ((err = i2c_transfer(state->i2c, msg, 2)) != 2) {
-		printk(KERN_WARNING "or51132: I2C error reading register %d: %d\n",
-		       reg, err);
-		return -EREMOTEIO;
-	}
-	return buf[0] | (buf[1] << 8);
-}
-
-static int or51132_load_firmware (struct dvb_frontend* fe, const struct firmware *fw)
-{
-	struct or51132_state* state = fe->demodulator_priv;
-	static const u8 run_buf[] = {0x7F,0x01};
-	u8 rec_buf[8];
-	u32 firmwareAsize, firmwareBsize;
-	int i,ret;
-
-	dprintk("Firmware is %Zd bytes\n",fw->size);
-
-	/* Get size of firmware A and B */
-	firmwareAsize = le32_to_cpu(*((__le32*)fw->data));
-	dprintk("FirmwareA is %i bytes\n",firmwareAsize);
-	firmwareBsize = le32_to_cpu(*((__le32*)(fw->data+4)));
-	dprintk("FirmwareB is %i bytes\n",firmwareBsize);
-
-	/* Upload firmware */
-	if ((ret = or51132_writebuf(state, &fw->data[8], firmwareAsize))) {
-		printk(KERN_WARNING "or51132: load_firmware error 1\n");
-		return ret;
-	}
-	if ((ret = or51132_writebuf(state, &fw->data[8+firmwareAsize],
-				    firmwareBsize))) {
-		printk(KERN_WARNING "or51132: load_firmware error 2\n");
-		return ret;
-	}
-
-	if ((ret = or51132_writebuf(state, run_buf, 2))) {
-		printk(KERN_WARNING "or51132: load_firmware error 3\n");
-		return ret;
-	}
-	if ((ret = or51132_writebuf(state, run_buf, 2))) {
-		printk(KERN_WARNING "or51132: load_firmware error 4\n");
-		return ret;
-	}
-
-	/* 50ms for operation to begin */
-	msleep(50);
-
-	/* Read back ucode version to besure we loaded correctly and are really up and running */
-	/* Get uCode version */
-	if ((ret = or51132_writebytes(state, 0x10, 0x10, 0x00))) {
-		printk(KERN_WARNING "or51132: load_firmware error a\n");
-		return ret;
-	}
-	if ((ret = or51132_writebytes(state, 0x04, 0x17))) {
-		printk(KERN_WARNING "or51132: load_firmware error b\n");
-		return ret;
-	}
-	if ((ret = or51132_writebytes(state, 0x00, 0x00))) {
-		printk(KERN_WARNING "or51132: load_firmware error c\n");
-		return ret;
-	}
-	for (i=0;i<4;i++) {
-		/* Once upon a time, this command might have had something
-		   to do with getting the firmware version, but it's
-		   not used anymore:
-		   {0x04,0x00,0x30,0x00,i+1} */
-		/* Read 8 bytes, two bytes at a time */
-		if ((ret = or51132_readbuf(state, &rec_buf[i*2], 2))) {
-			printk(KERN_WARNING
-			       "or51132: load_firmware error d - %d\n",i);
-			return ret;
-		}
-	}
-
-	printk(KERN_WARNING
-	       "or51132: Version: %02X%02X%02X%02X-%02X%02X%02X%02X (%02X%01X-%01X-%02X%01X-%01X)\n",
-	       rec_buf[1],rec_buf[0],rec_buf[3],rec_buf[2],
-	       rec_buf[5],rec_buf[4],rec_buf[7],rec_buf[6],
-	       rec_buf[3],rec_buf[2]>>4,rec_buf[2]&0x0f,
-	       rec_buf[5],rec_buf[4]>>4,rec_buf[4]&0x0f);
-
-	if ((ret = or51132_writebytes(state, 0x10, 0x00, 0x00))) {
-		printk(KERN_WARNING "or51132: load_firmware error e\n");
-		return ret;
-	}
-	return 0;
-};
-
-static int or51132_init(struct dvb_frontend* fe)
-{
-	return 0;
-}
-
-static int or51132_read_ber(struct dvb_frontend* fe, u32* ber)
-{
-	*ber = 0;
-	return 0;
-}
-
-static int or51132_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
-{
-	*ucblocks = 0;
-	return 0;
-}
-
-static int or51132_sleep(struct dvb_frontend* fe)
-{
-	return 0;
-}
-
-static int or51132_setmode(struct dvb_frontend* fe)
-{
-	struct or51132_state* state = fe->demodulator_priv;
-	u8 cmd_buf1[3] = {0x04, 0x01, 0x5f};
-	u8 cmd_buf2[3] = {0x1c, 0x00, 0 };
-
-	dprintk("setmode %d\n",(int)state->current_modulation);
-
-	switch (state->current_modulation) {
-	case VSB_8:
-		/* Auto CH, Auto NTSC rej, MPEGser, MPEG2tr, phase noise-high */
-		cmd_buf1[2] = 0x50;
-		/* REC MODE inv IF spectrum, Normal */
-		cmd_buf2[1] = 0x03;
-		/* Channel MODE ATSC/VSB8 */
-		cmd_buf2[2] = 0x06;
-		break;
-	/* All QAM modes are:
-	   Auto-deinterleave; MPEGser, MPEG2tr, phase noise-high
-	   REC MODE Normal Carrier Lock */
-	case QAM_AUTO:
-		/* Channel MODE Auto QAM64/256 */
-		cmd_buf2[2] = 0x4f;
-		break;
-	case QAM_256:
-		/* Channel MODE QAM256 */
-		cmd_buf2[2] = 0x45;
-		break;
-	case QAM_64:
-		/* Channel MODE QAM64 */
-		cmd_buf2[2] = 0x43;
-		break;
-	default:
-		printk(KERN_WARNING
-		       "or51132: setmode: Modulation set to unsupported value (%d)\n",
-		       state->current_modulation);
-		return -EINVAL;
-	}
-
-	/* Set Receiver 1 register */
-	if (or51132_writebuf(state, cmd_buf1, 3)) {
-		printk(KERN_WARNING "or51132: set_mode error 1\n");
-		return -EREMOTEIO;
-	}
-	dprintk("set #1 to %02x\n", cmd_buf1[2]);
-
-	/* Set operation mode in Receiver 6 register */
-	if (or51132_writebuf(state, cmd_buf2, 3)) {
-		printk(KERN_WARNING "or51132: set_mode error 2\n");
-		return -EREMOTEIO;
-	}
-	dprintk("set #6 to 0x%02x%02x\n", cmd_buf2[1], cmd_buf2[2]);
-
-	return 0;
-}
-
-/* Some modulations use the same firmware.  This classifies modulations
-   by the firmware they use. */
-#define MOD_FWCLASS_UNKNOWN	0
-#define MOD_FWCLASS_VSB		1
-#define MOD_FWCLASS_QAM		2
-static int modulation_fw_class(fe_modulation_t modulation)
-{
-	switch(modulation) {
-	case VSB_8:
-		return MOD_FWCLASS_VSB;
-	case QAM_AUTO:
-	case QAM_64:
-	case QAM_256:
-		return MOD_FWCLASS_QAM;
-	default:
-		return MOD_FWCLASS_UNKNOWN;
-	}
-}
-
-static int or51132_set_parameters(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	int ret;
-	struct or51132_state* state = fe->demodulator_priv;
-	const struct firmware *fw;
-	const char *fwname;
-	int clock_mode;
-
-	/* Upload new firmware only if we need a different one */
-	if (modulation_fw_class(state->current_modulation) !=
-	    modulation_fw_class(p->modulation)) {
-		switch (modulation_fw_class(p->modulation)) {
-		case MOD_FWCLASS_VSB:
-			dprintk("set_parameters VSB MODE\n");
-			fwname = OR51132_VSB_FIRMWARE;
-
-			/* Set non-punctured clock for VSB */
-			clock_mode = 0;
-			break;
-		case MOD_FWCLASS_QAM:
-			dprintk("set_parameters QAM MODE\n");
-			fwname = OR51132_QAM_FIRMWARE;
-
-			/* Set punctured clock for QAM */
-			clock_mode = 1;
-			break;
-		default:
-			printk("or51132: Modulation type(%d) UNSUPPORTED\n",
-			       p->modulation);
-			return -1;
-		}
-		printk("or51132: Waiting for firmware upload(%s)...\n",
-		       fwname);
-		ret = request_firmware(&fw, fwname, state->i2c->dev.parent);
-		if (ret) {
-			printk(KERN_WARNING "or51132: No firmware up"
-			       "loaded(timeout or file not found?)\n");
-			return ret;
-		}
-		ret = or51132_load_firmware(fe, fw);
-		release_firmware(fw);
-		if (ret) {
-			printk(KERN_WARNING "or51132: Writing firmware to "
-			       "device failed!\n");
-			return ret;
-		}
-		printk("or51132: Firmware upload complete.\n");
-		state->config->set_ts_params(fe, clock_mode);
-	}
-	/* Change only if we are actually changing the modulation */
-	if (state->current_modulation != p->modulation) {
-		state->current_modulation = p->modulation;
-		or51132_setmode(fe);
-	}
-
-	if (fe->ops.tuner_ops.set_params) {
-		fe->ops.tuner_ops.set_params(fe);
-		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
-	}
-
-	/* Set to current mode */
-	or51132_setmode(fe);
-
-	/* Update current frequency */
-	state->current_frequency = p->frequency;
-	return 0;
-}
-
-static int or51132_get_parameters(struct dvb_frontend* fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct or51132_state* state = fe->demodulator_priv;
-	int status;
-	int retry = 1;
-
-start:
-	/* Receiver Status */
-	if ((status = or51132_readreg(state, 0x00)) < 0) {
-		printk(KERN_WARNING "or51132: get_parameters: error reading receiver status\n");
-		return -EREMOTEIO;
-	}
-	switch(status&0xff) {
-	case 0x06:
-		p->modulation = VSB_8;
-		break;
-	case 0x43:
-		p->modulation = QAM_64;
-		break;
-	case 0x45:
-		p->modulation = QAM_256;
-		break;
-	default:
-		if (retry--)
-			goto start;
-		printk(KERN_WARNING "or51132: unknown status 0x%02x\n",
-		       status&0xff);
-		return -EREMOTEIO;
-	}
-
-	/* FIXME: Read frequency from frontend, take AFC into account */
-	p->frequency = state->current_frequency;
-
-	/* FIXME: How to read inversion setting? Receiver 6 register? */
-	p->inversion = INVERSION_AUTO;
-
-	return 0;
-}
-
-static int or51132_read_status(struct dvb_frontend* fe, fe_status_t* status)
-{
-	struct or51132_state* state = fe->demodulator_priv;
-	int reg;
-
-	/* Receiver Status */
-	if ((reg = or51132_readreg(state, 0x00)) < 0) {
-		printk(KERN_WARNING "or51132: read_status: error reading receiver status: %d\n", reg);
-		*status = 0;
-		return -EREMOTEIO;
-	}
-	dprintk("%s: read_status %04x\n", __func__, reg);
-
-	if (reg & 0x0100) /* Receiver Lock */
-		*status = FE_HAS_SIGNAL|FE_HAS_CARRIER|FE_HAS_VITERBI|
-			  FE_HAS_SYNC|FE_HAS_LOCK;
-	else
-		*status = 0;
-	return 0;
-}
-
-/* Calculate SNR estimation (scaled by 2^24)
-
-   8-VSB SNR and QAM equations from Oren datasheets
-
-   For 8-VSB:
-     SNR[dB] = 10 * log10(897152044.8282 / MSE^2 ) - K
-
-     Where K = 0 if NTSC rejection filter is OFF; and
-	   K = 3 if NTSC rejection filter is ON
-
-   For QAM64:
-     SNR[dB] = 10 * log10(897152044.8282 / MSE^2 )
-
-   For QAM256:
-     SNR[dB] = 10 * log10(907832426.314266  / MSE^2 )
-
-   We re-write the snr equation as:
-     SNR * 2^24 = 10*(c - 2*intlog10(MSE))
-   Where for QAM256, c = log10(907832426.314266) * 2^24
-   and for 8-VSB and QAM64, c = log10(897152044.8282) * 2^24 */
-
-static u32 calculate_snr(u32 mse, u32 c)
-{
-	if (mse == 0) /* No signal */
-		return 0;
-
-	mse = 2*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 or51132_read_snr(struct dvb_frontend* fe, u16* snr)
-{
-	struct or51132_state* state = fe->demodulator_priv;
-	int noise, reg;
-	u32 c, usK = 0;
-	int retry = 1;
-
-start:
-	/* SNR after Equalizer */
-	noise = or51132_readreg(state, 0x02);
-	if (noise < 0) {
-		printk(KERN_WARNING "or51132: read_snr: error reading equalizer\n");
-		return -EREMOTEIO;
-	}
-	dprintk("read_snr noise (%d)\n", noise);
-
-	/* Read status, contains modulation type for QAM_AUTO and
-	   NTSC filter for VSB */
-	reg = or51132_readreg(state, 0x00);
-	if (reg < 0) {
-		printk(KERN_WARNING "or51132: read_snr: error reading receiver status\n");
-		return -EREMOTEIO;
-	}
-
-	switch (reg&0xff) {
-	case 0x06:
-		if (reg & 0x1000) usK = 3 << 24;
-		/* Fall through to QAM64 case */
-	case 0x43:
-		c = 150204167;
-		break;
-	case 0x45:
-		c = 150290396;
-		break;
-	default:
-		printk(KERN_WARNING "or51132: unknown status 0x%02x\n", reg&0xff);
-		if (retry--) goto start;
-		return -EREMOTEIO;
-	}
-	dprintk("%s: modulation %02x, NTSC rej O%s\n", __func__,
-		reg&0xff, reg&0x1000?"n":"ff");
-
-	/* Calculate SNR using noise, c, and NTSC rejection correction */
-	state->snr = calculate_snr(noise, c) - usK;
-	*snr = (state->snr) >> 16;
-
-	dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __func__, noise,
-		state->snr >> 24, (((state->snr>>8) & 0xffff) * 100) >> 16);
-
-	return 0;
-}
-
-static int or51132_read_signal_strength(struct dvb_frontend* fe, u16* strength)
-{
-	/* 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 or51132_state* state = (struct or51132_state*) fe->demodulator_priv;
-	u16 snr;
-	int ret;
-
-	ret = fe->ops.read_snr(fe, &snr);
-	if (ret != 0)
-		return ret;
-	/* 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;
-
-	return 0;
-}
-
-static int or51132_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fe_tune_settings)
-{
-	fe_tune_settings->min_delay_ms = 500;
-	fe_tune_settings->step_size = 0;
-	fe_tune_settings->max_drift = 0;
-
-	return 0;
-}
-
-static void or51132_release(struct dvb_frontend* fe)
-{
-	struct or51132_state* state = fe->demodulator_priv;
-	kfree(state);
-}
-
-static struct dvb_frontend_ops or51132_ops;
-
-struct dvb_frontend* or51132_attach(const struct or51132_config* config,
-				    struct i2c_adapter* i2c)
-{
-	struct or51132_state* state = NULL;
-
-	/* Allocate memory for the internal state */
-	state = kzalloc(sizeof(struct or51132_state), GFP_KERNEL);
-	if (state == NULL)
-		return NULL;
-
-	/* Setup the state */
-	state->config = config;
-	state->i2c = i2c;
-	state->current_frequency = -1;
-	state->current_modulation = -1;
-
-	/* Create dvb_frontend */
-	memcpy(&state->frontend.ops, &or51132_ops, sizeof(struct dvb_frontend_ops));
-	state->frontend.demodulator_priv = state;
-	return &state->frontend;
-}
-
-static struct dvb_frontend_ops or51132_ops = {
-	.delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
-	.info = {
-		.name			= "Oren OR51132 VSB/QAM Frontend",
-		.frequency_min		= 44000000,
-		.frequency_max		= 958000000,
-		.frequency_stepsize	= 166666,
-		.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_FEC_AUTO |
-			FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_QAM_AUTO |
-			FE_CAN_8VSB
-	},
-
-	.release = or51132_release,
-
-	.init = or51132_init,
-	.sleep = or51132_sleep,
-
-	.set_frontend = or51132_set_parameters,
-	.get_frontend = or51132_get_parameters,
-	.get_tune_settings = or51132_get_tune_settings,
-
-	.read_status = or51132_read_status,
-	.read_ber = or51132_read_ber,
-	.read_signal_strength = or51132_read_signal_strength,
-	.read_snr = or51132_read_snr,
-	.read_ucblocks = or51132_read_ucblocks,
-};
-
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
-
-MODULE_DESCRIPTION("OR51132 ATSC [pcHDTV HD-3000] (8VSB & ITU J83 AnnexB FEC QAM64/256) Demodulator Driver");
-MODULE_AUTHOR("Kirk Lapray");
-MODULE_AUTHOR("Trent Piepho");
-MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(or51132_attach);
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/dvb/frontends/or51132.h b/drivers/media/dvb/frontends/or51132.h
deleted file mode 100644
index 1b8e04d..0000000
--- a/drivers/media/dvb/frontends/or51132.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- *    Support for OR51132 (pcHDTV HD-3000) - VSB/QAM
- *
- *    Copyright (C) 2005 Kirk Lapray <kirk_lapray@bigfoot.com>
- *
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
-*/
-
-#ifndef OR51132_H
-#define OR51132_H
-
-#include <linux/firmware.h>
-#include <linux/dvb/frontend.h>
-
-struct or51132_config
-{
-	/* The demodulator's i2c address */
-	u8 demod_address;
-
-	/* Need to set device param for start_dma */
-	int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured);
-};
-
-#if defined(CONFIG_DVB_OR51132) || (defined(CONFIG_DVB_OR51132_MODULE) && defined(MODULE))
-extern struct dvb_frontend* or51132_attach(const struct or51132_config* config,
-					   struct i2c_adapter* i2c);
-#else
-static inline struct dvb_frontend* or51132_attach(const struct or51132_config* config,
-					   struct i2c_adapter* i2c)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif // CONFIG_DVB_OR51132
-
-#endif // OR51132_H
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/dvb/frontends/or51211.c b/drivers/media/dvb/frontends/or51211.c
deleted file mode 100644
index c625b57..0000000
--- a/drivers/media/dvb/frontends/or51211.c
+++ /dev/null
@@ -1,581 +0,0 @@
-/*
- *    Support for OR51211 (pcHDTV HD-2000) - VSB
- *
- *    Copyright (C) 2005 Kirk Lapray <kirk_lapray@bigfoot.com>
- *
- *    Based on code from Jack Kelliher (kelliher@xmission.com)
- *                           Copyright (C) 2002 & pcHDTV, inc.
- *
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
-*/
-
-/*
- * This driver needs external firmware. Please use the command
- * "<kerneldir>/Documentation/dvb/get_dvb_firmware or51211" to
- * download/extract it, and then copy it to /usr/lib/hotplug/firmware
- * or /lib/firmware (depending on configuration of firmware hotplug).
- */
-#define OR51211_DEFAULT_FIRMWARE "dvb-fe-or51211.fw"
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/firmware.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <asm/byteorder.h>
-
-#include "dvb_math.h"
-#include "dvb_frontend.h"
-#include "or51211.h"
-
-static int debug;
-#define dprintk(args...) \
-	do { \
-		if (debug) printk(KERN_DEBUG "or51211: " args); \
-	} while (0)
-
-static u8 run_buf[] = {0x7f,0x01};
-static u8 cmd_buf[] = {0x04,0x01,0x50,0x80,0x06}; // ATSC
-
-struct or51211_state {
-
-	struct i2c_adapter* i2c;
-
-	/* Configuration settings */
-	const struct or51211_config* config;
-
-	struct dvb_frontend frontend;
-	struct bt878* bt;
-
-	/* Demodulator private data */
-	u8 initialized:1;
-	u32 snr; /* Result of last SNR claculation */
-
-	/* Tuner private data */
-	u32 current_frequency;
-};
-
-static int i2c_writebytes (struct or51211_state* state, u8 reg, const u8 *buf,
-			   int len)
-{
-	int err;
-	struct i2c_msg msg;
-	msg.addr	= reg;
-	msg.flags	= 0;
-	msg.len		= len;
-	msg.buf		= (u8 *)buf;
-
-	if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
-		printk(KERN_WARNING "or51211: i2c_writebytes error "
-		       "(addr %02x, err == %i)\n", reg, err);
-		return -EREMOTEIO;
-	}
-
-	return 0;
-}
-
-static int i2c_readbytes(struct or51211_state *state, u8 reg, u8 *buf, int len)
-{
-	int err;
-	struct i2c_msg msg;
-	msg.addr	= reg;
-	msg.flags	= I2C_M_RD;
-	msg.len		= len;
-	msg.buf		= buf;
-
-	if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
-		printk(KERN_WARNING "or51211: i2c_readbytes error "
-		       "(addr %02x, err == %i)\n", reg, err);
-		return -EREMOTEIO;
-	}
-
-	return 0;
-}
-
-static int or51211_load_firmware (struct dvb_frontend* fe,
-				  const struct firmware *fw)
-{
-	struct or51211_state* state = fe->demodulator_priv;
-	u8 tudata[585];
-	int i;
-
-	dprintk("Firmware is %zd bytes\n",fw->size);
-
-	/* Get eprom data */
-	tudata[0] = 17;
-	if (i2c_writebytes(state,0x50,tudata,1)) {
-		printk(KERN_WARNING "or51211:load_firmware error eprom addr\n");
-		return -1;
-	}
-	if (i2c_readbytes(state,0x50,&tudata[145],192)) {
-		printk(KERN_WARNING "or51211: load_firmware error eprom\n");
-		return -1;
-	}
-
-	/* Create firmware buffer */
-	for (i = 0; i < 145; i++)
-		tudata[i] = fw->data[i];
-
-	for (i = 0; i < 248; i++)
-		tudata[i+337] = fw->data[145+i];
-
-	state->config->reset(fe);
-
-	if (i2c_writebytes(state,state->config->demod_address,tudata,585)) {
-		printk(KERN_WARNING "or51211: load_firmware error 1\n");
-		return -1;
-	}
-	msleep(1);
-
-	if (i2c_writebytes(state,state->config->demod_address,
-			   &fw->data[393],8125)) {
-		printk(KERN_WARNING "or51211: load_firmware error 2\n");
-		return -1;
-	}
-	msleep(1);
-
-	if (i2c_writebytes(state,state->config->demod_address,run_buf,2)) {
-		printk(KERN_WARNING "or51211: load_firmware error 3\n");
-		return -1;
-	}
-
-	/* Wait at least 5 msec */
-	msleep(10);
-	if (i2c_writebytes(state,state->config->demod_address,run_buf,2)) {
-		printk(KERN_WARNING "or51211: load_firmware error 4\n");
-		return -1;
-	}
-	msleep(10);
-
-	printk("or51211: Done.\n");
-	return 0;
-};
-
-static int or51211_setmode(struct dvb_frontend* fe, int mode)
-{
-	struct or51211_state* state = fe->demodulator_priv;
-	u8 rec_buf[14];
-
-	state->config->setmode(fe, mode);
-
-	if (i2c_writebytes(state,state->config->demod_address,run_buf,2)) {
-		printk(KERN_WARNING "or51211: setmode error 1\n");
-		return -1;
-	}
-
-	/* Wait at least 5 msec */
-	msleep(10);
-	if (i2c_writebytes(state,state->config->demod_address,run_buf,2)) {
-		printk(KERN_WARNING "or51211: setmode error 2\n");
-		return -1;
-	}
-
-	msleep(10);
-
-	/* Set operation mode in Receiver 1 register;
-	 * type 1:
-	 * data 0x50h  Automatic sets receiver channel conditions
-	 *             Automatic NTSC rejection filter
-	 *             Enable  MPEG serial data output
-	 *             MPEG2tr
-	 *             High tuner phase noise
-	 *             normal +/-150kHz Carrier acquisition range
-	 */
-	if (i2c_writebytes(state,state->config->demod_address,cmd_buf,3)) {
-		printk(KERN_WARNING "or51211: setmode error 3\n");
-		return -1;
-	}
-
-	rec_buf[0] = 0x04;
-	rec_buf[1] = 0x00;
-	rec_buf[2] = 0x03;
-	rec_buf[3] = 0x00;
-	msleep(20);
-	if (i2c_writebytes(state,state->config->demod_address,rec_buf,3)) {
-		printk(KERN_WARNING "or51211: setmode error 5\n");
-	}
-	msleep(3);
-	if (i2c_readbytes(state,state->config->demod_address,&rec_buf[10],2)) {
-		printk(KERN_WARNING "or51211: setmode error 6");
-		return -1;
-	}
-	dprintk("setmode rec status %02x %02x\n",rec_buf[10],rec_buf[11]);
-
-	return 0;
-}
-
-static int or51211_set_parameters(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct or51211_state* state = fe->demodulator_priv;
-
-	/* Change only if we are actually changing the channel */
-	if (state->current_frequency != p->frequency) {
-		if (fe->ops.tuner_ops.set_params) {
-			fe->ops.tuner_ops.set_params(fe);
-			if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
-		}
-
-		/* Set to ATSC mode */
-		or51211_setmode(fe,0);
-
-		/* Update current frequency */
-		state->current_frequency = p->frequency;
-	}
-	return 0;
-}
-
-static int or51211_read_status(struct dvb_frontend* fe, fe_status_t* status)
-{
-	struct or51211_state* state = fe->demodulator_priv;
-	unsigned char rec_buf[2];
-	unsigned char snd_buf[] = {0x04,0x00,0x03,0x00};
-	*status = 0;
-
-	/* Receiver Status */
-	if (i2c_writebytes(state,state->config->demod_address,snd_buf,3)) {
-		printk(KERN_WARNING "or51132: read_status write error\n");
-		return -1;
-	}
-	msleep(3);
-	if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) {
-		printk(KERN_WARNING "or51132: read_status read error\n");
-		return -1;
-	}
-	dprintk("read_status %x %x\n",rec_buf[0],rec_buf[1]);
-
-	if (rec_buf[0] &  0x01) { /* Receiver Lock */
-		*status |= FE_HAS_SIGNAL;
-		*status |= FE_HAS_CARRIER;
-		*status |= FE_HAS_VITERBI;
-		*status |= FE_HAS_SYNC;
-		*status |= FE_HAS_LOCK;
-	}
-	return 0;
-}
-
-/* Calculate SNR estimation (scaled by 2^24)
-
-   8-VSB SNR equation from Oren datasheets
-
-   For 8-VSB:
-     SNR[dB] = 10 * log10(219037.9454 / MSE^2 )
-
-   We re-write the snr equation as:
-     SNR * 2^24 = 10*(c - 2*intlog10(MSE))
-   Where for 8-VSB, c = log10(219037.9454) * 2^24 */
-
-static u32 calculate_snr(u32 mse, u32 c)
-{
-	if (mse == 0) /* No signal */
-		return 0;
-
-	mse = 2*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 or51211_read_snr(struct dvb_frontend* fe, u16* snr)
-{
-	struct or51211_state* state = fe->demodulator_priv;
-	u8 rec_buf[2];
-	u8 snd_buf[3];
-
-	/* SNR after Equalizer */
-	snd_buf[0] = 0x04;
-	snd_buf[1] = 0x00;
-	snd_buf[2] = 0x04;
-
-	if (i2c_writebytes(state,state->config->demod_address,snd_buf,3)) {
-		printk(KERN_WARNING "%s: error writing snr reg\n",
-		       __func__);
-		return -1;
-	}
-	if (i2c_readbytes(state,state->config->demod_address,rec_buf,2)) {
-		printk(KERN_WARNING "%s: read_status read error\n",
-		       __func__);
-		return -1;
-	}
-
-	state->snr = calculate_snr(rec_buf[0], 89599047);
-	*snr = (state->snr) >> 16;
-
-	dprintk("%s: noise = 0x%02x, snr = %d.%02d dB\n", __func__, rec_buf[0],
-		state->snr >> 24, (((state->snr>>8) & 0xffff) * 100) >> 16);
-
-	return 0;
-}
-
-static int or51211_read_signal_strength(struct dvb_frontend* fe, u16* strength)
-{
-	/* 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 or51211_state* state = (struct or51211_state*)fe->demodulator_priv;
-	u16 snr;
-	int ret;
-
-	ret = fe->ops.read_snr(fe, &snr);
-	if (ret != 0)
-		return ret;
-	/* 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;
-
-	return 0;
-}
-
-static int or51211_read_ber(struct dvb_frontend* fe, u32* ber)
-{
-	*ber = -ENOSYS;
-	return 0;
-}
-
-static int or51211_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
-{
-	*ucblocks = -ENOSYS;
-	return 0;
-}
-
-static int or51211_sleep(struct dvb_frontend* fe)
-{
-	return 0;
-}
-
-static int or51211_init(struct dvb_frontend* fe)
-{
-	struct or51211_state* state = fe->demodulator_priv;
-	const struct or51211_config* config = state->config;
-	const struct firmware* fw;
-	unsigned char get_ver_buf[] = {0x04,0x00,0x30,0x00,0x00};
-	unsigned char rec_buf[14];
-	int ret,i;
-
-	if (!state->initialized) {
-		/* Request the firmware, this will block until it uploads */
-		printk(KERN_INFO "or51211: Waiting for firmware upload "
-		       "(%s)...\n", OR51211_DEFAULT_FIRMWARE);
-		ret = config->request_firmware(fe, &fw,
-					       OR51211_DEFAULT_FIRMWARE);
-		printk(KERN_INFO "or51211:Got Hotplug firmware\n");
-		if (ret) {
-			printk(KERN_WARNING "or51211: No firmware uploaded "
-			       "(timeout or file not found?)\n");
-			return ret;
-		}
-
-		ret = or51211_load_firmware(fe, fw);
-		release_firmware(fw);
-		if (ret) {
-			printk(KERN_WARNING "or51211: Writing firmware to "
-			       "device failed!\n");
-			return ret;
-		}
-		printk(KERN_INFO "or51211: Firmware upload complete.\n");
-
-		/* Set operation mode in Receiver 1 register;
-		 * type 1:
-		 * data 0x50h  Automatic sets receiver channel conditions
-		 *             Automatic NTSC rejection filter
-		 *             Enable  MPEG serial data output
-		 *             MPEG2tr
-		 *             High tuner phase noise
-		 *             normal +/-150kHz Carrier acquisition range
-		 */
-		if (i2c_writebytes(state,state->config->demod_address,
-				   cmd_buf,3)) {
-			printk(KERN_WARNING "or51211: Load DVR Error 5\n");
-			return -1;
-		}
-
-		/* Read back ucode version to besure we loaded correctly */
-		/* and are really up and running */
-		rec_buf[0] = 0x04;
-		rec_buf[1] = 0x00;
-		rec_buf[2] = 0x03;
-		rec_buf[3] = 0x00;
-		msleep(30);
-		if (i2c_writebytes(state,state->config->demod_address,
-				   rec_buf,3)) {
-			printk(KERN_WARNING "or51211: Load DVR Error A\n");
-			return -1;
-		}
-		msleep(3);
-		if (i2c_readbytes(state,state->config->demod_address,
-				  &rec_buf[10],2)) {
-			printk(KERN_WARNING "or51211: Load DVR Error B\n");
-			return -1;
-		}
-
-		rec_buf[0] = 0x04;
-		rec_buf[1] = 0x00;
-		rec_buf[2] = 0x01;
-		rec_buf[3] = 0x00;
-		msleep(20);
-		if (i2c_writebytes(state,state->config->demod_address,
-				   rec_buf,3)) {
-			printk(KERN_WARNING "or51211: Load DVR Error C\n");
-			return -1;
-		}
-		msleep(3);
-		if (i2c_readbytes(state,state->config->demod_address,
-				  &rec_buf[12],2)) {
-			printk(KERN_WARNING "or51211: Load DVR Error D\n");
-			return -1;
-		}
-
-		for (i = 0; i < 8; i++)
-			rec_buf[i]=0xed;
-
-		for (i = 0; i < 5; i++) {
-			msleep(30);
-			get_ver_buf[4] = i+1;
-			if (i2c_writebytes(state,state->config->demod_address,
-					   get_ver_buf,5)) {
-				printk(KERN_WARNING "or51211:Load DVR Error 6"
-				       " - %d\n",i);
-				return -1;
-			}
-			msleep(3);
-
-			if (i2c_readbytes(state,state->config->demod_address,
-					  &rec_buf[i*2],2)) {
-				printk(KERN_WARNING "or51211:Load DVR Error 7"
-				       " - %d\n",i);
-				return -1;
-			}
-			/* If we didn't receive the right index, try again */
-			if ((int)rec_buf[i*2+1]!=i+1){
-			  i--;
-			}
-		}
-		dprintk("read_fwbits %x %x %x %x %x %x %x %x %x %x\n",
-			rec_buf[0], rec_buf[1], rec_buf[2], rec_buf[3],
-			rec_buf[4], rec_buf[5], rec_buf[6], rec_buf[7],
-			rec_buf[8], rec_buf[9]);
-
-		printk(KERN_INFO "or51211: ver TU%02x%02x%02x VSB mode %02x"
-		       " Status %02x\n",
-		       rec_buf[2], rec_buf[4],rec_buf[6],
-		       rec_buf[12],rec_buf[10]);
-
-		rec_buf[0] = 0x04;
-		rec_buf[1] = 0x00;
-		rec_buf[2] = 0x03;
-		rec_buf[3] = 0x00;
-		msleep(20);
-		if (i2c_writebytes(state,state->config->demod_address,
-				   rec_buf,3)) {
-			printk(KERN_WARNING "or51211: Load DVR Error 8\n");
-			return -1;
-		}
-		msleep(20);
-		if (i2c_readbytes(state,state->config->demod_address,
-				  &rec_buf[8],2)) {
-			printk(KERN_WARNING "or51211: Load DVR Error 9\n");
-			return -1;
-		}
-		state->initialized = 1;
-	}
-
-	return 0;
-}
-
-static int or51211_get_tune_settings(struct dvb_frontend* fe,
-				     struct dvb_frontend_tune_settings* fesettings)
-{
-	fesettings->min_delay_ms = 500;
-	fesettings->step_size = 0;
-	fesettings->max_drift = 0;
-	return 0;
-}
-
-static void or51211_release(struct dvb_frontend* fe)
-{
-	struct or51211_state* state = fe->demodulator_priv;
-	state->config->sleep(fe);
-	kfree(state);
-}
-
-static struct dvb_frontend_ops or51211_ops;
-
-struct dvb_frontend* or51211_attach(const struct or51211_config* config,
-				    struct i2c_adapter* i2c)
-{
-	struct or51211_state* state = NULL;
-
-	/* Allocate memory for the internal state */
-	state = kzalloc(sizeof(struct or51211_state), GFP_KERNEL);
-	if (state == NULL)
-		return NULL;
-
-	/* Setup the state */
-	state->config = config;
-	state->i2c = i2c;
-	state->initialized = 0;
-	state->current_frequency = 0;
-
-	/* Create dvb_frontend */
-	memcpy(&state->frontend.ops, &or51211_ops, sizeof(struct dvb_frontend_ops));
-	state->frontend.demodulator_priv = state;
-	return &state->frontend;
-}
-
-static struct dvb_frontend_ops or51211_ops = {
-	.delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
-	.info = {
-		.name               = "Oren OR51211 VSB Frontend",
-		.frequency_min      = 44000000,
-		.frequency_max      = 958000000,
-		.frequency_stepsize = 166666,
-		.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_FEC_AUTO |
-			FE_CAN_8VSB
-	},
-
-	.release = or51211_release,
-
-	.init = or51211_init,
-	.sleep = or51211_sleep,
-
-	.set_frontend = or51211_set_parameters,
-	.get_tune_settings = or51211_get_tune_settings,
-
-	.read_status = or51211_read_status,
-	.read_ber = or51211_read_ber,
-	.read_signal_strength = or51211_read_signal_strength,
-	.read_snr = or51211_read_snr,
-	.read_ucblocks = or51211_read_ucblocks,
-};
-
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
-
-MODULE_DESCRIPTION("Oren OR51211 VSB [pcHDTV HD-2000] Demodulator Driver");
-MODULE_AUTHOR("Kirk Lapray");
-MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(or51211_attach);
-
diff --git a/drivers/media/dvb/frontends/or51211.h b/drivers/media/dvb/frontends/or51211.h
deleted file mode 100644
index 3ce0508..0000000
--- a/drivers/media/dvb/frontends/or51211.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- *    Support for OR51211 (pcHDTV HD-2000) - VSB
- *
- *    Copyright (C) 2005 Kirk Lapray <kirk_lapray@bigfoot.com>
- *
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
-*/
-
-#ifndef OR51211_H
-#define OR51211_H
-
-#include <linux/dvb/frontend.h>
-#include <linux/firmware.h>
-
-struct or51211_config
-{
-	/* The demodulator's i2c address */
-	u8 demod_address;
-
-	/* Request firmware for device */
-	int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name);
-	void (*setmode)(struct dvb_frontend * fe, int mode);
-	void (*reset)(struct dvb_frontend * fe);
-	void (*sleep)(struct dvb_frontend * fe);
-};
-
-#if defined(CONFIG_DVB_OR51211) || (defined(CONFIG_DVB_OR51211_MODULE) && defined(MODULE))
-extern struct dvb_frontend* or51211_attach(const struct or51211_config* config,
-					   struct i2c_adapter* i2c);
-#else
-static inline struct dvb_frontend* or51211_attach(const struct or51211_config* config,
-					   struct i2c_adapter* i2c)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif // CONFIG_DVB_OR51211
-
-#endif // OR51211_H
-
diff --git a/drivers/media/dvb/frontends/rtl2830.c b/drivers/media/dvb/frontends/rtl2830.c
deleted file mode 100644
index 93612eb..0000000
--- a/drivers/media/dvb/frontends/rtl2830.c
+++ /dev/null
@@ -1,757 +0,0 @@
-/*
- * Realtek RTL2830 DVB-T demodulator driver
- *
- * Copyright (C) 2011 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.,
- *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-
-/*
- * Driver implements own I2C-adapter for tuner I2C access. That's since chip
- * have unusual I2C-gate control which closes gate automatically after each
- * I2C transfer. Using own I2C adapter we can workaround that.
- */
-
-#include "rtl2830_priv.h"
-
-int rtl2830_debug;
-module_param_named(debug, rtl2830_debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
-
-/* write multiple hardware registers */
-static int rtl2830_wr(struct rtl2830_priv *priv, u8 reg, u8 *val, int len)
-{
-	int ret;
-	u8 buf[1+len];
-	struct i2c_msg msg[1] = {
-		{
-			.addr = priv->cfg.i2c_addr,
-			.flags = 0,
-			.len = 1+len,
-			.buf = buf,
-		}
-	};
-
-	buf[0] = reg;
-	memcpy(&buf[1], val, len);
-
-	ret = i2c_transfer(priv->i2c, msg, 1);
-	if (ret == 1) {
-		ret = 0;
-	} else {
-		warn("i2c wr failed=%d reg=%02x len=%d", ret, reg, len);
-		ret = -EREMOTEIO;
-	}
-	return ret;
-}
-
-/* read multiple hardware registers */
-static int rtl2830_rd(struct rtl2830_priv *priv, u8 reg, u8 *val, int len)
-{
-	int ret;
-	struct i2c_msg msg[2] = {
-		{
-			.addr = priv->cfg.i2c_addr,
-			.flags = 0,
-			.len = 1,
-			.buf = &reg,
-		}, {
-			.addr = priv->cfg.i2c_addr,
-			.flags = I2C_M_RD,
-			.len = len,
-			.buf = val,
-		}
-	};
-
-	ret = i2c_transfer(priv->i2c, msg, 2);
-	if (ret == 2) {
-		ret = 0;
-	} else {
-		warn("i2c rd failed=%d reg=%02x len=%d", ret, reg, len);
-		ret = -EREMOTEIO;
-	}
-	return ret;
-}
-
-/* write multiple registers */
-static int rtl2830_wr_regs(struct rtl2830_priv *priv, u16 reg, u8 *val, int len)
-{
-	int ret;
-	u8 reg2 = (reg >> 0) & 0xff;
-	u8 page = (reg >> 8) & 0xff;
-
-	/* switch bank if needed */
-	if (page != priv->page) {
-		ret = rtl2830_wr(priv, 0x00, &page, 1);
-		if (ret)
-			return ret;
-
-		priv->page = page;
-	}
-
-	return rtl2830_wr(priv, reg2, val, len);
-}
-
-/* read multiple registers */
-static int rtl2830_rd_regs(struct rtl2830_priv *priv, u16 reg, u8 *val, int len)
-{
-	int ret;
-	u8 reg2 = (reg >> 0) & 0xff;
-	u8 page = (reg >> 8) & 0xff;
-
-	/* switch bank if needed */
-	if (page != priv->page) {
-		ret = rtl2830_wr(priv, 0x00, &page, 1);
-		if (ret)
-			return ret;
-
-		priv->page = page;
-	}
-
-	return rtl2830_rd(priv, reg2, val, len);
-}
-
-#if 0 /* currently not used */
-/* write single register */
-static int rtl2830_wr_reg(struct rtl2830_priv *priv, u16 reg, u8 val)
-{
-	return rtl2830_wr_regs(priv, reg, &val, 1);
-}
-#endif
-
-/* read single register */
-static int rtl2830_rd_reg(struct rtl2830_priv *priv, u16 reg, u8 *val)
-{
-	return rtl2830_rd_regs(priv, reg, val, 1);
-}
-
-/* write single register with mask */
-int rtl2830_wr_reg_mask(struct rtl2830_priv *priv, u16 reg, u8 val, u8 mask)
-{
-	int ret;
-	u8 tmp;
-
-	/* no need for read if whole reg is written */
-	if (mask != 0xff) {
-		ret = rtl2830_rd_regs(priv, reg, &tmp, 1);
-		if (ret)
-			return ret;
-
-		val &= mask;
-		tmp &= ~mask;
-		val |= tmp;
-	}
-
-	return rtl2830_wr_regs(priv, reg, &val, 1);
-}
-
-/* read single register with mask */
-int rtl2830_rd_reg_mask(struct rtl2830_priv *priv, u16 reg, u8 *val, u8 mask)
-{
-	int ret, i;
-	u8 tmp;
-
-	ret = rtl2830_rd_regs(priv, reg, &tmp, 1);
-	if (ret)
-		return ret;
-
-	tmp &= mask;
-
-	/* find position of the first bit */
-	for (i = 0; i < 8; i++) {
-		if ((mask >> i) & 0x01)
-			break;
-	}
-	*val = tmp >> i;
-
-	return 0;
-}
-
-static int rtl2830_init(struct dvb_frontend *fe)
-{
-	struct rtl2830_priv *priv = fe->demodulator_priv;
-	int ret, i;
-	u64 num;
-	u8 buf[3], tmp;
-	u32 if_ctl;
-	struct rtl2830_reg_val_mask tab[] = {
-		{ 0x00d, 0x01, 0x03 },
-		{ 0x00d, 0x10, 0x10 },
-		{ 0x104, 0x00, 0x1e },
-		{ 0x105, 0x80, 0x80 },
-		{ 0x110, 0x02, 0x03 },
-		{ 0x110, 0x08, 0x0c },
-		{ 0x17b, 0x00, 0x40 },
-		{ 0x17d, 0x05, 0x0f },
-		{ 0x17d, 0x50, 0xf0 },
-		{ 0x18c, 0x08, 0x0f },
-		{ 0x18d, 0x00, 0xc0 },
-		{ 0x188, 0x05, 0x0f },
-		{ 0x189, 0x00, 0xfc },
-		{ 0x2d5, 0x02, 0x02 },
-		{ 0x2f1, 0x02, 0x06 },
-		{ 0x2f1, 0x20, 0xf8 },
-		{ 0x16d, 0x00, 0x01 },
-		{ 0x1a6, 0x00, 0x80 },
-		{ 0x106, priv->cfg.vtop, 0x3f },
-		{ 0x107, priv->cfg.krf, 0x3f },
-		{ 0x112, 0x28, 0xff },
-		{ 0x103, priv->cfg.agc_targ_val, 0xff },
-		{ 0x00a, 0x02, 0x07 },
-		{ 0x140, 0x0c, 0x3c },
-		{ 0x140, 0x40, 0xc0 },
-		{ 0x15b, 0x05, 0x07 },
-		{ 0x15b, 0x28, 0x38 },
-		{ 0x15c, 0x05, 0x07 },
-		{ 0x15c, 0x28, 0x38 },
-		{ 0x115, priv->cfg.spec_inv, 0x01 },
-		{ 0x16f, 0x01, 0x07 },
-		{ 0x170, 0x18, 0x38 },
-		{ 0x172, 0x0f, 0x0f },
-		{ 0x173, 0x08, 0x38 },
-		{ 0x175, 0x01, 0x07 },
-		{ 0x176, 0x00, 0xc0 },
-	};
-
-	for (i = 0; i < ARRAY_SIZE(tab); i++) {
-		ret = rtl2830_wr_reg_mask(priv, tab[i].reg, tab[i].val,
-			tab[i].mask);
-		if (ret)
-			goto err;
-	}
-
-	ret = rtl2830_wr_regs(priv, 0x18f, "\x28\x00", 2);
-	if (ret)
-		goto err;
-
-	ret = rtl2830_wr_regs(priv, 0x195,
-		"\x04\x06\x0a\x12\x0a\x12\x1e\x28", 8);
-	if (ret)
-		goto err;
-
-	num = priv->cfg.if_dvbt % priv->cfg.xtal;
-	num *= 0x400000;
-	num = div_u64(num, priv->cfg.xtal);
-	num = -num;
-	if_ctl = num & 0x3fffff;
-	dbg("%s: if_ctl=%08x", __func__, if_ctl);
-
-	ret = rtl2830_rd_reg_mask(priv, 0x119, &tmp, 0xc0); /* b[7:6] */
-	if (ret)
-		goto err;
-
-	buf[0] = tmp << 6;
-	buf[0] = (if_ctl >> 16) & 0x3f;
-	buf[1] = (if_ctl >>  8) & 0xff;
-	buf[2] = (if_ctl >>  0) & 0xff;
-
-	ret = rtl2830_wr_regs(priv, 0x119, buf, 3);
-	if (ret)
-		goto err;
-
-	/* TODO: spec init */
-
-	/* soft reset */
-	ret = rtl2830_wr_reg_mask(priv, 0x101, 0x04, 0x04);
-	if (ret)
-		goto err;
-
-	ret = rtl2830_wr_reg_mask(priv, 0x101, 0x00, 0x04);
-	if (ret)
-		goto err;
-
-	priv->sleeping = false;
-
-	return ret;
-err:
-	dbg("%s: failed=%d", __func__, ret);
-	return ret;
-}
-
-static int rtl2830_sleep(struct dvb_frontend *fe)
-{
-	struct rtl2830_priv *priv = fe->demodulator_priv;
-	priv->sleeping = true;
-	return 0;
-}
-
-int rtl2830_get_tune_settings(struct dvb_frontend *fe,
-	struct dvb_frontend_tune_settings *s)
-{
-	s->min_delay_ms = 500;
-	s->step_size = fe->ops.info.frequency_stepsize * 2;
-	s->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1;
-
-	return 0;
-}
-
-static int rtl2830_set_frontend(struct dvb_frontend *fe)
-{
-	struct rtl2830_priv *priv = fe->demodulator_priv;
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	int ret, i;
-	static u8 bw_params1[3][34] = {
-		{
-		0x1f, 0xf0, 0x1f, 0xf0, 0x1f, 0xfa, 0x00, 0x17, 0x00, 0x41,
-		0x00, 0x64, 0x00, 0x67, 0x00, 0x38, 0x1f, 0xde, 0x1f, 0x7a,
-		0x1f, 0x47, 0x1f, 0x7c, 0x00, 0x30, 0x01, 0x4b, 0x02, 0x82,
-		0x03, 0x73, 0x03, 0xcf, /* 6 MHz */
-		}, {
-		0x1f, 0xfa, 0x1f, 0xda, 0x1f, 0xc1, 0x1f, 0xb3, 0x1f, 0xca,
-		0x00, 0x07, 0x00, 0x4d, 0x00, 0x6d, 0x00, 0x40, 0x1f, 0xca,
-		0x1f, 0x4d, 0x1f, 0x2a, 0x1f, 0xb2, 0x00, 0xec, 0x02, 0x7e,
-		0x03, 0xd0, 0x04, 0x53, /* 7 MHz */
-		}, {
-		0x00, 0x10, 0x00, 0x0e, 0x1f, 0xf7, 0x1f, 0xc9, 0x1f, 0xa0,
-		0x1f, 0xa6, 0x1f, 0xec, 0x00, 0x4e, 0x00, 0x7d, 0x00, 0x3a,
-		0x1f, 0x98, 0x1f, 0x10, 0x1f, 0x40, 0x00, 0x75, 0x02, 0x5f,
-		0x04, 0x24, 0x04, 0xdb, /* 8 MHz */
-		},
-	};
-	static u8 bw_params2[3][6] = {
-		{0xc3, 0x0c, 0x44, 0x33, 0x33, 0x30,}, /* 6 MHz */
-		{0xb8, 0xe3, 0x93, 0x99, 0x99, 0x98,}, /* 7 MHz */
-		{0xae, 0xba, 0xf3, 0x26, 0x66, 0x64,}, /* 8 MHz */
-	};
-
-
-	dbg("%s: frequency=%d bandwidth_hz=%d inversion=%d", __func__,
-		c->frequency, c->bandwidth_hz, c->inversion);
-
-	/* program tuner */
-	if (fe->ops.tuner_ops.set_params)
-		fe->ops.tuner_ops.set_params(fe);
-
-	switch (c->bandwidth_hz) {
-	case 6000000:
-		i = 0;
-		break;
-	case 7000000:
-		i = 1;
-		break;
-	case 8000000:
-		i = 2;
-		break;
-	default:
-		dbg("invalid bandwidth");
-		return -EINVAL;
-	}
-
-	ret = rtl2830_wr_reg_mask(priv, 0x008, i << 1, 0x06);
-	if (ret)
-		goto err;
-
-	/* 1/2 split I2C write */
-	ret = rtl2830_wr_regs(priv, 0x11c, &bw_params1[i][0], 17);
-	if (ret)
-		goto err;
-
-	/* 2/2 split I2C write */
-	ret = rtl2830_wr_regs(priv, 0x12d, &bw_params1[i][17], 17);
-	if (ret)
-		goto err;
-
-	ret = rtl2830_wr_regs(priv, 0x19d, bw_params2[i], 6);
-	if (ret)
-		goto err;
-
-	return ret;
-err:
-	dbg("%s: failed=%d", __func__, ret);
-	return ret;
-}
-
-static int rtl2830_get_frontend(struct dvb_frontend *fe)
-{
-	struct rtl2830_priv *priv = fe->demodulator_priv;
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	int ret;
-	u8 buf[3];
-
-	if (priv->sleeping)
-		return 0;
-
-	ret = rtl2830_rd_regs(priv, 0x33c, buf, 2);
-	if (ret)
-		goto err;
-
-	ret = rtl2830_rd_reg(priv, 0x351, &buf[2]);
-	if (ret)
-		goto err;
-
-	dbg("%s: TPS=%02x %02x %02x", __func__, buf[0], buf[1], buf[2]);
-
-	switch ((buf[0] >> 2) & 3) {
-	case 0:
-		c->modulation = QPSK;
-		break;
-	case 1:
-		c->modulation = QAM_16;
-		break;
-	case 2:
-		c->modulation = QAM_64;
-		break;
-	}
-
-	switch ((buf[2] >> 2) & 1) {
-	case 0:
-		c->transmission_mode = TRANSMISSION_MODE_2K;
-		break;
-	case 1:
-		c->transmission_mode = TRANSMISSION_MODE_8K;
-	}
-
-	switch ((buf[2] >> 0) & 3) {
-	case 0:
-		c->guard_interval = GUARD_INTERVAL_1_32;
-		break;
-	case 1:
-		c->guard_interval = GUARD_INTERVAL_1_16;
-		break;
-	case 2:
-		c->guard_interval = GUARD_INTERVAL_1_8;
-		break;
-	case 3:
-		c->guard_interval = GUARD_INTERVAL_1_4;
-		break;
-	}
-
-	switch ((buf[0] >> 4) & 7) {
-	case 0:
-		c->hierarchy = HIERARCHY_NONE;
-		break;
-	case 1:
-		c->hierarchy = HIERARCHY_1;
-		break;
-	case 2:
-		c->hierarchy = HIERARCHY_2;
-		break;
-	case 3:
-		c->hierarchy = HIERARCHY_4;
-		break;
-	}
-
-	switch ((buf[1] >> 3) & 7) {
-	case 0:
-		c->code_rate_HP = FEC_1_2;
-		break;
-	case 1:
-		c->code_rate_HP = FEC_2_3;
-		break;
-	case 2:
-		c->code_rate_HP = FEC_3_4;
-		break;
-	case 3:
-		c->code_rate_HP = FEC_5_6;
-		break;
-	case 4:
-		c->code_rate_HP = FEC_7_8;
-		break;
-	}
-
-	switch ((buf[1] >> 0) & 7) {
-	case 0:
-		c->code_rate_LP = FEC_1_2;
-		break;
-	case 1:
-		c->code_rate_LP = FEC_2_3;
-		break;
-	case 2:
-		c->code_rate_LP = FEC_3_4;
-		break;
-	case 3:
-		c->code_rate_LP = FEC_5_6;
-		break;
-	case 4:
-		c->code_rate_LP = FEC_7_8;
-		break;
-	}
-
-	return 0;
-err:
-	dbg("%s: failed=%d", __func__, ret);
-	return ret;
-}
-
-static int rtl2830_read_status(struct dvb_frontend *fe, fe_status_t *status)
-{
-	struct rtl2830_priv *priv = fe->demodulator_priv;
-	int ret;
-	u8 tmp;
-	*status = 0;
-
-	if (priv->sleeping)
-		return 0;
-
-	ret = rtl2830_rd_reg_mask(priv, 0x351, &tmp, 0x78); /* [6:3] */
-	if (ret)
-		goto err;
-
-	if (tmp == 11) {
-		*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
-			FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
-	} else if (tmp == 10) {
-		*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
-			FE_HAS_VITERBI;
-	}
-
-	return ret;
-err:
-	dbg("%s: failed=%d", __func__, ret);
-	return ret;
-}
-
-static int rtl2830_read_snr(struct dvb_frontend *fe, u16 *snr)
-{
-	struct rtl2830_priv *priv = fe->demodulator_priv;
-	int ret, hierarchy, constellation;
-	u8 buf[2], tmp;
-	u16 tmp16;
-#define CONSTELLATION_NUM 3
-#define HIERARCHY_NUM 4
-	static const u32 snr_constant[CONSTELLATION_NUM][HIERARCHY_NUM] = {
-		{ 70705899, 70705899, 70705899, 70705899 },
-		{ 82433173, 82433173, 87483115, 94445660 },
-		{ 92888734, 92888734, 95487525, 99770748 },
-	};
-
-	if (priv->sleeping)
-		return 0;
-
-	/* reports SNR in resolution of 0.1 dB */
-
-	ret = rtl2830_rd_reg(priv, 0x33c, &tmp);
-	if (ret)
-		goto err;
-
-	constellation = (tmp >> 2) & 0x03; /* [3:2] */
-	if (constellation > CONSTELLATION_NUM - 1)
-		goto err;
-
-	hierarchy = (tmp >> 4) & 0x07; /* [6:4] */
-	if (hierarchy > HIERARCHY_NUM - 1)
-		goto err;
-
-	ret = rtl2830_rd_regs(priv, 0x40c, buf, 2);
-	if (ret)
-		goto err;
-
-	tmp16 = buf[0] << 8 | buf[1];
-
-	if (tmp16)
-		*snr = (snr_constant[constellation][hierarchy] -
-				intlog10(tmp16)) / ((1 << 24) / 100);
-	else
-		*snr = 0;
-
-	return 0;
-err:
-	dbg("%s: failed=%d", __func__, ret);
-	return ret;
-}
-
-static int rtl2830_read_ber(struct dvb_frontend *fe, u32 *ber)
-{
-	struct rtl2830_priv *priv = fe->demodulator_priv;
-	int ret;
-	u8 buf[2];
-
-	if (priv->sleeping)
-		return 0;
-
-	ret = rtl2830_rd_regs(priv, 0x34e, buf, 2);
-	if (ret)
-		goto err;
-
-	*ber = buf[0] << 8 | buf[1];
-
-	return 0;
-err:
-	dbg("%s: failed=%d", __func__, ret);
-	return ret;
-}
-
-static int rtl2830_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
-{
-	*ucblocks = 0;
-	return 0;
-}
-
-static int rtl2830_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
-{
-	struct rtl2830_priv *priv = fe->demodulator_priv;
-	int ret;
-	u8 buf[2];
-	u16 if_agc_raw, if_agc;
-
-	if (priv->sleeping)
-		return 0;
-
-	ret = rtl2830_rd_regs(priv, 0x359, buf, 2);
-	if (ret)
-		goto err;
-
-	if_agc_raw = (buf[0] << 8 | buf[1]) & 0x3fff;
-
-	if (if_agc_raw & (1 << 9))
-		if_agc = -(~(if_agc_raw - 1) & 0x1ff);
-	else
-		if_agc = if_agc_raw;
-
-	*strength = (u8) (55 - if_agc / 182);
-	*strength |= *strength << 8;
-
-	return 0;
-err:
-	dbg("%s: failed=%d", __func__, ret);
-	return ret;
-}
-
-static struct dvb_frontend_ops rtl2830_ops;
-
-static u32 rtl2830_tuner_i2c_func(struct i2c_adapter *adapter)
-{
-	return I2C_FUNC_I2C;
-}
-
-static int rtl2830_tuner_i2c_xfer(struct i2c_adapter *i2c_adap,
-	struct i2c_msg msg[], int num)
-{
-	struct rtl2830_priv *priv = i2c_get_adapdata(i2c_adap);
-	int ret;
-
-	/* open i2c-gate */
-	ret = rtl2830_wr_reg_mask(priv, 0x101, 0x08, 0x08);
-	if (ret)
-		goto err;
-
-	ret = i2c_transfer(priv->i2c, msg, num);
-	if (ret < 0)
-		warn("tuner i2c failed=%d", ret);
-
-	return ret;
-err:
-	dbg("%s: failed=%d", __func__, ret);
-	return ret;
-}
-
-static struct i2c_algorithm rtl2830_tuner_i2c_algo = {
-	.master_xfer   = rtl2830_tuner_i2c_xfer,
-	.functionality = rtl2830_tuner_i2c_func,
-};
-
-struct i2c_adapter *rtl2830_get_tuner_i2c_adapter(struct dvb_frontend *fe)
-{
-	struct rtl2830_priv *priv = fe->demodulator_priv;
-	return &priv->tuner_i2c_adapter;
-}
-EXPORT_SYMBOL(rtl2830_get_tuner_i2c_adapter);
-
-static void rtl2830_release(struct dvb_frontend *fe)
-{
-	struct rtl2830_priv *priv = fe->demodulator_priv;
-
-	i2c_del_adapter(&priv->tuner_i2c_adapter);
-	kfree(priv);
-}
-
-struct dvb_frontend *rtl2830_attach(const struct rtl2830_config *cfg,
-	struct i2c_adapter *i2c)
-{
-	struct rtl2830_priv *priv = NULL;
-	int ret = 0;
-	u8 tmp;
-
-	/* allocate memory for the internal state */
-	priv = kzalloc(sizeof(struct rtl2830_priv), GFP_KERNEL);
-	if (priv == NULL)
-		goto err;
-
-	/* setup the priv */
-	priv->i2c = i2c;
-	memcpy(&priv->cfg, cfg, sizeof(struct rtl2830_config));
-
-	/* check if the demod is there */
-	ret = rtl2830_rd_reg(priv, 0x000, &tmp);
-	if (ret)
-		goto err;
-
-	/* create dvb_frontend */
-	memcpy(&priv->fe.ops, &rtl2830_ops, sizeof(struct dvb_frontend_ops));
-	priv->fe.demodulator_priv = priv;
-
-	/* create tuner i2c adapter */
-	strlcpy(priv->tuner_i2c_adapter.name, "RTL2830 tuner I2C adapter",
-		sizeof(priv->tuner_i2c_adapter.name));
-	priv->tuner_i2c_adapter.algo = &rtl2830_tuner_i2c_algo;
-	priv->tuner_i2c_adapter.algo_data = NULL;
-	i2c_set_adapdata(&priv->tuner_i2c_adapter, priv);
-	if (i2c_add_adapter(&priv->tuner_i2c_adapter) < 0) {
-		err("tuner I2C bus could not be initialized");
-		goto err;
-	}
-
-	priv->sleeping = true;
-
-	return &priv->fe;
-err:
-	dbg("%s: failed=%d", __func__, ret);
-	kfree(priv);
-	return NULL;
-}
-EXPORT_SYMBOL(rtl2830_attach);
-
-static struct dvb_frontend_ops rtl2830_ops = {
-	.delsys = { SYS_DVBT },
-	.info = {
-		.name = "Realtek RTL2830 (DVB-T)",
-		.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_FEC_AUTO |
-			FE_CAN_QPSK |
-			FE_CAN_QAM_16 |
-			FE_CAN_QAM_64 |
-			FE_CAN_QAM_AUTO |
-			FE_CAN_TRANSMISSION_MODE_AUTO |
-			FE_CAN_GUARD_INTERVAL_AUTO |
-			FE_CAN_HIERARCHY_AUTO |
-			FE_CAN_RECOVER |
-			FE_CAN_MUTE_TS
-	},
-
-	.release = rtl2830_release,
-
-	.init = rtl2830_init,
-	.sleep = rtl2830_sleep,
-
-	.get_tune_settings = rtl2830_get_tune_settings,
-
-	.set_frontend = rtl2830_set_frontend,
-	.get_frontend = rtl2830_get_frontend,
-
-	.read_status = rtl2830_read_status,
-	.read_snr = rtl2830_read_snr,
-	.read_ber = rtl2830_read_ber,
-	.read_ucblocks = rtl2830_read_ucblocks,
-	.read_signal_strength = rtl2830_read_signal_strength,
-};
-
-MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
-MODULE_DESCRIPTION("Realtek RTL2830 DVB-T demodulator driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/rtl2830.h b/drivers/media/dvb/frontends/rtl2830.h
deleted file mode 100644
index 1c6ee91..0000000
--- a/drivers/media/dvb/frontends/rtl2830.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Realtek RTL2830 DVB-T demodulator driver
- *
- * Copyright (C) 2011 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.,
- *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef RTL2830_H
-#define RTL2830_H
-
-#include <linux/dvb/frontend.h>
-
-struct rtl2830_config {
-	/*
-	 * Demodulator I2C address.
-	 */
-	u8 i2c_addr;
-
-	/*
-	 * Xtal frequency.
-	 * Hz
-	 * 4000000, 16000000, 25000000, 28800000
-	 */
-	u32 xtal;
-
-	/*
-	 * TS output mode.
-	 */
-	u8 ts_mode;
-
-	/*
-	 * Spectrum inversion.
-	 */
-	bool spec_inv;
-
-	/*
-	 * IFs for all used modes.
-	 * Hz
-	 * 4570000, 4571429, 36000000, 36125000, 36166667, 44000000
-	 */
-	u32 if_dvbt;
-
-	/*
-	 */
-	u8 vtop;
-
-	/*
-	 */
-	u8 krf;
-
-	/*
-	 */
-	u8 agc_targ_val;
-};
-
-#if defined(CONFIG_DVB_RTL2830) || \
-	(defined(CONFIG_DVB_RTL2830_MODULE) && defined(MODULE))
-extern struct dvb_frontend *rtl2830_attach(
-	const struct rtl2830_config *config,
-	struct i2c_adapter *i2c
-);
-
-extern struct i2c_adapter *rtl2830_get_tuner_i2c_adapter(
-	struct dvb_frontend *fe
-);
-#else
-static inline struct dvb_frontend *rtl2830_attach(
-	const struct rtl2830_config *config,
-	struct i2c_adapter *i2c
-)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-
-static inline struct i2c_adapter *rtl2830_get_tuner_i2c_adapter(
-	struct dvb_frontend *fe
-)
-{
-	return NULL;
-}
-#endif
-
-#endif /* RTL2830_H */
diff --git a/drivers/media/dvb/frontends/rtl2830_priv.h b/drivers/media/dvb/frontends/rtl2830_priv.h
deleted file mode 100644
index 9b20557..0000000
--- a/drivers/media/dvb/frontends/rtl2830_priv.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Realtek RTL2830 DVB-T demodulator driver
- *
- * Copyright (C) 2011 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.,
- *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef RTL2830_PRIV_H
-#define RTL2830_PRIV_H
-
-#include "dvb_frontend.h"
-#include "dvb_math.h"
-#include "rtl2830.h"
-
-#define LOG_PREFIX "rtl2830"
-
-#undef dbg
-#define dbg(f, arg...) \
-	if (rtl2830_debug) \
-		printk(KERN_INFO            LOG_PREFIX": " f "\n" , ## arg)
-#undef err
-#define err(f, arg...)  printk(KERN_ERR     LOG_PREFIX": " f "\n" , ## arg)
-#undef info
-#define info(f, arg...) printk(KERN_INFO    LOG_PREFIX": " f "\n" , ## arg)
-#undef warn
-#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg)
-
-struct rtl2830_priv {
-	struct i2c_adapter *i2c;
-	struct dvb_frontend fe;
-	struct rtl2830_config cfg;
-	struct i2c_adapter tuner_i2c_adapter;
-
-	bool sleeping;
-
-	u8 page; /* active register page */
-};
-
-struct rtl2830_reg_val_mask {
-	u16 reg;
-	u8  val;
-	u8  mask;
-};
-
-#endif /* RTL2830_PRIV_H */
diff --git a/drivers/media/dvb/frontends/rtl2832.c b/drivers/media/dvb/frontends/rtl2832.c
deleted file mode 100644
index 28269cc..0000000
--- a/drivers/media/dvb/frontends/rtl2832.c
+++ /dev/null
@@ -1,789 +0,0 @@
-/*
- * Realtek RTL2832 DVB-T demodulator driver
- *
- * Copyright (C) 2012 Thomas Mair <thomas.mair86@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 "rtl2832_priv.h"
-#include <linux/bitops.h>
-
-int rtl2832_debug;
-module_param_named(debug, rtl2832_debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
-
-#define REG_MASK(b) (BIT(b + 1) - 1)
-
-static const struct rtl2832_reg_entry registers[] = {
-	[DVBT_SOFT_RST]		= {0x1, 0x1,   2, 2},
-	[DVBT_IIC_REPEAT]	= {0x1, 0x1,   3, 3},
-	[DVBT_TR_WAIT_MIN_8K]	= {0x1, 0x88, 11, 2},
-	[DVBT_RSD_BER_FAIL_VAL]	= {0x1, 0x8f, 15, 0},
-	[DVBT_EN_BK_TRK]	= {0x1, 0xa6,  7, 7},
-	[DVBT_AD_EN_REG]	= {0x0, 0x8,   7, 7},
-	[DVBT_AD_EN_REG1]	= {0x0, 0x8,   6, 6},
-	[DVBT_EN_BBIN]		= {0x1, 0xb1,  0, 0},
-	[DVBT_MGD_THD0]		= {0x1, 0x95,  7, 0},
-	[DVBT_MGD_THD1]		= {0x1, 0x96,  7, 0},
-	[DVBT_MGD_THD2]		= {0x1, 0x97,  7, 0},
-	[DVBT_MGD_THD3]		= {0x1, 0x98,  7, 0},
-	[DVBT_MGD_THD4]		= {0x1, 0x99,  7, 0},
-	[DVBT_MGD_THD5]		= {0x1, 0x9a,  7, 0},
-	[DVBT_MGD_THD6]		= {0x1, 0x9b,  7, 0},
-	[DVBT_MGD_THD7]		= {0x1, 0x9c,  7, 0},
-	[DVBT_EN_CACQ_NOTCH]	= {0x1, 0x61,  4, 4},
-	[DVBT_AD_AV_REF]	= {0x0, 0x9,   6, 0},
-	[DVBT_REG_PI]		= {0x0, 0xa,   2, 0},
-	[DVBT_PIP_ON]		= {0x0, 0x21,  3, 3},
-	[DVBT_SCALE1_B92]	= {0x2, 0x92,  7, 0},
-	[DVBT_SCALE1_B93]	= {0x2, 0x93,  7, 0},
-	[DVBT_SCALE1_BA7]	= {0x2, 0xa7,  7, 0},
-	[DVBT_SCALE1_BA9]	= {0x2, 0xa9,  7, 0},
-	[DVBT_SCALE1_BAA]	= {0x2, 0xaa,  7, 0},
-	[DVBT_SCALE1_BAB]	= {0x2, 0xab,  7, 0},
-	[DVBT_SCALE1_BAC]	= {0x2, 0xac,  7, 0},
-	[DVBT_SCALE1_BB0]	= {0x2, 0xb0,  7, 0},
-	[DVBT_SCALE1_BB1]	= {0x2, 0xb1,  7, 0},
-	[DVBT_KB_P1]		= {0x1, 0x64,  3, 1},
-	[DVBT_KB_P2]		= {0x1, 0x64,  6, 4},
-	[DVBT_KB_P3]		= {0x1, 0x65,  2, 0},
-	[DVBT_OPT_ADC_IQ]	= {0x0, 0x6,   5, 4},
-	[DVBT_AD_AVI]		= {0x0, 0x9,   1, 0},
-	[DVBT_AD_AVQ]		= {0x0, 0x9,   3, 2},
-	[DVBT_K1_CR_STEP12]	= {0x2, 0xad,  9, 4},
-	[DVBT_TRK_KS_P2]	= {0x1, 0x6f,  2, 0},
-	[DVBT_TRK_KS_I2]	= {0x1, 0x70,  5, 3},
-	[DVBT_TR_THD_SET2]	= {0x1, 0x72,  3, 0},
-	[DVBT_TRK_KC_P2]	= {0x1, 0x73,  5, 3},
-	[DVBT_TRK_KC_I2]	= {0x1, 0x75,  2, 0},
-	[DVBT_CR_THD_SET2]	= {0x1, 0x76,  7, 6},
-	[DVBT_PSET_IFFREQ]	= {0x1, 0x19, 21, 0},
-	[DVBT_SPEC_INV]		= {0x1, 0x15,  0, 0},
-	[DVBT_RSAMP_RATIO]	= {0x1, 0x9f, 27, 2},
-	[DVBT_CFREQ_OFF_RATIO]	= {0x1, 0x9d, 23, 4},
-	[DVBT_FSM_STAGE]	= {0x3, 0x51,  6, 3},
-	[DVBT_RX_CONSTEL]	= {0x3, 0x3c,  3, 2},
-	[DVBT_RX_HIER]		= {0x3, 0x3c,  6, 4},
-	[DVBT_RX_C_RATE_LP]	= {0x3, 0x3d,  2, 0},
-	[DVBT_RX_C_RATE_HP]	= {0x3, 0x3d,  5, 3},
-	[DVBT_GI_IDX]		= {0x3, 0x51,  1, 0},
-	[DVBT_FFT_MODE_IDX]	= {0x3, 0x51,  2, 2},
-	[DVBT_RSD_BER_EST]	= {0x3, 0x4e, 15, 0},
-	[DVBT_CE_EST_EVM]	= {0x4, 0xc,  15, 0},
-	[DVBT_RF_AGC_VAL]	= {0x3, 0x5b, 13, 0},
-	[DVBT_IF_AGC_VAL]	= {0x3, 0x59, 13, 0},
-	[DVBT_DAGC_VAL]		= {0x3, 0x5,   7, 0},
-	[DVBT_SFREQ_OFF]	= {0x3, 0x18, 13, 0},
-	[DVBT_CFREQ_OFF]	= {0x3, 0x5f, 17, 0},
-	[DVBT_POLAR_RF_AGC]	= {0x0, 0xe,   1, 1},
-	[DVBT_POLAR_IF_AGC]	= {0x0, 0xe,   0, 0},
-	[DVBT_AAGC_HOLD]	= {0x1, 0x4,   5, 5},
-	[DVBT_EN_RF_AGC]	= {0x1, 0x4,   6, 6},
-	[DVBT_EN_IF_AGC]	= {0x1, 0x4,   7, 7},
-	[DVBT_IF_AGC_MIN]	= {0x1, 0x8,   7, 0},
-	[DVBT_IF_AGC_MAX]	= {0x1, 0x9,   7, 0},
-	[DVBT_RF_AGC_MIN]	= {0x1, 0xa,   7, 0},
-	[DVBT_RF_AGC_MAX]	= {0x1, 0xb,   7, 0},
-	[DVBT_IF_AGC_MAN]	= {0x1, 0xc,   6, 6},
-	[DVBT_IF_AGC_MAN_VAL]	= {0x1, 0xc,  13, 0},
-	[DVBT_RF_AGC_MAN]	= {0x1, 0xe,   6, 6},
-	[DVBT_RF_AGC_MAN_VAL]	= {0x1, 0xe,  13, 0},
-	[DVBT_DAGC_TRG_VAL]	= {0x1, 0x12,  7, 0},
-	[DVBT_AGC_TARG_VAL_0]	= {0x1, 0x2,   0, 0},
-	[DVBT_AGC_TARG_VAL_8_1]	= {0x1, 0x3,   7, 0},
-	[DVBT_AAGC_LOOP_GAIN]	= {0x1, 0xc7,  5, 1},
-	[DVBT_LOOP_GAIN2_3_0]	= {0x1, 0x4,   4, 1},
-	[DVBT_LOOP_GAIN2_4]	= {0x1, 0x5,   7, 7},
-	[DVBT_LOOP_GAIN3]	= {0x1, 0xc8,  4, 0},
-	[DVBT_VTOP1]		= {0x1, 0x6,   5, 0},
-	[DVBT_VTOP2]		= {0x1, 0xc9,  5, 0},
-	[DVBT_VTOP3]		= {0x1, 0xca,  5, 0},
-	[DVBT_KRF1]		= {0x1, 0xcb,  7, 0},
-	[DVBT_KRF2]		= {0x1, 0x7,   7, 0},
-	[DVBT_KRF3]		= {0x1, 0xcd,  7, 0},
-	[DVBT_KRF4]		= {0x1, 0xce,  7, 0},
-	[DVBT_EN_GI_PGA]	= {0x1, 0xe5,  0, 0},
-	[DVBT_THD_LOCK_UP]	= {0x1, 0xd9,  8, 0},
-	[DVBT_THD_LOCK_DW]	= {0x1, 0xdb,  8, 0},
-	[DVBT_THD_UP1]		= {0x1, 0xdd,  7, 0},
-	[DVBT_THD_DW1]		= {0x1, 0xde,  7, 0},
-	[DVBT_INTER_CNT_LEN]	= {0x1, 0xd8,  3, 0},
-	[DVBT_GI_PGA_STATE]	= {0x1, 0xe6,  3, 3},
-	[DVBT_EN_AGC_PGA]	= {0x1, 0xd7,  0, 0},
-	[DVBT_CKOUTPAR]		= {0x1, 0x7b,  5, 5},
-	[DVBT_CKOUT_PWR]	= {0x1, 0x7b,  6, 6},
-	[DVBT_SYNC_DUR]		= {0x1, 0x7b,  7, 7},
-	[DVBT_ERR_DUR]		= {0x1, 0x7c,  0, 0},
-	[DVBT_SYNC_LVL]		= {0x1, 0x7c,  1, 1},
-	[DVBT_ERR_LVL]		= {0x1, 0x7c,  2, 2},
-	[DVBT_VAL_LVL]		= {0x1, 0x7c,  3, 3},
-	[DVBT_SERIAL]		= {0x1, 0x7c,  4, 4},
-	[DVBT_SER_LSB]		= {0x1, 0x7c,  5, 5},
-	[DVBT_CDIV_PH0]		= {0x1, 0x7d,  3, 0},
-	[DVBT_CDIV_PH1]		= {0x1, 0x7d,  7, 4},
-	[DVBT_MPEG_IO_OPT_2_2]	= {0x0, 0x6,   7, 7},
-	[DVBT_MPEG_IO_OPT_1_0]	= {0x0, 0x7,   7, 6},
-	[DVBT_CKOUTPAR_PIP]	= {0x0, 0xb7,  4, 4},
-	[DVBT_CKOUT_PWR_PIP]	= {0x0, 0xb7,  3, 3},
-	[DVBT_SYNC_LVL_PIP]	= {0x0, 0xb7,  2, 2},
-	[DVBT_ERR_LVL_PIP]	= {0x0, 0xb7,  1, 1},
-	[DVBT_VAL_LVL_PIP]	= {0x0, 0xb7,  0, 0},
-	[DVBT_CKOUTPAR_PID]	= {0x0, 0xb9,  4, 4},
-	[DVBT_CKOUT_PWR_PID]	= {0x0, 0xb9,  3, 3},
-	[DVBT_SYNC_LVL_PID]	= {0x0, 0xb9,  2, 2},
-	[DVBT_ERR_LVL_PID]	= {0x0, 0xb9,  1, 1},
-	[DVBT_VAL_LVL_PID]	= {0x0, 0xb9,  0, 0},
-	[DVBT_SM_PASS]		= {0x1, 0x93, 11, 0},
-	[DVBT_AD7_SETTING]	= {0x0, 0x11, 15, 0},
-	[DVBT_RSSI_R]		= {0x3, 0x1,   6, 0},
-	[DVBT_ACI_DET_IND]	= {0x3, 0x12,  0, 0},
-	[DVBT_REG_MON]		= {0x0, 0xd,   1, 0},
-	[DVBT_REG_MONSEL]	= {0x0, 0xd,   2, 2},
-	[DVBT_REG_GPE]		= {0x0, 0xd,   7, 7},
-	[DVBT_REG_GPO]		= {0x0, 0x10,  0, 0},
-	[DVBT_REG_4MSEL]	= {0x0, 0x13,  0, 0},
-};
-
-/* write multiple hardware registers */
-static int rtl2832_wr(struct rtl2832_priv *priv, u8 reg, u8 *val, int len)
-{
-	int ret;
-	u8 buf[1+len];
-	struct i2c_msg msg[1] = {
-		{
-			.addr = priv->cfg.i2c_addr,
-			.flags = 0,
-			.len = 1+len,
-			.buf = buf,
-		}
-	};
-
-	buf[0] = reg;
-	memcpy(&buf[1], val, len);
-
-	ret = i2c_transfer(priv->i2c, msg, 1);
-	if (ret == 1) {
-		ret = 0;
-	} else {
-		warn("i2c wr failed=%d reg=%02x len=%d", ret, reg, len);
-		ret = -EREMOTEIO;
-	}
-	return ret;
-}
-
-/* read multiple hardware registers */
-static int rtl2832_rd(struct rtl2832_priv *priv, u8 reg, u8 *val, int len)
-{
-	int ret;
-	struct i2c_msg msg[2] = {
-		{
-			.addr = priv->cfg.i2c_addr,
-			.flags = 0,
-			.len = 1,
-			.buf = &reg,
-		}, {
-			.addr = priv->cfg.i2c_addr,
-			.flags = I2C_M_RD,
-			.len = len,
-			.buf = val,
-		}
-	};
-
-	ret = i2c_transfer(priv->i2c, msg, 2);
-	if (ret == 2) {
-		ret = 0;
-	} else {
-		warn("i2c rd failed=%d reg=%02x len=%d", ret, reg, len);
-		ret = -EREMOTEIO;
-}
-return ret;
-}
-
-/* write multiple registers */
-static int rtl2832_wr_regs(struct rtl2832_priv *priv, u8 reg, u8 page, u8 *val,
-	int len)
-{
-	int ret;
-
-
-	/* switch bank if needed */
-	if (page != priv->page) {
-		ret = rtl2832_wr(priv, 0x00, &page, 1);
-		if (ret)
-			return ret;
-
-		priv->page = page;
-}
-
-return rtl2832_wr(priv, reg, val, len);
-}
-
-/* read multiple registers */
-static int rtl2832_rd_regs(struct rtl2832_priv *priv, u8 reg, u8 page, u8 *val,
-	int len)
-{
-	int ret;
-
-	/* switch bank if needed */
-	if (page != priv->page) {
-		ret = rtl2832_wr(priv, 0x00, &page, 1);
-		if (ret)
-			return ret;
-
-		priv->page = page;
-	}
-
-	return rtl2832_rd(priv, reg, val, len);
-}
-
-#if 0 /* currently not used */
-/* write single register */
-static int rtl2832_wr_reg(struct rtl2832_priv *priv, u8 reg, u8 page, u8 val)
-{
-	return rtl2832_wr_regs(priv, reg, page, &val, 1);
-}
-#endif
-
-/* read single register */
-static int rtl2832_rd_reg(struct rtl2832_priv *priv, u8 reg, u8 page, u8 *val)
-{
-	return rtl2832_rd_regs(priv, reg, page, val, 1);
-}
-
-int rtl2832_rd_demod_reg(struct rtl2832_priv *priv, int reg, u32 *val)
-{
-	int ret;
-
-	u8 reg_start_addr;
-	u8 msb, lsb;
-	u8 page;
-	u8 reading[4];
-	u32 reading_tmp;
-	int i;
-
-	u8 len;
-	u32 mask;
-
-	reg_start_addr = registers[reg].start_address;
-	msb = registers[reg].msb;
-	lsb = registers[reg].lsb;
-	page = registers[reg].page;
-
-	len = (msb >> 3) + 1;
-	mask = REG_MASK(msb - lsb);
-
-	ret = rtl2832_rd_regs(priv, reg_start_addr, page, &reading[0], len);
-	if (ret)
-		goto err;
-
-	reading_tmp = 0;
-	for (i = 0; i < len; i++)
-		reading_tmp |= reading[i] << ((len - 1 - i) * 8);
-
-	*val = (reading_tmp >> lsb) & mask;
-
-	return ret;
-
-err:
-	dbg("%s: failed=%d", __func__, ret);
-	return ret;
-
-}
-
-int rtl2832_wr_demod_reg(struct rtl2832_priv *priv, int reg, u32 val)
-{
-	int ret, i;
-	u8 len;
-	u8 reg_start_addr;
-	u8 msb, lsb;
-	u8 page;
-	u32 mask;
-
-
-	u8 reading[4];
-	u8 writing[4];
-	u32 reading_tmp;
-	u32 writing_tmp;
-
-
-	reg_start_addr = registers[reg].start_address;
-	msb = registers[reg].msb;
-	lsb = registers[reg].lsb;
-	page = registers[reg].page;
-
-	len = (msb >> 3) + 1;
-	mask = REG_MASK(msb - lsb);
-
-
-	ret = rtl2832_rd_regs(priv, reg_start_addr, page, &reading[0], len);
-	if (ret)
-		goto err;
-
-	reading_tmp = 0;
-	for (i = 0; i < len; i++)
-		reading_tmp |= reading[i] << ((len - 1 - i) * 8);
-
-	writing_tmp = reading_tmp & ~(mask << lsb);
-	writing_tmp |= ((val & mask) << lsb);
-
-
-	for (i = 0; i < len; i++)
-		writing[i] = (writing_tmp >> ((len - 1 - i) * 8)) & 0xff;
-
-	ret = rtl2832_wr_regs(priv, reg_start_addr, page, &writing[0], len);
-	if (ret)
-		goto err;
-
-	return ret;
-
-err:
-	dbg("%s: failed=%d", __func__, ret);
-	return ret;
-
-}
-
-
-static int rtl2832_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
-{
-	int ret;
-	struct rtl2832_priv *priv = fe->demodulator_priv;
-
-	dbg("%s: enable=%d", __func__, enable);
-
-	/* gate already open or close */
-	if (priv->i2c_gate_state == enable)
-		return 0;
-
-	ret = rtl2832_wr_demod_reg(priv, DVBT_IIC_REPEAT, (enable ? 0x1 : 0x0));
-	if (ret)
-		goto err;
-
-	priv->i2c_gate_state = enable;
-
-	return ret;
-err:
-	dbg("%s: failed=%d", __func__, ret);
-	return ret;
-}
-
-
-
-static int rtl2832_init(struct dvb_frontend *fe)
-{
-	struct rtl2832_priv *priv = fe->demodulator_priv;
-	int i, ret;
-
-	u8 en_bbin;
-	u64 pset_iffreq;
-
-	/* initialization values for the demodulator registers */
-	struct rtl2832_reg_value rtl2832_initial_regs[] = {
-		{DVBT_AD_EN_REG,		0x1},
-		{DVBT_AD_EN_REG1,		0x1},
-		{DVBT_RSD_BER_FAIL_VAL,		0x2800},
-		{DVBT_MGD_THD0,			0x10},
-		{DVBT_MGD_THD1,			0x20},
-		{DVBT_MGD_THD2,			0x20},
-		{DVBT_MGD_THD3,			0x40},
-		{DVBT_MGD_THD4,			0x22},
-		{DVBT_MGD_THD5,			0x32},
-		{DVBT_MGD_THD6,			0x37},
-		{DVBT_MGD_THD7,			0x39},
-		{DVBT_EN_BK_TRK,		0x0},
-		{DVBT_EN_CACQ_NOTCH,		0x0},
-		{DVBT_AD_AV_REF,		0x2a},
-		{DVBT_REG_PI,			0x6},
-		{DVBT_PIP_ON,			0x0},
-		{DVBT_CDIV_PH0,			0x8},
-		{DVBT_CDIV_PH1,			0x8},
-		{DVBT_SCALE1_B92,		0x4},
-		{DVBT_SCALE1_B93,		0xb0},
-		{DVBT_SCALE1_BA7,		0x78},
-		{DVBT_SCALE1_BA9,		0x28},
-		{DVBT_SCALE1_BAA,		0x59},
-		{DVBT_SCALE1_BAB,		0x83},
-		{DVBT_SCALE1_BAC,		0xd4},
-		{DVBT_SCALE1_BB0,		0x65},
-		{DVBT_SCALE1_BB1,		0x43},
-		{DVBT_KB_P1,			0x1},
-		{DVBT_KB_P2,			0x4},
-		{DVBT_KB_P3,			0x7},
-		{DVBT_K1_CR_STEP12,		0xa},
-		{DVBT_REG_GPE,			0x1},
-		{DVBT_SERIAL,			0x0},
-		{DVBT_CDIV_PH0,			0x9},
-		{DVBT_CDIV_PH1,			0x9},
-		{DVBT_MPEG_IO_OPT_2_2,		0x0},
-		{DVBT_MPEG_IO_OPT_1_0,		0x0},
-		{DVBT_TRK_KS_P2,		0x4},
-		{DVBT_TRK_KS_I2,		0x7},
-		{DVBT_TR_THD_SET2,		0x6},
-		{DVBT_TRK_KC_I2,		0x5},
-		{DVBT_CR_THD_SET2,		0x1},
-		{DVBT_SPEC_INV,			0x0},
-		{DVBT_DAGC_TRG_VAL,		0x5a},
-		{DVBT_AGC_TARG_VAL_0,		0x0},
-		{DVBT_AGC_TARG_VAL_8_1,		0x5a},
-		{DVBT_AAGC_LOOP_GAIN,		0x16},
-		{DVBT_LOOP_GAIN2_3_0,		0x6},
-		{DVBT_LOOP_GAIN2_4,		0x1},
-		{DVBT_LOOP_GAIN3,		0x16},
-		{DVBT_VTOP1,			0x35},
-		{DVBT_VTOP2,			0x21},
-		{DVBT_VTOP3,			0x21},
-		{DVBT_KRF1,			0x0},
-		{DVBT_KRF2,			0x40},
-		{DVBT_KRF3,			0x10},
-		{DVBT_KRF4,			0x10},
-		{DVBT_IF_AGC_MIN,		0x80},
-		{DVBT_IF_AGC_MAX,		0x7f},
-		{DVBT_RF_AGC_MIN,		0x80},
-		{DVBT_RF_AGC_MAX,		0x7f},
-		{DVBT_POLAR_RF_AGC,		0x0},
-		{DVBT_POLAR_IF_AGC,		0x0},
-		{DVBT_AD7_SETTING,		0xe9bf},
-		{DVBT_EN_GI_PGA,		0x0},
-		{DVBT_THD_LOCK_UP,		0x0},
-		{DVBT_THD_LOCK_DW,		0x0},
-		{DVBT_THD_UP1,			0x11},
-		{DVBT_THD_DW1,			0xef},
-		{DVBT_INTER_CNT_LEN,		0xc},
-		{DVBT_GI_PGA_STATE,		0x0},
-		{DVBT_EN_AGC_PGA,		0x1},
-		{DVBT_IF_AGC_MAN,		0x0},
-	};
-
-
-	dbg("%s", __func__);
-
-	en_bbin = (priv->cfg.if_dvbt == 0 ? 0x1 : 0x0);
-
-	/*
-	* PSET_IFFREQ = - floor((IfFreqHz % CrystalFreqHz) * pow(2, 22)
-	*		/ CrystalFreqHz)
-	*/
-	pset_iffreq = priv->cfg.if_dvbt % priv->cfg.xtal;
-	pset_iffreq *= 0x400000;
-	pset_iffreq = div_u64(pset_iffreq, priv->cfg.xtal);
-	pset_iffreq = pset_iffreq & 0x3fffff;
-
-
-
-	for (i = 0; i < ARRAY_SIZE(rtl2832_initial_regs); i++) {
-		ret = rtl2832_wr_demod_reg(priv, rtl2832_initial_regs[i].reg,
-			rtl2832_initial_regs[i].value);
-		if (ret)
-			goto err;
-	}
-
-	/* if frequency settings */
-	ret = rtl2832_wr_demod_reg(priv, DVBT_EN_BBIN, en_bbin);
-		if (ret)
-			goto err;
-
-	ret = rtl2832_wr_demod_reg(priv, DVBT_PSET_IFFREQ, pset_iffreq);
-		if (ret)
-			goto err;
-
-	priv->sleeping = false;
-
-	return ret;
-
-err:
-	dbg("%s: failed=%d", __func__, ret);
-	return ret;
-}
-
-static int rtl2832_sleep(struct dvb_frontend *fe)
-{
-	struct rtl2832_priv *priv = fe->demodulator_priv;
-
-	dbg("%s", __func__);
-	priv->sleeping = true;
-	return 0;
-}
-
-int rtl2832_get_tune_settings(struct dvb_frontend *fe,
-	struct dvb_frontend_tune_settings *s)
-{
-	dbg("%s", __func__);
-	s->min_delay_ms = 1000;
-	s->step_size = fe->ops.info.frequency_stepsize * 2;
-	s->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1;
-	return 0;
-}
-
-static int rtl2832_set_frontend(struct dvb_frontend *fe)
-{
-	struct rtl2832_priv *priv = fe->demodulator_priv;
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	int ret, i, j;
-	u64 bw_mode, num, num2;
-	u32 resamp_ratio, cfreq_off_ratio;
-
-
-	static u8 bw_params[3][32] = {
-	/* 6 MHz bandwidth */
-		{
-		0xf5, 0xff, 0x15, 0x38, 0x5d, 0x6d, 0x52, 0x07, 0xfa, 0x2f,
-		0x53, 0xf5, 0x3f, 0xca, 0x0b, 0x91, 0xea, 0x30, 0x63, 0xb2,
-		0x13, 0xda, 0x0b, 0xc4, 0x18, 0x7e, 0x16, 0x66, 0x08, 0x67,
-		0x19, 0xe0,
-		},
-
-	/*  7 MHz bandwidth */
-		{
-		0xe7, 0xcc, 0xb5, 0xba, 0xe8, 0x2f, 0x67, 0x61, 0x00, 0xaf,
-		0x86, 0xf2, 0xbf, 0x59, 0x04, 0x11, 0xb6, 0x33, 0xa4, 0x30,
-		0x15, 0x10, 0x0a, 0x42, 0x18, 0xf8, 0x17, 0xd9, 0x07, 0x22,
-		0x19, 0x10,
-		},
-
-	/*  8 MHz bandwidth */
-		{
-		0x09, 0xf6, 0xd2, 0xa7, 0x9a, 0xc9, 0x27, 0x77, 0x06, 0xbf,
-		0xec, 0xf4, 0x4f, 0x0b, 0xfc, 0x01, 0x63, 0x35, 0x54, 0xa7,
-		0x16, 0x66, 0x08, 0xb4, 0x19, 0x6e, 0x19, 0x65, 0x05, 0xc8,
-		0x19, 0xe0,
-		},
-	};
-
-
-	dbg("%s: frequency=%d bandwidth_hz=%d inversion=%d", __func__,
-		c->frequency, c->bandwidth_hz, c->inversion);
-
-
-	/* program tuner */
-	if (fe->ops.tuner_ops.set_params)
-		fe->ops.tuner_ops.set_params(fe);
-
-
-	switch (c->bandwidth_hz) {
-	case 6000000:
-		i = 0;
-		bw_mode = 48000000;
-		break;
-	case 7000000:
-		i = 1;
-		bw_mode = 56000000;
-		break;
-	case 8000000:
-		i = 2;
-		bw_mode = 64000000;
-		break;
-	default:
-		dbg("invalid bandwidth");
-		return -EINVAL;
-	}
-
-	for (j = 0; j < sizeof(bw_params[0]); j++) {
-		ret = rtl2832_wr_regs(priv, 0x1c+j, 1, &bw_params[i][j], 1);
-		if (ret)
-			goto err;
-	}
-
-	/* calculate and set resample ratio
-	* RSAMP_RATIO = floor(CrystalFreqHz * 7 * pow(2, 22)
-	*	/ ConstWithBandwidthMode)
-	*/
-	num = priv->cfg.xtal * 7;
-	num *= 0x400000;
-	num = div_u64(num, bw_mode);
-	resamp_ratio =  num & 0x3ffffff;
-	ret = rtl2832_wr_demod_reg(priv, DVBT_RSAMP_RATIO, resamp_ratio);
-	if (ret)
-		goto err;
-
-	/* calculate and set cfreq off ratio
-	* CFREQ_OFF_RATIO = - floor(ConstWithBandwidthMode * pow(2, 20)
-	*	/ (CrystalFreqHz * 7))
-	*/
-	num = bw_mode << 20;
-	num2 = priv->cfg.xtal * 7;
-	num = div_u64(num, num2);
-	num = -num;
-	cfreq_off_ratio = num & 0xfffff;
-	ret = rtl2832_wr_demod_reg(priv, DVBT_CFREQ_OFF_RATIO, cfreq_off_ratio);
-	if (ret)
-		goto err;
-
-
-	/* soft reset */
-	ret = rtl2832_wr_demod_reg(priv, DVBT_SOFT_RST, 0x1);
-	if (ret)
-		goto err;
-
-	ret = rtl2832_wr_demod_reg(priv, DVBT_SOFT_RST, 0x0);
-	if (ret)
-		goto err;
-
-	return ret;
-err:
-	info("%s: failed=%d", __func__, ret);
-	return ret;
-}
-
-static int rtl2832_read_status(struct dvb_frontend *fe, fe_status_t *status)
-{
-	struct rtl2832_priv *priv = fe->demodulator_priv;
-	int ret;
-	u32 tmp;
-	*status = 0;
-
-
-	dbg("%s", __func__);
-	if (priv->sleeping)
-		return 0;
-
-	ret = rtl2832_rd_demod_reg(priv, DVBT_FSM_STAGE, &tmp);
-	if (ret)
-		goto err;
-
-	if (tmp == 11) {
-		*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
-				FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
-	}
-	/* TODO find out if this is also true for rtl2832? */
-	/*else if (tmp == 10) {
-		*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
-				FE_HAS_VITERBI;
-	}*/
-
-	return ret;
-err:
-	info("%s: failed=%d", __func__, ret);
-	return ret;
-}
-
-static int rtl2832_read_snr(struct dvb_frontend *fe, u16 *snr)
-{
-	*snr = 0;
-	return 0;
-}
-
-static int rtl2832_read_ber(struct dvb_frontend *fe, u32 *ber)
-{
-	*ber = 0;
-	return 0;
-}
-
-static int rtl2832_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
-{
-	*ucblocks = 0;
-	return 0;
-}
-
-
-static int rtl2832_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
-{
-	*strength = 0;
-	return 0;
-}
-
-static struct dvb_frontend_ops rtl2832_ops;
-
-static void rtl2832_release(struct dvb_frontend *fe)
-{
-	struct rtl2832_priv *priv = fe->demodulator_priv;
-
-	dbg("%s", __func__);
-	kfree(priv);
-}
-
-struct dvb_frontend *rtl2832_attach(const struct rtl2832_config *cfg,
-	struct i2c_adapter *i2c)
-{
-	struct rtl2832_priv *priv = NULL;
-	int ret = 0;
-	u8 tmp;
-
-	dbg("%s", __func__);
-
-	/* allocate memory for the internal state */
-	priv = kzalloc(sizeof(struct rtl2832_priv), GFP_KERNEL);
-	if (priv == NULL)
-		goto err;
-
-	/* setup the priv */
-	priv->i2c = i2c;
-	priv->tuner = cfg->tuner;
-	memcpy(&priv->cfg, cfg, sizeof(struct rtl2832_config));
-
-	/* check if the demod is there */
-	ret = rtl2832_rd_reg(priv, 0x00, 0x0, &tmp);
-	if (ret)
-		goto err;
-
-	/* create dvb_frontend */
-	memcpy(&priv->fe.ops, &rtl2832_ops, sizeof(struct dvb_frontend_ops));
-	priv->fe.demodulator_priv = priv;
-
-	/* TODO implement sleep mode */
-	priv->sleeping = true;
-
-	return &priv->fe;
-err:
-	dbg("%s: failed=%d", __func__, ret);
-	kfree(priv);
-	return NULL;
-}
-EXPORT_SYMBOL(rtl2832_attach);
-
-static struct dvb_frontend_ops rtl2832_ops = {
-	.delsys = { SYS_DVBT },
-	.info = {
-		.name = "Realtek RTL2832 (DVB-T)",
-		.frequency_min	  = 174000000,
-		.frequency_max	  = 862000000,
-		.frequency_stepsize = 166667,
-		.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_FEC_AUTO |
-			FE_CAN_QPSK |
-			FE_CAN_QAM_16 |
-			FE_CAN_QAM_64 |
-			FE_CAN_QAM_AUTO |
-			FE_CAN_TRANSMISSION_MODE_AUTO |
-			FE_CAN_GUARD_INTERVAL_AUTO |
-			FE_CAN_HIERARCHY_AUTO |
-			FE_CAN_RECOVER |
-			FE_CAN_MUTE_TS
-	 },
-
-	.release = rtl2832_release,
-
-	.init = rtl2832_init,
-	.sleep = rtl2832_sleep,
-
-	.get_tune_settings = rtl2832_get_tune_settings,
-
-	.set_frontend = rtl2832_set_frontend,
-
-	.read_status = rtl2832_read_status,
-	.read_snr = rtl2832_read_snr,
-	.read_ber = rtl2832_read_ber,
-	.read_ucblocks = rtl2832_read_ucblocks,
-	.read_signal_strength = rtl2832_read_signal_strength,
-	.i2c_gate_ctrl = rtl2832_i2c_gate_ctrl,
-};
-
-MODULE_AUTHOR("Thomas Mair <mair.thomas86@gmail.com>");
-MODULE_DESCRIPTION("Realtek RTL2832 DVB-T demodulator driver");
-MODULE_LICENSE("GPL");
-MODULE_VERSION("0.5");
diff --git a/drivers/media/dvb/frontends/rtl2832.h b/drivers/media/dvb/frontends/rtl2832.h
deleted file mode 100644
index d94dc9a..0000000
--- a/drivers/media/dvb/frontends/rtl2832.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Realtek RTL2832 DVB-T demodulator driver
- *
- * Copyright (C) 2012 Thomas Mair <thomas.mair86@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.
- */
-
-#ifndef RTL2832_H
-#define RTL2832_H
-
-#include <linux/dvb/frontend.h>
-
-struct rtl2832_config {
-	/*
-	 * Demodulator I2C address.
-	 */
-	u8 i2c_addr;
-
-	/*
-	 * Xtal frequency.
-	 * Hz
-	 * 4000000, 16000000, 25000000, 28800000
-	 */
-	u32 xtal;
-
-	/*
-	 * IFs for all used modes.
-	 * Hz
-	 * 4570000, 4571429, 36000000, 36125000, 36166667, 44000000
-	 */
-	u32 if_dvbt;
-
-	/*
-	 */
-	u8 tuner;
-};
-
-
-#if defined(CONFIG_DVB_RTL2832) || \
-	(defined(CONFIG_DVB_RTL2832_MODULE) && defined(MODULE))
-extern struct dvb_frontend *rtl2832_attach(
-	const struct rtl2832_config *cfg,
-	struct i2c_adapter *i2c
-);
-
-extern struct i2c_adapter *rtl2832_get_tuner_i2c_adapter(
-	struct dvb_frontend *fe
-);
-#else
-static inline struct dvb_frontend *rtl2832_attach(
-	const struct rtl2832_config *config,
-	struct i2c_adapter *i2c
-)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif
-
-
-#endif /* RTL2832_H */
diff --git a/drivers/media/dvb/frontends/rtl2832_priv.h b/drivers/media/dvb/frontends/rtl2832_priv.h
deleted file mode 100644
index 0ce9502..0000000
--- a/drivers/media/dvb/frontends/rtl2832_priv.h
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
- * Realtek RTL2832 DVB-T demodulator driver
- *
- * Copyright (C) 2012 Thomas Mair <thomas.mair86@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.
- */
-
-#ifndef RTL2832_PRIV_H
-#define RTL2832_PRIV_H
-
-#include "dvb_frontend.h"
-#include "rtl2832.h"
-
-#define LOG_PREFIX "rtl2832"
-
-#undef dbg
-#define dbg(f, arg...) \
-do { \
-	if (rtl2832_debug)  \
-		printk(KERN_INFO     LOG_PREFIX": " f "\n" , ## arg); \
-} while (0)
-#undef err
-#define err(f, arg...)  printk(KERN_ERR     LOG_PREFIX": " f "\n" , ## arg)
-#undef info
-#define info(f, arg...) printk(KERN_INFO    LOG_PREFIX": " f "\n" , ## arg)
-#undef warn
-#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg)
-
-struct rtl2832_priv {
-	struct i2c_adapter *i2c;
-	struct dvb_frontend fe;
-	struct rtl2832_config cfg;
-
-	bool i2c_gate_state;
-	bool sleeping;
-
-	u8 tuner;
-	u8 page; /* active register page */
-};
-
-struct rtl2832_reg_entry {
-	u8 page;
-	u8 start_address;
-	u8 msb;
-	u8 lsb;
-};
-
-struct rtl2832_reg_value {
-	int reg;
-	u32 value;
-};
-
-
-/* Demod register bit names */
-enum DVBT_REG_BIT_NAME {
-	DVBT_SOFT_RST,
-	DVBT_IIC_REPEAT,
-	DVBT_TR_WAIT_MIN_8K,
-	DVBT_RSD_BER_FAIL_VAL,
-	DVBT_EN_BK_TRK,
-	DVBT_REG_PI,
-	DVBT_REG_PFREQ_1_0,
-	DVBT_PD_DA8,
-	DVBT_LOCK_TH,
-	DVBT_BER_PASS_SCAL,
-	DVBT_CE_FFSM_BYPASS,
-	DVBT_ALPHAIIR_N,
-	DVBT_ALPHAIIR_DIF,
-	DVBT_EN_TRK_SPAN,
-	DVBT_LOCK_TH_LEN,
-	DVBT_CCI_THRE,
-	DVBT_CCI_MON_SCAL,
-	DVBT_CCI_M0,
-	DVBT_CCI_M1,
-	DVBT_CCI_M2,
-	DVBT_CCI_M3,
-	DVBT_SPEC_INIT_0,
-	DVBT_SPEC_INIT_1,
-	DVBT_SPEC_INIT_2,
-	DVBT_AD_EN_REG,
-	DVBT_AD_EN_REG1,
-	DVBT_EN_BBIN,
-	DVBT_MGD_THD0,
-	DVBT_MGD_THD1,
-	DVBT_MGD_THD2,
-	DVBT_MGD_THD3,
-	DVBT_MGD_THD4,
-	DVBT_MGD_THD5,
-	DVBT_MGD_THD6,
-	DVBT_MGD_THD7,
-	DVBT_EN_CACQ_NOTCH,
-	DVBT_AD_AV_REF,
-	DVBT_PIP_ON,
-	DVBT_SCALE1_B92,
-	DVBT_SCALE1_B93,
-	DVBT_SCALE1_BA7,
-	DVBT_SCALE1_BA9,
-	DVBT_SCALE1_BAA,
-	DVBT_SCALE1_BAB,
-	DVBT_SCALE1_BAC,
-	DVBT_SCALE1_BB0,
-	DVBT_SCALE1_BB1,
-	DVBT_KB_P1,
-	DVBT_KB_P2,
-	DVBT_KB_P3,
-	DVBT_OPT_ADC_IQ,
-	DVBT_AD_AVI,
-	DVBT_AD_AVQ,
-	DVBT_K1_CR_STEP12,
-	DVBT_TRK_KS_P2,
-	DVBT_TRK_KS_I2,
-	DVBT_TR_THD_SET2,
-	DVBT_TRK_KC_P2,
-	DVBT_TRK_KC_I2,
-	DVBT_CR_THD_SET2,
-	DVBT_PSET_IFFREQ,
-	DVBT_SPEC_INV,
-	DVBT_BW_INDEX,
-	DVBT_RSAMP_RATIO,
-	DVBT_CFREQ_OFF_RATIO,
-	DVBT_FSM_STAGE,
-	DVBT_RX_CONSTEL,
-	DVBT_RX_HIER,
-	DVBT_RX_C_RATE_LP,
-	DVBT_RX_C_RATE_HP,
-	DVBT_GI_IDX,
-	DVBT_FFT_MODE_IDX,
-	DVBT_RSD_BER_EST,
-	DVBT_CE_EST_EVM,
-	DVBT_RF_AGC_VAL,
-	DVBT_IF_AGC_VAL,
-	DVBT_DAGC_VAL,
-	DVBT_SFREQ_OFF,
-	DVBT_CFREQ_OFF,
-	DVBT_POLAR_RF_AGC,
-	DVBT_POLAR_IF_AGC,
-	DVBT_AAGC_HOLD,
-	DVBT_EN_RF_AGC,
-	DVBT_EN_IF_AGC,
-	DVBT_IF_AGC_MIN,
-	DVBT_IF_AGC_MAX,
-	DVBT_RF_AGC_MIN,
-	DVBT_RF_AGC_MAX,
-	DVBT_IF_AGC_MAN,
-	DVBT_IF_AGC_MAN_VAL,
-	DVBT_RF_AGC_MAN,
-	DVBT_RF_AGC_MAN_VAL,
-	DVBT_DAGC_TRG_VAL,
-	DVBT_AGC_TARG_VAL,
-	DVBT_LOOP_GAIN_3_0,
-	DVBT_LOOP_GAIN_4,
-	DVBT_VTOP,
-	DVBT_KRF,
-	DVBT_AGC_TARG_VAL_0,
-	DVBT_AGC_TARG_VAL_8_1,
-	DVBT_AAGC_LOOP_GAIN,
-	DVBT_LOOP_GAIN2_3_0,
-	DVBT_LOOP_GAIN2_4,
-	DVBT_LOOP_GAIN3,
-	DVBT_VTOP1,
-	DVBT_VTOP2,
-	DVBT_VTOP3,
-	DVBT_KRF1,
-	DVBT_KRF2,
-	DVBT_KRF3,
-	DVBT_KRF4,
-	DVBT_EN_GI_PGA,
-	DVBT_THD_LOCK_UP,
-	DVBT_THD_LOCK_DW,
-	DVBT_THD_UP1,
-	DVBT_THD_DW1,
-	DVBT_INTER_CNT_LEN,
-	DVBT_GI_PGA_STATE,
-	DVBT_EN_AGC_PGA,
-	DVBT_CKOUTPAR,
-	DVBT_CKOUT_PWR,
-	DVBT_SYNC_DUR,
-	DVBT_ERR_DUR,
-	DVBT_SYNC_LVL,
-	DVBT_ERR_LVL,
-	DVBT_VAL_LVL,
-	DVBT_SERIAL,
-	DVBT_SER_LSB,
-	DVBT_CDIV_PH0,
-	DVBT_CDIV_PH1,
-	DVBT_MPEG_IO_OPT_2_2,
-	DVBT_MPEG_IO_OPT_1_0,
-	DVBT_CKOUTPAR_PIP,
-	DVBT_CKOUT_PWR_PIP,
-	DVBT_SYNC_LVL_PIP,
-	DVBT_ERR_LVL_PIP,
-	DVBT_VAL_LVL_PIP,
-	DVBT_CKOUTPAR_PID,
-	DVBT_CKOUT_PWR_PID,
-	DVBT_SYNC_LVL_PID,
-	DVBT_ERR_LVL_PID,
-	DVBT_VAL_LVL_PID,
-	DVBT_SM_PASS,
-	DVBT_UPDATE_REG_2,
-	DVBT_BTHD_P3,
-	DVBT_BTHD_D3,
-	DVBT_FUNC4_REG0,
-	DVBT_FUNC4_REG1,
-	DVBT_FUNC4_REG2,
-	DVBT_FUNC4_REG3,
-	DVBT_FUNC4_REG4,
-	DVBT_FUNC4_REG5,
-	DVBT_FUNC4_REG6,
-	DVBT_FUNC4_REG7,
-	DVBT_FUNC4_REG8,
-	DVBT_FUNC4_REG9,
-	DVBT_FUNC4_REG10,
-	DVBT_FUNC5_REG0,
-	DVBT_FUNC5_REG1,
-	DVBT_FUNC5_REG2,
-	DVBT_FUNC5_REG3,
-	DVBT_FUNC5_REG4,
-	DVBT_FUNC5_REG5,
-	DVBT_FUNC5_REG6,
-	DVBT_FUNC5_REG7,
-	DVBT_FUNC5_REG8,
-	DVBT_FUNC5_REG9,
-	DVBT_FUNC5_REG10,
-	DVBT_FUNC5_REG11,
-	DVBT_FUNC5_REG12,
-	DVBT_FUNC5_REG13,
-	DVBT_FUNC5_REG14,
-	DVBT_FUNC5_REG15,
-	DVBT_FUNC5_REG16,
-	DVBT_FUNC5_REG17,
-	DVBT_FUNC5_REG18,
-	DVBT_AD7_SETTING,
-	DVBT_RSSI_R,
-	DVBT_ACI_DET_IND,
-	DVBT_REG_MON,
-	DVBT_REG_MONSEL,
-	DVBT_REG_GPE,
-	DVBT_REG_GPO,
-	DVBT_REG_4MSEL,
-	DVBT_TEST_REG_1,
-	DVBT_TEST_REG_2,
-	DVBT_TEST_REG_3,
-	DVBT_TEST_REG_4,
-	DVBT_REG_BIT_NAME_ITEM_TERMINATOR,
-};
-
-#endif /* RTL2832_PRIV_H */
diff --git a/drivers/media/dvb/frontends/s5h1409.c b/drivers/media/dvb/frontends/s5h1409.c
deleted file mode 100644
index f71b062..0000000
--- a/drivers/media/dvb/frontends/s5h1409.c
+++ /dev/null
@@ -1,1029 +0,0 @@
-/*
-    Samsung S5H1409 VSB/QAM demodulator driver
-
-    Copyright (C) 2006 Steven Toth <stoth@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/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include "dvb_frontend.h"
-#include "s5h1409.h"
-
-struct s5h1409_state {
-
-	struct i2c_adapter *i2c;
-
-	/* configuration settings */
-	const struct s5h1409_config *config;
-
-	struct dvb_frontend frontend;
-
-	/* previous uncorrected block counter */
-	fe_modulation_t current_modulation;
-
-	u32 current_frequency;
-	int if_freq;
-
-	u32 is_qam_locked;
-
-	/* QAM tuning state goes through the following state transitions */
-#define QAM_STATE_UNTUNED 0
-#define QAM_STATE_TUNING_STARTED 1
-#define QAM_STATE_INTERLEAVE_SET 2
-#define QAM_STATE_QAM_OPTIMIZED_L1 3
-#define QAM_STATE_QAM_OPTIMIZED_L2 4
-#define QAM_STATE_QAM_OPTIMIZED_L3 5
-	u8  qam_state;
-};
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Enable verbose debug messages");
-
-#define dprintk	if (debug) printk
-
-/* Register values to initialise the demod, this will set VSB by default */
-static struct init_tab {
-	u8	reg;
-	u16	data;
-} init_tab[] = {
-	{ 0x00, 0x0071, },
-	{ 0x01, 0x3213, },
-	{ 0x09, 0x0025, },
-	{ 0x1c, 0x001d, },
-	{ 0x1f, 0x002d, },
-	{ 0x20, 0x001d, },
-	{ 0x22, 0x0022, },
-	{ 0x23, 0x0020, },
-	{ 0x29, 0x110f, },
-	{ 0x2a, 0x10b4, },
-	{ 0x2b, 0x10ae, },
-	{ 0x2c, 0x0031, },
-	{ 0x31, 0x010d, },
-	{ 0x32, 0x0100, },
-	{ 0x44, 0x0510, },
-	{ 0x54, 0x0104, },
-	{ 0x58, 0x2222, },
-	{ 0x59, 0x1162, },
-	{ 0x5a, 0x3211, },
-	{ 0x5d, 0x0370, },
-	{ 0x5e, 0x0296, },
-	{ 0x61, 0x0010, },
-	{ 0x63, 0x4a00, },
-	{ 0x65, 0x0800, },
-	{ 0x71, 0x0003, },
-	{ 0x72, 0x0470, },
-	{ 0x81, 0x0002, },
-	{ 0x82, 0x0600, },
-	{ 0x86, 0x0002, },
-	{ 0x8a, 0x2c38, },
-	{ 0x8b, 0x2a37, },
-	{ 0x92, 0x302f, },
-	{ 0x93, 0x3332, },
-	{ 0x96, 0x000c, },
-	{ 0x99, 0x0101, },
-	{ 0x9c, 0x2e37, },
-	{ 0x9d, 0x2c37, },
-	{ 0x9e, 0x2c37, },
-	{ 0xab, 0x0100, },
-	{ 0xac, 0x1003, },
-	{ 0xad, 0x103f, },
-	{ 0xe2, 0x0100, },
-	{ 0xe3, 0x1000, },
-	{ 0x28, 0x1010, },
-	{ 0xb1, 0x000e, },
-};
-
-/* VSB SNR lookup table */
-static struct vsb_snr_tab {
-	u16	val;
-	u16	data;
-} vsb_snr_tab[] = {
-	{  924, 300, },
-	{  923, 300, },
-	{  918, 295, },
-	{  915, 290, },
-	{  911, 285, },
-	{  906, 280, },
-	{  901, 275, },
-	{  896, 270, },
-	{  891, 265, },
-	{  885, 260, },
-	{  879, 255, },
-	{  873, 250, },
-	{  864, 245, },
-	{  858, 240, },
-	{  850, 235, },
-	{  841, 230, },
-	{  832, 225, },
-	{  823, 220, },
-	{  812, 215, },
-	{  802, 210, },
-	{  788, 205, },
-	{  778, 200, },
-	{  767, 195, },
-	{  753, 190, },
-	{  740, 185, },
-	{  725, 180, },
-	{  707, 175, },
-	{  689, 170, },
-	{  671, 165, },
-	{  656, 160, },
-	{  637, 155, },
-	{  616, 150, },
-	{  542, 145, },
-	{  519, 140, },
-	{  507, 135, },
-	{  497, 130, },
-	{  492, 125, },
-	{  474, 120, },
-	{  300, 111, },
-	{    0,   0, },
-};
-
-/* QAM64 SNR lookup table */
-static struct qam64_snr_tab {
-	u16	val;
-	u16	data;
-} qam64_snr_tab[] = {
-	{    1,   0, },
-	{   12, 300, },
-	{   15, 290, },
-	{   18, 280, },
-	{   22, 270, },
-	{   23, 268, },
-	{   24, 266, },
-	{   25, 264, },
-	{   27, 262, },
-	{   28, 260, },
-	{   29, 258, },
-	{   30, 256, },
-	{   32, 254, },
-	{   33, 252, },
-	{   34, 250, },
-	{   35, 249, },
-	{   36, 248, },
-	{   37, 247, },
-	{   38, 246, },
-	{   39, 245, },
-	{   40, 244, },
-	{   41, 243, },
-	{   42, 241, },
-	{   43, 240, },
-	{   44, 239, },
-	{   45, 238, },
-	{   46, 237, },
-	{   47, 236, },
-	{   48, 235, },
-	{   49, 234, },
-	{   50, 233, },
-	{   51, 232, },
-	{   52, 231, },
-	{   53, 230, },
-	{   55, 229, },
-	{   56, 228, },
-	{   57, 227, },
-	{   58, 226, },
-	{   59, 225, },
-	{   60, 224, },
-	{   62, 223, },
-	{   63, 222, },
-	{   65, 221, },
-	{   66, 220, },
-	{   68, 219, },
-	{   69, 218, },
-	{   70, 217, },
-	{   72, 216, },
-	{   73, 215, },
-	{   75, 214, },
-	{   76, 213, },
-	{   78, 212, },
-	{   80, 211, },
-	{   81, 210, },
-	{   83, 209, },
-	{   84, 208, },
-	{   85, 207, },
-	{   87, 206, },
-	{   89, 205, },
-	{   91, 204, },
-	{   93, 203, },
-	{   95, 202, },
-	{   96, 201, },
-	{  104, 200, },
-	{  255,   0, },
-};
-
-/* QAM256 SNR lookup table */
-static struct qam256_snr_tab {
-	u16	val;
-	u16	data;
-} qam256_snr_tab[] = {
-	{    1,   0, },
-	{   12, 400, },
-	{   13, 390, },
-	{   15, 380, },
-	{   17, 360, },
-	{   19, 350, },
-	{   22, 348, },
-	{   23, 346, },
-	{   24, 344, },
-	{   25, 342, },
-	{   26, 340, },
-	{   27, 336, },
-	{   28, 334, },
-	{   29, 332, },
-	{   30, 330, },
-	{   31, 328, },
-	{   32, 326, },
-	{   33, 325, },
-	{   34, 322, },
-	{   35, 320, },
-	{   37, 318, },
-	{   39, 316, },
-	{   40, 314, },
-	{   41, 312, },
-	{   42, 310, },
-	{   43, 308, },
-	{   46, 306, },
-	{   47, 304, },
-	{   49, 302, },
-	{   51, 300, },
-	{   53, 298, },
-	{   54, 297, },
-	{   55, 296, },
-	{   56, 295, },
-	{   57, 294, },
-	{   59, 293, },
-	{   60, 292, },
-	{   61, 291, },
-	{   63, 290, },
-	{   64, 289, },
-	{   65, 288, },
-	{   66, 287, },
-	{   68, 286, },
-	{   69, 285, },
-	{   71, 284, },
-	{   72, 283, },
-	{   74, 282, },
-	{   75, 281, },
-	{   76, 280, },
-	{   77, 279, },
-	{   78, 278, },
-	{   81, 277, },
-	{   83, 276, },
-	{   84, 275, },
-	{   86, 274, },
-	{   87, 273, },
-	{   89, 272, },
-	{   90, 271, },
-	{   92, 270, },
-	{   93, 269, },
-	{   95, 268, },
-	{   96, 267, },
-	{   98, 266, },
-	{  100, 265, },
-	{  102, 264, },
-	{  104, 263, },
-	{  105, 262, },
-	{  106, 261, },
-	{  110, 260, },
-	{  255,   0, },
-};
-
-/* 8 bit registers, 16 bit values */
-static int s5h1409_writereg(struct s5h1409_state *state, u8 reg, u16 data)
-{
-	int ret;
-	u8 buf[] = { reg, data >> 8,  data & 0xff };
-
-	struct i2c_msg msg = { .addr = state->config->demod_address,
-			       .flags = 0, .buf = buf, .len = 3 };
-
-	ret = i2c_transfer(state->i2c, &msg, 1);
-
-	if (ret != 1)
-		printk(KERN_ERR "%s: error (reg == 0x%02x, val == 0x%04x, "
-		       "ret == %i)\n", __func__, reg, data, ret);
-
-	return (ret != 1) ? -1 : 0;
-}
-
-static u16 s5h1409_readreg(struct s5h1409_state *state, u8 reg)
-{
-	int ret;
-	u8 b0[] = { reg };
-	u8 b1[] = { 0, 0 };
-
-	struct i2c_msg msg[] = {
-		{ .addr = state->config->demod_address, .flags = 0,
-		  .buf = b0, .len = 1 },
-		{ .addr = state->config->demod_address, .flags = I2C_M_RD,
-		  .buf = b1, .len = 2 } };
-
-	ret = i2c_transfer(state->i2c, msg, 2);
-
-	if (ret != 2)
-		printk("%s: readreg error (ret == %i)\n", __func__, ret);
-	return (b1[0] << 8) | b1[1];
-}
-
-static int s5h1409_softreset(struct dvb_frontend *fe)
-{
-	struct s5h1409_state *state = fe->demodulator_priv;
-
-	dprintk("%s()\n", __func__);
-
-	s5h1409_writereg(state, 0xf5, 0);
-	s5h1409_writereg(state, 0xf5, 1);
-	state->is_qam_locked = 0;
-	state->qam_state = QAM_STATE_UNTUNED;
-	return 0;
-}
-
-#define S5H1409_VSB_IF_FREQ 5380
-#define S5H1409_QAM_IF_FREQ (state->config->qam_if)
-
-static int s5h1409_set_if_freq(struct dvb_frontend *fe, int KHz)
-{
-	struct s5h1409_state *state = fe->demodulator_priv;
-
-	dprintk("%s(%d KHz)\n", __func__, KHz);
-
-	switch (KHz) {
-	case 4000:
-		s5h1409_writereg(state, 0x87, 0x014b);
-		s5h1409_writereg(state, 0x88, 0x0cb5);
-		s5h1409_writereg(state, 0x89, 0x03e2);
-		break;
-	case 5380:
-	case 44000:
-	default:
-		s5h1409_writereg(state, 0x87, 0x01be);
-		s5h1409_writereg(state, 0x88, 0x0436);
-		s5h1409_writereg(state, 0x89, 0x054d);
-		break;
-	}
-	state->if_freq = KHz;
-
-	return 0;
-}
-
-static int s5h1409_set_spectralinversion(struct dvb_frontend *fe, int inverted)
-{
-	struct s5h1409_state *state = fe->demodulator_priv;
-
-	dprintk("%s(%d)\n", __func__, inverted);
-
-	if (inverted == 1)
-		return s5h1409_writereg(state, 0x1b, 0x1101); /* Inverted */
-	else
-		return s5h1409_writereg(state, 0x1b, 0x0110); /* Normal */
-}
-
-static int s5h1409_enable_modulation(struct dvb_frontend *fe,
-				     fe_modulation_t m)
-{
-	struct s5h1409_state *state = fe->demodulator_priv;
-
-	dprintk("%s(0x%08x)\n", __func__, m);
-
-	switch (m) {
-	case VSB_8:
-		dprintk("%s() VSB_8\n", __func__);
-		if (state->if_freq != S5H1409_VSB_IF_FREQ)
-			s5h1409_set_if_freq(fe, S5H1409_VSB_IF_FREQ);
-		s5h1409_writereg(state, 0xf4, 0);
-		break;
-	case QAM_64:
-	case QAM_256:
-	case QAM_AUTO:
-		dprintk("%s() QAM_AUTO (64/256)\n", __func__);
-		if (state->if_freq != S5H1409_QAM_IF_FREQ)
-			s5h1409_set_if_freq(fe, S5H1409_QAM_IF_FREQ);
-		s5h1409_writereg(state, 0xf4, 1);
-		s5h1409_writereg(state, 0x85, 0x110);
-		break;
-	default:
-		dprintk("%s() Invalid modulation\n", __func__);
-		return -EINVAL;
-	}
-
-	state->current_modulation = m;
-	s5h1409_softreset(fe);
-
-	return 0;
-}
-
-static int s5h1409_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
-{
-	struct s5h1409_state *state = fe->demodulator_priv;
-
-	dprintk("%s(%d)\n", __func__, enable);
-
-	if (enable)
-		return s5h1409_writereg(state, 0xf3, 1);
-	else
-		return s5h1409_writereg(state, 0xf3, 0);
-}
-
-static int s5h1409_set_gpio(struct dvb_frontend *fe, int enable)
-{
-	struct s5h1409_state *state = fe->demodulator_priv;
-
-	dprintk("%s(%d)\n", __func__, enable);
-
-	if (enable)
-		return s5h1409_writereg(state, 0xe3,
-			s5h1409_readreg(state, 0xe3) | 0x1100);
-	else
-		return s5h1409_writereg(state, 0xe3,
-			s5h1409_readreg(state, 0xe3) & 0xfeff);
-}
-
-static int s5h1409_sleep(struct dvb_frontend *fe, int enable)
-{
-	struct s5h1409_state *state = fe->demodulator_priv;
-
-	dprintk("%s(%d)\n", __func__, enable);
-
-	return s5h1409_writereg(state, 0xf2, enable);
-}
-
-static int s5h1409_register_reset(struct dvb_frontend *fe)
-{
-	struct s5h1409_state *state = fe->demodulator_priv;
-
-	dprintk("%s()\n", __func__);
-
-	return s5h1409_writereg(state, 0xfa, 0);
-}
-
-static void s5h1409_set_qam_amhum_mode(struct dvb_frontend *fe)
-{
-	struct s5h1409_state *state = fe->demodulator_priv;
-	u16 reg;
-
-	if (state->qam_state < QAM_STATE_INTERLEAVE_SET) {
-		/* We should not perform amhum optimization until
-		   the interleave mode has been configured */
-		return;
-	}
-
-	if (state->qam_state == QAM_STATE_QAM_OPTIMIZED_L3) {
-		/* We've already reached the maximum optimization level, so
-		   dont bother banging on the status registers */
-		return;
-	}
-
-	/* QAM EQ lock check */
-	reg = s5h1409_readreg(state, 0xf0);
-
-	if ((reg >> 13) & 0x1) {
-		reg &= 0xff;
-
-		s5h1409_writereg(state, 0x96, 0x000c);
-		if (reg < 0x68) {
-			if (state->qam_state < QAM_STATE_QAM_OPTIMIZED_L3) {
-				dprintk("%s() setting QAM state to OPT_L3\n",
-					__func__);
-				s5h1409_writereg(state, 0x93, 0x3130);
-				s5h1409_writereg(state, 0x9e, 0x2836);
-				state->qam_state = QAM_STATE_QAM_OPTIMIZED_L3;
-			}
-		} else {
-			if (state->qam_state < QAM_STATE_QAM_OPTIMIZED_L2) {
-				dprintk("%s() setting QAM state to OPT_L2\n",
-					__func__);
-				s5h1409_writereg(state, 0x93, 0x3332);
-				s5h1409_writereg(state, 0x9e, 0x2c37);
-				state->qam_state = QAM_STATE_QAM_OPTIMIZED_L2;
-			}
-		}
-
-	} else {
-		if (state->qam_state < QAM_STATE_QAM_OPTIMIZED_L1) {
-			dprintk("%s() setting QAM state to OPT_L1\n", __func__);
-			s5h1409_writereg(state, 0x96, 0x0008);
-			s5h1409_writereg(state, 0x93, 0x3332);
-			s5h1409_writereg(state, 0x9e, 0x2c37);
-			state->qam_state = QAM_STATE_QAM_OPTIMIZED_L1;
-		}
-	}
-}
-
-static void s5h1409_set_qam_amhum_mode_legacy(struct dvb_frontend *fe)
-{
-	struct s5h1409_state *state = fe->demodulator_priv;
-	u16 reg;
-
-	if (state->is_qam_locked)
-		return;
-
-	/* QAM EQ lock check */
-	reg = s5h1409_readreg(state, 0xf0);
-
-	if ((reg >> 13) & 0x1) {
-
-		state->is_qam_locked = 1;
-		reg &= 0xff;
-
-		s5h1409_writereg(state, 0x96, 0x00c);
-		if ((reg < 0x38) || (reg > 0x68)) {
-			s5h1409_writereg(state, 0x93, 0x3332);
-			s5h1409_writereg(state, 0x9e, 0x2c37);
-		} else {
-			s5h1409_writereg(state, 0x93, 0x3130);
-			s5h1409_writereg(state, 0x9e, 0x2836);
-		}
-
-	} else {
-		s5h1409_writereg(state, 0x96, 0x0008);
-		s5h1409_writereg(state, 0x93, 0x3332);
-		s5h1409_writereg(state, 0x9e, 0x2c37);
-	}
-}
-
-static void s5h1409_set_qam_interleave_mode(struct dvb_frontend *fe)
-{
-	struct s5h1409_state *state = fe->demodulator_priv;
-	u16 reg, reg1, reg2;
-
-	if (state->qam_state >= QAM_STATE_INTERLEAVE_SET) {
-		/* We've done the optimization already */
-		return;
-	}
-
-	reg = s5h1409_readreg(state, 0xf1);
-
-	/* Master lock */
-	if ((reg >> 15) & 0x1) {
-		if (state->qam_state == QAM_STATE_UNTUNED ||
-		    state->qam_state == QAM_STATE_TUNING_STARTED) {
-			dprintk("%s() setting QAM state to INTERLEAVE_SET\n",
-				__func__);
-			reg1 = s5h1409_readreg(state, 0xb2);
-			reg2 = s5h1409_readreg(state, 0xad);
-
-			s5h1409_writereg(state, 0x96, 0x0020);
-			s5h1409_writereg(state, 0xad,
-				(((reg1 & 0xf000) >> 4) | (reg2 & 0xf0ff)));
-			state->qam_state = QAM_STATE_INTERLEAVE_SET;
-		}
-	} else {
-		if (state->qam_state == QAM_STATE_UNTUNED) {
-			dprintk("%s() setting QAM state to TUNING_STARTED\n",
-				__func__);
-			s5h1409_writereg(state, 0x96, 0x08);
-			s5h1409_writereg(state, 0xab,
-				s5h1409_readreg(state, 0xab) | 0x1001);
-			state->qam_state = QAM_STATE_TUNING_STARTED;
-		}
-	}
-}
-
-static void s5h1409_set_qam_interleave_mode_legacy(struct dvb_frontend *fe)
-{
-	struct s5h1409_state *state = fe->demodulator_priv;
-	u16 reg, reg1, reg2;
-
-	reg = s5h1409_readreg(state, 0xf1);
-
-	/* Master lock */
-	if ((reg >> 15) & 0x1) {
-		if (state->qam_state != 2) {
-			state->qam_state = 2;
-			reg1 = s5h1409_readreg(state, 0xb2);
-			reg2 = s5h1409_readreg(state, 0xad);
-
-			s5h1409_writereg(state, 0x96, 0x20);
-			s5h1409_writereg(state, 0xad,
-				(((reg1 & 0xf000) >> 4) | (reg2 & 0xf0ff)));
-			s5h1409_writereg(state, 0xab,
-				s5h1409_readreg(state, 0xab) & 0xeffe);
-		}
-	} else {
-		if (state->qam_state != 1) {
-			state->qam_state = 1;
-			s5h1409_writereg(state, 0x96, 0x08);
-			s5h1409_writereg(state, 0xab,
-				s5h1409_readreg(state, 0xab) | 0x1001);
-		}
-	}
-}
-
-/* Talk to the demod, set the FEC, GUARD, QAM settings etc */
-static int s5h1409_set_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct s5h1409_state *state = fe->demodulator_priv;
-
-	dprintk("%s(frequency=%d)\n", __func__, p->frequency);
-
-	s5h1409_softreset(fe);
-
-	state->current_frequency = p->frequency;
-
-	s5h1409_enable_modulation(fe, p->modulation);
-
-	if (fe->ops.tuner_ops.set_params) {
-		if (fe->ops.i2c_gate_ctrl)
-			fe->ops.i2c_gate_ctrl(fe, 1);
-		fe->ops.tuner_ops.set_params(fe);
-		if (fe->ops.i2c_gate_ctrl)
-			fe->ops.i2c_gate_ctrl(fe, 0);
-	}
-
-	/* Issue a reset to the demod so it knows to resync against the
-	   newly tuned frequency */
-	s5h1409_softreset(fe);
-
-	/* Optimize the demod for QAM */
-	if (state->current_modulation != VSB_8) {
-		/* This almost certainly applies to all boards, but for now
-		   only do it for the HVR-1600.  Once the other boards are
-		   tested, the "legacy" versions can just go away */
-		if (state->config->hvr1600_opt == S5H1409_HVR1600_OPTIMIZE) {
-			s5h1409_set_qam_interleave_mode(fe);
-			s5h1409_set_qam_amhum_mode(fe);
-		} else {
-			s5h1409_set_qam_amhum_mode_legacy(fe);
-			s5h1409_set_qam_interleave_mode_legacy(fe);
-		}
-	}
-
-	return 0;
-}
-
-static int s5h1409_set_mpeg_timing(struct dvb_frontend *fe, int mode)
-{
-	struct s5h1409_state *state = fe->demodulator_priv;
-	u16 val;
-
-	dprintk("%s(%d)\n", __func__, mode);
-
-	val = s5h1409_readreg(state, 0xac) & 0xcfff;
-	switch (mode) {
-	case S5H1409_MPEGTIMING_CONTINOUS_INVERTING_CLOCK:
-		val |= 0x0000;
-		break;
-	case S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK:
-		dprintk("%s(%d) Mode1 or Defaulting\n", __func__, mode);
-		val |= 0x1000;
-		break;
-	case S5H1409_MPEGTIMING_NONCONTINOUS_INVERTING_CLOCK:
-		val |= 0x2000;
-		break;
-	case S5H1409_MPEGTIMING_NONCONTINOUS_NONINVERTING_CLOCK:
-		val |= 0x3000;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	/* Configure MPEG Signal Timing charactistics */
-	return s5h1409_writereg(state, 0xac, val);
-}
-
-/* Reset the demod hardware and reset all of the configuration registers
-   to a default state. */
-static int s5h1409_init(struct dvb_frontend *fe)
-{
-	int i;
-
-	struct s5h1409_state *state = fe->demodulator_priv;
-	dprintk("%s()\n", __func__);
-
-	s5h1409_sleep(fe, 0);
-	s5h1409_register_reset(fe);
-
-	for (i = 0; i < ARRAY_SIZE(init_tab); i++)
-		s5h1409_writereg(state, init_tab[i].reg, init_tab[i].data);
-
-	/* The datasheet says that after initialisation, VSB is default */
-	state->current_modulation = VSB_8;
-
-	/* Optimize for the HVR-1600 if appropriate.  Note that some of these
-	   may get folded into the generic case after testing with other
-	   devices */
-	if (state->config->hvr1600_opt == S5H1409_HVR1600_OPTIMIZE) {
-		/* VSB AGC REF */
-		s5h1409_writereg(state, 0x09, 0x0050);
-
-		/* Unknown but Windows driver does it... */
-		s5h1409_writereg(state, 0x21, 0x0001);
-		s5h1409_writereg(state, 0x50, 0x030e);
-
-		/* QAM AGC REF */
-		s5h1409_writereg(state, 0x82, 0x0800);
-	}
-
-	if (state->config->output_mode == S5H1409_SERIAL_OUTPUT)
-		s5h1409_writereg(state, 0xab,
-			s5h1409_readreg(state, 0xab) | 0x100); /* Serial */
-	else
-		s5h1409_writereg(state, 0xab,
-			s5h1409_readreg(state, 0xab) & 0xfeff); /* Parallel */
-
-	s5h1409_set_spectralinversion(fe, state->config->inversion);
-	s5h1409_set_if_freq(fe, state->if_freq);
-	s5h1409_set_gpio(fe, state->config->gpio);
-	s5h1409_set_mpeg_timing(fe, state->config->mpeg_timing);
-	s5h1409_softreset(fe);
-
-	/* Note: Leaving the I2C gate closed. */
-	s5h1409_i2c_gate_ctrl(fe, 0);
-
-	return 0;
-}
-
-static int s5h1409_read_status(struct dvb_frontend *fe, fe_status_t *status)
-{
-	struct s5h1409_state *state = fe->demodulator_priv;
-	u16 reg;
-	u32 tuner_status = 0;
-
-	*status = 0;
-
-	/* Optimize the demod for QAM */
-	if (state->current_modulation != VSB_8) {
-		/* This almost certainly applies to all boards, but for now
-		   only do it for the HVR-1600.  Once the other boards are
-		   tested, the "legacy" versions can just go away */
-		if (state->config->hvr1600_opt == S5H1409_HVR1600_OPTIMIZE) {
-			s5h1409_set_qam_interleave_mode(fe);
-			s5h1409_set_qam_amhum_mode(fe);
-		}
-	}
-
-	/* Get the demodulator status */
-	reg = s5h1409_readreg(state, 0xf1);
-	if (reg & 0x1000)
-		*status |= FE_HAS_VITERBI;
-	if (reg & 0x8000)
-		*status |= FE_HAS_LOCK | FE_HAS_SYNC;
-
-	switch (state->config->status_mode) {
-	case S5H1409_DEMODLOCKING:
-		if (*status & FE_HAS_VITERBI)
-			*status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
-		break;
-	case S5H1409_TUNERLOCKING:
-		/* Get the tuner status */
-		if (fe->ops.tuner_ops.get_status) {
-			if (fe->ops.i2c_gate_ctrl)
-				fe->ops.i2c_gate_ctrl(fe, 1);
-
-			fe->ops.tuner_ops.get_status(fe, &tuner_status);
-
-			if (fe->ops.i2c_gate_ctrl)
-				fe->ops.i2c_gate_ctrl(fe, 0);
-		}
-		if (tuner_status)
-			*status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
-		break;
-	}
-
-	dprintk("%s() status 0x%08x\n", __func__, *status);
-
-	return 0;
-}
-
-static int s5h1409_qam256_lookup_snr(struct dvb_frontend *fe, u16 *snr, u16 v)
-{
-	int i, ret = -EINVAL;
-	dprintk("%s()\n", __func__);
-
-	for (i = 0; i < ARRAY_SIZE(qam256_snr_tab); i++) {
-		if (v < qam256_snr_tab[i].val) {
-			*snr = qam256_snr_tab[i].data;
-			ret = 0;
-			break;
-		}
-	}
-	return ret;
-}
-
-static int s5h1409_qam64_lookup_snr(struct dvb_frontend *fe, u16 *snr, u16 v)
-{
-	int i, ret = -EINVAL;
-	dprintk("%s()\n", __func__);
-
-	for (i = 0; i < ARRAY_SIZE(qam64_snr_tab); i++) {
-		if (v < qam64_snr_tab[i].val) {
-			*snr = qam64_snr_tab[i].data;
-			ret = 0;
-			break;
-		}
-	}
-	return ret;
-}
-
-static int s5h1409_vsb_lookup_snr(struct dvb_frontend *fe, u16 *snr, u16 v)
-{
-	int i, ret = -EINVAL;
-	dprintk("%s()\n", __func__);
-
-	for (i = 0; i < ARRAY_SIZE(vsb_snr_tab); i++) {
-		if (v > vsb_snr_tab[i].val) {
-			*snr = vsb_snr_tab[i].data;
-			ret = 0;
-			break;
-		}
-	}
-	dprintk("%s() snr=%d\n", __func__, *snr);
-	return ret;
-}
-
-static int s5h1409_read_snr(struct dvb_frontend *fe, u16 *snr)
-{
-	struct s5h1409_state *state = fe->demodulator_priv;
-	u16 reg;
-	dprintk("%s()\n", __func__);
-
-	switch (state->current_modulation) {
-	case QAM_64:
-		reg = s5h1409_readreg(state, 0xf0) & 0xff;
-		return s5h1409_qam64_lookup_snr(fe, snr, reg);
-	case QAM_256:
-		reg = s5h1409_readreg(state, 0xf0) & 0xff;
-		return s5h1409_qam256_lookup_snr(fe, snr, reg);
-	case VSB_8:
-		reg = s5h1409_readreg(state, 0xf1) & 0x3ff;
-		return s5h1409_vsb_lookup_snr(fe, snr, reg);
-	default:
-		break;
-	}
-
-	return -EINVAL;
-}
-
-static int s5h1409_read_signal_strength(struct dvb_frontend *fe,
-					u16 *signal_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%
-	 */
-	u16 snr;
-	u32 tmp;
-	int ret = s5h1409_read_snr(fe, &snr);
-
-	*signal_strength = 0;
-
-	if (0 == ret) {
-		/* The following calculation method was chosen
-		 * purely for the sake of code re-use from the
-		 * other demod drivers that use this method */
-
-		/* Convert from SNR in dB * 10 to 8.24 fixed-point */
-		tmp = (snr * ((1 << 24) / 10));
-
-		/* Convert from 8.24 fixed-point to
-		 * scale the range 0 - 35*2^24 into 0 - 65535*/
-		if (tmp >= 8960 * 0x10000)
-			*signal_strength = 0xffff;
-		else
-			*signal_strength = tmp / 8960;
-	}
-
-	return ret;
-}
-
-static int s5h1409_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
-{
-	struct s5h1409_state *state = fe->demodulator_priv;
-
-	*ucblocks = s5h1409_readreg(state, 0xb5);
-
-	return 0;
-}
-
-static int s5h1409_read_ber(struct dvb_frontend *fe, u32 *ber)
-{
-	return s5h1409_read_ucblocks(fe, ber);
-}
-
-static int s5h1409_get_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct s5h1409_state *state = fe->demodulator_priv;
-
-	p->frequency = state->current_frequency;
-	p->modulation = state->current_modulation;
-
-	return 0;
-}
-
-static int s5h1409_get_tune_settings(struct dvb_frontend *fe,
-				     struct dvb_frontend_tune_settings *tune)
-{
-	tune->min_delay_ms = 1000;
-	return 0;
-}
-
-static void s5h1409_release(struct dvb_frontend *fe)
-{
-	struct s5h1409_state *state = fe->demodulator_priv;
-	kfree(state);
-}
-
-static struct dvb_frontend_ops s5h1409_ops;
-
-struct dvb_frontend *s5h1409_attach(const struct s5h1409_config *config,
-				    struct i2c_adapter *i2c)
-{
-	struct s5h1409_state *state = NULL;
-	u16 reg;
-
-	/* allocate memory for the internal state */
-	state = kzalloc(sizeof(struct s5h1409_state), GFP_KERNEL);
-	if (state == NULL)
-		goto error;
-
-	/* setup the state */
-	state->config = config;
-	state->i2c = i2c;
-	state->current_modulation = 0;
-	state->if_freq = S5H1409_VSB_IF_FREQ;
-
-	/* check if the demod exists */
-	reg = s5h1409_readreg(state, 0x04);
-	if ((reg != 0x0066) && (reg != 0x007f))
-		goto error;
-
-	/* create dvb_frontend */
-	memcpy(&state->frontend.ops, &s5h1409_ops,
-	       sizeof(struct dvb_frontend_ops));
-	state->frontend.demodulator_priv = state;
-
-	if (s5h1409_init(&state->frontend) != 0) {
-		printk(KERN_ERR "%s: Failed to initialize correctly\n",
-			__func__);
-		goto error;
-	}
-
-	/* Note: Leaving the I2C gate open here. */
-	s5h1409_i2c_gate_ctrl(&state->frontend, 1);
-
-	return &state->frontend;
-
-error:
-	kfree(state);
-	return NULL;
-}
-EXPORT_SYMBOL(s5h1409_attach);
-
-static struct dvb_frontend_ops s5h1409_ops = {
-	.delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
-	.info = {
-		.name			= "Samsung S5H1409 QAM/8VSB Frontend",
-		.frequency_min		= 54000000,
-		.frequency_max		= 858000000,
-		.frequency_stepsize	= 62500,
-		.caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
-	},
-
-	.init                 = s5h1409_init,
-	.i2c_gate_ctrl        = s5h1409_i2c_gate_ctrl,
-	.set_frontend         = s5h1409_set_frontend,
-	.get_frontend         = s5h1409_get_frontend,
-	.get_tune_settings    = s5h1409_get_tune_settings,
-	.read_status          = s5h1409_read_status,
-	.read_ber             = s5h1409_read_ber,
-	.read_signal_strength = s5h1409_read_signal_strength,
-	.read_snr             = s5h1409_read_snr,
-	.read_ucblocks        = s5h1409_read_ucblocks,
-	.release              = s5h1409_release,
-};
-
-MODULE_DESCRIPTION("Samsung S5H1409 QAM-B/ATSC Demodulator driver");
-MODULE_AUTHOR("Steven Toth");
-MODULE_LICENSE("GPL");
-
-
-/*
- * Local variables:
- * c-basic-offset: 8
- */
diff --git a/drivers/media/dvb/frontends/s5h1409.h b/drivers/media/dvb/frontends/s5h1409.h
deleted file mode 100644
index 91f2ebd..0000000
--- a/drivers/media/dvb/frontends/s5h1409.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
-    Samsung S5H1409 VSB/QAM demodulator driver
-
-    Copyright (C) 2006 Steven Toth <stoth@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 __S5H1409_H__
-#define __S5H1409_H__
-
-#include <linux/dvb/frontend.h>
-
-struct s5h1409_config {
-	/* the demodulator's i2c address */
-	u8 demod_address;
-
-	/* serial/parallel output */
-#define S5H1409_PARALLEL_OUTPUT 0
-#define S5H1409_SERIAL_OUTPUT   1
-	u8 output_mode;
-
-	/* GPIO Setting */
-#define S5H1409_GPIO_OFF 0
-#define S5H1409_GPIO_ON  1
-	u8 gpio;
-
-	/* IF Freq for QAM in KHz, VSB is hardcoded to 5380 */
-	u16 qam_if;
-
-	/* Spectral Inversion */
-#define S5H1409_INVERSION_OFF 0
-#define S5H1409_INVERSION_ON  1
-	u8 inversion;
-
-	/* Return lock status based on tuner lock, or demod lock */
-#define S5H1409_TUNERLOCKING 0
-#define S5H1409_DEMODLOCKING 1
-	u8 status_mode;
-
-	/* MPEG signal timing */
-#define S5H1409_MPEGTIMING_CONTINOUS_INVERTING_CLOCK       0
-#define S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK    1
-#define S5H1409_MPEGTIMING_NONCONTINOUS_INVERTING_CLOCK    2
-#define S5H1409_MPEGTIMING_NONCONTINOUS_NONINVERTING_CLOCK 3
-	u16 mpeg_timing;
-
-	/* HVR-1600 optimizations (to better work with MXL5005s)
-	   Note: some of these are likely to be folded into the generic driver
-	   after being regression tested with other boards */
-#define S5H1409_HVR1600_NOOPTIMIZE 0
-#define S5H1409_HVR1600_OPTIMIZE   1
-	u8 hvr1600_opt;
-};
-
-#if defined(CONFIG_DVB_S5H1409) || (defined(CONFIG_DVB_S5H1409_MODULE) \
-	&& defined(MODULE))
-extern struct dvb_frontend *s5h1409_attach(const struct s5h1409_config *config,
-					   struct i2c_adapter *i2c);
-#else
-static inline struct dvb_frontend *s5h1409_attach(
-	const struct s5h1409_config *config,
-	struct i2c_adapter *i2c)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif /* CONFIG_DVB_S5H1409 */
-
-#endif /* __S5H1409_H__ */
-
-/*
- * Local variables:
- * c-basic-offset: 8
- */
diff --git a/drivers/media/dvb/frontends/s5h1411.c b/drivers/media/dvb/frontends/s5h1411.c
deleted file mode 100644
index 6cc4b7a..0000000
--- a/drivers/media/dvb/frontends/s5h1411.c
+++ /dev/null
@@ -1,951 +0,0 @@
-/*
-    Samsung S5H1411 VSB/QAM demodulator driver
-
-    Copyright (C) 2008 Steven Toth <stoth@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/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include "dvb_frontend.h"
-#include "s5h1411.h"
-
-struct s5h1411_state {
-
-	struct i2c_adapter *i2c;
-
-	/* configuration settings */
-	const struct s5h1411_config *config;
-
-	struct dvb_frontend frontend;
-
-	fe_modulation_t current_modulation;
-	unsigned int first_tune:1;
-
-	u32 current_frequency;
-	int if_freq;
-
-	u8 inversion;
-};
-
-static int debug;
-
-#define dprintk(arg...) do {	\
-	if (debug)		\
-		printk(arg);	\
-	} while (0)
-
-/* Register values to initialise the demod, defaults to VSB */
-static struct init_tab {
-	u8	addr;
-	u8	reg;
-	u16	data;
-} init_tab[] = {
-	{ S5H1411_I2C_TOP_ADDR, 0x00, 0x0071, },
-	{ S5H1411_I2C_TOP_ADDR, 0x08, 0x0047, },
-	{ S5H1411_I2C_TOP_ADDR, 0x1c, 0x0400, },
-	{ S5H1411_I2C_TOP_ADDR, 0x1e, 0x0370, },
-	{ S5H1411_I2C_TOP_ADDR, 0x1f, 0x342c, },
-	{ S5H1411_I2C_TOP_ADDR, 0x24, 0x0231, },
-	{ S5H1411_I2C_TOP_ADDR, 0x25, 0x1011, },
-	{ S5H1411_I2C_TOP_ADDR, 0x26, 0x0f07, },
-	{ S5H1411_I2C_TOP_ADDR, 0x27, 0x0f04, },
-	{ S5H1411_I2C_TOP_ADDR, 0x28, 0x070f, },
-	{ S5H1411_I2C_TOP_ADDR, 0x29, 0x2820, },
-	{ S5H1411_I2C_TOP_ADDR, 0x2a, 0x102e, },
-	{ S5H1411_I2C_TOP_ADDR, 0x2b, 0x0220, },
-	{ S5H1411_I2C_TOP_ADDR, 0x2e, 0x0d0e, },
-	{ S5H1411_I2C_TOP_ADDR, 0x2f, 0x1013, },
-	{ S5H1411_I2C_TOP_ADDR, 0x31, 0x171b, },
-	{ S5H1411_I2C_TOP_ADDR, 0x32, 0x0e0f, },
-	{ S5H1411_I2C_TOP_ADDR, 0x33, 0x0f10, },
-	{ S5H1411_I2C_TOP_ADDR, 0x34, 0x170e, },
-	{ S5H1411_I2C_TOP_ADDR, 0x35, 0x4b10, },
-	{ S5H1411_I2C_TOP_ADDR, 0x36, 0x0f17, },
-	{ S5H1411_I2C_TOP_ADDR, 0x3c, 0x1577, },
-	{ S5H1411_I2C_TOP_ADDR, 0x3d, 0x081a, },
-	{ S5H1411_I2C_TOP_ADDR, 0x3e, 0x77ee, },
-	{ S5H1411_I2C_TOP_ADDR, 0x40, 0x1e09, },
-	{ S5H1411_I2C_TOP_ADDR, 0x41, 0x0f0c, },
-	{ S5H1411_I2C_TOP_ADDR, 0x42, 0x1f10, },
-	{ S5H1411_I2C_TOP_ADDR, 0x4d, 0x0509, },
-	{ S5H1411_I2C_TOP_ADDR, 0x4e, 0x0a00, },
-	{ S5H1411_I2C_TOP_ADDR, 0x50, 0x0000, },
-	{ S5H1411_I2C_TOP_ADDR, 0x5b, 0x0000, },
-	{ S5H1411_I2C_TOP_ADDR, 0x5c, 0x0008, },
-	{ S5H1411_I2C_TOP_ADDR, 0x57, 0x1101, },
-	{ S5H1411_I2C_TOP_ADDR, 0x65, 0x007c, },
-	{ S5H1411_I2C_TOP_ADDR, 0x68, 0x0512, },
-	{ S5H1411_I2C_TOP_ADDR, 0x69, 0x0258, },
-	{ S5H1411_I2C_TOP_ADDR, 0x70, 0x0004, },
-	{ S5H1411_I2C_TOP_ADDR, 0x71, 0x0007, },
-	{ S5H1411_I2C_TOP_ADDR, 0x76, 0x00a9, },
-	{ S5H1411_I2C_TOP_ADDR, 0x78, 0x3141, },
-	{ S5H1411_I2C_TOP_ADDR, 0x7a, 0x3141, },
-	{ S5H1411_I2C_TOP_ADDR, 0xb3, 0x8003, },
-	{ S5H1411_I2C_TOP_ADDR, 0xb5, 0xa6bb, },
-	{ S5H1411_I2C_TOP_ADDR, 0xb6, 0x0609, },
-	{ S5H1411_I2C_TOP_ADDR, 0xb7, 0x2f06, },
-	{ S5H1411_I2C_TOP_ADDR, 0xb8, 0x003f, },
-	{ S5H1411_I2C_TOP_ADDR, 0xb9, 0x2700, },
-	{ S5H1411_I2C_TOP_ADDR, 0xba, 0xfac8, },
-	{ S5H1411_I2C_TOP_ADDR, 0xbe, 0x1003, },
-	{ S5H1411_I2C_TOP_ADDR, 0xbf, 0x103f, },
-	{ S5H1411_I2C_TOP_ADDR, 0xce, 0x2000, },
-	{ S5H1411_I2C_TOP_ADDR, 0xcf, 0x0800, },
-	{ S5H1411_I2C_TOP_ADDR, 0xd0, 0x0800, },
-	{ S5H1411_I2C_TOP_ADDR, 0xd1, 0x0400, },
-	{ S5H1411_I2C_TOP_ADDR, 0xd2, 0x0800, },
-	{ S5H1411_I2C_TOP_ADDR, 0xd3, 0x2000, },
-	{ S5H1411_I2C_TOP_ADDR, 0xd4, 0x3000, },
-	{ S5H1411_I2C_TOP_ADDR, 0xdb, 0x4a9b, },
-	{ S5H1411_I2C_TOP_ADDR, 0xdc, 0x1000, },
-	{ S5H1411_I2C_TOP_ADDR, 0xde, 0x0001, },
-	{ S5H1411_I2C_TOP_ADDR, 0xdf, 0x0000, },
-	{ S5H1411_I2C_TOP_ADDR, 0xe3, 0x0301, },
-	{ S5H1411_I2C_QAM_ADDR, 0xf3, 0x0000, },
-	{ S5H1411_I2C_QAM_ADDR, 0xf3, 0x0001, },
-	{ S5H1411_I2C_QAM_ADDR, 0x08, 0x0600, },
-	{ S5H1411_I2C_QAM_ADDR, 0x18, 0x4201, },
-	{ S5H1411_I2C_QAM_ADDR, 0x1e, 0x6476, },
-	{ S5H1411_I2C_QAM_ADDR, 0x21, 0x0830, },
-	{ S5H1411_I2C_QAM_ADDR, 0x0c, 0x5679, },
-	{ S5H1411_I2C_QAM_ADDR, 0x0d, 0x579b, },
-	{ S5H1411_I2C_QAM_ADDR, 0x24, 0x0102, },
-	{ S5H1411_I2C_QAM_ADDR, 0x31, 0x7488, },
-	{ S5H1411_I2C_QAM_ADDR, 0x32, 0x0a08, },
-	{ S5H1411_I2C_QAM_ADDR, 0x3d, 0x8689, },
-	{ S5H1411_I2C_QAM_ADDR, 0x49, 0x0048, },
-	{ S5H1411_I2C_QAM_ADDR, 0x57, 0x2012, },
-	{ S5H1411_I2C_QAM_ADDR, 0x5d, 0x7676, },
-	{ S5H1411_I2C_QAM_ADDR, 0x04, 0x0400, },
-	{ S5H1411_I2C_QAM_ADDR, 0x58, 0x00c0, },
-	{ S5H1411_I2C_QAM_ADDR, 0x5b, 0x0100, },
-};
-
-/* VSB SNR lookup table */
-static struct vsb_snr_tab {
-	u16	val;
-	u16	data;
-} vsb_snr_tab[] = {
-	{  0x39f, 300, },
-	{  0x39b, 295, },
-	{  0x397, 290, },
-	{  0x394, 285, },
-	{  0x38f, 280, },
-	{  0x38b, 275, },
-	{  0x387, 270, },
-	{  0x382, 265, },
-	{  0x37d, 260, },
-	{  0x377, 255, },
-	{  0x370, 250, },
-	{  0x36a, 245, },
-	{  0x364, 240, },
-	{  0x35b, 235, },
-	{  0x353, 230, },
-	{  0x349, 225, },
-	{  0x340, 320, },
-	{  0x337, 215, },
-	{  0x327, 210, },
-	{  0x31b, 205, },
-	{  0x310, 200, },
-	{  0x302, 195, },
-	{  0x2f3, 190, },
-	{  0x2e4, 185, },
-	{  0x2d7, 180, },
-	{  0x2cd, 175, },
-	{  0x2bb, 170, },
-	{  0x2a9, 165, },
-	{  0x29e, 160, },
-	{  0x284, 155, },
-	{  0x27a, 150, },
-	{  0x260, 145, },
-	{  0x23a, 140, },
-	{  0x224, 135, },
-	{  0x213, 130, },
-	{  0x204, 125, },
-	{  0x1fe, 120, },
-	{      0,   0, },
-};
-
-/* QAM64 SNR lookup table */
-static struct qam64_snr_tab {
-	u16	val;
-	u16	data;
-} qam64_snr_tab[] = {
-	{  0x0001,   0, },
-	{  0x0af0, 300, },
-	{  0x0d80, 290, },
-	{  0x10a0, 280, },
-	{  0x14b5, 270, },
-	{  0x1590, 268, },
-	{  0x1680, 266, },
-	{  0x17b0, 264, },
-	{  0x18c0, 262, },
-	{  0x19b0, 260, },
-	{  0x1ad0, 258, },
-	{  0x1d00, 256, },
-	{  0x1da0, 254, },
-	{  0x1ef0, 252, },
-	{  0x2050, 250, },
-	{  0x20f0, 249, },
-	{  0x21d0, 248, },
-	{  0x22b0, 247, },
-	{  0x23a0, 246, },
-	{  0x2470, 245, },
-	{  0x24f0, 244, },
-	{  0x25a0, 243, },
-	{  0x26c0, 242, },
-	{  0x27b0, 241, },
-	{  0x28d0, 240, },
-	{  0x29b0, 239, },
-	{  0x2ad0, 238, },
-	{  0x2ba0, 237, },
-	{  0x2c80, 236, },
-	{  0x2d20, 235, },
-	{  0x2e00, 234, },
-	{  0x2f10, 233, },
-	{  0x3050, 232, },
-	{  0x3190, 231, },
-	{  0x3300, 230, },
-	{  0x3340, 229, },
-	{  0x3200, 228, },
-	{  0x3550, 227, },
-	{  0x3610, 226, },
-	{  0x3600, 225, },
-	{  0x3700, 224, },
-	{  0x3800, 223, },
-	{  0x3920, 222, },
-	{  0x3a20, 221, },
-	{  0x3b30, 220, },
-	{  0x3d00, 219, },
-	{  0x3e00, 218, },
-	{  0x4000, 217, },
-	{  0x4100, 216, },
-	{  0x4300, 215, },
-	{  0x4400, 214, },
-	{  0x4600, 213, },
-	{  0x4700, 212, },
-	{  0x4800, 211, },
-	{  0x4a00, 210, },
-	{  0x4b00, 209, },
-	{  0x4d00, 208, },
-	{  0x4f00, 207, },
-	{  0x5050, 206, },
-	{  0x5200, 205, },
-	{  0x53c0, 204, },
-	{  0x5450, 203, },
-	{  0x5650, 202, },
-	{  0x5820, 201, },
-	{  0x6000, 200, },
-	{  0xffff,   0, },
-};
-
-/* QAM256 SNR lookup table */
-static struct qam256_snr_tab {
-	u16	val;
-	u16	data;
-} qam256_snr_tab[] = {
-	{  0x0001,   0, },
-	{  0x0970, 400, },
-	{  0x0a90, 390, },
-	{  0x0b90, 380, },
-	{  0x0d90, 370, },
-	{  0x0ff0, 360, },
-	{  0x1240, 350, },
-	{  0x1345, 348, },
-	{  0x13c0, 346, },
-	{  0x14c0, 344, },
-	{  0x1500, 342, },
-	{  0x1610, 340, },
-	{  0x1700, 338, },
-	{  0x1800, 336, },
-	{  0x18b0, 334, },
-	{  0x1900, 332, },
-	{  0x1ab0, 330, },
-	{  0x1bc0, 328, },
-	{  0x1cb0, 326, },
-	{  0x1db0, 324, },
-	{  0x1eb0, 322, },
-	{  0x2030, 320, },
-	{  0x2200, 318, },
-	{  0x2280, 316, },
-	{  0x2410, 314, },
-	{  0x25b0, 312, },
-	{  0x27a0, 310, },
-	{  0x2840, 308, },
-	{  0x29d0, 306, },
-	{  0x2b10, 304, },
-	{  0x2d30, 302, },
-	{  0x2f20, 300, },
-	{  0x30c0, 298, },
-	{  0x3260, 297, },
-	{  0x32c0, 296, },
-	{  0x3300, 295, },
-	{  0x33b0, 294, },
-	{  0x34b0, 293, },
-	{  0x35a0, 292, },
-	{  0x3650, 291, },
-	{  0x3800, 290, },
-	{  0x3900, 289, },
-	{  0x3a50, 288, },
-	{  0x3b30, 287, },
-	{  0x3cb0, 286, },
-	{  0x3e20, 285, },
-	{  0x3fa0, 284, },
-	{  0x40a0, 283, },
-	{  0x41c0, 282, },
-	{  0x42f0, 281, },
-	{  0x44a0, 280, },
-	{  0x4600, 279, },
-	{  0x47b0, 278, },
-	{  0x4900, 277, },
-	{  0x4a00, 276, },
-	{  0x4ba0, 275, },
-	{  0x4d00, 274, },
-	{  0x4f00, 273, },
-	{  0x5000, 272, },
-	{  0x51f0, 272, },
-	{  0x53a0, 270, },
-	{  0x5520, 269, },
-	{  0x5700, 268, },
-	{  0x5800, 267, },
-	{  0x5a00, 266, },
-	{  0x5c00, 265, },
-	{  0x5d00, 264, },
-	{  0x5f00, 263, },
-	{  0x6000, 262, },
-	{  0x6200, 261, },
-	{  0x6400, 260, },
-	{  0xffff,   0, },
-};
-
-/* 8 bit registers, 16 bit values */
-static int s5h1411_writereg(struct s5h1411_state *state,
-	u8 addr, u8 reg, u16 data)
-{
-	int ret;
-	u8 buf[] = { reg, data >> 8,  data & 0xff };
-
-	struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = buf, .len = 3 };
-
-	ret = i2c_transfer(state->i2c, &msg, 1);
-
-	if (ret != 1)
-		printk(KERN_ERR "%s: writereg error 0x%02x 0x%02x 0x%04x, "
-		       "ret == %i)\n", __func__, addr, reg, data, ret);
-
-	return (ret != 1) ? -1 : 0;
-}
-
-static u16 s5h1411_readreg(struct s5h1411_state *state, u8 addr, u8 reg)
-{
-	int ret;
-	u8 b0[] = { reg };
-	u8 b1[] = { 0, 0 };
-
-	struct i2c_msg msg[] = {
-		{ .addr = addr, .flags = 0, .buf = b0, .len = 1 },
-		{ .addr = addr, .flags = I2C_M_RD, .buf = b1, .len = 2 } };
-
-	ret = i2c_transfer(state->i2c, msg, 2);
-
-	if (ret != 2)
-		printk(KERN_ERR "%s: readreg error (ret == %i)\n",
-			__func__, ret);
-	return (b1[0] << 8) | b1[1];
-}
-
-static int s5h1411_softreset(struct dvb_frontend *fe)
-{
-	struct s5h1411_state *state = fe->demodulator_priv;
-
-	dprintk("%s()\n", __func__);
-
-	s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf7, 0);
-	s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf7, 1);
-	return 0;
-}
-
-static int s5h1411_set_if_freq(struct dvb_frontend *fe, int KHz)
-{
-	struct s5h1411_state *state = fe->demodulator_priv;
-
-	dprintk("%s(%d KHz)\n", __func__, KHz);
-
-	switch (KHz) {
-	case 3250:
-		s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x38, 0x10d5);
-		s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x39, 0x5342);
-		s5h1411_writereg(state, S5H1411_I2C_QAM_ADDR, 0x2c, 0x10d9);
-		break;
-	case 3500:
-		s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x38, 0x1225);
-		s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x39, 0x1e96);
-		s5h1411_writereg(state, S5H1411_I2C_QAM_ADDR, 0x2c, 0x1225);
-		break;
-	case 4000:
-		s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x38, 0x14bc);
-		s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x39, 0xb53e);
-		s5h1411_writereg(state, S5H1411_I2C_QAM_ADDR, 0x2c, 0x14bd);
-		break;
-	default:
-		dprintk("%s(%d KHz) Invalid, defaulting to 5380\n",
-			__func__, KHz);
-		/* no break, need to continue */
-	case 5380:
-	case 44000:
-		s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x38, 0x1be4);
-		s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x39, 0x3655);
-		s5h1411_writereg(state, S5H1411_I2C_QAM_ADDR, 0x2c, 0x1be4);
-		break;
-	}
-
-	state->if_freq = KHz;
-
-	return 0;
-}
-
-static int s5h1411_set_mpeg_timing(struct dvb_frontend *fe, int mode)
-{
-	struct s5h1411_state *state = fe->demodulator_priv;
-	u16 val;
-
-	dprintk("%s(%d)\n", __func__, mode);
-
-	val = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xbe) & 0xcfff;
-	switch (mode) {
-	case S5H1411_MPEGTIMING_CONTINOUS_INVERTING_CLOCK:
-		val |= 0x0000;
-		break;
-	case S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK:
-		dprintk("%s(%d) Mode1 or Defaulting\n", __func__, mode);
-		val |= 0x1000;
-		break;
-	case S5H1411_MPEGTIMING_NONCONTINOUS_INVERTING_CLOCK:
-		val |= 0x2000;
-		break;
-	case S5H1411_MPEGTIMING_NONCONTINOUS_NONINVERTING_CLOCK:
-		val |= 0x3000;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	/* Configure MPEG Signal Timing charactistics */
-	return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xbe, val);
-}
-
-static int s5h1411_set_spectralinversion(struct dvb_frontend *fe, int inversion)
-{
-	struct s5h1411_state *state = fe->demodulator_priv;
-	u16 val;
-
-	dprintk("%s(%d)\n", __func__, inversion);
-	val = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0x24) & ~0x1000;
-
-	if (inversion == 1)
-		val |= 0x1000; /* Inverted */
-
-	state->inversion = inversion;
-	return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x24, val);
-}
-
-static int s5h1411_set_serialmode(struct dvb_frontend *fe, int serial)
-{
-	struct s5h1411_state *state = fe->demodulator_priv;
-	u16 val;
-
-	dprintk("%s(%d)\n", __func__, serial);
-	val = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xbd) & ~0x100;
-
-	if (serial == 1)
-		val |= 0x100;
-
-	return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xbd, val);
-}
-
-static int s5h1411_enable_modulation(struct dvb_frontend *fe,
-				     fe_modulation_t m)
-{
-	struct s5h1411_state *state = fe->demodulator_priv;
-
-	dprintk("%s(0x%08x)\n", __func__, m);
-
-	if ((state->first_tune == 0) && (m == state->current_modulation)) {
-		dprintk("%s() Already at desired modulation.  Skipping...\n",
-			__func__);
-		return 0;
-	}
-
-	switch (m) {
-	case VSB_8:
-		dprintk("%s() VSB_8\n", __func__);
-		s5h1411_set_if_freq(fe, state->config->vsb_if);
-		s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x00, 0x71);
-		s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf6, 0x00);
-		s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xcd, 0xf1);
-		break;
-	case QAM_64:
-	case QAM_256:
-	case QAM_AUTO:
-		dprintk("%s() QAM_AUTO (64/256)\n", __func__);
-		s5h1411_set_if_freq(fe, state->config->qam_if);
-		s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x00, 0x0171);
-		s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf6, 0x0001);
-		s5h1411_writereg(state, S5H1411_I2C_QAM_ADDR, 0x16, 0x1101);
-		s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xcd, 0x00f0);
-		break;
-	default:
-		dprintk("%s() Invalid modulation\n", __func__);
-		return -EINVAL;
-	}
-
-	state->current_modulation = m;
-	state->first_tune = 0;
-	s5h1411_softreset(fe);
-
-	return 0;
-}
-
-static int s5h1411_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
-{
-	struct s5h1411_state *state = fe->demodulator_priv;
-
-	dprintk("%s(%d)\n", __func__, enable);
-
-	if (enable)
-		return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf5, 1);
-	else
-		return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf5, 0);
-}
-
-static int s5h1411_set_gpio(struct dvb_frontend *fe, int enable)
-{
-	struct s5h1411_state *state = fe->demodulator_priv;
-	u16 val;
-
-	dprintk("%s(%d)\n", __func__, enable);
-
-	val = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xe0) & ~0x02;
-
-	if (enable)
-		return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xe0,
-				val | 0x02);
-	else
-		return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xe0, val);
-}
-
-static int s5h1411_set_powerstate(struct dvb_frontend *fe, int enable)
-{
-	struct s5h1411_state *state = fe->demodulator_priv;
-
-	dprintk("%s(%d)\n", __func__, enable);
-
-	if (enable)
-		s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf4, 1);
-	else {
-		s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf4, 0);
-		s5h1411_softreset(fe);
-	}
-
-	return 0;
-}
-
-static int s5h1411_sleep(struct dvb_frontend *fe)
-{
-	return s5h1411_set_powerstate(fe, 1);
-}
-
-static int s5h1411_register_reset(struct dvb_frontend *fe)
-{
-	struct s5h1411_state *state = fe->demodulator_priv;
-
-	dprintk("%s()\n", __func__);
-
-	return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf3, 0);
-}
-
-/* Talk to the demod, set the FEC, GUARD, QAM settings etc */
-static int s5h1411_set_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct s5h1411_state *state = fe->demodulator_priv;
-
-	dprintk("%s(frequency=%d)\n", __func__, p->frequency);
-
-	s5h1411_softreset(fe);
-
-	state->current_frequency = p->frequency;
-
-	s5h1411_enable_modulation(fe, p->modulation);
-
-	if (fe->ops.tuner_ops.set_params) {
-		if (fe->ops.i2c_gate_ctrl)
-			fe->ops.i2c_gate_ctrl(fe, 1);
-
-		fe->ops.tuner_ops.set_params(fe);
-
-		if (fe->ops.i2c_gate_ctrl)
-			fe->ops.i2c_gate_ctrl(fe, 0);
-	}
-
-	/* Issue a reset to the demod so it knows to resync against the
-	   newly tuned frequency */
-	s5h1411_softreset(fe);
-
-	return 0;
-}
-
-/* Reset the demod hardware and reset all of the configuration registers
-   to a default state. */
-static int s5h1411_init(struct dvb_frontend *fe)
-{
-	struct s5h1411_state *state = fe->demodulator_priv;
-	int i;
-
-	dprintk("%s()\n", __func__);
-
-	s5h1411_set_powerstate(fe, 0);
-	s5h1411_register_reset(fe);
-
-	for (i = 0; i < ARRAY_SIZE(init_tab); i++)
-		s5h1411_writereg(state, init_tab[i].addr,
-			init_tab[i].reg,
-			init_tab[i].data);
-
-	/* The datasheet says that after initialisation, VSB is default */
-	state->current_modulation = VSB_8;
-
-	/* Although the datasheet says it's in VSB, empirical evidence
-	   shows problems getting lock on the first tuning request.  Make
-	   sure we call enable_modulation the first time around */
-	state->first_tune = 1;
-
-	if (state->config->output_mode == S5H1411_SERIAL_OUTPUT)
-		/* Serial */
-		s5h1411_set_serialmode(fe, 1);
-	else
-		/* Parallel */
-		s5h1411_set_serialmode(fe, 0);
-
-	s5h1411_set_spectralinversion(fe, state->config->inversion);
-	s5h1411_set_if_freq(fe, state->config->vsb_if);
-	s5h1411_set_gpio(fe, state->config->gpio);
-	s5h1411_set_mpeg_timing(fe, state->config->mpeg_timing);
-	s5h1411_softreset(fe);
-
-	/* Note: Leaving the I2C gate closed. */
-	s5h1411_i2c_gate_ctrl(fe, 0);
-
-	return 0;
-}
-
-static int s5h1411_read_status(struct dvb_frontend *fe, fe_status_t *status)
-{
-	struct s5h1411_state *state = fe->demodulator_priv;
-	u16 reg;
-	u32 tuner_status = 0;
-
-	*status = 0;
-
-	/* Register F2 bit 15 = Master Lock, removed */
-
-	switch (state->current_modulation) {
-	case QAM_64:
-	case QAM_256:
-		reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xf0);
-		if (reg & 0x10) /* QAM FEC Lock */
-			*status |= FE_HAS_SYNC | FE_HAS_LOCK;
-		if (reg & 0x100) /* QAM EQ Lock */
-			*status |= FE_HAS_VITERBI | FE_HAS_CARRIER | FE_HAS_SIGNAL;
-
-		break;
-	case VSB_8:
-		reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xf2);
-		if (reg & 0x1000) /* FEC Lock */
-			*status |= FE_HAS_SYNC | FE_HAS_LOCK;
-		if (reg & 0x2000) /* EQ Lock */
-			*status |= FE_HAS_VITERBI | FE_HAS_CARRIER | FE_HAS_SIGNAL;
-
-		reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0x53);
-		if (reg & 0x1) /* AFC Lock */
-			*status |= FE_HAS_SIGNAL;
-
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	switch (state->config->status_mode) {
-	case S5H1411_DEMODLOCKING:
-		if (*status & FE_HAS_VITERBI)
-			*status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
-		break;
-	case S5H1411_TUNERLOCKING:
-		/* Get the tuner status */
-		if (fe->ops.tuner_ops.get_status) {
-			if (fe->ops.i2c_gate_ctrl)
-				fe->ops.i2c_gate_ctrl(fe, 1);
-
-			fe->ops.tuner_ops.get_status(fe, &tuner_status);
-
-			if (fe->ops.i2c_gate_ctrl)
-				fe->ops.i2c_gate_ctrl(fe, 0);
-		}
-		if (tuner_status)
-			*status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
-		break;
-	}
-
-	dprintk("%s() status 0x%08x\n", __func__, *status);
-
-	return 0;
-}
-
-static int s5h1411_qam256_lookup_snr(struct dvb_frontend *fe, u16 *snr, u16 v)
-{
-	int i, ret = -EINVAL;
-	dprintk("%s()\n", __func__);
-
-	for (i = 0; i < ARRAY_SIZE(qam256_snr_tab); i++) {
-		if (v < qam256_snr_tab[i].val) {
-			*snr = qam256_snr_tab[i].data;
-			ret = 0;
-			break;
-		}
-	}
-	return ret;
-}
-
-static int s5h1411_qam64_lookup_snr(struct dvb_frontend *fe, u16 *snr, u16 v)
-{
-	int i, ret = -EINVAL;
-	dprintk("%s()\n", __func__);
-
-	for (i = 0; i < ARRAY_SIZE(qam64_snr_tab); i++) {
-		if (v < qam64_snr_tab[i].val) {
-			*snr = qam64_snr_tab[i].data;
-			ret = 0;
-			break;
-		}
-	}
-	return ret;
-}
-
-static int s5h1411_vsb_lookup_snr(struct dvb_frontend *fe, u16 *snr, u16 v)
-{
-	int i, ret = -EINVAL;
-	dprintk("%s()\n", __func__);
-
-	for (i = 0; i < ARRAY_SIZE(vsb_snr_tab); i++) {
-		if (v > vsb_snr_tab[i].val) {
-			*snr = vsb_snr_tab[i].data;
-			ret = 0;
-			break;
-		}
-	}
-	dprintk("%s() snr=%d\n", __func__, *snr);
-	return ret;
-}
-
-static int s5h1411_read_snr(struct dvb_frontend *fe, u16 *snr)
-{
-	struct s5h1411_state *state = fe->demodulator_priv;
-	u16 reg;
-	dprintk("%s()\n", __func__);
-
-	switch (state->current_modulation) {
-	case QAM_64:
-		reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xf1);
-		return s5h1411_qam64_lookup_snr(fe, snr, reg);
-	case QAM_256:
-		reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xf1);
-		return s5h1411_qam256_lookup_snr(fe, snr, reg);
-	case VSB_8:
-		reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR,
-			0xf2) & 0x3ff;
-		return s5h1411_vsb_lookup_snr(fe, snr, reg);
-	default:
-		break;
-	}
-
-	return -EINVAL;
-}
-
-static int s5h1411_read_signal_strength(struct dvb_frontend *fe,
-	u16 *signal_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%
-	 */
-	u16 snr;
-	u32 tmp;
-	int ret = s5h1411_read_snr(fe, &snr);
-
-	*signal_strength = 0;
-
-	if (0 == ret) {
-		/* The following calculation method was chosen
-		 * purely for the sake of code re-use from the
-		 * other demod drivers that use this method */
-
-		/* Convert from SNR in dB * 10 to 8.24 fixed-point */
-		tmp = (snr * ((1 << 24) / 10));
-
-		/* Convert from 8.24 fixed-point to
-		 * scale the range 0 - 35*2^24 into 0 - 65535*/
-		if (tmp >= 8960 * 0x10000)
-			*signal_strength = 0xffff;
-		else
-			*signal_strength = tmp / 8960;
-	}
-
-	return ret;
-}
-
-static int s5h1411_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
-{
-	struct s5h1411_state *state = fe->demodulator_priv;
-
-	*ucblocks = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xc9);
-
-	return 0;
-}
-
-static int s5h1411_read_ber(struct dvb_frontend *fe, u32 *ber)
-{
-	return s5h1411_read_ucblocks(fe, ber);
-}
-
-static int s5h1411_get_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct s5h1411_state *state = fe->demodulator_priv;
-
-	p->frequency = state->current_frequency;
-	p->modulation = state->current_modulation;
-
-	return 0;
-}
-
-static int s5h1411_get_tune_settings(struct dvb_frontend *fe,
-				     struct dvb_frontend_tune_settings *tune)
-{
-	tune->min_delay_ms = 1000;
-	return 0;
-}
-
-static void s5h1411_release(struct dvb_frontend *fe)
-{
-	struct s5h1411_state *state = fe->demodulator_priv;
-	kfree(state);
-}
-
-static struct dvb_frontend_ops s5h1411_ops;
-
-struct dvb_frontend *s5h1411_attach(const struct s5h1411_config *config,
-				    struct i2c_adapter *i2c)
-{
-	struct s5h1411_state *state = NULL;
-	u16 reg;
-
-	/* allocate memory for the internal state */
-	state = kzalloc(sizeof(struct s5h1411_state), GFP_KERNEL);
-	if (state == NULL)
-		goto error;
-
-	/* setup the state */
-	state->config = config;
-	state->i2c = i2c;
-	state->current_modulation = VSB_8;
-	state->inversion = state->config->inversion;
-
-	/* check if the demod exists */
-	reg = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0x05);
-	if (reg != 0x0066)
-		goto error;
-
-	/* create dvb_frontend */
-	memcpy(&state->frontend.ops, &s5h1411_ops,
-	       sizeof(struct dvb_frontend_ops));
-
-	state->frontend.demodulator_priv = state;
-
-	if (s5h1411_init(&state->frontend) != 0) {
-		printk(KERN_ERR "%s: Failed to initialize correctly\n",
-			__func__);
-		goto error;
-	}
-
-	/* Note: Leaving the I2C gate open here. */
-	s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xf5, 1);
-
-	/* Put the device into low-power mode until first use */
-	s5h1411_set_powerstate(&state->frontend, 1);
-
-	return &state->frontend;
-
-error:
-	kfree(state);
-	return NULL;
-}
-EXPORT_SYMBOL(s5h1411_attach);
-
-static struct dvb_frontend_ops s5h1411_ops = {
-	.delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
-	.info = {
-		.name			= "Samsung S5H1411 QAM/8VSB Frontend",
-		.frequency_min		= 54000000,
-		.frequency_max		= 858000000,
-		.frequency_stepsize	= 62500,
-		.caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
-	},
-
-	.init                 = s5h1411_init,
-	.sleep                = s5h1411_sleep,
-	.i2c_gate_ctrl        = s5h1411_i2c_gate_ctrl,
-	.set_frontend         = s5h1411_set_frontend,
-	.get_frontend         = s5h1411_get_frontend,
-	.get_tune_settings    = s5h1411_get_tune_settings,
-	.read_status          = s5h1411_read_status,
-	.read_ber             = s5h1411_read_ber,
-	.read_signal_strength = s5h1411_read_signal_strength,
-	.read_snr             = s5h1411_read_snr,
-	.read_ucblocks        = s5h1411_read_ucblocks,
-	.release              = s5h1411_release,
-};
-
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Enable verbose debug messages");
-
-MODULE_DESCRIPTION("Samsung S5H1411 QAM-B/ATSC Demodulator driver");
-MODULE_AUTHOR("Steven Toth");
-MODULE_LICENSE("GPL");
-
-/*
- * Local variables:
- * c-basic-offset: 8
- */
diff --git a/drivers/media/dvb/frontends/s5h1411.h b/drivers/media/dvb/frontends/s5h1411.h
deleted file mode 100644
index 45ec0f8..0000000
--- a/drivers/media/dvb/frontends/s5h1411.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
-    Samsung S5H1411 VSB/QAM demodulator driver
-
-    Copyright (C) 2008 Steven Toth <stoth@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 __S5H1411_H__
-#define __S5H1411_H__
-
-#include <linux/dvb/frontend.h>
-
-#define S5H1411_I2C_TOP_ADDR (0x32 >> 1)
-#define S5H1411_I2C_QAM_ADDR (0x34 >> 1)
-
-struct s5h1411_config {
-
-	/* serial/parallel output */
-#define S5H1411_PARALLEL_OUTPUT 0
-#define S5H1411_SERIAL_OUTPUT   1
-	u8 output_mode;
-
-	/* GPIO Setting */
-#define S5H1411_GPIO_OFF 0
-#define S5H1411_GPIO_ON  1
-	u8 gpio;
-
-	/* MPEG signal timing */
-#define S5H1411_MPEGTIMING_CONTINOUS_INVERTING_CLOCK       0
-#define S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK    1
-#define S5H1411_MPEGTIMING_NONCONTINOUS_INVERTING_CLOCK    2
-#define S5H1411_MPEGTIMING_NONCONTINOUS_NONINVERTING_CLOCK 3
-	u16 mpeg_timing;
-
-	/* IF Freq for QAM and VSB in KHz */
-#define S5H1411_IF_3250  3250
-#define S5H1411_IF_3500  3500
-#define S5H1411_IF_4000  4000
-#define S5H1411_IF_5380  5380
-#define S5H1411_IF_44000 44000
-#define S5H1411_VSB_IF_DEFAULT S5H1411_IF_44000
-#define S5H1411_QAM_IF_DEFAULT S5H1411_IF_44000
-	u16 qam_if;
-	u16 vsb_if;
-
-	/* Spectral Inversion */
-#define S5H1411_INVERSION_OFF 0
-#define S5H1411_INVERSION_ON  1
-	u8 inversion;
-
-	/* Return lock status based on tuner lock, or demod lock */
-#define S5H1411_TUNERLOCKING 0
-#define S5H1411_DEMODLOCKING 1
-	u8 status_mode;
-};
-
-#if defined(CONFIG_DVB_S5H1411) || \
-	(defined(CONFIG_DVB_S5H1411_MODULE) && defined(MODULE))
-extern struct dvb_frontend *s5h1411_attach(const struct s5h1411_config *config,
-					   struct i2c_adapter *i2c);
-#else
-static inline struct dvb_frontend *s5h1411_attach(
-	const struct s5h1411_config *config,
-	struct i2c_adapter *i2c)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif /* CONFIG_DVB_S5H1411 */
-
-#endif /* __S5H1411_H__ */
-
-/*
- * Local variables:
- * c-basic-offset: 8
- */
diff --git a/drivers/media/dvb/frontends/s5h1420.c b/drivers/media/dvb/frontends/s5h1420.c
deleted file mode 100644
index e2fec9e..0000000
--- a/drivers/media/dvb/frontends/s5h1420.c
+++ /dev/null
@@ -1,960 +0,0 @@
-/*
- * Driver for
- *    Samsung S5H1420 and
- *    PnpNetwork PN1010 QPSK Demodulator
- *
- * Copyright (C) 2005 Andrew de Quincey <adq_dvb@lidskialf.net>
- * Copyright (C) 2005-8 Patrick Boettcher <pb@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/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/jiffies.h>
-#include <asm/div64.h>
-
-#include <linux/i2c.h>
-
-
-#include "dvb_frontend.h"
-#include "s5h1420.h"
-#include "s5h1420_priv.h"
-
-#define TONE_FREQ 22000
-
-struct s5h1420_state {
-	struct i2c_adapter* i2c;
-	const struct s5h1420_config* config;
-
-	struct dvb_frontend frontend;
-	struct i2c_adapter tuner_i2c_adapter;
-
-	u8 CON_1_val;
-
-	u8 postlocked:1;
-	u32 fclk;
-	u32 tunedfreq;
-	fe_code_rate_t fec_inner;
-	u32 symbol_rate;
-
-	/* FIXME: ugly workaround for flexcop's incapable i2c-controller
-	 * it does not support repeated-start, workaround: write addr-1
-	 * and then read
-	 */
-	u8 shadow[256];
-};
-
-static u32 s5h1420_getsymbolrate(struct s5h1420_state* state);
-static int s5h1420_get_tune_settings(struct dvb_frontend* fe,
-				     struct dvb_frontend_tune_settings* fesettings);
-
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "enable debugging");
-
-#define dprintk(x...) do { \
-	if (debug) \
-		printk(KERN_DEBUG "S5H1420: " x); \
-} while (0)
-
-static u8 s5h1420_readreg(struct s5h1420_state *state, u8 reg)
-{
-	int ret;
-	u8 b[2];
-	struct i2c_msg msg[] = {
-		{ .addr = state->config->demod_address, .flags = 0, .buf = b, .len = 2 },
-		{ .addr = state->config->demod_address, .flags = 0, .buf = &reg, .len = 1 },
-		{ .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b, .len = 1 },
-	};
-
-	b[0] = (reg - 1) & 0xff;
-	b[1] = state->shadow[(reg - 1) & 0xff];
-
-	if (state->config->repeated_start_workaround) {
-		ret = i2c_transfer(state->i2c, msg, 3);
-		if (ret != 3)
-			return ret;
-	} else {
-		ret = i2c_transfer(state->i2c, &msg[1], 1);
-		if (ret != 1)
-			return ret;
-		ret = i2c_transfer(state->i2c, &msg[2], 1);
-		if (ret != 1)
-			return ret;
-	}
-
-	/* dprintk("rd(%02x): %02x %02x\n", state->config->demod_address, reg, b[0]); */
-
-	return b[0];
-}
-
-static int s5h1420_writereg (struct s5h1420_state* state, u8 reg, u8 data)
-{
-	u8 buf[] = { reg, data };
-	struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 };
-	int err;
-
-	/* dprintk("wr(%02x): %02x %02x\n", state->config->demod_address, reg, data); */
-	err = i2c_transfer(state->i2c, &msg, 1);
-	if (err != 1) {
-		dprintk("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __func__, err, reg, data);
-		return -EREMOTEIO;
-	}
-	state->shadow[reg] = data;
-
-	return 0;
-}
-
-static int s5h1420_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltage)
-{
-	struct s5h1420_state* state = fe->demodulator_priv;
-
-	dprintk("enter %s\n", __func__);
-
-	switch(voltage) {
-	case SEC_VOLTAGE_13:
-		s5h1420_writereg(state, 0x3c,
-				 (s5h1420_readreg(state, 0x3c) & 0xfe) | 0x02);
-		break;
-
-	case SEC_VOLTAGE_18:
-		s5h1420_writereg(state, 0x3c, s5h1420_readreg(state, 0x3c) | 0x03);
-		break;
-
-	case SEC_VOLTAGE_OFF:
-		s5h1420_writereg(state, 0x3c, s5h1420_readreg(state, 0x3c) & 0xfd);
-		break;
-	}
-
-	dprintk("leave %s\n", __func__);
-	return 0;
-}
-
-static int s5h1420_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
-{
-	struct s5h1420_state* state = fe->demodulator_priv;
-
-	dprintk("enter %s\n", __func__);
-	switch(tone) {
-	case SEC_TONE_ON:
-		s5h1420_writereg(state, 0x3b,
-				 (s5h1420_readreg(state, 0x3b) & 0x74) | 0x08);
-		break;
-
-	case SEC_TONE_OFF:
-		s5h1420_writereg(state, 0x3b,
-				 (s5h1420_readreg(state, 0x3b) & 0x74) | 0x01);
-		break;
-	}
-	dprintk("leave %s\n", __func__);
-
-	return 0;
-}
-
-static int s5h1420_send_master_cmd (struct dvb_frontend* fe,
-				    struct dvb_diseqc_master_cmd* cmd)
-{
-	struct s5h1420_state* state = fe->demodulator_priv;
-	u8 val;
-	int i;
-	unsigned long timeout;
-	int result = 0;
-
-	dprintk("enter %s\n", __func__);
-	if (cmd->msg_len > 8)
-		return -EINVAL;
-
-	/* setup for DISEQC */
-	val = s5h1420_readreg(state, 0x3b);
-	s5h1420_writereg(state, 0x3b, 0x02);
-	msleep(15);
-
-	/* write the DISEQC command bytes */
-	for(i=0; i< cmd->msg_len; i++) {
-		s5h1420_writereg(state, 0x3d + i, cmd->msg[i]);
-	}
-
-	/* kick off transmission */
-	s5h1420_writereg(state, 0x3b, s5h1420_readreg(state, 0x3b) |
-				      ((cmd->msg_len-1) << 4) | 0x08);
-
-	/* wait for transmission to complete */
-	timeout = jiffies + ((100*HZ) / 1000);
-	while(time_before(jiffies, timeout)) {
-		if (!(s5h1420_readreg(state, 0x3b) & 0x08))
-			break;
-
-		msleep(5);
-	}
-	if (time_after(jiffies, timeout))
-		result = -ETIMEDOUT;
-
-	/* restore original settings */
-	s5h1420_writereg(state, 0x3b, val);
-	msleep(15);
-	dprintk("leave %s\n", __func__);
-	return result;
-}
-
-static int s5h1420_recv_slave_reply (struct dvb_frontend* fe,
-				     struct dvb_diseqc_slave_reply* reply)
-{
-	struct s5h1420_state* state = fe->demodulator_priv;
-	u8 val;
-	int i;
-	int length;
-	unsigned long timeout;
-	int result = 0;
-
-	/* setup for DISEQC receive */
-	val = s5h1420_readreg(state, 0x3b);
-	s5h1420_writereg(state, 0x3b, 0x82); /* FIXME: guess - do we need to set DIS_RDY(0x08) in receive mode? */
-	msleep(15);
-
-	/* wait for reception to complete */
-	timeout = jiffies + ((reply->timeout*HZ) / 1000);
-	while(time_before(jiffies, timeout)) {
-		if (!(s5h1420_readreg(state, 0x3b) & 0x80)) /* FIXME: do we test DIS_RDY(0x08) or RCV_EN(0x80)? */
-			break;
-
-		msleep(5);
-	}
-	if (time_after(jiffies, timeout)) {
-		result = -ETIMEDOUT;
-		goto exit;
-	}
-
-	/* check error flag - FIXME: not sure what this does - docs do not describe
-	 * beyond "error flag for diseqc receive data :( */
-	if (s5h1420_readreg(state, 0x49)) {
-		result = -EIO;
-		goto exit;
-	}
-
-	/* check length */
-	length = (s5h1420_readreg(state, 0x3b) & 0x70) >> 4;
-	if (length > sizeof(reply->msg)) {
-		result = -EOVERFLOW;
-		goto exit;
-	}
-	reply->msg_len = length;
-
-	/* extract data */
-	for(i=0; i< length; i++) {
-		reply->msg[i] = s5h1420_readreg(state, 0x3d + i);
-	}
-
-exit:
-	/* restore original settings */
-	s5h1420_writereg(state, 0x3b, val);
-	msleep(15);
-	return result;
-}
-
-static int s5h1420_send_burst (struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd)
-{
-	struct s5h1420_state* state = fe->demodulator_priv;
-	u8 val;
-	int result = 0;
-	unsigned long timeout;
-
-	/* setup for tone burst */
-	val = s5h1420_readreg(state, 0x3b);
-	s5h1420_writereg(state, 0x3b, (s5h1420_readreg(state, 0x3b) & 0x70) | 0x01);
-
-	/* set value for B position if requested */
-	if (minicmd == SEC_MINI_B) {
-		s5h1420_writereg(state, 0x3b, s5h1420_readreg(state, 0x3b) | 0x04);
-	}
-	msleep(15);
-
-	/* start transmission */
-	s5h1420_writereg(state, 0x3b, s5h1420_readreg(state, 0x3b) | 0x08);
-
-	/* wait for transmission to complete */
-	timeout = jiffies + ((100*HZ) / 1000);
-	while(time_before(jiffies, timeout)) {
-		if (!(s5h1420_readreg(state, 0x3b) & 0x08))
-			break;
-
-		msleep(5);
-	}
-	if (time_after(jiffies, timeout))
-		result = -ETIMEDOUT;
-
-	/* restore original settings */
-	s5h1420_writereg(state, 0x3b, val);
-	msleep(15);
-	return result;
-}
-
-static fe_status_t s5h1420_get_status_bits(struct s5h1420_state* state)
-{
-	u8 val;
-	fe_status_t status = 0;
-
-	val = s5h1420_readreg(state, 0x14);
-	if (val & 0x02)
-		status |=  FE_HAS_SIGNAL;
-	if (val & 0x01)
-		status |=  FE_HAS_CARRIER;
-	val = s5h1420_readreg(state, 0x36);
-	if (val & 0x01)
-		status |=  FE_HAS_VITERBI;
-	if (val & 0x20)
-		status |=  FE_HAS_SYNC;
-	if (status == (FE_HAS_SIGNAL|FE_HAS_CARRIER|FE_HAS_VITERBI|FE_HAS_SYNC))
-		status |=  FE_HAS_LOCK;
-
-	return status;
-}
-
-static int s5h1420_read_status(struct dvb_frontend* fe, fe_status_t* status)
-{
-	struct s5h1420_state* state = fe->demodulator_priv;
-	u8 val;
-
-	dprintk("enter %s\n", __func__);
-
-	if (status == NULL)
-		return -EINVAL;
-
-	/* determine lock state */
-	*status = s5h1420_get_status_bits(state);
-
-	/* fix for FEC 5/6 inversion issue - if it doesn't quite lock, invert
-	the inversion, wait a bit and check again */
-	if (*status == (FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI)) {
-		val = s5h1420_readreg(state, Vit10);
-		if ((val & 0x07) == 0x03) {
-			if (val & 0x08)
-				s5h1420_writereg(state, Vit09, 0x13);
-			else
-				s5h1420_writereg(state, Vit09, 0x1b);
-
-			/* wait a bit then update lock status */
-			mdelay(200);
-			*status = s5h1420_get_status_bits(state);
-		}
-	}
-
-	/* perform post lock setup */
-	if ((*status & FE_HAS_LOCK) && !state->postlocked) {
-
-		/* calculate the data rate */
-		u32 tmp = s5h1420_getsymbolrate(state);
-		switch (s5h1420_readreg(state, Vit10) & 0x07) {
-		case 0: tmp = (tmp * 2 * 1) / 2; break;
-		case 1: tmp = (tmp * 2 * 2) / 3; break;
-		case 2: tmp = (tmp * 2 * 3) / 4; break;
-		case 3: tmp = (tmp * 2 * 5) / 6; break;
-		case 4: tmp = (tmp * 2 * 6) / 7; break;
-		case 5: tmp = (tmp * 2 * 7) / 8; break;
-		}
-
-		if (tmp == 0) {
-			printk(KERN_ERR "s5h1420: avoided division by 0\n");
-			tmp = 1;
-		}
-		tmp = state->fclk / tmp;
-
-
-		/* set the MPEG_CLK_INTL for the calculated data rate */
-		if (tmp < 2)
-			val = 0x00;
-		else if (tmp < 5)
-			val = 0x01;
-		else if (tmp < 9)
-			val = 0x02;
-		else if (tmp < 13)
-			val = 0x03;
-		else if (tmp < 17)
-			val = 0x04;
-		else if (tmp < 25)
-			val = 0x05;
-		else if (tmp < 33)
-			val = 0x06;
-		else
-			val = 0x07;
-		dprintk("for MPEG_CLK_INTL %d %x\n", tmp, val);
-
-		s5h1420_writereg(state, FEC01, 0x18);
-		s5h1420_writereg(state, FEC01, 0x10);
-		s5h1420_writereg(state, FEC01, val);
-
-		/* Enable "MPEG_Out" */
-		val = s5h1420_readreg(state, Mpeg02);
-		s5h1420_writereg(state, Mpeg02, val | (1 << 6));
-
-		/* kicker disable */
-		val = s5h1420_readreg(state, QPSK01) & 0x7f;
-		s5h1420_writereg(state, QPSK01, val);
-
-		/* DC freeze TODO it was never activated by default or it can stay activated */
-
-		if (s5h1420_getsymbolrate(state) >= 20000000) {
-			s5h1420_writereg(state, Loop04, 0x8a);
-			s5h1420_writereg(state, Loop05, 0x6a);
-		} else {
-			s5h1420_writereg(state, Loop04, 0x58);
-			s5h1420_writereg(state, Loop05, 0x27);
-		}
-
-		/* post-lock processing has been done! */
-		state->postlocked = 1;
-	}
-
-	dprintk("leave %s\n", __func__);
-
-	return 0;
-}
-
-static int s5h1420_read_ber(struct dvb_frontend* fe, u32* ber)
-{
-	struct s5h1420_state* state = fe->demodulator_priv;
-
-	s5h1420_writereg(state, 0x46, 0x1d);
-	mdelay(25);
-
-	*ber = (s5h1420_readreg(state, 0x48) << 8) | s5h1420_readreg(state, 0x47);
-
-	return 0;
-}
-
-static int s5h1420_read_signal_strength(struct dvb_frontend* fe, u16* strength)
-{
-	struct s5h1420_state* state = fe->demodulator_priv;
-
-	u8 val = s5h1420_readreg(state, 0x15);
-
-	*strength =  (u16) ((val << 8) | val);
-
-	return 0;
-}
-
-static int s5h1420_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
-{
-	struct s5h1420_state* state = fe->demodulator_priv;
-
-	s5h1420_writereg(state, 0x46, 0x1f);
-	mdelay(25);
-
-	*ucblocks = (s5h1420_readreg(state, 0x48) << 8) | s5h1420_readreg(state, 0x47);
-
-	return 0;
-}
-
-static void s5h1420_reset(struct s5h1420_state* state)
-{
-	dprintk("%s\n", __func__);
-	s5h1420_writereg (state, 0x01, 0x08);
-	s5h1420_writereg (state, 0x01, 0x00);
-	udelay(10);
-}
-
-static void s5h1420_setsymbolrate(struct s5h1420_state* state,
-				  struct dtv_frontend_properties *p)
-{
-	u8 v;
-	u64 val;
-
-	dprintk("enter %s\n", __func__);
-
-	val = ((u64) p->symbol_rate / 1000ULL) * (1ULL<<24);
-	if (p->symbol_rate < 29000000)
-		val *= 2;
-	do_div(val, (state->fclk / 1000));
-
-	dprintk("symbol rate register: %06llx\n", (unsigned long long)val);
-
-	v = s5h1420_readreg(state, Loop01);
-	s5h1420_writereg(state, Loop01, v & 0x7f);
-	s5h1420_writereg(state, Tnco01, val >> 16);
-	s5h1420_writereg(state, Tnco02, val >> 8);
-	s5h1420_writereg(state, Tnco03, val & 0xff);
-	s5h1420_writereg(state, Loop01,  v | 0x80);
-	dprintk("leave %s\n", __func__);
-}
-
-static u32 s5h1420_getsymbolrate(struct s5h1420_state* state)
-{
-	return state->symbol_rate;
-}
-
-static void s5h1420_setfreqoffset(struct s5h1420_state* state, int freqoffset)
-{
-	int val;
-	u8 v;
-
-	dprintk("enter %s\n", __func__);
-
-	/* remember freqoffset is in kHz, but the chip wants the offset in Hz, so
-	 * divide fclk by 1000000 to get the correct value. */
-	val = -(int) ((freqoffset * (1<<24)) / (state->fclk / 1000000));
-
-	dprintk("phase rotator/freqoffset: %d %06x\n", freqoffset, val);
-
-	v = s5h1420_readreg(state, Loop01);
-	s5h1420_writereg(state, Loop01, v & 0xbf);
-	s5h1420_writereg(state, Pnco01, val >> 16);
-	s5h1420_writereg(state, Pnco02, val >> 8);
-	s5h1420_writereg(state, Pnco03, val & 0xff);
-	s5h1420_writereg(state, Loop01, v | 0x40);
-	dprintk("leave %s\n", __func__);
-}
-
-static int s5h1420_getfreqoffset(struct s5h1420_state* state)
-{
-	int val;
-
-	s5h1420_writereg(state, 0x06, s5h1420_readreg(state, 0x06) | 0x08);
-	val  = s5h1420_readreg(state, 0x0e) << 16;
-	val |= s5h1420_readreg(state, 0x0f) << 8;
-	val |= s5h1420_readreg(state, 0x10);
-	s5h1420_writereg(state, 0x06, s5h1420_readreg(state, 0x06) & 0xf7);
-
-	if (val & 0x800000)
-		val |= 0xff000000;
-
-	/* remember freqoffset is in kHz, but the chip wants the offset in Hz, so
-	 * divide fclk by 1000000 to get the correct value. */
-	val = (((-val) * (state->fclk/1000000)) / (1<<24));
-
-	return val;
-}
-
-static void s5h1420_setfec_inversion(struct s5h1420_state* state,
-				     struct dtv_frontend_properties *p)
-{
-	u8 inversion = 0;
-	u8 vit08, vit09;
-
-	dprintk("enter %s\n", __func__);
-
-	if (p->inversion == INVERSION_OFF)
-		inversion = state->config->invert ? 0x08 : 0;
-	else if (p->inversion == INVERSION_ON)
-		inversion = state->config->invert ? 0 : 0x08;
-
-	if ((p->fec_inner == FEC_AUTO) || (p->inversion == INVERSION_AUTO)) {
-		vit08 = 0x3f;
-		vit09 = 0;
-	} else {
-		switch (p->fec_inner) {
-		case FEC_1_2:
-			vit08 = 0x01; vit09 = 0x10;
-			break;
-
-		case FEC_2_3:
-			vit08 = 0x02; vit09 = 0x11;
-			break;
-
-		case FEC_3_4:
-			vit08 = 0x04; vit09 = 0x12;
-			break;
-
-		case FEC_5_6:
-			vit08 = 0x08; vit09 = 0x13;
-			break;
-
-		case FEC_6_7:
-			vit08 = 0x10; vit09 = 0x14;
-			break;
-
-		case FEC_7_8:
-			vit08 = 0x20; vit09 = 0x15;
-			break;
-
-		default:
-			return;
-		}
-	}
-	vit09 |= inversion;
-	dprintk("fec: %02x %02x\n", vit08, vit09);
-	s5h1420_writereg(state, Vit08, vit08);
-	s5h1420_writereg(state, Vit09, vit09);
-	dprintk("leave %s\n", __func__);
-}
-
-static fe_code_rate_t s5h1420_getfec(struct s5h1420_state* state)
-{
-	switch(s5h1420_readreg(state, 0x32) & 0x07) {
-	case 0:
-		return FEC_1_2;
-
-	case 1:
-		return FEC_2_3;
-
-	case 2:
-		return FEC_3_4;
-
-	case 3:
-		return FEC_5_6;
-
-	case 4:
-		return FEC_6_7;
-
-	case 5:
-		return FEC_7_8;
-	}
-
-	return FEC_NONE;
-}
-
-static fe_spectral_inversion_t s5h1420_getinversion(struct s5h1420_state* state)
-{
-	if (s5h1420_readreg(state, 0x32) & 0x08)
-		return INVERSION_ON;
-
-	return INVERSION_OFF;
-}
-
-static int s5h1420_set_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct s5h1420_state* state = fe->demodulator_priv;
-	int frequency_delta;
-	struct dvb_frontend_tune_settings fesettings;
-
-	dprintk("enter %s\n", __func__);
-
-	/* check if we should do a fast-tune */
-	s5h1420_get_tune_settings(fe, &fesettings);
-	frequency_delta = p->frequency - state->tunedfreq;
-	if ((frequency_delta > -fesettings.max_drift) &&
-			(frequency_delta < fesettings.max_drift) &&
-			(frequency_delta != 0) &&
-			(state->fec_inner == p->fec_inner) &&
-			(state->symbol_rate == p->symbol_rate)) {
-
-		if (fe->ops.tuner_ops.set_params) {
-			fe->ops.tuner_ops.set_params(fe);
-			if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
-		}
-		if (fe->ops.tuner_ops.get_frequency) {
-			u32 tmp;
-			fe->ops.tuner_ops.get_frequency(fe, &tmp);
-			if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
-			s5h1420_setfreqoffset(state, p->frequency - tmp);
-		} else {
-			s5h1420_setfreqoffset(state, 0);
-		}
-		dprintk("simple tune\n");
-		return 0;
-	}
-	dprintk("tuning demod\n");
-
-	/* first of all, software reset */
-	s5h1420_reset(state);
-
-	/* set s5h1420 fclk PLL according to desired symbol rate */
-	if (p->symbol_rate > 33000000)
-		state->fclk = 80000000;
-	else if (p->symbol_rate > 28500000)
-		state->fclk = 59000000;
-	else if (p->symbol_rate > 25000000)
-		state->fclk = 86000000;
-	else if (p->symbol_rate > 1900000)
-		state->fclk = 88000000;
-	else
-		state->fclk = 44000000;
-
-	dprintk("pll01: %d, ToneFreq: %d\n", state->fclk/1000000 - 8, (state->fclk + (TONE_FREQ * 32) - 1) / (TONE_FREQ * 32));
-	s5h1420_writereg(state, PLL01, state->fclk/1000000 - 8);
-	s5h1420_writereg(state, PLL02, 0x40);
-	s5h1420_writereg(state, DiS01, (state->fclk + (TONE_FREQ * 32) - 1) / (TONE_FREQ * 32));
-
-	/* TODO DC offset removal, config parameter ? */
-	if (p->symbol_rate > 29000000)
-		s5h1420_writereg(state, QPSK01, 0xae | 0x10);
-	else
-		s5h1420_writereg(state, QPSK01, 0xac | 0x10);
-
-	/* set misc registers */
-	s5h1420_writereg(state, CON_1, 0x00);
-	s5h1420_writereg(state, QPSK02, 0x00);
-	s5h1420_writereg(state, Pre01, 0xb0);
-
-	s5h1420_writereg(state, Loop01, 0xF0);
-	s5h1420_writereg(state, Loop02, 0x2a); /* e7 for s5h1420 */
-	s5h1420_writereg(state, Loop03, 0x79); /* 78 for s5h1420 */
-	if (p->symbol_rate > 20000000)
-		s5h1420_writereg(state, Loop04, 0x79);
-	else
-		s5h1420_writereg(state, Loop04, 0x58);
-	s5h1420_writereg(state, Loop05, 0x6b);
-
-	if (p->symbol_rate >= 8000000)
-		s5h1420_writereg(state, Post01, (0 << 6) | 0x10);
-	else if (p->symbol_rate >= 4000000)
-		s5h1420_writereg(state, Post01, (1 << 6) | 0x10);
-	else
-		s5h1420_writereg(state, Post01, (3 << 6) | 0x10);
-
-	s5h1420_writereg(state, Monitor12, 0x00); /* unfreeze DC compensation */
-
-	s5h1420_writereg(state, Sync01, 0x33);
-	s5h1420_writereg(state, Mpeg01, state->config->cdclk_polarity);
-	s5h1420_writereg(state, Mpeg02, 0x3d); /* Parallel output more, disabled -> enabled later */
-	s5h1420_writereg(state, Err01, 0x03); /* 0x1d for s5h1420 */
-
-	s5h1420_writereg(state, Vit06, 0x6e); /* 0x8e for s5h1420 */
-	s5h1420_writereg(state, DiS03, 0x00);
-	s5h1420_writereg(state, Rf01, 0x61); /* Tuner i2c address - for the gate controller */
-
-	/* set tuner PLL */
-	if (fe->ops.tuner_ops.set_params) {
-		fe->ops.tuner_ops.set_params(fe);
-		if (fe->ops.i2c_gate_ctrl)
-			fe->ops.i2c_gate_ctrl(fe, 0);
-		s5h1420_setfreqoffset(state, 0);
-	}
-
-	/* set the reset of the parameters */
-	s5h1420_setsymbolrate(state, p);
-	s5h1420_setfec_inversion(state, p);
-
-	/* start QPSK */
-	s5h1420_writereg(state, QPSK01, s5h1420_readreg(state, QPSK01) | 1);
-
-	state->fec_inner = p->fec_inner;
-	state->symbol_rate = p->symbol_rate;
-	state->postlocked = 0;
-	state->tunedfreq = p->frequency;
-
-	dprintk("leave %s\n", __func__);
-	return 0;
-}
-
-static int s5h1420_get_frontend(struct dvb_frontend* fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct s5h1420_state* state = fe->demodulator_priv;
-
-	p->frequency = state->tunedfreq + s5h1420_getfreqoffset(state);
-	p->inversion = s5h1420_getinversion(state);
-	p->symbol_rate = s5h1420_getsymbolrate(state);
-	p->fec_inner = s5h1420_getfec(state);
-
-	return 0;
-}
-
-static int s5h1420_get_tune_settings(struct dvb_frontend* fe,
-				     struct dvb_frontend_tune_settings* fesettings)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	if (p->symbol_rate > 20000000) {
-		fesettings->min_delay_ms = 50;
-		fesettings->step_size = 2000;
-		fesettings->max_drift = 8000;
-	} else if (p->symbol_rate > 12000000) {
-		fesettings->min_delay_ms = 100;
-		fesettings->step_size = 1500;
-		fesettings->max_drift = 9000;
-	} else if (p->symbol_rate > 8000000) {
-		fesettings->min_delay_ms = 100;
-		fesettings->step_size = 1000;
-		fesettings->max_drift = 8000;
-	} else if (p->symbol_rate > 4000000) {
-		fesettings->min_delay_ms = 100;
-		fesettings->step_size = 500;
-		fesettings->max_drift = 7000;
-	} else if (p->symbol_rate > 2000000) {
-		fesettings->min_delay_ms = 200;
-		fesettings->step_size = (p->symbol_rate / 8000);
-		fesettings->max_drift = 14 * fesettings->step_size;
-	} else {
-		fesettings->min_delay_ms = 200;
-		fesettings->step_size = (p->symbol_rate / 8000);
-		fesettings->max_drift = 18 * fesettings->step_size;
-	}
-
-	return 0;
-}
-
-static int s5h1420_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
-{
-	struct s5h1420_state* state = fe->demodulator_priv;
-
-	if (enable)
-		return s5h1420_writereg(state, 0x02, state->CON_1_val | 1);
-	else
-		return s5h1420_writereg(state, 0x02, state->CON_1_val & 0xfe);
-}
-
-static int s5h1420_init (struct dvb_frontend* fe)
-{
-	struct s5h1420_state* state = fe->demodulator_priv;
-
-	/* disable power down and do reset */
-	state->CON_1_val = state->config->serial_mpeg << 4;
-	s5h1420_writereg(state, 0x02, state->CON_1_val);
-	msleep(10);
-	s5h1420_reset(state);
-
-	return 0;
-}
-
-static int s5h1420_sleep(struct dvb_frontend* fe)
-{
-	struct s5h1420_state* state = fe->demodulator_priv;
-	state->CON_1_val = 0x12;
-	return s5h1420_writereg(state, 0x02, state->CON_1_val);
-}
-
-static void s5h1420_release(struct dvb_frontend* fe)
-{
-	struct s5h1420_state* state = fe->demodulator_priv;
-	i2c_del_adapter(&state->tuner_i2c_adapter);
-	kfree(state);
-}
-
-static u32 s5h1420_tuner_i2c_func(struct i2c_adapter *adapter)
-{
-	return I2C_FUNC_I2C;
-}
-
-static int s5h1420_tuner_i2c_tuner_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)
-{
-	struct s5h1420_state *state = i2c_get_adapdata(i2c_adap);
-	struct i2c_msg m[1 + num];
-	u8 tx_open[2] = { CON_1, state->CON_1_val | 1 }; /* repeater stops once there was a stop condition */
-
-	memset(m, 0, sizeof(struct i2c_msg) * (1 + num));
-
-	m[0].addr = state->config->demod_address;
-	m[0].buf  = tx_open;
-	m[0].len  = 2;
-
-	memcpy(&m[1], msg, sizeof(struct i2c_msg) * num);
-
-	return i2c_transfer(state->i2c, m, 1+num) == 1 + num ? num : -EIO;
-}
-
-static struct i2c_algorithm s5h1420_tuner_i2c_algo = {
-	.master_xfer   = s5h1420_tuner_i2c_tuner_xfer,
-	.functionality = s5h1420_tuner_i2c_func,
-};
-
-struct i2c_adapter *s5h1420_get_tuner_i2c_adapter(struct dvb_frontend *fe)
-{
-	struct s5h1420_state *state = fe->demodulator_priv;
-	return &state->tuner_i2c_adapter;
-}
-EXPORT_SYMBOL(s5h1420_get_tuner_i2c_adapter);
-
-static struct dvb_frontend_ops s5h1420_ops;
-
-struct dvb_frontend *s5h1420_attach(const struct s5h1420_config *config,
-				    struct i2c_adapter *i2c)
-{
-	/* allocate memory for the internal state */
-	struct s5h1420_state *state = kzalloc(sizeof(struct s5h1420_state), GFP_KERNEL);
-	u8 i;
-
-	if (state == NULL)
-		goto error;
-
-	/* setup the state */
-	state->config = config;
-	state->i2c = i2c;
-	state->postlocked = 0;
-	state->fclk = 88000000;
-	state->tunedfreq = 0;
-	state->fec_inner = FEC_NONE;
-	state->symbol_rate = 0;
-
-	/* check if the demod is there + identify it */
-	i = s5h1420_readreg(state, ID01);
-	if (i != 0x03)
-		goto error;
-
-	memset(state->shadow, 0xff, sizeof(state->shadow));
-
-	for (i = 0; i < 0x50; i++)
-		state->shadow[i] = s5h1420_readreg(state, i);
-
-	/* create dvb_frontend */
-	memcpy(&state->frontend.ops, &s5h1420_ops, sizeof(struct dvb_frontend_ops));
-	state->frontend.demodulator_priv = state;
-
-	/* create tuner i2c adapter */
-	strlcpy(state->tuner_i2c_adapter.name, "S5H1420-PN1010 tuner I2C bus",
-		sizeof(state->tuner_i2c_adapter.name));
-	state->tuner_i2c_adapter.algo      = &s5h1420_tuner_i2c_algo;
-	state->tuner_i2c_adapter.algo_data = NULL;
-	i2c_set_adapdata(&state->tuner_i2c_adapter, state);
-	if (i2c_add_adapter(&state->tuner_i2c_adapter) < 0) {
-		printk(KERN_ERR "S5H1420/PN1010: tuner i2c bus could not be initialized\n");
-		goto error;
-	}
-
-	return &state->frontend;
-
-error:
-	kfree(state);
-	return NULL;
-}
-EXPORT_SYMBOL(s5h1420_attach);
-
-static struct dvb_frontend_ops s5h1420_ops = {
-	.delsys = { SYS_DVBS },
-	.info = {
-		.name     = "Samsung S5H1420/PnpNetwork PN1010 DVB-S",
-		.frequency_min    = 950000,
-		.frequency_max    = 2150000,
-		.frequency_stepsize = 125,     /* kHz for QPSK frontends */
-		.frequency_tolerance  = 29500,
-		.symbol_rate_min  = 1000000,
-		.symbol_rate_max  = 45000000,
-		/*  .symbol_rate_tolerance  = ???,*/
-		.caps = FE_CAN_INVERSION_AUTO |
-		FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
-		FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
-		FE_CAN_QPSK
-	},
-
-	.release = s5h1420_release,
-
-	.init = s5h1420_init,
-	.sleep = s5h1420_sleep,
-	.i2c_gate_ctrl = s5h1420_i2c_gate_ctrl,
-
-	.set_frontend = s5h1420_set_frontend,
-	.get_frontend = s5h1420_get_frontend,
-	.get_tune_settings = s5h1420_get_tune_settings,
-
-	.read_status = s5h1420_read_status,
-	.read_ber = s5h1420_read_ber,
-	.read_signal_strength = s5h1420_read_signal_strength,
-	.read_ucblocks = s5h1420_read_ucblocks,
-
-	.diseqc_send_master_cmd = s5h1420_send_master_cmd,
-	.diseqc_recv_slave_reply = s5h1420_recv_slave_reply,
-	.diseqc_send_burst = s5h1420_send_burst,
-	.set_tone = s5h1420_set_tone,
-	.set_voltage = s5h1420_set_voltage,
-};
-
-MODULE_DESCRIPTION("Samsung S5H1420/PnpNetwork PN1010 DVB-S Demodulator driver");
-MODULE_AUTHOR("Andrew de Quincey, Patrick Boettcher");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/s5h1420.h b/drivers/media/dvb/frontends/s5h1420.h
deleted file mode 100644
index ff30813..0000000
--- a/drivers/media/dvb/frontends/s5h1420.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Driver for
- *    Samsung S5H1420 and
- *    PnpNetwork PN1010 QPSK Demodulator
- *
- * Copyright (C) 2005 Andrew de Quincey <adq_dvb@lidskialf.net>
- * Copyright (C) 2005-8 Patrick Boettcher <pb@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 S5H1420_H
-#define S5H1420_H
-
-#include <linux/dvb/frontend.h>
-
-struct s5h1420_config
-{
-	/* the demodulator's i2c address */
-	u8 demod_address;
-
-	/* does the inversion require inversion? */
-	u8 invert:1;
-
-	u8 repeated_start_workaround:1;
-	u8 cdclk_polarity:1; /* 1 == falling edge, 0 == raising edge */
-
-	u8 serial_mpeg:1;
-};
-
-#if defined(CONFIG_DVB_S5H1420) || (defined(CONFIG_DVB_S5H1420_MODULE) && defined(MODULE))
-extern struct dvb_frontend *s5h1420_attach(const struct s5h1420_config *config,
-	     struct i2c_adapter *i2c);
-extern struct i2c_adapter *s5h1420_get_tuner_i2c_adapter(struct dvb_frontend *fe);
-#else
-static inline struct dvb_frontend *s5h1420_attach(const struct s5h1420_config *config,
-					   struct i2c_adapter *i2c)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-
-static inline struct i2c_adapter *s5h1420_get_tuner_i2c_adapter(struct dvb_frontend *fe)
-{
-	return NULL;
-}
-#endif // CONFIG_DVB_S5H1420
-
-#endif // S5H1420_H
diff --git a/drivers/media/dvb/frontends/s5h1420_priv.h b/drivers/media/dvb/frontends/s5h1420_priv.h
deleted file mode 100644
index d9c58d2..0000000
--- a/drivers/media/dvb/frontends/s5h1420_priv.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Driver for
- *    Samsung S5H1420 and
- *    PnpNetwork PN1010 QPSK Demodulator
- *
- * Copyright (C) 2005 Andrew de Quincey <adq_dvb@lidskialf.net>
- * Copyright (C) 2005 Patrick Boettcher <pb@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 S5H1420_PRIV
-#define S5H1420_PRIV
-
-#include <asm/types.h>
-
-enum s5h1420_register {
-	ID01      = 0x00,
-	CON_0     = 0x01,
-	CON_1     = 0x02,
-	PLL01     = 0x03,
-	PLL02     = 0x04,
-	QPSK01    = 0x05,
-	QPSK02    = 0x06,
-	Pre01     = 0x07,
-	Post01    = 0x08,
-	Loop01    = 0x09,
-	Loop02    = 0x0a,
-	Loop03    = 0x0b,
-	Loop04    = 0x0c,
-	Loop05    = 0x0d,
-	Pnco01    = 0x0e,
-	Pnco02    = 0x0f,
-	Pnco03    = 0x10,
-	Tnco01    = 0x11,
-	Tnco02    = 0x12,
-	Tnco03    = 0x13,
-	Monitor01 = 0x14,
-	Monitor02 = 0x15,
-	Monitor03 = 0x16,
-	Monitor04 = 0x17,
-	Monitor05 = 0x18,
-	Monitor06 = 0x19,
-	Monitor07 = 0x1a,
-	Monitor12 = 0x1f,
-
-	FEC01     = 0x22,
-	Soft01    = 0x23,
-	Soft02    = 0x24,
-	Soft03    = 0x25,
-	Soft04    = 0x26,
-	Soft05    = 0x27,
-	Soft06    = 0x28,
-	Vit01     = 0x29,
-	Vit02     = 0x2a,
-	Vit03     = 0x2b,
-	Vit04     = 0x2c,
-	Vit05     = 0x2d,
-	Vit06     = 0x2e,
-	Vit07     = 0x2f,
-	Vit08     = 0x30,
-	Vit09     = 0x31,
-	Vit10     = 0x32,
-	Vit11     = 0x33,
-	Vit12     = 0x34,
-	Sync01    = 0x35,
-	Sync02    = 0x36,
-	Rs01      = 0x37,
-	Mpeg01    = 0x38,
-	Mpeg02    = 0x39,
-	DiS01     = 0x3a,
-	DiS02     = 0x3b,
-	DiS03     = 0x3c,
-	DiS04     = 0x3d,
-	DiS05     = 0x3e,
-	DiS06     = 0x3f,
-	DiS07     = 0x40,
-	DiS08     = 0x41,
-	DiS09     = 0x42,
-	DiS10     = 0x43,
-	DiS11     = 0x44,
-	Rf01      = 0x45,
-	Err01     = 0x46,
-	Err02     = 0x47,
-	Err03     = 0x48,
-	Err04     = 0x49,
-};
-
-
-#endif
diff --git a/drivers/media/dvb/frontends/s5h1432.c b/drivers/media/dvb/frontends/s5h1432.c
deleted file mode 100644
index 8352ce1..0000000
--- a/drivers/media/dvb/frontends/s5h1432.c
+++ /dev/null
@@ -1,407 +0,0 @@
-/*
- *  Samsung s5h1432 DVB-T demodulator driver
- *
- *  Copyright (C) 2009 Bill Liu <Bill.Liu@Conexant.com>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include "dvb_frontend.h"
-#include "s5h1432.h"
-
-struct s5h1432_state {
-
-	struct i2c_adapter *i2c;
-
-	/* configuration settings */
-	const struct s5h1432_config *config;
-
-	struct dvb_frontend frontend;
-
-	fe_modulation_t current_modulation;
-	unsigned int first_tune:1;
-
-	u32 current_frequency;
-	int if_freq;
-
-	u8 inversion;
-};
-
-static int debug;
-
-#define dprintk(arg...) do {	\
-	if (debug)		\
-		printk(arg);	\
-	} while (0)
-
-static int s5h1432_writereg(struct s5h1432_state *state,
-			    u8 addr, u8 reg, u8 data)
-{
-	int ret;
-	u8 buf[] = { reg, data };
-
-	struct i2c_msg msg = {.addr = addr, .flags = 0, .buf = buf, .len = 2 };
-
-	ret = i2c_transfer(state->i2c, &msg, 1);
-
-	if (ret != 1)
-		printk(KERN_ERR "%s: writereg error 0x%02x 0x%02x 0x%04x, "
-		       "ret == %i)\n", __func__, addr, reg, data, ret);
-
-	return (ret != 1) ? -1 : 0;
-}
-
-static u8 s5h1432_readreg(struct s5h1432_state *state, u8 addr, u8 reg)
-{
-	int ret;
-	u8 b0[] = { reg };
-	u8 b1[] = { 0 };
-
-	struct i2c_msg msg[] = {
-		{.addr = addr, .flags = 0, .buf = b0, .len = 1},
-		{.addr = addr, .flags = I2C_M_RD, .buf = b1, .len = 1}
-	};
-
-	ret = i2c_transfer(state->i2c, msg, 2);
-
-	if (ret != 2)
-		printk(KERN_ERR "%s: readreg error (ret == %i)\n",
-		       __func__, ret);
-	return b1[0];
-}
-
-static int s5h1432_sleep(struct dvb_frontend *fe)
-{
-	return 0;
-}
-
-static int s5h1432_set_channel_bandwidth(struct dvb_frontend *fe,
-					 u32 bandwidth)
-{
-	struct s5h1432_state *state = fe->demodulator_priv;
-
-	u8 reg = 0;
-
-	/* Register [0x2E] bit 3:2 : 8MHz = 0; 7MHz = 1; 6MHz = 2 */
-	reg = s5h1432_readreg(state, S5H1432_I2C_TOP_ADDR, 0x2E);
-	reg &= ~(0x0C);
-	switch (bandwidth) {
-	case 6:
-		reg |= 0x08;
-		break;
-	case 7:
-		reg |= 0x04;
-		break;
-	case 8:
-		reg |= 0x00;
-		break;
-	default:
-		return 0;
-	}
-	s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x2E, reg);
-	return 1;
-}
-
-static int s5h1432_set_IF(struct dvb_frontend *fe, u32 ifFreqHz)
-{
-	struct s5h1432_state *state = fe->demodulator_priv;
-
-	switch (ifFreqHz) {
-	case TAIWAN_HI_IF_FREQ_44_MHZ:
-		s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe4, 0x55);
-		s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe5, 0x55);
-		s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe7, 0x15);
-		break;
-	case EUROPE_HI_IF_FREQ_36_MHZ:
-		s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe4, 0x00);
-		s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe5, 0x00);
-		s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe7, 0x40);
-		break;
-	case IF_FREQ_6_MHZ:
-		s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe4, 0x00);
-		s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe5, 0x00);
-		s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe7, 0xe0);
-		break;
-	case IF_FREQ_3point3_MHZ:
-		s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe4, 0x66);
-		s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe5, 0x66);
-		s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe7, 0xEE);
-		break;
-	case IF_FREQ_3point5_MHZ:
-		s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe4, 0x55);
-		s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe5, 0x55);
-		s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe7, 0xED);
-		break;
-	case IF_FREQ_4_MHZ:
-		s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe4, 0xAA);
-		s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe5, 0xAA);
-		s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe7, 0xEA);
-		break;
-	default:
-		{
-			u32 value = 0;
-			value = (u32) (((48000 - (ifFreqHz / 1000)) * 512 *
-					(u32) 32768) / (48 * 1000));
-			printk(KERN_INFO
-			       "Default IFFreq %d :reg value = 0x%x\n",
-			       ifFreqHz, value);
-			s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe4,
-					 (u8) value & 0xFF);
-			s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe5,
-					 (u8) (value >> 8) & 0xFF);
-			s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe7,
-					 (u8) (value >> 16) & 0xFF);
-			break;
-		}
-
-	}
-
-	return 1;
-}
-
-/* Talk to the demod, set the FEC, GUARD, QAM settings etc */
-static int s5h1432_set_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	u32 dvb_bandwidth = 8;
-	struct s5h1432_state *state = fe->demodulator_priv;
-
-	if (p->frequency == state->current_frequency) {
-		/*current_frequency = p->frequency; */
-		/*state->current_frequency = p->frequency; */
-	} else {
-		fe->ops.tuner_ops.set_params(fe);
-		msleep(300);
-		s5h1432_set_channel_bandwidth(fe, dvb_bandwidth);
-		switch (p->bandwidth_hz) {
-		case 6000000:
-			dvb_bandwidth = 6;
-			s5h1432_set_IF(fe, IF_FREQ_4_MHZ);
-			break;
-		case 7000000:
-			dvb_bandwidth = 7;
-			s5h1432_set_IF(fe, IF_FREQ_4_MHZ);
-			break;
-		case 8000000:
-			dvb_bandwidth = 8;
-			s5h1432_set_IF(fe, IF_FREQ_4_MHZ);
-			break;
-		default:
-			return 0;
-		}
-		/*fe->ops.tuner_ops.set_params(fe); */
-/*Soft Reset chip*/
-		msleep(30);
-		s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x09, 0x1a);
-		msleep(30);
-		s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x09, 0x1b);
-
-		s5h1432_set_channel_bandwidth(fe, dvb_bandwidth);
-		switch (p->bandwidth_hz) {
-		case 6000000:
-			dvb_bandwidth = 6;
-			s5h1432_set_IF(fe, IF_FREQ_4_MHZ);
-			break;
-		case 7000000:
-			dvb_bandwidth = 7;
-			s5h1432_set_IF(fe, IF_FREQ_4_MHZ);
-			break;
-		case 8000000:
-			dvb_bandwidth = 8;
-			s5h1432_set_IF(fe, IF_FREQ_4_MHZ);
-			break;
-		default:
-			return 0;
-		}
-		/*fe->ops.tuner_ops.set_params(fe); */
-		/*Soft Reset chip*/
-		msleep(30);
-		s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x09, 0x1a);
-		msleep(30);
-		s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x09, 0x1b);
-
-	}
-
-	state->current_frequency = p->frequency;
-
-	return 0;
-}
-
-static int s5h1432_init(struct dvb_frontend *fe)
-{
-	struct s5h1432_state *state = fe->demodulator_priv;
-
-	u8 reg = 0;
-	state->current_frequency = 0;
-	printk(KERN_INFO " s5h1432_init().\n");
-
-	/*Set VSB mode as default, this also does a soft reset */
-	/*Initialize registers */
-
-	s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x04, 0xa8);
-	s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x05, 0x01);
-	s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x07, 0x70);
-	s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x19, 0x80);
-	s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x1b, 0x9D);
-	s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x1c, 0x30);
-	s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x1d, 0x20);
-	s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x1e, 0x1B);
-	s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x2e, 0x40);
-	s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x42, 0x84);
-	s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x50, 0x5a);
-	s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x5a, 0xd3);
-	s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x68, 0x50);
-	s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xb8, 0x3c);
-	s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xc4, 0x10);
-	s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xcc, 0x9c);
-	s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xDA, 0x00);
-	s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe1, 0x94);
-	/* s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xf4, 0xa1); */
-	s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xf9, 0x00);
-
-	/*For NXP tuner*/
-
-	/*Set 3.3MHz as default IF frequency */
-	s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe4, 0x66);
-	s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe5, 0x66);
-	s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe7, 0xEE);
-	/* Set reg 0x1E to get the full dynamic range */
-	s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x1e, 0x31);
-
-	/* Mode setting in demod */
-	reg = s5h1432_readreg(state, S5H1432_I2C_TOP_ADDR, 0x42);
-	reg |= 0x80;
-	s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x42, reg);
-	/* Serial mode */
-
-	/* Soft Reset chip */
-
-	s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x09, 0x1a);
-	msleep(30);
-	s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x09, 0x1b);
-
-
-	return 0;
-}
-
-static int s5h1432_read_status(struct dvb_frontend *fe, fe_status_t *status)
-{
-	return 0;
-}
-
-static int s5h1432_read_signal_strength(struct dvb_frontend *fe,
-					u16 *signal_strength)
-{
-	return 0;
-}
-
-static int s5h1432_read_snr(struct dvb_frontend *fe, u16 *snr)
-{
-	return 0;
-}
-
-static int s5h1432_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
-{
-
-	return 0;
-}
-
-static int s5h1432_read_ber(struct dvb_frontend *fe, u32 *ber)
-{
-	return 0;
-}
-
-static int s5h1432_get_tune_settings(struct dvb_frontend *fe,
-				     struct dvb_frontend_tune_settings *tune)
-{
-	return 0;
-}
-
-static void s5h1432_release(struct dvb_frontend *fe)
-{
-	struct s5h1432_state *state = fe->demodulator_priv;
-	kfree(state);
-}
-
-static struct dvb_frontend_ops s5h1432_ops;
-
-struct dvb_frontend *s5h1432_attach(const struct s5h1432_config *config,
-				    struct i2c_adapter *i2c)
-{
-	struct s5h1432_state *state = NULL;
-
-	printk(KERN_INFO " Enter s5h1432_attach(). attach success!\n");
-	/* allocate memory for the internal state */
-	state = kmalloc(sizeof(struct s5h1432_state), GFP_KERNEL);
-	if (state == NULL)
-		goto error;
-
-	/* setup the state */
-	state->config = config;
-	state->i2c = i2c;
-	state->current_modulation = QAM_16;
-	state->inversion = state->config->inversion;
-
-	/* create dvb_frontend */
-	memcpy(&state->frontend.ops, &s5h1432_ops,
-	       sizeof(struct dvb_frontend_ops));
-
-	state->frontend.demodulator_priv = state;
-
-	return &state->frontend;
-
-error:
-	kfree(state);
-	return NULL;
-}
-EXPORT_SYMBOL(s5h1432_attach);
-
-static struct dvb_frontend_ops s5h1432_ops = {
-	.delsys = { SYS_DVBT },
-	.info = {
-		 .name = "Samsung s5h1432 DVB-T Frontend",
-		 .frequency_min = 177000000,
-		 .frequency_max = 858000000,
-		 .frequency_stepsize = 166666,
-		 .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_FEC_AUTO |
-		 FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
-		 FE_CAN_HIERARCHY_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |
-		 FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_RECOVER},
-
-	.init = s5h1432_init,
-	.sleep = s5h1432_sleep,
-	.set_frontend = s5h1432_set_frontend,
-	.get_tune_settings = s5h1432_get_tune_settings,
-	.read_status = s5h1432_read_status,
-	.read_ber = s5h1432_read_ber,
-	.read_signal_strength = s5h1432_read_signal_strength,
-	.read_snr = s5h1432_read_snr,
-	.read_ucblocks = s5h1432_read_ucblocks,
-	.release = s5h1432_release,
-};
-
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Enable verbose debug messages");
-
-MODULE_DESCRIPTION("Samsung s5h1432 DVB-T Demodulator driver");
-MODULE_AUTHOR("Bill Liu");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/s5h1432.h b/drivers/media/dvb/frontends/s5h1432.h
deleted file mode 100644
index b57438c..0000000
--- a/drivers/media/dvb/frontends/s5h1432.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- *  Samsung s5h1432 VSB/QAM demodulator driver
- *
- *  Copyright (C) 2009 Bill Liu <Bill.Liu@Conexant.com>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#ifndef __S5H1432_H__
-#define __S5H1432_H__
-
-#include <linux/dvb/frontend.h>
-
-#define S5H1432_I2C_TOP_ADDR (0x02 >> 1)
-
-#define TAIWAN_HI_IF_FREQ_44_MHZ 44000000
-#define EUROPE_HI_IF_FREQ_36_MHZ 36000000
-#define IF_FREQ_6_MHZ             6000000
-#define IF_FREQ_3point3_MHZ       3300000
-#define IF_FREQ_3point5_MHZ       3500000
-#define IF_FREQ_4_MHZ             4000000
-
-struct s5h1432_config {
-
-	/* serial/parallel output */
-#define S5H1432_PARALLEL_OUTPUT 0
-#define S5H1432_SERIAL_OUTPUT   1
-	u8 output_mode;
-
-	/* GPIO Setting */
-#define S5H1432_GPIO_OFF 0
-#define S5H1432_GPIO_ON  1
-	u8 gpio;
-
-	/* MPEG signal timing */
-#define S5H1432_MPEGTIMING_CONTINOUS_INVERTING_CLOCK       0
-#define S5H1432_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK    1
-#define S5H1432_MPEGTIMING_NONCONTINOUS_INVERTING_CLOCK    2
-#define S5H1432_MPEGTIMING_NONCONTINOUS_NONINVERTING_CLOCK 3
-	u16 mpeg_timing;
-
-	/* IF Freq for QAM and VSB in KHz */
-#define S5H1432_IF_3250  3250
-#define S5H1432_IF_3500  3500
-#define S5H1432_IF_4000  4000
-#define S5H1432_IF_5380  5380
-#define S5H1432_IF_44000 44000
-#define S5H1432_VSB_IF_DEFAULT s5h1432_IF_44000
-#define S5H1432_QAM_IF_DEFAULT s5h1432_IF_44000
-	u16 qam_if;
-	u16 vsb_if;
-
-	/* Spectral Inversion */
-#define S5H1432_INVERSION_OFF 0
-#define S5H1432_INVERSION_ON  1
-	u8 inversion;
-
-	/* Return lock status based on tuner lock, or demod lock */
-#define S5H1432_TUNERLOCKING 0
-#define S5H1432_DEMODLOCKING 1
-	u8 status_mode;
-};
-
-#if defined(CONFIG_DVB_S5H1432) || \
-	(defined(CONFIG_DVB_S5H1432_MODULE) && defined(MODULE))
-extern struct dvb_frontend *s5h1432_attach(const struct s5h1432_config *config,
-					   struct i2c_adapter *i2c);
-#else
-static inline struct dvb_frontend *s5h1432_attach(const struct s5h1432_config
-						  *config,
-						  struct i2c_adapter *i2c)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif /* CONFIG_DVB_s5h1432 */
-
-#endif /* __s5h1432_H__ */
diff --git a/drivers/media/dvb/frontends/s921.c b/drivers/media/dvb/frontends/s921.c
deleted file mode 100644
index cd2288c..0000000
--- a/drivers/media/dvb/frontends/s921.c
+++ /dev/null
@@ -1,549 +0,0 @@
-/*
- *   Sharp VA3A5JZ921 One Seg Broadcast Module driver
- *   This device is labeled as just S. 921 at the top of the frontend can
- *
- *   Copyright (C) 2009-2010 Mauro Carvalho Chehab <mchehab@redhat.com>
- *   Copyright (C) 2009-2010 Douglas Landgraf <dougsland@redhat.com>
- *
- *   Developed for Leadership SBTVD 1seg device sold in Brazil
- *
- *   Frontend module based on cx24123 driver, getting some info from
- *	the old s921 driver.
- *
- *   FIXME: Need to port to DVB v5.2 API
- *
- *   This program is free software; you can redistribute it and/or
- *   modify it under the terms of the GNU General Public License as
- *   published by the Free Software Foundation version 2.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *   General Public License for more details.
- */
-
-#include <linux/kernel.h>
-#include <asm/div64.h>
-
-#include "dvb_frontend.h"
-#include "s921.h"
-
-static int debug = 1;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)");
-
-#define rc(args...)  do {						\
-	printk(KERN_ERR  "s921: " args);				\
-} while (0)
-
-#define dprintk(args...)						\
-	do {								\
-		if (debug) {						\
-			printk(KERN_DEBUG "s921: %s: ", __func__);	\
-			printk(args);					\
-		}							\
-	} while (0)
-
-struct s921_state {
-	struct i2c_adapter *i2c;
-	const struct s921_config *config;
-
-	struct dvb_frontend frontend;
-
-	/* The Demod can't easily provide these, we cache them */
-	u32 currentfreq;
-};
-
-/*
- * Various tuner defaults need to be established for a given frequency kHz.
- * fixme: The bounds on the bands do not match the doc in real life.
- * fixme: Some of them have been moved, other might need adjustment.
- */
-static struct s921_bandselect_val {
-	u32 freq_low;
-	u8  band_reg;
-} s921_bandselect[] = {
-	{         0, 0x7b },
-	{ 485140000, 0x5b },
-	{ 515140000, 0x3b },
-	{ 545140000, 0x1b },
-	{ 599140000, 0xfb },
-	{ 623140000, 0xdb },
-	{ 659140000, 0xbb },
-	{ 713140000, 0x9b },
-};
-
-struct regdata {
-	u8 reg;
-	u8 data;
-};
-
-static struct regdata s921_init[] = {
-	{ 0x01, 0x80 },		/* Probably, a reset sequence */
-	{ 0x01, 0x40 },
-	{ 0x01, 0x80 },
-	{ 0x01, 0x40 },
-
-	{ 0x02, 0x00 },
-	{ 0x03, 0x40 },
-	{ 0x04, 0x01 },
-	{ 0x05, 0x00 },
-	{ 0x06, 0x00 },
-	{ 0x07, 0x00 },
-	{ 0x08, 0x00 },
-	{ 0x09, 0x00 },
-	{ 0x0a, 0x00 },
-	{ 0x0b, 0x5a },
-	{ 0x0c, 0x00 },
-	{ 0x0d, 0x00 },
-	{ 0x0f, 0x00 },
-	{ 0x13, 0x1b },
-	{ 0x14, 0x80 },
-	{ 0x15, 0x40 },
-	{ 0x17, 0x70 },
-	{ 0x18, 0x01 },
-	{ 0x19, 0x12 },
-	{ 0x1a, 0x01 },
-	{ 0x1b, 0x12 },
-	{ 0x1c, 0xa0 },
-	{ 0x1d, 0x00 },
-	{ 0x1e, 0x0a },
-	{ 0x1f, 0x08 },
-	{ 0x20, 0x40 },
-	{ 0x21, 0xff },
-	{ 0x22, 0x4c },
-	{ 0x23, 0x4e },
-	{ 0x24, 0x4c },
-	{ 0x25, 0x00 },
-	{ 0x26, 0x00 },
-	{ 0x27, 0xf4 },
-	{ 0x28, 0x60 },
-	{ 0x29, 0x88 },
-	{ 0x2a, 0x40 },
-	{ 0x2b, 0x40 },
-	{ 0x2c, 0xff },
-	{ 0x2d, 0x00 },
-	{ 0x2e, 0xff },
-	{ 0x2f, 0x00 },
-	{ 0x30, 0x20 },
-	{ 0x31, 0x06 },
-	{ 0x32, 0x0c },
-	{ 0x34, 0x0f },
-	{ 0x37, 0xfe },
-	{ 0x38, 0x00 },
-	{ 0x39, 0x63 },
-	{ 0x3a, 0x10 },
-	{ 0x3b, 0x10 },
-	{ 0x47, 0x00 },
-	{ 0x49, 0xe5 },
-	{ 0x4b, 0x00 },
-	{ 0x50, 0xc0 },
-	{ 0x52, 0x20 },
-	{ 0x54, 0x5a },
-	{ 0x55, 0x5b },
-	{ 0x56, 0x40 },
-	{ 0x57, 0x70 },
-	{ 0x5c, 0x50 },
-	{ 0x5d, 0x00 },
-	{ 0x62, 0x17 },
-	{ 0x63, 0x2f },
-	{ 0x64, 0x6f },
-	{ 0x68, 0x00 },
-	{ 0x69, 0x89 },
-	{ 0x6a, 0x00 },
-	{ 0x6b, 0x00 },
-	{ 0x6c, 0x00 },
-	{ 0x6d, 0x00 },
-	{ 0x6e, 0x00 },
-	{ 0x70, 0x10 },
-	{ 0x71, 0x00 },
-	{ 0x75, 0x00 },
-	{ 0x76, 0x30 },
-	{ 0x77, 0x01 },
-	{ 0xaf, 0x00 },
-	{ 0xb0, 0xa0 },
-	{ 0xb2, 0x3d },
-	{ 0xb3, 0x25 },
-	{ 0xb4, 0x8b },
-	{ 0xb5, 0x4b },
-	{ 0xb6, 0x3f },
-	{ 0xb7, 0xff },
-	{ 0xb8, 0xff },
-	{ 0xb9, 0xfc },
-	{ 0xba, 0x00 },
-	{ 0xbb, 0x00 },
-	{ 0xbc, 0x00 },
-	{ 0xd0, 0x30 },
-	{ 0xe4, 0x84 },
-	{ 0xf0, 0x48 },
-	{ 0xf1, 0x19 },
-	{ 0xf2, 0x5a },
-	{ 0xf3, 0x8e },
-	{ 0xf4, 0x2d },
-	{ 0xf5, 0x07 },
-	{ 0xf6, 0x5a },
-	{ 0xf7, 0xba },
-	{ 0xf8, 0xd7 },
-};
-
-static struct regdata s921_prefreq[] = {
-	{ 0x47, 0x60 },
-	{ 0x68, 0x00 },
-	{ 0x69, 0x89 },
-	{ 0xf0, 0x48 },
-	{ 0xf1, 0x19 },
-};
-
-static struct regdata s921_postfreq[] = {
-	{ 0xf5, 0xae },
-	{ 0xf6, 0xb7 },
-	{ 0xf7, 0xba },
-	{ 0xf8, 0xd7 },
-	{ 0x68, 0x0a },
-	{ 0x69, 0x09 },
-};
-
-static int s921_i2c_writereg(struct s921_state *state,
-			     u8 i2c_addr, int reg, int data)
-{
-	u8 buf[] = { reg, data };
-	struct i2c_msg msg = {
-		.addr = i2c_addr, .flags = 0, .buf = buf, .len = 2
-	};
-	int rc;
-
-	rc = i2c_transfer(state->i2c, &msg, 1);
-	if (rc != 1) {
-		printk("%s: writereg rcor(rc == %i, reg == 0x%02x,"
-			 " data == 0x%02x)\n", __func__, rc, reg, data);
-		return rc;
-	}
-
-	return 0;
-}
-
-static int s921_i2c_writeregdata(struct s921_state *state, u8 i2c_addr,
-				 struct regdata *rd, int size)
-{
-	int i, rc;
-
-	for (i = 0; i < size; i++) {
-		rc = s921_i2c_writereg(state, i2c_addr, rd[i].reg, rd[i].data);
-		if (rc < 0)
-			return rc;
-	}
-	return 0;
-}
-
-static int s921_i2c_readreg(struct s921_state *state, u8 i2c_addr, u8 reg)
-{
-	u8 val;
-	int rc;
-	struct i2c_msg msg[] = {
-		{ .addr = i2c_addr, .flags = 0, .buf = &reg, .len = 1 },
-		{ .addr = i2c_addr, .flags = I2C_M_RD, .buf = &val, .len = 1 }
-	};
-
-	rc = i2c_transfer(state->i2c, msg, 2);
-
-	if (rc != 2) {
-		rc("%s: reg=0x%x (rcor=%d)\n", __func__, reg, rc);
-		return rc;
-	}
-
-	return val;
-}
-
-#define s921_readreg(state, reg) \
-	s921_i2c_readreg(state, state->config->demod_address, reg)
-#define s921_writereg(state, reg, val) \
-	s921_i2c_writereg(state, state->config->demod_address, reg, val)
-#define s921_writeregdata(state, regdata) \
-	s921_i2c_writeregdata(state, state->config->demod_address, \
-	regdata, ARRAY_SIZE(regdata))
-
-static int s921_pll_tune(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct s921_state *state = fe->demodulator_priv;
-	int band, rc, i;
-	unsigned long f_offset;
-	u8 f_switch;
-	u64 offset;
-
-	dprintk("frequency=%i\n", p->frequency);
-
-	for (band = 0; band < ARRAY_SIZE(s921_bandselect); band++)
-		if (p->frequency < s921_bandselect[band].freq_low)
-			break;
-	band--;
-
-	if (band < 0) {
-		rc("%s: frequency out of range\n", __func__);
-		return -EINVAL;
-	}
-
-	f_switch = s921_bandselect[band].band_reg;
-
-	offset = ((u64)p->frequency) * 258;
-	do_div(offset, 6000000);
-	f_offset = ((unsigned long)offset) + 2321;
-
-	rc = s921_writeregdata(state, s921_prefreq);
-	if (rc < 0)
-		return rc;
-
-	rc = s921_writereg(state, 0xf2, (f_offset >> 8) & 0xff);
-	if (rc < 0)
-		return rc;
-
-	rc = s921_writereg(state, 0xf3, f_offset & 0xff);
-	if (rc < 0)
-		return rc;
-
-	rc = s921_writereg(state, 0xf4, f_switch);
-	if (rc < 0)
-		return rc;
-
-	rc = s921_writeregdata(state, s921_postfreq);
-	if (rc < 0)
-		return rc;
-
-	for (i = 0 ; i < 6; i++) {
-		rc = s921_readreg(state, 0x80);
-		dprintk("status 0x80: %02x\n", rc);
-	}
-	rc = s921_writereg(state, 0x01, 0x40);
-	if (rc < 0)
-		return rc;
-
-	rc = s921_readreg(state, 0x01);
-	dprintk("status 0x01: %02x\n", rc);
-
-	rc = s921_readreg(state, 0x80);
-	dprintk("status 0x80: %02x\n", rc);
-
-	rc = s921_readreg(state, 0x80);
-	dprintk("status 0x80: %02x\n", rc);
-
-	rc = s921_readreg(state, 0x32);
-	dprintk("status 0x32: %02x\n", rc);
-
-	dprintk("pll tune band=%d, pll=%d\n", f_switch, (int)f_offset);
-
-	return 0;
-}
-
-static int s921_initfe(struct dvb_frontend *fe)
-{
-	struct s921_state *state = fe->demodulator_priv;
-	int rc;
-
-	dprintk("\n");
-
-	rc = s921_writeregdata(state, s921_init);
-	if (rc < 0)
-		return rc;
-
-	return 0;
-}
-
-static int s921_read_status(struct dvb_frontend *fe, fe_status_t *status)
-{
-	struct s921_state *state = fe->demodulator_priv;
-	int regstatus, rc;
-
-	*status = 0;
-
-	rc = s921_readreg(state, 0x81);
-	if (rc < 0)
-		return rc;
-
-	regstatus = rc << 8;
-
-	rc = s921_readreg(state, 0x82);
-	if (rc < 0)
-		return rc;
-
-	regstatus |= rc;
-
-	dprintk("status = %04x\n", regstatus);
-
-	/* Full Sync - We don't know what each bit means on regs 0x81/0x82 */
-	if ((regstatus & 0xff) == 0x40) {
-		*status = FE_HAS_SIGNAL  |
-			  FE_HAS_CARRIER |
-			  FE_HAS_VITERBI |
-			  FE_HAS_SYNC    |
-			  FE_HAS_LOCK;
-	} else if (regstatus & 0x40) {
-		/* This is close to Full Sync, but not enough to get useful info */
-		*status = FE_HAS_SIGNAL  |
-			  FE_HAS_CARRIER |
-			  FE_HAS_VITERBI |
-			  FE_HAS_SYNC;
-	}
-
-	return 0;
-}
-
-static int s921_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
-{
-	fe_status_t	status;
-	struct s921_state *state = fe->demodulator_priv;
-	int rc;
-
-	/* FIXME: Use the proper register for it... 0x80? */
-	rc = s921_read_status(fe, &status);
-	if (rc < 0)
-		return rc;
-
-	*strength = (status & FE_HAS_LOCK) ? 0xffff : 0;
-
-	dprintk("strength = 0x%04x\n", *strength);
-
-	rc = s921_readreg(state, 0x01);
-	dprintk("status 0x01: %02x\n", rc);
-
-	rc = s921_readreg(state, 0x80);
-	dprintk("status 0x80: %02x\n", rc);
-
-	rc = s921_readreg(state, 0x32);
-	dprintk("status 0x32: %02x\n", rc);
-
-	return 0;
-}
-
-static int s921_set_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct s921_state *state = fe->demodulator_priv;
-	int rc;
-
-	dprintk("\n");
-
-	/* FIXME: We don't know how to use non-auto mode */
-
-	rc = s921_pll_tune(fe);
-	if (rc < 0)
-		return rc;
-
-	state->currentfreq = p->frequency;
-
-	return 0;
-}
-
-static int s921_get_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct s921_state *state = fe->demodulator_priv;
-
-	/* FIXME: Probably it is possible to get it from regs f1 and f2 */
-	p->frequency = state->currentfreq;
-	p->delivery_system = SYS_ISDBT;
-
-	return 0;
-}
-
-static int s921_tune(struct dvb_frontend *fe,
-			bool re_tune,
-			unsigned int mode_flags,
-			unsigned int *delay,
-			fe_status_t *status)
-{
-	int rc = 0;
-
-	dprintk("\n");
-
-	if (re_tune)
-		rc = s921_set_frontend(fe);
-
-	if (!(mode_flags & FE_TUNE_MODE_ONESHOT))
-		s921_read_status(fe, status);
-
-	return rc;
-}
-
-static int s921_get_algo(struct dvb_frontend *fe)
-{
-	return 1; /* FE_ALGO_HW */
-}
-
-static void s921_release(struct dvb_frontend *fe)
-{
-	struct s921_state *state = fe->demodulator_priv;
-
-	dprintk("\n");
-	kfree(state);
-}
-
-static struct dvb_frontend_ops s921_ops;
-
-struct dvb_frontend *s921_attach(const struct s921_config *config,
-				    struct i2c_adapter *i2c)
-{
-	/* allocate memory for the internal state */
-	struct s921_state *state =
-		kzalloc(sizeof(struct s921_state), GFP_KERNEL);
-
-	dprintk("\n");
-	if (state == NULL) {
-		rc("Unable to kzalloc\n");
-		goto rcor;
-	}
-
-	/* setup the state */
-	state->config = config;
-	state->i2c = i2c;
-
-	/* create dvb_frontend */
-	memcpy(&state->frontend.ops, &s921_ops,
-		sizeof(struct dvb_frontend_ops));
-	state->frontend.demodulator_priv = state;
-
-	return &state->frontend;
-
-rcor:
-	kfree(state);
-
-	return NULL;
-}
-EXPORT_SYMBOL(s921_attach);
-
-static struct dvb_frontend_ops s921_ops = {
-	.delsys = { SYS_ISDBT },
-	/* Use dib8000 values per default */
-	.info = {
-		.name = "Sharp S921",
-		.frequency_min = 470000000,
-		/*
-		 * Max should be 770MHz instead, according with Sharp docs,
-		 * but Leadership doc says it works up to 806 MHz. This is
-		 * required to get channel 69, used in Brazil
-		 */
-		.frequency_max = 806000000,
-		.frequency_tolerance = 0,
-		 .caps = FE_CAN_INVERSION_AUTO |
-			 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_FEC_AUTO |
-			 FE_CAN_QPSK     | FE_CAN_QAM_16 | FE_CAN_QAM_64 |
-			 FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO |
-			 FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_RECOVER |
-			 FE_CAN_HIERARCHY_AUTO,
-	},
-
-	.release = s921_release,
-
-	.init = s921_initfe,
-	.set_frontend = s921_set_frontend,
-	.get_frontend = s921_get_frontend,
-	.read_status = s921_read_status,
-	.read_signal_strength = s921_read_signal_strength,
-	.tune = s921_tune,
-	.get_frontend_algo = s921_get_algo,
-};
-
-MODULE_DESCRIPTION("DVB Frontend module for Sharp S921 hardware");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
-MODULE_AUTHOR("Douglas Landgraf <dougsland@redhat.com>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/s921.h b/drivers/media/dvb/frontends/s921.h
deleted file mode 100644
index f220d82..0000000
--- a/drivers/media/dvb/frontends/s921.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- *   Sharp s921 driver
- *
- *   Copyright (C) 2009 Mauro Carvalho Chehab <mchehab@redhat.com>
- *   Copyright (C) 2009 Douglas Landgraf <dougsland@redhat.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 version 2.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *   General Public License for more details.
- */
-
-#ifndef S921_H
-#define S921_H
-
-#include <linux/dvb/frontend.h>
-
-struct s921_config {
-	/* the demodulator's i2c address */
-	u8 demod_address;
-};
-
-#if defined(CONFIG_DVB_S921) || (defined(CONFIG_DVB_S921_MODULE) \
-	&& defined(MODULE))
-extern struct dvb_frontend *s921_attach(const struct s921_config *config,
-					   struct i2c_adapter *i2c);
-extern struct i2c_adapter *s921_get_tuner_i2c_adapter(struct dvb_frontend *);
-#else
-static inline struct dvb_frontend *s921_attach(
-	const struct s921_config *config, struct i2c_adapter *i2c)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-static struct i2c_adapter *
-	s921_get_tuner_i2c_adapter(struct dvb_frontend *fe)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif
-
-#endif /* S921_H */
diff --git a/drivers/media/dvb/frontends/si21xx.c b/drivers/media/dvb/frontends/si21xx.c
deleted file mode 100644
index a68a648..0000000
--- a/drivers/media/dvb/frontends/si21xx.c
+++ /dev/null
@@ -1,951 +0,0 @@
-/* DVB compliant Linux driver for the DVB-S si2109/2110 demodulator
-*
-* Copyright (C) 2008 Igor M. Liplianin (liplianin@me.by)
-*
-*	This program is free software; you can redistribute it and/or modify
-*	it under the terms of the 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/kernel.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/jiffies.h>
-#include <asm/div64.h>
-
-#include "dvb_frontend.h"
-#include "si21xx.h"
-
-#define	REVISION_REG			0x00
-#define	SYSTEM_MODE_REG			0x01
-#define	TS_CTRL_REG_1			0x02
-#define	TS_CTRL_REG_2			0x03
-#define	PIN_CTRL_REG_1			0x04
-#define	PIN_CTRL_REG_2			0x05
-#define	LOCK_STATUS_REG_1		0x0f
-#define	LOCK_STATUS_REG_2		0x10
-#define	ACQ_STATUS_REG			0x11
-#define	ACQ_CTRL_REG_1			0x13
-#define	ACQ_CTRL_REG_2			0x14
-#define	PLL_DIVISOR_REG			0x15
-#define	COARSE_TUNE_REG			0x16
-#define	FINE_TUNE_REG_L			0x17
-#define	FINE_TUNE_REG_H			0x18
-
-#define	ANALOG_AGC_POWER_LEVEL_REG	0x28
-#define	CFO_ESTIMATOR_CTRL_REG_1	0x29
-#define	CFO_ESTIMATOR_CTRL_REG_2	0x2a
-#define	CFO_ESTIMATOR_CTRL_REG_3	0x2b
-
-#define	SYM_RATE_ESTIMATE_REG_L		0x31
-#define	SYM_RATE_ESTIMATE_REG_M		0x32
-#define	SYM_RATE_ESTIMATE_REG_H		0x33
-
-#define	CFO_ESTIMATOR_OFFSET_REG_L	0x36
-#define	CFO_ESTIMATOR_OFFSET_REG_H	0x37
-#define	CFO_ERROR_REG_L			0x38
-#define	CFO_ERROR_REG_H			0x39
-#define	SYM_RATE_ESTIMATOR_CTRL_REG	0x3a
-
-#define	SYM_RATE_REG_L			0x3f
-#define	SYM_RATE_REG_M			0x40
-#define	SYM_RATE_REG_H			0x41
-#define	SYM_RATE_ESTIMATOR_MAXIMUM_REG	0x42
-#define	SYM_RATE_ESTIMATOR_MINIMUM_REG	0x43
-
-#define	C_N_ESTIMATOR_CTRL_REG		0x7c
-#define	C_N_ESTIMATOR_THRSHLD_REG	0x7d
-#define	C_N_ESTIMATOR_LEVEL_REG_L	0x7e
-#define	C_N_ESTIMATOR_LEVEL_REG_H	0x7f
-
-#define	BLIND_SCAN_CTRL_REG		0x80
-
-#define	LSA_CTRL_REG_1			0x8D
-#define	SPCTRM_TILT_CORR_THRSHLD_REG	0x8f
-#define	ONE_DB_BNDWDTH_THRSHLD_REG	0x90
-#define	TWO_DB_BNDWDTH_THRSHLD_REG	0x91
-#define	THREE_DB_BNDWDTH_THRSHLD_REG	0x92
-#define	INBAND_POWER_THRSHLD_REG	0x93
-#define	REF_NOISE_LVL_MRGN_THRSHLD_REG	0x94
-
-#define	VIT_SRCH_CTRL_REG_1		0xa0
-#define	VIT_SRCH_CTRL_REG_2		0xa1
-#define	VIT_SRCH_CTRL_REG_3		0xa2
-#define	VIT_SRCH_STATUS_REG		0xa3
-#define	VITERBI_BER_COUNT_REG_L		0xab
-#define	REED_SOLOMON_CTRL_REG		0xb0
-#define	REED_SOLOMON_ERROR_COUNT_REG_L	0xb1
-#define	PRBS_CTRL_REG			0xb5
-
-#define	LNB_CTRL_REG_1			0xc0
-#define	LNB_CTRL_REG_2			0xc1
-#define	LNB_CTRL_REG_3			0xc2
-#define	LNB_CTRL_REG_4			0xc3
-#define	LNB_CTRL_STATUS_REG		0xc4
-#define	LNB_FIFO_REGS_0			0xc5
-#define	LNB_FIFO_REGS_1			0xc6
-#define	LNB_FIFO_REGS_2			0xc7
-#define	LNB_FIFO_REGS_3			0xc8
-#define	LNB_FIFO_REGS_4			0xc9
-#define	LNB_FIFO_REGS_5			0xca
-#define	LNB_SUPPLY_CTRL_REG_1		0xcb
-#define	LNB_SUPPLY_CTRL_REG_2		0xcc
-#define	LNB_SUPPLY_CTRL_REG_3		0xcd
-#define	LNB_SUPPLY_CTRL_REG_4		0xce
-#define	LNB_SUPPLY_STATUS_REG		0xcf
-
-#define FAIL	-1
-#define PASS	0
-
-#define ALLOWABLE_FS_COUNT	10
-#define STATUS_BER		0
-#define STATUS_UCBLOCKS		1
-
-static int debug;
-#define dprintk(args...) \
-	do { \
-		if (debug) \
-			printk(KERN_DEBUG "si21xx: " args); \
-	} while (0)
-
-enum {
-	ACTIVE_HIGH,
-	ACTIVE_LOW
-};
-enum {
-	BYTE_WIDE,
-	BIT_WIDE
-};
-enum {
-	CLK_GAPPED_MODE,
-	CLK_CONTINUOUS_MODE
-};
-enum {
-	RISING_EDGE,
-	FALLING_EDGE
-};
-enum {
-	MSB_FIRST,
-	LSB_FIRST
-};
-enum {
-	SERIAL,
-	PARALLEL
-};
-
-struct si21xx_state {
-	struct i2c_adapter *i2c;
-	const struct si21xx_config *config;
-	struct dvb_frontend frontend;
-	u8 initialised:1;
-	int errmode;
-	int fs;			/*Sampling rate of the ADC in MHz*/
-};
-
-/*	register default initialization */
-static u8 serit_sp1511lhb_inittab[] = {
-	0x01, 0x28,	/* set i2c_inc_disable */
-	0x20, 0x03,
-	0x27, 0x20,
-	0xe0, 0x45,
-	0xe1, 0x08,
-	0xfe, 0x01,
-	0x01, 0x28,
-	0x89, 0x09,
-	0x04, 0x80,
-	0x05, 0x01,
-	0x06, 0x00,
-	0x20, 0x03,
-	0x24, 0x88,
-	0x29, 0x09,
-	0x2a, 0x0f,
-	0x2c, 0x10,
-	0x2d, 0x19,
-	0x2e, 0x08,
-	0x2f, 0x10,
-	0x30, 0x19,
-	0x34, 0x20,
-	0x35, 0x03,
-	0x45, 0x02,
-	0x46, 0x45,
-	0x47, 0xd0,
-	0x48, 0x00,
-	0x49, 0x40,
-	0x4a, 0x03,
-	0x4c, 0xfd,
-	0x4f, 0x2e,
-	0x50, 0x2e,
-	0x51, 0x10,
-	0x52, 0x10,
-	0x56, 0x92,
-	0x59, 0x00,
-	0x5a, 0x2d,
-	0x5b, 0x33,
-	0x5c, 0x1f,
-	0x5f, 0x76,
-	0x62, 0xc0,
-	0x63, 0xc0,
-	0x64, 0xf3,
-	0x65, 0xf3,
-	0x79, 0x40,
-	0x6a, 0x40,
-	0x6b, 0x0a,
-	0x6c, 0x80,
-	0x6d, 0x27,
-	0x71, 0x06,
-	0x75, 0x60,
-	0x78, 0x00,
-	0x79, 0xb5,
-	0x7c, 0x05,
-	0x7d, 0x1a,
-	0x87, 0x55,
-	0x88, 0x72,
-	0x8f, 0x08,
-	0x90, 0xe0,
-	0x94, 0x40,
-	0xa0, 0x3f,
-	0xa1, 0xc0,
-	0xa4, 0xcc,
-	0xa5, 0x66,
-	0xa6, 0x66,
-	0xa7, 0x7b,
-	0xa8, 0x7b,
-	0xa9, 0x7b,
-	0xaa, 0x9a,
-	0xed, 0x04,
-	0xad, 0x00,
-	0xae, 0x03,
-	0xcc, 0xab,
-	0x01, 0x08,
-	0xff, 0xff
-};
-
-/*	low level read/writes */
-static int si21_writeregs(struct si21xx_state *state, u8 reg1,
-							u8 *data, int len)
-{
-	int ret;
-	u8 buf[60];/* = { reg1, data };*/
-	struct i2c_msg msg = {
-				.addr = state->config->demod_address,
-				.flags = 0,
-				.buf = buf,
-				.len = len + 1
-	};
-
-	msg.buf[0] =  reg1;
-	memcpy(msg.buf + 1, data, len);
-
-	ret = i2c_transfer(state->i2c, &msg, 1);
-
-	if (ret != 1)
-		dprintk("%s: writereg error (reg1 == 0x%02x, data == 0x%02x, "
-			"ret == %i)\n", __func__, reg1, data[0], ret);
-
-	return (ret != 1) ? -EREMOTEIO : 0;
-}
-
-static int si21_writereg(struct si21xx_state *state, u8 reg, u8 data)
-{
-	int ret;
-	u8 buf[] = { reg, data };
-	struct i2c_msg msg = {
-				.addr = state->config->demod_address,
-				.flags = 0,
-				.buf = buf,
-				.len = 2
-	};
-
-	ret = i2c_transfer(state->i2c, &msg, 1);
-
-	if (ret != 1)
-		dprintk("%s: writereg error (reg == 0x%02x, data == 0x%02x, "
-			"ret == %i)\n", __func__, reg, data, ret);
-
-	return (ret != 1) ? -EREMOTEIO : 0;
-}
-
-static int si21_write(struct dvb_frontend *fe, const u8 buf[], int len)
-{
-	struct si21xx_state *state = fe->demodulator_priv;
-
-	if (len != 2)
-		return -EINVAL;
-
-	return si21_writereg(state, buf[0], buf[1]);
-}
-
-static u8 si21_readreg(struct si21xx_state *state, u8 reg)
-{
-	int ret;
-	u8 b0[] = { reg };
-	u8 b1[] = { 0 };
-	struct i2c_msg msg[] = {
-		{
-			.addr = state->config->demod_address,
-			.flags = 0,
-			.buf = b0,
-			.len = 1
-		}, {
-			.addr = state->config->demod_address,
-			.flags = I2C_M_RD,
-			.buf = b1,
-			.len = 1
-		}
-	};
-
-	ret = i2c_transfer(state->i2c, msg, 2);
-
-	if (ret != 2)
-		dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n",
-			__func__, reg, ret);
-
-	return b1[0];
-}
-
-static int si21_readregs(struct si21xx_state *state, u8 reg1, u8 *b, u8 len)
-{
-	int ret;
-	struct i2c_msg msg[] = {
-		{
-			.addr = state->config->demod_address,
-			.flags = 0,
-			.buf = &reg1,
-			.len = 1
-		}, {
-			.addr = state->config->demod_address,
-			.flags = I2C_M_RD,
-			.buf = b,
-			.len = len
-		}
-	};
-
-	ret = i2c_transfer(state->i2c, msg, 2);
-
-	if (ret != 2)
-		dprintk("%s: readreg error (ret == %i)\n", __func__, ret);
-
-	return ret == 2 ? 0 : -1;
-}
-
-static int si21xx_wait_diseqc_idle(struct si21xx_state *state, int timeout)
-{
-	unsigned long start = jiffies;
-
-	dprintk("%s\n", __func__);
-
-	while ((si21_readreg(state, LNB_CTRL_REG_1) & 0x8) == 8) {
-		if (jiffies - start > timeout) {
-			dprintk("%s: timeout!!\n", __func__);
-			return -ETIMEDOUT;
-		}
-		msleep(10);
-	};
-
-	return 0;
-}
-
-static int si21xx_set_symbolrate(struct dvb_frontend *fe, u32 srate)
-{
-	struct si21xx_state *state = fe->demodulator_priv;
-	u32 sym_rate, data_rate;
-	int i;
-	u8 sym_rate_bytes[3];
-
-	dprintk("%s : srate = %i\n", __func__ , srate);
-
-	if ((srate < 1000000) || (srate > 45000000))
-		return -EINVAL;
-
-	data_rate = srate;
-	sym_rate = 0;
-
-	for (i = 0; i < 4; ++i) {
-		sym_rate /= 100;
-		sym_rate = sym_rate + ((data_rate % 100) * 0x800000) /
-								state->fs;
-		data_rate /= 100;
-	}
-	for (i = 0; i < 3; ++i)
-		sym_rate_bytes[i] = (u8)((sym_rate >> (i * 8)) & 0xff);
-
-	si21_writeregs(state, SYM_RATE_REG_L, sym_rate_bytes, 0x03);
-
-	return 0;
-}
-
-static int si21xx_send_diseqc_msg(struct dvb_frontend *fe,
-					struct dvb_diseqc_master_cmd *m)
-{
-	struct si21xx_state *state = fe->demodulator_priv;
-	u8 lnb_status;
-	u8 LNB_CTRL_1;
-	int status;
-
-	dprintk("%s\n", __func__);
-
-	status = PASS;
-	LNB_CTRL_1 = 0;
-
-	status |= si21_readregs(state, LNB_CTRL_STATUS_REG, &lnb_status, 0x01);
-	status |= si21_readregs(state, LNB_CTRL_REG_1, &lnb_status, 0x01);
-
-	/*fill the FIFO*/
-	status |= si21_writeregs(state, LNB_FIFO_REGS_0, m->msg, m->msg_len);
-
-	LNB_CTRL_1 = (lnb_status & 0x70);
-	LNB_CTRL_1 |= m->msg_len;
-
-	LNB_CTRL_1 |= 0x80;	/* begin LNB signaling */
-
-	status |= si21_writeregs(state, LNB_CTRL_REG_1, &LNB_CTRL_1, 0x01);
-
-	return status;
-}
-
-static int si21xx_send_diseqc_burst(struct dvb_frontend *fe,
-						fe_sec_mini_cmd_t burst)
-{
-	struct si21xx_state *state = fe->demodulator_priv;
-	u8 val;
-
-	dprintk("%s\n", __func__);
-
-	if (si21xx_wait_diseqc_idle(state, 100) < 0)
-		return -ETIMEDOUT;
-
-	val = (0x80 | si21_readreg(state, 0xc1));
-	if (si21_writereg(state, LNB_CTRL_REG_1,
-			burst == SEC_MINI_A ? (val & ~0x10) : (val | 0x10)))
-		return -EREMOTEIO;
-
-	if (si21xx_wait_diseqc_idle(state, 100) < 0)
-		return -ETIMEDOUT;
-
-	if (si21_writereg(state, LNB_CTRL_REG_1, val))
-		return -EREMOTEIO;
-
-	return 0;
-}
-/*	30.06.2008 */
-static int si21xx_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
-{
-	struct si21xx_state *state = fe->demodulator_priv;
-	u8 val;
-
-	dprintk("%s\n", __func__);
-	val = (0x80 | si21_readreg(state, LNB_CTRL_REG_1));
-
-	switch (tone) {
-	case SEC_TONE_ON:
-		return si21_writereg(state, LNB_CTRL_REG_1, val | 0x20);
-
-	case SEC_TONE_OFF:
-		return si21_writereg(state, LNB_CTRL_REG_1, (val & ~0x20));
-
-	default:
-		return -EINVAL;
-	}
-}
-
-static int si21xx_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t volt)
-{
-	struct si21xx_state *state = fe->demodulator_priv;
-
-	u8 val;
-	dprintk("%s: %s\n", __func__,
-		volt == SEC_VOLTAGE_13 ? "SEC_VOLTAGE_13" :
-		volt == SEC_VOLTAGE_18 ? "SEC_VOLTAGE_18" : "??");
-
-
-	val = (0x80 | si21_readreg(state, LNB_CTRL_REG_1));
-
-	switch (volt) {
-	case SEC_VOLTAGE_18:
-		return si21_writereg(state, LNB_CTRL_REG_1, val | 0x40);
-		break;
-	case SEC_VOLTAGE_13:
-		return si21_writereg(state, LNB_CTRL_REG_1, (val & ~0x40));
-		break;
-	default:
-		return -EINVAL;
-	};
-}
-
-static int si21xx_init(struct dvb_frontend *fe)
-{
-	struct si21xx_state *state = fe->demodulator_priv;
-	int i;
-	int status = 0;
-	u8 reg1;
-	u8 val;
-	u8 reg2[2];
-
-	dprintk("%s\n", __func__);
-
-	for (i = 0; ; i += 2) {
-		reg1 = serit_sp1511lhb_inittab[i];
-		val = serit_sp1511lhb_inittab[i+1];
-		if (reg1 == 0xff && val == 0xff)
-			break;
-		si21_writeregs(state, reg1, &val, 1);
-	}
-
-	/*DVB QPSK SYSTEM MODE REG*/
-	reg1 = 0x08;
-	si21_writeregs(state, SYSTEM_MODE_REG, &reg1, 0x01);
-
-	/*transport stream config*/
-	/*
-	mode = PARALLEL;
-	sdata_form = LSB_FIRST;
-	clk_edge = FALLING_EDGE;
-	clk_mode = CLK_GAPPED_MODE;
-	strt_len = BYTE_WIDE;
-	sync_pol = ACTIVE_HIGH;
-	val_pol = ACTIVE_HIGH;
-	err_pol = ACTIVE_HIGH;
-	sclk_rate = 0x00;
-	parity = 0x00 ;
-	data_delay = 0x00;
-	clk_delay = 0x00;
-	pclk_smooth = 0x00;
-	*/
-	reg2[0] =
-		PARALLEL + (LSB_FIRST << 1)
-		+ (FALLING_EDGE << 2) + (CLK_GAPPED_MODE << 3)
-		+ (BYTE_WIDE << 4) + (ACTIVE_HIGH << 5)
-		+ (ACTIVE_HIGH << 6) + (ACTIVE_HIGH << 7);
-
-	reg2[1] = 0;
-	/*	sclk_rate + (parity << 2)
-		+ (data_delay << 3) + (clk_delay << 4)
-		+ (pclk_smooth << 5);
-	*/
-	status |= si21_writeregs(state, TS_CTRL_REG_1, reg2, 0x02);
-	if (status != 0)
-		dprintk(" %s : TS Set Error\n", __func__);
-
-	return 0;
-
-}
-
-static int si21_read_status(struct dvb_frontend *fe, fe_status_t *status)
-{
-	struct si21xx_state *state = fe->demodulator_priv;
-	u8 regs_read[2];
-	u8 reg_read;
-	u8 i;
-	u8 lock;
-	u8 signal = si21_readreg(state, ANALOG_AGC_POWER_LEVEL_REG);
-
-	si21_readregs(state, LOCK_STATUS_REG_1, regs_read, 0x02);
-	reg_read = 0;
-
-	for (i = 0; i < 7; ++i)
-		reg_read |= ((regs_read[0] >> i) & 0x01) << (6 - i);
-
-	lock = ((reg_read & 0x7f) | (regs_read[1] & 0x80));
-
-	dprintk("%s : FE_READ_STATUS : VSTATUS: 0x%02x\n", __func__, lock);
-	*status = 0;
-
-	if (signal > 10)
-		*status |= FE_HAS_SIGNAL;
-
-	if (lock & 0x2)
-		*status |= FE_HAS_CARRIER;
-
-	if (lock & 0x20)
-		*status |= FE_HAS_VITERBI;
-
-	if (lock & 0x40)
-		*status |= FE_HAS_SYNC;
-
-	if ((lock & 0x7b) == 0x7b)
-		*status |= FE_HAS_LOCK;
-
-	return 0;
-}
-
-static int si21_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
-{
-	struct si21xx_state *state = fe->demodulator_priv;
-
-	/*status = si21_readreg(state, ANALOG_AGC_POWER_LEVEL_REG,
-						(u8*)agclevel, 0x01);*/
-
-	u16 signal = (3 * si21_readreg(state, 0x27) *
-					si21_readreg(state, 0x28));
-
-	dprintk("%s : AGCPWR: 0x%02x%02x, signal=0x%04x\n", __func__,
-		si21_readreg(state, 0x27),
-		si21_readreg(state, 0x28), (int) signal);
-
-	signal  <<= 4;
-	*strength = signal;
-
-	return 0;
-}
-
-static int si21_read_ber(struct dvb_frontend *fe, u32 *ber)
-{
-	struct si21xx_state *state = fe->demodulator_priv;
-
-	dprintk("%s\n", __func__);
-
-	if (state->errmode != STATUS_BER)
-		return 0;
-
-	*ber = (si21_readreg(state, 0x1d) << 8) |
-				si21_readreg(state, 0x1e);
-
-	return 0;
-}
-
-static int si21_read_snr(struct dvb_frontend *fe, u16 *snr)
-{
-	struct si21xx_state *state = fe->demodulator_priv;
-
-	s32 xsnr = 0xffff - ((si21_readreg(state, 0x24) << 8) |
-					si21_readreg(state, 0x25));
-	xsnr = 3 * (xsnr - 0xa100);
-	*snr = (xsnr > 0xffff) ? 0xffff : (xsnr < 0) ? 0 : xsnr;
-
-	dprintk("%s\n", __func__);
-
-	return 0;
-}
-
-static int si21_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
-{
-	struct si21xx_state *state = fe->demodulator_priv;
-
-	dprintk("%s\n", __func__);
-
-	if (state->errmode != STATUS_UCBLOCKS)
-		*ucblocks = 0;
-	else
-		*ucblocks = (si21_readreg(state, 0x1d) << 8) |
-					si21_readreg(state, 0x1e);
-
-	return 0;
-}
-
-/*	initiates a channel acquisition sequence
-	using the specified symbol rate and code rate */
-static int si21xx_setacquire(struct dvb_frontend *fe, int symbrate,
-						fe_code_rate_t crate)
-{
-
-	struct si21xx_state *state = fe->demodulator_priv;
-	u8 coderates[] = {
-				0x0, 0x01, 0x02, 0x04, 0x00,
-				0x8, 0x10, 0x20, 0x00, 0x3f
-	};
-
-	u8 coderate_ptr;
-	int status;
-	u8 start_acq = 0x80;
-	u8 reg, regs[3];
-
-	dprintk("%s\n", __func__);
-
-	status = PASS;
-	coderate_ptr = coderates[crate];
-
-	si21xx_set_symbolrate(fe, symbrate);
-
-	/* write code rates to use in the Viterbi search */
-	status |= si21_writeregs(state,
-				VIT_SRCH_CTRL_REG_1,
-				&coderate_ptr, 0x01);
-
-	/* clear acq_start bit */
-	status |= si21_readregs(state, ACQ_CTRL_REG_2, &reg, 0x01);
-	reg &= ~start_acq;
-	status |= si21_writeregs(state, ACQ_CTRL_REG_2, &reg, 0x01);
-
-	/* use new Carrier Frequency Offset Estimator (QuickLock) */
-	regs[0] = 0xCB;
-	regs[1] = 0x40;
-	regs[2] = 0xCB;
-
-	status |= si21_writeregs(state,
-				TWO_DB_BNDWDTH_THRSHLD_REG,
-				&regs[0], 0x03);
-	reg = 0x56;
-	status |= si21_writeregs(state,
-				LSA_CTRL_REG_1, &reg, 1);
-	reg = 0x05;
-	status |= si21_writeregs(state,
-				BLIND_SCAN_CTRL_REG, &reg, 1);
-	/* start automatic acq */
-	status |= si21_writeregs(state,
-				ACQ_CTRL_REG_2, &start_acq, 0x01);
-
-	return status;
-}
-
-static int si21xx_set_frontend(struct dvb_frontend *fe)
-{
-	struct si21xx_state *state = fe->demodulator_priv;
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-
-	/* freq		Channel carrier frequency in KHz (i.e. 1550000 KHz)
-	 datarate	Channel symbol rate in Sps (i.e. 22500000 Sps)*/
-
-	/* in MHz */
-	unsigned char coarse_tune_freq;
-	int fine_tune_freq;
-	unsigned char sample_rate = 0;
-	/* boolean */
-	bool inband_interferer_ind;
-
-	/* INTERMEDIATE VALUES */
-	int icoarse_tune_freq; /* MHz */
-	int ifine_tune_freq; /* MHz */
-	unsigned int band_high;
-	unsigned int band_low;
-	unsigned int x1;
-	unsigned int x2;
-	int i;
-	bool inband_interferer_div2[ALLOWABLE_FS_COUNT];
-	bool inband_interferer_div4[ALLOWABLE_FS_COUNT];
-	int status;
-
-	/* allowable sample rates for ADC in MHz */
-	int afs[ALLOWABLE_FS_COUNT] = { 200, 192, 193, 194, 195,
-					196, 204, 205, 206, 207
-	};
-	/* in MHz */
-	int if_limit_high;
-	int if_limit_low;
-	int lnb_lo;
-	int lnb_uncertanity;
-
-	int rf_freq;
-	int data_rate;
-	unsigned char regs[4];
-
-	dprintk("%s : FE_SET_FRONTEND\n", __func__);
-
-	if (c->delivery_system != SYS_DVBS) {
-			dprintk("%s: unsupported delivery system selected (%d)\n",
-				__func__, c->delivery_system);
-			return -EOPNOTSUPP;
-	}
-
-	for (i = 0; i < ALLOWABLE_FS_COUNT; ++i)
-		inband_interferer_div2[i] = inband_interferer_div4[i] = false;
-
-	if_limit_high = -700000;
-	if_limit_low = -100000;
-	/* in MHz */
-	lnb_lo = 0;
-	lnb_uncertanity = 0;
-
-	rf_freq = 10 * c->frequency ;
-	data_rate = c->symbol_rate / 100;
-
-	status = PASS;
-
-	band_low = (rf_freq - lnb_lo) - ((lnb_uncertanity * 200)
-					+ (data_rate * 135)) / 200;
-
-	band_high = (rf_freq - lnb_lo) + ((lnb_uncertanity * 200)
-					+ (data_rate * 135)) / 200;
-
-
-	icoarse_tune_freq = 100000 *
-				(((rf_freq - lnb_lo) -
-					(if_limit_low + if_limit_high) / 2)
-								/ 100000);
-
-	ifine_tune_freq = (rf_freq - lnb_lo) - icoarse_tune_freq ;
-
-	for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) {
-		x1 = ((rf_freq - lnb_lo) / (afs[i] * 2500)) *
-					(afs[i] * 2500) + afs[i] * 2500;
-
-		x2 = ((rf_freq - lnb_lo) / (afs[i] * 2500)) *
-							(afs[i] * 2500);
-
-		if (((band_low < x1) && (x1 < band_high)) ||
-					((band_low < x2) && (x2 < band_high)))
-					inband_interferer_div4[i] = true;
-
-	}
-
-	for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) {
-		x1 = ((rf_freq - lnb_lo) / (afs[i] * 5000)) *
-					(afs[i] * 5000) + afs[i] * 5000;
-
-		x2 = ((rf_freq - lnb_lo) / (afs[i] * 5000)) *
-					(afs[i] * 5000);
-
-		if (((band_low < x1) && (x1 < band_high)) ||
-					((band_low < x2) && (x2 < band_high)))
-					inband_interferer_div2[i] = true;
-	}
-
-	inband_interferer_ind = true;
-	for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) {
-		if (inband_interferer_div2[i] || inband_interferer_div4[i]) {
-			inband_interferer_ind = false;
-			break;
-		}
-	}
-
-	if (inband_interferer_ind) {
-		for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) {
-			if (!inband_interferer_div2[i]) {
-				sample_rate = (u8) afs[i];
-				break;
-			}
-		}
-	} else {
-		for (i = 0; i < ALLOWABLE_FS_COUNT; ++i) {
-			if ((inband_interferer_div2[i] ||
-			     !inband_interferer_div4[i])) {
-				sample_rate = (u8) afs[i];
-				break;
-			}
-		}
-
-	}
-
-	if (sample_rate > 207 || sample_rate < 192)
-		sample_rate = 200;
-
-	fine_tune_freq = ((0x4000 * (ifine_tune_freq / 10)) /
-					((sample_rate) * 1000));
-
-	coarse_tune_freq = (u8)(icoarse_tune_freq / 100000);
-
-	regs[0] = sample_rate;
-	regs[1] = coarse_tune_freq;
-	regs[2] = fine_tune_freq & 0xFF;
-	regs[3] = fine_tune_freq >> 8 & 0xFF;
-
-	status |= si21_writeregs(state, PLL_DIVISOR_REG, &regs[0], 0x04);
-
-	state->fs = sample_rate;/*ADC MHz*/
-	si21xx_setacquire(fe, c->symbol_rate, c->fec_inner);
-
-	return 0;
-}
-
-static int si21xx_sleep(struct dvb_frontend *fe)
-{
-	struct si21xx_state *state = fe->demodulator_priv;
-	u8 regdata;
-
-	dprintk("%s\n", __func__);
-
-	si21_readregs(state, SYSTEM_MODE_REG, &regdata, 0x01);
-	regdata |= 1 << 6;
-	si21_writeregs(state, SYSTEM_MODE_REG, &regdata, 0x01);
-	state->initialised = 0;
-
-	return 0;
-}
-
-static void si21xx_release(struct dvb_frontend *fe)
-{
-	struct si21xx_state *state = fe->demodulator_priv;
-
-	dprintk("%s\n", __func__);
-
-	kfree(state);
-}
-
-static struct dvb_frontend_ops si21xx_ops = {
-	.delsys = { SYS_DVBS },
-	.info = {
-		.name			= "SL SI21XX DVB-S",
-		.frequency_min		= 950000,
-		.frequency_max		= 2150000,
-		.frequency_stepsize	= 125,	 /* kHz for QPSK frontends */
-		.frequency_tolerance	= 0,
-		.symbol_rate_min	= 1000000,
-		.symbol_rate_max	= 45000000,
-		.symbol_rate_tolerance	= 500,	/* ppm */
-		.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_FEC_AUTO
-	},
-
-	.release = si21xx_release,
-	.init = si21xx_init,
-	.sleep = si21xx_sleep,
-	.write = si21_write,
-	.read_status = si21_read_status,
-	.read_ber = si21_read_ber,
-	.read_signal_strength = si21_read_signal_strength,
-	.read_snr = si21_read_snr,
-	.read_ucblocks = si21_read_ucblocks,
-	.diseqc_send_master_cmd = si21xx_send_diseqc_msg,
-	.diseqc_send_burst = si21xx_send_diseqc_burst,
-	.set_tone = si21xx_set_tone,
-	.set_voltage = si21xx_set_voltage,
-
-	.set_frontend = si21xx_set_frontend,
-};
-
-struct dvb_frontend *si21xx_attach(const struct si21xx_config *config,
-						struct i2c_adapter *i2c)
-{
-	struct si21xx_state *state = NULL;
-	int id;
-
-	dprintk("%s\n", __func__);
-
-	/* allocate memory for the internal state */
-	state = kzalloc(sizeof(struct si21xx_state), GFP_KERNEL);
-	if (state == NULL)
-		goto error;
-
-	/* setup the state */
-	state->config = config;
-	state->i2c = i2c;
-	state->initialised = 0;
-	state->errmode = STATUS_BER;
-
-	/* check if the demod is there */
-	id = si21_readreg(state, SYSTEM_MODE_REG);
-	si21_writereg(state, SYSTEM_MODE_REG, id | 0x40); /* standby off */
-	msleep(200);
-	id = si21_readreg(state, 0x00);
-
-	/* register 0x00 contains:
-		0x34 for SI2107
-		0x24 for SI2108
-		0x14 for SI2109
-		0x04 for SI2110
-	*/
-	if (id != 0x04 && id != 0x14)
-		goto error;
-
-	/* create dvb_frontend */
-	memcpy(&state->frontend.ops, &si21xx_ops,
-					sizeof(struct dvb_frontend_ops));
-	state->frontend.demodulator_priv = state;
-	return &state->frontend;
-
-error:
-	kfree(state);
-	return NULL;
-}
-EXPORT_SYMBOL(si21xx_attach);
-
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
-
-MODULE_DESCRIPTION("SL SI21XX DVB Demodulator driver");
-MODULE_AUTHOR("Igor M. Liplianin");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/si21xx.h b/drivers/media/dvb/frontends/si21xx.h
deleted file mode 100644
index 141b5b8..0000000
--- a/drivers/media/dvb/frontends/si21xx.h
+++ /dev/null
@@ -1,37 +0,0 @@
-#ifndef SI21XX_H
-#define SI21XX_H
-
-#include <linux/dvb/frontend.h>
-#include "dvb_frontend.h"
-
-struct si21xx_config {
-	/* the demodulator's i2c address */
-	u8 demod_address;
-
-	/* minimum delay before retuning */
-	int min_delay_ms;
-};
-
-#if defined(CONFIG_DVB_SI21XX) || \
-		(defined(CONFIG_DVB_SI21XX_MODULE) && defined(MODULE))
-extern struct dvb_frontend *si21xx_attach(const struct si21xx_config *config,
-						struct i2c_adapter *i2c);
-#else
-static inline struct dvb_frontend *si21xx_attach(
-		const struct si21xx_config *config, struct i2c_adapter *i2c)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif
-
-static inline int si21xx_writeregister(struct dvb_frontend *fe, u8 reg, u8 val)
-{
-	int r = 0;
-	u8 buf[] = {reg, val};
-	if (fe->ops.write)
-		r = fe->ops.write(fe, buf, 2);
-	return r;
-}
-
-#endif
diff --git a/drivers/media/dvb/frontends/sp8870.c b/drivers/media/dvb/frontends/sp8870.c
deleted file mode 100644
index e37274c..0000000
--- a/drivers/media/dvb/frontends/sp8870.c
+++ /dev/null
@@ -1,620 +0,0 @@
-/*
-    Driver for Spase SP8870 demodulator
-
-    Copyright (C) 1999 Juergen Peitz
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the 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.
-
-*/
-/*
- * This driver needs external firmware. Please use the command
- * "<kerneldir>/Documentation/dvb/get_dvb_firmware alps_tdlb7" to
- * download/extract it, and then copy it to /usr/lib/hotplug/firmware
- * or /lib/firmware (depending on configuration of firmware hotplug).
- */
-#define SP8870_DEFAULT_FIRMWARE "dvb-fe-sp8870.fw"
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/firmware.h>
-#include <linux/delay.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-
-#include "dvb_frontend.h"
-#include "sp8870.h"
-
-
-struct sp8870_state {
-
-	struct i2c_adapter* i2c;
-
-	const struct sp8870_config* config;
-
-	struct dvb_frontend frontend;
-
-	/* demodulator private data */
-	u8 initialised:1;
-};
-
-static int debug;
-#define dprintk(args...) \
-	do { \
-		if (debug) printk(KERN_DEBUG "sp8870: " args); \
-	} while (0)
-
-/* firmware size for sp8870 */
-#define SP8870_FIRMWARE_SIZE 16382
-
-/* starting point for firmware in file 'Sc_main.mc' */
-#define SP8870_FIRMWARE_OFFSET 0x0A
-
-static int sp8870_writereg (struct sp8870_state* state, u16 reg, u16 data)
-{
-	u8 buf [] = { reg >> 8, reg & 0xff, data >> 8, data & 0xff };
-	struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 4 };
-	int err;
-
-	if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
-		dprintk ("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __func__, err, reg, data);
-		return -EREMOTEIO;
-	}
-
-	return 0;
-}
-
-static int sp8870_readreg (struct sp8870_state* state, u16 reg)
-{
-	int ret;
-	u8 b0 [] = { reg >> 8 , reg & 0xff };
-	u8 b1 [] = { 0, 0 };
-	struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 2 },
-			   { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 2 } };
-
-	ret = i2c_transfer (state->i2c, msg, 2);
-
-	if (ret != 2) {
-		dprintk("%s: readreg error (ret == %i)\n", __func__, ret);
-		return -1;
-	}
-
-	return (b1[0] << 8 | b1[1]);
-}
-
-static int sp8870_firmware_upload (struct sp8870_state* state, const struct firmware *fw)
-{
-	struct i2c_msg msg;
-	const char *fw_buf = fw->data;
-	int fw_pos;
-	u8 tx_buf[255];
-	int tx_len;
-	int err = 0;
-
-	dprintk ("%s: ...\n", __func__);
-
-	if (fw->size < SP8870_FIRMWARE_SIZE + SP8870_FIRMWARE_OFFSET)
-		return -EINVAL;
-
-	// system controller stop
-	sp8870_writereg(state, 0x0F00, 0x0000);
-
-	// instruction RAM register hiword
-	sp8870_writereg(state, 0x8F08, ((SP8870_FIRMWARE_SIZE / 2) & 0xFFFF));
-
-	// instruction RAM MWR
-	sp8870_writereg(state, 0x8F0A, ((SP8870_FIRMWARE_SIZE / 2) >> 16));
-
-	// do firmware upload
-	fw_pos = SP8870_FIRMWARE_OFFSET;
-	while (fw_pos < SP8870_FIRMWARE_SIZE + SP8870_FIRMWARE_OFFSET){
-		tx_len = (fw_pos <= SP8870_FIRMWARE_SIZE + SP8870_FIRMWARE_OFFSET - 252) ? 252 : SP8870_FIRMWARE_SIZE + SP8870_FIRMWARE_OFFSET - fw_pos;
-		// write register 0xCF0A
-		tx_buf[0] = 0xCF;
-		tx_buf[1] = 0x0A;
-		memcpy(&tx_buf[2], fw_buf + fw_pos, tx_len);
-		msg.addr = state->config->demod_address;
-		msg.flags = 0;
-		msg.buf = tx_buf;
-		msg.len = tx_len + 2;
-		if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
-			printk("%s: firmware upload failed!\n", __func__);
-			printk ("%s: i2c error (err == %i)\n", __func__, err);
-			return err;
-		}
-		fw_pos += tx_len;
-	}
-
-	dprintk ("%s: done!\n", __func__);
-	return 0;
-};
-
-static void sp8870_microcontroller_stop (struct sp8870_state* state)
-{
-	sp8870_writereg(state, 0x0F08, 0x000);
-	sp8870_writereg(state, 0x0F09, 0x000);
-
-	// microcontroller STOP
-	sp8870_writereg(state, 0x0F00, 0x000);
-}
-
-static void sp8870_microcontroller_start (struct sp8870_state* state)
-{
-	sp8870_writereg(state, 0x0F08, 0x000);
-	sp8870_writereg(state, 0x0F09, 0x000);
-
-	// microcontroller START
-	sp8870_writereg(state, 0x0F00, 0x001);
-	// not documented but if we don't read 0x0D01 out here
-	// we don't get a correct data valid signal
-	sp8870_readreg(state, 0x0D01);
-}
-
-static int sp8870_read_data_valid_signal(struct sp8870_state* state)
-{
-	return (sp8870_readreg(state, 0x0D02) > 0);
-}
-
-static int configure_reg0xc05 (struct dtv_frontend_properties *p, u16 *reg0xc05)
-{
-	int known_parameters = 1;
-
-	*reg0xc05 = 0x000;
-
-	switch (p->modulation) {
-	case QPSK:
-		break;
-	case QAM_16:
-		*reg0xc05 |= (1 << 10);
-		break;
-	case QAM_64:
-		*reg0xc05 |= (2 << 10);
-		break;
-	case QAM_AUTO:
-		known_parameters = 0;
-		break;
-	default:
-		return -EINVAL;
-	};
-
-	switch (p->hierarchy) {
-	case HIERARCHY_NONE:
-		break;
-	case HIERARCHY_1:
-		*reg0xc05 |= (1 << 7);
-		break;
-	case HIERARCHY_2:
-		*reg0xc05 |= (2 << 7);
-		break;
-	case HIERARCHY_4:
-		*reg0xc05 |= (3 << 7);
-		break;
-	case HIERARCHY_AUTO:
-		known_parameters = 0;
-		break;
-	default:
-		return -EINVAL;
-	};
-
-	switch (p->code_rate_HP) {
-	case FEC_1_2:
-		break;
-	case FEC_2_3:
-		*reg0xc05 |= (1 << 3);
-		break;
-	case FEC_3_4:
-		*reg0xc05 |= (2 << 3);
-		break;
-	case FEC_5_6:
-		*reg0xc05 |= (3 << 3);
-		break;
-	case FEC_7_8:
-		*reg0xc05 |= (4 << 3);
-		break;
-	case FEC_AUTO:
-		known_parameters = 0;
-		break;
-	default:
-		return -EINVAL;
-	};
-
-	if (known_parameters)
-		*reg0xc05 |= (2 << 1);	/* use specified parameters */
-	else
-		*reg0xc05 |= (1 << 1);	/* enable autoprobing */
-
-	return 0;
-}
-
-static int sp8870_wake_up(struct sp8870_state* state)
-{
-	// enable TS output and interface pins
-	return sp8870_writereg(state, 0xC18, 0x00D);
-}
-
-static int sp8870_set_frontend_parameters(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct sp8870_state* state = fe->demodulator_priv;
-	int  err;
-	u16 reg0xc05;
-
-	if ((err = configure_reg0xc05(p, &reg0xc05)))
-		return err;
-
-	// system controller stop
-	sp8870_microcontroller_stop(state);
-
-	// set tuner parameters
-	if (fe->ops.tuner_ops.set_params) {
-		fe->ops.tuner_ops.set_params(fe);
-		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
-	}
-
-	// sample rate correction bit [23..17]
-	sp8870_writereg(state, 0x0319, 0x000A);
-
-	// sample rate correction bit [16..0]
-	sp8870_writereg(state, 0x031A, 0x0AAB);
-
-	// integer carrier offset
-	sp8870_writereg(state, 0x0309, 0x0400);
-
-	// fractional carrier offset
-	sp8870_writereg(state, 0x030A, 0x0000);
-
-	// filter for 6/7/8 Mhz channel
-	if (p->bandwidth_hz == 6000000)
-		sp8870_writereg(state, 0x0311, 0x0002);
-	else if (p->bandwidth_hz == 7000000)
-		sp8870_writereg(state, 0x0311, 0x0001);
-	else
-		sp8870_writereg(state, 0x0311, 0x0000);
-
-	// scan order: 2k first = 0x0000, 8k first = 0x0001
-	if (p->transmission_mode == TRANSMISSION_MODE_2K)
-		sp8870_writereg(state, 0x0338, 0x0000);
-	else
-		sp8870_writereg(state, 0x0338, 0x0001);
-
-	sp8870_writereg(state, 0xc05, reg0xc05);
-
-	// read status reg in order to clear pending irqs
-	sp8870_readreg(state, 0x200);
-
-	// system controller start
-	sp8870_microcontroller_start(state);
-
-	return 0;
-}
-
-static int sp8870_init (struct dvb_frontend* fe)
-{
-	struct sp8870_state* state = fe->demodulator_priv;
-	const struct firmware *fw = NULL;
-
-	sp8870_wake_up(state);
-	if (state->initialised) return 0;
-	state->initialised = 1;
-
-	dprintk ("%s\n", __func__);
-
-
-	/* request the firmware, this will block until someone uploads it */
-	printk("sp8870: waiting for firmware upload (%s)...\n", SP8870_DEFAULT_FIRMWARE);
-	if (state->config->request_firmware(fe, &fw, SP8870_DEFAULT_FIRMWARE)) {
-		printk("sp8870: no firmware upload (timeout or file not found?)\n");
-		return -EIO;
-	}
-
-	if (sp8870_firmware_upload(state, fw)) {
-		printk("sp8870: writing firmware to device failed\n");
-		release_firmware(fw);
-		return -EIO;
-	}
-	release_firmware(fw);
-	printk("sp8870: firmware upload complete\n");
-
-	/* enable TS output and interface pins */
-	sp8870_writereg(state, 0xc18, 0x00d);
-
-	// system controller stop
-	sp8870_microcontroller_stop(state);
-
-	// ADC mode
-	sp8870_writereg(state, 0x0301, 0x0003);
-
-	// Reed Solomon parity bytes passed to output
-	sp8870_writereg(state, 0x0C13, 0x0001);
-
-	// MPEG clock is suppressed if no valid data
-	sp8870_writereg(state, 0x0C14, 0x0001);
-
-	/* bit 0x010: enable data valid signal */
-	sp8870_writereg(state, 0x0D00, 0x010);
-	sp8870_writereg(state, 0x0D01, 0x000);
-
-	return 0;
-}
-
-static int sp8870_read_status (struct dvb_frontend* fe, fe_status_t * fe_status)
-{
-	struct sp8870_state* state = fe->demodulator_priv;
-	int status;
-	int signal;
-
-	*fe_status = 0;
-
-	status = sp8870_readreg (state, 0x0200);
-	if (status < 0)
-		return -EIO;
-
-	signal = sp8870_readreg (state, 0x0303);
-	if (signal < 0)
-		return -EIO;
-
-	if (signal > 0x0F)
-		*fe_status |= FE_HAS_SIGNAL;
-	if (status & 0x08)
-		*fe_status |= FE_HAS_SYNC;
-	if (status & 0x04)
-		*fe_status |= FE_HAS_LOCK | FE_HAS_CARRIER | FE_HAS_VITERBI;
-
-	return 0;
-}
-
-static int sp8870_read_ber (struct dvb_frontend* fe, u32 * ber)
-{
-	struct sp8870_state* state = fe->demodulator_priv;
-	int ret;
-	u32 tmp;
-
-	*ber = 0;
-
-	ret = sp8870_readreg(state, 0xC08);
-	if (ret < 0)
-		return -EIO;
-
-	tmp = ret & 0x3F;
-
-	ret = sp8870_readreg(state, 0xC07);
-	if (ret < 0)
-		return -EIO;
-
-	 tmp = ret << 6;
-
-	if (tmp >= 0x3FFF0)
-		tmp = ~0;
-
-	*ber = tmp;
-
-	return 0;
-}
-
-static int sp8870_read_signal_strength(struct dvb_frontend* fe,  u16 * signal)
-{
-	struct sp8870_state* state = fe->demodulator_priv;
-	int ret;
-	u16 tmp;
-
-	*signal = 0;
-
-	ret = sp8870_readreg (state, 0x306);
-	if (ret < 0)
-		return -EIO;
-
-	tmp = ret << 8;
-
-	ret = sp8870_readreg (state, 0x303);
-	if (ret < 0)
-		return -EIO;
-
-	tmp |= ret;
-
-	if (tmp)
-		*signal = 0xFFFF - tmp;
-
-	return 0;
-}
-
-static int sp8870_read_uncorrected_blocks (struct dvb_frontend* fe, u32* ublocks)
-{
-	struct sp8870_state* state = fe->demodulator_priv;
-	int ret;
-
-	*ublocks = 0;
-
-	ret = sp8870_readreg(state, 0xC0C);
-	if (ret < 0)
-		return -EIO;
-
-	if (ret == 0xFFFF)
-		ret = ~0;
-
-	*ublocks = ret;
-
-	return 0;
-}
-
-/* number of trials to recover from lockup */
-#define MAXTRIALS 5
-/* maximum checks for data valid signal */
-#define MAXCHECKS 100
-
-/* only for debugging: counter for detected lockups */
-static int lockups;
-/* only for debugging: counter for channel switches */
-static int switches;
-
-static int sp8870_set_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct sp8870_state* state = fe->demodulator_priv;
-
-	/*
-	    The firmware of the sp8870 sometimes locks up after setting frontend parameters.
-	    We try to detect this by checking the data valid signal.
-	    If it is not set after MAXCHECKS we try to recover the lockup by setting
-	    the frontend parameters again.
-	*/
-
-	int err = 0;
-	int valid = 0;
-	int trials = 0;
-	int check_count = 0;
-
-	dprintk("%s: frequency = %i\n", __func__, p->frequency);
-
-	for (trials = 1; trials <= MAXTRIALS; trials++) {
-
-		err = sp8870_set_frontend_parameters(fe);
-		if (err)
-			return err;
-
-		for (check_count = 0; check_count < MAXCHECKS; check_count++) {
-//			valid = ((sp8870_readreg(i2c, 0x0200) & 4) == 0);
-			valid = sp8870_read_data_valid_signal(state);
-			if (valid) {
-				dprintk("%s: delay = %i usec\n",
-					__func__, check_count * 10);
-				break;
-			}
-			udelay(10);
-		}
-		if (valid)
-			break;
-	}
-
-	if (!valid) {
-		printk("%s: firmware crash!!!!!!\n", __func__);
-		return -EIO;
-	}
-
-	if (debug) {
-		if (valid) {
-			if (trials > 1) {
-				printk("%s: firmware lockup!!!\n", __func__);
-				printk("%s: recovered after %i trial(s))\n",  __func__, trials - 1);
-				lockups++;
-			}
-		}
-		switches++;
-		printk("%s: switches = %i lockups = %i\n", __func__, switches, lockups);
-	}
-
-	return 0;
-}
-
-static int sp8870_sleep(struct dvb_frontend* fe)
-{
-	struct sp8870_state* state = fe->demodulator_priv;
-
-	// tristate TS output and disable interface pins
-	return sp8870_writereg(state, 0xC18, 0x000);
-}
-
-static int sp8870_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings)
-{
-	fesettings->min_delay_ms = 350;
-	fesettings->step_size = 0;
-	fesettings->max_drift = 0;
-	return 0;
-}
-
-static int sp8870_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
-{
-	struct sp8870_state* state = fe->demodulator_priv;
-
-	if (enable) {
-		return sp8870_writereg(state, 0x206, 0x001);
-	} else {
-		return sp8870_writereg(state, 0x206, 0x000);
-	}
-}
-
-static void sp8870_release(struct dvb_frontend* fe)
-{
-	struct sp8870_state* state = fe->demodulator_priv;
-	kfree(state);
-}
-
-static struct dvb_frontend_ops sp8870_ops;
-
-struct dvb_frontend* sp8870_attach(const struct sp8870_config* config,
-				   struct i2c_adapter* i2c)
-{
-	struct sp8870_state* state = NULL;
-
-	/* allocate memory for the internal state */
-	state = kzalloc(sizeof(struct sp8870_state), GFP_KERNEL);
-	if (state == NULL) goto error;
-
-	/* setup the state */
-	state->config = config;
-	state->i2c = i2c;
-	state->initialised = 0;
-
-	/* check if the demod is there */
-	if (sp8870_readreg(state, 0x0200) < 0) goto error;
-
-	/* create dvb_frontend */
-	memcpy(&state->frontend.ops, &sp8870_ops, sizeof(struct dvb_frontend_ops));
-	state->frontend.demodulator_priv = state;
-	return &state->frontend;
-
-error:
-	kfree(state);
-	return NULL;
-}
-
-static struct dvb_frontend_ops sp8870_ops = {
-	.delsys = { SYS_DVBT },
-	.info = {
-		.name			= "Spase SP8870 DVB-T",
-		.frequency_min		= 470000000,
-		.frequency_max		= 860000000,
-		.frequency_stepsize	= 166666,
-		.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_FEC_AUTO |
-					  FE_CAN_QPSK | FE_CAN_QAM_16 |
-					  FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
-					  FE_CAN_HIERARCHY_AUTO |  FE_CAN_RECOVER
-	},
-
-	.release = sp8870_release,
-
-	.init = sp8870_init,
-	.sleep = sp8870_sleep,
-	.i2c_gate_ctrl = sp8870_i2c_gate_ctrl,
-
-	.set_frontend = sp8870_set_frontend,
-	.get_tune_settings = sp8870_get_tune_settings,
-
-	.read_status = sp8870_read_status,
-	.read_ber = sp8870_read_ber,
-	.read_signal_strength = sp8870_read_signal_strength,
-	.read_ucblocks = sp8870_read_uncorrected_blocks,
-};
-
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
-
-MODULE_DESCRIPTION("Spase SP8870 DVB-T Demodulator driver");
-MODULE_AUTHOR("Juergen Peitz");
-MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(sp8870_attach);
diff --git a/drivers/media/dvb/frontends/sp8870.h b/drivers/media/dvb/frontends/sp8870.h
deleted file mode 100644
index a764a79..0000000
--- a/drivers/media/dvb/frontends/sp8870.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
-    Driver for Spase SP8870 demodulator
-
-    Copyright (C) 1999 Juergen Peitz
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the 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 SP8870_H
-#define SP8870_H
-
-#include <linux/dvb/frontend.h>
-#include <linux/firmware.h>
-
-struct sp8870_config
-{
-	/* the demodulator's i2c address */
-	u8 demod_address;
-
-	/* request firmware for device */
-	int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name);
-};
-
-#if defined(CONFIG_DVB_SP8870) || (defined(CONFIG_DVB_SP8870_MODULE) && defined(MODULE))
-extern struct dvb_frontend* sp8870_attach(const struct sp8870_config* config,
-					  struct i2c_adapter* i2c);
-#else
-static inline struct dvb_frontend* sp8870_attach(const struct sp8870_config* config,
-					  struct i2c_adapter* i2c)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif // CONFIG_DVB_SP8870
-
-#endif // SP8870_H
diff --git a/drivers/media/dvb/frontends/sp887x.c b/drivers/media/dvb/frontends/sp887x.c
deleted file mode 100644
index f4096cc..0000000
--- a/drivers/media/dvb/frontends/sp887x.c
+++ /dev/null
@@ -1,629 +0,0 @@
-/*
-   Driver for the Spase sp887x demodulator
-*/
-
-/*
- * This driver needs external firmware. Please use the command
- * "<kerneldir>/Documentation/dvb/get_dvb_firmware sp887x" to
- * download/extract it, and then copy it to /usr/lib/hotplug/firmware
- * or /lib/firmware (depending on configuration of firmware hotplug).
- */
-#define SP887X_DEFAULT_FIRMWARE "dvb-fe-sp887x.fw"
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/firmware.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-
-#include "dvb_frontend.h"
-#include "sp887x.h"
-
-
-struct sp887x_state {
-	struct i2c_adapter* i2c;
-	const struct sp887x_config* config;
-	struct dvb_frontend frontend;
-
-	/* demodulator private data */
-	u8 initialised:1;
-};
-
-static int debug;
-#define dprintk(args...) \
-	do { \
-		if (debug) printk(KERN_DEBUG "sp887x: " args); \
-	} while (0)
-
-static int i2c_writebytes (struct sp887x_state* state, u8 *buf, u8 len)
-{
-	struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = len };
-	int err;
-
-	if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
-		printk ("%s: i2c write error (addr %02x, err == %i)\n",
-			__func__, state->config->demod_address, err);
-		return -EREMOTEIO;
-	}
-
-	return 0;
-}
-
-static int sp887x_writereg (struct sp887x_state* state, u16 reg, u16 data)
-{
-	u8 b0 [] = { reg >> 8 , reg & 0xff, data >> 8, data & 0xff };
-	struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 4 };
-	int ret;
-
-	if ((ret = i2c_transfer(state->i2c, &msg, 1)) != 1) {
-		/**
-		 *  in case of soft reset we ignore ACK errors...
-		 */
-		if (!(reg == 0xf1a && data == 0x000 &&
-			(ret == -EREMOTEIO || ret == -EFAULT)))
-		{
-			printk("%s: writereg error "
-			       "(reg %03x, data %03x, ret == %i)\n",
-			       __func__, reg & 0xffff, data & 0xffff, ret);
-			return ret;
-		}
-	}
-
-	return 0;
-}
-
-static int sp887x_readreg (struct sp887x_state* state, u16 reg)
-{
-	u8 b0 [] = { reg >> 8 , reg & 0xff };
-	u8 b1 [2];
-	int ret;
-	struct i2c_msg msg[] = {{ .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 2 },
-			 { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 2 }};
-
-	if ((ret = i2c_transfer(state->i2c, msg, 2)) != 2) {
-		printk("%s: readreg error (ret == %i)\n", __func__, ret);
-		return -1;
-	}
-
-	return (((b1[0] << 8) | b1[1]) & 0xfff);
-}
-
-static void sp887x_microcontroller_stop (struct sp887x_state* state)
-{
-	dprintk("%s\n", __func__);
-	sp887x_writereg(state, 0xf08, 0x000);
-	sp887x_writereg(state, 0xf09, 0x000);
-
-	/* microcontroller STOP */
-	sp887x_writereg(state, 0xf00, 0x000);
-}
-
-static void sp887x_microcontroller_start (struct sp887x_state* state)
-{
-	dprintk("%s\n", __func__);
-	sp887x_writereg(state, 0xf08, 0x000);
-	sp887x_writereg(state, 0xf09, 0x000);
-
-	/* microcontroller START */
-	sp887x_writereg(state, 0xf00, 0x001);
-}
-
-static void sp887x_setup_agc (struct sp887x_state* state)
-{
-	/* setup AGC parameters */
-	dprintk("%s\n", __func__);
-	sp887x_writereg(state, 0x33c, 0x054);
-	sp887x_writereg(state, 0x33b, 0x04c);
-	sp887x_writereg(state, 0x328, 0x000);
-	sp887x_writereg(state, 0x327, 0x005);
-	sp887x_writereg(state, 0x326, 0x001);
-	sp887x_writereg(state, 0x325, 0x001);
-	sp887x_writereg(state, 0x324, 0x001);
-	sp887x_writereg(state, 0x318, 0x050);
-	sp887x_writereg(state, 0x317, 0x3fe);
-	sp887x_writereg(state, 0x316, 0x001);
-	sp887x_writereg(state, 0x313, 0x005);
-	sp887x_writereg(state, 0x312, 0x002);
-	sp887x_writereg(state, 0x306, 0x000);
-	sp887x_writereg(state, 0x303, 0x000);
-}
-
-#define BLOCKSIZE 30
-#define FW_SIZE 0x4000
-/**
- *  load firmware and setup MPEG interface...
- */
-static int sp887x_initial_setup (struct dvb_frontend* fe, const struct firmware *fw)
-{
-	struct sp887x_state* state = fe->demodulator_priv;
-	u8 buf [BLOCKSIZE+2];
-	int i;
-	int fw_size = fw->size;
-	const unsigned char *mem = fw->data;
-
-	dprintk("%s\n", __func__);
-
-	/* ignore the first 10 bytes, then we expect 0x4000 bytes of firmware */
-	if (fw_size < FW_SIZE+10)
-		return -ENODEV;
-
-	mem = fw->data + 10;
-
-	/* soft reset */
-	sp887x_writereg(state, 0xf1a, 0x000);
-
-	sp887x_microcontroller_stop (state);
-
-	printk ("%s: firmware upload... ", __func__);
-
-	/* setup write pointer to -1 (end of memory) */
-	/* bit 0x8000 in address is set to enable 13bit mode */
-	sp887x_writereg(state, 0x8f08, 0x1fff);
-
-	/* dummy write (wrap around to start of memory) */
-	sp887x_writereg(state, 0x8f0a, 0x0000);
-
-	for (i = 0; i < FW_SIZE; i += BLOCKSIZE) {
-		int c = BLOCKSIZE;
-		int err;
-
-		if (i+c > FW_SIZE)
-			c = FW_SIZE - i;
-
-		/* bit 0x8000 in address is set to enable 13bit mode */
-		/* bit 0x4000 enables multibyte read/write transfers */
-		/* write register is 0xf0a */
-		buf[0] = 0xcf;
-		buf[1] = 0x0a;
-
-		memcpy(&buf[2], mem + i, c);
-
-		if ((err = i2c_writebytes (state, buf, c+2)) < 0) {
-			printk ("failed.\n");
-			printk ("%s: i2c error (err == %i)\n", __func__, err);
-			return err;
-		}
-	}
-
-	/* don't write RS bytes between packets */
-	sp887x_writereg(state, 0xc13, 0x001);
-
-	/* suppress clock if (!data_valid) */
-	sp887x_writereg(state, 0xc14, 0x000);
-
-	/* setup MPEG interface... */
-	sp887x_writereg(state, 0xc1a, 0x872);
-	sp887x_writereg(state, 0xc1b, 0x001);
-	sp887x_writereg(state, 0xc1c, 0x000); /* parallel mode (serial mode == 1) */
-	sp887x_writereg(state, 0xc1a, 0x871);
-
-	/* ADC mode, 2 for MT8872, 3 for SP8870/SP8871 */
-	sp887x_writereg(state, 0x301, 0x002);
-
-	sp887x_setup_agc(state);
-
-	/* bit 0x010: enable data valid signal */
-	sp887x_writereg(state, 0xd00, 0x010);
-	sp887x_writereg(state, 0x0d1, 0x000);
-	return 0;
-};
-
-static int configure_reg0xc05(struct dtv_frontend_properties *p, u16 *reg0xc05)
-{
-	int known_parameters = 1;
-
-	*reg0xc05 = 0x000;
-
-	switch (p->modulation) {
-	case QPSK:
-		break;
-	case QAM_16:
-		*reg0xc05 |= (1 << 10);
-		break;
-	case QAM_64:
-		*reg0xc05 |= (2 << 10);
-		break;
-	case QAM_AUTO:
-		known_parameters = 0;
-		break;
-	default:
-		return -EINVAL;
-	};
-
-	switch (p->hierarchy) {
-	case HIERARCHY_NONE:
-		break;
-	case HIERARCHY_1:
-		*reg0xc05 |= (1 << 7);
-		break;
-	case HIERARCHY_2:
-		*reg0xc05 |= (2 << 7);
-		break;
-	case HIERARCHY_4:
-		*reg0xc05 |= (3 << 7);
-		break;
-	case HIERARCHY_AUTO:
-		known_parameters = 0;
-		break;
-	default:
-		return -EINVAL;
-	};
-
-	switch (p->code_rate_HP) {
-	case FEC_1_2:
-		break;
-	case FEC_2_3:
-		*reg0xc05 |= (1 << 3);
-		break;
-	case FEC_3_4:
-		*reg0xc05 |= (2 << 3);
-		break;
-	case FEC_5_6:
-		*reg0xc05 |= (3 << 3);
-		break;
-	case FEC_7_8:
-		*reg0xc05 |= (4 << 3);
-		break;
-	case FEC_AUTO:
-		known_parameters = 0;
-		break;
-	default:
-		return -EINVAL;
-	};
-
-	if (known_parameters)
-		*reg0xc05 |= (2 << 1);	/* use specified parameters */
-	else
-		*reg0xc05 |= (1 << 1);	/* enable autoprobing */
-
-	return 0;
-}
-
-/**
- *  estimates division of two 24bit numbers,
- *  derived from the ves1820/stv0299 driver code
- */
-static void divide (int n, int d, int *quotient_i, int *quotient_f)
-{
-	unsigned int q, r;
-
-	r = (n % d) << 8;
-	q = (r / d);
-
-	if (quotient_i)
-		*quotient_i = q;
-
-	if (quotient_f) {
-		r = (r % d) << 8;
-		q = (q << 8) | (r / d);
-		r = (r % d) << 8;
-		*quotient_f = (q << 8) | (r / d);
-	}
-}
-
-static void sp887x_correct_offsets (struct sp887x_state* state,
-				    struct dtv_frontend_properties *p,
-				    int actual_freq)
-{
-	static const u32 srate_correction [] = { 1879617, 4544878, 8098561 };
-	int bw_index;
-	int freq_offset = actual_freq - p->frequency;
-	int sysclock = 61003; //[kHz]
-	int ifreq = 36000000;
-	int freq;
-	int frequency_shift;
-
-	switch (p->bandwidth_hz) {
-	default:
-	case 8000000:
-		bw_index = 0;
-		break;
-	case 7000000:
-		bw_index = 1;
-		break;
-	case 6000000:
-		bw_index = 2;
-		break;
-	}
-
-	if (p->inversion == INVERSION_ON)
-		freq = ifreq - freq_offset;
-	else
-		freq = ifreq + freq_offset;
-
-	divide(freq / 333, sysclock, NULL, &frequency_shift);
-
-	if (p->inversion == INVERSION_ON)
-		frequency_shift = -frequency_shift;
-
-	/* sample rate correction */
-	sp887x_writereg(state, 0x319, srate_correction[bw_index] >> 12);
-	sp887x_writereg(state, 0x31a, srate_correction[bw_index] & 0xfff);
-
-	/* carrier offset correction */
-	sp887x_writereg(state, 0x309, frequency_shift >> 12);
-	sp887x_writereg(state, 0x30a, frequency_shift & 0xfff);
-}
-
-static int sp887x_setup_frontend_parameters(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct sp887x_state* state = fe->demodulator_priv;
-	unsigned actual_freq;
-	int err;
-	u16 val, reg0xc05;
-
-	if (p->bandwidth_hz != 8000000 &&
-	    p->bandwidth_hz != 7000000 &&
-	    p->bandwidth_hz != 6000000)
-		return -EINVAL;
-
-	if ((err = configure_reg0xc05(p, &reg0xc05)))
-		return err;
-
-	sp887x_microcontroller_stop(state);
-
-	/* setup the PLL */
-	if (fe->ops.tuner_ops.set_params) {
-		fe->ops.tuner_ops.set_params(fe);
-		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
-	}
-	if (fe->ops.tuner_ops.get_frequency) {
-		fe->ops.tuner_ops.get_frequency(fe, &actual_freq);
-		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
-	} else {
-		actual_freq = p->frequency;
-	}
-
-	/* read status reg in order to clear <pending irqs */
-	sp887x_readreg(state, 0x200);
-
-	sp887x_correct_offsets(state, p, actual_freq);
-
-	/* filter for 6/7/8 Mhz channel */
-	if (p->bandwidth_hz == 6000000)
-		val = 2;
-	else if (p->bandwidth_hz == 7000000)
-		val = 1;
-	else
-		val = 0;
-
-	sp887x_writereg(state, 0x311, val);
-
-	/* scan order: 2k first = 0, 8k first = 1 */
-	if (p->transmission_mode == TRANSMISSION_MODE_2K)
-		sp887x_writereg(state, 0x338, 0x000);
-	else
-		sp887x_writereg(state, 0x338, 0x001);
-
-	sp887x_writereg(state, 0xc05, reg0xc05);
-
-	if (p->bandwidth_hz == 6000000)
-		val = 2 << 3;
-	else if (p->bandwidth_hz == 7000000)
-		val = 3 << 3;
-	else
-		val = 0 << 3;
-
-	/* enable OFDM and SAW bits as lock indicators in sync register 0xf17,
-	 * optimize algorithm for given bandwidth...
-	 */
-	sp887x_writereg(state, 0xf14, 0x160 | val);
-	sp887x_writereg(state, 0xf15, 0x000);
-
-	sp887x_microcontroller_start(state);
-	return 0;
-}
-
-static int sp887x_read_status(struct dvb_frontend* fe, fe_status_t* status)
-{
-	struct sp887x_state* state = fe->demodulator_priv;
-	u16 snr12 = sp887x_readreg(state, 0xf16);
-	u16 sync0x200 = sp887x_readreg(state, 0x200);
-	u16 sync0xf17 = sp887x_readreg(state, 0xf17);
-
-	*status = 0;
-
-	if (snr12 > 0x00f)
-		*status |= FE_HAS_SIGNAL;
-
-	//if (sync0x200 & 0x004)
-	//	*status |= FE_HAS_SYNC | FE_HAS_CARRIER;
-
-	//if (sync0x200 & 0x008)
-	//	*status |= FE_HAS_VITERBI;
-
-	if ((sync0xf17 & 0x00f) == 0x002) {
-		*status |= FE_HAS_LOCK;
-		*status |= FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_CARRIER;
-	}
-
-	if (sync0x200 & 0x001) {	/* tuner adjustment requested...*/
-		int steps = (sync0x200 >> 4) & 0x00f;
-		if (steps & 0x008)
-			steps = -steps;
-		dprintk("sp887x: implement tuner adjustment (%+i steps)!!\n",
-		       steps);
-	}
-
-	return 0;
-}
-
-static int sp887x_read_ber(struct dvb_frontend* fe, u32* ber)
-{
-	struct sp887x_state* state = fe->demodulator_priv;
-
-	*ber = (sp887x_readreg(state, 0xc08) & 0x3f) |
-	       (sp887x_readreg(state, 0xc07) << 6);
-	sp887x_writereg(state, 0xc08, 0x000);
-	sp887x_writereg(state, 0xc07, 0x000);
-	if (*ber >= 0x3fff0)
-		*ber = ~0;
-
-	return 0;
-}
-
-static int sp887x_read_signal_strength(struct dvb_frontend* fe, u16* strength)
-{
-	struct sp887x_state* state = fe->demodulator_priv;
-
-	u16 snr12 = sp887x_readreg(state, 0xf16);
-	u32 signal = 3 * (snr12 << 4);
-	*strength = (signal < 0xffff) ? signal : 0xffff;
-
-	return 0;
-}
-
-static int sp887x_read_snr(struct dvb_frontend* fe, u16* snr)
-{
-	struct sp887x_state* state = fe->demodulator_priv;
-
-	u16 snr12 = sp887x_readreg(state, 0xf16);
-	*snr = (snr12 << 4) | (snr12 >> 8);
-
-	return 0;
-}
-
-static int sp887x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
-{
-	struct sp887x_state* state = fe->demodulator_priv;
-
-	*ucblocks = sp887x_readreg(state, 0xc0c);
-	if (*ucblocks == 0xfff)
-		*ucblocks = ~0;
-
-	return 0;
-}
-
-static int sp887x_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
-{
-	struct sp887x_state* state = fe->demodulator_priv;
-
-	if (enable) {
-		return sp887x_writereg(state, 0x206, 0x001);
-	} else {
-		return sp887x_writereg(state, 0x206, 0x000);
-	}
-}
-
-static int sp887x_sleep(struct dvb_frontend* fe)
-{
-	struct sp887x_state* state = fe->demodulator_priv;
-
-	/* tristate TS output and disable interface pins */
-	sp887x_writereg(state, 0xc18, 0x000);
-
-	return 0;
-}
-
-static int sp887x_init(struct dvb_frontend* fe)
-{
-	struct sp887x_state* state = fe->demodulator_priv;
-	const struct firmware *fw = NULL;
-	int ret;
-
-	if (!state->initialised) {
-		/* request the firmware, this will block until someone uploads it */
-		printk("sp887x: waiting for firmware upload (%s)...\n", SP887X_DEFAULT_FIRMWARE);
-		ret = state->config->request_firmware(fe, &fw, SP887X_DEFAULT_FIRMWARE);
-		if (ret) {
-			printk("sp887x: no firmware upload (timeout or file not found?)\n");
-			return ret;
-		}
-
-		ret = sp887x_initial_setup(fe, fw);
-		release_firmware(fw);
-		if (ret) {
-			printk("sp887x: writing firmware to device failed\n");
-			return ret;
-		}
-		printk("sp887x: firmware upload complete\n");
-		state->initialised = 1;
-	}
-
-	/* enable TS output and interface pins */
-	sp887x_writereg(state, 0xc18, 0x00d);
-
-	return 0;
-}
-
-static int sp887x_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings)
-{
-	fesettings->min_delay_ms = 350;
-	fesettings->step_size = 166666*2;
-	fesettings->max_drift = (166666*2)+1;
-	return 0;
-}
-
-static void sp887x_release(struct dvb_frontend* fe)
-{
-	struct sp887x_state* state = fe->demodulator_priv;
-	kfree(state);
-}
-
-static struct dvb_frontend_ops sp887x_ops;
-
-struct dvb_frontend* sp887x_attach(const struct sp887x_config* config,
-				   struct i2c_adapter* i2c)
-{
-	struct sp887x_state* state = NULL;
-
-	/* allocate memory for the internal state */
-	state = kzalloc(sizeof(struct sp887x_state), GFP_KERNEL);
-	if (state == NULL) goto error;
-
-	/* setup the state */
-	state->config = config;
-	state->i2c = i2c;
-	state->initialised = 0;
-
-	/* check if the demod is there */
-	if (sp887x_readreg(state, 0x0200) < 0) goto error;
-
-	/* create dvb_frontend */
-	memcpy(&state->frontend.ops, &sp887x_ops, sizeof(struct dvb_frontend_ops));
-	state->frontend.demodulator_priv = state;
-	return &state->frontend;
-
-error:
-	kfree(state);
-	return NULL;
-}
-
-static struct dvb_frontend_ops sp887x_ops = {
-	.delsys = { SYS_DVBT },
-	.info = {
-		.name = "Spase SP887x DVB-T",
-		.frequency_min =  50500000,
-		.frequency_max = 858000000,
-		.frequency_stepsize = 166666,
-		.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_FEC_AUTO |
-			FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 |
-			FE_CAN_RECOVER
-	},
-
-	.release = sp887x_release,
-
-	.init = sp887x_init,
-	.sleep = sp887x_sleep,
-	.i2c_gate_ctrl = sp887x_i2c_gate_ctrl,
-
-	.set_frontend = sp887x_setup_frontend_parameters,
-	.get_tune_settings = sp887x_get_tune_settings,
-
-	.read_status = sp887x_read_status,
-	.read_ber = sp887x_read_ber,
-	.read_signal_strength = sp887x_read_signal_strength,
-	.read_snr = sp887x_read_snr,
-	.read_ucblocks = sp887x_read_ucblocks,
-};
-
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
-
-MODULE_DESCRIPTION("Spase sp887x DVB-T demodulator driver");
-MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(sp887x_attach);
diff --git a/drivers/media/dvb/frontends/sp887x.h b/drivers/media/dvb/frontends/sp887x.h
deleted file mode 100644
index 04eff6e..0000000
--- a/drivers/media/dvb/frontends/sp887x.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
-   Driver for the Spase sp887x demodulator
-*/
-
-#ifndef SP887X_H
-#define SP887X_H
-
-#include <linux/dvb/frontend.h>
-#include <linux/firmware.h>
-
-struct sp887x_config
-{
-	/* the demodulator's i2c address */
-	u8 demod_address;
-
-	/* request firmware for device */
-	int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name);
-};
-
-#if defined(CONFIG_DVB_SP887X) || (defined(CONFIG_DVB_SP887X_MODULE) && defined(MODULE))
-extern struct dvb_frontend* sp887x_attach(const struct sp887x_config* config,
-					  struct i2c_adapter* i2c);
-#else
-static inline struct dvb_frontend* sp887x_attach(const struct sp887x_config* config,
-					  struct i2c_adapter* i2c)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif // CONFIG_DVB_SP887X
-
-#endif // SP887X_H
diff --git a/drivers/media/dvb/frontends/stb0899_algo.c b/drivers/media/dvb/frontends/stb0899_algo.c
deleted file mode 100644
index 117a569..0000000
--- a/drivers/media/dvb/frontends/stb0899_algo.c
+++ /dev/null
@@ -1,1525 +0,0 @@
-/*
-	STB0899 Multistandard Frontend driver
-	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
-
-	Copyright (C) ST Microelectronics
-
-	This program is free software; you can redistribute it and/or modify
-	it under the terms of the 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 "stb0899_drv.h"
-#include "stb0899_priv.h"
-#include "stb0899_reg.h"
-
-static inline u32 stb0899_do_div(u64 n, u32 d)
-{
-	/* wrap do_div() for ease of use */
-
-	do_div(n, d);
-	return n;
-}
-
-#if 0
-/* These functions are currently unused */
-/*
- * stb0899_calc_srate
- * Compute symbol rate
- */
-static u32 stb0899_calc_srate(u32 master_clk, u8 *sfr)
-{
-	u64 tmp;
-
-	/* srate = (SFR * master_clk) >> 20 */
-
-	/* sfr is of size 20 bit, stored with an offset of 4 bit */
-	tmp = (((u32)sfr[0]) << 16) | (((u32)sfr[1]) << 8) | sfr[2];
-	tmp &= ~0xf;
-	tmp *= master_clk;
-	tmp >>= 24;
-
-	return tmp;
-}
-
-/*
- * stb0899_get_srate
- * Get the current symbol rate
- */
-static u32 stb0899_get_srate(struct stb0899_state *state)
-{
-	struct stb0899_internal *internal = &state->internal;
-	u8 sfr[3];
-
-	stb0899_read_regs(state, STB0899_SFRH, sfr, 3);
-
-	return stb0899_calc_srate(internal->master_clk, sfr);
-}
-#endif
-
-/*
- * stb0899_set_srate
- * Set symbol frequency
- * MasterClock: master clock frequency (hz)
- * SymbolRate: symbol rate (bauds)
- * return symbol frequency
- */
-static u32 stb0899_set_srate(struct stb0899_state *state, u32 master_clk, u32 srate)
-{
-	u32 tmp;
-	u8 sfr[3];
-
-	dprintk(state->verbose, FE_DEBUG, 1, "-->");
-	/*
-	 * in order to have the maximum precision, the symbol rate entered into
-	 * the chip is computed as the closest value of the "true value".
-	 * In this purpose, the symbol rate value is rounded (1 is added on the bit
-	 * below the LSB )
-	 *
-	 * srate = (SFR * master_clk) >> 20
-	 *      <=>
-	 *   SFR = srate << 20 / master_clk
-	 *
-	 * rounded:
-	 *   SFR = (srate << 21 + master_clk) / (2 * master_clk)
-	 *
-	 * stored as 20 bit number with an offset of 4 bit:
-	 *   sfr = SFR << 4;
-	 */
-
-	tmp = stb0899_do_div((((u64)srate) << 21) + master_clk, 2 * master_clk);
-	tmp <<= 4;
-
-	sfr[0] = tmp >> 16;
-	sfr[1] = tmp >>  8;
-	sfr[2] = tmp;
-
-	stb0899_write_regs(state, STB0899_SFRH, sfr, 3);
-
-	return srate;
-}
-
-/*
- * stb0899_calc_derot_time
- * Compute the amount of time needed by the derotator to lock
- * SymbolRate: Symbol rate
- * return: derotator time constant (ms)
- */
-static long stb0899_calc_derot_time(long srate)
-{
-	if (srate > 0)
-		return (100000 / (srate / 1000));
-	else
-		return 0;
-}
-
-/*
- * stb0899_carr_width
- * Compute the width of the carrier
- * return: width of carrier (kHz or Mhz)
- */
-long stb0899_carr_width(struct stb0899_state *state)
-{
-	struct stb0899_internal *internal = &state->internal;
-
-	return (internal->srate + (internal->srate * internal->rolloff) / 100);
-}
-
-/*
- * stb0899_first_subrange
- * Compute the first subrange of the search
- */
-static void stb0899_first_subrange(struct stb0899_state *state)
-{
-	struct stb0899_internal *internal	= &state->internal;
-	struct stb0899_params *params		= &state->params;
-	struct stb0899_config *config		=  state->config;
-
-	int range = 0;
-	u32 bandwidth = 0;
-
-	if (config->tuner_get_bandwidth) {
-		stb0899_i2c_gate_ctrl(&state->frontend, 1);
-		config->tuner_get_bandwidth(&state->frontend, &bandwidth);
-		stb0899_i2c_gate_ctrl(&state->frontend, 0);
-		range = bandwidth - stb0899_carr_width(state) / 2;
-	}
-
-	if (range > 0)
-		internal->sub_range = min(internal->srch_range, range);
-	else
-		internal->sub_range = 0;
-
-	internal->freq = params->freq;
-	internal->tuner_offst = 0L;
-	internal->sub_dir = 1;
-}
-
-/*
- * stb0899_check_tmg
- * check for timing lock
- * internal.Ttiming: time to wait for loop lock
- */
-static enum stb0899_status stb0899_check_tmg(struct stb0899_state *state)
-{
-	struct stb0899_internal *internal = &state->internal;
-	int lock;
-	u8 reg;
-	s8 timing;
-
-	msleep(internal->t_derot);
-
-	stb0899_write_reg(state, STB0899_RTF, 0xf2);
-	reg = stb0899_read_reg(state, STB0899_TLIR);
-	lock = STB0899_GETFIELD(TLIR_TMG_LOCK_IND, reg);
-	timing = stb0899_read_reg(state, STB0899_RTF);
-
-	if (lock >= 42) {
-		if ((lock > 48) && (abs(timing) >= 110)) {
-			internal->status = ANALOGCARRIER;
-			dprintk(state->verbose, FE_DEBUG, 1, "-->ANALOG Carrier !");
-		} else {
-			internal->status = TIMINGOK;
-			dprintk(state->verbose, FE_DEBUG, 1, "------->TIMING OK !");
-		}
-	} else {
-		internal->status = NOTIMING;
-		dprintk(state->verbose, FE_DEBUG, 1, "-->NO TIMING !");
-	}
-	return internal->status;
-}
-
-/*
- * stb0899_search_tmg
- * perform a fs/2 zig-zag to find timing
- */
-static enum stb0899_status stb0899_search_tmg(struct stb0899_state *state)
-{
-	struct stb0899_internal *internal = &state->internal;
-	struct stb0899_params *params = &state->params;
-
-	short int derot_step, derot_freq = 0, derot_limit, next_loop = 3;
-	int index = 0;
-	u8 cfr[2];
-
-	internal->status = NOTIMING;
-
-	/* timing loop computation & symbol rate optimisation	*/
-	derot_limit = (internal->sub_range / 2L) / internal->mclk;
-	derot_step = (params->srate / 2L) / internal->mclk;
-
-	while ((stb0899_check_tmg(state) != TIMINGOK) && next_loop) {
-		index++;
-		derot_freq += index * internal->direction * derot_step;	/* next derot zig zag position	*/
-
-		if (abs(derot_freq) > derot_limit)
-			next_loop--;
-
-		if (next_loop) {
-			STB0899_SETFIELD_VAL(CFRM, cfr[0], MSB(state->config->inversion * derot_freq));
-			STB0899_SETFIELD_VAL(CFRL, cfr[1], LSB(state->config->inversion * derot_freq));
-			stb0899_write_regs(state, STB0899_CFRM, cfr, 2); /* derotator frequency		*/
-		}
-		internal->direction = -internal->direction;	/* Change zigzag direction		*/
-	}
-
-	if (internal->status == TIMINGOK) {
-		stb0899_read_regs(state, STB0899_CFRM, cfr, 2); /* get derotator frequency		*/
-		internal->derot_freq = state->config->inversion * MAKEWORD16(cfr[0], cfr[1]);
-		dprintk(state->verbose, FE_DEBUG, 1, "------->TIMING OK ! Derot Freq = %d", internal->derot_freq);
-	}
-
-	return internal->status;
-}
-
-/*
- * stb0899_check_carrier
- * Check for carrier found
- */
-static enum stb0899_status stb0899_check_carrier(struct stb0899_state *state)
-{
-	struct stb0899_internal *internal = &state->internal;
-	u8 reg;
-
-	msleep(internal->t_derot); /* wait for derotator ok	*/
-
-	reg = stb0899_read_reg(state, STB0899_CFD);
-	STB0899_SETFIELD_VAL(CFD_ON, reg, 1);
-	stb0899_write_reg(state, STB0899_CFD, reg);
-
-	reg = stb0899_read_reg(state, STB0899_DSTATUS);
-	dprintk(state->verbose, FE_DEBUG, 1, "--------------------> STB0899_DSTATUS=[0x%02x]", reg);
-	if (STB0899_GETFIELD(CARRIER_FOUND, reg)) {
-		internal->status = CARRIEROK;
-		dprintk(state->verbose, FE_DEBUG, 1, "-------------> CARRIEROK !");
-	} else {
-		internal->status = NOCARRIER;
-		dprintk(state->verbose, FE_DEBUG, 1, "-------------> NOCARRIER !");
-	}
-
-	return internal->status;
-}
-
-/*
- * stb0899_search_carrier
- * Search for a QPSK carrier with the derotator
- */
-static enum stb0899_status stb0899_search_carrier(struct stb0899_state *state)
-{
-	struct stb0899_internal *internal = &state->internal;
-
-	short int derot_freq = 0, last_derot_freq = 0, derot_limit, next_loop = 3;
-	int index = 0;
-	u8 cfr[2];
-	u8 reg;
-
-	internal->status = NOCARRIER;
-	derot_limit = (internal->sub_range / 2L) / internal->mclk;
-	derot_freq = internal->derot_freq;
-
-	reg = stb0899_read_reg(state, STB0899_CFD);
-	STB0899_SETFIELD_VAL(CFD_ON, reg, 1);
-	stb0899_write_reg(state, STB0899_CFD, reg);
-
-	do {
-		dprintk(state->verbose, FE_DEBUG, 1, "Derot Freq=%d, mclk=%d", derot_freq, internal->mclk);
-		if (stb0899_check_carrier(state) == NOCARRIER) {
-			index++;
-			last_derot_freq = derot_freq;
-			derot_freq += index * internal->direction * internal->derot_step; /* next zig zag derotator position */
-
-			if(abs(derot_freq) > derot_limit)
-				next_loop--;
-
-			if (next_loop) {
-				reg = stb0899_read_reg(state, STB0899_CFD);
-				STB0899_SETFIELD_VAL(CFD_ON, reg, 1);
-				stb0899_write_reg(state, STB0899_CFD, reg);
-
-				STB0899_SETFIELD_VAL(CFRM, cfr[0], MSB(state->config->inversion * derot_freq));
-				STB0899_SETFIELD_VAL(CFRL, cfr[1], LSB(state->config->inversion * derot_freq));
-				stb0899_write_regs(state, STB0899_CFRM, cfr, 2); /* derotator frequency	*/
-			}
-		}
-
-		internal->direction = -internal->direction; /* Change zigzag direction */
-	} while ((internal->status != CARRIEROK) && next_loop);
-
-	if (internal->status == CARRIEROK) {
-		stb0899_read_regs(state, STB0899_CFRM, cfr, 2); /* get derotator frequency */
-		internal->derot_freq = state->config->inversion * MAKEWORD16(cfr[0], cfr[1]);
-		dprintk(state->verbose, FE_DEBUG, 1, "----> CARRIER OK !, Derot Freq=%d", internal->derot_freq);
-	} else {
-		internal->derot_freq = last_derot_freq;
-	}
-
-	return internal->status;
-}
-
-/*
- * stb0899_check_data
- * Check for data found
- */
-static enum stb0899_status stb0899_check_data(struct stb0899_state *state)
-{
-	struct stb0899_internal *internal = &state->internal;
-	struct stb0899_params *params = &state->params;
-
-	int lock = 0, index = 0, dataTime = 500, loop;
-	u8 reg;
-
-	internal->status = NODATA;
-
-	/* RESET FEC	*/
-	reg = stb0899_read_reg(state, STB0899_TSTRES);
-	STB0899_SETFIELD_VAL(FRESACS, reg, 1);
-	stb0899_write_reg(state, STB0899_TSTRES, reg);
-	msleep(1);
-	reg = stb0899_read_reg(state, STB0899_TSTRES);
-	STB0899_SETFIELD_VAL(FRESACS, reg, 0);
-	stb0899_write_reg(state, STB0899_TSTRES, reg);
-
-	if (params->srate <= 2000000)
-		dataTime = 2000;
-	else if (params->srate <= 5000000)
-		dataTime = 1500;
-	else if (params->srate <= 15000000)
-		dataTime = 1000;
-	else
-		dataTime = 500;
-
-	/* clear previous failed END_LOOPVIT */
-	stb0899_read_reg(state, STB0899_VSTATUS);
-
-	stb0899_write_reg(state, STB0899_DSTATUS2, 0x00); /* force search loop	*/
-	while (1) {
-		/* WARNING! VIT LOCKED has to be tested before VIT_END_LOOOP	*/
-		reg = stb0899_read_reg(state, STB0899_VSTATUS);
-		lock = STB0899_GETFIELD(VSTATUS_LOCKEDVIT, reg);
-		loop = STB0899_GETFIELD(VSTATUS_END_LOOPVIT, reg);
-
-		if (lock || loop || (index > dataTime))
-			break;
-		index++;
-	}
-
-	if (lock) {	/* DATA LOCK indicator	*/
-		internal->status = DATAOK;
-		dprintk(state->verbose, FE_DEBUG, 1, "-----------------> DATA OK !");
-	}
-
-	return internal->status;
-}
-
-/*
- * stb0899_search_data
- * Search for a QPSK carrier with the derotator
- */
-static enum stb0899_status stb0899_search_data(struct stb0899_state *state)
-{
-	short int derot_freq, derot_step, derot_limit, next_loop = 3;
-	u8 cfr[2];
-	u8 reg;
-	int index = 1;
-
-	struct stb0899_internal *internal = &state->internal;
-	struct stb0899_params *params = &state->params;
-
-	derot_step = (params->srate / 4L) / internal->mclk;
-	derot_limit = (internal->sub_range / 2L) / internal->mclk;
-	derot_freq = internal->derot_freq;
-
-	do {
-		if ((internal->status != CARRIEROK) || (stb0899_check_data(state) != DATAOK)) {
-
-			derot_freq += index * internal->direction * derot_step;	/* next zig zag derotator position */
-			if (abs(derot_freq) > derot_limit)
-				next_loop--;
-
-			if (next_loop) {
-				dprintk(state->verbose, FE_DEBUG, 1, "Derot freq=%d, mclk=%d", derot_freq, internal->mclk);
-				reg = stb0899_read_reg(state, STB0899_CFD);
-				STB0899_SETFIELD_VAL(CFD_ON, reg, 1);
-				stb0899_write_reg(state, STB0899_CFD, reg);
-
-				STB0899_SETFIELD_VAL(CFRM, cfr[0], MSB(state->config->inversion * derot_freq));
-				STB0899_SETFIELD_VAL(CFRL, cfr[1], LSB(state->config->inversion * derot_freq));
-				stb0899_write_regs(state, STB0899_CFRM, cfr, 2); /* derotator frequency	*/
-
-				stb0899_check_carrier(state);
-				index++;
-			}
-		}
-		internal->direction = -internal->direction; /* change zig zag direction */
-	} while ((internal->status != DATAOK) && next_loop);
-
-	if (internal->status == DATAOK) {
-		stb0899_read_regs(state, STB0899_CFRM, cfr, 2); /* get derotator frequency */
-		internal->derot_freq = state->config->inversion * MAKEWORD16(cfr[0], cfr[1]);
-		dprintk(state->verbose, FE_DEBUG, 1, "------> DATAOK ! Derot Freq=%d", internal->derot_freq);
-	}
-
-	return internal->status;
-}
-
-/*
- * stb0899_check_range
- * check if the found frequency is in the correct range
- */
-static enum stb0899_status stb0899_check_range(struct stb0899_state *state)
-{
-	struct stb0899_internal *internal = &state->internal;
-	struct stb0899_params *params = &state->params;
-
-	int range_offst, tp_freq;
-
-	range_offst = internal->srch_range / 2000;
-	tp_freq = internal->freq + (internal->derot_freq * internal->mclk) / 1000;
-
-	if ((tp_freq >= params->freq - range_offst) && (tp_freq <= params->freq + range_offst)) {
-		internal->status = RANGEOK;
-		dprintk(state->verbose, FE_DEBUG, 1, "----> RANGEOK !");
-	} else {
-		internal->status = OUTOFRANGE;
-		dprintk(state->verbose, FE_DEBUG, 1, "----> OUT OF RANGE !");
-	}
-
-	return internal->status;
-}
-
-/*
- * NextSubRange
- * Compute the next subrange of the search
- */
-static void next_sub_range(struct stb0899_state *state)
-{
-	struct stb0899_internal *internal = &state->internal;
-	struct stb0899_params *params = &state->params;
-
-	long old_sub_range;
-
-	if (internal->sub_dir > 0) {
-		old_sub_range = internal->sub_range;
-		internal->sub_range = min((internal->srch_range / 2) -
-					  (internal->tuner_offst + internal->sub_range / 2),
-					   internal->sub_range);
-
-		if (internal->sub_range < 0)
-			internal->sub_range = 0;
-
-		internal->tuner_offst += (old_sub_range + internal->sub_range) / 2;
-	}
-
-	internal->freq = params->freq + (internal->sub_dir * internal->tuner_offst) / 1000;
-	internal->sub_dir = -internal->sub_dir;
-}
-
-/*
- * stb0899_dvbs_algo
- * Search for a signal, timing, carrier and data for a
- * given frequency in a given range
- */
-enum stb0899_status stb0899_dvbs_algo(struct stb0899_state *state)
-{
-	struct stb0899_params *params		= &state->params;
-	struct stb0899_internal *internal	= &state->internal;
-	struct stb0899_config *config		= state->config;
-
-	u8 bclc, reg;
-	u8 cfr[2];
-	u8 eq_const[10];
-	s32 clnI = 3;
-	u32 bandwidth = 0;
-
-	/* BETA values rated @ 99MHz	*/
-	s32 betaTab[5][4] = {
-	       /*  5   10   20   30MBps */
-		{ 37,  34,  32,  31 }, /* QPSK 1/2	*/
-		{ 37,  35,  33,  31 }, /* QPSK 2/3	*/
-		{ 37,  35,  33,  31 }, /* QPSK 3/4	*/
-		{ 37,  36,  33,	 32 }, /* QPSK 5/6	*/
-		{ 37,  36,  33,	 32 }  /* QPSK 7/8	*/
-	};
-
-	internal->direction = 1;
-
-	stb0899_set_srate(state, internal->master_clk, params->srate);
-	/* Carrier loop optimization versus symbol rate for acquisition*/
-	if (params->srate <= 5000000) {
-		stb0899_write_reg(state, STB0899_ACLC, 0x89);
-		bclc = stb0899_read_reg(state, STB0899_BCLC);
-		STB0899_SETFIELD_VAL(BETA, bclc, 0x1c);
-		stb0899_write_reg(state, STB0899_BCLC, bclc);
-		clnI = 0;
-	} else if (params->srate <= 15000000) {
-		stb0899_write_reg(state, STB0899_ACLC, 0xc9);
-		bclc = stb0899_read_reg(state, STB0899_BCLC);
-		STB0899_SETFIELD_VAL(BETA, bclc, 0x22);
-		stb0899_write_reg(state, STB0899_BCLC, bclc);
-		clnI = 1;
-	} else if(params->srate <= 25000000) {
-		stb0899_write_reg(state, STB0899_ACLC, 0x89);
-		bclc = stb0899_read_reg(state, STB0899_BCLC);
-		STB0899_SETFIELD_VAL(BETA, bclc, 0x27);
-		stb0899_write_reg(state, STB0899_BCLC, bclc);
-		clnI = 2;
-	} else {
-		stb0899_write_reg(state, STB0899_ACLC, 0xc8);
-		bclc = stb0899_read_reg(state, STB0899_BCLC);
-		STB0899_SETFIELD_VAL(BETA, bclc, 0x29);
-		stb0899_write_reg(state, STB0899_BCLC, bclc);
-		clnI = 3;
-	}
-
-	dprintk(state->verbose, FE_DEBUG, 1, "Set the timing loop to acquisition");
-	/* Set the timing loop to acquisition	*/
-	stb0899_write_reg(state, STB0899_RTC, 0x46);
-	stb0899_write_reg(state, STB0899_CFD, 0xee);
-
-	/* !! WARNING !!
-	 * Do not read any status variables while acquisition,
-	 * If any needed, read before the acquisition starts
-	 * querying status while acquiring causes the
-	 * acquisition to go bad and hence no locks.
-	 */
-	dprintk(state->verbose, FE_DEBUG, 1, "Derot Percent=%d Srate=%d mclk=%d",
-		internal->derot_percent, params->srate, internal->mclk);
-
-	/* Initial calculations	*/
-	internal->derot_step = internal->derot_percent * (params->srate / 1000L) / internal->mclk; /* DerotStep/1000 * Fsymbol	*/
-	internal->t_derot = stb0899_calc_derot_time(params->srate);
-	internal->t_data = 500;
-
-	dprintk(state->verbose, FE_DEBUG, 1, "RESET stream merger");
-	/* RESET Stream merger	*/
-	reg = stb0899_read_reg(state, STB0899_TSTRES);
-	STB0899_SETFIELD_VAL(FRESRS, reg, 1);
-	stb0899_write_reg(state, STB0899_TSTRES, reg);
-
-	/*
-	 * Set KDIVIDER to an intermediate value between
-	 * 1/2 and 7/8 for acquisition
-	 */
-	reg = stb0899_read_reg(state, STB0899_DEMAPVIT);
-	STB0899_SETFIELD_VAL(DEMAPVIT_KDIVIDER, reg, 60);
-	stb0899_write_reg(state, STB0899_DEMAPVIT, reg);
-
-	stb0899_write_reg(state, STB0899_EQON, 0x01); /* Equalizer OFF while acquiring */
-	stb0899_write_reg(state, STB0899_VITSYNC, 0x19);
-
-	stb0899_first_subrange(state);
-	do {
-		/* Initialisations */
-		cfr[0] = cfr[1] = 0;
-		stb0899_write_regs(state, STB0899_CFRM, cfr, 2); /* RESET derotator frequency	*/
-
-		stb0899_write_reg(state, STB0899_RTF, 0);
-		reg = stb0899_read_reg(state, STB0899_CFD);
-		STB0899_SETFIELD_VAL(CFD_ON, reg, 1);
-		stb0899_write_reg(state, STB0899_CFD, reg);
-
-		internal->derot_freq = 0;
-		internal->status = NOAGC1;
-
-		/* enable tuner I/O */
-		stb0899_i2c_gate_ctrl(&state->frontend, 1);
-
-		/* Move tuner to frequency */
-		dprintk(state->verbose, FE_DEBUG, 1, "Tuner set frequency");
-		if (state->config->tuner_set_frequency)
-			state->config->tuner_set_frequency(&state->frontend, internal->freq);
-
-		if (state->config->tuner_get_frequency)
-			state->config->tuner_get_frequency(&state->frontend, &internal->freq);
-
-		msleep(internal->t_agc1 + internal->t_agc2 + internal->t_derot); /* AGC1, AGC2 and timing loop	*/
-		dprintk(state->verbose, FE_DEBUG, 1, "current derot freq=%d", internal->derot_freq);
-		internal->status = AGC1OK;
-
-		/* There is signal in the band	*/
-		if (config->tuner_get_bandwidth)
-			config->tuner_get_bandwidth(&state->frontend, &bandwidth);
-
-		/* disable tuner I/O */
-		stb0899_i2c_gate_ctrl(&state->frontend, 0);
-
-		if (params->srate <= bandwidth / 2)
-			stb0899_search_tmg(state); /* For low rates (SCPC)	*/
-		else
-			stb0899_check_tmg(state); /* For high rates (MCPC)	*/
-
-		if (internal->status == TIMINGOK) {
-			dprintk(state->verbose, FE_DEBUG, 1,
-				"TIMING OK ! Derot freq=%d, mclk=%d",
-				internal->derot_freq, internal->mclk);
-
-			if (stb0899_search_carrier(state) == CARRIEROK) {	/* Search for carrier	*/
-				dprintk(state->verbose, FE_DEBUG, 1,
-					"CARRIER OK ! Derot freq=%d, mclk=%d",
-					internal->derot_freq, internal->mclk);
-
-				if (stb0899_search_data(state) == DATAOK) {	/* Check for data	*/
-					dprintk(state->verbose, FE_DEBUG, 1,
-						"DATA OK ! Derot freq=%d, mclk=%d",
-						internal->derot_freq, internal->mclk);
-
-					if (stb0899_check_range(state) == RANGEOK) {
-						dprintk(state->verbose, FE_DEBUG, 1,
-							"RANGE OK ! derot freq=%d, mclk=%d",
-							internal->derot_freq, internal->mclk);
-
-						internal->freq = params->freq + ((internal->derot_freq * internal->mclk) / 1000);
-						reg = stb0899_read_reg(state, STB0899_PLPARM);
-						internal->fecrate = STB0899_GETFIELD(VITCURPUN, reg);
-						dprintk(state->verbose, FE_DEBUG, 1,
-							"freq=%d, internal resultant freq=%d",
-							params->freq, internal->freq);
-
-						dprintk(state->verbose, FE_DEBUG, 1,
-							"internal puncture rate=%d",
-							internal->fecrate);
-					}
-				}
-			}
-		}
-		if (internal->status != RANGEOK)
-			next_sub_range(state);
-
-	} while (internal->sub_range && internal->status != RANGEOK);
-
-	/* Set the timing loop to tracking	*/
-	stb0899_write_reg(state, STB0899_RTC, 0x33);
-	stb0899_write_reg(state, STB0899_CFD, 0xf7);
-	/* if locked and range ok, set Kdiv	*/
-	if (internal->status == RANGEOK) {
-		dprintk(state->verbose, FE_DEBUG, 1, "Locked & Range OK !");
-		stb0899_write_reg(state, STB0899_EQON, 0x41);		/* Equalizer OFF while acquiring	*/
-		stb0899_write_reg(state, STB0899_VITSYNC, 0x39);	/* SN to b'11 for acquisition		*/
-
-		/*
-		 * Carrier loop optimization versus
-		 * symbol Rate/Puncture Rate for Tracking
-		 */
-		reg = stb0899_read_reg(state, STB0899_BCLC);
-		switch (internal->fecrate) {
-		case STB0899_FEC_1_2:		/* 13	*/
-			stb0899_write_reg(state, STB0899_DEMAPVIT, 0x1a);
-			STB0899_SETFIELD_VAL(BETA, reg, betaTab[0][clnI]);
-			stb0899_write_reg(state, STB0899_BCLC, reg);
-			break;
-		case STB0899_FEC_2_3:		/* 18	*/
-			stb0899_write_reg(state, STB0899_DEMAPVIT, 44);
-			STB0899_SETFIELD_VAL(BETA, reg, betaTab[1][clnI]);
-			stb0899_write_reg(state, STB0899_BCLC, reg);
-			break;
-		case STB0899_FEC_3_4:		/* 21	*/
-			stb0899_write_reg(state, STB0899_DEMAPVIT, 60);
-			STB0899_SETFIELD_VAL(BETA, reg, betaTab[2][clnI]);
-			stb0899_write_reg(state, STB0899_BCLC, reg);
-			break;
-		case STB0899_FEC_5_6:		/* 24	*/
-			stb0899_write_reg(state, STB0899_DEMAPVIT, 75);
-			STB0899_SETFIELD_VAL(BETA, reg, betaTab[3][clnI]);
-			stb0899_write_reg(state, STB0899_BCLC, reg);
-			break;
-		case STB0899_FEC_6_7:		/* 25	*/
-			stb0899_write_reg(state, STB0899_DEMAPVIT, 88);
-			stb0899_write_reg(state, STB0899_ACLC, 0x88);
-			stb0899_write_reg(state, STB0899_BCLC, 0x9a);
-			break;
-		case STB0899_FEC_7_8:		/* 26	*/
-			stb0899_write_reg(state, STB0899_DEMAPVIT, 94);
-			STB0899_SETFIELD_VAL(BETA, reg, betaTab[4][clnI]);
-			stb0899_write_reg(state, STB0899_BCLC, reg);
-			break;
-		default:
-			dprintk(state->verbose, FE_DEBUG, 1, "Unsupported Puncture Rate");
-			break;
-		}
-		/* release stream merger RESET	*/
-		reg = stb0899_read_reg(state, STB0899_TSTRES);
-		STB0899_SETFIELD_VAL(FRESRS, reg, 0);
-		stb0899_write_reg(state, STB0899_TSTRES, reg);
-
-		/* disable carrier detector	*/
-		reg = stb0899_read_reg(state, STB0899_CFD);
-		STB0899_SETFIELD_VAL(CFD_ON, reg, 0);
-		stb0899_write_reg(state, STB0899_CFD, reg);
-
-		stb0899_read_regs(state, STB0899_EQUAI1, eq_const, 10);
-	}
-
-	return internal->status;
-}
-
-/*
- * stb0899_dvbs2_config_uwp
- * Configure UWP state machine
- */
-static void stb0899_dvbs2_config_uwp(struct stb0899_state *state)
-{
-	struct stb0899_internal *internal = &state->internal;
-	struct stb0899_config *config = state->config;
-	u32 uwp1, uwp2, uwp3, reg;
-
-	uwp1 = STB0899_READ_S2REG(STB0899_S2DEMOD, UWP_CNTRL1);
-	uwp2 = STB0899_READ_S2REG(STB0899_S2DEMOD, UWP_CNTRL2);
-	uwp3 = STB0899_READ_S2REG(STB0899_S2DEMOD, UWP_CNTRL3);
-
-	STB0899_SETFIELD_VAL(UWP_ESN0_AVE, uwp1, config->esno_ave);
-	STB0899_SETFIELD_VAL(UWP_ESN0_QUANT, uwp1, config->esno_quant);
-	STB0899_SETFIELD_VAL(UWP_TH_SOF, uwp1, config->uwp_threshold_sof);
-
-	STB0899_SETFIELD_VAL(FE_COARSE_TRK, uwp2, internal->av_frame_coarse);
-	STB0899_SETFIELD_VAL(FE_FINE_TRK, uwp2, internal->av_frame_fine);
-	STB0899_SETFIELD_VAL(UWP_MISS_TH, uwp2, config->miss_threshold);
-
-	STB0899_SETFIELD_VAL(UWP_TH_ACQ, uwp3, config->uwp_threshold_acq);
-	STB0899_SETFIELD_VAL(UWP_TH_TRACK, uwp3, config->uwp_threshold_track);
-
-	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_UWP_CNTRL1, STB0899_OFF0_UWP_CNTRL1, uwp1);
-	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_UWP_CNTRL2, STB0899_OFF0_UWP_CNTRL2, uwp2);
-	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_UWP_CNTRL3, STB0899_OFF0_UWP_CNTRL3, uwp3);
-
-	reg = STB0899_READ_S2REG(STB0899_S2DEMOD, SOF_SRCH_TO);
-	STB0899_SETFIELD_VAL(SOF_SEARCH_TIMEOUT, reg, config->sof_search_timeout);
-	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_SOF_SRCH_TO, STB0899_OFF0_SOF_SRCH_TO, reg);
-}
-
-/*
- * stb0899_dvbs2_config_csm_auto
- * Set CSM to AUTO mode
- */
-static void stb0899_dvbs2_config_csm_auto(struct stb0899_state *state)
-{
-	u32 reg;
-
-	reg = STB0899_READ_S2REG(STB0899_S2DEMOD, CSM_CNTRL1);
-	STB0899_SETFIELD_VAL(CSM_AUTO_PARAM, reg, 1);
-	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CSM_CNTRL1, STB0899_OFF0_CSM_CNTRL1, reg);
-}
-
-static long Log2Int(int number)
-{
-	int i;
-
-	i = 0;
-	while ((1 << i) <= abs(number))
-		i++;
-
-	if (number == 0)
-		i = 1;
-
-	return i - 1;
-}
-
-/*
- * stb0899_dvbs2_calc_srate
- * compute BTR_NOM_FREQ for the symbol rate
- */
-static u32 stb0899_dvbs2_calc_srate(struct stb0899_state *state)
-{
-	struct stb0899_internal *internal	= &state->internal;
-	struct stb0899_config *config		= state->config;
-
-	u32 dec_ratio, dec_rate, decim, remain, intval, btr_nom_freq;
-	u32 master_clk, srate;
-
-	dec_ratio = (internal->master_clk * 2) / (5 * internal->srate);
-	dec_ratio = (dec_ratio == 0) ? 1 : dec_ratio;
-	dec_rate = Log2Int(dec_ratio);
-	decim = 1 << dec_rate;
-	master_clk = internal->master_clk / 1000;
-	srate = internal->srate / 1000;
-
-	if (decim <= 4) {
-		intval = (decim * (1 << (config->btr_nco_bits - 1))) / master_clk;
-		remain = (decim * (1 << (config->btr_nco_bits - 1))) % master_clk;
-	} else {
-		intval = (1 << (config->btr_nco_bits - 1)) / (master_clk / 100) * decim / 100;
-		remain = (decim * (1 << (config->btr_nco_bits - 1))) % master_clk;
-	}
-	btr_nom_freq = (intval * srate) + ((remain * srate) / master_clk);
-
-	return btr_nom_freq;
-}
-
-/*
- * stb0899_dvbs2_calc_dev
- * compute the correction to be applied to symbol rate
- */
-static u32 stb0899_dvbs2_calc_dev(struct stb0899_state *state)
-{
-	struct stb0899_internal *internal = &state->internal;
-	u32 dec_ratio, correction, master_clk, srate;
-
-	dec_ratio = (internal->master_clk * 2) / (5 * internal->srate);
-	dec_ratio = (dec_ratio == 0) ? 1 : dec_ratio;
-
-	master_clk = internal->master_clk / 1000;	/* for integer Caculation*/
-	srate = internal->srate / 1000;	/* for integer Caculation*/
-	correction = (512 * master_clk) / (2 * dec_ratio * srate);
-
-	return	correction;
-}
-
-/*
- * stb0899_dvbs2_set_srate
- * Set DVBS2 symbol rate
- */
-static void stb0899_dvbs2_set_srate(struct stb0899_state *state)
-{
-	struct stb0899_internal *internal = &state->internal;
-
-	u32 dec_ratio, dec_rate, win_sel, decim, f_sym, btr_nom_freq;
-	u32 correction, freq_adj, band_lim, decim_cntrl, reg;
-	u8 anti_alias;
-
-	/*set decimation to 1*/
-	dec_ratio = (internal->master_clk * 2) / (5 * internal->srate);
-	dec_ratio = (dec_ratio == 0) ? 1 : dec_ratio;
-	dec_rate = Log2Int(dec_ratio);
-
-	win_sel = 0;
-	if (dec_rate >= 5)
-		win_sel = dec_rate - 4;
-
-	decim = (1 << dec_rate);
-	/* (FSamp/Fsymbol *100) for integer Caculation */
-	f_sym = internal->master_clk / ((decim * internal->srate) / 1000);
-
-	if (f_sym <= 2250)	/* don't band limit signal going into btr block*/
-		band_lim = 1;
-	else
-		band_lim = 0;	/* band limit signal going into btr block*/
-
-	decim_cntrl = ((win_sel << 3) & 0x18) + ((band_lim << 5) & 0x20) + (dec_rate & 0x7);
-	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_DECIM_CNTRL, STB0899_OFF0_DECIM_CNTRL, decim_cntrl);
-
-	if (f_sym <= 3450)
-		anti_alias = 0;
-	else if (f_sym <= 4250)
-		anti_alias = 1;
-	else
-		anti_alias = 2;
-
-	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_ANTI_ALIAS_SEL, STB0899_OFF0_ANTI_ALIAS_SEL, anti_alias);
-	btr_nom_freq = stb0899_dvbs2_calc_srate(state);
-	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_BTR_NOM_FREQ, STB0899_OFF0_BTR_NOM_FREQ, btr_nom_freq);
-
-	correction = stb0899_dvbs2_calc_dev(state);
-	reg = STB0899_READ_S2REG(STB0899_S2DEMOD, BTR_CNTRL);
-	STB0899_SETFIELD_VAL(BTR_FREQ_CORR, reg, correction);
-	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_BTR_CNTRL, STB0899_OFF0_BTR_CNTRL, reg);
-
-	/* scale UWP+CSM frequency to sample rate*/
-	freq_adj =  internal->srate / (internal->master_clk / 4096);
-	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_FREQ_ADJ_SCALE, STB0899_OFF0_FREQ_ADJ_SCALE, freq_adj);
-}
-
-/*
- * stb0899_dvbs2_set_btr_loopbw
- * set bit timing loop bandwidth as a percentage of the symbol rate
- */
-static void stb0899_dvbs2_set_btr_loopbw(struct stb0899_state *state)
-{
-	struct stb0899_internal *internal	= &state->internal;
-	struct stb0899_config *config		= state->config;
-
-	u32 sym_peak = 23, zeta = 707, loopbw_percent = 60;
-	s32 dec_ratio, dec_rate, k_btr1_rshft, k_btr1, k_btr0_rshft;
-	s32 k_btr0, k_btr2_rshft, k_direct_shift, k_indirect_shift;
-	u32 decim, K, wn, k_direct, k_indirect;
-	u32 reg;
-
-	dec_ratio = (internal->master_clk * 2) / (5 * internal->srate);
-	dec_ratio = (dec_ratio == 0) ? 1 : dec_ratio;
-	dec_rate = Log2Int(dec_ratio);
-	decim = (1 << dec_rate);
-
-	sym_peak *= 576000;
-	K = (1 << config->btr_nco_bits) / (internal->master_clk / 1000);
-	K *= (internal->srate / 1000000) * decim; /*k=k 10^-8*/
-
-	if (K != 0) {
-		K = sym_peak / K;
-		wn = (4 * zeta * zeta) + 1000000;
-		wn = (2 * (loopbw_percent * 1000) * 40 * zeta) /wn;  /*wn =wn 10^-8*/
-
-		k_indirect = (wn * wn) / K;
-		k_indirect = k_indirect;	  /*kindirect = kindirect 10^-6*/
-		k_direct   = (2 * wn * zeta) / K;	/*kDirect = kDirect 10^-2*/
-		k_direct  *= 100;
-
-		k_direct_shift = Log2Int(k_direct) - Log2Int(10000) - 2;
-		k_btr1_rshft = (-1 * k_direct_shift) + config->btr_gain_shift_offset;
-		k_btr1 = k_direct / (1 << k_direct_shift);
-		k_btr1 /= 10000;
-
-		k_indirect_shift = Log2Int(k_indirect + 15) - 20 /*- 2*/;
-		k_btr0_rshft = (-1 * k_indirect_shift) + config->btr_gain_shift_offset;
-		k_btr0 = k_indirect * (1 << (-k_indirect_shift));
-		k_btr0 /= 1000000;
-
-		k_btr2_rshft = 0;
-		if (k_btr0_rshft > 15) {
-			k_btr2_rshft = k_btr0_rshft - 15;
-			k_btr0_rshft = 15;
-		}
-		reg = STB0899_READ_S2REG(STB0899_S2DEMOD, BTR_LOOP_GAIN);
-		STB0899_SETFIELD_VAL(KBTR0_RSHFT, reg, k_btr0_rshft);
-		STB0899_SETFIELD_VAL(KBTR0, reg, k_btr0);
-		STB0899_SETFIELD_VAL(KBTR1_RSHFT, reg, k_btr1_rshft);
-		STB0899_SETFIELD_VAL(KBTR1, reg, k_btr1);
-		STB0899_SETFIELD_VAL(KBTR2_RSHFT, reg, k_btr2_rshft);
-		stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_BTR_LOOP_GAIN, STB0899_OFF0_BTR_LOOP_GAIN, reg);
-	} else
-		stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_BTR_LOOP_GAIN, STB0899_OFF0_BTR_LOOP_GAIN, 0xc4c4f);
-}
-
-/*
- * stb0899_dvbs2_set_carr_freq
- * set nominal frequency for carrier search
- */
-static void stb0899_dvbs2_set_carr_freq(struct stb0899_state *state, s32 carr_freq, u32 master_clk)
-{
-	struct stb0899_config *config = state->config;
-	s32 crl_nom_freq;
-	u32 reg;
-
-	crl_nom_freq = (1 << config->crl_nco_bits) / master_clk;
-	crl_nom_freq *= carr_freq;
-	reg = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_NOM_FREQ);
-	STB0899_SETFIELD_VAL(CRL_NOM_FREQ, reg, crl_nom_freq);
-	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CRL_NOM_FREQ, STB0899_OFF0_CRL_NOM_FREQ, reg);
-}
-
-/*
- * stb0899_dvbs2_init_calc
- * Initialize DVBS2 UWP, CSM, carrier and timing loops
- */
-static void stb0899_dvbs2_init_calc(struct stb0899_state *state)
-{
-	struct stb0899_internal *internal = &state->internal;
-	s32 steps, step_size;
-	u32 range, reg;
-
-	/* config uwp and csm */
-	stb0899_dvbs2_config_uwp(state);
-	stb0899_dvbs2_config_csm_auto(state);
-
-	/* initialize BTR	*/
-	stb0899_dvbs2_set_srate(state);
-	stb0899_dvbs2_set_btr_loopbw(state);
-
-	if (internal->srate / 1000000 >= 15)
-		step_size = (1 << 17) / 5;
-	else if (internal->srate / 1000000 >= 10)
-		step_size = (1 << 17) / 7;
-	else if (internal->srate / 1000000 >= 5)
-		step_size = (1 << 17) / 10;
-	else
-		step_size = (1 << 17) / 4;
-
-	range = internal->srch_range / 1000000;
-	steps = (10 * range * (1 << 17)) / (step_size * (internal->srate / 1000000));
-	steps = (steps + 6) / 10;
-	steps = (steps == 0) ? 1 : steps;
-	if (steps % 2 == 0)
-		stb0899_dvbs2_set_carr_freq(state, internal->center_freq -
-					   (internal->step_size * (internal->srate / 20000000)),
-					   (internal->master_clk) / 1000000);
-	else
-		stb0899_dvbs2_set_carr_freq(state, internal->center_freq, (internal->master_clk) / 1000000);
-
-	/*Set Carrier Search params (zigzag, num steps and freq step size*/
-	reg = STB0899_READ_S2REG(STB0899_S2DEMOD, ACQ_CNTRL2);
-	STB0899_SETFIELD_VAL(ZIGZAG, reg, 1);
-	STB0899_SETFIELD_VAL(NUM_STEPS, reg, steps);
-	STB0899_SETFIELD_VAL(FREQ_STEPSIZE, reg, step_size);
-	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_ACQ_CNTRL2, STB0899_OFF0_ACQ_CNTRL2, reg);
-}
-
-/*
- * stb0899_dvbs2_btr_init
- * initialize the timing loop
- */
-static void stb0899_dvbs2_btr_init(struct stb0899_state *state)
-{
-	u32 reg;
-
-	/* set enable BTR loopback	*/
-	reg = STB0899_READ_S2REG(STB0899_S2DEMOD, BTR_CNTRL);
-	STB0899_SETFIELD_VAL(INTRP_PHS_SENSE, reg, 1);
-	STB0899_SETFIELD_VAL(BTR_ERR_ENA, reg, 1);
-	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_BTR_CNTRL, STB0899_OFF0_BTR_CNTRL, reg);
-
-	/* fix btr freq accum at 0	*/
-	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_BTR_FREQ_INIT, STB0899_OFF0_BTR_FREQ_INIT, 0x10000000);
-	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_BTR_FREQ_INIT, STB0899_OFF0_BTR_FREQ_INIT, 0x00000000);
-
-	/* fix btr freq accum at 0	*/
-	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_BTR_PHS_INIT, STB0899_OFF0_BTR_PHS_INIT, 0x10000000);
-	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_BTR_PHS_INIT, STB0899_OFF0_BTR_PHS_INIT, 0x00000000);
-}
-
-/*
- * stb0899_dvbs2_reacquire
- * trigger a DVB-S2 acquisition
- */
-static void stb0899_dvbs2_reacquire(struct stb0899_state *state)
-{
-	u32 reg = 0;
-
-	/* demod soft reset	*/
-	STB0899_SETFIELD_VAL(DVBS2_RESET, reg, 1);
-	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_RESET_CNTRL, STB0899_OFF0_RESET_CNTRL, reg);
-
-	/*Reset Timing Loop	*/
-	stb0899_dvbs2_btr_init(state);
-
-	/* reset Carrier loop	*/
-	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CRL_FREQ_INIT, STB0899_OFF0_CRL_FREQ_INIT, (1 << 30));
-	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CRL_FREQ_INIT, STB0899_OFF0_CRL_FREQ_INIT, 0);
-	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CRL_LOOP_GAIN, STB0899_OFF0_CRL_LOOP_GAIN, 0);
-	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CRL_PHS_INIT, STB0899_OFF0_CRL_PHS_INIT, (1 << 30));
-	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CRL_PHS_INIT, STB0899_OFF0_CRL_PHS_INIT, 0);
-
-	/*release demod soft reset	*/
-	reg = 0;
-	STB0899_SETFIELD_VAL(DVBS2_RESET, reg, 0);
-	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_RESET_CNTRL, STB0899_OFF0_RESET_CNTRL, reg);
-
-	/* start acquisition process	*/
-	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_ACQUIRE_TRIG, STB0899_OFF0_ACQUIRE_TRIG, 1);
-	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_LOCK_LOST, STB0899_OFF0_LOCK_LOST, 0);
-
-	/* equalizer Init	*/
-	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_EQUALIZER_INIT, STB0899_OFF0_EQUALIZER_INIT, 1);
-
-	/*Start equilizer	*/
-	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_EQUALIZER_INIT, STB0899_OFF0_EQUALIZER_INIT, 0);
-
-	reg = STB0899_READ_S2REG(STB0899_S2DEMOD, EQ_CNTRL);
-	STB0899_SETFIELD_VAL(EQ_SHIFT, reg, 0);
-	STB0899_SETFIELD_VAL(EQ_DISABLE_UPDATE, reg, 0);
-	STB0899_SETFIELD_VAL(EQ_DELAY, reg, 0x05);
-	STB0899_SETFIELD_VAL(EQ_ADAPT_MODE, reg, 0x01);
-	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_EQ_CNTRL, STB0899_OFF0_EQ_CNTRL, reg);
-
-	/* RESET Packet delineator	*/
-	stb0899_write_reg(state, STB0899_PDELCTRL, 0x4a);
-}
-
-/*
- * stb0899_dvbs2_get_dmd_status
- * get DVB-S2 Demod LOCK status
- */
-static enum stb0899_status stb0899_dvbs2_get_dmd_status(struct stb0899_state *state, int timeout)
-{
-	int time = -10, lock = 0, uwp, csm;
-	u32 reg;
-
-	do {
-		reg = STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_STATUS);
-		dprintk(state->verbose, FE_DEBUG, 1, "DMD_STATUS=[0x%02x]", reg);
-		if (STB0899_GETFIELD(IF_AGC_LOCK, reg))
-			dprintk(state->verbose, FE_DEBUG, 1, "------------->IF AGC LOCKED !");
-		reg = STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_STAT2);
-		dprintk(state->verbose, FE_DEBUG, 1, "----------->DMD STAT2=[0x%02x]", reg);
-		uwp = STB0899_GETFIELD(UWP_LOCK, reg);
-		csm = STB0899_GETFIELD(CSM_LOCK, reg);
-		if (uwp && csm)
-			lock = 1;
-
-		time += 10;
-		msleep(10);
-
-	} while ((!lock) && (time <= timeout));
-
-	if (lock) {
-		dprintk(state->verbose, FE_DEBUG, 1, "----------------> DVB-S2 LOCK !");
-		return DVBS2_DEMOD_LOCK;
-	} else {
-		return DVBS2_DEMOD_NOLOCK;
-	}
-}
-
-/*
- * stb0899_dvbs2_get_data_lock
- * get FEC status
- */
-static int stb0899_dvbs2_get_data_lock(struct stb0899_state *state, int timeout)
-{
-	int time = 0, lock = 0;
-	u8 reg;
-
-	while ((!lock) && (time < timeout)) {
-		reg = stb0899_read_reg(state, STB0899_CFGPDELSTATUS1);
-		dprintk(state->verbose, FE_DEBUG, 1, "---------> CFGPDELSTATUS=[0x%02x]", reg);
-		lock = STB0899_GETFIELD(CFGPDELSTATUS_LOCK, reg);
-		time++;
-	}
-
-	return lock;
-}
-
-/*
- * stb0899_dvbs2_get_fec_status
- * get DVB-S2 FEC LOCK status
- */
-static enum stb0899_status stb0899_dvbs2_get_fec_status(struct stb0899_state *state, int timeout)
-{
-	int time = 0, Locked;
-
-	do {
-		Locked = stb0899_dvbs2_get_data_lock(state, 1);
-		time++;
-		msleep(1);
-
-	} while ((!Locked) && (time < timeout));
-
-	if (Locked) {
-		dprintk(state->verbose, FE_DEBUG, 1, "---------->DVB-S2 FEC LOCK !");
-		return DVBS2_FEC_LOCK;
-	} else {
-		return DVBS2_FEC_NOLOCK;
-	}
-}
-
-
-/*
- * stb0899_dvbs2_init_csm
- * set parameters for manual mode
- */
-static void stb0899_dvbs2_init_csm(struct stb0899_state *state, int pilots, enum stb0899_modcod modcod)
-{
-	struct stb0899_internal *internal = &state->internal;
-
-	s32 dvt_tbl = 1, two_pass = 0, agc_gain = 6, agc_shift = 0, loop_shift = 0, phs_diff_thr = 0x80;
-	s32 gamma_acq, gamma_rho_acq, gamma_trk, gamma_rho_trk, lock_count_thr;
-	u32 csm1, csm2, csm3, csm4;
-
-	if (((internal->master_clk / internal->srate) <= 4) && (modcod <= 11) && (pilots == 1)) {
-		switch (modcod) {
-		case STB0899_QPSK_12:
-			gamma_acq		= 25;
-			gamma_rho_acq		= 2700;
-			gamma_trk		= 12;
-			gamma_rho_trk		= 180;
-			lock_count_thr		= 8;
-			break;
-		case STB0899_QPSK_35:
-			gamma_acq		= 38;
-			gamma_rho_acq		= 7182;
-			gamma_trk		= 14;
-			gamma_rho_trk		= 308;
-			lock_count_thr		= 8;
-			break;
-		case STB0899_QPSK_23:
-			gamma_acq		= 42;
-			gamma_rho_acq		= 9408;
-			gamma_trk		= 17;
-			gamma_rho_trk		= 476;
-			lock_count_thr		= 8;
-			break;
-		case STB0899_QPSK_34:
-			gamma_acq		= 53;
-			gamma_rho_acq		= 16642;
-			gamma_trk		= 19;
-			gamma_rho_trk		= 646;
-			lock_count_thr		= 8;
-			break;
-		case STB0899_QPSK_45:
-			gamma_acq		= 53;
-			gamma_rho_acq		= 17119;
-			gamma_trk		= 22;
-			gamma_rho_trk		= 880;
-			lock_count_thr		= 8;
-			break;
-		case STB0899_QPSK_56:
-			gamma_acq		= 55;
-			gamma_rho_acq		= 19250;
-			gamma_trk		= 23;
-			gamma_rho_trk		= 989;
-			lock_count_thr		= 8;
-			break;
-		case STB0899_QPSK_89:
-			gamma_acq		= 60;
-			gamma_rho_acq		= 24240;
-			gamma_trk		= 24;
-			gamma_rho_trk		= 1176;
-			lock_count_thr		= 8;
-			break;
-		case STB0899_QPSK_910:
-			gamma_acq		= 66;
-			gamma_rho_acq		= 29634;
-			gamma_trk		= 24;
-			gamma_rho_trk		= 1176;
-			lock_count_thr		= 8;
-			break;
-		default:
-			gamma_acq		= 66;
-			gamma_rho_acq		= 29634;
-			gamma_trk		= 24;
-			gamma_rho_trk		= 1176;
-			lock_count_thr		= 8;
-			break;
-		}
-
-		csm1 = STB0899_READ_S2REG(STB0899_S2DEMOD, CSM_CNTRL1);
-		STB0899_SETFIELD_VAL(CSM_AUTO_PARAM, csm1, 0);
-		stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CSM_CNTRL1, STB0899_OFF0_CSM_CNTRL1, csm1);
-
-		csm1 = STB0899_READ_S2REG(STB0899_S2DEMOD, CSM_CNTRL1);
-		csm2 = STB0899_READ_S2REG(STB0899_S2DEMOD, CSM_CNTRL2);
-		csm3 = STB0899_READ_S2REG(STB0899_S2DEMOD, CSM_CNTRL3);
-		csm4 = STB0899_READ_S2REG(STB0899_S2DEMOD, CSM_CNTRL4);
-
-		STB0899_SETFIELD_VAL(CSM_DVT_TABLE, csm1, dvt_tbl);
-		STB0899_SETFIELD_VAL(CSM_TWO_PASS, csm1, two_pass);
-		STB0899_SETFIELD_VAL(CSM_AGC_GAIN, csm1, agc_gain);
-		STB0899_SETFIELD_VAL(CSM_AGC_SHIFT, csm1, agc_shift);
-		STB0899_SETFIELD_VAL(FE_LOOP_SHIFT, csm1, loop_shift);
-		STB0899_SETFIELD_VAL(CSM_GAMMA_ACQ, csm2, gamma_acq);
-		STB0899_SETFIELD_VAL(CSM_GAMMA_RHOACQ, csm2, gamma_rho_acq);
-		STB0899_SETFIELD_VAL(CSM_GAMMA_TRACK, csm3, gamma_trk);
-		STB0899_SETFIELD_VAL(CSM_GAMMA_RHOTRACK, csm3, gamma_rho_trk);
-		STB0899_SETFIELD_VAL(CSM_LOCKCOUNT_THRESH, csm4, lock_count_thr);
-		STB0899_SETFIELD_VAL(CSM_PHASEDIFF_THRESH, csm4, phs_diff_thr);
-
-		stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CSM_CNTRL1, STB0899_OFF0_CSM_CNTRL1, csm1);
-		stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CSM_CNTRL2, STB0899_OFF0_CSM_CNTRL2, csm2);
-		stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CSM_CNTRL3, STB0899_OFF0_CSM_CNTRL3, csm3);
-		stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CSM_CNTRL4, STB0899_OFF0_CSM_CNTRL4, csm4);
-	}
-}
-
-/*
- * stb0899_dvbs2_get_srate
- * get DVB-S2 Symbol Rate
- */
-static u32 stb0899_dvbs2_get_srate(struct stb0899_state *state)
-{
-	struct stb0899_internal *internal = &state->internal;
-	struct stb0899_config *config = state->config;
-
-	u32 bTrNomFreq, srate, decimRate, intval1, intval2, reg;
-	int div1, div2, rem1, rem2;
-
-	div1 = config->btr_nco_bits / 2;
-	div2 = config->btr_nco_bits - div1 - 1;
-
-	bTrNomFreq = STB0899_READ_S2REG(STB0899_S2DEMOD, BTR_NOM_FREQ);
-
-	reg = STB0899_READ_S2REG(STB0899_S2DEMOD, DECIM_CNTRL);
-	decimRate = STB0899_GETFIELD(DECIM_RATE, reg);
-	decimRate = (1 << decimRate);
-
-	intval1 = internal->master_clk / (1 << div1);
-	intval2 = bTrNomFreq / (1 << div2);
-
-	rem1 = internal->master_clk % (1 << div1);
-	rem2 = bTrNomFreq % (1 << div2);
-	/* only for integer calculation	*/
-	srate = (intval1 * intval2) + ((intval1 * rem2) / (1 << div2)) + ((intval2 * rem1) / (1 << div1));
-	srate /= decimRate;	/*symbrate = (btrnomfreq_register_val*MasterClock)/2^(27+decim_rate_field) */
-
-	return	srate;
-}
-
-/*
- * stb0899_dvbs2_algo
- * Search for signal, timing, carrier and data for a given
- * frequency in a given range
- */
-enum stb0899_status stb0899_dvbs2_algo(struct stb0899_state *state)
-{
-	struct stb0899_internal *internal = &state->internal;
-	enum stb0899_modcod modcod;
-
-	s32 offsetfreq, searchTime, FecLockTime, pilots, iqSpectrum;
-	int i = 0;
-	u32 reg, csm1;
-
-	if (internal->srate <= 2000000) {
-		searchTime	= 5000;	/* 5000 ms max time to lock UWP and CSM, SYMB <= 2Mbs		*/
-		FecLockTime	= 350;	/* 350  ms max time to lock FEC, SYMB <= 2Mbs			*/
-	} else if (internal->srate <= 5000000) {
-		searchTime	= 2500;	/* 2500 ms max time to lock UWP and CSM, 2Mbs < SYMB <= 5Mbs	*/
-		FecLockTime	= 170;	/* 170  ms max time to lock FEC, 2Mbs< SYMB <= 5Mbs		*/
-	} else if (internal->srate <= 10000000) {
-		searchTime	= 1500;	/* 1500 ms max time to lock UWP and CSM, 5Mbs <SYMB <= 10Mbs	*/
-		FecLockTime	= 80;	/* 80  ms max time to lock FEC, 5Mbs< SYMB <= 10Mbs		*/
-	} else if (internal->srate <= 15000000) {
-		searchTime	= 500;	/* 500 ms max time to lock UWP and CSM, 10Mbs <SYMB <= 15Mbs	*/
-		FecLockTime	= 50;	/* 50  ms max time to lock FEC, 10Mbs< SYMB <= 15Mbs		*/
-	} else if (internal->srate <= 20000000) {
-		searchTime	= 300;	/* 300 ms max time to lock UWP and CSM, 15Mbs < SYMB <= 20Mbs	*/
-		FecLockTime	= 30;	/* 50  ms max time to lock FEC, 15Mbs< SYMB <= 20Mbs		*/
-	} else if (internal->srate <= 25000000) {
-		searchTime	= 250;	/* 250 ms max time to lock UWP and CSM, 20 Mbs < SYMB <= 25Mbs	*/
-		FecLockTime	= 25;	/* 25 ms max time to lock FEC, 20Mbs< SYMB <= 25Mbs		*/
-	} else {
-		searchTime	= 150;	/* 150 ms max time to lock UWP and CSM, SYMB > 25Mbs		*/
-		FecLockTime	= 20;	/* 20 ms max time to lock FEC, 20Mbs< SYMB <= 25Mbs		*/
-	}
-
-	/* Maintain Stream Merger in reset during acquisition	*/
-	reg = stb0899_read_reg(state, STB0899_TSTRES);
-	STB0899_SETFIELD_VAL(FRESRS, reg, 1);
-	stb0899_write_reg(state, STB0899_TSTRES, reg);
-
-	/* enable tuner I/O */
-	stb0899_i2c_gate_ctrl(&state->frontend, 1);
-
-	/* Move tuner to frequency	*/
-	if (state->config->tuner_set_frequency)
-		state->config->tuner_set_frequency(&state->frontend, internal->freq);
-	if (state->config->tuner_get_frequency)
-		state->config->tuner_get_frequency(&state->frontend, &internal->freq);
-
-	/* disable tuner I/O */
-	stb0899_i2c_gate_ctrl(&state->frontend, 0);
-
-	/* Set IF AGC to acquisition	*/
-	reg = STB0899_READ_S2REG(STB0899_S2DEMOD, IF_AGC_CNTRL);
-	STB0899_SETFIELD_VAL(IF_LOOP_GAIN, reg,  4);
-	STB0899_SETFIELD_VAL(IF_AGC_REF, reg, 32);
-	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_IF_AGC_CNTRL, STB0899_OFF0_IF_AGC_CNTRL, reg);
-
-	reg = STB0899_READ_S2REG(STB0899_S2DEMOD, IF_AGC_CNTRL2);
-	STB0899_SETFIELD_VAL(IF_AGC_DUMP_PER, reg, 0);
-	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_IF_AGC_CNTRL2, STB0899_OFF0_IF_AGC_CNTRL2, reg);
-
-	/* Initialisation	*/
-	stb0899_dvbs2_init_calc(state);
-
-	reg = STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_CNTRL2);
-	switch (internal->inversion) {
-	case IQ_SWAP_OFF:
-		STB0899_SETFIELD_VAL(SPECTRUM_INVERT, reg, 0);
-		break;
-	case IQ_SWAP_ON:
-		STB0899_SETFIELD_VAL(SPECTRUM_INVERT, reg, 1);
-		break;
-	case IQ_SWAP_AUTO:	/* use last successful search first	*/
-		STB0899_SETFIELD_VAL(SPECTRUM_INVERT, reg, 1);
-		break;
-	}
-	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_DMD_CNTRL2, STB0899_OFF0_DMD_CNTRL2, reg);
-	stb0899_dvbs2_reacquire(state);
-
-	/* Wait for demod lock (UWP and CSM)	*/
-	internal->status = stb0899_dvbs2_get_dmd_status(state, searchTime);
-
-	if (internal->status == DVBS2_DEMOD_LOCK) {
-		dprintk(state->verbose, FE_DEBUG, 1, "------------> DVB-S2 DEMOD LOCK !");
-		i = 0;
-		/* Demod Locked, check FEC status	*/
-		internal->status = stb0899_dvbs2_get_fec_status(state, FecLockTime);
-
-		/*If false lock (UWP and CSM Locked but no FEC) try 3 time max*/
-		while ((internal->status != DVBS2_FEC_LOCK) && (i < 3)) {
-			/*	Read the frequency offset*/
-			offsetfreq = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_FREQ);
-
-			/* Set the Nominal frequency to the found frequency offset for the next reacquire*/
-			reg = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_NOM_FREQ);
-			STB0899_SETFIELD_VAL(CRL_NOM_FREQ, reg, offsetfreq);
-			stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CRL_NOM_FREQ, STB0899_OFF0_CRL_NOM_FREQ, reg);
-			stb0899_dvbs2_reacquire(state);
-			internal->status = stb0899_dvbs2_get_fec_status(state, searchTime);
-			i++;
-		}
-	}
-
-	if (internal->status != DVBS2_FEC_LOCK) {
-		if (internal->inversion == IQ_SWAP_AUTO) {
-			reg = STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_CNTRL2);
-			iqSpectrum = STB0899_GETFIELD(SPECTRUM_INVERT, reg);
-			/* IQ Spectrum Inversion	*/
-			STB0899_SETFIELD_VAL(SPECTRUM_INVERT, reg, !iqSpectrum);
-			stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_DMD_CNTRL2, STB0899_OFF0_DMD_CNTRL2, reg);
-			/* start acquistion process	*/
-			stb0899_dvbs2_reacquire(state);
-
-			/* Wait for demod lock (UWP and CSM)	*/
-			internal->status = stb0899_dvbs2_get_dmd_status(state, searchTime);
-			if (internal->status == DVBS2_DEMOD_LOCK) {
-				i = 0;
-				/* Demod Locked, check FEC	*/
-				internal->status = stb0899_dvbs2_get_fec_status(state, FecLockTime);
-				/*try thrice for false locks, (UWP and CSM Locked but no FEC)	*/
-				while ((internal->status != DVBS2_FEC_LOCK) && (i < 3)) {
-					/*	Read the frequency offset*/
-					offsetfreq = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_FREQ);
-
-					/* Set the Nominal frequency to the found frequency offset for the next reacquire*/
-					reg = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_NOM_FREQ);
-					STB0899_SETFIELD_VAL(CRL_NOM_FREQ, reg, offsetfreq);
-					stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CRL_NOM_FREQ, STB0899_OFF0_CRL_NOM_FREQ, reg);
-
-					stb0899_dvbs2_reacquire(state);
-					internal->status = stb0899_dvbs2_get_fec_status(state, searchTime);
-					i++;
-				}
-			}
-/*
-			if (pParams->DVBS2State == FE_DVBS2_FEC_LOCKED)
-				pParams->IQLocked = !iqSpectrum;
-*/
-		}
-	}
-	if (internal->status == DVBS2_FEC_LOCK) {
-		dprintk(state->verbose, FE_DEBUG, 1, "----------------> DVB-S2 FEC Lock !");
-		reg = STB0899_READ_S2REG(STB0899_S2DEMOD, UWP_STAT2);
-		modcod = STB0899_GETFIELD(UWP_DECODE_MOD, reg) >> 2;
-		pilots = STB0899_GETFIELD(UWP_DECODE_MOD, reg) & 0x01;
-
-		if ((((10 * internal->master_clk) / (internal->srate / 10)) <= 410) &&
-		      (INRANGE(STB0899_QPSK_23, modcod, STB0899_QPSK_910)) &&
-		      (pilots == 1)) {
-
-			stb0899_dvbs2_init_csm(state, pilots, modcod);
-			/* Wait for UWP,CSM and data LOCK 20ms max	*/
-			internal->status = stb0899_dvbs2_get_fec_status(state, FecLockTime);
-
-			i = 0;
-			while ((internal->status != DVBS2_FEC_LOCK) && (i < 3)) {
-				csm1 = STB0899_READ_S2REG(STB0899_S2DEMOD, CSM_CNTRL1);
-				STB0899_SETFIELD_VAL(CSM_TWO_PASS, csm1, 1);
-				stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CSM_CNTRL1, STB0899_OFF0_CSM_CNTRL1, csm1);
-				csm1 = STB0899_READ_S2REG(STB0899_S2DEMOD, CSM_CNTRL1);
-				STB0899_SETFIELD_VAL(CSM_TWO_PASS, csm1, 0);
-				stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CSM_CNTRL1, STB0899_OFF0_CSM_CNTRL1, csm1);
-
-				internal->status = stb0899_dvbs2_get_fec_status(state, FecLockTime);
-				i++;
-			}
-		}
-
-		if ((((10 * internal->master_clk) / (internal->srate / 10)) <= 410) &&
-		      (INRANGE(STB0899_QPSK_12, modcod, STB0899_QPSK_35)) &&
-		      (pilots == 1)) {
-
-			/* Equalizer Disable update	 */
-			reg = STB0899_READ_S2REG(STB0899_S2DEMOD, EQ_CNTRL);
-			STB0899_SETFIELD_VAL(EQ_DISABLE_UPDATE, reg, 1);
-			stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_EQ_CNTRL, STB0899_OFF0_EQ_CNTRL, reg);
-		}
-
-		/* slow down the Equalizer once locked	*/
-		reg = STB0899_READ_S2REG(STB0899_S2DEMOD, EQ_CNTRL);
-		STB0899_SETFIELD_VAL(EQ_SHIFT, reg, 0x02);
-		stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_EQ_CNTRL, STB0899_OFF0_EQ_CNTRL, reg);
-
-		/* Store signal parameters	*/
-		offsetfreq = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_FREQ);
-
-		offsetfreq = offsetfreq / ((1 << 30) / 1000);
-		offsetfreq *= (internal->master_clk / 1000000);
-		reg = STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_CNTRL2);
-		if (STB0899_GETFIELD(SPECTRUM_INVERT, reg))
-			offsetfreq *= -1;
-
-		internal->freq = internal->freq - offsetfreq;
-		internal->srate = stb0899_dvbs2_get_srate(state);
-
-		reg = STB0899_READ_S2REG(STB0899_S2DEMOD, UWP_STAT2);
-		internal->modcod = STB0899_GETFIELD(UWP_DECODE_MOD, reg) >> 2;
-		internal->pilots = STB0899_GETFIELD(UWP_DECODE_MOD, reg) & 0x01;
-		internal->frame_length = (STB0899_GETFIELD(UWP_DECODE_MOD, reg) >> 1) & 0x01;
-
-		 /* Set IF AGC to tracking	*/
-		reg = STB0899_READ_S2REG(STB0899_S2DEMOD, IF_AGC_CNTRL);
-		STB0899_SETFIELD_VAL(IF_LOOP_GAIN, reg,  3);
-
-		/* if QPSK 1/2,QPSK 3/5 or QPSK 2/3 set IF AGC reference to 16 otherwise 32*/
-		if (INRANGE(STB0899_QPSK_12, internal->modcod, STB0899_QPSK_23))
-			STB0899_SETFIELD_VAL(IF_AGC_REF, reg, 16);
-
-		stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_IF_AGC_CNTRL, STB0899_OFF0_IF_AGC_CNTRL, reg);
-
-		reg = STB0899_READ_S2REG(STB0899_S2DEMOD, IF_AGC_CNTRL2);
-		STB0899_SETFIELD_VAL(IF_AGC_DUMP_PER, reg, 7);
-		stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_IF_AGC_CNTRL2, STB0899_OFF0_IF_AGC_CNTRL2, reg);
-	}
-
-	/* Release Stream Merger Reset		*/
-	reg = stb0899_read_reg(state, STB0899_TSTRES);
-	STB0899_SETFIELD_VAL(FRESRS, reg, 0);
-	stb0899_write_reg(state, STB0899_TSTRES, reg);
-
-	return internal->status;
-}
diff --git a/drivers/media/dvb/frontends/stb0899_cfg.h b/drivers/media/dvb/frontends/stb0899_cfg.h
deleted file mode 100644
index 0867906..0000000
--- a/drivers/media/dvb/frontends/stb0899_cfg.h
+++ /dev/null
@@ -1,287 +0,0 @@
-/*
-	STB0899 Multistandard Frontend driver
-	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
-
-	Copyright (C) ST Microelectronics
-
-	This program is free software; you can redistribute it and/or modify
-	it under the terms of the 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 __STB0899_CFG_H
-#define __STB0899_CFG_H
-
-static const struct stb0899_s2_reg  stb0899_s2_init_2[] = {
-
-	{ STB0899_OFF0_DMD_STATUS	, STB0899_BASE_DMD_STATUS	, 0x00000103 },	/* DMDSTATUS	*/
-	{ STB0899_OFF0_CRL_FREQ		, STB0899_BASE_CRL_FREQ		, 0x3ed1da56 },	/* CRLFREQ	*/
-	{ STB0899_OFF0_BTR_FREQ		, STB0899_BASE_BTR_FREQ		, 0x00004000 },	/* BTRFREQ	*/
-	{ STB0899_OFF0_IF_AGC_GAIN	, STB0899_BASE_IF_AGC_GAIN	, 0x00002ade },	/* IFAGCGAIN	*/
-	{ STB0899_OFF0_BB_AGC_GAIN	, STB0899_BASE_BB_AGC_GAIN	, 0x000001bc },	/* BBAGCGAIN	*/
-	{ STB0899_OFF0_DC_OFFSET	, STB0899_BASE_DC_OFFSET	, 0x00000200 },	/* DCOFFSET	*/
-	{ STB0899_OFF0_DMD_CNTRL	, STB0899_BASE_DMD_CNTRL	, 0x0000000f },	/* DMDCNTRL	*/
-
-	{ STB0899_OFF0_IF_AGC_CNTRL	, STB0899_BASE_IF_AGC_CNTRL	, 0x03fb4a20 },	/* IFAGCCNTRL	*/
-	{ STB0899_OFF0_BB_AGC_CNTRL	, STB0899_BASE_BB_AGC_CNTRL	, 0x00200c97 },	/* BBAGCCNTRL	*/
-
-	{ STB0899_OFF0_CRL_CNTRL	, STB0899_BASE_CRL_CNTRL	, 0x00000016 },	/* CRLCNTRL	*/
-	{ STB0899_OFF0_CRL_PHS_INIT	, STB0899_BASE_CRL_PHS_INIT	, 0x00000000 },	/* CRLPHSINIT	*/
-	{ STB0899_OFF0_CRL_FREQ_INIT	, STB0899_BASE_CRL_FREQ_INIT	, 0x00000000 },	/* CRLFREQINIT	*/
-	{ STB0899_OFF0_CRL_LOOP_GAIN	, STB0899_BASE_CRL_LOOP_GAIN	, 0x00000000 },	/* CRLLOOPGAIN	*/
-	{ STB0899_OFF0_CRL_NOM_FREQ	, STB0899_BASE_CRL_NOM_FREQ	, 0x3ed097b6 },	/* CRLNOMFREQ	*/
-	{ STB0899_OFF0_CRL_SWP_RATE	, STB0899_BASE_CRL_SWP_RATE	, 0x00000000 },	/* CRLSWPRATE	*/
-	{ STB0899_OFF0_CRL_MAX_SWP	, STB0899_BASE_CRL_MAX_SWP	, 0x00000000 },	/* CRLMAXSWP	*/
-	{ STB0899_OFF0_CRL_LK_CNTRL	, STB0899_BASE_CRL_LK_CNTRL	, 0x0f6cdc01 },	/* CRLLKCNTRL	*/
-	{ STB0899_OFF0_DECIM_CNTRL	, STB0899_BASE_DECIM_CNTRL	, 0x00000000 },	/* DECIMCNTRL	*/
-	{ STB0899_OFF0_BTR_CNTRL	, STB0899_BASE_BTR_CNTRL	, 0x00003993 },	/* BTRCNTRL	*/
-	{ STB0899_OFF0_BTR_LOOP_GAIN	, STB0899_BASE_BTR_LOOP_GAIN	, 0x000d3c6f },	/* BTRLOOPGAIN	*/
-	{ STB0899_OFF0_BTR_PHS_INIT	, STB0899_BASE_BTR_PHS_INIT	, 0x00000000 },	/* BTRPHSINIT	*/
-	{ STB0899_OFF0_BTR_FREQ_INIT	, STB0899_BASE_BTR_FREQ_INIT	, 0x00000000 },	/* BTRFREQINIT	*/
-	{ STB0899_OFF0_BTR_NOM_FREQ	, STB0899_BASE_BTR_NOM_FREQ	, 0x0238e38e },	/* BTRNOMFREQ	*/
-	{ STB0899_OFF0_BTR_LK_CNTRL	, STB0899_BASE_BTR_LK_CNTRL	, 0x00000000 },	/* BTRLKCNTRL	*/
-	{ STB0899_OFF0_DECN_CNTRL	, STB0899_BASE_DECN_CNTRL	, 0x00000000 },	/* DECNCNTRL	*/
-	{ STB0899_OFF0_TP_CNTRL		, STB0899_BASE_TP_CNTRL		, 0x00000000 },	/* TPCNTRL	*/
-	{ STB0899_OFF0_TP_BUF_STATUS	, STB0899_BASE_TP_BUF_STATUS	, 0x00000000 },	/* TPBUFSTATUS	*/
-	{ STB0899_OFF0_DC_ESTIM		, STB0899_BASE_DC_ESTIM		, 0x00000000 },	/* DCESTIM	*/
-	{ STB0899_OFF0_FLL_CNTRL	, STB0899_BASE_FLL_CNTRL	, 0x00000000 },	/* FLLCNTRL	*/
-	{ STB0899_OFF0_FLL_FREQ_WD	, STB0899_BASE_FLL_FREQ_WD	, 0x40070000 },	/* FLLFREQWD	*/
-	{ STB0899_OFF0_ANTI_ALIAS_SEL	, STB0899_BASE_ANTI_ALIAS_SEL	, 0x00000001 },	/* ANTIALIASSEL */
-	{ STB0899_OFF0_RRC_ALPHA	, STB0899_BASE_RRC_ALPHA	, 0x00000002 },	/* RRCALPHA	*/
-	{ STB0899_OFF0_DC_ADAPT_LSHFT	, STB0899_BASE_DC_ADAPT_LSHFT	, 0x00000000 },	/* DCADAPTISHFT */
-	{ STB0899_OFF0_IMB_OFFSET	, STB0899_BASE_IMB_OFFSET	, 0x0000fe01 },	/* IMBOFFSET	*/
-	{ STB0899_OFF0_IMB_ESTIMATE	, STB0899_BASE_IMB_ESTIMATE	, 0x00000000 },	/* IMBESTIMATE	*/
-	{ STB0899_OFF0_IMB_CNTRL	, STB0899_BASE_IMB_CNTRL	, 0x00000001 },	/* IMBCNTRL	*/
-	{ STB0899_OFF0_IF_AGC_CNTRL2	, STB0899_BASE_IF_AGC_CNTRL2	, 0x00005007 },	/* IFAGCCNTRL2	*/
-	{ STB0899_OFF0_DMD_CNTRL2	, STB0899_BASE_DMD_CNTRL2	, 0x00000002 },	/* DMDCNTRL2	*/
-	{ STB0899_OFF0_TP_BUFFER	, STB0899_BASE_TP_BUFFER	, 0x00000000 },	/* TPBUFFER	*/
-	{ STB0899_OFF0_TP_BUFFER1	, STB0899_BASE_TP_BUFFER1	, 0x00000000 },	/* TPBUFFER1	*/
-	{ STB0899_OFF0_TP_BUFFER2	, STB0899_BASE_TP_BUFFER2	, 0x00000000 },	/* TPBUFFER2	*/
-	{ STB0899_OFF0_TP_BUFFER3	, STB0899_BASE_TP_BUFFER3	, 0x00000000 },	/* TPBUFFER3	*/
-	{ STB0899_OFF0_TP_BUFFER4	, STB0899_BASE_TP_BUFFER4	, 0x00000000 },	/* TPBUFFER4	*/
-	{ STB0899_OFF0_TP_BUFFER5	, STB0899_BASE_TP_BUFFER5	, 0x00000000 },	/* TPBUFFER5	*/
-	{ STB0899_OFF0_TP_BUFFER6	, STB0899_BASE_TP_BUFFER6	, 0x00000000 },	/* TPBUFFER6	*/
-	{ STB0899_OFF0_TP_BUFFER7	, STB0899_BASE_TP_BUFFER7	, 0x00000000 },	/* TPBUFFER7	*/
-	{ STB0899_OFF0_TP_BUFFER8	, STB0899_BASE_TP_BUFFER8	, 0x00000000 },	/* TPBUFFER8	*/
-	{ STB0899_OFF0_TP_BUFFER9	, STB0899_BASE_TP_BUFFER9	, 0x00000000 },	/* TPBUFFER9	*/
-	{ STB0899_OFF0_TP_BUFFER10	, STB0899_BASE_TP_BUFFER10	, 0x00000000 },	/* TPBUFFER10	*/
-	{ STB0899_OFF0_TP_BUFFER11	, STB0899_BASE_TP_BUFFER11	, 0x00000000 },	/* TPBUFFER11	*/
-	{ STB0899_OFF0_TP_BUFFER12	, STB0899_BASE_TP_BUFFER12	, 0x00000000 },	/* TPBUFFER12	*/
-	{ STB0899_OFF0_TP_BUFFER13	, STB0899_BASE_TP_BUFFER13	, 0x00000000 },	/* TPBUFFER13	*/
-	{ STB0899_OFF0_TP_BUFFER14	, STB0899_BASE_TP_BUFFER14	, 0x00000000 },	/* TPBUFFER14	*/
-	{ STB0899_OFF0_TP_BUFFER15	, STB0899_BASE_TP_BUFFER15	, 0x00000000 },	/* TPBUFFER15	*/
-	{ STB0899_OFF0_TP_BUFFER16	, STB0899_BASE_TP_BUFFER16	, 0x0000ff00 },	/* TPBUFFER16	*/
-	{ STB0899_OFF0_TP_BUFFER17	, STB0899_BASE_TP_BUFFER17	, 0x00000100 },	/* TPBUFFER17	*/
-	{ STB0899_OFF0_TP_BUFFER18	, STB0899_BASE_TP_BUFFER18	, 0x0000fe01 },	/* TPBUFFER18	*/
-	{ STB0899_OFF0_TP_BUFFER19	, STB0899_BASE_TP_BUFFER19	, 0x000004fe },	/* TPBUFFER19	*/
-	{ STB0899_OFF0_TP_BUFFER20	, STB0899_BASE_TP_BUFFER20	, 0x0000cfe7 },	/* TPBUFFER20	*/
-	{ STB0899_OFF0_TP_BUFFER21	, STB0899_BASE_TP_BUFFER21	, 0x0000bec6 },	/* TPBUFFER21	*/
-	{ STB0899_OFF0_TP_BUFFER22	, STB0899_BASE_TP_BUFFER22	, 0x0000c2bf },	/* TPBUFFER22	*/
-	{ STB0899_OFF0_TP_BUFFER23	, STB0899_BASE_TP_BUFFER23	, 0x0000c1c1 },	/* TPBUFFER23	*/
-	{ STB0899_OFF0_TP_BUFFER24	, STB0899_BASE_TP_BUFFER24	, 0x0000c1c1 },	/* TPBUFFER24	*/
-	{ STB0899_OFF0_TP_BUFFER25	, STB0899_BASE_TP_BUFFER25	, 0x0000c1c1 },	/* TPBUFFER25	*/
-	{ STB0899_OFF0_TP_BUFFER26	, STB0899_BASE_TP_BUFFER26	, 0x0000c1c1 },	/* TPBUFFER26	*/
-	{ STB0899_OFF0_TP_BUFFER27	, STB0899_BASE_TP_BUFFER27	, 0x0000c1c0 },	/* TPBUFFER27	*/
-	{ STB0899_OFF0_TP_BUFFER28	, STB0899_BASE_TP_BUFFER28	, 0x0000c0c0 },	/* TPBUFFER28	*/
-	{ STB0899_OFF0_TP_BUFFER29	, STB0899_BASE_TP_BUFFER29	, 0x0000c1c1 },	/* TPBUFFER29	*/
-	{ STB0899_OFF0_TP_BUFFER30	, STB0899_BASE_TP_BUFFER30	, 0x0000c1c1 },	/* TPBUFFER30	*/
-	{ STB0899_OFF0_TP_BUFFER31	, STB0899_BASE_TP_BUFFER31	, 0x0000c0c1 },	/* TPBUFFER31	*/
-	{ STB0899_OFF0_TP_BUFFER32	, STB0899_BASE_TP_BUFFER32	, 0x0000c0c1 },	/* TPBUFFER32	*/
-	{ STB0899_OFF0_TP_BUFFER33	, STB0899_BASE_TP_BUFFER33	, 0x0000c1c1 },	/* TPBUFFER33	*/
-	{ STB0899_OFF0_TP_BUFFER34	, STB0899_BASE_TP_BUFFER34	, 0x0000c1c1 },	/* TPBUFFER34	*/
-	{ STB0899_OFF0_TP_BUFFER35	, STB0899_BASE_TP_BUFFER35	, 0x0000c0c1 },	/* TPBUFFER35	*/
-	{ STB0899_OFF0_TP_BUFFER36	, STB0899_BASE_TP_BUFFER36	, 0x0000c1c1 },	/* TPBUFFER36	*/
-	{ STB0899_OFF0_TP_BUFFER37	, STB0899_BASE_TP_BUFFER37	, 0x0000c0c1 },	/* TPBUFFER37	*/
-	{ STB0899_OFF0_TP_BUFFER38	, STB0899_BASE_TP_BUFFER38	, 0x0000c1c1 },	/* TPBUFFER38	*/
-	{ STB0899_OFF0_TP_BUFFER39	, STB0899_BASE_TP_BUFFER39	, 0x0000c0c0 },	/* TPBUFFER39	*/
-	{ STB0899_OFF0_TP_BUFFER40	, STB0899_BASE_TP_BUFFER40	, 0x0000c1c0 },	/* TPBUFFER40	*/
-	{ STB0899_OFF0_TP_BUFFER41	, STB0899_BASE_TP_BUFFER41	, 0x0000c1c1 },	/* TPBUFFER41	*/
-	{ STB0899_OFF0_TP_BUFFER42	, STB0899_BASE_TP_BUFFER42	, 0x0000c0c0 },	/* TPBUFFER42	*/
-	{ STB0899_OFF0_TP_BUFFER43	, STB0899_BASE_TP_BUFFER43	, 0x0000c1c0 },	/* TPBUFFER43	*/
-	{ STB0899_OFF0_TP_BUFFER44	, STB0899_BASE_TP_BUFFER44	, 0x0000c0c1 },	/* TPBUFFER44	*/
-	{ STB0899_OFF0_TP_BUFFER45	, STB0899_BASE_TP_BUFFER45	, 0x0000c1be },	/* TPBUFFER45	*/
-	{ STB0899_OFF0_TP_BUFFER46	, STB0899_BASE_TP_BUFFER46	, 0x0000c1c9 },	/* TPBUFFER46	*/
-	{ STB0899_OFF0_TP_BUFFER47	, STB0899_BASE_TP_BUFFER47	, 0x0000c0da },	/* TPBUFFER47	*/
-	{ STB0899_OFF0_TP_BUFFER48	, STB0899_BASE_TP_BUFFER48	, 0x0000c0ba },	/* TPBUFFER48	*/
-	{ STB0899_OFF0_TP_BUFFER49	, STB0899_BASE_TP_BUFFER49	, 0x0000c1c4 },	/* TPBUFFER49	*/
-	{ STB0899_OFF0_TP_BUFFER50	, STB0899_BASE_TP_BUFFER50	, 0x0000c1bf },	/* TPBUFFER50	*/
-	{ STB0899_OFF0_TP_BUFFER51	, STB0899_BASE_TP_BUFFER51	, 0x0000c0c1 },	/* TPBUFFER51	*/
-	{ STB0899_OFF0_TP_BUFFER52	, STB0899_BASE_TP_BUFFER52	, 0x0000c1c0 },	/* TPBUFFER52	*/
-	{ STB0899_OFF0_TP_BUFFER53	, STB0899_BASE_TP_BUFFER53	, 0x0000c0c1 },	/* TPBUFFER53	*/
-	{ STB0899_OFF0_TP_BUFFER54	, STB0899_BASE_TP_BUFFER54	, 0x0000c1c1 },	/* TPBUFFER54	*/
-	{ STB0899_OFF0_TP_BUFFER55	, STB0899_BASE_TP_BUFFER55	, 0x0000c1c1 },	/* TPBUFFER55	*/
-	{ STB0899_OFF0_TP_BUFFER56	, STB0899_BASE_TP_BUFFER56	, 0x0000c1c1 },	/* TPBUFFER56	*/
-	{ STB0899_OFF0_TP_BUFFER57	, STB0899_BASE_TP_BUFFER57	, 0x0000c1c1 },	/* TPBUFFER57	*/
-	{ STB0899_OFF0_TP_BUFFER58	, STB0899_BASE_TP_BUFFER58	, 0x0000c1c1 },	/* TPBUFFER58	*/
-	{ STB0899_OFF0_TP_BUFFER59	, STB0899_BASE_TP_BUFFER59	, 0x0000c1c1 },	/* TPBUFFER59	*/
-	{ STB0899_OFF0_TP_BUFFER60	, STB0899_BASE_TP_BUFFER60	, 0x0000c1c1 },	/* TPBUFFER60	*/
-	{ STB0899_OFF0_TP_BUFFER61	, STB0899_BASE_TP_BUFFER61	, 0x0000c1c1 },	/* TPBUFFER61	*/
-	{ STB0899_OFF0_TP_BUFFER62	, STB0899_BASE_TP_BUFFER62	, 0x0000c1c1 },	/* TPBUFFER62	*/
-	{ STB0899_OFF0_TP_BUFFER63	, STB0899_BASE_TP_BUFFER63	, 0x0000c1c0 },	/* TPBUFFER63	*/
-	{ STB0899_OFF0_RESET_CNTRL	, STB0899_BASE_RESET_CNTRL	, 0x00000001 },	/* RESETCNTRL	*/
-	{ STB0899_OFF0_ACM_ENABLE	, STB0899_BASE_ACM_ENABLE	, 0x00005654 },	/* ACMENABLE	*/
-	{ STB0899_OFF0_DESCR_CNTRL	, STB0899_BASE_DESCR_CNTRL	, 0x00000000 },	/* DESCRCNTRL	*/
-	{ STB0899_OFF0_CSM_CNTRL1	, STB0899_BASE_CSM_CNTRL1	, 0x00020019 },	/* CSMCNTRL1	*/
-	{ STB0899_OFF0_CSM_CNTRL2	, STB0899_BASE_CSM_CNTRL2	, 0x004b3237 },	/* CSMCNTRL2	*/
-	{ STB0899_OFF0_CSM_CNTRL3	, STB0899_BASE_CSM_CNTRL3	, 0x0003dd17 },	/* CSMCNTRL3	*/
-	{ STB0899_OFF0_CSM_CNTRL4	, STB0899_BASE_CSM_CNTRL4	, 0x00008008 },	/* CSMCNTRL4	*/
-	{ STB0899_OFF0_UWP_CNTRL1	, STB0899_BASE_UWP_CNTRL1	, 0x002a3106 },	/* UWPCNTRL1	*/
-	{ STB0899_OFF0_UWP_CNTRL2	, STB0899_BASE_UWP_CNTRL2	, 0x0006140a },	/* UWPCNTRL2	*/
-	{ STB0899_OFF0_UWP_STAT1	, STB0899_BASE_UWP_STAT1	, 0x00008000 },	/* UWPSTAT1	*/
-	{ STB0899_OFF0_UWP_STAT2	, STB0899_BASE_UWP_STAT2	, 0x00000000 },	/* UWPSTAT2	*/
-	{ STB0899_OFF0_DMD_STAT2	, STB0899_BASE_DMD_STAT2	, 0x00000000 },	/* DMDSTAT2	*/
-	{ STB0899_OFF0_FREQ_ADJ_SCALE	, STB0899_BASE_FREQ_ADJ_SCALE	, 0x00000471 },	/* FREQADJSCALE */
-	{ STB0899_OFF0_UWP_CNTRL3	, STB0899_BASE_UWP_CNTRL3	, 0x017b0465 },	/* UWPCNTRL3	*/
-	{ STB0899_OFF0_SYM_CLK_SEL	, STB0899_BASE_SYM_CLK_SEL	, 0x00000002 },	/* SYMCLKSEL	*/
-	{ STB0899_OFF0_SOF_SRCH_TO	, STB0899_BASE_SOF_SRCH_TO	, 0x00196464 },	/* SOFSRCHTO	*/
-	{ STB0899_OFF0_ACQ_CNTRL1	, STB0899_BASE_ACQ_CNTRL1	, 0x00000603 },	/* ACQCNTRL1	*/
-	{ STB0899_OFF0_ACQ_CNTRL2	, STB0899_BASE_ACQ_CNTRL2	, 0x02046666 },	/* ACQCNTRL2	*/
-	{ STB0899_OFF0_ACQ_CNTRL3	, STB0899_BASE_ACQ_CNTRL3	, 0x10046583 },	/* ACQCNTRL3	*/
-	{ STB0899_OFF0_FE_SETTLE	, STB0899_BASE_FE_SETTLE	, 0x00010404 },	/* FESETTLE	*/
-	{ STB0899_OFF0_AC_DWELL		, STB0899_BASE_AC_DWELL		, 0x0002aa8a },	/* ACDWELL	*/
-	{ STB0899_OFF0_ACQUIRE_TRIG	, STB0899_BASE_ACQUIRE_TRIG	, 0x00000000 },	/* ACQUIRETRIG	*/
-	{ STB0899_OFF0_LOCK_LOST	, STB0899_BASE_LOCK_LOST	, 0x00000001 },	/* LOCKLOST	*/
-	{ STB0899_OFF0_ACQ_STAT1	, STB0899_BASE_ACQ_STAT1	, 0x00000500 },	/* ACQSTAT1	*/
-	{ STB0899_OFF0_ACQ_TIMEOUT	, STB0899_BASE_ACQ_TIMEOUT	, 0x0028a0a0 },	/* ACQTIMEOUT	*/
-	{ STB0899_OFF0_ACQ_TIME		, STB0899_BASE_ACQ_TIME		, 0x00000000 },	/* ACQTIME	*/
-	{ STB0899_OFF0_FINAL_AGC_CNTRL	, STB0899_BASE_FINAL_AGC_CNTRL	, 0x00800c17 },	/* FINALAGCCNTRL*/
-	{ STB0899_OFF0_FINAL_AGC_GAIN	, STB0899_BASE_FINAL_AGC_GAIN	, 0x00000000 },	/* FINALAGCCGAIN*/
-	{ STB0899_OFF0_EQUALIZER_INIT	, STB0899_BASE_EQUALIZER_INIT	, 0x00000000 },	/* EQUILIZERINIT*/
-	{ STB0899_OFF0_EQ_CNTRL		, STB0899_BASE_EQ_CNTRL		, 0x00054802 },	/* EQCNTL	*/
-	{ STB0899_OFF0_EQ_I_INIT_COEFF_0, STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000000 },	/* EQIINITCOEFF0 */
-	{ STB0899_OFF1_EQ_I_INIT_COEFF_1, STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000000 },	/* EQIINITCOEFF1 */
-	{ STB0899_OFF2_EQ_I_INIT_COEFF_2, STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000000 },	/* EQIINITCOEFF2 */
-	{ STB0899_OFF3_EQ_I_INIT_COEFF_3, STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000000 },	/* EQIINITCOEFF3 */
-	{ STB0899_OFF4_EQ_I_INIT_COEFF_4, STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000000 },	/* EQIINITCOEFF4 */
-	{ STB0899_OFF5_EQ_I_INIT_COEFF_5, STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000400 },	/* EQIINITCOEFF5 */
-	{ STB0899_OFF6_EQ_I_INIT_COEFF_6, STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000000 },	/* EQIINITCOEFF6 */
-	{ STB0899_OFF7_EQ_I_INIT_COEFF_7, STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000000 },	/* EQIINITCOEFF7 */
-	{ STB0899_OFF8_EQ_I_INIT_COEFF_8, STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000000 },	/* EQIINITCOEFF8 */
-	{ STB0899_OFF9_EQ_I_INIT_COEFF_9, STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000000 },	/* EQIINITCOEFF9 */
-	{ STB0899_OFFa_EQ_I_INIT_COEFF_10,STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000000 },	/* EQIINITCOEFF10*/
-	{ STB0899_OFF0_EQ_Q_INIT_COEFF_0, STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 },	/* EQQINITCOEFF0 */
-	{ STB0899_OFF1_EQ_Q_INIT_COEFF_1, STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 },	/* EQQINITCOEFF1 */
-	{ STB0899_OFF2_EQ_Q_INIT_COEFF_2, STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 },	/* EQQINITCOEFF2 */
-	{ STB0899_OFF3_EQ_Q_INIT_COEFF_3, STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 },	/* EQQINITCOEFF3 */
-	{ STB0899_OFF4_EQ_Q_INIT_COEFF_4, STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 },	/* EQQINITCOEFF4 */
-	{ STB0899_OFF5_EQ_Q_INIT_COEFF_5, STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 },	/* EQQINITCOEFF5 */
-	{ STB0899_OFF6_EQ_Q_INIT_COEFF_6, STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 },	/* EQQINITCOEFF6 */
-	{ STB0899_OFF7_EQ_Q_INIT_COEFF_7, STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 },	/* EQQINITCOEFF7 */
-	{ STB0899_OFF8_EQ_Q_INIT_COEFF_8, STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 },	/* EQQINITCOEFF8 */
-	{ STB0899_OFF9_EQ_Q_INIT_COEFF_9, STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 },	/* EQQINITCOEFF9 */
-	{ STB0899_OFFa_EQ_Q_INIT_COEFF_10,STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 },	/* EQQINITCOEFF10*/
-	{ STB0899_OFF0_EQ_I_OUT_COEFF_0	, STB0899_BASE_EQ_I_OUT_COEFF_N	, 0x00000000 }, /* EQICOEFFSOUT0 */
-	{ STB0899_OFF1_EQ_I_OUT_COEFF_1	, STB0899_BASE_EQ_I_OUT_COEFF_N	, 0x00000000 }, /* EQICOEFFSOUT1 */
-	{ STB0899_OFF2_EQ_I_OUT_COEFF_2	, STB0899_BASE_EQ_I_OUT_COEFF_N	, 0x00000000 }, /* EQICOEFFSOUT2 */
-	{ STB0899_OFF3_EQ_I_OUT_COEFF_3	, STB0899_BASE_EQ_I_OUT_COEFF_N	, 0x00000000 }, /* EQICOEFFSOUT3 */
-	{ STB0899_OFF4_EQ_I_OUT_COEFF_4	, STB0899_BASE_EQ_I_OUT_COEFF_N	, 0x00000000 }, /* EQICOEFFSOUT4 */
-	{ STB0899_OFF5_EQ_I_OUT_COEFF_5	, STB0899_BASE_EQ_I_OUT_COEFF_N	, 0x00000000 }, /* EQICOEFFSOUT5 */
-	{ STB0899_OFF6_EQ_I_OUT_COEFF_6	, STB0899_BASE_EQ_I_OUT_COEFF_N	, 0x00000000 }, /* EQICOEFFSOUT6 */
-	{ STB0899_OFF7_EQ_I_OUT_COEFF_7	, STB0899_BASE_EQ_I_OUT_COEFF_N	, 0x00000000 }, /* EQICOEFFSOUT7 */
-	{ STB0899_OFF8_EQ_I_OUT_COEFF_8	, STB0899_BASE_EQ_I_OUT_COEFF_N	, 0x00000000 }, /* EQICOEFFSOUT8 */
-	{ STB0899_OFF9_EQ_I_OUT_COEFF_9	, STB0899_BASE_EQ_I_OUT_COEFF_N	, 0x00000000 }, /* EQICOEFFSOUT9 */
-	{ STB0899_OFFa_EQ_I_OUT_COEFF_10,STB0899_BASE_EQ_I_OUT_COEFF_N	, 0x00000000 }, /* EQICOEFFSOUT10*/
-	{ STB0899_OFF0_EQ_Q_OUT_COEFF_0	, STB0899_BASE_EQ_Q_OUT_COEFF_N	, 0x00000000 },	/* EQQCOEFFSOUT0 */
-	{ STB0899_OFF1_EQ_Q_OUT_COEFF_1	, STB0899_BASE_EQ_Q_OUT_COEFF_N	, 0x00000000 },	/* EQQCOEFFSOUT1 */
-	{ STB0899_OFF2_EQ_Q_OUT_COEFF_2	, STB0899_BASE_EQ_Q_OUT_COEFF_N	, 0x00000000 },	/* EQQCOEFFSOUT2 */
-	{ STB0899_OFF3_EQ_Q_OUT_COEFF_3	, STB0899_BASE_EQ_Q_OUT_COEFF_N	, 0x00000000 },	/* EQQCOEFFSOUT3 */
-	{ STB0899_OFF4_EQ_Q_OUT_COEFF_4	, STB0899_BASE_EQ_Q_OUT_COEFF_N	, 0x00000000 },	/* EQQCOEFFSOUT4 */
-	{ STB0899_OFF5_EQ_Q_OUT_COEFF_5	, STB0899_BASE_EQ_Q_OUT_COEFF_N	, 0x00000000 },	/* EQQCOEFFSOUT5 */
-	{ STB0899_OFF6_EQ_Q_OUT_COEFF_6 , STB0899_BASE_EQ_Q_OUT_COEFF_N	, 0x00000000 },	/* EQQCOEFFSOUT6 */
-	{ STB0899_OFF7_EQ_Q_OUT_COEFF_7	, STB0899_BASE_EQ_Q_OUT_COEFF_N	, 0x00000000 },	/* EQQCOEFFSOUT7 */
-	{ STB0899_OFF8_EQ_Q_OUT_COEFF_8	, STB0899_BASE_EQ_Q_OUT_COEFF_N	, 0x00000000 },	/* EQQCOEFFSOUT8 */
-	{ STB0899_OFF9_EQ_Q_OUT_COEFF_9	, STB0899_BASE_EQ_Q_OUT_COEFF_N	, 0x00000000 },	/* EQQCOEFFSOUT9 */
-	{ STB0899_OFFa_EQ_Q_OUT_COEFF_10, STB0899_BASE_EQ_Q_OUT_COEFF_N	, 0x00000000 },	/* EQQCOEFFSOUT10*/
-	{ 0xffff			, 0xffffffff			, 0xffffffff },
-};
-static const struct stb0899_s2_reg stb0899_s2_init_4[] = {
-	{ STB0899_OFF0_BLOCK_LNGTH	, STB0899_BASE_BLOCK_LNGTH	, 0x00000008 },	/* BLOCKLNGTH	*/
-	{ STB0899_OFF0_ROW_STR		, STB0899_BASE_ROW_STR		, 0x000000b4 },	/* ROWSTR	*/
-	{ STB0899_OFF0_BN_END_ADDR	, STB0899_BASE_BN_END_ADDR	, 0x000004b5 },	/* BNANDADDR	*/
-	{ STB0899_OFF0_CN_END_ADDR	, STB0899_BASE_CN_END_ADDR	, 0x00000b4b },	/* CNANDADDR	*/
-	{ STB0899_OFF0_INFO_LENGTH	, STB0899_BASE_INFO_LENGTH	, 0x00000078 },	/* INFOLENGTH	*/
-	{ STB0899_OFF0_BOT_ADDR		, STB0899_BASE_BOT_ADDR		, 0x000001e0 },	/* BOT_ADDR	*/
-	{ STB0899_OFF0_BCH_BLK_LN	, STB0899_BASE_BCH_BLK_LN	, 0x0000a8c0 },	/* BCHBLKLN	*/
-	{ STB0899_OFF0_BCH_T		, STB0899_BASE_BCH_T		, 0x0000000c },	/* BCHT		*/
-	{ STB0899_OFF0_CNFG_MODE	, STB0899_BASE_CNFG_MODE	, 0x00000001 },	/* CNFGMODE	*/
-	{ STB0899_OFF0_LDPC_STAT	, STB0899_BASE_LDPC_STAT	, 0x0000000d },	/* LDPCSTAT	*/
-	{ STB0899_OFF0_ITER_SCALE	, STB0899_BASE_ITER_SCALE	, 0x00000040 },	/* ITERSCALE	*/
-	{ STB0899_OFF0_INPUT_MODE	, STB0899_BASE_INPUT_MODE	, 0x00000000 },	/* INPUTMODE	*/
-	{ STB0899_OFF0_LDPCDECRST	, STB0899_BASE_LDPCDECRST	, 0x00000000 },	/* LDPCDECRST	*/
-	{ STB0899_OFF0_CLK_PER_BYTE_RW	, STB0899_BASE_CLK_PER_BYTE_RW	, 0x00000008 },	/* CLKPERBYTE	*/
-	{ STB0899_OFF0_BCH_ERRORS	, STB0899_BASE_BCH_ERRORS	, 0x00000000 },	/* BCHERRORS	*/
-	{ STB0899_OFF0_LDPC_ERRORS	, STB0899_BASE_LDPC_ERRORS	, 0x00000000 },	/* LDPCERRORS	*/
-	{ STB0899_OFF0_BCH_MODE		, STB0899_BASE_BCH_MODE		, 0x00000000 },	/* BCHMODE	*/
-	{ STB0899_OFF0_ERR_ACC_PER	, STB0899_BASE_ERR_ACC_PER	, 0x00000008 },	/* ERRACCPER	*/
-	{ STB0899_OFF0_BCH_ERR_ACC	, STB0899_BASE_BCH_ERR_ACC	, 0x00000000 },	/* BCHERRACC	*/
-	{ STB0899_OFF0_FEC_TP_SEL	, STB0899_BASE_FEC_TP_SEL	, 0x00000000 },	/* FECTPSEL	*/
-	{ 0xffff			, 0xffffffff			, 0xffffffff },
-};
-
-static const struct stb0899_s1_reg stb0899_s1_init_5[] = {
-	{ STB0899_TSTCK		, 0x00 },
-	{ STB0899_TSTRES	, 0x00 },
-	{ STB0899_TSTOUT	, 0x00 },
-	{ STB0899_TSTIN		, 0x00 },
-	{ STB0899_TSTSYS	, 0x00 },
-	{ STB0899_TSTCHIP	, 0x00 },
-	{ STB0899_TSTFREE	, 0x00 },
-	{ STB0899_TSTI2C	, 0x00 },
-	{ STB0899_BITSPEEDM	, 0x00 },
-	{ STB0899_BITSPEEDL	, 0x00 },
-	{ STB0899_TBUSBIT	, 0x00 },
-	{ STB0899_TSTDIS	, 0x00 },
-	{ STB0899_TSTDISRX	, 0x00 },
-	{ STB0899_TSTJETON	, 0x00 },
-	{ STB0899_TSTDCADJ	, 0x00 },
-	{ STB0899_TSTAGC1	, 0x00 },
-	{ STB0899_TSTAGC1N	, 0x00 },
-	{ STB0899_TSTPOLYPH	, 0x00 },
-	{ STB0899_TSTR		, 0x00 },
-	{ STB0899_TSTAGC2	, 0x00 },
-	{ STB0899_TSTCTL1	, 0x00 },
-	{ STB0899_TSTCTL2	, 0x00 },
-	{ STB0899_TSTCTL3	, 0x00 },
-	{ STB0899_TSTDEMAP	, 0x00 },
-	{ STB0899_TSTDEMAP2	, 0x00 },
-	{ STB0899_TSTDEMMON	, 0x00 },
-	{ STB0899_TSTRATE	, 0x00 },
-	{ STB0899_TSTSELOUT	, 0x00 },
-	{ STB0899_TSYNC		, 0x00 },
-	{ STB0899_TSTERR	, 0x00 },
-	{ STB0899_TSTRAM1	, 0x00 },
-	{ STB0899_TSTVSELOUT	, 0x00 },
-	{ STB0899_TSTFORCEIN	, 0x00 },
-	{ STB0899_TSTRS1	, 0x00 },
-	{ STB0899_TSTRS2	, 0x00 },
-	{ STB0899_TSTRS3	, 0x00 },
-	{ STB0899_GHOSTREG	, 0x81 },
-	{ 0xffff		, 0xff },
-};
-
-#define STB0899_DVBS2_ESNO_AVE			3
-#define STB0899_DVBS2_ESNO_QUANT		32
-#define STB0899_DVBS2_AVFRAMES_COARSE		10
-#define STB0899_DVBS2_AVFRAMES_FINE		20
-#define STB0899_DVBS2_MISS_THRESHOLD		6
-#define STB0899_DVBS2_UWP_THRESHOLD_ACQ		1125
-#define STB0899_DVBS2_UWP_THRESHOLD_TRACK	758
-#define STB0899_DVBS2_UWP_THRESHOLD_SOF		1350
-#define STB0899_DVBS2_SOF_SEARCH_TIMEOUT	1664100
-
-#define STB0899_DVBS2_BTR_NCO_BITS		28
-#define STB0899_DVBS2_BTR_GAIN_SHIFT_OFFSET	15
-#define STB0899_DVBS2_CRL_NCO_BITS		30
-#define STB0899_DVBS2_LDPC_MAX_ITER		70
-
-#endif //__STB0899_CFG_H
diff --git a/drivers/media/dvb/frontends/stb0899_drv.c b/drivers/media/dvb/frontends/stb0899_drv.c
deleted file mode 100644
index 5d7f8a9..0000000
--- a/drivers/media/dvb/frontends/stb0899_drv.c
+++ /dev/null
@@ -1,1651 +0,0 @@
-/*
-	STB0899 Multistandard Frontend driver
-	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
-
-	Copyright (C) ST Microelectronics
-
-	This program is free software; you can redistribute it and/or modify
-	it under the terms of the 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/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-
-#include <linux/dvb/frontend.h>
-#include "dvb_frontend.h"
-
-#include "stb0899_drv.h"
-#include "stb0899_priv.h"
-#include "stb0899_reg.h"
-
-static unsigned int verbose = 0;//1;
-module_param(verbose, int, 0644);
-
-/* C/N in dB/10, NIRM/NIRL */
-static const struct stb0899_tab stb0899_cn_tab[] = {
-	{ 200,	2600 },
-	{ 190,	2700 },
-	{ 180,	2860 },
-	{ 170,	3020 },
-	{ 160,	3210 },
-	{ 150,	3440 },
-	{ 140,	3710 },
-	{ 130,	4010 },
-	{ 120,	4360 },
-	{ 110,	4740 },
-	{ 100,	5190 },
-	{ 90,	5670 },
-	{ 80,	6200 },
-	{ 70,	6770 },
-	{ 60,	7360 },
-	{ 50,	7970 },
-	{ 40,	8250 },
-	{ 30,	9000 },
-	{ 20,	9450 },
-	{ 15,	9600 },
-};
-
-/* DVB-S AGCIQ_VALUE vs. signal level in dBm/10.
- * As measured, connected to a modulator.
- * -8.0 to -50.0 dBm directly connected,
- * -52.0 to -74.8 with extra attenuation.
- * Cut-off to AGCIQ_VALUE = 0x80 below -74.8dBm.
- * Crude linear extrapolation below -84.8dBm and above -8.0dBm.
- */
-static const struct stb0899_tab stb0899_dvbsrf_tab[] = {
-	{ -750,	-128 },
-	{ -748,	 -94 },
-	{ -745,	 -92 },
-	{ -735,	 -90 },
-	{ -720,	 -87 },
-	{ -670,	 -77 },
-	{ -640,	 -70 },
-	{ -610,	 -62 },
-	{ -600,	 -60 },
-	{ -590,	 -56 },
-	{ -560,	 -41 },
-	{ -540,	 -25 },
-	{ -530,	 -17 },
-	{ -520,	 -11 },
-	{ -500,	   1 },
-	{ -490,	   6 },
-	{ -480,	  10 },
-	{ -440,	  22 },
-	{ -420,	  27 },
-	{ -400,	  31 },
-	{ -380,	  34 },
-	{ -340,	  40 },
-	{ -320,	  43 },
-	{ -280,	  48 },
-	{ -250,	  52 },
-	{ -230,	  55 },
-	{ -180,	  61 },
-	{ -140,	  66 },
-	{  -90,	  73 },
-	{  -80,	  74 },
-	{  500,	 127 }
-};
-
-/* DVB-S2 IF_AGC_GAIN vs. signal level in dBm/10.
- * As measured, connected to a modulator.
- * -8.0 to -50.1 dBm directly connected,
- * -53.0 to -76.6 with extra attenuation.
- * Cut-off to IF_AGC_GAIN = 0x3fff below -76.6dBm.
- * Crude linear extrapolation below -76.6dBm and above -8.0dBm.
- */
-static const struct stb0899_tab stb0899_dvbs2rf_tab[] = {
-	{  700,	    0 },
-	{  -80,	 3217 },
-	{ -150,	 3893 },
-	{ -190,	 4217 },
-	{ -240,	 4621 },
-	{ -280,	 4945 },
-	{ -320,	 5273 },
-	{ -350,	 5545 },
-	{ -370,	 5741 },
-	{ -410,	 6147 },
-	{ -450,	 6671 },
-	{ -490,	 7413 },
-	{ -501,	 7665 },
-	{ -530,	 8767 },
-	{ -560,	10219 },
-	{ -580,	10939 },
-	{ -590,	11518 },
-	{ -600,	11723 },
-	{ -650,	12659 },
-	{ -690,	13219 },
-	{ -730,	13645 },
-	{ -750,	13909 },
-	{ -766,	14153 },
-	{ -950,	16383 }
-};
-
-/* DVB-S2 Es/N0 quant in dB/100 vs read value * 100*/
-static struct stb0899_tab stb0899_quant_tab[] = {
-	{    0,	    0 },
-	{    0,	  100 },
-	{  600,	  200 },
-	{  950,	  299 },
-	{ 1200,	  398 },
-	{ 1400,	  501 },
-	{ 1560,	  603 },
-	{ 1690,	  700 },
-	{ 1810,	  804 },
-	{ 1910,	  902 },
-	{ 2000,	 1000 },
-	{ 2080,	 1096 },
-	{ 2160,	 1202 },
-	{ 2230,	 1303 },
-	{ 2350,	 1496 },
-	{ 2410,	 1603 },
-	{ 2460,	 1698 },
-	{ 2510,	 1799 },
-	{ 2600,	 1995 },
-	{ 2650,	 2113 },
-	{ 2690,  2213 },
-	{ 2720,	 2291 },
-	{ 2760,	 2399 },
-	{ 2800,	 2512 },
-	{ 2860,	 2692 },
-	{ 2930,	 2917 },
-	{ 2960,	 3020 },
-	{ 3010,	 3199 },
-	{ 3040,	 3311 },
-	{ 3060,	 3388 },
-	{ 3120,	 3631 },
-	{ 3190,	 3936 },
-	{ 3400,	 5012 },
-	{ 3610,	 6383 },
-	{ 3800,	 7943 },
-	{ 4210,	12735 },
-	{ 4500,	17783 },
-	{ 4690,	22131 },
-	{ 4810,	25410 }
-};
-
-/* DVB-S2 Es/N0 estimate in dB/100 vs read value */
-static struct stb0899_tab stb0899_est_tab[] = {
-	{    0,	     0 },
-	{    0,	     1 },
-	{  301,	     2 },
-	{ 1204,	    16 },
-	{ 1806,	    64 },
-	{ 2408,	   256 },
-	{ 2709,	   512 },
-	{ 3010,	  1023 },
-	{ 3311,	  2046 },
-	{ 3612,	  4093 },
-	{ 3823,	  6653 },
-	{ 3913,	  8185 },
-	{ 4010,	 10233 },
-	{ 4107,	 12794 },
-	{ 4214,	 16368 },
-	{ 4266,	 18450 },
-	{ 4311,	 20464 },
-	{ 4353,	 22542 },
-	{ 4391,	 24604 },
-	{ 4425,	 26607 },
-	{ 4457,	 28642 },
-	{ 4487,	 30690 },
-	{ 4515,	 32734 },
-	{ 4612,	 40926 },
-	{ 4692,	 49204 },
-	{ 4816,	 65464 },
-	{ 4913,	 81846 },
-	{ 4993,	 98401 },
-	{ 5060,	114815 },
-	{ 5118,	131220 },
-	{ 5200,	158489 },
-	{ 5300,	199526 },
-	{ 5400,	251189 },
-	{ 5500,	316228 },
-	{ 5600,	398107 },
-	{ 5720,	524807 },
-	{ 5721,	526017 },
-};
-
-static int _stb0899_read_reg(struct stb0899_state *state, unsigned int reg)
-{
-	int ret;
-
-	u8 b0[] = { reg >> 8, reg & 0xff };
-	u8 buf;
-
-	struct i2c_msg msg[] = {
-		{
-			.addr	= state->config->demod_address,
-			.flags	= 0,
-			.buf	= b0,
-			.len	= 2
-		},{
-			.addr	= state->config->demod_address,
-			.flags	= I2C_M_RD,
-			.buf	= &buf,
-			.len	= 1
-		}
-	};
-
-	ret = i2c_transfer(state->i2c, msg, 2);
-	if (ret != 2) {
-		if (ret != -ERESTARTSYS)
-			dprintk(state->verbose, FE_ERROR, 1,
-				"Read error, Reg=[0x%02x], Status=%d",
-				reg, ret);
-
-		return ret < 0 ? ret : -EREMOTEIO;
-	}
-	if (unlikely(*state->verbose >= FE_DEBUGREG))
-		dprintk(state->verbose, FE_ERROR, 1, "Reg=[0x%02x], data=%02x",
-			reg, buf);
-
-	return (unsigned int)buf;
-}
-
-int stb0899_read_reg(struct stb0899_state *state, unsigned int reg)
-{
-	int result;
-
-	result = _stb0899_read_reg(state, reg);
-	/*
-	 * Bug ID 9:
-	 * access to 0xf2xx/0xf6xx
-	 * must be followed by read from 0xf2ff/0xf6ff.
-	 */
-	if ((reg != 0xf2ff) && (reg != 0xf6ff) &&
-	    (((reg & 0xff00) == 0xf200) || ((reg & 0xff00) == 0xf600)))
-		_stb0899_read_reg(state, (reg | 0x00ff));
-
-	return result;
-}
-
-u32 _stb0899_read_s2reg(struct stb0899_state *state,
-			u32 stb0899_i2cdev,
-			u32 stb0899_base_addr,
-			u16 stb0899_reg_offset)
-{
-	int status;
-	u32 data;
-	u8 buf[7] = { 0 };
-	u16 tmpaddr;
-
-	u8 buf_0[] = {
-		GETBYTE(stb0899_i2cdev, BYTE1),		/* 0xf3	S2 Base Address (MSB)	*/
-		GETBYTE(stb0899_i2cdev, BYTE0),		/* 0xfc	S2 Base Address (LSB)	*/
-		GETBYTE(stb0899_base_addr, BYTE0),	/* 0x00	Base Address (LSB)	*/
-		GETBYTE(stb0899_base_addr, BYTE1),	/* 0x04	Base Address (LSB)	*/
-		GETBYTE(stb0899_base_addr, BYTE2),	/* 0x00	Base Address (MSB)	*/
-		GETBYTE(stb0899_base_addr, BYTE3),	/* 0x00	Base Address (MSB)	*/
-	};
-	u8 buf_1[] = {
-		0x00,	/* 0xf3	Reg Offset	*/
-		0x00,	/* 0x44	Reg Offset	*/
-	};
-
-	struct i2c_msg msg_0 = {
-		.addr	= state->config->demod_address,
-		.flags	= 0,
-		.buf	= buf_0,
-		.len	= 6
-	};
-
-	struct i2c_msg msg_1 = {
-		.addr	= state->config->demod_address,
-		.flags	= 0,
-		.buf	= buf_1,
-		.len	= 2
-	};
-
-	struct i2c_msg msg_r = {
-		.addr	= state->config->demod_address,
-		.flags	= I2C_M_RD,
-		.buf	= buf,
-		.len	= 4
-	};
-
-	tmpaddr = stb0899_reg_offset & 0xff00;
-	if (!(stb0899_reg_offset & 0x8))
-		tmpaddr = stb0899_reg_offset | 0x20;
-
-	buf_1[0] = GETBYTE(tmpaddr, BYTE1);
-	buf_1[1] = GETBYTE(tmpaddr, BYTE0);
-
-	status = i2c_transfer(state->i2c, &msg_0, 1);
-	if (status < 1) {
-		if (status != -ERESTARTSYS)
-			printk(KERN_ERR "%s ERR(1), Device=[0x%04x], Base address=[0x%08x], Offset=[0x%04x], Status=%d\n",
-			       __func__, stb0899_i2cdev, stb0899_base_addr, stb0899_reg_offset, status);
-
-		goto err;
-	}
-
-	/* Dummy	*/
-	status = i2c_transfer(state->i2c, &msg_1, 1);
-	if (status < 1)
-		goto err;
-
-	status = i2c_transfer(state->i2c, &msg_r, 1);
-	if (status < 1)
-		goto err;
-
-	buf_1[0] = GETBYTE(stb0899_reg_offset, BYTE1);
-	buf_1[1] = GETBYTE(stb0899_reg_offset, BYTE0);
-
-	/* Actual	*/
-	status = i2c_transfer(state->i2c, &msg_1, 1);
-	if (status < 1) {
-		if (status != -ERESTARTSYS)
-			printk(KERN_ERR "%s ERR(2), Device=[0x%04x], Base address=[0x%08x], Offset=[0x%04x], Status=%d\n",
-			       __func__, stb0899_i2cdev, stb0899_base_addr, stb0899_reg_offset, status);
-		goto err;
-	}
-
-	status = i2c_transfer(state->i2c, &msg_r, 1);
-	if (status < 1) {
-		if (status != -ERESTARTSYS)
-			printk(KERN_ERR "%s ERR(3), Device=[0x%04x], Base address=[0x%08x], Offset=[0x%04x], Status=%d\n",
-			       __func__, stb0899_i2cdev, stb0899_base_addr, stb0899_reg_offset, status);
-		return status < 0 ? status : -EREMOTEIO;
-	}
-
-	data = MAKEWORD32(buf[3], buf[2], buf[1], buf[0]);
-	if (unlikely(*state->verbose >= FE_DEBUGREG))
-		printk(KERN_DEBUG "%s Device=[0x%04x], Base address=[0x%08x], Offset=[0x%04x], Data=[0x%08x]\n",
-		       __func__, stb0899_i2cdev, stb0899_base_addr, stb0899_reg_offset, data);
-
-	return data;
-
-err:
-	return status < 0 ? status : -EREMOTEIO;
-}
-
-int stb0899_write_s2reg(struct stb0899_state *state,
-			u32 stb0899_i2cdev,
-			u32 stb0899_base_addr,
-			u16 stb0899_reg_offset,
-			u32 stb0899_data)
-{
-	int status;
-
-	/* Base Address Setup	*/
-	u8 buf_0[] = {
-		GETBYTE(stb0899_i2cdev, BYTE1),		/* 0xf3	S2 Base Address (MSB)	*/
-		GETBYTE(stb0899_i2cdev, BYTE0),		/* 0xfc	S2 Base Address (LSB)	*/
-		GETBYTE(stb0899_base_addr, BYTE0),	/* 0x00	Base Address (LSB)	*/
-		GETBYTE(stb0899_base_addr, BYTE1),	/* 0x04	Base Address (LSB)	*/
-		GETBYTE(stb0899_base_addr, BYTE2),	/* 0x00	Base Address (MSB)	*/
-		GETBYTE(stb0899_base_addr, BYTE3),	/* 0x00	Base Address (MSB)	*/
-	};
-	u8 buf_1[] = {
-		0x00,	/* 0xf3	Reg Offset	*/
-		0x00,	/* 0x44	Reg Offset	*/
-		0x00,	/* data			*/
-		0x00,	/* data			*/
-		0x00,	/* data			*/
-		0x00,	/* data			*/
-	};
-
-	struct i2c_msg msg_0 = {
-		.addr	= state->config->demod_address,
-		.flags	= 0,
-		.buf	= buf_0,
-		.len	= 6
-	};
-
-	struct i2c_msg msg_1 = {
-		.addr	= state->config->demod_address,
-		.flags	= 0,
-		.buf	= buf_1,
-		.len	= 6
-	};
-
-	buf_1[0] = GETBYTE(stb0899_reg_offset, BYTE1);
-	buf_1[1] = GETBYTE(stb0899_reg_offset, BYTE0);
-	buf_1[2] = GETBYTE(stb0899_data, BYTE0);
-	buf_1[3] = GETBYTE(stb0899_data, BYTE1);
-	buf_1[4] = GETBYTE(stb0899_data, BYTE2);
-	buf_1[5] = GETBYTE(stb0899_data, BYTE3);
-
-	if (unlikely(*state->verbose >= FE_DEBUGREG))
-		printk(KERN_DEBUG "%s Device=[0x%04x], Base Address=[0x%08x], Offset=[0x%04x], Data=[0x%08x]\n",
-		       __func__, stb0899_i2cdev, stb0899_base_addr, stb0899_reg_offset, stb0899_data);
-
-	status = i2c_transfer(state->i2c, &msg_0, 1);
-	if (unlikely(status < 1)) {
-		if (status != -ERESTARTSYS)
-			printk(KERN_ERR "%s ERR (1), Device=[0x%04x], Base Address=[0x%08x], Offset=[0x%04x], Data=[0x%08x], status=%d\n",
-			       __func__, stb0899_i2cdev, stb0899_base_addr, stb0899_reg_offset, stb0899_data, status);
-		goto err;
-	}
-	status = i2c_transfer(state->i2c, &msg_1, 1);
-	if (unlikely(status < 1)) {
-		if (status != -ERESTARTSYS)
-			printk(KERN_ERR "%s ERR (2), Device=[0x%04x], Base Address=[0x%08x], Offset=[0x%04x], Data=[0x%08x], status=%d\n",
-			       __func__, stb0899_i2cdev, stb0899_base_addr, stb0899_reg_offset, stb0899_data, status);
-
-		return status < 0 ? status : -EREMOTEIO;
-	}
-
-	return 0;
-
-err:
-	return status < 0 ? status : -EREMOTEIO;
-}
-
-int stb0899_read_regs(struct stb0899_state *state, unsigned int reg, u8 *buf, u32 count)
-{
-	int status;
-
-	u8 b0[] = { reg >> 8, reg & 0xff };
-
-	struct i2c_msg msg[] = {
-		{
-			.addr	= state->config->demod_address,
-			.flags	= 0,
-			.buf	= b0,
-			.len	= 2
-		},{
-			.addr	= state->config->demod_address,
-			.flags	= I2C_M_RD,
-			.buf	= buf,
-			.len	= count
-		}
-	};
-
-	status = i2c_transfer(state->i2c, msg, 2);
-	if (status != 2) {
-		if (status != -ERESTARTSYS)
-			printk(KERN_ERR "%s Read error, Reg=[0x%04x], Count=%u, Status=%d\n",
-			       __func__, reg, count, status);
-		goto err;
-	}
-	/*
-	 * Bug ID 9:
-	 * access to 0xf2xx/0xf6xx
-	 * must be followed by read from 0xf2ff/0xf6ff.
-	 */
-	if ((reg != 0xf2ff) && (reg != 0xf6ff) &&
-	    (((reg & 0xff00) == 0xf200) || ((reg & 0xff00) == 0xf600)))
-		_stb0899_read_reg(state, (reg | 0x00ff));
-
-	if (unlikely(*state->verbose >= FE_DEBUGREG)) {
-		int i;
-
-		printk(KERN_DEBUG "%s [0x%04x]:", __func__, reg);
-		for (i = 0; i < count; i++) {
-			printk(" %02x", buf[i]);
-		}
-		printk("\n");
-	}
-
-	return 0;
-err:
-	return status < 0 ? status : -EREMOTEIO;
-}
-
-int stb0899_write_regs(struct stb0899_state *state, unsigned int reg, u8 *data, u32 count)
-{
-	int ret;
-	u8 buf[2 + count];
-	struct i2c_msg i2c_msg = {
-		.addr	= state->config->demod_address,
-		.flags	= 0,
-		.buf	= buf,
-		.len	= 2 + count
-	};
-
-	buf[0] = reg >> 8;
-	buf[1] = reg & 0xff;
-	memcpy(&buf[2], data, count);
-
-	if (unlikely(*state->verbose >= FE_DEBUGREG)) {
-		int i;
-
-		printk(KERN_DEBUG "%s [0x%04x]:", __func__, reg);
-		for (i = 0; i < count; i++)
-			printk(" %02x", data[i]);
-		printk("\n");
-	}
-	ret = i2c_transfer(state->i2c, &i2c_msg, 1);
-
-	/*
-	 * Bug ID 9:
-	 * access to 0xf2xx/0xf6xx
-	 * must be followed by read from 0xf2ff/0xf6ff.
-	 */
-	if ((((reg & 0xff00) == 0xf200) || ((reg & 0xff00) == 0xf600)))
-		stb0899_read_reg(state, (reg | 0x00ff));
-
-	if (ret != 1) {
-		if (ret != -ERESTARTSYS)
-			dprintk(state->verbose, FE_ERROR, 1, "Reg=[0x%04x], Data=[0x%02x ...], Count=%u, Status=%d",
-				reg, data[0], count, ret);
-		return ret < 0 ? ret : -EREMOTEIO;
-	}
-
-	return 0;
-}
-
-int stb0899_write_reg(struct stb0899_state *state, unsigned int reg, u8 data)
-{
-	return stb0899_write_regs(state, reg, &data, 1);
-}
-
-/*
- * stb0899_get_mclk
- * Get STB0899 master clock frequency
- * ExtClk: external clock frequency (Hz)
- */
-static u32 stb0899_get_mclk(struct stb0899_state *state)
-{
-	u32 mclk = 0, div = 0;
-
-	div = stb0899_read_reg(state, STB0899_NCOARSE);
-	mclk = (div + 1) * state->config->xtal_freq / 6;
-	dprintk(state->verbose, FE_DEBUG, 1, "div=%d, mclk=%d", div, mclk);
-
-	return mclk;
-}
-
-/*
- * stb0899_set_mclk
- * Set STB0899 master Clock frequency
- * Mclk: demodulator master clock
- * ExtClk: external clock frequency (Hz)
- */
-static void stb0899_set_mclk(struct stb0899_state *state, u32 Mclk)
-{
-	struct stb0899_internal *internal = &state->internal;
-	u8 mdiv = 0;
-
-	dprintk(state->verbose, FE_DEBUG, 1, "state->config=%p", state->config);
-	mdiv = ((6 * Mclk) / state->config->xtal_freq) - 1;
-	dprintk(state->verbose, FE_DEBUG, 1, "mdiv=%d", mdiv);
-
-	stb0899_write_reg(state, STB0899_NCOARSE, mdiv);
-	internal->master_clk = stb0899_get_mclk(state);
-
-	dprintk(state->verbose, FE_DEBUG, 1, "MasterCLOCK=%d", internal->master_clk);
-}
-
-static int stb0899_postproc(struct stb0899_state *state, u8 ctl, int enable)
-{
-	struct stb0899_config *config		= state->config;
-	const struct stb0899_postproc *postproc	= config->postproc;
-
-	/* post process event */
-	if (postproc) {
-		if (enable) {
-			if (postproc[ctl].level == STB0899_GPIOPULLUP)
-				stb0899_write_reg(state, postproc[ctl].gpio, 0x02);
-			else
-				stb0899_write_reg(state, postproc[ctl].gpio, 0x82);
-		} else {
-			if (postproc[ctl].level == STB0899_GPIOPULLUP)
-				stb0899_write_reg(state, postproc[ctl].gpio, 0x82);
-			else
-				stb0899_write_reg(state, postproc[ctl].gpio, 0x02);
-		}
-	}
-	return 0;
-}
-
-static void stb0899_release(struct dvb_frontend *fe)
-{
-	struct stb0899_state *state = fe->demodulator_priv;
-
-	dprintk(state->verbose, FE_DEBUG, 1, "Release Frontend");
-	/* post process event */
-	stb0899_postproc(state, STB0899_POSTPROC_GPIO_POWER, 0);
-	kfree(state);
-}
-
-/*
- * stb0899_get_alpha
- * return: rolloff
- */
-static int stb0899_get_alpha(struct stb0899_state *state)
-{
-	u8 mode_coeff;
-
-	mode_coeff = stb0899_read_reg(state, STB0899_DEMOD);
-
-	if (STB0899_GETFIELD(MODECOEFF, mode_coeff) == 1)
-		return 20;
-	else
-		return 35;
-}
-
-/*
- * stb0899_init_calc
- */
-static void stb0899_init_calc(struct stb0899_state *state)
-{
-	struct stb0899_internal *internal = &state->internal;
-	int master_clk;
-	u8 agc[2];
-	u32 reg;
-
-	/* Read registers (in burst mode)	*/
-	stb0899_read_regs(state, STB0899_AGC1REF, agc, 2); /* AGC1R and AGC2O	*/
-
-	/* Initial calculations	*/
-	master_clk			= stb0899_get_mclk(state);
-	internal->t_agc1		= 0;
-	internal->t_agc2		= 0;
-	internal->master_clk		= master_clk;
-	internal->mclk			= master_clk / 65536L;
-	internal->rolloff		= stb0899_get_alpha(state);
-
-	/* DVBS2 Initial calculations	*/
-	/* Set AGC value to the middle	*/
-	internal->agc_gain		= 8154;
-	reg = STB0899_READ_S2REG(STB0899_S2DEMOD, IF_AGC_CNTRL);
-	STB0899_SETFIELD_VAL(IF_GAIN_INIT, reg, internal->agc_gain);
-	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_IF_AGC_CNTRL, STB0899_OFF0_IF_AGC_CNTRL, reg);
-
-	reg = STB0899_READ_S2REG(STB0899_S2DEMOD, RRC_ALPHA);
-	internal->rrc_alpha		= STB0899_GETFIELD(RRC_ALPHA, reg);
-
-	internal->center_freq		= 0;
-	internal->av_frame_coarse	= 10;
-	internal->av_frame_fine		= 20;
-	internal->step_size		= 2;
-/*
-	if ((pParams->SpectralInv == FE_IQ_NORMAL) || (pParams->SpectralInv == FE_IQ_AUTO))
-		pParams->IQLocked = 0;
-	else
-		pParams->IQLocked = 1;
-*/
-}
-
-static int stb0899_wait_diseqc_fifo_empty(struct stb0899_state *state, int timeout)
-{
-	u8 reg = 0;
-	unsigned long start = jiffies;
-
-	while (1) {
-		reg = stb0899_read_reg(state, STB0899_DISSTATUS);
-		if (!STB0899_GETFIELD(FIFOFULL, reg))
-			break;
-		if ((jiffies - start) > timeout) {
-			dprintk(state->verbose, FE_ERROR, 1, "timed out !!");
-			return -ETIMEDOUT;
-		}
-	}
-
-	return 0;
-}
-
-static int stb0899_send_diseqc_msg(struct dvb_frontend *fe, struct dvb_diseqc_master_cmd *cmd)
-{
-	struct stb0899_state *state = fe->demodulator_priv;
-	u8 reg, i;
-
-	if (cmd->msg_len > 8)
-		return -EINVAL;
-
-	/* enable FIFO precharge	*/
-	reg = stb0899_read_reg(state, STB0899_DISCNTRL1);
-	STB0899_SETFIELD_VAL(DISPRECHARGE, reg, 1);
-	stb0899_write_reg(state, STB0899_DISCNTRL1, reg);
-	for (i = 0; i < cmd->msg_len; i++) {
-		/* wait for FIFO empty	*/
-		if (stb0899_wait_diseqc_fifo_empty(state, 100) < 0)
-			return -ETIMEDOUT;
-
-		stb0899_write_reg(state, STB0899_DISFIFO, cmd->msg[i]);
-	}
-	reg = stb0899_read_reg(state, STB0899_DISCNTRL1);
-	STB0899_SETFIELD_VAL(DISPRECHARGE, reg, 0);
-	stb0899_write_reg(state, STB0899_DISCNTRL1, reg);
-	msleep(100);
-	return 0;
-}
-
-static int stb0899_wait_diseqc_rxidle(struct stb0899_state *state, int timeout)
-{
-	u8 reg = 0;
-	unsigned long start = jiffies;
-
-	while (!STB0899_GETFIELD(RXEND, reg)) {
-		reg = stb0899_read_reg(state, STB0899_DISRX_ST0);
-		if (jiffies - start > timeout) {
-			dprintk(state->verbose, FE_ERROR, 1, "timed out!!");
-			return -ETIMEDOUT;
-		}
-		msleep(10);
-	}
-
-	return 0;
-}
-
-static int stb0899_recv_slave_reply(struct dvb_frontend *fe, struct dvb_diseqc_slave_reply *reply)
-{
-	struct stb0899_state *state = fe->demodulator_priv;
-	u8 reg, length = 0, i;
-	int result;
-
-	if (stb0899_wait_diseqc_rxidle(state, 100) < 0)
-		return -ETIMEDOUT;
-
-	reg = stb0899_read_reg(state, STB0899_DISRX_ST0);
-	if (STB0899_GETFIELD(RXEND, reg)) {
-
-		reg = stb0899_read_reg(state, STB0899_DISRX_ST1);
-		length = STB0899_GETFIELD(FIFOBYTENBR, reg);
-
-		if (length > sizeof (reply->msg)) {
-			result = -EOVERFLOW;
-			goto exit;
-		}
-		reply->msg_len = length;
-
-		/* extract data */
-		for (i = 0; i < length; i++)
-			reply->msg[i] = stb0899_read_reg(state, STB0899_DISFIFO);
-	}
-
-	return 0;
-exit:
-
-	return result;
-}
-
-static int stb0899_wait_diseqc_txidle(struct stb0899_state *state, int timeout)
-{
-	u8 reg = 0;
-	unsigned long start = jiffies;
-
-	while (!STB0899_GETFIELD(TXIDLE, reg)) {
-		reg = stb0899_read_reg(state, STB0899_DISSTATUS);
-		if (jiffies - start > timeout) {
-			dprintk(state->verbose, FE_ERROR, 1, "timed out!!");
-			return -ETIMEDOUT;
-		}
-		msleep(10);
-	}
-	return 0;
-}
-
-static int stb0899_send_diseqc_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t burst)
-{
-	struct stb0899_state *state = fe->demodulator_priv;
-	u8 reg, old_state;
-
-	/* wait for diseqc idle	*/
-	if (stb0899_wait_diseqc_txidle(state, 100) < 0)
-		return -ETIMEDOUT;
-
-	reg = stb0899_read_reg(state, STB0899_DISCNTRL1);
-	old_state = reg;
-	/* set to burst mode	*/
-	STB0899_SETFIELD_VAL(DISEQCMODE, reg, 0x03);
-	STB0899_SETFIELD_VAL(DISPRECHARGE, reg, 0x01);
-	stb0899_write_reg(state, STB0899_DISCNTRL1, reg);
-	switch (burst) {
-	case SEC_MINI_A:
-		/* unmodulated	*/
-		stb0899_write_reg(state, STB0899_DISFIFO, 0x00);
-		break;
-	case SEC_MINI_B:
-		/* modulated	*/
-		stb0899_write_reg(state, STB0899_DISFIFO, 0xff);
-		break;
-	}
-	reg = stb0899_read_reg(state, STB0899_DISCNTRL1);
-	STB0899_SETFIELD_VAL(DISPRECHARGE, reg, 0x00);
-	stb0899_write_reg(state, STB0899_DISCNTRL1, reg);
-	/* wait for diseqc idle	*/
-	if (stb0899_wait_diseqc_txidle(state, 100) < 0)
-		return -ETIMEDOUT;
-
-	/* restore state	*/
-	stb0899_write_reg(state, STB0899_DISCNTRL1, old_state);
-
-	return 0;
-}
-
-static int stb0899_diseqc_init(struct stb0899_state *state)
-{
-/*
-	struct dvb_diseqc_slave_reply rx_data;
-*/
-	u8 f22_tx, reg;
-
-	u32 mclk, tx_freq = 22000;/* count = 0, i; */
-	reg = stb0899_read_reg(state, STB0899_DISCNTRL2);
-	STB0899_SETFIELD_VAL(ONECHIP_TRX, reg, 0);
-	stb0899_write_reg(state, STB0899_DISCNTRL2, reg);
-
-	/* disable Tx spy	*/
-	reg = stb0899_read_reg(state, STB0899_DISCNTRL1);
-	STB0899_SETFIELD_VAL(DISEQCRESET, reg, 1);
-	stb0899_write_reg(state, STB0899_DISCNTRL1, reg);
-
-	reg = stb0899_read_reg(state, STB0899_DISCNTRL1);
-	STB0899_SETFIELD_VAL(DISEQCRESET, reg, 0);
-	stb0899_write_reg(state, STB0899_DISCNTRL1, reg);
-
-	mclk = stb0899_get_mclk(state);
-	f22_tx = mclk / (tx_freq * 32);
-	stb0899_write_reg(state, STB0899_DISF22, f22_tx); /* DiSEqC Tx freq	*/
-	state->rx_freq = 20000;
-
-	return 0;
-}
-
-static int stb0899_sleep(struct dvb_frontend *fe)
-{
-	struct stb0899_state *state = fe->demodulator_priv;
-/*
-	u8 reg;
-*/
-	dprintk(state->verbose, FE_DEBUG, 1, "Going to Sleep .. (Really tired .. :-))");
-	/* post process event */
-	stb0899_postproc(state, STB0899_POSTPROC_GPIO_POWER, 0);
-
-	return 0;
-}
-
-static int stb0899_wakeup(struct dvb_frontend *fe)
-{
-	int rc;
-	struct stb0899_state *state = fe->demodulator_priv;
-
-	if ((rc = stb0899_write_reg(state, STB0899_SYNTCTRL, STB0899_SELOSCI)))
-		return rc;
-	/* Activate all clocks; DVB-S2 registers are inaccessible otherwise. */
-	if ((rc = stb0899_write_reg(state, STB0899_STOPCLK1, 0x00)))
-		return rc;
-	if ((rc = stb0899_write_reg(state, STB0899_STOPCLK2, 0x00)))
-		return rc;
-
-	/* post process event */
-	stb0899_postproc(state, STB0899_POSTPROC_GPIO_POWER, 1);
-
-	return 0;
-}
-
-static int stb0899_init(struct dvb_frontend *fe)
-{
-	int i;
-	struct stb0899_state *state = fe->demodulator_priv;
-	struct stb0899_config *config = state->config;
-
-	dprintk(state->verbose, FE_DEBUG, 1, "Initializing STB0899 ... ");
-
-	/* init device		*/
-	dprintk(state->verbose, FE_DEBUG, 1, "init device");
-	for (i = 0; config->init_dev[i].address != 0xffff; i++)
-		stb0899_write_reg(state, config->init_dev[i].address, config->init_dev[i].data);
-
-	dprintk(state->verbose, FE_DEBUG, 1, "init S2 demod");
-	/* init S2 demod	*/
-	for (i = 0; config->init_s2_demod[i].offset != 0xffff; i++)
-		stb0899_write_s2reg(state, STB0899_S2DEMOD,
-				    config->init_s2_demod[i].base_address,
-				    config->init_s2_demod[i].offset,
-				    config->init_s2_demod[i].data);
-
-	dprintk(state->verbose, FE_DEBUG, 1, "init S1 demod");
-	/* init S1 demod	*/
-	for (i = 0; config->init_s1_demod[i].address != 0xffff; i++)
-		stb0899_write_reg(state, config->init_s1_demod[i].address, config->init_s1_demod[i].data);
-
-	dprintk(state->verbose, FE_DEBUG, 1, "init S2 FEC");
-	/* init S2 fec		*/
-	for (i = 0; config->init_s2_fec[i].offset != 0xffff; i++)
-		stb0899_write_s2reg(state, STB0899_S2FEC,
-				    config->init_s2_fec[i].base_address,
-				    config->init_s2_fec[i].offset,
-				    config->init_s2_fec[i].data);
-
-	dprintk(state->verbose, FE_DEBUG, 1, "init TST");
-	/* init test		*/
-	for (i = 0; config->init_tst[i].address != 0xffff; i++)
-		stb0899_write_reg(state, config->init_tst[i].address, config->init_tst[i].data);
-
-	stb0899_init_calc(state);
-	stb0899_diseqc_init(state);
-
-	return 0;
-}
-
-static int stb0899_table_lookup(const struct stb0899_tab *tab, int max, int val)
-{
-	int res = 0;
-	int min = 0, med;
-
-	if (val < tab[min].read)
-		res = tab[min].real;
-	else if (val >= tab[max].read)
-		res = tab[max].real;
-	else {
-		while ((max - min) > 1) {
-			med = (max + min) / 2;
-			if (val >= tab[min].read && val < tab[med].read)
-				max = med;
-			else
-				min = med;
-		}
-		res = ((val - tab[min].read) *
-		       (tab[max].real - tab[min].real) /
-		       (tab[max].read - tab[min].read)) +
-			tab[min].real;
-	}
-
-	return res;
-}
-
-static int stb0899_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
-{
-	struct stb0899_state *state		= fe->demodulator_priv;
-	struct stb0899_internal *internal	= &state->internal;
-
-	int val;
-	u32 reg;
-	*strength = 0;
-	switch (state->delsys) {
-	case SYS_DVBS:
-	case SYS_DSS:
-		if (internal->lock) {
-			reg  = stb0899_read_reg(state, STB0899_VSTATUS);
-			if (STB0899_GETFIELD(VSTATUS_LOCKEDVIT, reg)) {
-
-				reg = stb0899_read_reg(state, STB0899_AGCIQIN);
-				val = (s32)(s8)STB0899_GETFIELD(AGCIQVALUE, reg);
-
-				*strength = stb0899_table_lookup(stb0899_dvbsrf_tab, ARRAY_SIZE(stb0899_dvbsrf_tab) - 1, val);
-				*strength += 750;
-				dprintk(state->verbose, FE_DEBUG, 1, "AGCIQVALUE = 0x%02x, C = %d * 0.1 dBm",
-					val & 0xff, *strength);
-			}
-		}
-		break;
-	case SYS_DVBS2:
-		if (internal->lock) {
-			reg = STB0899_READ_S2REG(STB0899_S2DEMOD, IF_AGC_GAIN);
-			val = STB0899_GETFIELD(IF_AGC_GAIN, reg);
-
-			*strength = stb0899_table_lookup(stb0899_dvbs2rf_tab, ARRAY_SIZE(stb0899_dvbs2rf_tab) - 1, val);
-			*strength += 950;
-			dprintk(state->verbose, FE_DEBUG, 1, "IF_AGC_GAIN = 0x%04x, C = %d * 0.1 dBm",
-				val & 0x3fff, *strength);
-		}
-		break;
-	default:
-		dprintk(state->verbose, FE_DEBUG, 1, "Unsupported delivery system");
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int stb0899_read_snr(struct dvb_frontend *fe, u16 *snr)
-{
-	struct stb0899_state *state		= fe->demodulator_priv;
-	struct stb0899_internal *internal	= &state->internal;
-
-	unsigned int val, quant, quantn = -1, est, estn = -1;
-	u8 buf[2];
-	u32 reg;
-
-	*snr = 0;
-	reg  = stb0899_read_reg(state, STB0899_VSTATUS);
-	switch (state->delsys) {
-	case SYS_DVBS:
-	case SYS_DSS:
-		if (internal->lock) {
-			if (STB0899_GETFIELD(VSTATUS_LOCKEDVIT, reg)) {
-
-				stb0899_read_regs(state, STB0899_NIRM, buf, 2);
-				val = MAKEWORD16(buf[0], buf[1]);
-
-				*snr = stb0899_table_lookup(stb0899_cn_tab, ARRAY_SIZE(stb0899_cn_tab) - 1, val);
-				dprintk(state->verbose, FE_DEBUG, 1, "NIR = 0x%02x%02x = %u, C/N = %d * 0.1 dBm\n",
-					buf[0], buf[1], val, *snr);
-			}
-		}
-		break;
-	case SYS_DVBS2:
-		if (internal->lock) {
-			reg = STB0899_READ_S2REG(STB0899_S2DEMOD, UWP_CNTRL1);
-			quant = STB0899_GETFIELD(UWP_ESN0_QUANT, reg);
-			reg = STB0899_READ_S2REG(STB0899_S2DEMOD, UWP_STAT2);
-			est = STB0899_GETFIELD(ESN0_EST, reg);
-			if (est == 1)
-				val = 301; /* C/N = 30.1 dB */
-			else if (est == 2)
-				val = 270; /* C/N = 27.0 dB */
-			else {
-				/* quantn = 100 * log(quant^2) */
-				quantn = stb0899_table_lookup(stb0899_quant_tab, ARRAY_SIZE(stb0899_quant_tab) - 1, quant * 100);
-				/* estn = 100 * log(est) */
-				estn = stb0899_table_lookup(stb0899_est_tab, ARRAY_SIZE(stb0899_est_tab) - 1, est);
-				/* snr(dBm/10) = -10*(log(est)-log(quant^2)) => snr(dBm/10) = (100*log(quant^2)-100*log(est))/10 */
-				val = (quantn - estn) / 10;
-			}
-			*snr = val;
-			dprintk(state->verbose, FE_DEBUG, 1, "Es/N0 quant = %d (%d) estimate = %u (%d), C/N = %d * 0.1 dBm",
-				quant, quantn, est, estn, val);
-		}
-		break;
-	default:
-		dprintk(state->verbose, FE_DEBUG, 1, "Unsupported delivery system");
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int stb0899_read_status(struct dvb_frontend *fe, enum fe_status *status)
-{
-	struct stb0899_state *state		= fe->demodulator_priv;
-	struct stb0899_internal *internal	= &state->internal;
-	u8 reg;
-	*status = 0;
-
-	switch (state->delsys) {
-	case SYS_DVBS:
-	case SYS_DSS:
-		dprintk(state->verbose, FE_DEBUG, 1, "Delivery system DVB-S/DSS");
-		if (internal->lock) {
-			reg  = stb0899_read_reg(state, STB0899_VSTATUS);
-			if (STB0899_GETFIELD(VSTATUS_LOCKEDVIT, reg)) {
-				dprintk(state->verbose, FE_DEBUG, 1, "--------> FE_HAS_CARRIER | FE_HAS_LOCK");
-				*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_LOCK;
-
-				reg = stb0899_read_reg(state, STB0899_PLPARM);
-				if (STB0899_GETFIELD(VITCURPUN, reg)) {
-					dprintk(state->verbose, FE_DEBUG, 1, "--------> FE_HAS_VITERBI | FE_HAS_SYNC");
-					*status |= FE_HAS_VITERBI | FE_HAS_SYNC;
-					/* post process event */
-					stb0899_postproc(state, STB0899_POSTPROC_GPIO_LOCK, 1);
-				}
-			}
-		}
-		break;
-	case SYS_DVBS2:
-		dprintk(state->verbose, FE_DEBUG, 1, "Delivery system DVB-S2");
-		if (internal->lock) {
-			reg = STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_STAT2);
-			if (STB0899_GETFIELD(UWP_LOCK, reg) && STB0899_GETFIELD(CSM_LOCK, reg)) {
-				*status |= FE_HAS_CARRIER;
-				dprintk(state->verbose, FE_DEBUG, 1,
-					"UWP & CSM Lock ! ---> DVB-S2 FE_HAS_CARRIER");
-
-				reg = stb0899_read_reg(state, STB0899_CFGPDELSTATUS1);
-				if (STB0899_GETFIELD(CFGPDELSTATUS_LOCK, reg)) {
-					*status |= FE_HAS_LOCK;
-					dprintk(state->verbose, FE_DEBUG, 1,
-						"Packet Delineator Locked ! -----> DVB-S2 FE_HAS_LOCK");
-
-				}
-				if (STB0899_GETFIELD(CONTINUOUS_STREAM, reg)) {
-					*status |= FE_HAS_VITERBI;
-					dprintk(state->verbose, FE_DEBUG, 1,
-						"Packet Delineator found VITERBI ! -----> DVB-S2 FE_HAS_VITERBI");
-				}
-				if (STB0899_GETFIELD(ACCEPTED_STREAM, reg)) {
-					*status |= FE_HAS_SYNC;
-					dprintk(state->verbose, FE_DEBUG, 1,
-						"Packet Delineator found SYNC ! -----> DVB-S2 FE_HAS_SYNC");
-					/* post process event */
-					stb0899_postproc(state, STB0899_POSTPROC_GPIO_LOCK, 1);
-				}
-			}
-		}
-		break;
-	default:
-		dprintk(state->verbose, FE_DEBUG, 1, "Unsupported delivery system");
-		return -EINVAL;
-	}
-	return 0;
-}
-
-/*
- * stb0899_get_error
- * viterbi error for DVB-S/DSS
- * packet error for DVB-S2
- * Bit Error Rate or Packet Error Rate * 10 ^ 7
- */
-static int stb0899_read_ber(struct dvb_frontend *fe, u32 *ber)
-{
-	struct stb0899_state *state		= fe->demodulator_priv;
-	struct stb0899_internal *internal	= &state->internal;
-
-	u8  lsb, msb;
-
-	*ber = 0;
-
-	switch (state->delsys) {
-	case SYS_DVBS:
-	case SYS_DSS:
-		if (internal->lock) {
-			lsb = stb0899_read_reg(state, STB0899_ECNT1L);
-			msb = stb0899_read_reg(state, STB0899_ECNT1M);
-			*ber = MAKEWORD16(msb, lsb);
-			/* Viterbi Check	*/
-			if (STB0899_GETFIELD(VSTATUS_PRFVIT, internal->v_status)) {
-				/* Error Rate		*/
-				*ber *= 9766;
-				/* ber = ber * 10 ^ 7	*/
-				*ber /= (-1 + (1 << (2 * STB0899_GETFIELD(NOE, internal->err_ctrl))));
-				*ber /= 8;
-			}
-		}
-		break;
-	case SYS_DVBS2:
-		if (internal->lock) {
-			lsb = stb0899_read_reg(state, STB0899_ECNT1L);
-			msb = stb0899_read_reg(state, STB0899_ECNT1M);
-			*ber = MAKEWORD16(msb, lsb);
-			/* ber = ber * 10 ^ 7	*/
-			*ber *= 10000000;
-			*ber /= (-1 + (1 << (4 + 2 * STB0899_GETFIELD(NOE, internal->err_ctrl))));
-		}
-		break;
-	default:
-		dprintk(state->verbose, FE_DEBUG, 1, "Unsupported delivery system");
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int stb0899_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
-{
-	struct stb0899_state *state = fe->demodulator_priv;
-
-	switch (voltage) {
-	case SEC_VOLTAGE_13:
-		stb0899_write_reg(state, STB0899_GPIO00CFG, 0x82);
-		stb0899_write_reg(state, STB0899_GPIO01CFG, 0x02);
-		stb0899_write_reg(state, STB0899_GPIO02CFG, 0x00);
-		break;
-	case SEC_VOLTAGE_18:
-		stb0899_write_reg(state, STB0899_GPIO00CFG, 0x02);
-		stb0899_write_reg(state, STB0899_GPIO01CFG, 0x02);
-		stb0899_write_reg(state, STB0899_GPIO02CFG, 0x82);
-		break;
-	case SEC_VOLTAGE_OFF:
-		stb0899_write_reg(state, STB0899_GPIO00CFG, 0x82);
-		stb0899_write_reg(state, STB0899_GPIO01CFG, 0x82);
-		stb0899_write_reg(state, STB0899_GPIO02CFG, 0x82);
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int stb0899_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
-{
-	struct stb0899_state *state = fe->demodulator_priv;
-	struct stb0899_internal *internal = &state->internal;
-
-	u8 div, reg;
-
-	/* wait for diseqc idle	*/
-	if (stb0899_wait_diseqc_txidle(state, 100) < 0)
-		return -ETIMEDOUT;
-
-	switch (tone) {
-	case SEC_TONE_ON:
-		div = (internal->master_clk / 100) / 5632;
-		div = (div + 5) / 10;
-		stb0899_write_reg(state, STB0899_DISEQCOCFG, 0x66);
-		reg = stb0899_read_reg(state, STB0899_ACRPRESC);
-		STB0899_SETFIELD_VAL(ACRPRESC, reg, 0x03);
-		stb0899_write_reg(state, STB0899_ACRPRESC, reg);
-		stb0899_write_reg(state, STB0899_ACRDIV1, div);
-		break;
-	case SEC_TONE_OFF:
-		stb0899_write_reg(state, STB0899_DISEQCOCFG, 0x20);
-		break;
-	default:
-		return -EINVAL;
-	}
-	return 0;
-}
-
-int stb0899_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
-{
-	int i2c_stat;
-	struct stb0899_state *state = fe->demodulator_priv;
-
-	i2c_stat = stb0899_read_reg(state, STB0899_I2CRPT);
-	if (i2c_stat < 0)
-		goto err;
-
-	if (enable) {
-		dprintk(state->verbose, FE_DEBUG, 1, "Enabling I2C Repeater ...");
-		i2c_stat |=  STB0899_I2CTON;
-		if (stb0899_write_reg(state, STB0899_I2CRPT, i2c_stat) < 0)
-			goto err;
-	} else {
-		dprintk(state->verbose, FE_DEBUG, 1, "Disabling I2C Repeater ...");
-		i2c_stat &= ~STB0899_I2CTON;
-		if (stb0899_write_reg(state, STB0899_I2CRPT, i2c_stat) < 0)
-			goto err;
-	}
-	return 0;
-err:
-	dprintk(state->verbose, FE_ERROR, 1, "I2C Repeater control failed");
-	return -EREMOTEIO;
-}
-
-
-static inline void CONVERT32(u32 x, char *str)
-{
-	*str++	= (x >> 24) & 0xff;
-	*str++	= (x >> 16) & 0xff;
-	*str++	= (x >>  8) & 0xff;
-	*str++	= (x >>  0) & 0xff;
-	*str	= '\0';
-}
-
-int stb0899_get_dev_id(struct stb0899_state *state)
-{
-	u8 chip_id, release;
-	u16 id;
-	u32 demod_ver = 0, fec_ver = 0;
-	char demod_str[5] = { 0 };
-	char fec_str[5] = { 0 };
-
-	id = stb0899_read_reg(state, STB0899_DEV_ID);
-	dprintk(state->verbose, FE_DEBUG, 1, "ID reg=[0x%02x]", id);
-	chip_id = STB0899_GETFIELD(CHIP_ID, id);
-	release = STB0899_GETFIELD(CHIP_REL, id);
-
-	dprintk(state->verbose, FE_ERROR, 1, "Device ID=[%d], Release=[%d]",
-		chip_id, release);
-
-	CONVERT32(STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_CORE_ID), (char *)&demod_str);
-
-	demod_ver = STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_VERSION_ID);
-	dprintk(state->verbose, FE_ERROR, 1, "Demodulator Core ID=[%s], Version=[%d]", (char *) &demod_str, demod_ver);
-	CONVERT32(STB0899_READ_S2REG(STB0899_S2FEC, FEC_CORE_ID_REG), (char *)&fec_str);
-	fec_ver = STB0899_READ_S2REG(STB0899_S2FEC, FEC_VER_ID_REG);
-	if (! (chip_id > 0)) {
-		dprintk(state->verbose, FE_ERROR, 1, "couldn't find a STB 0899");
-
-		return -ENODEV;
-	}
-	dprintk(state->verbose, FE_ERROR, 1, "FEC Core ID=[%s], Version=[%d]", (char*) &fec_str, fec_ver);
-
-	return 0;
-}
-
-static void stb0899_set_delivery(struct stb0899_state *state)
-{
-	u8 reg;
-	u8 stop_clk[2];
-
-	stop_clk[0] = stb0899_read_reg(state, STB0899_STOPCLK1);
-	stop_clk[1] = stb0899_read_reg(state, STB0899_STOPCLK2);
-
-	switch (state->delsys) {
-	case SYS_DVBS:
-		dprintk(state->verbose, FE_DEBUG, 1, "Delivery System -- DVB-S");
-		/* FECM/Viterbi ON	*/
-		reg = stb0899_read_reg(state, STB0899_FECM);
-		STB0899_SETFIELD_VAL(FECM_RSVD0, reg, 0);
-		STB0899_SETFIELD_VAL(FECM_VITERBI_ON, reg, 1);
-		stb0899_write_reg(state, STB0899_FECM, reg);
-
-		stb0899_write_reg(state, STB0899_RSULC, 0xb1);
-		stb0899_write_reg(state, STB0899_TSULC, 0x40);
-		stb0899_write_reg(state, STB0899_RSLLC, 0x42);
-		stb0899_write_reg(state, STB0899_TSLPL, 0x12);
-
-		reg = stb0899_read_reg(state, STB0899_TSTRES);
-		STB0899_SETFIELD_VAL(FRESLDPC, reg, 1);
-		stb0899_write_reg(state, STB0899_TSTRES, reg);
-
-		STB0899_SETFIELD_VAL(STOP_CHK8PSK, stop_clk[0], 1);
-		STB0899_SETFIELD_VAL(STOP_CKFEC108, stop_clk[0], 1);
-		STB0899_SETFIELD_VAL(STOP_CKFEC216, stop_clk[0], 1);
-
-		STB0899_SETFIELD_VAL(STOP_CKPKDLIN108, stop_clk[1], 1);
-		STB0899_SETFIELD_VAL(STOP_CKPKDLIN216, stop_clk[1], 1);
-
-		STB0899_SETFIELD_VAL(STOP_CKINTBUF216, stop_clk[0], 1);
-		STB0899_SETFIELD_VAL(STOP_CKCORE216, stop_clk[0], 0);
-
-		STB0899_SETFIELD_VAL(STOP_CKS2DMD108, stop_clk[1], 1);
-		break;
-	case SYS_DVBS2:
-		/* FECM/Viterbi OFF	*/
-		reg = stb0899_read_reg(state, STB0899_FECM);
-		STB0899_SETFIELD_VAL(FECM_RSVD0, reg, 0);
-		STB0899_SETFIELD_VAL(FECM_VITERBI_ON, reg, 0);
-		stb0899_write_reg(state, STB0899_FECM, reg);
-
-		stb0899_write_reg(state, STB0899_RSULC, 0xb1);
-		stb0899_write_reg(state, STB0899_TSULC, 0x42);
-		stb0899_write_reg(state, STB0899_RSLLC, 0x40);
-		stb0899_write_reg(state, STB0899_TSLPL, 0x02);
-
-		reg = stb0899_read_reg(state, STB0899_TSTRES);
-		STB0899_SETFIELD_VAL(FRESLDPC, reg, 0);
-		stb0899_write_reg(state, STB0899_TSTRES, reg);
-
-		STB0899_SETFIELD_VAL(STOP_CHK8PSK, stop_clk[0], 1);
-		STB0899_SETFIELD_VAL(STOP_CKFEC108, stop_clk[0], 0);
-		STB0899_SETFIELD_VAL(STOP_CKFEC216, stop_clk[0], 0);
-
-		STB0899_SETFIELD_VAL(STOP_CKPKDLIN108, stop_clk[1], 0);
-		STB0899_SETFIELD_VAL(STOP_CKPKDLIN216, stop_clk[1], 0);
-
-		STB0899_SETFIELD_VAL(STOP_CKINTBUF216, stop_clk[0], 0);
-		STB0899_SETFIELD_VAL(STOP_CKCORE216, stop_clk[0], 0);
-
-		STB0899_SETFIELD_VAL(STOP_CKS2DMD108, stop_clk[1], 0);
-		break;
-	case SYS_DSS:
-		/* FECM/Viterbi ON	*/
-		reg = stb0899_read_reg(state, STB0899_FECM);
-		STB0899_SETFIELD_VAL(FECM_RSVD0, reg, 1);
-		STB0899_SETFIELD_VAL(FECM_VITERBI_ON, reg, 1);
-		stb0899_write_reg(state, STB0899_FECM, reg);
-
-		stb0899_write_reg(state, STB0899_RSULC, 0xa1);
-		stb0899_write_reg(state, STB0899_TSULC, 0x61);
-		stb0899_write_reg(state, STB0899_RSLLC, 0x42);
-
-		reg = stb0899_read_reg(state, STB0899_TSTRES);
-		STB0899_SETFIELD_VAL(FRESLDPC, reg, 1);
-		stb0899_write_reg(state, STB0899_TSTRES, reg);
-
-		STB0899_SETFIELD_VAL(STOP_CHK8PSK, stop_clk[0], 1);
-		STB0899_SETFIELD_VAL(STOP_CKFEC108, stop_clk[0], 1);
-		STB0899_SETFIELD_VAL(STOP_CKFEC216, stop_clk[0], 1);
-
-		STB0899_SETFIELD_VAL(STOP_CKPKDLIN108, stop_clk[1], 1);
-		STB0899_SETFIELD_VAL(STOP_CKPKDLIN216, stop_clk[1], 1);
-
-		STB0899_SETFIELD_VAL(STOP_CKCORE216, stop_clk[0], 0);
-
-		STB0899_SETFIELD_VAL(STOP_CKS2DMD108, stop_clk[1], 1);
-		break;
-	default:
-		dprintk(state->verbose, FE_ERROR, 1, "Unsupported delivery system");
-		break;
-	}
-	STB0899_SETFIELD_VAL(STOP_CKADCI108, stop_clk[0], 0);
-	stb0899_write_regs(state, STB0899_STOPCLK1, stop_clk, 2);
-}
-
-/*
- * stb0899_set_iterations
- * set the LDPC iteration scale function
- */
-static void stb0899_set_iterations(struct stb0899_state *state)
-{
-	struct stb0899_internal *internal = &state->internal;
-	struct stb0899_config *config = state->config;
-
-	s32 iter_scale;
-	u32 reg;
-
-	iter_scale = 17 * (internal->master_clk / 1000);
-	iter_scale += 410000;
-	iter_scale /= (internal->srate / 1000000);
-	iter_scale /= 1000;
-
-	if (iter_scale > config->ldpc_max_iter)
-		iter_scale = config->ldpc_max_iter;
-
-	reg = STB0899_READ_S2REG(STB0899_S2FEC, MAX_ITER);
-	STB0899_SETFIELD_VAL(MAX_ITERATIONS, reg, iter_scale);
-	stb0899_write_s2reg(state, STB0899_S2FEC, STB0899_BASE_MAX_ITER, STB0899_OFF0_MAX_ITER, reg);
-}
-
-static enum dvbfe_search stb0899_search(struct dvb_frontend *fe)
-{
-	struct stb0899_state *state = fe->demodulator_priv;
-	struct stb0899_params *i_params = &state->params;
-	struct stb0899_internal *internal = &state->internal;
-	struct stb0899_config *config = state->config;
-	struct dtv_frontend_properties *props = &fe->dtv_property_cache;
-
-	u32 SearchRange, gain;
-
-	i_params->freq	= props->frequency;
-	i_params->srate = props->symbol_rate;
-	state->delsys = props->delivery_system;
-	dprintk(state->verbose, FE_DEBUG, 1, "delivery system=%d", state->delsys);
-
-	SearchRange = 10000000;
-	dprintk(state->verbose, FE_DEBUG, 1, "Frequency=%d, Srate=%d", i_params->freq, i_params->srate);
-	/* checking Search Range is meaningless for a fixed 3 Mhz			*/
-	if (INRANGE(i_params->srate, 1000000, 45000000)) {
-		dprintk(state->verbose, FE_DEBUG, 1, "Parameters IN RANGE");
-		stb0899_set_delivery(state);
-
-		if (state->config->tuner_set_rfsiggain) {
-			if (internal->srate > 15000000)
-				gain =  8; /* 15Mb < srate < 45Mb, gain = 8dB	*/
-			else if (internal->srate > 5000000)
-				gain = 12; /*  5Mb < srate < 15Mb, gain = 12dB	*/
-			else
-				gain = 14; /*  1Mb < srate <  5Mb, gain = 14db	*/
-			state->config->tuner_set_rfsiggain(fe, gain);
-		}
-
-		if (i_params->srate <= 5000000)
-			stb0899_set_mclk(state, config->lo_clk);
-		else
-			stb0899_set_mclk(state, config->hi_clk);
-
-		switch (state->delsys) {
-		case SYS_DVBS:
-		case SYS_DSS:
-			dprintk(state->verbose, FE_DEBUG, 1, "DVB-S delivery system");
-			internal->freq	= i_params->freq;
-			internal->srate	= i_params->srate;
-			/*
-			 * search = user search range +
-			 *	    500Khz +
-			 *	    2 * Tuner_step_size +
-			 *	    10% of the symbol rate
-			 */
-			internal->srch_range	= SearchRange + 1500000 + (i_params->srate / 5);
-			internal->derot_percent	= 30;
-
-			/* What to do for tuners having no bandwidth setup ?	*/
-			/* enable tuner I/O */
-			stb0899_i2c_gate_ctrl(&state->frontend, 1);
-
-			if (state->config->tuner_set_bandwidth)
-				state->config->tuner_set_bandwidth(fe, (13 * (stb0899_carr_width(state) + SearchRange)) / 10);
-			if (state->config->tuner_get_bandwidth)
-				state->config->tuner_get_bandwidth(fe, &internal->tuner_bw);
-
-			/* disable tuner I/O */
-			stb0899_i2c_gate_ctrl(&state->frontend, 0);
-
-			/* Set DVB-S1 AGC		*/
-			stb0899_write_reg(state, STB0899_AGCRFCFG, 0x11);
-
-			/* Run the search algorithm	*/
-			dprintk(state->verbose, FE_DEBUG, 1, "running DVB-S search algo ..");
-			if (stb0899_dvbs_algo(state)	== RANGEOK) {
-				internal->lock		= 1;
-				dprintk(state->verbose, FE_DEBUG, 1,
-					"-------------------------------------> DVB-S LOCK !");
-
-//				stb0899_write_reg(state, STB0899_ERRCTRL1, 0x3d); /* Viterbi Errors	*/
-//				internal->v_status = stb0899_read_reg(state, STB0899_VSTATUS);
-//				internal->err_ctrl = stb0899_read_reg(state, STB0899_ERRCTRL1);
-//				dprintk(state->verbose, FE_DEBUG, 1, "VSTATUS=0x%02x", internal->v_status);
-//				dprintk(state->verbose, FE_DEBUG, 1, "ERR_CTRL=0x%02x", internal->err_ctrl);
-
-				return DVBFE_ALGO_SEARCH_SUCCESS;
-			} else {
-				internal->lock		= 0;
-
-				return DVBFE_ALGO_SEARCH_FAILED;
-			}
-			break;
-		case SYS_DVBS2:
-			internal->freq			= i_params->freq;
-			internal->srate			= i_params->srate;
-			internal->srch_range		= SearchRange;
-
-			/* enable tuner I/O */
-			stb0899_i2c_gate_ctrl(&state->frontend, 1);
-
-			if (state->config->tuner_set_bandwidth)
-				state->config->tuner_set_bandwidth(fe, (stb0899_carr_width(state) + SearchRange));
-			if (state->config->tuner_get_bandwidth)
-				state->config->tuner_get_bandwidth(fe, &internal->tuner_bw);
-
-			/* disable tuner I/O */
-			stb0899_i2c_gate_ctrl(&state->frontend, 0);
-
-//			pParams->SpectralInv		= pSearch->IQ_Inversion;
-
-			/* Set DVB-S2 AGC		*/
-			stb0899_write_reg(state, STB0899_AGCRFCFG, 0x1c);
-
-			/* Set IterScale =f(MCLK,SYMB)	*/
-			stb0899_set_iterations(state);
-
-			/* Run the search algorithm	*/
-			dprintk(state->verbose, FE_DEBUG, 1, "running DVB-S2 search algo ..");
-			if (stb0899_dvbs2_algo(state)	== DVBS2_FEC_LOCK) {
-				internal->lock		= 1;
-				dprintk(state->verbose, FE_DEBUG, 1,
-					"-------------------------------------> DVB-S2 LOCK !");
-
-//				stb0899_write_reg(state, STB0899_ERRCTRL1, 0xb6); /* Packet Errors	*/
-//				internal->v_status = stb0899_read_reg(state, STB0899_VSTATUS);
-//				internal->err_ctrl = stb0899_read_reg(state, STB0899_ERRCTRL1);
-
-				return DVBFE_ALGO_SEARCH_SUCCESS;
-			} else {
-				internal->lock		= 0;
-
-				return DVBFE_ALGO_SEARCH_FAILED;
-			}
-			break;
-		default:
-			dprintk(state->verbose, FE_ERROR, 1, "Unsupported delivery system");
-			return DVBFE_ALGO_SEARCH_INVALID;
-		}
-	}
-
-	return DVBFE_ALGO_SEARCH_ERROR;
-}
-
-static int stb0899_get_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct stb0899_state *state		= fe->demodulator_priv;
-	struct stb0899_internal *internal	= &state->internal;
-
-	dprintk(state->verbose, FE_DEBUG, 1, "Get params");
-	p->symbol_rate = internal->srate;
-
-	return 0;
-}
-
-static enum dvbfe_algo stb0899_frontend_algo(struct dvb_frontend *fe)
-{
-	return DVBFE_ALGO_CUSTOM;
-}
-
-static struct dvb_frontend_ops stb0899_ops = {
-	.delsys = { SYS_DVBS, SYS_DVBS2, SYS_DSS },
-	.info = {
-		.name 			= "STB0899 Multistandard",
-		.frequency_min		= 950000,
-		.frequency_max 		= 2150000,
-		.frequency_stepsize	= 0,
-		.frequency_tolerance	= 0,
-		.symbol_rate_min 	=  5000000,
-		.symbol_rate_max 	= 45000000,
-
-		.caps 			= FE_CAN_INVERSION_AUTO	|
-					  FE_CAN_FEC_AUTO	|
-					  FE_CAN_2G_MODULATION	|
-					  FE_CAN_QPSK
-	},
-
-	.release			= stb0899_release,
-	.init				= stb0899_init,
-	.sleep				= stb0899_sleep,
-//	.wakeup				= stb0899_wakeup,
-
-	.i2c_gate_ctrl			= stb0899_i2c_gate_ctrl,
-
-	.get_frontend_algo		= stb0899_frontend_algo,
-	.search				= stb0899_search,
-	.get_frontend                   = stb0899_get_frontend,
-
-
-	.read_status			= stb0899_read_status,
-	.read_snr			= stb0899_read_snr,
-	.read_signal_strength		= stb0899_read_signal_strength,
-	.read_ber			= stb0899_read_ber,
-
-	.set_voltage			= stb0899_set_voltage,
-	.set_tone			= stb0899_set_tone,
-
-	.diseqc_send_master_cmd		= stb0899_send_diseqc_msg,
-	.diseqc_recv_slave_reply	= stb0899_recv_slave_reply,
-	.diseqc_send_burst		= stb0899_send_diseqc_burst,
-};
-
-struct dvb_frontend *stb0899_attach(struct stb0899_config *config, struct i2c_adapter *i2c)
-{
-	struct stb0899_state *state = NULL;
-	enum stb0899_inversion inversion;
-
-	state = kzalloc(sizeof (struct stb0899_state), GFP_KERNEL);
-	if (state == NULL)
-		goto error;
-
-	inversion				= config->inversion;
-	state->verbose				= &verbose;
-	state->config				= config;
-	state->i2c				= i2c;
-	state->frontend.ops			= stb0899_ops;
-	state->frontend.demodulator_priv	= state;
-	state->internal.inversion		= inversion;
-
-	stb0899_wakeup(&state->frontend);
-	if (stb0899_get_dev_id(state) == -ENODEV) {
-		printk("%s: Exiting .. !\n", __func__);
-		goto error;
-	}
-
-	printk("%s: Attaching STB0899 \n", __func__);
-	return &state->frontend;
-
-error:
-	kfree(state);
-	return NULL;
-}
-EXPORT_SYMBOL(stb0899_attach);
-MODULE_PARM_DESC(verbose, "Set Verbosity level");
-MODULE_AUTHOR("Manu Abraham");
-MODULE_DESCRIPTION("STB0899 Multi-Std frontend");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/stb0899_drv.h b/drivers/media/dvb/frontends/stb0899_drv.h
deleted file mode 100644
index 98b200c..0000000
--- a/drivers/media/dvb/frontends/stb0899_drv.h
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
-	STB0899 Multistandard Frontend driver
-	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
-
-	Copyright (C) ST Microelectronics
-
-	This program is free software; you can redistribute it and/or modify
-	it under the terms of the 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 __STB0899_DRV_H
-#define __STB0899_DRV_H
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-
-#include "dvb_frontend.h"
-
-#define STB0899_TSMODE_SERIAL		1
-#define STB0899_CLKPOL_FALLING		2
-#define STB0899_CLKNULL_PARITY		3
-#define STB0899_SYNC_FORCED		4
-#define STB0899_FECMODE_DSS		5
-
-struct stb0899_s1_reg {
-	u16	address;
-	u8	data;
-};
-
-struct stb0899_s2_reg {
-	u16	offset;
-	u32	base_address;
-	u32	data;
-};
-
-enum stb0899_inversion {
-	IQ_SWAP_OFF	= 0,
-	IQ_SWAP_ON,
-	IQ_SWAP_AUTO
-};
-
-#define STB0899_GPIO00				0xf140
-#define STB0899_GPIO01				0xf141
-#define STB0899_GPIO02				0xf142
-#define STB0899_GPIO03				0xf143
-#define STB0899_GPIO04				0xf144
-#define STB0899_GPIO05				0xf145
-#define STB0899_GPIO06				0xf146
-#define STB0899_GPIO07				0xf147
-#define STB0899_GPIO08				0xf148
-#define STB0899_GPIO09				0xf149
-#define STB0899_GPIO10				0xf14a
-#define STB0899_GPIO11				0xf14b
-#define STB0899_GPIO12				0xf14c
-#define STB0899_GPIO13				0xf14d
-#define STB0899_GPIO14				0xf14e
-#define STB0899_GPIO15				0xf14f
-#define STB0899_GPIO16				0xf150
-#define STB0899_GPIO17				0xf151
-#define STB0899_GPIO18				0xf152
-#define STB0899_GPIO19				0xf153
-#define STB0899_GPIO20				0xf154
-
-#define STB0899_GPIOPULLUP			0x01 /* Output device is connected to Vdd */
-#define STB0899_GPIOPULLDN			0x00 /* Output device is connected to Vss */
-
-#define STB0899_POSTPROC_GPIO_POWER		0x00
-#define STB0899_POSTPROC_GPIO_LOCK		0x01
-
-/*
- * Post process output configuration control
- * 1. POWER ON/OFF		(index 0)
- * 2. FE_HAS_LOCK/LOCK_LOSS	(index 1)
- *
- * @gpio 	= one of the above listed GPIO's
- * @level	= output state: pulled up or low
- */
-struct stb0899_postproc {
-	u16	gpio;
-	u8	level;
-};
-
-struct stb0899_config {
-	const struct stb0899_s1_reg	*init_dev;
-	const struct stb0899_s2_reg	*init_s2_demod;
-	const struct stb0899_s1_reg	*init_s1_demod;
-	const struct stb0899_s2_reg	*init_s2_fec;
-	const struct stb0899_s1_reg	*init_tst;
-
-	const struct stb0899_postproc	*postproc;
-
-	enum stb0899_inversion		inversion;
-
-	u32	xtal_freq;
-
-	u8	demod_address;
-	u8	ts_output_mode;
-	u8	block_sync_mode;
-	u8	ts_pfbit_toggle;
-
-	u8	clock_polarity;
-	u8	data_clk_parity;
-	u8	fec_mode;
-	u8	data_output_ctl;
-	u8	data_fifo_mode;
-	u8	out_rate_comp;
-	u8	i2c_repeater;
-//	int	inversion;
-	int	lo_clk;
-	int	hi_clk;
-
-	u32	esno_ave;
-	u32	esno_quant;
-	u32	avframes_coarse;
-	u32	avframes_fine;
-	u32	miss_threshold;
-	u32	uwp_threshold_acq;
-	u32	uwp_threshold_track;
-	u32	uwp_threshold_sof;
-	u32	sof_search_timeout;
-
-	u32	btr_nco_bits;
-	u32	btr_gain_shift_offset;
-	u32	crl_nco_bits;
-	u32	ldpc_max_iter;
-
-	int (*tuner_set_frequency)(struct dvb_frontend *fe, u32 frequency);
-	int (*tuner_get_frequency)(struct dvb_frontend *fe, u32 *frequency);
-	int (*tuner_set_bandwidth)(struct dvb_frontend *fe, u32 bandwidth);
-	int (*tuner_get_bandwidth)(struct dvb_frontend *fe, u32 *bandwidth);
-	int (*tuner_set_rfsiggain)(struct dvb_frontend *fe, u32 rf_gain);
-};
-
-#if defined(CONFIG_DVB_STB0899) || (defined(CONFIG_DVB_STB0899_MODULE) && defined(MODULE))
-
-extern struct dvb_frontend *stb0899_attach(struct stb0899_config *config,
-					   struct i2c_adapter *i2c);
-
-#else
-
-static inline struct dvb_frontend *stb0899_attach(struct stb0899_config *config,
-						  struct i2c_adapter *i2c)
-{
-	printk(KERN_WARNING "%s: Driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-
-#endif //CONFIG_DVB_STB0899
-
-
-#endif
diff --git a/drivers/media/dvb/frontends/stb0899_priv.h b/drivers/media/dvb/frontends/stb0899_priv.h
deleted file mode 100644
index 82395b9..0000000
--- a/drivers/media/dvb/frontends/stb0899_priv.h
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
-	STB0899 Multistandard Frontend driver
-	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
-
-	Copyright (C) ST Microelectronics
-
-	This program is free software; you can redistribute it and/or modify
-	it under the terms of the 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 __STB0899_PRIV_H
-#define __STB0899_PRIV_H
-
-#include "dvb_frontend.h"
-#include "stb0899_drv.h"
-
-#define FE_ERROR				0
-#define FE_NOTICE				1
-#define FE_INFO					2
-#define FE_DEBUG				3
-#define FE_DEBUGREG				4
-
-#define dprintk(x, y, z, format, arg...) do {						\
-	if (z) {									\
-		if	((*x > FE_ERROR) && (*x > y))					\
-			printk(KERN_ERR "%s: " format "\n", __func__ , ##arg);		\
-		else if	((*x > FE_NOTICE) && (*x > y))					\
-			printk(KERN_NOTICE "%s: " format "\n", __func__ , ##arg);	\
-		else if ((*x > FE_INFO) && (*x > y))					\
-			printk(KERN_INFO "%s: " format "\n", __func__ , ##arg);		\
-		else if ((*x > FE_DEBUG) && (*x > y))					\
-			printk(KERN_DEBUG "%s: " format "\n", __func__ , ##arg);	\
-	} else {									\
-		if (*x > y)								\
-			printk(format, ##arg);						\
-	}										\
-} while(0)
-
-#define INRANGE(val, x, y)			(((x <= val) && (val <= y)) ||		\
-						 ((y <= val) && (val <= x)) ? 1 : 0)
-
-#define BYTE0					0
-#define BYTE1					8
-#define BYTE2					16
-#define BYTE3					24
-
-#define GETBYTE(x, y)				(((x) >> (y)) & 0xff)
-#define MAKEWORD32(a, b, c, d)			(((a) << 24) | ((b) << 16) | ((c) << 8) | (d))
-#define MAKEWORD16(a, b)			(((a) << 8) | (b))
-
-#define LSB(x)					((x & 0xff))
-#define MSB(y)					((y >> 8) & 0xff)
-
-
-#define STB0899_GETFIELD(bitf, val)		((val >> STB0899_OFFST_##bitf) & ((1 << STB0899_WIDTH_##bitf) - 1))
-
-
-#define STB0899_SETFIELD(mask, val, width, offset)      (mask & (~(((1 << width) - 1) <<	\
-							 offset))) | ((val &			\
-							 ((1 << width) - 1)) << offset)
-
-#define STB0899_SETFIELD_VAL(bitf, mask, val)	(mask = (mask & (~(((1 << STB0899_WIDTH_##bitf) - 1) <<\
-							 STB0899_OFFST_##bitf))) | \
-							 (val << STB0899_OFFST_##bitf))
-
-
-enum stb0899_status {
-	NOAGC1	= 0,
-	AGC1OK,
-	NOTIMING,
-	ANALOGCARRIER,
-	TIMINGOK,
-	NOAGC2,
-	AGC2OK,
-	NOCARRIER,
-	CARRIEROK,
-	NODATA,
-	FALSELOCK,
-	DATAOK,
-	OUTOFRANGE,
-	RANGEOK,
-	DVBS2_DEMOD_LOCK,
-	DVBS2_DEMOD_NOLOCK,
-	DVBS2_FEC_LOCK,
-	DVBS2_FEC_NOLOCK
-};
-
-enum stb0899_modcod {
-	STB0899_DUMMY_PLF,
-	STB0899_QPSK_14,
-	STB0899_QPSK_13,
-	STB0899_QPSK_25,
-	STB0899_QPSK_12,
-	STB0899_QPSK_35,
-	STB0899_QPSK_23,
-	STB0899_QPSK_34,
-	STB0899_QPSK_45,
-	STB0899_QPSK_56,
-	STB0899_QPSK_89,
-	STB0899_QPSK_910,
-	STB0899_8PSK_35,
-	STB0899_8PSK_23,
-	STB0899_8PSK_34,
-	STB0899_8PSK_56,
-	STB0899_8PSK_89,
-	STB0899_8PSK_910,
-	STB0899_16APSK_23,
-	STB0899_16APSK_34,
-	STB0899_16APSK_45,
-	STB0899_16APSK_56,
-	STB0899_16APSK_89,
-	STB0899_16APSK_910,
-	STB0899_32APSK_34,
-	STB0899_32APSK_45,
-	STB0899_32APSK_56,
-	STB0899_32APSK_89,
-	STB0899_32APSK_910
-};
-
-enum stb0899_frame {
-	STB0899_LONG_FRAME,
-	STB0899_SHORT_FRAME
-};
-
-enum stb0899_alpha {
-	RRC_20,
-	RRC_25,
-	RRC_35
-};
-
-struct stb0899_tab {
-	s32 real;
-	s32 read;
-};
-
-enum stb0899_fec {
-	STB0899_FEC_1_2			= 13,
-	STB0899_FEC_2_3			= 18,
-	STB0899_FEC_3_4			= 21,
-	STB0899_FEC_5_6			= 24,
-	STB0899_FEC_6_7			= 25,
-	STB0899_FEC_7_8			= 26
-};
-
-struct stb0899_params {
-	u32	freq;					/* Frequency	*/
-	u32	srate;					/* Symbol rate	*/
-	enum fe_code_rate fecrate;
-};
-
-struct stb0899_internal {
-	u32			master_clk;
-	u32			freq;			/* Demod internal Frequency		*/
-	u32			srate;			/* Demod internal Symbol rate		*/
-	enum stb0899_fec	fecrate;		/* Demod internal FEC rate		*/
-	s32			srch_range;		/* Demod internal Search Range		*/
-	s32			sub_range;		/* Demod current sub range (Hz)		*/
-	s32			tuner_step;		/* Tuner step (Hz)			*/
-	s32			tuner_offst;		/* Relative offset to carrier (Hz)	*/
-	u32			tuner_bw;		/* Current bandwidth of the tuner (Hz)	*/
-
-	s32			mclk;			/* Masterclock Divider factor (binary)	*/
-	s32			rolloff;		/* Current RollOff of the filter (x100)	*/
-
-	s16			derot_freq;		/* Current derotator frequency (Hz)	*/
-	s16			derot_percent;
-
-	s16			direction;		/* Current derotator search direction	*/
-	s16			derot_step;		/* Derotator step (binary value)	*/
-	s16			t_derot;		/* Derotator time constant (ms)		*/
-	s16			t_data;			/* Data recovery time constant (ms)	*/
-	s16			sub_dir;		/* Direction of the next sub range	*/
-
-	s16			t_agc1;			/* Agc1 time constant (ms)		*/
-	s16			t_agc2;			/* Agc2 time constant (ms)		*/
-
-	u32			lock;			/* Demod internal lock state		*/
-	enum stb0899_status	status;			/* Demod internal status		*/
-
-	/* DVB-S2 */
-	s32			agc_gain;		/* RF AGC Gain				*/
-	s32			center_freq;		/* Nominal carrier frequency		*/
-	s32			av_frame_coarse;	/* Coarse carrier freq search frames	*/
-	s32			av_frame_fine;		/* Fine carrier freq search frames	*/
-
-	s16			step_size;		/* Carrier frequency search step size	*/
-
-	enum stb0899_alpha	rrc_alpha;
-	enum stb0899_inversion	inversion;
-	enum stb0899_modcod	modcod;
-	u8			pilots;			/* Pilots found				*/
-
-	enum stb0899_frame	frame_length;
-	u8			v_status;		/* VSTATUS				*/
-	u8			err_ctrl;		/* ERRCTRLn				*/
-};
-
-struct stb0899_state {
-	struct i2c_adapter		*i2c;
-	struct stb0899_config		*config;
-	struct dvb_frontend		frontend;
-
-	u32				*verbose;	/* Cached module verbosity level	*/
-
-	struct stb0899_internal		internal;	/* Device internal parameters		*/
-
-	/*	cached params from API	*/
-	enum fe_delivery_system		delsys;
-	struct stb0899_params		params;
-
-	u32				rx_freq;	/* DiSEqC 2.0 receiver freq		*/
-	struct mutex			search_lock;
-};
-/* stb0899.c		*/
-extern int stb0899_read_reg(struct stb0899_state *state,
-			    unsigned int reg);
-
-extern u32 _stb0899_read_s2reg(struct stb0899_state *state,
-			       u32 stb0899_i2cdev,
-			       u32 stb0899_base_addr,
-			       u16 stb0899_reg_offset);
-
-extern int stb0899_read_regs(struct stb0899_state *state,
-			     unsigned int reg, u8 *buf,
-			     u32 count);
-
-extern int stb0899_write_regs(struct stb0899_state *state,
-			      unsigned int reg, u8 *data,
-			      u32 count);
-
-extern int stb0899_write_reg(struct stb0899_state *state,
-			     unsigned int reg,
-			     u8 data);
-
-extern int stb0899_write_s2reg(struct stb0899_state *state,
-			       u32 stb0899_i2cdev,
-			       u32 stb0899_base_addr,
-			       u16 stb0899_reg_offset,
-			       u32 stb0899_data);
-
-extern int stb0899_i2c_gate_ctrl(struct dvb_frontend *fe, int enable);
-
-
-#define STB0899_READ_S2REG(DEVICE, REG) 	(_stb0899_read_s2reg(state, DEVICE, STB0899_BASE_##REG, STB0899_OFF0_##REG))
-//#define STB0899_WRITE_S2REG(DEVICE, REG, DATA)	(_stb0899_write_s2reg(state, DEVICE, STB0899_BASE_##REG, STB0899_OFF0_##REG, DATA))
-
-/* stb0899_algo.c	*/
-extern enum stb0899_status stb0899_dvbs_algo(struct stb0899_state *state);
-extern enum stb0899_status stb0899_dvbs2_algo(struct stb0899_state *state);
-extern long stb0899_carr_width(struct stb0899_state *state);
-
-#endif //__STB0899_PRIV_H
diff --git a/drivers/media/dvb/frontends/stb0899_reg.h b/drivers/media/dvb/frontends/stb0899_reg.h
deleted file mode 100644
index ba1ed56..0000000
--- a/drivers/media/dvb/frontends/stb0899_reg.h
+++ /dev/null
@@ -1,2027 +0,0 @@
-/*
-	STB0899 Multistandard Frontend driver
-	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
-
-	Copyright (C) ST Microelectronics
-
-	This program is free software; you can redistribute it and/or modify
-	it under the terms of the 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 __STB0899_REG_H
-#define __STB0899_REG_H
-
-/*	S1	*/
-#define STB0899_DEV_ID				0xf000
-#define STB0899_CHIP_ID				(0x0f << 4)
-#define STB0899_OFFST_CHIP_ID			4
-#define STB0899_WIDTH_CHIP_ID			4
-#define STB0899_CHIP_REL			(0x0f << 0)
-#define STB0899_OFFST_CHIP_REL			0
-#define STB0899_WIDTH_CHIP_REL			4
-
-#define STB0899_DEMOD				0xf40e
-#define STB0899_MODECOEFF			(0x01 << 0)
-#define STB0899_OFFST_MODECOEFF			0
-#define STB0899_WIDTH_MODECOEFF			1
-
-#define STB0899_RCOMPC				0xf410
-#define STB0899_AGC1CN				0xf412
-#define STB0899_AGC1REF				0xf413
-#define STB0899_RTC				0xf417
-#define STB0899_TMGCFG				0xf418
-#define STB0899_AGC2REF				0xf419
-#define STB0899_TLSR				0xf41a
-
-#define STB0899_CFD				0xf41b
-#define STB0899_CFD_ON				(0x01 << 7)
-#define STB0899_OFFST_CFD_ON			7
-#define STB0899_WIDTH_CFD_ON			1
-
-#define STB0899_ACLC				0xf41c
-
-#define STB0899_BCLC				0xf41d
-#define STB0899_OFFST_ALGO			6
-#define STB0899_WIDTH_ALGO_QPSK2		2
-#define STB0899_ALGO_QPSK2			(2 << 6)
-#define STB0899_ALGO_QPSK1			(1 << 6)
-#define STB0899_ALGO_BPSK			(0 << 6)
-#define STB0899_OFFST_BETA			0
-#define STB0899_WIDTH_BETA			6
-
-#define STB0899_EQON				0xf41e
-#define STB0899_LDT				0xf41f
-#define STB0899_LDT2				0xf420
-#define STB0899_EQUALREF			0xf425
-#define STB0899_TMGRAMP				0xf426
-#define STB0899_TMGTHD				0xf427
-#define STB0899_IDCCOMP				0xf428
-#define STB0899_QDCCOMP				0xf429
-#define STB0899_POWERI				0xf42a
-#define STB0899_POWERQ				0xf42b
-#define STB0899_RCOMP				0xf42c
-
-#define STB0899_AGCIQIN				0xf42e
-#define STB0899_AGCIQVALUE			(0xff << 0)
-#define STB0899_OFFST_AGCIQVALUE		0
-#define STB0899_WIDTH_AGCIQVALUE		8
-
-#define STB0899_AGC2I1				0xf436
-#define STB0899_AGC2I2				0xf437
-
-#define STB0899_TLIR				0xf438
-#define STB0899_TLIR_TMG_LOCK_IND		(0xff << 0)
-#define STB0899_OFFST_TLIR_TMG_LOCK_IND		0
-#define STB0899_WIDTH_TLIR_TMG_LOCK_IND		8
-
-#define STB0899_RTF				0xf439
-#define STB0899_RTF_TIMING_LOOP_FREQ		(0xff << 0)
-#define STB0899_OFFST_RTF_TIMING_LOOP_FREQ	0
-#define STB0899_WIDTH_RTF_TIMING_LOOP_FREQ	8
-
-#define STB0899_DSTATUS				0xf43a
-#define STB0899_CARRIER_FOUND			(0x01 << 7)
-#define STB0899_OFFST_CARRIER_FOUND		7
-#define STB0899_WIDTH_CARRIER_FOUND		1
-#define STB0899_TMG_LOCK			(0x01 << 6)
-#define STB0899_OFFST_TMG_LOCK			6
-#define STB0899_WIDTH_TMG_LOCK			1
-#define STB0899_DEMOD_LOCK			(0x01 << 5)
-#define STB0899_OFFST_DEMOD_LOCK		5
-#define STB0899_WIDTH_DEMOD_LOCK		1
-#define STB0899_TMG_AUTO			(0x01 << 4)
-#define STB0899_OFFST_TMG_AUTO			4
-#define STB0899_WIDTH_TMG_AUTO			1
-#define STB0899_END_MAIN			(0x01 << 3)
-#define STB0899_OFFST_END_MAIN			3
-#define STB0899_WIDTH_END_MAIN			1
-
-#define STB0899_LDI				0xf43b
-#define STB0899_OFFST_LDI			0
-#define STB0899_WIDTH_LDI			8
-
-#define STB0899_CFRM				0xf43e
-#define STB0899_OFFST_CFRM			0
-#define STB0899_WIDTH_CFRM			8
-
-#define STB0899_CFRL				0xf43f
-#define STB0899_OFFST_CFRL			0
-#define STB0899_WIDTH_CFRL			8
-
-#define STB0899_NIRM				0xf440
-#define STB0899_OFFST_NIRM			0
-#define STB0899_WIDTH_NIRM			8
-
-#define STB0899_NIRL				0xf441
-#define STB0899_OFFST_NIRL			0
-#define STB0899_WIDTH_NIRL			8
-
-#define STB0899_ISYMB				0xf444
-#define STB0899_QSYMB				0xf445
-
-#define STB0899_SFRH				0xf446
-#define STB0899_OFFST_SFRH			0
-#define STB0899_WIDTH_SFRH			8
-
-#define STB0899_SFRM				0xf447
-#define STB0899_OFFST_SFRM			0
-#define STB0899_WIDTH_SFRM			8
-
-#define STB0899_SFRL				0xf448
-#define STB0899_OFFST_SFRL			4
-#define STB0899_WIDTH_SFRL			4
-
-#define STB0899_SFRUPH				0xf44c
-#define STB0899_SFRUPM				0xf44d
-#define STB0899_SFRUPL				0xf44e
-
-#define STB0899_EQUAI1				0xf4e0
-#define STB0899_EQUAQ1				0xf4e1
-#define STB0899_EQUAI2				0xf4e2
-#define STB0899_EQUAQ2				0xf4e3
-#define STB0899_EQUAI3				0xf4e4
-#define STB0899_EQUAQ3				0xf4e5
-#define STB0899_EQUAI4				0xf4e6
-#define STB0899_EQUAQ4				0xf4e7
-#define STB0899_EQUAI5				0xf4e8
-#define STB0899_EQUAQ5				0xf4e9
-
-#define STB0899_DSTATUS2			0xf50c
-#define STB0899_DS2_TMG_AUTOSRCH		(0x01 << 7)
-#define STB8999_OFFST_DS2_TMG_AUTOSRCH		7
-#define STB0899_WIDTH_DS2_TMG_AUTOSRCH		1
-#define STB0899_DS2_END_MAINLOOP		(0x01 << 6)
-#define STB0899_OFFST_DS2_END_MAINLOOP		6
-#define STB0899_WIDTH_DS2_END_MAINLOOP		1
-#define STB0899_DS2_CFSYNC			(0x01 << 5)
-#define STB0899_OFFST_DS2_CFSYNC		5
-#define STB0899_WIDTH_DS2_CFSYNC		1
-#define STB0899_DS2_TMGLOCK			(0x01 << 4)
-#define STB0899_OFFST_DS2_TMGLOCK		4
-#define STB0899_WIDTH_DS2_TMGLOCK		1
-#define STB0899_DS2_DEMODWAIT			(0x01 << 3)
-#define STB0899_OFFST_DS2_DEMODWAIT		3
-#define STB0899_WIDTH_DS2_DEMODWAIT		1
-#define STB0899_DS2_FECON			(0x01 << 1)
-#define STB0899_OFFST_DS2_FECON			1
-#define STB0899_WIDTH_DS2_FECON			1
-
-/*	S1 FEC	*/
-#define STB0899_VSTATUS				0xf50d
-#define STB0899_VSTATUS_VITERBI_ON		(0x01 << 7)
-#define STB0899_OFFST_VSTATUS_VITERBI_ON	7
-#define STB0899_WIDTH_VSTATUS_VITERBI_ON	1
-#define STB0899_VSTATUS_END_LOOPVIT		(0x01 << 6)
-#define STB0899_OFFST_VSTATUS_END_LOOPVIT	6
-#define STB0899_WIDTH_VSTATUS_END_LOOPVIT	1
-#define STB0899_VSTATUS_PRFVIT			(0x01 << 4)
-#define STB0899_OFFST_VSTATUS_PRFVIT		4
-#define STB0899_WIDTH_VSTATUS_PRFVIT		1
-#define STB0899_VSTATUS_LOCKEDVIT		(0x01 << 3)
-#define STB0899_OFFST_VSTATUS_LOCKEDVIT		3
-#define STB0899_WIDTH_VSTATUS_LOCKEDVIT		1
-
-#define STB0899_VERROR				0xf50f
-
-#define STB0899_IQSWAP				0xf523
-#define STB0899_SYM				(0x01 << 3)
-#define STB0899_OFFST_SYM			3
-#define STB0899_WIDTH_SYM			1
-
-#define STB0899_FECAUTO1			0xf530
-#define STB0899_DSSSRCH				(0x01 << 3)
-#define STB0899_OFFST_DSSSRCH			3
-#define STB0899_WIDTH_DSSSRCH			1
-#define STB0899_SYMSRCH				(0x01 << 2)
-#define STB0899_OFFST_SYMSRCH			2
-#define STB0899_WIDTH_SYMSRCH			1
-#define STB0899_QPSKSRCH			(0x01 << 1)
-#define STB0899_OFFST_QPSKSRCH			1
-#define STB0899_WIDTH_QPSKSRCH			1
-#define STB0899_BPSKSRCH			(0x01 << 0)
-#define STB0899_OFFST_BPSKSRCH			0
-#define STB0899_WIDTH_BPSKSRCH			1
-
-#define STB0899_FECM				0xf533
-#define STB0899_FECM_NOT_DVB			(0x01 << 7)
-#define STB0899_OFFST_FECM_NOT_DVB		7
-#define STB0899_WIDTH_FECM_NOT_DVB		1
-#define STB0899_FECM_RSVD1			(0x07 << 4)
-#define STB0899_OFFST_FECM_RSVD1		4
-#define STB0899_WIDTH_FECM_RSVD1		3
-#define STB0899_FECM_VITERBI_ON			(0x01 << 3)
-#define STB0899_OFFST_FECM_VITERBI_ON		3
-#define STB0899_WIDTH_FECM_VITERBI_ON		1
-#define STB0899_FECM_RSVD0			(0x01 << 2)
-#define STB0899_OFFST_FECM_RSVD0		2
-#define STB0899_WIDTH_FECM_RSVD0		1
-#define STB0899_FECM_SYNCDIS			(0x01 << 1)
-#define STB0899_OFFST_FECM_SYNCDIS		1
-#define STB0899_WIDTH_FECM_SYNCDIS		1
-#define STB0899_FECM_SYMI			(0x01 << 0)
-#define STB0899_OFFST_FECM_SYMI			0
-#define STB0899_WIDTH_FECM_SYMI			1
-
-#define STB0899_VTH12				0xf534
-#define STB0899_VTH23				0xf535
-#define STB0899_VTH34				0xf536
-#define STB0899_VTH56				0xf537
-#define STB0899_VTH67				0xf538
-#define STB0899_VTH78				0xf539
-
-#define STB0899_PRVIT				0xf53c
-#define STB0899_PR_7_8				(0x01 << 5)
-#define STB0899_OFFST_PR_7_8			5
-#define STB0899_WIDTH_PR_7_8			1
-#define STB0899_PR_6_7				(0x01 << 4)
-#define STB0899_OFFST_PR_6_7			4
-#define STB0899_WIDTH_PR_6_7			1
-#define STB0899_PR_5_6				(0x01 << 3)
-#define STB0899_OFFST_PR_5_6			3
-#define STB0899_WIDTH_PR_5_6			1
-#define STB0899_PR_3_4				(0x01 << 2)
-#define STB0899_OFFST_PR_3_4			2
-#define STB0899_WIDTH_PR_3_4			1
-#define STB0899_PR_2_3				(0x01 << 1)
-#define STB0899_OFFST_PR_2_3			1
-#define STB0899_WIDTH_PR_2_3			1
-#define STB0899_PR_1_2				(0x01 << 0)
-#define STB0899_OFFST_PR_1_2			0
-#define STB0899_WIDTH_PR_1_2			1
-
-#define STB0899_VITSYNC				0xf53d
-#define STB0899_AM				(0x01 << 7)
-#define STB0899_OFFST_AM			7
-#define STB0899_WIDTH_AM			1
-#define STB0899_FREEZE				(0x01 << 6)
-#define STB0899_OFFST_FREEZE			6
-#define STB0899_WIDTH_FREEZE			1
-#define STB0899_SN_65536			(0x03 << 4)
-#define STB0899_OFFST_SN_65536			4
-#define STB0899_WIDTH_SN_65536			2
-#define STB0899_SN_16384			(0x01 << 5)
-#define STB0899_OFFST_SN_16384			5
-#define STB0899_WIDTH_SN_16384			1
-#define STB0899_SN_4096				(0x01 << 4)
-#define STB0899_OFFST_SN_4096			4
-#define STB0899_WIDTH_SN_4096			1
-#define STB0899_SN_1024				(0x00 << 4)
-#define STB0899_OFFST_SN_1024			4
-#define STB0899_WIDTH_SN_1024			0
-#define STB0899_TO_128				(0x03 << 2)
-#define STB0899_OFFST_TO_128			2
-#define STB0899_WIDTH_TO_128			2
-#define STB0899_TO_64				(0x01 << 3)
-#define STB0899_OFFST_TO_64			3
-#define STB0899_WIDTH_TO_64			1
-#define STB0899_TO_32				(0x01 << 2)
-#define STB0899_OFFST_TO_32			2
-#define STB0899_WIDTH_TO_32			1
-#define STB0899_TO_16				(0x00 << 2)
-#define STB0899_OFFST_TO_16			2
-#define STB0899_WIDTH_TO_16			0
-#define STB0899_HYST_128			(0x03 << 1)
-#define STB0899_OFFST_HYST_128			1
-#define STB0899_WIDTH_HYST_128			2
-#define STB0899_HYST_64				(0x01 << 1)
-#define STB0899_OFFST_HYST_64			1
-#define STB0899_WIDTH_HYST_64			1
-#define STB0899_HYST_32				(0x01 << 0)
-#define STB0899_OFFST_HYST_32			0
-#define STB0899_WIDTH_HYST_32			1
-#define STB0899_HYST_16				(0x00 << 0)
-#define STB0899_OFFST_HYST_16			0
-#define STB0899_WIDTH_HYST_16			0
-
-#define STB0899_RSULC				0xf548
-#define STB0899_ULDIL_ON			(0x01 << 7)
-#define STB0899_OFFST_ULDIL_ON			7
-#define STB0899_WIDTH_ULDIL_ON			1
-#define STB0899_ULAUTO_ON			(0x01 << 6)
-#define STB0899_OFFST_ULAUTO_ON			6
-#define STB0899_WIDTH_ULAUTO_ON			1
-#define STB0899_ULRS_ON				(0x01 << 5)
-#define STB0899_OFFST_ULRS_ON			5
-#define STB0899_WIDTH_ULRS_ON			1
-#define STB0899_ULDESCRAM_ON			(0x01 << 4)
-#define STB0899_OFFST_ULDESCRAM_ON		4
-#define STB0899_WIDTH_ULDESCRAM_ON		1
-#define STB0899_UL_DISABLE			(0x01 << 2)
-#define STB0899_OFFST_UL_DISABLE		2
-#define STB0899_WIDTH_UL_DISABLE		1
-#define STB0899_NOFTHRESHOLD			(0x01 << 0)
-#define STB0899_OFFST_NOFTHRESHOLD		0
-#define STB0899_WIDTH_NOFTHRESHOLD		1
-
-#define STB0899_RSLLC				0xf54a
-#define STB0899_DEMAPVIT			0xf583
-#define STB0899_DEMAPVIT_RSVD			(0x01 << 7)
-#define STB0899_OFFST_DEMAPVIT_RSVD		7
-#define STB0899_WIDTH_DEMAPVIT_RSVD		1
-#define STB0899_DEMAPVIT_KDIVIDER		(0x7f << 0)
-#define STB0899_OFFST_DEMAPVIT_KDIVIDER		0
-#define STB0899_WIDTH_DEMAPVIT_KDIVIDER		7
-
-#define STB0899_PLPARM				0xf58c
-#define STB0899_VITMAPPING			(0x07 << 5)
-#define STB0899_OFFST_VITMAPPING		5
-#define STB0899_WIDTH_VITMAPPING		3
-#define STB0899_VITMAPPING_BPSK			(0x01 << 5)
-#define STB0899_OFFST_VITMAPPING_BPSK		5
-#define STB0899_WIDTH_VITMAPPING_BPSK		1
-#define STB0899_VITMAPPING_QPSK			(0x00 << 5)
-#define STB0899_OFFST_VITMAPPING_QPSK		5
-#define STB0899_WIDTH_VITMAPPING_QPSK		0
-#define STB0899_VITCURPUN			(0x1f << 0)
-#define STB0899_OFFST_VITCURPUN			0
-#define STB0899_WIDTH_VITCURPUN			5
-#define STB0899_VITCURPUN_1_2			(0x0d << 0)
-#define STB0899_VITCURPUN_2_3			(0x12 << 0)
-#define STB0899_VITCURPUN_3_4			(0x15 << 0)
-#define STB0899_VITCURPUN_5_6			(0x18 << 0)
-#define STB0899_VITCURPUN_6_7			(0x19 << 0)
-#define STB0899_VITCURPUN_7_8			(0x1a << 0)
-
-/*	S2 DEMOD	*/
-#define STB0899_OFF0_DMD_STATUS			0xf300
-#define STB0899_BASE_DMD_STATUS			0x00000000
-#define STB0899_IF_AGC_LOCK			(0x01 << 8)
-#define STB0899_OFFST_IF_AGC_LOCK		0
-#define STB0899_WIDTH_IF_AGC_LOCK		1
-
-#define STB0899_OFF0_CRL_FREQ			0xf304
-#define STB0899_BASE_CRL_FREQ			0x00000000
-#define STB0899_CARR_FREQ			(0x3fffffff << 0)
-#define STB0899_OFFST_CARR_FREQ			0
-#define STB0899_WIDTH_CARR_FREQ			30
-
-#define STB0899_OFF0_BTR_FREQ			0xf308
-#define STB0899_BASE_BTR_FREQ			0x00000000
-#define STB0899_BTR_FREQ			(0xfffffff << 0)
-#define STB0899_OFFST_BTR_FREQ			0
-#define STB0899_WIDTH_BTR_FREQ			28
-
-#define STB0899_OFF0_IF_AGC_GAIN		0xf30c
-#define STB0899_BASE_IF_AGC_GAIN		0x00000000
-#define STB0899_IF_AGC_GAIN			(0x3fff < 0)
-#define STB0899_OFFST_IF_AGC_GAIN		0
-#define STB0899_WIDTH_IF_AGC_GAIN		14
-
-#define STB0899_OFF0_BB_AGC_GAIN		0xf310
-#define STB0899_BASE_BB_AGC_GAIN		0x00000000
-#define STB0899_BB_AGC_GAIN			(0x3fff < 0)
-#define STB0899_OFFST_BB_AGC_GAIN		0
-#define STB0899_WIDTH_BB_AGC_GAIN		14
-
-#define STB0899_OFF0_DC_OFFSET			0xf314
-#define STB0899_BASE_DC_OFFSET			0x00000000
-#define STB0899_I				(0xff < 8)
-#define STB0899_OFFST_I				8
-#define STB0899_WIDTH_I				8
-#define STB0899_Q				(0xff < 0)
-#define STB0899_OFFST_Q				8
-#define STB0899_WIDTH_Q				8
-
-#define STB0899_OFF0_DMD_CNTRL			0xf31c
-#define STB0899_BASE_DMD_CNTRL			0x00000000
-#define STB0899_ADC0_PINS1IN			(0x01 << 6)
-#define STB0899_OFFST_ADC0_PINS1IN              6
-#define STB0899_WIDTH_ADC0_PINS1IN              1
-#define STB0899_IN2COMP1_OFFBIN0		(0x01 << 3)
-#define STB0899_OFFST_IN2COMP1_OFFBIN0          3
-#define STB0899_WIDTH_IN2COMP1_OFFBIN0          1
-#define STB0899_DC_COMP				(0x01 << 2)
-#define STB0899_OFFST_DC_COMP			2
-#define STB0899_WIDTH_DC_COMP			1
-#define STB0899_MODMODE				(0x03 << 0)
-#define STB0899_OFFST_MODMODE			0
-#define STB0899_WIDTH_MODMODE			2
-
-#define STB0899_OFF0_IF_AGC_CNTRL		0xf320
-#define STB0899_BASE_IF_AGC_CNTRL		0x00000000
-#define STB0899_IF_GAIN_INIT			(0x3fff << 13)
-#define STB0899_OFFST_IF_GAIN_INIT		13
-#define STB0899_WIDTH_IF_GAIN_INIT		14
-#define STB0899_IF_GAIN_SENSE			(0x01 << 12)
-#define STB0899_OFFST_IF_GAIN_SENSE		12
-#define STB0899_WIDTH_IF_GAIN_SENSE		1
-#define STB0899_IF_LOOP_GAIN			(0x0f << 8)
-#define STB0899_OFFST_IF_LOOP_GAIN		8
-#define STB0899_WIDTH_IF_LOOP_GAIN		4
-#define STB0899_IF_LD_GAIN_INIT			(0x01 << 7)
-#define STB0899_OFFST_IF_LD_GAIN_INIT		7
-#define STB0899_WIDTH_IF_LD_GAIN_INIT		1
-#define STB0899_IF_AGC_REF			(0x7f << 0)
-#define STB0899_OFFST_IF_AGC_REF		0
-#define STB0899_WIDTH_IF_AGC_REF		7
-
-#define STB0899_OFF0_BB_AGC_CNTRL		0xf324
-#define STB0899_BASE_BB_AGC_CNTRL		0x00000000
-#define STB0899_BB_GAIN_INIT			(0x3fff << 12)
-#define STB0899_OFFST_BB_GAIN_INIT		12
-#define STB0899_WIDTH_BB_GAIN_INIT		14
-#define STB0899_BB_LOOP_GAIN			(0x0f << 8)
-#define STB0899_OFFST_BB_LOOP_GAIN		8
-#define STB0899_WIDTH_BB_LOOP_GAIN		4
-#define STB0899_BB_LD_GAIN_INIT			(0x01 << 7)
-#define STB0899_OFFST_BB_LD_GAIN_INIT		7
-#define STB0899_WIDTH_BB_LD_GAIN_INIT		1
-#define STB0899_BB_AGC_REF			(0x7f << 0)
-#define STB0899_OFFST_BB_AGC_REF		0
-#define STB0899_WIDTH_BB_AGC_REF		7
-
-#define STB0899_OFF0_CRL_CNTRL			0xf328
-#define STB0899_BASE_CRL_CNTRL			0x00000000
-#define STB0899_CRL_LOCK_CLEAR			(0x01 << 5)
-#define STB0899_OFFST_CRL_LOCK_CLEAR		5
-#define STB0899_WIDTH_CRL_LOCK_CLEAR		1
-#define STB0899_CRL_SWPR_CLEAR			(0x01 << 4)
-#define STB0899_OFFST_CRL_SWPR_CLEAR		4
-#define STB0899_WIDTH_CRL_SWPR_CLEAR		1
-#define STB0899_CRL_SWP_ENA			(0x01 << 3)
-#define STB0899_OFFST_CRL_SWP_ENA		3
-#define STB0899_WIDTH_CRL_SWP_ENA		1
-#define STB0899_CRL_DET_SEL			(0x01 << 2)
-#define STB0899_OFFST_CRL_DET_SEL		2
-#define STB0899_WIDTH_CRL_DET_SEL		1
-#define STB0899_CRL_SENSE			(0x01 << 1)
-#define STB0899_OFFST_CRL_SENSE			1
-#define STB0899_WIDTH_CRL_SENSE			1
-#define STB0899_CRL_PHSERR_CLEAR		(0x01 << 0)
-#define STB0899_OFFST_CRL_PHSERR_CLEAR		0
-#define STB0899_WIDTH_CRL_PHSERR_CLEAR		1
-
-#define STB0899_OFF0_CRL_PHS_INIT		0xf32c
-#define STB0899_BASE_CRL_PHS_INIT		0x00000000
-#define STB0899_CRL_PHS_INIT_31			(0x1 << 30)
-#define STB0899_OFFST_CRL_PHS_INIT_31		30
-#define STB0899_WIDTH_CRL_PHS_INIT_31		1
-#define STB0899_CRL_LD_INIT_PHASE		(0x1 << 24)
-#define STB0899_OFFST_CRL_LD_INIT_PHASE		24
-#define STB0899_WIDTH_CRL_LD_INIT_PHASE		1
-#define STB0899_CRL_INIT_PHASE			(0xffffff << 0)
-#define STB0899_OFFST_CRL_INIT_PHASE		0
-#define STB0899_WIDTH_CRL_INIT_PHASE		24
-
-#define STB0899_OFF0_CRL_FREQ_INIT		0xf330
-#define STB0899_BASE_CRL_FREQ_INIT		0x00000000
-#define STB0899_CRL_FREQ_INIT_31		(0x1 << 30)
-#define STB0899_OFFST_CRL_FREQ_INIT_31		30
-#define STB0899_WIDTH_CRL_FREQ_INIT_31		1
-#define STB0899_CRL_LD_FREQ_INIT		(0x1 << 24)
-#define STB0899_OFFST_CRL_LD_FREQ_INIT		24
-#define STB0899_WIDTH_CRL_LD_FREQ_INIT		1
-#define STB0899_CRL_FREQ_INIT			(0xffffff << 0)
-#define STB0899_OFFST_CRL_FREQ_INIT		0
-#define STB0899_WIDTH_CRL_FREQ_INIT		24
-
-#define STB0899_OFF0_CRL_LOOP_GAIN		0xf334
-#define STB0899_BASE_CRL_LOOP_GAIN		0x00000000
-#define STB0899_KCRL2_RSHFT			(0xf << 16)
-#define STB0899_OFFST_KCRL2_RSHFT		16
-#define STB0899_WIDTH_KCRL2_RSHFT		4
-#define STB0899_KCRL1				(0xf << 12)
-#define STB0899_OFFST_KCRL1			12
-#define STB0899_WIDTH_KCRL1			4
-#define STB0899_KCRL1_RSHFT			(0xf << 8)
-#define STB0899_OFFST_KCRL1_RSHFT		8
-#define STB0899_WIDTH_KCRL1_RSHFT		4
-#define STB0899_KCRL0				(0xf << 4)
-#define STB0899_OFFST_KCRL0			4
-#define STB0899_WIDTH_KCRL0			4
-#define STB0899_KCRL0_RSHFT			(0xf << 0)
-#define STB0899_OFFST_KCRL0_RSHFT		0
-#define STB0899_WIDTH_KCRL0_RSHFT		4
-
-#define STB0899_OFF0_CRL_NOM_FREQ		0xf338
-#define STB0899_BASE_CRL_NOM_FREQ		0x00000000
-#define STB0899_CRL_NOM_FREQ			(0x3fffffff << 0)
-#define STB0899_OFFST_CRL_NOM_FREQ		0
-#define STB0899_WIDTH_CRL_NOM_FREQ		30
-
-#define STB0899_OFF0_CRL_SWP_RATE		0xf33c
-#define STB0899_BASE_CRL_SWP_RATE		0x00000000
-#define STB0899_CRL_SWP_RATE			(0x3fffffff << 0)
-#define STB0899_OFFST_CRL_SWP_RATE		0
-#define STB0899_WIDTH_CRL_SWP_RATE		30
-
-#define STB0899_OFF0_CRL_MAX_SWP		0xf340
-#define STB0899_BASE_CRL_MAX_SWP		0x00000000
-#define STB0899_CRL_MAX_SWP			(0x3fffffff << 0)
-#define STB0899_OFFST_CRL_MAX_SWP		0
-#define STB0899_WIDTH_CRL_MAX_SWP		30
-
-#define STB0899_OFF0_CRL_LK_CNTRL		0xf344
-#define STB0899_BASE_CRL_LK_CNTRL		0x00000000
-
-#define STB0899_OFF0_DECIM_CNTRL		0xf348
-#define STB0899_BASE_DECIM_CNTRL		0x00000000
-#define STB0899_BAND_LIMIT_B			(0x01 << 5)
-#define STB0899_OFFST_BAND_LIMIT_B		5
-#define STB0899_WIDTH_BAND_LIMIT_B		1
-#define STB0899_WIN_SEL				(0x03 << 3)
-#define STB0899_OFFST_WIN_SEL			3
-#define STB0899_WIDTH_WIN_SEL			2
-#define STB0899_DECIM_RATE			(0x07 << 0)
-#define STB0899_OFFST_DECIM_RATE		0
-#define STB0899_WIDTH_DECIM_RATE		3
-
-#define STB0899_OFF0_BTR_CNTRL			0xf34c
-#define STB0899_BASE_BTR_CNTRL			0x00000000
-#define STB0899_BTR_FREQ_CORR			(0x7ff << 4)
-#define STB0899_OFFST_BTR_FREQ_CORR		4
-#define STB0899_WIDTH_BTR_FREQ_CORR		11
-#define STB0899_BTR_CLR_LOCK			(0x01 << 3)
-#define STB0899_OFFST_BTR_CLR_LOCK		3
-#define STB0899_WIDTH_BTR_CLR_LOCK		1
-#define STB0899_BTR_SENSE			(0x01 << 2)
-#define STB0899_OFFST_BTR_SENSE			2
-#define STB0899_WIDTH_BTR_SENSE			1
-#define STB0899_BTR_ERR_ENA			(0x01 << 1)
-#define STB0899_OFFST_BTR_ERR_ENA		1
-#define STB0899_WIDTH_BTR_ERR_ENA		1
-#define STB0899_INTRP_PHS_SENSE			(0x01 << 0)
-#define STB0899_OFFST_INTRP_PHS_SENSE		0
-#define STB0899_WIDTH_INTRP_PHS_SENSE		1
-
-#define STB0899_OFF0_BTR_LOOP_GAIN		0xf350
-#define STB0899_BASE_BTR_LOOP_GAIN		0x00000000
-#define STB0899_KBTR2_RSHFT			(0x0f << 16)
-#define STB0899_OFFST_KBTR2_RSHFT		16
-#define STB0899_WIDTH_KBTR2_RSHFT		4
-#define STB0899_KBTR1				(0x0f << 12)
-#define STB0899_OFFST_KBTR1			12
-#define STB0899_WIDTH_KBTR1			4
-#define STB0899_KBTR1_RSHFT			(0x0f << 8)
-#define STB0899_OFFST_KBTR1_RSHFT		8
-#define STB0899_WIDTH_KBTR1_RSHFT		4
-#define STB0899_KBTR0				(0x0f << 4)
-#define STB0899_OFFST_KBTR0			4
-#define STB0899_WIDTH_KBTR0			4
-#define STB0899_KBTR0_RSHFT			(0x0f << 0)
-#define STB0899_OFFST_KBTR0_RSHFT		0
-#define STB0899_WIDTH_KBTR0_RSHFT		4
-
-#define STB0899_OFF0_BTR_PHS_INIT		0xf354
-#define STB0899_BASE_BTR_PHS_INIT		0x00000000
-#define STB0899_BTR_LD_PHASE_INIT		(0x01 << 28)
-#define STB0899_OFFST_BTR_LD_PHASE_INIT		28
-#define STB0899_WIDTH_BTR_LD_PHASE_INIT		1
-#define STB0899_BTR_INIT_PHASE			(0xfffffff << 0)
-#define STB0899_OFFST_BTR_INIT_PHASE		0
-#define STB0899_WIDTH_BTR_INIT_PHASE		28
-
-#define STB0899_OFF0_BTR_FREQ_INIT		0xf358
-#define STB0899_BASE_BTR_FREQ_INIT		0x00000000
-#define STB0899_BTR_LD_FREQ_INIT		(1 << 28)
-#define STB0899_OFFST_BTR_LD_FREQ_INIT		28
-#define STB0899_WIDTH_BTR_LD_FREQ_INIT		1
-#define STB0899_BTR_FREQ_INIT			(0xfffffff << 0)
-#define STB0899_OFFST_BTR_FREQ_INIT		0
-#define STB0899_WIDTH_BTR_FREQ_INIT		28
-
-#define STB0899_OFF0_BTR_NOM_FREQ		0xf35c
-#define STB0899_BASE_BTR_NOM_FREQ		0x00000000
-#define STB0899_BTR_NOM_FREQ			(0xfffffff << 0)
-#define STB0899_OFFST_BTR_NOM_FREQ		0
-#define STB0899_WIDTH_BTR_NOM_FREQ		28
-
-#define STB0899_OFF0_BTR_LK_CNTRL		0xf360
-#define STB0899_BASE_BTR_LK_CNTRL		0x00000000
-#define STB0899_BTR_MIN_ENERGY			(0x0f << 24)
-#define STB0899_OFFST_BTR_MIN_ENERGY		24
-#define STB0899_WIDTH_BTR_MIN_ENERGY		4
-#define STB0899_BTR_LOCK_TH_LO			(0xff << 16)
-#define STB0899_OFFST_BTR_LOCK_TH_LO		16
-#define STB0899_WIDTH_BTR_LOCK_TH_LO		8
-#define STB0899_BTR_LOCK_TH_HI			(0xff << 8)
-#define STB0899_OFFST_BTR_LOCK_TH_HI		8
-#define STB0899_WIDTH_BTR_LOCK_TH_HI		8
-#define STB0899_BTR_LOCK_GAIN			(0x03 << 6)
-#define STB0899_OFFST_BTR_LOCK_GAIN		6
-#define STB0899_WIDTH_BTR_LOCK_GAIN		2
-#define STB0899_BTR_LOCK_LEAK			(0x3f << 0)
-#define STB0899_OFFST_BTR_LOCK_LEAK		0
-#define STB0899_WIDTH_BTR_LOCK_LEAK		6
-
-#define STB0899_OFF0_DECN_CNTRL			0xf364
-#define STB0899_BASE_DECN_CNTRL			0x00000000
-
-#define STB0899_OFF0_TP_CNTRL			0xf368
-#define STB0899_BASE_TP_CNTRL			0x00000000
-
-#define STB0899_OFF0_TP_BUF_STATUS		0xf36c
-#define STB0899_BASE_TP_BUF_STATUS		0x00000000
-#define STB0899_TP_BUFFER_FULL                  (1 << 0)
-
-#define STB0899_OFF0_DC_ESTIM			0xf37c
-#define STB0899_BASE_DC_ESTIM			0x0000
-#define STB0899_I_DC_ESTIMATE			(0xff << 8)
-#define STB0899_OFFST_I_DC_ESTIMATE		8
-#define STB0899_WIDTH_I_DC_ESTIMATE		8
-#define STB0899_Q_DC_ESTIMATE			(0xff << 0)
-#define STB0899_OFFST_Q_DC_ESTIMATE		0
-#define STB0899_WIDTH_Q_DC_ESTIMATE		8
-
-#define STB0899_OFF0_FLL_CNTRL			0xf310
-#define STB0899_BASE_FLL_CNTRL			0x00000020
-#define STB0899_CRL_FLL_ACC			(0x01 << 4)
-#define STB0899_OFFST_CRL_FLL_ACC		4
-#define STB0899_WIDTH_CRL_FLL_ACC		1
-#define STB0899_FLL_AVG_PERIOD			(0x0f << 0)
-#define STB0899_OFFST_FLL_AVG_PERIOD		0
-#define STB0899_WIDTH_FLL_AVG_PERIOD		4
-
-#define STB0899_OFF0_FLL_FREQ_WD		0xf314
-#define STB0899_BASE_FLL_FREQ_WD		0x00000020
-#define STB0899_FLL_FREQ_WD			(0xffffffff << 0)
-#define STB0899_OFFST_FLL_FREQ_WD		0
-#define STB0899_WIDTH_FLL_FREQ_WD		32
-
-#define STB0899_OFF0_ANTI_ALIAS_SEL		0xf358
-#define STB0899_BASE_ANTI_ALIAS_SEL		0x00000020
-#define STB0899_ANTI_ALIAS_SELB			(0x03 << 0)
-#define STB0899_OFFST_ANTI_ALIAS_SELB		0
-#define STB0899_WIDTH_ANTI_ALIAS_SELB		2
-
-#define STB0899_OFF0_RRC_ALPHA			0xf35c
-#define STB0899_BASE_RRC_ALPHA			0x00000020
-#define STB0899_RRC_ALPHA			(0x03 << 0)
-#define STB0899_OFFST_RRC_ALPHA			0
-#define STB0899_WIDTH_RRC_ALPHA			2
-
-#define STB0899_OFF0_DC_ADAPT_LSHFT		0xf360
-#define STB0899_BASE_DC_ADAPT_LSHFT		0x00000020
-#define STB0899_DC_ADAPT_LSHFT			(0x077 << 0)
-#define STB0899_OFFST_DC_ADAPT_LSHFT		0
-#define STB0899_WIDTH_DC_ADAPT_LSHFT		3
-
-#define STB0899_OFF0_IMB_OFFSET			0xf364
-#define STB0899_BASE_IMB_OFFSET			0x00000020
-#define STB0899_PHS_IMB_COMP			(0xff << 8)
-#define STB0899_OFFST_PHS_IMB_COMP		8
-#define STB0899_WIDTH_PHS_IMB_COMP		8
-#define STB0899_AMPL_IMB_COMP			(0xff << 0)
-#define STB0899_OFFST_AMPL_IMB_COMP		0
-#define STB0899_WIDTH_AMPL_IMB_COMP		8
-
-#define STB0899_OFF0_IMB_ESTIMATE		0xf368
-#define STB0899_BASE_IMB_ESTIMATE		0x00000020
-#define STB0899_PHS_IMB_ESTIMATE		(0xff << 8)
-#define STB0899_OFFST_PHS_IMB_ESTIMATE		8
-#define STB0899_WIDTH_PHS_IMB_ESTIMATE		8
-#define STB0899_AMPL_IMB_ESTIMATE		(0xff << 0)
-#define STB0899_OFFST_AMPL_IMB_ESTIMATE		0
-#define STB0899_WIDTH_AMPL_IMB_ESTIMATE		8
-
-#define STB0899_OFF0_IMB_CNTRL			0xf36c
-#define STB0899_BASE_IMB_CNTRL			0x00000020
-#define STB0899_PHS_ADAPT_LSHFT			(0x07 << 4)
-#define STB0899_OFFST_PHS_ADAPT_LSHFT		4
-#define STB0899_WIDTH_PHS_ADAPT_LSHFT		3
-#define STB0899_AMPL_ADAPT_LSHFT		(0x07 << 1)
-#define STB0899_OFFST_AMPL_ADAPT_LSHFT		1
-#define STB0899_WIDTH_AMPL_ADAPT_LSHFT		3
-#define STB0899_IMB_COMP			(0x01 << 0)
-#define STB0899_OFFST_IMB_COMP			0
-#define STB0899_WIDTH_IMB_COMP			1
-
-#define STB0899_OFF0_IF_AGC_CNTRL2		0xf374
-#define STB0899_BASE_IF_AGC_CNTRL2		0x00000020
-#define STB0899_IF_AGC_LOCK_TH			(0xff << 11)
-#define STB0899_OFFST_IF_AGC_LOCK_TH		11
-#define STB0899_WIDTH_IF_AGC_LOCK_TH		8
-#define STB0899_IF_AGC_SD_DIV			(0xff << 3)
-#define STB0899_OFFST_IF_AGC_SD_DIV		3
-#define STB0899_WIDTH_IF_AGC_SD_DIV		8
-#define STB0899_IF_AGC_DUMP_PER			(0x07 << 0)
-#define STB0899_OFFST_IF_AGC_DUMP_PER		0
-#define STB0899_WIDTH_IF_AGC_DUMP_PER		3
-
-#define STB0899_OFF0_DMD_CNTRL2			0xf378
-#define STB0899_BASE_DMD_CNTRL2			0x00000020
-#define STB0899_SPECTRUM_INVERT			(0x01 << 2)
-#define STB0899_OFFST_SPECTRUM_INVERT		2
-#define STB0899_WIDTH_SPECTRUM_INVERT		1
-#define STB0899_AGC_MODE			(0x01 << 1)
-#define STB0899_OFFST_AGC_MODE			1
-#define STB0899_WIDTH_AGC_MODE			1
-#define STB0899_CRL_FREQ_ADJ			(0x01 << 0)
-#define STB0899_OFFST_CRL_FREQ_ADJ		0
-#define STB0899_WIDTH_CRL_FREQ_ADJ		1
-
-#define STB0899_OFF0_TP_BUFFER			0xf300
-#define STB0899_BASE_TP_BUFFER			0x00000040
-#define STB0899_TP_BUFFER_IN			(0xffff << 0)
-#define STB0899_OFFST_TP_BUFFER_IN		0
-#define STB0899_WIDTH_TP_BUFFER_IN		16
-
-#define STB0899_OFF0_TP_BUFFER1			0xf304
-#define STB0899_BASE_TP_BUFFER1			0x00000040
-#define STB0899_OFF0_TP_BUFFER2			0xf308
-#define STB0899_BASE_TP_BUFFER2			0x00000040
-#define STB0899_OFF0_TP_BUFFER3			0xf30c
-#define STB0899_BASE_TP_BUFFER3			0x00000040
-#define STB0899_OFF0_TP_BUFFER4			0xf310
-#define STB0899_BASE_TP_BUFFER4			0x00000040
-#define STB0899_OFF0_TP_BUFFER5			0xf314
-#define STB0899_BASE_TP_BUFFER5			0x00000040
-#define STB0899_OFF0_TP_BUFFER6			0xf318
-#define STB0899_BASE_TP_BUFFER6			0x00000040
-#define STB0899_OFF0_TP_BUFFER7			0xf31c
-#define STB0899_BASE_TP_BUFFER7			0x00000040
-#define STB0899_OFF0_TP_BUFFER8			0xf320
-#define STB0899_BASE_TP_BUFFER8			0x00000040
-#define STB0899_OFF0_TP_BUFFER9			0xf324
-#define STB0899_BASE_TP_BUFFER9			0x00000040
-#define STB0899_OFF0_TP_BUFFER10		0xf328
-#define STB0899_BASE_TP_BUFFER10		0x00000040
-#define STB0899_OFF0_TP_BUFFER11		0xf32c
-#define STB0899_BASE_TP_BUFFER11		0x00000040
-#define STB0899_OFF0_TP_BUFFER12		0xf330
-#define STB0899_BASE_TP_BUFFER12		0x00000040
-#define STB0899_OFF0_TP_BUFFER13		0xf334
-#define STB0899_BASE_TP_BUFFER13		0x00000040
-#define STB0899_OFF0_TP_BUFFER14		0xf338
-#define STB0899_BASE_TP_BUFFER14		0x00000040
-#define STB0899_OFF0_TP_BUFFER15		0xf33c
-#define STB0899_BASE_TP_BUFFER15		0x00000040
-#define STB0899_OFF0_TP_BUFFER16		0xf340
-#define STB0899_BASE_TP_BUFFER16		0x00000040
-#define STB0899_OFF0_TP_BUFFER17		0xf344
-#define STB0899_BASE_TP_BUFFER17		0x00000040
-#define STB0899_OFF0_TP_BUFFER18		0xf348
-#define STB0899_BASE_TP_BUFFER18		0x00000040
-#define STB0899_OFF0_TP_BUFFER19		0xf34c
-#define STB0899_BASE_TP_BUFFER19		0x00000040
-#define STB0899_OFF0_TP_BUFFER20		0xf350
-#define STB0899_BASE_TP_BUFFER20		0x00000040
-#define STB0899_OFF0_TP_BUFFER21		0xf354
-#define STB0899_BASE_TP_BUFFER21		0x00000040
-#define STB0899_OFF0_TP_BUFFER22		0xf358
-#define STB0899_BASE_TP_BUFFER22		0x00000040
-#define STB0899_OFF0_TP_BUFFER23		0xf35c
-#define STB0899_BASE_TP_BUFFER23		0x00000040
-#define STB0899_OFF0_TP_BUFFER24		0xf360
-#define STB0899_BASE_TP_BUFFER24		0x00000040
-#define STB0899_OFF0_TP_BUFFER25		0xf364
-#define STB0899_BASE_TP_BUFFER25		0x00000040
-#define STB0899_OFF0_TP_BUFFER26		0xf368
-#define STB0899_BASE_TP_BUFFER26		0x00000040
-#define STB0899_OFF0_TP_BUFFER27		0xf36c
-#define STB0899_BASE_TP_BUFFER27		0x00000040
-#define STB0899_OFF0_TP_BUFFER28		0xf370
-#define STB0899_BASE_TP_BUFFER28		0x00000040
-#define STB0899_OFF0_TP_BUFFER29		0xf374
-#define STB0899_BASE_TP_BUFFER29		0x00000040
-#define STB0899_OFF0_TP_BUFFER30		0xf378
-#define STB0899_BASE_TP_BUFFER30		0x00000040
-#define STB0899_OFF0_TP_BUFFER31		0xf37c
-#define STB0899_BASE_TP_BUFFER31		0x00000040
-#define STB0899_OFF0_TP_BUFFER32		0xf300
-#define STB0899_BASE_TP_BUFFER32		0x00000060
-#define STB0899_OFF0_TP_BUFFER33		0xf304
-#define STB0899_BASE_TP_BUFFER33		0x00000060
-#define STB0899_OFF0_TP_BUFFER34		0xf308
-#define STB0899_BASE_TP_BUFFER34		0x00000060
-#define STB0899_OFF0_TP_BUFFER35		0xf30c
-#define STB0899_BASE_TP_BUFFER35		0x00000060
-#define STB0899_OFF0_TP_BUFFER36		0xf310
-#define STB0899_BASE_TP_BUFFER36		0x00000060
-#define STB0899_OFF0_TP_BUFFER37		0xf314
-#define STB0899_BASE_TP_BUFFER37		0x00000060
-#define STB0899_OFF0_TP_BUFFER38		0xf318
-#define STB0899_BASE_TP_BUFFER38		0x00000060
-#define STB0899_OFF0_TP_BUFFER39		0xf31c
-#define STB0899_BASE_TP_BUFFER39		0x00000060
-#define STB0899_OFF0_TP_BUFFER40		0xf320
-#define STB0899_BASE_TP_BUFFER40		0x00000060
-#define STB0899_OFF0_TP_BUFFER41		0xf324
-#define STB0899_BASE_TP_BUFFER41		0x00000060
-#define STB0899_OFF0_TP_BUFFER42		0xf328
-#define STB0899_BASE_TP_BUFFER42		0x00000060
-#define STB0899_OFF0_TP_BUFFER43		0xf32c
-#define STB0899_BASE_TP_BUFFER43		0x00000060
-#define STB0899_OFF0_TP_BUFFER44		0xf330
-#define STB0899_BASE_TP_BUFFER44		0x00000060
-#define STB0899_OFF0_TP_BUFFER45		0xf334
-#define STB0899_BASE_TP_BUFFER45		0x00000060
-#define STB0899_OFF0_TP_BUFFER46		0xf338
-#define STB0899_BASE_TP_BUFFER46		0x00000060
-#define STB0899_OFF0_TP_BUFFER47		0xf33c
-#define STB0899_BASE_TP_BUFFER47		0x00000060
-#define STB0899_OFF0_TP_BUFFER48		0xf340
-#define STB0899_BASE_TP_BUFFER48		0x00000060
-#define STB0899_OFF0_TP_BUFFER49		0xf344
-#define STB0899_BASE_TP_BUFFER49		0x00000060
-#define STB0899_OFF0_TP_BUFFER50		0xf348
-#define STB0899_BASE_TP_BUFFER50		0x00000060
-#define STB0899_OFF0_TP_BUFFER51		0xf34c
-#define STB0899_BASE_TP_BUFFER51		0x00000060
-#define STB0899_OFF0_TP_BUFFER52		0xf350
-#define STB0899_BASE_TP_BUFFER52		0x00000060
-#define STB0899_OFF0_TP_BUFFER53		0xf354
-#define STB0899_BASE_TP_BUFFER53		0x00000060
-#define STB0899_OFF0_TP_BUFFER54		0xf358
-#define STB0899_BASE_TP_BUFFER54		0x00000060
-#define STB0899_OFF0_TP_BUFFER55		0xf35c
-#define STB0899_BASE_TP_BUFFER55		0x00000060
-#define STB0899_OFF0_TP_BUFFER56		0xf360
-#define STB0899_BASE_TP_BUFFER56		0x00000060
-#define STB0899_OFF0_TP_BUFFER57		0xf364
-#define STB0899_BASE_TP_BUFFER57		0x00000060
-#define STB0899_OFF0_TP_BUFFER58		0xf368
-#define STB0899_BASE_TP_BUFFER58		0x00000060
-#define STB0899_OFF0_TP_BUFFER59		0xf36c
-#define STB0899_BASE_TP_BUFFER59		0x00000060
-#define STB0899_OFF0_TP_BUFFER60		0xf370
-#define STB0899_BASE_TP_BUFFER60		0x00000060
-#define STB0899_OFF0_TP_BUFFER61		0xf374
-#define STB0899_BASE_TP_BUFFER61		0x00000060
-#define STB0899_OFF0_TP_BUFFER62		0xf378
-#define STB0899_BASE_TP_BUFFER62		0x00000060
-#define STB0899_OFF0_TP_BUFFER63		0xf37c
-#define STB0899_BASE_TP_BUFFER63		0x00000060
-
-#define STB0899_OFF0_RESET_CNTRL		0xf300
-#define STB0899_BASE_RESET_CNTRL		0x00000400
-#define STB0899_DVBS2_RESET			(0x01 << 0)
-#define STB0899_OFFST_DVBS2_RESET		0
-#define STB0899_WIDTH_DVBS2_RESET		1
-
-#define STB0899_OFF0_ACM_ENABLE			0xf304
-#define STB0899_BASE_ACM_ENABLE			0x00000400
-#define STB0899_ACM_ENABLE			1
-
-#define STB0899_OFF0_DESCR_CNTRL		0xf30c
-#define STB0899_BASE_DESCR_CNTRL		0x00000400
-#define STB0899_OFFST_DESCR_CNTRL               0
-#define STB0899_WIDTH_DESCR_CNTRL               16
-
-#define STB0899_OFF0_UWP_CNTRL1			0xf320
-#define STB0899_BASE_UWP_CNTRL1			0x00000400
-#define STB0899_UWP_TH_SOF			(0x7fff << 11)
-#define STB0899_OFFST_UWP_TH_SOF		11
-#define STB0899_WIDTH_UWP_TH_SOF		15
-#define STB0899_UWP_ESN0_QUANT			(0xff << 3)
-#define STB0899_OFFST_UWP_ESN0_QUANT		3
-#define STB0899_WIDTH_UWP_ESN0_QUANT		8
-#define STB0899_UWP_ESN0_AVE			(0x03 << 1)
-#define STB0899_OFFST_UWP_ESN0_AVE		1
-#define STB0899_WIDTH_UWP_ESN0_AVE		2
-#define STB0899_UWP_START			(0x01 << 0)
-#define STB0899_OFFST_UWP_START			0
-#define STB0899_WIDTH_UWP_START			1
-
-#define STB0899_OFF0_UWP_CNTRL2			0xf324
-#define STB0899_BASE_UWP_CNTRL2			0x00000400
-#define STB0899_UWP_MISS_TH			(0xff << 16)
-#define STB0899_OFFST_UWP_MISS_TH		16
-#define STB0899_WIDTH_UWP_MISS_TH		8
-#define STB0899_FE_FINE_TRK			(0xff << 8)
-#define STB0899_OFFST_FE_FINE_TRK		8
-#define STB0899_WIDTH_FE_FINE_TRK		8
-#define STB0899_FE_COARSE_TRK			(0xff << 0)
-#define STB0899_OFFST_FE_COARSE_TRK		0
-#define STB0899_WIDTH_FE_COARSE_TRK		8
-
-#define STB0899_OFF0_UWP_STAT1			0xf328
-#define STB0899_BASE_UWP_STAT1			0x00000400
-#define STB0899_UWP_STATE			(0x03ff << 15)
-#define STB0899_OFFST_UWP_STATE			15
-#define STB0899_WIDTH_UWP_STATE			10
-#define STB0899_UW_MAX_PEAK			(0x7fff << 0)
-#define STB0899_OFFST_UW_MAX_PEAK		0
-#define STB0899_WIDTH_UW_MAX_PEAK		15
-
-#define STB0899_OFF0_UWP_STAT2			0xf32c
-#define STB0899_BASE_UWP_STAT2			0x00000400
-#define STB0899_ESNO_EST			(0x07ffff << 7)
-#define STB0899_OFFST_ESN0_EST			7
-#define STB0899_WIDTH_ESN0_EST			19
-#define STB0899_UWP_DECODE_MOD			(0x7f << 0)
-#define STB0899_OFFST_UWP_DECODE_MOD		0
-#define STB0899_WIDTH_UWP_DECODE_MOD		7
-
-#define STB0899_OFF0_DMD_CORE_ID		0xf334
-#define STB0899_BASE_DMD_CORE_ID		0x00000400
-#define STB0899_CORE_ID				(0xffffffff << 0)
-#define STB0899_OFFST_CORE_ID			0
-#define STB0899_WIDTH_CORE_ID			32
-
-#define STB0899_OFF0_DMD_VERSION_ID		0xf33c
-#define STB0899_BASE_DMD_VERSION_ID		0x00000400
-#define STB0899_VERSION_ID			(0xff << 0)
-#define STB0899_OFFST_VERSION_ID		0
-#define STB0899_WIDTH_VERSION_ID		8
-
-#define STB0899_OFF0_DMD_STAT2			0xf340
-#define STB0899_BASE_DMD_STAT2			0x00000400
-#define STB0899_CSM_LOCK			(0x01 << 1)
-#define STB0899_OFFST_CSM_LOCK			1
-#define STB0899_WIDTH_CSM_LOCK			1
-#define STB0899_UWP_LOCK			(0x01 << 0)
-#define STB0899_OFFST_UWP_LOCK			0
-#define STB0899_WIDTH_UWP_LOCK			1
-
-#define STB0899_OFF0_FREQ_ADJ_SCALE		0xf344
-#define STB0899_BASE_FREQ_ADJ_SCALE		0x00000400
-#define STB0899_FREQ_ADJ_SCALE			(0x0fff << 0)
-#define STB0899_OFFST_FREQ_ADJ_SCALE		0
-#define STB0899_WIDTH_FREQ_ADJ_SCALE		12
-
-#define STB0899_OFF0_UWP_CNTRL3			0xf34c
-#define STB0899_BASE_UWP_CNTRL3			0x00000400
-#define STB0899_UWP_TH_TRACK			(0x7fff << 15)
-#define STB0899_OFFST_UWP_TH_TRACK		15
-#define STB0899_WIDTH_UWP_TH_TRACK		15
-#define STB0899_UWP_TH_ACQ			(0x7fff << 0)
-#define STB0899_OFFST_UWP_TH_ACQ		0
-#define STB0899_WIDTH_UWP_TH_ACQ		15
-
-#define STB0899_OFF0_SYM_CLK_SEL		0xf350
-#define STB0899_BASE_SYM_CLK_SEL		0x00000400
-#define STB0899_SYM_CLK_SEL			(0x03 << 0)
-#define STB0899_OFFST_SYM_CLK_SEL		0
-#define STB0899_WIDTH_SYM_CLK_SEL		2
-
-#define STB0899_OFF0_SOF_SRCH_TO		0xf354
-#define STB0899_BASE_SOF_SRCH_TO		0x00000400
-#define STB0899_SOF_SEARCH_TIMEOUT		(0x3fffff << 0)
-#define STB0899_OFFST_SOF_SEARCH_TIMEOUT	0
-#define STB0899_WIDTH_SOF_SEARCH_TIMEOUT	22
-
-#define STB0899_OFF0_ACQ_CNTRL1			0xf358
-#define STB0899_BASE_ACQ_CNTRL1			0x00000400
-#define STB0899_FE_FINE_ACQ			(0xff << 8)
-#define STB0899_OFFST_FE_FINE_ACQ		8
-#define STB0899_WIDTH_FE_FINE_ACQ		8
-#define STB0899_FE_COARSE_ACQ			(0xff << 0)
-#define STB0899_OFFST_FE_COARSE_ACQ		0
-#define STB0899_WIDTH_FE_COARSE_ACQ		8
-
-#define STB0899_OFF0_ACQ_CNTRL2			0xf35c
-#define STB0899_BASE_ACQ_CNTRL2			0x00000400
-#define STB0899_ZIGZAG				(0x01 << 25)
-#define STB0899_OFFST_ZIGZAG			25
-#define STB0899_WIDTH_ZIGZAG			1
-#define STB0899_NUM_STEPS			(0xff << 17)
-#define STB0899_OFFST_NUM_STEPS			17
-#define STB0899_WIDTH_NUM_STEPS			8
-#define STB0899_FREQ_STEPSIZE			(0x1ffff << 0)
-#define STB0899_OFFST_FREQ_STEPSIZE		0
-#define STB0899_WIDTH_FREQ_STEPSIZE		17
-
-#define STB0899_OFF0_ACQ_CNTRL3			0xf360
-#define STB0899_BASE_ACQ_CNTRL3			0x00000400
-#define STB0899_THRESHOLD_SCL			(0x3f << 23)
-#define STB0899_OFFST_THRESHOLD_SCL		23
-#define STB0899_WIDTH_THRESHOLD_SCL		6
-#define STB0899_UWP_TH_SRCH			(0x7fff << 8)
-#define STB0899_OFFST_UWP_TH_SRCH		8
-#define STB0899_WIDTH_UWP_TH_SRCH		15
-#define STB0899_AUTO_REACQUIRE			(0x01 << 7)
-#define STB0899_OFFST_AUTO_REACQUIRE		7
-#define STB0899_WIDTH_AUTO_REACQUIRE		1
-#define STB0899_TRACK_LOCK_SEL			(0x01 << 6)
-#define STB0899_OFFST_TRACK_LOCK_SEL		6
-#define STB0899_WIDTH_TRACK_LOCK_SEL		1
-#define STB0899_ACQ_SEARCH_MODE			(0x03 << 4)
-#define STB0899_OFFST_ACQ_SEARCH_MODE		4
-#define STB0899_WIDTH_ACQ_SEARCH_MODE		2
-#define STB0899_CONFIRM_FRAMES			(0x0f << 0)
-#define STB0899_OFFST_CONFIRM_FRAMES		0
-#define STB0899_WIDTH_CONFIRM_FRAMES		4
-
-#define STB0899_OFF0_FE_SETTLE			0xf364
-#define STB0899_BASE_FE_SETTLE			0x00000400
-#define STB0899_SETTLING_TIME			(0x3fffff << 0)
-#define STB0899_OFFST_SETTLING_TIME		0
-#define STB0899_WIDTH_SETTLING_TIME		22
-
-#define STB0899_OFF0_AC_DWELL			0xf368
-#define STB0899_BASE_AC_DWELL			0x00000400
-#define STB0899_DWELL_TIME			(0x3fffff << 0)
-#define STB0899_OFFST_DWELL_TIME		0
-#define STB0899_WIDTH_DWELL_TIME		22
-
-#define STB0899_OFF0_ACQUIRE_TRIG		0xf36c
-#define STB0899_BASE_ACQUIRE_TRIG		0x00000400
-#define STB0899_ACQUIRE				(0x01 << 0)
-#define STB0899_OFFST_ACQUIRE			0
-#define STB0899_WIDTH_ACQUIRE			1
-
-#define STB0899_OFF0_LOCK_LOST			0xf370
-#define STB0899_BASE_LOCK_LOST			0x00000400
-#define STB0899_LOCK_LOST			(0x01 << 0)
-#define STB0899_OFFST_LOCK_LOST			0
-#define STB0899_WIDTH_LOCK_LOST			1
-
-#define STB0899_OFF0_ACQ_STAT1			0xf374
-#define STB0899_BASE_ACQ_STAT1			0x00000400
-#define STB0899_STEP_FREQ			(0x1fffff << 11)
-#define STB0899_OFFST_STEP_FREQ			11
-#define STB0899_WIDTH_STEP_FREQ			21
-#define STB0899_ACQ_STATE			(0x07 << 8)
-#define STB0899_OFFST_ACQ_STATE			8
-#define STB0899_WIDTH_ACQ_STATE			3
-#define STB0899_UW_DETECT_COUNT			(0xff << 0)
-#define STB0899_OFFST_UW_DETECT_COUNT		0
-#define STB0899_WIDTH_UW_DETECT_COUNT		8
-
-#define STB0899_OFF0_ACQ_TIMEOUT		0xf378
-#define STB0899_BASE_ACQ_TIMEOUT		0x00000400
-#define STB0899_ACQ_TIMEOUT			(0x3fffff << 0)
-#define STB0899_OFFST_ACQ_TIMEOUT		0
-#define STB0899_WIDTH_ACQ_TIMEOUT		22
-
-#define STB0899_OFF0_ACQ_TIME			0xf37c
-#define STB0899_BASE_ACQ_TIME			0x00000400
-#define STB0899_ACQ_TIME_SYM			(0xffffff << 0)
-#define STB0899_OFFST_ACQ_TIME_SYM		0
-#define STB0899_WIDTH_ACQ_TIME_SYM		24
-
-#define STB0899_OFF0_FINAL_AGC_CNTRL		0xf308
-#define STB0899_BASE_FINAL_AGC_CNTRL		0x00000440
-#define STB0899_FINAL_GAIN_INIT			(0x3fff << 12)
-#define STB0899_OFFST_FINAL_GAIN_INIT		12
-#define STB0899_WIDTH_FINAL_GAIN_INIT		14
-#define STB0899_FINAL_LOOP_GAIN			(0x0f << 8)
-#define STB0899_OFFST_FINAL_LOOP_GAIN		8
-#define STB0899_WIDTH_FINAL_LOOP_GAIN		4
-#define STB0899_FINAL_LD_GAIN_INIT		(0x01 << 7)
-#define STB0899_OFFST_FINAL_LD_GAIN_INIT	7
-#define STB0899_WIDTH_FINAL_LD_GAIN_INIT	1
-#define STB0899_FINAL_AGC_REF			(0x7f << 0)
-#define STB0899_OFFST_FINAL_AGC_REF		0
-#define STB0899_WIDTH_FINAL_AGC_REF		7
-
-#define STB0899_OFF0_FINAL_AGC_GAIN		0xf30c
-#define STB0899_BASE_FINAL_AGC_GAIN		0x00000440
-#define STB0899_FINAL_AGC_GAIN			(0x3fff << 0)
-#define STB0899_OFFST_FINAL_AGC_GAIN		0
-#define STB0899_WIDTH_FINAL_AGC_GAIN		14
-
-#define STB0899_OFF0_EQUALIZER_INIT		0xf310
-#define STB0899_BASE_EQUALIZER_INIT		0x00000440
-#define STB0899_EQ_SRST				(0x01 << 1)
-#define STB0899_OFFST_EQ_SRST			1
-#define STB0899_WIDTH_EQ_SRST			1
-#define STB0899_EQ_INIT				(0x01 << 0)
-#define STB0899_OFFST_EQ_INIT			0
-#define STB0899_WIDTH_EQ_INIT			1
-
-#define STB0899_OFF0_EQ_CNTRL			0xf314
-#define STB0899_BASE_EQ_CNTRL			0x00000440
-#define STB0899_EQ_ADAPT_MODE			(0x01 << 18)
-#define STB0899_OFFST_EQ_ADAPT_MODE		18
-#define STB0899_WIDTH_EQ_ADAPT_MODE		1
-#define STB0899_EQ_DELAY			(0x0f << 14)
-#define STB0899_OFFST_EQ_DELAY			14
-#define STB0899_WIDTH_EQ_DELAY			4
-#define STB0899_EQ_QUANT_LEVEL			(0xff << 6)
-#define STB0899_OFFST_EQ_QUANT_LEVEL		6
-#define STB0899_WIDTH_EQ_QUANT_LEVEL		8
-#define STB0899_EQ_DISABLE_UPDATE		(0x01 << 5)
-#define STB0899_OFFST_EQ_DISABLE_UPDATE		5
-#define STB0899_WIDTH_EQ_DISABLE_UPDATE		1
-#define STB0899_EQ_BYPASS			(0x01 << 4)
-#define STB0899_OFFST_EQ_BYPASS			4
-#define STB0899_WIDTH_EQ_BYPASS			1
-#define STB0899_EQ_SHIFT			(0x0f << 0)
-#define STB0899_OFFST_EQ_SHIFT			0
-#define STB0899_WIDTH_EQ_SHIFT			4
-
-#define STB0899_OFF0_EQ_I_INIT_COEFF_0		0xf320
-#define STB0899_OFF1_EQ_I_INIT_COEFF_1		0xf324
-#define STB0899_OFF2_EQ_I_INIT_COEFF_2		0xf328
-#define STB0899_OFF3_EQ_I_INIT_COEFF_3		0xf32c
-#define STB0899_OFF4_EQ_I_INIT_COEFF_4		0xf330
-#define STB0899_OFF5_EQ_I_INIT_COEFF_5		0xf334
-#define STB0899_OFF6_EQ_I_INIT_COEFF_6		0xf338
-#define STB0899_OFF7_EQ_I_INIT_COEFF_7		0xf33c
-#define STB0899_OFF8_EQ_I_INIT_COEFF_8		0xf340
-#define STB0899_OFF9_EQ_I_INIT_COEFF_9		0xf344
-#define STB0899_OFFa_EQ_I_INIT_COEFF_10		0xf348
-#define STB0899_BASE_EQ_I_INIT_COEFF_N		0x00000440
-#define STB0899_EQ_I_INIT_COEFF_N		(0x0fff << 0)
-#define STB0899_OFFST_EQ_I_INIT_COEFF_N		0
-#define STB0899_WIDTH_EQ_I_INIT_COEFF_N		12
-
-#define STB0899_OFF0_EQ_Q_INIT_COEFF_0		0xf350
-#define STB0899_OFF1_EQ_Q_INIT_COEFF_1		0xf354
-#define STB0899_OFF2_EQ_Q_INIT_COEFF_2		0xf358
-#define STB0899_OFF3_EQ_Q_INIT_COEFF_3		0xf35c
-#define STB0899_OFF4_EQ_Q_INIT_COEFF_4		0xf360
-#define STB0899_OFF5_EQ_Q_INIT_COEFF_5		0xf364
-#define STB0899_OFF6_EQ_Q_INIT_COEFF_6		0xf368
-#define STB0899_OFF7_EQ_Q_INIT_COEFF_7		0xf36c
-#define STB0899_OFF8_EQ_Q_INIT_COEFF_8		0xf370
-#define STB0899_OFF9_EQ_Q_INIT_COEFF_9		0xf374
-#define STB0899_OFFa_EQ_Q_INIT_COEFF_10		0xf378
-#define STB0899_BASE_EQ_Q_INIT_COEFF_N		0x00000440
-#define STB0899_EQ_Q_INIT_COEFF_N		(0x0fff << 0)
-#define STB0899_OFFST_EQ_Q_INIT_COEFF_N		0
-#define STB0899_WIDTH_EQ_Q_INIT_COEFF_N		12
-
-#define STB0899_OFF0_EQ_I_OUT_COEFF_0		0xf300
-#define STB0899_OFF1_EQ_I_OUT_COEFF_1		0xf304
-#define STB0899_OFF2_EQ_I_OUT_COEFF_2		0xf308
-#define STB0899_OFF3_EQ_I_OUT_COEFF_3		0xf30c
-#define STB0899_OFF4_EQ_I_OUT_COEFF_4		0xf310
-#define STB0899_OFF5_EQ_I_OUT_COEFF_5		0xf314
-#define STB0899_OFF6_EQ_I_OUT_COEFF_6		0xf318
-#define STB0899_OFF7_EQ_I_OUT_COEFF_7		0xf31c
-#define STB0899_OFF8_EQ_I_OUT_COEFF_8		0xf320
-#define STB0899_OFF9_EQ_I_OUT_COEFF_9		0xf324
-#define STB0899_OFFa_EQ_I_OUT_COEFF_10		0xf328
-#define STB0899_BASE_EQ_I_OUT_COEFF_N		0x00000460
-#define STB0899_EQ_I_OUT_COEFF_N		(0x0fff << 0)
-#define STB0899_OFFST_EQ_I_OUT_COEFF_N		0
-#define STB0899_WIDTH_EQ_I_OUT_COEFF_N		12
-
-#define STB0899_OFF0_EQ_Q_OUT_COEFF_0		0xf330
-#define STB0899_OFF1_EQ_Q_OUT_COEFF_1		0xf334
-#define STB0899_OFF2_EQ_Q_OUT_COEFF_2		0xf338
-#define STB0899_OFF3_EQ_Q_OUT_COEFF_3		0xf33c
-#define STB0899_OFF4_EQ_Q_OUT_COEFF_4		0xf340
-#define STB0899_OFF5_EQ_Q_OUT_COEFF_5		0xf344
-#define STB0899_OFF6_EQ_Q_OUT_COEFF_6		0xf348
-#define STB0899_OFF7_EQ_Q_OUT_COEFF_7		0xf34c
-#define STB0899_OFF8_EQ_Q_OUT_COEFF_8		0xf350
-#define STB0899_OFF9_EQ_Q_OUT_COEFF_9		0xf354
-#define STB0899_OFFa_EQ_Q_OUT_COEFF_10		0xf358
-#define STB0899_BASE_EQ_Q_OUT_COEFF_N		0x00000460
-#define STB0899_EQ_Q_OUT_COEFF_N		(0x0fff << 0)
-#define STB0899_OFFST_EQ_Q_OUT_COEFF_N		0
-#define STB0899_WIDTH_EQ_Q_OUT_COEFF_N		12
-
-/*	S2 FEC	*/
-#define STB0899_OFF0_BLOCK_LNGTH		0xfa04
-#define STB0899_BASE_BLOCK_LNGTH		0x00000000
-#define STB0899_BLOCK_LENGTH			(0xff << 0)
-#define STB0899_OFFST_BLOCK_LENGTH		0
-#define STB0899_WIDTH_BLOCK_LENGTH		8
-
-#define STB0899_OFF0_ROW_STR			0xfa08
-#define STB0899_BASE_ROW_STR			0x00000000
-#define STB0899_ROW_STRIDE			(0xff << 0)
-#define STB0899_OFFST_ROW_STRIDE		0
-#define STB0899_WIDTH_ROW_STRIDE		8
-
-#define STB0899_OFF0_MAX_ITER			0xfa0c
-#define STB0899_BASE_MAX_ITER			0x00000000
-#define STB0899_MAX_ITERATIONS			(0xff << 0)
-#define STB0899_OFFST_MAX_ITERATIONS		0
-#define STB0899_WIDTH_MAX_ITERATIONS		8
-
-#define STB0899_OFF0_BN_END_ADDR		0xfa10
-#define STB0899_BASE_BN_END_ADDR		0x00000000
-#define STB0899_BN_END_ADDR			(0x0fff << 0)
-#define STB0899_OFFST_BN_END_ADDR		0
-#define STB0899_WIDTH_BN_END_ADDR		12
-
-#define STB0899_OFF0_CN_END_ADDR		0xfa14
-#define STB0899_BASE_CN_END_ADDR		0x00000000
-#define STB0899_CN_END_ADDR			(0x0fff << 0)
-#define STB0899_OFFST_CN_END_ADDR		0
-#define STB0899_WIDTH_CN_END_ADDR		12
-
-#define STB0899_OFF0_INFO_LENGTH		0xfa1c
-#define STB0899_BASE_INFO_LENGTH		0x00000000
-#define STB0899_INFO_LENGTH			(0xff << 0)
-#define STB0899_OFFST_INFO_LENGTH		0
-#define STB0899_WIDTH_INFO_LENGTH		8
-
-#define STB0899_OFF0_BOT_ADDR			0xfa20
-#define STB0899_BASE_BOT_ADDR			0x00000000
-#define STB0899_BOTTOM_BASE_ADDR		(0x03ff << 0)
-#define STB0899_OFFST_BOTTOM_BASE_ADDR		0
-#define STB0899_WIDTH_BOTTOM_BASE_ADDR		10
-
-#define STB0899_OFF0_BCH_BLK_LN			0xfa24
-#define STB0899_BASE_BCH_BLK_LN			0x00000000
-#define STB0899_BCH_BLOCK_LENGTH		(0xffff << 0)
-#define STB0899_OFFST_BCH_BLOCK_LENGTH		0
-#define STB0899_WIDTH_BCH_BLOCK_LENGTH		16
-
-#define STB0899_OFF0_BCH_T			0xfa28
-#define STB0899_BASE_BCH_T			0x00000000
-#define STB0899_BCH_T				(0x0f << 0)
-#define STB0899_OFFST_BCH_T			0
-#define STB0899_WIDTH_BCH_T			4
-
-#define STB0899_OFF0_CNFG_MODE			0xfa00
-#define STB0899_BASE_CNFG_MODE			0x00000800
-#define STB0899_MODCOD				(0x1f << 2)
-#define STB0899_OFFST_MODCOD			2
-#define STB0899_WIDTH_MODCOD			5
-#define STB0899_MODCOD_SEL			(0x01 << 1)
-#define STB0899_OFFST_MODCOD_SEL		1
-#define STB0899_WIDTH_MODCOD_SEL		1
-#define STB0899_CONFIG_MODE			(0x01 << 0)
-#define STB0899_OFFST_CONFIG_MODE		0
-#define STB0899_WIDTH_CONFIG_MODE		1
-
-#define STB0899_OFF0_LDPC_STAT			0xfa04
-#define STB0899_BASE_LDPC_STAT			0x00000800
-#define STB0899_ITERATION			(0xff << 3)
-#define STB0899_OFFST_ITERATION			3
-#define STB0899_WIDTH_ITERATION			8
-#define STB0899_LDPC_DEC_STATE			(0x07 << 0)
-#define STB0899_OFFST_LDPC_DEC_STATE		0
-#define STB0899_WIDTH_LDPC_DEC_STATE		3
-
-#define STB0899_OFF0_ITER_SCALE			0xfa08
-#define STB0899_BASE_ITER_SCALE			0x00000800
-#define STB0899_ITERATION_SCALE			(0xff << 0)
-#define STB0899_OFFST_ITERATION_SCALE		0
-#define STB0899_WIDTH_ITERATION_SCALE		8
-
-#define STB0899_OFF0_INPUT_MODE			0xfa0c
-#define STB0899_BASE_INPUT_MODE			0x00000800
-#define STB0899_SD_BLOCK1_STREAM0		(0x01 << 0)
-#define STB0899_OFFST_SD_BLOCK1_STREAM0		0
-#define STB0899_WIDTH_SD_BLOCK1_STREAM0		1
-
-#define STB0899_OFF0_LDPCDECRST			0xfa10
-#define STB0899_BASE_LDPCDECRST			0x00000800
-#define STB0899_LDPC_DEC_RST			(0x01 << 0)
-#define STB0899_OFFST_LDPC_DEC_RST		0
-#define STB0899_WIDTH_LDPC_DEC_RST		1
-
-#define STB0899_OFF0_CLK_PER_BYTE_RW		0xfa14
-#define STB0899_BASE_CLK_PER_BYTE_RW		0x00000800
-#define STB0899_CLKS_PER_BYTE			(0x0f << 0)
-#define STB0899_OFFST_CLKS_PER_BYTE		0
-#define STB0899_WIDTH_CLKS_PER_BYTE		5
-
-#define STB0899_OFF0_BCH_ERRORS			0xfa18
-#define STB0899_BASE_BCH_ERRORS			0x00000800
-#define STB0899_BCH_ERRORS			(0x0f << 0)
-#define STB0899_OFFST_BCH_ERRORS		0
-#define STB0899_WIDTH_BCH_ERRORS		4
-
-#define STB0899_OFF0_LDPC_ERRORS		0xfa1c
-#define STB0899_BASE_LDPC_ERRORS		0x00000800
-#define STB0899_LDPC_ERRORS			(0xffff << 0)
-#define STB0899_OFFST_LDPC_ERRORS		0
-#define STB0899_WIDTH_LDPC_ERRORS		16
-
-#define STB0899_OFF0_BCH_MODE			0xfa20
-#define STB0899_BASE_BCH_MODE			0x00000800
-#define STB0899_BCH_CORRECT_N			(0x01 << 1)
-#define STB0899_OFFST_BCH_CORRECT_N		1
-#define STB0899_WIDTH_BCH_CORRECT_N		1
-#define STB0899_FULL_BYPASS			(0x01 << 0)
-#define STB0899_OFFST_FULL_BYPASS		0
-#define STB0899_WIDTH_FULL_BYPASS		1
-
-#define STB0899_OFF0_ERR_ACC_PER		0xfa24
-#define STB0899_BASE_ERR_ACC_PER		0x00000800
-#define STB0899_BCH_ERR_ACC_PERIOD		(0x0f << 0)
-#define STB0899_OFFST_BCH_ERR_ACC_PERIOD	0
-#define STB0899_WIDTH_BCH_ERR_ACC_PERIOD	4
-
-#define STB0899_OFF0_BCH_ERR_ACC		0xfa28
-#define STB0899_BASE_BCH_ERR_ACC		0x00000800
-#define STB0899_BCH_ERR_ACCUM			(0xff << 0)
-#define STB0899_OFFST_BCH_ERR_ACCUM		0
-#define STB0899_WIDTH_BCH_ERR_ACCUM		8
-
-#define STB0899_OFF0_FEC_CORE_ID_REG		0xfa2c
-#define STB0899_BASE_FEC_CORE_ID_REG		0x00000800
-#define STB0899_FEC_CORE_ID			(0xffffffff << 0)
-#define STB0899_OFFST_FEC_CORE_ID		0
-#define STB0899_WIDTH_FEC_CORE_ID		32
-
-#define STB0899_OFF0_FEC_VER_ID_REG		0xfa34
-#define STB0899_BASE_FEC_VER_ID_REG		0x00000800
-#define STB0899_FEC_VER_ID			(0xff << 0)
-#define STB0899_OFFST_FEC_VER_ID		0
-#define STB0899_WIDTH_FEC_VER_ID		8
-
-#define STB0899_OFF0_FEC_TP_SEL			0xfa38
-#define STB0899_BASE_FEC_TP_SEL			0x00000800
-
-#define STB0899_OFF0_CSM_CNTRL1			0xf310
-#define STB0899_BASE_CSM_CNTRL1			0x00000400
-#define STB0899_CSM_FORCE_FREQLOCK		(0x01 << 19)
-#define STB0899_OFFST_CSM_FORCE_FREQLOCK	19
-#define STB0899_WIDTH_CSM_FORCE_FREQLOCK	1
-#define STB0899_CSM_FREQ_LOCKSTATE		(0x01 << 18)
-#define STB0899_OFFST_CSM_FREQ_LOCKSTATE	18
-#define STB0899_WIDTH_CSM_FREQ_LOCKSTATE	1
-#define STB0899_CSM_AUTO_PARAM			(0x01 << 17)
-#define STB0899_OFFST_CSM_AUTO_PARAM		17
-#define STB0899_WIDTH_CSM_AUTO_PARAM		1
-#define STB0899_FE_LOOP_SHIFT			(0x07 << 14)
-#define STB0899_OFFST_FE_LOOP_SHIFT		14
-#define STB0899_WIDTH_FE_LOOP_SHIFT		3
-#define STB0899_CSM_AGC_SHIFT			(0x07 << 11)
-#define STB0899_OFFST_CSM_AGC_SHIFT		11
-#define STB0899_WIDTH_CSM_AGC_SHIFT		3
-#define STB0899_CSM_AGC_GAIN			(0x1ff << 2)
-#define STB0899_OFFST_CSM_AGC_GAIN		2
-#define STB0899_WIDTH_CSM_AGC_GAIN		9
-#define STB0899_CSM_TWO_PASS			(0x01 << 1)
-#define STB0899_OFFST_CSM_TWO_PASS		1
-#define STB0899_WIDTH_CSM_TWO_PASS		1
-#define STB0899_CSM_DVT_TABLE			(0x01 << 0)
-#define STB0899_OFFST_CSM_DVT_TABLE		0
-#define STB0899_WIDTH_CSM_DVT_TABLE		1
-
-#define STB0899_OFF0_CSM_CNTRL2			0xf314
-#define STB0899_BASE_CSM_CNTRL2			0x00000400
-#define STB0899_CSM_GAMMA_RHO_ACQ		(0x1ff << 9)
-#define STB0899_OFFST_CSM_GAMMA_RHOACQ		9
-#define STB0899_WIDTH_CSM_GAMMA_RHOACQ		9
-#define STB0899_CSM_GAMMA_ACQ			(0x1ff << 0)
-#define STB0899_OFFST_CSM_GAMMA_ACQ		0
-#define STB0899_WIDTH_CSM_GAMMA_ACQ		9
-
-#define STB0899_OFF0_CSM_CNTRL3			0xf318
-#define STB0899_BASE_CSM_CNTRL3			0x00000400
-#define STB0899_CSM_GAMMA_RHO_TRACK		(0x1ff << 9)
-#define STB0899_OFFST_CSM_GAMMA_RHOTRACK	9
-#define STB0899_WIDTH_CSM_GAMMA_RHOTRACK	9
-#define STB0899_CSM_GAMMA_TRACK			(0x1ff << 0)
-#define STB0899_OFFST_CSM_GAMMA_TRACK		0
-#define STB0899_WIDTH_CSM_GAMMA_TRACK		9
-
-#define STB0899_OFF0_CSM_CNTRL4			0xf31c
-#define STB0899_BASE_CSM_CNTRL4			0x00000400
-#define STB0899_CSM_PHASEDIFF_THRESH		(0x0f << 8)
-#define STB0899_OFFST_CSM_PHASEDIFF_THRESH	8
-#define STB0899_WIDTH_CSM_PHASEDIFF_THRESH	4
-#define STB0899_CSM_LOCKCOUNT_THRESH		(0xff << 0)
-#define STB0899_OFFST_CSM_LOCKCOUNT_THRESH	0
-#define STB0899_WIDTH_CSM_LOCKCOUNT_THRESH	8
-
-/*	Check on chapter 8 page 42	*/
-#define STB0899_ERRCTRL1			0xf574
-#define STB0899_ERRCTRL2			0xf575
-#define STB0899_ERRCTRL3			0xf576
-#define STB0899_ERR_SRC_S1			(0x1f << 3)
-#define STB0899_OFFST_ERR_SRC_S1		3
-#define STB0899_WIDTH_ERR_SRC_S1		5
-#define STB0899_ERR_SRC_S2			(0x0f << 0)
-#define STB0899_OFFST_ERR_SRC_S2		0
-#define STB0899_WIDTH_ERR_SRC_S2		4
-#define STB0899_NOE				(0x07 << 0)
-#define STB0899_OFFST_NOE			0
-#define STB0899_WIDTH_NOE			3
-
-#define STB0899_ECNT1M				0xf524
-#define STB0899_ECNT1L				0xf525
-#define STB0899_ECNT2M				0xf526
-#define STB0899_ECNT2L				0xf527
-#define STB0899_ECNT3M				0xf528
-#define STB0899_ECNT3L				0xf529
-
-#define STB0899_DMONMSK1			0xf57b
-#define STB0899_DMONMSK1_WAIT_1STEP		(1 << 7)
-#define STB0899_DMONMSK1_FREE_14		(1 << 6)
-#define STB0899_DMONMSK1_AVRGVIT_CALC		(1 << 5)
-#define STB0899_DMONMSK1_FREE_12		(1 << 4)
-#define STB0899_DMONMSK1_FREE_11		(1 << 3)
-#define STB0899_DMONMSK1_B0DIV_CALC		(1 << 2)
-#define STB0899_DMONMSK1_KDIVB1_CALC		(1 << 1)
-#define STB0899_DMONMSK1_KDIVB2_CALC		(1 << 0)
-
-#define STB0899_DMONMSK0			0xf57c
-#define STB0899_DMONMSK0_SMOTTH_CALC		(1 << 7)
-#define STB0899_DMONMSK0_FREE_6			(1 << 6)
-#define STB0899_DMONMSK0_SIGPOWER_CALC		(1 << 5)
-#define STB0899_DMONMSK0_QSEUIL_CALC		(1 << 4)
-#define STB0899_DMONMSK0_FREE_3			(1 << 3)
-#define STB0899_DMONMSK0_FREE_2			(1 << 2)
-#define STB0899_DMONMSK0_KVDIVB1_CALC		(1 << 1)
-#define STB0899_DMONMSK0_KVDIVB2_CALC		(1 << 0)
-
-#define STB0899_TSULC				0xf549
-#define STB0899_ULNOSYNCBYTES			(0x01 << 7)
-#define STB0899_OFFST_ULNOSYNCBYTES		7
-#define STB0899_WIDTH_ULNOSYNCBYTES		1
-#define STB0899_ULPARITY_ON			(0x01 << 6)
-#define STB0899_OFFST_ULPARITY_ON		6
-#define STB0899_WIDTH_ULPARITY_ON		1
-#define STB0899_ULSYNCOUTRS			(0x01 << 5)
-#define STB0899_OFFST_ULSYNCOUTRS		5
-#define STB0899_WIDTH_ULSYNCOUTRS		1
-#define STB0899_ULDSS_PACKETS			(0x01 << 0)
-#define STB0899_OFFST_ULDSS_PACKETS		0
-#define STB0899_WIDTH_ULDSS_PACKETS		1
-
-#define STB0899_TSLPL				0xf54b
-#define STB0899_LLDVBS2_MODE			(0x01 << 4)
-#define STB0899_OFFST_LLDVBS2_MODE		4
-#define STB0899_WIDTH_LLDVBS2_MODE		1
-#define STB0899_LLISSYI_ON			(0x01 << 3)
-#define STB0899_OFFST_LLISSYI_ON		3
-#define STB0899_WIDTH_LLISSYI_ON		1
-#define STB0899_LLNPD_ON			(0x01 << 2)
-#define STB0899_OFFST_LLNPD_ON			2
-#define STB0899_WIDTH_LLNPD_ON			1
-#define STB0899_LLCRC8_ON			(0x01 << 1)
-#define STB0899_OFFST_LLCRC8_ON			1
-#define STB0899_WIDTH_LLCRC8_ON			1
-
-#define STB0899_TSCFGH				0xf54c
-#define STB0899_OUTRS_PS			(0x01 << 6)
-#define STB0899_OFFST_OUTRS_PS			6
-#define STB0899_WIDTH_OUTRS_PS			1
-#define STB0899_SYNCBYTE			(0x01 << 5)
-#define STB0899_OFFST_SYNCBYTE			5
-#define STB0899_WIDTH_SYNCBYTE			1
-#define STB0899_PFBIT				(0x01 << 4)
-#define STB0899_OFFST_PFBIT			4
-#define STB0899_WIDTH_PFBIT			1
-#define STB0899_ERR_BIT				(0x01 << 3)
-#define STB0899_OFFST_ERR_BIT			3
-#define STB0899_WIDTH_ERR_BIT			1
-#define STB0899_MPEG				(0x01 << 2)
-#define STB0899_OFFST_MPEG			2
-#define STB0899_WIDTH_MPEG			1
-#define STB0899_CLK_POL				(0x01 << 1)
-#define STB0899_OFFST_CLK_POL			1
-#define STB0899_WIDTH_CLK_POL			1
-#define STB0899_FORCE0				(0x01 << 0)
-#define STB0899_OFFST_FORCE0			0
-#define STB0899_WIDTH_FORCE0			1
-
-#define STB0899_TSCFGM				0xf54d
-#define STB0899_LLPRIORITY			(0x01 << 3)
-#define STB0899_OFFST_LLPRIORIY			3
-#define STB0899_WIDTH_LLPRIORITY		1
-#define STB0899_EN188				(0x01 << 2)
-#define STB0899_OFFST_EN188			2
-#define STB0899_WIDTH_EN188			1
-
-#define STB0899_TSCFGL				0xf54e
-#define STB0899_DEL_ERRPCK			(0x01 << 7)
-#define STB0899_OFFST_DEL_ERRPCK		7
-#define STB0899_WIDTH_DEL_ERRPCK		1
-#define STB0899_ERRFLAGSTD			(0x01 << 5)
-#define STB0899_OFFST_ERRFLAGSTD		5
-#define STB0899_WIDTH_ERRFLAGSTD		1
-#define STB0899_MPEGERR				(0x01 << 4)
-#define STB0899_OFFST_MPEGERR			4
-#define STB0899_WIDTH_MPEGERR			1
-#define STB0899_BCH_CHK				(0x01 << 3)
-#define STB0899_OFFST_BCH_CHK			5
-#define STB0899_WIDTH_BCH_CHK			1
-#define STB0899_CRC8CHK				(0x01 << 2)
-#define STB0899_OFFST_CRC8CHK			2
-#define STB0899_WIDTH_CRC8CHK			1
-#define STB0899_SPEC_INFO			(0x01 << 1)
-#define STB0899_OFFST_SPEC_INFO			1
-#define STB0899_WIDTH_SPEC_INFO			1
-#define STB0899_LOW_PRIO_CLK			(0x01 << 0)
-#define STB0899_OFFST_LOW_PRIO_CLK		0
-#define STB0899_WIDTH_LOW_PRIO_CLK		1
-#define STB0899_ERROR_NORM			(0x00 << 0)
-#define STB0899_OFFST_ERROR_NORM		0
-#define STB0899_WIDTH_ERROR_NORM		0
-
-#define STB0899_TSOUT				0xf54f
-#define STB0899_RSSYNCDEL			0xf550
-#define STB0899_TSINHDELH			0xf551
-#define STB0899_TSINHDELM			0xf552
-#define STB0899_TSINHDELL			0xf553
-#define STB0899_TSLLSTKM			0xf55a
-#define STB0899_TSLLSTKL			0xf55b
-#define STB0899_TSULSTKM			0xf55c
-#define STB0899_TSULSTKL			0xf55d
-#define STB0899_TSSTATUS			0xf561
-
-#define STB0899_PDELCTRL			0xf600
-#define STB0899_INVERT_RES			(0x01 << 7)
-#define STB0899_OFFST_INVERT_RES		7
-#define STB0899_WIDTH_INVERT_RES		1
-#define STB0899_FORCE_ACCEPTED			(0x01 << 6)
-#define STB0899_OFFST_FORCE_ACCEPTED		6
-#define STB0899_WIDTH_FORCE_ACCEPTED		1
-#define STB0899_FILTER_EN			(0x01 << 5)
-#define STB0899_OFFST_FILTER_EN			5
-#define STB0899_WIDTH_FILTER_EN			1
-#define STB0899_LOCKFALL_THRESH			(0x01 << 4)
-#define STB0899_OFFST_LOCKFALL_THRESH		4
-#define STB0899_WIDTH_LOCKFALL_THRESH		1
-#define STB0899_HYST_EN				(0x01 << 3)
-#define STB0899_OFFST_HYST_EN			3
-#define STB0899_WIDTH_HYST_EN			1
-#define STB0899_HYST_SWRST			(0x01 << 2)
-#define STB0899_OFFST_HYST_SWRST		2
-#define STB0899_WIDTH_HYST_SWRST		1
-#define STB0899_ALGO_EN				(0x01 << 1)
-#define STB0899_OFFST_ALGO_EN			1
-#define STB0899_WIDTH_ALGO_EN			1
-#define STB0899_ALGO_SWRST			(0x01 << 0)
-#define STB0899_OFFST_ALGO_SWRST		0
-#define STB0899_WIDTH_ALGO_SWRST		1
-
-#define STB0899_PDELCTRL2			0xf601
-#define STB0899_BBHCTRL1			0xf602
-#define STB0899_BBHCTRL2			0xf603
-#define STB0899_HYSTTHRESH			0xf604
-
-#define STB0899_MATCSTM				0xf605
-#define STB0899_MATCSTL				0xf606
-#define STB0899_UPLCSTM				0xf607
-#define STB0899_UPLCSTL				0xf608
-#define STB0899_DFLCSTM				0xf609
-#define STB0899_DFLCSTL				0xf60a
-#define STB0899_SYNCCST				0xf60b
-#define STB0899_SYNCDCSTM			0xf60c
-#define STB0899_SYNCDCSTL			0xf60d
-#define STB0899_ISI_ENTRY			0xf60e
-#define STB0899_ISI_BIT_EN			0xf60f
-#define STB0899_MATSTRM				0xf610
-#define STB0899_MATSTRL				0xf611
-#define STB0899_UPLSTRM				0xf612
-#define STB0899_UPLSTRL				0xf613
-#define STB0899_DFLSTRM				0xf614
-#define STB0899_DFLSTRL				0xf615
-#define STB0899_SYNCSTR				0xf616
-#define STB0899_SYNCDSTRM			0xf617
-#define STB0899_SYNCDSTRL			0xf618
-
-#define STB0899_CFGPDELSTATUS1			0xf619
-#define STB0899_BADDFL				(0x01 << 6)
-#define STB0899_OFFST_BADDFL			6
-#define STB0899_WIDTH_BADDFL			1
-#define STB0899_CONTINUOUS_STREAM		(0x01 << 5)
-#define STB0899_OFFST_CONTINUOUS_STREAM		5
-#define STB0899_WIDTH_CONTINUOUS_STREAM		1
-#define STB0899_ACCEPTED_STREAM			(0x01 << 4)
-#define STB0899_OFFST_ACCEPTED_STREAM		4
-#define STB0899_WIDTH_ACCEPTED_STREAM		1
-#define STB0899_BCH_ERRFLAG			(0x01 << 3)
-#define STB0899_OFFST_BCH_ERRFLAG		3
-#define STB0899_WIDTH_BCH_ERRFLAG		1
-#define STB0899_CRCRES				(0x01 << 2)
-#define STB0899_OFFST_CRCRES			2
-#define STB0899_WIDTH_CRCRES			1
-#define STB0899_CFGPDELSTATUS_LOCK		(0x01 << 1)
-#define STB0899_OFFST_CFGPDELSTATUS_LOCK	1
-#define STB0899_WIDTH_CFGPDELSTATUS_LOCK	1
-#define STB0899_1STLOCK				(0x01 << 0)
-#define STB0899_OFFST_1STLOCK			0
-#define STB0899_WIDTH_1STLOCK			1
-
-#define STB0899_CFGPDELSTATUS2			0xf61a
-#define STB0899_BBFERRORM			0xf61b
-#define STB0899_BBFERRORL			0xf61c
-#define STB0899_UPKTERRORM			0xf61d
-#define STB0899_UPKTERRORL			0xf61e
-
-#define STB0899_TSTCK				0xff10
-
-#define STB0899_TSTRES				0xff11
-#define STB0899_FRESLDPC			(0x01 << 7)
-#define STB0899_OFFST_FRESLDPC			7
-#define STB0899_WIDTH_FRESLDPC			1
-#define STB0899_FRESRS				(0x01 << 6)
-#define STB0899_OFFST_FRESRS			6
-#define STB0899_WIDTH_FRESRS			1
-#define STB0899_FRESVIT				(0x01 << 5)
-#define STB0899_OFFST_FRESVIT			5
-#define STB0899_WIDTH_FRESVIT			1
-#define STB0899_FRESMAS1_2			(0x01 << 4)
-#define STB0899_OFFST_FRESMAS1_2		4
-#define STB0899_WIDTH_FRESMAS1_2		1
-#define STB0899_FRESACS				(0x01 << 3)
-#define STB0899_OFFST_FRESACS			3
-#define STB0899_WIDTH_FRESACS			1
-#define STB0899_FRESSYM				(0x01 << 2)
-#define STB0899_OFFST_FRESSYM			2
-#define STB0899_WIDTH_FRESSYM			1
-#define STB0899_FRESMAS				(0x01 << 1)
-#define STB0899_OFFST_FRESMAS			1
-#define STB0899_WIDTH_FRESMAS			1
-#define STB0899_FRESINT				(0x01 << 0)
-#define STB0899_OFFST_FRESINIT			0
-#define STB0899_WIDTH_FRESINIT			1
-
-#define STB0899_TSTOUT				0xff12
-#define STB0899_EN_SIGNATURE			(0x01 << 7)
-#define STB0899_OFFST_EN_SIGNATURE		7
-#define STB0899_WIDTH_EN_SIGNATURE		1
-#define STB0899_BCLK_CLK			(0x01 << 6)
-#define STB0899_OFFST_BCLK_CLK			6
-#define STB0899_WIDTH_BCLK_CLK			1
-#define STB0899_SGNL_OUT			(0x01 << 5)
-#define STB0899_OFFST_SGNL_OUT			5
-#define STB0899_WIDTH_SGNL_OUT			1
-#define STB0899_TS				(0x01 << 4)
-#define STB0899_OFFST_TS			4
-#define STB0899_WIDTH_TS			1
-#define STB0899_CTEST				(0x01 << 0)
-#define STB0899_OFFST_CTEST			0
-#define STB0899_WIDTH_CTEST			1
-
-#define STB0899_TSTIN				0xff13
-#define STB0899_TEST_IN				(0x01 << 7)
-#define STB0899_OFFST_TEST_IN			7
-#define STB0899_WIDTH_TEST_IN			1
-#define STB0899_EN_ADC				(0x01 << 6)
-#define STB0899_OFFST_EN_ADC			6
-#define STB0899_WIDTH_ENADC			1
-#define STB0899_SGN_ADC				(0x01 << 5)
-#define STB0899_OFFST_SGN_ADC			5
-#define STB0899_WIDTH_SGN_ADC			1
-#define STB0899_BCLK_IN				(0x01 << 4)
-#define STB0899_OFFST_BCLK_IN			4
-#define STB0899_WIDTH_BCLK_IN			1
-#define STB0899_JETONIN_MODE			(0x01 << 3)
-#define STB0899_OFFST_JETONIN_MODE		3
-#define STB0899_WIDTH_JETONIN_MODE		1
-#define STB0899_BCLK_VALUE			(0x01 << 2)
-#define STB0899_OFFST_BCLK_VALUE		2
-#define STB0899_WIDTH_BCLK_VALUE		1
-#define STB0899_SGNRST_T12			(0x01 << 1)
-#define STB0899_OFFST_SGNRST_T12		1
-#define STB0899_WIDTH_SGNRST_T12		1
-#define STB0899_LOWSP_ENAX			(0x01 << 0)
-#define STB0899_OFFST_LOWSP_ENAX		0
-#define STB0899_WIDTH_LOWSP_ENAX		1
-
-#define STB0899_TSTSYS				0xff14
-#define STB0899_TSTCHIP				0xff15
-#define STB0899_TSTFREE				0xff16
-#define STB0899_TSTI2C				0xff17
-#define STB0899_BITSPEEDM			0xff1c
-#define STB0899_BITSPEEDL			0xff1d
-#define STB0899_TBUSBIT				0xff1e
-#define STB0899_TSTDIS				0xff24
-#define STB0899_TSTDISRX			0xff25
-#define STB0899_TSTJETON			0xff28
-#define STB0899_TSTDCADJ			0xff40
-#define STB0899_TSTAGC1				0xff41
-#define STB0899_TSTAGC1N			0xff42
-#define STB0899_TSTPOLYPH			0xff48
-#define STB0899_TSTR				0xff49
-#define STB0899_TSTAGC2				0xff4a
-#define STB0899_TSTCTL1				0xff4b
-#define STB0899_TSTCTL2				0xff4c
-#define STB0899_TSTCTL3				0xff4d
-#define STB0899_TSTDEMAP			0xff50
-#define STB0899_TSTDEMAP2			0xff51
-#define STB0899_TSTDEMMON			0xff52
-#define STB0899_TSTRATE				0xff53
-#define STB0899_TSTSELOUT			0xff54
-#define STB0899_TSYNC				0xff55
-#define STB0899_TSTERR				0xff56
-#define STB0899_TSTRAM1				0xff58
-#define STB0899_TSTVSELOUT			0xff59
-#define STB0899_TSTFORCEIN			0xff5a
-#define STB0899_TSTRS1				0xff5c
-#define STB0899_TSTRS2				0xff5d
-#define STB0899_TSTRS3				0xff53
-
-#define STB0899_INTBUFSTATUS			0xf200
-#define STB0899_INTBUFCTRL			0xf201
-#define STB0899_PCKLENUL			0xf55e
-#define STB0899_PCKLENLL			0xf55f
-#define STB0899_RSPCKLEN			0xf560
-
-/*	2 registers	*/
-#define STB0899_SYNCDCST			0xf60c
-
-/*	DiSEqC	*/
-#define STB0899_DISCNTRL1			0xf0a0
-#define STB0899_TIMOFF				(0x01 << 7)
-#define STB0899_OFFST_TIMOFF			7
-#define STB0899_WIDTH_TIMOFF			1
-#define STB0899_DISEQCRESET			(0x01 << 6)
-#define STB0899_OFFST_DISEQCRESET		6
-#define STB0899_WIDTH_DISEQCRESET		1
-#define STB0899_TIMCMD				(0x03 << 4)
-#define STB0899_OFFST_TIMCMD			4
-#define STB0899_WIDTH_TIMCMD			2
-#define STB0899_DISPRECHARGE			(0x01 << 2)
-#define STB0899_OFFST_DISPRECHARGE		2
-#define STB0899_WIDTH_DISPRECHARGE		1
-#define STB0899_DISEQCMODE			(0x03 << 0)
-#define STB0899_OFFST_DISEQCMODE		0
-#define STB0899_WIDTH_DISEQCMODE		2
-
-#define STB0899_DISCNTRL2			0xf0a1
-#define STB0899_RECEIVER_ON			(0x01 << 7)
-#define STB0899_OFFST_RECEIVER_ON		7
-#define STB0899_WIDTH_RECEIVER_ON		1
-#define STB0899_IGNO_SHORT_22K			(0x01 << 6)
-#define STB0899_OFFST_IGNO_SHORT_22K		6
-#define STB0899_WIDTH_IGNO_SHORT_22K		1
-#define STB0899_ONECHIP_TRX			(0x01 << 5)
-#define STB0899_OFFST_ONECHIP_TRX		5
-#define STB0899_WIDTH_ONECHIP_TRX		1
-#define STB0899_EXT_ENVELOP			(0x01 << 4)
-#define STB0899_OFFST_EXT_ENVELOP		4
-#define STB0899_WIDTH_EXT_ENVELOP		1
-#define STB0899_PIN_SELECT			(0x03 << 2)
-#define STB0899_OFFST_PIN_SELCT			2
-#define STB0899_WIDTH_PIN_SELCT			2
-#define STB0899_IRQ_RXEND			(0x01 << 1)
-#define STB0899_OFFST_IRQ_RXEND			1
-#define STB0899_WIDTH_IRQ_RXEND			1
-#define STB0899_IRQ_4NBYTES			(0x01 << 0)
-#define STB0899_OFFST_IRQ_4NBYTES		0
-#define STB0899_WIDTH_IRQ_4NBYTES		1
-
-#define STB0899_DISRX_ST0			0xf0a4
-#define STB0899_RXEND				(0x01 << 7)
-#define STB0899_OFFST_RXEND			7
-#define STB0899_WIDTH_RXEND			1
-#define STB0899_RXACTIVE			(0x01 << 6)
-#define STB0899_OFFST_RXACTIVE			6
-#define STB0899_WIDTH_RXACTIVE			1
-#define STB0899_SHORT22K			(0x01 << 5)
-#define STB0899_OFFST_SHORT22K			5
-#define STB0899_WIDTH_SHORT22K			1
-#define STB0899_CONTTONE			(0x01 << 4)
-#define STB0899_OFFST_CONTTONE			4
-#define STB0899_WIDTH_CONTONE			1
-#define STB0899_4BFIFOREDY			(0x01 << 3)
-#define STB0899_OFFST_4BFIFOREDY		3
-#define STB0899_WIDTH_4BFIFOREDY		1
-#define STB0899_FIFOEMPTY			(0x01 << 2)
-#define STB0899_OFFST_FIFOEMPTY			2
-#define STB0899_WIDTH_FIFOEMPTY			1
-#define STB0899_ABORTTRX			(0x01 << 0)
-#define STB0899_OFFST_ABORTTRX			0
-#define STB0899_WIDTH_ABORTTRX			1
-
-#define STB0899_DISRX_ST1			0xf0a5
-#define STB0899_RXFAIL				(0x01 << 7)
-#define STB0899_OFFST_RXFAIL			7
-#define STB0899_WIDTH_RXFAIL			1
-#define STB0899_FIFOPFAIL			(0x01 << 6)
-#define STB0899_OFFST_FIFOPFAIL			6
-#define STB0899_WIDTH_FIFOPFAIL			1
-#define STB0899_RXNONBYTES			(0x01 << 5)
-#define STB0899_OFFST_RXNONBYTES		5
-#define STB0899_WIDTH_RXNONBYTES		1
-#define STB0899_FIFOOVF				(0x01 << 4)
-#define STB0899_OFFST_FIFOOVF			4
-#define STB0899_WIDTH_FIFOOVF			1
-#define STB0899_FIFOBYTENBR			(0x0f << 0)
-#define STB0899_OFFST_FIFOBYTENBR		0
-#define STB0899_WIDTH_FIFOBYTENBR		4
-
-#define STB0899_DISPARITY			0xf0a6
-
-#define STB0899_DISFIFO				0xf0a7
-
-#define STB0899_DISSTATUS			0xf0a8
-#define STB0899_FIFOFULL			(0x01 << 6)
-#define STB0899_OFFST_FIFOFULL			6
-#define STB0899_WIDTH_FIFOFULL			1
-#define STB0899_TXIDLE				(0x01 << 5)
-#define STB0899_OFFST_TXIDLE			5
-#define STB0899_WIDTH_TXIDLE			1
-#define STB0899_GAPBURST			(0x01 << 4)
-#define STB0899_OFFST_GAPBURST			4
-#define STB0899_WIDTH_GAPBURST			1
-#define STB0899_TXFIFOBYTES			(0x0f << 0)
-#define STB0899_OFFST_TXFIFOBYTES		0
-#define STB0899_WIDTH_TXFIFOBYTES		4
-#define STB0899_DISF22				0xf0a9
-
-#define STB0899_DISF22RX			0xf0aa
-
-/*	General Purpose	*/
-#define STB0899_SYSREG				0xf101
-#define STB0899_ACRPRESC			0xf110
-#define STB0899_OFFST_RSVD2			7
-#define STB0899_WIDTH_RSVD2			1
-#define STB0899_OFFST_ACRPRESC			4
-#define STB0899_WIDTH_ACRPRESC			3
-#define STB0899_OFFST_RSVD1			3
-#define STB0899_WIDTH_RSVD1			1
-#define STB0899_OFFST_ACRPRESC2			0
-#define STB0899_WIDTH_ACRPRESC2			3
-
-#define STB0899_ACRDIV1				0xf111
-#define STB0899_ACRDIV2				0xf112
-#define STB0899_DACR1				0xf113
-#define STB0899_DACR2				0xf114
-#define STB0899_OUTCFG				0xf11c
-#define STB0899_MODECFG				0xf11d
-#define STB0899_NCOARSE				0xf1b3
-
-#define STB0899_SYNTCTRL			0xf1b6
-#define STB0899_STANDBY				(0x01 << 7)
-#define STB0899_OFFST_STANDBY			7
-#define STB0899_WIDTH_STANDBY			1
-#define STB0899_BYPASSPLL			(0x01 << 6)
-#define STB0899_OFFST_BYPASSPLL			6
-#define STB0899_WIDTH_BYPASSPLL			1
-#define STB0899_SEL1XRATIO			(0x01 << 5)
-#define STB0899_OFFST_SEL1XRATIO		5
-#define STB0899_WIDTH_SEL1XRATIO		1
-#define STB0899_SELOSCI				(0x01 << 1)
-#define STB0899_OFFST_SELOSCI			1
-#define STB0899_WIDTH_SELOSCI			1
-
-#define STB0899_FILTCTRL			0xf1b7
-#define STB0899_SYSCTRL				0xf1b8
-
-#define STB0899_STOPCLK1			0xf1c2
-#define STB0899_STOP_CKINTBUF108		(0x01 << 7)
-#define STB0899_OFFST_STOP_CKINTBUF108		7
-#define STB0899_WIDTH_STOP_CKINTBUF108		1
-#define STB0899_STOP_CKINTBUF216		(0x01 << 6)
-#define STB0899_OFFST_STOP_CKINTBUF216		6
-#define STB0899_WIDTH_STOP_CKINTBUF216		1
-#define STB0899_STOP_CHK8PSK			(0x01 << 5)
-#define STB0899_OFFST_STOP_CHK8PSK		5
-#define STB0899_WIDTH_STOP_CHK8PSK		1
-#define STB0899_STOP_CKFEC108			(0x01 << 4)
-#define STB0899_OFFST_STOP_CKFEC108		4
-#define STB0899_WIDTH_STOP_CKFEC108		1
-#define STB0899_STOP_CKFEC216			(0x01 << 3)
-#define STB0899_OFFST_STOP_CKFEC216		3
-#define STB0899_WIDTH_STOP_CKFEC216		1
-#define STB0899_STOP_CKCORE216			(0x01 << 2)
-#define STB0899_OFFST_STOP_CKCORE216		2
-#define STB0899_WIDTH_STOP_CKCORE216		1
-#define STB0899_STOP_CKADCI108			(0x01 << 1)
-#define STB0899_OFFST_STOP_CKADCI108		1
-#define STB0899_WIDTH_STOP_CKADCI108		1
-#define STB0899_STOP_INVCKADCI108		(0x01 << 0)
-#define STB0899_OFFST_STOP_INVCKADCI108		0
-#define STB0899_WIDTH_STOP_INVCKADCI108		1
-
-#define STB0899_STOPCLK2			0xf1c3
-#define STB0899_STOP_CKS2DMD108			(0x01 << 2)
-#define STB0899_OFFST_STOP_CKS2DMD108		2
-#define STB0899_WIDTH_STOP_CKS2DMD108		1
-#define STB0899_STOP_CKPKDLIN108		(0x01 << 1)
-#define STB0899_OFFST_STOP_CKPKDLIN108		1
-#define STB0899_WIDTH_STOP_CKPKDLIN108		1
-#define STB0899_STOP_CKPKDLIN216		(0x01 << 0)
-#define STB0899_OFFST_STOP_CKPKDLIN216		0
-#define STB0899_WIDTH_STOP_CKPKDLIN216		1
-
-#define STB0899_TSTTNR1				0xf1e0
-#define STB0899_BYPASS_ADC			(0x01 << 7)
-#define STB0899_OFFST_BYPASS_ADC		7
-#define STB0899_WIDTH_BYPASS_ADC		1
-#define STB0899_INVADCICKOUT			(0x01 << 6)
-#define STB0899_OFFST_INVADCICKOUT		6
-#define STB0899_WIDTH_INVADCICKOUT		1
-#define STB0899_ADCTEST_VOLTAGE			(0x03 << 4)
-#define STB0899_OFFST_ADCTEST_VOLTAGE		4
-#define STB0899_WIDTH_ADCTEST_VOLTAGE		1
-#define STB0899_ADC_RESET			(0x01 << 3)
-#define STB0899_OFFST_ADC_RESET			3
-#define STB0899_WIDTH_ADC_RESET			1
-#define STB0899_TSTTNR1_2			(0x01 << 2)
-#define STB0899_OFFST_TSTTNR1_2			2
-#define STB0899_WIDTH_TSTTNR1_2			1
-#define STB0899_ADCPON				(0x01 << 1)
-#define STB0899_OFFST_ADCPON			1
-#define STB0899_WIDTH_ADCPON			1
-#define STB0899_ADCIN_MODE			(0x01 << 0)
-#define STB0899_OFFST_ADCIN_MODE		0
-#define STB0899_WIDTH_ADCIN_MODE		1
-
-#define STB0899_TSTTNR2				0xf1e1
-#define STB0899_TSTTNR2_7			(0x01 << 7)
-#define STB0899_OFFST_TSTTNR2_7			7
-#define STB0899_WIDTH_TSTTNR2_7			1
-#define STB0899_NOT_DISRX_WIRED			(0x01 << 6)
-#define STB0899_OFFST_NOT_DISRX_WIRED		6
-#define STB0899_WIDTH_NOT_DISRX_WIRED		1
-#define STB0899_DISEQC_DCURRENT			(0x01 << 5)
-#define STB0899_OFFST_DISEQC_DCURRENT		5
-#define STB0899_WIDTH_DISEQC_DCURRENT		1
-#define STB0899_DISEQC_ZCURRENT			(0x01 << 4)
-#define STB0899_OFFST_DISEQC_ZCURRENT		4
-#define STB0899_WIDTH_DISEQC_ZCURRENT		1
-#define STB0899_DISEQC_SINC_SOURCE		(0x03 << 2)
-#define STB0899_OFFST_DISEQC_SINC_SOURCE	2
-#define STB0899_WIDTH_DISEQC_SINC_SOURCE	2
-#define STB0899_SELIQSRC			(0x03 << 0)
-#define STB0899_OFFST_SELIQSRC			0
-#define STB0899_WIDTH_SELIQSRC			2
-
-#define STB0899_TSTTNR3				0xf1e2
-
-#define STB0899_I2CCFG				0xf129
-#define STB0899_I2CCFGRSVD			(0x0f << 4)
-#define STB0899_OFFST_I2CCFGRSVD		4
-#define STB0899_WIDTH_I2CCFGRSVD		4
-#define STB0899_I2CFASTMODE			(0x01 << 3)
-#define STB0899_OFFST_I2CFASTMODE		3
-#define STB0899_WIDTH_I2CFASTMODE		1
-#define STB0899_STATUSWR			(0x01 << 2)
-#define STB0899_OFFST_STATUSWR			2
-#define STB0899_WIDTH_STATUSWR			1
-#define STB0899_I2CADDRINC			(0x03 << 0)
-#define STB0899_OFFST_I2CADDRINC		0
-#define STB0899_WIDTH_I2CADDRINC		2
-
-#define STB0899_I2CRPT				0xf12a
-#define STB0899_I2CTON				(0x01 << 7)
-#define STB0899_OFFST_I2CTON			7
-#define STB0899_WIDTH_I2CTON			1
-#define STB0899_ENARPTLEVEL			(0x01 << 6)
-#define STB0899_OFFST_ENARPTLEVEL		6
-#define STB0899_WIDTH_ENARPTLEVEL		2
-#define STB0899_SCLTDELAY			(0x01 << 3)
-#define STB0899_OFFST_SCLTDELAY			3
-#define STB0899_WIDTH_SCLTDELAY			1
-#define STB0899_STOPENA				(0x01 << 2)
-#define STB0899_OFFST_STOPENA			2
-#define STB0899_WIDTH_STOPENA			1
-#define STB0899_STOPSDAT2SDA			(0x01 << 1)
-#define STB0899_OFFST_STOPSDAT2SDA		1
-#define STB0899_WIDTH_STOPSDAT2SDA		1
-
-#define STB0899_IOPVALUE8			0xf136
-#define STB0899_IOPVALUE7			0xf137
-#define STB0899_IOPVALUE6			0xf138
-#define STB0899_IOPVALUE5			0xf139
-#define STB0899_IOPVALUE4			0xf13a
-#define STB0899_IOPVALUE3			0xf13b
-#define STB0899_IOPVALUE2			0xf13c
-#define STB0899_IOPVALUE1			0xf13d
-#define STB0899_IOPVALUE0			0xf13e
-
-#define STB0899_GPIO00CFG			0xf140
-
-#define STB0899_GPIO01CFG			0xf141
-#define STB0899_GPIO02CFG			0xf142
-#define STB0899_GPIO03CFG			0xf143
-#define STB0899_GPIO04CFG			0xf144
-#define STB0899_GPIO05CFG			0xf145
-#define STB0899_GPIO06CFG			0xf146
-#define STB0899_GPIO07CFG			0xf147
-#define STB0899_GPIO08CFG			0xf148
-#define STB0899_GPIO09CFG			0xf149
-#define STB0899_GPIO10CFG			0xf14a
-#define STB0899_GPIO11CFG			0xf14b
-#define STB0899_GPIO12CFG			0xf14c
-#define STB0899_GPIO13CFG			0xf14d
-#define STB0899_GPIO14CFG			0xf14e
-#define STB0899_GPIO15CFG			0xf14f
-#define STB0899_GPIO16CFG			0xf150
-#define STB0899_GPIO17CFG			0xf151
-#define STB0899_GPIO18CFG			0xf152
-#define STB0899_GPIO19CFG			0xf153
-#define STB0899_GPIO20CFG			0xf154
-
-#define STB0899_SDATCFG				0xf155
-#define STB0899_SCLTCFG				0xf156
-#define STB0899_AGCRFCFG			0xf157
-#define STB0899_GPIO22				0xf158	/* AGCBB2CFG	*/
-#define STB0899_GPIO21				0xf159  /* AGCBB1CFG	*/
-#define STB0899_DIRCLKCFG			0xf15a
-#define STB0899_CLKOUT27CFG			0xf15b
-#define STB0899_STDBYCFG			0xf15c
-#define STB0899_CS0CFG				0xf15d
-#define STB0899_CS1CFG				0xf15e
-#define STB0899_DISEQCOCFG			0xf15f
-
-#define STB0899_GPIO32CFG			0xf160
-#define STB0899_GPIO33CFG			0xf161
-#define STB0899_GPIO34CFG			0xf162
-#define STB0899_GPIO35CFG			0xf163
-#define STB0899_GPIO36CFG			0xf164
-#define STB0899_GPIO37CFG			0xf165
-#define STB0899_GPIO38CFG			0xf166
-#define STB0899_GPIO39CFG			0xf167
-
-#define STB0899_IRQSTATUS_3			0xf120
-#define STB0899_IRQSTATUS_2			0xf121
-#define STB0899_IRQSTATUS_1			0xf122
-#define STB0899_IRQSTATUS_0			0xf123
-
-#define STB0899_IRQMSK_3			0xf124
-#define STB0899_IRQMSK_2			0xf125
-#define STB0899_IRQMSK_1			0xf126
-#define STB0899_IRQMSK_0			0xf127
-
-#define STB0899_IRQCFG				0xf128
-
-#define STB0899_GHOSTREG			0xf000
-
-#define STB0899_S2DEMOD				0xf3fc
-#define STB0899_S2FEC				0xfafc
-
-
-#endif
diff --git a/drivers/media/dvb/frontends/stb6000.c b/drivers/media/dvb/frontends/stb6000.c
deleted file mode 100644
index a0c3c52..0000000
--- a/drivers/media/dvb/frontends/stb6000.c
+++ /dev/null
@@ -1,256 +0,0 @@
-  /*
-     Driver for ST STB6000 DVBS Silicon tuner
-
-     Copyright (C) 2008 Igor M. Liplianin (liplianin@me.by)
-
-     This program is free software; you can redistribute it and/or modify
-     it under the terms of the 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/slab.h>
-#include <linux/module.h>
-#include <linux/dvb/frontend.h>
-#include <asm/types.h>
-
-#include "stb6000.h"
-
-static int debug;
-#define dprintk(args...) \
-	do { \
-		if (debug) \
-			printk(KERN_DEBUG "stb6000: " args); \
-	} while (0)
-
-struct stb6000_priv {
-	/* i2c details */
-	int i2c_address;
-	struct i2c_adapter *i2c;
-	u32 frequency;
-};
-
-static int stb6000_release(struct dvb_frontend *fe)
-{
-	kfree(fe->tuner_priv);
-	fe->tuner_priv = NULL;
-	return 0;
-}
-
-static int stb6000_sleep(struct dvb_frontend *fe)
-{
-	struct stb6000_priv *priv = fe->tuner_priv;
-	int ret;
-	u8 buf[] = { 10, 0 };
-	struct i2c_msg msg = {
-		.addr = priv->i2c_address,
-		.flags = 0,
-		.buf = buf,
-		.len = 2
-	};
-
-	dprintk("%s:\n", __func__);
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-
-	ret = i2c_transfer(priv->i2c, &msg, 1);
-	if (ret != 1)
-		dprintk("%s: i2c error\n", __func__);
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0);
-
-	return (ret == 1) ? 0 : ret;
-}
-
-static int stb6000_set_params(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct stb6000_priv *priv = fe->tuner_priv;
-	unsigned int n, m;
-	int ret;
-	u32 freq_mhz;
-	int bandwidth;
-	u8 buf[12];
-	struct i2c_msg msg = {
-		.addr = priv->i2c_address,
-		.flags = 0,
-		.buf = buf,
-		.len = 12
-	};
-
-	dprintk("%s:\n", __func__);
-
-	freq_mhz = p->frequency / 1000;
-	bandwidth = p->symbol_rate / 1000000;
-
-	if (bandwidth > 31)
-		bandwidth = 31;
-
-	if ((freq_mhz > 949) && (freq_mhz < 2151)) {
-		buf[0] = 0x01;
-		buf[1] = 0xac;
-		if (freq_mhz < 1950)
-			buf[1] = 0xaa;
-		if (freq_mhz < 1800)
-			buf[1] = 0xa8;
-		if (freq_mhz < 1650)
-			buf[1] = 0xa6;
-		if (freq_mhz < 1530)
-			buf[1] = 0xa5;
-		if (freq_mhz < 1470)
-			buf[1] = 0xa4;
-		if (freq_mhz < 1370)
-			buf[1] = 0xa2;
-		if (freq_mhz < 1300)
-			buf[1] = 0xa1;
-		if (freq_mhz < 1200)
-			buf[1] = 0xa0;
-		if (freq_mhz < 1075)
-			buf[1] = 0xbc;
-		if (freq_mhz < 1000)
-			buf[1] = 0xba;
-		if (freq_mhz < 1075) {
-			n = freq_mhz / 8; /* vco=lo*4 */
-			m = 2;
-		} else {
-			n = freq_mhz / 16; /* vco=lo*2 */
-			m = 1;
-		}
-		buf[2] = n >> 1;
-		buf[3] = (unsigned char)(((n & 1) << 7) |
-					(m * freq_mhz - n * 16) | 0x60);
-		buf[4] = 0x04;
-		buf[5] = 0x0e;
-
-		buf[6] = (unsigned char)(bandwidth);
-
-		buf[7] = 0xd8;
-		buf[8] = 0xd0;
-		buf[9] = 0x50;
-		buf[10] = 0xeb;
-		buf[11] = 0x4f;
-
-		if (fe->ops.i2c_gate_ctrl)
-			fe->ops.i2c_gate_ctrl(fe, 1);
-
-		ret = i2c_transfer(priv->i2c, &msg, 1);
-		if (ret != 1)
-			dprintk("%s: i2c error\n", __func__);
-
-		udelay(10);
-		if (fe->ops.i2c_gate_ctrl)
-			fe->ops.i2c_gate_ctrl(fe, 0);
-
-		buf[0] = 0x07;
-		buf[1] = 0xdf;
-		buf[2] = 0xd0;
-		buf[3] = 0x50;
-		buf[4] = 0xfb;
-		msg.len = 5;
-
-		if (fe->ops.i2c_gate_ctrl)
-			fe->ops.i2c_gate_ctrl(fe, 1);
-
-		ret = i2c_transfer(priv->i2c, &msg, 1);
-		if (ret != 1)
-			dprintk("%s: i2c error\n", __func__);
-
-		udelay(10);
-		if (fe->ops.i2c_gate_ctrl)
-			fe->ops.i2c_gate_ctrl(fe, 0);
-
-		priv->frequency = freq_mhz * 1000;
-
-		return (ret == 1) ? 0 : ret;
-	}
-	return -1;
-}
-
-static int stb6000_get_frequency(struct dvb_frontend *fe, u32 *frequency)
-{
-	struct stb6000_priv *priv = fe->tuner_priv;
-	*frequency = priv->frequency;
-	return 0;
-}
-
-static struct dvb_tuner_ops stb6000_tuner_ops = {
-	.info = {
-		.name = "ST STB6000",
-		.frequency_min = 950000,
-		.frequency_max = 2150000
-	},
-	.release = stb6000_release,
-	.sleep = stb6000_sleep,
-	.set_params = stb6000_set_params,
-	.get_frequency = stb6000_get_frequency,
-};
-
-struct dvb_frontend *stb6000_attach(struct dvb_frontend *fe, int addr,
-						struct i2c_adapter *i2c)
-{
-	struct stb6000_priv *priv = NULL;
-	u8 b0[] = { 0 };
-	u8 b1[] = { 0, 0 };
-	struct i2c_msg msg[2] = {
-		{
-			.addr = addr,
-			.flags = 0,
-			.buf = b0,
-			.len = 0
-		}, {
-			.addr = addr,
-			.flags = I2C_M_RD,
-			.buf = b1,
-			.len = 2
-		}
-	};
-	int ret;
-
-	dprintk("%s:\n", __func__);
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-
-	/* is some i2c device here ? */
-	ret = i2c_transfer(i2c, msg, 2);
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0);
-
-	if (ret != 2)
-		return NULL;
-
-	priv = kzalloc(sizeof(struct stb6000_priv), GFP_KERNEL);
-	if (priv == NULL)
-		return NULL;
-
-	priv->i2c_address = addr;
-	priv->i2c = i2c;
-
-	memcpy(&fe->ops.tuner_ops, &stb6000_tuner_ops,
-				sizeof(struct dvb_tuner_ops));
-
-	fe->tuner_priv = priv;
-
-	return fe;
-}
-EXPORT_SYMBOL(stb6000_attach);
-
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
-
-MODULE_DESCRIPTION("DVB STB6000 driver");
-MODULE_AUTHOR("Igor M. Liplianin <liplianin@me.by>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/stb6000.h b/drivers/media/dvb/frontends/stb6000.h
deleted file mode 100644
index 7be479c..0000000
--- a/drivers/media/dvb/frontends/stb6000.h
+++ /dev/null
@@ -1,51 +0,0 @@
-  /*
-     Driver for ST stb6000 DVBS Silicon tuner
-
-     Copyright (C) 2008 Igor M. Liplianin (liplianin@me.by)
-
-     This program is free software; you can redistribute it and/or modify
-     it under the terms of the 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_STB6000_H__
-#define __DVB_STB6000_H__
-
-#include <linux/i2c.h>
-#include "dvb_frontend.h"
-
-/**
- * Attach a stb6000 tuner to the supplied frontend structure.
- *
- * @param fe Frontend to attach to.
- * @param addr i2c address of the tuner.
- * @param i2c i2c adapter to use.
- * @return FE pointer on success, NULL on failure.
- */
-#if defined(CONFIG_DVB_STB6000) || (defined(CONFIG_DVB_STB6000_MODULE) \
-							&& defined(MODULE))
-extern struct dvb_frontend *stb6000_attach(struct dvb_frontend *fe, int addr,
-					   struct i2c_adapter *i2c);
-#else
-static inline struct dvb_frontend *stb6000_attach(struct dvb_frontend *fe,
-						  int addr,
-						  struct i2c_adapter *i2c)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif /* CONFIG_DVB_STB6000 */
-
-#endif /* __DVB_STB6000_H__ */
diff --git a/drivers/media/dvb/frontends/stb6100.c b/drivers/media/dvb/frontends/stb6100.c
deleted file mode 100644
index 2e93e65..0000000
--- a/drivers/media/dvb/frontends/stb6100.c
+++ /dev/null
@@ -1,611 +0,0 @@
-/*
-	STB6100 Silicon Tuner
-	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
-
-	Copyright (C) ST Microelectronics
-
-	This program is free software; you can redistribute it and/or modify
-	it under the terms of the 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/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-
-#include "dvb_frontend.h"
-#include "stb6100.h"
-
-static unsigned int verbose;
-module_param(verbose, int, 0644);
-
-
-#define FE_ERROR		0
-#define FE_NOTICE		1
-#define FE_INFO			2
-#define FE_DEBUG		3
-
-#define dprintk(x, y, z, format, arg...) do {						\
-	if (z) {									\
-		if	((x > FE_ERROR) && (x > y))					\
-			printk(KERN_ERR "%s: " format "\n", __func__ , ##arg);		\
-		else if	((x > FE_NOTICE) && (x > y))					\
-			printk(KERN_NOTICE "%s: " format "\n", __func__ , ##arg);	\
-		else if ((x > FE_INFO) && (x > y))					\
-			printk(KERN_INFO "%s: " format "\n", __func__ , ##arg);		\
-		else if ((x > FE_DEBUG) && (x > y))					\
-			printk(KERN_DEBUG "%s: " format "\n", __func__ , ##arg);	\
-	} else {									\
-		if (x > y)								\
-			printk(format, ##arg);						\
-	}										\
-} while (0)
-
-struct stb6100_lkup {
-	u32 val_low;
-	u32 val_high;
-	u8   reg;
-};
-
-static int stb6100_release(struct dvb_frontend *fe);
-
-static const struct stb6100_lkup lkup[] = {
-	{       0,  950000, 0x0a },
-	{  950000, 1000000, 0x0a },
-	{ 1000000, 1075000, 0x0c },
-	{ 1075000, 1200000, 0x00 },
-	{ 1200000, 1300000, 0x01 },
-	{ 1300000, 1370000, 0x02 },
-	{ 1370000, 1470000, 0x04 },
-	{ 1470000, 1530000, 0x05 },
-	{ 1530000, 1650000, 0x06 },
-	{ 1650000, 1800000, 0x08 },
-	{ 1800000, 1950000, 0x0a },
-	{ 1950000, 2150000, 0x0c },
-	{ 2150000, 9999999, 0x0c },
-	{       0,       0, 0x00 }
-};
-
-/* Register names for easy debugging.	*/
-static const char *stb6100_regnames[] = {
-	[STB6100_LD]		= "LD",
-	[STB6100_VCO]		= "VCO",
-	[STB6100_NI]		= "NI",
-	[STB6100_NF_LSB]	= "NF",
-	[STB6100_K]		= "K",
-	[STB6100_G]		= "G",
-	[STB6100_F]		= "F",
-	[STB6100_DLB]		= "DLB",
-	[STB6100_TEST1]		= "TEST1",
-	[STB6100_FCCK]		= "FCCK",
-	[STB6100_LPEN]		= "LPEN",
-	[STB6100_TEST3]		= "TEST3",
-};
-
-/* Template for normalisation, i.e. setting unused or undocumented
- * bits as required according to the documentation.
- */
-struct stb6100_regmask {
-	u8 mask;
-	u8 set;
-};
-
-static const struct stb6100_regmask stb6100_template[] = {
-	[STB6100_LD]		= { 0xff, 0x00 },
-	[STB6100_VCO]		= { 0xff, 0x00 },
-	[STB6100_NI]		= { 0xff, 0x00 },
-	[STB6100_NF_LSB]	= { 0xff, 0x00 },
-	[STB6100_K]		= { 0xc7, 0x38 },
-	[STB6100_G]		= { 0xef, 0x10 },
-	[STB6100_F]		= { 0x1f, 0xc0 },
-	[STB6100_DLB]		= { 0x38, 0xc4 },
-	[STB6100_TEST1]		= { 0x00, 0x8f },
-	[STB6100_FCCK]		= { 0x40, 0x0d },
-	[STB6100_LPEN]		= { 0xf0, 0x0b },
-	[STB6100_TEST3]		= { 0x00, 0xde },
-};
-
-/*
- * Currently unused. Some boards might need it in the future
- */
-static inline void stb6100_normalise_regs(u8 regs[])
-{
-	int i;
-
-	for (i = 0; i < STB6100_NUMREGS; i++)
-		regs[i] = (regs[i] & stb6100_template[i].mask) | stb6100_template[i].set;
-}
-
-static int stb6100_read_regs(struct stb6100_state *state, u8 regs[])
-{
-	int rc;
-	struct i2c_msg msg = {
-		.addr	= state->config->tuner_address,
-		.flags	= I2C_M_RD,
-		.buf	= regs,
-		.len	= STB6100_NUMREGS
-	};
-
-	rc = i2c_transfer(state->i2c, &msg, 1);
-	if (unlikely(rc != 1)) {
-		dprintk(verbose, FE_ERROR, 1, "Read (0x%x) err, rc=[%d]",
-			state->config->tuner_address, rc);
-
-		return -EREMOTEIO;
-	}
-	if (unlikely(verbose > FE_DEBUG)) {
-		int i;
-
-		dprintk(verbose, FE_DEBUG, 1, "    Read from 0x%02x", state->config->tuner_address);
-		for (i = 0; i < STB6100_NUMREGS; i++)
-			dprintk(verbose, FE_DEBUG, 1, "        %s: 0x%02x", stb6100_regnames[i], regs[i]);
-	}
-	return 0;
-}
-
-static int stb6100_read_reg(struct stb6100_state *state, u8 reg)
-{
-	u8 regs[STB6100_NUMREGS];
-
-	struct i2c_msg msg = {
-		.addr	= state->config->tuner_address + reg,
-		.flags	= I2C_M_RD,
-		.buf	= regs,
-		.len	= 1
-	};
-
-	i2c_transfer(state->i2c, &msg, 1);
-
-	if (unlikely(reg >= STB6100_NUMREGS)) {
-		dprintk(verbose, FE_ERROR, 1, "Invalid register offset 0x%x", reg);
-		return -EINVAL;
-	}
-	if (unlikely(verbose > FE_DEBUG)) {
-		dprintk(verbose, FE_DEBUG, 1, "    Read from 0x%02x", state->config->tuner_address);
-		dprintk(verbose, FE_DEBUG, 1, "        %s: 0x%02x", stb6100_regnames[reg], regs[0]);
-	}
-
-	return (unsigned int)regs[0];
-}
-
-static int stb6100_write_reg_range(struct stb6100_state *state, u8 buf[], int start, int len)
-{
-	int rc;
-	u8 cmdbuf[len + 1];
-	struct i2c_msg msg = {
-		.addr	= state->config->tuner_address,
-		.flags	= 0,
-		.buf	= cmdbuf,
-		.len	= len + 1
-	};
-
-	if (unlikely(start < 1 || start + len > STB6100_NUMREGS)) {
-		dprintk(verbose, FE_ERROR, 1, "Invalid register range %d:%d",
-			start, len);
-		return -EINVAL;
-	}
-	memcpy(&cmdbuf[1], buf, len);
-	cmdbuf[0] = start;
-
-	if (unlikely(verbose > FE_DEBUG)) {
-		int i;
-
-		dprintk(verbose, FE_DEBUG, 1, "    Write @ 0x%02x: [%d:%d]", state->config->tuner_address, start, len);
-		for (i = 0; i < len; i++)
-			dprintk(verbose, FE_DEBUG, 1, "        %s: 0x%02x", stb6100_regnames[start + i], buf[i]);
-	}
-	rc = i2c_transfer(state->i2c, &msg, 1);
-	if (unlikely(rc != 1)) {
-		dprintk(verbose, FE_ERROR, 1, "(0x%x) write err [%d:%d], rc=[%d]",
-			(unsigned int)state->config->tuner_address, start, len,	rc);
-		return -EREMOTEIO;
-	}
-	return 0;
-}
-
-static int stb6100_write_reg(struct stb6100_state *state, u8 reg, u8 data)
-{
-	if (unlikely(reg >= STB6100_NUMREGS)) {
-		dprintk(verbose, FE_ERROR, 1, "Invalid register offset 0x%x", reg);
-		return -EREMOTEIO;
-	}
-	data = (data & stb6100_template[reg].mask) | stb6100_template[reg].set;
-	return stb6100_write_reg_range(state, &data, reg, 1);
-}
-
-
-static int stb6100_get_status(struct dvb_frontend *fe, u32 *status)
-{
-	int rc;
-	struct stb6100_state *state = fe->tuner_priv;
-
-	rc = stb6100_read_reg(state, STB6100_LD);
-	if (rc < 0) {
-		dprintk(verbose, FE_ERROR, 1, "%s failed", __func__);
-		return rc;
-	}
-	return (rc & STB6100_LD_LOCK) ? TUNER_STATUS_LOCKED : 0;
-}
-
-static int stb6100_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
-{
-	int rc;
-	u8 f;
-	struct stb6100_state *state = fe->tuner_priv;
-
-	rc = stb6100_read_reg(state, STB6100_F);
-	if (rc < 0)
-		return rc;
-	f = rc & STB6100_F_F;
-
-	state->status.bandwidth = (f + 5) * 2000;	/* x2 for ZIF	*/
-
-	*bandwidth = state->bandwidth = state->status.bandwidth * 1000;
-	dprintk(verbose, FE_DEBUG, 1, "bandwidth = %u Hz", state->bandwidth);
-	return 0;
-}
-
-static int stb6100_set_bandwidth(struct dvb_frontend *fe, u32 bandwidth)
-{
-	u32 tmp;
-	int rc;
-	struct stb6100_state *state = fe->tuner_priv;
-
-	dprintk(verbose, FE_DEBUG, 1, "set bandwidth to %u Hz", bandwidth);
-
-	bandwidth /= 2; /* ZIF */
-
-	if (bandwidth >= 36000000)	/* F[4:0] BW/2 max =31+5=36 mhz for F=31	*/
-		tmp = 31;
-	else if (bandwidth <= 5000000)	/* bw/2 min = 5Mhz for F=0			*/
-		tmp = 0;
-	else				/* if 5 < bw/2 < 36				*/
-		tmp = (bandwidth + 500000) / 1000000 - 5;
-
-	/* Turn on LPF bandwidth setting clock control,
-	 * set bandwidth, wait 10ms, turn off.
-	 */
-	rc = stb6100_write_reg(state, STB6100_FCCK, 0x0d | STB6100_FCCK_FCCK);
-	if (rc < 0)
-		return rc;
-	rc = stb6100_write_reg(state, STB6100_F, 0xc0 | tmp);
-	if (rc < 0)
-		return rc;
-
-	msleep(5);  /*  This is dangerous as another (related) thread may start */
-
-	rc = stb6100_write_reg(state, STB6100_FCCK, 0x0d);
-	if (rc < 0)
-		return rc;
-
-	msleep(10);  /*  This is dangerous as another (related) thread may start */
-
-	return 0;
-}
-
-static int stb6100_get_frequency(struct dvb_frontend *fe, u32 *frequency)
-{
-	int rc;
-	u32 nint, nfrac, fvco;
-	int psd2, odiv;
-	struct stb6100_state *state = fe->tuner_priv;
-	u8 regs[STB6100_NUMREGS];
-
-	rc = stb6100_read_regs(state, regs);
-	if (rc < 0)
-		return rc;
-
-	odiv = (regs[STB6100_VCO] & STB6100_VCO_ODIV) >> STB6100_VCO_ODIV_SHIFT;
-	psd2 = (regs[STB6100_K] & STB6100_K_PSD2) >> STB6100_K_PSD2_SHIFT;
-	nint = regs[STB6100_NI];
-	nfrac = ((regs[STB6100_K] & STB6100_K_NF_MSB) << 8) | regs[STB6100_NF_LSB];
-	fvco = (nfrac * state->reference >> (9 - psd2)) + (nint * state->reference << psd2);
-	*frequency = state->frequency = fvco >> (odiv + 1);
-
-	dprintk(verbose, FE_DEBUG, 1,
-		"frequency = %u kHz, odiv = %u, psd2 = %u, fxtal = %u kHz, fvco = %u kHz, N(I) = %u, N(F) = %u",
-		state->frequency, odiv, psd2, state->reference,	fvco, nint, nfrac);
-	return 0;
-}
-
-
-static int stb6100_set_frequency(struct dvb_frontend *fe, u32 frequency)
-{
-	int rc;
-	const struct stb6100_lkup *ptr;
-	struct stb6100_state *state = fe->tuner_priv;
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-
-	u32 srate = 0, fvco, nint, nfrac;
-	u8 regs[STB6100_NUMREGS];
-	u8 g, psd2, odiv;
-
-	dprintk(verbose, FE_DEBUG, 1, "Version 2010-8-14 13:51");
-
-	if (fe->ops.get_frontend) {
-		dprintk(verbose, FE_DEBUG, 1, "Get frontend parameters");
-		fe->ops.get_frontend(fe);
-	}
-	srate = p->symbol_rate;
-
-	/* Set up tuner cleanly, LPF calibration on */
-	rc = stb6100_write_reg(state, STB6100_FCCK, 0x4d | STB6100_FCCK_FCCK);
-	if (rc < 0)
-		return rc;  /* allow LPF calibration */
-
-	/* PLL Loop disabled, bias on, VCO on, synth on */
-	regs[STB6100_LPEN] = 0xeb;
-	rc = stb6100_write_reg(state, STB6100_LPEN, regs[STB6100_LPEN]);
-	if (rc < 0)
-		return rc;
-
-	/* Program the registers with their data values */
-
-	/* VCO divide ratio (LO divide ratio, VCO prescaler enable).	*/
-	if (frequency <= 1075000)
-		odiv = 1;
-	else
-		odiv = 0;
-
-	/* VCO enabled, search clock off as per LL3.7, 3.4.1 */
-	regs[STB6100_VCO] = 0xe0 | (odiv << STB6100_VCO_ODIV_SHIFT);
-
-	/* OSM	*/
-	for (ptr = lkup;
-	     (ptr->val_high != 0) && !CHKRANGE(frequency, ptr->val_low, ptr->val_high);
-	     ptr++);
-
-	if (ptr->val_high == 0) {
-		printk(KERN_ERR "%s: frequency out of range: %u kHz\n", __func__, frequency);
-		return -EINVAL;
-	}
-	regs[STB6100_VCO] = (regs[STB6100_VCO] & ~STB6100_VCO_OSM) | ptr->reg;
-	rc = stb6100_write_reg(state, STB6100_VCO, regs[STB6100_VCO]);
-	if (rc < 0)
-		return rc;
-
-	if ((frequency > 1075000) && (frequency <= 1325000))
-		psd2 = 0;
-	else
-		psd2 = 1;
-	/* F(VCO) = F(LO) * (ODIV == 0 ? 2 : 4)			*/
-	fvco = frequency << (1 + odiv);
-	/* N(I) = floor(f(VCO) / (f(XTAL) * (PSD2 ? 2 : 1)))	*/
-	nint = fvco / (state->reference << psd2);
-	/* N(F) = round(f(VCO) / f(XTAL) * (PSD2 ? 2 : 1) - N(I)) * 2 ^ 9	*/
-	nfrac = DIV_ROUND_CLOSEST((fvco - (nint * state->reference << psd2))
-					 << (9 - psd2), state->reference);
-
-	/* NI */
-	regs[STB6100_NI] = nint;
-	rc = stb6100_write_reg(state, STB6100_NI, regs[STB6100_NI]);
-	if (rc < 0)
-		return rc;
-
-	/* NF */
-	regs[STB6100_NF_LSB] = nfrac;
-	rc = stb6100_write_reg(state, STB6100_NF_LSB, regs[STB6100_NF_LSB]);
-	if (rc < 0)
-		return rc;
-
-	/* K */
-	regs[STB6100_K] = (0x38 & ~STB6100_K_PSD2) | (psd2 << STB6100_K_PSD2_SHIFT);
-	regs[STB6100_K] = (regs[STB6100_K] & ~STB6100_K_NF_MSB) | ((nfrac >> 8) & STB6100_K_NF_MSB);
-	rc = stb6100_write_reg(state, STB6100_K, regs[STB6100_K]);
-	if (rc < 0)
-		return rc;
-
-	/* G Baseband gain. */
-	if (srate >= 15000000)
-		g = 9;  /*  +4 dB */
-	else if (srate >= 5000000)
-		g = 11; /*  +8 dB */
-	else
-		g = 14; /* +14 dB */
-
-	regs[STB6100_G] = (0x10 & ~STB6100_G_G) | g;
-	regs[STB6100_G] &= ~STB6100_G_GCT; /* mask GCT */
-	regs[STB6100_G] |= (1 << 5); /* 2Vp-p Mode */
-	rc = stb6100_write_reg(state, STB6100_G, regs[STB6100_G]);
-	if (rc < 0)
-		return rc;
-
-	/* F we don't write as it is set up in BW set */
-
-	/* DLB set DC servo loop BW to 160Hz (LLA 3.8 / 2.1) */
-	regs[STB6100_DLB] = 0xcc;
-	rc = stb6100_write_reg(state, STB6100_DLB, regs[STB6100_DLB]);
-	if (rc < 0)
-		return rc;
-
-	dprintk(verbose, FE_DEBUG, 1,
-		"frequency = %u, srate = %u, g = %u, odiv = %u, psd2 = %u, fxtal = %u, osm = %u, fvco = %u, N(I) = %u, N(F) = %u",
-		frequency, srate, (unsigned int)g, (unsigned int)odiv,
-		(unsigned int)psd2, state->reference,
-		ptr->reg, fvco, nint, nfrac);
-
-	/* Set up the test registers */
-	regs[STB6100_TEST1] = 0x8f;
-	rc = stb6100_write_reg(state, STB6100_TEST1, regs[STB6100_TEST1]);
-	if (rc < 0)
-		return rc;
-	regs[STB6100_TEST3] = 0xde;
-	rc = stb6100_write_reg(state, STB6100_TEST3, regs[STB6100_TEST3]);
-	if (rc < 0)
-		return rc;
-
-	/* Bring up tuner according to LLA 3.7 3.4.1, step 2 */
-	regs[STB6100_LPEN] = 0xfb; /* PLL Loop enabled, bias on, VCO on, synth on */
-	rc = stb6100_write_reg(state, STB6100_LPEN, regs[STB6100_LPEN]);
-	if (rc < 0)
-		return rc;
-
-	msleep(2);
-
-	/* Bring up tuner according to LLA 3.7 3.4.1, step 3 */
-	regs[STB6100_VCO] &= ~STB6100_VCO_OCK;		/* VCO fast search		*/
-	rc = stb6100_write_reg(state, STB6100_VCO, regs[STB6100_VCO]);
-	if (rc < 0)
-		return rc;
-
-	msleep(10);  /*  This is dangerous as another (related) thread may start */ /* wait for LO to lock */
-
-	regs[STB6100_VCO] &= ~STB6100_VCO_OSCH;		/* vco search disabled		*/
-	regs[STB6100_VCO] |= STB6100_VCO_OCK;		/* search clock off		*/
-	rc = stb6100_write_reg(state, STB6100_VCO, regs[STB6100_VCO]);
-	if (rc < 0)
-		return rc;
-
-	rc = stb6100_write_reg(state, STB6100_FCCK, 0x0d);
-	if (rc < 0)
-		return rc;  /* Stop LPF calibration */
-
-	msleep(10);  /*  This is dangerous as another (related) thread may start */
-		     /* wait for stabilisation, (should not be necessary)		*/
-	return 0;
-}
-
-static int stb6100_sleep(struct dvb_frontend *fe)
-{
-	/* TODO: power down	*/
-	return 0;
-}
-
-static int stb6100_init(struct dvb_frontend *fe)
-{
-	struct stb6100_state *state = fe->tuner_priv;
-	struct tuner_state *status = &state->status;
-
-	status->tunerstep	= 125000;
-	status->ifreq		= 0;
-	status->refclock	= 27000000;	/* Hz	*/
-	status->iqsense		= 1;
-	status->bandwidth	= 36000;	/* kHz	*/
-	state->bandwidth	= status->bandwidth * 1000;	/* Hz	*/
-	state->reference	= status->refclock / 1000;	/* kHz	*/
-
-	/* Set default bandwidth. Modified, PN 13-May-10	*/
-	return 0;
-}
-
-static int stb6100_get_state(struct dvb_frontend *fe,
-			     enum tuner_param param,
-			     struct tuner_state *state)
-{
-	switch (param) {
-	case DVBFE_TUNER_FREQUENCY:
-		stb6100_get_frequency(fe, &state->frequency);
-		break;
-	case DVBFE_TUNER_TUNERSTEP:
-		break;
-	case DVBFE_TUNER_IFFREQ:
-		break;
-	case DVBFE_TUNER_BANDWIDTH:
-		stb6100_get_bandwidth(fe, &state->bandwidth);
-		break;
-	case DVBFE_TUNER_REFCLOCK:
-		break;
-	default:
-		break;
-	}
-
-	return 0;
-}
-
-static int stb6100_set_state(struct dvb_frontend *fe,
-			     enum tuner_param param,
-			     struct tuner_state *state)
-{
-	struct stb6100_state *tstate = fe->tuner_priv;
-
-	switch (param) {
-	case DVBFE_TUNER_FREQUENCY:
-		stb6100_set_frequency(fe, state->frequency);
-		tstate->frequency = state->frequency;
-		break;
-	case DVBFE_TUNER_TUNERSTEP:
-		break;
-	case DVBFE_TUNER_IFFREQ:
-		break;
-	case DVBFE_TUNER_BANDWIDTH:
-		stb6100_set_bandwidth(fe, state->bandwidth);
-		tstate->bandwidth = state->bandwidth;
-		break;
-	case DVBFE_TUNER_REFCLOCK:
-		break;
-	default:
-		break;
-	}
-
-	return 0;
-}
-
-static struct dvb_tuner_ops stb6100_ops = {
-	.info = {
-		.name			= "STB6100 Silicon Tuner",
-		.frequency_min		= 950000,
-		.frequency_max		= 2150000,
-		.frequency_step		= 0,
-	},
-
-	.init		= stb6100_init,
-	.sleep          = stb6100_sleep,
-	.get_status	= stb6100_get_status,
-	.get_state	= stb6100_get_state,
-	.set_state	= stb6100_set_state,
-	.release	= stb6100_release
-};
-
-struct dvb_frontend *stb6100_attach(struct dvb_frontend *fe,
-				    const struct stb6100_config *config,
-				    struct i2c_adapter *i2c)
-{
-	struct stb6100_state *state = NULL;
-
-	state = kzalloc(sizeof (struct stb6100_state), GFP_KERNEL);
-	if (state == NULL)
-		goto error;
-
-	state->config		= config;
-	state->i2c		= i2c;
-	state->frontend		= fe;
-	state->reference	= config->refclock / 1000; /* kHz */
-	fe->tuner_priv		= state;
-	fe->ops.tuner_ops	= stb6100_ops;
-
-	printk("%s: Attaching STB6100 \n", __func__);
-	return fe;
-
-error:
-	kfree(state);
-	return NULL;
-}
-
-static int stb6100_release(struct dvb_frontend *fe)
-{
-	struct stb6100_state *state = fe->tuner_priv;
-
-	fe->tuner_priv = NULL;
-	kfree(state);
-
-	return 0;
-}
-
-EXPORT_SYMBOL(stb6100_attach);
-MODULE_PARM_DESC(verbose, "Set Verbosity level");
-
-MODULE_AUTHOR("Manu Abraham");
-MODULE_DESCRIPTION("STB6100 Silicon tuner");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/stb6100.h b/drivers/media/dvb/frontends/stb6100.h
deleted file mode 100644
index 2ab0966..0000000
--- a/drivers/media/dvb/frontends/stb6100.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
-	STB6100 Silicon Tuner
-	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
-
-	Copyright (C) ST Microelectronics
-
-	This program is free software; you can redistribute it and/or modify
-	it under the terms of the 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 __STB_6100_REG_H
-#define __STB_6100_REG_H
-
-#include <linux/dvb/frontend.h>
-#include "dvb_frontend.h"
-
-#define STB6100_LD			0x00
-#define STB6100_LD_LOCK			(1 << 0)
-
-#define STB6100_VCO			0x01
-#define STB6100_VCO_OSCH		(0x01 << 7)
-#define STB6100_VCO_OSCH_SHIFT		7
-#define STB6100_VCO_OCK			(0x03 << 5)
-#define STB6100_VCO_OCK_SHIFT		5
-#define STB6100_VCO_ODIV		(0x01 << 4)
-#define STB6100_VCO_ODIV_SHIFT		4
-#define STB6100_VCO_OSM			(0x0f << 0)
-
-#define STB6100_NI			0x02
-#define STB6100_NF_LSB			0x03
-
-#define STB6100_K			0x04
-#define STB6100_K_PSD2			(0x01 << 2)
-#define STB6100_K_PSD2_SHIFT            2
-#define STB6100_K_NF_MSB		(0x03 << 0)
-
-#define STB6100_G			0x05
-#define STB6100_G_G			(0x0f << 0)
-#define STB6100_G_GCT			(0x07 << 5)
-
-#define STB6100_F			0x06
-#define STB6100_F_F			(0x1f << 0)
-
-#define STB6100_DLB			0x07
-
-#define STB6100_TEST1			0x08
-
-#define STB6100_FCCK			0x09
-#define STB6100_FCCK_FCCK		(0x01 << 6)
-
-#define STB6100_LPEN			0x0a
-#define STB6100_LPEN_LPEN		(0x01 << 4)
-#define STB6100_LPEN_SYNP		(0x01 << 5)
-#define STB6100_LPEN_OSCP		(0x01 << 6)
-#define STB6100_LPEN_BEN		(0x01 << 7)
-
-#define STB6100_TEST3			0x0b
-
-#define STB6100_NUMREGS                 0x0c
-
-
-#define INRANGE(val, x, y)		(((x <= val) && (val <= y)) ||		\
-					 ((y <= val) && (val <= x)) ? 1 : 0)
-
-#define CHKRANGE(val, x, y)		(((val >= x) && (val < y)) ? 1 : 0)
-
-struct stb6100_config {
-	u8	tuner_address;
-	u32	refclock;
-};
-
-struct stb6100_state {
-	struct i2c_adapter *i2c;
-
-	const struct stb6100_config	*config;
-	struct dvb_tuner_ops		ops;
-	struct dvb_frontend		*frontend;
-	struct tuner_state		status;
-
-	u32 frequency;
-	u32 srate;
-	u32 bandwidth;
-	u32 reference;
-};
-
-#if defined(CONFIG_DVB_STB6100) || (defined(CONFIG_DVB_STB6100_MODULE) && defined(MODULE))
-
-extern struct dvb_frontend *stb6100_attach(struct dvb_frontend *fe,
-					   const struct stb6100_config *config,
-					   struct i2c_adapter *i2c);
-
-#else
-
-static inline struct dvb_frontend *stb6100_attach(struct dvb_frontend *fe,
-						  const struct stb6100_config *config,
-						  struct i2c_adapter *i2c)
-{
-	printk(KERN_WARNING "%s: Driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-
-#endif //CONFIG_DVB_STB6100
-
-#endif
diff --git a/drivers/media/dvb/frontends/stb6100_cfg.h b/drivers/media/dvb/frontends/stb6100_cfg.h
deleted file mode 100644
index 6314d18..0000000
--- a/drivers/media/dvb/frontends/stb6100_cfg.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
-	STB6100 Silicon Tuner
-	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
-
-	Copyright (C) ST Microelectronics
-
-	This program is free software; you can redistribute it and/or modify
-	it under the terms of the 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.
-*/
-
-static int stb6100_get_frequency(struct dvb_frontend *fe, u32 *frequency)
-{
-	struct dvb_frontend_ops	*frontend_ops = NULL;
-	struct dvb_tuner_ops	*tuner_ops = NULL;
-	struct tuner_state	t_state;
-	int err = 0;
-
-	if (&fe->ops)
-		frontend_ops = &fe->ops;
-	if (&frontend_ops->tuner_ops)
-		tuner_ops = &frontend_ops->tuner_ops;
-	if (tuner_ops->get_state) {
-		if ((err = tuner_ops->get_state(fe, DVBFE_TUNER_FREQUENCY, &t_state)) < 0) {
-			printk("%s: Invalid parameter\n", __func__);
-			return err;
-		}
-		*frequency = t_state.frequency;
-	}
-	return 0;
-}
-
-static int stb6100_set_frequency(struct dvb_frontend *fe, u32 frequency)
-{
-	struct dvb_frontend_ops	*frontend_ops = NULL;
-	struct dvb_tuner_ops	*tuner_ops = NULL;
-	struct tuner_state	t_state;
-	int err = 0;
-
-	t_state.frequency = frequency;
-	if (&fe->ops)
-		frontend_ops = &fe->ops;
-	if (&frontend_ops->tuner_ops)
-		tuner_ops = &frontend_ops->tuner_ops;
-	if (tuner_ops->set_state) {
-		if ((err = tuner_ops->set_state(fe, DVBFE_TUNER_FREQUENCY, &t_state)) < 0) {
-			printk("%s: Invalid parameter\n", __func__);
-			return err;
-		}
-	}
-	return 0;
-}
-
-static int stb6100_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
-{
-	struct dvb_frontend_ops	*frontend_ops = &fe->ops;
-	struct dvb_tuner_ops	*tuner_ops = &frontend_ops->tuner_ops;
-	struct tuner_state	t_state;
-	int err = 0;
-
-	if (&fe->ops)
-		frontend_ops = &fe->ops;
-	if (&frontend_ops->tuner_ops)
-		tuner_ops = &frontend_ops->tuner_ops;
-	if (tuner_ops->get_state) {
-		if ((err = tuner_ops->get_state(fe, DVBFE_TUNER_BANDWIDTH, &t_state)) < 0) {
-			printk("%s: Invalid parameter\n", __func__);
-			return err;
-		}
-		*bandwidth = t_state.bandwidth;
-	}
-	return 0;
-}
-
-static int stb6100_set_bandwidth(struct dvb_frontend *fe, u32 bandwidth)
-{
-	struct dvb_frontend_ops	*frontend_ops = NULL;
-	struct dvb_tuner_ops	*tuner_ops = NULL;
-	struct tuner_state	t_state;
-	int err = 0;
-
-	t_state.bandwidth = bandwidth;
-	if (&fe->ops)
-		frontend_ops = &fe->ops;
-	if (&frontend_ops->tuner_ops)
-		tuner_ops = &frontend_ops->tuner_ops;
-	if (tuner_ops->set_state) {
-		if ((err = tuner_ops->set_state(fe, DVBFE_TUNER_BANDWIDTH, &t_state)) < 0) {
-			printk("%s: Invalid parameter\n", __func__);
-			return err;
-		}
-	}
-	return 0;
-}
diff --git a/drivers/media/dvb/frontends/stb6100_proc.h b/drivers/media/dvb/frontends/stb6100_proc.h
deleted file mode 100644
index 112163a..0000000
--- a/drivers/media/dvb/frontends/stb6100_proc.h
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
-	STB6100 Silicon Tuner wrapper
-	Copyright (C)2009 Igor M. Liplianin (liplianin@me.by)
-
-	This program is free software; you can redistribute it and/or modify
-	it under the terms of the 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.
-*/
-
-static int stb6100_get_freq(struct dvb_frontend *fe, u32 *frequency)
-{
-	struct dvb_frontend_ops	*frontend_ops = NULL;
-	struct dvb_tuner_ops	*tuner_ops = NULL;
-	struct tuner_state	state;
-	int err = 0;
-
-	if (&fe->ops)
-		frontend_ops = &fe->ops;
-	if (&frontend_ops->tuner_ops)
-		tuner_ops = &frontend_ops->tuner_ops;
-	if (tuner_ops->get_state) {
-		if (frontend_ops->i2c_gate_ctrl)
-			frontend_ops->i2c_gate_ctrl(fe, 1);
-
-		err = tuner_ops->get_state(fe, DVBFE_TUNER_FREQUENCY, &state);
-		if (err < 0) {
-			printk(KERN_ERR "%s: Invalid parameter\n", __func__);
-			return err;
-		}
-
-		if (frontend_ops->i2c_gate_ctrl)
-			frontend_ops->i2c_gate_ctrl(fe, 0);
-
-		*frequency = state.frequency;
-	}
-
-	return 0;
-}
-
-static int stb6100_set_freq(struct dvb_frontend *fe, u32 frequency)
-{
-	struct dvb_frontend_ops	*frontend_ops = NULL;
-	struct dvb_tuner_ops	*tuner_ops = NULL;
-	struct tuner_state	state;
-	int err = 0;
-
-	state.frequency = frequency;
-	if (&fe->ops)
-		frontend_ops = &fe->ops;
-	if (&frontend_ops->tuner_ops)
-		tuner_ops = &frontend_ops->tuner_ops;
-	if (tuner_ops->set_state) {
-		if (frontend_ops->i2c_gate_ctrl)
-			frontend_ops->i2c_gate_ctrl(fe, 1);
-
-		err = tuner_ops->set_state(fe, DVBFE_TUNER_FREQUENCY, &state);
-		if (err < 0) {
-			printk(KERN_ERR "%s: Invalid parameter\n", __func__);
-			return err;
-		}
-
-		if (frontend_ops->i2c_gate_ctrl)
-			frontend_ops->i2c_gate_ctrl(fe, 0);
-
-	}
-
-	return 0;
-}
-
-static int stb6100_get_bandw(struct dvb_frontend *fe, u32 *bandwidth)
-{
-	struct dvb_frontend_ops	*frontend_ops = NULL;
-	struct dvb_tuner_ops	*tuner_ops = NULL;
-	struct tuner_state	state;
-	int err = 0;
-
-	if (&fe->ops)
-		frontend_ops = &fe->ops;
-	if (&frontend_ops->tuner_ops)
-		tuner_ops = &frontend_ops->tuner_ops;
-	if (tuner_ops->get_state) {
-		if (frontend_ops->i2c_gate_ctrl)
-			frontend_ops->i2c_gate_ctrl(fe, 1);
-
-		err = tuner_ops->get_state(fe, DVBFE_TUNER_BANDWIDTH, &state);
-		if (err < 0) {
-			printk(KERN_ERR "%s: Invalid parameter\n", __func__);
-			return err;
-		}
-
-		if (frontend_ops->i2c_gate_ctrl)
-			frontend_ops->i2c_gate_ctrl(fe, 0);
-
-		*bandwidth = state.bandwidth;
-	}
-
-	return 0;
-}
-
-static int stb6100_set_bandw(struct dvb_frontend *fe, u32 bandwidth)
-{
-	struct dvb_frontend_ops	*frontend_ops = NULL;
-	struct dvb_tuner_ops	*tuner_ops = NULL;
-	struct tuner_state	state;
-	int err = 0;
-
-	state.bandwidth = bandwidth;
-	if (&fe->ops)
-		frontend_ops = &fe->ops;
-	if (&frontend_ops->tuner_ops)
-		tuner_ops = &frontend_ops->tuner_ops;
-	if (tuner_ops->set_state) {
-		if (frontend_ops->i2c_gate_ctrl)
-			frontend_ops->i2c_gate_ctrl(fe, 1);
-
-		err = tuner_ops->set_state(fe, DVBFE_TUNER_BANDWIDTH, &state);
-		if (err < 0) {
-			printk(KERN_ERR "%s: Invalid parameter\n", __func__);
-			return err;
-		}
-
-		if (frontend_ops->i2c_gate_ctrl)
-			frontend_ops->i2c_gate_ctrl(fe, 0);
-
-	}
-
-	return 0;
-}
diff --git a/drivers/media/dvb/frontends/stv0288.c b/drivers/media/dvb/frontends/stv0288.c
deleted file mode 100644
index 632b251..0000000
--- a/drivers/media/dvb/frontends/stv0288.c
+++ /dev/null
@@ -1,626 +0,0 @@
-/*
-	Driver for ST STV0288 demodulator
-	Copyright (C) 2006 Georg Acher, BayCom GmbH, acher (at) baycom (dot) de
-		for Reel Multimedia
-	Copyright (C) 2008 TurboSight.com, Bob Liu <bob@turbosight.com>
-	Copyright (C) 2008 Igor M. Liplianin <liplianin@me.by>
-		Removed stb6000 specific tuner code and revised some
-		procedures.
-	2010-09-01 Josef Pavlik <josef@pavlik.it>
-		Fixed diseqc_msg, diseqc_burst and set_tone problems
-
-	This program is free software; you can redistribute it and/or modify
-	it under the terms of the 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/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/jiffies.h>
-#include <asm/div64.h>
-
-#include "dvb_frontend.h"
-#include "stv0288.h"
-
-struct stv0288_state {
-	struct i2c_adapter *i2c;
-	const struct stv0288_config *config;
-	struct dvb_frontend frontend;
-
-	u8 initialised:1;
-	u32 tuner_frequency;
-	u32 symbol_rate;
-	fe_code_rate_t fec_inner;
-	int errmode;
-};
-
-#define STATUS_BER 0
-#define STATUS_UCBLOCKS 1
-
-static int debug;
-static int debug_legacy_dish_switch;
-#define dprintk(args...) \
-	do { \
-		if (debug) \
-			printk(KERN_DEBUG "stv0288: " args); \
-	} while (0)
-
-
-static int stv0288_writeregI(struct stv0288_state *state, u8 reg, u8 data)
-{
-	int ret;
-	u8 buf[] = { reg, data };
-	struct i2c_msg msg = {
-		.addr = state->config->demod_address,
-		.flags = 0,
-		.buf = buf,
-		.len = 2
-	};
-
-	ret = i2c_transfer(state->i2c, &msg, 1);
-
-	if (ret != 1)
-		dprintk("%s: writereg error (reg == 0x%02x, val == 0x%02x, "
-			"ret == %i)\n", __func__, reg, data, ret);
-
-	return (ret != 1) ? -EREMOTEIO : 0;
-}
-
-static int stv0288_write(struct dvb_frontend *fe, const u8 buf[], int len)
-{
-	struct stv0288_state *state = fe->demodulator_priv;
-
-	if (len != 2)
-		return -EINVAL;
-
-	return stv0288_writeregI(state, buf[0], buf[1]);
-}
-
-static u8 stv0288_readreg(struct stv0288_state *state, u8 reg)
-{
-	int ret;
-	u8 b0[] = { reg };
-	u8 b1[] = { 0 };
-	struct i2c_msg msg[] = {
-		{
-			.addr = state->config->demod_address,
-			.flags = 0,
-			.buf = b0,
-			.len = 1
-		}, {
-			.addr = state->config->demod_address,
-			.flags = I2C_M_RD,
-			.buf = b1,
-			.len = 1
-		}
-	};
-
-	ret = i2c_transfer(state->i2c, msg, 2);
-
-	if (ret != 2)
-		dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n",
-				__func__, reg, ret);
-
-	return b1[0];
-}
-
-static int stv0288_set_symbolrate(struct dvb_frontend *fe, u32 srate)
-{
-	struct stv0288_state *state = fe->demodulator_priv;
-	unsigned int temp;
-	unsigned char b[3];
-
-	if ((srate < 1000000) || (srate > 45000000))
-		return -EINVAL;
-
-	stv0288_writeregI(state, 0x22, 0);
-	stv0288_writeregI(state, 0x23, 0);
-	stv0288_writeregI(state, 0x2b, 0xff);
-	stv0288_writeregI(state, 0x2c, 0xf7);
-
-	temp = (unsigned int)srate / 1000;
-
-		temp = temp * 32768;
-		temp = temp / 25;
-		temp = temp / 125;
-		b[0] = (unsigned char)((temp >> 12) & 0xff);
-		b[1] = (unsigned char)((temp >> 4) & 0xff);
-		b[2] = (unsigned char)((temp << 4) & 0xf0);
-		stv0288_writeregI(state, 0x28, 0x80); /* SFRH */
-		stv0288_writeregI(state, 0x29, 0); /* SFRM */
-		stv0288_writeregI(state, 0x2a, 0); /* SFRL */
-
-		stv0288_writeregI(state, 0x28, b[0]);
-		stv0288_writeregI(state, 0x29, b[1]);
-		stv0288_writeregI(state, 0x2a, b[2]);
-		dprintk("stv0288: stv0288_set_symbolrate\n");
-
-	return 0;
-}
-
-static int stv0288_send_diseqc_msg(struct dvb_frontend *fe,
-				    struct dvb_diseqc_master_cmd *m)
-{
-	struct stv0288_state *state = fe->demodulator_priv;
-
-	int i;
-
-	dprintk("%s\n", __func__);
-
-	stv0288_writeregI(state, 0x09, 0);
-	msleep(30);
-	stv0288_writeregI(state, 0x05, 0x12);/* modulated mode, single shot */
-
-	for (i = 0; i < m->msg_len; i++) {
-		if (stv0288_writeregI(state, 0x06, m->msg[i]))
-			return -EREMOTEIO;
-	}
-	msleep(m->msg_len*12);
-	return 0;
-}
-
-static int stv0288_send_diseqc_burst(struct dvb_frontend *fe,
-						fe_sec_mini_cmd_t burst)
-{
-	struct stv0288_state *state = fe->demodulator_priv;
-
-	dprintk("%s\n", __func__);
-
-	if (stv0288_writeregI(state, 0x05, 0x03))/* burst mode, single shot */
-		return -EREMOTEIO;
-
-	if (stv0288_writeregI(state, 0x06, burst == SEC_MINI_A ? 0x00 : 0xff))
-		return -EREMOTEIO;
-
-	msleep(15);
-	if (stv0288_writeregI(state, 0x05, 0x12))
-		return -EREMOTEIO;
-
-	return 0;
-}
-
-static int stv0288_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
-{
-	struct stv0288_state *state = fe->demodulator_priv;
-
-	switch (tone) {
-	case SEC_TONE_ON:
-		if (stv0288_writeregI(state, 0x05, 0x10))/* cont carrier */
-			return -EREMOTEIO;
-	break;
-
-	case SEC_TONE_OFF:
-		if (stv0288_writeregI(state, 0x05, 0x12))/* burst mode off*/
-			return -EREMOTEIO;
-	break;
-
-	default:
-		return -EINVAL;
-	}
-	return 0;
-}
-
-static u8 stv0288_inittab[] = {
-	0x01, 0x15,
-	0x02, 0x20,
-	0x09, 0x0,
-	0x0a, 0x4,
-	0x0b, 0x0,
-	0x0c, 0x0,
-	0x0d, 0x0,
-	0x0e, 0xd4,
-	0x0f, 0x30,
-	0x11, 0x80,
-	0x12, 0x03,
-	0x13, 0x48,
-	0x14, 0x84,
-	0x15, 0x45,
-	0x16, 0xb7,
-	0x17, 0x9c,
-	0x18, 0x0,
-	0x19, 0xa6,
-	0x1a, 0x88,
-	0x1b, 0x8f,
-	0x1c, 0xf0,
-	0x20, 0x0b,
-	0x21, 0x54,
-	0x22, 0x0,
-	0x23, 0x0,
-	0x2b, 0xff,
-	0x2c, 0xf7,
-	0x30, 0x0,
-	0x31, 0x1e,
-	0x32, 0x14,
-	0x33, 0x0f,
-	0x34, 0x09,
-	0x35, 0x0c,
-	0x36, 0x05,
-	0x37, 0x2f,
-	0x38, 0x16,
-	0x39, 0xbe,
-	0x3a, 0x0,
-	0x3b, 0x13,
-	0x3c, 0x11,
-	0x3d, 0x30,
-	0x40, 0x63,
-	0x41, 0x04,
-	0x42, 0x20,
-	0x43, 0x00,
-	0x44, 0x00,
-	0x45, 0x00,
-	0x46, 0x00,
-	0x47, 0x00,
-	0x4a, 0x00,
-	0x50, 0x10,
-	0x51, 0x38,
-	0x52, 0x21,
-	0x58, 0x54,
-	0x59, 0x86,
-	0x5a, 0x0,
-	0x5b, 0x9b,
-	0x5c, 0x08,
-	0x5d, 0x7f,
-	0x5e, 0x0,
-	0x5f, 0xff,
-	0x70, 0x0,
-	0x71, 0x0,
-	0x72, 0x0,
-	0x74, 0x0,
-	0x75, 0x0,
-	0x76, 0x0,
-	0x81, 0x0,
-	0x82, 0x3f,
-	0x83, 0x3f,
-	0x84, 0x0,
-	0x85, 0x0,
-	0x88, 0x0,
-	0x89, 0x0,
-	0x8a, 0x0,
-	0x8b, 0x0,
-	0x8c, 0x0,
-	0x90, 0x0,
-	0x91, 0x0,
-	0x92, 0x0,
-	0x93, 0x0,
-	0x94, 0x1c,
-	0x97, 0x0,
-	0xa0, 0x48,
-	0xa1, 0x0,
-	0xb0, 0xb8,
-	0xb1, 0x3a,
-	0xb2, 0x10,
-	0xb3, 0x82,
-	0xb4, 0x80,
-	0xb5, 0x82,
-	0xb6, 0x82,
-	0xb7, 0x82,
-	0xb8, 0x20,
-	0xb9, 0x0,
-	0xf0, 0x0,
-	0xf1, 0x0,
-	0xf2, 0xc0,
-	0x51, 0x36,
-	0x52, 0x09,
-	0x53, 0x94,
-	0x54, 0x62,
-	0x55, 0x29,
-	0x56, 0x64,
-	0x57, 0x2b,
-	0xff, 0xff,
-};
-
-static int stv0288_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t volt)
-{
-	dprintk("%s: %s\n", __func__,
-		volt == SEC_VOLTAGE_13 ? "SEC_VOLTAGE_13" :
-		volt == SEC_VOLTAGE_18 ? "SEC_VOLTAGE_18" : "??");
-
-	return 0;
-}
-
-static int stv0288_init(struct dvb_frontend *fe)
-{
-	struct stv0288_state *state = fe->demodulator_priv;
-	int i;
-	u8 reg;
-	u8 val;
-
-	dprintk("stv0288: init chip\n");
-	stv0288_writeregI(state, 0x41, 0x04);
-	msleep(50);
-
-	/* we have default inittab */
-	if (state->config->inittab == NULL) {
-		for (i = 0; !(stv0288_inittab[i] == 0xff &&
-				stv0288_inittab[i + 1] == 0xff); i += 2)
-			stv0288_writeregI(state, stv0288_inittab[i],
-					stv0288_inittab[i + 1]);
-	} else {
-		for (i = 0; ; i += 2)  {
-			reg = state->config->inittab[i];
-			val = state->config->inittab[i+1];
-			if (reg == 0xff && val == 0xff)
-				break;
-			stv0288_writeregI(state, reg, val);
-		}
-	}
-	return 0;
-}
-
-static int stv0288_read_status(struct dvb_frontend *fe, fe_status_t *status)
-{
-	struct stv0288_state *state = fe->demodulator_priv;
-
-	u8 sync = stv0288_readreg(state, 0x24);
-	if (sync == 255)
-		sync = 0;
-
-	dprintk("%s : FE_READ_STATUS : VSTATUS: 0x%02x\n", __func__, sync);
-
-	*status = 0;
-	if (sync & 0x80)
-		*status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
-	if (sync & 0x10)
-		*status |= FE_HAS_VITERBI;
-	if (sync & 0x08) {
-		*status |= FE_HAS_LOCK;
-		dprintk("stv0288 has locked\n");
-	}
-
-	return 0;
-}
-
-static int stv0288_read_ber(struct dvb_frontend *fe, u32 *ber)
-{
-	struct stv0288_state *state = fe->demodulator_priv;
-
-	if (state->errmode != STATUS_BER)
-		return 0;
-	*ber = (stv0288_readreg(state, 0x26) << 8) |
-					stv0288_readreg(state, 0x27);
-	dprintk("stv0288_read_ber %d\n", *ber);
-
-	return 0;
-}
-
-
-static int stv0288_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
-{
-	struct stv0288_state *state = fe->demodulator_priv;
-
-	s32 signal =  0xffff - ((stv0288_readreg(state, 0x10) << 8));
-
-
-	signal = signal * 5 / 4;
-	*strength = (signal > 0xffff) ? 0xffff : (signal < 0) ? 0 : signal;
-	dprintk("stv0288_read_signal_strength %d\n", *strength);
-
-	return 0;
-}
-static int stv0288_sleep(struct dvb_frontend *fe)
-{
-	struct stv0288_state *state = fe->demodulator_priv;
-
-	stv0288_writeregI(state, 0x41, 0x84);
-	state->initialised = 0;
-
-	return 0;
-}
-static int stv0288_read_snr(struct dvb_frontend *fe, u16 *snr)
-{
-	struct stv0288_state *state = fe->demodulator_priv;
-
-	s32 xsnr = 0xffff - ((stv0288_readreg(state, 0x2d) << 8)
-			   | stv0288_readreg(state, 0x2e));
-	xsnr = 3 * (xsnr - 0xa100);
-	*snr = (xsnr > 0xffff) ? 0xffff : (xsnr < 0) ? 0 : xsnr;
-	dprintk("stv0288_read_snr %d\n", *snr);
-
-	return 0;
-}
-
-static int stv0288_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
-{
-	struct stv0288_state *state = fe->demodulator_priv;
-
-	if (state->errmode != STATUS_BER)
-		return 0;
-	*ucblocks = (stv0288_readreg(state, 0x26) << 8) |
-					stv0288_readreg(state, 0x27);
-	dprintk("stv0288_read_ber %d\n", *ucblocks);
-
-	return 0;
-}
-
-static int stv0288_set_property(struct dvb_frontend *fe, struct dtv_property *p)
-{
-	dprintk("%s(..)\n", __func__);
-	return 0;
-}
-
-static int stv0288_set_frontend(struct dvb_frontend *fe)
-{
-	struct stv0288_state *state = fe->demodulator_priv;
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-
-	char tm;
-	unsigned char tda[3];
-	u8 reg, time_out = 0;
-
-	dprintk("%s : FE_SET_FRONTEND\n", __func__);
-
-	if (c->delivery_system != SYS_DVBS) {
-			dprintk("%s: unsupported delivery "
-				"system selected (%d)\n",
-				__func__, c->delivery_system);
-			return -EOPNOTSUPP;
-	}
-
-	if (state->config->set_ts_params)
-		state->config->set_ts_params(fe, 0);
-
-	/* only frequency & symbol_rate are used for tuner*/
-	if (fe->ops.tuner_ops.set_params) {
-		fe->ops.tuner_ops.set_params(fe);
-		if (fe->ops.i2c_gate_ctrl)
-			fe->ops.i2c_gate_ctrl(fe, 0);
-	}
-
-	udelay(10);
-	stv0288_set_symbolrate(fe, c->symbol_rate);
-	/* Carrier lock control register */
-	stv0288_writeregI(state, 0x15, 0xc5);
-
-	tda[2] = 0x0; /* CFRL */
-	for (tm = -9; tm < 7;) {
-		/* Viterbi status */
-		reg = stv0288_readreg(state, 0x24);
-		if (reg & 0x8)
-				break;
-		if (reg & 0x80) {
-			time_out++;
-			if (time_out > 10)
-				break;
-			tda[2] += 40;
-			if (tda[2] < 40)
-				tm++;
-		} else {
-			tm++;
-			tda[2] = 0;
-			time_out = 0;
-		}
-		tda[1] = (unsigned char)tm;
-		stv0288_writeregI(state, 0x2b, tda[1]);
-		stv0288_writeregI(state, 0x2c, tda[2]);
-		msleep(30);
-	}
-	state->tuner_frequency = c->frequency;
-	state->fec_inner = FEC_AUTO;
-	state->symbol_rate = c->symbol_rate;
-
-	return 0;
-}
-
-static int stv0288_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
-{
-	struct stv0288_state *state = fe->demodulator_priv;
-
-	if (enable)
-		stv0288_writeregI(state, 0x01, 0xb5);
-	else
-		stv0288_writeregI(state, 0x01, 0x35);
-
-	udelay(1);
-
-	return 0;
-}
-
-static void stv0288_release(struct dvb_frontend *fe)
-{
-	struct stv0288_state *state = fe->demodulator_priv;
-	kfree(state);
-}
-
-static struct dvb_frontend_ops stv0288_ops = {
-	.delsys = { SYS_DVBS },
-	.info = {
-		.name			= "ST STV0288 DVB-S",
-		.frequency_min		= 950000,
-		.frequency_max		= 2150000,
-		.frequency_stepsize	= 1000,	 /* kHz for QPSK frontends */
-		.frequency_tolerance	= 0,
-		.symbol_rate_min	= 1000000,
-		.symbol_rate_max	= 45000000,
-		.symbol_rate_tolerance	= 500,	/* ppm */
-		.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_FEC_AUTO
-	},
-
-	.release = stv0288_release,
-	.init = stv0288_init,
-	.sleep = stv0288_sleep,
-	.write = stv0288_write,
-	.i2c_gate_ctrl = stv0288_i2c_gate_ctrl,
-	.read_status = stv0288_read_status,
-	.read_ber = stv0288_read_ber,
-	.read_signal_strength = stv0288_read_signal_strength,
-	.read_snr = stv0288_read_snr,
-	.read_ucblocks = stv0288_read_ucblocks,
-	.diseqc_send_master_cmd = stv0288_send_diseqc_msg,
-	.diseqc_send_burst = stv0288_send_diseqc_burst,
-	.set_tone = stv0288_set_tone,
-	.set_voltage = stv0288_set_voltage,
-
-	.set_property = stv0288_set_property,
-	.set_frontend = stv0288_set_frontend,
-};
-
-struct dvb_frontend *stv0288_attach(const struct stv0288_config *config,
-				    struct i2c_adapter *i2c)
-{
-	struct stv0288_state *state = NULL;
-	int id;
-
-	/* allocate memory for the internal state */
-	state = kzalloc(sizeof(struct stv0288_state), GFP_KERNEL);
-	if (state == NULL)
-		goto error;
-
-	/* setup the state */
-	state->config = config;
-	state->i2c = i2c;
-	state->initialised = 0;
-	state->tuner_frequency = 0;
-	state->symbol_rate = 0;
-	state->fec_inner = 0;
-	state->errmode = STATUS_BER;
-
-	stv0288_writeregI(state, 0x41, 0x04);
-	msleep(200);
-	id = stv0288_readreg(state, 0x00);
-	dprintk("stv0288 id %x\n", id);
-
-	/* register 0x00 contains 0x11 for STV0288  */
-	if (id != 0x11)
-		goto error;
-
-	/* create dvb_frontend */
-	memcpy(&state->frontend.ops, &stv0288_ops,
-			sizeof(struct dvb_frontend_ops));
-	state->frontend.demodulator_priv = state;
-	return &state->frontend;
-
-error:
-	kfree(state);
-
-	return NULL;
-}
-EXPORT_SYMBOL(stv0288_attach);
-
-module_param(debug_legacy_dish_switch, int, 0444);
-MODULE_PARM_DESC(debug_legacy_dish_switch,
-		"Enable timing analysis for Dish Network legacy switches");
-
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
-
-MODULE_DESCRIPTION("ST STV0288 DVB Demodulator driver");
-MODULE_AUTHOR("Georg Acher, Bob Liu, Igor liplianin");
-MODULE_LICENSE("GPL");
-
diff --git a/drivers/media/dvb/frontends/stv0288.h b/drivers/media/dvb/frontends/stv0288.h
deleted file mode 100644
index f2b53db..0000000
--- a/drivers/media/dvb/frontends/stv0288.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
-	Driver for ST STV0288 demodulator
-
-	Copyright (C) 2006 Georg Acher, BayCom GmbH, acher (at) baycom (dot) de
-		for Reel Multimedia
-	Copyright (C) 2008 TurboSight.com, <bob@turbosight.com>
-	Copyright (C) 2008 Igor M. Liplianin <liplianin@me.by>
-		Removed stb6000 specific tuner code and revised some
-		procedures.
-
-	This program is free software; you can redistribute it and/or modify
-	it under the terms of the 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 STV0288_H
-#define STV0288_H
-
-#include <linux/dvb/frontend.h>
-#include "dvb_frontend.h"
-
-struct stv0288_config {
-	/* the demodulator's i2c address */
-	u8 demod_address;
-
-	u8* inittab;
-
-	/* minimum delay before retuning */
-	int min_delay_ms;
-
-	int (*set_ts_params)(struct dvb_frontend *fe, int is_punctured);
-};
-
-#if defined(CONFIG_DVB_STV0288) || (defined(CONFIG_DVB_STV0288_MODULE) && \
-							defined(MODULE))
-extern struct dvb_frontend *stv0288_attach(const struct stv0288_config *config,
-					   struct i2c_adapter *i2c);
-#else
-static inline struct dvb_frontend *stv0288_attach(const struct stv0288_config *config,
-					   struct i2c_adapter *i2c)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif /* CONFIG_DVB_STV0288 */
-
-static inline int stv0288_writereg(struct dvb_frontend *fe, u8 reg, u8 val)
-{
-	int r = 0;
-	u8 buf[] = { reg, val };
-	if (fe->ops.write)
-		r = fe->ops.write(fe, buf, 2);
-	return r;
-}
-
-#endif /* STV0288_H */
diff --git a/drivers/media/dvb/frontends/stv0297.c b/drivers/media/dvb/frontends/stv0297.c
deleted file mode 100644
index d40f226..0000000
--- a/drivers/media/dvb/frontends/stv0297.c
+++ /dev/null
@@ -1,722 +0,0 @@
-/*
-    Driver for STV0297 demodulator
-
-    Copyright (C) 2004 Andrew de Quincey <adq_dvb@lidskialf.net>
-    Copyright (C) 2003-2004 Dennis Noermann <dennis.noermann@noernet.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/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/delay.h>
-#include <linux/jiffies.h>
-#include <linux/slab.h>
-
-#include "dvb_frontend.h"
-#include "stv0297.h"
-
-struct stv0297_state {
-	struct i2c_adapter *i2c;
-	const struct stv0297_config *config;
-	struct dvb_frontend frontend;
-
-	unsigned long last_ber;
-	unsigned long base_freq;
-};
-
-#if 1
-#define dprintk(x...) printk(x)
-#else
-#define dprintk(x...)
-#endif
-
-#define STV0297_CLOCK_KHZ   28900
-
-
-static int stv0297_writereg(struct stv0297_state *state, u8 reg, u8 data)
-{
-	int ret;
-	u8 buf[] = { reg, data };
-	struct i2c_msg msg = {.addr = state->config->demod_address,.flags = 0,.buf = buf,.len = 2 };
-
-	ret = i2c_transfer(state->i2c, &msg, 1);
-
-	if (ret != 1)
-		dprintk("%s: writereg error (reg == 0x%02x, val == 0x%02x, "
-			"ret == %i)\n", __func__, reg, data, ret);
-
-	return (ret != 1) ? -1 : 0;
-}
-
-static int stv0297_readreg(struct stv0297_state *state, u8 reg)
-{
-	int ret;
-	u8 b0[] = { reg };
-	u8 b1[] = { 0 };
-	struct i2c_msg msg[] = { {.addr = state->config->demod_address,.flags = 0,.buf = b0,.len = 1},
-				 {.addr = state->config->demod_address,.flags = I2C_M_RD,.buf = b1,.len = 1}
-			       };
-
-	// this device needs a STOP between the register and data
-	if (state->config->stop_during_read) {
-		if ((ret = i2c_transfer(state->i2c, &msg[0], 1)) != 1) {
-			dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __func__, reg, ret);
-			return -1;
-		}
-		if ((ret = i2c_transfer(state->i2c, &msg[1], 1)) != 1) {
-			dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __func__, reg, ret);
-			return -1;
-		}
-	} else {
-		if ((ret = i2c_transfer(state->i2c, msg, 2)) != 2) {
-			dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __func__, reg, ret);
-			return -1;
-		}
-	}
-
-	return b1[0];
-}
-
-static int stv0297_writereg_mask(struct stv0297_state *state, u8 reg, u8 mask, u8 data)
-{
-	int val;
-
-	val = stv0297_readreg(state, reg);
-	val &= ~mask;
-	val |= (data & mask);
-	stv0297_writereg(state, reg, val);
-
-	return 0;
-}
-
-static int stv0297_readregs(struct stv0297_state *state, u8 reg1, u8 * b, u8 len)
-{
-	int ret;
-	struct i2c_msg msg[] = { {.addr = state->config->demod_address,.flags = 0,.buf =
-				  &reg1,.len = 1},
-	{.addr = state->config->demod_address,.flags = I2C_M_RD,.buf = b,.len = len}
-	};
-
-	// this device needs a STOP between the register and data
-	if (state->config->stop_during_read) {
-		if ((ret = i2c_transfer(state->i2c, &msg[0], 1)) != 1) {
-			dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __func__, reg1, ret);
-			return -1;
-		}
-		if ((ret = i2c_transfer(state->i2c, &msg[1], 1)) != 1) {
-			dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __func__, reg1, ret);
-			return -1;
-		}
-	} else {
-		if ((ret = i2c_transfer(state->i2c, msg, 2)) != 2) {
-			dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __func__, reg1, ret);
-			return -1;
-		}
-	}
-
-	return 0;
-}
-
-static u32 stv0297_get_symbolrate(struct stv0297_state *state)
-{
-	u64 tmp;
-
-	tmp = stv0297_readreg(state, 0x55);
-	tmp |= stv0297_readreg(state, 0x56) << 8;
-	tmp |= stv0297_readreg(state, 0x57) << 16;
-	tmp |= stv0297_readreg(state, 0x58) << 24;
-
-	tmp *= STV0297_CLOCK_KHZ;
-	tmp >>= 32;
-
-	return (u32) tmp;
-}
-
-static void stv0297_set_symbolrate(struct stv0297_state *state, u32 srate)
-{
-	long tmp;
-
-	tmp = 131072L * srate;	/* 131072 = 2^17  */
-	tmp = tmp / (STV0297_CLOCK_KHZ / 4);	/* 1/4 = 2^-2 */
-	tmp = tmp * 8192L;	/* 8192 = 2^13 */
-
-	stv0297_writereg(state, 0x55, (unsigned char) (tmp & 0xFF));
-	stv0297_writereg(state, 0x56, (unsigned char) (tmp >> 8));
-	stv0297_writereg(state, 0x57, (unsigned char) (tmp >> 16));
-	stv0297_writereg(state, 0x58, (unsigned char) (tmp >> 24));
-}
-
-static void stv0297_set_sweeprate(struct stv0297_state *state, short fshift, long symrate)
-{
-	long tmp;
-
-	tmp = (long) fshift *262144L;	/* 262144 = 2*18 */
-	tmp /= symrate;
-	tmp *= 1024;		/* 1024 = 2*10   */
-
-	// adjust
-	if (tmp >= 0) {
-		tmp += 500000;
-	} else {
-		tmp -= 500000;
-	}
-	tmp /= 1000000;
-
-	stv0297_writereg(state, 0x60, tmp & 0xFF);
-	stv0297_writereg_mask(state, 0x69, 0xF0, (tmp >> 4) & 0xf0);
-}
-
-static void stv0297_set_carrieroffset(struct stv0297_state *state, long offset)
-{
-	long tmp;
-
-	/* symrate is hardcoded to 10000 */
-	tmp = offset * 26844L;	/* (2**28)/10000 */
-	if (tmp < 0)
-		tmp += 0x10000000;
-	tmp &= 0x0FFFFFFF;
-
-	stv0297_writereg(state, 0x66, (unsigned char) (tmp & 0xFF));
-	stv0297_writereg(state, 0x67, (unsigned char) (tmp >> 8));
-	stv0297_writereg(state, 0x68, (unsigned char) (tmp >> 16));
-	stv0297_writereg_mask(state, 0x69, 0x0F, (tmp >> 24) & 0x0f);
-}
-
-/*
-static long stv0297_get_carrieroffset(struct stv0297_state *state)
-{
-	s64 tmp;
-
-	stv0297_writereg(state, 0x6B, 0x00);
-
-	tmp = stv0297_readreg(state, 0x66);
-	tmp |= (stv0297_readreg(state, 0x67) << 8);
-	tmp |= (stv0297_readreg(state, 0x68) << 16);
-	tmp |= (stv0297_readreg(state, 0x69) & 0x0F) << 24;
-
-	tmp *= stv0297_get_symbolrate(state);
-	tmp >>= 28;
-
-	return (s32) tmp;
-}
-*/
-
-static void stv0297_set_initialdemodfreq(struct stv0297_state *state, long freq)
-{
-	s32 tmp;
-
-	if (freq > 10000)
-		freq -= STV0297_CLOCK_KHZ;
-
-	tmp = (STV0297_CLOCK_KHZ * 1000) / (1 << 16);
-	tmp = (freq * 1000) / tmp;
-	if (tmp > 0xffff)
-		tmp = 0xffff;
-
-	stv0297_writereg_mask(state, 0x25, 0x80, 0x80);
-	stv0297_writereg(state, 0x21, tmp >> 8);
-	stv0297_writereg(state, 0x20, tmp);
-}
-
-static int stv0297_set_qam(struct stv0297_state *state, fe_modulation_t modulation)
-{
-	int val = 0;
-
-	switch (modulation) {
-	case QAM_16:
-		val = 0;
-		break;
-
-	case QAM_32:
-		val = 1;
-		break;
-
-	case QAM_64:
-		val = 4;
-		break;
-
-	case QAM_128:
-		val = 2;
-		break;
-
-	case QAM_256:
-		val = 3;
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	stv0297_writereg_mask(state, 0x00, 0x70, val << 4);
-
-	return 0;
-}
-
-static int stv0297_set_inversion(struct stv0297_state *state, fe_spectral_inversion_t inversion)
-{
-	int val = 0;
-
-	switch (inversion) {
-	case INVERSION_OFF:
-		val = 0;
-		break;
-
-	case INVERSION_ON:
-		val = 1;
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	stv0297_writereg_mask(state, 0x83, 0x08, val << 3);
-
-	return 0;
-}
-
-static int stv0297_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
-{
-	struct stv0297_state *state = fe->demodulator_priv;
-
-	if (enable) {
-		stv0297_writereg(state, 0x87, 0x78);
-		stv0297_writereg(state, 0x86, 0xc8);
-	}
-
-	return 0;
-}
-
-static int stv0297_init(struct dvb_frontend *fe)
-{
-	struct stv0297_state *state = fe->demodulator_priv;
-	int i;
-
-	/* load init table */
-	for (i=0; !(state->config->inittab[i] == 0xff && state->config->inittab[i+1] == 0xff); i+=2)
-		stv0297_writereg(state, state->config->inittab[i], state->config->inittab[i+1]);
-	msleep(200);
-
-	state->last_ber = 0;
-
-	return 0;
-}
-
-static int stv0297_sleep(struct dvb_frontend *fe)
-{
-	struct stv0297_state *state = fe->demodulator_priv;
-
-	stv0297_writereg_mask(state, 0x80, 1, 1);
-
-	return 0;
-}
-
-static int stv0297_read_status(struct dvb_frontend *fe, fe_status_t * status)
-{
-	struct stv0297_state *state = fe->demodulator_priv;
-
-	u8 sync = stv0297_readreg(state, 0xDF);
-
-	*status = 0;
-	if (sync & 0x80)
-		*status |=
-			FE_HAS_SYNC | FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_LOCK;
-	return 0;
-}
-
-static int stv0297_read_ber(struct dvb_frontend *fe, u32 * ber)
-{
-	struct stv0297_state *state = fe->demodulator_priv;
-	u8 BER[3];
-
-	stv0297_readregs(state, 0xA0, BER, 3);
-	if (!(BER[0] & 0x80)) {
-		state->last_ber = BER[2] << 8 | BER[1];
-		stv0297_writereg_mask(state, 0xA0, 0x80, 0x80);
-	}
-
-	*ber = state->last_ber;
-
-	return 0;
-}
-
-
-static int stv0297_read_signal_strength(struct dvb_frontend *fe, u16 * strength)
-{
-	struct stv0297_state *state = fe->demodulator_priv;
-	u8 STRENGTH[3];
-	u16 tmp;
-
-	stv0297_readregs(state, 0x41, STRENGTH, 3);
-	tmp = (STRENGTH[1] & 0x03) << 8 | STRENGTH[0];
-	if (STRENGTH[2] & 0x20) {
-		if (tmp < 0x200)
-			tmp = 0;
-		else
-			tmp = tmp - 0x200;
-	} else {
-		if (tmp > 0x1ff)
-			tmp = 0;
-		else
-			tmp = 0x1ff - tmp;
-	}
-	*strength = (tmp << 7) | (tmp >> 2);
-	return 0;
-}
-
-static int stv0297_read_snr(struct dvb_frontend *fe, u16 * snr)
-{
-	struct stv0297_state *state = fe->demodulator_priv;
-	u8 SNR[2];
-
-	stv0297_readregs(state, 0x07, SNR, 2);
-	*snr = SNR[1] << 8 | SNR[0];
-
-	return 0;
-}
-
-static int stv0297_read_ucblocks(struct dvb_frontend *fe, u32 * ucblocks)
-{
-	struct stv0297_state *state = fe->demodulator_priv;
-
-	stv0297_writereg_mask(state, 0xDF, 0x03, 0x03); /* freeze the counters */
-
-	*ucblocks = (stv0297_readreg(state, 0xD5) << 8)
-		| stv0297_readreg(state, 0xD4);
-
-	stv0297_writereg_mask(state, 0xDF, 0x03, 0x02); /* clear the counters */
-	stv0297_writereg_mask(state, 0xDF, 0x03, 0x01); /* re-enable the counters */
-
-	return 0;
-}
-
-static int stv0297_set_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct stv0297_state *state = fe->demodulator_priv;
-	int u_threshold;
-	int initial_u;
-	int blind_u;
-	int delay;
-	int sweeprate;
-	int carrieroffset;
-	unsigned long timeout;
-	fe_spectral_inversion_t inversion;
-
-	switch (p->modulation) {
-	case QAM_16:
-	case QAM_32:
-	case QAM_64:
-		delay = 100;
-		sweeprate = 1000;
-		break;
-
-	case QAM_128:
-	case QAM_256:
-		delay = 200;
-		sweeprate = 500;
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	// determine inversion dependent parameters
-	inversion = p->inversion;
-	if (state->config->invert)
-		inversion = (inversion == INVERSION_ON) ? INVERSION_OFF : INVERSION_ON;
-	carrieroffset = -330;
-	switch (inversion) {
-	case INVERSION_OFF:
-		break;
-
-	case INVERSION_ON:
-		sweeprate = -sweeprate;
-		carrieroffset = -carrieroffset;
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	stv0297_init(fe);
-	if (fe->ops.tuner_ops.set_params) {
-		fe->ops.tuner_ops.set_params(fe);
-		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
-	}
-
-	/* clear software interrupts */
-	stv0297_writereg(state, 0x82, 0x0);
-
-	/* set initial demodulation frequency */
-	stv0297_set_initialdemodfreq(state, 7250);
-
-	/* setup AGC */
-	stv0297_writereg_mask(state, 0x43, 0x10, 0x00);
-	stv0297_writereg(state, 0x41, 0x00);
-	stv0297_writereg_mask(state, 0x42, 0x03, 0x01);
-	stv0297_writereg_mask(state, 0x36, 0x60, 0x00);
-	stv0297_writereg_mask(state, 0x36, 0x18, 0x00);
-	stv0297_writereg_mask(state, 0x71, 0x80, 0x80);
-	stv0297_writereg(state, 0x72, 0x00);
-	stv0297_writereg(state, 0x73, 0x00);
-	stv0297_writereg_mask(state, 0x74, 0x0F, 0x00);
-	stv0297_writereg_mask(state, 0x43, 0x08, 0x00);
-	stv0297_writereg_mask(state, 0x71, 0x80, 0x00);
-
-	/* setup STL */
-	stv0297_writereg_mask(state, 0x5a, 0x20, 0x20);
-	stv0297_writereg_mask(state, 0x5b, 0x02, 0x02);
-	stv0297_writereg_mask(state, 0x5b, 0x02, 0x00);
-	stv0297_writereg_mask(state, 0x5b, 0x01, 0x00);
-	stv0297_writereg_mask(state, 0x5a, 0x40, 0x40);
-
-	/* disable frequency sweep */
-	stv0297_writereg_mask(state, 0x6a, 0x01, 0x00);
-
-	/* reset deinterleaver */
-	stv0297_writereg_mask(state, 0x81, 0x01, 0x01);
-	stv0297_writereg_mask(state, 0x81, 0x01, 0x00);
-
-	/* ??? */
-	stv0297_writereg_mask(state, 0x83, 0x20, 0x20);
-	stv0297_writereg_mask(state, 0x83, 0x20, 0x00);
-
-	/* reset equaliser */
-	u_threshold = stv0297_readreg(state, 0x00) & 0xf;
-	initial_u = stv0297_readreg(state, 0x01) >> 4;
-	blind_u = stv0297_readreg(state, 0x01) & 0xf;
-	stv0297_writereg_mask(state, 0x84, 0x01, 0x01);
-	stv0297_writereg_mask(state, 0x84, 0x01, 0x00);
-	stv0297_writereg_mask(state, 0x00, 0x0f, u_threshold);
-	stv0297_writereg_mask(state, 0x01, 0xf0, initial_u << 4);
-	stv0297_writereg_mask(state, 0x01, 0x0f, blind_u);
-
-	/* data comes from internal A/D */
-	stv0297_writereg_mask(state, 0x87, 0x80, 0x00);
-
-	/* clear phase registers */
-	stv0297_writereg(state, 0x63, 0x00);
-	stv0297_writereg(state, 0x64, 0x00);
-	stv0297_writereg(state, 0x65, 0x00);
-	stv0297_writereg(state, 0x66, 0x00);
-	stv0297_writereg(state, 0x67, 0x00);
-	stv0297_writereg(state, 0x68, 0x00);
-	stv0297_writereg_mask(state, 0x69, 0x0f, 0x00);
-
-	/* set parameters */
-	stv0297_set_qam(state, p->modulation);
-	stv0297_set_symbolrate(state, p->symbol_rate / 1000);
-	stv0297_set_sweeprate(state, sweeprate, p->symbol_rate / 1000);
-	stv0297_set_carrieroffset(state, carrieroffset);
-	stv0297_set_inversion(state, inversion);
-
-	/* kick off lock */
-	/* Disable corner detection for higher QAMs */
-	if (p->modulation == QAM_128 ||
-		p->modulation == QAM_256)
-		stv0297_writereg_mask(state, 0x88, 0x08, 0x00);
-	else
-		stv0297_writereg_mask(state, 0x88, 0x08, 0x08);
-
-	stv0297_writereg_mask(state, 0x5a, 0x20, 0x00);
-	stv0297_writereg_mask(state, 0x6a, 0x01, 0x01);
-	stv0297_writereg_mask(state, 0x43, 0x40, 0x40);
-	stv0297_writereg_mask(state, 0x5b, 0x30, 0x00);
-	stv0297_writereg_mask(state, 0x03, 0x0c, 0x0c);
-	stv0297_writereg_mask(state, 0x03, 0x03, 0x03);
-	stv0297_writereg_mask(state, 0x43, 0x10, 0x10);
-
-	/* wait for WGAGC lock */
-	timeout = jiffies + msecs_to_jiffies(2000);
-	while (time_before(jiffies, timeout)) {
-		msleep(10);
-		if (stv0297_readreg(state, 0x43) & 0x08)
-			break;
-	}
-	if (time_after(jiffies, timeout)) {
-		goto timeout;
-	}
-	msleep(20);
-
-	/* wait for equaliser partial convergence */
-	timeout = jiffies + msecs_to_jiffies(500);
-	while (time_before(jiffies, timeout)) {
-		msleep(10);
-
-		if (stv0297_readreg(state, 0x82) & 0x04) {
-			break;
-		}
-	}
-	if (time_after(jiffies, timeout)) {
-		goto timeout;
-	}
-
-	/* wait for equaliser full convergence */
-	timeout = jiffies + msecs_to_jiffies(delay);
-	while (time_before(jiffies, timeout)) {
-		msleep(10);
-
-		if (stv0297_readreg(state, 0x82) & 0x08) {
-			break;
-		}
-	}
-	if (time_after(jiffies, timeout)) {
-		goto timeout;
-	}
-
-	/* disable sweep */
-	stv0297_writereg_mask(state, 0x6a, 1, 0);
-	stv0297_writereg_mask(state, 0x88, 8, 0);
-
-	/* wait for main lock */
-	timeout = jiffies + msecs_to_jiffies(20);
-	while (time_before(jiffies, timeout)) {
-		msleep(10);
-
-		if (stv0297_readreg(state, 0xDF) & 0x80) {
-			break;
-		}
-	}
-	if (time_after(jiffies, timeout)) {
-		goto timeout;
-	}
-	msleep(100);
-
-	/* is it still locked after that delay? */
-	if (!(stv0297_readreg(state, 0xDF) & 0x80)) {
-		goto timeout;
-	}
-
-	/* success!! */
-	stv0297_writereg_mask(state, 0x5a, 0x40, 0x00);
-	state->base_freq = p->frequency;
-	return 0;
-
-timeout:
-	stv0297_writereg_mask(state, 0x6a, 0x01, 0x00);
-	return 0;
-}
-
-static int stv0297_get_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct stv0297_state *state = fe->demodulator_priv;
-	int reg_00, reg_83;
-
-	reg_00 = stv0297_readreg(state, 0x00);
-	reg_83 = stv0297_readreg(state, 0x83);
-
-	p->frequency = state->base_freq;
-	p->inversion = (reg_83 & 0x08) ? INVERSION_ON : INVERSION_OFF;
-	if (state->config->invert)
-		p->inversion = (p->inversion == INVERSION_ON) ? INVERSION_OFF : INVERSION_ON;
-	p->symbol_rate = stv0297_get_symbolrate(state) * 1000;
-	p->fec_inner = FEC_NONE;
-
-	switch ((reg_00 >> 4) & 0x7) {
-	case 0:
-		p->modulation = QAM_16;
-		break;
-	case 1:
-		p->modulation = QAM_32;
-		break;
-	case 2:
-		p->modulation = QAM_128;
-		break;
-	case 3:
-		p->modulation = QAM_256;
-		break;
-	case 4:
-		p->modulation = QAM_64;
-		break;
-	}
-
-	return 0;
-}
-
-static void stv0297_release(struct dvb_frontend *fe)
-{
-	struct stv0297_state *state = fe->demodulator_priv;
-	kfree(state);
-}
-
-static struct dvb_frontend_ops stv0297_ops;
-
-struct dvb_frontend *stv0297_attach(const struct stv0297_config *config,
-				    struct i2c_adapter *i2c)
-{
-	struct stv0297_state *state = NULL;
-
-	/* allocate memory for the internal state */
-	state = kzalloc(sizeof(struct stv0297_state), GFP_KERNEL);
-	if (state == NULL)
-		goto error;
-
-	/* setup the state */
-	state->config = config;
-	state->i2c = i2c;
-	state->last_ber = 0;
-	state->base_freq = 0;
-
-	/* check if the demod is there */
-	if ((stv0297_readreg(state, 0x80) & 0x70) != 0x20)
-		goto error;
-
-	/* create dvb_frontend */
-	memcpy(&state->frontend.ops, &stv0297_ops, sizeof(struct dvb_frontend_ops));
-	state->frontend.demodulator_priv = state;
-	return &state->frontend;
-
-error:
-	kfree(state);
-	return NULL;
-}
-
-static struct dvb_frontend_ops stv0297_ops = {
-	.delsys = { SYS_DVBC_ANNEX_A },
-	.info = {
-		 .name = "ST STV0297 DVB-C",
-		 .frequency_min = 47000000,
-		 .frequency_max = 862000000,
-		 .frequency_stepsize = 62500,
-		 .symbol_rate_min = 870000,
-		 .symbol_rate_max = 11700000,
-		 .caps = FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 |
-		 FE_CAN_QAM_128 | FE_CAN_QAM_256 | FE_CAN_FEC_AUTO},
-
-	.release = stv0297_release,
-
-	.init = stv0297_init,
-	.sleep = stv0297_sleep,
-	.i2c_gate_ctrl = stv0297_i2c_gate_ctrl,
-
-	.set_frontend = stv0297_set_frontend,
-	.get_frontend = stv0297_get_frontend,
-
-	.read_status = stv0297_read_status,
-	.read_ber = stv0297_read_ber,
-	.read_signal_strength = stv0297_read_signal_strength,
-	.read_snr = stv0297_read_snr,
-	.read_ucblocks = stv0297_read_ucblocks,
-};
-
-MODULE_DESCRIPTION("ST STV0297 DVB-C Demodulator driver");
-MODULE_AUTHOR("Dennis Noermann and Andrew de Quincey");
-MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(stv0297_attach);
diff --git a/drivers/media/dvb/frontends/stv0297.h b/drivers/media/dvb/frontends/stv0297.h
deleted file mode 100644
index 3f8f946..0000000
--- a/drivers/media/dvb/frontends/stv0297.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
-    Driver for STV0297 demodulator
-
-    Copyright (C) 2003-2004 Dennis Noermann <dennis.noermann@noernet.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 STV0297_H
-#define STV0297_H
-
-#include <linux/dvb/frontend.h>
-#include "dvb_frontend.h"
-
-struct stv0297_config
-{
-	/* the demodulator's i2c address */
-	u8 demod_address;
-
-	/* inittab - array of pairs of values.
-	* First of each pair is the register, second is the value.
-	* List should be terminated with an 0xff, 0xff pair.
-	*/
-	u8* inittab;
-
-	/* does the "inversion" need inverted? */
-	u8 invert:1;
-
-	/* set to 1 if the device requires an i2c STOP during reading */
-	u8 stop_during_read:1;
-};
-
-#if defined(CONFIG_DVB_STV0297) || (defined(CONFIG_DVB_STV0297_MODULE) && defined(MODULE))
-extern struct dvb_frontend* stv0297_attach(const struct stv0297_config* config,
-					   struct i2c_adapter* i2c);
-#else
-static inline struct dvb_frontend* stv0297_attach(const struct stv0297_config* config,
-					   struct i2c_adapter* i2c)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif // CONFIG_DVB_STV0297
-
-#endif // STV0297_H
diff --git a/drivers/media/dvb/frontends/stv0299.c b/drivers/media/dvb/frontends/stv0299.c
deleted file mode 100644
index 057b5f8..0000000
--- a/drivers/media/dvb/frontends/stv0299.c
+++ /dev/null
@@ -1,762 +0,0 @@
-/*
-    Driver for ST STV0299 demodulator
-
-    Copyright (C) 2001-2002 Convergence Integrated Media GmbH
-	<ralph@convergence.de>,
-	<holger@convergence.de>,
-	<js@convergence.de>
-
-
-    Philips SU1278/SH
-
-    Copyright (C) 2002 by Peter Schildmann <peter.schildmann@web.de>
-
-
-    LG TDQF-S001F
-
-    Copyright (C) 2002 Felix Domke <tmbinc@elitedvb.net>
-		     & Andreas Oberritter <obi@linuxtv.org>
-
-
-    Support for Samsung TBMU24112IMB used on Technisat SkyStar2 rev. 2.6B
-
-    Copyright (C) 2003 Vadim Catana <skystar@moldova.cc>:
-
-    Support for Philips SU1278 on Technotrend hardware
-
-    Copyright (C) 2004 Andrew de Quincey <adq_dvb@lidskialf.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 program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You 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/kernel.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/jiffies.h>
-#include <asm/div64.h>
-
-#include "dvb_frontend.h"
-#include "stv0299.h"
-
-struct stv0299_state {
-	struct i2c_adapter* i2c;
-	const struct stv0299_config* config;
-	struct dvb_frontend frontend;
-
-	u8 initialised:1;
-	u32 tuner_frequency;
-	u32 symbol_rate;
-	fe_code_rate_t fec_inner;
-	int errmode;
-	u32 ucblocks;
-	u8 mcr_reg;
-};
-
-#define STATUS_BER 0
-#define STATUS_UCBLOCKS 1
-
-static int debug;
-static int debug_legacy_dish_switch;
-#define dprintk(args...) \
-	do { \
-		if (debug) printk(KERN_DEBUG "stv0299: " args); \
-	} while (0)
-
-
-static int stv0299_writeregI (struct stv0299_state* state, u8 reg, u8 data)
-{
-	int ret;
-	u8 buf [] = { reg, data };
-	struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 };
-
-	ret = i2c_transfer (state->i2c, &msg, 1);
-
-	if (ret != 1)
-		dprintk("%s: writereg error (reg == 0x%02x, val == 0x%02x, "
-			"ret == %i)\n", __func__, reg, data, ret);
-
-	return (ret != 1) ? -EREMOTEIO : 0;
-}
-
-static int stv0299_write(struct dvb_frontend* fe, const u8 buf[], int len)
-{
-	struct stv0299_state* state = fe->demodulator_priv;
-
-	if (len != 2)
-		return -EINVAL;
-
-	return stv0299_writeregI(state, buf[0], buf[1]);
-}
-
-static u8 stv0299_readreg (struct stv0299_state* state, u8 reg)
-{
-	int ret;
-	u8 b0 [] = { reg };
-	u8 b1 [] = { 0 };
-	struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 },
-			   { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } };
-
-	ret = i2c_transfer (state->i2c, msg, 2);
-
-	if (ret != 2)
-		dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n",
-				__func__, reg, ret);
-
-	return b1[0];
-}
-
-static int stv0299_readregs (struct stv0299_state* state, u8 reg1, u8 *b, u8 len)
-{
-	int ret;
-	struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = &reg1, .len = 1 },
-			   { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b, .len = len } };
-
-	ret = i2c_transfer (state->i2c, msg, 2);
-
-	if (ret != 2)
-		dprintk("%s: readreg error (ret == %i)\n", __func__, ret);
-
-	return ret == 2 ? 0 : ret;
-}
-
-static int stv0299_set_FEC (struct stv0299_state* state, fe_code_rate_t fec)
-{
-	dprintk ("%s\n", __func__);
-
-	switch (fec) {
-	case FEC_AUTO:
-	{
-		return stv0299_writeregI (state, 0x31, 0x1f);
-	}
-	case FEC_1_2:
-	{
-		return stv0299_writeregI (state, 0x31, 0x01);
-	}
-	case FEC_2_3:
-	{
-		return stv0299_writeregI (state, 0x31, 0x02);
-	}
-	case FEC_3_4:
-	{
-		return stv0299_writeregI (state, 0x31, 0x04);
-	}
-	case FEC_5_6:
-	{
-		return stv0299_writeregI (state, 0x31, 0x08);
-	}
-	case FEC_7_8:
-	{
-		return stv0299_writeregI (state, 0x31, 0x10);
-	}
-	default:
-	{
-		return -EINVAL;
-	}
-    }
-}
-
-static fe_code_rate_t stv0299_get_fec (struct stv0299_state* state)
-{
-	static fe_code_rate_t fec_tab [] = { FEC_2_3, FEC_3_4, FEC_5_6,
-					     FEC_7_8, FEC_1_2 };
-	u8 index;
-
-	dprintk ("%s\n", __func__);
-
-	index = stv0299_readreg (state, 0x1b);
-	index &= 0x7;
-
-	if (index > 4)
-		return FEC_AUTO;
-
-	return fec_tab [index];
-}
-
-static int stv0299_wait_diseqc_fifo (struct stv0299_state* state, int timeout)
-{
-	unsigned long start = jiffies;
-
-	dprintk ("%s\n", __func__);
-
-	while (stv0299_readreg(state, 0x0a) & 1) {
-		if (jiffies - start > timeout) {
-			dprintk ("%s: timeout!!\n", __func__);
-			return -ETIMEDOUT;
-		}
-		msleep(10);
-	};
-
-	return 0;
-}
-
-static int stv0299_wait_diseqc_idle (struct stv0299_state* state, int timeout)
-{
-	unsigned long start = jiffies;
-
-	dprintk ("%s\n", __func__);
-
-	while ((stv0299_readreg(state, 0x0a) & 3) != 2 ) {
-		if (jiffies - start > timeout) {
-			dprintk ("%s: timeout!!\n", __func__);
-			return -ETIMEDOUT;
-		}
-		msleep(10);
-	};
-
-	return 0;
-}
-
-static int stv0299_set_symbolrate (struct dvb_frontend* fe, u32 srate)
-{
-	struct stv0299_state* state = fe->demodulator_priv;
-	u64 big = srate;
-	u32 ratio;
-
-	// check rate is within limits
-	if ((srate < 1000000) || (srate > 45000000)) return -EINVAL;
-
-	// calculate value to program
-	big = big << 20;
-	big += (state->config->mclk-1); // round correctly
-	do_div(big, state->config->mclk);
-	ratio = big << 4;
-
-	return state->config->set_symbol_rate(fe, srate, ratio);
-}
-
-static int stv0299_get_symbolrate (struct stv0299_state* state)
-{
-	u32 Mclk = state->config->mclk / 4096L;
-	u32 srate;
-	s32 offset;
-	u8 sfr[3];
-	s8 rtf;
-
-	dprintk ("%s\n", __func__);
-
-	stv0299_readregs (state, 0x1f, sfr, 3);
-	stv0299_readregs (state, 0x1a, (u8 *)&rtf, 1);
-
-	srate = (sfr[0] << 8) | sfr[1];
-	srate *= Mclk;
-	srate /= 16;
-	srate += (sfr[2] >> 4) * Mclk / 256;
-	offset = (s32) rtf * (srate / 4096L);
-	offset /= 128;
-
-	dprintk ("%s : srate = %i\n", __func__, srate);
-	dprintk ("%s : ofset = %i\n", __func__, offset);
-
-	srate += offset;
-
-	srate += 1000;
-	srate /= 2000;
-	srate *= 2000;
-
-	return srate;
-}
-
-static int stv0299_send_diseqc_msg (struct dvb_frontend* fe,
-				    struct dvb_diseqc_master_cmd *m)
-{
-	struct stv0299_state* state = fe->demodulator_priv;
-	u8 val;
-	int i;
-
-	dprintk ("%s\n", __func__);
-
-	if (stv0299_wait_diseqc_idle (state, 100) < 0)
-		return -ETIMEDOUT;
-
-	val = stv0299_readreg (state, 0x08);
-
-	if (stv0299_writeregI (state, 0x08, (val & ~0x7) | 0x6))  /* DiSEqC mode */
-		return -EREMOTEIO;
-
-	for (i=0; i<m->msg_len; i++) {
-		if (stv0299_wait_diseqc_fifo (state, 100) < 0)
-			return -ETIMEDOUT;
-
-		if (stv0299_writeregI (state, 0x09, m->msg[i]))
-			return -EREMOTEIO;
-	}
-
-	if (stv0299_wait_diseqc_idle (state, 100) < 0)
-		return -ETIMEDOUT;
-
-	return 0;
-}
-
-static int stv0299_send_diseqc_burst (struct dvb_frontend* fe, fe_sec_mini_cmd_t burst)
-{
-	struct stv0299_state* state = fe->demodulator_priv;
-	u8 val;
-
-	dprintk ("%s\n", __func__);
-
-	if (stv0299_wait_diseqc_idle (state, 100) < 0)
-		return -ETIMEDOUT;
-
-	val = stv0299_readreg (state, 0x08);
-
-	if (stv0299_writeregI (state, 0x08, (val & ~0x7) | 0x2))	/* burst mode */
-		return -EREMOTEIO;
-
-	if (stv0299_writeregI (state, 0x09, burst == SEC_MINI_A ? 0x00 : 0xff))
-		return -EREMOTEIO;
-
-	if (stv0299_wait_diseqc_idle (state, 100) < 0)
-		return -ETIMEDOUT;
-
-	if (stv0299_writeregI (state, 0x08, val))
-		return -EREMOTEIO;
-
-	return 0;
-}
-
-static int stv0299_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
-{
-	struct stv0299_state* state = fe->demodulator_priv;
-	u8 val;
-
-	if (stv0299_wait_diseqc_idle (state, 100) < 0)
-		return -ETIMEDOUT;
-
-	val = stv0299_readreg (state, 0x08);
-
-	switch (tone) {
-	case SEC_TONE_ON:
-		return stv0299_writeregI (state, 0x08, val | 0x3);
-
-	case SEC_TONE_OFF:
-		return stv0299_writeregI (state, 0x08, (val & ~0x3) | 0x02);
-
-	default:
-		return -EINVAL;
-	}
-}
-
-static int stv0299_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltage)
-{
-	struct stv0299_state* state = fe->demodulator_priv;
-	u8 reg0x08;
-	u8 reg0x0c;
-
-	dprintk("%s: %s\n", __func__,
-		voltage == SEC_VOLTAGE_13 ? "SEC_VOLTAGE_13" :
-		voltage == SEC_VOLTAGE_18 ? "SEC_VOLTAGE_18" : "??");
-
-	reg0x08 = stv0299_readreg (state, 0x08);
-	reg0x0c = stv0299_readreg (state, 0x0c);
-
-	/**
-	 *  H/V switching over OP0, OP1 and OP2 are LNB power enable bits
-	 */
-	reg0x0c &= 0x0f;
-	reg0x08 = (reg0x08 & 0x3f) | (state->config->lock_output << 6);
-
-	switch (voltage) {
-	case SEC_VOLTAGE_13:
-		if (state->config->volt13_op0_op1 == STV0299_VOLT13_OP0)
-			reg0x0c |= 0x10; /* OP1 off, OP0 on */
-		else
-			reg0x0c |= 0x40; /* OP1 on, OP0 off */
-		break;
-	case SEC_VOLTAGE_18:
-		reg0x0c |= 0x50; /* OP1 on, OP0 on */
-		break;
-	case SEC_VOLTAGE_OFF:
-		/* LNB power off! */
-		reg0x08 = 0x00;
-		reg0x0c = 0x00;
-		break;
-	default:
-		return -EINVAL;
-	};
-
-	if (state->config->op0_off)
-		reg0x0c &= ~0x10;
-
-	stv0299_writeregI(state, 0x08, reg0x08);
-	return stv0299_writeregI(state, 0x0c, reg0x0c);
-}
-
-static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, unsigned long cmd)
-{
-	struct stv0299_state* state = fe->demodulator_priv;
-	u8 reg0x08;
-	u8 reg0x0c;
-	u8 lv_mask = 0x40;
-	u8 last = 1;
-	int i;
-	struct timeval nexttime;
-	struct timeval tv[10];
-
-	reg0x08 = stv0299_readreg (state, 0x08);
-	reg0x0c = stv0299_readreg (state, 0x0c);
-	reg0x0c &= 0x0f;
-	stv0299_writeregI (state, 0x08, (reg0x08 & 0x3f) | (state->config->lock_output << 6));
-	if (state->config->volt13_op0_op1 == STV0299_VOLT13_OP0)
-		lv_mask = 0x10;
-
-	cmd = cmd << 1;
-	if (debug_legacy_dish_switch)
-		printk ("%s switch command: 0x%04lx\n",__func__, cmd);
-
-	do_gettimeofday (&nexttime);
-	if (debug_legacy_dish_switch)
-		memcpy (&tv[0], &nexttime, sizeof (struct timeval));
-	stv0299_writeregI (state, 0x0c, reg0x0c | 0x50); /* set LNB to 18V */
-
-	dvb_frontend_sleep_until(&nexttime, 32000);
-
-	for (i=0; i<9; i++) {
-		if (debug_legacy_dish_switch)
-			do_gettimeofday (&tv[i+1]);
-		if((cmd & 0x01) != last) {
-			/* set voltage to (last ? 13V : 18V) */
-			stv0299_writeregI (state, 0x0c, reg0x0c | (last ? lv_mask : 0x50));
-			last = (last) ? 0 : 1;
-		}
-
-		cmd = cmd >> 1;
-
-		if (i != 8)
-			dvb_frontend_sleep_until(&nexttime, 8000);
-	}
-	if (debug_legacy_dish_switch) {
-		printk ("%s(%d): switch delay (should be 32k followed by all 8k\n",
-			__func__, fe->dvb->num);
-		for (i = 1; i < 10; i++)
-			printk ("%d: %d\n", i, timeval_usec_diff(tv[i-1] , tv[i]));
-	}
-
-	return 0;
-}
-
-static int stv0299_init (struct dvb_frontend* fe)
-{
-	struct stv0299_state* state = fe->demodulator_priv;
-	int i;
-	u8 reg;
-	u8 val;
-
-	dprintk("stv0299: init chip\n");
-
-	stv0299_writeregI(state, 0x02, 0x30 | state->mcr_reg);
-	msleep(50);
-
-	for (i = 0; ; i += 2)  {
-		reg = state->config->inittab[i];
-		val = state->config->inittab[i+1];
-		if (reg == 0xff && val == 0xff)
-			break;
-		if (reg == 0x0c && state->config->op0_off)
-			val &= ~0x10;
-		if (reg == 0x2)
-			state->mcr_reg = val & 0xf;
-		stv0299_writeregI(state, reg, val);
-	}
-
-	return 0;
-}
-
-static int stv0299_read_status(struct dvb_frontend* fe, fe_status_t* status)
-{
-	struct stv0299_state* state = fe->demodulator_priv;
-
-	u8 signal = 0xff - stv0299_readreg (state, 0x18);
-	u8 sync = stv0299_readreg (state, 0x1b);
-
-	dprintk ("%s : FE_READ_STATUS : VSTATUS: 0x%02x\n", __func__, sync);
-	*status = 0;
-
-	if (signal > 10)
-		*status |= FE_HAS_SIGNAL;
-
-	if (sync & 0x80)
-		*status |= FE_HAS_CARRIER;
-
-	if (sync & 0x10)
-		*status |= FE_HAS_VITERBI;
-
-	if (sync & 0x08)
-		*status |= FE_HAS_SYNC;
-
-	if ((sync & 0x98) == 0x98)
-		*status |= FE_HAS_LOCK;
-
-	return 0;
-}
-
-static int stv0299_read_ber(struct dvb_frontend* fe, u32* ber)
-{
-	struct stv0299_state* state = fe->demodulator_priv;
-
-	if (state->errmode != STATUS_BER)
-		return -ENOSYS;
-
-	*ber = stv0299_readreg(state, 0x1e) | (stv0299_readreg(state, 0x1d) << 8);
-
-	return 0;
-}
-
-static int stv0299_read_signal_strength(struct dvb_frontend* fe, u16* strength)
-{
-	struct stv0299_state* state = fe->demodulator_priv;
-
-	s32 signal =  0xffff - ((stv0299_readreg (state, 0x18) << 8)
-			       | stv0299_readreg (state, 0x19));
-
-	dprintk ("%s : FE_READ_SIGNAL_STRENGTH : AGC2I: 0x%02x%02x, signal=0x%04x\n", __func__,
-		 stv0299_readreg (state, 0x18),
-		 stv0299_readreg (state, 0x19), (int) signal);
-
-	signal = signal * 5 / 4;
-	*strength = (signal > 0xffff) ? 0xffff : (signal < 0) ? 0 : signal;
-
-	return 0;
-}
-
-static int stv0299_read_snr(struct dvb_frontend* fe, u16* snr)
-{
-	struct stv0299_state* state = fe->demodulator_priv;
-
-	s32 xsnr = 0xffff - ((stv0299_readreg (state, 0x24) << 8)
-			   | stv0299_readreg (state, 0x25));
-	xsnr = 3 * (xsnr - 0xa100);
-	*snr = (xsnr > 0xffff) ? 0xffff : (xsnr < 0) ? 0 : xsnr;
-
-	return 0;
-}
-
-static int stv0299_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
-{
-	struct stv0299_state* state = fe->demodulator_priv;
-
-	if (state->errmode != STATUS_UCBLOCKS)
-		return -ENOSYS;
-
-	state->ucblocks += stv0299_readreg(state, 0x1e);
-	state->ucblocks += (stv0299_readreg(state, 0x1d) << 8);
-	*ucblocks = state->ucblocks;
-
-	return 0;
-}
-
-static int stv0299_set_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct stv0299_state* state = fe->demodulator_priv;
-	int invval = 0;
-
-	dprintk ("%s : FE_SET_FRONTEND\n", __func__);
-	if (state->config->set_ts_params)
-		state->config->set_ts_params(fe, 0);
-
-	// set the inversion
-	if (p->inversion == INVERSION_OFF) invval = 0;
-	else if (p->inversion == INVERSION_ON) invval = 1;
-	else {
-		printk("stv0299 does not support auto-inversion\n");
-		return -EINVAL;
-	}
-	if (state->config->invert) invval = (~invval) & 1;
-	stv0299_writeregI(state, 0x0c, (stv0299_readreg(state, 0x0c) & 0xfe) | invval);
-
-	if (fe->ops.tuner_ops.set_params) {
-		fe->ops.tuner_ops.set_params(fe);
-		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
-	}
-
-	stv0299_set_FEC(state, p->fec_inner);
-	stv0299_set_symbolrate(fe, p->symbol_rate);
-	stv0299_writeregI(state, 0x22, 0x00);
-	stv0299_writeregI(state, 0x23, 0x00);
-
-	state->tuner_frequency = p->frequency;
-	state->fec_inner = p->fec_inner;
-	state->symbol_rate = p->symbol_rate;
-
-	return 0;
-}
-
-static int stv0299_get_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct stv0299_state* state = fe->demodulator_priv;
-	s32 derot_freq;
-	int invval;
-
-	derot_freq = (s32)(s16) ((stv0299_readreg (state, 0x22) << 8)
-				| stv0299_readreg (state, 0x23));
-
-	derot_freq *= (state->config->mclk >> 16);
-	derot_freq += 500;
-	derot_freq /= 1000;
-
-	p->frequency += derot_freq;
-
-	invval = stv0299_readreg (state, 0x0c) & 1;
-	if (state->config->invert) invval = (~invval) & 1;
-	p->inversion = invval ? INVERSION_ON : INVERSION_OFF;
-
-	p->fec_inner = stv0299_get_fec(state);
-	p->symbol_rate = stv0299_get_symbolrate(state);
-
-	return 0;
-}
-
-static int stv0299_sleep(struct dvb_frontend* fe)
-{
-	struct stv0299_state* state = fe->demodulator_priv;
-
-	stv0299_writeregI(state, 0x02, 0xb0 | state->mcr_reg);
-	state->initialised = 0;
-
-	return 0;
-}
-
-static int stv0299_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
-{
-	struct stv0299_state* state = fe->demodulator_priv;
-
-	if (enable) {
-		stv0299_writeregI(state, 0x05, 0xb5);
-	} else {
-		stv0299_writeregI(state, 0x05, 0x35);
-	}
-	udelay(1);
-	return 0;
-}
-
-static int stv0299_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings)
-{
-	struct stv0299_state* state = fe->demodulator_priv;
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-
-	fesettings->min_delay_ms = state->config->min_delay_ms;
-	if (p->symbol_rate < 10000000) {
-		fesettings->step_size = p->symbol_rate / 32000;
-		fesettings->max_drift = 5000;
-	} else {
-		fesettings->step_size = p->symbol_rate / 16000;
-		fesettings->max_drift = p->symbol_rate / 2000;
-	}
-	return 0;
-}
-
-static void stv0299_release(struct dvb_frontend* fe)
-{
-	struct stv0299_state* state = fe->demodulator_priv;
-	kfree(state);
-}
-
-static struct dvb_frontend_ops stv0299_ops;
-
-struct dvb_frontend* stv0299_attach(const struct stv0299_config* config,
-				    struct i2c_adapter* i2c)
-{
-	struct stv0299_state* state = NULL;
-	int id;
-
-	/* allocate memory for the internal state */
-	state = kzalloc(sizeof(struct stv0299_state), GFP_KERNEL);
-	if (state == NULL) goto error;
-
-	/* setup the state */
-	state->config = config;
-	state->i2c = i2c;
-	state->initialised = 0;
-	state->tuner_frequency = 0;
-	state->symbol_rate = 0;
-	state->fec_inner = 0;
-	state->errmode = STATUS_BER;
-
-	/* check if the demod is there */
-	stv0299_writeregI(state, 0x02, 0x30); /* standby off */
-	msleep(200);
-	id = stv0299_readreg(state, 0x00);
-
-	/* register 0x00 contains 0xa1 for STV0299 and STV0299B */
-	/* register 0x00 might contain 0x80 when returning from standby */
-	if (id != 0xa1 && id != 0x80) goto error;
-
-	/* create dvb_frontend */
-	memcpy(&state->frontend.ops, &stv0299_ops, sizeof(struct dvb_frontend_ops));
-	state->frontend.demodulator_priv = state;
-	return &state->frontend;
-
-error:
-	kfree(state);
-	return NULL;
-}
-
-static struct dvb_frontend_ops stv0299_ops = {
-	.delsys = { SYS_DVBS },
-	.info = {
-		.name			= "ST STV0299 DVB-S",
-		.frequency_min		= 950000,
-		.frequency_max		= 2150000,
-		.frequency_stepsize	= 125,	 /* kHz for QPSK frontends */
-		.frequency_tolerance	= 0,
-		.symbol_rate_min	= 1000000,
-		.symbol_rate_max	= 45000000,
-		.symbol_rate_tolerance	= 500,	/* ppm */
-		.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_FEC_AUTO
-	},
-
-	.release = stv0299_release,
-
-	.init = stv0299_init,
-	.sleep = stv0299_sleep,
-	.write = stv0299_write,
-	.i2c_gate_ctrl = stv0299_i2c_gate_ctrl,
-
-	.set_frontend = stv0299_set_frontend,
-	.get_frontend = stv0299_get_frontend,
-	.get_tune_settings = stv0299_get_tune_settings,
-
-	.read_status = stv0299_read_status,
-	.read_ber = stv0299_read_ber,
-	.read_signal_strength = stv0299_read_signal_strength,
-	.read_snr = stv0299_read_snr,
-	.read_ucblocks = stv0299_read_ucblocks,
-
-	.diseqc_send_master_cmd = stv0299_send_diseqc_msg,
-	.diseqc_send_burst = stv0299_send_diseqc_burst,
-	.set_tone = stv0299_set_tone,
-	.set_voltage = stv0299_set_voltage,
-	.dishnetwork_send_legacy_command = stv0299_send_legacy_dish_cmd,
-};
-
-module_param(debug_legacy_dish_switch, int, 0444);
-MODULE_PARM_DESC(debug_legacy_dish_switch, "Enable timing analysis for Dish Network legacy switches");
-
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
-
-MODULE_DESCRIPTION("ST STV0299 DVB Demodulator driver");
-MODULE_AUTHOR("Ralph Metzler, Holger Waechtler, Peter Schildmann, Felix Domke, "
-	      "Andreas Oberritter, Andrew de Quincey, Kenneth Aafly");
-MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(stv0299_attach);
diff --git a/drivers/media/dvb/frontends/stv0299.h b/drivers/media/dvb/frontends/stv0299.h
deleted file mode 100644
index ba219b7..0000000
--- a/drivers/media/dvb/frontends/stv0299.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
-    Driver for ST STV0299 demodulator
-
-    Copyright (C) 2001-2002 Convergence Integrated Media GmbH
-	<ralph@convergence.de>,
-	<holger@convergence.de>,
-	<js@convergence.de>
-
-
-    Philips SU1278/SH
-
-    Copyright (C) 2002 by Peter Schildmann <peter.schildmann@web.de>
-
-
-    LG TDQF-S001F
-
-    Copyright (C) 2002 Felix Domke <tmbinc@elitedvb.net>
-		     & Andreas Oberritter <obi@linuxtv.org>
-
-
-    Support for Samsung TBMU24112IMB used on Technisat SkyStar2 rev. 2.6B
-
-    Copyright (C) 2003 Vadim Catana <skystar@moldova.cc>:
-
-    Support for Philips SU1278 on Technotrend hardware
-
-    Copyright (C) 2004 Andrew de Quincey <adq_dvb@lidskialf.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 program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You 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 STV0299_H
-#define STV0299_H
-
-#include <linux/dvb/frontend.h>
-#include "dvb_frontend.h"
-
-#define STV0299_LOCKOUTPUT_0  0
-#define STV0299_LOCKOUTPUT_1  1
-#define STV0299_LOCKOUTPUT_CF 2
-#define STV0299_LOCKOUTPUT_LK 3
-
-#define STV0299_VOLT13_OP0 0
-#define STV0299_VOLT13_OP1 1
-
-struct stv0299_config
-{
-	/* the demodulator's i2c address */
-	u8 demod_address;
-
-	/* inittab - array of pairs of values.
-	 * First of each pair is the register, second is the value.
-	 * List should be terminated with an 0xff, 0xff pair.
-	 */
-	const u8* inittab;
-
-	/* master clock to use */
-	u32 mclk;
-
-	/* does the inversion require inversion? */
-	u8 invert:1;
-
-	/* Skip reinitialisation? */
-	u8 skip_reinit:1;
-
-	/* LOCK OUTPUT setting */
-	u8 lock_output:2;
-
-	/* Is 13v controlled by OP0 or OP1? */
-	u8 volt13_op0_op1:1;
-
-	/* Turn-off OP0? */
-	u8 op0_off:1;
-
-	/* minimum delay before retuning */
-	int min_delay_ms;
-
-	/* Set the symbol rate */
-	int (*set_symbol_rate)(struct dvb_frontend *fe, u32 srate, u32 ratio);
-
-	/* Set device param to start dma */
-	int (*set_ts_params)(struct dvb_frontend *fe, int is_punctured);
-};
-
-#if defined(CONFIG_DVB_STV0299) || (defined(CONFIG_DVB_STV0299_MODULE) && defined(MODULE))
-extern struct dvb_frontend *stv0299_attach(const struct stv0299_config *config,
-					   struct i2c_adapter *i2c);
-#else
-static inline struct dvb_frontend *stv0299_attach(const struct stv0299_config *config,
-					   struct i2c_adapter *i2c)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif // CONFIG_DVB_STV0299
-
-static inline int stv0299_writereg(struct dvb_frontend *fe, u8 reg, u8 val) {
-	int r = 0;
-	u8 buf[] = {reg, val};
-	if (fe->ops.write)
-		r = fe->ops.write(fe, buf, 2);
-	return r;
-}
-
-#endif // STV0299_H
diff --git a/drivers/media/dvb/frontends/stv0367.c b/drivers/media/dvb/frontends/stv0367.c
deleted file mode 100644
index 2a8aaeb..0000000
--- a/drivers/media/dvb/frontends/stv0367.c
+++ /dev/null
@@ -1,3450 +0,0 @@
-/*
- * stv0367.c
- *
- * Driver for ST STV0367 DVB-T & DVB-C demodulator IC.
- *
- * Copyright (C) ST Microelectronics.
- * Copyright (C) 2010,2011 NetUP Inc.
- * Copyright (C) 2010,2011 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 "stv0367.h"
-#include "stv0367_regs.h"
-#include "stv0367_priv.h"
-
-static int stvdebug;
-module_param_named(debug, stvdebug, int, 0644);
-
-static int i2cdebug;
-module_param_named(i2c_debug, i2cdebug, int, 0644);
-
-#define dprintk(args...) \
-	do { \
-		if (stvdebug) \
-			printk(KERN_DEBUG args); \
-	} while (0)
-	/* DVB-C */
-
-struct stv0367cab_state {
-	enum stv0367_cab_signal_type	state;
-	u32	mclk;
-	u32	adc_clk;
-	s32	search_range;
-	s32	derot_offset;
-	/* results */
-	int locked;			/* channel found		*/
-	u32 freq_khz;			/* found frequency (in kHz)	*/
-	u32 symbol_rate;		/* found symbol rate (in Bds)	*/
-	enum stv0367cab_mod modulation;	/* modulation			*/
-	fe_spectral_inversion_t	spect_inv; /* Spectrum Inversion	*/
-};
-
-struct stv0367ter_state {
-	/* DVB-T */
-	enum stv0367_ter_signal_type state;
-	enum stv0367_ter_if_iq_mode if_iq_mode;
-	enum stv0367_ter_mode mode;/* mode 2K or 8K */
-	fe_guard_interval_t guard;
-	enum stv0367_ter_hierarchy hierarchy;
-	u32 frequency;
-	fe_spectral_inversion_t  sense; /*  current search spectrum */
-	u8  force; /* force mode/guard */
-	u8  bw; /* channel width 6, 7 or 8 in MHz */
-	u8  pBW; /* channel width used during previous lock */
-	u32 pBER;
-	u32 pPER;
-	u32 ucblocks;
-	s8  echo_pos; /* echo position */
-	u8  first_lock;
-	u8  unlock_counter;
-	u32 agc_val;
-};
-
-struct stv0367_state {
-	struct dvb_frontend fe;
-	struct i2c_adapter *i2c;
-	/* config settings */
-	const struct stv0367_config *config;
-	u8 chip_id;
-	/* DVB-C */
-	struct stv0367cab_state *cab_state;
-	/* DVB-T */
-	struct stv0367ter_state *ter_state;
-};
-
-struct st_register {
-	u16	addr;
-	u8	value;
-};
-
-/* values for STV4100 XTAL=30M int clk=53.125M*/
-static struct st_register def0367ter[STV0367TER_NBREGS] = {
-	{R367TER_ID,		0x60},
-	{R367TER_I2CRPT,	0xa0},
-	/* {R367TER_I2CRPT,	0x22},*/
-	{R367TER_TOPCTRL,	0x00},/* for xc5000; was 0x02 */
-	{R367TER_IOCFG0,	0x40},
-	{R367TER_DAC0R,		0x00},
-	{R367TER_IOCFG1,	0x00},
-	{R367TER_DAC1R,		0x00},
-	{R367TER_IOCFG2,	0x62},
-	{R367TER_SDFR,		0x00},
-	{R367TER_STATUS,	0xf8},
-	{R367TER_AUX_CLK,	0x0a},
-	{R367TER_FREESYS1,	0x00},
-	{R367TER_FREESYS2,	0x00},
-	{R367TER_FREESYS3,	0x00},
-	{R367TER_GPIO_CFG,	0x55},
-	{R367TER_GPIO_CMD,	0x00},
-	{R367TER_AGC2MAX,	0xff},
-	{R367TER_AGC2MIN,	0x00},
-	{R367TER_AGC1MAX,	0xff},
-	{R367TER_AGC1MIN,	0x00},
-	{R367TER_AGCR,		0xbc},
-	{R367TER_AGC2TH,	0x00},
-	{R367TER_AGC12C,	0x00},
-	{R367TER_AGCCTRL1,	0x85},
-	{R367TER_AGCCTRL2,	0x1f},
-	{R367TER_AGC1VAL1,	0x00},
-	{R367TER_AGC1VAL2,	0x00},
-	{R367TER_AGC2VAL1,	0x6f},
-	{R367TER_AGC2VAL2,	0x05},
-	{R367TER_AGC2PGA,	0x00},
-	{R367TER_OVF_RATE1,	0x00},
-	{R367TER_OVF_RATE2,	0x00},
-	{R367TER_GAIN_SRC1,	0xaa},/* for xc5000; was 0x2b */
-	{R367TER_GAIN_SRC2,	0xd6},/* for xc5000; was 0x04 */
-	{R367TER_INC_DEROT1,	0x55},
-	{R367TER_INC_DEROT2,	0x55},
-	{R367TER_PPM_CPAMP_DIR,	0x2c},
-	{R367TER_PPM_CPAMP_INV,	0x00},
-	{R367TER_FREESTFE_1,	0x00},
-	{R367TER_FREESTFE_2,	0x1c},
-	{R367TER_DCOFFSET,	0x00},
-	{R367TER_EN_PROCESS,	0x05},
-	{R367TER_SDI_SMOOTHER,	0x80},
-	{R367TER_FE_LOOP_OPEN,	0x1c},
-	{R367TER_FREQOFF1,	0x00},
-	{R367TER_FREQOFF2,	0x00},
-	{R367TER_FREQOFF3,	0x00},
-	{R367TER_TIMOFF1,	0x00},
-	{R367TER_TIMOFF2,	0x00},
-	{R367TER_EPQ,		0x02},
-	{R367TER_EPQAUTO,	0x01},
-	{R367TER_SYR_UPDATE,	0xf5},
-	{R367TER_CHPFREE,	0x00},
-	{R367TER_PPM_STATE_MAC,	0x23},
-	{R367TER_INR_THRESHOLD,	0xff},
-	{R367TER_EPQ_TPS_ID_CELL, 0xf9},
-	{R367TER_EPQ_CFG,	0x00},
-	{R367TER_EPQ_STATUS,	0x01},
-	{R367TER_AUTORELOCK,	0x81},
-	{R367TER_BER_THR_VMSB,	0x00},
-	{R367TER_BER_THR_MSB,	0x00},
-	{R367TER_BER_THR_LSB,	0x00},
-	{R367TER_CCD,		0x83},
-	{R367TER_SPECTR_CFG,	0x00},
-	{R367TER_CHC_DUMMY,	0x18},
-	{R367TER_INC_CTL,	0x88},
-	{R367TER_INCTHRES_COR1,	0xb4},
-	{R367TER_INCTHRES_COR2,	0x96},
-	{R367TER_INCTHRES_DET1,	0x0e},
-	{R367TER_INCTHRES_DET2,	0x11},
-	{R367TER_IIR_CELLNB,	0x8d},
-	{R367TER_IIRCX_COEFF1_MSB, 0x00},
-	{R367TER_IIRCX_COEFF1_LSB, 0x00},
-	{R367TER_IIRCX_COEFF2_MSB, 0x09},
-	{R367TER_IIRCX_COEFF2_LSB, 0x18},
-	{R367TER_IIRCX_COEFF3_MSB, 0x14},
-	{R367TER_IIRCX_COEFF3_LSB, 0x9c},
-	{R367TER_IIRCX_COEFF4_MSB, 0x00},
-	{R367TER_IIRCX_COEFF4_LSB, 0x00},
-	{R367TER_IIRCX_COEFF5_MSB, 0x36},
-	{R367TER_IIRCX_COEFF5_LSB, 0x42},
-	{R367TER_FEPATH_CFG,	0x00},
-	{R367TER_PMC1_FUNC,	0x65},
-	{R367TER_PMC1_FOR,	0x00},
-	{R367TER_PMC2_FUNC,	0x00},
-	{R367TER_STATUS_ERR_DA,	0xe0},
-	{R367TER_DIG_AGC_R,	0xfe},
-	{R367TER_COMAGC_TARMSB,	0x0b},
-	{R367TER_COM_AGC_TAR_ENMODE, 0x41},
-	{R367TER_COM_AGC_CFG,	0x3e},
-	{R367TER_COM_AGC_GAIN1, 0x39},
-	{R367TER_AUT_AGC_TARGETMSB, 0x0b},
-	{R367TER_LOCK_DET_MSB,	0x01},
-	{R367TER_AGCTAR_LOCK_LSBS, 0x40},
-	{R367TER_AUT_GAIN_EN,	0xf4},
-	{R367TER_AUT_CFG,	0xf0},
-	{R367TER_LOCKN,		0x23},
-	{R367TER_INT_X_3,	0x00},
-	{R367TER_INT_X_2,	0x03},
-	{R367TER_INT_X_1,	0x8d},
-	{R367TER_INT_X_0,	0xa0},
-	{R367TER_MIN_ERRX_MSB,	0x00},
-	{R367TER_COR_CTL,	0x23},
-	{R367TER_COR_STAT,	0xf6},
-	{R367TER_COR_INTEN,	0x00},
-	{R367TER_COR_INTSTAT,	0x3f},
-	{R367TER_COR_MODEGUARD,	0x03},
-	{R367TER_AGC_CTL,	0x08},
-	{R367TER_AGC_MANUAL1,	0x00},
-	{R367TER_AGC_MANUAL2,	0x00},
-	{R367TER_AGC_TARG,	0x16},
-	{R367TER_AGC_GAIN1,	0x53},
-	{R367TER_AGC_GAIN2,	0x1d},
-	{R367TER_RESERVED_1,	0x00},
-	{R367TER_RESERVED_2,	0x00},
-	{R367TER_RESERVED_3,	0x00},
-	{R367TER_CAS_CTL,	0x44},
-	{R367TER_CAS_FREQ,	0xb3},
-	{R367TER_CAS_DAGCGAIN,	0x12},
-	{R367TER_SYR_CTL,	0x04},
-	{R367TER_SYR_STAT,	0x10},
-	{R367TER_SYR_NCO1,	0x00},
-	{R367TER_SYR_NCO2,	0x00},
-	{R367TER_SYR_OFFSET1,	0x00},
-	{R367TER_SYR_OFFSET2,	0x00},
-	{R367TER_FFT_CTL,	0x00},
-	{R367TER_SCR_CTL,	0x70},
-	{R367TER_PPM_CTL1,	0xf8},
-	{R367TER_TRL_CTL,	0x14},/* for xc5000; was 0xac */
-	{R367TER_TRL_NOMRATE1,	0xae},/* for xc5000; was 0x1e */
-	{R367TER_TRL_NOMRATE2,	0x56},/* for xc5000; was 0x58 */
-	{R367TER_TRL_TIME1,	0x1d},
-	{R367TER_TRL_TIME2,	0xfc},
-	{R367TER_CRL_CTL,	0x24},
-	{R367TER_CRL_FREQ1,	0xad},
-	{R367TER_CRL_FREQ2,	0x9d},
-	{R367TER_CRL_FREQ3,	0xff},
-	{R367TER_CHC_CTL,	0x01},
-	{R367TER_CHC_SNR,	0xf0},
-	{R367TER_BDI_CTL,	0x00},
-	{R367TER_DMP_CTL,	0x00},
-	{R367TER_TPS_RCVD1,	0x30},
-	{R367TER_TPS_RCVD2,	0x02},
-	{R367TER_TPS_RCVD3,	0x01},
-	{R367TER_TPS_RCVD4,	0x00},
-	{R367TER_TPS_ID_CELL1,	0x00},
-	{R367TER_TPS_ID_CELL2,	0x00},
-	{R367TER_TPS_RCVD5_SET1, 0x02},
-	{R367TER_TPS_SET2,	0x02},
-	{R367TER_TPS_SET3,	0x01},
-	{R367TER_TPS_CTL,	0x00},
-	{R367TER_CTL_FFTOSNUM,	0x34},
-	{R367TER_TESTSELECT,	0x09},
-	{R367TER_MSC_REV,	0x0a},
-	{R367TER_PIR_CTL,	0x00},
-	{R367TER_SNR_CARRIER1,	0xa1},
-	{R367TER_SNR_CARRIER2,	0x9a},
-	{R367TER_PPM_CPAMP,	0x2c},
-	{R367TER_TSM_AP0,	0x00},
-	{R367TER_TSM_AP1,	0x00},
-	{R367TER_TSM_AP2 ,	0x00},
-	{R367TER_TSM_AP3,	0x00},
-	{R367TER_TSM_AP4,	0x00},
-	{R367TER_TSM_AP5,	0x00},
-	{R367TER_TSM_AP6,	0x00},
-	{R367TER_TSM_AP7,	0x00},
-	{R367TER_TSTRES,	0x00},
-	{R367TER_ANACTRL,	0x0D},/* PLL stoped, restart at init!!! */
-	{R367TER_TSTBUS,	0x00},
-	{R367TER_TSTRATE,	0x00},
-	{R367TER_CONSTMODE,	0x01},
-	{R367TER_CONSTCARR1,	0x00},
-	{R367TER_CONSTCARR2,	0x00},
-	{R367TER_ICONSTEL,	0x0a},
-	{R367TER_QCONSTEL,	0x15},
-	{R367TER_TSTBISTRES0,	0x00},
-	{R367TER_TSTBISTRES1,	0x00},
-	{R367TER_TSTBISTRES2,	0x28},
-	{R367TER_TSTBISTRES3,	0x00},
-	{R367TER_RF_AGC1,	0xff},
-	{R367TER_RF_AGC2,	0x83},
-	{R367TER_ANADIGCTRL,	0x19},
-	{R367TER_PLLMDIV,	0x01},/* for xc5000; was 0x0c */
-	{R367TER_PLLNDIV,	0x06},/* for xc5000; was 0x55 */
-	{R367TER_PLLSETUP,	0x18},
-	{R367TER_DUAL_AD12,	0x0C},/* for xc5000 AGC voltage 1.6V */
-	{R367TER_TSTBIST,	0x00},
-	{R367TER_PAD_COMP_CTRL,	0x00},
-	{R367TER_PAD_COMP_WR,	0x00},
-	{R367TER_PAD_COMP_RD,	0xe0},
-	{R367TER_SYR_TARGET_FFTADJT_MSB, 0x00},
-	{R367TER_SYR_TARGET_FFTADJT_LSB, 0x00},
-	{R367TER_SYR_TARGET_CHCADJT_MSB, 0x00},
-	{R367TER_SYR_TARGET_CHCADJT_LSB, 0x00},
-	{R367TER_SYR_FLAG,	0x00},
-	{R367TER_CRL_TARGET1,	0x00},
-	{R367TER_CRL_TARGET2,	0x00},
-	{R367TER_CRL_TARGET3,	0x00},
-	{R367TER_CRL_TARGET4,	0x00},
-	{R367TER_CRL_FLAG,	0x00},
-	{R367TER_TRL_TARGET1,	0x00},
-	{R367TER_TRL_TARGET2,	0x00},
-	{R367TER_TRL_CHC,	0x00},
-	{R367TER_CHC_SNR_TARG,	0x00},
-	{R367TER_TOP_TRACK,	0x00},
-	{R367TER_TRACKER_FREE1,	0x00},
-	{R367TER_ERROR_CRL1,	0x00},
-	{R367TER_ERROR_CRL2,	0x00},
-	{R367TER_ERROR_CRL3,	0x00},
-	{R367TER_ERROR_CRL4,	0x00},
-	{R367TER_DEC_NCO1,	0x2c},
-	{R367TER_DEC_NCO2,	0x0f},
-	{R367TER_DEC_NCO3,	0x20},
-	{R367TER_SNR,		0xf1},
-	{R367TER_SYR_FFTADJ1,	0x00},
-	{R367TER_SYR_FFTADJ2,	0x00},
-	{R367TER_SYR_CHCADJ1,	0x00},
-	{R367TER_SYR_CHCADJ2,	0x00},
-	{R367TER_SYR_OFF,	0x00},
-	{R367TER_PPM_OFFSET1,	0x00},
-	{R367TER_PPM_OFFSET2,	0x03},
-	{R367TER_TRACKER_FREE2,	0x00},
-	{R367TER_DEBG_LT10,	0x00},
-	{R367TER_DEBG_LT11,	0x00},
-	{R367TER_DEBG_LT12,	0x00},
-	{R367TER_DEBG_LT13,	0x00},
-	{R367TER_DEBG_LT14,	0x00},
-	{R367TER_DEBG_LT15,	0x00},
-	{R367TER_DEBG_LT16,	0x00},
-	{R367TER_DEBG_LT17,	0x00},
-	{R367TER_DEBG_LT18,	0x00},
-	{R367TER_DEBG_LT19,	0x00},
-	{R367TER_DEBG_LT1A,	0x00},
-	{R367TER_DEBG_LT1B,	0x00},
-	{R367TER_DEBG_LT1C,	0x00},
-	{R367TER_DEBG_LT1D,	0x00},
-	{R367TER_DEBG_LT1E,	0x00},
-	{R367TER_DEBG_LT1F,	0x00},
-	{R367TER_RCCFGH,	0x00},
-	{R367TER_RCCFGM,	0x00},
-	{R367TER_RCCFGL,	0x00},
-	{R367TER_RCINSDELH,	0x00},
-	{R367TER_RCINSDELM,	0x00},
-	{R367TER_RCINSDELL,	0x00},
-	{R367TER_RCSTATUS,	0x00},
-	{R367TER_RCSPEED,	0x6f},
-	{R367TER_RCDEBUGM,	0xe7},
-	{R367TER_RCDEBUGL,	0x9b},
-	{R367TER_RCOBSCFG,	0x00},
-	{R367TER_RCOBSM,	0x00},
-	{R367TER_RCOBSL,	0x00},
-	{R367TER_RCFECSPY,	0x00},
-	{R367TER_RCFSPYCFG,	0x00},
-	{R367TER_RCFSPYDATA,	0x00},
-	{R367TER_RCFSPYOUT,	0x00},
-	{R367TER_RCFSTATUS,	0x00},
-	{R367TER_RCFGOODPACK,	0x00},
-	{R367TER_RCFPACKCNT,	0x00},
-	{R367TER_RCFSPYMISC,	0x00},
-	{R367TER_RCFBERCPT4,	0x00},
-	{R367TER_RCFBERCPT3,	0x00},
-	{R367TER_RCFBERCPT2,	0x00},
-	{R367TER_RCFBERCPT1,	0x00},
-	{R367TER_RCFBERCPT0,	0x00},
-	{R367TER_RCFBERERR2,	0x00},
-	{R367TER_RCFBERERR1,	0x00},
-	{R367TER_RCFBERERR0,	0x00},
-	{R367TER_RCFSTATESM,	0x00},
-	{R367TER_RCFSTATESL,	0x00},
-	{R367TER_RCFSPYBER,	0x00},
-	{R367TER_RCFSPYDISTM,	0x00},
-	{R367TER_RCFSPYDISTL,	0x00},
-	{R367TER_RCFSPYOBS7,	0x00},
-	{R367TER_RCFSPYOBS6,	0x00},
-	{R367TER_RCFSPYOBS5,	0x00},
-	{R367TER_RCFSPYOBS4,	0x00},
-	{R367TER_RCFSPYOBS3,	0x00},
-	{R367TER_RCFSPYOBS2,	0x00},
-	{R367TER_RCFSPYOBS1,	0x00},
-	{R367TER_RCFSPYOBS0,	0x00},
-	{R367TER_TSGENERAL,	0x00},
-	{R367TER_RC1SPEED,	0x6f},
-	{R367TER_TSGSTATUS,	0x18},
-	{R367TER_FECM,		0x01},
-	{R367TER_VTH12,		0xff},
-	{R367TER_VTH23,		0xa1},
-	{R367TER_VTH34,		0x64},
-	{R367TER_VTH56,		0x40},
-	{R367TER_VTH67,		0x00},
-	{R367TER_VTH78,		0x2c},
-	{R367TER_VITCURPUN,	0x12},
-	{R367TER_VERROR,	0x01},
-	{R367TER_PRVIT,		0x3f},
-	{R367TER_VAVSRVIT,	0x00},
-	{R367TER_VSTATUSVIT,	0xbd},
-	{R367TER_VTHINUSE,	0xa1},
-	{R367TER_KDIV12,	0x20},
-	{R367TER_KDIV23,	0x40},
-	{R367TER_KDIV34,	0x20},
-	{R367TER_KDIV56,	0x30},
-	{R367TER_KDIV67,	0x00},
-	{R367TER_KDIV78,	0x30},
-	{R367TER_SIGPOWER,	0x54},
-	{R367TER_DEMAPVIT,	0x40},
-	{R367TER_VITSCALE,	0x00},
-	{R367TER_FFEC1PRG,	0x00},
-	{R367TER_FVITCURPUN,	0x12},
-	{R367TER_FVERROR,	0x01},
-	{R367TER_FVSTATUSVIT,	0xbd},
-	{R367TER_DEBUG_LT1,	0x00},
-	{R367TER_DEBUG_LT2,	0x00},
-	{R367TER_DEBUG_LT3,	0x00},
-	{R367TER_TSTSFMET,	0x00},
-	{R367TER_SELOUT,	0x00},
-	{R367TER_TSYNC,		0x00},
-	{R367TER_TSTERR,	0x00},
-	{R367TER_TSFSYNC,	0x00},
-	{R367TER_TSTSFERR,	0x00},
-	{R367TER_TSTTSSF1,	0x01},
-	{R367TER_TSTTSSF2,	0x1f},
-	{R367TER_TSTTSSF3,	0x00},
-	{R367TER_TSTTS1,	0x00},
-	{R367TER_TSTTS2,	0x1f},
-	{R367TER_TSTTS3,	0x01},
-	{R367TER_TSTTS4,	0x00},
-	{R367TER_TSTTSRC,	0x00},
-	{R367TER_TSTTSRS,	0x00},
-	{R367TER_TSSTATEM,	0xb0},
-	{R367TER_TSSTATEL,	0x40},
-	{R367TER_TSCFGH,	0xC0},
-	{R367TER_TSCFGM,	0xc0},/* for xc5000; was 0x00 */
-	{R367TER_TSCFGL,	0x20},
-	{R367TER_TSSYNC,	0x00},
-	{R367TER_TSINSDELH,	0x00},
-	{R367TER_TSINSDELM,	0x00},
-	{R367TER_TSINSDELL,	0x00},
-	{R367TER_TSDIVN,	0x03},
-	{R367TER_TSDIVPM,	0x00},
-	{R367TER_TSDIVPL,	0x00},
-	{R367TER_TSDIVQM,	0x00},
-	{R367TER_TSDIVQL,	0x00},
-	{R367TER_TSDILSTKM,	0x00},
-	{R367TER_TSDILSTKL,	0x00},
-	{R367TER_TSSPEED,	0x40},/* for xc5000; was 0x6f */
-	{R367TER_TSSTATUS,	0x81},
-	{R367TER_TSSTATUS2,	0x6a},
-	{R367TER_TSBITRATEM,	0x0f},
-	{R367TER_TSBITRATEL,	0xc6},
-	{R367TER_TSPACKLENM,	0x00},
-	{R367TER_TSPACKLENL,	0xfc},
-	{R367TER_TSBLOCLENM,	0x0a},
-	{R367TER_TSBLOCLENL,	0x80},
-	{R367TER_TSDLYH,	0x90},
-	{R367TER_TSDLYM,	0x68},
-	{R367TER_TSDLYL,	0x01},
-	{R367TER_TSNPDAV,	0x00},
-	{R367TER_TSBUFSTATH,	0x00},
-	{R367TER_TSBUFSTATM,	0x00},
-	{R367TER_TSBUFSTATL,	0x00},
-	{R367TER_TSDEBUGM,	0xcf},
-	{R367TER_TSDEBUGL,	0x1e},
-	{R367TER_TSDLYSETH,	0x00},
-	{R367TER_TSDLYSETM,	0x68},
-	{R367TER_TSDLYSETL,	0x00},
-	{R367TER_TSOBSCFG,	0x00},
-	{R367TER_TSOBSM,	0x47},
-	{R367TER_TSOBSL,	0x1f},
-	{R367TER_ERRCTRL1,	0x95},
-	{R367TER_ERRCNT1H,	0x80},
-	{R367TER_ERRCNT1M,	0x00},
-	{R367TER_ERRCNT1L,	0x00},
-	{R367TER_ERRCTRL2,	0x95},
-	{R367TER_ERRCNT2H,	0x00},
-	{R367TER_ERRCNT2M,	0x00},
-	{R367TER_ERRCNT2L,	0x00},
-	{R367TER_FECSPY,	0x88},
-	{R367TER_FSPYCFG,	0x2c},
-	{R367TER_FSPYDATA,	0x3a},
-	{R367TER_FSPYOUT,	0x06},
-	{R367TER_FSTATUS,	0x61},
-	{R367TER_FGOODPACK,	0xff},
-	{R367TER_FPACKCNT,	0xff},
-	{R367TER_FSPYMISC,	0x66},
-	{R367TER_FBERCPT4,	0x00},
-	{R367TER_FBERCPT3,	0x00},
-	{R367TER_FBERCPT2,	0x36},
-	{R367TER_FBERCPT1,	0x36},
-	{R367TER_FBERCPT0,	0x14},
-	{R367TER_FBERERR2,	0x00},
-	{R367TER_FBERERR1,	0x03},
-	{R367TER_FBERERR0,	0x28},
-	{R367TER_FSTATESM,	0x00},
-	{R367TER_FSTATESL,	0x02},
-	{R367TER_FSPYBER,	0x00},
-	{R367TER_FSPYDISTM,	0x01},
-	{R367TER_FSPYDISTL,	0x9f},
-	{R367TER_FSPYOBS7,	0xc9},
-	{R367TER_FSPYOBS6,	0x99},
-	{R367TER_FSPYOBS5,	0x08},
-	{R367TER_FSPYOBS4,	0xec},
-	{R367TER_FSPYOBS3,	0x01},
-	{R367TER_FSPYOBS2,	0x0f},
-	{R367TER_FSPYOBS1,	0xf5},
-	{R367TER_FSPYOBS0,	0x08},
-	{R367TER_SFDEMAP,	0x40},
-	{R367TER_SFERROR,	0x00},
-	{R367TER_SFAVSR,	0x30},
-	{R367TER_SFECSTATUS,	0xcc},
-	{R367TER_SFKDIV12,	0x20},
-	{R367TER_SFKDIV23,	0x40},
-	{R367TER_SFKDIV34,	0x20},
-	{R367TER_SFKDIV56,	0x20},
-	{R367TER_SFKDIV67,	0x00},
-	{R367TER_SFKDIV78,	0x20},
-	{R367TER_SFDILSTKM,	0x00},
-	{R367TER_SFDILSTKL,	0x00},
-	{R367TER_SFSTATUS,	0xb5},
-	{R367TER_SFDLYH,	0x90},
-	{R367TER_SFDLYM,	0x60},
-	{R367TER_SFDLYL,	0x01},
-	{R367TER_SFDLYSETH,	0xc0},
-	{R367TER_SFDLYSETM,	0x60},
-	{R367TER_SFDLYSETL,	0x00},
-	{R367TER_SFOBSCFG,	0x00},
-	{R367TER_SFOBSM,	0x47},
-	{R367TER_SFOBSL,	0x05},
-	{R367TER_SFECINFO,	0x40},
-	{R367TER_SFERRCTRL,	0x74},
-	{R367TER_SFERRCNTH,	0x80},
-	{R367TER_SFERRCNTM ,	0x00},
-	{R367TER_SFERRCNTL,	0x00},
-	{R367TER_SYMBRATEM,	0x2f},
-	{R367TER_SYMBRATEL,	0x50},
-	{R367TER_SYMBSTATUS,	0x7f},
-	{R367TER_SYMBCFG,	0x00},
-	{R367TER_SYMBFIFOM,	0xf4},
-	{R367TER_SYMBFIFOL,	0x0d},
-	{R367TER_SYMBOFFSM,	0xf0},
-	{R367TER_SYMBOFFSL,	0x2d},
-	{R367TER_DEBUG_LT4,	0x00},
-	{R367TER_DEBUG_LT5,	0x00},
-	{R367TER_DEBUG_LT6,	0x00},
-	{R367TER_DEBUG_LT7,	0x00},
-	{R367TER_DEBUG_LT8,	0x00},
-	{R367TER_DEBUG_LT9,	0x00},
-};
-
-#define RF_LOOKUP_TABLE_SIZE  31
-#define RF_LOOKUP_TABLE2_SIZE 16
-/* RF Level (for RF AGC->AGC1) Lookup Table, depends on the board and tuner.*/
-s32 stv0367cab_RF_LookUp1[RF_LOOKUP_TABLE_SIZE][RF_LOOKUP_TABLE_SIZE] = {
-	{/*AGC1*/
-		48, 50, 51, 53, 54, 56, 57, 58, 60, 61, 62, 63,
-		64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75,
-		76, 77, 78, 80, 83, 85, 88,
-	}, {/*RF(dbm)*/
-		22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
-		34, 35, 36, 37, 38, 39, 41, 42, 43, 44, 46, 47,
-		49, 50, 52, 53, 54, 55, 56,
-	}
-};
-/* RF Level (for IF AGC->AGC2) Lookup Table, depends on the board and tuner.*/
-s32 stv0367cab_RF_LookUp2[RF_LOOKUP_TABLE2_SIZE][RF_LOOKUP_TABLE2_SIZE] = {
-	{/*AGC2*/
-		28, 29, 31, 32, 34, 35, 36, 37,
-		38, 39, 40, 41, 42, 43, 44, 45,
-	}, {/*RF(dbm)*/
-		57, 58, 59, 60, 61, 62, 63, 64,
-		65, 66, 67, 68, 69, 70, 71, 72,
-	}
-};
-
-static struct st_register def0367cab[STV0367CAB_NBREGS] = {
-	{R367CAB_ID,		0x60},
-	{R367CAB_I2CRPT,	0xa0},
-	/*{R367CAB_I2CRPT,	0x22},*/
-	{R367CAB_TOPCTRL,	0x10},
-	{R367CAB_IOCFG0,	0x80},
-	{R367CAB_DAC0R,		0x00},
-	{R367CAB_IOCFG1,	0x00},
-	{R367CAB_DAC1R,		0x00},
-	{R367CAB_IOCFG2,	0x00},
-	{R367CAB_SDFR,		0x00},
-	{R367CAB_AUX_CLK,	0x00},
-	{R367CAB_FREESYS1,	0x00},
-	{R367CAB_FREESYS2,	0x00},
-	{R367CAB_FREESYS3,	0x00},
-	{R367CAB_GPIO_CFG,	0x55},
-	{R367CAB_GPIO_CMD,	0x01},
-	{R367CAB_TSTRES,	0x00},
-	{R367CAB_ANACTRL,	0x0d},/* was 0x00 need to check - I.M.L.*/
-	{R367CAB_TSTBUS,	0x00},
-	{R367CAB_RF_AGC1,	0xea},
-	{R367CAB_RF_AGC2,	0x82},
-	{R367CAB_ANADIGCTRL,	0x0b},
-	{R367CAB_PLLMDIV,	0x01},
-	{R367CAB_PLLNDIV,	0x08},
-	{R367CAB_PLLSETUP,	0x18},
-	{R367CAB_DUAL_AD12,	0x0C}, /* for xc5000 AGC voltage 1.6V */
-	{R367CAB_TSTBIST,	0x00},
-	{R367CAB_CTRL_1,	0x00},
-	{R367CAB_CTRL_2,	0x03},
-	{R367CAB_IT_STATUS1,	0x2b},
-	{R367CAB_IT_STATUS2,	0x08},
-	{R367CAB_IT_EN1,	0x00},
-	{R367CAB_IT_EN2,	0x00},
-	{R367CAB_CTRL_STATUS,	0x04},
-	{R367CAB_TEST_CTL,	0x00},
-	{R367CAB_AGC_CTL,	0x73},
-	{R367CAB_AGC_IF_CFG,	0x50},
-	{R367CAB_AGC_RF_CFG,	0x00},
-	{R367CAB_AGC_PWM_CFG,	0x03},
-	{R367CAB_AGC_PWR_REF_L,	0x5a},
-	{R367CAB_AGC_PWR_REF_H,	0x00},
-	{R367CAB_AGC_RF_TH_L,	0xff},
-	{R367CAB_AGC_RF_TH_H,	0x07},
-	{R367CAB_AGC_IF_LTH_L,	0x00},
-	{R367CAB_AGC_IF_LTH_H,	0x08},
-	{R367CAB_AGC_IF_HTH_L,	0xff},
-	{R367CAB_AGC_IF_HTH_H,	0x07},
-	{R367CAB_AGC_PWR_RD_L,	0xa0},
-	{R367CAB_AGC_PWR_RD_M,	0xe9},
-	{R367CAB_AGC_PWR_RD_H,	0x03},
-	{R367CAB_AGC_PWM_IFCMD_L,	0xe4},
-	{R367CAB_AGC_PWM_IFCMD_H,	0x00},
-	{R367CAB_AGC_PWM_RFCMD_L,	0xff},
-	{R367CAB_AGC_PWM_RFCMD_H,	0x07},
-	{R367CAB_IQDEM_CFG,	0x01},
-	{R367CAB_MIX_NCO_LL,	0x22},
-	{R367CAB_MIX_NCO_HL,	0x96},
-	{R367CAB_MIX_NCO_HH,	0x55},
-	{R367CAB_SRC_NCO_LL,	0xff},
-	{R367CAB_SRC_NCO_LH,	0x0c},
-	{R367CAB_SRC_NCO_HL,	0xf5},
-	{R367CAB_SRC_NCO_HH,	0x20},
-	{R367CAB_IQDEM_GAIN_SRC_L,	0x06},
-	{R367CAB_IQDEM_GAIN_SRC_H,	0x01},
-	{R367CAB_IQDEM_DCRM_CFG_LL,	0xfe},
-	{R367CAB_IQDEM_DCRM_CFG_LH,	0xff},
-	{R367CAB_IQDEM_DCRM_CFG_HL,	0x0f},
-	{R367CAB_IQDEM_DCRM_CFG_HH,	0x00},
-	{R367CAB_IQDEM_ADJ_COEFF0,	0x34},
-	{R367CAB_IQDEM_ADJ_COEFF1,	0xae},
-	{R367CAB_IQDEM_ADJ_COEFF2,	0x46},
-	{R367CAB_IQDEM_ADJ_COEFF3,	0x77},
-	{R367CAB_IQDEM_ADJ_COEFF4,	0x96},
-	{R367CAB_IQDEM_ADJ_COEFF5,	0x69},
-	{R367CAB_IQDEM_ADJ_COEFF6,	0xc7},
-	{R367CAB_IQDEM_ADJ_COEFF7,	0x01},
-	{R367CAB_IQDEM_ADJ_EN,	0x04},
-	{R367CAB_IQDEM_ADJ_AGC_REF,	0x94},
-	{R367CAB_ALLPASSFILT1,	0xc9},
-	{R367CAB_ALLPASSFILT2,	0x2d},
-	{R367CAB_ALLPASSFILT3,	0xa3},
-	{R367CAB_ALLPASSFILT4,	0xfb},
-	{R367CAB_ALLPASSFILT5,	0xf6},
-	{R367CAB_ALLPASSFILT6,	0x45},
-	{R367CAB_ALLPASSFILT7,	0x6f},
-	{R367CAB_ALLPASSFILT8,	0x7e},
-	{R367CAB_ALLPASSFILT9,	0x05},
-	{R367CAB_ALLPASSFILT10,	0x0a},
-	{R367CAB_ALLPASSFILT11,	0x51},
-	{R367CAB_TRL_AGC_CFG,	0x20},
-	{R367CAB_TRL_LPF_CFG,	0x28},
-	{R367CAB_TRL_LPF_ACQ_GAIN,	0x44},
-	{R367CAB_TRL_LPF_TRK_GAIN,	0x22},
-	{R367CAB_TRL_LPF_OUT_GAIN,	0x03},
-	{R367CAB_TRL_LOCKDET_LTH,	0x04},
-	{R367CAB_TRL_LOCKDET_HTH,	0x11},
-	{R367CAB_TRL_LOCKDET_TRGVAL,	0x20},
-	{R367CAB_IQ_QAM,	0x01},
-	{R367CAB_FSM_STATE,	0xa0},
-	{R367CAB_FSM_CTL,	0x08},
-	{R367CAB_FSM_STS,	0x0c},
-	{R367CAB_FSM_SNR0_HTH,	0x00},
-	{R367CAB_FSM_SNR1_HTH,	0x00},
-	{R367CAB_FSM_SNR2_HTH,	0x23},/* 0x00 */
-	{R367CAB_FSM_SNR0_LTH,	0x00},
-	{R367CAB_FSM_SNR1_LTH,	0x00},
-	{R367CAB_FSM_EQA1_HTH,	0x00},
-	{R367CAB_FSM_TEMPO,	0x32},
-	{R367CAB_FSM_CONFIG,	0x03},
-	{R367CAB_EQU_I_TESTTAP_L,	0x11},
-	{R367CAB_EQU_I_TESTTAP_M,	0x00},
-	{R367CAB_EQU_I_TESTTAP_H,	0x00},
-	{R367CAB_EQU_TESTAP_CFG,	0x00},
-	{R367CAB_EQU_Q_TESTTAP_L,	0xff},
-	{R367CAB_EQU_Q_TESTTAP_M,	0x00},
-	{R367CAB_EQU_Q_TESTTAP_H,	0x00},
-	{R367CAB_EQU_TAP_CTRL,	0x00},
-	{R367CAB_EQU_CTR_CRL_CONTROL_L,	0x11},
-	{R367CAB_EQU_CTR_CRL_CONTROL_H,	0x05},
-	{R367CAB_EQU_CTR_HIPOW_L,	0x00},
-	{R367CAB_EQU_CTR_HIPOW_H,	0x00},
-	{R367CAB_EQU_I_EQU_LO,	0xef},
-	{R367CAB_EQU_I_EQU_HI,	0x00},
-	{R367CAB_EQU_Q_EQU_LO,	0xee},
-	{R367CAB_EQU_Q_EQU_HI,	0x00},
-	{R367CAB_EQU_MAPPER,	0xc5},
-	{R367CAB_EQU_SWEEP_RATE,	0x80},
-	{R367CAB_EQU_SNR_LO,	0x64},
-	{R367CAB_EQU_SNR_HI,	0x03},
-	{R367CAB_EQU_GAMMA_LO,	0x00},
-	{R367CAB_EQU_GAMMA_HI,	0x00},
-	{R367CAB_EQU_ERR_GAIN,	0x36},
-	{R367CAB_EQU_RADIUS,	0xaa},
-	{R367CAB_EQU_FFE_MAINTAP,	0x00},
-	{R367CAB_EQU_FFE_LEAKAGE,	0x63},
-	{R367CAB_EQU_FFE_MAINTAP_POS,	0xdf},
-	{R367CAB_EQU_GAIN_WIDE,	0x88},
-	{R367CAB_EQU_GAIN_NARROW,	0x41},
-	{R367CAB_EQU_CTR_LPF_GAIN,	0xd1},
-	{R367CAB_EQU_CRL_LPF_GAIN,	0xa7},
-	{R367CAB_EQU_GLOBAL_GAIN,	0x06},
-	{R367CAB_EQU_CRL_LD_SEN,	0x85},
-	{R367CAB_EQU_CRL_LD_VAL,	0xe2},
-	{R367CAB_EQU_CRL_TFR,	0x20},
-	{R367CAB_EQU_CRL_BISTH_LO,	0x00},
-	{R367CAB_EQU_CRL_BISTH_HI,	0x00},
-	{R367CAB_EQU_SWEEP_RANGE_LO,	0x00},
-	{R367CAB_EQU_SWEEP_RANGE_HI,	0x00},
-	{R367CAB_EQU_CRL_LIMITER,	0x40},
-	{R367CAB_EQU_MODULUS_MAP,	0x90},
-	{R367CAB_EQU_PNT_GAIN,	0xa7},
-	{R367CAB_FEC_AC_CTR_0,	0x16},
-	{R367CAB_FEC_AC_CTR_1,	0x0b},
-	{R367CAB_FEC_AC_CTR_2,	0x88},
-	{R367CAB_FEC_AC_CTR_3,	0x02},
-	{R367CAB_FEC_STATUS,	0x12},
-	{R367CAB_RS_COUNTER_0,	0x7d},
-	{R367CAB_RS_COUNTER_1,	0xd0},
-	{R367CAB_RS_COUNTER_2,	0x19},
-	{R367CAB_RS_COUNTER_3,	0x0b},
-	{R367CAB_RS_COUNTER_4,	0xa3},
-	{R367CAB_RS_COUNTER_5,	0x00},
-	{R367CAB_BERT_0,	0x01},
-	{R367CAB_BERT_1,	0x25},
-	{R367CAB_BERT_2,	0x41},
-	{R367CAB_BERT_3,	0x39},
-	{R367CAB_OUTFORMAT_0,	0xc2},
-	{R367CAB_OUTFORMAT_1,	0x22},
-	{R367CAB_SMOOTHER_2,	0x28},
-	{R367CAB_TSMF_CTRL_0,	0x01},
-	{R367CAB_TSMF_CTRL_1,	0xc6},
-	{R367CAB_TSMF_CTRL_3,	0x43},
-	{R367CAB_TS_ON_ID_0,	0x00},
-	{R367CAB_TS_ON_ID_1,	0x00},
-	{R367CAB_TS_ON_ID_2,	0x00},
-	{R367CAB_TS_ON_ID_3,	0x00},
-	{R367CAB_RE_STATUS_0,	0x00},
-	{R367CAB_RE_STATUS_1,	0x00},
-	{R367CAB_RE_STATUS_2,	0x00},
-	{R367CAB_RE_STATUS_3,	0x00},
-	{R367CAB_TS_STATUS_0,	0x00},
-	{R367CAB_TS_STATUS_1,	0x00},
-	{R367CAB_TS_STATUS_2,	0xa0},
-	{R367CAB_TS_STATUS_3,	0x00},
-	{R367CAB_T_O_ID_0,	0x00},
-	{R367CAB_T_O_ID_1,	0x00},
-	{R367CAB_T_O_ID_2,	0x00},
-	{R367CAB_T_O_ID_3,	0x00},
-};
-
-static
-int stv0367_writeregs(struct stv0367_state *state, u16 reg, u8 *data, int len)
-{
-	u8 buf[len + 2];
-	struct i2c_msg msg = {
-		.addr = state->config->demod_address,
-		.flags = 0,
-		.buf = buf,
-		.len = len + 2
-	};
-	int ret;
-
-	buf[0] = MSB(reg);
-	buf[1] = LSB(reg);
-	memcpy(buf + 2, data, len);
-
-	if (i2cdebug)
-		printk(KERN_DEBUG "%s: %02x: %02x\n", __func__, reg, buf[2]);
-
-	ret = i2c_transfer(state->i2c, &msg, 1);
-	if (ret != 1)
-		printk(KERN_ERR "%s: i2c write error!\n", __func__);
-
-	return (ret != 1) ? -EREMOTEIO : 0;
-}
-
-static int stv0367_writereg(struct stv0367_state *state, u16 reg, u8 data)
-{
-	return stv0367_writeregs(state, reg, &data, 1);
-}
-
-static u8 stv0367_readreg(struct stv0367_state *state, u16 reg)
-{
-	u8 b0[] = { 0, 0 };
-	u8 b1[] = { 0 };
-	struct i2c_msg msg[] = {
-		{
-			.addr = state->config->demod_address,
-			.flags = 0,
-			.buf = b0,
-			.len = 2
-		}, {
-			.addr = state->config->demod_address,
-			.flags = I2C_M_RD,
-			.buf = b1,
-			.len = 1
-		}
-	};
-	int ret;
-
-	b0[0] = MSB(reg);
-	b0[1] = LSB(reg);
-
-	ret = i2c_transfer(state->i2c, msg, 2);
-	if (ret != 2)
-		printk(KERN_ERR "%s: i2c read error\n", __func__);
-
-	if (i2cdebug)
-		printk(KERN_DEBUG "%s: %02x: %02x\n", __func__, reg, b1[0]);
-
-	return b1[0];
-}
-
-static 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);
-}
-
-static void stv0367_writebits(struct stv0367_state *state, u32 label, u8 val)
-{
-	u8 reg, mask, pos;
-
-	reg = stv0367_readreg(state, (label >> 16) & 0xffff);
-	extract_mask_pos(label, &mask, &pos);
-
-	val = mask & (val << pos);
-
-	reg = (reg & (~mask)) | val;
-	stv0367_writereg(state, (label >> 16) & 0xffff, reg);
-
-}
-
-static void stv0367_setbits(u8 *reg, u32 label, u8 val)
-{
-	u8 mask, pos;
-
-	extract_mask_pos(label, &mask, &pos);
-
-	val = mask & (val << pos);
-
-	(*reg) = ((*reg) & (~mask)) | val;
-}
-
-static u8 stv0367_readbits(struct stv0367_state *state, u32 label)
-{
-	u8 val = 0xff;
-	u8 mask, pos;
-
-	extract_mask_pos(label, &mask, &pos);
-
-	val = stv0367_readreg(state, label >> 16);
-	val = (val & mask) >> pos;
-
-	return val;
-}
-
-u8 stv0367_getbits(u8 reg, u32 label)
-{
-	u8 mask, pos;
-
-	extract_mask_pos(label, &mask, &pos);
-
-	return (reg & mask) >> pos;
-}
-
-static int stv0367ter_gate_ctrl(struct dvb_frontend *fe, int enable)
-{
-	struct stv0367_state *state = fe->demodulator_priv;
-	u8 tmp = stv0367_readreg(state, R367TER_I2CRPT);
-
-	dprintk("%s:\n", __func__);
-
-	if (enable) {
-		stv0367_setbits(&tmp, F367TER_STOP_ENABLE, 0);
-		stv0367_setbits(&tmp, F367TER_I2CT_ON, 1);
-	} else {
-		stv0367_setbits(&tmp, F367TER_STOP_ENABLE, 1);
-		stv0367_setbits(&tmp, F367TER_I2CT_ON, 0);
-	}
-
-	stv0367_writereg(state, R367TER_I2CRPT, tmp);
-
-	return 0;
-}
-
-static u32 stv0367_get_tuner_freq(struct dvb_frontend *fe)
-{
-	struct dvb_frontend_ops	*frontend_ops = NULL;
-	struct dvb_tuner_ops	*tuner_ops = NULL;
-	u32 freq = 0;
-	int err = 0;
-
-	dprintk("%s:\n", __func__);
-
-
-	if (&fe->ops)
-		frontend_ops = &fe->ops;
-	if (&frontend_ops->tuner_ops)
-		tuner_ops = &frontend_ops->tuner_ops;
-	if (tuner_ops->get_frequency) {
-		err = tuner_ops->get_frequency(fe, &freq);
-		if (err < 0) {
-			printk(KERN_ERR "%s: Invalid parameter\n", __func__);
-			return err;
-		}
-
-		dprintk("%s: frequency=%d\n", __func__, freq);
-
-	} else
-		return -1;
-
-	return freq;
-}
-
-static u16 CellsCoeffs_8MHz_367cofdm[3][6][5] = {
-	{
-		{0x10EF, 0xE205, 0x10EF, 0xCE49, 0x6DA7}, /* CELL 1 COEFFS 27M*/
-		{0x2151, 0xc557, 0x2151, 0xc705, 0x6f93}, /* CELL 2 COEFFS */
-		{0x2503, 0xc000, 0x2503, 0xc375, 0x7194}, /* CELL 3 COEFFS */
-		{0x20E9, 0xca94, 0x20e9, 0xc153, 0x7194}, /* CELL 4 COEFFS */
-		{0x06EF, 0xF852, 0x06EF, 0xC057, 0x7207}, /* CELL 5 COEFFS */
-		{0x0000, 0x0ECC, 0x0ECC, 0x0000, 0x3647} /* CELL 6 COEFFS */
-	}, {
-		{0x10A0, 0xE2AF, 0x10A1, 0xCE76, 0x6D6D}, /* CELL 1 COEFFS 25M*/
-		{0x20DC, 0xC676, 0x20D9, 0xC80A, 0x6F29},
-		{0x2532, 0xC000, 0x251D, 0xC391, 0x706F},
-		{0x1F7A, 0xCD2B, 0x2032, 0xC15E, 0x711F},
-		{0x0698, 0xFA5E, 0x0568, 0xC059, 0x7193},
-		{0x0000, 0x0918, 0x149C, 0x0000, 0x3642} /* CELL 6 COEFFS */
-	}, {
-		{0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, /* 30M */
-		{0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
-		{0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
-		{0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
-		{0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
-		{0x0000, 0x0000, 0x0000, 0x0000, 0x0000}
-	}
-};
-
-static u16 CellsCoeffs_7MHz_367cofdm[3][6][5] = {
-	{
-		{0x12CA, 0xDDAF, 0x12CA, 0xCCEB, 0x6FB1}, /* CELL 1 COEFFS 27M*/
-		{0x2329, 0xC000, 0x2329, 0xC6B0, 0x725F}, /* CELL 2 COEFFS */
-		{0x2394, 0xC000, 0x2394, 0xC2C7, 0x7410}, /* CELL 3 COEFFS */
-		{0x251C, 0xC000, 0x251C, 0xC103, 0x74D9}, /* CELL 4 COEFFS */
-		{0x0804, 0xF546, 0x0804, 0xC040, 0x7544}, /* CELL 5 COEFFS */
-		{0x0000, 0x0CD9, 0x0CD9, 0x0000, 0x370A} /* CELL 6 COEFFS */
-	}, {
-		{0x1285, 0xDE47, 0x1285, 0xCD17, 0x6F76}, /*25M*/
-		{0x234C, 0xC000, 0x2348, 0xC6DA, 0x7206},
-		{0x23B4, 0xC000, 0x23AC, 0xC2DB, 0x73B3},
-		{0x253D, 0xC000, 0x25B6, 0xC10B, 0x747F},
-		{0x0721, 0xF79C, 0x065F, 0xC041, 0x74EB},
-		{0x0000, 0x08FA, 0x1162, 0x0000, 0x36FF}
-	}, {
-		{0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, /* 30M */
-		{0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
-		{0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
-		{0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
-		{0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
-		{0x0000, 0x0000, 0x0000, 0x0000, 0x0000}
-	}
-};
-
-static u16 CellsCoeffs_6MHz_367cofdm[3][6][5] = {
-	{
-		{0x1699, 0xD5B8, 0x1699, 0xCBC3, 0x713B}, /* CELL 1 COEFFS 27M*/
-		{0x2245, 0xC000, 0x2245, 0xC568, 0x74D5}, /* CELL 2 COEFFS */
-		{0x227F, 0xC000, 0x227F, 0xC1FC, 0x76C6}, /* CELL 3 COEFFS */
-		{0x235E, 0xC000, 0x235E, 0xC0A7, 0x778A}, /* CELL 4 COEFFS */
-		{0x0ECB, 0xEA0B, 0x0ECB, 0xC027, 0x77DD}, /* CELL 5 COEFFS */
-		{0x0000, 0x0B68, 0x0B68, 0x0000, 0xC89A}, /* CELL 6 COEFFS */
-	}, {
-		{0x1655, 0xD64E, 0x1658, 0xCBEF, 0x70FE}, /*25M*/
-		{0x225E, 0xC000, 0x2256, 0xC589, 0x7489},
-		{0x2293, 0xC000, 0x2295, 0xC209, 0x767E},
-		{0x2377, 0xC000, 0x23AA, 0xC0AB, 0x7746},
-		{0x0DC7, 0xEBC8, 0x0D07, 0xC027, 0x7799},
-		{0x0000, 0x0888, 0x0E9C, 0x0000, 0x3757}
-
-	}, {
-		{0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, /* 30M */
-		{0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
-		{0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
-		{0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
-		{0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
-		{0x0000, 0x0000, 0x0000, 0x0000, 0x0000}
-	}
-};
-
-static u32 stv0367ter_get_mclk(struct stv0367_state *state, u32 ExtClk_Hz)
-{
-	u32 mclk_Hz = 0; /* master clock frequency (Hz) */
-	u32 m, n, p;
-
-	dprintk("%s:\n", __func__);
-
-	if (stv0367_readbits(state, F367TER_BYPASS_PLLXN) == 0) {
-		n = (u32)stv0367_readbits(state, F367TER_PLL_NDIV);
-		if (n == 0)
-			n = n + 1;
-
-		m = (u32)stv0367_readbits(state, F367TER_PLL_MDIV);
-		if (m == 0)
-			m = m + 1;
-
-		p = (u32)stv0367_readbits(state, F367TER_PLL_PDIV);
-		if (p > 5)
-			p = 5;
-
-		mclk_Hz = ((ExtClk_Hz / 2) * n) / (m * (1 << p));
-
-		dprintk("N=%d M=%d P=%d mclk_Hz=%d ExtClk_Hz=%d\n",
-				n, m, p, mclk_Hz, ExtClk_Hz);
-	} else
-		mclk_Hz = ExtClk_Hz;
-
-	dprintk("%s: mclk_Hz=%d\n", __func__, mclk_Hz);
-
-	return mclk_Hz;
-}
-
-static int stv0367ter_filt_coeff_init(struct stv0367_state *state,
-				u16 CellsCoeffs[3][6][5], u32 DemodXtal)
-{
-	int i, j, k, freq;
-
-	dprintk("%s:\n", __func__);
-
-	freq = stv0367ter_get_mclk(state, DemodXtal);
-
-	if (freq == 53125000)
-		k = 1; /* equivalent to Xtal 25M on 362*/
-	else if (freq == 54000000)
-		k = 0; /* equivalent to Xtal 27M on 362*/
-	else if (freq == 52500000)
-		k = 2; /* equivalent to Xtal 30M on 362*/
-	else
-		return 0;
-
-	for (i = 1; i <= 6; i++) {
-		stv0367_writebits(state, F367TER_IIR_CELL_NB, i - 1);
-
-		for (j = 1; j <= 5; j++) {
-			stv0367_writereg(state,
-				(R367TER_IIRCX_COEFF1_MSB + 2 * (j - 1)),
-				MSB(CellsCoeffs[k][i-1][j-1]));
-			stv0367_writereg(state,
-				(R367TER_IIRCX_COEFF1_LSB + 2 * (j - 1)),
-				LSB(CellsCoeffs[k][i-1][j-1]));
-		}
-	}
-
-	return 1;
-
-}
-
-static void stv0367ter_agc_iir_lock_detect_set(struct stv0367_state *state)
-{
-	dprintk("%s:\n", __func__);
-
-	stv0367_writebits(state, F367TER_LOCK_DETECT_LSB, 0x00);
-
-	/* Lock detect 1 */
-	stv0367_writebits(state, F367TER_LOCK_DETECT_CHOICE, 0x00);
-	stv0367_writebits(state, F367TER_LOCK_DETECT_MSB, 0x06);
-	stv0367_writebits(state, F367TER_AUT_AGC_TARGET_LSB, 0x04);
-
-	/* Lock detect 2 */
-	stv0367_writebits(state, F367TER_LOCK_DETECT_CHOICE, 0x01);
-	stv0367_writebits(state, F367TER_LOCK_DETECT_MSB, 0x06);
-	stv0367_writebits(state, F367TER_AUT_AGC_TARGET_LSB, 0x04);
-
-	/* Lock detect 3 */
-	stv0367_writebits(state, F367TER_LOCK_DETECT_CHOICE, 0x02);
-	stv0367_writebits(state, F367TER_LOCK_DETECT_MSB, 0x01);
-	stv0367_writebits(state, F367TER_AUT_AGC_TARGET_LSB, 0x00);
-
-	/* Lock detect 4 */
-	stv0367_writebits(state, F367TER_LOCK_DETECT_CHOICE, 0x03);
-	stv0367_writebits(state, F367TER_LOCK_DETECT_MSB, 0x01);
-	stv0367_writebits(state, F367TER_AUT_AGC_TARGET_LSB, 0x00);
-
-}
-
-static int stv0367_iir_filt_init(struct stv0367_state *state, u8 Bandwidth,
-							u32 DemodXtalValue)
-{
-	dprintk("%s:\n", __func__);
-
-	stv0367_writebits(state, F367TER_NRST_IIR, 0);
-
-	switch (Bandwidth) {
-	case 6:
-		if (!stv0367ter_filt_coeff_init(state,
-				CellsCoeffs_6MHz_367cofdm,
-				DemodXtalValue))
-			return 0;
-		break;
-	case 7:
-		if (!stv0367ter_filt_coeff_init(state,
-				CellsCoeffs_7MHz_367cofdm,
-				DemodXtalValue))
-			return 0;
-		break;
-	case 8:
-		if (!stv0367ter_filt_coeff_init(state,
-				CellsCoeffs_8MHz_367cofdm,
-				DemodXtalValue))
-			return 0;
-		break;
-	default:
-		return 0;
-	}
-
-	stv0367_writebits(state, F367TER_NRST_IIR, 1);
-
-	return 1;
-}
-
-static void stv0367ter_agc_iir_rst(struct stv0367_state *state)
-{
-
-	u8 com_n;
-
-	dprintk("%s:\n", __func__);
-
-	com_n = stv0367_readbits(state, F367TER_COM_N);
-
-	stv0367_writebits(state, F367TER_COM_N, 0x07);
-
-	stv0367_writebits(state, F367TER_COM_SOFT_RSTN, 0x00);
-	stv0367_writebits(state, F367TER_COM_AGC_ON, 0x00);
-
-	stv0367_writebits(state, F367TER_COM_SOFT_RSTN, 0x01);
-	stv0367_writebits(state, F367TER_COM_AGC_ON, 0x01);
-
-	stv0367_writebits(state, F367TER_COM_N, com_n);
-
-}
-
-static int stv0367ter_duration(s32 mode, int tempo1, int tempo2, int tempo3)
-{
-	int local_tempo = 0;
-	switch (mode) {
-	case 0:
-		local_tempo = tempo1;
-		break;
-	case 1:
-		local_tempo = tempo2;
-		break ;
-
-	case 2:
-		local_tempo = tempo3;
-		break;
-
-	default:
-		break;
-	}
-	/*	msleep(local_tempo);  */
-	return local_tempo;
-}
-
-static enum
-stv0367_ter_signal_type stv0367ter_check_syr(struct stv0367_state *state)
-{
-	int wd = 100;
-	unsigned short int SYR_var;
-	s32 SYRStatus;
-
-	dprintk("%s:\n", __func__);
-
-	SYR_var = stv0367_readbits(state, F367TER_SYR_LOCK);
-
-	while ((!SYR_var) && (wd > 0)) {
-		usleep_range(2000, 3000);
-		wd -= 2;
-		SYR_var = stv0367_readbits(state, F367TER_SYR_LOCK);
-	}
-
-	if (!SYR_var)
-		SYRStatus = FE_TER_NOSYMBOL;
-	else
-		SYRStatus =  FE_TER_SYMBOLOK;
-
-	dprintk("stv0367ter_check_syr SYRStatus %s\n",
-				SYR_var == 0 ? "No Symbol" : "OK");
-
-	return SYRStatus;
-}
-
-static enum
-stv0367_ter_signal_type stv0367ter_check_cpamp(struct stv0367_state *state,
-								s32 FFTmode)
-{
-
-	s32  CPAMPvalue = 0, CPAMPStatus, CPAMPMin;
-	int wd = 0;
-
-	dprintk("%s:\n", __func__);
-
-	switch (FFTmode) {
-	case 0: /*2k mode*/
-		CPAMPMin = 20;
-		wd = 10;
-		break;
-	case 1: /*8k mode*/
-		CPAMPMin = 80;
-		wd = 55;
-		break;
-	case 2: /*4k mode*/
-		CPAMPMin = 40;
-		wd = 30;
-		break;
-	default:
-		CPAMPMin = 0xffff;  /*drives to NOCPAMP	*/
-		break;
-	}
-
-	dprintk("%s: CPAMPMin=%d wd=%d\n", __func__, CPAMPMin, wd);
-
-	CPAMPvalue = stv0367_readbits(state, F367TER_PPM_CPAMP_DIRECT);
-	while ((CPAMPvalue < CPAMPMin) && (wd > 0)) {
-		usleep_range(1000, 2000);
-		wd -= 1;
-		CPAMPvalue = stv0367_readbits(state, F367TER_PPM_CPAMP_DIRECT);
-		/*dprintk("CPAMPvalue= %d at wd=%d\n",CPAMPvalue,wd); */
-	}
-	dprintk("******last CPAMPvalue= %d at wd=%d\n", CPAMPvalue, wd);
-	if (CPAMPvalue < CPAMPMin) {
-		CPAMPStatus = FE_TER_NOCPAMP;
-		printk(KERN_ERR "CPAMP failed\n");
-	} else {
-		printk(KERN_ERR "CPAMP OK !\n");
-		CPAMPStatus = FE_TER_CPAMPOK;
-	}
-
-	return CPAMPStatus;
-}
-
-enum
-stv0367_ter_signal_type stv0367ter_lock_algo(struct stv0367_state *state)
-{
-	enum stv0367_ter_signal_type ret_flag;
-	short int wd, tempo;
-	u8 try, u_var1 = 0, u_var2 = 0, u_var3 = 0, u_var4 = 0, mode, guard;
-	u8 tmp, tmp2;
-
-	dprintk("%s:\n", __func__);
-
-	if (state == NULL)
-		return FE_TER_SWNOK;
-
-	try = 0;
-	do {
-		ret_flag = FE_TER_LOCKOK;
-
-		stv0367_writebits(state, F367TER_CORE_ACTIVE, 0);
-
-		if (state->config->if_iq_mode != 0)
-			stv0367_writebits(state, F367TER_COM_N, 0x07);
-
-		stv0367_writebits(state, F367TER_GUARD, 3);/* suggest 2k 1/4 */
-		stv0367_writebits(state, F367TER_MODE, 0);
-		stv0367_writebits(state, F367TER_SYR_TR_DIS, 0);
-		usleep_range(5000, 10000);
-
-		stv0367_writebits(state, F367TER_CORE_ACTIVE, 1);
-
-
-		if (stv0367ter_check_syr(state) == FE_TER_NOSYMBOL)
-			return FE_TER_NOSYMBOL;
-		else { /*
-			if chip locked on wrong mode first try,
-			it must lock correctly second try */
-			mode = stv0367_readbits(state, F367TER_SYR_MODE);
-			if (stv0367ter_check_cpamp(state, mode) ==
-							FE_TER_NOCPAMP) {
-				if (try == 0)
-					ret_flag = FE_TER_NOCPAMP;
-
-			}
-		}
-
-		try++;
-	} while ((try < 10) && (ret_flag != FE_TER_LOCKOK));
-
-	tmp  = stv0367_readreg(state, R367TER_SYR_STAT);
-	tmp2 = stv0367_readreg(state, R367TER_STATUS);
-	dprintk("state=%p\n", state);
-	dprintk("LOCK OK! mode=%d SYR_STAT=0x%x R367TER_STATUS=0x%x\n",
-							mode, tmp, tmp2);
-
-	tmp  = stv0367_readreg(state, R367TER_PRVIT);
-	tmp2 = stv0367_readreg(state, R367TER_I2CRPT);
-	dprintk("PRVIT=0x%x I2CRPT=0x%x\n", tmp, tmp2);
-
-	tmp  = stv0367_readreg(state, R367TER_GAIN_SRC1);
-	dprintk("GAIN_SRC1=0x%x\n", tmp);
-
-	if ((mode != 0) && (mode != 1) && (mode != 2))
-		return FE_TER_SWNOK;
-
-	/*guard=stv0367_readbits(state,F367TER_SYR_GUARD); */
-
-	/*suppress EPQ auto for SYR_GARD 1/16 or 1/32
-	and set channel predictor in automatic */
-#if 0
-	switch (guard) {
-
-	case 0:
-	case 1:
-		stv0367_writebits(state, F367TER_AUTO_LE_EN, 0);
-		stv0367_writereg(state, R367TER_CHC_CTL, 0x01);
-		break;
-	case 2:
-	case 3:
-		stv0367_writebits(state, F367TER_AUTO_LE_EN, 1);
-		stv0367_writereg(state, R367TER_CHC_CTL, 0x11);
-		break;
-
-	default:
-		return FE_TER_SWNOK;
-	}
-#endif
-
-	/*reset fec an reedsolo FOR 367 only*/
-	stv0367_writebits(state, F367TER_RST_SFEC, 1);
-	stv0367_writebits(state, F367TER_RST_REEDSOLO, 1);
-	usleep_range(1000, 2000);
-	stv0367_writebits(state, F367TER_RST_SFEC, 0);
-	stv0367_writebits(state, F367TER_RST_REEDSOLO, 0);
-
-	u_var1 = stv0367_readbits(state, F367TER_LK);
-	u_var2 = stv0367_readbits(state, F367TER_PRF);
-	u_var3 = stv0367_readbits(state, F367TER_TPS_LOCK);
-	/*	u_var4=stv0367_readbits(state,F367TER_TSFIFO_LINEOK); */
-
-	wd = stv0367ter_duration(mode, 125, 500, 250);
-	tempo = stv0367ter_duration(mode, 4, 16, 8);
-
-	/*while ( ((!u_var1)||(!u_var2)||(!u_var3)||(!u_var4))  && (wd>=0)) */
-	while (((!u_var1) || (!u_var2) || (!u_var3)) && (wd >= 0)) {
-		usleep_range(1000 * tempo, 1000 * (tempo + 1));
-		wd -= tempo;
-		u_var1 = stv0367_readbits(state, F367TER_LK);
-		u_var2 = stv0367_readbits(state, F367TER_PRF);
-		u_var3 = stv0367_readbits(state, F367TER_TPS_LOCK);
-		/*u_var4=stv0367_readbits(state, F367TER_TSFIFO_LINEOK); */
-	}
-
-	if (!u_var1)
-		return FE_TER_NOLOCK;
-
-
-	if (!u_var2)
-		return FE_TER_NOPRFOUND;
-
-	if (!u_var3)
-		return FE_TER_NOTPS;
-
-	guard = stv0367_readbits(state, F367TER_SYR_GUARD);
-	stv0367_writereg(state, R367TER_CHC_CTL, 0x11);
-	switch (guard) {
-	case 0:
-	case 1:
-		stv0367_writebits(state, F367TER_AUTO_LE_EN, 0);
-		/*stv0367_writereg(state,R367TER_CHC_CTL, 0x1);*/
-		stv0367_writebits(state, F367TER_SYR_FILTER, 0);
-		break;
-	case 2:
-	case 3:
-		stv0367_writebits(state, F367TER_AUTO_LE_EN, 1);
-		/*stv0367_writereg(state,R367TER_CHC_CTL, 0x11);*/
-		stv0367_writebits(state, F367TER_SYR_FILTER, 1);
-		break;
-
-	default:
-		return FE_TER_SWNOK;
-	}
-
-	/* apply Sfec workaround if 8K 64QAM CR!=1/2*/
-	if ((stv0367_readbits(state, F367TER_TPS_CONST) == 2) &&
-			(mode == 1) &&
-			(stv0367_readbits(state, F367TER_TPS_HPCODE) != 0)) {
-		stv0367_writereg(state, R367TER_SFDLYSETH, 0xc0);
-		stv0367_writereg(state, R367TER_SFDLYSETM, 0x60);
-		stv0367_writereg(state, R367TER_SFDLYSETL, 0x0);
-	} else
-		stv0367_writereg(state, R367TER_SFDLYSETH, 0x0);
-
-	wd = stv0367ter_duration(mode, 125, 500, 250);
-	u_var4 = stv0367_readbits(state, F367TER_TSFIFO_LINEOK);
-
-	while ((!u_var4) && (wd >= 0)) {
-		usleep_range(1000 * tempo, 1000 * (tempo + 1));
-		wd -= tempo;
-		u_var4 = stv0367_readbits(state, F367TER_TSFIFO_LINEOK);
-	}
-
-	if (!u_var4)
-		return FE_TER_NOLOCK;
-
-	/* for 367 leave COM_N at 0x7 for IQ_mode*/
-	/*if(ter_state->if_iq_mode!=FE_TER_NORMAL_IF_TUNER) {
-		tempo=0;
-		while ((stv0367_readbits(state,F367TER_COM_USEGAINTRK)!=1) &&
-		(stv0367_readbits(state,F367TER_COM_AGCLOCK)!=1)&&(tempo<100)) {
-			ChipWaitOrAbort(state,1);
-			tempo+=1;
-		}
-
-		stv0367_writebits(state,F367TER_COM_N,0x17);
-	} */
-
-	stv0367_writebits(state, F367TER_SYR_TR_DIS, 1);
-
-	dprintk("FE_TER_LOCKOK !!!\n");
-
-	return	FE_TER_LOCKOK;
-
-}
-
-static void stv0367ter_set_ts_mode(struct stv0367_state *state,
-					enum stv0367_ts_mode PathTS)
-{
-
-	dprintk("%s:\n", __func__);
-
-	if (state == NULL)
-		return;
-
-	stv0367_writebits(state, F367TER_TS_DIS, 0);
-	switch (PathTS) {
-	default:
-		/*for removing warning :default we can assume in parallel mode*/
-	case STV0367_PARALLEL_PUNCT_CLOCK:
-		stv0367_writebits(state, F367TER_TSFIFO_SERIAL, 0);
-		stv0367_writebits(state, F367TER_TSFIFO_DVBCI, 0);
-		break;
-	case STV0367_SERIAL_PUNCT_CLOCK:
-		stv0367_writebits(state, F367TER_TSFIFO_SERIAL, 1);
-		stv0367_writebits(state, F367TER_TSFIFO_DVBCI, 1);
-		break;
-	}
-}
-
-static void stv0367ter_set_clk_pol(struct stv0367_state *state,
-					enum stv0367_clk_pol clock)
-{
-
-	dprintk("%s:\n", __func__);
-
-	if (state == NULL)
-		return;
-
-	switch (clock) {
-	case STV0367_RISINGEDGE_CLOCK:
-		stv0367_writebits(state, F367TER_TS_BYTE_CLK_INV, 1);
-		break;
-	case STV0367_FALLINGEDGE_CLOCK:
-		stv0367_writebits(state, F367TER_TS_BYTE_CLK_INV, 0);
-		break;
-		/*case FE_TER_CLOCK_POLARITY_DEFAULT:*/
-	default:
-		stv0367_writebits(state, F367TER_TS_BYTE_CLK_INV, 0);
-		break;
-	}
-}
-
-#if 0
-static void stv0367ter_core_sw(struct stv0367_state *state)
-{
-
-	dprintk("%s:\n", __func__);
-
-	stv0367_writebits(state, F367TER_CORE_ACTIVE, 0);
-	stv0367_writebits(state, F367TER_CORE_ACTIVE, 1);
-	msleep(350);
-}
-#endif
-static int stv0367ter_standby(struct dvb_frontend *fe, u8 standby_on)
-{
-	struct stv0367_state *state = fe->demodulator_priv;
-
-	dprintk("%s:\n", __func__);
-
-	if (standby_on) {
-		stv0367_writebits(state, F367TER_STDBY, 1);
-		stv0367_writebits(state, F367TER_STDBY_FEC, 1);
-		stv0367_writebits(state, F367TER_STDBY_CORE, 1);
-	} else {
-		stv0367_writebits(state, F367TER_STDBY, 0);
-		stv0367_writebits(state, F367TER_STDBY_FEC, 0);
-		stv0367_writebits(state, F367TER_STDBY_CORE, 0);
-	}
-
-	return 0;
-}
-
-static int stv0367ter_sleep(struct dvb_frontend *fe)
-{
-	return stv0367ter_standby(fe, 1);
-}
-
-int stv0367ter_init(struct dvb_frontend *fe)
-{
-	struct stv0367_state *state = fe->demodulator_priv;
-	struct stv0367ter_state *ter_state = state->ter_state;
-	int i;
-
-	dprintk("%s:\n", __func__);
-
-	ter_state->pBER = 0;
-
-	for (i = 0; i < STV0367TER_NBREGS; i++)
-		stv0367_writereg(state, def0367ter[i].addr,
-					def0367ter[i].value);
-
-	switch (state->config->xtal) {
-		/*set internal freq to 53.125MHz */
-	case 25000000:
-		stv0367_writereg(state, R367TER_PLLMDIV, 0xa);
-		stv0367_writereg(state, R367TER_PLLNDIV, 0x55);
-		stv0367_writereg(state, R367TER_PLLSETUP, 0x18);
-		break;
-	default:
-	case 27000000:
-		dprintk("FE_STV0367TER_SetCLKgen for 27Mhz\n");
-		stv0367_writereg(state, R367TER_PLLMDIV, 0x1);
-		stv0367_writereg(state, R367TER_PLLNDIV, 0x8);
-		stv0367_writereg(state, R367TER_PLLSETUP, 0x18);
-		break;
-	case 30000000:
-		stv0367_writereg(state, R367TER_PLLMDIV, 0xc);
-		stv0367_writereg(state, R367TER_PLLNDIV, 0x55);
-		stv0367_writereg(state, R367TER_PLLSETUP, 0x18);
-		break;
-	}
-
-	stv0367_writereg(state, R367TER_I2CRPT, 0xa0);
-	stv0367_writereg(state, R367TER_ANACTRL, 0x00);
-
-	/*Set TS1 and TS2 to serial or parallel mode */
-	stv0367ter_set_ts_mode(state, state->config->ts_mode);
-	stv0367ter_set_clk_pol(state, state->config->clk_pol);
-
-	state->chip_id = stv0367_readreg(state, R367TER_ID);
-	ter_state->first_lock = 0;
-	ter_state->unlock_counter = 2;
-
-	return 0;
-}
-
-static int stv0367ter_algo(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct stv0367_state *state = fe->demodulator_priv;
-	struct stv0367ter_state *ter_state = state->ter_state;
-	int offset = 0, tempo = 0;
-	u8 u_var;
-	u8 /*constell,*/ counter;
-	s8 step;
-	s32 timing_offset = 0;
-	u32 trl_nomrate = 0, InternalFreq = 0, temp = 0;
-
-	dprintk("%s:\n", __func__);
-
-	ter_state->frequency = p->frequency;
-	ter_state->force = FE_TER_FORCENONE
-			+ stv0367_readbits(state, F367TER_FORCE) * 2;
-	ter_state->if_iq_mode = state->config->if_iq_mode;
-	switch (state->config->if_iq_mode) {
-	case FE_TER_NORMAL_IF_TUNER:  /* Normal IF mode */
-		dprintk("ALGO: FE_TER_NORMAL_IF_TUNER selected\n");
-		stv0367_writebits(state, F367TER_TUNER_BB, 0);
-		stv0367_writebits(state, F367TER_LONGPATH_IF, 0);
-		stv0367_writebits(state, F367TER_DEMUX_SWAP, 0);
-		break;
-	case FE_TER_LONGPATH_IF_TUNER:  /* Long IF mode */
-		dprintk("ALGO: FE_TER_LONGPATH_IF_TUNER selected\n");
-		stv0367_writebits(state, F367TER_TUNER_BB, 0);
-		stv0367_writebits(state, F367TER_LONGPATH_IF, 1);
-		stv0367_writebits(state, F367TER_DEMUX_SWAP, 1);
-		break;
-	case FE_TER_IQ_TUNER:  /* IQ mode */
-		dprintk("ALGO: FE_TER_IQ_TUNER selected\n");
-		stv0367_writebits(state, F367TER_TUNER_BB, 1);
-		stv0367_writebits(state, F367TER_PPM_INVSEL, 0);
-		break;
-	default:
-		printk(KERN_ERR "ALGO: wrong TUNER type selected\n");
-		return -EINVAL;
-	}
-
-	usleep_range(5000, 7000);
-
-	switch (p->inversion) {
-	case INVERSION_AUTO:
-	default:
-		dprintk("%s: inversion AUTO\n", __func__);
-		if (ter_state->if_iq_mode == FE_TER_IQ_TUNER)
-			stv0367_writebits(state, F367TER_IQ_INVERT,
-						ter_state->sense);
-		else
-			stv0367_writebits(state, F367TER_INV_SPECTR,
-						ter_state->sense);
-
-		break;
-	case INVERSION_ON:
-	case INVERSION_OFF:
-		if (ter_state->if_iq_mode == FE_TER_IQ_TUNER)
-			stv0367_writebits(state, F367TER_IQ_INVERT,
-						p->inversion);
-		else
-			stv0367_writebits(state, F367TER_INV_SPECTR,
-						p->inversion);
-
-		break;
-	}
-
-	if ((ter_state->if_iq_mode != FE_TER_NORMAL_IF_TUNER) &&
-				(ter_state->pBW != ter_state->bw)) {
-		stv0367ter_agc_iir_lock_detect_set(state);
-
-		/*set fine agc target to 180 for LPIF or IQ mode*/
-		/* set Q_AGCTarget */
-		stv0367_writebits(state, F367TER_SEL_IQNTAR, 1);
-		stv0367_writebits(state, F367TER_AUT_AGC_TARGET_MSB, 0xB);
-		/*stv0367_writebits(state,AUT_AGC_TARGET_LSB,0x04); */
-
-		/* set Q_AGCTarget */
-		stv0367_writebits(state, F367TER_SEL_IQNTAR, 0);
-		stv0367_writebits(state, F367TER_AUT_AGC_TARGET_MSB, 0xB);
-		/*stv0367_writebits(state,AUT_AGC_TARGET_LSB,0x04); */
-
-		if (!stv0367_iir_filt_init(state, ter_state->bw,
-						state->config->xtal))
-			return -EINVAL;
-		/*set IIR filter once for 6,7 or 8MHz BW*/
-		ter_state->pBW = ter_state->bw;
-
-		stv0367ter_agc_iir_rst(state);
-	}
-
-	if (ter_state->hierarchy == FE_TER_HIER_LOW_PRIO)
-		stv0367_writebits(state, F367TER_BDI_LPSEL, 0x01);
-	else
-		stv0367_writebits(state, F367TER_BDI_LPSEL, 0x00);
-
-	InternalFreq = stv0367ter_get_mclk(state, state->config->xtal) / 1000;
-	temp = (int)
-		((((ter_state->bw * 64 * (1 << 15) * 100)
-						/ (InternalFreq)) * 10) / 7);
-
-	stv0367_writebits(state, F367TER_TRL_NOMRATE_LSB, temp % 2);
-	temp = temp / 2;
-	stv0367_writebits(state, F367TER_TRL_NOMRATE_HI, temp / 256);
-	stv0367_writebits(state, F367TER_TRL_NOMRATE_LO, temp % 256);
-
-	temp = stv0367_readbits(state, F367TER_TRL_NOMRATE_HI) * 512 +
-			stv0367_readbits(state, F367TER_TRL_NOMRATE_LO) * 2 +
-			stv0367_readbits(state, F367TER_TRL_NOMRATE_LSB);
-	temp = (int)(((1 << 17) * ter_state->bw * 1000) / (7 * (InternalFreq)));
-	stv0367_writebits(state, F367TER_GAIN_SRC_HI, temp / 256);
-	stv0367_writebits(state, F367TER_GAIN_SRC_LO, temp % 256);
-	temp = stv0367_readbits(state, F367TER_GAIN_SRC_HI) * 256 +
-			stv0367_readbits(state, F367TER_GAIN_SRC_LO);
-
-	temp = (int)
-		((InternalFreq - state->config->if_khz) * (1 << 16)
-							/ (InternalFreq));
-
-	dprintk("DEROT temp=0x%x\n", temp);
-	stv0367_writebits(state, F367TER_INC_DEROT_HI, temp / 256);
-	stv0367_writebits(state, F367TER_INC_DEROT_LO, temp % 256);
-
-	ter_state->echo_pos = 0;
-	ter_state->ucblocks = 0; /* liplianin */
-	ter_state->pBER = 0; /* liplianin */
-	stv0367_writebits(state, F367TER_LONG_ECHO, ter_state->echo_pos);
-
-	if (stv0367ter_lock_algo(state) != FE_TER_LOCKOK)
-		return 0;
-
-	ter_state->state = FE_TER_LOCKOK;
-
-	ter_state->mode = stv0367_readbits(state, F367TER_SYR_MODE);
-	ter_state->guard = stv0367_readbits(state, F367TER_SYR_GUARD);
-
-	ter_state->first_lock = 1; /* we know sense now :) */
-
-	ter_state->agc_val =
-			(stv0367_readbits(state, F367TER_AGC1_VAL_LO) << 16) +
-			(stv0367_readbits(state, F367TER_AGC1_VAL_HI) << 24) +
-			stv0367_readbits(state, F367TER_AGC2_VAL_LO) +
-			(stv0367_readbits(state, F367TER_AGC2_VAL_HI) << 8);
-
-	/* Carrier offset calculation */
-	stv0367_writebits(state, F367TER_FREEZE, 1);
-	offset = (stv0367_readbits(state, F367TER_CRL_FOFFSET_VHI) << 16) ;
-	offset += (stv0367_readbits(state, F367TER_CRL_FOFFSET_HI) << 8);
-	offset += (stv0367_readbits(state, F367TER_CRL_FOFFSET_LO));
-	stv0367_writebits(state, F367TER_FREEZE, 0);
-	if (offset > 8388607)
-		offset -= 16777216;
-
-	offset = offset * 2 / 16384;
-
-	if (ter_state->mode == FE_TER_MODE_2K)
-		offset = (offset * 4464) / 1000;/*** 1 FFT BIN=4.464khz***/
-	else if (ter_state->mode == FE_TER_MODE_4K)
-		offset = (offset * 223) / 100;/*** 1 FFT BIN=2.23khz***/
-	else  if (ter_state->mode == FE_TER_MODE_8K)
-		offset = (offset * 111) / 100;/*** 1 FFT BIN=1.1khz***/
-
-	if (stv0367_readbits(state, F367TER_PPM_INVSEL) == 1) {
-		if ((stv0367_readbits(state, F367TER_INV_SPECTR) ==
-				(stv0367_readbits(state,
-					F367TER_STATUS_INV_SPECRUM) == 1)))
-			offset = offset * -1;
-	}
-
-	if (ter_state->bw == 6)
-		offset = (offset * 6) / 8;
-	else if (ter_state->bw == 7)
-		offset = (offset * 7) / 8;
-
-	ter_state->frequency += offset;
-
-	tempo = 10;  /* exit even if timing_offset stays null */
-	while ((timing_offset == 0) && (tempo > 0)) {
-		usleep_range(10000, 20000);	/*was 20ms  */
-		/* fine tuning of timing offset if required */
-		timing_offset = stv0367_readbits(state, F367TER_TRL_TOFFSET_LO)
-				+ 256 * stv0367_readbits(state,
-							F367TER_TRL_TOFFSET_HI);
-		if (timing_offset >= 32768)
-			timing_offset -= 65536;
-		trl_nomrate = (512 * stv0367_readbits(state,
-							F367TER_TRL_NOMRATE_HI)
-			+ stv0367_readbits(state, F367TER_TRL_NOMRATE_LO) * 2
-			+ stv0367_readbits(state, F367TER_TRL_NOMRATE_LSB));
-
-		timing_offset = ((signed)(1000000 / trl_nomrate) *
-							timing_offset) / 2048;
-		tempo--;
-	}
-
-	if (timing_offset <= 0) {
-		timing_offset = (timing_offset - 11) / 22;
-		step = -1;
-	} else {
-		timing_offset = (timing_offset + 11) / 22;
-		step = 1;
-	}
-
-	for (counter = 0; counter < abs(timing_offset); counter++) {
-		trl_nomrate += step;
-		stv0367_writebits(state, F367TER_TRL_NOMRATE_LSB,
-						trl_nomrate % 2);
-		stv0367_writebits(state, F367TER_TRL_NOMRATE_LO,
-						trl_nomrate / 2);
-		usleep_range(1000, 2000);
-	}
-
-	usleep_range(5000, 6000);
-	/* unlocks could happen in case of trl centring big step,
-	then a core off/on restarts demod */
-	u_var = stv0367_readbits(state, F367TER_LK);
-
-	if (!u_var) {
-		stv0367_writebits(state, F367TER_CORE_ACTIVE, 0);
-		msleep(20);
-		stv0367_writebits(state, F367TER_CORE_ACTIVE, 1);
-	}
-
-	return 0;
-}
-
-static int stv0367ter_set_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct stv0367_state *state = fe->demodulator_priv;
-	struct stv0367ter_state *ter_state = state->ter_state;
-
-	/*u8 trials[2]; */
-	s8 num_trials, index;
-	u8 SenseTrials[] = { INVERSION_ON, INVERSION_OFF };
-
-	stv0367ter_init(fe);
-
-	if (fe->ops.tuner_ops.set_params) {
-		if (fe->ops.i2c_gate_ctrl)
-			fe->ops.i2c_gate_ctrl(fe, 1);
-		fe->ops.tuner_ops.set_params(fe);
-		if (fe->ops.i2c_gate_ctrl)
-			fe->ops.i2c_gate_ctrl(fe, 0);
-	}
-
-	switch (p->transmission_mode) {
-	default:
-	case TRANSMISSION_MODE_AUTO:
-	case TRANSMISSION_MODE_2K:
-		ter_state->mode = FE_TER_MODE_2K;
-		break;
-/*	case TRANSMISSION_MODE_4K:
-		pLook.mode = FE_TER_MODE_4K;
-		break;*/
-	case TRANSMISSION_MODE_8K:
-		ter_state->mode = FE_TER_MODE_8K;
-		break;
-	}
-
-	switch (p->guard_interval) {
-	default:
-	case GUARD_INTERVAL_1_32:
-	case GUARD_INTERVAL_1_16:
-	case GUARD_INTERVAL_1_8:
-	case GUARD_INTERVAL_1_4:
-		ter_state->guard = p->guard_interval;
-		break;
-	case GUARD_INTERVAL_AUTO:
-		ter_state->guard = GUARD_INTERVAL_1_32;
-		break;
-	}
-
-	switch (p->bandwidth_hz) {
-	case 6000000:
-		ter_state->bw = FE_TER_CHAN_BW_6M;
-		break;
-	case 7000000:
-		ter_state->bw = FE_TER_CHAN_BW_7M;
-		break;
-	case 8000000:
-	default:
-		ter_state->bw = FE_TER_CHAN_BW_8M;
-	}
-
-	ter_state->hierarchy = FE_TER_HIER_NONE;
-
-	switch (p->inversion) {
-	case INVERSION_OFF:
-	case INVERSION_ON:
-		num_trials = 1;
-		break;
-	default:
-		num_trials = 2;
-		if (ter_state->first_lock)
-			num_trials = 1;
-		break;
-	}
-
-	ter_state->state = FE_TER_NOLOCK;
-	index = 0;
-
-	while (((index) < num_trials) && (ter_state->state != FE_TER_LOCKOK)) {
-		if (!ter_state->first_lock) {
-			if (p->inversion == INVERSION_AUTO)
-				ter_state->sense = SenseTrials[index];
-
-		}
-		stv0367ter_algo(fe);
-
-		if ((ter_state->state == FE_TER_LOCKOK) &&
-				(p->inversion == INVERSION_AUTO) &&
-								(index == 1)) {
-			/* invert spectrum sense */
-			SenseTrials[index] = SenseTrials[0];
-			SenseTrials[(index + 1) % 2] = (SenseTrials[1] + 1) % 2;
-		}
-
-		index++;
-	}
-
-	return 0;
-}
-
-static int stv0367ter_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
-{
-	struct stv0367_state *state = fe->demodulator_priv;
-	struct stv0367ter_state *ter_state = state->ter_state;
-	u32 errs = 0;
-
-	/*wait for counting completion*/
-	if (stv0367_readbits(state, F367TER_SFERRC_OLDVALUE) == 0) {
-		errs =
-			((u32)stv0367_readbits(state, F367TER_ERR_CNT1)
-			* (1 << 16))
-			+ ((u32)stv0367_readbits(state, F367TER_ERR_CNT1_HI)
-			* (1 << 8))
-			+ ((u32)stv0367_readbits(state, F367TER_ERR_CNT1_LO));
-		ter_state->ucblocks = errs;
-	}
-
-	(*ucblocks) = ter_state->ucblocks;
-
-	return 0;
-}
-
-static int stv0367ter_get_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct stv0367_state *state = fe->demodulator_priv;
-	struct stv0367ter_state *ter_state = state->ter_state;
-
-	int error = 0;
-	enum stv0367_ter_mode mode;
-	int constell = 0,/* snr = 0,*/ Data = 0;
-
-	p->frequency = stv0367_get_tuner_freq(fe);
-	if ((int)p->frequency < 0)
-		p->frequency = -p->frequency;
-
-	constell = stv0367_readbits(state, F367TER_TPS_CONST);
-	if (constell == 0)
-		p->modulation = QPSK;
-	else if (constell == 1)
-		p->modulation = QAM_16;
-	else
-		p->modulation = QAM_64;
-
-	p->inversion = stv0367_readbits(state, F367TER_INV_SPECTR);
-
-	/* Get the Hierarchical mode */
-	Data = stv0367_readbits(state, F367TER_TPS_HIERMODE);
-
-	switch (Data) {
-	case 0:
-		p->hierarchy = HIERARCHY_NONE;
-		break;
-	case 1:
-		p->hierarchy = HIERARCHY_1;
-		break;
-	case 2:
-		p->hierarchy = HIERARCHY_2;
-		break;
-	case 3:
-		p->hierarchy = HIERARCHY_4;
-		break;
-	default:
-		p->hierarchy = HIERARCHY_AUTO;
-		break; /* error */
-	}
-
-	/* Get the FEC Rate */
-	if (ter_state->hierarchy == FE_TER_HIER_LOW_PRIO)
-		Data = stv0367_readbits(state, F367TER_TPS_LPCODE);
-	else
-		Data = stv0367_readbits(state, F367TER_TPS_HPCODE);
-
-	switch (Data) {
-	case 0:
-		p->code_rate_HP = FEC_1_2;
-		break;
-	case 1:
-		p->code_rate_HP = FEC_2_3;
-		break;
-	case 2:
-		p->code_rate_HP = FEC_3_4;
-		break;
-	case 3:
-		p->code_rate_HP = FEC_5_6;
-		break;
-	case 4:
-		p->code_rate_HP = FEC_7_8;
-		break;
-	default:
-		p->code_rate_HP = FEC_AUTO;
-		break; /* error */
-	}
-
-	mode = stv0367_readbits(state, F367TER_SYR_MODE);
-
-	switch (mode) {
-	case FE_TER_MODE_2K:
-		p->transmission_mode = TRANSMISSION_MODE_2K;
-		break;
-/*	case FE_TER_MODE_4K:
-		p->transmission_mode = TRANSMISSION_MODE_4K;
-		break;*/
-	case FE_TER_MODE_8K:
-		p->transmission_mode = TRANSMISSION_MODE_8K;
-		break;
-	default:
-		p->transmission_mode = TRANSMISSION_MODE_AUTO;
-	}
-
-	p->guard_interval = stv0367_readbits(state, F367TER_SYR_GUARD);
-
-	return error;
-}
-
-static int stv0367ter_read_snr(struct dvb_frontend *fe, u16 *snr)
-{
-	struct stv0367_state *state = fe->demodulator_priv;
-	u32 snru32 = 0;
-	int cpt = 0;
-	u8 cut = stv0367_readbits(state, F367TER_IDENTIFICATIONREG);
-
-	while (cpt < 10) {
-		usleep_range(2000, 3000);
-		if (cut == 0x50) /*cut 1.0 cut 1.1*/
-			snru32 += stv0367_readbits(state, F367TER_CHCSNR) / 4;
-		else /*cu2.0*/
-			snru32 += 125 * stv0367_readbits(state, F367TER_CHCSNR);
-
-		cpt++;
-	}
-
-	snru32 /= 10;/*average on 10 values*/
-
-	*snr = snru32 / 1000;
-
-	return 0;
-}
-
-#if 0
-static int stv0367ter_status(struct dvb_frontend *fe)
-{
-
-	struct stv0367_state *state = fe->demodulator_priv;
-	struct stv0367ter_state *ter_state = state->ter_state;
-	int locked = FALSE;
-
-	locked = (stv0367_readbits(state, F367TER_LK));
-	if (!locked)
-		ter_state->unlock_counter += 1;
-	else
-		ter_state->unlock_counter = 0;
-
-	if (ter_state->unlock_counter > 2) {
-		if (!stv0367_readbits(state, F367TER_TPS_LOCK) ||
-				(!stv0367_readbits(state, F367TER_LK))) {
-			stv0367_writebits(state, F367TER_CORE_ACTIVE, 0);
-			usleep_range(2000, 3000);
-			stv0367_writebits(state, F367TER_CORE_ACTIVE, 1);
-			msleep(350);
-			locked = (stv0367_readbits(state, F367TER_TPS_LOCK)) &&
-					(stv0367_readbits(state, F367TER_LK));
-		}
-
-	}
-
-	return locked;
-}
-#endif
-static int stv0367ter_read_status(struct dvb_frontend *fe, fe_status_t *status)
-{
-	struct stv0367_state *state = fe->demodulator_priv;
-
-	dprintk("%s:\n", __func__);
-
-	*status = 0;
-
-	if (stv0367_readbits(state, F367TER_LK)) {
-		*status |= FE_HAS_LOCK;
-		dprintk("%s: stv0367 has locked\n", __func__);
-	}
-
-	return 0;
-}
-
-static int stv0367ter_read_ber(struct dvb_frontend *fe, u32 *ber)
-{
-	struct stv0367_state *state = fe->demodulator_priv;
-	struct stv0367ter_state *ter_state = state->ter_state;
-	u32 Errors = 0, tber = 0, temporary = 0;
-	int abc = 0, def = 0;
-
-
-	/*wait for counting completion*/
-	if (stv0367_readbits(state, F367TER_SFERRC_OLDVALUE) == 0)
-		Errors = ((u32)stv0367_readbits(state, F367TER_SFEC_ERR_CNT)
-			* (1 << 16))
-			+ ((u32)stv0367_readbits(state, F367TER_SFEC_ERR_CNT_HI)
-			* (1 << 8))
-			+ ((u32)stv0367_readbits(state,
-						F367TER_SFEC_ERR_CNT_LO));
-	/*measurement not completed, load previous value*/
-	else {
-		tber = ter_state->pBER;
-		return 0;
-	}
-
-	abc = stv0367_readbits(state, F367TER_SFEC_ERR_SOURCE);
-	def = stv0367_readbits(state, F367TER_SFEC_NUM_EVENT);
-
-	if (Errors == 0) {
-		tber = 0;
-	} else if (abc == 0x7) {
-		if (Errors <= 4) {
-			temporary = (Errors * 1000000000) / (8 * (1 << 14));
-			temporary =  temporary;
-		} else if (Errors <= 42) {
-			temporary = (Errors * 100000000) / (8 * (1 << 14));
-			temporary = temporary * 10;
-		} else if (Errors <= 429) {
-			temporary = (Errors * 10000000) / (8 * (1 << 14));
-			temporary = temporary * 100;
-		} else if (Errors <= 4294) {
-			temporary = (Errors * 1000000) / (8 * (1 << 14));
-			temporary = temporary * 1000;
-		} else if (Errors <= 42949) {
-			temporary = (Errors * 100000) / (8 * (1 << 14));
-			temporary = temporary * 10000;
-		} else if (Errors <= 429496) {
-			temporary = (Errors * 10000) / (8 * (1 << 14));
-			temporary = temporary * 100000;
-		} else { /*if (Errors<4294967) 2^22 max error*/
-			temporary = (Errors * 1000) / (8 * (1 << 14));
-			temporary = temporary * 100000;	/* still to *10 */
-		}
-
-		/* Byte error*/
-		if (def == 2)
-			/*tber=Errors/(8*(1 <<14));*/
-			tber = temporary;
-		else if (def == 3)
-			/*tber=Errors/(8*(1 <<16));*/
-			tber = temporary / 4;
-		else if (def == 4)
-			/*tber=Errors/(8*(1 <<18));*/
-			tber = temporary / 16;
-		else if (def == 5)
-			/*tber=Errors/(8*(1 <<20));*/
-			tber = temporary / 64;
-		else if (def == 6)
-			/*tber=Errors/(8*(1 <<22));*/
-			tber = temporary / 256;
-		else
-			/* should not pass here*/
-			tber = 0;
-
-		if ((Errors < 4294967) && (Errors > 429496))
-			tber *= 10;
-
-	}
-
-	/* save actual value */
-	ter_state->pBER = tber;
-
-	(*ber) = tber;
-
-	return 0;
-}
-#if 0
-static u32 stv0367ter_get_per(struct stv0367_state *state)
-{
-	struct stv0367ter_state *ter_state = state->ter_state;
-	u32 Errors = 0, Per = 0, temporary = 0;
-	int abc = 0, def = 0, cpt = 0;
-
-	while (((stv0367_readbits(state, F367TER_SFERRC_OLDVALUE) == 1) &&
-			(cpt < 400)) || ((Errors == 0) && (cpt < 400))) {
-		usleep_range(1000, 2000);
-		Errors = ((u32)stv0367_readbits(state, F367TER_ERR_CNT1)
-			* (1 << 16))
-			+ ((u32)stv0367_readbits(state, F367TER_ERR_CNT1_HI)
-			* (1 << 8))
-			+ ((u32)stv0367_readbits(state, F367TER_ERR_CNT1_LO));
-		cpt++;
-	}
-	abc = stv0367_readbits(state, F367TER_ERR_SRC1);
-	def = stv0367_readbits(state, F367TER_NUM_EVT1);
-
-	if (Errors == 0)
-		Per = 0;
-	else if (abc == 0x9) {
-		if (Errors <= 4) {
-			temporary = (Errors * 1000000000) / (8 * (1 << 8));
-			temporary =  temporary;
-		} else if (Errors <= 42) {
-			temporary = (Errors * 100000000) / (8 * (1 << 8));
-			temporary = temporary * 10;
-		} else if (Errors <= 429) {
-			temporary = (Errors * 10000000) / (8 * (1 << 8));
-			temporary = temporary * 100;
-		} else if (Errors <= 4294) {
-			temporary = (Errors * 1000000) / (8 * (1 << 8));
-			temporary = temporary * 1000;
-		} else if (Errors <= 42949) {
-			temporary = (Errors * 100000) / (8 * (1 << 8));
-			temporary = temporary * 10000;
-		} else { /*if(Errors<=429496)  2^16 errors max*/
-			temporary = (Errors * 10000) / (8 * (1 << 8));
-			temporary = temporary * 100000;
-		}
-
-		/* pkt error*/
-		if (def == 2)
-			/*Per=Errors/(1 << 8);*/
-			Per = temporary;
-		else if (def == 3)
-			/*Per=Errors/(1 << 10);*/
-			Per = temporary / 4;
-		else if (def == 4)
-			/*Per=Errors/(1 << 12);*/
-			Per = temporary / 16;
-		else if (def == 5)
-			/*Per=Errors/(1 << 14);*/
-			Per = temporary / 64;
-		else if (def == 6)
-			/*Per=Errors/(1 << 16);*/
-			Per = temporary / 256;
-		else
-			Per = 0;
-
-	}
-	/* save actual value */
-	ter_state->pPER = Per;
-
-	return Per;
-}
-#endif
-static int stv0367_get_tune_settings(struct dvb_frontend *fe,
-					struct dvb_frontend_tune_settings
-					*fe_tune_settings)
-{
-	fe_tune_settings->min_delay_ms = 1000;
-	fe_tune_settings->step_size = 0;
-	fe_tune_settings->max_drift = 0;
-
-	return 0;
-}
-
-static void stv0367_release(struct dvb_frontend *fe)
-{
-	struct stv0367_state *state = fe->demodulator_priv;
-
-	kfree(state->ter_state);
-	kfree(state->cab_state);
-	kfree(state);
-}
-
-static struct dvb_frontend_ops stv0367ter_ops = {
-	.delsys = { SYS_DVBT },
-	.info = {
-		.name			= "ST STV0367 DVB-T",
-		.frequency_min		= 47000000,
-		.frequency_max		= 862000000,
-		.frequency_stepsize	= 15625,
-		.frequency_tolerance	= 0,
-		.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_FEC_AUTO |
-			FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 |
-			FE_CAN_QAM_128 | FE_CAN_QAM_256 | FE_CAN_QAM_AUTO |
-			FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_RECOVER |
-			FE_CAN_INVERSION_AUTO |
-			FE_CAN_MUTE_TS
-	},
-	.release = stv0367_release,
-	.init = stv0367ter_init,
-	.sleep = stv0367ter_sleep,
-	.i2c_gate_ctrl = stv0367ter_gate_ctrl,
-	.set_frontend = stv0367ter_set_frontend,
-	.get_frontend = stv0367ter_get_frontend,
-	.get_tune_settings = stv0367_get_tune_settings,
-	.read_status = stv0367ter_read_status,
-	.read_ber = stv0367ter_read_ber,/* too slow */
-/*	.read_signal_strength = stv0367_read_signal_strength,*/
-	.read_snr = stv0367ter_read_snr,
-	.read_ucblocks = stv0367ter_read_ucblocks,
-};
-
-struct dvb_frontend *stv0367ter_attach(const struct stv0367_config *config,
-				   struct i2c_adapter *i2c)
-{
-	struct stv0367_state *state = NULL;
-	struct stv0367ter_state *ter_state = NULL;
-
-	/* allocate memory for the internal state */
-	state = kzalloc(sizeof(struct stv0367_state), GFP_KERNEL);
-	if (state == NULL)
-		goto error;
-	ter_state = kzalloc(sizeof(struct stv0367ter_state), GFP_KERNEL);
-	if (ter_state == NULL)
-		goto error;
-
-	/* setup the state */
-	state->i2c = i2c;
-	state->config = config;
-	state->ter_state = ter_state;
-	state->fe.ops = stv0367ter_ops;
-	state->fe.demodulator_priv = state;
-	state->chip_id = stv0367_readreg(state, 0xf000);
-
-	dprintk("%s: chip_id = 0x%x\n", __func__, state->chip_id);
-
-	/* check if the demod is there */
-	if ((state->chip_id != 0x50) && (state->chip_id != 0x60))
-		goto error;
-
-	return &state->fe;
-
-error:
-	kfree(ter_state);
-	kfree(state);
-	return NULL;
-}
-EXPORT_SYMBOL(stv0367ter_attach);
-
-static int stv0367cab_gate_ctrl(struct dvb_frontend *fe, int enable)
-{
-	struct stv0367_state *state = fe->demodulator_priv;
-
-	dprintk("%s:\n", __func__);
-
-	stv0367_writebits(state, F367CAB_I2CT_ON, (enable > 0) ? 1 : 0);
-
-	return 0;
-}
-
-static u32 stv0367cab_get_mclk(struct dvb_frontend *fe, u32 ExtClk_Hz)
-{
-	struct stv0367_state *state = fe->demodulator_priv;
-	u32 mclk_Hz = 0;/* master clock frequency (Hz) */
-	u32 M, N, P;
-
-
-	if (stv0367_readbits(state, F367CAB_BYPASS_PLLXN) == 0) {
-		N = (u32)stv0367_readbits(state, F367CAB_PLL_NDIV);
-		if (N == 0)
-			N = N + 1;
-
-		M = (u32)stv0367_readbits(state, F367CAB_PLL_MDIV);
-		if (M == 0)
-			M = M + 1;
-
-		P = (u32)stv0367_readbits(state, F367CAB_PLL_PDIV);
-
-		if (P > 5)
-			P = 5;
-
-		mclk_Hz = ((ExtClk_Hz / 2) * N) / (M * (1 << P));
-		dprintk("stv0367cab_get_mclk BYPASS_PLLXN mclk_Hz=%d\n",
-								mclk_Hz);
-	} else
-		mclk_Hz = ExtClk_Hz;
-
-	dprintk("stv0367cab_get_mclk final mclk_Hz=%d\n", mclk_Hz);
-
-	return mclk_Hz;
-}
-
-static u32 stv0367cab_get_adc_freq(struct dvb_frontend *fe, u32 ExtClk_Hz)
-{
-	u32 ADCClk_Hz = ExtClk_Hz;
-
-	ADCClk_Hz = stv0367cab_get_mclk(fe, ExtClk_Hz);
-
-	return ADCClk_Hz;
-}
-
-enum stv0367cab_mod stv0367cab_SetQamSize(struct stv0367_state *state,
-					u32 SymbolRate,
-					enum stv0367cab_mod QAMSize)
-{
-	/* Set QAM size */
-	stv0367_writebits(state, F367CAB_QAM_MODE, QAMSize);
-
-	/* Set Registers settings specific to the QAM size */
-	switch (QAMSize) {
-	case FE_CAB_MOD_QAM4:
-		stv0367_writereg(state, R367CAB_IQDEM_ADJ_AGC_REF, 0x00);
-		break;
-	case FE_CAB_MOD_QAM16:
-		stv0367_writereg(state, R367CAB_AGC_PWR_REF_L, 0x64);
-		stv0367_writereg(state, R367CAB_IQDEM_ADJ_AGC_REF, 0x00);
-		stv0367_writereg(state, R367CAB_FSM_STATE, 0x90);
-		stv0367_writereg(state, R367CAB_EQU_CTR_LPF_GAIN, 0xc1);
-		stv0367_writereg(state, R367CAB_EQU_CRL_LPF_GAIN, 0xa7);
-		stv0367_writereg(state, R367CAB_EQU_CRL_LD_SEN, 0x95);
-		stv0367_writereg(state, R367CAB_EQU_CRL_LIMITER, 0x40);
-		stv0367_writereg(state, R367CAB_EQU_PNT_GAIN, 0x8a);
-		break;
-	case FE_CAB_MOD_QAM32:
-		stv0367_writereg(state, R367CAB_IQDEM_ADJ_AGC_REF, 0x00);
-		stv0367_writereg(state, R367CAB_AGC_PWR_REF_L, 0x6e);
-		stv0367_writereg(state, R367CAB_FSM_STATE, 0xb0);
-		stv0367_writereg(state, R367CAB_EQU_CTR_LPF_GAIN, 0xc1);
-		stv0367_writereg(state, R367CAB_EQU_CRL_LPF_GAIN, 0xb7);
-		stv0367_writereg(state, R367CAB_EQU_CRL_LD_SEN, 0x9d);
-		stv0367_writereg(state, R367CAB_EQU_CRL_LIMITER, 0x7f);
-		stv0367_writereg(state, R367CAB_EQU_PNT_GAIN, 0xa7);
-		break;
-	case FE_CAB_MOD_QAM64:
-		stv0367_writereg(state, R367CAB_IQDEM_ADJ_AGC_REF, 0x82);
-		stv0367_writereg(state, R367CAB_AGC_PWR_REF_L, 0x5a);
-		if (SymbolRate > 45000000) {
-			stv0367_writereg(state, R367CAB_FSM_STATE, 0xb0);
-			stv0367_writereg(state, R367CAB_EQU_CTR_LPF_GAIN, 0xc1);
-			stv0367_writereg(state, R367CAB_EQU_CRL_LPF_GAIN, 0xa5);
-		} else if (SymbolRate > 25000000) {
-			stv0367_writereg(state, R367CAB_FSM_STATE, 0xa0);
-			stv0367_writereg(state, R367CAB_EQU_CTR_LPF_GAIN, 0xc1);
-			stv0367_writereg(state, R367CAB_EQU_CRL_LPF_GAIN, 0xa6);
-		} else {
-			stv0367_writereg(state, R367CAB_FSM_STATE, 0xa0);
-			stv0367_writereg(state, R367CAB_EQU_CTR_LPF_GAIN, 0xd1);
-			stv0367_writereg(state, R367CAB_EQU_CRL_LPF_GAIN, 0xa7);
-		}
-		stv0367_writereg(state, R367CAB_EQU_CRL_LD_SEN, 0x95);
-		stv0367_writereg(state, R367CAB_EQU_CRL_LIMITER, 0x40);
-		stv0367_writereg(state, R367CAB_EQU_PNT_GAIN, 0x99);
-		break;
-	case FE_CAB_MOD_QAM128:
-		stv0367_writereg(state, R367CAB_IQDEM_ADJ_AGC_REF, 0x00);
-		stv0367_writereg(state, R367CAB_AGC_PWR_REF_L, 0x76);
-		stv0367_writereg(state, R367CAB_FSM_STATE, 0x90);
-		stv0367_writereg(state, R367CAB_EQU_CTR_LPF_GAIN, 0xb1);
-		if (SymbolRate > 45000000)
-			stv0367_writereg(state, R367CAB_EQU_CRL_LPF_GAIN, 0xa7);
-		else if (SymbolRate > 25000000)
-			stv0367_writereg(state, R367CAB_EQU_CRL_LPF_GAIN, 0xa6);
-		else
-			stv0367_writereg(state, R367CAB_EQU_CRL_LPF_GAIN, 0x97);
-
-		stv0367_writereg(state, R367CAB_EQU_CRL_LD_SEN, 0x8e);
-		stv0367_writereg(state, R367CAB_EQU_CRL_LIMITER, 0x7f);
-		stv0367_writereg(state, R367CAB_EQU_PNT_GAIN, 0xa7);
-		break;
-	case FE_CAB_MOD_QAM256:
-		stv0367_writereg(state, R367CAB_IQDEM_ADJ_AGC_REF, 0x94);
-		stv0367_writereg(state, R367CAB_AGC_PWR_REF_L, 0x5a);
-		stv0367_writereg(state, R367CAB_FSM_STATE, 0xa0);
-		if (SymbolRate > 45000000)
-			stv0367_writereg(state, R367CAB_EQU_CTR_LPF_GAIN, 0xc1);
-		else if (SymbolRate > 25000000)
-			stv0367_writereg(state, R367CAB_EQU_CTR_LPF_GAIN, 0xc1);
-		else
-			stv0367_writereg(state, R367CAB_EQU_CTR_LPF_GAIN, 0xd1);
-
-		stv0367_writereg(state, R367CAB_EQU_CRL_LPF_GAIN, 0xa7);
-		stv0367_writereg(state, R367CAB_EQU_CRL_LD_SEN, 0x85);
-		stv0367_writereg(state, R367CAB_EQU_CRL_LIMITER, 0x40);
-		stv0367_writereg(state, R367CAB_EQU_PNT_GAIN, 0xa7);
-		break;
-	case FE_CAB_MOD_QAM512:
-		stv0367_writereg(state, R367CAB_IQDEM_ADJ_AGC_REF, 0x00);
-		break;
-	case FE_CAB_MOD_QAM1024:
-		stv0367_writereg(state, R367CAB_IQDEM_ADJ_AGC_REF, 0x00);
-		break;
-	default:
-		break;
-	}
-
-	return QAMSize;
-}
-
-static u32 stv0367cab_set_derot_freq(struct stv0367_state *state,
-					u32 adc_hz, s32 derot_hz)
-{
-	u32 sampled_if = 0;
-	u32 adc_khz;
-
-	adc_khz = adc_hz / 1000;
-
-	dprintk("%s: adc_hz=%d derot_hz=%d\n", __func__, adc_hz, derot_hz);
-
-	if (adc_khz != 0) {
-		if (derot_hz < 1000000)
-			derot_hz = adc_hz / 4; /* ZIF operation */
-		if (derot_hz > adc_hz)
-			derot_hz = derot_hz - adc_hz;
-		sampled_if = (u32)derot_hz / 1000;
-		sampled_if *= 32768;
-		sampled_if /= adc_khz;
-		sampled_if *= 256;
-	}
-
-	if (sampled_if > 8388607)
-		sampled_if = 8388607;
-
-	dprintk("%s: sampled_if=0x%x\n", __func__, sampled_if);
-
-	stv0367_writereg(state, R367CAB_MIX_NCO_LL, sampled_if);
-	stv0367_writereg(state, R367CAB_MIX_NCO_HL, (sampled_if >> 8));
-	stv0367_writebits(state, F367CAB_MIX_NCO_INC_HH, (sampled_if >> 16));
-
-	return derot_hz;
-}
-
-static u32 stv0367cab_get_derot_freq(struct stv0367_state *state, u32 adc_hz)
-{
-	u32 sampled_if;
-
-	sampled_if = stv0367_readbits(state, F367CAB_MIX_NCO_INC_LL) +
-			(stv0367_readbits(state, F367CAB_MIX_NCO_INC_HL) << 8) +
-			(stv0367_readbits(state, F367CAB_MIX_NCO_INC_HH) << 16);
-
-	sampled_if /= 256;
-	sampled_if *= (adc_hz / 1000);
-	sampled_if += 1;
-	sampled_if /= 32768;
-
-	return sampled_if;
-}
-
-static u32 stv0367cab_set_srate(struct stv0367_state *state, u32 adc_hz,
-			u32 mclk_hz, u32 SymbolRate,
-			enum stv0367cab_mod QAMSize)
-{
-	u32 QamSizeCorr = 0;
-	u32 u32_tmp = 0, u32_tmp1 = 0;
-	u32 adp_khz;
-
-	dprintk("%s:\n", __func__);
-
-	/* Set Correction factor of SRC gain */
-	switch (QAMSize) {
-	case FE_CAB_MOD_QAM4:
-		QamSizeCorr = 1110;
-		break;
-	case FE_CAB_MOD_QAM16:
-		QamSizeCorr = 1032;
-		break;
-	case FE_CAB_MOD_QAM32:
-		QamSizeCorr =  954;
-		break;
-	case FE_CAB_MOD_QAM64:
-		QamSizeCorr =  983;
-		break;
-	case FE_CAB_MOD_QAM128:
-		QamSizeCorr =  957;
-		break;
-	case FE_CAB_MOD_QAM256:
-		QamSizeCorr =  948;
-		break;
-	case FE_CAB_MOD_QAM512:
-		QamSizeCorr =    0;
-		break;
-	case FE_CAB_MOD_QAM1024:
-		QamSizeCorr =  944;
-		break;
-	default:
-		break;
-	}
-
-	/* Transfer ratio calculation */
-	if (adc_hz != 0) {
-		u32_tmp = 256 * SymbolRate;
-		u32_tmp = u32_tmp / adc_hz;
-	}
-	stv0367_writereg(state, R367CAB_EQU_CRL_TFR, (u8)u32_tmp);
-
-	/* Symbol rate and SRC gain calculation */
-	adp_khz = (mclk_hz >> 1) / 1000;/* TRL works at half the system clock */
-	if (adp_khz != 0) {
-		u32_tmp = SymbolRate;
-		u32_tmp1 = SymbolRate;
-
-		if (u32_tmp < 2097152) { /* 2097152 = 2^21 */
-			/* Symbol rate calculation */
-			u32_tmp *= 2048; /* 2048 = 2^11 */
-			u32_tmp = u32_tmp / adp_khz;
-			u32_tmp = u32_tmp * 16384; /* 16384 = 2^14 */
-			u32_tmp /= 125 ; /* 125 = 1000/2^3 */
-			u32_tmp = u32_tmp * 8; /* 8 = 2^3 */
-
-			/* SRC Gain Calculation */
-			u32_tmp1 *= 2048; /* *2*2^10 */
-			u32_tmp1 /= 439; /* *2/878 */
-			u32_tmp1 *= 256; /* *2^8 */
-			u32_tmp1 = u32_tmp1 / adp_khz; /* /(AdpClk in kHz) */
-			u32_tmp1 *= QamSizeCorr * 9; /* *1000*corr factor */
-			u32_tmp1 = u32_tmp1 / 10000000;
-
-		} else if (u32_tmp < 4194304) { /* 4194304 = 2**22 */
-			/* Symbol rate calculation */
-			u32_tmp *= 1024 ; /* 1024 = 2**10 */
-			u32_tmp = u32_tmp / adp_khz;
-			u32_tmp = u32_tmp * 16384; /* 16384 = 2**14 */
-			u32_tmp /= 125 ; /* 125 = 1000/2**3 */
-			u32_tmp = u32_tmp * 16; /* 16 = 2**4 */
-
-			/* SRC Gain Calculation */
-			u32_tmp1 *= 1024; /* *2*2^9 */
-			u32_tmp1 /= 439; /* *2/878 */
-			u32_tmp1 *= 256; /* *2^8 */
-			u32_tmp1 = u32_tmp1 / adp_khz; /* /(AdpClk in kHz)*/
-			u32_tmp1 *= QamSizeCorr * 9; /* *1000*corr factor */
-			u32_tmp1 = u32_tmp1 / 5000000;
-		} else if (u32_tmp < 8388607) { /* 8388607 = 2**23 */
-			/* Symbol rate calculation */
-			u32_tmp *= 512 ; /* 512 = 2**9 */
-			u32_tmp = u32_tmp / adp_khz;
-			u32_tmp = u32_tmp * 16384; /* 16384 = 2**14 */
-			u32_tmp /= 125 ; /* 125 = 1000/2**3 */
-			u32_tmp = u32_tmp * 32; /* 32 = 2**5 */
-
-			/* SRC Gain Calculation */
-			u32_tmp1 *= 512; /* *2*2^8 */
-			u32_tmp1 /= 439; /* *2/878 */
-			u32_tmp1 *= 256; /* *2^8 */
-			u32_tmp1 = u32_tmp1 / adp_khz; /* /(AdpClk in kHz) */
-			u32_tmp1 *= QamSizeCorr * 9; /* *1000*corr factor */
-			u32_tmp1 = u32_tmp1 / 2500000;
-		} else {
-			/* Symbol rate calculation */
-			u32_tmp *= 256 ; /* 256 = 2**8 */
-			u32_tmp = u32_tmp / adp_khz;
-			u32_tmp = u32_tmp * 16384; /* 16384 = 2**13 */
-			u32_tmp /= 125 ; /* 125 = 1000/2**3 */
-			u32_tmp = u32_tmp * 64; /* 64 = 2**6 */
-
-			/* SRC Gain Calculation */
-			u32_tmp1 *= 256; /* 2*2^7 */
-			u32_tmp1 /= 439; /* *2/878 */
-			u32_tmp1 *= 256; /* *2^8 */
-			u32_tmp1 = u32_tmp1 / adp_khz; /* /(AdpClk in kHz) */
-			u32_tmp1 *= QamSizeCorr * 9; /* *1000*corr factor */
-			u32_tmp1 = u32_tmp1 / 1250000;
-		}
-	}
-#if 0
-	/* Filters' coefficients are calculated and written
-	into registers only if the filters are enabled */
-	if (stv0367_readbits(state, F367CAB_ADJ_EN)) {
-		stv0367cab_SetIirAdjacentcoefficient(state, mclk_hz,
-								SymbolRate);
-		/* AllPass filter must be enabled
-		when the adjacents filter is used */
-		stv0367_writebits(state, F367CAB_ALLPASSFILT_EN, 1);
-		stv0367cab_SetAllPasscoefficient(state, mclk_hz, SymbolRate);
-	} else
-		/* AllPass filter must be disabled
-		when the adjacents filter is not used */
-#endif
-	stv0367_writebits(state, F367CAB_ALLPASSFILT_EN, 0);
-
-	stv0367_writereg(state, R367CAB_SRC_NCO_LL, u32_tmp);
-	stv0367_writereg(state, R367CAB_SRC_NCO_LH, (u32_tmp >> 8));
-	stv0367_writereg(state, R367CAB_SRC_NCO_HL, (u32_tmp >> 16));
-	stv0367_writereg(state, R367CAB_SRC_NCO_HH, (u32_tmp >> 24));
-
-	stv0367_writereg(state, R367CAB_IQDEM_GAIN_SRC_L, u32_tmp1 & 0x00ff);
-	stv0367_writebits(state, F367CAB_GAIN_SRC_HI, (u32_tmp1 >> 8) & 0x00ff);
-
-	return SymbolRate ;
-}
-
-static u32 stv0367cab_GetSymbolRate(struct stv0367_state *state, u32 mclk_hz)
-{
-	u32 regsym;
-	u32 adp_khz;
-
-	regsym = stv0367_readreg(state, R367CAB_SRC_NCO_LL) +
-		(stv0367_readreg(state, R367CAB_SRC_NCO_LH) << 8) +
-		(stv0367_readreg(state, R367CAB_SRC_NCO_HL) << 16) +
-		(stv0367_readreg(state, R367CAB_SRC_NCO_HH) << 24);
-
-	adp_khz = (mclk_hz >> 1) / 1000;/* TRL works at half the system clock */
-
-	if (regsym < 134217728) {		/* 134217728L = 2**27*/
-		regsym = regsym * 32;		/* 32 = 2**5 */
-		regsym = regsym / 32768;	/* 32768L = 2**15 */
-		regsym = adp_khz * regsym;	/* AdpClk in kHz */
-		regsym = regsym / 128;		/* 128 = 2**7 */
-		regsym *= 125 ;			/* 125 = 1000/2**3 */
-		regsym /= 2048 ;		/* 2048 = 2**11	*/
-	} else if (regsym < 268435456) {	/* 268435456L = 2**28 */
-		regsym = regsym * 16;		/* 16 = 2**4 */
-		regsym = regsym / 32768;	/* 32768L = 2**15 */
-		regsym = adp_khz * regsym;	/* AdpClk in kHz */
-		regsym = regsym / 128;		/* 128 = 2**7 */
-		regsym *= 125 ;			/* 125 = 1000/2**3*/
-		regsym /= 1024 ;		/* 256 = 2**10*/
-	} else if (regsym < 536870912) {	/* 536870912L = 2**29*/
-		regsym = regsym * 8;		/* 8 = 2**3 */
-		regsym = regsym / 32768;	/* 32768L = 2**15 */
-		regsym = adp_khz * regsym;	/* AdpClk in kHz */
-		regsym = regsym / 128;		/* 128 = 2**7 */
-		regsym *= 125 ;			/* 125 = 1000/2**3 */
-		regsym /= 512 ;			/* 128 = 2**9 */
-	} else {
-		regsym = regsym * 4;		/* 4 = 2**2 */
-		regsym = regsym / 32768;	/* 32768L = 2**15 */
-		regsym = adp_khz * regsym;	/* AdpClk in kHz */
-		regsym = regsym / 128;		/* 128 = 2**7 */
-		regsym *= 125 ;			/* 125 = 1000/2**3 */
-		regsym /= 256 ;			/* 64 = 2**8 */
-	}
-
-	return regsym;
-}
-
-static int stv0367cab_read_status(struct dvb_frontend *fe, fe_status_t *status)
-{
-	struct stv0367_state *state = fe->demodulator_priv;
-
-	dprintk("%s:\n", __func__);
-
-	*status = 0;
-
-	if (stv0367_readbits(state, F367CAB_QAMFEC_LOCK)) {
-		*status |= FE_HAS_LOCK;
-		dprintk("%s: stv0367 has locked\n", __func__);
-	}
-
-	return 0;
-}
-
-static int stv0367cab_standby(struct dvb_frontend *fe, u8 standby_on)
-{
-	struct stv0367_state *state = fe->demodulator_priv;
-
-	dprintk("%s:\n", __func__);
-
-	if (standby_on) {
-		stv0367_writebits(state, F367CAB_BYPASS_PLLXN, 0x03);
-		stv0367_writebits(state, F367CAB_STDBY_PLLXN, 0x01);
-		stv0367_writebits(state, F367CAB_STDBY, 1);
-		stv0367_writebits(state, F367CAB_STDBY_CORE, 1);
-		stv0367_writebits(state, F367CAB_EN_BUFFER_I, 0);
-		stv0367_writebits(state, F367CAB_EN_BUFFER_Q, 0);
-		stv0367_writebits(state, F367CAB_POFFQ, 1);
-		stv0367_writebits(state, F367CAB_POFFI, 1);
-	} else {
-		stv0367_writebits(state, F367CAB_STDBY_PLLXN, 0x00);
-		stv0367_writebits(state, F367CAB_BYPASS_PLLXN, 0x00);
-		stv0367_writebits(state, F367CAB_STDBY, 0);
-		stv0367_writebits(state, F367CAB_STDBY_CORE, 0);
-		stv0367_writebits(state, F367CAB_EN_BUFFER_I, 1);
-		stv0367_writebits(state, F367CAB_EN_BUFFER_Q, 1);
-		stv0367_writebits(state, F367CAB_POFFQ, 0);
-		stv0367_writebits(state, F367CAB_POFFI, 0);
-	}
-
-	return 0;
-}
-
-static int stv0367cab_sleep(struct dvb_frontend *fe)
-{
-	return stv0367cab_standby(fe, 1);
-}
-
-int stv0367cab_init(struct dvb_frontend *fe)
-{
-	struct stv0367_state *state = fe->demodulator_priv;
-	struct stv0367cab_state *cab_state = state->cab_state;
-	int i;
-
-	dprintk("%s:\n", __func__);
-
-	for (i = 0; i < STV0367CAB_NBREGS; i++)
-		stv0367_writereg(state, def0367cab[i].addr,
-						def0367cab[i].value);
-
-	switch (state->config->ts_mode) {
-	case STV0367_DVBCI_CLOCK:
-		dprintk("Setting TSMode = STV0367_DVBCI_CLOCK\n");
-		stv0367_writebits(state, F367CAB_OUTFORMAT, 0x03);
-		break;
-	case STV0367_SERIAL_PUNCT_CLOCK:
-	case STV0367_SERIAL_CONT_CLOCK:
-		stv0367_writebits(state, F367CAB_OUTFORMAT, 0x01);
-		break;
-	case STV0367_PARALLEL_PUNCT_CLOCK:
-	case STV0367_OUTPUTMODE_DEFAULT:
-		stv0367_writebits(state, F367CAB_OUTFORMAT, 0x00);
-		break;
-	}
-
-	switch (state->config->clk_pol) {
-	case STV0367_RISINGEDGE_CLOCK:
-		stv0367_writebits(state, F367CAB_CLK_POLARITY, 0x00);
-		break;
-	case STV0367_FALLINGEDGE_CLOCK:
-	case STV0367_CLOCKPOLARITY_DEFAULT:
-		stv0367_writebits(state, F367CAB_CLK_POLARITY, 0x01);
-		break;
-	}
-
-	stv0367_writebits(state, F367CAB_SYNC_STRIP, 0x00);
-
-	stv0367_writebits(state, F367CAB_CT_NBST, 0x01);
-
-	stv0367_writebits(state, F367CAB_TS_SWAP, 0x01);
-
-	stv0367_writebits(state, F367CAB_FIFO_BYPASS, 0x00);
-
-	stv0367_writereg(state, R367CAB_ANACTRL, 0x00);/*PLL enabled and used */
-
-	cab_state->mclk = stv0367cab_get_mclk(fe, state->config->xtal);
-	cab_state->adc_clk = stv0367cab_get_adc_freq(fe, state->config->xtal);
-
-	return 0;
-}
-static
-enum stv0367_cab_signal_type stv0367cab_algo(struct stv0367_state *state,
-					     struct dtv_frontend_properties *p)
-{
-	struct stv0367cab_state *cab_state = state->cab_state;
-	enum stv0367_cab_signal_type signalType = FE_CAB_NOAGC;
-	u32	QAMFEC_Lock, QAM_Lock, u32_tmp,
-		LockTime, TRLTimeOut, AGCTimeOut, CRLSymbols,
-		CRLTimeOut, EQLTimeOut, DemodTimeOut, FECTimeOut;
-	u8	TrackAGCAccum;
-	s32	tmp;
-
-	dprintk("%s:\n", __func__);
-
-	/* Timeouts calculation */
-	/* A max lock time of 25 ms is allowed for delayed AGC */
-	AGCTimeOut = 25;
-	/* 100000 symbols needed by the TRL as a maximum value */
-	TRLTimeOut = 100000000 / p->symbol_rate;
-	/* CRLSymbols is the needed number of symbols to achieve a lock
-	   within [-4%, +4%] of the symbol rate.
-	   CRL timeout is calculated
-	   for a lock within [-search_range, +search_range].
-	   EQL timeout can be changed depending on
-	   the micro-reflections we want to handle.
-	   A characterization must be performed
-	   with these echoes to get new timeout values.
-	*/
-	switch (p->modulation) {
-	case QAM_16:
-		CRLSymbols = 150000;
-		EQLTimeOut = 100;
-		break;
-	case QAM_32:
-		CRLSymbols = 250000;
-		EQLTimeOut = 100;
-		break;
-	case QAM_64:
-		CRLSymbols = 200000;
-		EQLTimeOut = 100;
-		break;
-	case QAM_128:
-		CRLSymbols = 250000;
-		EQLTimeOut = 100;
-		break;
-	case QAM_256:
-		CRLSymbols = 250000;
-		EQLTimeOut = 100;
-		break;
-	default:
-		CRLSymbols = 200000;
-		EQLTimeOut = 100;
-		break;
-	}
-#if 0
-	if (pIntParams->search_range < 0) {
-		CRLTimeOut = (25 * CRLSymbols *
-				(-pIntParams->search_range / 1000)) /
-					(pIntParams->symbol_rate / 1000);
-	} else
-#endif
-	CRLTimeOut = (25 * CRLSymbols * (cab_state->search_range / 1000)) /
-					(p->symbol_rate / 1000);
-
-	CRLTimeOut = (1000 * CRLTimeOut) / p->symbol_rate;
-	/* Timeouts below 50ms are coerced */
-	if (CRLTimeOut < 50)
-		CRLTimeOut = 50;
-	/* A maximum of 100 TS packets is needed to get FEC lock even in case
-	the spectrum inversion needs to be changed.
-	   This is equal to 20 ms in case of the lowest symbol rate of 0.87Msps
-	*/
-	FECTimeOut = 20;
-	DemodTimeOut = AGCTimeOut + TRLTimeOut + CRLTimeOut + EQLTimeOut;
-
-	dprintk("%s: DemodTimeOut=%d\n", __func__, DemodTimeOut);
-
-	/* Reset the TRL to ensure nothing starts until the
-	   AGC is stable which ensures a better lock time
-	*/
-	stv0367_writereg(state, R367CAB_CTRL_1, 0x04);
-	/* Set AGC accumulation time to minimum and lock threshold to maximum
-	in order to speed up the AGC lock */
-	TrackAGCAccum = stv0367_readbits(state, F367CAB_AGC_ACCUMRSTSEL);
-	stv0367_writebits(state, F367CAB_AGC_ACCUMRSTSEL, 0x0);
-	/* Modulus Mapper is disabled */
-	stv0367_writebits(state, F367CAB_MODULUSMAP_EN, 0);
-	/* Disable the sweep function */
-	stv0367_writebits(state, F367CAB_SWEEP_EN, 0);
-	/* The sweep function is never used, Sweep rate must be set to 0 */
-	/* Set the derotator frequency in Hz */
-	stv0367cab_set_derot_freq(state, cab_state->adc_clk,
-		(1000 * (s32)state->config->if_khz + cab_state->derot_offset));
-	/* Disable the Allpass Filter when the symbol rate is out of range */
-	if ((p->symbol_rate > 10800000) | (p->symbol_rate < 1800000)) {
-		stv0367_writebits(state, F367CAB_ADJ_EN, 0);
-		stv0367_writebits(state, F367CAB_ALLPASSFILT_EN, 0);
-	}
-#if 0
-	/* Check if the tuner is locked */
-	tuner_lock = stv0367cab_tuner_get_status(fe);
-	if (tuner_lock == 0)
-		return FE_367CAB_NOTUNER;
-#endif
-	/* Relase the TRL to start demodulator acquisition */
-	/* Wait for QAM lock */
-	LockTime = 0;
-	stv0367_writereg(state, R367CAB_CTRL_1, 0x00);
-	do {
-		QAM_Lock = stv0367_readbits(state, F367CAB_FSM_STATUS);
-		if ((LockTime >= (DemodTimeOut - EQLTimeOut)) &&
-							(QAM_Lock == 0x04))
-			/*
-			 * We don't wait longer, the frequency/phase offset
-			 * must be too big
-			 */
-			LockTime = DemodTimeOut;
-		else if ((LockTime >= (AGCTimeOut + TRLTimeOut)) &&
-							(QAM_Lock == 0x02))
-			/*
-			 * We don't wait longer, either there is no signal or
-			 * it is not the right symbol rate or it is an analog
-			 * carrier
-			 */
-		{
-			LockTime = DemodTimeOut;
-			u32_tmp = stv0367_readbits(state,
-						F367CAB_AGC_PWR_WORD_LO) +
-					(stv0367_readbits(state,
-						F367CAB_AGC_PWR_WORD_ME) << 8) +
-					(stv0367_readbits(state,
-						F367CAB_AGC_PWR_WORD_HI) << 16);
-			if (u32_tmp >= 131072)
-				u32_tmp = 262144 - u32_tmp;
-			u32_tmp = u32_tmp / (1 << (11 - stv0367_readbits(state,
-							F367CAB_AGC_IF_BWSEL)));
-
-			if (u32_tmp < stv0367_readbits(state,
-						F367CAB_AGC_PWRREF_LO) +
-					256 * stv0367_readbits(state,
-						F367CAB_AGC_PWRREF_HI) - 10)
-				QAM_Lock = 0x0f;
-		} else {
-			usleep_range(10000, 20000);
-			LockTime += 10;
-		}
-		dprintk("QAM_Lock=0x%x LockTime=%d\n", QAM_Lock, LockTime);
-		tmp = stv0367_readreg(state, R367CAB_IT_STATUS1);
-
-		dprintk("R367CAB_IT_STATUS1=0x%x\n", tmp);
-
-	} while (((QAM_Lock != 0x0c) && (QAM_Lock != 0x0b)) &&
-						(LockTime < DemodTimeOut));
-
-	dprintk("QAM_Lock=0x%x\n", QAM_Lock);
-
-	tmp = stv0367_readreg(state, R367CAB_IT_STATUS1);
-	dprintk("R367CAB_IT_STATUS1=0x%x\n", tmp);
-	tmp = stv0367_readreg(state, R367CAB_IT_STATUS2);
-	dprintk("R367CAB_IT_STATUS2=0x%x\n", tmp);
-
-	tmp  = stv0367cab_get_derot_freq(state, cab_state->adc_clk);
-	dprintk("stv0367cab_get_derot_freq=0x%x\n", tmp);
-
-	if ((QAM_Lock == 0x0c) || (QAM_Lock == 0x0b)) {
-		/* Wait for FEC lock */
-		LockTime = 0;
-		do {
-			usleep_range(5000, 7000);
-			LockTime += 5;
-			QAMFEC_Lock = stv0367_readbits(state,
-							F367CAB_QAMFEC_LOCK);
-		} while (!QAMFEC_Lock && (LockTime < FECTimeOut));
-	} else
-		QAMFEC_Lock = 0;
-
-	if (QAMFEC_Lock) {
-		signalType = FE_CAB_DATAOK;
-		cab_state->modulation = p->modulation;
-		cab_state->spect_inv = stv0367_readbits(state,
-							F367CAB_QUAD_INV);
-#if 0
-/* not clear for me */
-		if (state->config->if_khz != 0) {
-			if (state->config->if_khz > cab_state->adc_clk / 1000) {
-				cab_state->freq_khz =
-					FE_Cab_TunerGetFrequency(pIntParams->hTuner)
-				- stv0367cab_get_derot_freq(state, cab_state->adc_clk)
-				- cab_state->adc_clk / 1000 + state->config->if_khz;
-			} else {
-				cab_state->freq_khz =
-						FE_Cab_TunerGetFrequency(pIntParams->hTuner)
-						- stv0367cab_get_derot_freq(state, cab_state->adc_clk)
-										+ state->config->if_khz;
-			}
-		} else {
-			cab_state->freq_khz =
-				FE_Cab_TunerGetFrequency(pIntParams->hTuner) +
-				stv0367cab_get_derot_freq(state,
-							cab_state->adc_clk) -
-				cab_state->adc_clk / 4000;
-		}
-#endif
-		cab_state->symbol_rate = stv0367cab_GetSymbolRate(state,
-							cab_state->mclk);
-		cab_state->locked = 1;
-
-		/* stv0367_setbits(state, F367CAB_AGC_ACCUMRSTSEL,7);*/
-	} else {
-		switch (QAM_Lock) {
-		case 1:
-			signalType = FE_CAB_NOAGC;
-			break;
-		case 2:
-			signalType = FE_CAB_NOTIMING;
-			break;
-		case 3:
-			signalType = FE_CAB_TIMINGOK;
-			break;
-		case 4:
-			signalType = FE_CAB_NOCARRIER;
-			break;
-		case 5:
-			signalType = FE_CAB_CARRIEROK;
-			break;
-		case 7:
-			signalType = FE_CAB_NOBLIND;
-			break;
-		case 8:
-			signalType = FE_CAB_BLINDOK;
-			break;
-		case 10:
-			signalType = FE_CAB_NODEMOD;
-			break;
-		case 11:
-			signalType = FE_CAB_DEMODOK;
-			break;
-		case 12:
-			signalType = FE_CAB_DEMODOK;
-			break;
-		case 13:
-			signalType = FE_CAB_NODEMOD;
-			break;
-		case 14:
-			signalType = FE_CAB_NOBLIND;
-			break;
-		case 15:
-			signalType = FE_CAB_NOSIGNAL;
-			break;
-		default:
-			break;
-		}
-
-	}
-
-	/* Set the AGC control values to tracking values */
-	stv0367_writebits(state, F367CAB_AGC_ACCUMRSTSEL, TrackAGCAccum);
-	return signalType;
-}
-
-static int stv0367cab_set_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct stv0367_state *state = fe->demodulator_priv;
-	struct stv0367cab_state *cab_state = state->cab_state;
-	enum stv0367cab_mod QAMSize = 0;
-
-	dprintk("%s: freq = %d, srate = %d\n", __func__,
-					p->frequency, p->symbol_rate);
-
-	cab_state->derot_offset = 0;
-
-	switch (p->modulation) {
-	case QAM_16:
-		QAMSize = FE_CAB_MOD_QAM16;
-		break;
-	case QAM_32:
-		QAMSize = FE_CAB_MOD_QAM32;
-		break;
-	case QAM_64:
-		QAMSize = FE_CAB_MOD_QAM64;
-		break;
-	case QAM_128:
-		QAMSize = FE_CAB_MOD_QAM128;
-		break;
-	case QAM_256:
-		QAMSize = FE_CAB_MOD_QAM256;
-		break;
-	default:
-		break;
-	}
-
-	stv0367cab_init(fe);
-
-	/* Tuner Frequency Setting */
-	if (fe->ops.tuner_ops.set_params) {
-		if (fe->ops.i2c_gate_ctrl)
-			fe->ops.i2c_gate_ctrl(fe, 1);
-		fe->ops.tuner_ops.set_params(fe);
-		if (fe->ops.i2c_gate_ctrl)
-			fe->ops.i2c_gate_ctrl(fe, 0);
-	}
-
-	stv0367cab_SetQamSize(
-			state,
-			p->symbol_rate,
-			QAMSize);
-
-	stv0367cab_set_srate(state,
-			cab_state->adc_clk,
-			cab_state->mclk,
-			p->symbol_rate,
-			QAMSize);
-	/* Search algorithm launch, [-1.1*RangeOffset, +1.1*RangeOffset] scan */
-	cab_state->state = stv0367cab_algo(state, p);
-	return 0;
-}
-
-static int stv0367cab_get_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct stv0367_state *state = fe->demodulator_priv;
-	struct stv0367cab_state *cab_state = state->cab_state;
-
-	enum stv0367cab_mod QAMSize;
-
-	dprintk("%s:\n", __func__);
-
-	p->symbol_rate = stv0367cab_GetSymbolRate(state, cab_state->mclk);
-
-	QAMSize = stv0367_readbits(state, F367CAB_QAM_MODE);
-	switch (QAMSize) {
-	case FE_CAB_MOD_QAM16:
-		p->modulation = QAM_16;
-		break;
-	case FE_CAB_MOD_QAM32:
-		p->modulation = QAM_32;
-		break;
-	case FE_CAB_MOD_QAM64:
-		p->modulation = QAM_64;
-		break;
-	case FE_CAB_MOD_QAM128:
-		p->modulation = QAM_128;
-		break;
-	case QAM_256:
-		p->modulation = QAM_256;
-		break;
-	default:
-		break;
-	}
-
-	p->frequency = stv0367_get_tuner_freq(fe);
-
-	dprintk("%s: tuner frequency = %d\n", __func__, p->frequency);
-
-	if (state->config->if_khz == 0) {
-		p->frequency +=
-			(stv0367cab_get_derot_freq(state, cab_state->adc_clk) -
-			cab_state->adc_clk / 4000);
-		return 0;
-	}
-
-	if (state->config->if_khz > cab_state->adc_clk / 1000)
-		p->frequency += (state->config->if_khz
-			- stv0367cab_get_derot_freq(state, cab_state->adc_clk)
-			- cab_state->adc_clk / 1000);
-	else
-		p->frequency += (state->config->if_khz
-			- stv0367cab_get_derot_freq(state, cab_state->adc_clk));
-
-	return 0;
-}
-
-#if 0
-void stv0367cab_GetErrorCount(state, enum stv0367cab_mod QAMSize,
-			u32 symbol_rate, FE_367qam_Monitor *Monitor_results)
-{
-	stv0367cab_OptimiseNByteAndGetBER(state, QAMSize, symbol_rate, Monitor_results);
-	stv0367cab_GetPacketsCount(state, Monitor_results);
-
-	return;
-}
-
-static int stv0367cab_read_ber(struct dvb_frontend *fe, u32 *ber)
-{
-	struct stv0367_state *state = fe->demodulator_priv;
-
-	return 0;
-}
-#endif
-static s32 stv0367cab_get_rf_lvl(struct stv0367_state *state)
-{
-	s32 rfLevel = 0;
-	s32 RfAgcPwm = 0, IfAgcPwm = 0;
-	u8 i;
-
-	stv0367_writebits(state, F367CAB_STDBY_ADCGP, 0x0);
-
-	RfAgcPwm =
-		(stv0367_readbits(state, F367CAB_RF_AGC1_LEVEL_LO) & 0x03) +
-		(stv0367_readbits(state, F367CAB_RF_AGC1_LEVEL_HI) << 2);
-	RfAgcPwm = 100 * RfAgcPwm / 1023;
-
-	IfAgcPwm =
-		stv0367_readbits(state, F367CAB_AGC_IF_PWMCMD_LO) +
-		(stv0367_readbits(state, F367CAB_AGC_IF_PWMCMD_HI) << 8);
-	if (IfAgcPwm >= 2048)
-		IfAgcPwm -= 2048;
-	else
-		IfAgcPwm += 2048;
-
-	IfAgcPwm = 100 * IfAgcPwm / 4095;
-
-	/* For DTT75467 on NIM */
-	if (RfAgcPwm < 90  && IfAgcPwm < 28) {
-		for (i = 0; i < RF_LOOKUP_TABLE_SIZE; i++) {
-			if (RfAgcPwm <= stv0367cab_RF_LookUp1[0][i]) {
-				rfLevel = (-1) * stv0367cab_RF_LookUp1[1][i];
-				break;
-			}
-		}
-		if (i == RF_LOOKUP_TABLE_SIZE)
-			rfLevel = -56;
-	} else { /*if IF AGC>10*/
-		for (i = 0; i < RF_LOOKUP_TABLE2_SIZE; i++) {
-			if (IfAgcPwm <= stv0367cab_RF_LookUp2[0][i]) {
-				rfLevel = (-1) * stv0367cab_RF_LookUp2[1][i];
-				break;
-			}
-		}
-		if (i == RF_LOOKUP_TABLE2_SIZE)
-			rfLevel = -72;
-	}
-	return rfLevel;
-}
-
-static int stv0367cab_read_strength(struct dvb_frontend *fe, u16 *strength)
-{
-	struct stv0367_state *state = fe->demodulator_priv;
-
-	s32 signal =  stv0367cab_get_rf_lvl(state);
-
-	dprintk("%s: signal=%d dBm\n", __func__, signal);
-
-	if (signal <= -72)
-		*strength = 65535;
-	else
-		*strength = (22 + signal) * (-1311);
-
-	dprintk("%s: strength=%d\n", __func__, (*strength));
-
-	return 0;
-}
-
-static int stv0367cab_read_snr(struct dvb_frontend *fe, u16 *snr)
-{
-	struct stv0367_state *state = fe->demodulator_priv;
-	u32 noisepercentage;
-	enum stv0367cab_mod QAMSize;
-	u32 regval = 0, temp = 0;
-	int power, i;
-
-	QAMSize = stv0367_readbits(state, F367CAB_QAM_MODE);
-	switch (QAMSize) {
-	case FE_CAB_MOD_QAM4:
-		power = 21904;
-		break;
-	case FE_CAB_MOD_QAM16:
-		power = 20480;
-		break;
-	case FE_CAB_MOD_QAM32:
-		power = 23040;
-		break;
-	case FE_CAB_MOD_QAM64:
-		power = 21504;
-		break;
-	case FE_CAB_MOD_QAM128:
-		power = 23616;
-		break;
-	case FE_CAB_MOD_QAM256:
-		power = 21760;
-		break;
-	case FE_CAB_MOD_QAM512:
-		power = 1;
-		break;
-	case FE_CAB_MOD_QAM1024:
-		power = 21280;
-		break;
-	default:
-		power = 1;
-		break;
-	}
-
-	for (i = 0; i < 10; i++) {
-		regval += (stv0367_readbits(state, F367CAB_SNR_LO)
-			+ 256 * stv0367_readbits(state, F367CAB_SNR_HI));
-	}
-
-	regval /= 10; /*for average over 10 times in for loop above*/
-	if (regval != 0) {
-		temp = power
-			* (1 << (3 + stv0367_readbits(state, F367CAB_SNR_PER)));
-		temp /= regval;
-	}
-
-	/* table values, not needed to calculate logarithms */
-	if (temp >= 5012)
-		noisepercentage = 100;
-	else if (temp >= 3981)
-		noisepercentage = 93;
-	else if (temp >= 3162)
-		noisepercentage = 86;
-	else if (temp >= 2512)
-		noisepercentage = 79;
-	else if (temp >= 1995)
-		noisepercentage = 72;
-	else if (temp >= 1585)
-		noisepercentage = 65;
-	else if (temp >= 1259)
-		noisepercentage = 58;
-	else if (temp >= 1000)
-		noisepercentage = 50;
-	else if (temp >= 794)
-		noisepercentage = 43;
-	else if (temp >= 501)
-		noisepercentage = 36;
-	else if (temp >= 316)
-		noisepercentage = 29;
-	else if (temp >= 200)
-		noisepercentage = 22;
-	else if (temp >= 158)
-		noisepercentage = 14;
-	else if (temp >= 126)
-		noisepercentage = 7;
-	else
-		noisepercentage = 0;
-
-	dprintk("%s: noisepercentage=%d\n", __func__, noisepercentage);
-
-	*snr = (noisepercentage * 65535) / 100;
-
-	return 0;
-}
-
-static int stv0367cab_read_ucblcks(struct dvb_frontend *fe, u32 *ucblocks)
-{
-	struct stv0367_state *state = fe->demodulator_priv;
-	int corrected, tscount;
-
-	*ucblocks = (stv0367_readreg(state, R367CAB_RS_COUNTER_5) << 8)
-			| stv0367_readreg(state, R367CAB_RS_COUNTER_4);
-	corrected = (stv0367_readreg(state, R367CAB_RS_COUNTER_3) << 8)
-			| stv0367_readreg(state, R367CAB_RS_COUNTER_2);
-	tscount = (stv0367_readreg(state, R367CAB_RS_COUNTER_2) << 8)
-			| stv0367_readreg(state, R367CAB_RS_COUNTER_1);
-
-	dprintk("%s: uncorrected blocks=%d corrected blocks=%d tscount=%d\n",
-				__func__, *ucblocks, corrected, tscount);
-
-	return 0;
-};
-
-static struct dvb_frontend_ops stv0367cab_ops = {
-	.delsys = { SYS_DVBC_ANNEX_A },
-	.info = {
-		.name = "ST STV0367 DVB-C",
-		.frequency_min = 47000000,
-		.frequency_max = 862000000,
-		.frequency_stepsize = 62500,
-		.symbol_rate_min = 870000,
-		.symbol_rate_max = 11700000,
-		.caps = 0x400 |/* FE_CAN_QAM_4 */
-			FE_CAN_QAM_16 | FE_CAN_QAM_32  |
-			FE_CAN_QAM_64 | FE_CAN_QAM_128 |
-			FE_CAN_QAM_256 | FE_CAN_FEC_AUTO
-	},
-	.release				= stv0367_release,
-	.init					= stv0367cab_init,
-	.sleep					= stv0367cab_sleep,
-	.i2c_gate_ctrl				= stv0367cab_gate_ctrl,
-	.set_frontend				= stv0367cab_set_frontend,
-	.get_frontend				= stv0367cab_get_frontend,
-	.read_status				= stv0367cab_read_status,
-/*	.read_ber				= stv0367cab_read_ber, */
-	.read_signal_strength			= stv0367cab_read_strength,
-	.read_snr				= stv0367cab_read_snr,
-	.read_ucblocks				= stv0367cab_read_ucblcks,
-	.get_tune_settings			= stv0367_get_tune_settings,
-};
-
-struct dvb_frontend *stv0367cab_attach(const struct stv0367_config *config,
-				   struct i2c_adapter *i2c)
-{
-	struct stv0367_state *state = NULL;
-	struct stv0367cab_state *cab_state = NULL;
-
-	/* allocate memory for the internal state */
-	state = kzalloc(sizeof(struct stv0367_state), GFP_KERNEL);
-	if (state == NULL)
-		goto error;
-	cab_state = kzalloc(sizeof(struct stv0367cab_state), GFP_KERNEL);
-	if (cab_state == NULL)
-		goto error;
-
-	/* setup the state */
-	state->i2c = i2c;
-	state->config = config;
-	cab_state->search_range = 280000;
-	state->cab_state = cab_state;
-	state->fe.ops = stv0367cab_ops;
-	state->fe.demodulator_priv = state;
-	state->chip_id = stv0367_readreg(state, 0xf000);
-
-	dprintk("%s: chip_id = 0x%x\n", __func__, state->chip_id);
-
-	/* check if the demod is there */
-	if ((state->chip_id != 0x50) && (state->chip_id != 0x60))
-		goto error;
-
-	return &state->fe;
-
-error:
-	kfree(cab_state);
-	kfree(state);
-	return NULL;
-}
-EXPORT_SYMBOL(stv0367cab_attach);
-
-MODULE_PARM_DESC(debug, "Set debug");
-MODULE_PARM_DESC(i2c_debug, "Set i2c debug");
-
-MODULE_AUTHOR("Igor M. Liplianin");
-MODULE_DESCRIPTION("ST STV0367 DVB-C/T demodulator driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/stv0367.h b/drivers/media/dvb/frontends/stv0367.h
deleted file mode 100644
index 93cc4a5..0000000
--- a/drivers/media/dvb/frontends/stv0367.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * stv0367.h
- *
- * Driver for ST STV0367 DVB-T & DVB-C demodulator IC.
- *
- * Copyright (C) ST Microelectronics.
- * Copyright (C) 2010,2011 NetUP Inc.
- * Copyright (C) 2010,2011 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 STV0367_H
-#define STV0367_H
-
-#include <linux/dvb/frontend.h>
-#include "dvb_frontend.h"
-
-struct stv0367_config {
-	u8 demod_address;
-	u32 xtal;
-	u32 if_khz;/*4500*/
-	int if_iq_mode;
-	int ts_mode;
-	int clk_pol;
-};
-
-#if defined(CONFIG_DVB_STV0367) || (defined(CONFIG_DVB_STV0367_MODULE) \
-							&& defined(MODULE))
-extern struct
-dvb_frontend *stv0367ter_attach(const struct stv0367_config *config,
-					struct i2c_adapter *i2c);
-extern struct
-dvb_frontend *stv0367cab_attach(const struct stv0367_config *config,
-					struct i2c_adapter *i2c);
-#else
-static inline struct
-dvb_frontend *stv0367ter_attach(const struct stv0367_config *config,
-					struct i2c_adapter *i2c)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-static inline struct
-dvb_frontend *stv0367cab_attach(const struct stv0367_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/stv0367_priv.h b/drivers/media/dvb/frontends/stv0367_priv.h
deleted file mode 100644
index 995db06..0000000
--- a/drivers/media/dvb/frontends/stv0367_priv.h
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * stv0367_priv.h
- *
- * Driver for ST STV0367 DVB-T & DVB-C demodulator IC.
- *
- * Copyright (C) ST Microelectronics.
- * Copyright (C) 2010,2011 NetUP Inc.
- * Copyright (C) 2010,2011 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.
- */
-/* Common driver error constants */
-
-#ifndef STV0367_PRIV_H
-#define STV0367_PRIV_H
-
-#ifndef TRUE
-    #define TRUE (1 == 1)
-#endif
-#ifndef FALSE
-    #define FALSE (!TRUE)
-#endif
-
-#ifndef NULL
-#define NULL 0
-#endif
-
-/* MACRO definitions */
-#define ABS(X) ((X) < 0 ? (-1 * (X)) : (X))
-#define MAX(X, Y) ((X) >= (Y) ? (X) : (Y))
-#define MIN(X, Y) ((X) <= (Y) ? (X) : (Y))
-#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)
-#define MMSB(Y)(((Y) >> 16) & 0xff)
-
-enum stv0367_ter_signal_type {
-	FE_TER_NOAGC = 0,
-	FE_TER_AGCOK = 5,
-	FE_TER_NOTPS = 6,
-	FE_TER_TPSOK = 7,
-	FE_TER_NOSYMBOL = 8,
-	FE_TER_BAD_CPQ = 9,
-	FE_TER_PRFOUNDOK = 10,
-	FE_TER_NOPRFOUND = 11,
-	FE_TER_LOCKOK = 12,
-	FE_TER_NOLOCK = 13,
-	FE_TER_SYMBOLOK = 15,
-	FE_TER_CPAMPOK = 16,
-	FE_TER_NOCPAMP = 17,
-	FE_TER_SWNOK = 18
-};
-
-enum stv0367_ts_mode {
-	STV0367_OUTPUTMODE_DEFAULT,
-	STV0367_SERIAL_PUNCT_CLOCK,
-	STV0367_SERIAL_CONT_CLOCK,
-	STV0367_PARALLEL_PUNCT_CLOCK,
-	STV0367_DVBCI_CLOCK
-};
-
-enum stv0367_clk_pol {
-	STV0367_CLOCKPOLARITY_DEFAULT,
-	STV0367_RISINGEDGE_CLOCK,
-	STV0367_FALLINGEDGE_CLOCK
-};
-
-enum stv0367_ter_bw {
-	FE_TER_CHAN_BW_6M = 6,
-	FE_TER_CHAN_BW_7M = 7,
-	FE_TER_CHAN_BW_8M = 8
-};
-
-#if 0
-enum FE_TER_Rate_TPS {
-	FE_TER_TPS_1_2 = 0,
-	FE_TER_TPS_2_3 = 1,
-	FE_TER_TPS_3_4 = 2,
-	FE_TER_TPS_5_6 = 3,
-	FE_TER_TPS_7_8 = 4
-};
-#endif
-
-enum stv0367_ter_mode {
-	FE_TER_MODE_2K,
-	FE_TER_MODE_8K,
-	FE_TER_MODE_4K
-};
-#if 0
-enum FE_TER_Hierarchy_Alpha {
-	FE_TER_HIER_ALPHA_NONE,	/* Regular modulation */
-	FE_TER_HIER_ALPHA_1,	/* Hierarchical modulation a = 1*/
-	FE_TER_HIER_ALPHA_2,	/* Hierarchical modulation a = 2*/
-	FE_TER_HIER_ALPHA_4	/* Hierarchical modulation a = 4*/
-};
-#endif
-enum stv0367_ter_hierarchy {
-	FE_TER_HIER_NONE,	/*Hierarchy None*/
-	FE_TER_HIER_LOW_PRIO,	/*Hierarchy : Low Priority*/
-	FE_TER_HIER_HIGH_PRIO,	/*Hierarchy : High Priority*/
-	FE_TER_HIER_PRIO_ANY	/*Hierarchy  :Any*/
-};
-
-#if 0
-enum fe_stv0367_ter_spec {
-	FE_TER_INVERSION_NONE = 0,
-	FE_TER_INVERSION = 1,
-	FE_TER_INVERSION_AUTO = 2,
-	FE_TER_INVERSION_UNK  = 4
-};
-#endif
-
-enum stv0367_ter_if_iq_mode {
-	FE_TER_NORMAL_IF_TUNER = 0,
-	FE_TER_LONGPATH_IF_TUNER = 1,
-	FE_TER_IQ_TUNER = 2
-
-};
-
-#if 0
-enum FE_TER_FECRate {
-	FE_TER_FEC_NONE = 0x00,	/* no FEC rate specified */
-	FE_TER_FEC_ALL = 0xFF,	 /* Logical OR of all FECs */
-	FE_TER_FEC_1_2 = 1,
-	FE_TER_FEC_2_3 = (1 << 1),
-	FE_TER_FEC_3_4 = (1 << 2),
-	FE_TER_FEC_4_5 = (1 << 3),
-	FE_TER_FEC_5_6 = (1 << 4),
-	FE_TER_FEC_6_7 = (1 << 5),
-	FE_TER_FEC_7_8 = (1 << 6),
-	FE_TER_FEC_8_9 = (1 << 7)
-};
-
-enum FE_TER_Rate {
-	FE_TER_FE_1_2 = 0,
-	FE_TER_FE_2_3 = 1,
-	FE_TER_FE_3_4 = 2,
-	FE_TER_FE_5_6 = 3,
-	FE_TER_FE_6_7 = 4,
-	FE_TER_FE_7_8 = 5
-};
-#endif
-
-enum stv0367_ter_force {
-	FE_TER_FORCENONE = 0,
-	FE_TER_FORCE_M_G = 1
-};
-
-enum  stv0367cab_mod {
-	FE_CAB_MOD_QAM4,
-	FE_CAB_MOD_QAM16,
-	FE_CAB_MOD_QAM32,
-	FE_CAB_MOD_QAM64,
-	FE_CAB_MOD_QAM128,
-	FE_CAB_MOD_QAM256,
-	FE_CAB_MOD_QAM512,
-	FE_CAB_MOD_QAM1024
-};
-#if 0
-enum {
-	FE_CAB_FEC_A = 1,	/* J83 Annex A */
-	FE_CAB_FEC_B = (1 << 1),/* J83 Annex B */
-	FE_CAB_FEC_C = (1 << 2)	/* J83 Annex C */
-} FE_CAB_FECType_t;
-#endif
-struct stv0367_cab_signal_info {
-	int locked;
-	u32 frequency; /* kHz */
-	u32 symbol_rate; /* Mbds */
-	enum stv0367cab_mod modulation;
-	fe_spectral_inversion_t spect_inv;
-	s32 Power_dBmx10;	/* Power of the RF signal (dBm x 10) */
-	u32	CN_dBx10;	/* Carrier to noise ratio (dB x 10) */
-	u32	BER;		/* Bit error rate (x 10000000)	*/
-};
-
-enum stv0367_cab_signal_type {
-	FE_CAB_NOTUNER,
-	FE_CAB_NOAGC,
-	FE_CAB_NOSIGNAL,
-	FE_CAB_NOTIMING,
-	FE_CAB_TIMINGOK,
-	FE_CAB_NOCARRIER,
-	FE_CAB_CARRIEROK,
-	FE_CAB_NOBLIND,
-	FE_CAB_BLINDOK,
-	FE_CAB_NODEMOD,
-	FE_CAB_DEMODOK,
-	FE_CAB_DATAOK
-};
-
-#endif
diff --git a/drivers/media/dvb/frontends/stv0367_regs.h b/drivers/media/dvb/frontends/stv0367_regs.h
deleted file mode 100644
index a96fbdc..0000000
--- a/drivers/media/dvb/frontends/stv0367_regs.h
+++ /dev/null
@@ -1,3614 +0,0 @@
-/*
- * stv0367_regs.h
- *
- * Driver for ST STV0367 DVB-T & DVB-C demodulator IC.
- *
- * Copyright (C) ST Microelectronics.
- * Copyright (C) 2010,2011 NetUP Inc.
- * Copyright (C) 2010,2011 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 STV0367_REGS_H
-#define STV0367_REGS_H
-
-/* ID */
-#define	R367TER_ID	0xf000
-#define	F367TER_IDENTIFICATIONREG	0xf00000ff
-
-/* I2CRPT */
-#define	R367TER_I2CRPT	0xf001
-#define	F367TER_I2CT_ON	0xf0010080
-#define	F367TER_ENARPT_LEVEL	0xf0010070
-#define	F367TER_SCLT_DELAY	0xf0010008
-#define	F367TER_SCLT_NOD	0xf0010004
-#define	F367TER_STOP_ENABLE	0xf0010002
-#define	F367TER_SDAT_NOD	0xf0010001
-
-/* TOPCTRL */
-#define	R367TER_TOPCTRL	0xf002
-#define	F367TER_STDBY	0xf0020080
-#define	F367TER_STDBY_FEC	0xf0020040
-#define	F367TER_STDBY_CORE	0xf0020020
-#define	F367TER_QAM_COFDM	0xf0020010
-#define	F367TER_TS_DIS	0xf0020008
-#define	F367TER_DIR_CLK_216	0xf0020004
-#define	F367TER_TUNER_BB	0xf0020002
-#define	F367TER_DVBT_H	0xf0020001
-
-/* IOCFG0 */
-#define	R367TER_IOCFG0	0xf003
-#define	F367TER_OP0_SD	0xf0030080
-#define	F367TER_OP0_VAL	0xf0030040
-#define	F367TER_OP0_OD	0xf0030020
-#define	F367TER_OP0_INV	0xf0030010
-#define	F367TER_OP0_DACVALUE_HI	0xf003000f
-
-/* DAc0R */
-#define	R367TER_DAC0R	0xf004
-#define	F367TER_OP0_DACVALUE_LO	0xf00400ff
-
-/* IOCFG1 */
-#define	R367TER_IOCFG1	0xf005
-#define	F367TER_IP0	0xf0050040
-#define	F367TER_OP1_OD	0xf0050020
-#define	F367TER_OP1_INV	0xf0050010
-#define	F367TER_OP1_DACVALUE_HI	0xf005000f
-
-/* DAC1R */
-#define	R367TER_DAC1R	0xf006
-#define	F367TER_OP1_DACVALUE_LO	0xf00600ff
-
-/* IOCFG2 */
-#define	R367TER_IOCFG2	0xf007
-#define	F367TER_OP2_LOCK_CONF	0xf00700e0
-#define	F367TER_OP2_OD	0xf0070010
-#define	F367TER_OP2_VAL	0xf0070008
-#define	F367TER_OP1_LOCK_CONF	0xf0070007
-
-/* SDFR */
-#define	R367TER_SDFR	0xf008
-#define	F367TER_OP0_FREQ	0xf00800f0
-#define	F367TER_OP1_FREQ	0xf008000f
-
-/* STATUS */
-#define	R367TER_STATUS	0xf009
-#define	F367TER_TPS_LOCK	0xf0090080
-#define	F367TER_SYR_LOCK	0xf0090040
-#define	F367TER_AGC_LOCK	0xf0090020
-#define	F367TER_PRF	0xf0090010
-#define	F367TER_LK	0xf0090008
-#define	F367TER_PR	0xf0090007
-
-/* AUX_CLK */
-#define	R367TER_AUX_CLK	0xf00a
-#define	F367TER_AUXFEC_CTL	0xf00a00c0
-#define	F367TER_DIS_CKX4	0xf00a0020
-#define	F367TER_CKSEL	0xf00a0018
-#define	F367TER_CKDIV_PROG	0xf00a0006
-#define	F367TER_AUXCLK_ENA	0xf00a0001
-
-/* FREESYS1 */
-#define	R367TER_FREESYS1	0xf00b
-#define	F367TER_FREE_SYS1	0xf00b00ff
-
-/* FREESYS2 */
-#define	R367TER_FREESYS2	0xf00c
-#define	F367TER_FREE_SYS2	0xf00c00ff
-
-/* FREESYS3 */
-#define	R367TER_FREESYS3	0xf00d
-#define	F367TER_FREE_SYS3	0xf00d00ff
-
-/* GPIO_CFG */
-#define	R367TER_GPIO_CFG	0xf00e
-#define	F367TER_GPIO7_NOD	0xf00e0080
-#define	F367TER_GPIO7_CFG	0xf00e0040
-#define	F367TER_GPIO6_NOD	0xf00e0020
-#define	F367TER_GPIO6_CFG	0xf00e0010
-#define	F367TER_GPIO5_NOD	0xf00e0008
-#define	F367TER_GPIO5_CFG	0xf00e0004
-#define	F367TER_GPIO4_NOD	0xf00e0002
-#define	F367TER_GPIO4_CFG	0xf00e0001
-
-/* GPIO_CMD */
-#define	R367TER_GPIO_CMD	0xf00f
-#define	F367TER_GPIO7_VAL	0xf00f0008
-#define	F367TER_GPIO6_VAL	0xf00f0004
-#define	F367TER_GPIO5_VAL	0xf00f0002
-#define	F367TER_GPIO4_VAL	0xf00f0001
-
-/* AGC2MAX */
-#define	R367TER_AGC2MAX	0xf010
-#define	F367TER_AGC2_MAX	0xf01000ff
-
-/* AGC2MIN */
-#define	R367TER_AGC2MIN	0xf011
-#define	F367TER_AGC2_MIN	0xf01100ff
-
-/* AGC1MAX */
-#define	R367TER_AGC1MAX	0xf012
-#define	F367TER_AGC1_MAX	0xf01200ff
-
-/* AGC1MIN */
-#define	R367TER_AGC1MIN	0xf013
-#define	F367TER_AGC1_MIN	0xf01300ff
-
-/* AGCR */
-#define	R367TER_AGCR	0xf014
-#define	F367TER_RATIO_A	0xf01400e0
-#define	F367TER_RATIO_B	0xf0140018
-#define	F367TER_RATIO_C	0xf0140007
-
-/* AGC2TH */
-#define	R367TER_AGC2TH	0xf015
-#define	F367TER_AGC2_THRES	0xf01500ff
-
-/* AGC12c */
-#define	R367TER_AGC12C	0xf016
-#define	F367TER_AGC1_IV	0xf0160080
-#define	F367TER_AGC1_OD	0xf0160040
-#define	F367TER_AGC1_LOAD	0xf0160020
-#define	F367TER_AGC2_IV	0xf0160010
-#define	F367TER_AGC2_OD	0xf0160008
-#define	F367TER_AGC2_LOAD	0xf0160004
-#define	F367TER_AGC12_MODE	0xf0160003
-
-/* AGCCTRL1 */
-#define	R367TER_AGCCTRL1	0xf017
-#define	F367TER_DAGC_ON	0xf0170080
-#define	F367TER_INVERT_AGC12	0xf0170040
-#define	F367TER_AGC1_MODE	0xf0170008
-#define	F367TER_AGC2_MODE	0xf0170007
-
-/* AGCCTRL2 */
-#define	R367TER_AGCCTRL2	0xf018
-#define	F367TER_FRZ2_CTRL	0xf0180060
-#define	F367TER_FRZ1_CTRL	0xf0180018
-#define	F367TER_TIME_CST	0xf0180007
-
-/* AGC1VAL1 */
-#define	R367TER_AGC1VAL1	0xf019
-#define	F367TER_AGC1_VAL_LO	0xf01900ff
-
-/* AGC1VAL2 */
-#define	R367TER_AGC1VAL2	0xf01a
-#define	F367TER_AGC1_VAL_HI	0xf01a000f
-
-/* AGC2VAL1 */
-#define	R367TER_AGC2VAL1	0xf01b
-#define	F367TER_AGC2_VAL_LO	0xf01b00ff
-
-/* AGC2VAL2 */
-#define	R367TER_AGC2VAL2	0xf01c
-#define	F367TER_AGC2_VAL_HI	0xf01c000f
-
-/* AGC2PGA */
-#define	R367TER_AGC2PGA	0xf01d
-#define	F367TER_AGC2_PGA	0xf01d00ff
-
-/* OVF_RATE1 */
-#define	R367TER_OVF_RATE1	0xf01e
-#define	F367TER_OVF_RATE_HI	0xf01e000f
-
-/* OVF_RATE2 */
-#define	R367TER_OVF_RATE2	0xf01f
-#define	F367TER_OVF_RATE_LO	0xf01f00ff
-
-/* GAIN_SRC1 */
-#define	R367TER_GAIN_SRC1	0xf020
-#define	F367TER_INV_SPECTR	0xf0200080
-#define	F367TER_IQ_INVERT	0xf0200040
-#define	F367TER_INR_BYPASS	0xf0200020
-#define	F367TER_STATUS_INV_SPECRUM	0xf0200010
-#define	F367TER_GAIN_SRC_HI	0xf020000f
-
-/* GAIN_SRC2 */
-#define	R367TER_GAIN_SRC2	0xf021
-#define	F367TER_GAIN_SRC_LO	0xf02100ff
-
-/* INC_DEROT1 */
-#define	R367TER_INC_DEROT1	0xf022
-#define	F367TER_INC_DEROT_HI	0xf02200ff
-
-/* INC_DEROT2 */
-#define	R367TER_INC_DEROT2	0xf023
-#define	F367TER_INC_DEROT_LO	0xf02300ff
-
-/* PPM_CPAMP_DIR */
-#define	R367TER_PPM_CPAMP_DIR	0xf024
-#define	F367TER_PPM_CPAMP_DIRECT	0xf02400ff
-
-/* PPM_CPAMP_INV */
-#define	R367TER_PPM_CPAMP_INV	0xf025
-#define	F367TER_PPM_CPAMP_INVER	0xf02500ff
-
-/* FREESTFE_1 */
-#define	R367TER_FREESTFE_1	0xf026
-#define	F367TER_SYMBOL_NUMBER_INC	0xf02600c0
-#define	F367TER_SEL_LSB	0xf0260004
-#define	F367TER_AVERAGE_ON	0xf0260002
-#define	F367TER_DC_ADJ	0xf0260001
-
-/* FREESTFE_2 */
-#define	R367TER_FREESTFE_2	0xf027
-#define	F367TER_SEL_SRCOUT	0xf02700c0
-#define	F367TER_SEL_SYRTHR	0xf027001f
-
-/* DCOFFSET */
-#define	R367TER_DCOFFSET	0xf028
-#define	F367TER_SELECT_I_Q	0xf0280080
-#define	F367TER_DC_OFFSET	0xf028007f
-
-/* EN_PROCESS */
-#define	R367TER_EN_PROCESS	0xf029
-#define	F367TER_FREE	0xf02900f0
-#define	F367TER_ENAB_MANUAL	0xf0290001
-
-/* SDI_SMOOTHER */
-#define	R367TER_SDI_SMOOTHER	0xf02a
-#define	F367TER_DIS_SMOOTH	0xf02a0080
-#define	F367TER_SDI_INC_SMOOTHER	0xf02a007f
-
-/* FE_LOOP_OPEN */
-#define	R367TER_FE_LOOP_OPEN	0xf02b
-#define	F367TER_TRL_LOOP_OP	0xf02b0002
-#define	F367TER_CRL_LOOP_OP	0xf02b0001
-
-/* FREQOFF1 */
-#define	R367TER_FREQOFF1	0xf02c
-#define	F367TER_FREQ_OFFSET_LOOP_OPEN_VHI	0xf02c00ff
-
-/* FREQOFF2 */
-#define	R367TER_FREQOFF2	0xf02d
-#define	F367TER_FREQ_OFFSET_LOOP_OPEN_HI	0xf02d00ff
-
-/* FREQOFF3 */
-#define	R367TER_FREQOFF3	0xf02e
-#define	F367TER_FREQ_OFFSET_LOOP_OPEN_LO	0xf02e00ff
-
-/* TIMOFF1 */
-#define	R367TER_TIMOFF1	0xf02f
-#define	F367TER_TIM_OFFSET_LOOP_OPEN_HI	0xf02f00ff
-
-/* TIMOFF2 */
-#define	R367TER_TIMOFF2	0xf030
-#define	F367TER_TIM_OFFSET_LOOP_OPEN_LO	0xf03000ff
-
-/* EPQ */
-#define	R367TER_EPQ	0xf031
-#define	F367TER_EPQ1	0xf03100ff
-
-/* EPQAUTO */
-#define	R367TER_EPQAUTO	0xf032
-#define	F367TER_EPQ2	0xf03200ff
-
-/* SYR_UPDATE */
-#define	R367TER_SYR_UPDATE	0xf033
-#define	F367TER_SYR_PROTV	0xf0330080
-#define	F367TER_SYR_PROTV_GAIN	0xf0330060
-#define	F367TER_SYR_FILTER	0xf0330010
-#define	F367TER_SYR_TRACK_THRES	0xf033000c
-
-/* CHPFREE */
-#define	R367TER_CHPFREE	0xf034
-#define	F367TER_CHP_FREE	0xf03400ff
-
-/* PPM_STATE_MAC */
-#define	R367TER_PPM_STATE_MAC	0xf035
-#define	F367TER_PPM_STATE_MACHINE_DECODER	0xf035003f
-
-/* INR_THRESHOLD */
-#define	R367TER_INR_THRESHOLD	0xf036
-#define	F367TER_INR_THRESH	0xf03600ff
-
-/* EPQ_TPS_ID_CELL */
-#define	R367TER_EPQ_TPS_ID_CELL	0xf037
-#define	F367TER_ENABLE_LGTH_TO_CF	0xf0370080
-#define	F367TER_DIS_TPS_RSVD	0xf0370040
-#define	F367TER_DIS_BCH	0xf0370020
-#define	F367TER_DIS_ID_CEL	0xf0370010
-#define	F367TER_TPS_ADJUST_SYM	0xf037000f
-
-/* EPQ_CFG */
-#define	R367TER_EPQ_CFG	0xf038
-#define	F367TER_EPQ_RANGE	0xf0380002
-#define	F367TER_EPQ_SOFT	0xf0380001
-
-/* EPQ_STATUS */
-#define	R367TER_EPQ_STATUS	0xf039
-#define	F367TER_SLOPE_INC	0xf03900fc
-#define	F367TER_TPS_FIELD	0xf0390003
-
-/* AUTORELOCK */
-#define	R367TER_AUTORELOCK	0xf03a
-#define	F367TER_BYPASS_BER_TEMPO	0xf03a0080
-#define	F367TER_BER_TEMPO	0xf03a0070
-#define	F367TER_BYPASS_COFDM_TEMPO	0xf03a0008
-#define	F367TER_COFDM_TEMPO	0xf03a0007
-
-/* BER_THR_VMSB */
-#define	R367TER_BER_THR_VMSB	0xf03b
-#define	F367TER_BER_THRESHOLD_HI	0xf03b00ff
-
-/* BER_THR_MSB */
-#define	R367TER_BER_THR_MSB	0xf03c
-#define	F367TER_BER_THRESHOLD_MID	0xf03c00ff
-
-/* BER_THR_LSB */
-#define	R367TER_BER_THR_LSB	0xf03d
-#define	F367TER_BER_THRESHOLD_LO	0xf03d00ff
-
-/* CCD */
-#define	R367TER_CCD	0xf03e
-#define	F367TER_CCD_DETECTED	0xf03e0080
-#define	F367TER_CCD_RESET	0xf03e0040
-#define	F367TER_CCD_THRESHOLD	0xf03e000f
-
-/* SPECTR_CFG */
-#define	R367TER_SPECTR_CFG	0xf03f
-#define	F367TER_SPECT_CFG	0xf03f0003
-
-/* CONSTMU_MSB */
-#define	R367TER_CONSTMU_MSB	0xf040
-#define	F367TER_CONSTMU_FREEZE	0xf0400080
-#define	F367TER_CONSTNU_FORCE_EN	0xf0400040
-#define	F367TER_CONST_MU_MSB	0xf040003f
-
-/* CONSTMU_LSB */
-#define	R367TER_CONSTMU_LSB	0xf041
-#define	F367TER_CONST_MU_LSB	0xf04100ff
-
-/* CONSTMU_MAX_MSB */
-#define	R367TER_CONSTMU_MAX_MSB	0xf042
-#define	F367TER_CONST_MU_MAX_MSB	0xf042003f
-
-/* CONSTMU_MAX_LSB */
-#define	R367TER_CONSTMU_MAX_LSB	0xf043
-#define	F367TER_CONST_MU_MAX_LSB	0xf04300ff
-
-/* ALPHANOISE */
-#define	R367TER_ALPHANOISE	0xf044
-#define	F367TER_USE_ALLFILTER	0xf0440080
-#define	F367TER_INTER_ON	0xf0440040
-#define	F367TER_ALPHA_NOISE	0xf044001f
-
-/* MAXGP_MSB */
-#define	R367TER_MAXGP_MSB	0xf045
-#define	F367TER_MUFILTER_LENGTH	0xf04500f0
-#define	F367TER_MAX_GP_MSB	0xf045000f
-
-/* MAXGP_LSB */
-#define	R367TER_MAXGP_LSB	0xf046
-#define	F367TER_MAX_GP_LSB	0xf04600ff
-
-/* ALPHAMSB */
-#define	R367TER_ALPHAMSB	0xf047
-#define	F367TER_CHC_DATARATE	0xf04700c0
-#define	F367TER_ALPHA_MSB	0xf047003f
-
-/* ALPHALSB */
-#define	R367TER_ALPHALSB	0xf048
-#define	F367TER_ALPHA_LSB	0xf04800ff
-
-/* PILOT_ACCU */
-#define	R367TER_PILOT_ACCU	0xf049
-#define	F367TER_USE_SCAT4ADDAPT	0xf0490080
-#define	F367TER_PILOT_ACC	0xf049001f
-
-/* PILOTMU_ACCU */
-#define	R367TER_PILOTMU_ACCU	0xf04a
-#define	F367TER_DISCARD_BAD_SP	0xf04a0080
-#define	F367TER_DISCARD_BAD_CP	0xf04a0040
-#define	F367TER_PILOT_MU_ACCU	0xf04a001f
-
-/* FILT_CHANNEL_EST */
-#define	R367TER_FILT_CHANNEL_EST	0xf04b
-#define	F367TER_USE_FILT_PILOT	0xf04b0080
-#define	F367TER_FILT_CHANNEL	0xf04b007f
-
-/* ALPHA_NOPISE_FREQ */
-#define	R367TER_ALPHA_NOPISE_FREQ	0xf04c
-#define	F367TER_NOISE_FREQ_FILT	0xf04c0040
-#define	F367TER_ALPHA_NOISE_FREQ	0xf04c003f
-
-/* RATIO_PILOT */
-#define	R367TER_RATIO_PILOT	0xf04d
-#define	F367TER_RATIO_MEAN_SP	0xf04d00f0
-#define	F367TER_RATIO_MEAN_CP	0xf04d000f
-
-/* CHC_CTL */
-#define	R367TER_CHC_CTL	0xf04e
-#define	F367TER_TRACK_EN	0xf04e0080
-#define	F367TER_NOISE_NORM_EN	0xf04e0040
-#define	F367TER_FORCE_CHC_RESET	0xf04e0020
-#define	F367TER_SHORT_TIME	0xf04e0010
-#define	F367TER_FORCE_STATE_EN	0xf04e0008
-#define	F367TER_FORCE_STATE	0xf04e0007
-
-/* EPQ_ADJUST */
-#define	R367TER_EPQ_ADJUST	0xf04f
-#define	F367TER_ADJUST_SCAT_IND	0xf04f00c0
-#define	F367TER_ONE_SYMBOL	0xf04f0010
-#define	F367TER_EPQ_DECAY	0xf04f000e
-#define	F367TER_HOLD_SLOPE	0xf04f0001
-
-/* EPQ_THRES */
-#define	R367TER_EPQ_THRES	0xf050
-#define	F367TER_EPQ_THR	0xf05000ff
-
-/* OMEGA_CTL */
-#define	R367TER_OMEGA_CTL	0xf051
-#define	F367TER_OMEGA_RST	0xf0510080
-#define	F367TER_FREEZE_OMEGA	0xf0510040
-#define	F367TER_OMEGA_SEL	0xf051003f
-
-/* GP_CTL */
-#define	R367TER_GP_CTL	0xf052
-#define	F367TER_CHC_STATE	0xf05200e0
-#define	F367TER_FREEZE_GP	0xf0520010
-#define	F367TER_GP_SEL	0xf052000f
-
-/* MUMSB */
-#define	R367TER_MUMSB	0xf053
-#define	F367TER_MU_MSB	0xf053007f
-
-/* MULSB */
-#define	R367TER_MULSB	0xf054
-#define	F367TER_MU_LSB	0xf05400ff
-
-/* GPMSB */
-#define	R367TER_GPMSB	0xf055
-#define	F367TER_CSI_THRESHOLD	0xf05500e0
-#define	F367TER_GP_MSB	0xf055000f
-
-/* GPLSB */
-#define	R367TER_GPLSB	0xf056
-#define	F367TER_GP_LSB	0xf05600ff
-
-/* OMEGAMSB */
-#define	R367TER_OMEGAMSB	0xf057
-#define	F367TER_OMEGA_MSB	0xf057007f
-
-/* OMEGALSB */
-#define	R367TER_OMEGALSB	0xf058
-#define	F367TER_OMEGA_LSB	0xf05800ff
-
-/* SCAT_NB */
-#define	R367TER_SCAT_NB	0xf059
-#define	F367TER_CHC_TEST	0xf05900f8
-#define	F367TER_SCAT_NUMB	0xf0590003
-
-/* CHC_DUMMY */
-#define	R367TER_CHC_DUMMY	0xf05a
-#define	F367TER_CHC_DUM	0xf05a00ff
-
-/* INC_CTL */
-#define	R367TER_INC_CTL	0xf05b
-#define	F367TER_INC_BYPASS	0xf05b0080
-#define	F367TER_INC_NDEPTH	0xf05b000c
-#define	F367TER_INC_MADEPTH	0xf05b0003
-
-/* INCTHRES_COR1 */
-#define	R367TER_INCTHRES_COR1	0xf05c
-#define	F367TER_INC_THRES_COR1	0xf05c00ff
-
-/* INCTHRES_COR2 */
-#define	R367TER_INCTHRES_COR2	0xf05d
-#define	F367TER_INC_THRES_COR2	0xf05d00ff
-
-/* INCTHRES_DET1 */
-#define	R367TER_INCTHRES_DET1	0xf05e
-#define	F367TER_INC_THRES_DET1	0xf05e003f
-
-/* INCTHRES_DET2 */
-#define	R367TER_INCTHRES_DET2	0xf05f
-#define	F367TER_INC_THRES_DET2	0xf05f003f
-
-/* IIR_CELLNB */
-#define	R367TER_IIR_CELLNB	0xf060
-#define	F367TER_NRST_IIR	0xf0600080
-#define	F367TER_IIR_CELL_NB	0xf0600007
-
-/* IIRCX_COEFF1_MSB */
-#define	R367TER_IIRCX_COEFF1_MSB	0xf061
-#define	F367TER_IIR_CX_COEFF1_MSB	0xf06100ff
-
-/* IIRCX_COEFF1_LSB */
-#define	R367TER_IIRCX_COEFF1_LSB	0xf062
-#define	F367TER_IIR_CX_COEFF1_LSB	0xf06200ff
-
-/* IIRCX_COEFF2_MSB */
-#define	R367TER_IIRCX_COEFF2_MSB	0xf063
-#define	F367TER_IIR_CX_COEFF2_MSB	0xf06300ff
-
-/* IIRCX_COEFF2_LSB */
-#define	R367TER_IIRCX_COEFF2_LSB	0xf064
-#define	F367TER_IIR_CX_COEFF2_LSB	0xf06400ff
-
-/* IIRCX_COEFF3_MSB */
-#define	R367TER_IIRCX_COEFF3_MSB	0xf065
-#define	F367TER_IIR_CX_COEFF3_MSB	0xf06500ff
-
-/* IIRCX_COEFF3_LSB */
-#define	R367TER_IIRCX_COEFF3_LSB	0xf066
-#define	F367TER_IIR_CX_COEFF3_LSB	0xf06600ff
-
-/* IIRCX_COEFF4_MSB */
-#define	R367TER_IIRCX_COEFF4_MSB	0xf067
-#define	F367TER_IIR_CX_COEFF4_MSB	0xf06700ff
-
-/* IIRCX_COEFF4_LSB */
-#define	R367TER_IIRCX_COEFF4_LSB	0xf068
-#define	F367TER_IIR_CX_COEFF4_LSB	0xf06800ff
-
-/* IIRCX_COEFF5_MSB */
-#define	R367TER_IIRCX_COEFF5_MSB	0xf069
-#define	F367TER_IIR_CX_COEFF5_MSB	0xf06900ff
-
-/* IIRCX_COEFF5_LSB */
-#define	R367TER_IIRCX_COEFF5_LSB	0xf06a
-#define	F367TER_IIR_CX_COEFF5_LSB	0xf06a00ff
-
-/* FEPATH_CFG */
-#define	R367TER_FEPATH_CFG	0xf06b
-#define	F367TER_DEMUX_SWAP	0xf06b0004
-#define	F367TER_DIGAGC_SWAP	0xf06b0002
-#define	F367TER_LONGPATH_IF	0xf06b0001
-
-/* PMC1_FUNC */
-#define	R367TER_PMC1_FUNC	0xf06c
-#define	F367TER_SOFT_RSTN	0xf06c0080
-#define	F367TER_PMC1_AVERAGE_TIME	0xf06c0078
-#define	F367TER_PMC1_WAIT_TIME	0xf06c0006
-#define	F367TER_PMC1_2N_SEL	0xf06c0001
-
-/* PMC1_FOR */
-#define	R367TER_PMC1_FOR	0xf06d
-#define	F367TER_PMC1_FORCE	0xf06d0080
-#define	F367TER_PMC1_FORCE_VALUE	0xf06d007c
-
-/* PMC2_FUNC */
-#define	R367TER_PMC2_FUNC	0xf06e
-#define	F367TER_PMC2_SOFT_STN	0xf06e0080
-#define	F367TER_PMC2_ACCU_TIME	0xf06e0070
-#define	F367TER_PMC2_CMDP_MN	0xf06e0008
-#define	F367TER_PMC2_SWAP	0xf06e0004
-
-/* STATUS_ERR_DA */
-#define	R367TER_STATUS_ERR_DA	0xf06f
-#define	F367TER_COM_USEGAINTRK	0xf06f0080
-#define	F367TER_COM_AGCLOCK	0xf06f0040
-#define	F367TER_AUT_AGCLOCK	0xf06f0020
-#define	F367TER_MIN_ERR_X_LSB	0xf06f000f
-
-/* DIG_AGC_R */
-#define	R367TER_DIG_AGC_R	0xf070
-#define	F367TER_COM_SOFT_RSTN	0xf0700080
-#define	F367TER_COM_AGC_ON	0xf0700040
-#define	F367TER_COM_EARLY	0xf0700020
-#define	F367TER_AUT_SOFT_RESETN	0xf0700010
-#define	F367TER_AUT_AGC_ON	0xf0700008
-#define	F367TER_AUT_EARLY	0xf0700004
-#define	F367TER_AUT_ROT_EN	0xf0700002
-#define	F367TER_LOCK_SOFT_RESETN	0xf0700001
-
-/* COMAGC_TARMSB */
-#define	R367TER_COMAGC_TARMSB	0xf071
-#define	F367TER_COM_AGC_TARGET_MSB	0xf07100ff
-
-/* COM_AGC_TAR_ENMODE */
-#define	R367TER_COM_AGC_TAR_ENMODE	0xf072
-#define	F367TER_COM_AGC_TARGET_LSB	0xf07200f0
-#define	F367TER_COM_ENMODE	0xf072000f
-
-/* COM_AGC_CFG */
-#define	R367TER_COM_AGC_CFG	0xf073
-#define	F367TER_COM_N	0xf07300f8
-#define	F367TER_COM_STABMODE	0xf0730006
-#define	F367TER_ERR_SEL	0xf0730001
-
-/* COM_AGC_GAIN1 */
-#define	R367TER_COM_AGC_GAIN1	0xf074
-#define	F367TER_COM_GAIN1aCK	0xf07400f0
-#define	F367TER_COM_GAIN1TRK	0xf074000f
-
-/* AUT_AGC_TARGETMSB */
-#define	R367TER_AUT_AGC_TARGETMSB	0xf075
-#define	F367TER_AUT_AGC_TARGET_MSB	0xf07500ff
-
-/* LOCK_DET_MSB */
-#define	R367TER_LOCK_DET_MSB	0xf076
-#define	F367TER_LOCK_DETECT_MSB	0xf07600ff
-
-/* AGCTAR_LOCK_LSBS */
-#define	R367TER_AGCTAR_LOCK_LSBS	0xf077
-#define	F367TER_AUT_AGC_TARGET_LSB	0xf07700f0
-#define	F367TER_LOCK_DETECT_LSB	0xf077000f
-
-/* AUT_GAIN_EN */
-#define	R367TER_AUT_GAIN_EN	0xf078
-#define	F367TER_AUT_ENMODE	0xf07800f0
-#define	F367TER_AUT_GAIN2	0xf078000f
-
-/* AUT_CFG */
-#define	R367TER_AUT_CFG	0xf079
-#define	F367TER_AUT_N	0xf07900f8
-#define	F367TER_INT_CHOICE	0xf0790006
-#define	F367TER_INT_LOAD	0xf0790001
-
-/* LOCKN */
-#define	R367TER_LOCKN	0xf07a
-#define	F367TER_LOCK_N	0xf07a00f8
-#define	F367TER_SEL_IQNTAR	0xf07a0004
-#define	F367TER_LOCK_DETECT_CHOICE	0xf07a0003
-
-/* INT_X_3 */
-#define	R367TER_INT_X_3	0xf07b
-#define	F367TER_INT_X3	0xf07b00ff
-
-/* INT_X_2 */
-#define	R367TER_INT_X_2	0xf07c
-#define	F367TER_INT_X2	0xf07c00ff
-
-/* INT_X_1 */
-#define	R367TER_INT_X_1	0xf07d
-#define	F367TER_INT_X1	0xf07d00ff
-
-/* INT_X_0 */
-#define	R367TER_INT_X_0	0xf07e
-#define	F367TER_INT_X0	0xf07e00ff
-
-/* MIN_ERRX_MSB */
-#define	R367TER_MIN_ERRX_MSB	0xf07f
-#define	F367TER_MIN_ERR_X_MSB	0xf07f00ff
-
-/* COR_CTL */
-#define	R367TER_COR_CTL	0xf080
-#define	F367TER_CORE_ACTIVE	0xf0800020
-#define	F367TER_HOLD	0xf0800010
-#define	F367TER_CORE_STATE_CTL	0xf080000f
-
-/* COR_STAT */
-#define	R367TER_COR_STAT	0xf081
-#define	F367TER_SCATT_LOCKED	0xf0810080
-#define	F367TER_TPS_LOCKED	0xf0810040
-#define	F367TER_SYR_LOCKED_COR	0xf0810020
-#define	F367TER_AGC_LOCKED_STAT	0xf0810010
-#define	F367TER_CORE_STATE_STAT	0xf081000f
-
-/* COR_INTEN */
-#define	R367TER_COR_INTEN	0xf082
-#define	F367TER_INTEN	0xf0820080
-#define	F367TER_INTEN_SYR	0xf0820020
-#define	F367TER_INTEN_FFT	0xf0820010
-#define	F367TER_INTEN_AGC	0xf0820008
-#define	F367TER_INTEN_TPS1	0xf0820004
-#define	F367TER_INTEN_TPS2	0xf0820002
-#define	F367TER_INTEN_TPS3	0xf0820001
-
-/* COR_INTSTAT */
-#define	R367TER_COR_INTSTAT	0xf083
-#define	F367TER_INTSTAT_SYR	0xf0830020
-#define	F367TER_INTSTAT_FFT	0xf0830010
-#define	F367TER_INTSAT_AGC	0xf0830008
-#define	F367TER_INTSTAT_TPS1	0xf0830004
-#define	F367TER_INTSTAT_TPS2	0xf0830002
-#define	F367TER_INTSTAT_TPS3	0xf0830001
-
-/* COR_MODEGUARD */
-#define	R367TER_COR_MODEGUARD	0xf084
-#define	F367TER_FORCE	0xf0840010
-#define	F367TER_MODE	0xf084000c
-#define	F367TER_GUARD	0xf0840003
-
-/* AGC_CTL */
-#define	R367TER_AGC_CTL	0xf085
-#define	F367TER_AGC_TIMING_FACTOR	0xf08500e0
-#define	F367TER_AGC_LAST	0xf0850010
-#define	F367TER_AGC_GAIN	0xf085000c
-#define	F367TER_AGC_NEG	0xf0850002
-#define	F367TER_AGC_SET	0xf0850001
-
-/* AGC_MANUAL1 */
-#define	R367TER_AGC_MANUAL1	0xf086
-#define	F367TER_AGC_VAL_LO	0xf08600ff
-
-/* AGC_MANUAL2 */
-#define	R367TER_AGC_MANUAL2	0xf087
-#define	F367TER_AGC_VAL_HI	0xf087000f
-
-/* AGC_TARG */
-#define	R367TER_AGC_TARG	0xf088
-#define	F367TER_AGC_TARGET	0xf08800ff
-
-/* AGC_GAIN1 */
-#define	R367TER_AGC_GAIN1	0xf089
-#define	F367TER_AGC_GAIN_LO	0xf08900ff
-
-/* AGC_GAIN2 */
-#define	R367TER_AGC_GAIN2	0xf08a
-#define	F367TER_AGC_LOCKED_GAIN2	0xf08a0010
-#define	F367TER_AGC_GAIN_HI	0xf08a000f
-
-/* RESERVED_1 */
-#define	R367TER_RESERVED_1	0xf08b
-#define	F367TER_RESERVED1	0xf08b00ff
-
-/* RESERVED_2 */
-#define	R367TER_RESERVED_2	0xf08c
-#define	F367TER_RESERVED2	0xf08c00ff
-
-/* RESERVED_3 */
-#define	R367TER_RESERVED_3	0xf08d
-#define	F367TER_RESERVED3	0xf08d00ff
-
-/* CAS_CTL */
-#define	R367TER_CAS_CTL	0xf08e
-#define	F367TER_CCS_ENABLE	0xf08e0080
-#define	F367TER_ACS_DISABLE	0xf08e0040
-#define	F367TER_DAGC_DIS	0xf08e0020
-#define	F367TER_DAGC_GAIN	0xf08e0018
-#define	F367TER_CCSMU	0xf08e0007
-
-/* CAS_FREQ */
-#define	R367TER_CAS_FREQ	0xf08f
-#define	F367TER_CCS_FREQ	0xf08f00ff
-
-/* CAS_DAGCGAIN */
-#define	R367TER_CAS_DAGCGAIN	0xf090
-#define	F367TER_CAS_DAGC_GAIN	0xf09000ff
-
-/* SYR_CTL */
-#define	R367TER_SYR_CTL	0xf091
-#define	F367TER_SICTH_ENABLE	0xf0910080
-#define	F367TER_LONG_ECHO	0xf0910078
-#define	F367TER_AUTO_LE_EN	0xf0910004
-#define	F367TER_SYR_BYPASS	0xf0910002
-#define	F367TER_SYR_TR_DIS	0xf0910001
-
-/* SYR_STAT */
-#define	R367TER_SYR_STAT	0xf092
-#define	F367TER_SYR_LOCKED_STAT	0xf0920010
-#define	F367TER_SYR_MODE	0xf092000c
-#define	F367TER_SYR_GUARD	0xf0920003
-
-/* SYR_NCO1 */
-#define	R367TER_SYR_NCO1	0xf093
-#define	F367TER_SYR_NCO_LO	0xf09300ff
-
-/* SYR_NCO2 */
-#define	R367TER_SYR_NCO2	0xf094
-#define	F367TER_SYR_NCO_HI	0xf094003f
-
-/* SYR_OFFSET1 */
-#define	R367TER_SYR_OFFSET1	0xf095
-#define	F367TER_SYR_OFFSET_LO	0xf09500ff
-
-/* SYR_OFFSET2 */
-#define	R367TER_SYR_OFFSET2	0xf096
-#define	F367TER_SYR_OFFSET_HI	0xf096003f
-
-/* FFT_CTL */
-#define	R367TER_FFT_CTL	0xf097
-#define	F367TER_SHIFT_FFT_TRIG	0xf0970018
-#define	F367TER_FFT_TRIGGER	0xf0970004
-#define	F367TER_FFT_MANUAL	0xf0970002
-#define	F367TER_IFFT_MODE	0xf0970001
-
-/* SCR_CTL */
-#define	R367TER_SCR_CTL	0xf098
-#define	F367TER_SYRADJDECAY	0xf0980070
-#define	F367TER_SCR_CPEDIS	0xf0980002
-#define	F367TER_SCR_DIS	0xf0980001
-
-/* PPM_CTL1 */
-#define	R367TER_PPM_CTL1	0xf099
-#define	F367TER_PPM_MAXFREQ	0xf0990030
-#define	F367TER_PPM_MAXTIM	0xf0990008
-#define	F367TER_PPM_INVSEL	0xf0990004
-#define	F367TER_PPM_SCATDIS	0xf0990002
-#define	F367TER_PPM_BYP	0xf0990001
-
-/* TRL_CTL */
-#define	R367TER_TRL_CTL	0xf09a
-#define	F367TER_TRL_NOMRATE_LSB	0xf09a0080
-#define	F367TER_TRL_GAIN_FACTOR	0xf09a0078
-#define	F367TER_TRL_LOOPGAIN	0xf09a0007
-
-/* TRL_NOMRATE1 */
-#define	R367TER_TRL_NOMRATE1	0xf09b
-#define	F367TER_TRL_NOMRATE_LO	0xf09b00ff
-
-/* TRL_NOMRATE2 */
-#define	R367TER_TRL_NOMRATE2	0xf09c
-#define	F367TER_TRL_NOMRATE_HI	0xf09c00ff
-
-/* TRL_TIME1 */
-#define	R367TER_TRL_TIME1	0xf09d
-#define	F367TER_TRL_TOFFSET_LO	0xf09d00ff
-
-/* TRL_TIME2 */
-#define	R367TER_TRL_TIME2	0xf09e
-#define	F367TER_TRL_TOFFSET_HI	0xf09e00ff
-
-/* CRL_CTL */
-#define	R367TER_CRL_CTL	0xf09f
-#define	F367TER_CRL_DIS	0xf09f0080
-#define	F367TER_CRL_GAIN_FACTOR	0xf09f0078
-#define	F367TER_CRL_LOOPGAIN	0xf09f0007
-
-/* CRL_FREQ1 */
-#define	R367TER_CRL_FREQ1	0xf0a0
-#define	F367TER_CRL_FOFFSET_LO	0xf0a000ff
-
-/* CRL_FREQ2 */
-#define	R367TER_CRL_FREQ2	0xf0a1
-#define	F367TER_CRL_FOFFSET_HI	0xf0a100ff
-
-/* CRL_FREQ3 */
-#define	R367TER_CRL_FREQ3	0xf0a2
-#define	F367TER_CRL_FOFFSET_VHI	0xf0a200ff
-
-/* TPS_SFRAME_CTL */
-#define	R367TER_TPS_SFRAME_CTL	0xf0a3
-#define	F367TER_TPS_SFRAME_SYNC	0xf0a30001
-
-/* CHC_SNR */
-#define	R367TER_CHC_SNR	0xf0a4
-#define	F367TER_CHCSNR	0xf0a400ff
-
-/* BDI_CTL */
-#define	R367TER_BDI_CTL	0xf0a5
-#define	F367TER_BDI_LPSEL	0xf0a50002
-#define	F367TER_BDI_SERIAL	0xf0a50001
-
-/* DMP_CTL */
-#define	R367TER_DMP_CTL	0xf0a6
-#define	F367TER_DMP_SCALING_FACTOR	0xf0a6001e
-#define	F367TER_DMP_SDDIS	0xf0a60001
-
-/* TPS_RCVD1 */
-#define	R367TER_TPS_RCVD1	0xf0a7
-#define	F367TER_TPS_CHANGE	0xf0a70040
-#define	F367TER_BCH_OK	0xf0a70020
-#define	F367TER_TPS_SYNC	0xf0a70010
-#define	F367TER_TPS_FRAME	0xf0a70003
-
-/* TPS_RCVD2 */
-#define	R367TER_TPS_RCVD2	0xf0a8
-#define	F367TER_TPS_HIERMODE	0xf0a80070
-#define	F367TER_TPS_CONST	0xf0a80003
-
-/* TPS_RCVD3 */
-#define	R367TER_TPS_RCVD3	0xf0a9
-#define	F367TER_TPS_LPCODE	0xf0a90070
-#define	F367TER_TPS_HPCODE	0xf0a90007
-
-/* TPS_RCVD4 */
-#define	R367TER_TPS_RCVD4	0xf0aa
-#define	F367TER_TPS_GUARD	0xf0aa0030
-#define	F367TER_TPS_MODE	0xf0aa0003
-
-/* TPS_ID_CELL1 */
-#define	R367TER_TPS_ID_CELL1	0xf0ab
-#define	F367TER_TPS_ID_CELL_LO	0xf0ab00ff
-
-/* TPS_ID_CELL2 */
-#define	R367TER_TPS_ID_CELL2	0xf0ac
-#define	F367TER_TPS_ID_CELL_HI	0xf0ac00ff
-
-/* TPS_RCVD5_SET1 */
-#define	R367TER_TPS_RCVD5_SET1	0xf0ad
-#define	F367TER_TPS_NA	0xf0ad00fC
-#define	F367TER_TPS_SETFRAME	0xf0ad0003
-
-/* TPS_SET2 */
-#define	R367TER_TPS_SET2	0xf0ae
-#define	F367TER_TPS_SETHIERMODE	0xf0ae0070
-#define	F367TER_TPS_SETCONST	0xf0ae0003
-
-/* TPS_SET3 */
-#define	R367TER_TPS_SET3	0xf0af
-#define	F367TER_TPS_SETLPCODE	0xf0af0070
-#define	F367TER_TPS_SETHPCODE	0xf0af0007
-
-/* TPS_CTL */
-#define	R367TER_TPS_CTL	0xf0b0
-#define	F367TER_TPS_IMM	0xf0b00004
-#define	F367TER_TPS_BCHDIS	0xf0b00002
-#define	F367TER_TPS_UPDDIS	0xf0b00001
-
-/* CTL_FFTOSNUM */
-#define	R367TER_CTL_FFTOSNUM	0xf0b1
-#define	F367TER_SYMBOL_NUMBER	0xf0b1007f
-
-/* TESTSELECT */
-#define	R367TER_TESTSELECT	0xf0b2
-#define	F367TER_TEST_SELECT	0xf0b2001f
-
-/* MSC_REV */
-#define	R367TER_MSC_REV	0xf0b3
-#define	F367TER_REV_NUMBER	0xf0b300ff
-
-/* PIR_CTL */
-#define	R367TER_PIR_CTL	0xf0b4
-#define	F367TER_FREEZE	0xf0b40001
-
-/* SNR_CARRIER1 */
-#define	R367TER_SNR_CARRIER1	0xf0b5
-#define	F367TER_SNR_CARRIER_LO	0xf0b500ff
-
-/* SNR_CARRIER2 */
-#define	R367TER_SNR_CARRIER2	0xf0b6
-#define	F367TER_MEAN	0xf0b600c0
-#define	F367TER_SNR_CARRIER_HI	0xf0b6001f
-
-/* PPM_CPAMP */
-#define	R367TER_PPM_CPAMP	0xf0b7
-#define	F367TER_PPM_CPC	0xf0b700ff
-
-/* TSM_AP0 */
-#define	R367TER_TSM_AP0	0xf0b8
-#define	F367TER_ADDRESS_BYTE_0	0xf0b800ff
-
-/* TSM_AP1 */
-#define	R367TER_TSM_AP1	0xf0b9
-#define	F367TER_ADDRESS_BYTE_1	0xf0b900ff
-
-/* TSM_AP2 */
-#define	R367TER_TSM_AP2	0xf0bA
-#define	F367TER_DATA_BYTE_0	0xf0ba00ff
-
-/* TSM_AP3 */
-#define	R367TER_TSM_AP3	0xf0bB
-#define	F367TER_DATA_BYTE_1	0xf0bb00ff
-
-/* TSM_AP4 */
-#define	R367TER_TSM_AP4	0xf0bC
-#define	F367TER_DATA_BYTE_2	0xf0bc00ff
-
-/* TSM_AP5 */
-#define	R367TER_TSM_AP5	0xf0bD
-#define	F367TER_DATA_BYTE_3	0xf0bd00ff
-
-/* TSM_AP6 */
-#define	R367TER_TSM_AP6	0xf0bE
-#define	F367TER_TSM_AP_6	0xf0be00ff
-
-/* TSM_AP7 */
-#define	R367TER_TSM_AP7	0xf0bF
-#define	F367TER_MEM_SELECT_BYTE	0xf0bf00ff
-
-/* TSTRES */
-#define	R367TER_TSTRES	0xf0c0
-#define	F367TER_FRES_DISPLAY	0xf0c00080
-#define	F367TER_FRES_FIFO_AD	0xf0c00020
-#define	F367TER_FRESRS	0xf0c00010
-#define	F367TER_FRESACS	0xf0c00008
-#define	F367TER_FRESFEC	0xf0c00004
-#define	F367TER_FRES_PRIF	0xf0c00002
-#define	F367TER_FRESCORE	0xf0c00001
-
-/* ANACTRL */
-#define	R367TER_ANACTRL	0xf0c1
-#define	F367TER_BYPASS_XTAL	0xf0c10040
-#define	F367TER_BYPASS_PLLXN	0xf0c1000c
-#define	F367TER_DIS_PAD_OSC	0xf0c10002
-#define	F367TER_STDBY_PLLXN	0xf0c10001
-
-/* TSTBUS */
-#define	R367TER_TSTBUS	0xf0c2
-#define	F367TER_TS_BYTE_CLK_INV	0xf0c20080
-#define	F367TER_CFG_IP	0xf0c20070
-#define	F367TER_CFG_TST	0xf0c2000f
-
-/* TSTRATE */
-#define	R367TER_TSTRATE	0xf0c6
-#define	F367TER_FORCEPHA	0xf0c60080
-#define	F367TER_FNEWPHA	0xf0c60010
-#define	F367TER_FROT90	0xf0c60008
-#define	F367TER_FR	0xf0c60007
-
-/* CONSTMODE */
-#define	R367TER_CONSTMODE	0xf0cb
-#define	F367TER_TST_PRIF	0xf0cb00e0
-#define	F367TER_CAR_TYPE	0xf0cb0018
-#define	F367TER_CONST_MODE	0xf0cb0003
-
-/* CONSTCARR1 */
-#define	R367TER_CONSTCARR1	0xf0cc
-#define	F367TER_CONST_CARR_LO	0xf0cc00ff
-
-/* CONSTCARR2 */
-#define	R367TER_CONSTCARR2	0xf0cd
-#define	F367TER_CONST_CARR_HI	0xf0cd001f
-
-/* ICONSTEL */
-#define	R367TER_ICONSTEL	0xf0ce
-#define	F367TER_PICONSTEL	0xf0ce00ff
-
-/* QCONSTEL */
-#define	R367TER_QCONSTEL	0xf0cf
-#define	F367TER_PQCONSTEL	0xf0cf00ff
-
-/* TSTBISTRES0 */
-#define	R367TER_TSTBISTRES0	0xf0d0
-#define	F367TER_BEND_PPM	0xf0d00080
-#define	F367TER_BBAD_PPM	0xf0d00040
-#define	F367TER_BEND_FFTW	0xf0d00020
-#define	F367TER_BBAD_FFTW	0xf0d00010
-#define	F367TER_BEND_FFT_BUF	0xf0d00008
-#define	F367TER_BBAD_FFT_BUF	0xf0d00004
-#define	F367TER_BEND_SYR	0xf0d00002
-#define	F367TER_BBAD_SYR	0xf0d00001
-
-/* TSTBISTRES1 */
-#define	R367TER_TSTBISTRES1	0xf0d1
-#define	F367TER_BEND_CHC_CP	0xf0d10080
-#define	F367TER_BBAD_CHC_CP	0xf0d10040
-#define	F367TER_BEND_CHCI	0xf0d10020
-#define	F367TER_BBAD_CHCI	0xf0d10010
-#define	F367TER_BEND_BDI	0xf0d10008
-#define	F367TER_BBAD_BDI	0xf0d10004
-#define	F367TER_BEND_SDI	0xf0d10002
-#define	F367TER_BBAD_SDI	0xf0d10001
-
-/* TSTBISTRES2 */
-#define	R367TER_TSTBISTRES2	0xf0d2
-#define	F367TER_BEND_CHC_INC	0xf0d20080
-#define	F367TER_BBAD_CHC_INC	0xf0d20040
-#define	F367TER_BEND_CHC_SPP	0xf0d20020
-#define	F367TER_BBAD_CHC_SPP	0xf0d20010
-#define	F367TER_BEND_CHC_CPP	0xf0d20008
-#define	F367TER_BBAD_CHC_CPP	0xf0d20004
-#define	F367TER_BEND_CHC_SP	0xf0d20002
-#define	F367TER_BBAD_CHC_SP	0xf0d20001
-
-/* TSTBISTRES3 */
-#define	R367TER_TSTBISTRES3	0xf0d3
-#define	F367TER_BEND_QAM	0xf0d30080
-#define	F367TER_BBAD_QAM	0xf0d30040
-#define	F367TER_BEND_SFEC_VIT	0xf0d30020
-#define	F367TER_BBAD_SFEC_VIT	0xf0d30010
-#define	F367TER_BEND_SFEC_DLINE	0xf0d30008
-#define	F367TER_BBAD_SFEC_DLINE	0xf0d30004
-#define	F367TER_BEND_SFEC_HW	0xf0d30002
-#define	F367TER_BBAD_SFEC_HW	0xf0d30001
-
-/* RF_AGC1 */
-#define	R367TER_RF_AGC1	0xf0d4
-#define	F367TER_RF_AGC1_LEVEL_HI	0xf0d400ff
-
-/* RF_AGC2 */
-#define	R367TER_RF_AGC2	0xf0d5
-#define	F367TER_REF_ADGP	0xf0d50080
-#define	F367TER_STDBY_ADCGP	0xf0d50020
-#define	F367TER_CHANNEL_SEL	0xf0d5001c
-#define	F367TER_RF_AGC1_LEVEL_LO	0xf0d50003
-
-/* ANADIGCTRL */
-#define	R367TER_ANADIGCTRL	0xf0d7
-#define	F367TER_SEL_CLKDEM	0xf0d70020
-#define	F367TER_EN_BUFFER_Q	0xf0d70010
-#define	F367TER_EN_BUFFER_I	0xf0d70008
-#define	F367TER_ADC_RIS_EGDE	0xf0d70004
-#define	F367TER_SGN_ADC	0xf0d70002
-#define	F367TER_SEL_AD12_SYNC	0xf0d70001
-
-/* PLLMDIV */
-#define	R367TER_PLLMDIV	0xf0d8
-#define	F367TER_PLL_MDIV	0xf0d800ff
-
-/* PLLNDIV */
-#define	R367TER_PLLNDIV	0xf0d9
-#define	F367TER_PLL_NDIV	0xf0d900ff
-
-/* PLLSETUP */
-#define	R367TER_PLLSETUP	0xf0dA
-#define	F367TER_PLL_PDIV	0xf0da0070
-#define	F367TER_PLL_KDIV	0xf0da000f
-
-/* DUAL_AD12 */
-#define	R367TER_DUAL_AD12	0xf0dB
-#define	F367TER_FS20M	0xf0db0020
-#define	F367TER_FS50M	0xf0db0010
-#define	F367TER_INMODe0	0xf0db0008
-#define	F367TER_POFFQ	0xf0db0004
-#define	F367TER_POFFI	0xf0db0002
-#define	F367TER_INMODE1	0xf0db0001
-
-/* TSTBIST */
-#define	R367TER_TSTBIST	0xf0dC
-#define	F367TER_TST_BYP_CLK	0xf0dc0080
-#define	F367TER_TST_GCLKENA_STD	0xf0dc0040
-#define	F367TER_TST_GCLKENA	0xf0dc0020
-#define	F367TER_TST_MEMBIST	0xf0dc001f
-
-/* PAD_COMP_CTRL */
-#define	R367TER_PAD_COMP_CTRL	0xf0dD
-#define	F367TER_COMPTQ	0xf0dd0010
-#define	F367TER_COMPEN	0xf0dd0008
-#define	F367TER_FREEZE2	0xf0dd0004
-#define	F367TER_SLEEP_INHBT	0xf0dd0002
-#define	F367TER_CHIP_SLEEP	0xf0dd0001
-
-/* PAD_COMP_WR */
-#define	R367TER_PAD_COMP_WR	0xf0de
-#define	F367TER_WR_ASRC	0xf0de007f
-
-/* PAD_COMP_RD */
-#define	R367TER_PAD_COMP_RD	0xf0df
-#define	F367TER_COMPOK	0xf0df0080
-#define	F367TER_RD_ASRC	0xf0df007f
-
-/* SYR_TARGET_FFTADJT_MSB */
-#define	R367TER_SYR_TARGET_FFTADJT_MSB	0xf100
-#define	F367TER_SYR_START	0xf1000080
-#define	F367TER_SYR_TARGET_FFTADJ_HI	0xf100000f
-
-/* SYR_TARGET_FFTADJT_LSB */
-#define	R367TER_SYR_TARGET_FFTADJT_LSB	0xf101
-#define	F367TER_SYR_TARGET_FFTADJ_LO	0xf10100ff
-
-/* SYR_TARGET_CHCADJT_MSB */
-#define	R367TER_SYR_TARGET_CHCADJT_MSB	0xf102
-#define	F367TER_SYR_TARGET_CHCADJ_HI	0xf102000f
-
-/* SYR_TARGET_CHCADJT_LSB */
-#define	R367TER_SYR_TARGET_CHCADJT_LSB	0xf103
-#define	F367TER_SYR_TARGET_CHCADJ_LO	0xf10300ff
-
-/* SYR_FLAG */
-#define	R367TER_SYR_FLAG	0xf104
-#define	F367TER_TRIG_FLG1	0xf1040080
-#define	F367TER_TRIG_FLG0	0xf1040040
-#define	F367TER_FFT_FLG1	0xf1040008
-#define	F367TER_FFT_FLG0	0xf1040004
-#define	F367TER_CHC_FLG1	0xf1040002
-#define	F367TER_CHC_FLG0	0xf1040001
-
-/* CRL_TARGET1 */
-#define	R367TER_CRL_TARGET1	0xf105
-#define	F367TER_CRL_START	0xf1050080
-#define	F367TER_CRL_TARGET_VHI	0xf105000f
-
-/* CRL_TARGET2 */
-#define	R367TER_CRL_TARGET2	0xf106
-#define	F367TER_CRL_TARGET_HI	0xf10600ff
-
-/* CRL_TARGET3 */
-#define	R367TER_CRL_TARGET3	0xf107
-#define	F367TER_CRL_TARGET_LO	0xf10700ff
-
-/* CRL_TARGET4 */
-#define	R367TER_CRL_TARGET4	0xf108
-#define	F367TER_CRL_TARGET_VLO	0xf10800ff
-
-/* CRL_FLAG */
-#define	R367TER_CRL_FLAG	0xf109
-#define	F367TER_CRL_FLAG1	0xf1090002
-#define	F367TER_CRL_FLAG0	0xf1090001
-
-/* TRL_TARGET1 */
-#define	R367TER_TRL_TARGET1	0xf10a
-#define	F367TER_TRL_TARGET_HI	0xf10a00ff
-
-/* TRL_TARGET2 */
-#define	R367TER_TRL_TARGET2	0xf10b
-#define	F367TER_TRL_TARGET_LO	0xf10b00ff
-
-/* TRL_CHC */
-#define	R367TER_TRL_CHC	0xf10c
-#define	F367TER_TRL_START	0xf10c0080
-#define	F367TER_CHC_START	0xf10c0040
-#define	F367TER_TRL_FLAG1	0xf10c0002
-#define	F367TER_TRL_FLAG0	0xf10c0001
-
-/* CHC_SNR_TARG */
-#define	R367TER_CHC_SNR_TARG	0xf10d
-#define	F367TER_CHC_SNR_TARGET	0xf10d00ff
-
-/* TOP_TRACK */
-#define	R367TER_TOP_TRACK	0xf10e
-#define	F367TER_TOP_START	0xf10e0080
-#define	F367TER_FIRST_FLAG	0xf10e0070
-#define	F367TER_TOP_FLAG1	0xf10e0008
-#define	F367TER_TOP_FLAG0	0xf10e0004
-#define	F367TER_CHC_FLAG1	0xf10e0002
-#define	F367TER_CHC_FLAG0	0xf10e0001
-
-/* TRACKER_FREE1 */
-#define	R367TER_TRACKER_FREE1	0xf10f
-#define	F367TER_TRACKER_FREE_1	0xf10f00ff
-
-/* ERROR_CRL1 */
-#define	R367TER_ERROR_CRL1	0xf110
-#define	F367TER_ERROR_CRL_VHI	0xf11000ff
-
-/* ERROR_CRL2 */
-#define	R367TER_ERROR_CRL2	0xf111
-#define	F367TER_ERROR_CRL_HI	0xf11100ff
-
-/* ERROR_CRL3 */
-#define	R367TER_ERROR_CRL3	0xf112
-#define	F367TER_ERROR_CRL_LOI	0xf11200ff
-
-/* ERROR_CRL4 */
-#define	R367TER_ERROR_CRL4	0xf113
-#define	F367TER_ERROR_CRL_VLO	0xf11300ff
-
-/* DEC_NCO1 */
-#define	R367TER_DEC_NCO1	0xf114
-#define	F367TER_DEC_NCO_VHI	0xf11400ff
-
-/* DEC_NCO2 */
-#define	R367TER_DEC_NCO2	0xf115
-#define	F367TER_DEC_NCO_HI	0xf11500ff
-
-/* DEC_NCO3 */
-#define	R367TER_DEC_NCO3	0xf116
-#define	F367TER_DEC_NCO_LO	0xf11600ff
-
-/* SNR */
-#define	R367TER_SNR	0xf117
-#define	F367TER_SNRATIO	0xf11700ff
-
-/* SYR_FFTADJ1 */
-#define	R367TER_SYR_FFTADJ1	0xf118
-#define	F367TER_SYR_FFTADJ_HI	0xf11800ff
-
-/* SYR_FFTADJ2 */
-#define	R367TER_SYR_FFTADJ2	0xf119
-#define	F367TER_SYR_FFTADJ_LO	0xf11900ff
-
-/* SYR_CHCADJ1 */
-#define	R367TER_SYR_CHCADJ1	0xf11a
-#define	F367TER_SYR_CHCADJ_HI	0xf11a00ff
-
-/* SYR_CHCADJ2 */
-#define	R367TER_SYR_CHCADJ2	0xf11b
-#define	F367TER_SYR_CHCADJ_LO	0xf11b00ff
-
-/* SYR_OFF */
-#define	R367TER_SYR_OFF	0xf11c
-#define	F367TER_SYR_OFFSET	0xf11c00ff
-
-/* PPM_OFFSET1 */
-#define	R367TER_PPM_OFFSET1	0xf11d
-#define	F367TER_PPM_OFFSET_HI	0xf11d00ff
-
-/* PPM_OFFSET2 */
-#define	R367TER_PPM_OFFSET2	0xf11e
-#define	F367TER_PPM_OFFSET_LO	0xf11e00ff
-
-/* TRACKER_FREE2 */
-#define	R367TER_TRACKER_FREE2	0xf11f
-#define	F367TER_TRACKER_FREE_2	0xf11f00ff
-
-/* DEBG_LT10 */
-#define	R367TER_DEBG_LT10	0xf120
-#define	F367TER_DEBUG_LT10	0xf12000ff
-
-/* DEBG_LT11 */
-#define	R367TER_DEBG_LT11	0xf121
-#define	F367TER_DEBUG_LT11	0xf12100ff
-
-/* DEBG_LT12 */
-#define	R367TER_DEBG_LT12	0xf122
-#define	F367TER_DEBUG_LT12	0xf12200ff
-
-/* DEBG_LT13 */
-#define	R367TER_DEBG_LT13	0xf123
-#define	F367TER_DEBUG_LT13	0xf12300ff
-
-/* DEBG_LT14 */
-#define	R367TER_DEBG_LT14	0xf124
-#define	F367TER_DEBUG_LT14	0xf12400ff
-
-/* DEBG_LT15 */
-#define	R367TER_DEBG_LT15	0xf125
-#define	F367TER_DEBUG_LT15	0xf12500ff
-
-/* DEBG_LT16 */
-#define	R367TER_DEBG_LT16	0xf126
-#define	F367TER_DEBUG_LT16	0xf12600ff
-
-/* DEBG_LT17 */
-#define	R367TER_DEBG_LT17	0xf127
-#define	F367TER_DEBUG_LT17	0xf12700ff
-
-/* DEBG_LT18 */
-#define	R367TER_DEBG_LT18	0xf128
-#define	F367TER_DEBUG_LT18	0xf12800ff
-
-/* DEBG_LT19 */
-#define	R367TER_DEBG_LT19	0xf129
-#define	F367TER_DEBUG_LT19	0xf12900ff
-
-/* DEBG_LT1a */
-#define	R367TER_DEBG_LT1A	0xf12a
-#define	F367TER_DEBUG_LT1A	0xf12a00ff
-
-/* DEBG_LT1b */
-#define	R367TER_DEBG_LT1B	0xf12b
-#define	F367TER_DEBUG_LT1B	0xf12b00ff
-
-/* DEBG_LT1c */
-#define	R367TER_DEBG_LT1C	0xf12c
-#define	F367TER_DEBUG_LT1C	0xf12c00ff
-
-/* DEBG_LT1D */
-#define	R367TER_DEBG_LT1D	0xf12d
-#define	F367TER_DEBUG_LT1D	0xf12d00ff
-
-/* DEBG_LT1E */
-#define	R367TER_DEBG_LT1E	0xf12e
-#define	F367TER_DEBUG_LT1E	0xf12e00ff
-
-/* DEBG_LT1F */
-#define	R367TER_DEBG_LT1F	0xf12f
-#define	F367TER_DEBUG_LT1F	0xf12f00ff
-
-/* RCCFGH */
-#define	R367TER_RCCFGH	0xf200
-#define	F367TER_TSRCFIFO_DVBCI	0xf2000080
-#define	F367TER_TSRCFIFO_SERIAL	0xf2000040
-#define	F367TER_TSRCFIFO_DISABLE	0xf2000020
-#define	F367TER_TSFIFO_2TORC	0xf2000010
-#define	F367TER_TSRCFIFO_HSGNLOUT	0xf2000008
-#define	F367TER_TSRCFIFO_ERRMODE	0xf2000006
-#define	F367TER_RCCFGH_0	0xf2000001
-
-/* RCCFGM */
-#define	R367TER_RCCFGM	0xf201
-#define	F367TER_TSRCFIFO_MANSPEED	0xf20100c0
-#define	F367TER_TSRCFIFO_PERMDATA	0xf2010020
-#define	F367TER_TSRCFIFO_NONEWSGNL	0xf2010010
-#define	F367TER_RCBYTE_OVERSAMPLING	0xf201000e
-#define	F367TER_TSRCFIFO_INVDATA	0xf2010001
-
-/* RCCFGL */
-#define	R367TER_RCCFGL	0xf202
-#define	F367TER_TSRCFIFO_BCLKDEL1cK	0xf20200c0
-#define	F367TER_RCCFGL_5	0xf2020020
-#define	F367TER_TSRCFIFO_DUTY50	0xf2020010
-#define	F367TER_TSRCFIFO_NSGNL2dATA	0xf2020008
-#define	F367TER_TSRCFIFO_DISSERMUX	0xf2020004
-#define	F367TER_RCCFGL_1	0xf2020002
-#define	F367TER_TSRCFIFO_STOPCKDIS	0xf2020001
-
-/* RCINSDELH */
-#define	R367TER_RCINSDELH	0xf203
-#define	F367TER_TSRCDEL_SYNCBYTE	0xf2030080
-#define	F367TER_TSRCDEL_XXHEADER	0xf2030040
-#define	F367TER_TSRCDEL_BBHEADER	0xf2030020
-#define	F367TER_TSRCDEL_DATAFIELD	0xf2030010
-#define	F367TER_TSRCINSDEL_ISCR	0xf2030008
-#define	F367TER_TSRCINSDEL_NPD	0xf2030004
-#define	F367TER_TSRCINSDEL_RSPARITY	0xf2030002
-#define	F367TER_TSRCINSDEL_CRC8	0xf2030001
-
-/* RCINSDELM */
-#define	R367TER_RCINSDELM	0xf204
-#define	F367TER_TSRCINS_BBPADDING	0xf2040080
-#define	F367TER_TSRCINS_BCHFEC	0xf2040040
-#define	F367TER_TSRCINS_LDPCFEC	0xf2040020
-#define	F367TER_TSRCINS_EMODCOD	0xf2040010
-#define	F367TER_TSRCINS_TOKEN	0xf2040008
-#define	F367TER_TSRCINS_XXXERR	0xf2040004
-#define	F367TER_TSRCINS_MATYPE	0xf2040002
-#define	F367TER_TSRCINS_UPL	0xf2040001
-
-/* RCINSDELL */
-#define	R367TER_RCINSDELL	0xf205
-#define	F367TER_TSRCINS_DFL	0xf2050080
-#define	F367TER_TSRCINS_SYNCD	0xf2050040
-#define	F367TER_TSRCINS_BLOCLEN	0xf2050020
-#define	F367TER_TSRCINS_SIGPCOUNT	0xf2050010
-#define	F367TER_TSRCINS_FIFO	0xf2050008
-#define	F367TER_TSRCINS_REALPACK	0xf2050004
-#define	F367TER_TSRCINS_TSCONFIG	0xf2050002
-#define	F367TER_TSRCINS_LATENCY	0xf2050001
-
-/* RCSTATUS */
-#define	R367TER_RCSTATUS	0xf206
-#define	F367TER_TSRCFIFO_LINEOK	0xf2060080
-#define	F367TER_TSRCFIFO_ERROR	0xf2060040
-#define	F367TER_TSRCFIFO_DATA7	0xf2060020
-#define	F367TER_RCSTATUS_4	0xf2060010
-#define	F367TER_TSRCFIFO_DEMODSEL	0xf2060008
-#define	F367TER_TSRC1FIFOSPEED_STORE	0xf2060004
-#define	F367TER_RCSTATUS_1	0xf2060002
-#define	F367TER_TSRCSERIAL_IMPOSSIBLE	0xf2060001
-
-/* RCSPEED */
-#define	R367TER_RCSPEED	0xf207
-#define	F367TER_TSRCFIFO_OUTSPEED	0xf20700ff
-
-/* RCDEBUGM */
-#define	R367TER_RCDEBUGM	0xf208
-#define	F367TER_SD_UNSYNC	0xf2080080
-#define	F367TER_ULFLOCK_DETECTM	0xf2080040
-#define	F367TER_SUL_SELECTOS	0xf2080020
-#define	F367TER_DILUL_NOSCRBLE	0xf2080010
-#define	F367TER_NUL_SCRB	0xf2080008
-#define	F367TER_UL_SCRB	0xf2080004
-#define	F367TER_SCRAULBAD	0xf2080002
-#define	F367TER_SCRAUL_UNSYNC	0xf2080001
-
-/* RCDEBUGL */
-#define	R367TER_RCDEBUGL	0xf209
-#define	F367TER_RS_ERR	0xf2090080
-#define	F367TER_LLFLOCK_DETECTM	0xf2090040
-#define	F367TER_NOT_SUL_SELECTOS	0xf2090020
-#define	F367TER_DILLL_NOSCRBLE	0xf2090010
-#define	F367TER_NLL_SCRB	0xf2090008
-#define	F367TER_LL_SCRB	0xf2090004
-#define	F367TER_SCRALLBAD	0xf2090002
-#define	F367TER_SCRALL_UNSYNC	0xf2090001
-
-/* RCOBSCFG */
-#define	R367TER_RCOBSCFG	0xf20a
-#define	F367TER_TSRCFIFO_OBSCFG	0xf20a00ff
-
-/* RCOBSM */
-#define	R367TER_RCOBSM	0xf20b
-#define	F367TER_TSRCFIFO_OBSDATA_HI	0xf20b00ff
-
-/* RCOBSL */
-#define	R367TER_RCOBSL	0xf20c
-#define	F367TER_TSRCFIFO_OBSDATA_LO	0xf20c00ff
-
-/* RCFECSPY */
-#define	R367TER_RCFECSPY	0xf210
-#define	F367TER_SPYRC_ENABLE	0xf2100080
-#define	F367TER_RCNO_SYNCBYTE	0xf2100040
-#define	F367TER_RCSERIAL_MODE	0xf2100020
-#define	F367TER_RCUNUSUAL_PACKET	0xf2100010
-#define	F367TER_BERRCMETER_DATAMODE	0xf210000c
-#define	F367TER_BERRCMETER_LMODE	0xf2100002
-#define	F367TER_BERRCMETER_RESET	0xf2100001
-
-/* RCFSPYCFG */
-#define	R367TER_RCFSPYCFG	0xf211
-#define	F367TER_FECSPYRC_INPUT	0xf21100c0
-#define	F367TER_RCRST_ON_ERROR	0xf2110020
-#define	F367TER_RCONE_SHOT	0xf2110010
-#define	F367TER_RCI2C_MODE	0xf211000c
-#define	F367TER_SPYRC_HSTERESIS	0xf2110003
-
-/* RCFSPYDATA */
-#define	R367TER_RCFSPYDATA	0xf212
-#define	F367TER_SPYRC_STUFFING	0xf2120080
-#define	F367TER_RCNOERR_PKTJITTER	0xf2120040
-#define	F367TER_SPYRC_CNULLPKT	0xf2120020
-#define	F367TER_SPYRC_OUTDATA_MODE	0xf212001f
-
-/* RCFSPYOUT */
-#define	R367TER_RCFSPYOUT	0xf213
-#define	F367TER_FSPYRC_DIRECT	0xf2130080
-#define	F367TER_RCFSPYOUT_6	0xf2130040
-#define	F367TER_SPYRC_OUTDATA_BUS	0xf2130038
-#define	F367TER_RCSTUFF_MODE	0xf2130007
-
-/* RCFSTATUS */
-#define	R367TER_RCFSTATUS	0xf214
-#define	F367TER_SPYRC_ENDSIM	0xf2140080
-#define	F367TER_RCVALID_SIM	0xf2140040
-#define	F367TER_RCFOUND_SIGNAL	0xf2140020
-#define	F367TER_RCDSS_SYNCBYTE	0xf2140010
-#define	F367TER_RCRESULT_STATE	0xf214000f
-
-/* RCFGOODPACK */
-#define	R367TER_RCFGOODPACK	0xf215
-#define	F367TER_RCGOOD_PACKET	0xf21500ff
-
-/* RCFPACKCNT */
-#define	R367TER_RCFPACKCNT	0xf216
-#define	F367TER_RCPACKET_COUNTER	0xf21600ff
-
-/* RCFSPYMISC */
-#define	R367TER_RCFSPYMISC	0xf217
-#define	F367TER_RCLABEL_COUNTER	0xf21700ff
-
-/* RCFBERCPT4 */
-#define	R367TER_RCFBERCPT4	0xf218
-#define	F367TER_FBERRCMETER_CPT_MMMMSB	0xf21800ff
-
-/* RCFBERCPT3 */
-#define	R367TER_RCFBERCPT3	0xf219
-#define	F367TER_FBERRCMETER_CPT_MMMSB	0xf21900ff
-
-/* RCFBERCPT2 */
-#define	R367TER_RCFBERCPT2	0xf21a
-#define	F367TER_FBERRCMETER_CPT_MMSB	0xf21a00ff
-
-/* RCFBERCPT1 */
-#define	R367TER_RCFBERCPT1	0xf21b
-#define	F367TER_FBERRCMETER_CPT_MSB	0xf21b00ff
-
-/* RCFBERCPT0 */
-#define	R367TER_RCFBERCPT0	0xf21c
-#define	F367TER_FBERRCMETER_CPT_LSB	0xf21c00ff
-
-/* RCFBERERR2 */
-#define	R367TER_RCFBERERR2	0xf21d
-#define	F367TER_FBERRCMETER_ERR_HI	0xf21d00ff
-
-/* RCFBERERR1 */
-#define	R367TER_RCFBERERR1	0xf21e
-#define	F367TER_FBERRCMETER_ERR	0xf21e00ff
-
-/* RCFBERERR0 */
-#define	R367TER_RCFBERERR0	0xf21f
-#define	F367TER_FBERRCMETER_ERR_LO	0xf21f00ff
-
-/* RCFSTATESM */
-#define	R367TER_RCFSTATESM	0xf220
-#define	F367TER_RCRSTATE_F	0xf2200080
-#define	F367TER_RCRSTATE_E	0xf2200040
-#define	F367TER_RCRSTATE_D	0xf2200020
-#define	F367TER_RCRSTATE_C	0xf2200010
-#define	F367TER_RCRSTATE_B	0xf2200008
-#define	F367TER_RCRSTATE_A	0xf2200004
-#define	F367TER_RCRSTATE_9	0xf2200002
-#define	F367TER_RCRSTATE_8	0xf2200001
-
-/* RCFSTATESL */
-#define	R367TER_RCFSTATESL	0xf221
-#define	F367TER_RCRSTATE_7	0xf2210080
-#define	F367TER_RCRSTATE_6	0xf2210040
-#define	F367TER_RCRSTATE_5	0xf2210020
-#define	F367TER_RCRSTATE_4	0xf2210010
-#define	F367TER_RCRSTATE_3	0xf2210008
-#define	F367TER_RCRSTATE_2	0xf2210004
-#define	F367TER_RCRSTATE_1	0xf2210002
-#define	F367TER_RCRSTATE_0	0xf2210001
-
-/* RCFSPYBER */
-#define	R367TER_RCFSPYBER	0xf222
-#define	F367TER_RCFSPYBER_7	0xf2220080
-#define	F367TER_SPYRCOBS_XORREAD	0xf2220040
-#define	F367TER_FSPYRCBER_OBSMODE	0xf2220020
-#define	F367TER_FSPYRCBER_SYNCBYT	0xf2220010
-#define	F367TER_FSPYRCBER_UNSYNC	0xf2220008
-#define	F367TER_FSPYRCBER_CTIME	0xf2220007
-
-/* RCFSPYDISTM */
-#define	R367TER_RCFSPYDISTM	0xf223
-#define	F367TER_RCPKTTIME_DISTANCE_HI	0xf22300ff
-
-/* RCFSPYDISTL */
-#define	R367TER_RCFSPYDISTL	0xf224
-#define	F367TER_RCPKTTIME_DISTANCE_LO	0xf22400ff
-
-/* RCFSPYOBS7 */
-#define	R367TER_RCFSPYOBS7	0xf228
-#define	F367TER_RCSPYOBS_SPYFAIL	0xf2280080
-#define	F367TER_RCSPYOBS_SPYFAIL1	0xf2280040
-#define	F367TER_RCSPYOBS_ERROR	0xf2280020
-#define	F367TER_RCSPYOBS_STROUT	0xf2280010
-#define	F367TER_RCSPYOBS_RESULTSTATE1	0xf228000f
-
-/* RCFSPYOBS6 */
-#define	R367TER_RCFSPYOBS6	0xf229
-#define	F367TER_RCSPYOBS_RESULTSTATe0	0xf22900f0
-#define	F367TER_RCSPYOBS_RESULTSTATEM1	0xf229000f
-
-/* RCFSPYOBS5 */
-#define	R367TER_RCFSPYOBS5	0xf22a
-#define	F367TER_RCSPYOBS_BYTEOFPACKET1	0xf22a00ff
-
-/* RCFSPYOBS4 */
-#define	R367TER_RCFSPYOBS4	0xf22b
-#define	F367TER_RCSPYOBS_BYTEVALUE1	0xf22b00ff
-
-/* RCFSPYOBS3 */
-#define	R367TER_RCFSPYOBS3	0xf22c
-#define	F367TER_RCSPYOBS_DATA1	0xf22c00ff
-
-/* RCFSPYOBS2 */
-#define	R367TER_RCFSPYOBS2	0xf22d
-#define	F367TER_RCSPYOBS_DATa0	0xf22d00ff
-
-/* RCFSPYOBS1 */
-#define	R367TER_RCFSPYOBS1	0xf22e
-#define	F367TER_RCSPYOBS_DATAM1	0xf22e00ff
-
-/* RCFSPYOBS0 */
-#define	R367TER_RCFSPYOBS0	0xf22f
-#define	F367TER_RCSPYOBS_DATAM2	0xf22f00ff
-
-/* TSGENERAL */
-#define	R367TER_TSGENERAL	0xf230
-#define	F367TER_TSGENERAL_7	0xf2300080
-#define	F367TER_TSGENERAL_6	0xf2300040
-#define	F367TER_TSFIFO_BCLK1aLL	0xf2300020
-#define	F367TER_TSGENERAL_4	0xf2300010
-#define	F367TER_MUXSTREAM_OUTMODE	0xf2300008
-#define	F367TER_TSFIFO_PERMPARAL	0xf2300006
-#define	F367TER_RST_REEDSOLO	0xf2300001
-
-/* RC1SPEED */
-#define	R367TER_RC1SPEED	0xf231
-#define	F367TER_TSRCFIFO1_OUTSPEED	0xf23100ff
-
-/* TSGSTATUS */
-#define	R367TER_TSGSTATUS	0xf232
-#define	F367TER_TSGSTATUS_7	0xf2320080
-#define	F367TER_TSGSTATUS_6	0xf2320040
-#define	F367TER_RSMEM_FULL	0xf2320020
-#define	F367TER_RS_MULTCALC	0xf2320010
-#define	F367TER_RSIN_OVERTIME	0xf2320008
-#define	F367TER_TSFIFO3_DEMODSEL	0xf2320004
-#define	F367TER_TSFIFO2_DEMODSEL	0xf2320002
-#define	F367TER_TSFIFO1_DEMODSEL	0xf2320001
-
-
-/* FECM */
-#define	R367TER_FECM	0xf233
-#define	F367TER_DSS_DVB	0xf2330080
-#define	F367TER_DEMOD_BYPASS	0xf2330040
-#define	F367TER_CMP_SLOWMODE	0xf2330020
-#define	F367TER_DSS_SRCH	0xf2330010
-#define	F367TER_FECM_3	0xf2330008
-#define	F367TER_DIFF_MODEVIT	0xf2330004
-#define	F367TER_SYNCVIT	0xf2330002
-#define	F367TER_I2CSYM	0xf2330001
-
-/* VTH12 */
-#define	R367TER_VTH12	0xf234
-#define	F367TER_VTH_12	0xf23400ff
-
-/* VTH23 */
-#define	R367TER_VTH23	0xf235
-#define	F367TER_VTH_23	0xf23500ff
-
-/* VTH34 */
-#define	R367TER_VTH34	0xf236
-#define	F367TER_VTH_34	0xf23600ff
-
-/* VTH56 */
-#define	R367TER_VTH56	0xf237
-#define	F367TER_VTH_56	0xf23700ff
-
-/* VTH67 */
-#define	R367TER_VTH67	0xf238
-#define	F367TER_VTH_67	0xf23800ff
-
-/* VTH78 */
-#define	R367TER_VTH78	0xf239
-#define	F367TER_VTH_78	0xf23900ff
-
-/* VITCURPUN */
-#define	R367TER_VITCURPUN	0xf23a
-#define	F367TER_VIT_MAPPING	0xf23a00e0
-#define	F367TER_VIT_CURPUN	0xf23a001f
-
-/* VERROR */
-#define	R367TER_VERROR	0xf23b
-#define	F367TER_REGERR_VIT	0xf23b00ff
-
-/* PRVIT */
-#define	R367TER_PRVIT	0xf23c
-#define	F367TER_PRVIT_7	0xf23c0080
-#define	F367TER_DIS_VTHLOCK	0xf23c0040
-#define	F367TER_E7_8VIT	0xf23c0020
-#define	F367TER_E6_7VIT	0xf23c0010
-#define	F367TER_E5_6VIT	0xf23c0008
-#define	F367TER_E3_4VIT	0xf23c0004
-#define	F367TER_E2_3VIT	0xf23c0002
-#define	F367TER_E1_2VIT	0xf23c0001
-
-/* VAVSRVIT */
-#define	R367TER_VAVSRVIT	0xf23d
-#define	F367TER_AMVIT	0xf23d0080
-#define	F367TER_FROZENVIT	0xf23d0040
-#define	F367TER_SNVIT	0xf23d0030
-#define	F367TER_TOVVIT	0xf23d000c
-#define	F367TER_HYPVIT	0xf23d0003
-
-/* VSTATUSVIT */
-#define	R367TER_VSTATUSVIT	0xf23e
-#define	F367TER_VITERBI_ON	0xf23e0080
-#define	F367TER_END_LOOPVIT	0xf23e0040
-#define	F367TER_VITERBI_DEPRF	0xf23e0020
-#define	F367TER_PRFVIT	0xf23e0010
-#define	F367TER_LOCKEDVIT	0xf23e0008
-#define	F367TER_VITERBI_DELOCK	0xf23e0004
-#define	F367TER_VIT_DEMODSEL	0xf23e0002
-#define	F367TER_VITERBI_COMPOUT	0xf23e0001
-
-/* VTHINUSE */
-#define	R367TER_VTHINUSE	0xf23f
-#define	F367TER_VIT_INUSE	0xf23f00ff
-
-/* KDIV12 */
-#define	R367TER_KDIV12	0xf240
-#define	F367TER_KDIV12_MANUAL	0xf2400080
-#define	F367TER_K_DIVIDER_12	0xf240007f
-
-/* KDIV23 */
-#define	R367TER_KDIV23	0xf241
-#define	F367TER_KDIV23_MANUAL	0xf2410080
-#define	F367TER_K_DIVIDER_23	0xf241007f
-
-/* KDIV34 */
-#define	R367TER_KDIV34	0xf242
-#define	F367TER_KDIV34_MANUAL	0xf2420080
-#define	F367TER_K_DIVIDER_34	0xf242007f
-
-/* KDIV56 */
-#define	R367TER_KDIV56	0xf243
-#define	F367TER_KDIV56_MANUAL	0xf2430080
-#define	F367TER_K_DIVIDER_56	0xf243007f
-
-/* KDIV67 */
-#define	R367TER_KDIV67	0xf244
-#define	F367TER_KDIV67_MANUAL	0xf2440080
-#define	F367TER_K_DIVIDER_67	0xf244007f
-
-/* KDIV78 */
-#define	R367TER_KDIV78	0xf245
-#define	F367TER_KDIV78_MANUAL	0xf2450080
-#define	F367TER_K_DIVIDER_78	0xf245007f
-
-/* SIGPOWER */
-#define	R367TER_SIGPOWER	0xf246
-#define	F367TER_SIGPOWER_MANUAL	0xf2460080
-#define	F367TER_SIG_POWER	0xf246007f
-
-/* DEMAPVIT */
-#define	R367TER_DEMAPVIT	0xf247
-#define	F367TER_DEMAPVIT_7	0xf2470080
-#define	F367TER_K_DIVIDER_VIT	0xf247007f
-
-/* VITSCALE */
-#define	R367TER_VITSCALE	0xf248
-#define	F367TER_NVTH_NOSRANGE	0xf2480080
-#define	F367TER_VERROR_MAXMODE	0xf2480040
-#define	F367TER_KDIV_MODE	0xf2480030
-#define	F367TER_NSLOWSN_LOCKED	0xf2480008
-#define	F367TER_DELOCK_PRFLOSS	0xf2480004
-#define	F367TER_DIS_RSFLOCK	0xf2480002
-#define	F367TER_VITSCALE_0	0xf2480001
-
-/* FFEC1PRG */
-#define	R367TER_FFEC1PRG	0xf249
-#define	F367TER_FDSS_DVB	0xf2490080
-#define	F367TER_FDSS_SRCH	0xf2490040
-#define	F367TER_FFECPROG_5	0xf2490020
-#define	F367TER_FFECPROG_4	0xf2490010
-#define	F367TER_FFECPROG_3	0xf2490008
-#define	F367TER_FFECPROG_2	0xf2490004
-#define	F367TER_FTS1_DISABLE	0xf2490002
-#define	F367TER_FTS2_DISABLE	0xf2490001
-
-/* FVITCURPUN */
-#define	R367TER_FVITCURPUN	0xf24a
-#define	F367TER_FVIT_MAPPING	0xf24a00e0
-#define	F367TER_FVIT_CURPUN	0xf24a001f
-
-/* FVERROR */
-#define	R367TER_FVERROR	0xf24b
-#define	F367TER_FREGERR_VIT	0xf24b00ff
-
-/* FVSTATUSVIT */
-#define	R367TER_FVSTATUSVIT	0xf24c
-#define	F367TER_FVITERBI_ON	0xf24c0080
-#define	F367TER_F1END_LOOPVIT	0xf24c0040
-#define	F367TER_FVITERBI_DEPRF	0xf24c0020
-#define	F367TER_FPRFVIT	0xf24c0010
-#define	F367TER_FLOCKEDVIT	0xf24c0008
-#define	F367TER_FVITERBI_DELOCK	0xf24c0004
-#define	F367TER_FVIT_DEMODSEL	0xf24c0002
-#define	F367TER_FVITERBI_COMPOUT	0xf24c0001
-
-/* DEBUG_LT1 */
-#define	R367TER_DEBUG_LT1	0xf24d
-#define	F367TER_DBG_LT1	0xf24d00ff
-
-/* DEBUG_LT2 */
-#define	R367TER_DEBUG_LT2	0xf24e
-#define	F367TER_DBG_LT2	0xf24e00ff
-
-/* DEBUG_LT3 */
-#define	R367TER_DEBUG_LT3	0xf24f
-#define	F367TER_DBG_LT3	0xf24f00ff
-
-/*	TSTSFMET */
-#define	R367TER_TSTSFMET	0xf250
-#define F367TER_TSTSFEC_METRIQUES	0xf25000ff
-
-/*	SELOUT */
-#define	R367TER_SELOUT	0xf252
-#define	F367TER_EN_SYNC	0xf2520080
-#define	F367TER_EN_TBUSDEMAP	0xf2520040
-#define	F367TER_SELOUT_5	0xf2520020
-#define	F367TER_SELOUT_4	0xf2520010
-#define	F367TER_TSTSYNCHRO_MODE	0xf2520002
-
-/*	TSYNC */
-#define R367TER_TSYNC	0xf253
-#define F367TER_CURPUN_INCMODE	0xf2530080
-#define F367TER_CERR_TSTMODE	0xf2530040
-#define F367TER_SHIFTSOF_MODE	0xf2530030
-#define F367TER_SLOWPHA_MODE	0xf2530008
-#define F367TER_PXX_BYPALL	0xf2530004
-#define F367TER_FROTA45_FIRST	0xf2530002
-#define F367TER_TST_BCHERROR	0xf2530001
-
-/*	TSTERR */
-#define R367TER_TSTERR	0xf254
-#define F367TER_TST_LONGPKT	0xf2540080
-#define F367TER_TST_ISSYION	0xf2540040
-#define F367TER_TST_NPDON	0xf2540020
-#define F367TER_TSTERR_4	0xf2540010
-#define F367TER_TRACEBACK_MODE	0xf2540008
-#define F367TER_TST_RSPARITY	0xf2540004
-#define F367TER_METRIQUE_MODE	0xf2540003
-
-/*	TSFSYNC */
-#define R367TER_TSFSYNC	0xf255
-#define F367TER_EN_SFECSYNC	0xf2550080
-#define F367TER_EN_SFECDEMAP	0xf2550040
-#define F367TER_SFCERR_TSTMODE	0xf2550020
-#define F367TER_SFECPXX_BYPALL	0xf2550010
-#define F367TER_SFECTSTSYNCHRO_MODE 0xf255000f
-
-/*	TSTSFERR */
-#define R367TER_TSTSFERR	0xf256
-#define F367TER_TSTSTERR_7	0xf2560080
-#define F367TER_TSTSTERR_6	0xf2560040
-#define F367TER_TSTSTERR_5	0xf2560020
-#define F367TER_TSTSTERR_4	0xf2560010
-#define F367TER_SFECTRACEBACK_MODE	0xf2560008
-#define F367TER_SFEC_NCONVPROG	0xf2560004
-#define F367TER_SFECMETRIQUE_MODE	0xf2560003
-
-/*	TSTTSSF1 */
-#define R367TER_TSTTSSF1	0xf258
-#define F367TER_TSTERSSF	0xf2580080
-#define F367TER_TSTTSSFEN	0xf2580040
-#define F367TER_SFEC_OUTMODE	0xf2580030
-#define F367TER_XLSF_NOFTHRESHOLD  0xf2580008
-#define F367TER_TSTTSSF_STACKSEL	0xf2580007
-
-/*	TSTTSSF2 */
-#define R367TER_TSTTSSF2	0xf259
-#define F367TER_DILSF_DBBHEADER	0xf2590080
-#define F367TER_TSTTSSF_DISBUG	0xf2590040
-#define F367TER_TSTTSSF_NOBADSTART	0xf2590020
-#define F367TER_TSTTSSF_SELECT	0xf259001f
-
-/*	TSTTSSF3 */
-#define R367TER_TSTTSSF3	0xf25a
-#define F367TER_TSTTSSF3_7	0xf25a0080
-#define F367TER_TSTTSSF3_6	0xf25a0040
-#define F367TER_TSTTSSF3_5	0xf25a0020
-#define F367TER_TSTTSSF3_4	0xf25a0010
-#define F367TER_TSTTSSF3_3	0xf25a0008
-#define F367TER_TSTTSSF3_2	0xf25a0004
-#define F367TER_TSTTSSF3_1	0xf25a0002
-#define F367TER_DISSF_CLKENABLE	0xf25a0001
-
-/*	TSTTS1 */
-#define R367TER_TSTTS1	0xf25c
-#define F367TER_TSTERS	0xf25c0080
-#define F367TER_TSFIFO_DSSSYNCB	0xf25c0040
-#define F367TER_TSTTS_FSPYBEFRS	0xf25c0020
-#define F367TER_NFORCE_SYNCBYTE	0xf25c0010
-#define F367TER_XL_NOFTHRESHOLD	0xf25c0008
-#define F367TER_TSTTS_FRFORCEPKT	0xf25c0004
-#define F367TER_DESCR_NOTAUTO	0xf25c0002
-#define F367TER_TSTTSEN	0xf25c0001
-
-/*	TSTTS2 */
-#define R367TER_TSTTS2	0xf25d
-#define F367TER_DIL_DBBHEADER	0xf25d0080
-#define F367TER_TSTTS_NOBADXXX	0xf25d0040
-#define F367TER_TSFIFO_DELSPEEDUP	0xf25d0020
-#define F367TER_TSTTS_SELECT	0xf25d001f
-
-/*	TSTTS3 */
-#define R367TER_TSTTS3	0xf25e
-#define F367TER_TSTTS_NOPKTGAIN	0xf25e0080
-#define F367TER_TSTTS_NOPKTENE	0xf25e0040
-#define F367TER_TSTTS_ISOLATION	0xf25e0020
-#define F367TER_TSTTS_DISBUG	0xf25e0010
-#define F367TER_TSTTS_NOBADSTART	0xf25e0008
-#define F367TER_TSTTS_STACKSEL	0xf25e0007
-
-/*	TSTTS4 */
-#define R367TER_TSTTS4	0xf25f
-#define F367TER_TSTTS4_7	0xf25f0080
-#define F367TER_TSTTS4_6	0xf25f0040
-#define F367TER_TSTTS4_5	0xf25f0020
-#define F367TER_TSTTS_DISDSTATE	0xf25f0010
-#define F367TER_TSTTS_FASTNOSYNC	0xf25f0008
-#define F367TER_EXT_FECSPYIN	0xf25f0004
-#define F367TER_TSTTS_NODPZERO	0xf25f0002
-#define F367TER_TSTTS_NODIV3	0xf25f0001
-
-/*	TSTTSRC */
-#define R367TER_TSTTSRC	0xf26c
-#define F367TER_TSTTSRC_7	0xf26c0080
-#define F367TER_TSRCFIFO_DSSSYNCB	0xf26c0040
-#define F367TER_TSRCFIFO_DPUNACTIVE	0xf26c0020
-#define F367TER_TSRCFIFO_DELSPEEDUP	0xf26c0010
-#define F367TER_TSTTSRC_NODIV3	0xf26c0008
-#define F367TER_TSTTSRC_FRFORCEPKT	0xf26c0004
-#define F367TER_SAT25_SDDORIGINE	0xf26c0002
-#define F367TER_TSTTSRC_INACTIVE	0xf26c0001
-
-/*	TSTTSRS */
-#define R367TER_TSTTSRS	0xf26d
-#define F367TER_TSTTSRS_7	0xf26d0080
-#define F367TER_TSTTSRS_6	0xf26d0040
-#define F367TER_TSTTSRS_5	0xf26d0020
-#define F367TER_TSTTSRS_4	0xf26d0010
-#define F367TER_TSTTSRS_3	0xf26d0008
-#define F367TER_TSTTSRS_2	0xf26d0004
-#define F367TER_TSTRS_DISRS2	0xf26d0002
-#define F367TER_TSTRS_DISRS1	0xf26d0001
-
-/* TSSTATEM */
-#define	R367TER_TSSTATEM	0xf270
-#define	F367TER_TSDIL_ON	0xf2700080
-#define	F367TER_TSSKIPRS_ON	0xf2700040
-#define	F367TER_TSRS_ON	0xf2700020
-#define	F367TER_TSDESCRAMB_ON	0xf2700010
-#define	F367TER_TSFRAME_MODE	0xf2700008
-#define	F367TER_TS_DISABLE	0xf2700004
-#define	F367TER_TSACM_MODE	0xf2700002
-#define	F367TER_TSOUT_NOSYNC	0xf2700001
-
-/* TSSTATEL */
-#define	R367TER_TSSTATEL	0xf271
-#define	F367TER_TSNOSYNCBYTE	0xf2710080
-#define	F367TER_TSPARITY_ON	0xf2710040
-#define	F367TER_TSSYNCOUTRS_ON	0xf2710020
-#define	F367TER_TSDVBS2_MODE	0xf2710010
-#define	F367TER_TSISSYI_ON	0xf2710008
-#define	F367TER_TSNPD_ON	0xf2710004
-#define	F367TER_TSCRC8_ON	0xf2710002
-#define	F367TER_TSDSS_PACKET	0xf2710001
-
-/* TSCFGH */
-#define	R367TER_TSCFGH	0xf272
-#define	F367TER_TSFIFO_DVBCI	0xf2720080
-#define	F367TER_TSFIFO_SERIAL	0xf2720040
-#define	F367TER_TSFIFO_TEIUPDATE	0xf2720020
-#define	F367TER_TSFIFO_DUTY50	0xf2720010
-#define	F367TER_TSFIFO_HSGNLOUT	0xf2720008
-#define	F367TER_TSFIFO_ERRMODE	0xf2720006
-#define	F367TER_RST_HWARE	0xf2720001
-
-/* TSCFGM */
-#define	R367TER_TSCFGM	0xf273
-#define	F367TER_TSFIFO_MANSPEED	0xf27300c0
-#define	F367TER_TSFIFO_PERMDATA	0xf2730020
-#define	F367TER_TSFIFO_NONEWSGNL	0xf2730010
-#define	F367TER_TSFIFO_BITSPEED	0xf2730008
-#define	F367TER_NPD_SPECDVBS2	0xf2730004
-#define	F367TER_TSFIFO_STOPCKDIS	0xf2730002
-#define	F367TER_TSFIFO_INVDATA	0xf2730001
-
-/* TSCFGL */
-#define	R367TER_TSCFGL	0xf274
-#define	F367TER_TSFIFO_BCLKDEL1cK	0xf27400c0
-#define	F367TER_BCHERROR_MODE	0xf2740030
-#define	F367TER_TSFIFO_NSGNL2dATA	0xf2740008
-#define	F367TER_TSFIFO_EMBINDVB	0xf2740004
-#define	F367TER_TSFIFO_DPUNACT	0xf2740002
-#define	F367TER_TSFIFO_NPDOFF	0xf2740001
-
-/* TSSYNC */
-#define	R367TER_TSSYNC	0xf275
-#define	F367TER_TSFIFO_PERMUTE	0xf2750080
-#define	F367TER_TSFIFO_FISCR3B	0xf2750060
-#define	F367TER_TSFIFO_SYNCMODE	0xf2750018
-#define	F367TER_TSFIFO_SYNCSEL	0xf2750007
-
-/* TSINSDELH */
-#define	R367TER_TSINSDELH	0xf276
-#define	F367TER_TSDEL_SYNCBYTE	0xf2760080
-#define	F367TER_TSDEL_XXHEADER	0xf2760040
-#define	F367TER_TSDEL_BBHEADER	0xf2760020
-#define	F367TER_TSDEL_DATAFIELD	0xf2760010
-#define	F367TER_TSINSDEL_ISCR	0xf2760008
-#define	F367TER_TSINSDEL_NPD	0xf2760004
-#define	F367TER_TSINSDEL_RSPARITY	0xf2760002
-#define	F367TER_TSINSDEL_CRC8	0xf2760001
-
-/* TSINSDELM */
-#define	R367TER_TSINSDELM	0xf277
-#define	F367TER_TSINS_BBPADDING	0xf2770080
-#define	F367TER_TSINS_BCHFEC	0xf2770040
-#define	F367TER_TSINS_LDPCFEC	0xf2770020
-#define	F367TER_TSINS_EMODCOD	0xf2770010
-#define	F367TER_TSINS_TOKEN	0xf2770008
-#define	F367TER_TSINS_XXXERR	0xf2770004
-#define	F367TER_TSINS_MATYPE	0xf2770002
-#define	F367TER_TSINS_UPL	0xf2770001
-
-/* TSINSDELL */
-#define	R367TER_TSINSDELL	0xf278
-#define	F367TER_TSINS_DFL	0xf2780080
-#define	F367TER_TSINS_SYNCD	0xf2780040
-#define	F367TER_TSINS_BLOCLEN	0xf2780020
-#define	F367TER_TSINS_SIGPCOUNT	0xf2780010
-#define	F367TER_TSINS_FIFO	0xf2780008
-#define	F367TER_TSINS_REALPACK	0xf2780004
-#define	F367TER_TSINS_TSCONFIG	0xf2780002
-#define	F367TER_TSINS_LATENCY	0xf2780001
-
-/* TSDIVN */
-#define	R367TER_TSDIVN	0xf279
-#define	F367TER_TSFIFO_LOWSPEED	0xf2790080
-#define	F367TER_BYTE_OVERSAMPLING	0xf2790070
-#define	F367TER_TSMANUAL_PACKETNBR	0xf279000f
-
-/* TSDIVPM */
-#define	R367TER_TSDIVPM	0xf27a
-#define	F367TER_TSMANUAL_P_HI	0xf27a00ff
-
-/* TSDIVPL */
-#define	R367TER_TSDIVPL	0xf27b
-#define	F367TER_TSMANUAL_P_LO	0xf27b00ff
-
-/* TSDIVQM */
-#define	R367TER_TSDIVQM	0xf27c
-#define	F367TER_TSMANUAL_Q_HI	0xf27c00ff
-
-/* TSDIVQL */
-#define	R367TER_TSDIVQL	0xf27d
-#define	F367TER_TSMANUAL_Q_LO	0xf27d00ff
-
-/* TSDILSTKM */
-#define	R367TER_TSDILSTKM	0xf27e
-#define	F367TER_TSFIFO_DILSTK_HI	0xf27e00ff
-
-/* TSDILSTKL */
-#define	R367TER_TSDILSTKL	0xf27f
-#define	F367TER_TSFIFO_DILSTK_LO	0xf27f00ff
-
-/* TSSPEED */
-#define	R367TER_TSSPEED	0xf280
-#define	F367TER_TSFIFO_OUTSPEED	0xf28000ff
-
-/* TSSTATUS */
-#define	R367TER_TSSTATUS	0xf281
-#define	F367TER_TSFIFO_LINEOK	0xf2810080
-#define	F367TER_TSFIFO_ERROR	0xf2810040
-#define	F367TER_TSFIFO_DATA7	0xf2810020
-#define	F367TER_TSFIFO_NOSYNC	0xf2810010
-#define	F367TER_ISCR_INITIALIZED	0xf2810008
-#define	F367TER_ISCR_UPDATED	0xf2810004
-#define	F367TER_SOFFIFO_UNREGUL	0xf2810002
-#define	F367TER_DIL_READY	0xf2810001
-
-/* TSSTATUS2 */
-#define	R367TER_TSSTATUS2	0xf282
-#define	F367TER_TSFIFO_DEMODSEL	0xf2820080
-#define	F367TER_TSFIFOSPEED_STORE	0xf2820040
-#define	F367TER_DILXX_RESET	0xf2820020
-#define	F367TER_TSSERIAL_IMPOSSIBLE	0xf2820010
-#define	F367TER_TSFIFO_UNDERSPEED	0xf2820008
-#define	F367TER_BITSPEED_EVENT	0xf2820004
-#define	F367TER_UL_SCRAMBDETECT	0xf2820002
-#define	F367TER_ULDTV67_FALSELOCK	0xf2820001
-
-/* TSBITRATEM */
-#define	R367TER_TSBITRATEM	0xf283
-#define	F367TER_TSFIFO_BITRATE_HI	0xf28300ff
-
-/* TSBITRATEL */
-#define	R367TER_TSBITRATEL	0xf284
-#define	F367TER_TSFIFO_BITRATE_LO	0xf28400ff
-
-/* TSPACKLENM */
-#define	R367TER_TSPACKLENM	0xf285
-#define	F367TER_TSFIFO_PACKCPT	0xf28500e0
-#define	F367TER_DIL_RPLEN_HI	0xf285001f
-
-/* TSPACKLENL */
-#define	R367TER_TSPACKLENL	0xf286
-#define	F367TER_DIL_RPLEN_LO	0xf28600ff
-
-/* TSBLOCLENM */
-#define	R367TER_TSBLOCLENM	0xf287
-#define	F367TER_TSFIFO_PFLEN_HI	0xf28700ff
-
-/* TSBLOCLENL */
-#define	R367TER_TSBLOCLENL	0xf288
-#define	F367TER_TSFIFO_PFLEN_LO	0xf28800ff
-
-/* TSDLYH */
-#define	R367TER_TSDLYH	0xf289
-#define	F367TER_SOFFIFO_TSTIMEVALID	0xf2890080
-#define	F367TER_SOFFIFO_SPEEDUP	0xf2890040
-#define	F367TER_SOFFIFO_STOP	0xf2890020
-#define	F367TER_SOFFIFO_REGULATED	0xf2890010
-#define	F367TER_SOFFIFO_REALSBOFF_HI	0xf289000f
-
-/* TSDLYM */
-#define	R367TER_TSDLYM	0xf28a
-#define	F367TER_SOFFIFO_REALSBOFF_MED	0xf28a00ff
-
-/* TSDLYL */
-#define	R367TER_TSDLYL	0xf28b
-#define	F367TER_SOFFIFO_REALSBOFF_LO	0xf28b00ff
-
-/* TSNPDAV */
-#define	R367TER_TSNPDAV	0xf28c
-#define	F367TER_TSNPD_AVERAGE	0xf28c00ff
-
-/* TSBUFSTATH */
-#define	R367TER_TSBUFSTATH	0xf28d
-#define	F367TER_TSISCR_3BYTES	0xf28d0080
-#define	F367TER_TSISCR_NEWDATA	0xf28d0040
-#define	F367TER_TSISCR_BUFSTAT_HI	0xf28d003f
-
-/* TSBUFSTATM */
-#define	R367TER_TSBUFSTATM	0xf28e
-#define	F367TER_TSISCR_BUFSTAT_MED	0xf28e00ff
-
-/* TSBUFSTATL */
-#define	R367TER_TSBUFSTATL	0xf28f
-#define	F367TER_TSISCR_BUFSTAT_LO	0xf28f00ff
-
-/* TSDEBUGM */
-#define	R367TER_TSDEBUGM	0xf290
-#define	F367TER_TSFIFO_ILLPACKET	0xf2900080
-#define	F367TER_DIL_NOSYNC	0xf2900040
-#define	F367TER_DIL_ISCR	0xf2900020
-#define	F367TER_DILOUT_BSYNCB	0xf2900010
-#define	F367TER_TSFIFO_EMPTYPKT	0xf2900008
-#define	F367TER_TSFIFO_EMPTYRD	0xf2900004
-#define	F367TER_SOFFIFO_STOPM	0xf2900002
-#define	F367TER_SOFFIFO_SPEEDUPM	0xf2900001
-
-/* TSDEBUGL */
-#define	R367TER_TSDEBUGL	0xf291
-#define	F367TER_TSFIFO_PACKLENFAIL	0xf2910080
-#define	F367TER_TSFIFO_SYNCBFAIL	0xf2910040
-#define	F367TER_TSFIFO_VITLIBRE	0xf2910020
-#define	F367TER_TSFIFO_BOOSTSPEEDM	0xf2910010
-#define	F367TER_TSFIFO_UNDERSPEEDM	0xf2910008
-#define	F367TER_TSFIFO_ERROR_EVNT	0xf2910004
-#define	F367TER_TSFIFO_FULL	0xf2910002
-#define	F367TER_TSFIFO_OVERFLOWM	0xf2910001
-
-/* TSDLYSETH */
-#define	R367TER_TSDLYSETH	0xf292
-#define	F367TER_SOFFIFO_OFFSET	0xf29200e0
-#define	F367TER_SOFFIFO_SYMBOFFSET_HI	0xf292001f
-
-/* TSDLYSETM */
-#define	R367TER_TSDLYSETM	0xf293
-#define	F367TER_SOFFIFO_SYMBOFFSET_MED	0xf29300ff
-
-/* TSDLYSETL */
-#define	R367TER_TSDLYSETL	0xf294
-#define	F367TER_SOFFIFO_SYMBOFFSET_LO	0xf29400ff
-
-/* TSOBSCFG */
-#define	R367TER_TSOBSCFG	0xf295
-#define	F367TER_TSFIFO_OBSCFG	0xf29500ff
-
-/* TSOBSM */
-#define	R367TER_TSOBSM	0xf296
-#define	F367TER_TSFIFO_OBSDATA_HI	0xf29600ff
-
-/* TSOBSL */
-#define	R367TER_TSOBSL	0xf297
-#define	F367TER_TSFIFO_OBSDATA_LO	0xf29700ff
-
-/* ERRCTRL1 */
-#define	R367TER_ERRCTRL1	0xf298
-#define	F367TER_ERR_SRC1	0xf29800f0
-#define	F367TER_ERRCTRL1_3	0xf2980008
-#define	F367TER_NUM_EVT1	0xf2980007
-
-/* ERRCNT1H */
-#define	R367TER_ERRCNT1H	0xf299
-#define	F367TER_ERRCNT1_OLDVALUE	0xf2990080
-#define	F367TER_ERR_CNT1	0xf299007f
-
-/* ERRCNT1M */
-#define	R367TER_ERRCNT1M	0xf29a
-#define	F367TER_ERR_CNT1_HI	0xf29a00ff
-
-/* ERRCNT1L */
-#define	R367TER_ERRCNT1L	0xf29b
-#define	F367TER_ERR_CNT1_LO	0xf29b00ff
-
-/* ERRCTRL2 */
-#define	R367TER_ERRCTRL2	0xf29c
-#define	F367TER_ERR_SRC2	0xf29c00f0
-#define	F367TER_ERRCTRL2_3	0xf29c0008
-#define	F367TER_NUM_EVT2	0xf29c0007
-
-/* ERRCNT2H */
-#define	R367TER_ERRCNT2H	0xf29d
-#define	F367TER_ERRCNT2_OLDVALUE	0xf29d0080
-#define	F367TER_ERR_CNT2_HI	0xf29d007f
-
-/* ERRCNT2M */
-#define	R367TER_ERRCNT2M	0xf29e
-#define	F367TER_ERR_CNT2_MED	0xf29e00ff
-
-/* ERRCNT2L */
-#define	R367TER_ERRCNT2L	0xf29f
-#define	F367TER_ERR_CNT2_LO	0xf29f00ff
-
-/* FECSPY */
-#define	R367TER_FECSPY	0xf2a0
-#define	F367TER_SPY_ENABLE	0xf2a00080
-#define	F367TER_NO_SYNCBYTE	0xf2a00040
-#define	F367TER_SERIAL_MODE	0xf2a00020
-#define	F367TER_UNUSUAL_PACKET	0xf2a00010
-#define	F367TER_BERMETER_DATAMODE	0xf2a0000c
-#define	F367TER_BERMETER_LMODE	0xf2a00002
-#define	F367TER_BERMETER_RESET	0xf2a00001
-
-/* FSPYCFG */
-#define	R367TER_FSPYCFG	0xf2a1
-#define	F367TER_FECSPY_INPUT	0xf2a100c0
-#define	F367TER_RST_ON_ERROR	0xf2a10020
-#define	F367TER_ONE_SHOT	0xf2a10010
-#define	F367TER_I2C_MOD	0xf2a1000c
-#define	F367TER_SPY_HYSTERESIS	0xf2a10003
-
-/* FSPYDATA */
-#define	R367TER_FSPYDATA	0xf2a2
-#define	F367TER_SPY_STUFFING	0xf2a20080
-#define	F367TER_NOERROR_PKTJITTER	0xf2a20040
-#define	F367TER_SPY_CNULLPKT	0xf2a20020
-#define	F367TER_SPY_OUTDATA_MODE	0xf2a2001f
-
-/* FSPYOUT */
-#define	R367TER_FSPYOUT	0xf2a3
-#define	F367TER_FSPY_DIRECT	0xf2a30080
-#define	F367TER_FSPYOUT_6	0xf2a30040
-#define	F367TER_SPY_OUTDATA_BUS	0xf2a30038
-#define	F367TER_STUFF_MODE	0xf2a30007
-
-/* FSTATUS */
-#define	R367TER_FSTATUS	0xf2a4
-#define	F367TER_SPY_ENDSIM	0xf2a40080
-#define	F367TER_VALID_SIM	0xf2a40040
-#define	F367TER_FOUND_SIGNAL	0xf2a40020
-#define	F367TER_DSS_SYNCBYTE	0xf2a40010
-#define	F367TER_RESULT_STATE	0xf2a4000f
-
-/* FGOODPACK */
-#define	R367TER_FGOODPACK	0xf2a5
-#define	F367TER_FGOOD_PACKET	0xf2a500ff
-
-/* FPACKCNT */
-#define	R367TER_FPACKCNT	0xf2a6
-#define	F367TER_FPACKET_COUNTER	0xf2a600ff
-
-/* FSPYMISC */
-#define	R367TER_FSPYMISC	0xf2a7
-#define	F367TER_FLABEL_COUNTER	0xf2a700ff
-
-/* FBERCPT4 */
-#define	R367TER_FBERCPT4	0xf2a8
-#define	F367TER_FBERMETER_CPT5	0xf2a800ff
-
-/* FBERCPT3 */
-#define	R367TER_FBERCPT3	0xf2a9
-#define	F367TER_FBERMETER_CPT4	0xf2a900ff
-
-/* FBERCPT2 */
-#define	R367TER_FBERCPT2	0xf2aa
-#define	F367TER_FBERMETER_CPT3	0xf2aa00ff
-
-/* FBERCPT1 */
-#define	R367TER_FBERCPT1	0xf2ab
-#define	F367TER_FBERMETER_CPT2	0xf2ab00ff
-
-/* FBERCPT0 */
-#define	R367TER_FBERCPT0	0xf2ac
-#define	F367TER_FBERMETER_CPT1	0xf2ac00ff
-
-/* FBERERR2 */
-#define	R367TER_FBERERR2	0xf2ad
-#define	F367TER_FBERMETER_ERR_HI	0xf2ad00ff
-
-/* FBERERR1 */
-#define	R367TER_FBERERR1	0xf2ae
-#define	F367TER_FBERMETER_ERR_MED	0xf2ae00ff
-
-/* FBERERR0 */
-#define	R367TER_FBERERR0	0xf2af
-#define	F367TER_FBERMETER_ERR_LO	0xf2af00ff
-
-/* FSTATESM */
-#define	R367TER_FSTATESM	0xf2b0
-#define	F367TER_RSTATE_F	0xf2b00080
-#define	F367TER_RSTATE_E	0xf2b00040
-#define	F367TER_RSTATE_D	0xf2b00020
-#define	F367TER_RSTATE_C	0xf2b00010
-#define	F367TER_RSTATE_B	0xf2b00008
-#define	F367TER_RSTATE_A	0xf2b00004
-#define	F367TER_RSTATE_9	0xf2b00002
-#define	F367TER_RSTATE_8	0xf2b00001
-
-/* FSTATESL */
-#define	R367TER_FSTATESL	0xf2b1
-#define	F367TER_RSTATE_7	0xf2b10080
-#define	F367TER_RSTATE_6	0xf2b10040
-#define	F367TER_RSTATE_5	0xf2b10020
-#define	F367TER_RSTATE_4	0xf2b10010
-#define	F367TER_RSTATE_3	0xf2b10008
-#define	F367TER_RSTATE_2	0xf2b10004
-#define	F367TER_RSTATE_1	0xf2b10002
-#define	F367TER_RSTATE_0	0xf2b10001
-
-/* FSPYBER */
-#define	R367TER_FSPYBER	0xf2b2
-#define	F367TER_FSPYBER_7	0xf2b20080
-#define	F367TER_FSPYOBS_XORREAD	0xf2b20040
-#define	F367TER_FSPYBER_OBSMODE	0xf2b20020
-#define	F367TER_FSPYBER_SYNCBYTE	0xf2b20010
-#define	F367TER_FSPYBER_UNSYNC	0xf2b20008
-#define	F367TER_FSPYBER_CTIME	0xf2b20007
-
-/* FSPYDISTM */
-#define	R367TER_FSPYDISTM	0xf2b3
-#define	F367TER_PKTTIME_DISTANCE_HI	0xf2b300ff
-
-/* FSPYDISTL */
-#define	R367TER_FSPYDISTL	0xf2b4
-#define	F367TER_PKTTIME_DISTANCE_LO	0xf2b400ff
-
-/* FSPYOBS7 */
-#define	R367TER_FSPYOBS7	0xf2b8
-#define	F367TER_FSPYOBS_SPYFAIL	0xf2b80080
-#define	F367TER_FSPYOBS_SPYFAIL1	0xf2b80040
-#define	F367TER_FSPYOBS_ERROR	0xf2b80020
-#define	F367TER_FSPYOBS_STROUT	0xf2b80010
-#define	F367TER_FSPYOBS_RESULTSTATE1	0xf2b8000f
-
-/* FSPYOBS6 */
-#define	R367TER_FSPYOBS6	0xf2b9
-#define	F367TER_FSPYOBS_RESULTSTATe0	0xf2b900f0
-#define	F367TER_FSPYOBS_RESULTSTATEM1	0xf2b9000f
-
-/* FSPYOBS5 */
-#define	R367TER_FSPYOBS5	0xf2ba
-#define	F367TER_FSPYOBS_BYTEOFPACKET1	0xf2ba00ff
-
-/* FSPYOBS4 */
-#define	R367TER_FSPYOBS4	0xf2bb
-#define	F367TER_FSPYOBS_BYTEVALUE1	0xf2bb00ff
-
-/* FSPYOBS3 */
-#define	R367TER_FSPYOBS3	0xf2bc
-#define	F367TER_FSPYOBS_DATA1	0xf2bc00ff
-
-/* FSPYOBS2 */
-#define	R367TER_FSPYOBS2	0xf2bd
-#define	F367TER_FSPYOBS_DATa0	0xf2bd00ff
-
-/* FSPYOBS1 */
-#define	R367TER_FSPYOBS1	0xf2be
-#define	F367TER_FSPYOBS_DATAM1	0xf2be00ff
-
-/* FSPYOBS0 */
-#define	R367TER_FSPYOBS0	0xf2bf
-#define	F367TER_FSPYOBS_DATAM2	0xf2bf00ff
-
-/* SFDEMAP */
-#define	R367TER_SFDEMAP	0xf2c0
-#define	F367TER_SFDEMAP_7	0xf2c00080
-#define	F367TER_SFEC_K_DIVIDER_VIT	0xf2c0007f
-
-/* SFERROR */
-#define	R367TER_SFERROR	0xf2c1
-#define	F367TER_SFEC_REGERR_VIT	0xf2c100ff
-
-/* SFAVSR */
-#define	R367TER_SFAVSR	0xf2c2
-#define	F367TER_SFEC_SUMERRORS	0xf2c20080
-#define	F367TER_SERROR_MAXMODE	0xf2c20040
-#define	F367TER_SN_SFEC	0xf2c20030
-#define	F367TER_KDIV_MODE_SFEC	0xf2c2000c
-#define	F367TER_SFAVSR_1	0xf2c20002
-#define	F367TER_SFAVSR_0	0xf2c20001
-
-/* SFECSTATUS */
-#define	R367TER_SFECSTATUS	0xf2c3
-#define	F367TER_SFEC_ON	0xf2c30080
-#define	F367TER_SFSTATUS_6	0xf2c30040
-#define	F367TER_SFSTATUS_5	0xf2c30020
-#define	F367TER_SFSTATUS_4	0xf2c30010
-#define	F367TER_LOCKEDSFEC	0xf2c30008
-#define	F367TER_SFEC_DELOCK	0xf2c30004
-#define	F367TER_SFEC_DEMODSEL1	0xf2c30002
-#define	F367TER_SFEC_OVFON	0xf2c30001
-
-/* SFKDIV12 */
-#define	R367TER_SFKDIV12	0xf2c4
-#define	F367TER_SFECKDIV12_MAN	0xf2c40080
-#define	F367TER_SFEC_K_DIVIDER_12	0xf2c4007f
-
-/* SFKDIV23 */
-#define	R367TER_SFKDIV23	0xf2c5
-#define	F367TER_SFECKDIV23_MAN	0xf2c50080
-#define	F367TER_SFEC_K_DIVIDER_23	0xf2c5007f
-
-/* SFKDIV34 */
-#define	R367TER_SFKDIV34	0xf2c6
-#define	F367TER_SFECKDIV34_MAN	0xf2c60080
-#define	F367TER_SFEC_K_DIVIDER_34	0xf2c6007f
-
-/* SFKDIV56 */
-#define	R367TER_SFKDIV56	0xf2c7
-#define	F367TER_SFECKDIV56_MAN	0xf2c70080
-#define	F367TER_SFEC_K_DIVIDER_56	0xf2c7007f
-
-/* SFKDIV67 */
-#define	R367TER_SFKDIV67	0xf2c8
-#define	F367TER_SFECKDIV67_MAN	0xf2c80080
-#define	F367TER_SFEC_K_DIVIDER_67	0xf2c8007f
-
-/* SFKDIV78 */
-#define	R367TER_SFKDIV78	0xf2c9
-#define	F367TER_SFECKDIV78_MAN	0xf2c90080
-#define	F367TER_SFEC_K_DIVIDER_78	0xf2c9007f
-
-/* SFDILSTKM */
-#define	R367TER_SFDILSTKM	0xf2ca
-#define	F367TER_SFEC_PACKCPT	0xf2ca00e0
-#define	F367TER_SFEC_DILSTK_HI	0xf2ca001f
-
-/* SFDILSTKL */
-#define	R367TER_SFDILSTKL	0xf2cb
-#define	F367TER_SFEC_DILSTK_LO	0xf2cb00ff
-
-/* SFSTATUS */
-#define	R367TER_SFSTATUS	0xf2cc
-#define	F367TER_SFEC_LINEOK	0xf2cc0080
-#define	F367TER_SFEC_ERROR	0xf2cc0040
-#define	F367TER_SFEC_DATA7	0xf2cc0020
-#define	F367TER_SFEC_OVERFLOW	0xf2cc0010
-#define	F367TER_SFEC_DEMODSEL2	0xf2cc0008
-#define	F367TER_SFEC_NOSYNC	0xf2cc0004
-#define	F367TER_SFEC_UNREGULA	0xf2cc0002
-#define	F367TER_SFEC_READY	0xf2cc0001
-
-/* SFDLYH */
-#define	R367TER_SFDLYH	0xf2cd
-#define	F367TER_SFEC_TSTIMEVALID	0xf2cd0080
-#define	F367TER_SFEC_SPEEDUP	0xf2cd0040
-#define	F367TER_SFEC_STOP	0xf2cd0020
-#define	F367TER_SFEC_REGULATED	0xf2cd0010
-#define	F367TER_SFEC_REALSYMBOFFSET	0xf2cd000f
-
-/* SFDLYM */
-#define	R367TER_SFDLYM	0xf2ce
-#define	F367TER_SFEC_REALSYMBOFFSET_HI	0xf2ce00ff
-
-/* SFDLYL */
-#define	R367TER_SFDLYL	0xf2cf
-#define	F367TER_SFEC_REALSYMBOFFSET_LO	0xf2cf00ff
-
-/* SFDLYSETH */
-#define	R367TER_SFDLYSETH	0xf2d0
-#define	F367TER_SFEC_OFFSET	0xf2d000e0
-#define	F367TER_SFECDLYSETH_4	0xf2d00010
-#define	F367TER_RST_SFEC	0xf2d00008
-#define	F367TER_SFECDLYSETH_2	0xf2d00004
-#define	F367TER_SFEC_DISABLE	0xf2d00002
-#define	F367TER_SFEC_UNREGUL	0xf2d00001
-
-/* SFDLYSETM */
-#define	R367TER_SFDLYSETM	0xf2d1
-#define	F367TER_SFECDLYSETM_7	0xf2d10080
-#define	F367TER_SFEC_SYMBOFFSET_HI	0xf2d1007f
-
-/* SFDLYSETL */
-#define	R367TER_SFDLYSETL	0xf2d2
-#define	F367TER_SFEC_SYMBOFFSET_LO	0xf2d200ff
-
-/* SFOBSCFG */
-#define	R367TER_SFOBSCFG	0xf2d3
-#define	F367TER_SFEC_OBSCFG	0xf2d300ff
-
-/* SFOBSM */
-#define	R367TER_SFOBSM	0xf2d4
-#define	F367TER_SFEC_OBSDATA_HI	0xf2d400ff
-
-/* SFOBSL */
-#define	R367TER_SFOBSL	0xf2d5
-#define	F367TER_SFEC_OBSDATA_LO	0xf2d500ff
-
-/* SFECINFO */
-#define	R367TER_SFECINFO	0xf2d6
-#define	F367TER_SFECINFO_7	0xf2d60080
-#define	F367TER_SFEC_SYNCDLSB	0xf2d60070
-#define	F367TER_SFCE_S1cPHASE	0xf2d6000f
-
-/* SFERRCTRL */
-#define	R367TER_SFERRCTRL	0xf2d8
-#define	F367TER_SFEC_ERR_SOURCE	0xf2d800f0
-#define	F367TER_SFERRCTRL_3	0xf2d80008
-#define	F367TER_SFEC_NUM_EVENT	0xf2d80007
-
-/* SFERRCNTH */
-#define	R367TER_SFERRCNTH	0xf2d9
-#define	F367TER_SFERRC_OLDVALUE	0xf2d90080
-#define	F367TER_SFEC_ERR_CNT	0xf2d9007f
-
-/* SFERRCNTM */
-#define	R367TER_SFERRCNTM	0xf2da
-#define	F367TER_SFEC_ERR_CNT_HI	0xf2da00ff
-
-/* SFERRCNTL */
-#define	R367TER_SFERRCNTL	0xf2db
-#define	F367TER_SFEC_ERR_CNT_LO	0xf2db00ff
-
-/* SYMBRATEM */
-#define	R367TER_SYMBRATEM	0xf2e0
-#define	F367TER_DEFGEN_SYMBRATE_HI	0xf2e000ff
-
-/* SYMBRATEL */
-#define	R367TER_SYMBRATEL	0xf2e1
-#define	F367TER_DEFGEN_SYMBRATE_LO	0xf2e100ff
-
-/* SYMBSTATUS */
-#define	R367TER_SYMBSTATUS	0xf2e2
-#define	F367TER_SYMBDLINE2_OFF	0xf2e20080
-#define	F367TER_SDDL_REINIT1	0xf2e20040
-#define	F367TER_SDD_REINIT1	0xf2e20020
-#define	F367TER_TOKENID_ERROR	0xf2e20010
-#define	F367TER_SYMBRATE_OVERFLOW	0xf2e20008
-#define	F367TER_SYMBRATE_UNDERFLOW	0xf2e20004
-#define	F367TER_TOKENID_RSTEVENT	0xf2e20002
-#define	F367TER_TOKENID_RESET1	0xf2e20001
-
-/* SYMBCFG */
-#define	R367TER_SYMBCFG	0xf2e3
-#define	F367TER_SYMBCFG_7	0xf2e30080
-#define	F367TER_SYMBCFG_6	0xf2e30040
-#define	F367TER_SYMBCFG_5	0xf2e30020
-#define	F367TER_SYMBCFG_4	0xf2e30010
-#define	F367TER_SYMRATE_FSPEED	0xf2e3000c
-#define	F367TER_SYMRATE_SSPEED	0xf2e30003
-
-/* SYMBFIFOM */
-#define	R367TER_SYMBFIFOM	0xf2e4
-#define	F367TER_SYMBFIFOM_7	0xf2e40080
-#define	F367TER_SYMBFIFOM_6	0xf2e40040
-#define	F367TER_DEFGEN_SYMFIFO_HI	0xf2e4003f
-
-/* SYMBFIFOL */
-#define	R367TER_SYMBFIFOL	0xf2e5
-#define	F367TER_DEFGEN_SYMFIFO_LO	0xf2e500ff
-
-/* SYMBOFFSM */
-#define	R367TER_SYMBOFFSM	0xf2e6
-#define	F367TER_TOKENID_RESET2	0xf2e60080
-#define	F367TER_SDDL_REINIT2	0xf2e60040
-#define	F367TER_SDD_REINIT2	0xf2e60020
-#define	F367TER_SYMBOFFSM_4	0xf2e60010
-#define	F367TER_SYMBOFFSM_3	0xf2e60008
-#define	F367TER_DEFGEN_SYMBOFFSET_HI	0xf2e60007
-
-/* SYMBOFFSL */
-#define	R367TER_SYMBOFFSL	0xf2e7
-#define	F367TER_DEFGEN_SYMBOFFSET_LO	0xf2e700ff
-
-/* DEBUG_LT4 */
-#define	R367TER_DEBUG_LT4	0xf400
-#define	F367TER_F_DEBUG_LT4	0xf40000ff
-
-/* DEBUG_LT5 */
-#define	R367TER_DEBUG_LT5	0xf401
-#define	F367TER_F_DEBUG_LT5	0xf40100ff
-
-/* DEBUG_LT6 */
-#define	R367TER_DEBUG_LT6	0xf402
-#define	F367TER_F_DEBUG_LT6	0xf40200ff
-
-/* DEBUG_LT7 */
-#define	R367TER_DEBUG_LT7	0xf403
-#define	F367TER_F_DEBUG_LT7	0xf40300ff
-
-/* DEBUG_LT8 */
-#define	R367TER_DEBUG_LT8	0xf404
-#define	F367TER_F_DEBUG_LT8	0xf40400ff
-
-/* DEBUG_LT9 */
-#define	R367TER_DEBUG_LT9	0xf405
-#define	F367TER_F_DEBUG_LT9	0xf40500ff
-
-#define STV0367TER_NBREGS	445
-
-/* ID */
-#define	R367CAB_ID	0xf000
-#define	F367CAB_IDENTIFICATIONREGISTER	0xf00000ff
-
-/* I2CRPT */
-#define	R367CAB_I2CRPT	0xf001
-#define	F367CAB_I2CT_ON	0xf0010080
-#define	F367CAB_ENARPT_LEVEL	0xf0010070
-#define	F367CAB_SCLT_DELAY	0xf0010008
-#define	F367CAB_SCLT_NOD	0xf0010004
-#define	F367CAB_STOP_ENABLE	0xf0010002
-#define	F367CAB_SDAT_NOD	0xf0010001
-
-/* TOPCTRL */
-#define	R367CAB_TOPCTRL	0xf002
-#define	F367CAB_STDBY	0xf0020080
-#define	F367CAB_STDBY_CORE	0xf0020020
-#define	F367CAB_QAM_COFDM	0xf0020010
-#define	F367CAB_TS_DIS	0xf0020008
-#define	F367CAB_DIR_CLK_216	0xf0020004
-
-/* IOCFG0 */
-#define	R367CAB_IOCFG0	0xf003
-#define	F367CAB_OP0_SD	0xf0030080
-#define	F367CAB_OP0_VAL	0xf0030040
-#define	F367CAB_OP0_OD	0xf0030020
-#define	F367CAB_OP0_INV	0xf0030010
-#define	F367CAB_OP0_DACVALUE_HI	0xf003000f
-
-/* DAc0R */
-#define	R367CAB_DAC0R	0xf004
-#define	F367CAB_OP0_DACVALUE_LO	0xf00400ff
-
-/* IOCFG1 */
-#define	R367CAB_IOCFG1	0xf005
-#define	F367CAB_IP0	0xf0050040
-#define	F367CAB_OP1_OD	0xf0050020
-#define	F367CAB_OP1_INV	0xf0050010
-#define	F367CAB_OP1_DACVALUE_HI	0xf005000f
-
-/* DAC1R */
-#define	R367CAB_DAC1R	0xf006
-#define	F367CAB_OP1_DACVALUE_LO	0xf00600ff
-
-/* IOCFG2 */
-#define	R367CAB_IOCFG2	0xf007
-#define	F367CAB_OP2_LOCK_CONF	0xf00700e0
-#define	F367CAB_OP2_OD	0xf0070010
-#define	F367CAB_OP2_VAL	0xf0070008
-#define	F367CAB_OP1_LOCK_CONF	0xf0070007
-
-/* SDFR */
-#define	R367CAB_SDFR	0xf008
-#define	F367CAB_OP0_FREQ	0xf00800f0
-#define	F367CAB_OP1_FREQ	0xf008000f
-
-/* AUX_CLK */
-#define	R367CAB_AUX_CLK	0xf00a
-#define	F367CAB_AUXFEC_CTL	0xf00a00c0
-#define	F367CAB_DIS_CKX4	0xf00a0020
-#define	F367CAB_CKSEL	0xf00a0018
-#define	F367CAB_CKDIV_PROG	0xf00a0006
-#define	F367CAB_AUXCLK_ENA	0xf00a0001
-
-/* FREESYS1 */
-#define	R367CAB_FREESYS1	0xf00b
-#define	F367CAB_FREESYS_1	0xf00b00ff
-
-/* FREESYS2 */
-#define	R367CAB_FREESYS2	0xf00c
-#define	F367CAB_FREESYS_2	0xf00c00ff
-
-/* FREESYS3 */
-#define	R367CAB_FREESYS3	0xf00d
-#define	F367CAB_FREESYS_3	0xf00d00ff
-
-/* GPIO_CFG */
-#define	R367CAB_GPIO_CFG	0xf00e
-#define	F367CAB_GPIO7_OD	0xf00e0080
-#define	F367CAB_GPIO7_CFG	0xf00e0040
-#define	F367CAB_GPIO6_OD	0xf00e0020
-#define	F367CAB_GPIO6_CFG	0xf00e0010
-#define	F367CAB_GPIO5_OD	0xf00e0008
-#define	F367CAB_GPIO5_CFG	0xf00e0004
-#define	F367CAB_GPIO4_OD	0xf00e0002
-#define	F367CAB_GPIO4_CFG	0xf00e0001
-
-/* GPIO_CMD */
-#define	R367CAB_GPIO_CMD	0xf00f
-#define	F367CAB_GPIO7_VAL	0xf00f0008
-#define	F367CAB_GPIO6_VAL	0xf00f0004
-#define	F367CAB_GPIO5_VAL	0xf00f0002
-#define	F367CAB_GPIO4_VAL	0xf00f0001
-
-/* TSTRES */
-#define	R367CAB_TSTRES	0xf0c0
-#define	F367CAB_FRES_DISPLAY	0xf0c00080
-#define	F367CAB_FRES_FIFO_AD	0xf0c00020
-#define	F367CAB_FRESRS	0xf0c00010
-#define	F367CAB_FRESACS	0xf0c00008
-#define	F367CAB_FRESFEC	0xf0c00004
-#define	F367CAB_FRES_PRIF	0xf0c00002
-#define	F367CAB_FRESCORE	0xf0c00001
-
-/* ANACTRL */
-#define	R367CAB_ANACTRL	0xf0c1
-#define	F367CAB_BYPASS_XTAL	0xf0c10040
-#define	F367CAB_BYPASS_PLLXN	0xf0c1000c
-#define	F367CAB_DIS_PAD_OSC	0xf0c10002
-#define	F367CAB_STDBY_PLLXN	0xf0c10001
-
-/* TSTBUS */
-#define	R367CAB_TSTBUS	0xf0c2
-#define	F367CAB_TS_BYTE_CLK_INV	0xf0c20080
-#define	F367CAB_CFG_IP	0xf0c20070
-#define	F367CAB_CFG_TST	0xf0c2000f
-
-/* RF_AGC1 */
-#define	R367CAB_RF_AGC1	0xf0d4
-#define	F367CAB_RF_AGC1_LEVEL_HI	0xf0d400ff
-
-/* RF_AGC2 */
-#define	R367CAB_RF_AGC2	0xf0d5
-#define	F367CAB_REF_ADGP	0xf0d50080
-#define	F367CAB_STDBY_ADCGP	0xf0d50020
-#define	F367CAB_RF_AGC1_LEVEL_LO	0xf0d50003
-
-/* ANADIGCTRL */
-#define	R367CAB_ANADIGCTRL	0xf0d7
-#define	F367CAB_SEL_CLKDEM	0xf0d70020
-#define	F367CAB_EN_BUFFER_Q	0xf0d70010
-#define	F367CAB_EN_BUFFER_I	0xf0d70008
-#define	F367CAB_ADC_RIS_EGDE	0xf0d70004
-#define	F367CAB_SGN_ADC	0xf0d70002
-#define	F367CAB_SEL_AD12_SYNC	0xf0d70001
-
-/* PLLMDIV */
-#define	R367CAB_PLLMDIV	0xf0d8
-#define	F367CAB_PLL_MDIV	0xf0d800ff
-
-/* PLLNDIV */
-#define	R367CAB_PLLNDIV	0xf0d9
-#define	F367CAB_PLL_NDIV	0xf0d900ff
-
-/* PLLSETUP */
-#define	R367CAB_PLLSETUP	0xf0da
-#define	F367CAB_PLL_PDIV	0xf0da0070
-#define	F367CAB_PLL_KDIV	0xf0da000f
-
-/* DUAL_AD12 */
-#define	R367CAB_DUAL_AD12	0xf0db
-#define	F367CAB_FS20M	0xf0db0020
-#define	F367CAB_FS50M	0xf0db0010
-#define	F367CAB_INMODe0	0xf0db0008
-#define	F367CAB_POFFQ	0xf0db0004
-#define	F367CAB_POFFI	0xf0db0002
-#define	F367CAB_INMODE1	0xf0db0001
-
-/* TSTBIST */
-#define	R367CAB_TSTBIST	0xf0dc
-#define	F367CAB_TST_BYP_CLK	0xf0dc0080
-#define	F367CAB_TST_GCLKENA_STD	0xf0dc0040
-#define	F367CAB_TST_GCLKENA	0xf0dc0020
-#define	F367CAB_TST_MEMBIST	0xf0dc001f
-
-/* CTRL_1 */
-#define	R367CAB_CTRL_1	0xf402
-#define	F367CAB_SOFT_RST	0xf4020080
-#define	F367CAB_EQU_RST	0xf4020008
-#define	F367CAB_CRL_RST	0xf4020004
-#define	F367CAB_TRL_RST	0xf4020002
-#define	F367CAB_AGC_RST	0xf4020001
-
-/* CTRL_2 */
-#define	R367CAB_CTRL_2	0xf403
-#define	F367CAB_DEINT_RST	0xf4030008
-#define	F367CAB_RS_RST	0xf4030004
-
-/* IT_STATUS1 */
-#define	R367CAB_IT_STATUS1	0xf408
-#define	F367CAB_SWEEP_OUT	0xf4080080
-#define	F367CAB_FSM_CRL	0xf4080040
-#define	F367CAB_CRL_LOCK	0xf4080020
-#define	F367CAB_MFSM	0xf4080010
-#define	F367CAB_TRL_LOCK	0xf4080008
-#define	F367CAB_TRL_AGC_LIMIT	0xf4080004
-#define	F367CAB_ADJ_AGC_LOCK	0xf4080002
-#define	F367CAB_AGC_QAM_LOCK	0xf4080001
-
-/* IT_STATUS2 */
-#define	R367CAB_IT_STATUS2	0xf409
-#define	F367CAB_TSMF_CNT	0xf4090080
-#define	F367CAB_TSMF_EOF	0xf4090040
-#define	F367CAB_TSMF_RDY	0xf4090020
-#define	F367CAB_FEC_NOCORR	0xf4090010
-#define	F367CAB_SYNCSTATE	0xf4090008
-#define	F367CAB_DEINT_LOCK	0xf4090004
-#define	F367CAB_FADDING_FRZ	0xf4090002
-#define	F367CAB_TAPMON_ALARM	0xf4090001
-
-/* IT_EN1 */
-#define	R367CAB_IT_EN1	0xf40a
-#define	F367CAB_SWEEP_OUTE	0xf40a0080
-#define	F367CAB_FSM_CRLE	0xf40a0040
-#define	F367CAB_CRL_LOCKE	0xf40a0020
-#define	F367CAB_MFSME	0xf40a0010
-#define	F367CAB_TRL_LOCKE	0xf40a0008
-#define	F367CAB_TRL_AGC_LIMITE	0xf40a0004
-#define	F367CAB_ADJ_AGC_LOCKE	0xf40a0002
-#define	F367CAB_AGC_LOCKE	0xf40a0001
-
-/* IT_EN2 */
-#define	R367CAB_IT_EN2	0xf40b
-#define	F367CAB_TSMF_CNTE	0xf40b0080
-#define	F367CAB_TSMF_EOFE	0xf40b0040
-#define	F367CAB_TSMF_RDYE	0xf40b0020
-#define	F367CAB_FEC_NOCORRE	0xf40b0010
-#define	F367CAB_SYNCSTATEE	0xf40b0008
-#define	F367CAB_DEINT_LOCKE	0xf40b0004
-#define	F367CAB_FADDING_FRZE	0xf40b0002
-#define	F367CAB_TAPMON_ALARME	0xf40b0001
-
-/* CTRL_STATUS */
-#define	R367CAB_CTRL_STATUS	0xf40c
-#define	F367CAB_QAMFEC_LOCK	0xf40c0004
-#define	F367CAB_TSMF_LOCK	0xf40c0002
-#define	F367CAB_TSMF_ERROR	0xf40c0001
-
-/* TEST_CTL */
-#define	R367CAB_TEST_CTL	0xf40f
-#define	F367CAB_TST_BLK_SEL	0xf40f0060
-#define	F367CAB_TST_BUS_SEL	0xf40f001f
-
-/* AGC_CTL */
-#define	R367CAB_AGC_CTL	0xf410
-#define	F367CAB_AGC_LCK_TH	0xf41000f0
-#define	F367CAB_AGC_ACCUMRSTSEL	0xf4100007
-
-/* AGC_IF_CFG */
-#define	R367CAB_AGC_IF_CFG	0xf411
-#define	F367CAB_AGC_IF_BWSEL	0xf41100f0
-#define	F367CAB_AGC_IF_FREEZE	0xf4110002
-
-/* AGC_RF_CFG */
-#define	R367CAB_AGC_RF_CFG	0xf412
-#define	F367CAB_AGC_RF_BWSEL	0xf4120070
-#define	F367CAB_AGC_RF_FREEZE	0xf4120002
-
-/* AGC_PWM_CFG */
-#define	R367CAB_AGC_PWM_CFG	0xf413
-#define	F367CAB_AGC_RF_PWM_TST	0xf4130080
-#define	F367CAB_AGC_RF_PWM_INV	0xf4130040
-#define	F367CAB_AGC_IF_PWM_TST	0xf4130008
-#define	F367CAB_AGC_IF_PWM_INV	0xf4130004
-#define	F367CAB_AGC_PWM_CLKDIV	0xf4130003
-
-/* AGC_PWR_REF_L */
-#define	R367CAB_AGC_PWR_REF_L	0xf414
-#define	F367CAB_AGC_PWRREF_LO	0xf41400ff
-
-/* AGC_PWR_REF_H */
-#define	R367CAB_AGC_PWR_REF_H	0xf415
-#define	F367CAB_AGC_PWRREF_HI	0xf4150003
-
-/* AGC_RF_TH_L */
-#define	R367CAB_AGC_RF_TH_L	0xf416
-#define	F367CAB_AGC_RF_TH_LO	0xf41600ff
-
-/* AGC_RF_TH_H */
-#define	R367CAB_AGC_RF_TH_H	0xf417
-#define	F367CAB_AGC_RF_TH_HI	0xf417000f
-
-/* AGC_IF_LTH_L */
-#define	R367CAB_AGC_IF_LTH_L	0xf418
-#define	F367CAB_AGC_IF_THLO_LO	0xf41800ff
-
-/* AGC_IF_LTH_H */
-#define	R367CAB_AGC_IF_LTH_H	0xf419
-#define	F367CAB_AGC_IF_THLO_HI	0xf419000f
-
-/* AGC_IF_HTH_L */
-#define	R367CAB_AGC_IF_HTH_L	0xf41a
-#define	F367CAB_AGC_IF_THHI_LO	0xf41a00ff
-
-/* AGC_IF_HTH_H */
-#define	R367CAB_AGC_IF_HTH_H	0xf41b
-#define	F367CAB_AGC_IF_THHI_HI	0xf41b000f
-
-/* AGC_PWR_RD_L */
-#define	R367CAB_AGC_PWR_RD_L	0xf41c
-#define	F367CAB_AGC_PWR_WORD_LO	0xf41c00ff
-
-/* AGC_PWR_RD_M */
-#define	R367CAB_AGC_PWR_RD_M	0xf41d
-#define	F367CAB_AGC_PWR_WORD_ME	0xf41d00ff
-
-/* AGC_PWR_RD_H */
-#define	R367CAB_AGC_PWR_RD_H	0xf41e
-#define	F367CAB_AGC_PWR_WORD_HI	0xf41e0003
-
-/* AGC_PWM_IFCMD_L */
-#define	R367CAB_AGC_PWM_IFCMD_L	0xf420
-#define	F367CAB_AGC_IF_PWMCMD_LO	0xf42000ff
-
-/* AGC_PWM_IFCMD_H */
-#define	R367CAB_AGC_PWM_IFCMD_H	0xf421
-#define	F367CAB_AGC_IF_PWMCMD_HI	0xf421000f
-
-/* AGC_PWM_RFCMD_L */
-#define	R367CAB_AGC_PWM_RFCMD_L	0xf422
-#define	F367CAB_AGC_RF_PWMCMD_LO	0xf42200ff
-
-/* AGC_PWM_RFCMD_H */
-#define	R367CAB_AGC_PWM_RFCMD_H	0xf423
-#define	F367CAB_AGC_RF_PWMCMD_HI	0xf423000f
-
-/* IQDEM_CFG */
-#define	R367CAB_IQDEM_CFG	0xf424
-#define	F367CAB_IQDEM_CLK_SEL	0xf4240004
-#define	F367CAB_IQDEM_INVIQ	0xf4240002
-#define	F367CAB_IQDEM_A2dTYPE	0xf4240001
-
-/* MIX_NCO_LL */
-#define	R367CAB_MIX_NCO_LL	0xf425
-#define	F367CAB_MIX_NCO_INC_LL	0xf42500ff
-
-/* MIX_NCO_HL */
-#define	R367CAB_MIX_NCO_HL	0xf426
-#define	F367CAB_MIX_NCO_INC_HL	0xf42600ff
-
-/* MIX_NCO_HH */
-#define	R367CAB_MIX_NCO_HH	0xf427
-#define	F367CAB_MIX_NCO_INVCNST	0xf4270080
-#define	F367CAB_MIX_NCO_INC_HH	0xf427007f
-
-/* SRC_NCO_LL */
-#define	R367CAB_SRC_NCO_LL	0xf428
-#define	F367CAB_SRC_NCO_INC_LL	0xf42800ff
-
-/* SRC_NCO_LH */
-#define	R367CAB_SRC_NCO_LH	0xf429
-#define	F367CAB_SRC_NCO_INC_LH	0xf42900ff
-
-/* SRC_NCO_HL */
-#define	R367CAB_SRC_NCO_HL	0xf42a
-#define	F367CAB_SRC_NCO_INC_HL	0xf42a00ff
-
-/* SRC_NCO_HH */
-#define	R367CAB_SRC_NCO_HH	0xf42b
-#define	F367CAB_SRC_NCO_INC_HH	0xf42b007f
-
-/* IQDEM_GAIN_SRC_L */
-#define	R367CAB_IQDEM_GAIN_SRC_L	0xf42c
-#define	F367CAB_GAIN_SRC_LO	0xf42c00ff
-
-/* IQDEM_GAIN_SRC_H */
-#define	R367CAB_IQDEM_GAIN_SRC_H	0xf42d
-#define	F367CAB_GAIN_SRC_HI	0xf42d0003
-
-/* IQDEM_DCRM_CFG_LL */
-#define	R367CAB_IQDEM_DCRM_CFG_LL	0xf430
-#define	F367CAB_DCRM0_DCIN_L	0xf43000ff
-
-/* IQDEM_DCRM_CFG_LH */
-#define	R367CAB_IQDEM_DCRM_CFG_LH	0xf431
-#define	F367CAB_DCRM1_I_DCIN_L	0xf43100fc
-#define	F367CAB_DCRM0_DCIN_H	0xf4310003
-
-/* IQDEM_DCRM_CFG_HL */
-#define	R367CAB_IQDEM_DCRM_CFG_HL	0xf432
-#define	F367CAB_DCRM1_Q_DCIN_L	0xf43200f0
-#define	F367CAB_DCRM1_I_DCIN_H	0xf432000f
-
-/* IQDEM_DCRM_CFG_HH */
-#define	R367CAB_IQDEM_DCRM_CFG_HH	0xf433
-#define	F367CAB_DCRM1_FRZ	0xf4330080
-#define	F367CAB_DCRM0_FRZ	0xf4330040
-#define	F367CAB_DCRM1_Q_DCIN_H	0xf433003f
-
-/* IQDEM_ADJ_COEFf0 */
-#define	R367CAB_IQDEM_ADJ_COEFF0	0xf434
-#define	F367CAB_ADJIIR_COEFF10_L	0xf43400ff
-
-/* IQDEM_ADJ_COEFF1 */
-#define	R367CAB_IQDEM_ADJ_COEFF1	0xf435
-#define	F367CAB_ADJIIR_COEFF11_L	0xf43500fc
-#define	F367CAB_ADJIIR_COEFF10_H	0xf4350003
-
-/* IQDEM_ADJ_COEFF2 */
-#define	R367CAB_IQDEM_ADJ_COEFF2	0xf436
-#define	F367CAB_ADJIIR_COEFF12_L	0xf43600f0
-#define	F367CAB_ADJIIR_COEFF11_H	0xf436000f
-
-/* IQDEM_ADJ_COEFF3 */
-#define	R367CAB_IQDEM_ADJ_COEFF3	0xf437
-#define	F367CAB_ADJIIR_COEFF20_L	0xf43700c0
-#define	F367CAB_ADJIIR_COEFF12_H	0xf437003f
-
-/* IQDEM_ADJ_COEFF4 */
-#define	R367CAB_IQDEM_ADJ_COEFF4	0xf438
-#define	F367CAB_ADJIIR_COEFF20_H	0xf43800ff
-
-/* IQDEM_ADJ_COEFF5 */
-#define	R367CAB_IQDEM_ADJ_COEFF5	0xf439
-#define	F367CAB_ADJIIR_COEFF21_L	0xf43900ff
-
-/* IQDEM_ADJ_COEFF6 */
-#define	R367CAB_IQDEM_ADJ_COEFF6	0xf43a
-#define	F367CAB_ADJIIR_COEFF22_L	0xf43a00fc
-#define	F367CAB_ADJIIR_COEFF21_H	0xf43a0003
-
-/* IQDEM_ADJ_COEFF7 */
-#define	R367CAB_IQDEM_ADJ_COEFF7	0xf43b
-#define	F367CAB_ADJIIR_COEFF22_H	0xf43b000f
-
-/* IQDEM_ADJ_EN */
-#define	R367CAB_IQDEM_ADJ_EN	0xf43c
-#define	F367CAB_ALLPASSFILT_EN	0xf43c0008
-#define	F367CAB_ADJ_AGC_EN	0xf43c0004
-#define	F367CAB_ADJ_COEFF_FRZ	0xf43c0002
-#define	F367CAB_ADJ_EN	0xf43c0001
-
-/* IQDEM_ADJ_AGC_REF */
-#define	R367CAB_IQDEM_ADJ_AGC_REF	0xf43d
-#define	F367CAB_ADJ_AGC_REF	0xf43d00ff
-
-/* ALLPASSFILT1 */
-#define	R367CAB_ALLPASSFILT1	0xf440
-#define	F367CAB_ALLPASSFILT_COEFF1_LO	0xf44000ff
-
-/* ALLPASSFILT2 */
-#define	R367CAB_ALLPASSFILT2	0xf441
-#define	F367CAB_ALLPASSFILT_COEFF1_ME	0xf44100ff
-
-/* ALLPASSFILT3 */
-#define	R367CAB_ALLPASSFILT3	0xf442
-#define	F367CAB_ALLPASSFILT_COEFF2_LO	0xf44200c0
-#define	F367CAB_ALLPASSFILT_COEFF1_HI	0xf442003f
-
-/* ALLPASSFILT4 */
-#define	R367CAB_ALLPASSFILT4	0xf443
-#define	F367CAB_ALLPASSFILT_COEFF2_MEL	0xf44300ff
-
-/* ALLPASSFILT5 */
-#define	R367CAB_ALLPASSFILT5	0xf444
-#define	F367CAB_ALLPASSFILT_COEFF2_MEH	0xf44400ff
-
-/* ALLPASSFILT6 */
-#define	R367CAB_ALLPASSFILT6	0xf445
-#define	F367CAB_ALLPASSFILT_COEFF3_LO	0xf44500f0
-#define	F367CAB_ALLPASSFILT_COEFF2_HI	0xf445000f
-
-/* ALLPASSFILT7 */
-#define	R367CAB_ALLPASSFILT7	0xf446
-#define	F367CAB_ALLPASSFILT_COEFF3_MEL	0xf44600ff
-
-/* ALLPASSFILT8 */
-#define	R367CAB_ALLPASSFILT8	0xf447
-#define	F367CAB_ALLPASSFILT_COEFF3_MEH	0xf44700ff
-
-/* ALLPASSFILT9 */
-#define	R367CAB_ALLPASSFILT9	0xf448
-#define	F367CAB_ALLPASSFILT_COEFF4_LO	0xf44800fc
-#define	F367CAB_ALLPASSFILT_COEFF3_HI	0xf4480003
-
-/* ALLPASSFILT10 */
-#define	R367CAB_ALLPASSFILT10	0xf449
-#define	F367CAB_ALLPASSFILT_COEFF4_ME	0xf44900ff
-
-/* ALLPASSFILT11 */
-#define	R367CAB_ALLPASSFILT11	0xf44a
-#define	F367CAB_ALLPASSFILT_COEFF4_HI	0xf44a00ff
-
-/* TRL_AGC_CFG */
-#define	R367CAB_TRL_AGC_CFG	0xf450
-#define	F367CAB_TRL_AGC_FREEZE	0xf4500080
-#define	F367CAB_TRL_AGC_REF	0xf450007f
-
-/* TRL_LPF_CFG */
-#define	R367CAB_TRL_LPF_CFG	0xf454
-#define	F367CAB_NYQPOINT_INV	0xf4540040
-#define	F367CAB_TRL_SHIFT	0xf4540030
-#define	F367CAB_NYQ_COEFF_SEL	0xf454000c
-#define	F367CAB_TRL_LPF_FREEZE	0xf4540002
-#define	F367CAB_TRL_LPF_CRT	0xf4540001
-
-/* TRL_LPF_ACQ_GAIN */
-#define	R367CAB_TRL_LPF_ACQ_GAIN	0xf455
-#define	F367CAB_TRL_GDIR_ACQ	0xf4550070
-#define	F367CAB_TRL_GINT_ACQ	0xf4550007
-
-/* TRL_LPF_TRK_GAIN */
-#define	R367CAB_TRL_LPF_TRK_GAIN	0xf456
-#define	F367CAB_TRL_GDIR_TRK	0xf4560070
-#define	F367CAB_TRL_GINT_TRK	0xf4560007
-
-/* TRL_LPF_OUT_GAIN */
-#define	R367CAB_TRL_LPF_OUT_GAIN	0xf457
-#define	F367CAB_TRL_GAIN_OUT	0xf4570007
-
-/* TRL_LOCKDET_LTH */
-#define	R367CAB_TRL_LOCKDET_LTH	0xf458
-#define	F367CAB_TRL_LCK_THLO	0xf4580007
-
-/* TRL_LOCKDET_HTH */
-#define	R367CAB_TRL_LOCKDET_HTH	0xf459
-#define	F367CAB_TRL_LCK_THHI	0xf45900ff
-
-/* TRL_LOCKDET_TRGVAL */
-#define	R367CAB_TRL_LOCKDET_TRGVAL	0xf45a
-#define	F367CAB_TRL_LCK_TRG	0xf45a00ff
-
-/* IQ_QAM */
-#define	R367CAB_IQ_QAM	0xf45c
-#define	F367CAB_IQ_INPUT	0xf45c0008
-#define	F367CAB_DETECT_MODE	0xf45c0007
-
-/* FSM_STATE */
-#define	R367CAB_FSM_STATE	0xf460
-#define	F367CAB_CRL_DFE	0xf4600080
-#define	F367CAB_DFE_START	0xf4600040
-#define	F367CAB_CTRLG_START	0xf4600030
-#define	F367CAB_FSM_FORCESTATE	0xf460000f
-
-/* FSM_CTL */
-#define	R367CAB_FSM_CTL	0xf461
-#define	F367CAB_FEC2_EN	0xf4610040
-#define	F367CAB_SIT_EN	0xf4610020
-#define	F367CAB_TRL_AHEAD	0xf4610010
-#define	F367CAB_TRL2_EN	0xf4610008
-#define	F367CAB_FSM_EQA1_EN	0xf4610004
-#define	F367CAB_FSM_BKP_DIS	0xf4610002
-#define	F367CAB_FSM_FORCE_EN	0xf4610001
-
-/* FSM_STS */
-#define	R367CAB_FSM_STS	0xf462
-#define	F367CAB_FSM_STATUS	0xf462000f
-
-/* FSM_SNR0_HTH */
-#define	R367CAB_FSM_SNR0_HTH	0xf463
-#define	F367CAB_SNR0_HTH	0xf46300ff
-
-/* FSM_SNR1_HTH */
-#define	R367CAB_FSM_SNR1_HTH	0xf464
-#define	F367CAB_SNR1_HTH	0xf46400ff
-
-/* FSM_SNR2_HTH */
-#define	R367CAB_FSM_SNR2_HTH	0xf465
-#define	F367CAB_SNR2_HTH	0xf46500ff
-
-/* FSM_SNR0_LTH */
-#define	R367CAB_FSM_SNR0_LTH	0xf466
-#define	F367CAB_SNR0_LTH	0xf46600ff
-
-/* FSM_SNR1_LTH */
-#define	R367CAB_FSM_SNR1_LTH	0xf467
-#define	F367CAB_SNR1_LTH	0xf46700ff
-
-/* FSM_EQA1_HTH */
-#define	R367CAB_FSM_EQA1_HTH	0xf468
-#define	F367CAB_SNR3_HTH_LO	0xf46800f0
-#define	F367CAB_EQA1_HTH	0xf468000f
-
-/* FSM_TEMPO */
-#define	R367CAB_FSM_TEMPO	0xf469
-#define	F367CAB_SIT	0xf46900c0
-#define	F367CAB_WST	0xf4690038
-#define	F367CAB_ELT	0xf4690006
-#define	F367CAB_SNR3_HTH_HI	0xf4690001
-
-/* FSM_CONFIG */
-#define	R367CAB_FSM_CONFIG	0xf46a
-#define	F367CAB_FEC2_DFEOFF	0xf46a0004
-#define	F367CAB_PRIT_STATE	0xf46a0002
-#define	F367CAB_MODMAP_STATE	0xf46a0001
-
-/* EQU_I_TESTTAP_L */
-#define	R367CAB_EQU_I_TESTTAP_L	0xf474
-#define	F367CAB_I_TEST_TAP_L	0xf47400ff
-
-/* EQU_I_TESTTAP_M */
-#define	R367CAB_EQU_I_TESTTAP_M	0xf475
-#define	F367CAB_I_TEST_TAP_M	0xf47500ff
-
-/* EQU_I_TESTTAP_H */
-#define	R367CAB_EQU_I_TESTTAP_H	0xf476
-#define	F367CAB_I_TEST_TAP_H	0xf476001f
-
-/* EQU_TESTAP_CFG */
-#define	R367CAB_EQU_TESTAP_CFG	0xf477
-#define	F367CAB_TEST_FFE_DFE_SEL	0xf4770040
-#define	F367CAB_TEST_TAP_SELECT	0xf477003f
-
-/* EQU_Q_TESTTAP_L */
-#define	R367CAB_EQU_Q_TESTTAP_L	0xf478
-#define	F367CAB_Q_TEST_TAP_L	0xf47800ff
-
-/* EQU_Q_TESTTAP_M */
-#define	R367CAB_EQU_Q_TESTTAP_M	0xf479
-#define	F367CAB_Q_TEST_TAP_M	0xf47900ff
-
-/* EQU_Q_TESTTAP_H */
-#define	R367CAB_EQU_Q_TESTTAP_H	0xf47a
-#define	F367CAB_Q_TEST_TAP_H	0xf47a001f
-
-/* EQU_TAP_CTRL */
-#define	R367CAB_EQU_TAP_CTRL	0xf47b
-#define	F367CAB_MTAP_FRZ	0xf47b0010
-#define	F367CAB_PRE_FREEZE	0xf47b0008
-#define	F367CAB_DFE_TAPMON_EN	0xf47b0004
-#define	F367CAB_FFE_TAPMON_EN	0xf47b0002
-#define	F367CAB_MTAP_ONLY	0xf47b0001
-
-/* EQU_CTR_CRL_CONTROL_L */
-#define	R367CAB_EQU_CTR_CRL_CONTROL_L	0xf47c
-#define	F367CAB_EQU_CTR_CRL_CONTROL_LO	0xf47c00ff
-
-/* EQU_CTR_CRL_CONTROL_H */
-#define	R367CAB_EQU_CTR_CRL_CONTROL_H	0xf47d
-#define	F367CAB_EQU_CTR_CRL_CONTROL_HI	0xf47d00ff
-
-/* EQU_CTR_HIPOW_L */
-#define	R367CAB_EQU_CTR_HIPOW_L	0xf47e
-#define	F367CAB_CTR_HIPOW_L	0xf47e00ff
-
-/* EQU_CTR_HIPOW_H */
-#define	R367CAB_EQU_CTR_HIPOW_H	0xf47f
-#define	F367CAB_CTR_HIPOW_H	0xf47f00ff
-
-/* EQU_I_EQU_LO */
-#define	R367CAB_EQU_I_EQU_LO	0xf480
-#define	F367CAB_EQU_I_EQU_L	0xf48000ff
-
-/* EQU_I_EQU_HI */
-#define	R367CAB_EQU_I_EQU_HI	0xf481
-#define	F367CAB_EQU_I_EQU_H	0xf4810003
-
-/* EQU_Q_EQU_LO */
-#define	R367CAB_EQU_Q_EQU_LO	0xf482
-#define	F367CAB_EQU_Q_EQU_L	0xf48200ff
-
-/* EQU_Q_EQU_HI */
-#define	R367CAB_EQU_Q_EQU_HI	0xf483
-#define	F367CAB_EQU_Q_EQU_H	0xf4830003
-
-/* EQU_MAPPER */
-#define	R367CAB_EQU_MAPPER	0xf484
-#define	F367CAB_QUAD_AUTO	0xf4840080
-#define	F367CAB_QUAD_INV	0xf4840040
-#define	F367CAB_QAM_MODE	0xf4840007
-
-/* EQU_SWEEP_RATE */
-#define	R367CAB_EQU_SWEEP_RATE	0xf485
-#define	F367CAB_SNR_PER	0xf48500c0
-#define	F367CAB_SWEEP_RATE	0xf485003f
-
-/* EQU_SNR_LO */
-#define	R367CAB_EQU_SNR_LO	0xf486
-#define	F367CAB_SNR_LO	0xf48600ff
-
-/* EQU_SNR_HI */
-#define	R367CAB_EQU_SNR_HI	0xf487
-#define	F367CAB_SNR_HI	0xf48700ff
-
-/* EQU_GAMMA_LO */
-#define	R367CAB_EQU_GAMMA_LO	0xf488
-#define	F367CAB_GAMMA_LO	0xf48800ff
-
-/* EQU_GAMMA_HI */
-#define	R367CAB_EQU_GAMMA_HI	0xf489
-#define	F367CAB_GAMMA_ME	0xf48900ff
-
-/* EQU_ERR_GAIN */
-#define	R367CAB_EQU_ERR_GAIN	0xf48a
-#define	F367CAB_EQA1MU	0xf48a0070
-#define	F367CAB_CRL2MU	0xf48a000e
-#define	F367CAB_GAMMA_HI	0xf48a0001
-
-/* EQU_RADIUS */
-#define	R367CAB_EQU_RADIUS	0xf48b
-#define	F367CAB_RADIUS	0xf48b00ff
-
-/* EQU_FFE_MAINTAP */
-#define	R367CAB_EQU_FFE_MAINTAP	0xf48c
-#define	F367CAB_FFE_MAINTAP_INIT	0xf48c00ff
-
-/* EQU_FFE_LEAKAGE */
-#define	R367CAB_EQU_FFE_LEAKAGE	0xf48e
-#define	F367CAB_LEAK_PER	0xf48e00f0
-#define	F367CAB_EQU_OUTSEL	0xf48e0002
-#define	F367CAB_PNT2dFE	0xf48e0001
-
-/* EQU_FFE_MAINTAP_POS */
-#define	R367CAB_EQU_FFE_MAINTAP_POS	0xf48f
-#define	F367CAB_FFE_LEAK_EN	0xf48f0080
-#define	F367CAB_DFE_LEAK_EN	0xf48f0040
-#define	F367CAB_FFE_MAINTAP_POS	0xf48f003f
-
-/* EQU_GAIN_WIDE */
-#define	R367CAB_EQU_GAIN_WIDE	0xf490
-#define	F367CAB_DFE_GAIN_WIDE	0xf49000f0
-#define	F367CAB_FFE_GAIN_WIDE	0xf490000f
-
-/* EQU_GAIN_NARROW */
-#define	R367CAB_EQU_GAIN_NARROW	0xf491
-#define	F367CAB_DFE_GAIN_NARROW	0xf49100f0
-#define	F367CAB_FFE_GAIN_NARROW	0xf491000f
-
-/* EQU_CTR_LPF_GAIN */
-#define	R367CAB_EQU_CTR_LPF_GAIN	0xf492
-#define	F367CAB_CTR_GTO	0xf4920080
-#define	F367CAB_CTR_GDIR	0xf4920070
-#define	F367CAB_SWEEP_EN	0xf4920008
-#define	F367CAB_CTR_GINT	0xf4920007
-
-/* EQU_CRL_LPF_GAIN */
-#define	R367CAB_EQU_CRL_LPF_GAIN	0xf493
-#define	F367CAB_CRL_GTO	0xf4930080
-#define	F367CAB_CRL_GDIR	0xf4930070
-#define	F367CAB_SWEEP_DIR	0xf4930008
-#define	F367CAB_CRL_GINT	0xf4930007
-
-/* EQU_GLOBAL_GAIN */
-#define	R367CAB_EQU_GLOBAL_GAIN	0xf494
-#define	F367CAB_CRL_GAIN	0xf49400f8
-#define	F367CAB_CTR_INC_GAIN	0xf4940004
-#define	F367CAB_CTR_FRAC	0xf4940003
-
-/* EQU_CRL_LD_SEN */
-#define	R367CAB_EQU_CRL_LD_SEN	0xf495
-#define	F367CAB_CTR_BADPOINT_EN	0xf4950080
-#define	F367CAB_CTR_GAIN	0xf4950070
-#define	F367CAB_LIMANEN	0xf4950008
-#define	F367CAB_CRL_LD_SEN	0xf4950007
-
-/* EQU_CRL_LD_VAL */
-#define	R367CAB_EQU_CRL_LD_VAL	0xf496
-#define	F367CAB_CRL_BISTH_LIMIT	0xf4960080
-#define	F367CAB_CARE_EN	0xf4960040
-#define	F367CAB_CRL_LD_PER	0xf4960030
-#define	F367CAB_CRL_LD_WST	0xf496000c
-#define	F367CAB_CRL_LD_TFS	0xf4960003
-
-/* EQU_CRL_TFR */
-#define	R367CAB_EQU_CRL_TFR	0xf497
-#define	F367CAB_CRL_LD_TFR	0xf49700ff
-
-/* EQU_CRL_BISTH_LO */
-#define	R367CAB_EQU_CRL_BISTH_LO	0xf498
-#define	F367CAB_CRL_BISTH_LO	0xf49800ff
-
-/* EQU_CRL_BISTH_HI */
-#define	R367CAB_EQU_CRL_BISTH_HI	0xf499
-#define	F367CAB_CRL_BISTH_HI	0xf49900ff
-
-/* EQU_SWEEP_RANGE_LO */
-#define	R367CAB_EQU_SWEEP_RANGE_LO	0xf49a
-#define	F367CAB_SWEEP_RANGE_LO	0xf49a00ff
-
-/* EQU_SWEEP_RANGE_HI */
-#define	R367CAB_EQU_SWEEP_RANGE_HI	0xf49b
-#define	F367CAB_SWEEP_RANGE_HI	0xf49b00ff
-
-/* EQU_CRL_LIMITER */
-#define	R367CAB_EQU_CRL_LIMITER	0xf49c
-#define	F367CAB_BISECTOR_EN	0xf49c0080
-#define	F367CAB_PHEST128_EN	0xf49c0040
-#define	F367CAB_CRL_LIM	0xf49c003f
-
-/* EQU_MODULUS_MAP */
-#define	R367CAB_EQU_MODULUS_MAP	0xf49d
-#define	F367CAB_PNT_DEPTH	0xf49d00e0
-#define	F367CAB_MODULUS_CMP	0xf49d001f
-
-/* EQU_PNT_GAIN */
-#define	R367CAB_EQU_PNT_GAIN	0xf49e
-#define	F367CAB_PNT_EN	0xf49e0080
-#define	F367CAB_MODULUSMAP_EN	0xf49e0040
-#define	F367CAB_PNT_GAIN	0xf49e003f
-
-/* FEC_AC_CTR_0 */
-#define	R367CAB_FEC_AC_CTR_0	0xf4a8
-#define	F367CAB_BE_BYPASS	0xf4a80020
-#define	F367CAB_REFRESH47	0xf4a80010
-#define	F367CAB_CT_NBST	0xf4a80008
-#define	F367CAB_TEI_ENA	0xf4a80004
-#define	F367CAB_DS_ENA	0xf4a80002
-#define	F367CAB_TSMF_EN	0xf4a80001
-
-/* FEC_AC_CTR_1 */
-#define	R367CAB_FEC_AC_CTR_1	0xf4a9
-#define	F367CAB_DEINT_DEPTH	0xf4a900ff
-
-/* FEC_AC_CTR_2 */
-#define	R367CAB_FEC_AC_CTR_2	0xf4aa
-#define	F367CAB_DEINT_M	0xf4aa00f8
-#define	F367CAB_DIS_UNLOCK	0xf4aa0004
-#define	F367CAB_DESCR_MODE	0xf4aa0003
-
-/* FEC_AC_CTR_3 */
-#define	R367CAB_FEC_AC_CTR_3	0xf4ab
-#define	F367CAB_DI_UNLOCK	0xf4ab0080
-#define	F367CAB_DI_FREEZE	0xf4ab0040
-#define	F367CAB_MISMATCH	0xf4ab0030
-#define	F367CAB_ACQ_MODE	0xf4ab000c
-#define	F367CAB_TRK_MODE	0xf4ab0003
-
-/* FEC_STATUS */
-#define	R367CAB_FEC_STATUS	0xf4ac
-#define	F367CAB_DEINT_SMCNTR	0xf4ac00e0
-#define	F367CAB_DEINT_SYNCSTATE	0xf4ac0018
-#define	F367CAB_DEINT_SYNLOST	0xf4ac0004
-#define	F367CAB_DESCR_SYNCSTATE	0xf4ac0002
-
-/* RS_COUNTER_0 */
-#define	R367CAB_RS_COUNTER_0	0xf4ae
-#define	F367CAB_BK_CT_L	0xf4ae00ff
-
-/* RS_COUNTER_1 */
-#define	R367CAB_RS_COUNTER_1	0xf4af
-#define	F367CAB_BK_CT_H	0xf4af00ff
-
-/* RS_COUNTER_2 */
-#define	R367CAB_RS_COUNTER_2	0xf4b0
-#define	F367CAB_CORR_CT_L	0xf4b000ff
-
-/* RS_COUNTER_3 */
-#define	R367CAB_RS_COUNTER_3	0xf4b1
-#define	F367CAB_CORR_CT_H	0xf4b100ff
-
-/* RS_COUNTER_4 */
-#define	R367CAB_RS_COUNTER_4	0xf4b2
-#define	F367CAB_UNCORR_CT_L	0xf4b200ff
-
-/* RS_COUNTER_5 */
-#define	R367CAB_RS_COUNTER_5	0xf4b3
-#define	F367CAB_UNCORR_CT_H	0xf4b300ff
-
-/* BERT_0 */
-#define	R367CAB_BERT_0	0xf4b4
-#define	F367CAB_RS_NOCORR	0xf4b40004
-#define	F367CAB_CT_HOLD	0xf4b40002
-#define	F367CAB_CT_CLEAR	0xf4b40001
-
-/* BERT_1 */
-#define	R367CAB_BERT_1	0xf4b5
-#define	F367CAB_BERT_ON	0xf4b50020
-#define	F367CAB_BERT_ERR_SRC	0xf4b50010
-#define	F367CAB_BERT_ERR_MODE	0xf4b50008
-#define	F367CAB_BERT_NBYTE	0xf4b50007
-
-/* BERT_2 */
-#define	R367CAB_BERT_2	0xf4b6
-#define	F367CAB_BERT_ERRCOUNT_L	0xf4b600ff
-
-/* BERT_3 */
-#define	R367CAB_BERT_3	0xf4b7
-#define	F367CAB_BERT_ERRCOUNT_H	0xf4b700ff
-
-/* OUTFORMAT_0 */
-#define	R367CAB_OUTFORMAT_0	0xf4b8
-#define	F367CAB_CLK_POLARITY	0xf4b80080
-#define	F367CAB_FEC_TYPE	0xf4b80040
-#define	F367CAB_SYNC_STRIP	0xf4b80008
-#define	F367CAB_TS_SWAP	0xf4b80004
-#define	F367CAB_OUTFORMAT	0xf4b80003
-
-/* OUTFORMAT_1 */
-#define	R367CAB_OUTFORMAT_1	0xf4b9
-#define	F367CAB_CI_DIVRANGE	0xf4b900ff
-
-/* SMOOTHER_2 */
-#define	R367CAB_SMOOTHER_2	0xf4be
-#define	F367CAB_FIFO_BYPASS	0xf4be0020
-
-/* TSMF_CTRL_0 */
-#define	R367CAB_TSMF_CTRL_0	0xf4c0
-#define	F367CAB_TS_NUMBER	0xf4c0001e
-#define	F367CAB_SEL_MODE	0xf4c00001
-
-/* TSMF_CTRL_1 */
-#define	R367CAB_TSMF_CTRL_1	0xf4c1
-#define	F367CAB_CHECK_ERROR_BIT	0xf4c10080
-#define	F367CAB_CHCK_F_SYNC	0xf4c10040
-#define	F367CAB_H_MODE	0xf4c10008
-#define	F367CAB_D_V_MODE	0xf4c10004
-#define	F367CAB_MODE	0xf4c10003
-
-/* TSMF_CTRL_3 */
-#define	R367CAB_TSMF_CTRL_3	0xf4c3
-#define	F367CAB_SYNC_IN_COUNT	0xf4c300f0
-#define	F367CAB_SYNC_OUT_COUNT	0xf4c3000f
-
-/* TS_ON_ID_0 */
-#define	R367CAB_TS_ON_ID_0	0xf4c4
-#define	F367CAB_TS_ID_L	0xf4c400ff
-
-/* TS_ON_ID_1 */
-#define	R367CAB_TS_ON_ID_1	0xf4c5
-#define	F367CAB_TS_ID_H	0xf4c500ff
-
-/* TS_ON_ID_2 */
-#define	R367CAB_TS_ON_ID_2	0xf4c6
-#define	F367CAB_ON_ID_L	0xf4c600ff
-
-/* TS_ON_ID_3 */
-#define	R367CAB_TS_ON_ID_3	0xf4c7
-#define	F367CAB_ON_ID_H	0xf4c700ff
-
-/* RE_STATUS_0 */
-#define	R367CAB_RE_STATUS_0	0xf4c8
-#define	F367CAB_RECEIVE_STATUS_L	0xf4c800ff
-
-/* RE_STATUS_1 */
-#define	R367CAB_RE_STATUS_1	0xf4c9
-#define	F367CAB_RECEIVE_STATUS_LH	0xf4c900ff
-
-/* RE_STATUS_2 */
-#define	R367CAB_RE_STATUS_2	0xf4ca
-#define	F367CAB_RECEIVE_STATUS_HL	0xf4ca00ff
-
-/* RE_STATUS_3 */
-#define	R367CAB_RE_STATUS_3	0xf4cb
-#define	F367CAB_RECEIVE_STATUS_HH	0xf4cb003f
-
-/* TS_STATUS_0 */
-#define	R367CAB_TS_STATUS_0	0xf4cc
-#define	F367CAB_TS_STATUS_L	0xf4cc00ff
-
-/* TS_STATUS_1 */
-#define	R367CAB_TS_STATUS_1	0xf4cd
-#define	F367CAB_TS_STATUS_H	0xf4cd007f
-
-/* TS_STATUS_2 */
-#define	R367CAB_TS_STATUS_2	0xf4ce
-#define	F367CAB_ERROR	0xf4ce0080
-#define	F367CAB_EMERGENCY	0xf4ce0040
-#define	F367CAB_CRE_TS	0xf4ce0030
-#define	F367CAB_VER	0xf4ce000e
-#define	F367CAB_M_LOCK	0xf4ce0001
-
-/* TS_STATUS_3 */
-#define	R367CAB_TS_STATUS_3	0xf4cf
-#define	F367CAB_UPDATE_READY	0xf4cf0080
-#define	F367CAB_END_FRAME_HEADER	0xf4cf0040
-#define	F367CAB_CONTCNT	0xf4cf0020
-#define	F367CAB_TS_IDENTIFIER_SEL	0xf4cf000f
-
-/* T_O_ID_0 */
-#define	R367CAB_T_O_ID_0	0xf4d0
-#define	F367CAB_ON_ID_I_L	0xf4d000ff
-
-/* T_O_ID_1 */
-#define	R367CAB_T_O_ID_1	0xf4d1
-#define	F367CAB_ON_ID_I_H	0xf4d100ff
-
-/* T_O_ID_2 */
-#define	R367CAB_T_O_ID_2	0xf4d2
-#define	F367CAB_TS_ID_I_L	0xf4d200ff
-
-/* T_O_ID_3 */
-#define	R367CAB_T_O_ID_3	0xf4d3
-#define	F367CAB_TS_ID_I_H	0xf4d300ff
-
-#define STV0367CAB_NBREGS	187
-
-#endif
diff --git a/drivers/media/dvb/frontends/stv0900.h b/drivers/media/dvb/frontends/stv0900.h
deleted file mode 100644
index 91c7ee8..0000000
--- a/drivers/media/dvb/frontends/stv0900.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * 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_reg {
-	u16 addr;
-	u8  val;
-};
-
-struct stv0900_config {
-	u8 demod_address;
-	u8 demod_mode;
-	u32 xtal;
-	u8 clkmode;/* 0 for CLKI,  2 for XTALI */
-
-	u8 diseqc_mode;
-
-	u8 path1_mode;
-	u8 path2_mode;
-	struct stv0900_reg *ts_config_regs;
-	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;
-	u8 tun1_type;/* for now 3 for stb6100 auto, else - software */
-	u8 tun2_type;
-	/* Set device param to start dma */
-	int (*set_ts_params)(struct dvb_frontend *fe, int is_punctured);
-	/* Hook for Lock LED */
-	void (*set_lock_led)(struct dvb_frontend *fe, int offon);
-};
-
-#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
deleted file mode 100644
index 7f1bada..0000000
--- a/drivers/media/dvb/frontends/stv0900_core.c
+++ /dev/null
@@ -1,1959 +0,0 @@
-/*
- * 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"
-
-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 *intp, u16 reg_addr,
-								u8 reg_data)
-{
-	u8 data[3];
-	int ret;
-	struct i2c_msg i2cmsg = {
-		.addr  = intp->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(intp->i2c_adap, &i2cmsg, 1);
-	if (ret != 1)
-		dprintk("%s: i2c error %d\n", __func__, ret);
-}
-
-u8 stv0900_read_reg(struct stv0900_internal *intp, u16 reg)
-{
-	int ret;
-	u8 b0[] = { MSB(reg), LSB(reg) };
-	u8 buf = 0;
-	struct i2c_msg msg[] = {
-		{
-			.addr	= intp->i2c_addr,
-			.flags	= 0,
-			.buf = b0,
-			.len = 2,
-		}, {
-			.addr	= intp->i2c_addr,
-			.flags	= I2C_M_RD,
-			.buf = &buf,
-			.len = 1,
-		},
-	};
-
-	ret = i2c_transfer(intp->i2c_adap, msg, 2);
-	if (ret != 2)
-		dprintk("%s: i2c error %d, reg[0x%02x]\n",
-				__func__, ret, reg);
-
-	return buf;
-}
-
-static 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 *intp, u32 label, u8 val)
-{
-	u8 reg, mask, pos;
-
-	reg = stv0900_read_reg(intp, (label >> 16) & 0xffff);
-	extract_mask_pos(label, &mask, &pos);
-
-	val = mask & (val << pos);
-
-	reg = (reg & (~mask)) | val;
-	stv0900_write_reg(intp, (label >> 16) & 0xffff, reg);
-
-}
-
-u8 stv0900_get_bits(struct stv0900_internal *intp, u32 label)
-{
-	u8 val = 0xff;
-	u8 mask, pos;
-
-	extract_mask_pos(label, &mask, &pos);
-
-	val = stv0900_read_reg(intp, label >> 16);
-	val = (val & mask) >> pos;
-
-	return val;
-}
-
-static enum fe_stv0900_error stv0900_initialize(struct stv0900_internal *intp)
-{
-	s32 i;
-
-	if (intp == NULL)
-		return STV0900_INVALID_HANDLE;
-
-	intp->chip_id = stv0900_read_reg(intp, R0900_MID);
-
-	if (intp->errs != STV0900_NO_ERROR)
-		return intp->errs;
-
-	/*Startup sequence*/
-	stv0900_write_reg(intp, R0900_P1_DMDISTATE, 0x5c);
-	stv0900_write_reg(intp, R0900_P2_DMDISTATE, 0x5c);
-	msleep(3);
-	stv0900_write_reg(intp, R0900_P1_TNRCFG, 0x6c);
-	stv0900_write_reg(intp, R0900_P2_TNRCFG, 0x6f);
-	stv0900_write_reg(intp, R0900_P1_I2CRPT, 0x20);
-	stv0900_write_reg(intp, R0900_P2_I2CRPT, 0x20);
-	stv0900_write_reg(intp, R0900_NCOARSE, 0x13);
-	msleep(3);
-	stv0900_write_reg(intp, R0900_I2CCFG, 0x08);
-
-	switch (intp->clkmode) {
-	case 0:
-	case 2:
-		stv0900_write_reg(intp, R0900_SYNTCTRL, 0x20
-				| intp->clkmode);
-		break;
-	default:
-		/* preserve SELOSCI bit */
-		i = 0x02 & stv0900_read_reg(intp, R0900_SYNTCTRL);
-		stv0900_write_reg(intp, R0900_SYNTCTRL, 0x20 | i);
-		break;
-	}
-
-	msleep(3);
-	for (i = 0; i < 181; i++)
-		stv0900_write_reg(intp, STV0900_InitVal[i][0],
-				STV0900_InitVal[i][1]);
-
-	if (stv0900_read_reg(intp, R0900_MID) >= 0x20) {
-		stv0900_write_reg(intp, R0900_TSGENERAL, 0x0c);
-		for (i = 0; i < 32; i++)
-			stv0900_write_reg(intp, STV0900_Cut20_AddOnVal[i][0],
-					STV0900_Cut20_AddOnVal[i][1]);
-	}
-
-	stv0900_write_reg(intp, R0900_P1_FSPYCFG, 0x6c);
-	stv0900_write_reg(intp, R0900_P2_FSPYCFG, 0x6c);
-
-	stv0900_write_reg(intp, R0900_P1_PDELCTRL2, 0x01);
-	stv0900_write_reg(intp, R0900_P2_PDELCTRL2, 0x21);
-
-	stv0900_write_reg(intp, R0900_P1_PDELCTRL3, 0x20);
-	stv0900_write_reg(intp, R0900_P2_PDELCTRL3, 0x20);
-
-	stv0900_write_reg(intp, R0900_TSTRES0, 0x80);
-	stv0900_write_reg(intp, R0900_TSTRES0, 0x00);
-
-	return STV0900_NO_ERROR;
-}
-
-static u32 stv0900_get_mclk_freq(struct stv0900_internal *intp, u32 ext_clk)
-{
-	u32 mclk = 90000000, div = 0, ad_div = 0;
-
-	div = stv0900_get_bits(intp, F0900_M_DIV);
-	ad_div = ((stv0900_get_bits(intp, F0900_SELX1RATIO) == 1) ? 4 : 6);
-
-	mclk = (div + 1) * ext_clk / ad_div;
-
-	dprintk("%s: Calculated Mclk = %d\n", __func__, mclk);
-
-	return mclk;
-}
-
-static enum fe_stv0900_error stv0900_set_mclk(struct stv0900_internal *intp, u32 mclk)
-{
-	u32 m_div, clk_sel;
-
-	dprintk("%s: Mclk set to %d, Quartz = %d\n", __func__, mclk,
-			intp->quartz);
-
-	if (intp == NULL)
-		return STV0900_INVALID_HANDLE;
-
-	if (intp->errs)
-		return STV0900_I2C_ERROR;
-
-	clk_sel = ((stv0900_get_bits(intp, F0900_SELX1RATIO) == 1) ? 4 : 6);
-	m_div = ((clk_sel * mclk) / intp->quartz) - 1;
-	stv0900_write_bits(intp, F0900_M_DIV, m_div);
-	intp->mclk = stv0900_get_mclk_freq(intp,
-					intp->quartz);
-
-	/*Set the DiseqC frequency to 22KHz */
-	/*
-		Formula:
-		DiseqC_TX_Freq= MasterClock/(32*F22TX_Reg)
-		DiseqC_RX_Freq= MasterClock/(32*F22RX_Reg)
-	*/
-	m_div = intp->mclk / 704000;
-	stv0900_write_reg(intp, R0900_P1_F22TX, m_div);
-	stv0900_write_reg(intp, R0900_P1_F22RX, m_div);
-
-	stv0900_write_reg(intp, R0900_P2_F22TX, m_div);
-	stv0900_write_reg(intp, R0900_P2_F22RX, m_div);
-
-	if ((intp->errs))
-		return STV0900_I2C_ERROR;
-
-	return STV0900_NO_ERROR;
-}
-
-static u32 stv0900_get_err_count(struct stv0900_internal *intp, int cntr,
-					enum fe_stv0900_demod_num demod)
-{
-	u32 lsb, msb, hsb, err_val;
-
-	switch (cntr) {
-	case 0:
-	default:
-		hsb = stv0900_get_bits(intp, ERR_CNT12);
-		msb = stv0900_get_bits(intp, ERR_CNT11);
-		lsb = stv0900_get_bits(intp, ERR_CNT10);
-		break;
-	case 1:
-		hsb = stv0900_get_bits(intp, ERR_CNT22);
-		msb = stv0900_get_bits(intp, ERR_CNT21);
-		lsb = stv0900_get_bits(intp, ERR_CNT20);
-		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 *intp = state->internal;
-	enum fe_stv0900_demod_num demod = state->demod;
-
-	stv0900_write_bits(intp, I2CT_ON, enable);
-
-	return 0;
-}
-
-static void stv0900_set_ts_parallel_serial(struct stv0900_internal *intp,
-					enum fe_stv0900_clock_type path1_ts,
-					enum fe_stv0900_clock_type path2_ts)
-{
-
-	dprintk("%s\n", __func__);
-
-	if (intp->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(intp, R0900_TSGENERAL,
-							0x00);
-				break;
-			case STV0900_PARALLEL_PUNCT_CLOCK:
-			case STV0900_DVBCI_CLOCK:
-				stv0900_write_reg(intp, R0900_TSGENERAL,
-							0x06);
-				stv0900_write_bits(intp,
-						F0900_P1_TSFIFO_MANSPEED, 3);
-				stv0900_write_bits(intp,
-						F0900_P2_TSFIFO_MANSPEED, 0);
-				stv0900_write_reg(intp,
-						R0900_P1_TSSPEED, 0x14);
-				stv0900_write_reg(intp,
-						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(intp,
-						R0900_TSGENERAL, 0x0C);
-				break;
-			case STV0900_PARALLEL_PUNCT_CLOCK:
-			case STV0900_DVBCI_CLOCK:
-				stv0900_write_reg(intp,
-						R0900_TSGENERAL, 0x0A);
-				dprintk("%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(intp, R0900_TSGENERAL1X,
-							0x10);
-				break;
-			case STV0900_PARALLEL_PUNCT_CLOCK:
-			case STV0900_DVBCI_CLOCK:
-				stv0900_write_reg(intp, R0900_TSGENERAL1X,
-							0x16);
-				stv0900_write_bits(intp,
-						F0900_P1_TSFIFO_MANSPEED, 3);
-				stv0900_write_bits(intp,
-						F0900_P2_TSFIFO_MANSPEED, 0);
-				stv0900_write_reg(intp, R0900_P1_TSSPEED,
-							0x14);
-				stv0900_write_reg(intp, 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(intp, R0900_TSGENERAL1X,
-							0x14);
-				break;
-			case STV0900_PARALLEL_PUNCT_CLOCK:
-			case STV0900_DVBCI_CLOCK:
-				stv0900_write_reg(intp, R0900_TSGENERAL1X,
-							0x12);
-				dprintk("%s: 0x12\n", __func__);
-				break;
-			}
-
-			break;
-		}
-	}
-
-	switch (path1_ts) {
-	case STV0900_PARALLEL_PUNCT_CLOCK:
-		stv0900_write_bits(intp, F0900_P1_TSFIFO_SERIAL, 0x00);
-		stv0900_write_bits(intp, F0900_P1_TSFIFO_DVBCI, 0x00);
-		break;
-	case STV0900_DVBCI_CLOCK:
-		stv0900_write_bits(intp, F0900_P1_TSFIFO_SERIAL, 0x00);
-		stv0900_write_bits(intp, F0900_P1_TSFIFO_DVBCI, 0x01);
-		break;
-	case STV0900_SERIAL_PUNCT_CLOCK:
-		stv0900_write_bits(intp, F0900_P1_TSFIFO_SERIAL, 0x01);
-		stv0900_write_bits(intp, F0900_P1_TSFIFO_DVBCI, 0x00);
-		break;
-	case STV0900_SERIAL_CONT_CLOCK:
-		stv0900_write_bits(intp, F0900_P1_TSFIFO_SERIAL, 0x01);
-		stv0900_write_bits(intp, F0900_P1_TSFIFO_DVBCI, 0x01);
-		break;
-	default:
-		break;
-	}
-
-	switch (path2_ts) {
-	case STV0900_PARALLEL_PUNCT_CLOCK:
-		stv0900_write_bits(intp, F0900_P2_TSFIFO_SERIAL, 0x00);
-		stv0900_write_bits(intp, F0900_P2_TSFIFO_DVBCI, 0x00);
-		break;
-	case STV0900_DVBCI_CLOCK:
-		stv0900_write_bits(intp, F0900_P2_TSFIFO_SERIAL, 0x00);
-		stv0900_write_bits(intp, F0900_P2_TSFIFO_DVBCI, 0x01);
-		break;
-	case STV0900_SERIAL_PUNCT_CLOCK:
-		stv0900_write_bits(intp, F0900_P2_TSFIFO_SERIAL, 0x01);
-		stv0900_write_bits(intp, F0900_P2_TSFIFO_DVBCI, 0x00);
-		break;
-	case STV0900_SERIAL_CONT_CLOCK:
-		stv0900_write_bits(intp, F0900_P2_TSFIFO_SERIAL, 0x01);
-		stv0900_write_bits(intp, F0900_P2_TSFIFO_DVBCI, 0x01);
-		break;
-	default:
-		break;
-	}
-
-	stv0900_write_bits(intp, F0900_P2_RST_HWARE, 1);
-	stv0900_write_bits(intp, F0900_P2_RST_HWARE, 0);
-	stv0900_write_bits(intp, F0900_P1_RST_HWARE, 1);
-	stv0900_write_bits(intp, 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);
-
-	}
-}
-
-u32 stv0900_get_freq_auto(struct stv0900_internal *intp, int demod)
-{
-	u32 freq, round;
-	/*	Formulat :
-	Tuner_Frequency(MHz)	= Regs / 64
-	Tuner_granularity(MHz)	= Regs / 2048
-	real_Tuner_Frequency	= Tuner_Frequency(MHz) - Tuner_granularity(MHz)
-	*/
-	freq = (stv0900_get_bits(intp, TUN_RFFREQ2) << 10) +
-		(stv0900_get_bits(intp, TUN_RFFREQ1) << 2) +
-		stv0900_get_bits(intp, TUN_RFFREQ0);
-
-	freq = (freq * 1000) / 64;
-
-	round = (stv0900_get_bits(intp, TUN_RFRESTE1) >> 2) +
-		stv0900_get_bits(intp, TUN_RFRESTE0);
-
-	round = (round * 1000) / 2048;
-
-	return freq + round;
-}
-
-void stv0900_set_tuner_auto(struct stv0900_internal *intp, u32 Frequency,
-						u32 Bandwidth, int demod)
-{
-	u32 tunerFrequency;
-	/* Formulat:
-	Tuner_frequency_reg= Frequency(MHz)*64
-	*/
-	tunerFrequency = (Frequency * 64) / 1000;
-
-	stv0900_write_bits(intp, TUN_RFFREQ2, (tunerFrequency >> 10));
-	stv0900_write_bits(intp, TUN_RFFREQ1, (tunerFrequency >> 2) & 0xff);
-	stv0900_write_bits(intp, TUN_RFFREQ0, (tunerFrequency & 0x03));
-	/* Low Pass Filter = BW /2 (MHz)*/
-	stv0900_write_bits(intp, TUN_BW, Bandwidth / 2000000);
-	/* Tuner Write trig */
-	stv0900_write_reg(intp, TNRLD, 1);
-}
-
-static s32 stv0900_get_rf_level(struct stv0900_internal *intp,
-				const struct stv0900_table *lookup,
-				enum fe_stv0900_demod_num demod)
-{
-	s32 agc_gain = 0,
-		imin,
-		imax,
-		i,
-		rf_lvl = 0;
-
-	dprintk("%s\n", __func__);
-
-	if ((lookup == NULL) || (lookup->size <= 0))
-		return 0;
-
-	agc_gain = MAKEWORD(stv0900_get_bits(intp, AGCIQ_VALUE1),
-				stv0900_get_bits(intp, AGCIQ_VALUE0));
-
-	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;
-		rf_lvl *= (lookup->table[imax].realval -
-				lookup->table[imin].realval);
-		rf_lvl /= (lookup->table[imax].regval -
-				lookup->table[imin].regval);
-		rf_lvl += 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("%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);
-
-	rflevel = (rflevel + 100) * (65535 / 70);
-	if (rflevel < 0)
-		rflevel = 0;
-
-	if (rflevel > 65535)
-		rflevel = 65535;
-
-	*strength = rflevel;
-
-	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 *intp = state->internal;
-	enum fe_stv0900_demod_num demod = state->demod;
-
-	s32	c_n = -100,
-		regval,
-		imin,
-		imax,
-		i,
-		noise_field1,
-		noise_field0;
-
-	dprintk("%s\n", __func__);
-
-	if (stv0900_get_standard(fe, demod) == STV0900_DVBS2_STANDARD) {
-		noise_field1 = NOSPLHT_NORMED1;
-		noise_field0 = NOSPLHT_NORMED0;
-	} else {
-		noise_field1 = NOSDATAT_NORMED1;
-		noise_field0 = NOSDATAT_NORMED0;
-	}
-
-	if (stv0900_get_bits(intp, LOCK_DEFINITIF)) {
-		if ((lookup != NULL) && lookup->size) {
-			regval = 0;
-			msleep(5);
-			for (i = 0; i < 16; i++) {
-				regval += MAKEWORD(stv0900_get_bits(intp,
-								noise_field1),
-						stv0900_get_bits(intp,
-								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_ucblocks(struct dvb_frontend *fe, u32 * ucblocks)
-{
-	struct stv0900_state *state = fe->demodulator_priv;
-	struct stv0900_internal *intp = state->internal;
-	enum fe_stv0900_demod_num demod = state->demod;
-	u8 err_val1, err_val0;
-	u32 header_err_val = 0;
-
-	*ucblocks = 0x0;
-	if (stv0900_get_standard(fe, demod) == STV0900_DVBS2_STANDARD) {
-		/* DVB-S2 delineator errors count */
-
-		/* retreiving number for errnous headers */
-		err_val1 = stv0900_read_reg(intp, BBFCRCKO1);
-		err_val0 = stv0900_read_reg(intp, BBFCRCKO0);
-		header_err_val = (err_val1 << 8) | err_val0;
-
-		/* retreiving number for errnous packets */
-		err_val1 = stv0900_read_reg(intp, UPCRCKO1);
-		err_val0 = stv0900_read_reg(intp, UPCRCKO0);
-		*ucblocks = (err_val1 << 8) | err_val0;
-		*ucblocks += header_err_val;
-	}
-
-	return 0;
-}
-
-static int stv0900_read_snr(struct dvb_frontend *fe, u16 *snr)
-{
-	s32 snrlcl = stv0900_carr_get_quality(fe,
-			(const struct stv0900_table *)&stv0900_s2_cn);
-	snrlcl = (snrlcl + 30) * 384;
-	if (snrlcl < 0)
-		snrlcl = 0;
-
-	if (snrlcl > 65535)
-		snrlcl = 65535;
-
-	*snr = snrlcl;
-
-	return 0;
-}
-
-static u32 stv0900_get_ber(struct stv0900_internal *intp,
-				enum fe_stv0900_demod_num demod)
-{
-	u32 ber = 10000000, i;
-	s32 demod_state;
-
-	demod_state = stv0900_get_bits(intp, HEADER_MODE);
-
-	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(intp, 0, demod);
-		}
-
-		ber /= 5;
-		if (stv0900_get_bits(intp, PRFVIT)) {
-			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(intp, 0, demod);
-		}
-
-		ber /= 5;
-		if (stv0900_get_bits(intp, PKTDELIN_LOCK)) {
-			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 *intp,
-			enum fe_stv0900_demod_num demod, s32 time_out)
-{
-	s32 timer = 0,
-		lock = 0;
-
-	enum fe_stv0900_search_state	dmd_state;
-
-	while ((timer < time_out) && (lock == 0)) {
-		dmd_state = stv0900_get_bits(intp, HEADER_MODE);
-		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(intp, LOCK_DEFINITIF);
-			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 *intp,
-				enum fe_stv0900_demod_num demod)
-{
-	s32 regflist,
-	i;
-
-	dprintk("%s\n", __func__);
-
-	regflist = MODCODLST0;
-
-	for (i = 0; i < 16; i++)
-		stv0900_write_reg(intp, regflist + i, 0xff);
-}
-
-void stv0900_activate_s2_modcod(struct stv0900_internal *intp,
-				enum fe_stv0900_demod_num demod)
-{
-	u32 matype,
-		mod_code,
-		fmod,
-		reg_index,
-		field_index;
-
-	dprintk("%s\n", __func__);
-
-	if (intp->chip_id <= 0x11) {
-		msleep(5);
-
-		mod_code = stv0900_read_reg(intp, PLHMODCOD);
-		matype = mod_code & 0x3;
-		mod_code = (mod_code & 0x7f) >> 2;
-
-		reg_index = MODCODLSTF - mod_code / 2;
-		field_index = mod_code % 2;
-
-		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(intp, reg_index,
-							0xf0 | fmod);
-			else
-				stv0900_write_reg(intp, reg_index,
-							(fmod << 4) | 0xf);
-		}
-
-	} else if (intp->chip_id >= 0x12) {
-		for (reg_index = 0; reg_index < 7; reg_index++)
-			stv0900_write_reg(intp, MODCODLST0 + reg_index, 0xff);
-
-		stv0900_write_reg(intp, MODCODLSTE, 0xff);
-		stv0900_write_reg(intp, MODCODLSTF, 0xcf);
-		for (reg_index = 0; reg_index < 8; reg_index++)
-			stv0900_write_reg(intp, MODCODLST7 + reg_index, 0xcc);
-
-
-	}
-}
-
-void stv0900_activate_s2_modcod_single(struct stv0900_internal *intp,
-					enum fe_stv0900_demod_num demod)
-{
-	u32 reg_index;
-
-	dprintk("%s\n", __func__);
-
-	stv0900_write_reg(intp, MODCODLST0, 0xff);
-	stv0900_write_reg(intp, MODCODLST1, 0xf0);
-	stv0900_write_reg(intp, MODCODLSTF, 0x0f);
-	for (reg_index = 0; reg_index < 13; reg_index++)
-		stv0900_write_reg(intp, MODCODLST2 + reg_index, 0);
-
-}
-
-static enum dvbfe_algo stv0900_frontend_algo(struct dvb_frontend *fe)
-{
-	return DVBFE_ALGO_CUSTOM;
-}
-
-void stv0900_start_search(struct stv0900_internal *intp,
-				enum fe_stv0900_demod_num demod)
-{
-	u32 freq;
-	s16 freq_s16 ;
-
-	stv0900_write_bits(intp, DEMOD_MODE, 0x1f);
-	if (intp->chip_id == 0x10)
-		stv0900_write_reg(intp, CORRELEXP, 0xaa);
-
-	if (intp->chip_id < 0x20)
-		stv0900_write_reg(intp, CARHDR, 0x55);
-
-	if (intp->chip_id <= 0x20) {
-		if (intp->symbol_rate[0] <= 5000000) {
-			stv0900_write_reg(intp, CARCFG, 0x44);
-			stv0900_write_reg(intp, CFRUP1, 0x0f);
-			stv0900_write_reg(intp, CFRUP0, 0xff);
-			stv0900_write_reg(intp, CFRLOW1, 0xf0);
-			stv0900_write_reg(intp, CFRLOW0, 0x00);
-			stv0900_write_reg(intp, RTCS2, 0x68);
-		} else {
-			stv0900_write_reg(intp, CARCFG, 0xc4);
-			stv0900_write_reg(intp, RTCS2, 0x44);
-		}
-
-	} else { /*cut 3.0 above*/
-		if (intp->symbol_rate[demod] <= 5000000)
-			stv0900_write_reg(intp, RTCS2, 0x68);
-		else
-			stv0900_write_reg(intp, RTCS2, 0x44);
-
-		stv0900_write_reg(intp, CARCFG, 0x46);
-		if (intp->srch_algo[demod] == STV0900_WARM_START) {
-			freq = 1000 << 16;
-			freq /= (intp->mclk / 1000);
-			freq_s16 = (s16)freq;
-		} else {
-			freq = (intp->srch_range[demod] / 2000);
-			if (intp->symbol_rate[demod] <= 5000000)
-				freq += 80;
-			else
-				freq += 600;
-
-			freq = freq << 16;
-			freq /= (intp->mclk / 1000);
-			freq_s16 = (s16)freq;
-		}
-
-		stv0900_write_bits(intp, CFR_UP1, MSB(freq_s16));
-		stv0900_write_bits(intp, CFR_UP0, LSB(freq_s16));
-		freq_s16 *= (-1);
-		stv0900_write_bits(intp, CFR_LOW1, MSB(freq_s16));
-		stv0900_write_bits(intp, CFR_LOW0, LSB(freq_s16));
-	}
-
-	stv0900_write_reg(intp, CFRINIT1, 0);
-	stv0900_write_reg(intp, CFRINIT0, 0);
-
-	if (intp->chip_id >= 0x20) {
-		stv0900_write_reg(intp, EQUALCFG, 0x41);
-		stv0900_write_reg(intp, FFECFG, 0x41);
-
-		if ((intp->srch_standard[demod] == STV0900_SEARCH_DVBS1) ||
-			(intp->srch_standard[demod] == STV0900_SEARCH_DSS) ||
-			(intp->srch_standard[demod] == STV0900_AUTO_SEARCH)) {
-			stv0900_write_reg(intp, VITSCALE,
-								0x82);
-			stv0900_write_reg(intp, VAVSRVIT, 0x0);
-		}
-	}
-
-	stv0900_write_reg(intp, SFRSTEP, 0x00);
-	stv0900_write_reg(intp, TMGTHRISE, 0xe0);
-	stv0900_write_reg(intp, TMGTHFALL, 0xc0);
-	stv0900_write_bits(intp, SCAN_ENABLE, 0);
-	stv0900_write_bits(intp, CFR_AUTOSCAN, 0);
-	stv0900_write_bits(intp, S1S2_SEQUENTIAL, 0);
-	stv0900_write_reg(intp, RTC, 0x88);
-	if (intp->chip_id >= 0x20) {
-		if (intp->symbol_rate[demod] < 2000000) {
-			if (intp->chip_id <= 0x20)
-				stv0900_write_reg(intp, CARFREQ, 0x39);
-			else  /*cut 3.0*/
-				stv0900_write_reg(intp, CARFREQ, 0x89);
-
-			stv0900_write_reg(intp, CARHDR, 0x40);
-		} else if (intp->symbol_rate[demod] < 10000000) {
-			stv0900_write_reg(intp, CARFREQ, 0x4c);
-			stv0900_write_reg(intp, CARHDR, 0x20);
-		} else {
-			stv0900_write_reg(intp, CARFREQ, 0x4b);
-			stv0900_write_reg(intp, CARHDR, 0x20);
-		}
-
-	} else {
-		if (intp->symbol_rate[demod] < 10000000)
-			stv0900_write_reg(intp, CARFREQ, 0xef);
-		else
-			stv0900_write_reg(intp, CARFREQ, 0xed);
-	}
-
-	switch (intp->srch_algo[demod]) {
-	case STV0900_WARM_START:
-		stv0900_write_reg(intp, DMDISTATE, 0x1f);
-		stv0900_write_reg(intp, DMDISTATE, 0x18);
-		break;
-	case STV0900_COLD_START:
-		stv0900_write_reg(intp, DMDISTATE, 0x1f);
-		stv0900_write_reg(intp, DMDISTATE, 0x15);
-		break;
-	default:
-		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 *cls2, *cllqs2, *cllas2;
-
-	dprintk("%s\n", __func__);
-
-	if (chip_id <= 0x12) {
-		cls2 = FE_STV0900_S2CarLoop;
-		cllqs2 = FE_STV0900_S2LowQPCarLoopCut30;
-		cllas2 = FE_STV0900_S2APSKCarLoopCut30;
-	} else if (chip_id == 0x20) {
-		cls2 = FE_STV0900_S2CarLoopCut20;
-		cllqs2 = FE_STV0900_S2LowQPCarLoopCut20;
-		cllas2 = FE_STV0900_S2APSKCarLoopCut20;
-	} else {
-		cls2 = FE_STV0900_S2CarLoopCut30;
-		cllqs2 = FE_STV0900_S2LowQPCarLoopCut30;
-		cllas2 = FE_STV0900_S2APSKCarLoopCut30;
-	}
-
-	if (modcode < STV0900_QPSK_12) {
-		i = 0;
-		while ((i < 3) && (modcode != cllqs2[i].modcode))
-			i++;
-
-		if (i >= 3)
-			i = 2;
-	} else {
-		i = 0;
-		while ((i < 14) && (modcode != cls2[i].modcode))
-			i++;
-
-		if (i >= 14) {
-			i = 0;
-			while ((i < 11) && (modcode != cllas2[i].modcode))
-				i++;
-
-			if (i >= 11)
-				i = 10;
-		}
-	}
-
-	if (modcode <= STV0900_QPSK_25) {
-		if (pilot) {
-			if (srate <= 3000000)
-				aclc_value = cllqs2[i].car_loop_pilots_on_2;
-			else if (srate <= 7000000)
-				aclc_value = cllqs2[i].car_loop_pilots_on_5;
-			else if (srate <= 15000000)
-				aclc_value = cllqs2[i].car_loop_pilots_on_10;
-			else if (srate <= 25000000)
-				aclc_value = cllqs2[i].car_loop_pilots_on_20;
-			else
-				aclc_value = cllqs2[i].car_loop_pilots_on_30;
-		} else {
-			if (srate <= 3000000)
-				aclc_value = cllqs2[i].car_loop_pilots_off_2;
-			else if (srate <= 7000000)
-				aclc_value = cllqs2[i].car_loop_pilots_off_5;
-			else if (srate <= 15000000)
-				aclc_value = cllqs2[i].car_loop_pilots_off_10;
-			else if (srate <= 25000000)
-				aclc_value = cllqs2[i].car_loop_pilots_off_20;
-			else
-				aclc_value = cllqs2[i].car_loop_pilots_off_30;
-		}
-
-	} else if (modcode <= STV0900_8PSK_910) {
-		if (pilot) {
-			if (srate <= 3000000)
-				aclc_value = cls2[i].car_loop_pilots_on_2;
-			else if (srate <= 7000000)
-				aclc_value = cls2[i].car_loop_pilots_on_5;
-			else if (srate <= 15000000)
-				aclc_value = cls2[i].car_loop_pilots_on_10;
-			else if (srate <= 25000000)
-				aclc_value = cls2[i].car_loop_pilots_on_20;
-			else
-				aclc_value = cls2[i].car_loop_pilots_on_30;
-		} else {
-			if (srate <= 3000000)
-				aclc_value = cls2[i].car_loop_pilots_off_2;
-			else if (srate <= 7000000)
-				aclc_value = cls2[i].car_loop_pilots_off_5;
-			else if (srate <= 15000000)
-				aclc_value = cls2[i].car_loop_pilots_off_10;
-			else if (srate <= 25000000)
-				aclc_value = cls2[i].car_loop_pilots_off_20;
-			else
-				aclc_value = cls2[i].car_loop_pilots_off_30;
-		}
-
-	} else {
-		if (srate <= 3000000)
-			aclc_value = cllas2[i].car_loop_pilots_on_2;
-		else if (srate <= 7000000)
-			aclc_value = cllas2[i].car_loop_pilots_on_5;
-		else if (srate <= 15000000)
-			aclc_value = cllas2[i].car_loop_pilots_on_10;
-		else if (srate <= 25000000)
-			aclc_value = cllas2[i].car_loop_pilots_on_20;
-		else
-			aclc_value = cllas2[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)
-{
-	const struct stv0900_short_frames_car_loop_optim *s2scl;
-	const struct stv0900_short_frames_car_loop_optim_vs_mod *s2sclc30;
-	s32 mod_index = 0;
-	u8 aclc_value = 0x0b;
-
-	dprintk("%s\n", __func__);
-
-	s2scl = FE_STV0900_S2ShortCarLoop;
-	s2sclc30 = FE_STV0900_S2ShortCarLoopCut30;
-
-	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;
-	}
-
-	if (chip_id >= 0x30) {
-		if (srate <= 3000000)
-			aclc_value = s2sclc30[mod_index].car_loop_2;
-		else if (srate <= 7000000)
-			aclc_value = s2sclc30[mod_index].car_loop_5;
-		else if (srate <= 15000000)
-			aclc_value = s2sclc30[mod_index].car_loop_10;
-		else if (srate <= 25000000)
-			aclc_value = s2sclc30[mod_index].car_loop_20;
-		else
-			aclc_value = s2sclc30[mod_index].car_loop_30;
-
-	} else if (chip_id >= 0x20) {
-		if (srate <= 3000000)
-			aclc_value = s2scl[mod_index].car_loop_cut20_2;
-		else if (srate <= 7000000)
-			aclc_value = s2scl[mod_index].car_loop_cut20_5;
-		else if (srate <= 15000000)
-			aclc_value = s2scl[mod_index].car_loop_cut20_10;
-		else if (srate <= 25000000)
-			aclc_value = s2scl[mod_index].car_loop_cut20_20;
-		else
-			aclc_value = s2scl[mod_index].car_loop_cut20_30;
-
-	} else {
-		if (srate <= 3000000)
-			aclc_value = s2scl[mod_index].car_loop_cut12_2;
-		else if (srate <= 7000000)
-			aclc_value = s2scl[mod_index].car_loop_cut12_5;
-		else if (srate <= 15000000)
-			aclc_value = s2scl[mod_index].car_loop_cut12_10;
-		else if (srate <= 25000000)
-			aclc_value = s2scl[mod_index].car_loop_cut12_20;
-		else
-			aclc_value = s2scl[mod_index].car_loop_cut12_30;
-
-	}
-
-	return aclc_value;
-}
-
-static
-enum fe_stv0900_error stv0900_st_dvbs2_single(struct stv0900_internal *intp,
-					enum fe_stv0900_demod_mode LDPC_Mode,
-					enum fe_stv0900_demod_num demod)
-{
-	enum fe_stv0900_error error = STV0900_NO_ERROR;
-	s32 reg_ind;
-
-	dprintk("%s\n", __func__);
-
-	switch (LDPC_Mode) {
-	case STV0900_DUAL:
-	default:
-		if ((intp->demod_mode != STV0900_DUAL)
-			|| (stv0900_get_bits(intp, F0900_DDEMOD) != 1)) {
-			stv0900_write_reg(intp, R0900_GENCFG, 0x1d);
-
-			intp->demod_mode = STV0900_DUAL;
-
-			stv0900_write_bits(intp, F0900_FRESFEC, 1);
-			stv0900_write_bits(intp, F0900_FRESFEC, 0);
-
-			for (reg_ind = 0; reg_ind < 7; reg_ind++)
-				stv0900_write_reg(intp,
-						R0900_P1_MODCODLST0 + reg_ind,
-						0xff);
-			for (reg_ind = 0; reg_ind < 8; reg_ind++)
-				stv0900_write_reg(intp,
-						R0900_P1_MODCODLST7 + reg_ind,
-						0xcc);
-
-			stv0900_write_reg(intp, R0900_P1_MODCODLSTE, 0xff);
-			stv0900_write_reg(intp, R0900_P1_MODCODLSTF, 0xcf);
-
-			for (reg_ind = 0; reg_ind < 7; reg_ind++)
-				stv0900_write_reg(intp,
-						R0900_P2_MODCODLST0 + reg_ind,
-						0xff);
-			for (reg_ind = 0; reg_ind < 8; reg_ind++)
-				stv0900_write_reg(intp,
-						R0900_P2_MODCODLST7 + reg_ind,
-						0xcc);
-
-			stv0900_write_reg(intp, R0900_P2_MODCODLSTE, 0xff);
-			stv0900_write_reg(intp, R0900_P2_MODCODLSTF, 0xcf);
-		}
-
-		break;
-	case STV0900_SINGLE:
-		if (demod == STV0900_DEMOD_2) {
-			stv0900_stop_all_s2_modcod(intp, STV0900_DEMOD_1);
-			stv0900_activate_s2_modcod_single(intp,
-							STV0900_DEMOD_2);
-			stv0900_write_reg(intp, R0900_GENCFG, 0x06);
-		} else {
-			stv0900_stop_all_s2_modcod(intp, STV0900_DEMOD_2);
-			stv0900_activate_s2_modcod_single(intp,
-							STV0900_DEMOD_1);
-			stv0900_write_reg(intp, R0900_GENCFG, 0x04);
-		}
-
-		intp->demod_mode = STV0900_SINGLE;
-
-		stv0900_write_bits(intp, F0900_FRESFEC, 1);
-		stv0900_write_bits(intp, F0900_FRESFEC, 0);
-		stv0900_write_bits(intp, F0900_P1_ALGOSWRST, 1);
-		stv0900_write_bits(intp, F0900_P1_ALGOSWRST, 0);
-		stv0900_write_bits(intp, F0900_P2_ALGOSWRST, 1);
-		stv0900_write_bits(intp, 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;
-	struct stv0900_internal *intp = NULL;
-	int selosci, i;
-
-	struct stv0900_inode *temp_int = find_inode(state->i2c_adap,
-						state->config->demod_address);
-
-	dprintk("%s\n", __func__);
-
-	if ((temp_int != NULL) && (p_init->demod_mode == STV0900_DUAL)) {
-		state->internal = temp_int->internal;
-		(state->internal->dmds_used)++;
-		dprintk("%s: Find Internal Structure!\n", __func__);
-		return STV0900_NO_ERROR;
-	} else {
-		state->internal = kmalloc(sizeof(struct stv0900_internal),
-								GFP_KERNEL);
-		if (state->internal == NULL)
-			return STV0900_INVALID_HANDLE;
-		temp_int = append_internal(state->internal);
-		if (temp_int == NULL) {
-			kfree(state->internal);
-			state->internal = NULL;
-			return STV0900_INVALID_HANDLE;
-		}
-		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("%s: Create New Internal Structure!\n", __func__);
-	}
-
-	if (state->internal == NULL) {
-		error = STV0900_INVALID_HANDLE;
-		return error;
-	}
-
-	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;
-
-		return error;
-	}
-
-	intp = state->internal;
-
-	intp->demod_mode = p_init->demod_mode;
-	stv0900_st_dvbs2_single(intp, intp->demod_mode,	STV0900_DEMOD_1);
-	intp->chip_id = stv0900_read_reg(intp, R0900_MID);
-	intp->rolloff = p_init->rolloff;
-	intp->quartz = p_init->dmd_ref_clk;
-
-	stv0900_write_bits(intp, F0900_P1_ROLLOFF_CONTROL, p_init->rolloff);
-	stv0900_write_bits(intp, F0900_P2_ROLLOFF_CONTROL, p_init->rolloff);
-
-	intp->ts_config = p_init->ts_config;
-	if (intp->ts_config == NULL)
-		stv0900_set_ts_parallel_serial(intp,
-				p_init->path1_ts_clock,
-				p_init->path2_ts_clock);
-	else {
-		for (i = 0; intp->ts_config[i].addr != 0xffff; i++)
-			stv0900_write_reg(intp,
-					intp->ts_config[i].addr,
-					intp->ts_config[i].val);
-
-		stv0900_write_bits(intp, F0900_P2_RST_HWARE, 1);
-		stv0900_write_bits(intp, F0900_P2_RST_HWARE, 0);
-		stv0900_write_bits(intp, F0900_P1_RST_HWARE, 1);
-		stv0900_write_bits(intp, F0900_P1_RST_HWARE, 0);
-	}
-
-	intp->tuner_type[0] = p_init->tuner1_type;
-	intp->tuner_type[1] = p_init->tuner2_type;
-	/* tuner init */
-	switch (p_init->tuner1_type) {
-	case 3: /*FE_AUTO_STB6100:*/
-		stv0900_write_reg(intp, R0900_P1_TNRCFG, 0x3c);
-		stv0900_write_reg(intp, R0900_P1_TNRCFG2, 0x86);
-		stv0900_write_reg(intp, R0900_P1_TNRCFG3, 0x18);
-		stv0900_write_reg(intp, R0900_P1_TNRXTAL, 27); /* 27MHz */
-		stv0900_write_reg(intp, R0900_P1_TNRSTEPS, 0x05);
-		stv0900_write_reg(intp, R0900_P1_TNRGAIN, 0x17);
-		stv0900_write_reg(intp, R0900_P1_TNRADJ, 0x1f);
-		stv0900_write_reg(intp, R0900_P1_TNRCTL2, 0x0);
-		stv0900_write_bits(intp, F0900_P1_TUN_TYPE, 3);
-		break;
-	/* case FE_SW_TUNER: */
-	default:
-		stv0900_write_bits(intp, F0900_P1_TUN_TYPE, 6);
-		break;
-	}
-
-	stv0900_write_bits(intp, F0900_P1_TUN_MADDRESS, p_init->tun1_maddress);
-	switch (p_init->tuner1_adc) {
-	case 1:
-		stv0900_write_reg(intp, R0900_TSTTNR1, 0x26);
-		break;
-	default:
-		break;
-	}
-
-	stv0900_write_reg(intp, R0900_P1_TNRLD, 1); /* hw tuner */
-
-	/* tuner init */
-	switch (p_init->tuner2_type) {
-	case 3: /*FE_AUTO_STB6100:*/
-		stv0900_write_reg(intp, R0900_P2_TNRCFG, 0x3c);
-		stv0900_write_reg(intp, R0900_P2_TNRCFG2, 0x86);
-		stv0900_write_reg(intp, R0900_P2_TNRCFG3, 0x18);
-		stv0900_write_reg(intp, R0900_P2_TNRXTAL, 27); /* 27MHz */
-		stv0900_write_reg(intp, R0900_P2_TNRSTEPS, 0x05);
-		stv0900_write_reg(intp, R0900_P2_TNRGAIN, 0x17);
-		stv0900_write_reg(intp, R0900_P2_TNRADJ, 0x1f);
-		stv0900_write_reg(intp, R0900_P2_TNRCTL2, 0x0);
-		stv0900_write_bits(intp, F0900_P2_TUN_TYPE, 3);
-		break;
-	/* case FE_SW_TUNER: */
-	default:
-		stv0900_write_bits(intp, F0900_P2_TUN_TYPE, 6);
-		break;
-	}
-
-	stv0900_write_bits(intp, F0900_P2_TUN_MADDRESS, p_init->tun2_maddress);
-	switch (p_init->tuner2_adc) {
-	case 1:
-		stv0900_write_reg(intp, R0900_TSTTNR3, 0x26);
-		break;
-	default:
-		break;
-	}
-
-	stv0900_write_reg(intp, R0900_P2_TNRLD, 1); /* hw tuner */
-
-	stv0900_write_bits(intp, F0900_P1_TUN_IQSWAP, p_init->tun1_iq_inv);
-	stv0900_write_bits(intp, F0900_P2_TUN_IQSWAP, p_init->tun2_iq_inv);
-	stv0900_set_mclk(intp, 135000000);
-	msleep(3);
-
-	switch (intp->clkmode) {
-	case 0:
-	case 2:
-		stv0900_write_reg(intp, R0900_SYNTCTRL, 0x20 | intp->clkmode);
-		break;
-	default:
-		selosci = 0x02 & stv0900_read_reg(intp, R0900_SYNTCTRL);
-		stv0900_write_reg(intp, R0900_SYNTCTRL, 0x20 | selosci);
-		break;
-	}
-	msleep(3);
-
-	intp->mclk = stv0900_get_mclk_freq(intp, intp->quartz);
-	if (intp->errs)
-		error = STV0900_I2C_ERROR;
-
-	return error;
-}
-
-static int stv0900_status(struct stv0900_internal *intp,
-					enum fe_stv0900_demod_num demod)
-{
-	enum fe_stv0900_search_state demod_state;
-	int locked = FALSE;
-	u8 tsbitrate0_val, tsbitrate1_val;
-	s32 bitrate;
-
-	demod_state = stv0900_get_bits(intp, HEADER_MODE);
-	switch (demod_state) {
-	case STV0900_SEARCH:
-	case STV0900_PLH_DETECTED:
-	default:
-		locked = FALSE;
-		break;
-	case STV0900_DVBS2_FOUND:
-		locked = stv0900_get_bits(intp, LOCK_DEFINITIF) &&
-				stv0900_get_bits(intp, PKTDELIN_LOCK) &&
-				stv0900_get_bits(intp, TSFIFO_LINEOK);
-		break;
-	case STV0900_DVBS_FOUND:
-		locked = stv0900_get_bits(intp, LOCK_DEFINITIF) &&
-				stv0900_get_bits(intp, LOCKEDVIT) &&
-				stv0900_get_bits(intp, TSFIFO_LINEOK);
-		break;
-	}
-
-	dprintk("%s: locked = %d\n", __func__, locked);
-
-	if (stvdebug) {
-		/* Print TS bitrate */
-		tsbitrate0_val = stv0900_read_reg(intp, TSBITRATE0);
-		tsbitrate1_val = stv0900_read_reg(intp, TSBITRATE1);
-		/* Formula Bit rate = Mclk * px_tsfifo_bitrate / 16384 */
-		bitrate = (stv0900_get_mclk_freq(intp, intp->quartz)/1000000)
-			* (tsbitrate1_val << 8 | tsbitrate0_val);
-		bitrate /= 16384;
-		dprintk("TS bitrate = %d Mbit/sec \n", bitrate);
-	};
-
-	return locked;
-}
-
-static enum dvbfe_search stv0900_search(struct dvb_frontend *fe)
-{
-	struct stv0900_state *state = fe->demodulator_priv;
-	struct stv0900_internal *intp = state->internal;
-	enum fe_stv0900_demod_num demod = state->demod;
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-
-	struct stv0900_search_params p_search;
-	struct stv0900_signal_info p_result = intp->result[demod];
-
-	enum fe_stv0900_error error = STV0900_NO_ERROR;
-
-	dprintk("%s: ", __func__);
-
-	if (!(INRANGE(100000, c->symbol_rate, 70000000)))
-		return DVBFE_ALGO_SEARCH_FAILED;
-
-	if (state->config->set_ts_params)
-		state->config->set_ts_params(fe, 0);
-
-	p_result.locked = FALSE;
-	p_search.path = 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;
-	/* Speeds up DVB-S searching */
-	if (c->delivery_system == SYS_DVBS)
-		p_search.standard = STV0900_SEARCH_DVBS1;
-
-	intp->srch_standard[demod] = p_search.standard;
-	intp->symbol_rate[demod] = p_search.symbol_rate;
-	intp->srch_range[demod] = p_search.search_range;
-	intp->freq[demod] = p_search.frequency;
-	intp->srch_algo[demod] = p_search.search_algo;
-	intp->srch_iq_inv[demod] = p_search.iq_inversion;
-	intp->fec[demod] = p_search.fec;
-	if ((stv0900_algo(fe) == STV0900_RANGEOK) &&
-				(intp->errs == STV0900_NO_ERROR)) {
-		p_result.locked = intp->result[demod].locked;
-		p_result.standard = intp->result[demod].standard;
-		p_result.frequency = intp->result[demod].frequency;
-		p_result.symbol_rate = intp->result[demod].symbol_rate;
-		p_result.fec = intp->result[demod].fec;
-		p_result.modcode = intp->result[demod].modcode;
-		p_result.pilot = intp->result[demod].pilot;
-		p_result.frame_len = intp->result[demod].frame_len;
-		p_result.spectrum = intp->result[demod].spectrum;
-		p_result.rolloff = intp->result[demod].rolloff;
-		p_result.modulation = intp->result[demod].modulation;
-	} else {
-		p_result.locked = FALSE;
-		switch (intp->err[demod]) {
-		case STV0900_I2C_ERROR:
-			error = STV0900_I2C_ERROR;
-			break;
-		case STV0900_NO_ERROR:
-		default:
-			error = STV0900_SEARCH_FAILED;
-			break;
-		}
-	}
-
-	if ((p_result.locked == TRUE) && (error == STV0900_NO_ERROR)) {
-		dprintk("Search Success\n");
-		return DVBFE_ALGO_SEARCH_SUCCESS;
-	} else {
-		dprintk("Search Fail\n");
-		return DVBFE_ALGO_SEARCH_FAILED;
-	}
-
-}
-
-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;
-		if (state->config->set_lock_led)
-			state->config->set_lock_led(fe, 1);
-	} else {
-		*status = 0;
-		if (state->config->set_lock_led)
-			state->config->set_lock_led(fe, 0);
-		dprintk("DEMOD LOCK FAIL\n");
-	}
-
-	return 0;
-}
-
-static int stv0900_stop_ts(struct dvb_frontend *fe, int stop_ts)
-{
-
-	struct stv0900_state *state = fe->demodulator_priv;
-	struct stv0900_internal *intp = state->internal;
-	enum fe_stv0900_demod_num demod = state->demod;
-
-	if (stop_ts == TRUE)
-		stv0900_write_bits(intp, RST_HWARE, 1);
-	else
-		stv0900_write_bits(intp, RST_HWARE, 0);
-
-	return 0;
-}
-
-static int stv0900_diseqc_init(struct dvb_frontend *fe)
-{
-	struct stv0900_state *state = fe->demodulator_priv;
-	struct stv0900_internal *intp = state->internal;
-	enum fe_stv0900_demod_num demod = state->demod;
-
-	stv0900_write_bits(intp, DISTX_MODE, state->config->diseqc_mode);
-	stv0900_write_bits(intp, DISEQC_RESET, 1);
-	stv0900_write_bits(intp, DISEQC_RESET, 0);
-
-	return 0;
-}
-
-static int stv0900_init(struct dvb_frontend *fe)
-{
-	dprintk("%s\n", __func__);
-
-	stv0900_stop_ts(fe, 1);
-	stv0900_diseqc_init(fe);
-
-	return 0;
-}
-
-static int stv0900_diseqc_send(struct stv0900_internal *intp , u8 *data,
-				u32 NbData, enum fe_stv0900_demod_num demod)
-{
-	s32 i = 0;
-
-	stv0900_write_bits(intp, DIS_PRECHARGE, 1);
-	while (i < NbData) {
-		while (stv0900_get_bits(intp, FIFO_FULL))
-			;/* checkpatch complains */
-		stv0900_write_reg(intp, DISTXDATA, data[i]);
-		i++;
-	}
-
-	stv0900_write_bits(intp, DIS_PRECHARGE, 0);
-	i = 0;
-	while ((stv0900_get_bits(intp, TX_IDLE) != 1) && (i < 10)) {
-		msleep(10);
-		i++;
-	}
-
-	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 *intp = state->internal;
-	enum fe_stv0900_demod_num demod = state->demod;
-	u8 data;
-
-
-	switch (burst) {
-	case SEC_MINI_A:
-		stv0900_write_bits(intp, DISTX_MODE, 3);/* Unmodulated */
-		data = 0x00;
-		stv0900_diseqc_send(intp, &data, 1, state->demod);
-		break;
-	case SEC_MINI_B:
-		stv0900_write_bits(intp, DISTX_MODE, 2);/* Modulated */
-		data = 0xff;
-		stv0900_diseqc_send(intp, &data, 1, state->demod);
-		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 *intp = state->internal;
-	enum fe_stv0900_demod_num demod = state->demod;
-	s32 i = 0;
-
-	reply->msg_len = 0;
-
-	while ((stv0900_get_bits(intp, RX_END) != 1) && (i < 10)) {
-		msleep(10);
-		i++;
-	}
-
-	if (stv0900_get_bits(intp, RX_END)) {
-		reply->msg_len = stv0900_get_bits(intp, FIFO_BYTENBR);
-
-		for (i = 0; i < reply->msg_len; i++)
-			reply->msg[i] = stv0900_read_reg(intp, DISRXDATA);
-	}
-
-	return 0;
-}
-
-static int stv0900_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t toneoff)
-{
-	struct stv0900_state *state = fe->demodulator_priv;
-	struct stv0900_internal *intp = state->internal;
-	enum fe_stv0900_demod_num demod = state->demod;
-
-	dprintk("%s: %s\n", __func__, ((toneoff == 0) ? "On" : "Off"));
-
-	switch (toneoff) {
-	case SEC_TONE_ON:
-		/*Set the DiseqC mode to 22Khz _continues_ tone*/
-		stv0900_write_bits(intp, DISTX_MODE, 0);
-		stv0900_write_bits(intp, DISEQC_RESET, 1);
-		/*release DiseqC reset to enable the 22KHz tone*/
-		stv0900_write_bits(intp, DISEQC_RESET, 0);
-		break;
-	case SEC_TONE_OFF:
-		/*return diseqc mode to config->diseqc_mode.
-		Usually it's without _continues_ tone */
-		stv0900_write_bits(intp, DISTX_MODE,
-				state->config->diseqc_mode);
-		/*maintain the DiseqC reset to disable the 22KHz tone*/
-		stv0900_write_bits(intp, DISEQC_RESET, 1);
-		stv0900_write_bits(intp, DISEQC_RESET, 0);
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static void stv0900_release(struct dvb_frontend *fe)
-{
-	struct stv0900_state *state = fe->demodulator_priv;
-
-	dprintk("%s\n", __func__);
-
-	if (state->config->set_lock_led)
-		state->config->set_lock_led(fe, 0);
-
-	if ((--(state->internal->dmds_used)) <= 0) {
-
-		dprintk("%s: Actually removing\n", __func__);
-
-		remove_inode(state->internal);
-		kfree(state->internal);
-	}
-
-	kfree(state);
-}
-
-static int stv0900_sleep(struct dvb_frontend *fe)
-{
-	struct stv0900_state *state = fe->demodulator_priv;
-
-	dprintk("%s\n", __func__);
-
-	if (state->config->set_lock_led)
-		state->config->set_lock_led(fe, 0);
-
-	return 0;
-}
-
-static int stv0900_get_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct stv0900_state *state = fe->demodulator_priv;
-	struct stv0900_internal *intp = state->internal;
-	enum fe_stv0900_demod_num demod = state->demod;
-	struct stv0900_signal_info p_result = intp->result[demod];
-
-	p->frequency = p_result.locked ? p_result.frequency : 0;
-	p->symbol_rate = p_result.locked ? p_result.symbol_rate : 0;
-	return 0;
-}
-
-static struct dvb_frontend_ops stv0900_ops = {
-	.delsys = { SYS_DVBS, SYS_DVBS2, SYS_DSS },
-	.info = {
-		.name			= "STV0900 frontend",
-		.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                   = stv0900_get_frontend,
-	.sleep				= stv0900_sleep,
-	.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,
-	.search				= stv0900_search,
-	.read_status			= stv0900_read_status,
-	.read_ber			= stv0900_read_ber,
-	.read_signal_strength		= stv0900_read_signal_strength,
-	.read_snr			= stv0900_read_snr,
-	.read_ucblocks                  = stv0900_read_ucblocks,
-};
-
-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		= config->demod_mode;
-		init_params.rolloff		= STV0900_35;
-		init_params.path1_ts_clock	= config->path1_mode;
-		init_params.tun1_maddress	= config->tun1_maddress;
-		init_params.tun1_iq_inv		= STV0900_IQ_NORMAL;
-		init_params.tuner1_adc		= config->tun1_adc;
-		init_params.tuner1_type		= config->tun1_type;
-		init_params.path2_ts_clock	= config->path2_mode;
-		init_params.ts_config		= config->ts_config_regs;
-		init_params.tun2_maddress	= config->tun2_maddress;
-		init_params.tuner2_adc		= config->tun2_adc;
-		init_params.tuner2_type		= config->tun2_type;
-		init_params.tun2_iq_inv		= 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
deleted file mode 100644
index b684df9..0000000
--- a/drivers/media/dvb/frontends/stv0900_init.h
+++ /dev/null
@@ -1,584 +0,0 @@
-/*
- * 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 */
-
-};
-
-struct stv0900_short_frames_car_loop_optim_vs_mod {
-	enum fe_stv0900_modulation modulation;
-	u8 car_loop_2;	  /* SR<3msps      */
-	u8 car_loop_5;	  /* 3<SR<=7msps   */
-	u8 car_loop_10;   /* 7<SR<=15msps  */
-	u8 car_loop_20;   /* 10<SR<=25msps */
-	u8 car_loop_30;   /* 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		2Mcut1.2 2Mcut2.0 5Mcut1.2 5Mcut2.0 10Mcut1.2
-			10Mcut2.0 20Mcut1.2 20M_cut2.0 30Mcut1.2 30Mcut2.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 struct stv0900_car_loop_optim FE_STV0900_S2CarLoopCut30[14] = {
-	/*Modcod		2MPon 	2MPoff	5MPon 	5MPoff	10MPon
-				10MPoff	20MPon 	20MPoff	30MPon 	30MPoff	*/
-	{ STV0900_QPSK_12,	0x3C,	0x2C,	0x0C,	0x2C,	0x1B,
-				0x2C,	0x1B,	0x1C,	0x0B, 	0x3B },
-	{ STV0900_QPSK_35,	0x0D,	0x0D,	0x0C,	0x0D,	0x1B,
-				0x3C,	0x1B,	0x1C,	0x0B,	0x3B },
-	{ STV0900_QPSK_23,	0x1D,	0x0D,	0x0C,	0x1D,	0x2B,
-				0x3C,	0x1B,	0x1C,	0x0B,	0x3B },
-	{ STV0900_QPSK_34,	0x1D,	0x1D,	0x0C,	0x1D,	0x2B,
-				0x3C,	0x1B,	0x1C,	0x0B,	0x3B },
-	{ STV0900_QPSK_45,	0x2D,	0x1D,	0x1C,	0x1D,	0x2B,
-				0x3C,	0x2B,	0x0C,	0x1B,	0x3B },
-	{ STV0900_QPSK_56,	0x2D,	0x1D,	0x1C,	0x1D,	0x2B,
-				0x3C,	0x2B,	0x0C,	0x1B,	0x3B },
-	{ STV0900_QPSK_89,	0x3D,	0x2D,	0x1C,	0x1D,	0x3B,
-				0x3C,	0x2B,	0x0C,	0x1B,	0x3B },
-	{ STV0900_QPSK_910,	0x3D,	0x2D,	0x1C,	0x1D,	0x3B,
-				0x3C,	0x2B,	0x0C,	0x1B,	0x3B },
-	{ STV0900_8PSK_35,	0x39,	0x19,	0x39,	0x19,	0x19,
-				0x19,	0x19,	0x19,	0x09,	0x19 },
-	{ STV0900_8PSK_23,	0x2A,	0x39,	0x1A,	0x0A,	0x39,
-				0x0A,	0x29,	0x39,	0x29,	0x0A },
-	{ STV0900_8PSK_34,	0x0B,	0x3A,	0x0B,	0x0B,	0x3A,
-				0x1B,	0x1A,	0x0B,	0x1A,	0x3A },
-	{ STV0900_8PSK_56,	0x0C,	0x1B,	0x3B,	0x2B,	0x1B,
-				0x3B,	0x3A,	0x3B,	0x3A,	0x1B },
-	{ STV0900_8PSK_89,	0x2C,	0x2C,	0x2C,	0x1C,	0x2B,
-				0x0C,	0x0B,	0x3B,	0x0B,	0x1B },
-	{ STV0900_8PSK_910,	0x2C,	0x3C,	0x2C,	0x1C,	0x3B,
-				0x1C,	0x0B,	0x3B,	0x0B,	0x1B }
-};
-
-static	const
-struct stv0900_car_loop_optim FE_STV0900_S2APSKCarLoopCut30[11] = {
-	/*Modcod		2MPon 	2MPoff	5MPon 	5MPoff	10MPon
-				10MPoff	20MPon 	20MPoff	30MPon 	30MPoff	*/
-	{ STV0900_16APSK_23,	0x0A,	0x0A,	0x0A,	0x0A,	0x1A,
-				0x0A,	0x3A,	0x0A,	0x2A,	0x0A },
-	{ STV0900_16APSK_34,	0x0A,	0x0A,	0x0A,	0x0A,	0x0B,
-				0x0A,	0x3B,	0x0A,	0x1B,	0x0A },
-	{ STV0900_16APSK_45,	0x0A,	0x0A,	0x0A,	0x0A,	0x1B,
-				0x0A,	0x3B,	0x0A,	0x2B,	0x0A },
-	{ STV0900_16APSK_56,	0x0A,	0x0A,	0x0A,	0x0A,	0x1B,
-				0x0A,	0x3B,	0x0A,	0x2B,	0x0A },
-	{ STV0900_16APSK_89,	0x0A,	0x0A,	0x0A,	0x0A,	0x2B,
-				0x0A,	0x0C,	0x0A,	0x3B,	0x0A },
-	{ STV0900_16APSK_910,	0x0A,	0x0A,	0x0A,	0x0A,	0x2B,
-				0x0A,	0x0C,	0x0A,	0x3B,	0x0A },
-	{ STV0900_32APSK_34,	0x0A,	0x0A,	0x0A,	0x0A,	0x0A,
-				0x0A,	0x0A,	0x0A,	0x0A,	0x0A },
-	{ STV0900_32APSK_45,	0x0A,	0x0A,	0x0A,	0x0A,	0x0A,
-				0x0A,	0x0A,	0x0A,	0x0A,	0x0A },
-	{ STV0900_32APSK_56,	0x0A,	0x0A,	0x0A,	0x0A,	0x0A,
-				0x0A,	0x0A,	0x0A,	0x0A,	0x0A },
-	{ STV0900_32APSK_89,	0x0A,	0x0A,	0x0A,	0x0A,	0x0A,
-				0x0A,	0x0A,	0x0A,	0x0A,	0x0A },
-	{ STV0900_32APSK_910,	0x0A,	0x0A,	0x0A,	0x0A,	0x0A,
-				0x0A,	0x0A,	0x0A,	0x0A,	0x0A }
-};
-
-static	const
-struct stv0900_car_loop_optim FE_STV0900_S2LowQPCarLoopCut30[3] = {
-	/*Modcod		2MPon 	2MPoff	5MPon 	5MPoff	10MPon
-				10MPoff	20MPon 	20MPoff	30MPon 	30MPoff*/
-	{ STV0900_QPSK_14,	0x0C,	0x3C,	0x0B,	0x3C,	0x2A,
-				0x2C,	0x2A,	0x1C,	0x3A,	0x3B },
-	{ STV0900_QPSK_13,	0x0C,	0x3C,	0x0B,	0x3C,	0x2A,
-				0x2C,	0x3A,	0x0C,	0x3A,	0x2B },
-	{ STV0900_QPSK_25,	0x1C,	0x3C,	0x1B,	0x3C,	0x3A,
-				0x1C,	0x3A,	0x3B,	0x3A,	0x2B }
-};
-
-static	const struct stv0900_short_frames_car_loop_optim_vs_mod
-FE_STV0900_S2ShortCarLoopCut30[4] = {
-	/*Mod		2Mcut3.0 5Mcut3.0 10Mcut3.0 20Mcut3.0 30Mcut3.0*/
-	{ STV0900_QPSK,		0x2C,	0x2B,	0x0B,	0x0B,	0x3A },
-	{ STV0900_8PSK,		0x3B,	0x0B,	0x2A,	0x0A,	0x39 },
-	{ STV0900_16APSK,	0x1B,	0x1B,	0x1B,	0x3A,	0x2A },
-	{ STV0900_32APSK,	0x1B,	0x1B,	0x1B,	0x3A,	0x2A },
-
-};
-
-static const u16 STV0900_InitVal[181][2] = {
-	{ R0900_OUTCFG		, 0x00	},
-	{ 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_RCCFG2		, 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
deleted file mode 100644
index e0ea74c..0000000
--- a/drivers/media/dvb/frontends/stv0900_priv.h
+++ /dev/null
@@ -1,408 +0,0 @@
-/*
- * 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 dprintk(args...) \
-	do { \
-		if (stvdebug) \
-			printk(KERN_DEBUG args); \
-	} while (0)
-
-#define STV0900_MAXLOOKUPSIZE 500
-#define STV0900_BLIND_SEARCH_AGC2_TH 700
-#define STV0900_BLIND_SEARCH_AGC2_TH_CUT30 1400
-#define IQPOWER_THRESHOLD  30
-
-/* 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;/* Reference,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;
-	int 	tuner1_type;
-
-	/* IQ from the tuner1 to the demod */
-	enum stv0900_iq_inversion	tun1_iq_inv;
-	enum fe_stv0900_clock_type	path2_ts_clock;
-
-	u8	tun2_maddress;
-	int	tuner2_adc;
-	int	tuner2_type;
-
-	/* IQ from the tuner2 to the demod */
-	enum stv0900_iq_inversion	tun2_iq_inv;
-	struct stv0900_reg		*ts_config;
-};
-
-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_len;
-	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;
-
-	/*Demods */
-	s32	freq[2];
-	s32	bw[2];
-	s32	symbol_rate[2];
-	s32	srch_range[2];
-	/* for software/auto tuner */
-	int	tuner_type[2];
-
-	/* algorithm for search Blind, Cold or Warm*/
-	enum fe_stv0900_search_algo	srch_algo[2];
-	/* search standard: Auto, DVBS1/DSS only or DVBS2 only*/
-	enum fe_stv0900_search_standard	srch_standard[2];
-	/* inversion search : auto, auto norma first, normal or inverted */
-	enum fe_stv0900_search_iq	srch_iq_inv[2];
-	enum fe_stv0900_modcode		modcode[2];
-	enum fe_stv0900_modulation	modulation[2];
-	enum fe_stv0900_fec		fec[2];
-
-	struct stv0900_signal_info	result[2];
-	enum fe_stv0900_error		err[2];
-
-
-	struct i2c_adapter	*i2c_adap;
-	u8			i2c_addr;
-	u8			clkmode;/* 0 for CLKI, 2 for XTALI */
-	u8			chip_id;
-	struct stv0900_reg	*ts_config;
-	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 int stvdebug;
-
-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_modcod(struct stv0900_internal *i_params,
-				enum fe_stv0900_demod_num demod);
-
-extern void stv0900_activate_s2_modcod_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);
-
-extern u32
-stv0900_get_freq_auto(struct stv0900_internal *intp, int demod);
-
-extern void
-stv0900_set_tuner_auto(struct stv0900_internal *intp, u32 Frequency,
-						u32 Bandwidth, int demod);
-
-#endif
diff --git a/drivers/media/dvb/frontends/stv0900_reg.h b/drivers/media/dvb/frontends/stv0900_reg.h
deleted file mode 100644
index 731afe9..0000000
--- a/drivers/media/dvb/frontends/stv0900_reg.h
+++ /dev/null
@@ -1,3981 +0,0 @@
-/*
- * 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
-
-extern s32 shiftx(s32 x, int demod, s32 shift);
-
-#define REGx(x) shiftx(x, demod, 0x200)
-#define FLDx(x) shiftx(x, demod, 0x2000000)
-
-/*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_OUTSERRS1_HZ 0xf11c0040
-#define F0900_OUTSERRS2_HZ 0xf11c0020
-#define F0900_OUTSERRS3_HZ 0xf11c0010
-#define F0900_OUTPARRS3_HZ 0xf11c0008
-
-/*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_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_I2C_FASTMODE 0xf1290008
-#define F0900_I2CADDR_INC 0xf1290003
-
-/*P1_I2CRPT*/
-#define R0900_P1_I2CRPT 0xf12a
-#define I2CRPT shiftx(R0900_P1_I2CRPT, demod, -1)
-#define F0900_P1_I2CT_ON 0xf12a0080
-#define I2CT_ON shiftx(F0900_P1_I2CT_ON, demod, -0x10000)
-#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
-
-/*IOPVALUE6*/
-#define R0900_IOPVALUE6 0xf138
-#define F0900_VSCL 0xf1380004
-#define F0900_VSDA 0xf1380002
-#define F0900_VDATA3_0 0xf1380001
-
-/*IOPVALUE5*/
-#define R0900_IOPVALUE5 0xf139
-#define F0900_VDATA3_1 0xf1390080
-#define F0900_VDATA3_2 0xf1390040
-#define F0900_VDATA3_3 0xf1390020
-#define F0900_VDATA3_4 0xf1390010
-#define F0900_VDATA3_5 0xf1390008
-#define F0900_VDATA3_6 0xf1390004
-#define F0900_VDATA3_7 0xf1390002
-#define F0900_VCLKOUT3 0xf1390001
-
-/*IOPVALUE4*/
-#define R0900_IOPVALUE4 0xf13a
-#define F0900_VSTROUT3 0xf13a0080
-#define F0900_VDPN3 0xf13a0040
-#define F0900_VERROR3 0xf13a0020
-#define F0900_VDATA2_7 0xf13a0010
-#define F0900_VCLKOUT2 0xf13a0008
-#define F0900_VSTROUT2 0xf13a0004
-#define F0900_VDPN2 0xf13a0002
-#define F0900_VERROR2 0xf13a0001
-
-/*IOPVALUE3*/
-#define R0900_IOPVALUE3 0xf13b
-#define F0900_VDATA1_7 0xf13b0080
-#define F0900_VCLKOUT1 0xf13b0040
-#define F0900_VSTROUT1 0xf13b0020
-#define F0900_VDPN1 0xf13b0010
-#define F0900_VERROR1 0xf13b0008
-#define F0900_VCLKOUT27 0xf13b0004
-#define F0900_VDISEQCOUT2 0xf13b0002
-#define F0900_VSCLT2 0xf13b0001
-
-/*IOPVALUE2*/
-#define R0900_IOPVALUE2 0xf13c
-#define F0900_VSDAT2 0xf13c0080
-#define F0900_VAGCRF2 0xf13c0040
-#define F0900_VDISEQCOUT1 0xf13c0020
-#define F0900_VSCLT1 0xf13c0010
-#define F0900_VSDAT1 0xf13c0008
-#define F0900_VAGCRF1 0xf13c0004
-#define F0900_VDIRCLK 0xf13c0002
-#define F0900_VSTDBY 0xf13c0001
-
-/*IOPVALUE1*/
-#define R0900_IOPVALUE1 0xf13d
-#define F0900_VCS1 0xf13d0080
-#define F0900_VCS0 0xf13d0040
-#define F0900_VGPIO13 0xf13d0020
-#define F0900_VGPIO12 0xf13d0010
-#define F0900_VGPIO11 0xf13d0008
-#define F0900_VGPIO10 0xf13d0004
-#define F0900_VGPIO9 0xf13d0002
-#define F0900_VGPIO8 0xf13d0001
-
-/*IOPVALUE0*/
-#define R0900_IOPVALUE0 0xf13e
-#define F0900_VGPIO7 0xf13e0080
-#define F0900_VGPIO6 0xf13e0040
-#define F0900_VGPIO5 0xf13e0020
-#define F0900_VGPIO4 0xf13e0010
-#define F0900_VGPIO3 0xf13e0008
-#define F0900_VGPIO2 0xf13e0004
-#define F0900_VGPIO1 0xf13e0002
-#define F0900_VCLKI2 0xf13e0001
-
-/*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
-
-/*STRSTATUS1*/
-#define R0900_STRSTATUS1 0xf16a
-#define F0900_STRSTATUS_SEL2 0xf16a00f0
-#define F0900_STRSTATUS_SEL1 0xf16a000f
-
-/*STRSTATUS2*/
-#define R0900_STRSTATUS2 0xf16b
-#define F0900_STRSTATUS_SEL4 0xf16b00f0
-#define F0900_STRSTATUS_SEL3 0xf16b000f
-
-/*STRSTATUS3*/
-#define R0900_STRSTATUS3 0xf16c
-#define F0900_STRSTATUS_SEL6 0xf16c00f0
-#define F0900_STRSTATUS_SEL5 0xf16c000f
-
-/*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_SELECT0 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_PRESC 0xf19c0007
-
-/*P2_ACRDIV*/
-#define R0900_P2_ACRDIV 0xf19d
-#define F0900_P2_ACR_DIV 0xf19d00ff
-
-/*P1_DISTXCTL*/
-#define R0900_P1_DISTXCTL 0xf1a0
-#define DISTXCTL shiftx(R0900_P1_DISTXCTL, demod, 0x10)
-#define F0900_P1_TIM_OFF 0xf1a00080
-#define F0900_P1_DISEQC_RESET 0xf1a00040
-#define DISEQC_RESET shiftx(F0900_P1_DISEQC_RESET, demod, 0x100000)
-#define F0900_P1_TIM_CMD 0xf1a00030
-#define F0900_P1_DIS_PRECHARGE 0xf1a00008
-#define DIS_PRECHARGE shiftx(F0900_P1_DIS_PRECHARGE, demod, 0x100000)
-#define F0900_P1_DISTX_MODE 0xf1a00007
-#define DISTX_MODE shiftx(F0900_P1_DISTX_MODE, demod, 0x100000)
-
-/*P1_DISRXCTL*/
-#define R0900_P1_DISRXCTL 0xf1a1
-#define DISRXCTL shiftx(R0900_P1_DISRXCTL, demod, 0x10)
-#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_SELECT0 0xf1a1000c
-#define F0900_P1_IRQ_RXEND 0xf1a10002
-#define F0900_P1_IRQ_4NBYTES 0xf1a10001
-
-/*P1_DISRX_ST0*/
-#define R0900_P1_DISRX_ST0 0xf1a4
-#define DISRX_ST0 shiftx(R0900_P1_DISRX_ST0, demod, 0x10)
-#define F0900_P1_RX_END 0xf1a40080
-#define RX_END shiftx(F0900_P1_RX_END, demod, 0x100000)
-#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 DISRX_ST1 shiftx(R0900_P1_DISRX_ST1, demod, 0x10)
-#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
-#define FIFO_BYTENBR shiftx(F0900_P1_FIFO_BYTENBR, demod, 0x100000)
-
-/*P1_DISRXDATA*/
-#define R0900_P1_DISRXDATA 0xf1a6
-#define DISRXDATA shiftx(R0900_P1_DISRXDATA, demod, 0x10)
-#define F0900_P1_DISRX_DATA 0xf1a600ff
-
-/*P1_DISTXDATA*/
-#define R0900_P1_DISTXDATA 0xf1a7
-#define DISTXDATA shiftx(R0900_P1_DISTXDATA, demod, 0x10)
-#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 FIFO_FULL shiftx(F0900_P1_FIFO_FULL, demod, 0x100000)
-#define F0900_P1_TX_IDLE 0xf1a80020
-#define TX_IDLE shiftx(F0900_P1_TX_IDLE, demod, 0x100000)
-#define F0900_P1_GAP_BURST 0xf1a80010
-#define F0900_P1_TXFIFO_BYTES 0xf1a8000f
-
-/*P1_F22TX*/
-#define R0900_P1_F22TX 0xf1a9
-#define F22TX shiftx(R0900_P1_F22TX, demod, 0x10)
-#define F0900_P1_F22_REG 0xf1a900ff
-
-/*P1_F22RX*/
-#define R0900_P1_F22RX 0xf1aa
-#define F22RX shiftx(R0900_P1_F22RX, demod, 0x10)
-#define F0900_P1_F22RX_REG 0xf1aa00ff
-
-/*P1_ACRPRESC*/
-#define R0900_P1_ACRPRESC 0xf1ac
-#define ACRPRESC shiftx(R0900_P1_ACRPRESC, demod, 0x10)
-#define F0900_P1_ACR_PRESC 0xf1ac0007
-
-/*P1_ACRDIV*/
-#define R0900_P1_ACRDIV 0xf1ad
-#define ACRDIV shiftx(R0900_P1_ACRDIV, demod, 0x10)
-#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_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_SEL_FSKCKDIV 0xf1b70004
-#define F0900_INV_CLKFSK 0xf1b70002
-#define F0900_BYPASS_APPLI 0xf1b70001
-
-/*PLLSTAT*/
-#define R0900_PLLSTAT 0xf1b8
-#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 STOP_CLKVIT shiftx(F0900_STOP_CLKVIT1, demod, -2)
-#define F0900_STOP_CLKTS 0xf1c30001
-
-/*TSTTNR0*/
-#define R0900_TSTTNR0 0xf1df
-#define F0900_SEL_FSK 0xf1df0080
-#define F0900_FSK_PON 0xf1df0004
-
-/*TSTTNR1*/
-#define R0900_TSTTNR1 0xf1e0
-#define F0900_ADC1_PON 0xf1e00002
-#define F0900_ADC1_INMODE 0xf1e00001
-
-/*TSTTNR2*/
-#define R0900_TSTTNR2 0xf1e1
-#define F0900_DISEQC1_PON 0xf1e10020
-
-/*TSTTNR3*/
-#define R0900_TSTTNR3 0xf1e2
-#define F0900_ADC2_PON 0xf1e20002
-#define F0900_ADC2_INMODE 0xf1e20001
-
-/*TSTTNR4*/
-#define R0900_TSTTNR4 0xf1e3
-#define F0900_DISEQC2_PON 0xf1e30020
-
-/*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
-
-/*P2_AGC1CN*/
-#define R0900_P2_AGC1CN 0xf206
-#define F0900_P2_AGC1_LOCKED 0xf2060080
-#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_MANUALS2_ROLLOFF 0xf2100080
-#define F0900_P2_SPECINV_CONTROL 0xf2100030
-#define F0900_P2_FORCE_ENASAMP 0xf2100008
-#define F0900_P2_MANUALSX_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_LOCK_DEFINITIF 0xf2120008
-#define F0900_P2_OVADC_DETECT 0xf2120001
-
-/*P2_DSTATUS2*/
-#define R0900_P2_DSTATUS2 0xf213
-#define F0900_P2_DEMOD_DELOCK 0xf2130080
-#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_SCAN_ENABLE 0xf2140010
-#define F0900_P2_CFR_AUTOSCAN 0xf2140008
-#define F0900_P2_TUN_RNG 0xf2140003
-
-/*P2_DMDCFG2*/
-#define R0900_P2_DMDCFG2 0xf215
-#define F0900_P2_S1S2_SEQUENTIAL 0xf2150040
-#define F0900_P2_INFINITE_RELOCK 0xf2150010
-
-/*P2_DMDISTATE*/
-#define R0900_P2_DMDISTATE 0xf216
-#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_HEADER_MODE 0xf21b0060
-
-/*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_DEMOD_CFGMODE 0xf21d0060
-
-/*P2_DMDCFG3*/
-#define R0900_P2_DMDCFG3 0xf21e
-#define F0900_P2_NOSTOP_FIFOFULL 0xf21e0008
-
-/*P2_DMDCFG4*/
-#define R0900_P2_DMDCFG4 0xf21f
-#define F0900_P2_TUNER_NRELAUNCH 0xf21f0008
-
-/*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_DMDREG*/
-#define R0900_P2_DMDREG 0xf225
-#define F0900_P2_DECIM_PLFRAMES 0xf2250001
-
-/*P2_AGC2O*/
-#define R0900_P2_AGC2O 0xf22c
-#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_AGC1_ADJUSTED 0xf22e007f
-
-/*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_ROTAON 0xf2380004
-#define F0900_P2_PH_DET_ALGO 0xf2380003
-
-/*P2_ACLC*/
-#define R0900_P2_ACLC 0xf239
-#define F0900_P2_CAR_ALPHA_MANT 0xf2390030
-#define F0900_P2_CAR_ALPHA_EXP 0xf239000f
-
-/*P2_BCLC*/
-#define R0900_P2_BCLC 0xf23a
-#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_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 0xf24a003f
-
-/*P2_CFRINC0*/
-#define R0900_P2_CFRINC0 0xf24b
-#define F0900_P2_CFR_INC0 0xf24b00f8
-
-/*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_DO_TIMING_CORR 0xf2500010
-#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_SFRRATIO_FINE 0xf25a0001
-
-/*P2_KREFTMG2*/
-#define R0900_P2_KREFTMG2 0xf25b
-#define F0900_P2_KREF_TMG2 0xf25b00ff
-
-/*P2_SFRINIT1*/
-#define R0900_P2_SFRINIT1 0xf25e
-#define F0900_P2_SFR_INIT1 0xf25e007f
-
-/*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
-
-/*P2_EQUALCFG*/
-#define R0900_P2_EQUALCFG 0xf26f
-#define F0900_P2_EQUAL_ON 0xf26f0040
-#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_CARRIER3_DISABLE 0xf2900040
-#define F0900_P2_ROTA2ON 0xf2900004
-#define F0900_P2_PH_DET_ALGO2 0xf2900003
-
-/*P2_CFR2CFR1*/
-#define R0900_P2_CFR2CFR1 0xf291
-#define F0900_P2_CFR2TOCFR1_DVBS1 0xf29100c0
-#define F0900_P2_EN_S2CAR2CENTER 0xf2910020
-#define F0900_P2_DIS_BCHERRCFR2 0xf2910010
-#define F0900_P2_CFR2TOCFR1_BETA 0xf2910007
-
-/*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_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_8_ALPH_M 0xf2980030
-#define F0900_P2_CAR2S2_8_ALPH_E 0xf298000f
-
-/*P2_ACLC2S216A*/
-#define R0900_P2_ACLC2S216A 0xf299
-#define F0900_P2_DIS_C3STOPA2 0xf2990080
-#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_CAR2S2_Q_BETA_M 0xf29c0030
-#define F0900_P2_CAR2S2_Q_BETA_E 0xf29c000f
-
-/*P2_BCLC2S28*/
-#define R0900_P2_BCLC2S28 0xf29d
-#define F0900_P2_CAR2S2_8_BETA_M 0xf29d0030
-#define F0900_P2_CAR2S2_8_BETA_E 0xf29d000f
-
-/*P2_BCLC2S216A*/
-#define R0900_P2_BCLC2S216A 0xf29e
-
-/*P2_BCLC2S232A*/
-#define R0900_P2_BCLC2S232A 0xf29f
-
-/*P2_PLROOT2*/
-#define R0900_P2_PLROOT2 0xf2ac
-#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
-
-/*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
-
-/*P2_GAUSSR0*/
-#define R0900_P2_GAUSSR0 0xf2c0
-#define F0900_P2_EN_CCIMODE 0xf2c00080
-#define F0900_P2_R0_GAUSSIEN 0xf2c0007f
-
-/*P2_CCIR0*/
-#define R0900_P2_CCIR0 0xf2c1
-#define F0900_P2_CCIDETECT_PLHONLY 0xf2c10080
-#define F0900_P2_R0_CCI 0xf2c1007f
-
-/*P2_CCIQUANT*/
-#define R0900_P2_CCIQUANT 0xf2c2
-#define F0900_P2_CCI_BETA 0xf2c200e0
-#define F0900_P2_CCI_QUANT 0xf2c2001f
-
-/*P2_CCITHRES*/
-#define R0900_P2_CCITHRES 0xf2c3
-#define F0900_P2_CCI_THRESHOLD 0xf2c300ff
-
-/*P2_CCIACC*/
-#define R0900_P2_CCIACC 0xf2c4
-#define F0900_P2_CCI_VALUE 0xf2c400ff
-
-/*P2_DMDRESCFG*/
-#define R0900_P2_DMDRESCFG 0xf2c6
-#define F0900_P2_DMDRES_RESET 0xf2c60080
-#define F0900_P2_DMDRES_STRALL 0xf2c60008
-#define F0900_P2_DMDRES_NEWONLY 0xf2c60004
-#define F0900_P2_DMDRES_NOSTORE 0xf2c60002
-
-/*P2_DMDRESADR*/
-#define R0900_P2_DMDRESADR 0xf2c7
-#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_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_DIS_BWCALC 0xf2e10004
-#define F0900_P2_SHORT_WAITSTATES 0xf2e10002
-
-/*P2_TNRXTAL*/
-#define R0900_P2_TNRXTAL 0xf2e4
-#define F0900_P2_TUN_XTALFREQ 0xf2e4001f
-
-/*P2_TNRSTEPS*/
-#define R0900_P2_TNRSTEPS 0xf2e7
-#define F0900_P2_TUNER_BW0P125 0xf2e70080
-#define F0900_P2_BWINC_OFFSET 0xf2e70170
-#define F0900_P2_SOFTSTEP_RNG 0xf2e70008
-#define F0900_P2_TUN_BWOFFSET 0xf2e70007
-
-/*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_CALTIME 0xf2ec0040
-
-/*P2_TNRCTL2*/
-#define R0900_P2_TNRCTL2 0xf2ed
-#define F0900_P2_STB61X0_RCCKOFF 0xf2ed0080
-#define F0900_P2_STB61X0_ICP_SDOFF 0xf2ed0040
-#define F0900_P2_STB61X0_DCLOOPOFF 0xf2ed0020
-#define F0900_P2_STB61X0_REFOUTSEL 0xf2ed0010
-#define F0900_P2_STB61X0_CALOFF 0xf2ed0008
-#define F0900_P2_STB6XX0_LPT_BEN 0xf2ed0004
-#define F0900_P2_STB6XX0_RX_OSCP 0xf2ed0002
-#define F0900_P2_STB6XX0_SYN 0xf2ed0001
-
-/*P2_TNRCFG3*/
-#define R0900_P2_TNRCFG3 0xf2ee
-#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_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_NCO2MAX1*/
-#define R0900_P2_NCO2MAX1 0xf314
-#define F0900_P2_TETA2_MAXVABS1 0xf31400ff
-
-/*P2_NCO2MAX0*/
-#define R0900_P2_NCO2MAX0 0xf315
-#define F0900_P2_TETA2_MAXVABS0 0xf31500ff
-
-/*P2_NCO2FR1*/
-#define R0900_P2_NCO2FR1 0xf316
-#define F0900_P2_NCO2FINAL_ANGLE1 0xf31600ff
-
-/*P2_NCO2FR0*/
-#define R0900_P2_NCO2FR0 0xf317
-#define F0900_P2_NCO2FINAL_ANGLE0 0xf31700ff
-
-/*P2_CFR2AVRGE1*/
-#define R0900_P2_CFR2AVRGE1 0xf318
-#define F0900_P2_I2C_CFR2AVERAGE1 0xf31800ff
-
-/*P2_CFR2AVRGE0*/
-#define R0900_P2_CFR2AVRGE0 0xf319
-#define F0900_P2_I2C_CFR2AVERAGE0 0xf31900ff
-
-/*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_NSLOWSN_LOCKED 0xf3320008
-#define F0900_P2_DIS_RSFLOCK 0xf3320002
-
-/*P2_FECM*/
-#define R0900_P2_FECM 0xf333
-#define F0900_P2_DSS_DVB 0xf3330080
-#define F0900_P2_DSS_SRCH 0xf3330010
-#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_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_PRFVIT 0xf33e0010
-#define F0900_P2_LOCKEDVIT 0xf33e0008
-
-/*P2_VTHINUSE*/
-#define R0900_P2_VTHINUSE 0xf33f
-#define F0900_P2_VIT_INUSE 0xf33f00ff
-
-/*P2_KDIV12*/
-#define R0900_P2_KDIV12 0xf340
-#define F0900_P2_K_DIVIDER_12 0xf340007f
-
-/*P2_KDIV23*/
-#define R0900_P2_KDIV23 0xf341
-#define F0900_P2_K_DIVIDER_23 0xf341007f
-
-/*P2_KDIV34*/
-#define R0900_P2_KDIV34 0xf342
-#define F0900_P2_K_DIVIDER_34 0xf342007f
-
-/*P2_KDIV56*/
-#define R0900_P2_KDIV56 0xf343
-#define F0900_P2_K_DIVIDER_56 0xf343007f
-
-/*P2_KDIV67*/
-#define R0900_P2_KDIV67 0xf344
-#define F0900_P2_K_DIVIDER_67 0xf344007f
-
-/*P2_KDIV78*/
-#define R0900_P2_KDIV78 0xf345
-#define F0900_P2_K_DIVIDER_78 0xf345007f
-
-/*P2_PDELCTRL1*/
-#define R0900_P2_PDELCTRL1 0xf350
-#define F0900_P2_INV_MISMASK 0xf3500080
-#define F0900_P2_FILTER_EN 0xf3500020
-#define F0900_P2_EN_MIS00 0xf3500002
-#define F0900_P2_ALGOSWRST 0xf3500001
-
-/*P2_PDELCTRL2*/
-#define R0900_P2_PDELCTRL2 0xf351
-#define F0900_P2_RESET_UPKO_COUNT 0xf3510040
-#define F0900_P2_FRAME_MODE 0xf3510002
-#define F0900_P2_NOBCHERRFLG_USE 0xf3510001
-
-/*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_PKTDELIN_LOCK 0xf3690002
-#define F0900_P2_FIRST_LOCK 0xf3690001
-
-/*P2_PDELSTATUS2*/
-#define R0900_P2_PDELSTATUS2 0xf36a
-#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_PDELCTRL3*/
-#define R0900_P2_PDELCTRL3 0xf36f
-#define F0900_P2_PKTDEL_CONTFAIL 0xf36f0080
-#define F0900_P2_NOFIFO_BCHERR 0xf36f0020
-
-/*P2_TSSTATEM*/
-#define R0900_P2_TSSTATEM 0xf370
-#define F0900_P2_TSDIL_ON 0xf3700080
-#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_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_DPUNACT 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_BITSPEED 0xf3740003
-
-/*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_TSDIVN*/
-#define R0900_P2_TSDIVN 0xf379
-#define F0900_P2_TSFIFO_SPEEDMODE 0xf37900c0
-
-/*P2_TSCFG4*/
-#define R0900_P2_TSCFG4 0xf37a
-#define F0900_P2_TSFIFO_TSSPEEDMODE 0xf37a00c0
-
-/*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_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_SCRAMBDETECT 0xf3820002
-
-/*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_BERMETER_DATAMODE 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_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_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_FSPYBER_SYNCBYTE 0xf3b20010
-#define F0900_P2_FSPYBER_UNSYNC 0xf3b20008
-#define F0900_P2_FSPYBER_CTIME 0xf3b20007
-
-/*P1_IQCONST*/
-#define R0900_P1_IQCONST 0xf400
-#define IQCONST REGx(R0900_P1_IQCONST)
-#define F0900_P1_CONSTEL_SELECT 0xf4000060
-#define F0900_P1_IQSYMB_SEL 0xf400001f
-
-/*P1_NOSCFG*/
-#define R0900_P1_NOSCFG 0xf401
-#define NOSCFG REGx(R0900_P1_NOSCFG)
-#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 ISYMB REGx(R0900_P1_ISYMB)
-#define F0900_P1_I_SYMBOL 0xf40201ff
-
-/*P1_QSYMB*/
-#define R0900_P1_QSYMB 0xf403
-#define QSYMB REGx(R0900_P1_QSYMB)
-#define F0900_P1_Q_SYMBOL 0xf40301ff
-
-/*P1_AGC1CFG*/
-#define R0900_P1_AGC1CFG 0xf404
-#define AGC1CFG REGx(R0900_P1_AGC1CFG)
-#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
-
-/*P1_AGC1CN*/
-#define R0900_P1_AGC1CN 0xf406
-#define AGC1CN REGx(R0900_P1_AGC1CN)
-#define F0900_P1_AGC1_LOCKED 0xf4060080
-#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 AGC1REF REGx(R0900_P1_AGC1REF)
-#define F0900_P1_AGCIQ_REF 0xf40700ff
-
-/*P1_IDCCOMP*/
-#define R0900_P1_IDCCOMP 0xf408
-#define IDCCOMP REGx(R0900_P1_IDCCOMP)
-#define F0900_P1_IAVERAGE_ADJ 0xf40801ff
-
-/*P1_QDCCOMP*/
-#define R0900_P1_QDCCOMP 0xf409
-#define QDCCOMP REGx(R0900_P1_QDCCOMP)
-#define F0900_P1_QAVERAGE_ADJ 0xf40901ff
-
-/*P1_POWERI*/
-#define R0900_P1_POWERI 0xf40a
-#define POWERI REGx(R0900_P1_POWERI)
-#define F0900_P1_POWER_I 0xf40a00ff
-#define POWER_I FLDx(F0900_P1_POWER_I)
-
-/*P1_POWERQ*/
-#define R0900_P1_POWERQ 0xf40b
-#define POWERQ REGx(R0900_P1_POWERQ)
-#define F0900_P1_POWER_Q 0xf40b00ff
-#define POWER_Q FLDx(F0900_P1_POWER_Q)
-
-/*P1_AGC1AMM*/
-#define R0900_P1_AGC1AMM 0xf40c
-#define AGC1AMM REGx(R0900_P1_AGC1AMM)
-#define F0900_P1_AMM_VALUE 0xf40c00ff
-
-/*P1_AGC1QUAD*/
-#define R0900_P1_AGC1QUAD 0xf40d
-#define AGC1QUAD REGx(R0900_P1_AGC1QUAD)
-#define F0900_P1_QUAD_VALUE 0xf40d01ff
-
-/*P1_AGCIQIN1*/
-#define R0900_P1_AGCIQIN1 0xf40e
-#define AGCIQIN1 REGx(R0900_P1_AGCIQIN1)
-#define F0900_P1_AGCIQ_VALUE1 0xf40e00ff
-#define AGCIQ_VALUE1 FLDx(F0900_P1_AGCIQ_VALUE1)
-
-/*P1_AGCIQIN0*/
-#define R0900_P1_AGCIQIN0 0xf40f
-#define AGCIQIN0 REGx(R0900_P1_AGCIQIN0)
-#define F0900_P1_AGCIQ_VALUE0 0xf40f00ff
-#define AGCIQ_VALUE0 FLDx(F0900_P1_AGCIQ_VALUE0)
-
-/*P1_DEMOD*/
-#define R0900_P1_DEMOD 0xf410
-#define DEMOD REGx(R0900_P1_DEMOD)
-#define F0900_P1_MANUALS2_ROLLOFF 0xf4100080
-#define MANUALS2_ROLLOFF FLDx(F0900_P1_MANUALS2_ROLLOFF)
-
-#define F0900_P1_SPECINV_CONTROL 0xf4100030
-#define SPECINV_CONTROL FLDx(F0900_P1_SPECINV_CONTROL)
-#define F0900_P1_FORCE_ENASAMP 0xf4100008
-#define F0900_P1_MANUALSX_ROLLOFF 0xf4100004
-#define MANUALSX_ROLLOFF FLDx(F0900_P1_MANUALSX_ROLLOFF)
-#define F0900_P1_ROLLOFF_CONTROL 0xf4100003
-#define ROLLOFF_CONTROL FLDx(F0900_P1_ROLLOFF_CONTROL)
-
-/*P1_DMDMODCOD*/
-#define R0900_P1_DMDMODCOD 0xf411
-#define DMDMODCOD REGx(R0900_P1_DMDMODCOD)
-#define F0900_P1_MANUAL_MODCOD 0xf4110080
-#define F0900_P1_DEMOD_MODCOD 0xf411007c
-#define DEMOD_MODCOD FLDx(F0900_P1_DEMOD_MODCOD)
-#define F0900_P1_DEMOD_TYPE 0xf4110003
-#define DEMOD_TYPE FLDx(F0900_P1_DEMOD_TYPE)
-
-/*P1_DSTATUS*/
-#define R0900_P1_DSTATUS 0xf412
-#define DSTATUS REGx(R0900_P1_DSTATUS)
-#define F0900_P1_CAR_LOCK 0xf4120080
-#define F0900_P1_TMGLOCK_QUALITY 0xf4120060
-#define TMGLOCK_QUALITY FLDx(F0900_P1_TMGLOCK_QUALITY)
-#define F0900_P1_LOCK_DEFINITIF 0xf4120008
-#define LOCK_DEFINITIF FLDx(F0900_P1_LOCK_DEFINITIF)
-#define F0900_P1_OVADC_DETECT 0xf4120001
-
-/*P1_DSTATUS2*/
-#define R0900_P1_DSTATUS2 0xf413
-#define DSTATUS2 REGx(R0900_P1_DSTATUS2)
-#define F0900_P1_DEMOD_DELOCK 0xf4130080
-#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 DMDCFGMD REGx(R0900_P1_DMDCFGMD)
-#define F0900_P1_DVBS2_ENABLE 0xf4140080
-#define DVBS2_ENABLE FLDx(F0900_P1_DVBS2_ENABLE)
-#define F0900_P1_DVBS1_ENABLE 0xf4140040
-#define DVBS1_ENABLE FLDx(F0900_P1_DVBS1_ENABLE)
-#define F0900_P1_SCAN_ENABLE 0xf4140010
-#define SCAN_ENABLE FLDx(F0900_P1_SCAN_ENABLE)
-#define F0900_P1_CFR_AUTOSCAN 0xf4140008
-#define CFR_AUTOSCAN FLDx(F0900_P1_CFR_AUTOSCAN)
-#define F0900_P1_TUN_RNG 0xf4140003
-
-/*P1_DMDCFG2*/
-#define R0900_P1_DMDCFG2 0xf415
-#define DMDCFG2 REGx(R0900_P1_DMDCFG2)
-#define F0900_P1_S1S2_SEQUENTIAL 0xf4150040
-#define S1S2_SEQUENTIAL FLDx(F0900_P1_S1S2_SEQUENTIAL)
-#define F0900_P1_INFINITE_RELOCK 0xf4150010
-
-/*P1_DMDISTATE*/
-#define R0900_P1_DMDISTATE 0xf416
-#define DMDISTATE REGx(R0900_P1_DMDISTATE)
-#define F0900_P1_I2C_DEMOD_MODE 0xf416001f
-#define DEMOD_MODE FLDx(F0900_P1_I2C_DEMOD_MODE)
-
-/*P1_DMDT0M*/
-#define R0900_P1_DMDT0M 0xf417
-#define DMDT0M REGx(R0900_P1_DMDT0M)
-#define F0900_P1_DMDT0_MIN 0xf41700ff
-
-/*P1_DMDSTATE*/
-#define R0900_P1_DMDSTATE 0xf41b
-#define DMDSTATE REGx(R0900_P1_DMDSTATE)
-#define F0900_P1_HEADER_MODE 0xf41b0060
-#define HEADER_MODE FLDx(F0900_P1_HEADER_MODE)
-
-/*P1_DMDFLYW*/
-#define R0900_P1_DMDFLYW 0xf41c
-#define DMDFLYW REGx(R0900_P1_DMDFLYW)
-#define F0900_P1_I2C_IRQVAL 0xf41c00f0
-#define F0900_P1_FLYWHEEL_CPT 0xf41c000f
-#define FLYWHEEL_CPT FLDx(F0900_P1_FLYWHEEL_CPT)
-
-/*P1_DSTATUS3*/
-#define R0900_P1_DSTATUS3 0xf41d
-#define DSTATUS3 REGx(R0900_P1_DSTATUS3)
-#define F0900_P1_DEMOD_CFGMODE 0xf41d0060
-
-/*P1_DMDCFG3*/
-#define R0900_P1_DMDCFG3 0xf41e
-#define DMDCFG3 REGx(R0900_P1_DMDCFG3)
-#define F0900_P1_NOSTOP_FIFOFULL 0xf41e0008
-
-/*P1_DMDCFG4*/
-#define R0900_P1_DMDCFG4 0xf41f
-#define DMDCFG4 REGx(R0900_P1_DMDCFG4)
-#define F0900_P1_TUNER_NRELAUNCH 0xf41f0008
-
-/*P1_CORRELMANT*/
-#define R0900_P1_CORRELMANT 0xf420
-#define CORRELMANT REGx(R0900_P1_CORRELMANT)
-#define F0900_P1_CORREL_MANT 0xf42000ff
-
-/*P1_CORRELABS*/
-#define R0900_P1_CORRELABS 0xf421
-#define CORRELABS REGx(R0900_P1_CORRELABS)
-#define F0900_P1_CORREL_ABS 0xf42100ff
-
-/*P1_CORRELEXP*/
-#define R0900_P1_CORRELEXP 0xf422
-#define CORRELEXP REGx(R0900_P1_CORRELEXP)
-#define F0900_P1_CORREL_ABSEXP 0xf42200f0
-#define F0900_P1_CORREL_EXP 0xf422000f
-
-/*P1_PLHMODCOD*/
-#define R0900_P1_PLHMODCOD 0xf424
-#define PLHMODCOD REGx(R0900_P1_PLHMODCOD)
-#define F0900_P1_SPECINV_DEMOD 0xf4240080
-#define SPECINV_DEMOD FLDx(F0900_P1_SPECINV_DEMOD)
-#define F0900_P1_PLH_MODCOD 0xf424007c
-#define F0900_P1_PLH_TYPE 0xf4240003
-
-/*P1_DMDREG*/
-#define R0900_P1_DMDREG 0xf425
-#define DMDREG REGx(R0900_P1_DMDREG)
-#define F0900_P1_DECIM_PLFRAMES 0xf4250001
-
-/*P1_AGC2O*/
-#define R0900_P1_AGC2O 0xf42c
-#define AGC2O REGx(R0900_P1_AGC2O)
-#define F0900_P1_AGC2_COEF 0xf42c0007
-
-/*P1_AGC2REF*/
-#define R0900_P1_AGC2REF 0xf42d
-#define AGC2REF REGx(R0900_P1_AGC2REF)
-#define F0900_P1_AGC2_REF 0xf42d00ff
-
-/*P1_AGC1ADJ*/
-#define R0900_P1_AGC1ADJ 0xf42e
-#define AGC1ADJ REGx(R0900_P1_AGC1ADJ)
-#define F0900_P1_AGC1_ADJUSTED 0xf42e007f
-
-/*P1_AGC2I1*/
-#define R0900_P1_AGC2I1 0xf436
-#define AGC2I1 REGx(R0900_P1_AGC2I1)
-#define F0900_P1_AGC2_INTEGRATOR1 0xf43600ff
-
-/*P1_AGC2I0*/
-#define R0900_P1_AGC2I0 0xf437
-#define AGC2I0 REGx(R0900_P1_AGC2I0)
-#define F0900_P1_AGC2_INTEGRATOR0 0xf43700ff
-
-/*P1_CARCFG*/
-#define R0900_P1_CARCFG 0xf438
-#define CARCFG REGx(R0900_P1_CARCFG)
-#define F0900_P1_CFRUPLOW_AUTO 0xf4380080
-#define F0900_P1_CFRUPLOW_TEST 0xf4380040
-#define F0900_P1_ROTAON 0xf4380004
-#define F0900_P1_PH_DET_ALGO 0xf4380003
-
-/*P1_ACLC*/
-#define R0900_P1_ACLC 0xf439
-#define ACLC REGx(R0900_P1_ACLC)
-#define F0900_P1_CAR_ALPHA_MANT 0xf4390030
-#define F0900_P1_CAR_ALPHA_EXP 0xf439000f
-
-/*P1_BCLC*/
-#define R0900_P1_BCLC 0xf43a
-#define BCLC REGx(R0900_P1_BCLC)
-#define F0900_P1_CAR_BETA_MANT 0xf43a0030
-#define F0900_P1_CAR_BETA_EXP 0xf43a000f
-
-/*P1_CARFREQ*/
-#define R0900_P1_CARFREQ 0xf43d
-#define CARFREQ REGx(R0900_P1_CARFREQ)
-#define F0900_P1_KC_COARSE_EXP 0xf43d00f0
-#define F0900_P1_BETA_FREQ 0xf43d000f
-
-/*P1_CARHDR*/
-#define R0900_P1_CARHDR 0xf43e
-#define CARHDR REGx(R0900_P1_CARHDR)
-#define F0900_P1_K_FREQ_HDR 0xf43e00ff
-
-/*P1_LDT*/
-#define R0900_P1_LDT 0xf43f
-#define LDT REGx(R0900_P1_LDT)
-#define F0900_P1_CARLOCK_THRES 0xf43f01ff
-
-/*P1_LDT2*/
-#define R0900_P1_LDT2 0xf440
-#define LDT2 REGx(R0900_P1_LDT2)
-#define F0900_P1_CARLOCK_THRES2 0xf44001ff
-
-/*P1_CFRICFG*/
-#define R0900_P1_CFRICFG 0xf441
-#define CFRICFG REGx(R0900_P1_CFRICFG)
-#define F0900_P1_NEG_CFRSTEP 0xf4410001
-
-/*P1_CFRUP1*/
-#define R0900_P1_CFRUP1 0xf442
-#define CFRUP1 REGx(R0900_P1_CFRUP1)
-#define F0900_P1_CFR_UP1 0xf44201ff
-#define CFR_UP1 FLDx(F0900_P1_CFR_UP1)
-
-/*P1_CFRUP0*/
-#define R0900_P1_CFRUP0 0xf443
-#define CFRUP0 REGx(R0900_P1_CFRUP0)
-#define F0900_P1_CFR_UP0 0xf44300ff
-#define CFR_UP0 FLDx(F0900_P1_CFR_UP0)
-
-/*P1_CFRLOW1*/
-#define R0900_P1_CFRLOW1 0xf446
-#define CFRLOW1 REGx(R0900_P1_CFRLOW1)
-#define F0900_P1_CFR_LOW1 0xf44601ff
-#define CFR_LOW1 FLDx(F0900_P1_CFR_LOW1)
-
-/*P1_CFRLOW0*/
-#define R0900_P1_CFRLOW0 0xf447
-#define CFRLOW0 REGx(R0900_P1_CFRLOW0)
-#define F0900_P1_CFR_LOW0 0xf44700ff
-#define CFR_LOW0 FLDx(F0900_P1_CFR_LOW0)
-
-/*P1_CFRINIT1*/
-#define R0900_P1_CFRINIT1 0xf448
-#define CFRINIT1 REGx(R0900_P1_CFRINIT1)
-#define F0900_P1_CFR_INIT1 0xf44801ff
-#define CFR_INIT1 FLDx(F0900_P1_CFR_INIT1)
-
-/*P1_CFRINIT0*/
-#define R0900_P1_CFRINIT0 0xf449
-#define CFRINIT0 REGx(R0900_P1_CFRINIT0)
-#define F0900_P1_CFR_INIT0 0xf44900ff
-#define CFR_INIT0 FLDx(F0900_P1_CFR_INIT0)
-
-/*P1_CFRINC1*/
-#define R0900_P1_CFRINC1 0xf44a
-#define CFRINC1 REGx(R0900_P1_CFRINC1)
-#define F0900_P1_MANUAL_CFRINC 0xf44a0080
-#define F0900_P1_CFR_INC1 0xf44a003f
-
-/*P1_CFRINC0*/
-#define R0900_P1_CFRINC0 0xf44b
-#define CFRINC0 REGx(R0900_P1_CFRINC0)
-#define F0900_P1_CFR_INC0 0xf44b00f8
-
-/*P1_CFR2*/
-#define R0900_P1_CFR2 0xf44c
-#define CFR2 REGx(R0900_P1_CFR2)
-#define F0900_P1_CAR_FREQ2 0xf44c01ff
-#define CAR_FREQ2 FLDx(F0900_P1_CAR_FREQ2)
-
-/*P1_CFR1*/
-#define R0900_P1_CFR1 0xf44d
-#define CFR1 REGx(R0900_P1_CFR1)
-#define F0900_P1_CAR_FREQ1 0xf44d00ff
-#define CAR_FREQ1 FLDx(F0900_P1_CAR_FREQ1)
-
-/*P1_CFR0*/
-#define R0900_P1_CFR0 0xf44e
-#define CFR0 REGx(R0900_P1_CFR0)
-#define F0900_P1_CAR_FREQ0 0xf44e00ff
-#define CAR_FREQ0 FLDx(F0900_P1_CAR_FREQ0)
-
-/*P1_LDI*/
-#define R0900_P1_LDI 0xf44f
-#define LDI REGx(R0900_P1_LDI)
-#define F0900_P1_LOCK_DET_INTEGR 0xf44f01ff
-
-/*P1_TMGCFG*/
-#define R0900_P1_TMGCFG 0xf450
-#define TMGCFG REGx(R0900_P1_TMGCFG)
-#define F0900_P1_TMGLOCK_BETA 0xf45000c0
-#define F0900_P1_DO_TIMING_CORR 0xf4500010
-#define F0900_P1_TMG_MINFREQ 0xf4500003
-
-/*P1_RTC*/
-#define R0900_P1_RTC 0xf451
-#define RTC REGx(R0900_P1_RTC)
-#define F0900_P1_TMGALPHA_EXP 0xf45100f0
-#define F0900_P1_TMGBETA_EXP 0xf451000f
-
-/*P1_RTCS2*/
-#define R0900_P1_RTCS2 0xf452
-#define RTCS2 REGx(R0900_P1_RTCS2)
-#define F0900_P1_TMGALPHAS2_EXP 0xf45200f0
-#define F0900_P1_TMGBETAS2_EXP 0xf452000f
-
-/*P1_TMGTHRISE*/
-#define R0900_P1_TMGTHRISE 0xf453
-#define TMGTHRISE REGx(R0900_P1_TMGTHRISE)
-#define F0900_P1_TMGLOCK_THRISE 0xf45300ff
-
-/*P1_TMGTHFALL*/
-#define R0900_P1_TMGTHFALL 0xf454
-#define TMGTHFALL REGx(R0900_P1_TMGTHFALL)
-#define F0900_P1_TMGLOCK_THFALL 0xf45400ff
-
-/*P1_SFRUPRATIO*/
-#define R0900_P1_SFRUPRATIO 0xf455
-#define SFRUPRATIO REGx(R0900_P1_SFRUPRATIO)
-#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 KREFTMG REGx(R0900_P1_KREFTMG)
-#define F0900_P1_KREF_TMG 0xf45800ff
-
-/*P1_SFRSTEP*/
-#define R0900_P1_SFRSTEP 0xf459
-#define SFRSTEP REGx(R0900_P1_SFRSTEP)
-#define F0900_P1_SFR_SCANSTEP 0xf45900f0
-#define F0900_P1_SFR_CENTERSTEP 0xf459000f
-
-/*P1_TMGCFG2*/
-#define R0900_P1_TMGCFG2 0xf45a
-#define TMGCFG2 REGx(R0900_P1_TMGCFG2)
-#define F0900_P1_SFRRATIO_FINE 0xf45a0001
-
-/*P1_KREFTMG2*/
-#define R0900_P1_KREFTMG2 0xf45b
-#define KREFTMG2 REGx(R0900_P1_KREFTMG2)
-#define F0900_P1_KREF_TMG2 0xf45b00ff
-
-/*P1_SFRINIT1*/
-#define R0900_P1_SFRINIT1 0xf45e
-#define SFRINIT1 REGx(R0900_P1_SFRINIT1)
-#define F0900_P1_SFR_INIT1 0xf45e007f
-
-/*P1_SFRINIT0*/
-#define R0900_P1_SFRINIT0 0xf45f
-#define SFRINIT0 REGx(R0900_P1_SFRINIT0)
-#define F0900_P1_SFR_INIT0 0xf45f00ff
-
-/*P1_SFRUP1*/
-#define R0900_P1_SFRUP1 0xf460
-#define SFRUP1 REGx(R0900_P1_SFRUP1)
-#define F0900_P1_AUTO_GUP 0xf4600080
-#define AUTO_GUP FLDx(F0900_P1_AUTO_GUP)
-#define F0900_P1_SYMB_FREQ_UP1 0xf460007f
-
-/*P1_SFRUP0*/
-#define R0900_P1_SFRUP0 0xf461
-#define SFRUP0 REGx(R0900_P1_SFRUP0)
-#define F0900_P1_SYMB_FREQ_UP0 0xf46100ff
-
-/*P1_SFRLOW1*/
-#define R0900_P1_SFRLOW1 0xf462
-#define SFRLOW1 REGx(R0900_P1_SFRLOW1)
-#define F0900_P1_AUTO_GLOW 0xf4620080
-#define AUTO_GLOW FLDx(F0900_P1_AUTO_GLOW)
-#define F0900_P1_SYMB_FREQ_LOW1 0xf462007f
-
-/*P1_SFRLOW0*/
-#define R0900_P1_SFRLOW0 0xf463
-#define SFRLOW0 REGx(R0900_P1_SFRLOW0)
-#define F0900_P1_SYMB_FREQ_LOW0 0xf46300ff
-
-/*P1_SFR3*/
-#define R0900_P1_SFR3 0xf464
-#define SFR3 REGx(R0900_P1_SFR3)
-#define F0900_P1_SYMB_FREQ3 0xf46400ff
-#define SYMB_FREQ3 FLDx(F0900_P1_SYMB_FREQ3)
-
-/*P1_SFR2*/
-#define R0900_P1_SFR2 0xf465
-#define SFR2 REGx(R0900_P1_SFR2)
-#define F0900_P1_SYMB_FREQ2 0xf46500ff
-#define SYMB_FREQ2 FLDx(F0900_P1_SYMB_FREQ2)
-
-/*P1_SFR1*/
-#define R0900_P1_SFR1 0xf466
-#define SFR1 REGx(R0900_P1_SFR1)
-#define F0900_P1_SYMB_FREQ1 0xf46600ff
-#define SYMB_FREQ1 FLDx(F0900_P1_SYMB_FREQ1)
-
-/*P1_SFR0*/
-#define R0900_P1_SFR0 0xf467
-#define SFR0 REGx(R0900_P1_SFR0)
-#define F0900_P1_SYMB_FREQ0 0xf46700ff
-#define SYMB_FREQ0 FLDx(F0900_P1_SYMB_FREQ0)
-
-/*P1_TMGREG2*/
-#define R0900_P1_TMGREG2 0xf468
-#define TMGREG2 REGx(R0900_P1_TMGREG2)
-#define F0900_P1_TMGREG2 0xf46800ff
-
-/*P1_TMGREG1*/
-#define R0900_P1_TMGREG1 0xf469
-#define TMGREG1 REGx(R0900_P1_TMGREG1)
-#define F0900_P1_TMGREG1 0xf46900ff
-
-/*P1_TMGREG0*/
-#define R0900_P1_TMGREG0 0xf46a
-#define TMGREG0 REGx(R0900_P1_TMGREG0)
-#define F0900_P1_TMGREG0 0xf46a00ff
-
-/*P1_TMGLOCK1*/
-#define R0900_P1_TMGLOCK1 0xf46b
-#define TMGLOCK1 REGx(R0900_P1_TMGLOCK1)
-#define F0900_P1_TMGLOCK_LEVEL1 0xf46b01ff
-
-/*P1_TMGLOCK0*/
-#define R0900_P1_TMGLOCK0 0xf46c
-#define TMGLOCK0 REGx(R0900_P1_TMGLOCK0)
-#define F0900_P1_TMGLOCK_LEVEL0 0xf46c00ff
-
-/*P1_TMGOBS*/
-#define R0900_P1_TMGOBS 0xf46d
-#define TMGOBS REGx(R0900_P1_TMGOBS)
-#define F0900_P1_ROLLOFF_STATUS 0xf46d00c0
-#define ROLLOFF_STATUS FLDx(F0900_P1_ROLLOFF_STATUS)
-
-/*P1_EQUALCFG*/
-#define R0900_P1_EQUALCFG 0xf46f
-#define EQUALCFG REGx(R0900_P1_EQUALCFG)
-#define F0900_P1_EQUAL_ON 0xf46f0040
-#define F0900_P1_MU_EQUALDFE 0xf46f0007
-
-/*P1_EQUAI1*/
-#define R0900_P1_EQUAI1 0xf470
-#define EQUAI1 REGx(R0900_P1_EQUAI1)
-#define F0900_P1_EQUA_ACCI1 0xf47001ff
-
-/*P1_EQUAQ1*/
-#define R0900_P1_EQUAQ1 0xf471
-#define EQUAQ1 REGx(R0900_P1_EQUAQ1)
-#define F0900_P1_EQUA_ACCQ1 0xf47101ff
-
-/*P1_EQUAI2*/
-#define R0900_P1_EQUAI2 0xf472
-#define EQUAI2 REGx(R0900_P1_EQUAI2)
-#define F0900_P1_EQUA_ACCI2 0xf47201ff
-
-/*P1_EQUAQ2*/
-#define R0900_P1_EQUAQ2 0xf473
-#define EQUAQ2 REGx(R0900_P1_EQUAQ2)
-#define F0900_P1_EQUA_ACCQ2 0xf47301ff
-
-/*P1_EQUAI3*/
-#define R0900_P1_EQUAI3 0xf474
-#define EQUAI3 REGx(R0900_P1_EQUAI3)
-#define F0900_P1_EQUA_ACCI3 0xf47401ff
-
-/*P1_EQUAQ3*/
-#define R0900_P1_EQUAQ3 0xf475
-#define EQUAQ3 REGx(R0900_P1_EQUAQ3)
-#define F0900_P1_EQUA_ACCQ3 0xf47501ff
-
-/*P1_EQUAI4*/
-#define R0900_P1_EQUAI4 0xf476
-#define EQUAI4 REGx(R0900_P1_EQUAI4)
-#define F0900_P1_EQUA_ACCI4 0xf47601ff
-
-/*P1_EQUAQ4*/
-#define R0900_P1_EQUAQ4 0xf477
-#define EQUAQ4 REGx(R0900_P1_EQUAQ4)
-#define F0900_P1_EQUA_ACCQ4 0xf47701ff
-
-/*P1_EQUAI5*/
-#define R0900_P1_EQUAI5 0xf478
-#define EQUAI5 REGx(R0900_P1_EQUAI5)
-#define F0900_P1_EQUA_ACCI5 0xf47801ff
-
-/*P1_EQUAQ5*/
-#define R0900_P1_EQUAQ5 0xf479
-#define EQUAQ5 REGx(R0900_P1_EQUAQ5)
-#define F0900_P1_EQUA_ACCQ5 0xf47901ff
-
-/*P1_EQUAI6*/
-#define R0900_P1_EQUAI6 0xf47a
-#define EQUAI6 REGx(R0900_P1_EQUAI6)
-#define F0900_P1_EQUA_ACCI6 0xf47a01ff
-
-/*P1_EQUAQ6*/
-#define R0900_P1_EQUAQ6 0xf47b
-#define EQUAQ6 REGx(R0900_P1_EQUAQ6)
-#define F0900_P1_EQUA_ACCQ6 0xf47b01ff
-
-/*P1_EQUAI7*/
-#define R0900_P1_EQUAI7 0xf47c
-#define EQUAI7 REGx(R0900_P1_EQUAI7)
-#define F0900_P1_EQUA_ACCI7 0xf47c01ff
-
-/*P1_EQUAQ7*/
-#define R0900_P1_EQUAQ7 0xf47d
-#define EQUAQ7 REGx(R0900_P1_EQUAQ7)
-#define F0900_P1_EQUA_ACCQ7 0xf47d01ff
-
-/*P1_EQUAI8*/
-#define R0900_P1_EQUAI8 0xf47e
-#define EQUAI8 REGx(R0900_P1_EQUAI8)
-#define F0900_P1_EQUA_ACCI8 0xf47e01ff
-
-/*P1_EQUAQ8*/
-#define R0900_P1_EQUAQ8 0xf47f
-#define EQUAQ8 REGx(R0900_P1_EQUAQ8)
-#define F0900_P1_EQUA_ACCQ8 0xf47f01ff
-
-/*P1_NNOSDATAT1*/
-#define R0900_P1_NNOSDATAT1 0xf480
-#define NNOSDATAT1 REGx(R0900_P1_NNOSDATAT1)
-#define F0900_P1_NOSDATAT_NORMED1 0xf48000ff
-#define NOSDATAT_NORMED1 FLDx(F0900_P1_NOSDATAT_NORMED1)
-
-/*P1_NNOSDATAT0*/
-#define R0900_P1_NNOSDATAT0 0xf481
-#define NNOSDATAT0 REGx(R0900_P1_NNOSDATAT0)
-#define F0900_P1_NOSDATAT_NORMED0 0xf48100ff
-#define NOSDATAT_NORMED0 FLDx(F0900_P1_NOSDATAT_NORMED0)
-
-/*P1_NNOSDATA1*/
-#define R0900_P1_NNOSDATA1 0xf482
-#define NNOSDATA1 REGx(R0900_P1_NNOSDATA1)
-#define F0900_P1_NOSDATA_NORMED1 0xf48200ff
-
-/*P1_NNOSDATA0*/
-#define R0900_P1_NNOSDATA0 0xf483
-#define NNOSDATA0 REGx(R0900_P1_NNOSDATA0)
-#define F0900_P1_NOSDATA_NORMED0 0xf48300ff
-
-/*P1_NNOSPLHT1*/
-#define R0900_P1_NNOSPLHT1 0xf484
-#define NNOSPLHT1 REGx(R0900_P1_NNOSPLHT1)
-#define F0900_P1_NOSPLHT_NORMED1 0xf48400ff
-#define NOSPLHT_NORMED1 FLDx(F0900_P1_NOSPLHT_NORMED1)
-
-/*P1_NNOSPLHT0*/
-#define R0900_P1_NNOSPLHT0 0xf485
-#define NNOSPLHT0 REGx(R0900_P1_NNOSPLHT0)
-#define F0900_P1_NOSPLHT_NORMED0 0xf48500ff
-#define NOSPLHT_NORMED0 FLDx(F0900_P1_NOSPLHT_NORMED0)
-
-/*P1_NNOSPLH1*/
-#define R0900_P1_NNOSPLH1 0xf486
-#define NNOSPLH1 REGx(R0900_P1_NNOSPLH1)
-#define F0900_P1_NOSPLH_NORMED1 0xf48600ff
-
-/*P1_NNOSPLH0*/
-#define R0900_P1_NNOSPLH0 0xf487
-#define NNOSPLH0 REGx(R0900_P1_NNOSPLH0)
-#define F0900_P1_NOSPLH_NORMED0 0xf48700ff
-
-/*P1_NOSDATAT1*/
-#define R0900_P1_NOSDATAT1 0xf488
-#define NOSDATAT1 REGx(R0900_P1_NOSDATAT1)
-#define F0900_P1_NOSDATAT_UNNORMED1 0xf48800ff
-
-/*P1_NOSDATAT0*/
-#define R0900_P1_NOSDATAT0 0xf489
-#define NOSDATAT0 REGx(R0900_P1_NOSDATAT0)
-#define F0900_P1_NOSDATAT_UNNORMED0 0xf48900ff
-
-/*P1_NOSDATA1*/
-#define R0900_P1_NOSDATA1 0xf48a
-#define NOSDATA1 REGx(R0900_P1_NOSDATA1)
-#define F0900_P1_NOSDATA_UNNORMED1 0xf48a00ff
-
-/*P1_NOSDATA0*/
-#define R0900_P1_NOSDATA0 0xf48b
-#define NOSDATA0 REGx(R0900_P1_NOSDATA0)
-#define F0900_P1_NOSDATA_UNNORMED0 0xf48b00ff
-
-/*P1_NOSPLHT1*/
-#define R0900_P1_NOSPLHT1 0xf48c
-#define NOSPLHT1 REGx(R0900_P1_NOSPLHT1)
-#define F0900_P1_NOSPLHT_UNNORMED1 0xf48c00ff
-
-/*P1_NOSPLHT0*/
-#define R0900_P1_NOSPLHT0 0xf48d
-#define NOSPLHT0 REGx(R0900_P1_NOSPLHT0)
-#define F0900_P1_NOSPLHT_UNNORMED0 0xf48d00ff
-
-/*P1_NOSPLH1*/
-#define R0900_P1_NOSPLH1 0xf48e
-#define NOSPLH1 REGx(R0900_P1_NOSPLH1)
-#define F0900_P1_NOSPLH_UNNORMED1 0xf48e00ff
-
-/*P1_NOSPLH0*/
-#define R0900_P1_NOSPLH0 0xf48f
-#define NOSPLH0 REGx(R0900_P1_NOSPLH0)
-#define F0900_P1_NOSPLH_UNNORMED0 0xf48f00ff
-
-/*P1_CAR2CFG*/
-#define R0900_P1_CAR2CFG 0xf490
-#define CAR2CFG REGx(R0900_P1_CAR2CFG)
-#define F0900_P1_CARRIER3_DISABLE 0xf4900040
-#define F0900_P1_ROTA2ON 0xf4900004
-#define F0900_P1_PH_DET_ALGO2 0xf4900003
-
-/*P1_CFR2CFR1*/
-#define R0900_P1_CFR2CFR1 0xf491
-#define CFR2CFR1 REGx(R0900_P1_CFR2CFR1)
-#define F0900_P1_CFR2TOCFR1_DVBS1 0xf49100c0
-#define F0900_P1_EN_S2CAR2CENTER 0xf4910020
-#define F0900_P1_DIS_BCHERRCFR2 0xf4910010
-#define F0900_P1_CFR2TOCFR1_BETA 0xf4910007
-
-/*P1_CFR22*/
-#define R0900_P1_CFR22 0xf493
-#define CFR22 REGx(R0900_P1_CFR22)
-#define F0900_P1_CAR2_FREQ2 0xf49301ff
-
-/*P1_CFR21*/
-#define R0900_P1_CFR21 0xf494
-#define CFR21 REGx(R0900_P1_CFR21)
-#define F0900_P1_CAR2_FREQ1 0xf49400ff
-
-/*P1_CFR20*/
-#define R0900_P1_CFR20 0xf495
-#define CFR20 REGx(R0900_P1_CFR20)
-#define F0900_P1_CAR2_FREQ0 0xf49500ff
-
-/*P1_ACLC2S2Q*/
-#define R0900_P1_ACLC2S2Q 0xf497
-#define ACLC2S2Q REGx(R0900_P1_ACLC2S2Q)
-#define F0900_P1_ENAB_SPSKSYMB 0xf4970080
-#define F0900_P1_CAR2S2_Q_ALPH_M 0xf4970030
-#define F0900_P1_CAR2S2_Q_ALPH_E 0xf497000f
-
-/*P1_ACLC2S28*/
-#define R0900_P1_ACLC2S28 0xf498
-#define ACLC2S28 REGx(R0900_P1_ACLC2S28)
-#define F0900_P1_OLDI3Q_MODE 0xf4980080
-#define F0900_P1_CAR2S2_8_ALPH_M 0xf4980030
-#define F0900_P1_CAR2S2_8_ALPH_E 0xf498000f
-
-/*P1_ACLC2S216A*/
-#define R0900_P1_ACLC2S216A 0xf499
-#define ACLC2S216A REGx(R0900_P1_ACLC2S216A)
-#define F0900_P1_DIS_C3STOPA2 0xf4990080
-#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 ACLC2S232A REGx(R0900_P1_ACLC2S232A)
-#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 BCLC2S2Q REGx(R0900_P1_BCLC2S2Q)
-#define F0900_P1_CAR2S2_Q_BETA_M 0xf49c0030
-#define F0900_P1_CAR2S2_Q_BETA_E 0xf49c000f
-
-/*P1_BCLC2S28*/
-#define R0900_P1_BCLC2S28 0xf49d
-#define BCLC2S28 REGx(R0900_P1_BCLC2S28)
-#define F0900_P1_CAR2S2_8_BETA_M 0xf49d0030
-#define F0900_P1_CAR2S2_8_BETA_E 0xf49d000f
-
-/*P1_BCLC2S216A*/
-#define R0900_P1_BCLC2S216A 0xf49e
-#define BCLC2S216A REGx(R0900_P1_BCLC2S216A)
-
-/*P1_BCLC2S232A*/
-#define R0900_P1_BCLC2S232A 0xf49f
-#define BCLC2S232A REGx(R0900_P1_BCLC2S232A)
-
-/*P1_PLROOT2*/
-#define R0900_P1_PLROOT2 0xf4ac
-#define PLROOT2 REGx(R0900_P1_PLROOT2)
-#define F0900_P1_PLSCRAMB_MODE 0xf4ac000c
-#define F0900_P1_PLSCRAMB_ROOT2 0xf4ac0003
-
-/*P1_PLROOT1*/
-#define R0900_P1_PLROOT1 0xf4ad
-#define PLROOT1 REGx(R0900_P1_PLROOT1)
-#define F0900_P1_PLSCRAMB_ROOT1 0xf4ad00ff
-
-/*P1_PLROOT0*/
-#define R0900_P1_PLROOT0 0xf4ae
-#define PLROOT0 REGx(R0900_P1_PLROOT0)
-#define F0900_P1_PLSCRAMB_ROOT0 0xf4ae00ff
-
-/*P1_MODCODLST0*/
-#define R0900_P1_MODCODLST0 0xf4b0
-#define MODCODLST0 REGx(R0900_P1_MODCODLST0)
-
-/*P1_MODCODLST1*/
-#define R0900_P1_MODCODLST1 0xf4b1
-#define MODCODLST1 REGx(R0900_P1_MODCODLST1)
-#define F0900_P1_DIS_MODCOD29 0xf4b100f0
-#define F0900_P1_DIS_32PSK_9_10 0xf4b1000f
-
-/*P1_MODCODLST2*/
-#define R0900_P1_MODCODLST2 0xf4b2
-#define MODCODLST2 REGx(R0900_P1_MODCODLST2)
-#define F0900_P1_DIS_32PSK_8_9 0xf4b200f0
-#define F0900_P1_DIS_32PSK_5_6 0xf4b2000f
-
-/*P1_MODCODLST3*/
-#define R0900_P1_MODCODLST3 0xf4b3
-#define MODCODLST3 REGx(R0900_P1_MODCODLST3)
-#define F0900_P1_DIS_32PSK_4_5 0xf4b300f0
-#define F0900_P1_DIS_32PSK_3_4 0xf4b3000f
-
-/*P1_MODCODLST4*/
-#define R0900_P1_MODCODLST4 0xf4b4
-#define MODCODLST4 REGx(R0900_P1_MODCODLST4)
-#define F0900_P1_DIS_16PSK_9_10 0xf4b400f0
-#define F0900_P1_DIS_16PSK_8_9 0xf4b4000f
-
-/*P1_MODCODLST5*/
-#define R0900_P1_MODCODLST5 0xf4b5
-#define MODCODLST5 REGx(R0900_P1_MODCODLST5)
-#define F0900_P1_DIS_16PSK_5_6 0xf4b500f0
-#define F0900_P1_DIS_16PSK_4_5 0xf4b5000f
-
-/*P1_MODCODLST6*/
-#define R0900_P1_MODCODLST6 0xf4b6
-#define MODCODLST6 REGx(R0900_P1_MODCODLST6)
-#define F0900_P1_DIS_16PSK_3_4 0xf4b600f0
-#define F0900_P1_DIS_16PSK_2_3 0xf4b6000f
-
-/*P1_MODCODLST7*/
-#define R0900_P1_MODCODLST7 0xf4b7
-#define MODCODLST7 REGx(R0900_P1_MODCODLST7)
-#define F0900_P1_DIS_8P_9_10 0xf4b700f0
-#define F0900_P1_DIS_8P_8_9 0xf4b7000f
-
-/*P1_MODCODLST8*/
-#define R0900_P1_MODCODLST8 0xf4b8
-#define MODCODLST8 REGx(R0900_P1_MODCODLST8)
-#define F0900_P1_DIS_8P_5_6 0xf4b800f0
-#define F0900_P1_DIS_8P_3_4 0xf4b8000f
-
-/*P1_MODCODLST9*/
-#define R0900_P1_MODCODLST9 0xf4b9
-#define MODCODLST9 REGx(R0900_P1_MODCODLST9)
-#define F0900_P1_DIS_8P_2_3 0xf4b900f0
-#define F0900_P1_DIS_8P_3_5 0xf4b9000f
-
-/*P1_MODCODLSTA*/
-#define R0900_P1_MODCODLSTA 0xf4ba
-#define MODCODLSTA REGx(R0900_P1_MODCODLSTA)
-#define F0900_P1_DIS_QP_9_10 0xf4ba00f0
-#define F0900_P1_DIS_QP_8_9 0xf4ba000f
-
-/*P1_MODCODLSTB*/
-#define R0900_P1_MODCODLSTB 0xf4bb
-#define MODCODLSTB REGx(R0900_P1_MODCODLSTB)
-#define F0900_P1_DIS_QP_5_6 0xf4bb00f0
-#define F0900_P1_DIS_QP_4_5 0xf4bb000f
-
-/*P1_MODCODLSTC*/
-#define R0900_P1_MODCODLSTC 0xf4bc
-#define MODCODLSTC REGx(R0900_P1_MODCODLSTC)
-#define F0900_P1_DIS_QP_3_4 0xf4bc00f0
-#define F0900_P1_DIS_QP_2_3 0xf4bc000f
-
-/*P1_MODCODLSTD*/
-#define R0900_P1_MODCODLSTD 0xf4bd
-#define MODCODLSTD REGx(R0900_P1_MODCODLSTD)
-#define F0900_P1_DIS_QP_3_5 0xf4bd00f0
-#define F0900_P1_DIS_QP_1_2 0xf4bd000f
-
-/*P1_MODCODLSTE*/
-#define R0900_P1_MODCODLSTE 0xf4be
-#define MODCODLSTE REGx(R0900_P1_MODCODLSTE)
-#define F0900_P1_DIS_QP_2_5 0xf4be00f0
-#define F0900_P1_DIS_QP_1_3 0xf4be000f
-
-/*P1_MODCODLSTF*/
-#define R0900_P1_MODCODLSTF 0xf4bf
-#define MODCODLSTF REGx(R0900_P1_MODCODLSTF)
-#define F0900_P1_DIS_QP_1_4 0xf4bf00f0
-
-/*P1_GAUSSR0*/
-#define R0900_P1_GAUSSR0 0xf4c0
-#define GAUSSR0 REGx(R0900_P1_GAUSSR0)
-#define F0900_P1_EN_CCIMODE 0xf4c00080
-#define F0900_P1_R0_GAUSSIEN 0xf4c0007f
-
-/*P1_CCIR0*/
-#define R0900_P1_CCIR0 0xf4c1
-#define CCIR0 REGx(R0900_P1_CCIR0)
-#define F0900_P1_CCIDETECT_PLHONLY 0xf4c10080
-#define F0900_P1_R0_CCI 0xf4c1007f
-
-/*P1_CCIQUANT*/
-#define R0900_P1_CCIQUANT 0xf4c2
-#define CCIQUANT REGx(R0900_P1_CCIQUANT)
-#define F0900_P1_CCI_BETA 0xf4c200e0
-#define F0900_P1_CCI_QUANT 0xf4c2001f
-
-/*P1_CCITHRES*/
-#define R0900_P1_CCITHRES 0xf4c3
-#define CCITHRES REGx(R0900_P1_CCITHRES)
-#define F0900_P1_CCI_THRESHOLD 0xf4c300ff
-
-/*P1_CCIACC*/
-#define R0900_P1_CCIACC 0xf4c4
-#define CCIACC REGx(R0900_P1_CCIACC)
-#define F0900_P1_CCI_VALUE 0xf4c400ff
-
-/*P1_DMDRESCFG*/
-#define R0900_P1_DMDRESCFG 0xf4c6
-#define DMDRESCFG REGx(R0900_P1_DMDRESCFG)
-#define F0900_P1_DMDRES_RESET 0xf4c60080
-#define F0900_P1_DMDRES_STRALL 0xf4c60008
-#define F0900_P1_DMDRES_NEWONLY 0xf4c60004
-#define F0900_P1_DMDRES_NOSTORE 0xf4c60002
-
-/*P1_DMDRESADR*/
-#define R0900_P1_DMDRESADR 0xf4c7
-#define DMDRESADR REGx(R0900_P1_DMDRESADR)
-#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 FFEI1 REGx(R0900_P1_FFEI1)
-#define F0900_P1_FFE_ACCI1 0xf4d001ff
-
-/*P1_FFEQ1*/
-#define R0900_P1_FFEQ1 0xf4d1
-#define FFEQ1 REGx(R0900_P1_FFEQ1)
-#define F0900_P1_FFE_ACCQ1 0xf4d101ff
-
-/*P1_FFEI2*/
-#define R0900_P1_FFEI2 0xf4d2
-#define FFEI2 REGx(R0900_P1_FFEI2)
-#define F0900_P1_FFE_ACCI2 0xf4d201ff
-
-/*P1_FFEQ2*/
-#define R0900_P1_FFEQ2 0xf4d3
-#define FFEQ2 REGx(R0900_P1_FFEQ2)
-#define F0900_P1_FFE_ACCQ2 0xf4d301ff
-
-/*P1_FFEI3*/
-#define R0900_P1_FFEI3 0xf4d4
-#define FFEI3 REGx(R0900_P1_FFEI3)
-#define F0900_P1_FFE_ACCI3 0xf4d401ff
-
-/*P1_FFEQ3*/
-#define R0900_P1_FFEQ3 0xf4d5
-#define FFEQ3 REGx(R0900_P1_FFEQ3)
-#define F0900_P1_FFE_ACCQ3 0xf4d501ff
-
-/*P1_FFEI4*/
-#define R0900_P1_FFEI4 0xf4d6
-#define FFEI4 REGx(R0900_P1_FFEI4)
-#define F0900_P1_FFE_ACCI4 0xf4d601ff
-
-/*P1_FFEQ4*/
-#define R0900_P1_FFEQ4 0xf4d7
-#define FFEQ4 REGx(R0900_P1_FFEQ4)
-#define F0900_P1_FFE_ACCQ4 0xf4d701ff
-
-/*P1_FFECFG*/
-#define R0900_P1_FFECFG 0xf4d8
-#define FFECFG REGx(R0900_P1_FFECFG)
-#define F0900_P1_EQUALFFE_ON 0xf4d80040
-#define F0900_P1_MU_EQUALFFE 0xf4d80007
-
-/*P1_TNRCFG*/
-#define R0900_P1_TNRCFG 0xf4e0
-#define TNRCFG REGx(R0900_P1_TNRCFG)
-#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 TNRCFG2 REGx(R0900_P1_TNRCFG2)
-#define F0900_P1_TUN_IQSWAP 0xf4e10080
-#define F0900_P1_DIS_BWCALC 0xf4e10004
-#define F0900_P1_SHORT_WAITSTATES 0xf4e10002
-
-/*P1_TNRXTAL*/
-#define R0900_P1_TNRXTAL 0xf4e4
-#define TNRXTAL REGx(R0900_P1_TNRXTAL)
-#define F0900_P1_TUN_XTALFREQ 0xf4e4001f
-
-/*P1_TNRSTEPS*/
-#define R0900_P1_TNRSTEPS 0xf4e7
-#define TNRSTEPS REGx(R0900_P1_TNRSTEPS)
-#define F0900_P1_TUNER_BW0P125 0xf4e70080
-#define F0900_P1_BWINC_OFFSET 0xf4e70170
-#define F0900_P1_SOFTSTEP_RNG 0xf4e70008
-#define F0900_P1_TUN_BWOFFSET 0xf4e70007
-
-/*P1_TNRGAIN*/
-#define R0900_P1_TNRGAIN 0xf4e8
-#define TNRGAIN REGx(R0900_P1_TNRGAIN)
-#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 TNRRF1 REGx(R0900_P1_TNRRF1)
-#define F0900_P1_TUN_RFFREQ2 0xf4e900ff
-#define TUN_RFFREQ2 FLDx(F0900_P1_TUN_RFFREQ2)
-
-/*P1_TNRRF0*/
-#define R0900_P1_TNRRF0 0xf4ea
-#define TNRRF0 REGx(R0900_P1_TNRRF0)
-#define F0900_P1_TUN_RFFREQ1 0xf4ea00ff
-#define TUN_RFFREQ1 FLDx(F0900_P1_TUN_RFFREQ1)
-
-/*P1_TNRBW*/
-#define R0900_P1_TNRBW 0xf4eb
-#define TNRBW REGx(R0900_P1_TNRBW)
-#define F0900_P1_TUN_RFFREQ0 0xf4eb00c0
-#define TUN_RFFREQ0 FLDx(F0900_P1_TUN_RFFREQ0)
-#define F0900_P1_TUN_BW 0xf4eb003f
-#define TUN_BW FLDx(F0900_P1_TUN_BW)
-
-/*P1_TNRADJ*/
-#define R0900_P1_TNRADJ 0xf4ec
-#define TNRADJ REGx(R0900_P1_TNRADJ)
-#define F0900_P1_STB61X0_CALTIME 0xf4ec0040
-
-/*P1_TNRCTL2*/
-#define R0900_P1_TNRCTL2 0xf4ed
-#define TNRCTL2 REGx(R0900_P1_TNRCTL2)
-#define F0900_P1_STB61X0_RCCKOFF 0xf4ed0080
-#define F0900_P1_STB61X0_ICP_SDOFF 0xf4ed0040
-#define F0900_P1_STB61X0_DCLOOPOFF 0xf4ed0020
-#define F0900_P1_STB61X0_REFOUTSEL 0xf4ed0010
-#define F0900_P1_STB61X0_CALOFF 0xf4ed0008
-#define F0900_P1_STB6XX0_LPT_BEN 0xf4ed0004
-#define F0900_P1_STB6XX0_RX_OSCP 0xf4ed0002
-#define F0900_P1_STB6XX0_SYN 0xf4ed0001
-
-/*P1_TNRCFG3*/
-#define R0900_P1_TNRCFG3 0xf4ee
-#define TNRCFG3 REGx(R0900_P1_TNRCFG3)
-#define F0900_P1_TUN_PLLFREQ 0xf4ee001c
-#define F0900_P1_TUN_I2CFREQ_MODE 0xf4ee0003
-
-/*P1_TNRLAUNCH*/
-#define R0900_P1_TNRLAUNCH 0xf4f0
-#define TNRLAUNCH REGx(R0900_P1_TNRLAUNCH)
-
-/*P1_TNRLD*/
-#define R0900_P1_TNRLD 0xf4f0
-#define TNRLD REGx(R0900_P1_TNRLD)
-#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 TNROBSL REGx(R0900_P1_TNROBSL)
-#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
-#define TUN_RFRESTE1 FLDx(F0900_P1_TUN_RFRESTE1)
-
-/*P1_TNRRESTE*/
-#define R0900_P1_TNRRESTE 0xf4f7
-#define TNRRESTE REGx(R0900_P1_TNRRESTE)
-#define F0900_P1_TUN_RFRESTE0 0xf4f700ff
-#define TUN_RFRESTE0 FLDx(F0900_P1_TUN_RFRESTE0)
-
-/*P1_SMAPCOEF7*/
-#define R0900_P1_SMAPCOEF7 0xf500
-#define SMAPCOEF7 REGx(R0900_P1_SMAPCOEF7)
-#define F0900_P1_DIS_QSCALE 0xf5000080
-#define F0900_P1_SMAPCOEF_Q_LLR12 0xf500017f
-
-/*P1_SMAPCOEF6*/
-#define R0900_P1_SMAPCOEF6 0xf501
-#define SMAPCOEF6 REGx(R0900_P1_SMAPCOEF6)
-#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 SMAPCOEF5 REGx(R0900_P1_SMAPCOEF5)
-#define F0900_P1_DIS_8SCALE 0xf5020080
-#define F0900_P1_SMAPCOEF_8P_LLR23 0xf502017f
-
-/*P1_NCO2MAX1*/
-#define R0900_P1_NCO2MAX1 0xf514
-#define NCO2MAX1 REGx(R0900_P1_NCO2MAX1)
-#define F0900_P1_TETA2_MAXVABS1 0xf51400ff
-
-/*P1_NCO2MAX0*/
-#define R0900_P1_NCO2MAX0 0xf515
-#define NCO2MAX0 REGx(R0900_P1_NCO2MAX0)
-#define F0900_P1_TETA2_MAXVABS0 0xf51500ff
-
-/*P1_NCO2FR1*/
-#define R0900_P1_NCO2FR1 0xf516
-#define NCO2FR1 REGx(R0900_P1_NCO2FR1)
-#define F0900_P1_NCO2FINAL_ANGLE1 0xf51600ff
-
-/*P1_NCO2FR0*/
-#define R0900_P1_NCO2FR0 0xf517
-#define NCO2FR0 REGx(R0900_P1_NCO2FR0)
-#define F0900_P1_NCO2FINAL_ANGLE0 0xf51700ff
-
-/*P1_CFR2AVRGE1*/
-#define R0900_P1_CFR2AVRGE1 0xf518
-#define CFR2AVRGE1 REGx(R0900_P1_CFR2AVRGE1)
-#define F0900_P1_I2C_CFR2AVERAGE1 0xf51800ff
-
-/*P1_CFR2AVRGE0*/
-#define R0900_P1_CFR2AVRGE0 0xf519
-#define CFR2AVRGE0 REGx(R0900_P1_CFR2AVRGE0)
-#define F0900_P1_I2C_CFR2AVERAGE0 0xf51900ff
-
-/*P1_DMDPLHSTAT*/
-#define R0900_P1_DMDPLHSTAT 0xf520
-#define DMDPLHSTAT REGx(R0900_P1_DMDPLHSTAT)
-#define F0900_P1_PLH_STATISTIC 0xf52000ff
-
-/*P1_LOCKTIME3*/
-#define R0900_P1_LOCKTIME3 0xf522
-#define LOCKTIME3 REGx(R0900_P1_LOCKTIME3)
-#define F0900_P1_DEMOD_LOCKTIME3 0xf52200ff
-
-/*P1_LOCKTIME2*/
-#define R0900_P1_LOCKTIME2 0xf523
-#define LOCKTIME2 REGx(R0900_P1_LOCKTIME2)
-#define F0900_P1_DEMOD_LOCKTIME2 0xf52300ff
-
-/*P1_LOCKTIME1*/
-#define R0900_P1_LOCKTIME1 0xf524
-#define LOCKTIME1 REGx(R0900_P1_LOCKTIME1)
-#define F0900_P1_DEMOD_LOCKTIME1 0xf52400ff
-
-/*P1_LOCKTIME0*/
-#define R0900_P1_LOCKTIME0 0xf525
-#define LOCKTIME0 REGx(R0900_P1_LOCKTIME0)
-#define F0900_P1_DEMOD_LOCKTIME0 0xf52500ff
-
-/*P1_VITSCALE*/
-#define R0900_P1_VITSCALE 0xf532
-#define VITSCALE REGx(R0900_P1_VITSCALE)
-#define F0900_P1_NVTH_NOSRANGE 0xf5320080
-#define F0900_P1_VERROR_MAXMODE 0xf5320040
-#define F0900_P1_NSLOWSN_LOCKED 0xf5320008
-#define F0900_P1_DIS_RSFLOCK 0xf5320002
-
-/*P1_FECM*/
-#define R0900_P1_FECM 0xf533
-#define FECM REGx(R0900_P1_FECM)
-#define F0900_P1_DSS_DVB 0xf5330080
-#define DSS_DVB FLDx(F0900_P1_DSS_DVB)
-#define F0900_P1_DSS_SRCH 0xf5330010
-#define F0900_P1_SYNCVIT 0xf5330002
-#define F0900_P1_IQINV 0xf5330001
-#define IQINV FLDx(F0900_P1_IQINV)
-
-/*P1_VTH12*/
-#define R0900_P1_VTH12 0xf534
-#define VTH12 REGx(R0900_P1_VTH12)
-#define F0900_P1_VTH12 0xf53400ff
-
-/*P1_VTH23*/
-#define R0900_P1_VTH23 0xf535
-#define VTH23 REGx(R0900_P1_VTH23)
-#define F0900_P1_VTH23 0xf53500ff
-
-/*P1_VTH34*/
-#define R0900_P1_VTH34 0xf536
-#define VTH34 REGx(R0900_P1_VTH34)
-#define F0900_P1_VTH34 0xf53600ff
-
-/*P1_VTH56*/
-#define R0900_P1_VTH56 0xf537
-#define VTH56 REGx(R0900_P1_VTH56)
-#define F0900_P1_VTH56 0xf53700ff
-
-/*P1_VTH67*/
-#define R0900_P1_VTH67 0xf538
-#define VTH67 REGx(R0900_P1_VTH67)
-#define F0900_P1_VTH67 0xf53800ff
-
-/*P1_VTH78*/
-#define R0900_P1_VTH78 0xf539
-#define VTH78 REGx(R0900_P1_VTH78)
-#define F0900_P1_VTH78 0xf53900ff
-
-/*P1_VITCURPUN*/
-#define R0900_P1_VITCURPUN 0xf53a
-#define VITCURPUN REGx(R0900_P1_VITCURPUN)
-#define F0900_P1_VIT_CURPUN 0xf53a001f
-#define VIT_CURPUN FLDx(F0900_P1_VIT_CURPUN)
-
-/*P1_VERROR*/
-#define R0900_P1_VERROR 0xf53b
-#define VERROR REGx(R0900_P1_VERROR)
-#define F0900_P1_REGERR_VIT 0xf53b00ff
-
-/*P1_PRVIT*/
-#define R0900_P1_PRVIT 0xf53c
-#define PRVIT REGx(R0900_P1_PRVIT)
-#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 VAVSRVIT REGx(R0900_P1_VAVSRVIT)
-#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 VSTATUSVIT REGx(R0900_P1_VSTATUSVIT)
-#define F0900_P1_PRFVIT 0xf53e0010
-#define PRFVIT FLDx(F0900_P1_PRFVIT)
-#define F0900_P1_LOCKEDVIT 0xf53e0008
-#define LOCKEDVIT FLDx(F0900_P1_LOCKEDVIT)
-
-/*P1_VTHINUSE*/
-#define R0900_P1_VTHINUSE 0xf53f
-#define VTHINUSE REGx(R0900_P1_VTHINUSE)
-#define F0900_P1_VIT_INUSE 0xf53f00ff
-
-/*P1_KDIV12*/
-#define R0900_P1_KDIV12 0xf540
-#define KDIV12 REGx(R0900_P1_KDIV12)
-#define F0900_P1_K_DIVIDER_12 0xf540007f
-
-/*P1_KDIV23*/
-#define R0900_P1_KDIV23 0xf541
-#define KDIV23 REGx(R0900_P1_KDIV23)
-#define F0900_P1_K_DIVIDER_23 0xf541007f
-
-/*P1_KDIV34*/
-#define R0900_P1_KDIV34 0xf542
-#define KDIV34 REGx(R0900_P1_KDIV34)
-#define F0900_P1_K_DIVIDER_34 0xf542007f
-
-/*P1_KDIV56*/
-#define R0900_P1_KDIV56 0xf543
-#define KDIV56 REGx(R0900_P1_KDIV56)
-#define F0900_P1_K_DIVIDER_56 0xf543007f
-
-/*P1_KDIV67*/
-#define R0900_P1_KDIV67 0xf544
-#define KDIV67 REGx(R0900_P1_KDIV67)
-#define F0900_P1_K_DIVIDER_67 0xf544007f
-
-/*P1_KDIV78*/
-#define R0900_P1_KDIV78 0xf545
-#define KDIV78 REGx(R0900_P1_KDIV78)
-#define F0900_P1_K_DIVIDER_78 0xf545007f
-
-/*P1_PDELCTRL1*/
-#define R0900_P1_PDELCTRL1 0xf550
-#define PDELCTRL1 REGx(R0900_P1_PDELCTRL1)
-#define F0900_P1_INV_MISMASK 0xf5500080
-#define F0900_P1_FILTER_EN 0xf5500020
-#define F0900_P1_EN_MIS00 0xf5500002
-#define F0900_P1_ALGOSWRST 0xf5500001
-#define ALGOSWRST FLDx(F0900_P1_ALGOSWRST)
-
-/*P1_PDELCTRL2*/
-#define R0900_P1_PDELCTRL2 0xf551
-#define PDELCTRL2 REGx(R0900_P1_PDELCTRL2)
-#define F0900_P1_RESET_UPKO_COUNT 0xf5510040
-#define RESET_UPKO_COUNT FLDx(F0900_P1_RESET_UPKO_COUNT)
-#define F0900_P1_FRAME_MODE 0xf5510002
-#define F0900_P1_NOBCHERRFLG_USE 0xf5510001
-
-/*P1_HYSTTHRESH*/
-#define R0900_P1_HYSTTHRESH 0xf554
-#define HYSTTHRESH REGx(R0900_P1_HYSTTHRESH)
-#define F0900_P1_UNLCK_THRESH 0xf55400f0
-#define F0900_P1_DELIN_LCK_THRESH 0xf554000f
-
-/*P1_ISIENTRY*/
-#define R0900_P1_ISIENTRY 0xf55e
-#define ISIENTRY REGx(R0900_P1_ISIENTRY)
-#define F0900_P1_ISI_ENTRY 0xf55e00ff
-
-/*P1_ISIBITENA*/
-#define R0900_P1_ISIBITENA 0xf55f
-#define ISIBITENA REGx(R0900_P1_ISIBITENA)
-#define F0900_P1_ISI_BIT_EN 0xf55f00ff
-
-/*P1_MATSTR1*/
-#define R0900_P1_MATSTR1 0xf560
-#define MATSTR1 REGx(R0900_P1_MATSTR1)
-#define F0900_P1_MATYPE_CURRENT1 0xf56000ff
-
-/*P1_MATSTR0*/
-#define R0900_P1_MATSTR0 0xf561
-#define MATSTR0 REGx(R0900_P1_MATSTR0)
-#define F0900_P1_MATYPE_CURRENT0 0xf56100ff
-
-/*P1_UPLSTR1*/
-#define R0900_P1_UPLSTR1 0xf562
-#define UPLSTR1 REGx(R0900_P1_UPLSTR1)
-#define F0900_P1_UPL_CURRENT1 0xf56200ff
-
-/*P1_UPLSTR0*/
-#define R0900_P1_UPLSTR0 0xf563
-#define UPLSTR0 REGx(R0900_P1_UPLSTR0)
-#define F0900_P1_UPL_CURRENT0 0xf56300ff
-
-/*P1_DFLSTR1*/
-#define R0900_P1_DFLSTR1 0xf564
-#define DFLSTR1 REGx(R0900_P1_DFLSTR1)
-#define F0900_P1_DFL_CURRENT1 0xf56400ff
-
-/*P1_DFLSTR0*/
-#define R0900_P1_DFLSTR0 0xf565
-#define DFLSTR0 REGx(R0900_P1_DFLSTR0)
-#define F0900_P1_DFL_CURRENT0 0xf56500ff
-
-/*P1_SYNCSTR*/
-#define R0900_P1_SYNCSTR 0xf566
-#define SYNCSTR REGx(R0900_P1_SYNCSTR)
-#define F0900_P1_SYNC_CURRENT 0xf56600ff
-
-/*P1_SYNCDSTR1*/
-#define R0900_P1_SYNCDSTR1 0xf567
-#define SYNCDSTR1 REGx(R0900_P1_SYNCDSTR1)
-#define F0900_P1_SYNCD_CURRENT1 0xf56700ff
-
-/*P1_SYNCDSTR0*/
-#define R0900_P1_SYNCDSTR0 0xf568
-#define SYNCDSTR0 REGx(R0900_P1_SYNCDSTR0)
-#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_PKTDELIN_LOCK 0xf5690002
-#define PKTDELIN_LOCK FLDx(F0900_P1_PKTDELIN_LOCK)
-#define F0900_P1_FIRST_LOCK 0xf5690001
-
-/*P1_PDELSTATUS2*/
-#define R0900_P1_PDELSTATUS2 0xf56a
-#define F0900_P1_FRAME_MODCOD 0xf56a007c
-#define F0900_P1_FRAME_TYPE 0xf56a0003
-
-/*P1_BBFCRCKO1*/
-#define R0900_P1_BBFCRCKO1 0xf56b
-#define BBFCRCKO1 REGx(R0900_P1_BBFCRCKO1)
-#define F0900_P1_BBHCRC_KOCNT1 0xf56b00ff
-
-/*P1_BBFCRCKO0*/
-#define R0900_P1_BBFCRCKO0 0xf56c
-#define BBFCRCKO0 REGx(R0900_P1_BBFCRCKO0)
-#define F0900_P1_BBHCRC_KOCNT0 0xf56c00ff
-
-/*P1_UPCRCKO1*/
-#define R0900_P1_UPCRCKO1 0xf56d
-#define UPCRCKO1 REGx(R0900_P1_UPCRCKO1)
-#define F0900_P1_PKTCRC_KOCNT1 0xf56d00ff
-
-/*P1_UPCRCKO0*/
-#define R0900_P1_UPCRCKO0 0xf56e
-#define UPCRCKO0 REGx(R0900_P1_UPCRCKO0)
-#define F0900_P1_PKTCRC_KOCNT0 0xf56e00ff
-
-/*P1_PDELCTRL3*/
-#define R0900_P1_PDELCTRL3 0xf56f
-#define PDELCTRL3 REGx(R0900_P1_PDELCTRL3)
-#define F0900_P1_PKTDEL_CONTFAIL 0xf56f0080
-#define F0900_P1_NOFIFO_BCHERR 0xf56f0020
-
-/*P1_TSSTATEM*/
-#define R0900_P1_TSSTATEM 0xf570
-#define TSSTATEM REGx(R0900_P1_TSSTATEM)
-#define F0900_P1_TSDIL_ON 0xf5700080
-#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_TSOUT_NOSYNC 0xf5700001
-
-/*P1_TSCFGH*/
-#define R0900_P1_TSCFGH 0xf572
-#define TSCFGH REGx(R0900_P1_TSCFGH)
-#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
-#define RST_HWARE FLDx(F0900_P1_RST_HWARE)
-
-/*P1_TSCFGM*/
-#define R0900_P1_TSCFGM 0xf573
-#define TSCFGM REGx(R0900_P1_TSCFGM)
-#define F0900_P1_TSFIFO_MANSPEED 0xf57300c0
-#define F0900_P1_TSFIFO_PERMDATA 0xf5730020
-#define F0900_P1_TSFIFO_DPUNACT 0xf5730002
-#define F0900_P1_TSFIFO_INVDATA 0xf5730001
-
-/*P1_TSCFGL*/
-#define R0900_P1_TSCFGL 0xf574
-#define TSCFGL REGx(R0900_P1_TSCFGL)
-#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_BITSPEED 0xf5740003
-
-/*P1_TSINSDELH*/
-#define R0900_P1_TSINSDELH 0xf576
-#define TSINSDELH REGx(R0900_P1_TSINSDELH)
-#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_TSDIVN*/
-#define R0900_P1_TSDIVN 0xf579
-#define TSDIVN REGx(R0900_P1_TSDIVN)
-#define F0900_P1_TSFIFO_SPEEDMODE 0xf57900c0
-
-/*P1_TSCFG4*/
-#define R0900_P1_TSCFG4 0xf57a
-#define TSCFG4 REGx(R0900_P1_TSCFG4)
-#define F0900_P1_TSFIFO_TSSPEEDMODE 0xf57a00c0
-
-/*P1_TSSPEED*/
-#define R0900_P1_TSSPEED 0xf580
-#define TSSPEED REGx(R0900_P1_TSSPEED)
-#define F0900_P1_TSFIFO_OUTSPEED 0xf58000ff
-
-/*P1_TSSTATUS*/
-#define R0900_P1_TSSTATUS 0xf581
-#define TSSTATUS REGx(R0900_P1_TSSTATUS)
-#define F0900_P1_TSFIFO_LINEOK 0xf5810080
-#define TSFIFO_LINEOK FLDx(F0900_P1_TSFIFO_LINEOK)
-#define F0900_P1_TSFIFO_ERROR 0xf5810040
-#define F0900_P1_DIL_READY 0xf5810001
-
-/*P1_TSSTATUS2*/
-#define R0900_P1_TSSTATUS2 0xf582
-#define TSSTATUS2 REGx(R0900_P1_TSSTATUS2)
-#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_SCRAMBDETECT 0xf5820002
-
-/*P1_TSBITRATE1*/
-#define R0900_P1_TSBITRATE1 0xf583
-#define TSBITRATE1 REGx(R0900_P1_TSBITRATE1)
-#define F0900_P1_TSFIFO_BITRATE1 0xf58300ff
-
-/*P1_TSBITRATE0*/
-#define R0900_P1_TSBITRATE0 0xf584
-#define TSBITRATE0 REGx(R0900_P1_TSBITRATE0)
-#define F0900_P1_TSFIFO_BITRATE0 0xf58400ff
-
-/*P1_ERRCTRL1*/
-#define R0900_P1_ERRCTRL1 0xf598
-#define ERRCTRL1 REGx(R0900_P1_ERRCTRL1)
-#define F0900_P1_ERR_SOURCE1 0xf59800f0
-#define F0900_P1_NUM_EVENT1 0xf5980007
-
-/*P1_ERRCNT12*/
-#define R0900_P1_ERRCNT12 0xf599
-#define ERRCNT12 REGx(R0900_P1_ERRCNT12)
-#define F0900_P1_ERRCNT1_OLDVALUE 0xf5990080
-#define F0900_P1_ERR_CNT12 0xf599007f
-#define ERR_CNT12 FLDx(F0900_P1_ERR_CNT12)
-
-/*P1_ERRCNT11*/
-#define R0900_P1_ERRCNT11 0xf59a
-#define ERRCNT11 REGx(R0900_P1_ERRCNT11)
-#define F0900_P1_ERR_CNT11 0xf59a00ff
-#define ERR_CNT11 FLDx(F0900_P1_ERR_CNT11)
-
-/*P1_ERRCNT10*/
-#define R0900_P1_ERRCNT10 0xf59b
-#define ERRCNT10 REGx(R0900_P1_ERRCNT10)
-#define F0900_P1_ERR_CNT10 0xf59b00ff
-#define ERR_CNT10 FLDx(F0900_P1_ERR_CNT10)
-
-/*P1_ERRCTRL2*/
-#define R0900_P1_ERRCTRL2 0xf59c
-#define ERRCTRL2 REGx(R0900_P1_ERRCTRL2)
-#define F0900_P1_ERR_SOURCE2 0xf59c00f0
-#define F0900_P1_NUM_EVENT2 0xf59c0007
-
-/*P1_ERRCNT22*/
-#define R0900_P1_ERRCNT22 0xf59d
-#define ERRCNT22 REGx(R0900_P1_ERRCNT22)
-#define F0900_P1_ERRCNT2_OLDVALUE 0xf59d0080
-#define F0900_P1_ERR_CNT22 0xf59d007f
-#define ERR_CNT22 FLDx(F0900_P1_ERR_CNT22)
-
-/*P1_ERRCNT21*/
-#define R0900_P1_ERRCNT21 0xf59e
-#define ERRCNT21 REGx(R0900_P1_ERRCNT21)
-#define F0900_P1_ERR_CNT21 0xf59e00ff
-#define ERR_CNT21 FLDx(F0900_P1_ERR_CNT21)
-
-/*P1_ERRCNT20*/
-#define R0900_P1_ERRCNT20 0xf59f
-#define ERRCNT20 REGx(R0900_P1_ERRCNT20)
-#define F0900_P1_ERR_CNT20 0xf59f00ff
-#define ERR_CNT20 FLDx(F0900_P1_ERR_CNT20)
-
-/*P1_FECSPY*/
-#define R0900_P1_FECSPY 0xf5a0
-#define FECSPY REGx(R0900_P1_FECSPY)
-#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_BERMETER_DATAMODE 0xf5a00008
-#define F0900_P1_BERMETER_LMODE 0xf5a00002
-#define F0900_P1_BERMETER_RESET 0xf5a00001
-
-/*P1_FSPYCFG*/
-#define R0900_P1_FSPYCFG 0xf5a1
-#define FSPYCFG REGx(R0900_P1_FSPYCFG)
-#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 FSPYDATA REGx(R0900_P1_FSPYDATA)
-#define F0900_P1_SPY_STUFFING 0xf5a20080
-#define F0900_P1_SPY_CNULLPKT 0xf5a20020
-#define F0900_P1_SPY_OUTDATA_MODE 0xf5a2001f
-
-/*P1_FSPYOUT*/
-#define R0900_P1_FSPYOUT 0xf5a3
-#define FSPYOUT REGx(R0900_P1_FSPYOUT)
-#define F0900_P1_FSPY_DIRECT 0xf5a30080
-#define F0900_P1_STUFF_MODE 0xf5a30007
-
-/*P1_FSTATUS*/
-#define R0900_P1_FSTATUS 0xf5a4
-#define FSTATUS REGx(R0900_P1_FSTATUS)
-#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 FBERCPT4 REGx(R0900_P1_FBERCPT4)
-#define F0900_P1_FBERMETER_CPT4 0xf5a800ff
-
-/*P1_FBERCPT3*/
-#define R0900_P1_FBERCPT3 0xf5a9
-#define FBERCPT3 REGx(R0900_P1_FBERCPT3)
-#define F0900_P1_FBERMETER_CPT3 0xf5a900ff
-
-/*P1_FBERCPT2*/
-#define R0900_P1_FBERCPT2 0xf5aa
-#define FBERCPT2 REGx(R0900_P1_FBERCPT2)
-#define F0900_P1_FBERMETER_CPT2 0xf5aa00ff
-
-/*P1_FBERCPT1*/
-#define R0900_P1_FBERCPT1 0xf5ab
-#define FBERCPT1 REGx(R0900_P1_FBERCPT1)
-#define F0900_P1_FBERMETER_CPT1 0xf5ab00ff
-
-/*P1_FBERCPT0*/
-#define R0900_P1_FBERCPT0 0xf5ac
-#define FBERCPT0 REGx(R0900_P1_FBERCPT0)
-#define F0900_P1_FBERMETER_CPT0 0xf5ac00ff
-
-/*P1_FBERERR2*/
-#define R0900_P1_FBERERR2 0xf5ad
-#define FBERERR2 REGx(R0900_P1_FBERERR2)
-#define F0900_P1_FBERMETER_ERR2 0xf5ad00ff
-
-/*P1_FBERERR1*/
-#define R0900_P1_FBERERR1 0xf5ae
-#define FBERERR1 REGx(R0900_P1_FBERERR1)
-#define F0900_P1_FBERMETER_ERR1 0xf5ae00ff
-
-/*P1_FBERERR0*/
-#define R0900_P1_FBERERR0 0xf5af
-#define FBERERR0 REGx(R0900_P1_FBERERR0)
-#define F0900_P1_FBERMETER_ERR0 0xf5af00ff
-
-/*P1_FSPYBER*/
-#define R0900_P1_FSPYBER 0xf5b2
-#define FSPYBER REGx(R0900_P1_FSPYBER)
-#define F0900_P1_FSPYBER_SYNCBYTE 0xf5b20010
-#define F0900_P1_FSPYBER_UNSYNC 0xf5b20008
-#define F0900_P1_FSPYBER_CTIME 0xf5b20007
-
-/*RCCFG2*/
-#define R0900_RCCFG2 0xf600
-
-/*TSGENERAL*/
-#define R0900_TSGENERAL 0xf630
-#define F0900_TSFIFO_DISTS2PAR 0xf6300040
-#define F0900_MUXSTREAM_OUTMODE 0xf6300008
-#define F0900_TSFIFO_PERMPARAL 0xf6300006
-
-/*TSGENERAL1X*/
-#define R0900_TSGENERAL1X 0xf670
-
-/*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_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
-
-/*P2_TCTL4*/
-#define R0900_P2_TCTL4 0xff28
-#define F0900_P2_PN4_SELECT 0xff280020
-
-/*P1_TCTL4*/
-#define R0900_P1_TCTL4 0xff48
-#define TCTL4 shiftx(R0900_P1_TCTL4, demod, 0x20)
-#define F0900_P1_PN4_SELECT 0xff480020
-
-/*P2_TSTDISRX*/
-#define R0900_P2_TSTDISRX 0xff65
-#define F0900_P2_PIN_SELECT1 0xff650008
-
-/*P1_TSTDISRX*/
-#define R0900_P1_TSTDISRX 0xff67
-#define TSTDISRX shiftx(R0900_P1_TSTDISRX, demod, 2)
-#define F0900_P1_PIN_SELECT1 0xff670008
-#define PIN_SELECT1 shiftx(F0900_P1_PIN_SELECT1, demod, 0x20000)
-
-#define STV0900_NBREGS 723
-#define STV0900_NBFIELDS 1420
-
-#endif
-
diff --git a/drivers/media/dvb/frontends/stv0900_sw.c b/drivers/media/dvb/frontends/stv0900_sw.c
deleted file mode 100644
index 4af2078..0000000
--- a/drivers/media/dvb/frontends/stv0900_sw.c
+++ /dev/null
@@ -1,2032 +0,0 @@
-/*
- * 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"
-
-s32 shiftx(s32 x, int demod, s32 shift)
-{
-	if (demod == 1)
-		return x - shift;
-
-	return x;
-}
-
-int stv0900_check_signal_presence(struct stv0900_internal *intp,
-					enum fe_stv0900_demod_num demod)
-{
-	s32	carr_offset,
-		agc2_integr,
-		max_carrier;
-
-	int no_signal = FALSE;
-
-	carr_offset = (stv0900_read_reg(intp, CFR2) << 8)
-					| stv0900_read_reg(intp, CFR1);
-	carr_offset = ge2comp(carr_offset, 16);
-	agc2_integr = (stv0900_read_reg(intp, AGC2I1) << 8)
-					| stv0900_read_reg(intp, AGC2I0);
-	max_carrier = intp->srch_range[demod] / 1000;
-
-	max_carrier += (max_carrier / 10);
-	max_carrier = 65536 * (max_carrier / 2);
-	max_carrier /= intp->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;
-
-	return no_signal;
-}
-
-static void stv0900_get_sw_loop_params(struct stv0900_internal *intp,
-				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;
-
-	srate = intp->symbol_rate[demod];
-	max_carrier = intp->srch_range[demod] / 1000;
-	max_carrier += max_carrier / 10;
-	standard = intp->srch_standard[demod];
-
-	max_carrier = 65536 * (max_carrier / 2);
-	max_carrier /= intp->mclk / 1000;
-
-	if (max_carrier > 0x4000)
-		max_carrier = 0x4000;
-
-	freq_inc = srate;
-	freq_inc /= intp->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 *intp,
-				s32 FreqIncr, s32 Timeout, int zigzag,
-				s32 MaxStep, enum fe_stv0900_demod_num demod)
-{
-	int	no_signal,
-		lock = FALSE;
-	s32	stepCpt,
-		freqOffset,
-		max_carrier;
-
-	max_carrier = intp->srch_range[demod] / 1000;
-	max_carrier += (max_carrier / 10);
-
-	max_carrier = 65536 * (max_carrier / 2);
-	max_carrier /= intp->mclk / 1000;
-
-	if (max_carrier > 0x4000)
-		max_carrier = 0x4000;
-
-	if (zigzag == TRUE)
-		freqOffset = 0;
-	else
-		freqOffset = -max_carrier + FreqIncr;
-
-	stepCpt = 0;
-
-	do {
-		stv0900_write_reg(intp, DMDISTATE, 0x1c);
-		stv0900_write_reg(intp, CFRINIT1, (freqOffset / 256) & 0xff);
-		stv0900_write_reg(intp, CFRINIT0, freqOffset & 0xff);
-		stv0900_write_reg(intp, DMDISTATE, 0x18);
-		stv0900_write_bits(intp, ALGOSWRST, 1);
-
-		if (intp->chip_id == 0x12) {
-			stv0900_write_bits(intp, RST_HWARE, 1);
-			stv0900_write_bits(intp, RST_HWARE, 0);
-		}
-
-		if (zigzag == TRUE) {
-			if (freqOffset >= 0)
-				freqOffset = -freqOffset - 2 * FreqIncr;
-			else
-				freqOffset = -freqOffset;
-		} else
-			freqOffset += + 2 * FreqIncr;
-
-		stepCpt++;
-		lock = stv0900_get_demod_lock(intp, demod, Timeout);
-		no_signal = stv0900_check_signal_presence(intp, demod);
-
-	} while ((lock == FALSE)
-			&& (no_signal == FALSE)
-			&& ((freqOffset - FreqIncr) <  max_carrier)
-			&& ((freqOffset + FreqIncr) > -max_carrier)
-			&& (stepCpt < MaxStep));
-
-	stv0900_write_bits(intp, ALGOSWRST, 0);
-
-	return lock;
-}
-
-static int stv0900_sw_algo(struct stv0900_internal *intp,
-				enum fe_stv0900_demod_num demod)
-{
-	int	lock = FALSE,
-		no_signal,
-		zigzag;
-	s32	s2fw,
-		fqc_inc,
-		sft_stp_tout,
-		trial_cntr,
-		max_steps;
-
-	stv0900_get_sw_loop_params(intp, &fqc_inc, &sft_stp_tout,
-					&max_steps, demod);
-	switch (intp->srch_standard[demod]) {
-	case STV0900_SEARCH_DVBS1:
-	case STV0900_SEARCH_DSS:
-		if (intp->chip_id >= 0x20)
-			stv0900_write_reg(intp, CARFREQ, 0x3b);
-		else
-			stv0900_write_reg(intp, CARFREQ, 0xef);
-
-		stv0900_write_reg(intp, DMDCFGMD, 0x49);
-		zigzag = FALSE;
-		break;
-	case STV0900_SEARCH_DVBS2:
-		if (intp->chip_id >= 0x20)
-			stv0900_write_reg(intp, CORRELABS, 0x79);
-		else
-			stv0900_write_reg(intp, CORRELABS, 0x68);
-
-		stv0900_write_reg(intp, DMDCFGMD, 0x89);
-
-		zigzag = TRUE;
-		break;
-	case STV0900_AUTO_SEARCH:
-	default:
-		if (intp->chip_id >= 0x20) {
-			stv0900_write_reg(intp, CARFREQ, 0x3b);
-			stv0900_write_reg(intp, CORRELABS, 0x79);
-		} else {
-			stv0900_write_reg(intp, CARFREQ, 0xef);
-			stv0900_write_reg(intp, CORRELABS, 0x68);
-		}
-
-		stv0900_write_reg(intp, DMDCFGMD, 0xc9);
-		zigzag = FALSE;
-		break;
-	}
-
-	trial_cntr = 0;
-	do {
-		lock = stv0900_search_carr_sw_loop(intp,
-						fqc_inc,
-						sft_stp_tout,
-						zigzag,
-						max_steps,
-						demod);
-		no_signal = stv0900_check_signal_presence(intp, demod);
-		trial_cntr++;
-		if ((lock == TRUE)
-				|| (no_signal == TRUE)
-				|| (trial_cntr == 2)) {
-
-			if (intp->chip_id >= 0x20) {
-				stv0900_write_reg(intp, CARFREQ, 0x49);
-				stv0900_write_reg(intp, CORRELABS, 0x9e);
-			} else {
-				stv0900_write_reg(intp, CARFREQ, 0xed);
-				stv0900_write_reg(intp, CORRELABS, 0x88);
-			}
-
-			if ((stv0900_get_bits(intp, HEADER_MODE) ==
-						STV0900_DVBS2_FOUND) &&
-							(lock == TRUE)) {
-				msleep(sft_stp_tout);
-				s2fw = stv0900_get_bits(intp, FLYWHEEL_CPT);
-
-				if (s2fw < 0xd) {
-					msleep(sft_stp_tout);
-					s2fw = stv0900_get_bits(intp,
-								FLYWHEEL_CPT);
-				}
-
-				if (s2fw < 0xd) {
-					lock = FALSE;
-
-					if (trial_cntr < 2) {
-						if (intp->chip_id >= 0x20)
-							stv0900_write_reg(intp,
-								CORRELABS,
-								0x79);
-						else
-							stv0900_write_reg(intp,
-								CORRELABS,
-								0x68);
-
-						stv0900_write_reg(intp,
-								DMDCFGMD,
-								0x89);
-					}
-				}
-			}
-		}
-
-	} while ((lock == FALSE)
-		&& (trial_cntr < 2)
-		&& (no_signal == FALSE));
-
-	return lock;
-}
-
-static u32 stv0900_get_symbol_rate(struct stv0900_internal *intp,
-					u32 mclk,
-					enum fe_stv0900_demod_num demod)
-{
-	s32	rem1, rem2, intval1, intval2, srate;
-
-	srate = (stv0900_get_bits(intp, SYMB_FREQ3) << 24) +
-		(stv0900_get_bits(intp, SYMB_FREQ2) << 16) +
-		(stv0900_get_bits(intp, SYMB_FREQ1) << 8) +
-		(stv0900_get_bits(intp, SYMB_FREQ0));
-	dprintk("lock: srate=%d r0=0x%x r1=0x%x r2=0x%x r3=0x%x \n",
-		srate, stv0900_get_bits(intp, SYMB_FREQ0),
-		stv0900_get_bits(intp, SYMB_FREQ1),
-		stv0900_get_bits(intp, SYMB_FREQ2),
-		stv0900_get_bits(intp, SYMB_FREQ3));
-
-	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 *intp,
-					u32 mclk, u32 srate,
-					enum fe_stv0900_demod_num demod)
-{
-	u32 symb;
-
-	dprintk("%s: Mclk %d, SR %d, Dmd %d\n", __func__, mclk,
-							srate, demod);
-
-	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(intp, SFRINIT1, (symb >> 8) & 0x7f);
-	stv0900_write_reg(intp, SFRINIT1 + 1, (symb & 0xff));
-}
-
-static void stv0900_set_max_symbol_rate(struct stv0900_internal *intp,
-					u32 mclk, u32 srate,
-					enum fe_stv0900_demod_num demod)
-{
-	u32 symb;
-
-	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(intp, SFRUP1, (symb >> 8) & 0x7f);
-		stv0900_write_reg(intp, SFRUP1 + 1, (symb & 0xff));
-	} else {
-		stv0900_write_reg(intp, SFRUP1, 0x7f);
-		stv0900_write_reg(intp, SFRUP1 + 1, 0xff);
-	}
-}
-
-static void stv0900_set_min_symbol_rate(struct stv0900_internal *intp,
-					u32 mclk, u32 srate,
-					enum fe_stv0900_demod_num demod)
-{
-	u32	symb;
-
-	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(intp, SFRLOW1, (symb >> 8) & 0xff);
-	stv0900_write_reg(intp, SFRLOW1 + 1, (symb & 0xff));
-}
-
-static s32 stv0900_get_timing_offst(struct stv0900_internal *intp,
-					u32 srate,
-					enum fe_stv0900_demod_num demod)
-{
-	s32 timingoffset;
-
-
-	timingoffset = (stv0900_read_reg(intp, TMGREG2) << 16) +
-		       (stv0900_read_reg(intp, TMGREG2 + 1) << 8) +
-		       (stv0900_read_reg(intp, TMGREG2 + 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 *intp,
-					enum fe_stv0900_demod_num demod)
-{
-	s32 rolloff;
-
-	if (intp->chip_id == 0x10) {
-		stv0900_write_bits(intp, MANUALSX_ROLLOFF, 1);
-		rolloff = stv0900_read_reg(intp, MATSTR1) & 0x03;
-		stv0900_write_bits(intp, ROLLOFF_CONTROL, rolloff);
-	} else if (intp->chip_id <= 0x20)
-		stv0900_write_bits(intp, MANUALSX_ROLLOFF, 0);
-	else /* cut 3.0 */
-		stv0900_write_bits(intp, MANUALS2_ROLLOFF, 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 *intp,
-				enum fe_stv0900_demod_num demod)
-{
-	int timingLock = FALSE;
-	s32	i,
-		timingcpt = 0;
-	u8	car_freq,
-		tmg_th_high,
-		tmg_th_low;
-
-	car_freq = stv0900_read_reg(intp, CARFREQ);
-	tmg_th_high = stv0900_read_reg(intp, TMGTHRISE);
-	tmg_th_low = stv0900_read_reg(intp, TMGTHFALL);
-	stv0900_write_reg(intp, TMGTHRISE, 0x20);
-	stv0900_write_reg(intp, TMGTHFALL, 0x0);
-	stv0900_write_bits(intp, CFR_AUTOSCAN, 0);
-	stv0900_write_reg(intp, RTC, 0x80);
-	stv0900_write_reg(intp, RTCS2, 0x40);
-	stv0900_write_reg(intp, CARFREQ, 0x0);
-	stv0900_write_reg(intp, CFRINIT1, 0x0);
-	stv0900_write_reg(intp, CFRINIT0, 0x0);
-	stv0900_write_reg(intp, AGC2REF, 0x65);
-	stv0900_write_reg(intp, DMDISTATE, 0x18);
-	msleep(7);
-
-	for (i = 0; i < 10; i++) {
-		if (stv0900_get_bits(intp, TMGLOCK_QUALITY) >= 2)
-			timingcpt++;
-
-		msleep(1);
-	}
-
-	if (timingcpt >= 3)
-		timingLock = TRUE;
-
-	stv0900_write_reg(intp, AGC2REF, 0x38);
-	stv0900_write_reg(intp, RTC, 0x88);
-	stv0900_write_reg(intp, RTCS2, 0x68);
-	stv0900_write_reg(intp, CARFREQ, car_freq);
-	stv0900_write_reg(intp, TMGTHRISE, tmg_th_high);
-	stv0900_write_reg(intp, TMGTHFALL, tmg_th_low);
-
-	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 *intp = state->internal;
-	enum fe_stv0900_demod_num demod = state->demod;
-	int	lock = FALSE,
-		d = demod;
-	s32	srate,
-		search_range,
-		locktimeout,
-		currier_step,
-		nb_steps,
-		current_step,
-		direction,
-		tuner_freq,
-		timeout,
-		freq;
-
-	srate = intp->symbol_rate[d];
-	search_range = intp->srch_range[d];
-
-	if (srate >= 10000000)
-		locktimeout = demod_timeout / 3;
-	else
-		locktimeout = demod_timeout / 2;
-
-	lock = stv0900_get_demod_lock(intp, d, locktimeout);
-
-	if (lock != FALSE)
-		return lock;
-
-	if (srate >= 10000000) {
-		if (stv0900_check_timing_lock(intp, d) == TRUE) {
-			stv0900_write_reg(intp, DMDISTATE, 0x1f);
-			stv0900_write_reg(intp, DMDISTATE, 0x15);
-			lock = stv0900_get_demod_lock(intp, d, demod_timeout);
-		} else
-			lock = FALSE;
-
-		return lock;
-	}
-
-	if (intp->chip_id <= 0x20) {
-		if (srate <= 1000000)
-			currier_step = 500;
-		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;
-
-		if (srate >= 2000000) {
-			timeout = (demod_timeout / 3);
-			if (timeout > 1000)
-				timeout = 1000;
-		} else
-			timeout = (demod_timeout / 2);
-	} else {
-		/*cut 3.0 */
-		currier_step = srate / 4000;
-		timeout = (demod_timeout * 3) / 4;
-	}
-
-	nb_steps = ((search_range / 1000) / currier_step);
-
-	if ((nb_steps % 2) != 0)
-		nb_steps += 1;
-
-	if (nb_steps <= 0)
-		nb_steps = 2;
-	else if (nb_steps > 12)
-		nb_steps = 12;
-
-	current_step = 1;
-	direction = 1;
-
-	if (intp->chip_id <= 0x20) {
-		tuner_freq = intp->freq[d];
-		intp->bw[d] = stv0900_carrier_width(intp->symbol_rate[d],
-				intp->rolloff) + intp->symbol_rate[d];
-	} else
-		tuner_freq = 0;
-
-	while ((current_step <= nb_steps) && (lock == FALSE)) {
-		if (direction > 0)
-			tuner_freq += (current_step * currier_step);
-		else
-			tuner_freq -= (current_step * currier_step);
-
-		if (intp->chip_id <= 0x20) {
-			if (intp->tuner_type[d] == 3)
-				stv0900_set_tuner_auto(intp, tuner_freq,
-						intp->bw[d], demod);
-			else
-				stv0900_set_tuner(fe, tuner_freq, intp->bw[d]);
-
-			stv0900_write_reg(intp, DMDISTATE, 0x1c);
-			stv0900_write_reg(intp, CFRINIT1, 0);
-			stv0900_write_reg(intp, CFRINIT0, 0);
-			stv0900_write_reg(intp, DMDISTATE, 0x1f);
-			stv0900_write_reg(intp, DMDISTATE, 0x15);
-		} else {
-			stv0900_write_reg(intp, DMDISTATE, 0x1c);
-			freq = (tuner_freq * 65536) / (intp->mclk / 1000);
-			stv0900_write_bits(intp, CFR_INIT1, MSB(freq));
-			stv0900_write_bits(intp, CFR_INIT0, LSB(freq));
-			stv0900_write_reg(intp, DMDISTATE, 0x1f);
-			stv0900_write_reg(intp, DMDISTATE, 0x05);
-		}
-
-		lock = stv0900_get_demod_lock(intp, d, timeout);
-		direction *= -1;
-		current_step++;
-	}
-
-	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 *intp,
-					enum fe_stv0900_demod_num demod)
-{
-
-	s32 vth_reg = VTH12;
-
-	dprintk("%s\n", __func__);
-
-	stv0900_write_reg(intp, vth_reg++, 0xd0);
-	stv0900_write_reg(intp, vth_reg++, 0x7d);
-	stv0900_write_reg(intp, vth_reg++, 0x53);
-	stv0900_write_reg(intp, vth_reg++, 0x2f);
-	stv0900_write_reg(intp, vth_reg++, 0x24);
-	stv0900_write_reg(intp, vth_reg++, 0x1f);
-}
-
-static void stv0900_set_viterbi_standard(struct stv0900_internal *intp,
-				   enum fe_stv0900_search_standard standard,
-				   enum fe_stv0900_fec fec,
-				   enum fe_stv0900_demod_num demod)
-{
-	dprintk("%s: ViterbiStandard = ", __func__);
-
-	switch (standard) {
-	case STV0900_AUTO_SEARCH:
-		dprintk("Auto\n");
-		stv0900_write_reg(intp, FECM, 0x10);
-		stv0900_write_reg(intp, PRVIT, 0x3f);
-		break;
-	case STV0900_SEARCH_DVBS1:
-		dprintk("DVBS1\n");
-		stv0900_write_reg(intp, FECM, 0x00);
-		switch (fec) {
-		case STV0900_FEC_UNKNOWN:
-		default:
-			stv0900_write_reg(intp, PRVIT, 0x2f);
-			break;
-		case STV0900_FEC_1_2:
-			stv0900_write_reg(intp, PRVIT, 0x01);
-			break;
-		case STV0900_FEC_2_3:
-			stv0900_write_reg(intp, PRVIT, 0x02);
-			break;
-		case STV0900_FEC_3_4:
-			stv0900_write_reg(intp, PRVIT, 0x04);
-			break;
-		case STV0900_FEC_5_6:
-			stv0900_write_reg(intp, PRVIT, 0x08);
-			break;
-		case STV0900_FEC_7_8:
-			stv0900_write_reg(intp, PRVIT, 0x20);
-			break;
-		}
-
-		break;
-	case STV0900_SEARCH_DSS:
-		dprintk("DSS\n");
-		stv0900_write_reg(intp, FECM, 0x80);
-		switch (fec) {
-		case STV0900_FEC_UNKNOWN:
-		default:
-			stv0900_write_reg(intp, PRVIT, 0x13);
-			break;
-		case STV0900_FEC_1_2:
-			stv0900_write_reg(intp, PRVIT, 0x01);
-			break;
-		case STV0900_FEC_2_3:
-			stv0900_write_reg(intp, PRVIT, 0x02);
-			break;
-		case STV0900_FEC_6_7:
-			stv0900_write_reg(intp, PRVIT, 0x10);
-			break;
-		}
-		break;
-	default:
-		break;
-	}
-}
-
-static enum fe_stv0900_fec stv0900_get_vit_fec(struct stv0900_internal *intp,
-						enum fe_stv0900_demod_num demod)
-{
-	enum fe_stv0900_fec prate;
-	s32 rate_fld = stv0900_get_bits(intp, VIT_CURPUN);
-
-	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 void stv0900_set_dvbs1_track_car_loop(struct stv0900_internal *intp,
-					enum fe_stv0900_demod_num demod,
-					u32 srate)
-{
-	if (intp->chip_id >= 0x30) {
-		if (srate >= 15000000) {
-			stv0900_write_reg(intp, ACLC, 0x2b);
-			stv0900_write_reg(intp, BCLC, 0x1a);
-		} else if ((srate >= 7000000) && (15000000 > srate)) {
-			stv0900_write_reg(intp, ACLC, 0x0c);
-			stv0900_write_reg(intp, BCLC, 0x1b);
-		} else if (srate < 7000000) {
-			stv0900_write_reg(intp, ACLC, 0x2c);
-			stv0900_write_reg(intp, BCLC, 0x1c);
-		}
-
-	} else { /*cut 2.0 and 1.x*/
-		stv0900_write_reg(intp, ACLC, 0x1a);
-		stv0900_write_reg(intp, BCLC, 0x09);
-	}
-
-}
-
-static void stv0900_track_optimization(struct dvb_frontend *fe)
-{
-	struct stv0900_state *state = fe->demodulator_priv;
-	struct stv0900_internal *intp = state->internal;
-	enum fe_stv0900_demod_num demod = state->demod;
-
-	s32	srate,
-		pilots,
-		aclc,
-		freq1,
-		freq0,
-		i = 0,
-		timed,
-		timef,
-		blind_tun_sw = 0,
-		modulation;
-
-	enum fe_stv0900_modcode foundModcod;
-
-	dprintk("%s\n", __func__);
-
-	srate = stv0900_get_symbol_rate(intp, intp->mclk, demod);
-	srate += stv0900_get_timing_offst(intp, srate, demod);
-
-	switch (intp->result[demod].standard) {
-	case STV0900_DVBS1_STANDARD:
-	case STV0900_DSS_STANDARD:
-		dprintk("%s: found DVB-S or DSS\n", __func__);
-		if (intp->srch_standard[demod] == STV0900_AUTO_SEARCH) {
-			stv0900_write_bits(intp, DVBS1_ENABLE, 1);
-			stv0900_write_bits(intp, DVBS2_ENABLE, 0);
-		}
-
-		stv0900_write_bits(intp, ROLLOFF_CONTROL, intp->rolloff);
-		stv0900_write_bits(intp, MANUALSX_ROLLOFF, 1);
-
-		if (intp->chip_id < 0x30) {
-			stv0900_write_reg(intp, ERRCTRL1, 0x75);
-			break;
-		}
-
-		if (stv0900_get_vit_fec(intp, demod) == STV0900_FEC_1_2) {
-			stv0900_write_reg(intp, GAUSSR0, 0x98);
-			stv0900_write_reg(intp, CCIR0, 0x18);
-		} else {
-			stv0900_write_reg(intp, GAUSSR0, 0x18);
-			stv0900_write_reg(intp, CCIR0, 0x18);
-		}
-
-		stv0900_write_reg(intp, ERRCTRL1, 0x75);
-		break;
-	case STV0900_DVBS2_STANDARD:
-		dprintk("%s: found DVB-S2\n", __func__);
-		stv0900_write_bits(intp, DVBS1_ENABLE, 0);
-		stv0900_write_bits(intp, DVBS2_ENABLE, 1);
-		stv0900_write_reg(intp, ACLC, 0);
-		stv0900_write_reg(intp, BCLC, 0);
-		if (intp->result[demod].frame_len == STV0900_LONG_FRAME) {
-			foundModcod = stv0900_get_bits(intp, DEMOD_MODCOD);
-			pilots = stv0900_get_bits(intp, DEMOD_TYPE) & 0x01;
-			aclc = stv0900_get_optim_carr_loop(srate,
-							foundModcod,
-							pilots,
-							intp->chip_id);
-			if (foundModcod <= STV0900_QPSK_910)
-				stv0900_write_reg(intp, ACLC2S2Q, aclc);
-			else if (foundModcod <= STV0900_8PSK_910) {
-				stv0900_write_reg(intp, ACLC2S2Q, 0x2a);
-				stv0900_write_reg(intp, ACLC2S28, aclc);
-			}
-
-			if ((intp->demod_mode == STV0900_SINGLE) &&
-					(foundModcod > STV0900_8PSK_910)) {
-				if (foundModcod <= STV0900_16APSK_910) {
-					stv0900_write_reg(intp, ACLC2S2Q, 0x2a);
-					stv0900_write_reg(intp, ACLC2S216A,
-									aclc);
-				} else if (foundModcod <= STV0900_32APSK_910) {
-					stv0900_write_reg(intp, ACLC2S2Q, 0x2a);
-					stv0900_write_reg(intp,	ACLC2S232A,
-									aclc);
-				}
-			}
-
-		} else {
-			modulation = intp->result[demod].modulation;
-			aclc = stv0900_get_optim_short_carr_loop(srate,
-					modulation, intp->chip_id);
-			if (modulation == STV0900_QPSK)
-				stv0900_write_reg(intp, ACLC2S2Q, aclc);
-			else if (modulation == STV0900_8PSK) {
-				stv0900_write_reg(intp, ACLC2S2Q, 0x2a);
-				stv0900_write_reg(intp, ACLC2S28, aclc);
-			} else if (modulation == STV0900_16APSK) {
-				stv0900_write_reg(intp, ACLC2S2Q, 0x2a);
-				stv0900_write_reg(intp, ACLC2S216A, aclc);
-			} else if (modulation == STV0900_32APSK) {
-				stv0900_write_reg(intp, ACLC2S2Q, 0x2a);
-				stv0900_write_reg(intp, ACLC2S232A, aclc);
-			}
-
-		}
-
-		if (intp->chip_id <= 0x11) {
-			if (intp->demod_mode != STV0900_SINGLE)
-				stv0900_activate_s2_modcod(intp, demod);
-
-		}
-
-		stv0900_write_reg(intp, ERRCTRL1, 0x67);
-		break;
-	case STV0900_UNKNOWN_STANDARD:
-	default:
-		dprintk("%s: found unknown standard\n", __func__);
-		stv0900_write_bits(intp, DVBS1_ENABLE, 1);
-		stv0900_write_bits(intp, DVBS2_ENABLE, 1);
-		break;
-	}
-
-	freq1 = stv0900_read_reg(intp, CFR2);
-	freq0 = stv0900_read_reg(intp, CFR1);
-	if (intp->srch_algo[demod] == STV0900_BLIND_SEARCH) {
-		stv0900_write_reg(intp, SFRSTEP, 0x00);
-		stv0900_write_bits(intp, SCAN_ENABLE, 0);
-		stv0900_write_bits(intp, CFR_AUTOSCAN, 0);
-		stv0900_write_reg(intp, TMGCFG2, 0xc1);
-		stv0900_set_symbol_rate(intp, intp->mclk, srate, demod);
-		blind_tun_sw = 1;
-		if (intp->result[demod].standard != STV0900_DVBS2_STANDARD)
-			stv0900_set_dvbs1_track_car_loop(intp, demod, srate);
-
-	}
-
-	if (intp->chip_id >= 0x20) {
-		if ((intp->srch_standard[demod] == STV0900_SEARCH_DVBS1) ||
-				(intp->srch_standard[demod] ==
-							STV0900_SEARCH_DSS) ||
-				(intp->srch_standard[demod] ==
-							STV0900_AUTO_SEARCH)) {
-			stv0900_write_reg(intp, VAVSRVIT, 0x0a);
-			stv0900_write_reg(intp, VITSCALE, 0x0);
-		}
-	}
-
-	if (intp->chip_id < 0x20)
-		stv0900_write_reg(intp, CARHDR, 0x08);
-
-	if (intp->chip_id == 0x10)
-		stv0900_write_reg(intp, CORRELEXP, 0x0a);
-
-	stv0900_write_reg(intp, AGC2REF, 0x38);
-
-	if ((intp->chip_id >= 0x20) ||
-			(blind_tun_sw == 1) ||
-			(intp->symbol_rate[demod] < 10000000)) {
-		stv0900_write_reg(intp, CFRINIT1, freq1);
-		stv0900_write_reg(intp, CFRINIT0, freq0);
-		intp->bw[demod] = stv0900_carrier_width(srate,
-					intp->rolloff) + 10000000;
-
-		if ((intp->chip_id >= 0x20) || (blind_tun_sw == 1)) {
-			if (intp->srch_algo[demod] != STV0900_WARM_START) {
-				if (intp->tuner_type[demod] == 3)
-					stv0900_set_tuner_auto(intp,
-							intp->freq[demod],
-							intp->bw[demod],
-							demod);
-				else
-					stv0900_set_bandwidth(fe,
-							intp->bw[demod]);
-			}
-		}
-
-		if ((intp->srch_algo[demod] == STV0900_BLIND_SEARCH) ||
-				(intp->symbol_rate[demod] < 10000000))
-			msleep(50);
-		else
-			msleep(5);
-
-		stv0900_get_lock_timeout(&timed, &timef, srate,
-						STV0900_WARM_START);
-
-		if (stv0900_get_demod_lock(intp, demod, timed / 2) == FALSE) {
-			stv0900_write_reg(intp, DMDISTATE, 0x1f);
-			stv0900_write_reg(intp, CFRINIT1, freq1);
-			stv0900_write_reg(intp, CFRINIT0, freq0);
-			stv0900_write_reg(intp, DMDISTATE, 0x18);
-			i = 0;
-			while ((stv0900_get_demod_lock(intp,
-							demod,
-							timed / 2) == FALSE) &&
-						(i <= 2)) {
-				stv0900_write_reg(intp, DMDISTATE, 0x1f);
-				stv0900_write_reg(intp, CFRINIT1, freq1);
-				stv0900_write_reg(intp, CFRINIT0, freq0);
-				stv0900_write_reg(intp, DMDISTATE, 0x18);
-				i++;
-			}
-		}
-
-	}
-
-	if (intp->chip_id >= 0x20)
-		stv0900_write_reg(intp, CARFREQ, 0x49);
-
-	if ((intp->result[demod].standard == STV0900_DVBS1_STANDARD) ||
-			(intp->result[demod].standard == STV0900_DSS_STANDARD))
-		stv0900_set_viterbi_tracq(intp, demod);
-
-}
-
-static int stv0900_get_fec_lock(struct stv0900_internal *intp,
-				enum fe_stv0900_demod_num demod, s32 time_out)
-{
-	s32 timer = 0, lock = 0;
-
-	enum fe_stv0900_search_state dmd_state;
-
-	dprintk("%s\n", __func__);
-
-	dmd_state = stv0900_get_bits(intp, HEADER_MODE);
-
-	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(intp, PKTDELIN_LOCK);
-			break;
-		case STV0900_DVBS_FOUND:
-			lock = stv0900_get_bits(intp, LOCKEDVIT);
-			break;
-		}
-
-		if (lock == 0) {
-			msleep(10);
-			timer += 10;
-		}
-	}
-
-	if (lock)
-		dprintk("%s: DEMOD FEC LOCK OK\n", __func__);
-	else
-		dprintk("%s: DEMOD FEC LOCK FAIL\n", __func__);
-
-	return lock;
-}
-
-static int stv0900_wait_for_lock(struct stv0900_internal *intp,
-				enum fe_stv0900_demod_num demod,
-				s32 dmd_timeout, s32 fec_timeout)
-{
-
-	s32 timer = 0, lock = 0;
-
-	dprintk("%s\n", __func__);
-
-	lock = stv0900_get_demod_lock(intp, demod, dmd_timeout);
-
-	if (lock)
-		lock = lock && stv0900_get_fec_lock(intp, demod, fec_timeout);
-
-	if (lock) {
-		lock = 0;
-
-		dprintk("%s: Timer = %d, time_out = %d\n",
-				__func__, timer, fec_timeout);
-
-		while ((timer < fec_timeout) && (lock == 0)) {
-			lock = stv0900_get_bits(intp, TSFIFO_LINEOK);
-			msleep(1);
-			timer++;
-		}
-	}
-
-	if (lock)
-		dprintk("%s: DEMOD LOCK OK\n", __func__);
-	else
-		dprintk("%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 *intp = state->internal;
-	enum fe_stv0900_tracking_standard fnd_standard;
-
-	int hdr_mode = stv0900_get_bits(intp, HEADER_MODE);
-
-	switch (hdr_mode) {
-	case 2:
-		fnd_standard = STV0900_DVBS2_STANDARD;
-		break;
-	case 3:
-		if (stv0900_get_bits(intp, DSS_DVB) == 1)
-			fnd_standard = STV0900_DSS_STANDARD;
-		else
-			fnd_standard = STV0900_DVBS1_STANDARD;
-
-		break;
-	default:
-		fnd_standard = STV0900_UNKNOWN_STANDARD;
-	}
-
-	dprintk("%s: standard %d\n", __func__, fnd_standard);
-
-	return fnd_standard;
-}
-
-static s32 stv0900_get_carr_freq(struct stv0900_internal *intp, u32 mclk,
-					enum fe_stv0900_demod_num demod)
-{
-	s32	derot,
-		rem1,
-		rem2,
-		intval1,
-		intval2;
-
-	derot = (stv0900_get_bits(intp, CAR_FREQ2) << 16) +
-		(stv0900_get_bits(intp, CAR_FREQ1) << 8) +
-		(stv0900_get_bits(intp, CAR_FREQ0));
-
-	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 freq = 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, &freq)) < 0)
-			dprintk("%s: Invalid parameter\n", __func__);
-		else
-			dprintk("%s: Frequency=%d\n", __func__, freq);
-
-	}
-
-	return freq;
-}
-
-static enum
-fe_stv0900_signal_type stv0900_get_signal_params(struct dvb_frontend *fe)
-{
-	struct stv0900_state *state = fe->demodulator_priv;
-	struct stv0900_internal *intp = state->internal;
-	enum fe_stv0900_demod_num demod = state->demod;
-	enum fe_stv0900_signal_type range = STV0900_OUTOFRANGE;
-	struct stv0900_signal_info *result = &intp->result[demod];
-	s32	offsetFreq,
-		srate_offset;
-	int	i = 0,
-		d = demod;
-
-	u8 timing;
-
-	msleep(5);
-	if (intp->srch_algo[d] == STV0900_BLIND_SEARCH) {
-		timing = stv0900_read_reg(intp, TMGREG2);
-		i = 0;
-		stv0900_write_reg(intp, SFRSTEP, 0x5c);
-
-		while ((i <= 50) && (timing != 0) && (timing != 0xff)) {
-			timing = stv0900_read_reg(intp, TMGREG2);
-			msleep(5);
-			i += 5;
-		}
-	}
-
-	result->standard = stv0900_get_standard(fe, d);
-	if (intp->tuner_type[demod] == 3)
-		result->frequency = stv0900_get_freq_auto(intp, d);
-	else
-		result->frequency = stv0900_get_tuner_freq(fe);
-
-	offsetFreq = stv0900_get_carr_freq(intp, intp->mclk, d) / 1000;
-	result->frequency += offsetFreq;
-	result->symbol_rate = stv0900_get_symbol_rate(intp, intp->mclk, d);
-	srate_offset = stv0900_get_timing_offst(intp, result->symbol_rate, d);
-	result->symbol_rate += srate_offset;
-	result->fec = stv0900_get_vit_fec(intp, d);
-	result->modcode = stv0900_get_bits(intp, DEMOD_MODCOD);
-	result->pilot = stv0900_get_bits(intp, DEMOD_TYPE) & 0x01;
-	result->frame_len = ((u32)stv0900_get_bits(intp, DEMOD_TYPE)) >> 1;
-	result->rolloff = stv0900_get_bits(intp, ROLLOFF_STATUS);
-
-	dprintk("%s: modcode=0x%x \n", __func__, result->modcode);
-
-	switch (result->standard) {
-	case STV0900_DVBS2_STANDARD:
-		result->spectrum = stv0900_get_bits(intp, SPECINV_DEMOD);
-		if (result->modcode <= STV0900_QPSK_910)
-			result->modulation = STV0900_QPSK;
-		else if (result->modcode <= STV0900_8PSK_910)
-			result->modulation = STV0900_8PSK;
-		else if (result->modcode <= STV0900_16APSK_910)
-			result->modulation = STV0900_16APSK;
-		else if (result->modcode <= STV0900_32APSK_910)
-			result->modulation = STV0900_32APSK;
-		else
-			result->modulation = STV0900_UNKNOWN;
-		break;
-	case STV0900_DVBS1_STANDARD:
-	case STV0900_DSS_STANDARD:
-		result->spectrum = stv0900_get_bits(intp, IQINV);
-		result->modulation = STV0900_QPSK;
-		break;
-	default:
-		break;
-	}
-
-	if ((intp->srch_algo[d] == STV0900_BLIND_SEARCH) ||
-				(intp->symbol_rate[d] < 10000000)) {
-		offsetFreq = result->frequency - intp->freq[d];
-		if (intp->tuner_type[demod] == 3)
-			intp->freq[d] = stv0900_get_freq_auto(intp, d);
-		else
-			intp->freq[d] = stv0900_get_tuner_freq(fe);
-
-		if (ABS(offsetFreq) <= ((intp->srch_range[d] / 2000) + 500))
-			range = STV0900_RANGEOK;
-		else if (ABS(offsetFreq) <=
-				(stv0900_carrier_width(result->symbol_rate,
-						result->rolloff) / 2000))
-			range = STV0900_RANGEOK;
-
-	} else if (ABS(offsetFreq) <= ((intp->srch_range[d] / 2000) + 500))
-		range = STV0900_RANGEOK;
-
-	dprintk("%s: range %d\n", __func__, range);
-
-	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 *intp = state->internal;
-	enum fe_stv0900_demod_num demod = state->demod;
-	enum fe_stv0900_signal_type signal_type = STV0900_NODATA;
-
-	s32	srate,
-		demod_timeout,
-		fec_timeout,
-		freq1,
-		freq0;
-
-	intp->result[demod].locked = FALSE;
-
-	if (stv0900_get_bits(intp, HEADER_MODE) == STV0900_DVBS_FOUND) {
-		srate = stv0900_get_symbol_rate(intp, intp->mclk, demod);
-		srate += stv0900_get_timing_offst(intp, srate, demod);
-		if (intp->srch_algo[demod] == STV0900_BLIND_SEARCH)
-			stv0900_set_symbol_rate(intp, intp->mclk, srate, demod);
-
-		stv0900_get_lock_timeout(&demod_timeout, &fec_timeout,
-					srate, STV0900_WARM_START);
-		freq1 = stv0900_read_reg(intp, CFR2);
-		freq0 = stv0900_read_reg(intp, CFR1);
-		stv0900_write_bits(intp, CFR_AUTOSCAN, 0);
-		stv0900_write_bits(intp, SPECINV_CONTROL,
-					STV0900_IQ_FORCE_SWAPPED);
-		stv0900_write_reg(intp, DMDISTATE, 0x1c);
-		stv0900_write_reg(intp, CFRINIT1, freq1);
-		stv0900_write_reg(intp, CFRINIT0, freq0);
-		stv0900_write_reg(intp, DMDISTATE, 0x18);
-		if (stv0900_wait_for_lock(intp, demod,
-				demod_timeout, fec_timeout) == TRUE) {
-			intp->result[demod].locked = TRUE;
-			signal_type = stv0900_get_signal_params(fe);
-			stv0900_track_optimization(fe);
-		} else {
-			stv0900_write_bits(intp, SPECINV_CONTROL,
-					STV0900_IQ_FORCE_NORMAL);
-			stv0900_write_reg(intp, DMDISTATE, 0x1c);
-			stv0900_write_reg(intp, CFRINIT1, freq1);
-			stv0900_write_reg(intp, CFRINIT0, freq0);
-			stv0900_write_reg(intp, DMDISTATE, 0x18);
-			if (stv0900_wait_for_lock(intp, demod,
-					demod_timeout, fec_timeout) == TRUE) {
-				intp->result[demod].locked = TRUE;
-				signal_type = stv0900_get_signal_params(fe);
-				stv0900_track_optimization(fe);
-			}
-
-		}
-
-	} else
-		intp->result[demod].locked = FALSE;
-
-	return signal_type;
-}
-
-static u16 stv0900_blind_check_agc2_min_level(struct stv0900_internal *intp,
-					enum fe_stv0900_demod_num demod)
-{
-	u32 minagc2level = 0xffff,
-		agc2level,
-		init_freq, freq_step;
-
-	s32 i, j, nb_steps, direction;
-
-	dprintk("%s\n", __func__);
-
-	stv0900_write_reg(intp, AGC2REF, 0x38);
-	stv0900_write_bits(intp, SCAN_ENABLE, 0);
-	stv0900_write_bits(intp, CFR_AUTOSCAN, 0);
-
-	stv0900_write_bits(intp, AUTO_GUP, 1);
-	stv0900_write_bits(intp, AUTO_GLOW, 1);
-
-	stv0900_write_reg(intp, DMDT0M, 0x0);
-
-	stv0900_set_symbol_rate(intp, intp->mclk, 1000000, demod);
-	nb_steps = -1 + (intp->srch_range[demod] / 1000000);
-	nb_steps /= 2;
-	nb_steps = (2 * nb_steps) + 1;
-
-	if (nb_steps < 0)
-		nb_steps = 1;
-
-	direction = 1;
-
-	freq_step = (1000000 << 8) / (intp->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(intp, DMDISTATE, 0x5C);
-		stv0900_write_reg(intp, CFRINIT1, (init_freq >> 8) & 0xff);
-		stv0900_write_reg(intp, CFRINIT0, init_freq  & 0xff);
-		stv0900_write_reg(intp, DMDISTATE, 0x58);
-		msleep(10);
-		agc2level = 0;
-
-		for (j = 0; j < 10; j++)
-			agc2level += (stv0900_read_reg(intp, AGC2I1) << 8)
-					| stv0900_read_reg(intp, AGC2I0);
-
-		agc2level /= 10;
-
-		if (agc2level < minagc2level)
-			minagc2level = agc2level;
-
-	}
-
-	return (u16)minagc2level;
-}
-
-static u32 stv0900_search_srate_coarse(struct dvb_frontend *fe)
-{
-	struct stv0900_state *state = fe->demodulator_priv;
-	struct stv0900_internal *intp = state->internal;
-	enum fe_stv0900_demod_num demod = state->demod;
-	int timing_lck = FALSE;
-	s32 i, timingcpt = 0,
-		direction = 1,
-		nb_steps,
-		current_step = 0,
-		tuner_freq;
-	u32 agc2_th,
-		coarse_srate = 0,
-		agc2_integr = 0,
-		currier_step = 1200;
-
-	if (intp->chip_id >= 0x30)
-		agc2_th = 0x2e00;
-	else
-		agc2_th = 0x1f00;
-
-	stv0900_write_bits(intp, DEMOD_MODE, 0x1f);
-	stv0900_write_reg(intp, TMGCFG, 0x12);
-	stv0900_write_reg(intp, TMGTHRISE, 0xf0);
-	stv0900_write_reg(intp, TMGTHFALL, 0xe0);
-	stv0900_write_bits(intp, SCAN_ENABLE, 1);
-	stv0900_write_bits(intp, CFR_AUTOSCAN, 1);
-	stv0900_write_reg(intp, SFRUP1, 0x83);
-	stv0900_write_reg(intp, SFRUP0, 0xc0);
-	stv0900_write_reg(intp, SFRLOW1, 0x82);
-	stv0900_write_reg(intp, SFRLOW0, 0xa0);
-	stv0900_write_reg(intp, DMDT0M, 0x0);
-	stv0900_write_reg(intp, AGC2REF, 0x50);
-
-	if (intp->chip_id >= 0x30) {
-		stv0900_write_reg(intp, CARFREQ, 0x99);
-		stv0900_write_reg(intp, SFRSTEP, 0x98);
-	} else if (intp->chip_id >= 0x20) {
-		stv0900_write_reg(intp, CARFREQ, 0x6a);
-		stv0900_write_reg(intp, SFRSTEP, 0x95);
-	} else {
-		stv0900_write_reg(intp, CARFREQ, 0xed);
-		stv0900_write_reg(intp, SFRSTEP, 0x73);
-	}
-
-	if (intp->symbol_rate[demod] <= 2000000)
-		currier_step = 1000;
-	else if (intp->symbol_rate[demod] <= 5000000)
-		currier_step = 2000;
-	else if (intp->symbol_rate[demod] <= 12000000)
-		currier_step = 3000;
-	else
-			currier_step = 5000;
-
-	nb_steps = -1 + ((intp->srch_range[demod] / 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 = (intp->srch_range[demod] / 1000) / 10;
-	}
-
-	current_step = 0;
-	direction = 1;
-
-	tuner_freq = intp->freq[demod];
-
-	while ((timing_lck == FALSE) && (current_step < nb_steps)) {
-		stv0900_write_reg(intp, DMDISTATE, 0x5f);
-		stv0900_write_bits(intp, DEMOD_MODE, 0);
-
-		msleep(50);
-
-		for (i = 0; i < 10; i++) {
-			if (stv0900_get_bits(intp, TMGLOCK_QUALITY) >= 2)
-				timingcpt++;
-
-			agc2_integr += (stv0900_read_reg(intp, AGC2I1) << 8) |
-					stv0900_read_reg(intp, AGC2I0);
-		}
-
-		agc2_integr /= 10;
-		coarse_srate = stv0900_get_symbol_rate(intp, intp->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 < agc2_th) &&
-				(coarse_srate < 55000000) &&
-				(coarse_srate > 850000))
-			timing_lck = TRUE;
-		else if (current_step < nb_steps) {
-			if (direction > 0)
-				tuner_freq += (current_step * currier_step);
-			else
-				tuner_freq -= (current_step * currier_step);
-
-			if (intp->tuner_type[demod] == 3)
-				stv0900_set_tuner_auto(intp, tuner_freq,
-						intp->bw[demod], demod);
-			else
-				stv0900_set_tuner(fe, tuner_freq,
-						intp->bw[demod]);
-		}
-	}
-
-	if (timing_lck == FALSE)
-		coarse_srate = 0;
-	else
-		coarse_srate = stv0900_get_symbol_rate(intp, intp->mclk, demod);
-
-	return coarse_srate;
-}
-
-static u32 stv0900_search_srate_fine(struct dvb_frontend *fe)
-{
-	struct stv0900_state *state = fe->demodulator_priv;
-	struct stv0900_internal *intp = state->internal;
-	enum fe_stv0900_demod_num demod = state->demod;
-	u32	coarse_srate,
-		coarse_freq,
-		symb,
-		symbmax,
-		symbmin,
-		symbcomp;
-
-	coarse_srate = stv0900_get_symbol_rate(intp, intp->mclk, demod);
-
-	if (coarse_srate > 3000000) {
-		symbmax = 13 * (coarse_srate / 10);
-		symbmax = (symbmax / 1000) * 65536;
-		symbmax /= (intp->mclk / 1000);
-
-		symbmin = 10 * (coarse_srate / 13);
-		symbmin = (symbmin / 1000)*65536;
-		symbmin /= (intp->mclk / 1000);
-
-		symb = (coarse_srate / 1000) * 65536;
-		symb /= (intp->mclk / 1000);
-	} else {
-		symbmax = 13 * (coarse_srate / 10);
-		symbmax = (symbmax / 100) * 65536;
-		symbmax /= (intp->mclk / 100);
-
-		symbmin = 10 * (coarse_srate / 14);
-		symbmin = (symbmin / 100) * 65536;
-		symbmin /= (intp->mclk / 100);
-
-		symb = (coarse_srate / 100) * 65536;
-		symb /= (intp->mclk / 100);
-	}
-
-	symbcomp = 13 * (coarse_srate / 10);
-		coarse_freq = (stv0900_read_reg(intp, CFR2) << 8)
-					| stv0900_read_reg(intp, CFR1);
-
-	if (symbcomp < intp->symbol_rate[demod])
-		coarse_srate = 0;
-	else {
-		stv0900_write_reg(intp, DMDISTATE, 0x1f);
-		stv0900_write_reg(intp, TMGCFG2, 0xc1);
-		stv0900_write_reg(intp, TMGTHRISE, 0x20);
-		stv0900_write_reg(intp, TMGTHFALL, 0x00);
-		stv0900_write_reg(intp, TMGCFG, 0xd2);
-		stv0900_write_bits(intp, CFR_AUTOSCAN, 0);
-		stv0900_write_reg(intp, AGC2REF, 0x38);
-
-		if (intp->chip_id >= 0x30)
-			stv0900_write_reg(intp, CARFREQ, 0x79);
-		else if (intp->chip_id >= 0x20)
-			stv0900_write_reg(intp, CARFREQ, 0x49);
-		else
-			stv0900_write_reg(intp, CARFREQ, 0xed);
-
-		stv0900_write_reg(intp, SFRUP1, (symbmax >> 8) & 0x7f);
-		stv0900_write_reg(intp, SFRUP0, (symbmax & 0xff));
-
-		stv0900_write_reg(intp, SFRLOW1, (symbmin >> 8) & 0x7f);
-		stv0900_write_reg(intp, SFRLOW0, (symbmin & 0xff));
-
-		stv0900_write_reg(intp, SFRINIT1, (symb >> 8) & 0xff);
-		stv0900_write_reg(intp, SFRINIT0, (symb & 0xff));
-
-		stv0900_write_reg(intp, DMDT0M, 0x20);
-		stv0900_write_reg(intp, CFRINIT1, (coarse_freq >> 8) & 0xff);
-		stv0900_write_reg(intp, CFRINIT0, coarse_freq  & 0xff);
-		stv0900_write_reg(intp, DMDISTATE, 0x15);
-	}
-
-	return coarse_srate;
-}
-
-static int stv0900_blind_search_algo(struct dvb_frontend *fe)
-{
-	struct stv0900_state *state = fe->demodulator_priv;
-	struct stv0900_internal *intp = 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,
-		agc2_th;
-	int	lock = FALSE,
-		coarse_fail = FALSE;
-	s32	demod_timeout = 500,
-		fec_timeout = 50,
-		fail_cpt,
-		i,
-		agc2_overflow;
-	u16	agc2_int;
-	u8	dstatus2;
-
-	dprintk("%s\n", __func__);
-
-	if (intp->chip_id < 0x20) {
-		k_ref_tmg_max = 233;
-		k_ref_tmg_min = 143;
-	} else {
-		k_ref_tmg_max = 110;
-		k_ref_tmg_min = 10;
-	}
-
-	if (intp->chip_id <= 0x20)
-		agc2_th = STV0900_BLIND_SEARCH_AGC2_TH;
-	else
-		agc2_th = STV0900_BLIND_SEARCH_AGC2_TH_CUT30;
-
-	agc2_int = stv0900_blind_check_agc2_min_level(intp, demod);
-
-	dprintk("%s agc2_int=%d agc2_th=%d \n", __func__, agc2_int, agc2_th);
-	if (agc2_int > agc2_th)
-		return FALSE;
-
-	if (intp->chip_id == 0x10)
-		stv0900_write_reg(intp, CORRELEXP, 0xaa);
-
-	if (intp->chip_id < 0x20)
-		stv0900_write_reg(intp, CARHDR, 0x55);
-	else
-		stv0900_write_reg(intp, CARHDR, 0x20);
-
-	if (intp->chip_id <= 0x20)
-		stv0900_write_reg(intp, CARCFG, 0xc4);
-	else
-		stv0900_write_reg(intp, CARCFG, 0x6);
-
-	stv0900_write_reg(intp, RTCS2, 0x44);
-
-	if (intp->chip_id >= 0x20) {
-		stv0900_write_reg(intp, EQUALCFG, 0x41);
-		stv0900_write_reg(intp, FFECFG, 0x41);
-		stv0900_write_reg(intp, VITSCALE, 0x82);
-		stv0900_write_reg(intp, VAVSRVIT, 0x0);
-	}
-
-	k_ref_tmg = k_ref_tmg_max;
-
-	do {
-		stv0900_write_reg(intp, KREFTMG, 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(intp,
-							demod,
-							demod_timeout);
-			} else
-				lock = FALSE;
-		} else {
-			fail_cpt = 0;
-			agc2_overflow = 0;
-
-			for (i = 0; i < 10; i++) {
-				agc2_int = (stv0900_read_reg(intp, AGC2I1) << 8)
-					| stv0900_read_reg(intp, AGC2I0);
-
-				if (agc2_int >= 0xff00)
-					agc2_overflow++;
-
-				dstatus2 = stv0900_read_reg(intp, DSTATUS2);
-
-				if (((dstatus2 & 0x1) == 0x1) &&
-						((dstatus2 >> 7) == 1))
-					fail_cpt++;
-			}
-
-			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 *intp,
-					enum fe_stv0900_demod_num demod)
-{
-	s32 vth_reg = VTH12;
-
-	dprintk("%s\n", __func__);
-
-	stv0900_write_reg(intp, vth_reg++, 0x96);
-	stv0900_write_reg(intp, vth_reg++, 0x64);
-	stv0900_write_reg(intp, vth_reg++, 0x36);
-	stv0900_write_reg(intp, vth_reg++, 0x23);
-	stv0900_write_reg(intp, vth_reg++, 0x1e);
-	stv0900_write_reg(intp, vth_reg++, 0x19);
-}
-
-static void stv0900_set_search_standard(struct stv0900_internal *intp,
-					enum fe_stv0900_demod_num demod)
-{
-
-	dprintk("%s\n", __func__);
-
-	switch (intp->srch_standard[demod]) {
-	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 (intp->srch_standard[demod]) {
-	case STV0900_SEARCH_DVBS1:
-	case STV0900_SEARCH_DSS:
-		stv0900_write_bits(intp, DVBS1_ENABLE, 1);
-		stv0900_write_bits(intp, DVBS2_ENABLE, 0);
-		stv0900_write_bits(intp, STOP_CLKVIT, 0);
-		stv0900_set_dvbs1_track_car_loop(intp,
-						demod,
-						intp->symbol_rate[demod]);
-		stv0900_write_reg(intp, CAR2CFG, 0x22);
-
-		stv0900_set_viterbi_acq(intp, demod);
-		stv0900_set_viterbi_standard(intp,
-					intp->srch_standard[demod],
-					intp->fec[demod], demod);
-
-		break;
-	case STV0900_SEARCH_DVBS2:
-		stv0900_write_bits(intp, DVBS1_ENABLE, 0);
-		stv0900_write_bits(intp, DVBS2_ENABLE, 1);
-		stv0900_write_bits(intp, STOP_CLKVIT, 1);
-		stv0900_write_reg(intp, ACLC, 0x1a);
-		stv0900_write_reg(intp, BCLC, 0x09);
-		if (intp->chip_id <= 0x20) /*cut 1.x and 2.0*/
-			stv0900_write_reg(intp, CAR2CFG, 0x26);
-		else
-			stv0900_write_reg(intp, CAR2CFG, 0x66);
-
-		if (intp->demod_mode != STV0900_SINGLE) {
-			if (intp->chip_id <= 0x11)
-				stv0900_stop_all_s2_modcod(intp, demod);
-			else
-				stv0900_activate_s2_modcod(intp, demod);
-
-		} else
-			stv0900_activate_s2_modcod_single(intp, demod);
-
-		stv0900_set_viterbi_tracq(intp, demod);
-
-		break;
-	case STV0900_AUTO_SEARCH:
-	default:
-		stv0900_write_bits(intp, DVBS1_ENABLE, 1);
-		stv0900_write_bits(intp, DVBS2_ENABLE, 1);
-		stv0900_write_bits(intp, STOP_CLKVIT, 0);
-		stv0900_write_reg(intp, ACLC, 0x1a);
-		stv0900_write_reg(intp, BCLC, 0x09);
-		stv0900_set_dvbs1_track_car_loop(intp,
-						demod,
-						intp->symbol_rate[demod]);
-		if (intp->chip_id <= 0x20) /*cut 1.x and 2.0*/
-			stv0900_write_reg(intp, CAR2CFG, 0x26);
-		else
-			stv0900_write_reg(intp, CAR2CFG, 0x66);
-
-		if (intp->demod_mode != STV0900_SINGLE) {
-			if (intp->chip_id <= 0x11)
-				stv0900_stop_all_s2_modcod(intp, demod);
-			else
-				stv0900_activate_s2_modcod(intp, demod);
-
-		} else
-			stv0900_activate_s2_modcod_single(intp, demod);
-
-		stv0900_set_viterbi_tracq(intp, demod);
-		stv0900_set_viterbi_standard(intp,
-						intp->srch_standard[demod],
-						intp->fec[demod], demod);
-
-		break;
-	}
-}
-
-enum fe_stv0900_signal_type stv0900_algo(struct dvb_frontend *fe)
-{
-	struct stv0900_state *state = fe->demodulator_priv;
-	struct stv0900_internal *intp = state->internal;
-	enum fe_stv0900_demod_num demod = state->demod;
-
-	s32 demod_timeout = 500, fec_timeout = 50;
-	s32 aq_power, agc1_power, i;
-
-	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("%s\n", __func__);
-
-	algo = intp->srch_algo[demod];
-	stv0900_write_bits(intp, RST_HWARE, 1);
-	stv0900_write_reg(intp, DMDISTATE, 0x5c);
-	if (intp->chip_id >= 0x20) {
-		if (intp->symbol_rate[demod] > 5000000)
-			stv0900_write_reg(intp, CORRELABS, 0x9e);
-		else
-			stv0900_write_reg(intp, CORRELABS, 0x82);
-	} else
-		stv0900_write_reg(intp, CORRELABS, 0x88);
-
-	stv0900_get_lock_timeout(&demod_timeout, &fec_timeout,
-				intp->symbol_rate[demod],
-				intp->srch_algo[demod]);
-
-	if (intp->srch_algo[demod] == STV0900_BLIND_SEARCH) {
-		intp->bw[demod] = 2 * 36000000;
-
-		stv0900_write_reg(intp, TMGCFG2, 0xc0);
-		stv0900_write_reg(intp, CORRELMANT, 0x70);
-
-		stv0900_set_symbol_rate(intp, intp->mclk, 1000000, demod);
-	} else {
-		stv0900_write_reg(intp, DMDT0M, 0x20);
-		stv0900_write_reg(intp, TMGCFG, 0xd2);
-
-		if (intp->symbol_rate[demod] < 2000000)
-			stv0900_write_reg(intp, CORRELMANT, 0x63);
-		else
-			stv0900_write_reg(intp, CORRELMANT, 0x70);
-
-		stv0900_write_reg(intp, AGC2REF, 0x38);
-
-		intp->bw[demod] =
-				stv0900_carrier_width(intp->symbol_rate[demod],
-								intp->rolloff);
-		if (intp->chip_id >= 0x20) {
-			stv0900_write_reg(intp, KREFTMG, 0x5a);
-
-			if (intp->srch_algo[demod] == STV0900_COLD_START) {
-				intp->bw[demod] += 10000000;
-				intp->bw[demod] *= 15;
-				intp->bw[demod] /= 10;
-			} else if (intp->srch_algo[demod] == STV0900_WARM_START)
-				intp->bw[demod] += 10000000;
-
-		} else {
-			stv0900_write_reg(intp, KREFTMG, 0xc1);
-			intp->bw[demod] += 10000000;
-			intp->bw[demod] *= 15;
-			intp->bw[demod] /= 10;
-		}
-
-		stv0900_write_reg(intp, TMGCFG2, 0xc1);
-
-		stv0900_set_symbol_rate(intp, intp->mclk,
-					intp->symbol_rate[demod], demod);
-		stv0900_set_max_symbol_rate(intp, intp->mclk,
-					intp->symbol_rate[demod], demod);
-		stv0900_set_min_symbol_rate(intp, intp->mclk,
-					intp->symbol_rate[demod], demod);
-		if (intp->symbol_rate[demod] >= 10000000)
-			low_sr = FALSE;
-		else
-			low_sr = TRUE;
-
-	}
-
-	if (intp->tuner_type[demod] == 3)
-		stv0900_set_tuner_auto(intp, intp->freq[demod],
-				intp->bw[demod], demod);
-	else
-		stv0900_set_tuner(fe, intp->freq[demod], intp->bw[demod]);
-
-	agc1_power = MAKEWORD(stv0900_get_bits(intp, AGCIQ_VALUE1),
-				stv0900_get_bits(intp, AGCIQ_VALUE0));
-
-	aq_power = 0;
-
-	if (agc1_power == 0) {
-		for (i = 0; i < 5; i++)
-			aq_power += (stv0900_get_bits(intp, POWER_I) +
-					stv0900_get_bits(intp, POWER_Q)) / 2;
-
-		aq_power /= 5;
-	}
-
-	if ((agc1_power == 0) && (aq_power < IQPOWER_THRESHOLD)) {
-		intp->result[demod].locked = FALSE;
-		signal_type = STV0900_NOAGC1;
-		dprintk("%s: NO AGC1, POWERI, POWERQ\n", __func__);
-	} else {
-		stv0900_write_bits(intp, SPECINV_CONTROL,
-					intp->srch_iq_inv[demod]);
-		if (intp->chip_id <= 0x20) /*cut 2.0*/
-			stv0900_write_bits(intp, MANUALSX_ROLLOFF, 1);
-		else /*cut 3.0*/
-			stv0900_write_bits(intp, MANUALS2_ROLLOFF, 1);
-
-		stv0900_set_search_standard(intp, demod);
-
-		if (intp->srch_algo[demod] != STV0900_BLIND_SEARCH)
-			stv0900_start_search(intp, demod);
-	}
-
-	if (signal_type == STV0900_NOAGC1)
-		return signal_type;
-
-	if (intp->chip_id == 0x12) {
-		stv0900_write_bits(intp, RST_HWARE, 0);
-		msleep(3);
-		stv0900_write_bits(intp, RST_HWARE, 1);
-		stv0900_write_bits(intp, RST_HWARE, 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(intp, demod, demod_timeout);
-
-	if ((lock == FALSE) && (algo == STV0900_COLD_START)) {
-		if (low_sr == FALSE) {
-			if (stv0900_check_timing_lock(intp, demod) == TRUE)
-				lock = stv0900_sw_algo(intp, demod);
-		}
-	}
-
-	if (lock == TRUE)
-		signal_type = stv0900_get_signal_params(fe);
-
-	if ((lock == TRUE) && (signal_type == STV0900_RANGEOK)) {
-		stv0900_track_optimization(fe);
-		if (intp->chip_id <= 0x11) {
-			if ((stv0900_get_standard(fe, 0) ==
-						STV0900_DVBS1_STANDARD) &&
-			   (stv0900_get_standard(fe, 1) ==
-						STV0900_DVBS1_STANDARD)) {
-				msleep(20);
-				stv0900_write_bits(intp, RST_HWARE, 0);
-			} else {
-				stv0900_write_bits(intp, RST_HWARE, 0);
-				msleep(3);
-				stv0900_write_bits(intp, RST_HWARE, 1);
-				stv0900_write_bits(intp, RST_HWARE, 0);
-			}
-
-		} else if (intp->chip_id >= 0x20) {
-			stv0900_write_bits(intp, RST_HWARE, 0);
-			msleep(3);
-			stv0900_write_bits(intp, RST_HWARE, 1);
-			stv0900_write_bits(intp, RST_HWARE, 0);
-		}
-
-		if (stv0900_wait_for_lock(intp, demod,
-					fec_timeout, fec_timeout) == TRUE) {
-			lock = TRUE;
-			intp->result[demod].locked = TRUE;
-			if (intp->result[demod].standard ==
-						STV0900_DVBS2_STANDARD) {
-				stv0900_set_dvbs2_rolloff(intp, demod);
-				stv0900_write_bits(intp, RESET_UPKO_COUNT, 1);
-				stv0900_write_bits(intp, RESET_UPKO_COUNT, 0);
-				stv0900_write_reg(intp, ERRCTRL1, 0x67);
-			} else {
-				stv0900_write_reg(intp, ERRCTRL1, 0x75);
-			}
-
-			stv0900_write_reg(intp, FBERCPT4, 0);
-			stv0900_write_reg(intp, ERRCTRL2, 0xc1);
-		} else {
-			lock = FALSE;
-			signal_type = STV0900_NODATA;
-			no_signal = stv0900_check_signal_presence(intp, demod);
-
-				intp->result[demod].locked = FALSE;
-		}
-	}
-
-	if ((signal_type != STV0900_NODATA) || (no_signal != FALSE))
-		return signal_type;
-
-	if (intp->chip_id > 0x11) {
-		intp->result[demod].locked = FALSE;
-		return signal_type;
-	}
-
-	if ((stv0900_get_bits(intp, HEADER_MODE) == STV0900_DVBS_FOUND) &&
-	   (intp->srch_iq_inv[demod] <= STV0900_IQ_AUTO_NORMAL_FIRST))
-		signal_type = stv0900_dvbs1_acq_workaround(fe);
-
-	return signal_type;
-}
-
diff --git a/drivers/media/dvb/frontends/stv090x.c b/drivers/media/dvb/frontends/stv090x.c
deleted file mode 100644
index ea86a56..0000000
--- a/drivers/media/dvb/frontends/stv090x.c
+++ /dev/null
@@ -1,4823 +0,0 @@
-/*
-	STV0900/0903 Multistandard Broadcast Frontend driver
-	Copyright (C) Manu Abraham <abraham.manu@gmail.com>
-
-	Copyright (C) ST Microelectronics
-
-	This program is free software; you can redistribute it and/or modify
-	it under the terms of the 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/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/mutex.h>
-
-#include <linux/dvb/frontend.h>
-#include "dvb_frontend.h"
-
-#include "stv6110x.h" /* for demodulator internal modes */
-
-#include "stv090x_reg.h"
-#include "stv090x.h"
-#include "stv090x_priv.h"
-
-static unsigned int verbose;
-module_param(verbose, int, 0644);
-
-/* internal params node */
-struct stv090x_dev {
-	/* pointer for internal params, one for each pair of demods */
-	struct stv090x_internal		*internal;
-	struct stv090x_dev		*next_dev;
-};
-
-/* first internal params */
-static struct stv090x_dev *stv090x_first_dev;
-
-/* find chip by i2c adapter and i2c address */
-static struct stv090x_dev *find_dev(struct i2c_adapter *i2c_adap,
-					u8 i2c_addr)
-{
-	struct stv090x_dev *temp_dev = stv090x_first_dev;
-
-	/*
-	 Search of the last stv0900 chip or
-	 find it by i2c adapter and i2c address */
-	while ((temp_dev != NULL) &&
-		((temp_dev->internal->i2c_adap != i2c_adap) ||
-		(temp_dev->internal->i2c_addr != i2c_addr))) {
-
-		temp_dev = temp_dev->next_dev;
-	}
-
-	return temp_dev;
-}
-
-/* deallocating chip */
-static void remove_dev(struct stv090x_internal *internal)
-{
-	struct stv090x_dev *prev_dev = stv090x_first_dev;
-	struct stv090x_dev *del_dev = find_dev(internal->i2c_adap,
-						internal->i2c_addr);
-
-	if (del_dev != NULL) {
-		if (del_dev == stv090x_first_dev) {
-			stv090x_first_dev = del_dev->next_dev;
-		} else {
-			while (prev_dev->next_dev != del_dev)
-				prev_dev = prev_dev->next_dev;
-
-			prev_dev->next_dev = del_dev->next_dev;
-		}
-
-		kfree(del_dev);
-	}
-}
-
-/* allocating new chip */
-static struct stv090x_dev *append_internal(struct stv090x_internal *internal)
-{
-	struct stv090x_dev *new_dev;
-	struct stv090x_dev *temp_dev;
-
-	new_dev = kmalloc(sizeof(struct stv090x_dev), GFP_KERNEL);
-	if (new_dev != NULL) {
-		new_dev->internal = internal;
-		new_dev->next_dev = NULL;
-
-		/* append to list */
-		if (stv090x_first_dev == NULL) {
-			stv090x_first_dev = new_dev;
-		} else {
-			temp_dev = stv090x_first_dev;
-			while (temp_dev->next_dev != NULL)
-				temp_dev = temp_dev->next_dev;
-
-			temp_dev->next_dev = new_dev;
-		}
-	}
-
-	return new_dev;
-}
-
-
-/* DVBS1 and DSS C/N Lookup table */
-static const struct stv090x_tab stv090x_s1cn_tab[] = {
-	{   0, 8917 }, /*  0.0dB */
-	{   5, 8801 }, /*  0.5dB */
-	{  10, 8667 }, /*  1.0dB */
-	{  15, 8522 }, /*  1.5dB */
-	{  20, 8355 }, /*  2.0dB */
-	{  25, 8175 }, /*  2.5dB */
-	{  30, 7979 }, /*  3.0dB */
-	{  35, 7763 }, /*  3.5dB */
-	{  40, 7530 }, /*  4.0dB */
-	{  45, 7282 }, /*  4.5dB */
-	{  50, 7026 }, /*  5.0dB */
-	{  55, 6781 }, /*  5.5dB */
-	{  60, 6514 }, /*  6.0dB */
-	{  65, 6241 }, /*  6.5dB */
-	{  70, 5965 }, /*  7.0dB */
-	{  75, 5690 }, /*  7.5dB */
-	{  80, 5424 }, /*  8.0dB */
-	{  85, 5161 }, /*  8.5dB */
-	{  90, 4902 }, /*  9.0dB */
-	{  95, 4654 }, /*  9.5dB */
-	{ 100, 4417 }, /* 10.0dB */
-	{ 105, 4186 }, /* 10.5dB */
-	{ 110, 3968 }, /* 11.0dB */
-	{ 115, 3757 }, /* 11.5dB */
-	{ 120, 3558 }, /* 12.0dB */
-	{ 125, 3366 }, /* 12.5dB */
-	{ 130, 3185 }, /* 13.0dB */
-	{ 135, 3012 }, /* 13.5dB */
-	{ 140, 2850 }, /* 14.0dB */
-	{ 145, 2698 }, /* 14.5dB */
-	{ 150, 2550 }, /* 15.0dB */
-	{ 160, 2283 }, /* 16.0dB */
-	{ 170, 2042 }, /* 17.0dB */
-	{ 180, 1827 }, /* 18.0dB */
-	{ 190, 1636 }, /* 19.0dB */
-	{ 200, 1466 }, /* 20.0dB */
-	{ 210, 1315 }, /* 21.0dB */
-	{ 220, 1181 }, /* 22.0dB */
-	{ 230, 1064 }, /* 23.0dB */
-	{ 240,	960 }, /* 24.0dB */
-	{ 250,	869 }, /* 25.0dB */
-	{ 260,	792 }, /* 26.0dB */
-	{ 270,	724 }, /* 27.0dB */
-	{ 280,	665 }, /* 28.0dB */
-	{ 290,	616 }, /* 29.0dB */
-	{ 300,	573 }, /* 30.0dB */
-	{ 310,	537 }, /* 31.0dB */
-	{ 320,	507 }, /* 32.0dB */
-	{ 330,	483 }, /* 33.0dB */
-	{ 400,	398 }, /* 40.0dB */
-	{ 450,	381 }, /* 45.0dB */
-	{ 500,	377 }  /* 50.0dB */
-};
-
-/* DVBS2 C/N Lookup table */
-static const struct stv090x_tab stv090x_s2cn_tab[] = {
-	{ -30, 13348 }, /* -3.0dB */
-	{ -20, 12640 }, /* -2d.0B */
-	{ -10, 11883 }, /* -1.0dB */
-	{   0, 11101 }, /* -0.0dB */
-	{   5, 10718 }, /*  0.5dB */
-	{  10, 10339 }, /*  1.0dB */
-	{  15,  9947 }, /*  1.5dB */
-	{  20,  9552 }, /*  2.0dB */
-	{  25,  9183 }, /*  2.5dB */
-	{  30,  8799 }, /*  3.0dB */
-	{  35,  8422 }, /*  3.5dB */
-	{  40,  8062 }, /*  4.0dB */
-	{  45,  7707 }, /*  4.5dB */
-	{  50,  7353 }, /*  5.0dB */
-	{  55,  7025 }, /*  5.5dB */
-	{  60,  6684 }, /*  6.0dB */
-	{  65,  6331 }, /*  6.5dB */
-	{  70,  6036 }, /*  7.0dB */
-	{  75,  5727 }, /*  7.5dB */
-	{  80,  5437 }, /*  8.0dB */
-	{  85,  5164 }, /*  8.5dB */
-	{  90,  4902 }, /*  9.0dB */
-	{  95,  4653 }, /*  9.5dB */
-	{ 100,  4408 }, /* 10.0dB */
-	{ 105,  4187 }, /* 10.5dB */
-	{ 110,  3961 }, /* 11.0dB */
-	{ 115,  3751 }, /* 11.5dB */
-	{ 120,  3558 }, /* 12.0dB */
-	{ 125,  3368 }, /* 12.5dB */
-	{ 130,  3191 }, /* 13.0dB */
-	{ 135,  3017 }, /* 13.5dB */
-	{ 140,  2862 }, /* 14.0dB */
-	{ 145,  2710 }, /* 14.5dB */
-	{ 150,  2565 }, /* 15.0dB */
-	{ 160,  2300 }, /* 16.0dB */
-	{ 170,  2058 }, /* 17.0dB */
-	{ 180,  1849 }, /* 18.0dB */
-	{ 190,  1663 }, /* 19.0dB */
-	{ 200,  1495 }, /* 20.0dB */
-	{ 210,  1349 }, /* 21.0dB */
-	{ 220,  1222 }, /* 22.0dB */
-	{ 230,  1110 }, /* 23.0dB */
-	{ 240,  1011 }, /* 24.0dB */
-	{ 250,   925 }, /* 25.0dB */
-	{ 260,   853 }, /* 26.0dB */
-	{ 270,   789 }, /* 27.0dB */
-	{ 280,   734 }, /* 28.0dB */
-	{ 290,   690 }, /* 29.0dB */
-	{ 300,   650 }, /* 30.0dB */
-	{ 310,   619 }, /* 31.0dB */
-	{ 320,   593 }, /* 32.0dB */
-	{ 330,   571 }, /* 33.0dB */
-	{ 400,   498 }, /* 40.0dB */
-	{ 450,	 484 }, /* 45.0dB */
-	{ 500,	 481 }	/* 50.0dB */
-};
-
-/* RF level C/N lookup table */
-static const struct stv090x_tab stv090x_rf_tab[] = {
-	{  -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, 0x07aa }	 /* -70dBm */
-};
-
-
-static struct stv090x_reg stv0900_initval[] = {
-
-	{ STV090x_OUTCFG,		0x00 },
-	{ STV090x_MODECFG,		0xff },
-	{ STV090x_AGCRF1CFG,		0x11 },
-	{ STV090x_AGCRF2CFG,		0x13 },
-	{ STV090x_TSGENERAL1X,		0x14 },
-	{ STV090x_TSTTNR2,		0x21 },
-	{ STV090x_TSTTNR4,		0x21 },
-	{ STV090x_P2_DISTXCTL,		0x22 },
-	{ STV090x_P2_F22TX,		0xc0 },
-	{ STV090x_P2_F22RX,		0xc0 },
-	{ STV090x_P2_DISRXCTL,		0x00 },
-	{ STV090x_P2_DMDCFGMD,		0xF9 },
-	{ STV090x_P2_DEMOD,		0x08 },
-	{ STV090x_P2_DMDCFG3,		0xc4 },
-	{ STV090x_P2_CARFREQ,		0xed },
-	{ STV090x_P2_LDT,		0xd0 },
-	{ STV090x_P2_LDT2,		0xb8 },
-	{ STV090x_P2_TMGCFG,		0xd2 },
-	{ STV090x_P2_TMGTHRISE,		0x20 },
-	{ STV090x_P1_TMGCFG,		0xd2 },
-
-	{ STV090x_P2_TMGTHFALL,		0x00 },
-	{ STV090x_P2_FECSPY,		0x88 },
-	{ STV090x_P2_FSPYDATA,		0x3a },
-	{ STV090x_P2_FBERCPT4,		0x00 },
-	{ STV090x_P2_FSPYBER,		0x10 },
-	{ STV090x_P2_ERRCTRL1,		0x35 },
-	{ STV090x_P2_ERRCTRL2,		0xc1 },
-	{ STV090x_P2_CFRICFG,		0xf8 },
-	{ STV090x_P2_NOSCFG,		0x1c },
-	{ STV090x_P2_DMDTOM,		0x20 },
-	{ STV090x_P2_CORRELMANT,	0x70 },
-	{ STV090x_P2_CORRELABS,		0x88 },
-	{ STV090x_P2_AGC2O,		0x5b },
-	{ STV090x_P2_AGC2REF,		0x38 },
-	{ STV090x_P2_CARCFG,		0xe4 },
-	{ STV090x_P2_ACLC,		0x1A },
-	{ STV090x_P2_BCLC,		0x09 },
-	{ STV090x_P2_CARHDR,		0x08 },
-	{ STV090x_P2_KREFTMG,		0xc1 },
-	{ STV090x_P2_SFRUPRATIO,	0xf0 },
-	{ STV090x_P2_SFRLOWRATIO,	0x70 },
-	{ STV090x_P2_SFRSTEP,		0x58 },
-	{ STV090x_P2_TMGCFG2,		0x01 },
-	{ STV090x_P2_CAR2CFG,		0x26 },
-	{ STV090x_P2_BCLC2S2Q,		0x86 },
-	{ STV090x_P2_BCLC2S28,		0x86 },
-	{ STV090x_P2_SMAPCOEF7,		0x77 },
-	{ STV090x_P2_SMAPCOEF6,		0x85 },
-	{ STV090x_P2_SMAPCOEF5,		0x77 },
-	{ STV090x_P2_TSCFGL,		0x20 },
-	{ STV090x_P2_DMDCFG2,		0x3b },
-	{ STV090x_P2_MODCODLST0,	0xff },
-	{ STV090x_P2_MODCODLST1,	0xff },
-	{ STV090x_P2_MODCODLST2,	0xff },
-	{ STV090x_P2_MODCODLST3,	0xff },
-	{ STV090x_P2_MODCODLST4,	0xff },
-	{ STV090x_P2_MODCODLST5,	0xff },
-	{ STV090x_P2_MODCODLST6,	0xff },
-	{ STV090x_P2_MODCODLST7,	0xcc },
-	{ STV090x_P2_MODCODLST8,	0xcc },
-	{ STV090x_P2_MODCODLST9,	0xcc },
-	{ STV090x_P2_MODCODLSTA,	0xcc },
-	{ STV090x_P2_MODCODLSTB,	0xcc },
-	{ STV090x_P2_MODCODLSTC,	0xcc },
-	{ STV090x_P2_MODCODLSTD,	0xcc },
-	{ STV090x_P2_MODCODLSTE,	0xcc },
-	{ STV090x_P2_MODCODLSTF,	0xcf },
-	{ STV090x_P1_DISTXCTL,		0x22 },
-	{ STV090x_P1_F22TX,		0xc0 },
-	{ STV090x_P1_F22RX,		0xc0 },
-	{ STV090x_P1_DISRXCTL,		0x00 },
-	{ STV090x_P1_DMDCFGMD,		0xf9 },
-	{ STV090x_P1_DEMOD,		0x08 },
-	{ STV090x_P1_DMDCFG3,		0xc4 },
-	{ STV090x_P1_DMDTOM,		0x20 },
-	{ STV090x_P1_CARFREQ,		0xed },
-	{ STV090x_P1_LDT,		0xd0 },
-	{ STV090x_P1_LDT2,		0xb8 },
-	{ STV090x_P1_TMGCFG,		0xd2 },
-	{ STV090x_P1_TMGTHRISE,		0x20 },
-	{ STV090x_P1_TMGTHFALL,		0x00 },
-	{ STV090x_P1_SFRUPRATIO,	0xf0 },
-	{ STV090x_P1_SFRLOWRATIO,	0x70 },
-	{ STV090x_P1_TSCFGL,		0x20 },
-	{ STV090x_P1_FECSPY,		0x88 },
-	{ STV090x_P1_FSPYDATA,		0x3a },
-	{ STV090x_P1_FBERCPT4,		0x00 },
-	{ STV090x_P1_FSPYBER,		0x10 },
-	{ STV090x_P1_ERRCTRL1,		0x35 },
-	{ STV090x_P1_ERRCTRL2,		0xc1 },
-	{ STV090x_P1_CFRICFG,		0xf8 },
-	{ STV090x_P1_NOSCFG,		0x1c },
-	{ STV090x_P1_CORRELMANT,	0x70 },
-	{ STV090x_P1_CORRELABS,		0x88 },
-	{ STV090x_P1_AGC2O,		0x5b },
-	{ STV090x_P1_AGC2REF,		0x38 },
-	{ STV090x_P1_CARCFG,		0xe4 },
-	{ STV090x_P1_ACLC,		0x1A },
-	{ STV090x_P1_BCLC,		0x09 },
-	{ STV090x_P1_CARHDR,		0x08 },
-	{ STV090x_P1_KREFTMG,		0xc1 },
-	{ STV090x_P1_SFRSTEP,		0x58 },
-	{ STV090x_P1_TMGCFG2,		0x01 },
-	{ STV090x_P1_CAR2CFG,		0x26 },
-	{ STV090x_P1_BCLC2S2Q,		0x86 },
-	{ STV090x_P1_BCLC2S28,		0x86 },
-	{ STV090x_P1_SMAPCOEF7,		0x77 },
-	{ STV090x_P1_SMAPCOEF6,		0x85 },
-	{ STV090x_P1_SMAPCOEF5,		0x77 },
-	{ STV090x_P1_DMDCFG2,		0x3b },
-	{ STV090x_P1_MODCODLST0,	0xff },
-	{ STV090x_P1_MODCODLST1,	0xff },
-	{ STV090x_P1_MODCODLST2,	0xff },
-	{ STV090x_P1_MODCODLST3,	0xff },
-	{ STV090x_P1_MODCODLST4,	0xff },
-	{ STV090x_P1_MODCODLST5,	0xff },
-	{ STV090x_P1_MODCODLST6,	0xff },
-	{ STV090x_P1_MODCODLST7,	0xcc },
-	{ STV090x_P1_MODCODLST8,	0xcc },
-	{ STV090x_P1_MODCODLST9,	0xcc },
-	{ STV090x_P1_MODCODLSTA,	0xcc },
-	{ STV090x_P1_MODCODLSTB,	0xcc },
-	{ STV090x_P1_MODCODLSTC,	0xcc },
-	{ STV090x_P1_MODCODLSTD,	0xcc },
-	{ STV090x_P1_MODCODLSTE,	0xcc },
-	{ STV090x_P1_MODCODLSTF,	0xcf },
-	{ STV090x_GENCFG,		0x1d },
-	{ STV090x_NBITER_NF4,		0x37 },
-	{ STV090x_NBITER_NF5,		0x29 },
-	{ STV090x_NBITER_NF6,		0x37 },
-	{ STV090x_NBITER_NF7,		0x33 },
-	{ STV090x_NBITER_NF8,		0x31 },
-	{ STV090x_NBITER_NF9,		0x2f },
-	{ STV090x_NBITER_NF10,		0x39 },
-	{ STV090x_NBITER_NF11,		0x3a },
-	{ STV090x_NBITER_NF12,		0x29 },
-	{ STV090x_NBITER_NF13,		0x37 },
-	{ STV090x_NBITER_NF14,		0x33 },
-	{ STV090x_NBITER_NF15,		0x2f },
-	{ STV090x_NBITER_NF16,		0x39 },
-	{ STV090x_NBITER_NF17,		0x3a },
-	{ STV090x_NBITERNOERR,		0x04 },
-	{ STV090x_GAINLLR_NF4,		0x0C },
-	{ STV090x_GAINLLR_NF5,		0x0F },
-	{ STV090x_GAINLLR_NF6,		0x11 },
-	{ STV090x_GAINLLR_NF7,		0x14 },
-	{ STV090x_GAINLLR_NF8,		0x17 },
-	{ STV090x_GAINLLR_NF9,		0x19 },
-	{ STV090x_GAINLLR_NF10,		0x20 },
-	{ STV090x_GAINLLR_NF11,		0x21 },
-	{ STV090x_GAINLLR_NF12,		0x0D },
-	{ STV090x_GAINLLR_NF13,		0x0F },
-	{ STV090x_GAINLLR_NF14,		0x13 },
-	{ STV090x_GAINLLR_NF15,		0x1A },
-	{ STV090x_GAINLLR_NF16,		0x1F },
-	{ STV090x_GAINLLR_NF17,		0x21 },
-	{ STV090x_RCCFGH,		0x20 },
-	{ STV090x_P1_FECM,		0x01 }, /* disable DSS modes */
-	{ STV090x_P2_FECM,		0x01 }, /* disable DSS modes */
-	{ STV090x_P1_PRVIT,		0x2F }, /* disable PR 6/7 */
-	{ STV090x_P2_PRVIT,		0x2F }, /* disable PR 6/7 */
-};
-
-static struct stv090x_reg stv0903_initval[] = {
-	{ STV090x_OUTCFG,		0x00 },
-	{ STV090x_AGCRF1CFG,		0x11 },
-	{ STV090x_STOPCLK1,		0x48 },
-	{ STV090x_STOPCLK2,		0x14 },
-	{ STV090x_TSTTNR1,		0x27 },
-	{ STV090x_TSTTNR2,		0x21 },
-	{ STV090x_P1_DISTXCTL,		0x22 },
-	{ STV090x_P1_F22TX,		0xc0 },
-	{ STV090x_P1_F22RX,		0xc0 },
-	{ STV090x_P1_DISRXCTL,		0x00 },
-	{ STV090x_P1_DMDCFGMD,		0xF9 },
-	{ STV090x_P1_DEMOD,		0x08 },
-	{ STV090x_P1_DMDCFG3,		0xc4 },
-	{ STV090x_P1_CARFREQ,		0xed },
-	{ STV090x_P1_TNRCFG2,		0x82 },
-	{ STV090x_P1_LDT,		0xd0 },
-	{ STV090x_P1_LDT2,		0xb8 },
-	{ STV090x_P1_TMGCFG,		0xd2 },
-	{ STV090x_P1_TMGTHRISE,		0x20 },
-	{ STV090x_P1_TMGTHFALL,		0x00 },
-	{ STV090x_P1_SFRUPRATIO,	0xf0 },
-	{ STV090x_P1_SFRLOWRATIO,	0x70 },
-	{ STV090x_P1_TSCFGL,		0x20 },
-	{ STV090x_P1_FECSPY,		0x88 },
-	{ STV090x_P1_FSPYDATA,		0x3a },
-	{ STV090x_P1_FBERCPT4,		0x00 },
-	{ STV090x_P1_FSPYBER,		0x10 },
-	{ STV090x_P1_ERRCTRL1,		0x35 },
-	{ STV090x_P1_ERRCTRL2,		0xc1 },
-	{ STV090x_P1_CFRICFG,		0xf8 },
-	{ STV090x_P1_NOSCFG,		0x1c },
-	{ STV090x_P1_DMDTOM,		0x20 },
-	{ STV090x_P1_CORRELMANT,	0x70 },
-	{ STV090x_P1_CORRELABS,		0x88 },
-	{ STV090x_P1_AGC2O,		0x5b },
-	{ STV090x_P1_AGC2REF,		0x38 },
-	{ STV090x_P1_CARCFG,		0xe4 },
-	{ STV090x_P1_ACLC,		0x1A },
-	{ STV090x_P1_BCLC,		0x09 },
-	{ STV090x_P1_CARHDR,		0x08 },
-	{ STV090x_P1_KREFTMG,		0xc1 },
-	{ STV090x_P1_SFRSTEP,		0x58 },
-	{ STV090x_P1_TMGCFG2,		0x01 },
-	{ STV090x_P1_CAR2CFG,		0x26 },
-	{ STV090x_P1_BCLC2S2Q,		0x86 },
-	{ STV090x_P1_BCLC2S28,		0x86 },
-	{ STV090x_P1_SMAPCOEF7,		0x77 },
-	{ STV090x_P1_SMAPCOEF6,		0x85 },
-	{ STV090x_P1_SMAPCOEF5,		0x77 },
-	{ STV090x_P1_DMDCFG2,		0x3b },
-	{ STV090x_P1_MODCODLST0,	0xff },
-	{ STV090x_P1_MODCODLST1,	0xff },
-	{ STV090x_P1_MODCODLST2,	0xff },
-	{ STV090x_P1_MODCODLST3,	0xff },
-	{ STV090x_P1_MODCODLST4,	0xff },
-	{ STV090x_P1_MODCODLST5,	0xff },
-	{ STV090x_P1_MODCODLST6,	0xff },
-	{ STV090x_P1_MODCODLST7,	0xcc },
-	{ STV090x_P1_MODCODLST8,	0xcc },
-	{ STV090x_P1_MODCODLST9,	0xcc },
-	{ STV090x_P1_MODCODLSTA,	0xcc },
-	{ STV090x_P1_MODCODLSTB,	0xcc },
-	{ STV090x_P1_MODCODLSTC,	0xcc },
-	{ STV090x_P1_MODCODLSTD,	0xcc },
-	{ STV090x_P1_MODCODLSTE,	0xcc },
-	{ STV090x_P1_MODCODLSTF,	0xcf },
-	{ STV090x_GENCFG,		0x1c },
-	{ STV090x_NBITER_NF4,		0x37 },
-	{ STV090x_NBITER_NF5,		0x29 },
-	{ STV090x_NBITER_NF6,		0x37 },
-	{ STV090x_NBITER_NF7,		0x33 },
-	{ STV090x_NBITER_NF8,		0x31 },
-	{ STV090x_NBITER_NF9,		0x2f },
-	{ STV090x_NBITER_NF10,		0x39 },
-	{ STV090x_NBITER_NF11,		0x3a },
-	{ STV090x_NBITER_NF12,		0x29 },
-	{ STV090x_NBITER_NF13,		0x37 },
-	{ STV090x_NBITER_NF14,		0x33 },
-	{ STV090x_NBITER_NF15,		0x2f },
-	{ STV090x_NBITER_NF16,		0x39 },
-	{ STV090x_NBITER_NF17,		0x3a },
-	{ STV090x_NBITERNOERR,		0x04 },
-	{ STV090x_GAINLLR_NF4,		0x0C },
-	{ STV090x_GAINLLR_NF5,		0x0F },
-	{ STV090x_GAINLLR_NF6,		0x11 },
-	{ STV090x_GAINLLR_NF7,		0x14 },
-	{ STV090x_GAINLLR_NF8,		0x17 },
-	{ STV090x_GAINLLR_NF9,		0x19 },
-	{ STV090x_GAINLLR_NF10,		0x20 },
-	{ STV090x_GAINLLR_NF11,		0x21 },
-	{ STV090x_GAINLLR_NF12,		0x0D },
-	{ STV090x_GAINLLR_NF13,		0x0F },
-	{ STV090x_GAINLLR_NF14,		0x13 },
-	{ STV090x_GAINLLR_NF15,		0x1A },
-	{ STV090x_GAINLLR_NF16,		0x1F },
-	{ STV090x_GAINLLR_NF17,		0x21 },
-	{ STV090x_RCCFGH,		0x20 },
-	{ STV090x_P1_FECM,		0x01 }, /*disable the DSS mode */
-	{ STV090x_P1_PRVIT,		0x2f }  /*disable puncture rate 6/7*/
-};
-
-static struct stv090x_reg stv0900_cut20_val[] = {
-
-	{ STV090x_P2_DMDCFG3,		0xe8 },
-	{ STV090x_P2_DMDCFG4,		0x10 },
-	{ STV090x_P2_CARFREQ,		0x38 },
-	{ STV090x_P2_CARHDR,		0x20 },
-	{ STV090x_P2_KREFTMG,		0x5a },
-	{ STV090x_P2_SMAPCOEF7,		0x06 },
-	{ STV090x_P2_SMAPCOEF6,		0x00 },
-	{ STV090x_P2_SMAPCOEF5,		0x04 },
-	{ STV090x_P2_NOSCFG,		0x0c },
-	{ STV090x_P1_DMDCFG3,		0xe8 },
-	{ STV090x_P1_DMDCFG4,		0x10 },
-	{ STV090x_P1_CARFREQ,		0x38 },
-	{ STV090x_P1_CARHDR,		0x20 },
-	{ STV090x_P1_KREFTMG,		0x5a },
-	{ STV090x_P1_SMAPCOEF7,		0x06 },
-	{ STV090x_P1_SMAPCOEF6,		0x00 },
-	{ STV090x_P1_SMAPCOEF5,		0x04 },
-	{ STV090x_P1_NOSCFG,		0x0c },
-	{ STV090x_GAINLLR_NF4,		0x21 },
-	{ STV090x_GAINLLR_NF5,		0x21 },
-	{ STV090x_GAINLLR_NF6,		0x20 },
-	{ STV090x_GAINLLR_NF7,		0x1F },
-	{ STV090x_GAINLLR_NF8,		0x1E },
-	{ STV090x_GAINLLR_NF9,		0x1E },
-	{ STV090x_GAINLLR_NF10,		0x1D },
-	{ STV090x_GAINLLR_NF11,		0x1B },
-	{ STV090x_GAINLLR_NF12,		0x20 },
-	{ STV090x_GAINLLR_NF13,		0x20 },
-	{ STV090x_GAINLLR_NF14,		0x20 },
-	{ STV090x_GAINLLR_NF15,		0x20 },
-	{ STV090x_GAINLLR_NF16,		0x20 },
-	{ STV090x_GAINLLR_NF17,		0x21 },
-};
-
-static struct stv090x_reg stv0903_cut20_val[] = {
-	{ STV090x_P1_DMDCFG3,		0xe8 },
-	{ STV090x_P1_DMDCFG4,		0x10 },
-	{ STV090x_P1_CARFREQ,		0x38 },
-	{ STV090x_P1_CARHDR,		0x20 },
-	{ STV090x_P1_KREFTMG,		0x5a },
-	{ STV090x_P1_SMAPCOEF7,		0x06 },
-	{ STV090x_P1_SMAPCOEF6,		0x00 },
-	{ STV090x_P1_SMAPCOEF5,		0x04 },
-	{ STV090x_P1_NOSCFG,		0x0c },
-	{ STV090x_GAINLLR_NF4,		0x21 },
-	{ STV090x_GAINLLR_NF5,		0x21 },
-	{ STV090x_GAINLLR_NF6,		0x20 },
-	{ STV090x_GAINLLR_NF7,		0x1F },
-	{ STV090x_GAINLLR_NF8,		0x1E },
-	{ STV090x_GAINLLR_NF9,		0x1E },
-	{ STV090x_GAINLLR_NF10,		0x1D },
-	{ STV090x_GAINLLR_NF11,		0x1B },
-	{ STV090x_GAINLLR_NF12,		0x20 },
-	{ STV090x_GAINLLR_NF13,		0x20 },
-	{ STV090x_GAINLLR_NF14,		0x20 },
-	{ STV090x_GAINLLR_NF15,		0x20 },
-	{ STV090x_GAINLLR_NF16,		0x20 },
-	{ STV090x_GAINLLR_NF17,		0x21 }
-};
-
-/* Cut 2.0 Long Frame Tracking CR loop */
-static struct stv090x_long_frame_crloop stv090x_s2_crl_cut20[] = {
-	/* MODCOD  2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff 20MPon 20MPoff 30MPon 30MPoff */
-	{ STV090x_QPSK_12,  0x1f, 0x3f, 0x1e, 0x3f, 0x3d, 0x1f, 0x3d, 0x3e, 0x3d, 0x1e },
-	{ STV090x_QPSK_35,  0x2f, 0x3f, 0x2e, 0x2f, 0x3d, 0x0f, 0x0e, 0x2e, 0x3d, 0x0e },
-	{ STV090x_QPSK_23,  0x2f, 0x3f, 0x2e, 0x2f, 0x0e, 0x0f, 0x0e, 0x1e, 0x3d, 0x3d },
-	{ STV090x_QPSK_34,  0x3f, 0x3f, 0x3e, 0x1f, 0x0e, 0x3e, 0x0e, 0x1e, 0x3d, 0x3d },
-	{ STV090x_QPSK_45,  0x3f, 0x3f, 0x3e, 0x1f, 0x0e, 0x3e, 0x0e, 0x1e, 0x3d, 0x3d },
-	{ STV090x_QPSK_56,  0x3f, 0x3f, 0x3e, 0x1f, 0x0e, 0x3e, 0x0e, 0x1e, 0x3d, 0x3d },
-	{ STV090x_QPSK_89,  0x3f, 0x3f, 0x3e, 0x1f, 0x1e, 0x3e, 0x0e, 0x1e, 0x3d, 0x3d },
-	{ STV090x_QPSK_910, 0x3f, 0x3f, 0x3e, 0x1f, 0x1e, 0x3e, 0x0e, 0x1e, 0x3d, 0x3d },
-	{ STV090x_8PSK_35,  0x3c, 0x3e, 0x1c, 0x2e, 0x0c, 0x1e, 0x2b, 0x2d, 0x1b, 0x1d },
-	{ STV090x_8PSK_23,  0x1d, 0x3e, 0x3c, 0x2e, 0x2c, 0x1e, 0x0c, 0x2d, 0x2b, 0x1d },
-	{ STV090x_8PSK_34,  0x0e, 0x3e, 0x3d, 0x2e, 0x0d, 0x1e, 0x2c, 0x2d, 0x0c, 0x1d },
-	{ STV090x_8PSK_56,  0x2e, 0x3e, 0x1e, 0x2e, 0x2d, 0x1e, 0x3c, 0x2d, 0x2c, 0x1d },
-	{ STV090x_8PSK_89,  0x3e, 0x3e, 0x1e, 0x2e, 0x3d, 0x1e, 0x0d, 0x2d, 0x3c, 0x1d },
-	{ STV090x_8PSK_910, 0x3e, 0x3e, 0x1e, 0x2e, 0x3d, 0x1e, 0x1d, 0x2d, 0x0d, 0x1d }
-};
-
-/* Cut 3.0 Long Frame Tracking CR loop */
-static	struct stv090x_long_frame_crloop stv090x_s2_crl_cut30[] = {
-	/* MODCOD  2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff 20MPon 20MPoff 30MPon 30MPoff */
-	{ STV090x_QPSK_12,  0x3c, 0x2c, 0x0c, 0x2c, 0x1b, 0x2c, 0x1b, 0x1c, 0x0b, 0x3b },
-	{ STV090x_QPSK_35,  0x0d, 0x0d, 0x0c, 0x0d, 0x1b, 0x3c, 0x1b, 0x1c, 0x0b, 0x3b },
-	{ STV090x_QPSK_23,  0x1d, 0x0d, 0x0c, 0x1d, 0x2b, 0x3c, 0x1b, 0x1c, 0x0b, 0x3b },
-	{ STV090x_QPSK_34,  0x1d, 0x1d, 0x0c, 0x1d, 0x2b, 0x3c, 0x1b, 0x1c, 0x0b, 0x3b },
-	{ STV090x_QPSK_45,  0x2d, 0x1d, 0x1c, 0x1d, 0x2b, 0x3c, 0x2b, 0x0c, 0x1b, 0x3b },
-	{ STV090x_QPSK_56,  0x2d, 0x1d, 0x1c, 0x1d, 0x2b, 0x3c, 0x2b, 0x0c, 0x1b, 0x3b },
-	{ STV090x_QPSK_89,  0x3d, 0x2d, 0x1c, 0x1d, 0x3b, 0x3c, 0x2b, 0x0c, 0x1b, 0x3b },
-	{ STV090x_QPSK_910, 0x3d, 0x2d, 0x1c, 0x1d, 0x3b, 0x3c, 0x2b, 0x0c, 0x1b, 0x3b },
-	{ STV090x_8PSK_35,  0x39, 0x29, 0x39, 0x19, 0x19, 0x19, 0x19, 0x19, 0x09, 0x19 },
-	{ STV090x_8PSK_23,  0x2a, 0x39, 0x1a, 0x0a, 0x39, 0x0a, 0x29, 0x39, 0x29, 0x0a },
-	{ STV090x_8PSK_34,  0x2b, 0x3a, 0x1b, 0x1b, 0x3a, 0x1b, 0x1a, 0x0b, 0x1a, 0x3a },
-	{ STV090x_8PSK_56,  0x0c, 0x1b, 0x3b, 0x3b, 0x1b, 0x3b, 0x3a, 0x3b, 0x3a, 0x1b },
-	{ STV090x_8PSK_89,  0x0d, 0x3c, 0x2c, 0x2c, 0x2b, 0x0c, 0x0b, 0x3b, 0x0b, 0x1b },
-	{ STV090x_8PSK_910, 0x0d, 0x0d, 0x2c, 0x3c, 0x3b, 0x1c, 0x0b, 0x3b, 0x0b, 0x1b }
-};
-
-/* Cut 2.0 Long Frame Tracking CR Loop */
-static struct stv090x_long_frame_crloop stv090x_s2_apsk_crl_cut20[] = {
-	/* MODCOD  2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff 20MPon 20MPoff 30MPon 30MPoff */
-	{ STV090x_16APSK_23,  0x0c, 0x0c, 0x0c, 0x0c, 0x1d, 0x0c, 0x3c, 0x0c, 0x2c, 0x0c },
-	{ STV090x_16APSK_34,  0x0c, 0x0c, 0x0c, 0x0c, 0x0e, 0x0c, 0x2d, 0x0c, 0x1d, 0x0c },
-	{ STV090x_16APSK_45,  0x0c, 0x0c, 0x0c, 0x0c, 0x1e, 0x0c, 0x3d, 0x0c, 0x2d, 0x0c },
-	{ STV090x_16APSK_56,  0x0c, 0x0c, 0x0c, 0x0c, 0x1e, 0x0c, 0x3d, 0x0c, 0x2d, 0x0c },
-	{ STV090x_16APSK_89,  0x0c, 0x0c, 0x0c, 0x0c, 0x2e, 0x0c, 0x0e, 0x0c, 0x3d, 0x0c },
-	{ STV090x_16APSK_910, 0x0c, 0x0c, 0x0c, 0x0c, 0x2e, 0x0c, 0x0e, 0x0c, 0x3d, 0x0c },
-	{ STV090x_32APSK_34,  0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c },
-	{ STV090x_32APSK_45,  0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c },
-	{ STV090x_32APSK_56,  0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c },
-	{ STV090x_32APSK_89,  0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c },
-	{ STV090x_32APSK_910, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c }
-};
-
-/* Cut 3.0 Long Frame Tracking CR Loop */
-static struct stv090x_long_frame_crloop	stv090x_s2_apsk_crl_cut30[] = {
-	/* MODCOD  2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff 20MPon 20MPoff 30MPon 30MPoff */
-	{ STV090x_16APSK_23,  0x0a, 0x0a, 0x0a, 0x0a, 0x1a, 0x0a, 0x3a, 0x0a, 0x2a, 0x0a },
-	{ STV090x_16APSK_34,  0x0a, 0x0a, 0x0a, 0x0a, 0x0b, 0x0a, 0x3b, 0x0a, 0x1b, 0x0a },
-	{ STV090x_16APSK_45,  0x0a, 0x0a, 0x0a, 0x0a, 0x1b, 0x0a, 0x3b, 0x0a, 0x2b, 0x0a },
-	{ STV090x_16APSK_56,  0x0a, 0x0a, 0x0a, 0x0a, 0x1b, 0x0a, 0x3b, 0x0a, 0x2b, 0x0a },
-	{ STV090x_16APSK_89,  0x0a, 0x0a, 0x0a, 0x0a, 0x2b, 0x0a, 0x0c, 0x0a, 0x3b, 0x0a },
-	{ STV090x_16APSK_910, 0x0a, 0x0a, 0x0a, 0x0a, 0x2b, 0x0a, 0x0c, 0x0a, 0x3b, 0x0a },
-	{ STV090x_32APSK_34,  0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a },
-	{ STV090x_32APSK_45,  0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a },
-	{ STV090x_32APSK_56,  0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a },
-	{ STV090x_32APSK_89,  0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a },
-	{ STV090x_32APSK_910, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a }
-};
-
-static struct stv090x_long_frame_crloop stv090x_s2_lowqpsk_crl_cut20[] = {
-	/* MODCOD  2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff 20MPon 20MPoff 30MPon 30MPoff */
-	{ STV090x_QPSK_14,  0x0f, 0x3f, 0x0e, 0x3f, 0x2d, 0x2f, 0x2d, 0x1f, 0x3d, 0x3e },
-	{ STV090x_QPSK_13,  0x0f, 0x3f, 0x0e, 0x3f, 0x2d, 0x2f, 0x3d, 0x0f, 0x3d, 0x2e },
-	{ STV090x_QPSK_25,  0x1f, 0x3f, 0x1e, 0x3f, 0x3d, 0x1f, 0x3d, 0x3e, 0x3d, 0x2e }
-};
-
-static struct stv090x_long_frame_crloop	stv090x_s2_lowqpsk_crl_cut30[] = {
-	/* MODCOD  2MPon 2MPoff 5MPon 5MPoff 10MPon 10MPoff 20MPon 20MPoff 30MPon 30MPoff */
-	{ STV090x_QPSK_14,  0x0c, 0x3c, 0x0b, 0x3c, 0x2a, 0x2c, 0x2a, 0x1c, 0x3a, 0x3b },
-	{ STV090x_QPSK_13,  0x0c, 0x3c, 0x0b, 0x3c, 0x2a, 0x2c, 0x3a, 0x0c, 0x3a, 0x2b },
-	{ STV090x_QPSK_25,  0x1c, 0x3c, 0x1b, 0x3c, 0x3a, 0x1c, 0x3a, 0x3b, 0x3a, 0x2b }
-};
-
-/* Cut 2.0 Short Frame Tracking CR Loop */
-static struct stv090x_short_frame_crloop stv090x_s2_short_crl_cut20[] = {
-	/* MODCOD	  2M    5M    10M   20M   30M */
-	{ STV090x_QPSK,   0x2f, 0x2e, 0x0e, 0x0e, 0x3d },
-	{ STV090x_8PSK,   0x3e, 0x0e, 0x2d, 0x0d, 0x3c },
-	{ STV090x_16APSK, 0x1e, 0x1e, 0x1e, 0x3d, 0x2d },
-	{ STV090x_32APSK, 0x1e, 0x1e, 0x1e, 0x3d, 0x2d }
-};
-
-/* Cut 3.0 Short Frame Tracking CR Loop */
-static struct stv090x_short_frame_crloop stv090x_s2_short_crl_cut30[] = {
-	/* MODCOD  	  2M	5M    10M   20M	  30M */
-	{ STV090x_QPSK,   0x2C, 0x2B, 0x0B, 0x0B, 0x3A },
-	{ STV090x_8PSK,   0x3B, 0x0B, 0x2A, 0x0A, 0x39 },
-	{ STV090x_16APSK, 0x1B, 0x1B, 0x1B, 0x3A, 0x2A },
-	{ STV090x_32APSK, 0x1B, 0x1B, 0x1B, 0x3A, 0x2A }
-};
-
-static inline s32 comp2(s32 __x, s32 __width)
-{
-	if (__width == 32)
-		return __x;
-	else
-		return (__x >= (1 << (__width - 1))) ? (__x - (1 << __width)) : __x;
-}
-
-static int stv090x_read_reg(struct stv090x_state *state, unsigned int reg)
-{
-	const struct stv090x_config *config = state->config;
-	int ret;
-
-	u8 b0[] = { reg >> 8, reg & 0xff };
-	u8 buf;
-
-	struct i2c_msg msg[] = {
-		{ .addr	= config->address, .flags	= 0, 		.buf = b0,   .len = 2 },
-		{ .addr	= config->address, .flags	= I2C_M_RD,	.buf = &buf, .len = 1 }
-	};
-
-	ret = i2c_transfer(state->i2c, msg, 2);
-	if (ret != 2) {
-		if (ret != -ERESTARTSYS)
-			dprintk(FE_ERROR, 1,
-				"Read error, Reg=[0x%02x], Status=%d",
-				reg, ret);
-
-		return ret < 0 ? ret : -EREMOTEIO;
-	}
-	if (unlikely(*state->verbose >= FE_DEBUGREG))
-		dprintk(FE_ERROR, 1, "Reg=[0x%02x], data=%02x",
-			reg, buf);
-
-	return (unsigned int) buf;
-}
-
-static int stv090x_write_regs(struct stv090x_state *state, unsigned int reg, u8 *data, u32 count)
-{
-	const struct stv090x_config *config = state->config;
-	int ret;
-	u8 buf[2 + count];
-	struct i2c_msg i2c_msg = { .addr = config->address, .flags = 0, .buf = buf, .len = 2 + count };
-
-	buf[0] = reg >> 8;
-	buf[1] = reg & 0xff;
-	memcpy(&buf[2], data, count);
-
-	if (unlikely(*state->verbose >= FE_DEBUGREG)) {
-		int i;
-
-		printk(KERN_DEBUG "%s [0x%04x]:", __func__, reg);
-		for (i = 0; i < count; i++)
-			printk(" %02x", data[i]);
-		printk("\n");
-	}
-
-	ret = i2c_transfer(state->i2c, &i2c_msg, 1);
-	if (ret != 1) {
-		if (ret != -ERESTARTSYS)
-			dprintk(FE_ERROR, 1, "Reg=[0x%04x], Data=[0x%02x ...], Count=%u, Status=%d",
-				reg, data[0], count, ret);
-		return ret < 0 ? ret : -EREMOTEIO;
-	}
-
-	return 0;
-}
-
-static int stv090x_write_reg(struct stv090x_state *state, unsigned int reg, u8 data)
-{
-	return stv090x_write_regs(state, reg, &data, 1);
-}
-
-static int stv090x_i2c_gate_ctrl(struct stv090x_state *state, int enable)
-{
-	u32 reg;
-
-	/*
-	 * NOTE! A lock is used as a FSM to control the state in which
-	 * access is serialized between two tuners on the same demod.
-	 * This has nothing to do with a lock to protect a critical section
-	 * which may in some other cases be confused with protecting I/O
-	 * access to the demodulator gate.
-	 * In case of any error, the lock is unlocked and exit within the
-	 * relevant operations themselves.
-	 */
-	if (enable) {
-		if (state->config->tuner_i2c_lock)
-			state->config->tuner_i2c_lock(&state->frontend, 1);
-		else
-			mutex_lock(&state->internal->tuner_lock);
-	}
-
-	reg = STV090x_READ_DEMOD(state, I2CRPT);
-	if (enable) {
-		dprintk(FE_DEBUG, 1, "Enable Gate");
-		STV090x_SETFIELD_Px(reg, I2CT_ON_FIELD, 1);
-		if (STV090x_WRITE_DEMOD(state, I2CRPT, reg) < 0)
-			goto err;
-
-	} else {
-		dprintk(FE_DEBUG, 1, "Disable Gate");
-		STV090x_SETFIELD_Px(reg, I2CT_ON_FIELD, 0);
-		if ((STV090x_WRITE_DEMOD(state, I2CRPT, reg)) < 0)
-			goto err;
-	}
-
-	if (!enable) {
-		if (state->config->tuner_i2c_lock)
-			state->config->tuner_i2c_lock(&state->frontend, 0);
-		else
-			mutex_unlock(&state->internal->tuner_lock);
-	}
-
-	return 0;
-err:
-	dprintk(FE_ERROR, 1, "I/O error");
-	if (state->config->tuner_i2c_lock)
-		state->config->tuner_i2c_lock(&state->frontend, 0);
-	else
-		mutex_unlock(&state->internal->tuner_lock);
-	return -1;
-}
-
-static void stv090x_get_lock_tmg(struct stv090x_state *state)
-{
-	switch (state->algo) {
-	case STV090x_BLIND_SEARCH:
-		dprintk(FE_DEBUG, 1, "Blind Search");
-		if (state->srate <= 1500000) {  /*10Msps< SR <=15Msps*/
-			state->DemodTimeout = 1500;
-			state->FecTimeout = 400;
-		} else if (state->srate <= 5000000) {  /*10Msps< SR <=15Msps*/
-			state->DemodTimeout = 1000;
-			state->FecTimeout = 300;
-		} else {  /*SR >20Msps*/
-			state->DemodTimeout = 700;
-			state->FecTimeout = 100;
-		}
-		break;
-
-	case STV090x_COLD_SEARCH:
-	case STV090x_WARM_SEARCH:
-	default:
-		dprintk(FE_DEBUG, 1, "Normal Search");
-		if (state->srate <= 1000000) {  /*SR <=1Msps*/
-			state->DemodTimeout = 4500;
-			state->FecTimeout = 1700;
-		} else if (state->srate <= 2000000) { /*1Msps < SR <= 2Msps */
-			state->DemodTimeout = 2500;
-			state->FecTimeout = 1100;
-		} else if (state->srate <= 5000000) { /*2Msps < SR <= 5Msps */
-			state->DemodTimeout = 1000;
-			state->FecTimeout = 550;
-		} else if (state->srate <= 10000000) { /*5Msps < SR <= 10Msps */
-			state->DemodTimeout = 700;
-			state->FecTimeout = 250;
-		} else if (state->srate <= 20000000) { /*10Msps < SR <= 20Msps */
-			state->DemodTimeout = 400;
-			state->FecTimeout = 130;
-		} else {   /*SR >20Msps*/
-			state->DemodTimeout = 300;
-			state->FecTimeout = 100;
-		}
-		break;
-	}
-
-	if (state->algo == STV090x_WARM_SEARCH)
-		state->DemodTimeout /= 2;
-}
-
-static int stv090x_set_srate(struct stv090x_state *state, u32 srate)
-{
-	u32 sym;
-
-	if (srate > 60000000) {
-		sym  = (srate << 4); /* SR * 2^16 / master_clk */
-		sym /= (state->internal->mclk >> 12);
-	} else if (srate > 6000000) {
-		sym  = (srate << 6);
-		sym /= (state->internal->mclk >> 10);
-	} else {
-		sym  = (srate << 9);
-		sym /= (state->internal->mclk >> 7);
-	}
-
-	if (STV090x_WRITE_DEMOD(state, SFRINIT1, (sym >> 8) & 0x7f) < 0) /* MSB */
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, SFRINIT0, (sym & 0xff)) < 0) /* LSB */
-		goto err;
-
-	return 0;
-err:
-	dprintk(FE_ERROR, 1, "I/O error");
-	return -1;
-}
-
-static int stv090x_set_max_srate(struct stv090x_state *state, u32 clk, u32 srate)
-{
-	u32 sym;
-
-	srate = 105 * (srate / 100);
-	if (srate > 60000000) {
-		sym  = (srate << 4); /* SR * 2^16 / master_clk */
-		sym /= (state->internal->mclk >> 12);
-	} else if (srate > 6000000) {
-		sym  = (srate << 6);
-		sym /= (state->internal->mclk >> 10);
-	} else {
-		sym  = (srate << 9);
-		sym /= (state->internal->mclk >> 7);
-	}
-
-	if (sym < 0x7fff) {
-		if (STV090x_WRITE_DEMOD(state, SFRUP1, (sym >> 8) & 0x7f) < 0) /* MSB */
-			goto err;
-		if (STV090x_WRITE_DEMOD(state, SFRUP0, sym & 0xff) < 0) /* LSB */
-			goto err;
-	} else {
-		if (STV090x_WRITE_DEMOD(state, SFRUP1, 0x7f) < 0) /* MSB */
-			goto err;
-		if (STV090x_WRITE_DEMOD(state, SFRUP0, 0xff) < 0) /* LSB */
-			goto err;
-	}
-
-	return 0;
-err:
-	dprintk(FE_ERROR, 1, "I/O error");
-	return -1;
-}
-
-static int stv090x_set_min_srate(struct stv090x_state *state, u32 clk, u32 srate)
-{
-	u32 sym;
-
-	srate = 95 * (srate / 100);
-	if (srate > 60000000) {
-		sym  = (srate << 4); /* SR * 2^16 / master_clk */
-		sym /= (state->internal->mclk >> 12);
-	} else if (srate > 6000000) {
-		sym  = (srate << 6);
-		sym /= (state->internal->mclk >> 10);
-	} else {
-		sym  = (srate << 9);
-		sym /= (state->internal->mclk >> 7);
-	}
-
-	if (STV090x_WRITE_DEMOD(state, SFRLOW1, ((sym >> 8) & 0x7f)) < 0) /* MSB */
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, SFRLOW0, (sym & 0xff)) < 0) /* LSB */
-		goto err;
-	return 0;
-err:
-	dprintk(FE_ERROR, 1, "I/O error");
-	return -1;
-}
-
-static u32 stv090x_car_width(u32 srate, enum stv090x_rolloff rolloff)
-{
-	u32 ro;
-
-	switch (rolloff) {
-	case STV090x_RO_20:
-		ro = 20;
-		break;
-	case STV090x_RO_25:
-		ro = 25;
-		break;
-	case STV090x_RO_35:
-	default:
-		ro = 35;
-		break;
-	}
-
-	return srate + (srate * ro) / 100;
-}
-
-static int stv090x_set_vit_thacq(struct stv090x_state *state)
-{
-	if (STV090x_WRITE_DEMOD(state, VTH12, 0x96) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, VTH23, 0x64) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, VTH34, 0x36) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, VTH56, 0x23) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, VTH67, 0x1e) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, VTH78, 0x19) < 0)
-		goto err;
-	return 0;
-err:
-	dprintk(FE_ERROR, 1, "I/O error");
-	return -1;
-}
-
-static int stv090x_set_vit_thtracq(struct stv090x_state *state)
-{
-	if (STV090x_WRITE_DEMOD(state, VTH12, 0xd0) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, VTH23, 0x7d) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, VTH34, 0x53) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, VTH56, 0x2f) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, VTH67, 0x24) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, VTH78, 0x1f) < 0)
-		goto err;
-	return 0;
-err:
-	dprintk(FE_ERROR, 1, "I/O error");
-	return -1;
-}
-
-static int stv090x_set_viterbi(struct stv090x_state *state)
-{
-	switch (state->search_mode) {
-	case STV090x_SEARCH_AUTO:
-		if (STV090x_WRITE_DEMOD(state, FECM, 0x10) < 0) /* DVB-S and DVB-S2 */
-			goto err;
-		if (STV090x_WRITE_DEMOD(state, PRVIT, 0x3f) < 0) /* all puncture rate */
-			goto err;
-		break;
-	case STV090x_SEARCH_DVBS1:
-		if (STV090x_WRITE_DEMOD(state, FECM, 0x00) < 0) /* disable DSS */
-			goto err;
-		switch (state->fec) {
-		case STV090x_PR12:
-			if (STV090x_WRITE_DEMOD(state, PRVIT, 0x01) < 0)
-				goto err;
-			break;
-
-		case STV090x_PR23:
-			if (STV090x_WRITE_DEMOD(state, PRVIT, 0x02) < 0)
-				goto err;
-			break;
-
-		case STV090x_PR34:
-			if (STV090x_WRITE_DEMOD(state, PRVIT, 0x04) < 0)
-				goto err;
-			break;
-
-		case STV090x_PR56:
-			if (STV090x_WRITE_DEMOD(state, PRVIT, 0x08) < 0)
-				goto err;
-			break;
-
-		case STV090x_PR78:
-			if (STV090x_WRITE_DEMOD(state, PRVIT, 0x20) < 0)
-				goto err;
-			break;
-
-		default:
-			if (STV090x_WRITE_DEMOD(state, PRVIT, 0x2f) < 0) /* all */
-				goto err;
-			break;
-		}
-		break;
-	case STV090x_SEARCH_DSS:
-		if (STV090x_WRITE_DEMOD(state, FECM, 0x80) < 0)
-			goto err;
-		switch (state->fec) {
-		case STV090x_PR12:
-			if (STV090x_WRITE_DEMOD(state, PRVIT, 0x01) < 0)
-				goto err;
-			break;
-
-		case STV090x_PR23:
-			if (STV090x_WRITE_DEMOD(state, PRVIT, 0x02) < 0)
-				goto err;
-			break;
-
-		case STV090x_PR67:
-			if (STV090x_WRITE_DEMOD(state, PRVIT, 0x10) < 0)
-				goto err;
-			break;
-
-		default:
-			if (STV090x_WRITE_DEMOD(state, PRVIT, 0x13) < 0) /* 1/2, 2/3, 6/7 */
-				goto err;
-			break;
-		}
-		break;
-	default:
-		break;
-	}
-	return 0;
-err:
-	dprintk(FE_ERROR, 1, "I/O error");
-	return -1;
-}
-
-static int stv090x_stop_modcod(struct stv090x_state *state)
-{
-	if (STV090x_WRITE_DEMOD(state, MODCODLST0, 0xff) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, MODCODLST1, 0xff) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, MODCODLST2, 0xff) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, MODCODLST3, 0xff) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, MODCODLST4, 0xff) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, MODCODLST5, 0xff) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, MODCODLST6, 0xff) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, MODCODLST7, 0xff) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, MODCODLST8, 0xff) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, MODCODLST9, 0xff) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, MODCODLSTA, 0xff) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, MODCODLSTB, 0xff) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, MODCODLSTC, 0xff) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, MODCODLSTD, 0xff) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, MODCODLSTE, 0xff) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, MODCODLSTF, 0xff) < 0)
-		goto err;
-	return 0;
-err:
-	dprintk(FE_ERROR, 1, "I/O error");
-	return -1;
-}
-
-static int stv090x_activate_modcod(struct stv090x_state *state)
-{
-	if (STV090x_WRITE_DEMOD(state, MODCODLST0, 0xff) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, MODCODLST1, 0xfc) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, MODCODLST2, 0xcc) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, MODCODLST3, 0xcc) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, MODCODLST4, 0xcc) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, MODCODLST5, 0xcc) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, MODCODLST6, 0xcc) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, MODCODLST7, 0xcc) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, MODCODLST8, 0xcc) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, MODCODLST9, 0xcc) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, MODCODLSTA, 0xcc) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, MODCODLSTB, 0xcc) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, MODCODLSTC, 0xcc) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, MODCODLSTD, 0xcc) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, MODCODLSTE, 0xcc) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, MODCODLSTF, 0xcf) < 0)
-		goto err;
-
-	return 0;
-err:
-	dprintk(FE_ERROR, 1, "I/O error");
-	return -1;
-}
-
-static int stv090x_activate_modcod_single(struct stv090x_state *state)
-{
-
-	if (STV090x_WRITE_DEMOD(state, MODCODLST0, 0xff) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, MODCODLST1, 0xf0) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, MODCODLST2, 0x00) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, MODCODLST3, 0x00) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, MODCODLST4, 0x00) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, MODCODLST5, 0x00) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, MODCODLST6, 0x00) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, MODCODLST7, 0x00) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, MODCODLST8, 0x00) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, MODCODLST9, 0x00) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, MODCODLSTA, 0x00) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, MODCODLSTB, 0x00) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, MODCODLSTC, 0x00) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, MODCODLSTD, 0x00) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, MODCODLSTE, 0x00) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, MODCODLSTF, 0x0f) < 0)
-		goto err;
-
-	return 0;
-
-err:
-	dprintk(FE_ERROR, 1, "I/O error");
-	return -1;
-}
-
-static int stv090x_vitclk_ctl(struct stv090x_state *state, int enable)
-{
-	u32 reg;
-
-	switch (state->demod) {
-	case STV090x_DEMODULATOR_0:
-		mutex_lock(&state->internal->demod_lock);
-		reg = stv090x_read_reg(state, STV090x_STOPCLK2);
-		STV090x_SETFIELD(reg, STOP_CLKVIT1_FIELD, enable);
-		if (stv090x_write_reg(state, STV090x_STOPCLK2, reg) < 0)
-			goto err;
-		mutex_unlock(&state->internal->demod_lock);
-		break;
-
-	case STV090x_DEMODULATOR_1:
-		mutex_lock(&state->internal->demod_lock);
-		reg = stv090x_read_reg(state, STV090x_STOPCLK2);
-		STV090x_SETFIELD(reg, STOP_CLKVIT2_FIELD, enable);
-		if (stv090x_write_reg(state, STV090x_STOPCLK2, reg) < 0)
-			goto err;
-		mutex_unlock(&state->internal->demod_lock);
-		break;
-
-	default:
-		dprintk(FE_ERROR, 1, "Wrong demodulator!");
-		break;
-	}
-	return 0;
-err:
-	mutex_unlock(&state->internal->demod_lock);
-	dprintk(FE_ERROR, 1, "I/O error");
-	return -1;
-}
-
-static int stv090x_dvbs_track_crl(struct stv090x_state *state)
-{
-	if (state->internal->dev_ver >= 0x30) {
-		/* Set ACLC BCLC optimised value vs SR */
-		if (state->srate >= 15000000) {
-			if (STV090x_WRITE_DEMOD(state, ACLC, 0x2b) < 0)
-				goto err;
-			if (STV090x_WRITE_DEMOD(state, BCLC, 0x1a) < 0)
-				goto err;
-		} else if ((state->srate >= 7000000) && (15000000 > state->srate)) {
-			if (STV090x_WRITE_DEMOD(state, ACLC, 0x0c) < 0)
-				goto err;
-			if (STV090x_WRITE_DEMOD(state, BCLC, 0x1b) < 0)
-				goto err;
-		} else if (state->srate < 7000000) {
-			if (STV090x_WRITE_DEMOD(state, ACLC, 0x2c) < 0)
-				goto err;
-			if (STV090x_WRITE_DEMOD(state, BCLC, 0x1c) < 0)
-				goto err;
-		}
-
-	} else {
-		/* Cut 2.0 */
-		if (STV090x_WRITE_DEMOD(state, ACLC, 0x1a) < 0)
-			goto err;
-		if (STV090x_WRITE_DEMOD(state, BCLC, 0x09) < 0)
-			goto err;
-	}
-	return 0;
-err:
-	dprintk(FE_ERROR, 1, "I/O error");
-	return -1;
-}
-
-static int stv090x_delivery_search(struct stv090x_state *state)
-{
-	u32 reg;
-
-	switch (state->search_mode) {
-	case STV090x_SEARCH_DVBS1:
-	case STV090x_SEARCH_DSS:
-		reg = STV090x_READ_DEMOD(state, DMDCFGMD);
-		STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 1);
-		STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 0);
-		if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
-			goto err;
-
-		/* Activate Viterbi decoder in legacy search,
-		 * do not use FRESVIT1, might impact VITERBI2
-		 */
-		if (stv090x_vitclk_ctl(state, 0) < 0)
-			goto err;
-
-		if (stv090x_dvbs_track_crl(state) < 0)
-			goto err;
-
-		if (STV090x_WRITE_DEMOD(state, CAR2CFG, 0x22) < 0) /* disable DVB-S2 */
-			goto err;
-
-		if (stv090x_set_vit_thacq(state) < 0)
-			goto err;
-		if (stv090x_set_viterbi(state) < 0)
-			goto err;
-		break;
-
-	case STV090x_SEARCH_DVBS2:
-		reg = STV090x_READ_DEMOD(state, DMDCFGMD);
-		STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 0);
-		STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 0);
-		if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
-			goto err;
-		STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 1);
-		STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 1);
-		if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
-			goto err;
-
-		if (stv090x_vitclk_ctl(state, 1) < 0)
-			goto err;
-
-		if (STV090x_WRITE_DEMOD(state, ACLC, 0x1a) < 0) /* stop DVB-S CR loop */
-			goto err;
-		if (STV090x_WRITE_DEMOD(state, BCLC, 0x09) < 0)
-			goto err;
-
-		if (state->internal->dev_ver <= 0x20) {
-			/* enable S2 carrier loop */
-			if (STV090x_WRITE_DEMOD(state, CAR2CFG, 0x26) < 0)
-				goto err;
-		} else {
-			/* > Cut 3: Stop carrier 3 */
-			if (STV090x_WRITE_DEMOD(state, CAR2CFG, 0x66) < 0)
-				goto err;
-		}
-
-		if (state->demod_mode != STV090x_SINGLE) {
-			/* Cut 2: enable link during search */
-			if (stv090x_activate_modcod(state) < 0)
-				goto err;
-		} else {
-			/* Single demodulator
-			 * Authorize SHORT and LONG frames,
-			 * QPSK, 8PSK, 16APSK and 32APSK
-			 */
-			if (stv090x_activate_modcod_single(state) < 0)
-				goto err;
-		}
-
-		if (stv090x_set_vit_thtracq(state) < 0)
-			goto err;
-		break;
-
-	case STV090x_SEARCH_AUTO:
-	default:
-		/* enable DVB-S2 and DVB-S2 in Auto MODE */
-		reg = STV090x_READ_DEMOD(state, DMDCFGMD);
-		STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 0);
-		STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 0);
-		if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
-			goto err;
-		STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 1);
-		STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 1);
-		if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
-			goto err;
-
-		if (stv090x_vitclk_ctl(state, 0) < 0)
-			goto err;
-
-		if (stv090x_dvbs_track_crl(state) < 0)
-			goto err;
-
-		if (state->internal->dev_ver <= 0x20) {
-			/* enable S2 carrier loop */
-			if (STV090x_WRITE_DEMOD(state, CAR2CFG, 0x26) < 0)
-				goto err;
-		} else {
-			/* > Cut 3: Stop carrier 3 */
-			if (STV090x_WRITE_DEMOD(state, CAR2CFG, 0x66) < 0)
-				goto err;
-		}
-
-		if (state->demod_mode != STV090x_SINGLE) {
-			/* Cut 2: enable link during search */
-			if (stv090x_activate_modcod(state) < 0)
-				goto err;
-		} else {
-			/* Single demodulator
-			 * Authorize SHORT and LONG frames,
-			 * QPSK, 8PSK, 16APSK and 32APSK
-			 */
-			if (stv090x_activate_modcod_single(state) < 0)
-				goto err;
-		}
-
-		if (stv090x_set_vit_thacq(state) < 0)
-			goto err;
-
-		if (stv090x_set_viterbi(state) < 0)
-			goto err;
-		break;
-	}
-	return 0;
-err:
-	dprintk(FE_ERROR, 1, "I/O error");
-	return -1;
-}
-
-static int stv090x_start_search(struct stv090x_state *state)
-{
-	u32 reg, freq_abs;
-	s16 freq;
-
-	/* Reset demodulator */
-	reg = STV090x_READ_DEMOD(state, DMDISTATE);
-	STV090x_SETFIELD_Px(reg, I2C_DEMOD_MODE_FIELD, 0x1f);
-	if (STV090x_WRITE_DEMOD(state, DMDISTATE, reg) < 0)
-		goto err;
-
-	if (state->internal->dev_ver <= 0x20) {
-		if (state->srate <= 5000000) {
-			if (STV090x_WRITE_DEMOD(state, CARCFG, 0x44) < 0)
-				goto err;
-			if (STV090x_WRITE_DEMOD(state, CFRUP1, 0x0f) < 0)
-				goto err;
-			if (STV090x_WRITE_DEMOD(state, CFRUP0, 0xff) < 0)
-				goto err;
-			if (STV090x_WRITE_DEMOD(state, CFRLOW1, 0xf0) < 0)
-				goto err;
-			if (STV090x_WRITE_DEMOD(state, CFRLOW0, 0x00) < 0)
-				goto err;
-
-			/*enlarge the timing bandwidth for Low SR*/
-			if (STV090x_WRITE_DEMOD(state, RTCS2, 0x68) < 0)
-				goto err;
-		} else {
-			/* If the symbol rate is >5 Msps
-			Set The carrier search up and low to auto mode */
-			if (STV090x_WRITE_DEMOD(state, CARCFG, 0xc4) < 0)
-				goto err;
-			/*reduce the timing bandwidth for high SR*/
-			if (STV090x_WRITE_DEMOD(state, RTCS2, 0x44) < 0)
-				goto err;
-		}
-	} else {
-		/* >= Cut 3 */
-		if (state->srate <= 5000000) {
-			/* enlarge the timing bandwidth for Low SR */
-			STV090x_WRITE_DEMOD(state, RTCS2, 0x68);
-		} else {
-			/* reduce timing bandwidth for high SR */
-			STV090x_WRITE_DEMOD(state, RTCS2, 0x44);
-		}
-
-		/* Set CFR min and max to manual mode */
-		STV090x_WRITE_DEMOD(state, CARCFG, 0x46);
-
-		if (state->algo == STV090x_WARM_SEARCH) {
-			/* WARM Start
-			 * CFR min = -1MHz,
-			 * CFR max = +1MHz
-			 */
-			freq_abs  = 1000 << 16;
-			freq_abs /= (state->internal->mclk / 1000);
-			freq      = (s16) freq_abs;
-		} else {
-			/* COLD Start
-			 * CFR min =- (SearchRange / 2 + 600KHz)
-			 * CFR max = +(SearchRange / 2 + 600KHz)
-			 * (600KHz for the tuner step size)
-			 */
-			freq_abs  = (state->search_range / 2000) + 600;
-			freq_abs  = freq_abs << 16;
-			freq_abs /= (state->internal->mclk / 1000);
-			freq      = (s16) freq_abs;
-		}
-
-		if (STV090x_WRITE_DEMOD(state, CFRUP1, MSB(freq)) < 0)
-			goto err;
-		if (STV090x_WRITE_DEMOD(state, CFRUP0, LSB(freq)) < 0)
-			goto err;
-
-		freq *= -1;
-
-		if (STV090x_WRITE_DEMOD(state, CFRLOW1, MSB(freq)) < 0)
-			goto err;
-		if (STV090x_WRITE_DEMOD(state, CFRLOW0, LSB(freq)) < 0)
-			goto err;
-
-	}
-
-	if (STV090x_WRITE_DEMOD(state, CFRINIT1, 0) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, CFRINIT0, 0) < 0)
-		goto err;
-
-	if (state->internal->dev_ver >= 0x20) {
-		if (STV090x_WRITE_DEMOD(state, EQUALCFG, 0x41) < 0)
-			goto err;
-		if (STV090x_WRITE_DEMOD(state, FFECFG, 0x41) < 0)
-			goto err;
-
-		if ((state->search_mode == STV090x_SEARCH_DVBS1)	||
-			(state->search_mode == STV090x_SEARCH_DSS)	||
-			(state->search_mode == STV090x_SEARCH_AUTO)) {
-
-			if (STV090x_WRITE_DEMOD(state, VITSCALE, 0x82) < 0)
-				goto err;
-			if (STV090x_WRITE_DEMOD(state, VAVSRVIT, 0x00) < 0)
-				goto err;
-		}
-	}
-
-	if (STV090x_WRITE_DEMOD(state, SFRSTEP, 0x00) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, TMGTHRISE, 0xe0) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, TMGTHFALL, 0xc0) < 0)
-		goto err;
-
-	reg = STV090x_READ_DEMOD(state, DMDCFGMD);
-	STV090x_SETFIELD_Px(reg, SCAN_ENABLE_FIELD, 0);
-	STV090x_SETFIELD_Px(reg, CFR_AUTOSCAN_FIELD, 0);
-	if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
-		goto err;
-	reg = STV090x_READ_DEMOD(state, DMDCFG2);
-	STV090x_SETFIELD_Px(reg, S1S2_SEQUENTIAL_FIELD, 0x0);
-	if (STV090x_WRITE_DEMOD(state, DMDCFG2, reg) < 0)
-		goto err;
-
-	if (STV090x_WRITE_DEMOD(state, RTC, 0x88) < 0)
-		goto err;
-
-	if (state->internal->dev_ver >= 0x20) {
-		/*Frequency offset detector setting*/
-		if (state->srate < 2000000) {
-			if (state->internal->dev_ver <= 0x20) {
-				/* Cut 2 */
-				if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x39) < 0)
-					goto err;
-			} else {
-				/* Cut 3 */
-				if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x89) < 0)
-					goto err;
-			}
-			if (STV090x_WRITE_DEMOD(state, CARHDR, 0x40) < 0)
-				goto err;
-		} else if (state->srate < 10000000) {
-			if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x4c) < 0)
-				goto err;
-			if (STV090x_WRITE_DEMOD(state, CARHDR, 0x20) < 0)
-				goto err;
-		} else {
-			if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x4b) < 0)
-				goto err;
-			if (STV090x_WRITE_DEMOD(state, CARHDR, 0x20) < 0)
-				goto err;
-		}
-	} else {
-		if (state->srate < 10000000) {
-			if (STV090x_WRITE_DEMOD(state, CARFREQ, 0xef) < 0)
-				goto err;
-		} else {
-			if (STV090x_WRITE_DEMOD(state, CARFREQ, 0xed) < 0)
-				goto err;
-		}
-	}
-
-	switch (state->algo) {
-	case STV090x_WARM_SEARCH:
-		/* The symbol rate and the exact
-		 * carrier Frequency are known
-		 */
-		if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0)
-			goto err;
-		if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x18) < 0)
-			goto err;
-		break;
-
-	case STV090x_COLD_SEARCH:
-		/* The symbol rate is known */
-		if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0)
-			goto err;
-		if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x15) < 0)
-			goto err;
-		break;
-
-	default:
-		break;
-	}
-	return 0;
-err:
-	dprintk(FE_ERROR, 1, "I/O error");
-	return -1;
-}
-
-static int stv090x_get_agc2_min_level(struct stv090x_state *state)
-{
-	u32 agc2_min = 0xffff, agc2 = 0, freq_init, freq_step, reg;
-	s32 i, j, steps, dir;
-
-	if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x38) < 0)
-		goto err;
-	reg = STV090x_READ_DEMOD(state, DMDCFGMD);
-	STV090x_SETFIELD_Px(reg, SCAN_ENABLE_FIELD, 0);
-	STV090x_SETFIELD_Px(reg, CFR_AUTOSCAN_FIELD, 0);
-	if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
-		goto err;
-
-	if (STV090x_WRITE_DEMOD(state, SFRUP1, 0x83) < 0) /* SR = 65 Msps Max */
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, SFRUP0, 0xc0) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, SFRLOW1, 0x82) < 0) /* SR= 400 ksps Min */
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, SFRLOW0, 0xa0) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, DMDTOM, 0x00) < 0) /* stop acq @ coarse carrier state */
-		goto err;
-	if (stv090x_set_srate(state, 1000000) < 0)
-		goto err;
-
-	steps  = state->search_range / 1000000;
-	if (steps <= 0)
-		steps = 1;
-
-	dir = 1;
-	freq_step = (1000000 * 256) / (state->internal->mclk / 256);
-	freq_init = 0;
-
-	for (i = 0; i < steps; i++) {
-		if (dir > 0)
-			freq_init = freq_init + (freq_step * i);
-		else
-			freq_init = freq_init - (freq_step * i);
-
-		dir *= -1;
-
-		if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x5c) < 0) /* Demod RESET */
-			goto err;
-		if (STV090x_WRITE_DEMOD(state, CFRINIT1, (freq_init >> 8) & 0xff) < 0)
-			goto err;
-		if (STV090x_WRITE_DEMOD(state, CFRINIT0, freq_init & 0xff) < 0)
-			goto err;
-		if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x58) < 0) /* Demod RESET */
-			goto err;
-		msleep(10);
-
-		agc2 = 0;
-		for (j = 0; j < 10; j++) {
-			agc2 += (STV090x_READ_DEMOD(state, AGC2I1) << 8) |
-				STV090x_READ_DEMOD(state, AGC2I0);
-		}
-		agc2 /= 10;
-		if (agc2 < agc2_min)
-			agc2_min = agc2;
-	}
-
-	return agc2_min;
-err:
-	dprintk(FE_ERROR, 1, "I/O error");
-	return -1;
-}
-
-static u32 stv090x_get_srate(struct stv090x_state *state, u32 clk)
-{
-	u8 r3, r2, r1, r0;
-	s32 srate, int_1, int_2, tmp_1, tmp_2;
-
-	r3 = STV090x_READ_DEMOD(state, SFR3);
-	r2 = STV090x_READ_DEMOD(state, SFR2);
-	r1 = STV090x_READ_DEMOD(state, SFR1);
-	r0 = STV090x_READ_DEMOD(state, SFR0);
-
-	srate = ((r3 << 24) | (r2 << 16) | (r1 <<  8) | r0);
-
-	int_1 = clk >> 16;
-	int_2 = srate >> 16;
-
-	tmp_1 = clk % 0x10000;
-	tmp_2 = srate % 0x10000;
-
-	srate = (int_1 * int_2) +
-		((int_1 * tmp_2) >> 16) +
-		((int_2 * tmp_1) >> 16);
-
-	return srate;
-}
-
-static u32 stv090x_srate_srch_coarse(struct stv090x_state *state)
-{
-	struct dvb_frontend *fe = &state->frontend;
-
-	int tmg_lock = 0, i;
-	s32 tmg_cpt = 0, dir = 1, steps, cur_step = 0, freq;
-	u32 srate_coarse = 0, agc2 = 0, car_step = 1200, reg;
-	u32 agc2th;
-
-	if (state->internal->dev_ver >= 0x30)
-		agc2th = 0x2e00;
-	else
-		agc2th = 0x1f00;
-
-	reg = STV090x_READ_DEMOD(state, DMDISTATE);
-	STV090x_SETFIELD_Px(reg, I2C_DEMOD_MODE_FIELD, 0x1f); /* Demod RESET */
-	if (STV090x_WRITE_DEMOD(state, DMDISTATE, reg) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, TMGCFG, 0x12) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, TMGCFG2, 0xc0) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, TMGTHRISE, 0xf0) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, TMGTHFALL, 0xe0) < 0)
-		goto err;
-	reg = STV090x_READ_DEMOD(state, DMDCFGMD);
-	STV090x_SETFIELD_Px(reg, SCAN_ENABLE_FIELD, 1);
-	STV090x_SETFIELD_Px(reg, CFR_AUTOSCAN_FIELD, 0);
-	if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
-		goto err;
-
-	if (STV090x_WRITE_DEMOD(state, SFRUP1, 0x83) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, SFRUP0, 0xc0) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, SFRLOW1, 0x82) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, SFRLOW0, 0xa0) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, DMDTOM, 0x00) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x50) < 0)
-		goto err;
-
-	if (state->internal->dev_ver >= 0x30) {
-		if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x99) < 0)
-			goto err;
-		if (STV090x_WRITE_DEMOD(state, SFRSTEP, 0x98) < 0)
-			goto err;
-
-	} else if (state->internal->dev_ver >= 0x20) {
-		if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x6a) < 0)
-			goto err;
-		if (STV090x_WRITE_DEMOD(state, SFRSTEP, 0x95) < 0)
-			goto err;
-	}
-
-	if (state->srate <= 2000000)
-		car_step = 1000;
-	else if (state->srate <= 5000000)
-		car_step = 2000;
-	else if (state->srate <= 12000000)
-		car_step = 3000;
-	else
-		car_step = 5000;
-
-	steps  = -1 + ((state->search_range / 1000) / car_step);
-	steps /= 2;
-	steps  = (2 * steps) + 1;
-	if (steps < 0)
-		steps = 1;
-	else if (steps > 10) {
-		steps = 11;
-		car_step = (state->search_range / 1000) / 10;
-	}
-	cur_step = 0;
-	dir = 1;
-	freq = state->frequency;
-
-	while ((!tmg_lock) && (cur_step < steps)) {
-		if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x5f) < 0) /* Demod RESET */
-			goto err;
-		if (STV090x_WRITE_DEMOD(state, CFRINIT1, 0x00) < 0)
-			goto err;
-		if (STV090x_WRITE_DEMOD(state, CFRINIT0, 0x00) < 0)
-			goto err;
-		if (STV090x_WRITE_DEMOD(state, SFRINIT1, 0x00) < 0)
-			goto err;
-		if (STV090x_WRITE_DEMOD(state, SFRINIT0, 0x00) < 0)
-			goto err;
-		/* trigger acquisition */
-		if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x40) < 0)
-			goto err;
-		msleep(50);
-		for (i = 0; i < 10; i++) {
-			reg = STV090x_READ_DEMOD(state, DSTATUS);
-			if (STV090x_GETFIELD_Px(reg, TMGLOCK_QUALITY_FIELD) >= 2)
-				tmg_cpt++;
-			agc2 += (STV090x_READ_DEMOD(state, AGC2I1) << 8) |
-				STV090x_READ_DEMOD(state, AGC2I0);
-		}
-		agc2 /= 10;
-		srate_coarse = stv090x_get_srate(state, state->internal->mclk);
-		cur_step++;
-		dir *= -1;
-		if ((tmg_cpt >= 5) && (agc2 < agc2th) &&
-		    (srate_coarse < 50000000) && (srate_coarse > 850000))
-			tmg_lock = 1;
-		else if (cur_step < steps) {
-			if (dir > 0)
-				freq += cur_step * car_step;
-			else
-				freq -= cur_step * car_step;
-
-			/* Setup tuner */
-			if (stv090x_i2c_gate_ctrl(state, 1) < 0)
-				goto err;
-
-			if (state->config->tuner_set_frequency) {
-				if (state->config->tuner_set_frequency(fe, freq) < 0)
-					goto err_gateoff;
-			}
-
-			if (state->config->tuner_set_bandwidth) {
-				if (state->config->tuner_set_bandwidth(fe, state->tuner_bw) < 0)
-					goto err_gateoff;
-			}
-
-			if (stv090x_i2c_gate_ctrl(state, 0) < 0)
-				goto err;
-
-			msleep(50);
-
-			if (stv090x_i2c_gate_ctrl(state, 1) < 0)
-				goto err;
-
-			if (state->config->tuner_get_status) {
-				if (state->config->tuner_get_status(fe, &reg) < 0)
-					goto err_gateoff;
-			}
-
-			if (reg)
-				dprintk(FE_DEBUG, 1, "Tuner phase locked");
-			else
-				dprintk(FE_DEBUG, 1, "Tuner unlocked");
-
-			if (stv090x_i2c_gate_ctrl(state, 0) < 0)
-				goto err;
-
-		}
-	}
-	if (!tmg_lock)
-		srate_coarse = 0;
-	else
-		srate_coarse = stv090x_get_srate(state, state->internal->mclk);
-
-	return srate_coarse;
-
-err_gateoff:
-	stv090x_i2c_gate_ctrl(state, 0);
-err:
-	dprintk(FE_ERROR, 1, "I/O error");
-	return -1;
-}
-
-static u32 stv090x_srate_srch_fine(struct stv090x_state *state)
-{
-	u32 srate_coarse, freq_coarse, sym, reg;
-
-	srate_coarse = stv090x_get_srate(state, state->internal->mclk);
-	freq_coarse  = STV090x_READ_DEMOD(state, CFR2) << 8;
-	freq_coarse |= STV090x_READ_DEMOD(state, CFR1);
-	sym = 13 * (srate_coarse / 10); /* SFRUP = SFR + 30% */
-
-	if (sym < state->srate)
-		srate_coarse = 0;
-	else {
-		if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0) /* Demod RESET */
-			goto err;
-		if (STV090x_WRITE_DEMOD(state, TMGCFG2, 0xc1) < 0)
-			goto err;
-		if (STV090x_WRITE_DEMOD(state, TMGTHRISE, 0x20) < 0)
-			goto err;
-		if (STV090x_WRITE_DEMOD(state, TMGTHFALL, 0x00) < 0)
-			goto err;
-		if (STV090x_WRITE_DEMOD(state, TMGCFG, 0xd2) < 0)
-			goto err;
-		reg = STV090x_READ_DEMOD(state, DMDCFGMD);
-		STV090x_SETFIELD_Px(reg, CFR_AUTOSCAN_FIELD, 0x00);
-		if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
-			goto err;
-
-		if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x38) < 0)
-			goto err;
-
-		if (state->internal->dev_ver >= 0x30) {
-			if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x79) < 0)
-				goto err;
-		} else if (state->internal->dev_ver >= 0x20) {
-			if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x49) < 0)
-				goto err;
-		}
-
-		if (srate_coarse > 3000000) {
-			sym  = 13 * (srate_coarse / 10); /* SFRUP = SFR + 30% */
-			sym  = (sym / 1000) * 65536;
-			sym /= (state->internal->mclk / 1000);
-			if (STV090x_WRITE_DEMOD(state, SFRUP1, (sym >> 8) & 0x7f) < 0)
-				goto err;
-			if (STV090x_WRITE_DEMOD(state, SFRUP0, sym & 0xff) < 0)
-				goto err;
-			sym  = 10 * (srate_coarse / 13); /* SFRLOW = SFR - 30% */
-			sym  = (sym / 1000) * 65536;
-			sym /= (state->internal->mclk / 1000);
-			if (STV090x_WRITE_DEMOD(state, SFRLOW1, (sym >> 8) & 0x7f) < 0)
-				goto err;
-			if (STV090x_WRITE_DEMOD(state, SFRLOW0, sym & 0xff) < 0)
-				goto err;
-			sym  = (srate_coarse / 1000) * 65536;
-			sym /= (state->internal->mclk / 1000);
-			if (STV090x_WRITE_DEMOD(state, SFRINIT1, (sym >> 8) & 0xff) < 0)
-				goto err;
-			if (STV090x_WRITE_DEMOD(state, SFRINIT0, sym & 0xff) < 0)
-				goto err;
-		} else {
-			sym  = 13 * (srate_coarse / 10); /* SFRUP = SFR + 30% */
-			sym  = (sym / 100) * 65536;
-			sym /= (state->internal->mclk / 100);
-			if (STV090x_WRITE_DEMOD(state, SFRUP1, (sym >> 8) & 0x7f) < 0)
-				goto err;
-			if (STV090x_WRITE_DEMOD(state, SFRUP0, sym & 0xff) < 0)
-				goto err;
-			sym  = 10 * (srate_coarse / 14); /* SFRLOW = SFR - 30% */
-			sym  = (sym / 100) * 65536;
-			sym /= (state->internal->mclk / 100);
-			if (STV090x_WRITE_DEMOD(state, SFRLOW1, (sym >> 8) & 0x7f) < 0)
-				goto err;
-			if (STV090x_WRITE_DEMOD(state, SFRLOW0, sym & 0xff) < 0)
-				goto err;
-			sym  = (srate_coarse / 100) * 65536;
-			sym /= (state->internal->mclk / 100);
-			if (STV090x_WRITE_DEMOD(state, SFRINIT1, (sym >> 8) & 0xff) < 0)
-				goto err;
-			if (STV090x_WRITE_DEMOD(state, SFRINIT0, sym & 0xff) < 0)
-				goto err;
-		}
-		if (STV090x_WRITE_DEMOD(state, DMDTOM, 0x20) < 0)
-			goto err;
-		if (STV090x_WRITE_DEMOD(state, CFRINIT1, (freq_coarse >> 8) & 0xff) < 0)
-			goto err;
-		if (STV090x_WRITE_DEMOD(state, CFRINIT0, freq_coarse & 0xff) < 0)
-			goto err;
-		if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x15) < 0) /* trigger acquisition */
-			goto err;
-	}
-
-	return srate_coarse;
-
-err:
-	dprintk(FE_ERROR, 1, "I/O error");
-	return -1;
-}
-
-static int stv090x_get_dmdlock(struct stv090x_state *state, s32 timeout)
-{
-	s32 timer = 0, lock = 0;
-	u32 reg;
-	u8 stat;
-
-	while ((timer < timeout) && (!lock)) {
-		reg = STV090x_READ_DEMOD(state, DMDSTATE);
-		stat = STV090x_GETFIELD_Px(reg, HEADER_MODE_FIELD);
-
-		switch (stat) {
-		case 0: /* searching */
-		case 1: /* first PLH detected */
-		default:
-			dprintk(FE_DEBUG, 1, "Demodulator searching ..");
-			lock = 0;
-			break;
-		case 2: /* DVB-S2 mode */
-		case 3: /* DVB-S1/legacy mode */
-			reg = STV090x_READ_DEMOD(state, DSTATUS);
-			lock = STV090x_GETFIELD_Px(reg, LOCK_DEFINITIF_FIELD);
-			break;
-		}
-
-		if (!lock)
-			msleep(10);
-		else
-			dprintk(FE_DEBUG, 1, "Demodulator acquired LOCK");
-
-		timer += 10;
-	}
-	return lock;
-}
-
-static int stv090x_blind_search(struct stv090x_state *state)
-{
-	u32 agc2, reg, srate_coarse;
-	s32 cpt_fail, agc2_ovflw, i;
-	u8 k_ref, k_max, k_min;
-	int coarse_fail = 0;
-	int lock;
-
-	k_max = 110;
-	k_min = 10;
-
-	agc2 = stv090x_get_agc2_min_level(state);
-
-	if (agc2 > STV090x_SEARCH_AGC2_TH(state->internal->dev_ver)) {
-		lock = 0;
-	} else {
-
-		if (state->internal->dev_ver <= 0x20) {
-			if (STV090x_WRITE_DEMOD(state, CARCFG, 0xc4) < 0)
-				goto err;
-		} else {
-			/* > Cut 3 */
-			if (STV090x_WRITE_DEMOD(state, CARCFG, 0x06) < 0)
-				goto err;
-		}
-
-		if (STV090x_WRITE_DEMOD(state, RTCS2, 0x44) < 0)
-			goto err;
-
-		if (state->internal->dev_ver >= 0x20) {
-			if (STV090x_WRITE_DEMOD(state, EQUALCFG, 0x41) < 0)
-				goto err;
-			if (STV090x_WRITE_DEMOD(state, FFECFG, 0x41) < 0)
-				goto err;
-			if (STV090x_WRITE_DEMOD(state, VITSCALE, 0x82) < 0)
-				goto err;
-			if (STV090x_WRITE_DEMOD(state, VAVSRVIT, 0x00) < 0) /* set viterbi hysteresis */
-				goto err;
-		}
-
-		k_ref = k_max;
-		do {
-			if (STV090x_WRITE_DEMOD(state, KREFTMG, k_ref) < 0)
-				goto err;
-			if (stv090x_srate_srch_coarse(state) != 0) {
-				srate_coarse = stv090x_srate_srch_fine(state);
-				if (srate_coarse != 0) {
-					stv090x_get_lock_tmg(state);
-					lock = stv090x_get_dmdlock(state,
-							state->DemodTimeout);
-				} else {
-					lock = 0;
-				}
-			} else {
-				cpt_fail = 0;
-				agc2_ovflw = 0;
-				for (i = 0; i < 10; i++) {
-					agc2 += (STV090x_READ_DEMOD(state, AGC2I1) << 8) |
-						STV090x_READ_DEMOD(state, AGC2I0);
-					if (agc2 >= 0xff00)
-						agc2_ovflw++;
-					reg = STV090x_READ_DEMOD(state, DSTATUS2);
-					if ((STV090x_GETFIELD_Px(reg, CFR_OVERFLOW_FIELD) == 0x01) &&
-					    (STV090x_GETFIELD_Px(reg, DEMOD_DELOCK_FIELD) == 0x01))
-
-						cpt_fail++;
-				}
-				if ((cpt_fail > 7) || (agc2_ovflw > 7))
-					coarse_fail = 1;
-
-				lock = 0;
-			}
-			k_ref -= 20;
-		} while ((k_ref >= k_min) && (!lock) && (!coarse_fail));
-	}
-
-	return lock;
-
-err:
-	dprintk(FE_ERROR, 1, "I/O error");
-	return -1;
-}
-
-static int stv090x_chk_tmg(struct stv090x_state *state)
-{
-	u32 reg;
-	s32 tmg_cpt = 0, i;
-	u8 freq, tmg_thh, tmg_thl;
-	int tmg_lock = 0;
-
-	freq = STV090x_READ_DEMOD(state, CARFREQ);
-	tmg_thh = STV090x_READ_DEMOD(state, TMGTHRISE);
-	tmg_thl = STV090x_READ_DEMOD(state, TMGTHFALL);
-	if (STV090x_WRITE_DEMOD(state, TMGTHRISE, 0x20) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, TMGTHFALL, 0x00) < 0)
-		goto err;
-
-	reg = STV090x_READ_DEMOD(state, DMDCFGMD);
-	STV090x_SETFIELD_Px(reg, CFR_AUTOSCAN_FIELD, 0x00); /* stop carrier offset search */
-	if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, RTC, 0x80) < 0)
-		goto err;
-
-	if (STV090x_WRITE_DEMOD(state, RTCS2, 0x40) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x00) < 0)
-		goto err;
-
-	if (STV090x_WRITE_DEMOD(state, CFRINIT1, 0x00) < 0) /* set car ofset to 0 */
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, CFRINIT0, 0x00) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x65) < 0)
-		goto err;
-
-	if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x18) < 0) /* trigger acquisition */
-		goto err;
-	msleep(10);
-
-	for (i = 0; i < 10; i++) {
-		reg = STV090x_READ_DEMOD(state, DSTATUS);
-		if (STV090x_GETFIELD_Px(reg, TMGLOCK_QUALITY_FIELD) >= 2)
-			tmg_cpt++;
-		msleep(1);
-	}
-	if (tmg_cpt >= 3)
-		tmg_lock = 1;
-
-	if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x38) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, RTC, 0x88) < 0) /* DVB-S1 timing */
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, RTCS2, 0x68) < 0) /* DVB-S2 timing */
-		goto err;
-
-	if (STV090x_WRITE_DEMOD(state, CARFREQ, freq) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, TMGTHRISE, tmg_thh) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, TMGTHFALL, tmg_thl) < 0)
-		goto err;
-
-	return	tmg_lock;
-
-err:
-	dprintk(FE_ERROR, 1, "I/O error");
-	return -1;
-}
-
-static int stv090x_get_coldlock(struct stv090x_state *state, s32 timeout_dmd)
-{
-	struct dvb_frontend *fe = &state->frontend;
-
-	u32 reg;
-	s32 car_step, steps, cur_step, dir, freq, timeout_lock;
-	int lock = 0;
-
-	if (state->srate >= 10000000)
-		timeout_lock = timeout_dmd / 3;
-	else
-		timeout_lock = timeout_dmd / 2;
-
-	lock = stv090x_get_dmdlock(state, timeout_lock); /* cold start wait */
-	if (!lock) {
-		if (state->srate >= 10000000) {
-			if (stv090x_chk_tmg(state)) {
-				if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0)
-					goto err;
-				if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x15) < 0)
-					goto err;
-				lock = stv090x_get_dmdlock(state, timeout_dmd);
-			} else {
-				lock = 0;
-			}
-		} else {
-			if (state->srate <= 4000000)
-				car_step = 1000;
-			else if (state->srate <= 7000000)
-				car_step = 2000;
-			else if (state->srate <= 10000000)
-				car_step = 3000;
-			else
-				car_step = 5000;
-
-			steps  = (state->search_range / 1000) / car_step;
-			steps /= 2;
-			steps  = 2 * (steps + 1);
-			if (steps < 0)
-				steps = 2;
-			else if (steps > 12)
-				steps = 12;
-
-			cur_step = 1;
-			dir = 1;
-
-			if (!lock) {
-				freq = state->frequency;
-				state->tuner_bw = stv090x_car_width(state->srate, state->rolloff) + state->srate;
-				while ((cur_step <= steps) && (!lock)) {
-					if (dir > 0)
-						freq += cur_step * car_step;
-					else
-						freq -= cur_step * car_step;
-
-					/* Setup tuner */
-					if (stv090x_i2c_gate_ctrl(state, 1) < 0)
-						goto err;
-
-					if (state->config->tuner_set_frequency) {
-						if (state->config->tuner_set_frequency(fe, freq) < 0)
-							goto err_gateoff;
-					}
-
-					if (state->config->tuner_set_bandwidth) {
-						if (state->config->tuner_set_bandwidth(fe, state->tuner_bw) < 0)
-							goto err_gateoff;
-					}
-
-					if (stv090x_i2c_gate_ctrl(state, 0) < 0)
-						goto err;
-
-					msleep(50);
-
-					if (stv090x_i2c_gate_ctrl(state, 1) < 0)
-						goto err;
-
-					if (state->config->tuner_get_status) {
-						if (state->config->tuner_get_status(fe, &reg) < 0)
-							goto err_gateoff;
-					}
-
-					if (reg)
-						dprintk(FE_DEBUG, 1, "Tuner phase locked");
-					else
-						dprintk(FE_DEBUG, 1, "Tuner unlocked");
-
-					if (stv090x_i2c_gate_ctrl(state, 0) < 0)
-						goto err;
-
-					STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1c);
-					if (STV090x_WRITE_DEMOD(state, CFRINIT1, 0x00) < 0)
-						goto err;
-					if (STV090x_WRITE_DEMOD(state, CFRINIT0, 0x00) < 0)
-						goto err;
-					if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0)
-						goto err;
-					if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x15) < 0)
-						goto err;
-					lock = stv090x_get_dmdlock(state, (timeout_dmd / 3));
-
-					dir *= -1;
-					cur_step++;
-				}
-			}
-		}
-	}
-
-	return lock;
-
-err_gateoff:
-	stv090x_i2c_gate_ctrl(state, 0);
-err:
-	dprintk(FE_ERROR, 1, "I/O error");
-	return -1;
-}
-
-static int stv090x_get_loop_params(struct stv090x_state *state, s32 *freq_inc, s32 *timeout_sw, s32 *steps)
-{
-	s32 timeout, inc, steps_max, srate, car_max;
-
-	srate = state->srate;
-	car_max = state->search_range / 1000;
-	car_max += car_max / 10;
-	car_max  = 65536 * (car_max / 2);
-	car_max /= (state->internal->mclk / 1000);
-
-	if (car_max > 0x4000)
-		car_max = 0x4000 ; /* maxcarrier should be<= +-1/4 Mclk */
-
-	inc  = srate;
-	inc /= state->internal->mclk / 1000;
-	inc *= 256;
-	inc *= 256;
-	inc /= 1000;
-
-	switch (state->search_mode) {
-	case STV090x_SEARCH_DVBS1:
-	case STV090x_SEARCH_DSS:
-		inc *= 3; /* freq step = 3% of srate */
-		timeout = 20;
-		break;
-
-	case STV090x_SEARCH_DVBS2:
-		inc *= 4;
-		timeout = 25;
-		break;
-
-	case STV090x_SEARCH_AUTO:
-	default:
-		inc *= 3;
-		timeout = 25;
-		break;
-	}
-	inc /= 100;
-	if ((inc > car_max) || (inc < 0))
-		inc = car_max / 2; /* increment <= 1/8 Mclk */
-
-	timeout *= 27500; /* 27.5 Msps reference */
-	if (srate > 0)
-		timeout /= (srate / 1000);
-
-	if ((timeout > 100) || (timeout < 0))
-		timeout = 100;
-
-	steps_max = (car_max / inc) + 1; /* min steps = 3 */
-	if ((steps_max > 100) || (steps_max < 0)) {
-		steps_max = 100; /* max steps <= 100 */
-		inc = car_max / steps_max;
-	}
-	*freq_inc = inc;
-	*timeout_sw = timeout;
-	*steps = steps_max;
-
-	return 0;
-}
-
-static int stv090x_chk_signal(struct stv090x_state *state)
-{
-	s32 offst_car, agc2, car_max;
-	int no_signal;
-
-	offst_car  = STV090x_READ_DEMOD(state, CFR2) << 8;
-	offst_car |= STV090x_READ_DEMOD(state, CFR1);
-	offst_car = comp2(offst_car, 16);
-
-	agc2  = STV090x_READ_DEMOD(state, AGC2I1) << 8;
-	agc2 |= STV090x_READ_DEMOD(state, AGC2I0);
-	car_max = state->search_range / 1000;
-
-	car_max += (car_max / 10); /* 10% margin */
-	car_max  = (65536 * car_max / 2);
-	car_max /= state->internal->mclk / 1000;
-
-	if (car_max > 0x4000)
-		car_max = 0x4000;
-
-	if ((agc2 > 0x2000) || (offst_car > 2 * car_max) || (offst_car < -2 * car_max)) {
-		no_signal = 1;
-		dprintk(FE_DEBUG, 1, "No Signal");
-	} else {
-		no_signal = 0;
-		dprintk(FE_DEBUG, 1, "Found Signal");
-	}
-
-	return no_signal;
-}
-
-static int stv090x_search_car_loop(struct stv090x_state *state, s32 inc, s32 timeout, int zigzag, s32 steps_max)
-{
-	int no_signal, lock = 0;
-	s32 cpt_step = 0, offst_freq, car_max;
-	u32 reg;
-
-	car_max  = state->search_range / 1000;
-	car_max += (car_max / 10);
-	car_max  = (65536 * car_max / 2);
-	car_max /= (state->internal->mclk / 1000);
-	if (car_max > 0x4000)
-		car_max = 0x4000;
-
-	if (zigzag)
-		offst_freq = 0;
-	else
-		offst_freq = -car_max + inc;
-
-	do {
-		if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1c) < 0)
-			goto err;
-		if (STV090x_WRITE_DEMOD(state, CFRINIT1, ((offst_freq / 256) & 0xff)) < 0)
-			goto err;
-		if (STV090x_WRITE_DEMOD(state, CFRINIT0, offst_freq & 0xff) < 0)
-			goto err;
-		if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x18) < 0)
-			goto err;
-
-		reg = STV090x_READ_DEMOD(state, PDELCTRL1);
-		STV090x_SETFIELD_Px(reg, ALGOSWRST_FIELD, 0x1); /* stop DVB-S2 packet delin */
-		if (STV090x_WRITE_DEMOD(state, PDELCTRL1, reg) < 0)
-			goto err;
-
-		if (zigzag) {
-			if (offst_freq >= 0)
-				offst_freq = -offst_freq - 2 * inc;
-			else
-				offst_freq = -offst_freq;
-		} else {
-			offst_freq += 2 * inc;
-		}
-
-		cpt_step++;
-
-		lock = stv090x_get_dmdlock(state, timeout);
-		no_signal = stv090x_chk_signal(state);
-
-	} while ((!lock) &&
-		 (!no_signal) &&
-		  ((offst_freq - inc) < car_max) &&
-		  ((offst_freq + inc) > -car_max) &&
-		  (cpt_step < steps_max));
-
-	reg = STV090x_READ_DEMOD(state, PDELCTRL1);
-	STV090x_SETFIELD_Px(reg, ALGOSWRST_FIELD, 0);
-	if (STV090x_WRITE_DEMOD(state, PDELCTRL1, reg) < 0)
-			goto err;
-
-	return lock;
-err:
-	dprintk(FE_ERROR, 1, "I/O error");
-	return -1;
-}
-
-static int stv090x_sw_algo(struct stv090x_state *state)
-{
-	int no_signal, zigzag, lock = 0;
-	u32 reg;
-
-	s32 dvbs2_fly_wheel;
-	s32 inc, timeout_step, trials, steps_max;
-
-	/* get params */
-	stv090x_get_loop_params(state, &inc, &timeout_step, &steps_max);
-
-	switch (state->search_mode) {
-	case STV090x_SEARCH_DVBS1:
-	case STV090x_SEARCH_DSS:
-		/* accelerate the frequency detector */
-		if (state->internal->dev_ver >= 0x20) {
-			if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x3B) < 0)
-				goto err;
-		}
-
-		if (STV090x_WRITE_DEMOD(state, DMDCFGMD, 0x49) < 0)
-			goto err;
-		zigzag = 0;
-		break;
-
-	case STV090x_SEARCH_DVBS2:
-		if (state->internal->dev_ver >= 0x20) {
-			if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x79) < 0)
-				goto err;
-		}
-
-		if (STV090x_WRITE_DEMOD(state, DMDCFGMD, 0x89) < 0)
-			goto err;
-		zigzag = 1;
-		break;
-
-	case STV090x_SEARCH_AUTO:
-	default:
-		/* accelerate the frequency detector */
-		if (state->internal->dev_ver >= 0x20) {
-			if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x3b) < 0)
-				goto err;
-			if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x79) < 0)
-				goto err;
-		}
-
-		if (STV090x_WRITE_DEMOD(state, DMDCFGMD, 0xc9) < 0)
-			goto err;
-		zigzag = 0;
-		break;
-	}
-
-	trials = 0;
-	do {
-		lock = stv090x_search_car_loop(state, inc, timeout_step, zigzag, steps_max);
-		no_signal = stv090x_chk_signal(state);
-		trials++;
-
-		/*run the SW search 2 times maximum*/
-		if (lock || no_signal || (trials == 2)) {
-			/*Check if the demod is not losing lock in DVBS2*/
-			if (state->internal->dev_ver >= 0x20) {
-				if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x49) < 0)
-					goto err;
-				if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x9e) < 0)
-					goto err;
-			}
-
-			reg = STV090x_READ_DEMOD(state, DMDSTATE);
-			if ((lock) && (STV090x_GETFIELD_Px(reg, HEADER_MODE_FIELD) == STV090x_DVBS2)) {
-				/*Check if the demod is not losing lock in DVBS2*/
-				msleep(timeout_step);
-				reg = STV090x_READ_DEMOD(state, DMDFLYW);
-				dvbs2_fly_wheel = STV090x_GETFIELD_Px(reg, FLYWHEEL_CPT_FIELD);
-				if (dvbs2_fly_wheel < 0xd) {	 /*if correct frames is decrementing */
-					msleep(timeout_step);
-					reg = STV090x_READ_DEMOD(state, DMDFLYW);
-					dvbs2_fly_wheel = STV090x_GETFIELD_Px(reg, FLYWHEEL_CPT_FIELD);
-				}
-				if (dvbs2_fly_wheel < 0xd) {
-					/*FALSE lock, The demod is losing lock */
-					lock = 0;
-					if (trials < 2) {
-						if (state->internal->dev_ver >= 0x20) {
-							if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x79) < 0)
-								goto err;
-						}
-
-						if (STV090x_WRITE_DEMOD(state, DMDCFGMD, 0x89) < 0)
-							goto err;
-					}
-				}
-			}
-		}
-	} while ((!lock) && (trials < 2) && (!no_signal));
-
-	return lock;
-err:
-	dprintk(FE_ERROR, 1, "I/O error");
-	return -1;
-}
-
-static enum stv090x_delsys stv090x_get_std(struct stv090x_state *state)
-{
-	u32 reg;
-	enum stv090x_delsys delsys;
-
-	reg = STV090x_READ_DEMOD(state, DMDSTATE);
-	if (STV090x_GETFIELD_Px(reg, HEADER_MODE_FIELD) == 2)
-		delsys = STV090x_DVBS2;
-	else if (STV090x_GETFIELD_Px(reg, HEADER_MODE_FIELD) == 3) {
-		reg = STV090x_READ_DEMOD(state, FECM);
-		if (STV090x_GETFIELD_Px(reg, DSS_DVB_FIELD) == 1)
-			delsys = STV090x_DSS;
-		else
-			delsys = STV090x_DVBS1;
-	} else {
-		delsys = STV090x_ERROR;
-	}
-
-	return delsys;
-}
-
-/* in Hz */
-static s32 stv090x_get_car_freq(struct stv090x_state *state, u32 mclk)
-{
-	s32 derot, int_1, int_2, tmp_1, tmp_2;
-
-	derot  = STV090x_READ_DEMOD(state, CFR2) << 16;
-	derot |= STV090x_READ_DEMOD(state, CFR1) <<  8;
-	derot |= STV090x_READ_DEMOD(state, CFR0);
-
-	derot = comp2(derot, 24);
-	int_1 = mclk >> 12;
-	int_2 = derot >> 12;
-
-	/* carrier_frequency = MasterClock * Reg / 2^24 */
-	tmp_1 = mclk % 0x1000;
-	tmp_2 = derot % 0x1000;
-
-	derot = (int_1 * int_2) +
-		((int_1 * tmp_2) >> 12) +
-		((int_2 * tmp_1) >> 12);
-
-	return derot;
-}
-
-static int stv090x_get_viterbi(struct stv090x_state *state)
-{
-	u32 reg, rate;
-
-	reg = STV090x_READ_DEMOD(state, VITCURPUN);
-	rate = STV090x_GETFIELD_Px(reg, VIT_CURPUN_FIELD);
-
-	switch (rate) {
-	case 13:
-		state->fec = STV090x_PR12;
-		break;
-
-	case 18:
-		state->fec = STV090x_PR23;
-		break;
-
-	case 21:
-		state->fec = STV090x_PR34;
-		break;
-
-	case 24:
-		state->fec = STV090x_PR56;
-		break;
-
-	case 25:
-		state->fec = STV090x_PR67;
-		break;
-
-	case 26:
-		state->fec = STV090x_PR78;
-		break;
-
-	default:
-		state->fec = STV090x_PRERR;
-		break;
-	}
-
-	return 0;
-}
-
-static enum stv090x_signal_state stv090x_get_sig_params(struct stv090x_state *state)
-{
-	struct dvb_frontend *fe = &state->frontend;
-
-	u8 tmg;
-	u32 reg;
-	s32 i = 0, offst_freq;
-
-	msleep(5);
-
-	if (state->algo == STV090x_BLIND_SEARCH) {
-		tmg = STV090x_READ_DEMOD(state, TMGREG2);
-		STV090x_WRITE_DEMOD(state, SFRSTEP, 0x5c);
-		while ((i <= 50) && (tmg != 0) && (tmg != 0xff)) {
-			tmg = STV090x_READ_DEMOD(state, TMGREG2);
-			msleep(5);
-			i += 5;
-		}
-	}
-	state->delsys = stv090x_get_std(state);
-
-	if (stv090x_i2c_gate_ctrl(state, 1) < 0)
-		goto err;
-
-	if (state->config->tuner_get_frequency) {
-		if (state->config->tuner_get_frequency(fe, &state->frequency) < 0)
-			goto err_gateoff;
-	}
-
-	if (stv090x_i2c_gate_ctrl(state, 0) < 0)
-		goto err;
-
-	offst_freq = stv090x_get_car_freq(state, state->internal->mclk) / 1000;
-	state->frequency += offst_freq;
-
-	if (stv090x_get_viterbi(state) < 0)
-		goto err;
-
-	reg = STV090x_READ_DEMOD(state, DMDMODCOD);
-	state->modcod = STV090x_GETFIELD_Px(reg, DEMOD_MODCOD_FIELD);
-	state->pilots = STV090x_GETFIELD_Px(reg, DEMOD_TYPE_FIELD) & 0x01;
-	state->frame_len = STV090x_GETFIELD_Px(reg, DEMOD_TYPE_FIELD) >> 1;
-	reg = STV090x_READ_DEMOD(state, TMGOBS);
-	state->rolloff = STV090x_GETFIELD_Px(reg, ROLLOFF_STATUS_FIELD);
-	reg = STV090x_READ_DEMOD(state, FECM);
-	state->inversion = STV090x_GETFIELD_Px(reg, IQINV_FIELD);
-
-	if ((state->algo == STV090x_BLIND_SEARCH) || (state->srate < 10000000)) {
-
-		if (stv090x_i2c_gate_ctrl(state, 1) < 0)
-			goto err;
-
-		if (state->config->tuner_get_frequency) {
-			if (state->config->tuner_get_frequency(fe, &state->frequency) < 0)
-				goto err_gateoff;
-		}
-
-		if (stv090x_i2c_gate_ctrl(state, 0) < 0)
-			goto err;
-
-		if (abs(offst_freq) <= ((state->search_range / 2000) + 500))
-			return STV090x_RANGEOK;
-		else if (abs(offst_freq) <= (stv090x_car_width(state->srate, state->rolloff) / 2000))
-			return STV090x_RANGEOK;
-		else
-			return STV090x_OUTOFRANGE; /* Out of Range */
-	} else {
-		if (abs(offst_freq) <= ((state->search_range / 2000) + 500))
-			return STV090x_RANGEOK;
-		else
-			return STV090x_OUTOFRANGE;
-	}
-
-	return STV090x_OUTOFRANGE;
-
-err_gateoff:
-	stv090x_i2c_gate_ctrl(state, 0);
-err:
-	dprintk(FE_ERROR, 1, "I/O error");
-	return -1;
-}
-
-static u32 stv090x_get_tmgoffst(struct stv090x_state *state, u32 srate)
-{
-	s32 offst_tmg;
-
-	offst_tmg  = STV090x_READ_DEMOD(state, TMGREG2) << 16;
-	offst_tmg |= STV090x_READ_DEMOD(state, TMGREG1) <<  8;
-	offst_tmg |= STV090x_READ_DEMOD(state, TMGREG0);
-
-	offst_tmg = comp2(offst_tmg, 24); /* 2's complement */
-	if (!offst_tmg)
-		offst_tmg = 1;
-
-	offst_tmg  = ((s32) srate * 10) / ((s32) 0x1000000 / offst_tmg);
-	offst_tmg /= 320;
-
-	return offst_tmg;
-}
-
-static u8 stv090x_optimize_carloop(struct stv090x_state *state, enum stv090x_modcod modcod, s32 pilots)
-{
-	u8 aclc = 0x29;
-	s32 i;
-	struct stv090x_long_frame_crloop *car_loop, *car_loop_qpsk_low, *car_loop_apsk_low;
-
-	if (state->internal->dev_ver == 0x20) {
-		car_loop		= stv090x_s2_crl_cut20;
-		car_loop_qpsk_low	= stv090x_s2_lowqpsk_crl_cut20;
-		car_loop_apsk_low	= stv090x_s2_apsk_crl_cut20;
-	} else {
-		/* >= Cut 3 */
-		car_loop		= stv090x_s2_crl_cut30;
-		car_loop_qpsk_low	= stv090x_s2_lowqpsk_crl_cut30;
-		car_loop_apsk_low	= stv090x_s2_apsk_crl_cut30;
-	}
-
-	if (modcod < STV090x_QPSK_12) {
-		i = 0;
-		while ((i < 3) && (modcod != car_loop_qpsk_low[i].modcod))
-			i++;
-
-		if (i >= 3)
-			i = 2;
-
-	} else {
-		i = 0;
-		while ((i < 14) && (modcod != car_loop[i].modcod))
-			i++;
-
-		if (i >= 14) {
-			i = 0;
-			while ((i < 11) && (modcod != car_loop_apsk_low[i].modcod))
-				i++;
-
-			if (i >= 11)
-				i = 10;
-		}
-	}
-
-	if (modcod <= STV090x_QPSK_25) {
-		if (pilots) {
-			if (state->srate <= 3000000)
-				aclc = car_loop_qpsk_low[i].crl_pilots_on_2;
-			else if (state->srate <= 7000000)
-				aclc = car_loop_qpsk_low[i].crl_pilots_on_5;
-			else if (state->srate <= 15000000)
-				aclc = car_loop_qpsk_low[i].crl_pilots_on_10;
-			else if (state->srate <= 25000000)
-				aclc = car_loop_qpsk_low[i].crl_pilots_on_20;
-			else
-				aclc = car_loop_qpsk_low[i].crl_pilots_on_30;
-		} else {
-			if (state->srate <= 3000000)
-				aclc = car_loop_qpsk_low[i].crl_pilots_off_2;
-			else if (state->srate <= 7000000)
-				aclc = car_loop_qpsk_low[i].crl_pilots_off_5;
-			else if (state->srate <= 15000000)
-				aclc = car_loop_qpsk_low[i].crl_pilots_off_10;
-			else if (state->srate <= 25000000)
-				aclc = car_loop_qpsk_low[i].crl_pilots_off_20;
-			else
-				aclc = car_loop_qpsk_low[i].crl_pilots_off_30;
-		}
-
-	} else if (modcod <= STV090x_8PSK_910) {
-		if (pilots) {
-			if (state->srate <= 3000000)
-				aclc = car_loop[i].crl_pilots_on_2;
-			else if (state->srate <= 7000000)
-				aclc = car_loop[i].crl_pilots_on_5;
-			else if (state->srate <= 15000000)
-				aclc = car_loop[i].crl_pilots_on_10;
-			else if (state->srate <= 25000000)
-				aclc = car_loop[i].crl_pilots_on_20;
-			else
-				aclc = car_loop[i].crl_pilots_on_30;
-		} else {
-			if (state->srate <= 3000000)
-				aclc = car_loop[i].crl_pilots_off_2;
-			else if (state->srate <= 7000000)
-				aclc = car_loop[i].crl_pilots_off_5;
-			else if (state->srate <= 15000000)
-				aclc = car_loop[i].crl_pilots_off_10;
-			else if (state->srate <= 25000000)
-				aclc = car_loop[i].crl_pilots_off_20;
-			else
-				aclc = car_loop[i].crl_pilots_off_30;
-		}
-	} else { /* 16APSK and 32APSK */
-		if (state->srate <= 3000000)
-			aclc = car_loop_apsk_low[i].crl_pilots_on_2;
-		else if (state->srate <= 7000000)
-			aclc = car_loop_apsk_low[i].crl_pilots_on_5;
-		else if (state->srate <= 15000000)
-			aclc = car_loop_apsk_low[i].crl_pilots_on_10;
-		else if (state->srate <= 25000000)
-			aclc = car_loop_apsk_low[i].crl_pilots_on_20;
-		else
-			aclc = car_loop_apsk_low[i].crl_pilots_on_30;
-	}
-
-	return aclc;
-}
-
-static u8 stv090x_optimize_carloop_short(struct stv090x_state *state)
-{
-	struct stv090x_short_frame_crloop *short_crl = NULL;
-	s32 index = 0;
-	u8 aclc = 0x0b;
-
-	switch (state->modulation) {
-	case STV090x_QPSK:
-	default:
-		index = 0;
-		break;
-	case STV090x_8PSK:
-		index = 1;
-		break;
-	case STV090x_16APSK:
-		index = 2;
-		break;
-	case STV090x_32APSK:
-		index = 3;
-		break;
-	}
-
-	if (state->internal->dev_ver >= 0x30) {
-		/* Cut 3.0 and up */
-		short_crl = stv090x_s2_short_crl_cut30;
-	} else {
-		/* Cut 2.0 and up: we don't support cuts older than 2.0 */
-		short_crl = stv090x_s2_short_crl_cut20;
-	}
-
-	if (state->srate <= 3000000)
-		aclc = short_crl[index].crl_2;
-	else if (state->srate <= 7000000)
-		aclc = short_crl[index].crl_5;
-	else if (state->srate <= 15000000)
-		aclc = short_crl[index].crl_10;
-	else if (state->srate <= 25000000)
-		aclc = short_crl[index].crl_20;
-	else
-		aclc = short_crl[index].crl_30;
-
-	return aclc;
-}
-
-static int stv090x_optimize_track(struct stv090x_state *state)
-{
-	struct dvb_frontend *fe = &state->frontend;
-
-	enum stv090x_modcod modcod;
-
-	s32 srate, pilots, aclc, f_1, f_0, i = 0, blind_tune = 0;
-	u32 reg;
-
-	srate  = stv090x_get_srate(state, state->internal->mclk);
-	srate += stv090x_get_tmgoffst(state, srate);
-
-	switch (state->delsys) {
-	case STV090x_DVBS1:
-	case STV090x_DSS:
-		if (state->search_mode == STV090x_SEARCH_AUTO) {
-			reg = STV090x_READ_DEMOD(state, DMDCFGMD);
-			STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 1);
-			STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 0);
-			if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
-				goto err;
-		}
-		reg = STV090x_READ_DEMOD(state, DEMOD);
-		STV090x_SETFIELD_Px(reg, ROLLOFF_CONTROL_FIELD, state->rolloff);
-		STV090x_SETFIELD_Px(reg, MANUAL_SXROLLOFF_FIELD, 0x01);
-		if (STV090x_WRITE_DEMOD(state, DEMOD, reg) < 0)
-			goto err;
-
-		if (state->internal->dev_ver >= 0x30) {
-			if (stv090x_get_viterbi(state) < 0)
-				goto err;
-
-			if (state->fec == STV090x_PR12) {
-				if (STV090x_WRITE_DEMOD(state, GAUSSR0, 0x98) < 0)
-					goto err;
-				if (STV090x_WRITE_DEMOD(state, CCIR0, 0x18) < 0)
-					goto err;
-			} else {
-				if (STV090x_WRITE_DEMOD(state, GAUSSR0, 0x18) < 0)
-					goto err;
-				if (STV090x_WRITE_DEMOD(state, CCIR0, 0x18) < 0)
-					goto err;
-			}
-		}
-
-		if (STV090x_WRITE_DEMOD(state, ERRCTRL1, 0x75) < 0)
-			goto err;
-		break;
-
-	case STV090x_DVBS2:
-		reg = STV090x_READ_DEMOD(state, DMDCFGMD);
-		STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 0);
-		STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 1);
-		if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
-			goto err;
-		if (state->internal->dev_ver >= 0x30) {
-			if (STV090x_WRITE_DEMOD(state, ACLC, 0) < 0)
-				goto err;
-			if (STV090x_WRITE_DEMOD(state, BCLC, 0) < 0)
-				goto err;
-		}
-		if (state->frame_len == STV090x_LONG_FRAME) {
-			reg = STV090x_READ_DEMOD(state, DMDMODCOD);
-			modcod = STV090x_GETFIELD_Px(reg, DEMOD_MODCOD_FIELD);
-			pilots = STV090x_GETFIELD_Px(reg, DEMOD_TYPE_FIELD) & 0x01;
-			aclc = stv090x_optimize_carloop(state, modcod, pilots);
-			if (modcod <= STV090x_QPSK_910) {
-				STV090x_WRITE_DEMOD(state, ACLC2S2Q, aclc);
-			} else if (modcod <= STV090x_8PSK_910) {
-				if (STV090x_WRITE_DEMOD(state, ACLC2S2Q, 0x2a) < 0)
-					goto err;
-				if (STV090x_WRITE_DEMOD(state, ACLC2S28, aclc) < 0)
-					goto err;
-			}
-			if ((state->demod_mode == STV090x_SINGLE) && (modcod > STV090x_8PSK_910)) {
-				if (modcod <= STV090x_16APSK_910) {
-					if (STV090x_WRITE_DEMOD(state, ACLC2S2Q, 0x2a) < 0)
-						goto err;
-					if (STV090x_WRITE_DEMOD(state, ACLC2S216A, aclc) < 0)
-						goto err;
-				} else {
-					if (STV090x_WRITE_DEMOD(state, ACLC2S2Q, 0x2a) < 0)
-						goto err;
-					if (STV090x_WRITE_DEMOD(state, ACLC2S232A, aclc) < 0)
-						goto err;
-				}
-			}
-		} else {
-			/*Carrier loop setting for short frame*/
-			aclc = stv090x_optimize_carloop_short(state);
-			if (state->modulation == STV090x_QPSK) {
-				if (STV090x_WRITE_DEMOD(state, ACLC2S2Q, aclc) < 0)
-					goto err;
-			} else if (state->modulation == STV090x_8PSK) {
-				if (STV090x_WRITE_DEMOD(state, ACLC2S2Q, 0x2a) < 0)
-					goto err;
-				if (STV090x_WRITE_DEMOD(state, ACLC2S28, aclc) < 0)
-					goto err;
-			} else if (state->modulation == STV090x_16APSK) {
-				if (STV090x_WRITE_DEMOD(state, ACLC2S2Q, 0x2a) < 0)
-					goto err;
-				if (STV090x_WRITE_DEMOD(state, ACLC2S216A, aclc) < 0)
-					goto err;
-			} else if (state->modulation == STV090x_32APSK)  {
-				if (STV090x_WRITE_DEMOD(state, ACLC2S2Q, 0x2a) < 0)
-					goto err;
-				if (STV090x_WRITE_DEMOD(state, ACLC2S232A, aclc) < 0)
-					goto err;
-			}
-		}
-
-		STV090x_WRITE_DEMOD(state, ERRCTRL1, 0x67); /* PER */
-		break;
-
-	case STV090x_ERROR:
-	default:
-		reg = STV090x_READ_DEMOD(state, DMDCFGMD);
-		STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 1);
-		STV090x_SETFIELD_Px(reg, DVBS2_ENABLE_FIELD, 1);
-		if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
-			goto err;
-		break;
-	}
-
-	f_1 = STV090x_READ_DEMOD(state, CFR2);
-	f_0 = STV090x_READ_DEMOD(state, CFR1);
-	reg = STV090x_READ_DEMOD(state, TMGOBS);
-
-	if (state->algo == STV090x_BLIND_SEARCH) {
-		STV090x_WRITE_DEMOD(state, SFRSTEP, 0x00);
-		reg = STV090x_READ_DEMOD(state, DMDCFGMD);
-		STV090x_SETFIELD_Px(reg, SCAN_ENABLE_FIELD, 0x00);
-		STV090x_SETFIELD_Px(reg, CFR_AUTOSCAN_FIELD, 0x00);
-		if (STV090x_WRITE_DEMOD(state, DMDCFGMD, reg) < 0)
-			goto err;
-		if (STV090x_WRITE_DEMOD(state, TMGCFG2, 0xc1) < 0)
-			goto err;
-
-		if (stv090x_set_srate(state, srate) < 0)
-			goto err;
-		blind_tune = 1;
-
-		if (stv090x_dvbs_track_crl(state) < 0)
-			goto err;
-	}
-
-	if (state->internal->dev_ver >= 0x20) {
-		if ((state->search_mode == STV090x_SEARCH_DVBS1)	||
-		    (state->search_mode == STV090x_SEARCH_DSS)		||
-		    (state->search_mode == STV090x_SEARCH_AUTO)) {
-
-			if (STV090x_WRITE_DEMOD(state, VAVSRVIT, 0x0a) < 0)
-				goto err;
-			if (STV090x_WRITE_DEMOD(state, VITSCALE, 0x00) < 0)
-				goto err;
-		}
-	}
-
-	if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x38) < 0)
-		goto err;
-
-	/* AUTO tracking MODE */
-	if (STV090x_WRITE_DEMOD(state, SFRUP1, 0x80) < 0)
-		goto err;
-	/* AUTO tracking MODE */
-	if (STV090x_WRITE_DEMOD(state, SFRLOW1, 0x80) < 0)
-		goto err;
-
-	if ((state->internal->dev_ver >= 0x20) || (blind_tune == 1) ||
-	    (state->srate < 10000000)) {
-		/* update initial carrier freq with the found freq offset */
-		if (STV090x_WRITE_DEMOD(state, CFRINIT1, f_1) < 0)
-			goto err;
-		if (STV090x_WRITE_DEMOD(state, CFRINIT0, f_0) < 0)
-			goto err;
-		state->tuner_bw = stv090x_car_width(srate, state->rolloff) + 10000000;
-
-		if ((state->internal->dev_ver >= 0x20) || (blind_tune == 1)) {
-
-			if (state->algo != STV090x_WARM_SEARCH) {
-
-				if (stv090x_i2c_gate_ctrl(state, 1) < 0)
-					goto err;
-
-				if (state->config->tuner_set_bandwidth) {
-					if (state->config->tuner_set_bandwidth(fe, state->tuner_bw) < 0)
-						goto err_gateoff;
-				}
-
-				if (stv090x_i2c_gate_ctrl(state, 0) < 0)
-					goto err;
-
-			}
-		}
-		if ((state->algo == STV090x_BLIND_SEARCH) || (state->srate < 10000000))
-			msleep(50); /* blind search: wait 50ms for SR stabilization */
-		else
-			msleep(5);
-
-		stv090x_get_lock_tmg(state);
-
-		if (!(stv090x_get_dmdlock(state, (state->DemodTimeout / 2)))) {
-			if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0)
-				goto err;
-			if (STV090x_WRITE_DEMOD(state, CFRINIT1, f_1) < 0)
-				goto err;
-			if (STV090x_WRITE_DEMOD(state, CFRINIT0, f_0) < 0)
-				goto err;
-			if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x18) < 0)
-				goto err;
-
-			i = 0;
-
-			while ((!(stv090x_get_dmdlock(state, (state->DemodTimeout / 2)))) && (i <= 2)) {
-
-				if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0)
-					goto err;
-				if (STV090x_WRITE_DEMOD(state, CFRINIT1, f_1) < 0)
-					goto err;
-				if (STV090x_WRITE_DEMOD(state, CFRINIT0, f_0) < 0)
-					goto err;
-				if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x18) < 0)
-					goto err;
-				i++;
-			}
-		}
-
-	}
-
-	if (state->internal->dev_ver >= 0x20) {
-		if (STV090x_WRITE_DEMOD(state, CARFREQ, 0x49) < 0)
-			goto err;
-	}
-
-	if ((state->delsys == STV090x_DVBS1) || (state->delsys == STV090x_DSS))
-		stv090x_set_vit_thtracq(state);
-
-	return 0;
-
-err_gateoff:
-	stv090x_i2c_gate_ctrl(state, 0);
-err:
-	dprintk(FE_ERROR, 1, "I/O error");
-	return -1;
-}
-
-static int stv090x_get_feclock(struct stv090x_state *state, s32 timeout)
-{
-	s32 timer = 0, lock = 0, stat;
-	u32 reg;
-
-	while ((timer < timeout) && (!lock)) {
-		reg = STV090x_READ_DEMOD(state, DMDSTATE);
-		stat = STV090x_GETFIELD_Px(reg, HEADER_MODE_FIELD);
-
-		switch (stat) {
-		case 0: /* searching */
-		case 1: /* first PLH detected */
-		default:
-			lock = 0;
-			break;
-
-		case 2: /* DVB-S2 mode */
-			reg = STV090x_READ_DEMOD(state, PDELSTATUS1);
-			lock = STV090x_GETFIELD_Px(reg, PKTDELIN_LOCK_FIELD);
-			break;
-
-		case 3: /* DVB-S1/legacy mode */
-			reg = STV090x_READ_DEMOD(state, VSTATUSVIT);
-			lock = STV090x_GETFIELD_Px(reg, LOCKEDVIT_FIELD);
-			break;
-		}
-		if (!lock) {
-			msleep(10);
-			timer += 10;
-		}
-	}
-	return lock;
-}
-
-static int stv090x_get_lock(struct stv090x_state *state, s32 timeout_dmd, s32 timeout_fec)
-{
-	u32 reg;
-	s32 timer = 0;
-	int lock;
-
-	lock = stv090x_get_dmdlock(state, timeout_dmd);
-	if (lock)
-		lock = stv090x_get_feclock(state, timeout_fec);
-
-	if (lock) {
-		lock = 0;
-
-		while ((timer < timeout_fec) && (!lock)) {
-			reg = STV090x_READ_DEMOD(state, TSSTATUS);
-			lock = STV090x_GETFIELD_Px(reg, TSFIFO_LINEOK_FIELD);
-			msleep(1);
-			timer++;
-		}
-	}
-
-	return lock;
-}
-
-static int stv090x_set_s2rolloff(struct stv090x_state *state)
-{
-	u32 reg;
-
-	if (state->internal->dev_ver <= 0x20) {
-		/* rolloff to auto mode if DVBS2 */
-		reg = STV090x_READ_DEMOD(state, DEMOD);
-		STV090x_SETFIELD_Px(reg, MANUAL_SXROLLOFF_FIELD, 0x00);
-		if (STV090x_WRITE_DEMOD(state, DEMOD, reg) < 0)
-			goto err;
-	} else {
-		/* DVB-S2 rolloff to auto mode if DVBS2 */
-		reg = STV090x_READ_DEMOD(state, DEMOD);
-		STV090x_SETFIELD_Px(reg, MANUAL_S2ROLLOFF_FIELD, 0x00);
-		if (STV090x_WRITE_DEMOD(state, DEMOD, reg) < 0)
-			goto err;
-	}
-	return 0;
-err:
-	dprintk(FE_ERROR, 1, "I/O error");
-	return -1;
-}
-
-
-static enum stv090x_signal_state stv090x_algo(struct stv090x_state *state)
-{
-	struct dvb_frontend *fe = &state->frontend;
-	enum stv090x_signal_state signal_state = STV090x_NOCARRIER;
-	u32 reg;
-	s32 agc1_power, power_iq = 0, i;
-	int lock = 0, low_sr = 0;
-
-	reg = STV090x_READ_DEMOD(state, TSCFGH);
-	STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 1); /* Stop path 1 stream merger */
-	if (STV090x_WRITE_DEMOD(state, TSCFGH, reg) < 0)
-		goto err;
-
-	if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x5c) < 0) /* Demod stop */
-		goto err;
-
-	if (state->internal->dev_ver >= 0x20) {
-		if (state->srate > 5000000) {
-			if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x9e) < 0)
-				goto err;
-		} else {
-			if (STV090x_WRITE_DEMOD(state, CORRELABS, 0x82) < 0)
-				goto err;
-		}
-	}
-
-	stv090x_get_lock_tmg(state);
-
-	if (state->algo == STV090x_BLIND_SEARCH) {
-		state->tuner_bw = 2 * 36000000; /* wide bw for unknown srate */
-		if (STV090x_WRITE_DEMOD(state, TMGCFG2, 0xc0) < 0) /* wider srate scan */
-			goto err;
-		if (STV090x_WRITE_DEMOD(state, CORRELMANT, 0x70) < 0)
-			goto err;
-		if (stv090x_set_srate(state, 1000000) < 0) /* initial srate = 1Msps */
-			goto err;
-	} else {
-		/* known srate */
-		if (STV090x_WRITE_DEMOD(state, DMDTOM, 0x20) < 0)
-			goto err;
-		if (STV090x_WRITE_DEMOD(state, TMGCFG, 0xd2) < 0)
-			goto err;
-
-		if (state->srate < 2000000) {
-			/* SR < 2MSPS */
-			if (STV090x_WRITE_DEMOD(state, CORRELMANT, 0x63) < 0)
-				goto err;
-		} else {
-			/* SR >= 2Msps */
-			if (STV090x_WRITE_DEMOD(state, CORRELMANT, 0x70) < 0)
-				goto err;
-		}
-
-		if (STV090x_WRITE_DEMOD(state, AGC2REF, 0x38) < 0)
-			goto err;
-
-		if (state->internal->dev_ver >= 0x20) {
-			if (STV090x_WRITE_DEMOD(state, KREFTMG, 0x5a) < 0)
-				goto err;
-			if (state->algo == STV090x_COLD_SEARCH)
-				state->tuner_bw = (15 * (stv090x_car_width(state->srate, state->rolloff) + 10000000)) / 10;
-			else if (state->algo == STV090x_WARM_SEARCH)
-				state->tuner_bw = stv090x_car_width(state->srate, state->rolloff) + 10000000;
-		}
-
-		/* if cold start or warm  (Symbolrate is known)
-		 * use a Narrow symbol rate scan range
-		 */
-		if (STV090x_WRITE_DEMOD(state, TMGCFG2, 0xc1) < 0) /* narrow srate scan */
-			goto err;
-
-		if (stv090x_set_srate(state, state->srate) < 0)
-			goto err;
-
-		if (stv090x_set_max_srate(state, state->internal->mclk,
-					  state->srate) < 0)
-			goto err;
-		if (stv090x_set_min_srate(state, state->internal->mclk,
-					  state->srate) < 0)
-			goto err;
-
-		if (state->srate >= 10000000)
-			low_sr = 0;
-		else
-			low_sr = 1;
-	}
-
-	/* Setup tuner */
-	if (stv090x_i2c_gate_ctrl(state, 1) < 0)
-		goto err;
-
-	if (state->config->tuner_set_bbgain) {
-		reg = state->config->tuner_bbgain;
-		if (reg == 0)
-			reg = 10; /* default: 10dB */
-		if (state->config->tuner_set_bbgain(fe, reg) < 0)
-			goto err_gateoff;
-	}
-
-	if (state->config->tuner_set_frequency) {
-		if (state->config->tuner_set_frequency(fe, state->frequency) < 0)
-			goto err_gateoff;
-	}
-
-	if (state->config->tuner_set_bandwidth) {
-		if (state->config->tuner_set_bandwidth(fe, state->tuner_bw) < 0)
-			goto err_gateoff;
-	}
-
-	if (stv090x_i2c_gate_ctrl(state, 0) < 0)
-		goto err;
-
-	msleep(50);
-
-	if (state->config->tuner_get_status) {
-		if (stv090x_i2c_gate_ctrl(state, 1) < 0)
-			goto err;
-		if (state->config->tuner_get_status(fe, &reg) < 0)
-			goto err_gateoff;
-		if (stv090x_i2c_gate_ctrl(state, 0) < 0)
-			goto err;
-
-		if (reg)
-			dprintk(FE_DEBUG, 1, "Tuner phase locked");
-		else {
-			dprintk(FE_DEBUG, 1, "Tuner unlocked");
-			return STV090x_NOCARRIER;
-		}
-	}
-
-	msleep(10);
-	agc1_power = MAKEWORD16(STV090x_READ_DEMOD(state, AGCIQIN1),
-				STV090x_READ_DEMOD(state, AGCIQIN0));
-
-	if (agc1_power == 0) {
-		/* If AGC1 integrator value is 0
-		 * then read POWERI, POWERQ
-		 */
-		for (i = 0; i < 5; i++) {
-			power_iq += (STV090x_READ_DEMOD(state, POWERI) +
-				     STV090x_READ_DEMOD(state, POWERQ)) >> 1;
-		}
-		power_iq /= 5;
-	}
-
-	if ((agc1_power == 0) && (power_iq < STV090x_IQPOWER_THRESHOLD)) {
-		dprintk(FE_ERROR, 1, "No Signal: POWER_IQ=0x%02x", power_iq);
-		lock = 0;
-		signal_state = STV090x_NOAGC1;
-	} else {
-		reg = STV090x_READ_DEMOD(state, DEMOD);
-		STV090x_SETFIELD_Px(reg, SPECINV_CONTROL_FIELD, state->inversion);
-
-		if (state->internal->dev_ver <= 0x20) {
-			/* rolloff to auto mode if DVBS2 */
-			STV090x_SETFIELD_Px(reg, MANUAL_SXROLLOFF_FIELD, 1);
-		} else {
-			/* DVB-S2 rolloff to auto mode if DVBS2 */
-			STV090x_SETFIELD_Px(reg, MANUAL_S2ROLLOFF_FIELD, 1);
-		}
-		if (STV090x_WRITE_DEMOD(state, DEMOD, reg) < 0)
-			goto err;
-
-		if (stv090x_delivery_search(state) < 0)
-			goto err;
-
-		if (state->algo != STV090x_BLIND_SEARCH) {
-			if (stv090x_start_search(state) < 0)
-				goto err;
-		}
-	}
-
-	if (signal_state == STV090x_NOAGC1)
-		return signal_state;
-
-	if (state->algo == STV090x_BLIND_SEARCH)
-		lock = stv090x_blind_search(state);
-
-	else if (state->algo == STV090x_COLD_SEARCH)
-		lock = stv090x_get_coldlock(state, state->DemodTimeout);
-
-	else if (state->algo == STV090x_WARM_SEARCH)
-		lock = stv090x_get_dmdlock(state, state->DemodTimeout);
-
-	if ((!lock) && (state->algo == STV090x_COLD_SEARCH)) {
-		if (!low_sr) {
-			if (stv090x_chk_tmg(state))
-				lock = stv090x_sw_algo(state);
-		}
-	}
-
-	if (lock)
-		signal_state = stv090x_get_sig_params(state);
-
-	if ((lock) && (signal_state == STV090x_RANGEOK)) { /* signal within Range */
-		stv090x_optimize_track(state);
-
-		if (state->internal->dev_ver >= 0x20) {
-			/* >= Cut 2.0 :release TS reset after
-			 * demod lock and optimized Tracking
-			 */
-			reg = STV090x_READ_DEMOD(state, TSCFGH);
-			STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0); /* release merger reset */
-			if (STV090x_WRITE_DEMOD(state, TSCFGH, reg) < 0)
-				goto err;
-
-			msleep(3);
-
-			STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 1); /* merger reset */
-			if (STV090x_WRITE_DEMOD(state, TSCFGH, reg) < 0)
-				goto err;
-
-			STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0); /* release merger reset */
-			if (STV090x_WRITE_DEMOD(state, TSCFGH, reg) < 0)
-				goto err;
-		}
-
-		lock = stv090x_get_lock(state, state->FecTimeout,
-				state->FecTimeout);
-		if (lock) {
-			if (state->delsys == STV090x_DVBS2) {
-				stv090x_set_s2rolloff(state);
-
-				reg = STV090x_READ_DEMOD(state, PDELCTRL2);
-				STV090x_SETFIELD_Px(reg, RESET_UPKO_COUNT, 1);
-				if (STV090x_WRITE_DEMOD(state, PDELCTRL2, reg) < 0)
-					goto err;
-				/* Reset DVBS2 packet delinator error counter */
-				reg = STV090x_READ_DEMOD(state, PDELCTRL2);
-				STV090x_SETFIELD_Px(reg, RESET_UPKO_COUNT, 0);
-				if (STV090x_WRITE_DEMOD(state, PDELCTRL2, reg) < 0)
-					goto err;
-
-				if (STV090x_WRITE_DEMOD(state, ERRCTRL1, 0x67) < 0) /* PER */
-					goto err;
-			} else {
-				if (STV090x_WRITE_DEMOD(state, ERRCTRL1, 0x75) < 0)
-					goto err;
-			}
-			/* Reset the Total packet counter */
-			if (STV090x_WRITE_DEMOD(state, FBERCPT4, 0x00) < 0)
-				goto err;
-			/* Reset the packet Error counter2 */
-			if (STV090x_WRITE_DEMOD(state, ERRCTRL2, 0xc1) < 0)
-				goto err;
-		} else {
-			signal_state = STV090x_NODATA;
-			stv090x_chk_signal(state);
-		}
-	}
-	return signal_state;
-
-err_gateoff:
-	stv090x_i2c_gate_ctrl(state, 0);
-err:
-	dprintk(FE_ERROR, 1, "I/O error");
-	return -1;
-}
-
-static enum dvbfe_search stv090x_search(struct dvb_frontend *fe)
-{
-	struct stv090x_state *state = fe->demodulator_priv;
-	struct dtv_frontend_properties *props = &fe->dtv_property_cache;
-
-	if (props->frequency == 0)
-		return DVBFE_ALGO_SEARCH_INVALID;
-
-	state->delsys = props->delivery_system;
-	state->frequency = props->frequency;
-	state->srate = props->symbol_rate;
-	state->search_mode = STV090x_SEARCH_AUTO;
-	state->algo = STV090x_COLD_SEARCH;
-	state->fec = STV090x_PRERR;
-	if (state->srate > 10000000) {
-		dprintk(FE_DEBUG, 1, "Search range: 10 MHz");
-		state->search_range = 10000000;
-	} else {
-		dprintk(FE_DEBUG, 1, "Search range: 5 MHz");
-		state->search_range = 5000000;
-	}
-
-	if (stv090x_algo(state) == STV090x_RANGEOK) {
-		dprintk(FE_DEBUG, 1, "Search success!");
-		return DVBFE_ALGO_SEARCH_SUCCESS;
-	} else {
-		dprintk(FE_DEBUG, 1, "Search failed!");
-		return DVBFE_ALGO_SEARCH_FAILED;
-	}
-
-	return DVBFE_ALGO_SEARCH_ERROR;
-}
-
-static int stv090x_read_status(struct dvb_frontend *fe, enum fe_status *status)
-{
-	struct stv090x_state *state = fe->demodulator_priv;
-	u32 reg, dstatus;
-	u8 search_state;
-
-	*status = 0;
-
-	dstatus = STV090x_READ_DEMOD(state, DSTATUS);
-	if (STV090x_GETFIELD_Px(dstatus, CAR_LOCK_FIELD))
-		*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER;
-
-	reg = STV090x_READ_DEMOD(state, DMDSTATE);
-	search_state = STV090x_GETFIELD_Px(reg, HEADER_MODE_FIELD);
-
-	switch (search_state) {
-	case 0: /* searching */
-	case 1: /* first PLH detected */
-	default:
-		dprintk(FE_DEBUG, 1, "Status: Unlocked (Searching ..)");
-		break;
-
-	case 2: /* DVB-S2 mode */
-		dprintk(FE_DEBUG, 1, "Delivery system: DVB-S2");
-		if (STV090x_GETFIELD_Px(dstatus, LOCK_DEFINITIF_FIELD)) {
-			reg = STV090x_READ_DEMOD(state, PDELSTATUS1);
-			if (STV090x_GETFIELD_Px(reg, PKTDELIN_LOCK_FIELD)) {
-				*status |= FE_HAS_VITERBI;
-				reg = STV090x_READ_DEMOD(state, TSSTATUS);
-				if (STV090x_GETFIELD_Px(reg, TSFIFO_LINEOK_FIELD))
-					*status |= FE_HAS_SYNC | FE_HAS_LOCK;
-			}
-		}
-		break;
-
-	case 3: /* DVB-S1/legacy mode */
-		dprintk(FE_DEBUG, 1, "Delivery system: DVB-S");
-		if (STV090x_GETFIELD_Px(dstatus, LOCK_DEFINITIF_FIELD)) {
-			reg = STV090x_READ_DEMOD(state, VSTATUSVIT);
-			if (STV090x_GETFIELD_Px(reg, LOCKEDVIT_FIELD)) {
-				*status |= FE_HAS_VITERBI;
-				reg = STV090x_READ_DEMOD(state, TSSTATUS);
-				if (STV090x_GETFIELD_Px(reg, TSFIFO_LINEOK_FIELD))
-					*status |= FE_HAS_SYNC | FE_HAS_LOCK;
-			}
-		}
-		break;
-	}
-
-	return 0;
-}
-
-static int stv090x_read_per(struct dvb_frontend *fe, u32 *per)
-{
-	struct stv090x_state *state = fe->demodulator_priv;
-
-	s32 count_4, count_3, count_2, count_1, count_0, count;
-	u32 reg, h, m, l;
-	enum fe_status status;
-
-	stv090x_read_status(fe, &status);
-	if (!(status & FE_HAS_LOCK)) {
-		*per = 1 << 23; /* Max PER */
-	} else {
-		/* Counter 2 */
-		reg = STV090x_READ_DEMOD(state, ERRCNT22);
-		h = STV090x_GETFIELD_Px(reg, ERR_CNT2_FIELD);
-
-		reg = STV090x_READ_DEMOD(state, ERRCNT21);
-		m = STV090x_GETFIELD_Px(reg, ERR_CNT21_FIELD);
-
-		reg = STV090x_READ_DEMOD(state, ERRCNT20);
-		l = STV090x_GETFIELD_Px(reg, ERR_CNT20_FIELD);
-
-		*per = ((h << 16) | (m << 8) | l);
-
-		count_4 = STV090x_READ_DEMOD(state, FBERCPT4);
-		count_3 = STV090x_READ_DEMOD(state, FBERCPT3);
-		count_2 = STV090x_READ_DEMOD(state, FBERCPT2);
-		count_1 = STV090x_READ_DEMOD(state, FBERCPT1);
-		count_0 = STV090x_READ_DEMOD(state, FBERCPT0);
-
-		if ((!count_4) && (!count_3)) {
-			count  = (count_2 & 0xff) << 16;
-			count |= (count_1 & 0xff) <<  8;
-			count |=  count_0 & 0xff;
-		} else {
-			count = 1 << 24;
-		}
-		if (count == 0)
-			*per = 1;
-	}
-	if (STV090x_WRITE_DEMOD(state, FBERCPT4, 0) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, ERRCTRL2, 0xc1) < 0)
-		goto err;
-
-	return 0;
-err:
-	dprintk(FE_ERROR, 1, "I/O error");
-	return -1;
-}
-
-static int stv090x_table_lookup(const struct stv090x_tab *tab, int max, int val)
-{
-	int res = 0;
-	int min = 0, med;
-
-	if ((val >= tab[min].read && val < tab[max].read) ||
-	    (val >= tab[max].read && val < tab[min].read)) {
-		while ((max - min) > 1) {
-			med = (max + min) / 2;
-			if ((val >= tab[min].read && val < tab[med].read) ||
-			    (val >= tab[med].read && val < tab[min].read))
-				max = med;
-			else
-				min = med;
-		}
-		res = ((val - tab[min].read) *
-		       (tab[max].real - tab[min].real) /
-		       (tab[max].read - tab[min].read)) +
-			tab[min].real;
-	} else {
-		if (tab[min].read < tab[max].read) {
-			if (val < tab[min].read)
-				res = tab[min].real;
-			else if (val >= tab[max].read)
-				res = tab[max].real;
-		} else {
-			if (val >= tab[min].read)
-				res = tab[min].real;
-			else if (val < tab[max].read)
-				res = tab[max].real;
-		}
-	}
-
-	return res;
-}
-
-static int stv090x_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
-{
-	struct stv090x_state *state = fe->demodulator_priv;
-	u32 reg;
-	s32 agc_0, agc_1, agc;
-	s32 str;
-
-	reg = STV090x_READ_DEMOD(state, AGCIQIN1);
-	agc_1 = STV090x_GETFIELD_Px(reg, AGCIQ_VALUE_FIELD);
-	reg = STV090x_READ_DEMOD(state, AGCIQIN0);
-	agc_0 = STV090x_GETFIELD_Px(reg, AGCIQ_VALUE_FIELD);
-	agc = MAKEWORD16(agc_1, agc_0);
-
-	str = stv090x_table_lookup(stv090x_rf_tab,
-		ARRAY_SIZE(stv090x_rf_tab) - 1, agc);
-	if (agc > stv090x_rf_tab[0].read)
-		str = 0;
-	else if (agc < stv090x_rf_tab[ARRAY_SIZE(stv090x_rf_tab) - 1].read)
-		str = -100;
-	*strength = (str + 100) * 0xFFFF / 100;
-
-	return 0;
-}
-
-static int stv090x_read_cnr(struct dvb_frontend *fe, u16 *cnr)
-{
-	struct stv090x_state *state = fe->demodulator_priv;
-	u32 reg_0, reg_1, reg, i;
-	s32 val_0, val_1, val = 0;
-	u8 lock_f;
-	s32 div;
-	u32 last;
-
-	switch (state->delsys) {
-	case STV090x_DVBS2:
-		reg = STV090x_READ_DEMOD(state, DSTATUS);
-		lock_f = STV090x_GETFIELD_Px(reg, LOCK_DEFINITIF_FIELD);
-		if (lock_f) {
-			msleep(5);
-			for (i = 0; i < 16; i++) {
-				reg_1 = STV090x_READ_DEMOD(state, NNOSPLHT1);
-				val_1 = STV090x_GETFIELD_Px(reg_1, NOSPLHT_NORMED_FIELD);
-				reg_0 = STV090x_READ_DEMOD(state, NNOSPLHT0);
-				val_0 = STV090x_GETFIELD_Px(reg_0, NOSPLHT_NORMED_FIELD);
-				val  += MAKEWORD16(val_1, val_0);
-				msleep(1);
-			}
-			val /= 16;
-			last = ARRAY_SIZE(stv090x_s2cn_tab) - 1;
-			div = stv090x_s2cn_tab[0].read -
-			      stv090x_s2cn_tab[last].read;
-			*cnr = 0xFFFF - ((val * 0xFFFF) / div);
-		}
-		break;
-
-	case STV090x_DVBS1:
-	case STV090x_DSS:
-		reg = STV090x_READ_DEMOD(state, DSTATUS);
-		lock_f = STV090x_GETFIELD_Px(reg, LOCK_DEFINITIF_FIELD);
-		if (lock_f) {
-			msleep(5);
-			for (i = 0; i < 16; i++) {
-				reg_1 = STV090x_READ_DEMOD(state, NOSDATAT1);
-				val_1 = STV090x_GETFIELD_Px(reg_1, NOSDATAT_UNNORMED_FIELD);
-				reg_0 = STV090x_READ_DEMOD(state, NOSDATAT0);
-				val_0 = STV090x_GETFIELD_Px(reg_0, NOSDATAT_UNNORMED_FIELD);
-				val  += MAKEWORD16(val_1, val_0);
-				msleep(1);
-			}
-			val /= 16;
-			last = ARRAY_SIZE(stv090x_s1cn_tab) - 1;
-			div = stv090x_s1cn_tab[0].read -
-			      stv090x_s1cn_tab[last].read;
-			*cnr = 0xFFFF - ((val * 0xFFFF) / div);
-		}
-		break;
-	default:
-		break;
-	}
-
-	return 0;
-}
-
-static int stv090x_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
-{
-	struct stv090x_state *state = fe->demodulator_priv;
-	u32 reg;
-
-	reg = STV090x_READ_DEMOD(state, DISTXCTL);
-	switch (tone) {
-	case SEC_TONE_ON:
-		STV090x_SETFIELD_Px(reg, DISTX_MODE_FIELD, 0);
-		STV090x_SETFIELD_Px(reg, DISEQC_RESET_FIELD, 1);
-		if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0)
-			goto err;
-		STV090x_SETFIELD_Px(reg, DISEQC_RESET_FIELD, 0);
-		if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0)
-			goto err;
-		break;
-
-	case SEC_TONE_OFF:
-		STV090x_SETFIELD_Px(reg, DISTX_MODE_FIELD, 0);
-		STV090x_SETFIELD_Px(reg, DISEQC_RESET_FIELD, 1);
-		if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0)
-			goto err;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-err:
-	dprintk(FE_ERROR, 1, "I/O error");
-	return -1;
-}
-
-
-static enum dvbfe_algo stv090x_frontend_algo(struct dvb_frontend *fe)
-{
-	return DVBFE_ALGO_CUSTOM;
-}
-
-static int stv090x_send_diseqc_msg(struct dvb_frontend *fe, struct dvb_diseqc_master_cmd *cmd)
-{
-	struct stv090x_state *state = fe->demodulator_priv;
-	u32 reg, idle = 0, fifo_full = 1;
-	int i;
-
-	reg = STV090x_READ_DEMOD(state, DISTXCTL);
-
-	STV090x_SETFIELD_Px(reg, DISTX_MODE_FIELD,
-		(state->config->diseqc_envelope_mode) ? 4 : 2);
-	STV090x_SETFIELD_Px(reg, DISEQC_RESET_FIELD, 1);
-	if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0)
-		goto err;
-	STV090x_SETFIELD_Px(reg, DISEQC_RESET_FIELD, 0);
-	if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0)
-		goto err;
-
-	STV090x_SETFIELD_Px(reg, DIS_PRECHARGE_FIELD, 1);
-	if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0)
-		goto err;
-
-	for (i = 0; i < cmd->msg_len; i++) {
-
-		while (fifo_full) {
-			reg = STV090x_READ_DEMOD(state, DISTXSTATUS);
-			fifo_full = STV090x_GETFIELD_Px(reg, FIFO_FULL_FIELD);
-		}
-
-		if (STV090x_WRITE_DEMOD(state, DISTXDATA, cmd->msg[i]) < 0)
-			goto err;
-	}
-	reg = STV090x_READ_DEMOD(state, DISTXCTL);
-	STV090x_SETFIELD_Px(reg, DIS_PRECHARGE_FIELD, 0);
-	if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0)
-		goto err;
-
-	i = 0;
-
-	while ((!idle) && (i < 10)) {
-		reg = STV090x_READ_DEMOD(state, DISTXSTATUS);
-		idle = STV090x_GETFIELD_Px(reg, TX_IDLE_FIELD);
-		msleep(10);
-		i++;
-	}
-
-	return 0;
-err:
-	dprintk(FE_ERROR, 1, "I/O error");
-	return -1;
-}
-
-static int stv090x_send_diseqc_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t burst)
-{
-	struct stv090x_state *state = fe->demodulator_priv;
-	u32 reg, idle = 0, fifo_full = 1;
-	u8 mode, value;
-	int i;
-
-	reg = STV090x_READ_DEMOD(state, DISTXCTL);
-
-	if (burst == SEC_MINI_A) {
-		mode = (state->config->diseqc_envelope_mode) ? 5 : 3;
-		value = 0x00;
-	} else {
-		mode = (state->config->diseqc_envelope_mode) ? 4 : 2;
-		value = 0xFF;
-	}
-
-	STV090x_SETFIELD_Px(reg, DISTX_MODE_FIELD, mode);
-	STV090x_SETFIELD_Px(reg, DISEQC_RESET_FIELD, 1);
-	if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0)
-		goto err;
-	STV090x_SETFIELD_Px(reg, DISEQC_RESET_FIELD, 0);
-	if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0)
-		goto err;
-
-	STV090x_SETFIELD_Px(reg, DIS_PRECHARGE_FIELD, 1);
-	if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0)
-		goto err;
-
-	while (fifo_full) {
-		reg = STV090x_READ_DEMOD(state, DISTXSTATUS);
-		fifo_full = STV090x_GETFIELD_Px(reg, FIFO_FULL_FIELD);
-	}
-
-	if (STV090x_WRITE_DEMOD(state, DISTXDATA, value) < 0)
-		goto err;
-
-	reg = STV090x_READ_DEMOD(state, DISTXCTL);
-	STV090x_SETFIELD_Px(reg, DIS_PRECHARGE_FIELD, 0);
-	if (STV090x_WRITE_DEMOD(state, DISTXCTL, reg) < 0)
-		goto err;
-
-	i = 0;
-
-	while ((!idle) && (i < 10)) {
-		reg = STV090x_READ_DEMOD(state, DISTXSTATUS);
-		idle = STV090x_GETFIELD_Px(reg, TX_IDLE_FIELD);
-		msleep(10);
-		i++;
-	}
-
-	return 0;
-err:
-	dprintk(FE_ERROR, 1, "I/O error");
-	return -1;
-}
-
-static int stv090x_recv_slave_reply(struct dvb_frontend *fe, struct dvb_diseqc_slave_reply *reply)
-{
-	struct stv090x_state *state = fe->demodulator_priv;
-	u32 reg = 0, i = 0, rx_end = 0;
-
-	while ((rx_end != 1) && (i < 10)) {
-		msleep(10);
-		i++;
-		reg = STV090x_READ_DEMOD(state, DISRX_ST0);
-		rx_end = STV090x_GETFIELD_Px(reg, RX_END_FIELD);
-	}
-
-	if (rx_end) {
-		reply->msg_len = STV090x_GETFIELD_Px(reg, FIFO_BYTENBR_FIELD);
-		for (i = 0; i < reply->msg_len; i++)
-			reply->msg[i] = STV090x_READ_DEMOD(state, DISRXDATA);
-	}
-
-	return 0;
-}
-
-static int stv090x_sleep(struct dvb_frontend *fe)
-{
-	struct stv090x_state *state = fe->demodulator_priv;
-	u32 reg;
-	u8 full_standby = 0;
-
-	if (stv090x_i2c_gate_ctrl(state, 1) < 0)
-		goto err;
-
-	if (state->config->tuner_sleep) {
-		if (state->config->tuner_sleep(fe) < 0)
-			goto err_gateoff;
-	}
-
-	if (stv090x_i2c_gate_ctrl(state, 0) < 0)
-		goto err;
-
-	dprintk(FE_DEBUG, 1, "Set %s(%d) to sleep",
-		state->device == STV0900 ? "STV0900" : "STV0903",
-		state->demod);
-
-	mutex_lock(&state->internal->demod_lock);
-
-	switch (state->demod) {
-	case STV090x_DEMODULATOR_0:
-		/* power off ADC 1 */
-		reg = stv090x_read_reg(state, STV090x_TSTTNR1);
-		STV090x_SETFIELD(reg, ADC1_PON_FIELD, 0);
-		if (stv090x_write_reg(state, STV090x_TSTTNR1, reg) < 0)
-			goto err;
-		/* power off DiSEqC 1 */
-		reg = stv090x_read_reg(state, STV090x_TSTTNR2);
-		STV090x_SETFIELD(reg, DISEQC1_PON_FIELD, 0);
-		if (stv090x_write_reg(state, STV090x_TSTTNR2, reg) < 0)
-			goto err;
-
-		/* check whether path 2 is already sleeping, that is when
-		   ADC2 is off */
-		reg = stv090x_read_reg(state, STV090x_TSTTNR3);
-		if (STV090x_GETFIELD(reg, ADC2_PON_FIELD) == 0)
-			full_standby = 1;
-
-		/* stop clocks */
-		reg = stv090x_read_reg(state, STV090x_STOPCLK1);
-		/* packet delineator 1 clock */
-		STV090x_SETFIELD(reg, STOP_CLKPKDT1_FIELD, 1);
-		/* ADC 1 clock */
-		STV090x_SETFIELD(reg, STOP_CLKADCI1_FIELD, 1);
-		/* FEC clock is shared between the two paths, only stop it
-		   when full standby is possible */
-		if (full_standby)
-			STV090x_SETFIELD(reg, STOP_CLKFEC_FIELD, 1);
-		if (stv090x_write_reg(state, STV090x_STOPCLK1, reg) < 0)
-			goto err;
-		reg = stv090x_read_reg(state, STV090x_STOPCLK2);
-		/* sampling 1 clock */
-		STV090x_SETFIELD(reg, STOP_CLKSAMP1_FIELD, 1);
-		/* viterbi 1 clock */
-		STV090x_SETFIELD(reg, STOP_CLKVIT1_FIELD, 1);
-		/* TS clock is shared between the two paths, only stop it
-		   when full standby is possible */
-		if (full_standby)
-			STV090x_SETFIELD(reg, STOP_CLKTS_FIELD, 1);
-		if (stv090x_write_reg(state, STV090x_STOPCLK2, reg) < 0)
-			goto err;
-		break;
-
-	case STV090x_DEMODULATOR_1:
-		/* power off ADC 2 */
-		reg = stv090x_read_reg(state, STV090x_TSTTNR3);
-		STV090x_SETFIELD(reg, ADC2_PON_FIELD, 0);
-		if (stv090x_write_reg(state, STV090x_TSTTNR3, reg) < 0)
-			goto err;
-		/* power off DiSEqC 2 */
-		reg = stv090x_read_reg(state, STV090x_TSTTNR4);
-		STV090x_SETFIELD(reg, DISEQC2_PON_FIELD, 0);
-		if (stv090x_write_reg(state, STV090x_TSTTNR4, reg) < 0)
-			goto err;
-
-		/* check whether path 1 is already sleeping, that is when
-		   ADC1 is off */
-		reg = stv090x_read_reg(state, STV090x_TSTTNR1);
-		if (STV090x_GETFIELD(reg, ADC1_PON_FIELD) == 0)
-			full_standby = 1;
-
-		/* stop clocks */
-		reg = stv090x_read_reg(state, STV090x_STOPCLK1);
-		/* packet delineator 2 clock */
-		STV090x_SETFIELD(reg, STOP_CLKPKDT2_FIELD, 1);
-		/* ADC 2 clock */
-		STV090x_SETFIELD(reg, STOP_CLKADCI2_FIELD, 1);
-		/* FEC clock is shared between the two paths, only stop it
-		   when full standby is possible */
-		if (full_standby)
-			STV090x_SETFIELD(reg, STOP_CLKFEC_FIELD, 1);
-		if (stv090x_write_reg(state, STV090x_STOPCLK1, reg) < 0)
-			goto err;
-		reg = stv090x_read_reg(state, STV090x_STOPCLK2);
-		/* sampling 2 clock */
-		STV090x_SETFIELD(reg, STOP_CLKSAMP2_FIELD, 1);
-		/* viterbi 2 clock */
-		STV090x_SETFIELD(reg, STOP_CLKVIT2_FIELD, 1);
-		/* TS clock is shared between the two paths, only stop it
-		   when full standby is possible */
-		if (full_standby)
-			STV090x_SETFIELD(reg, STOP_CLKTS_FIELD, 1);
-		if (stv090x_write_reg(state, STV090x_STOPCLK2, reg) < 0)
-			goto err;
-		break;
-
-	default:
-		dprintk(FE_ERROR, 1, "Wrong demodulator!");
-		break;
-	}
-
-	if (full_standby) {
-		/* general power off */
-		reg = stv090x_read_reg(state, STV090x_SYNTCTRL);
-		STV090x_SETFIELD(reg, STANDBY_FIELD, 0x01);
-		if (stv090x_write_reg(state, STV090x_SYNTCTRL, reg) < 0)
-			goto err;
-	}
-
-	mutex_unlock(&state->internal->demod_lock);
-	return 0;
-
-err_gateoff:
-	stv090x_i2c_gate_ctrl(state, 0);
-err:
-	mutex_unlock(&state->internal->demod_lock);
-	dprintk(FE_ERROR, 1, "I/O error");
-	return -1;
-}
-
-static int stv090x_wakeup(struct dvb_frontend *fe)
-{
-	struct stv090x_state *state = fe->demodulator_priv;
-	u32 reg;
-
-	dprintk(FE_DEBUG, 1, "Wake %s(%d) from standby",
-		state->device == STV0900 ? "STV0900" : "STV0903",
-		state->demod);
-
-	mutex_lock(&state->internal->demod_lock);
-
-	/* general power on */
-	reg = stv090x_read_reg(state, STV090x_SYNTCTRL);
-	STV090x_SETFIELD(reg, STANDBY_FIELD, 0x00);
-	if (stv090x_write_reg(state, STV090x_SYNTCTRL, reg) < 0)
-		goto err;
-
-	switch (state->demod) {
-	case STV090x_DEMODULATOR_0:
-		/* power on ADC 1 */
-		reg = stv090x_read_reg(state, STV090x_TSTTNR1);
-		STV090x_SETFIELD(reg, ADC1_PON_FIELD, 1);
-		if (stv090x_write_reg(state, STV090x_TSTTNR1, reg) < 0)
-			goto err;
-		/* power on DiSEqC 1 */
-		reg = stv090x_read_reg(state, STV090x_TSTTNR2);
-		STV090x_SETFIELD(reg, DISEQC1_PON_FIELD, 1);
-		if (stv090x_write_reg(state, STV090x_TSTTNR2, reg) < 0)
-			goto err;
-
-		/* activate clocks */
-		reg = stv090x_read_reg(state, STV090x_STOPCLK1);
-		/* packet delineator 1 clock */
-		STV090x_SETFIELD(reg, STOP_CLKPKDT1_FIELD, 0);
-		/* ADC 1 clock */
-		STV090x_SETFIELD(reg, STOP_CLKADCI1_FIELD, 0);
-		/* FEC clock */
-		STV090x_SETFIELD(reg, STOP_CLKFEC_FIELD, 0);
-		if (stv090x_write_reg(state, STV090x_STOPCLK1, reg) < 0)
-			goto err;
-		reg = stv090x_read_reg(state, STV090x_STOPCLK2);
-		/* sampling 1 clock */
-		STV090x_SETFIELD(reg, STOP_CLKSAMP1_FIELD, 0);
-		/* viterbi 1 clock */
-		STV090x_SETFIELD(reg, STOP_CLKVIT1_FIELD, 0);
-		/* TS clock */
-		STV090x_SETFIELD(reg, STOP_CLKTS_FIELD, 0);
-		if (stv090x_write_reg(state, STV090x_STOPCLK2, reg) < 0)
-			goto err;
-		break;
-
-	case STV090x_DEMODULATOR_1:
-		/* power on ADC 2 */
-		reg = stv090x_read_reg(state, STV090x_TSTTNR3);
-		STV090x_SETFIELD(reg, ADC2_PON_FIELD, 1);
-		if (stv090x_write_reg(state, STV090x_TSTTNR3, reg) < 0)
-			goto err;
-		/* power on DiSEqC 2 */
-		reg = stv090x_read_reg(state, STV090x_TSTTNR4);
-		STV090x_SETFIELD(reg, DISEQC2_PON_FIELD, 1);
-		if (stv090x_write_reg(state, STV090x_TSTTNR4, reg) < 0)
-			goto err;
-
-		/* activate clocks */
-		reg = stv090x_read_reg(state, STV090x_STOPCLK1);
-		/* packet delineator 2 clock */
-		STV090x_SETFIELD(reg, STOP_CLKPKDT2_FIELD, 0);
-		/* ADC 2 clock */
-		STV090x_SETFIELD(reg, STOP_CLKADCI2_FIELD, 0);
-		/* FEC clock */
-		STV090x_SETFIELD(reg, STOP_CLKFEC_FIELD, 0);
-		if (stv090x_write_reg(state, STV090x_STOPCLK1, reg) < 0)
-			goto err;
-		reg = stv090x_read_reg(state, STV090x_STOPCLK2);
-		/* sampling 2 clock */
-		STV090x_SETFIELD(reg, STOP_CLKSAMP2_FIELD, 0);
-		/* viterbi 2 clock */
-		STV090x_SETFIELD(reg, STOP_CLKVIT2_FIELD, 0);
-		/* TS clock */
-		STV090x_SETFIELD(reg, STOP_CLKTS_FIELD, 0);
-		if (stv090x_write_reg(state, STV090x_STOPCLK2, reg) < 0)
-			goto err;
-		break;
-
-	default:
-		dprintk(FE_ERROR, 1, "Wrong demodulator!");
-		break;
-	}
-
-	mutex_unlock(&state->internal->demod_lock);
-	return 0;
-err:
-	mutex_unlock(&state->internal->demod_lock);
-	dprintk(FE_ERROR, 1, "I/O error");
-	return -1;
-}
-
-static void stv090x_release(struct dvb_frontend *fe)
-{
-	struct stv090x_state *state = fe->demodulator_priv;
-
-	state->internal->num_used--;
-	if (state->internal->num_used <= 0) {
-
-		dprintk(FE_ERROR, 1, "Actually removing");
-
-		remove_dev(state->internal);
-		kfree(state->internal);
-	}
-
-	kfree(state);
-}
-
-static int stv090x_ldpc_mode(struct stv090x_state *state, enum stv090x_mode ldpc_mode)
-{
-	u32 reg = 0;
-
-	reg = stv090x_read_reg(state, STV090x_GENCFG);
-
-	switch (ldpc_mode) {
-	case STV090x_DUAL:
-	default:
-		if ((state->demod_mode != STV090x_DUAL) || (STV090x_GETFIELD(reg, DDEMOD_FIELD) != 1)) {
-			/* set LDPC to dual mode */
-			if (stv090x_write_reg(state, STV090x_GENCFG, 0x1d) < 0)
-				goto err;
-
-			state->demod_mode = STV090x_DUAL;
-
-			reg = stv090x_read_reg(state, STV090x_TSTRES0);
-			STV090x_SETFIELD(reg, FRESFEC_FIELD, 0x1);
-			if (stv090x_write_reg(state, STV090x_TSTRES0, reg) < 0)
-				goto err;
-			STV090x_SETFIELD(reg, FRESFEC_FIELD, 0x0);
-			if (stv090x_write_reg(state, STV090x_TSTRES0, reg) < 0)
-				goto err;
-
-			if (STV090x_WRITE_DEMOD(state, MODCODLST0, 0xff) < 0)
-				goto err;
-			if (STV090x_WRITE_DEMOD(state, MODCODLST1, 0xff) < 0)
-				goto err;
-			if (STV090x_WRITE_DEMOD(state, MODCODLST2, 0xff) < 0)
-				goto err;
-			if (STV090x_WRITE_DEMOD(state, MODCODLST3, 0xff) < 0)
-				goto err;
-			if (STV090x_WRITE_DEMOD(state, MODCODLST4, 0xff) < 0)
-				goto err;
-			if (STV090x_WRITE_DEMOD(state, MODCODLST5, 0xff) < 0)
-				goto err;
-			if (STV090x_WRITE_DEMOD(state, MODCODLST6, 0xff) < 0)
-				goto err;
-
-			if (STV090x_WRITE_DEMOD(state, MODCODLST7, 0xcc) < 0)
-				goto err;
-			if (STV090x_WRITE_DEMOD(state, MODCODLST8, 0xcc) < 0)
-				goto err;
-			if (STV090x_WRITE_DEMOD(state, MODCODLST9, 0xcc) < 0)
-				goto err;
-			if (STV090x_WRITE_DEMOD(state, MODCODLSTA, 0xcc) < 0)
-				goto err;
-			if (STV090x_WRITE_DEMOD(state, MODCODLSTB, 0xcc) < 0)
-				goto err;
-			if (STV090x_WRITE_DEMOD(state, MODCODLSTC, 0xcc) < 0)
-				goto err;
-			if (STV090x_WRITE_DEMOD(state, MODCODLSTD, 0xcc) < 0)
-				goto err;
-
-			if (STV090x_WRITE_DEMOD(state, MODCODLSTE, 0xff) < 0)
-				goto err;
-			if (STV090x_WRITE_DEMOD(state, MODCODLSTF, 0xcf) < 0)
-				goto err;
-		}
-		break;
-
-	case STV090x_SINGLE:
-		if (stv090x_stop_modcod(state) < 0)
-			goto err;
-		if (stv090x_activate_modcod_single(state) < 0)
-			goto err;
-
-		if (state->demod == STV090x_DEMODULATOR_1) {
-			if (stv090x_write_reg(state, STV090x_GENCFG, 0x06) < 0) /* path 2 */
-				goto err;
-		} else {
-			if (stv090x_write_reg(state, STV090x_GENCFG, 0x04) < 0) /* path 1 */
-				goto err;
-		}
-
-		reg = stv090x_read_reg(state, STV090x_TSTRES0);
-		STV090x_SETFIELD(reg, FRESFEC_FIELD, 0x1);
-		if (stv090x_write_reg(state, STV090x_TSTRES0, reg) < 0)
-			goto err;
-		STV090x_SETFIELD(reg, FRESFEC_FIELD, 0x0);
-		if (stv090x_write_reg(state, STV090x_TSTRES0, reg) < 0)
-			goto err;
-
-		reg = STV090x_READ_DEMOD(state, PDELCTRL1);
-		STV090x_SETFIELD_Px(reg, ALGOSWRST_FIELD, 0x01);
-		if (STV090x_WRITE_DEMOD(state, PDELCTRL1, reg) < 0)
-			goto err;
-		STV090x_SETFIELD_Px(reg, ALGOSWRST_FIELD, 0x00);
-		if (STV090x_WRITE_DEMOD(state, PDELCTRL1, reg) < 0)
-			goto err;
-		break;
-	}
-
-	return 0;
-err:
-	dprintk(FE_ERROR, 1, "I/O error");
-	return -1;
-}
-
-/* return (Hz), clk in Hz*/
-static u32 stv090x_get_mclk(struct stv090x_state *state)
-{
-	const struct stv090x_config *config = state->config;
-	u32 div, reg;
-	u8 ratio;
-
-	div = stv090x_read_reg(state, STV090x_NCOARSE);
-	reg = stv090x_read_reg(state, STV090x_SYNTCTRL);
-	ratio = STV090x_GETFIELD(reg, SELX1RATIO_FIELD) ? 4 : 6;
-
-	return (div + 1) * config->xtal / ratio; /* kHz */
-}
-
-static int stv090x_set_mclk(struct stv090x_state *state, u32 mclk, u32 clk)
-{
-	const struct stv090x_config *config = state->config;
-	u32 reg, div, clk_sel;
-
-	reg = stv090x_read_reg(state, STV090x_SYNTCTRL);
-	clk_sel = ((STV090x_GETFIELD(reg, SELX1RATIO_FIELD) == 1) ? 4 : 6);
-
-	div = ((clk_sel * mclk) / config->xtal) - 1;
-
-	reg = stv090x_read_reg(state, STV090x_NCOARSE);
-	STV090x_SETFIELD(reg, M_DIV_FIELD, div);
-	if (stv090x_write_reg(state, STV090x_NCOARSE, reg) < 0)
-		goto err;
-
-	state->internal->mclk = stv090x_get_mclk(state);
-
-	/*Set the DiseqC frequency to 22KHz */
-	div = state->internal->mclk / 704000;
-	if (STV090x_WRITE_DEMOD(state, F22TX, div) < 0)
-		goto err;
-	if (STV090x_WRITE_DEMOD(state, F22RX, div) < 0)
-		goto err;
-
-	return 0;
-err:
-	dprintk(FE_ERROR, 1, "I/O error");
-	return -1;
-}
-
-static int stv090x_set_tspath(struct stv090x_state *state)
-{
-	u32 reg;
-
-	if (state->internal->dev_ver >= 0x20) {
-		switch (state->config->ts1_mode) {
-		case STV090x_TSMODE_PARALLEL_PUNCTURED:
-		case STV090x_TSMODE_DVBCI:
-			switch (state->config->ts2_mode) {
-			case STV090x_TSMODE_SERIAL_PUNCTURED:
-			case STV090x_TSMODE_SERIAL_CONTINUOUS:
-			default:
-				stv090x_write_reg(state, STV090x_TSGENERAL, 0x00);
-				break;
-
-			case STV090x_TSMODE_PARALLEL_PUNCTURED:
-			case STV090x_TSMODE_DVBCI:
-				if (stv090x_write_reg(state, STV090x_TSGENERAL, 0x06) < 0) /* Mux'd stream mode */
-					goto err;
-				reg = stv090x_read_reg(state, STV090x_P1_TSCFGM);
-				STV090x_SETFIELD_Px(reg, TSFIFO_MANSPEED_FIELD, 3);
-				if (stv090x_write_reg(state, STV090x_P1_TSCFGM, reg) < 0)
-					goto err;
-				reg = stv090x_read_reg(state, STV090x_P2_TSCFGM);
-				STV090x_SETFIELD_Px(reg, TSFIFO_MANSPEED_FIELD, 3);
-				if (stv090x_write_reg(state, STV090x_P2_TSCFGM, reg) < 0)
-					goto err;
-				if (stv090x_write_reg(state, STV090x_P1_TSSPEED, 0x14) < 0)
-					goto err;
-				if (stv090x_write_reg(state, STV090x_P2_TSSPEED, 0x28) < 0)
-					goto err;
-				break;
-			}
-			break;
-
-		case STV090x_TSMODE_SERIAL_PUNCTURED:
-		case STV090x_TSMODE_SERIAL_CONTINUOUS:
-		default:
-			switch (state->config->ts2_mode) {
-			case STV090x_TSMODE_SERIAL_PUNCTURED:
-			case STV090x_TSMODE_SERIAL_CONTINUOUS:
-			default:
-				if (stv090x_write_reg(state, STV090x_TSGENERAL, 0x0c) < 0)
-					goto err;
-				break;
-
-			case STV090x_TSMODE_PARALLEL_PUNCTURED:
-			case STV090x_TSMODE_DVBCI:
-				if (stv090x_write_reg(state, STV090x_TSGENERAL, 0x0a) < 0)
-					goto err;
-				break;
-			}
-			break;
-		}
-	} else {
-		switch (state->config->ts1_mode) {
-		case STV090x_TSMODE_PARALLEL_PUNCTURED:
-		case STV090x_TSMODE_DVBCI:
-			switch (state->config->ts2_mode) {
-			case STV090x_TSMODE_SERIAL_PUNCTURED:
-			case STV090x_TSMODE_SERIAL_CONTINUOUS:
-			default:
-				stv090x_write_reg(state, STV090x_TSGENERAL1X, 0x10);
-				break;
-
-			case STV090x_TSMODE_PARALLEL_PUNCTURED:
-			case STV090x_TSMODE_DVBCI:
-				stv090x_write_reg(state, STV090x_TSGENERAL1X, 0x16);
-				reg = stv090x_read_reg(state, STV090x_P1_TSCFGM);
-				STV090x_SETFIELD_Px(reg, TSFIFO_MANSPEED_FIELD, 3);
-				if (stv090x_write_reg(state, STV090x_P1_TSCFGM, reg) < 0)
-					goto err;
-				reg = stv090x_read_reg(state, STV090x_P1_TSCFGM);
-				STV090x_SETFIELD_Px(reg, TSFIFO_MANSPEED_FIELD, 0);
-				if (stv090x_write_reg(state, STV090x_P1_TSCFGM, reg) < 0)
-					goto err;
-				if (stv090x_write_reg(state, STV090x_P1_TSSPEED, 0x14) < 0)
-					goto err;
-				if (stv090x_write_reg(state, STV090x_P2_TSSPEED, 0x28) < 0)
-					goto err;
-				break;
-			}
-			break;
-
-		case STV090x_TSMODE_SERIAL_PUNCTURED:
-		case STV090x_TSMODE_SERIAL_CONTINUOUS:
-		default:
-			switch (state->config->ts2_mode) {
-			case STV090x_TSMODE_SERIAL_PUNCTURED:
-			case STV090x_TSMODE_SERIAL_CONTINUOUS:
-			default:
-				stv090x_write_reg(state, STV090x_TSGENERAL1X, 0x14);
-				break;
-
-			case STV090x_TSMODE_PARALLEL_PUNCTURED:
-			case STV090x_TSMODE_DVBCI:
-				stv090x_write_reg(state, STV090x_TSGENERAL1X, 0x12);
-				break;
-			}
-			break;
-		}
-	}
-
-	switch (state->config->ts1_mode) {
-	case STV090x_TSMODE_PARALLEL_PUNCTURED:
-		reg = stv090x_read_reg(state, STV090x_P1_TSCFGH);
-		STV090x_SETFIELD_Px(reg, TSFIFO_TEIUPDATE_FIELD, state->config->ts1_tei);
-		STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x00);
-		STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x00);
-		if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0)
-			goto err;
-		break;
-
-	case STV090x_TSMODE_DVBCI:
-		reg = stv090x_read_reg(state, STV090x_P1_TSCFGH);
-		STV090x_SETFIELD_Px(reg, TSFIFO_TEIUPDATE_FIELD, state->config->ts1_tei);
-		STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x00);
-		STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x01);
-		if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0)
-			goto err;
-		break;
-
-	case STV090x_TSMODE_SERIAL_PUNCTURED:
-		reg = stv090x_read_reg(state, STV090x_P1_TSCFGH);
-		STV090x_SETFIELD_Px(reg, TSFIFO_TEIUPDATE_FIELD, state->config->ts1_tei);
-		STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x01);
-		STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x00);
-		if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0)
-			goto err;
-		break;
-
-	case STV090x_TSMODE_SERIAL_CONTINUOUS:
-		reg = stv090x_read_reg(state, STV090x_P1_TSCFGH);
-		STV090x_SETFIELD_Px(reg, TSFIFO_TEIUPDATE_FIELD, state->config->ts1_tei);
-		STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x01);
-		STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x01);
-		if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0)
-			goto err;
-		break;
-
-	default:
-		break;
-	}
-
-	switch (state->config->ts2_mode) {
-	case STV090x_TSMODE_PARALLEL_PUNCTURED:
-		reg = stv090x_read_reg(state, STV090x_P2_TSCFGH);
-		STV090x_SETFIELD_Px(reg, TSFIFO_TEIUPDATE_FIELD, state->config->ts2_tei);
-		STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x00);
-		STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x00);
-		if (stv090x_write_reg(state, STV090x_P2_TSCFGH, reg) < 0)
-			goto err;
-		break;
-
-	case STV090x_TSMODE_DVBCI:
-		reg = stv090x_read_reg(state, STV090x_P2_TSCFGH);
-		STV090x_SETFIELD_Px(reg, TSFIFO_TEIUPDATE_FIELD, state->config->ts2_tei);
-		STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x00);
-		STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x01);
-		if (stv090x_write_reg(state, STV090x_P2_TSCFGH, reg) < 0)
-			goto err;
-		break;
-
-	case STV090x_TSMODE_SERIAL_PUNCTURED:
-		reg = stv090x_read_reg(state, STV090x_P2_TSCFGH);
-		STV090x_SETFIELD_Px(reg, TSFIFO_TEIUPDATE_FIELD, state->config->ts2_tei);
-		STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x01);
-		STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x00);
-		if (stv090x_write_reg(state, STV090x_P2_TSCFGH, reg) < 0)
-			goto err;
-		break;
-
-	case STV090x_TSMODE_SERIAL_CONTINUOUS:
-		reg = stv090x_read_reg(state, STV090x_P2_TSCFGH);
-		STV090x_SETFIELD_Px(reg, TSFIFO_TEIUPDATE_FIELD, state->config->ts2_tei);
-		STV090x_SETFIELD_Px(reg, TSFIFO_SERIAL_FIELD, 0x01);
-		STV090x_SETFIELD_Px(reg, TSFIFO_DVBCI_FIELD, 0x01);
-		if (stv090x_write_reg(state, STV090x_P2_TSCFGH, reg) < 0)
-			goto err;
-		break;
-
-	default:
-		break;
-	}
-
-	if (state->config->ts1_clk > 0) {
-		u32 speed;
-
-		switch (state->config->ts1_mode) {
-		case STV090x_TSMODE_PARALLEL_PUNCTURED:
-		case STV090x_TSMODE_DVBCI:
-		default:
-			speed = state->internal->mclk /
-				(state->config->ts1_clk / 4);
-			if (speed < 0x08)
-				speed = 0x08;
-			if (speed > 0xFF)
-				speed = 0xFF;
-			break;
-		case STV090x_TSMODE_SERIAL_PUNCTURED:
-		case STV090x_TSMODE_SERIAL_CONTINUOUS:
-			speed = state->internal->mclk /
-				(state->config->ts1_clk / 32);
-			if (speed < 0x20)
-				speed = 0x20;
-			if (speed > 0xFF)
-				speed = 0xFF;
-			break;
-		}
-		reg = stv090x_read_reg(state, STV090x_P1_TSCFGM);
-		STV090x_SETFIELD_Px(reg, TSFIFO_MANSPEED_FIELD, 3);
-		if (stv090x_write_reg(state, STV090x_P1_TSCFGM, reg) < 0)
-			goto err;
-		if (stv090x_write_reg(state, STV090x_P1_TSSPEED, speed) < 0)
-			goto err;
-	}
-
-	if (state->config->ts2_clk > 0) {
-		u32 speed;
-
-		switch (state->config->ts2_mode) {
-		case STV090x_TSMODE_PARALLEL_PUNCTURED:
-		case STV090x_TSMODE_DVBCI:
-		default:
-			speed = state->internal->mclk /
-				(state->config->ts2_clk / 4);
-			if (speed < 0x08)
-				speed = 0x08;
-			if (speed > 0xFF)
-				speed = 0xFF;
-			break;
-		case STV090x_TSMODE_SERIAL_PUNCTURED:
-		case STV090x_TSMODE_SERIAL_CONTINUOUS:
-			speed = state->internal->mclk /
-				(state->config->ts2_clk / 32);
-			if (speed < 0x20)
-				speed = 0x20;
-			if (speed > 0xFF)
-				speed = 0xFF;
-			break;
-		}
-		reg = stv090x_read_reg(state, STV090x_P2_TSCFGM);
-		STV090x_SETFIELD_Px(reg, TSFIFO_MANSPEED_FIELD, 3);
-		if (stv090x_write_reg(state, STV090x_P2_TSCFGM, reg) < 0)
-			goto err;
-		if (stv090x_write_reg(state, STV090x_P2_TSSPEED, speed) < 0)
-			goto err;
-	}
-
-	reg = stv090x_read_reg(state, STV090x_P2_TSCFGH);
-	STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0x01);
-	if (stv090x_write_reg(state, STV090x_P2_TSCFGH, reg) < 0)
-		goto err;
-	STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0x00);
-	if (stv090x_write_reg(state, STV090x_P2_TSCFGH, reg) < 0)
-		goto err;
-
-	reg = stv090x_read_reg(state, STV090x_P1_TSCFGH);
-	STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0x01);
-	if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0)
-		goto err;
-	STV090x_SETFIELD_Px(reg, RST_HWARE_FIELD, 0x00);
-	if (stv090x_write_reg(state, STV090x_P1_TSCFGH, reg) < 0)
-		goto err;
-
-	return 0;
-err:
-	dprintk(FE_ERROR, 1, "I/O error");
-	return -1;
-}
-
-static int stv090x_init(struct dvb_frontend *fe)
-{
-	struct stv090x_state *state = fe->demodulator_priv;
-	const struct stv090x_config *config = state->config;
-	u32 reg;
-
-	if (state->internal->mclk == 0) {
-		/* call tuner init to configure the tuner's clock output
-		   divider directly before setting up the master clock of
-		   the stv090x. */
-		if (stv090x_i2c_gate_ctrl(state, 1) < 0)
-			goto err;
-
-		if (config->tuner_init) {
-			if (config->tuner_init(fe) < 0)
-				goto err_gateoff;
-		}
-
-		if (stv090x_i2c_gate_ctrl(state, 0) < 0)
-			goto err;
-
-		stv090x_set_mclk(state, 135000000, config->xtal); /* 135 Mhz */
-		msleep(5);
-		if (stv090x_write_reg(state, STV090x_SYNTCTRL,
-				      0x20 | config->clk_mode) < 0)
-			goto err;
-		stv090x_get_mclk(state);
-	}
-
-	if (stv090x_wakeup(fe) < 0) {
-		dprintk(FE_ERROR, 1, "Error waking device");
-		goto err;
-	}
-
-	if (stv090x_ldpc_mode(state, state->demod_mode) < 0)
-		goto err;
-
-	reg = STV090x_READ_DEMOD(state, TNRCFG2);
-	STV090x_SETFIELD_Px(reg, TUN_IQSWAP_FIELD, state->inversion);
-	if (STV090x_WRITE_DEMOD(state, TNRCFG2, reg) < 0)
-		goto err;
-	reg = STV090x_READ_DEMOD(state, DEMOD);
-	STV090x_SETFIELD_Px(reg, ROLLOFF_CONTROL_FIELD, state->rolloff);
-	if (STV090x_WRITE_DEMOD(state, DEMOD, reg) < 0)
-		goto err;
-
-	if (stv090x_i2c_gate_ctrl(state, 1) < 0)
-		goto err;
-
-	if (config->tuner_set_mode) {
-		if (config->tuner_set_mode(fe, TUNER_WAKE) < 0)
-			goto err_gateoff;
-	}
-
-	if (config->tuner_init) {
-		if (config->tuner_init(fe) < 0)
-			goto err_gateoff;
-	}
-
-	if (stv090x_i2c_gate_ctrl(state, 0) < 0)
-		goto err;
-
-	if (stv090x_set_tspath(state) < 0)
-		goto err;
-
-	return 0;
-
-err_gateoff:
-	stv090x_i2c_gate_ctrl(state, 0);
-err:
-	dprintk(FE_ERROR, 1, "I/O error");
-	return -1;
-}
-
-static int stv090x_setup(struct dvb_frontend *fe)
-{
-	struct stv090x_state *state = fe->demodulator_priv;
-	const struct stv090x_config *config = state->config;
-	const struct stv090x_reg *stv090x_initval = NULL;
-	const struct stv090x_reg *stv090x_cut20_val = NULL;
-	unsigned long t1_size = 0, t2_size = 0;
-	u32 reg = 0;
-
-	int i;
-
-	if (state->device == STV0900) {
-		dprintk(FE_DEBUG, 1, "Initializing STV0900");
-		stv090x_initval = stv0900_initval;
-		t1_size = ARRAY_SIZE(stv0900_initval);
-		stv090x_cut20_val = stv0900_cut20_val;
-		t2_size = ARRAY_SIZE(stv0900_cut20_val);
-	} else if (state->device == STV0903) {
-		dprintk(FE_DEBUG, 1, "Initializing STV0903");
-		stv090x_initval = stv0903_initval;
-		t1_size = ARRAY_SIZE(stv0903_initval);
-		stv090x_cut20_val = stv0903_cut20_val;
-		t2_size = ARRAY_SIZE(stv0903_cut20_val);
-	}
-
-	/* STV090x init */
-
-	/* Stop Demod */
-	if (stv090x_write_reg(state, STV090x_P1_DMDISTATE, 0x5c) < 0)
-		goto err;
-	if (stv090x_write_reg(state, STV090x_P2_DMDISTATE, 0x5c) < 0)
-		goto err;
-
-	msleep(5);
-
-	/* Set No Tuner Mode */
-	if (stv090x_write_reg(state, STV090x_P1_TNRCFG, 0x6c) < 0)
-		goto err;
-	if (stv090x_write_reg(state, STV090x_P2_TNRCFG, 0x6c) < 0)
-		goto err;
-
-	/* I2C repeater OFF */
-	STV090x_SETFIELD_Px(reg, ENARPT_LEVEL_FIELD, config->repeater_level);
-	if (stv090x_write_reg(state, STV090x_P1_I2CRPT, reg) < 0)
-		goto err;
-	if (stv090x_write_reg(state, STV090x_P2_I2CRPT, reg) < 0)
-		goto err;
-
-	if (stv090x_write_reg(state, STV090x_NCOARSE, 0x13) < 0) /* set PLL divider */
-		goto err;
-	msleep(5);
-	if (stv090x_write_reg(state, STV090x_I2CCFG, 0x08) < 0) /* 1/41 oversampling */
-		goto err;
-	if (stv090x_write_reg(state, STV090x_SYNTCTRL, 0x20 | config->clk_mode) < 0) /* enable PLL */
-		goto err;
-	msleep(5);
-
-	/* write initval */
-	dprintk(FE_DEBUG, 1, "Setting up initial values");
-	for (i = 0; i < t1_size; i++) {
-		if (stv090x_write_reg(state, stv090x_initval[i].addr, stv090x_initval[i].data) < 0)
-			goto err;
-	}
-
-	state->internal->dev_ver = stv090x_read_reg(state, STV090x_MID);
-	if (state->internal->dev_ver >= 0x20) {
-		if (stv090x_write_reg(state, STV090x_TSGENERAL, 0x0c) < 0)
-			goto err;
-
-		/* write cut20_val*/
-		dprintk(FE_DEBUG, 1, "Setting up Cut 2.0 initial values");
-		for (i = 0; i < t2_size; i++) {
-			if (stv090x_write_reg(state, stv090x_cut20_val[i].addr, stv090x_cut20_val[i].data) < 0)
-				goto err;
-		}
-
-	} else if (state->internal->dev_ver < 0x20) {
-		dprintk(FE_ERROR, 1, "ERROR: Unsupported Cut: 0x%02x!",
-			state->internal->dev_ver);
-
-		goto err;
-	} else if (state->internal->dev_ver > 0x30) {
-		/* we shouldn't bail out from here */
-		dprintk(FE_ERROR, 1, "INFO: Cut: 0x%02x probably incomplete support!",
-			state->internal->dev_ver);
-	}
-
-	/* ADC1 range */
-	reg = stv090x_read_reg(state, STV090x_TSTTNR1);
-	STV090x_SETFIELD(reg, ADC1_INMODE_FIELD,
-		(config->adc1_range == STV090x_ADC_1Vpp) ? 0 : 1);
-	if (stv090x_write_reg(state, STV090x_TSTTNR1, reg) < 0)
-		goto err;
-
-	/* ADC2 range */
-	reg = stv090x_read_reg(state, STV090x_TSTTNR3);
-	STV090x_SETFIELD(reg, ADC2_INMODE_FIELD,
-		(config->adc2_range == STV090x_ADC_1Vpp) ? 0 : 1);
-	if (stv090x_write_reg(state, STV090x_TSTTNR3, reg) < 0)
-		goto err;
-
-	if (stv090x_write_reg(state, STV090x_TSTRES0, 0x80) < 0)
-		goto err;
-	if (stv090x_write_reg(state, STV090x_TSTRES0, 0x00) < 0)
-		goto err;
-
-	return 0;
-err:
-	dprintk(FE_ERROR, 1, "I/O error");
-	return -1;
-}
-
-int stv090x_set_gpio(struct dvb_frontend *fe, u8 gpio, u8 dir, u8 value,
-		u8 xor_value)
-{
-	struct stv090x_state *state = fe->demodulator_priv;
-	u8 reg = 0;
-
-	STV090x_SETFIELD(reg, GPIOx_OPD_FIELD, dir);
-	STV090x_SETFIELD(reg, GPIOx_CONFIG_FIELD, value);
-	STV090x_SETFIELD(reg, GPIOx_XOR_FIELD, xor_value);
-
-	return stv090x_write_reg(state, STV090x_GPIOxCFG(gpio), reg);
-}
-EXPORT_SYMBOL(stv090x_set_gpio);
-
-static struct dvb_frontend_ops stv090x_ops = {
-	.delsys = { SYS_DVBS, SYS_DVBS2, SYS_DSS },
-	.info = {
-		.name			= "STV090x Multistandard",
-		.frequency_min		= 950000,
-		.frequency_max 		= 2150000,
-		.frequency_stepsize	= 0,
-		.frequency_tolerance	= 0,
-		.symbol_rate_min 	= 1000000,
-		.symbol_rate_max 	= 45000000,
-		.caps			= FE_CAN_INVERSION_AUTO |
-					  FE_CAN_FEC_AUTO       |
-					  FE_CAN_QPSK           |
-					  FE_CAN_2G_MODULATION
-	},
-
-	.release			= stv090x_release,
-	.init				= stv090x_init,
-
-	.sleep				= stv090x_sleep,
-	.get_frontend_algo		= stv090x_frontend_algo,
-
-	.diseqc_send_master_cmd		= stv090x_send_diseqc_msg,
-	.diseqc_send_burst		= stv090x_send_diseqc_burst,
-	.diseqc_recv_slave_reply	= stv090x_recv_slave_reply,
-	.set_tone			= stv090x_set_tone,
-
-	.search				= stv090x_search,
-	.read_status			= stv090x_read_status,
-	.read_ber			= stv090x_read_per,
-	.read_signal_strength		= stv090x_read_signal_strength,
-	.read_snr			= stv090x_read_cnr,
-};
-
-
-struct dvb_frontend *stv090x_attach(const struct stv090x_config *config,
-				    struct i2c_adapter *i2c,
-				    enum stv090x_demodulator demod)
-{
-	struct stv090x_state *state = NULL;
-	struct stv090x_dev *temp_int;
-
-	state = kzalloc(sizeof (struct stv090x_state), GFP_KERNEL);
-	if (state == NULL)
-		goto error;
-
-	state->verbose				= &verbose;
-	state->config				= config;
-	state->i2c				= i2c;
-	state->frontend.ops			= stv090x_ops;
-	state->frontend.demodulator_priv	= state;
-	state->demod				= demod;
-	state->demod_mode 			= config->demod_mode; /* Single or Dual mode */
-	state->device				= config->device;
-	state->rolloff				= STV090x_RO_35; /* default */
-
-	temp_int = find_dev(state->i2c,
-				state->config->address);
-
-	if ((temp_int != NULL) && (state->demod_mode == STV090x_DUAL)) {
-		state->internal = temp_int->internal;
-		state->internal->num_used++;
-		dprintk(FE_INFO, 1, "Found Internal Structure!");
-	} else {
-		state->internal = kmalloc(sizeof(struct stv090x_internal),
-					  GFP_KERNEL);
-		if (!state->internal)
-			goto error;
-		temp_int = append_internal(state->internal);
-		if (!temp_int) {
-			kfree(state->internal);
-			goto error;
-		}
-		state->internal->num_used = 1;
-		state->internal->mclk = 0;
-		state->internal->dev_ver = 0;
-		state->internal->i2c_adap = state->i2c;
-		state->internal->i2c_addr = state->config->address;
-		dprintk(FE_INFO, 1, "Create New Internal Structure!");
-
-		mutex_init(&state->internal->demod_lock);
-		mutex_init(&state->internal->tuner_lock);
-
-		if (stv090x_setup(&state->frontend) < 0) {
-			dprintk(FE_ERROR, 1, "Error setting up device");
-			goto err_remove;
-		}
-	}
-
-	/* workaround for stuck DiSEqC output */
-	if (config->diseqc_envelope_mode)
-		stv090x_send_diseqc_burst(&state->frontend, SEC_MINI_A);
-
-	dprintk(FE_ERROR, 1, "Attaching %s demodulator(%d) Cut=0x%02x",
-	       state->device == STV0900 ? "STV0900" : "STV0903",
-	       demod,
-	       state->internal->dev_ver);
-
-	return &state->frontend;
-
-err_remove:
-	remove_dev(state->internal);
-	kfree(state->internal);
-error:
-	kfree(state);
-	return NULL;
-}
-EXPORT_SYMBOL(stv090x_attach);
-MODULE_PARM_DESC(verbose, "Set Verbosity level");
-MODULE_AUTHOR("Manu Abraham");
-MODULE_DESCRIPTION("STV090x Multi-Std Broadcast frontend");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/stv090x.h b/drivers/media/dvb/frontends/stv090x.h
deleted file mode 100644
index 29cdc2b..0000000
--- a/drivers/media/dvb/frontends/stv090x.h
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
-	STV0900/0903 Multistandard Broadcast Frontend driver
-	Copyright (C) Manu Abraham <abraham.manu@gmail.com>
-
-	Copyright (C) ST Microelectronics
-
-	This program is free software; you can redistribute it and/or modify
-	it under the terms of the 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 __STV090x_H
-#define __STV090x_H
-
-enum stv090x_demodulator {
-	STV090x_DEMODULATOR_0 = 1,
-	STV090x_DEMODULATOR_1
-};
-
-enum stv090x_device {
-	STV0903	=  0,
-	STV0900,
-};
-
-enum stv090x_mode {
-	STV090x_DUAL = 0,
-	STV090x_SINGLE
-};
-
-enum stv090x_tsmode {
-	STV090x_TSMODE_SERIAL_PUNCTURED	= 1,
-	STV090x_TSMODE_SERIAL_CONTINUOUS,
-	STV090x_TSMODE_PARALLEL_PUNCTURED,
-	STV090x_TSMODE_DVBCI
-};
-
-enum stv090x_clkmode {
-	STV090x_CLK_INT = 0, /* Clk i/p = CLKI */
-	STV090x_CLK_EXT = 2 /* Clk i/p = XTALI */
-};
-
-enum stv090x_i2crpt {
-	STV090x_RPTLEVEL_256	= 0,
-	STV090x_RPTLEVEL_128	= 1,
-	STV090x_RPTLEVEL_64	= 2,
-	STV090x_RPTLEVEL_32	= 3,
-	STV090x_RPTLEVEL_16	= 4,
-	STV090x_RPTLEVEL_8	= 5,
-	STV090x_RPTLEVEL_4	= 6,
-	STV090x_RPTLEVEL_2	= 7,
-};
-
-enum stv090x_adc_range {
-	STV090x_ADC_2Vpp	= 0,
-	STV090x_ADC_1Vpp	= 1
-};
-
-struct stv090x_config {
-	enum stv090x_device	device;
-	enum stv090x_mode	demod_mode;
-	enum stv090x_clkmode	clk_mode;
-
-	u32 xtal; /* default: 8000000 */
-	u8 address; /* default: 0x68 */
-
-	u8 ts1_mode;
-	u8 ts2_mode;
-	u32 ts1_clk;
-	u32 ts2_clk;
-
-	u8 ts1_tei : 1;
-	u8 ts2_tei : 1;
-
-	enum stv090x_i2crpt	repeater_level;
-
-	u8			tuner_bbgain; /* default: 10db */
-	enum stv090x_adc_range	adc1_range; /* default: 2Vpp */
-	enum stv090x_adc_range	adc2_range; /* default: 2Vpp */
-
-	bool diseqc_envelope_mode;
-
-	int (*tuner_init) (struct dvb_frontend *fe);
-	int (*tuner_sleep) (struct dvb_frontend *fe);
-	int (*tuner_set_mode) (struct dvb_frontend *fe, enum tuner_mode mode);
-	int (*tuner_set_frequency) (struct dvb_frontend *fe, u32 frequency);
-	int (*tuner_get_frequency) (struct dvb_frontend *fe, u32 *frequency);
-	int (*tuner_set_bandwidth) (struct dvb_frontend *fe, u32 bandwidth);
-	int (*tuner_get_bandwidth) (struct dvb_frontend *fe, u32 *bandwidth);
-	int (*tuner_set_bbgain) (struct dvb_frontend *fe, u32 gain);
-	int (*tuner_get_bbgain) (struct dvb_frontend *fe, u32 *gain);
-	int (*tuner_set_refclk)  (struct dvb_frontend *fe, u32 refclk);
-	int (*tuner_get_status) (struct dvb_frontend *fe, u32 *status);
-	void (*tuner_i2c_lock) (struct dvb_frontend *fe, int lock);
-};
-
-#if defined(CONFIG_DVB_STV090x) || (defined(CONFIG_DVB_STV090x_MODULE) && defined(MODULE))
-
-extern struct dvb_frontend *stv090x_attach(const struct stv090x_config *config,
-					   struct i2c_adapter *i2c,
-					   enum stv090x_demodulator demod);
-
-/* dir = 0 -> output, dir = 1 -> input/open-drain */
-extern int stv090x_set_gpio(struct dvb_frontend *fe, u8 gpio,
-		u8 dir, u8 value, u8 xor_value);
-
-#else
-
-static inline struct dvb_frontend *stv090x_attach(const struct stv090x_config *config,
-						  struct i2c_adapter *i2c,
-						  enum stv090x_demodulator demod)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-
-static inline int stv090x_set_gpio(struct dvb_frontend *fe, u8 gpio,
-		u8 opd, u8 value, u8 xor_value)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return -ENODEV;
-}
-#endif /* CONFIG_DVB_STV090x */
-
-#endif /* __STV090x_H */
diff --git a/drivers/media/dvb/frontends/stv090x_priv.h b/drivers/media/dvb/frontends/stv090x_priv.h
deleted file mode 100644
index 5b780c8..0000000
--- a/drivers/media/dvb/frontends/stv090x_priv.h
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
-	STV0900/0903 Multistandard Broadcast Frontend driver
-	Copyright (C) Manu Abraham <abraham.manu@gmail.com>
-
-	Copyright (C) ST Microelectronics
-
-	This program is free software; you can redistribute it and/or modify
-	it under the terms of the 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 __STV090x_PRIV_H
-#define __STV090x_PRIV_H
-
-#include "dvb_frontend.h"
-
-#define FE_ERROR				0
-#define FE_NOTICE				1
-#define FE_INFO					2
-#define FE_DEBUG				3
-#define FE_DEBUGREG				4
-
-#define dprintk(__y, __z, format, arg...) do {						\
-	if (__z) {									\
-		if	((verbose > FE_ERROR) && (verbose > __y))			\
-			printk(KERN_ERR "%s: " format "\n", __func__ , ##arg);		\
-		else if	((verbose > FE_NOTICE) && (verbose > __y))			\
-			printk(KERN_NOTICE "%s: " format "\n", __func__ , ##arg);	\
-		else if ((verbose > FE_INFO) && (verbose > __y))			\
-			printk(KERN_INFO "%s: " format "\n", __func__ , ##arg);		\
-		else if ((verbose > FE_DEBUG) && (verbose > __y))			\
-			printk(KERN_DEBUG "%s: " format "\n", __func__ , ##arg);	\
-	} else {									\
-		if (verbose > __y)							\
-			printk(format, ##arg);						\
-	}										\
-} while (0)
-
-#define STV090x_READ_DEMOD(__state, __reg) ((			\
-	(__state)->demod == STV090x_DEMODULATOR_1)	?	\
-	stv090x_read_reg(__state, STV090x_P2_##__reg) :		\
-	stv090x_read_reg(__state, STV090x_P1_##__reg))
-
-#define STV090x_WRITE_DEMOD(__state, __reg, __data) ((		\
-	(__state)->demod == STV090x_DEMODULATOR_1)	?	\
-	stv090x_write_reg(__state, STV090x_P2_##__reg, __data) :\
-	stv090x_write_reg(__state, STV090x_P1_##__reg, __data))
-
-#define STV090x_ADDR_OFFST(__state, __x) ((			\
-	(__state->demod) == STV090x_DEMODULATOR_1)	?	\
-		STV090x_P1_##__x :				\
-		STV090x_P2_##__x)
-
-
-#define STV090x_SETFIELD(mask, bitf, val)	(mask = (mask & (~(((1 << STV090x_WIDTH_##bitf) - 1) <<\
-							 STV090x_OFFST_##bitf))) | \
-							 (val << STV090x_OFFST_##bitf))
-
-#define STV090x_GETFIELD(val, bitf)		((val >> STV090x_OFFST_##bitf) & ((1 << STV090x_WIDTH_##bitf) - 1))
-
-
-#define STV090x_SETFIELD_Px(mask, bitf, val)	(mask = (mask & (~(((1 << STV090x_WIDTH_Px_##bitf) - 1) <<\
-							 STV090x_OFFST_Px_##bitf))) | \
-							 (val << STV090x_OFFST_Px_##bitf))
-
-#define STV090x_GETFIELD_Px(val, bitf)		((val >> STV090x_OFFST_Px_##bitf) & ((1 << STV090x_WIDTH_Px_##bitf) - 1))
-
-#define MAKEWORD16(__a, __b)			(((__a) << 8) | (__b))
-
-#define MSB(__x)				((__x >> 8) & 0xff)
-#define LSB(__x)				(__x & 0xff)
-
-
-#define STV090x_IQPOWER_THRESHOLD	  30
-#define STV090x_SEARCH_AGC2_TH_CUT20	 700
-#define STV090x_SEARCH_AGC2_TH_CUT30	1400
-
-#define STV090x_SEARCH_AGC2_TH(__ver)	\
-	((__ver <= 0x20) ?		\
-	STV090x_SEARCH_AGC2_TH_CUT20 :	\
-	STV090x_SEARCH_AGC2_TH_CUT30)
-
-enum stv090x_signal_state {
-	STV090x_NOAGC1,
-	STV090x_NOCARRIER,
-	STV090x_NODATA,
-	STV090x_DATAOK,
-	STV090x_RANGEOK,
-	STV090x_OUTOFRANGE
-};
-
-enum stv090x_fec {
-	STV090x_PR12 = 0,
-	STV090x_PR23,
-	STV090x_PR34,
-	STV090x_PR45,
-	STV090x_PR56,
-	STV090x_PR67,
-	STV090x_PR78,
-	STV090x_PR89,
-	STV090x_PR910,
-	STV090x_PRERR
-};
-
-enum stv090x_modulation {
-	STV090x_QPSK,
-	STV090x_8PSK,
-	STV090x_16APSK,
-	STV090x_32APSK,
-	STV090x_UNKNOWN
-};
-
-enum stv090x_frame {
-	STV090x_LONG_FRAME,
-	STV090x_SHORT_FRAME
-};
-
-enum stv090x_pilot {
-	STV090x_PILOTS_OFF,
-	STV090x_PILOTS_ON
-};
-
-enum stv090x_rolloff {
-	STV090x_RO_35,
-	STV090x_RO_25,
-	STV090x_RO_20
-};
-
-enum stv090x_inversion {
-	STV090x_IQ_AUTO,
-	STV090x_IQ_NORMAL,
-	STV090x_IQ_SWAP
-};
-
-enum stv090x_modcod {
-	STV090x_DUMMY_PLF = 0,
-	STV090x_QPSK_14,
-	STV090x_QPSK_13,
-	STV090x_QPSK_25,
-	STV090x_QPSK_12,
-	STV090x_QPSK_35,
-	STV090x_QPSK_23,
-	STV090x_QPSK_34,
-	STV090x_QPSK_45,
-	STV090x_QPSK_56,
-	STV090x_QPSK_89,
-	STV090x_QPSK_910,
-	STV090x_8PSK_35,
-	STV090x_8PSK_23,
-	STV090x_8PSK_34,
-	STV090x_8PSK_56,
-	STV090x_8PSK_89,
-	STV090x_8PSK_910,
-	STV090x_16APSK_23,
-	STV090x_16APSK_34,
-	STV090x_16APSK_45,
-	STV090x_16APSK_56,
-	STV090x_16APSK_89,
-	STV090x_16APSK_910,
-	STV090x_32APSK_34,
-	STV090x_32APSK_45,
-	STV090x_32APSK_56,
-	STV090x_32APSK_89,
-	STV090x_32APSK_910,
-	STV090x_MODCODE_UNKNOWN
-};
-
-enum stv090x_search {
-	STV090x_SEARCH_DSS = 0,
-	STV090x_SEARCH_DVBS1,
-	STV090x_SEARCH_DVBS2,
-	STV090x_SEARCH_AUTO
-};
-
-enum stv090x_algo {
-	STV090x_BLIND_SEARCH,
-	STV090x_COLD_SEARCH,
-	STV090x_WARM_SEARCH
-};
-
-enum stv090x_delsys {
-	STV090x_ERROR = 0,
-	STV090x_DVBS1 = 1,
-	STV090x_DVBS2,
-	STV090x_DSS
-};
-
-struct stv090x_long_frame_crloop {
-	enum stv090x_modcod	modcod;
-
-	u8 crl_pilots_on_2;
-	u8 crl_pilots_off_2;
-	u8 crl_pilots_on_5;
-	u8 crl_pilots_off_5;
-	u8 crl_pilots_on_10;
-	u8 crl_pilots_off_10;
-	u8 crl_pilots_on_20;
-	u8 crl_pilots_off_20;
-	u8 crl_pilots_on_30;
-	u8 crl_pilots_off_30;
-};
-
-struct stv090x_short_frame_crloop {
-	enum stv090x_modulation	modulation;
-
-	u8 crl_2;  /*      SR <   3M */
-	u8 crl_5;  /*  3 < SR <=  7M */
-	u8 crl_10; /*  7 < SR <= 15M */
-	u8 crl_20; /* 10 < SR <= 25M */
-	u8 crl_30; /* 10 < SR <= 45M */
-};
-
-struct stv090x_reg {
-	u16 addr;
-	u8  data;
-};
-
-struct stv090x_tab {
-	s32 real;
-	s32 read;
-};
-
-struct stv090x_internal {
-	struct i2c_adapter 	*i2c_adap;
-	u8			i2c_addr;
-
-	struct mutex		demod_lock; /* Lock access to shared register */
-	struct mutex		tuner_lock; /* Lock access to tuners */
-	s32			mclk; /* Masterclock Divider factor */
-	u32			dev_ver;
-
-	int			num_used;
-};
-
-struct stv090x_state {
-	enum stv090x_device		device;
-	enum stv090x_demodulator	demod;
-	enum stv090x_mode		demod_mode;
-	struct stv090x_internal		*internal;
-
-	struct i2c_adapter		*i2c;
-	const struct stv090x_config	*config;
-	struct dvb_frontend		frontend;
-
-	u32				*verbose; /* Cached module verbosity */
-
-	enum stv090x_delsys		delsys;
-	enum stv090x_fec		fec;
-	enum stv090x_modulation		modulation;
-	enum stv090x_modcod		modcod;
-	enum stv090x_search		search_mode;
-	enum stv090x_frame		frame_len;
-	enum stv090x_pilot		pilots;
-	enum stv090x_rolloff		rolloff;
-	enum stv090x_inversion		inversion;
-	enum stv090x_algo		algo;
-
-	u32				frequency;
-	u32				srate;
-
-	s32				tuner_bw;
-
-	s32				search_range;
-
-	s32				DemodTimeout;
-	s32				FecTimeout;
-};
-
-#endif /* __STV090x_PRIV_H */
diff --git a/drivers/media/dvb/frontends/stv090x_reg.h b/drivers/media/dvb/frontends/stv090x_reg.h
deleted file mode 100644
index 93741ee..0000000
--- a/drivers/media/dvb/frontends/stv090x_reg.h
+++ /dev/null
@@ -1,2371 +0,0 @@
-/*
-	STV0900/0903 Multistandard Broadcast Frontend driver
-	Copyright (C) Manu Abraham <abraham.manu@gmail.com>
-
-	Copyright (C) ST Microelectronics
-
-	This program is free software; you can redistribute it and/or modify
-	it under the terms of the 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 __STV090x_REG_H
-#define __STV090x_REG_H
-
-#define STV090x_MID				0xf100
-#define STV090x_OFFST_MCHIP_IDENT_FIELD		4
-#define STV090x_WIDTH_MCHIP_IDENT_FIELD		4
-#define STV090x_OFFST_MRELEASE_FIELD		0
-#define STV090x_WIDTH_MRELEASE_FIELD		4
-
-#define STV090x_DACR1				0xf113
-#define STV090x_OFFST_DACR1_MODE_FIELD		5
-#define STV090x_WIDTH_DACR1_MODE_FIELD		3
-#define STV090x_OFFST_DACR1_VALUE_FIELD		0
-#define STV090x_WIDTH_DACR1_VALUE_FIELD		4
-
-#define STV090x_DACR2				0xf114
-#define STV090x_OFFST_DACR2_VALUE_FIELD		0
-#define STV090x_WIDTH_DACR2_VALUE_FIELD		8
-
-#define STV090x_OUTCFG				0xf11c
-#define STV090x_OFFST_OUTSERRS1_HZ_FIELD	6
-#define STV090x_WIDTH_OUTSERRS1_HZ_FIELD	1
-#define STV090x_OFFST_OUTSERRS2_HZ_FIELD	5
-#define STV090x_WIDTH_OUTSERRS2_HZ_FIELD	1
-#define STV090x_OFFST_OUTSERRS3_HZ_FIELD	4
-#define STV090x_WIDTH_OUTSERRS3_HZ_FIELD	1
-#define STV090x_OFFST_OUTPARRS3_HZ_FIELD	3
-#define STV090x_WIDTH_OUTPARRS3_HZ_FIELD	1
-
-#define STV090x_MODECFG				0xf11d
-
-#define STV090x_IRQSTATUS3			0xf120
-#define STV090x_OFFST_SPLL_LOCK_FIELD		5
-#define STV090x_WIDTH_SPLL_LOCK_FIELD		1
-#define STV090x_OFFST_SSTREAM_LCK_3_FIELD	4
-#define STV090x_WIDTH_SSTREAM_LCK_3_FIELD	1
-#define STV090x_OFFST_SSTREAM_LCK_2_FIELD	3
-#define STV090x_WIDTH_SSTREAM_LCK_2_FIELD	1
-#define STV090x_OFFST_SSTREAM_LCK_1_FIELD	2
-#define STV090x_WIDTH_SSTREAM_LCK_1_FIELD	1
-#define STV090x_OFFST_SDVBS1_PRF_2_FIELD	1
-#define STV090x_WIDTH_SDVBS1_PRF_2_FIELD	1
-#define STV090x_OFFST_SDVBS1_PRF_1_FIELD	0
-#define STV090x_WIDTH_SDVBS1_PRF_1_FIELD	1
-
-#define STV090x_IRQSTATUS2			0xf121
-#define STV090x_OFFST_SSPY_ENDSIM_3_FIELD	7
-#define STV090x_WIDTH_SSPY_ENDSIM_3_FIELD	1
-#define STV090x_OFFST_SSPY_ENDSIM_2_FIELD	6
-#define STV090x_WIDTH_SSPY_ENDSIM_2_FIELD	1
-#define STV090x_OFFST_SSPY_ENDSIM_1_FIELD	5
-#define STV090x_WIDTH_SSPY_ENDSIM_1_FIELD	1
-#define STV090x_OFFST_SPKTDEL_ERROR_2_FIELD	4
-#define STV090x_WIDTH_SPKTDEL_ERROR_2_FIELD	1
-#define STV090x_OFFST_SPKTDEL_LOCKB_2_FIELD	3
-#define STV090x_WIDTH_SPKTDEL_LOCKB_2_FIELD	1
-#define STV090x_OFFST_SPKTDEL_LOCK_2_FIELD	2
-#define STV090x_WIDTH_SPKTDEL_LOCK_2_FIELD	1
-#define STV090x_OFFST_SPKTDEL_ERROR_1_FIELD	1
-#define STV090x_WIDTH_SPKTDEL_ERROR_1_FIELD	1
-#define STV090x_OFFST_SPKTDEL_LOCKB_1_FIELD	0
-#define STV090x_WIDTH_SPKTDEL_LOCKB_1_FIELD	1
-
-#define STV090x_IRQSTATUS1			0xf122
-#define STV090x_OFFST_SPKTDEL_LOCK_1_FIELD	7
-#define STV090x_WIDTH_SPKTDEL_LOCK_1_FIELD	1
-#define STV090x_OFFST_SDEMOD_LOCKB_2_FIELD	2
-#define STV090x_WIDTH_SDEMOD_LOCKB_2_FIELD	1
-#define STV090x_OFFST_SDEMOD_LOCK_2_FIELD	1
-#define STV090x_WIDTH_SDEMOD_LOCK_2_FIELD	1
-#define STV090x_OFFST_SDEMOD_IRQ_2_FIELD	0
-#define STV090x_WIDTH_SDEMOD_IRQ_2_FIELD	1
-
-#define STV090x_IRQSTATUS0			0xf123
-#define STV090x_OFFST_SDEMOD_LOCKB_1_FIELD	7
-#define STV090x_WIDTH_SDEMOD_LOCKB_1_FIELD	1
-#define STV090x_OFFST_SDEMOD_LOCK_1_FIELD	6
-#define STV090x_WIDTH_SDEMOD_LOCK_1_FIELD	1
-#define STV090x_OFFST_SDEMOD_IRQ_1_FIELD	5
-#define STV090x_WIDTH_SDEMOD_IRQ_1_FIELD	1
-#define STV090x_OFFST_SBCH_ERRFLAG_FIELD	4
-#define STV090x_WIDTH_SBCH_ERRFLAG_FIELD	1
-#define STV090x_OFFST_SDISEQC2RX_IRQ_FIELD	3
-#define STV090x_WIDTH_SDISEQC2RX_IRQ_FIELD	1
-#define STV090x_OFFST_SDISEQC2TX_IRQ_FIELD	2
-#define STV090x_WIDTH_SDISEQC2TX_IRQ_FIELD	1
-#define STV090x_OFFST_SDISEQC1RX_IRQ_FIELD	1
-#define STV090x_WIDTH_SDISEQC1RX_IRQ_FIELD	1
-#define STV090x_OFFST_SDISEQC1TX_IRQ_FIELD	0
-#define STV090x_WIDTH_SDISEQC1TX_IRQ_FIELD	1
-
-#define STV090x_IRQMASK3			0xf124
-#define STV090x_OFFST_MPLL_LOCK_FIELD		5
-#define STV090x_WIDTH_MPLL_LOCK_FIELD		1
-#define STV090x_OFFST_MSTREAM_LCK_3_FIELD	4
-#define STV090x_WIDTH_MSTREAM_LCK_3_FIELD	1
-#define STV090x_OFFST_MSTREAM_LCK_2_FIELD	3
-#define STV090x_WIDTH_MSTREAM_LCK_2_FIELD	1
-#define STV090x_OFFST_MSTREAM_LCK_1_FIELD	2
-#define STV090x_WIDTH_MSTREAM_LCK_1_FIELD	1
-#define STV090x_OFFST_MDVBS1_PRF_2_FIELD	1
-#define STV090x_WIDTH_MDVBS1_PRF_2_FIELD	1
-#define STV090x_OFFST_MDVBS1_PRF_1_FIELD	0
-#define STV090x_WIDTH_MDVBS1_PRF_1_FIELD	1
-
-#define STV090x_IRQMASK2			0xf125
-#define STV090x_OFFST_MSPY_ENDSIM_3_FIELD	7
-#define STV090x_WIDTH_MSPY_ENDSIM_3_FIELD	1
-#define STV090x_OFFST_MSPY_ENDSIM_2_FIELD	6
-#define STV090x_WIDTH_MSPY_ENDSIM_2_FIELD	1
-#define STV090x_OFFST_MSPY_ENDSIM_1_FIELD	5
-#define STV090x_WIDTH_MSPY_ENDSIM_1_FIELD	1
-#define STV090x_OFFST_MPKTDEL_ERROR_2_FIELD	4
-#define STV090x_WIDTH_MPKTDEL_ERROR_2_FIELD	1
-#define STV090x_OFFST_MPKTDEL_LOCKB_2_FIELD	3
-#define STV090x_WIDTH_MPKTDEL_LOCKB_2_FIELD	1
-#define STV090x_OFFST_MPKTDEL_LOCK_2_FIELD	2
-#define STV090x_WIDTH_MPKTDEL_LOCK_2_FIELD	1
-#define STV090x_OFFST_MPKTDEL_ERROR_1_FIELD	1
-#define STV090x_WIDTH_MPKTDEL_ERROR_1_FIELD	1
-#define STV090x_OFFST_MPKTDEL_LOCKB_1_FIELD	0
-#define STV090x_WIDTH_MPKTDEL_LOCKB_1_FIELD	1
-
-#define STV090x_IRQMASK1			0xf126
-#define STV090x_OFFST_MPKTDEL_LOCK_1_FIELD	7
-#define STV090x_WIDTH_MPKTDEL_LOCK_1_FIELD	1
-#define STV090x_OFFST_MEXTPINB2_FIELD		6
-#define STV090x_WIDTH_MEXTPINB2_FIELD		1
-#define STV090x_OFFST_MEXTPIN2_FIELD		5
-#define STV090x_WIDTH_MEXTPIN2_FIELD		1
-#define STV090x_OFFST_MEXTPINB1_FIELD		4
-#define STV090x_WIDTH_MEXTPINB1_FIELD		1
-#define STV090x_OFFST_MEXTPIN1_FIELD		3
-#define STV090x_WIDTH_MEXTPIN1_FIELD		1
-#define STV090x_OFFST_MDEMOD_LOCKB_2_FIELD	2
-#define STV090x_WIDTH_MDEMOD_LOCKB_2_FIELD	1
-#define STV090x_OFFST_MDEMOD_LOCK_2_FIELD	1
-#define STV090x_WIDTH_MDEMOD_LOCK_2_FIELD	1
-#define STV090x_OFFST_MDEMOD_IRQ_2_FIELD	0
-#define STV090x_WIDTH_MDEMOD_IRQ_2_FIELD	1
-
-#define STV090x_IRQMASK0			0xf127
-#define STV090x_OFFST_MDEMOD_LOCKB_1_FIELD	7
-#define STV090x_WIDTH_MDEMOD_LOCKB_1_FIELD	1
-#define STV090x_OFFST_MDEMOD_LOCK_1_FIELD	6
-#define STV090x_WIDTH_MDEMOD_LOCK_1_FIELD	1
-#define STV090x_OFFST_MDEMOD_IRQ_1_FIELD	5
-#define STV090x_WIDTH_MDEMOD_IRQ_1_FIELD	1
-#define STV090x_OFFST_MBCH_ERRFLAG_FIELD	4
-#define STV090x_WIDTH_MBCH_ERRFLAG_FIELD	1
-#define STV090x_OFFST_MDISEQC2RX_IRQ_FIELD	3
-#define STV090x_WIDTH_MDISEQC2RX_IRQ_FIELD	1
-#define STV090x_OFFST_MDISEQC2TX_IRQ_FIELD	2
-#define STV090x_WIDTH_MDISEQC2TX_IRQ_FIELD	1
-#define STV090x_OFFST_MDISEQC1RX_IRQ_FIELD	1
-#define STV090x_WIDTH_MDISEQC1RX_IRQ_FIELD	1
-#define STV090x_OFFST_MDISEQC1TX_IRQ_FIELD	0
-#define STV090x_WIDTH_MDISEQC1TX_IRQ_FIELD	1
-
-#define STV090x_I2CCFG				0xf129
-#define STV090x_OFFST_12C_FASTMODE_FIELD	3
-#define STV090x_WIDTH_12C_FASTMODE_FIELD	1
-#define STV090x_OFFST_12CADDR_INC_FIELD		0
-#define STV090x_WIDTH_12CADDR_INC_FIELD		2
-
-#define STV090x_Px_I2CRPT(__x)			(0xf12a + (__x - 1) * 0x1)
-#define STV090x_P1_I2CRPT			STV090x_Px_I2CRPT(1)
-#define STV090x_P2_I2CRPT			STV090x_Px_I2CRPT(2)
-#define STV090x_OFFST_Px_I2CT_ON_FIELD		7
-#define STV090x_WIDTH_Px_I2CT_ON_FIELD		1
-#define STV090x_OFFST_Px_ENARPT_LEVEL_FIELD	4
-#define STV090x_WIDTH_Px_ENARPT_LEVEL_FIELD	3
-#define STV090x_OFFST_Px_SCLT_DELAY_FIELD	3
-#define STV090x_WIDTH_Px_SCLT_DELAY_FIELD	1
-#define STV090x_OFFST_Px_STOP_ENABLE_FIELD	2
-#define STV090x_WIDTH_Px_STOP_ENABLE_FIELD	1
-#define STV090x_OFFST_Px_STOP_SDAT2SDA_FIELD	1
-#define STV090x_WIDTH_Px_STOP_SDAT2SDA_FIELD	1
-
-#define STV090x_CLKI2CFG			0xf140
-#define STV090x_OFFST_CLKI2_OPD_FIELD		7
-#define STV090x_WIDTH_CLKI2_OPD_FIELD		1
-#define STV090x_OFFST_CLKI2_CONFIG_FIELD	1
-#define STV090x_WIDTH_CLKI2_CONFIG_FIELD	6
-#define STV090x_OFFST_CLKI2_XOR_FIELD		0
-#define STV090x_WIDTH_CLKI2_XOR_FIELD		1
-
-#define STV090x_GPIOxCFG(__x)			(0xf141 + (__x - 1))
-#define STV090x_GPIO1CFG			STV090x_GPIOxCFG(1)
-#define STV090x_GPIO2CFG			STV090x_GPIOxCFG(2)
-#define STV090x_GPIO3CFG			STV090x_GPIOxCFG(3)
-#define STV090x_GPIO4CFG			STV090x_GPIOxCFG(4)
-#define STV090x_GPIO5CFG			STV090x_GPIOxCFG(5)
-#define STV090x_GPIO6CFG			STV090x_GPIOxCFG(6)
-#define STV090x_GPIO7CFG			STV090x_GPIOxCFG(7)
-#define STV090x_GPIO8CFG			STV090x_GPIOxCFG(8)
-#define STV090x_GPIO9CFG			STV090x_GPIOxCFG(9)
-#define STV090x_GPIO10CFG			STV090x_GPIOxCFG(10)
-#define STV090x_GPIO11CFG			STV090x_GPIOxCFG(11)
-#define STV090x_GPIO12CFG			STV090x_GPIOxCFG(12)
-#define STV090x_GPIO13CFG			STV090x_GPIOxCFG(13)
-#define STV090x_OFFST_GPIOx_OPD_FIELD		7
-#define STV090x_WIDTH_GPIOx_OPD_FIELD		1
-#define STV090x_OFFST_GPIOx_CONFIG_FIELD	1
-#define STV090x_WIDTH_GPIOx_CONFIG_FIELD	6
-#define STV090x_OFFST_GPIOx_XOR_FIELD		0
-#define STV090x_WIDTH_GPIOx_XOR_FIELD		1
-
-#define STV090x_CSxCFG(__x)			(0xf14e + __x * 0x1)
-#define STV090x_CS0CFG				STV090x_CSxCFG(0)
-#define STV090x_CS1CFG				STV090x_CSxCFG(1)
-#define STV090x_OFFST_CSX_OPD_FIELD		7
-#define STV090x_WIDTH_CSX_OPD_FIELD		1
-#define STV090x_OFFST_CSX_CONFIG_FIELD		1
-#define STV090x_WIDTH_CSX_CONFIG_FIELD		6
-#define STV090x_OFFST_CSX_XOR_FIELD		0
-#define STV090x_WIDTH_CSX_XOR_FIELD		1
-
-
-#define STV090x_STDBYCFG			0xf150
-#define STV090x_OFFST_STDBY_OPD_FIELD		7
-#define STV090x_WIDTH_STDBY_OPD_FIELD		1
-#define STV090x_OFFST_STDBY_CONFIG_FIELD	1
-#define STV090x_WIDTH_STDBY_CONFIG_FIELD	6
-#define STV090x_OFFST_STDBY_XOR_FIELD		0
-#define STV090x_WIDTH_STDBY_XOR_FIELD		1
-
-#define STV090x_DIRCLKCFG			0xf151
-#define STV090x_OFFST_DIRCLK_OPD_FIELD		7
-#define STV090x_WIDTH_DIRCLK_OPD_FIELD		1
-#define STV090x_OFFST_DIRCLK_CONFIG_FIELD	1
-#define STV090x_WIDTH_DIRCLK_CONFIG_FIELD	6
-#define STV090x_OFFST_DIRCLK_XOR_FIELD		0
-#define STV090x_WIDTH_DIRCLK_XOR_FIELD		1
-
-
-#define STV090x_AGCRFxCFG(__x)			(0xf152 + (__x - 1) * 0x4)
-#define STV090x_AGCRF1CFG			STV090x_AGCRFxCFG(1)
-#define STV090x_AGCRF2CFG			STV090x_AGCRFxCFG(2)
-#define STV090x_OFFST_AGCRFx_OPD_FIELD		7
-#define STV090x_WIDTH_AGCRFx_OPD_FIELD		1
-#define STV090x_OFFST_AGCRFx_CONFIG_FIELD	1
-#define STV090x_WIDTH_AGCRFx_CONFIG_FIELD	6
-#define STV090x_OFFST_AGCRFx_XOR_FIELD		0
-#define STV090x_WIDTH_AGCRFx_XOR_FIELD		1
-
-#define STV090x_SDATxCFG(__x)			(0xf153 + (__x - 1) * 0x4)
-#define STV090x_SDAT1CFG			STV090x_SDATxCFG(1)
-#define STV090x_SDAT2CFG			STV090x_SDATxCFG(2)
-#define STV090x_OFFST_SDATx_OPD_FIELD		7
-#define STV090x_WIDTH_SDATx_OPD_FIELD		1
-#define STV090x_OFFST_SDATx_CONFIG_FIELD	1
-#define STV090x_WIDTH_SDATx_CONFIG_FIELD	6
-#define STV090x_OFFST_SDATx_XOR_FIELD		0
-#define STV090x_WIDTH_SDATx_XOR_FIELD		1
-
-#define STV090x_SCLTxCFG(__x)			(0xf154 + (__x - 1) * 0x4)
-#define STV090x_SCLT1CFG			STV090x_SCLTxCFG(1)
-#define STV090x_SCLT2CFG			STV090x_SCLTxCFG(2)
-#define STV090x_OFFST_SCLTx_OPD_FIELD		7
-#define STV090x_WIDTH_SCLTx_OPD_FIELD		1
-#define STV090x_OFFST_SCLTx_CONFIG_FIELD	1
-#define STV090x_WIDTH_SCLTx_CONFIG_FIELD	6
-#define STV090x_OFFST_SCLTx_XOR_FIELD		0
-#define STV090x_WIDTH_SCLTx_XOR_FIELD		1
-
-#define STV090x_DISEQCOxCFG(__x)		(0xf155 + (__x - 1) * 0x4)
-#define STV090x_DISEQCO1CFG			STV090x_DISEQCOxCFG(1)
-#define STV090x_DISEQCO2CFG			STV090x_DISEQCOxCFG(2)
-#define STV090x_OFFST_DISEQCOx_OPD_FIELD	7
-#define STV090x_WIDTH_DISEQCOx_OPD_FIELD	1
-#define STV090x_OFFST_DISEQCOx_CONFIG_FIELD	1
-#define STV090x_WIDTH_DISEQCOx_CONFIG_FIELD	6
-#define STV090x_OFFST_DISEQCOx_XOR_FIELD	0
-#define STV090x_WIDTH_DISEQCOx_XOR_FIELD	1
-
-#define STV090x_CLKOUT27CFG			0xf15a
-#define STV090x_OFFST_CLKOUT27_OPD_FIELD	7
-#define STV090x_WIDTH_CLKOUT27_OPD_FIELD	1
-#define STV090x_OFFST_CLKOUT27_CONFIG_FIELD	1
-#define STV090x_WIDTH_CLKOUT27_CONFIG_FIELD	6
-#define STV090x_OFFST_CLKOUT27_XOR_FIELD	0
-#define STV090x_WIDTH_CLKOUT27_XOR_FIELD	1
-
-#define STV090x_ERRORxCFG(__x)			(0xf15b + (__x - 1) * 0x5)
-#define STV090x_ERROR1CFG			STV090x_ERRORxCFG(1)
-#define STV090x_ERROR2CFG			STV090x_ERRORxCFG(2)
-#define STV090x_ERROR3CFG			STV090x_ERRORxCFG(3)
-#define STV090x_OFFST_ERRORx_OPD_FIELD		7
-#define STV090x_WIDTH_ERRORx_OPD_FIELD		1
-#define STV090x_OFFST_ERRORx_CONFIG_FIELD	1
-#define STV090x_WIDTH_ERRORx_CONFIG_FIELD	6
-#define STV090x_OFFST_ERRORx_XOR_FIELD		0
-#define STV090x_WIDTH_ERRORx_XOR_FIELD		1
-
-#define STV090x_DPNxCFG(__x)			(0xf15c + (__x - 1) * 0x5)
-#define STV090x_DPN1CFG				STV090x_DPNxCFG(1)
-#define STV090x_DPN2CFG				STV090x_DPNxCFG(2)
-#define STV090x_DPN3CFG				STV090x_DPNxCFG(3)
-#define STV090x_OFFST_DPNx_OPD_FIELD		7
-#define STV090x_WIDTH_DPNx_OPD_FIELD		1
-#define STV090x_OFFST_DPNx_CONFIG_FIELD		1
-#define STV090x_WIDTH_DPNx_CONFIG_FIELD		6
-#define STV090x_OFFST_DPNx_XOR_FIELD		0
-#define STV090x_WIDTH_DPNx_XOR_FIELD		1
-
-#define STV090x_STROUTxCFG(__x)			(0xf15d + (__x - 1) * 0x5)
-#define STV090x_STROUT1CFG			STV090x_STROUTxCFG(1)
-#define STV090x_STROUT2CFG			STV090x_STROUTxCFG(2)
-#define STV090x_STROUT3CFG			STV090x_STROUTxCFG(3)
-#define STV090x_OFFST_STROUTx_OPD_FIELD		7
-#define STV090x_WIDTH_STROUTx_OPD_FIELD		1
-#define STV090x_OFFST_STROUTx_CONFIG_FIELD	1
-#define STV090x_WIDTH_STROUTx_CONFIG_FIELD	6
-#define STV090x_OFFST_STROUTx_XOR_FIELD		0
-#define STV090x_WIDTH_STROUTx_XOR_FIELD		1
-
-#define STV090x_CLKOUTxCFG(__x)			(0xf15e + (__x - 1) * 0x5)
-#define STV090x_CLKOUT1CFG			STV090x_CLKOUTxCFG(1)
-#define STV090x_CLKOUT2CFG			STV090x_CLKOUTxCFG(2)
-#define STV090x_CLKOUT3CFG			STV090x_CLKOUTxCFG(3)
-#define STV090x_OFFST_CLKOUTx_OPD_FIELD		7
-#define STV090x_WIDTH_CLKOUTx_OPD_FIELD		1
-#define STV090x_OFFST_CLKOUTx_CONFIG_FIELD	1
-#define STV090x_WIDTH_CLKOUTx_CONFIG_FIELD	6
-#define STV090x_OFFST_CLKOUTx_XOR_FIELD		0
-#define STV090x_WIDTH_CLKOUTx_XOR_FIELD		1
-
-#define STV090x_DATAxCFG(__x)			(0xf15f + (__x - 71) * 0x5)
-#define STV090x_DATA71CFG			STV090x_DATAxCFG(71)
-#define STV090x_DATA72CFG			STV090x_DATAxCFG(72)
-#define STV090x_DATA73CFG			STV090x_DATAxCFG(73)
-#define STV090x_OFFST_DATAx_OPD_FIELD		7
-#define STV090x_WIDTH_DATAx_OPD_FIELD		1
-#define STV090x_OFFST_DATAx_CONFIG_FIELD	1
-#define STV090x_WIDTH_DATAx_CONFIG_FIELD	6
-#define STV090x_OFFST_DATAx_XOR_FIELD		0
-#define STV090x_WIDTH_DATAx_XOR_FIELD		1
-
-#define STV090x_NCOARSE				0xf1b3
-#define STV090x_OFFST_M_DIV_FIELD		0
-#define STV090x_WIDTH_M_DIV_FIELD		8
-
-#define STV090x_SYNTCTRL			0xf1b6
-#define STV090x_OFFST_STANDBY_FIELD		7
-#define STV090x_WIDTH_STANDBY_FIELD		1
-#define STV090x_OFFST_BYPASSPLLCORE_FIELD	6
-#define STV090x_WIDTH_BYPASSPLLCORE_FIELD	1
-#define STV090x_OFFST_SELX1RATIO_FIELD		5
-#define STV090x_WIDTH_SELX1RATIO_FIELD		1
-#define STV090x_OFFST_STOP_PLL_FIELD		3
-#define STV090x_WIDTH_STOP_PLL_FIELD		1
-#define STV090x_OFFST_BYPASSPLLFSK_FIELD	2
-#define STV090x_WIDTH_BYPASSPLLFSK_FIELD	1
-#define STV090x_OFFST_SELOSCI_FIELD		1
-#define STV090x_WIDTH_SELOSCI_FIELD		1
-#define STV090x_OFFST_BYPASSPLLADC_FIELD	0
-#define STV090x_WIDTH_BYPASSPLLADC_FIELD	1
-
-#define STV090x_FILTCTRL			0xf1b7
-#define STV090x_OFFST_INV_CLK135_FIELD		7
-#define STV090x_WIDTH_INV_CLK135_FIELD		1
-#define STV090x_OFFST_SEL_FSKCKDIV_FIELD	2
-#define STV090x_WIDTH_SEL_FSKCKDIV_FIELD	1
-#define STV090x_OFFST_INV_CLKFSK_FIELD		1
-#define STV090x_WIDTH_INV_CLKFSK_FIELD		1
-#define STV090x_OFFST_BYPASS_APPLI_FIELD	0
-#define STV090x_WIDTH_BYPASS_APPLI_FIELD	1
-
-#define STV090x_PLLSTAT				0xf1b8
-#define STV090x_OFFST_PLLLOCK_FIELD		0
-#define STV090x_WIDTH_PLLLOCK_FIELD		1
-
-#define STV090x_STOPCLK1			0xf1c2
-#define STV090x_OFFST_STOP_CLKPKDT2_FIELD	6
-#define STV090x_WIDTH_STOP_CLKPKDT2_FIELD	1
-#define STV090x_OFFST_STOP_CLKPKDT1_FIELD	5
-#define STV090x_WIDTH_STOP_CLKPKDT1_FIELD	1
-#define STV090x_OFFST_STOP_CLKFEC_FIELD		4
-#define STV090x_WIDTH_STOP_CLKFEC_FIELD		1
-#define STV090x_OFFST_STOP_CLKADCI2_FIELD	3
-#define STV090x_WIDTH_STOP_CLKADCI2_FIELD	1
-#define STV090x_OFFST_INV_CLKADCI2_FIELD	2
-#define STV090x_WIDTH_INV_CLKADCI2_FIELD	1
-#define STV090x_OFFST_STOP_CLKADCI1_FIELD	1
-#define STV090x_WIDTH_STOP_CLKADCI1_FIELD	1
-#define STV090x_OFFST_INV_CLKADCI1_FIELD	0
-#define STV090x_WIDTH_INV_CLKADCI1_FIELD	1
-
-#define STV090x_STOPCLK2			0xf1c3
-#define STV090x_OFFST_STOP_CLKSAMP2_FIELD	4
-#define STV090x_WIDTH_STOP_CLKSAMP2_FIELD	1
-#define STV090x_OFFST_STOP_CLKSAMP1_FIELD	3
-#define STV090x_WIDTH_STOP_CLKSAMP1_FIELD	1
-#define STV090x_OFFST_STOP_CLKVIT2_FIELD	2
-#define STV090x_WIDTH_STOP_CLKVIT2_FIELD	1
-#define STV090x_OFFST_STOP_CLKVIT1_FIELD	1
-#define STV090x_WIDTH_STOP_CLKVIT1_FIELD	1
-#define STV090x_OFFST_STOP_CLKTS_FIELD		0
-#define STV090x_WIDTH_STOP_CLKTS_FIELD		1
-
-#define STV090x_TSTTNR0				0xf1df
-#define STV090x_OFFST_SEL_FSK_FIELD		7
-#define STV090x_WIDTH_SEL_FSK_FIELD		1
-#define STV090x_OFFST_FSK_PON_FIELD		2
-#define STV090x_WIDTH_FSK_PON_FIELD		1
-
-#define STV090x_TSTTNR1				0xf1e0
-#define STV090x_OFFST_ADC1_PON_FIELD		1
-#define STV090x_WIDTH_ADC1_PON_FIELD		1
-#define STV090x_OFFST_ADC1_INMODE_FIELD		0
-#define STV090x_WIDTH_ADC1_INMODE_FIELD		1
-
-#define STV090x_TSTTNR2				0xf1e1
-#define STV090x_OFFST_DISEQC1_PON_FIELD		5
-#define STV090x_WIDTH_DISEQC1_PON_FIELD		1
-
-#define STV090x_TSTTNR3				0xf1e2
-#define STV090x_OFFST_ADC2_PON_FIELD		1
-#define STV090x_WIDTH_ADC2_PON_FIELD		1
-#define STV090x_OFFST_ADC2_INMODE_FIELD		0
-#define STV090x_WIDTH_ADC2_INMODE_FIELD		1
-
-#define STV090x_TSTTNR4				0xf1e3
-#define STV090x_OFFST_DISEQC2_PON_FIELD		5
-#define STV090x_WIDTH_DISEQC2_PON_FIELD		1
-
-#define STV090x_FSKTFC2				0xf170
-#define STV090x_OFFST_FSKT_KMOD_FIELD		2
-#define STV090x_WIDTH_FSKT_KMOD_FIELD		6
-#define STV090x_OFFST_FSKT_CAR_FIELD		0
-#define STV090x_WIDTH_FSKT_CAR_FIELD		2
-
-#define STV090x_FSKTFC1				0xf171
-#define STV090x_OFFST_FSKTC1_CAR_FIELD		0
-#define STV090x_WIDTH_FSKTC1_CAR_FIELD		8
-
-#define STV090x_FSKTFC0				0xf172
-#define STV090x_OFFST_FSKTC0_CAR_FIELD		0
-#define STV090x_WIDTH_FSKTC0_CAR_FIELD		8
-
-#define STV090x_FSKTDELTAF1			0xf173
-#define STV090x_OFFST_FSKTF1_DELTAF_FIELD	0
-#define STV090x_WIDTH_FSKTF1_DELTAF_FIELD	4
-
-#define STV090x_FSKTDELTAF0			0xf174
-#define STV090x_OFFST_FSKTF0_DELTAF_FIELD	0
-#define STV090x_WIDTH_FSKTF0_DELTAF_FIELD	8
-
-#define STV090x_FSKTCTRL			0xf175
-#define STV090x_OFFST_FSKT_EN_SGN_FIELD		6
-#define STV090x_WIDTH_FSKT_EN_SGN_FIELD		1
-#define STV090x_OFFST_FSKT_MOD_SGN_FIELD	5
-#define STV090x_WIDTH_FSKT_MOD_SGN_FIELD	1
-#define STV090x_OFFST_FSKT_MOD_EN_FIELD		2
-#define STV090x_WIDTH_FSKT_MOD_EN_FIELD		3
-#define STV090x_OFFST_FSKT_DACMODE_FIELD	0
-#define STV090x_WIDTH_FSKT_DACMODE_FIELD	2
-
-#define STV090x_FSKRFC2				0xf176
-#define STV090x_OFFST_FSKRC2_DETSGN_FIELD	6
-#define STV090x_WIDTH_FSKRC2_DETSGN_FIELD	1
-#define STV090x_OFFST_FSKRC2_OUTSGN_FIELD	5
-#define STV090x_WIDTH_FSKRC2_OUTSGN_FIELD	1
-#define STV090x_OFFST_FSKRC2_KAGC_FIELD		2
-#define STV090x_WIDTH_FSKRC2_KAGC_FIELD		3
-#define STV090x_OFFST_FSKRC2_CAR_FIELD		0
-#define STV090x_WIDTH_FSKRC2_CAR_FIELD		2
-
-#define STV090x_FSKRFC1				0xf177
-#define STV090x_OFFST_FSKRC1_CAR_FIELD		0
-#define STV090x_WIDTH_FSKRC1_CAR_FIELD		8
-
-#define STV090x_FSKRFC0				0xf178
-#define STV090x_OFFST_FSKRC0_CAR_FIELD		0
-#define STV090x_WIDTH_FSKRC0_CAR_FIELD		8
-
-#define STV090x_FSKRK1				0xf179
-#define STV090x_OFFST_FSKR_K1_EXP_FIELD		5
-#define STV090x_WIDTH_FSKR_K1_EXP_FIELD		3
-#define STV090x_OFFST_FSKR_K1_MANT_FIELD	0
-#define STV090x_WIDTH_FSKR_K1_MANT_FIELD	5
-
-#define STV090x_FSKRK2				0xf17a
-#define STV090x_OFFST_FSKR_K2_EXP_FIELD		5
-#define STV090x_WIDTH_FSKR_K2_EXP_FIELD		3
-#define STV090x_OFFST_FSKR_K2_MANT_FIELD	0
-#define STV090x_WIDTH_FSKR_K2_MANT_FIELD	5
-
-#define STV090x_FSKRAGCR			0xf17b
-#define STV090x_OFFST_FSKR_OUTCTL_FIELD		6
-#define STV090x_WIDTH_FSKR_OUTCTL_FIELD		2
-#define STV090x_OFFST_FSKR_AGC_REF_FIELD	0
-#define STV090x_WIDTH_FSKR_AGC_REF_FIELD	6
-
-#define STV090x_FSKRAGC				0xf17c
-#define STV090x_OFFST_FSKR_AGC_ACCU_FIELD	0
-#define STV090x_WIDTH_FSKR_AGC_ACCU_FIELD	8
-
-#define STV090x_FSKRALPHA			0xf17d
-#define STV090x_OFFST_FSKR_ALPHA_EXP_FIELD	2
-#define STV090x_WIDTH_FSKR_ALPHA_EXP_FIELD	3
-#define STV090x_OFFST_FSKR_ALPHA_M_FIELD	0
-#define STV090x_WIDTH_FSKR_ALPHA_M_FIELD	2
-
-#define STV090x_FSKRPLTH1			0xf17e
-#define STV090x_OFFST_FSKR_BETA_FIELD		4
-#define STV090x_WIDTH_FSKR_BETA_FIELD		4
-#define STV090x_OFFST_FSKR_PLL_TRESH1_FIELD	0
-#define STV090x_WIDTH_FSKR_PLL_TRESH1_FIELD	4
-
-#define STV090x_FSKRPLTH0			0xf17f
-#define STV090x_OFFST_FSKR_PLL_TRESH0_FIELD	0
-#define STV090x_WIDTH_FSKR_PLL_TRESH0_FIELD	8
-
-#define STV090x_FSKRDF1				0xf180
-#define STV090x_OFFST_FSKR_DELTAF1_FIELD	0
-#define STV090x_WIDTH_FSKR_DELTAF1_FIELD	5
-
-#define STV090x_FSKRDF0				0xf181
-#define STV090x_OFFST_FSKR_DELTAF0_FIELD	0
-#define STV090x_WIDTH_FSKR_DELTAF0_FIELD	8
-
-#define STV090x_FSKRSTEPP			0xf182
-#define STV090x_OFFST_FSKR_STEP_PLUS_FIELD	0
-#define STV090x_WIDTH_FSKR_STEP_PLUS_FIELD	8
-
-#define STV090x_FSKRSTEPM			0xf183
-#define STV090x_OFFST_FSKR_STEP_MINUS_FIELD	0
-#define STV090x_WIDTH_FSKR_STEP_MINUS_FIELD	8
-
-#define STV090x_FSKRDET1			0xf184
-#define STV090x_OFFST_FSKR_CARDET1_ACCU_FIELD	0
-#define STV090x_WIDTH_FSKR_CARDET1_ACCU_FIELD	4
-
-#define STV090x_FSKRDET0			0xf185
-#define STV090x_OFFST_FSKR_CARDET0_ACCU_FIELD	0
-#define STV090x_WIDTH_FSKR_CARDET0_ACCU_FIELD	8
-
-#define STV090x_FSKRDTH1				0xf186
-#define STV090x_OFFST_FSKR_CARLOSS_THRESH1_FIELD	4
-#define STV090x_WIDTH_FSKR_CARLOSS_THRESH1_FIELD	4
-#define STV090x_OFFST_FSKR_CARDET_THRESH1_FIELD		0
-#define STV090x_WIDTH_FSKR_CARDET_THRESH1_FIELD		4
-
-#define STV090x_FSKRDTH0			0xf187
-#define STV090x_OFFST_FSKR_CARDET_THRESH0_FIELD	0
-#define STV090x_WIDTH_FSKR_CARDET_THRESH0_FIELD	8
-
-#define STV090x_FSKRLOSS			0xf188
-#define STV090x_OFFST_FSKR_CARLOSS_THRESH_FIELD	0
-#define STV090x_WIDTH_FSKR_CARLOSS_THRESH_FIELD	8
-
-#define STV090x_Px_DISTXCTL(__x)		(0xF1A0 - (__x - 1) * 0x10)
-#define STV090x_P1_DISTXCTL			STV090x_Px_DISTXCTL(1)
-#define STV090x_P2_DISTXCTL			STV090x_Px_DISTXCTL(2)
-#define STV090x_OFFST_Px_TIM_OFF_FIELD		7
-#define STV090x_WIDTH_Px_TIM_OFF_FIELD		1
-#define STV090x_OFFST_Px_DISEQC_RESET_FIELD	6
-#define STV090x_WIDTH_Px_DISEQC_RESET_FIELD	1
-#define STV090x_OFFST_Px_TIM_CMD_FIELD		4
-#define STV090x_WIDTH_Px_TIM_CMD_FIELD		2
-#define STV090x_OFFST_Px_DIS_PRECHARGE_FIELD	3
-#define STV090x_WIDTH_Px_DIS_PRECHARGE_FIELD	1
-#define STV090x_OFFST_Px_DISTX_MODE_FIELD	0
-#define STV090x_WIDTH_Px_DISTX_MODE_FIELD	3
-
-#define STV090x_Px_DISRXCTL(__x)		(0xf1a1 - (__x - 1) * 0x10)
-#define STV090x_P1_DISRXCTL			STV090x_Px_DISRXCTL(1)
-#define STV090x_P2_DISRXCTL			STV090x_Px_DISRXCTL(2)
-#define STV090x_OFFST_Px_RECEIVER_ON_FIELD	7
-#define STV090x_WIDTH_Px_RECEIVER_ON_FIELD	1
-#define STV090x_OFFST_Px_IGNO_SHORT22K_FIELD	6
-#define STV090x_WIDTH_Px_IGNO_SHORT22K_FIELD	1
-#define STV090x_OFFST_Px_ONECHIP_TRX_FIELD	5
-#define STV090x_WIDTH_Px_ONECHIP_TRX_FIELD	1
-#define STV090x_OFFST_Px_EXT_ENVELOP_FIELD	4
-#define STV090x_WIDTH_Px_EXT_ENVELOP_FIELD	1
-#define STV090x_OFFST_Px_PIN_SELECT_FIELD	2
-#define STV090x_WIDTH_Px_PIN_SELECT_FIELD	2
-#define STV090x_OFFST_Px_IRQ_RXEND_FIELD	1
-#define STV090x_WIDTH_Px_IRQ_RXEND_FIELD	1
-#define STV090x_OFFST_Px_IRQ_4NBYTES_FIELD	0
-#define STV090x_WIDTH_Px_IRQ_4NBYTES_FIELD	1
-
-#define STV090x_Px_DISRX_ST0(__x)		(0xf1a4 - (__x - 1) * 0x10)
-#define STV090x_P1_DISRX_ST0			STV090x_Px_DISRX_ST0(1)
-#define STV090x_P2_DISRX_ST0			STV090x_Px_DISRX_ST0(2)
-#define STV090x_OFFST_Px_RX_END_FIELD		7
-#define STV090x_WIDTH_Px_RX_END_FIELD		1
-#define STV090x_OFFST_Px_RX_ACTIVE_FIELD	6
-#define STV090x_WIDTH_Px_RX_ACTIVE_FIELD	1
-#define STV090x_OFFST_Px_SHORT_22KHZ_FIELD	5
-#define STV090x_WIDTH_Px_SHORT_22KHZ_FIELD	1
-#define STV090x_OFFST_Px_CONT_TONE_FIELD	4
-#define STV090x_WIDTH_Px_CONT_TONE_FIELD	1
-#define STV090x_OFFST_Px_FIFO_4BREADY_FIELD	3
-#define STV090x_WIDTH_Px_FIFO_4BREADY_FIELD	1
-#define STV090x_OFFST_Px_FIFO_EMPTY_FIELD	2
-#define STV090x_WIDTH_Px_FIFO_EMPTY_FIELD	1
-#define STV090x_OFFST_Px_ABORT_DISRX_FIELD	0
-#define STV090x_WIDTH_Px_ABORT_DISRX_FIELD	1
-
-#define STV090x_Px_DISRX_ST1(__x)		(0xf1a5 - (__x - 1) * 0x10)
-#define STV090x_P1_DISRX_ST1			STV090x_Px_DISRX_ST1(1)
-#define STV090x_P2_DISRX_ST1			STV090x_Px_DISRX_ST1(2)
-#define STV090x_OFFST_Px_RX_FAIL_FIELD		7
-#define STV090x_WIDTH_Px_RX_FAIL_FIELD		1
-#define STV090x_OFFST_Px_FIFO_PARITYFAIL_FIELD	6
-#define STV090x_WIDTH_Px_FIFO_PARITYFAIL_FIELD	1
-#define STV090x_OFFST_Px_RX_NONBYTE_FIELD	5
-#define STV090x_WIDTH_Px_RX_NONBYTE_FIELD	1
-#define STV090x_OFFST_Px_FIFO_OVERFLOW_FIELD	4
-#define STV090x_WIDTH_Px_FIFO_OVERFLOW_FIELD	1
-#define STV090x_OFFST_Px_FIFO_BYTENBR_FIELD	0
-#define STV090x_WIDTH_Px_FIFO_BYTENBR_FIELD	4
-
-#define STV090x_Px_DISRXDATA(__x)		(0xf1a6 - (__x - 1) * 0x10)
-#define STV090x_P1_DISRXDATA			STV090x_Px_DISRXDATA(1)
-#define STV090x_P2_DISRXDATA			STV090x_Px_DISRXDATA(2)
-#define STV090x_OFFST_Px_DISRX_DATA_FIELD	0
-#define STV090x_WIDTH_Px_DISRX_DATA_FIELD	8
-
-#define STV090x_Px_DISTXDATA(__x)		(0xf1a7 - (__x - 1) * 0x10)
-#define STV090x_P1_DISTXDATA			STV090x_Px_DISTXDATA(1)
-#define STV090x_P2_DISTXDATA			STV090x_Px_DISTXDATA(2)
-#define STV090x_OFFST_Px_DISEQC_FIFO_FIELD	0
-#define STV090x_WIDTH_Px_DISEQC_FIFO_FIELD	8
-
-#define STV090x_Px_DISTXSTATUS(__x)		(0xf1a8 - (__x - 1) * 0x10)
-#define STV090x_P1_DISTXSTATUS			STV090x_Px_DISTXSTATUS(1)
-#define STV090x_P2_DISTXSTATUS			STV090x_Px_DISTXSTATUS(2)
-#define STV090x_OFFST_Px_TX_FAIL_FIELD		7
-#define STV090x_WIDTH_Px_TX_FAIL_FIELD		1
-#define STV090x_OFFST_Px_FIFO_FULL_FIELD	6
-#define STV090x_WIDTH_Px_FIFO_FULL_FIELD	1
-#define STV090x_OFFST_Px_TX_IDLE_FIELD		5
-#define STV090x_WIDTH_Px_TX_IDLE_FIELD		1
-#define STV090x_OFFST_Px_GAP_BURST_FIELD	4
-#define STV090x_WIDTH_Px_GAP_BURST_FIELD	1
-#define STV090x_OFFST_Px_TXFIFO_BYTES_FIELD	0
-#define STV090x_WIDTH_Px_TXFIFO_BYTES_FIELD	4
-
-#define STV090x_Px_F22TX(__x)			(0xf1a9 - (__x - 1) * 0x10)
-#define STV090x_P1_F22TX			STV090x_Px_F22TX(1)
-#define STV090x_P2_F22TX			STV090x_Px_F22TX(2)
-#define STV090x_OFFST_Px_F22_REG_FIELD		0
-#define STV090x_WIDTH_Px_F22_REG_FIELD		8
-
-#define STV090x_Px_F22RX(__x)			(0xf1aa - (__x - 1) * 0x10)
-#define STV090x_P1_F22RX			STV090x_Px_F22RX(1)
-#define STV090x_P2_F22RX			STV090x_Px_F22RX(2)
-#define STV090x_OFFST_Px_F22RX_REG_FIELD	0
-#define STV090x_WIDTH_Px_F22RX_REG_FIELD	8
-
-#define STV090x_Px_ACRPRESC(__x)		(0xf1ac - (__x - 1) * 0x10)
-#define STV090x_P1_ACRPRESC			STV090x_Px_ACRPRESC(1)
-#define STV090x_P2_ACRPRESC			STV090x_Px_ACRPRESC(2)
-#define STV090x_OFFST_Px_ACR_PRESC_FIELD	0
-#define STV090x_WIDTH_Px_ACR_PRESC_FIELD	3
-
-#define STV090x_Px_ACRDIV(__x)			(0xf1ad - (__x - 1) * 0x10)
-#define STV090x_P1_ACRDIV			STV090x_Px_ACRDIV(1)
-#define STV090x_P2_ACRDIV			STV090x_Px_ACRDIV(2)
-#define STV090x_OFFST_Px_ACR_DIV_FIELD		0
-#define STV090x_WIDTH_Px_ACR_DIV_FIELD		8
-
-#define STV090x_Px_IQCONST(__x)			(0xF400 - (__x - 1) * 0x200)
-#define STV090x_P1_IQCONST			STV090x_Px_IQCONST(1)
-#define STV090x_P2_IQCONST			STV090x_Px_IQCONST(2)
-#define STV090x_OFFST_Px_CONSTEL_SELECT_FIELD	5
-#define STV090x_WIDTH_Px_CONSTEL_SELECT_FIELD	2
-
-#define STV090x_Px_NOSCFG(__x)			(0xF401 - (__x - 1) * 0x200)
-#define STV090x_P1_NOSCFG			STV090x_Px_NOSCFG(1)
-#define STV090x_P2_NOSCFG			STV090x_Px_NOSCFG(2)
-#define STV090x_OFFST_Px_NOSPLH_BETA_FIELD	3
-#define STV090x_WIDTH_Px_NOSPLH_BETA_FIELD	2
-#define STV090x_OFFST_Px_NOSDATA_BETA_FIELD	0
-#define STV090x_WIDTH_Px_NOSDATA_BETA_FIELD	3
-
-#define STV090x_Px_ISYMB(__x)			(0xF402 - (__x - 1) * 0x200)
-#define STV090x_P1_ISYMB			STV090x_Px_ISYMB(1)
-#define STV090x_P2_ISYMB			STV090x_Px_ISYMB(2)
-#define STV090x_OFFST_Px_I_SYMBOL_FIELD		0
-#define STV090x_WIDTH_Px_I_SYMBOL_FIELD		8
-
-#define STV090x_Px_QSYMB(__x)			(0xF403 - (__x - 1) * 0x200)
-#define STV090x_P1_QSYMB			STV090x_Px_QSYMB(1)
-#define STV090x_P2_QSYMB			STV090x_Px_QSYMB(2)
-#define STV090x_OFFST_Px_Q_SYMBOL_FIELD		0
-#define STV090x_WIDTH_Px_Q_SYMBOL_FIELD		8
-
-#define STV090x_Px_AGC1CFG(__x)			(0xF404 - (__x - 1) * 0x200)
-#define STV090x_P1_AGC1CFG			STV090x_Px_AGC1CFG(1)
-#define STV090x_P2_AGC1CFG			STV090x_Px_AGC1CFG(2)
-#define STV090x_OFFST_Px_DC_FROZEN_FIELD	7
-#define STV090x_WIDTH_Px_DC_FROZEN_FIELD	1
-#define STV090x_OFFST_Px_DC_CORRECT_FIELD	6
-#define STV090x_WIDTH_Px_DC_CORRECT_FIELD	1
-#define STV090x_OFFST_Px_AMM_FROZEN_FIELD	5
-#define STV090x_WIDTH_Px_AMM_FROZEN_FIELD	1
-#define STV090x_OFFST_Px_AMM_CORRECT_FIELD	4
-#define STV090x_WIDTH_Px_AMM_CORRECT_FIELD	1
-#define STV090x_OFFST_Px_QUAD_FROZEN_FIELD	3
-#define STV090x_WIDTH_Px_QUAD_FROZEN_FIELD	1
-#define STV090x_OFFST_Px_QUAD_CORRECT_FIELD	2
-#define STV090x_WIDTH_Px_QUAD_CORRECT_FIELD	1
-
-#define STV090x_Px_AGC1CN(__x)			(0xF406 - (__x - 1) * 0x200)
-#define STV090x_P1_AGC1CN			STV090x_Px_AGC1CN(1)
-#define STV090x_P2_AGC1CN			STV090x_Px_AGC1CN(2)
-#define STV090x_WIDTH_Px_AGC1_LOCKED_FIELD	7
-#define STV090x_OFFST_Px_AGC1_LOCKED_FIELD	1
-#define STV090x_OFFST_Px_AGC1_MINPOWER_FIELD	4
-#define STV090x_WIDTH_Px_AGC1_MINPOWER_FIELD	1
-#define STV090x_OFFST_Px_AGCOUT_FAST_FIELD	3
-#define STV090x_WIDTH_Px_AGCOUT_FAST_FIELD	1
-#define STV090x_OFFST_Px_AGCIQ_BETA_FIELD	0
-#define STV090x_WIDTH_Px_AGCIQ_BETA_FIELD	3
-
-#define STV090x_Px_AGC1REF(__x)			(0xF407 - (__x - 1) * 0x200)
-#define STV090x_P1_AGC1REF			STV090x_Px_AGC1REF(1)
-#define STV090x_P2_AGC1REF			STV090x_Px_AGC1REF(2)
-#define STV090x_OFFST_Px_AGCIQ_REF_FIELD	0
-#define STV090x_WIDTH_Px_AGCIQ_REF_FIELD	8
-
-#define STV090x_Px_IDCCOMP(__x)			(0xF408 - (__x - 1) * 0x200)
-#define STV090x_P1_IDCCOMP			STV090x_Px_IDCCOMP(1)
-#define STV090x_P2_IDCCOMP			STV090x_Px_IDCCOMP(2)
-#define STV090x_OFFST_Px_IAVERAGE_ADJ_FIELD	0
-#define STV090x_WIDTH_Px_IAVERAGE_ADJ_FIELD	8
-
-#define STV090x_Px_QDCCOMP(__x)			(0xF409 - (__x - 1) * 0x200)
-#define STV090x_P1_QDCCOMP			STV090x_Px_QDCCOMP(1)
-#define STV090x_P2_QDCCOMP			STV090x_Px_QDCCOMP(2)
-#define STV090x_OFFST_Px_QAVERAGE_ADJ_FIELD	0
-#define STV090x_WIDTH_Px_QAVERAGE_ADJ_FIELD	8
-
-#define STV090x_Px_POWERI(__x)			(0xF40A - (__x - 1) * 0x200)
-#define STV090x_P1_POWERI			STV090x_Px_POWERI(1)
-#define STV090x_P2_POWERI			STV090x_Px_POWERI(2)
-#define STV090x_OFFST_Px_POWER_I_FIELD		0
-#define STV090x_WIDTH_Px_POWER_I_FIELD		8
-
-#define STV090x_Px_POWERQ(__x)			(0xF40B - (__x - 1) * 0x200)
-#define STV090x_P1_POWERQ			STV090x_Px_POWERQ(1)
-#define STV090x_P2_POWERQ			STV090x_Px_POWERQ(2)
-#define STV090x_OFFST_Px_POWER_Q_FIELD		0
-#define STV090x_WIDTH_Px_POWER_Q_FIELD		8
-
-#define STV090x_Px_AGC1AMM(__x)			(0xF40C - (__x - 1) * 0x200)
-#define STV090x_P1_AGC1AMM			STV090x_Px_AGC1AMM(1)
-#define STV090x_P2_AGC1AMM			STV090x_Px_AGC1AMM(2)
-#define STV090x_OFFST_Px_AMM_VALUE_FIELD	0
-#define STV090x_WIDTH_Px_AMM_VALUE_FIELD	8
-
-#define STV090x_Px_AGC1QUAD(__x)		(0xF40D - (__x - 1) * 0x200)
-#define STV090x_P1_AGC1QUAD			STV090x_Px_AGC1QUAD(1)
-#define STV090x_P2_AGC1QUAD			STV090x_Px_AGC1QUAD(2)
-#define STV090x_OFFST_Px_QUAD_VALUE_FIELD	0
-#define STV090x_WIDTH_Px_QUAD_VALUE_FIELD	8
-
-#define STV090x_Px_AGCIQINy(__x, __y)		(0xF40F - (__x-1) * 0x200 - __y * 0x1)
-#define STV090x_P1_AGCIQIN0			STV090x_Px_AGCIQINy(1, 0)
-#define STV090x_P1_AGCIQIN1			STV090x_Px_AGCIQINy(1, 1)
-#define STV090x_P2_AGCIQIN0			STV090x_Px_AGCIQINy(2, 0)
-#define STV090x_P2_AGCIQIN1			STV090x_Px_AGCIQINy(2, 1)
-#define STV090x_OFFST_Px_AGCIQ_VALUE_FIELD	0
-#define STV090x_WIDTH_Px_AGCIQ_VALUE_FIELD	8
-
-#define STV090x_Px_DEMOD(__x)			(0xF410 - (__x - 1) * 0x200)
-#define STV090x_P1_DEMOD			STV090x_Px_DEMOD(1)
-#define STV090x_P2_DEMOD			STV090x_Px_DEMOD(2)
-#define STV090x_OFFST_Px_MANUAL_S2ROLLOFF_FIELD	7
-#define STV090x_WIDTH_Px_MANUAL_S2ROLLOFF_FIELD	1
-#define STV090x_OFFST_Px_DEMOD_STOP_FIELD	6
-#define STV090x_WIDTH_Px_DEMOD_STOP_FIELD	1
-#define STV090x_OFFST_Px_SPECINV_CONTROL_FIELD	4
-#define STV090x_WIDTH_Px_SPECINV_CONTROL_FIELD	2
-#define STV090x_OFFST_Px_FORCE_ENASAMP_FIELD	3
-#define STV090x_WIDTH_Px_FORCE_ENASAMP_FIELD	1
-#define STV090x_OFFST_Px_MANUAL_SXROLLOFF_FIELD	2
-#define STV090x_WIDTH_Px_MANUAL_SXROLLOFF_FIELD	1
-#define STV090x_OFFST_Px_ROLLOFF_CONTROL_FIELD	0
-#define STV090x_WIDTH_Px_ROLLOFF_CONTROL_FIELD	2
-
-#define STV090x_Px_DMDMODCOD(__x)		(0xF411 - (__x - 1) * 0x200)
-#define STV090x_P1_DMDMODCOD			STV090x_Px_DMDMODCOD(1)
-#define STV090x_P2_DMDMODCOD			STV090x_Px_DMDMODCOD(2)
-#define STV090x_OFFST_Px_MANUAL_MODCOD_FIELD	7
-#define STV090x_WIDTH_Px_MANUAL_MODCOD_FIELD	1
-#define STV090x_OFFST_Px_DEMOD_MODCOD_FIELD	2
-#define STV090x_WIDTH_Px_DEMOD_MODCOD_FIELD	5
-#define STV090x_OFFST_Px_DEMOD_TYPE_FIELD	0
-#define STV090x_WIDTH_Px_DEMOD_TYPE_FIELD	2
-
-#define STV090x_Px_DSTATUS(__x)			(0xF412 - (__x - 1) * 0x200)
-#define STV090x_P1_DSTATUS			STV090x_Px_DSTATUS(1)
-#define STV090x_P2_DSTATUS			STV090x_Px_DSTATUS(2)
-#define STV090x_OFFST_Px_CAR_LOCK_FIELD		7
-#define STV090x_WIDTH_Px_CAR_LOCK_FIELD		1
-#define STV090x_OFFST_Px_TMGLOCK_QUALITY_FIELD	5
-#define STV090x_WIDTH_Px_TMGLOCK_QUALITY_FIELD	2
-#define STV090x_OFFST_Px_LOCK_DEFINITIF_FIELD	3
-#define STV090x_WIDTH_Px_LOCK_DEFINITIF_FIELD	1
-
-#define STV090x_Px_DSTATUS2(__x)		(0xF413 - (__x - 1) * 0x200)
-#define STV090x_P1_DSTATUS2			STV090x_Px_DSTATUS2(1)
-#define STV090x_P2_DSTATUS2			STV090x_Px_DSTATUS2(2)
-#define STV090x_OFFST_Px_DEMOD_DELOCK_FIELD	7
-#define STV090x_WIDTH_Px_DEMOD_DELOCK_FIELD	1
-#define STV090x_OFFST_Px_AGC1_NOSIGNALACK_FIELD	3
-#define STV090x_WIDTH_Px_AGC1_NOSIGNALACK_FIELD	1
-#define STV090x_OFFST_Px_AGC2_OVERFLOW_FIELD	2
-#define STV090x_WIDTH_Px_AGC2_OVERFLOW_FIELD	1
-#define STV090x_OFFST_Px_CFR_OVERFLOW_FIELD	1
-#define STV090x_WIDTH_Px_CFR_OVERFLOW_FIELD	1
-#define STV090x_OFFST_Px_GAMMA_OVERUNDER_FIELD	0
-#define STV090x_WIDTH_Px_GAMMA_OVERUNDER_FIELD	1
-
-#define STV090x_Px_DMDCFGMD(__x)		(0xF414 - (__x - 1) * 0x200)
-#define STV090x_P1_DMDCFGMD			STV090x_Px_DMDCFGMD(1)
-#define STV090x_P2_DMDCFGMD			STV090x_Px_DMDCFGMD(2)
-#define STV090x_OFFST_Px_DVBS2_ENABLE_FIELD	7
-#define STV090x_WIDTH_Px_DVBS2_ENABLE_FIELD	1
-#define STV090x_OFFST_Px_DVBS1_ENABLE_FIELD	6
-#define STV090x_WIDTH_Px_DVBS1_ENABLE_FIELD	1
-#define STV090x_OFFST_Px_SCAN_ENABLE_FIELD	4
-#define STV090x_WIDTH_Px_SCAN_ENABLE_FIELD	1
-#define STV090x_OFFST_Px_CFR_AUTOSCAN_FIELD	3
-#define STV090x_WIDTH_Px_CFR_AUTOSCAN_FIELD	1
-#define STV090x_OFFST_Px_NOFORCE_RELOCK_FIELD	2
-#define STV090x_WIDTH_Px_NOFORCE_RELOCK_FIELD	1
-#define STV090x_OFFST_Px_TUN_RNG_FIELD		0
-#define STV090x_WIDTH_Px_TUN_RNG_FIELD		2
-
-#define STV090x_Px_DMDCFG2(__x)			(0xF415 - (__x - 1) * 0x200)
-#define STV090x_P1_DMDCFG2			STV090x_Px_DMDCFG2(1)
-#define STV090x_P2_DMDCFG2			STV090x_Px_DMDCFG2(2)
-#define STV090x_OFFST_Px_S1S2_SEQUENTIAL_FIELD	6
-#define STV090x_WIDTH_Px_S1S2_SEQUENTIAL_FIELD	1
-
-#define STV090x_Px_DMDISTATE(__x)		(0xF416 - (__x - 1) * 0x200)
-#define STV090x_P1_DMDISTATE			STV090x_Px_DMDISTATE(1)
-#define STV090x_P2_DMDISTATE			STV090x_Px_DMDISTATE(2)
-#define STV090x_OFFST_Px_I2C_DEMOD_MODE_FIELD	0
-#define STV090x_WIDTH_Px_I2C_DEMOD_MODE_FIELD	5
-
-#define STV090x_Px_DMDTOM(__x)			(0xF417 - (__x - 1) * 0x200) /* check */
-#define STV090x_P1_DMDTOM			STV090x_Px_DMDTOM(1)
-#define STV090x_P2_DMDTOM			STV090x_Px_DMDTOM(2)
-
-#define STV090x_Px_DMDSTATE(__x)		(0xF41B - (__x - 1) * 0x200)
-#define STV090x_P1_DMDSTATE			STV090x_Px_DMDSTATE(1)
-#define STV090x_P2_DMDSTATE			STV090x_Px_DMDSTATE(2)
-#define STV090x_OFFST_Px_HEADER_MODE_FIELD	5
-#define STV090x_WIDTH_Px_HEADER_MODE_FIELD	2
-
-#define STV090x_Px_DMDFLYW(__x)			(0xF41C - (__x - 1) * 0x200)
-#define STV090x_P1_DMDFLYW			STV090x_Px_DMDFLYW(1)
-#define STV090x_P2_DMDFLYW			STV090x_Px_DMDFLYW(2)
-#define STV090x_OFFST_Px_I2C_IRQVAL_FIELD	4
-#define STV090x_WIDTH_Px_I2C_IRQVAL_FIELD	4
-#define STV090x_OFFST_Px_FLYWHEEL_CPT_FIELD	0
-#define STV090x_WIDTH_Px_FLYWHEEL_CPT_FIELD	4
-
-#define STV090x_Px_DSTATUS3(__x)		(0xF41D - (__x - 1) * 0x200)
-#define STV090x_P1_DSTATUS3			STV090x_Px_DSTATUS3(1)
-#define STV090x_P2_DSTATUS3			STV090x_Px_DSTATUS3(2)
-#define STV090x_OFFST_Px_DEMOD_CFGMODE_FIELD	5
-#define STV090x_WIDTH_Px_DEMOD_CFGMODE_FIELD	2
-
-#define STV090x_Px_DMDCFG3(__x)			(0xF41E - (__x - 1) * 0x200)
-#define STV090x_P1_DMDCFG3			STV090x_Px_DMDCFG3(1)
-#define STV090x_P2_DMDCFG3			STV090x_Px_DMDCFG3(2)
-#define STV090x_OFFST_Px_NOSTOP_FIFOFULL_FIELD	3
-#define STV090x_WIDTH_Px_NOSTOP_FIFOFULL_FIELD	1
-
-#define STV090x_Px_DMDCFG4(__x)			(0xf41f - (__x - 1) * 0x200)
-#define STV090x_P1_DMDCFG4			STV090x_Px_DMDCFG4(1)
-#define STV090x_P2_DMDCFG4			STV090x_Px_DMDCFG4(2)
-
-#define STV090x_Px_CORRELMANT(__x)		(0xF420 - (__x - 1) * 0x200)
-#define STV090x_P1_CORRELMANT			STV090x_Px_CORRELMANT(1)
-#define STV090x_P2_CORRELMANT			STV090x_Px_CORRELMANT(2)
-#define STV090x_OFFST_Px_CORREL_MANT_FIELD	0
-#define STV090x_WIDTH_Px_CORREL_MANT_FIELD	8
-
-#define STV090x_Px_CORRELABS(__x)		(0xF421 - (__x - 1) * 0x200)
-#define STV090x_P1_CORRELABS			STV090x_Px_CORRELABS(1)
-#define STV090x_P2_CORRELABS			STV090x_Px_CORRELABS(2)
-#define STV090x_OFFST_Px_CORREL_ABS_FIELD	0
-#define STV090x_WIDTH_Px_CORREL_ABS_FIELD	8
-
-#define STV090x_Px_CORRELEXP(__x)		(0xF422 - (__x - 1) * 0x200)
-#define STV090x_P1_CORRELEXP			STV090x_Px_CORRELEXP(1)
-#define STV090x_P2_CORRELEXP			STV090x_Px_CORRELEXP(2)
-#define STV090x_OFFST_Px_CORREL_ABSEXP_FIELD	4
-#define STV090x_WIDTH_Px_CORREL_ABSEXP_FIELD	4
-#define STV090x_OFFST_Px_CORREL_EXP_FIELD	0
-#define STV090x_WIDTH_Px_CORREL_EXP_FIELD	4
-
-#define STV090x_Px_PLHMODCOD(__x)		(0xF424 - (__x - 1) * 0x200)
-#define STV090x_P1_PLHMODCOD			STV090x_Px_PLHMODCOD(1)
-#define STV090x_P2_PLHMODCOD			STV090x_Px_PLHMODCOD(2)
-#define STV090x_OFFST_Px_SPECINV_DEMOD_FIELD	7
-#define STV090x_WIDTH_Px_SPECINV_DEMOD_FIELD	1
-#define STV090x_OFFST_Px_PLH_MODCOD_FIELD	2
-#define STV090x_WIDTH_Px_PLH_MODCOD_FIELD	5
-#define STV090x_OFFST_Px_PLH_TYPE_FIELD		0
-#define STV090x_WIDTH_Px_PLH_TYPE_FIELD		2
-
-#define STV090x_Px_AGCK32(__x)			(0xf42b - (__x - 1) * 0x200)
-#define STV090x_P1_AGCK32			STV090x_Px_AGCK32(1)
-#define STV090x_P2_AGCK32			STV090x_Px_AGCK32(2)
-
-#define STV090x_Px_AGC2O(__x)			(0xF42C - (__x - 1) * 0x200)
-#define STV090x_P1_AGC2O			STV090x_Px_AGC2O(1)
-#define STV090x_P2_AGC2O			STV090x_Px_AGC2O(2)
-
-#define STV090x_Px_AGC2REF(__x)			(0xF42D - (__x - 1) * 0x200)
-#define STV090x_P1_AGC2REF			STV090x_Px_AGC2REF(1)
-#define STV090x_P2_AGC2REF			STV090x_Px_AGC2REF(2)
-#define STV090x_OFFST_Px_AGC2_REF_FIELD		0
-#define STV090x_WIDTH_Px_AGC2_REF_FIELD		8
-
-#define STV090x_Px_AGC1ADJ(__x)			(0xF42E - (__x - 1) * 0x200)
-#define STV090x_P1_AGC1ADJ			STV090x_Px_AGC1ADJ(1)
-#define STV090x_P2_AGC1ADJ			STV090x_Px_AGC1ADJ(2)
-#define STV090x_OFFST_Px_AGC1_ADJUSTED_FIELD	0
-#define STV090x_WIDTH_Px_AGC1_ADJUSTED_FIELD	7
-
-#define STV090x_Px_AGC2Iy(__x, __y)		(0xF437 - (__x - 1) * 0x200 - __y * 0x1)
-#define STV090x_P1_AGC2I0			STV090x_Px_AGC2Iy(1, 0)
-#define STV090x_P1_AGC2I1			STV090x_Px_AGC2Iy(1, 1)
-#define STV090x_P2_AGC2I0			STV090x_Px_AGC2Iy(2, 0)
-#define STV090x_P2_AGC2I1			STV090x_Px_AGC2Iy(2, 1)
-#define STV090x_OFFST_Px_AGC2_INTEGRATOR_FIELD	0
-#define STV090x_WIDTH_Px_AGC2_INTEGRATOR_FIELD	8
-
-#define STV090x_Px_CARCFG(__x)			(0xF438 - (__x - 1) * 0x200)
-#define STV090x_P1_CARCFG			STV090x_Px_CARCFG(1)
-#define STV090x_P2_CARCFG			STV090x_Px_CARCFG(2)
-#define STV090x_OFFST_Px_EN_CAR2CENTER_FIELD	5
-#define STV090x_WIDTH_Px_EN_CAR2CENTER_FIELD	1
-#define STV090x_OFFST_Px_ROTATON_FIELD		2
-#define STV090x_WIDTH_Px_ROTATON_FIELD		1
-#define STV090x_OFFST_Px_PH_DET_ALGO_FIELD	0
-#define STV090x_WIDTH_Px_PH_DET_ALGO_FIELD	2
-
-#define STV090x_Px_ACLC(__x)			(0xF439 - (__x - 1) * 0x200)
-#define STV090x_P1_ACLC				STV090x_Px_ACLC(1)
-#define STV090x_P2_ACLC				STV090x_Px_ACLC(2)
-#define STV090x_OFFST_Px_CAR_ALPHA_MANT_FIELD	4
-#define STV090x_WIDTH_Px_CAR_ALPHA_MANT_FIELD	2
-#define STV090x_OFFST_Px_CAR_ALPHA_EXP_FIELD	0
-#define STV090x_WIDTH_Px_CAR_ALPHA_EXP_FIELD	4
-
-#define STV090x_Px_BCLC(__x)			(0xF43A - (__x - 1) * 0x200)
-#define STV090x_P1_BCLC				STV090x_Px_BCLC(1)
-#define STV090x_P2_BCLC				STV090x_Px_BCLC(2)
-#define STV090x_OFFST_Px_CAR_BETA_MANT_FIELD	4
-#define STV090x_WIDTH_Px_CAR_BETA_MANT_FIELD	2
-#define STV090x_OFFST_Px_CAR_BETA_EXP_FIELD	0
-#define STV090x_WIDTH_Px_CAR_BETA_EXP_FIELD	4
-
-#define STV090x_Px_CARFREQ(__x)			(0xF43D - (__x - 1) * 0x200)
-#define STV090x_P1_CARFREQ			STV090x_Px_CARFREQ(1)
-#define STV090x_P2_CARFREQ			STV090x_Px_CARFREQ(2)
-#define STV090x_OFFST_Px_KC_COARSE_EXP_FIELD	4
-#define STV090x_WIDTH_Px_KC_COARSE_EXP_FIELD	4
-#define STV090x_OFFST_Px_BETA_FREQ_FIELD	0
-#define STV090x_WIDTH_Px_BETA_FREQ_FIELD	4
-
-#define STV090x_Px_CARHDR(__x)			(0xF43E - (__x - 1) * 0x200)
-#define STV090x_P1_CARHDR			STV090x_Px_CARHDR(1)
-#define STV090x_P2_CARHDR			STV090x_Px_CARHDR(2)
-#define STV090x_OFFST_Px_FREQ_HDR_FIELD		0
-#define STV090x_WIDTH_Px_FREQ_HDR_FIELD		8
-
-#define STV090x_Px_LDT(__x)			(0xF43F - (__x - 1) * 0x200)
-#define STV090x_P1_LDT				STV090x_Px_LDT(1)
-#define STV090x_P2_LDT				STV090x_Px_LDT(2)
-#define STV090x_OFFST_Px_CARLOCK_THRES_FIELD	0
-#define STV090x_WIDTH_Px_CARLOCK_THRES_FIELD	8
-
-#define STV090x_Px_LDT2(__x)			(0xF440 - (__x - 1) * 0x200)
-#define STV090x_P1_LDT2				STV090x_Px_LDT2(1)
-#define STV090x_P2_LDT2				STV090x_Px_LDT2(2)
-#define STV090x_OFFST_Px_CARLOCK_THRES2_FIELD	0
-#define STV090x_WIDTH_Px_CARLOCK_THRES2_FIELD	8
-
-#define STV090x_Px_CFRICFG(__x)			(0xF441 - (__x - 1) * 0x200)
-#define STV090x_P1_CFRICFG			STV090x_Px_CFRICFG(1)
-#define STV090x_P2_CFRICFG			STV090x_Px_CFRICFG(2)
-#define STV090x_OFFST_Px_NEG_CFRSTEP_FIELD	0
-#define STV090x_WIDTH_Px_NEG_CFRSTEP_FIELD	1
-
-#define STV090x_Pn_CFRUPy(__x, __y)		(0xF443 - (__x - 1) * 0x200 - __y * 0x1)
-#define STV090x_P1_CFRUP0			STV090x_Pn_CFRUPy(1, 0)
-#define STV090x_P1_CFRUP1			STV090x_Pn_CFRUPy(1, 1)
-#define STV090x_P2_CFRUP0			STV090x_Pn_CFRUPy(2, 0)
-#define STV090x_P2_CFRUP1			STV090x_Pn_CFRUPy(2, 1)
-#define STV090x_OFFST_Px_CFR_UP_FIELD		0
-#define STV090x_WIDTH_Px_CFR_UP_FIELD		8
-
-#define STV090x_Pn_CFRLOWy(__x, __y)		(0xF447 - (__x - 1) * 0x200 - __y * 0x1)
-#define STV090x_P1_CFRLOW0			STV090x_Pn_CFRLOWy(1, 0)
-#define STV090x_P1_CFRLOW1			STV090x_Pn_CFRLOWy(1, 1)
-#define STV090x_P2_CFRLOW0			STV090x_Pn_CFRLOWy(2, 0)
-#define STV090x_P2_CFRLOW1			STV090x_Pn_CFRLOWy(2, 1)
-#define STV090x_OFFST_Px_CFR_LOW_FIELD		0
-#define STV090x_WIDTH_Px_CFR_LOW_FIELD		8
-
-#define STV090x_Pn_CFRINITy(__x, __y)		(0xF449 - (__x - 1) * 0x200 - __y * 0x1)
-#define STV090x_P1_CFRINIT0			STV090x_Pn_CFRINITy(1, 0)
-#define STV090x_P1_CFRINIT1			STV090x_Pn_CFRINITy(1, 1)
-#define STV090x_P2_CFRINIT0			STV090x_Pn_CFRINITy(2, 0)
-#define STV090x_P2_CFRINIT1			STV090x_Pn_CFRINITy(2, 1)
-#define STV090x_OFFST_Px_CFR_INIT_FIELD		0
-#define STV090x_WIDTH_Px_CFR_INIT_FIELD		8
-
-#define STV090x_Px_CFRINC1(__x)			(0xF44A - (__x - 1) * 0x200)
-#define STV090x_P1_CFRINC1			STV090x_Px_CFRINC1(1)
-#define STV090x_P2_CFRINC1			STV090x_Px_CFRINC1(2)
-#define STV090x_OFFST_Px_CFR_INC1_FIELD		0
-#define STV090x_WIDTH_Px_CFR_INC1_FIELD		7 /* check */
-
-#define STV090x_Px_CFRINC0(__x)			(0xF44B - (__x - 1) * 0x200)
-#define STV090x_P1_CFRINC0			STV090x_Px_CFRINC0(1)
-#define STV090x_P2_CFRINC0			STV090x_Px_CFRINC0(2)
-#define STV090x_OFFST_Px_CFR_INC0_FIELD		4 /* check */
-#define STV090x_WIDTH_Px_CFR_INC0_FIELD		4
-
-#define STV090x_Pn_CFRy(__x, __y)		(0xF44E - (__x - 1) * 0x200 - __y * 0x1)
-#define STV090x_P1_CFR0				STV090x_Pn_CFRy(1, 0)
-#define STV090x_P1_CFR1				STV090x_Pn_CFRy(1, 1)
-#define STV090x_P1_CFR2				STV090x_Pn_CFRy(1, 2)
-#define STV090x_P2_CFR0				STV090x_Pn_CFRy(2, 0)
-#define STV090x_P2_CFR1				STV090x_Pn_CFRy(2, 1)
-#define STV090x_P2_CFR2				STV090x_Pn_CFRy(2, 2)
-#define STV090x_OFFST_Px_CAR_FREQ_FIELD		0
-#define STV090x_WIDTH_Px_CAR_FREQ_FIELD		8
-
-#define STV090x_Px_LDI(__x)			(0xF44F - (__x - 1) * 0x200)
-#define STV090x_P1_LDI				STV090x_Px_LDI(1)
-#define STV090x_P2_LDI				STV090x_Px_LDI(2)
-#define STV090x_OFFST_Px_LOCK_DET_INTEGR_FIELD	0
-#define STV090x_WIDTH_Px_LOCK_DET_INTEGR_FIELD	8
-
-#define STV090x_Px_TMGCFG(__x)			(0xF450 - (__x - 1) * 0x200)
-#define STV090x_P1_TMGCFG			STV090x_Px_TMGCFG(1)
-#define STV090x_P2_TMGCFG			STV090x_Px_TMGCFG(2)
-#define STV090x_OFFST_Px_TMGLOCK_BETA_FIELD	6
-#define STV090x_WIDTH_Px_TMGLOCK_BETA_FIELD	2
-#define STV090x_OFFST_Px_DO_TIMING_FIELD	4
-#define STV090x_WIDTH_Px_DO_TIMING_FIELD	1
-#define STV090x_OFFST_Px_TMG_MINFREQ_FIELD	0
-#define STV090x_WIDTH_Px_TMG_MINFREQ_FIELD	2
-
-#define STV090x_Px_RTC(__x)			(0xF451 - (__x - 1) * 0x200)
-#define STV090x_P1_RTC				STV090x_Px_RTC(1)
-#define STV090x_P2_RTC				STV090x_Px_RTC(2)
-#define STV090x_OFFST_Px_TMGALPHA_EXP_FIELD	4
-#define STV090x_WIDTH_Px_TMGALPHA_EXP_FIELD	4
-#define STV090x_OFFST_Px_TMGBETA_EXP_FIELD	0
-#define STV090x_WIDTH_Px_TMGBETA_EXP_FIELD	4
-
-#define STV090x_Px_RTCS2(__x)			(0xF452 - (__x - 1) * 0x200)
-#define STV090x_P1_RTCS2			STV090x_Px_RTCS2(1)
-#define STV090x_P2_RTCS2			STV090x_Px_RTCS2(2)
-#define STV090x_OFFST_Px_TMGALPHAS2_EXP_FIELD	4
-#define STV090x_WIDTH_Px_TMGALPHAS2_EXP_FIELD	4
-#define STV090x_OFFST_Px_TMGBETAS2_EXP_FIELD	0
-#define STV090x_WIDTH_Px_TMGBETAS2_EXP_FIELD	4
-
-#define STV090x_Px_TMGTHRISE(__x)		(0xF453 - (__x - 1) * 0x200)
-#define STV090x_P1_TMGTHRISE			STV090x_Px_TMGTHRISE(1)
-#define STV090x_P2_TMGTHRISE			STV090x_Px_TMGTHRISE(2)
-#define STV090x_OFFST_Px_TMGLOCK_THRISE_FIELD	0
-#define STV090x_WIDTH_Px_TMGLOCK_THRISE_FIELD	8
-
-#define STV090x_Px_TMGTHFALL(__x)		(0xF454 - (__x - 1) * 0x200)
-#define STV090x_P1_TMGTHFALL			STV090x_Px_TMGTHFALL(1)
-#define STV090x_P2_TMGTHFALL			STV090x_Px_TMGTHFALL(2)
-#define STV090x_OFFST_Px_TMGLOCK_THFALL_FIELD	0
-#define STV090x_WIDTH_Px_TMGLOCK_THFALL_FIELD	8
-
-#define STV090x_Px_SFRUPRATIO(__x)		(0xF455 - (__x - 1) * 0x200)
-#define STV090x_P1_SFRUPRATIO			STV090x_Px_SFRUPRATIO(1)
-#define STV090x_P2_SFRUPRATIO			STV090x_Px_SFRUPRATIO(2)
-#define STV090x_OFFST_Px_SFR_UPRATIO_FIELD	0
-#define STV090x_WIDTH_Px_SFR_UPRATIO_FIELD	8
-
-#define STV090x_Px_SFRLOWRATIO(__x)		(0xF456 - (__x - 1) * 0x200)
-#define STV090x_P1_SFRLOWRATIO			STV090x_Px_SFRLOWRATIO(1)
-#define STV090x_P2_SFRLOWRATIO			STV090x_Px_SFRLOWRATIO(2)
-#define STV090x_OFFST_Px_SFR_LOWRATIO_FIELD	0
-#define STV090x_WIDTH_Px_SFR_LOWRATIO_FIELD	8
-
-#define STV090x_Px_KREFTMG(__x)			(0xF458 - (__x - 1) * 0x200)
-#define STV090x_P1_KREFTMG			STV090x_Px_KREFTMG(1)
-#define STV090x_P2_KREFTMG			STV090x_Px_KREFTMG(2)
-#define STV090x_OFFST_Px_KREF_TMG_FIELD		0
-#define STV090x_WIDTH_Px_KREF_TMG_FIELD		8
-
-#define STV090x_Px_SFRSTEP(__x)			(0xF459 - (__x - 1) * 0x200)
-#define STV090x_P1_SFRSTEP			STV090x_Px_SFRSTEP(1)
-#define STV090x_P2_SFRSTEP			STV090x_Px_SFRSTEP(2)
-#define STV090x_OFFST_Px_SFR_SCANSTEP_FIELD	4
-#define STV090x_WIDTH_Px_SFR_SCANSTEP_FIELD	4
-#define STV090x_OFFST_Px_SFR_CENTERSTEP_FIELD	0
-#define STV090x_WIDTH_Px_SFR_CENTERSTEP_FIELD	4
-
-#define STV090x_Px_TMGCFG2(__x)			(0xF45A - (__x - 1) * 0x200)
-#define STV090x_P1_TMGCFG2			STV090x_Px_TMGCFG2(1)
-#define STV090x_P2_TMGCFG2			STV090x_Px_TMGCFG2(2)
-#define STV090x_OFFST_Px_SFRRATIO_FINE_FIELD	0
-#define STV090x_WIDTH_Px_SFRRATIO_FINE_FIELD	1
-
-#define STV090x_Px_SFRINIT1(__x)		(0xF45E - (__x - 1) * 0x200)
-#define STV090x_P1_SFRINIT1			STV090x_Px_SFRINIT1(1)
-#define STV090x_P2_SFRINIT1			STV090x_Px_SFRINIT1(2)
-#define STV090x_OFFST_Px_SFR_INIT1_FIELD	0
-#define STV090x_WIDTH_Px_SFR_INIT1_FIELD	7
-
-#define STV090x_Px_SFRINIT0(__x)		(0xF45F - (__x - 1) * 0x200)
-#define STV090x_P1_SFRINIT0			STV090x_Px_SFRINIT0(1)
-#define STV090x_P2_SFRINIT0			STV090x_Px_SFRINIT0(2)
-#define STV090x_OFFST_Px_SFR_INIT0_FIELD	0
-#define STV090x_WIDTH_Px_SFR_INIT0_FIELD	8
-
-#define STV090x_Px_SFRUP1(__x)			(0xF460 - (__x - 1) * 0x200)
-#define STV090x_P1_SFRUP1			STV090x_Px_SFRUP1(1)
-#define STV090x_P2_SFRUP1			STV090x_Px_SFRUP1(2)
-#define STV090x_OFFST_Px_SYMB_FREQ_UP1_FIELD	0
-#define STV090x_WIDTH_Px_SYMB_FREQ_UP1_FIELD	7
-
-#define STV090x_Px_SFRUP0(__x)			(0xF461 - (__x - 1) * 0x200)
-#define STV090x_P1_SFRUP0			STV090x_Px_SFRUP0(1)
-#define STV090x_P2_SFRUP0			STV090x_Px_SFRUP0(2)
-#define STV090x_OFFST_Px_SYMB_FREQ_UP0_FIELD	0
-#define STV090x_WIDTH_Px_SYMB_FREQ_UP0_FIELD	8
-
-#define STV090x_Px_SFRLOW1(__x)			(0xF462 - (__x - 1) * 0x200)
-#define STV090x_P1_SFRLOW1			STV090x_Px_SFRLOW1(1)
-#define STV090x_P2_SFRLOW1			STV090x_Px_SFRLOW1(2)
-#define STV090x_OFFST_Px_SYMB_FREQ_LOW1_FIELD	0
-#define STV090x_WIDTH_Px_SYMB_FREQ_LOW1_FIELD	7
-
-#define STV090x_Px_SFRLOW0(__x)			(0xF463 - (__x - 1) * 0x200)
-#define STV090x_P1_SFRLOW0			STV090x_Px_SFRLOW0(1)
-#define STV090x_P2_SFRLOW0			STV090x_Px_SFRLOW0(2)
-#define STV090x_OFFST_Px_SYMB_FREQ_LOW0_FIELD	0
-#define STV090x_WIDTH_Px_SYMB_FREQ_LOW0_FIELD	8
-
-#define STV090x_Px_SFRy(__x, __y)		(0xF467 - (__x-1) * 0x200 - __y)
-#define STV090x_P1_SFR0				STV090x_Px_SFRy(1, 0)
-#define STV090x_P1_SFR1				STV090x_Px_SFRy(1, 1)
-#define STV090x_P1_SFR2				STV090x_Px_SFRy(1, 2)
-#define STV090x_P1_SFR3				STV090x_Px_SFRy(1, 3)
-#define STV090x_P2_SFR0				STV090x_Px_SFRy(2, 0)
-#define STV090x_P2_SFR1				STV090x_Px_SFRy(2, 1)
-#define STV090x_P2_SFR2				STV090x_Px_SFRy(2, 2)
-#define STV090x_P2_SFR3				STV090x_Px_SFRy(2, 3)
-#define STV090x_OFFST_Px_SYMB_FREQ_FIELD	0
-#define STV090x_WIDTH_Px_SYMB_FREQ_FIELD	8
-
-#define STV090x_Px_TMGREG2(__x)			(0xF468 - (__x - 1) * 0x200)
-#define STV090x_P1_TMGREG2			STV090x_Px_TMGREG2(1)
-#define STV090x_P2_TMGREG2			STV090x_Px_TMGREG2(2)
-#define STV090x_OFFST_Px_TMGREG_FIELD		0
-#define STV090x_WIDTH_Px_TMGREG_FIELD		8
-
-#define STV090x_Px_TMGREG1(__x)			(0xF469 - (__x - 1) * 0x200)
-#define STV090x_P1_TMGREG1			STV090x_Px_TMGREG1(1)
-#define STV090x_P2_TMGREG1			STV090x_Px_TMGREG1(2)
-#define STV090x_OFFST_Px_TMGREG_FIELD		0
-#define STV090x_WIDTH_Px_TMGREG_FIELD		8
-
-#define STV090x_Px_TMGREG0(__x)			(0xF46A - (__x - 1) * 0x200)
-#define STV090x_P1_TMGREG0			STV090x_Px_TMGREG0(1)
-#define STV090x_P2_TMGREG0			STV090x_Px_TMGREG0(2)
-#define STV090x_OFFST_Px_TMGREG_FIELD		0
-#define STV090x_WIDTH_Px_TMGREG_FIELD		8
-
-#define STV090x_Px_TMGLOCKy(__x, __y)		(0xF46C - (__x - 1) * 0x200 - __y * 0x1)
-#define STV090x_P1_TMGLOCK0			STV090x_Px_TMGLOCKy(1, 0)
-#define STV090x_P1_TMGLOCK1			STV090x_Px_TMGLOCKy(1, 1)
-#define STV090x_P2_TMGLOCK0			STV090x_Px_TMGLOCKy(2, 0)
-#define STV090x_P2_TMGLOCK1			STV090x_Px_TMGLOCKy(2, 1)
-#define STV090x_OFFST_Px_TMGLOCK_LEVEL_FIELD	0
-#define STV090x_WIDTH_Px_TMGLOCK_LEVEL_FIELD	8
-
-#define STV090x_Px_TMGOBS(__x)			(0xF46D - (__x - 1) * 0x200)
-#define STV090x_P1_TMGOBS			STV090x_Px_TMGOBS(1)
-#define STV090x_P2_TMGOBS			STV090x_Px_TMGOBS(2)
-#define STV090x_OFFST_Px_ROLLOFF_STATUS_FIELD	6
-#define STV090x_WIDTH_Px_ROLLOFF_STATUS_FIELD	2
-
-#define STV090x_Px_EQUALCFG(__x)		(0xF46F - (__x - 1) * 0x200)
-#define STV090x_P1_EQUALCFG			STV090x_Px_EQUALCFG(1)
-#define STV090x_P2_EQUALCFG			STV090x_Px_EQUALCFG(2)
-#define STV090x_OFFST_Px_EQUAL_ON_FIELD		6
-#define STV090x_WIDTH_Px_EQUAL_ON_FIELD		1
-#define STV090x_OFFST_Px_MU_EQUALDFE_FIELD	0
-#define STV090x_WIDTH_Px_MU_EQUALDFE_FIELD	3
-
-#define STV090x_Px_EQUAIy(__x, __y)	(0xf470 - (__x-1) * 0x200 + 2 * (__y-1))
-#define STV090x_P1_EQUAI1			STV090x_Px_EQUAIy(1, 1)
-#define STV090x_P1_EQUAI2			STV090x_Px_EQUAIy(1, 2)
-#define STV090x_P1_EQUAI3			STV090x_Px_EQUAIy(1, 3)
-#define STV090x_P1_EQUAI4			STV090x_Px_EQUAIy(1, 4)
-#define STV090x_P1_EQUAI5			STV090x_Px_EQUAIy(1, 5)
-#define STV090x_P1_EQUAI6			STV090x_Px_EQUAIy(1, 6)
-#define STV090x_P1_EQUAI7			STV090x_Px_EQUAIy(1, 7)
-#define STV090x_P1_EQUAI8			STV090x_Px_EQUAIy(1, 8)
-
-#define STV090x_P2_EQUAI1			STV090x_Px_EQUAIy(2, 1)
-#define STV090x_P2_EQUAI2			STV090x_Px_EQUAIy(2, 2)
-#define STV090x_P2_EQUAI3			STV090x_Px_EQUAIy(2, 3)
-#define STV090x_P2_EQUAI4			STV090x_Px_EQUAIy(2, 4)
-#define STV090x_P2_EQUAI5			STV090x_Px_EQUAIy(2, 5)
-#define STV090x_P2_EQUAI6			STV090x_Px_EQUAIy(2, 6)
-#define STV090x_P2_EQUAI7			STV090x_Px_EQUAIy(2, 7)
-#define STV090x_P2_EQUAI8			STV090x_Px_EQUAIy(2, 8)
-#define STV090x_OFFST_Px_EQUA_ACCIy_FIELD	0
-#define STV090x_WIDTH_Px_EQUA_ACCIy_FIELD	8
-
-#define STV090x_Px_EQUAQy(__x, __y)	(0xf471 - (__x-1) * 0x200 + 2 * (__y-1))
-#define STV090x_P1_EQUAQ1			STV090x_Px_EQUAQy(1, 1)
-#define STV090x_P1_EQUAQ2			STV090x_Px_EQUAQy(1, 2)
-#define STV090x_P1_EQUAQ3			STV090x_Px_EQUAQy(1, 3)
-#define STV090x_P1_EQUAQ4			STV090x_Px_EQUAQy(1, 4)
-#define STV090x_P1_EQUAQ5			STV090x_Px_EQUAQy(1, 5)
-#define STV090x_P1_EQUAQ6			STV090x_Px_EQUAQy(1, 6)
-#define STV090x_P1_EQUAQ7			STV090x_Px_EQUAQy(1, 7)
-#define STV090x_P1_EQUAQ8			STV090x_Px_EQUAQy(1, 8)
-
-#define STV090x_P2_EQUAQ1			STV090x_Px_EQUAQy(2, 1)
-#define STV090x_P2_EQUAQ2			STV090x_Px_EQUAQy(2, 2)
-#define STV090x_P2_EQUAQ3			STV090x_Px_EQUAQy(2, 3)
-#define STV090x_P2_EQUAQ4			STV090x_Px_EQUAQy(2, 4)
-#define STV090x_P2_EQUAQ5			STV090x_Px_EQUAQy(2, 5)
-#define STV090x_P2_EQUAQ6			STV090x_Px_EQUAQy(2, 6)
-#define STV090x_P2_EQUAQ7			STV090x_Px_EQUAQy(2, 7)
-#define STV090x_P2_EQUAQ8			STV090x_Px_EQUAQy(2, 8)
-#define STV090x_OFFST_Px_EQUA_ACCQy_FIELD	0
-#define STV090x_WIDTH_Px_EQUA_ACCQy_FIELD	8
-
-#define STV090x_Px_NNOSDATATy(__x, __y)		(0xf481 - (__x - 1) * 0x200 - __y * 0x1)
-#define STV090x_P1_NNOSDATAT0			STV090x_Px_NNOSDATATy(1, 0)
-#define STV090x_P1_NNOSDATAT1			STV090x_Px_NNOSDATATy(1, 1)
-#define STV090x_P2_NNOSDATAT0			STV090x_Px_NNOSDATATy(2, 0)
-#define STV090x_P2_NNOSDATAT1			STV090x_Px_NNOSDATATy(2, 1)
-#define STV090x_OFFST_Px_NOSDATAT_NORMED_FIELD	0
-#define STV090x_WIDTH_Px_NOSDATAT_NORMED_FIELD	8
-
-#define STV090x_Px_NNOSDATAy(__x, __y)		(0xf483 - (__x - 1) * 0x200 - __y * 0x1)
-#define STV090x_P1_NNOSDATA0			STV090x_Px_NNOSDATAy(1, 0)
-#define STV090x_P1_NNOSDATA1			STV090x_Px_NNOSDATAy(1, 1)
-#define STV090x_P2_NNOSDATA0			STV090x_Px_NNOSDATAy(2, 0)
-#define STV090x_P2_NNOSDATA1			STV090x_Px_NNOSDATAy(2, 1)
-#define STV090x_OFFST_Px_NOSDATA_NORMED_FIELD	0
-#define STV090x_WIDTH_Px_NOSDATA_NORMED_FIELD	8
-
-#define STV090x_Px_NNOSPLHTy(__x, __y)		(0xf485 - (__x - 1) * 0x200 - __y * 0x1)
-#define STV090x_P1_NNOSPLHT0			STV090x_Px_NNOSPLHTy(1, 0)
-#define STV090x_P1_NNOSPLHT1			STV090x_Px_NNOSPLHTy(1, 1)
-#define STV090x_P2_NNOSPLHT0			STV090x_Px_NNOSPLHTy(2, 0)
-#define STV090x_P2_NNOSPLHT1			STV090x_Px_NNOSPLHTy(2, 1)
-#define STV090x_OFFST_Px_NOSPLHT_NORMED_FIELD	0
-#define STV090x_WIDTH_Px_NOSPLHT_NORMED_FIELD	8
-
-#define STV090x_Px_NNOSPLHy(__x, __y)		(0xf487 - (__x - 1) * 0x200 - __y * 0x1)
-#define STV090x_P1_NNOSPLH0			STV090x_Px_NNOSPLHy(1, 0)
-#define STV090x_P1_NNOSPLH1			STV090x_Px_NNOSPLHy(1, 1)
-#define STV090x_P2_NNOSPLH0			STV090x_Px_NNOSPLHy(2, 0)
-#define STV090x_P2_NNOSPLH1			STV090x_Px_NNOSPLHy(2, 1)
-#define STV090x_OFFST_Px_NOSPLH_NORMED_FIELD	0
-#define STV090x_WIDTH_Px_NOSPLH_NORMED_FIELD	8
-
-#define STV090x_Px_NOSDATATy(__x, __y)			(0xf489 - (__x - 1) * 0x200 - __y * 0x1)
-#define STV090x_P1_NOSDATAT0				STV090x_Px_NOSDATATy(1, 0)
-#define STV090x_P1_NOSDATAT1				STV090x_Px_NOSDATATy(1, 1)
-#define STV090x_P2_NOSDATAT0				STV090x_Px_NOSDATATy(2, 0)
-#define STV090x_P2_NOSDATAT1				STV090x_Px_NOSDATATy(2, 1)
-#define STV090x_OFFST_Px_NOSDATAT_UNNORMED_FIELD	0
-#define STV090x_WIDTH_Px_NOSDATAT_UNNORMED_FIELD	8
-
-#define STV090x_Px_NOSDATAy(__x, __y)		(0xf48b - (__x - 1) * 0x200 - __y * 0x1)
-#define STV090x_P1_NOSDATA0			STV090x_Px_NOSDATAy(1, 0)
-#define STV090x_P1_NOSDATA1			STV090x_Px_NOSDATAy(1, 1)
-#define STV090x_P2_NOSDATA0			STV090x_Px_NOSDATAy(2, 0)
-#define STV090x_P2_NOSDATA1			STV090x_Px_NOSDATAy(2, 1)
-#define STV090x_OFFST_Px_NOSDATA_UNNORMED_FIELD	0
-#define STV090x_WIDTH_Px_NOSDATA_UNNORMED_FIELD	8
-
-#define STV090x_Px_NOSPLHTy(__x, __y)		(0xf48d - (__x - 1) * 0x200 - __y * 0x1)
-#define STV090x_P1_NOSPLHT0			STV090x_Px_NOSPLHTy(1, 0)
-#define STV090x_P1_NOSPLHT1			STV090x_Px_NOSPLHTy(1, 1)
-#define STV090x_P2_NOSPLHT0			STV090x_Px_NOSPLHTy(2, 0)
-#define STV090x_P2_NOSPLHT1			STV090x_Px_NOSPLHTy(2, 1)
-#define STV090x_OFFST_Px_NOSPLHT_UNNORMED_FIELD	0
-#define STV090x_WIDTH_Px_NOSPLHT_UNNORMED_FIELD	8
-
-#define STV090x_Px_NOSPLHy(__x, __y)		(0xf48f - (__x - 1) * 0x200 - __y * 0x1)
-#define STV090x_P1_NOSPLH0			STV090x_Px_NOSPLHy(1, 0)
-#define STV090x_P1_NOSPLH1			STV090x_Px_NOSPLHy(1, 1)
-#define STV090x_P2_NOSPLH0			STV090x_Px_NOSPLHy(2, 0)
-#define STV090x_P2_NOSPLH1			STV090x_Px_NOSPLHy(2, 1)
-#define STV090x_OFFST_Px_NOSPLH_UNNORMED_FIELD	0
-#define STV090x_WIDTH_Px_NOSPLH_UNNORMED_FIELD	8
-
-#define STV090x_Px_CAR2CFG(__x)			(0xf490 - (__x - 1) * 0x200)
-#define STV090x_P1_CAR2CFG			STV090x_Px_CAR2CFG(1)
-#define STV090x_P2_CAR2CFG			STV090x_Px_CAR2CFG(2)
-#define STV090x_OFFST_Px_PN4_SELECT_FIELD	6
-#define STV090x_WIDTH_Px_PN4_SELECT_FIELD	1
-#define STV090x_OFFST_Px_CFR2_STOPDVBS1_FIELD	5
-#define STV090x_WIDTH_Px_CFR2_STOPDVBS1_FIELD	1
-#define STV090x_OFFST_Px_ROTA2ON_FIELD		2
-#define STV090x_WIDTH_Px_ROTA2ON_FIELD		1
-#define STV090x_OFFST_Px_PH_DET_ALGO2_FIELD	0
-#define STV090x_WIDTH_Px_PH_DET_ALGO2_FIELD	2
-
-#define STV090x_Px_ACLC2(__x)			(0xf491 - (__x - 1) * 0x200)
-#define STV090x_P1_ACLC2			STV090x_Px_ACLC2(1)
-#define STV090x_P2_ACLC2			STV090x_Px_ACLC2(2)
-#define STV090x_OFFST_Px_CAR2_ALPHA_MANT_FIELD	4
-#define STV090x_WIDTH_Px_CAR2_ALPHA_MANT_FIELD	2
-#define STV090x_OFFST_Px_CAR2_ALPHA_EXP_FIELD	0
-#define STV090x_WIDTH_Px_CAR2_ALPHA_EXP_FIELD	4
-
-#define STV090x_Px_BCLC2(__x)			(0xf492 - (__x - 1) * 0x200)
-#define STV090x_P1_BCLC2			STV090x_Px_BCLC2(1)
-#define STV090x_P2_BCLC2			STV090x_Px_BCLC2(2)
-#define STV090x_OFFST_Px_CAR2_BETA_MANT_FIELD	4
-#define STV090x_WIDTH_Px_CAR2_BETA_MANT_FIELD	2
-#define STV090x_OFFST_Px_CAR2_BETA_EXP_FIELD	0
-#define STV090x_WIDTH_Px_CAR2_BETA_EXP_FIELD	4
-
-#define STV090x_Px_ACLC2S2Q(__x)		(0xf497 - (__x - 1) * 0x200)
-#define STV090x_P1_ACLC2S2Q			STV090x_Px_ACLC2S2Q(1)
-#define STV090x_P2_ACLC2S2Q			STV090x_Px_ACLC2S2Q(2)
-#define STV090x_OFFST_Px_ENAB_SPSKSYMB_FIELD	7
-#define STV090x_WIDTH_Px_ENAB_SPSKSYMB_FIELD	1
-#define STV090x_OFFST_Px_CAR2S2_Q_ALPH_M_FIELD	4
-#define STV090x_WIDTH_Px_CAR2S2_Q_ALPH_M_FIELD	2
-#define STV090x_OFFST_Px_CAR2S2_Q_ALPH_E_FIELD	0
-#define STV090x_WIDTH_Px_CAR2S2_Q_ALPH_E_FIELD	4
-
-#define STV090x_Px_ACLC2S28(__x)		(0xf498 - (__x - 1) * 0x200)
-#define STV090x_P1_ACLC2S28			STV090x_Px_ACLC2S28(1)
-#define STV090x_P2_ACLC2S28			STV090x_Px_ACLC2S28(2)
-#define STV090x_OFFST_Px_CAR2S2_8_ALPH_M_FIELD	4
-#define STV090x_WIDTH_Px_CAR2S2_8_ALPH_M_FIELD	2
-#define STV090x_OFFST_Px_CAR2S2_8_ALPH_E_FIELD	0
-#define STV090x_WIDTH_Px_CAR2S2_8_ALPH_E_FIELD	4
-
-#define STV090x_Px_ACLC2S216A(__x)		(0xf499 - (__x - 1) * 0x200)
-#define STV090x_P1_ACLC2S216A			STV090x_Px_ACLC2S216A(1)
-#define STV090x_P2_ACLC2S216A			STV090x_Px_ACLC2S216A(2)
-#define STV090x_OFFST_Px_CAR2S2_16A_ALPH_M_FIELD	4
-#define STV090x_WIDTH_Px_CAR2S2_16A_ALPH_M_FIELD	2
-#define STV090x_OFFST_Px_CAR2S2_16A_ALPH_E_FIELD	0
-#define STV090x_WIDTH_Px_CAR2S2_16A_ALPH_E_FIELD	4
-
-#define STV090x_Px_ACLC2S232A(__x)		(0xf49A - (__x - 1) * 0x200)
-#define STV090x_P1_ACLC2S232A			STV090x_Px_ACLC2S232A(1)
-#define STV090x_P2_ACLC2S232A			STV090x_Px_ACLC2S232A(2)
-#define STV090x_OFFST_Px_CAR2S2_32A_ALPH_M_FIELD	4
-#define STV090x_WIDTH_Px_CAR2S2_32A_ALPH_M_FIELD	2
-#define STV090x_OFFST_Px_CAR2S2_32A_ALPH_E_FIELD	0
-#define STV090x_WIDTH_Px_CAR2S2_32A_ALPH_E_FIELD	4
-
-#define STV090x_Px_BCLC2S2Q(__x)		(0xf49c - (__x - 1) * 0x200)
-#define STV090x_P1_BCLC2S2Q			STV090x_Px_BCLC2S2Q(1)
-#define STV090x_P2_BCLC2S2Q			STV090x_Px_BCLC2S2Q(2)
-#define STV090x_OFFST_Px_CAR2S2_Q_BETA_M_FIELD	4
-#define STV090x_WIDTH_Px_CAR2S2_Q_BETA_M_FIELD	2
-#define STV090x_OFFST_Px_CAR2S2_Q_BETA_E_FIELD	0
-#define STV090x_WIDTH_Px_CAR2S2_Q_BETA_E_FIELD	4
-
-#define STV090x_Px_BCLC2S28(__x)		(0xf49d - (__x - 1) * 0x200)
-#define STV090x_P1_BCLC2S28			STV090x_Px_BCLC2S28(1)
-#define STV090x_P2_BCLC2S28			STV090x_Px_BCLC2S28(2)
-#define STV090x_OFFST_Px_CAR2S2_8_BETA_M_FIELD	4
-#define STV090x_WIDTH_Px_CAR2S2_8_BETA_M_FIELD	2
-#define STV090x_OFFST_Px_CAR2S2_8_BETA_E_FIELD	0
-#define STV090x_WIDTH_Px_CAR2S2_8_BETA_E_FIELD	4
-
-#define STV090x_Px_BCLC2S216A(__x)		(0xf49e - (__x - 1) * 0x200)
-#define STV090x_P1_BCLC2S216A			STV090x_Px_BCLC2S216A(1)
-#define STV090x_P2_BCLC2S216A			STV090x_Px_BCLC2S216A(2)
-#define STV090x_OFFST_Px_CAR2S2_16A_BETA_M_FIELD	4
-#define STV090x_WIDTH_Px_CAR2S2_16A_BETA_M_FIELD	2
-#define STV090x_OFFST_Px_CAR2S2_16A_BETA_E_FIELD	0
-#define STV090x_WIDTH_Px_CAR2S2_16A_BETA_E_FIELD	4
-
-#define STV090x_Px_BCLC2S232A(__x)		(0xf49f - (__x - 1) * 0x200)
-#define STV090x_P1_BCLC2S232A			STV090x_Px_BCLC2S232A(1)
-#define STV090x_P2_BCLC2S232A			STV090x_Px_BCLC2S232A(2)
-#define STV090x_OFFST_Px_CAR2S2_32A_BETA_M_FIELD	4
-#define STV090x_WIDTH_Px_CAR2S2_32A_BETA_M_FIELD	2
-#define STV090x_OFFST_Px_CAR2S2_32A_BETA_E_FIELD	0
-#define STV090x_WIDTH_Px_CAR2S2_32A_BETA_E_FIELD	4
-
-#define STV090x_Px_PLROOT2(__x)			(0xf4ac - (__x - 1) * 0x200)
-#define STV090x_P1_PLROOT2			STV090x_Px_PLROOT2(1)
-#define STV090x_P2_PLROOT2			STV090x_Px_PLROOT2(2)
-#define STV090x_OFFST_Px_PLSCRAMB_MODE_FIELD	2
-#define STV090x_WIDTH_Px_PLSCRAMB_MODE_FIELD	2
-#define STV090x_OFFST_Px_PLSCRAMB_ROOT_FIELD	0
-#define STV090x_WIDTH_Px_PLSCRAMB_ROOT_FIELD	2
-
-#define STV090x_Px_PLROOT1(__x)			(0xf4ad - (__x - 1) * 0x200)
-#define STV090x_P1_PLROOT1			STV090x_Px_PLROOT1(1)
-#define STV090x_P2_PLROOT1			STV090x_Px_PLROOT1(2)
-#define STV090x_OFFST_Px_PLSCRAMB_ROOT1_FIELD	0
-#define STV090x_WIDTH_Px_PLSCRAMB_ROOT1_FIELD	8
-
-#define STV090x_Px_PLROOT0(__x)			(0xf4ae - (__x - 1) * 0x200)
-#define STV090x_P1_PLROOT0			STV090x_Px_PLROOT0(1)
-#define STV090x_P2_PLROOT0			STV090x_Px_PLROOT0(2)
-#define STV090x_OFFST_Px_PLSCRAMB_ROOT0_FIELD	0
-#define STV090x_WIDTH_Px_PLSCRAMB_ROOT0_FIELD	8
-
-#define STV090x_Px_MODCODLST0(__x)		(0xf4b0 - (__x - 1) * 0x200) /* check */
-#define STV090x_P1_MODCODLST0			STV090x_Px_MODCODLST0(1)
-#define STV090x_P2_MODCODLST0			STV090x_Px_MODCODLST0(2)
-
-#define STV090x_Px_MODCODLST1(__x)		(0xf4b1 - (__x - 1) * 0x200)
-#define STV090x_P1_MODCODLST1			STV090x_Px_MODCODLST1(1)
-#define STV090x_P2_MODCODLST1			STV090x_Px_MODCODLST1(2)
-#define STV090x_OFFST_Px_DIS_MODCOD29_FIELD	4
-#define STV090x_WIDTH_Px_DIS_MODCOD29_FIELD	4
-#define STV090x_OFFST_Px_DIS_32PSK_9_10_FIELD	0
-#define STV090x_WIDTH_Px_DIS_32PSK_9_10_FIELD	4
-
-#define STV090x_Px_MODCODLST2(__x)		(0xf4b2 - (__x - 1) * 0x200)
-#define STV090x_P1_MODCODLST2			STV090x_Px_MODCODLST2(1)
-#define STV090x_P2_MODCODLST2			STV090x_Px_MODCODLST2(2)
-#define STV090x_OFFST_Px_DIS_32PSK_8_9_FIELD	4
-#define STV090x_WIDTH_Px_DIS_32PSK_8_9_FIELD	4
-#define STV090x_OFFST_Px_DIS_32PSK_5_6_FIELD	0
-#define STV090x_WIDTH_Px_DIS_32PSK_5_6_FIELD	4
-
-#define STV090x_Px_MODCODLST3(__x)		(0xf4b3 - (__x - 1) * 0x200)
-#define STV090x_P1_MODCODLST3			STV090x_Px_MODCODLST3(1)
-#define STV090x_P2_MODCODLST3			STV090x_Px_MODCODLST3(2)
-#define STV090x_OFFST_Px_DIS_32PSK_4_5_FIELD	4
-#define STV090x_WIDTH_Px_DIS_32PSK_4_5_FIELD	4
-#define STV090x_OFFST_Px_DIS_32PSK_3_4_FIELD	0
-#define STV090x_WIDTH_Px_DIS_32PSK_3_4_FIELD	4
-
-#define STV090x_Px_MODCODLST4(__x)		(0xf4b4 - (__x - 1) * 0x200)
-#define STV090x_P1_MODCODLST4			STV090x_Px_MODCODLST4(1)
-#define STV090x_P2_MODCODLST4			STV090x_Px_MODCODLST4(2)
-#define STV090x_OFFST_Px_DIS_16PSK_9_10_FIELD	4
-#define STV090x_WIDTH_Px_DIS_16PSK_9_10_FIELD	4
-#define STV090x_OFFST_Px_DIS_16PSK_8_9_FIELD	0
-#define STV090x_WIDTH_Px_DIS_16PSK_8_9_FIELD	4
-
-#define STV090x_Px_MODCODLST5(__x)		(0xf4b5 - (__x - 1) * 0x200)
-#define STV090x_P1_MODCODLST5			STV090x_Px_MODCODLST5(1)
-#define STV090x_P2_MODCODLST5			STV090x_Px_MODCODLST5(2)
-#define STV090x_OFFST_Px_DIS_16PSK_5_6_FIELD	4
-#define STV090x_WIDTH_Px_DIS_16PSK_5_6_FIELD	4
-#define STV090x_OFFST_Px_DIS_16PSK_4_5_FIELD	0
-#define STV090x_WIDTH_Px_DIS_16PSK_4_5_FIELD	4
-
-#define STV090x_Px_MODCODLST6(__x)		(0xf4b6 - (__x - 1) * 0x200)
-#define STV090x_P1_MODCODLST6			STV090x_Px_MODCODLST6(1)
-#define STV090x_P2_MODCODLST6			STV090x_Px_MODCODLST6(2)
-#define STV090x_OFFST_Px_DIS_16PSK_3_4_FIELD	4
-#define STV090x_WIDTH_Px_DIS_16PSK_3_4_FIELD	4
-#define STV090x_OFFST_Px_DIS_16PSK_2_3_FIELD	0
-#define STV090x_WIDTH_Px_DIS_16PSK_2_3_FIELD	4
-
-#define STV090x_Px_MODCODLST7(__x)		(0xf4b7 - (__x - 1) * 0x200)
-#define STV090x_P1_MODCODLST7			STV090x_Px_MODCODLST7(1)
-#define STV090x_P2_MODCODLST7			STV090x_Px_MODCODLST7(2)
-#define STV090x_OFFST_Px_DIS_8P_9_10_FIELD	4
-#define STV090x_WIDTH_Px_DIS_8P_9_10_FIELD	4
-#define STV090x_OFFST_Px_DIS_8P_8_9_FIELD	0
-#define STV090x_WIDTH_Px_DIS_8P_8_9_FIELD	4
-
-#define STV090x_Px_MODCODLST8(__x)		(0xf4b8 - (__x - 1) * 0x200)
-#define STV090x_P1_MODCODLST8			STV090x_Px_MODCODLST8(1)
-#define STV090x_P2_MODCODLST8			STV090x_Px_MODCODLST8(2)
-#define STV090x_OFFST_Px_DIS_8P_5_6_FIELD	4
-#define STV090x_WIDTH_Px_DIS_8P_5_6_FIELD	4
-#define STV090x_OFFST_Px_DIS_8P_3_4_FIELD	0
-#define STV090x_WIDTH_Px_DIS_8P_3_4_FIELD	4
-
-#define STV090x_Px_MODCODLST9(__x)		(0xf4b9 - (__x - 1) * 0x200)
-#define STV090x_P1_MODCODLST9			STV090x_Px_MODCODLST9(1)
-#define STV090x_P2_MODCODLST9			STV090x_Px_MODCODLST9(2)
-#define STV090x_OFFST_Px_DIS_8P_2_3_FIELD	4
-#define STV090x_WIDTH_Px_DIS_8P_2_3_FIELD	4
-#define STV090x_OFFST_Px_DIS_8P_3_5_FIELD	0
-#define STV090x_WIDTH_Px_DIS_8P_3_5_FIELD	4
-
-#define STV090x_Px_MODCODLSTA(__x)		(0xf4ba - (__x - 1) * 0x200)
-#define STV090x_P1_MODCODLSTA			STV090x_Px_MODCODLSTA(1)
-#define STV090x_P2_MODCODLSTA			STV090x_Px_MODCODLSTA(2)
-#define STV090x_OFFST_Px_DIS_QP_9_10_FIELD	4
-#define STV090x_WIDTH_Px_DIS_QP_9_10_FIELD	4
-#define STV090x_OFFST_Px_DIS_QP_8_9_FIELD	0
-#define STV090x_WIDTH_Px_DIS_QP_8_9_FIELD	4
-
-#define STV090x_Px_MODCODLSTB(__x)		(0xf4bb - (__x - 1) * 0x200)
-#define STV090x_P1_MODCODLSTB			STV090x_Px_MODCODLSTB(1)
-#define STV090x_P2_MODCODLSTB			STV090x_Px_MODCODLSTB(2)
-#define STV090x_OFFST_Px_DIS_QP_5_6_FIELD	4
-#define STV090x_WIDTH_Px_DIS_QP_5_6_FIELD	4
-#define STV090x_OFFST_Px_DIS_QP_4_5_FIELD	0
-#define STV090x_WIDTH_Px_DIS_QP_4_5_FIELD	4
-
-#define STV090x_Px_MODCODLSTC(__x)		(0xf4bc - (__x - 1) * 0x200)
-#define STV090x_P1_MODCODLSTC			STV090x_Px_MODCODLSTC(1)
-#define STV090x_P2_MODCODLSTC			STV090x_Px_MODCODLSTC(2)
-#define STV090x_OFFST_Px_DIS_QP_3_4_FIELD	4
-#define STV090x_WIDTH_Px_DIS_QP_3_4_FIELD	4
-#define STV090x_OFFST_Px_DIS_QP_2_3_FIELD	0
-#define STV090x_WIDTH_Px_DIS_QP_2_3_FIELD	4
-
-#define STV090x_Px_MODCODLSTD(__x)		(0xf4bd - (__x - 1) * 0x200)
-#define STV090x_P1_MODCODLSTD			STV090x_Px_MODCODLSTD(1)
-#define STV090x_P2_MODCODLSTD			STV090x_Px_MODCODLSTD(2)
-#define STV090x_OFFST_Px_DIS_QP_3_5_FIELD	4
-#define STV090x_WIDTH_Px_DIS_QP_3_5_FIELD	4
-#define STV090x_OFFST_Px_DIS_QP_1_2_FIELD	0
-#define STV090x_WIDTH_Px_DIS_QP_1_2_FIELD	4
-
-#define STV090x_Px_MODCODLSTE(__x)		(0xf4be - (__x - 1) * 0x200)
-#define STV090x_P1_MODCODLSTE			STV090x_Px_MODCODLSTE(1)
-#define STV090x_P2_MODCODLSTE			STV090x_Px_MODCODLSTE(2)
-#define STV090x_OFFST_Px_DIS_QP_2_5_FIELD	4
-#define STV090x_WIDTH_Px_DIS_QP_2_5_FIELD	4
-#define STV090x_OFFST_Px_DIS_QP_1_3_FIELD	0
-#define STV090x_WIDTH_Px_DIS_QP_1_3_FIELD	4
-
-#define STV090x_Px_MODCODLSTF(__x)		(0xf4bf - (__x - 1) * 0x200)
-#define STV090x_P1_MODCODLSTF			STV090x_Px_MODCODLSTF(1)
-#define STV090x_P2_MODCODLSTF			STV090x_Px_MODCODLSTF(2)
-#define STV090x_OFFST_Px_DIS_QP_1_4_FIELD	4
-#define STV090x_WIDTH_Px_DIS_QP_1_4_FIELD	4
-
-#define STV090x_Px_GAUSSR0(__x)			(0xf4c0 - (__x - 1) * 0x200)
-#define STV090x_P1_GAUSSR0			STV090x_Px_GAUSSR0(1)
-#define STV090x_P2_GAUSSR0			STV090x_Px_GAUSSR0(2)
-#define STV090x_OFFST_Px_EN_CCIMODE_FIELD	7
-#define STV090x_WIDTH_Px_EN_CCIMODE_FIELD	1
-#define STV090x_OFFST_Px_R0_GAUSSIEN_FIELD	0
-#define STV090x_WIDTH_Px_R0_GAUSSIEN_FIELD	7
-
-#define STV090x_Px_CCIR0(__x)			(0xf4c1 - (__x - 1) * 0x200)
-#define STV090x_P1_CCIR0			STV090x_Px_CCIR0(1)
-#define STV090x_P2_CCIR0			STV090x_Px_CCIR0(2)
-#define STV090x_OFFST_Px_CCIDETECT_PLH_FIELD	7
-#define STV090x_WIDTH_Px_CCIDETECT_PLH_FIELD	1
-#define STV090x_OFFST_Px_R0_CCI_FIELD		0
-#define STV090x_WIDTH_Px_R0_CCI_FIELD		7
-
-#define STV090x_Px_CCIQUANT(__x)		(0xf4c2 - (__x - 1) * 0x200)
-#define STV090x_P1_CCIQUANT			STV090x_Px_CCIQUANT(1)
-#define STV090x_P2_CCIQUANT			STV090x_Px_CCIQUANT(2)
-#define STV090x_OFFST_Px_CCI_BETA_FIELD		5
-#define STV090x_WIDTH_Px_CCI_BETA_FIELD		3
-#define STV090x_OFFST_Px_CCI_QUANT_FIELD	0
-#define STV090x_WIDTH_Px_CCI_QUANT_FIELD	5
-
-#define STV090x_Px_CCITHRESH(__x)		(0xf4c3 - (__x - 1) * 0x200)
-#define STV090x_P1_CCITHRESH			STV090x_Px_CCITHRESH(1)
-#define STV090x_P2_CCITHRESH			STV090x_Px_CCITHRESH(2)
-#define STV090x_OFFST_Px_CCI_THRESHOLD_FIELD	0
-#define STV090x_WIDTH_Px_CCI_THRESHOLD_FIELD	8
-
-#define STV090x_Px_CCIACC(__x)			(0xf4c4 - (__x - 1) * 0x200)
-#define STV090x_P1_CCIACC			STV090x_Px_CCIACC(1)
-#define STV090x_P2_CCIACC			STV090x_Px_CCIACC(2)
-#define STV090x_OFFST_Px_CCI_VALUE_FIELD	0
-#define STV090x_WIDTH_Px_CCI_VALUE_FIELD	8
-
-#define STV090x_Px_DMDRESCFG(__x)		(0xF4C6 - (__x - 1) * 0x200)
-#define STV090x_P1_DMDRESCFG			STV090x_Px_DMDRESCFG(1)
-#define STV090x_P2_DMDRESCFG			STV090x_Px_DMDRESCFG(2)
-#define STV090x_OFFST_Px_DMDRES_RESET_FIELD	7
-#define STV090x_WIDTH_Px_DMDRES_RESET_FIELD	1
-
-#define STV090x_Px_DMDRESADR(__x)		(0xF4C7 - (__x - 1) * 0x200)
-#define STV090x_P1_DMDRESADR			STV090x_Px_DMDRESADR(1)
-#define STV090x_P2_DMDRESADR			STV090x_Px_DMDRESADR(2)
-#define STV090x_OFFST_Px_DMDRES_RESNBR_FIELD	0
-#define STV090x_WIDTH_Px_DMDRES_RESNBR_FIELD	4
-
-#define STV090x_Px_DMDRESDATAy(__x, __y)	(0xF4C8 - (__x - 1) * 0x200 + (7 - __y))
-#define STV090x_P1_DMDRESDATA0			STV090x_Px_DMDRESDATAy(1, 0)
-#define STV090x_P1_DMDRESDATA1			STV090x_Px_DMDRESDATAy(1, 1)
-#define STV090x_P1_DMDRESDATA2			STV090x_Px_DMDRESDATAy(1, 2)
-#define STV090x_P1_DMDRESDATA3			STV090x_Px_DMDRESDATAy(1, 3)
-#define STV090x_P1_DMDRESDATA4			STV090x_Px_DMDRESDATAy(1, 4)
-#define STV090x_P1_DMDRESDATA5			STV090x_Px_DMDRESDATAy(1, 5)
-#define STV090x_P1_DMDRESDATA6			STV090x_Px_DMDRESDATAy(1, 6)
-#define STV090x_P1_DMDRESDATA7			STV090x_Px_DMDRESDATAy(1, 7)
-#define STV090x_P2_DMDRESDATA0			STV090x_Px_DMDRESDATAy(2, 0)
-#define STV090x_P2_DMDRESDATA1			STV090x_Px_DMDRESDATAy(2, 1)
-#define STV090x_P2_DMDRESDATA2			STV090x_Px_DMDRESDATAy(2, 2)
-#define STV090x_P2_DMDRESDATA3			STV090x_Px_DMDRESDATAy(2, 3)
-#define STV090x_P2_DMDRESDATA4			STV090x_Px_DMDRESDATAy(2, 4)
-#define STV090x_P2_DMDRESDATA5			STV090x_Px_DMDRESDATAy(2, 5)
-#define STV090x_P2_DMDRESDATA6			STV090x_Px_DMDRESDATAy(2, 6)
-#define STV090x_P2_DMDRESDATA7			STV090x_Px_DMDRESDATAy(2, 7)
-#define STV090x_OFFST_Px_DMDRES_DATA_FIELD	0
-#define STV090x_WIDTH_Px_DMDRES_DATA_FIELD	8
-
-#define STV090x_Px_FFEIy(__x, __y)		(0xf4d0 - (__x - 1) * 0x200 + 0x2 * (__y - 1))
-#define STV090x_P1_FFEI1			STV090x_Px_FFEIy(1, 1)
-#define STV090x_P1_FFEI2			STV090x_Px_FFEIy(1, 2)
-#define STV090x_P1_FFEI3			STV090x_Px_FFEIy(1, 3)
-#define STV090x_P1_FFEI4			STV090x_Px_FFEIy(1, 4)
-#define STV090x_P2_FFEI1			STV090x_Px_FFEIy(2, 1)
-#define STV090x_P2_FFEI2			STV090x_Px_FFEIy(2, 2)
-#define STV090x_P2_FFEI3			STV090x_Px_FFEIy(2, 3)
-#define STV090x_P2_FFEI4			STV090x_Px_FFEIy(2, 4)
-#define STV090x_OFFST_Px_FFE_ACCIy_FIELD	0
-#define STV090x_WIDTH_Px_FFE_ACCIy_FIELD	8
-
-#define STV090x_Px_FFEQy(__x, __y)		(0xf4d1 - (__x - 1) * 0x200 + 0x2 * (__y - 1))
-#define STV090x_P1_FFEQ1			STV090x_Px_FFEQy(1, 1)
-#define STV090x_P1_FFEQ2			STV090x_Px_FFEQy(1, 2)
-#define STV090x_P1_FFEQ3			STV090x_Px_FFEQy(1, 3)
-#define STV090x_P1_FFEQ4			STV090x_Px_FFEQy(1, 4)
-#define STV090x_P2_FFEQ1			STV090x_Px_FFEQy(2, 1)
-#define STV090x_P2_FFEQ2			STV090x_Px_FFEQy(2, 2)
-#define STV090x_P2_FFEQ3			STV090x_Px_FFEQy(2, 3)
-#define STV090x_P2_FFEQ4			STV090x_Px_FFEQy(2, 4)
-#define STV090x_OFFST_Px_FFE_ACCQy_FIELD	0
-#define STV090x_WIDTH_Px_FFE_ACCQy_FIELD	8
-
-#define STV090x_Px_FFECFG(__x)			(0xf4d8 - (__x - 1) * 0x200)
-#define STV090x_P1_FFECFG			STV090x_Px_FFECFG(1)
-#define STV090x_P2_FFECFG			STV090x_Px_FFECFG(2)
-#define STV090x_OFFST_Px_EQUALFFE_ON_FIELD	6
-#define STV090x_WIDTH_Px_EQUALFFE_ON_FIELD	1
-
-#define STV090x_Px_SMAPCOEF7(__x)		(0xf500 - (__x - 1) * 0x200)
-#define STV090x_P1_SMAPCOEF7			STV090x_Px_SMAPCOEF7(1)
-#define STV090x_P2_SMAPCOEF7			STV090x_Px_SMAPCOEF7(2)
-#define STV090x_OFFST_Px_DIS_QSCALE_FIELD	7
-#define STV090x_WIDTH_Px_DIS_QSCALE_FIELD	1
-#define STV090x_OFFST_Px_SMAPCOEF_Q_LLR12_FIELD	0
-#define STV090x_WIDTH_Px_SMAPCOEF_Q_LLR12_FIELD	7
-
-#define STV090x_Px_SMAPCOEF6(__x)		(0xf501 - (__x - 1) * 0x200)
-#define STV090x_P1_SMAPCOEF6			STV090x_Px_SMAPCOEF6(1)
-#define STV090x_P2_SMAPCOEF6			STV090x_Px_SMAPCOEF6(2)
-#define STV090x_OFFST_Px_ADJ_8PSKLLR1_FIELD	2
-#define STV090x_WIDTH_Px_ADJ_8PSKLLR1_FIELD	1
-#define STV090x_OFFST_Px_OLD_8PSKLLR1_FIELD	1
-#define STV090x_WIDTH_Px_OLD_8PSKLLR1_FIELD	1
-#define STV090x_OFFST_Px_DIS_AB8PSK_FIELD	0
-#define STV090x_WIDTH_Px_DIS_AB8PSK_FIELD	1
-
-#define STV090x_Px_SMAPCOEF5(__x)			(0xf502 - (__x - 1) * 0x200)
-#define STV090x_P1_SMAPCOEF5				STV090x_Px_SMAPCOEF5(1)
-#define STV090x_P2_SMAPCOEF5				STV090x_Px_SMAPCOEF5(2)
-#define STV090x_OFFST_Px_DIS_8SCALE_FIELD		7
-#define STV090x_WIDTH_Px_DIS_8SCALE_FIELD		1
-#define STV090x_OFFST_Px_SMAPCOEF_8P_LLR23_FIELD	0
-#define STV090x_WIDTH_Px_SMAPCOEF_8P_LLR23_FIELD	7
-
-#define STV090x_Px_DMDPLHSTAT(__x)		(0xF520 - (__x - 1) * 0x200)
-#define STV090x_P1_DMDPLHSTAT			STV090x_Px_DMDPLHSTAT(1)
-#define STV090x_P2_DMDPLHSTAT			STV090x_Px_DMDPLHSTAT(2)
-#define STV090x_OFFST_Px_PLH_STATISTIC_FIELD	0
-#define STV090x_WIDTH_Px_PLH_STATISTIC_FIELD	8
-
-#define STV090x_Px_LOCKTIMEy(__x, __y)		(0xF525 - (__x - 1) * 0x200 - __y * 0x1)
-#define STV090x_P1_LOCKTIME0			STV090x_Px_LOCKTIMEy(1, 0)
-#define STV090x_P1_LOCKTIME1			STV090x_Px_LOCKTIMEy(1, 1)
-#define STV090x_P1_LOCKTIME2			STV090x_Px_LOCKTIMEy(1, 2)
-#define STV090x_P1_LOCKTIME3			STV090x_Px_LOCKTIMEy(1, 3)
-#define STV090x_P2_LOCKTIME0			STV090x_Px_LOCKTIMEy(2, 0)
-#define STV090x_P2_LOCKTIME1			STV090x_Px_LOCKTIMEy(2, 1)
-#define STV090x_P2_LOCKTIME2			STV090x_Px_LOCKTIMEy(2, 2)
-#define STV090x_P2_LOCKTIME3			STV090x_Px_LOCKTIMEy(2, 3)
-#define STV090x_OFFST_Px_DEMOD_LOCKTIME_FIELD	0
-#define STV090x_WIDTH_Px_DEMOD_LOCKTIME_FIELD	8
-
-#define STV090x_Px_TNRCFG(__x)			(0xf4e0 - (__x - 1) * 0x200) /* check */
-#define STV090x_P1_TNRCFG			STV090x_Px_TNRCFG(1)
-#define STV090x_P2_TNRCFG			STV090x_Px_TNRCFG(2)
-
-#define STV090x_Px_TNRCFG2(__x)			(0xf4e1 - (__x - 1) * 0x200)
-#define STV090x_P1_TNRCFG2			STV090x_Px_TNRCFG2(1)
-#define STV090x_P2_TNRCFG2			STV090x_Px_TNRCFG2(2)
-#define STV090x_OFFST_Px_TUN_IQSWAP_FIELD	7
-#define STV090x_WIDTH_Px_TUN_IQSWAP_FIELD	1
-
-#define STV090x_Px_VITSCALE(__x)		(0xf532 - (__x - 1) * 0x200)
-#define STV090x_P1_VITSCALE			STV090x_Px_VITSCALE(1)
-#define STV090x_P2_VITSCALE			STV090x_Px_VITSCALE(2)
-#define STV090x_OFFST_Px_NVTH_NOSRANGE_FIELD	7
-#define STV090x_WIDTH_Px_NVTH_NOSRANGE_FIELD	1
-#define STV090x_OFFST_Px_VERROR_MAXMODE_FIELD	6
-#define STV090x_WIDTH_Px_VERROR_MAXMODE_FIELD	1
-#define STV090x_OFFST_Px_NSLOWSN_LOCKED_FIELD	3
-#define STV090x_WIDTH_Px_NSLOWSN_LOCKED_FIELD	1
-#define STV090x_OFFST_Px_DIS_RSFLOCK_FIELD	1
-#define STV090x_WIDTH_Px_DIS_RSFLOCK_FIELD	1
-
-#define STV090x_Px_FECM(__x)			(0xf533 - (__x - 1) * 0x200)
-#define STV090x_P1_FECM				STV090x_Px_FECM(1)
-#define STV090x_P2_FECM				STV090x_Px_FECM(2)
-#define STV090x_OFFST_Px_DSS_DVB_FIELD		7
-#define STV090x_WIDTH_Px_DSS_DVB_FIELD		1
-#define STV090x_OFFST_Px_DSS_SRCH_FIELD		4
-#define STV090x_WIDTH_Px_DSS_SRCH_FIELD		1
-#define STV090x_OFFST_Px_SYNCVIT_FIELD		1
-#define STV090x_WIDTH_Px_SYNCVIT_FIELD		1
-#define STV090x_OFFST_Px_IQINV_FIELD		0
-#define STV090x_WIDTH_Px_IQINV_FIELD		1
-
-#define STV090x_Px_VTH12(__x)			(0xf534 - (__x - 1) * 0x200)
-#define STV090x_P1_VTH12			STV090x_Px_VTH12(1)
-#define STV090x_P2_VTH12			STV090x_Px_VTH12(2)
-#define STV090x_OFFST_Px_VTH12_FIELD		0
-#define STV090x_WIDTH_Px_VTH12_FIELD		8
-
-#define STV090x_Px_VTH23(__x)			(0xf535 - (__x - 1) * 0x200)
-#define STV090x_P1_VTH23			STV090x_Px_VTH23(1)
-#define STV090x_P2_VTH23			STV090x_Px_VTH23(2)
-#define STV090x_OFFST_Px_VTH23_FIELD		0
-#define STV090x_WIDTH_Px_VTH23_FIELD		8
-
-#define STV090x_Px_VTH34(__x)			(0xf536 - (__x - 1) * 0x200)
-#define STV090x_P1_VTH34			STV090x_Px_VTH34(1)
-#define STV090x_P2_VTH34			STV090x_Px_VTH34(2)
-#define STV090x_OFFST_Px_VTH34_FIELD		0
-#define STV090x_WIDTH_Px_VTH34_FIELD		8
-
-#define STV090x_Px_VTH56(__x)			(0xf537 - (__x - 1) * 0x200)
-#define STV090x_P1_VTH56			STV090x_Px_VTH56(1)
-#define STV090x_P2_VTH56			STV090x_Px_VTH56(2)
-#define STV090x_OFFST_Px_VTH56_FIELD		0
-#define STV090x_WIDTH_Px_VTH56_FIELD		8
-
-#define STV090x_Px_VTH67(__x)			(0xf538 - (__x - 1) * 0x200)
-#define STV090x_P1_VTH67			STV090x_Px_VTH67(1)
-#define STV090x_P2_VTH67			STV090x_Px_VTH67(2)
-#define STV090x_OFFST_Px_VTH67_FIELD		0
-#define STV090x_WIDTH_Px_VTH67_FIELD		8
-
-#define STV090x_Px_VTH78(__x)			(0xf539 - (__x - 1) * 0x200)
-#define STV090x_P1_VTH78			STV090x_Px_VTH78(1)
-#define STV090x_P2_VTH78			STV090x_Px_VTH78(2)
-#define STV090x_OFFST_Px_VTH78_FIELD		0
-#define STV090x_WIDTH_Px_VTH78_FIELD		8
-
-#define STV090x_Px_VITCURPUN(__x)		(0xf53a - (__x - 1) * 0x200)
-#define STV090x_P1_VITCURPUN			STV090x_Px_VITCURPUN(1)
-#define STV090x_P2_VITCURPUN			STV090x_Px_VITCURPUN(2)
-#define STV090x_OFFST_Px_VIT_CURPUN_FIELD	0
-#define STV090x_WIDTH_Px_VIT_CURPUN_FIELD	5
-
-#define STV090x_Px_VERROR(__x)			(0xf53b - (__x - 1) * 0x200)
-#define STV090x_P1_VERROR			STV090x_Px_VERROR(1)
-#define STV090x_P2_VERROR			STV090x_Px_VERROR(2)
-#define STV090x_OFFST_Px_REGERR_VIT_FIELD	0
-#define STV090x_WIDTH_Px_REGERR_VIT_FIELD	8
-
-#define STV090x_Px_PRVIT(__x)			(0xf53c - (__x - 1) * 0x200)
-#define STV090x_P1_PRVIT			STV090x_Px_PRVIT(1)
-#define STV090x_P2_PRVIT			STV090x_Px_PRVIT(2)
-#define STV090x_OFFST_Px_DIS_VTHLOCK_FIELD	6
-#define STV090x_WIDTH_Px_DIS_VTHLOCK_FIELD	1
-#define STV090x_OFFST_Px_E7_8VIT_FIELD		5
-#define STV090x_WIDTH_Px_E7_8VIT_FIELD		1
-#define STV090x_OFFST_Px_E6_7VIT_FIELD		4
-#define STV090x_WIDTH_Px_E6_7VIT_FIELD		1
-#define STV090x_OFFST_Px_E5_6VIT_FIELD		3
-#define STV090x_WIDTH_Px_E5_6VIT_FIELD		1
-#define STV090x_OFFST_Px_E3_4VIT_FIELD		2
-#define STV090x_WIDTH_Px_E3_4VIT_FIELD		1
-#define STV090x_OFFST_Px_E2_3VIT_FIELD		1
-#define STV090x_WIDTH_Px_E2_3VIT_FIELD		1
-#define STV090x_OFFST_Px_E1_2VIT_FIELD		0
-#define STV090x_WIDTH_Px_E1_2VIT_FIELD		1
-
-#define STV090x_Px_VAVSRVIT(__x)		(0xf53d - (__x - 1) * 0x200)
-#define STV090x_P1_VAVSRVIT			STV090x_Px_VAVSRVIT(1)
-#define STV090x_P2_VAVSRVIT			STV090x_Px_VAVSRVIT(2)
-#define STV090x_OFFST_Px_SNVIT_FIELD		4
-#define STV090x_WIDTH_Px_SNVIT_FIELD		2
-#define STV090x_OFFST_Px_TOVVIT_FIELD		2
-#define STV090x_WIDTH_Px_TOVVIT_FIELD		2
-#define STV090x_OFFST_Px_HYPVIT_FIELD		0
-#define STV090x_WIDTH_Px_HYPVIT_FIELD		2
-
-#define STV090x_Px_VSTATUSVIT(__x)		(0xf53e - (__x - 1) * 0x200)
-#define STV090x_P1_VSTATUSVIT			STV090x_Px_VSTATUSVIT(1)
-#define STV090x_P2_VSTATUSVIT			STV090x_Px_VSTATUSVIT(2)
-#define STV090x_OFFST_Px_PRFVIT_FIELD		4
-#define STV090x_WIDTH_Px_PRFVIT_FIELD		1
-#define STV090x_OFFST_Px_LOCKEDVIT_FIELD	3
-#define STV090x_WIDTH_Px_LOCKEDVIT_FIELD	1
-
-#define STV090x_Px_VTHINUSE(__x)		(0xf53f - (__x - 1) * 0x200)
-#define STV090x_P1_VTHINUSE			STV090x_Px_VTHINUSE(1)
-#define STV090x_P2_VTHINUSE			STV090x_Px_VTHINUSE(2)
-#define STV090x_OFFST_Px_VIT_INUSE_FIELD	0
-#define STV090x_WIDTH_Px_VIT_INUSE_FIELD	8
-
-#define STV090x_Px_KDIV12(__x)			(0xf540 - (__x - 1) * 0x200)
-#define STV090x_P1_KDIV12			STV090x_Px_KDIV12(1)
-#define STV090x_P2_KDIV12			STV090x_Px_KDIV12(2)
-#define STV090x_OFFST_Px_K_DIVIDER_12_FIELD	0
-#define STV090x_WIDTH_Px_K_DIVIDER_12_FIELD	7
-
-#define STV090x_Px_KDIV23(__x)			(0xf541 - (__x - 1) * 0x200)
-#define STV090x_P1_KDIV23			STV090x_Px_KDIV23(1)
-#define STV090x_P2_KDIV23			STV090x_Px_KDIV23(2)
-#define STV090x_OFFST_Px_K_DIVIDER_23_FIELD	0
-#define STV090x_WIDTH_Px_K_DIVIDER_23_FIELD	7
-
-#define STV090x_Px_KDIV34(__x)			(0xf542 - (__x - 1) * 0x200)
-#define STV090x_P1_KDIV34			STV090x_Px_KDIV34(1)
-#define STV090x_P2_KDIV34			STV090x_Px_KDIV34(2)
-#define STV090x_OFFST_Px_K_DIVIDER_34_FIELD	0
-#define STV090x_WIDTH_Px_K_DIVIDER_34_FIELD	7
-
-#define STV090x_Px_KDIV56(__x)			(0xf543 - (__x - 1) * 0x200)
-#define STV090x_P1_KDIV56			STV090x_Px_KDIV56(1)
-#define STV090x_P2_KDIV56			STV090x_Px_KDIV56(2)
-#define STV090x_OFFST_Px_K_DIVIDER_56_FIELD	0
-#define STV090x_WIDTH_Px_K_DIVIDER_56_FIELD	7
-
-#define STV090x_Px_KDIV67(__x)			(0xf544 - (__x - 1) * 0x200)
-#define STV090x_P1_KDIV67			STV090x_Px_KDIV67(1)
-#define STV090x_P2_KDIV67			STV090x_Px_KDIV67(2)
-#define STV090x_OFFST_Px_K_DIVIDER_67_FIELD	0
-#define STV090x_WIDTH_Px_K_DIVIDER_67_FIELD	7
-
-#define STV090x_Px_KDIV78(__x)			(0xf545 - (__x - 1) * 0x200)
-#define STV090x_P1_KDIV78			STV090x_Px_KDIV78(1)
-#define STV090x_P2_KDIV78			STV090x_Px_KDIV78(2)
-#define STV090x_OFFST_Px_K_DIVIDER_78_FIELD	0
-#define STV090x_WIDTH_Px_K_DIVIDER_78_FIELD	7
-
-#define STV090x_Px_PDELCTRL1(__x)		(0xf550 - (__x - 1) * 0x200)
-#define STV090x_P1_PDELCTRL1			STV090x_Px_PDELCTRL1(1)
-#define STV090x_P2_PDELCTRL1			STV090x_Px_PDELCTRL1(2)
-#define STV090x_OFFST_Px_INV_MISMASK_FIELD	7
-#define STV090x_WIDTH_Px_INV_MISMASK_FIELD	1
-#define STV090x_OFFST_Px_FILTER_EN_FIELD	5
-#define STV090x_WIDTH_Px_FILTER_EN_FIELD	1
-#define STV090x_OFFST_Px_EN_MIS00_FIELD		1
-#define STV090x_WIDTH_Px_EN_MIS00_FIELD		1
-#define STV090x_OFFST_Px_ALGOSWRST_FIELD	0
-#define STV090x_WIDTH_Px_ALGOSWRST_FIELD	1
-
-#define STV090x_Px_PDELCTRL2(__x)		(0xf551 - (__x - 1) * 0x200)
-#define STV090x_P1_PDELCTRL2			STV090x_Px_PDELCTRL2(1)
-#define STV090x_P2_PDELCTRL2			STV090x_Px_PDELCTRL2(2)
-#define STV090x_OFFST_Px_FORCE_CONTINUOUS	7
-#define STV090x_WIDTH_Px_FORCE_CONTINUOUS	1
-#define STV090x_OFFST_Px_RESET_UPKO_COUNT	6
-#define STV090x_WIDTH_Px_RESET_UPKO_COUNT	1
-#define STV090x_OFFST_Px_USER_PKTDELIN_NB	5
-#define STV090x_WIDTH_Px_USER_PKTDELIN_NB	1
-#define STV090x_OFFST_Px_FORCE_LOCKED		4
-#define STV090x_WIDTH_Px_FORCE_LOCKED		1
-#define STV090x_OFFST_Px_DATA_UNBBSCRAM		3
-#define STV090x_WIDTH_Px_DATA_UNBBSCRAM		1
-#define STV090x_OFFST_Px_FORCE_LONGPACKET	2
-#define STV090x_WIDTH_Px_FORCE_LONGPACKET	1
-#define STV090x_OFFST_Px_FRAME_MODE_FIELD	1
-#define STV090x_WIDTH_Px_FRAME_MODE_FIELD	1
-
-#define STV090x_Px_HYSTTHRESH(__x)		(0xf554 - (__x - 1) * 0x200)
-#define STV090x_P1_HYSTTHRESH			STV090x_Px_HYSTTHRESH(1)
-#define STV090x_P2_HYSTTHRESH			STV090x_Px_HYSTTHRESH(2)
-#define STV090x_OFFST_Px_UNLCK_THRESH_FIELD	4
-#define STV090x_WIDTH_Px_UNLCK_THRESH_FIELD	4
-#define STV090x_OFFST_Px_DELIN_LCK_THRESH_FIELD	0
-#define STV090x_WIDTH_Px_DELIN_LCK_THRESH_FIELD	4
-
-#define STV090x_Px_ISIENTRY(__x)		(0xf55e - (__x - 1) * 0x200)
-#define STV090x_P1_ISIENTRY			STV090x_Px_ISIENTRY(1)
-#define STV090x_P2_ISIENTRY			STV090x_Px_ISIENTRY(2)
-#define STV090x_OFFST_Px_ISI_ENTRY_FIELD	0
-#define STV090x_WIDTH_Px_ISI_ENTRY_FIELD	8
-
-#define STV090x_Px_ISIBITENA(__x)		(0xf55f - (__x - 1) * 0x200)
-#define STV090x_P1_ISIBITENA			STV090x_Px_ISIBITENA(1)
-#define STV090x_P2_ISIBITENA			STV090x_Px_ISIBITENA(2)
-#define STV090x_OFFST_Px_ISI_BIT_EN_FIELD	0
-#define STV090x_WIDTH_Px_ISI_BIT_EN_FIELD	8
-
-#define STV090x_Px_MATSTRy(__x, __y)		(0xf561 - (__x - 1) * 0x200 - __y * 0x1)
-#define STV090x_P1_MATSTR0			STV090x_Px_MATSTRy(1, 0)
-#define STV090x_P1_MATSTR1			STV090x_Px_MATSTRy(1, 1)
-#define STV090x_P2_MATSTR0			STV090x_Px_MATSTRy(2, 0)
-#define STV090x_P2_MATSTR1			STV090x_Px_MATSTRy(2, 1)
-#define STV090x_OFFST_Px_MATYPE_CURRENT_FIELD	0
-#define STV090x_WIDTH_Px_MATYPE_CURRENT_FIELD	8
-
-#define STV090x_Px_UPLSTRy(__x, __y)		(0xf563 - (__x - 1) * 0x200 - __y * 0x1)
-#define STV090x_P1_UPLSTR0			STV090x_Px_UPLSTRy(1, 0)
-#define STV090x_P1_UPLSTR1			STV090x_Px_UPLSTRy(1, 1)
-#define STV090x_P2_UPLSTR0			STV090x_Px_UPLSTRy(2, 0)
-#define STV090x_P2_UPLSTR1			STV090x_Px_UPLSTRy(2, 1)
-#define STV090x_OFFST_Px_UPL_CURRENT_FIELD	0
-#define STV090x_WIDTH_Px_UPL_CURRENT_FIELD	8
-
-#define STV090x_Px_DFLSTRy(__x, __y)		(0xf565 - (__x - 1) * 0x200 - __y * 0x1)
-#define STV090x_P1_DFLSTR0			STV090x_Px_DFLSTRy(1, 0)
-#define STV090x_P1_DFLSTR1			STV090x_Px_DFLSTRy(1, 1)
-#define STV090x_P2_DFLSTR0			STV090x_Px_DFLSTRy(2, 0)
-#define STV090x_P2_DFLSTR1			STV090x_Px_DFLSTRy(2, 1)
-#define STV090x_OFFST_Px_DFL_CURRENT_FIELD	0
-#define STV090x_WIDTH_Px_DFL_CURRENT_FIELD	8
-
-#define STV090x_Px_SYNCSTR(__x)			(0xf566 - (__x - 1) * 0x200)
-#define STV090x_P1_SYNCSTR			STV090x_Px_SYNCSTR(1)
-#define STV090x_P2_SYNCSTR			STV090x_Px_SYNCSTR(2)
-#define STV090x_OFFST_Px_SYNC_CURRENT_FIELD	0
-#define STV090x_WIDTH_Px_SYNC_CURRENT_FIELD	8
-
-#define STV090x_Px_SYNCDSTRy(__x, __y)		(0xf568 - (__x - 1) * 0x200 - __y * 0x1)
-#define STV090x_P1_SYNCDSTR0			STV090x_Px_SYNCDSTRy(1, 0)
-#define STV090x_P1_SYNCDSTR1			STV090x_Px_SYNCDSTRy(1, 1)
-#define STV090x_P2_SYNCDSTR0			STV090x_Px_SYNCDSTRy(2, 0)
-#define STV090x_P2_SYNCDSTR1			STV090x_Px_SYNCDSTRy(2, 1)
-#define STV090x_OFFST_Px_SYNCD_CURRENT_FIELD	0
-#define STV090x_WIDTH_Px_SYNCD_CURRENT_FIELD	8
-
-#define STV090x_Px_PDELSTATUS1(__x)		(0xf569 - (__x - 1) * 0x200)
-#define STV090x_P1_PDELSTATUS1			STV090x_Px_PDELSTATUS1(1)
-#define STV090x_P2_PDELSTATUS1			STV090x_Px_PDELSTATUS1(2)
-#define STV090x_OFFST_Px_PKTDELIN_LOCK_FIELD	1
-#define STV090x_WIDTH_Px_PKTDELIN_LOCK_FIELD	1
-#define STV090x_OFFST_Px_FIRST_LOCK_FIELD	0
-#define STV090x_WIDTH_Px_FIRST_LOCK_FIELD	1
-
-#define STV090x_Px_PDELSTATUS2(__x)		(0xf56a - (__x - 1) * 0x200)
-#define STV090x_P1_PDELSTATUS2			STV090x_Px_PDELSTATUS2(1)
-#define STV090x_P2_PDELSTATUS2			STV090x_Px_PDELSTATUS2(2)
-#define STV090x_OFFST_Px_FRAME_MODCOD_FIELD	2
-#define STV090x_WIDTH_Px_FRAME_MODCOD_FIELD	5
-#define STV090x_OFFST_Px_FRAME_TYPE_FIELD	0
-#define STV090x_WIDTH_Px_FRAME_TYPE_FIELD	2
-
-#define STV090x_Px_BBFCRCKO1(__x)		(0xf56b - (__x - 1) * 0x200)
-#define STV090x_P1_BBFCRCKO1			STV090x_Px_BBFCRCKO1(1)
-#define STV090x_P2_BBFCRCKO1			STV090x_Px_BBFCRCKO1(2)
-#define STV090x_OFFST_Px_BBHCRC_KOCNT_FIELD	0
-#define STV090x_WIDTH_Px_BBHCRC_KOCNT_FIELD	8
-
-#define STV090x_Px_BBFCRCKO0(__x)		(0xf56c - (__x - 1) * 0x200)
-#define STV090x_P1_BBFCRCKO0			STV090x_Px_BBFCRCKO0(1)
-#define STV090x_P2_BBFCRCKO0			STV090x_Px_BBFCRCKO0(2)
-#define STV090x_OFFST_Px_BBHCRC_KOCNT_FIELD	0
-#define STV090x_WIDTH_Px_BBHCRC_KOCNT_FIELD	8
-
-#define STV090x_Px_UPCRCKO1(__x)		(0xf56d - (__x - 1) * 0x200)
-#define STV090x_P1_UPCRCKO1			STV090x_Px_UPCRCKO1(1)
-#define STV090x_P2_UPCRCKO1			STV090x_Px_UPCRCKO1(2)
-#define STV090x_OFFST_Px_PKTCRC_KOCNT_FIELD	0
-#define STV090x_WIDTH_Px_PKTCRC_KOCNT_FIELD	8
-
-#define STV090x_Px_UPCRCKO0(__x)		(0xf56e - (__x - 1) * 0x200)
-#define STV090x_P1_UPCRCKO0			STV090x_Px_UPCRCKO0(1)
-#define STV090x_P2_UPCRCKO0			STV090x_Px_UPCRCKO0(2)
-#define STV090x_OFFST_Px_PKTCRC_KOCNT_FIELD	0
-#define STV090x_WIDTH_Px_PKTCRC_KOCNT_FIELD	8
-
-#define STV090x_NBITER_NFx(__x)				(0xFA03 + (__x - 4) * 0x1)
-#define STV090x_NBITER_NF4				STV090x_NBITER_NFx(4)
-#define STV090x_NBITER_NF5				STV090x_NBITER_NFx(5)
-#define STV090x_NBITER_NF6				STV090x_NBITER_NFx(6)
-#define STV090x_NBITER_NF7				STV090x_NBITER_NFx(7)
-#define STV090x_NBITER_NF8				STV090x_NBITER_NFx(8)
-#define STV090x_NBITER_NF9				STV090x_NBITER_NFx(9)
-#define STV090x_NBITER_NF10				STV090x_NBITER_NFx(10)
-#define STV090x_NBITER_NF11				STV090x_NBITER_NFx(11)
-#define STV090x_NBITER_NF12				STV090x_NBITER_NFx(12)
-#define STV090x_NBITER_NF13				STV090x_NBITER_NFx(13)
-#define STV090x_NBITER_NF14				STV090x_NBITER_NFx(14)
-#define STV090x_NBITER_NF15				STV090x_NBITER_NFx(15)
-#define STV090x_NBITER_NF16				STV090x_NBITER_NFx(16)
-#define STV090x_NBITER_NF17				STV090x_NBITER_NFx(17)
-
-#define STV090x_NBITERNOERR				0xFA3F
-#define STV090x_OFFST_NBITER_STOP_CRIT_FIELD		0
-#define STV090x_WIDTH_NBITER_STOP_CRIT_FIELD		4
-
-#define STV090x_GAINLLR_NFx(__x)			(0xFA43 + (__x - 4) * 0x1)
-#define STV090x_GAINLLR_NF4				STV090x_GAINLLR_NFx(4)
-#define STV090x_OFFST_GAINLLR_NF_QP_1_2_FIELD		0
-#define STV090x_WIDTH_GAINLLR_NF_QP_1_2_FIELD		7
-
-#define STV090x_GAINLLR_NF5				STV090x_GAINLLR_NFx(5)
-#define STV090x_OFFST_GAINLLR_NF_QP_3_5_FIELD		0
-#define STV090x_WIDTH_GAINLLR_NF_QP_3_5_FIELD		7
-
-#define STV090x_GAINLLR_NF6				STV090x_GAINLLR_NFx(6)
-#define STV090x_OFFST_GAINLLR_NF_QP_2_3_FIELD		0
-#define STV090x_WIDTH_GAINLLR_NF_QP_2_3_FIELD		7
-
-#define STV090x_GAINLLR_NF7				STV090x_GAINLLR_NFx(7)
-#define STV090x_OFFST_GAINLLR_NF_QP_3_4_FIELD		0
-#define STV090x_WIDTH_GAINLLR_NF_QP_3_4_FIELD		7
-
-#define STV090x_GAINLLR_NF8				STV090x_GAINLLR_NFx(8)
-#define STV090x_OFFST_GAINLLR_NF_QP_4_5_FIELD		0
-#define STV090x_WIDTH_GAINLLR_NF_QP_4_5_FIELD		7
-
-#define STV090x_GAINLLR_NF9				STV090x_GAINLLR_NFx(9)
-#define STV090x_OFFST_GAINLLR_NF_QP_5_6_FIELD		0
-#define STV090x_WIDTH_GAINLLR_NF_QP_5_6_FIELD		7
-
-#define STV090x_GAINLLR_NF10				STV090x_GAINLLR_NFx(10)
-#define STV090x_OFFST_GAINLLR_NF_QP_8_9_FIELD		0
-#define STV090x_WIDTH_GAINLLR_NF_QP_8_9_FIELD		7
-
-#define STV090x_GAINLLR_NF11				STV090x_GAINLLR_NFx(11)
-#define STV090x_OFFST_GAINLLR_NF_QP_9_10_FIELD		0
-#define STV090x_WIDTH_GAINLLR_NF_QP_9_10_FIELD		7
-
-#define STV090x_GAINLLR_NF12				STV090x_GAINLLR_NFx(12)
-#define STV090x_OFFST_GAINLLR_NF_8P_3_5_FIELD		0
-#define STV090x_WIDTH_GAINLLR_NF_8P_3_5_FIELD		7
-
-#define STV090x_GAINLLR_NF13				STV090x_GAINLLR_NFx(13)
-#define STV090x_OFFST_GAINLLR_NF_8P_2_3_FIELD		0
-#define STV090x_WIDTH_GAINLLR_NF_8P_2_3_FIELD		7
-
-#define STV090x_GAINLLR_NF14				STV090x_GAINLLR_NFx(14)
-#define STV090x_OFFST_GAINLLR_NF_8P_3_4_FIELD		0
-#define STV090x_WIDTH_GAINLLR_NF_8P_3_4_FIELD		7
-
-#define STV090x_GAINLLR_NF15				STV090x_GAINLLR_NFx(15)
-#define STV090x_OFFST_GAINLLR_NF_8P_5_6_FIELD		0
-#define STV090x_WIDTH_GAINLLR_NF_8P_5_6_FIELD		7
-
-#define STV090x_GAINLLR_NF16				STV090x_GAINLLR_NFx(16)
-#define STV090x_OFFST_GAINLLR_NF_8P_8_9_FIELD		0
-#define STV090x_WIDTH_GAINLLR_NF_8P_8_9_FIELD		7
-
-#define STV090x_GAINLLR_NF17				STV090x_GAINLLR_NFx(17)
-#define STV090x_OFFST_GAINLLR_NF_8P_9_10_FIELD		0
-#define STV090x_WIDTH_GAINLLR_NF_8P_9_10_FIELD		7
-
-#define STV090x_GENCFG					0xFA86
-#define STV090x_OFFST_BROADCAST_FIELD			4
-#define STV090x_WIDTH_BROADCAST_FIELD			1
-#define STV090x_OFFST_PRIORITY_FIELD			1
-#define STV090x_WIDTH_PRIORITY_FIELD			1
-#define STV090x_OFFST_DDEMOD_FIELD			0
-#define STV090x_WIDTH_DDEMOD_FIELD			1
-
-#define STV090x_LDPCERRx(__x)				(0xFA97 - (__x  * 0x1))
-#define STV090x_LDPCERR0				STV090x_LDPCERRx(0)
-#define STV090x_LDPCERR1				STV090x_LDPCERRx(1)
-#define STV090x_OFFST_Px_LDPC_ERRORS_COUNTER_FIELD	0
-#define STV090x_WIDTH_Px_LDPC_ERRORS_COUNTER_FIELD	8
-
-#define STV090x_BCHERR					0xFA98
-#define STV090x_OFFST_Px_ERRORFLAG_FIELD		4
-#define STV090x_WIDTH_Px_ERRORFLAG_FIELD		1
-#define STV090x_OFFST_Px_BCH_ERRORS_COUNTER_FIELD	0
-#define STV090x_WIDTH_Px_BCH_ERRORS_COUNTER_FIELD	4
-
-#define STV090x_Px_TSSTATEM(__x)			(0xF570 - (__x - 1) * 0x200)
-#define STV090x_P1_TSSTATEM				STV090x_Px_TSSTATEM(1)
-#define STV090x_P2_TSSTATEM				STV090x_Px_TSSTATEM(2)
-#define STV090x_OFFST_Px_TSDIL_ON_FIELD			7
-#define STV090x_WIDTH_Px_TSDIL_ON_FIELD			1
-#define STV090x_OFFST_Px_TSRS_ON_FIELD			5
-#define STV090x_WIDTH_Px_TSRS_ON_FIELD			1
-
-#define STV090x_Px_TSCFGH(__x)				(0xF572 - (__x - 1) * 0x200)
-#define STV090x_P1_TSCFGH				STV090x_Px_TSCFGH(1)
-#define STV090x_P2_TSCFGH				STV090x_Px_TSCFGH(2)
-#define STV090x_OFFST_Px_TSFIFO_DVBCI_FIELD		7
-#define STV090x_WIDTH_Px_TSFIFO_DVBCI_FIELD		1
-#define STV090x_OFFST_Px_TSFIFO_SERIAL_FIELD		6
-#define STV090x_WIDTH_Px_TSFIFO_SERIAL_FIELD		1
-#define STV090x_OFFST_Px_TSFIFO_TEIUPDATE_FIELD		5
-#define STV090x_WIDTH_Px_TSFIFO_TEIUPDATE_FIELD		1
-#define STV090x_OFFST_Px_TSFIFO_DUTY50_FIELD		4
-#define STV090x_WIDTH_Px_TSFIFO_DUTY50_FIELD		1
-#define STV090x_OFFST_Px_TSFIFO_HSGNLOUT_FIELD		3
-#define STV090x_WIDTH_Px_TSFIFO_HSGNLOUT_FIELD		1
-#define STV090x_OFFST_Px_TSFIFO_ERRORMODE_FIELD		1
-#define STV090x_WIDTH_Px_TSFIFO_ERRORMODE_FIELD		2
-#define STV090x_OFFST_Px_RST_HWARE_FIELD		0
-#define STV090x_WIDTH_Px_RST_HWARE_FIELD		1
-
-#define STV090x_Px_TSCFGM(__x)				(0xF573 - (__x - 1) * 0x200)
-#define STV090x_P1_TSCFGM				STV090x_Px_TSCFGM(1)
-#define STV090x_P2_TSCFGM				STV090x_Px_TSCFGM(2)
-#define STV090x_OFFST_Px_TSFIFO_MANSPEED_FIELD		6
-#define STV090x_WIDTH_Px_TSFIFO_MANSPEED_FIELD		2
-#define STV090x_OFFST_Px_TSFIFO_PERMDATA_FIELD		5
-#define STV090x_WIDTH_Px_TSFIFO_PERMDATA_FIELD		1
-#define STV090x_OFFST_Px_TSFIFO_INVDATA_FIELD		0
-#define STV090x_WIDTH_Px_TSFIFO_INVDATA_FIELD		1
-
-#define STV090x_Px_TSCFGL(__x)				(0xF574 - (__x - 1) * 0x200)
-#define STV090x_P1_TSCFGL				STV090x_Px_TSCFGL(1)
-#define STV090x_P2_TSCFGL				STV090x_Px_TSCFGL(2)
-#define STV090x_OFFST_Px_TSFIFO_BCLKDEL1CK_FIELD	6
-#define STV090x_WIDTH_Px_TSFIFO_BCLKDEL1CK_FIELD	2
-#define STV090x_OFFST_Px_BCHERROR_MODE_FIELD		4
-#define STV090x_WIDTH_Px_BCHERROR_MODE_FIELD		2
-#define STV090x_OFFST_Px_TSFIFO_NSGNL2DATA_FIELD	3
-#define STV090x_WIDTH_Px_TSFIFO_NSGNL2DATA_FIELD	1
-#define STV090x_OFFST_Px_TSFIFO_EMBINDVB_FIELD		2
-#define STV090x_WIDTH_Px_TSFIFO_EMBINDVB_FIELD		1
-#define STV090x_OFFST_Px_TSFIFO_DPUNACT_FIELD		1
-#define STV090x_WIDTH_Px_TSFIFO_DPUNACT_FIELD		1
-
-#define STV090x_Px_TSINSDELH(__x)			(0xF576 - (__x - 1) * 0x200)
-#define STV090x_P1_TSINSDELH				STV090x_Px_TSINSDELH(1)
-#define STV090x_P2_TSINSDELH				STV090x_Px_TSINSDELH(2)
-#define STV090x_OFFST_Px_TSDEL_SYNCBYTE_FIELD		7
-#define STV090x_WIDTH_Px_TSDEL_SYNCBYTE_FIELD		1
-#define STV090x_OFFST_Px_TSDEL_XXHEADER_FIELD		6
-#define STV090x_WIDTH_Px_TSDEL_XXHEADER_FIELD		1
-
-#define STV090x_Px_TSSPEED(__x)				(0xF580 - (__x - 1) * 0x200)
-#define STV090x_P1_TSSPEED				STV090x_Px_TSSPEED(1)
-#define STV090x_P2_TSSPEED				STV090x_Px_TSSPEED(2)
-#define STV090x_OFFST_Px_TSFIFO_OUTSPEED_FIELD		0
-#define STV090x_WIDTH_Px_TSFIFO_OUTSPEED_FIELD		8
-
-#define STV090x_Px_TSSTATUS(__x)			(0xF581 - (__x - 1) * 0x200)
-#define STV090x_P1_TSSTATUS				STV090x_Px_TSSTATUS(1)
-#define STV090x_P2_TSSTATUS				STV090x_Px_TSSTATUS(2)
-#define STV090x_OFFST_Px_TSFIFO_LINEOK_FIELD		7
-#define STV090x_WIDTH_Px_TSFIFO_LINEOK_FIELD		1
-#define STV090x_OFFST_Px_TSFIFO_ERROR_FIELD		6
-#define STV090x_WIDTH_Px_TSFIFO_ERROR_FIELD		1
-
-#define STV090x_Px_TSSTATUS2(__x)			(0xF582 - (__x - 1) * 0x200)
-#define STV090x_P1_TSSTATUS2				STV090x_Px_TSSTATUS2(1)
-#define STV090x_P2_TSSTATUS2				STV090x_Px_TSSTATUS2(2)
-#define STV090x_OFFST_Px_TSFIFO_DEMODSEL_FIELD		7
-#define STV090x_WIDTH_Px_TSFIFO_DEMODSEL_FIELD		1
-#define STV090x_OFFST_Px_TSFIFOSPEED_STORE_FIELD	6
-#define STV090x_WIDTH_Px_TSFIFOSPEED_STORE_FIELD	1
-#define STV090x_OFFST_Px_DILXX_RESET_FIELD		5
-#define STV090x_WIDTH_Px_DILXX_RESET_FIELD		1
-#define STV090x_OFFST_Px_TSSERIAL_IMPOS_FIELD		4
-#define STV090x_WIDTH_Px_TSSERIAL_IMPOS_FIELD		1
-#define STV090x_OFFST_Px_SCRAMBDETECT_FIELD		1
-#define STV090x_WIDTH_Px_SCRAMBDETECT_FIELD		1
-
-#define STV090x_Px_TSBITRATEy(__x, __y)			(0xF584 - (__x - 1) * 0x200 - __y * 0x1)
-#define STV090x_P1_TSBITRATE0				STV090x_Px_TSBITRATEy(1, 0)
-#define STV090x_P1_TSBITRATE1				STV090x_Px_TSBITRATEy(1, 1)
-#define STV090x_P2_TSBITRATE0				STV090x_Px_TSBITRATEy(2, 0)
-#define STV090x_P2_TSBITRATE1				STV090x_Px_TSBITRATEy(2, 1)
-#define STV090x_OFFST_Px_TSFIFO_BITRATE_FIELD		0
-#define STV090x_WIDTH_Px_TSFIFO_BITRATE_FIELD		8
-
-#define STV090x_Px_ERRCTRL1(__x)			(0xF598 - (__x - 1) * 0x200)
-#define STV090x_P1_ERRCTRL1				STV090x_Px_ERRCTRL1(1)
-#define STV090x_P2_ERRCTRL1				STV090x_Px_ERRCTRL1(2)
-#define STV090x_OFFST_Px_ERR_SOURCE_FIELD		4
-#define STV090x_WIDTH_Px_ERR_SOURCE_FIELD		4
-#define STV090x_OFFST_Px_NUM_EVENT_FIELD		0
-#define STV090x_WIDTH_Px_NUM_EVENT_FIELD		3
-
-#define STV090x_Px_ERRCNT12(__x)			(0xF599 - (__x - 1) * 0x200)
-#define STV090x_P1_ERRCNT12				STV090x_Px_ERRCNT12(1)
-#define STV090x_P2_ERRCNT12				STV090x_Px_ERRCNT12(2)
-#define STV090x_OFFST_Px_ERRCNT1_OLDVALUE_FIELD		7
-#define STV090x_WIDTH_Px_ERRCNT1_OLDVALUE_FIELD		1
-#define STV090x_OFFST_Px_ERR_CNT12_FIELD		0
-#define STV090x_WIDTH_Px_ERR_CNT12_FIELD		7
-
-#define STV090x_Px_ERRCNT11(__x)			(0xF59A - (__x - 1) * 0x200)
-#define STV090x_P1_ERRCNT11				STV090x_Px_ERRCNT11(1)
-#define STV090x_P2_ERRCNT11				STV090x_Px_ERRCNT11(2)
-#define STV090x_OFFST_Px_ERR_CNT11_FIELD		0
-#define STV090x_WIDTH_Px_ERR_CNT11_FIELD		8
-
-#define STV090x_Px_ERRCNT10(__x)			(0xF59B - (__x - 1) * 0x200)
-#define STV090x_P1_ERRCNT10				STV090x_Px_ERRCNT10(1)
-#define STV090x_P2_ERRCNT10				STV090x_Px_ERRCNT10(2)
-#define STV090x_OFFST_Px_ERR_CNT10_FIELD		0
-#define STV090x_WIDTH_Px_ERR_CNT10_FIELD		8
-
-#define STV090x_Px_ERRCTRL2(__x)			(0xF59C - (__x - 1) * 0x200)
-#define STV090x_P1_ERRCTRL2				STV090x_Px_ERRCTRL2(1)
-#define STV090x_P2_ERRCTRL2				STV090x_Px_ERRCTRL2(2)
-#define STV090x_OFFST_Px_ERR_SOURCE2_FIELD		4
-#define STV090x_WIDTH_Px_ERR_SOURCE2_FIELD		4
-#define STV090x_OFFST_Px_NUM_EVENT2_FIELD		0
-#define STV090x_WIDTH_Px_NUM_EVENT2_FIELD		3
-
-#define STV090x_Px_ERRCNT22(__x)			(0xF59D - (__x - 1) * 0x200)
-#define STV090x_P1_ERRCNT22				STV090x_Px_ERRCNT22(1)
-#define STV090x_P2_ERRCNT22				STV090x_Px_ERRCNT22(2)
-#define STV090x_OFFST_Px_ERRCNT2_OLDVALUE_FIELD		7
-#define STV090x_WIDTH_Px_ERRCNT2_OLDVALUE_FIELD		1
-#define STV090x_OFFST_Px_ERR_CNT2_FIELD			0
-#define STV090x_WIDTH_Px_ERR_CNT2_FIELD			7
-
-#define STV090x_Px_ERRCNT21(__x)			(0xF59E - (__x - 1) * 0x200)
-#define STV090x_P1_ERRCNT21				STV090x_Px_ERRCNT21(1)
-#define STV090x_P2_ERRCNT21				STV090x_Px_ERRCNT21(2)
-#define STV090x_OFFST_Px_ERR_CNT21_FIELD		0
-#define STV090x_WIDTH_Px_ERR_CNT21_FIELD		8
-
-#define STV090x_Px_ERRCNT20(__x)			(0xF59F - (__x - 1) * 0x200)
-#define STV090x_P1_ERRCNT20				STV090x_Px_ERRCNT20(1)
-#define STV090x_P2_ERRCNT20				STV090x_Px_ERRCNT20(2)
-#define STV090x_OFFST_Px_ERR_CNT20_FIELD		0
-#define STV090x_WIDTH_Px_ERR_CNT20_FIELD		8
-
-#define STV090x_Px_FECSPY(__x)				(0xF5A0 - (__x - 1) * 0x200)
-#define STV090x_P1_FECSPY				STV090x_Px_FECSPY(1)
-#define STV090x_P2_FECSPY				STV090x_Px_FECSPY(2)
-#define STV090x_OFFST_Px_SPY_ENABLE_FIELD		7
-#define STV090x_WIDTH_Px_SPY_ENABLE_FIELD		1
-#define STV090x_OFFST_Px_BERMETER_DATAMAODE_FIELD	2
-#define STV090x_WIDTH_Px_BERMETER_DATAMAODE_FIELD	2
-
-#define STV090x_Px_FSPYCFG(__x)				(0xF5A1 - (__x - 1) * 0x200)
-#define STV090x_P1_FSPYCFG				STV090x_Px_FSPYCFG(1)
-#define STV090x_P2_FSPYCFG				STV090x_Px_FSPYCFG(2)
-#define STV090x_OFFST_Px_RST_ON_ERROR_FIELD		5
-#define STV090x_WIDTH_Px_RST_ON_ERROR_FIELD		1
-#define STV090x_OFFST_Px_ONE_SHOT_FIELD			4
-#define STV090x_WIDTH_Px_ONE_SHOT_FIELD			1
-#define STV090x_OFFST_Px_I2C_MODE_FIELD			2
-#define STV090x_WIDTH_Px_I2C_MODE_FIELD			2
-
-#define STV090x_Px_FSPYDATA(__x)			(0xF5A2 - (__x - 1) * 0x200)
-#define STV090x_P1_FSPYDATA				STV090x_Px_FSPYDATA(1)
-#define STV090x_P2_FSPYDATA				STV090x_Px_FSPYDATA(2)
-#define STV090x_OFFST_Px_SPY_STUFFING_FIELD		7
-#define STV090x_WIDTH_Px_SPY_STUFFING_FIELD		1
-#define STV090x_OFFST_Px_SPY_CNULLPKT_FIELD		5
-#define STV090x_WIDTH_Px_SPY_CNULLPKT_FIELD		1
-#define STV090x_OFFST_Px_SPY_OUTDATA_MODE_FIELD		0
-#define STV090x_WIDTH_Px_SPY_OUTDATA_MODE_FIELD		5
-
-#define STV090x_Px_FSPYOUT(__x)				(0xF5A3 - (__x - 1) * 0x200)
-#define STV090x_P1_FSPYOUT				STV090x_Px_FSPYOUT(1)
-#define STV090x_P2_FSPYOUT				STV090x_Px_FSPYOUT(2)
-#define STV090x_OFFST_Px_FSPY_DIRECT_FIELD		7
-#define STV090x_WIDTH_Px_FSPY_DIRECT_FIELD		1
-#define STV090x_OFFST_Px_STUFF_MODE_FIELD		0
-#define STV090x_WIDTH_Px_STUFF_MODE_FIELD		3
-
-#define STV090x_Px_FSTATUS(__x)				(0xF5A4 - (__x - 1) * 0x200)
-#define STV090x_P1_FSTATUS				STV090x_Px_FSTATUS(1)
-#define STV090x_P2_FSTATUS				STV090x_Px_FSTATUS(2)
-#define STV090x_OFFST_Px_SPY_ENDSIM_FIELD		7
-#define STV090x_WIDTH_Px_SPY_ENDSIM_FIELD		1
-#define STV090x_OFFST_Px_VALID_SIM_FIELD		6
-#define STV090x_WIDTH_Px_VALID_SIM_FIELD		1
-#define STV090x_OFFST_Px_FOUND_SIGNAL_FIELD		5
-#define STV090x_WIDTH_Px_FOUND_SIGNAL_FIELD		1
-#define STV090x_OFFST_Px_DSS_SYNCBYTE_FIELD		4
-#define STV090x_WIDTH_Px_DSS_SYNCBYTE_FIELD		1
-#define STV090x_OFFST_Px_RESULT_STATE_FIELD		0
-#define STV090x_WIDTH_Px_RESULT_STATE_FIELD		4
-
-#define STV090x_Px_FBERCPT4(__x)			(0xF5A8 - (__x - 1) * 0x200)
-#define STV090x_P1_FBERCPT4				STV090x_Px_FBERCPT4(1)
-#define STV090x_P2_FBERCPT4				STV090x_Px_FBERCPT4(2)
-#define STV090x_OFFST_Px_FBERMETER_CPT_FIELD		0
-#define STV090x_WIDTH_Px_FBERMETER_CPT_FIELD		8
-
-#define STV090x_Px_FBERCPT3(__x)			(0xF5A9 - (__x - 1) * 0x200)
-#define STV090x_P1_FBERCPT3				STV090x_Px_FBERCPT3(1)
-#define STV090x_P2_FBERCPT3				STV090x_Px_FBERCPT3(2)
-#define STV090x_OFFST_Px_FBERMETER_CPT_FIELD		0
-#define STV090x_WIDTH_Px_FBERMETER_CPT_FIELD		8
-
-#define STV090x_Px_FBERCPT2(__x)			(0xF5AA - (__x - 1) * 0x200)
-#define STV090x_P1_FBERCPT2				STV090x_Px_FBERCPT2(1)
-#define STV090x_P2_FBERCPT2				STV090x_Px_FBERCPT2(2)
-#define STV090x_OFFST_Px_FBERMETER_CPT_FIELD		0
-#define STV090x_WIDTH_Px_FBERMETER_CPT_FIELD		8
-
-#define STV090x_Px_FBERCPT1(__x)			(0xF5AB - (__x - 1) * 0x200)
-#define STV090x_P1_FBERCPT1				STV090x_Px_FBERCPT1(1)
-#define STV090x_P2_FBERCPT1				STV090x_Px_FBERCPT1(2)
-#define STV090x_OFFST_Px_FBERMETER_CPT_FIELD		0
-#define STV090x_WIDTH_Px_FBERMETER_CPT_FIELD		8
-
-#define STV090x_Px_FBERCPT0(__x)			(0xF5AC - (__x - 1) * 0x200)
-#define STV090x_P1_FBERCPT0				STV090x_Px_FBERCPT0(1)
-#define STV090x_P2_FBERCPT0				STV090x_Px_FBERCPT0(2)
-#define STV090x_OFFST_Px_FBERMETER_CPT_FIELD		0
-#define STV090x_WIDTH_Px_FBERMETER_CPT_FIELD		8
-
-#define STV090x_Px_FBERERRy(__x, __y)			(0xF5AF - (__x - 1) * 0x200 - __y * 0x1)
-#define STV090x_P1_FBERERR0				STV090x_Px_FBERERRy(1, 0)
-#define STV090x_P1_FBERERR1				STV090x_Px_FBERERRy(1, 1)
-#define STV090x_P1_FBERERR2				STV090x_Px_FBERERRy(1, 2)
-#define STV090x_P2_FBERERR0				STV090x_Px_FBERERRy(2, 0)
-#define STV090x_P2_FBERERR1				STV090x_Px_FBERERRy(2, 1)
-#define STV090x_P2_FBERERR2				STV090x_Px_FBERERRy(2, 2)
-#define STV090x_OFFST_Px_FBERMETER_CPT_ERR_FIELD	0
-#define STV090x_WIDTH_Px_FBERMETER_CPT_ERR_FIELD	8
-
-#define STV090x_Px_FSPYBER(__x)				(0xF5B2 - (__x - 1) * 0x200)
-#define STV090x_P1_FSPYBER				STV090x_Px_FSPYBER(1)
-#define STV090x_P2_FSPYBER				STV090x_Px_FSPYBER(2)
-#define STV090x_OFFST_Px_FSPYBER_SYNCBYTE_FIELD		4
-#define STV090x_WIDTH_Px_FSPYBER_SYNCBYTE_FIELD		1
-#define STV090x_OFFST_Px_FSPYBER_UNSYNC_FIELD		3
-#define STV090x_WIDTH_Px_FSPYBER_UNSYNC_FIELD		1
-#define STV090x_OFFST_Px_FSPYBER_CTIME_FIELD		0
-#define STV090x_WIDTH_Px_FSPYBER_CTIME_FIELD		3
-
-#define STV090x_RCCFGH					0xf600
-
-#define STV090x_TSGENERAL				0xF630
-#define STV090x_OFFST_Px_MUXSTREAM_OUT_FIELD		3
-#define STV090x_WIDTH_Px_MUXSTREAM_OUT_FIELD		1
-#define STV090x_OFFST_Px_TSFIFO_PERMPARAL_FIELD		1
-#define STV090x_WIDTH_Px_TSFIFO_PERMPARAL_FIELD		2
-
-#define STV090x_TSGENERAL1X				0xf670
-#define STV090x_CFGEXT					0xfa80
-
-#define STV090x_TSTRES0					0xFF11
-#define STV090x_OFFST_FRESFEC_FIELD			7
-#define STV090x_WIDTH_FRESFEC_FIELD			1
-
-#define STV090x_Px_TSTDISRX(__x)			(0xFF67 - (__x - 1) * 0x2)
-#define STV090x_P1_TSTDISRX				STV090x_Px_TSTDISRX(1)
-#define STV090x_P2_TSTDISRX				STV090x_Px_TSTDISRX(2)
-#define STV090x_OFFST_Px_TSTDISRX_SELECT_FIELD		3
-#define STV090x_WIDTH_Px_TSTDISRX_SELECT_FIELD		1
-
-#endif /* __STV090x_REG_H */
diff --git a/drivers/media/dvb/frontends/stv6110.c b/drivers/media/dvb/frontends/stv6110.c
deleted file mode 100644
index 20b5fa9..0000000
--- a/drivers/media/dvb/frontends/stv6110.c
+++ /dev/null
@@ -1,451 +0,0 @@
-/*
- * 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/slab.h>
-#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 clk_div;
-	u8 gain;
-	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[] = {
-		{
-			.addr	= priv->i2c_address,
-			.flags	= 0,
-			.buf	= reg,
-			.len	= 1,
-		}, {
-			.addr	= priv->i2c_address,
-			.flags	= I2C_M_RD,
-			.buf	= regs,
-			.len	= len,
-		},
-	};
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-
-	rc = i2c_transfer(priv->i2c, msg, 2);
-	if (rc != 2)
-		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);
-
-	/* divisor value for the output clock */
-	priv->regs[RSTV6110_CTRL2] &= ~0xc0;
-	priv->regs[RSTV6110_CTRL2] |= (priv->clk_div << 6);
-
-	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;
-
-	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;
-
-	priv->regs[RSTV6110_CTRL2] &= ~0x0f;
-	priv->regs[RSTV6110_CTRL2] |= (priv->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 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;
-
-	/* divisor value for the output clock */
-	reg0[2] &= ~0xc0;
-	reg0[2] |= (config->clk_div << 6);
-
-	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;
-	priv->clk_div = config->clk_div;
-	priv->gain = config->gain;
-
-	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
deleted file mode 100644
index fe71bba..0000000
--- a/drivers/media/dvb/frontends/stv6110.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * 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;
-	u8 gain;
-	u8 clk_div;	/* divisor value for the output clock */
-};
-
-#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/stv6110x.c b/drivers/media/dvb/frontends/stv6110x.c
deleted file mode 100644
index f36cab1..0000000
--- a/drivers/media/dvb/frontends/stv6110x.c
+++ /dev/null
@@ -1,405 +0,0 @@
-/*
-	STV6110(A) Silicon tuner driver
-
-	Copyright (C) Manu Abraham <abraham.manu@gmail.com>
-
-	Copyright (C) ST Microelectronics
-
-	This program is free software; you can redistribute it and/or modify
-	it under the terms of the 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/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-
-#include "dvb_frontend.h"
-
-#include "stv6110x_reg.h"
-#include "stv6110x.h"
-#include "stv6110x_priv.h"
-
-static unsigned int verbose;
-module_param(verbose, int, 0644);
-MODULE_PARM_DESC(verbose, "Set Verbosity level");
-
-static int stv6110x_read_reg(struct stv6110x_state *stv6110x, u8 reg, u8 *data)
-{
-	int ret;
-	const struct stv6110x_config *config = stv6110x->config;
-	u8 b0[] = { reg };
-	u8 b1[] = { 0 };
-	struct i2c_msg msg[] = {
-		{ .addr = config->addr, .flags = 0, 	   .buf = b0, .len = 1 },
-		{ .addr = config->addr, .flags = I2C_M_RD, .buf = b1, .len = 1 }
-	};
-
-	ret = i2c_transfer(stv6110x->i2c, msg, 2);
-	if (ret != 2) {
-		dprintk(FE_ERROR, 1, "I/O Error");
-		return -EREMOTEIO;
-	}
-	*data = b1[0];
-
-	return 0;
-}
-
-static int stv6110x_write_regs(struct stv6110x_state *stv6110x, int start, u8 data[], int len)
-{
-	int ret;
-	const struct stv6110x_config *config = stv6110x->config;
-	u8 buf[len + 1];
-	struct i2c_msg msg = {
-		.addr = config->addr,
-		.flags = 0,
-		.buf = buf,
-		.len = len + 1
-	};
-
-	if (start + len > 8)
-		return -EINVAL;
-
-	buf[0] = start;
-	memcpy(&buf[1], data, len);
-
-	ret = i2c_transfer(stv6110x->i2c, &msg, 1);
-	if (ret != 1) {
-		dprintk(FE_ERROR, 1, "I/O Error");
-		return -EREMOTEIO;
-	}
-
-	return 0;
-}
-
-static int stv6110x_write_reg(struct stv6110x_state *stv6110x, u8 reg, u8 data)
-{
-	return stv6110x_write_regs(stv6110x, reg, &data, 1);
-}
-
-static int stv6110x_init(struct dvb_frontend *fe)
-{
-	struct stv6110x_state *stv6110x = fe->tuner_priv;
-	int ret;
-
-	ret = stv6110x_write_regs(stv6110x, 0, stv6110x->regs,
-				  ARRAY_SIZE(stv6110x->regs));
-	if (ret < 0) {
-		dprintk(FE_ERROR, 1, "Initialization failed");
-		return -1;
-	}
-
-	return 0;
-}
-
-static int stv6110x_set_frequency(struct dvb_frontend *fe, u32 frequency)
-{
-	struct stv6110x_state *stv6110x = fe->tuner_priv;
-	u32 rDiv, divider;
-	s32 pVal, pCalc, rDivOpt = 0, pCalcOpt = 1000;
-	u8 i;
-
-	STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL1], CTRL1_K, (REFCLOCK_MHz - 16));
-
-	if (frequency <= 1023000) {
-		STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_DIV4SEL, 1);
-		STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_PRESC32_ON, 0);
-		pVal = 40;
-	} else if (frequency <= 1300000) {
-		STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_DIV4SEL, 1);
-		STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_PRESC32_ON, 1);
-		pVal = 40;
-	} else if (frequency <= 2046000) {
-		STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_DIV4SEL, 0);
-		STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_PRESC32_ON, 0);
-		pVal = 20;
-	} else {
-		STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_DIV4SEL, 0);
-		STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_PRESC32_ON, 1);
-		pVal = 20;
-	}
-
-	for (rDiv = 0; rDiv <= 3; rDiv++) {
-		pCalc = (REFCLOCK_kHz / 100) / R_DIV(rDiv);
-
-		if ((abs((s32)(pCalc - pVal))) < (abs((s32)(pCalcOpt - pVal))))
-			rDivOpt = rDiv;
-
-		pCalcOpt = (REFCLOCK_kHz / 100) / R_DIV(rDivOpt);
-	}
-
-	divider = (frequency * R_DIV(rDivOpt) * pVal) / REFCLOCK_kHz;
-	divider = (divider + 5) / 10;
-
-	STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_R_DIV, rDivOpt);
-	STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG1], TNG1_N_DIV_11_8, MSB(divider));
-	STV6110x_SETFIELD(stv6110x->regs[STV6110x_TNG0], TNG0_N_DIV_7_0, LSB(divider));
-
-	/* VCO Auto calibration */
-	STV6110x_SETFIELD(stv6110x->regs[STV6110x_STAT1], STAT1_CALVCO_STRT, 1);
-
-	stv6110x_write_reg(stv6110x, STV6110x_CTRL1, stv6110x->regs[STV6110x_CTRL1]);
-	stv6110x_write_reg(stv6110x, STV6110x_TNG1, stv6110x->regs[STV6110x_TNG1]);
-	stv6110x_write_reg(stv6110x, STV6110x_TNG0, stv6110x->regs[STV6110x_TNG0]);
-	stv6110x_write_reg(stv6110x, STV6110x_STAT1, stv6110x->regs[STV6110x_STAT1]);
-
-	for (i = 0; i < TRIALS; i++) {
-		stv6110x_read_reg(stv6110x, STV6110x_STAT1, &stv6110x->regs[STV6110x_STAT1]);
-		if (!STV6110x_GETFIELD(STAT1_CALVCO_STRT, stv6110x->regs[STV6110x_STAT1]))
-				break;
-		msleep(1);
-	}
-
-	return 0;
-}
-
-static int stv6110x_get_frequency(struct dvb_frontend *fe, u32 *frequency)
-{
-	struct stv6110x_state *stv6110x = fe->tuner_priv;
-
-	stv6110x_read_reg(stv6110x, STV6110x_TNG1, &stv6110x->regs[STV6110x_TNG1]);
-	stv6110x_read_reg(stv6110x, STV6110x_TNG0, &stv6110x->regs[STV6110x_TNG0]);
-
-	*frequency = (MAKEWORD16(STV6110x_GETFIELD(TNG1_N_DIV_11_8, stv6110x->regs[STV6110x_TNG1]),
-				 STV6110x_GETFIELD(TNG0_N_DIV_7_0, stv6110x->regs[STV6110x_TNG0]))) * REFCLOCK_kHz;
-
-	*frequency /= (1 << (STV6110x_GETFIELD(TNG1_R_DIV, stv6110x->regs[STV6110x_TNG1]) +
-			     STV6110x_GETFIELD(TNG1_DIV4SEL, stv6110x->regs[STV6110x_TNG1])));
-
-	*frequency >>= 2;
-
-	return 0;
-}
-
-static int stv6110x_set_bandwidth(struct dvb_frontend *fe, u32 bandwidth)
-{
-	struct stv6110x_state *stv6110x = fe->tuner_priv;
-	u32 halfbw;
-	u8 i;
-
-	halfbw = bandwidth >> 1;
-
-	if (halfbw > 36000000)
-		STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL3], CTRL3_CF, 31); /* LPF */
-	else if (halfbw < 5000000)
-		STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL3], CTRL3_CF, 0); /* LPF */
-	else
-		STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL3], CTRL3_CF, ((halfbw / 1000000) - 5)); /* LPF */
-
-
-	STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL3], CTRL3_RCCLK_OFF, 0x0); /* cal. clk activated */
-	STV6110x_SETFIELD(stv6110x->regs[STV6110x_STAT1], STAT1_CALRC_STRT, 0x1); /* LPF auto cal */
-
-	stv6110x_write_reg(stv6110x, STV6110x_CTRL3, stv6110x->regs[STV6110x_CTRL3]);
-	stv6110x_write_reg(stv6110x, STV6110x_STAT1, stv6110x->regs[STV6110x_STAT1]);
-
-	for (i = 0; i < TRIALS; i++) {
-		stv6110x_read_reg(stv6110x, STV6110x_STAT1, &stv6110x->regs[STV6110x_STAT1]);
-		if (!STV6110x_GETFIELD(STAT1_CALRC_STRT, stv6110x->regs[STV6110x_STAT1]))
-			break;
-		msleep(1);
-	}
-	STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL3], CTRL3_RCCLK_OFF, 0x1); /* cal. done */
-	stv6110x_write_reg(stv6110x, STV6110x_CTRL3, stv6110x->regs[STV6110x_CTRL3]);
-
-	return 0;
-}
-
-static int stv6110x_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
-{
-	struct stv6110x_state *stv6110x = fe->tuner_priv;
-
-	stv6110x_read_reg(stv6110x, STV6110x_CTRL3, &stv6110x->regs[STV6110x_CTRL3]);
-	*bandwidth = (STV6110x_GETFIELD(CTRL3_CF, stv6110x->regs[STV6110x_CTRL3]) + 5) * 2000000;
-
-	return 0;
-}
-
-static int stv6110x_set_refclock(struct dvb_frontend *fe, u32 refclock)
-{
-	struct stv6110x_state *stv6110x = fe->tuner_priv;
-
-	/* setup divider */
-	switch (refclock) {
-	default:
-	case 1:
-		STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 0);
-		break;
-	case 2:
-		STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 1);
-		break;
-	case 4:
-		STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 2);
-		break;
-	case 8:
-	case 0:
-		STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 3);
-		break;
-	}
-	stv6110x_write_reg(stv6110x, STV6110x_CTRL2, stv6110x->regs[STV6110x_CTRL2]);
-
-	return 0;
-}
-
-static int stv6110x_get_bbgain(struct dvb_frontend *fe, u32 *gain)
-{
-	struct stv6110x_state *stv6110x = fe->tuner_priv;
-
-	stv6110x_read_reg(stv6110x, STV6110x_CTRL2, &stv6110x->regs[STV6110x_CTRL2]);
-	*gain = 2 * STV6110x_GETFIELD(CTRL2_BBGAIN, stv6110x->regs[STV6110x_CTRL2]);
-
-	return 0;
-}
-
-static int stv6110x_set_bbgain(struct dvb_frontend *fe, u32 gain)
-{
-	struct stv6110x_state *stv6110x = fe->tuner_priv;
-
-	STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_BBGAIN, gain / 2);
-	stv6110x_write_reg(stv6110x, STV6110x_CTRL2, stv6110x->regs[STV6110x_CTRL2]);
-
-	return 0;
-}
-
-static int stv6110x_set_mode(struct dvb_frontend *fe, enum tuner_mode mode)
-{
-	struct stv6110x_state *stv6110x = fe->tuner_priv;
-	int ret;
-
-	switch (mode) {
-	case TUNER_SLEEP:
-		STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL1], CTRL1_SYN, 0);
-		STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL1], CTRL1_RX, 0);
-		STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL1], CTRL1_LPT, 0);
-		break;
-
-	case TUNER_WAKE:
-		STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL1], CTRL1_SYN, 1);
-		STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL1], CTRL1_RX, 1);
-		STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL1], CTRL1_LPT, 1);
-		break;
-	}
-
-	ret = stv6110x_write_reg(stv6110x, STV6110x_CTRL1, stv6110x->regs[STV6110x_CTRL1]);
-	if (ret < 0) {
-		dprintk(FE_ERROR, 1, "I/O Error");
-		return -EIO;
-	}
-
-	return 0;
-}
-
-static int stv6110x_sleep(struct dvb_frontend *fe)
-{
-	if (fe->tuner_priv)
-		return stv6110x_set_mode(fe, TUNER_SLEEP);
-
-	return 0;
-}
-
-static int stv6110x_get_status(struct dvb_frontend *fe, u32 *status)
-{
-	struct stv6110x_state *stv6110x = fe->tuner_priv;
-
-	stv6110x_read_reg(stv6110x, STV6110x_STAT1, &stv6110x->regs[STV6110x_STAT1]);
-
-	if (STV6110x_GETFIELD(STAT1_LOCK, stv6110x->regs[STV6110x_STAT1]))
-		*status = TUNER_PHASELOCKED;
-	else
-		*status = 0;
-
-	return 0;
-}
-
-
-static int stv6110x_release(struct dvb_frontend *fe)
-{
-	struct stv6110x_state *stv6110x = fe->tuner_priv;
-
-	fe->tuner_priv = NULL;
-	kfree(stv6110x);
-
-	return 0;
-}
-
-static struct dvb_tuner_ops stv6110x_ops = {
-	.info = {
-		.name		= "STV6110(A) Silicon Tuner",
-		.frequency_min	=  950000,
-		.frequency_max	= 2150000,
-		.frequency_step	= 0,
-	},
-	.release		= stv6110x_release
-};
-
-static struct stv6110x_devctl stv6110x_ctl = {
-	.tuner_init		= stv6110x_init,
-	.tuner_sleep		= stv6110x_sleep,
-	.tuner_set_mode		= stv6110x_set_mode,
-	.tuner_set_frequency	= stv6110x_set_frequency,
-	.tuner_get_frequency	= stv6110x_get_frequency,
-	.tuner_set_bandwidth	= stv6110x_set_bandwidth,
-	.tuner_get_bandwidth	= stv6110x_get_bandwidth,
-	.tuner_set_bbgain	= stv6110x_set_bbgain,
-	.tuner_get_bbgain	= stv6110x_get_bbgain,
-	.tuner_set_refclk	= stv6110x_set_refclock,
-	.tuner_get_status	= stv6110x_get_status,
-};
-
-struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe,
-					const struct stv6110x_config *config,
-					struct i2c_adapter *i2c)
-{
-	struct stv6110x_state *stv6110x;
-	u8 default_regs[] = {0x07, 0x11, 0xdc, 0x85, 0x17, 0x01, 0xe6, 0x1e};
-
-	stv6110x = kzalloc(sizeof (struct stv6110x_state), GFP_KERNEL);
-	if (!stv6110x)
-		return NULL;
-
-	stv6110x->i2c		= i2c;
-	stv6110x->config	= config;
-	stv6110x->devctl	= &stv6110x_ctl;
-	memcpy(stv6110x->regs, default_regs, 8);
-
-	/* setup divider */
-	switch (stv6110x->config->clk_div) {
-	default:
-	case 1:
-		STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 0);
-		break;
-	case 2:
-		STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 1);
-		break;
-	case 4:
-		STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 2);
-		break;
-	case 8:
-	case 0:
-		STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 3);
-		break;
-	}
-
-	fe->tuner_priv		= stv6110x;
-	fe->ops.tuner_ops	= stv6110x_ops;
-
-	printk(KERN_INFO "%s: Attaching STV6110x\n", __func__);
-	return stv6110x->devctl;
-}
-EXPORT_SYMBOL(stv6110x_attach);
-
-MODULE_AUTHOR("Manu Abraham");
-MODULE_DESCRIPTION("STV6110x Silicon tuner");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/stv6110x.h b/drivers/media/dvb/frontends/stv6110x.h
deleted file mode 100644
index 47516753..0000000
--- a/drivers/media/dvb/frontends/stv6110x.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
-	STV6110(A) Silicon tuner driver
-
-	Copyright (C) Manu Abraham <abraham.manu@gmail.com>
-
-	Copyright (C) ST Microelectronics
-
-	This program is free software; you can redistribute it and/or modify
-	it under the terms of the 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 __STV6110x_H
-#define __STV6110x_H
-
-struct stv6110x_config {
-	u8	addr;
-	u32	refclk;
-	u8	clk_div; /* divisor value for the output clock */
-};
-
-enum tuner_mode {
-	TUNER_SLEEP = 1,
-	TUNER_WAKE,
-};
-
-enum tuner_status {
-	TUNER_PHASELOCKED = 1,
-};
-
-struct stv6110x_devctl {
-	int (*tuner_init) (struct dvb_frontend *fe);
-	int (*tuner_sleep) (struct dvb_frontend *fe);
-	int (*tuner_set_mode) (struct dvb_frontend *fe, enum tuner_mode mode);
-	int (*tuner_set_frequency) (struct dvb_frontend *fe, u32 frequency);
-	int (*tuner_get_frequency) (struct dvb_frontend *fe, u32 *frequency);
-	int (*tuner_set_bandwidth) (struct dvb_frontend *fe, u32 bandwidth);
-	int (*tuner_get_bandwidth) (struct dvb_frontend *fe, u32 *bandwidth);
-	int (*tuner_set_bbgain) (struct dvb_frontend *fe, u32 gain);
-	int (*tuner_get_bbgain) (struct dvb_frontend *fe, u32 *gain);
-	int (*tuner_set_refclk)  (struct dvb_frontend *fe, u32 refclk);
-	int (*tuner_get_status) (struct dvb_frontend *fe, u32 *status);
-};
-
-
-#if defined(CONFIG_DVB_STV6110x) || (defined(CONFIG_DVB_STV6110x_MODULE) && defined(MODULE))
-
-extern struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe,
-					       const struct stv6110x_config *config,
-					       struct i2c_adapter *i2c);
-
-#else
-static inline struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe,
-						      const struct stv6110x_config *config,
-						      struct i2c_adapter *i2c)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-
-#endif /* CONFIG_DVB_STV6110x */
-
-#endif /* __STV6110x_H */
diff --git a/drivers/media/dvb/frontends/stv6110x_priv.h b/drivers/media/dvb/frontends/stv6110x_priv.h
deleted file mode 100644
index 0ec936a..0000000
--- a/drivers/media/dvb/frontends/stv6110x_priv.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
-	STV6110(A) Silicon tuner driver
-
-	Copyright (C) Manu Abraham <abraham.manu@gmail.com>
-
-	Copyright (C) ST Microelectronics
-
-	This program is free software; you can redistribute it and/or modify
-	it under the terms of the 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 __STV6110x_PRIV_H
-#define __STV6110x_PRIV_H
-
-#define FE_ERROR				0
-#define FE_NOTICE				1
-#define FE_INFO					2
-#define FE_DEBUG				3
-#define FE_DEBUGREG				4
-
-#define dprintk(__y, __z, format, arg...) do {						\
-	if (__z) {									\
-		if	((verbose > FE_ERROR) && (verbose > __y))			\
-			printk(KERN_ERR "%s: " format "\n", __func__ , ##arg);		\
-		else if	((verbose > FE_NOTICE) && (verbose > __y))			\
-			printk(KERN_NOTICE "%s: " format "\n", __func__ , ##arg);	\
-		else if ((verbose > FE_INFO) && (verbose > __y))			\
-			printk(KERN_INFO "%s: " format "\n", __func__ , ##arg);		\
-		else if ((verbose > FE_DEBUG) && (verbose > __y))			\
-			printk(KERN_DEBUG "%s: " format "\n", __func__ , ##arg);	\
-	} else {									\
-		if (verbose > __y)							\
-			printk(format, ##arg);						\
-	}										\
-} while (0)
-
-
-#define STV6110x_SETFIELD(mask, bitf, val)				\
-	(mask = (mask & (~(((1 << STV6110x_WIDTH_##bitf) - 1) <<	\
-				  STV6110x_OFFST_##bitf))) | 		\
-			  (val << STV6110x_OFFST_##bitf))
-
-#define STV6110x_GETFIELD(bitf, val)					\
-	((val >> STV6110x_OFFST_##bitf) & 				\
-	((1 << STV6110x_WIDTH_##bitf) - 1))
-
-#define MAKEWORD16(a, b)			(((a) << 8) | (b))
-
-#define LSB(x)					((x & 0xff))
-#define MSB(y)					((y >> 8) & 0xff)
-
-#define TRIALS					10
-#define R_DIV(__div)				(1 << (__div + 1))
-#define REFCLOCK_kHz				(stv6110x->config->refclk /    1000)
-#define REFCLOCK_MHz				(stv6110x->config->refclk / 1000000)
-
-struct stv6110x_state {
-	struct i2c_adapter		*i2c;
-	const struct stv6110x_config	*config;
-	u8 				regs[8];
-
-	struct stv6110x_devctl		*devctl;
-};
-
-#endif /* __STV6110x_PRIV_H */
diff --git a/drivers/media/dvb/frontends/stv6110x_reg.h b/drivers/media/dvb/frontends/stv6110x_reg.h
deleted file mode 100644
index 93e5c70..0000000
--- a/drivers/media/dvb/frontends/stv6110x_reg.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
-	STV6110(A) Silicon tuner driver
-
-	Copyright (C) Manu Abraham <abraham.manu@gmail.com>
-
-	Copyright (C) ST Microelectronics
-
-	This program is free software; you can redistribute it and/or modify
-	it under the terms of the 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 __STV6110x_REG_H
-#define __STV6110x_REG_H
-
-#define STV6110x_CTRL1				0x00
-#define STV6110x_OFFST_CTRL1_K			3
-#define STV6110x_WIDTH_CTRL1_K			5
-#define STV6110x_OFFST_CTRL1_LPT		2
-#define STV6110x_WIDTH_CTRL1_LPT		1
-#define STV6110x_OFFST_CTRL1_RX			1
-#define STV6110x_WIDTH_CTRL1_RX			1
-#define STV6110x_OFFST_CTRL1_SYN		0
-#define STV6110x_WIDTH_CTRL1_SYN		1
-
-#define STV6110x_CTRL2				0x01
-#define STV6110x_OFFST_CTRL2_CO_DIV		6
-#define STV6110x_WIDTH_CTRL2_CO_DIV		2
-#define STV6110x_OFFST_CTRL2_RSVD		5
-#define STV6110x_WIDTH_CTRL2_RSVD		1
-#define STV6110x_OFFST_CTRL2_REFOUT_SEL		4
-#define STV6110x_WIDTH_CTRL2_REFOUT_SEL		1
-#define STV6110x_OFFST_CTRL2_BBGAIN		0
-#define STV6110x_WIDTH_CTRL2_BBGAIN		4
-
-#define STV6110x_TNG0				0x02
-#define STV6110x_OFFST_TNG0_N_DIV_7_0		0
-#define STV6110x_WIDTH_TNG0_N_DIV_7_0		8
-
-#define STV6110x_TNG1				0x03
-#define STV6110x_OFFST_TNG1_R_DIV		6
-#define STV6110x_WIDTH_TNG1_R_DIV		2
-#define STV6110x_OFFST_TNG1_PRESC32_ON		5
-#define STV6110x_WIDTH_TNG1_PRESC32_ON		1
-#define STV6110x_OFFST_TNG1_DIV4SEL		4
-#define STV6110x_WIDTH_TNG1_DIV4SEL		1
-#define STV6110x_OFFST_TNG1_N_DIV_11_8		0
-#define STV6110x_WIDTH_TNG1_N_DIV_11_8		4
-
-
-#define STV6110x_CTRL3				0x04
-#define STV6110x_OFFST_CTRL3_DCLOOP_OFF		7
-#define STV6110x_WIDTH_CTRL3_DCLOOP_OFF		1
-#define STV6110x_OFFST_CTRL3_RCCLK_OFF		6
-#define STV6110x_WIDTH_CTRL3_RCCLK_OFF		1
-#define STV6110x_OFFST_CTRL3_ICP		5
-#define STV6110x_WIDTH_CTRL3_ICP		1
-#define STV6110x_OFFST_CTRL3_CF			0
-#define STV6110x_WIDTH_CTRL3_CF			5
-
-#define STV6110x_STAT1				0x05
-#define STV6110x_OFFST_STAT1_CALVCO_STRT	2
-#define STV6110x_WIDTH_STAT1_CALVCO_STRT	1
-#define STV6110x_OFFST_STAT1_CALRC_STRT		1
-#define STV6110x_WIDTH_STAT1_CALRC_STRT		1
-#define STV6110x_OFFST_STAT1_LOCK		0
-#define STV6110x_WIDTH_STAT1_LOCK		1
-
-#define STV6110x_STAT2				0x06
-#define STV6110x_STAT3				0x07
-
-#endif /* __STV6110x_REG_H */
diff --git a/drivers/media/dvb/frontends/tda10021.c b/drivers/media/dvb/frontends/tda10021.c
deleted file mode 100644
index 1bff7f4..0000000
--- a/drivers/media/dvb/frontends/tda10021.c
+++ /dev/null
@@ -1,528 +0,0 @@
-/*
-    TDA10021  - Single Chip Cable Channel Receiver driver module
-	       used on the Siemens DVB-C cards
-
-    Copyright (C) 1999 Convergence Integrated Media GmbH <ralph@convergence.de>
-    Copyright (C) 2004 Markus Schulz <msc@antzsystem.de>
-		   Support for TDA10021
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the 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/delay.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-
-#include "dvb_frontend.h"
-#include "tda1002x.h"
-
-
-struct tda10021_state {
-	struct i2c_adapter* i2c;
-	/* configuration settings */
-	const struct tda1002x_config* config;
-	struct dvb_frontend frontend;
-
-	u8 pwm;
-	u8 reg0;
-};
-
-
-#if 0
-#define dprintk(x...) printk(x)
-#else
-#define dprintk(x...)
-#endif
-
-static int verbose;
-
-#define XIN 57840000UL
-
-#define FIN (XIN >> 4)
-
-static int tda10021_inittab_size = 0x40;
-static u8 tda10021_inittab[0x40]=
-{
-	0x73, 0x6a, 0x23, 0x0a, 0x02, 0x37, 0x77, 0x1a,
-	0x37, 0x6a, 0x17, 0x8a, 0x1e, 0x86, 0x43, 0x40,
-	0xb8, 0x3f, 0xa1, 0x00, 0xcd, 0x01, 0x00, 0xff,
-	0x11, 0x00, 0x7c, 0x31, 0x30, 0x20, 0x00, 0x00,
-	0x02, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x00, 0x00,
-	0x07, 0x00, 0x33, 0x11, 0x0d, 0x95, 0x08, 0x58,
-	0x00, 0x00, 0x80, 0x00, 0x80, 0xff, 0x00, 0x00,
-	0x04, 0x2d, 0x2f, 0xff, 0x00, 0x00, 0x00, 0x00,
-};
-
-static int _tda10021_writereg (struct tda10021_state* state, u8 reg, u8 data)
-{
-	u8 buf[] = { reg, data };
-	struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 };
-	int ret;
-
-	ret = i2c_transfer (state->i2c, &msg, 1);
-	if (ret != 1)
-		printk("DVB: TDA10021(%d): %s, writereg error "
-			"(reg == 0x%02x, val == 0x%02x, ret == %i)\n",
-			state->frontend.dvb->num, __func__, reg, data, ret);
-
-	msleep(10);
-	return (ret != 1) ? -EREMOTEIO : 0;
-}
-
-static u8 tda10021_readreg (struct tda10021_state* state, u8 reg)
-{
-	u8 b0 [] = { reg };
-	u8 b1 [] = { 0 };
-	struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 },
-				  { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } };
-	int ret;
-
-	ret = i2c_transfer (state->i2c, msg, 2);
-	// Don't print an error message if the id is read.
-	if (ret != 2 && reg != 0x1a)
-		printk("DVB: TDA10021: %s: readreg error (ret == %i)\n",
-				__func__, ret);
-	return b1[0];
-}
-
-//get access to tuner
-static int lock_tuner(struct tda10021_state* state)
-{
-	u8 buf[2] = { 0x0f, tda10021_inittab[0x0f] | 0x80 };
-	struct i2c_msg msg = {.addr=state->config->demod_address, .flags=0, .buf=buf, .len=2};
-
-	if(i2c_transfer(state->i2c, &msg, 1) != 1)
-	{
-		printk("tda10021: lock tuner fails\n");
-		return -EREMOTEIO;
-	}
-	return 0;
-}
-
-//release access from tuner
-static int unlock_tuner(struct tda10021_state* state)
-{
-	u8 buf[2] = { 0x0f, tda10021_inittab[0x0f] & 0x7f };
-	struct i2c_msg msg_post={.addr=state->config->demod_address, .flags=0, .buf=buf, .len=2};
-
-	if(i2c_transfer(state->i2c, &msg_post, 1) != 1)
-	{
-		printk("tda10021: unlock tuner fails\n");
-		return -EREMOTEIO;
-	}
-	return 0;
-}
-
-static int tda10021_setup_reg0 (struct tda10021_state* state, u8 reg0,
-				fe_spectral_inversion_t inversion)
-{
-	reg0 |= state->reg0 & 0x63;
-
-	if ((INVERSION_ON == inversion) ^ (state->config->invert == 0))
-		reg0 &= ~0x20;
-	else
-		reg0 |= 0x20;
-
-	_tda10021_writereg (state, 0x00, reg0 & 0xfe);
-	_tda10021_writereg (state, 0x00, reg0 | 0x01);
-
-	state->reg0 = reg0;
-	return 0;
-}
-
-static int tda10021_set_symbolrate (struct tda10021_state* state, u32 symbolrate)
-{
-	s32 BDR;
-	s32 BDRI;
-	s16 SFIL=0;
-	u16 NDEC = 0;
-	u32 tmp, ratio;
-
-	if (symbolrate > XIN/2)
-		symbolrate = XIN/2;
-	if (symbolrate < 500000)
-		symbolrate = 500000;
-
-	if (symbolrate < XIN/16) NDEC = 1;
-	if (symbolrate < XIN/32) NDEC = 2;
-	if (symbolrate < XIN/64) NDEC = 3;
-
-	if (symbolrate < (u32)(XIN/12.3)) SFIL = 1;
-	if (symbolrate < (u32)(XIN/16))	 SFIL = 0;
-	if (symbolrate < (u32)(XIN/24.6)) SFIL = 1;
-	if (symbolrate < (u32)(XIN/32))	 SFIL = 0;
-	if (symbolrate < (u32)(XIN/49.2)) SFIL = 1;
-	if (symbolrate < (u32)(XIN/64))	 SFIL = 0;
-	if (symbolrate < (u32)(XIN/98.4)) SFIL = 1;
-
-	symbolrate <<= NDEC;
-	ratio = (symbolrate << 4) / FIN;
-	tmp =  ((symbolrate << 4) % FIN) << 8;
-	ratio = (ratio << 8) + tmp / FIN;
-	tmp = (tmp % FIN) << 8;
-	ratio = (ratio << 8) + DIV_ROUND_CLOSEST(tmp, FIN);
-
-	BDR = ratio;
-	BDRI = (((XIN << 5) / symbolrate) + 1) / 2;
-
-	if (BDRI > 0xFF)
-		BDRI = 0xFF;
-
-	SFIL = (SFIL << 4) | tda10021_inittab[0x0E];
-
-	NDEC = (NDEC << 6) | tda10021_inittab[0x03];
-
-	_tda10021_writereg (state, 0x03, NDEC);
-	_tda10021_writereg (state, 0x0a, BDR&0xff);
-	_tda10021_writereg (state, 0x0b, (BDR>> 8)&0xff);
-	_tda10021_writereg (state, 0x0c, (BDR>>16)&0x3f);
-
-	_tda10021_writereg (state, 0x0d, BDRI);
-	_tda10021_writereg (state, 0x0e, SFIL);
-
-	return 0;
-}
-
-static int tda10021_init (struct dvb_frontend *fe)
-{
-	struct tda10021_state* state = fe->demodulator_priv;
-	int i;
-
-	dprintk("DVB: TDA10021(%d): init chip\n", fe->adapter->num);
-
-	//_tda10021_writereg (fe, 0, 0);
-
-	for (i=0; i<tda10021_inittab_size; i++)
-		_tda10021_writereg (state, i, tda10021_inittab[i]);
-
-	_tda10021_writereg (state, 0x34, state->pwm);
-
-	//Comment by markus
-	//0x2A[3-0] == PDIV -> P multiplaying factor (P=PDIV+1)(default 0)
-	//0x2A[4] == BYPPLL -> Power down mode (default 1)
-	//0x2A[5] == LCK -> PLL Lock Flag
-	//0x2A[6] == POLAXIN -> Polarity of the input reference clock (default 0)
-
-	//Activate PLL
-	_tda10021_writereg(state, 0x2a, tda10021_inittab[0x2a] & 0xef);
-	return 0;
-}
-
-struct qam_params {
-	u8 conf, agcref, lthr, mseth, aref;
-};
-
-static int tda10021_set_parameters(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	u32 delsys  = c->delivery_system;
-	unsigned qam = c->modulation;
-	bool is_annex_c;
-	u32 reg0x3d;
-	struct tda10021_state* state = fe->demodulator_priv;
-	static const struct qam_params qam_params[] = {
-		/* Modulation  Conf  AGCref  LTHR  MSETH  AREF */
-		[QPSK]	   = { 0x14, 0x78,   0x78, 0x8c,  0x96 },
-		[QAM_16]   = { 0x00, 0x8c,   0x87, 0xa2,  0x91 },
-		[QAM_32]   = { 0x04, 0x8c,   0x64, 0x74,  0x96 },
-		[QAM_64]   = { 0x08, 0x6a,   0x46, 0x43,  0x6a },
-		[QAM_128]  = { 0x0c, 0x78,   0x36, 0x34,  0x7e },
-		[QAM_256]  = { 0x10, 0x5c,   0x26, 0x23,  0x6b },
-	};
-
-	switch (delsys) {
-	case SYS_DVBC_ANNEX_A:
-		is_annex_c = false;
-		break;
-	case SYS_DVBC_ANNEX_C:
-		is_annex_c = true;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	/*
-	 * gcc optimizes the code bellow the same way as it would code:
-	 *           "if (qam > 5) return -EINVAL;"
-	 * Yet, the code is clearer, as it shows what QAM standards are
-	 * supported by the driver, and avoids the usage of magic numbers on
-	 * it.
-	 */
-	switch (qam) {
-	case QPSK:
-	case QAM_16:
-	case QAM_32:
-	case QAM_64:
-	case QAM_128:
-	case QAM_256:
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	if (c->inversion != INVERSION_ON && c->inversion != INVERSION_OFF)
-		return -EINVAL;
-
-	/*printk("tda10021: set frequency to %d qam=%d symrate=%d\n", p->frequency,qam,p->symbol_rate);*/
-
-	if (fe->ops.tuner_ops.set_params) {
-		fe->ops.tuner_ops.set_params(fe);
-		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
-	}
-
-	tda10021_set_symbolrate(state, c->symbol_rate);
-	_tda10021_writereg(state, 0x34, state->pwm);
-
-	_tda10021_writereg(state, 0x01, qam_params[qam].agcref);
-	_tda10021_writereg(state, 0x05, qam_params[qam].lthr);
-	_tda10021_writereg(state, 0x08, qam_params[qam].mseth);
-	_tda10021_writereg(state, 0x09, qam_params[qam].aref);
-
-	/*
-	 * Bit 0 == 0 means roll-off = 0.15 (Annex A)
-	 *	 == 1 means roll-off = 0.13 (Annex C)
-	 */
-	reg0x3d = tda10021_readreg (state, 0x3d);
-	if (is_annex_c)
-		_tda10021_writereg (state, 0x3d, 0x01 | reg0x3d);
-	else
-		_tda10021_writereg (state, 0x3d, 0xfe & reg0x3d);
-	tda10021_setup_reg0(state, qam_params[qam].conf, c->inversion);
-
-	return 0;
-}
-
-static int tda10021_read_status(struct dvb_frontend* fe, fe_status_t* status)
-{
-	struct tda10021_state* state = fe->demodulator_priv;
-	int sync;
-
-	*status = 0;
-	//0x11[0] == EQALGO -> Equalizer algorithms state
-	//0x11[1] == CARLOCK -> Carrier locked
-	//0x11[2] == FSYNC -> Frame synchronisation
-	//0x11[3] == FEL -> Front End locked
-	//0x11[6] == NODVB -> DVB Mode Information
-	sync = tda10021_readreg (state, 0x11);
-
-	if (sync & 2)
-		*status |= FE_HAS_SIGNAL|FE_HAS_CARRIER;
-
-	if (sync & 4)
-		*status |= FE_HAS_SYNC|FE_HAS_VITERBI;
-
-	if (sync & 8)
-		*status |= FE_HAS_LOCK;
-
-	return 0;
-}
-
-static int tda10021_read_ber(struct dvb_frontend* fe, u32* ber)
-{
-	struct tda10021_state* state = fe->demodulator_priv;
-
-	u32 _ber = tda10021_readreg(state, 0x14) |
-		(tda10021_readreg(state, 0x15) << 8) |
-		((tda10021_readreg(state, 0x16) & 0x0f) << 16);
-	_tda10021_writereg(state, 0x10, (tda10021_readreg(state, 0x10) & ~0xc0)
-					| (tda10021_inittab[0x10] & 0xc0));
-	*ber = 10 * _ber;
-
-	return 0;
-}
-
-static int tda10021_read_signal_strength(struct dvb_frontend* fe, u16* strength)
-{
-	struct tda10021_state* state = fe->demodulator_priv;
-
-	u8 config = tda10021_readreg(state, 0x02);
-	u8 gain = tda10021_readreg(state, 0x17);
-	if (config & 0x02)
-		/* the agc value is inverted */
-		gain = ~gain;
-	*strength = (gain << 8) | gain;
-
-	return 0;
-}
-
-static int tda10021_read_snr(struct dvb_frontend* fe, u16* snr)
-{
-	struct tda10021_state* state = fe->demodulator_priv;
-
-	u8 quality = ~tda10021_readreg(state, 0x18);
-	*snr = (quality << 8) | quality;
-
-	return 0;
-}
-
-static int tda10021_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
-{
-	struct tda10021_state* state = fe->demodulator_priv;
-
-	*ucblocks = tda10021_readreg (state, 0x13) & 0x7f;
-	if (*ucblocks == 0x7f)
-		*ucblocks = 0xffffffff;
-
-	/* reset uncorrected block counter */
-	_tda10021_writereg (state, 0x10, tda10021_inittab[0x10] & 0xdf);
-	_tda10021_writereg (state, 0x10, tda10021_inittab[0x10]);
-
-	return 0;
-}
-
-static int tda10021_get_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct tda10021_state* state = fe->demodulator_priv;
-	int sync;
-	s8 afc = 0;
-
-	sync = tda10021_readreg(state, 0x11);
-	afc = tda10021_readreg(state, 0x19);
-	if (verbose) {
-		/* AFC only valid when carrier has been recovered */
-		printk(sync & 2 ? "DVB: TDA10021(%d): AFC (%d) %dHz\n" :
-				  "DVB: TDA10021(%d): [AFC (%d) %dHz]\n",
-			state->frontend.dvb->num, afc,
-		       -((s32)p->symbol_rate * afc) >> 10);
-	}
-
-	p->inversion = ((state->reg0 & 0x20) == 0x20) ^ (state->config->invert != 0) ? INVERSION_ON : INVERSION_OFF;
-	p->modulation = ((state->reg0 >> 2) & 7) + QAM_16;
-
-	p->fec_inner = FEC_NONE;
-	p->frequency = ((p->frequency + 31250) / 62500) * 62500;
-
-	if (sync & 2)
-		p->frequency -= ((s32)p->symbol_rate * afc) >> 10;
-
-	return 0;
-}
-
-static int tda10021_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
-{
-	struct tda10021_state* state = fe->demodulator_priv;
-
-	if (enable) {
-		lock_tuner(state);
-	} else {
-		unlock_tuner(state);
-	}
-	return 0;
-}
-
-static int tda10021_sleep(struct dvb_frontend* fe)
-{
-	struct tda10021_state* state = fe->demodulator_priv;
-
-	_tda10021_writereg (state, 0x1b, 0x02);  /* pdown ADC */
-	_tda10021_writereg (state, 0x00, 0x80);  /* standby */
-
-	return 0;
-}
-
-static void tda10021_release(struct dvb_frontend* fe)
-{
-	struct tda10021_state* state = fe->demodulator_priv;
-	kfree(state);
-}
-
-static struct dvb_frontend_ops tda10021_ops;
-
-struct dvb_frontend* tda10021_attach(const struct tda1002x_config* config,
-				     struct i2c_adapter* i2c,
-				     u8 pwm)
-{
-	struct tda10021_state* state = NULL;
-	u8 id;
-
-	/* allocate memory for the internal state */
-	state = kzalloc(sizeof(struct tda10021_state), GFP_KERNEL);
-	if (state == NULL) goto error;
-
-	/* setup the state */
-	state->config = config;
-	state->i2c = i2c;
-	state->pwm = pwm;
-	state->reg0 = tda10021_inittab[0];
-
-	/* check if the demod is there */
-	id = tda10021_readreg(state, 0x1a);
-	if ((id & 0xf0) != 0x70) goto error;
-
-	/* Don't claim TDA10023 */
-	if (id == 0x7d)
-		goto error;
-
-	printk("TDA10021: i2c-addr = 0x%02x, id = 0x%02x\n",
-	       state->config->demod_address, id);
-
-	/* create dvb_frontend */
-	memcpy(&state->frontend.ops, &tda10021_ops, sizeof(struct dvb_frontend_ops));
-	state->frontend.demodulator_priv = state;
-	return &state->frontend;
-
-error:
-	kfree(state);
-	return NULL;
-}
-
-static struct dvb_frontend_ops tda10021_ops = {
-	.delsys = { SYS_DVBC_ANNEX_A, SYS_DVBC_ANNEX_C },
-	.info = {
-		.name = "Philips TDA10021 DVB-C",
-		.frequency_stepsize = 62500,
-		.frequency_min = 47000000,
-		.frequency_max = 862000000,
-		.symbol_rate_min = (XIN/2)/64,     /* SACLK/64 == (XIN/2)/64 */
-		.symbol_rate_max = (XIN/2)/4,      /* SACLK/4 */
-	#if 0
-		.frequency_tolerance = ???,
-		.symbol_rate_tolerance = ???,  /* ppm */  /* == 8% (spec p. 5) */
-	#endif
-		.caps = 0x400 | //FE_CAN_QAM_4
-			FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 |
-			FE_CAN_QAM_128 | FE_CAN_QAM_256 |
-			FE_CAN_FEC_AUTO
-	},
-
-	.release = tda10021_release,
-
-	.init = tda10021_init,
-	.sleep = tda10021_sleep,
-	.i2c_gate_ctrl = tda10021_i2c_gate_ctrl,
-
-	.set_frontend = tda10021_set_parameters,
-	.get_frontend = tda10021_get_frontend,
-
-	.read_status = tda10021_read_status,
-	.read_ber = tda10021_read_ber,
-	.read_signal_strength = tda10021_read_signal_strength,
-	.read_snr = tda10021_read_snr,
-	.read_ucblocks = tda10021_read_ucblocks,
-};
-
-module_param(verbose, int, 0644);
-MODULE_PARM_DESC(verbose, "print AFC offset after tuning for debugging the PWM setting");
-
-MODULE_DESCRIPTION("Philips TDA10021 DVB-C demodulator driver");
-MODULE_AUTHOR("Ralph Metzler, Holger Waechtler, Markus Schulz");
-MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(tda10021_attach);
diff --git a/drivers/media/dvb/frontends/tda10023.c b/drivers/media/dvb/frontends/tda10023.c
deleted file mode 100644
index ca1e0d5..0000000
--- a/drivers/media/dvb/frontends/tda10023.c
+++ /dev/null
@@ -1,610 +0,0 @@
-/*
-    TDA10023  - DVB-C decoder
-    (as used in Philips CU1216-3 NIM and the Reelbox DVB-C tuner card)
-
-    Copyright (C) 2005 Georg Acher, BayCom GmbH (acher at baycom dot de)
-    Copyright (c) 2006 Hartmut Birr (e9hack at gmail dot com)
-
-    Remotely based on tda10021.c
-    Copyright (C) 1999 Convergence Integrated Media GmbH <ralph@convergence.de>
-    Copyright (C) 2004 Markus Schulz <msc@antzsystem.de>
-		   Support for TDA10021
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the 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/delay.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-
-#include <asm/div64.h>
-
-#include "dvb_frontend.h"
-#include "tda1002x.h"
-
-#define REG0_INIT_VAL 0x23
-
-struct tda10023_state {
-	struct i2c_adapter* i2c;
-	/* configuration settings */
-	const struct tda10023_config *config;
-	struct dvb_frontend frontend;
-
-	u8 pwm;
-	u8 reg0;
-
-	/* clock settings */
-	u32 xtal;
-	u8 pll_m;
-	u8 pll_p;
-	u8 pll_n;
-	u32 sysclk;
-};
-
-#define dprintk(x...)
-
-static int verbose;
-
-static u8 tda10023_readreg (struct tda10023_state* state, u8 reg)
-{
-	u8 b0 [] = { reg };
-	u8 b1 [] = { 0 };
-	struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 },
-				  { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } };
-	int ret;
-
-	ret = i2c_transfer (state->i2c, msg, 2);
-	if (ret != 2) {
-		int num = state->frontend.dvb ? state->frontend.dvb->num : -1;
-		printk(KERN_ERR "DVB: TDA10023(%d): %s: readreg error "
-			"(reg == 0x%02x, ret == %i)\n",
-			num, __func__, reg, ret);
-	}
-	return b1[0];
-}
-
-static int tda10023_writereg (struct tda10023_state* state, u8 reg, u8 data)
-{
-	u8 buf[] = { reg, data };
-	struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 };
-	int ret;
-
-	ret = i2c_transfer (state->i2c, &msg, 1);
-	if (ret != 1) {
-		int num = state->frontend.dvb ? state->frontend.dvb->num : -1;
-		printk(KERN_ERR "DVB: TDA10023(%d): %s, writereg error "
-			"(reg == 0x%02x, val == 0x%02x, ret == %i)\n",
-			num, __func__, reg, data, ret);
-	}
-	return (ret != 1) ? -EREMOTEIO : 0;
-}
-
-
-static int tda10023_writebit (struct tda10023_state* state, u8 reg, u8 mask,u8 data)
-{
-	if (mask==0xff)
-		return tda10023_writereg(state, reg, data);
-	else {
-		u8 val;
-		val=tda10023_readreg(state,reg);
-		val&=~mask;
-		val|=(data&mask);
-		return tda10023_writereg(state, reg, val);
-	}
-}
-
-static void tda10023_writetab(struct tda10023_state* state, u8* tab)
-{
-	u8 r,m,v;
-	while (1) {
-		r=*tab++;
-		m=*tab++;
-		v=*tab++;
-		if (r==0xff) {
-			if (m==0xff)
-				break;
-			else
-				msleep(m);
-		}
-		else
-			tda10023_writebit(state,r,m,v);
-	}
-}
-
-//get access to tuner
-static int lock_tuner(struct tda10023_state* state)
-{
-	u8 buf[2] = { 0x0f, 0xc0 };
-	struct i2c_msg msg = {.addr=state->config->demod_address, .flags=0, .buf=buf, .len=2};
-
-	if(i2c_transfer(state->i2c, &msg, 1) != 1)
-	{
-		printk("tda10023: lock tuner fails\n");
-		return -EREMOTEIO;
-	}
-	return 0;
-}
-
-//release access from tuner
-static int unlock_tuner(struct tda10023_state* state)
-{
-	u8 buf[2] = { 0x0f, 0x40 };
-	struct i2c_msg msg_post={.addr=state->config->demod_address, .flags=0, .buf=buf, .len=2};
-
-	if(i2c_transfer(state->i2c, &msg_post, 1) != 1)
-	{
-		printk("tda10023: unlock tuner fails\n");
-		return -EREMOTEIO;
-	}
-	return 0;
-}
-
-static int tda10023_setup_reg0 (struct tda10023_state* state, u8 reg0)
-{
-	reg0 |= state->reg0 & 0x63;
-
-	tda10023_writereg (state, 0x00, reg0 & 0xfe);
-	tda10023_writereg (state, 0x00, reg0 | 0x01);
-
-	state->reg0 = reg0;
-	return 0;
-}
-
-static int tda10023_set_symbolrate (struct tda10023_state* state, u32 sr)
-{
-	s32 BDR;
-	s32 BDRI;
-	s16 SFIL=0;
-	u16 NDEC = 0;
-
-	/* avoid floating point operations multiplying syscloc and divider
-	   by 10 */
-	u32 sysclk_x_10 = state->sysclk * 10;
-
-	if (sr < (u32)(sysclk_x_10/984)) {
-		NDEC=3;
-		SFIL=1;
-	} else if (sr < (u32)(sysclk_x_10/640)) {
-		NDEC=3;
-		SFIL=0;
-	} else if (sr < (u32)(sysclk_x_10/492)) {
-		NDEC=2;
-		SFIL=1;
-	} else if (sr < (u32)(sysclk_x_10/320)) {
-		NDEC=2;
-		SFIL=0;
-	} else if (sr < (u32)(sysclk_x_10/246)) {
-		NDEC=1;
-		SFIL=1;
-	} else if (sr < (u32)(sysclk_x_10/160)) {
-		NDEC=1;
-		SFIL=0;
-	} else if (sr < (u32)(sysclk_x_10/123)) {
-		NDEC=0;
-		SFIL=1;
-	}
-
-	BDRI = (state->sysclk)*16;
-	BDRI>>=NDEC;
-	BDRI +=sr/2;
-	BDRI /=sr;
-
-	if (BDRI>255)
-		BDRI=255;
-
-	{
-		u64 BDRX;
-
-		BDRX=1<<(24+NDEC);
-		BDRX*=sr;
-		do_div(BDRX, state->sysclk); 	/* BDRX/=SYSCLK; */
-
-		BDR=(s32)BDRX;
-	}
-	dprintk("Symbolrate %i, BDR %i BDRI %i, NDEC %i\n",
-		sr, BDR, BDRI, NDEC);
-	tda10023_writebit (state, 0x03, 0xc0, NDEC<<6);
-	tda10023_writereg (state, 0x0a, BDR&255);
-	tda10023_writereg (state, 0x0b, (BDR>>8)&255);
-	tda10023_writereg (state, 0x0c, (BDR>>16)&31);
-	tda10023_writereg (state, 0x0d, BDRI);
-	tda10023_writereg (state, 0x3d, (SFIL<<7));
-	return 0;
-}
-
-static int tda10023_init (struct dvb_frontend *fe)
-{
-	struct tda10023_state* state = fe->demodulator_priv;
-	u8 tda10023_inittab[] = {
-/*        reg  mask val */
-/* 000 */ 0x2a, 0xff, 0x02,  /* PLL3, Bypass, Power Down */
-/* 003 */ 0xff, 0x64, 0x00,  /* Sleep 100ms */
-/* 006 */ 0x2a, 0xff, 0x03,  /* PLL3, Bypass, Power Down */
-/* 009 */ 0xff, 0x64, 0x00,  /* Sleep 100ms */
-			   /* PLL1 */
-/* 012 */ 0x28, 0xff, (state->pll_m-1),
-			   /* PLL2 */
-/* 015 */ 0x29, 0xff, ((state->pll_p-1)<<6)|(state->pll_n-1),
-			   /* GPR FSAMPLING=1 */
-/* 018 */ 0x00, 0xff, REG0_INIT_VAL,
-/* 021 */ 0x2a, 0xff, 0x08,  /* PLL3 PSACLK=1 */
-/* 024 */ 0xff, 0x64, 0x00,  /* Sleep 100ms */
-/* 027 */ 0x1f, 0xff, 0x00,  /* RESET */
-/* 030 */ 0xff, 0x64, 0x00,  /* Sleep 100ms */
-/* 033 */ 0xe6, 0x0c, 0x04,  /* RSCFG_IND */
-/* 036 */ 0x10, 0xc0, 0x80,  /* DECDVBCFG1 PBER=1 */
-
-/* 039 */ 0x0e, 0xff, 0x82,  /* GAIN1 */
-/* 042 */ 0x03, 0x08, 0x08,  /* CLKCONF DYN=1 */
-/* 045 */ 0x2e, 0xbf, 0x30,  /* AGCCONF2 TRIAGC=0,POSAGC=ENAGCIF=1
-				       PPWMTUN=0 PPWMIF=0 */
-/* 048 */ 0x01, 0xff, 0x30,  /* AGCREF */
-/* 051 */ 0x1e, 0x84, 0x84,  /* CONTROL SACLK_ON=1 */
-/* 054 */ 0x1b, 0xff, 0xc8,  /* ADC TWOS=1 */
-/* 057 */ 0x3b, 0xff, 0xff,  /* IFMAX */
-/* 060 */ 0x3c, 0xff, 0x00,  /* IFMIN */
-/* 063 */ 0x34, 0xff, 0x00,  /* PWMREF */
-/* 066 */ 0x35, 0xff, 0xff,  /* TUNMAX */
-/* 069 */ 0x36, 0xff, 0x00,  /* TUNMIN */
-/* 072 */ 0x06, 0xff, 0x7f,  /* EQCONF1 POSI=7 ENADAPT=ENEQUAL=DFE=1 */
-/* 075 */ 0x1c, 0x30, 0x30,  /* EQCONF2 STEPALGO=SGNALGO=1 */
-/* 078 */ 0x37, 0xff, 0xf6,  /* DELTAF_LSB */
-/* 081 */ 0x38, 0xff, 0xff,  /* DELTAF_MSB */
-/* 084 */ 0x02, 0xff, 0x93,  /* AGCCONF1  IFS=1 KAGCIF=2 KAGCTUN=3 */
-/* 087 */ 0x2d, 0xff, 0xf6,  /* SWEEP SWPOS=1 SWDYN=7 SWSTEP=1 SWLEN=2 */
-/* 090 */ 0x04, 0x10, 0x00,  /* SWRAMP=1 */
-/* 093 */ 0x12, 0xff, TDA10023_OUTPUT_MODE_PARALLEL_B, /*
-				INTP1 POCLKP=1 FEL=1 MFS=0 */
-/* 096 */ 0x2b, 0x01, 0xa1,  /* INTS1 */
-/* 099 */ 0x20, 0xff, 0x04,  /* INTP2 SWAPP=? MSBFIRSTP=? INTPSEL=? */
-/* 102 */ 0x2c, 0xff, 0x0d,  /* INTP/S TRIP=0 TRIS=0 */
-/* 105 */ 0xc4, 0xff, 0x00,
-/* 108 */ 0xc3, 0x30, 0x00,
-/* 111 */ 0xb5, 0xff, 0x19,  /* ERAGC_THD */
-/* 114 */ 0x00, 0x03, 0x01,  /* GPR, CLBS soft reset */
-/* 117 */ 0x00, 0x03, 0x03,  /* GPR, CLBS soft reset */
-/* 120 */ 0xff, 0x64, 0x00,  /* Sleep 100ms */
-/* 123 */ 0xff, 0xff, 0xff
-};
-	dprintk("DVB: TDA10023(%d): init chip\n", fe->dvb->num);
-
-	/* override default values if set in config */
-	if (state->config->deltaf) {
-		tda10023_inittab[80] = (state->config->deltaf & 0xff);
-		tda10023_inittab[83] = (state->config->deltaf >> 8);
-	}
-
-	if (state->config->output_mode)
-		tda10023_inittab[95] = state->config->output_mode;
-
-	tda10023_writetab(state, tda10023_inittab);
-
-	return 0;
-}
-
-struct qam_params {
-	u8 qam, lockthr, mseth, aref, agcrefnyq, eragnyq_thd;
-};
-
-static int tda10023_set_parameters(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	u32 delsys  = c->delivery_system;
-	unsigned qam = c->modulation;
-	bool is_annex_c;
-	struct tda10023_state* state = fe->demodulator_priv;
-	static const struct qam_params qam_params[] = {
-		/* Modulation  QAM    LOCKTHR   MSETH   AREF AGCREFNYQ ERAGCNYQ_THD */
-		[QPSK]    = { (5<<2),  0x78,    0x8c,   0x96,   0x78,   0x4c  },
-		[QAM_16]  = { (0<<2),  0x87,    0xa2,   0x91,   0x8c,   0x57  },
-		[QAM_32]  = { (1<<2),  0x64,    0x74,   0x96,   0x8c,   0x57  },
-		[QAM_64]  = { (2<<2),  0x46,    0x43,   0x6a,   0x6a,   0x44  },
-		[QAM_128] = { (3<<2),  0x36,    0x34,   0x7e,   0x78,   0x4c  },
-		[QAM_256] = { (4<<2),  0x26,    0x23,   0x6c,   0x5c,   0x3c  },
-	};
-
-	switch (delsys) {
-	case SYS_DVBC_ANNEX_A:
-		is_annex_c = false;
-		break;
-	case SYS_DVBC_ANNEX_C:
-		is_annex_c = true;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	/*
-	 * gcc optimizes the code bellow the same way as it would code:
-	 *		 "if (qam > 5) return -EINVAL;"
-	 * Yet, the code is clearer, as it shows what QAM standards are
-	 * supported by the driver, and avoids the usage of magic numbers on
-	 * it.
-	 */
-	switch (qam) {
-	case QPSK:
-	case QAM_16:
-	case QAM_32:
-	case QAM_64:
-	case QAM_128:
-	case QAM_256:
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	if (fe->ops.tuner_ops.set_params) {
-		fe->ops.tuner_ops.set_params(fe);
-		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
-	}
-
-	tda10023_set_symbolrate(state, c->symbol_rate);
-	tda10023_writereg(state, 0x05, qam_params[qam].lockthr);
-	tda10023_writereg(state, 0x08, qam_params[qam].mseth);
-	tda10023_writereg(state, 0x09, qam_params[qam].aref);
-	tda10023_writereg(state, 0xb4, qam_params[qam].agcrefnyq);
-	tda10023_writereg(state, 0xb6, qam_params[qam].eragnyq_thd);
-#if 0
-	tda10023_writereg(state, 0x04, (c->inversion ? 0x12 : 0x32));
-	tda10023_writebit(state, 0x04, 0x60, (c->inversion ? 0 : 0x20));
-#endif
-	tda10023_writebit(state, 0x04, 0x40, 0x40);
-
-	if (is_annex_c)
-		tda10023_writebit(state, 0x3d, 0xfc, 0x03);
-	else
-		tda10023_writebit(state, 0x3d, 0xfc, 0x02);
-
-	tda10023_setup_reg0(state, qam_params[qam].qam);
-
-	return 0;
-}
-
-static int tda10023_read_status(struct dvb_frontend* fe, fe_status_t* status)
-{
-	struct tda10023_state* state = fe->demodulator_priv;
-	int sync;
-
-	*status = 0;
-
-	//0x11[1] == CARLOCK -> Carrier locked
-	//0x11[2] == FSYNC -> Frame synchronisation
-	//0x11[3] == FEL -> Front End locked
-	//0x11[6] == NODVB -> DVB Mode Information
-	sync = tda10023_readreg (state, 0x11);
-
-	if (sync & 2)
-		*status |= FE_HAS_SIGNAL|FE_HAS_CARRIER;
-
-	if (sync & 4)
-		*status |= FE_HAS_SYNC|FE_HAS_VITERBI;
-
-	if (sync & 8)
-		*status |= FE_HAS_LOCK;
-
-	return 0;
-}
-
-static int tda10023_read_ber(struct dvb_frontend* fe, u32* ber)
-{
-	struct tda10023_state* state = fe->demodulator_priv;
-	u8 a,b,c;
-	a=tda10023_readreg(state, 0x14);
-	b=tda10023_readreg(state, 0x15);
-	c=tda10023_readreg(state, 0x16)&0xf;
-	tda10023_writebit (state, 0x10, 0xc0, 0x00);
-
-	*ber = a | (b<<8)| (c<<16);
-	return 0;
-}
-
-static int tda10023_read_signal_strength(struct dvb_frontend* fe, u16* strength)
-{
-	struct tda10023_state* state = fe->demodulator_priv;
-	u8 ifgain=tda10023_readreg(state, 0x2f);
-
-	u16 gain = ((255-tda10023_readreg(state, 0x17))) + (255-ifgain)/16;
-	// Max raw value is about 0xb0 -> Normalize to >0xf0 after 0x90
-	if (gain>0x90)
-		gain=gain+2*(gain-0x90);
-	if (gain>255)
-		gain=255;
-
-	*strength = (gain<<8)|gain;
-	return 0;
-}
-
-static int tda10023_read_snr(struct dvb_frontend* fe, u16* snr)
-{
-	struct tda10023_state* state = fe->demodulator_priv;
-
-	u8 quality = ~tda10023_readreg(state, 0x18);
-	*snr = (quality << 8) | quality;
-	return 0;
-}
-
-static int tda10023_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
-{
-	struct tda10023_state* state = fe->demodulator_priv;
-	u8 a,b,c,d;
-	a= tda10023_readreg (state, 0x74);
-	b= tda10023_readreg (state, 0x75);
-	c= tda10023_readreg (state, 0x76);
-	d= tda10023_readreg (state, 0x77);
-	*ucblocks = a | (b<<8)|(c<<16)|(d<<24);
-
-	tda10023_writebit (state, 0x10, 0x20,0x00);
-	tda10023_writebit (state, 0x10, 0x20,0x20);
-	tda10023_writebit (state, 0x13, 0x01, 0x00);
-
-	return 0;
-}
-
-static int tda10023_get_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct tda10023_state* state = fe->demodulator_priv;
-	int sync,inv;
-	s8 afc = 0;
-
-	sync = tda10023_readreg(state, 0x11);
-	afc = tda10023_readreg(state, 0x19);
-	inv = tda10023_readreg(state, 0x04);
-
-	if (verbose) {
-		/* AFC only valid when carrier has been recovered */
-		printk(sync & 2 ? "DVB: TDA10023(%d): AFC (%d) %dHz\n" :
-				  "DVB: TDA10023(%d): [AFC (%d) %dHz]\n",
-			state->frontend.dvb->num, afc,
-		       -((s32)p->symbol_rate * afc) >> 10);
-	}
-
-	p->inversion = (inv&0x20?0:1);
-	p->modulation = ((state->reg0 >> 2) & 7) + QAM_16;
-
-	p->fec_inner = FEC_NONE;
-	p->frequency = ((p->frequency + 31250) / 62500) * 62500;
-
-	if (sync & 2)
-		p->frequency -= ((s32)p->symbol_rate * afc) >> 10;
-
-	return 0;
-}
-
-static int tda10023_sleep(struct dvb_frontend* fe)
-{
-	struct tda10023_state* state = fe->demodulator_priv;
-
-	tda10023_writereg (state, 0x1b, 0x02);  /* pdown ADC */
-	tda10023_writereg (state, 0x00, 0x80);  /* standby */
-
-	return 0;
-}
-
-static int tda10023_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
-{
-	struct tda10023_state* state = fe->demodulator_priv;
-
-	if (enable) {
-		lock_tuner(state);
-	} else {
-		unlock_tuner(state);
-	}
-	return 0;
-}
-
-static void tda10023_release(struct dvb_frontend* fe)
-{
-	struct tda10023_state* state = fe->demodulator_priv;
-	kfree(state);
-}
-
-static struct dvb_frontend_ops tda10023_ops;
-
-struct dvb_frontend *tda10023_attach(const struct tda10023_config *config,
-				     struct i2c_adapter *i2c,
-				     u8 pwm)
-{
-	struct tda10023_state* state = NULL;
-
-	/* allocate memory for the internal state */
-	state = kzalloc(sizeof(struct tda10023_state), GFP_KERNEL);
-	if (state == NULL) goto error;
-
-	/* setup the state */
-	state->config = config;
-	state->i2c = i2c;
-
-	/* wakeup if in standby */
-	tda10023_writereg (state, 0x00, 0x33);
-	/* check if the demod is there */
-	if ((tda10023_readreg(state, 0x1a) & 0xf0) != 0x70) goto error;
-
-	/* create dvb_frontend */
-	memcpy(&state->frontend.ops, &tda10023_ops, sizeof(struct dvb_frontend_ops));
-	state->pwm = pwm;
-	state->reg0 = REG0_INIT_VAL;
-	if (state->config->xtal) {
-		state->xtal  = state->config->xtal;
-		state->pll_m = state->config->pll_m;
-		state->pll_p = state->config->pll_p;
-		state->pll_n = state->config->pll_n;
-	} else {
-		/* set default values if not defined in config */
-		state->xtal  = 28920000;
-		state->pll_m = 8;
-		state->pll_p = 4;
-		state->pll_n = 1;
-	}
-
-	/* calc sysclk */
-	state->sysclk = (state->xtal * state->pll_m / \
-			(state->pll_n * state->pll_p));
-
-	state->frontend.ops.info.symbol_rate_min = (state->sysclk/2)/64;
-	state->frontend.ops.info.symbol_rate_max = (state->sysclk/2)/4;
-
-	dprintk("DVB: TDA10023 %s: xtal:%d pll_m:%d pll_p:%d pll_n:%d\n",
-		__func__, state->xtal, state->pll_m, state->pll_p,
-		state->pll_n);
-
-	state->frontend.demodulator_priv = state;
-	return &state->frontend;
-
-error:
-	kfree(state);
-	return NULL;
-}
-
-static struct dvb_frontend_ops tda10023_ops = {
-	.delsys = { SYS_DVBC_ANNEX_A, SYS_DVBC_ANNEX_C },
-	.info = {
-		.name = "Philips TDA10023 DVB-C",
-		.frequency_stepsize = 62500,
-		.frequency_min =  47000000,
-		.frequency_max = 862000000,
-		.symbol_rate_min = 0,  /* set in tda10023_attach */
-		.symbol_rate_max = 0,  /* set in tda10023_attach */
-		.caps = 0x400 | //FE_CAN_QAM_4
-			FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 |
-			FE_CAN_QAM_128 | FE_CAN_QAM_256 |
-			FE_CAN_FEC_AUTO
-	},
-
-	.release = tda10023_release,
-
-	.init = tda10023_init,
-	.sleep = tda10023_sleep,
-	.i2c_gate_ctrl = tda10023_i2c_gate_ctrl,
-
-	.set_frontend = tda10023_set_parameters,
-	.get_frontend = tda10023_get_frontend,
-	.read_status = tda10023_read_status,
-	.read_ber = tda10023_read_ber,
-	.read_signal_strength = tda10023_read_signal_strength,
-	.read_snr = tda10023_read_snr,
-	.read_ucblocks = tda10023_read_ucblocks,
-};
-
-
-MODULE_DESCRIPTION("Philips TDA10023 DVB-C demodulator driver");
-MODULE_AUTHOR("Georg Acher, Hartmut Birr");
-MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(tda10023_attach);
diff --git a/drivers/media/dvb/frontends/tda1002x.h b/drivers/media/dvb/frontends/tda1002x.h
deleted file mode 100644
index 04d1941..0000000
--- a/drivers/media/dvb/frontends/tda1002x.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
-    TDA10021/TDA10023  - Single Chip Cable Channel Receiver driver module
-			 used on the the Siemens DVB-C cards
-
-    Copyright (C) 1999 Convergence Integrated Media GmbH <ralph@convergence.de>
-    Copyright (C) 2004 Markus Schulz <msc@antzsystem.de>
-		   Support for TDA10021
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the 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 TDA1002x_H
-#define TDA1002x_H
-
-#include <linux/dvb/frontend.h>
-
-struct tda1002x_config {
-	/* the demodulator's i2c address */
-	u8 demod_address;
-	u8 invert;
-};
-
-enum tda10023_output_mode {
-	TDA10023_OUTPUT_MODE_PARALLEL_A = 0xe0,
-	TDA10023_OUTPUT_MODE_PARALLEL_B = 0xa1,
-	TDA10023_OUTPUT_MODE_PARALLEL_C = 0xa0,
-	TDA10023_OUTPUT_MODE_SERIAL, /* TODO: not implemented */
-};
-
-struct tda10023_config {
-	/* the demodulator's i2c address */
-	u8 demod_address;
-	u8 invert;
-
-	/* clock settings */
-	u32 xtal; /* defaults: 28920000 */
-	u8 pll_m; /* defaults: 8 */
-	u8 pll_p; /* defaults: 4 */
-	u8 pll_n; /* defaults: 1 */
-
-	/* MPEG2 TS output mode */
-	u8 output_mode;
-
-	/* input freq offset + baseband conversion type */
-	u16 deltaf;
-};
-
-#if defined(CONFIG_DVB_TDA10021) || (defined(CONFIG_DVB_TDA10021_MODULE) && defined(MODULE))
-extern struct dvb_frontend* tda10021_attach(const struct tda1002x_config* config,
-					    struct i2c_adapter* i2c, u8 pwm);
-#else
-static inline struct dvb_frontend* tda10021_attach(const struct tda1002x_config* config,
-					    struct i2c_adapter* i2c, u8 pwm)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif // CONFIG_DVB_TDA10021
-
-#if defined(CONFIG_DVB_TDA10023) || \
-	(defined(CONFIG_DVB_TDA10023_MODULE) && defined(MODULE))
-extern struct dvb_frontend *tda10023_attach(
-	const struct tda10023_config *config,
-	struct i2c_adapter *i2c, u8 pwm);
-#else
-static inline struct dvb_frontend *tda10023_attach(
-	const struct tda10023_config *config,
-	struct i2c_adapter *i2c, u8 pwm)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif // CONFIG_DVB_TDA10023
-
-#endif // TDA1002x_H
diff --git a/drivers/media/dvb/frontends/tda10048.c b/drivers/media/dvb/frontends/tda10048.c
deleted file mode 100644
index 71fb632..0000000
--- a/drivers/media/dvb/frontends/tda10048.c
+++ /dev/null
@@ -1,1191 +0,0 @@
-/*
-    NXP TDA10048HN DVB OFDM demodulator driver
-
-    Copyright (C) 2009 Steven Toth <stoth@kernellabs.com>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/math64.h>
-#include <asm/div64.h>
-#include "dvb_frontend.h"
-#include "dvb_math.h"
-#include "tda10048.h"
-
-#define TDA10048_DEFAULT_FIRMWARE "dvb-fe-tda10048-1.0.fw"
-#define TDA10048_DEFAULT_FIRMWARE_SIZE 24878
-
-/* Register name definitions */
-#define TDA10048_IDENTITY          0x00
-#define TDA10048_VERSION           0x01
-#define TDA10048_DSP_CODE_CPT      0x0C
-#define TDA10048_DSP_CODE_IN       0x0E
-#define TDA10048_IN_CONF1          0x10
-#define TDA10048_IN_CONF2          0x11
-#define TDA10048_IN_CONF3          0x12
-#define TDA10048_OUT_CONF1         0x14
-#define TDA10048_OUT_CONF2         0x15
-#define TDA10048_OUT_CONF3         0x16
-#define TDA10048_AUTO              0x18
-#define TDA10048_SYNC_STATUS       0x1A
-#define TDA10048_CONF_C4_1         0x1E
-#define TDA10048_CONF_C4_2         0x1F
-#define TDA10048_CODE_IN_RAM       0x20
-#define TDA10048_CHANNEL_INFO1_R   0x22
-#define TDA10048_CHANNEL_INFO2_R   0x23
-#define TDA10048_CHANNEL_INFO1     0x24
-#define TDA10048_CHANNEL_INFO2     0x25
-#define TDA10048_TIME_ERROR_R      0x26
-#define TDA10048_TIME_ERROR        0x27
-#define TDA10048_FREQ_ERROR_LSB_R  0x28
-#define TDA10048_FREQ_ERROR_MSB_R  0x29
-#define TDA10048_FREQ_ERROR_LSB    0x2A
-#define TDA10048_FREQ_ERROR_MSB    0x2B
-#define TDA10048_IT_SEL            0x30
-#define TDA10048_IT_STAT           0x32
-#define TDA10048_DSP_AD_LSB        0x3C
-#define TDA10048_DSP_AD_MSB        0x3D
-#define TDA10048_DSP_REG_LSB       0x3E
-#define TDA10048_DSP_REG_MSB       0x3F
-#define TDA10048_CONF_TRISTATE1    0x44
-#define TDA10048_CONF_TRISTATE2    0x45
-#define TDA10048_CONF_POLARITY     0x46
-#define TDA10048_GPIO_SP_DS0       0x48
-#define TDA10048_GPIO_SP_DS1       0x49
-#define TDA10048_GPIO_SP_DS2       0x4A
-#define TDA10048_GPIO_SP_DS3       0x4B
-#define TDA10048_GPIO_OUT_SEL      0x4C
-#define TDA10048_GPIO_SELECT       0x4D
-#define TDA10048_IC_MODE           0x4E
-#define TDA10048_CONF_XO           0x50
-#define TDA10048_CONF_PLL1         0x51
-#define TDA10048_CONF_PLL2         0x52
-#define TDA10048_CONF_PLL3         0x53
-#define TDA10048_CONF_ADC          0x54
-#define TDA10048_CONF_ADC_2        0x55
-#define TDA10048_CONF_C1_1         0x60
-#define TDA10048_CONF_C1_3         0x62
-#define TDA10048_AGC_CONF          0x70
-#define TDA10048_AGC_THRESHOLD_LSB 0x72
-#define TDA10048_AGC_THRESHOLD_MSB 0x73
-#define TDA10048_AGC_RENORM        0x74
-#define TDA10048_AGC_GAINS         0x76
-#define TDA10048_AGC_TUN_MIN       0x78
-#define TDA10048_AGC_TUN_MAX       0x79
-#define TDA10048_AGC_IF_MIN        0x7A
-#define TDA10048_AGC_IF_MAX        0x7B
-#define TDA10048_AGC_TUN_LEVEL     0x7E
-#define TDA10048_AGC_IF_LEVEL      0x7F
-#define TDA10048_DIG_AGC_LEVEL     0x81
-#define TDA10048_FREQ_PHY2_LSB     0x86
-#define TDA10048_FREQ_PHY2_MSB     0x87
-#define TDA10048_TIME_INVWREF_LSB  0x88
-#define TDA10048_TIME_INVWREF_MSB  0x89
-#define TDA10048_TIME_WREF_LSB     0x8A
-#define TDA10048_TIME_WREF_MID1    0x8B
-#define TDA10048_TIME_WREF_MID2    0x8C
-#define TDA10048_TIME_WREF_MSB     0x8D
-#define TDA10048_NP_OUT            0xA2
-#define TDA10048_CELL_ID_LSB       0xA4
-#define TDA10048_CELL_ID_MSB       0xA5
-#define TDA10048_EXTTPS_ODD        0xAA
-#define TDA10048_EXTTPS_EVEN       0xAB
-#define TDA10048_TPS_LENGTH        0xAC
-#define TDA10048_FREE_REG_1        0xB2
-#define TDA10048_FREE_REG_2        0xB3
-#define TDA10048_CONF_C3_1         0xC0
-#define TDA10048_CVBER_CTRL        0xC2
-#define TDA10048_CBER_NMAX_LSB     0xC4
-#define TDA10048_CBER_NMAX_MSB     0xC5
-#define TDA10048_CBER_LSB          0xC6
-#define TDA10048_CBER_MSB          0xC7
-#define TDA10048_VBER_LSB          0xC8
-#define TDA10048_VBER_MID          0xC9
-#define TDA10048_VBER_MSB          0xCA
-#define TDA10048_CVBER_LUT         0xCC
-#define TDA10048_UNCOR_CTRL        0xCD
-#define TDA10048_UNCOR_CPT_LSB     0xCE
-#define TDA10048_UNCOR_CPT_MSB     0xCF
-#define TDA10048_SOFT_IT_C3        0xD6
-#define TDA10048_CONF_TS2          0xE0
-#define TDA10048_CONF_TS1          0xE1
-
-static unsigned int debug;
-
-#define dprintk(level, fmt, arg...)\
-	do { if (debug >= level)\
-		printk(KERN_DEBUG "tda10048: " fmt, ## arg);\
-	} while (0)
-
-struct tda10048_state {
-
-	struct i2c_adapter *i2c;
-
-	/* We'll cache and update the attach config settings */
-	struct tda10048_config config;
-	struct dvb_frontend frontend;
-
-	int fwloaded;
-
-	u32 freq_if_hz;
-	u32 xtal_hz;
-	u32 pll_mfactor;
-	u32 pll_nfactor;
-	u32 pll_pfactor;
-	u32 sample_freq;
-
-	u32 bandwidth;
-};
-
-static struct init_tab {
-	u8	reg;
-	u16	data;
-} init_tab[] = {
-	{ TDA10048_CONF_PLL1, 0x08 },
-	{ TDA10048_CONF_ADC_2, 0x00 },
-	{ TDA10048_CONF_C4_1, 0x00 },
-	{ TDA10048_CONF_PLL1, 0x0f },
-	{ TDA10048_CONF_PLL2, 0x0a },
-	{ TDA10048_CONF_PLL3, 0x43 },
-	{ TDA10048_FREQ_PHY2_LSB, 0x02 },
-	{ TDA10048_FREQ_PHY2_MSB, 0x0a },
-	{ TDA10048_TIME_WREF_LSB, 0xbd },
-	{ TDA10048_TIME_WREF_MID1, 0xe4 },
-	{ TDA10048_TIME_WREF_MID2, 0xa8 },
-	{ TDA10048_TIME_WREF_MSB, 0x02 },
-	{ TDA10048_TIME_INVWREF_LSB, 0x04 },
-	{ TDA10048_TIME_INVWREF_MSB, 0x06 },
-	{ TDA10048_CONF_C4_1, 0x00 },
-	{ TDA10048_CONF_C1_1, 0xa8 },
-	{ TDA10048_AGC_CONF, 0x16 },
-	{ TDA10048_CONF_C1_3, 0x0b },
-	{ TDA10048_AGC_TUN_MIN, 0x00 },
-	{ TDA10048_AGC_TUN_MAX, 0xff },
-	{ TDA10048_AGC_IF_MIN, 0x00 },
-	{ TDA10048_AGC_IF_MAX, 0xff },
-	{ TDA10048_AGC_THRESHOLD_MSB, 0x00 },
-	{ TDA10048_AGC_THRESHOLD_LSB, 0x70 },
-	{ TDA10048_CVBER_CTRL, 0x38 },
-	{ TDA10048_AGC_GAINS, 0x12 },
-	{ TDA10048_CONF_XO, 0x00 },
-	{ TDA10048_CONF_TS1, 0x07 },
-	{ TDA10048_IC_MODE, 0x00 },
-	{ TDA10048_CONF_TS2, 0xc0 },
-	{ TDA10048_CONF_TRISTATE1, 0x21 },
-	{ TDA10048_CONF_TRISTATE2, 0x00 },
-	{ TDA10048_CONF_POLARITY, 0x00 },
-	{ TDA10048_CONF_C4_2, 0x04 },
-	{ TDA10048_CONF_ADC, 0x60 },
-	{ TDA10048_CONF_ADC_2, 0x10 },
-	{ TDA10048_CONF_ADC, 0x60 },
-	{ TDA10048_CONF_ADC_2, 0x00 },
-	{ TDA10048_CONF_C1_1, 0xa8 },
-	{ TDA10048_UNCOR_CTRL, 0x00 },
-	{ TDA10048_CONF_C4_2, 0x04 },
-};
-
-static struct pll_tab {
-	u32	clk_freq_khz;
-	u32	if_freq_khz;
-} pll_tab[] = {
-	{ TDA10048_CLK_4000,  TDA10048_IF_36130 },
-	{ TDA10048_CLK_16000, TDA10048_IF_3300 },
-	{ TDA10048_CLK_16000, TDA10048_IF_3500 },
-	{ TDA10048_CLK_16000, TDA10048_IF_3800 },
-	{ TDA10048_CLK_16000, TDA10048_IF_4000 },
-	{ TDA10048_CLK_16000, TDA10048_IF_4300 },
-	{ TDA10048_CLK_16000, TDA10048_IF_4500 },
-	{ TDA10048_CLK_16000, TDA10048_IF_5000 },
-	{ TDA10048_CLK_16000, TDA10048_IF_36130 },
-};
-
-static int tda10048_writereg(struct tda10048_state *state, u8 reg, u8 data)
-{
-	struct tda10048_config *config = &state->config;
-	int ret;
-	u8 buf[] = { reg, data };
-	struct i2c_msg msg = {
-		.addr = config->demod_address,
-		.flags = 0, .buf = buf, .len = 2 };
-
-	dprintk(2, "%s(reg = 0x%02x, data = 0x%02x)\n", __func__, reg, data);
-
-	ret = i2c_transfer(state->i2c, &msg, 1);
-
-	if (ret != 1)
-		printk("%s: writereg error (ret == %i)\n", __func__, ret);
-
-	return (ret != 1) ? -1 : 0;
-}
-
-static u8 tda10048_readreg(struct tda10048_state *state, u8 reg)
-{
-	struct tda10048_config *config = &state->config;
-	int ret;
-	u8 b0[] = { reg };
-	u8 b1[] = { 0 };
-	struct i2c_msg msg[] = {
-		{ .addr = config->demod_address,
-			.flags = 0, .buf = b0, .len = 1 },
-		{ .addr = config->demod_address,
-			.flags = I2C_M_RD, .buf = b1, .len = 1 } };
-
-	dprintk(2, "%s(reg = 0x%02x)\n", __func__, reg);
-
-	ret = i2c_transfer(state->i2c, msg, 2);
-
-	if (ret != 2)
-		printk(KERN_ERR "%s: readreg error (ret == %i)\n",
-			__func__, ret);
-
-	return b1[0];
-}
-
-static int tda10048_writeregbulk(struct tda10048_state *state, u8 reg,
-				 const u8 *data, u16 len)
-{
-	struct tda10048_config *config = &state->config;
-	int ret = -EREMOTEIO;
-	struct i2c_msg msg;
-	u8 *buf;
-
-	dprintk(2, "%s(%d, ?, len = %d)\n", __func__, reg, len);
-
-	buf = kmalloc(len + 1, GFP_KERNEL);
-	if (buf == NULL) {
-		ret = -ENOMEM;
-		goto error;
-	}
-
-	*buf = reg;
-	memcpy(buf + 1, data, len);
-
-	msg.addr = config->demod_address;
-	msg.flags = 0;
-	msg.buf = buf;
-	msg.len = len + 1;
-
-	dprintk(2, "%s():  write len = %d\n",
-		__func__, msg.len);
-
-	ret = i2c_transfer(state->i2c, &msg, 1);
-	if (ret != 1) {
-		printk(KERN_ERR "%s(): writereg error err %i\n",
-			 __func__, ret);
-		ret = -EREMOTEIO;
-	}
-
-error:
-	kfree(buf);
-
-	return ret;
-}
-
-static int tda10048_set_phy2(struct dvb_frontend *fe, u32 sample_freq_hz,
-			     u32 if_hz)
-{
-	struct tda10048_state *state = fe->demodulator_priv;
-	u64 t;
-
-	dprintk(1, "%s()\n", __func__);
-
-	if (sample_freq_hz == 0)
-		return -EINVAL;
-
-	if (if_hz < (sample_freq_hz / 2)) {
-		/* PHY2 = (if2/fs) * 2^15 */
-		t = if_hz;
-		t *= 10;
-		t *= 32768;
-		do_div(t, sample_freq_hz);
-		t += 5;
-		do_div(t, 10);
-	} else {
-		/* PHY2 = ((IF1-fs)/fs) * 2^15 */
-		t = sample_freq_hz - if_hz;
-		t *= 10;
-		t *= 32768;
-		do_div(t, sample_freq_hz);
-		t += 5;
-		do_div(t, 10);
-		t = ~t + 1;
-	}
-
-	tda10048_writereg(state, TDA10048_FREQ_PHY2_LSB, (u8)t);
-	tda10048_writereg(state, TDA10048_FREQ_PHY2_MSB, (u8)(t >> 8));
-
-	return 0;
-}
-
-static int tda10048_set_wref(struct dvb_frontend *fe, u32 sample_freq_hz,
-			     u32 bw)
-{
-	struct tda10048_state *state = fe->demodulator_priv;
-	u64 t, z;
-
-	dprintk(1, "%s()\n", __func__);
-
-	if (sample_freq_hz == 0)
-		return -EINVAL;
-
-	/* WREF = (B / (7 * fs)) * 2^31 */
-	t = bw * 10;
-	/* avoid warning: this decimal constant is unsigned only in ISO C90 */
-	/* t *= 2147483648 on 32bit platforms */
-	t *= (2048 * 1024);
-	t *= 1024;
-	z = 7 * sample_freq_hz;
-	do_div(t, z);
-	t += 5;
-	do_div(t, 10);
-
-	tda10048_writereg(state, TDA10048_TIME_WREF_LSB, (u8)t);
-	tda10048_writereg(state, TDA10048_TIME_WREF_MID1, (u8)(t >> 8));
-	tda10048_writereg(state, TDA10048_TIME_WREF_MID2, (u8)(t >> 16));
-	tda10048_writereg(state, TDA10048_TIME_WREF_MSB, (u8)(t >> 24));
-
-	return 0;
-}
-
-static int tda10048_set_invwref(struct dvb_frontend *fe, u32 sample_freq_hz,
-				u32 bw)
-{
-	struct tda10048_state *state = fe->demodulator_priv;
-	u64 t;
-
-	dprintk(1, "%s()\n", __func__);
-
-	if (sample_freq_hz == 0)
-		return -EINVAL;
-
-	/* INVWREF = ((7 * fs) / B) * 2^5 */
-	t = sample_freq_hz;
-	t *= 7;
-	t *= 32;
-	t *= 10;
-	do_div(t, bw);
-	t += 5;
-	do_div(t, 10);
-
-	tda10048_writereg(state, TDA10048_TIME_INVWREF_LSB, (u8)t);
-	tda10048_writereg(state, TDA10048_TIME_INVWREF_MSB, (u8)(t >> 8));
-
-	return 0;
-}
-
-static int tda10048_set_bandwidth(struct dvb_frontend *fe,
-	u32 bw)
-{
-	struct tda10048_state *state = fe->demodulator_priv;
-	dprintk(1, "%s(bw=%d)\n", __func__, bw);
-
-	/* Bandwidth setting may need to be adjusted */
-	switch (bw) {
-	case 6000000:
-	case 7000000:
-	case 8000000:
-		tda10048_set_wref(fe, state->sample_freq, bw);
-		tda10048_set_invwref(fe, state->sample_freq, bw);
-		break;
-	default:
-		printk(KERN_ERR "%s() invalid bandwidth\n", __func__);
-		return -EINVAL;
-	}
-
-	state->bandwidth = bw;
-
-	return 0;
-}
-
-static int tda10048_set_if(struct dvb_frontend *fe, u32 bw)
-{
-	struct tda10048_state *state = fe->demodulator_priv;
-	struct tda10048_config *config = &state->config;
-	int i;
-	u32 if_freq_khz;
-
-	dprintk(1, "%s(bw = %d)\n", __func__, bw);
-
-	/* based on target bandwidth and clk we calculate pll factors */
-	switch (bw) {
-	case 6000000:
-		if_freq_khz = config->dtv6_if_freq_khz;
-		break;
-	case 7000000:
-		if_freq_khz = config->dtv7_if_freq_khz;
-		break;
-	case 8000000:
-		if_freq_khz = config->dtv8_if_freq_khz;
-		break;
-	default:
-		printk(KERN_ERR "%s() no default\n", __func__);
-		return -EINVAL;
-	}
-
-	for (i = 0; i < ARRAY_SIZE(pll_tab); i++) {
-		if ((pll_tab[i].clk_freq_khz == config->clk_freq_khz) &&
-			(pll_tab[i].if_freq_khz == if_freq_khz)) {
-
-			state->freq_if_hz = pll_tab[i].if_freq_khz * 1000;
-			state->xtal_hz = pll_tab[i].clk_freq_khz * 1000;
-			break;
-		}
-	}
-	if (i == ARRAY_SIZE(pll_tab)) {
-		printk(KERN_ERR "%s() Incorrect attach settings\n",
-			__func__);
-		return -EINVAL;
-	}
-
-	dprintk(1, "- freq_if_hz = %d\n", state->freq_if_hz);
-	dprintk(1, "- xtal_hz = %d\n", state->xtal_hz);
-	dprintk(1, "- pll_mfactor = %d\n", state->pll_mfactor);
-	dprintk(1, "- pll_nfactor = %d\n", state->pll_nfactor);
-	dprintk(1, "- pll_pfactor = %d\n", state->pll_pfactor);
-
-	/* Calculate the sample frequency */
-	state->sample_freq = state->xtal_hz * (state->pll_mfactor + 45);
-	state->sample_freq /= (state->pll_nfactor + 1);
-	state->sample_freq /= (state->pll_pfactor + 4);
-	dprintk(1, "- sample_freq = %d\n", state->sample_freq);
-
-	/* Update the I/F */
-	tda10048_set_phy2(fe, state->sample_freq, state->freq_if_hz);
-
-	return 0;
-}
-
-static int tda10048_firmware_upload(struct dvb_frontend *fe)
-{
-	struct tda10048_state *state = fe->demodulator_priv;
-	struct tda10048_config *config = &state->config;
-	const struct firmware *fw;
-	int ret;
-	int pos = 0;
-	int cnt;
-	u8 wlen = config->fwbulkwritelen;
-
-	if ((wlen != TDA10048_BULKWRITE_200) && (wlen != TDA10048_BULKWRITE_50))
-		wlen = TDA10048_BULKWRITE_200;
-
-	/* request the firmware, this will block and timeout */
-	printk(KERN_INFO "%s: waiting for firmware upload (%s)...\n",
-		__func__,
-		TDA10048_DEFAULT_FIRMWARE);
-
-	ret = request_firmware(&fw, TDA10048_DEFAULT_FIRMWARE,
-		state->i2c->dev.parent);
-	if (ret) {
-		printk(KERN_ERR "%s: Upload failed. (file not found?)\n",
-			__func__);
-		return -EIO;
-	} else {
-		printk(KERN_INFO "%s: firmware read %Zu bytes.\n",
-			__func__,
-			fw->size);
-		ret = 0;
-	}
-
-	if (fw->size != TDA10048_DEFAULT_FIRMWARE_SIZE) {
-		printk(KERN_ERR "%s: firmware incorrect size\n", __func__);
-		ret = -EIO;
-	} else {
-		printk(KERN_INFO "%s: firmware uploading\n", __func__);
-
-		/* Soft reset */
-		tda10048_writereg(state, TDA10048_CONF_TRISTATE1,
-			tda10048_readreg(state, TDA10048_CONF_TRISTATE1)
-				& 0xfe);
-		tda10048_writereg(state, TDA10048_CONF_TRISTATE1,
-			tda10048_readreg(state, TDA10048_CONF_TRISTATE1)
-				| 0x01);
-
-		/* Put the demod into host download mode */
-		tda10048_writereg(state, TDA10048_CONF_C4_1,
-			tda10048_readreg(state, TDA10048_CONF_C4_1) & 0xf9);
-
-		/* Boot the DSP */
-		tda10048_writereg(state, TDA10048_CONF_C4_1,
-			tda10048_readreg(state, TDA10048_CONF_C4_1) | 0x08);
-
-		/* Prepare for download */
-		tda10048_writereg(state, TDA10048_DSP_CODE_CPT, 0);
-
-		/* Download the firmware payload */
-		while (pos < fw->size) {
-
-			if ((fw->size - pos) > wlen)
-				cnt = wlen;
-			else
-				cnt = fw->size - pos;
-
-			tda10048_writeregbulk(state, TDA10048_DSP_CODE_IN,
-				&fw->data[pos], cnt);
-
-			pos += cnt;
-		}
-
-		ret = -EIO;
-		/* Wait up to 250ms for the DSP to boot */
-		for (cnt = 0; cnt < 250 ; cnt += 10) {
-
-			msleep(10);
-
-			if (tda10048_readreg(state, TDA10048_SYNC_STATUS)
-				& 0x40) {
-				ret = 0;
-				break;
-			}
-		}
-	}
-
-	release_firmware(fw);
-
-	if (ret == 0) {
-		printk(KERN_INFO "%s: firmware uploaded\n", __func__);
-		state->fwloaded = 1;
-	} else
-		printk(KERN_ERR "%s: firmware upload failed\n", __func__);
-
-	return ret;
-}
-
-static int tda10048_set_inversion(struct dvb_frontend *fe, int inversion)
-{
-	struct tda10048_state *state = fe->demodulator_priv;
-
-	dprintk(1, "%s(%d)\n", __func__, inversion);
-
-	if (inversion == TDA10048_INVERSION_ON)
-		tda10048_writereg(state, TDA10048_CONF_C1_1,
-			tda10048_readreg(state, TDA10048_CONF_C1_1) | 0x20);
-	else
-		tda10048_writereg(state, TDA10048_CONF_C1_1,
-			tda10048_readreg(state, TDA10048_CONF_C1_1) & 0xdf);
-
-	return 0;
-}
-
-/* Retrieve the demod settings */
-static int tda10048_get_tps(struct tda10048_state *state,
-	struct dtv_frontend_properties *p)
-{
-	u8 val;
-
-	/* Make sure the TPS regs are valid */
-	if (!(tda10048_readreg(state, TDA10048_AUTO) & 0x01))
-		return -EAGAIN;
-
-	val = tda10048_readreg(state, TDA10048_OUT_CONF2);
-	switch ((val & 0x60) >> 5) {
-	case 0:
-		p->modulation = QPSK;
-		break;
-	case 1:
-		p->modulation = QAM_16;
-		break;
-	case 2:
-		p->modulation = QAM_64;
-		break;
-	}
-	switch ((val & 0x18) >> 3) {
-	case 0:
-		p->hierarchy = HIERARCHY_NONE;
-		break;
-	case 1:
-		p->hierarchy = HIERARCHY_1;
-		break;
-	case 2:
-		p->hierarchy = HIERARCHY_2;
-		break;
-	case 3:
-		p->hierarchy = HIERARCHY_4;
-		break;
-	}
-	switch (val & 0x07) {
-	case 0:
-		p->code_rate_HP = FEC_1_2;
-		break;
-	case 1:
-		p->code_rate_HP = FEC_2_3;
-		break;
-	case 2:
-		p->code_rate_HP = FEC_3_4;
-		break;
-	case 3:
-		p->code_rate_HP = FEC_5_6;
-		break;
-	case 4:
-		p->code_rate_HP = FEC_7_8;
-		break;
-	}
-
-	val = tda10048_readreg(state, TDA10048_OUT_CONF3);
-	switch (val & 0x07) {
-	case 0:
-		p->code_rate_LP = FEC_1_2;
-		break;
-	case 1:
-		p->code_rate_LP = FEC_2_3;
-		break;
-	case 2:
-		p->code_rate_LP = FEC_3_4;
-		break;
-	case 3:
-		p->code_rate_LP = FEC_5_6;
-		break;
-	case 4:
-		p->code_rate_LP = FEC_7_8;
-		break;
-	}
-
-	val = tda10048_readreg(state, TDA10048_OUT_CONF1);
-	switch ((val & 0x0c) >> 2) {
-	case 0:
-		p->guard_interval = GUARD_INTERVAL_1_32;
-		break;
-	case 1:
-		p->guard_interval = GUARD_INTERVAL_1_16;
-		break;
-	case 2:
-		p->guard_interval =  GUARD_INTERVAL_1_8;
-		break;
-	case 3:
-		p->guard_interval =  GUARD_INTERVAL_1_4;
-		break;
-	}
-	switch (val & 0x03) {
-	case 0:
-		p->transmission_mode = TRANSMISSION_MODE_2K;
-		break;
-	case 1:
-		p->transmission_mode = TRANSMISSION_MODE_8K;
-		break;
-	}
-
-	return 0;
-}
-
-static int tda10048_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
-{
-	struct tda10048_state *state = fe->demodulator_priv;
-	struct tda10048_config *config = &state->config;
-	dprintk(1, "%s(%d)\n", __func__, enable);
-
-	if (config->disable_gate_access)
-		return 0;
-
-	if (enable)
-		return tda10048_writereg(state, TDA10048_CONF_C4_1,
-			tda10048_readreg(state, TDA10048_CONF_C4_1) | 0x02);
-	else
-		return tda10048_writereg(state, TDA10048_CONF_C4_1,
-			tda10048_readreg(state, TDA10048_CONF_C4_1) & 0xfd);
-}
-
-static int tda10048_output_mode(struct dvb_frontend *fe, int serial)
-{
-	struct tda10048_state *state = fe->demodulator_priv;
-	dprintk(1, "%s(%d)\n", __func__, serial);
-
-	/* Ensure pins are out of tri-state */
-	tda10048_writereg(state, TDA10048_CONF_TRISTATE1, 0x21);
-	tda10048_writereg(state, TDA10048_CONF_TRISTATE2, 0x00);
-
-	if (serial) {
-		tda10048_writereg(state, TDA10048_IC_MODE, 0x80 | 0x20);
-		tda10048_writereg(state, TDA10048_CONF_TS2, 0xc0);
-	} else {
-		tda10048_writereg(state, TDA10048_IC_MODE, 0x00);
-		tda10048_writereg(state, TDA10048_CONF_TS2, 0x01);
-	}
-
-	return 0;
-}
-
-/* Talk to the demod, set the FEC, GUARD, QAM settings etc */
-/* TODO: Support manual tuning with specific params */
-static int tda10048_set_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct tda10048_state *state = fe->demodulator_priv;
-
-	dprintk(1, "%s(frequency=%d)\n", __func__, p->frequency);
-
-	/* Update the I/F pll's if the bandwidth changes */
-	if (p->bandwidth_hz != state->bandwidth) {
-		tda10048_set_if(fe, p->bandwidth_hz);
-		tda10048_set_bandwidth(fe, p->bandwidth_hz);
-	}
-
-	if (fe->ops.tuner_ops.set_params) {
-
-		if (fe->ops.i2c_gate_ctrl)
-			fe->ops.i2c_gate_ctrl(fe, 1);
-
-		fe->ops.tuner_ops.set_params(fe);
-
-		if (fe->ops.i2c_gate_ctrl)
-			fe->ops.i2c_gate_ctrl(fe, 0);
-	}
-
-	/* Enable demod TPS auto detection and begin acquisition */
-	tda10048_writereg(state, TDA10048_AUTO, 0x57);
-	/* trigger cber and vber acquisition */
-	tda10048_writereg(state, TDA10048_CVBER_CTRL, 0x3B);
-
-	return 0;
-}
-
-/* Establish sane defaults and load firmware. */
-static int tda10048_init(struct dvb_frontend *fe)
-{
-	struct tda10048_state *state = fe->demodulator_priv;
-	struct tda10048_config *config = &state->config;
-	int ret = 0, i;
-
-	dprintk(1, "%s()\n", __func__);
-
-	/* PLL */
-	init_tab[4].data = (u8)(state->pll_mfactor);
-	init_tab[5].data = (u8)(state->pll_nfactor) | 0x40;
-
-	/* Apply register defaults */
-	for (i = 0; i < ARRAY_SIZE(init_tab); i++)
-		tda10048_writereg(state, init_tab[i].reg, init_tab[i].data);
-
-	if (state->fwloaded == 0)
-		ret = tda10048_firmware_upload(fe);
-
-	/* Set either serial or parallel */
-	tda10048_output_mode(fe, config->output_mode);
-
-	/* Set inversion */
-	tda10048_set_inversion(fe, config->inversion);
-
-	/* Establish default RF values */
-	tda10048_set_if(fe, 8000000);
-	tda10048_set_bandwidth(fe, 8000000);
-
-	/* Ensure we leave the gate closed */
-	tda10048_i2c_gate_ctrl(fe, 0);
-
-	return ret;
-}
-
-static int tda10048_read_status(struct dvb_frontend *fe, fe_status_t *status)
-{
-	struct tda10048_state *state = fe->demodulator_priv;
-	u8 reg;
-
-	*status = 0;
-
-	reg = tda10048_readreg(state, TDA10048_SYNC_STATUS);
-
-	dprintk(1, "%s() status =0x%02x\n", __func__, reg);
-
-	if (reg & 0x02)
-		*status |= FE_HAS_CARRIER;
-
-	if (reg & 0x04)
-		*status |= FE_HAS_SIGNAL;
-
-	if (reg & 0x08) {
-		*status |= FE_HAS_LOCK;
-		*status |= FE_HAS_VITERBI;
-		*status |= FE_HAS_SYNC;
-	}
-
-	return 0;
-}
-
-static int tda10048_read_ber(struct dvb_frontend *fe, u32 *ber)
-{
-	struct tda10048_state *state = fe->demodulator_priv;
-	static u32 cber_current;
-	u32 cber_nmax;
-	u64 cber_tmp;
-
-	dprintk(1, "%s()\n", __func__);
-
-	/* update cber on interrupt */
-	if (tda10048_readreg(state, TDA10048_SOFT_IT_C3) & 0x01) {
-		cber_tmp = tda10048_readreg(state, TDA10048_CBER_MSB) << 8 |
-			tda10048_readreg(state, TDA10048_CBER_LSB);
-		cber_nmax = tda10048_readreg(state, TDA10048_CBER_NMAX_MSB) << 8 |
-			tda10048_readreg(state, TDA10048_CBER_NMAX_LSB);
-		cber_tmp *= 100000000;
-		cber_tmp *= 2;
-		cber_tmp = div_u64(cber_tmp, (cber_nmax * 32) + 1);
-		cber_current = (u32)cber_tmp;
-		/* retrigger cber acquisition */
-		tda10048_writereg(state, TDA10048_CVBER_CTRL, 0x39);
-	}
-	/* actual cber is (*ber)/1e8 */
-	*ber = cber_current;
-
-	return 0;
-}
-
-static int tda10048_read_signal_strength(struct dvb_frontend *fe,
-	u16 *signal_strength)
-{
-	struct tda10048_state *state = fe->demodulator_priv;
-	u8 v;
-
-	dprintk(1, "%s()\n", __func__);
-
-	*signal_strength = 65535;
-
-	v = tda10048_readreg(state, TDA10048_NP_OUT);
-	if (v > 0)
-		*signal_strength -= (v << 8) | v;
-
-	return 0;
-}
-
-/* SNR lookup table */
-static struct snr_tab {
-	u8 val;
-	u8 data;
-} snr_tab[] = {
-	{   0,   0 },
-	{   1, 246 },
-	{   2, 215 },
-	{   3, 198 },
-	{   4, 185 },
-	{   5, 176 },
-	{   6, 168 },
-	{   7, 161 },
-	{   8, 155 },
-	{   9, 150 },
-	{  10, 146 },
-	{  11, 141 },
-	{  12, 138 },
-	{  13, 134 },
-	{  14, 131 },
-	{  15, 128 },
-	{  16, 125 },
-	{  17, 122 },
-	{  18, 120 },
-	{  19, 118 },
-	{  20, 115 },
-	{  21, 113 },
-	{  22, 111 },
-	{  23, 109 },
-	{  24, 107 },
-	{  25, 106 },
-	{  26, 104 },
-	{  27, 102 },
-	{  28, 101 },
-	{  29,  99 },
-	{  30,  98 },
-	{  31,  96 },
-	{  32,  95 },
-	{  33,  94 },
-	{  34,  92 },
-	{  35,  91 },
-	{  36,  90 },
-	{  37,  89 },
-	{  38,  88 },
-	{  39,  86 },
-	{  40,  85 },
-	{  41,  84 },
-	{  42,  83 },
-	{  43,  82 },
-	{  44,  81 },
-	{  45,  80 },
-	{  46,  79 },
-	{  47,  78 },
-	{  48,  77 },
-	{  49,  76 },
-	{  50,  76 },
-	{  51,  75 },
-	{  52,  74 },
-	{  53,  73 },
-	{  54,  72 },
-	{  56,  71 },
-	{  57,  70 },
-	{  58,  69 },
-	{  60,  68 },
-	{  61,  67 },
-	{  63,  66 },
-	{  64,  65 },
-	{  66,  64 },
-	{  67,  63 },
-	{  68,  62 },
-	{  69,  62 },
-	{  70,  61 },
-	{  72,  60 },
-	{  74,  59 },
-	{  75,  58 },
-	{  77,  57 },
-	{  79,  56 },
-	{  81,  55 },
-	{  83,  54 },
-	{  85,  53 },
-	{  87,  52 },
-	{  89,  51 },
-	{  91,  50 },
-	{  93,  49 },
-	{  95,  48 },
-	{  97,  47 },
-	{ 100,  46 },
-	{ 102,  45 },
-	{ 104,  44 },
-	{ 107,  43 },
-	{ 109,  42 },
-	{ 112,  41 },
-	{ 114,  40 },
-	{ 117,  39 },
-	{ 120,  38 },
-	{ 123,  37 },
-	{ 125,  36 },
-	{ 128,  35 },
-	{ 131,  34 },
-	{ 134,  33 },
-	{ 138,  32 },
-	{ 141,  31 },
-	{ 144,  30 },
-	{ 147,  29 },
-	{ 151,  28 },
-	{ 154,  27 },
-	{ 158,  26 },
-	{ 162,  25 },
-	{ 165,  24 },
-	{ 169,  23 },
-	{ 173,  22 },
-	{ 177,  21 },
-	{ 181,  20 },
-	{ 186,  19 },
-	{ 190,  18 },
-	{ 194,  17 },
-	{ 199,  16 },
-	{ 204,  15 },
-	{ 208,  14 },
-	{ 213,  13 },
-	{ 218,  12 },
-	{ 223,  11 },
-	{ 229,  10 },
-	{ 234,   9 },
-	{ 239,   8 },
-	{ 245,   7 },
-	{ 251,   6 },
-	{ 255,   5 },
-};
-
-static int tda10048_read_snr(struct dvb_frontend *fe, u16 *snr)
-{
-	struct tda10048_state *state = fe->demodulator_priv;
-	u8 v;
-	int i, ret = -EINVAL;
-
-	dprintk(1, "%s()\n", __func__);
-
-	v = tda10048_readreg(state, TDA10048_NP_OUT);
-	for (i = 0; i < ARRAY_SIZE(snr_tab); i++) {
-		if (v <= snr_tab[i].val) {
-			*snr = snr_tab[i].data;
-			ret = 0;
-			break;
-		}
-	}
-
-	return ret;
-}
-
-static int tda10048_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
-{
-	struct tda10048_state *state = fe->demodulator_priv;
-
-	dprintk(1, "%s()\n", __func__);
-
-	*ucblocks = tda10048_readreg(state, TDA10048_UNCOR_CPT_MSB) << 8 |
-		tda10048_readreg(state, TDA10048_UNCOR_CPT_LSB);
-	/* clear the uncorrected TS packets counter when saturated */
-	if (*ucblocks == 0xFFFF)
-		tda10048_writereg(state, TDA10048_UNCOR_CTRL, 0x80);
-
-	return 0;
-}
-
-static int tda10048_get_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct tda10048_state *state = fe->demodulator_priv;
-
-	dprintk(1, "%s()\n", __func__);
-
-	p->inversion = tda10048_readreg(state, TDA10048_CONF_C1_1)
-		& 0x20 ? INVERSION_ON : INVERSION_OFF;
-
-	return tda10048_get_tps(state, p);
-}
-
-static int tda10048_get_tune_settings(struct dvb_frontend *fe,
-	struct dvb_frontend_tune_settings *tune)
-{
-	tune->min_delay_ms = 1000;
-	return 0;
-}
-
-static void tda10048_release(struct dvb_frontend *fe)
-{
-	struct tda10048_state *state = fe->demodulator_priv;
-	dprintk(1, "%s()\n", __func__);
-	kfree(state);
-}
-
-static void tda10048_establish_defaults(struct dvb_frontend *fe)
-{
-	struct tda10048_state *state = fe->demodulator_priv;
-	struct tda10048_config *config = &state->config;
-
-	/* Validate/default the config */
-	if (config->dtv6_if_freq_khz == 0) {
-		config->dtv6_if_freq_khz = TDA10048_IF_4300;
-		printk(KERN_WARNING "%s() tda10048_config.dtv6_if_freq_khz "
-			"is not set (defaulting to %d)\n",
-			__func__,
-			config->dtv6_if_freq_khz);
-	}
-
-	if (config->dtv7_if_freq_khz == 0) {
-		config->dtv7_if_freq_khz = TDA10048_IF_4300;
-		printk(KERN_WARNING "%s() tda10048_config.dtv7_if_freq_khz "
-			"is not set (defaulting to %d)\n",
-			__func__,
-			config->dtv7_if_freq_khz);
-	}
-
-	if (config->dtv8_if_freq_khz == 0) {
-		config->dtv8_if_freq_khz = TDA10048_IF_4300;
-		printk(KERN_WARNING "%s() tda10048_config.dtv8_if_freq_khz "
-			"is not set (defaulting to %d)\n",
-			__func__,
-			config->dtv8_if_freq_khz);
-	}
-
-	if (config->clk_freq_khz == 0) {
-		config->clk_freq_khz = TDA10048_CLK_16000;
-		printk(KERN_WARNING "%s() tda10048_config.clk_freq_khz "
-			"is not set (defaulting to %d)\n",
-			__func__,
-			config->clk_freq_khz);
-	}
-}
-
-static struct dvb_frontend_ops tda10048_ops;
-
-struct dvb_frontend *tda10048_attach(const struct tda10048_config *config,
-	struct i2c_adapter *i2c)
-{
-	struct tda10048_state *state = NULL;
-
-	dprintk(1, "%s()\n", __func__);
-
-	/* allocate memory for the internal state */
-	state = kzalloc(sizeof(struct tda10048_state), GFP_KERNEL);
-	if (state == NULL)
-		goto error;
-
-	/* setup the state and clone the config */
-	memcpy(&state->config, config, sizeof(*config));
-	state->i2c = i2c;
-	state->fwloaded = config->no_firmware;
-	state->bandwidth = 8000000;
-
-	/* check if the demod is present */
-	if (tda10048_readreg(state, TDA10048_IDENTITY) != 0x048)
-		goto error;
-
-	/* create dvb_frontend */
-	memcpy(&state->frontend.ops, &tda10048_ops,
-		sizeof(struct dvb_frontend_ops));
-	state->frontend.demodulator_priv = state;
-
-	/* set pll */
-	if (config->set_pll) {
-		state->pll_mfactor = config->pll_m;
-		state->pll_nfactor = config->pll_n;
-		state->pll_pfactor = config->pll_p;
-	} else {
-		state->pll_mfactor = 10;
-		state->pll_nfactor = 3;
-		state->pll_pfactor = 0;
-	}
-
-	/* Establish any defaults the the user didn't pass */
-	tda10048_establish_defaults(&state->frontend);
-
-	/* Set the xtal and freq defaults */
-	if (tda10048_set_if(&state->frontend, 8000000) != 0)
-		goto error;
-
-	/* Default bandwidth */
-	if (tda10048_set_bandwidth(&state->frontend, 8000000) != 0)
-		goto error;
-
-	/* Leave the gate closed */
-	tda10048_i2c_gate_ctrl(&state->frontend, 0);
-
-	return &state->frontend;
-
-error:
-	kfree(state);
-	return NULL;
-}
-EXPORT_SYMBOL(tda10048_attach);
-
-static struct dvb_frontend_ops tda10048_ops = {
-	.delsys = { SYS_DVBT },
-	.info = {
-		.name			= "NXP TDA10048HN DVB-T",
-		.frequency_min		= 177000000,
-		.frequency_max		= 858000000,
-		.frequency_stepsize	= 166666,
-		.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_FEC_AUTO |
-		FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
-		FE_CAN_HIERARCHY_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |
-		FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_RECOVER
-	},
-
-	.release = tda10048_release,
-	.init = tda10048_init,
-	.i2c_gate_ctrl = tda10048_i2c_gate_ctrl,
-	.set_frontend = tda10048_set_frontend,
-	.get_frontend = tda10048_get_frontend,
-	.get_tune_settings = tda10048_get_tune_settings,
-	.read_status = tda10048_read_status,
-	.read_ber = tda10048_read_ber,
-	.read_signal_strength = tda10048_read_signal_strength,
-	.read_snr = tda10048_read_snr,
-	.read_ucblocks = tda10048_read_ucblocks,
-};
-
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Enable verbose debug messages");
-
-MODULE_DESCRIPTION("NXP TDA10048HN DVB-T Demodulator driver");
-MODULE_AUTHOR("Steven Toth");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/tda10048.h b/drivers/media/dvb/frontends/tda10048.h
deleted file mode 100644
index fb2ef5a..0000000
--- a/drivers/media/dvb/frontends/tda10048.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
-    NXP TDA10048HN DVB OFDM demodulator driver
-
-    Copyright (C) 2009 Steven Toth <stoth@kernellabs.com>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#ifndef TDA10048_H
-#define TDA10048_H
-
-#include <linux/dvb/frontend.h>
-#include <linux/firmware.h>
-
-struct tda10048_config {
-
-	/* the demodulator's i2c address */
-	u8 demod_address;
-
-	/* serial/parallel output */
-#define TDA10048_PARALLEL_OUTPUT 0
-#define TDA10048_SERIAL_OUTPUT   1
-	u8 output_mode;
-
-#define TDA10048_BULKWRITE_200	200
-#define TDA10048_BULKWRITE_50	50
-	u8 fwbulkwritelen;
-
-	/* Spectral Inversion */
-#define TDA10048_INVERSION_OFF 0
-#define TDA10048_INVERSION_ON  1
-	u8 inversion;
-
-#define TDA10048_IF_3300  3300
-#define TDA10048_IF_3500  3500
-#define TDA10048_IF_3800  3800
-#define TDA10048_IF_4000  4000
-#define TDA10048_IF_4300  4300
-#define TDA10048_IF_4500  4500
-#define TDA10048_IF_4750  4750
-#define TDA10048_IF_5000  5000
-#define TDA10048_IF_36130 36130
-	u16 dtv6_if_freq_khz;
-	u16 dtv7_if_freq_khz;
-	u16 dtv8_if_freq_khz;
-
-#define TDA10048_CLK_4000  4000
-#define TDA10048_CLK_16000 16000
-	u16 clk_freq_khz;
-
-	/* Disable I2C gate access */
-	u8 disable_gate_access;
-
-	bool no_firmware;
-
-	bool set_pll;
-	u8 pll_m;
-	u8 pll_p;
-	u8 pll_n;
-};
-
-#if defined(CONFIG_DVB_TDA10048) || \
-	(defined(CONFIG_DVB_TDA10048_MODULE) && defined(MODULE))
-extern struct dvb_frontend *tda10048_attach(
-	const struct tda10048_config *config,
-	struct i2c_adapter *i2c);
-#else
-static inline struct dvb_frontend *tda10048_attach(
-	const struct tda10048_config *config,
-	struct i2c_adapter *i2c)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif /* CONFIG_DVB_TDA10048 */
-
-#endif /* TDA10048_H */
diff --git a/drivers/media/dvb/frontends/tda1004x.c b/drivers/media/dvb/frontends/tda1004x.c
deleted file mode 100644
index 35d72b4..0000000
--- a/drivers/media/dvb/frontends/tda1004x.c
+++ /dev/null
@@ -1,1381 +0,0 @@
-  /*
-     Driver for Philips tda1004xh OFDM Demodulator
-
-     (c) 2003, 2004 Andrew de Quincey & Robert Schlabbach
-
-     This program is free software; you can redistribute it and/or modify
-     it under the terms of the 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.
-
-   */
-/*
- * This driver needs external firmware. Please use the commands
- * "<kerneldir>/Documentation/dvb/get_dvb_firmware tda10045",
- * "<kerneldir>/Documentation/dvb/get_dvb_firmware tda10046" to
- * download/extract them, and then copy them to /usr/lib/hotplug/firmware
- * or /lib/firmware (depending on configuration of firmware hotplug).
- */
-#define TDA10045_DEFAULT_FIRMWARE "dvb-fe-tda10045.fw"
-#define TDA10046_DEFAULT_FIRMWARE "dvb-fe-tda10046.fw"
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/jiffies.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-
-#include "dvb_frontend.h"
-#include "tda1004x.h"
-
-static int debug;
-#define dprintk(args...) \
-	do { \
-		if (debug) printk(KERN_DEBUG "tda1004x: " args); \
-	} while (0)
-
-#define TDA1004X_CHIPID		 0x00
-#define TDA1004X_AUTO		 0x01
-#define TDA1004X_IN_CONF1	 0x02
-#define TDA1004X_IN_CONF2	 0x03
-#define TDA1004X_OUT_CONF1	 0x04
-#define TDA1004X_OUT_CONF2	 0x05
-#define TDA1004X_STATUS_CD	 0x06
-#define TDA1004X_CONFC4		 0x07
-#define TDA1004X_DSSPARE2	 0x0C
-#define TDA10045H_CODE_IN	 0x0D
-#define TDA10045H_FWPAGE	 0x0E
-#define TDA1004X_SCAN_CPT	 0x10
-#define TDA1004X_DSP_CMD	 0x11
-#define TDA1004X_DSP_ARG	 0x12
-#define TDA1004X_DSP_DATA1	 0x13
-#define TDA1004X_DSP_DATA2	 0x14
-#define TDA1004X_CONFADC1	 0x15
-#define TDA1004X_CONFC1		 0x16
-#define TDA10045H_S_AGC		 0x1a
-#define TDA10046H_AGC_TUN_LEVEL	 0x1a
-#define TDA1004X_SNR		 0x1c
-#define TDA1004X_CONF_TS1	 0x1e
-#define TDA1004X_CONF_TS2	 0x1f
-#define TDA1004X_CBER_RESET	 0x20
-#define TDA1004X_CBER_MSB	 0x21
-#define TDA1004X_CBER_LSB	 0x22
-#define TDA1004X_CVBER_LUT	 0x23
-#define TDA1004X_VBER_MSB	 0x24
-#define TDA1004X_VBER_MID	 0x25
-#define TDA1004X_VBER_LSB	 0x26
-#define TDA1004X_UNCOR		 0x27
-
-#define TDA10045H_CONFPLL_P	 0x2D
-#define TDA10045H_CONFPLL_M_MSB	 0x2E
-#define TDA10045H_CONFPLL_M_LSB	 0x2F
-#define TDA10045H_CONFPLL_N	 0x30
-
-#define TDA10046H_CONFPLL1	 0x2D
-#define TDA10046H_CONFPLL2	 0x2F
-#define TDA10046H_CONFPLL3	 0x30
-#define TDA10046H_TIME_WREF1	 0x31
-#define TDA10046H_TIME_WREF2	 0x32
-#define TDA10046H_TIME_WREF3	 0x33
-#define TDA10046H_TIME_WREF4	 0x34
-#define TDA10046H_TIME_WREF5	 0x35
-
-#define TDA10045H_UNSURW_MSB	 0x31
-#define TDA10045H_UNSURW_LSB	 0x32
-#define TDA10045H_WREF_MSB	 0x33
-#define TDA10045H_WREF_MID	 0x34
-#define TDA10045H_WREF_LSB	 0x35
-#define TDA10045H_MUXOUT	 0x36
-#define TDA1004X_CONFADC2	 0x37
-
-#define TDA10045H_IOFFSET	 0x38
-
-#define TDA10046H_CONF_TRISTATE1 0x3B
-#define TDA10046H_CONF_TRISTATE2 0x3C
-#define TDA10046H_CONF_POLARITY	 0x3D
-#define TDA10046H_FREQ_OFFSET	 0x3E
-#define TDA10046H_GPIO_OUT_SEL	 0x41
-#define TDA10046H_GPIO_SELECT	 0x42
-#define TDA10046H_AGC_CONF	 0x43
-#define TDA10046H_AGC_THR	 0x44
-#define TDA10046H_AGC_RENORM	 0x45
-#define TDA10046H_AGC_GAINS	 0x46
-#define TDA10046H_AGC_TUN_MIN	 0x47
-#define TDA10046H_AGC_TUN_MAX	 0x48
-#define TDA10046H_AGC_IF_MIN	 0x49
-#define TDA10046H_AGC_IF_MAX	 0x4A
-
-#define TDA10046H_FREQ_PHY2_MSB	 0x4D
-#define TDA10046H_FREQ_PHY2_LSB	 0x4E
-
-#define TDA10046H_CVBER_CTRL	 0x4F
-#define TDA10046H_AGC_IF_LEVEL	 0x52
-#define TDA10046H_CODE_CPT	 0x57
-#define TDA10046H_CODE_IN	 0x58
-
-
-static int tda1004x_write_byteI(struct tda1004x_state *state, int reg, int data)
-{
-	int ret;
-	u8 buf[] = { reg, data };
-	struct i2c_msg msg = { .flags = 0, .buf = buf, .len = 2 };
-
-	dprintk("%s: reg=0x%x, data=0x%x\n", __func__, reg, data);
-
-	msg.addr = state->config->demod_address;
-	ret = i2c_transfer(state->i2c, &msg, 1);
-
-	if (ret != 1)
-		dprintk("%s: error reg=0x%x, data=0x%x, ret=%i\n",
-			__func__, reg, data, ret);
-
-	dprintk("%s: success reg=0x%x, data=0x%x, ret=%i\n", __func__,
-		reg, data, ret);
-	return (ret != 1) ? -1 : 0;
-}
-
-static int tda1004x_read_byte(struct tda1004x_state *state, int reg)
-{
-	int ret;
-	u8 b0[] = { reg };
-	u8 b1[] = { 0 };
-	struct i2c_msg msg[] = {{ .flags = 0, .buf = b0, .len = 1 },
-				{ .flags = I2C_M_RD, .buf = b1, .len = 1 }};
-
-	dprintk("%s: reg=0x%x\n", __func__, reg);
-
-	msg[0].addr = state->config->demod_address;
-	msg[1].addr = state->config->demod_address;
-	ret = i2c_transfer(state->i2c, msg, 2);
-
-	if (ret != 2) {
-		dprintk("%s: error reg=0x%x, ret=%i\n", __func__, reg,
-			ret);
-		return -EINVAL;
-	}
-
-	dprintk("%s: success reg=0x%x, data=0x%x, ret=%i\n", __func__,
-		reg, b1[0], ret);
-	return b1[0];
-}
-
-static int tda1004x_write_mask(struct tda1004x_state *state, int reg, int mask, int data)
-{
-	int val;
-	dprintk("%s: reg=0x%x, mask=0x%x, data=0x%x\n", __func__, reg,
-		mask, data);
-
-	// read a byte and check
-	val = tda1004x_read_byte(state, reg);
-	if (val < 0)
-		return val;
-
-	// mask if off
-	val = val & ~mask;
-	val |= data & 0xff;
-
-	// write it out again
-	return tda1004x_write_byteI(state, reg, val);
-}
-
-static int tda1004x_write_buf(struct tda1004x_state *state, int reg, unsigned char *buf, int len)
-{
-	int i;
-	int result;
-
-	dprintk("%s: reg=0x%x, len=0x%x\n", __func__, reg, len);
-
-	result = 0;
-	for (i = 0; i < len; i++) {
-		result = tda1004x_write_byteI(state, reg + i, buf[i]);
-		if (result != 0)
-			break;
-	}
-
-	return result;
-}
-
-static int tda1004x_enable_tuner_i2c(struct tda1004x_state *state)
-{
-	int result;
-	dprintk("%s\n", __func__);
-
-	result = tda1004x_write_mask(state, TDA1004X_CONFC4, 2, 2);
-	msleep(20);
-	return result;
-}
-
-static int tda1004x_disable_tuner_i2c(struct tda1004x_state *state)
-{
-	dprintk("%s\n", __func__);
-
-	return tda1004x_write_mask(state, TDA1004X_CONFC4, 2, 0);
-}
-
-static int tda10045h_set_bandwidth(struct tda1004x_state *state,
-				   u32 bandwidth)
-{
-	static u8 bandwidth_6mhz[] = { 0x02, 0x00, 0x3d, 0x00, 0x60, 0x1e, 0xa7, 0x45, 0x4f };
-	static u8 bandwidth_7mhz[] = { 0x02, 0x00, 0x37, 0x00, 0x4a, 0x2f, 0x6d, 0x76, 0xdb };
-	static u8 bandwidth_8mhz[] = { 0x02, 0x00, 0x3d, 0x00, 0x48, 0x17, 0x89, 0xc7, 0x14 };
-
-	switch (bandwidth) {
-	case 6000000:
-		tda1004x_write_buf(state, TDA10045H_CONFPLL_P, bandwidth_6mhz, sizeof(bandwidth_6mhz));
-		break;
-
-	case 7000000:
-		tda1004x_write_buf(state, TDA10045H_CONFPLL_P, bandwidth_7mhz, sizeof(bandwidth_7mhz));
-		break;
-
-	case 8000000:
-		tda1004x_write_buf(state, TDA10045H_CONFPLL_P, bandwidth_8mhz, sizeof(bandwidth_8mhz));
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	tda1004x_write_byteI(state, TDA10045H_IOFFSET, 0);
-
-	return 0;
-}
-
-static int tda10046h_set_bandwidth(struct tda1004x_state *state,
-				   u32 bandwidth)
-{
-	static u8 bandwidth_6mhz_53M[] = { 0x7b, 0x2e, 0x11, 0xf0, 0xd2 };
-	static u8 bandwidth_7mhz_53M[] = { 0x6a, 0x02, 0x6a, 0x43, 0x9f };
-	static u8 bandwidth_8mhz_53M[] = { 0x5c, 0x32, 0xc2, 0x96, 0x6d };
-
-	static u8 bandwidth_6mhz_48M[] = { 0x70, 0x02, 0x49, 0x24, 0x92 };
-	static u8 bandwidth_7mhz_48M[] = { 0x60, 0x02, 0xaa, 0xaa, 0xab };
-	static u8 bandwidth_8mhz_48M[] = { 0x54, 0x03, 0x0c, 0x30, 0xc3 };
-	int tda10046_clk53m;
-
-	if ((state->config->if_freq == TDA10046_FREQ_045) ||
-	    (state->config->if_freq == TDA10046_FREQ_052))
-		tda10046_clk53m = 0;
-	else
-		tda10046_clk53m = 1;
-	switch (bandwidth) {
-	case 6000000:
-		if (tda10046_clk53m)
-			tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_6mhz_53M,
-						  sizeof(bandwidth_6mhz_53M));
-		else
-			tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_6mhz_48M,
-						  sizeof(bandwidth_6mhz_48M));
-		if (state->config->if_freq == TDA10046_FREQ_045) {
-			tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0a);
-			tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0xab);
-		}
-		break;
-
-	case 7000000:
-		if (tda10046_clk53m)
-			tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_7mhz_53M,
-						  sizeof(bandwidth_7mhz_53M));
-		else
-			tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_7mhz_48M,
-						  sizeof(bandwidth_7mhz_48M));
-		if (state->config->if_freq == TDA10046_FREQ_045) {
-			tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0c);
-			tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x00);
-		}
-		break;
-
-	case 8000000:
-		if (tda10046_clk53m)
-			tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_8mhz_53M,
-						  sizeof(bandwidth_8mhz_53M));
-		else
-			tda1004x_write_buf(state, TDA10046H_TIME_WREF1, bandwidth_8mhz_48M,
-						  sizeof(bandwidth_8mhz_48M));
-		if (state->config->if_freq == TDA10046_FREQ_045) {
-			tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0d);
-			tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x55);
-		}
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int tda1004x_do_upload(struct tda1004x_state *state,
-			      const unsigned char *mem, unsigned int len,
-			      u8 dspCodeCounterReg, u8 dspCodeInReg)
-{
-	u8 buf[65];
-	struct i2c_msg fw_msg = { .flags = 0, .buf = buf, .len = 0 };
-	int tx_size;
-	int pos = 0;
-
-	/* clear code counter */
-	tda1004x_write_byteI(state, dspCodeCounterReg, 0);
-	fw_msg.addr = state->config->demod_address;
-
-	buf[0] = dspCodeInReg;
-	while (pos != len) {
-		// work out how much to send this time
-		tx_size = len - pos;
-		if (tx_size > 0x10)
-			tx_size = 0x10;
-
-		// send the chunk
-		memcpy(buf + 1, mem + pos, tx_size);
-		fw_msg.len = tx_size + 1;
-		if (i2c_transfer(state->i2c, &fw_msg, 1) != 1) {
-			printk(KERN_ERR "tda1004x: Error during firmware upload\n");
-			return -EIO;
-		}
-		pos += tx_size;
-
-		dprintk("%s: fw_pos=0x%x\n", __func__, pos);
-	}
-	// give the DSP a chance to settle 03/10/05 Hac
-	msleep(100);
-
-	return 0;
-}
-
-static int tda1004x_check_upload_ok(struct tda1004x_state *state)
-{
-	u8 data1, data2;
-	unsigned long timeout;
-
-	if (state->demod_type == TDA1004X_DEMOD_TDA10046) {
-		timeout = jiffies + 2 * HZ;
-		while(!(tda1004x_read_byte(state, TDA1004X_STATUS_CD) & 0x20)) {
-			if (time_after(jiffies, timeout)) {
-				printk(KERN_ERR "tda1004x: timeout waiting for DSP ready\n");
-				break;
-			}
-			msleep(1);
-		}
-	} else
-		msleep(100);
-
-	// check upload was OK
-	tda1004x_write_mask(state, TDA1004X_CONFC4, 0x10, 0); // we want to read from the DSP
-	tda1004x_write_byteI(state, TDA1004X_DSP_CMD, 0x67);
-
-	data1 = tda1004x_read_byte(state, TDA1004X_DSP_DATA1);
-	data2 = tda1004x_read_byte(state, TDA1004X_DSP_DATA2);
-	if (data1 != 0x67 || data2 < 0x20 || data2 > 0x2e) {
-		printk(KERN_INFO "tda1004x: found firmware revision %x -- invalid\n", data2);
-		return -EIO;
-	}
-	printk(KERN_INFO "tda1004x: found firmware revision %x -- ok\n", data2);
-	return 0;
-}
-
-static int tda10045_fwupload(struct dvb_frontend* fe)
-{
-	struct tda1004x_state* state = fe->demodulator_priv;
-	int ret;
-	const struct firmware *fw;
-
-	/* don't re-upload unless necessary */
-	if (tda1004x_check_upload_ok(state) == 0)
-		return 0;
-
-	/* request the firmware, this will block until someone uploads it */
-	printk(KERN_INFO "tda1004x: waiting for firmware upload (%s)...\n", TDA10045_DEFAULT_FIRMWARE);
-	ret = state->config->request_firmware(fe, &fw, TDA10045_DEFAULT_FIRMWARE);
-	if (ret) {
-		printk(KERN_ERR "tda1004x: no firmware upload (timeout or file not found?)\n");
-		return ret;
-	}
-
-	/* reset chip */
-	tda1004x_write_mask(state, TDA1004X_CONFC4, 0x10, 0);
-	tda1004x_write_mask(state, TDA1004X_CONFC4, 8, 8);
-	tda1004x_write_mask(state, TDA1004X_CONFC4, 8, 0);
-	msleep(10);
-
-	/* set parameters */
-	tda10045h_set_bandwidth(state, 8000000);
-
-	ret = tda1004x_do_upload(state, fw->data, fw->size, TDA10045H_FWPAGE, TDA10045H_CODE_IN);
-	release_firmware(fw);
-	if (ret)
-		return ret;
-	printk(KERN_INFO "tda1004x: firmware upload complete\n");
-
-	/* wait for DSP to initialise */
-	/* DSPREADY doesn't seem to work on the TDA10045H */
-	msleep(100);
-
-	return tda1004x_check_upload_ok(state);
-}
-
-static void tda10046_init_plls(struct dvb_frontend* fe)
-{
-	struct tda1004x_state* state = fe->demodulator_priv;
-	int tda10046_clk53m;
-
-	if ((state->config->if_freq == TDA10046_FREQ_045) ||
-	    (state->config->if_freq == TDA10046_FREQ_052))
-		tda10046_clk53m = 0;
-	else
-		tda10046_clk53m = 1;
-
-	tda1004x_write_byteI(state, TDA10046H_CONFPLL1, 0xf0);
-	if(tda10046_clk53m) {
-		printk(KERN_INFO "tda1004x: setting up plls for 53MHz sampling clock\n");
-		tda1004x_write_byteI(state, TDA10046H_CONFPLL2, 0x08); // PLL M = 8
-	} else {
-		printk(KERN_INFO "tda1004x: setting up plls for 48MHz sampling clock\n");
-		tda1004x_write_byteI(state, TDA10046H_CONFPLL2, 0x03); // PLL M = 3
-	}
-	if (state->config->xtal_freq == TDA10046_XTAL_4M ) {
-		dprintk("%s: setting up PLLs for a 4 MHz Xtal\n", __func__);
-		tda1004x_write_byteI(state, TDA10046H_CONFPLL3, 0); // PLL P = N = 0
-	} else {
-		dprintk("%s: setting up PLLs for a 16 MHz Xtal\n", __func__);
-		tda1004x_write_byteI(state, TDA10046H_CONFPLL3, 3); // PLL P = 0, N = 3
-	}
-	if(tda10046_clk53m)
-		tda1004x_write_byteI(state, TDA10046H_FREQ_OFFSET, 0x67);
-	else
-		tda1004x_write_byteI(state, TDA10046H_FREQ_OFFSET, 0x72);
-	/* Note clock frequency is handled implicitly */
-	switch (state->config->if_freq) {
-	case TDA10046_FREQ_045:
-		tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0c);
-		tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x00);
-		break;
-	case TDA10046_FREQ_052:
-		tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0x0d);
-		tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0xc7);
-		break;
-	case TDA10046_FREQ_3617:
-		tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0xd7);
-		tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x59);
-		break;
-	case TDA10046_FREQ_3613:
-		tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0xd7);
-		tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x3f);
-		break;
-	}
-	tda10046h_set_bandwidth(state, 8000000); /* default bandwidth 8 MHz */
-	/* let the PLLs settle */
-	msleep(120);
-}
-
-static int tda10046_fwupload(struct dvb_frontend* fe)
-{
-	struct tda1004x_state* state = fe->demodulator_priv;
-	int ret, confc4;
-	const struct firmware *fw;
-
-	/* reset + wake up chip */
-	if (state->config->xtal_freq == TDA10046_XTAL_4M) {
-		confc4 = 0;
-	} else {
-		dprintk("%s: 16MHz Xtal, reducing I2C speed\n", __func__);
-		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) {
-		tda1004x_write_byteI(state, TDA10046H_CONF_TRISTATE2, 0x33);
-		tda1004x_write_mask(state, TDA10046H_CONF_POLARITY, 0x0f, state->config->gpio_config &0x0f);
-	}
-	/* let the clocks recover from sleep */
-	msleep(10);
-
-	/* The PLLs need to be reprogrammed after sleep */
-	tda10046_init_plls(fe);
-	tda1004x_write_mask(state, TDA1004X_CONFADC2, 0xc0, 0);
-
-	/* don't re-upload unless necessary */
-	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_byteI(state, TDA1004X_CONFC4, 4);
-	msleep(300);
-	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");
-		ret = state->config->request_firmware(fe, &fw, TDA10046_DEFAULT_FIRMWARE);
-		if (ret) {
-			/* remain compatible to old bug: try to load with tda10045 image name */
-			ret = state->config->request_firmware(fe, &fw, TDA10045_DEFAULT_FIRMWARE);
-			if (ret) {
-				printk(KERN_ERR "tda1004x: no firmware upload (timeout or file not found?)\n");
-				return ret;
-			} else {
-				printk(KERN_INFO "tda1004x: please rename the firmware file to %s\n",
-						  TDA10046_DEFAULT_FIRMWARE);
-			}
-		}
-	} else {
-		printk(KERN_ERR "tda1004x: no request function defined, can't upload from file\n");
-		return -EIO;
-	}
-	tda1004x_write_mask(state, TDA1004X_CONFC4, 8, 8); // going to boot from HOST
-	ret = tda1004x_do_upload(state, fw->data, fw->size, TDA10046H_CODE_CPT, TDA10046H_CODE_IN);
-	release_firmware(fw);
-	return tda1004x_check_upload_ok(state);
-}
-
-static int tda1004x_encode_fec(int fec)
-{
-	// convert known FEC values
-	switch (fec) {
-	case FEC_1_2:
-		return 0;
-	case FEC_2_3:
-		return 1;
-	case FEC_3_4:
-		return 2;
-	case FEC_5_6:
-		return 3;
-	case FEC_7_8:
-		return 4;
-	}
-
-	// unsupported
-	return -EINVAL;
-}
-
-static int tda1004x_decode_fec(int tdafec)
-{
-	// convert known FEC values
-	switch (tdafec) {
-	case 0:
-		return FEC_1_2;
-	case 1:
-		return FEC_2_3;
-	case 2:
-		return FEC_3_4;
-	case 3:
-		return FEC_5_6;
-	case 4:
-		return FEC_7_8;
-	}
-
-	// unsupported
-	return -1;
-}
-
-static int tda1004x_write(struct dvb_frontend* fe, const u8 buf[], int len)
-{
-	struct tda1004x_state* state = fe->demodulator_priv;
-
-	if (len != 2)
-		return -EINVAL;
-
-	return tda1004x_write_byteI(state, buf[0], buf[1]);
-}
-
-static int tda10045_init(struct dvb_frontend* fe)
-{
-	struct tda1004x_state* state = fe->demodulator_priv;
-
-	dprintk("%s\n", __func__);
-
-	if (tda10045_fwupload(fe)) {
-		printk("tda1004x: firmware upload failed\n");
-		return -EIO;
-	}
-
-	tda1004x_write_mask(state, TDA1004X_CONFADC1, 0x10, 0); // wake up the ADC
-
-	// tda setup
-	tda1004x_write_mask(state, TDA1004X_CONFC4, 0x20, 0); // disable DSP watchdog timer
-	tda1004x_write_mask(state, TDA1004X_AUTO, 8, 0); // select HP stream
-	tda1004x_write_mask(state, TDA1004X_CONFC1, 0x40, 0); // set polarity of VAGC signal
-	tda1004x_write_mask(state, TDA1004X_CONFC1, 0x80, 0x80); // enable pulse killer
-	tda1004x_write_mask(state, TDA1004X_AUTO, 0x10, 0x10); // enable auto offset
-	tda1004x_write_mask(state, TDA1004X_IN_CONF2, 0xC0, 0x0); // no frequency offset
-	tda1004x_write_byteI(state, TDA1004X_CONF_TS1, 0); // setup MPEG2 TS interface
-	tda1004x_write_byteI(state, TDA1004X_CONF_TS2, 0); // setup MPEG2 TS interface
-	tda1004x_write_mask(state, TDA1004X_VBER_MSB, 0xe0, 0xa0); // 10^6 VBER measurement bits
-	tda1004x_write_mask(state, TDA1004X_CONFC1, 0x10, 0); // VAGC polarity
-	tda1004x_write_byteI(state, TDA1004X_CONFADC1, 0x2e);
-
-	tda1004x_write_mask(state, 0x1f, 0x01, state->config->invert_oclk);
-
-	return 0;
-}
-
-static int tda10046_init(struct dvb_frontend* fe)
-{
-	struct tda1004x_state* state = fe->demodulator_priv;
-	dprintk("%s\n", __func__);
-
-	if (tda10046_fwupload(fe)) {
-		printk("tda1004x: firmware upload failed\n");
-			return -EIO;
-	}
-
-	// tda setup
-	tda1004x_write_mask(state, TDA1004X_CONFC4, 0x20, 0); // disable DSP watchdog timer
-	tda1004x_write_byteI(state, TDA1004X_AUTO, 0x87);    // 100 ppm crystal, select HP stream
-	tda1004x_write_byteI(state, TDA1004X_CONFC1, 0x88);      // enable pulse killer
-
-	switch (state->config->agc_config) {
-	case TDA10046_AGC_DEFAULT:
-		tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x00); // AGC setup
-		tda1004x_write_mask(state, TDA10046H_CONF_POLARITY, 0xf0, 0x60);  // set AGC polarities
-		break;
-	case TDA10046_AGC_IFO_AUTO_NEG:
-		tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x0a); // AGC setup
-		tda1004x_write_mask(state, TDA10046H_CONF_POLARITY, 0xf0, 0x60);  // set AGC polarities
-		break;
-	case TDA10046_AGC_IFO_AUTO_POS:
-		tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x0a); // AGC setup
-		tda1004x_write_mask(state, TDA10046H_CONF_POLARITY, 0xf0, 0x00);  // set AGC polarities
-		break;
-	case TDA10046_AGC_TDA827X:
-		tda1004x_write_byteI(state, TDA10046H_AGC_CONF, 0x02);   // AGC setup
-		tda1004x_write_byteI(state, TDA10046H_AGC_THR, 0x70);    // AGC Threshold
-		tda1004x_write_byteI(state, TDA10046H_AGC_RENORM, 0x08); // Gain Renormalize
-		tda1004x_write_mask(state, TDA10046H_CONF_POLARITY, 0xf0, 0x60);  // set AGC polarities
-		break;
-	}
-	if (state->config->ts_mode == 0) {
-		tda1004x_write_mask(state, TDA10046H_CONF_TRISTATE1, 0xc0, 0x40);
-		tda1004x_write_mask(state, 0x3a, 0x80, state->config->invert_oclk << 7);
-	} else {
-		tda1004x_write_mask(state, TDA10046H_CONF_TRISTATE1, 0xc0, 0x80);
-		tda1004x_write_mask(state, TDA10046H_CONF_POLARITY, 0x10,
-							state->config->invert_oclk << 4);
-	}
-	tda1004x_write_byteI(state, TDA1004X_CONFADC2, 0x38);
-	tda1004x_write_mask (state, TDA10046H_CONF_TRISTATE1, 0x3e, 0x38); // Turn IF AGC output on
-	tda1004x_write_byteI(state, TDA10046H_AGC_TUN_MIN, 0);	  // }
-	tda1004x_write_byteI(state, TDA10046H_AGC_TUN_MAX, 0xff); // } AGC min/max values
-	tda1004x_write_byteI(state, TDA10046H_AGC_IF_MIN, 0);	  // }
-	tda1004x_write_byteI(state, TDA10046H_AGC_IF_MAX, 0xff);  // }
-	tda1004x_write_byteI(state, TDA10046H_AGC_GAINS, 0x12); // IF gain 2, TUN gain 1
-	tda1004x_write_byteI(state, TDA10046H_CVBER_CTRL, 0x1a); // 10^6 VBER measurement bits
-	tda1004x_write_byteI(state, TDA1004X_CONF_TS1, 7); // MPEG2 interface config
-	tda1004x_write_byteI(state, TDA1004X_CONF_TS2, 0xc0); // MPEG2 interface config
-	// tda1004x_write_mask(state, 0x50, 0x80, 0x80);         // handle out of guard echoes
-
-	return 0;
-}
-
-static int tda1004x_set_fe(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *fe_params = &fe->dtv_property_cache;
-	struct tda1004x_state* state = fe->demodulator_priv;
-	int tmp;
-	int inversion;
-
-	dprintk("%s\n", __func__);
-
-	if (state->demod_type == TDA1004X_DEMOD_TDA10046) {
-		// setup auto offset
-		tda1004x_write_mask(state, TDA1004X_AUTO, 0x10, 0x10);
-		tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x80, 0);
-		tda1004x_write_mask(state, TDA1004X_IN_CONF2, 0xC0, 0);
-
-		// disable agc_conf[2]
-		tda1004x_write_mask(state, TDA10046H_AGC_CONF, 4, 0);
-	}
-
-	// set frequency
-	if (fe->ops.tuner_ops.set_params) {
-		fe->ops.tuner_ops.set_params(fe);
-		if (fe->ops.i2c_gate_ctrl)
-			fe->ops.i2c_gate_ctrl(fe, 0);
-	}
-
-	// Hardcoded to use auto as much as possible on the TDA10045 as it
-	// is very unreliable if AUTO mode is _not_ used.
-	if (state->demod_type == TDA1004X_DEMOD_TDA10045) {
-		fe_params->code_rate_HP = FEC_AUTO;
-		fe_params->guard_interval = GUARD_INTERVAL_AUTO;
-		fe_params->transmission_mode = TRANSMISSION_MODE_AUTO;
-	}
-
-	// Set standard params.. or put them to auto
-	if ((fe_params->code_rate_HP == FEC_AUTO) ||
-		(fe_params->code_rate_LP == FEC_AUTO) ||
-		(fe_params->modulation == QAM_AUTO) ||
-		(fe_params->hierarchy == HIERARCHY_AUTO)) {
-		tda1004x_write_mask(state, TDA1004X_AUTO, 1, 1);	// enable auto
-		tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x03, 0);	/* turn off modulation bits */
-		tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x60, 0);	// turn off hierarchy bits
-		tda1004x_write_mask(state, TDA1004X_IN_CONF2, 0x3f, 0);	// turn off FEC bits
-	} else {
-		tda1004x_write_mask(state, TDA1004X_AUTO, 1, 0);	// disable auto
-
-		// set HP FEC
-		tmp = tda1004x_encode_fec(fe_params->code_rate_HP);
-		if (tmp < 0)
-			return tmp;
-		tda1004x_write_mask(state, TDA1004X_IN_CONF2, 7, tmp);
-
-		// set LP FEC
-		tmp = tda1004x_encode_fec(fe_params->code_rate_LP);
-		if (tmp < 0)
-			return tmp;
-		tda1004x_write_mask(state, TDA1004X_IN_CONF2, 0x38, tmp << 3);
-
-		/* set modulation */
-		switch (fe_params->modulation) {
-		case QPSK:
-			tda1004x_write_mask(state, TDA1004X_IN_CONF1, 3, 0);
-			break;
-
-		case QAM_16:
-			tda1004x_write_mask(state, TDA1004X_IN_CONF1, 3, 1);
-			break;
-
-		case QAM_64:
-			tda1004x_write_mask(state, TDA1004X_IN_CONF1, 3, 2);
-			break;
-
-		default:
-			return -EINVAL;
-		}
-
-		// set hierarchy
-		switch (fe_params->hierarchy) {
-		case HIERARCHY_NONE:
-			tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x60, 0 << 5);
-			break;
-
-		case HIERARCHY_1:
-			tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x60, 1 << 5);
-			break;
-
-		case HIERARCHY_2:
-			tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x60, 2 << 5);
-			break;
-
-		case HIERARCHY_4:
-			tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x60, 3 << 5);
-			break;
-
-		default:
-			return -EINVAL;
-		}
-	}
-
-	// set bandwidth
-	switch (state->demod_type) {
-	case TDA1004X_DEMOD_TDA10045:
-		tda10045h_set_bandwidth(state, fe_params->bandwidth_hz);
-		break;
-
-	case TDA1004X_DEMOD_TDA10046:
-		tda10046h_set_bandwidth(state, fe_params->bandwidth_hz);
-		break;
-	}
-
-	// set inversion
-	inversion = fe_params->inversion;
-	if (state->config->invert)
-		inversion = inversion ? INVERSION_OFF : INVERSION_ON;
-	switch (inversion) {
-	case INVERSION_OFF:
-		tda1004x_write_mask(state, TDA1004X_CONFC1, 0x20, 0);
-		break;
-
-	case INVERSION_ON:
-		tda1004x_write_mask(state, TDA1004X_CONFC1, 0x20, 0x20);
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	// set guard interval
-	switch (fe_params->guard_interval) {
-	case GUARD_INTERVAL_1_32:
-		tda1004x_write_mask(state, TDA1004X_AUTO, 2, 0);
-		tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x0c, 0 << 2);
-		break;
-
-	case GUARD_INTERVAL_1_16:
-		tda1004x_write_mask(state, TDA1004X_AUTO, 2, 0);
-		tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x0c, 1 << 2);
-		break;
-
-	case GUARD_INTERVAL_1_8:
-		tda1004x_write_mask(state, TDA1004X_AUTO, 2, 0);
-		tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x0c, 2 << 2);
-		break;
-
-	case GUARD_INTERVAL_1_4:
-		tda1004x_write_mask(state, TDA1004X_AUTO, 2, 0);
-		tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x0c, 3 << 2);
-		break;
-
-	case GUARD_INTERVAL_AUTO:
-		tda1004x_write_mask(state, TDA1004X_AUTO, 2, 2);
-		tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x0c, 0 << 2);
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	// set transmission mode
-	switch (fe_params->transmission_mode) {
-	case TRANSMISSION_MODE_2K:
-		tda1004x_write_mask(state, TDA1004X_AUTO, 4, 0);
-		tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x10, 0 << 4);
-		break;
-
-	case TRANSMISSION_MODE_8K:
-		tda1004x_write_mask(state, TDA1004X_AUTO, 4, 0);
-		tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x10, 1 << 4);
-		break;
-
-	case TRANSMISSION_MODE_AUTO:
-		tda1004x_write_mask(state, TDA1004X_AUTO, 4, 4);
-		tda1004x_write_mask(state, TDA1004X_IN_CONF1, 0x10, 0);
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	// start the lock
-	switch (state->demod_type) {
-	case TDA1004X_DEMOD_TDA10045:
-		tda1004x_write_mask(state, TDA1004X_CONFC4, 8, 8);
-		tda1004x_write_mask(state, TDA1004X_CONFC4, 8, 0);
-		break;
-
-	case TDA1004X_DEMOD_TDA10046:
-		tda1004x_write_mask(state, TDA1004X_AUTO, 0x40, 0x40);
-		msleep(1);
-		tda1004x_write_mask(state, TDA10046H_AGC_CONF, 4, 1);
-		break;
-	}
-
-	msleep(10);
-
-	return 0;
-}
-
-static int tda1004x_get_fe(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *fe_params = &fe->dtv_property_cache;
-	struct tda1004x_state* state = fe->demodulator_priv;
-
-	dprintk("%s\n", __func__);
-
-	// inversion status
-	fe_params->inversion = INVERSION_OFF;
-	if (tda1004x_read_byte(state, TDA1004X_CONFC1) & 0x20)
-		fe_params->inversion = INVERSION_ON;
-	if (state->config->invert)
-		fe_params->inversion = fe_params->inversion ? INVERSION_OFF : INVERSION_ON;
-
-	// bandwidth
-	switch (state->demod_type) {
-	case TDA1004X_DEMOD_TDA10045:
-		switch (tda1004x_read_byte(state, TDA10045H_WREF_LSB)) {
-		case 0x14:
-			fe_params->bandwidth_hz = 8000000;
-			break;
-		case 0xdb:
-			fe_params->bandwidth_hz = 7000000;
-			break;
-		case 0x4f:
-			fe_params->bandwidth_hz = 6000000;
-			break;
-		}
-		break;
-	case TDA1004X_DEMOD_TDA10046:
-		switch (tda1004x_read_byte(state, TDA10046H_TIME_WREF1)) {
-		case 0x5c:
-		case 0x54:
-			fe_params->bandwidth_hz = 8000000;
-			break;
-		case 0x6a:
-		case 0x60:
-			fe_params->bandwidth_hz = 7000000;
-			break;
-		case 0x7b:
-		case 0x70:
-			fe_params->bandwidth_hz = 6000000;
-			break;
-		}
-		break;
-	}
-
-	// FEC
-	fe_params->code_rate_HP =
-	    tda1004x_decode_fec(tda1004x_read_byte(state, TDA1004X_OUT_CONF2) & 7);
-	fe_params->code_rate_LP =
-	    tda1004x_decode_fec((tda1004x_read_byte(state, TDA1004X_OUT_CONF2) >> 3) & 7);
-
-	/* modulation */
-	switch (tda1004x_read_byte(state, TDA1004X_OUT_CONF1) & 3) {
-	case 0:
-		fe_params->modulation = QPSK;
-		break;
-	case 1:
-		fe_params->modulation = QAM_16;
-		break;
-	case 2:
-		fe_params->modulation = QAM_64;
-		break;
-	}
-
-	// transmission mode
-	fe_params->transmission_mode = TRANSMISSION_MODE_2K;
-	if (tda1004x_read_byte(state, TDA1004X_OUT_CONF1) & 0x10)
-		fe_params->transmission_mode = TRANSMISSION_MODE_8K;
-
-	// guard interval
-	switch ((tda1004x_read_byte(state, TDA1004X_OUT_CONF1) & 0x0c) >> 2) {
-	case 0:
-		fe_params->guard_interval = GUARD_INTERVAL_1_32;
-		break;
-	case 1:
-		fe_params->guard_interval = GUARD_INTERVAL_1_16;
-		break;
-	case 2:
-		fe_params->guard_interval = GUARD_INTERVAL_1_8;
-		break;
-	case 3:
-		fe_params->guard_interval = GUARD_INTERVAL_1_4;
-		break;
-	}
-
-	// hierarchy
-	switch ((tda1004x_read_byte(state, TDA1004X_OUT_CONF1) & 0x60) >> 5) {
-	case 0:
-		fe_params->hierarchy = HIERARCHY_NONE;
-		break;
-	case 1:
-		fe_params->hierarchy = HIERARCHY_1;
-		break;
-	case 2:
-		fe_params->hierarchy = HIERARCHY_2;
-		break;
-	case 3:
-		fe_params->hierarchy = HIERARCHY_4;
-		break;
-	}
-
-	return 0;
-}
-
-static int tda1004x_read_status(struct dvb_frontend* fe, fe_status_t * fe_status)
-{
-	struct tda1004x_state* state = fe->demodulator_priv;
-	int status;
-	int cber;
-	int vber;
-
-	dprintk("%s\n", __func__);
-
-	// read status
-	status = tda1004x_read_byte(state, TDA1004X_STATUS_CD);
-	if (status == -1)
-		return -EIO;
-
-	// decode
-	*fe_status = 0;
-	if (status & 4)
-		*fe_status |= FE_HAS_SIGNAL;
-	if (status & 2)
-		*fe_status |= FE_HAS_CARRIER;
-	if (status & 8)
-		*fe_status |= FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
-
-	// if we don't already have VITERBI (i.e. not LOCKED), see if the viterbi
-	// is getting anything valid
-	if (!(*fe_status & FE_HAS_VITERBI)) {
-		// read the CBER
-		cber = tda1004x_read_byte(state, TDA1004X_CBER_LSB);
-		if (cber == -1)
-			return -EIO;
-		status = tda1004x_read_byte(state, TDA1004X_CBER_MSB);
-		if (status == -1)
-			return -EIO;
-		cber |= (status << 8);
-		// The address 0x20 should be read to cope with a TDA10046 bug
-		tda1004x_read_byte(state, TDA1004X_CBER_RESET);
-
-		if (cber != 65535)
-			*fe_status |= FE_HAS_VITERBI;
-	}
-
-	// if we DO have some valid VITERBI output, but don't already have SYNC
-	// bytes (i.e. not LOCKED), see if the RS decoder is getting anything valid.
-	if ((*fe_status & FE_HAS_VITERBI) && (!(*fe_status & FE_HAS_SYNC))) {
-		// read the VBER
-		vber = tda1004x_read_byte(state, TDA1004X_VBER_LSB);
-		if (vber == -1)
-			return -EIO;
-		status = tda1004x_read_byte(state, TDA1004X_VBER_MID);
-		if (status == -1)
-			return -EIO;
-		vber |= (status << 8);
-		status = tda1004x_read_byte(state, TDA1004X_VBER_MSB);
-		if (status == -1)
-			return -EIO;
-		vber |= (status & 0x0f) << 16;
-		// The CVBER_LUT should be read to cope with TDA10046 hardware bug
-		tda1004x_read_byte(state, TDA1004X_CVBER_LUT);
-
-		// if RS has passed some valid TS packets, then we must be
-		// getting some SYNC bytes
-		if (vber < 16632)
-			*fe_status |= FE_HAS_SYNC;
-	}
-
-	// success
-	dprintk("%s: fe_status=0x%x\n", __func__, *fe_status);
-	return 0;
-}
-
-static int tda1004x_read_signal_strength(struct dvb_frontend* fe, u16 * signal)
-{
-	struct tda1004x_state* state = fe->demodulator_priv;
-	int tmp;
-	int reg = 0;
-
-	dprintk("%s\n", __func__);
-
-	// determine the register to use
-	switch (state->demod_type) {
-	case TDA1004X_DEMOD_TDA10045:
-		reg = TDA10045H_S_AGC;
-		break;
-
-	case TDA1004X_DEMOD_TDA10046:
-		reg = TDA10046H_AGC_IF_LEVEL;
-		break;
-	}
-
-	// read it
-	tmp = tda1004x_read_byte(state, reg);
-	if (tmp < 0)
-		return -EIO;
-
-	*signal = (tmp << 8) | tmp;
-	dprintk("%s: signal=0x%x\n", __func__, *signal);
-	return 0;
-}
-
-static int tda1004x_read_snr(struct dvb_frontend* fe, u16 * snr)
-{
-	struct tda1004x_state* state = fe->demodulator_priv;
-	int tmp;
-
-	dprintk("%s\n", __func__);
-
-	// read it
-	tmp = tda1004x_read_byte(state, TDA1004X_SNR);
-	if (tmp < 0)
-		return -EIO;
-	tmp = 255 - tmp;
-
-	*snr = ((tmp << 8) | tmp);
-	dprintk("%s: snr=0x%x\n", __func__, *snr);
-	return 0;
-}
-
-static int tda1004x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
-{
-	struct tda1004x_state* state = fe->demodulator_priv;
-	int tmp;
-	int tmp2;
-	int counter;
-
-	dprintk("%s\n", __func__);
-
-	// read the UCBLOCKS and reset
-	counter = 0;
-	tmp = tda1004x_read_byte(state, TDA1004X_UNCOR);
-	if (tmp < 0)
-		return -EIO;
-	tmp &= 0x7f;
-	while (counter++ < 5) {
-		tda1004x_write_mask(state, TDA1004X_UNCOR, 0x80, 0);
-		tda1004x_write_mask(state, TDA1004X_UNCOR, 0x80, 0);
-		tda1004x_write_mask(state, TDA1004X_UNCOR, 0x80, 0);
-
-		tmp2 = tda1004x_read_byte(state, TDA1004X_UNCOR);
-		if (tmp2 < 0)
-			return -EIO;
-		tmp2 &= 0x7f;
-		if ((tmp2 < tmp) || (tmp2 == 0))
-			break;
-	}
-
-	if (tmp != 0x7f)
-		*ucblocks = tmp;
-	else
-		*ucblocks = 0xffffffff;
-
-	dprintk("%s: ucblocks=0x%x\n", __func__, *ucblocks);
-	return 0;
-}
-
-static int tda1004x_read_ber(struct dvb_frontend* fe, u32* ber)
-{
-	struct tda1004x_state* state = fe->demodulator_priv;
-	int tmp;
-
-	dprintk("%s\n", __func__);
-
-	// read it in
-	tmp = tda1004x_read_byte(state, TDA1004X_CBER_LSB);
-	if (tmp < 0)
-		return -EIO;
-	*ber = tmp << 1;
-	tmp = tda1004x_read_byte(state, TDA1004X_CBER_MSB);
-	if (tmp < 0)
-		return -EIO;
-	*ber |= (tmp << 9);
-	// The address 0x20 should be read to cope with a TDA10046 bug
-	tda1004x_read_byte(state, TDA1004X_CBER_RESET);
-
-	dprintk("%s: ber=0x%x\n", __func__, *ber);
-	return 0;
-}
-
-static int tda1004x_sleep(struct dvb_frontend* fe)
-{
-	struct tda1004x_state* state = fe->demodulator_priv;
-	int gpio_conf;
-
-	switch (state->demod_type) {
-	case TDA1004X_DEMOD_TDA10045:
-		tda1004x_write_mask(state, TDA1004X_CONFADC1, 0x10, 0x10);
-		break;
-
-	case TDA1004X_DEMOD_TDA10046:
-		/* set outputs to tristate */
-		tda1004x_write_byteI(state, TDA10046H_CONF_TRISTATE1, 0xff);
-		/* invert GPIO 1 and 3 if desired*/
-		gpio_conf = state->config->gpio_config;
-		if (gpio_conf >= TDA10046_GP00_I)
-			tda1004x_write_mask(state, TDA10046H_CONF_POLARITY, 0x0f,
-							(gpio_conf & 0x0f) ^ 0x0a);
-
-		tda1004x_write_mask(state, TDA1004X_CONFADC2, 0xc0, 0xc0);
-		tda1004x_write_mask(state, TDA1004X_CONFC4, 1, 1);
-		break;
-	}
-
-	return 0;
-}
-
-static int tda1004x_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
-{
-	struct tda1004x_state* state = fe->demodulator_priv;
-
-	if (enable) {
-		return tda1004x_enable_tuner_i2c(state);
-	} else {
-		return tda1004x_disable_tuner_i2c(state);
-	}
-}
-
-static int tda1004x_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings)
-{
-	fesettings->min_delay_ms = 800;
-	/* Drift compensation makes no sense for DVB-T */
-	fesettings->step_size = 0;
-	fesettings->max_drift = 0;
-	return 0;
-}
-
-static void tda1004x_release(struct dvb_frontend* fe)
-{
-	struct tda1004x_state *state = fe->demodulator_priv;
-	kfree(state);
-}
-
-static struct dvb_frontend_ops tda10045_ops = {
-	.delsys = { SYS_DVBT },
-	.info = {
-		.name = "Philips TDA10045H DVB-T",
-		.frequency_min = 51000000,
-		.frequency_max = 858000000,
-		.frequency_stepsize = 166667,
-		.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_FEC_AUTO |
-		    FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
-		    FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO
-	},
-
-	.release = tda1004x_release,
-
-	.init = tda10045_init,
-	.sleep = tda1004x_sleep,
-	.write = tda1004x_write,
-	.i2c_gate_ctrl = tda1004x_i2c_gate_ctrl,
-
-	.set_frontend = tda1004x_set_fe,
-	.get_frontend = tda1004x_get_fe,
-	.get_tune_settings = tda1004x_get_tune_settings,
-
-	.read_status = tda1004x_read_status,
-	.read_ber = tda1004x_read_ber,
-	.read_signal_strength = tda1004x_read_signal_strength,
-	.read_snr = tda1004x_read_snr,
-	.read_ucblocks = tda1004x_read_ucblocks,
-};
-
-struct dvb_frontend* tda10045_attach(const struct tda1004x_config* config,
-				     struct i2c_adapter* i2c)
-{
-	struct tda1004x_state *state;
-	int id;
-
-	/* allocate memory for the internal state */
-	state = kzalloc(sizeof(struct tda1004x_state), GFP_KERNEL);
-	if (!state) {
-		printk(KERN_ERR "Can't allocate memory for tda10045 state\n");
-		return NULL;
-	}
-
-	/* setup the state */
-	state->config = config;
-	state->i2c = i2c;
-	state->demod_type = TDA1004X_DEMOD_TDA10045;
-
-	/* check if the demod is there */
-	id = tda1004x_read_byte(state, TDA1004X_CHIPID);
-	if (id < 0) {
-		printk(KERN_ERR "tda10045: chip is not answering. Giving up.\n");
-		kfree(state);
-		return NULL;
-	}
-
-	if (id != 0x25) {
-		printk(KERN_ERR "Invalid tda1004x ID = 0x%02x. Can't proceed\n", id);
-		kfree(state);
-		return NULL;
-	}
-
-	/* create dvb_frontend */
-	memcpy(&state->frontend.ops, &tda10045_ops, sizeof(struct dvb_frontend_ops));
-	state->frontend.demodulator_priv = state;
-	return &state->frontend;
-}
-
-static struct dvb_frontend_ops tda10046_ops = {
-	.delsys = { SYS_DVBT },
-	.info = {
-		.name = "Philips TDA10046H DVB-T",
-		.frequency_min = 51000000,
-		.frequency_max = 858000000,
-		.frequency_stepsize = 166667,
-		.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_FEC_AUTO |
-		    FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
-		    FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO
-	},
-
-	.release = tda1004x_release,
-
-	.init = tda10046_init,
-	.sleep = tda1004x_sleep,
-	.write = tda1004x_write,
-	.i2c_gate_ctrl = tda1004x_i2c_gate_ctrl,
-
-	.set_frontend = tda1004x_set_fe,
-	.get_frontend = tda1004x_get_fe,
-	.get_tune_settings = tda1004x_get_tune_settings,
-
-	.read_status = tda1004x_read_status,
-	.read_ber = tda1004x_read_ber,
-	.read_signal_strength = tda1004x_read_signal_strength,
-	.read_snr = tda1004x_read_snr,
-	.read_ucblocks = tda1004x_read_ucblocks,
-};
-
-struct dvb_frontend* tda10046_attach(const struct tda1004x_config* config,
-				     struct i2c_adapter* i2c)
-{
-	struct tda1004x_state *state;
-	int id;
-
-	/* allocate memory for the internal state */
-	state = kzalloc(sizeof(struct tda1004x_state), GFP_KERNEL);
-	if (!state) {
-		printk(KERN_ERR "Can't allocate memory for tda10046 state\n");
-		return NULL;
-	}
-
-	/* setup the state */
-	state->config = config;
-	state->i2c = i2c;
-	state->demod_type = TDA1004X_DEMOD_TDA10046;
-
-	/* check if the demod is there */
-	id = tda1004x_read_byte(state, TDA1004X_CHIPID);
-	if (id < 0) {
-		printk(KERN_ERR "tda10046: chip is not answering. Giving up.\n");
-		kfree(state);
-		return NULL;
-	}
-	if (id != 0x46) {
-		printk(KERN_ERR "Invalid tda1004x ID = 0x%02x. Can't proceed\n", id);
-		kfree(state);
-		return NULL;
-	}
-
-	/* create dvb_frontend */
-	memcpy(&state->frontend.ops, &tda10046_ops, sizeof(struct dvb_frontend_ops));
-	state->frontend.demodulator_priv = state;
-	return &state->frontend;
-}
-
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
-
-MODULE_DESCRIPTION("Philips TDA10045H & TDA10046H DVB-T Demodulator");
-MODULE_AUTHOR("Andrew de Quincey & Robert Schlabbach");
-MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(tda10045_attach);
-EXPORT_SYMBOL(tda10046_attach);
diff --git a/drivers/media/dvb/frontends/tda1004x.h b/drivers/media/dvb/frontends/tda1004x.h
deleted file mode 100644
index 4e27ffb..0000000
--- a/drivers/media/dvb/frontends/tda1004x.h
+++ /dev/null
@@ -1,149 +0,0 @@
-  /*
-     Driver for Philips tda1004xh OFDM Frontend
-
-     (c) 2004 Andrew de Quincey
-
-     This program is free software; you can redistribute it and/or modify
-     it under the terms of the 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 TDA1004X_H
-#define TDA1004X_H
-
-#include <linux/dvb/frontend.h>
-#include <linux/firmware.h>
-
-enum tda10046_xtal {
-	TDA10046_XTAL_4M,
-	TDA10046_XTAL_16M,
-};
-
-enum tda10046_agc {
-	TDA10046_AGC_DEFAULT,		/* original configuration */
-	TDA10046_AGC_IFO_AUTO_NEG,	/* IF AGC only, automatic, negtive */
-	TDA10046_AGC_IFO_AUTO_POS,	/* IF AGC only, automatic, positive */
-	TDA10046_AGC_TDA827X,		/* IF AGC only, special setup for tda827x */
-};
-
-/* Many (hybrid) boards use GPIO 1 and 3
-	GPIO1	analog - dvb switch
-	GPIO3	firmware eeprom address switch
-*/
-enum tda10046_gpio {
-	TDA10046_GPTRI  = 0x00,		/* All GPIOs tristate */
-	TDA10046_GP00   = 0x40,		/* GPIO3=0, GPIO1=0 */
-	TDA10046_GP01   = 0x42,		/* GPIO3=0, GPIO1=1 */
-	TDA10046_GP10   = 0x48,		/* GPIO3=1, GPIO1=0 */
-	TDA10046_GP11   = 0x4a,		/* GPIO3=1, GPIO1=1 */
-	TDA10046_GP00_I = 0x80,		/* GPIO3=0, GPIO1=0, invert in sleep mode*/
-	TDA10046_GP01_I = 0x82,		/* GPIO3=0, GPIO1=1, invert in sleep mode */
-	TDA10046_GP10_I = 0x88,		/* GPIO3=1, GPIO1=0, invert in sleep mode */
-	TDA10046_GP11_I = 0x8a,		/* GPIO3=1, GPIO1=1, invert in sleep mode */
-};
-
-enum tda10046_if {
-	TDA10046_FREQ_3617,		/* original config, 36,166 MHZ */
-	TDA10046_FREQ_3613,		/* 36,13 MHZ */
-	TDA10046_FREQ_045,		/* low IF, 4.0, 4.5, or 5.0 MHZ */
-	TDA10046_FREQ_052,		/* low IF, 5.1667 MHZ for tda9889 */
-};
-
-enum tda10046_tsout {
-	TDA10046_TS_PARALLEL  = 0x00,	/* parallel transport stream, default */
-	TDA10046_TS_SERIAL    = 0x01,	/* serial transport stream */
-};
-
-struct tda1004x_config
-{
-	/* the demodulator's i2c address */
-	u8 demod_address;
-
-	/* does the "inversion" need inverted? */
-	u8 invert;
-
-	/* Does the OCLK signal need inverted? */
-	u8 invert_oclk;
-
-	/* parallel or serial transport stream */
-	enum tda10046_tsout ts_mode;
-
-	/* Xtal frequency, 4 or 16MHz*/
-	enum tda10046_xtal xtal_freq;
-
-	/* IF frequency */
-	enum tda10046_if if_freq;
-
-	/* AGC configuration */
-	enum tda10046_agc agc_config;
-
-	/* setting of GPIO1 and 3 */
-	enum tda10046_gpio gpio_config;
-
-	/* slave address and configuration of the tuner */
-	u8 tuner_address;
-	u8 antenna_switch;
-
-	/* if the board uses another I2c Bridge (tda8290), its address */
-	u8 i2c_gate;
-
-	/* request firmware for device */
-	int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name);
-};
-
-enum tda1004x_demod {
-	TDA1004X_DEMOD_TDA10045,
-	TDA1004X_DEMOD_TDA10046,
-};
-
-struct tda1004x_state {
-	struct i2c_adapter* i2c;
-	const struct tda1004x_config* config;
-	struct dvb_frontend frontend;
-
-	/* private demod data */
-	enum tda1004x_demod demod_type;
-};
-
-#if defined(CONFIG_DVB_TDA1004X) || (defined(CONFIG_DVB_TDA1004X_MODULE) && defined(MODULE))
-extern struct dvb_frontend* tda10045_attach(const struct tda1004x_config* config,
-					    struct i2c_adapter* i2c);
-
-extern struct dvb_frontend* tda10046_attach(const struct tda1004x_config* config,
-					    struct i2c_adapter* i2c);
-#else
-static inline struct dvb_frontend* tda10045_attach(const struct tda1004x_config* config,
-					    struct i2c_adapter* i2c)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-static inline struct dvb_frontend* tda10046_attach(const struct tda1004x_config* config,
-					    struct i2c_adapter* i2c)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif // CONFIG_DVB_TDA1004X
-
-static inline int tda1004x_writereg(struct dvb_frontend *fe, u8 reg, u8 val) {
-	int r = 0;
-	u8 buf[] = {reg, val};
-	if (fe->ops.write)
-		r = fe->ops.write(fe, buf, 2);
-	return r;
-}
-
-#endif // TDA1004X_H
diff --git a/drivers/media/dvb/frontends/tda10071.c b/drivers/media/dvb/frontends/tda10071.c
deleted file mode 100644
index 703c3d0..0000000
--- a/drivers/media/dvb/frontends/tda10071.c
+++ /dev/null
@@ -1,1284 +0,0 @@
-/*
- * NXP TDA10071 + Conexant CX24118A DVB-S/S2 demodulator + tuner driver
- *
- * Copyright (C) 2011 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.,
- *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include "tda10071_priv.h"
-
-static struct dvb_frontend_ops tda10071_ops;
-
-/* write multiple registers */
-static int tda10071_wr_regs(struct tda10071_priv *priv, u8 reg, u8 *val,
-	int len)
-{
-	int ret;
-	u8 buf[len+1];
-	struct i2c_msg msg[1] = {
-		{
-			.addr = priv->cfg.i2c_address,
-			.flags = 0,
-			.len = sizeof(buf),
-			.buf = buf,
-		}
-	};
-
-	buf[0] = reg;
-	memcpy(&buf[1], val, len);
-
-	ret = i2c_transfer(priv->i2c, msg, 1);
-	if (ret == 1) {
-		ret = 0;
-	} else {
-		dev_warn(&priv->i2c->dev, "%s: i2c wr failed=%d reg=%02x " \
-				"len=%d\n", KBUILD_MODNAME, ret, reg, len);
-		ret = -EREMOTEIO;
-	}
-	return ret;
-}
-
-/* read multiple registers */
-static int tda10071_rd_regs(struct tda10071_priv *priv, u8 reg, u8 *val,
-	int len)
-{
-	int ret;
-	u8 buf[len];
-	struct i2c_msg msg[2] = {
-		{
-			.addr = priv->cfg.i2c_address,
-			.flags = 0,
-			.len = 1,
-			.buf = &reg,
-		}, {
-			.addr = priv->cfg.i2c_address,
-			.flags = I2C_M_RD,
-			.len = sizeof(buf),
-			.buf = buf,
-		}
-	};
-
-	ret = i2c_transfer(priv->i2c, msg, 2);
-	if (ret == 2) {
-		memcpy(val, buf, len);
-		ret = 0;
-	} else {
-		dev_warn(&priv->i2c->dev, "%s: i2c rd failed=%d reg=%02x " \
-				"len=%d\n", KBUILD_MODNAME, ret, reg, len);
-		ret = -EREMOTEIO;
-	}
-	return ret;
-}
-
-/* write single register */
-static int tda10071_wr_reg(struct tda10071_priv *priv, u8 reg, u8 val)
-{
-	return tda10071_wr_regs(priv, reg, &val, 1);
-}
-
-/* read single register */
-static int tda10071_rd_reg(struct tda10071_priv *priv, u8 reg, u8 *val)
-{
-	return tda10071_rd_regs(priv, reg, val, 1);
-}
-
-/* write single register with mask */
-int tda10071_wr_reg_mask(struct tda10071_priv *priv, u8 reg, u8 val, u8 mask)
-{
-	int ret;
-	u8 tmp;
-
-	/* no need for read if whole reg is written */
-	if (mask != 0xff) {
-		ret = tda10071_rd_regs(priv, reg, &tmp, 1);
-		if (ret)
-			return ret;
-
-		val &= mask;
-		tmp &= ~mask;
-		val |= tmp;
-	}
-
-	return tda10071_wr_regs(priv, reg, &val, 1);
-}
-
-/* read single register with mask */
-int tda10071_rd_reg_mask(struct tda10071_priv *priv, u8 reg, u8 *val, u8 mask)
-{
-	int ret, i;
-	u8 tmp;
-
-	ret = tda10071_rd_regs(priv, reg, &tmp, 1);
-	if (ret)
-		return ret;
-
-	tmp &= mask;
-
-	/* find position of the first bit */
-	for (i = 0; i < 8; i++) {
-		if ((mask >> i) & 0x01)
-			break;
-	}
-	*val = tmp >> i;
-
-	return 0;
-}
-
-/* execute firmware command */
-static int tda10071_cmd_execute(struct tda10071_priv *priv,
-	struct tda10071_cmd *cmd)
-{
-	int ret, i;
-	u8 tmp;
-
-	if (!priv->warm) {
-		ret = -EFAULT;
-		goto error;
-	}
-
-	/* write cmd and args for firmware */
-	ret = tda10071_wr_regs(priv, 0x00, cmd->args, cmd->len);
-	if (ret)
-		goto error;
-
-	/* start cmd execution */
-	ret = tda10071_wr_reg(priv, 0x1f, 1);
-	if (ret)
-		goto error;
-
-	/* wait cmd execution terminate */
-	for (i = 1000, tmp = 1; i && tmp; i--) {
-		ret = tda10071_rd_reg(priv, 0x1f, &tmp);
-		if (ret)
-			goto error;
-
-		usleep_range(200, 5000);
-	}
-
-	dev_dbg(&priv->i2c->dev, "%s: loop=%d\n", __func__, i);
-
-	if (i == 0) {
-		ret = -ETIMEDOUT;
-		goto error;
-	}
-
-	return ret;
-error:
-	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
-	return ret;
-}
-
-static int tda10071_set_tone(struct dvb_frontend *fe,
-	fe_sec_tone_mode_t fe_sec_tone_mode)
-{
-	struct tda10071_priv *priv = fe->demodulator_priv;
-	struct tda10071_cmd cmd;
-	int ret;
-	u8 tone;
-
-	if (!priv->warm) {
-		ret = -EFAULT;
-		goto error;
-	}
-
-	dev_dbg(&priv->i2c->dev, "%s: tone_mode=%d\n", __func__,
-			fe_sec_tone_mode);
-
-	switch (fe_sec_tone_mode) {
-	case SEC_TONE_ON:
-		tone = 1;
-		break;
-	case SEC_TONE_OFF:
-		tone = 0;
-		break;
-	default:
-		dev_dbg(&priv->i2c->dev, "%s: invalid fe_sec_tone_mode\n",
-				__func__);
-		ret = -EINVAL;
-		goto error;
-	}
-
-	cmd.args[0] = CMD_LNB_PCB_CONFIG;
-	cmd.args[1] = 0;
-	cmd.args[2] = 0x00;
-	cmd.args[3] = 0x00;
-	cmd.args[4] = tone;
-	cmd.len = 5;
-	ret = tda10071_cmd_execute(priv, &cmd);
-	if (ret)
-		goto error;
-
-	return ret;
-error:
-	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
-	return ret;
-}
-
-static int tda10071_set_voltage(struct dvb_frontend *fe,
-	fe_sec_voltage_t fe_sec_voltage)
-{
-	struct tda10071_priv *priv = fe->demodulator_priv;
-	struct tda10071_cmd cmd;
-	int ret;
-	u8 voltage;
-
-	if (!priv->warm) {
-		ret = -EFAULT;
-		goto error;
-	}
-
-	dev_dbg(&priv->i2c->dev, "%s: voltage=%d\n", __func__, fe_sec_voltage);
-
-	switch (fe_sec_voltage) {
-	case SEC_VOLTAGE_13:
-		voltage = 0;
-		break;
-	case SEC_VOLTAGE_18:
-		voltage = 1;
-		break;
-	case SEC_VOLTAGE_OFF:
-		voltage = 0;
-		break;
-	default:
-		dev_dbg(&priv->i2c->dev, "%s: invalid fe_sec_voltage\n",
-				__func__);
-		ret = -EINVAL;
-		goto error;
-	};
-
-	cmd.args[0] = CMD_LNB_SET_DC_LEVEL;
-	cmd.args[1] = 0;
-	cmd.args[2] = voltage;
-	cmd.len = 3;
-	ret = tda10071_cmd_execute(priv, &cmd);
-	if (ret)
-		goto error;
-
-	return ret;
-error:
-	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
-	return ret;
-}
-
-static int tda10071_diseqc_send_master_cmd(struct dvb_frontend *fe,
-	struct dvb_diseqc_master_cmd *diseqc_cmd)
-{
-	struct tda10071_priv *priv = fe->demodulator_priv;
-	struct tda10071_cmd cmd;
-	int ret, i;
-	u8 tmp;
-
-	if (!priv->warm) {
-		ret = -EFAULT;
-		goto error;
-	}
-
-	dev_dbg(&priv->i2c->dev, "%s: msg_len=%d\n", __func__,
-			diseqc_cmd->msg_len);
-
-	if (diseqc_cmd->msg_len < 3 || diseqc_cmd->msg_len > 6) {
-		ret = -EINVAL;
-		goto error;
-	}
-
-	/* wait LNB TX */
-	for (i = 500, tmp = 0; i && !tmp; i--) {
-		ret = tda10071_rd_reg_mask(priv, 0x47, &tmp, 0x01);
-		if (ret)
-			goto error;
-
-		usleep_range(10000, 20000);
-	}
-
-	dev_dbg(&priv->i2c->dev, "%s: loop=%d\n", __func__, i);
-
-	if (i == 0) {
-		ret = -ETIMEDOUT;
-		goto error;
-	}
-
-	ret = tda10071_wr_reg_mask(priv, 0x47, 0x00, 0x01);
-	if (ret)
-		goto error;
-
-	cmd.args[0] = CMD_LNB_SEND_DISEQC;
-	cmd.args[1] = 0;
-	cmd.args[2] = 0;
-	cmd.args[3] = 0;
-	cmd.args[4] = 2;
-	cmd.args[5] = 0;
-	cmd.args[6] = diseqc_cmd->msg_len;
-	memcpy(&cmd.args[7], diseqc_cmd->msg, diseqc_cmd->msg_len);
-	cmd.len = 7 + diseqc_cmd->msg_len;
-	ret = tda10071_cmd_execute(priv, &cmd);
-	if (ret)
-		goto error;
-
-	return ret;
-error:
-	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
-	return ret;
-}
-
-static int tda10071_diseqc_recv_slave_reply(struct dvb_frontend *fe,
-	struct dvb_diseqc_slave_reply *reply)
-{
-	struct tda10071_priv *priv = fe->demodulator_priv;
-	struct tda10071_cmd cmd;
-	int ret, i;
-	u8 tmp;
-
-	if (!priv->warm) {
-		ret = -EFAULT;
-		goto error;
-	}
-
-	dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
-
-	/* wait LNB RX */
-	for (i = 500, tmp = 0; i && !tmp; i--) {
-		ret = tda10071_rd_reg_mask(priv, 0x47, &tmp, 0x02);
-		if (ret)
-			goto error;
-
-		usleep_range(10000, 20000);
-	}
-
-	dev_dbg(&priv->i2c->dev, "%s: loop=%d\n", __func__, i);
-
-	if (i == 0) {
-		ret = -ETIMEDOUT;
-		goto error;
-	}
-
-	/* reply len */
-	ret = tda10071_rd_reg(priv, 0x46, &tmp);
-	if (ret)
-		goto error;
-
-	reply->msg_len = tmp & 0x1f; /* [4:0] */;
-	if (reply->msg_len > sizeof(reply->msg))
-		reply->msg_len = sizeof(reply->msg); /* truncate API max */
-
-	/* read reply */
-	cmd.args[0] = CMD_LNB_UPDATE_REPLY;
-	cmd.args[1] = 0;
-	cmd.len = 2;
-	ret = tda10071_cmd_execute(priv, &cmd);
-	if (ret)
-		goto error;
-
-	ret = tda10071_rd_regs(priv, cmd.len, reply->msg, reply->msg_len);
-	if (ret)
-		goto error;
-
-	return ret;
-error:
-	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
-	return ret;
-}
-
-static int tda10071_diseqc_send_burst(struct dvb_frontend *fe,
-	fe_sec_mini_cmd_t fe_sec_mini_cmd)
-{
-	struct tda10071_priv *priv = fe->demodulator_priv;
-	struct tda10071_cmd cmd;
-	int ret, i;
-	u8 tmp, burst;
-
-	if (!priv->warm) {
-		ret = -EFAULT;
-		goto error;
-	}
-
-	dev_dbg(&priv->i2c->dev, "%s: fe_sec_mini_cmd=%d\n", __func__,
-			fe_sec_mini_cmd);
-
-	switch (fe_sec_mini_cmd) {
-	case SEC_MINI_A:
-		burst = 0;
-		break;
-	case SEC_MINI_B:
-		burst = 1;
-		break;
-	default:
-		dev_dbg(&priv->i2c->dev, "%s: invalid fe_sec_mini_cmd\n",
-				__func__);
-		ret = -EINVAL;
-		goto error;
-	}
-
-	/* wait LNB TX */
-	for (i = 500, tmp = 0; i && !tmp; i--) {
-		ret = tda10071_rd_reg_mask(priv, 0x47, &tmp, 0x01);
-		if (ret)
-			goto error;
-
-		usleep_range(10000, 20000);
-	}
-
-	dev_dbg(&priv->i2c->dev, "%s: loop=%d\n", __func__, i);
-
-	if (i == 0) {
-		ret = -ETIMEDOUT;
-		goto error;
-	}
-
-	ret = tda10071_wr_reg_mask(priv, 0x47, 0x00, 0x01);
-	if (ret)
-		goto error;
-
-	cmd.args[0] = CMD_LNB_SEND_TONEBURST;
-	cmd.args[1] = 0;
-	cmd.args[2] = burst;
-	cmd.len = 3;
-	ret = tda10071_cmd_execute(priv, &cmd);
-	if (ret)
-		goto error;
-
-	return ret;
-error:
-	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
-	return ret;
-}
-
-static int tda10071_read_status(struct dvb_frontend *fe, fe_status_t *status)
-{
-	struct tda10071_priv *priv = fe->demodulator_priv;
-	int ret;
-	u8 tmp;
-
-	*status = 0;
-
-	if (!priv->warm) {
-		ret = 0;
-		goto error;
-	}
-
-	ret = tda10071_rd_reg(priv, 0x39, &tmp);
-	if (ret)
-		goto error;
-
-	if (tmp & 0x01) /* tuner PLL */
-		*status |= FE_HAS_SIGNAL;
-	if (tmp & 0x02) /* demod PLL */
-		*status |= FE_HAS_CARRIER;
-	if (tmp & 0x04) /* viterbi or LDPC*/
-		*status |= FE_HAS_VITERBI;
-	if (tmp & 0x08) /* RS or BCH */
-		*status |= FE_HAS_SYNC | FE_HAS_LOCK;
-
-	priv->fe_status = *status;
-
-	return ret;
-error:
-	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
-	return ret;
-}
-
-static int tda10071_read_snr(struct dvb_frontend *fe, u16 *snr)
-{
-	struct tda10071_priv *priv = fe->demodulator_priv;
-	int ret;
-	u8 buf[2];
-
-	if (!priv->warm || !(priv->fe_status & FE_HAS_LOCK)) {
-		*snr = 0;
-		ret = 0;
-		goto error;
-	}
-
-	ret = tda10071_rd_regs(priv, 0x3a, buf, 2);
-	if (ret)
-		goto error;
-
-	/* Es/No dBx10 */
-	*snr = buf[0] << 8 | buf[1];
-
-	return ret;
-error:
-	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
-	return ret;
-}
-
-static int tda10071_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
-{
-	struct tda10071_priv *priv = fe->demodulator_priv;
-	struct tda10071_cmd cmd;
-	int ret;
-	u8 tmp;
-
-	if (!priv->warm || !(priv->fe_status & FE_HAS_LOCK)) {
-		*strength = 0;
-		ret = 0;
-		goto error;
-	}
-
-	cmd.args[0] = CMD_GET_AGCACC;
-	cmd.args[1] = 0;
-	cmd.len = 2;
-	ret = tda10071_cmd_execute(priv, &cmd);
-	if (ret)
-		goto error;
-
-	/* input power estimate dBm */
-	ret = tda10071_rd_reg(priv, 0x50, &tmp);
-	if (ret)
-		goto error;
-
-	if (tmp < 181)
-		tmp = 181; /* -75 dBm */
-	else if (tmp > 236)
-		tmp = 236; /* -20 dBm */
-
-	/* scale value to 0x0000-0xffff */
-	*strength = (tmp-181) * 0xffff / (236-181);
-
-	return ret;
-error:
-	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
-	return ret;
-}
-
-static int tda10071_read_ber(struct dvb_frontend *fe, u32 *ber)
-{
-	struct tda10071_priv *priv = fe->demodulator_priv;
-	struct tda10071_cmd cmd;
-	int ret, i, len;
-	u8 tmp, reg, buf[8];
-
-	if (!priv->warm || !(priv->fe_status & FE_HAS_LOCK)) {
-		*ber = priv->ber = 0;
-		ret = 0;
-		goto error;
-	}
-
-	switch (priv->delivery_system) {
-	case SYS_DVBS:
-		reg = 0x4c;
-		len = 8;
-		i = 1;
-		break;
-	case SYS_DVBS2:
-		reg = 0x4d;
-		len = 4;
-		i = 0;
-		break;
-	default:
-		*ber = priv->ber = 0;
-		return 0;
-	}
-
-	ret = tda10071_rd_reg(priv, reg, &tmp);
-	if (ret)
-		goto error;
-
-	if (priv->meas_count[i] == tmp) {
-		dev_dbg(&priv->i2c->dev, "%s: meas not ready=%02x\n", __func__,
-				tmp);
-		*ber = priv->ber;
-		return 0;
-	} else {
-		priv->meas_count[i] = tmp;
-	}
-
-	cmd.args[0] = CMD_BER_UPDATE_COUNTERS;
-	cmd.args[1] = 0;
-	cmd.args[2] = i;
-	cmd.len = 3;
-	ret = tda10071_cmd_execute(priv, &cmd);
-	if (ret)
-		goto error;
-
-	ret = tda10071_rd_regs(priv, cmd.len, buf, len);
-	if (ret)
-		goto error;
-
-	if (priv->delivery_system == SYS_DVBS) {
-		*ber = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
-		priv->ucb += (buf[4] << 8) | buf[5];
-	} else {
-		*ber = (buf[0] << 8) | buf[1];
-	}
-	priv->ber = *ber;
-
-	return ret;
-error:
-	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
-	return ret;
-}
-
-static int tda10071_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
-{
-	struct tda10071_priv *priv = fe->demodulator_priv;
-	int ret = 0;
-
-	if (!priv->warm || !(priv->fe_status & FE_HAS_LOCK)) {
-		*ucblocks = 0;
-		goto error;
-	}
-
-	/* UCB is updated when BER is read. Assume BER is read anyway. */
-
-	*ucblocks = priv->ucb;
-
-	return ret;
-error:
-	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
-	return ret;
-}
-
-static int tda10071_set_frontend(struct dvb_frontend *fe)
-{
-	struct tda10071_priv *priv = fe->demodulator_priv;
-	struct tda10071_cmd cmd;
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	int ret, i;
-	u8 mode, rolloff, pilot, inversion, div;
-
-	dev_dbg(&priv->i2c->dev, "%s: delivery_system=%d modulation=%d " \
-		"frequency=%d symbol_rate=%d inversion=%d pilot=%d " \
-		"rolloff=%d\n", __func__, c->delivery_system, c->modulation,
-		c->frequency, c->symbol_rate, c->inversion, c->pilot,
-		c->rolloff);
-
-	priv->delivery_system = SYS_UNDEFINED;
-
-	if (!priv->warm) {
-		ret = -EFAULT;
-		goto error;
-	}
-
-	switch (c->inversion) {
-	case INVERSION_OFF:
-		inversion = 1;
-		break;
-	case INVERSION_ON:
-		inversion = 0;
-		break;
-	case INVERSION_AUTO:
-		/* 2 = auto; try first on then off
-		 * 3 = auto; try first off then on */
-		inversion = 3;
-		break;
-	default:
-		dev_dbg(&priv->i2c->dev, "%s: invalid inversion\n", __func__);
-		ret = -EINVAL;
-		goto error;
-	}
-
-	switch (c->delivery_system) {
-	case SYS_DVBS:
-		rolloff = 0;
-		pilot = 2;
-		break;
-	case SYS_DVBS2:
-		switch (c->rolloff) {
-		case ROLLOFF_20:
-			rolloff = 2;
-			break;
-		case ROLLOFF_25:
-			rolloff = 1;
-			break;
-		case ROLLOFF_35:
-			rolloff = 0;
-			break;
-		case ROLLOFF_AUTO:
-		default:
-			dev_dbg(&priv->i2c->dev, "%s: invalid rolloff\n",
-					__func__);
-			ret = -EINVAL;
-			goto error;
-		}
-
-		switch (c->pilot) {
-		case PILOT_OFF:
-			pilot = 0;
-			break;
-		case PILOT_ON:
-			pilot = 1;
-			break;
-		case PILOT_AUTO:
-			pilot = 2;
-			break;
-		default:
-			dev_dbg(&priv->i2c->dev, "%s: invalid pilot\n",
-					__func__);
-			ret = -EINVAL;
-			goto error;
-		}
-		break;
-	default:
-		dev_dbg(&priv->i2c->dev, "%s: invalid delivery_system\n",
-				__func__);
-		ret = -EINVAL;
-		goto error;
-	}
-
-	for (i = 0, mode = 0xff; i < ARRAY_SIZE(TDA10071_MODCOD); i++) {
-		if (c->delivery_system == TDA10071_MODCOD[i].delivery_system &&
-			c->modulation == TDA10071_MODCOD[i].modulation &&
-			c->fec_inner == TDA10071_MODCOD[i].fec) {
-			mode = TDA10071_MODCOD[i].val;
-			dev_dbg(&priv->i2c->dev, "%s: mode found=%02x\n",
-					__func__, mode);
-			break;
-		}
-	}
-
-	if (mode == 0xff) {
-		dev_dbg(&priv->i2c->dev, "%s: invalid parameter combination\n",
-				__func__);
-		ret = -EINVAL;
-		goto error;
-	}
-
-	if (c->symbol_rate <= 5000000)
-		div = 14;
-	else
-		div = 4;
-
-	ret = tda10071_wr_reg(priv, 0x81, div);
-	if (ret)
-		goto error;
-
-	ret = tda10071_wr_reg(priv, 0xe3, div);
-	if (ret)
-		goto error;
-
-	cmd.args[0] = CMD_CHANGE_CHANNEL;
-	cmd.args[1] = 0;
-	cmd.args[2] = mode;
-	cmd.args[3] = (c->frequency >> 16) & 0xff;
-	cmd.args[4] = (c->frequency >>  8) & 0xff;
-	cmd.args[5] = (c->frequency >>  0) & 0xff;
-	cmd.args[6] = ((c->symbol_rate / 1000) >> 8) & 0xff;
-	cmd.args[7] = ((c->symbol_rate / 1000) >> 0) & 0xff;
-	cmd.args[8] = (tda10071_ops.info.frequency_tolerance >> 8) & 0xff;
-	cmd.args[9] = (tda10071_ops.info.frequency_tolerance >> 0) & 0xff;
-	cmd.args[10] = rolloff;
-	cmd.args[11] = inversion;
-	cmd.args[12] = pilot;
-	cmd.args[13] = 0x00;
-	cmd.args[14] = 0x00;
-	cmd.len = 15;
-	ret = tda10071_cmd_execute(priv, &cmd);
-	if (ret)
-		goto error;
-
-	priv->delivery_system = c->delivery_system;
-
-	return ret;
-error:
-	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
-	return ret;
-}
-
-static int tda10071_get_frontend(struct dvb_frontend *fe)
-{
-	struct tda10071_priv *priv = fe->demodulator_priv;
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	int ret, i;
-	u8 buf[5], tmp;
-
-	if (!priv->warm || !(priv->fe_status & FE_HAS_LOCK)) {
-		ret = -EFAULT;
-		goto error;
-	}
-
-	ret = tda10071_rd_regs(priv, 0x30, buf, 5);
-	if (ret)
-		goto error;
-
-	tmp = buf[0] & 0x3f;
-	for (i = 0; i < ARRAY_SIZE(TDA10071_MODCOD); i++) {
-		if (tmp == TDA10071_MODCOD[i].val) {
-			c->modulation = TDA10071_MODCOD[i].modulation;
-			c->fec_inner = TDA10071_MODCOD[i].fec;
-			c->delivery_system = TDA10071_MODCOD[i].delivery_system;
-		}
-	}
-
-	switch ((buf[1] >> 0) & 0x01) {
-	case 0:
-		c->inversion = INVERSION_OFF;
-		break;
-	case 1:
-		c->inversion = INVERSION_ON;
-		break;
-	}
-
-	switch ((buf[1] >> 7) & 0x01) {
-	case 0:
-		c->pilot = PILOT_OFF;
-		break;
-	case 1:
-		c->pilot = PILOT_ON;
-		break;
-	}
-
-	c->frequency = (buf[2] << 16) | (buf[3] << 8) | (buf[4] << 0);
-
-	ret = tda10071_rd_regs(priv, 0x52, buf, 3);
-	if (ret)
-		goto error;
-
-	c->symbol_rate = (buf[0] << 16) | (buf[1] << 8) | (buf[2] << 0);
-
-	return ret;
-error:
-	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
-	return ret;
-}
-
-static int tda10071_init(struct dvb_frontend *fe)
-{
-	struct tda10071_priv *priv = fe->demodulator_priv;
-	struct tda10071_cmd cmd;
-	int ret, i, len, remaining, fw_size;
-	const struct firmware *fw;
-	u8 *fw_file = TDA10071_DEFAULT_FIRMWARE;
-	u8 tmp, buf[4];
-	struct tda10071_reg_val_mask tab[] = {
-		{ 0xcd, 0x00, 0x07 },
-		{ 0x80, 0x00, 0x02 },
-		{ 0xcd, 0x00, 0xc0 },
-		{ 0xce, 0x00, 0x1b },
-		{ 0x9d, 0x00, 0x01 },
-		{ 0x9d, 0x00, 0x02 },
-		{ 0x9e, 0x00, 0x01 },
-		{ 0x87, 0x00, 0x80 },
-		{ 0xce, 0x00, 0x08 },
-		{ 0xce, 0x00, 0x10 },
-	};
-	struct tda10071_reg_val_mask tab2[] = {
-		{ 0xf1, 0x70, 0xff },
-		{ 0x88, priv->cfg.pll_multiplier, 0x3f },
-		{ 0x89, 0x00, 0x10 },
-		{ 0x89, 0x10, 0x10 },
-		{ 0xc0, 0x01, 0x01 },
-		{ 0xc0, 0x00, 0x01 },
-		{ 0xe0, 0xff, 0xff },
-		{ 0xe0, 0x00, 0xff },
-		{ 0x96, 0x1e, 0x7e },
-		{ 0x8b, 0x08, 0x08 },
-		{ 0x8b, 0x00, 0x08 },
-		{ 0x8f, 0x1a, 0x7e },
-		{ 0x8c, 0x68, 0xff },
-		{ 0x8d, 0x08, 0xff },
-		{ 0x8e, 0x4c, 0xff },
-		{ 0x8f, 0x01, 0x01 },
-		{ 0x8b, 0x04, 0x04 },
-		{ 0x8b, 0x00, 0x04 },
-		{ 0x87, 0x05, 0x07 },
-		{ 0x80, 0x00, 0x20 },
-		{ 0xc8, 0x01, 0xff },
-		{ 0xb4, 0x47, 0xff },
-		{ 0xb5, 0x9c, 0xff },
-		{ 0xb6, 0x7d, 0xff },
-		{ 0xba, 0x00, 0x03 },
-		{ 0xb7, 0x47, 0xff },
-		{ 0xb8, 0x9c, 0xff },
-		{ 0xb9, 0x7d, 0xff },
-		{ 0xba, 0x00, 0x0c },
-		{ 0xc8, 0x00, 0xff },
-		{ 0xcd, 0x00, 0x04 },
-		{ 0xcd, 0x00, 0x20 },
-		{ 0xe8, 0x02, 0xff },
-		{ 0xcf, 0x20, 0xff },
-		{ 0x9b, 0xd7, 0xff },
-		{ 0x9a, 0x01, 0x03 },
-		{ 0xa8, 0x05, 0x0f },
-		{ 0xa8, 0x65, 0xf0 },
-		{ 0xa6, 0xa0, 0xf0 },
-		{ 0x9d, 0x50, 0xfc },
-		{ 0x9e, 0x20, 0xe0 },
-		{ 0xa3, 0x1c, 0x7c },
-		{ 0xd5, 0x03, 0x03 },
-	};
-
-	/* firmware status */
-	ret = tda10071_rd_reg(priv, 0x51, &tmp);
-	if (ret)
-		goto error;
-
-	if (!tmp) {
-		/* warm state - wake up device from sleep */
-		priv->warm = 1;
-
-		for (i = 0; i < ARRAY_SIZE(tab); i++) {
-			ret = tda10071_wr_reg_mask(priv, tab[i].reg,
-				tab[i].val, tab[i].mask);
-			if (ret)
-				goto error;
-		}
-
-		cmd.args[0] = CMD_SET_SLEEP_MODE;
-		cmd.args[1] = 0;
-		cmd.args[2] = 0;
-		cmd.len = 3;
-		ret = tda10071_cmd_execute(priv, &cmd);
-		if (ret)
-			goto error;
-	} else {
-		/* cold state - try to download firmware */
-		priv->warm = 0;
-
-		/* request the firmware, this will block and timeout */
-		ret = request_firmware(&fw, fw_file, priv->i2c->dev.parent);
-		if (ret) {
-			dev_err(&priv->i2c->dev, "%s: did not find the " \
-					"firmware file. (%s) Please see " \
-					"linux/Documentation/dvb/ for more " \
-					"details on firmware-problems. (%d)\n",
-					KBUILD_MODNAME, fw_file, ret);
-			goto error;
-		}
-
-		/* init */
-		for (i = 0; i < ARRAY_SIZE(tab2); i++) {
-			ret = tda10071_wr_reg_mask(priv, tab2[i].reg,
-				tab2[i].val, tab2[i].mask);
-			if (ret)
-				goto error_release_firmware;
-		}
-
-		/*  download firmware */
-		ret = tda10071_wr_reg(priv, 0xe0, 0x7f);
-		if (ret)
-			goto error_release_firmware;
-
-		ret = tda10071_wr_reg(priv, 0xf7, 0x81);
-		if (ret)
-			goto error_release_firmware;
-
-		ret = tda10071_wr_reg(priv, 0xf8, 0x00);
-		if (ret)
-			goto error_release_firmware;
-
-		ret = tda10071_wr_reg(priv, 0xf9, 0x00);
-		if (ret)
-			goto error_release_firmware;
-
-		dev_info(&priv->i2c->dev, "%s: found a '%s' in cold state, " \
-				"will try to load a firmware\n", KBUILD_MODNAME,
-				tda10071_ops.info.name);
-		dev_info(&priv->i2c->dev, "%s: downloading firmware from " \
-				"file '%s'\n", KBUILD_MODNAME, fw_file);
-
-		/* do not download last byte */
-		fw_size = fw->size - 1;
-
-		for (remaining = fw_size; remaining > 0;
-			remaining -= (priv->cfg.i2c_wr_max - 1)) {
-			len = remaining;
-			if (len > (priv->cfg.i2c_wr_max - 1))
-				len = (priv->cfg.i2c_wr_max - 1);
-
-			ret = tda10071_wr_regs(priv, 0xfa,
-				(u8 *) &fw->data[fw_size - remaining], len);
-			if (ret) {
-				dev_err(&priv->i2c->dev, "%s: firmware " \
-						"download failed=%d\n",
-						KBUILD_MODNAME, ret);
-				if (ret)
-					goto error_release_firmware;
-			}
-		}
-		release_firmware(fw);
-
-		ret = tda10071_wr_reg(priv, 0xf7, 0x0c);
-		if (ret)
-			goto error;
-
-		ret = tda10071_wr_reg(priv, 0xe0, 0x00);
-		if (ret)
-			goto error;
-
-		/* wait firmware start */
-		msleep(250);
-
-		/* firmware status */
-		ret = tda10071_rd_reg(priv, 0x51, &tmp);
-		if (ret)
-			goto error;
-
-		if (tmp) {
-			dev_info(&priv->i2c->dev, "%s: firmware did not run\n",
-					KBUILD_MODNAME);
-			ret = -EFAULT;
-			goto error;
-		} else {
-			priv->warm = 1;
-		}
-
-		cmd.args[0] = CMD_GET_FW_VERSION;
-		cmd.len = 1;
-		ret = tda10071_cmd_execute(priv, &cmd);
-		if (ret)
-			goto error;
-
-		ret = tda10071_rd_regs(priv, cmd.len, buf, 4);
-		if (ret)
-			goto error;
-
-		dev_info(&priv->i2c->dev, "%s: firmware version %d.%d.%d.%d\n",
-				KBUILD_MODNAME, buf[0], buf[1], buf[2], buf[3]);
-		dev_info(&priv->i2c->dev, "%s: found a '%s' in warm state\n",
-				KBUILD_MODNAME, tda10071_ops.info.name);
-
-		ret = tda10071_rd_regs(priv, 0x81, buf, 2);
-		if (ret)
-			goto error;
-
-		cmd.args[0] = CMD_DEMOD_INIT;
-		cmd.args[1] = ((priv->cfg.xtal / 1000) >> 8) & 0xff;
-		cmd.args[2] = ((priv->cfg.xtal / 1000) >> 0) & 0xff;
-		cmd.args[3] = buf[0];
-		cmd.args[4] = buf[1];
-		cmd.args[5] = priv->cfg.pll_multiplier;
-		cmd.args[6] = priv->cfg.spec_inv;
-		cmd.args[7] = 0x00;
-		cmd.len = 8;
-		ret = tda10071_cmd_execute(priv, &cmd);
-		if (ret)
-			goto error;
-
-		cmd.args[0] = CMD_TUNER_INIT;
-		cmd.args[1] = 0x00;
-		cmd.args[2] = 0x00;
-		cmd.args[3] = 0x00;
-		cmd.args[4] = 0x00;
-		cmd.args[5] = 0x14;
-		cmd.args[6] = 0x00;
-		cmd.args[7] = 0x03;
-		cmd.args[8] = 0x02;
-		cmd.args[9] = 0x02;
-		cmd.args[10] = 0x00;
-		cmd.args[11] = 0x00;
-		cmd.args[12] = 0x00;
-		cmd.args[13] = 0x00;
-		cmd.args[14] = 0x00;
-		cmd.len = 15;
-		ret = tda10071_cmd_execute(priv, &cmd);
-		if (ret)
-			goto error;
-
-		cmd.args[0] = CMD_MPEG_CONFIG;
-		cmd.args[1] = 0;
-		cmd.args[2] = priv->cfg.ts_mode;
-		cmd.args[3] = 0x00;
-		cmd.args[4] = 0x04;
-		cmd.args[5] = 0x00;
-		cmd.len = 6;
-		ret = tda10071_cmd_execute(priv, &cmd);
-		if (ret)
-			goto error;
-
-		ret = tda10071_wr_reg_mask(priv, 0xf0, 0x01, 0x01);
-		if (ret)
-			goto error;
-
-		cmd.args[0] = CMD_LNB_CONFIG;
-		cmd.args[1] = 0;
-		cmd.args[2] = 150;
-		cmd.args[3] = 3;
-		cmd.args[4] = 22;
-		cmd.args[5] = 1;
-		cmd.args[6] = 1;
-		cmd.args[7] = 30;
-		cmd.args[8] = 30;
-		cmd.args[9] = 30;
-		cmd.args[10] = 30;
-		cmd.len = 11;
-		ret = tda10071_cmd_execute(priv, &cmd);
-		if (ret)
-			goto error;
-
-		cmd.args[0] = CMD_BER_CONTROL;
-		cmd.args[1] = 0;
-		cmd.args[2] = 14;
-		cmd.args[3] = 14;
-		cmd.len = 4;
-		ret = tda10071_cmd_execute(priv, &cmd);
-		if (ret)
-			goto error;
-	}
-
-	return ret;
-error_release_firmware:
-	release_firmware(fw);
-error:
-	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
-	return ret;
-}
-
-static int tda10071_sleep(struct dvb_frontend *fe)
-{
-	struct tda10071_priv *priv = fe->demodulator_priv;
-	struct tda10071_cmd cmd;
-	int ret, i;
-	struct tda10071_reg_val_mask tab[] = {
-		{ 0xcd, 0x07, 0x07 },
-		{ 0x80, 0x02, 0x02 },
-		{ 0xcd, 0xc0, 0xc0 },
-		{ 0xce, 0x1b, 0x1b },
-		{ 0x9d, 0x01, 0x01 },
-		{ 0x9d, 0x02, 0x02 },
-		{ 0x9e, 0x01, 0x01 },
-		{ 0x87, 0x80, 0x80 },
-		{ 0xce, 0x08, 0x08 },
-		{ 0xce, 0x10, 0x10 },
-	};
-
-	if (!priv->warm) {
-		ret = -EFAULT;
-		goto error;
-	}
-
-	cmd.args[0] = CMD_SET_SLEEP_MODE;
-	cmd.args[1] = 0;
-	cmd.args[2] = 1;
-	cmd.len = 3;
-	ret = tda10071_cmd_execute(priv, &cmd);
-	if (ret)
-		goto error;
-
-	for (i = 0; i < ARRAY_SIZE(tab); i++) {
-		ret = tda10071_wr_reg_mask(priv, tab[i].reg, tab[i].val,
-			tab[i].mask);
-		if (ret)
-			goto error;
-	}
-
-	return ret;
-error:
-	dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
-	return ret;
-}
-
-static int tda10071_get_tune_settings(struct dvb_frontend *fe,
-	struct dvb_frontend_tune_settings *s)
-{
-	s->min_delay_ms = 8000;
-	s->step_size = 0;
-	s->max_drift = 0;
-
-	return 0;
-}
-
-static void tda10071_release(struct dvb_frontend *fe)
-{
-	struct tda10071_priv *priv = fe->demodulator_priv;
-	kfree(priv);
-}
-
-struct dvb_frontend *tda10071_attach(const struct tda10071_config *config,
-	struct i2c_adapter *i2c)
-{
-	int ret;
-	struct tda10071_priv *priv = NULL;
-	u8 tmp;
-
-	/* allocate memory for the internal priv */
-	priv = kzalloc(sizeof(struct tda10071_priv), GFP_KERNEL);
-	if (priv == NULL) {
-		ret = -ENOMEM;
-		goto error;
-	}
-
-	/* setup the priv */
-	priv->i2c = i2c;
-	memcpy(&priv->cfg, config, sizeof(struct tda10071_config));
-
-	/* chip ID */
-	ret = tda10071_rd_reg(priv, 0xff, &tmp);
-	if (ret || tmp != 0x0f)
-		goto error;
-
-	/* chip type */
-	ret = tda10071_rd_reg(priv, 0xdd, &tmp);
-	if (ret || tmp != 0x00)
-		goto error;
-
-	/* chip version */
-	ret = tda10071_rd_reg(priv, 0xfe, &tmp);
-	if (ret || tmp != 0x01)
-		goto error;
-
-	/* create dvb_frontend */
-	memcpy(&priv->fe.ops, &tda10071_ops, sizeof(struct dvb_frontend_ops));
-	priv->fe.demodulator_priv = priv;
-
-	return &priv->fe;
-error:
-	dev_dbg(&i2c->dev, "%s: failed=%d\n", __func__, ret);
-	kfree(priv);
-	return NULL;
-}
-EXPORT_SYMBOL(tda10071_attach);
-
-static struct dvb_frontend_ops tda10071_ops = {
-	.delsys = { SYS_DVBS, SYS_DVBS2 },
-	.info = {
-		.name = "NXP TDA10071",
-		.frequency_min = 950000,
-		.frequency_max = 2150000,
-		.frequency_tolerance = 5000,
-		.symbol_rate_min = 1000000,
-		.symbol_rate_max = 45000000,
-		.caps = FE_CAN_INVERSION_AUTO |
-			FE_CAN_FEC_1_2 |
-			FE_CAN_FEC_2_3 |
-			FE_CAN_FEC_3_4 |
-			FE_CAN_FEC_4_5 |
-			FE_CAN_FEC_5_6 |
-			FE_CAN_FEC_6_7 |
-			FE_CAN_FEC_7_8 |
-			FE_CAN_FEC_8_9 |
-			FE_CAN_FEC_AUTO |
-			FE_CAN_QPSK |
-			FE_CAN_RECOVER |
-			FE_CAN_2G_MODULATION
-	},
-
-	.release = tda10071_release,
-
-	.get_tune_settings = tda10071_get_tune_settings,
-
-	.init = tda10071_init,
-	.sleep = tda10071_sleep,
-
-	.set_frontend = tda10071_set_frontend,
-	.get_frontend = tda10071_get_frontend,
-
-	.read_status = tda10071_read_status,
-	.read_snr = tda10071_read_snr,
-	.read_signal_strength = tda10071_read_signal_strength,
-	.read_ber = tda10071_read_ber,
-	.read_ucblocks = tda10071_read_ucblocks,
-
-	.diseqc_send_master_cmd = tda10071_diseqc_send_master_cmd,
-	.diseqc_recv_slave_reply = tda10071_diseqc_recv_slave_reply,
-	.diseqc_send_burst = tda10071_diseqc_send_burst,
-
-	.set_tone = tda10071_set_tone,
-	.set_voltage = tda10071_set_voltage,
-};
-
-MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
-MODULE_DESCRIPTION("NXP TDA10071 DVB-S/S2 demodulator driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/tda10071.h b/drivers/media/dvb/frontends/tda10071.h
deleted file mode 100644
index 21163c4..0000000
--- a/drivers/media/dvb/frontends/tda10071.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * NXP TDA10071 + Conexant CX24118A DVB-S/S2 demodulator + tuner driver
- *
- * Copyright (C) 2011 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.,
- *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef TDA10071_H
-#define TDA10071_H
-
-#include <linux/dvb/frontend.h>
-
-struct tda10071_config {
-	/* Demodulator I2C address.
-	 * Default: none, must set
-	 * Values: 0x55,
-	 */
-	u8 i2c_address;
-
-	/* Max bytes I2C provider can write at once.
-	 * Note: Buffer is taken from the stack currently!
-	 * Default: none, must set
-	 * Values:
-	 */
-	u16 i2c_wr_max;
-
-	/* TS output mode.
-	 * Default: TDA10071_TS_SERIAL
-	 * Values:
-	 */
-#define TDA10071_TS_SERIAL        0
-#define TDA10071_TS_PARALLEL      1
-	u8 ts_mode;
-
-	/* Input spectrum inversion.
-	 * Default: 0
-	 * Values: 0, 1
-	 */
-	bool spec_inv;
-
-	/* Xtal frequency Hz
-	 * Default: none, must set
-	 * Values:
-	 */
-	u32 xtal;
-
-	/* PLL multiplier.
-	 * Default: none, must set
-	 * Values:
-	 */
-	u8 pll_multiplier;
-};
-
-
-#if defined(CONFIG_DVB_TDA10071) || \
-	(defined(CONFIG_DVB_TDA10071_MODULE) && defined(MODULE))
-extern struct dvb_frontend *tda10071_attach(
-	const struct tda10071_config *config, struct i2c_adapter *i2c);
-#else
-static inline struct dvb_frontend *tda10071_attach(
-	const struct tda10071_config *config, struct i2c_adapter *i2c)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif
-
-#endif /* TDA10071_H */
diff --git a/drivers/media/dvb/frontends/tda10071_priv.h b/drivers/media/dvb/frontends/tda10071_priv.h
deleted file mode 100644
index 0fa85cf..0000000
--- a/drivers/media/dvb/frontends/tda10071_priv.h
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * NXP TDA10071 + Conexant CX24118A DVB-S/S2 demodulator + tuner driver
- *
- * Copyright (C) 2011 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.,
- *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef TDA10071_PRIV
-#define TDA10071_PRIV
-
-#include "dvb_frontend.h"
-#include "tda10071.h"
-#include <linux/firmware.h>
-
-struct tda10071_priv {
-	struct i2c_adapter *i2c;
-	struct dvb_frontend fe;
-	struct tda10071_config cfg;
-
-	u8 meas_count[2];
-	u32 ber;
-	u32 ucb;
-	fe_status_t fe_status;
-	fe_delivery_system_t delivery_system;
-	bool warm; /* FW running */
-};
-
-static struct tda10071_modcod {
-	fe_delivery_system_t delivery_system;
-	fe_modulation_t modulation;
-	fe_code_rate_t fec;
-	u8 val;
-} TDA10071_MODCOD[] = {
-	/* NBC-QPSK */
-	{ SYS_DVBS2, QPSK,  FEC_AUTO, 0x00 },
-	{ SYS_DVBS2, QPSK,  FEC_1_2,  0x04 },
-	{ SYS_DVBS2, QPSK,  FEC_3_5,  0x05 },
-	{ SYS_DVBS2, QPSK,  FEC_2_3,  0x06 },
-	{ SYS_DVBS2, QPSK,  FEC_3_4,  0x07 },
-	{ SYS_DVBS2, QPSK,  FEC_4_5,  0x08 },
-	{ SYS_DVBS2, QPSK,  FEC_5_6,  0x09 },
-	{ SYS_DVBS2, QPSK,  FEC_8_9,  0x0a },
-	{ SYS_DVBS2, QPSK,  FEC_9_10, 0x0b },
-	/* 8PSK */
-	{ SYS_DVBS2, PSK_8, FEC_3_5,  0x0c },
-	{ SYS_DVBS2, PSK_8, FEC_2_3,  0x0d },
-	{ SYS_DVBS2, PSK_8, FEC_3_4,  0x0e },
-	{ SYS_DVBS2, PSK_8, FEC_5_6,  0x0f },
-	{ SYS_DVBS2, PSK_8, FEC_8_9,  0x10 },
-	{ SYS_DVBS2, PSK_8, FEC_9_10, 0x11 },
-	/* QPSK */
-	{ SYS_DVBS,  QPSK,  FEC_AUTO, 0x2d },
-	{ SYS_DVBS,  QPSK,  FEC_1_2,  0x2e },
-	{ SYS_DVBS,  QPSK,  FEC_2_3,  0x2f },
-	{ SYS_DVBS,  QPSK,  FEC_3_4,  0x30 },
-	{ SYS_DVBS,  QPSK,  FEC_5_6,  0x31 },
-	{ SYS_DVBS,  QPSK,  FEC_7_8,  0x32 },
-};
-
-struct tda10071_reg_val_mask {
-	u8 reg;
-	u8 val;
-	u8 mask;
-};
-
-/* firmware filename */
-#define TDA10071_DEFAULT_FIRMWARE      "dvb-fe-tda10071.fw"
-
-/* firmware commands */
-#define CMD_DEMOD_INIT          0x10
-#define CMD_CHANGE_CHANNEL      0x11
-#define CMD_MPEG_CONFIG         0x13
-#define CMD_TUNER_INIT          0x15
-#define CMD_GET_AGCACC          0x1a
-
-#define CMD_LNB_CONFIG          0x20
-#define CMD_LNB_SEND_DISEQC     0x21
-#define CMD_LNB_SET_DC_LEVEL    0x22
-#define CMD_LNB_PCB_CONFIG      0x23
-#define CMD_LNB_SEND_TONEBURST  0x24
-#define CMD_LNB_UPDATE_REPLY    0x25
-
-#define CMD_GET_FW_VERSION      0x35
-#define CMD_SET_SLEEP_MODE      0x36
-#define CMD_BER_CONTROL         0x3e
-#define CMD_BER_UPDATE_COUNTERS 0x3f
-
-/* firmare command struct */
-#define TDA10071_ARGLEN      30
-struct tda10071_cmd {
-	u8 args[TDA10071_ARGLEN];
-	u8 len;
-};
-
-
-#endif /* TDA10071_PRIV */
diff --git a/drivers/media/dvb/frontends/tda10086.c b/drivers/media/dvb/frontends/tda10086.c
deleted file mode 100644
index fcfe2e0..0000000
--- a/drivers/media/dvb/frontends/tda10086.c
+++ /dev/null
@@ -1,777 +0,0 @@
-  /*
-     Driver for Philips tda10086 DVBS Demodulator
-
-     (c) 2006 Andrew de Quincey
-
-     This program is free software; you can redistribute it and/or modify
-     it under the terms of the 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/init.h>
-#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/jiffies.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-
-#include "dvb_frontend.h"
-#include "tda10086.h"
-
-#define SACLK 96000000
-
-struct tda10086_state {
-	struct i2c_adapter* i2c;
-	const struct tda10086_config* config;
-	struct dvb_frontend frontend;
-
-	/* private demod data */
-	u32 frequency;
-	u32 symbol_rate;
-	bool has_lock;
-};
-
-static int debug;
-#define dprintk(args...) \
-	do { \
-		if (debug) printk(KERN_DEBUG "tda10086: " args); \
-	} while (0)
-
-static int tda10086_write_byte(struct tda10086_state *state, int reg, int data)
-{
-	int ret;
-	u8 b0[] = { reg, data };
-	struct i2c_msg msg = { .flags = 0, .buf = b0, .len = 2 };
-
-	msg.addr = state->config->demod_address;
-	ret = i2c_transfer(state->i2c, &msg, 1);
-
-	if (ret != 1)
-		dprintk("%s: error reg=0x%x, data=0x%x, ret=%i\n",
-			__func__, reg, data, ret);
-
-	return (ret != 1) ? ret : 0;
-}
-
-static int tda10086_read_byte(struct tda10086_state *state, int reg)
-{
-	int ret;
-	u8 b0[] = { reg };
-	u8 b1[] = { 0 };
-	struct i2c_msg msg[] = {{ .flags = 0, .buf = b0, .len = 1 },
-				{ .flags = I2C_M_RD, .buf = b1, .len = 1 }};
-
-	msg[0].addr = state->config->demod_address;
-	msg[1].addr = state->config->demod_address;
-	ret = i2c_transfer(state->i2c, msg, 2);
-
-	if (ret != 2) {
-		dprintk("%s: error reg=0x%x, ret=%i\n", __func__, reg,
-			ret);
-		return ret;
-	}
-
-	return b1[0];
-}
-
-static int tda10086_write_mask(struct tda10086_state *state, int reg, int mask, int data)
-{
-	int val;
-
-	/* read a byte and check */
-	val = tda10086_read_byte(state, reg);
-	if (val < 0)
-		return val;
-
-	/* mask if off */
-	val = val & ~mask;
-	val |= data & 0xff;
-
-	/* write it out again */
-	return tda10086_write_byte(state, reg, val);
-}
-
-static int tda10086_init(struct dvb_frontend* fe)
-{
-	struct tda10086_state* state = fe->demodulator_priv;
-	u8 t22k_off = 0x80;
-
-	dprintk ("%s\n", __func__);
-
-	if (state->config->diseqc_tone)
-		t22k_off = 0;
-	/* reset */
-	tda10086_write_byte(state, 0x00, 0x00);
-	msleep(10);
-
-	/* misc setup */
-	tda10086_write_byte(state, 0x01, 0x94);
-	tda10086_write_byte(state, 0x02, 0x35); /* NOTE: TT drivers appear to disable CSWP */
-	tda10086_write_byte(state, 0x03, 0xe4);
-	tda10086_write_byte(state, 0x04, 0x43);
-	tda10086_write_byte(state, 0x0c, 0x0c);
-	tda10086_write_byte(state, 0x1b, 0xb0); /* noise threshold */
-	tda10086_write_byte(state, 0x20, 0x89); /* misc */
-	tda10086_write_byte(state, 0x30, 0x04); /* acquisition period length */
-	tda10086_write_byte(state, 0x32, 0x00); /* irq off */
-	tda10086_write_byte(state, 0x31, 0x56); /* setup AFC */
-
-	/* setup PLL (this assumes SACLK = 96MHz) */
-	tda10086_write_byte(state, 0x55, 0x2c); /* misc PLL setup */
-	if (state->config->xtal_freq == TDA10086_XTAL_16M) {
-		tda10086_write_byte(state, 0x3a, 0x0b); /* M=12 */
-		tda10086_write_byte(state, 0x3b, 0x01); /* P=2 */
-	} else {
-		tda10086_write_byte(state, 0x3a, 0x17); /* M=24 */
-		tda10086_write_byte(state, 0x3b, 0x00); /* P=1 */
-	}
-	tda10086_write_mask(state, 0x55, 0x20, 0x00); /* powerup PLL */
-
-	/* setup TS interface */
-	tda10086_write_byte(state, 0x11, 0x81);
-	tda10086_write_byte(state, 0x12, 0x81);
-	tda10086_write_byte(state, 0x19, 0x40); /* parallel mode A + MSBFIRST */
-	tda10086_write_byte(state, 0x56, 0x80); /* powerdown WPLL - unused in the mode we use */
-	tda10086_write_byte(state, 0x57, 0x08); /* bypass WPLL - unused in the mode we use */
-	tda10086_write_byte(state, 0x10, 0x2a);
-
-	/* setup ADC */
-	tda10086_write_byte(state, 0x58, 0x61); /* ADC setup */
-	tda10086_write_mask(state, 0x58, 0x01, 0x00); /* powerup ADC */
-
-	/* setup AGC */
-	tda10086_write_byte(state, 0x05, 0x0B);
-	tda10086_write_byte(state, 0x37, 0x63);
-	tda10086_write_byte(state, 0x3f, 0x0a); /* NOTE: flydvb varies it */
-	tda10086_write_byte(state, 0x40, 0x64);
-	tda10086_write_byte(state, 0x41, 0x4f);
-	tda10086_write_byte(state, 0x42, 0x43);
-
-	/* setup viterbi */
-	tda10086_write_byte(state, 0x1a, 0x11); /* VBER 10^6, DVB, QPSK */
-
-	/* setup carrier recovery */
-	tda10086_write_byte(state, 0x3d, 0x80);
-
-	/* setup SEC */
-	tda10086_write_byte(state, 0x36, t22k_off); /* all SEC off, 22k tone */
-	tda10086_write_byte(state, 0x34, (((1<<19) * (22000/1000)) / (SACLK/1000)));
-	tda10086_write_byte(state, 0x35, (((1<<19) * (22000/1000)) / (SACLK/1000)) >> 8);
-
-	return 0;
-}
-
-static void tda10086_diseqc_wait(struct tda10086_state *state)
-{
-	unsigned long timeout = jiffies + msecs_to_jiffies(200);
-	while (!(tda10086_read_byte(state, 0x50) & 0x01)) {
-		if(time_after(jiffies, timeout)) {
-			printk("%s: diseqc queue not ready, command may be lost.\n", __func__);
-			break;
-		}
-		msleep(10);
-	}
-}
-
-static int tda10086_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
-{
-	struct tda10086_state* state = fe->demodulator_priv;
-	u8 t22k_off = 0x80;
-
-	dprintk ("%s\n", __func__);
-
-	if (state->config->diseqc_tone)
-		t22k_off = 0;
-
-	switch (tone) {
-	case SEC_TONE_OFF:
-		tda10086_write_byte(state, 0x36, t22k_off);
-		break;
-
-	case SEC_TONE_ON:
-		tda10086_write_byte(state, 0x36, 0x01 + t22k_off);
-		break;
-	}
-
-	return 0;
-}
-
-static int tda10086_send_master_cmd (struct dvb_frontend* fe,
-				    struct dvb_diseqc_master_cmd* cmd)
-{
-	struct tda10086_state* state = fe->demodulator_priv;
-	int i;
-	u8 oldval;
-	u8 t22k_off = 0x80;
-
-	dprintk ("%s\n", __func__);
-
-	if (state->config->diseqc_tone)
-		t22k_off = 0;
-
-	if (cmd->msg_len > 6)
-		return -EINVAL;
-	oldval = tda10086_read_byte(state, 0x36);
-
-	for(i=0; i< cmd->msg_len; i++) {
-		tda10086_write_byte(state, 0x48+i, cmd->msg[i]);
-	}
-	tda10086_write_byte(state, 0x36, (0x08 + t22k_off)
-					| ((cmd->msg_len - 1) << 4));
-
-	tda10086_diseqc_wait(state);
-
-	tda10086_write_byte(state, 0x36, oldval);
-
-	return 0;
-}
-
-static int tda10086_send_burst (struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd)
-{
-	struct tda10086_state* state = fe->demodulator_priv;
-	u8 oldval = tda10086_read_byte(state, 0x36);
-	u8 t22k_off = 0x80;
-
-	dprintk ("%s\n", __func__);
-
-	if (state->config->diseqc_tone)
-		t22k_off = 0;
-
-	switch(minicmd) {
-	case SEC_MINI_A:
-		tda10086_write_byte(state, 0x36, 0x04 + t22k_off);
-		break;
-
-	case SEC_MINI_B:
-		tda10086_write_byte(state, 0x36, 0x06 + t22k_off);
-		break;
-	}
-
-	tda10086_diseqc_wait(state);
-
-	tda10086_write_byte(state, 0x36, oldval);
-
-	return 0;
-}
-
-static int tda10086_set_inversion(struct tda10086_state *state,
-				  struct dtv_frontend_properties *fe_params)
-{
-	u8 invval = 0x80;
-
-	dprintk ("%s %i %i\n", __func__, fe_params->inversion, state->config->invert);
-
-	switch(fe_params->inversion) {
-	case INVERSION_OFF:
-		if (state->config->invert)
-			invval = 0x40;
-		break;
-	case INVERSION_ON:
-		if (!state->config->invert)
-			invval = 0x40;
-		break;
-	case INVERSION_AUTO:
-		invval = 0x00;
-		break;
-	}
-	tda10086_write_mask(state, 0x0c, 0xc0, invval);
-
-	return 0;
-}
-
-static int tda10086_set_symbol_rate(struct tda10086_state *state,
-				    struct dtv_frontend_properties *fe_params)
-{
-	u8 dfn = 0;
-	u8 afs = 0;
-	u8 byp = 0;
-	u8 reg37 = 0x43;
-	u8 reg42 = 0x43;
-	u64 big;
-	u32 tmp;
-	u32 bdr;
-	u32 bdri;
-	u32 symbol_rate = fe_params->symbol_rate;
-
-	dprintk ("%s %i\n", __func__, symbol_rate);
-
-	/* setup the decimation and anti-aliasing filters.. */
-	if (symbol_rate < (u32) (SACLK * 0.0137)) {
-		dfn=4;
-		afs=1;
-	} else if (symbol_rate < (u32) (SACLK * 0.0208)) {
-		dfn=4;
-		afs=0;
-	} else if (symbol_rate < (u32) (SACLK * 0.0270)) {
-		dfn=3;
-		afs=1;
-	} else if (symbol_rate < (u32) (SACLK * 0.0416)) {
-		dfn=3;
-		afs=0;
-	} else if (symbol_rate < (u32) (SACLK * 0.0550)) {
-		dfn=2;
-		afs=1;
-	} else if (symbol_rate < (u32) (SACLK * 0.0833)) {
-		dfn=2;
-		afs=0;
-	} else if (symbol_rate < (u32) (SACLK * 0.1100)) {
-		dfn=1;
-		afs=1;
-	} else if (symbol_rate < (u32) (SACLK * 0.1666)) {
-		dfn=1;
-		afs=0;
-	} else if (symbol_rate < (u32) (SACLK * 0.2200)) {
-		dfn=0;
-		afs=1;
-	} else if (symbol_rate < (u32) (SACLK * 0.3333)) {
-		dfn=0;
-		afs=0;
-	} else {
-		reg37 = 0x63;
-		reg42 = 0x4f;
-		byp=1;
-	}
-
-	/* calculate BDR */
-	big = (1ULL<<21) * ((u64) symbol_rate/1000ULL) * (1ULL<<dfn);
-	big += ((SACLK/1000ULL)-1ULL);
-	do_div(big, (SACLK/1000ULL));
-	bdr = big & 0xfffff;
-
-	/* calculate BDRI */
-	tmp = (1<<dfn)*(symbol_rate/1000);
-	bdri = ((32 * (SACLK/1000)) + (tmp-1)) / tmp;
-
-	tda10086_write_byte(state, 0x21, (afs << 7) | dfn);
-	tda10086_write_mask(state, 0x20, 0x08, byp << 3);
-	tda10086_write_byte(state, 0x06, bdr);
-	tda10086_write_byte(state, 0x07, bdr >> 8);
-	tda10086_write_byte(state, 0x08, bdr >> 16);
-	tda10086_write_byte(state, 0x09, bdri);
-	tda10086_write_byte(state, 0x37, reg37);
-	tda10086_write_byte(state, 0x42, reg42);
-
-	return 0;
-}
-
-static int tda10086_set_fec(struct tda10086_state *state,
-			    struct dtv_frontend_properties *fe_params)
-{
-	u8 fecval;
-
-	dprintk("%s %i\n", __func__, fe_params->fec_inner);
-
-	switch (fe_params->fec_inner) {
-	case FEC_1_2:
-		fecval = 0x00;
-		break;
-	case FEC_2_3:
-		fecval = 0x01;
-		break;
-	case FEC_3_4:
-		fecval = 0x02;
-		break;
-	case FEC_4_5:
-		fecval = 0x03;
-		break;
-	case FEC_5_6:
-		fecval = 0x04;
-		break;
-	case FEC_6_7:
-		fecval = 0x05;
-		break;
-	case FEC_7_8:
-		fecval = 0x06;
-		break;
-	case FEC_8_9:
-		fecval = 0x07;
-		break;
-	case FEC_AUTO:
-		fecval = 0x08;
-		break;
-	default:
-		return -1;
-	}
-	tda10086_write_byte(state, 0x0d, fecval);
-
-	return 0;
-}
-
-static int tda10086_set_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *fe_params = &fe->dtv_property_cache;
-	struct tda10086_state *state = fe->demodulator_priv;
-	int ret;
-	u32 freq = 0;
-	int freqoff;
-
-	dprintk ("%s\n", __func__);
-
-	/* modify parameters for tuning */
-	tda10086_write_byte(state, 0x02, 0x35);
-	state->has_lock = false;
-
-	/* set params */
-	if (fe->ops.tuner_ops.set_params) {
-		fe->ops.tuner_ops.set_params(fe);
-		if (fe->ops.i2c_gate_ctrl)
-			fe->ops.i2c_gate_ctrl(fe, 0);
-
-		if (fe->ops.tuner_ops.get_frequency)
-			fe->ops.tuner_ops.get_frequency(fe, &freq);
-		if (fe->ops.i2c_gate_ctrl)
-			fe->ops.i2c_gate_ctrl(fe, 0);
-	}
-
-	/* calcluate the frequency offset (in *Hz* not kHz) */
-	freqoff = fe_params->frequency - freq;
-	freqoff = ((1<<16) * freqoff) / (SACLK/1000);
-	tda10086_write_byte(state, 0x3d, 0x80 | ((freqoff >> 8) & 0x7f));
-	tda10086_write_byte(state, 0x3e, freqoff);
-
-	if ((ret = tda10086_set_inversion(state, fe_params)) < 0)
-		return ret;
-	if ((ret = tda10086_set_symbol_rate(state, fe_params)) < 0)
-		return ret;
-	if ((ret = tda10086_set_fec(state, fe_params)) < 0)
-		return ret;
-
-	/* soft reset + disable TS output until lock */
-	tda10086_write_mask(state, 0x10, 0x40, 0x40);
-	tda10086_write_mask(state, 0x00, 0x01, 0x00);
-
-	state->symbol_rate = fe_params->symbol_rate;
-	state->frequency = fe_params->frequency;
-	return 0;
-}
-
-static int tda10086_get_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *fe_params = &fe->dtv_property_cache;
-	struct tda10086_state* state = fe->demodulator_priv;
-	u8 val;
-	int tmp;
-	u64 tmp64;
-
-	dprintk ("%s\n", __func__);
-
-	/* check for invalid symbol rate */
-	if (fe_params->symbol_rate < 500000)
-		return -EINVAL;
-
-	/* calculate the updated frequency (note: we convert from Hz->kHz) */
-	tmp64 = tda10086_read_byte(state, 0x52);
-	tmp64 |= (tda10086_read_byte(state, 0x51) << 8);
-	if (tmp64 & 0x8000)
-		tmp64 |= 0xffffffffffff0000ULL;
-	tmp64 = (tmp64 * (SACLK/1000ULL));
-	do_div(tmp64, (1ULL<<15) * (1ULL<<1));
-	fe_params->frequency = (int) state->frequency + (int) tmp64;
-
-	/* the inversion */
-	val = tda10086_read_byte(state, 0x0c);
-	if (val & 0x80) {
-		switch(val & 0x40) {
-		case 0x00:
-			fe_params->inversion = INVERSION_OFF;
-			if (state->config->invert)
-				fe_params->inversion = INVERSION_ON;
-			break;
-		default:
-			fe_params->inversion = INVERSION_ON;
-			if (state->config->invert)
-				fe_params->inversion = INVERSION_OFF;
-			break;
-		}
-	} else {
-		tda10086_read_byte(state, 0x0f);
-		switch(val & 0x02) {
-		case 0x00:
-			fe_params->inversion = INVERSION_OFF;
-			if (state->config->invert)
-				fe_params->inversion = INVERSION_ON;
-			break;
-		default:
-			fe_params->inversion = INVERSION_ON;
-			if (state->config->invert)
-				fe_params->inversion = INVERSION_OFF;
-			break;
-		}
-	}
-
-	/* calculate the updated symbol rate */
-	tmp = tda10086_read_byte(state, 0x1d);
-	if (tmp & 0x80)
-		tmp |= 0xffffff00;
-	tmp = (tmp * 480 * (1<<1)) / 128;
-	tmp = ((state->symbol_rate/1000) * tmp) / (1000000/1000);
-	fe_params->symbol_rate = state->symbol_rate + tmp;
-
-	/* the FEC */
-	val = (tda10086_read_byte(state, 0x0d) & 0x70) >> 4;
-	switch(val) {
-	case 0x00:
-		fe_params->fec_inner = FEC_1_2;
-		break;
-	case 0x01:
-		fe_params->fec_inner = FEC_2_3;
-		break;
-	case 0x02:
-		fe_params->fec_inner = FEC_3_4;
-		break;
-	case 0x03:
-		fe_params->fec_inner = FEC_4_5;
-		break;
-	case 0x04:
-		fe_params->fec_inner = FEC_5_6;
-		break;
-	case 0x05:
-		fe_params->fec_inner = FEC_6_7;
-		break;
-	case 0x06:
-		fe_params->fec_inner = FEC_7_8;
-		break;
-	case 0x07:
-		fe_params->fec_inner = FEC_8_9;
-		break;
-	}
-
-	return 0;
-}
-
-static int tda10086_read_status(struct dvb_frontend* fe, fe_status_t *fe_status)
-{
-	struct tda10086_state* state = fe->demodulator_priv;
-	u8 val;
-
-	dprintk ("%s\n", __func__);
-
-	val = tda10086_read_byte(state, 0x0e);
-	*fe_status = 0;
-	if (val & 0x01)
-		*fe_status |= FE_HAS_SIGNAL;
-	if (val & 0x02)
-		*fe_status |= FE_HAS_CARRIER;
-	if (val & 0x04)
-		*fe_status |= FE_HAS_VITERBI;
-	if (val & 0x08)
-		*fe_status |= FE_HAS_SYNC;
-	if (val & 0x10) {
-		*fe_status |= FE_HAS_LOCK;
-		if (!state->has_lock) {
-			state->has_lock = true;
-			/* modify parameters for stable reception */
-			tda10086_write_byte(state, 0x02, 0x00);
-		}
-	}
-
-	return 0;
-}
-
-static int tda10086_read_signal_strength(struct dvb_frontend* fe, u16 * signal)
-{
-	struct tda10086_state* state = fe->demodulator_priv;
-	u8 _str;
-
-	dprintk ("%s\n", __func__);
-
-	_str = 0xff - tda10086_read_byte(state, 0x43);
-	*signal = (_str << 8) | _str;
-
-	return 0;
-}
-
-static int tda10086_read_snr(struct dvb_frontend* fe, u16 * snr)
-{
-	struct tda10086_state* state = fe->demodulator_priv;
-	u8 _snr;
-
-	dprintk ("%s\n", __func__);
-
-	_snr = 0xff - tda10086_read_byte(state, 0x1c);
-	*snr = (_snr << 8) | _snr;
-
-	return 0;
-}
-
-static int tda10086_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
-{
-	struct tda10086_state* state = fe->demodulator_priv;
-
-	dprintk ("%s\n", __func__);
-
-	/* read it */
-	*ucblocks = tda10086_read_byte(state, 0x18) & 0x7f;
-
-	/* reset counter */
-	tda10086_write_byte(state, 0x18, 0x00);
-	tda10086_write_byte(state, 0x18, 0x80);
-
-	return 0;
-}
-
-static int tda10086_read_ber(struct dvb_frontend* fe, u32* ber)
-{
-	struct tda10086_state* state = fe->demodulator_priv;
-
-	dprintk ("%s\n", __func__);
-
-	/* read it */
-	*ber = 0;
-	*ber |= tda10086_read_byte(state, 0x15);
-	*ber |= tda10086_read_byte(state, 0x16) << 8;
-	*ber |= (tda10086_read_byte(state, 0x17) & 0xf) << 16;
-
-	return 0;
-}
-
-static int tda10086_sleep(struct dvb_frontend* fe)
-{
-	struct tda10086_state* state = fe->demodulator_priv;
-
-	dprintk ("%s\n", __func__);
-
-	tda10086_write_mask(state, 0x00, 0x08, 0x08);
-
-	return 0;
-}
-
-static int tda10086_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
-{
-	struct tda10086_state* state = fe->demodulator_priv;
-
-	dprintk ("%s\n", __func__);
-
-	if (enable) {
-		tda10086_write_mask(state, 0x00, 0x10, 0x10);
-	} else {
-		tda10086_write_mask(state, 0x00, 0x10, 0x00);
-	}
-
-	return 0;
-}
-
-static int tda10086_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-
-	if (p->symbol_rate > 20000000) {
-		fesettings->min_delay_ms = 50;
-		fesettings->step_size = 2000;
-		fesettings->max_drift = 8000;
-	} else if (p->symbol_rate > 12000000) {
-		fesettings->min_delay_ms = 100;
-		fesettings->step_size = 1500;
-		fesettings->max_drift = 9000;
-	} else if (p->symbol_rate > 8000000) {
-		fesettings->min_delay_ms = 100;
-		fesettings->step_size = 1000;
-		fesettings->max_drift = 8000;
-	} else if (p->symbol_rate > 4000000) {
-		fesettings->min_delay_ms = 100;
-		fesettings->step_size = 500;
-		fesettings->max_drift = 7000;
-	} else if (p->symbol_rate > 2000000) {
-		fesettings->min_delay_ms = 200;
-		fesettings->step_size = p->symbol_rate / 8000;
-		fesettings->max_drift = 14 * fesettings->step_size;
-	} else {
-		fesettings->min_delay_ms = 200;
-		fesettings->step_size =  p->symbol_rate / 8000;
-		fesettings->max_drift = 18 * fesettings->step_size;
-	}
-
-	return 0;
-}
-
-static void tda10086_release(struct dvb_frontend* fe)
-{
-	struct tda10086_state *state = fe->demodulator_priv;
-	tda10086_sleep(fe);
-	kfree(state);
-}
-
-static struct dvb_frontend_ops tda10086_ops = {
-	.delsys = { SYS_DVBS },
-	.info = {
-		.name     = "Philips TDA10086 DVB-S",
-		.frequency_min    = 950000,
-		.frequency_max    = 2150000,
-		.frequency_stepsize = 125,     /* kHz for QPSK frontends */
-		.symbol_rate_min  = 1000000,
-		.symbol_rate_max  = 45000000,
-		.caps = FE_CAN_INVERSION_AUTO |
-			FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
-			FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
-			FE_CAN_QPSK
-	},
-
-	.release = tda10086_release,
-
-	.init = tda10086_init,
-	.sleep = tda10086_sleep,
-	.i2c_gate_ctrl = tda10086_i2c_gate_ctrl,
-
-	.set_frontend = tda10086_set_frontend,
-	.get_frontend = tda10086_get_frontend,
-	.get_tune_settings = tda10086_get_tune_settings,
-
-	.read_status = tda10086_read_status,
-	.read_ber = tda10086_read_ber,
-	.read_signal_strength = tda10086_read_signal_strength,
-	.read_snr = tda10086_read_snr,
-	.read_ucblocks = tda10086_read_ucblocks,
-
-	.diseqc_send_master_cmd = tda10086_send_master_cmd,
-	.diseqc_send_burst = tda10086_send_burst,
-	.set_tone = tda10086_set_tone,
-};
-
-struct dvb_frontend* tda10086_attach(const struct tda10086_config* config,
-				     struct i2c_adapter* i2c)
-{
-	struct tda10086_state *state;
-
-	dprintk ("%s\n", __func__);
-
-	/* allocate memory for the internal state */
-	state = kzalloc(sizeof(struct tda10086_state), GFP_KERNEL);
-	if (!state)
-		return NULL;
-
-	/* setup the state */
-	state->config = config;
-	state->i2c = i2c;
-
-	/* check if the demod is there */
-	if (tda10086_read_byte(state, 0x1e) != 0xe1) {
-		kfree(state);
-		return NULL;
-	}
-
-	/* create dvb_frontend */
-	memcpy(&state->frontend.ops, &tda10086_ops, sizeof(struct dvb_frontend_ops));
-	state->frontend.demodulator_priv = state;
-	return &state->frontend;
-}
-
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
-
-MODULE_DESCRIPTION("Philips TDA10086 DVB-S Demodulator");
-MODULE_AUTHOR("Andrew de Quincey");
-MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(tda10086_attach);
diff --git a/drivers/media/dvb/frontends/tda10086.h b/drivers/media/dvb/frontends/tda10086.h
deleted file mode 100644
index 61148c5..0000000
--- a/drivers/media/dvb/frontends/tda10086.h
+++ /dev/null
@@ -1,61 +0,0 @@
-  /*
-     Driver for Philips tda10086 DVBS Frontend
-
-     (c) 2006 Andrew de Quincey
-
-     This program is free software; you can redistribute it and/or modify
-     it under the terms of the 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 TDA10086_H
-#define TDA10086_H
-
-#include <linux/dvb/frontend.h>
-#include <linux/firmware.h>
-
-enum tda10086_xtal {
-	TDA10086_XTAL_16M,
-	TDA10086_XTAL_4M
-};
-
-struct tda10086_config
-{
-	/* the demodulator's i2c address */
-	u8 demod_address;
-
-	/* does the "inversion" need inverted? */
-	u8 invert;
-
-	/* do we need the diseqc signal with carrier? */
-	u8 diseqc_tone;
-
-	/* frequency of the reference xtal */
-	enum tda10086_xtal xtal_freq;
-};
-
-#if defined(CONFIG_DVB_TDA10086) || (defined(CONFIG_DVB_TDA10086_MODULE) && defined(MODULE))
-extern struct dvb_frontend* tda10086_attach(const struct tda10086_config* config,
-					    struct i2c_adapter* i2c);
-#else
-static inline struct dvb_frontend* tda10086_attach(const struct tda10086_config* config,
-						   struct i2c_adapter* i2c)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif /* CONFIG_DVB_TDA10086 */
-
-#endif /* TDA10086_H */
diff --git a/drivers/media/dvb/frontends/tda18271c2dd.c b/drivers/media/dvb/frontends/tda18271c2dd.c
deleted file mode 100644
index ad7c72e..0000000
--- a/drivers/media/dvb/frontends/tda18271c2dd.c
+++ /dev/null
@@ -1,1246 +0,0 @@
-/*
- * tda18271c2dd: Driver for the TDA18271C2 tuner
- *
- * Copyright (C) 2010 Digital Devices GmbH
- *
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 only, as published by the Free Software Foundation.
- *
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/firmware.h>
-#include <linux/i2c.h>
-#include <asm/div64.h>
-
-#include "dvb_frontend.h"
-
-struct SStandardParam {
-	s32   m_IFFrequency;
-	u32   m_BandWidth;
-	u8    m_EP3_4_0;
-	u8    m_EB22;
-};
-
-struct SMap {
-	u32   m_Frequency;
-	u8    m_Param;
-};
-
-struct SMapI {
-	u32   m_Frequency;
-	s32    m_Param;
-};
-
-struct SMap2 {
-	u32   m_Frequency;
-	u8    m_Param1;
-	u8    m_Param2;
-};
-
-struct SRFBandMap {
-	u32   m_RF_max;
-	u32   m_RF1_Default;
-	u32   m_RF2_Default;
-	u32   m_RF3_Default;
-};
-
-enum ERegister {
-	ID = 0,
-	TM,
-	PL,
-	EP1, EP2, EP3, EP4, EP5,
-	CPD, CD1, CD2, CD3,
-	MPD, MD1, MD2, MD3,
-	EB1, EB2, EB3, EB4, EB5, EB6, EB7, EB8, EB9, EB10,
-	EB11, EB12, EB13, EB14, EB15, EB16, EB17, EB18, EB19, EB20,
-	EB21, EB22, EB23,
-	NUM_REGS
-};
-
-struct tda_state {
-	struct i2c_adapter *i2c;
-	u8 adr;
-
-	u32   m_Frequency;
-	u32   IF;
-
-	u8    m_IFLevelAnalog;
-	u8    m_IFLevelDigital;
-	u8    m_IFLevelDVBC;
-	u8    m_IFLevelDVBT;
-
-	u8    m_EP4;
-	u8    m_EP3_Standby;
-
-	bool  m_bMaster;
-
-	s32   m_SettlingTime;
-
-	u8    m_Regs[NUM_REGS];
-
-	/* Tracking filter settings for band 0..6 */
-	u32   m_RF1[7];
-	s32   m_RF_A1[7];
-	s32   m_RF_B1[7];
-	u32   m_RF2[7];
-	s32   m_RF_A2[7];
-	s32   m_RF_B2[7];
-	u32   m_RF3[7];
-
-	u8    m_TMValue_RFCal;    /* Calibration temperatur */
-
-	bool  m_bFMInput;         /* true to use Pin 8 for FM Radio */
-
-};
-
-static int PowerScan(struct tda_state *state,
-		     u8 RFBand, u32 RF_in,
-		     u32 *pRF_Out, bool *pbcal);
-
-static int i2c_readn(struct i2c_adapter *adapter, u8 adr, u8 *data, int len)
-{
-	struct i2c_msg msgs[1] = {{.addr = adr,  .flags = I2C_M_RD,
-				   .buf  = data, .len   = len} };
-	return (i2c_transfer(adapter, msgs, 1) == 1) ? 0 : -1;
-}
-
-static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len)
-{
-	struct i2c_msg msg = {.addr = adr, .flags = 0,
-			      .buf = data, .len = len};
-
-	if (i2c_transfer(adap, &msg, 1) != 1) {
-		printk(KERN_ERR "tda18271c2dd: i2c write error at addr %i\n", adr);
-		return -1;
-	}
-	return 0;
-}
-
-static int WriteRegs(struct tda_state *state,
-		     u8 SubAddr, u8 *Regs, u16 nRegs)
-{
-	u8 data[nRegs+1];
-
-	data[0] = SubAddr;
-	memcpy(data + 1, Regs, nRegs);
-	return i2c_write(state->i2c, state->adr, data, nRegs+1);
-}
-
-static int WriteReg(struct tda_state *state, u8 SubAddr, u8 Reg)
-{
-	u8 msg[2] = {SubAddr, Reg};
-
-	return i2c_write(state->i2c, state->adr, msg, 2);
-}
-
-static int Read(struct tda_state *state, u8 * Regs)
-{
-	return i2c_readn(state->i2c, state->adr, Regs, 16);
-}
-
-static int ReadExtented(struct tda_state *state, u8 * Regs)
-{
-	return i2c_readn(state->i2c, state->adr, Regs, NUM_REGS);
-}
-
-static int UpdateRegs(struct tda_state *state, u8 RegFrom, u8 RegTo)
-{
-	return WriteRegs(state, RegFrom,
-			 &state->m_Regs[RegFrom], RegTo-RegFrom+1);
-}
-static int UpdateReg(struct tda_state *state, u8 Reg)
-{
-	return WriteReg(state, Reg, state->m_Regs[Reg]);
-}
-
-#include "tda18271c2dd_maps.h"
-
-static void reset(struct tda_state *state)
-{
-	u32   ulIFLevelAnalog = 0;
-	u32   ulIFLevelDigital = 2;
-	u32   ulIFLevelDVBC = 7;
-	u32   ulIFLevelDVBT = 6;
-	u32   ulXTOut = 0;
-	u32   ulStandbyMode = 0x06;    /* Send in stdb, but leave osc on */
-	u32   ulSlave = 0;
-	u32   ulFMInput = 0;
-	u32   ulSettlingTime = 100;
-
-	state->m_Frequency         = 0;
-	state->m_SettlingTime = 100;
-	state->m_IFLevelAnalog = (ulIFLevelAnalog & 0x07) << 2;
-	state->m_IFLevelDigital = (ulIFLevelDigital & 0x07) << 2;
-	state->m_IFLevelDVBC = (ulIFLevelDVBC & 0x07) << 2;
-	state->m_IFLevelDVBT = (ulIFLevelDVBT & 0x07) << 2;
-
-	state->m_EP4 = 0x20;
-	if (ulXTOut != 0)
-		state->m_EP4 |= 0x40;
-
-	state->m_EP3_Standby = ((ulStandbyMode & 0x07) << 5) | 0x0F;
-	state->m_bMaster = (ulSlave == 0);
-
-	state->m_SettlingTime = ulSettlingTime;
-
-	state->m_bFMInput = (ulFMInput == 2);
-}
-
-static bool SearchMap1(struct SMap Map[],
-		       u32 Frequency, u8 *pParam)
-{
-	int i = 0;
-
-	while ((Map[i].m_Frequency != 0) && (Frequency > Map[i].m_Frequency))
-		i += 1;
-	if (Map[i].m_Frequency == 0)
-		return false;
-	*pParam = Map[i].m_Param;
-	return true;
-}
-
-static bool SearchMap2(struct SMapI Map[],
-		       u32 Frequency, s32 *pParam)
-{
-	int i = 0;
-
-	while ((Map[i].m_Frequency != 0) &&
-	       (Frequency > Map[i].m_Frequency))
-		i += 1;
-	if (Map[i].m_Frequency == 0)
-		return false;
-	*pParam = Map[i].m_Param;
-	return true;
-}
-
-static bool SearchMap3(struct SMap2 Map[], u32 Frequency,
-		       u8 *pParam1, u8 *pParam2)
-{
-	int i = 0;
-
-	while ((Map[i].m_Frequency != 0) &&
-	       (Frequency > Map[i].m_Frequency))
-		i += 1;
-	if (Map[i].m_Frequency == 0)
-		return false;
-	*pParam1 = Map[i].m_Param1;
-	*pParam2 = Map[i].m_Param2;
-	return true;
-}
-
-static bool SearchMap4(struct SRFBandMap Map[],
-		       u32 Frequency, u8 *pRFBand)
-{
-	int i = 0;
-
-	while (i < 7 && (Frequency > Map[i].m_RF_max))
-		i += 1;
-	if (i == 7)
-		return false;
-	*pRFBand = i;
-	return true;
-}
-
-static int ThermometerRead(struct tda_state *state, u8 *pTM_Value)
-{
-	int status = 0;
-
-	do {
-		u8 Regs[16];
-		state->m_Regs[TM] |= 0x10;
-		status = UpdateReg(state, TM);
-		if (status < 0)
-			break;
-		status = Read(state, Regs);
-		if (status < 0)
-			break;
-		if (((Regs[TM] & 0x0F) == 0 && (Regs[TM] & 0x20) == 0x20) ||
-		    ((Regs[TM] & 0x0F) == 8 && (Regs[TM] & 0x20) == 0x00)) {
-			state->m_Regs[TM] ^= 0x20;
-			status = UpdateReg(state, TM);
-			if (status < 0)
-				break;
-			msleep(10);
-			status = Read(state, Regs);
-			if (status < 0)
-				break;
-		}
-		*pTM_Value = (Regs[TM] & 0x20)
-				? m_Thermometer_Map_2[Regs[TM] & 0x0F]
-				: m_Thermometer_Map_1[Regs[TM] & 0x0F] ;
-		state->m_Regs[TM] &= ~0x10;        /* Thermometer off */
-		status = UpdateReg(state, TM);
-		if (status < 0)
-			break;
-		state->m_Regs[EP4] &= ~0x03;       /* CAL_mode = 0 ????????? */
-		status = UpdateReg(state, EP4);
-		if (status < 0)
-			break;
-	} while (0);
-
-	return status;
-}
-
-static int StandBy(struct tda_state *state)
-{
-	int status = 0;
-	do {
-		state->m_Regs[EB12] &= ~0x20;  /* PD_AGC1_Det = 0 */
-		status = UpdateReg(state, EB12);
-		if (status < 0)
-			break;
-		state->m_Regs[EB18] &= ~0x83;  /* AGC1_loop_off = 0, AGC1_Gain = 6 dB */
-		status = UpdateReg(state, EB18);
-		if (status < 0)
-			break;
-		state->m_Regs[EB21] |= 0x03; /* AGC2_Gain = -6 dB */
-		state->m_Regs[EP3] = state->m_EP3_Standby;
-		status = UpdateReg(state, EP3);
-		if (status < 0)
-			break;
-		state->m_Regs[EB23] &= ~0x06; /* ForceLP_Fc2_En = 0, LP_Fc[2] = 0 */
-		status = UpdateRegs(state, EB21, EB23);
-		if (status < 0)
-			break;
-	} while (0);
-	return status;
-}
-
-static int CalcMainPLL(struct tda_state *state, u32 freq)
-{
-
-	u8  PostDiv;
-	u8  Div;
-	u64 OscFreq;
-	u32 MainDiv;
-
-	if (!SearchMap3(m_Main_PLL_Map, freq, &PostDiv, &Div))
-		return -EINVAL;
-
-	OscFreq = (u64) freq * (u64) Div;
-	OscFreq *= (u64) 16384;
-	do_div(OscFreq, (u64)16000000);
-	MainDiv = OscFreq;
-
-	state->m_Regs[MPD] = PostDiv & 0x77;
-	state->m_Regs[MD1] = ((MainDiv >> 16) & 0x7F);
-	state->m_Regs[MD2] = ((MainDiv >>  8) & 0xFF);
-	state->m_Regs[MD3] = (MainDiv & 0xFF);
-
-	return UpdateRegs(state, MPD, MD3);
-}
-
-static int CalcCalPLL(struct tda_state *state, u32 freq)
-{
-	u8 PostDiv;
-	u8 Div;
-	u64 OscFreq;
-	u32 CalDiv;
-
-	if (!SearchMap3(m_Cal_PLL_Map, freq, &PostDiv, &Div))
-		return -EINVAL;
-
-	OscFreq = (u64)freq * (u64)Div;
-	/* CalDiv = u32( OscFreq * 16384 / 16000000 ); */
-	OscFreq *= (u64)16384;
-	do_div(OscFreq, (u64)16000000);
-	CalDiv = OscFreq;
-
-	state->m_Regs[CPD] = PostDiv;
-	state->m_Regs[CD1] = ((CalDiv >> 16) & 0xFF);
-	state->m_Regs[CD2] = ((CalDiv >>  8) & 0xFF);
-	state->m_Regs[CD3] = (CalDiv & 0xFF);
-
-	return UpdateRegs(state, CPD, CD3);
-}
-
-static int CalibrateRF(struct tda_state *state,
-		       u8 RFBand, u32 freq, s32 *pCprog)
-{
-	int status = 0;
-	u8 Regs[NUM_REGS];
-	do {
-		u8 BP_Filter = 0;
-		u8 GainTaper = 0;
-		u8 RFC_K = 0;
-		u8 RFC_M = 0;
-
-		state->m_Regs[EP4] &= ~0x03; /* CAL_mode = 0 */
-		status = UpdateReg(state, EP4);
-		if (status < 0)
-			break;
-		state->m_Regs[EB18] |= 0x03;  /* AGC1_Gain = 3 */
-		status = UpdateReg(state, EB18);
-		if (status < 0)
-			break;
-
-		/* Switching off LT (as datasheet says) causes calibration on C1 to fail */
-		/* (Readout of Cprog is allways 255) */
-		if (state->m_Regs[ID] != 0x83)    /* C1: ID == 83, C2: ID == 84 */
-			state->m_Regs[EP3] |= 0x40; /* SM_LT = 1 */
-
-		if (!(SearchMap1(m_BP_Filter_Map, freq, &BP_Filter) &&
-			SearchMap1(m_GainTaper_Map, freq, &GainTaper) &&
-			SearchMap3(m_KM_Map, freq, &RFC_K, &RFC_M)))
-			return -EINVAL;
-
-		state->m_Regs[EP1] = (state->m_Regs[EP1] & ~0x07) | BP_Filter;
-		state->m_Regs[EP2] = (RFBand << 5) | GainTaper;
-
-		state->m_Regs[EB13] = (state->m_Regs[EB13] & ~0x7C) | (RFC_K << 4) | (RFC_M << 2);
-
-		status = UpdateRegs(state, EP1, EP3);
-		if (status < 0)
-			break;
-		status = UpdateReg(state, EB13);
-		if (status < 0)
-			break;
-
-		state->m_Regs[EB4] |= 0x20;    /* LO_ForceSrce = 1 */
-		status = UpdateReg(state, EB4);
-		if (status < 0)
-			break;
-
-		state->m_Regs[EB7] |= 0x20;    /* CAL_ForceSrce = 1 */
-		status = UpdateReg(state, EB7);
-		if (status < 0)
-			break;
-
-		state->m_Regs[EB14] = 0; /* RFC_Cprog = 0 */
-		status = UpdateReg(state, EB14);
-		if (status < 0)
-			break;
-
-		state->m_Regs[EB20] &= ~0x20;  /* ForceLock = 0; */
-		status = UpdateReg(state, EB20);
-		if (status < 0)
-			break;
-
-		state->m_Regs[EP4] |= 0x03;  /* CAL_Mode = 3 */
-		status = UpdateRegs(state, EP4, EP5);
-		if (status < 0)
-			break;
-
-		status = CalcCalPLL(state, freq);
-		if (status < 0)
-			break;
-		status = CalcMainPLL(state, freq + 1000000);
-		if (status < 0)
-			break;
-
-		msleep(5);
-		status = UpdateReg(state, EP2);
-		if (status < 0)
-			break;
-		status = UpdateReg(state, EP1);
-		if (status < 0)
-			break;
-		status = UpdateReg(state, EP2);
-		if (status < 0)
-			break;
-		status = UpdateReg(state, EP1);
-		if (status < 0)
-			break;
-
-		state->m_Regs[EB4] &= ~0x20;    /* LO_ForceSrce = 0 */
-		status = UpdateReg(state, EB4);
-		if (status < 0)
-			break;
-
-		state->m_Regs[EB7] &= ~0x20;    /* CAL_ForceSrce = 0 */
-		status = UpdateReg(state, EB7);
-		if (status < 0)
-			break;
-		msleep(10);
-
-		state->m_Regs[EB20] |= 0x20;  /* ForceLock = 1; */
-		status = UpdateReg(state, EB20);
-		if (status < 0)
-			break;
-		msleep(60);
-
-		state->m_Regs[EP4] &= ~0x03;  /* CAL_Mode = 0 */
-		state->m_Regs[EP3] &= ~0x40; /* SM_LT = 0 */
-		state->m_Regs[EB18] &= ~0x03;  /* AGC1_Gain = 0 */
-		status = UpdateReg(state, EB18);
-		if (status < 0)
-			break;
-		status = UpdateRegs(state, EP3, EP4);
-		if (status < 0)
-			break;
-		status = UpdateReg(state, EP1);
-		if (status < 0)
-			break;
-
-		status = ReadExtented(state, Regs);
-		if (status < 0)
-			break;
-
-		*pCprog = Regs[EB14];
-
-	} while (0);
-	return status;
-}
-
-static int RFTrackingFiltersInit(struct tda_state *state,
-				 u8 RFBand)
-{
-	int status = 0;
-
-	u32   RF1 = m_RF_Band_Map[RFBand].m_RF1_Default;
-	u32   RF2 = m_RF_Band_Map[RFBand].m_RF2_Default;
-	u32   RF3 = m_RF_Band_Map[RFBand].m_RF3_Default;
-	bool    bcal = false;
-
-	s32    Cprog_cal1 = 0;
-	s32    Cprog_table1 = 0;
-	s32    Cprog_cal2 = 0;
-	s32    Cprog_table2 = 0;
-	s32    Cprog_cal3 = 0;
-	s32    Cprog_table3 = 0;
-
-	state->m_RF_A1[RFBand] = 0;
-	state->m_RF_B1[RFBand] = 0;
-	state->m_RF_A2[RFBand] = 0;
-	state->m_RF_B2[RFBand] = 0;
-
-	do {
-		status = PowerScan(state, RFBand, RF1, &RF1, &bcal);
-		if (status < 0)
-			break;
-		if (bcal) {
-			status = CalibrateRF(state, RFBand, RF1, &Cprog_cal1);
-			if (status < 0)
-				break;
-		}
-		SearchMap2(m_RF_Cal_Map, RF1, &Cprog_table1);
-		if (!bcal)
-			Cprog_cal1 = Cprog_table1;
-		state->m_RF_B1[RFBand] = Cprog_cal1 - Cprog_table1;
-		/* state->m_RF_A1[RF_Band] = ???? */
-
-		if (RF2 == 0)
-			break;
-
-		status = PowerScan(state, RFBand, RF2, &RF2, &bcal);
-		if (status < 0)
-			break;
-		if (bcal) {
-			status = CalibrateRF(state, RFBand, RF2, &Cprog_cal2);
-			if (status < 0)
-				break;
-		}
-		SearchMap2(m_RF_Cal_Map, RF2, &Cprog_table2);
-		if (!bcal)
-			Cprog_cal2 = Cprog_table2;
-
-		state->m_RF_A1[RFBand] =
-			(Cprog_cal2 - Cprog_table2 - Cprog_cal1 + Cprog_table1) /
-			((s32)(RF2) - (s32)(RF1));
-
-		if (RF3 == 0)
-			break;
-
-		status = PowerScan(state, RFBand, RF3, &RF3, &bcal);
-		if (status < 0)
-			break;
-		if (bcal) {
-			status = CalibrateRF(state, RFBand, RF3, &Cprog_cal3);
-			if (status < 0)
-				break;
-		}
-		SearchMap2(m_RF_Cal_Map, RF3, &Cprog_table3);
-		if (!bcal)
-			Cprog_cal3 = Cprog_table3;
-		state->m_RF_A2[RFBand] = (Cprog_cal3 - Cprog_table3 - Cprog_cal2 + Cprog_table2) / ((s32)(RF3) - (s32)(RF2));
-		state->m_RF_B2[RFBand] = Cprog_cal2 - Cprog_table2;
-
-	} while (0);
-
-	state->m_RF1[RFBand] = RF1;
-	state->m_RF2[RFBand] = RF2;
-	state->m_RF3[RFBand] = RF3;
-
-#if 0
-	printk(KERN_ERR "tda18271c2dd: %s %d RF1 = %d A1 = %d B1 = %d RF2 = %d A2 = %d B2 = %d RF3 = %d\n", __func__,
-	       RFBand, RF1, state->m_RF_A1[RFBand], state->m_RF_B1[RFBand], RF2,
-	       state->m_RF_A2[RFBand], state->m_RF_B2[RFBand], RF3);
-#endif
-
-	return status;
-}
-
-static int PowerScan(struct tda_state *state,
-		     u8 RFBand, u32 RF_in, u32 *pRF_Out, bool *pbcal)
-{
-	int status = 0;
-	do {
-		u8   Gain_Taper = 0;
-		s32  RFC_Cprog = 0;
-		u8   CID_Target = 0;
-		u8   CountLimit = 0;
-		u32  freq_MainPLL;
-		u8   Regs[NUM_REGS];
-		u8   CID_Gain;
-		s32  Count = 0;
-		int  sign  = 1;
-		bool wait = false;
-
-		if (!(SearchMap2(m_RF_Cal_Map, RF_in, &RFC_Cprog) &&
-		      SearchMap1(m_GainTaper_Map, RF_in, &Gain_Taper) &&
-		      SearchMap3(m_CID_Target_Map, RF_in, &CID_Target, &CountLimit))) {
-
-			printk(KERN_ERR "tda18271c2dd: %s Search map failed\n", __func__);
-			return -EINVAL;
-		}
-
-		state->m_Regs[EP2] = (RFBand << 5) | Gain_Taper;
-		state->m_Regs[EB14] = (RFC_Cprog);
-		status = UpdateReg(state, EP2);
-		if (status < 0)
-			break;
-		status = UpdateReg(state, EB14);
-		if (status < 0)
-			break;
-
-		freq_MainPLL = RF_in + 1000000;
-		status = CalcMainPLL(state, freq_MainPLL);
-		if (status < 0)
-			break;
-		msleep(5);
-		state->m_Regs[EP4] = (state->m_Regs[EP4] & ~0x03) | 1;    /* CAL_mode = 1 */
-		status = UpdateReg(state, EP4);
-		if (status < 0)
-			break;
-		status = UpdateReg(state, EP2);  /* Launch power measurement */
-		if (status < 0)
-			break;
-		status = ReadExtented(state, Regs);
-		if (status < 0)
-			break;
-		CID_Gain = Regs[EB10] & 0x3F;
-		state->m_Regs[ID] = Regs[ID];  /* Chip version, (needed for C1 workarround in CalibrateRF) */
-
-		*pRF_Out = RF_in;
-
-		while (CID_Gain < CID_Target) {
-			freq_MainPLL = RF_in + sign * Count + 1000000;
-			status = CalcMainPLL(state, freq_MainPLL);
-			if (status < 0)
-				break;
-			msleep(wait ? 5 : 1);
-			wait = false;
-			status = UpdateReg(state, EP2);  /* Launch power measurement */
-			if (status < 0)
-				break;
-			status = ReadExtented(state, Regs);
-			if (status < 0)
-				break;
-			CID_Gain = Regs[EB10] & 0x3F;
-			Count += 200000;
-
-			if (Count < CountLimit * 100000)
-				continue;
-			if (sign < 0)
-				break;
-
-			sign = -sign;
-			Count = 200000;
-			wait = true;
-		}
-		status = status;
-		if (status < 0)
-			break;
-		if (CID_Gain >= CID_Target) {
-			*pbcal = true;
-			*pRF_Out = freq_MainPLL - 1000000;
-		} else
-			*pbcal = false;
-	} while (0);
-
-	return status;
-}
-
-static int PowerScanInit(struct tda_state *state)
-{
-	int status = 0;
-	do {
-		state->m_Regs[EP3] = (state->m_Regs[EP3] & ~0x1F) | 0x12;
-		state->m_Regs[EP4] = (state->m_Regs[EP4] & ~0x1F); /* If level = 0, Cal mode = 0 */
-		status = UpdateRegs(state, EP3, EP4);
-		if (status < 0)
-			break;
-		state->m_Regs[EB18] = (state->m_Regs[EB18] & ~0x03); /* AGC 1 Gain = 0 */
-		status = UpdateReg(state, EB18);
-		if (status < 0)
-			break;
-		state->m_Regs[EB21] = (state->m_Regs[EB21] & ~0x03); /* AGC 2 Gain = 0 (Datasheet = 3) */
-		state->m_Regs[EB23] = (state->m_Regs[EB23] | 0x06); /* ForceLP_Fc2_En = 1, LPFc[2] = 1 */
-		status = UpdateRegs(state, EB21, EB23);
-		if (status < 0)
-			break;
-	} while (0);
-	return status;
-}
-
-static int CalcRFFilterCurve(struct tda_state *state)
-{
-	int status = 0;
-	do {
-		msleep(200);      /* Temperature stabilisation */
-		status = PowerScanInit(state);
-		if (status < 0)
-			break;
-		status = RFTrackingFiltersInit(state, 0);
-		if (status < 0)
-			break;
-		status = RFTrackingFiltersInit(state, 1);
-		if (status < 0)
-			break;
-		status = RFTrackingFiltersInit(state, 2);
-		if (status < 0)
-			break;
-		status = RFTrackingFiltersInit(state, 3);
-		if (status < 0)
-			break;
-		status = RFTrackingFiltersInit(state, 4);
-		if (status < 0)
-			break;
-		status = RFTrackingFiltersInit(state, 5);
-		if (status < 0)
-			break;
-		status = RFTrackingFiltersInit(state, 6);
-		if (status < 0)
-			break;
-		status = ThermometerRead(state, &state->m_TMValue_RFCal); /* also switches off Cal mode !!! */
-		if (status < 0)
-			break;
-	} while (0);
-
-	return status;
-}
-
-static int FixedContentsI2CUpdate(struct tda_state *state)
-{
-	static u8 InitRegs[] = {
-		0x08, 0x80, 0xC6,
-		0xDF, 0x16, 0x60, 0x80,
-		0x80, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00,
-		0xFC, 0x01, 0x84, 0x41,
-		0x01, 0x84, 0x40, 0x07,
-		0x00, 0x00, 0x96, 0x3F,
-		0xC1, 0x00, 0x8F, 0x00,
-		0x00, 0x8C, 0x00, 0x20,
-		0xB3, 0x48, 0xB0,
-	};
-	int status = 0;
-	memcpy(&state->m_Regs[TM], InitRegs, EB23 - TM + 1);
-	do {
-		status = UpdateRegs(state, TM, EB23);
-		if (status < 0)
-			break;
-
-		/* AGC1 gain setup */
-		state->m_Regs[EB17] = 0x00;
-		status = UpdateReg(state, EB17);
-		if (status < 0)
-			break;
-		state->m_Regs[EB17] = 0x03;
-		status = UpdateReg(state, EB17);
-		if (status < 0)
-			break;
-		state->m_Regs[EB17] = 0x43;
-		status = UpdateReg(state, EB17);
-		if (status < 0)
-			break;
-		state->m_Regs[EB17] = 0x4C;
-		status = UpdateReg(state, EB17);
-		if (status < 0)
-			break;
-
-		/* IRC Cal Low band */
-		state->m_Regs[EP3] = 0x1F;
-		state->m_Regs[EP4] = 0x66;
-		state->m_Regs[EP5] = 0x81;
-		state->m_Regs[CPD] = 0xCC;
-		state->m_Regs[CD1] = 0x6C;
-		state->m_Regs[CD2] = 0x00;
-		state->m_Regs[CD3] = 0x00;
-		state->m_Regs[MPD] = 0xC5;
-		state->m_Regs[MD1] = 0x77;
-		state->m_Regs[MD2] = 0x08;
-		state->m_Regs[MD3] = 0x00;
-		status = UpdateRegs(state, EP2, MD3); /* diff between sw and datasheet (ep3-md3) */
-		if (status < 0)
-			break;
-
-#if 0
-		state->m_Regs[EB4] = 0x61;          /* missing in sw */
-		status = UpdateReg(state, EB4);
-		if (status < 0)
-			break;
-		msleep(1);
-		state->m_Regs[EB4] = 0x41;
-		status = UpdateReg(state, EB4);
-		if (status < 0)
-			break;
-#endif
-
-		msleep(5);
-		status = UpdateReg(state, EP1);
-		if (status < 0)
-			break;
-		msleep(5);
-
-		state->m_Regs[EP5] = 0x85;
-		state->m_Regs[CPD] = 0xCB;
-		state->m_Regs[CD1] = 0x66;
-		state->m_Regs[CD2] = 0x70;
-		status = UpdateRegs(state, EP3, CD3);
-		if (status < 0)
-			break;
-		msleep(5);
-		status = UpdateReg(state, EP2);
-		if (status < 0)
-			break;
-		msleep(30);
-
-		/* IRC Cal mid band */
-		state->m_Regs[EP5] = 0x82;
-		state->m_Regs[CPD] = 0xA8;
-		state->m_Regs[CD2] = 0x00;
-		state->m_Regs[MPD] = 0xA1; /* Datasheet = 0xA9 */
-		state->m_Regs[MD1] = 0x73;
-		state->m_Regs[MD2] = 0x1A;
-		status = UpdateRegs(state, EP3, MD3);
-		if (status < 0)
-			break;
-
-		msleep(5);
-		status = UpdateReg(state, EP1);
-		if (status < 0)
-			break;
-		msleep(5);
-
-		state->m_Regs[EP5] = 0x86;
-		state->m_Regs[CPD] = 0xA8;
-		state->m_Regs[CD1] = 0x66;
-		state->m_Regs[CD2] = 0xA0;
-		status = UpdateRegs(state, EP3, CD3);
-		if (status < 0)
-			break;
-		msleep(5);
-		status = UpdateReg(state, EP2);
-		if (status < 0)
-			break;
-		msleep(30);
-
-		/* IRC Cal high band */
-		state->m_Regs[EP5] = 0x83;
-		state->m_Regs[CPD] = 0x98;
-		state->m_Regs[CD1] = 0x65;
-		state->m_Regs[CD2] = 0x00;
-		state->m_Regs[MPD] = 0x91;  /* Datasheet = 0x91 */
-		state->m_Regs[MD1] = 0x71;
-		state->m_Regs[MD2] = 0xCD;
-		status = UpdateRegs(state, EP3, MD3);
-		if (status < 0)
-			break;
-		msleep(5);
-		status = UpdateReg(state, EP1);
-		if (status < 0)
-			break;
-		msleep(5);
-		state->m_Regs[EP5] = 0x87;
-		state->m_Regs[CD1] = 0x65;
-		state->m_Regs[CD2] = 0x50;
-		status = UpdateRegs(state, EP3, CD3);
-		if (status < 0)
-			break;
-		msleep(5);
-		status = UpdateReg(state, EP2);
-		if (status < 0)
-			break;
-		msleep(30);
-
-		/* Back to normal */
-		state->m_Regs[EP4] = 0x64;
-		status = UpdateReg(state, EP4);
-		if (status < 0)
-			break;
-		status = UpdateReg(state, EP1);
-		if (status < 0)
-			break;
-
-	} while (0);
-	return status;
-}
-
-static int InitCal(struct tda_state *state)
-{
-	int status = 0;
-
-	do {
-		status = FixedContentsI2CUpdate(state);
-		if (status < 0)
-			break;
-		status = CalcRFFilterCurve(state);
-		if (status < 0)
-			break;
-		status = StandBy(state);
-		if (status < 0)
-			break;
-		/* m_bInitDone = true; */
-	} while (0);
-	return status;
-};
-
-static int RFTrackingFiltersCorrection(struct tda_state *state,
-				       u32 Frequency)
-{
-	int status = 0;
-	s32 Cprog_table;
-	u8 RFBand;
-	u8 dCoverdT;
-
-	if (!SearchMap2(m_RF_Cal_Map, Frequency, &Cprog_table) ||
-	    !SearchMap4(m_RF_Band_Map, Frequency, &RFBand) ||
-	    !SearchMap1(m_RF_Cal_DC_Over_DT_Map, Frequency, &dCoverdT))
-
-		return -EINVAL;
-
-	do {
-		u8 TMValue_Current;
-		u32   RF1 = state->m_RF1[RFBand];
-		u32   RF2 = state->m_RF1[RFBand];
-		u32   RF3 = state->m_RF1[RFBand];
-		s32    RF_A1 = state->m_RF_A1[RFBand];
-		s32    RF_B1 = state->m_RF_B1[RFBand];
-		s32    RF_A2 = state->m_RF_A2[RFBand];
-		s32    RF_B2 = state->m_RF_B2[RFBand];
-		s32 Capprox = 0;
-		int TComp;
-
-		state->m_Regs[EP3] &= ~0xE0;  /* Power up */
-		status = UpdateReg(state, EP3);
-		if (status < 0)
-			break;
-
-		status = ThermometerRead(state, &TMValue_Current);
-		if (status < 0)
-			break;
-
-		if (RF3 == 0 || Frequency < RF2)
-			Capprox = RF_A1 * ((s32)(Frequency) - (s32)(RF1)) + RF_B1 + Cprog_table;
-		else
-			Capprox = RF_A2 * ((s32)(Frequency) - (s32)(RF2)) + RF_B2 + Cprog_table;
-
-		TComp = (int)(dCoverdT) * ((int)(TMValue_Current) - (int)(state->m_TMValue_RFCal))/1000;
-
-		Capprox += TComp;
-
-		if (Capprox < 0)
-			Capprox = 0;
-		else if (Capprox > 255)
-			Capprox = 255;
-
-
-		/* TODO Temperature compensation. There is defenitely a scale factor */
-		/*      missing in the datasheet, so leave it out for now.           */
-		state->m_Regs[EB14] = Capprox;
-
-		status = UpdateReg(state, EB14);
-		if (status < 0)
-			break;
-
-	} while (0);
-	return status;
-}
-
-static int ChannelConfiguration(struct tda_state *state,
-				u32 Frequency, int Standard)
-{
-
-	s32 IntermediateFrequency = m_StandardTable[Standard].m_IFFrequency;
-	int status = 0;
-
-	u8 BP_Filter = 0;
-	u8 RF_Band = 0;
-	u8 GainTaper = 0;
-	u8 IR_Meas = 0;
-
-	state->IF = IntermediateFrequency;
-	/* printk("tda18271c2dd: %s Freq = %d Standard = %d IF = %d\n", __func__, Frequency, Standard, IntermediateFrequency); */
-	/* get values from tables */
-
-	if (!(SearchMap1(m_BP_Filter_Map, Frequency, &BP_Filter) &&
-	       SearchMap1(m_GainTaper_Map, Frequency, &GainTaper) &&
-	       SearchMap1(m_IR_Meas_Map, Frequency, &IR_Meas) &&
-	       SearchMap4(m_RF_Band_Map, Frequency, &RF_Band))) {
-
-		printk(KERN_ERR "tda18271c2dd: %s SearchMap failed\n", __func__);
-		return -EINVAL;
-	}
-
-	do {
-		state->m_Regs[EP3] = (state->m_Regs[EP3] & ~0x1F) | m_StandardTable[Standard].m_EP3_4_0;
-		state->m_Regs[EP3] &= ~0x04;   /* switch RFAGC to high speed mode */
-
-		/* m_EP4 default for XToutOn, CAL_Mode (0) */
-		state->m_Regs[EP4] = state->m_EP4 | ((Standard > HF_AnalogMax) ? state->m_IFLevelDigital : state->m_IFLevelAnalog);
-		/* state->m_Regs[EP4] = state->m_EP4 | state->m_IFLevelDigital; */
-		if (Standard <= HF_AnalogMax)
-			state->m_Regs[EP4] = state->m_EP4 | state->m_IFLevelAnalog;
-		else if (Standard <= HF_ATSC)
-			state->m_Regs[EP4] = state->m_EP4 | state->m_IFLevelDVBT;
-		else if (Standard <= HF_DVBC)
-			state->m_Regs[EP4] = state->m_EP4 | state->m_IFLevelDVBC;
-		else
-			state->m_Regs[EP4] = state->m_EP4 | state->m_IFLevelDigital;
-
-		if ((Standard == HF_FM_Radio) && state->m_bFMInput)
-			state->m_Regs[EP4] |= 80;
-
-		state->m_Regs[MPD] &= ~0x80;
-		if (Standard > HF_AnalogMax)
-			state->m_Regs[MPD] |= 0x80; /* Add IF_notch for digital */
-
-		state->m_Regs[EB22] = m_StandardTable[Standard].m_EB22;
-
-		/* Note: This is missing from flowchart in TDA18271 specification ( 1.5 MHz cutoff for FM ) */
-		if (Standard == HF_FM_Radio)
-			state->m_Regs[EB23] |=  0x06; /* ForceLP_Fc2_En = 1, LPFc[2] = 1 */
-		else
-			state->m_Regs[EB23] &= ~0x06; /* ForceLP_Fc2_En = 0, LPFc[2] = 0 */
-
-		status = UpdateRegs(state, EB22, EB23);
-		if (status < 0)
-			break;
-
-		state->m_Regs[EP1] = (state->m_Regs[EP1] & ~0x07) | 0x40 | BP_Filter;   /* Dis_Power_level = 1, Filter */
-		state->m_Regs[EP5] = (state->m_Regs[EP5] & ~0x07) | IR_Meas;
-		state->m_Regs[EP2] = (RF_Band << 5) | GainTaper;
-
-		state->m_Regs[EB1] = (state->m_Regs[EB1] & ~0x07) |
-			(state->m_bMaster ? 0x04 : 0x00); /* CALVCO_FortLOn = MS */
-		/* AGC1_always_master = 0 */
-		/* AGC_firstn = 0 */
-		status = UpdateReg(state, EB1);
-		if (status < 0)
-			break;
-
-		if (state->m_bMaster) {
-			status = CalcMainPLL(state, Frequency + IntermediateFrequency);
-			if (status < 0)
-				break;
-			status = UpdateRegs(state, TM, EP5);
-			if (status < 0)
-				break;
-			state->m_Regs[EB4] |= 0x20;    /* LO_forceSrce = 1 */
-			status = UpdateReg(state, EB4);
-			if (status < 0)
-				break;
-			msleep(1);
-			state->m_Regs[EB4] &= ~0x20;   /* LO_forceSrce = 0 */
-			status = UpdateReg(state, EB4);
-			if (status < 0)
-				break;
-		} else {
-			u8 PostDiv = 0;
-			u8 Div;
-			status = CalcCalPLL(state, Frequency + IntermediateFrequency);
-			if (status < 0)
-				break;
-
-			SearchMap3(m_Cal_PLL_Map, Frequency + IntermediateFrequency, &PostDiv, &Div);
-			state->m_Regs[MPD] = (state->m_Regs[MPD] & ~0x7F) | (PostDiv & 0x77);
-			status = UpdateReg(state, MPD);
-			if (status < 0)
-				break;
-			status = UpdateRegs(state, TM, EP5);
-			if (status < 0)
-				break;
-
-			state->m_Regs[EB7] |= 0x20;    /* CAL_forceSrce = 1 */
-			status = UpdateReg(state, EB7);
-			if (status < 0)
-				break;
-			msleep(1);
-			state->m_Regs[EB7] &= ~0x20;   /* CAL_forceSrce = 0 */
-			status = UpdateReg(state, EB7);
-			if (status < 0)
-				break;
-		}
-		msleep(20);
-		if (Standard != HF_FM_Radio)
-			state->m_Regs[EP3] |= 0x04;    /* RFAGC to normal mode */
-		status = UpdateReg(state, EP3);
-		if (status < 0)
-			break;
-
-	} while (0);
-	return status;
-}
-
-static int sleep(struct dvb_frontend *fe)
-{
-	struct tda_state *state = fe->tuner_priv;
-
-	StandBy(state);
-	return 0;
-}
-
-static int init(struct dvb_frontend *fe)
-{
-	return 0;
-}
-
-static int release(struct dvb_frontend *fe)
-{
-	kfree(fe->tuner_priv);
-	fe->tuner_priv = NULL;
-	return 0;
-}
-
-
-static int set_params(struct dvb_frontend *fe)
-{
-	struct tda_state *state = fe->tuner_priv;
-	int status = 0;
-	int Standard;
-	u32 bw = fe->dtv_property_cache.bandwidth_hz;
-	u32 delsys  = fe->dtv_property_cache.delivery_system;
-
-	state->m_Frequency = fe->dtv_property_cache.frequency;
-
-	switch (delsys) {
-	case  SYS_DVBT:
-	case  SYS_DVBT2:
-		switch (bw) {
-		case 6000000:
-			Standard = HF_DVBT_6MHZ;
-			break;
-		case 7000000:
-			Standard = HF_DVBT_7MHZ;
-			break;
-		case 8000000:
-			Standard = HF_DVBT_8MHZ;
-			break;
-		default:
-			return -EINVAL;
-		}
-	case SYS_DVBC_ANNEX_A:
-	case SYS_DVBC_ANNEX_C:
-		if (bw <= 6000000)
-			Standard = HF_DVBC_6MHZ;
-		else if (bw <= 7000000)
-			Standard = HF_DVBC_7MHZ;
-		else
-			Standard = HF_DVBC_8MHZ;
-		break;
-	default:
-		return -EINVAL;
-	}
-	do {
-		status = RFTrackingFiltersCorrection(state, state->m_Frequency);
-		if (status < 0)
-			break;
-		status = ChannelConfiguration(state, state->m_Frequency,
-					      Standard);
-		if (status < 0)
-			break;
-
-		msleep(state->m_SettlingTime);  /* Allow AGC's to settle down */
-	} while (0);
-	return status;
-}
-
-#if 0
-static int GetSignalStrength(s32 *pSignalStrength, u32 RFAgc, u32 IFAgc)
-{
-	if (IFAgc < 500) {
-		/* Scale this from 0 to 50000 */
-		*pSignalStrength = IFAgc * 100;
-	} else {
-		/* Scale range 500-1500 to 50000-80000 */
-		*pSignalStrength = 50000 + (IFAgc - 500) * 30;
-	}
-
-	return 0;
-}
-#endif
-
-static int get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
-{
-	struct tda_state *state = fe->tuner_priv;
-
-	*frequency = state->IF;
-	return 0;
-}
-
-static int get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
-{
-	/* struct tda_state *state = fe->tuner_priv; */
-	/* *bandwidth = priv->bandwidth; */
-	return 0;
-}
-
-
-static struct dvb_tuner_ops tuner_ops = {
-	.info = {
-		.name = "NXP TDA18271C2D",
-		.frequency_min  =  47125000,
-		.frequency_max  = 865000000,
-		.frequency_step =     62500
-	},
-	.init              = init,
-	.sleep             = sleep,
-	.set_params        = set_params,
-	.release           = release,
-	.get_if_frequency  = get_if_frequency,
-	.get_bandwidth     = get_bandwidth,
-};
-
-struct dvb_frontend *tda18271c2dd_attach(struct dvb_frontend *fe,
-					 struct i2c_adapter *i2c, u8 adr)
-{
-	struct tda_state *state;
-
-	state = kzalloc(sizeof(struct tda_state), GFP_KERNEL);
-	if (!state)
-		return NULL;
-
-	fe->tuner_priv = state;
-	state->adr = adr;
-	state->i2c = i2c;
-	memcpy(&fe->ops.tuner_ops, &tuner_ops, sizeof(struct dvb_tuner_ops));
-	reset(state);
-	InitCal(state);
-
-	return fe;
-}
-EXPORT_SYMBOL_GPL(tda18271c2dd_attach);
-
-MODULE_DESCRIPTION("TDA18271C2 driver");
-MODULE_AUTHOR("DD");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/tda18271c2dd.h b/drivers/media/dvb/frontends/tda18271c2dd.h
deleted file mode 100644
index 1389c74..0000000
--- a/drivers/media/dvb/frontends/tda18271c2dd.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef _TDA18271C2DD_H_
-#define _TDA18271C2DD_H_
-#if defined(CONFIG_DVB_TDA18271C2DD) || (defined(CONFIG_DVB_TDA18271C2DD_MODULE) \
-        && defined(MODULE))
-struct dvb_frontend *tda18271c2dd_attach(struct dvb_frontend *fe,
-					 struct i2c_adapter *i2c, u8 adr);
-#else
-static inline struct dvb_frontend *tda18271c2dd_attach(struct dvb_frontend *fe,
-					 struct i2c_adapter *i2c, u8 adr)
-{
-        printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-        return NULL;
-}
-#endif
-
-#endif
diff --git a/drivers/media/dvb/frontends/tda18271c2dd_maps.h b/drivers/media/dvb/frontends/tda18271c2dd_maps.h
deleted file mode 100644
index b87661b..0000000
--- a/drivers/media/dvb/frontends/tda18271c2dd_maps.h
+++ /dev/null
@@ -1,814 +0,0 @@
-enum HF_S {
-	HF_None = 0, HF_B, HF_DK, HF_G, HF_I, HF_L, HF_L1, HF_MN, HF_FM_Radio,
-	HF_AnalogMax, HF_DVBT_6MHZ, HF_DVBT_7MHZ, HF_DVBT_8MHZ,
-	HF_DVBT, HF_ATSC,  HF_DVBC_6MHZ,  HF_DVBC_7MHZ,
-	HF_DVBC_8MHZ, HF_DVBC
-};
-
-struct SStandardParam m_StandardTable[] = {
-	{       0,        0, 0x00, 0x00 },    /* HF_None */
-	{ 6000000,  7000000, 0x1D, 0x2C },    /* HF_B, */
-	{ 6900000,  8000000, 0x1E, 0x2C },    /* HF_DK, */
-	{ 7100000,  8000000, 0x1E, 0x2C },    /* HF_G, */
-	{ 7250000,  8000000, 0x1E, 0x2C },    /* HF_I, */
-	{ 6900000,  8000000, 0x1E, 0x2C },    /* HF_L, */
-	{ 1250000,  8000000, 0x1E, 0x2C },    /* HF_L1, */
-	{ 5400000,  6000000, 0x1C, 0x2C },    /* HF_MN, */
-	{ 1250000,   500000, 0x18, 0x2C },    /* HF_FM_Radio, */
-	{       0,        0, 0x00, 0x00 },    /* HF_AnalogMax (Unused) */
-	{ 3300000,  6000000, 0x1C, 0x58 },    /* HF_DVBT_6MHZ */
-	{ 3500000,  7000000, 0x1C, 0x37 },    /* HF_DVBT_7MHZ */
-	{ 4000000,  8000000, 0x1D, 0x37 },    /* HF_DVBT_8MHZ */
-	{       0,        0, 0x00, 0x00 },    /* HF_DVBT (Unused) */
-	{ 5000000,  6000000, 0x1C, 0x37 },    /* HF_ATSC  (center = 3.25 MHz) */
-	{ 4000000,  6000000, 0x1D, 0x58 },    /* HF_DVBC_6MHZ (Chicago) */
-	{ 4500000,  7000000, 0x1E, 0x37 },    /* HF_DVBC_7MHZ (not documented by NXP) */
-	{ 5000000,  8000000, 0x1F, 0x37 },    /* HF_DVBC_8MHZ */
-	{       0,        0, 0x00, 0x00 },    /* HF_DVBC (Unused) */
-};
-
-struct SMap  m_BP_Filter_Map[] = {
-	{   62000000,  0x00 },
-	{   84000000,  0x01 },
-	{  100000000,  0x02 },
-	{  140000000,  0x03 },
-	{  170000000,  0x04 },
-	{  180000000,  0x05 },
-	{  865000000,  0x06 },
-	{          0,  0x00 },    /* Table End */
-};
-
-static struct SMapI m_RF_Cal_Map[] = {
-	{   41000000,  0x0F },
-	{   43000000,  0x1C },
-	{   45000000,  0x2F },
-	{   46000000,  0x39 },
-	{   47000000,  0x40 },
-	{   47900000,  0x50 },
-	{   49100000,  0x16 },
-	{   50000000,  0x18 },
-	{   51000000,  0x20 },
-	{   53000000,  0x28 },
-	{   55000000,  0x2B },
-	{   56000000,  0x32 },
-	{   57000000,  0x35 },
-	{   58000000,  0x3E },
-	{   59000000,  0x43 },
-	{   60000000,  0x4E },
-	{   61100000,  0x55 },
-	{   63000000,  0x0F },
-	{   64000000,  0x11 },
-	{   65000000,  0x12 },
-	{   66000000,  0x15 },
-	{   67000000,  0x16 },
-	{   68000000,  0x17 },
-	{   70000000,  0x19 },
-	{   71000000,  0x1C },
-	{   72000000,  0x1D },
-	{   73000000,  0x1F },
-	{   74000000,  0x20 },
-	{   75000000,  0x21 },
-	{   76000000,  0x24 },
-	{   77000000,  0x25 },
-	{   78000000,  0x27 },
-	{   80000000,  0x28 },
-	{   81000000,  0x29 },
-	{   82000000,  0x2D },
-	{   83000000,  0x2E },
-	{   84000000,  0x2F },
-	{   85000000,  0x31 },
-	{   86000000,  0x33 },
-	{   87000000,  0x34 },
-	{   88000000,  0x35 },
-	{   89000000,  0x37 },
-	{   90000000,  0x38 },
-	{   91000000,  0x39 },
-	{   93000000,  0x3C },
-	{   94000000,  0x3E },
-	{   95000000,  0x3F },
-	{   96000000,  0x40 },
-	{   97000000,  0x42 },
-	{   99000000,  0x45 },
-	{  100000000,  0x46 },
-	{  102000000,  0x48 },
-	{  103000000,  0x4A },
-	{  105000000,  0x4D },
-	{  106000000,  0x4E },
-	{  107000000,  0x50 },
-	{  108000000,  0x51 },
-	{  110000000,  0x54 },
-	{  111000000,  0x56 },
-	{  112000000,  0x57 },
-	{  113000000,  0x58 },
-	{  114000000,  0x59 },
-	{  115000000,  0x5C },
-	{  116000000,  0x5D },
-	{  117000000,  0x5F },
-	{  119000000,  0x60 },
-	{  120000000,  0x64 },
-	{  121000000,  0x65 },
-	{  122000000,  0x66 },
-	{  123000000,  0x68 },
-	{  124000000,  0x69 },
-	{  125000000,  0x6C },
-	{  126000000,  0x6D },
-	{  127000000,  0x6E },
-	{  128000000,  0x70 },
-	{  129000000,  0x71 },
-	{  130000000,  0x75 },
-	{  131000000,  0x77 },
-	{  132000000,  0x78 },
-	{  133000000,  0x7B },
-	{  134000000,  0x7E },
-	{  135000000,  0x81 },
-	{  136000000,  0x82 },
-	{  137000000,  0x87 },
-	{  138000000,  0x88 },
-	{  139000000,  0x8D },
-	{  140000000,  0x8E },
-	{  141000000,  0x91 },
-	{  142000000,  0x95 },
-	{  143000000,  0x9A },
-	{  144000000,  0x9D },
-	{  145000000,  0xA1 },
-	{  146000000,  0xA2 },
-	{  147000000,  0xA4 },
-	{  148000000,  0xA9 },
-	{  149000000,  0xAE },
-	{  150000000,  0xB0 },
-	{  151000000,  0xB1 },
-	{  152000000,  0xB7 },
-	{  152600000,  0xBD },
-	{  154000000,  0x20 },
-	{  155000000,  0x22 },
-	{  156000000,  0x24 },
-	{  157000000,  0x25 },
-	{  158000000,  0x27 },
-	{  159000000,  0x29 },
-	{  160000000,  0x2C },
-	{  161000000,  0x2D },
-	{  163000000,  0x2E },
-	{  164000000,  0x2F },
-	{  164700000,  0x30 },
-	{  166000000,  0x11 },
-	{  167000000,  0x12 },
-	{  168000000,  0x13 },
-	{  169000000,  0x14 },
-	{  170000000,  0x15 },
-	{  172000000,  0x16 },
-	{  173000000,  0x17 },
-	{  174000000,  0x18 },
-	{  175000000,  0x1A },
-	{  176000000,  0x1B },
-	{  178000000,  0x1D },
-	{  179000000,  0x1E },
-	{  180000000,  0x1F },
-	{  181000000,  0x20 },
-	{  182000000,  0x21 },
-	{  183000000,  0x22 },
-	{  184000000,  0x24 },
-	{  185000000,  0x25 },
-	{  186000000,  0x26 },
-	{  187000000,  0x27 },
-	{  188000000,  0x29 },
-	{  189000000,  0x2A },
-	{  190000000,  0x2C },
-	{  191000000,  0x2D },
-	{  192000000,  0x2E },
-	{  193000000,  0x2F },
-	{  194000000,  0x30 },
-	{  195000000,  0x33 },
-	{  196000000,  0x35 },
-	{  198000000,  0x36 },
-	{  200000000,  0x38 },
-	{  201000000,  0x3C },
-	{  202000000,  0x3D },
-	{  203500000,  0x3E },
-	{  206000000,  0x0E },
-	{  208000000,  0x0F },
-	{  212000000,  0x10 },
-	{  216000000,  0x11 },
-	{  217000000,  0x12 },
-	{  218000000,  0x13 },
-	{  220000000,  0x14 },
-	{  222000000,  0x15 },
-	{  225000000,  0x16 },
-	{  228000000,  0x17 },
-	{  231000000,  0x18 },
-	{  234000000,  0x19 },
-	{  235000000,  0x1A },
-	{  236000000,  0x1B },
-	{  237000000,  0x1C },
-	{  240000000,  0x1D },
-	{  242000000,  0x1E },
-	{  244000000,  0x1F },
-	{  247000000,  0x20 },
-	{  249000000,  0x21 },
-	{  252000000,  0x22 },
-	{  253000000,  0x23 },
-	{  254000000,  0x24 },
-	{  256000000,  0x25 },
-	{  259000000,  0x26 },
-	{  262000000,  0x27 },
-	{  264000000,  0x28 },
-	{  267000000,  0x29 },
-	{  269000000,  0x2A },
-	{  271000000,  0x2B },
-	{  273000000,  0x2C },
-	{  275000000,  0x2D },
-	{  277000000,  0x2E },
-	{  279000000,  0x2F },
-	{  282000000,  0x30 },
-	{  284000000,  0x31 },
-	{  286000000,  0x32 },
-	{  287000000,  0x33 },
-	{  290000000,  0x34 },
-	{  293000000,  0x35 },
-	{  295000000,  0x36 },
-	{  297000000,  0x37 },
-	{  300000000,  0x38 },
-	{  303000000,  0x39 },
-	{  305000000,  0x3A },
-	{  306000000,  0x3B },
-	{  307000000,  0x3C },
-	{  310000000,  0x3D },
-	{  312000000,  0x3E },
-	{  315000000,  0x3F },
-	{  318000000,  0x40 },
-	{  320000000,  0x41 },
-	{  323000000,  0x42 },
-	{  324000000,  0x43 },
-	{  325000000,  0x44 },
-	{  327000000,  0x45 },
-	{  331000000,  0x46 },
-	{  334000000,  0x47 },
-	{  337000000,  0x48 },
-	{  339000000,  0x49 },
-	{  340000000,  0x4A },
-	{  341000000,  0x4B },
-	{  343000000,  0x4C },
-	{  345000000,  0x4D },
-	{  349000000,  0x4E },
-	{  352000000,  0x4F },
-	{  353000000,  0x50 },
-	{  355000000,  0x51 },
-	{  357000000,  0x52 },
-	{  359000000,  0x53 },
-	{  361000000,  0x54 },
-	{  362000000,  0x55 },
-	{  364000000,  0x56 },
-	{  368000000,  0x57 },
-	{  370000000,  0x58 },
-	{  372000000,  0x59 },
-	{  375000000,  0x5A },
-	{  376000000,  0x5B },
-	{  377000000,  0x5C },
-	{  379000000,  0x5D },
-	{  382000000,  0x5E },
-	{  384000000,  0x5F },
-	{  385000000,  0x60 },
-	{  386000000,  0x61 },
-	{  388000000,  0x62 },
-	{  390000000,  0x63 },
-	{  393000000,  0x64 },
-	{  394000000,  0x65 },
-	{  396000000,  0x66 },
-	{  397000000,  0x67 },
-	{  398000000,  0x68 },
-	{  400000000,  0x69 },
-	{  402000000,  0x6A },
-	{  403000000,  0x6B },
-	{  407000000,  0x6C },
-	{  408000000,  0x6D },
-	{  409000000,  0x6E },
-	{  410000000,  0x6F },
-	{  411000000,  0x70 },
-	{  412000000,  0x71 },
-	{  413000000,  0x72 },
-	{  414000000,  0x73 },
-	{  417000000,  0x74 },
-	{  418000000,  0x75 },
-	{  420000000,  0x76 },
-	{  422000000,  0x77 },
-	{  423000000,  0x78 },
-	{  424000000,  0x79 },
-	{  427000000,  0x7A },
-	{  428000000,  0x7B },
-	{  429000000,  0x7D },
-	{  432000000,  0x7F },
-	{  434000000,  0x80 },
-	{  435000000,  0x81 },
-	{  436000000,  0x83 },
-	{  437000000,  0x84 },
-	{  438000000,  0x85 },
-	{  439000000,  0x86 },
-	{  440000000,  0x87 },
-	{  441000000,  0x88 },
-	{  442000000,  0x89 },
-	{  445000000,  0x8A },
-	{  446000000,  0x8B },
-	{  447000000,  0x8C },
-	{  448000000,  0x8E },
-	{  449000000,  0x8F },
-	{  450000000,  0x90 },
-	{  452000000,  0x91 },
-	{  453000000,  0x93 },
-	{  454000000,  0x94 },
-	{  456000000,  0x96 },
-	{  457800000,  0x98 },
-	{  461000000,  0x11 },
-	{  468000000,  0x12 },
-	{  472000000,  0x13 },
-	{  473000000,  0x14 },
-	{  474000000,  0x15 },
-	{  481000000,  0x16 },
-	{  486000000,  0x17 },
-	{  491000000,  0x18 },
-	{  498000000,  0x19 },
-	{  499000000,  0x1A },
-	{  501000000,  0x1B },
-	{  506000000,  0x1C },
-	{  511000000,  0x1D },
-	{  516000000,  0x1E },
-	{  520000000,  0x1F },
-	{  521000000,  0x20 },
-	{  525000000,  0x21 },
-	{  529000000,  0x22 },
-	{  533000000,  0x23 },
-	{  539000000,  0x24 },
-	{  541000000,  0x25 },
-	{  547000000,  0x26 },
-	{  549000000,  0x27 },
-	{  551000000,  0x28 },
-	{  556000000,  0x29 },
-	{  561000000,  0x2A },
-	{  563000000,  0x2B },
-	{  565000000,  0x2C },
-	{  569000000,  0x2D },
-	{  571000000,  0x2E },
-	{  577000000,  0x2F },
-	{  580000000,  0x30 },
-	{  582000000,  0x31 },
-	{  584000000,  0x32 },
-	{  588000000,  0x33 },
-	{  591000000,  0x34 },
-	{  596000000,  0x35 },
-	{  598000000,  0x36 },
-	{  603000000,  0x37 },
-	{  604000000,  0x38 },
-	{  606000000,  0x39 },
-	{  612000000,  0x3A },
-	{  615000000,  0x3B },
-	{  617000000,  0x3C },
-	{  621000000,  0x3D },
-	{  622000000,  0x3E },
-	{  625000000,  0x3F },
-	{  632000000,  0x40 },
-	{  633000000,  0x41 },
-	{  634000000,  0x42 },
-	{  642000000,  0x43 },
-	{  643000000,  0x44 },
-	{  647000000,  0x45 },
-	{  650000000,  0x46 },
-	{  652000000,  0x47 },
-	{  657000000,  0x48 },
-	{  661000000,  0x49 },
-	{  662000000,  0x4A },
-	{  665000000,  0x4B },
-	{  667000000,  0x4C },
-	{  670000000,  0x4D },
-	{  673000000,  0x4E },
-	{  676000000,  0x4F },
-	{  677000000,  0x50 },
-	{  681000000,  0x51 },
-	{  683000000,  0x52 },
-	{  686000000,  0x53 },
-	{  688000000,  0x54 },
-	{  689000000,  0x55 },
-	{  691000000,  0x56 },
-	{  695000000,  0x57 },
-	{  698000000,  0x58 },
-	{  703000000,  0x59 },
-	{  704000000,  0x5A },
-	{  705000000,  0x5B },
-	{  707000000,  0x5C },
-	{  710000000,  0x5D },
-	{  712000000,  0x5E },
-	{  717000000,  0x5F },
-	{  718000000,  0x60 },
-	{  721000000,  0x61 },
-	{  722000000,  0x62 },
-	{  723000000,  0x63 },
-	{  725000000,  0x64 },
-	{  727000000,  0x65 },
-	{  730000000,  0x66 },
-	{  732000000,  0x67 },
-	{  735000000,  0x68 },
-	{  740000000,  0x69 },
-	{  741000000,  0x6A },
-	{  742000000,  0x6B },
-	{  743000000,  0x6C },
-	{  745000000,  0x6D },
-	{  747000000,  0x6E },
-	{  748000000,  0x6F },
-	{  750000000,  0x70 },
-	{  752000000,  0x71 },
-	{  754000000,  0x72 },
-	{  757000000,  0x73 },
-	{  758000000,  0x74 },
-	{  760000000,  0x75 },
-	{  763000000,  0x76 },
-	{  764000000,  0x77 },
-	{  766000000,  0x78 },
-	{  767000000,  0x79 },
-	{  768000000,  0x7A },
-	{  773000000,  0x7B },
-	{  774000000,  0x7C },
-	{  776000000,  0x7D },
-	{  777000000,  0x7E },
-	{  778000000,  0x7F },
-	{  779000000,  0x80 },
-	{  781000000,  0x81 },
-	{  783000000,  0x82 },
-	{  784000000,  0x83 },
-	{  785000000,  0x84 },
-	{  786000000,  0x85 },
-	{  793000000,  0x86 },
-	{  794000000,  0x87 },
-	{  795000000,  0x88 },
-	{  797000000,  0x89 },
-	{  799000000,  0x8A },
-	{  801000000,  0x8B },
-	{  802000000,  0x8C },
-	{  803000000,  0x8D },
-	{  804000000,  0x8E },
-	{  810000000,  0x90 },
-	{  811000000,  0x91 },
-	{  812000000,  0x92 },
-	{  814000000,  0x93 },
-	{  816000000,  0x94 },
-	{  817000000,  0x96 },
-	{  818000000,  0x97 },
-	{  820000000,  0x98 },
-	{  821000000,  0x99 },
-	{  822000000,  0x9A },
-	{  828000000,  0x9B },
-	{  829000000,  0x9D },
-	{  830000000,  0x9F },
-	{  831000000,  0xA0 },
-	{  833000000,  0xA1 },
-	{  835000000,  0xA2 },
-	{  836000000,  0xA3 },
-	{  837000000,  0xA4 },
-	{  838000000,  0xA6 },
-	{  840000000,  0xA8 },
-	{  842000000,  0xA9 },
-	{  845000000,  0xAA },
-	{  846000000,  0xAB },
-	{  847000000,  0xAD },
-	{  848000000,  0xAE },
-	{  852000000,  0xAF },
-	{  853000000,  0xB0 },
-	{  858000000,  0xB1 },
-	{  860000000,  0xB2 },
-	{  861000000,  0xB3 },
-	{  862000000,  0xB4 },
-	{  863000000,  0xB6 },
-	{  864000000,  0xB8 },
-	{  865000000,  0xB9 },
-	{          0,  0x00 },    /* Table End */
-};
-
-
-static struct SMap2  m_KM_Map[] = {
-	{   47900000,  3, 2 },
-	{   61100000,  3, 1 },
-	{  350000000,  3, 0 },
-	{  720000000,  2, 1 },
-	{  865000000,  3, 3 },
-	{          0,  0x00 },    /* Table End */
-};
-
-static struct SMap2 m_Main_PLL_Map[] = {
-	{  33125000, 0x57, 0xF0 },
-	{  35500000, 0x56, 0xE0 },
-	{  38188000, 0x55, 0xD0 },
-	{  41375000, 0x54, 0xC0 },
-	{  45125000, 0x53, 0xB0 },
-	{  49688000, 0x52, 0xA0 },
-	{  55188000, 0x51, 0x90 },
-	{  62125000, 0x50, 0x80 },
-	{  66250000, 0x47, 0x78 },
-	{  71000000, 0x46, 0x70 },
-	{  76375000, 0x45, 0x68 },
-	{  82750000, 0x44, 0x60 },
-	{  90250000, 0x43, 0x58 },
-	{  99375000, 0x42, 0x50 },
-	{ 110375000, 0x41, 0x48 },
-	{ 124250000, 0x40, 0x40 },
-	{ 132500000, 0x37, 0x3C },
-	{ 142000000, 0x36, 0x38 },
-	{ 152750000, 0x35, 0x34 },
-	{ 165500000, 0x34, 0x30 },
-	{ 180500000, 0x33, 0x2C },
-	{ 198750000, 0x32, 0x28 },
-	{ 220750000, 0x31, 0x24 },
-	{ 248500000, 0x30, 0x20 },
-	{ 265000000, 0x27, 0x1E },
-	{ 284000000, 0x26, 0x1C },
-	{ 305500000, 0x25, 0x1A },
-	{ 331000000, 0x24, 0x18 },
-	{ 361000000, 0x23, 0x16 },
-	{ 397500000, 0x22, 0x14 },
-	{ 441500000, 0x21, 0x12 },
-	{ 497000000, 0x20, 0x10 },
-	{ 530000000, 0x17, 0x0F },
-	{ 568000000, 0x16, 0x0E },
-	{ 611000000, 0x15, 0x0D },
-	{ 662000000, 0x14, 0x0C },
-	{ 722000000, 0x13, 0x0B },
-	{ 795000000, 0x12, 0x0A },
-	{ 883000000, 0x11, 0x09 },
-	{ 994000000, 0x10, 0x08 },
-	{         0, 0x00, 0x00 },    /* Table End */
-};
-
-static struct SMap2 m_Cal_PLL_Map[] = {
-	{  33813000, 0xDD, 0xD0 },
-	{  36625000, 0xDC, 0xC0 },
-	{  39938000, 0xDB, 0xB0 },
-	{  43938000, 0xDA, 0xA0 },
-	{  48813000, 0xD9, 0x90 },
-	{  54938000, 0xD8, 0x80 },
-	{  62813000, 0xD3, 0x70 },
-	{  67625000, 0xCD, 0x68 },
-	{  73250000, 0xCC, 0x60 },
-	{  79875000, 0xCB, 0x58 },
-	{  87875000, 0xCA, 0x50 },
-	{  97625000, 0xC9, 0x48 },
-	{ 109875000, 0xC8, 0x40 },
-	{ 125625000, 0xC3, 0x38 },
-	{ 135250000, 0xBD, 0x34 },
-	{ 146500000, 0xBC, 0x30 },
-	{ 159750000, 0xBB, 0x2C },
-	{ 175750000, 0xBA, 0x28 },
-	{ 195250000, 0xB9, 0x24 },
-	{ 219750000, 0xB8, 0x20 },
-	{ 251250000, 0xB3, 0x1C },
-	{ 270500000, 0xAD, 0x1A },
-	{ 293000000, 0xAC, 0x18 },
-	{ 319500000, 0xAB, 0x16 },
-	{ 351500000, 0xAA, 0x14 },
-	{ 390500000, 0xA9, 0x12 },
-	{ 439500000, 0xA8, 0x10 },
-	{ 502500000, 0xA3, 0x0E },
-	{ 541000000, 0x9D, 0x0D },
-	{ 586000000, 0x9C, 0x0C },
-	{ 639000000, 0x9B, 0x0B },
-	{ 703000000, 0x9A, 0x0A },
-	{ 781000000, 0x99, 0x09 },
-	{ 879000000, 0x98, 0x08 },
-	{         0, 0x00, 0x00 },    /* Table End */
-};
-
-static struct SMap  m_GainTaper_Map[] = {
-	{  45400000, 0x1F },
-	{  45800000, 0x1E },
-	{  46200000, 0x1D },
-	{  46700000, 0x1C },
-	{  47100000, 0x1B },
-	{  47500000, 0x1A },
-	{  47900000, 0x19 },
-	{  49600000, 0x17 },
-	{  51200000, 0x16 },
-	{  52900000, 0x15 },
-	{  54500000, 0x14 },
-	{  56200000, 0x13 },
-	{  57800000, 0x12 },
-	{  59500000, 0x11 },
-	{  61100000, 0x10 },
-	{  67600000, 0x0D },
-	{  74200000, 0x0C },
-	{  80700000, 0x0B },
-	{  87200000, 0x0A },
-	{  93800000, 0x09 },
-	{ 100300000, 0x08 },
-	{ 106900000, 0x07 },
-	{ 113400000, 0x06 },
-	{ 119900000, 0x05 },
-	{ 126500000, 0x04 },
-	{ 133000000, 0x03 },
-	{ 139500000, 0x02 },
-	{ 146100000, 0x01 },
-	{ 152600000, 0x00 },
-	{ 154300000, 0x1F },
-	{ 156100000, 0x1E },
-	{ 157800000, 0x1D },
-	{ 159500000, 0x1C },
-	{ 161200000, 0x1B },
-	{ 163000000, 0x1A },
-	{ 164700000, 0x19 },
-	{ 170200000, 0x17 },
-	{ 175800000, 0x16 },
-	{ 181300000, 0x15 },
-	{ 186900000, 0x14 },
-	{ 192400000, 0x13 },
-	{ 198000000, 0x12 },
-	{ 203500000, 0x11 },
-	{ 216200000, 0x14 },
-	{ 228900000, 0x13 },
-	{ 241600000, 0x12 },
-	{ 254400000, 0x11 },
-	{ 267100000, 0x10 },
-	{ 279800000, 0x0F },
-	{ 292500000, 0x0E },
-	{ 305200000, 0x0D },
-	{ 317900000, 0x0C },
-	{ 330700000, 0x0B },
-	{ 343400000, 0x0A },
-	{ 356100000, 0x09 },
-	{ 368800000, 0x08 },
-	{ 381500000, 0x07 },
-	{ 394200000, 0x06 },
-	{ 406900000, 0x05 },
-	{ 419700000, 0x04 },
-	{ 432400000, 0x03 },
-	{ 445100000, 0x02 },
-	{ 457800000, 0x01 },
-	{ 476300000, 0x19 },
-	{ 494800000, 0x18 },
-	{ 513300000, 0x17 },
-	{ 531800000, 0x16 },
-	{ 550300000, 0x15 },
-	{ 568900000, 0x14 },
-	{ 587400000, 0x13 },
-	{ 605900000, 0x12 },
-	{ 624400000, 0x11 },
-	{ 642900000, 0x10 },
-	{ 661400000, 0x0F },
-	{ 679900000, 0x0E },
-	{ 698400000, 0x0D },
-	{ 716900000, 0x0C },
-	{ 735400000, 0x0B },
-	{ 753900000, 0x0A },
-	{ 772500000, 0x09 },
-	{ 791000000, 0x08 },
-	{ 809500000, 0x07 },
-	{ 828000000, 0x06 },
-	{ 846500000, 0x05 },
-	{ 865000000, 0x04 },
-	{         0, 0x00 },    /* Table End */
-};
-
-static struct SMap m_RF_Cal_DC_Over_DT_Map[] = {
-	{  47900000, 0x00 },
-	{  55000000, 0x00 },
-	{  61100000, 0x0A },
-	{  64000000, 0x0A },
-	{  82000000, 0x14 },
-	{  84000000, 0x19 },
-	{ 119000000, 0x1C },
-	{ 124000000, 0x20 },
-	{ 129000000, 0x2A },
-	{ 134000000, 0x32 },
-	{ 139000000, 0x39 },
-	{ 144000000, 0x3E },
-	{ 149000000, 0x3F },
-	{ 152600000, 0x40 },
-	{ 154000000, 0x40 },
-	{ 164700000, 0x41 },
-	{ 203500000, 0x32 },
-	{ 353000000, 0x19 },
-	{ 356000000, 0x1A },
-	{ 359000000, 0x1B },
-	{ 363000000, 0x1C },
-	{ 366000000, 0x1D },
-	{ 369000000, 0x1E },
-	{ 373000000, 0x1F },
-	{ 376000000, 0x20 },
-	{ 379000000, 0x21 },
-	{ 383000000, 0x22 },
-	{ 386000000, 0x23 },
-	{ 389000000, 0x24 },
-	{ 393000000, 0x25 },
-	{ 396000000, 0x26 },
-	{ 399000000, 0x27 },
-	{ 402000000, 0x28 },
-	{ 404000000, 0x29 },
-	{ 407000000, 0x2A },
-	{ 409000000, 0x2B },
-	{ 412000000, 0x2C },
-	{ 414000000, 0x2D },
-	{ 417000000, 0x2E },
-	{ 419000000, 0x2F },
-	{ 422000000, 0x30 },
-	{ 424000000, 0x31 },
-	{ 427000000, 0x32 },
-	{ 429000000, 0x33 },
-	{ 432000000, 0x34 },
-	{ 434000000, 0x35 },
-	{ 437000000, 0x36 },
-	{ 439000000, 0x37 },
-	{ 442000000, 0x38 },
-	{ 444000000, 0x39 },
-	{ 447000000, 0x3A },
-	{ 449000000, 0x3B },
-	{ 457800000, 0x3C },
-	{ 465000000, 0x0F },
-	{ 477000000, 0x12 },
-	{ 483000000, 0x14 },
-	{ 502000000, 0x19 },
-	{ 508000000, 0x1B },
-	{ 519000000, 0x1C },
-	{ 522000000, 0x1D },
-	{ 524000000, 0x1E },
-	{ 534000000, 0x1F },
-	{ 549000000, 0x20 },
-	{ 554000000, 0x22 },
-	{ 584000000, 0x24 },
-	{ 589000000, 0x26 },
-	{ 658000000, 0x27 },
-	{ 664000000, 0x2C },
-	{ 669000000, 0x2D },
-	{ 699000000, 0x2E },
-	{ 704000000, 0x30 },
-	{ 709000000, 0x31 },
-	{ 714000000, 0x32 },
-	{ 724000000, 0x33 },
-	{ 729000000, 0x36 },
-	{ 739000000, 0x38 },
-	{ 744000000, 0x39 },
-	{ 749000000, 0x3B },
-	{ 754000000, 0x3C },
-	{ 759000000, 0x3D },
-	{ 764000000, 0x3E },
-	{ 769000000, 0x3F },
-	{ 774000000, 0x40 },
-	{ 779000000, 0x41 },
-	{ 784000000, 0x43 },
-	{ 789000000, 0x46 },
-	{ 794000000, 0x48 },
-	{ 799000000, 0x4B },
-	{ 804000000, 0x4F },
-	{ 809000000, 0x54 },
-	{ 814000000, 0x59 },
-	{ 819000000, 0x5D },
-	{ 824000000, 0x61 },
-	{ 829000000, 0x68 },
-	{ 834000000, 0x6E },
-	{ 839000000, 0x75 },
-	{ 844000000, 0x7E },
-	{ 849000000, 0x82 },
-	{ 854000000, 0x84 },
-	{ 859000000, 0x8F },
-	{ 865000000, 0x9A },
-	{         0, 0x00 },    /* Table End */
-};
-
-
-static struct SMap  m_IR_Meas_Map[] = {
-	{ 200000000, 0x05 },
-	{ 400000000, 0x06 },
-	{ 865000000, 0x07 },
-	{         0, 0x00 },    /* Table End */
-};
-
-static struct SMap2 m_CID_Target_Map[] = {
-	{  46000000, 0x04, 18 },
-	{  52200000, 0x0A, 15 },
-	{  70100000, 0x01, 40 },
-	{ 136800000, 0x18, 40 },
-	{ 156700000, 0x18, 40 },
-	{ 186250000, 0x0A, 40 },
-	{ 230000000, 0x0A, 40 },
-	{ 345000000, 0x18, 40 },
-	{ 426000000, 0x0E, 40 },
-	{ 489500000, 0x1E, 40 },
-	{ 697500000, 0x32, 40 },
-	{ 842000000, 0x3A, 40 },
-	{         0, 0x00,  0 },    /* Table End */
-};
-
-static struct SRFBandMap  m_RF_Band_Map[7] = {
-	{   47900000,   46000000,           0,          0},
-	{   61100000,   52200000,           0,          0},
-	{  152600000,   70100000,   136800000,          0},
-	{  164700000,  156700000,           0,          0},
-	{  203500000,  186250000,           0,          0},
-	{  457800000,  230000000,   345000000,  426000000},
-	{  865000000,  489500000,   697500000,  842000000},
-};
-
-u8 m_Thermometer_Map_1[16] = {
-	60, 62, 66, 64,
-	74, 72, 68, 70,
-	90, 88, 84, 86,
-	76, 78, 82, 80,
-};
-
-u8 m_Thermometer_Map_2[16] = {
-	92, 94, 98, 96,
-	106, 104, 100, 102,
-	122, 120, 116, 118,
-	108, 110, 114, 112,
-};
diff --git a/drivers/media/dvb/frontends/tda665x.c b/drivers/media/dvb/frontends/tda665x.c
deleted file mode 100644
index 2c1c759..0000000
--- a/drivers/media/dvb/frontends/tda665x.c
+++ /dev/null
@@ -1,258 +0,0 @@
-/*
-	TDA665x tuner driver
-	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-
-#include "dvb_frontend.h"
-#include "tda665x.h"
-
-struct tda665x_state {
-	struct dvb_frontend		*fe;
-	struct i2c_adapter		*i2c;
-	const struct tda665x_config	*config;
-
-	u32 frequency;
-	u32 bandwidth;
-};
-
-static int tda665x_read(struct tda665x_state *state, u8 *buf)
-{
-	const struct tda665x_config *config = state->config;
-	int err = 0;
-	struct i2c_msg msg = { .addr = config->addr, .flags = I2C_M_RD, .buf = buf, .len = 2 };
-
-	err = i2c_transfer(state->i2c, &msg, 1);
-	if (err != 1)
-		goto exit;
-
-	return err;
-exit:
-	printk(KERN_ERR "%s: I/O Error err=<%d>\n", __func__, err);
-	return err;
-}
-
-static int tda665x_write(struct tda665x_state *state, u8 *buf, u8 length)
-{
-	const struct tda665x_config *config = state->config;
-	int err = 0;
-	struct i2c_msg msg = { .addr = config->addr, .flags = 0, .buf = buf, .len = length };
-
-	err = i2c_transfer(state->i2c, &msg, 1);
-	if (err != 1)
-		goto exit;
-
-	return err;
-exit:
-	printk(KERN_ERR "%s: I/O Error err=<%d>\n", __func__, err);
-	return err;
-}
-
-static int tda665x_get_state(struct dvb_frontend *fe,
-			     enum tuner_param param,
-			     struct tuner_state *tstate)
-{
-	struct tda665x_state *state = fe->tuner_priv;
-	int err = 0;
-
-	switch (param) {
-	case DVBFE_TUNER_FREQUENCY:
-		tstate->frequency = state->frequency;
-		break;
-	case DVBFE_TUNER_BANDWIDTH:
-		break;
-	default:
-		printk(KERN_ERR "%s: Unknown parameter (param=%d)\n", __func__, param);
-		err = -EINVAL;
-		break;
-	}
-
-	return err;
-}
-
-static int tda665x_get_status(struct dvb_frontend *fe, u32 *status)
-{
-	struct tda665x_state *state = fe->tuner_priv;
-	u8 result = 0;
-	int err = 0;
-
-	*status = 0;
-
-	err = tda665x_read(state, &result);
-	if (err < 0)
-		goto exit;
-
-	if ((result >> 6) & 0x01) {
-		printk(KERN_DEBUG "%s: Tuner Phase Locked\n", __func__);
-		*status = 1;
-	}
-
-	return err;
-exit:
-	printk(KERN_ERR "%s: I/O Error\n", __func__);
-	return err;
-}
-
-static int tda665x_set_state(struct dvb_frontend *fe,
-			     enum tuner_param param,
-			     struct tuner_state *tstate)
-{
-	struct tda665x_state *state = fe->tuner_priv;
-	const struct tda665x_config *config = state->config;
-	u32 frequency, status = 0;
-	u8 buf[4];
-	int err = 0;
-
-	if (param & DVBFE_TUNER_FREQUENCY) {
-
-		frequency = tstate->frequency;
-		if ((frequency < config->frequency_max) || (frequency > config->frequency_min)) {
-			printk(KERN_ERR "%s: Frequency beyond limits, frequency=%d\n", __func__, frequency);
-			return -EINVAL;
-		}
-
-		frequency += config->frequency_offst;
-		frequency *= config->ref_multiplier;
-		frequency += config->ref_divider >> 1;
-		frequency /= config->ref_divider;
-
-		buf[0] = (u8) ((frequency & 0x7f00) >> 8);
-		buf[1] = (u8) (frequency & 0x00ff) >> 0;
-		buf[2] = 0x80 | 0x40 | 0x02;
-		buf[3] = 0x00;
-
-		/* restore frequency */
-		frequency = tstate->frequency;
-
-		if (frequency < 153000000) {
-			/* VHF-L */
-			buf[3] |= 0x01; /* fc, Low Band, 47 - 153 MHz */
-			if (frequency < 68000000)
-				buf[3] |= 0x40; /* 83uA */
-			if (frequency < 1040000000)
-				buf[3] |= 0x60; /* 122uA */
-			if (frequency < 1250000000)
-				buf[3] |= 0x80; /* 163uA */
-			else
-				buf[3] |= 0xa0; /* 254uA */
-		} else if (frequency < 438000000) {
-			/* VHF-H */
-			buf[3] |= 0x02; /* fc, Mid Band, 153 - 438 MHz */
-			if (frequency < 230000000)
-				buf[3] |= 0x40;
-			if (frequency < 300000000)
-				buf[3] |= 0x60;
-			else
-				buf[3] |= 0x80;
-		} else {
-			/* UHF */
-			buf[3] |= 0x04; /* fc, High Band, 438 - 862 MHz */
-			if (frequency < 470000000)
-				buf[3] |= 0x60;
-			if (frequency < 526000000)
-				buf[3] |= 0x80;
-			else
-				buf[3] |= 0xa0;
-		}
-
-		/* Set params */
-		err = tda665x_write(state, buf, 5);
-		if (err < 0)
-			goto exit;
-
-		/* sleep for some time */
-		printk(KERN_DEBUG "%s: Waiting to Phase LOCK\n", __func__);
-		msleep(20);
-		/* check status */
-		err = tda665x_get_status(fe, &status);
-		if (err < 0)
-			goto exit;
-
-		if (status == 1) {
-			printk(KERN_DEBUG "%s: Tuner Phase locked: status=%d\n", __func__, status);
-			state->frequency = frequency; /* cache successful state */
-		} else {
-			printk(KERN_ERR "%s: No Phase lock: status=%d\n", __func__, status);
-		}
-	} else {
-		printk(KERN_ERR "%s: Unknown parameter (param=%d)\n", __func__, param);
-		return -EINVAL;
-	}
-
-	return 0;
-exit:
-	printk(KERN_ERR "%s: I/O Error\n", __func__);
-	return err;
-}
-
-static int tda665x_release(struct dvb_frontend *fe)
-{
-	struct tda665x_state *state = fe->tuner_priv;
-
-	fe->tuner_priv = NULL;
-	kfree(state);
-	return 0;
-}
-
-static struct dvb_tuner_ops tda665x_ops = {
-
-	.set_state	= tda665x_set_state,
-	.get_state	= tda665x_get_state,
-	.get_status	= tda665x_get_status,
-	.release	= tda665x_release
-};
-
-struct dvb_frontend *tda665x_attach(struct dvb_frontend *fe,
-				    const struct tda665x_config *config,
-				    struct i2c_adapter *i2c)
-{
-	struct tda665x_state *state = NULL;
-	struct dvb_tuner_info *info;
-
-	state = kzalloc(sizeof(struct tda665x_state), GFP_KERNEL);
-	if (state == NULL)
-		goto exit;
-
-	state->config		= config;
-	state->i2c		= i2c;
-	state->fe		= fe;
-	fe->tuner_priv		= state;
-	fe->ops.tuner_ops	= tda665x_ops;
-	info			 = &fe->ops.tuner_ops.info;
-
-	memcpy(info->name, config->name, sizeof(config->name));
-	info->frequency_min	= config->frequency_min;
-	info->frequency_max	= config->frequency_max;
-	info->frequency_step	= config->frequency_offst;
-
-	printk(KERN_DEBUG "%s: Attaching TDA665x (%s) tuner\n", __func__, info->name);
-
-	return fe;
-
-exit:
-	kfree(state);
-	return NULL;
-}
-EXPORT_SYMBOL(tda665x_attach);
-
-MODULE_DESCRIPTION("TDA665x driver");
-MODULE_AUTHOR("Manu Abraham");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/tda665x.h b/drivers/media/dvb/frontends/tda665x.h
deleted file mode 100644
index ec7927a..0000000
--- a/drivers/media/dvb/frontends/tda665x.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
-	TDA665x tuner driver
-	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#ifndef __TDA665x_H
-#define __TDA665x_H
-
-struct tda665x_config {
-	char name[128];
-
-	u8	addr;
-	u32	frequency_min;
-	u32	frequency_max;
-	u32	frequency_offst;
-	u32	ref_multiplier;
-	u32	ref_divider;
-};
-
-#if defined(CONFIG_DVB_TDA665x) || (defined(CONFIG_DVB_TDA665x_MODULE) && defined(MODULE))
-
-extern struct dvb_frontend *tda665x_attach(struct dvb_frontend *fe,
-					   const struct tda665x_config *config,
-					   struct i2c_adapter *i2c);
-
-#else
-
-static inline struct dvb_frontend *tda665x_attach(struct dvb_frontend *fe,
-						  const struct tda665x_config *config,
-						  struct i2c_adapter *i2c)
-{
-	printk(KERN_WARNING "%s: Driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-
-#endif /* CONFIG_DVB_TDA665x */
-
-#endif /* __TDA665x_H */
diff --git a/drivers/media/dvb/frontends/tda8083.c b/drivers/media/dvb/frontends/tda8083.c
deleted file mode 100644
index 15912c9..0000000
--- a/drivers/media/dvb/frontends/tda8083.c
+++ /dev/null
@@ -1,487 +0,0 @@
-/*
-    Driver for Philips TDA8083 based QPSK Demodulator
-
-    Copyright (C) 2001 Convergence Integrated Media GmbH
-
-    written by Ralph Metzler <ralph@convergence.de>
-
-    adoption to the new DVB frontend API and diagnostic ioctl's
-    by Holger Waechtler <holger@convergence.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/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/jiffies.h>
-#include "dvb_frontend.h"
-#include "tda8083.h"
-
-
-struct tda8083_state {
-	struct i2c_adapter* i2c;
-	/* configuration settings */
-	const struct tda8083_config* config;
-	struct dvb_frontend frontend;
-};
-
-static int debug;
-#define dprintk(args...) \
-	do { \
-		if (debug) printk(KERN_DEBUG "tda8083: " args); \
-	} while (0)
-
-
-static u8 tda8083_init_tab [] = {
-	0x04, 0x00, 0x4a, 0x79, 0x04, 0x00, 0xff, 0xea,
-	0x48, 0x42, 0x79, 0x60, 0x70, 0x52, 0x9a, 0x10,
-	0x0e, 0x10, 0xf2, 0xa7, 0x93, 0x0b, 0x05, 0xc8,
-	0x9d, 0x00, 0x42, 0x80, 0x00, 0x60, 0x40, 0x00,
-	0x00, 0x75, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00
-};
-
-
-static int tda8083_writereg (struct tda8083_state* state, u8 reg, u8 data)
-{
-	int ret;
-	u8 buf [] = { reg, data };
-	struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 };
-
-	ret = i2c_transfer(state->i2c, &msg, 1);
-
-	if (ret != 1)
-		dprintk ("%s: writereg error (reg %02x, ret == %i)\n",
-			__func__, reg, ret);
-
-	return (ret != 1) ? -1 : 0;
-}
-
-static int tda8083_readregs (struct tda8083_state* state, u8 reg1, u8 *b, u8 len)
-{
-	int ret;
-	struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = &reg1, .len = 1 },
-			   { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b, .len = len } };
-
-	ret = i2c_transfer(state->i2c, msg, 2);
-
-	if (ret != 2)
-		dprintk ("%s: readreg error (reg %02x, ret == %i)\n",
-			__func__, reg1, ret);
-
-	return ret == 2 ? 0 : -1;
-}
-
-static inline u8 tda8083_readreg (struct tda8083_state* state, u8 reg)
-{
-	u8 val;
-
-	tda8083_readregs (state, reg, &val, 1);
-
-	return val;
-}
-
-static int tda8083_set_inversion (struct tda8083_state* state, fe_spectral_inversion_t inversion)
-{
-	/*  XXX FIXME: implement other modes than FEC_AUTO */
-	if (inversion == INVERSION_AUTO)
-		return 0;
-
-	return -EINVAL;
-}
-
-static int tda8083_set_fec (struct tda8083_state* state, fe_code_rate_t fec)
-{
-	if (fec == FEC_AUTO)
-		return tda8083_writereg (state, 0x07, 0xff);
-
-	if (fec >= FEC_1_2 && fec <= FEC_8_9)
-		return tda8083_writereg (state, 0x07, 1 << (FEC_8_9 - fec));
-
-	return -EINVAL;
-}
-
-static fe_code_rate_t tda8083_get_fec (struct tda8083_state* state)
-{
-	u8 index;
-	static fe_code_rate_t fec_tab [] = { FEC_8_9, FEC_1_2, FEC_2_3, FEC_3_4,
-				       FEC_4_5, FEC_5_6, FEC_6_7, FEC_7_8 };
-
-	index = tda8083_readreg(state, 0x0e) & 0x07;
-
-	return fec_tab [index];
-}
-
-static int tda8083_set_symbolrate (struct tda8083_state* state, u32 srate)
-{
-	u32 ratio;
-	u32 tmp;
-	u8 filter;
-
-	if (srate > 32000000)
-		srate = 32000000;
-	if (srate < 500000)
-		srate = 500000;
-
-	filter = 0;
-	if (srate < 24000000)
-		filter = 2;
-	if (srate < 16000000)
-		filter = 3;
-
-	tmp = 31250 << 16;
-	ratio = tmp / srate;
-
-	tmp = (tmp % srate) << 8;
-	ratio = (ratio << 8) + tmp / srate;
-
-	tmp = (tmp % srate) << 8;
-	ratio = (ratio << 8) + tmp / srate;
-
-	dprintk("tda8083: ratio == %08x\n", (unsigned int) ratio);
-
-	tda8083_writereg (state, 0x05, filter);
-	tda8083_writereg (state, 0x02, (ratio >> 16) & 0xff);
-	tda8083_writereg (state, 0x03, (ratio >>  8) & 0xff);
-	tda8083_writereg (state, 0x04, (ratio      ) & 0xff);
-
-	tda8083_writereg (state, 0x00, 0x3c);
-	tda8083_writereg (state, 0x00, 0x04);
-
-	return 1;
-}
-
-static void tda8083_wait_diseqc_fifo (struct tda8083_state* state, int timeout)
-{
-	unsigned long start = jiffies;
-
-	while (jiffies - start < timeout &&
-	       !(tda8083_readreg(state, 0x02) & 0x80))
-	{
-		msleep(50);
-	};
-}
-
-static int tda8083_set_tone (struct tda8083_state* state, fe_sec_tone_mode_t tone)
-{
-	tda8083_writereg (state, 0x26, 0xf1);
-
-	switch (tone) {
-	case SEC_TONE_OFF:
-		return tda8083_writereg (state, 0x29, 0x00);
-	case SEC_TONE_ON:
-		return tda8083_writereg (state, 0x29, 0x80);
-	default:
-		return -EINVAL;
-	};
-}
-
-static int tda8083_set_voltage (struct tda8083_state* state, fe_sec_voltage_t voltage)
-{
-	switch (voltage) {
-	case SEC_VOLTAGE_13:
-		return tda8083_writereg (state, 0x20, 0x00);
-	case SEC_VOLTAGE_18:
-		return tda8083_writereg (state, 0x20, 0x11);
-	default:
-		return -EINVAL;
-	};
-}
-
-static int tda8083_send_diseqc_burst (struct tda8083_state* state, fe_sec_mini_cmd_t burst)
-{
-	switch (burst) {
-	case SEC_MINI_A:
-		tda8083_writereg (state, 0x29, (5 << 2));  /* send burst A */
-		break;
-	case SEC_MINI_B:
-		tda8083_writereg (state, 0x29, (7 << 2));  /* send B */
-		break;
-	default:
-		return -EINVAL;
-	};
-
-	tda8083_wait_diseqc_fifo (state, 100);
-
-	return 0;
-}
-
-static int tda8083_send_diseqc_msg (struct dvb_frontend* fe,
-				    struct dvb_diseqc_master_cmd *m)
-{
-	struct tda8083_state* state = fe->demodulator_priv;
-	int i;
-
-	tda8083_writereg (state, 0x29, (m->msg_len - 3) | (1 << 2)); /* enable */
-
-	for (i=0; i<m->msg_len; i++)
-		tda8083_writereg (state, 0x23 + i, m->msg[i]);
-
-	tda8083_writereg (state, 0x29, (m->msg_len - 3) | (3 << 2)); /* send!! */
-
-	tda8083_wait_diseqc_fifo (state, 100);
-
-	return 0;
-}
-
-static int tda8083_read_status(struct dvb_frontend* fe, fe_status_t* status)
-{
-	struct tda8083_state* state = fe->demodulator_priv;
-
-	u8 signal = ~tda8083_readreg (state, 0x01);
-	u8 sync = tda8083_readreg (state, 0x02);
-
-	*status = 0;
-
-	if (signal > 10)
-		*status |= FE_HAS_SIGNAL;
-
-	if (sync & 0x01)
-		*status |= FE_HAS_CARRIER;
-
-	if (sync & 0x02)
-		*status |= FE_HAS_VITERBI;
-
-	if (sync & 0x10)
-		*status |= FE_HAS_SYNC;
-
-	if (sync & 0x20) /* frontend can not lock */
-		*status |= FE_TIMEDOUT;
-
-	if ((sync & 0x1f) == 0x1f)
-		*status |= FE_HAS_LOCK;
-
-	return 0;
-}
-
-static int tda8083_read_ber(struct dvb_frontend* fe, u32* ber)
-{
-	struct tda8083_state* state = fe->demodulator_priv;
-	int ret;
-	u8 buf[3];
-
-	if ((ret = tda8083_readregs(state, 0x0b, buf, sizeof(buf))))
-		return ret;
-
-	*ber = ((buf[0] & 0x1f) << 16) | (buf[1] << 8) | buf[2];
-
-	return 0;
-}
-
-static int tda8083_read_signal_strength(struct dvb_frontend* fe, u16* strength)
-{
-	struct tda8083_state* state = fe->demodulator_priv;
-
-	u8 signal = ~tda8083_readreg (state, 0x01);
-	*strength = (signal << 8) | signal;
-
-	return 0;
-}
-
-static int tda8083_read_snr(struct dvb_frontend* fe, u16* snr)
-{
-	struct tda8083_state* state = fe->demodulator_priv;
-
-	u8 _snr = tda8083_readreg (state, 0x08);
-	*snr = (_snr << 8) | _snr;
-
-	return 0;
-}
-
-static int tda8083_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
-{
-	struct tda8083_state* state = fe->demodulator_priv;
-
-	*ucblocks = tda8083_readreg(state, 0x0f);
-	if (*ucblocks == 0xff)
-		*ucblocks = 0xffffffff;
-
-	return 0;
-}
-
-static int tda8083_set_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct tda8083_state* state = fe->demodulator_priv;
-
-	if (fe->ops.tuner_ops.set_params) {
-		fe->ops.tuner_ops.set_params(fe);
-		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
-	}
-
-	tda8083_set_inversion (state, p->inversion);
-	tda8083_set_fec(state, p->fec_inner);
-	tda8083_set_symbolrate(state, p->symbol_rate);
-
-	tda8083_writereg (state, 0x00, 0x3c);
-	tda8083_writereg (state, 0x00, 0x04);
-
-	return 0;
-}
-
-static int tda8083_get_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct tda8083_state* state = fe->demodulator_priv;
-
-	/*  FIXME: get symbolrate & frequency offset...*/
-	/*p->frequency = ???;*/
-	p->inversion = (tda8083_readreg (state, 0x0e) & 0x80) ?
-			INVERSION_ON : INVERSION_OFF;
-	p->fec_inner = tda8083_get_fec(state);
-	/*p->symbol_rate = tda8083_get_symbolrate (state);*/
-
-	return 0;
-}
-
-static int tda8083_sleep(struct dvb_frontend* fe)
-{
-	struct tda8083_state* state = fe->demodulator_priv;
-
-	tda8083_writereg (state, 0x00, 0x02);
-	return 0;
-}
-
-static int tda8083_init(struct dvb_frontend* fe)
-{
-	struct tda8083_state* state = fe->demodulator_priv;
-	int i;
-
-	for (i=0; i<44; i++)
-		tda8083_writereg (state, i, tda8083_init_tab[i]);
-
-	tda8083_writereg (state, 0x00, 0x3c);
-	tda8083_writereg (state, 0x00, 0x04);
-
-	return 0;
-}
-
-static int tda8083_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t burst)
-{
-	struct tda8083_state* state = fe->demodulator_priv;
-
-	tda8083_send_diseqc_burst (state, burst);
-	tda8083_writereg (state, 0x00, 0x3c);
-	tda8083_writereg (state, 0x00, 0x04);
-
-	return 0;
-}
-
-static int tda8083_diseqc_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
-{
-	struct tda8083_state* state = fe->demodulator_priv;
-
-	tda8083_set_tone (state, tone);
-	tda8083_writereg (state, 0x00, 0x3c);
-	tda8083_writereg (state, 0x00, 0x04);
-
-	return 0;
-}
-
-static int tda8083_diseqc_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
-{
-	struct tda8083_state* state = fe->demodulator_priv;
-
-	tda8083_set_voltage (state, voltage);
-	tda8083_writereg (state, 0x00, 0x3c);
-	tda8083_writereg (state, 0x00, 0x04);
-
-	return 0;
-}
-
-static void tda8083_release(struct dvb_frontend* fe)
-{
-	struct tda8083_state* state = fe->demodulator_priv;
-	kfree(state);
-}
-
-static struct dvb_frontend_ops tda8083_ops;
-
-struct dvb_frontend* tda8083_attach(const struct tda8083_config* config,
-				    struct i2c_adapter* i2c)
-{
-	struct tda8083_state* state = NULL;
-
-	/* allocate memory for the internal state */
-	state = kzalloc(sizeof(struct tda8083_state), GFP_KERNEL);
-	if (state == NULL) goto error;
-
-	/* setup the state */
-	state->config = config;
-	state->i2c = i2c;
-
-	/* check if the demod is there */
-	if ((tda8083_readreg(state, 0x00)) != 0x05) goto error;
-
-	/* create dvb_frontend */
-	memcpy(&state->frontend.ops, &tda8083_ops, sizeof(struct dvb_frontend_ops));
-	state->frontend.demodulator_priv = state;
-	return &state->frontend;
-
-error:
-	kfree(state);
-	return NULL;
-}
-
-static struct dvb_frontend_ops tda8083_ops = {
-	.delsys = { SYS_DVBS },
-	.info = {
-		.name			= "Philips TDA8083 DVB-S",
-		.frequency_min		= 920000,     /* TDA8060 */
-		.frequency_max		= 2200000,    /* TDA8060 */
-		.frequency_stepsize	= 125,   /* kHz for QPSK frontends */
-	/*      .frequency_tolerance	= ???,*/
-		.symbol_rate_min	= 12000000,
-		.symbol_rate_max	= 30000000,
-	/*      .symbol_rate_tolerance	= ???,*/
-		.caps = FE_CAN_INVERSION_AUTO |
-			FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
-			FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
-			FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO |
-			FE_CAN_QPSK | FE_CAN_MUTE_TS
-	},
-
-	.release = tda8083_release,
-
-	.init = tda8083_init,
-	.sleep = tda8083_sleep,
-
-	.set_frontend = tda8083_set_frontend,
-	.get_frontend = tda8083_get_frontend,
-
-	.read_status = tda8083_read_status,
-	.read_signal_strength = tda8083_read_signal_strength,
-	.read_snr = tda8083_read_snr,
-	.read_ber = tda8083_read_ber,
-	.read_ucblocks = tda8083_read_ucblocks,
-
-	.diseqc_send_master_cmd = tda8083_send_diseqc_msg,
-	.diseqc_send_burst = tda8083_diseqc_send_burst,
-	.set_tone = tda8083_diseqc_set_tone,
-	.set_voltage = tda8083_diseqc_set_voltage,
-};
-
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
-
-MODULE_DESCRIPTION("Philips TDA8083 DVB-S Demodulator");
-MODULE_AUTHOR("Ralph Metzler, Holger Waechtler");
-MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(tda8083_attach);
diff --git a/drivers/media/dvb/frontends/tda8083.h b/drivers/media/dvb/frontends/tda8083.h
deleted file mode 100644
index 5a03c14..0000000
--- a/drivers/media/dvb/frontends/tda8083.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
-    Driver for Grundig 29504-491, a Philips TDA8083 based QPSK Frontend
-
-    Copyright (C) 2001 Convergence Integrated Media GmbH
-
-    written by Ralph Metzler <ralph@convergence.de>
-
-    adoption to the new DVB frontend API and diagnostic ioctl's
-    by Holger Waechtler <holger@convergence.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 TDA8083_H
-#define TDA8083_H
-
-#include <linux/dvb/frontend.h>
-
-struct tda8083_config
-{
-	/* the demodulator's i2c address */
-	u8 demod_address;
-};
-
-#if defined(CONFIG_DVB_TDA8083) || (defined(CONFIG_DVB_TDA8083_MODULE) && defined(MODULE))
-extern struct dvb_frontend* tda8083_attach(const struct tda8083_config* config,
-					   struct i2c_adapter* i2c);
-#else
-static inline struct dvb_frontend* tda8083_attach(const struct tda8083_config* config,
-					   struct i2c_adapter* i2c)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif // CONFIG_DVB_TDA8083
-
-#endif // TDA8083_H
diff --git a/drivers/media/dvb/frontends/tda8261.c b/drivers/media/dvb/frontends/tda8261.c
deleted file mode 100644
index 53c7d8f..0000000
--- a/drivers/media/dvb/frontends/tda8261.c
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
-	TDA8261 8PSK/QPSK tuner driver
-	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-
-#include "dvb_frontend.h"
-#include "tda8261.h"
-
-struct tda8261_state {
-	struct dvb_frontend		*fe;
-	struct i2c_adapter		*i2c;
-	const struct tda8261_config	*config;
-
-	/* state cache */
-	u32 frequency;
-	u32 bandwidth;
-};
-
-static int tda8261_read(struct tda8261_state *state, u8 *buf)
-{
-	const struct tda8261_config *config = state->config;
-	int err = 0;
-	struct i2c_msg msg = { .addr	= config->addr, .flags = I2C_M_RD,.buf = buf,  .len = 1 };
-
-	if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1)
-		printk("%s: read error, err=%d\n", __func__, err);
-
-	return err;
-}
-
-static int tda8261_write(struct tda8261_state *state, u8 *buf)
-{
-	const struct tda8261_config *config = state->config;
-	int err = 0;
-	struct i2c_msg msg = { .addr = config->addr, .flags = 0, .buf = buf, .len = 4 };
-
-	if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1)
-		printk("%s: write error, err=%d\n", __func__, err);
-
-	return err;
-}
-
-static int tda8261_get_status(struct dvb_frontend *fe, u32 *status)
-{
-	struct tda8261_state *state = fe->tuner_priv;
-	u8 result = 0;
-	int err = 0;
-
-	*status = 0;
-
-	if ((err = tda8261_read(state, &result)) < 0) {
-		printk("%s: I/O Error\n", __func__);
-		return err;
-	}
-	if ((result >> 6) & 0x01) {
-		printk("%s: Tuner Phase Locked\n", __func__);
-		*status = 1;
-	}
-
-	return err;
-}
-
-static const u32 div_tab[] = { 2000, 1000,  500,  250,  125 }; /* kHz */
-static const u8  ref_div[] = { 0x00, 0x01, 0x02, 0x05, 0x07 };
-
-static int tda8261_get_state(struct dvb_frontend *fe,
-			     enum tuner_param param,
-			     struct tuner_state *tstate)
-{
-	struct tda8261_state *state = fe->tuner_priv;
-	int err = 0;
-
-	switch (param) {
-	case DVBFE_TUNER_FREQUENCY:
-		tstate->frequency = state->frequency;
-		break;
-	case DVBFE_TUNER_BANDWIDTH:
-		tstate->bandwidth = 40000000; /* FIXME! need to calculate Bandwidth */
-		break;
-	default:
-		printk("%s: Unknown parameter (param=%d)\n", __func__, param);
-		err = -EINVAL;
-		break;
-	}
-
-	return err;
-}
-
-static int tda8261_set_state(struct dvb_frontend *fe,
-			     enum tuner_param param,
-			     struct tuner_state *tstate)
-{
-	struct tda8261_state *state = fe->tuner_priv;
-	const struct tda8261_config *config = state->config;
-	u32 frequency, N, status = 0;
-	u8 buf[4];
-	int err = 0;
-
-	if (param & DVBFE_TUNER_FREQUENCY) {
-		/**
-		 * N = Max VCO Frequency / Channel Spacing
-		 * Max VCO Frequency = VCO frequency + (channel spacing - 1)
-		 * (to account for half channel spacing on either side)
-		 */
-		frequency = tstate->frequency;
-		if ((frequency < 950000) || (frequency > 2150000)) {
-			printk("%s: Frequency beyond limits, frequency=%d\n", __func__, frequency);
-			return -EINVAL;
-		}
-		N = (frequency + (div_tab[config->step_size] - 1)) / div_tab[config->step_size];
-		printk("%s: Step size=%d, Divider=%d, PG=0x%02x (%d)\n",
-			__func__, config->step_size, div_tab[config->step_size], N, N);
-
-		buf[0] = (N >> 8) & 0xff;
-		buf[1] = N & 0xff;
-		buf[2] = (0x01 << 7) | ((ref_div[config->step_size] & 0x07) << 1);
-
-		if (frequency < 1450000)
-			buf[3] = 0x00;
-		else if (frequency < 2000000)
-			buf[3] = 0x40;
-		else if (frequency < 2150000)
-			buf[3] = 0x80;
-
-		/* Set params */
-		if ((err = tda8261_write(state, buf)) < 0) {
-			printk("%s: I/O Error\n", __func__);
-			return err;
-		}
-		/* sleep for some time */
-		printk("%s: Waiting to Phase LOCK\n", __func__);
-		msleep(20);
-		/* check status */
-		if ((err = tda8261_get_status(fe, &status)) < 0) {
-			printk("%s: I/O Error\n", __func__);
-			return err;
-		}
-		if (status == 1) {
-			printk("%s: Tuner Phase locked: status=%d\n", __func__, status);
-			state->frequency = frequency; /* cache successful state */
-		} else {
-			printk("%s: No Phase lock: status=%d\n", __func__, status);
-		}
-	} else {
-		printk("%s: Unknown parameter (param=%d)\n", __func__, param);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int tda8261_release(struct dvb_frontend *fe)
-{
-	struct tda8261_state *state = fe->tuner_priv;
-
-	fe->tuner_priv = NULL;
-	kfree(state);
-	return 0;
-}
-
-static struct dvb_tuner_ops tda8261_ops = {
-
-	.info = {
-		.name		= "TDA8261",
-//		.tuner_name	= NULL,
-		.frequency_min	=  950000,
-		.frequency_max	= 2150000,
-		.frequency_step = 0
-	},
-
-	.set_state	= tda8261_set_state,
-	.get_state	= tda8261_get_state,
-	.get_status	= tda8261_get_status,
-	.release	= tda8261_release
-};
-
-struct dvb_frontend *tda8261_attach(struct dvb_frontend *fe,
-				    const struct tda8261_config *config,
-				    struct i2c_adapter *i2c)
-{
-	struct tda8261_state *state = NULL;
-
-	if ((state = kzalloc(sizeof (struct tda8261_state), GFP_KERNEL)) == NULL)
-		goto exit;
-
-	state->config		= config;
-	state->i2c		= i2c;
-	state->fe		= fe;
-	fe->tuner_priv		= state;
-	fe->ops.tuner_ops	= tda8261_ops;
-
-	fe->ops.tuner_ops.info.frequency_step = div_tab[config->step_size];
-//	fe->ops.tuner_ops.tuner_name	 = &config->buf;
-
-//	printk("%s: Attaching %s TDA8261 8PSK/QPSK tuner\n",
-//		__func__, fe->ops.tuner_ops.tuner_name);
-	printk("%s: Attaching TDA8261 8PSK/QPSK tuner\n", __func__);
-
-	return fe;
-
-exit:
-	kfree(state);
-	return NULL;
-}
-
-EXPORT_SYMBOL(tda8261_attach);
-
-MODULE_AUTHOR("Manu Abraham");
-MODULE_DESCRIPTION("TDA8261 8PSK/QPSK Tuner");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/tda8261.h b/drivers/media/dvb/frontends/tda8261.h
deleted file mode 100644
index 006e453..0000000
--- a/drivers/media/dvb/frontends/tda8261.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
-	TDA8261 8PSK/QPSK tuner driver
-	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#ifndef __TDA8261_H
-#define __TDA8261_H
-
-enum tda8261_step {
-	TDA8261_STEP_2000 = 0,	/* 2000 kHz */
-	TDA8261_STEP_1000,	/* 1000 kHz */
-	TDA8261_STEP_500,	/*  500 kHz */
-	TDA8261_STEP_250,	/*  250 kHz */
-	TDA8261_STEP_125	/*  125 kHz */
-};
-
-struct tda8261_config {
-//	u8			buf[16];
-	u8			addr;
-	enum tda8261_step	step_size;
-};
-
-#if defined(CONFIG_DVB_TDA8261) || (defined(CONFIG_DVB_TDA8261_MODULE) && defined(MODULE))
-
-extern struct dvb_frontend *tda8261_attach(struct dvb_frontend *fe,
-					   const struct tda8261_config *config,
-					   struct i2c_adapter *i2c);
-
-#else
-
-static inline struct dvb_frontend *tda8261_attach(struct dvb_frontend *fe,
-						  const struct tda8261_config *config,
-						  struct i2c_adapter *i2c)
-{
-	printk(KERN_WARNING "%s: Driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-
-#endif //CONFIG_DVB_TDA8261
-
-#endif// __TDA8261_H
diff --git a/drivers/media/dvb/frontends/tda8261_cfg.h b/drivers/media/dvb/frontends/tda8261_cfg.h
deleted file mode 100644
index 1af1ee4..0000000
--- a/drivers/media/dvb/frontends/tda8261_cfg.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
-	TDA8261 8PSK/QPSK tuner driver
-	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-static int tda8261_get_frequency(struct dvb_frontend *fe, u32 *frequency)
-{
-	struct dvb_frontend_ops	*frontend_ops = NULL;
-	struct dvb_tuner_ops	*tuner_ops = NULL;
-	struct tuner_state	t_state;
-	int err = 0;
-
-	if (&fe->ops)
-		frontend_ops = &fe->ops;
-	if (&frontend_ops->tuner_ops)
-		tuner_ops = &frontend_ops->tuner_ops;
-	if (tuner_ops->get_state) {
-		if ((err = tuner_ops->get_state(fe, DVBFE_TUNER_FREQUENCY, &t_state)) < 0) {
-			printk("%s: Invalid parameter\n", __func__);
-			return err;
-		}
-		*frequency = t_state.frequency;
-		printk("%s: Frequency=%d\n", __func__, t_state.frequency);
-	}
-	return 0;
-}
-
-static int tda8261_set_frequency(struct dvb_frontend *fe, u32 frequency)
-{
-	struct dvb_frontend_ops	*frontend_ops = NULL;
-	struct dvb_tuner_ops	*tuner_ops = NULL;
-	struct tuner_state	t_state;
-	int err = 0;
-
-	t_state.frequency = frequency;
-	if (&fe->ops)
-		frontend_ops = &fe->ops;
-	if (&frontend_ops->tuner_ops)
-		tuner_ops = &frontend_ops->tuner_ops;
-	if (tuner_ops->set_state) {
-		if ((err = tuner_ops->set_state(fe, DVBFE_TUNER_FREQUENCY, &t_state)) < 0) {
-			printk("%s: Invalid parameter\n", __func__);
-			return err;
-		}
-	}
-	printk("%s: Frequency=%d\n", __func__, t_state.frequency);
-	return 0;
-}
-
-static int tda8261_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
-{
-	struct dvb_frontend_ops	*frontend_ops = &fe->ops;
-	struct dvb_tuner_ops	*tuner_ops = &frontend_ops->tuner_ops;
-	struct tuner_state	t_state;
-	int err = 0;
-
-	if (&fe->ops)
-		frontend_ops = &fe->ops;
-	if (&frontend_ops->tuner_ops)
-		tuner_ops = &frontend_ops->tuner_ops;
-	if (tuner_ops->get_state) {
-		if ((err = tuner_ops->get_state(fe, DVBFE_TUNER_BANDWIDTH, &t_state)) < 0) {
-			printk("%s: Invalid parameter\n", __func__);
-			return err;
-		}
-		*bandwidth = t_state.bandwidth;
-	}
-	printk("%s: Bandwidth=%d\n", __func__, t_state.bandwidth);
-	return 0;
-}
diff --git a/drivers/media/dvb/frontends/tda826x.c b/drivers/media/dvb/frontends/tda826x.c
deleted file mode 100644
index 04bbcc2..0000000
--- a/drivers/media/dvb/frontends/tda826x.c
+++ /dev/null
@@ -1,188 +0,0 @@
-  /*
-     Driver for Philips tda8262/tda8263 DVBS Silicon tuners
-
-     (c) 2006 Andrew de Quincey
-
-     This program is free software; you can redistribute it and/or modify
-     it under the terms of the 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/slab.h>
-#include <linux/module.h>
-#include <linux/dvb/frontend.h>
-#include <asm/types.h>
-
-#include "tda826x.h"
-
-static int debug;
-#define dprintk(args...) \
-	do { \
-		if (debug) printk(KERN_DEBUG "tda826x: " args); \
-	} while (0)
-
-struct tda826x_priv {
-	/* i2c details */
-	int i2c_address;
-	struct i2c_adapter *i2c;
-	u8 has_loopthrough:1;
-	u32 frequency;
-};
-
-static int tda826x_release(struct dvb_frontend *fe)
-{
-	kfree(fe->tuner_priv);
-	fe->tuner_priv = NULL;
-	return 0;
-}
-
-static int tda826x_sleep(struct dvb_frontend *fe)
-{
-	struct tda826x_priv *priv = fe->tuner_priv;
-	int ret;
-	u8 buf [] = { 0x00, 0x8d };
-	struct i2c_msg msg = { .addr = priv->i2c_address, .flags = 0, .buf = buf, .len = 2 };
-
-	dprintk("%s:\n", __func__);
-
-	if (!priv->has_loopthrough)
-		buf[1] = 0xad;
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	if ((ret = i2c_transfer (priv->i2c, &msg, 1)) != 1) {
-		dprintk("%s: i2c error\n", __func__);
-	}
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0);
-
-	return (ret == 1) ? 0 : ret;
-}
-
-static int tda826x_set_params(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct tda826x_priv *priv = fe->tuner_priv;
-	int ret;
-	u32 div;
-	u32 ksyms;
-	u32 bandwidth;
-	u8 buf [11];
-	struct i2c_msg msg = { .addr = priv->i2c_address, .flags = 0, .buf = buf, .len = 11 };
-
-	dprintk("%s:\n", __func__);
-
-	div = (p->frequency + (1000-1)) / 1000;
-
-	/* BW = ((1 + RO) * SR/2 + 5) * 1.3      [SR in MSPS, BW in MHz] */
-	/* with R0 = 0.35 and some transformations: */
-	ksyms = p->symbol_rate / 1000;
-	bandwidth = (878 * ksyms + 6500000) / 1000000 + 1;
-	if (bandwidth < 5)
-		bandwidth = 5;
-	else if (bandwidth > 36)
-		bandwidth = 36;
-
-	buf[0] = 0x00; // subaddress
-	buf[1] = 0x09; // powerdown RSSI + the magic value 1
-	if (!priv->has_loopthrough)
-		buf[1] |= 0x20; // power down loopthrough if not needed
-	buf[2] = (1<<5) | 0x0b; // 1Mhz + 0.45 VCO
-	buf[3] = div >> 7;
-	buf[4] = div << 1;
-	buf[5] = ((bandwidth - 5) << 3) | 7; /* baseband cut-off */
-	buf[6] = 0xfe; // baseband gain 9 db + no RF attenuation
-	buf[7] = 0x83; // charge pumps at high, tests off
-	buf[8] = 0x80; // recommended value 4 for AMPVCO + disable ports.
-	buf[9] = 0x1a; // normal caltime + recommended values for SELTH + SELVTL
-	buf[10] = 0xd4; // recommended value 13 for BBIAS + unknown bit set on
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	if ((ret = i2c_transfer (priv->i2c, &msg, 1)) != 1) {
-		dprintk("%s: i2c error\n", __func__);
-	}
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0);
-
-	priv->frequency = div * 1000;
-
-	return (ret == 1) ? 0 : ret;
-}
-
-static int tda826x_get_frequency(struct dvb_frontend *fe, u32 *frequency)
-{
-	struct tda826x_priv *priv = fe->tuner_priv;
-	*frequency = priv->frequency;
-	return 0;
-}
-
-static struct dvb_tuner_ops tda826x_tuner_ops = {
-	.info = {
-		.name = "Philips TDA826X",
-		.frequency_min = 950000,
-		.frequency_max = 2175000
-	},
-	.release = tda826x_release,
-	.sleep = tda826x_sleep,
-	.set_params = tda826x_set_params,
-	.get_frequency = tda826x_get_frequency,
-};
-
-struct dvb_frontend *tda826x_attach(struct dvb_frontend *fe, int addr, struct i2c_adapter *i2c, int has_loopthrough)
-{
-	struct tda826x_priv *priv = NULL;
-	u8 b1 [] = { 0, 0 };
-	struct i2c_msg msg[2] = {
-		{ .addr = addr, .flags = 0,        .buf = NULL, .len = 0 },
-		{ .addr = addr, .flags = I2C_M_RD, .buf = b1, .len = 2 }
-	};
-	int ret;
-
-	dprintk("%s:\n", __func__);
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	ret = i2c_transfer (i2c, msg, 2);
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0);
-
-	if (ret != 2)
-		return NULL;
-	if (!(b1[1] & 0x80))
-		return NULL;
-
-	priv = kzalloc(sizeof(struct tda826x_priv), GFP_KERNEL);
-	if (priv == NULL)
-		return NULL;
-
-	priv->i2c_address = addr;
-	priv->i2c = i2c;
-	priv->has_loopthrough = has_loopthrough;
-
-	memcpy(&fe->ops.tuner_ops, &tda826x_tuner_ops, sizeof(struct dvb_tuner_ops));
-
-	fe->tuner_priv = priv;
-
-	return fe;
-}
-EXPORT_SYMBOL(tda826x_attach);
-
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
-
-MODULE_DESCRIPTION("DVB TDA826x driver");
-MODULE_AUTHOR("Andrew de Quincey");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/tda826x.h b/drivers/media/dvb/frontends/tda826x.h
deleted file mode 100644
index 89e9792..0000000
--- a/drivers/media/dvb/frontends/tda826x.h
+++ /dev/null
@@ -1,53 +0,0 @@
-  /*
-     Driver for Philips tda8262/tda8263 DVBS Silicon tuners
-
-     (c) 2006 Andrew de Quincey
-
-     This program is free software; you can redistribute it and/or modify
-     it under the terms of the 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_TDA826X_H__
-#define __DVB_TDA826X_H__
-
-#include <linux/i2c.h>
-#include "dvb_frontend.h"
-
-/**
- * Attach a tda826x tuner to the supplied frontend structure.
- *
- * @param fe Frontend to attach to.
- * @param addr i2c address of the tuner.
- * @param i2c i2c adapter to use.
- * @param has_loopthrough Set to 1 if the card has a loopthrough RF connector.
- * @return FE pointer on success, NULL on failure.
- */
-#if defined(CONFIG_DVB_TDA826X) || (defined(CONFIG_DVB_TDA826X_MODULE) && defined(MODULE))
-extern struct dvb_frontend* tda826x_attach(struct dvb_frontend *fe, int addr,
-					   struct i2c_adapter *i2c,
-					   int has_loopthrough);
-#else
-static inline struct dvb_frontend* tda826x_attach(struct dvb_frontend *fe,
-						  int addr,
-						  struct i2c_adapter *i2c,
-						  int has_loopthrough)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif // CONFIG_DVB_TDA826X
-
-#endif // __DVB_TDA826X_H__
diff --git a/drivers/media/dvb/frontends/tdhd1.h b/drivers/media/dvb/frontends/tdhd1.h
deleted file mode 100644
index 1775098..0000000
--- a/drivers/media/dvb/frontends/tdhd1.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * tdhd1.h - ALPS TDHD1-204A tuner support
- *
- * Copyright (C) 2008 Oliver Endriss <o.endriss@gmx.de>
- *
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * 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.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- *
- *
- * The project's page is at http://www.linuxtv.org
- */
-
-#ifndef TDHD1_H
-#define TDHD1_H
-
-#include "tda1004x.h"
-
-static int alps_tdhd1_204_request_firmware(struct dvb_frontend *fe, const struct firmware **fw, char *name);
-
-static struct tda1004x_config alps_tdhd1_204a_config = {
-	.demod_address = 0x8,
-	.invert = 1,
-	.invert_oclk = 0,
-	.xtal_freq = TDA10046_XTAL_4M,
-	.agc_config = TDA10046_AGC_DEFAULT,
-	.if_freq = TDA10046_FREQ_3617,
-	.request_firmware = alps_tdhd1_204_request_firmware
-};
-
-static int alps_tdhd1_204a_tuner_set_params(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct i2c_adapter *i2c = fe->tuner_priv;
-	u8 data[4];
-	struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
-	u32 div;
-
-	div = (p->frequency + 36166666) / 166666;
-
-	data[0] = (div >> 8) & 0x7f;
-	data[1] = div & 0xff;
-	data[2] = 0x85;
-
-	if (p->frequency >= 174000000 && p->frequency <= 230000000)
-		data[3] = 0x02;
-	else if (p->frequency >= 470000000 && p->frequency <= 823000000)
-		data[3] = 0x0C;
-	else if (p->frequency > 823000000 && p->frequency <= 862000000)
-		data[3] = 0x8C;
-	else
-		return -EINVAL;
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	if (i2c_transfer(i2c, &msg, 1) != 1)
-		return -EIO;
-
-	return 0;
-}
-
-#endif /* TDHD1_H */
diff --git a/drivers/media/dvb/frontends/tua6100.c b/drivers/media/dvb/frontends/tua6100.c
deleted file mode 100644
index 029384d..0000000
--- a/drivers/media/dvb/frontends/tua6100.c
+++ /dev/null
@@ -1,206 +0,0 @@
-/**
- * Driver for Infineon tua6100 pll.
- *
- * (c) 2006 Andrew de Quincey
- *
- * Based on code found in budget-av.c, which has the following:
- * Compiled from various sources by Michael Hunold <michael@mihu.de>
- *
- * CI interface support (c) 2004 Olivier Gournet <ogournet@anevia.com> &
- *                               Andrew de Quincey <adq_dvb@lidskialf.net>
- *
- * Copyright (C) 2002 Ralph Metzler <rjkm@metzlerbros.de>
- *
- * Copyright (C) 1999-2002 Ralph  Metzler
- *                       & Marcus Metzler for convergence integrated media GmbH
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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/slab.h>
-#include <linux/module.h>
-#include <linux/dvb/frontend.h>
-#include <asm/types.h>
-
-#include "tua6100.h"
-
-struct tua6100_priv {
-	/* i2c details */
-	int i2c_address;
-	struct i2c_adapter *i2c;
-	u32 frequency;
-};
-
-static int tua6100_release(struct dvb_frontend *fe)
-{
-	kfree(fe->tuner_priv);
-	fe->tuner_priv = NULL;
-	return 0;
-}
-
-static int tua6100_sleep(struct dvb_frontend *fe)
-{
-	struct tua6100_priv *priv = fe->tuner_priv;
-	int ret;
-	u8 reg0[] = { 0x00, 0x00 };
-	struct i2c_msg msg = { .addr = priv->i2c_address, .flags = 0, .buf = reg0, .len = 2 };
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	if ((ret = i2c_transfer (priv->i2c, &msg, 1)) != 1) {
-		printk("%s: i2c error\n", __func__);
-	}
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0);
-
-	return (ret == 1) ? 0 : ret;
-}
-
-static int tua6100_set_params(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	struct tua6100_priv *priv = fe->tuner_priv;
-	u32 div;
-	u32 prediv;
-	u8 reg0[] = { 0x00, 0x00 };
-	u8 reg1[] = { 0x01, 0x00, 0x00, 0x00 };
-	u8 reg2[] = { 0x02, 0x00, 0x00 };
-	struct i2c_msg msg0 = { .addr = priv->i2c_address, .flags = 0, .buf = reg0, .len = 2 };
-	struct i2c_msg msg1 = { .addr = priv->i2c_address, .flags = 0, .buf = reg1, .len = 4 };
-	struct i2c_msg msg2 = { .addr = priv->i2c_address, .flags = 0, .buf = reg2, .len = 3 };
-
-#define _R 4
-#define _P 32
-#define _ri 4000000
-
-	// setup register 0
-	if (c->frequency < 2000000)
-		reg0[1] = 0x03;
-	else
-		reg0[1] = 0x07;
-
-	// setup register 1
-	if (c->frequency < 1630000)
-		reg1[1] = 0x2c;
-	else
-		reg1[1] = 0x0c;
-
-	if (_P == 64)
-		reg1[1] |= 0x40;
-	if (c->frequency >= 1525000)
-		reg1[1] |= 0x80;
-
-	// register 2
-	reg2[1] = (_R >> 8) & 0x03;
-	reg2[2] = _R;
-	if (c->frequency < 1455000)
-		reg2[1] |= 0x1c;
-	else if (c->frequency < 1630000)
-		reg2[1] |= 0x0c;
-	else
-		reg2[1] |= 0x1c;
-
-	/*
-	 * The N divisor ratio (note: c->frequency is in kHz, but we
-	 * need it in Hz)
-	 */
-	prediv = (c->frequency * _R) / (_ri / 1000);
-	div = prediv / _P;
-	reg1[1] |= (div >> 9) & 0x03;
-	reg1[2] = div >> 1;
-	reg1[3] = (div << 7);
-	priv->frequency = ((div * _P) * (_ri / 1000)) / _R;
-
-	// Finally, calculate and store the value for A
-	reg1[3] |= (prediv - (div*_P)) & 0x7f;
-
-#undef _R
-#undef _P
-#undef _ri
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	if (i2c_transfer(priv->i2c, &msg0, 1) != 1)
-		return -EIO;
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	if (i2c_transfer(priv->i2c, &msg2, 1) != 1)
-		return -EIO;
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	if (i2c_transfer(priv->i2c, &msg1, 1) != 1)
-		return -EIO;
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0);
-
-	return 0;
-}
-
-static int tua6100_get_frequency(struct dvb_frontend *fe, u32 *frequency)
-{
-	struct tua6100_priv *priv = fe->tuner_priv;
-	*frequency = priv->frequency;
-	return 0;
-}
-
-static struct dvb_tuner_ops tua6100_tuner_ops = {
-	.info = {
-		.name = "Infineon TUA6100",
-		.frequency_min = 950000,
-		.frequency_max = 2150000,
-		.frequency_step = 1000,
-	},
-	.release = tua6100_release,
-	.sleep = tua6100_sleep,
-	.set_params = tua6100_set_params,
-	.get_frequency = tua6100_get_frequency,
-};
-
-struct dvb_frontend *tua6100_attach(struct dvb_frontend *fe, int addr, struct i2c_adapter *i2c)
-{
-	struct tua6100_priv *priv = NULL;
-	u8 b1 [] = { 0x80 };
-	u8 b2 [] = { 0x00 };
-	struct i2c_msg msg [] = { { .addr = addr, .flags = 0, .buf = b1, .len = 1 },
-				  { .addr = addr, .flags = I2C_M_RD, .buf = b2, .len = 1 } };
-	int ret;
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	ret = i2c_transfer (i2c, msg, 2);
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0);
-
-	if (ret != 2)
-		return NULL;
-
-	priv = kzalloc(sizeof(struct tua6100_priv), GFP_KERNEL);
-	if (priv == NULL)
-		return NULL;
-
-	priv->i2c_address = addr;
-	priv->i2c = i2c;
-
-	memcpy(&fe->ops.tuner_ops, &tua6100_tuner_ops, sizeof(struct dvb_tuner_ops));
-	fe->tuner_priv = priv;
-	return fe;
-}
-EXPORT_SYMBOL(tua6100_attach);
-
-MODULE_DESCRIPTION("DVB tua6100 driver");
-MODULE_AUTHOR("Andrew de Quincey");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/tua6100.h b/drivers/media/dvb/frontends/tua6100.h
deleted file mode 100644
index f83dbd5..0000000
--- a/drivers/media/dvb/frontends/tua6100.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/**
- * Driver for Infineon tua6100 PLL.
- *
- * (c) 2006 Andrew de Quincey
- *
- * Based on code found in budget-av.c, which has the following:
- * Compiled from various sources by Michael Hunold <michael@mihu.de>
- *
- * CI interface support (c) 2004 Olivier Gournet <ogournet@anevia.com> &
- *                               Andrew de Quincey <adq_dvb@lidskialf.net>
- *
- * Copyright (C) 2002 Ralph Metzler <rjkm@metzlerbros.de>
- *
- * Copyright (C) 1999-2002 Ralph  Metzler
- *                       & Marcus Metzler for convergence integrated media GmbH
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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_TUA6100_H__
-#define __DVB_TUA6100_H__
-
-#include <linux/i2c.h>
-#include "dvb_frontend.h"
-
-#if defined(CONFIG_DVB_TUA6100) || (defined(CONFIG_DVB_TUA6100_MODULE) && defined(MODULE))
-extern struct dvb_frontend *tua6100_attach(struct dvb_frontend *fe, int addr, struct i2c_adapter *i2c);
-#else
-static inline struct dvb_frontend* tua6100_attach(struct dvb_frontend *fe, int addr, struct i2c_adapter *i2c)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif // CONFIG_DVB_TUA6100
-
-#endif
diff --git a/drivers/media/dvb/frontends/ves1820.c b/drivers/media/dvb/frontends/ves1820.c
deleted file mode 100644
index bb42b56..0000000
--- a/drivers/media/dvb/frontends/ves1820.c
+++ /dev/null
@@ -1,447 +0,0 @@
-/*
-    VES1820  - Single Chip Cable Channel Receiver driver module
-
-    Copyright (C) 1999 Convergence Integrated Media GmbH <ralph@convergence.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/delay.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <asm/div64.h>
-
-#include "dvb_frontend.h"
-#include "ves1820.h"
-
-
-
-struct ves1820_state {
-	struct i2c_adapter* i2c;
-	/* configuration settings */
-	const struct ves1820_config* config;
-	struct dvb_frontend frontend;
-
-	/* private demodulator data */
-	u8 reg0;
-	u8 pwm;
-};
-
-
-static int verbose;
-
-static u8 ves1820_inittab[] = {
-	0x69, 0x6A, 0x93, 0x1A, 0x12, 0x46, 0x26, 0x1A,
-	0x43, 0x6A, 0xAA, 0xAA, 0x1E, 0x85, 0x43, 0x20,
-	0xE0, 0x00, 0xA1, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
-	0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x40
-};
-
-static int ves1820_writereg(struct ves1820_state *state, u8 reg, u8 data)
-{
-	u8 buf[] = { 0x00, reg, data };
-	struct i2c_msg msg = {.addr = state->config->demod_address,.flags = 0,.buf = buf,.len = 3 };
-	int ret;
-
-	ret = i2c_transfer(state->i2c, &msg, 1);
-
-	if (ret != 1)
-		printk("ves1820: %s(): writereg error (reg == 0x%02x, "
-			"val == 0x%02x, ret == %i)\n", __func__, reg, data, ret);
-
-	return (ret != 1) ? -EREMOTEIO : 0;
-}
-
-static u8 ves1820_readreg(struct ves1820_state *state, u8 reg)
-{
-	u8 b0[] = { 0x00, reg };
-	u8 b1[] = { 0 };
-	struct i2c_msg msg[] = {
-		{.addr = state->config->demod_address,.flags = 0,.buf = b0,.len = 2},
-		{.addr = state->config->demod_address,.flags = I2C_M_RD,.buf = b1,.len = 1}
-	};
-	int ret;
-
-	ret = i2c_transfer(state->i2c, msg, 2);
-
-	if (ret != 2)
-		printk("ves1820: %s(): readreg error (reg == 0x%02x, "
-		"ret == %i)\n", __func__, reg, ret);
-
-	return b1[0];
-}
-
-static int ves1820_setup_reg0(struct ves1820_state *state, u8 reg0, fe_spectral_inversion_t inversion)
-{
-	reg0 |= state->reg0 & 0x62;
-
-	if (INVERSION_ON == inversion) {
-		if (!state->config->invert) reg0 |= 0x20;
-		else reg0 &= ~0x20;
-	} else if (INVERSION_OFF == inversion) {
-		if (!state->config->invert) reg0 &= ~0x20;
-		else reg0 |= 0x20;
-	}
-
-	ves1820_writereg(state, 0x00, reg0 & 0xfe);
-	ves1820_writereg(state, 0x00, reg0 | 0x01);
-
-	state->reg0 = reg0;
-
-	return 0;
-}
-
-static int ves1820_set_symbolrate(struct ves1820_state *state, u32 symbolrate)
-{
-	s32 BDR;
-	s32 BDRI;
-	s16 SFIL = 0;
-	u16 NDEC = 0;
-	u32 ratio;
-	u32 fin;
-	u32 tmp;
-	u64 fptmp;
-	u64 fpxin;
-
-	if (symbolrate > state->config->xin / 2)
-		symbolrate = state->config->xin / 2;
-
-	if (symbolrate < 500000)
-		symbolrate = 500000;
-
-	if (symbolrate < state->config->xin / 16)
-		NDEC = 1;
-	if (symbolrate < state->config->xin / 32)
-		NDEC = 2;
-	if (symbolrate < state->config->xin / 64)
-		NDEC = 3;
-
-	/* yeuch! */
-	fpxin = state->config->xin * 10;
-	fptmp = fpxin; do_div(fptmp, 123);
-	if (symbolrate < fptmp)
-		SFIL = 1;
-	fptmp = fpxin; do_div(fptmp, 160);
-	if (symbolrate < fptmp)
-		SFIL = 0;
-	fptmp = fpxin; do_div(fptmp, 246);
-	if (symbolrate < fptmp)
-		SFIL = 1;
-	fptmp = fpxin; do_div(fptmp, 320);
-	if (symbolrate < fptmp)
-		SFIL = 0;
-	fptmp = fpxin; do_div(fptmp, 492);
-	if (symbolrate < fptmp)
-		SFIL = 1;
-	fptmp = fpxin; do_div(fptmp, 640);
-	if (symbolrate < fptmp)
-		SFIL = 0;
-	fptmp = fpxin; do_div(fptmp, 984);
-	if (symbolrate < fptmp)
-		SFIL = 1;
-
-	fin = state->config->xin >> 4;
-	symbolrate <<= NDEC;
-	ratio = (symbolrate << 4) / fin;
-	tmp = ((symbolrate << 4) % fin) << 8;
-	ratio = (ratio << 8) + tmp / fin;
-	tmp = (tmp % fin) << 8;
-	ratio = (ratio << 8) + DIV_ROUND_CLOSEST(tmp, fin);
-
-	BDR = ratio;
-	BDRI = (((state->config->xin << 5) / symbolrate) + 1) / 2;
-
-	if (BDRI > 0xFF)
-		BDRI = 0xFF;
-
-	SFIL = (SFIL << 4) | ves1820_inittab[0x0E];
-
-	NDEC = (NDEC << 6) | ves1820_inittab[0x03];
-
-	ves1820_writereg(state, 0x03, NDEC);
-	ves1820_writereg(state, 0x0a, BDR & 0xff);
-	ves1820_writereg(state, 0x0b, (BDR >> 8) & 0xff);
-	ves1820_writereg(state, 0x0c, (BDR >> 16) & 0x3f);
-
-	ves1820_writereg(state, 0x0d, BDRI);
-	ves1820_writereg(state, 0x0e, SFIL);
-
-	return 0;
-}
-
-static int ves1820_init(struct dvb_frontend* fe)
-{
-	struct ves1820_state* state = fe->demodulator_priv;
-	int i;
-
-	ves1820_writereg(state, 0, 0);
-
-	for (i = 0; i < sizeof(ves1820_inittab); i++)
-		ves1820_writereg(state, i, ves1820_inittab[i]);
-	if (state->config->selagc)
-		ves1820_writereg(state, 2, ves1820_inittab[2] | 0x08);
-
-	ves1820_writereg(state, 0x34, state->pwm);
-
-	return 0;
-}
-
-static int ves1820_set_parameters(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct ves1820_state* state = fe->demodulator_priv;
-	static const u8 reg0x00[] = { 0x00, 0x04, 0x08, 0x0c, 0x10 };
-	static const u8 reg0x01[] = { 140, 140, 106, 100, 92 };
-	static const u8 reg0x05[] = { 135, 100, 70, 54, 38 };
-	static const u8 reg0x08[] = { 162, 116, 67, 52, 35 };
-	static const u8 reg0x09[] = { 145, 150, 106, 126, 107 };
-	int real_qam = p->modulation - QAM_16;
-
-	if (real_qam < 0 || real_qam > 4)
-		return -EINVAL;
-
-	if (fe->ops.tuner_ops.set_params) {
-		fe->ops.tuner_ops.set_params(fe);
-		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
-	}
-
-	ves1820_set_symbolrate(state, p->symbol_rate);
-	ves1820_writereg(state, 0x34, state->pwm);
-
-	ves1820_writereg(state, 0x01, reg0x01[real_qam]);
-	ves1820_writereg(state, 0x05, reg0x05[real_qam]);
-	ves1820_writereg(state, 0x08, reg0x08[real_qam]);
-	ves1820_writereg(state, 0x09, reg0x09[real_qam]);
-
-	ves1820_setup_reg0(state, reg0x00[real_qam], p->inversion);
-	ves1820_writereg(state, 2, ves1820_inittab[2] | (state->config->selagc ? 0x08 : 0));
-	return 0;
-}
-
-static int ves1820_read_status(struct dvb_frontend* fe, fe_status_t* status)
-{
-	struct ves1820_state* state = fe->demodulator_priv;
-	int sync;
-
-	*status = 0;
-	sync = ves1820_readreg(state, 0x11);
-
-	if (sync & 1)
-		*status |= FE_HAS_SIGNAL;
-
-	if (sync & 2)
-		*status |= FE_HAS_CARRIER;
-
-	if (sync & 2)	/* XXX FIXME! */
-		*status |= FE_HAS_VITERBI;
-
-	if (sync & 4)
-		*status |= FE_HAS_SYNC;
-
-	if (sync & 8)
-		*status |= FE_HAS_LOCK;
-
-	return 0;
-}
-
-static int ves1820_read_ber(struct dvb_frontend* fe, u32* ber)
-{
-	struct ves1820_state* state = fe->demodulator_priv;
-
-	u32 _ber = ves1820_readreg(state, 0x14) |
-			(ves1820_readreg(state, 0x15) << 8) |
-			((ves1820_readreg(state, 0x16) & 0x0f) << 16);
-	*ber = 10 * _ber;
-
-	return 0;
-}
-
-static int ves1820_read_signal_strength(struct dvb_frontend* fe, u16* strength)
-{
-	struct ves1820_state* state = fe->demodulator_priv;
-
-	u8 gain = ves1820_readreg(state, 0x17);
-	*strength = (gain << 8) | gain;
-
-	return 0;
-}
-
-static int ves1820_read_snr(struct dvb_frontend* fe, u16* snr)
-{
-	struct ves1820_state* state = fe->demodulator_priv;
-
-	u8 quality = ~ves1820_readreg(state, 0x18);
-	*snr = (quality << 8) | quality;
-
-	return 0;
-}
-
-static int ves1820_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
-{
-	struct ves1820_state* state = fe->demodulator_priv;
-
-	*ucblocks = ves1820_readreg(state, 0x13) & 0x7f;
-	if (*ucblocks == 0x7f)
-		*ucblocks = 0xffffffff;
-
-	/* reset uncorrected block counter */
-	ves1820_writereg(state, 0x10, ves1820_inittab[0x10] & 0xdf);
-	ves1820_writereg(state, 0x10, ves1820_inittab[0x10]);
-
-	return 0;
-}
-
-static int ves1820_get_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct ves1820_state* state = fe->demodulator_priv;
-	int sync;
-	s8 afc = 0;
-
-	sync = ves1820_readreg(state, 0x11);
-	afc = ves1820_readreg(state, 0x19);
-	if (verbose) {
-		/* AFC only valid when carrier has been recovered */
-		printk(sync & 2 ? "ves1820: AFC (%d) %dHz\n" :
-			"ves1820: [AFC (%d) %dHz]\n", afc, -((s32) p->symbol_rate * afc) >> 10);
-	}
-
-	if (!state->config->invert) {
-		p->inversion = (state->reg0 & 0x20) ? INVERSION_ON : INVERSION_OFF;
-	} else {
-		p->inversion = (!(state->reg0 & 0x20)) ? INVERSION_ON : INVERSION_OFF;
-	}
-
-	p->modulation = ((state->reg0 >> 2) & 7) + QAM_16;
-
-	p->fec_inner = FEC_NONE;
-
-	p->frequency = ((p->frequency + 31250) / 62500) * 62500;
-	if (sync & 2)
-		p->frequency -= ((s32) p->symbol_rate * afc) >> 10;
-
-	return 0;
-}
-
-static int ves1820_sleep(struct dvb_frontend* fe)
-{
-	struct ves1820_state* state = fe->demodulator_priv;
-
-	ves1820_writereg(state, 0x1b, 0x02);	/* pdown ADC */
-	ves1820_writereg(state, 0x00, 0x80);	/* standby */
-
-	return 0;
-}
-
-static int ves1820_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings)
-{
-
-	fesettings->min_delay_ms = 200;
-	fesettings->step_size = 0;
-	fesettings->max_drift = 0;
-	return 0;
-}
-
-static void ves1820_release(struct dvb_frontend* fe)
-{
-	struct ves1820_state* state = fe->demodulator_priv;
-	kfree(state);
-}
-
-static struct dvb_frontend_ops ves1820_ops;
-
-struct dvb_frontend* ves1820_attach(const struct ves1820_config* config,
-				    struct i2c_adapter* i2c,
-				    u8 pwm)
-{
-	struct ves1820_state* state = NULL;
-
-	/* allocate memory for the internal state */
-	state = kzalloc(sizeof(struct ves1820_state), GFP_KERNEL);
-	if (state == NULL)
-		goto error;
-
-	/* setup the state */
-	state->reg0 = ves1820_inittab[0];
-	state->config = config;
-	state->i2c = i2c;
-	state->pwm = pwm;
-
-	/* check if the demod is there */
-	if ((ves1820_readreg(state, 0x1a) & 0xf0) != 0x70)
-		goto error;
-
-	if (verbose)
-		printk("ves1820: pwm=0x%02x\n", state->pwm);
-
-	/* create dvb_frontend */
-	memcpy(&state->frontend.ops, &ves1820_ops, sizeof(struct dvb_frontend_ops));
-	state->frontend.ops.info.symbol_rate_min = (state->config->xin / 2) / 64;      /* SACLK/64 == (XIN/2)/64 */
-	state->frontend.ops.info.symbol_rate_max = (state->config->xin / 2) / 4;       /* SACLK/4 */
-	state->frontend.demodulator_priv = state;
-
-	return &state->frontend;
-
-error:
-	kfree(state);
-	return NULL;
-}
-
-static struct dvb_frontend_ops ves1820_ops = {
-	.delsys = { SYS_DVBC_ANNEX_A },
-	.info = {
-		.name = "VLSI VES1820 DVB-C",
-		.frequency_stepsize = 62500,
-		.frequency_min = 47000000,
-		.frequency_max = 862000000,
-		.caps = FE_CAN_QAM_16 |
-			FE_CAN_QAM_32 |
-			FE_CAN_QAM_64 |
-			FE_CAN_QAM_128 |
-			FE_CAN_QAM_256 |
-			FE_CAN_FEC_AUTO
-	},
-
-	.release = ves1820_release,
-
-	.init = ves1820_init,
-	.sleep = ves1820_sleep,
-
-	.set_frontend = ves1820_set_parameters,
-	.get_frontend = ves1820_get_frontend,
-	.get_tune_settings = ves1820_get_tune_settings,
-
-	.read_status = ves1820_read_status,
-	.read_ber = ves1820_read_ber,
-	.read_signal_strength = ves1820_read_signal_strength,
-	.read_snr = ves1820_read_snr,
-	.read_ucblocks = ves1820_read_ucblocks,
-};
-
-module_param(verbose, int, 0644);
-MODULE_PARM_DESC(verbose, "print AFC offset after tuning for debugging the PWM setting");
-
-MODULE_DESCRIPTION("VLSI VES1820 DVB-C Demodulator driver");
-MODULE_AUTHOR("Ralph Metzler, Holger Waechtler");
-MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(ves1820_attach);
diff --git a/drivers/media/dvb/frontends/ves1820.h b/drivers/media/dvb/frontends/ves1820.h
deleted file mode 100644
index e902ed6..0000000
--- a/drivers/media/dvb/frontends/ves1820.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
-    VES1820  - Single Chip Cable Channel Receiver driver module
-
-    Copyright (C) 1999 Convergence Integrated Media GmbH <ralph@convergence.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 VES1820_H
-#define VES1820_H
-
-#include <linux/dvb/frontend.h>
-
-#define VES1820_SELAGC_PWM 0
-#define VES1820_SELAGC_SIGNAMPERR 1
-
-struct ves1820_config
-{
-	/* the demodulator's i2c address */
-	u8 demod_address;
-
-	/* value of XIN to use */
-	u32 xin;
-
-	/* does inversion need inverted? */
-	u8 invert:1;
-
-	/* SELAGC control */
-	u8 selagc:1;
-};
-
-#if defined(CONFIG_DVB_VES1820) || (defined(CONFIG_DVB_VES1820_MODULE) && defined(MODULE))
-extern struct dvb_frontend* ves1820_attach(const struct ves1820_config* config,
-					   struct i2c_adapter* i2c, u8 pwm);
-#else
-static inline struct dvb_frontend* ves1820_attach(const struct ves1820_config* config,
-					   struct i2c_adapter* i2c, u8 pwm)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif // CONFIG_DVB_VES1820
-
-#endif // VES1820_H
diff --git a/drivers/media/dvb/frontends/ves1x93.c b/drivers/media/dvb/frontends/ves1x93.c
deleted file mode 100644
index 9c17eac..0000000
--- a/drivers/media/dvb/frontends/ves1x93.c
+++ /dev/null
@@ -1,553 +0,0 @@
-/*
-    Driver for VES1893 and VES1993 QPSK Demodulators
-
-    Copyright (C) 1999 Convergence Integrated Media GmbH <ralph@convergence.de>
-    Copyright (C) 2001 Ronny Strutz <3des@elitedvb.de>
-    Copyright (C) 2002 Dennis Noermann <dennis.noermann@noernet.de>
-    Copyright (C) 2002-2003 Andreas Oberritter <obi@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/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-
-#include "dvb_frontend.h"
-#include "ves1x93.h"
-
-
-struct ves1x93_state {
-	struct i2c_adapter* i2c;
-	/* configuration settings */
-	const struct ves1x93_config* config;
-	struct dvb_frontend frontend;
-
-	/* previous uncorrected block counter */
-	fe_spectral_inversion_t inversion;
-	u8 *init_1x93_tab;
-	u8 *init_1x93_wtab;
-	u8 tab_size;
-	u8 demod_type;
-	u32 frequency;
-};
-
-static int debug;
-#define dprintk	if (debug) printk
-
-#define DEMOD_VES1893		0
-#define DEMOD_VES1993		1
-
-static u8 init_1893_tab [] = {
-	0x01, 0xa4, 0x35, 0x80, 0x2a, 0x0b, 0x55, 0xc4,
-	0x09, 0x69, 0x00, 0x86, 0x4c, 0x28, 0x7f, 0x00,
-	0x00, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x80, 0x00, 0x21, 0xb0, 0x14, 0x00, 0xdc, 0x00,
-	0x81, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x55, 0x00, 0x00, 0x7f, 0x00
-};
-
-static u8 init_1993_tab [] = {
-	0x00, 0x9c, 0x35, 0x80, 0x6a, 0x09, 0x72, 0x8c,
-	0x09, 0x6b, 0x00, 0x00, 0x4c, 0x08, 0x00, 0x00,
-	0x00, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x80, 0x40, 0x21, 0xb0, 0x00, 0x00, 0x00, 0x10,
-	0x81, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x55, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03,
-	0x00, 0x00, 0x0e, 0x80, 0x00
-};
-
-static u8 init_1893_wtab[] =
-{
-	1,1,1,1,1,1,1,1, 1,1,0,0,1,1,0,0,
-	0,1,0,0,0,0,0,0, 1,0,1,1,0,0,0,1,
-	1,1,1,0,0,0,0,0, 0,0,1,1,0,0,0,0,
-	1,1,1,0,1,1
-};
-
-static u8 init_1993_wtab[] =
-{
-	1,1,1,1,1,1,1,1, 1,1,0,0,1,1,0,0,
-	0,1,0,0,0,0,0,0, 1,1,1,1,0,0,0,1,
-	1,1,1,0,0,0,0,0, 0,0,1,1,0,0,0,0,
-	1,1,1,0,1,1,1,1, 1,1,1,1,1
-};
-
-static int ves1x93_writereg (struct ves1x93_state* state, u8 reg, u8 data)
-{
-	u8 buf [] = { 0x00, reg, data };
-	struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 3 };
-	int err;
-
-	if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
-		dprintk ("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __func__, err, reg, data);
-		return -EREMOTEIO;
-	}
-
-	return 0;
-}
-
-static u8 ves1x93_readreg (struct ves1x93_state* state, u8 reg)
-{
-	int ret;
-	u8 b0 [] = { 0x00, reg };
-	u8 b1 [] = { 0 };
-	struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 2 },
-			   { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } };
-
-	ret = i2c_transfer (state->i2c, msg, 2);
-
-	if (ret != 2) return ret;
-
-	return b1[0];
-}
-
-static int ves1x93_clr_bit (struct ves1x93_state* state)
-{
-	msleep(10);
-	ves1x93_writereg (state, 0, state->init_1x93_tab[0] & 0xfe);
-	ves1x93_writereg (state, 0, state->init_1x93_tab[0]);
-	msleep(50);
-	return 0;
-}
-
-static int ves1x93_set_inversion (struct ves1x93_state* state, fe_spectral_inversion_t inversion)
-{
-	u8 val;
-
-	/*
-	 * inversion on/off are interchanged because i and q seem to
-	 * be swapped on the hardware
-	 */
-
-	switch (inversion) {
-	case INVERSION_OFF:
-		val = 0xc0;
-		break;
-	case INVERSION_ON:
-		val = 0x80;
-		break;
-	case INVERSION_AUTO:
-		val = 0x00;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return ves1x93_writereg (state, 0x0c, (state->init_1x93_tab[0x0c] & 0x3f) | val);
-}
-
-static int ves1x93_set_fec (struct ves1x93_state* state, fe_code_rate_t fec)
-{
-	if (fec == FEC_AUTO)
-		return ves1x93_writereg (state, 0x0d, 0x08);
-	else if (fec < FEC_1_2 || fec > FEC_8_9)
-		return -EINVAL;
-	else
-		return ves1x93_writereg (state, 0x0d, fec - FEC_1_2);
-}
-
-static fe_code_rate_t ves1x93_get_fec (struct ves1x93_state* state)
-{
-	return FEC_1_2 + ((ves1x93_readreg (state, 0x0d) >> 4) & 0x7);
-}
-
-static int ves1x93_set_symbolrate (struct ves1x93_state* state, u32 srate)
-{
-	u32 BDR;
-	u32 ratio;
-	u8  ADCONF, FCONF, FNR, AGCR;
-	u32 BDRI;
-	u32 tmp;
-	u32 FIN;
-
-	dprintk("%s: srate == %d\n", __func__, (unsigned int) srate);
-
-	if (srate > state->config->xin/2)
-		srate = state->config->xin/2;
-
-	if (srate < 500000)
-		srate = 500000;
-
-#define MUL (1UL<<26)
-
-	FIN = (state->config->xin + 6000) >> 4;
-
-	tmp = srate << 6;
-	ratio = tmp / FIN;
-
-	tmp = (tmp % FIN) << 8;
-	ratio = (ratio << 8) + tmp / FIN;
-
-	tmp = (tmp % FIN) << 8;
-	ratio = (ratio << 8) + tmp / FIN;
-
-	FNR = 0xff;
-
-	if (ratio < MUL/3)	     FNR = 0;
-	if (ratio < (MUL*11)/50)     FNR = 1;
-	if (ratio < MUL/6)	     FNR = 2;
-	if (ratio < MUL/9)	     FNR = 3;
-	if (ratio < MUL/12)	     FNR = 4;
-	if (ratio < (MUL*11)/200)    FNR = 5;
-	if (ratio < MUL/24)	     FNR = 6;
-	if (ratio < (MUL*27)/1000)   FNR = 7;
-	if (ratio < MUL/48)	     FNR = 8;
-	if (ratio < (MUL*137)/10000) FNR = 9;
-
-	if (FNR == 0xff) {
-		ADCONF = 0x89;
-		FCONF  = 0x80;
-		FNR	= 0;
-	} else {
-		ADCONF = 0x81;
-		FCONF  = 0x88 | (FNR >> 1) | ((FNR & 0x01) << 5);
-		/*FCONF	 = 0x80 | ((FNR & 0x01) << 5) | (((FNR > 1) & 0x03) << 3) | ((FNR >> 1) & 0x07);*/
-	}
-
-	BDR = (( (ratio << (FNR >> 1)) >> 4) + 1) >> 1;
-	BDRI = ( ((FIN << 8) / ((srate << (FNR >> 1)) >> 2)) + 1) >> 1;
-
-	dprintk("FNR= %d\n", FNR);
-	dprintk("ratio= %08x\n", (unsigned int) ratio);
-	dprintk("BDR= %08x\n", (unsigned int) BDR);
-	dprintk("BDRI= %02x\n", (unsigned int) BDRI);
-
-	if (BDRI > 0xff)
-		BDRI = 0xff;
-
-	ves1x93_writereg (state, 0x06, 0xff & BDR);
-	ves1x93_writereg (state, 0x07, 0xff & (BDR >> 8));
-	ves1x93_writereg (state, 0x08, 0x0f & (BDR >> 16));
-
-	ves1x93_writereg (state, 0x09, BDRI);
-	ves1x93_writereg (state, 0x20, ADCONF);
-	ves1x93_writereg (state, 0x21, FCONF);
-
-	AGCR = state->init_1x93_tab[0x05];
-	if (state->config->invert_pwm)
-		AGCR |= 0x20;
-
-	if (srate < 6000000)
-		AGCR |= 0x80;
-	else
-		AGCR &= ~0x80;
-
-	ves1x93_writereg (state, 0x05, AGCR);
-
-	/* ves1993 hates this, will lose lock */
-	if (state->demod_type != DEMOD_VES1993)
-		ves1x93_clr_bit (state);
-
-	return 0;
-}
-
-static int ves1x93_init (struct dvb_frontend* fe)
-{
-	struct ves1x93_state* state = fe->demodulator_priv;
-	int i;
-	int val;
-
-	dprintk("%s: init chip\n", __func__);
-
-	for (i = 0; i < state->tab_size; i++) {
-		if (state->init_1x93_wtab[i]) {
-			val = state->init_1x93_tab[i];
-
-			if (state->config->invert_pwm && (i == 0x05)) val |= 0x20; /* invert PWM */
-			ves1x93_writereg (state, i, val);
-		}
-	}
-
-	return 0;
-}
-
-static int ves1x93_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltage)
-{
-	struct ves1x93_state* state = fe->demodulator_priv;
-
-	switch (voltage) {
-	case SEC_VOLTAGE_13:
-		return ves1x93_writereg (state, 0x1f, 0x20);
-	case SEC_VOLTAGE_18:
-		return ves1x93_writereg (state, 0x1f, 0x30);
-	case SEC_VOLTAGE_OFF:
-		return ves1x93_writereg (state, 0x1f, 0x00);
-	default:
-		return -EINVAL;
-	}
-}
-
-static int ves1x93_read_status(struct dvb_frontend* fe, fe_status_t* status)
-{
-	struct ves1x93_state* state = fe->demodulator_priv;
-
-	u8 sync = ves1x93_readreg (state, 0x0e);
-
-	/*
-	 * The ves1893 sometimes returns sync values that make no sense,
-	 * because, e.g., the SIGNAL bit is 0, while some of the higher
-	 * bits are 1 (and how can there be a CARRIER w/o a SIGNAL?).
-	 * Tests showed that the VITERBI and SYNC bits are returned
-	 * reliably, while the SIGNAL and CARRIER bits ar sometimes wrong.
-	 * If such a case occurs, we read the value again, until we get a
-	 * valid value.
-	 */
-	int maxtry = 10; /* just for safety - let's not get stuck here */
-	while ((sync & 0x03) != 0x03 && (sync & 0x0c) && maxtry--) {
-		msleep(10);
-		sync = ves1x93_readreg (state, 0x0e);
-	}
-
-	*status = 0;
-
-	if (sync & 1)
-		*status |= FE_HAS_SIGNAL;
-
-	if (sync & 2)
-		*status |= FE_HAS_CARRIER;
-
-	if (sync & 4)
-		*status |= FE_HAS_VITERBI;
-
-	if (sync & 8)
-		*status |= FE_HAS_SYNC;
-
-	if ((sync & 0x1f) == 0x1f)
-		*status |= FE_HAS_LOCK;
-
-	return 0;
-}
-
-static int ves1x93_read_ber(struct dvb_frontend* fe, u32* ber)
-{
-	struct ves1x93_state* state = fe->demodulator_priv;
-
-	*ber = ves1x93_readreg (state, 0x15);
-	*ber |= (ves1x93_readreg (state, 0x16) << 8);
-	*ber |= ((ves1x93_readreg (state, 0x17) & 0x0F) << 16);
-	*ber *= 10;
-
-	return 0;
-}
-
-static int ves1x93_read_signal_strength(struct dvb_frontend* fe, u16* strength)
-{
-	struct ves1x93_state* state = fe->demodulator_priv;
-
-	u8 signal = ~ves1x93_readreg (state, 0x0b);
-	*strength = (signal << 8) | signal;
-
-	return 0;
-}
-
-static int ves1x93_read_snr(struct dvb_frontend* fe, u16* snr)
-{
-	struct ves1x93_state* state = fe->demodulator_priv;
-
-	u8 _snr = ~ves1x93_readreg (state, 0x1c);
-	*snr = (_snr << 8) | _snr;
-
-	return 0;
-}
-
-static int ves1x93_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
-{
-	struct ves1x93_state* state = fe->demodulator_priv;
-
-	*ucblocks = ves1x93_readreg (state, 0x18) & 0x7f;
-
-	if (*ucblocks == 0x7f)
-		*ucblocks = 0xffffffff;   /* counter overflow... */
-
-	ves1x93_writereg (state, 0x18, 0x00);  /* reset the counter */
-	ves1x93_writereg (state, 0x18, 0x80);  /* dto. */
-
-	return 0;
-}
-
-static int ves1x93_set_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct ves1x93_state* state = fe->demodulator_priv;
-
-	if (fe->ops.tuner_ops.set_params) {
-		fe->ops.tuner_ops.set_params(fe);
-		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
-	}
-	ves1x93_set_inversion (state, p->inversion);
-	ves1x93_set_fec(state, p->fec_inner);
-	ves1x93_set_symbolrate(state, p->symbol_rate);
-	state->inversion = p->inversion;
-	state->frequency = p->frequency;
-
-	return 0;
-}
-
-static int ves1x93_get_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct ves1x93_state* state = fe->demodulator_priv;
-	int afc;
-
-	afc = ((int)((char)(ves1x93_readreg (state, 0x0a) << 1)))/2;
-	afc = (afc * (int)(p->symbol_rate/1000/8))/16;
-
-	p->frequency = state->frequency - afc;
-
-	/*
-	 * inversion indicator is only valid
-	 * if auto inversion was used
-	 */
-	if (state->inversion == INVERSION_AUTO)
-		p->inversion = (ves1x93_readreg (state, 0x0f) & 2) ?
-				INVERSION_OFF : INVERSION_ON;
-	p->fec_inner = ves1x93_get_fec(state);
-	/*  XXX FIXME: timing offset !! */
-
-	return 0;
-}
-
-static int ves1x93_sleep(struct dvb_frontend* fe)
-{
-	struct ves1x93_state* state = fe->demodulator_priv;
-
-	return ves1x93_writereg (state, 0x00, 0x08);
-}
-
-static void ves1x93_release(struct dvb_frontend* fe)
-{
-	struct ves1x93_state* state = fe->demodulator_priv;
-	kfree(state);
-}
-
-static int ves1x93_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
-{
-	struct ves1x93_state* state = fe->demodulator_priv;
-
-	if (enable) {
-		return ves1x93_writereg(state, 0x00, 0x11);
-	} else {
-		return ves1x93_writereg(state, 0x00, 0x01);
-	}
-}
-
-static struct dvb_frontend_ops ves1x93_ops;
-
-struct dvb_frontend* ves1x93_attach(const struct ves1x93_config* config,
-				    struct i2c_adapter* i2c)
-{
-	struct ves1x93_state* state = NULL;
-	u8 identity;
-
-	/* allocate memory for the internal state */
-	state = kzalloc(sizeof(struct ves1x93_state), GFP_KERNEL);
-	if (state == NULL) goto error;
-
-	/* setup the state */
-	state->config = config;
-	state->i2c = i2c;
-	state->inversion = INVERSION_OFF;
-
-	/* check if the demod is there + identify it */
-	identity = ves1x93_readreg(state, 0x1e);
-	switch (identity) {
-	case 0xdc: /* VES1893A rev1 */
-		printk("ves1x93: Detected ves1893a rev1\n");
-		state->demod_type = DEMOD_VES1893;
-		state->init_1x93_tab = init_1893_tab;
-		state->init_1x93_wtab = init_1893_wtab;
-		state->tab_size = sizeof(init_1893_tab);
-		break;
-
-	case 0xdd: /* VES1893A rev2 */
-		printk("ves1x93: Detected ves1893a rev2\n");
-		state->demod_type = DEMOD_VES1893;
-		state->init_1x93_tab = init_1893_tab;
-		state->init_1x93_wtab = init_1893_wtab;
-		state->tab_size = sizeof(init_1893_tab);
-		break;
-
-	case 0xde: /* VES1993 */
-		printk("ves1x93: Detected ves1993\n");
-		state->demod_type = DEMOD_VES1993;
-		state->init_1x93_tab = init_1993_tab;
-		state->init_1x93_wtab = init_1993_wtab;
-		state->tab_size = sizeof(init_1993_tab);
-		break;
-
-	default:
-		goto error;
-	}
-
-	/* create dvb_frontend */
-	memcpy(&state->frontend.ops, &ves1x93_ops, sizeof(struct dvb_frontend_ops));
-	state->frontend.demodulator_priv = state;
-	return &state->frontend;
-
-error:
-	kfree(state);
-	return NULL;
-}
-
-static struct dvb_frontend_ops ves1x93_ops = {
-	.delsys = { SYS_DVBS },
-	.info = {
-		.name			= "VLSI VES1x93 DVB-S",
-		.frequency_min		= 950000,
-		.frequency_max		= 2150000,
-		.frequency_stepsize	= 125,		 /* kHz for QPSK frontends */
-		.frequency_tolerance	= 29500,
-		.symbol_rate_min	= 1000000,
-		.symbol_rate_max	= 45000000,
-	/*	.symbol_rate_tolerance	=	???,*/
-		.caps = FE_CAN_INVERSION_AUTO |
-			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_FEC_AUTO |
-			FE_CAN_QPSK
-	},
-
-	.release = ves1x93_release,
-
-	.init = ves1x93_init,
-	.sleep = ves1x93_sleep,
-	.i2c_gate_ctrl = ves1x93_i2c_gate_ctrl,
-
-	.set_frontend = ves1x93_set_frontend,
-	.get_frontend = ves1x93_get_frontend,
-
-	.read_status = ves1x93_read_status,
-	.read_ber = ves1x93_read_ber,
-	.read_signal_strength = ves1x93_read_signal_strength,
-	.read_snr = ves1x93_read_snr,
-	.read_ucblocks = ves1x93_read_ucblocks,
-
-	.set_voltage = ves1x93_set_voltage,
-};
-
-module_param(debug, int, 0644);
-
-MODULE_DESCRIPTION("VLSI VES1x93 DVB-S Demodulator driver");
-MODULE_AUTHOR("Ralph Metzler");
-MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(ves1x93_attach);
diff --git a/drivers/media/dvb/frontends/ves1x93.h b/drivers/media/dvb/frontends/ves1x93.h
deleted file mode 100644
index 8a5a49e..0000000
--- a/drivers/media/dvb/frontends/ves1x93.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
-    Driver for VES1893 and VES1993 QPSK Demodulators
-
-    Copyright (C) 1999 Convergence Integrated Media GmbH <ralph@convergence.de>
-    Copyright (C) 2001 Ronny Strutz <3des@elitedvb.de>
-    Copyright (C) 2002 Dennis Noermann <dennis.noermann@noernet.de>
-    Copyright (C) 2002-2003 Andreas Oberritter <obi@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 VES1X93_H
-#define VES1X93_H
-
-#include <linux/dvb/frontend.h>
-
-struct ves1x93_config
-{
-	/* the demodulator's i2c address */
-	u8 demod_address;
-
-	/* value of XIN to use */
-	u32 xin;
-
-	/* should PWM be inverted? */
-	u8 invert_pwm:1;
-};
-
-#if defined(CONFIG_DVB_VES1X93) || (defined(CONFIG_DVB_VES1X93_MODULE) && defined(MODULE))
-extern struct dvb_frontend* ves1x93_attach(const struct ves1x93_config* config,
-					   struct i2c_adapter* i2c);
-#else
-static inline struct dvb_frontend* ves1x93_attach(const struct ves1x93_config* config,
-					   struct i2c_adapter* i2c)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif // CONFIG_DVB_VES1X93
-
-#endif // VES1X93_H
diff --git a/drivers/media/dvb/frontends/z0194a.h b/drivers/media/dvb/frontends/z0194a.h
deleted file mode 100644
index 96d86d6..0000000
--- a/drivers/media/dvb/frontends/z0194a.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/* z0194a.h Sharp z0194a tuner support
-*
-* Copyright (C) 2008 Igor M. Liplianin (liplianin@me.by)
-*
-*	This program is free software; 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.
-*
-* see Documentation/dvb/README.dvb-usb for more information
-*/
-
-#ifndef Z0194A
-#define Z0194A
-
-static int sharp_z0194a_set_symbol_rate(struct dvb_frontend *fe,
-					 u32 srate, u32 ratio)
-{
-	u8 aclk = 0;
-	u8 bclk = 0;
-
-	if (srate < 1500000) {
-		aclk = 0xb7; bclk = 0x47; }
-	else if (srate < 3000000) {
-		aclk = 0xb7; bclk = 0x4b; }
-	else if (srate < 7000000) {
-		aclk = 0xb7; bclk = 0x4f; }
-	else if (srate < 14000000) {
-		aclk = 0xb7; bclk = 0x53; }
-	else if (srate < 30000000) {
-		aclk = 0xb6; bclk = 0x53; }
-	else if (srate < 45000000) {
-		aclk = 0xb4; bclk = 0x51; }
-
-	stv0299_writereg(fe, 0x13, aclk);
-	stv0299_writereg(fe, 0x14, bclk);
-	stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
-	stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff);
-	stv0299_writereg(fe, 0x21, (ratio) & 0xf0);
-
-	return 0;
-}
-
-static u8 sharp_z0194a_inittab[] = {
-	0x01, 0x15,
-	0x02, 0x30,
-	0x03, 0x00,
-	0x04, 0x7d,   /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */
-	0x05, 0x35,   /* I2CT = 0, SCLT = 1, SDAT = 1 */
-	0x06, 0x40,   /* DAC not used, set to high impendance mode */
-	0x07, 0x00,   /* DAC LSB */
-	0x08, 0x40,   /* DiSEqC off, LNB power on OP2/LOCK pin on */
-	0x09, 0x00,   /* FIFO */
-	0x0c, 0x51,   /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */
-	0x0d, 0x82,   /* DC offset compensation = ON, beta_agc1 = 2 */
-	0x0e, 0x23,   /* alpha_tmg = 2, beta_tmg = 3 */
-	0x10, 0x3f,   /* AGC2  0x3d */
-	0x11, 0x84,
-	0x12, 0xb9,
-	0x15, 0xc9,   /* lock detector threshold */
-	0x16, 0x00,
-	0x17, 0x00,
-	0x18, 0x00,
-	0x19, 0x00,
-	0x1a, 0x00,
-	0x1f, 0x50,
-	0x20, 0x00,
-	0x21, 0x00,
-	0x22, 0x00,
-	0x23, 0x00,
-	0x28, 0x00,  /* out imp: normal  out type: parallel FEC mode:0 */
-	0x29, 0x1e,  /* 1/2 threshold */
-	0x2a, 0x14,  /* 2/3 threshold */
-	0x2b, 0x0f,  /* 3/4 threshold */
-	0x2c, 0x09,  /* 5/6 threshold */
-	0x2d, 0x05,  /* 7/8 threshold */
-	0x2e, 0x01,
-	0x31, 0x1f,  /* test all FECs */
-	0x32, 0x19,  /* viterbi and synchro search */
-	0x33, 0xfc,  /* rs control */
-	0x34, 0x93,  /* error control */
-	0x0f, 0x52,
-	0xff, 0xff
-};
-
-#endif
diff --git a/drivers/media/dvb/frontends/zl10036.c b/drivers/media/dvb/frontends/zl10036.c
deleted file mode 100644
index 0903d46..0000000
--- a/drivers/media/dvb/frontends/zl10036.c
+++ /dev/null
@@ -1,520 +0,0 @@
-/**
- * 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 <linux/slab.h>
-#include <linux/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 dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct zl10036_state *state = fe->tuner_priv;
-	int ret = 0;
-	u32 frequency = p->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 * p->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, p->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][0] |= 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;
-	int ret;
-
-	if (!config) {
-		printk(KERN_ERR "%s: no config specified", __func__);
-		return NULL;
-	}
-
-	state = kzalloc(sizeof(struct zl10036_state), GFP_KERNEL);
-	if (!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:
-	kfree(state);
-	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
deleted file mode 100644
index d84b8f8..0000000
--- a/drivers/media/dvb/frontends/zl10036.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/**
- * 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/zl10039.c b/drivers/media/dvb/frontends/zl10039.c
deleted file mode 100644
index eff9c5f..0000000
--- a/drivers/media/dvb/frontends/zl10039.c
+++ /dev/null
@@ -1,307 +0,0 @@
-/*
- *  Driver for Zarlink ZL10039 DVB-S tuner
- *
- *  Copyright 2007 Jan D. Louw <jd.louw@mweb.co.za>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the 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/init.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/dvb/frontend.h>
-
-#include "dvb_frontend.h"
-#include "zl10039.h"
-
-static int debug;
-
-#define dprintk(args...) \
-	do { \
-		if (debug) \
-			printk(KERN_DEBUG args); \
-	} while (0)
-
-enum zl10039_model_id {
-	ID_ZL10039 = 1
-};
-
-struct zl10039_state {
-	struct i2c_adapter *i2c;
-	u8 i2c_addr;
-	u8 id;
-};
-
-enum zl10039_reg_addr {
-	PLL0 = 0,
-	PLL1,
-	PLL2,
-	PLL3,
-	RFFE,
-	BASE0,
-	BASE1,
-	BASE2,
-	LO0,
-	LO1,
-	LO2,
-	LO3,
-	LO4,
-	LO5,
-	LO6,
-	GENERAL
-};
-
-static int zl10039_read(const struct zl10039_state *state,
-			const enum zl10039_reg_addr reg, u8 *buf,
-			const size_t count)
-{
-	u8 regbuf[] = { reg };
-	struct i2c_msg msg[] = {
-		{/* Write register address */
-			.addr = state->i2c_addr,
-			.flags = 0,
-			.buf = regbuf,
-			.len = 1,
-		}, {/* Read count bytes */
-			.addr = state->i2c_addr,
-			.flags = I2C_M_RD,
-			.buf = buf,
-			.len = count,
-		},
-	};
-
-	dprintk("%s\n", __func__);
-
-	if (i2c_transfer(state->i2c, msg, 2) != 2) {
-		dprintk("%s: i2c read error\n", __func__);
-		return -EREMOTEIO;
-	}
-
-	return 0; /* Success */
-}
-
-static int zl10039_write(struct zl10039_state *state,
-			const enum zl10039_reg_addr reg, const u8 *src,
-			const size_t count)
-{
-	u8 buf[count + 1];
-	struct i2c_msg msg = {
-		.addr = state->i2c_addr,
-		.flags = 0,
-		.buf = buf,
-		.len = count + 1,
-	};
-
-	dprintk("%s\n", __func__);
-	/* Write register address and data in one go */
-	buf[0] = reg;
-	memcpy(&buf[1], src, count);
-	if (i2c_transfer(state->i2c, &msg, 1) != 1) {
-		dprintk("%s: i2c write error\n", __func__);
-		return -EREMOTEIO;
-	}
-
-	return 0; /* Success */
-}
-
-static inline int zl10039_readreg(struct zl10039_state *state,
-				const enum zl10039_reg_addr reg, u8 *val)
-{
-	return zl10039_read(state, reg, val, 1);
-}
-
-static inline int zl10039_writereg(struct zl10039_state *state,
-				const enum zl10039_reg_addr reg,
-				const u8 val)
-{
-	return zl10039_write(state, reg, &val, 1);
-}
-
-static int zl10039_init(struct dvb_frontend *fe)
-{
-	struct zl10039_state *state = fe->tuner_priv;
-	int ret;
-
-	dprintk("%s\n", __func__);
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	/* Reset logic */
-	ret = zl10039_writereg(state, GENERAL, 0x40);
-	if (ret < 0) {
-		dprintk("Note: i2c write error normal when resetting the "
-			"tuner\n");
-	}
-	/* Wake up */
-	ret = zl10039_writereg(state, GENERAL, 0x01);
-	if (ret < 0) {
-		dprintk("Tuner power up failed\n");
-		return ret;
-	}
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0);
-
-	return 0;
-}
-
-static int zl10039_sleep(struct dvb_frontend *fe)
-{
-	struct zl10039_state *state = fe->tuner_priv;
-	int ret;
-
-	dprintk("%s\n", __func__);
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	ret = zl10039_writereg(state, GENERAL, 0x80);
-	if (ret < 0) {
-		dprintk("Tuner sleep failed\n");
-		return ret;
-	}
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0);
-
-	return 0;
-}
-
-static int zl10039_set_params(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	struct zl10039_state *state = fe->tuner_priv;
-	u8 buf[6];
-	u8 bf;
-	u32 fbw;
-	u32 div;
-	int ret;
-
-	dprintk("%s\n", __func__);
-	dprintk("Set frequency = %d, symbol rate = %d\n",
-			c->frequency, c->symbol_rate);
-
-	/* Assumed 10.111 MHz crystal oscillator */
-	/* Cancelled num/den 80 to prevent overflow */
-	div = (c->frequency * 1000) / 126387;
-	fbw = (c->symbol_rate * 27) / 32000;
-	/* Cancelled num/den 10 to prevent overflow */
-	bf = ((fbw * 5088) / 1011100) - 1;
-
-	/*PLL divider*/
-	buf[0] = (div >> 8) & 0x7f;
-	buf[1] = (div >> 0) & 0xff;
-	/*Reference divider*/
-	/* Select reference ratio of 80 */
-	buf[2] = 0x1D;
-	/*PLL test modes*/
-	buf[3] = 0x40;
-	/*RF Control register*/
-	buf[4] = 0x6E; /* Bypass enable */
-	/*Baseband filter cutoff */
-	buf[5] = bf;
-
-	/* Open i2c gate */
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	/* BR = 10, Enable filter adjustment */
-	ret = zl10039_writereg(state, BASE1, 0x0A);
-	if (ret < 0)
-		goto error;
-	/* Write new config values */
-	ret = zl10039_write(state, PLL0, buf, sizeof(buf));
-	if (ret < 0)
-		goto error;
-	/* BR = 10, Disable filter adjustment */
-	ret = zl10039_writereg(state, BASE1, 0x6A);
-	if (ret < 0)
-		goto error;
-
-	/* Close i2c gate */
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0);
-	return 0;
-error:
-	dprintk("Error setting tuner\n");
-	return ret;
-}
-
-static int zl10039_release(struct dvb_frontend *fe)
-{
-	struct zl10039_state *state = fe->tuner_priv;
-
-	dprintk("%s\n", __func__);
-	kfree(state);
-	fe->tuner_priv = NULL;
-	return 0;
-}
-
-static struct dvb_tuner_ops zl10039_ops = {
-	.release = zl10039_release,
-	.init = zl10039_init,
-	.sleep = zl10039_sleep,
-	.set_params = zl10039_set_params,
-};
-
-struct dvb_frontend *zl10039_attach(struct dvb_frontend *fe,
-		u8 i2c_addr, struct i2c_adapter *i2c)
-{
-	struct zl10039_state *state = NULL;
-
-	dprintk("%s\n", __func__);
-	state = kmalloc(sizeof(struct zl10039_state), GFP_KERNEL);
-	if (state == NULL)
-		goto error;
-
-	state->i2c = i2c;
-	state->i2c_addr = i2c_addr;
-
-	/* Open i2c gate */
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	/* check if this is a valid tuner */
-	if (zl10039_readreg(state, GENERAL, &state->id) < 0) {
-		/* Close i2c gate */
-		if (fe->ops.i2c_gate_ctrl)
-			fe->ops.i2c_gate_ctrl(fe, 0);
-		goto error;
-	}
-	/* Close i2c gate */
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0);
-
-	state->id = state->id & 0x0f;
-	switch (state->id) {
-	case ID_ZL10039:
-		strcpy(fe->ops.tuner_ops.info.name,
-			"Zarlink ZL10039 DVB-S tuner");
-		break;
-	default:
-		dprintk("Chip ID=%x does not match a known type\n", state->id);
-		goto error;
-	}
-
-	memcpy(&fe->ops.tuner_ops, &zl10039_ops, sizeof(struct dvb_tuner_ops));
-	fe->tuner_priv = state;
-	dprintk("Tuner attached @ i2c address 0x%02x\n", i2c_addr);
-	return fe;
-error:
-	kfree(state);
-	return NULL;
-}
-EXPORT_SYMBOL(zl10039_attach);
-
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
-MODULE_DESCRIPTION("Zarlink ZL10039 DVB-S tuner driver");
-MODULE_AUTHOR("Jan D. Louw <jd.louw@mweb.co.za>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/zl10039.h b/drivers/media/dvb/frontends/zl10039.h
deleted file mode 100644
index 5eee7ea..0000000
--- a/drivers/media/dvb/frontends/zl10039.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
-    Driver for Zarlink ZL10039 DVB-S tuner
-
-    Copyright (C) 2007 Jan D. Louw <jd.louw@mweb.co.za>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the 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 ZL10039_H
-#define ZL10039_H
-
-#if defined(CONFIG_DVB_ZL10039) || (defined(CONFIG_DVB_ZL10039_MODULE) \
-	    && defined(MODULE))
-struct dvb_frontend *zl10039_attach(struct dvb_frontend *fe,
-					u8 i2c_addr,
-					struct i2c_adapter *i2c);
-#else
-static inline struct dvb_frontend *zl10039_attach(struct dvb_frontend *fe,
-					u8 i2c_addr,
-					struct i2c_adapter *i2c)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif /* CONFIG_DVB_ZL10039 */
-
-#endif /* ZL10039_H */
diff --git a/drivers/media/dvb/frontends/zl10353.c b/drivers/media/dvb/frontends/zl10353.c
deleted file mode 100644
index 82946cd..0000000
--- a/drivers/media/dvb/frontends/zl10353.c
+++ /dev/null
@@ -1,684 +0,0 @@
-/*
- * Driver for Zarlink DVB-T ZL10353 demodulator
- *
- * Copyright (C) 2006, 2007 Christopher Pascoe <c.pascoe@itee.uq.edu.au>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *
- * GNU General Public License for more details.
- *
- * You 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/init.h>
-#include <linux/delay.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <asm/div64.h>
-
-#include "dvb_frontend.h"
-#include "zl10353_priv.h"
-#include "zl10353.h"
-
-struct zl10353_state {
-	struct i2c_adapter *i2c;
-	struct dvb_frontend frontend;
-
-	struct zl10353_config config;
-
-	u32 bandwidth;
-	u32 ucblocks;
-	u32 frequency;
-};
-
-static int debug;
-#define dprintk(args...) \
-	do { \
-		if (debug) printk(KERN_DEBUG "zl10353: " args); \
-	} while (0)
-
-static int debug_regs;
-
-static int zl10353_single_write(struct dvb_frontend *fe, u8 reg, u8 val)
-{
-	struct zl10353_state *state = fe->demodulator_priv;
-	u8 buf[2] = { reg, val };
-	struct i2c_msg msg = { .addr = state->config.demod_address, .flags = 0,
-			       .buf = buf, .len = 2 };
-	int err = i2c_transfer(state->i2c, &msg, 1);
-	if (err != 1) {
-		printk("zl10353: write to reg %x failed (err = %d)!\n", reg, err);
-		return err;
-	}
-	return 0;
-}
-
-static int zl10353_write(struct dvb_frontend *fe, const u8 ibuf[], int ilen)
-{
-	int err, i;
-	for (i = 0; i < ilen - 1; i++)
-		if ((err = zl10353_single_write(fe, ibuf[0] + i, ibuf[i + 1])))
-			return err;
-
-	return 0;
-}
-
-static int zl10353_read_register(struct zl10353_state *state, u8 reg)
-{
-	int ret;
-	u8 b0[1] = { reg };
-	u8 b1[1] = { 0 };
-	struct i2c_msg msg[2] = { { .addr = state->config.demod_address,
-				    .flags = 0,
-				    .buf = b0, .len = 1 },
-				  { .addr = state->config.demod_address,
-				    .flags = I2C_M_RD,
-				    .buf = b1, .len = 1 } };
-
-	ret = i2c_transfer(state->i2c, msg, 2);
-
-	if (ret != 2) {
-		printk("%s: readreg error (reg=%d, ret==%i)\n",
-		       __func__, reg, ret);
-		return ret;
-	}
-
-	return b1[0];
-}
-
-static void zl10353_dump_regs(struct dvb_frontend *fe)
-{
-	struct zl10353_state *state = fe->demodulator_priv;
-	int ret;
-	u8 reg;
-
-	/* Dump all registers. */
-	for (reg = 0; ; reg++) {
-		if (reg % 16 == 0) {
-			if (reg)
-				printk(KERN_CONT "\n");
-			printk(KERN_DEBUG "%02x:", reg);
-		}
-		ret = zl10353_read_register(state, reg);
-		if (ret >= 0)
-			printk(KERN_CONT " %02x", (u8)ret);
-		else
-			printk(KERN_CONT " --");
-		if (reg == 0xff)
-			break;
-	}
-	printk(KERN_CONT "\n");
-}
-
-static void zl10353_calc_nominal_rate(struct dvb_frontend *fe,
-				      u32 bandwidth,
-				      u16 *nominal_rate)
-{
-	struct zl10353_state *state = fe->demodulator_priv;
-	u32 adc_clock = 450560; /* 45.056 MHz */
-	u64 value;
-	u8 bw = bandwidth / 1000000;
-
-	if (state->config.adc_clock)
-		adc_clock = state->config.adc_clock;
-
-	value = (u64)10 * (1 << 23) / 7 * 125;
-	value = (bw * value) + adc_clock / 2;
-	do_div(value, adc_clock);
-	*nominal_rate = value;
-
-	dprintk("%s: bw %d, adc_clock %d => 0x%x\n",
-		__func__, bw, adc_clock, *nominal_rate);
-}
-
-static void zl10353_calc_input_freq(struct dvb_frontend *fe,
-				    u16 *input_freq)
-{
-	struct zl10353_state *state = fe->demodulator_priv;
-	u32 adc_clock = 450560;	/* 45.056  MHz */
-	int if2 = 361667;	/* 36.1667 MHz */
-	int ife;
-	u64 value;
-
-	if (state->config.adc_clock)
-		adc_clock = state->config.adc_clock;
-	if (state->config.if2)
-		if2 = state->config.if2;
-
-	if (adc_clock >= if2 * 2)
-		ife = if2;
-	else {
-		ife = adc_clock - (if2 % adc_clock);
-		if (ife > adc_clock / 2)
-			ife = adc_clock - ife;
-	}
-	value = (u64)65536 * ife + adc_clock / 2;
-	do_div(value, adc_clock);
-	*input_freq = -value;
-
-	dprintk("%s: if2 %d, ife %d, adc_clock %d => %d / 0x%x\n",
-		__func__, if2, ife, adc_clock, -(int)value, *input_freq);
-}
-
-static int zl10353_sleep(struct dvb_frontend *fe)
-{
-	static u8 zl10353_softdown[] = { 0x50, 0x0C, 0x44 };
-
-	zl10353_write(fe, zl10353_softdown, sizeof(zl10353_softdown));
-	return 0;
-}
-
-static int zl10353_set_parameters(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	struct zl10353_state *state = fe->demodulator_priv;
-	u16 nominal_rate, input_freq;
-	u8 pllbuf[6] = { 0x67 }, acq_ctl = 0;
-	u16 tps = 0;
-
-	state->frequency = c->frequency;
-
-	zl10353_single_write(fe, RESET, 0x80);
-	udelay(200);
-	zl10353_single_write(fe, 0xEA, 0x01);
-	udelay(200);
-	zl10353_single_write(fe, 0xEA, 0x00);
-
-	zl10353_single_write(fe, AGC_TARGET, 0x28);
-
-	if (c->transmission_mode != TRANSMISSION_MODE_AUTO)
-		acq_ctl |= (1 << 0);
-	if (c->guard_interval != GUARD_INTERVAL_AUTO)
-		acq_ctl |= (1 << 1);
-	zl10353_single_write(fe, ACQ_CTL, acq_ctl);
-
-	switch (c->bandwidth_hz) {
-	case 6000000:
-		/* These are extrapolated from the 7 and 8MHz values */
-		zl10353_single_write(fe, MCLK_RATIO, 0x97);
-		zl10353_single_write(fe, 0x64, 0x34);
-		zl10353_single_write(fe, 0xcc, 0xdd);
-		break;
-	case 7000000:
-		zl10353_single_write(fe, MCLK_RATIO, 0x86);
-		zl10353_single_write(fe, 0x64, 0x35);
-		zl10353_single_write(fe, 0xcc, 0x73);
-		break;
-	default:
-		c->bandwidth_hz = 8000000;
-		/* fall though */
-	case 8000000:
-		zl10353_single_write(fe, MCLK_RATIO, 0x75);
-		zl10353_single_write(fe, 0x64, 0x36);
-		zl10353_single_write(fe, 0xcc, 0x73);
-	}
-
-	zl10353_calc_nominal_rate(fe, c->bandwidth_hz, &nominal_rate);
-	zl10353_single_write(fe, TRL_NOMINAL_RATE_1, msb(nominal_rate));
-	zl10353_single_write(fe, TRL_NOMINAL_RATE_0, lsb(nominal_rate));
-	state->bandwidth = c->bandwidth_hz;
-
-	zl10353_calc_input_freq(fe, &input_freq);
-	zl10353_single_write(fe, INPUT_FREQ_1, msb(input_freq));
-	zl10353_single_write(fe, INPUT_FREQ_0, lsb(input_freq));
-
-	/* Hint at TPS settings */
-	switch (c->code_rate_HP) {
-	case FEC_2_3:
-		tps |= (1 << 7);
-		break;
-	case FEC_3_4:
-		tps |= (2 << 7);
-		break;
-	case FEC_5_6:
-		tps |= (3 << 7);
-		break;
-	case FEC_7_8:
-		tps |= (4 << 7);
-		break;
-	case FEC_1_2:
-	case FEC_AUTO:
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	switch (c->code_rate_LP) {
-	case FEC_2_3:
-		tps |= (1 << 4);
-		break;
-	case FEC_3_4:
-		tps |= (2 << 4);
-		break;
-	case FEC_5_6:
-		tps |= (3 << 4);
-		break;
-	case FEC_7_8:
-		tps |= (4 << 4);
-		break;
-	case FEC_1_2:
-	case FEC_AUTO:
-		break;
-	case FEC_NONE:
-		if (c->hierarchy == HIERARCHY_AUTO ||
-		    c->hierarchy == HIERARCHY_NONE)
-			break;
-	default:
-		return -EINVAL;
-	}
-
-	switch (c->modulation) {
-	case QPSK:
-		break;
-	case QAM_AUTO:
-	case QAM_16:
-		tps |= (1 << 13);
-		break;
-	case QAM_64:
-		tps |= (2 << 13);
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	switch (c->transmission_mode) {
-	case TRANSMISSION_MODE_2K:
-	case TRANSMISSION_MODE_AUTO:
-		break;
-	case TRANSMISSION_MODE_8K:
-		tps |= (1 << 0);
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	switch (c->guard_interval) {
-	case GUARD_INTERVAL_1_32:
-	case GUARD_INTERVAL_AUTO:
-		break;
-	case GUARD_INTERVAL_1_16:
-		tps |= (1 << 2);
-		break;
-	case GUARD_INTERVAL_1_8:
-		tps |= (2 << 2);
-		break;
-	case GUARD_INTERVAL_1_4:
-		tps |= (3 << 2);
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	switch (c->hierarchy) {
-	case HIERARCHY_AUTO:
-	case HIERARCHY_NONE:
-		break;
-	case HIERARCHY_1:
-		tps |= (1 << 10);
-		break;
-	case HIERARCHY_2:
-		tps |= (2 << 10);
-		break;
-	case HIERARCHY_4:
-		tps |= (3 << 10);
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	zl10353_single_write(fe, TPS_GIVEN_1, msb(tps));
-	zl10353_single_write(fe, TPS_GIVEN_0, lsb(tps));
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 0);
-
-	/*
-	 * If there is no tuner attached to the secondary I2C bus, we call
-	 * set_params to program a potential tuner attached somewhere else.
-	 * Otherwise, we update the PLL registers via calc_regs.
-	 */
-	if (state->config.no_tuner) {
-		if (fe->ops.tuner_ops.set_params) {
-			fe->ops.tuner_ops.set_params(fe);
-			if (fe->ops.i2c_gate_ctrl)
-				fe->ops.i2c_gate_ctrl(fe, 0);
-		}
-	} else if (fe->ops.tuner_ops.calc_regs) {
-		fe->ops.tuner_ops.calc_regs(fe, pllbuf + 1, 5);
-		pllbuf[1] <<= 1;
-		zl10353_write(fe, pllbuf, sizeof(pllbuf));
-	}
-
-	zl10353_single_write(fe, 0x5F, 0x13);
-
-	/* If no attached tuner or invalid PLL registers, just start the FSM. */
-	if (state->config.no_tuner || fe->ops.tuner_ops.calc_regs == NULL)
-		zl10353_single_write(fe, FSM_GO, 0x01);
-	else
-		zl10353_single_write(fe, TUNER_GO, 0x01);
-
-	return 0;
-}
-
-static int zl10353_get_parameters(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	struct zl10353_state *state = fe->demodulator_priv;
-	int s6, s9;
-	u16 tps;
-	static const u8 tps_fec_to_api[8] = {
-		FEC_1_2,
-		FEC_2_3,
-		FEC_3_4,
-		FEC_5_6,
-		FEC_7_8,
-		FEC_AUTO,
-		FEC_AUTO,
-		FEC_AUTO
-	};
-
-	s6 = zl10353_read_register(state, STATUS_6);
-	s9 = zl10353_read_register(state, STATUS_9);
-	if (s6 < 0 || s9 < 0)
-		return -EREMOTEIO;
-	if ((s6 & (1 << 5)) == 0 || (s9 & (1 << 4)) == 0)
-		return -EINVAL;	/* no FE or TPS lock */
-
-	tps = zl10353_read_register(state, TPS_RECEIVED_1) << 8 |
-	      zl10353_read_register(state, TPS_RECEIVED_0);
-
-	c->code_rate_HP = tps_fec_to_api[(tps >> 7) & 7];
-	c->code_rate_LP = tps_fec_to_api[(tps >> 4) & 7];
-
-	switch ((tps >> 13) & 3) {
-	case 0:
-		c->modulation = QPSK;
-		break;
-	case 1:
-		c->modulation = QAM_16;
-		break;
-	case 2:
-		c->modulation = QAM_64;
-		break;
-	default:
-		c->modulation = QAM_AUTO;
-		break;
-	}
-
-	c->transmission_mode = (tps & 0x01) ? TRANSMISSION_MODE_8K :
-					       TRANSMISSION_MODE_2K;
-
-	switch ((tps >> 2) & 3) {
-	case 0:
-		c->guard_interval = GUARD_INTERVAL_1_32;
-		break;
-	case 1:
-		c->guard_interval = GUARD_INTERVAL_1_16;
-		break;
-	case 2:
-		c->guard_interval = GUARD_INTERVAL_1_8;
-		break;
-	case 3:
-		c->guard_interval = GUARD_INTERVAL_1_4;
-		break;
-	default:
-		c->guard_interval = GUARD_INTERVAL_AUTO;
-		break;
-	}
-
-	switch ((tps >> 10) & 7) {
-	case 0:
-		c->hierarchy = HIERARCHY_NONE;
-		break;
-	case 1:
-		c->hierarchy = HIERARCHY_1;
-		break;
-	case 2:
-		c->hierarchy = HIERARCHY_2;
-		break;
-	case 3:
-		c->hierarchy = HIERARCHY_4;
-		break;
-	default:
-		c->hierarchy = HIERARCHY_AUTO;
-		break;
-	}
-
-	c->frequency = state->frequency;
-	c->bandwidth_hz = state->bandwidth;
-	c->inversion = INVERSION_AUTO;
-
-	return 0;
-}
-
-static int zl10353_read_status(struct dvb_frontend *fe, fe_status_t *status)
-{
-	struct zl10353_state *state = fe->demodulator_priv;
-	int s6, s7, s8;
-
-	if ((s6 = zl10353_read_register(state, STATUS_6)) < 0)
-		return -EREMOTEIO;
-	if ((s7 = zl10353_read_register(state, STATUS_7)) < 0)
-		return -EREMOTEIO;
-	if ((s8 = zl10353_read_register(state, STATUS_8)) < 0)
-		return -EREMOTEIO;
-
-	*status = 0;
-	if (s6 & (1 << 2))
-		*status |= FE_HAS_CARRIER;
-	if (s6 & (1 << 1))
-		*status |= FE_HAS_VITERBI;
-	if (s6 & (1 << 5))
-		*status |= FE_HAS_LOCK;
-	if (s7 & (1 << 4))
-		*status |= FE_HAS_SYNC;
-	if (s8 & (1 << 6))
-		*status |= FE_HAS_SIGNAL;
-
-	if ((*status & (FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC)) !=
-	    (FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC))
-		*status &= ~FE_HAS_LOCK;
-
-	return 0;
-}
-
-static int zl10353_read_ber(struct dvb_frontend *fe, u32 *ber)
-{
-	struct zl10353_state *state = fe->demodulator_priv;
-
-	*ber = zl10353_read_register(state, RS_ERR_CNT_2) << 16 |
-	       zl10353_read_register(state, RS_ERR_CNT_1) << 8 |
-	       zl10353_read_register(state, RS_ERR_CNT_0);
-
-	return 0;
-}
-
-static int zl10353_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
-{
-	struct zl10353_state *state = fe->demodulator_priv;
-
-	u16 signal = zl10353_read_register(state, AGC_GAIN_1) << 10 |
-		     zl10353_read_register(state, AGC_GAIN_0) << 2 | 3;
-
-	*strength = ~signal;
-
-	return 0;
-}
-
-static int zl10353_read_snr(struct dvb_frontend *fe, u16 *snr)
-{
-	struct zl10353_state *state = fe->demodulator_priv;
-	u8 _snr;
-
-	if (debug_regs)
-		zl10353_dump_regs(fe);
-
-	_snr = zl10353_read_register(state, SNR);
-	*snr = 10 * _snr / 8;
-
-	return 0;
-}
-
-static int zl10353_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
-{
-	struct zl10353_state *state = fe->demodulator_priv;
-       u32 ubl = 0;
-
-       ubl = zl10353_read_register(state, RS_UBC_1) << 8 |
-	     zl10353_read_register(state, RS_UBC_0);
-
-       state->ucblocks += ubl;
-       *ucblocks = state->ucblocks;
-
-	return 0;
-}
-
-static int zl10353_get_tune_settings(struct dvb_frontend *fe,
-				     struct dvb_frontend_tune_settings
-					 *fe_tune_settings)
-{
-	fe_tune_settings->min_delay_ms = 1000;
-	fe_tune_settings->step_size = 0;
-	fe_tune_settings->max_drift = 0;
-
-	return 0;
-}
-
-static int zl10353_init(struct dvb_frontend *fe)
-{
-	struct zl10353_state *state = fe->demodulator_priv;
-	u8 zl10353_reset_attach[6] = { 0x50, 0x03, 0x64, 0x46, 0x15, 0x0F };
-
-	if (debug_regs)
-		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] ||
-	    zl10353_read_register(state, 0x51) != zl10353_reset_attach[2]) {
-		zl10353_write(fe, zl10353_reset_attach,
-				   sizeof(zl10353_reset_attach));
-		if (debug_regs)
-			zl10353_dump_regs(fe);
-	}
-
-	return 0;
-}
-
-static int zl10353_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
-{
-	struct zl10353_state *state = fe->demodulator_priv;
-	u8 val = 0x0a;
-
-	if (state->config.disable_i2c_gate_ctrl) {
-		/* No tuner attached to the internal I2C bus */
-		/* If set enable I2C bridge, the main I2C bus stopped hardly */
-		return 0;
-	}
-
-	if (enable)
-		val |= 0x10;
-
-	return zl10353_single_write(fe, 0x62, val);
-}
-
-static void zl10353_release(struct dvb_frontend *fe)
-{
-	struct zl10353_state *state = fe->demodulator_priv;
-	kfree(state);
-}
-
-static struct dvb_frontend_ops zl10353_ops;
-
-struct dvb_frontend *zl10353_attach(const struct zl10353_config *config,
-				    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);
-	if (state == NULL)
-		goto error;
-
-	/* setup the state */
-	state->i2c = i2c;
-	memcpy(&state->config, config, sizeof(struct zl10353_config));
-
-	/* check if the demod is there */
-	id = zl10353_read_register(state, CHIP_ID);
-	if ((id != ID_ZL10353) && (id != ID_CE6230) && (id != ID_CE6231))
-		goto error;
-
-	/* create dvb_frontend */
-	memcpy(&state->frontend.ops, &zl10353_ops, sizeof(struct dvb_frontend_ops));
-	state->frontend.demodulator_priv = state;
-
-	return &state->frontend;
-error:
-	kfree(state);
-	return NULL;
-}
-
-static struct dvb_frontend_ops zl10353_ops = {
-	.delsys = { SYS_DVBT },
-	.info = {
-		.name			= "Zarlink ZL10353 DVB-T",
-		.frequency_min		= 174000000,
-		.frequency_max		= 862000000,
-		.frequency_stepsize	= 166667,
-		.frequency_tolerance	= 0,
-		.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_FEC_AUTO |
-			FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
-			FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |
-			FE_CAN_HIERARCHY_AUTO | FE_CAN_RECOVER |
-			FE_CAN_MUTE_TS
-	},
-
-	.release = zl10353_release,
-
-	.init = zl10353_init,
-	.sleep = zl10353_sleep,
-	.i2c_gate_ctrl = zl10353_i2c_gate_ctrl,
-	.write = zl10353_write,
-
-	.set_frontend = zl10353_set_parameters,
-	.get_frontend = zl10353_get_parameters,
-	.get_tune_settings = zl10353_get_tune_settings,
-
-	.read_status = zl10353_read_status,
-	.read_ber = zl10353_read_ber,
-	.read_signal_strength = zl10353_read_signal_strength,
-	.read_snr = zl10353_read_snr,
-	.read_ucblocks = zl10353_read_ucblocks,
-};
-
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
-
-module_param(debug_regs, int, 0644);
-MODULE_PARM_DESC(debug_regs, "Turn on/off frontend register dumps (default:off).");
-
-MODULE_DESCRIPTION("Zarlink ZL10353 DVB-T demodulator driver");
-MODULE_AUTHOR("Chris Pascoe");
-MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(zl10353_attach);
diff --git a/drivers/media/dvb/frontends/zl10353.h b/drivers/media/dvb/frontends/zl10353.h
deleted file mode 100644
index 6e3ca9e..0000000
--- a/drivers/media/dvb/frontends/zl10353.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- *  Driver for Zarlink DVB-T ZL10353 demodulator
- *
- *  Copyright (C) 2006, 2007 Christopher Pascoe <c.pascoe@itee.uq.edu.au>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *
- *  GNU General Public License for more details.
- *
- *  You 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 ZL10353_H
-#define ZL10353_H
-
-#include <linux/dvb/frontend.h>
-
-struct zl10353_config
-{
-	/* demodulator's I2C address */
-	u8 demod_address;
-
-	/* frequencies in units of 0.1kHz */
-	int adc_clock;	/* default: 450560 (45.056  MHz) */
-	int if2;	/* default: 361667 (36.1667 MHz) */
-
-	/* set if no pll is connected to the secondary i2c bus */
-	int no_tuner;
-
-	/* set if parallel ts output is required */
-	int parallel_ts;
-
-	/* 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))
-extern struct dvb_frontend* zl10353_attach(const struct zl10353_config *config,
-					   struct i2c_adapter *i2c);
-#else
-static inline struct dvb_frontend* zl10353_attach(const struct zl10353_config *config,
-					   struct i2c_adapter *i2c)
-{
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-	return NULL;
-}
-#endif /* CONFIG_DVB_ZL10353 */
-
-#endif /* ZL10353_H */
diff --git a/drivers/media/dvb/frontends/zl10353_priv.h b/drivers/media/dvb/frontends/zl10353_priv.h
deleted file mode 100644
index e0dd1d3..0000000
--- a/drivers/media/dvb/frontends/zl10353_priv.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- *  Driver for Zarlink DVB-T ZL10353 demodulator
- *
- *  Copyright (C) 2006, 2007 Christopher Pascoe <c.pascoe@itee.uq.edu.au>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *
- *  GNU General Public License for more details.
- *
- *  You 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 _ZL10353_PRIV_
-#define _ZL10353_PRIV_
-
-#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)
-
-enum zl10353_reg_addr {
-	INTERRUPT_0        = 0x00,
-	INTERRUPT_1        = 0x01,
-	INTERRUPT_2        = 0x02,
-	INTERRUPT_3        = 0x03,
-	INTERRUPT_4        = 0x04,
-	INTERRUPT_5        = 0x05,
-	STATUS_6           = 0x06,
-	STATUS_7           = 0x07,
-	STATUS_8           = 0x08,
-	STATUS_9           = 0x09,
-	AGC_GAIN_1         = 0x0A,
-	AGC_GAIN_0         = 0x0B,
-	SNR                = 0x10,
-	RS_ERR_CNT_2       = 0x11,
-	RS_ERR_CNT_1       = 0x12,
-	RS_ERR_CNT_0       = 0x13,
-	RS_UBC_1           = 0x14,
-	RS_UBC_0           = 0x15,
-	TPS_RECEIVED_1     = 0x1D,
-	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,
-	ACQ_CTL            = 0x5E,
-	TRL_NOMINAL_RATE_1 = 0x65,
-	TRL_NOMINAL_RATE_0 = 0x66,
-	INPUT_FREQ_1       = 0x6C,
-	INPUT_FREQ_0       = 0x6D,
-	TPS_GIVEN_1        = 0x6E,
-	TPS_GIVEN_0        = 0x6F,
-	TUNER_GO           = 0x70,
-	FSM_GO             = 0x71,
-	CHIP_ID            = 0x7F,
-	CHAN_STEP_1        = 0xE4,
-	CHAN_STEP_0        = 0xE5,
-	OFDM_LOCK_TIME     = 0xE7,
-	FEC_LOCK_TIME      = 0xE8,
-	ACQ_DELAY          = 0xE9,
-};
-
-#endif                          /* _ZL10353_PRIV_ */
diff --git a/drivers/media/dvb/mantis/Kconfig b/drivers/media/dvb/mantis/Kconfig
deleted file mode 100644
index a13a505..0000000
--- a/drivers/media/dvb/mantis/Kconfig
+++ /dev/null
@@ -1,38 +0,0 @@
-config MANTIS_CORE
-	tristate "Mantis/Hopper PCI bridge based devices"
-	depends on PCI && I2C && INPUT && RC_CORE
-
-	help
-	  Support for PCI cards based on the Mantis and Hopper PCi bridge.
-
-	  Say Y if you own such a device and want to use it.
-
-config DVB_MANTIS
-	tristate "MANTIS based cards"
-	depends on MANTIS_CORE && DVB_CORE && PCI && I2C
-	select DVB_MB86A16 if !DVB_FE_CUSTOMISE
-	select DVB_ZL10353 if !DVB_FE_CUSTOMISE
-	select DVB_STV0299 if !DVB_FE_CUSTOMISE
-	select DVB_LNBP21 if !DVB_FE_CUSTOMISE
-	select DVB_STB0899 if !DVB_FE_CUSTOMISE
-	select DVB_STB6100 if !DVB_FE_CUSTOMISE
-	select DVB_TDA665x if !DVB_FE_CUSTOMISE
-	select DVB_TDA10021 if !DVB_FE_CUSTOMISE
-	select DVB_TDA10023 if !DVB_FE_CUSTOMISE
-	select DVB_PLL
-	help
-	  Support for PCI cards based on the Mantis PCI bridge.
-	  Say Y when you have a Mantis based DVB card and want to use it.
-
-	  If unsure say N.
-
-config DVB_HOPPER
-	tristate "HOPPER based cards"
-	depends on MANTIS_CORE && DVB_CORE && PCI && I2C
-	select DVB_ZL10353 if !DVB_FE_CUSTOMISE
-	select DVB_PLL
-	help
-	  Support for PCI cards based on the Hopper  PCI bridge.
-	  Say Y when you have a Hopper based DVB card and want to use it.
-
-	  If unsure say N
diff --git a/drivers/media/dvb/mantis/Makefile b/drivers/media/dvb/mantis/Makefile
deleted file mode 100644
index ec8116d..0000000
--- a/drivers/media/dvb/mantis/Makefile
+++ /dev/null
@@ -1,28 +0,0 @@
-mantis_core-objs :=	mantis_ioc.o	\
-			mantis_uart.o	\
-			mantis_dma.o	\
-			mantis_pci.o	\
-			mantis_i2c.o	\
-			mantis_dvb.o	\
-			mantis_evm.o	\
-			mantis_hif.o	\
-			mantis_ca.o	\
-			mantis_pcmcia.o	\
-			mantis_input.o
-
-mantis-objs	:=	mantis_cards.o	\
-			mantis_vp1033.o	\
-			mantis_vp1034.o	\
-			mantis_vp1041.o	\
-			mantis_vp2033.o	\
-			mantis_vp2040.o	\
-			mantis_vp3030.o
-
-hopper-objs	:=	hopper_cards.o	\
-			hopper_vp3028.o
-
-obj-$(CONFIG_MANTIS_CORE)	+= mantis_core.o
-obj-$(CONFIG_DVB_MANTIS)	+= mantis.o
-obj-$(CONFIG_DVB_HOPPER)	+= hopper.o
-
-ccflags-y += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
diff --git a/drivers/media/dvb/mantis/hopper_cards.c b/drivers/media/dvb/mantis/hopper_cards.c
deleted file mode 100644
index cc0251e..0000000
--- a/drivers/media/dvb/mantis/hopper_cards.c
+++ /dev/null
@@ -1,277 +0,0 @@
-/*
-	Hopper PCI bridge driver
-
-	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-#include <asm/irq.h>
-#include <linux/interrupt.h>
-
-#include "dmxdev.h"
-#include "dvbdev.h"
-#include "dvb_demux.h"
-#include "dvb_frontend.h"
-#include "dvb_net.h"
-
-#include "mantis_common.h"
-#include "hopper_vp3028.h"
-#include "mantis_dma.h"
-#include "mantis_dvb.h"
-#include "mantis_uart.h"
-#include "mantis_ioc.h"
-#include "mantis_pci.h"
-#include "mantis_i2c.h"
-#include "mantis_reg.h"
-
-static unsigned int verbose;
-module_param(verbose, int, 0644);
-MODULE_PARM_DESC(verbose, "verbose startup messages, default is 0 (no)");
-
-#define DRIVER_NAME	"Hopper"
-
-static char *label[10] = {
-	"DMA",
-	"IRQ-0",
-	"IRQ-1",
-	"OCERR",
-	"PABRT",
-	"RIPRR",
-	"PPERR",
-	"FTRGT",
-	"RISCI",
-	"RACK"
-};
-
-static int devs;
-
-static irqreturn_t hopper_irq_handler(int irq, void *dev_id)
-{
-	u32 stat = 0, mask = 0;
-	u32 rst_stat = 0, rst_mask = 0;
-
-	struct mantis_pci *mantis;
-	struct mantis_ca *ca;
-
-	mantis = (struct mantis_pci *) dev_id;
-	if (unlikely(mantis == NULL)) {
-		dprintk(MANTIS_ERROR, 1, "Mantis == NULL");
-		return IRQ_NONE;
-	}
-	ca = mantis->mantis_ca;
-
-	stat = mmread(MANTIS_INT_STAT);
-	mask = mmread(MANTIS_INT_MASK);
-	if (!(stat & mask))
-		return IRQ_NONE;
-
-	rst_mask  = MANTIS_GPIF_WRACK  |
-		    MANTIS_GPIF_OTHERR |
-		    MANTIS_SBUF_WSTO   |
-		    MANTIS_GPIF_EXTIRQ;
-
-	rst_stat  = mmread(MANTIS_GPIF_STATUS);
-	rst_stat &= rst_mask;
-	mmwrite(rst_stat, MANTIS_GPIF_STATUS);
-
-	mantis->mantis_int_stat = stat;
-	mantis->mantis_int_mask = mask;
-	dprintk(MANTIS_DEBUG, 0, "\n-- Stat=<%02x> Mask=<%02x> --", stat, mask);
-	if (stat & MANTIS_INT_RISCEN) {
-		dprintk(MANTIS_DEBUG, 0, "<%s>", label[0]);
-	}
-	if (stat & MANTIS_INT_IRQ0) {
-		dprintk(MANTIS_DEBUG, 0, "<%s>", label[1]);
-		mantis->gpif_status = rst_stat;
-		wake_up(&ca->hif_write_wq);
-		schedule_work(&ca->hif_evm_work);
-	}
-	if (stat & MANTIS_INT_IRQ1) {
-		dprintk(MANTIS_DEBUG, 0, "<%s>", label[2]);
-		schedule_work(&mantis->uart_work);
-	}
-	if (stat & MANTIS_INT_OCERR) {
-		dprintk(MANTIS_DEBUG, 0, "<%s>", label[3]);
-	}
-	if (stat & MANTIS_INT_PABORT) {
-		dprintk(MANTIS_DEBUG, 0, "<%s>", label[4]);
-	}
-	if (stat & MANTIS_INT_RIPERR) {
-		dprintk(MANTIS_DEBUG, 0, "<%s>", label[5]);
-	}
-	if (stat & MANTIS_INT_PPERR) {
-		dprintk(MANTIS_DEBUG, 0, "<%s>", label[6]);
-	}
-	if (stat & MANTIS_INT_FTRGT) {
-		dprintk(MANTIS_DEBUG, 0, "<%s>", label[7]);
-	}
-	if (stat & MANTIS_INT_RISCI) {
-		dprintk(MANTIS_DEBUG, 0, "<%s>", label[8]);
-		mantis->busy_block = (stat & MANTIS_INT_RISCSTAT) >> 28;
-		tasklet_schedule(&mantis->tasklet);
-	}
-	if (stat & MANTIS_INT_I2CDONE) {
-		dprintk(MANTIS_DEBUG, 0, "<%s>", label[9]);
-		wake_up(&mantis->i2c_wq);
-	}
-	mmwrite(stat, MANTIS_INT_STAT);
-	stat &= ~(MANTIS_INT_RISCEN   | MANTIS_INT_I2CDONE |
-		  MANTIS_INT_I2CRACK  | MANTIS_INT_PCMCIA7 |
-		  MANTIS_INT_PCMCIA6  | MANTIS_INT_PCMCIA5 |
-		  MANTIS_INT_PCMCIA4  | MANTIS_INT_PCMCIA3 |
-		  MANTIS_INT_PCMCIA2  | MANTIS_INT_PCMCIA1 |
-		  MANTIS_INT_PCMCIA0  | MANTIS_INT_IRQ1	   |
-		  MANTIS_INT_IRQ0     | MANTIS_INT_OCERR   |
-		  MANTIS_INT_PABORT   | MANTIS_INT_RIPERR  |
-		  MANTIS_INT_PPERR    | MANTIS_INT_FTRGT   |
-		  MANTIS_INT_RISCI);
-
-	if (stat)
-		dprintk(MANTIS_DEBUG, 0, "<Unknown> Stat=<%02x> Mask=<%02x>", stat, mask);
-
-	dprintk(MANTIS_DEBUG, 0, "\n");
-	return IRQ_HANDLED;
-}
-
-static int __devinit hopper_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
-{
-	struct mantis_pci *mantis;
-	struct mantis_hwconfig *config;
-	int err = 0;
-
-	mantis = kzalloc(sizeof(struct mantis_pci), GFP_KERNEL);
-	if (mantis == NULL) {
-		printk(KERN_ERR "%s ERROR: Out of memory\n", __func__);
-		err = -ENOMEM;
-		goto fail0;
-	}
-
-	mantis->num		= devs;
-	mantis->verbose		= verbose;
-	mantis->pdev		= pdev;
-	config			= (struct mantis_hwconfig *) pci_id->driver_data;
-	config->irq_handler	= &hopper_irq_handler;
-	mantis->hwconfig	= config;
-
-	err = mantis_pci_init(mantis);
-	if (err) {
-		dprintk(MANTIS_ERROR, 1, "ERROR: Mantis PCI initialization failed <%d>", err);
-		goto fail1;
-	}
-
-	err = mantis_stream_control(mantis, STREAM_TO_HIF);
-	if (err < 0) {
-		dprintk(MANTIS_ERROR, 1, "ERROR: Mantis stream control failed <%d>", err);
-		goto fail1;
-	}
-
-	err = mantis_i2c_init(mantis);
-	if (err < 0) {
-		dprintk(MANTIS_ERROR, 1, "ERROR: Mantis I2C initialization failed <%d>", err);
-		goto fail2;
-	}
-
-	err = mantis_get_mac(mantis);
-	if (err < 0) {
-		dprintk(MANTIS_ERROR, 1, "ERROR: Mantis MAC address read failed <%d>", err);
-		goto fail2;
-	}
-
-	err = mantis_dma_init(mantis);
-	if (err < 0) {
-		dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DMA initialization failed <%d>", err);
-		goto fail3;
-	}
-
-	err = mantis_dvb_init(mantis);
-	if (err < 0) {
-		dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DVB initialization failed <%d>", err);
-		goto fail4;
-	}
-	devs++;
-
-	return err;
-
-fail4:
-	dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DMA exit! <%d>", err);
-	mantis_dma_exit(mantis);
-
-fail3:
-	dprintk(MANTIS_ERROR, 1, "ERROR: Mantis I2C exit! <%d>", err);
-	mantis_i2c_exit(mantis);
-
-fail2:
-	dprintk(MANTIS_ERROR, 1, "ERROR: Mantis PCI exit! <%d>", err);
-	mantis_pci_exit(mantis);
-
-fail1:
-	dprintk(MANTIS_ERROR, 1, "ERROR: Mantis free! <%d>", err);
-	kfree(mantis);
-
-fail0:
-	return err;
-}
-
-static void __devexit hopper_pci_remove(struct pci_dev *pdev)
-{
-	struct mantis_pci *mantis = pci_get_drvdata(pdev);
-
-	if (mantis) {
-		mantis_dvb_exit(mantis);
-		mantis_dma_exit(mantis);
-		mantis_i2c_exit(mantis);
-		mantis_pci_exit(mantis);
-		kfree(mantis);
-	}
-	return;
-
-}
-
-static struct pci_device_id hopper_pci_table[] = {
-	MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_3028_DVB_T, &vp3028_config),
-	{ }
-};
-
-MODULE_DEVICE_TABLE(pci, hopper_pci_table);
-
-static struct pci_driver hopper_pci_driver = {
-	.name		= DRIVER_NAME,
-	.id_table	= hopper_pci_table,
-	.probe		= hopper_pci_probe,
-	.remove		= hopper_pci_remove,
-};
-
-static int __devinit hopper_init(void)
-{
-	return pci_register_driver(&hopper_pci_driver);
-}
-
-static void __devexit hopper_exit(void)
-{
-	return pci_unregister_driver(&hopper_pci_driver);
-}
-
-module_init(hopper_init);
-module_exit(hopper_exit);
-
-MODULE_DESCRIPTION("HOPPER driver");
-MODULE_AUTHOR("Manu Abraham");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/mantis/hopper_vp3028.c b/drivers/media/dvb/mantis/hopper_vp3028.c
deleted file mode 100644
index 68a29f8..0000000
--- a/drivers/media/dvb/mantis/hopper_vp3028.c
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
-	Hopper VP-3028 driver
-
-	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-
-#include "dmxdev.h"
-#include "dvbdev.h"
-#include "dvb_demux.h"
-#include "dvb_frontend.h"
-#include "dvb_net.h"
-
-#include "zl10353.h"
-#include "mantis_common.h"
-#include "mantis_ioc.h"
-#include "mantis_dvb.h"
-#include "hopper_vp3028.h"
-
-struct zl10353_config hopper_vp3028_config = {
-	.demod_address	= 0x0f,
-};
-
-#define MANTIS_MODEL_NAME	"VP-3028"
-#define MANTIS_DEV_TYPE		"DVB-T"
-
-static int vp3028_frontend_init(struct mantis_pci *mantis, struct dvb_frontend *fe)
-{
-	struct i2c_adapter *adapter	= &mantis->adapter;
-	struct mantis_hwconfig *config	= mantis->hwconfig;
-	int err = 0;
-
-	mantis_gpio_set_bits(mantis, config->reset, 0);
-	msleep(100);
-	err = mantis_frontend_power(mantis, POWER_ON);
-	msleep(100);
-	mantis_gpio_set_bits(mantis, config->reset, 1);
-
-	err = mantis_frontend_power(mantis, POWER_ON);
-	if (err == 0) {
-		msleep(250);
-		dprintk(MANTIS_ERROR, 1, "Probing for 10353 (DVB-T)");
-		fe = dvb_attach(zl10353_attach, &hopper_vp3028_config, adapter);
-
-		if (!fe)
-			return -1;
-	} else {
-		dprintk(MANTIS_ERROR, 1, "Frontend on <%s> POWER ON failed! <%d>",
-			adapter->name,
-			err);
-
-		return -EIO;
-	}
-	dprintk(MANTIS_ERROR, 1, "Done!");
-
-	return 0;
-}
-
-struct mantis_hwconfig vp3028_config = {
-	.model_name	= MANTIS_MODEL_NAME,
-	.dev_type	= MANTIS_DEV_TYPE,
-	.ts_size	= MANTIS_TS_188,
-
-	.baud_rate	= MANTIS_BAUD_9600,
-	.parity		= MANTIS_PARITY_NONE,
-	.bytes		= 0,
-
-	.frontend_init	= vp3028_frontend_init,
-	.power		= GPIF_A00,
-	.reset		= GPIF_A03,
-};
diff --git a/drivers/media/dvb/mantis/hopper_vp3028.h b/drivers/media/dvb/mantis/hopper_vp3028.h
deleted file mode 100644
index 5723949..0000000
--- a/drivers/media/dvb/mantis/hopper_vp3028.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
-	Hopper VP-3028 driver
-
-	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#ifndef __MANTIS_VP3028_H
-#define __MANTIS_VP3028_H
-
-#include "mantis_common.h"
-
-#define MANTIS_VP_3028_DVB_T	0x0028
-
-extern struct mantis_hwconfig vp3028_config;
-
-#endif /* __MANTIS_VP3028_H */
diff --git a/drivers/media/dvb/mantis/mantis_ca.c b/drivers/media/dvb/mantis/mantis_ca.c
deleted file mode 100644
index 3d70469..0000000
--- a/drivers/media/dvb/mantis/mantis_ca.c
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
-	Mantis PCI bridge driver
-
-	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include <linux/signal.h>
-#include <linux/slab.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <asm/io.h>
-
-#include "dmxdev.h"
-#include "dvbdev.h"
-#include "dvb_demux.h"
-#include "dvb_frontend.h"
-#include "dvb_net.h"
-
-#include "mantis_common.h"
-#include "mantis_link.h"
-#include "mantis_hif.h"
-#include "mantis_reg.h"
-
-#include "mantis_ca.h"
-
-static int mantis_ca_read_attr_mem(struct dvb_ca_en50221 *en50221, int slot, int addr)
-{
-	struct mantis_ca *ca = en50221->data;
-	struct mantis_pci *mantis = ca->ca_priv;
-
-	dprintk(MANTIS_DEBUG, 1, "Slot(%d): Request Attribute Mem Read", slot);
-
-	if (slot != 0)
-		return -EINVAL;
-
-	return mantis_hif_read_mem(ca, addr);
-}
-
-static int mantis_ca_write_attr_mem(struct dvb_ca_en50221 *en50221, int slot, int addr, u8 data)
-{
-	struct mantis_ca *ca = en50221->data;
-	struct mantis_pci *mantis = ca->ca_priv;
-
-	dprintk(MANTIS_DEBUG, 1, "Slot(%d): Request Attribute Mem Write", slot);
-
-	if (slot != 0)
-		return -EINVAL;
-
-	return mantis_hif_write_mem(ca, addr, data);
-}
-
-static int mantis_ca_read_cam_ctl(struct dvb_ca_en50221 *en50221, int slot, u8 addr)
-{
-	struct mantis_ca *ca = en50221->data;
-	struct mantis_pci *mantis = ca->ca_priv;
-
-	dprintk(MANTIS_DEBUG, 1, "Slot(%d): Request CAM control Read", slot);
-
-	if (slot != 0)
-		return -EINVAL;
-
-	return mantis_hif_read_iom(ca, addr);
-}
-
-static int mantis_ca_write_cam_ctl(struct dvb_ca_en50221 *en50221, int slot, u8 addr, u8 data)
-{
-	struct mantis_ca *ca = en50221->data;
-	struct mantis_pci *mantis = ca->ca_priv;
-
-	dprintk(MANTIS_DEBUG, 1, "Slot(%d): Request CAM control Write", slot);
-
-	if (slot != 0)
-		return -EINVAL;
-
-	return mantis_hif_write_iom(ca, addr, data);
-}
-
-static int mantis_ca_slot_reset(struct dvb_ca_en50221 *en50221, int slot)
-{
-	struct mantis_ca *ca = en50221->data;
-	struct mantis_pci *mantis = ca->ca_priv;
-
-	dprintk(MANTIS_DEBUG, 1, "Slot(%d): Slot RESET", slot);
-	udelay(500); /* Wait.. */
-	mmwrite(0xda, MANTIS_PCMCIA_RESET); /* Leading edge assert */
-	udelay(500);
-	mmwrite(0x00, MANTIS_PCMCIA_RESET); /* Trailing edge deassert */
-	msleep(1000);
-	dvb_ca_en50221_camready_irq(&ca->en50221, 0);
-
-	return 0;
-}
-
-static int mantis_ca_slot_shutdown(struct dvb_ca_en50221 *en50221, int slot)
-{
-	struct mantis_ca *ca = en50221->data;
-	struct mantis_pci *mantis = ca->ca_priv;
-
-	dprintk(MANTIS_DEBUG, 1, "Slot(%d): Slot shutdown", slot);
-
-	return 0;
-}
-
-static int mantis_ts_control(struct dvb_ca_en50221 *en50221, int slot)
-{
-	struct mantis_ca *ca = en50221->data;
-	struct mantis_pci *mantis = ca->ca_priv;
-
-	dprintk(MANTIS_DEBUG, 1, "Slot(%d): TS control", slot);
-/*	mantis_set_direction(mantis, 1); */ /* Enable TS through CAM */
-
-	return 0;
-}
-
-static int mantis_slot_status(struct dvb_ca_en50221 *en50221, int slot, int open)
-{
-	struct mantis_ca *ca = en50221->data;
-	struct mantis_pci *mantis = ca->ca_priv;
-
-	dprintk(MANTIS_DEBUG, 1, "Slot(%d): Poll Slot status", slot);
-
-	if (ca->slot_state == MODULE_INSERTED) {
-		dprintk(MANTIS_DEBUG, 1, "CA Module present and ready");
-		return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY;
-	} else {
-		dprintk(MANTIS_DEBUG, 1, "CA Module not present or not ready");
-	}
-
-	return 0;
-}
-
-int mantis_ca_init(struct mantis_pci *mantis)
-{
-	struct dvb_adapter *dvb_adapter	= &mantis->dvb_adapter;
-	struct mantis_ca *ca;
-	int ca_flags = 0, result;
-
-	dprintk(MANTIS_DEBUG, 1, "Initializing Mantis CA");
-	ca = kzalloc(sizeof(struct mantis_ca), GFP_KERNEL);
-	if (!ca) {
-		dprintk(MANTIS_ERROR, 1, "Out of memory!, exiting ..");
-		result = -ENOMEM;
-		goto err;
-	}
-
-	ca->ca_priv		= mantis;
-	mantis->mantis_ca	= ca;
-	ca_flags		= DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE;
-	/* register CA interface */
-	ca->en50221.owner		= THIS_MODULE;
-	ca->en50221.read_attribute_mem	= mantis_ca_read_attr_mem;
-	ca->en50221.write_attribute_mem	= mantis_ca_write_attr_mem;
-	ca->en50221.read_cam_control	= mantis_ca_read_cam_ctl;
-	ca->en50221.write_cam_control	= mantis_ca_write_cam_ctl;
-	ca->en50221.slot_reset		= mantis_ca_slot_reset;
-	ca->en50221.slot_shutdown	= mantis_ca_slot_shutdown;
-	ca->en50221.slot_ts_enable	= mantis_ts_control;
-	ca->en50221.poll_slot_status	= mantis_slot_status;
-	ca->en50221.data		= ca;
-
-	mutex_init(&ca->ca_lock);
-
-	init_waitqueue_head(&ca->hif_data_wq);
-	init_waitqueue_head(&ca->hif_opdone_wq);
-	init_waitqueue_head(&ca->hif_write_wq);
-
-	dprintk(MANTIS_ERROR, 1, "Registering EN50221 device");
-	result = dvb_ca_en50221_init(dvb_adapter, &ca->en50221, ca_flags, 1);
-	if (result != 0) {
-		dprintk(MANTIS_ERROR, 1, "EN50221: Initialization failed <%d>", result);
-		goto err;
-	}
-	dprintk(MANTIS_ERROR, 1, "Registered EN50221 device");
-	mantis_evmgr_init(ca);
-	return 0;
-err:
-	kfree(ca);
-	return result;
-}
-EXPORT_SYMBOL_GPL(mantis_ca_init);
-
-void mantis_ca_exit(struct mantis_pci *mantis)
-{
-	struct mantis_ca *ca = mantis->mantis_ca;
-
-	dprintk(MANTIS_DEBUG, 1, "Mantis CA exit");
-
-	mantis_evmgr_exit(ca);
-	dprintk(MANTIS_ERROR, 1, "Unregistering EN50221 device");
-	if (ca)
-		dvb_ca_en50221_release(&ca->en50221);
-
-	kfree(ca);
-}
-EXPORT_SYMBOL_GPL(mantis_ca_exit);
diff --git a/drivers/media/dvb/mantis/mantis_ca.h b/drivers/media/dvb/mantis/mantis_ca.h
deleted file mode 100644
index dc63e55..0000000
--- a/drivers/media/dvb/mantis/mantis_ca.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
-	Mantis PCI bridge driver
-
-	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#ifndef __MANTIS_CA_H
-#define __MANTIS_CA_H
-
-extern int mantis_ca_init(struct mantis_pci *mantis);
-extern void mantis_ca_exit(struct mantis_pci *mantis);
-
-#endif /* __MANTIS_CA_H */
diff --git a/drivers/media/dvb/mantis/mantis_cards.c b/drivers/media/dvb/mantis/mantis_cards.c
deleted file mode 100644
index 095cf3a..0000000
--- a/drivers/media/dvb/mantis/mantis_cards.c
+++ /dev/null
@@ -1,307 +0,0 @@
-/*
-	Mantis PCI bridge driver
-
-	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-#include <asm/irq.h>
-#include <linux/interrupt.h>
-
-#include "dmxdev.h"
-#include "dvbdev.h"
-#include "dvb_demux.h"
-#include "dvb_frontend.h"
-#include "dvb_net.h"
-
-#include "mantis_common.h"
-
-#include "mantis_vp1033.h"
-#include "mantis_vp1034.h"
-#include "mantis_vp1041.h"
-#include "mantis_vp2033.h"
-#include "mantis_vp2040.h"
-#include "mantis_vp3030.h"
-
-#include "mantis_dma.h"
-#include "mantis_ca.h"
-#include "mantis_dvb.h"
-#include "mantis_uart.h"
-#include "mantis_ioc.h"
-#include "mantis_pci.h"
-#include "mantis_i2c.h"
-#include "mantis_reg.h"
-
-static unsigned int verbose;
-module_param(verbose, int, 0644);
-MODULE_PARM_DESC(verbose, "verbose startup messages, default is 0 (no)");
-
-static int devs;
-
-#define DRIVER_NAME	"Mantis"
-
-static char *label[10] = {
-	"DMA",
-	"IRQ-0",
-	"IRQ-1",
-	"OCERR",
-	"PABRT",
-	"RIPRR",
-	"PPERR",
-	"FTRGT",
-	"RISCI",
-	"RACK"
-};
-
-static irqreturn_t mantis_irq_handler(int irq, void *dev_id)
-{
-	u32 stat = 0, mask = 0;
-	u32 rst_stat = 0, rst_mask = 0;
-
-	struct mantis_pci *mantis;
-	struct mantis_ca *ca;
-
-	mantis = (struct mantis_pci *) dev_id;
-	if (unlikely(mantis == NULL)) {
-		dprintk(MANTIS_ERROR, 1, "Mantis == NULL");
-		return IRQ_NONE;
-	}
-	ca = mantis->mantis_ca;
-
-	stat = mmread(MANTIS_INT_STAT);
-	mask = mmread(MANTIS_INT_MASK);
-	if (!(stat & mask))
-		return IRQ_NONE;
-
-	rst_mask  = MANTIS_GPIF_WRACK  |
-		    MANTIS_GPIF_OTHERR |
-		    MANTIS_SBUF_WSTO   |
-		    MANTIS_GPIF_EXTIRQ;
-
-	rst_stat  = mmread(MANTIS_GPIF_STATUS);
-	rst_stat &= rst_mask;
-	mmwrite(rst_stat, MANTIS_GPIF_STATUS);
-
-	mantis->mantis_int_stat = stat;
-	mantis->mantis_int_mask = mask;
-	dprintk(MANTIS_DEBUG, 0, "\n-- Stat=<%02x> Mask=<%02x> --", stat, mask);
-	if (stat & MANTIS_INT_RISCEN) {
-		dprintk(MANTIS_DEBUG, 0, "<%s>", label[0]);
-	}
-	if (stat & MANTIS_INT_IRQ0) {
-		dprintk(MANTIS_DEBUG, 0, "<%s>", label[1]);
-		mantis->gpif_status = rst_stat;
-		wake_up(&ca->hif_write_wq);
-		schedule_work(&ca->hif_evm_work);
-	}
-	if (stat & MANTIS_INT_IRQ1) {
-		dprintk(MANTIS_DEBUG, 0, "<%s>", label[2]);
-		schedule_work(&mantis->uart_work);
-	}
-	if (stat & MANTIS_INT_OCERR) {
-		dprintk(MANTIS_DEBUG, 0, "<%s>", label[3]);
-	}
-	if (stat & MANTIS_INT_PABORT) {
-		dprintk(MANTIS_DEBUG, 0, "<%s>", label[4]);
-	}
-	if (stat & MANTIS_INT_RIPERR) {
-		dprintk(MANTIS_DEBUG, 0, "<%s>", label[5]);
-	}
-	if (stat & MANTIS_INT_PPERR) {
-		dprintk(MANTIS_DEBUG, 0, "<%s>", label[6]);
-	}
-	if (stat & MANTIS_INT_FTRGT) {
-		dprintk(MANTIS_DEBUG, 0, "<%s>", label[7]);
-	}
-	if (stat & MANTIS_INT_RISCI) {
-		dprintk(MANTIS_DEBUG, 0, "<%s>", label[8]);
-		mantis->busy_block = (stat & MANTIS_INT_RISCSTAT) >> 28;
-		tasklet_schedule(&mantis->tasklet);
-	}
-	if (stat & MANTIS_INT_I2CDONE) {
-		dprintk(MANTIS_DEBUG, 0, "<%s>", label[9]);
-		wake_up(&mantis->i2c_wq);
-	}
-	mmwrite(stat, MANTIS_INT_STAT);
-	stat &= ~(MANTIS_INT_RISCEN   | MANTIS_INT_I2CDONE |
-		  MANTIS_INT_I2CRACK  | MANTIS_INT_PCMCIA7 |
-		  MANTIS_INT_PCMCIA6  | MANTIS_INT_PCMCIA5 |
-		  MANTIS_INT_PCMCIA4  | MANTIS_INT_PCMCIA3 |
-		  MANTIS_INT_PCMCIA2  | MANTIS_INT_PCMCIA1 |
-		  MANTIS_INT_PCMCIA0  | MANTIS_INT_IRQ1	   |
-		  MANTIS_INT_IRQ0     | MANTIS_INT_OCERR   |
-		  MANTIS_INT_PABORT   | MANTIS_INT_RIPERR  |
-		  MANTIS_INT_PPERR    | MANTIS_INT_FTRGT   |
-		  MANTIS_INT_RISCI);
-
-	if (stat)
-		dprintk(MANTIS_DEBUG, 0, "<Unknown> Stat=<%02x> Mask=<%02x>", stat, mask);
-
-	dprintk(MANTIS_DEBUG, 0, "\n");
-	return IRQ_HANDLED;
-}
-
-static int __devinit mantis_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
-{
-	struct mantis_pci *mantis;
-	struct mantis_hwconfig *config;
-	int err = 0;
-
-	mantis = kzalloc(sizeof(struct mantis_pci), GFP_KERNEL);
-	if (mantis == NULL) {
-		printk(KERN_ERR "%s ERROR: Out of memory\n", __func__);
-		err = -ENOMEM;
-		goto fail0;
-	}
-
-	mantis->num		= devs;
-	mantis->verbose		= verbose;
-	mantis->pdev		= pdev;
-	config			= (struct mantis_hwconfig *) pci_id->driver_data;
-	config->irq_handler	= &mantis_irq_handler;
-	mantis->hwconfig	= config;
-
-	err = mantis_pci_init(mantis);
-	if (err) {
-		dprintk(MANTIS_ERROR, 1, "ERROR: Mantis PCI initialization failed <%d>", err);
-		goto fail1;
-	}
-
-	err = mantis_stream_control(mantis, STREAM_TO_HIF);
-	if (err < 0) {
-		dprintk(MANTIS_ERROR, 1, "ERROR: Mantis stream control failed <%d>", err);
-		goto fail1;
-	}
-
-	err = mantis_i2c_init(mantis);
-	if (err < 0) {
-		dprintk(MANTIS_ERROR, 1, "ERROR: Mantis I2C initialization failed <%d>", err);
-		goto fail2;
-	}
-
-	err = mantis_get_mac(mantis);
-	if (err < 0) {
-		dprintk(MANTIS_ERROR, 1, "ERROR: Mantis MAC address read failed <%d>", err);
-		goto fail2;
-	}
-
-	err = mantis_dma_init(mantis);
-	if (err < 0) {
-		dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DMA initialization failed <%d>", err);
-		goto fail3;
-	}
-
-	err = mantis_dvb_init(mantis);
-	if (err < 0) {
-		dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DVB initialization failed <%d>", err);
-		goto fail4;
-	}
-	err = mantis_uart_init(mantis);
-	if (err < 0) {
-		dprintk(MANTIS_ERROR, 1, "ERROR: Mantis UART initialization failed <%d>", err);
-		goto fail6;
-	}
-
-	devs++;
-
-	return err;
-
-
-	dprintk(MANTIS_ERROR, 1, "ERROR: Mantis UART exit! <%d>", err);
-	mantis_uart_exit(mantis);
-
-fail6:
-fail4:
-	dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DMA exit! <%d>", err);
-	mantis_dma_exit(mantis);
-
-fail3:
-	dprintk(MANTIS_ERROR, 1, "ERROR: Mantis I2C exit! <%d>", err);
-	mantis_i2c_exit(mantis);
-
-fail2:
-	dprintk(MANTIS_ERROR, 1, "ERROR: Mantis PCI exit! <%d>", err);
-	mantis_pci_exit(mantis);
-
-fail1:
-	dprintk(MANTIS_ERROR, 1, "ERROR: Mantis free! <%d>", err);
-	kfree(mantis);
-
-fail0:
-	return err;
-}
-
-static void __devexit mantis_pci_remove(struct pci_dev *pdev)
-{
-	struct mantis_pci *mantis = pci_get_drvdata(pdev);
-
-	if (mantis) {
-
-		mantis_uart_exit(mantis);
-		mantis_dvb_exit(mantis);
-		mantis_dma_exit(mantis);
-		mantis_i2c_exit(mantis);
-		mantis_pci_exit(mantis);
-		kfree(mantis);
-	}
-	return;
-}
-
-static struct pci_device_id mantis_pci_table[] = {
-	MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_1033_DVB_S, &vp1033_config),
-	MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_1034_DVB_S, &vp1034_config),
-	MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_1041_DVB_S2, &vp1041_config),
-	MAKE_ENTRY(TECHNISAT, SKYSTAR_HD2_10, &vp1041_config),
-	MAKE_ENTRY(TECHNISAT, SKYSTAR_HD2_20, &vp1041_config),
-	MAKE_ENTRY(TERRATEC, CINERGY_S2_PCI_HD, &vp1041_config),
-	MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_2033_DVB_C, &vp2033_config),
-	MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_2040_DVB_C, &vp2040_config),
-	MAKE_ENTRY(TECHNISAT, CABLESTAR_HD2, &vp2040_config),
-	MAKE_ENTRY(TERRATEC, CINERGY_C, &vp2033_config),
-	MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_3030_DVB_T, &vp3030_config),
-	{ }
-};
-
-MODULE_DEVICE_TABLE(pci, mantis_pci_table);
-
-static struct pci_driver mantis_pci_driver = {
-	.name		= DRIVER_NAME,
-	.id_table	= mantis_pci_table,
-	.probe		= mantis_pci_probe,
-	.remove		= mantis_pci_remove,
-};
-
-static int __devinit mantis_init(void)
-{
-	return pci_register_driver(&mantis_pci_driver);
-}
-
-static void __devexit mantis_exit(void)
-{
-	return pci_unregister_driver(&mantis_pci_driver);
-}
-
-module_init(mantis_init);
-module_exit(mantis_exit);
-
-MODULE_DESCRIPTION("MANTIS driver");
-MODULE_AUTHOR("Manu Abraham");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/mantis/mantis_common.h b/drivers/media/dvb/mantis/mantis_common.h
deleted file mode 100644
index f2410cf..0000000
--- a/drivers/media/dvb/mantis/mantis_common.h
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
-	Mantis PCI bridge driver
-
-	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#ifndef __MANTIS_COMMON_H
-#define __MANTIS_COMMON_H
-
-#include <linux/interrupt.h>
-#include <linux/mutex.h>
-#include <linux/workqueue.h>
-
-#include "mantis_uart.h"
-
-#include "mantis_link.h"
-
-#define MANTIS_ERROR		0
-#define MANTIS_NOTICE		1
-#define MANTIS_INFO		2
-#define MANTIS_DEBUG		3
-#define MANTIS_TMG		9
-
-#define dprintk(y, z, format, arg...) do {								\
-	if (z) {											\
-		if	((mantis->verbose > MANTIS_ERROR) && (mantis->verbose > y))			\
-			printk(KERN_ERR "%s (%d): " format "\n" , __func__ , mantis->num , ##arg);	\
-		else if	((mantis->verbose > MANTIS_NOTICE) && (mantis->verbose > y))			\
-			printk(KERN_NOTICE "%s (%d): " format "\n" , __func__ , mantis->num , ##arg);	\
-		else if ((mantis->verbose > MANTIS_INFO) && (mantis->verbose > y))			\
-			printk(KERN_INFO "%s (%d): " format "\n" , __func__ , mantis->num , ##arg);	\
-		else if ((mantis->verbose > MANTIS_DEBUG) && (mantis->verbose > y))			\
-			printk(KERN_DEBUG "%s (%d): " format "\n" , __func__ , mantis->num , ##arg);	\
-		else if ((mantis->verbose > MANTIS_TMG) && (mantis->verbose > y))			\
-			printk(KERN_DEBUG "%s (%d): " format "\n" , __func__ , mantis->num , ##arg);	\
-	} else {											\
-		if (mantis->verbose > y)								\
-			printk(format , ##arg);								\
-	}												\
-} while(0)
-
-#define mwrite(dat, addr)	writel((dat), addr)
-#define mread(addr)		readl(addr)
-
-#define mmwrite(dat, addr)	mwrite((dat), (mantis->mmio + (addr)))
-#define mmread(addr)		mread(mantis->mmio + (addr))
-
-#define MANTIS_TS_188		0
-#define MANTIS_TS_204		1
-
-#define TWINHAN_TECHNOLOGIES	0x1822
-#define MANTIS			0x4e35
-
-#define TECHNISAT		0x1ae4
-#define TERRATEC		0x153b
-
-#define MAKE_ENTRY(__subven, __subdev, __configptr) {			\
-		.vendor		= TWINHAN_TECHNOLOGIES,			\
-		.device		= MANTIS,				\
-		.subvendor	= (__subven),				\
-		.subdevice	= (__subdev),				\
-		.driver_data	= (unsigned long) (__configptr)		\
-}
-
-enum mantis_i2c_mode {
-	MANTIS_PAGE_MODE = 0,
-	MANTIS_BYTE_MODE,
-};
-
-struct mantis_pci;
-
-struct mantis_hwconfig {
-	char			*model_name;
-	char			*dev_type;
-	u32			ts_size;
-
-	enum mantis_baud	baud_rate;
-	enum mantis_parity	parity;
-	u32			bytes;
-
-	irqreturn_t (*irq_handler)(int irq, void *dev_id);
-	int (*frontend_init)(struct mantis_pci *mantis, struct dvb_frontend *fe);
-
-	u8			power;
-	u8			reset;
-
-	enum mantis_i2c_mode	i2c_mode;
-};
-
-struct mantis_pci {
-	unsigned int		verbose;
-
-	/*	PCI stuff		*/
-	u16			vendor_id;
-	u16			device_id;
-	u16			subsystem_vendor;
-	u16			subsystem_device;
-
-	u8			latency;
-
-	struct pci_dev		*pdev;
-
-	unsigned long		mantis_addr;
-	void __iomem		*mmio;
-
-	u8			irq;
-	u8			revision;
-
-	unsigned int		num;
-
-	/*	RISC Core		*/
-	u32			busy_block;
-	u32			last_block;
-	u8			*buf_cpu;
-	dma_addr_t		buf_dma;
-	u32			*risc_cpu;
-	dma_addr_t		risc_dma;
-
-	struct tasklet_struct	tasklet;
-
-	struct i2c_adapter	adapter;
-	int			i2c_rc;
-	wait_queue_head_t	i2c_wq;
-	struct mutex		i2c_lock;
-
-	/*	DVB stuff		*/
-	struct dvb_adapter	dvb_adapter;
-	struct dvb_frontend	*fe;
-	struct dvb_demux	demux;
-	struct dmxdev		dmxdev;
-	struct dmx_frontend	fe_hw;
-	struct dmx_frontend	fe_mem;
-	struct dvb_net		dvbnet;
-
-	u8			feeds;
-
-	struct mantis_hwconfig	*hwconfig;
-
-	u32			mantis_int_stat;
-	u32			mantis_int_mask;
-
-	/*	board specific		*/
-	u8			mac_address[8];
-	u32			sub_vendor_id;
-	u32			sub_device_id;
-
-	 /*	A12 A13 A14		*/
-	u32			gpio_status;
-
-	u32			gpif_status;
-
-	struct mantis_ca	*mantis_ca;
-
-	wait_queue_head_t	uart_wq;
-	struct work_struct	uart_work;
-	spinlock_t		uart_lock;
-
-	struct rc_dev		*rc;
-	char			input_name[80];
-	char			input_phys[80];
-};
-
-#define MANTIS_HIF_STATUS	(mantis->gpio_status)
-
-#endif /* __MANTIS_COMMON_H */
diff --git a/drivers/media/dvb/mantis/mantis_core.c b/drivers/media/dvb/mantis/mantis_core.c
deleted file mode 100644
index 22524a8..0000000
--- a/drivers/media/dvb/mantis/mantis_core.c
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
-	Mantis PCI bridge driver
-
-	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include "mantis_common.h"
-#include "mantis_core.h"
-#include "mantis_vp1033.h"
-#include "mantis_vp1034.h"
-#include "mantis_vp1041.h"
-#include "mantis_vp2033.h"
-#include "mantis_vp2040.h"
-#include "mantis_vp3030.h"
-
-static int read_eeprom_byte(struct mantis_pci *mantis, u8 *data, u8 length)
-{
-	int err;
-	struct i2c_msg msg[] = {
-		{
-			.addr = 0x50,
-			.flags = 0,
-			.buf = data,
-			.len = 1
-		}, {
-			.addr = 0x50,
-			.flags = I2C_M_RD,
-			.buf = data,
-			.len = length
-		},
-	};
-
-	err = i2c_transfer(&mantis->adapter, msg, 2);
-	if (err < 0) {
-		dprintk(verbose, MANTIS_ERROR, 1,
-			"ERROR: i2c read: < err=%i d0=0x%02x d1=0x%02x >",
-			err, data[0], data[1]);
-
-		return err;
-	}
-
-	return 0;
-}
-
-static int write_eeprom_byte(struct mantis_pci *mantis, u8 *data, u8 length)
-{
-	int err;
-
-	struct i2c_msg msg = {
-		.addr = 0x50,
-		.flags = 0,
-		.buf = data,
-		.len = length
-	};
-
-	err = i2c_transfer(&mantis->adapter, &msg, 1);
-	if (err < 0) {
-		dprintk(verbose, MANTIS_ERROR, 1,
-			"ERROR: i2c write: < err=%i length=0x%02x d0=0x%02x, d1=0x%02x >",
-			err, length, data[0], data[1]);
-
-		return err;
-	}
-
-	return 0;
-}
-
-static int get_mac_address(struct mantis_pci *mantis)
-{
-	int err;
-
-	mantis->mac_address[0] = 0x08;
-	err = read_eeprom_byte(mantis, &mantis->mac_address[0], 6);
-	if (err < 0) {
-		dprintk(verbose, MANTIS_ERROR, 1, "Mantis EEPROM read error");
-
-		return err;
-	}
-	dprintk(verbose, MANTIS_ERROR, 0,
-		"    MAC Address=[%pM]\n", mantis->mac_address);
-
-	return 0;
-}
-
-#define MANTIS_MODEL_UNKNOWN	"UNKNOWN"
-#define MANTIS_DEV_UNKNOWN	"UNKNOWN"
-
-struct mantis_hwconfig unknown_device = {
-	.model_name	= MANTIS_MODEL_UNKNOWN,
-	.dev_type	= MANTIS_DEV_UNKNOWN,
-};
-
-static void mantis_load_config(struct mantis_pci *mantis)
-{
-	switch (mantis->subsystem_device) {
-	case MANTIS_VP_1033_DVB_S:	/* VP-1033 */
-		mantis->hwconfig = &vp1033_mantis_config;
-		break;
-	case MANTIS_VP_1034_DVB_S:	/* VP-1034 */
-		mantis->hwconfig = &vp1034_mantis_config;
-		break;
-	case MANTIS_VP_1041_DVB_S2:	/* VP-1041 */
-	case TECHNISAT_SKYSTAR_HD2:
-		mantis->hwconfig = &vp1041_mantis_config;
-		break;
-	case MANTIS_VP_2033_DVB_C:	/* VP-2033 */
-		mantis->hwconfig = &vp2033_mantis_config;
-		break;
-	case MANTIS_VP_2040_DVB_C:	/* VP-2040 */
-	case TERRATEC_CINERGY_C_PCI:	/* VP-2040 clone */
-	case TECHNISAT_CABLESTAR_HD2:
-		mantis->hwconfig = &vp2040_mantis_config;
-		break;
-	case MANTIS_VP_3030_DVB_T:	/* VP-3030 */
-		mantis->hwconfig = &vp3030_mantis_config;
-		break;
-	default:
-		mantis->hwconfig = &unknown_device;
-		break;
-	}
-}
-
-int mantis_core_init(struct mantis_pci *mantis)
-{
-	int err = 0;
-
-	mantis_load_config(mantis);
-	dprintk(verbose, MANTIS_ERROR, 0, "found a %s PCI %s device on (%02x:%02x.%x),\n",
-		mantis->hwconfig->model_name, mantis->hwconfig->dev_type,
-		mantis->pdev->bus->number, PCI_SLOT(mantis->pdev->devfn), PCI_FUNC(mantis->pdev->devfn));
-	dprintk(verbose, MANTIS_ERROR, 0, "    Mantis Rev %d [%04x:%04x], ",
-		mantis->revision,
-		mantis->subsystem_vendor, mantis->subsystem_device);
-	dprintk(verbose, MANTIS_ERROR, 0,
-		"irq: %d, latency: %d\n    memory: 0x%lx, mmio: 0x%p\n",
-		mantis->pdev->irq, mantis->latency,
-		mantis->mantis_addr, mantis->mantis_mmio);
-
-	err = mantis_i2c_init(mantis);
-	if (err < 0) {
-		dprintk(verbose, MANTIS_ERROR, 1, "Mantis I2C init failed");
-		return err;
-	}
-	err = get_mac_address(mantis);
-	if (err < 0) {
-		dprintk(verbose, MANTIS_ERROR, 1, "get MAC address failed");
-		return err;
-	}
-	err = mantis_dma_init(mantis);
-	if (err < 0) {
-		dprintk(verbose, MANTIS_ERROR, 1, "Mantis DMA init failed");
-		return err;
-	}
-	err = mantis_dvb_init(mantis);
-	if (err < 0) {
-		dprintk(verbose, MANTIS_DEBUG, 1, "Mantis DVB init failed");
-		return err;
-	}
-	err = mantis_uart_init(mantis);
-	if (err < 0) {
-		dprintk(verbose, MANTIS_DEBUG, 1, "Mantis UART init failed");
-		return err;
-	}
-
-	return 0;
-}
-
-int mantis_core_exit(struct mantis_pci *mantis)
-{
-	mantis_dma_stop(mantis);
-	dprintk(verbose, MANTIS_ERROR, 1, "DMA engine stopping");
-
-	mantis_uart_exit(mantis);
-	dprintk(verbose, MANTIS_ERROR, 1, "UART exit failed");
-
-	if (mantis_dma_exit(mantis) < 0)
-		dprintk(verbose, MANTIS_ERROR, 1, "DMA exit failed");
-	if (mantis_dvb_exit(mantis) < 0)
-		dprintk(verbose, MANTIS_ERROR, 1, "DVB exit failed");
-	if (mantis_i2c_exit(mantis) < 0)
-		dprintk(verbose, MANTIS_ERROR, 1, "I2C adapter delete.. failed");
-
-	return 0;
-}
-
-/* Turn the given bit on or off. */
-void gpio_set_bits(struct mantis_pci *mantis, u32 bitpos, u8 value)
-{
-	u32 cur;
-
-	cur = mmread(MANTIS_GPIF_ADDR);
-	if (value)
-		mantis->gpio_status = cur | (1 << bitpos);
-	else
-		mantis->gpio_status = cur & (~(1 << bitpos));
-
-	mmwrite(mantis->gpio_status, MANTIS_GPIF_ADDR);
-	mmwrite(0x00, MANTIS_GPIF_DOUT);
-	udelay(100);
-}
-
-/* direction = 0 , no CI passthrough ; 1 , CI passthrough */
-void mantis_set_direction(struct mantis_pci *mantis, int direction)
-{
-	u32 reg;
-
-	reg = mmread(0x28);
-	dprintk(verbose, MANTIS_DEBUG, 1, "TS direction setup");
-	if (direction == 0x01) {
-		/* to CI */
-		reg |= 0x04;
-		mmwrite(reg, 0x28);
-		reg &= 0xff - 0x04;
-		mmwrite(reg, 0x28);
-	} else {
-		reg &= 0xff - 0x04;
-		mmwrite(reg, 0x28);
-		reg |= 0x04;
-		mmwrite(reg, 0x28);
-	}
-}
diff --git a/drivers/media/dvb/mantis/mantis_core.h b/drivers/media/dvb/mantis/mantis_core.h
deleted file mode 100644
index 833ee42..0000000
--- a/drivers/media/dvb/mantis/mantis_core.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
-	Mantis PCI bridge driver
-
-	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#ifndef __MANTIS_CORE_H
-#define __MANTIS_CORE_H
-
-#include "mantis_common.h"
-
-
-#define FE_TYPE_SAT	0
-#define FE_TYPE_CAB	1
-#define FE_TYPE_TER	2
-
-#define FE_TYPE_TS204	0
-#define FE_TYPE_TS188	1
-
-
-struct vendorname {
-	u8  *sub_vendor_name;
-	u32 sub_vendor_id;
-};
-
-struct devicetype {
-	u8  *sub_device_name;
-	u32 sub_device_id;
-	u8  device_type;
-	u32 type_flags;
-};
-
-
-extern int mantis_dma_init(struct mantis_pci *mantis);
-extern int mantis_dma_exit(struct mantis_pci *mantis);
-extern void mantis_dma_start(struct mantis_pci *mantis);
-extern void mantis_dma_stop(struct mantis_pci *mantis);
-extern int mantis_i2c_init(struct mantis_pci *mantis);
-extern int mantis_i2c_exit(struct mantis_pci *mantis);
-extern int mantis_core_init(struct mantis_pci *mantis);
-extern int mantis_core_exit(struct mantis_pci *mantis);
-
-#endif /* __MANTIS_CORE_H */
diff --git a/drivers/media/dvb/mantis/mantis_dma.c b/drivers/media/dvb/mantis/mantis_dma.c
deleted file mode 100644
index 566c407..0000000
--- a/drivers/media/dvb/mantis/mantis_dma.c
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
-	Mantis PCI bridge driver
-
-	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include <linux/kernel.h>
-#include <asm/page.h>
-#include <linux/vmalloc.h>
-#include <linux/pci.h>
-
-#include <asm/irq.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-
-#include "dmxdev.h"
-#include "dvbdev.h"
-#include "dvb_demux.h"
-#include "dvb_frontend.h"
-#include "dvb_net.h"
-
-#include "mantis_common.h"
-#include "mantis_reg.h"
-#include "mantis_dma.h"
-
-#define RISC_WRITE		(0x01 << 28)
-#define RISC_JUMP		(0x07 << 28)
-#define RISC_IRQ		(0x01 << 24)
-
-#define RISC_STATUS(status)	((((~status) & 0x0f) << 20) | ((status & 0x0f) << 16))
-#define RISC_FLUSH(risc_pos)		(risc_pos = 0)
-#define RISC_INSTR(risc_pos, opcode)	(mantis->risc_cpu[risc_pos++] = cpu_to_le32(opcode))
-
-#define MANTIS_BUF_SIZE		(64 * 1024)
-#define MANTIS_BLOCK_BYTES      (MANTIS_BUF_SIZE / 4)
-#define MANTIS_DMA_TR_BYTES     (2 * 1024) /* upper limit: 4095 bytes. */
-#define MANTIS_BLOCK_COUNT	(MANTIS_BUF_SIZE / MANTIS_BLOCK_BYTES)
-
-#define MANTIS_DMA_TR_UNITS     (MANTIS_BLOCK_BYTES / MANTIS_DMA_TR_BYTES)
-/* MANTIS_BUF_SIZE / MANTIS_DMA_TR_UNITS must not exceed MANTIS_RISC_SIZE (4k RISC cmd buffer) */
-#define MANTIS_RISC_SIZE	PAGE_SIZE /* RISC program must fit here. */
-
-int mantis_dma_exit(struct mantis_pci *mantis)
-{
-	if (mantis->buf_cpu) {
-		dprintk(MANTIS_ERROR, 1,
-			"DMA=0x%lx cpu=0x%p size=%d",
-			(unsigned long) mantis->buf_dma,
-			 mantis->buf_cpu,
-			 MANTIS_BUF_SIZE);
-
-		pci_free_consistent(mantis->pdev, MANTIS_BUF_SIZE,
-				    mantis->buf_cpu, mantis->buf_dma);
-
-		mantis->buf_cpu = NULL;
-	}
-	if (mantis->risc_cpu) {
-		dprintk(MANTIS_ERROR, 1,
-			"RISC=0x%lx cpu=0x%p size=%lx",
-			(unsigned long) mantis->risc_dma,
-			mantis->risc_cpu,
-			MANTIS_RISC_SIZE);
-
-		pci_free_consistent(mantis->pdev, MANTIS_RISC_SIZE,
-				    mantis->risc_cpu, mantis->risc_dma);
-
-		mantis->risc_cpu = NULL;
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(mantis_dma_exit);
-
-static inline int mantis_alloc_buffers(struct mantis_pci *mantis)
-{
-	if (!mantis->buf_cpu) {
-		mantis->buf_cpu = pci_alloc_consistent(mantis->pdev,
-						       MANTIS_BUF_SIZE,
-						       &mantis->buf_dma);
-		if (!mantis->buf_cpu) {
-			dprintk(MANTIS_ERROR, 1,
-				"DMA buffer allocation failed");
-
-			goto err;
-		}
-		dprintk(MANTIS_ERROR, 1,
-			"DMA=0x%lx cpu=0x%p size=%d",
-			(unsigned long) mantis->buf_dma,
-			mantis->buf_cpu, MANTIS_BUF_SIZE);
-	}
-	if (!mantis->risc_cpu) {
-		mantis->risc_cpu = pci_alloc_consistent(mantis->pdev,
-							MANTIS_RISC_SIZE,
-							&mantis->risc_dma);
-
-		if (!mantis->risc_cpu) {
-			dprintk(MANTIS_ERROR, 1,
-				"RISC program allocation failed");
-
-			mantis_dma_exit(mantis);
-
-			goto err;
-		}
-		dprintk(MANTIS_ERROR, 1,
-			"RISC=0x%lx cpu=0x%p size=%lx",
-			(unsigned long) mantis->risc_dma,
-			mantis->risc_cpu, MANTIS_RISC_SIZE);
-	}
-
-	return 0;
-err:
-	dprintk(MANTIS_ERROR, 1, "Out of memory (?) .....");
-	return -ENOMEM;
-}
-
-int mantis_dma_init(struct mantis_pci *mantis)
-{
-	int err = 0;
-
-	dprintk(MANTIS_DEBUG, 1, "Mantis DMA init");
-	if (mantis_alloc_buffers(mantis) < 0) {
-		dprintk(MANTIS_ERROR, 1, "Error allocating DMA buffer");
-
-		/* Stop RISC Engine */
-		mmwrite(0, MANTIS_DMA_CTL);
-
-		goto err;
-	}
-
-	return 0;
-err:
-	return err;
-}
-EXPORT_SYMBOL_GPL(mantis_dma_init);
-
-static inline void mantis_risc_program(struct mantis_pci *mantis)
-{
-	u32 buf_pos = 0;
-	u32 line, step;
-	u32 risc_pos;
-
-	dprintk(MANTIS_DEBUG, 1, "Mantis create RISC program");
-	RISC_FLUSH(risc_pos);
-
-	dprintk(MANTIS_DEBUG, 1, "risc len lines %u, bytes per line %u, bytes per DMA tr %u",
-		MANTIS_BLOCK_COUNT, MANTIS_BLOCK_BYTES, MANTIS_DMA_TR_BYTES);
-
-	for (line = 0; line < MANTIS_BLOCK_COUNT; line++) {
-		for (step = 0; step < MANTIS_DMA_TR_UNITS; step++) {
-			dprintk(MANTIS_DEBUG, 1, "RISC PROG line=[%d], step=[%d]", line, step);
-			if (step == 0) {
-				RISC_INSTR(risc_pos, RISC_WRITE	|
-					   RISC_IRQ	|
-					   RISC_STATUS(line) |
-					   MANTIS_DMA_TR_BYTES);
-			} else {
-				RISC_INSTR(risc_pos, RISC_WRITE | MANTIS_DMA_TR_BYTES);
-			}
-			RISC_INSTR(risc_pos, mantis->buf_dma + buf_pos);
-			buf_pos += MANTIS_DMA_TR_BYTES;
-		  }
-	}
-	RISC_INSTR(risc_pos, RISC_JUMP);
-	RISC_INSTR(risc_pos, mantis->risc_dma);
-}
-
-void mantis_dma_start(struct mantis_pci *mantis)
-{
-	dprintk(MANTIS_DEBUG, 1, "Mantis Start DMA engine");
-
-	mantis_risc_program(mantis);
-	mmwrite(mantis->risc_dma, MANTIS_RISC_START);
-	mmwrite(mmread(MANTIS_GPIF_ADDR) | MANTIS_GPIF_HIFRDWRN, MANTIS_GPIF_ADDR);
-
-	mmwrite(0, MANTIS_DMA_CTL);
-	mantis->last_block = mantis->busy_block = 0;
-
-	mmwrite(mmread(MANTIS_INT_MASK) | MANTIS_INT_RISCI, MANTIS_INT_MASK);
-
-	mmwrite(MANTIS_FIFO_EN | MANTIS_DCAP_EN
-			       | MANTIS_RISC_EN, MANTIS_DMA_CTL);
-
-}
-
-void mantis_dma_stop(struct mantis_pci *mantis)
-{
-	dprintk(MANTIS_DEBUG, 1, "Mantis Stop DMA engine");
-
-	mmwrite((mmread(MANTIS_GPIF_ADDR) & (~(MANTIS_GPIF_HIFRDWRN))), MANTIS_GPIF_ADDR);
-
-	mmwrite((mmread(MANTIS_DMA_CTL) & ~(MANTIS_FIFO_EN |
-					    MANTIS_DCAP_EN |
-					    MANTIS_RISC_EN)), MANTIS_DMA_CTL);
-
-	mmwrite(mmread(MANTIS_INT_STAT), MANTIS_INT_STAT);
-
-	mmwrite(mmread(MANTIS_INT_MASK) & ~(MANTIS_INT_RISCI |
-					    MANTIS_INT_RISCEN), MANTIS_INT_MASK);
-}
-
-
-void mantis_dma_xfer(unsigned long data)
-{
-	struct mantis_pci *mantis = (struct mantis_pci *) data;
-	struct mantis_hwconfig *config = mantis->hwconfig;
-
-	while (mantis->last_block != mantis->busy_block) {
-		dprintk(MANTIS_DEBUG, 1, "last block=[%d] finished block=[%d]",
-			mantis->last_block, mantis->busy_block);
-
-		(config->ts_size ? dvb_dmx_swfilter_204 : dvb_dmx_swfilter)
-		(&mantis->demux, &mantis->buf_cpu[mantis->last_block * MANTIS_BLOCK_BYTES], MANTIS_BLOCK_BYTES);
-		mantis->last_block = (mantis->last_block + 1) % MANTIS_BLOCK_COUNT;
-	}
-}
diff --git a/drivers/media/dvb/mantis/mantis_dma.h b/drivers/media/dvb/mantis/mantis_dma.h
deleted file mode 100644
index 6be00fa..0000000
--- a/drivers/media/dvb/mantis/mantis_dma.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
-	Mantis PCI bridge driver
-
-	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#ifndef __MANTIS_DMA_H
-#define __MANTIS_DMA_H
-
-extern int mantis_dma_init(struct mantis_pci *mantis);
-extern int mantis_dma_exit(struct mantis_pci *mantis);
-extern void mantis_dma_start(struct mantis_pci *mantis);
-extern void mantis_dma_stop(struct mantis_pci *mantis);
-extern void mantis_dma_xfer(unsigned long data);
-
-#endif /* __MANTIS_DMA_H */
diff --git a/drivers/media/dvb/mantis/mantis_dvb.c b/drivers/media/dvb/mantis/mantis_dvb.c
deleted file mode 100644
index e5180e4..0000000
--- a/drivers/media/dvb/mantis/mantis_dvb.c
+++ /dev/null
@@ -1,299 +0,0 @@
-/*
-	Mantis PCI bridge driver
-	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include <linux/kernel.h>
-#include <linux/bitops.h>
-
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/i2c.h>
-
-#include "dmxdev.h"
-#include "dvbdev.h"
-#include "dvb_demux.h"
-#include "dvb_frontend.h"
-#include "dvb_net.h"
-
-#include "mantis_common.h"
-#include "mantis_dma.h"
-#include "mantis_ca.h"
-#include "mantis_ioc.h"
-#include "mantis_dvb.h"
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-int mantis_frontend_power(struct mantis_pci *mantis, enum mantis_power power)
-{
-	struct mantis_hwconfig *config = mantis->hwconfig;
-
-	switch (power) {
-	case POWER_ON:
-		dprintk(MANTIS_DEBUG, 1, "Power ON");
-		mantis_gpio_set_bits(mantis, config->power, POWER_ON);
-		msleep(100);
-		mantis_gpio_set_bits(mantis, config->power, POWER_ON);
-		msleep(100);
-		break;
-
-	case POWER_OFF:
-		dprintk(MANTIS_DEBUG, 1, "Power OFF");
-		mantis_gpio_set_bits(mantis, config->power, POWER_OFF);
-		msleep(100);
-		break;
-
-	default:
-		dprintk(MANTIS_DEBUG, 1, "Unknown state <%02x>", power);
-		return -1;
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(mantis_frontend_power);
-
-void mantis_frontend_soft_reset(struct mantis_pci *mantis)
-{
-	struct mantis_hwconfig *config = mantis->hwconfig;
-
-	dprintk(MANTIS_DEBUG, 1, "Frontend RESET");
-	mantis_gpio_set_bits(mantis, config->reset, 0);
-	msleep(100);
-	mantis_gpio_set_bits(mantis, config->reset, 0);
-	msleep(100);
-	mantis_gpio_set_bits(mantis, config->reset, 1);
-	msleep(100);
-	mantis_gpio_set_bits(mantis, config->reset, 1);
-	msleep(100);
-
-	return;
-}
-EXPORT_SYMBOL_GPL(mantis_frontend_soft_reset);
-
-static int mantis_frontend_shutdown(struct mantis_pci *mantis)
-{
-	int err;
-
-	mantis_frontend_soft_reset(mantis);
-	err = mantis_frontend_power(mantis, POWER_OFF);
-	if (err != 0) {
-		dprintk(MANTIS_ERROR, 1, "Frontend POWER OFF failed! <%d>", err);
-		return 1;
-	}
-
-	return 0;
-}
-
-static int mantis_dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed)
-{
-	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
-	struct mantis_pci *mantis = dvbdmx->priv;
-
-	dprintk(MANTIS_DEBUG, 1, "Mantis DVB Start feed");
-	if (!dvbdmx->dmx.frontend) {
-		dprintk(MANTIS_DEBUG, 1, "no frontend ?");
-		return -EINVAL;
-	}
-
-	mantis->feeds++;
-	dprintk(MANTIS_DEBUG, 1, "mantis start feed, feeds=%d",	mantis->feeds);
-
-	if (mantis->feeds == 1)	 {
-		dprintk(MANTIS_DEBUG, 1, "mantis start feed & dma");
-		mantis_dma_start(mantis);
-		tasklet_enable(&mantis->tasklet);
-	}
-
-	return mantis->feeds;
-}
-
-static int mantis_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
-{
-	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
-	struct mantis_pci *mantis = dvbdmx->priv;
-
-	dprintk(MANTIS_DEBUG, 1, "Mantis DVB Stop feed");
-	if (!dvbdmx->dmx.frontend) {
-		dprintk(MANTIS_DEBUG, 1, "no frontend ?");
-		return -EINVAL;
-	}
-
-	mantis->feeds--;
-	if (mantis->feeds == 0) {
-		dprintk(MANTIS_DEBUG, 1, "mantis stop feed and dma");
-		tasklet_disable(&mantis->tasklet);
-		mantis_dma_stop(mantis);
-	}
-
-	return 0;
-}
-
-int __devinit mantis_dvb_init(struct mantis_pci *mantis)
-{
-	struct mantis_hwconfig *config = mantis->hwconfig;
-	int result = -1;
-
-	dprintk(MANTIS_DEBUG, 1, "dvb_register_adapter");
-
-	result = dvb_register_adapter(&mantis->dvb_adapter,
-				      "Mantis DVB adapter",
-				      THIS_MODULE,
-				      &mantis->pdev->dev,
-				      adapter_nr);
-
-	if (result < 0) {
-
-		dprintk(MANTIS_ERROR, 1, "Error registering adapter");
-		return -ENODEV;
-	}
-
-	mantis->dvb_adapter.priv	= mantis;
-	mantis->demux.dmx.capabilities	= DMX_TS_FILTERING	|
-					 DMX_SECTION_FILTERING	|
-					 DMX_MEMORY_BASED_FILTERING;
-
-	mantis->demux.priv		= mantis;
-	mantis->demux.filternum		= 256;
-	mantis->demux.feednum		= 256;
-	mantis->demux.start_feed	= mantis_dvb_start_feed;
-	mantis->demux.stop_feed		= mantis_dvb_stop_feed;
-	mantis->demux.write_to_decoder	= NULL;
-
-	dprintk(MANTIS_DEBUG, 1, "dvb_dmx_init");
-	result = dvb_dmx_init(&mantis->demux);
-	if (result < 0) {
-		dprintk(MANTIS_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result);
-
-		goto err0;
-	}
-
-	mantis->dmxdev.filternum	= 256;
-	mantis->dmxdev.demux		= &mantis->demux.dmx;
-	mantis->dmxdev.capabilities	= 0;
-	dprintk(MANTIS_DEBUG, 1, "dvb_dmxdev_init");
-
-	result = dvb_dmxdev_init(&mantis->dmxdev, &mantis->dvb_adapter);
-	if (result < 0) {
-
-		dprintk(MANTIS_ERROR, 1, "dvb_dmxdev_init failed, ERROR=%d", result);
-		goto err1;
-	}
-
-	mantis->fe_hw.source		= DMX_FRONTEND_0;
-	result = mantis->demux.dmx.add_frontend(&mantis->demux.dmx, &mantis->fe_hw);
-	if (result < 0) {
-
-		dprintk(MANTIS_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result);
-		goto err2;
-	}
-
-	mantis->fe_mem.source		= DMX_MEMORY_FE;
-	result = mantis->demux.dmx.add_frontend(&mantis->demux.dmx, &mantis->fe_mem);
-	if (result < 0) {
-		dprintk(MANTIS_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result);
-		goto err3;
-	}
-
-	result = mantis->demux.dmx.connect_frontend(&mantis->demux.dmx, &mantis->fe_hw);
-	if (result < 0) {
-		dprintk(MANTIS_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result);
-		goto err4;
-	}
-
-	dvb_net_init(&mantis->dvb_adapter, &mantis->dvbnet, &mantis->demux.dmx);
-	tasklet_init(&mantis->tasklet, mantis_dma_xfer, (unsigned long) mantis);
-	tasklet_disable(&mantis->tasklet);
-	if (mantis->hwconfig) {
-		result = config->frontend_init(mantis, mantis->fe);
-		if (result < 0) {
-			dprintk(MANTIS_ERROR, 1, "!!! NO Frontends found !!!");
-			goto err5;
-		} else {
-			if (mantis->fe == NULL) {
-				dprintk(MANTIS_ERROR, 1, "FE <NULL>");
-				goto err5;
-			}
-
-			if (dvb_register_frontend(&mantis->dvb_adapter, mantis->fe)) {
-				dprintk(MANTIS_ERROR, 1, "ERROR: Frontend registration failed");
-
-				if (mantis->fe->ops.release)
-					mantis->fe->ops.release(mantis->fe);
-
-				mantis->fe = NULL;
-				goto err5;
-			}
-		}
-	}
-
-	return 0;
-
-	/* Error conditions ..	*/
-err5:
-	tasklet_kill(&mantis->tasklet);
-	dvb_net_release(&mantis->dvbnet);
-	dvb_unregister_frontend(mantis->fe);
-	dvb_frontend_detach(mantis->fe);
-err4:
-	mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_mem);
-
-err3:
-	mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_hw);
-
-err2:
-	dvb_dmxdev_release(&mantis->dmxdev);
-
-err1:
-	dvb_dmx_release(&mantis->demux);
-
-err0:
-	dvb_unregister_adapter(&mantis->dvb_adapter);
-
-	return result;
-}
-EXPORT_SYMBOL_GPL(mantis_dvb_init);
-
-int __devexit mantis_dvb_exit(struct mantis_pci *mantis)
-{
-	int err;
-
-	if (mantis->fe) {
-		/* mantis_ca_exit(mantis); */
-		err = mantis_frontend_shutdown(mantis);
-		if (err != 0)
-			dprintk(MANTIS_ERROR, 1, "Frontend exit while POWER ON! <%d>", err);
-		dvb_unregister_frontend(mantis->fe);
-		dvb_frontend_detach(mantis->fe);
-	}
-
-	tasklet_kill(&mantis->tasklet);
-	dvb_net_release(&mantis->dvbnet);
-
-	mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_mem);
-	mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_hw);
-
-	dvb_dmxdev_release(&mantis->dmxdev);
-	dvb_dmx_release(&mantis->demux);
-
-	dprintk(MANTIS_DEBUG, 1, "dvb_unregister_adapter");
-	dvb_unregister_adapter(&mantis->dvb_adapter);
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(mantis_dvb_exit);
diff --git a/drivers/media/dvb/mantis/mantis_dvb.h b/drivers/media/dvb/mantis/mantis_dvb.h
deleted file mode 100644
index 464199d..0000000
--- a/drivers/media/dvb/mantis/mantis_dvb.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
-	Mantis PCI bridge driver
-
-	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#ifndef __MANTIS_DVB_H
-#define __MANTIS_DVB_H
-
-enum mantis_power {
-	POWER_OFF	= 0,
-	POWER_ON	= 1
-};
-
-extern int mantis_frontend_power(struct mantis_pci *mantis, enum mantis_power power);
-extern void mantis_frontend_soft_reset(struct mantis_pci *mantis);
-
-extern int mantis_dvb_init(struct mantis_pci *mantis);
-extern int mantis_dvb_exit(struct mantis_pci *mantis);
-
-#endif /* __MANTIS_DVB_H */
diff --git a/drivers/media/dvb/mantis/mantis_evm.c b/drivers/media/dvb/mantis/mantis_evm.c
deleted file mode 100644
index 71ce528..0000000
--- a/drivers/media/dvb/mantis/mantis_evm.c
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
-	Mantis PCI bridge driver
-
-	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include <linux/kernel.h>
-
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <asm/io.h>
-
-#include "dmxdev.h"
-#include "dvbdev.h"
-#include "dvb_demux.h"
-#include "dvb_frontend.h"
-#include "dvb_net.h"
-
-#include "mantis_common.h"
-#include "mantis_link.h"
-#include "mantis_hif.h"
-#include "mantis_reg.h"
-
-static void mantis_hifevm_work(struct work_struct *work)
-{
-	struct mantis_ca *ca = container_of(work, struct mantis_ca, hif_evm_work);
-	struct mantis_pci *mantis = ca->ca_priv;
-
-	u32 gpif_stat;
-
-	gpif_stat = mmread(MANTIS_GPIF_STATUS);
-
-	if (gpif_stat & MANTIS_GPIF_DETSTAT) {
-		if (gpif_stat & MANTIS_CARD_PLUGIN) {
-			dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): CAM Plugin", mantis->num);
-			mmwrite(0xdada0000, MANTIS_CARD_RESET);
-			mantis_event_cam_plugin(ca);
-			dvb_ca_en50221_camchange_irq(&ca->en50221,
-						     0,
-						     DVB_CA_EN50221_CAMCHANGE_INSERTED);
-		}
-	} else {
-		if (gpif_stat & MANTIS_CARD_PLUGOUT) {
-			dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): CAM Unplug", mantis->num);
-			mmwrite(0xdada0000, MANTIS_CARD_RESET);
-			mantis_event_cam_unplug(ca);
-			dvb_ca_en50221_camchange_irq(&ca->en50221,
-						     0,
-						     DVB_CA_EN50221_CAMCHANGE_REMOVED);
-		}
-	}
-
-	if (mantis->gpif_status & MANTIS_GPIF_EXTIRQ)
-		dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Ext IRQ", mantis->num);
-
-	if (mantis->gpif_status & MANTIS_SBUF_WSTO)
-		dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Timeout", mantis->num);
-
-	if (mantis->gpif_status & MANTIS_GPIF_OTHERR)
-		dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Alignment Error", mantis->num);
-
-	if (gpif_stat & MANTIS_SBUF_OVFLW)
-		dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Overflow", mantis->num);
-
-	if (gpif_stat & MANTIS_GPIF_BRRDY)
-		dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Read Ready", mantis->num);
-
-	if (gpif_stat & MANTIS_GPIF_INTSTAT)
-		dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): GPIF IRQ", mantis->num);
-
-	if (gpif_stat & MANTIS_SBUF_EMPTY)
-		dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Empty", mantis->num);
-
-	if (gpif_stat & MANTIS_SBUF_OPDONE) {
-		dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer operation complete", mantis->num);
-		ca->sbuf_status = MANTIS_SBUF_DATA_AVAIL;
-		ca->hif_event = MANTIS_SBUF_OPDONE;
-		wake_up(&ca->hif_opdone_wq);
-	}
-}
-
-int mantis_evmgr_init(struct mantis_ca *ca)
-{
-	struct mantis_pci *mantis = ca->ca_priv;
-
-	dprintk(MANTIS_DEBUG, 1, "Initializing Mantis Host I/F Event manager");
-	INIT_WORK(&ca->hif_evm_work, mantis_hifevm_work);
-	mantis_pcmcia_init(ca);
-	schedule_work(&ca->hif_evm_work);
-	mantis_hif_init(ca);
-	return 0;
-}
-
-void mantis_evmgr_exit(struct mantis_ca *ca)
-{
-	struct mantis_pci *mantis = ca->ca_priv;
-
-	dprintk(MANTIS_DEBUG, 1, "Mantis Host I/F Event manager exiting");
-	flush_work_sync(&ca->hif_evm_work);
-	mantis_hif_exit(ca);
-	mantis_pcmcia_exit(ca);
-}
diff --git a/drivers/media/dvb/mantis/mantis_hif.c b/drivers/media/dvb/mantis/mantis_hif.c
deleted file mode 100644
index 10c68df..0000000
--- a/drivers/media/dvb/mantis/mantis_hif.c
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
-	Mantis PCI bridge driver
-
-	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include <linux/kernel.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-
-#include <linux/interrupt.h>
-#include <asm/io.h>
-
-#include "dmxdev.h"
-#include "dvbdev.h"
-#include "dvb_demux.h"
-#include "dvb_frontend.h"
-#include "dvb_net.h"
-
-#include "mantis_common.h"
-
-#include "mantis_hif.h"
-#include "mantis_link.h" /* temporary due to physical layer stuff */
-
-#include "mantis_reg.h"
-
-
-static int mantis_hif_sbuf_opdone_wait(struct mantis_ca *ca)
-{
-	struct mantis_pci *mantis = ca->ca_priv;
-	int rc = 0;
-
-	if (wait_event_timeout(ca->hif_opdone_wq,
-			       ca->hif_event & MANTIS_SBUF_OPDONE,
-			       msecs_to_jiffies(500)) == -ERESTARTSYS) {
-
-		dprintk(MANTIS_ERROR, 1, "Adapter(%d) Slot(0): Smart buffer operation timeout !", mantis->num);
-		rc = -EREMOTEIO;
-	}
-	dprintk(MANTIS_DEBUG, 1, "Smart Buffer Operation complete");
-	ca->hif_event &= ~MANTIS_SBUF_OPDONE;
-	return rc;
-}
-
-static int mantis_hif_write_wait(struct mantis_ca *ca)
-{
-	struct mantis_pci *mantis = ca->ca_priv;
-	u32 opdone = 0, timeout = 0;
-	int rc = 0;
-
-	if (wait_event_timeout(ca->hif_write_wq,
-			       mantis->gpif_status & MANTIS_GPIF_WRACK,
-			       msecs_to_jiffies(500)) == -ERESTARTSYS) {
-
-		dprintk(MANTIS_ERROR, 1, "Adapter(%d) Slot(0): Write ACK timed out !", mantis->num);
-		rc = -EREMOTEIO;
-	}
-	dprintk(MANTIS_DEBUG, 1, "Write Acknowledged");
-	mantis->gpif_status &= ~MANTIS_GPIF_WRACK;
-	while (!opdone) {
-		opdone = (mmread(MANTIS_GPIF_STATUS) & MANTIS_SBUF_OPDONE);
-		udelay(500);
-		timeout++;
-		if (timeout > 100) {
-			dprintk(MANTIS_ERROR, 1, "Adapter(%d) Slot(0): Write operation timed out!", mantis->num);
-			rc = -ETIMEDOUT;
-			break;
-		}
-	}
-	dprintk(MANTIS_DEBUG, 1, "HIF Write success");
-	return rc;
-}
-
-
-int mantis_hif_read_mem(struct mantis_ca *ca, u32 addr)
-{
-	struct mantis_pci *mantis = ca->ca_priv;
-	u32 hif_addr = 0, data, count = 4;
-
-	dprintk(MANTIS_DEBUG, 1, "Adapter(%d) Slot(0): Request HIF Mem Read", mantis->num);
-	mutex_lock(&ca->ca_lock);
-	hif_addr &= ~MANTIS_GPIF_PCMCIAREG;
-	hif_addr &= ~MANTIS_GPIF_PCMCIAIOM;
-	hif_addr |=  MANTIS_HIF_STATUS;
-	hif_addr |=  addr;
-
-	mmwrite(hif_addr, MANTIS_GPIF_BRADDR);
-	mmwrite(count, MANTIS_GPIF_BRBYTES);
-	udelay(20);
-	mmwrite(hif_addr | MANTIS_GPIF_HIFRDWRN, MANTIS_GPIF_ADDR);
-
-	if (mantis_hif_sbuf_opdone_wait(ca) != 0) {
-		dprintk(MANTIS_ERROR, 1, "Adapter(%d) Slot(0): GPIF Smart Buffer operation failed", mantis->num);
-		mutex_unlock(&ca->ca_lock);
-		return -EREMOTEIO;
-	}
-	data = mmread(MANTIS_GPIF_DIN);
-	mutex_unlock(&ca->ca_lock);
-	dprintk(MANTIS_DEBUG, 1, "Mem Read: 0x%02x", data);
-	return (data >> 24) & 0xff;
-}
-
-int mantis_hif_write_mem(struct mantis_ca *ca, u32 addr, u8 data)
-{
-	struct mantis_slot *slot = ca->slot;
-	struct mantis_pci *mantis = ca->ca_priv;
-	u32 hif_addr = 0;
-
-	dprintk(MANTIS_DEBUG, 1, "Adapter(%d) Slot(0): Request HIF Mem Write", mantis->num);
-	mutex_lock(&ca->ca_lock);
-	hif_addr &= ~MANTIS_GPIF_HIFRDWRN;
-	hif_addr &= ~MANTIS_GPIF_PCMCIAREG;
-	hif_addr &= ~MANTIS_GPIF_PCMCIAIOM;
-	hif_addr |=  MANTIS_HIF_STATUS;
-	hif_addr |=  addr;
-
-	mmwrite(slot->slave_cfg, MANTIS_GPIF_CFGSLA); /* Slot0 alone for now */
-	mmwrite(hif_addr, MANTIS_GPIF_ADDR);
-	mmwrite(data, MANTIS_GPIF_DOUT);
-
-	if (mantis_hif_write_wait(ca) != 0) {
-		dprintk(MANTIS_ERROR, 1, "Adapter(%d) Slot(0): HIF Smart Buffer operation failed", mantis->num);
-		mutex_unlock(&ca->ca_lock);
-		return -EREMOTEIO;
-	}
-	dprintk(MANTIS_DEBUG, 1, "Mem Write: (0x%02x to 0x%02x)", data, addr);
-	mutex_unlock(&ca->ca_lock);
-
-	return 0;
-}
-
-int mantis_hif_read_iom(struct mantis_ca *ca, u32 addr)
-{
-	struct mantis_pci *mantis = ca->ca_priv;
-	u32 data, hif_addr = 0;
-
-	dprintk(MANTIS_DEBUG, 1, "Adapter(%d) Slot(0): Request HIF I/O Read", mantis->num);
-	mutex_lock(&ca->ca_lock);
-	hif_addr &= ~MANTIS_GPIF_PCMCIAREG;
-	hif_addr |=  MANTIS_GPIF_PCMCIAIOM;
-	hif_addr |=  MANTIS_HIF_STATUS;
-	hif_addr |=  addr;
-
-	mmwrite(hif_addr, MANTIS_GPIF_BRADDR);
-	mmwrite(1, MANTIS_GPIF_BRBYTES);
-	udelay(20);
-	mmwrite(hif_addr | MANTIS_GPIF_HIFRDWRN, MANTIS_GPIF_ADDR);
-
-	if (mantis_hif_sbuf_opdone_wait(ca) != 0) {
-		dprintk(MANTIS_ERROR, 1, "Adapter(%d) Slot(0): HIF Smart Buffer operation failed", mantis->num);
-		mutex_unlock(&ca->ca_lock);
-		return -EREMOTEIO;
-	}
-	data = mmread(MANTIS_GPIF_DIN);
-	dprintk(MANTIS_DEBUG, 1, "I/O Read: 0x%02x", data);
-	udelay(50);
-	mutex_unlock(&ca->ca_lock);
-
-	return (u8) data;
-}
-
-int mantis_hif_write_iom(struct mantis_ca *ca, u32 addr, u8 data)
-{
-	struct mantis_pci *mantis = ca->ca_priv;
-	u32 hif_addr = 0;
-
-	dprintk(MANTIS_DEBUG, 1, "Adapter(%d) Slot(0): Request HIF I/O Write", mantis->num);
-	mutex_lock(&ca->ca_lock);
-	hif_addr &= ~MANTIS_GPIF_PCMCIAREG;
-	hif_addr &= ~MANTIS_GPIF_HIFRDWRN;
-	hif_addr |=  MANTIS_GPIF_PCMCIAIOM;
-	hif_addr |=  MANTIS_HIF_STATUS;
-	hif_addr |=  addr;
-
-	mmwrite(hif_addr, MANTIS_GPIF_ADDR);
-	mmwrite(data, MANTIS_GPIF_DOUT);
-
-	if (mantis_hif_write_wait(ca) != 0) {
-		dprintk(MANTIS_ERROR, 1, "Adapter(%d) Slot(0): HIF Smart Buffer operation failed", mantis->num);
-		mutex_unlock(&ca->ca_lock);
-		return -EREMOTEIO;
-	}
-	dprintk(MANTIS_DEBUG, 1, "I/O Write: (0x%02x to 0x%02x)", data, addr);
-	mutex_unlock(&ca->ca_lock);
-	udelay(50);
-
-	return 0;
-}
-
-int mantis_hif_init(struct mantis_ca *ca)
-{
-	struct mantis_slot *slot = ca->slot;
-	struct mantis_pci *mantis = ca->ca_priv;
-	u32 irqcfg;
-
-	slot[0].slave_cfg = 0x70773028;
-	dprintk(MANTIS_ERROR, 1, "Adapter(%d) Initializing Mantis Host Interface", mantis->num);
-
-	mutex_lock(&ca->ca_lock);
-	irqcfg = mmread(MANTIS_GPIF_IRQCFG);
-	irqcfg = MANTIS_MASK_BRRDY	|
-		 MANTIS_MASK_WRACK	|
-		 MANTIS_MASK_EXTIRQ	|
-		 MANTIS_MASK_WSTO	|
-		 MANTIS_MASK_OTHERR	|
-		 MANTIS_MASK_OVFLW;
-
-	mmwrite(irqcfg, MANTIS_GPIF_IRQCFG);
-	mutex_unlock(&ca->ca_lock);
-
-	return 0;
-}
-
-void mantis_hif_exit(struct mantis_ca *ca)
-{
-	struct mantis_pci *mantis = ca->ca_priv;
-	u32 irqcfg;
-
-	dprintk(MANTIS_ERROR, 1, "Adapter(%d) Exiting Mantis Host Interface", mantis->num);
-	mutex_lock(&ca->ca_lock);
-	irqcfg = mmread(MANTIS_GPIF_IRQCFG);
-	irqcfg &= ~MANTIS_MASK_BRRDY;
-	mmwrite(irqcfg, MANTIS_GPIF_IRQCFG);
-	mutex_unlock(&ca->ca_lock);
-}
diff --git a/drivers/media/dvb/mantis/mantis_hif.h b/drivers/media/dvb/mantis/mantis_hif.h
deleted file mode 100644
index 9094f9e..0000000
--- a/drivers/media/dvb/mantis/mantis_hif.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
-	Mantis PCI bridge driver
-
-	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#ifndef __MANTIS_HIF_H
-#define __MANTIS_HIF_H
-
-#define MANTIS_HIF_MEMRD		1
-#define MANTIS_HIF_MEMWR		2
-#define MANTIS_HIF_IOMRD		3
-#define MANTIS_HIF_IOMWR		4
-
-#endif /* __MANTIS_HIF_H */
diff --git a/drivers/media/dvb/mantis/mantis_i2c.c b/drivers/media/dvb/mantis/mantis_i2c.c
deleted file mode 100644
index e779451..0000000
--- a/drivers/media/dvb/mantis/mantis_i2c.c
+++ /dev/null
@@ -1,266 +0,0 @@
-/*
-	Mantis PCI bridge driver
-
-	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include <asm/io.h>
-#include <linux/ioport.h>
-#include <linux/pci.h>
-#include <linux/i2c.h>
-
-#include "dmxdev.h"
-#include "dvbdev.h"
-#include "dvb_demux.h"
-#include "dvb_frontend.h"
-#include "dvb_net.h"
-
-#include "mantis_common.h"
-#include "mantis_reg.h"
-#include "mantis_i2c.h"
-
-#define TRIALS			10000
-
-static int mantis_i2c_read(struct mantis_pci *mantis, const struct i2c_msg *msg)
-{
-	u32 rxd, i, stat, trials;
-
-	dprintk(MANTIS_INFO, 0, "        %s:  Address=[0x%02x] <R>[ ",
-		__func__, msg->addr);
-
-	for (i = 0; i < msg->len; i++) {
-		rxd = (msg->addr << 25) | (1 << 24)
-					| MANTIS_I2C_RATE_3
-					| MANTIS_I2C_STOP
-					| MANTIS_I2C_PGMODE;
-
-		if (i == (msg->len - 1))
-			rxd &= ~MANTIS_I2C_STOP;
-
-		mmwrite(MANTIS_INT_I2CDONE, MANTIS_INT_STAT);
-		mmwrite(rxd, MANTIS_I2CDATA_CTL);
-
-		/* wait for xfer completion */
-		for (trials = 0; trials < TRIALS; trials++) {
-			stat = mmread(MANTIS_INT_STAT);
-			if (stat & MANTIS_INT_I2CDONE)
-				break;
-		}
-
-		dprintk(MANTIS_TMG, 0, "I2CDONE: trials=%d\n", trials);
-
-		/* wait for xfer completion */
-		for (trials = 0; trials < TRIALS; trials++) {
-			stat = mmread(MANTIS_INT_STAT);
-			if (stat & MANTIS_INT_I2CRACK)
-				break;
-		}
-
-		dprintk(MANTIS_TMG, 0, "I2CRACK: trials=%d\n", trials);
-
-		rxd = mmread(MANTIS_I2CDATA_CTL);
-		msg->buf[i] = (u8)((rxd >> 8) & 0xFF);
-		dprintk(MANTIS_INFO, 0, "%02x ", msg->buf[i]);
-	}
-	dprintk(MANTIS_INFO, 0, "]\n");
-
-	return 0;
-}
-
-static int mantis_i2c_write(struct mantis_pci *mantis, const struct i2c_msg *msg)
-{
-	int i;
-	u32 txd = 0, stat, trials;
-
-	dprintk(MANTIS_INFO, 0, "        %s: Address=[0x%02x] <W>[ ",
-		__func__, msg->addr);
-
-	for (i = 0; i < msg->len; i++) {
-		dprintk(MANTIS_INFO, 0, "%02x ", msg->buf[i]);
-		txd = (msg->addr << 25) | (msg->buf[i] << 8)
-					| MANTIS_I2C_RATE_3
-					| MANTIS_I2C_STOP
-					| MANTIS_I2C_PGMODE;
-
-		if (i == (msg->len - 1))
-			txd &= ~MANTIS_I2C_STOP;
-
-		mmwrite(MANTIS_INT_I2CDONE, MANTIS_INT_STAT);
-		mmwrite(txd, MANTIS_I2CDATA_CTL);
-
-		/* wait for xfer completion */
-		for (trials = 0; trials < TRIALS; trials++) {
-			stat = mmread(MANTIS_INT_STAT);
-			if (stat & MANTIS_INT_I2CDONE)
-				break;
-		}
-
-		dprintk(MANTIS_TMG, 0, "I2CDONE: trials=%d\n", trials);
-
-		/* wait for xfer completion */
-		for (trials = 0; trials < TRIALS; trials++) {
-			stat = mmread(MANTIS_INT_STAT);
-			if (stat & MANTIS_INT_I2CRACK)
-				break;
-		}
-
-		dprintk(MANTIS_TMG, 0, "I2CRACK: trials=%d\n", trials);
-	}
-	dprintk(MANTIS_INFO, 0, "]\n");
-
-	return 0;
-}
-
-static int mantis_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num)
-{
-	int ret = 0, i = 0, trials;
-	u32 stat, data, txd;
-	struct mantis_pci *mantis;
-	struct mantis_hwconfig *config;
-
-	mantis = i2c_get_adapdata(adapter);
-	BUG_ON(!mantis);
-	config = mantis->hwconfig;
-	BUG_ON(!config);
-
-	dprintk(MANTIS_DEBUG, 1, "Messages:%d", num);
-	mutex_lock(&mantis->i2c_lock);
-
-	while (i < num) {
-		/* Byte MODE */
-		if ((config->i2c_mode & MANTIS_BYTE_MODE) &&
-		    ((i + 1) < num)			&&
-		    (msgs[i].len < 2)			&&
-		    (msgs[i + 1].len < 2)		&&
-		    (msgs[i + 1].flags & I2C_M_RD)) {
-
-			dprintk(MANTIS_DEBUG, 0, "        Byte MODE:\n");
-
-			/* Read operation */
-			txd = msgs[i].addr << 25 | (0x1 << 24)
-						 | (msgs[i].buf[0] << 16)
-						 | MANTIS_I2C_RATE_3;
-
-			mmwrite(txd, MANTIS_I2CDATA_CTL);
-			/* wait for xfer completion */
-			for (trials = 0; trials < TRIALS; trials++) {
-				stat = mmread(MANTIS_INT_STAT);
-				if (stat & MANTIS_INT_I2CDONE)
-					break;
-			}
-
-			/* check for xfer completion */
-			if (stat & MANTIS_INT_I2CDONE) {
-				/* check xfer was acknowledged */
-				if (stat & MANTIS_INT_I2CRACK) {
-					data = mmread(MANTIS_I2CDATA_CTL);
-					msgs[i + 1].buf[0] = (data >> 8) & 0xff;
-					dprintk(MANTIS_DEBUG, 0, "        Byte <%d> RXD=0x%02x  [%02x]\n", 0x0, data, msgs[i + 1].buf[0]);
-				} else {
-					/* I/O error */
-					dprintk(MANTIS_ERROR, 1, "        I/O error, LINE:%d", __LINE__);
-					ret = -EIO;
-					break;
-				}
-			} else {
-				/* I/O error */
-				dprintk(MANTIS_ERROR, 1, "        I/O error, LINE:%d", __LINE__);
-				ret = -EIO;
-				break;
-			}
-			i += 2; /* Write/Read operation in one go */
-		}
-
-		if (i < num) {
-			if (msgs[i].flags & I2C_M_RD)
-				ret = mantis_i2c_read(mantis, &msgs[i]);
-			else
-				ret = mantis_i2c_write(mantis, &msgs[i]);
-
-			i++;
-			if (ret < 0)
-				goto bail_out;
-		}
-
-	}
-
-	mutex_unlock(&mantis->i2c_lock);
-
-	return num;
-
-bail_out:
-	mutex_unlock(&mantis->i2c_lock);
-	return ret;
-}
-
-static u32 mantis_i2c_func(struct i2c_adapter *adapter)
-{
-	return I2C_FUNC_SMBUS_EMUL;
-}
-
-static struct i2c_algorithm mantis_algo = {
-	.master_xfer		= mantis_i2c_xfer,
-	.functionality		= mantis_i2c_func,
-};
-
-int __devinit mantis_i2c_init(struct mantis_pci *mantis)
-{
-	u32 intstat, intmask;
-	struct i2c_adapter *i2c_adapter = &mantis->adapter;
-	struct pci_dev *pdev		= mantis->pdev;
-
-	init_waitqueue_head(&mantis->i2c_wq);
-	mutex_init(&mantis->i2c_lock);
-	strncpy(i2c_adapter->name, "Mantis I2C", sizeof(i2c_adapter->name));
-	i2c_set_adapdata(i2c_adapter, mantis);
-
-	i2c_adapter->owner	= THIS_MODULE;
-	i2c_adapter->algo	= &mantis_algo;
-	i2c_adapter->algo_data	= NULL;
-	i2c_adapter->timeout	= 500;
-	i2c_adapter->retries	= 3;
-	i2c_adapter->dev.parent	= &pdev->dev;
-
-	mantis->i2c_rc		= i2c_add_adapter(i2c_adapter);
-	if (mantis->i2c_rc < 0)
-		return mantis->i2c_rc;
-
-	dprintk(MANTIS_DEBUG, 1, "Initializing I2C ..");
-
-	intstat = mmread(MANTIS_INT_STAT);
-	intmask = mmread(MANTIS_INT_MASK);
-	mmwrite(intstat, MANTIS_INT_STAT);
-	dprintk(MANTIS_DEBUG, 1, "Disabling I2C interrupt");
-	intmask = mmread(MANTIS_INT_MASK);
-	mmwrite((intmask & ~MANTIS_INT_I2CDONE), MANTIS_INT_MASK);
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(mantis_i2c_init);
-
-int mantis_i2c_exit(struct mantis_pci *mantis)
-{
-	u32 intmask;
-
-	dprintk(MANTIS_DEBUG, 1, "Disabling I2C interrupt");
-	intmask = mmread(MANTIS_INT_MASK);
-	mmwrite((intmask & ~MANTIS_INT_I2CDONE), MANTIS_INT_MASK);
-
-	dprintk(MANTIS_DEBUG, 1, "Removing I2C adapter");
-	return i2c_del_adapter(&mantis->adapter);
-}
-EXPORT_SYMBOL_GPL(mantis_i2c_exit);
diff --git a/drivers/media/dvb/mantis/mantis_i2c.h b/drivers/media/dvb/mantis/mantis_i2c.h
deleted file mode 100644
index 1342df2..0000000
--- a/drivers/media/dvb/mantis/mantis_i2c.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
-	Mantis PCI bridge driver
-
-	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#ifndef __MANTIS_I2C_H
-#define __MANTIS_I2C_H
-
-#define I2C_STOP		(1 <<  0)
-#define I2C_READ		(1 <<  1)
-
-extern int mantis_i2c_init(struct mantis_pci *mantis);
-extern int mantis_i2c_exit(struct mantis_pci *mantis);
-
-#endif /* __MANTIS_I2C_H */
diff --git a/drivers/media/dvb/mantis/mantis_input.c b/drivers/media/dvb/mantis/mantis_input.c
deleted file mode 100644
index db6d54d..0000000
--- a/drivers/media/dvb/mantis/mantis_input.c
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
-	Mantis PCI bridge driver
-
-	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include <media/rc-core.h>
-#include <linux/pci.h>
-
-#include "dmxdev.h"
-#include "dvbdev.h"
-#include "dvb_demux.h"
-#include "dvb_frontend.h"
-#include "dvb_net.h"
-
-#include "mantis_common.h"
-#include "mantis_reg.h"
-#include "mantis_uart.h"
-
-#define MODULE_NAME "mantis_core"
-#define RC_MAP_MANTIS "rc-mantis"
-
-static struct rc_map_table mantis_ir_table[] = {
-	{ 0x29, KEY_POWER	},
-	{ 0x28, KEY_FAVORITES	},
-	{ 0x30, KEY_TEXT	},
-	{ 0x17, KEY_INFO	}, /* Preview */
-	{ 0x23, KEY_EPG		},
-	{ 0x3b, KEY_F22		}, /* Record List */
-	{ 0x3c, KEY_1		},
-	{ 0x3e, KEY_2		},
-	{ 0x39, KEY_3		},
-	{ 0x36, KEY_4		},
-	{ 0x22, KEY_5		},
-	{ 0x20, KEY_6		},
-	{ 0x32, KEY_7		},
-	{ 0x26, KEY_8		},
-	{ 0x24, KEY_9		},
-	{ 0x2a, KEY_0		},
-
-	{ 0x33, KEY_CANCEL	},
-	{ 0x2c, KEY_BACK	},
-	{ 0x15, KEY_CLEAR	},
-	{ 0x3f, KEY_TAB		},
-	{ 0x10, KEY_ENTER	},
-	{ 0x14, KEY_UP		},
-	{ 0x0d, KEY_RIGHT	},
-	{ 0x0e, KEY_DOWN	},
-	{ 0x11, KEY_LEFT	},
-
-	{ 0x21, KEY_VOLUMEUP	},
-	{ 0x35, KEY_VOLUMEDOWN	},
-	{ 0x3d, KEY_CHANNELDOWN	},
-	{ 0x3a, KEY_CHANNELUP	},
-	{ 0x2e, KEY_RECORD	},
-	{ 0x2b, KEY_PLAY	},
-	{ 0x13, KEY_PAUSE	},
-	{ 0x25, KEY_STOP	},
-
-	{ 0x1f, KEY_REWIND	},
-	{ 0x2d, KEY_FASTFORWARD	},
-	{ 0x1e, KEY_PREVIOUS	}, /* Replay |< */
-	{ 0x1d, KEY_NEXT	}, /* Skip   >| */
-
-	{ 0x0b, KEY_CAMERA	}, /* Capture */
-	{ 0x0f, KEY_LANGUAGE	}, /* SAP */
-	{ 0x18, KEY_MODE	}, /* PIP */
-	{ 0x12, KEY_ZOOM	}, /* Full screen */
-	{ 0x1c, KEY_SUBTITLE	},
-	{ 0x2f, KEY_MUTE	},
-	{ 0x16, KEY_F20		}, /* L/R */
-	{ 0x38, KEY_F21		}, /* Hibernate */
-
-	{ 0x37, KEY_SWITCHVIDEOMODE }, /* A/V */
-	{ 0x31, KEY_AGAIN	}, /* Recall */
-	{ 0x1a, KEY_KPPLUS	}, /* Zoom+ */
-	{ 0x19, KEY_KPMINUS	}, /* Zoom- */
-	{ 0x27, KEY_RED		},
-	{ 0x0C, KEY_GREEN	},
-	{ 0x01, KEY_YELLOW	},
-	{ 0x00, KEY_BLUE	},
-};
-
-static struct rc_map_list ir_mantis_map = {
-	.map = {
-		.scan = mantis_ir_table,
-		.size = ARRAY_SIZE(mantis_ir_table),
-		.rc_type = RC_TYPE_UNKNOWN,
-		.name = RC_MAP_MANTIS,
-	}
-};
-
-int mantis_input_init(struct mantis_pci *mantis)
-{
-	struct rc_dev *dev;
-	int err;
-
-	err = rc_map_register(&ir_mantis_map);
-	if (err)
-		goto out;
-
-	dev = rc_allocate_device();
-	if (!dev) {
-		dprintk(MANTIS_ERROR, 1, "Remote device allocation failed");
-		err = -ENOMEM;
-		goto out_map;
-	}
-
-	sprintf(mantis->input_name, "Mantis %s IR receiver", mantis->hwconfig->model_name);
-	sprintf(mantis->input_phys, "pci-%s/ir0", pci_name(mantis->pdev));
-
-	dev->input_name         = mantis->input_name;
-	dev->input_phys         = mantis->input_phys;
-	dev->input_id.bustype   = BUS_PCI;
-	dev->input_id.vendor    = mantis->vendor_id;
-	dev->input_id.product   = mantis->device_id;
-	dev->input_id.version   = 1;
-	dev->driver_name        = MODULE_NAME;
-	dev->map_name           = RC_MAP_MANTIS;
-	dev->dev.parent         = &mantis->pdev->dev;
-
-	err = rc_register_device(dev);
-	if (err) {
-		dprintk(MANTIS_ERROR, 1, "IR device registration failed, ret = %d", err);
-		goto out_dev;
-	}
-
-	mantis->rc = dev;
-	return 0;
-
-out_dev:
-	rc_free_device(dev);
-out_map:
-	rc_map_unregister(&ir_mantis_map);
-out:
-	return err;
-}
-
-int mantis_exit(struct mantis_pci *mantis)
-{
-	rc_unregister_device(mantis->rc);
-	rc_map_unregister(&ir_mantis_map);
-	return 0;
-}
-
diff --git a/drivers/media/dvb/mantis/mantis_ioc.c b/drivers/media/dvb/mantis/mantis_ioc.c
deleted file mode 100644
index 24fcdc6..0000000
--- a/drivers/media/dvb/mantis/mantis_ioc.c
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
-	Mantis PCI bridge driver
-
-	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include <linux/kernel.h>
-#include <linux/i2c.h>
-
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <asm/io.h>
-
-#include "dmxdev.h"
-#include "dvbdev.h"
-#include "dvb_demux.h"
-#include "dvb_frontend.h"
-#include "dvb_net.h"
-
-#include "mantis_common.h"
-#include "mantis_reg.h"
-#include "mantis_ioc.h"
-
-static int read_eeprom_bytes(struct mantis_pci *mantis, u8 reg, u8 *data, u8 length)
-{
-	struct i2c_adapter *adapter = &mantis->adapter;
-	int err;
-	u8 buf = reg;
-
-	struct i2c_msg msg[] = {
-		{ .addr = 0x50, .flags = 0, .buf = &buf, .len = 1 },
-		{ .addr = 0x50, .flags = I2C_M_RD, .buf = data, .len = length },
-	};
-
-	err = i2c_transfer(adapter, msg, 2);
-	if (err < 0) {
-		dprintk(MANTIS_ERROR, 1, "ERROR: i2c read: < err=%i d0=0x%02x d1=0x%02x >",
-			err, data[0], data[1]);
-
-		return err;
-	}
-
-	return 0;
-}
-int mantis_get_mac(struct mantis_pci *mantis)
-{
-	int err;
-	u8 mac_addr[6] = {0};
-
-	err = read_eeprom_bytes(mantis, 0x08, mac_addr, 6);
-	if (err < 0) {
-		dprintk(MANTIS_ERROR, 1, "ERROR: Mantis EEPROM read error <%d>", err);
-
-		return err;
-	}
-
-	dprintk(MANTIS_ERROR, 0, "    MAC Address=[%pM]\n", mac_addr);
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(mantis_get_mac);
-
-/* Turn the given bit on or off. */
-void mantis_gpio_set_bits(struct mantis_pci *mantis, u32 bitpos, u8 value)
-{
-	u32 cur;
-
-	dprintk(MANTIS_DEBUG, 1, "Set Bit <%d> to <%d>", bitpos, value);
-	cur = mmread(MANTIS_GPIF_ADDR);
-	if (value)
-		mantis->gpio_status = cur | (1 << bitpos);
-	else
-		mantis->gpio_status = cur & (~(1 << bitpos));
-
-	dprintk(MANTIS_DEBUG, 1, "GPIO Value <%02x>", mantis->gpio_status);
-	mmwrite(mantis->gpio_status, MANTIS_GPIF_ADDR);
-	mmwrite(0x00, MANTIS_GPIF_DOUT);
-}
-EXPORT_SYMBOL_GPL(mantis_gpio_set_bits);
-
-int mantis_stream_control(struct mantis_pci *mantis, enum mantis_stream_control stream_ctl)
-{
-	u32 reg;
-
-	reg = mmread(MANTIS_CONTROL);
-	switch (stream_ctl) {
-	case STREAM_TO_HIF:
-		dprintk(MANTIS_DEBUG, 1, "Set stream to HIF");
-		reg &= 0xff - MANTIS_BYPASS;
-		mmwrite(reg, MANTIS_CONTROL);
-		reg |= MANTIS_BYPASS;
-		mmwrite(reg, MANTIS_CONTROL);
-		break;
-
-	case STREAM_TO_CAM:
-		dprintk(MANTIS_DEBUG, 1, "Set stream to CAM");
-		reg |= MANTIS_BYPASS;
-		mmwrite(reg, MANTIS_CONTROL);
-		reg &= 0xff - MANTIS_BYPASS;
-		mmwrite(reg, MANTIS_CONTROL);
-		break;
-	default:
-		dprintk(MANTIS_ERROR, 1, "Unknown MODE <%02x>", stream_ctl);
-		return -1;
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(mantis_stream_control);
diff --git a/drivers/media/dvb/mantis/mantis_ioc.h b/drivers/media/dvb/mantis/mantis_ioc.h
deleted file mode 100644
index d56e002..0000000
--- a/drivers/media/dvb/mantis/mantis_ioc.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
-	Mantis PCI bridge driver
-
-	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#ifndef __MANTIS_IOC_H
-#define __MANTIS_IOC_H
-
-#define GPIF_A00		0x00
-#define GPIF_A01		0x01
-#define GPIF_A02		0x02
-#define GPIF_A03		0x03
-#define GPIF_A04		0x04
-#define GPIF_A05		0x05
-#define GPIF_A06		0x06
-#define GPIF_A07		0x07
-#define GPIF_A08		0x08
-#define GPIF_A09		0x09
-#define GPIF_A10		0x0a
-#define GPIF_A11		0x0b
-
-#define GPIF_A12		0x0c
-#define GPIF_A13		0x0d
-#define GPIF_A14		0x0e
-
-enum mantis_stream_control {
-	STREAM_TO_HIF = 0,
-	STREAM_TO_CAM
-};
-
-extern int mantis_get_mac(struct mantis_pci *mantis);
-extern void mantis_gpio_set_bits(struct mantis_pci *mantis, u32 bitpos, u8 value);
-
-extern int mantis_stream_control(struct mantis_pci *mantis, enum mantis_stream_control stream_ctl);
-
-#endif /* __MANTIS_IOC_H */
diff --git a/drivers/media/dvb/mantis/mantis_link.h b/drivers/media/dvb/mantis/mantis_link.h
deleted file mode 100644
index 2a81477..0000000
--- a/drivers/media/dvb/mantis/mantis_link.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
-	Mantis PCI bridge driver
-
-	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#ifndef __MANTIS_LINK_H
-#define __MANTIS_LINK_H
-
-#include <linux/mutex.h>
-#include <linux/workqueue.h>
-#include "dvb_ca_en50221.h"
-
-enum mantis_sbuf_status {
-	MANTIS_SBUF_DATA_AVAIL		= 1,
-	MANTIS_SBUF_DATA_EMPTY		= 2,
-	MANTIS_SBUF_DATA_OVFLW		= 3
-};
-
-struct mantis_slot {
-	u32				timeout;
-	u32				slave_cfg;
-	u32				bar;
-};
-
-/* Physical layer */
-enum mantis_slot_state {
-	MODULE_INSERTED			= 3,
-	MODULE_XTRACTED			= 4
-};
-
-struct mantis_ca {
-	struct mantis_slot		slot[4];
-
-	struct work_struct		hif_evm_work;
-
-	u32				hif_event;
-	wait_queue_head_t		hif_opdone_wq;
-	wait_queue_head_t		hif_brrdyw_wq;
-	wait_queue_head_t		hif_data_wq;
-	wait_queue_head_t		hif_write_wq; /* HIF Write op */
-
-	enum mantis_sbuf_status		sbuf_status;
-
-	enum mantis_slot_state		slot_state;
-
-	void				*ca_priv;
-
-	struct dvb_ca_en50221		en50221;
-	struct mutex			ca_lock;
-};
-
-/* CA */
-extern void mantis_event_cam_plugin(struct mantis_ca *ca);
-extern void mantis_event_cam_unplug(struct mantis_ca *ca);
-extern int mantis_pcmcia_init(struct mantis_ca *ca);
-extern void mantis_pcmcia_exit(struct mantis_ca *ca);
-extern int mantis_evmgr_init(struct mantis_ca *ca);
-extern void mantis_evmgr_exit(struct mantis_ca *ca);
-
-/* HIF */
-extern int mantis_hif_init(struct mantis_ca *ca);
-extern void mantis_hif_exit(struct mantis_ca *ca);
-extern int mantis_hif_read_mem(struct mantis_ca *ca, u32 addr);
-extern int mantis_hif_write_mem(struct mantis_ca *ca, u32 addr, u8 data);
-extern int mantis_hif_read_iom(struct mantis_ca *ca, u32 addr);
-extern int mantis_hif_write_iom(struct mantis_ca *ca, u32 addr, u8 data);
-
-#endif /* __MANTIS_LINK_H */
diff --git a/drivers/media/dvb/mantis/mantis_pci.c b/drivers/media/dvb/mantis/mantis_pci.c
deleted file mode 100644
index 371558a..0000000
--- a/drivers/media/dvb/mantis/mantis_pci.c
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
-	Mantis PCI bridge driver
-
-	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/kernel.h>
-#include <asm/io.h>
-#include <asm/page.h>
-#include <linux/kmod.h>
-#include <linux/vmalloc.h>
-#include <linux/init.h>
-#include <linux/device.h>
-#include <linux/pci.h>
-
-#include <asm/irq.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-
-#include "dmxdev.h"
-#include "dvbdev.h"
-#include "dvb_demux.h"
-#include "dvb_frontend.h"
-#include "dvb_net.h"
-
-#include "mantis_common.h"
-#include "mantis_reg.h"
-#include "mantis_pci.h"
-
-#define DRIVER_NAME		"Mantis Core"
-
-int __devinit mantis_pci_init(struct mantis_pci *mantis)
-{
-	u8 latency;
-	struct mantis_hwconfig *config	= mantis->hwconfig;
-	struct pci_dev *pdev		= mantis->pdev;
-	int err, ret = 0;
-
-	dprintk(MANTIS_ERROR, 0, "found a %s PCI %s device on (%02x:%02x.%x),\n",
-		config->model_name,
-		config->dev_type,
-		mantis->pdev->bus->number,
-		PCI_SLOT(mantis->pdev->devfn),
-		PCI_FUNC(mantis->pdev->devfn));
-
-	err = pci_enable_device(pdev);
-	if (err != 0) {
-		ret = -ENODEV;
-		dprintk(MANTIS_ERROR, 1, "ERROR: PCI enable failed <%i>", err);
-		goto fail0;
-	}
-
-	err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
-	if (err != 0) {
-		dprintk(MANTIS_ERROR, 1, "ERROR: Unable to obtain 32 bit DMA <%i>", err);
-		ret = -ENOMEM;
-		goto fail1;
-	}
-
-	pci_set_master(pdev);
-
-	if (!request_mem_region(pci_resource_start(pdev, 0),
-				pci_resource_len(pdev, 0),
-				DRIVER_NAME)) {
-
-		dprintk(MANTIS_ERROR, 1, "ERROR: BAR0 Request failed !");
-		ret = -ENODEV;
-		goto fail1;
-	}
-
-	mantis->mmio = ioremap(pci_resource_start(pdev, 0),
-			       pci_resource_len(pdev, 0));
-
-	if (!mantis->mmio) {
-		dprintk(MANTIS_ERROR, 1, "ERROR: BAR0 remap failed !");
-		ret = -ENODEV;
-		goto fail2;
-	}
-
-	pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &latency);
-	mantis->latency = latency;
-	mantis->revision = pdev->revision;
-
-	dprintk(MANTIS_ERROR, 0, "    Mantis Rev %d [%04x:%04x], ",
-		mantis->revision,
-		mantis->pdev->subsystem_vendor,
-		mantis->pdev->subsystem_device);
-
-	dprintk(MANTIS_ERROR, 0,
-		"irq: %d, latency: %d\n    memory: 0x%lx, mmio: 0x%p\n",
-		mantis->pdev->irq,
-		mantis->latency,
-		mantis->mantis_addr,
-		mantis->mmio);
-
-	err = request_irq(pdev->irq,
-			  config->irq_handler,
-			  IRQF_SHARED,
-			  DRIVER_NAME,
-			  mantis);
-
-	if (err != 0) {
-
-		dprintk(MANTIS_ERROR, 1, "ERROR: IRQ registration failed ! <%d>", err);
-		ret = -ENODEV;
-		goto fail3;
-	}
-
-	pci_set_drvdata(pdev, mantis);
-	return ret;
-
-	/* Error conditions */
-fail3:
-	dprintk(MANTIS_ERROR, 1, "ERROR: <%d> I/O unmap", ret);
-	if (mantis->mmio)
-		iounmap(mantis->mmio);
-
-fail2:
-	dprintk(MANTIS_ERROR, 1, "ERROR: <%d> releasing regions", ret);
-	release_mem_region(pci_resource_start(pdev, 0),
-			   pci_resource_len(pdev, 0));
-
-fail1:
-	dprintk(MANTIS_ERROR, 1, "ERROR: <%d> disabling device", ret);
-	pci_disable_device(pdev);
-
-fail0:
-	dprintk(MANTIS_ERROR, 1, "ERROR: <%d> exiting", ret);
-	pci_set_drvdata(pdev, NULL);
-	return ret;
-}
-EXPORT_SYMBOL_GPL(mantis_pci_init);
-
-void mantis_pci_exit(struct mantis_pci *mantis)
-{
-	struct pci_dev *pdev = mantis->pdev;
-
-	dprintk(MANTIS_NOTICE, 1, " mem: 0x%p", mantis->mmio);
-	free_irq(pdev->irq, mantis);
-	if (mantis->mmio) {
-		iounmap(mantis->mmio);
-		release_mem_region(pci_resource_start(pdev, 0),
-				   pci_resource_len(pdev, 0));
-	}
-
-	pci_disable_device(pdev);
-	pci_set_drvdata(pdev, NULL);
-}
-EXPORT_SYMBOL_GPL(mantis_pci_exit);
-
-MODULE_DESCRIPTION("Mantis PCI DTV bridge driver");
-MODULE_AUTHOR("Manu Abraham");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/mantis/mantis_pci.h b/drivers/media/dvb/mantis/mantis_pci.h
deleted file mode 100644
index 65f0045..0000000
--- a/drivers/media/dvb/mantis/mantis_pci.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
-	Mantis PCI bridge driver
-
-	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#ifndef __MANTIS_PCI_H
-#define __MANTIS_PCI_H
-
-extern int mantis_pci_init(struct mantis_pci *mantis);
-extern void mantis_pci_exit(struct mantis_pci *mantis);
-
-#endif /* __MANTIS_PCI_H */
diff --git a/drivers/media/dvb/mantis/mantis_pcmcia.c b/drivers/media/dvb/mantis/mantis_pcmcia.c
deleted file mode 100644
index 2f188c0..0000000
--- a/drivers/media/dvb/mantis/mantis_pcmcia.c
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
-	Mantis PCI bridge driver
-
-	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include <linux/kernel.h>
-
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <asm/io.h>
-
-#include "dmxdev.h"
-#include "dvbdev.h"
-#include "dvb_demux.h"
-#include "dvb_frontend.h"
-#include "dvb_net.h"
-
-#include "mantis_common.h"
-#include "mantis_link.h" /* temporary due to physical layer stuff */
-#include "mantis_reg.h"
-
-/*
- * If Slot state is already PLUG_IN event and we are called
- * again, definitely it is jitter alone
- */
-void mantis_event_cam_plugin(struct mantis_ca *ca)
-{
-	struct mantis_pci *mantis = ca->ca_priv;
-
-	u32 gpif_irqcfg;
-
-	if (ca->slot_state == MODULE_XTRACTED) {
-		dprintk(MANTIS_DEBUG, 1, "Event: CAM Plugged IN: Adapter(%d) Slot(0)", mantis->num);
-		udelay(50);
-		mmwrite(0xda000000, MANTIS_CARD_RESET);
-		gpif_irqcfg  = mmread(MANTIS_GPIF_IRQCFG);
-		gpif_irqcfg |= MANTIS_MASK_PLUGOUT;
-		gpif_irqcfg &= ~MANTIS_MASK_PLUGIN;
-		mmwrite(gpif_irqcfg, MANTIS_GPIF_IRQCFG);
-		udelay(500);
-		ca->slot_state = MODULE_INSERTED;
-	}
-	udelay(100);
-}
-
-/*
- * If Slot state is already UN_PLUG event and we are called
- * again, definitely it is jitter alone
- */
-void mantis_event_cam_unplug(struct mantis_ca *ca)
-{
-	struct mantis_pci *mantis = ca->ca_priv;
-
-	u32 gpif_irqcfg;
-
-	if (ca->slot_state == MODULE_INSERTED) {
-		dprintk(MANTIS_DEBUG, 1, "Event: CAM Unplugged: Adapter(%d) Slot(0)", mantis->num);
-		udelay(50);
-		mmwrite(0x00da0000, MANTIS_CARD_RESET);
-		gpif_irqcfg  = mmread(MANTIS_GPIF_IRQCFG);
-		gpif_irqcfg |= MANTIS_MASK_PLUGIN;
-		gpif_irqcfg &= ~MANTIS_MASK_PLUGOUT;
-		mmwrite(gpif_irqcfg, MANTIS_GPIF_IRQCFG);
-		udelay(500);
-		ca->slot_state = MODULE_XTRACTED;
-	}
-	udelay(100);
-}
-
-int mantis_pcmcia_init(struct mantis_ca *ca)
-{
-	struct mantis_pci *mantis = ca->ca_priv;
-
-	u32 gpif_stat, card_stat;
-
-	mmwrite(mmread(MANTIS_INT_MASK) | MANTIS_INT_IRQ0, MANTIS_INT_MASK);
-	gpif_stat = mmread(MANTIS_GPIF_STATUS);
-	card_stat = mmread(MANTIS_GPIF_IRQCFG);
-
-	if (gpif_stat & MANTIS_GPIF_DETSTAT) {
-		dprintk(MANTIS_DEBUG, 1, "CAM found on Adapter(%d) Slot(0)", mantis->num);
-		mmwrite(card_stat | MANTIS_MASK_PLUGOUT, MANTIS_GPIF_IRQCFG);
-		ca->slot_state = MODULE_INSERTED;
-		dvb_ca_en50221_camchange_irq(&ca->en50221,
-					     0,
-					     DVB_CA_EN50221_CAMCHANGE_INSERTED);
-	} else {
-		dprintk(MANTIS_DEBUG, 1, "Empty Slot on Adapter(%d) Slot(0)", mantis->num);
-		mmwrite(card_stat | MANTIS_MASK_PLUGIN, MANTIS_GPIF_IRQCFG);
-		ca->slot_state = MODULE_XTRACTED;
-		dvb_ca_en50221_camchange_irq(&ca->en50221,
-					     0,
-					     DVB_CA_EN50221_CAMCHANGE_REMOVED);
-	}
-
-	return 0;
-}
-
-void mantis_pcmcia_exit(struct mantis_ca *ca)
-{
-	struct mantis_pci *mantis = ca->ca_priv;
-
-	mmwrite(mmread(MANTIS_GPIF_STATUS) & (~MANTIS_CARD_PLUGOUT | ~MANTIS_CARD_PLUGIN), MANTIS_GPIF_STATUS);
-	mmwrite(mmread(MANTIS_INT_MASK) & ~MANTIS_INT_IRQ0, MANTIS_INT_MASK);
-}
diff --git a/drivers/media/dvb/mantis/mantis_reg.h b/drivers/media/dvb/mantis/mantis_reg.h
deleted file mode 100644
index 7761f9d..0000000
--- a/drivers/media/dvb/mantis/mantis_reg.h
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
-	Mantis PCI bridge driver
-
-	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#ifndef __MANTIS_REG_H
-#define __MANTIS_REG_H
-
-/* Interrupts */
-#define MANTIS_INT_STAT			0x00
-#define MANTIS_INT_MASK			0x04
-
-#define MANTIS_INT_RISCSTAT		(0x0f << 28)
-#define MANTIS_INT_RISCEN		(0x01 << 27)
-#define MANTIS_INT_I2CRACK		(0x01 << 26)
-
-/* #define MANTIS_INT_GPIF			(0xff << 12) */
-
-#define MANTIS_INT_PCMCIA7		(0x01 << 19)
-#define MANTIS_INT_PCMCIA6		(0x01 << 18)
-#define MANTIS_INT_PCMCIA5		(0x01 << 17)
-#define MANTIS_INT_PCMCIA4		(0x01 << 16)
-#define MANTIS_INT_PCMCIA3		(0x01 << 15)
-#define MANTIS_INT_PCMCIA2		(0x01 << 14)
-#define MANTIS_INT_PCMCIA1		(0x01 << 13)
-#define MANTIS_INT_PCMCIA0		(0x01 << 12)
-#define MANTIS_INT_IRQ1			(0x01 << 11)
-#define MANTIS_INT_IRQ0			(0x01 << 10)
-#define MANTIS_INT_OCERR		(0x01 <<  8)
-#define MANTIS_INT_PABORT		(0x01 <<  7)
-#define MANTIS_INT_RIPERR		(0x01 <<  6)
-#define MANTIS_INT_PPERR		(0x01 <<  5)
-#define MANTIS_INT_FTRGT		(0x01 <<  3)
-#define MANTIS_INT_RISCI		(0x01 <<  1)
-#define MANTIS_INT_I2CDONE		(0x01 <<  0)
-
-/* DMA */
-#define MANTIS_DMA_CTL			0x08
-#define MANTIS_GPIF_RD			(0xff << 24)
-#define MANTIS_GPIF_WR			(0xff << 16)
-#define MANTIS_CPU_DO			(0x01 << 10)
-#define MANTIS_DRV_DO			(0x01 <<  9)
-#define	MANTIS_I2C_RD			(0x01 <<  7)
-#define MANTIS_I2C_WR			(0x01 <<  6)
-#define MANTIS_DCAP_MODE		(0x01 <<  5)
-#define MANTIS_FIFO_TP_4		(0x00 <<  3)
-#define MANTIS_FIFO_TP_8		(0x01 <<  3)
-#define MANTIS_FIFO_TP_16		(0x02 <<  3)
-#define MANTIS_FIFO_EN			(0x01 <<  2)
-#define MANTIS_DCAP_EN			(0x01 <<  1)
-#define MANTIS_RISC_EN			(0x01 <<  0)
-
-/* DEBUG */
-#define MANTIS_DEBUGREG			0x0c
-#define MANTIS_DATINV			(0x0e <<  7)
-#define MANTIS_TOP_DEBUGSEL		(0x07 <<  4)
-#define MANTIS_PCMCIA_DEBUGSEL		(0x0f <<  0)
-
-#define MANTIS_RISC_START		0x10
-#define MANTIS_RISC_PC			0x14
-
-/* I2C */
-#define MANTIS_I2CDATA_CTL		0x18
-#define MANTIS_I2C_RATE_1		(0x00 <<  6)
-#define MANTIS_I2C_RATE_2		(0x01 <<  6)
-#define MANTIS_I2C_RATE_3		(0x02 <<  6)
-#define MANTIS_I2C_RATE_4		(0x03 <<  6)
-#define MANTIS_I2C_STOP			(0x01 <<  5)
-#define MANTIS_I2C_PGMODE		(0x01 <<  3)
-
-/* DATA */
-#define MANTIS_CMD_DATA_R1		0x20
-#define MANTIS_CMD_DATA_3		(0xff << 24)
-#define MANTIS_CMD_DATA_2		(0xff << 16)
-#define MANTIS_CMD_DATA_1		(0xff <<  8)
-#define MANTIS_CMD_DATA_0		(0xff <<  0)
-
-#define MANTIS_CMD_DATA_R2		0x24
-#define MANTIS_CMD_DATA_7		(0xff << 24)
-#define MANTIS_CMD_DATA_6		(0xff << 16)
-#define MANTIS_CMD_DATA_5		(0xff <<  8)
-#define MANTIS_CMD_DATA_4		(0xff <<  0)
-
-#define MANTIS_CONTROL			0x28
-#define MANTIS_DET			(0x01 <<  7)
-#define MANTIS_DAT_CF_EN		(0x01 <<  6)
-#define MANTIS_ACS			(0x03 <<  4)
-#define MANTIS_VCCEN			(0x01 <<  3)
-#define MANTIS_BYPASS			(0x01 <<  2)
-#define MANTIS_MRST			(0x01 <<  1)
-#define MANTIS_CRST_INT			(0x01 <<  0)
-
-#define MANTIS_GPIF_CFGSLA		0x84
-#define MANTIS_GPIF_WAITSMPL		(0x07 << 28)
-#define MANTIS_GPIF_BYTEADDRSUB		(0x01 << 25)
-#define MANTIS_GPIF_WAITPOL		(0x01 << 24)
-#define MANTIS_GPIF_NCDELAY		(0x07 << 20)
-#define MANTIS_GPIF_RW2CSDELAY		(0x07 << 16)
-#define MANTIS_GPIF_SLFTIMEDMODE	(0x01 << 15)
-#define MANTIS_GPIF_SLFTIMEDDELY	(0x7f <<  8)
-#define MANTIS_GPIF_DEVTYPE		(0x07 <<  4)
-#define MANTIS_GPIF_BIGENDIAN		(0x01 <<  3)
-#define MANTIS_GPIF_FETCHCMD		(0x03 <<  1)
-#define MANTIS_GPIF_HWORDDEV		(0x01 <<  0)
-
-#define MANTIS_GPIF_WSTOPER		0x90
-#define MANTIS_GPIF_WSTOPERWREN3	(0x01 << 31)
-#define MANTIS_GPIF_PARBOOTN		(0x01 << 29)
-#define MANTIS_GPIF_WSTOPERSLID3	(0x1f << 24)
-#define MANTIS_GPIF_WSTOPERWREN2	(0x01 << 23)
-#define MANTIS_GPIF_WSTOPERSLID2	(0x1f << 16)
-#define MANTIS_GPIF_WSTOPERWREN1	(0x01 << 15)
-#define MANTIS_GPIF_WSTOPERSLID1	(0x1f <<  8)
-#define MANTIS_GPIF_WSTOPERWREN0	(0x01 <<  7)
-#define MANTIS_GPIF_WSTOPERSLID0	(0x1f <<  0)
-
-#define MANTIS_GPIF_CS2RW		0x94
-#define MANTIS_GPIF_CS2RWWREN3		(0x01 << 31)
-#define MANTIS_GPIF_CS2RWDELY3		(0x3f << 24)
-#define MANTIS_GPIF_CS2RWWREN2		(0x01 << 23)
-#define MANTIS_GPIF_CS2RWDELY2		(0x3f << 16)
-#define MANTIS_GPIF_CS2RWWREN1		(0x01 << 15)
-#define MANTIS_GPIF_CS2RWDELY1		(0x3f <<  8)
-#define MANTIS_GPIF_CS2RWWREN0		(0x01 <<  7)
-#define MANTIS_GPIF_CS2RWDELY0		(0x3f <<  0)
-
-#define MANTIS_GPIF_IRQCFG		0x98
-#define MANTIS_GPIF_IRQPOL		(0x01 <<  8)
-#define MANTIS_MASK_WRACK		(0x01 <<  7)
-#define MANTIS_MASK_BRRDY		(0x01 <<  6)
-#define MANTIS_MASK_OVFLW		(0x01 <<  5)
-#define MANTIS_MASK_OTHERR		(0x01 <<  4)
-#define MANTIS_MASK_WSTO		(0x01 <<  3)
-#define MANTIS_MASK_EXTIRQ		(0x01 <<  2)
-#define MANTIS_MASK_PLUGIN		(0x01 <<  1)
-#define MANTIS_MASK_PLUGOUT		(0x01 <<  0)
-
-#define MANTIS_GPIF_STATUS		0x9c
-#define MANTIS_SBUF_KILLOP		(0x01 << 15)
-#define MANTIS_SBUF_OPDONE		(0x01 << 14)
-#define MANTIS_SBUF_EMPTY		(0x01 << 13)
-#define MANTIS_GPIF_DETSTAT		(0x01 <<  9)
-#define MANTIS_GPIF_INTSTAT		(0x01 <<  8)
-#define MANTIS_GPIF_WRACK		(0x01 <<  7)
-#define MANTIS_GPIF_BRRDY		(0x01 <<  6)
-#define MANTIS_SBUF_OVFLW		(0x01 <<  5)
-#define MANTIS_GPIF_OTHERR		(0x01 <<  4)
-#define MANTIS_SBUF_WSTO		(0x01 <<  3)
-#define MANTIS_GPIF_EXTIRQ		(0x01 <<  2)
-#define MANTIS_CARD_PLUGIN		(0x01 <<  1)
-#define MANTIS_CARD_PLUGOUT		(0x01 <<  0)
-
-#define MANTIS_GPIF_BRADDR		0xa0
-#define MANTIS_GPIF_PCMCIAREG		(0x01 		<< 27)
-#define MANTIS_GPIF_PCMCIAIOM		(0x01 		<< 26)
-#define MANTIS_GPIF_BR_ADDR		(0xfffffff	<<  0)
-
-#define MANTIS_GPIF_BRBYTES		0xa4
-#define MANTIS_GPIF_BRCNT		(0xfff 		<<  0)
-
-#define MANTIS_PCMCIA_RESET		0xa8
-#define MANTIS_PCMCIA_RSTVAL		(0xff << 0)
-
-#define MANTIS_CARD_RESET		0xac
-
-#define MANTIS_GPIF_ADDR		0xb0
-#define MANTIS_GPIF_HIFRDWRN		(0x01		<< 31)
-#define MANTIS_GPIF_PCMCIAREG		(0x01		<< 27)
-#define MANTIS_GPIF_PCMCIAIOM		(0x01		<< 26)
-#define MANTIS_GPIF_HIFADDR		(0xfffffff	<<  0)
-
-#define MANTIS_GPIF_DOUT		0xb4
-#define MANTIS_GPIF_HIFDOUT		(0xfffffff	<<  0)
-
-#define MANTIS_GPIF_DIN			0xb8
-#define MANTIS_GPIF_HIFDIN		(0xfffffff	<<  0)
-
-#define MANTIS_GPIF_SPARE		0xbc
-#define MANTIS_GPIF_LOGICRD		(0xffff		<< 16)
-#define MANTIS_GPIF_LOGICRW		(0xffff		<<  0)
-
-#endif /* __MANTIS_REG_H */
diff --git a/drivers/media/dvb/mantis/mantis_uart.c b/drivers/media/dvb/mantis/mantis_uart.c
deleted file mode 100644
index 18340da..0000000
--- a/drivers/media/dvb/mantis/mantis_uart.c
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
-	Mantis PCI bridge driver
-
-	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include <linux/kernel.h>
-#include <linux/spinlock.h>
-#include <asm/io.h>
-
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-
-#include "dmxdev.h"
-#include "dvbdev.h"
-#include "dvb_demux.h"
-#include "dvb_frontend.h"
-#include "dvb_net.h"
-
-#include "mantis_common.h"
-#include "mantis_reg.h"
-#include "mantis_uart.h"
-
-struct mantis_uart_params {
-	enum mantis_baud	baud_rate;
-	enum mantis_parity	parity;
-};
-
-static struct {
-	char string[7];
-} rates[5] = {
-	{ "9600" },
-	{ "19200" },
-	{ "38400" },
-	{ "57600" },
-	{ "115200" }
-};
-
-static struct {
-	char string[5];
-} parity[3] = {
-	{ "NONE" },
-	{ "ODD" },
-	{ "EVEN" }
-};
-
-#define UART_MAX_BUF			16
-
-int mantis_uart_read(struct mantis_pci *mantis, u8 *data)
-{
-	struct mantis_hwconfig *config = mantis->hwconfig;
-	u32 stat = 0, i;
-
-	/* get data */
-	for (i = 0; i < (config->bytes + 1); i++) {
-
-		stat = mmread(MANTIS_UART_STAT);
-
-		if (stat & MANTIS_UART_RXFIFO_FULL) {
-			dprintk(MANTIS_ERROR, 1, "RX Fifo FULL");
-		}
-		data[i] = mmread(MANTIS_UART_RXD) & 0x3f;
-
-		dprintk(MANTIS_DEBUG, 1, "Reading ... <%02x>", data[i] & 0x3f);
-
-		if (data[i] & (1 << 7)) {
-			dprintk(MANTIS_ERROR, 1, "UART framing error");
-			return -EINVAL;
-		}
-		if (data[i] & (1 << 6)) {
-			dprintk(MANTIS_ERROR, 1, "UART parity error");
-			return -EINVAL;
-		}
-	}
-
-	return 0;
-}
-
-static void mantis_uart_work(struct work_struct *work)
-{
-	struct mantis_pci *mantis = container_of(work, struct mantis_pci, uart_work);
-	struct mantis_hwconfig *config = mantis->hwconfig;
-	u8 buf[16];
-	int i;
-
-	mantis_uart_read(mantis, buf);
-
-	for (i = 0; i < (config->bytes + 1); i++)
-		dprintk(MANTIS_INFO, 1, "UART BUF:%d <%02x> ", i, buf[i]);
-
-	dprintk(MANTIS_DEBUG, 0, "\n");
-}
-
-static int mantis_uart_setup(struct mantis_pci *mantis,
-			     struct mantis_uart_params *params)
-{
-	u32 reg;
-
-	mmwrite((mmread(MANTIS_UART_CTL) | (params->parity & 0x3)), MANTIS_UART_CTL);
-
-	reg = mmread(MANTIS_UART_BAUD);
-
-	switch (params->baud_rate) {
-	case MANTIS_BAUD_9600:
-		reg |= 0xd8;
-		break;
-	case MANTIS_BAUD_19200:
-		reg |= 0x6c;
-		break;
-	case MANTIS_BAUD_38400:
-		reg |= 0x36;
-		break;
-	case MANTIS_BAUD_57600:
-		reg |= 0x23;
-		break;
-	case MANTIS_BAUD_115200:
-		reg |= 0x11;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	mmwrite(reg, MANTIS_UART_BAUD);
-
-	return 0;
-}
-
-int mantis_uart_init(struct mantis_pci *mantis)
-{
-	struct mantis_hwconfig *config = mantis->hwconfig;
-	struct mantis_uart_params params;
-
-	/* default parity: */
-	params.baud_rate = config->baud_rate;
-	params.parity = config->parity;
-	dprintk(MANTIS_INFO, 1, "Initializing UART @ %sbps parity:%s",
-		rates[params.baud_rate].string,
-		parity[params.parity].string);
-
-	init_waitqueue_head(&mantis->uart_wq);
-	spin_lock_init(&mantis->uart_lock);
-
-	INIT_WORK(&mantis->uart_work, mantis_uart_work);
-
-	/* disable interrupt */
-	mmwrite(mmread(MANTIS_UART_CTL) & 0xffef, MANTIS_UART_CTL);
-
-	mantis_uart_setup(mantis, &params);
-
-	/* default 1 byte */
-	mmwrite((mmread(MANTIS_UART_BAUD) | (config->bytes << 8)), MANTIS_UART_BAUD);
-
-	/* flush buffer */
-	mmwrite((mmread(MANTIS_UART_CTL) | MANTIS_UART_RXFLUSH), MANTIS_UART_CTL);
-
-	/* enable interrupt */
-	mmwrite(mmread(MANTIS_INT_MASK) | 0x800, MANTIS_INT_MASK);
-	mmwrite(mmread(MANTIS_UART_CTL) | MANTIS_UART_RXINT, MANTIS_UART_CTL);
-
-	schedule_work(&mantis->uart_work);
-	dprintk(MANTIS_DEBUG, 1, "UART successfully initialized");
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(mantis_uart_init);
-
-void mantis_uart_exit(struct mantis_pci *mantis)
-{
-	/* disable interrupt */
-	mmwrite(mmread(MANTIS_UART_CTL) & 0xffef, MANTIS_UART_CTL);
-	flush_work_sync(&mantis->uart_work);
-}
-EXPORT_SYMBOL_GPL(mantis_uart_exit);
diff --git a/drivers/media/dvb/mantis/mantis_uart.h b/drivers/media/dvb/mantis/mantis_uart.h
deleted file mode 100644
index ffb62a0..0000000
--- a/drivers/media/dvb/mantis/mantis_uart.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
-	Mantis PCI bridge driver
-
-	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#ifndef __MANTIS_UART_H
-#define __MANTIS_UART_H
-
-#define MANTIS_UART_CTL			0xe0
-#define MANTIS_UART_RXINT		(1 << 4)
-#define MANTIS_UART_RXFLUSH		(1 << 2)
-
-#define MANTIS_UART_RXD			0xe8
-#define MANTIS_UART_BAUD		0xec
-
-#define MANTIS_UART_STAT		0xf0
-#define MANTIS_UART_RXFIFO_DATA		(1 << 7)
-#define MANTIS_UART_RXFIFO_EMPTY	(1 << 6)
-#define MANTIS_UART_RXFIFO_FULL		(1 << 3)
-#define MANTIS_UART_FRAME_ERR		(1 << 2)
-#define MANTIS_UART_PARITY_ERR		(1 << 1)
-#define MANTIS_UART_RXTHRESH_INT	(1 << 0)
-
-enum mantis_baud {
-	MANTIS_BAUD_9600	= 0,
-	MANTIS_BAUD_19200,
-	MANTIS_BAUD_38400,
-	MANTIS_BAUD_57600,
-	MANTIS_BAUD_115200
-};
-
-enum mantis_parity {
-	MANTIS_PARITY_NONE	= 0,
-	MANTIS_PARITY_EVEN,
-	MANTIS_PARITY_ODD,
-};
-
-struct mantis_pci;
-
-extern int mantis_uart_init(struct mantis_pci *mantis);
-extern void mantis_uart_exit(struct mantis_pci *mantis);
-
-#endif /* __MANTIS_UART_H */
diff --git a/drivers/media/dvb/mantis/mantis_vp1033.c b/drivers/media/dvb/mantis/mantis_vp1033.c
deleted file mode 100644
index ad013e9..0000000
--- a/drivers/media/dvb/mantis/mantis_vp1033.c
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
-	Mantis VP-1033 driver
-
-	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-
-#include "dmxdev.h"
-#include "dvbdev.h"
-#include "dvb_demux.h"
-#include "dvb_frontend.h"
-#include "dvb_net.h"
-
-#include "stv0299.h"
-#include "mantis_common.h"
-#include "mantis_ioc.h"
-#include "mantis_dvb.h"
-#include "mantis_vp1033.h"
-#include "mantis_reg.h"
-
-u8 lgtdqcs001f_inittab[] = {
-	0x01, 0x15,
-	0x02, 0x30,
-	0x03, 0x00,
-	0x04, 0x2a,
-	0x05, 0x85,
-	0x06, 0x02,
-	0x07, 0x00,
-	0x08, 0x00,
-	0x0c, 0x01,
-	0x0d, 0x81,
-	0x0e, 0x44,
-	0x0f, 0x94,
-	0x10, 0x3c,
-	0x11, 0x84,
-	0x12, 0xb9,
-	0x13, 0xb5,
-	0x14, 0x4f,
-	0x15, 0xc9,
-	0x16, 0x80,
-	0x17, 0x36,
-	0x18, 0xfb,
-	0x19, 0xcf,
-	0x1a, 0xbc,
-	0x1c, 0x2b,
-	0x1d, 0x27,
-	0x1e, 0x00,
-	0x1f, 0x0b,
-	0x20, 0xa1,
-	0x21, 0x60,
-	0x22, 0x00,
-	0x23, 0x00,
-	0x28, 0x00,
-	0x29, 0x28,
-	0x2a, 0x14,
-	0x2b, 0x0f,
-	0x2c, 0x09,
-	0x2d, 0x05,
-	0x31, 0x1f,
-	0x32, 0x19,
-	0x33, 0xfc,
-	0x34, 0x13,
-	0xff, 0xff,
-};
-
-#define MANTIS_MODEL_NAME	"VP-1033"
-#define MANTIS_DEV_TYPE		"DVB-S/DSS"
-
-int lgtdqcs001f_tuner_set(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct mantis_pci *mantis	= fe->dvb->priv;
-	struct i2c_adapter *adapter	= &mantis->adapter;
-
-	u8 buf[4];
-	u32 div;
-
-
-	struct i2c_msg msg = {.addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf)};
-
-	div = p->frequency / 250;
-
-	buf[0] = (div >> 8) & 0x7f;
-	buf[1] =  div & 0xff;
-	buf[2] =  0x83;
-	buf[3] =  0xc0;
-
-	if (p->frequency < 1531000)
-		buf[3] |= 0x04;
-	else
-		buf[3] &= ~0x04;
-	if (i2c_transfer(adapter, &msg, 1) < 0) {
-		dprintk(MANTIS_ERROR, 1, "Write: I2C Transfer failed");
-		return -EIO;
-	}
-	msleep_interruptible(100);
-
-	return 0;
-}
-
-int lgtdqcs001f_set_symbol_rate(struct dvb_frontend *fe,
-				u32 srate, u32 ratio)
-{
-	u8 aclk = 0;
-	u8 bclk = 0;
-
-	if (srate < 1500000) {
-		aclk = 0xb7;
-		bclk = 0x47;
-	} else if (srate < 3000000) {
-		aclk = 0xb7;
-		bclk = 0x4b;
-	} else if (srate < 7000000) {
-		aclk = 0xb7;
-		bclk = 0x4f;
-	} else if (srate < 14000000) {
-		aclk = 0xb7;
-		bclk = 0x53;
-	} else if (srate < 30000000) {
-		aclk = 0xb6;
-		bclk = 0x53;
-	} else if (srate < 45000000) {
-		aclk = 0xb4;
-		bclk = 0x51;
-	}
-	stv0299_writereg(fe, 0x13, aclk);
-	stv0299_writereg(fe, 0x14, bclk);
-
-	stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
-	stv0299_writereg(fe, 0x20, (ratio >>  8) & 0xff);
-	stv0299_writereg(fe, 0x21,  ratio & 0xf0);
-
-	return 0;
-}
-
-struct stv0299_config lgtdqcs001f_config = {
-	.demod_address		= 0x68,
-	.inittab		= lgtdqcs001f_inittab,
-	.mclk			= 88000000UL,
-	.invert			= 0,
-	.skip_reinit		= 0,
-	.volt13_op0_op1		= STV0299_VOLT13_OP0,
-	.min_delay_ms		= 100,
-	.set_symbol_rate	= lgtdqcs001f_set_symbol_rate,
-};
-
-static int vp1033_frontend_init(struct mantis_pci *mantis, struct dvb_frontend *fe)
-{
-	struct i2c_adapter *adapter	= &mantis->adapter;
-
-	int err = 0;
-
-	err = mantis_frontend_power(mantis, POWER_ON);
-	if (err == 0) {
-		mantis_frontend_soft_reset(mantis);
-		msleep(250);
-
-		dprintk(MANTIS_ERROR, 1, "Probing for STV0299 (DVB-S)");
-		fe = dvb_attach(stv0299_attach, &lgtdqcs001f_config, adapter);
-
-		if (fe) {
-			fe->ops.tuner_ops.set_params = lgtdqcs001f_tuner_set;
-			dprintk(MANTIS_ERROR, 1, "found STV0299 DVB-S frontend @ 0x%02x",
-				lgtdqcs001f_config.demod_address);
-
-			dprintk(MANTIS_ERROR, 1, "Mantis DVB-S STV0299 frontend attach success");
-		} else {
-			return -1;
-		}
-	} else {
-		dprintk(MANTIS_ERROR, 1, "Frontend on <%s> POWER ON failed! <%d>",
-			adapter->name,
-			err);
-
-		return -EIO;
-	}
-	mantis->fe = fe;
-	dprintk(MANTIS_ERROR, 1, "Done!");
-
-	return 0;
-}
-
-struct mantis_hwconfig vp1033_config = {
-	.model_name		= MANTIS_MODEL_NAME,
-	.dev_type		= MANTIS_DEV_TYPE,
-	.ts_size		= MANTIS_TS_204,
-
-	.baud_rate		= MANTIS_BAUD_9600,
-	.parity			= MANTIS_PARITY_NONE,
-	.bytes			= 0,
-
-	.frontend_init		= vp1033_frontend_init,
-	.power			= GPIF_A12,
-	.reset			= GPIF_A13,
-};
diff --git a/drivers/media/dvb/mantis/mantis_vp1033.h b/drivers/media/dvb/mantis/mantis_vp1033.h
deleted file mode 100644
index 7daaa1b..0000000
--- a/drivers/media/dvb/mantis/mantis_vp1033.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
-	Mantis VP-1033 driver
-
-	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#ifndef __MANTIS_VP1033_H
-#define __MANTIS_VP1033_H
-
-#include "mantis_common.h"
-
-#define MANTIS_VP_1033_DVB_S	0x0016
-
-extern struct mantis_hwconfig vp1033_config;
-
-#endif /* __MANTIS_VP1033_H */
diff --git a/drivers/media/dvb/mantis/mantis_vp1034.c b/drivers/media/dvb/mantis/mantis_vp1034.c
deleted file mode 100644
index 430ae84..0000000
--- a/drivers/media/dvb/mantis/mantis_vp1034.c
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
-	Mantis VP-1034 driver
-
-	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <asm/io.h>
-
-#include "dmxdev.h"
-#include "dvbdev.h"
-#include "dvb_demux.h"
-#include "dvb_frontend.h"
-#include "dvb_net.h"
-
-#include "mb86a16.h"
-#include "mantis_common.h"
-#include "mantis_ioc.h"
-#include "mantis_dvb.h"
-#include "mantis_vp1034.h"
-#include "mantis_reg.h"
-
-struct mb86a16_config vp1034_mb86a16_config = {
-	.demod_address	= 0x08,
-	.set_voltage	= vp1034_set_voltage,
-};
-
-#define MANTIS_MODEL_NAME	"VP-1034"
-#define MANTIS_DEV_TYPE		"DVB-S/DSS"
-
-int vp1034_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
-{
-	struct mantis_pci *mantis = fe->dvb->priv;
-
-	switch (voltage) {
-	case SEC_VOLTAGE_13:
-		dprintk(MANTIS_ERROR, 1, "Polarization=[13V]");
-		mantis_gpio_set_bits(mantis, 13, 1);
-		mantis_gpio_set_bits(mantis, 14, 0);
-		break;
-	case SEC_VOLTAGE_18:
-		dprintk(MANTIS_ERROR, 1, "Polarization=[18V]");
-		mantis_gpio_set_bits(mantis, 13, 1);
-		mantis_gpio_set_bits(mantis, 14, 1);
-		break;
-	case SEC_VOLTAGE_OFF:
-		dprintk(MANTIS_ERROR, 1, "Frontend (dummy) POWERDOWN");
-		break;
-	default:
-		dprintk(MANTIS_ERROR, 1, "Invalid = (%d)", (u32) voltage);
-		return -EINVAL;
-	}
-	mmwrite(0x00, MANTIS_GPIF_DOUT);
-
-	return 0;
-}
-
-static int vp1034_frontend_init(struct mantis_pci *mantis, struct dvb_frontend *fe)
-{
-	struct i2c_adapter *adapter	= &mantis->adapter;
-
-	int err = 0;
-
-	err = mantis_frontend_power(mantis, POWER_ON);
-	if (err == 0) {
-		mantis_frontend_soft_reset(mantis);
-		msleep(250);
-
-		dprintk(MANTIS_ERROR, 1, "Probing for MB86A16 (DVB-S/DSS)");
-		fe = dvb_attach(mb86a16_attach, &vp1034_mb86a16_config, adapter);
-		if (fe) {
-			dprintk(MANTIS_ERROR, 1,
-			"found MB86A16 DVB-S/DSS frontend @0x%02x",
-			vp1034_mb86a16_config.demod_address);
-
-		} else {
-			return -1;
-		}
-	} else {
-		dprintk(MANTIS_ERROR, 1, "Frontend on <%s> POWER ON failed! <%d>",
-			adapter->name,
-			err);
-
-		return -EIO;
-	}
-	mantis->fe = fe;
-	dprintk(MANTIS_ERROR, 1, "Done!");
-
-	return 0;
-}
-
-struct mantis_hwconfig vp1034_config = {
-	.model_name	= MANTIS_MODEL_NAME,
-	.dev_type	= MANTIS_DEV_TYPE,
-	.ts_size	= MANTIS_TS_204,
-
-	.baud_rate	= MANTIS_BAUD_9600,
-	.parity		= MANTIS_PARITY_NONE,
-	.bytes		= 0,
-
-	.frontend_init	= vp1034_frontend_init,
-	.power		= GPIF_A12,
-	.reset		= GPIF_A13,
-};
diff --git a/drivers/media/dvb/mantis/mantis_vp1034.h b/drivers/media/dvb/mantis/mantis_vp1034.h
deleted file mode 100644
index 323f38e..0000000
--- a/drivers/media/dvb/mantis/mantis_vp1034.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
-	Mantis VP-1034 driver
-
-	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#ifndef __MANTIS_VP1034_H
-#define __MANTIS_VP1034_H
-
-#include "dvb_frontend.h"
-#include "mantis_common.h"
-
-
-#define MANTIS_VP_1034_DVB_S	0x0014
-
-extern struct mantis_hwconfig vp1034_config;
-extern int vp1034_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage);
-
-#endif /* __MANTIS_VP1034_H */
diff --git a/drivers/media/dvb/mantis/mantis_vp1041.c b/drivers/media/dvb/mantis/mantis_vp1041.c
deleted file mode 100644
index 07aa887..0000000
--- a/drivers/media/dvb/mantis/mantis_vp1041.c
+++ /dev/null
@@ -1,357 +0,0 @@
-/*
-	Mantis VP-1041 driver
-
-	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-
-#include "dmxdev.h"
-#include "dvbdev.h"
-#include "dvb_demux.h"
-#include "dvb_frontend.h"
-#include "dvb_net.h"
-
-#include "mantis_common.h"
-#include "mantis_ioc.h"
-#include "mantis_dvb.h"
-#include "mantis_vp1041.h"
-#include "stb0899_reg.h"
-#include "stb0899_drv.h"
-#include "stb0899_cfg.h"
-#include "stb6100_cfg.h"
-#include "stb6100.h"
-#include "lnbp21.h"
-
-#define MANTIS_MODEL_NAME	"VP-1041"
-#define MANTIS_DEV_TYPE		"DSS/DVB-S/DVB-S2"
-
-static const struct stb0899_s1_reg vp1041_stb0899_s1_init_1[] = {
-
-	/* 0x0000000b, *//* SYSREG */
-	{ STB0899_DEV_ID		, 0x30 },
-	{ STB0899_DISCNTRL1		, 0x32 },
-	{ STB0899_DISCNTRL2     	, 0x80 },
-	{ STB0899_DISRX_ST0     	, 0x04 },
-	{ STB0899_DISRX_ST1     	, 0x00 },
-	{ STB0899_DISPARITY     	, 0x00 },
-	{ STB0899_DISSTATUS		, 0x20 },
-	{ STB0899_DISF22        	, 0x99 },
-	{ STB0899_DISF22RX      	, 0xa8 },
-	/* SYSREG ? */
-	{ STB0899_ACRPRESC      	, 0x11 },
-	{ STB0899_ACRDIV1       	, 0x0a },
-	{ STB0899_ACRDIV2       	, 0x05 },
-	{ STB0899_DACR1         	, 0x00 },
-	{ STB0899_DACR2         	, 0x00 },
-	{ STB0899_OUTCFG        	, 0x00 },
-	{ STB0899_MODECFG       	, 0x00 },
-	{ STB0899_IRQSTATUS_3		, 0xfe },
-	{ STB0899_IRQSTATUS_2		, 0x03 },
-	{ STB0899_IRQSTATUS_1		, 0x7c },
-	{ STB0899_IRQSTATUS_0		, 0xf4 },
-	{ STB0899_IRQMSK_3      	, 0xf3 },
-	{ STB0899_IRQMSK_2      	, 0xfc },
-	{ STB0899_IRQMSK_1      	, 0xff },
-	{ STB0899_IRQMSK_0		, 0xff },
-	{ STB0899_IRQCFG		, 0x00 },
-	{ STB0899_I2CCFG        	, 0x88 },
-	{ STB0899_I2CRPT        	, 0x58 },
-	{ STB0899_IOPVALUE5		, 0x00 },
-	{ STB0899_IOPVALUE4		, 0x33 },
-	{ STB0899_IOPVALUE3		, 0x6d },
-	{ STB0899_IOPVALUE2		, 0x90 },
-	{ STB0899_IOPVALUE1		, 0x60 },
-	{ STB0899_IOPVALUE0		, 0x00 },
-	{ STB0899_GPIO00CFG     	, 0x82 },
-	{ STB0899_GPIO01CFG     	, 0x82 },
-	{ STB0899_GPIO02CFG     	, 0x82 },
-	{ STB0899_GPIO03CFG     	, 0x82 },
-	{ STB0899_GPIO04CFG     	, 0x82 },
-	{ STB0899_GPIO05CFG     	, 0x82 },
-	{ STB0899_GPIO06CFG     	, 0x82 },
-	{ STB0899_GPIO07CFG     	, 0x82 },
-	{ STB0899_GPIO08CFG     	, 0x82 },
-	{ STB0899_GPIO09CFG     	, 0x82 },
-	{ STB0899_GPIO10CFG     	, 0x82 },
-	{ STB0899_GPIO11CFG     	, 0x82 },
-	{ STB0899_GPIO12CFG     	, 0x82 },
-	{ STB0899_GPIO13CFG     	, 0x82 },
-	{ STB0899_GPIO14CFG     	, 0x82 },
-	{ STB0899_GPIO15CFG     	, 0x82 },
-	{ STB0899_GPIO16CFG     	, 0x82 },
-	{ STB0899_GPIO17CFG     	, 0x82 },
-	{ STB0899_GPIO18CFG     	, 0x82 },
-	{ STB0899_GPIO19CFG     	, 0x82 },
-	{ STB0899_GPIO20CFG     	, 0x82 },
-	{ STB0899_SDATCFG       	, 0xb8 },
-	{ STB0899_SCLTCFG       	, 0xba },
-	{ STB0899_AGCRFCFG      	, 0x1c }, /* 0x11 */
-	{ STB0899_GPIO22        	, 0x82 }, /* AGCBB2CFG */
-	{ STB0899_GPIO21        	, 0x91 }, /* AGCBB1CFG */
-	{ STB0899_DIRCLKCFG     	, 0x82 },
-	{ STB0899_CLKOUT27CFG   	, 0x7e },
-	{ STB0899_STDBYCFG      	, 0x82 },
-	{ STB0899_CS0CFG        	, 0x82 },
-	{ STB0899_CS1CFG        	, 0x82 },
-	{ STB0899_DISEQCOCFG    	, 0x20 },
-	{ STB0899_GPIO32CFG		, 0x82 },
-	{ STB0899_GPIO33CFG		, 0x82 },
-	{ STB0899_GPIO34CFG		, 0x82 },
-	{ STB0899_GPIO35CFG		, 0x82 },
-	{ STB0899_GPIO36CFG		, 0x82 },
-	{ STB0899_GPIO37CFG		, 0x82 },
-	{ STB0899_GPIO38CFG		, 0x82 },
-	{ STB0899_GPIO39CFG		, 0x82 },
-	{ STB0899_NCOARSE       	, 0x17 }, /* 0x15 = 27 Mhz Clock, F/3 = 198MHz, F/6 = 99MHz */
-	{ STB0899_SYNTCTRL      	, 0x02 }, /* 0x00 = CLK from CLKI, 0x02 = CLK from XTALI */
-	{ STB0899_FILTCTRL      	, 0x00 },
-	{ STB0899_SYSCTRL       	, 0x01 },
-	{ STB0899_STOPCLK1      	, 0x20 },
-	{ STB0899_STOPCLK2      	, 0x00 },
-	{ STB0899_INTBUFSTATUS		, 0x00 },
-	{ STB0899_INTBUFCTRL    	, 0x0a },
-	{ 0xffff			, 0xff },
-};
-
-static const struct stb0899_s1_reg vp1041_stb0899_s1_init_3[] = {
-	{ STB0899_DEMOD         	, 0x00 },
-	{ STB0899_RCOMPC        	, 0xc9 },
-	{ STB0899_AGC1CN        	, 0x01 },
-	{ STB0899_AGC1REF       	, 0x10 },
-	{ STB0899_RTC			, 0x23 },
-	{ STB0899_TMGCFG        	, 0x4e },
-	{ STB0899_AGC2REF       	, 0x34 },
-	{ STB0899_TLSR          	, 0x84 },
-	{ STB0899_CFD           	, 0xf7 },
-	{ STB0899_ACLC			, 0x87 },
-	{ STB0899_BCLC          	, 0x94 },
-	{ STB0899_EQON          	, 0x41 },
-	{ STB0899_LDT           	, 0xf1 },
-	{ STB0899_LDT2          	, 0xe3 },
-	{ STB0899_EQUALREF      	, 0xb4 },
-	{ STB0899_TMGRAMP       	, 0x10 },
-	{ STB0899_TMGTHD        	, 0x30 },
-	{ STB0899_IDCCOMP		, 0xfd },
-	{ STB0899_QDCCOMP		, 0xff },
-	{ STB0899_POWERI		, 0x0c },
-	{ STB0899_POWERQ		, 0x0f },
-	{ STB0899_RCOMP			, 0x6c },
-	{ STB0899_AGCIQIN		, 0x80 },
-	{ STB0899_AGC2I1		, 0x06 },
-	{ STB0899_AGC2I2		, 0x00 },
-	{ STB0899_TLIR			, 0x30 },
-	{ STB0899_RTF			, 0x7f },
-	{ STB0899_DSTATUS		, 0x00 },
-	{ STB0899_LDI			, 0xbc },
-	{ STB0899_CFRM			, 0xea },
-	{ STB0899_CFRL			, 0x31 },
-	{ STB0899_NIRM			, 0x2b },
-	{ STB0899_NIRL			, 0x80 },
-	{ STB0899_ISYMB			, 0x1d },
-	{ STB0899_QSYMB			, 0xa6 },
-	{ STB0899_SFRH          	, 0x2f },
-	{ STB0899_SFRM          	, 0x68 },
-	{ STB0899_SFRL          	, 0x40 },
-	{ STB0899_SFRUPH        	, 0x2f },
-	{ STB0899_SFRUPM        	, 0x68 },
-	{ STB0899_SFRUPL        	, 0x40 },
-	{ STB0899_EQUAI1		, 0x02 },
-	{ STB0899_EQUAQ1		, 0xff },
-	{ STB0899_EQUAI2		, 0x04 },
-	{ STB0899_EQUAQ2		, 0x05 },
-	{ STB0899_EQUAI3		, 0x02 },
-	{ STB0899_EQUAQ3		, 0xfd },
-	{ STB0899_EQUAI4		, 0x03 },
-	{ STB0899_EQUAQ4		, 0x07 },
-	{ STB0899_EQUAI5		, 0x08 },
-	{ STB0899_EQUAQ5		, 0xf5 },
-	{ STB0899_DSTATUS2		, 0x00 },
-	{ STB0899_VSTATUS       	, 0x00 },
-	{ STB0899_VERROR		, 0x86 },
-	{ STB0899_IQSWAP		, 0x2a },
-	{ STB0899_ECNT1M		, 0x00 },
-	{ STB0899_ECNT1L		, 0x00 },
-	{ STB0899_ECNT2M		, 0x00 },
-	{ STB0899_ECNT2L		, 0x00 },
-	{ STB0899_ECNT3M		, 0x0a },
-	{ STB0899_ECNT3L		, 0xad },
-	{ STB0899_FECAUTO1      	, 0x06 },
-	{ STB0899_FECM			, 0x01 },
-	{ STB0899_VTH12         	, 0xb0 },
-	{ STB0899_VTH23         	, 0x7a },
-	{ STB0899_VTH34			, 0x58 },
-	{ STB0899_VTH56         	, 0x38 },
-	{ STB0899_VTH67         	, 0x34 },
-	{ STB0899_VTH78         	, 0x24 },
-	{ STB0899_PRVIT         	, 0xff },
-	{ STB0899_VITSYNC       	, 0x19 },
-	{ STB0899_RSULC         	, 0xb1 }, /* DVB = 0xb1, DSS = 0xa1 */
-	{ STB0899_TSULC         	, 0x42 },
-	{ STB0899_RSLLC         	, 0x41 },
-	{ STB0899_TSLPL			, 0x12 },
-	{ STB0899_TSCFGH        	, 0x0c },
-	{ STB0899_TSCFGM        	, 0x00 },
-	{ STB0899_TSCFGL        	, 0x00 },
-	{ STB0899_TSOUT			, 0x69 }, /* 0x0d for CAM */
-	{ STB0899_RSSYNCDEL     	, 0x00 },
-	{ STB0899_TSINHDELH     	, 0x02 },
-	{ STB0899_TSINHDELM		, 0x00 },
-	{ STB0899_TSINHDELL		, 0x00 },
-	{ STB0899_TSLLSTKM		, 0x1b },
-	{ STB0899_TSLLSTKL		, 0xb3 },
-	{ STB0899_TSULSTKM		, 0x00 },
-	{ STB0899_TSULSTKL		, 0x00 },
-	{ STB0899_PCKLENUL		, 0xbc },
-	{ STB0899_PCKLENLL		, 0xcc },
-	{ STB0899_RSPCKLEN		, 0xbd },
-	{ STB0899_TSSTATUS		, 0x90 },
-	{ STB0899_ERRCTRL1      	, 0xb6 },
-	{ STB0899_ERRCTRL2      	, 0x95 },
-	{ STB0899_ERRCTRL3      	, 0x8d },
-	{ STB0899_DMONMSK1		, 0x27 },
-	{ STB0899_DMONMSK0		, 0x03 },
-	{ STB0899_DEMAPVIT      	, 0x5c },
-	{ STB0899_PLPARM		, 0x19 },
-	{ STB0899_PDELCTRL      	, 0x48 },
-	{ STB0899_PDELCTRL2     	, 0x00 },
-	{ STB0899_BBHCTRL1      	, 0x00 },
-	{ STB0899_BBHCTRL2      	, 0x00 },
-	{ STB0899_HYSTTHRESH    	, 0x77 },
-	{ STB0899_MATCSTM		, 0x00 },
-	{ STB0899_MATCSTL		, 0x00 },
-	{ STB0899_UPLCSTM		, 0x00 },
-	{ STB0899_UPLCSTL		, 0x00 },
-	{ STB0899_DFLCSTM		, 0x00 },
-	{ STB0899_DFLCSTL		, 0x00 },
-	{ STB0899_SYNCCST		, 0x00 },
-	{ STB0899_SYNCDCSTM		, 0x00 },
-	{ STB0899_SYNCDCSTL		, 0x00 },
-	{ STB0899_ISI_ENTRY		, 0x00 },
-	{ STB0899_ISI_BIT_EN		, 0x00 },
-	{ STB0899_MATSTRM		, 0xf0 },
-	{ STB0899_MATSTRL		, 0x02 },
-	{ STB0899_UPLSTRM		, 0x45 },
-	{ STB0899_UPLSTRL		, 0x60 },
-	{ STB0899_DFLSTRM		, 0xe3 },
-	{ STB0899_DFLSTRL		, 0x00 },
-	{ STB0899_SYNCSTR		, 0x47 },
-	{ STB0899_SYNCDSTRM		, 0x05 },
-	{ STB0899_SYNCDSTRL		, 0x18 },
-	{ STB0899_CFGPDELSTATUS1	, 0x19 },
-	{ STB0899_CFGPDELSTATUS2	, 0x2b },
-	{ STB0899_BBFERRORM		, 0x00 },
-	{ STB0899_BBFERRORL		, 0x01 },
-	{ STB0899_UPKTERRORM		, 0x00 },
-	{ STB0899_UPKTERRORL		, 0x00 },
-	{ 0xffff			, 0xff },
-};
-
-struct stb0899_config vp1041_stb0899_config = {
-	.init_dev		= vp1041_stb0899_s1_init_1,
-	.init_s2_demod		= stb0899_s2_init_2,
-	.init_s1_demod		= vp1041_stb0899_s1_init_3,
-	.init_s2_fec		= stb0899_s2_init_4,
-	.init_tst		= stb0899_s1_init_5,
-
-	.demod_address 		= 0x68, /*  0xd0 >> 1 */
-
-	.xtal_freq		= 27000000,
-	.inversion		= IQ_SWAP_ON, /* 1 */
-
-	.lo_clk			= 76500000,
-	.hi_clk			= 99000000,
-
-	.esno_ave		= STB0899_DVBS2_ESNO_AVE,
-	.esno_quant		= STB0899_DVBS2_ESNO_QUANT,
-	.avframes_coarse	= STB0899_DVBS2_AVFRAMES_COARSE,
-	.avframes_fine		= STB0899_DVBS2_AVFRAMES_FINE,
-	.miss_threshold		= STB0899_DVBS2_MISS_THRESHOLD,
-	.uwp_threshold_acq	= STB0899_DVBS2_UWP_THRESHOLD_ACQ,
-	.uwp_threshold_track	= STB0899_DVBS2_UWP_THRESHOLD_TRACK,
-	.uwp_threshold_sof	= STB0899_DVBS2_UWP_THRESHOLD_SOF,
-	.sof_search_timeout	= STB0899_DVBS2_SOF_SEARCH_TIMEOUT,
-
-	.btr_nco_bits		= STB0899_DVBS2_BTR_NCO_BITS,
-	.btr_gain_shift_offset	= STB0899_DVBS2_BTR_GAIN_SHIFT_OFFSET,
-	.crl_nco_bits		= STB0899_DVBS2_CRL_NCO_BITS,
-	.ldpc_max_iter		= STB0899_DVBS2_LDPC_MAX_ITER,
-
-	.tuner_get_frequency	= stb6100_get_frequency,
-	.tuner_set_frequency	= stb6100_set_frequency,
-	.tuner_set_bandwidth	= stb6100_set_bandwidth,
-	.tuner_get_bandwidth	= stb6100_get_bandwidth,
-	.tuner_set_rfsiggain	= NULL,
-};
-
-struct stb6100_config vp1041_stb6100_config = {
-	.tuner_address	= 0x60,
-	.refclock	= 27000000,
-};
-
-static int vp1041_frontend_init(struct mantis_pci *mantis, struct dvb_frontend *fe)
-{
-	struct i2c_adapter *adapter	= &mantis->adapter;
-
-	int err = 0;
-
-	err = mantis_frontend_power(mantis, POWER_ON);
-	if (err == 0) {
-		mantis_frontend_soft_reset(mantis);
-		msleep(250);
-		mantis->fe = dvb_attach(stb0899_attach, &vp1041_stb0899_config, adapter);
-		if (mantis->fe) {
-			dprintk(MANTIS_ERROR, 1,
-				"found STB0899 DVB-S/DVB-S2 frontend @0x%02x",
-				vp1041_stb0899_config.demod_address);
-
-			if (dvb_attach(stb6100_attach, mantis->fe, &vp1041_stb6100_config, adapter)) {
-				if (!dvb_attach(lnbp21_attach, mantis->fe, adapter, 0, 0))
-					dprintk(MANTIS_ERROR, 1, "No LNBP21 found!");
-			}
-		} else {
-			return -EREMOTEIO;
-		}
-	} else {
-		dprintk(MANTIS_ERROR, 1, "Frontend on <%s> POWER ON failed! <%d>",
-			adapter->name,
-			err);
-
-		return -EIO;
-	}
-
-
-	dprintk(MANTIS_ERROR, 1, "Done!");
-
-	return 0;
-}
-
-struct mantis_hwconfig vp1041_config = {
-	.model_name	= MANTIS_MODEL_NAME,
-	.dev_type	= MANTIS_DEV_TYPE,
-	.ts_size	= MANTIS_TS_188,
-
-	.baud_rate	= MANTIS_BAUD_9600,
-	.parity		= MANTIS_PARITY_NONE,
-	.bytes		= 0,
-
-	.frontend_init	= vp1041_frontend_init,
-	.power		= GPIF_A12,
-	.reset		= GPIF_A13,
-};
diff --git a/drivers/media/dvb/mantis/mantis_vp1041.h b/drivers/media/dvb/mantis/mantis_vp1041.h
deleted file mode 100644
index 1ae5b3d..0000000
--- a/drivers/media/dvb/mantis/mantis_vp1041.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
-	Mantis VP-1041 driver
-
-	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#ifndef __MANTIS_VP1041_H
-#define __MANTIS_VP1041_H
-
-#include "mantis_common.h"
-
-#define MANTIS_VP_1041_DVB_S2	0x0031
-#define SKYSTAR_HD2_10		0x0001
-#define SKYSTAR_HD2_20		0x0003
-#define CINERGY_S2_PCI_HD	0x1179
-
-extern struct mantis_hwconfig vp1041_config;
-
-#endif /* __MANTIS_VP1041_H */
diff --git a/drivers/media/dvb/mantis/mantis_vp2033.c b/drivers/media/dvb/mantis/mantis_vp2033.c
deleted file mode 100644
index 1ca6837..0000000
--- a/drivers/media/dvb/mantis/mantis_vp2033.c
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
-	Mantis VP-2033 driver
-
-	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-
-#include "dmxdev.h"
-#include "dvbdev.h"
-#include "dvb_demux.h"
-#include "dvb_frontend.h"
-#include "dvb_net.h"
-
-#include "tda1002x.h"
-#include "mantis_common.h"
-#include "mantis_ioc.h"
-#include "mantis_dvb.h"
-#include "mantis_vp2033.h"
-
-#define MANTIS_MODEL_NAME	"VP-2033"
-#define MANTIS_DEV_TYPE		"DVB-C"
-
-struct tda1002x_config vp2033_tda1002x_cu1216_config = {
-	.demod_address = 0x18 >> 1,
-	.invert = 1,
-};
-
-struct tda10023_config vp2033_tda10023_cu1216_config = {
-	.demod_address = 0x18 >> 1,
-	.invert = 1,
-};
-
-static u8 read_pwm(struct mantis_pci *mantis)
-{
-	struct i2c_adapter *adapter = &mantis->adapter;
-
-	u8 b = 0xff;
-	u8 pwm;
-	struct i2c_msg msg[] = {
-		{.addr = 0x50, .flags = 0, .buf = &b, .len = 1},
-		{.addr = 0x50, .flags = I2C_M_RD, .buf = &pwm, .len = 1}
-	};
-
-	if ((i2c_transfer(adapter, msg, 2) != 2)
-	    || (pwm == 0xff))
-		pwm = 0x48;
-
-	return pwm;
-}
-
-static int tda1002x_cu1216_tuner_set(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct mantis_pci *mantis = fe->dvb->priv;
-	struct i2c_adapter *adapter = &mantis->adapter;
-
-	u8 buf[6];
-	struct i2c_msg msg = {.addr = 0x60, .flags = 0, .buf = buf, .len = sizeof(buf)};
-	int i;
-
-#define CU1216_IF 36125000
-#define TUNER_MUL 62500
-
-	u32 div = (p->frequency + CU1216_IF + TUNER_MUL / 2) / TUNER_MUL;
-
-	buf[0] = (div >> 8) & 0x7f;
-	buf[1] = div & 0xff;
-	buf[2] = 0xce;
-	buf[3] = (p->frequency < 150000000 ? 0x01 :
-		  p->frequency < 445000000 ? 0x02 : 0x04);
-	buf[4] = 0xde;
-	buf[5] = 0x20;
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-
-	if (i2c_transfer(adapter, &msg, 1) != 1)
-		return -EIO;
-
-	/* wait for the pll lock */
-	msg.flags = I2C_M_RD;
-	msg.len = 1;
-	for (i = 0; i < 20; i++) {
-		if (fe->ops.i2c_gate_ctrl)
-			fe->ops.i2c_gate_ctrl(fe, 1);
-
-		if (i2c_transfer(adapter, &msg, 1) == 1 && (buf[0] & 0x40))
-			break;
-
-		msleep(10);
-	}
-
-	/* switch the charge pump to the lower current */
-	msg.flags = 0;
-	msg.len = 2;
-	msg.buf = &buf[2];
-	buf[2] &= ~0x40;
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-
-	if (i2c_transfer(adapter, &msg, 1) != 1)
-		return -EIO;
-
-	return 0;
-}
-
-static int vp2033_frontend_init(struct mantis_pci *mantis, struct dvb_frontend *fe)
-{
-	struct i2c_adapter *adapter = &mantis->adapter;
-
-	int err = 0;
-
-	err = mantis_frontend_power(mantis, POWER_ON);
-	if (err == 0) {
-		mantis_frontend_soft_reset(mantis);
-		msleep(250);
-
-		dprintk(MANTIS_ERROR, 1, "Probing for CU1216 (DVB-C)");
-		fe = dvb_attach(tda10021_attach, &vp2033_tda1002x_cu1216_config,
-				     adapter,
-				     read_pwm(mantis));
-
-		if (fe) {
-			dprintk(MANTIS_ERROR, 1,
-				"found Philips CU1216 DVB-C frontend (TDA10021) @ 0x%02x",
-				vp2033_tda1002x_cu1216_config.demod_address);
-		} else {
-			fe = dvb_attach(tda10023_attach, &vp2033_tda10023_cu1216_config,
-					     adapter,
-					     read_pwm(mantis));
-
-			if (fe) {
-				dprintk(MANTIS_ERROR, 1,
-					"found Philips CU1216 DVB-C frontend (TDA10023) @ 0x%02x",
-					vp2033_tda1002x_cu1216_config.demod_address);
-			}
-		}
-
-		if (fe) {
-			fe->ops.tuner_ops.set_params = tda1002x_cu1216_tuner_set;
-			dprintk(MANTIS_ERROR, 1, "Mantis DVB-C Philips CU1216 frontend attach success");
-		} else {
-			return -1;
-		}
-	} else {
-		dprintk(MANTIS_ERROR, 1, "Frontend on <%s> POWER ON failed! <%d>",
-			adapter->name,
-			err);
-
-		return -EIO;
-	}
-
-	mantis->fe = fe;
-	dprintk(MANTIS_DEBUG, 1, "Done!");
-
-	return 0;
-}
-
-struct mantis_hwconfig vp2033_config = {
-	.model_name	= MANTIS_MODEL_NAME,
-	.dev_type	= MANTIS_DEV_TYPE,
-	.ts_size	= MANTIS_TS_204,
-
-	.baud_rate	= MANTIS_BAUD_9600,
-	.parity		= MANTIS_PARITY_NONE,
-	.bytes		= 0,
-
-	.frontend_init	= vp2033_frontend_init,
-	.power		= GPIF_A12,
-	.reset		= GPIF_A13,
-};
diff --git a/drivers/media/dvb/mantis/mantis_vp2033.h b/drivers/media/dvb/mantis/mantis_vp2033.h
deleted file mode 100644
index c55242b..0000000
--- a/drivers/media/dvb/mantis/mantis_vp2033.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
-	Mantis VP-2033 driver
-
-	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#ifndef __MANTIS_VP2033_H
-#define __MANTIS_VP2033_H
-
-#include "mantis_common.h"
-
-#define MANTIS_VP_2033_DVB_C	0x0008
-
-extern struct mantis_hwconfig vp2033_config;
-
-#endif /* __MANTIS_VP2033_H */
diff --git a/drivers/media/dvb/mantis/mantis_vp2040.c b/drivers/media/dvb/mantis/mantis_vp2040.c
deleted file mode 100644
index d480741..0000000
--- a/drivers/media/dvb/mantis/mantis_vp2040.c
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
-	Mantis VP-2040 driver
-
-	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-
-#include "dmxdev.h"
-#include "dvbdev.h"
-#include "dvb_demux.h"
-#include "dvb_frontend.h"
-#include "dvb_net.h"
-
-#include "tda1002x.h"
-#include "mantis_common.h"
-#include "mantis_ioc.h"
-#include "mantis_dvb.h"
-#include "mantis_vp2040.h"
-
-#define MANTIS_MODEL_NAME	"VP-2040"
-#define MANTIS_DEV_TYPE		"DVB-C"
-
-struct tda1002x_config vp2040_tda1002x_cu1216_config = {
-	.demod_address	= 0x18 >> 1,
-	.invert		= 1,
-};
-
-struct tda10023_config vp2040_tda10023_cu1216_config = {
-	.demod_address	= 0x18 >> 1,
-	.invert		= 1,
-};
-
-static int tda1002x_cu1216_tuner_set(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct mantis_pci *mantis	= fe->dvb->priv;
-	struct i2c_adapter *adapter	= &mantis->adapter;
-
-	u8 buf[6];
-	struct i2c_msg msg = {.addr = 0x60, .flags = 0, .buf = buf, .len = sizeof(buf)};
-	int i;
-
-#define CU1216_IF 36125000
-#define TUNER_MUL 62500
-
-	u32 div = (p->frequency + CU1216_IF + TUNER_MUL / 2) / TUNER_MUL;
-
-	buf[0] = (div >> 8) & 0x7f;
-	buf[1] = div & 0xff;
-	buf[2] = 0xce;
-	buf[3] = (p->frequency < 150000000 ? 0x01 :
-		  p->frequency < 445000000 ? 0x02 : 0x04);
-	buf[4] = 0xde;
-	buf[5] = 0x20;
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-
-	if (i2c_transfer(adapter, &msg, 1) != 1)
-		return -EIO;
-
-	/* wait for the pll lock */
-	msg.flags = I2C_M_RD;
-	msg.len = 1;
-	for (i = 0; i < 20; i++) {
-		if (fe->ops.i2c_gate_ctrl)
-			fe->ops.i2c_gate_ctrl(fe, 1);
-
-		if (i2c_transfer(adapter, &msg, 1) == 1 && (buf[0] & 0x40))
-			break;
-
-		msleep(10);
-	}
-
-	/* switch the charge pump to the lower current */
-	msg.flags = 0;
-	msg.len = 2;
-	msg.buf = &buf[2];
-	buf[2] &= ~0x40;
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-
-	if (i2c_transfer(adapter, &msg, 1) != 1)
-		return -EIO;
-
-	return 0;
-}
-
-static u8 read_pwm(struct mantis_pci *mantis)
-{
-	struct i2c_adapter *adapter = &mantis->adapter;
-
-	u8 b = 0xff;
-	u8 pwm;
-	struct i2c_msg msg[] = {
-		{.addr = 0x50, .flags = 0, .buf = &b, .len = 1},
-		{.addr = 0x50, .flags = I2C_M_RD, .buf = &pwm, .len = 1}
-	};
-
-	if ((i2c_transfer(adapter, msg, 2) != 2)
-	    || (pwm == 0xff))
-		pwm = 0x48;
-
-	return pwm;
-}
-
-static int vp2040_frontend_init(struct mantis_pci *mantis, struct dvb_frontend *fe)
-{
-	struct i2c_adapter *adapter = &mantis->adapter;
-
-	int err = 0;
-
-	err = mantis_frontend_power(mantis, POWER_ON);
-	if (err == 0) {
-		mantis_frontend_soft_reset(mantis);
-		msleep(250);
-
-		dprintk(MANTIS_ERROR, 1, "Probing for CU1216 (DVB-C)");
-		fe = dvb_attach(tda10021_attach, &vp2040_tda1002x_cu1216_config,
-				     adapter,
-				     read_pwm(mantis));
-
-		if (fe) {
-			dprintk(MANTIS_ERROR, 1,
-				"found Philips CU1216 DVB-C frontend (TDA10021) @ 0x%02x",
-				vp2040_tda1002x_cu1216_config.demod_address);
-		} else {
-			fe = dvb_attach(tda10023_attach, &vp2040_tda10023_cu1216_config,
-					     adapter,
-					     read_pwm(mantis));
-
-			if (fe) {
-				dprintk(MANTIS_ERROR, 1,
-					"found Philips CU1216 DVB-C frontend (TDA10023) @ 0x%02x",
-					vp2040_tda1002x_cu1216_config.demod_address);
-			}
-		}
-
-		if (fe) {
-			fe->ops.tuner_ops.set_params = tda1002x_cu1216_tuner_set;
-			dprintk(MANTIS_ERROR, 1, "Mantis DVB-C Philips CU1216 frontend attach success");
-		} else {
-			return -1;
-		}
-	} else {
-		dprintk(MANTIS_ERROR, 1, "Frontend on <%s> POWER ON failed! <%d>",
-			adapter->name,
-			err);
-
-		return -EIO;
-	}
-	mantis->fe = fe;
-	dprintk(MANTIS_DEBUG, 1, "Done!");
-
-	return 0;
-}
-
-struct mantis_hwconfig vp2040_config = {
-	.model_name	= MANTIS_MODEL_NAME,
-	.dev_type	= MANTIS_DEV_TYPE,
-	.ts_size	= MANTIS_TS_204,
-
-	.baud_rate	= MANTIS_BAUD_9600,
-	.parity		= MANTIS_PARITY_NONE,
-	.bytes		= 0,
-
-	.frontend_init	= vp2040_frontend_init,
-	.power		= GPIF_A12,
-	.reset		= GPIF_A13,
-};
diff --git a/drivers/media/dvb/mantis/mantis_vp2040.h b/drivers/media/dvb/mantis/mantis_vp2040.h
deleted file mode 100644
index d125e21..0000000
--- a/drivers/media/dvb/mantis/mantis_vp2040.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
-	Mantis VP-2040 driver
-
-	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#ifndef __MANTIS_VP2040_H
-#define __MANTIS_VP2040_H
-
-#include "mantis_common.h"
-
-#define MANTIS_VP_2040_DVB_C	0x0043
-#define CINERGY_C		0x1178
-#define CABLESTAR_HD2		0x0002
-
-extern struct mantis_hwconfig vp2040_config;
-
-#endif /* __MANTIS_VP2040_H */
diff --git a/drivers/media/dvb/mantis/mantis_vp3028.c b/drivers/media/dvb/mantis/mantis_vp3028.c
deleted file mode 100644
index 4155c83..0000000
--- a/drivers/media/dvb/mantis/mantis_vp3028.c
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
-	Mantis VP-3028 driver
-
-	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include "mantis_common.h"
-#include "mantis_vp3028.h"
-
-struct zl10353_config mantis_vp3028_config = {
-	.demod_address	= 0x0f,
-};
-
-#define MANTIS_MODEL_NAME	"VP-3028"
-#define MANTIS_DEV_TYPE		"DVB-T"
-
-struct mantis_hwconfig vp3028_mantis_config = {
-	.model_name	= MANTIS_MODEL_NAME,
-	.dev_type	= MANTIS_DEV_TYPE,
-	.ts_size	= MANTIS_TS_188,
-	.baud_rate	= MANTIS_BAUD_9600,
-	.parity		= MANTIS_PARITY_NONE,
-	.bytes		= 0,
-};
diff --git a/drivers/media/dvb/mantis/mantis_vp3028.h b/drivers/media/dvb/mantis/mantis_vp3028.h
deleted file mode 100644
index b07be6a..0000000
--- a/drivers/media/dvb/mantis/mantis_vp3028.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
-	Mantis VP-3028 driver
-
-	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#ifndef __MANTIS_VP3028_H
-#define __MANTIS_VP3028_H
-
-#include "dvb_frontend.h"
-#include "mantis_common.h"
-#include "zl10353.h"
-
-#define MANTIS_VP_3028_DVB_T	0x0028
-
-extern struct zl10353_config mantis_vp3028_config;
-extern struct mantis_hwconfig vp3028_mantis_config;
-
-#endif /* __MANTIS_VP3028_H */
diff --git a/drivers/media/dvb/mantis/mantis_vp3030.c b/drivers/media/dvb/mantis/mantis_vp3030.c
deleted file mode 100644
index c09308cd..0000000
--- a/drivers/media/dvb/mantis/mantis_vp3030.c
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
-	Mantis VP-3030 driver
-
-	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-
-#include "dmxdev.h"
-#include "dvbdev.h"
-#include "dvb_demux.h"
-#include "dvb_frontend.h"
-#include "dvb_net.h"
-
-#include "zl10353.h"
-#include "tda665x.h"
-#include "mantis_common.h"
-#include "mantis_ioc.h"
-#include "mantis_dvb.h"
-#include "mantis_vp3030.h"
-
-struct zl10353_config mantis_vp3030_config = {
-	.demod_address		= 0x0f,
-};
-
-struct tda665x_config env57h12d5_config = {
-	.name			= "ENV57H12D5 (ET-50DT)",
-	.addr			= 0x60,
-	.frequency_min		=  47000000,
-	.frequency_max		= 862000000,
-	.frequency_offst	=   3616667,
-	.ref_multiplier		= 6, /* 1/6 MHz */
-	.ref_divider		= 100000, /* 1/6 MHz */
-};
-
-#define MANTIS_MODEL_NAME	"VP-3030"
-#define MANTIS_DEV_TYPE		"DVB-T"
-
-
-static int vp3030_frontend_init(struct mantis_pci *mantis, struct dvb_frontend *fe)
-{
-	struct i2c_adapter *adapter	= &mantis->adapter;
-	struct mantis_hwconfig *config	= mantis->hwconfig;
-	int err = 0;
-
-	mantis_gpio_set_bits(mantis, config->reset, 0);
-	msleep(100);
-	err = mantis_frontend_power(mantis, POWER_ON);
-	msleep(100);
-	mantis_gpio_set_bits(mantis, config->reset, 1);
-
-	if (err == 0) {
-		msleep(250);
-		dprintk(MANTIS_ERROR, 1, "Probing for 10353 (DVB-T)");
-		fe = dvb_attach(zl10353_attach, &mantis_vp3030_config, adapter);
-
-		if (!fe)
-			return -1;
-
-		dvb_attach(tda665x_attach, fe, &env57h12d5_config, adapter);
-	} else {
-		dprintk(MANTIS_ERROR, 1, "Frontend on <%s> POWER ON failed! <%d>",
-			adapter->name,
-			err);
-
-		return -EIO;
-
-	}
-	mantis->fe = fe;
-	dprintk(MANTIS_ERROR, 1, "Done!");
-
-	return 0;
-}
-
-struct mantis_hwconfig vp3030_config = {
-	.model_name	= MANTIS_MODEL_NAME,
-	.dev_type	= MANTIS_DEV_TYPE,
-	.ts_size	= MANTIS_TS_188,
-
-	.baud_rate	= MANTIS_BAUD_9600,
-	.parity		= MANTIS_PARITY_NONE,
-	.bytes		= 0,
-
-	.frontend_init	= vp3030_frontend_init,
-	.power		= GPIF_A12,
-	.reset		= GPIF_A13,
-
-	.i2c_mode	= MANTIS_BYTE_MODE
-};
diff --git a/drivers/media/dvb/mantis/mantis_vp3030.h b/drivers/media/dvb/mantis/mantis_vp3030.h
deleted file mode 100644
index 5f12c42..0000000
--- a/drivers/media/dvb/mantis/mantis_vp3030.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
-	Mantis VP-3030 driver
-
-	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#ifndef __MANTIS_VP3030_H
-#define __MANTIS_VP3030_H
-
-#include "mantis_common.h"
-
-#define MANTIS_VP_3030_DVB_T	0x0024
-
-extern struct mantis_hwconfig vp3030_config;
-
-#endif /* __MANTIS_VP3030_H */
diff --git a/drivers/media/dvb/ngene/Kconfig b/drivers/media/dvb/ngene/Kconfig
deleted file mode 100644
index 64c8470..0000000
--- a/drivers/media/dvb/ngene/Kconfig
+++ /dev/null
@@ -1,13 +0,0 @@
-config DVB_NGENE
-	tristate "Micronas nGene support"
-	depends on DVB_CORE && PCI && I2C
-	select DVB_LNBP21 if !DVB_FE_CUSTOMISE
-	select DVB_STV6110x if !DVB_FE_CUSTOMISE
-	select DVB_STV090x if !DVB_FE_CUSTOMISE
-	select DVB_LGDT330X if !DVB_FE_CUSTOMISE
-	select DVB_DRXK if !DVB_FE_CUSTOMISE
-	select DVB_TDA18271C2DD if !DVB_FE_CUSTOMISE
-	select MEDIA_TUNER_MT2131 if !MEDIA_TUNER_CUSTOMISE
-	---help---
-	  Support for Micronas PCI express cards with nGene bridge.
-
diff --git a/drivers/media/dvb/ngene/Makefile b/drivers/media/dvb/ngene/Makefile
deleted file mode 100644
index 13ebeff..0000000
--- a/drivers/media/dvb/ngene/Makefile
+++ /dev/null
@@ -1,14 +0,0 @@
-#
-# Makefile for the nGene device driver
-#
-
-ngene-objs := ngene-core.o ngene-i2c.o ngene-cards.o ngene-dvb.o
-
-obj-$(CONFIG_DVB_NGENE) += ngene.o
-
-ccflags-y += -Idrivers/media/dvb/dvb-core/
-ccflags-y += -Idrivers/media/dvb/frontends/
-ccflags-y += -Idrivers/media/common/tuners/
-
-# For the staging CI driver cxd2099
-ccflags-y += -Idrivers/staging/media/cxd2099/
diff --git a/drivers/media/dvb/ngene/ngene-cards.c b/drivers/media/dvb/ngene/ngene-cards.c
deleted file mode 100644
index 72ee8de..0000000
--- a/drivers/media/dvb/ngene/ngene-cards.c
+++ /dev/null
@@ -1,560 +0,0 @@
-/*
- * ngene-cards.c: nGene PCIe bridge driver - card specific info
- *
- * Copyright (C) 2005-2007 Micronas
- *
- * Copyright (C) 2008-2009 Ralph Metzler <rjkm@metzlerbros.de>
- *                         Modifications for new nGene firmware,
- *                         support for EEPROM-copying,
- *                         support for new dual DVB-S2 card prototype
- *
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 only, as published by the Free Software Foundation.
- *
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/pci_ids.h>
-
-#include "ngene.h"
-
-/* demods/tuners */
-#include "stv6110x.h"
-#include "stv090x.h"
-#include "lnbh24.h"
-#include "lgdt330x.h"
-#include "mt2131.h"
-#include "tda18271c2dd.h"
-#include "drxk.h"
-
-
-/****************************************************************************/
-/* Demod/tuner attachment ***************************************************/
-/****************************************************************************/
-
-static int tuner_attach_stv6110(struct ngene_channel *chan)
-{
-	struct i2c_adapter *i2c;
-	struct stv090x_config *feconf = (struct stv090x_config *)
-		chan->dev->card_info->fe_config[chan->number];
-	struct stv6110x_config *tunerconf = (struct stv6110x_config *)
-		chan->dev->card_info->tuner_config[chan->number];
-	struct stv6110x_devctl *ctl;
-
-	/* tuner 1+2: i2c adapter #0, tuner 3+4: i2c adapter #1 */
-	if (chan->number < 2)
-		i2c = &chan->dev->channel[0].i2c_adapter;
-	else
-		i2c = &chan->dev->channel[1].i2c_adapter;
-
-	ctl = dvb_attach(stv6110x_attach, chan->fe, tunerconf, i2c);
-	if (ctl == NULL) {
-		printk(KERN_ERR	DEVICE_NAME ": No STV6110X found!\n");
-		return -ENODEV;
-	}
-
-	feconf->tuner_init          = ctl->tuner_init;
-	feconf->tuner_sleep         = ctl->tuner_sleep;
-	feconf->tuner_set_mode      = ctl->tuner_set_mode;
-	feconf->tuner_set_frequency = ctl->tuner_set_frequency;
-	feconf->tuner_get_frequency = ctl->tuner_get_frequency;
-	feconf->tuner_set_bandwidth = ctl->tuner_set_bandwidth;
-	feconf->tuner_get_bandwidth = ctl->tuner_get_bandwidth;
-	feconf->tuner_set_bbgain    = ctl->tuner_set_bbgain;
-	feconf->tuner_get_bbgain    = ctl->tuner_get_bbgain;
-	feconf->tuner_set_refclk    = ctl->tuner_set_refclk;
-	feconf->tuner_get_status    = ctl->tuner_get_status;
-
-	return 0;
-}
-
-
-static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable)
-{
-	struct ngene_channel *chan = fe->sec_priv;
-	int status;
-
-	if (enable) {
-		down(&chan->dev->pll_mutex);
-		status = chan->gate_ctrl(fe, 1);
-	} else {
-		status = chan->gate_ctrl(fe, 0);
-		up(&chan->dev->pll_mutex);
-	}
-	return status;
-}
-
-static int tuner_attach_tda18271(struct ngene_channel *chan)
-{
-	struct i2c_adapter *i2c;
-	struct dvb_frontend *fe;
-
-	i2c = &chan->dev->channel[0].i2c_adapter;
-	if (chan->fe->ops.i2c_gate_ctrl)
-		chan->fe->ops.i2c_gate_ctrl(chan->fe, 1);
-	fe = dvb_attach(tda18271c2dd_attach, chan->fe, i2c, 0x60);
-	if (chan->fe->ops.i2c_gate_ctrl)
-		chan->fe->ops.i2c_gate_ctrl(chan->fe, 0);
-	if (!fe) {
-		printk(KERN_ERR "No TDA18271 found!\n");
-		return -ENODEV;
-	}
-
-	return 0;
-}
-
-static int tuner_attach_probe(struct ngene_channel *chan)
-{
-	if (chan->demod_type == 0)
-		return tuner_attach_stv6110(chan);
-	if (chan->demod_type == 1)
-		return tuner_attach_tda18271(chan);
-	return -EINVAL;
-}
-
-static int demod_attach_stv0900(struct ngene_channel *chan)
-{
-	struct i2c_adapter *i2c;
-	struct stv090x_config *feconf = (struct stv090x_config *)
-		chan->dev->card_info->fe_config[chan->number];
-
-	/* tuner 1+2: i2c adapter #0, tuner 3+4: i2c adapter #1 */
-	/* Note: Both adapters share the same i2c bus, but the demod     */
-	/*       driver requires that each demod has its own i2c adapter */
-	if (chan->number < 2)
-		i2c = &chan->dev->channel[0].i2c_adapter;
-	else
-		i2c = &chan->dev->channel[1].i2c_adapter;
-
-	chan->fe = dvb_attach(stv090x_attach, feconf, i2c,
-			(chan->number & 1) == 0 ? STV090x_DEMODULATOR_0
-						: STV090x_DEMODULATOR_1);
-	if (chan->fe == NULL) {
-		printk(KERN_ERR	DEVICE_NAME ": No STV0900 found!\n");
-		return -ENODEV;
-	}
-
-	/* store channel info */
-	if (feconf->tuner_i2c_lock)
-		chan->fe->analog_demod_priv = chan;
-
-	if (!dvb_attach(lnbh24_attach, chan->fe, i2c, 0,
-			0, chan->dev->card_info->lnb[chan->number])) {
-		printk(KERN_ERR DEVICE_NAME ": No LNBH24 found!\n");
-		dvb_frontend_detach(chan->fe);
-		chan->fe = NULL;
-		return -ENODEV;
-	}
-
-	return 0;
-}
-
-static void cineS2_tuner_i2c_lock(struct dvb_frontend *fe, int lock)
-{
-	struct ngene_channel *chan = fe->analog_demod_priv;
-
-	if (lock)
-		down(&chan->dev->pll_mutex);
-	else
-		up(&chan->dev->pll_mutex);
-}
-
-static int i2c_read(struct i2c_adapter *adapter, u8 adr, u8 *val)
-{
-	struct i2c_msg msgs[1] = {{.addr = adr,  .flags = I2C_M_RD,
-				   .buf  = val,  .len   = 1 } };
-	return (i2c_transfer(adapter, msgs, 1) == 1) ? 0 : -1;
-}
-
-static int i2c_read_reg16(struct i2c_adapter *adapter, u8 adr,
-			  u16 reg, u8 *val)
-{
-	u8 msg[2] = {reg>>8, reg&0xff};
-	struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0,
-				   .buf  = msg, .len   = 2},
-				  {.addr = adr, .flags = I2C_M_RD,
-				   .buf  = val, .len   = 1} };
-	return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1;
-}
-
-static int port_has_stv0900(struct i2c_adapter *i2c, int port)
-{
-	u8 val;
-	if (i2c_read_reg16(i2c, 0x68+port/2, 0xf100, &val) < 0)
-		return 0;
-	return 1;
-}
-
-static int port_has_drxk(struct i2c_adapter *i2c, int port)
-{
-	u8 val;
-
-	if (i2c_read(i2c, 0x29+port, &val) < 0)
-		return 0;
-	return 1;
-}
-
-static int demod_attach_drxk(struct ngene_channel *chan,
-			     struct i2c_adapter *i2c)
-{
-	struct drxk_config config;
-
-	memset(&config, 0, sizeof(config));
-	config.microcode_name = "drxk_a3.mc";
-	config.qam_demod_parameter_count = 4;
-	config.adr = 0x29 + (chan->number ^ 2);
-
-	chan->fe = dvb_attach(drxk_attach, &config, i2c);
-	if (!chan->fe) {
-		printk(KERN_ERR "No DRXK found!\n");
-		return -ENODEV;
-	}
-	chan->fe->sec_priv = chan;
-	chan->gate_ctrl = chan->fe->ops.i2c_gate_ctrl;
-	chan->fe->ops.i2c_gate_ctrl = drxk_gate_ctrl;
-	return 0;
-}
-
-static int cineS2_probe(struct ngene_channel *chan)
-{
-	struct i2c_adapter *i2c;
-	struct stv090x_config *fe_conf;
-	u8 buf[3];
-	struct i2c_msg i2c_msg = { .flags = 0, .buf = buf };
-	int rc;
-
-	/* tuner 1+2: i2c adapter #0, tuner 3+4: i2c adapter #1 */
-	if (chan->number < 2)
-		i2c = &chan->dev->channel[0].i2c_adapter;
-	else
-		i2c = &chan->dev->channel[1].i2c_adapter;
-
-	if (port_has_stv0900(i2c, chan->number)) {
-		chan->demod_type = 0;
-		fe_conf = chan->dev->card_info->fe_config[chan->number];
-		/* demod found, attach it */
-		rc = demod_attach_stv0900(chan);
-		if (rc < 0 || chan->number < 2)
-			return rc;
-
-		/* demod #2: reprogram outputs DPN1 & DPN2 */
-		i2c_msg.addr = fe_conf->address;
-		i2c_msg.len = 3;
-		buf[0] = 0xf1;
-		switch (chan->number) {
-		case 2:
-			buf[1] = 0x5c;
-			buf[2] = 0xc2;
-			break;
-		case 3:
-			buf[1] = 0x61;
-			buf[2] = 0xcc;
-			break;
-		default:
-			return -ENODEV;
-		}
-		rc = i2c_transfer(i2c, &i2c_msg, 1);
-		if (rc != 1) {
-			printk(KERN_ERR DEVICE_NAME ": could not setup DPNx\n");
-			return -EIO;
-		}
-	} else if (port_has_drxk(i2c, chan->number^2)) {
-		chan->demod_type = 1;
-		demod_attach_drxk(chan, i2c);
-	} else {
-		printk(KERN_ERR "No demod found on chan %d\n", chan->number);
-		return -ENODEV;
-	}
-	return 0;
-}
-
-
-static struct lgdt330x_config aver_m780 = {
-	.demod_address = 0xb2 >> 1,
-	.demod_chip    = LGDT3303,
-	.serial_mpeg   = 0x00, /* PARALLEL */
-	.clock_polarity_flip = 1,
-};
-
-static struct mt2131_config m780_tunerconfig = {
-	0xc0 >> 1
-};
-
-/* A single func to attach the demo and tuner, rather than
- * use two sep funcs like the current design mandates.
- */
-static int demod_attach_lg330x(struct ngene_channel *chan)
-{
-	chan->fe = dvb_attach(lgdt330x_attach, &aver_m780, &chan->i2c_adapter);
-	if (chan->fe == NULL) {
-		printk(KERN_ERR	DEVICE_NAME ": No LGDT330x found!\n");
-		return -ENODEV;
-	}
-
-	dvb_attach(mt2131_attach, chan->fe, &chan->i2c_adapter,
-		   &m780_tunerconfig, 0);
-
-	return (chan->fe) ? 0 : -ENODEV;
-}
-
-/****************************************************************************/
-/* Switch control (I2C gates, etc.) *****************************************/
-/****************************************************************************/
-
-
-static struct stv090x_config fe_cineS2 = {
-	.device         = STV0900,
-	.demod_mode     = STV090x_DUAL,
-	.clk_mode       = STV090x_CLK_EXT,
-
-	.xtal           = 27000000,
-	.address        = 0x68,
-
-	.ts1_mode       = STV090x_TSMODE_SERIAL_PUNCTURED,
-	.ts2_mode       = STV090x_TSMODE_SERIAL_PUNCTURED,
-
-	.repeater_level = STV090x_RPTLEVEL_16,
-
-	.adc1_range	= STV090x_ADC_1Vpp,
-	.adc2_range	= STV090x_ADC_1Vpp,
-
-	.diseqc_envelope_mode = true,
-
-	.tuner_i2c_lock = cineS2_tuner_i2c_lock,
-};
-
-static struct stv090x_config fe_cineS2_2 = {
-	.device         = STV0900,
-	.demod_mode     = STV090x_DUAL,
-	.clk_mode       = STV090x_CLK_EXT,
-
-	.xtal           = 27000000,
-	.address        = 0x69,
-
-	.ts1_mode       = STV090x_TSMODE_SERIAL_PUNCTURED,
-	.ts2_mode       = STV090x_TSMODE_SERIAL_PUNCTURED,
-
-	.repeater_level = STV090x_RPTLEVEL_16,
-
-	.adc1_range	= STV090x_ADC_1Vpp,
-	.adc2_range	= STV090x_ADC_1Vpp,
-
-	.diseqc_envelope_mode = true,
-
-	.tuner_i2c_lock = cineS2_tuner_i2c_lock,
-};
-
-static struct stv6110x_config tuner_cineS2_0 = {
-	.addr	= 0x60,
-	.refclk	= 27000000,
-	.clk_div = 1,
-};
-
-static struct stv6110x_config tuner_cineS2_1 = {
-	.addr	= 0x63,
-	.refclk	= 27000000,
-	.clk_div = 1,
-};
-
-static struct ngene_info ngene_info_cineS2 = {
-	.type		= NGENE_SIDEWINDER,
-	.name		= "Linux4Media cineS2 DVB-S2 Twin Tuner",
-	.io_type	= {NGENE_IO_TSIN, NGENE_IO_TSIN},
-	.demod_attach	= {demod_attach_stv0900, demod_attach_stv0900},
-	.tuner_attach	= {tuner_attach_stv6110, tuner_attach_stv6110},
-	.fe_config	= {&fe_cineS2, &fe_cineS2},
-	.tuner_config	= {&tuner_cineS2_0, &tuner_cineS2_1},
-	.lnb		= {0x0b, 0x08},
-	.tsf		= {3, 3},
-	.fw_version	= 18,
-	.msi_supported	= true,
-};
-
-static struct ngene_info ngene_info_satixS2 = {
-	.type		= NGENE_SIDEWINDER,
-	.name		= "Mystique SaTiX-S2 Dual",
-	.io_type	= {NGENE_IO_TSIN, NGENE_IO_TSIN},
-	.demod_attach	= {demod_attach_stv0900, demod_attach_stv0900},
-	.tuner_attach	= {tuner_attach_stv6110, tuner_attach_stv6110},
-	.fe_config	= {&fe_cineS2, &fe_cineS2},
-	.tuner_config	= {&tuner_cineS2_0, &tuner_cineS2_1},
-	.lnb		= {0x0b, 0x08},
-	.tsf		= {3, 3},
-	.fw_version	= 18,
-	.msi_supported	= true,
-};
-
-static struct ngene_info ngene_info_satixS2v2 = {
-	.type		= NGENE_SIDEWINDER,
-	.name		= "Mystique SaTiX-S2 Dual (v2)",
-	.io_type	= {NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN,
-			   NGENE_IO_TSOUT},
-	.demod_attach	= {demod_attach_stv0900, demod_attach_stv0900, cineS2_probe, cineS2_probe},
-	.tuner_attach	= {tuner_attach_stv6110, tuner_attach_stv6110, tuner_attach_probe, tuner_attach_probe},
-	.fe_config	= {&fe_cineS2, &fe_cineS2, &fe_cineS2_2, &fe_cineS2_2},
-	.tuner_config	= {&tuner_cineS2_0, &tuner_cineS2_1, &tuner_cineS2_0, &tuner_cineS2_1},
-	.lnb		= {0x0a, 0x08, 0x0b, 0x09},
-	.tsf		= {3, 3},
-	.fw_version	= 18,
-	.msi_supported	= true,
-};
-
-static struct ngene_info ngene_info_cineS2v5 = {
-	.type		= NGENE_SIDEWINDER,
-	.name		= "Linux4Media cineS2 DVB-S2 Twin Tuner (v5)",
-	.io_type	= {NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN,
-			   NGENE_IO_TSOUT},
-	.demod_attach	= {demod_attach_stv0900, demod_attach_stv0900, cineS2_probe, cineS2_probe},
-	.tuner_attach	= {tuner_attach_stv6110, tuner_attach_stv6110, tuner_attach_probe, tuner_attach_probe},
-	.fe_config	= {&fe_cineS2, &fe_cineS2, &fe_cineS2_2, &fe_cineS2_2},
-	.tuner_config	= {&tuner_cineS2_0, &tuner_cineS2_1, &tuner_cineS2_0, &tuner_cineS2_1},
-	.lnb		= {0x0a, 0x08, 0x0b, 0x09},
-	.tsf		= {3, 3},
-	.fw_version	= 18,
-	.msi_supported	= true,
-};
-
-
-static struct ngene_info ngene_info_duoFlex = {
-	.type           = NGENE_SIDEWINDER,
-	.name           = "Digital Devices DuoFlex PCIe or miniPCIe",
-	.io_type        = {NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN,
-			   NGENE_IO_TSOUT},
-	.demod_attach   = {cineS2_probe, cineS2_probe, cineS2_probe, cineS2_probe},
-	.tuner_attach   = {tuner_attach_probe, tuner_attach_probe, tuner_attach_probe, tuner_attach_probe},
-	.fe_config      = {&fe_cineS2, &fe_cineS2, &fe_cineS2_2, &fe_cineS2_2},
-	.tuner_config   = {&tuner_cineS2_0, &tuner_cineS2_1, &tuner_cineS2_0, &tuner_cineS2_1},
-	.lnb            = {0x0a, 0x08, 0x0b, 0x09},
-	.tsf            = {3, 3},
-	.fw_version     = 18,
-	.msi_supported	= true,
-};
-
-static struct ngene_info ngene_info_m780 = {
-	.type           = NGENE_APP,
-	.name           = "Aver M780 ATSC/QAM-B",
-
-	/* Channel 0 is analog, which is currently unsupported */
-	.io_type        = { NGENE_IO_NONE, NGENE_IO_TSIN },
-	.demod_attach   = { NULL, demod_attach_lg330x },
-
-	/* Ensure these are NULL else the frame will call them (as funcs) */
-	.tuner_attach   = { 0, 0, 0, 0 },
-	.fe_config      = { NULL, &aver_m780 },
-	.avf            = { 0 },
-
-	/* A custom electrical interface config for the demod to bridge */
-	.tsf		= { 4, 4 },
-	.fw_version	= 15,
-};
-
-/****************************************************************************/
-
-
-
-/****************************************************************************/
-/* PCI Subsystem ID *********************************************************/
-/****************************************************************************/
-
-#define NGENE_ID(_subvend, _subdev, _driverdata) { \
-	.vendor = NGENE_VID, .device = NGENE_PID, \
-	.subvendor = _subvend, .subdevice = _subdev, \
-	.driver_data = (unsigned long) &_driverdata }
-
-/****************************************************************************/
-
-static const struct pci_device_id ngene_id_tbl[] __devinitdata = {
-	NGENE_ID(0x18c3, 0xabc3, ngene_info_cineS2),
-	NGENE_ID(0x18c3, 0xabc4, ngene_info_cineS2),
-	NGENE_ID(0x18c3, 0xdb01, ngene_info_satixS2),
-	NGENE_ID(0x18c3, 0xdb02, ngene_info_satixS2v2),
-	NGENE_ID(0x18c3, 0xdd00, ngene_info_cineS2v5),
-	NGENE_ID(0x18c3, 0xdd10, ngene_info_duoFlex),
-	NGENE_ID(0x18c3, 0xdd20, ngene_info_duoFlex),
-	NGENE_ID(0x1461, 0x062e, ngene_info_m780),
-	{0}
-};
-MODULE_DEVICE_TABLE(pci, ngene_id_tbl);
-
-/****************************************************************************/
-/* Init/Exit ****************************************************************/
-/****************************************************************************/
-
-static pci_ers_result_t ngene_error_detected(struct pci_dev *dev,
-					     enum pci_channel_state state)
-{
-	printk(KERN_ERR DEVICE_NAME ": PCI error\n");
-	if (state == pci_channel_io_perm_failure)
-		return PCI_ERS_RESULT_DISCONNECT;
-	if (state == pci_channel_io_frozen)
-		return PCI_ERS_RESULT_NEED_RESET;
-	return PCI_ERS_RESULT_CAN_RECOVER;
-}
-
-static pci_ers_result_t ngene_link_reset(struct pci_dev *dev)
-{
-	printk(KERN_INFO DEVICE_NAME ": link reset\n");
-	return 0;
-}
-
-static pci_ers_result_t ngene_slot_reset(struct pci_dev *dev)
-{
-	printk(KERN_INFO DEVICE_NAME ": slot reset\n");
-	return 0;
-}
-
-static void ngene_resume(struct pci_dev *dev)
-{
-	printk(KERN_INFO DEVICE_NAME ": resume\n");
-}
-
-static struct pci_error_handlers ngene_errors = {
-	.error_detected = ngene_error_detected,
-	.link_reset = ngene_link_reset,
-	.slot_reset = ngene_slot_reset,
-	.resume = ngene_resume,
-};
-
-static struct pci_driver ngene_pci_driver = {
-	.name        = "ngene",
-	.id_table    = ngene_id_tbl,
-	.probe       = ngene_probe,
-	.remove      = __devexit_p(ngene_remove),
-	.err_handler = &ngene_errors,
-	.shutdown    = ngene_shutdown,
-};
-
-static __init int module_init_ngene(void)
-{
-	printk(KERN_INFO
-	       "nGene PCIE bridge driver, Copyright (C) 2005-2007 Micronas\n");
-	return pci_register_driver(&ngene_pci_driver);
-}
-
-static __exit void module_exit_ngene(void)
-{
-	pci_unregister_driver(&ngene_pci_driver);
-}
-
-module_init(module_init_ngene);
-module_exit(module_exit_ngene);
-
-MODULE_DESCRIPTION("nGene");
-MODULE_AUTHOR("Micronas, Ralph Metzler, Manfred Voelkel");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/ngene/ngene-core.c b/drivers/media/dvb/ngene/ngene-core.c
deleted file mode 100644
index 3985738..0000000
--- a/drivers/media/dvb/ngene/ngene-core.c
+++ /dev/null
@@ -1,1713 +0,0 @@
-/*
- * ngene.c: nGene PCIe bridge driver
- *
- * Copyright (C) 2005-2007 Micronas
- *
- * Copyright (C) 2008-2009 Ralph Metzler <rjkm@metzlerbros.de>
- *                         Modifications for new nGene firmware,
- *                         support for EEPROM-copying,
- *                         support for new dual DVB-S2 card prototype
- *
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 only, as published by the Free Software Foundation.
- *
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/poll.h>
-#include <linux/io.h>
-#include <asm/div64.h>
-#include <linux/pci.h>
-#include <linux/timer.h>
-#include <linux/byteorder/generic.h>
-#include <linux/firmware.h>
-#include <linux/vmalloc.h>
-
-#include "ngene.h"
-
-static int one_adapter;
-module_param(one_adapter, int, 0444);
-MODULE_PARM_DESC(one_adapter, "Use only one adapter.");
-
-static int shutdown_workaround;
-module_param(shutdown_workaround, int, 0644);
-MODULE_PARM_DESC(shutdown_workaround, "Activate workaround for shutdown problem with some chipsets.");
-
-static int debug;
-module_param(debug, int, 0444);
-MODULE_PARM_DESC(debug, "Print debugging information.");
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-#define dprintk	if (debug) printk
-
-#define ngwriteb(dat, adr)         writeb((dat), (char *)(dev->iomem + (adr)))
-#define ngwritel(dat, adr)         writel((dat), (char *)(dev->iomem + (adr)))
-#define ngwriteb(dat, adr)         writeb((dat), (char *)(dev->iomem + (adr)))
-#define ngreadl(adr)               readl(dev->iomem + (adr))
-#define ngreadb(adr)               readb(dev->iomem + (adr))
-#define ngcpyto(adr, src, count)   memcpy_toio((char *) \
-				   (dev->iomem + (adr)), (src), (count))
-#define ngcpyfrom(dst, adr, count) memcpy_fromio((dst), (char *) \
-				   (dev->iomem + (adr)), (count))
-
-/****************************************************************************/
-/* nGene interrupt handler **************************************************/
-/****************************************************************************/
-
-static void event_tasklet(unsigned long data)
-{
-	struct ngene *dev = (struct ngene *)data;
-
-	while (dev->EventQueueReadIndex != dev->EventQueueWriteIndex) {
-		struct EVENT_BUFFER Event =
-			dev->EventQueue[dev->EventQueueReadIndex];
-		dev->EventQueueReadIndex =
-			(dev->EventQueueReadIndex + 1) & (EVENT_QUEUE_SIZE - 1);
-
-		if ((Event.UARTStatus & 0x01) && (dev->TxEventNotify))
-			dev->TxEventNotify(dev, Event.TimeStamp);
-		if ((Event.UARTStatus & 0x02) && (dev->RxEventNotify))
-			dev->RxEventNotify(dev, Event.TimeStamp,
-					   Event.RXCharacter);
-	}
-}
-
-static void demux_tasklet(unsigned long data)
-{
-	struct ngene_channel *chan = (struct ngene_channel *)data;
-	struct SBufferHeader *Cur = chan->nextBuffer;
-
-	spin_lock_irq(&chan->state_lock);
-
-	while (Cur->ngeneBuffer.SR.Flags & 0x80) {
-		if (chan->mode & NGENE_IO_TSOUT) {
-			u32 Flags = chan->DataFormatFlags;
-			if (Cur->ngeneBuffer.SR.Flags & 0x20)
-				Flags |= BEF_OVERFLOW;
-			if (chan->pBufferExchange) {
-				if (!chan->pBufferExchange(chan,
-							   Cur->Buffer1,
-							   chan->Capture1Length,
-							   Cur->ngeneBuffer.SR.
-							   Clock, Flags)) {
-					/*
-					   We didn't get data
-					   Clear in service flag to make sure we
-					   get called on next interrupt again.
-					   leave fill/empty (0x80) flag alone
-					   to avoid hardware running out of
-					   buffers during startup, we hold only
-					   in run state ( the source may be late
-					   delivering data )
-					*/
-
-					if (chan->HWState == HWSTATE_RUN) {
-						Cur->ngeneBuffer.SR.Flags &=
-							~0x40;
-						break;
-						/* Stop processing stream */
-					}
-				} else {
-					/* We got a valid buffer,
-					   so switch to run state */
-					chan->HWState = HWSTATE_RUN;
-				}
-			} else {
-				printk(KERN_ERR DEVICE_NAME ": OOPS\n");
-				if (chan->HWState == HWSTATE_RUN) {
-					Cur->ngeneBuffer.SR.Flags &= ~0x40;
-					break;	/* Stop processing stream */
-				}
-			}
-			if (chan->AudioDTOUpdated) {
-				printk(KERN_INFO DEVICE_NAME
-				       ": Update AudioDTO = %d\n",
-				       chan->AudioDTOValue);
-				Cur->ngeneBuffer.SR.DTOUpdate =
-					chan->AudioDTOValue;
-				chan->AudioDTOUpdated = 0;
-			}
-		} else {
-			if (chan->HWState == HWSTATE_RUN) {
-				u32 Flags = chan->DataFormatFlags;
-				IBufferExchange *exch1 = chan->pBufferExchange;
-				IBufferExchange *exch2 = chan->pBufferExchange2;
-				if (Cur->ngeneBuffer.SR.Flags & 0x01)
-					Flags |= BEF_EVEN_FIELD;
-				if (Cur->ngeneBuffer.SR.Flags & 0x20)
-					Flags |= BEF_OVERFLOW;
-				spin_unlock_irq(&chan->state_lock);
-				if (exch1)
-					exch1(chan, Cur->Buffer1,
-						chan->Capture1Length,
-						Cur->ngeneBuffer.SR.Clock,
-						Flags);
-				if (exch2)
-					exch2(chan, Cur->Buffer2,
-						chan->Capture2Length,
-						Cur->ngeneBuffer.SR.Clock,
-						Flags);
-				spin_lock_irq(&chan->state_lock);
-			} else if (chan->HWState != HWSTATE_STOP)
-				chan->HWState = HWSTATE_RUN;
-		}
-		Cur->ngeneBuffer.SR.Flags = 0x00;
-		Cur = Cur->Next;
-	}
-	chan->nextBuffer = Cur;
-
-	spin_unlock_irq(&chan->state_lock);
-}
-
-static irqreturn_t irq_handler(int irq, void *dev_id)
-{
-	struct ngene *dev = (struct ngene *)dev_id;
-	u32 icounts = 0;
-	irqreturn_t rc = IRQ_NONE;
-	u32 i = MAX_STREAM;
-	u8 *tmpCmdDoneByte;
-
-	if (dev->BootFirmware) {
-		icounts = ngreadl(NGENE_INT_COUNTS);
-		if (icounts != dev->icounts) {
-			ngwritel(0, FORCE_NMI);
-			dev->cmd_done = 1;
-			wake_up(&dev->cmd_wq);
-			dev->icounts = icounts;
-			rc = IRQ_HANDLED;
-		}
-		return rc;
-	}
-
-	ngwritel(0, FORCE_NMI);
-
-	spin_lock(&dev->cmd_lock);
-	tmpCmdDoneByte = dev->CmdDoneByte;
-	if (tmpCmdDoneByte &&
-	    (*tmpCmdDoneByte ||
-	    (dev->ngenetohost[0] == 1 && dev->ngenetohost[1] != 0))) {
-		dev->CmdDoneByte = NULL;
-		dev->cmd_done = 1;
-		wake_up(&dev->cmd_wq);
-		rc = IRQ_HANDLED;
-	}
-	spin_unlock(&dev->cmd_lock);
-
-	if (dev->EventBuffer->EventStatus & 0x80) {
-		u8 nextWriteIndex =
-			(dev->EventQueueWriteIndex + 1) &
-			(EVENT_QUEUE_SIZE - 1);
-		if (nextWriteIndex != dev->EventQueueReadIndex) {
-			dev->EventQueue[dev->EventQueueWriteIndex] =
-				*(dev->EventBuffer);
-			dev->EventQueueWriteIndex = nextWriteIndex;
-		} else {
-			printk(KERN_ERR DEVICE_NAME ": event overflow\n");
-			dev->EventQueueOverflowCount += 1;
-			dev->EventQueueOverflowFlag = 1;
-		}
-		dev->EventBuffer->EventStatus &= ~0x80;
-		tasklet_schedule(&dev->event_tasklet);
-		rc = IRQ_HANDLED;
-	}
-
-	while (i > 0) {
-		i--;
-		spin_lock(&dev->channel[i].state_lock);
-		/* if (dev->channel[i].State>=KSSTATE_RUN) { */
-		if (dev->channel[i].nextBuffer) {
-			if ((dev->channel[i].nextBuffer->
-			     ngeneBuffer.SR.Flags & 0xC0) == 0x80) {
-				dev->channel[i].nextBuffer->
-					ngeneBuffer.SR.Flags |= 0x40;
-				tasklet_schedule(
-					&dev->channel[i].demux_tasklet);
-				rc = IRQ_HANDLED;
-			}
-		}
-		spin_unlock(&dev->channel[i].state_lock);
-	}
-
-	/* Request might have been processed by a previous call. */
-	return IRQ_HANDLED;
-}
-
-/****************************************************************************/
-/* nGene command interface **************************************************/
-/****************************************************************************/
-
-static void dump_command_io(struct ngene *dev)
-{
-	u8 buf[8], *b;
-
-	ngcpyfrom(buf, HOST_TO_NGENE, 8);
-	printk(KERN_ERR "host_to_ngene (%04x): %02x %02x %02x %02x %02x %02x %02x %02x\n",
-		HOST_TO_NGENE, buf[0], buf[1], buf[2], buf[3],
-		buf[4], buf[5], buf[6], buf[7]);
-
-	ngcpyfrom(buf, NGENE_TO_HOST, 8);
-	printk(KERN_ERR "ngene_to_host (%04x): %02x %02x %02x %02x %02x %02x %02x %02x\n",
-		NGENE_TO_HOST, buf[0], buf[1], buf[2], buf[3],
-		buf[4], buf[5], buf[6], buf[7]);
-
-	b = dev->hosttongene;
-	printk(KERN_ERR "dev->hosttongene (%p): %02x %02x %02x %02x %02x %02x %02x %02x\n",
-		b, b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]);
-
-	b = dev->ngenetohost;
-	printk(KERN_ERR "dev->ngenetohost (%p): %02x %02x %02x %02x %02x %02x %02x %02x\n",
-		b, b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]);
-}
-
-static int ngene_command_mutex(struct ngene *dev, struct ngene_command *com)
-{
-	int ret;
-	u8 *tmpCmdDoneByte;
-
-	dev->cmd_done = 0;
-
-	if (com->cmd.hdr.Opcode == CMD_FWLOAD_PREPARE) {
-		dev->BootFirmware = 1;
-		dev->icounts = ngreadl(NGENE_INT_COUNTS);
-		ngwritel(0, NGENE_COMMAND);
-		ngwritel(0, NGENE_COMMAND_HI);
-		ngwritel(0, NGENE_STATUS);
-		ngwritel(0, NGENE_STATUS_HI);
-		ngwritel(0, NGENE_EVENT);
-		ngwritel(0, NGENE_EVENT_HI);
-	} else if (com->cmd.hdr.Opcode == CMD_FWLOAD_FINISH) {
-		u64 fwio = dev->PAFWInterfaceBuffer;
-
-		ngwritel(fwio & 0xffffffff, NGENE_COMMAND);
-		ngwritel(fwio >> 32, NGENE_COMMAND_HI);
-		ngwritel((fwio + 256) & 0xffffffff, NGENE_STATUS);
-		ngwritel((fwio + 256) >> 32, NGENE_STATUS_HI);
-		ngwritel((fwio + 512) & 0xffffffff, NGENE_EVENT);
-		ngwritel((fwio + 512) >> 32, NGENE_EVENT_HI);
-	}
-
-	memcpy(dev->FWInterfaceBuffer, com->cmd.raw8, com->in_len + 2);
-
-	if (dev->BootFirmware)
-		ngcpyto(HOST_TO_NGENE, com->cmd.raw8, com->in_len + 2);
-
-	spin_lock_irq(&dev->cmd_lock);
-	tmpCmdDoneByte = dev->ngenetohost + com->out_len;
-	if (!com->out_len)
-		tmpCmdDoneByte++;
-	*tmpCmdDoneByte = 0;
-	dev->ngenetohost[0] = 0;
-	dev->ngenetohost[1] = 0;
-	dev->CmdDoneByte = tmpCmdDoneByte;
-	spin_unlock_irq(&dev->cmd_lock);
-
-	/* Notify 8051. */
-	ngwritel(1, FORCE_INT);
-
-	ret = wait_event_timeout(dev->cmd_wq, dev->cmd_done == 1, 2 * HZ);
-	if (!ret) {
-		/*ngwritel(0, FORCE_NMI);*/
-
-		printk(KERN_ERR DEVICE_NAME
-		       ": Command timeout cmd=%02x prev=%02x\n",
-		       com->cmd.hdr.Opcode, dev->prev_cmd);
-		dump_command_io(dev);
-		return -1;
-	}
-	if (com->cmd.hdr.Opcode == CMD_FWLOAD_FINISH)
-		dev->BootFirmware = 0;
-
-	dev->prev_cmd = com->cmd.hdr.Opcode;
-
-	if (!com->out_len)
-		return 0;
-
-	memcpy(com->cmd.raw8, dev->ngenetohost, com->out_len);
-
-	return 0;
-}
-
-int ngene_command(struct ngene *dev, struct ngene_command *com)
-{
-	int result;
-
-	down(&dev->cmd_mutex);
-	result = ngene_command_mutex(dev, com);
-	up(&dev->cmd_mutex);
-	return result;
-}
-
-
-static int ngene_command_load_firmware(struct ngene *dev,
-				       u8 *ngene_fw, u32 size)
-{
-#define FIRSTCHUNK (1024)
-	u32 cleft;
-	struct ngene_command com;
-
-	com.cmd.hdr.Opcode = CMD_FWLOAD_PREPARE;
-	com.cmd.hdr.Length = 0;
-	com.in_len = 0;
-	com.out_len = 0;
-
-	ngene_command(dev, &com);
-
-	cleft = (size + 3) & ~3;
-	if (cleft > FIRSTCHUNK) {
-		ngcpyto(PROGRAM_SRAM + FIRSTCHUNK, ngene_fw + FIRSTCHUNK,
-			cleft - FIRSTCHUNK);
-		cleft = FIRSTCHUNK;
-	}
-	ngcpyto(DATA_FIFO_AREA, ngene_fw, cleft);
-
-	memset(&com, 0, sizeof(struct ngene_command));
-	com.cmd.hdr.Opcode = CMD_FWLOAD_FINISH;
-	com.cmd.hdr.Length = 4;
-	com.cmd.FWLoadFinish.Address = DATA_FIFO_AREA;
-	com.cmd.FWLoadFinish.Length = (unsigned short)cleft;
-	com.in_len = 4;
-	com.out_len = 0;
-
-	return ngene_command(dev, &com);
-}
-
-
-static int ngene_command_config_buf(struct ngene *dev, u8 config)
-{
-	struct ngene_command com;
-
-	com.cmd.hdr.Opcode = CMD_CONFIGURE_BUFFER;
-	com.cmd.hdr.Length = 1;
-	com.cmd.ConfigureBuffers.config = config;
-	com.in_len = 1;
-	com.out_len = 0;
-
-	if (ngene_command(dev, &com) < 0)
-		return -EIO;
-	return 0;
-}
-
-static int ngene_command_config_free_buf(struct ngene *dev, u8 *config)
-{
-	struct ngene_command com;
-
-	com.cmd.hdr.Opcode = CMD_CONFIGURE_FREE_BUFFER;
-	com.cmd.hdr.Length = 6;
-	memcpy(&com.cmd.ConfigureBuffers.config, config, 6);
-	com.in_len = 6;
-	com.out_len = 0;
-
-	if (ngene_command(dev, &com) < 0)
-		return -EIO;
-
-	return 0;
-}
-
-int ngene_command_gpio_set(struct ngene *dev, u8 select, u8 level)
-{
-	struct ngene_command com;
-
-	com.cmd.hdr.Opcode = CMD_SET_GPIO_PIN;
-	com.cmd.hdr.Length = 1;
-	com.cmd.SetGpioPin.select = select | (level << 7);
-	com.in_len = 1;
-	com.out_len = 0;
-
-	return ngene_command(dev, &com);
-}
-
-
-/*
- 02000640 is sample on rising edge.
- 02000740 is sample on falling edge.
- 02000040 is ignore "valid" signal
-
- 0: FD_CTL1 Bit 7,6 must be 0,1
-    7   disable(fw controlled)
-    6   0-AUX,1-TS
-    5   0-par,1-ser
-    4   0-lsb/1-msb
-    3,2 reserved
-    1,0 0-no sync, 1-use ext. start, 2-use 0x47, 3-both
- 1: FD_CTL2 has 3-valid must be hi, 2-use valid, 1-edge
- 2: FD_STA is read-only. 0-sync
- 3: FD_INSYNC is number of 47s to trigger "in sync".
- 4: FD_OUTSYNC is number of 47s to trigger "out of sync".
- 5: FD_MAXBYTE1 is low-order of bytes per packet.
- 6: FD_MAXBYTE2 is high-order of bytes per packet.
- 7: Top byte is unused.
-*/
-
-/****************************************************************************/
-
-static u8 TSFeatureDecoderSetup[8 * 5] = {
-	0x42, 0x00, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00,
-	0x40, 0x06, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00,	/* DRXH */
-	0x71, 0x07, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00,	/* DRXHser */
-	0x72, 0x00, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00,	/* S2ser */
-	0x40, 0x07, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00, /* LGDT3303 */
-};
-
-/* Set NGENE I2S Config to 16 bit packed */
-static u8 I2SConfiguration[] = {
-	0x00, 0x10, 0x00, 0x00,
-	0x80, 0x10, 0x00, 0x00,
-};
-
-static u8 SPDIFConfiguration[10] = {
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-/* Set NGENE I2S Config to transport stream compatible mode */
-
-static u8 TS_I2SConfiguration[4] = { 0x3E, 0x18, 0x00, 0x00 };
-
-static u8 TS_I2SOutConfiguration[4] = { 0x80, 0x04, 0x00, 0x00 };
-
-static u8 ITUDecoderSetup[4][16] = {
-	{0x1c, 0x13, 0x01, 0x68, 0x3d, 0x90, 0x14, 0x20,  /* SDTV */
-	 0x00, 0x00, 0x01, 0xb0, 0x9c, 0x00, 0x00, 0x00},
-	{0x9c, 0x03, 0x23, 0xC0, 0x60, 0x0E, 0x13, 0x00,
-	 0x00, 0x00, 0x00, 0x01, 0xB0, 0x00, 0x00, 0x00},
-	{0x9f, 0x00, 0x23, 0xC0, 0x60, 0x0F, 0x13, 0x00,  /* HDTV 1080i50 */
-	 0x00, 0x00, 0x00, 0x01, 0xB0, 0x00, 0x00, 0x00},
-	{0x9c, 0x01, 0x23, 0xC0, 0x60, 0x0E, 0x13, 0x00,  /* HDTV 1080i60 */
-	 0x00, 0x00, 0x00, 0x01, 0xB0, 0x00, 0x00, 0x00},
-};
-
-/*
- * 50 48 60 gleich
- * 27p50 9f 00 22 80 42 69 18 ...
- * 27p60 93 00 22 80 82 69 1c ...
- */
-
-/* Maxbyte to 1144 (for raw data) */
-static u8 ITUFeatureDecoderSetup[8] = {
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x04, 0x00
-};
-
-void FillTSBuffer(void *Buffer, int Length, u32 Flags)
-{
-	u32 *ptr = Buffer;
-
-	memset(Buffer, TS_FILLER, Length);
-	while (Length > 0) {
-		if (Flags & DF_SWAP32)
-			*ptr = 0x471FFF10;
-		else
-			*ptr = 0x10FF1F47;
-		ptr += (188 / 4);
-		Length -= 188;
-	}
-}
-
-
-static void flush_buffers(struct ngene_channel *chan)
-{
-	u8 val;
-
-	do {
-		msleep(1);
-		spin_lock_irq(&chan->state_lock);
-		val = chan->nextBuffer->ngeneBuffer.SR.Flags & 0x80;
-		spin_unlock_irq(&chan->state_lock);
-	} while (val);
-}
-
-static void clear_buffers(struct ngene_channel *chan)
-{
-	struct SBufferHeader *Cur = chan->nextBuffer;
-
-	do {
-		memset(&Cur->ngeneBuffer.SR, 0, sizeof(Cur->ngeneBuffer.SR));
-		if (chan->mode & NGENE_IO_TSOUT)
-			FillTSBuffer(Cur->Buffer1,
-				     chan->Capture1Length,
-				     chan->DataFormatFlags);
-		Cur = Cur->Next;
-	} while (Cur != chan->nextBuffer);
-
-	if (chan->mode & NGENE_IO_TSOUT) {
-		chan->nextBuffer->ngeneBuffer.SR.DTOUpdate =
-			chan->AudioDTOValue;
-		chan->AudioDTOUpdated = 0;
-
-		Cur = chan->TSIdleBuffer.Head;
-
-		do {
-			memset(&Cur->ngeneBuffer.SR, 0,
-			       sizeof(Cur->ngeneBuffer.SR));
-			FillTSBuffer(Cur->Buffer1,
-				     chan->Capture1Length,
-				     chan->DataFormatFlags);
-			Cur = Cur->Next;
-		} while (Cur != chan->TSIdleBuffer.Head);
-	}
-}
-
-static int ngene_command_stream_control(struct ngene *dev, u8 stream,
-					u8 control, u8 mode, u8 flags)
-{
-	struct ngene_channel *chan = &dev->channel[stream];
-	struct ngene_command com;
-	u16 BsUVI = ((stream & 1) ? 0x9400 : 0x9300);
-	u16 BsSDI = ((stream & 1) ? 0x9600 : 0x9500);
-	u16 BsSPI = ((stream & 1) ? 0x9800 : 0x9700);
-	u16 BsSDO = 0x9B00;
-
-	down(&dev->stream_mutex);
-	memset(&com, 0, sizeof(com));
-	com.cmd.hdr.Opcode = CMD_CONTROL;
-	com.cmd.hdr.Length = sizeof(struct FW_STREAM_CONTROL) - 2;
-	com.cmd.StreamControl.Stream = stream | (control ? 8 : 0);
-	if (chan->mode & NGENE_IO_TSOUT)
-		com.cmd.StreamControl.Stream |= 0x07;
-	com.cmd.StreamControl.Control = control |
-		(flags & SFLAG_ORDER_LUMA_CHROMA);
-	com.cmd.StreamControl.Mode = mode;
-	com.in_len = sizeof(struct FW_STREAM_CONTROL);
-	com.out_len = 0;
-
-	dprintk(KERN_INFO DEVICE_NAME
-		": Stream=%02x, Control=%02x, Mode=%02x\n",
-		com.cmd.StreamControl.Stream, com.cmd.StreamControl.Control,
-		com.cmd.StreamControl.Mode);
-
-	chan->Mode = mode;
-
-	if (!(control & 0x80)) {
-		spin_lock_irq(&chan->state_lock);
-		if (chan->State == KSSTATE_RUN) {
-			chan->State = KSSTATE_ACQUIRE;
-			chan->HWState = HWSTATE_STOP;
-			spin_unlock_irq(&chan->state_lock);
-			if (ngene_command(dev, &com) < 0) {
-				up(&dev->stream_mutex);
-				return -1;
-			}
-			/* clear_buffers(chan); */
-			flush_buffers(chan);
-			up(&dev->stream_mutex);
-			return 0;
-		}
-		spin_unlock_irq(&chan->state_lock);
-		up(&dev->stream_mutex);
-		return 0;
-	}
-
-	if (mode & SMODE_AUDIO_CAPTURE) {
-		com.cmd.StreamControl.CaptureBlockCount =
-			chan->Capture1Length / AUDIO_BLOCK_SIZE;
-		com.cmd.StreamControl.Buffer_Address = chan->RingBuffer.PAHead;
-	} else if (mode & SMODE_TRANSPORT_STREAM) {
-		com.cmd.StreamControl.CaptureBlockCount =
-			chan->Capture1Length / TS_BLOCK_SIZE;
-		com.cmd.StreamControl.MaxLinesPerField =
-			chan->Capture1Length / TS_BLOCK_SIZE;
-		com.cmd.StreamControl.Buffer_Address =
-			chan->TSRingBuffer.PAHead;
-		if (chan->mode & NGENE_IO_TSOUT) {
-			com.cmd.StreamControl.BytesPerVBILine =
-				chan->Capture1Length / TS_BLOCK_SIZE;
-			com.cmd.StreamControl.Stream |= 0x07;
-		}
-	} else {
-		com.cmd.StreamControl.BytesPerVideoLine = chan->nBytesPerLine;
-		com.cmd.StreamControl.MaxLinesPerField = chan->nLines;
-		com.cmd.StreamControl.MinLinesPerField = 100;
-		com.cmd.StreamControl.Buffer_Address = chan->RingBuffer.PAHead;
-
-		if (mode & SMODE_VBI_CAPTURE) {
-			com.cmd.StreamControl.MaxVBILinesPerField =
-				chan->nVBILines;
-			com.cmd.StreamControl.MinVBILinesPerField = 0;
-			com.cmd.StreamControl.BytesPerVBILine =
-				chan->nBytesPerVBILine;
-		}
-		if (flags & SFLAG_COLORBAR)
-			com.cmd.StreamControl.Stream |= 0x04;
-	}
-
-	spin_lock_irq(&chan->state_lock);
-	if (mode & SMODE_AUDIO_CAPTURE) {
-		chan->nextBuffer = chan->RingBuffer.Head;
-		if (mode & SMODE_AUDIO_SPDIF) {
-			com.cmd.StreamControl.SetupDataLen =
-				sizeof(SPDIFConfiguration);
-			com.cmd.StreamControl.SetupDataAddr = BsSPI;
-			memcpy(com.cmd.StreamControl.SetupData,
-			       SPDIFConfiguration, sizeof(SPDIFConfiguration));
-		} else {
-			com.cmd.StreamControl.SetupDataLen = 4;
-			com.cmd.StreamControl.SetupDataAddr = BsSDI;
-			memcpy(com.cmd.StreamControl.SetupData,
-			       I2SConfiguration +
-			       4 * dev->card_info->i2s[stream], 4);
-		}
-	} else if (mode & SMODE_TRANSPORT_STREAM) {
-		chan->nextBuffer = chan->TSRingBuffer.Head;
-		if (stream >= STREAM_AUDIOIN1) {
-			if (chan->mode & NGENE_IO_TSOUT) {
-				com.cmd.StreamControl.SetupDataLen =
-					sizeof(TS_I2SOutConfiguration);
-				com.cmd.StreamControl.SetupDataAddr = BsSDO;
-				memcpy(com.cmd.StreamControl.SetupData,
-				       TS_I2SOutConfiguration,
-				       sizeof(TS_I2SOutConfiguration));
-			} else {
-				com.cmd.StreamControl.SetupDataLen =
-					sizeof(TS_I2SConfiguration);
-				com.cmd.StreamControl.SetupDataAddr = BsSDI;
-				memcpy(com.cmd.StreamControl.SetupData,
-				       TS_I2SConfiguration,
-				       sizeof(TS_I2SConfiguration));
-			}
-		} else {
-			com.cmd.StreamControl.SetupDataLen = 8;
-			com.cmd.StreamControl.SetupDataAddr = BsUVI + 0x10;
-			memcpy(com.cmd.StreamControl.SetupData,
-			       TSFeatureDecoderSetup +
-			       8 * dev->card_info->tsf[stream], 8);
-		}
-	} else {
-		chan->nextBuffer = chan->RingBuffer.Head;
-		com.cmd.StreamControl.SetupDataLen =
-			16 + sizeof(ITUFeatureDecoderSetup);
-		com.cmd.StreamControl.SetupDataAddr = BsUVI;
-		memcpy(com.cmd.StreamControl.SetupData,
-		       ITUDecoderSetup[chan->itumode], 16);
-		memcpy(com.cmd.StreamControl.SetupData + 16,
-		       ITUFeatureDecoderSetup, sizeof(ITUFeatureDecoderSetup));
-	}
-	clear_buffers(chan);
-	chan->State = KSSTATE_RUN;
-	if (mode & SMODE_TRANSPORT_STREAM)
-		chan->HWState = HWSTATE_RUN;
-	else
-		chan->HWState = HWSTATE_STARTUP;
-	spin_unlock_irq(&chan->state_lock);
-
-	if (ngene_command(dev, &com) < 0) {
-		up(&dev->stream_mutex);
-		return -1;
-	}
-	up(&dev->stream_mutex);
-	return 0;
-}
-
-void set_transfer(struct ngene_channel *chan, int state)
-{
-	u8 control = 0, mode = 0, flags = 0;
-	struct ngene *dev = chan->dev;
-	int ret;
-
-	/*
-	printk(KERN_INFO DEVICE_NAME ": st %d\n", state);
-	msleep(100);
-	*/
-
-	if (state) {
-		if (chan->running) {
-			printk(KERN_INFO DEVICE_NAME ": already running\n");
-			return;
-		}
-	} else {
-		if (!chan->running) {
-			printk(KERN_INFO DEVICE_NAME ": already stopped\n");
-			return;
-		}
-	}
-
-	if (dev->card_info->switch_ctrl)
-		dev->card_info->switch_ctrl(chan, 1, state ^ 1);
-
-	if (state) {
-		spin_lock_irq(&chan->state_lock);
-
-		/* printk(KERN_INFO DEVICE_NAME ": lock=%08x\n",
-			  ngreadl(0x9310)); */
-		dvb_ringbuffer_flush(&dev->tsout_rbuf);
-		control = 0x80;
-		if (chan->mode & (NGENE_IO_TSIN | NGENE_IO_TSOUT)) {
-			chan->Capture1Length = 512 * 188;
-			mode = SMODE_TRANSPORT_STREAM;
-		}
-		if (chan->mode & NGENE_IO_TSOUT) {
-			chan->pBufferExchange = tsout_exchange;
-			/* 0x66666666 = 50MHz *2^33 /250MHz */
-			chan->AudioDTOValue = 0x80000000;
-			chan->AudioDTOUpdated = 1;
-		}
-		if (chan->mode & NGENE_IO_TSIN)
-			chan->pBufferExchange = tsin_exchange;
-		spin_unlock_irq(&chan->state_lock);
-	} else
-		;/* printk(KERN_INFO DEVICE_NAME ": lock=%08x\n",
-			   ngreadl(0x9310)); */
-
-	ret = ngene_command_stream_control(dev, chan->number,
-					   control, mode, flags);
-	if (!ret)
-		chan->running = state;
-	else
-		printk(KERN_ERR DEVICE_NAME ": set_transfer %d failed\n",
-		       state);
-	if (!state) {
-		spin_lock_irq(&chan->state_lock);
-		chan->pBufferExchange = NULL;
-		dvb_ringbuffer_flush(&dev->tsout_rbuf);
-		spin_unlock_irq(&chan->state_lock);
-	}
-}
-
-
-/****************************************************************************/
-/* nGene hardware init and release functions ********************************/
-/****************************************************************************/
-
-static void free_ringbuffer(struct ngene *dev, struct SRingBufferDescriptor *rb)
-{
-	struct SBufferHeader *Cur = rb->Head;
-	u32 j;
-
-	if (!Cur)
-		return;
-
-	for (j = 0; j < rb->NumBuffers; j++, Cur = Cur->Next) {
-		if (Cur->Buffer1)
-			pci_free_consistent(dev->pci_dev,
-					    rb->Buffer1Length,
-					    Cur->Buffer1,
-					    Cur->scList1->Address);
-
-		if (Cur->Buffer2)
-			pci_free_consistent(dev->pci_dev,
-					    rb->Buffer2Length,
-					    Cur->Buffer2,
-					    Cur->scList2->Address);
-	}
-
-	if (rb->SCListMem)
-		pci_free_consistent(dev->pci_dev, rb->SCListMemSize,
-				    rb->SCListMem, rb->PASCListMem);
-
-	pci_free_consistent(dev->pci_dev, rb->MemSize, rb->Head, rb->PAHead);
-}
-
-static void free_idlebuffer(struct ngene *dev,
-		     struct SRingBufferDescriptor *rb,
-		     struct SRingBufferDescriptor *tb)
-{
-	int j;
-	struct SBufferHeader *Cur = tb->Head;
-
-	if (!rb->Head)
-		return;
-	free_ringbuffer(dev, rb);
-	for (j = 0; j < tb->NumBuffers; j++, Cur = Cur->Next) {
-		Cur->Buffer2 = NULL;
-		Cur->scList2 = NULL;
-		Cur->ngeneBuffer.Address_of_first_entry_2 = 0;
-		Cur->ngeneBuffer.Number_of_entries_2 = 0;
-	}
-}
-
-static void free_common_buffers(struct ngene *dev)
-{
-	u32 i;
-	struct ngene_channel *chan;
-
-	for (i = STREAM_VIDEOIN1; i < MAX_STREAM; i++) {
-		chan = &dev->channel[i];
-		free_idlebuffer(dev, &chan->TSIdleBuffer, &chan->TSRingBuffer);
-		free_ringbuffer(dev, &chan->RingBuffer);
-		free_ringbuffer(dev, &chan->TSRingBuffer);
-	}
-
-	if (dev->OverflowBuffer)
-		pci_free_consistent(dev->pci_dev,
-				    OVERFLOW_BUFFER_SIZE,
-				    dev->OverflowBuffer, dev->PAOverflowBuffer);
-
-	if (dev->FWInterfaceBuffer)
-		pci_free_consistent(dev->pci_dev,
-				    4096,
-				    dev->FWInterfaceBuffer,
-				    dev->PAFWInterfaceBuffer);
-}
-
-/****************************************************************************/
-/* Ring buffer handling *****************************************************/
-/****************************************************************************/
-
-static int create_ring_buffer(struct pci_dev *pci_dev,
-		       struct SRingBufferDescriptor *descr, u32 NumBuffers)
-{
-	dma_addr_t tmp;
-	struct SBufferHeader *Head;
-	u32 i;
-	u32 MemSize = SIZEOF_SBufferHeader * NumBuffers;
-	u64 PARingBufferHead;
-	u64 PARingBufferCur;
-	u64 PARingBufferNext;
-	struct SBufferHeader *Cur, *Next;
-
-	descr->Head = NULL;
-	descr->MemSize = 0;
-	descr->PAHead = 0;
-	descr->NumBuffers = 0;
-
-	if (MemSize < 4096)
-		MemSize = 4096;
-
-	Head = pci_alloc_consistent(pci_dev, MemSize, &tmp);
-	PARingBufferHead = tmp;
-
-	if (!Head)
-		return -ENOMEM;
-
-	memset(Head, 0, MemSize);
-
-	PARingBufferCur = PARingBufferHead;
-	Cur = Head;
-
-	for (i = 0; i < NumBuffers - 1; i++) {
-		Next = (struct SBufferHeader *)
-			(((u8 *) Cur) + SIZEOF_SBufferHeader);
-		PARingBufferNext = PARingBufferCur + SIZEOF_SBufferHeader;
-		Cur->Next = Next;
-		Cur->ngeneBuffer.Next = PARingBufferNext;
-		Cur = Next;
-		PARingBufferCur = PARingBufferNext;
-	}
-	/* Last Buffer points back to first one */
-	Cur->Next = Head;
-	Cur->ngeneBuffer.Next = PARingBufferHead;
-
-	descr->Head       = Head;
-	descr->MemSize    = MemSize;
-	descr->PAHead     = PARingBufferHead;
-	descr->NumBuffers = NumBuffers;
-
-	return 0;
-}
-
-static int AllocateRingBuffers(struct pci_dev *pci_dev,
-			       dma_addr_t of,
-			       struct SRingBufferDescriptor *pRingBuffer,
-			       u32 Buffer1Length, u32 Buffer2Length)
-{
-	dma_addr_t tmp;
-	u32 i, j;
-	int status = 0;
-	u32 SCListMemSize = pRingBuffer->NumBuffers
-		* ((Buffer2Length != 0) ? (NUM_SCATTER_GATHER_ENTRIES * 2) :
-		    NUM_SCATTER_GATHER_ENTRIES)
-		* sizeof(struct HW_SCATTER_GATHER_ELEMENT);
-
-	u64 PASCListMem;
-	struct HW_SCATTER_GATHER_ELEMENT *SCListEntry;
-	u64 PASCListEntry;
-	struct SBufferHeader *Cur;
-	void *SCListMem;
-
-	if (SCListMemSize < 4096)
-		SCListMemSize = 4096;
-
-	SCListMem = pci_alloc_consistent(pci_dev, SCListMemSize, &tmp);
-
-	PASCListMem = tmp;
-	if (SCListMem == NULL)
-		return -ENOMEM;
-
-	memset(SCListMem, 0, SCListMemSize);
-
-	pRingBuffer->SCListMem = SCListMem;
-	pRingBuffer->PASCListMem = PASCListMem;
-	pRingBuffer->SCListMemSize = SCListMemSize;
-	pRingBuffer->Buffer1Length = Buffer1Length;
-	pRingBuffer->Buffer2Length = Buffer2Length;
-
-	SCListEntry = SCListMem;
-	PASCListEntry = PASCListMem;
-	Cur = pRingBuffer->Head;
-
-	for (i = 0; i < pRingBuffer->NumBuffers; i += 1, Cur = Cur->Next) {
-		u64 PABuffer;
-
-		void *Buffer = pci_alloc_consistent(pci_dev, Buffer1Length,
-						    &tmp);
-		PABuffer = tmp;
-
-		if (Buffer == NULL)
-			return -ENOMEM;
-
-		Cur->Buffer1 = Buffer;
-
-		SCListEntry->Address = PABuffer;
-		SCListEntry->Length  = Buffer1Length;
-
-		Cur->scList1 = SCListEntry;
-		Cur->ngeneBuffer.Address_of_first_entry_1 = PASCListEntry;
-		Cur->ngeneBuffer.Number_of_entries_1 =
-			NUM_SCATTER_GATHER_ENTRIES;
-
-		SCListEntry += 1;
-		PASCListEntry += sizeof(struct HW_SCATTER_GATHER_ELEMENT);
-
-#if NUM_SCATTER_GATHER_ENTRIES > 1
-		for (j = 0; j < NUM_SCATTER_GATHER_ENTRIES - 1; j += 1) {
-			SCListEntry->Address = of;
-			SCListEntry->Length = OVERFLOW_BUFFER_SIZE;
-			SCListEntry += 1;
-			PASCListEntry +=
-				sizeof(struct HW_SCATTER_GATHER_ELEMENT);
-		}
-#endif
-
-		if (!Buffer2Length)
-			continue;
-
-		Buffer = pci_alloc_consistent(pci_dev, Buffer2Length, &tmp);
-		PABuffer = tmp;
-
-		if (Buffer == NULL)
-			return -ENOMEM;
-
-		Cur->Buffer2 = Buffer;
-
-		SCListEntry->Address = PABuffer;
-		SCListEntry->Length  = Buffer2Length;
-
-		Cur->scList2 = SCListEntry;
-		Cur->ngeneBuffer.Address_of_first_entry_2 = PASCListEntry;
-		Cur->ngeneBuffer.Number_of_entries_2 =
-			NUM_SCATTER_GATHER_ENTRIES;
-
-		SCListEntry   += 1;
-		PASCListEntry += sizeof(struct HW_SCATTER_GATHER_ELEMENT);
-
-#if NUM_SCATTER_GATHER_ENTRIES > 1
-		for (j = 0; j < NUM_SCATTER_GATHER_ENTRIES - 1; j++) {
-			SCListEntry->Address = of;
-			SCListEntry->Length = OVERFLOW_BUFFER_SIZE;
-			SCListEntry += 1;
-			PASCListEntry +=
-				sizeof(struct HW_SCATTER_GATHER_ELEMENT);
-		}
-#endif
-
-	}
-
-	return status;
-}
-
-static int FillTSIdleBuffer(struct SRingBufferDescriptor *pIdleBuffer,
-			    struct SRingBufferDescriptor *pRingBuffer)
-{
-	int status = 0;
-
-	/* Copy pointer to scatter gather list in TSRingbuffer
-	   structure for buffer 2
-	   Load number of buffer
-	*/
-	u32 n = pRingBuffer->NumBuffers;
-
-	/* Point to first buffer entry */
-	struct SBufferHeader *Cur = pRingBuffer->Head;
-	int i;
-	/* Loop thru all buffer and set Buffer 2 pointers to TSIdlebuffer */
-	for (i = 0; i < n; i++) {
-		Cur->Buffer2 = pIdleBuffer->Head->Buffer1;
-		Cur->scList2 = pIdleBuffer->Head->scList1;
-		Cur->ngeneBuffer.Address_of_first_entry_2 =
-			pIdleBuffer->Head->ngeneBuffer.
-			Address_of_first_entry_1;
-		Cur->ngeneBuffer.Number_of_entries_2 =
-			pIdleBuffer->Head->ngeneBuffer.Number_of_entries_1;
-		Cur = Cur->Next;
-	}
-	return status;
-}
-
-static u32 RingBufferSizes[MAX_STREAM] = {
-	RING_SIZE_VIDEO,
-	RING_SIZE_VIDEO,
-	RING_SIZE_AUDIO,
-	RING_SIZE_AUDIO,
-	RING_SIZE_AUDIO,
-};
-
-static u32 Buffer1Sizes[MAX_STREAM] = {
-	MAX_VIDEO_BUFFER_SIZE,
-	MAX_VIDEO_BUFFER_SIZE,
-	MAX_AUDIO_BUFFER_SIZE,
-	MAX_AUDIO_BUFFER_SIZE,
-	MAX_AUDIO_BUFFER_SIZE
-};
-
-static u32 Buffer2Sizes[MAX_STREAM] = {
-	MAX_VBI_BUFFER_SIZE,
-	MAX_VBI_BUFFER_SIZE,
-	0,
-	0,
-	0
-};
-
-
-static int AllocCommonBuffers(struct ngene *dev)
-{
-	int status = 0, i;
-
-	dev->FWInterfaceBuffer = pci_alloc_consistent(dev->pci_dev, 4096,
-						     &dev->PAFWInterfaceBuffer);
-	if (!dev->FWInterfaceBuffer)
-		return -ENOMEM;
-	dev->hosttongene = dev->FWInterfaceBuffer;
-	dev->ngenetohost = dev->FWInterfaceBuffer + 256;
-	dev->EventBuffer = dev->FWInterfaceBuffer + 512;
-
-	dev->OverflowBuffer = pci_alloc_consistent(dev->pci_dev,
-						   OVERFLOW_BUFFER_SIZE,
-						   &dev->PAOverflowBuffer);
-	if (!dev->OverflowBuffer)
-		return -ENOMEM;
-	memset(dev->OverflowBuffer, 0, OVERFLOW_BUFFER_SIZE);
-
-	for (i = STREAM_VIDEOIN1; i < MAX_STREAM; i++) {
-		int type = dev->card_info->io_type[i];
-
-		dev->channel[i].State = KSSTATE_STOP;
-
-		if (type & (NGENE_IO_TV | NGENE_IO_HDTV | NGENE_IO_AIN)) {
-			status = create_ring_buffer(dev->pci_dev,
-						    &dev->channel[i].RingBuffer,
-						    RingBufferSizes[i]);
-			if (status < 0)
-				break;
-
-			if (type & (NGENE_IO_TV | NGENE_IO_AIN)) {
-				status = AllocateRingBuffers(dev->pci_dev,
-							     dev->
-							     PAOverflowBuffer,
-							     &dev->channel[i].
-							     RingBuffer,
-							     Buffer1Sizes[i],
-							     Buffer2Sizes[i]);
-				if (status < 0)
-					break;
-			} else if (type & NGENE_IO_HDTV) {
-				status = AllocateRingBuffers(dev->pci_dev,
-							     dev->
-							     PAOverflowBuffer,
-							     &dev->channel[i].
-							     RingBuffer,
-							   MAX_HDTV_BUFFER_SIZE,
-							     0);
-				if (status < 0)
-					break;
-			}
-		}
-
-		if (type & (NGENE_IO_TSIN | NGENE_IO_TSOUT)) {
-
-			status = create_ring_buffer(dev->pci_dev,
-						    &dev->channel[i].
-						    TSRingBuffer, RING_SIZE_TS);
-			if (status < 0)
-				break;
-
-			status = AllocateRingBuffers(dev->pci_dev,
-						     dev->PAOverflowBuffer,
-						     &dev->channel[i].
-						     TSRingBuffer,
-						     MAX_TS_BUFFER_SIZE, 0);
-			if (status)
-				break;
-		}
-
-		if (type & NGENE_IO_TSOUT) {
-			status = create_ring_buffer(dev->pci_dev,
-						    &dev->channel[i].
-						    TSIdleBuffer, 1);
-			if (status < 0)
-				break;
-			status = AllocateRingBuffers(dev->pci_dev,
-						     dev->PAOverflowBuffer,
-						     &dev->channel[i].
-						     TSIdleBuffer,
-						     MAX_TS_BUFFER_SIZE, 0);
-			if (status)
-				break;
-			FillTSIdleBuffer(&dev->channel[i].TSIdleBuffer,
-					 &dev->channel[i].TSRingBuffer);
-		}
-	}
-	return status;
-}
-
-static void ngene_release_buffers(struct ngene *dev)
-{
-	if (dev->iomem)
-		iounmap(dev->iomem);
-	free_common_buffers(dev);
-	vfree(dev->tsout_buf);
-	vfree(dev->tsin_buf);
-	vfree(dev->ain_buf);
-	vfree(dev->vin_buf);
-	vfree(dev);
-}
-
-static int ngene_get_buffers(struct ngene *dev)
-{
-	if (AllocCommonBuffers(dev))
-		return -ENOMEM;
-	if (dev->card_info->io_type[4] & NGENE_IO_TSOUT) {
-		dev->tsout_buf = vmalloc(TSOUT_BUF_SIZE);
-		if (!dev->tsout_buf)
-			return -ENOMEM;
-		dvb_ringbuffer_init(&dev->tsout_rbuf,
-				    dev->tsout_buf, TSOUT_BUF_SIZE);
-	}
-	if (dev->card_info->io_type[2]&NGENE_IO_TSIN) {
-		dev->tsin_buf = vmalloc(TSIN_BUF_SIZE);
-		if (!dev->tsin_buf)
-			return -ENOMEM;
-		dvb_ringbuffer_init(&dev->tsin_rbuf,
-				    dev->tsin_buf, TSIN_BUF_SIZE);
-	}
-	if (dev->card_info->io_type[2] & NGENE_IO_AIN) {
-		dev->ain_buf = vmalloc(AIN_BUF_SIZE);
-		if (!dev->ain_buf)
-			return -ENOMEM;
-		dvb_ringbuffer_init(&dev->ain_rbuf, dev->ain_buf, AIN_BUF_SIZE);
-	}
-	if (dev->card_info->io_type[0] & NGENE_IO_HDTV) {
-		dev->vin_buf = vmalloc(VIN_BUF_SIZE);
-		if (!dev->vin_buf)
-			return -ENOMEM;
-		dvb_ringbuffer_init(&dev->vin_rbuf, dev->vin_buf, VIN_BUF_SIZE);
-	}
-	dev->iomem = ioremap(pci_resource_start(dev->pci_dev, 0),
-			     pci_resource_len(dev->pci_dev, 0));
-	if (!dev->iomem)
-		return -ENOMEM;
-
-	return 0;
-}
-
-static void ngene_init(struct ngene *dev)
-{
-	int i;
-
-	tasklet_init(&dev->event_tasklet, event_tasklet, (unsigned long)dev);
-
-	memset_io(dev->iomem + 0xc000, 0x00, 0x220);
-	memset_io(dev->iomem + 0xc400, 0x00, 0x100);
-
-	for (i = 0; i < MAX_STREAM; i++) {
-		dev->channel[i].dev = dev;
-		dev->channel[i].number = i;
-	}
-
-	dev->fw_interface_version = 0;
-
-	ngwritel(0, NGENE_INT_ENABLE);
-
-	dev->icounts = ngreadl(NGENE_INT_COUNTS);
-
-	dev->device_version = ngreadl(DEV_VER) & 0x0f;
-	printk(KERN_INFO DEVICE_NAME ": Device version %d\n",
-	       dev->device_version);
-}
-
-static int ngene_load_firm(struct ngene *dev)
-{
-	u32 size;
-	const struct firmware *fw = NULL;
-	u8 *ngene_fw;
-	char *fw_name;
-	int err, version;
-
-	version = dev->card_info->fw_version;
-
-	switch (version) {
-	default:
-	case 15:
-		version = 15;
-		size = 23466;
-		fw_name = "ngene_15.fw";
-		dev->cmd_timeout_workaround = true;
-		break;
-	case 16:
-		size = 23498;
-		fw_name = "ngene_16.fw";
-		dev->cmd_timeout_workaround = true;
-		break;
-	case 17:
-		size = 24446;
-		fw_name = "ngene_17.fw";
-		dev->cmd_timeout_workaround = true;
-		break;
-	case 18:
-		size = 0;
-		fw_name = "ngene_18.fw";
-		break;
-	}
-
-	if (request_firmware(&fw, fw_name, &dev->pci_dev->dev) < 0) {
-		printk(KERN_ERR DEVICE_NAME
-			": Could not load firmware file %s.\n", fw_name);
-		printk(KERN_INFO DEVICE_NAME
-			": Copy %s to your hotplug directory!\n", fw_name);
-		return -1;
-	}
-	if (size == 0)
-		size = fw->size;
-	if (size != fw->size) {
-		printk(KERN_ERR DEVICE_NAME
-			": Firmware %s has invalid size!", fw_name);
-		err = -1;
-	} else {
-		printk(KERN_INFO DEVICE_NAME
-			": Loading firmware file %s.\n", fw_name);
-		ngene_fw = (u8 *) fw->data;
-		err = ngene_command_load_firmware(dev, ngene_fw, size);
-	}
-
-	release_firmware(fw);
-
-	return err;
-}
-
-static void ngene_stop(struct ngene *dev)
-{
-	down(&dev->cmd_mutex);
-	i2c_del_adapter(&(dev->channel[0].i2c_adapter));
-	i2c_del_adapter(&(dev->channel[1].i2c_adapter));
-	ngwritel(0, NGENE_INT_ENABLE);
-	ngwritel(0, NGENE_COMMAND);
-	ngwritel(0, NGENE_COMMAND_HI);
-	ngwritel(0, NGENE_STATUS);
-	ngwritel(0, NGENE_STATUS_HI);
-	ngwritel(0, NGENE_EVENT);
-	ngwritel(0, NGENE_EVENT_HI);
-	free_irq(dev->pci_dev->irq, dev);
-#ifdef CONFIG_PCI_MSI
-	if (dev->msi_enabled)
-		pci_disable_msi(dev->pci_dev);
-#endif
-}
-
-static int ngene_buffer_config(struct ngene *dev)
-{
-	int stat;
-
-	if (dev->card_info->fw_version >= 17) {
-		u8 tsin12_config[6]   = { 0x60, 0x60, 0x00, 0x00, 0x00, 0x00 };
-		u8 tsin1234_config[6] = { 0x30, 0x30, 0x00, 0x30, 0x30, 0x00 };
-		u8 tsio1235_config[6] = { 0x30, 0x30, 0x00, 0x28, 0x00, 0x38 };
-		u8 *bconf = tsin12_config;
-
-		if (dev->card_info->io_type[2]&NGENE_IO_TSIN &&
-		    dev->card_info->io_type[3]&NGENE_IO_TSIN) {
-			bconf = tsin1234_config;
-			if (dev->card_info->io_type[4]&NGENE_IO_TSOUT &&
-			    dev->ci.en)
-				bconf = tsio1235_config;
-		}
-		stat = ngene_command_config_free_buf(dev, bconf);
-	} else {
-		int bconf = BUFFER_CONFIG_4422;
-
-		if (dev->card_info->io_type[3] == NGENE_IO_TSIN)
-			bconf = BUFFER_CONFIG_3333;
-		stat = ngene_command_config_buf(dev, bconf);
-	}
-	return stat;
-}
-
-
-static int ngene_start(struct ngene *dev)
-{
-	int stat;
-	int i;
-
-	pci_set_master(dev->pci_dev);
-	ngene_init(dev);
-
-	stat = request_irq(dev->pci_dev->irq, irq_handler,
-			   IRQF_SHARED, "nGene",
-			   (void *)dev);
-	if (stat < 0)
-		return stat;
-
-	init_waitqueue_head(&dev->cmd_wq);
-	init_waitqueue_head(&dev->tx_wq);
-	init_waitqueue_head(&dev->rx_wq);
-	sema_init(&dev->cmd_mutex, 1);
-	sema_init(&dev->stream_mutex, 1);
-	sema_init(&dev->pll_mutex, 1);
-	sema_init(&dev->i2c_switch_mutex, 1);
-	spin_lock_init(&dev->cmd_lock);
-	for (i = 0; i < MAX_STREAM; i++)
-		spin_lock_init(&dev->channel[i].state_lock);
-	ngwritel(1, TIMESTAMPS);
-
-	ngwritel(1, NGENE_INT_ENABLE);
-
-	stat = ngene_load_firm(dev);
-	if (stat < 0)
-		goto fail;
-
-#ifdef CONFIG_PCI_MSI
-	/* enable MSI if kernel and card support it */
-	if (pci_msi_enabled() && dev->card_info->msi_supported) {
-		unsigned long flags;
-
-		ngwritel(0, NGENE_INT_ENABLE);
-		free_irq(dev->pci_dev->irq, dev);
-		stat = pci_enable_msi(dev->pci_dev);
-		if (stat) {
-			printk(KERN_INFO DEVICE_NAME
-				": MSI not available\n");
-			flags = IRQF_SHARED;
-		} else {
-			flags = 0;
-			dev->msi_enabled = true;
-		}
-		stat = request_irq(dev->pci_dev->irq, irq_handler,
-					flags, "nGene", dev);
-		if (stat < 0)
-			goto fail2;
-		ngwritel(1, NGENE_INT_ENABLE);
-	}
-#endif
-
-	stat = ngene_i2c_init(dev, 0);
-	if (stat < 0)
-		goto fail;
-
-	stat = ngene_i2c_init(dev, 1);
-	if (stat < 0)
-		goto fail;
-
-	return 0;
-
-fail:
-	ngwritel(0, NGENE_INT_ENABLE);
-	free_irq(dev->pci_dev->irq, dev);
-#ifdef CONFIG_PCI_MSI
-fail2:
-	if (dev->msi_enabled)
-		pci_disable_msi(dev->pci_dev);
-#endif
-	return stat;
-}
-
-/****************************************************************************/
-/****************************************************************************/
-/****************************************************************************/
-
-static void release_channel(struct ngene_channel *chan)
-{
-	struct dvb_demux *dvbdemux = &chan->demux;
-	struct ngene *dev = chan->dev;
-
-	if (chan->running)
-		set_transfer(chan, 0);
-
-	tasklet_kill(&chan->demux_tasklet);
-
-	if (chan->ci_dev) {
-		dvb_unregister_device(chan->ci_dev);
-		chan->ci_dev = NULL;
-	}
-
-	if (chan->fe2)
-		dvb_unregister_frontend(chan->fe2);
-
-	if (chan->fe) {
-		dvb_unregister_frontend(chan->fe);
-		dvb_frontend_detach(chan->fe);
-		chan->fe = NULL;
-	}
-
-	if (chan->has_demux) {
-		dvb_net_release(&chan->dvbnet);
-		dvbdemux->dmx.close(&dvbdemux->dmx);
-		dvbdemux->dmx.remove_frontend(&dvbdemux->dmx,
-					      &chan->hw_frontend);
-		dvbdemux->dmx.remove_frontend(&dvbdemux->dmx,
-					      &chan->mem_frontend);
-		dvb_dmxdev_release(&chan->dmxdev);
-		dvb_dmx_release(&chan->demux);
-		chan->has_demux = false;
-	}
-
-	if (chan->has_adapter) {
-		dvb_unregister_adapter(&dev->adapter[chan->number]);
-		chan->has_adapter = false;
-	}
-}
-
-static int init_channel(struct ngene_channel *chan)
-{
-	int ret = 0, nr = chan->number;
-	struct dvb_adapter *adapter = NULL;
-	struct dvb_demux *dvbdemux = &chan->demux;
-	struct ngene *dev = chan->dev;
-	struct ngene_info *ni = dev->card_info;
-	int io = ni->io_type[nr];
-
-	tasklet_init(&chan->demux_tasklet, demux_tasklet, (unsigned long)chan);
-	chan->users = 0;
-	chan->type = io;
-	chan->mode = chan->type;	/* for now only one mode */
-
-	if (io & NGENE_IO_TSIN) {
-		chan->fe = NULL;
-		if (ni->demod_attach[nr]) {
-			ret = ni->demod_attach[nr](chan);
-			if (ret < 0)
-				goto err;
-		}
-		if (chan->fe && ni->tuner_attach[nr]) {
-			ret = ni->tuner_attach[nr](chan);
-			if (ret < 0)
-				goto err;
-		}
-	}
-
-	if (!dev->ci.en && (io & NGENE_IO_TSOUT))
-		return 0;
-
-	if (io & (NGENE_IO_TSIN | NGENE_IO_TSOUT)) {
-		if (nr >= STREAM_AUDIOIN1)
-			chan->DataFormatFlags = DF_SWAP32;
-
-		if (nr == 0 || !one_adapter || dev->first_adapter == NULL) {
-			adapter = &dev->adapter[nr];
-			ret = dvb_register_adapter(adapter, "nGene",
-						   THIS_MODULE,
-						   &chan->dev->pci_dev->dev,
-						   adapter_nr);
-			if (ret < 0)
-				goto err;
-			if (dev->first_adapter == NULL)
-				dev->first_adapter = adapter;
-			chan->has_adapter = true;
-		} else
-			adapter = dev->first_adapter;
-	}
-
-	if (dev->ci.en && (io & NGENE_IO_TSOUT)) {
-		dvb_ca_en50221_init(adapter, dev->ci.en, 0, 1);
-		set_transfer(chan, 1);
-		chan->dev->channel[2].DataFormatFlags = DF_SWAP32;
-		set_transfer(&chan->dev->channel[2], 1);
-		dvb_register_device(adapter, &chan->ci_dev,
-				    &ngene_dvbdev_ci, (void *) chan,
-				    DVB_DEVICE_SEC);
-		if (!chan->ci_dev)
-			goto err;
-	}
-
-	if (chan->fe) {
-		if (dvb_register_frontend(adapter, chan->fe) < 0)
-			goto err;
-		chan->has_demux = true;
-	}
-	if (chan->fe2) {
-		if (dvb_register_frontend(adapter, chan->fe2) < 0)
-			goto err;
-		chan->fe2->tuner_priv = chan->fe->tuner_priv;
-		memcpy(&chan->fe2->ops.tuner_ops,
-		       &chan->fe->ops.tuner_ops,
-		       sizeof(struct dvb_tuner_ops));
-	}
-
-	if (chan->has_demux) {
-		ret = my_dvb_dmx_ts_card_init(dvbdemux, "SW demux",
-					      ngene_start_feed,
-					      ngene_stop_feed, chan);
-		ret = my_dvb_dmxdev_ts_card_init(&chan->dmxdev, &chan->demux,
-						 &chan->hw_frontend,
-						 &chan->mem_frontend, adapter);
-		ret = dvb_net_init(adapter, &chan->dvbnet, &chan->demux.dmx);
-	}
-
-	return ret;
-
-err:
-	if (chan->fe) {
-		dvb_frontend_detach(chan->fe);
-		chan->fe = NULL;
-	}
-	release_channel(chan);
-	return 0;
-}
-
-static int init_channels(struct ngene *dev)
-{
-	int i, j;
-
-	for (i = 0; i < MAX_STREAM; i++) {
-		dev->channel[i].number = i;
-		if (init_channel(&dev->channel[i]) < 0) {
-			for (j = i - 1; j >= 0; j--)
-				release_channel(&dev->channel[j]);
-			return -1;
-		}
-	}
-	return 0;
-}
-
-static struct cxd2099_cfg cxd_cfg = {
-	.bitrate = 62000,
-	.adr = 0x40,
-	.polarity = 0,
-	.clock_mode = 0,
-};
-
-static void cxd_attach(struct ngene *dev)
-{
-	struct ngene_ci *ci = &dev->ci;
-
-	ci->en = cxd2099_attach(&cxd_cfg, dev, &dev->channel[0].i2c_adapter);
-	ci->dev = dev;
-	return;
-}
-
-static void cxd_detach(struct ngene *dev)
-{
-	struct ngene_ci *ci = &dev->ci;
-
-	dvb_ca_en50221_release(ci->en);
-	kfree(ci->en);
-	ci->en = 0;
-}
-
-/***********************************/
-/* workaround for shutdown failure */
-/***********************************/
-
-static void ngene_unlink(struct ngene *dev)
-{
-	struct ngene_command com;
-
-	com.cmd.hdr.Opcode = CMD_MEM_WRITE;
-	com.cmd.hdr.Length = 3;
-	com.cmd.MemoryWrite.address = 0x910c;
-	com.cmd.MemoryWrite.data = 0xff;
-	com.in_len = 3;
-	com.out_len = 1;
-
-	down(&dev->cmd_mutex);
-	ngwritel(0, NGENE_INT_ENABLE);
-	ngene_command_mutex(dev, &com);
-	up(&dev->cmd_mutex);
-}
-
-void ngene_shutdown(struct pci_dev *pdev)
-{
-	struct ngene *dev = (struct ngene *)pci_get_drvdata(pdev);
-
-	if (!dev || !shutdown_workaround)
-		return;
-
-	printk(KERN_INFO DEVICE_NAME ": shutdown workaround...\n");
-	ngene_unlink(dev);
-	pci_disable_device(pdev);
-}
-
-/****************************************************************************/
-/* device probe/remove calls ************************************************/
-/****************************************************************************/
-
-void __devexit ngene_remove(struct pci_dev *pdev)
-{
-	struct ngene *dev = pci_get_drvdata(pdev);
-	int i;
-
-	tasklet_kill(&dev->event_tasklet);
-	for (i = MAX_STREAM - 1; i >= 0; i--)
-		release_channel(&dev->channel[i]);
-	if (dev->ci.en)
-		cxd_detach(dev);
-	ngene_stop(dev);
-	ngene_release_buffers(dev);
-	pci_set_drvdata(pdev, NULL);
-	pci_disable_device(pdev);
-}
-
-int __devinit ngene_probe(struct pci_dev *pci_dev,
-			  const struct pci_device_id *id)
-{
-	struct ngene *dev;
-	int stat = 0;
-
-	if (pci_enable_device(pci_dev) < 0)
-		return -ENODEV;
-
-	dev = vzalloc(sizeof(struct ngene));
-	if (dev == NULL) {
-		stat = -ENOMEM;
-		goto fail0;
-	}
-
-	dev->pci_dev = pci_dev;
-	dev->card_info = (struct ngene_info *)id->driver_data;
-	printk(KERN_INFO DEVICE_NAME ": Found %s\n", dev->card_info->name);
-
-	pci_set_drvdata(pci_dev, dev);
-
-	/* Alloc buffers and start nGene */
-	stat = ngene_get_buffers(dev);
-	if (stat < 0)
-		goto fail1;
-	stat = ngene_start(dev);
-	if (stat < 0)
-		goto fail1;
-
-	cxd_attach(dev);
-
-	stat = ngene_buffer_config(dev);
-	if (stat < 0)
-		goto fail1;
-
-
-	dev->i2c_current_bus = -1;
-
-	/* Register DVB adapters and devices for both channels */
-	if (init_channels(dev) < 0)
-		goto fail2;
-
-	return 0;
-
-fail2:
-	ngene_stop(dev);
-fail1:
-	ngene_release_buffers(dev);
-fail0:
-	pci_disable_device(pci_dev);
-	pci_set_drvdata(pci_dev, NULL);
-	return stat;
-}
diff --git a/drivers/media/dvb/ngene/ngene-dvb.c b/drivers/media/dvb/ngene/ngene-dvb.c
deleted file mode 100644
index fcb16a6..0000000
--- a/drivers/media/dvb/ngene/ngene-dvb.c
+++ /dev/null
@@ -1,261 +0,0 @@
-/*
- * ngene-dvb.c: nGene PCIe bridge driver - DVB functions
- *
- * Copyright (C) 2005-2007 Micronas
- *
- * Copyright (C) 2008-2009 Ralph Metzler <rjkm@metzlerbros.de>
- *                         Modifications for new nGene firmware,
- *                         support for EEPROM-copying,
- *                         support for new dual DVB-S2 card prototype
- *
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 only, as published by the Free Software Foundation.
- *
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/poll.h>
-#include <linux/io.h>
-#include <asm/div64.h>
-#include <linux/pci.h>
-#include <linux/timer.h>
-#include <linux/byteorder/generic.h>
-#include <linux/firmware.h>
-#include <linux/vmalloc.h>
-
-#include "ngene.h"
-
-
-/****************************************************************************/
-/* COMMAND API interface ****************************************************/
-/****************************************************************************/
-
-static ssize_t ts_write(struct file *file, const char *buf,
-			size_t count, loff_t *ppos)
-{
-	struct dvb_device *dvbdev = file->private_data;
-	struct ngene_channel *chan = dvbdev->priv;
-	struct ngene *dev = chan->dev;
-
-	if (wait_event_interruptible(dev->tsout_rbuf.queue,
-				     dvb_ringbuffer_free
-				     (&dev->tsout_rbuf) >= count) < 0)
-		return 0;
-
-	dvb_ringbuffer_write(&dev->tsout_rbuf, buf, count);
-
-	return count;
-}
-
-static ssize_t ts_read(struct file *file, char *buf,
-		       size_t count, loff_t *ppos)
-{
-	struct dvb_device *dvbdev = file->private_data;
-	struct ngene_channel *chan = dvbdev->priv;
-	struct ngene *dev = chan->dev;
-	int left, avail;
-
-	left = count;
-	while (left) {
-		if (wait_event_interruptible(
-			    dev->tsin_rbuf.queue,
-			    dvb_ringbuffer_avail(&dev->tsin_rbuf) > 0) < 0)
-			return -EAGAIN;
-		avail = dvb_ringbuffer_avail(&dev->tsin_rbuf);
-		if (avail > left)
-			avail = left;
-		dvb_ringbuffer_read_user(&dev->tsin_rbuf, buf, avail);
-		left -= avail;
-		buf += avail;
-	}
-	return count;
-}
-
-static const struct file_operations ci_fops = {
-	.owner   = THIS_MODULE,
-	.read    = ts_read,
-	.write   = ts_write,
-	.open    = dvb_generic_open,
-	.release = dvb_generic_release,
-};
-
-struct dvb_device ngene_dvbdev_ci = {
-	.priv    = 0,
-	.readers = -1,
-	.writers = -1,
-	.users   = -1,
-	.fops    = &ci_fops,
-};
-
-
-/****************************************************************************/
-/* DVB functions and API interface ******************************************/
-/****************************************************************************/
-
-static void swap_buffer(u32 *p, u32 len)
-{
-	while (len) {
-		*p = swab32(*p);
-		p++;
-		len -= 4;
-	}
-}
-
-/* start of filler packet */
-static u8 fill_ts[] = { 0x47, 0x1f, 0xff, 0x10, TS_FILLER };
-
-/* #define DEBUG_CI_XFER */
-#ifdef DEBUG_CI_XFER
-static u32 ok;
-static u32 overflow;
-static u32 stripped;
-#endif
-
-void *tsin_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags)
-{
-	struct ngene_channel *chan = priv;
-	struct ngene *dev = chan->dev;
-
-
-	if (flags & DF_SWAP32)
-		swap_buffer(buf, len);
-
-	if (dev->ci.en && chan->number == 2) {
-		while (len >= 188) {
-			if (memcmp(buf, fill_ts, sizeof fill_ts) != 0) {
-				if (dvb_ringbuffer_free(&dev->tsin_rbuf) >= 188) {
-					dvb_ringbuffer_write(&dev->tsin_rbuf, buf, 188);
-					wake_up(&dev->tsin_rbuf.queue);
-#ifdef DEBUG_CI_XFER
-					ok++;
-#endif
-				}
-#ifdef DEBUG_CI_XFER
-				else
-					overflow++;
-#endif
-			}
-#ifdef DEBUG_CI_XFER
-			else
-				stripped++;
-
-			if (ok % 100 == 0 && overflow)
-				printk(KERN_WARNING "%s: ok %u overflow %u dropped %u\n", __func__, ok, overflow, stripped);
-#endif
-			buf += 188;
-			len -= 188;
-		}
-		return NULL;
-	}
-
-	if (chan->users > 0)
-		dvb_dmx_swfilter(&chan->demux, buf, len);
-
-	return NULL;
-}
-
-void *tsout_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags)
-{
-	struct ngene_channel *chan = priv;
-	struct ngene *dev = chan->dev;
-	u32 alen;
-
-	alen = dvb_ringbuffer_avail(&dev->tsout_rbuf);
-	alen -= alen % 188;
-
-	if (alen < len)
-		FillTSBuffer(buf + alen, len - alen, flags);
-	else
-		alen = len;
-	dvb_ringbuffer_read(&dev->tsout_rbuf, buf, alen);
-	if (flags & DF_SWAP32)
-		swap_buffer((u32 *)buf, alen);
-	wake_up_interruptible(&dev->tsout_rbuf.queue);
-	return buf;
-}
-
-
-
-int ngene_start_feed(struct dvb_demux_feed *dvbdmxfeed)
-{
-	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
-	struct ngene_channel *chan = dvbdmx->priv;
-
-	if (chan->users == 0) {
-		if (!chan->dev->cmd_timeout_workaround || !chan->running)
-			set_transfer(chan, 1);
-	}
-
-	return ++chan->users;
-}
-
-int ngene_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
-{
-	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
-	struct ngene_channel *chan = dvbdmx->priv;
-
-	if (--chan->users)
-		return chan->users;
-
-	if (!chan->dev->cmd_timeout_workaround)
-		set_transfer(chan, 0);
-
-	return 0;
-}
-
-int my_dvb_dmx_ts_card_init(struct dvb_demux *dvbdemux, char *id,
-			    int (*start_feed)(struct dvb_demux_feed *),
-			    int (*stop_feed)(struct dvb_demux_feed *),
-			    void *priv)
-{
-	dvbdemux->priv = priv;
-
-	dvbdemux->filternum = 256;
-	dvbdemux->feednum = 256;
-	dvbdemux->start_feed = start_feed;
-	dvbdemux->stop_feed = stop_feed;
-	dvbdemux->write_to_decoder = NULL;
-	dvbdemux->dmx.capabilities = (DMX_TS_FILTERING |
-				      DMX_SECTION_FILTERING |
-				      DMX_MEMORY_BASED_FILTERING);
-	return dvb_dmx_init(dvbdemux);
-}
-
-int my_dvb_dmxdev_ts_card_init(struct dmxdev *dmxdev,
-			       struct dvb_demux *dvbdemux,
-			       struct dmx_frontend *hw_frontend,
-			       struct dmx_frontend *mem_frontend,
-			       struct dvb_adapter *dvb_adapter)
-{
-	int ret;
-
-	dmxdev->filternum = 256;
-	dmxdev->demux = &dvbdemux->dmx;
-	dmxdev->capabilities = 0;
-	ret = dvb_dmxdev_init(dmxdev, dvb_adapter);
-	if (ret < 0)
-		return ret;
-
-	hw_frontend->source = DMX_FRONTEND_0;
-	dvbdemux->dmx.add_frontend(&dvbdemux->dmx, hw_frontend);
-	mem_frontend->source = DMX_MEMORY_FE;
-	dvbdemux->dmx.add_frontend(&dvbdemux->dmx, mem_frontend);
-	return dvbdemux->dmx.connect_frontend(&dvbdemux->dmx, hw_frontend);
-}
diff --git a/drivers/media/dvb/ngene/ngene-i2c.c b/drivers/media/dvb/ngene/ngene-i2c.c
deleted file mode 100644
index d28554f..0000000
--- a/drivers/media/dvb/ngene/ngene-i2c.c
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * ngene-i2c.c: nGene PCIe bridge driver i2c functions
- *
- * Copyright (C) 2005-2007 Micronas
- *
- * Copyright (C) 2008-2009 Ralph Metzler <rjkm@metzlerbros.de>
- *                         Modifications for new nGene firmware,
- *                         support for EEPROM-copying,
- *                         support for new dual DVB-S2 card prototype
- *
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 only, as published by the Free Software Foundation.
- *
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-/* FIXME - some of these can probably be removed */
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/poll.h>
-#include <linux/io.h>
-#include <asm/div64.h>
-#include <linux/pci.h>
-#include <linux/pci_ids.h>
-#include <linux/timer.h>
-#include <linux/byteorder/generic.h>
-#include <linux/firmware.h>
-#include <linux/vmalloc.h>
-
-#include "ngene.h"
-
-/* Firmware command for i2c operations */
-static int ngene_command_i2c_read(struct ngene *dev, u8 adr,
-			   u8 *out, u8 outlen, u8 *in, u8 inlen, int flag)
-{
-	struct ngene_command com;
-
-	com.cmd.hdr.Opcode = CMD_I2C_READ;
-	com.cmd.hdr.Length = outlen + 3;
-	com.cmd.I2CRead.Device = adr << 1;
-	memcpy(com.cmd.I2CRead.Data, out, outlen);
-	com.cmd.I2CRead.Data[outlen] = inlen;
-	com.cmd.I2CRead.Data[outlen + 1] = 0;
-	com.in_len = outlen + 3;
-	com.out_len = inlen + 1;
-
-	if (ngene_command(dev, &com) < 0)
-		return -EIO;
-
-	if ((com.cmd.raw8[0] >> 1) != adr)
-		return -EIO;
-
-	if (flag)
-		memcpy(in, com.cmd.raw8, inlen + 1);
-	else
-		memcpy(in, com.cmd.raw8 + 1, inlen);
-	return 0;
-}
-
-static int ngene_command_i2c_write(struct ngene *dev, u8 adr,
-				   u8 *out, u8 outlen)
-{
-	struct ngene_command com;
-
-
-	com.cmd.hdr.Opcode = CMD_I2C_WRITE;
-	com.cmd.hdr.Length = outlen + 1;
-	com.cmd.I2CRead.Device = adr << 1;
-	memcpy(com.cmd.I2CRead.Data, out, outlen);
-	com.in_len = outlen + 1;
-	com.out_len = 1;
-
-	if (ngene_command(dev, &com) < 0)
-		return -EIO;
-
-	if (com.cmd.raw8[0] == 1)
-		return -EIO;
-
-	return 0;
-}
-
-static void ngene_i2c_set_bus(struct ngene *dev, int bus)
-{
-	if (!(dev->card_info->i2c_access & 2))
-		return;
-	if (dev->i2c_current_bus == bus)
-		return;
-
-	switch (bus) {
-	case 0:
-		ngene_command_gpio_set(dev, 3, 0);
-		ngene_command_gpio_set(dev, 2, 1);
-		break;
-
-	case 1:
-		ngene_command_gpio_set(dev, 2, 0);
-		ngene_command_gpio_set(dev, 3, 1);
-		break;
-	}
-	dev->i2c_current_bus = bus;
-}
-
-static int ngene_i2c_master_xfer(struct i2c_adapter *adapter,
-				 struct i2c_msg msg[], int num)
-{
-	struct ngene_channel *chan =
-		(struct ngene_channel *)i2c_get_adapdata(adapter);
-	struct ngene *dev = chan->dev;
-
-	down(&dev->i2c_switch_mutex);
-	ngene_i2c_set_bus(dev, chan->number);
-
-	if (num == 2 && msg[1].flags & I2C_M_RD && !(msg[0].flags & I2C_M_RD))
-		if (!ngene_command_i2c_read(dev, msg[0].addr,
-					    msg[0].buf, msg[0].len,
-					    msg[1].buf, msg[1].len, 0))
-			goto done;
-
-	if (num == 1 && !(msg[0].flags & I2C_M_RD))
-		if (!ngene_command_i2c_write(dev, msg[0].addr,
-					     msg[0].buf, msg[0].len))
-			goto done;
-	if (num == 1 && (msg[0].flags & I2C_M_RD))
-		if (!ngene_command_i2c_read(dev, msg[0].addr, NULL, 0,
-					    msg[0].buf, msg[0].len, 0))
-			goto done;
-
-	up(&dev->i2c_switch_mutex);
-	return -EIO;
-
-done:
-	up(&dev->i2c_switch_mutex);
-	return num;
-}
-
-
-static u32 ngene_i2c_functionality(struct i2c_adapter *adap)
-{
-	return I2C_FUNC_SMBUS_EMUL;
-}
-
-static struct i2c_algorithm ngene_i2c_algo = {
-	.master_xfer = ngene_i2c_master_xfer,
-	.functionality = ngene_i2c_functionality,
-};
-
-int ngene_i2c_init(struct ngene *dev, int dev_nr)
-{
-	struct i2c_adapter *adap = &(dev->channel[dev_nr].i2c_adapter);
-
-	i2c_set_adapdata(adap, &(dev->channel[dev_nr]));
-
-	strcpy(adap->name, "nGene");
-
-	adap->algo = &ngene_i2c_algo;
-	adap->algo_data = (void *)&(dev->channel[dev_nr]);
-	adap->dev.parent = &dev->pci_dev->dev;
-
-	return i2c_add_adapter(adap);
-}
-
diff --git a/drivers/media/dvb/ngene/ngene.h b/drivers/media/dvb/ngene/ngene.h
deleted file mode 100644
index 5443dc0..0000000
--- a/drivers/media/dvb/ngene/ngene.h
+++ /dev/null
@@ -1,921 +0,0 @@
-/*
- * ngene.h: nGene PCIe bridge driver
- *
- * Copyright (C) 2005-2007 Micronas
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 only, as published by the Free Software Foundation.
- *
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- */
-
-#ifndef _NGENE_H_
-#define _NGENE_H_
-
-#include <linux/types.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/i2c.h>
-#include <asm/dma.h>
-#include <linux/scatterlist.h>
-
-#include <linux/dvb/frontend.h>
-
-#include "dmxdev.h"
-#include "dvbdev.h"
-#include "dvb_demux.h"
-#include "dvb_ca_en50221.h"
-#include "dvb_frontend.h"
-#include "dvb_ringbuffer.h"
-#include "dvb_net.h"
-#include "cxd2099.h"
-
-#define DEVICE_NAME "ngene"
-
-#define NGENE_VID       0x18c3
-#define NGENE_PID       0x0720
-
-#ifndef VIDEO_CAP_VC1
-#define VIDEO_CAP_AVC   128
-#define VIDEO_CAP_H264  128
-#define VIDEO_CAP_VC1   256
-#define VIDEO_CAP_WMV9  256
-#define VIDEO_CAP_MPEG4 512
-#endif
-
-enum STREAM {
-	STREAM_VIDEOIN1 = 0,        /* ITU656 or TS Input */
-	STREAM_VIDEOIN2,
-	STREAM_AUDIOIN1,            /* I2S or SPI Input */
-	STREAM_AUDIOIN2,
-	STREAM_AUDIOOUT,
-	MAX_STREAM
-};
-
-enum SMODE_BITS {
-	SMODE_AUDIO_SPDIF = 0x20,
-	SMODE_AVSYNC = 0x10,
-	SMODE_TRANSPORT_STREAM = 0x08,
-	SMODE_AUDIO_CAPTURE = 0x04,
-	SMODE_VBI_CAPTURE = 0x02,
-	SMODE_VIDEO_CAPTURE = 0x01
-};
-
-enum STREAM_FLAG_BITS {
-	SFLAG_CHROMA_FORMAT_2COMP  = 0x01, /* Chroma Format : 2's complement */
-	SFLAG_CHROMA_FORMAT_OFFSET = 0x00, /* Chroma Format : Binary offset */
-	SFLAG_ORDER_LUMA_CHROMA    = 0x02, /* Byte order: Y,Cb,Y,Cr */
-	SFLAG_ORDER_CHROMA_LUMA    = 0x00, /* Byte order: Cb,Y,Cr,Y */
-	SFLAG_COLORBAR             = 0x04, /* Select colorbar */
-};
-
-#define PROGRAM_ROM     0x0000
-#define PROGRAM_SRAM    0x1000
-#define PERIPHERALS0    0x8000
-#define PERIPHERALS1    0x9000
-#define SHARED_BUFFER   0xC000
-
-#define HOST_TO_NGENE    (SHARED_BUFFER+0x0000)
-#define NGENE_TO_HOST    (SHARED_BUFFER+0x0100)
-#define NGENE_COMMAND    (SHARED_BUFFER+0x0200)
-#define NGENE_COMMAND_HI (SHARED_BUFFER+0x0204)
-#define NGENE_STATUS     (SHARED_BUFFER+0x0208)
-#define NGENE_STATUS_HI  (SHARED_BUFFER+0x020C)
-#define NGENE_EVENT      (SHARED_BUFFER+0x0210)
-#define NGENE_EVENT_HI   (SHARED_BUFFER+0x0214)
-#define VARIABLES        (SHARED_BUFFER+0x0210)
-
-#define NGENE_INT_COUNTS       (SHARED_BUFFER+0x0260)
-#define NGENE_INT_ENABLE       (SHARED_BUFFER+0x0264)
-#define NGENE_VBI_LINE_COUNT   (SHARED_BUFFER+0x0268)
-
-#define BUFFER_GP_XMIT  (SHARED_BUFFER+0x0800)
-#define BUFFER_GP_RECV  (SHARED_BUFFER+0x0900)
-#define EEPROM_AREA     (SHARED_BUFFER+0x0A00)
-
-#define SG_V_IN_1       (SHARED_BUFFER+0x0A80)
-#define SG_VBI_1        (SHARED_BUFFER+0x0B00)
-#define SG_A_IN_1       (SHARED_BUFFER+0x0B80)
-#define SG_V_IN_2       (SHARED_BUFFER+0x0C00)
-#define SG_VBI_2        (SHARED_BUFFER+0x0C80)
-#define SG_A_IN_2       (SHARED_BUFFER+0x0D00)
-#define SG_V_OUT        (SHARED_BUFFER+0x0D80)
-#define SG_A_OUT2       (SHARED_BUFFER+0x0E00)
-
-#define DATA_A_IN_1     (SHARED_BUFFER+0x0E80)
-#define DATA_A_IN_2     (SHARED_BUFFER+0x0F00)
-#define DATA_A_OUT      (SHARED_BUFFER+0x0F80)
-#define DATA_V_IN_1     (SHARED_BUFFER+0x1000)
-#define DATA_V_IN_2     (SHARED_BUFFER+0x2000)
-#define DATA_V_OUT      (SHARED_BUFFER+0x3000)
-
-#define DATA_FIFO_AREA  (SHARED_BUFFER+0x1000)
-
-#define TIMESTAMPS      0xA000
-#define SCRATCHPAD      0xA080
-#define FORCE_INT       0xA088
-#define FORCE_NMI       0xA090
-#define INT_STATUS      0xA0A0
-
-#define DEV_VER         0x9004
-
-#define FW_DEBUG_DEFAULT (PROGRAM_SRAM+0x00FF)
-
-struct SG_ADDR {
-	u64 start;
-	u64 curr;
-	u16 curr_ptr;
-	u16 elements;
-	u32 pad[3];
-} __attribute__ ((__packed__));
-
-struct SHARED_MEMORY {
-	/* C000 */
-	u32 HostToNgene[64];
-
-	/* C100 */
-	u32 NgeneToHost[64];
-
-	/* C200 */
-	u64 NgeneCommand;
-	u64 NgeneStatus;
-	u64 NgeneEvent;
-
-	/* C210 */
-	u8 pad1[0xc260 - 0xc218];
-
-	/* C260 */
-	u32 IntCounts;
-	u32 IntEnable;
-
-	/* C268 */
-	u8 pad2[0xd000 - 0xc268];
-
-} __attribute__ ((__packed__));
-
-struct BUFFER_STREAM_RESULTS {
-	u32 Clock;           /* Stream time in 100ns units */
-	u16 RemainingLines;  /* Remaining lines in this field.
-				0 for complete field */
-	u8  FieldCount;      /* Video field number */
-	u8  Flags;           /* Bit 7 = Done, Bit 6 = seen, Bit 5 = overflow,
-				Bit 0 = FieldID */
-	u16 BlockCount;      /* Audio block count (unused) */
-	u8  Reserved[2];
-	u32 DTOUpdate;
-} __attribute__ ((__packed__));
-
-struct HW_SCATTER_GATHER_ELEMENT {
-	u64 Address;
-	u32 Length;
-	u32 Reserved;
-} __attribute__ ((__packed__));
-
-struct BUFFER_HEADER {
-	u64    Next;
-	struct BUFFER_STREAM_RESULTS SR;
-
-	u32    Number_of_entries_1;
-	u32    Reserved5;
-	u64    Address_of_first_entry_1;
-
-	u32    Number_of_entries_2;
-	u32    Reserved7;
-	u64    Address_of_first_entry_2;
-} __attribute__ ((__packed__));
-
-struct EVENT_BUFFER {
-	u32    TimeStamp;
-	u8     GPIOStatus;
-	u8     UARTStatus;
-	u8     RXCharacter;
-	u8     EventStatus;
-	u32    Reserved[2];
-} __attribute__ ((__packed__));
-
-/* Firmware commands. */
-
-enum OPCODES {
-	CMD_NOP = 0,
-	CMD_FWLOAD_PREPARE  = 0x01,
-	CMD_FWLOAD_FINISH   = 0x02,
-	CMD_I2C_READ        = 0x03,
-	CMD_I2C_WRITE       = 0x04,
-
-	CMD_I2C_WRITE_NOSTOP = 0x05,
-	CMD_I2C_CONTINUE_WRITE = 0x06,
-	CMD_I2C_CONTINUE_WRITE_NOSTOP = 0x07,
-
-	CMD_DEBUG_OUTPUT    = 0x09,
-
-	CMD_CONTROL         = 0x10,
-	CMD_CONFIGURE_BUFFER = 0x11,
-	CMD_CONFIGURE_FREE_BUFFER = 0x12,
-
-	CMD_SPI_READ        = 0x13,
-	CMD_SPI_WRITE       = 0x14,
-
-	CMD_MEM_READ        = 0x20,
-	CMD_MEM_WRITE	    = 0x21,
-	CMD_SFR_READ	    = 0x22,
-	CMD_SFR_WRITE	    = 0x23,
-	CMD_IRAM_READ	    = 0x24,
-	CMD_IRAM_WRITE	    = 0x25,
-	CMD_SET_GPIO_PIN    = 0x26,
-	CMD_SET_GPIO_INT    = 0x27,
-	CMD_CONFIGURE_UART  = 0x28,
-	CMD_WRITE_UART      = 0x29,
-	MAX_CMD
-};
-
-enum RESPONSES {
-	OK = 0,
-	ERROR = 1
-};
-
-struct FW_HEADER {
-	u8 Opcode;
-	u8 Length;
-} __attribute__ ((__packed__));
-
-struct FW_I2C_WRITE {
-	struct FW_HEADER hdr;
-	u8 Device;
-	u8 Data[250];
-} __attribute__ ((__packed__));
-
-struct FW_I2C_CONTINUE_WRITE {
-	struct FW_HEADER hdr;
-	u8 Data[250];
-} __attribute__ ((__packed__));
-
-struct FW_I2C_READ {
-	struct FW_HEADER hdr;
-	u8 Device;
-	u8 Data[252];    /* followed by two bytes of read data count */
-} __attribute__ ((__packed__));
-
-struct FW_SPI_WRITE {
-	struct FW_HEADER hdr;
-	u8 ModeSelect;
-	u8 Data[250];
-} __attribute__ ((__packed__));
-
-struct FW_SPI_READ {
-	struct FW_HEADER hdr;
-	u8 ModeSelect;
-	u8 Data[252];    /* followed by two bytes of read data count */
-} __attribute__ ((__packed__));
-
-struct FW_FWLOAD_PREPARE {
-	struct FW_HEADER hdr;
-} __attribute__ ((__packed__));
-
-struct FW_FWLOAD_FINISH {
-	struct FW_HEADER hdr;
-	u16 Address;     /* address of final block */
-	u16 Length;
-} __attribute__ ((__packed__));
-
-/*
- * Meaning of FW_STREAM_CONTROL::Mode bits:
- *  Bit 7: Loopback PEXin to PEXout using TVOut channel
- *  Bit 6: AVLOOP
- *  Bit 5: Audio select; 0=I2S, 1=SPDIF
- *  Bit 4: AVSYNC
- *  Bit 3: Enable transport stream
- *  Bit 2: Enable audio capture
- *  Bit 1: Enable ITU-Video VBI capture
- *  Bit 0: Enable ITU-Video capture
- *
- * Meaning of FW_STREAM_CONTROL::Control bits (see UVI1_CTL)
- *  Bit 7: continuous capture
- *  Bit 6: capture one field
- *  Bit 5: capture one frame
- *  Bit 4: unused
- *  Bit 3: starting field; 0=odd, 1=even
- *  Bit 2: sample size; 0=8-bit, 1=10-bit
- *  Bit 1: data format; 0=UYVY, 1=YUY2
- *  Bit 0: resets buffer pointers
-*/
-
-enum FSC_MODE_BITS {
-	SMODE_LOOPBACK          = 0x80,
-	SMODE_AVLOOP            = 0x40,
-	_SMODE_AUDIO_SPDIF      = 0x20,
-	_SMODE_AVSYNC           = 0x10,
-	_SMODE_TRANSPORT_STREAM = 0x08,
-	_SMODE_AUDIO_CAPTURE    = 0x04,
-	_SMODE_VBI_CAPTURE      = 0x02,
-	_SMODE_VIDEO_CAPTURE    = 0x01
-};
-
-
-/* Meaning of FW_STREAM_CONTROL::Stream bits:
- * Bit 3: Audio sample count:  0 = relative, 1 = absolute
- * Bit 2: color bar select; 1=color bars, 0=CV3 decoder
- * Bits 1-0: stream select, UVI1, UVI2, TVOUT
- */
-
-struct FW_STREAM_CONTROL {
-	struct FW_HEADER hdr;
-	u8     Stream;             /* Stream number (UVI1, UVI2, TVOUT) */
-	u8     Control;            /* Value written to UVI1_CTL */
-	u8     Mode;               /* Controls clock source */
-	u8     SetupDataLen;	   /* Length of setup data, MSB=1 write
-				      backwards */
-	u16    CaptureBlockCount;  /* Blocks (a 256 Bytes) to capture per buffer
-				      for TS and Audio */
-	u64    Buffer_Address;	   /* Address of first buffer header */
-	u16    BytesPerVideoLine;
-	u16    MaxLinesPerField;
-	u16    MinLinesPerField;
-	u16    Reserved_1;
-	u16    BytesPerVBILine;
-	u16    MaxVBILinesPerField;
-	u16    MinVBILinesPerField;
-	u16    SetupDataAddr;      /* ngene relative address of setup data */
-	u8     SetupData[32];      /* setup data */
-} __attribute__((__packed__));
-
-#define AUDIO_BLOCK_SIZE    256
-#define TS_BLOCK_SIZE       256
-
-struct FW_MEM_READ {
-	struct FW_HEADER hdr;
-	u16   address;
-} __attribute__ ((__packed__));
-
-struct FW_MEM_WRITE {
-	struct FW_HEADER hdr;
-	u16   address;
-	u8    data;
-} __attribute__ ((__packed__));
-
-struct FW_SFR_IRAM_READ {
-	struct FW_HEADER hdr;
-	u8    address;
-} __attribute__ ((__packed__));
-
-struct FW_SFR_IRAM_WRITE {
-	struct FW_HEADER hdr;
-	u8    address;
-	u8    data;
-} __attribute__ ((__packed__));
-
-struct FW_SET_GPIO_PIN {
-	struct FW_HEADER hdr;
-	u8    select;
-} __attribute__ ((__packed__));
-
-struct FW_SET_GPIO_INT {
-	struct FW_HEADER hdr;
-	u8    select;
-} __attribute__ ((__packed__));
-
-struct FW_SET_DEBUGMODE {
-	struct FW_HEADER hdr;
-	u8   debug_flags;
-} __attribute__ ((__packed__));
-
-struct FW_CONFIGURE_BUFFERS {
-	struct FW_HEADER hdr;
-	u8   config;
-} __attribute__ ((__packed__));
-
-enum _BUFFER_CONFIGS {
-	/* 4k UVI1, 4k UVI2, 2k AUD1, 2k AUD2  (standard usage) */
-	BUFFER_CONFIG_4422 = 0,
-	/* 3k UVI1, 3k UVI2, 3k AUD1, 3k AUD2  (4x TS input usage) */
-	BUFFER_CONFIG_3333 = 1,
-	/* 8k UVI1, 0k UVI2, 2k AUD1, 2k I2SOut  (HDTV decoder usage) */
-	BUFFER_CONFIG_8022 = 2,
-	BUFFER_CONFIG_FW17 = 255, /* Use new FW 17 command */
-};
-
-struct FW_CONFIGURE_FREE_BUFFERS {
-	struct FW_HEADER hdr;
-	u8   UVI1_BufferLength;
-	u8   UVI2_BufferLength;
-	u8   TVO_BufferLength;
-	u8   AUD1_BufferLength;
-	u8   AUD2_BufferLength;
-	u8   TVA_BufferLength;
-} __attribute__ ((__packed__));
-
-struct FW_CONFIGURE_UART {
-	struct FW_HEADER hdr;
-	u8 UartControl;
-} __attribute__ ((__packed__));
-
-enum _UART_CONFIG {
-	_UART_BAUDRATE_19200 = 0,
-	_UART_BAUDRATE_9600  = 1,
-	_UART_BAUDRATE_4800  = 2,
-	_UART_BAUDRATE_2400  = 3,
-	_UART_RX_ENABLE      = 0x40,
-	_UART_TX_ENABLE      = 0x80,
-};
-
-struct FW_WRITE_UART {
-	struct FW_HEADER hdr;
-	u8 Data[252];
-} __attribute__ ((__packed__));
-
-
-struct ngene_command {
-	u32 in_len;
-	u32 out_len;
-	union {
-		u32                              raw[64];
-		u8                               raw8[256];
-		struct FW_HEADER                 hdr;
-		struct FW_I2C_WRITE              I2CWrite;
-		struct FW_I2C_CONTINUE_WRITE     I2CContinueWrite;
-		struct FW_I2C_READ               I2CRead;
-		struct FW_STREAM_CONTROL         StreamControl;
-		struct FW_FWLOAD_PREPARE         FWLoadPrepare;
-		struct FW_FWLOAD_FINISH          FWLoadFinish;
-		struct FW_MEM_READ		 MemoryRead;
-		struct FW_MEM_WRITE		 MemoryWrite;
-		struct FW_SFR_IRAM_READ		 SfrIramRead;
-		struct FW_SFR_IRAM_WRITE         SfrIramWrite;
-		struct FW_SPI_WRITE              SPIWrite;
-		struct FW_SPI_READ               SPIRead;
-		struct FW_SET_GPIO_PIN           SetGpioPin;
-		struct FW_SET_GPIO_INT           SetGpioInt;
-		struct FW_SET_DEBUGMODE          SetDebugMode;
-		struct FW_CONFIGURE_BUFFERS      ConfigureBuffers;
-		struct FW_CONFIGURE_FREE_BUFFERS ConfigureFreeBuffers;
-		struct FW_CONFIGURE_UART         ConfigureUart;
-		struct FW_WRITE_UART             WriteUart;
-	} cmd;
-} __attribute__ ((__packed__));
-
-#define NGENE_INTERFACE_VERSION 0x103
-#define MAX_VIDEO_BUFFER_SIZE   (417792) /* 288*1440 rounded up to next page */
-#define MAX_AUDIO_BUFFER_SIZE     (8192) /* Gives room for about 23msec@48KHz */
-#define MAX_VBI_BUFFER_SIZE      (28672) /* 1144*18 rounded up to next page */
-#define MAX_TS_BUFFER_SIZE       (98304) /* 512*188 rounded up to next page */
-#define MAX_HDTV_BUFFER_SIZE   (2080768) /* 541*1920*2 rounded up to next page
-					    Max: (1920x1080i60) */
-
-#define OVERFLOW_BUFFER_SIZE    (8192)
-
-#define RING_SIZE_VIDEO     4
-#define RING_SIZE_AUDIO     8
-#define RING_SIZE_TS        8
-
-#define NUM_SCATTER_GATHER_ENTRIES  8
-
-#define MAX_DMA_LENGTH (((MAX_VIDEO_BUFFER_SIZE + MAX_VBI_BUFFER_SIZE) * \
-			RING_SIZE_VIDEO * 2) + \
-			(MAX_AUDIO_BUFFER_SIZE * RING_SIZE_AUDIO * 2) + \
-			(MAX_TS_BUFFER_SIZE * RING_SIZE_TS * 4) + \
-			(RING_SIZE_VIDEO * PAGE_SIZE * 2) + \
-			(RING_SIZE_AUDIO * PAGE_SIZE * 2) + \
-			(RING_SIZE_TS    * PAGE_SIZE * 4) + \
-			 8 * PAGE_SIZE + OVERFLOW_BUFFER_SIZE + PAGE_SIZE)
-
-#define EVENT_QUEUE_SIZE    16
-
-/* Gathers the current state of a single channel. */
-
-struct SBufferHeader {
-	struct BUFFER_HEADER   ngeneBuffer; /* Physical descriptor */
-	struct SBufferHeader  *Next;
-	void                  *Buffer1;
-	struct HW_SCATTER_GATHER_ELEMENT *scList1;
-	void                  *Buffer2;
-	struct HW_SCATTER_GATHER_ELEMENT *scList2;
-};
-
-/* Sizeof SBufferHeader aligned to next 64 Bit boundary (hw restriction) */
-#define SIZEOF_SBufferHeader ((sizeof(struct SBufferHeader) + 63) & ~63)
-
-enum HWSTATE {
-	HWSTATE_STOP,
-	HWSTATE_STARTUP,
-	HWSTATE_RUN,
-	HWSTATE_PAUSE,
-};
-
-enum KSSTATE {
-	KSSTATE_STOP,
-	KSSTATE_ACQUIRE,
-	KSSTATE_PAUSE,
-	KSSTATE_RUN,
-};
-
-struct SRingBufferDescriptor {
-	struct SBufferHeader *Head; /* Points to first buffer in ring buffer
-				       structure*/
-	u64   PAHead;         /* Physical address of first buffer */
-	u32   MemSize;        /* Memory size of allocated ring buffers
-				 (needed for freeing) */
-	u32   NumBuffers;     /* Number of buffers in the ring */
-	u32   Buffer1Length;  /* Allocated length of Buffer 1 */
-	u32   Buffer2Length;  /* Allocated length of Buffer 2 */
-	void *SCListMem;      /* Memory to hold scatter gather lists for this
-				 ring */
-	u64   PASCListMem;    /* Physical address  .. */
-	u32   SCListMemSize;  /* Size of this memory */
-};
-
-enum STREAMMODEFLAGS {
-	StreamMode_NONE   = 0, /* Stream not used */
-	StreamMode_ANALOG = 1, /* Analog: Stream 0,1 = Video, 2,3 = Audio */
-	StreamMode_TSIN   = 2, /* Transport stream input (all) */
-	StreamMode_HDTV   = 4, /* HDTV: Maximum 1920x1080p30,1920x1080i60
-				  (only stream 0) */
-	StreamMode_TSOUT  = 8, /* Transport stream output (only stream 3) */
-};
-
-
-enum BufferExchangeFlags {
-	BEF_EVEN_FIELD   = 0x00000001,
-	BEF_CONTINUATION = 0x00000002,
-	BEF_MORE_DATA    = 0x00000004,
-	BEF_OVERFLOW     = 0x00000008,
-	DF_SWAP32        = 0x00010000,
-};
-
-typedef void *(IBufferExchange)(void *, void *, u32, u32, u32);
-
-struct MICI_STREAMINFO {
-	IBufferExchange    *pExchange;
-	IBufferExchange    *pExchangeVBI;     /* Secondary (VBI, ancillary) */
-	u8  Stream;
-	u8  Flags;
-	u8  Mode;
-	u8  Reserved;
-	u16 nLinesVideo;
-	u16 nBytesPerLineVideo;
-	u16 nLinesVBI;
-	u16 nBytesPerLineVBI;
-	u32 CaptureLength;    /* Used for audio and transport stream */
-};
-
-/****************************************************************************/
-/* STRUCTS ******************************************************************/
-/****************************************************************************/
-
-/* sound hardware definition */
-#define MIXER_ADDR_TVTUNER      0
-#define MIXER_ADDR_LAST         0
-
-struct ngene_channel;
-
-/*struct sound chip*/
-
-struct mychip {
-	struct ngene_channel *chan;
-	struct snd_card *card;
-	struct pci_dev *pci;
-	struct snd_pcm_substream *substream;
-	struct snd_pcm *pcm;
-	unsigned long port;
-	int irq;
-	spinlock_t mixer_lock;
-	spinlock_t lock;
-	int mixer_volume[MIXER_ADDR_LAST + 1][2];
-	int capture_source[MIXER_ADDR_LAST + 1][2];
-};
-
-#ifdef NGENE_V4L
-struct ngene_overlay {
-	int                    tvnorm;
-	struct v4l2_rect       w;
-	enum v4l2_field        field;
-	struct v4l2_clip       *clips;
-	int                    nclips;
-	int                    setup_ok;
-};
-
-struct ngene_tvnorm {
-	int   v4l2_id;
-	char  *name;
-	u16   swidth, sheight; /* scaled standard width, height */
-	int   tuner_norm;
-	int   soundstd;
-};
-
-struct ngene_vopen {
-	struct ngene_channel      *ch;
-	enum v4l2_priority         prio;
-	int                        width;
-	int                        height;
-	int                        depth;
-	struct videobuf_queue      vbuf_q;
-	struct videobuf_queue      vbi;
-	int                        fourcc;
-	int                        picxcount;
-	int                        resources;
-	enum v4l2_buf_type         type;
-	const struct ngene_format *fmt;
-
-	const struct ngene_format *ovfmt;
-	struct ngene_overlay       ov;
-};
-#endif
-
-struct ngene_channel {
-	struct device         device;
-	struct i2c_adapter    i2c_adapter;
-
-	struct ngene         *dev;
-	int                   number;
-	int                   type;
-	int                   mode;
-	bool                  has_adapter;
-	bool                  has_demux;
-	int                   demod_type;
-	int (*gate_ctrl)(struct dvb_frontend *, int);
-
-	struct dvb_frontend  *fe;
-	struct dvb_frontend  *fe2;
-	struct dmxdev         dmxdev;
-	struct dvb_demux      demux;
-	struct dvb_net        dvbnet;
-	struct dmx_frontend   hw_frontend;
-	struct dmx_frontend   mem_frontend;
-	int                   users;
-	struct video_device  *v4l_dev;
-	struct dvb_device    *ci_dev;
-	struct tasklet_struct demux_tasklet;
-
-	struct SBufferHeader *nextBuffer;
-	enum KSSTATE          State;
-	enum HWSTATE          HWState;
-	u8                    Stream;
-	u8                    Flags;
-	u8                    Mode;
-	IBufferExchange      *pBufferExchange;
-	IBufferExchange      *pBufferExchange2;
-
-	spinlock_t            state_lock;
-	u16                   nLines;
-	u16                   nBytesPerLine;
-	u16                   nVBILines;
-	u16                   nBytesPerVBILine;
-	u16                   itumode;
-	u32                   Capture1Length;
-	u32                   Capture2Length;
-	struct SRingBufferDescriptor RingBuffer;
-	struct SRingBufferDescriptor TSRingBuffer;
-	struct SRingBufferDescriptor TSIdleBuffer;
-
-	u32                   DataFormatFlags;
-
-	int                   AudioDTOUpdated;
-	u32                   AudioDTOValue;
-
-	int (*set_tone)(struct dvb_frontend *, fe_sec_tone_mode_t);
-	u8 lnbh;
-
-	/* stuff from analog driver */
-
-	int minor;
-	struct mychip        *mychip;
-	struct snd_card      *soundcard;
-	u8                   *evenbuffer;
-	u8                    dma_on;
-	int                   soundstreamon;
-	int                   audiomute;
-	int                   soundbuffisallocated;
-	int                   sndbuffflag;
-	int                   tun_rdy;
-	int                   dec_rdy;
-	int                   tun_dec_rdy;
-	int                   lastbufferflag;
-
-	struct ngene_tvnorm  *tvnorms;
-	int                   tvnorm_num;
-	int                   tvnorm;
-
-#ifdef NGENE_V4L
-	int                   videousers;
-	struct v4l2_prio_state prio;
-	struct ngene_vopen    init;
-	int                   resources;
-	struct v4l2_framebuffer fbuf;
-	struct ngene_buffer  *screen;     /* overlay             */
-	struct list_head      capture;    /* video capture queue */
-	spinlock_t s_lock;
-	struct semaphore reslock;
-#endif
-
-	int running;
-};
-
-
-struct ngene_ci {
-	struct device         device;
-	struct i2c_adapter    i2c_adapter;
-
-	struct ngene         *dev;
-	struct dvb_ca_en50221 *en;
-};
-
-struct ngene;
-
-typedef void (rx_cb_t)(struct ngene *, u32, u8);
-typedef void (tx_cb_t)(struct ngene *, u32);
-
-struct ngene {
-	int                   nr;
-	struct pci_dev       *pci_dev;
-	unsigned char        *iomem;
-
-	/*struct i2c_adapter  i2c_adapter;*/
-
-	u32                   device_version;
-	u32                   fw_interface_version;
-	u32                   icounts;
-	bool                  msi_enabled;
-	bool                  cmd_timeout_workaround;
-
-	u8                   *CmdDoneByte;
-	int                   BootFirmware;
-	void                 *OverflowBuffer;
-	dma_addr_t            PAOverflowBuffer;
-	void                 *FWInterfaceBuffer;
-	dma_addr_t            PAFWInterfaceBuffer;
-	u8                   *ngenetohost;
-	u8                   *hosttongene;
-
-	struct EVENT_BUFFER   EventQueue[EVENT_QUEUE_SIZE];
-	int                   EventQueueOverflowCount;
-	int                   EventQueueOverflowFlag;
-	struct tasklet_struct event_tasklet;
-	struct EVENT_BUFFER  *EventBuffer;
-	int                   EventQueueWriteIndex;
-	int                   EventQueueReadIndex;
-
-	wait_queue_head_t     cmd_wq;
-	int                   cmd_done;
-	struct semaphore      cmd_mutex;
-	struct semaphore      stream_mutex;
-	struct semaphore      pll_mutex;
-	struct semaphore      i2c_switch_mutex;
-	int                   i2c_current_channel;
-	int                   i2c_current_bus;
-	spinlock_t            cmd_lock;
-
-	struct dvb_adapter    adapter[MAX_STREAM];
-	struct dvb_adapter    *first_adapter; /* "one_adapter" modprobe opt */
-	struct ngene_channel  channel[MAX_STREAM];
-
-	struct ngene_info    *card_info;
-
-	tx_cb_t              *TxEventNotify;
-	rx_cb_t              *RxEventNotify;
-	int                   tx_busy;
-	wait_queue_head_t     tx_wq;
-	wait_queue_head_t     rx_wq;
-#define UART_RBUF_LEN 4096
-	u8                    uart_rbuf[UART_RBUF_LEN];
-	int                   uart_rp, uart_wp;
-
-#define TS_FILLER  0x6f
-
-	u8                   *tsout_buf;
-#define TSOUT_BUF_SIZE (512*188*8)
-	struct dvb_ringbuffer tsout_rbuf;
-
-	u8                   *tsin_buf;
-#define TSIN_BUF_SIZE (512*188*8)
-	struct dvb_ringbuffer tsin_rbuf;
-
-	u8                   *ain_buf;
-#define AIN_BUF_SIZE (128*1024)
-	struct dvb_ringbuffer ain_rbuf;
-
-
-	u8                   *vin_buf;
-#define VIN_BUF_SIZE (4*1920*1080)
-	struct dvb_ringbuffer vin_rbuf;
-
-	unsigned long         exp_val;
-	int prev_cmd;
-
-	struct ngene_ci       ci;
-};
-
-struct ngene_info {
-	int   type;
-#define NGENE_APP        0
-#define NGENE_TERRATEC   1
-#define NGENE_SIDEWINDER 2
-#define NGENE_RACER      3
-#define NGENE_VIPER      4
-#define NGENE_PYTHON     5
-#define NGENE_VBOX_V1	 6
-#define NGENE_VBOX_V2	 7
-
-	int   fw_version;
-	bool  msi_supported;
-	char *name;
-
-	int   io_type[MAX_STREAM];
-#define NGENE_IO_NONE    0
-#define NGENE_IO_TV      1
-#define NGENE_IO_HDTV    2
-#define NGENE_IO_TSIN    4
-#define NGENE_IO_TSOUT   8
-#define NGENE_IO_AIN     16
-
-	void *fe_config[4];
-	void *tuner_config[4];
-
-	int (*demod_attach[4])(struct ngene_channel *);
-	int (*tuner_attach[4])(struct ngene_channel *);
-
-	u8    avf[4];
-	u8    msp[4];
-	u8    demoda[4];
-	u8    lnb[4];
-	int   i2c_access;
-	u8    ntsc;
-	u8    tsf[4];
-	u8    i2s[4];
-
-	int (*gate_ctrl)(struct dvb_frontend *, int);
-	int (*switch_ctrl)(struct ngene_channel *, int, int);
-};
-
-#ifdef NGENE_V4L
-struct ngene_format {
-	char *name;
-	int   fourcc;          /* video4linux 2      */
-	int   btformat;        /* BT848_COLOR_FMT_*  */
-	int   format;
-	int   btswap;          /* BT848_COLOR_CTL_*  */
-	int   depth;           /* bit/pixel          */
-	int   flags;
-	int   hshift, vshift;  /* for planar modes   */
-	int   palette;
-};
-
-#define RESOURCE_OVERLAY       1
-#define RESOURCE_VIDEO         2
-#define RESOURCE_VBI           4
-
-struct ngene_buffer {
-	/* common v4l buffer stuff -- must be first */
-	struct videobuf_buffer     vb;
-
-	/* ngene specific */
-	const struct ngene_format *fmt;
-	int                        tvnorm;
-	int                        btformat;
-	int                        btswap;
-};
-#endif
-
-
-/* Provided by ngene-core.c */
-int __devinit ngene_probe(struct pci_dev *pci_dev,
-			  const struct pci_device_id *id);
-void __devexit ngene_remove(struct pci_dev *pdev);
-void ngene_shutdown(struct pci_dev *pdev);
-int ngene_command(struct ngene *dev, struct ngene_command *com);
-int ngene_command_gpio_set(struct ngene *dev, u8 select, u8 level);
-void set_transfer(struct ngene_channel *chan, int state);
-void FillTSBuffer(void *Buffer, int Length, u32 Flags);
-
-/* Provided by ngene-i2c.c */
-int ngene_i2c_init(struct ngene *dev, int dev_nr);
-
-/* Provided by ngene-dvb.c */
-extern struct dvb_device ngene_dvbdev_ci;
-void *tsout_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags);
-void *tsin_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags);
-int ngene_start_feed(struct dvb_demux_feed *dvbdmxfeed);
-int ngene_stop_feed(struct dvb_demux_feed *dvbdmxfeed);
-int my_dvb_dmx_ts_card_init(struct dvb_demux *dvbdemux, char *id,
-			    int (*start_feed)(struct dvb_demux_feed *),
-			    int (*stop_feed)(struct dvb_demux_feed *),
-			    void *priv);
-int my_dvb_dmxdev_ts_card_init(struct dmxdev *dmxdev,
-			       struct dvb_demux *dvbdemux,
-			       struct dmx_frontend *hw_frontend,
-			       struct dmx_frontend *mem_frontend,
-			       struct dvb_adapter *dvb_adapter);
-
-#endif
-
-/*  LocalWords:  Endif
- */
diff --git a/drivers/media/dvb/pluto2/Kconfig b/drivers/media/dvb/pluto2/Kconfig
deleted file mode 100644
index 7d8e6e8..0000000
--- a/drivers/media/dvb/pluto2/Kconfig
+++ /dev/null
@@ -1,15 +0,0 @@
-config DVB_PLUTO2
-	tristate "Pluto2 cards"
-	depends on DVB_CORE && PCI && I2C
-	select I2C_ALGOBIT
-	select DVB_TDA1004X
-	help
-	  Support for PCI cards based on the Pluto2 FPGA like the Satelco
-	  Easywatch Mobile Terrestrial DVB-T Receiver.
-
-	  Since these cards have no MPEG decoder onboard, they transmit
-	  only compressed MPEG data over the PCI bus, so you need
-	  an external software decoder to watch TV on your computer.
-
-	  Say Y or M if you own such a device and want to use it.
-
diff --git a/drivers/media/dvb/pluto2/Makefile b/drivers/media/dvb/pluto2/Makefile
deleted file mode 100644
index 7008223..0000000
--- a/drivers/media/dvb/pluto2/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-obj-$(CONFIG_DVB_PLUTO2) += pluto2.o
-
-ccflags-y += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
diff --git a/drivers/media/dvb/pluto2/pluto2.c b/drivers/media/dvb/pluto2/pluto2.c
deleted file mode 100644
index f148b19..0000000
--- a/drivers/media/dvb/pluto2/pluto2.c
+++ /dev/null
@@ -1,815 +0,0 @@
-/*
- * pluto2.c - Satelco Easywatch Mobile Terrestrial Receiver [DVB-T]
- *
- * Copyright (C) 2005 Andreas Oberritter <obi@linuxtv.org>
- *
- * based on pluto2.c 1.10 - http://instinct-wp8.no-ip.org/pluto/
- * 	by Dany Salman <salmandany@yahoo.fr>
- *	Copyright (c) 2004 TDF
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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/i2c.h>
-#include <linux/i2c-algo-bit.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/dma-mapping.h>
-#include <linux/slab.h>
-
-#include "demux.h"
-#include "dmxdev.h"
-#include "dvb_demux.h"
-#include "dvb_frontend.h"
-#include "dvb_net.h"
-#include "dvbdev.h"
-#include "tda1004x.h"
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-#define DRIVER_NAME		"pluto2"
-
-#define REG_PIDn(n)		((n) << 2)	/* PID n pattern registers */
-#define REG_PCAR		0x0020		/* PC address register */
-#define REG_TSCR		0x0024		/* TS ctrl & status */
-#define REG_MISC		0x0028		/* miscellaneous */
-#define REG_MMAC		0x002c		/* MSB MAC address */
-#define REG_IMAC		0x0030		/* ISB MAC address */
-#define REG_LMAC		0x0034		/* LSB MAC address */
-#define REG_SPID		0x0038		/* SPI data */
-#define REG_SLCS		0x003c		/* serial links ctrl/status */
-
-#define PID0_NOFIL		(0x0001 << 16)
-#define PIDn_ENP		(0x0001 << 15)
-#define PID0_END		(0x0001 << 14)
-#define PID0_AFIL		(0x0001 << 13)
-#define PIDn_PID		(0x1fff <<  0)
-
-#define TSCR_NBPACKETS		(0x00ff << 24)
-#define TSCR_DEM		(0x0001 << 17)
-#define TSCR_DE			(0x0001 << 16)
-#define TSCR_RSTN		(0x0001 << 15)
-#define TSCR_MSKO		(0x0001 << 14)
-#define TSCR_MSKA		(0x0001 << 13)
-#define TSCR_MSKL		(0x0001 << 12)
-#define TSCR_OVR		(0x0001 << 11)
-#define TSCR_AFUL		(0x0001 << 10)
-#define TSCR_LOCK		(0x0001 <<  9)
-#define TSCR_IACK		(0x0001 <<  8)
-#define TSCR_ADEF		(0x007f <<  0)
-
-#define MISC_DVR		(0x0fff <<  4)
-#define MISC_ALED		(0x0001 <<  3)
-#define MISC_FRST		(0x0001 <<  2)
-#define MISC_LED1		(0x0001 <<  1)
-#define MISC_LED0		(0x0001 <<  0)
-
-#define SPID_SPIDR		(0x00ff <<  0)
-
-#define SLCS_SCL		(0x0001 <<  7)
-#define SLCS_SDA		(0x0001 <<  6)
-#define SLCS_CSN		(0x0001 <<  2)
-#define SLCS_OVR		(0x0001 <<  1)
-#define SLCS_SWC		(0x0001 <<  0)
-
-#define TS_DMA_PACKETS		(8)
-#define TS_DMA_BYTES		(188 * TS_DMA_PACKETS)
-
-#define I2C_ADDR_TDA10046	0x10
-#define I2C_ADDR_TUA6034	0xc2
-#define NHWFILTERS		8
-
-struct pluto {
-	/* pci */
-	struct pci_dev *pdev;
-	u8 __iomem *io_mem;
-
-	/* dvb */
-	struct dmx_frontend hw_frontend;
-	struct dmx_frontend mem_frontend;
-	struct dmxdev dmxdev;
-	struct dvb_adapter dvb_adapter;
-	struct dvb_demux demux;
-	struct dvb_frontend *fe;
-	struct dvb_net dvbnet;
-	unsigned int full_ts_users;
-	unsigned int users;
-
-	/* i2c */
-	struct i2c_algo_bit_data i2c_bit;
-	struct i2c_adapter i2c_adap;
-	unsigned int i2cbug;
-
-	/* irq */
-	unsigned int overflow;
-	unsigned int dead;
-
-	/* dma */
-	dma_addr_t dma_addr;
-	u8 dma_buf[TS_DMA_BYTES];
-	u8 dummy[4096];
-};
-
-static inline struct pluto *feed_to_pluto(struct dvb_demux_feed *feed)
-{
-	return container_of(feed->demux, struct pluto, demux);
-}
-
-static inline struct pluto *frontend_to_pluto(struct dvb_frontend *fe)
-{
-	return container_of(fe->dvb, struct pluto, dvb_adapter);
-}
-
-static inline u32 pluto_readreg(struct pluto *pluto, u32 reg)
-{
-	return readl(&pluto->io_mem[reg]);
-}
-
-static inline void pluto_writereg(struct pluto *pluto, u32 reg, u32 val)
-{
-	writel(val, &pluto->io_mem[reg]);
-}
-
-static inline void pluto_rw(struct pluto *pluto, u32 reg, u32 mask, u32 bits)
-{
-	u32 val = readl(&pluto->io_mem[reg]);
-	val &= ~mask;
-	val |= bits;
-	writel(val, &pluto->io_mem[reg]);
-}
-
-static void pluto_write_tscr(struct pluto *pluto, u32 val)
-{
-	/* set the number of packets */
-	val &= ~TSCR_ADEF;
-	val |= TS_DMA_PACKETS / 2;
-
-	pluto_writereg(pluto, REG_TSCR, val);
-}
-
-static void pluto_setsda(void *data, int state)
-{
-	struct pluto *pluto = data;
-
-	if (state)
-		pluto_rw(pluto, REG_SLCS, SLCS_SDA, SLCS_SDA);
-	else
-		pluto_rw(pluto, REG_SLCS, SLCS_SDA, 0);
-}
-
-static void pluto_setscl(void *data, int state)
-{
-	struct pluto *pluto = data;
-
-	if (state)
-		pluto_rw(pluto, REG_SLCS, SLCS_SCL, SLCS_SCL);
-	else
-		pluto_rw(pluto, REG_SLCS, SLCS_SCL, 0);
-
-	/* try to detect i2c_inb() to workaround hardware bug:
-	 * reset SDA to high after SCL has been set to low */
-	if ((state) && (pluto->i2cbug == 0)) {
-		pluto->i2cbug = 1;
-	} else {
-		if ((!state) && (pluto->i2cbug == 1))
-			pluto_setsda(pluto, 1);
-		pluto->i2cbug = 0;
-	}
-}
-
-static int pluto_getsda(void *data)
-{
-	struct pluto *pluto = data;
-
-	return pluto_readreg(pluto, REG_SLCS) & SLCS_SDA;
-}
-
-static int pluto_getscl(void *data)
-{
-	struct pluto *pluto = data;
-
-	return pluto_readreg(pluto, REG_SLCS) & SLCS_SCL;
-}
-
-static void pluto_reset_frontend(struct pluto *pluto, int reenable)
-{
-	u32 val = pluto_readreg(pluto, REG_MISC);
-
-	if (val & MISC_FRST) {
-		val &= ~MISC_FRST;
-		pluto_writereg(pluto, REG_MISC, val);
-	}
-	if (reenable) {
-		val |= MISC_FRST;
-		pluto_writereg(pluto, REG_MISC, val);
-	}
-}
-
-static void pluto_reset_ts(struct pluto *pluto, int reenable)
-{
-	u32 val = pluto_readreg(pluto, REG_TSCR);
-
-	if (val & TSCR_RSTN) {
-		val &= ~TSCR_RSTN;
-		pluto_write_tscr(pluto, val);
-	}
-	if (reenable) {
-		val |= TSCR_RSTN;
-		pluto_write_tscr(pluto, val);
-	}
-}
-
-static void pluto_set_dma_addr(struct pluto *pluto)
-{
-	pluto_writereg(pluto, REG_PCAR, pluto->dma_addr);
-}
-
-static int __devinit pluto_dma_map(struct pluto *pluto)
-{
-	pluto->dma_addr = pci_map_single(pluto->pdev, pluto->dma_buf,
-			TS_DMA_BYTES, PCI_DMA_FROMDEVICE);
-
-	return pci_dma_mapping_error(pluto->pdev, pluto->dma_addr);
-}
-
-static void pluto_dma_unmap(struct pluto *pluto)
-{
-	pci_unmap_single(pluto->pdev, pluto->dma_addr,
-			TS_DMA_BYTES, PCI_DMA_FROMDEVICE);
-}
-
-static int pluto_start_feed(struct dvb_demux_feed *f)
-{
-	struct pluto *pluto = feed_to_pluto(f);
-
-	/* enable PID filtering */
-	if (pluto->users++ == 0)
-		pluto_rw(pluto, REG_PIDn(0), PID0_AFIL | PID0_NOFIL, 0);
-
-	if ((f->pid < 0x2000) && (f->index < NHWFILTERS))
-		pluto_rw(pluto, REG_PIDn(f->index), PIDn_ENP | PIDn_PID, PIDn_ENP | f->pid);
-	else if (pluto->full_ts_users++ == 0)
-		pluto_rw(pluto, REG_PIDn(0), PID0_NOFIL, PID0_NOFIL);
-
-	return 0;
-}
-
-static int pluto_stop_feed(struct dvb_demux_feed *f)
-{
-	struct pluto *pluto = feed_to_pluto(f);
-
-	/* disable PID filtering */
-	if (--pluto->users == 0)
-		pluto_rw(pluto, REG_PIDn(0), PID0_AFIL, PID0_AFIL);
-
-	if ((f->pid < 0x2000) && (f->index < NHWFILTERS))
-		pluto_rw(pluto, REG_PIDn(f->index), PIDn_ENP | PIDn_PID, 0x1fff);
-	else if (--pluto->full_ts_users == 0)
-		pluto_rw(pluto, REG_PIDn(0), PID0_NOFIL, 0);
-
-	return 0;
-}
-
-static void pluto_dma_end(struct pluto *pluto, unsigned int nbpackets)
-{
-	/* synchronize the DMA transfer with the CPU
-	 * first so that we see updated contents. */
-	pci_dma_sync_single_for_cpu(pluto->pdev, pluto->dma_addr,
-			TS_DMA_BYTES, PCI_DMA_FROMDEVICE);
-
-	/* Workaround for broken hardware:
-	 * [1] On startup NBPACKETS seems to contain an uninitialized value,
-	 *     but no packets have been transferred.
-	 * [2] Sometimes (actually very often) NBPACKETS stays at zero
-	 *     although one packet has been transferred.
-	 * [3] Sometimes (actually rarely), the card gets into an erroneous
-	 *     mode where it continuously generates interrupts, claiming it
-	 *     has received nbpackets>TS_DMA_PACKETS packets, but no packet
-	 *     has been transferred. Only a reset seems to solve this
-	 */
-	if ((nbpackets == 0) || (nbpackets > TS_DMA_PACKETS)) {
-		unsigned int i = 0;
-		while (pluto->dma_buf[i] == 0x47)
-			i += 188;
-		nbpackets = i / 188;
-		if (i == 0) {
-			pluto_reset_ts(pluto, 1);
-			dev_printk(KERN_DEBUG, &pluto->pdev->dev, "resetting TS because of invalid packet counter\n");
-		}
-	}
-
-	dvb_dmx_swfilter_packets(&pluto->demux, pluto->dma_buf, nbpackets);
-
-	/* clear the dma buffer. this is needed to be able to identify
-	 * new valid ts packets above */
-	memset(pluto->dma_buf, 0, nbpackets * 188);
-
-	/* reset the dma address */
-	pluto_set_dma_addr(pluto);
-
-	/* sync the buffer and give it back to the card */
-	pci_dma_sync_single_for_device(pluto->pdev, pluto->dma_addr,
-			TS_DMA_BYTES, PCI_DMA_FROMDEVICE);
-}
-
-static irqreturn_t pluto_irq(int irq, void *dev_id)
-{
-	struct pluto *pluto = dev_id;
-	u32 tscr;
-
-	/* check whether an interrupt occurred on this device */
-	tscr = pluto_readreg(pluto, REG_TSCR);
-	if (!(tscr & (TSCR_DE | TSCR_OVR)))
-		return IRQ_NONE;
-
-	if (tscr == 0xffffffff) {
-		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;
-	}
-
-	/* dma end interrupt */
-	if (tscr & TSCR_DE) {
-		pluto_dma_end(pluto, (tscr & TSCR_NBPACKETS) >> 24);
-		/* overflow interrupt */
-		if (tscr & TSCR_OVR)
-			pluto->overflow++;
-		if (pluto->overflow) {
-			dev_err(&pluto->pdev->dev, "overflow irq (%d)\n",
-					pluto->overflow);
-			pluto_reset_ts(pluto, 1);
-			pluto->overflow = 0;
-		}
-	} else if (tscr & TSCR_OVR) {
-		pluto->overflow++;
-	}
-
-	/* ACK the interrupt */
-	pluto_write_tscr(pluto, tscr | TSCR_IACK);
-
-	return IRQ_HANDLED;
-}
-
-static void __devinit pluto_enable_irqs(struct pluto *pluto)
-{
-	u32 val = pluto_readreg(pluto, REG_TSCR);
-
-	/* disable AFUL and LOCK interrupts */
-	val |= (TSCR_MSKA | TSCR_MSKL);
-	/* enable DMA and OVERFLOW interrupts */
-	val &= ~(TSCR_DEM | TSCR_MSKO);
-	/* clear pending interrupts */
-	val |= TSCR_IACK;
-
-	pluto_write_tscr(pluto, val);
-}
-
-static void pluto_disable_irqs(struct pluto *pluto)
-{
-	u32 val = pluto_readreg(pluto, REG_TSCR);
-
-	/* disable all interrupts */
-	val |= (TSCR_DEM | TSCR_MSKO | TSCR_MSKA | TSCR_MSKL);
-	/* clear pending interrupts */
-	val |= TSCR_IACK;
-
-	pluto_write_tscr(pluto, val);
-}
-
-static int __devinit pluto_hw_init(struct pluto *pluto)
-{
-	pluto_reset_frontend(pluto, 1);
-
-	/* set automatic LED control by FPGA */
-	pluto_rw(pluto, REG_MISC, MISC_ALED, MISC_ALED);
-
-	/* set data endianess */
-#ifdef __LITTLE_ENDIAN
-	pluto_rw(pluto, REG_PIDn(0), PID0_END, PID0_END);
-#else
-	pluto_rw(pluto, REG_PIDn(0), PID0_END, 0);
-#endif
-	/* map DMA and set address */
-	pluto_dma_map(pluto);
-	pluto_set_dma_addr(pluto);
-
-	/* enable interrupts */
-	pluto_enable_irqs(pluto);
-
-	/* reset TS logic */
-	pluto_reset_ts(pluto, 1);
-
-	return 0;
-}
-
-static void pluto_hw_exit(struct pluto *pluto)
-{
-	/* disable interrupts */
-	pluto_disable_irqs(pluto);
-
-	pluto_reset_ts(pluto, 0);
-
-	/* LED: disable automatic control, enable yellow, disable green */
-	pluto_rw(pluto, REG_MISC, MISC_ALED | MISC_LED1 | MISC_LED0, MISC_LED1);
-
-	/* unmap DMA */
-	pluto_dma_unmap(pluto);
-
-	pluto_reset_frontend(pluto, 0);
-}
-
-static inline u32 divide(u32 numerator, u32 denominator)
-{
-	if (denominator == 0)
-		return ~0;
-
-	return DIV_ROUND_CLOSEST(numerator, denominator);
-}
-
-/* LG Innotek TDTE-E001P (Infineon TUA6034) */
-static int lg_tdtpe001p_tuner_set_params(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct pluto *pluto = frontend_to_pluto(fe);
-	struct i2c_msg msg;
-	int ret;
-	u8 buf[4];
-	u32 div;
-
-	// Fref = 166.667 Hz
-	// Fref * 3 = 500.000 Hz
-	// IF = 36166667
-	// IF / Fref = 217
-	//div = divide(p->frequency + 36166667, 166667);
-	div = divide(p->frequency * 3, 500000) + 217;
-	buf[0] = (div >> 8) & 0x7f;
-	buf[1] = (div >> 0) & 0xff;
-
-	if (p->frequency < 611000000)
-		buf[2] = 0xb4;
-	else if (p->frequency < 811000000)
-		buf[2] = 0xbc;
-	else
-		buf[2] = 0xf4;
-
-	// VHF: 174-230 MHz
-	// center: 350 MHz
-	// UHF: 470-862 MHz
-	if (p->frequency < 350000000)
-		buf[3] = 0x02;
-	else
-		buf[3] = 0x04;
-
-	if (p->bandwidth_hz == 8000000)
-		buf[3] |= 0x08;
-
-	msg.addr = I2C_ADDR_TUA6034 >> 1;
-	msg.flags = 0;
-	msg.buf = buf;
-	msg.len = sizeof(buf);
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	ret = i2c_transfer(&pluto->i2c_adap, &msg, 1);
-	if (ret < 0)
-		return ret;
-	else if (ret == 0)
-		return -EREMOTEIO;
-
-	return 0;
-}
-
-static int pluto2_request_firmware(struct dvb_frontend *fe,
-				   const struct firmware **fw, char *name)
-{
-	struct pluto *pluto = frontend_to_pluto(fe);
-
-	return request_firmware(fw, name, &pluto->pdev->dev);
-}
-
-static struct tda1004x_config pluto2_fe_config __devinitdata = {
-	.demod_address = I2C_ADDR_TDA10046 >> 1,
-	.invert = 1,
-	.invert_oclk = 0,
-	.xtal_freq = TDA10046_XTAL_16M,
-	.agc_config = TDA10046_AGC_DEFAULT,
-	.if_freq = TDA10046_FREQ_3617,
-	.request_firmware = pluto2_request_firmware,
-};
-
-static int __devinit frontend_init(struct pluto *pluto)
-{
-	int ret;
-
-	pluto->fe = tda10046_attach(&pluto2_fe_config, &pluto->i2c_adap);
-	if (!pluto->fe) {
-		dev_err(&pluto->pdev->dev, "could not attach frontend\n");
-		return -ENODEV;
-	}
-	pluto->fe->ops.tuner_ops.set_params = lg_tdtpe001p_tuner_set_params;
-
-	ret = dvb_register_frontend(&pluto->dvb_adapter, pluto->fe);
-	if (ret < 0) {
-		if (pluto->fe->ops.release)
-			pluto->fe->ops.release(pluto->fe);
-		return ret;
-	}
-
-	return 0;
-}
-
-static void __devinit pluto_read_rev(struct pluto *pluto)
-{
-	u32 val = pluto_readreg(pluto, REG_MISC) & MISC_DVR;
-	dev_info(&pluto->pdev->dev, "board revision %d.%d\n",
-			(val >> 12) & 0x0f, (val >> 4) & 0xff);
-}
-
-static void __devinit pluto_read_mac(struct pluto *pluto, u8 *mac)
-{
-	u32 val = pluto_readreg(pluto, REG_MMAC);
-	mac[0] = (val >> 8) & 0xff;
-	mac[1] = (val >> 0) & 0xff;
-
-	val = pluto_readreg(pluto, REG_IMAC);
-	mac[2] = (val >> 8) & 0xff;
-	mac[3] = (val >> 0) & 0xff;
-
-	val = pluto_readreg(pluto, REG_LMAC);
-	mac[4] = (val >> 8) & 0xff;
-	mac[5] = (val >> 0) & 0xff;
-
-	dev_info(&pluto->pdev->dev, "MAC %pM\n", mac);
-}
-
-static int __devinit pluto_read_serial(struct pluto *pluto)
-{
-	struct pci_dev *pdev = pluto->pdev;
-	unsigned int i, j;
-	u8 __iomem *cis;
-
-	cis = pci_iomap(pdev, 1, 0);
-	if (!cis)
-		return -EIO;
-
-	dev_info(&pdev->dev, "S/N ");
-
-	for (i = 0xe0; i < 0x100; i += 4) {
-		u32 val = readl(&cis[i]);
-		for (j = 0; j < 32; j += 8) {
-			if ((val & 0xff) == 0xff)
-				goto out;
-			printk("%c", val & 0xff);
-			val >>= 8;
-		}
-	}
-out:
-	printk("\n");
-	pci_iounmap(pdev, cis);
-
-	return 0;
-}
-
-static int __devinit pluto2_probe(struct pci_dev *pdev,
-				  const struct pci_device_id *ent)
-{
-	struct pluto *pluto;
-	struct dvb_adapter *dvb_adapter;
-	struct dvb_demux *dvbdemux;
-	struct dmx_demux *dmx;
-	int ret = -ENOMEM;
-
-	pluto = kzalloc(sizeof(struct pluto), GFP_KERNEL);
-	if (!pluto)
-		goto out;
-
-	pluto->pdev = pdev;
-
-	ret = pci_enable_device(pdev);
-	if (ret < 0)
-		goto err_kfree;
-
-	/* enable interrupts */
-	pci_write_config_dword(pdev, 0x6c, 0x8000);
-
-	ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
-	if (ret < 0)
-		goto err_pci_disable_device;
-
-	pci_set_master(pdev);
-
-	ret = pci_request_regions(pdev, DRIVER_NAME);
-	if (ret < 0)
-		goto err_pci_disable_device;
-
-	pluto->io_mem = pci_iomap(pdev, 0, 0x40);
-	if (!pluto->io_mem) {
-		ret = -EIO;
-		goto err_pci_release_regions;
-	}
-
-	pci_set_drvdata(pdev, pluto);
-
-	ret = request_irq(pdev->irq, pluto_irq, IRQF_SHARED, DRIVER_NAME, pluto);
-	if (ret < 0)
-		goto err_pci_iounmap;
-
-	ret = pluto_hw_init(pluto);
-	if (ret < 0)
-		goto err_free_irq;
-
-	/* i2c */
-	i2c_set_adapdata(&pluto->i2c_adap, pluto);
-	strcpy(pluto->i2c_adap.name, DRIVER_NAME);
-	pluto->i2c_adap.owner = THIS_MODULE;
-	pluto->i2c_adap.dev.parent = &pdev->dev;
-	pluto->i2c_adap.algo_data = &pluto->i2c_bit;
-	pluto->i2c_bit.data = pluto;
-	pluto->i2c_bit.setsda = pluto_setsda;
-	pluto->i2c_bit.setscl = pluto_setscl;
-	pluto->i2c_bit.getsda = pluto_getsda;
-	pluto->i2c_bit.getscl = pluto_getscl;
-	pluto->i2c_bit.udelay = 10;
-	pluto->i2c_bit.timeout = 10;
-
-	/* Raise SCL and SDA */
-	pluto_setsda(pluto, 1);
-	pluto_setscl(pluto, 1);
-
-	ret = i2c_bit_add_bus(&pluto->i2c_adap);
-	if (ret < 0)
-		goto err_pluto_hw_exit;
-
-	/* dvb */
-	ret = dvb_register_adapter(&pluto->dvb_adapter, DRIVER_NAME,
-				   THIS_MODULE, &pdev->dev, adapter_nr);
-	if (ret < 0)
-		goto err_i2c_del_adapter;
-
-	dvb_adapter = &pluto->dvb_adapter;
-
-	pluto_read_rev(pluto);
-	pluto_read_serial(pluto);
-	pluto_read_mac(pluto, dvb_adapter->proposed_mac);
-
-	dvbdemux = &pluto->demux;
-	dvbdemux->filternum = 256;
-	dvbdemux->feednum = 256;
-	dvbdemux->start_feed = pluto_start_feed;
-	dvbdemux->stop_feed = pluto_stop_feed;
-	dvbdemux->dmx.capabilities = (DMX_TS_FILTERING |
-			DMX_SECTION_FILTERING | DMX_MEMORY_BASED_FILTERING);
-	ret = dvb_dmx_init(dvbdemux);
-	if (ret < 0)
-		goto err_dvb_unregister_adapter;
-
-	dmx = &dvbdemux->dmx;
-
-	pluto->hw_frontend.source = DMX_FRONTEND_0;
-	pluto->mem_frontend.source = DMX_MEMORY_FE;
-	pluto->dmxdev.filternum = NHWFILTERS;
-	pluto->dmxdev.demux = dmx;
-
-	ret = dvb_dmxdev_init(&pluto->dmxdev, dvb_adapter);
-	if (ret < 0)
-		goto err_dvb_dmx_release;
-
-	ret = dmx->add_frontend(dmx, &pluto->hw_frontend);
-	if (ret < 0)
-		goto err_dvb_dmxdev_release;
-
-	ret = dmx->add_frontend(dmx, &pluto->mem_frontend);
-	if (ret < 0)
-		goto err_remove_hw_frontend;
-
-	ret = dmx->connect_frontend(dmx, &pluto->hw_frontend);
-	if (ret < 0)
-		goto err_remove_mem_frontend;
-
-	ret = frontend_init(pluto);
-	if (ret < 0)
-		goto err_disconnect_frontend;
-
-	dvb_net_init(dvb_adapter, &pluto->dvbnet, dmx);
-out:
-	return ret;
-
-err_disconnect_frontend:
-	dmx->disconnect_frontend(dmx);
-err_remove_mem_frontend:
-	dmx->remove_frontend(dmx, &pluto->mem_frontend);
-err_remove_hw_frontend:
-	dmx->remove_frontend(dmx, &pluto->hw_frontend);
-err_dvb_dmxdev_release:
-	dvb_dmxdev_release(&pluto->dmxdev);
-err_dvb_dmx_release:
-	dvb_dmx_release(dvbdemux);
-err_dvb_unregister_adapter:
-	dvb_unregister_adapter(dvb_adapter);
-err_i2c_del_adapter:
-	i2c_del_adapter(&pluto->i2c_adap);
-err_pluto_hw_exit:
-	pluto_hw_exit(pluto);
-err_free_irq:
-	free_irq(pdev->irq, pluto);
-err_pci_iounmap:
-	pci_iounmap(pdev, pluto->io_mem);
-err_pci_release_regions:
-	pci_release_regions(pdev);
-err_pci_disable_device:
-	pci_disable_device(pdev);
-err_kfree:
-	pci_set_drvdata(pdev, NULL);
-	kfree(pluto);
-	goto out;
-}
-
-static void __devexit pluto2_remove(struct pci_dev *pdev)
-{
-	struct pluto *pluto = pci_get_drvdata(pdev);
-	struct dvb_adapter *dvb_adapter = &pluto->dvb_adapter;
-	struct dvb_demux *dvbdemux = &pluto->demux;
-	struct dmx_demux *dmx = &dvbdemux->dmx;
-
-	dmx->close(dmx);
-	dvb_net_release(&pluto->dvbnet);
-	if (pluto->fe)
-		dvb_unregister_frontend(pluto->fe);
-
-	dmx->disconnect_frontend(dmx);
-	dmx->remove_frontend(dmx, &pluto->mem_frontend);
-	dmx->remove_frontend(dmx, &pluto->hw_frontend);
-	dvb_dmxdev_release(&pluto->dmxdev);
-	dvb_dmx_release(dvbdemux);
-	dvb_unregister_adapter(dvb_adapter);
-	i2c_del_adapter(&pluto->i2c_adap);
-	pluto_hw_exit(pluto);
-	free_irq(pdev->irq, pluto);
-	pci_iounmap(pdev, pluto->io_mem);
-	pci_release_regions(pdev);
-	pci_disable_device(pdev);
-	pci_set_drvdata(pdev, NULL);
-	kfree(pluto);
-}
-
-#ifndef PCI_VENDOR_ID_SCM
-#define PCI_VENDOR_ID_SCM	0x0432
-#endif
-#ifndef PCI_DEVICE_ID_PLUTO2
-#define PCI_DEVICE_ID_PLUTO2	0x0001
-#endif
-
-static struct pci_device_id pluto2_id_table[] __devinitdata = {
-	{
-		.vendor = PCI_VENDOR_ID_SCM,
-		.device = PCI_DEVICE_ID_PLUTO2,
-		.subvendor = PCI_ANY_ID,
-		.subdevice = PCI_ANY_ID,
-	}, {
-		/* empty */
-	},
-};
-
-MODULE_DEVICE_TABLE(pci, pluto2_id_table);
-
-static struct pci_driver pluto2_driver = {
-	.name = DRIVER_NAME,
-	.id_table = pluto2_id_table,
-	.probe = pluto2_probe,
-	.remove = __devexit_p(pluto2_remove),
-};
-
-static int __init pluto2_init(void)
-{
-	return pci_register_driver(&pluto2_driver);
-}
-
-static void __exit pluto2_exit(void)
-{
-	pci_unregister_driver(&pluto2_driver);
-}
-
-module_init(pluto2_init);
-module_exit(pluto2_exit);
-
-MODULE_AUTHOR("Andreas Oberritter <obi@linuxtv.org>");
-MODULE_DESCRIPTION("Pluto2 driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/pt1/Kconfig b/drivers/media/dvb/pt1/Kconfig
deleted file mode 100644
index 24501d5..0000000
--- a/drivers/media/dvb/pt1/Kconfig
+++ /dev/null
@@ -1,12 +0,0 @@
-config DVB_PT1
-	tristate "PT1 cards"
-	depends on DVB_CORE && PCI && I2C
-	help
-	  Support for Earthsoft PT1 PCI cards.
-
-	  Since these cards have no MPEG decoder onboard, they transmit
-	  only compressed MPEG data over the PCI bus, so you need
-	  an external software decoder to watch TV on your computer.
-
-	  Say Y or M if you own such a device and want to use it.
-
diff --git a/drivers/media/dvb/pt1/Makefile b/drivers/media/dvb/pt1/Makefile
deleted file mode 100644
index d80d8e8..0000000
--- a/drivers/media/dvb/pt1/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-earth-pt1-objs := pt1.o va1j5jf8007s.o va1j5jf8007t.o
-
-obj-$(CONFIG_DVB_PT1) += earth-pt1.o
-
-ccflags-y += -Idrivers/media/dvb/dvb-core -Idrivers/media/dvb/frontends
diff --git a/drivers/media/dvb/pt1/pt1.c b/drivers/media/dvb/pt1/pt1.c
deleted file mode 100644
index 15b35c4..0000000
--- a/drivers/media/dvb/pt1/pt1.c
+++ /dev/null
@@ -1,1246 +0,0 @@
-/*
- * driver for Earthsoft PT1/PT2
- *
- * Copyright (C) 2009 HIRANO Takahito <hiranotaka@zng.info>
- *
- * based on pt1dvr - http://pt1dvr.sourceforge.jp/
- * 	by Tomoaki Ishikawa <tomy@users.sourceforge.jp>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/pci.h>
-#include <linux/kthread.h>
-#include <linux/freezer.h>
-#include <linux/ratelimit.h>
-
-#include "dvbdev.h"
-#include "dvb_demux.h"
-#include "dmxdev.h"
-#include "dvb_net.h"
-#include "dvb_frontend.h"
-
-#include "va1j5jf8007t.h"
-#include "va1j5jf8007s.h"
-
-#define DRIVER_NAME "earth-pt1"
-
-#define PT1_PAGE_SHIFT 12
-#define PT1_PAGE_SIZE (1 << PT1_PAGE_SHIFT)
-#define PT1_NR_UPACKETS 1024
-#define PT1_NR_BUFS 511
-
-struct pt1_buffer_page {
-	__le32 upackets[PT1_NR_UPACKETS];
-};
-
-struct pt1_table_page {
-	__le32 next_pfn;
-	__le32 buf_pfns[PT1_NR_BUFS];
-};
-
-struct pt1_buffer {
-	struct pt1_buffer_page *page;
-	dma_addr_t addr;
-};
-
-struct pt1_table {
-	struct pt1_table_page *page;
-	dma_addr_t addr;
-	struct pt1_buffer bufs[PT1_NR_BUFS];
-};
-
-#define PT1_NR_ADAPS 4
-
-struct pt1_adapter;
-
-struct pt1 {
-	struct pci_dev *pdev;
-	void __iomem *regs;
-	struct i2c_adapter i2c_adap;
-	int i2c_running;
-	struct pt1_adapter *adaps[PT1_NR_ADAPS];
-	struct pt1_table *tables;
-	struct task_struct *kthread;
-	int table_index;
-	int buf_index;
-
-	struct mutex lock;
-	int power;
-	int reset;
-};
-
-struct pt1_adapter {
-	struct pt1 *pt1;
-	int index;
-
-	u8 *buf;
-	int upacket_count;
-	int packet_count;
-	int st_count;
-
-	struct dvb_adapter adap;
-	struct dvb_demux demux;
-	int users;
-	struct dmxdev dmxdev;
-	struct dvb_frontend *fe;
-	int (*orig_set_voltage)(struct dvb_frontend *fe,
-				fe_sec_voltage_t voltage);
-	int (*orig_sleep)(struct dvb_frontend *fe);
-	int (*orig_init)(struct dvb_frontend *fe);
-
-	fe_sec_voltage_t voltage;
-	int sleep;
-};
-
-#define pt1_printk(level, pt1, format, arg...)	\
-	dev_printk(level, &(pt1)->pdev->dev, format, ##arg)
-
-static void pt1_write_reg(struct pt1 *pt1, int reg, u32 data)
-{
-	writel(data, pt1->regs + reg * 4);
-}
-
-static u32 pt1_read_reg(struct pt1 *pt1, int reg)
-{
-	return readl(pt1->regs + reg * 4);
-}
-
-static int pt1_nr_tables = 8;
-module_param_named(nr_tables, pt1_nr_tables, int, 0);
-
-static void pt1_increment_table_count(struct pt1 *pt1)
-{
-	pt1_write_reg(pt1, 0, 0x00000020);
-}
-
-static void pt1_init_table_count(struct pt1 *pt1)
-{
-	pt1_write_reg(pt1, 0, 0x00000010);
-}
-
-static void pt1_register_tables(struct pt1 *pt1, u32 first_pfn)
-{
-	pt1_write_reg(pt1, 5, first_pfn);
-	pt1_write_reg(pt1, 0, 0x0c000040);
-}
-
-static void pt1_unregister_tables(struct pt1 *pt1)
-{
-	pt1_write_reg(pt1, 0, 0x08080000);
-}
-
-static int pt1_sync(struct pt1 *pt1)
-{
-	int i;
-	for (i = 0; i < 57; i++) {
-		if (pt1_read_reg(pt1, 0) & 0x20000000)
-			return 0;
-		pt1_write_reg(pt1, 0, 0x00000008);
-	}
-	pt1_printk(KERN_ERR, pt1, "could not sync\n");
-	return -EIO;
-}
-
-static u64 pt1_identify(struct pt1 *pt1)
-{
-	int i;
-	u64 id;
-	id = 0;
-	for (i = 0; i < 57; i++) {
-		id |= (u64)(pt1_read_reg(pt1, 0) >> 30 & 1) << i;
-		pt1_write_reg(pt1, 0, 0x00000008);
-	}
-	return id;
-}
-
-static int pt1_unlock(struct pt1 *pt1)
-{
-	int i;
-	pt1_write_reg(pt1, 0, 0x00000008);
-	for (i = 0; i < 3; i++) {
-		if (pt1_read_reg(pt1, 0) & 0x80000000)
-			return 0;
-		schedule_timeout_uninterruptible((HZ + 999) / 1000);
-	}
-	pt1_printk(KERN_ERR, pt1, "could not unlock\n");
-	return -EIO;
-}
-
-static int pt1_reset_pci(struct pt1 *pt1)
-{
-	int i;
-	pt1_write_reg(pt1, 0, 0x01010000);
-	pt1_write_reg(pt1, 0, 0x01000000);
-	for (i = 0; i < 10; i++) {
-		if (pt1_read_reg(pt1, 0) & 0x00000001)
-			return 0;
-		schedule_timeout_uninterruptible((HZ + 999) / 1000);
-	}
-	pt1_printk(KERN_ERR, pt1, "could not reset PCI\n");
-	return -EIO;
-}
-
-static int pt1_reset_ram(struct pt1 *pt1)
-{
-	int i;
-	pt1_write_reg(pt1, 0, 0x02020000);
-	pt1_write_reg(pt1, 0, 0x02000000);
-	for (i = 0; i < 10; i++) {
-		if (pt1_read_reg(pt1, 0) & 0x00000002)
-			return 0;
-		schedule_timeout_uninterruptible((HZ + 999) / 1000);
-	}
-	pt1_printk(KERN_ERR, pt1, "could not reset RAM\n");
-	return -EIO;
-}
-
-static int pt1_do_enable_ram(struct pt1 *pt1)
-{
-	int i, j;
-	u32 status;
-	status = pt1_read_reg(pt1, 0) & 0x00000004;
-	pt1_write_reg(pt1, 0, 0x00000002);
-	for (i = 0; i < 10; i++) {
-		for (j = 0; j < 1024; j++) {
-			if ((pt1_read_reg(pt1, 0) & 0x00000004) != status)
-				return 0;
-		}
-		schedule_timeout_uninterruptible((HZ + 999) / 1000);
-	}
-	pt1_printk(KERN_ERR, pt1, "could not enable RAM\n");
-	return -EIO;
-}
-
-static int pt1_enable_ram(struct pt1 *pt1)
-{
-	int i, ret;
-	int phase;
-	schedule_timeout_uninterruptible((HZ + 999) / 1000);
-	phase = pt1->pdev->device == 0x211a ? 128 : 166;
-	for (i = 0; i < phase; i++) {
-		ret = pt1_do_enable_ram(pt1);
-		if (ret < 0)
-			return ret;
-	}
-	return 0;
-}
-
-static void pt1_disable_ram(struct pt1 *pt1)
-{
-	pt1_write_reg(pt1, 0, 0x0b0b0000);
-}
-
-static void pt1_set_stream(struct pt1 *pt1, int index, int enabled)
-{
-	pt1_write_reg(pt1, 2, 1 << (index + 8) | enabled << index);
-}
-
-static void pt1_init_streams(struct pt1 *pt1)
-{
-	int i;
-	for (i = 0; i < PT1_NR_ADAPS; i++)
-		pt1_set_stream(pt1, i, 0);
-}
-
-static int pt1_filter(struct pt1 *pt1, struct pt1_buffer_page *page)
-{
-	u32 upacket;
-	int i;
-	int index;
-	struct pt1_adapter *adap;
-	int offset;
-	u8 *buf;
-	int sc;
-
-	if (!page->upackets[PT1_NR_UPACKETS - 1])
-		return 0;
-
-	for (i = 0; i < PT1_NR_UPACKETS; i++) {
-		upacket = le32_to_cpu(page->upackets[i]);
-		index = (upacket >> 29) - 1;
-		if (index < 0 || index >=  PT1_NR_ADAPS)
-			continue;
-
-		adap = pt1->adaps[index];
-		if (upacket >> 25 & 1)
-			adap->upacket_count = 0;
-		else if (!adap->upacket_count)
-			continue;
-
-		if (upacket >> 24 & 1)
-			printk_ratelimited(KERN_INFO "earth-pt1: device "
-				"buffer overflowing. table[%d] buf[%d]\n",
-				pt1->table_index, pt1->buf_index);
-		sc = upacket >> 26 & 0x7;
-		if (adap->st_count != -1 && sc != ((adap->st_count + 1) & 0x7))
-			printk_ratelimited(KERN_INFO "earth-pt1: data loss"
-				" in streamID(adapter)[%d]\n", index);
-		adap->st_count = sc;
-
-		buf = adap->buf;
-		offset = adap->packet_count * 188 + adap->upacket_count * 3;
-		buf[offset] = upacket >> 16;
-		buf[offset + 1] = upacket >> 8;
-		if (adap->upacket_count != 62)
-			buf[offset + 2] = upacket;
-
-		if (++adap->upacket_count >= 63) {
-			adap->upacket_count = 0;
-			if (++adap->packet_count >= 21) {
-				dvb_dmx_swfilter_packets(&adap->demux, buf, 21);
-				adap->packet_count = 0;
-			}
-		}
-	}
-
-	page->upackets[PT1_NR_UPACKETS - 1] = 0;
-	return 1;
-}
-
-static int pt1_thread(void *data)
-{
-	struct pt1 *pt1;
-	struct pt1_buffer_page *page;
-
-	pt1 = data;
-	set_freezable();
-
-	while (!kthread_should_stop()) {
-		try_to_freeze();
-
-		page = pt1->tables[pt1->table_index].bufs[pt1->buf_index].page;
-		if (!pt1_filter(pt1, page)) {
-			schedule_timeout_interruptible((HZ + 999) / 1000);
-			continue;
-		}
-
-		if (++pt1->buf_index >= PT1_NR_BUFS) {
-			pt1_increment_table_count(pt1);
-			pt1->buf_index = 0;
-			if (++pt1->table_index >= pt1_nr_tables)
-				pt1->table_index = 0;
-		}
-	}
-
-	return 0;
-}
-
-static void pt1_free_page(struct pt1 *pt1, void *page, dma_addr_t addr)
-{
-	dma_free_coherent(&pt1->pdev->dev, PT1_PAGE_SIZE, page, addr);
-}
-
-static void *pt1_alloc_page(struct pt1 *pt1, dma_addr_t *addrp, u32 *pfnp)
-{
-	void *page;
-	dma_addr_t addr;
-
-	page = dma_alloc_coherent(&pt1->pdev->dev, PT1_PAGE_SIZE, &addr,
-				  GFP_KERNEL);
-	if (page == NULL)
-		return NULL;
-
-	BUG_ON(addr & (PT1_PAGE_SIZE - 1));
-	BUG_ON(addr >> PT1_PAGE_SHIFT >> 31 >> 1);
-
-	*addrp = addr;
-	*pfnp = addr >> PT1_PAGE_SHIFT;
-	return page;
-}
-
-static void pt1_cleanup_buffer(struct pt1 *pt1, struct pt1_buffer *buf)
-{
-	pt1_free_page(pt1, buf->page, buf->addr);
-}
-
-static int
-pt1_init_buffer(struct pt1 *pt1, struct pt1_buffer *buf,  u32 *pfnp)
-{
-	struct pt1_buffer_page *page;
-	dma_addr_t addr;
-
-	page = pt1_alloc_page(pt1, &addr, pfnp);
-	if (page == NULL)
-		return -ENOMEM;
-
-	page->upackets[PT1_NR_UPACKETS - 1] = 0;
-
-	buf->page = page;
-	buf->addr = addr;
-	return 0;
-}
-
-static void pt1_cleanup_table(struct pt1 *pt1, struct pt1_table *table)
-{
-	int i;
-
-	for (i = 0; i < PT1_NR_BUFS; i++)
-		pt1_cleanup_buffer(pt1, &table->bufs[i]);
-
-	pt1_free_page(pt1, table->page, table->addr);
-}
-
-static int
-pt1_init_table(struct pt1 *pt1, struct pt1_table *table, u32 *pfnp)
-{
-	struct pt1_table_page *page;
-	dma_addr_t addr;
-	int i, ret;
-	u32 buf_pfn;
-
-	page = pt1_alloc_page(pt1, &addr, pfnp);
-	if (page == NULL)
-		return -ENOMEM;
-
-	for (i = 0; i < PT1_NR_BUFS; i++) {
-		ret = pt1_init_buffer(pt1, &table->bufs[i], &buf_pfn);
-		if (ret < 0)
-			goto err;
-
-		page->buf_pfns[i] = cpu_to_le32(buf_pfn);
-	}
-
-	pt1_increment_table_count(pt1);
-	table->page = page;
-	table->addr = addr;
-	return 0;
-
-err:
-	while (i--)
-		pt1_cleanup_buffer(pt1, &table->bufs[i]);
-
-	pt1_free_page(pt1, page, addr);
-	return ret;
-}
-
-static void pt1_cleanup_tables(struct pt1 *pt1)
-{
-	struct pt1_table *tables;
-	int i;
-
-	tables = pt1->tables;
-	pt1_unregister_tables(pt1);
-
-	for (i = 0; i < pt1_nr_tables; i++)
-		pt1_cleanup_table(pt1, &tables[i]);
-
-	vfree(tables);
-}
-
-static int pt1_init_tables(struct pt1 *pt1)
-{
-	struct pt1_table *tables;
-	int i, ret;
-	u32 first_pfn, pfn;
-
-	tables = vmalloc(sizeof(struct pt1_table) * pt1_nr_tables);
-	if (tables == NULL)
-		return -ENOMEM;
-
-	pt1_init_table_count(pt1);
-
-	i = 0;
-	if (pt1_nr_tables) {
-		ret = pt1_init_table(pt1, &tables[0], &first_pfn);
-		if (ret)
-			goto err;
-		i++;
-	}
-
-	while (i < pt1_nr_tables) {
-		ret = pt1_init_table(pt1, &tables[i], &pfn);
-		if (ret)
-			goto err;
-		tables[i - 1].page->next_pfn = cpu_to_le32(pfn);
-		i++;
-	}
-
-	tables[pt1_nr_tables - 1].page->next_pfn = cpu_to_le32(first_pfn);
-
-	pt1_register_tables(pt1, first_pfn);
-	pt1->tables = tables;
-	return 0;
-
-err:
-	while (i--)
-		pt1_cleanup_table(pt1, &tables[i]);
-
-	vfree(tables);
-	return ret;
-}
-
-static int pt1_start_polling(struct pt1 *pt1)
-{
-	int ret = 0;
-
-	mutex_lock(&pt1->lock);
-	if (!pt1->kthread) {
-		pt1->kthread = kthread_run(pt1_thread, pt1, "earth-pt1");
-		if (IS_ERR(pt1->kthread)) {
-			ret = PTR_ERR(pt1->kthread);
-			pt1->kthread = NULL;
-		}
-	}
-	mutex_unlock(&pt1->lock);
-	return ret;
-}
-
-static int pt1_start_feed(struct dvb_demux_feed *feed)
-{
-	struct pt1_adapter *adap;
-	adap = container_of(feed->demux, struct pt1_adapter, demux);
-	if (!adap->users++) {
-		int ret;
-
-		ret = pt1_start_polling(adap->pt1);
-		if (ret)
-			return ret;
-		pt1_set_stream(adap->pt1, adap->index, 1);
-	}
-	return 0;
-}
-
-static void pt1_stop_polling(struct pt1 *pt1)
-{
-	int i, count;
-
-	mutex_lock(&pt1->lock);
-	for (i = 0, count = 0; i < PT1_NR_ADAPS; i++)
-		count += pt1->adaps[i]->users;
-
-	if (count == 0 && pt1->kthread) {
-		kthread_stop(pt1->kthread);
-		pt1->kthread = NULL;
-	}
-	mutex_unlock(&pt1->lock);
-}
-
-static int pt1_stop_feed(struct dvb_demux_feed *feed)
-{
-	struct pt1_adapter *adap;
-	adap = container_of(feed->demux, struct pt1_adapter, demux);
-	if (!--adap->users) {
-		pt1_set_stream(adap->pt1, adap->index, 0);
-		pt1_stop_polling(adap->pt1);
-	}
-	return 0;
-}
-
-static void
-pt1_update_power(struct pt1 *pt1)
-{
-	int bits;
-	int i;
-	struct pt1_adapter *adap;
-	static const int sleep_bits[] = {
-		1 << 4,
-		1 << 6 | 1 << 7,
-		1 << 5,
-		1 << 6 | 1 << 8,
-	};
-
-	bits = pt1->power | !pt1->reset << 3;
-	mutex_lock(&pt1->lock);
-	for (i = 0; i < PT1_NR_ADAPS; i++) {
-		adap = pt1->adaps[i];
-		switch (adap->voltage) {
-		case SEC_VOLTAGE_13: /* actually 11V */
-			bits |= 1 << 1;
-			break;
-		case SEC_VOLTAGE_18: /* actually 15V */
-			bits |= 1 << 1 | 1 << 2;
-			break;
-		default:
-			break;
-		}
-
-		/* XXX: The bits should be changed depending on adap->sleep. */
-		bits |= sleep_bits[i];
-	}
-	pt1_write_reg(pt1, 1, bits);
-	mutex_unlock(&pt1->lock);
-}
-
-static int pt1_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
-{
-	struct pt1_adapter *adap;
-
-	adap = container_of(fe->dvb, struct pt1_adapter, adap);
-	adap->voltage = voltage;
-	pt1_update_power(adap->pt1);
-
-	if (adap->orig_set_voltage)
-		return adap->orig_set_voltage(fe, voltage);
-	else
-		return 0;
-}
-
-static int pt1_sleep(struct dvb_frontend *fe)
-{
-	struct pt1_adapter *adap;
-
-	adap = container_of(fe->dvb, struct pt1_adapter, adap);
-	adap->sleep = 1;
-	pt1_update_power(adap->pt1);
-
-	if (adap->orig_sleep)
-		return adap->orig_sleep(fe);
-	else
-		return 0;
-}
-
-static int pt1_wakeup(struct dvb_frontend *fe)
-{
-	struct pt1_adapter *adap;
-
-	adap = container_of(fe->dvb, struct pt1_adapter, adap);
-	adap->sleep = 0;
-	pt1_update_power(adap->pt1);
-	schedule_timeout_uninterruptible((HZ + 999) / 1000);
-
-	if (adap->orig_init)
-		return adap->orig_init(fe);
-	else
-		return 0;
-}
-
-static void pt1_free_adapter(struct pt1_adapter *adap)
-{
-	adap->demux.dmx.close(&adap->demux.dmx);
-	dvb_dmxdev_release(&adap->dmxdev);
-	dvb_dmx_release(&adap->demux);
-	dvb_unregister_adapter(&adap->adap);
-	free_page((unsigned long)adap->buf);
-	kfree(adap);
-}
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-static struct pt1_adapter *
-pt1_alloc_adapter(struct pt1 *pt1)
-{
-	struct pt1_adapter *adap;
-	void *buf;
-	struct dvb_adapter *dvb_adap;
-	struct dvb_demux *demux;
-	struct dmxdev *dmxdev;
-	int ret;
-
-	adap = kzalloc(sizeof(struct pt1_adapter), GFP_KERNEL);
-	if (!adap) {
-		ret = -ENOMEM;
-		goto err;
-	}
-
-	adap->pt1 = pt1;
-
-	adap->voltage = SEC_VOLTAGE_OFF;
-	adap->sleep = 1;
-
-	buf = (u8 *)__get_free_page(GFP_KERNEL);
-	if (!buf) {
-		ret = -ENOMEM;
-		goto err_kfree;
-	}
-
-	adap->buf = buf;
-	adap->upacket_count = 0;
-	adap->packet_count = 0;
-	adap->st_count = -1;
-
-	dvb_adap = &adap->adap;
-	dvb_adap->priv = adap;
-	ret = dvb_register_adapter(dvb_adap, DRIVER_NAME, THIS_MODULE,
-				   &pt1->pdev->dev, adapter_nr);
-	if (ret < 0)
-		goto err_free_page;
-
-	demux = &adap->demux;
-	demux->dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING;
-	demux->priv = adap;
-	demux->feednum = 256;
-	demux->filternum = 256;
-	demux->start_feed = pt1_start_feed;
-	demux->stop_feed = pt1_stop_feed;
-	demux->write_to_decoder = NULL;
-	ret = dvb_dmx_init(demux);
-	if (ret < 0)
-		goto err_unregister_adapter;
-
-	dmxdev = &adap->dmxdev;
-	dmxdev->filternum = 256;
-	dmxdev->demux = &demux->dmx;
-	dmxdev->capabilities = 0;
-	ret = dvb_dmxdev_init(dmxdev, dvb_adap);
-	if (ret < 0)
-		goto err_dmx_release;
-
-	return adap;
-
-err_dmx_release:
-	dvb_dmx_release(demux);
-err_unregister_adapter:
-	dvb_unregister_adapter(dvb_adap);
-err_free_page:
-	free_page((unsigned long)buf);
-err_kfree:
-	kfree(adap);
-err:
-	return ERR_PTR(ret);
-}
-
-static void pt1_cleanup_adapters(struct pt1 *pt1)
-{
-	int i;
-	for (i = 0; i < PT1_NR_ADAPS; i++)
-		pt1_free_adapter(pt1->adaps[i]);
-}
-
-static int pt1_init_adapters(struct pt1 *pt1)
-{
-	int i;
-	struct pt1_adapter *adap;
-	int ret;
-
-	for (i = 0; i < PT1_NR_ADAPS; i++) {
-		adap = pt1_alloc_adapter(pt1);
-		if (IS_ERR(adap)) {
-			ret = PTR_ERR(adap);
-			goto err;
-		}
-
-		adap->index = i;
-		pt1->adaps[i] = adap;
-	}
-	return 0;
-
-err:
-	while (i--)
-		pt1_free_adapter(pt1->adaps[i]);
-
-	return ret;
-}
-
-static void pt1_cleanup_frontend(struct pt1_adapter *adap)
-{
-	dvb_unregister_frontend(adap->fe);
-}
-
-static int pt1_init_frontend(struct pt1_adapter *adap, struct dvb_frontend *fe)
-{
-	int ret;
-
-	adap->orig_set_voltage = fe->ops.set_voltage;
-	adap->orig_sleep = fe->ops.sleep;
-	adap->orig_init = fe->ops.init;
-	fe->ops.set_voltage = pt1_set_voltage;
-	fe->ops.sleep = pt1_sleep;
-	fe->ops.init = pt1_wakeup;
-
-	ret = dvb_register_frontend(&adap->adap, fe);
-	if (ret < 0)
-		return ret;
-
-	adap->fe = fe;
-	return 0;
-}
-
-static void pt1_cleanup_frontends(struct pt1 *pt1)
-{
-	int i;
-	for (i = 0; i < PT1_NR_ADAPS; i++)
-		pt1_cleanup_frontend(pt1->adaps[i]);
-}
-
-struct pt1_config {
-	struct va1j5jf8007s_config va1j5jf8007s_config;
-	struct va1j5jf8007t_config va1j5jf8007t_config;
-};
-
-static const struct pt1_config pt1_configs[2] = {
-	{
-		{
-			.demod_address = 0x1b,
-			.frequency = VA1J5JF8007S_20MHZ,
-		},
-		{
-			.demod_address = 0x1a,
-			.frequency = VA1J5JF8007T_20MHZ,
-		},
-	}, {
-		{
-			.demod_address = 0x19,
-			.frequency = VA1J5JF8007S_20MHZ,
-		},
-		{
-			.demod_address = 0x18,
-			.frequency = VA1J5JF8007T_20MHZ,
-		},
-	},
-};
-
-static const struct pt1_config pt2_configs[2] = {
-	{
-		{
-			.demod_address = 0x1b,
-			.frequency = VA1J5JF8007S_25MHZ,
-		},
-		{
-			.demod_address = 0x1a,
-			.frequency = VA1J5JF8007T_25MHZ,
-		},
-	}, {
-		{
-			.demod_address = 0x19,
-			.frequency = VA1J5JF8007S_25MHZ,
-		},
-		{
-			.demod_address = 0x18,
-			.frequency = VA1J5JF8007T_25MHZ,
-		},
-	},
-};
-
-static int pt1_init_frontends(struct pt1 *pt1)
-{
-	int i, j;
-	struct i2c_adapter *i2c_adap;
-	const struct pt1_config *configs, *config;
-	struct dvb_frontend *fe[4];
-	int ret;
-
-	i = 0;
-	j = 0;
-
-	i2c_adap = &pt1->i2c_adap;
-	configs = pt1->pdev->device == 0x211a ? pt1_configs : pt2_configs;
-	do {
-		config = &configs[i / 2];
-
-		fe[i] = va1j5jf8007s_attach(&config->va1j5jf8007s_config,
-					    i2c_adap);
-		if (!fe[i]) {
-			ret = -ENODEV; /* This does not sound nice... */
-			goto err;
-		}
-		i++;
-
-		fe[i] = va1j5jf8007t_attach(&config->va1j5jf8007t_config,
-					    i2c_adap);
-		if (!fe[i]) {
-			ret = -ENODEV;
-			goto err;
-		}
-		i++;
-
-		ret = va1j5jf8007s_prepare(fe[i - 2]);
-		if (ret < 0)
-			goto err;
-
-		ret = va1j5jf8007t_prepare(fe[i - 1]);
-		if (ret < 0)
-			goto err;
-
-	} while (i < 4);
-
-	do {
-		ret = pt1_init_frontend(pt1->adaps[j], fe[j]);
-		if (ret < 0)
-			goto err;
-	} while (++j < 4);
-
-	return 0;
-
-err:
-	while (i-- > j)
-		fe[i]->ops.release(fe[i]);
-
-	while (j--)
-		dvb_unregister_frontend(fe[j]);
-
-	return ret;
-}
-
-static void pt1_i2c_emit(struct pt1 *pt1, int addr, int busy, int read_enable,
-			 int clock, int data, int next_addr)
-{
-	pt1_write_reg(pt1, 4, addr << 18 | busy << 13 | read_enable << 12 |
-		      !clock << 11 | !data << 10 | next_addr);
-}
-
-static void pt1_i2c_write_bit(struct pt1 *pt1, int addr, int *addrp, int data)
-{
-	pt1_i2c_emit(pt1, addr,     1, 0, 0, data, addr + 1);
-	pt1_i2c_emit(pt1, addr + 1, 1, 0, 1, data, addr + 2);
-	pt1_i2c_emit(pt1, addr + 2, 1, 0, 0, data, addr + 3);
-	*addrp = addr + 3;
-}
-
-static void pt1_i2c_read_bit(struct pt1 *pt1, int addr, int *addrp)
-{
-	pt1_i2c_emit(pt1, addr,     1, 0, 0, 1, addr + 1);
-	pt1_i2c_emit(pt1, addr + 1, 1, 0, 1, 1, addr + 2);
-	pt1_i2c_emit(pt1, addr + 2, 1, 1, 1, 1, addr + 3);
-	pt1_i2c_emit(pt1, addr + 3, 1, 0, 0, 1, addr + 4);
-	*addrp = addr + 4;
-}
-
-static void pt1_i2c_write_byte(struct pt1 *pt1, int addr, int *addrp, int data)
-{
-	int i;
-	for (i = 0; i < 8; i++)
-		pt1_i2c_write_bit(pt1, addr, &addr, data >> (7 - i) & 1);
-	pt1_i2c_write_bit(pt1, addr, &addr, 1);
-	*addrp = addr;
-}
-
-static void pt1_i2c_read_byte(struct pt1 *pt1, int addr, int *addrp, int last)
-{
-	int i;
-	for (i = 0; i < 8; i++)
-		pt1_i2c_read_bit(pt1, addr, &addr);
-	pt1_i2c_write_bit(pt1, addr, &addr, last);
-	*addrp = addr;
-}
-
-static void pt1_i2c_prepare(struct pt1 *pt1, int addr, int *addrp)
-{
-	pt1_i2c_emit(pt1, addr,     1, 0, 1, 1, addr + 1);
-	pt1_i2c_emit(pt1, addr + 1, 1, 0, 1, 0, addr + 2);
-	pt1_i2c_emit(pt1, addr + 2, 1, 0, 0, 0, addr + 3);
-	*addrp = addr + 3;
-}
-
-static void
-pt1_i2c_write_msg(struct pt1 *pt1, int addr, int *addrp, struct i2c_msg *msg)
-{
-	int i;
-	pt1_i2c_prepare(pt1, addr, &addr);
-	pt1_i2c_write_byte(pt1, addr, &addr, msg->addr << 1);
-	for (i = 0; i < msg->len; i++)
-		pt1_i2c_write_byte(pt1, addr, &addr, msg->buf[i]);
-	*addrp = addr;
-}
-
-static void
-pt1_i2c_read_msg(struct pt1 *pt1, int addr, int *addrp, struct i2c_msg *msg)
-{
-	int i;
-	pt1_i2c_prepare(pt1, addr, &addr);
-	pt1_i2c_write_byte(pt1, addr, &addr, msg->addr << 1 | 1);
-	for (i = 0; i < msg->len; i++)
-		pt1_i2c_read_byte(pt1, addr, &addr, i == msg->len - 1);
-	*addrp = addr;
-}
-
-static int pt1_i2c_end(struct pt1 *pt1, int addr)
-{
-	pt1_i2c_emit(pt1, addr,     1, 0, 0, 0, addr + 1);
-	pt1_i2c_emit(pt1, addr + 1, 1, 0, 1, 0, addr + 2);
-	pt1_i2c_emit(pt1, addr + 2, 1, 0, 1, 1, 0);
-
-	pt1_write_reg(pt1, 0, 0x00000004);
-	do {
-		if (signal_pending(current))
-			return -EINTR;
-		schedule_timeout_interruptible((HZ + 999) / 1000);
-	} while (pt1_read_reg(pt1, 0) & 0x00000080);
-	return 0;
-}
-
-static void pt1_i2c_begin(struct pt1 *pt1, int *addrp)
-{
-	int addr;
-	addr = 0;
-
-	pt1_i2c_emit(pt1, addr,     0, 0, 1, 1, addr /* itself */);
-	addr = addr + 1;
-
-	if (!pt1->i2c_running) {
-		pt1_i2c_emit(pt1, addr,     1, 0, 1, 1, addr + 1);
-		pt1_i2c_emit(pt1, addr + 1, 1, 0, 1, 0, addr + 2);
-		addr = addr + 2;
-		pt1->i2c_running = 1;
-	}
-	*addrp = addr;
-}
-
-static int pt1_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
-{
-	struct pt1 *pt1;
-	int i;
-	struct i2c_msg *msg, *next_msg;
-	int addr, ret;
-	u16 len;
-	u32 word;
-
-	pt1 = i2c_get_adapdata(adap);
-
-	for (i = 0; i < num; i++) {
-		msg = &msgs[i];
-		if (msg->flags & I2C_M_RD)
-			return -ENOTSUPP;
-
-		if (i + 1 < num)
-			next_msg = &msgs[i + 1];
-		else
-			next_msg = NULL;
-
-		if (next_msg && next_msg->flags & I2C_M_RD) {
-			i++;
-
-			len = next_msg->len;
-			if (len > 4)
-				return -ENOTSUPP;
-
-			pt1_i2c_begin(pt1, &addr);
-			pt1_i2c_write_msg(pt1, addr, &addr, msg);
-			pt1_i2c_read_msg(pt1, addr, &addr, next_msg);
-			ret = pt1_i2c_end(pt1, addr);
-			if (ret < 0)
-				return ret;
-
-			word = pt1_read_reg(pt1, 2);
-			while (len--) {
-				next_msg->buf[len] = word;
-				word >>= 8;
-			}
-		} else {
-			pt1_i2c_begin(pt1, &addr);
-			pt1_i2c_write_msg(pt1, addr, &addr, msg);
-			ret = pt1_i2c_end(pt1, addr);
-			if (ret < 0)
-				return ret;
-		}
-	}
-
-	return num;
-}
-
-static u32 pt1_i2c_func(struct i2c_adapter *adap)
-{
-	return I2C_FUNC_I2C;
-}
-
-static const struct i2c_algorithm pt1_i2c_algo = {
-	.master_xfer = pt1_i2c_xfer,
-	.functionality = pt1_i2c_func,
-};
-
-static void pt1_i2c_wait(struct pt1 *pt1)
-{
-	int i;
-	for (i = 0; i < 128; i++)
-		pt1_i2c_emit(pt1, 0, 0, 0, 1, 1, 0);
-}
-
-static void pt1_i2c_init(struct pt1 *pt1)
-{
-	int i;
-	for (i = 0; i < 1024; i++)
-		pt1_i2c_emit(pt1, i, 0, 0, 1, 1, 0);
-}
-
-static void __devexit pt1_remove(struct pci_dev *pdev)
-{
-	struct pt1 *pt1;
-	void __iomem *regs;
-
-	pt1 = pci_get_drvdata(pdev);
-	regs = pt1->regs;
-
-	if (pt1->kthread)
-		kthread_stop(pt1->kthread);
-	pt1_cleanup_tables(pt1);
-	pt1_cleanup_frontends(pt1);
-	pt1_disable_ram(pt1);
-	pt1->power = 0;
-	pt1->reset = 1;
-	pt1_update_power(pt1);
-	pt1_cleanup_adapters(pt1);
-	i2c_del_adapter(&pt1->i2c_adap);
-	pci_set_drvdata(pdev, NULL);
-	kfree(pt1);
-	pci_iounmap(pdev, regs);
-	pci_release_regions(pdev);
-	pci_disable_device(pdev);
-}
-
-static int __devinit
-pt1_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
-{
-	int ret;
-	void __iomem *regs;
-	struct pt1 *pt1;
-	struct i2c_adapter *i2c_adap;
-
-	ret = pci_enable_device(pdev);
-	if (ret < 0)
-		goto err;
-
-	ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
-	if (ret < 0)
-		goto err_pci_disable_device;
-
-	pci_set_master(pdev);
-
-	ret = pci_request_regions(pdev, DRIVER_NAME);
-	if (ret < 0)
-		goto err_pci_disable_device;
-
-	regs = pci_iomap(pdev, 0, 0);
-	if (!regs) {
-		ret = -EIO;
-		goto err_pci_release_regions;
-	}
-
-	pt1 = kzalloc(sizeof(struct pt1), GFP_KERNEL);
-	if (!pt1) {
-		ret = -ENOMEM;
-		goto err_pci_iounmap;
-	}
-
-	mutex_init(&pt1->lock);
-	pt1->pdev = pdev;
-	pt1->regs = regs;
-	pci_set_drvdata(pdev, pt1);
-
-	ret = pt1_init_adapters(pt1);
-	if (ret < 0)
-		goto err_kfree;
-
-	mutex_init(&pt1->lock);
-
-	pt1->power = 0;
-	pt1->reset = 1;
-	pt1_update_power(pt1);
-
-	i2c_adap = &pt1->i2c_adap;
-	i2c_adap->algo = &pt1_i2c_algo;
-	i2c_adap->algo_data = NULL;
-	i2c_adap->dev.parent = &pdev->dev;
-	strcpy(i2c_adap->name, DRIVER_NAME);
-	i2c_set_adapdata(i2c_adap, pt1);
-	ret = i2c_add_adapter(i2c_adap);
-	if (ret < 0)
-		goto err_pt1_cleanup_adapters;
-
-	pt1_i2c_init(pt1);
-	pt1_i2c_wait(pt1);
-
-	ret = pt1_sync(pt1);
-	if (ret < 0)
-		goto err_i2c_del_adapter;
-
-	pt1_identify(pt1);
-
-	ret = pt1_unlock(pt1);
-	if (ret < 0)
-		goto err_i2c_del_adapter;
-
-	ret = pt1_reset_pci(pt1);
-	if (ret < 0)
-		goto err_i2c_del_adapter;
-
-	ret = pt1_reset_ram(pt1);
-	if (ret < 0)
-		goto err_i2c_del_adapter;
-
-	ret = pt1_enable_ram(pt1);
-	if (ret < 0)
-		goto err_i2c_del_adapter;
-
-	pt1_init_streams(pt1);
-
-	pt1->power = 1;
-	pt1_update_power(pt1);
-	schedule_timeout_uninterruptible((HZ + 49) / 50);
-
-	pt1->reset = 0;
-	pt1_update_power(pt1);
-	schedule_timeout_uninterruptible((HZ + 999) / 1000);
-
-	ret = pt1_init_frontends(pt1);
-	if (ret < 0)
-		goto err_pt1_disable_ram;
-
-	ret = pt1_init_tables(pt1);
-	if (ret < 0)
-		goto err_pt1_cleanup_frontends;
-
-	return 0;
-
-err_pt1_cleanup_frontends:
-	pt1_cleanup_frontends(pt1);
-err_pt1_disable_ram:
-	pt1_disable_ram(pt1);
-	pt1->power = 0;
-	pt1->reset = 1;
-	pt1_update_power(pt1);
-err_i2c_del_adapter:
-	i2c_del_adapter(i2c_adap);
-err_pt1_cleanup_adapters:
-	pt1_cleanup_adapters(pt1);
-err_kfree:
-	pci_set_drvdata(pdev, NULL);
-	kfree(pt1);
-err_pci_iounmap:
-	pci_iounmap(pdev, regs);
-err_pci_release_regions:
-	pci_release_regions(pdev);
-err_pci_disable_device:
-	pci_disable_device(pdev);
-err:
-	return ret;
-
-}
-
-static struct pci_device_id pt1_id_table[] = {
-	{ PCI_DEVICE(0x10ee, 0x211a) },
-	{ PCI_DEVICE(0x10ee, 0x222a) },
-	{ },
-};
-MODULE_DEVICE_TABLE(pci, pt1_id_table);
-
-static struct pci_driver pt1_driver = {
-	.name		= DRIVER_NAME,
-	.probe		= pt1_probe,
-	.remove		= __devexit_p(pt1_remove),
-	.id_table	= pt1_id_table,
-};
-
-
-static int __init pt1_init(void)
-{
-	return pci_register_driver(&pt1_driver);
-}
-
-
-static void __exit pt1_cleanup(void)
-{
-	pci_unregister_driver(&pt1_driver);
-}
-
-module_init(pt1_init);
-module_exit(pt1_cleanup);
-
-MODULE_AUTHOR("Takahito HIRANO <hiranotaka@zng.info>");
-MODULE_DESCRIPTION("Earthsoft PT1/PT2 Driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/pt1/va1j5jf8007s.c b/drivers/media/dvb/pt1/va1j5jf8007s.c
deleted file mode 100644
index d980dfb..0000000
--- a/drivers/media/dvb/pt1/va1j5jf8007s.c
+++ /dev/null
@@ -1,735 +0,0 @@
-/*
- * ISDB-S driver for VA1J5JF8007/VA1J5JF8011
- *
- * Copyright (C) 2009 HIRANO Takahito <hiranotaka@zng.info>
- *
- * based on pt1dvr - http://pt1dvr.sourceforge.jp/
- * 	by Tomoaki Ishikawa <tomy@users.sourceforge.jp>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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/slab.h>
-#include <linux/i2c.h>
-#include "dvb_frontend.h"
-#include "va1j5jf8007s.h"
-
-enum va1j5jf8007s_tune_state {
-	VA1J5JF8007S_IDLE,
-	VA1J5JF8007S_SET_FREQUENCY_1,
-	VA1J5JF8007S_SET_FREQUENCY_2,
-	VA1J5JF8007S_SET_FREQUENCY_3,
-	VA1J5JF8007S_CHECK_FREQUENCY,
-	VA1J5JF8007S_SET_MODULATION,
-	VA1J5JF8007S_CHECK_MODULATION,
-	VA1J5JF8007S_SET_TS_ID,
-	VA1J5JF8007S_CHECK_TS_ID,
-	VA1J5JF8007S_TRACK,
-};
-
-struct va1j5jf8007s_state {
-	const struct va1j5jf8007s_config *config;
-	struct i2c_adapter *adap;
-	struct dvb_frontend fe;
-	enum va1j5jf8007s_tune_state tune_state;
-};
-
-static int va1j5jf8007s_read_snr(struct dvb_frontend *fe, u16 *snr)
-{
-	struct va1j5jf8007s_state *state;
-	u8 addr;
-	int i;
-	u8 write_buf[1], read_buf[1];
-	struct i2c_msg msgs[2];
-	s32 word, x1, x2, x3, x4, x5, y;
-
-	state = fe->demodulator_priv;
-	addr = state->config->demod_address;
-
-	word = 0;
-	for (i = 0; i < 2; i++) {
-		write_buf[0] = 0xbc + i;
-
-		msgs[0].addr = addr;
-		msgs[0].flags = 0;
-		msgs[0].len = sizeof(write_buf);
-		msgs[0].buf = write_buf;
-
-		msgs[1].addr = addr;
-		msgs[1].flags = I2C_M_RD;
-		msgs[1].len = sizeof(read_buf);
-		msgs[1].buf = read_buf;
-
-		if (i2c_transfer(state->adap, msgs, 2) != 2)
-			return -EREMOTEIO;
-
-		word <<= 8;
-		word |= read_buf[0];
-	}
-
-	word -= 3000;
-	if (word < 0)
-		word = 0;
-
-	x1 = int_sqrt(word << 16) * ((15625ll << 21) / 1000000);
-	x2 = (s64)x1 * x1 >> 31;
-	x3 = (s64)x2 * x1 >> 31;
-	x4 = (s64)x2 * x2 >> 31;
-	x5 = (s64)x4 * x1 >> 31;
-
-	y = (58857ll << 23) / 1000;
-	y -= (s64)x1 * ((89565ll << 24) / 1000) >> 30;
-	y += (s64)x2 * ((88977ll << 24) / 1000) >> 28;
-	y -= (s64)x3 * ((50259ll << 25) / 1000) >> 27;
-	y += (s64)x4 * ((14341ll << 27) / 1000) >> 27;
-	y -= (s64)x5 * ((16346ll << 30) / 10000) >> 28;
-
-	*snr = y < 0 ? 0 : y >> 15;
-	return 0;
-}
-
-static int va1j5jf8007s_get_frontend_algo(struct dvb_frontend *fe)
-{
-	return DVBFE_ALGO_HW;
-}
-
-static int
-va1j5jf8007s_read_status(struct dvb_frontend *fe, fe_status_t *status)
-{
-	struct va1j5jf8007s_state *state;
-
-	state = fe->demodulator_priv;
-
-	switch (state->tune_state) {
-	case VA1J5JF8007S_IDLE:
-	case VA1J5JF8007S_SET_FREQUENCY_1:
-	case VA1J5JF8007S_SET_FREQUENCY_2:
-	case VA1J5JF8007S_SET_FREQUENCY_3:
-	case VA1J5JF8007S_CHECK_FREQUENCY:
-		*status = 0;
-		return 0;
-
-
-	case VA1J5JF8007S_SET_MODULATION:
-	case VA1J5JF8007S_CHECK_MODULATION:
-		*status |= FE_HAS_SIGNAL;
-		return 0;
-
-	case VA1J5JF8007S_SET_TS_ID:
-	case VA1J5JF8007S_CHECK_TS_ID:
-		*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER;
-		return 0;
-
-	case VA1J5JF8007S_TRACK:
-		*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_LOCK;
-		return 0;
-	}
-
-	BUG();
-}
-
-struct va1j5jf8007s_cb_map {
-	u32 frequency;
-	u8 cb;
-};
-
-static const struct va1j5jf8007s_cb_map va1j5jf8007s_cb_maps[] = {
-	{  986000, 0xb2 },
-	{ 1072000, 0xd2 },
-	{ 1154000, 0xe2 },
-	{ 1291000, 0x20 },
-	{ 1447000, 0x40 },
-	{ 1615000, 0x60 },
-	{ 1791000, 0x80 },
-	{ 1972000, 0xa0 },
-};
-
-static u8 va1j5jf8007s_lookup_cb(u32 frequency)
-{
-	int i;
-	const struct va1j5jf8007s_cb_map *map;
-
-	for (i = 0; i < ARRAY_SIZE(va1j5jf8007s_cb_maps); i++) {
-		map = &va1j5jf8007s_cb_maps[i];
-		if (frequency < map->frequency)
-			return map->cb;
-	}
-	return 0xc0;
-}
-
-static int va1j5jf8007s_set_frequency_1(struct va1j5jf8007s_state *state)
-{
-	u32 frequency;
-	u16 word;
-	u8 buf[6];
-	struct i2c_msg msg;
-
-	frequency = state->fe.dtv_property_cache.frequency;
-
-	word = (frequency + 500) / 1000;
-	if (frequency < 1072000)
-		word = (word << 1 & ~0x1f) | (word & 0x0f);
-
-	buf[0] = 0xfe;
-	buf[1] = 0xc0;
-	buf[2] = 0x40 | word >> 8;
-	buf[3] = word;
-	buf[4] = 0xe0;
-	buf[5] = va1j5jf8007s_lookup_cb(frequency);
-
-	msg.addr = state->config->demod_address;
-	msg.flags = 0;
-	msg.len = sizeof(buf);
-	msg.buf = buf;
-
-	if (i2c_transfer(state->adap, &msg, 1) != 1)
-		return -EREMOTEIO;
-
-	return 0;
-}
-
-static int va1j5jf8007s_set_frequency_2(struct va1j5jf8007s_state *state)
-{
-	u8 buf[3];
-	struct i2c_msg msg;
-
-	buf[0] = 0xfe;
-	buf[1] = 0xc0;
-	buf[2] = 0xe4;
-
-	msg.addr = state->config->demod_address;
-	msg.flags = 0;
-	msg.len = sizeof(buf);
-	msg.buf = buf;
-
-	if (i2c_transfer(state->adap, &msg, 1) != 1)
-		return -EREMOTEIO;
-
-	return 0;
-}
-
-static int va1j5jf8007s_set_frequency_3(struct va1j5jf8007s_state *state)
-{
-	u32 frequency;
-	u8 buf[4];
-	struct i2c_msg msg;
-
-	frequency = state->fe.dtv_property_cache.frequency;
-
-	buf[0] = 0xfe;
-	buf[1] = 0xc0;
-	buf[2] = 0xf4;
-	buf[3] = va1j5jf8007s_lookup_cb(frequency) | 0x4;
-
-	msg.addr = state->config->demod_address;
-	msg.flags = 0;
-	msg.len = sizeof(buf);
-	msg.buf = buf;
-
-	if (i2c_transfer(state->adap, &msg, 1) != 1)
-		return -EREMOTEIO;
-
-	return 0;
-}
-
-static int
-va1j5jf8007s_check_frequency(struct va1j5jf8007s_state *state, int *lock)
-{
-	u8 addr;
-	u8 write_buf[2], read_buf[1];
-	struct i2c_msg msgs[2];
-
-	addr = state->config->demod_address;
-
-	write_buf[0] = 0xfe;
-	write_buf[1] = 0xc1;
-
-	msgs[0].addr = addr;
-	msgs[0].flags = 0;
-	msgs[0].len = sizeof(write_buf);
-	msgs[0].buf = write_buf;
-
-	msgs[1].addr = addr;
-	msgs[1].flags = I2C_M_RD;
-	msgs[1].len = sizeof(read_buf);
-	msgs[1].buf = read_buf;
-
-	if (i2c_transfer(state->adap, msgs, 2) != 2)
-		return -EREMOTEIO;
-
-	*lock = read_buf[0] & 0x40;
-	return 0;
-}
-
-static int va1j5jf8007s_set_modulation(struct va1j5jf8007s_state *state)
-{
-	u8 buf[2];
-	struct i2c_msg msg;
-
-	buf[0] = 0x03;
-	buf[1] = 0x01;
-
-	msg.addr = state->config->demod_address;
-	msg.flags = 0;
-	msg.len = sizeof(buf);
-	msg.buf = buf;
-
-	if (i2c_transfer(state->adap, &msg, 1) != 1)
-		return -EREMOTEIO;
-
-	return 0;
-}
-
-static int
-va1j5jf8007s_check_modulation(struct va1j5jf8007s_state *state, int *lock)
-{
-	u8 addr;
-	u8 write_buf[1], read_buf[1];
-	struct i2c_msg msgs[2];
-
-	addr = state->config->demod_address;
-
-	write_buf[0] = 0xc3;
-
-	msgs[0].addr = addr;
-	msgs[0].flags = 0;
-	msgs[0].len = sizeof(write_buf);
-	msgs[0].buf = write_buf;
-
-	msgs[1].addr = addr;
-	msgs[1].flags = I2C_M_RD;
-	msgs[1].len = sizeof(read_buf);
-	msgs[1].buf = read_buf;
-
-	if (i2c_transfer(state->adap, msgs, 2) != 2)
-		return -EREMOTEIO;
-
-	*lock = !(read_buf[0] & 0x10);
-	return 0;
-}
-
-static int
-va1j5jf8007s_set_ts_id(struct va1j5jf8007s_state *state)
-{
-	u32 ts_id;
-	u8 buf[3];
-	struct i2c_msg msg;
-
-	ts_id = state->fe.dtv_property_cache.isdbs_ts_id;
-	if (!ts_id)
-		return 0;
-
-	buf[0] = 0x8f;
-	buf[1] = ts_id >> 8;
-	buf[2] = ts_id;
-
-	msg.addr = state->config->demod_address;
-	msg.flags = 0;
-	msg.len = sizeof(buf);
-	msg.buf = buf;
-
-	if (i2c_transfer(state->adap, &msg, 1) != 1)
-		return -EREMOTEIO;
-
-	return 0;
-}
-
-static int
-va1j5jf8007s_check_ts_id(struct va1j5jf8007s_state *state, int *lock)
-{
-	u8 addr;
-	u8 write_buf[1], read_buf[2];
-	struct i2c_msg msgs[2];
-	u32 ts_id;
-
-	ts_id = state->fe.dtv_property_cache.isdbs_ts_id;
-	if (!ts_id) {
-		*lock = 1;
-		return 0;
-	}
-
-	addr = state->config->demod_address;
-
-	write_buf[0] = 0xe6;
-
-	msgs[0].addr = addr;
-	msgs[0].flags = 0;
-	msgs[0].len = sizeof(write_buf);
-	msgs[0].buf = write_buf;
-
-	msgs[1].addr = addr;
-	msgs[1].flags = I2C_M_RD;
-	msgs[1].len = sizeof(read_buf);
-	msgs[1].buf = read_buf;
-
-	if (i2c_transfer(state->adap, msgs, 2) != 2)
-		return -EREMOTEIO;
-
-	*lock = (read_buf[0] << 8 | read_buf[1]) == ts_id;
-	return 0;
-}
-
-static int
-va1j5jf8007s_tune(struct dvb_frontend *fe,
-		  bool re_tune,
-		  unsigned int mode_flags,  unsigned int *delay,
-		  fe_status_t *status)
-{
-	struct va1j5jf8007s_state *state;
-	int ret;
-	int lock = 0;
-
-	state = fe->demodulator_priv;
-
-	if (re_tune)
-		state->tune_state = VA1J5JF8007S_SET_FREQUENCY_1;
-
-	switch (state->tune_state) {
-	case VA1J5JF8007S_IDLE:
-		*delay = 3 * HZ;
-		*status = 0;
-		return 0;
-
-	case VA1J5JF8007S_SET_FREQUENCY_1:
-		ret = va1j5jf8007s_set_frequency_1(state);
-		if (ret < 0)
-			return ret;
-
-		state->tune_state = VA1J5JF8007S_SET_FREQUENCY_2;
-		*delay = 0;
-		*status = 0;
-		return 0;
-
-	case VA1J5JF8007S_SET_FREQUENCY_2:
-		ret = va1j5jf8007s_set_frequency_2(state);
-		if (ret < 0)
-			return ret;
-
-		state->tune_state = VA1J5JF8007S_SET_FREQUENCY_3;
-		*delay = (HZ + 99) / 100;
-		*status = 0;
-		return 0;
-
-	case VA1J5JF8007S_SET_FREQUENCY_3:
-		ret = va1j5jf8007s_set_frequency_3(state);
-		if (ret < 0)
-			return ret;
-
-		state->tune_state = VA1J5JF8007S_CHECK_FREQUENCY;
-		*delay = 0;
-		*status = 0;
-		return 0;
-
-	case VA1J5JF8007S_CHECK_FREQUENCY:
-		ret = va1j5jf8007s_check_frequency(state, &lock);
-		if (ret < 0)
-			return ret;
-
-		if (!lock)  {
-			*delay = (HZ + 999) / 1000;
-			*status = 0;
-			return 0;
-		}
-
-		state->tune_state = VA1J5JF8007S_SET_MODULATION;
-		*delay = 0;
-		*status = FE_HAS_SIGNAL;
-		return 0;
-
-	case VA1J5JF8007S_SET_MODULATION:
-		ret = va1j5jf8007s_set_modulation(state);
-		if (ret < 0)
-			return ret;
-
-		state->tune_state = VA1J5JF8007S_CHECK_MODULATION;
-		*delay = 0;
-		*status = FE_HAS_SIGNAL;
-		return 0;
-
-	case VA1J5JF8007S_CHECK_MODULATION:
-		ret = va1j5jf8007s_check_modulation(state, &lock);
-		if (ret < 0)
-			return ret;
-
-		if (!lock)  {
-			*delay = (HZ + 49) / 50;
-			*status = FE_HAS_SIGNAL;
-			return 0;
-		}
-
-		state->tune_state = VA1J5JF8007S_SET_TS_ID;
-		*delay = 0;
-		*status = FE_HAS_SIGNAL | FE_HAS_CARRIER;
-		return 0;
-
-	case VA1J5JF8007S_SET_TS_ID:
-		ret = va1j5jf8007s_set_ts_id(state);
-		if (ret < 0)
-			return ret;
-
-		state->tune_state = VA1J5JF8007S_CHECK_TS_ID;
-		return 0;
-
-	case VA1J5JF8007S_CHECK_TS_ID:
-		ret = va1j5jf8007s_check_ts_id(state, &lock);
-		if (ret < 0)
-			return ret;
-
-		if (!lock)  {
-			*delay = (HZ + 99) / 100;
-			*status = FE_HAS_SIGNAL | FE_HAS_CARRIER;
-			return 0;
-		}
-
-		state->tune_state = VA1J5JF8007S_TRACK;
-		/* fall through */
-
-	case VA1J5JF8007S_TRACK:
-		*delay = 3 * HZ;
-		*status = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_LOCK;
-		return 0;
-	}
-
-	BUG();
-}
-
-static int va1j5jf8007s_init_frequency(struct va1j5jf8007s_state *state)
-{
-	u8 buf[4];
-	struct i2c_msg msg;
-
-	buf[0] = 0xfe;
-	buf[1] = 0xc0;
-	buf[2] = 0xf0;
-	buf[3] = 0x04;
-
-	msg.addr = state->config->demod_address;
-	msg.flags = 0;
-	msg.len = sizeof(buf);
-	msg.buf = buf;
-
-	if (i2c_transfer(state->adap, &msg, 1) != 1)
-		return -EREMOTEIO;
-
-	return 0;
-}
-
-static int va1j5jf8007s_set_sleep(struct va1j5jf8007s_state *state, int sleep)
-{
-	u8 buf[2];
-	struct i2c_msg msg;
-
-	buf[0] = 0x17;
-	buf[1] = sleep ? 0x01 : 0x00;
-
-	msg.addr = state->config->demod_address;
-	msg.flags = 0;
-	msg.len = sizeof(buf);
-	msg.buf = buf;
-
-	if (i2c_transfer(state->adap, &msg, 1) != 1)
-		return -EREMOTEIO;
-
-	return 0;
-}
-
-static int va1j5jf8007s_sleep(struct dvb_frontend *fe)
-{
-	struct va1j5jf8007s_state *state;
-	int ret;
-
-	state = fe->demodulator_priv;
-
-	ret = va1j5jf8007s_init_frequency(state);
-	if (ret < 0)
-		return ret;
-
-	return va1j5jf8007s_set_sleep(state, 1);
-}
-
-static int va1j5jf8007s_init(struct dvb_frontend *fe)
-{
-	struct va1j5jf8007s_state *state;
-
-	state = fe->demodulator_priv;
-	state->tune_state = VA1J5JF8007S_IDLE;
-
-	return va1j5jf8007s_set_sleep(state, 0);
-}
-
-static void va1j5jf8007s_release(struct dvb_frontend *fe)
-{
-	struct va1j5jf8007s_state *state;
-	state = fe->demodulator_priv;
-	kfree(state);
-}
-
-static struct dvb_frontend_ops va1j5jf8007s_ops = {
-	.delsys = { SYS_ISDBS },
-	.info = {
-		.name = "VA1J5JF8007/VA1J5JF8011 ISDB-S",
-		.frequency_min = 950000,
-		.frequency_max = 2150000,
-		.frequency_stepsize = 1000,
-		.caps = FE_CAN_INVERSION_AUTO | FE_CAN_FEC_AUTO |
-			FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO |
-			FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO,
-	},
-
-	.read_snr = va1j5jf8007s_read_snr,
-	.get_frontend_algo = va1j5jf8007s_get_frontend_algo,
-	.read_status = va1j5jf8007s_read_status,
-	.tune = va1j5jf8007s_tune,
-	.sleep = va1j5jf8007s_sleep,
-	.init = va1j5jf8007s_init,
-	.release = va1j5jf8007s_release,
-};
-
-static int va1j5jf8007s_prepare_1(struct va1j5jf8007s_state *state)
-{
-	u8 addr;
-	u8 write_buf[1], read_buf[1];
-	struct i2c_msg msgs[2];
-
-	addr = state->config->demod_address;
-
-	write_buf[0] = 0x07;
-
-	msgs[0].addr = addr;
-	msgs[0].flags = 0;
-	msgs[0].len = sizeof(write_buf);
-	msgs[0].buf = write_buf;
-
-	msgs[1].addr = addr;
-	msgs[1].flags = I2C_M_RD;
-	msgs[1].len = sizeof(read_buf);
-	msgs[1].buf = read_buf;
-
-	if (i2c_transfer(state->adap, msgs, 2) != 2)
-		return -EREMOTEIO;
-
-	if (read_buf[0] != 0x41)
-		return -EIO;
-
-	return 0;
-}
-
-static const u8 va1j5jf8007s_20mhz_prepare_bufs[][2] = {
-	{0x04, 0x02}, {0x0d, 0x55}, {0x11, 0x40}, {0x13, 0x80}, {0x17, 0x01},
-	{0x1c, 0x0a}, {0x1d, 0xaa}, {0x1e, 0x20}, {0x1f, 0x88}, {0x51, 0xb0},
-	{0x52, 0x89}, {0x53, 0xb3}, {0x5a, 0x2d}, {0x5b, 0xd3}, {0x85, 0x69},
-	{0x87, 0x04}, {0x8e, 0x02}, {0xa3, 0xf7}, {0xa5, 0xc0},
-};
-
-static const u8 va1j5jf8007s_25mhz_prepare_bufs[][2] = {
-	{0x04, 0x02}, {0x11, 0x40}, {0x13, 0x80}, {0x17, 0x01}, {0x1c, 0x0a},
-	{0x1d, 0xaa}, {0x1e, 0x20}, {0x1f, 0x88}, {0x51, 0xb0}, {0x52, 0x89},
-	{0x53, 0xb3}, {0x5a, 0x2d}, {0x5b, 0xd3}, {0x85, 0x69}, {0x87, 0x04},
-	{0x8e, 0x26}, {0xa3, 0xf7}, {0xa5, 0xc0},
-};
-
-static int va1j5jf8007s_prepare_2(struct va1j5jf8007s_state *state)
-{
-	const u8 (*bufs)[2];
-	int size;
-	u8 addr;
-	u8 buf[2];
-	struct i2c_msg msg;
-	int i;
-
-	switch (state->config->frequency) {
-	case VA1J5JF8007S_20MHZ:
-		bufs = va1j5jf8007s_20mhz_prepare_bufs;
-		size = ARRAY_SIZE(va1j5jf8007s_20mhz_prepare_bufs);
-		break;
-	case VA1J5JF8007S_25MHZ:
-		bufs = va1j5jf8007s_25mhz_prepare_bufs;
-		size = ARRAY_SIZE(va1j5jf8007s_25mhz_prepare_bufs);
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	addr = state->config->demod_address;
-
-	msg.addr = addr;
-	msg.flags = 0;
-	msg.len = 2;
-	msg.buf = buf;
-	for (i = 0; i < size; i++) {
-		memcpy(buf, bufs[i], sizeof(buf));
-		if (i2c_transfer(state->adap, &msg, 1) != 1)
-			return -EREMOTEIO;
-	}
-
-	return 0;
-}
-
-/* must be called after va1j5jf8007t_attach */
-int va1j5jf8007s_prepare(struct dvb_frontend *fe)
-{
-	struct va1j5jf8007s_state *state;
-	int ret;
-
-	state = fe->demodulator_priv;
-
-	ret = va1j5jf8007s_prepare_1(state);
-	if (ret < 0)
-		return ret;
-
-	ret = va1j5jf8007s_prepare_2(state);
-	if (ret < 0)
-		return ret;
-
-	return va1j5jf8007s_init_frequency(state);
-}
-
-struct dvb_frontend *
-va1j5jf8007s_attach(const struct va1j5jf8007s_config *config,
-		    struct i2c_adapter *adap)
-{
-	struct va1j5jf8007s_state *state;
-	struct dvb_frontend *fe;
-	u8 buf[2];
-	struct i2c_msg msg;
-
-	state = kzalloc(sizeof(struct va1j5jf8007s_state), GFP_KERNEL);
-	if (!state)
-		return NULL;
-
-	state->config = config;
-	state->adap = adap;
-
-	fe = &state->fe;
-	memcpy(&fe->ops, &va1j5jf8007s_ops, sizeof(struct dvb_frontend_ops));
-	fe->demodulator_priv = state;
-
-	buf[0] = 0x01;
-	buf[1] = 0x80;
-
-	msg.addr = state->config->demod_address;
-	msg.flags = 0;
-	msg.len = sizeof(buf);
-	msg.buf = buf;
-
-	if (i2c_transfer(state->adap, &msg, 1) != 1) {
-		kfree(state);
-		return NULL;
-	}
-
-	return fe;
-}
diff --git a/drivers/media/dvb/pt1/va1j5jf8007s.h b/drivers/media/dvb/pt1/va1j5jf8007s.h
deleted file mode 100644
index b7d6f05..0000000
--- a/drivers/media/dvb/pt1/va1j5jf8007s.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * ISDB-S driver for VA1J5JF8007/VA1J5JF8011
- *
- * Copyright (C) 2009 HIRANO Takahito <hiranotaka@zng.info>
- *
- * based on pt1dvr - http://pt1dvr.sourceforge.jp/
- * 	by Tomoaki Ishikawa <tomy@users.sourceforge.jp>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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 VA1J5JF8007S_H
-#define VA1J5JF8007S_H
-
-enum va1j5jf8007s_frequency {
-	VA1J5JF8007S_20MHZ,
-	VA1J5JF8007S_25MHZ,
-};
-
-struct va1j5jf8007s_config {
-	u8 demod_address;
-	enum va1j5jf8007s_frequency frequency;
-};
-
-struct i2c_adapter;
-
-struct dvb_frontend *
-va1j5jf8007s_attach(const struct va1j5jf8007s_config *config,
-		    struct i2c_adapter *adap);
-
-/* must be called after va1j5jf8007t_attach */
-int va1j5jf8007s_prepare(struct dvb_frontend *fe);
-
-#endif
diff --git a/drivers/media/dvb/pt1/va1j5jf8007t.c b/drivers/media/dvb/pt1/va1j5jf8007t.c
deleted file mode 100644
index 2db15159..0000000
--- a/drivers/media/dvb/pt1/va1j5jf8007t.c
+++ /dev/null
@@ -1,536 +0,0 @@
-/*
- * ISDB-T driver for VA1J5JF8007/VA1J5JF8011
- *
- * Copyright (C) 2009 HIRANO Takahito <hiranotaka@zng.info>
- *
- * based on pt1dvr - http://pt1dvr.sourceforge.jp/
- * 	by Tomoaki Ishikawa <tomy@users.sourceforge.jp>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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/slab.h>
-#include <linux/i2c.h>
-#include "dvb_frontend.h"
-#include "dvb_math.h"
-#include "va1j5jf8007t.h"
-
-enum va1j5jf8007t_tune_state {
-	VA1J5JF8007T_IDLE,
-	VA1J5JF8007T_SET_FREQUENCY,
-	VA1J5JF8007T_CHECK_FREQUENCY,
-	VA1J5JF8007T_SET_MODULATION,
-	VA1J5JF8007T_CHECK_MODULATION,
-	VA1J5JF8007T_TRACK,
-	VA1J5JF8007T_ABORT,
-};
-
-struct va1j5jf8007t_state {
-	const struct va1j5jf8007t_config *config;
-	struct i2c_adapter *adap;
-	struct dvb_frontend fe;
-	enum va1j5jf8007t_tune_state tune_state;
-};
-
-static int va1j5jf8007t_read_snr(struct dvb_frontend *fe, u16 *snr)
-{
-	struct va1j5jf8007t_state *state;
-	u8 addr;
-	int i;
-	u8 write_buf[1], read_buf[1];
-	struct i2c_msg msgs[2];
-	s32 word, x, y;
-
-	state = fe->demodulator_priv;
-	addr = state->config->demod_address;
-
-	word = 0;
-	for (i = 0; i < 3; i++) {
-		write_buf[0] = 0x8b + i;
-
-		msgs[0].addr = addr;
-		msgs[0].flags = 0;
-		msgs[0].len = sizeof(write_buf);
-		msgs[0].buf = write_buf;
-
-		msgs[1].addr = addr;
-		msgs[1].flags = I2C_M_RD;
-		msgs[1].len = sizeof(read_buf);
-		msgs[1].buf = read_buf;
-
-		if (i2c_transfer(state->adap, msgs, 2) != 2)
-			return -EREMOTEIO;
-
-		word <<= 8;
-		word |= read_buf[0];
-	}
-
-	if (!word)
-		return -EIO;
-
-	x = 10 * (intlog10(0x540000 * 100 / word) - (2 << 24));
-	y = (24ll << 46) / 1000000;
-	y = ((s64)y * x >> 30) - (16ll << 40) / 10000;
-	y = ((s64)y * x >> 29) + (398ll << 35) / 10000;
-	y = ((s64)y * x >> 30) + (5491ll << 29) / 10000;
-	y = ((s64)y * x >> 30) + (30965ll << 23) / 10000;
-	*snr = y >> 15;
-	return 0;
-}
-
-static int va1j5jf8007t_get_frontend_algo(struct dvb_frontend *fe)
-{
-	return DVBFE_ALGO_HW;
-}
-
-static int
-va1j5jf8007t_read_status(struct dvb_frontend *fe, fe_status_t *status)
-{
-	struct va1j5jf8007t_state *state;
-
-	state = fe->demodulator_priv;
-
-	switch (state->tune_state) {
-	case VA1J5JF8007T_IDLE:
-	case VA1J5JF8007T_SET_FREQUENCY:
-	case VA1J5JF8007T_CHECK_FREQUENCY:
-		*status = 0;
-		return 0;
-
-
-	case VA1J5JF8007T_SET_MODULATION:
-	case VA1J5JF8007T_CHECK_MODULATION:
-	case VA1J5JF8007T_ABORT:
-		*status |= FE_HAS_SIGNAL;
-		return 0;
-
-	case VA1J5JF8007T_TRACK:
-		*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_LOCK;
-		return 0;
-	}
-
-	BUG();
-}
-
-struct va1j5jf8007t_cb_map {
-	u32 frequency;
-	u8 cb;
-};
-
-static const struct va1j5jf8007t_cb_map va1j5jf8007t_cb_maps[] = {
-	{  90000000, 0x80 },
-	{ 140000000, 0x81 },
-	{ 170000000, 0xa1 },
-	{ 220000000, 0x62 },
-	{ 330000000, 0xa2 },
-	{ 402000000, 0xe2 },
-	{ 450000000, 0x64 },
-	{ 550000000, 0x84 },
-	{ 600000000, 0xa4 },
-	{ 700000000, 0xc4 },
-};
-
-static u8 va1j5jf8007t_lookup_cb(u32 frequency)
-{
-	int i;
-	const struct va1j5jf8007t_cb_map *map;
-
-	for (i = 0; i < ARRAY_SIZE(va1j5jf8007t_cb_maps); i++) {
-		map = &va1j5jf8007t_cb_maps[i];
-		if (frequency < map->frequency)
-			return map->cb;
-	}
-	return 0xe4;
-}
-
-static int va1j5jf8007t_set_frequency(struct va1j5jf8007t_state *state)
-{
-	u32 frequency;
-	u16 word;
-	u8 buf[6];
-	struct i2c_msg msg;
-
-	frequency = state->fe.dtv_property_cache.frequency;
-
-	word = (frequency + 71428) / 142857 + 399;
-	buf[0] = 0xfe;
-	buf[1] = 0xc2;
-	buf[2] = word >> 8;
-	buf[3] = word;
-	buf[4] = 0x80;
-	buf[5] = va1j5jf8007t_lookup_cb(frequency);
-
-	msg.addr = state->config->demod_address;
-	msg.flags = 0;
-	msg.len = sizeof(buf);
-	msg.buf = buf;
-
-	if (i2c_transfer(state->adap, &msg, 1) != 1)
-		return -EREMOTEIO;
-
-	return 0;
-}
-
-static int
-va1j5jf8007t_check_frequency(struct va1j5jf8007t_state *state, int *lock)
-{
-	u8 addr;
-	u8 write_buf[2], read_buf[1];
-	struct i2c_msg msgs[2];
-
-	addr = state->config->demod_address;
-
-	write_buf[0] = 0xfe;
-	write_buf[1] = 0xc3;
-
-	msgs[0].addr = addr;
-	msgs[0].flags = 0;
-	msgs[0].len = sizeof(write_buf);
-	msgs[0].buf = write_buf;
-
-	msgs[1].addr = addr;
-	msgs[1].flags = I2C_M_RD;
-	msgs[1].len = sizeof(read_buf);
-	msgs[1].buf = read_buf;
-
-	if (i2c_transfer(state->adap, msgs, 2) != 2)
-		return -EREMOTEIO;
-
-	*lock = read_buf[0] & 0x40;
-	return 0;
-}
-
-static int va1j5jf8007t_set_modulation(struct va1j5jf8007t_state *state)
-{
-	u8 buf[2];
-	struct i2c_msg msg;
-
-	buf[0] = 0x01;
-	buf[1] = 0x40;
-
-	msg.addr = state->config->demod_address;
-	msg.flags = 0;
-	msg.len = sizeof(buf);
-	msg.buf = buf;
-
-	if (i2c_transfer(state->adap, &msg, 1) != 1)
-		return -EREMOTEIO;
-
-	return 0;
-}
-
-static int va1j5jf8007t_check_modulation(struct va1j5jf8007t_state *state,
-					 int *lock, int *retry)
-{
-	u8 addr;
-	u8 write_buf[1], read_buf[1];
-	struct i2c_msg msgs[2];
-
-	addr = state->config->demod_address;
-
-	write_buf[0] = 0x80;
-
-	msgs[0].addr = addr;
-	msgs[0].flags = 0;
-	msgs[0].len = sizeof(write_buf);
-	msgs[0].buf = write_buf;
-
-	msgs[1].addr = addr;
-	msgs[1].flags = I2C_M_RD;
-	msgs[1].len = sizeof(read_buf);
-	msgs[1].buf = read_buf;
-
-	if (i2c_transfer(state->adap, msgs, 2) != 2)
-		return -EREMOTEIO;
-
-	*lock = !(read_buf[0] & 0x10);
-	*retry = read_buf[0] & 0x80;
-	return 0;
-}
-
-static int
-va1j5jf8007t_tune(struct dvb_frontend *fe,
-		  bool re_tune,
-		  unsigned int mode_flags,  unsigned int *delay,
-		  fe_status_t *status)
-{
-	struct va1j5jf8007t_state *state;
-	int ret;
-	int lock = 0, retry = 0;
-
-	state = fe->demodulator_priv;
-
-	if (re_tune)
-		state->tune_state = VA1J5JF8007T_SET_FREQUENCY;
-
-	switch (state->tune_state) {
-	case VA1J5JF8007T_IDLE:
-		*delay = 3 * HZ;
-		*status = 0;
-		return 0;
-
-	case VA1J5JF8007T_SET_FREQUENCY:
-		ret = va1j5jf8007t_set_frequency(state);
-		if (ret < 0)
-			return ret;
-
-		state->tune_state = VA1J5JF8007T_CHECK_FREQUENCY;
-		*delay = 0;
-		*status = 0;
-		return 0;
-
-	case VA1J5JF8007T_CHECK_FREQUENCY:
-		ret = va1j5jf8007t_check_frequency(state, &lock);
-		if (ret < 0)
-			return ret;
-
-		if (!lock)  {
-			*delay = (HZ + 999) / 1000;
-			*status = 0;
-			return 0;
-		}
-
-		state->tune_state = VA1J5JF8007T_SET_MODULATION;
-		*delay = 0;
-		*status = FE_HAS_SIGNAL;
-		return 0;
-
-	case VA1J5JF8007T_SET_MODULATION:
-		ret = va1j5jf8007t_set_modulation(state);
-		if (ret < 0)
-			return ret;
-
-		state->tune_state = VA1J5JF8007T_CHECK_MODULATION;
-		*delay = 0;
-		*status = FE_HAS_SIGNAL;
-		return 0;
-
-	case VA1J5JF8007T_CHECK_MODULATION:
-		ret = va1j5jf8007t_check_modulation(state, &lock, &retry);
-		if (ret < 0)
-			return ret;
-
-		if (!lock)  {
-			if (!retry)  {
-				state->tune_state = VA1J5JF8007T_ABORT;
-				*delay = 3 * HZ;
-				*status = FE_HAS_SIGNAL;
-				return 0;
-			}
-			*delay = (HZ + 999) / 1000;
-			*status = FE_HAS_SIGNAL;
-			return 0;
-		}
-
-		state->tune_state = VA1J5JF8007T_TRACK;
-		/* fall through */
-
-	case VA1J5JF8007T_TRACK:
-		*delay = 3 * HZ;
-		*status = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_LOCK;
-		return 0;
-
-	case VA1J5JF8007T_ABORT:
-		*delay = 3 * HZ;
-		*status = FE_HAS_SIGNAL;
-		return 0;
-	}
-
-	BUG();
-}
-
-static int va1j5jf8007t_init_frequency(struct va1j5jf8007t_state *state)
-{
-	u8 buf[7];
-	struct i2c_msg msg;
-
-	buf[0] = 0xfe;
-	buf[1] = 0xc2;
-	buf[2] = 0x01;
-	buf[3] = 0x8f;
-	buf[4] = 0xc1;
-	buf[5] = 0x80;
-	buf[6] = 0x80;
-
-	msg.addr = state->config->demod_address;
-	msg.flags = 0;
-	msg.len = sizeof(buf);
-	msg.buf = buf;
-
-	if (i2c_transfer(state->adap, &msg, 1) != 1)
-		return -EREMOTEIO;
-
-	return 0;
-}
-
-static int va1j5jf8007t_set_sleep(struct va1j5jf8007t_state *state, int sleep)
-{
-	u8 buf[2];
-	struct i2c_msg msg;
-
-	buf[0] = 0x03;
-	buf[1] = sleep ? 0x90 : 0x80;
-
-	msg.addr = state->config->demod_address;
-	msg.flags = 0;
-	msg.len = sizeof(buf);
-	msg.buf = buf;
-
-	if (i2c_transfer(state->adap, &msg, 1) != 1)
-		return -EREMOTEIO;
-
-	return 0;
-}
-
-static int va1j5jf8007t_sleep(struct dvb_frontend *fe)
-{
-	struct va1j5jf8007t_state *state;
-	int ret;
-
-	state = fe->demodulator_priv;
-
-	ret = va1j5jf8007t_init_frequency(state);
-	if (ret < 0)
-		return ret;
-
-	return va1j5jf8007t_set_sleep(state, 1);
-}
-
-static int va1j5jf8007t_init(struct dvb_frontend *fe)
-{
-	struct va1j5jf8007t_state *state;
-
-	state = fe->demodulator_priv;
-	state->tune_state = VA1J5JF8007T_IDLE;
-
-	return va1j5jf8007t_set_sleep(state, 0);
-}
-
-static void va1j5jf8007t_release(struct dvb_frontend *fe)
-{
-	struct va1j5jf8007t_state *state;
-	state = fe->demodulator_priv;
-	kfree(state);
-}
-
-static struct dvb_frontend_ops va1j5jf8007t_ops = {
-	.delsys = { SYS_ISDBT },
-	.info = {
-		.name = "VA1J5JF8007/VA1J5JF8011 ISDB-T",
-		.frequency_min = 90000000,
-		.frequency_max = 770000000,
-		.frequency_stepsize = 142857,
-		.caps = FE_CAN_INVERSION_AUTO | FE_CAN_FEC_AUTO |
-			FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO |
-			FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO,
-	},
-
-	.read_snr = va1j5jf8007t_read_snr,
-	.get_frontend_algo = va1j5jf8007t_get_frontend_algo,
-	.read_status = va1j5jf8007t_read_status,
-	.tune = va1j5jf8007t_tune,
-	.sleep = va1j5jf8007t_sleep,
-	.init = va1j5jf8007t_init,
-	.release = va1j5jf8007t_release,
-};
-
-static const u8 va1j5jf8007t_20mhz_prepare_bufs[][2] = {
-	{0x03, 0x90}, {0x14, 0x8f}, {0x1c, 0x2a}, {0x1d, 0xa8}, {0x1e, 0xa2},
-	{0x22, 0x83}, {0x31, 0x0d}, {0x32, 0xe0}, {0x39, 0xd3}, {0x3a, 0x00},
-	{0x5c, 0x40}, {0x5f, 0x80}, {0x75, 0x02}, {0x76, 0x4e}, {0x77, 0x03},
-	{0xef, 0x01}
-};
-
-static const u8 va1j5jf8007t_25mhz_prepare_bufs[][2] = {
-	{0x03, 0x90}, {0x1c, 0x2a}, {0x1d, 0xa8}, {0x1e, 0xa2}, {0x22, 0x83},
-	{0x3a, 0x00}, {0x5c, 0x40}, {0x5f, 0x80}, {0x75, 0x0a}, {0x76, 0x4c},
-	{0x77, 0x03}, {0xef, 0x01}
-};
-
-int va1j5jf8007t_prepare(struct dvb_frontend *fe)
-{
-	struct va1j5jf8007t_state *state;
-	const u8 (*bufs)[2];
-	int size;
-	u8 buf[2];
-	struct i2c_msg msg;
-	int i;
-
-	state = fe->demodulator_priv;
-
-	switch (state->config->frequency) {
-	case VA1J5JF8007T_20MHZ:
-		bufs = va1j5jf8007t_20mhz_prepare_bufs;
-		size = ARRAY_SIZE(va1j5jf8007t_20mhz_prepare_bufs);
-		break;
-	case VA1J5JF8007T_25MHZ:
-		bufs = va1j5jf8007t_25mhz_prepare_bufs;
-		size = ARRAY_SIZE(va1j5jf8007t_25mhz_prepare_bufs);
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	msg.addr = state->config->demod_address;
-	msg.flags = 0;
-	msg.len = sizeof(buf);
-	msg.buf = buf;
-
-	for (i = 0; i < size; i++) {
-		memcpy(buf, bufs[i], sizeof(buf));
-		if (i2c_transfer(state->adap, &msg, 1) != 1)
-			return -EREMOTEIO;
-	}
-
-	return va1j5jf8007t_init_frequency(state);
-}
-
-struct dvb_frontend *
-va1j5jf8007t_attach(const struct va1j5jf8007t_config *config,
-		    struct i2c_adapter *adap)
-{
-	struct va1j5jf8007t_state *state;
-	struct dvb_frontend *fe;
-	u8 buf[2];
-	struct i2c_msg msg;
-
-	state = kzalloc(sizeof(struct va1j5jf8007t_state), GFP_KERNEL);
-	if (!state)
-		return NULL;
-
-	state->config = config;
-	state->adap = adap;
-
-	fe = &state->fe;
-	memcpy(&fe->ops, &va1j5jf8007t_ops, sizeof(struct dvb_frontend_ops));
-	fe->demodulator_priv = state;
-
-	buf[0] = 0x01;
-	buf[1] = 0x80;
-
-	msg.addr = state->config->demod_address;
-	msg.flags = 0;
-	msg.len = sizeof(buf);
-	msg.buf = buf;
-
-	if (i2c_transfer(state->adap, &msg, 1) != 1) {
-		kfree(state);
-		return NULL;
-	}
-
-	return fe;
-}
diff --git a/drivers/media/dvb/pt1/va1j5jf8007t.h b/drivers/media/dvb/pt1/va1j5jf8007t.h
deleted file mode 100644
index 2903be5..0000000
--- a/drivers/media/dvb/pt1/va1j5jf8007t.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * ISDB-T driver for VA1J5JF8007/VA1J5JF8011
- *
- * Copyright (C) 2009 HIRANO Takahito <hiranotaka@zng.info>
- *
- * based on pt1dvr - http://pt1dvr.sourceforge.jp/
- * 	by Tomoaki Ishikawa <tomy@users.sourceforge.jp>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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 VA1J5JF8007T_H
-#define VA1J5JF8007T_H
-
-enum va1j5jf8007t_frequency {
-	VA1J5JF8007T_20MHZ,
-	VA1J5JF8007T_25MHZ,
-};
-
-struct va1j5jf8007t_config {
-	u8 demod_address;
-	enum va1j5jf8007t_frequency frequency;
-};
-
-struct i2c_adapter;
-
-struct dvb_frontend *
-va1j5jf8007t_attach(const struct va1j5jf8007t_config *config,
-		    struct i2c_adapter *adap);
-
-/* must be called after va1j5jf8007s_attach */
-int va1j5jf8007t_prepare(struct dvb_frontend *fe);
-
-#endif
diff --git a/drivers/media/dvb/siano/Kconfig b/drivers/media/dvb/siano/Kconfig
deleted file mode 100644
index bc6456e..0000000
--- a/drivers/media/dvb/siano/Kconfig
+++ /dev/null
@@ -1,34 +0,0 @@
-#
-# Siano Mobile Silicon Digital TV device configuration
-#
-
-config SMS_SIANO_MDTV
-	tristate "Siano SMS1xxx based MDTV receiver"
-	depends on DVB_CORE && RC_CORE && HAS_DMA
-	---help---
-	  Choose Y or M here if you have MDTV receiver with a Siano chipset.
-
-	  To compile this driver as a module, choose M here
-	  (The module will be called smsmdtv).
-
-	  Further documentation on this driver can be found on the WWW
-	  at http://www.siano-ms.com/
-
-if SMS_SIANO_MDTV
-menu "Siano module components"
-
-# Hardware interfaces support
-
-config SMS_USB_DRV
-	tristate "USB interface support"
-	depends on DVB_CORE && USB
-	---help---
-	  Choose if you would like to have Siano's support for USB interface
-
-config SMS_SDIO_DRV
-	tristate "SDIO interface support"
-	depends on DVB_CORE && MMC
-	---help---
-	  Choose if you would like to have Siano's support for SDIO interface
-endmenu
-endif # SMS_SIANO_MDTV
diff --git a/drivers/media/dvb/siano/Makefile b/drivers/media/dvb/siano/Makefile
deleted file mode 100644
index f233b57..0000000
--- a/drivers/media/dvb/siano/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-
-smsmdtv-objs := smscoreapi.o sms-cards.o smsendian.o smsir.o
-
-obj-$(CONFIG_SMS_SIANO_MDTV) += smsmdtv.o smsdvb.o
-obj-$(CONFIG_SMS_USB_DRV) += smsusb.o
-obj-$(CONFIG_SMS_SDIO_DRV) += smssdio.o
-
-ccflags-y += -Idrivers/media/dvb/dvb-core
-
-ccflags-y += $(extra-cflags-y) $(extra-cflags-m)
-
diff --git a/drivers/media/dvb/siano/sms-cards.c b/drivers/media/dvb/siano/sms-cards.c
deleted file mode 100644
index 680c781..0000000
--- a/drivers/media/dvb/siano/sms-cards.c
+++ /dev/null
@@ -1,311 +0,0 @@
-/*
- *  Card-specific functions for the Siano SMS1xxx USB dongle
- *
- *  Copyright (c) 2008 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 version 2 as
- *  published by the Free Software Foundation;
- *
- *  Software distributed under the License is distributed on an "AS IS"
- *  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
- *
- *  See the GNU General Public License for more details.
- *
- *  You 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 "sms-cards.h"
-#include "smsir.h"
-#include <linux/module.h>
-
-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] = {
-		.name	= "Unknown board",
-	},
-	[SMS1XXX_BOARD_SIANO_STELLAR] = {
-		.name	= "Siano Stellar Digital Receiver",
-		.type	= SMS_STELLAR,
-	},
-	[SMS1XXX_BOARD_SIANO_NOVA_A] = {
-		.name	= "Siano Nova A Digital Receiver",
-		.type	= SMS_NOVA_A0,
-	},
-	[SMS1XXX_BOARD_SIANO_NOVA_B] = {
-		.name	= "Siano Nova B Digital Receiver",
-		.type	= SMS_NOVA_B0,
-	},
-	[SMS1XXX_BOARD_SIANO_VEGA] = {
-		.name	= "Siano Vega Digital Receiver",
-		.type	= SMS_VEGA,
-	},
-	[SMS1XXX_BOARD_HAUPPAUGE_CATAMOUNT] = {
-		.name	= "Hauppauge Catamount",
-		.type	= SMS_STELLAR,
-		.fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-stellar-dvbt-01.fw",
-	},
-	[SMS1XXX_BOARD_HAUPPAUGE_OKEMO_A] = {
-		.name	= "Hauppauge Okemo-A",
-		.type	= SMS_NOVA_A0,
-		.fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-nova-a-dvbt-01.fw",
-	},
-	[SMS1XXX_BOARD_HAUPPAUGE_OKEMO_B] = {
-		.name	= "Hauppauge Okemo-B",
-		.type	= SMS_NOVA_B0,
-		.fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-nova-b-dvbt-01.fw",
-	},
-	[SMS1XXX_BOARD_HAUPPAUGE_WINDHAM] = {
-		.name	= "Hauppauge WinTV MiniStick",
-		.type	= SMS_NOVA_B0,
-		.fw[DEVICE_MODE_ISDBT_BDA] = "sms1xxx-hcw-55xxx-isdbt-02.fw",
-		.fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-02.fw",
-		.rc_codes = RC_MAP_HAUPPAUGE,
-		.board_cfg.leds_power = 26,
-		.board_cfg.led0 = 27,
-		.board_cfg.led1 = 28,
-		.board_cfg.ir = 9,
-		.led_power = 26,
-		.led_lo    = 27,
-		.led_hi    = 28,
-	},
-	[SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD] = {
-		.name	= "Hauppauge WinTV MiniCard",
-		.type	= SMS_NOVA_B0,
-		.fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-02.fw",
-		.lna_ctrl  = 29,
-		.board_cfg.foreign_lna0_ctrl = 29,
-		.rf_switch = 17,
-		.board_cfg.rf_switch_uhf = 17,
-	},
-	[SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2] = {
-		.name	= "Hauppauge WinTV MiniCard",
-		.type	= SMS_NOVA_B0,
-		.fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-02.fw",
-		.lna_ctrl  = -1,
-	},
-	[SMS1XXX_BOARD_SIANO_NICE] = {
-	/* 11 */
-		.name = "Siano Nice Digital Receiver",
-		.type = SMS_NOVA_B0,
-	},
-	[SMS1XXX_BOARD_SIANO_VENICE] = {
-	/* 12 */
-		.name = "Siano Venice Digital Receiver",
-		.type = SMS_VEGA,
-	},
-};
-
-struct sms_board *sms_get_board(unsigned id)
-{
-	BUG_ON(id >= ARRAY_SIZE(sms_boards));
-
-	return &sms_boards[id];
-}
-EXPORT_SYMBOL_GPL(sms_get_board);
-static inline void sms_gpio_assign_11xx_default_led_config(
-		struct smscore_gpio_config *pGpioConfig) {
-	pGpioConfig->Direction = SMS_GPIO_DIRECTION_OUTPUT;
-	pGpioConfig->InputCharacteristics =
-		SMS_GPIO_INPUT_CHARACTERISTICS_NORMAL;
-	pGpioConfig->OutputDriving = SMS_GPIO_OUTPUT_DRIVING_4mA;
-	pGpioConfig->OutputSlewRate = SMS_GPIO_OUTPUT_SLEW_RATE_0_45_V_NS;
-	pGpioConfig->PullUpDown = SMS_GPIO_PULL_UP_DOWN_NONE;
-}
-
-int sms_board_event(struct smscore_device_t *coredev,
-		enum SMS_BOARD_EVENTS gevent) {
-	struct smscore_gpio_config MyGpioConfig;
-
-	sms_gpio_assign_11xx_default_led_config(&MyGpioConfig);
-
-	switch (gevent) {
-	case BOARD_EVENT_POWER_INIT: /* including hotplug */
-		break; /* BOARD_EVENT_BIND */
-
-	case BOARD_EVENT_POWER_SUSPEND:
-		break; /* BOARD_EVENT_POWER_SUSPEND */
-
-	case BOARD_EVENT_POWER_RESUME:
-		break; /* BOARD_EVENT_POWER_RESUME */
-
-	case BOARD_EVENT_BIND:
-		break; /* BOARD_EVENT_BIND */
-
-	case BOARD_EVENT_SCAN_PROG:
-		break; /* BOARD_EVENT_SCAN_PROG */
-	case BOARD_EVENT_SCAN_COMP:
-		break; /* BOARD_EVENT_SCAN_COMP */
-	case BOARD_EVENT_EMERGENCY_WARNING_SIGNAL:
-		break; /* BOARD_EVENT_EMERGENCY_WARNING_SIGNAL */
-	case BOARD_EVENT_FE_LOCK:
-		break; /* BOARD_EVENT_FE_LOCK */
-	case BOARD_EVENT_FE_UNLOCK:
-		break; /* BOARD_EVENT_FE_UNLOCK */
-	case BOARD_EVENT_DEMOD_LOCK:
-		break; /* BOARD_EVENT_DEMOD_LOCK */
-	case BOARD_EVENT_DEMOD_UNLOCK:
-		break; /* BOARD_EVENT_DEMOD_UNLOCK */
-	case BOARD_EVENT_RECEPTION_MAX_4:
-		break; /* BOARD_EVENT_RECEPTION_MAX_4 */
-	case BOARD_EVENT_RECEPTION_3:
-		break; /* BOARD_EVENT_RECEPTION_3 */
-	case BOARD_EVENT_RECEPTION_2:
-		break; /* BOARD_EVENT_RECEPTION_2 */
-	case BOARD_EVENT_RECEPTION_1:
-		break; /* BOARD_EVENT_RECEPTION_1 */
-	case BOARD_EVENT_RECEPTION_LOST_0:
-		break; /* BOARD_EVENT_RECEPTION_LOST_0 */
-	case BOARD_EVENT_MULTIPLEX_OK:
-		break; /* BOARD_EVENT_MULTIPLEX_OK */
-	case BOARD_EVENT_MULTIPLEX_ERRORS:
-		break; /* BOARD_EVENT_MULTIPLEX_ERRORS */
-
-	default:
-		sms_err("Unknown SMS board event");
-		break;
-	}
-	return 0;
-}
-EXPORT_SYMBOL_GPL(sms_board_event);
-
-static int sms_set_gpio(struct smscore_device_t *coredev, int pin, int enable)
-{
-	int lvl, ret;
-	u32 gpio;
-	struct smscore_config_gpio gpioconfig = {
-		.direction            = SMS_GPIO_DIRECTION_OUTPUT,
-		.pullupdown           = SMS_GPIO_PULLUPDOWN_NONE,
-		.inputcharacteristics = SMS_GPIO_INPUTCHARACTERISTICS_NORMAL,
-		.outputslewrate       = SMS_GPIO_OUTPUTSLEWRATE_FAST,
-		.outputdriving        = SMS_GPIO_OUTPUTDRIVING_4mA,
-	};
-
-	if (pin == 0)
-		return -EINVAL;
-
-	if (pin < 0) {
-		/* inverted gpio */
-		gpio = pin * -1;
-		lvl = enable ? 0 : 1;
-	} else {
-		gpio = pin;
-		lvl = enable ? 1 : 0;
-	}
-
-	ret = smscore_configure_gpio(coredev, gpio, &gpioconfig);
-	if (ret < 0)
-		return ret;
-
-	return smscore_set_gpio(coredev, gpio, lvl);
-}
-
-int sms_board_setup(struct smscore_device_t *coredev)
-{
-	int board_id = smscore_get_board_id(coredev);
-	struct sms_board *board = sms_get_board(board_id);
-
-	switch (board_id) {
-	case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM:
-		/* turn off all LEDs */
-		sms_set_gpio(coredev, board->led_power, 0);
-		sms_set_gpio(coredev, board->led_hi, 0);
-		sms_set_gpio(coredev, board->led_lo, 0);
-		break;
-	case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2:
-	case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD:
-		/* turn off LNA */
-		sms_set_gpio(coredev, board->lna_ctrl, 0);
-		break;
-	}
-	return 0;
-}
-EXPORT_SYMBOL_GPL(sms_board_setup);
-
-int sms_board_power(struct smscore_device_t *coredev, int onoff)
-{
-	int board_id = smscore_get_board_id(coredev);
-	struct sms_board *board = sms_get_board(board_id);
-
-	switch (board_id) {
-	case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM:
-		/* power LED */
-		sms_set_gpio(coredev,
-			     board->led_power, onoff ? 1 : 0);
-		break;
-	case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2:
-	case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD:
-		/* LNA */
-		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)
-{
-	int board_id = smscore_get_board_id(coredev);
-	struct sms_board *board = sms_get_board(board_id);
-
-	/* dont touch GPIO if LEDs are already set */
-	if (smscore_led_state(coredev, -1) == led)
-		return 0;
-
-	switch (board_id) {
-	case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM:
-		sms_set_gpio(coredev,
-			     board->led_lo, (led & SMS_LED_LO) ? 1 : 0);
-		sms_set_gpio(coredev,
-			     board->led_hi, (led & SMS_LED_HI) ? 1 : 0);
-
-		smscore_led_state(coredev, led);
-		break;
-	}
-	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:
-	case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD:
-	case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2:
-		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
deleted file mode 100644
index d8cdf75..0000000
--- a/drivers/media/dvb/siano/sms-cards.h
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- *  Card-specific functions for the Siano SMS1xxx USB dongle
- *
- *  Copyright (c) 2008 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 version 2 as
- *  published by the Free Software Foundation;
- *
- *  Software distributed under the License is distributed on an "AS IS"
- *  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
- *
- *  See the GNU General Public License for more details.
- *
- *  You 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 __SMS_CARDS_H__
-#define __SMS_CARDS_H__
-
-#include <linux/usb.h>
-#include "smscoreapi.h"
-#include "smsir.h"
-
-#define SMS_BOARD_UNKNOWN 0
-#define SMS1XXX_BOARD_SIANO_STELLAR 1
-#define SMS1XXX_BOARD_SIANO_NOVA_A  2
-#define SMS1XXX_BOARD_SIANO_NOVA_B  3
-#define SMS1XXX_BOARD_SIANO_VEGA    4
-#define SMS1XXX_BOARD_HAUPPAUGE_CATAMOUNT 5
-#define SMS1XXX_BOARD_HAUPPAUGE_OKEMO_A 6
-#define SMS1XXX_BOARD_HAUPPAUGE_OKEMO_B 7
-#define SMS1XXX_BOARD_HAUPPAUGE_WINDHAM 8
-#define SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD 9
-#define SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2 10
-#define SMS1XXX_BOARD_SIANO_NICE	11
-#define SMS1XXX_BOARD_SIANO_VENICE	12
-
-struct sms_board_gpio_cfg {
-	int lna_vhf_exist;
-	int lna_vhf_ctrl;
-	int lna_uhf_exist;
-	int lna_uhf_ctrl;
-	int lna_uhf_d_ctrl;
-	int lna_sband_exist;
-	int lna_sband_ctrl;
-	int lna_sband_d_ctrl;
-	int foreign_lna0_ctrl;
-	int foreign_lna1_ctrl;
-	int foreign_lna2_ctrl;
-	int rf_switch_vhf;
-	int rf_switch_uhf;
-	int rf_switch_sband;
-	int leds_power;
-	int led0;
-	int led1;
-	int led2;
-	int led3;
-	int led4;
-	int ir;
-	int eeprom_wp;
-	int mrc_sense;
-	int mrc_pdn_resetn;
-	int mrc_gp0; /* mrcs spi int */
-	int mrc_gp1;
-	int mrc_gp2;
-	int mrc_gp3;
-	int mrc_gp4;
-	int host_spi_gsp_ts_int;
-};
-
-struct sms_board {
-	enum sms_device_type_st type;
-	char *name, *fw[DEVICE_MODE_MAX];
-	struct sms_board_gpio_cfg board_cfg;
-	char *rc_codes;				/* Name of IR codes table */
-
-	/* gpios */
-	int led_power, led_hi, led_lo, lna_ctrl, rf_switch;
-};
-
-struct sms_board *sms_get_board(unsigned id);
-
-extern struct smscore_device_t *coredev;
-
-enum SMS_BOARD_EVENTS {
-	BOARD_EVENT_POWER_INIT,
-	BOARD_EVENT_POWER_SUSPEND,
-	BOARD_EVENT_POWER_RESUME,
-	BOARD_EVENT_BIND,
-	BOARD_EVENT_SCAN_PROG,
-	BOARD_EVENT_SCAN_COMP,
-	BOARD_EVENT_EMERGENCY_WARNING_SIGNAL,
-	BOARD_EVENT_FE_LOCK,
-	BOARD_EVENT_FE_UNLOCK,
-	BOARD_EVENT_DEMOD_LOCK,
-	BOARD_EVENT_DEMOD_UNLOCK,
-	BOARD_EVENT_RECEPTION_MAX_4,
-	BOARD_EVENT_RECEPTION_3,
-	BOARD_EVENT_RECEPTION_2,
-	BOARD_EVENT_RECEPTION_1,
-	BOARD_EVENT_RECEPTION_LOST_0,
-	BOARD_EVENT_MULTIPLEX_OK,
-	BOARD_EVENT_MULTIPLEX_ERRORS
-};
-
-int sms_board_event(struct smscore_device_t *coredev,
-		enum SMS_BOARD_EVENTS gevent);
-
-int sms_board_setup(struct smscore_device_t *coredev);
-
-#define SMS_LED_OFF 0
-#define SMS_LED_LO  1
-#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 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
deleted file mode 100644
index 9cc5554..0000000
--- a/drivers/media/dvb/siano/smscoreapi.c
+++ /dev/null
@@ -1,1637 +0,0 @@
-/*
- *  Siano core API module
- *
- *  This file contains implementation for the interface to sms core component
- *
- *  author: Uri Shkolnik
- *
- *  Copyright (c), 2005-2008 Siano Mobile Silicon, 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;
- *
- *  Software distributed under the License is distributed on an "AS IS"
- *  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
- *
- *  See the GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/dma-mapping.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-
-#include <linux/firmware.h>
-#include <linux/wait.h>
-#include <asm/byteorder.h>
-
-#include "smscoreapi.h"
-#include "sms-cards.h"
-#include "smsir.h"
-#include "smsendian.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))");
-
-struct smscore_device_notifyee_t {
-	struct list_head entry;
-	hotplug_t hotplug;
-};
-
-struct smscore_idlist_t {
-	struct list_head entry;
-	int		id;
-	int		data_type;
-};
-
-struct smscore_client_t {
-	struct list_head entry;
-	struct smscore_device_t *coredev;
-	void			*context;
-	struct list_head 	idlist;
-	onresponse_t	onresponse_handler;
-	onremove_t		onremove_handler;
-};
-
-void smscore_set_board_id(struct smscore_device_t *core, int id)
-{
-	core->board_id = id;
-}
-
-int smscore_led_state(struct smscore_device_t *core, int led)
-{
-	if (led >= 0)
-		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;
-	char			devpath[32];
-	int				mode;
-	enum sms_device_type_st	type;
-};
-
-static struct list_head g_smscore_notifyees;
-static struct list_head g_smscore_devices;
-static struct mutex g_smscore_deviceslock;
-
-static struct list_head g_smscore_registry;
-static struct mutex g_smscore_registrylock;
-
-static int default_mode = 4;
-
-module_param(default_mode, int, 0644);
-MODULE_PARM_DESC(default_mode, "default firmware id (device mode)");
-
-static struct smscore_registry_entry_t *smscore_find_registry(char *devpath)
-{
-	struct smscore_registry_entry_t *entry;
-	struct list_head *next;
-
-	kmutex_lock(&g_smscore_registrylock);
-	for (next = g_smscore_registry.next;
-	     next != &g_smscore_registry;
-	     next = next->next) {
-		entry = (struct smscore_registry_entry_t *) next;
-		if (!strcmp(entry->devpath, devpath)) {
-			kmutex_unlock(&g_smscore_registrylock);
-			return entry;
-		}
-	}
-	entry = kmalloc(sizeof(struct smscore_registry_entry_t), GFP_KERNEL);
-	if (entry) {
-		entry->mode = default_mode;
-		strcpy(entry->devpath, devpath);
-		list_add(&entry->entry, &g_smscore_registry);
-	} else
-		sms_err("failed to create smscore_registry.");
-	kmutex_unlock(&g_smscore_registrylock);
-	return entry;
-}
-
-int smscore_registry_getmode(char *devpath)
-{
-	struct smscore_registry_entry_t *entry;
-
-	entry = smscore_find_registry(devpath);
-	if (entry)
-		return entry->mode;
-	else
-		sms_err("No registry found.");
-
-	return default_mode;
-}
-EXPORT_SYMBOL_GPL(smscore_registry_getmode);
-
-static enum sms_device_type_st smscore_registry_gettype(char *devpath)
-{
-	struct smscore_registry_entry_t *entry;
-
-	entry = smscore_find_registry(devpath);
-	if (entry)
-		return entry->type;
-	else
-		sms_err("No registry found.");
-
-	return -1;
-}
-
-void smscore_registry_setmode(char *devpath, int mode)
-{
-	struct smscore_registry_entry_t *entry;
-
-	entry = smscore_find_registry(devpath);
-	if (entry)
-		entry->mode = mode;
-	else
-		sms_err("No registry found.");
-}
-
-static void smscore_registry_settype(char *devpath,
-				     enum sms_device_type_st type)
-{
-	struct smscore_registry_entry_t *entry;
-
-	entry = smscore_find_registry(devpath);
-	if (entry)
-		entry->type = type;
-	else
-		sms_err("No registry found.");
-}
-
-
-static void list_add_locked(struct list_head *new, struct list_head *head,
-			    spinlock_t *lock)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(lock, flags);
-
-	list_add(new, head);
-
-	spin_unlock_irqrestore(lock, flags);
-}
-
-/**
- * register a client callback that called when device plugged in/unplugged
- * NOTE: if devices exist callback is called immediately for each device
- *
- * @param hotplug callback
- *
- * @return 0 on success, <0 on error.
- */
-int smscore_register_hotplug(hotplug_t hotplug)
-{
-	struct smscore_device_notifyee_t *notifyee;
-	struct list_head *next, *first;
-	int rc = 0;
-
-	kmutex_lock(&g_smscore_deviceslock);
-
-	notifyee = kmalloc(sizeof(struct smscore_device_notifyee_t),
-			   GFP_KERNEL);
-	if (notifyee) {
-		/* now notify callback about existing devices */
-		first = &g_smscore_devices;
-		for (next = first->next;
-		     next != first && !rc;
-		     next = next->next) {
-			struct smscore_device_t *coredev =
-				(struct smscore_device_t *) next;
-			rc = hotplug(coredev, coredev->device, 1);
-		}
-
-		if (rc >= 0) {
-			notifyee->hotplug = hotplug;
-			list_add(&notifyee->entry, &g_smscore_notifyees);
-		} else
-			kfree(notifyee);
-	} else
-		rc = -ENOMEM;
-
-	kmutex_unlock(&g_smscore_deviceslock);
-
-	return rc;
-}
-EXPORT_SYMBOL_GPL(smscore_register_hotplug);
-
-/**
- * unregister a client callback that called when device plugged in/unplugged
- *
- * @param hotplug callback
- *
- */
-void smscore_unregister_hotplug(hotplug_t hotplug)
-{
-	struct list_head *next, *first;
-
-	kmutex_lock(&g_smscore_deviceslock);
-
-	first = &g_smscore_notifyees;
-
-	for (next = first->next; next != first;) {
-		struct smscore_device_notifyee_t *notifyee =
-			(struct smscore_device_notifyee_t *) next;
-		next = next->next;
-
-		if (notifyee->hotplug == hotplug) {
-			list_del(&notifyee->entry);
-			kfree(notifyee);
-		}
-	}
-
-	kmutex_unlock(&g_smscore_deviceslock);
-}
-EXPORT_SYMBOL_GPL(smscore_unregister_hotplug);
-
-static void smscore_notify_clients(struct smscore_device_t *coredev)
-{
-	struct smscore_client_t *client;
-
-	/* the client must call smscore_unregister_client from remove handler */
-	while (!list_empty(&coredev->clients)) {
-		client = (struct smscore_client_t *) coredev->clients.next;
-		client->onremove_handler(client->context);
-	}
-}
-
-static int smscore_notify_callbacks(struct smscore_device_t *coredev,
-				    struct device *device, int arrival)
-{
-	struct smscore_device_notifyee_t *elem;
-	int rc = 0;
-
-	/* note: must be called under g_deviceslock */
-
-	list_for_each_entry(elem, &g_smscore_notifyees, entry) {
-		rc = elem->hotplug(coredev, device, arrival);
-		if (rc < 0)
-			break;
-	}
-
-	return rc;
-}
-
-static struct
-smscore_buffer_t *smscore_createbuffer(u8 *buffer, void *common_buffer,
-				       dma_addr_t common_buffer_phys)
-{
-	struct smscore_buffer_t *cb =
-		kmalloc(sizeof(struct smscore_buffer_t), GFP_KERNEL);
-	if (!cb) {
-		sms_info("kmalloc(...) failed");
-		return NULL;
-	}
-
-	cb->p = buffer;
-	cb->offset_in_common = buffer - (u8 *) common_buffer;
-	cb->phys = common_buffer_phys + cb->offset_in_common;
-
-	return cb;
-}
-
-/**
- * creates coredev object for a device, prepares buffers,
- * creates buffer mappings, notifies registered hotplugs about new device.
- *
- * @param params device pointer to struct with device specific parameters
- *               and handlers
- * @param coredev pointer to a value that receives created coredev object
- *
- * @return 0 on success, <0 on error.
- */
-int smscore_register_device(struct smsdevice_params_t *params,
-			    struct smscore_device_t **coredev)
-{
-	struct smscore_device_t *dev;
-	u8 *buffer;
-
-	dev = kzalloc(sizeof(struct smscore_device_t), GFP_KERNEL);
-	if (!dev) {
-		sms_info("kzalloc(...) failed");
-		return -ENOMEM;
-	}
-
-	/* init list entry so it could be safe in smscore_unregister_device */
-	INIT_LIST_HEAD(&dev->entry);
-
-	/* init queues */
-	INIT_LIST_HEAD(&dev->clients);
-	INIT_LIST_HEAD(&dev->buffers);
-
-	/* init locks */
-	spin_lock_init(&dev->clientslock);
-	spin_lock_init(&dev->bufferslock);
-
-	/* init completion events */
-	init_completion(&dev->version_ex_done);
-	init_completion(&dev->data_download_done);
-	init_completion(&dev->trigger_done);
-	init_completion(&dev->init_device_done);
-	init_completion(&dev->reload_start_done);
-	init_completion(&dev->resume_done);
-	init_completion(&dev->gpio_configuration_done);
-	init_completion(&dev->gpio_set_level_done);
-	init_completion(&dev->gpio_get_level_done);
-	init_completion(&dev->ir_init_done);
-
-	/* Buffer management */
-	init_waitqueue_head(&dev->buffer_mng_waitq);
-
-	/* alloc common buffer */
-	dev->common_buffer_size = params->buffer_size * params->num_buffers;
-	dev->common_buffer = dma_alloc_coherent(NULL, dev->common_buffer_size,
-						&dev->common_buffer_phys,
-						GFP_KERNEL | GFP_DMA);
-	if (!dev->common_buffer) {
-		smscore_unregister_device(dev);
-		return -ENOMEM;
-	}
-
-	/* prepare dma buffers */
-	for (buffer = dev->common_buffer;
-	     dev->num_buffers < params->num_buffers;
-	     dev->num_buffers++, buffer += params->buffer_size) {
-		struct smscore_buffer_t *cb =
-			smscore_createbuffer(buffer, dev->common_buffer,
-					     dev->common_buffer_phys);
-		if (!cb) {
-			smscore_unregister_device(dev);
-			return -ENOMEM;
-		}
-
-		smscore_putbuffer(dev, cb);
-	}
-
-	sms_info("allocated %d buffers", dev->num_buffers);
-
-	dev->mode = DEVICE_MODE_NONE;
-	dev->context = params->context;
-	dev->device = params->device;
-	dev->setmode_handler = params->setmode_handler;
-	dev->detectmode_handler = params->detectmode_handler;
-	dev->sendrequest_handler = params->sendrequest_handler;
-	dev->preload_handler = params->preload_handler;
-	dev->postload_handler = params->postload_handler;
-
-	dev->device_flags = params->flags;
-	strcpy(dev->devpath, params->devpath);
-
-	smscore_registry_settype(dev->devpath, params->device_type);
-
-	/* add device to devices list */
-	kmutex_lock(&g_smscore_deviceslock);
-	list_add(&dev->entry, &g_smscore_devices);
-	kmutex_unlock(&g_smscore_deviceslock);
-
-	*coredev = dev;
-
-	sms_info("device %p created", dev);
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(smscore_register_device);
-
-
-static int smscore_sendrequest_and_wait(struct smscore_device_t *coredev,
-		void *buffer, size_t size, struct completion *completion) {
-	int rc = coredev->sendrequest_handler(coredev->context, buffer, size);
-	if (rc < 0) {
-		sms_info("sendrequest returned error %d", rc);
-		return rc;
-	}
-
-	return wait_for_completion_timeout(completion,
-			msecs_to_jiffies(SMS_PROTOCOL_MAX_RAOUNDTRIP_MS)) ?
-			0 : -ETIME;
-}
-
-/**
- * Starts & enables IR operations
- *
- * @return 0 on success, < 0 on error.
- */
-static int smscore_init_ir(struct smscore_device_t *coredev)
-{
-	int ir_io;
-	int rc;
-	void *buffer;
-
-	coredev->ir.dev = NULL;
-	ir_io = sms_get_board(smscore_get_board_id(coredev))->board_cfg.ir;
-	if (ir_io) {/* only if IR port exist we use IR sub-module */
-		sms_info("IR loading");
-		rc = sms_ir_init(coredev);
-
-		if	(rc != 0)
-			sms_err("Error initialization DTV IR sub-module");
-		else {
-			buffer = kmalloc(sizeof(struct SmsMsgData_ST2) +
-						SMS_DMA_ALIGNMENT,
-						GFP_KERNEL | GFP_DMA);
-			if (buffer) {
-				struct SmsMsgData_ST2 *msg =
-				(struct SmsMsgData_ST2 *)
-				SMS_ALIGN_ADDRESS(buffer);
-
-				SMS_INIT_MSG(&msg->xMsgHeader,
-						MSG_SMS_START_IR_REQ,
-						sizeof(struct SmsMsgData_ST2));
-				msg->msgData[0] = coredev->ir.controller;
-				msg->msgData[1] = coredev->ir.timeout;
-
-				smsendian_handle_tx_message(
-					(struct SmsMsgHdr_ST2 *)msg);
-				rc = smscore_sendrequest_and_wait(coredev, msg,
-						msg->xMsgHeader. msgLength,
-						&coredev->ir_init_done);
-
-				kfree(buffer);
-			} else
-				sms_err
-				("Sending IR initialization message failed");
-		}
-	} else
-		sms_info("IR port has not been detected");
-
-	return 0;
-}
-
-/**
- * sets initial device mode and notifies client hotplugs that device is ready
- *
- * @param coredev pointer to a coredev object returned by
- * 		  smscore_register_device
- *
- * @return 0 on success, <0 on error.
- */
-int smscore_start_device(struct smscore_device_t *coredev)
-{
-	int rc = smscore_set_device_mode(
-			coredev, smscore_registry_getmode(coredev->devpath));
-	if (rc < 0) {
-		sms_info("set device mode faile , rc %d", rc);
-		return rc;
-	}
-
-	kmutex_lock(&g_smscore_deviceslock);
-
-	rc = smscore_notify_callbacks(coredev, coredev->device, 1);
-	smscore_init_ir(coredev);
-
-	sms_info("device %p started, rc %d", coredev, rc);
-
-	kmutex_unlock(&g_smscore_deviceslock);
-
-	return rc;
-}
-EXPORT_SYMBOL_GPL(smscore_start_device);
-
-
-static int smscore_load_firmware_family2(struct smscore_device_t *coredev,
-					 void *buffer, size_t size)
-{
-	struct SmsFirmware_ST *firmware = (struct SmsFirmware_ST *) buffer;
-	struct SmsMsgHdr_ST *msg;
-	u32 mem_address;
-	u8 *payload = firmware->Payload;
-	int rc = 0;
-	firmware->StartAddress = le32_to_cpu(firmware->StartAddress);
-	firmware->Length = le32_to_cpu(firmware->Length);
-
-	mem_address = firmware->StartAddress;
-
-	sms_info("loading FW to addr 0x%x size %d",
-		 mem_address, firmware->Length);
-	if (coredev->preload_handler) {
-		rc = coredev->preload_handler(coredev->context);
-		if (rc < 0)
-			return rc;
-	}
-
-	/* PAGE_SIZE buffer shall be enough and dma aligned */
-	msg = kmalloc(PAGE_SIZE, GFP_KERNEL | GFP_DMA);
-	if (!msg)
-		return -ENOMEM;
-
-	if (coredev->mode != DEVICE_MODE_NONE) {
-		sms_debug("sending reload command.");
-		SMS_INIT_MSG(msg, MSG_SW_RELOAD_START_REQ,
-			     sizeof(struct SmsMsgHdr_ST));
-		rc = smscore_sendrequest_and_wait(coredev, msg,
-						  msg->msgLength,
-						  &coredev->reload_start_done);
-		mem_address = *(u32 *) &payload[20];
-	}
-
-	while (size && rc >= 0) {
-		struct SmsDataDownload_ST *DataMsg =
-			(struct SmsDataDownload_ST *) msg;
-		int payload_size = min((int) size, SMS_MAX_PAYLOAD_SIZE);
-
-		SMS_INIT_MSG(msg, MSG_SMS_DATA_DOWNLOAD_REQ,
-			     (u16)(sizeof(struct SmsMsgHdr_ST) +
-				      sizeof(u32) + payload_size));
-
-		DataMsg->MemAddr = mem_address;
-		memcpy(DataMsg->Payload, payload, payload_size);
-
-		if ((coredev->device_flags & SMS_ROM_NO_RESPONSE) &&
-		    (coredev->mode == DEVICE_MODE_NONE))
-			rc = coredev->sendrequest_handler(
-				coredev->context, DataMsg,
-				DataMsg->xMsgHeader.msgLength);
-		else
-			rc = smscore_sendrequest_and_wait(
-				coredev, DataMsg,
-				DataMsg->xMsgHeader.msgLength,
-				&coredev->data_download_done);
-
-		payload += payload_size;
-		size -= payload_size;
-		mem_address += payload_size;
-	}
-
-	if (rc >= 0) {
-		if (coredev->mode == DEVICE_MODE_NONE) {
-			struct SmsMsgData_ST *TriggerMsg =
-				(struct SmsMsgData_ST *) msg;
-
-			SMS_INIT_MSG(msg, MSG_SMS_SWDOWNLOAD_TRIGGER_REQ,
-				     sizeof(struct SmsMsgHdr_ST) +
-				     sizeof(u32) * 5);
-
-			TriggerMsg->msgData[0] = firmware->StartAddress;
-						/* Entry point */
-			TriggerMsg->msgData[1] = 5; /* Priority */
-			TriggerMsg->msgData[2] = 0x200; /* Stack size */
-			TriggerMsg->msgData[3] = 0; /* Parameter */
-			TriggerMsg->msgData[4] = 4; /* Task ID */
-
-			if (coredev->device_flags & SMS_ROM_NO_RESPONSE) {
-				rc = coredev->sendrequest_handler(
-					coredev->context, TriggerMsg,
-					TriggerMsg->xMsgHeader.msgLength);
-				msleep(100);
-			} else
-				rc = smscore_sendrequest_and_wait(
-					coredev, TriggerMsg,
-					TriggerMsg->xMsgHeader.msgLength,
-					&coredev->trigger_done);
-		} else {
-			SMS_INIT_MSG(msg, MSG_SW_RELOAD_EXEC_REQ,
-				     sizeof(struct SmsMsgHdr_ST));
-
-			rc = coredev->sendrequest_handler(coredev->context,
-							  msg, msg->msgLength);
-		}
-		msleep(500);
-	}
-
-	sms_debug("rc=%d, postload=%p ", rc,
-		  coredev->postload_handler);
-
-	kfree(msg);
-
-	return ((rc >= 0) && coredev->postload_handler) ?
-		coredev->postload_handler(coredev->context) :
-		rc;
-}
-
-/**
- * loads specified firmware into a buffer and calls device loadfirmware_handler
- *
- * @param coredev pointer to a coredev object returned by
- *                smscore_register_device
- * @param filename null-terminated string specifies firmware file name
- * @param loadfirmware_handler device handler that loads firmware
- *
- * @return 0 on success, <0 on error.
- */
-static int smscore_load_firmware_from_file(struct smscore_device_t *coredev,
-					   char *filename,
-					   loadfirmware_t loadfirmware_handler)
-{
-	int rc = -ENOENT;
-	const struct firmware *fw;
-	u8 *fw_buffer;
-
-	if (loadfirmware_handler == NULL && !(coredev->device_flags &
-					      SMS_DEVICE_FAMILY2))
-		return -EINVAL;
-
-	rc = request_firmware(&fw, filename, coredev->device);
-	if (rc < 0) {
-		sms_info("failed to open \"%s\"", filename);
-		return rc;
-	}
-	sms_info("read FW %s, size=%zd", filename, fw->size);
-	fw_buffer = kmalloc(ALIGN(fw->size, SMS_ALLOC_ALIGNMENT),
-			    GFP_KERNEL | GFP_DMA);
-	if (fw_buffer) {
-		memcpy(fw_buffer, fw->data, fw->size);
-
-		rc = (coredev->device_flags & SMS_DEVICE_FAMILY2) ?
-		      smscore_load_firmware_family2(coredev,
-						    fw_buffer,
-						    fw->size) :
-		      loadfirmware_handler(coredev->context,
-					   fw_buffer, fw->size);
-
-		kfree(fw_buffer);
-	} else {
-		sms_info("failed to allocate firmware buffer");
-		rc = -ENOMEM;
-	}
-
-	release_firmware(fw);
-
-	return rc;
-}
-
-/**
- * notifies all clients registered with the device, notifies hotplugs,
- * frees all buffers and coredev object
- *
- * @param coredev pointer to a coredev object returned by
- *                smscore_register_device
- *
- * @return 0 on success, <0 on error.
- */
-void smscore_unregister_device(struct smscore_device_t *coredev)
-{
-	struct smscore_buffer_t *cb;
-	int num_buffers = 0;
-	int retry = 0;
-
-	kmutex_lock(&g_smscore_deviceslock);
-
-	/* Release input device (IR) resources */
-	sms_ir_exit(coredev);
-
-	smscore_notify_clients(coredev);
-	smscore_notify_callbacks(coredev, NULL, 0);
-
-	/* at this point all buffers should be back
-	 * onresponse must no longer be called */
-
-	while (1) {
-		while (!list_empty(&coredev->buffers)) {
-			cb = (struct smscore_buffer_t *) coredev->buffers.next;
-			list_del(&cb->entry);
-			kfree(cb);
-			num_buffers++;
-		}
-		if (num_buffers == coredev->num_buffers)
-			break;
-		if (++retry > 10) {
-			sms_info("exiting although "
-				 "not all buffers released.");
-			break;
-		}
-
-		sms_info("waiting for %d buffer(s)",
-			 coredev->num_buffers - num_buffers);
-		msleep(100);
-	}
-
-	sms_info("freed %d buffers", num_buffers);
-
-	if (coredev->common_buffer)
-		dma_free_coherent(NULL, coredev->common_buffer_size,
-			coredev->common_buffer, coredev->common_buffer_phys);
-
-	if (coredev->fw_buf != NULL)
-		kfree(coredev->fw_buf);
-
-	list_del(&coredev->entry);
-	kfree(coredev);
-
-	kmutex_unlock(&g_smscore_deviceslock);
-
-	sms_info("device %p destroyed", coredev);
-}
-EXPORT_SYMBOL_GPL(smscore_unregister_device);
-
-static int smscore_detect_mode(struct smscore_device_t *coredev)
-{
-	void *buffer = kmalloc(sizeof(struct SmsMsgHdr_ST) + SMS_DMA_ALIGNMENT,
-			       GFP_KERNEL | GFP_DMA);
-	struct SmsMsgHdr_ST *msg =
-		(struct SmsMsgHdr_ST *) SMS_ALIGN_ADDRESS(buffer);
-	int rc;
-
-	if (!buffer)
-		return -ENOMEM;
-
-	SMS_INIT_MSG(msg, MSG_SMS_GET_VERSION_EX_REQ,
-		     sizeof(struct SmsMsgHdr_ST));
-
-	rc = smscore_sendrequest_and_wait(coredev, msg, msg->msgLength,
-					  &coredev->version_ex_done);
-	if (rc == -ETIME) {
-		sms_err("MSG_SMS_GET_VERSION_EX_REQ failed first try");
-
-		if (wait_for_completion_timeout(&coredev->resume_done,
-						msecs_to_jiffies(5000))) {
-			rc = smscore_sendrequest_and_wait(
-				coredev, msg, msg->msgLength,
-				&coredev->version_ex_done);
-			if (rc < 0)
-				sms_err("MSG_SMS_GET_VERSION_EX_REQ failed "
-					"second try, rc %d", rc);
-		} else
-			rc = -ETIME;
-	}
-
-	kfree(buffer);
-
-	return rc;
-}
-
-static char *smscore_fw_lkup[][SMS_NUM_OF_DEVICE_TYPES] = {
-	/*Stellar		NOVA A0		Nova B0		VEGA*/
-	/*DVBT*/
-	{"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"},
-	/*DVBH*/
-	{"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"},
-	/*TDMB*/
-	{"none", "tdmb_nova_12mhz.inp", "tdmb_nova_12mhz_b0.inp", "none"},
-	/*DABIP*/
-	{"none", "none", "none", "none"},
-	/*BDA*/
-	{"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"},
-	/*ISDBT*/
-	{"none", "isdbt_nova_12mhz.inp", "isdbt_nova_12mhz_b0.inp", "none"},
-	/*ISDBTBDA*/
-	{"none", "isdbt_nova_12mhz.inp", "isdbt_nova_12mhz_b0.inp", "none"},
-	/*CMMB*/
-	{"none", "none", "none", "cmmb_vega_12mhz.inp"}
-};
-
-static inline char *sms_get_fw_name(struct smscore_device_t *coredev,
-				    int mode, enum sms_device_type_st type)
-{
-	char **fw = sms_get_board(smscore_get_board_id(coredev))->fw;
-	return (fw && fw[mode]) ? fw[mode] : smscore_fw_lkup[mode][type];
-}
-
-/**
- * calls device handler to change mode of operation
- * NOTE: stellar/usb may disconnect when changing mode
- *
- * @param coredev pointer to a coredev object returned by
- *                smscore_register_device
- * @param mode requested mode of operation
- *
- * @return 0 on success, <0 on error.
- */
-int smscore_set_device_mode(struct smscore_device_t *coredev, int mode)
-{
-	void *buffer;
-	int rc = 0;
-	enum sms_device_type_st type;
-
-	sms_debug("set device mode to %d", mode);
-	if (coredev->device_flags & SMS_DEVICE_FAMILY2) {
-		if (mode < DEVICE_MODE_DVBT || mode >= DEVICE_MODE_RAW_TUNER) {
-			sms_err("invalid mode specified %d", mode);
-			return -EINVAL;
-		}
-
-		smscore_registry_setmode(coredev->devpath, mode);
-
-		if (!(coredev->device_flags & SMS_DEVICE_NOT_READY)) {
-			rc = smscore_detect_mode(coredev);
-			if (rc < 0) {
-				sms_err("mode detect failed %d", rc);
-				return rc;
-			}
-		}
-
-		if (coredev->mode == mode) {
-			sms_info("device mode %d already set", mode);
-			return 0;
-		}
-
-		if (!(coredev->modes_supported & (1 << mode))) {
-			char *fw_filename;
-
-			type = smscore_registry_gettype(coredev->devpath);
-			fw_filename = sms_get_fw_name(coredev, mode, type);
-
-			rc = smscore_load_firmware_from_file(coredev,
-							     fw_filename, NULL);
-			if (rc < 0) {
-				sms_warn("error %d loading firmware: %s, "
-					 "trying again with default firmware",
-					 rc, fw_filename);
-
-				/* try again with the default firmware */
-				fw_filename = smscore_fw_lkup[mode][type];
-				rc = smscore_load_firmware_from_file(coredev,
-							     fw_filename, NULL);
-
-				if (rc < 0) {
-					sms_warn("error %d loading "
-						 "firmware: %s", rc,
-						 fw_filename);
-					return rc;
-				}
-			}
-			sms_log("firmware download success: %s", fw_filename);
-		} else
-			sms_info("mode %d supported by running "
-				 "firmware", mode);
-
-		buffer = kmalloc(sizeof(struct SmsMsgData_ST) +
-				 SMS_DMA_ALIGNMENT, GFP_KERNEL | GFP_DMA);
-		if (buffer) {
-			struct SmsMsgData_ST *msg =
-				(struct SmsMsgData_ST *)
-					SMS_ALIGN_ADDRESS(buffer);
-
-			SMS_INIT_MSG(&msg->xMsgHeader, MSG_SMS_INIT_DEVICE_REQ,
-				     sizeof(struct SmsMsgData_ST));
-			msg->msgData[0] = mode;
-
-			rc = smscore_sendrequest_and_wait(
-				coredev, msg, msg->xMsgHeader.msgLength,
-				&coredev->init_device_done);
-
-			kfree(buffer);
-		} else {
-			sms_err("Could not allocate buffer for "
-				"init device message.");
-			rc = -ENOMEM;
-		}
-	} else {
-		if (mode < DEVICE_MODE_DVBT || mode > DEVICE_MODE_DVBT_BDA) {
-			sms_err("invalid mode specified %d", mode);
-			return -EINVAL;
-		}
-
-		smscore_registry_setmode(coredev->devpath, mode);
-
-		if (coredev->detectmode_handler)
-			coredev->detectmode_handler(coredev->context,
-						    &coredev->mode);
-
-		if (coredev->mode != mode && coredev->setmode_handler)
-			rc = coredev->setmode_handler(coredev->context, mode);
-	}
-
-	if (rc >= 0) {
-		coredev->mode = mode;
-		coredev->device_flags &= ~SMS_DEVICE_NOT_READY;
-	}
-
-	if (rc < 0)
-		sms_err("return error code %d.", rc);
-	return rc;
-}
-
-/**
- * calls device handler to get current mode of operation
- *
- * @param coredev pointer to a coredev object returned by
- *                smscore_register_device
- *
- * @return current mode
- */
-int smscore_get_device_mode(struct smscore_device_t *coredev)
-{
-	return coredev->mode;
-}
-EXPORT_SYMBOL_GPL(smscore_get_device_mode);
-
-/**
- * find client by response id & type within the clients list.
- * return client handle or NULL.
- *
- * @param coredev pointer to a coredev object returned by
- *                smscore_register_device
- * @param data_type client data type (SMS_DONT_CARE for all types)
- * @param id client id (SMS_DONT_CARE for all id)
- *
- */
-static struct
-smscore_client_t *smscore_find_client(struct smscore_device_t *coredev,
-				      int data_type, int id)
-{
-	struct list_head *first;
-	struct smscore_client_t *client;
-	unsigned long flags;
-	struct list_head *firstid;
-	struct smscore_idlist_t *client_id;
-
-	spin_lock_irqsave(&coredev->clientslock, flags);
-	first = &coredev->clients;
-	list_for_each_entry(client, first, entry) {
-		firstid = &client->idlist;
-		list_for_each_entry(client_id, firstid, entry) {
-			if ((client_id->id == id) &&
-			    (client_id->data_type == data_type ||
-			    (client_id->data_type == 0)))
-				goto found;
-		}
-	}
-	client = NULL;
-found:
-	spin_unlock_irqrestore(&coredev->clientslock, flags);
-	return client;
-}
-
-/**
- * find client by response id/type, call clients onresponse handler
- * return buffer to pool on error
- *
- * @param coredev pointer to a coredev object returned by
- *                smscore_register_device
- * @param cb pointer to response buffer descriptor
- *
- */
-void smscore_onresponse(struct smscore_device_t *coredev,
-		struct smscore_buffer_t *cb) {
-	struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *) ((u8 *) cb->p
-			+ cb->offset);
-	struct smscore_client_t *client;
-	int rc = -EBUSY;
-	static unsigned long last_sample_time; /* = 0; */
-	static int data_total; /* = 0; */
-	unsigned long time_now = jiffies_to_msecs(jiffies);
-
-	if (!last_sample_time)
-		last_sample_time = time_now;
-
-	if (time_now - last_sample_time > 10000) {
-		sms_debug("\ndata rate %d bytes/secs",
-			  (int)((data_total * 1000) /
-				(time_now - last_sample_time)));
-
-		last_sample_time = time_now;
-		data_total = 0;
-	}
-
-	data_total += cb->size;
-	/* Do we need to re-route? */
-	if ((phdr->msgType == MSG_SMS_HO_PER_SLICES_IND) ||
-			(phdr->msgType == MSG_SMS_TRANSMISSION_IND)) {
-		if (coredev->mode == DEVICE_MODE_DVBT_BDA)
-			phdr->msgDstId = DVBT_BDA_CONTROL_MSG_ID;
-	}
-
-
-	client = smscore_find_client(coredev, phdr->msgType, phdr->msgDstId);
-
-	/* If no client registered for type & id,
-	 * check for control client where type is not registered */
-	if (client)
-		rc = client->onresponse_handler(client->context, cb);
-
-	if (rc < 0) {
-		switch (phdr->msgType) {
-		case MSG_SMS_GET_VERSION_EX_RES:
-		{
-			struct SmsVersionRes_ST *ver =
-				(struct SmsVersionRes_ST *) phdr;
-			sms_debug("MSG_SMS_GET_VERSION_EX_RES "
-				  "id %d prots 0x%x ver %d.%d",
-				  ver->FirmwareId, ver->SupportedProtocols,
-				  ver->RomVersionMajor, ver->RomVersionMinor);
-
-			coredev->mode = ver->FirmwareId == 255 ?
-				DEVICE_MODE_NONE : ver->FirmwareId;
-			coredev->modes_supported = ver->SupportedProtocols;
-
-			complete(&coredev->version_ex_done);
-			break;
-		}
-		case MSG_SMS_INIT_DEVICE_RES:
-			sms_debug("MSG_SMS_INIT_DEVICE_RES");
-			complete(&coredev->init_device_done);
-			break;
-		case MSG_SW_RELOAD_START_RES:
-			sms_debug("MSG_SW_RELOAD_START_RES");
-			complete(&coredev->reload_start_done);
-			break;
-		case MSG_SMS_DATA_DOWNLOAD_RES:
-			complete(&coredev->data_download_done);
-			break;
-		case MSG_SW_RELOAD_EXEC_RES:
-			sms_debug("MSG_SW_RELOAD_EXEC_RES");
-			break;
-		case MSG_SMS_SWDOWNLOAD_TRIGGER_RES:
-			sms_debug("MSG_SMS_SWDOWNLOAD_TRIGGER_RES");
-			complete(&coredev->trigger_done);
-			break;
-		case MSG_SMS_SLEEP_RESUME_COMP_IND:
-			complete(&coredev->resume_done);
-			break;
-		case MSG_SMS_GPIO_CONFIG_EX_RES:
-			sms_debug("MSG_SMS_GPIO_CONFIG_EX_RES");
-			complete(&coredev->gpio_configuration_done);
-			break;
-		case MSG_SMS_GPIO_SET_LEVEL_RES:
-			sms_debug("MSG_SMS_GPIO_SET_LEVEL_RES");
-			complete(&coredev->gpio_set_level_done);
-			break;
-		case MSG_SMS_GPIO_GET_LEVEL_RES:
-		{
-			u32 *msgdata = (u32 *) phdr;
-			coredev->gpio_get_res = msgdata[1];
-			sms_debug("MSG_SMS_GPIO_GET_LEVEL_RES gpio level %d",
-					coredev->gpio_get_res);
-			complete(&coredev->gpio_get_level_done);
-			break;
-		}
-		case MSG_SMS_START_IR_RES:
-			complete(&coredev->ir_init_done);
-			break;
-		case MSG_SMS_IR_SAMPLES_IND:
-			sms_ir_event(coredev,
-				(const char *)
-				((char *)phdr
-				+ sizeof(struct SmsMsgHdr_ST)),
-				(int)phdr->msgLength
-				- sizeof(struct SmsMsgHdr_ST));
-			break;
-
-		default:
-			break;
-		}
-		smscore_putbuffer(coredev, cb);
-	}
-}
-EXPORT_SYMBOL_GPL(smscore_onresponse);
-
-/**
- * return pointer to next free buffer descriptor from core pool
- *
- * @param coredev pointer to a coredev object returned by
- *                smscore_register_device
- *
- * @return pointer to descriptor on success, NULL on error.
- */
-
-struct smscore_buffer_t *get_entry(struct smscore_device_t *coredev)
-{
-	struct smscore_buffer_t *cb = NULL;
-	unsigned long flags;
-
-	spin_lock_irqsave(&coredev->bufferslock, flags);
-	if (!list_empty(&coredev->buffers)) {
-		cb = (struct smscore_buffer_t *) coredev->buffers.next;
-		list_del(&cb->entry);
-	}
-	spin_unlock_irqrestore(&coredev->bufferslock, flags);
-	return cb;
-}
-
-struct smscore_buffer_t *smscore_getbuffer(struct smscore_device_t *coredev)
-{
-	struct smscore_buffer_t *cb = NULL;
-
-	wait_event(coredev->buffer_mng_waitq, (cb = get_entry(coredev)));
-
-	return cb;
-}
-EXPORT_SYMBOL_GPL(smscore_getbuffer);
-
-/**
- * return buffer descriptor to a pool
- *
- * @param coredev pointer to a coredev object returned by
- *                smscore_register_device
- * @param cb pointer buffer descriptor
- *
- */
-void smscore_putbuffer(struct smscore_device_t *coredev,
-		struct smscore_buffer_t *cb) {
-	wake_up_interruptible(&coredev->buffer_mng_waitq);
-	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,
-				   int data_type, int id)
-{
-	struct smscore_idlist_t *listentry;
-	struct smscore_client_t *registered_client;
-
-	if (!client) {
-		sms_err("bad parameter.");
-		return -EINVAL;
-	}
-	registered_client = smscore_find_client(coredev, data_type, id);
-	if (registered_client == client)
-		return 0;
-
-	if (registered_client) {
-		sms_err("The msg ID already registered to another client.");
-		return -EEXIST;
-	}
-	listentry = kzalloc(sizeof(struct smscore_idlist_t), GFP_KERNEL);
-	if (!listentry) {
-		sms_err("Can't allocate memory for client id.");
-		return -ENOMEM;
-	}
-	listentry->id = id;
-	listentry->data_type = data_type;
-	list_add_locked(&listentry->entry, &client->idlist,
-			&coredev->clientslock);
-	return 0;
-}
-
-/**
- * creates smsclient object, check that id is taken by another client
- *
- * @param coredev pointer to a coredev object from clients hotplug
- * @param initial_id all messages with this id would be sent to this client
- * @param data_type all messages of this type would be sent to this client
- * @param onresponse_handler client handler that is called to
- *                           process incoming messages
- * @param onremove_handler client handler that is called when device is removed
- * @param context client-specific context
- * @param client pointer to a value that receives created smsclient object
- *
- * @return 0 on success, <0 on error.
- */
-int smscore_register_client(struct smscore_device_t *coredev,
-			    struct smsclient_params_t *params,
-			    struct smscore_client_t **client)
-{
-	struct smscore_client_t *newclient;
-	/* check that no other channel with same parameters exists */
-	if (smscore_find_client(coredev, params->data_type,
-				params->initial_id)) {
-		sms_err("Client already exist.");
-		return -EEXIST;
-	}
-
-	newclient = kzalloc(sizeof(struct smscore_client_t), GFP_KERNEL);
-	if (!newclient) {
-		sms_err("Failed to allocate memory for client.");
-		return -ENOMEM;
-	}
-
-	INIT_LIST_HEAD(&newclient->idlist);
-	newclient->coredev = coredev;
-	newclient->onresponse_handler = params->onresponse_handler;
-	newclient->onremove_handler = params->onremove_handler;
-	newclient->context = params->context;
-	list_add_locked(&newclient->entry, &coredev->clients,
-			&coredev->clientslock);
-	smscore_validate_client(coredev, newclient, params->data_type,
-				params->initial_id);
-	*client = newclient;
-	sms_debug("%p %d %d", params->context, params->data_type,
-		  params->initial_id);
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(smscore_register_client);
-
-/**
- * frees smsclient object and all subclients associated with it
- *
- * @param client pointer to smsclient object returned by
- *               smscore_register_client
- *
- */
-void smscore_unregister_client(struct smscore_client_t *client)
-{
-	struct smscore_device_t *coredev = client->coredev;
-	unsigned long flags;
-
-	spin_lock_irqsave(&coredev->clientslock, flags);
-
-
-	while (!list_empty(&client->idlist)) {
-		struct smscore_idlist_t *identry =
-			(struct smscore_idlist_t *) client->idlist.next;
-		list_del(&identry->entry);
-		kfree(identry);
-	}
-
-	sms_info("%p", client->context);
-
-	list_del(&client->entry);
-	kfree(client);
-
-	spin_unlock_irqrestore(&coredev->clientslock, flags);
-}
-EXPORT_SYMBOL_GPL(smscore_unregister_client);
-
-/**
- * verifies that source id is not taken by another client,
- * calls device handler to send requests to the device
- *
- * @param client pointer to smsclient object returned by
- *               smscore_register_client
- * @param buffer pointer to a request buffer
- * @param size size (in bytes) of request buffer
- *
- * @return 0 on success, <0 on error.
- */
-int smsclient_sendrequest(struct smscore_client_t *client,
-			  void *buffer, size_t size)
-{
-	struct smscore_device_t *coredev;
-	struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *) buffer;
-	int rc;
-
-	if (client == NULL) {
-		sms_err("Got NULL client");
-		return -EINVAL;
-	}
-
-	coredev = client->coredev;
-
-	/* check that no other channel with same id exists */
-	if (coredev == NULL) {
-		sms_err("Got NULL coredev");
-		return -EINVAL;
-	}
-
-	rc = smscore_validate_client(client->coredev, client, 0,
-				     phdr->msgSrcId);
-	if (rc < 0)
-		return rc;
-
-	return coredev->sendrequest_handler(coredev->context, buffer, size);
-}
-EXPORT_SYMBOL_GPL(smsclient_sendrequest);
-
-
-/* old GPIO managements implementation */
-int smscore_configure_gpio(struct smscore_device_t *coredev, u32 pin,
-			   struct smscore_config_gpio *pinconfig)
-{
-	struct {
-		struct SmsMsgHdr_ST hdr;
-		u32 data[6];
-	} msg;
-
-	if (coredev->device_flags & SMS_DEVICE_FAMILY2) {
-		msg.hdr.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
-		msg.hdr.msgDstId = HIF_TASK;
-		msg.hdr.msgFlags = 0;
-		msg.hdr.msgType  = MSG_SMS_GPIO_CONFIG_EX_REQ;
-		msg.hdr.msgLength = sizeof(msg);
-
-		msg.data[0] = pin;
-		msg.data[1] = pinconfig->pullupdown;
-
-		/* Convert slew rate for Nova: Fast(0) = 3 / Slow(1) = 0; */
-		msg.data[2] = pinconfig->outputslewrate == 0 ? 3 : 0;
-
-		switch (pinconfig->outputdriving) {
-		case SMS_GPIO_OUTPUTDRIVING_16mA:
-			msg.data[3] = 7; /* Nova - 16mA */
-			break;
-		case SMS_GPIO_OUTPUTDRIVING_12mA:
-			msg.data[3] = 5; /* Nova - 11mA */
-			break;
-		case SMS_GPIO_OUTPUTDRIVING_8mA:
-			msg.data[3] = 3; /* Nova - 7mA */
-			break;
-		case SMS_GPIO_OUTPUTDRIVING_4mA:
-		default:
-			msg.data[3] = 2; /* Nova - 4mA */
-			break;
-		}
-
-		msg.data[4] = pinconfig->direction;
-		msg.data[5] = 0;
-	} else /* TODO: SMS_DEVICE_FAMILY1 */
-		return -EINVAL;
-
-	return coredev->sendrequest_handler(coredev->context,
-					    &msg, sizeof(msg));
-}
-
-int smscore_set_gpio(struct smscore_device_t *coredev, u32 pin, int level)
-{
-	struct {
-		struct SmsMsgHdr_ST hdr;
-		u32 data[3];
-	} msg;
-
-	if (pin > MAX_GPIO_PIN_NUMBER)
-		return -EINVAL;
-
-	msg.hdr.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
-	msg.hdr.msgDstId = HIF_TASK;
-	msg.hdr.msgFlags = 0;
-	msg.hdr.msgType  = MSG_SMS_GPIO_SET_LEVEL_REQ;
-	msg.hdr.msgLength = sizeof(msg);
-
-	msg.data[0] = pin;
-	msg.data[1] = level ? 1 : 0;
-	msg.data[2] = 0;
-
-	return coredev->sendrequest_handler(coredev->context,
-					    &msg, sizeof(msg));
-}
-
-/* new GPIO management implementation */
-static int GetGpioPinParams(u32 PinNum, u32 *pTranslatedPinNum,
-		u32 *pGroupNum, u32 *pGroupCfg) {
-
-	*pGroupCfg = 1;
-
-	if (PinNum <= 1)	{
-		*pTranslatedPinNum = 0;
-		*pGroupNum = 9;
-		*pGroupCfg = 2;
-	} else if (PinNum >= 2 && PinNum <= 6) {
-		*pTranslatedPinNum = 2;
-		*pGroupNum = 0;
-		*pGroupCfg = 2;
-	} else if (PinNum >= 7 && PinNum <= 11) {
-		*pTranslatedPinNum = 7;
-		*pGroupNum = 1;
-	} else if (PinNum >= 12 && PinNum <= 15) {
-		*pTranslatedPinNum = 12;
-		*pGroupNum = 2;
-		*pGroupCfg = 3;
-	} else if (PinNum == 16) {
-		*pTranslatedPinNum = 16;
-		*pGroupNum = 23;
-	} else if (PinNum >= 17 && PinNum <= 24) {
-		*pTranslatedPinNum = 17;
-		*pGroupNum = 3;
-	} else if (PinNum == 25) {
-		*pTranslatedPinNum = 25;
-		*pGroupNum = 6;
-	} else if (PinNum >= 26 && PinNum <= 28) {
-		*pTranslatedPinNum = 26;
-		*pGroupNum = 4;
-	} else if (PinNum == 29) {
-		*pTranslatedPinNum = 29;
-		*pGroupNum = 5;
-		*pGroupCfg = 2;
-	} else if (PinNum == 30) {
-		*pTranslatedPinNum = 30;
-		*pGroupNum = 8;
-	} else if (PinNum == 31) {
-		*pTranslatedPinNum = 31;
-		*pGroupNum = 17;
-	} else
-		return -1;
-
-	*pGroupCfg <<= 24;
-
-	return 0;
-}
-
-int smscore_gpio_configure(struct smscore_device_t *coredev, u8 PinNum,
-		struct smscore_gpio_config *pGpioConfig) {
-
-	u32 totalLen;
-	u32 TranslatedPinNum = 0;
-	u32 GroupNum = 0;
-	u32 ElectricChar;
-	u32 groupCfg;
-	void *buffer;
-	int rc;
-
-	struct SetGpioMsg {
-		struct SmsMsgHdr_ST xMsgHeader;
-		u32 msgData[6];
-	} *pMsg;
-
-
-	if (PinNum > MAX_GPIO_PIN_NUMBER)
-		return -EINVAL;
-
-	if (pGpioConfig == NULL)
-		return -EINVAL;
-
-	totalLen = sizeof(struct SmsMsgHdr_ST) + (sizeof(u32) * 6);
-
-	buffer = kmalloc(totalLen + SMS_DMA_ALIGNMENT,
-			GFP_KERNEL | GFP_DMA);
-	if (!buffer)
-		return -ENOMEM;
-
-	pMsg = (struct SetGpioMsg *) SMS_ALIGN_ADDRESS(buffer);
-
-	pMsg->xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
-	pMsg->xMsgHeader.msgDstId = HIF_TASK;
-	pMsg->xMsgHeader.msgFlags = 0;
-	pMsg->xMsgHeader.msgLength = (u16) totalLen;
-	pMsg->msgData[0] = PinNum;
-
-	if (!(coredev->device_flags & SMS_DEVICE_FAMILY2)) {
-		pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_CONFIG_REQ;
-		if (GetGpioPinParams(PinNum, &TranslatedPinNum, &GroupNum,
-				&groupCfg) != 0) {
-			rc = -EINVAL;
-			goto free;
-		}
-
-		pMsg->msgData[1] = TranslatedPinNum;
-		pMsg->msgData[2] = GroupNum;
-		ElectricChar = (pGpioConfig->PullUpDown)
-				| (pGpioConfig->InputCharacteristics << 2)
-				| (pGpioConfig->OutputSlewRate << 3)
-				| (pGpioConfig->OutputDriving << 4);
-		pMsg->msgData[3] = ElectricChar;
-		pMsg->msgData[4] = pGpioConfig->Direction;
-		pMsg->msgData[5] = groupCfg;
-	} else {
-		pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_CONFIG_EX_REQ;
-		pMsg->msgData[1] = pGpioConfig->PullUpDown;
-		pMsg->msgData[2] = pGpioConfig->OutputSlewRate;
-		pMsg->msgData[3] = pGpioConfig->OutputDriving;
-		pMsg->msgData[4] = pGpioConfig->Direction;
-		pMsg->msgData[5] = 0;
-	}
-
-	smsendian_handle_tx_message((struct SmsMsgHdr_ST *)pMsg);
-	rc = smscore_sendrequest_and_wait(coredev, pMsg, totalLen,
-			&coredev->gpio_configuration_done);
-
-	if (rc != 0) {
-		if (rc == -ETIME)
-			sms_err("smscore_gpio_configure timeout");
-		else
-			sms_err("smscore_gpio_configure error");
-	}
-free:
-	kfree(buffer);
-
-	return rc;
-}
-
-int smscore_gpio_set_level(struct smscore_device_t *coredev, u8 PinNum,
-		u8 NewLevel) {
-
-	u32 totalLen;
-	int rc;
-	void *buffer;
-
-	struct SetGpioMsg {
-		struct SmsMsgHdr_ST xMsgHeader;
-		u32 msgData[3]; /* keep it 3 ! */
-	} *pMsg;
-
-	if ((NewLevel > 1) || (PinNum > MAX_GPIO_PIN_NUMBER))
-		return -EINVAL;
-
-	totalLen = sizeof(struct SmsMsgHdr_ST) +
-			(3 * sizeof(u32)); /* keep it 3 ! */
-
-	buffer = kmalloc(totalLen + SMS_DMA_ALIGNMENT,
-			GFP_KERNEL | GFP_DMA);
-	if (!buffer)
-		return -ENOMEM;
-
-	pMsg = (struct SetGpioMsg *) SMS_ALIGN_ADDRESS(buffer);
-
-	pMsg->xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
-	pMsg->xMsgHeader.msgDstId = HIF_TASK;
-	pMsg->xMsgHeader.msgFlags = 0;
-	pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_SET_LEVEL_REQ;
-	pMsg->xMsgHeader.msgLength = (u16) totalLen;
-	pMsg->msgData[0] = PinNum;
-	pMsg->msgData[1] = NewLevel;
-
-	/* Send message to SMS */
-	smsendian_handle_tx_message((struct SmsMsgHdr_ST *)pMsg);
-	rc = smscore_sendrequest_and_wait(coredev, pMsg, totalLen,
-			&coredev->gpio_set_level_done);
-
-	if (rc != 0) {
-		if (rc == -ETIME)
-			sms_err("smscore_gpio_set_level timeout");
-		else
-			sms_err("smscore_gpio_set_level error");
-	}
-	kfree(buffer);
-
-	return rc;
-}
-
-int smscore_gpio_get_level(struct smscore_device_t *coredev, u8 PinNum,
-		u8 *level) {
-
-	u32 totalLen;
-	int rc;
-	void *buffer;
-
-	struct SetGpioMsg {
-		struct SmsMsgHdr_ST xMsgHeader;
-		u32 msgData[2];
-	} *pMsg;
-
-
-	if (PinNum > MAX_GPIO_PIN_NUMBER)
-		return -EINVAL;
-
-	totalLen = sizeof(struct SmsMsgHdr_ST) + (2 * sizeof(u32));
-
-	buffer = kmalloc(totalLen + SMS_DMA_ALIGNMENT,
-			GFP_KERNEL | GFP_DMA);
-	if (!buffer)
-		return -ENOMEM;
-
-	pMsg = (struct SetGpioMsg *) SMS_ALIGN_ADDRESS(buffer);
-
-	pMsg->xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
-	pMsg->xMsgHeader.msgDstId = HIF_TASK;
-	pMsg->xMsgHeader.msgFlags = 0;
-	pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_GET_LEVEL_REQ;
-	pMsg->xMsgHeader.msgLength = (u16) totalLen;
-	pMsg->msgData[0] = PinNum;
-	pMsg->msgData[1] = 0;
-
-	/* Send message to SMS */
-	smsendian_handle_tx_message((struct SmsMsgHdr_ST *)pMsg);
-	rc = smscore_sendrequest_and_wait(coredev, pMsg, totalLen,
-			&coredev->gpio_get_level_done);
-
-	if (rc != 0) {
-		if (rc == -ETIME)
-			sms_err("smscore_gpio_get_level timeout");
-		else
-			sms_err("smscore_gpio_get_level error");
-	}
-	kfree(buffer);
-
-	/* Its a race between other gpio_get_level() and the copy of the single
-	 * global 'coredev->gpio_get_res' to  the function's variable 'level'
-	 */
-	*level = coredev->gpio_get_res;
-
-	return rc;
-}
-
-static int __init smscore_module_init(void)
-{
-	int rc = 0;
-
-	INIT_LIST_HEAD(&g_smscore_notifyees);
-	INIT_LIST_HEAD(&g_smscore_devices);
-	kmutex_init(&g_smscore_deviceslock);
-
-	INIT_LIST_HEAD(&g_smscore_registry);
-	kmutex_init(&g_smscore_registrylock);
-
-	return rc;
-}
-
-static void __exit smscore_module_exit(void)
-{
-	kmutex_lock(&g_smscore_deviceslock);
-	while (!list_empty(&g_smscore_notifyees)) {
-		struct smscore_device_notifyee_t *notifyee =
-			(struct smscore_device_notifyee_t *)
-				g_smscore_notifyees.next;
-
-		list_del(&notifyee->entry);
-		kfree(notifyee);
-	}
-	kmutex_unlock(&g_smscore_deviceslock);
-
-	kmutex_lock(&g_smscore_registrylock);
-	while (!list_empty(&g_smscore_registry)) {
-		struct smscore_registry_entry_t *entry =
-			(struct smscore_registry_entry_t *)
-				g_smscore_registry.next;
-
-		list_del(&entry->entry);
-		kfree(entry);
-	}
-	kmutex_unlock(&g_smscore_registrylock);
-
-	sms_debug("");
-}
-
-module_init(smscore_module_init);
-module_exit(smscore_module_exit);
-
-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
deleted file mode 100644
index c592ae0..0000000
--- a/drivers/media/dvb/siano/smscoreapi.h
+++ /dev/null
@@ -1,775 +0,0 @@
-/****************************************************************
-
-Siano Mobile Silicon, Inc.
-MDTV receiver kernel modules.
-Copyright (C) 2006-2008, Uri Shkolnik, Anatoly Greenblat
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 2 of the License, or
-(at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-****************************************************************/
-
-#ifndef __SMS_CORE_API_H__
-#define __SMS_CORE_API_H__
-
-#include <linux/device.h>
-#include <linux/list.h>
-#include <linux/mm.h>
-#include <linux/scatterlist.h>
-#include <linux/types.h>
-#include <linux/mutex.h>
-#include <linux/wait.h>
-#include <linux/timer.h>
-
-#include <asm/page.h>
-
-#include "smsir.h"
-
-#define kmutex_init(_p_) mutex_init(_p_)
-#define kmutex_lock(_p_) mutex_lock(_p_)
-#define kmutex_trylock(_p_) mutex_trylock(_p_)
-#define kmutex_unlock(_p_) mutex_unlock(_p_)
-
-#ifndef min
-#define min(a, b) (((a) < (b)) ? (a) : (b))
-#endif
-
-#define SMS_PROTOCOL_MAX_RAOUNDTRIP_MS			(10000)
-#define SMS_ALLOC_ALIGNMENT				128
-#define SMS_DMA_ALIGNMENT				16
-#define SMS_ALIGN_ADDRESS(addr) \
-	((((uintptr_t)(addr)) + (SMS_DMA_ALIGNMENT-1)) & ~(SMS_DMA_ALIGNMENT-1))
-
-#define SMS_DEVICE_FAMILY2				1
-#define SMS_ROM_NO_RESPONSE				2
-#define SMS_DEVICE_NOT_READY				0x8000000
-
-enum sms_device_type_st {
-	SMS_STELLAR = 0,
-	SMS_NOVA_A0,
-	SMS_NOVA_B0,
-	SMS_VEGA,
-	SMS_NUM_OF_DEVICE_TYPES
-};
-
-struct smscore_device_t;
-struct smscore_client_t;
-struct smscore_buffer_t;
-
-typedef int (*hotplug_t)(struct smscore_device_t *coredev,
-			 struct device *device, int arrival);
-
-typedef int (*setmode_t)(void *context, int mode);
-typedef void (*detectmode_t)(void *context, int *mode);
-typedef int (*sendrequest_t)(void *context, void *buffer, size_t size);
-typedef int (*loadfirmware_t)(void *context, void *buffer, size_t size);
-typedef int (*preload_t)(void *context);
-typedef int (*postload_t)(void *context);
-
-typedef int (*onresponse_t)(void *context, struct smscore_buffer_t *cb);
-typedef void (*onremove_t)(void *context);
-
-struct smscore_buffer_t {
-	/* public members, once passed to clients can be changed freely */
-	struct list_head entry;
-	int size;
-	int offset;
-
-	/* private members, read-only for clients */
-	void *p;
-	dma_addr_t phys;
-	unsigned long offset_in_common;
-};
-
-struct smsdevice_params_t {
-	struct device	*device;
-
-	int				buffer_size;
-	int				num_buffers;
-
-	char			devpath[32];
-	unsigned long	flags;
-
-	setmode_t		setmode_handler;
-	detectmode_t	detectmode_handler;
-	sendrequest_t	sendrequest_handler;
-	preload_t		preload_handler;
-	postload_t		postload_handler;
-
-	void			*context;
-	enum sms_device_type_st device_type;
-};
-
-struct smsclient_params_t {
-	int				initial_id;
-	int				data_type;
-	onresponse_t	onresponse_handler;
-	onremove_t		onremove_handler;
-	void			*context;
-};
-
-struct smscore_device_t {
-	struct list_head entry;
-
-	struct list_head clients;
-	struct list_head subclients;
-	spinlock_t clientslock;
-
-	struct list_head buffers;
-	spinlock_t bufferslock;
-	int num_buffers;
-
-	void *common_buffer;
-	int common_buffer_size;
-	dma_addr_t common_buffer_phys;
-
-	void *context;
-	struct device *device;
-
-	char devpath[32];
-	unsigned long device_flags;
-
-	setmode_t setmode_handler;
-	detectmode_t detectmode_handler;
-	sendrequest_t sendrequest_handler;
-	preload_t preload_handler;
-	postload_t postload_handler;
-
-	int mode, modes_supported;
-
-	/* host <--> device messages */
-	struct completion version_ex_done, data_download_done, trigger_done;
-	struct completion init_device_done, reload_start_done, resume_done;
-	struct completion gpio_configuration_done, gpio_set_level_done;
-	struct completion gpio_get_level_done, ir_init_done;
-
-	/* Buffer management */
-	wait_queue_head_t buffer_mng_waitq;
-
-	/* GPIO */
-	int gpio_get_res;
-
-	/* Target hardware board */
-	int board_id;
-
-	/* Firmware */
-	u8 *fw_buf;
-	u32 fw_buf_size;
-
-	/* Infrared (IR) */
-	struct ir_t ir;
-
-	int led_state;
-};
-
-/* GPIO definitions for antenna frequency domain control (SMS8021) */
-#define SMS_ANTENNA_GPIO_0					1
-#define SMS_ANTENNA_GPIO_1					0
-
-#define BW_8_MHZ							0
-#define BW_7_MHZ							1
-#define BW_6_MHZ							2
-#define BW_5_MHZ							3
-#define BW_ISDBT_1SEG						4
-#define BW_ISDBT_3SEG						5
-
-#define MSG_HDR_FLAG_SPLIT_MSG				4
-
-#define MAX_GPIO_PIN_NUMBER					31
-
-#define HIF_TASK							11
-#define SMS_HOST_LIB						150
-#define DVBT_BDA_CONTROL_MSG_ID				201
-
-#define SMS_MAX_PAYLOAD_SIZE				240
-#define SMS_TUNE_TIMEOUT					500
-
-#define MSG_SMS_GPIO_CONFIG_REQ				507
-#define MSG_SMS_GPIO_CONFIG_RES				508
-#define MSG_SMS_GPIO_SET_LEVEL_REQ			509
-#define MSG_SMS_GPIO_SET_LEVEL_RES			510
-#define MSG_SMS_GPIO_GET_LEVEL_REQ			511
-#define MSG_SMS_GPIO_GET_LEVEL_RES			512
-#define MSG_SMS_RF_TUNE_REQ					561
-#define MSG_SMS_RF_TUNE_RES					562
-#define MSG_SMS_INIT_DEVICE_REQ				578
-#define MSG_SMS_INIT_DEVICE_RES				579
-#define MSG_SMS_ADD_PID_FILTER_REQ			601
-#define MSG_SMS_ADD_PID_FILTER_RES			602
-#define MSG_SMS_REMOVE_PID_FILTER_REQ			603
-#define MSG_SMS_REMOVE_PID_FILTER_RES			604
-#define MSG_SMS_DAB_CHANNEL				607
-#define MSG_SMS_GET_PID_FILTER_LIST_REQ			608
-#define MSG_SMS_GET_PID_FILTER_LIST_RES			609
-#define MSG_SMS_GET_STATISTICS_RES			616
-#define MSG_SMS_GET_STATISTICS_REQ			615
-#define MSG_SMS_HO_PER_SLICES_IND			630
-#define MSG_SMS_SET_ANTENNA_CONFIG_REQ			651
-#define MSG_SMS_SET_ANTENNA_CONFIG_RES			652
-#define MSG_SMS_SLEEP_RESUME_COMP_IND			655
-#define MSG_SMS_DATA_DOWNLOAD_REQ			660
-#define MSG_SMS_DATA_DOWNLOAD_RES			661
-#define MSG_SMS_SWDOWNLOAD_TRIGGER_REQ		664
-#define MSG_SMS_SWDOWNLOAD_TRIGGER_RES		665
-#define MSG_SMS_SWDOWNLOAD_BACKDOOR_REQ		666
-#define MSG_SMS_SWDOWNLOAD_BACKDOOR_RES		667
-#define MSG_SMS_GET_VERSION_EX_REQ			668
-#define MSG_SMS_GET_VERSION_EX_RES			669
-#define MSG_SMS_SET_CLOCK_OUTPUT_REQ		670
-#define MSG_SMS_I2C_SET_FREQ_REQ			685
-#define MSG_SMS_GENERIC_I2C_REQ				687
-#define MSG_SMS_GENERIC_I2C_RES				688
-#define MSG_SMS_DVBT_BDA_DATA				693
-#define MSG_SW_RELOAD_REQ					697
-#define MSG_SMS_DATA_MSG					699
-#define MSG_SW_RELOAD_START_REQ				702
-#define MSG_SW_RELOAD_START_RES				703
-#define MSG_SW_RELOAD_EXEC_REQ				704
-#define MSG_SW_RELOAD_EXEC_RES				705
-#define MSG_SMS_SPI_INT_LINE_SET_REQ		710
-#define MSG_SMS_GPIO_CONFIG_EX_REQ			712
-#define MSG_SMS_GPIO_CONFIG_EX_RES			713
-#define MSG_SMS_ISDBT_TUNE_REQ				776
-#define MSG_SMS_ISDBT_TUNE_RES				777
-#define MSG_SMS_TRANSMISSION_IND			782
-#define MSG_SMS_START_IR_REQ				800
-#define MSG_SMS_START_IR_RES				801
-#define MSG_SMS_IR_SAMPLES_IND				802
-#define MSG_SMS_SIGNAL_DETECTED_IND			827
-#define MSG_SMS_NO_SIGNAL_IND				828
-
-#define SMS_INIT_MSG_EX(ptr, type, src, dst, len) do { \
-	(ptr)->msgType = type; (ptr)->msgSrcId = src; (ptr)->msgDstId = dst; \
-	(ptr)->msgLength = len; (ptr)->msgFlags = 0; \
-} while (0)
-
-#define SMS_INIT_MSG(ptr, type, len) \
-	SMS_INIT_MSG_EX(ptr, type, 0, HIF_TASK, len)
-
-enum SMS_DVB3_EVENTS {
-	DVB3_EVENT_INIT = 0,
-	DVB3_EVENT_SLEEP,
-	DVB3_EVENT_HOTPLUG,
-	DVB3_EVENT_FE_LOCK,
-	DVB3_EVENT_FE_UNLOCK,
-	DVB3_EVENT_UNC_OK,
-	DVB3_EVENT_UNC_ERR
-};
-
-enum SMS_DEVICE_MODE {
-	DEVICE_MODE_NONE = -1,
-	DEVICE_MODE_DVBT = 0,
-	DEVICE_MODE_DVBH,
-	DEVICE_MODE_DAB_TDMB,
-	DEVICE_MODE_DAB_TDMB_DABIP,
-	DEVICE_MODE_DVBT_BDA,
-	DEVICE_MODE_ISDBT,
-	DEVICE_MODE_ISDBT_BDA,
-	DEVICE_MODE_CMMB,
-	DEVICE_MODE_RAW_TUNER,
-	DEVICE_MODE_MAX,
-};
-
-struct SmsMsgHdr_ST {
-	u16	msgType;
-	u8	msgSrcId;
-	u8	msgDstId;
-	u16	msgLength; /* Length of entire message, including header */
-	u16	msgFlags;
-};
-
-struct SmsMsgData_ST {
-	struct SmsMsgHdr_ST xMsgHeader;
-	u32 msgData[1];
-};
-
-struct SmsMsgData_ST2 {
-	struct SmsMsgHdr_ST xMsgHeader;
-	u32 msgData[2];
-};
-
-struct SmsDataDownload_ST {
-	struct SmsMsgHdr_ST	xMsgHeader;
-	u32			MemAddr;
-	u8			Payload[SMS_MAX_PAYLOAD_SIZE];
-};
-
-struct SmsVersionRes_ST {
-	struct SmsMsgHdr_ST	xMsgHeader;
-
-	u16		ChipModel; /* e.g. 0x1102 for SMS-1102 "Nova" */
-	u8		Step; /* 0 - Step A */
-	u8		MetalFix; /* 0 - Metal 0 */
-
-	/* FirmwareId 0xFF if ROM, otherwise the
-	 * value indicated by SMSHOSTLIB_DEVICE_MODES_E */
-	u8 FirmwareId;
-	/* SupportedProtocols Bitwise OR combination of
-					     * supported protocols */
-	u8 SupportedProtocols;
-
-	u8		VersionMajor;
-	u8		VersionMinor;
-	u8		VersionPatch;
-	u8		VersionFieldPatch;
-
-	u8		RomVersionMajor;
-	u8		RomVersionMinor;
-	u8		RomVersionPatch;
-	u8		RomVersionFieldPatch;
-
-	u8		TextLabel[34];
-};
-
-struct SmsFirmware_ST {
-	u32			CheckSum;
-	u32			Length;
-	u32			StartAddress;
-	u8			Payload[1];
-};
-
-/* Statistics information returned as response for
- * SmsHostApiGetStatistics_Req */
-struct SMSHOSTLIB_STATISTICS_ST {
-	u32 Reserved;		/* Reserved */
-
-	/* Common parameters */
-	u32 IsRfLocked;		/* 0 - not locked, 1 - locked */
-	u32 IsDemodLocked;	/* 0 - not locked, 1 - locked */
-	u32 IsExternalLNAOn;	/* 0 - external LNA off, 1 - external LNA on */
-
-	/* Reception quality */
-	s32 SNR;		/* dB */
-	u32 BER;		/* Post Viterbi BER [1E-5] */
-	u32 FIB_CRC;		/* CRC errors percentage, valid only for DAB */
-	u32 TS_PER;		/* Transport stream PER,
-	0xFFFFFFFF indicate N/A, valid only for DVB-T/H */
-	u32 MFER;		/* DVB-H frame error rate in percentage,
-	0xFFFFFFFF indicate N/A, valid only for DVB-H */
-	s32 RSSI;		/* dBm */
-	s32 InBandPwr;		/* In band power in dBM */
-	s32 CarrierOffset;	/* Carrier Offset in bin/1024 */
-
-	/* Transmission parameters */
-	u32 Frequency;		/* Frequency in Hz */
-	u32 Bandwidth;		/* Bandwidth in MHz, valid only for DVB-T/H */
-	u32 TransmissionMode;	/* Transmission Mode, for DAB modes 1-4,
-	for DVB-T/H FFT mode carriers in Kilos */
-	u32 ModemState;		/* from SMSHOSTLIB_DVB_MODEM_STATE_ET,
-	valid only for DVB-T/H */
-	u32 GuardInterval;	/* Guard Interval from
-	SMSHOSTLIB_GUARD_INTERVALS_ET, 	valid only for DVB-T/H */
-	u32 CodeRate;		/* Code Rate from SMSHOSTLIB_CODE_RATE_ET,
-	valid only for DVB-T/H */
-	u32 LPCodeRate;		/* Low Priority Code Rate from
-	SMSHOSTLIB_CODE_RATE_ET, valid only for DVB-T/H */
-	u32 Hierarchy;		/* Hierarchy from SMSHOSTLIB_HIERARCHY_ET,
-	valid only for DVB-T/H */
-	u32 Constellation;	/* Constellation from
-	SMSHOSTLIB_CONSTELLATION_ET, valid only for DVB-T/H */
-
-	/* Burst parameters, valid only for DVB-H */
-	u32 BurstSize;		/* Current burst size in bytes,
-	valid only for DVB-H */
-	u32 BurstDuration;	/* Current burst duration in mSec,
-	valid only for DVB-H */
-	u32 BurstCycleTime;	/* Current burst cycle time in mSec,
-	valid only for DVB-H */
-	u32 CalculatedBurstCycleTime;/* Current burst cycle time in mSec,
-	as calculated by demodulator, valid only for DVB-H */
-	u32 NumOfRows;		/* Number of rows in MPE table,
-	valid only for DVB-H */
-	u32 NumOfPaddCols;	/* Number of padding columns in MPE table,
-	valid only for DVB-H */
-	u32 NumOfPunctCols;	/* Number of puncturing columns in MPE table,
-	valid only for DVB-H */
-	u32 ErrorTSPackets;	/* Number of erroneous
-	transport-stream packets */
-	u32 TotalTSPackets;	/* Total number of transport-stream packets */
-	u32 NumOfValidMpeTlbs;	/* Number of MPE tables which do not include
-	errors after MPE RS decoding */
-	u32 NumOfInvalidMpeTlbs;/* Number of MPE tables which include errors
-	after MPE RS decoding */
-	u32 NumOfCorrectedMpeTlbs;/* Number of MPE tables which were
-	corrected by MPE RS decoding */
-	/* Common params */
-	u32 BERErrorCount;	/* Number of errornous SYNC bits. */
-	u32 BERBitCount;	/* Total number of SYNC bits. */
-
-	/* Interface information */
-	u32 SmsToHostTxErrors;	/* Total number of transmission errors. */
-
-	/* DAB/T-DMB */
-	u32 PreBER; 		/* DAB/T-DMB only: Pre Viterbi BER [1E-5] */
-
-	/* DVB-H TPS parameters */
-	u32 CellId;		/* TPS Cell ID in bits 15..0, bits 31..16 zero;
-	 if set to 0xFFFFFFFF cell_id not yet recovered */
-	u32 DvbhSrvIndHP;	/* DVB-H service indication info, bit 1 -
-	Time Slicing indicator, bit 0 - MPE-FEC indicator */
-	u32 DvbhSrvIndLP;	/* DVB-H service indication info, bit 1 -
-	Time Slicing indicator, bit 0 - MPE-FEC indicator */
-
-	u32 NumMPEReceived;	/* DVB-H, Num MPE section received */
-
-	u32 ReservedFields[10];	/* Reserved */
-};
-
-struct SmsMsgStatisticsInfo_ST {
-	u32 RequestResult;
-
-	struct SMSHOSTLIB_STATISTICS_ST Stat;
-
-	/* Split the calc of the SNR in DAB */
-	u32 Signal; /* dB */
-	u32 Noise; /* dB */
-
-};
-
-struct SMSHOSTLIB_ISDBT_LAYER_STAT_ST {
-	/* Per-layer information */
-	u32 CodeRate; /* Code Rate from SMSHOSTLIB_CODE_RATE_ET,
-		       * 255 means layer does not exist */
-	u32 Constellation; /* Constellation from SMSHOSTLIB_CONSTELLATION_ET,
-			    * 255 means layer does not exist */
-	u32 BER; /* Post Viterbi BER [1E-5], 0xFFFFFFFF indicate N/A */
-	u32 BERErrorCount; /* Post Viterbi Error Bits Count */
-	u32 BERBitCount; /* Post Viterbi Total Bits Count */
-	u32 PreBER; /* Pre Viterbi BER [1E-5], 0xFFFFFFFF indicate N/A */
-	u32 TS_PER; /* Transport stream PER [%], 0xFFFFFFFF indicate N/A */
-	u32 ErrorTSPackets; /* Number of erroneous transport-stream packets */
-	u32 TotalTSPackets; /* Total number of transport-stream packets */
-	u32 TILdepthI; /* Time interleaver depth I parameter,
-			* 255 means layer does not exist */
-	u32 NumberOfSegments; /* Number of segments in layer A,
-			       * 255 means layer does not exist */
-	u32 TMCCErrors; /* TMCC errors */
-};
-
-struct SMSHOSTLIB_STATISTICS_ISDBT_ST {
-	u32 StatisticsType; /* Enumerator identifying the type of the
-				* structure.  Values are the same as
-				* SMSHOSTLIB_DEVICE_MODES_E
-				*
-				* This field MUST always be first in any
-				* statistics structure */
-
-	u32 FullSize; /* Total size of the structure returned by the modem.
-		       * If the size requested by the host is smaller than
-		       * FullSize, the struct will be truncated */
-
-	/* Common parameters */
-	u32 IsRfLocked; /* 0 - not locked, 1 - locked */
-	u32 IsDemodLocked; /* 0 - not locked, 1 - locked */
-	u32 IsExternalLNAOn; /* 0 - external LNA off, 1 - external LNA on */
-
-	/* Reception quality */
-	s32  SNR; /* dB */
-	s32  RSSI; /* dBm */
-	s32  InBandPwr; /* In band power in dBM */
-	s32  CarrierOffset; /* Carrier Offset in Hz */
-
-	/* Transmission parameters */
-	u32 Frequency; /* Frequency in Hz */
-	u32 Bandwidth; /* Bandwidth in MHz */
-	u32 TransmissionMode; /* ISDB-T transmission mode */
-	u32 ModemState; /* 0 - Acquisition, 1 - Locked */
-	u32 GuardInterval; /* Guard Interval, 1 divided by value */
-	u32 SystemType; /* ISDB-T system type (ISDB-T / ISDB-Tsb) */
-	u32 PartialReception; /* TRUE - partial reception, FALSE otherwise */
-	u32 NumOfLayers; /* Number of ISDB-T layers in the network */
-
-	/* Per-layer information */
-	/* Layers A, B and C */
-	struct SMSHOSTLIB_ISDBT_LAYER_STAT_ST	LayerInfo[3];
-	/* Per-layer statistics, see SMSHOSTLIB_ISDBT_LAYER_STAT_ST */
-
-	/* Interface information */
-	u32 SmsToHostTxErrors; /* Total number of transmission errors. */
-};
-
-struct PID_STATISTICS_DATA_S {
-	struct PID_BURST_S {
-		u32 size;
-		u32 padding_cols;
-		u32 punct_cols;
-		u32 duration;
-		u32 cycle;
-		u32 calc_cycle;
-	} burst;
-
-	u32 tot_tbl_cnt;
-	u32 invalid_tbl_cnt;
-	u32 tot_cor_tbl;
-};
-
-struct PID_DATA_S {
-	u32 pid;
-	u32 num_rows;
-	struct PID_STATISTICS_DATA_S pid_statistics;
-};
-
-#define CORRECT_STAT_RSSI(_stat) ((_stat).RSSI *= -1)
-#define CORRECT_STAT_BANDWIDTH(_stat) (_stat.Bandwidth = 8 - _stat.Bandwidth)
-#define CORRECT_STAT_TRANSMISSON_MODE(_stat) \
-	if (_stat.TransmissionMode == 0) \
-		_stat.TransmissionMode = 2; \
-	else if (_stat.TransmissionMode == 1) \
-		_stat.TransmissionMode = 8; \
-		else \
-			_stat.TransmissionMode = 4;
-
-struct TRANSMISSION_STATISTICS_S {
-	u32 Frequency;		/* Frequency in Hz */
-	u32 Bandwidth;		/* Bandwidth in MHz */
-	u32 TransmissionMode;	/* FFT mode carriers in Kilos */
-	u32 GuardInterval;	/* Guard Interval from
-	SMSHOSTLIB_GUARD_INTERVALS_ET */
-	u32 CodeRate;		/* Code Rate from SMSHOSTLIB_CODE_RATE_ET */
-	u32 LPCodeRate;		/* Low Priority Code Rate from
-	SMSHOSTLIB_CODE_RATE_ET */
-	u32 Hierarchy;		/* Hierarchy from SMSHOSTLIB_HIERARCHY_ET */
-	u32 Constellation;	/* Constellation from
-	SMSHOSTLIB_CONSTELLATION_ET */
-
-	/* DVB-H TPS parameters */
-	u32 CellId;		/* TPS Cell ID in bits 15..0, bits 31..16 zero;
-	 if set to 0xFFFFFFFF cell_id not yet recovered */
-	u32 DvbhSrvIndHP;	/* DVB-H service indication info, bit 1 -
-	 Time Slicing indicator, bit 0 - MPE-FEC indicator */
-	u32 DvbhSrvIndLP;	/* DVB-H service indication info, bit 1 -
-	 Time Slicing indicator, bit 0 - MPE-FEC indicator */
-	u32 IsDemodLocked;	/* 0 - not locked, 1 - locked */
-};
-
-struct RECEPTION_STATISTICS_S {
-	u32 IsRfLocked;		/* 0 - not locked, 1 - locked */
-	u32 IsDemodLocked;	/* 0 - not locked, 1 - locked */
-	u32 IsExternalLNAOn;	/* 0 - external LNA off, 1 - external LNA on */
-
-	u32 ModemState;		/* from SMSHOSTLIB_DVB_MODEM_STATE_ET */
-	s32 SNR;		/* dB */
-	u32 BER;		/* Post Viterbi BER [1E-5] */
-	u32 BERErrorCount;	/* Number of erronous SYNC bits. */
-	u32 BERBitCount;	/* Total number of SYNC bits. */
-	u32 TS_PER;		/* Transport stream PER,
-	0xFFFFFFFF indicate N/A */
-	u32 MFER;		/* DVB-H frame error rate in percentage,
-	0xFFFFFFFF indicate N/A, valid only for DVB-H */
-	s32 RSSI;		/* dBm */
-	s32 InBandPwr;		/* In band power in dBM */
-	s32 CarrierOffset;	/* Carrier Offset in bin/1024 */
-	u32 ErrorTSPackets;	/* Number of erroneous
-	transport-stream packets */
-	u32 TotalTSPackets;	/* Total number of transport-stream packets */
-
-	s32 MRC_SNR;		/* dB */
-	s32 MRC_RSSI;		/* dBm */
-	s32 MRC_InBandPwr;	/* In band power in dBM */
-};
-
-
-/* Statistics information returned as response for
- * SmsHostApiGetStatisticsEx_Req for DVB applications, SMS1100 and up */
-struct SMSHOSTLIB_STATISTICS_DVB_S {
-	/* Reception */
-	struct RECEPTION_STATISTICS_S ReceptionData;
-
-	/* Transmission parameters */
-	struct TRANSMISSION_STATISTICS_S TransmissionData;
-
-	/* Burst parameters, valid only for DVB-H */
-#define	SRVM_MAX_PID_FILTERS 8
-	struct PID_DATA_S PidData[SRVM_MAX_PID_FILTERS];
-};
-
-struct SRVM_SIGNAL_STATUS_S {
-	u32 result;
-	u32 snr;
-	u32 tsPackets;
-	u32 etsPackets;
-	u32 constellation;
-	u32 hpCode;
-	u32 tpsSrvIndLP;
-	u32 tpsSrvIndHP;
-	u32 cellId;
-	u32 reason;
-
-	s32 inBandPower;
-	u32 requestId;
-};
-
-struct SMSHOSTLIB_I2C_REQ_ST {
-	u32	DeviceAddress; /* I2c device address */
-	u32	WriteCount; /* number of bytes to write */
-	u32	ReadCount; /* number of bytes to read */
-	u8	Data[1];
-};
-
-struct SMSHOSTLIB_I2C_RES_ST {
-	u32	Status; /* non-zero value in case of failure */
-	u32	ReadCount; /* number of bytes read */
-	u8	Data[1];
-};
-
-
-struct smscore_config_gpio {
-#define SMS_GPIO_DIRECTION_INPUT  0
-#define SMS_GPIO_DIRECTION_OUTPUT 1
-	u8 direction;
-
-#define SMS_GPIO_PULLUPDOWN_NONE     0
-#define SMS_GPIO_PULLUPDOWN_PULLDOWN 1
-#define SMS_GPIO_PULLUPDOWN_PULLUP   2
-#define SMS_GPIO_PULLUPDOWN_KEEPER   3
-	u8 pullupdown;
-
-#define SMS_GPIO_INPUTCHARACTERISTICS_NORMAL  0
-#define SMS_GPIO_INPUTCHARACTERISTICS_SCHMITT 1
-	u8 inputcharacteristics;
-
-#define SMS_GPIO_OUTPUTSLEWRATE_FAST 0
-#define SMS_GPIO_OUTPUTSLEWRATE_SLOW 1
-	u8 outputslewrate;
-
-#define SMS_GPIO_OUTPUTDRIVING_4mA  0
-#define SMS_GPIO_OUTPUTDRIVING_8mA  1
-#define SMS_GPIO_OUTPUTDRIVING_12mA 2
-#define SMS_GPIO_OUTPUTDRIVING_16mA 3
-	u8 outputdriving;
-};
-
-struct smscore_gpio_config {
-#define SMS_GPIO_DIRECTION_INPUT  0
-#define SMS_GPIO_DIRECTION_OUTPUT 1
-	u8 Direction;
-
-#define SMS_GPIO_PULL_UP_DOWN_NONE     0
-#define SMS_GPIO_PULL_UP_DOWN_PULLDOWN 1
-#define SMS_GPIO_PULL_UP_DOWN_PULLUP   2
-#define SMS_GPIO_PULL_UP_DOWN_KEEPER   3
-	u8 PullUpDown;
-
-#define SMS_GPIO_INPUT_CHARACTERISTICS_NORMAL  0
-#define SMS_GPIO_INPUT_CHARACTERISTICS_SCHMITT 1
-	u8 InputCharacteristics;
-
-#define SMS_GPIO_OUTPUT_SLEW_RATE_SLOW		1 /* 10xx */
-#define SMS_GPIO_OUTPUT_SLEW_RATE_FAST		0 /* 10xx */
-
-
-#define SMS_GPIO_OUTPUT_SLEW_RATE_0_45_V_NS	0 /* 11xx */
-#define SMS_GPIO_OUTPUT_SLEW_RATE_0_9_V_NS	1 /* 11xx */
-#define SMS_GPIO_OUTPUT_SLEW_RATE_1_7_V_NS	2 /* 11xx */
-#define SMS_GPIO_OUTPUT_SLEW_RATE_3_3_V_NS	3 /* 11xx */
-	u8 OutputSlewRate;
-
-#define SMS_GPIO_OUTPUT_DRIVING_S_4mA		0 /* 10xx */
-#define SMS_GPIO_OUTPUT_DRIVING_S_8mA		1 /* 10xx */
-#define SMS_GPIO_OUTPUT_DRIVING_S_12mA		2 /* 10xx */
-#define SMS_GPIO_OUTPUT_DRIVING_S_16mA		3 /* 10xx */
-
-#define SMS_GPIO_OUTPUT_DRIVING_1_5mA		0 /* 11xx */
-#define SMS_GPIO_OUTPUT_DRIVING_2_8mA		1 /* 11xx */
-#define SMS_GPIO_OUTPUT_DRIVING_4mA		2 /* 11xx */
-#define SMS_GPIO_OUTPUT_DRIVING_7mA		3 /* 11xx */
-#define SMS_GPIO_OUTPUT_DRIVING_10mA		4 /* 11xx */
-#define SMS_GPIO_OUTPUT_DRIVING_11mA		5 /* 11xx */
-#define SMS_GPIO_OUTPUT_DRIVING_14mA		6 /* 11xx */
-#define SMS_GPIO_OUTPUT_DRIVING_16mA		7 /* 11xx */
-	u8 OutputDriving;
-};
-
-extern void smscore_registry_setmode(char *devpath, int mode);
-extern int smscore_registry_getmode(char *devpath);
-
-extern int smscore_register_hotplug(hotplug_t hotplug);
-extern void smscore_unregister_hotplug(hotplug_t hotplug);
-
-extern int smscore_register_device(struct smsdevice_params_t *params,
-				   struct smscore_device_t **coredev);
-extern void smscore_unregister_device(struct smscore_device_t *coredev);
-
-extern int smscore_start_device(struct smscore_device_t *coredev);
-extern int smscore_load_firmware(struct smscore_device_t *coredev,
-				 char *filename,
-				 loadfirmware_t loadfirmware_handler);
-
-extern int smscore_set_device_mode(struct smscore_device_t *coredev, int mode);
-extern int smscore_get_device_mode(struct smscore_device_t *coredev);
-
-extern int smscore_register_client(struct smscore_device_t *coredev,
-				    struct smsclient_params_t *params,
-				    struct smscore_client_t **client);
-extern void smscore_unregister_client(struct smscore_client_t *client);
-
-extern int smsclient_sendrequest(struct smscore_client_t *client,
-				 void *buffer, size_t size);
-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);
-extern void smscore_putbuffer(struct smscore_device_t *coredev,
-			      struct smscore_buffer_t *cb);
-
-/* old GPIO management */
-int smscore_configure_gpio(struct smscore_device_t *coredev, u32 pin,
-			   struct smscore_config_gpio *pinconfig);
-int smscore_set_gpio(struct smscore_device_t *coredev, u32 pin, int level);
-
-/* new GPIO management */
-extern int smscore_gpio_configure(struct smscore_device_t *coredev, u8 PinNum,
-		struct smscore_gpio_config *pGpioConfig);
-extern int smscore_gpio_set_level(struct smscore_device_t *coredev, u8 PinNum,
-		u8 NewLevel);
-extern int smscore_gpio_get_level(struct smscore_device_t *coredev, u8 PinNum,
-		u8 *level);
-
-void smscore_set_board_id(struct smscore_device_t *core, int id);
-int smscore_get_board_id(struct smscore_device_t *core);
-
-int smscore_led_state(struct smscore_device_t *core, int led);
-
-
-/* ------------------------------------------------------------------------ */
-
-#define DBG_INFO 1
-#define DBG_ADV  2
-
-#define sms_printk(kern, fmt, arg...) \
-	printk(kern "%s: " fmt "\n", __func__, ##arg)
-
-#define dprintk(kern, lvl, fmt, arg...) do {\
-	if (sms_dbg & lvl) \
-		sms_printk(kern, fmt, ##arg); } while (0)
-
-#define sms_log(fmt, arg...) sms_printk(KERN_INFO, fmt, ##arg)
-#define sms_err(fmt, arg...) \
-	sms_printk(KERN_ERR, "line: %d: " fmt, __LINE__, ##arg)
-#define sms_warn(fmt, arg...)  sms_printk(KERN_WARNING, fmt, ##arg)
-#define sms_info(fmt, arg...) \
-	dprintk(KERN_INFO, DBG_INFO, fmt, ##arg)
-#define sms_debug(fmt, arg...) \
-	dprintk(KERN_DEBUG, DBG_ADV, fmt, ##arg)
-
-
-#endif /* __SMS_CORE_API_H__ */
diff --git a/drivers/media/dvb/siano/smsdvb.c b/drivers/media/dvb/siano/smsdvb.c
deleted file mode 100644
index aa77e54..0000000
--- a/drivers/media/dvb/siano/smsdvb.c
+++ /dev/null
@@ -1,1078 +0,0 @@
-/****************************************************************
-
-Siano Mobile Silicon, Inc.
-MDTV receiver kernel modules.
-Copyright (C) 2006-2008, Uri Shkolnik
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 2 of the License, or
-(at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-****************************************************************/
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-
-#include "dmxdev.h"
-#include "dvbdev.h"
-#include "dvb_demux.h"
-#include "dvb_frontend.h"
-
-#include "smscoreapi.h"
-#include "smsendian.h"
-#include "sms-cards.h"
-
-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;
-
-	struct completion       tune_done;
-
-	struct SMSHOSTLIB_STATISTICS_DVB_S sms_stat_dvb;
-	int event_fe_state;
-	int event_unc_state;
-};
-
-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))");
-
-/* Events that may come from DVB v3 adapter */
-static void sms_board_dvb3_event(struct smsdvb_client_t *client,
-		enum SMS_DVB3_EVENTS event) {
-
-	struct smscore_device_t *coredev = client->coredev;
-	switch (event) {
-	case DVB3_EVENT_INIT:
-		sms_debug("DVB3_EVENT_INIT");
-		sms_board_event(coredev, BOARD_EVENT_BIND);
-		break;
-	case DVB3_EVENT_SLEEP:
-		sms_debug("DVB3_EVENT_SLEEP");
-		sms_board_event(coredev, BOARD_EVENT_POWER_SUSPEND);
-		break;
-	case DVB3_EVENT_HOTPLUG:
-		sms_debug("DVB3_EVENT_HOTPLUG");
-		sms_board_event(coredev, BOARD_EVENT_POWER_INIT);
-		break;
-	case DVB3_EVENT_FE_LOCK:
-		if (client->event_fe_state != DVB3_EVENT_FE_LOCK) {
-			client->event_fe_state = DVB3_EVENT_FE_LOCK;
-			sms_debug("DVB3_EVENT_FE_LOCK");
-			sms_board_event(coredev, BOARD_EVENT_FE_LOCK);
-		}
-		break;
-	case DVB3_EVENT_FE_UNLOCK:
-		if (client->event_fe_state != DVB3_EVENT_FE_UNLOCK) {
-			client->event_fe_state = DVB3_EVENT_FE_UNLOCK;
-			sms_debug("DVB3_EVENT_FE_UNLOCK");
-			sms_board_event(coredev, BOARD_EVENT_FE_UNLOCK);
-		}
-		break;
-	case DVB3_EVENT_UNC_OK:
-		if (client->event_unc_state != DVB3_EVENT_UNC_OK) {
-			client->event_unc_state = DVB3_EVENT_UNC_OK;
-			sms_debug("DVB3_EVENT_UNC_OK");
-			sms_board_event(coredev, BOARD_EVENT_MULTIPLEX_OK);
-		}
-		break;
-	case DVB3_EVENT_UNC_ERR:
-		if (client->event_unc_state != DVB3_EVENT_UNC_ERR) {
-			client->event_unc_state = DVB3_EVENT_UNC_ERR;
-			sms_debug("DVB3_EVENT_UNC_ERR");
-			sms_board_event(coredev, BOARD_EVENT_MULTIPLEX_ERRORS);
-		}
-		break;
-
-	default:
-		sms_err("Unknown dvb3 api event");
-		break;
-	}
-}
-
-
-static void smsdvb_update_dvb_stats(struct RECEPTION_STATISTICS_S *pReceptionData,
-				   struct SMSHOSTLIB_STATISTICS_ST *p)
-{
-	if (sms_dbg & 2) {
-		printk(KERN_DEBUG "Reserved = %d", p->Reserved);
-		printk(KERN_DEBUG "IsRfLocked = %d", p->IsRfLocked);
-		printk(KERN_DEBUG "IsDemodLocked = %d", p->IsDemodLocked);
-		printk(KERN_DEBUG "IsExternalLNAOn = %d", p->IsExternalLNAOn);
-		printk(KERN_DEBUG "SNR = %d", p->SNR);
-		printk(KERN_DEBUG "BER = %d", p->BER);
-		printk(KERN_DEBUG "FIB_CRC = %d", p->FIB_CRC);
-		printk(KERN_DEBUG "TS_PER = %d", p->TS_PER);
-		printk(KERN_DEBUG "MFER = %d", p->MFER);
-		printk(KERN_DEBUG "RSSI = %d", p->RSSI);
-		printk(KERN_DEBUG "InBandPwr = %d", p->InBandPwr);
-		printk(KERN_DEBUG "CarrierOffset = %d", p->CarrierOffset);
-		printk(KERN_DEBUG "Frequency = %d", p->Frequency);
-		printk(KERN_DEBUG "Bandwidth = %d", p->Bandwidth);
-		printk(KERN_DEBUG "TransmissionMode = %d", p->TransmissionMode);
-		printk(KERN_DEBUG "ModemState = %d", p->ModemState);
-		printk(KERN_DEBUG "GuardInterval = %d", p->GuardInterval);
-		printk(KERN_DEBUG "CodeRate = %d", p->CodeRate);
-		printk(KERN_DEBUG "LPCodeRate = %d", p->LPCodeRate);
-		printk(KERN_DEBUG "Hierarchy = %d", p->Hierarchy);
-		printk(KERN_DEBUG "Constellation = %d", p->Constellation);
-		printk(KERN_DEBUG "BurstSize = %d", p->BurstSize);
-		printk(KERN_DEBUG "BurstDuration = %d", p->BurstDuration);
-		printk(KERN_DEBUG "BurstCycleTime = %d", p->BurstCycleTime);
-		printk(KERN_DEBUG "CalculatedBurstCycleTime = %d", p->CalculatedBurstCycleTime);
-		printk(KERN_DEBUG "NumOfRows = %d", p->NumOfRows);
-		printk(KERN_DEBUG "NumOfPaddCols = %d", p->NumOfPaddCols);
-		printk(KERN_DEBUG "NumOfPunctCols = %d", p->NumOfPunctCols);
-		printk(KERN_DEBUG "ErrorTSPackets = %d", p->ErrorTSPackets);
-		printk(KERN_DEBUG "TotalTSPackets = %d", p->TotalTSPackets);
-		printk(KERN_DEBUG "NumOfValidMpeTlbs = %d", p->NumOfValidMpeTlbs);
-		printk(KERN_DEBUG "NumOfInvalidMpeTlbs = %d", p->NumOfInvalidMpeTlbs);
-		printk(KERN_DEBUG "NumOfCorrectedMpeTlbs = %d", p->NumOfCorrectedMpeTlbs);
-		printk(KERN_DEBUG "BERErrorCount = %d", p->BERErrorCount);
-		printk(KERN_DEBUG "BERBitCount = %d", p->BERBitCount);
-		printk(KERN_DEBUG "SmsToHostTxErrors = %d", p->SmsToHostTxErrors);
-		printk(KERN_DEBUG "PreBER = %d", p->PreBER);
-		printk(KERN_DEBUG "CellId = %d", p->CellId);
-		printk(KERN_DEBUG "DvbhSrvIndHP = %d", p->DvbhSrvIndHP);
-		printk(KERN_DEBUG "DvbhSrvIndLP = %d", p->DvbhSrvIndLP);
-		printk(KERN_DEBUG "NumMPEReceived = %d", p->NumMPEReceived);
-	}
-
-	pReceptionData->IsDemodLocked = p->IsDemodLocked;
-
-	pReceptionData->SNR = p->SNR;
-	pReceptionData->BER = p->BER;
-	pReceptionData->BERErrorCount = p->BERErrorCount;
-	pReceptionData->InBandPwr = p->InBandPwr;
-	pReceptionData->ErrorTSPackets = p->ErrorTSPackets;
-};
-
-
-static void smsdvb_update_isdbt_stats(struct RECEPTION_STATISTICS_S *pReceptionData,
-				    struct SMSHOSTLIB_STATISTICS_ISDBT_ST *p)
-{
-	int i;
-
-	if (sms_dbg & 2) {
-		printk(KERN_DEBUG "IsRfLocked = %d", p->IsRfLocked);
-		printk(KERN_DEBUG "IsDemodLocked = %d", p->IsDemodLocked);
-		printk(KERN_DEBUG "IsExternalLNAOn = %d", p->IsExternalLNAOn);
-		printk(KERN_DEBUG "SNR = %d", p->SNR);
-		printk(KERN_DEBUG "RSSI = %d", p->RSSI);
-		printk(KERN_DEBUG "InBandPwr = %d", p->InBandPwr);
-		printk(KERN_DEBUG "CarrierOffset = %d", p->CarrierOffset);
-		printk(KERN_DEBUG "Frequency = %d", p->Frequency);
-		printk(KERN_DEBUG "Bandwidth = %d", p->Bandwidth);
-		printk(KERN_DEBUG "TransmissionMode = %d", p->TransmissionMode);
-		printk(KERN_DEBUG "ModemState = %d", p->ModemState);
-		printk(KERN_DEBUG "GuardInterval = %d", p->GuardInterval);
-		printk(KERN_DEBUG "SystemType = %d", p->SystemType);
-		printk(KERN_DEBUG "PartialReception = %d", p->PartialReception);
-		printk(KERN_DEBUG "NumOfLayers = %d", p->NumOfLayers);
-		printk(KERN_DEBUG "SmsToHostTxErrors = %d", p->SmsToHostTxErrors);
-
-		for (i = 0; i < 3; i++) {
-			printk(KERN_DEBUG "%d: CodeRate = %d", i, p->LayerInfo[i].CodeRate);
-			printk(KERN_DEBUG "%d: Constellation = %d", i, p->LayerInfo[i].Constellation);
-			printk(KERN_DEBUG "%d: BER = %d", i, p->LayerInfo[i].BER);
-			printk(KERN_DEBUG "%d: BERErrorCount = %d", i, p->LayerInfo[i].BERErrorCount);
-			printk(KERN_DEBUG "%d: BERBitCount = %d", i, p->LayerInfo[i].BERBitCount);
-			printk(KERN_DEBUG "%d: PreBER = %d", i, p->LayerInfo[i].PreBER);
-			printk(KERN_DEBUG "%d: TS_PER = %d", i, p->LayerInfo[i].TS_PER);
-			printk(KERN_DEBUG "%d: ErrorTSPackets = %d", i, p->LayerInfo[i].ErrorTSPackets);
-			printk(KERN_DEBUG "%d: TotalTSPackets = %d", i, p->LayerInfo[i].TotalTSPackets);
-			printk(KERN_DEBUG "%d: TILdepthI = %d", i, p->LayerInfo[i].TILdepthI);
-			printk(KERN_DEBUG "%d: NumberOfSegments = %d", i, p->LayerInfo[i].NumberOfSegments);
-			printk(KERN_DEBUG "%d: TMCCErrors = %d", i, p->LayerInfo[i].TMCCErrors);
-		}
-	}
-
-	pReceptionData->IsDemodLocked = p->IsDemodLocked;
-
-	pReceptionData->SNR = p->SNR;
-	pReceptionData->InBandPwr = p->InBandPwr;
-
-	pReceptionData->ErrorTSPackets = 0;
-	pReceptionData->BER = 0;
-	pReceptionData->BERErrorCount = 0;
-	for (i = 0; i < 3; i++) {
-		pReceptionData->BER += p->LayerInfo[i].BER;
-		pReceptionData->BERErrorCount += p->LayerInfo[i].BERErrorCount;
-		pReceptionData->ErrorTSPackets += p->LayerInfo[i].ErrorTSPackets;
-	}
-}
-
-static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb)
-{
-	struct smsdvb_client_t *client = (struct smsdvb_client_t *) context;
-	struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *) (((u8 *) cb->p)
-			+ cb->offset);
-	u32 *pMsgData = (u32 *) phdr + 1;
-	/*u32 MsgDataLen = phdr->msgLength - sizeof(struct SmsMsgHdr_ST);*/
-	bool is_status_update = false;
-
-	smsendian_handle_rx_message((struct SmsMsgData_ST *) phdr);
-
-	switch (phdr->msgType) {
-	case MSG_SMS_DVBT_BDA_DATA:
-		dvb_dmx_swfilter(&client->demux, (u8 *)(phdr + 1),
-				 cb->size - sizeof(struct SmsMsgHdr_ST));
-		break;
-
-	case MSG_SMS_RF_TUNE_RES:
-	case MSG_SMS_ISDBT_TUNE_RES:
-		complete(&client->tune_done);
-		break;
-
-	case MSG_SMS_SIGNAL_DETECTED_IND:
-		sms_info("MSG_SMS_SIGNAL_DETECTED_IND");
-		client->sms_stat_dvb.TransmissionData.IsDemodLocked = true;
-		is_status_update = true;
-		break;
-
-	case MSG_SMS_NO_SIGNAL_IND:
-		sms_info("MSG_SMS_NO_SIGNAL_IND");
-		client->sms_stat_dvb.TransmissionData.IsDemodLocked = false;
-		is_status_update = true;
-		break;
-
-	case MSG_SMS_TRANSMISSION_IND: {
-		sms_info("MSG_SMS_TRANSMISSION_IND");
-
-		pMsgData++;
-		memcpy(&client->sms_stat_dvb.TransmissionData, pMsgData,
-				sizeof(struct TRANSMISSION_STATISTICS_S));
-
-		/* Mo need to correct guard interval
-		 * (as opposed to old statistics message).
-		 */
-		CORRECT_STAT_BANDWIDTH(client->sms_stat_dvb.TransmissionData);
-		CORRECT_STAT_TRANSMISSON_MODE(
-				client->sms_stat_dvb.TransmissionData);
-		is_status_update = true;
-		break;
-	}
-	case MSG_SMS_HO_PER_SLICES_IND: {
-		struct RECEPTION_STATISTICS_S *pReceptionData =
-				&client->sms_stat_dvb.ReceptionData;
-		struct SRVM_SIGNAL_STATUS_S SignalStatusData;
-
-		/*sms_info("MSG_SMS_HO_PER_SLICES_IND");*/
-		pMsgData++;
-		SignalStatusData.result = pMsgData[0];
-		SignalStatusData.snr = pMsgData[1];
-		SignalStatusData.inBandPower = (s32) pMsgData[2];
-		SignalStatusData.tsPackets = pMsgData[3];
-		SignalStatusData.etsPackets = pMsgData[4];
-		SignalStatusData.constellation = pMsgData[5];
-		SignalStatusData.hpCode = pMsgData[6];
-		SignalStatusData.tpsSrvIndLP = pMsgData[7] & 0x03;
-		SignalStatusData.tpsSrvIndHP = pMsgData[8] & 0x03;
-		SignalStatusData.cellId = pMsgData[9] & 0xFFFF;
-		SignalStatusData.reason = pMsgData[10];
-		SignalStatusData.requestId = pMsgData[11];
-		pReceptionData->IsRfLocked = pMsgData[16];
-		pReceptionData->IsDemodLocked = pMsgData[17];
-		pReceptionData->ModemState = pMsgData[12];
-		pReceptionData->SNR = pMsgData[1];
-		pReceptionData->BER = pMsgData[13];
-		pReceptionData->RSSI = pMsgData[14];
-		CORRECT_STAT_RSSI(client->sms_stat_dvb.ReceptionData);
-
-		pReceptionData->InBandPwr = (s32) pMsgData[2];
-		pReceptionData->CarrierOffset = (s32) pMsgData[15];
-		pReceptionData->TotalTSPackets = pMsgData[3];
-		pReceptionData->ErrorTSPackets = pMsgData[4];
-
-		/* TS PER */
-		if ((SignalStatusData.tsPackets + SignalStatusData.etsPackets)
-				> 0) {
-			pReceptionData->TS_PER = (SignalStatusData.etsPackets
-					* 100) / (SignalStatusData.tsPackets
-					+ SignalStatusData.etsPackets);
-		} else {
-			pReceptionData->TS_PER = 0;
-		}
-
-		pReceptionData->BERBitCount = pMsgData[18];
-		pReceptionData->BERErrorCount = pMsgData[19];
-
-		pReceptionData->MRC_SNR = pMsgData[20];
-		pReceptionData->MRC_InBandPwr = pMsgData[21];
-		pReceptionData->MRC_RSSI = pMsgData[22];
-
-		is_status_update = true;
-		break;
-	}
-	case MSG_SMS_GET_STATISTICS_RES: {
-		union {
-			struct SMSHOSTLIB_STATISTICS_ISDBT_ST  isdbt;
-			struct SmsMsgStatisticsInfo_ST         dvb;
-		} *p = (void *) (phdr + 1);
-		struct RECEPTION_STATISTICS_S *pReceptionData =
-				&client->sms_stat_dvb.ReceptionData;
-
-		sms_info("MSG_SMS_GET_STATISTICS_RES");
-
-		is_status_update = true;
-
-		switch (smscore_get_device_mode(client->coredev)) {
-		case DEVICE_MODE_ISDBT:
-		case DEVICE_MODE_ISDBT_BDA:
-			smsdvb_update_isdbt_stats(pReceptionData, &p->isdbt);
-			break;
-		default:
-			smsdvb_update_dvb_stats(pReceptionData, &p->dvb.Stat);
-		}
-		if (!pReceptionData->IsDemodLocked) {
-			pReceptionData->SNR = 0;
-			pReceptionData->BER = 0;
-			pReceptionData->BERErrorCount = 0;
-			pReceptionData->InBandPwr = 0;
-			pReceptionData->ErrorTSPackets = 0;
-		}
-
-		complete(&client->tune_done);
-		break;
-	}
-	default:
-		sms_info("Unhandled message %d", phdr->msgType);
-
-	}
-	smscore_putbuffer(client->coredev, cb);
-
-	if (is_status_update) {
-		if (client->sms_stat_dvb.ReceptionData.IsDemodLocked) {
-			client->fe_status = FE_HAS_SIGNAL | FE_HAS_CARRIER
-				| FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
-			sms_board_dvb3_event(client, DVB3_EVENT_FE_LOCK);
-			if (client->sms_stat_dvb.ReceptionData.ErrorTSPackets
-					== 0)
-				sms_board_dvb3_event(client, DVB3_EVENT_UNC_OK);
-			else
-				sms_board_dvb3_event(client,
-						DVB3_EVENT_UNC_ERR);
-
-		} else {
-			if (client->sms_stat_dvb.ReceptionData.IsRfLocked)
-				client->fe_status = FE_HAS_SIGNAL | FE_HAS_CARRIER;
-			else
-				client->fe_status = 0;
-			sms_board_dvb3_event(client, DVB3_EVENT_FE_UNLOCK);
-		}
-	}
-
-	return 0;
-}
-
-static void smsdvb_unregister_client(struct smsdvb_client_t *client)
-{
-	/* must be called under clientslock */
-
-	list_del(&client->entry);
-
-	smscore_unregister_client(client->smsclient);
-	dvb_unregister_frontend(&client->frontend);
-	dvb_dmxdev_release(&client->dmxdev);
-	dvb_dmx_release(&client->demux);
-	dvb_unregister_adapter(&client->adapter);
-	kfree(client);
-}
-
-static void smsdvb_onremove(void *context)
-{
-	kmutex_lock(&g_smsdvb_clientslock);
-
-	smsdvb_unregister_client((struct smsdvb_client_t *) context);
-
-	kmutex_unlock(&g_smsdvb_clientslock);
-}
-
-static int smsdvb_start_feed(struct dvb_demux_feed *feed)
-{
-	struct smsdvb_client_t *client =
-		container_of(feed->demux, struct smsdvb_client_t, demux);
-	struct SmsMsgData_ST PidMsg;
-
-	sms_debug("add pid %d(%x)",
-		  feed->pid, feed->pid);
-
-	PidMsg.xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
-	PidMsg.xMsgHeader.msgDstId = HIF_TASK;
-	PidMsg.xMsgHeader.msgFlags = 0;
-	PidMsg.xMsgHeader.msgType  = MSG_SMS_ADD_PID_FILTER_REQ;
-	PidMsg.xMsgHeader.msgLength = sizeof(PidMsg);
-	PidMsg.msgData[0] = feed->pid;
-
-	smsendian_handle_tx_message((struct SmsMsgHdr_ST *)&PidMsg);
-	return smsclient_sendrequest(client->smsclient,
-				     &PidMsg, sizeof(PidMsg));
-}
-
-static int smsdvb_stop_feed(struct dvb_demux_feed *feed)
-{
-	struct smsdvb_client_t *client =
-		container_of(feed->demux, struct smsdvb_client_t, demux);
-	struct SmsMsgData_ST PidMsg;
-
-	sms_debug("remove pid %d(%x)",
-		  feed->pid, feed->pid);
-
-	PidMsg.xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
-	PidMsg.xMsgHeader.msgDstId = HIF_TASK;
-	PidMsg.xMsgHeader.msgFlags = 0;
-	PidMsg.xMsgHeader.msgType  = MSG_SMS_REMOVE_PID_FILTER_REQ;
-	PidMsg.xMsgHeader.msgLength = sizeof(PidMsg);
-	PidMsg.msgData[0] = feed->pid;
-
-	smsendian_handle_tx_message((struct SmsMsgHdr_ST *)&PidMsg);
-	return smsclient_sendrequest(client->smsclient,
-				     &PidMsg, sizeof(PidMsg));
-}
-
-static int smsdvb_sendrequest_and_wait(struct smsdvb_client_t *client,
-					void *buffer, size_t size,
-					struct completion *completion)
-{
-	int rc;
-
-	smsendian_handle_tx_message((struct SmsMsgHdr_ST *)buffer);
-	rc = smsclient_sendrequest(client->smsclient, buffer, size);
-	if (rc < 0)
-		return rc;
-
-	return wait_for_completion_timeout(completion,
-					   msecs_to_jiffies(2000)) ?
-						0 : -ETIME;
-}
-
-static int smsdvb_send_statistics_request(struct smsdvb_client_t *client)
-{
-	int rc;
-	struct SmsMsgHdr_ST Msg = { MSG_SMS_GET_STATISTICS_REQ,
-				    DVBT_BDA_CONTROL_MSG_ID,
-				    HIF_TASK,
-				    sizeof(struct SmsMsgHdr_ST), 0 };
-
-	rc = smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg),
-					  &client->tune_done);
-
-	return rc;
-}
-
-static inline int led_feedback(struct smsdvb_client_t *client)
-{
-	if (client->fe_status & FE_HAS_LOCK)
-		return sms_board_led_feedback(client->coredev,
-			(client->sms_stat_dvb.ReceptionData.BER
-			== 0) ? SMS_LED_HI : SMS_LED_LO);
-	else
-		return sms_board_led_feedback(client->coredev, SMS_LED_OFF);
-}
-
-static int smsdvb_read_status(struct dvb_frontend *fe, fe_status_t *stat)
-{
-	int rc;
-	struct smsdvb_client_t *client;
-	client = container_of(fe, struct smsdvb_client_t, frontend);
-
-	rc = smsdvb_send_statistics_request(client);
-
-	*stat = client->fe_status;
-
-	led_feedback(client);
-
-	return rc;
-}
-
-static int smsdvb_read_ber(struct dvb_frontend *fe, u32 *ber)
-{
-	int rc;
-	struct smsdvb_client_t *client;
-	client = container_of(fe, struct smsdvb_client_t, frontend);
-
-	rc = smsdvb_send_statistics_request(client);
-
-	*ber = client->sms_stat_dvb.ReceptionData.BER;
-
-	led_feedback(client);
-
-	return rc;
-}
-
-static int smsdvb_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
-{
-	int rc;
-
-	struct smsdvb_client_t *client;
-	client = container_of(fe, struct smsdvb_client_t, frontend);
-
-	rc = smsdvb_send_statistics_request(client);
-
-	if (client->sms_stat_dvb.ReceptionData.InBandPwr < -95)
-		*strength = 0;
-		else if (client->sms_stat_dvb.ReceptionData.InBandPwr > -29)
-			*strength = 100;
-		else
-			*strength =
-				(client->sms_stat_dvb.ReceptionData.InBandPwr
-				+ 95) * 3 / 2;
-
-	led_feedback(client);
-
-	return rc;
-}
-
-static int smsdvb_read_snr(struct dvb_frontend *fe, u16 *snr)
-{
-	int rc;
-	struct smsdvb_client_t *client;
-	client = container_of(fe, struct smsdvb_client_t, frontend);
-
-	rc = smsdvb_send_statistics_request(client);
-
-	*snr = client->sms_stat_dvb.ReceptionData.SNR;
-
-	led_feedback(client);
-
-	return rc;
-}
-
-static int smsdvb_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
-{
-	int rc;
-	struct smsdvb_client_t *client;
-	client = container_of(fe, struct smsdvb_client_t, frontend);
-
-	rc = smsdvb_send_statistics_request(client);
-
-	*ucblocks = client->sms_stat_dvb.ReceptionData.ErrorTSPackets;
-
-	led_feedback(client);
-
-	return rc;
-}
-
-static int smsdvb_get_tune_settings(struct dvb_frontend *fe,
-				    struct dvb_frontend_tune_settings *tune)
-{
-	sms_debug("");
-
-	tune->min_delay_ms = 400;
-	tune->step_size = 250000;
-	tune->max_drift = 0;
-	return 0;
-}
-
-static int smsdvb_dvbt_set_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	struct smsdvb_client_t *client =
-		container_of(fe, struct smsdvb_client_t, frontend);
-
-	struct {
-		struct SmsMsgHdr_ST	Msg;
-		u32		Data[3];
-	} Msg;
-
-	int ret;
-
-	client->fe_status = FE_HAS_SIGNAL;
-	client->event_fe_state = -1;
-	client->event_unc_state = -1;
-	fe->dtv_property_cache.delivery_system = SYS_DVBT;
-
-	Msg.Msg.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
-	Msg.Msg.msgDstId = HIF_TASK;
-	Msg.Msg.msgFlags = 0;
-	Msg.Msg.msgType = MSG_SMS_RF_TUNE_REQ;
-	Msg.Msg.msgLength = sizeof(Msg);
-	Msg.Data[0] = c->frequency;
-	Msg.Data[2] = 12000000;
-
-	sms_info("%s: freq %d band %d", __func__, c->frequency,
-		 c->bandwidth_hz);
-
-	switch (c->bandwidth_hz / 1000000) {
-	case 8:
-		Msg.Data[1] = BW_8_MHZ;
-		break;
-	case 7:
-		Msg.Data[1] = BW_7_MHZ;
-		break;
-	case 6:
-		Msg.Data[1] = BW_6_MHZ;
-		break;
-	case 0:
-		return -EOPNOTSUPP;
-	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 didn't 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);
-}
-
-static int smsdvb_isdbt_set_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	struct smsdvb_client_t *client =
-		container_of(fe, struct smsdvb_client_t, frontend);
-
-	struct {
-		struct SmsMsgHdr_ST	Msg;
-		u32		Data[4];
-	} Msg;
-
-	fe->dtv_property_cache.delivery_system = SYS_ISDBT;
-
-	Msg.Msg.msgSrcId  = DVBT_BDA_CONTROL_MSG_ID;
-	Msg.Msg.msgDstId  = HIF_TASK;
-	Msg.Msg.msgFlags  = 0;
-	Msg.Msg.msgType   = MSG_SMS_ISDBT_TUNE_REQ;
-	Msg.Msg.msgLength = sizeof(Msg);
-
-	if (c->isdbt_sb_segment_idx == -1)
-		c->isdbt_sb_segment_idx = 0;
-
-	switch (c->isdbt_sb_segment_count) {
-	case 3:
-		Msg.Data[1] = BW_ISDBT_3SEG;
-		break;
-	case 1:
-		Msg.Data[1] = BW_ISDBT_1SEG;
-		break;
-	case 0:	/* AUTO */
-		switch (c->bandwidth_hz / 1000000) {
-		case 8:
-		case 7:
-			c->isdbt_sb_segment_count = 3;
-			Msg.Data[1] = BW_ISDBT_3SEG;
-			break;
-		case 6:
-			c->isdbt_sb_segment_count = 1;
-			Msg.Data[1] = BW_ISDBT_1SEG;
-			break;
-		default: /* Assumes 6 MHZ bw */
-			c->isdbt_sb_segment_count = 1;
-			c->bandwidth_hz = 6000;
-			Msg.Data[1] = BW_ISDBT_1SEG;
-			break;
-		}
-		break;
-	default:
-		sms_info("Segment count %d not supported", c->isdbt_sb_segment_count);
-		return -EINVAL;
-	}
-
-	Msg.Data[0] = c->frequency;
-	Msg.Data[2] = 12000000;
-	Msg.Data[3] = c->isdbt_sb_segment_idx;
-
-	sms_info("%s: freq %d segwidth %d segindex %d\n", __func__,
-		 c->frequency, c->isdbt_sb_segment_count,
-		 c->isdbt_sb_segment_idx);
-
-	return smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg),
-					   &client->tune_done);
-}
-
-static int smsdvb_set_frontend(struct dvb_frontend *fe)
-{
-	struct smsdvb_client_t *client =
-		container_of(fe, struct smsdvb_client_t, frontend);
-	struct smscore_device_t *coredev = client->coredev;
-
-	switch (smscore_get_device_mode(coredev)) {
-	case DEVICE_MODE_DVBT:
-	case DEVICE_MODE_DVBT_BDA:
-		return smsdvb_dvbt_set_frontend(fe);
-	case DEVICE_MODE_ISDBT:
-	case DEVICE_MODE_ISDBT_BDA:
-		return smsdvb_isdbt_set_frontend(fe);
-	default:
-		return -EINVAL;
-	}
-}
-
-static int smsdvb_get_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
-	struct smsdvb_client_t *client =
-		container_of(fe, struct smsdvb_client_t, frontend);
-	struct smscore_device_t *coredev = client->coredev;
-	struct TRANSMISSION_STATISTICS_S *td =
-		&client->sms_stat_dvb.TransmissionData;
-
-	switch (smscore_get_device_mode(coredev)) {
-	case DEVICE_MODE_DVBT:
-	case DEVICE_MODE_DVBT_BDA:
-		fep->frequency = td->Frequency;
-
-		switch (td->Bandwidth) {
-		case 6:
-			fep->bandwidth_hz = 6000000;
-			break;
-		case 7:
-			fep->bandwidth_hz = 7000000;
-			break;
-		case 8:
-			fep->bandwidth_hz = 8000000;
-			break;
-		}
-
-		switch (td->TransmissionMode) {
-		case 2:
-			fep->transmission_mode = TRANSMISSION_MODE_2K;
-			break;
-		case 8:
-			fep->transmission_mode = TRANSMISSION_MODE_8K;
-		}
-
-		switch (td->GuardInterval) {
-		case 0:
-			fep->guard_interval = GUARD_INTERVAL_1_32;
-			break;
-		case 1:
-			fep->guard_interval = GUARD_INTERVAL_1_16;
-			break;
-		case 2:
-			fep->guard_interval = GUARD_INTERVAL_1_8;
-			break;
-		case 3:
-			fep->guard_interval = GUARD_INTERVAL_1_4;
-			break;
-		}
-
-		switch (td->CodeRate) {
-		case 0:
-			fep->code_rate_HP = FEC_1_2;
-			break;
-		case 1:
-			fep->code_rate_HP = FEC_2_3;
-			break;
-		case 2:
-			fep->code_rate_HP = FEC_3_4;
-			break;
-		case 3:
-			fep->code_rate_HP = FEC_5_6;
-			break;
-		case 4:
-			fep->code_rate_HP = FEC_7_8;
-			break;
-		}
-
-		switch (td->LPCodeRate) {
-		case 0:
-			fep->code_rate_LP = FEC_1_2;
-			break;
-		case 1:
-			fep->code_rate_LP = FEC_2_3;
-			break;
-		case 2:
-			fep->code_rate_LP = FEC_3_4;
-			break;
-		case 3:
-			fep->code_rate_LP = FEC_5_6;
-			break;
-		case 4:
-			fep->code_rate_LP = FEC_7_8;
-			break;
-		}
-
-		switch (td->Constellation) {
-		case 0:
-			fep->modulation = QPSK;
-			break;
-		case 1:
-			fep->modulation = QAM_16;
-			break;
-		case 2:
-			fep->modulation = QAM_64;
-			break;
-		}
-
-		switch (td->Hierarchy) {
-		case 0:
-			fep->hierarchy = HIERARCHY_NONE;
-			break;
-		case 1:
-			fep->hierarchy = HIERARCHY_1;
-			break;
-		case 2:
-			fep->hierarchy = HIERARCHY_2;
-			break;
-		case 3:
-			fep->hierarchy = HIERARCHY_4;
-			break;
-		}
-
-		fep->inversion = INVERSION_AUTO;
-		break;
-	case DEVICE_MODE_ISDBT:
-	case DEVICE_MODE_ISDBT_BDA:
-		fep->frequency = td->Frequency;
-		fep->bandwidth_hz = 6000000;
-		/* todo: retrive the other parameters */
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int smsdvb_init(struct dvb_frontend *fe)
-{
-	struct smsdvb_client_t *client =
-		container_of(fe, struct smsdvb_client_t, frontend);
-
-	sms_board_power(client->coredev, 1);
-
-	sms_board_dvb3_event(client, DVB3_EVENT_INIT);
-	return 0;
-}
-
-static int smsdvb_sleep(struct dvb_frontend *fe)
-{
-	struct smsdvb_client_t *client =
-		container_of(fe, struct smsdvb_client_t, frontend);
-
-	sms_board_led_feedback(client->coredev, SMS_LED_OFF);
-	sms_board_power(client->coredev, 0);
-
-	sms_board_dvb3_event(client, DVB3_EVENT_SLEEP);
-
-	return 0;
-}
-
-static void smsdvb_release(struct dvb_frontend *fe)
-{
-	/* do nothing */
-}
-
-static struct dvb_frontend_ops smsdvb_fe_ops = {
-	.info = {
-		.name			= "Siano Mobile Digital MDTV Receiver",
-		.frequency_min		= 44250000,
-		.frequency_max		= 867250000,
-		.frequency_stepsize	= 250000,
-		.caps = FE_CAN_INVERSION_AUTO |
-			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_FEC_AUTO |
-			FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 |
-			FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO |
-			FE_CAN_GUARD_INTERVAL_AUTO |
-			FE_CAN_RECOVER |
-			FE_CAN_HIERARCHY_AUTO,
-	},
-
-	.release = smsdvb_release,
-
-	.set_frontend = smsdvb_set_frontend,
-	.get_frontend = smsdvb_get_frontend,
-	.get_tune_settings = smsdvb_get_tune_settings,
-
-	.read_status = smsdvb_read_status,
-	.read_ber = smsdvb_read_ber,
-	.read_signal_strength = smsdvb_read_signal_strength,
-	.read_snr = smsdvb_read_snr,
-	.read_ucblocks = smsdvb_read_ucblocks,
-
-	.init = smsdvb_init,
-	.sleep = smsdvb_sleep,
-};
-
-static int smsdvb_hotplug(struct smscore_device_t *coredev,
-			  struct device *device, int arrival)
-{
-	struct smsclient_params_t params;
-	struct smsdvb_client_t *client;
-	int rc;
-
-	/* device removal handled by onremove callback */
-	if (!arrival)
-		return 0;
-	client = kzalloc(sizeof(struct smsdvb_client_t), GFP_KERNEL);
-	if (!client) {
-		sms_err("kmalloc() failed");
-		return -ENOMEM;
-	}
-
-	/* register dvb adapter */
-	rc = dvb_register_adapter(&client->adapter,
-				  sms_get_board(
-					smscore_get_board_id(coredev))->name,
-				  THIS_MODULE, device, adapter_nr);
-	if (rc < 0) {
-		sms_err("dvb_register_adapter() failed %d", rc);
-		goto adapter_error;
-	}
-
-	/* init dvb demux */
-	client->demux.dmx.capabilities = DMX_TS_FILTERING;
-	client->demux.filternum = 32; /* todo: nova ??? */
-	client->demux.feednum = 32;
-	client->demux.start_feed = smsdvb_start_feed;
-	client->demux.stop_feed = smsdvb_stop_feed;
-
-	rc = dvb_dmx_init(&client->demux);
-	if (rc < 0) {
-		sms_err("dvb_dmx_init failed %d", rc);
-		goto dvbdmx_error;
-	}
-
-	/* init dmxdev */
-	client->dmxdev.filternum = 32;
-	client->dmxdev.demux = &client->demux.dmx;
-	client->dmxdev.capabilities = 0;
-
-	rc = dvb_dmxdev_init(&client->dmxdev, &client->adapter);
-	if (rc < 0) {
-		sms_err("dvb_dmxdev_init failed %d", rc);
-		goto dmxdev_error;
-	}
-
-	/* init and register frontend */
-	memcpy(&client->frontend.ops, &smsdvb_fe_ops,
-	       sizeof(struct dvb_frontend_ops));
-
-	switch (smscore_get_device_mode(coredev)) {
-	case DEVICE_MODE_DVBT:
-	case DEVICE_MODE_DVBT_BDA:
-		client->frontend.ops.delsys[0] = SYS_DVBT;
-		break;
-	case DEVICE_MODE_ISDBT:
-	case DEVICE_MODE_ISDBT_BDA:
-		client->frontend.ops.delsys[0] = SYS_ISDBT;
-		break;
-	}
-
-	rc = dvb_register_frontend(&client->adapter, &client->frontend);
-	if (rc < 0) {
-		sms_err("frontend registration failed %d", rc);
-		goto frontend_error;
-	}
-
-	params.initial_id = 1;
-	params.data_type = MSG_SMS_DVBT_BDA_DATA;
-	params.onresponse_handler = smsdvb_onresponse;
-	params.onremove_handler = smsdvb_onremove;
-	params.context = client;
-
-	rc = smscore_register_client(coredev, &params, &client->smsclient);
-	if (rc < 0) {
-		sms_err("smscore_register_client() failed %d", rc);
-		goto client_error;
-	}
-
-	client->coredev = coredev;
-
-	init_completion(&client->tune_done);
-
-	kmutex_lock(&g_smsdvb_clientslock);
-
-	list_add(&client->entry, &g_smsdvb_clients);
-
-	kmutex_unlock(&g_smsdvb_clientslock);
-
-	client->event_fe_state = -1;
-	client->event_unc_state = -1;
-	sms_board_dvb3_event(client, DVB3_EVENT_HOTPLUG);
-
-	sms_info("success");
-	sms_board_setup(coredev);
-
-	return 0;
-
-client_error:
-	dvb_unregister_frontend(&client->frontend);
-
-frontend_error:
-	dvb_dmxdev_release(&client->dmxdev);
-
-dmxdev_error:
-	dvb_dmx_release(&client->demux);
-
-dvbdmx_error:
-	dvb_unregister_adapter(&client->adapter);
-
-adapter_error:
-	kfree(client);
-	return rc;
-}
-
-static int __init smsdvb_module_init(void)
-{
-	int rc;
-
-	INIT_LIST_HEAD(&g_smsdvb_clients);
-	kmutex_init(&g_smsdvb_clientslock);
-
-	rc = smscore_register_hotplug(smsdvb_hotplug);
-
-	sms_debug("");
-
-	return rc;
-}
-
-static void __exit smsdvb_module_exit(void)
-{
-	smscore_unregister_hotplug(smsdvb_hotplug);
-
-	kmutex_lock(&g_smsdvb_clientslock);
-
-	while (!list_empty(&g_smsdvb_clients))
-	       smsdvb_unregister_client(
-			(struct smsdvb_client_t *) g_smsdvb_clients.next);
-
-	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/smsendian.c b/drivers/media/dvb/siano/smsendian.c
deleted file mode 100644
index e2657c2..0000000
--- a/drivers/media/dvb/siano/smsendian.c
+++ /dev/null
@@ -1,103 +0,0 @@
-/****************************************************************
-
- Siano Mobile Silicon, Inc.
- MDTV receiver kernel modules.
- Copyright (C) 2006-2009, Uri Shkolnik
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
- ****************************************************************/
-
-#include <linux/export.h>
-#include <asm/byteorder.h>
-
-#include "smsendian.h"
-#include "smscoreapi.h"
-
-void smsendian_handle_tx_message(void *buffer)
-{
-#ifdef __BIG_ENDIAN
-	struct SmsMsgData_ST *msg = (struct SmsMsgData_ST *)buffer;
-	int i;
-	int msgWords;
-
-	switch (msg->xMsgHeader.msgType) {
-	case MSG_SMS_DATA_DOWNLOAD_REQ:
-	{
-		msg->msgData[0] = le32_to_cpu(msg->msgData[0]);
-		break;
-	}
-
-	default:
-		msgWords = (msg->xMsgHeader.msgLength -
-				sizeof(struct SmsMsgHdr_ST))/4;
-
-		for (i = 0; i < msgWords; i++)
-			msg->msgData[i] = le32_to_cpu(msg->msgData[i]);
-
-		break;
-	}
-#endif /* __BIG_ENDIAN */
-}
-EXPORT_SYMBOL_GPL(smsendian_handle_tx_message);
-
-void smsendian_handle_rx_message(void *buffer)
-{
-#ifdef __BIG_ENDIAN
-	struct SmsMsgData_ST *msg = (struct SmsMsgData_ST *)buffer;
-	int i;
-	int msgWords;
-
-	switch (msg->xMsgHeader.msgType) {
-	case MSG_SMS_GET_VERSION_EX_RES:
-	{
-		struct SmsVersionRes_ST *ver =
-			(struct SmsVersionRes_ST *) msg;
-		ver->ChipModel = le16_to_cpu(ver->ChipModel);
-		break;
-	}
-
-	case MSG_SMS_DVBT_BDA_DATA:
-	case MSG_SMS_DAB_CHANNEL:
-	case MSG_SMS_DATA_MSG:
-	{
-		break;
-	}
-
-	default:
-	{
-		msgWords = (msg->xMsgHeader.msgLength -
-				sizeof(struct SmsMsgHdr_ST))/4;
-
-		for (i = 0; i < msgWords; i++)
-			msg->msgData[i] = le32_to_cpu(msg->msgData[i]);
-
-		break;
-	}
-	}
-#endif /* __BIG_ENDIAN */
-}
-EXPORT_SYMBOL_GPL(smsendian_handle_rx_message);
-
-void smsendian_handle_message_header(void *msg)
-{
-#ifdef __BIG_ENDIAN
-	struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *)msg;
-
-	phdr->msgType = le16_to_cpu(phdr->msgType);
-	phdr->msgLength = le16_to_cpu(phdr->msgLength);
-	phdr->msgFlags = le16_to_cpu(phdr->msgFlags);
-#endif /* __BIG_ENDIAN */
-}
-EXPORT_SYMBOL_GPL(smsendian_handle_message_header);
diff --git a/drivers/media/dvb/siano/smsendian.h b/drivers/media/dvb/siano/smsendian.h
deleted file mode 100644
index 1624d6f..0000000
--- a/drivers/media/dvb/siano/smsendian.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/****************************************************************
-
-Siano Mobile Silicon, Inc.
-MDTV receiver kernel modules.
-Copyright (C) 2006-2009, Uri Shkolnik
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 2 of the License, or
-(at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-****************************************************************/
-
-#ifndef __SMS_ENDIAN_H__
-#define __SMS_ENDIAN_H__
-
-#include <asm/byteorder.h>
-
-extern void smsendian_handle_tx_message(void *buffer);
-extern void smsendian_handle_rx_message(void *buffer);
-extern void smsendian_handle_message_header(void *msg);
-
-#endif /* __SMS_ENDIAN_H__ */
-
diff --git a/drivers/media/dvb/siano/smsir.c b/drivers/media/dvb/siano/smsir.c
deleted file mode 100644
index 37bc5c4..0000000
--- a/drivers/media/dvb/siano/smsir.c
+++ /dev/null
@@ -1,114 +0,0 @@
-/****************************************************************
-
- Siano Mobile Silicon, Inc.
- MDTV receiver kernel modules.
- Copyright (C) 2006-2009, Uri Shkolnik
-
- Copyright (c) 2010 - Mauro Carvalho Chehab
-	- Ported the driver to use rc-core
-	- IR raw event decoding is now done at rc-core
-	- Code almost re-written
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
- ****************************************************************/
-
-
-#include <linux/types.h>
-#include <linux/input.h>
-
-#include "smscoreapi.h"
-#include "smsir.h"
-#include "sms-cards.h"
-
-#define MODULE_NAME "smsmdtv"
-
-void sms_ir_event(struct smscore_device_t *coredev, const char *buf, int len)
-{
-	int i;
-	const s32 *samples = (const void *)buf;
-
-	for (i = 0; i < len >> 2; i++) {
-		DEFINE_IR_RAW_EVENT(ev);
-
-		ev.duration = abs(samples[i]) * 1000; /* Convert to ns */
-		ev.pulse = (samples[i] > 0) ? false : true;
-
-		ir_raw_event_store(coredev->ir.dev, &ev);
-	}
-	ir_raw_event_handle(coredev->ir.dev);
-}
-
-int sms_ir_init(struct smscore_device_t *coredev)
-{
-	int err;
-	int board_id = smscore_get_board_id(coredev);
-	struct rc_dev *dev;
-
-	sms_log("Allocating rc device");
-	dev = rc_allocate_device();
-	if (!dev) {
-		sms_err("Not enough memory");
-		return -ENOMEM;
-	}
-
-	coredev->ir.controller = 0;	/* Todo: vega/nova SPI number */
-	coredev->ir.timeout = IR_DEFAULT_TIMEOUT;
-	sms_log("IR port %d, timeout %d ms",
-			coredev->ir.controller, coredev->ir.timeout);
-
-	snprintf(coredev->ir.name, sizeof(coredev->ir.name),
-		 "SMS IR (%s)", sms_get_board(board_id)->name);
-
-	strlcpy(coredev->ir.phys, coredev->devpath, sizeof(coredev->ir.phys));
-	strlcat(coredev->ir.phys, "/ir0", sizeof(coredev->ir.phys));
-
-	dev->input_name = coredev->ir.name;
-	dev->input_phys = coredev->ir.phys;
-	dev->dev.parent = coredev->device;
-
-#if 0
-	/* TODO: properly initialize the parameters bellow */
-	dev->input_id.bustype = BUS_USB;
-	dev->input_id.version = 1;
-	dev->input_id.vendor = le16_to_cpu(dev->udev->descriptor.idVendor);
-	dev->input_id.product = le16_to_cpu(dev->udev->descriptor.idProduct);
-#endif
-
-	dev->priv = coredev;
-	dev->driver_type = RC_DRIVER_IR_RAW;
-	dev->allowed_protos = RC_TYPE_ALL;
-	dev->map_name = sms_get_board(board_id)->rc_codes;
-	dev->driver_name = MODULE_NAME;
-
-	sms_log("Input device (IR) %s is set for key events", dev->input_name);
-
-	err = rc_register_device(dev);
-	if (err < 0) {
-		sms_err("Failed to register device");
-		rc_free_device(dev);
-		return err;
-	}
-
-	coredev->ir.dev = dev;
-	return 0;
-}
-
-void sms_ir_exit(struct smscore_device_t *coredev)
-{
-	if (coredev->ir.dev)
-		rc_unregister_device(coredev->ir.dev);
-
-	sms_log("");
-}
diff --git a/drivers/media/dvb/siano/smsir.h b/drivers/media/dvb/siano/smsir.h
deleted file mode 100644
index ae92b3a..0000000
--- a/drivers/media/dvb/siano/smsir.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/****************************************************************
-
-Siano Mobile Silicon, Inc.
-MDTV receiver kernel modules.
-Copyright (C) 2006-2009, Uri Shkolnik
-
- Copyright (c) 2010 - Mauro Carvalho Chehab
-	- Ported the driver to use rc-core
-	- IR raw event decoding is now done at rc-core
-	- Code almost re-written
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 2 of the License, or
-(at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-****************************************************************/
-
-#ifndef __SMS_IR_H__
-#define __SMS_IR_H__
-
-#include <linux/input.h>
-#include <media/rc-core.h>
-
-#define IR_DEFAULT_TIMEOUT		100
-
-struct smscore_device_t;
-
-struct ir_t {
-	struct rc_dev *dev;
-	char name[40];
-	char phys[32];
-
-	char *rc_codes;
-	u64 protocol;
-
-	u32 timeout;
-	u32 controller;
-};
-
-int sms_ir_init(struct smscore_device_t *coredev);
-void sms_ir_exit(struct smscore_device_t *coredev);
-void sms_ir_event(struct smscore_device_t *coredev,
-			const char *buf, int len);
-
-#endif /* __SMS_IR_H__ */
-
diff --git a/drivers/media/dvb/siano/smssdio.c b/drivers/media/dvb/siano/smssdio.c
deleted file mode 100644
index d6f3f10..0000000
--- a/drivers/media/dvb/siano/smssdio.c
+++ /dev/null
@@ -1,365 +0,0 @@
-/*
- *  smssdio.c - Siano 1xxx SDIO interface driver
- *
- *  Copyright 2008 Pierre Ossman
- *
- * Based on code by Siano Mobile Silicon, Inc.,
- * Copyright (C) 2006-2008, Uri Shkolnik
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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 hardware is a bit odd in that all transfers should be done
- * to/from the SMSSDIO_DATA register, yet the "increase address" bit
- * always needs to be set.
- *
- * Also, buffers from the card are always aligned to 128 byte
- * boundaries.
- */
-
-/*
- * General cleanup notes:
- *
- * - only typedefs should be name *_t
- *
- * - use ERR_PTR and friends for smscore_register_device()
- *
- * - smscore_getbuffer should zero fields
- *
- * Fix stop command
- */
-
-#include <linux/moduleparam.h>
-#include <linux/slab.h>
-#include <linux/firmware.h>
-#include <linux/delay.h>
-#include <linux/mmc/card.h>
-#include <linux/mmc/sdio_func.h>
-#include <linux/mmc/sdio_ids.h>
-#include <linux/module.h>
-
-#include "smscoreapi.h"
-#include "sms-cards.h"
-
-/* Registers */
-
-#define SMSSDIO_DATA		0x00
-#define SMSSDIO_INT		0x04
-#define SMSSDIO_BLOCK_SIZE	128
-
-static const struct sdio_device_id smssdio_ids[] __devinitconst = {
-	{SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_STELLAR),
-	 .driver_data = SMS1XXX_BOARD_SIANO_STELLAR},
-	{SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_NOVA_A0),
-	 .driver_data = SMS1XXX_BOARD_SIANO_NOVA_A},
-	{SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_NOVA_B0),
-	 .driver_data = SMS1XXX_BOARD_SIANO_NOVA_B},
-	{SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_VEGA_A0),
-	 .driver_data = SMS1XXX_BOARD_SIANO_VEGA},
-	{SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_VENICE),
-	 .driver_data = SMS1XXX_BOARD_SIANO_VEGA},
-	{ /* end: all zeroes */ },
-};
-
-MODULE_DEVICE_TABLE(sdio, smssdio_ids);
-
-struct smssdio_device {
-	struct sdio_func *func;
-
-	struct smscore_device_t *coredev;
-
-	struct smscore_buffer_t *split_cb;
-};
-
-/*******************************************************************/
-/* Siano core callbacks                                            */
-/*******************************************************************/
-
-static int smssdio_sendrequest(void *context, void *buffer, size_t size)
-{
-	int ret = 0;
-	struct smssdio_device *smsdev;
-
-	smsdev = context;
-
-	sdio_claim_host(smsdev->func);
-
-	while (size >= smsdev->func->cur_blksize) {
-		ret = sdio_memcpy_toio(smsdev->func, SMSSDIO_DATA,
-					buffer, smsdev->func->cur_blksize);
-		if (ret)
-			goto out;
-
-		buffer += smsdev->func->cur_blksize;
-		size -= smsdev->func->cur_blksize;
-	}
-
-	if (size) {
-		ret = sdio_memcpy_toio(smsdev->func, SMSSDIO_DATA,
-					buffer, size);
-	}
-
-out:
-	sdio_release_host(smsdev->func);
-
-	return ret;
-}
-
-/*******************************************************************/
-/* SDIO callbacks                                                  */
-/*******************************************************************/
-
-static void smssdio_interrupt(struct sdio_func *func)
-{
-	int ret;
-
-	struct smssdio_device *smsdev;
-	struct smscore_buffer_t *cb;
-	struct SmsMsgHdr_ST *hdr;
-	size_t size;
-
-	smsdev = sdio_get_drvdata(func);
-
-	/*
-	 * The interrupt register has no defined meaning. It is just
-	 * a way of turning of the level triggered interrupt.
-	 */
-	(void)sdio_readb(func, SMSSDIO_INT, &ret);
-	if (ret) {
-		sms_err("Unable to read interrupt register!\n");
-		return;
-	}
-
-	if (smsdev->split_cb == NULL) {
-		cb = smscore_getbuffer(smsdev->coredev);
-		if (!cb) {
-			sms_err("Unable to allocate data buffer!\n");
-			return;
-		}
-
-		ret = sdio_memcpy_fromio(smsdev->func,
-					 cb->p,
-					 SMSSDIO_DATA,
-					 SMSSDIO_BLOCK_SIZE);
-		if (ret) {
-			sms_err("Error %d reading initial block!\n", ret);
-			return;
-		}
-
-		hdr = cb->p;
-
-		if (hdr->msgFlags & MSG_HDR_FLAG_SPLIT_MSG) {
-			smsdev->split_cb = cb;
-			return;
-		}
-
-		if (hdr->msgLength > smsdev->func->cur_blksize)
-			size = hdr->msgLength - smsdev->func->cur_blksize;
-		else
-			size = 0;
-	} else {
-		cb = smsdev->split_cb;
-		hdr = cb->p;
-
-		size = hdr->msgLength - sizeof(struct SmsMsgHdr_ST);
-
-		smsdev->split_cb = NULL;
-	}
-
-	if (size) {
-		void *buffer;
-
-		buffer = cb->p + (hdr->msgLength - size);
-		size = ALIGN(size, SMSSDIO_BLOCK_SIZE);
-
-		BUG_ON(smsdev->func->cur_blksize != SMSSDIO_BLOCK_SIZE);
-
-		/*
-		 * First attempt to transfer all of it in one go...
-		 */
-		ret = sdio_memcpy_fromio(smsdev->func,
-					 buffer,
-					 SMSSDIO_DATA,
-					 size);
-		if (ret && ret != -EINVAL) {
-			smscore_putbuffer(smsdev->coredev, cb);
-			sms_err("Error %d reading data from card!\n", ret);
-			return;
-		}
-
-		/*
-		 * ..then fall back to one block at a time if that is
-		 * not possible...
-		 *
-		 * (we have to do this manually because of the
-		 * problem with the "increase address" bit)
-		 */
-		if (ret == -EINVAL) {
-			while (size) {
-				ret = sdio_memcpy_fromio(smsdev->func,
-						  buffer, SMSSDIO_DATA,
-						  smsdev->func->cur_blksize);
-				if (ret) {
-					smscore_putbuffer(smsdev->coredev, cb);
-					sms_err("Error %d reading "
-						"data from card!\n", ret);
-					return;
-				}
-
-				buffer += smsdev->func->cur_blksize;
-				if (size > smsdev->func->cur_blksize)
-					size -= smsdev->func->cur_blksize;
-				else
-					size = 0;
-			}
-		}
-	}
-
-	cb->size = hdr->msgLength;
-	cb->offset = 0;
-
-	smscore_onresponse(smsdev->coredev, cb);
-}
-
-static int __devinit smssdio_probe(struct sdio_func *func,
-			 const struct sdio_device_id *id)
-{
-	int ret;
-
-	int board_id;
-	struct smssdio_device *smsdev;
-	struct smsdevice_params_t params;
-
-	board_id = id->driver_data;
-
-	smsdev = kzalloc(sizeof(struct smssdio_device), GFP_KERNEL);
-	if (!smsdev)
-		return -ENOMEM;
-
-	smsdev->func = func;
-
-	memset(&params, 0, sizeof(struct smsdevice_params_t));
-
-	params.device = &func->dev;
-	params.buffer_size = 0x5000;	/* ?? */
-	params.num_buffers = 22;	/* ?? */
-	params.context = smsdev;
-
-	snprintf(params.devpath, sizeof(params.devpath),
-		 "sdio\\%s", sdio_func_id(func));
-
-	params.sendrequest_handler = smssdio_sendrequest;
-
-	params.device_type = sms_get_board(board_id)->type;
-
-	if (params.device_type != SMS_STELLAR)
-		params.flags |= SMS_DEVICE_FAMILY2;
-	else {
-		/*
-		 * FIXME: Stellar needs special handling...
-		 */
-		ret = -ENODEV;
-		goto free;
-	}
-
-	ret = smscore_register_device(&params, &smsdev->coredev);
-	if (ret < 0)
-		goto free;
-
-	smscore_set_board_id(smsdev->coredev, board_id);
-
-	sdio_claim_host(func);
-
-	ret = sdio_enable_func(func);
-	if (ret)
-		goto release;
-
-	ret = sdio_set_block_size(func, SMSSDIO_BLOCK_SIZE);
-	if (ret)
-		goto disable;
-
-	ret = sdio_claim_irq(func, smssdio_interrupt);
-	if (ret)
-		goto disable;
-
-	sdio_set_drvdata(func, smsdev);
-
-	sdio_release_host(func);
-
-	ret = smscore_start_device(smsdev->coredev);
-	if (ret < 0)
-		goto reclaim;
-
-	return 0;
-
-reclaim:
-	sdio_claim_host(func);
-	sdio_release_irq(func);
-disable:
-	sdio_disable_func(func);
-release:
-	sdio_release_host(func);
-	smscore_unregister_device(smsdev->coredev);
-free:
-	kfree(smsdev);
-
-	return ret;
-}
-
-static void smssdio_remove(struct sdio_func *func)
-{
-	struct smssdio_device *smsdev;
-
-	smsdev = sdio_get_drvdata(func);
-
-	/* FIXME: racy! */
-	if (smsdev->split_cb)
-		smscore_putbuffer(smsdev->coredev, smsdev->split_cb);
-
-	smscore_unregister_device(smsdev->coredev);
-
-	sdio_claim_host(func);
-	sdio_release_irq(func);
-	sdio_disable_func(func);
-	sdio_release_host(func);
-
-	kfree(smsdev);
-}
-
-static struct sdio_driver smssdio_driver = {
-	.name = "smssdio",
-	.id_table = smssdio_ids,
-	.probe = smssdio_probe,
-	.remove = smssdio_remove,
-};
-
-/*******************************************************************/
-/* Module functions                                                */
-/*******************************************************************/
-
-static int __init smssdio_module_init(void)
-{
-	int ret = 0;
-
-	printk(KERN_INFO "smssdio: Siano SMS1xxx SDIO driver\n");
-	printk(KERN_INFO "smssdio: Copyright Pierre Ossman\n");
-
-	ret = sdio_register_driver(&smssdio_driver);
-
-	return ret;
-}
-
-static void __exit smssdio_module_exit(void)
-{
-	sdio_unregister_driver(&smssdio_driver);
-}
-
-module_init(smssdio_module_init);
-module_exit(smssdio_module_exit);
-
-MODULE_DESCRIPTION("Siano SMS1xxx SDIO driver");
-MODULE_AUTHOR("Pierre Ossman");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/siano/smsusb.c b/drivers/media/dvb/siano/smsusb.c
deleted file mode 100644
index aac6222..0000000
--- a/drivers/media/dvb/siano/smsusb.c
+++ /dev/null
@@ -1,568 +0,0 @@
-/****************************************************************
-
-Siano Mobile Silicon, Inc.
-MDTV receiver kernel modules.
-Copyright (C) 2005-2009, Uri Shkolnik, Anatoly Greenblat
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 2 of the License, or
-(at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-****************************************************************/
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/usb.h>
-#include <linux/firmware.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-
-#include "smscoreapi.h"
-#include "sms-cards.h"
-#include "smsendian.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
-
-#define MAX_BUFFERS		50
-#define MAX_URBS		10
-
-struct smsusb_device_t;
-
-struct smsusb_urb_t {
-	struct smscore_buffer_t *cb;
-	struct smsusb_device_t	*dev;
-
-	struct urb urb;
-};
-
-struct smsusb_device_t {
-	struct usb_device *udev;
-	struct smscore_device_t *coredev;
-
-	struct smsusb_urb_t 	surbs[MAX_URBS];
-
-	int		response_alignment;
-	int		buffer_size;
-};
-
-static int smsusb_submit_urb(struct smsusb_device_t *dev,
-			     struct smsusb_urb_t *surb);
-
-static void smsusb_onresponse(struct urb *urb)
-{
-	struct smsusb_urb_t *surb = (struct smsusb_urb_t *) urb->context;
-	struct smsusb_device_t *dev = surb->dev;
-
-	if (urb->status == -ESHUTDOWN) {
-		sms_err("error, urb status %d (-ESHUTDOWN), %d bytes",
-			urb->status, urb->actual_length);
-		return;
-	}
-
-	if ((urb->actual_length > 0) && (urb->status == 0)) {
-		struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *)surb->cb->p;
-
-		smsendian_handle_message_header(phdr);
-		if (urb->actual_length >= phdr->msgLength) {
-			surb->cb->size = phdr->msgLength;
-
-			if (dev->response_alignment &&
-			    (phdr->msgFlags & MSG_HDR_FLAG_SPLIT_MSG)) {
-
-				surb->cb->offset =
-					dev->response_alignment +
-					((phdr->msgFlags >> 8) & 3);
-
-				/* sanity check */
-				if (((int) phdr->msgLength +
-				     surb->cb->offset) > urb->actual_length) {
-					sms_err("invalid response "
-						"msglen %d offset %d "
-						"size %d",
-						phdr->msgLength,
-						surb->cb->offset,
-						urb->actual_length);
-					goto exit_and_resubmit;
-				}
-
-				/* move buffer pointer and
-				 * copy header to its new location */
-				memcpy((char *) phdr + surb->cb->offset,
-				       phdr, sizeof(struct SmsMsgHdr_ST));
-			} else
-				surb->cb->offset = 0;
-
-			smscore_onresponse(dev->coredev, surb->cb);
-			surb->cb = NULL;
-		} else {
-			sms_err("invalid response "
-				"msglen %d actual %d",
-				phdr->msgLength, urb->actual_length);
-		}
-	} else
-		sms_err("error, urb status %d, %d bytes",
-			urb->status, urb->actual_length);
-
-
-exit_and_resubmit:
-	smsusb_submit_urb(dev, surb);
-}
-
-static int smsusb_submit_urb(struct smsusb_device_t *dev,
-			     struct smsusb_urb_t *surb)
-{
-	if (!surb->cb) {
-		surb->cb = smscore_getbuffer(dev->coredev);
-		if (!surb->cb) {
-			sms_err("smscore_getbuffer(...) returned NULL");
-			return -ENOMEM;
-		}
-	}
-
-	usb_fill_bulk_urb(
-		&surb->urb,
-		dev->udev,
-		usb_rcvbulkpipe(dev->udev, 0x81),
-		surb->cb->p,
-		dev->buffer_size,
-		smsusb_onresponse,
-		surb
-	);
-	surb->urb.transfer_dma = surb->cb->phys;
-	surb->urb.transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
-
-	return usb_submit_urb(&surb->urb, GFP_ATOMIC);
-}
-
-static void smsusb_stop_streaming(struct smsusb_device_t *dev)
-{
-	int i;
-
-	for (i = 0; i < MAX_URBS; i++) {
-		usb_kill_urb(&dev->surbs[i].urb);
-
-		if (dev->surbs[i].cb) {
-			smscore_putbuffer(dev->coredev, dev->surbs[i].cb);
-			dev->surbs[i].cb = NULL;
-		}
-	}
-}
-
-static int smsusb_start_streaming(struct smsusb_device_t *dev)
-{
-	int i, rc;
-
-	for (i = 0; i < MAX_URBS; i++) {
-		rc = smsusb_submit_urb(dev, &dev->surbs[i]);
-		if (rc < 0) {
-			sms_err("smsusb_submit_urb(...) failed");
-			smsusb_stop_streaming(dev);
-			break;
-		}
-	}
-
-	return rc;
-}
-
-static int smsusb_sendrequest(void *context, void *buffer, size_t size)
-{
-	struct smsusb_device_t *dev = (struct smsusb_device_t *) context;
-	int dummy;
-
-	smsendian_handle_message_header((struct SmsMsgHdr_ST *)buffer);
-	return usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, 2),
-			    buffer, size, &dummy, 1000);
-}
-
-static char *smsusb1_fw_lkup[] = {
-	"dvbt_stellar_usb.inp",
-	"dvbh_stellar_usb.inp",
-	"tdmb_stellar_usb.inp",
-	"none",
-	"dvbt_bda_stellar_usb.inp",
-};
-
-static inline char *sms_get_fw_name(int mode, int board_id)
-{
-	char **fw = sms_get_board(board_id)->fw;
-	return (fw && fw[mode]) ? fw[mode] : smsusb1_fw_lkup[mode];
-}
-
-static int smsusb1_load_firmware(struct usb_device *udev, int id, int board_id)
-{
-	const struct firmware *fw;
-	u8 *fw_buffer;
-	int rc, dummy;
-	char *fw_filename;
-
-	if (id < DEVICE_MODE_DVBT || id > DEVICE_MODE_DVBT_BDA) {
-		sms_err("invalid firmware id specified %d", id);
-		return -EINVAL;
-	}
-
-	fw_filename = sms_get_fw_name(id, board_id);
-
-	rc = request_firmware(&fw, fw_filename, &udev->dev);
-	if (rc < 0) {
-		sms_warn("failed to open \"%s\" mode %d, "
-			 "trying again with default firmware", fw_filename, id);
-
-		fw_filename = smsusb1_fw_lkup[id];
-		rc = request_firmware(&fw, fw_filename, &udev->dev);
-		if (rc < 0) {
-			sms_warn("failed to open \"%s\" mode %d",
-				 fw_filename, id);
-
-			return rc;
-		}
-	}
-
-	fw_buffer = kmalloc(fw->size, GFP_KERNEL);
-	if (fw_buffer) {
-		memcpy(fw_buffer, fw->data, fw->size);
-
-		rc = usb_bulk_msg(udev, usb_sndbulkpipe(udev, 2),
-				  fw_buffer, fw->size, &dummy, 1000);
-
-		sms_info("sent %zd(%d) bytes, rc %d", fw->size, dummy, rc);
-
-		kfree(fw_buffer);
-	} else {
-		sms_err("failed to allocate firmware buffer");
-		rc = -ENOMEM;
-	}
-	sms_info("read FW %s, size=%zd", fw_filename, fw->size);
-
-	release_firmware(fw);
-
-	return rc;
-}
-
-static void smsusb1_detectmode(void *context, int *mode)
-{
-	char *product_string =
-		((struct smsusb_device_t *) context)->udev->product;
-
-	*mode = DEVICE_MODE_NONE;
-
-	if (!product_string) {
-		product_string = "none";
-		sms_err("product string not found");
-	} else if (strstr(product_string, "DVBH"))
-		*mode = 1;
-	else if (strstr(product_string, "BDA"))
-		*mode = 4;
-	else if (strstr(product_string, "DVBT"))
-		*mode = 0;
-	else if (strstr(product_string, "TDMB"))
-		*mode = 2;
-
-	sms_info("%d \"%s\"", *mode, product_string);
-}
-
-static int smsusb1_setmode(void *context, int mode)
-{
-	struct SmsMsgHdr_ST Msg = { MSG_SW_RELOAD_REQ, 0, HIF_TASK,
-			     sizeof(struct SmsMsgHdr_ST), 0 };
-
-	if (mode < DEVICE_MODE_DVBT || mode > DEVICE_MODE_DVBT_BDA) {
-		sms_err("invalid firmware id specified %d", mode);
-		return -EINVAL;
-	}
-
-	return smsusb_sendrequest(context, &Msg, sizeof(Msg));
-}
-
-static void smsusb_term_device(struct usb_interface *intf)
-{
-	struct smsusb_device_t *dev = usb_get_intfdata(intf);
-
-	if (dev) {
-		smsusb_stop_streaming(dev);
-
-		/* unregister from smscore */
-		if (dev->coredev)
-			smscore_unregister_device(dev->coredev);
-
-		sms_info("device %p destroyed", dev);
-		kfree(dev);
-	}
-
-	usb_set_intfdata(intf, NULL);
-}
-
-static int smsusb_init_device(struct usb_interface *intf, int board_id)
-{
-	struct smsdevice_params_t params;
-	struct smsusb_device_t *dev;
-	int i, rc;
-
-	/* create device object */
-	dev = kzalloc(sizeof(struct smsusb_device_t), GFP_KERNEL);
-	if (!dev) {
-		sms_err("kzalloc(sizeof(struct smsusb_device_t) failed");
-		return -ENOMEM;
-	}
-
-	memset(&params, 0, sizeof(params));
-	usb_set_intfdata(intf, dev);
-	dev->udev = interface_to_usbdev(intf);
-
-	params.device_type = sms_get_board(board_id)->type;
-
-	switch (params.device_type) {
-	case SMS_STELLAR:
-		dev->buffer_size = USB1_BUFFER_SIZE;
-
-		params.setmode_handler = smsusb1_setmode;
-		params.detectmode_handler = smsusb1_detectmode;
-		break;
-	default:
-		sms_err("Unspecified sms device type!");
-		/* fall-thru */
-	case SMS_NOVA_A0:
-	case SMS_NOVA_B0:
-	case SMS_VEGA:
-		dev->buffer_size = USB2_BUFFER_SIZE;
-		dev->response_alignment =
-		    le16_to_cpu(dev->udev->ep_in[1]->desc.wMaxPacketSize) -
-		    sizeof(struct SmsMsgHdr_ST);
-
-		params.flags |= SMS_DEVICE_FAMILY2;
-		break;
-	}
-
-	params.device = &dev->udev->dev;
-	params.buffer_size = dev->buffer_size;
-	params.num_buffers = MAX_BUFFERS;
-	params.sendrequest_handler = smsusb_sendrequest;
-	params.context = dev;
-	usb_make_path(dev->udev, params.devpath, sizeof(params.devpath));
-
-	/* register in smscore */
-	rc = smscore_register_device(&params, &dev->coredev);
-	if (rc < 0) {
-		sms_err("smscore_register_device(...) failed, rc %d", rc);
-		smsusb_term_device(intf);
-		return rc;
-	}
-
-	smscore_set_board_id(dev->coredev, board_id);
-
-	/* initialize urbs */
-	for (i = 0; i < MAX_URBS; i++) {
-		dev->surbs[i].dev = dev;
-		usb_init_urb(&dev->surbs[i].urb);
-	}
-
-	sms_info("smsusb_start_streaming(...).");
-	rc = smsusb_start_streaming(dev);
-	if (rc < 0) {
-		sms_err("smsusb_start_streaming(...) failed");
-		smsusb_term_device(intf);
-		return rc;
-	}
-
-	rc = smscore_start_device(dev->coredev);
-	if (rc < 0) {
-		sms_err("smscore_start_device(...) failed");
-		smsusb_term_device(intf);
-		return rc;
-	}
-
-	sms_info("device %p created", dev);
-
-	return rc;
-}
-
-static int __devinit smsusb_probe(struct usb_interface *intf,
-			const struct usb_device_id *id)
-{
-	struct usb_device *udev = interface_to_usbdev(intf);
-	char devpath[32];
-	int i, rc;
-
-	rc = usb_clear_halt(udev, usb_rcvbulkpipe(udev, 0x81));
-	rc = usb_clear_halt(udev, usb_rcvbulkpipe(udev, 0x02));
-
-	if (intf->num_altsetting > 0) {
-		rc = usb_set_interface(
-			udev, intf->cur_altsetting->desc.bInterfaceNumber, 0);
-		if (rc < 0) {
-			sms_err("usb_set_interface failed, rc %d", rc);
-			return rc;
-		}
-	}
-
-	sms_info("smsusb_probe %d",
-	       intf->cur_altsetting->desc.bInterfaceNumber);
-	for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++)
-		sms_info("endpoint %d %02x %02x %d", i,
-		       intf->cur_altsetting->endpoint[i].desc.bEndpointAddress,
-		       intf->cur_altsetting->endpoint[i].desc.bmAttributes,
-		       intf->cur_altsetting->endpoint[i].desc.wMaxPacketSize);
-
-	if ((udev->actconfig->desc.bNumInterfaces == 2) &&
-	    (intf->cur_altsetting->desc.bInterfaceNumber == 0)) {
-		sms_err("rom interface 0 is not used");
-		return -ENODEV;
-	}
-
-	if (intf->cur_altsetting->desc.bInterfaceNumber == 1) {
-		snprintf(devpath, sizeof(devpath), "usb\\%d-%s",
-			 udev->bus->busnum, udev->devpath);
-		sms_info("stellar device was found.");
-		return smsusb1_load_firmware(
-				udev, smscore_registry_getmode(devpath),
-				id->driver_info);
-	}
-
-	rc = smsusb_init_device(intf, id->driver_info);
-	sms_info("rc %d", rc);
-	sms_board_load_modules(id->driver_info);
-	return rc;
-}
-
-static void smsusb_disconnect(struct usb_interface *intf)
-{
-	smsusb_term_device(intf);
-}
-
-static int smsusb_suspend(struct usb_interface *intf, pm_message_t msg)
-{
-	struct smsusb_device_t *dev = usb_get_intfdata(intf);
-	printk(KERN_INFO "%s: Entering status %d.\n", __func__, msg.event);
-	smsusb_stop_streaming(dev);
-	return 0;
-}
-
-static int smsusb_resume(struct usb_interface *intf)
-{
-	int rc, i;
-	struct smsusb_device_t *dev = usb_get_intfdata(intf);
-	struct usb_device *udev = interface_to_usbdev(intf);
-
-	printk(KERN_INFO "%s: Entering.\n", __func__);
-	usb_clear_halt(udev, usb_rcvbulkpipe(udev, 0x81));
-	usb_clear_halt(udev, usb_rcvbulkpipe(udev, 0x02));
-
-	for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++)
-		printk(KERN_INFO "endpoint %d %02x %02x %d\n", i,
-		       intf->cur_altsetting->endpoint[i].desc.bEndpointAddress,
-		       intf->cur_altsetting->endpoint[i].desc.bmAttributes,
-		       intf->cur_altsetting->endpoint[i].desc.wMaxPacketSize);
-
-	if (intf->num_altsetting > 0) {
-		rc = usb_set_interface(udev,
-				       intf->cur_altsetting->desc.
-				       bInterfaceNumber, 0);
-		if (rc < 0) {
-			printk(KERN_INFO "%s usb_set_interface failed, "
-			       "rc %d\n", __func__, rc);
-			return rc;
-		}
-	}
-
-	smsusb_start_streaming(dev);
-	return 0;
-}
-
-static const struct usb_device_id smsusb_id_table[] = {
-	{ 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 },
-	{ 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 },
-	{ USB_DEVICE(0x187f, 0x0202),
-		.driver_info = SMS1XXX_BOARD_SIANO_NICE },
-	{ USB_DEVICE(0x187f, 0x0301),
-		.driver_info = SMS1XXX_BOARD_SIANO_VENICE },
-	{ USB_DEVICE(0x2040, 0xb900),
-		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
-	{ USB_DEVICE(0x2040, 0xb910),
-		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
-	{ USB_DEVICE(0x2040, 0xb980),
-		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
-	{ USB_DEVICE(0x2040, 0xb990),
-		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
-	{ USB_DEVICE(0x2040, 0xc000),
-		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
-	{ USB_DEVICE(0x2040, 0xc010),
-		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
-	{ USB_DEVICE(0x2040, 0xc080),
-		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
-	{ USB_DEVICE(0x2040, 0xc090),
-		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
-	{ USB_DEVICE(0x2040, 0xc0a0),
-		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
-	{ USB_DEVICE(0x2040, 0xf5a0),
-		.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
-	{ } /* Terminating entry */
-	};
-
-MODULE_DEVICE_TABLE(usb, smsusb_id_table);
-
-static struct usb_driver smsusb_driver = {
-	.name			= "smsusb",
-	.probe			= smsusb_probe,
-	.disconnect		= smsusb_disconnect,
-	.id_table		= smsusb_id_table,
-
-	.suspend		= smsusb_suspend,
-	.resume			= smsusb_resume,
-};
-
-module_usb_driver(smsusb_driver);
-
-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
deleted file mode 100644
index 9d83ced..0000000
--- a/drivers/media/dvb/ttpci/Kconfig
+++ /dev/null
@@ -1,159 +0,0 @@
-config TTPCI_EEPROM
-	tristate
-	depends on I2C
-	default n
-
-config DVB_AV7110
-	tristate "AV7110 cards"
-	depends on DVB_CORE && PCI && I2C
-	select TTPCI_EEPROM
-	select VIDEO_SAA7146_VV
-	depends on VIDEO_DEV	# dependencies of VIDEO_SAA7146_VV
-	select DVB_VES1820 if !DVB_FE_CUSTOMISE
-	select DVB_VES1X93 if !DVB_FE_CUSTOMISE
-	select DVB_STV0299 if !DVB_FE_CUSTOMISE
-	select DVB_TDA8083 if !DVB_FE_CUSTOMISE
-	select DVB_SP8870 if !DVB_FE_CUSTOMISE
-	select DVB_STV0297 if !DVB_FE_CUSTOMISE
-	select DVB_L64781 if !DVB_FE_CUSTOMISE
-	select DVB_LNBP21 if !DVB_FE_CUSTOMISE
-	help
-	  Support for SAA7146 and AV7110 based DVB cards as produced
-	  by Fujitsu-Siemens, Technotrend, Hauppauge and others.
-
-	  This driver only supports the fullfeatured cards with
-	  onboard MPEG2 decoder.
-
-	  This driver needs an external firmware. Please use the script
-	  "<kerneldir>/Documentation/dvb/get_dvb_firmware av7110" to
-	  download/extract it, and then copy it to /usr/lib/hotplug/firmware
-	  or /lib/firmware (depending on configuration of firmware hotplug).
-
-	  Alternatively, you can download the file and use the kernel's
-	  EXTRA_FIRMWARE configuration option to build it into your
-	  kernel image by adding the filename to the EXTRA_FIRMWARE
-	  configuration option string.
-
-	  Say Y if you own such a card and want to use it.
-
-config DVB_AV7110_OSD
-	bool "AV7110 OSD support"
-	depends on DVB_AV7110
-	default y if DVB_AV7110=y || DVB_AV7110=m
-	help
-	  The AV7110 firmware provides some code to generate an OnScreenDisplay
-	  on the video output. This is kind of nonstandard and not guaranteed to
-	  be maintained.
-
-	  Anyway, some popular DVB software like VDR uses this OSD to render
-	  its menus, so say Y if you want to use this software.
-
-	  All other people say N.
-
-config DVB_BUDGET_CORE
-	tristate "SAA7146 DVB cards (aka Budget, Nova-PCI)"
-	depends on DVB_CORE && PCI && I2C
-	select VIDEO_SAA7146
-	select TTPCI_EEPROM
-	help
-	  Support for simple SAA7146 based DVB cards
-	  (so called Budget- or Nova-PCI cards) without onboard
-	  MPEG2 decoder.
-
-config DVB_BUDGET
-	tristate "Budget cards"
-	depends on DVB_BUDGET_CORE && I2C
-	select DVB_STV0299 if !DVB_FE_CUSTOMISE
-	select DVB_VES1X93 if !DVB_FE_CUSTOMISE
-	select DVB_VES1820 if !DVB_FE_CUSTOMISE
-	select DVB_L64781 if !DVB_FE_CUSTOMISE
-	select DVB_TDA8083 if !DVB_FE_CUSTOMISE
-	select DVB_S5H1420 if !DVB_FE_CUSTOMISE
-	select DVB_TDA10086 if !DVB_FE_CUSTOMISE
-	select DVB_TDA826X if !DVB_FE_CUSTOMISE
-	select DVB_LNBP21 if !DVB_FE_CUSTOMISE
-	select DVB_TDA1004X if !DVB_FE_CUSTOMISE
-	select DVB_ISL6423 if !DVB_FE_CUSTOMISE
-	select DVB_STV090x if !DVB_FE_CUSTOMISE
-	select DVB_STV6110x if !DVB_FE_CUSTOMISE
-	help
-	  Support for simple SAA7146 based DVB cards (so called Budget-
-	  or Nova-PCI cards) without onboard MPEG2 decoder, and without
-	  analog inputs or an onboard Common Interface connector.
-
-	  Say Y if you own such a card and want to use it.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called budget.
-
-config DVB_BUDGET_CI
-	tristate "Budget cards with onboard CI connector"
-	depends on DVB_BUDGET_CORE && I2C
-	select DVB_STV0297 if !DVB_FE_CUSTOMISE
-	select DVB_STV0299 if !DVB_FE_CUSTOMISE
-	select DVB_TDA1004X if !DVB_FE_CUSTOMISE
-	select DVB_STB0899 if !DVB_FE_CUSTOMISE
-	select DVB_STB6100 if !DVB_FE_CUSTOMISE
-	select DVB_LNBP21 if !DVB_FE_CUSTOMISE
-	select DVB_STV0288 if !DVB_FE_CUSTOMISE
-	select DVB_STB6000 if !DVB_FE_CUSTOMISE
-	select DVB_TDA10023 if !DVB_FE_CUSTOMISE
-	select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMISE
-	depends on RC_CORE
-	help
-	  Support for simple SAA7146 based DVB cards
-	  (so called Budget- or Nova-PCI cards) without onboard
-	  MPEG2 decoder, but with onboard Common Interface connector.
-
-	  Note: The Common Interface is not yet supported by this driver
-	  due to lack of information from the vendor.
-
-	  Say Y if you own such a card and want to use it.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called budget-ci.
-
-config DVB_BUDGET_AV
-	tristate "Budget cards with analog video inputs"
-	depends on DVB_BUDGET_CORE && I2C
-	select VIDEO_SAA7146_VV
-	depends on VIDEO_DEV	# dependencies of VIDEO_SAA7146_VV
-	select DVB_PLL if !DVB_FE_CUSTOMISE
-	select DVB_STV0299 if !DVB_FE_CUSTOMISE
-	select DVB_TDA1004X if !DVB_FE_CUSTOMISE
-	select DVB_TDA10021 if !DVB_FE_CUSTOMISE
-	select DVB_TDA10023 if !DVB_FE_CUSTOMISE
-	select DVB_STB0899 if !DVB_FE_CUSTOMISE
-	select DVB_TDA8261 if !DVB_FE_CUSTOMISE
-	select DVB_TUA6100 if !DVB_FE_CUSTOMISE
-	help
-	  Support for simple SAA7146 based DVB cards
-	  (so called Budget- or Nova-PCI cards) without onboard
-	  MPEG2 decoder, but with one or more analog video inputs.
-
-	  Say Y if you own such a card and want to use it.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called budget-av.
-
-config DVB_BUDGET_PATCH
-	tristate "AV7110 cards with Budget Patch"
-	depends on DVB_BUDGET_CORE && I2C
-	depends on DVB_AV7110
-	select DVB_STV0299 if !DVB_FE_CUSTOMISE
-	select DVB_VES1X93 if !DVB_FE_CUSTOMISE
-	select DVB_TDA8083 if !DVB_FE_CUSTOMISE
-	help
-	  Support for Budget Patch (full TS) modification on
-	  SAA7146+AV7110 based cards (DVB-S cards). This
-	  driver doesn't use onboard MPEG2 decoder. The
-	  card is driven in Budget-only mode. Card is
-	  required to have loaded firmware to tune properly.
-	  Firmware can be loaded by insertion and removal of
-	  standard AV7110 driver prior to loading this
-	  driver.
-
-	  Say Y if you own such a card and want to use it.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called budget-patch.
diff --git a/drivers/media/dvb/ttpci/Makefile b/drivers/media/dvb/ttpci/Makefile
deleted file mode 100644
index f6e8693..0000000
--- a/drivers/media/dvb/ttpci/Makefile
+++ /dev/null
@@ -1,21 +0,0 @@
-#
-# Makefile for the kernel SAA7146 FULL TS DVB device driver
-# and the AV7110 DVB device driver
-#
-
-dvb-ttpci-objs := av7110_hw.o av7110_v4l.o av7110_av.o av7110_ca.o av7110.o av7110_ipack.o
-
-ifdef CONFIG_INPUT_EVDEV
-dvb-ttpci-objs += av7110_ir.o
-endif
-
-obj-$(CONFIG_TTPCI_EEPROM) += ttpci-eeprom.o
-obj-$(CONFIG_DVB_BUDGET_CORE) += budget-core.o
-obj-$(CONFIG_DVB_BUDGET) += budget.o
-obj-$(CONFIG_DVB_BUDGET_AV) += budget-av.o
-obj-$(CONFIG_DVB_BUDGET_CI) += budget-ci.o
-obj-$(CONFIG_DVB_BUDGET_PATCH) += budget-patch.o
-obj-$(CONFIG_DVB_AV7110) += dvb-ttpci.o
-
-ccflags-y += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
-ccflags-y += -Idrivers/media/common/tuners
diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c
deleted file mode 100644
index 4bd8bd5..0000000
--- a/drivers/media/dvb/ttpci/av7110.c
+++ /dev/null
@@ -1,2939 +0,0 @@
-/*
- * driver for the SAA7146 based AV110 cards (like the Fujitsu-Siemens DVB)
- * av7110.c: initialization and demux stuff
- *
- * Copyright (C) 1999-2002 Ralph  Metzler
- *                       & Marcus Metzler for convergence integrated media GmbH
- *
- * originally based on code by:
- * Copyright (C) 1998,1999 Christian Theiss <mistert@rz.fh-augsburg.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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- *
- *
- * the project's page is at http://www.linuxtv.org/ 
- */
-
-
-#include <linux/module.h>
-#include <linux/kmod.h>
-#include <linux/delay.h>
-#include <linux/fs.h>
-#include <linux/timer.h>
-#include <linux/poll.h>
-
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/interrupt.h>
-#include <linux/string.h>
-#include <linux/pci.h>
-#include <linux/vmalloc.h>
-#include <linux/firmware.h>
-#include <linux/crc32.h>
-#include <linux/i2c.h>
-#include <linux/kthread.h>
-#include <linux/slab.h>
-#include <asm/unaligned.h>
-#include <asm/byteorder.h>
-
-
-#include <linux/dvb/frontend.h>
-
-#include "dvb_frontend.h"
-
-#include "ttpci-eeprom.h"
-#include "av7110.h"
-#include "av7110_hw.h"
-#include "av7110_av.h"
-#include "av7110_ca.h"
-#include "av7110_ipack.h"
-
-#include "bsbe1.h"
-#include "lnbp21.h"
-#include "bsru6.h"
-
-#define TS_WIDTH  376
-#define TS_HEIGHT 512
-#define TS_BUFLEN (TS_WIDTH*TS_HEIGHT)
-#define TS_MAX_PACKETS (TS_BUFLEN/TS_SIZE)
-
-
-int av7110_debug;
-
-static int vidmode = CVBS_RGB_OUT;
-static int pids_off;
-static int adac = DVB_ADAC_TI;
-static int hw_sections;
-static int rgb_on;
-static int volume = 255;
-static int budgetpatch;
-static int wss_cfg_4_3 = 0x4008;
-static int wss_cfg_16_9 = 0x0007;
-static int tv_standard;
-static int full_ts;
-
-module_param_named(debug, av7110_debug, int, 0644);
-MODULE_PARM_DESC(debug, "debug level (bitmask, default 0)");
-module_param(vidmode, int, 0444);
-MODULE_PARM_DESC(vidmode,"analog video out: 0 off, 1 CVBS+RGB (default), 2 CVBS+YC, 3 YC");
-module_param(pids_off, int, 0444);
-MODULE_PARM_DESC(pids_off,"clear video/audio/PCR PID filters when demux is closed");
-module_param(adac, int, 0444);
-MODULE_PARM_DESC(adac,"audio DAC type: 0 TI, 1 CRYSTAL, 2 MSP (use if autodetection fails)");
-module_param(hw_sections, int, 0444);
-MODULE_PARM_DESC(hw_sections, "0 use software section filter, 1 use hardware");
-module_param(rgb_on, int, 0444);
-MODULE_PARM_DESC(rgb_on, "For Siemens DVB-C cards only: Enable RGB control"
-		" signal on SCART pin 16 to switch SCART video mode from CVBS to RGB");
-module_param(volume, int, 0444);
-MODULE_PARM_DESC(volume, "initial volume: default 255 (range 0-255)");
-module_param(budgetpatch, int, 0444);
-MODULE_PARM_DESC(budgetpatch, "use budget-patch hardware modification: default 0 (0 no, 1 autodetect, 2 always)");
-module_param(full_ts, int, 0444);
-MODULE_PARM_DESC(full_ts, "enable code for full-ts hardware modification: 0 disable (default), 1 enable");
-module_param(wss_cfg_4_3, int, 0444);
-MODULE_PARM_DESC(wss_cfg_4_3, "WSS 4:3 - default 0x4008 - bit 15: disable, 14: burst mode, 13..0: wss data");
-module_param(wss_cfg_16_9, int, 0444);
-MODULE_PARM_DESC(wss_cfg_16_9, "WSS 16:9 - default 0x0007 - bit 15: disable, 14: burst mode, 13..0: wss data");
-module_param(tv_standard, int, 0444);
-MODULE_PARM_DESC(tv_standard, "TV standard: 0 PAL (default), 1 NTSC");
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-static void restart_feeds(struct av7110 *av7110);
-static int budget_start_feed(struct dvb_demux_feed *feed);
-static int budget_stop_feed(struct dvb_demux_feed *feed);
-
-static int av7110_num;
-
-#define FE_FUNC_OVERRIDE(fe_func, av7110_copy, av7110_func) \
-{\
-	if (fe_func != NULL) { \
-		av7110_copy = fe_func; \
-		fe_func = av7110_func; \
-	} \
-}
-
-
-static void init_av7110_av(struct av7110 *av7110)
-{
-	int ret;
-	struct saa7146_dev *dev = av7110->dev;
-
-	/* set internal volume control to maximum */
-	av7110->adac_type = DVB_ADAC_TI;
-	ret = av7110_set_volume(av7110, av7110->mixer.volume_left, av7110->mixer.volume_right);
-	if (ret < 0)
-		printk("dvb-ttpci:cannot set internal volume to maximum:%d\n",ret);
-
-	ret = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetMonitorType,
-			    1, (u16) av7110->display_ar);
-	if (ret < 0)
-		printk("dvb-ttpci: unable to set aspect ratio\n");
-	ret = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetPanScanType,
-			    1, av7110->display_panscan);
-	if (ret < 0)
-		printk("dvb-ttpci: unable to set pan scan\n");
-
-	ret = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig, 2, 2, wss_cfg_4_3);
-	if (ret < 0)
-		printk("dvb-ttpci: unable to configure 4:3 wss\n");
-	ret = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig, 2, 3, wss_cfg_16_9);
-	if (ret < 0)
-		printk("dvb-ttpci: unable to configure 16:9 wss\n");
-
-	ret = av7710_set_video_mode(av7110, vidmode);
-	if (ret < 0)
-		printk("dvb-ttpci:cannot set video mode:%d\n",ret);
-
-	/* handle different card types */
-	/* remaining inits according to card and frontend type */
-	av7110->analog_tuner_flags = 0;
-	av7110->current_input = 0;
-	if (dev->pci->subsystem_vendor == 0x13c2 && dev->pci->subsystem_device == 0x000a)
-		av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, ADSwitch, 1, 0); // SPDIF on
-	if (i2c_writereg(av7110, 0x20, 0x00, 0x00) == 1) {
-		printk ("dvb-ttpci: Crystal audio DAC @ card %d detected\n",
-			av7110->dvb_adapter.num);
-		av7110->adac_type = DVB_ADAC_CRYSTAL;
-		i2c_writereg(av7110, 0x20, 0x01, 0xd2);
-		i2c_writereg(av7110, 0x20, 0x02, 0x49);
-		i2c_writereg(av7110, 0x20, 0x03, 0x00);
-		i2c_writereg(av7110, 0x20, 0x04, 0x00);
-
-		/**
-		 * some special handling for the Siemens DVB-C cards...
-		 */
-	} else if (0 == av7110_init_analog_module(av7110)) {
-		/* done. */
-	}
-	else if (dev->pci->subsystem_vendor == 0x110a) {
-		printk("dvb-ttpci: DVB-C w/o analog module @ card %d detected\n",
-			av7110->dvb_adapter.num);
-		av7110->adac_type = DVB_ADAC_NONE;
-	}
-	else {
-		av7110->adac_type = adac;
-		printk("dvb-ttpci: adac type set to %d @ card %d\n",
-			av7110->adac_type, av7110->dvb_adapter.num);
-	}
-
-	if (av7110->adac_type == DVB_ADAC_NONE || av7110->adac_type == DVB_ADAC_MSP34x0) {
-		// switch DVB SCART on
-		ret = av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, MainSwitch, 1, 0);
-		if (ret < 0)
-			printk("dvb-ttpci:cannot switch on SCART(Main):%d\n",ret);
-		ret = av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, ADSwitch, 1, 1);
-		if (ret < 0)
-			printk("dvb-ttpci:cannot switch on SCART(AD):%d\n",ret);
-		if (rgb_on &&
-		    ((av7110->dev->pci->subsystem_vendor == 0x110a) ||
-		     (av7110->dev->pci->subsystem_vendor == 0x13c2)) &&
-		     (av7110->dev->pci->subsystem_device == 0x0000)) {
-			saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); // RGB on, SCART pin 16
-			//saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); // SCARTpin 8
-		}
-	}
-
-	if (dev->pci->subsystem_vendor == 0x13c2 && dev->pci->subsystem_device == 0x000e)
-		av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, SpdifSwitch, 1, 0); // SPDIF on
-
-	ret = av7110_set_volume(av7110, av7110->mixer.volume_left, av7110->mixer.volume_right);
-	if (ret < 0)
-		printk("dvb-ttpci:cannot set volume :%d\n",ret);
-}
-
-static void recover_arm(struct av7110 *av7110)
-{
-	dprintk(4, "%p\n",av7110);
-
-	av7110_bootarm(av7110);
-	msleep(100);
-
-	init_av7110_av(av7110);
-
-	/* card-specific recovery */
-	if (av7110->recover)
-		av7110->recover(av7110);
-
-	restart_feeds(av7110);
-
-#if defined(CONFIG_INPUT_EVDEV) || defined(CONFIG_INPUT_EVDEV_MODULE)
-	av7110_check_ir_config(av7110, true);
-#endif
-}
-
-static void av7110_arm_sync(struct av7110 *av7110)
-{
-	if (av7110->arm_thread)
-		kthread_stop(av7110->arm_thread);
-
-	av7110->arm_thread = NULL;
-}
-
-static int arm_thread(void *data)
-{
-	struct av7110 *av7110 = data;
-	u16 newloops = 0;
-	int timeout;
-
-	dprintk(4, "%p\n",av7110);
-
-	for (;;) {
-		timeout = wait_event_interruptible_timeout(av7110->arm_wait,
-			kthread_should_stop(), 5 * HZ);
-
-		if (-ERESTARTSYS == timeout || kthread_should_stop()) {
-			/* got signal or told to quit*/
-			break;
-		}
-
-		if (!av7110->arm_ready)
-			continue;
-
-#if defined(CONFIG_INPUT_EVDEV) || defined(CONFIG_INPUT_EVDEV_MODULE)
-		av7110_check_ir_config(av7110, false);
-#endif
-
-		if (mutex_lock_interruptible(&av7110->dcomlock))
-			break;
-		newloops = rdebi(av7110, DEBINOSWAP, STATUS_LOOPS, 0, 2);
-		mutex_unlock(&av7110->dcomlock);
-
-		if (newloops == av7110->arm_loops || av7110->arm_errors > 3) {
-			printk(KERN_ERR "dvb-ttpci: ARM crashed @ card %d\n",
-			       av7110->dvb_adapter.num);
-
-			recover_arm(av7110);
-
-			if (mutex_lock_interruptible(&av7110->dcomlock))
-				break;
-			newloops = rdebi(av7110, DEBINOSWAP, STATUS_LOOPS, 0, 2) - 1;
-			mutex_unlock(&av7110->dcomlock);
-		}
-		av7110->arm_loops = newloops;
-		av7110->arm_errors = 0;
-	}
-
-	return 0;
-}
-
-
-/****************************************************************************
- * IRQ handling
- ****************************************************************************/
-
-static int DvbDmxFilterCallback(u8 *buffer1, size_t buffer1_len,
-				u8 *buffer2, size_t buffer2_len,
-				struct dvb_demux_filter *dvbdmxfilter,
-				enum dmx_success success,
-				struct av7110 *av7110)
-{
-	if (!dvbdmxfilter->feed->demux->dmx.frontend)
-		return 0;
-	if (dvbdmxfilter->feed->demux->dmx.frontend->source == DMX_MEMORY_FE)
-		return 0;
-
-	switch (dvbdmxfilter->type) {
-	case DMX_TYPE_SEC:
-		if ((((buffer1[1] << 8) | buffer1[2]) & 0xfff) + 3 != buffer1_len)
-			return 0;
-		if (dvbdmxfilter->doneq) {
-			struct dmx_section_filter *filter = &dvbdmxfilter->filter;
-			int i;
-			u8 xor, neq = 0;
-
-			for (i = 0; i < DVB_DEMUX_MASK_MAX; i++) {
-				xor = filter->filter_value[i] ^ buffer1[i];
-				neq |= dvbdmxfilter->maskandnotmode[i] & xor;
-			}
-			if (!neq)
-				return 0;
-		}
-		return dvbdmxfilter->feed->cb.sec(buffer1, buffer1_len,
-						  buffer2, buffer2_len,
-						  &dvbdmxfilter->filter,
-						  DMX_OK);
-	case DMX_TYPE_TS:
-		if (!(dvbdmxfilter->feed->ts_type & TS_PACKET))
-			return 0;
-		if (dvbdmxfilter->feed->ts_type & TS_PAYLOAD_ONLY)
-			return dvbdmxfilter->feed->cb.ts(buffer1, buffer1_len,
-							 buffer2, buffer2_len,
-							 &dvbdmxfilter->feed->feed.ts,
-							 DMX_OK);
-		else
-			av7110_p2t_write(buffer1, buffer1_len,
-					 dvbdmxfilter->feed->pid,
-					 &av7110->p2t_filter[dvbdmxfilter->index]);
-	default:
-		return 0;
-	}
-}
-
-
-//#define DEBUG_TIMING
-static inline void print_time(char *s)
-{
-#ifdef DEBUG_TIMING
-	struct timeval tv;
-	do_gettimeofday(&tv);
-	printk("%s: %d.%d\n", s, (int)tv.tv_sec, (int)tv.tv_usec);
-#endif
-}
-
-#define DEBI_READ 0
-#define DEBI_WRITE 1
-static inline void start_debi_dma(struct av7110 *av7110, int dir,
-				  unsigned long addr, unsigned int len)
-{
-	dprintk(8, "%c %08lx %u\n", dir == DEBI_READ ? 'R' : 'W', addr, len);
-	if (saa7146_wait_for_debi_done(av7110->dev, 0)) {
-		printk(KERN_ERR "%s: saa7146_wait_for_debi_done timed out\n", __func__);
-		return;
-	}
-
-	SAA7146_ISR_CLEAR(av7110->dev, MASK_19); /* for good measure */
-	SAA7146_IER_ENABLE(av7110->dev, MASK_19);
-	if (len < 5)
-		len = 5; /* we want a real DEBI DMA */
-	if (dir == DEBI_WRITE)
-		iwdebi(av7110, DEBISWAB, addr, 0, (len + 3) & ~3);
-	else
-		irdebi(av7110, DEBISWAB, addr, 0, len);
-}
-
-static void debiirq(unsigned long cookie)
-{
-	struct av7110 *av7110 = (struct av7110 *)cookie;
-	int type = av7110->debitype;
-	int handle = (type >> 8) & 0x1f;
-	unsigned int xfer = 0;
-
-	print_time("debi");
-	dprintk(4, "type 0x%04x\n", type);
-
-	if (type == -1) {
-		printk("DEBI irq oops @ %ld, psr:0x%08x, ssr:0x%08x\n",
-		       jiffies, saa7146_read(av7110->dev, PSR),
-		       saa7146_read(av7110->dev, SSR));
-		goto debi_done;
-	}
-	av7110->debitype = -1;
-
-	switch (type & 0xff) {
-
-	case DATA_TS_RECORD:
-		dvb_dmx_swfilter_packets(&av7110->demux,
-					 (const u8 *) av7110->debi_virt,
-					 av7110->debilen / 188);
-		xfer = RX_BUFF;
-		break;
-
-	case DATA_PES_RECORD:
-		if (av7110->demux.recording)
-			av7110_record_cb(&av7110->p2t[handle],
-					 (u8 *) av7110->debi_virt,
-					 av7110->debilen);
-		xfer = RX_BUFF;
-		break;
-
-	case DATA_IPMPE:
-	case DATA_FSECTION:
-	case DATA_PIPING:
-		if (av7110->handle2filter[handle])
-			DvbDmxFilterCallback((u8 *)av7110->debi_virt,
-					     av7110->debilen, NULL, 0,
-					     av7110->handle2filter[handle],
-					     DMX_OK, av7110);
-		xfer = RX_BUFF;
-		break;
-
-	case DATA_CI_GET:
-	{
-		u8 *data = av7110->debi_virt;
-
-		if ((data[0] < 2) && data[2] == 0xff) {
-			int flags = 0;
-			if (data[5] > 0)
-				flags |= CA_CI_MODULE_PRESENT;
-			if (data[5] > 5)
-				flags |= CA_CI_MODULE_READY;
-			av7110->ci_slot[data[0]].flags = flags;
-		} else
-			ci_get_data(&av7110->ci_rbuffer,
-				    av7110->debi_virt,
-				    av7110->debilen);
-		xfer = RX_BUFF;
-		break;
-	}
-
-	case DATA_COMMON_INTERFACE:
-		CI_handle(av7110, (u8 *)av7110->debi_virt, av7110->debilen);
-#if 0
-	{
-		int i;
-
-		printk("av7110%d: ", av7110->num);
-		printk("%02x ", *(u8 *)av7110->debi_virt);
-		printk("%02x ", *(1+(u8 *)av7110->debi_virt));
-		for (i = 2; i < av7110->debilen; i++)
-			printk("%02x ", (*(i+(unsigned char *)av7110->debi_virt)));
-		for (i = 2; i < av7110->debilen; i++)
-			printk("%c", chtrans(*(i+(unsigned char *)av7110->debi_virt)));
-
-		printk("\n");
-	}
-#endif
-		xfer = RX_BUFF;
-		break;
-
-	case DATA_DEBUG_MESSAGE:
-		((s8*)av7110->debi_virt)[Reserved_SIZE - 1] = 0;
-		printk("%s\n", (s8 *) av7110->debi_virt);
-		xfer = RX_BUFF;
-		break;
-
-	case DATA_CI_PUT:
-		dprintk(4, "debi DATA_CI_PUT\n");
-	case DATA_MPEG_PLAY:
-		dprintk(4, "debi DATA_MPEG_PLAY\n");
-	case DATA_BMP_LOAD:
-		dprintk(4, "debi DATA_BMP_LOAD\n");
-		xfer = TX_BUFF;
-		break;
-	default:
-		break;
-	}
-debi_done:
-	spin_lock(&av7110->debilock);
-	if (xfer)
-		iwdebi(av7110, DEBINOSWAP, xfer, 0, 2);
-	ARM_ClearMailBox(av7110);
-	spin_unlock(&av7110->debilock);
-}
-
-/* irq from av7110 firmware writing the mailbox register in the DPRAM */
-static void gpioirq(unsigned long cookie)
-{
-	struct av7110 *av7110 = (struct av7110 *)cookie;
-	u32 rxbuf, txbuf;
-	int len;
-
-	if (av7110->debitype != -1)
-		/* we shouldn't get any irq while a debi xfer is running */
-		printk("dvb-ttpci: GPIO0 irq oops @ %ld, psr:0x%08x, ssr:0x%08x\n",
-		       jiffies, saa7146_read(av7110->dev, PSR),
-		       saa7146_read(av7110->dev, SSR));
-
-	if (saa7146_wait_for_debi_done(av7110->dev, 0)) {
-		printk(KERN_ERR "%s: saa7146_wait_for_debi_done timed out\n", __func__);
-		BUG(); /* maybe we should try resetting the debi? */
-	}
-
-	spin_lock(&av7110->debilock);
-	ARM_ClearIrq(av7110);
-
-	/* see what the av7110 wants */
-	av7110->debitype = irdebi(av7110, DEBINOSWAP, IRQ_STATE, 0, 2);
-	av7110->debilen  = irdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
-	rxbuf = irdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
-	txbuf = irdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
-	len = (av7110->debilen + 3) & ~3;
-
-	print_time("gpio");
-	dprintk(8, "GPIO0 irq 0x%04x %d\n", av7110->debitype, av7110->debilen);
-
-	switch (av7110->debitype & 0xff) {
-
-	case DATA_TS_PLAY:
-	case DATA_PES_PLAY:
-		break;
-
-	case DATA_MPEG_VIDEO_EVENT:
-	{
-		u32 h_ar;
-		struct video_event event;
-
-		av7110->video_size.w = irdebi(av7110, DEBINOSWAP, STATUS_MPEG_WIDTH, 0, 2);
-		h_ar = irdebi(av7110, DEBINOSWAP, STATUS_MPEG_HEIGHT_AR, 0, 2);
-
-		iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
-		iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
-
-		av7110->video_size.h = h_ar & 0xfff;
-
-		event.type = VIDEO_EVENT_SIZE_CHANGED;
-		event.u.size.w = av7110->video_size.w;
-		event.u.size.h = av7110->video_size.h;
-		switch ((h_ar >> 12) & 0xf)
-		{
-		case 3:
-			av7110->video_size.aspect_ratio = VIDEO_FORMAT_16_9;
-			event.u.size.aspect_ratio = VIDEO_FORMAT_16_9;
-			av7110->videostate.video_format = VIDEO_FORMAT_16_9;
-			break;
-		case 4:
-			av7110->video_size.aspect_ratio = VIDEO_FORMAT_221_1;
-			event.u.size.aspect_ratio = VIDEO_FORMAT_221_1;
-			av7110->videostate.video_format = VIDEO_FORMAT_221_1;
-			break;
-		default:
-			av7110->video_size.aspect_ratio = VIDEO_FORMAT_4_3;
-			event.u.size.aspect_ratio = VIDEO_FORMAT_4_3;
-			av7110->videostate.video_format = VIDEO_FORMAT_4_3;
-		}
-
-		dprintk(8, "GPIO0 irq: DATA_MPEG_VIDEO_EVENT: w/h/ar = %u/%u/%u\n",
-			av7110->video_size.w, av7110->video_size.h,
-			av7110->video_size.aspect_ratio);
-
-		dvb_video_add_event(av7110, &event);
-		break;
-	}
-
-	case DATA_CI_PUT:
-	{
-		int avail;
-		struct dvb_ringbuffer *cibuf = &av7110->ci_wbuffer;
-
-		avail = dvb_ringbuffer_avail(cibuf);
-		if (avail <= 2) {
-			iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
-			iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
-			iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
-			break;
-		}
-		len = DVB_RINGBUFFER_PEEK(cibuf, 0) << 8;
-		len |= DVB_RINGBUFFER_PEEK(cibuf, 1);
-		if (avail < len + 2) {
-			iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
-			iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
-			iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
-			break;
-		}
-		DVB_RINGBUFFER_SKIP(cibuf, 2);
-
-		dvb_ringbuffer_read(cibuf, av7110->debi_virt, len);
-
-		iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2);
-		iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2);
-		dprintk(8, "DMA: CI\n");
-		start_debi_dma(av7110, DEBI_WRITE, DPRAM_BASE + txbuf, len);
-		spin_unlock(&av7110->debilock);
-		wake_up(&cibuf->queue);
-		return;
-	}
-
-	case DATA_MPEG_PLAY:
-		if (!av7110->playing) {
-			iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
-			iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
-			iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
-			break;
-		}
-		len = 0;
-		if (av7110->debitype & 0x100) {
-			spin_lock(&av7110->aout.lock);
-			len = av7110_pes_play(av7110->debi_virt, &av7110->aout, 2048);
-			spin_unlock(&av7110->aout.lock);
-		}
-		if (len <= 0 && (av7110->debitype & 0x200)
-		    &&av7110->videostate.play_state != VIDEO_FREEZED) {
-			spin_lock(&av7110->avout.lock);
-			len = av7110_pes_play(av7110->debi_virt, &av7110->avout, 2048);
-			spin_unlock(&av7110->avout.lock);
-		}
-		if (len <= 0) {
-			iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
-			iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
-			iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
-			break;
-		}
-		dprintk(8, "GPIO0 PES_PLAY len=%04x\n", len);
-		iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2);
-		iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2);
-		dprintk(8, "DMA: MPEG_PLAY\n");
-		start_debi_dma(av7110, DEBI_WRITE, DPRAM_BASE + txbuf, len);
-		spin_unlock(&av7110->debilock);
-		return;
-
-	case DATA_BMP_LOAD:
-		len = av7110->debilen;
-		dprintk(8, "gpio DATA_BMP_LOAD len %d\n", len);
-		if (!len) {
-			av7110->bmp_state = BMP_LOADED;
-			iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
-			iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
-			iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
-			wake_up(&av7110->bmpq);
-			dprintk(8, "gpio DATA_BMP_LOAD done\n");
-			break;
-		}
-		if (len > av7110->bmplen)
-			len = av7110->bmplen;
-		if (len > 2 * 1024)
-			len = 2 * 1024;
-		iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2);
-		iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2);
-		memcpy(av7110->debi_virt, av7110->bmpbuf+av7110->bmpp, len);
-		av7110->bmpp += len;
-		av7110->bmplen -= len;
-		dprintk(8, "gpio DATA_BMP_LOAD DMA len %d\n", len);
-		start_debi_dma(av7110, DEBI_WRITE, DPRAM_BASE+txbuf, len);
-		spin_unlock(&av7110->debilock);
-		return;
-
-	case DATA_CI_GET:
-	case DATA_COMMON_INTERFACE:
-	case DATA_FSECTION:
-	case DATA_IPMPE:
-	case DATA_PIPING:
-		if (!len || len > 4 * 1024) {
-			iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
-			break;
-		}
-		/* fall through */
-
-	case DATA_TS_RECORD:
-	case DATA_PES_RECORD:
-		dprintk(8, "DMA: TS_REC etc.\n");
-		start_debi_dma(av7110, DEBI_READ, DPRAM_BASE+rxbuf, len);
-		spin_unlock(&av7110->debilock);
-		return;
-
-	case DATA_DEBUG_MESSAGE:
-		if (!len || len > 0xff) {
-			iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
-			break;
-		}
-		start_debi_dma(av7110, DEBI_READ, Reserved, len);
-		spin_unlock(&av7110->debilock);
-		return;
-
-	case DATA_IRCOMMAND:
-		if (av7110->ir.ir_handler)
-			av7110->ir.ir_handler(av7110,
-				swahw32(irdebi(av7110, DEBINOSWAP, Reserved, 0, 4)));
-		iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2);
-		break;
-
-	default:
-		printk("dvb-ttpci: gpioirq unknown type=%d len=%d\n",
-		       av7110->debitype, av7110->debilen);
-		break;
-	}
-	av7110->debitype = -1;
-	ARM_ClearMailBox(av7110);
-	spin_unlock(&av7110->debilock);
-}
-
-
-#ifdef CONFIG_DVB_AV7110_OSD
-static int dvb_osd_ioctl(struct file *file,
-			 unsigned int cmd, void *parg)
-{
-	struct dvb_device *dvbdev = file->private_data;
-	struct av7110 *av7110 = dvbdev->priv;
-
-	dprintk(4, "%p\n", av7110);
-
-	if (cmd == OSD_SEND_CMD)
-		return av7110_osd_cmd(av7110, (osd_cmd_t *) parg);
-	if (cmd == OSD_GET_CAPABILITY)
-		return av7110_osd_capability(av7110, (osd_cap_t *) parg);
-
-	return -EINVAL;
-}
-
-
-static const struct file_operations dvb_osd_fops = {
-	.owner		= THIS_MODULE,
-	.unlocked_ioctl	= dvb_generic_ioctl,
-	.open		= dvb_generic_open,
-	.release	= dvb_generic_release,
-	.llseek		= noop_llseek,
-};
-
-static struct dvb_device dvbdev_osd = {
-	.priv		= NULL,
-	.users		= 1,
-	.writers	= 1,
-	.fops		= &dvb_osd_fops,
-	.kernel_ioctl	= dvb_osd_ioctl,
-};
-#endif /* CONFIG_DVB_AV7110_OSD */
-
-
-static inline int SetPIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
-			  u16 subpid, u16 pcrpid)
-{
-	u16 aflags = 0;
-
-	dprintk(4, "%p\n", av7110);
-
-	if (vpid == 0x1fff || apid == 0x1fff ||
-	    ttpid == 0x1fff || subpid == 0x1fff || pcrpid == 0x1fff) {
-		vpid = apid = ttpid = subpid = pcrpid = 0;
-		av7110->pids[DMX_PES_VIDEO] = 0;
-		av7110->pids[DMX_PES_AUDIO] = 0;
-		av7110->pids[DMX_PES_TELETEXT] = 0;
-		av7110->pids[DMX_PES_PCR] = 0;
-	}
-
-	if (av7110->audiostate.bypass_mode)
-		aflags |= 0x8000;
-
-	return av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, MultiPID, 6,
-			     pcrpid, vpid, apid, ttpid, subpid, aflags);
-}
-
-int ChangePIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
-		u16 subpid, u16 pcrpid)
-{
-	int ret = 0;
-	dprintk(4, "%p\n", av7110);
-
-	if (mutex_lock_interruptible(&av7110->pid_mutex))
-		return -ERESTARTSYS;
-
-	if (!(vpid & 0x8000))
-		av7110->pids[DMX_PES_VIDEO] = vpid;
-	if (!(apid & 0x8000))
-		av7110->pids[DMX_PES_AUDIO] = apid;
-	if (!(ttpid & 0x8000))
-		av7110->pids[DMX_PES_TELETEXT] = ttpid;
-	if (!(pcrpid & 0x8000))
-		av7110->pids[DMX_PES_PCR] = pcrpid;
-
-	av7110->pids[DMX_PES_SUBTITLE] = 0;
-
-	if (av7110->fe_synced) {
-		pcrpid = av7110->pids[DMX_PES_PCR];
-		ret = SetPIDs(av7110, vpid, apid, ttpid, subpid, pcrpid);
-	}
-
-	mutex_unlock(&av7110->pid_mutex);
-	return ret;
-}
-
-
-/******************************************************************************
- * hardware filter functions
- ******************************************************************************/
-
-static int StartHWFilter(struct dvb_demux_filter *dvbdmxfilter)
-{
-	struct dvb_demux_feed *dvbdmxfeed = dvbdmxfilter->feed;
-	struct av7110 *av7110 = dvbdmxfeed->demux->priv;
-	u16 buf[20];
-	int ret, i;
-	u16 handle;
-//	u16 mode = 0x0320;
-	u16 mode = 0xb96a;
-
-	dprintk(4, "%p\n", av7110);
-
-	if (av7110->full_ts)
-		return 0;
-
-	if (dvbdmxfilter->type == DMX_TYPE_SEC) {
-		if (hw_sections) {
-			buf[4] = (dvbdmxfilter->filter.filter_value[0] << 8) |
-				dvbdmxfilter->maskandmode[0];
-			for (i = 3; i < 18; i++)
-				buf[i + 4 - 2] =
-					(dvbdmxfilter->filter.filter_value[i] << 8) |
-					dvbdmxfilter->maskandmode[i];
-			mode = 4;
-		}
-	} else if ((dvbdmxfeed->ts_type & TS_PACKET) &&
-		   !(dvbdmxfeed->ts_type & TS_PAYLOAD_ONLY)) {
-		av7110_p2t_init(&av7110->p2t_filter[dvbdmxfilter->index], dvbdmxfeed);
-	}
-
-	buf[0] = (COMTYPE_PID_FILTER << 8) + AddPIDFilter;
-	buf[1] = 16;
-	buf[2] = dvbdmxfeed->pid;
-	buf[3] = mode;
-
-	ret = av7110_fw_request(av7110, buf, 20, &handle, 1);
-	if (ret != 0 || handle >= 32) {
-		printk("dvb-ttpci: %s error  buf %04x %04x %04x %04x  "
-				"ret %d  handle %04x\n",
-				__func__, buf[0], buf[1], buf[2], buf[3],
-				ret, handle);
-		dvbdmxfilter->hw_handle = 0xffff;
-		if (!ret)
-			ret = -1;
-		return ret;
-	}
-
-	av7110->handle2filter[handle] = dvbdmxfilter;
-	dvbdmxfilter->hw_handle = handle;
-
-	return ret;
-}
-
-static int StopHWFilter(struct dvb_demux_filter *dvbdmxfilter)
-{
-	struct av7110 *av7110 = dvbdmxfilter->feed->demux->priv;
-	u16 buf[3];
-	u16 answ[2];
-	int ret;
-	u16 handle;
-
-	dprintk(4, "%p\n", av7110);
-
-	if (av7110->full_ts)
-		return 0;
-
-	handle = dvbdmxfilter->hw_handle;
-	if (handle >= 32) {
-		printk("%s tried to stop invalid filter %04x, filter type = %x\n",
-				__func__, handle, dvbdmxfilter->type);
-		return -EINVAL;
-	}
-
-	av7110->handle2filter[handle] = NULL;
-
-	buf[0] = (COMTYPE_PID_FILTER << 8) + DelPIDFilter;
-	buf[1] = 1;
-	buf[2] = handle;
-	ret = av7110_fw_request(av7110, buf, 3, answ, 2);
-	if (ret != 0 || answ[1] != handle) {
-		printk("dvb-ttpci: %s error  cmd %04x %04x %04x  ret %x  "
-				"resp %04x %04x  pid %d\n",
-				__func__, buf[0], buf[1], buf[2], ret,
-				answ[0], answ[1], dvbdmxfilter->feed->pid);
-		if (!ret)
-			ret = -1;
-	}
-	return ret;
-}
-
-
-static int dvb_feed_start_pid(struct dvb_demux_feed *dvbdmxfeed)
-{
-	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
-	struct av7110 *av7110 = dvbdmx->priv;
-	u16 *pid = dvbdmx->pids, npids[5];
-	int i;
-	int ret = 0;
-
-	dprintk(4, "%p\n", av7110);
-
-	npids[0] = npids[1] = npids[2] = npids[3] = npids[4] = 0xffff;
-	i = dvbdmxfeed->pes_type;
-	npids[i] = (pid[i]&0x8000) ? 0 : pid[i];
-	if ((i == 2) && npids[i] && (dvbdmxfeed->ts_type & TS_PACKET)) {
-		npids[i] = 0;
-		ret = ChangePIDs(av7110, npids[1], npids[0], npids[2], npids[3], npids[4]);
-		if (!ret)
-			ret = StartHWFilter(dvbdmxfeed->filter);
-		return ret;
-	}
-	if (dvbdmxfeed->pes_type <= 2 || dvbdmxfeed->pes_type == 4) {
-		ret = ChangePIDs(av7110, npids[1], npids[0], npids[2], npids[3], npids[4]);
-		if (ret)
-			return ret;
-	}
-
-	if (dvbdmxfeed->pes_type < 2 && npids[0])
-		if (av7110->fe_synced)
-		{
-			ret = av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, Scan, 0);
-			if (ret)
-				return ret;
-		}
-
-	if ((dvbdmxfeed->ts_type & TS_PACKET) && !av7110->full_ts) {
-		if (dvbdmxfeed->pes_type == 0 && !(dvbdmx->pids[0] & 0x8000))
-			ret = av7110_av_start_record(av7110, RP_AUDIO, dvbdmxfeed);
-		if (dvbdmxfeed->pes_type == 1 && !(dvbdmx->pids[1] & 0x8000))
-			ret = av7110_av_start_record(av7110, RP_VIDEO, dvbdmxfeed);
-	}
-	return ret;
-}
-
-static int dvb_feed_stop_pid(struct dvb_demux_feed *dvbdmxfeed)
-{
-	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
-	struct av7110 *av7110 = dvbdmx->priv;
-	u16 *pid = dvbdmx->pids, npids[5];
-	int i;
-
-	int ret = 0;
-
-	dprintk(4, "%p\n", av7110);
-
-	if (dvbdmxfeed->pes_type <= 1) {
-		ret = av7110_av_stop(av7110, dvbdmxfeed->pes_type ?  RP_VIDEO : RP_AUDIO);
-		if (ret)
-			return ret;
-		if (!av7110->rec_mode)
-			dvbdmx->recording = 0;
-		if (!av7110->playing)
-			dvbdmx->playing = 0;
-	}
-	npids[0] = npids[1] = npids[2] = npids[3] = npids[4] = 0xffff;
-	i = dvbdmxfeed->pes_type;
-	switch (i) {
-	case 2: //teletext
-		if (dvbdmxfeed->ts_type & TS_PACKET)
-			ret = StopHWFilter(dvbdmxfeed->filter);
-		npids[2] = 0;
-		break;
-	case 0:
-	case 1:
-	case 4:
-		if (!pids_off)
-			return 0;
-		npids[i] = (pid[i]&0x8000) ? 0 : pid[i];
-		break;
-	}
-	if (!ret)
-		ret = ChangePIDs(av7110, npids[1], npids[0], npids[2], npids[3], npids[4]);
-	return ret;
-}
-
-static int av7110_start_feed(struct dvb_demux_feed *feed)
-{
-	struct dvb_demux *demux = feed->demux;
-	struct av7110 *av7110 = demux->priv;
-	int ret = 0;
-
-	dprintk(4, "%p\n", av7110);
-
-	if (!demux->dmx.frontend)
-		return -EINVAL;
-
-	if (!av7110->full_ts && feed->pid > 0x1fff)
-		return -EINVAL;
-
-	if (feed->type == DMX_TYPE_TS) {
-		if ((feed->ts_type & TS_DECODER) &&
-		    (feed->pes_type <= DMX_TS_PES_PCR)) {
-			switch (demux->dmx.frontend->source) {
-			case DMX_MEMORY_FE:
-				if (feed->ts_type & TS_DECODER)
-				       if (feed->pes_type < 2 &&
-					   !(demux->pids[0] & 0x8000) &&
-					   !(demux->pids[1] & 0x8000)) {
-					       dvb_ringbuffer_flush_spinlock_wakeup(&av7110->avout);
-					       dvb_ringbuffer_flush_spinlock_wakeup(&av7110->aout);
-					       ret = av7110_av_start_play(av7110,RP_AV);
-					       if (!ret)
-						       demux->playing = 1;
-					}
-				break;
-			default:
-				ret = dvb_feed_start_pid(feed);
-				break;
-			}
-		} else if ((feed->ts_type & TS_PACKET) &&
-			   (demux->dmx.frontend->source != DMX_MEMORY_FE)) {
-			ret = StartHWFilter(feed->filter);
-		}
-	}
-
-	if (av7110->full_ts) {
-		budget_start_feed(feed);
-		return ret;
-	}
-
-	if (feed->type == DMX_TYPE_SEC) {
-		int i;
-
-		for (i = 0; i < demux->filternum; i++) {
-			if (demux->filter[i].state != DMX_STATE_READY)
-				continue;
-			if (demux->filter[i].type != DMX_TYPE_SEC)
-				continue;
-			if (demux->filter[i].filter.parent != &feed->feed.sec)
-				continue;
-			demux->filter[i].state = DMX_STATE_GO;
-			if (demux->dmx.frontend->source != DMX_MEMORY_FE) {
-				ret = StartHWFilter(&demux->filter[i]);
-				if (ret)
-					break;
-			}
-		}
-	}
-
-	return ret;
-}
-
-
-static int av7110_stop_feed(struct dvb_demux_feed *feed)
-{
-	struct dvb_demux *demux = feed->demux;
-	struct av7110 *av7110 = demux->priv;
-	int i, rc, ret = 0;
-	dprintk(4, "%p\n", av7110);
-
-	if (feed->type == DMX_TYPE_TS) {
-		if (feed->ts_type & TS_DECODER) {
-			if (feed->pes_type >= DMX_TS_PES_OTHER ||
-			    !demux->pesfilter[feed->pes_type])
-				return -EINVAL;
-			demux->pids[feed->pes_type] |= 0x8000;
-			demux->pesfilter[feed->pes_type] = NULL;
-		}
-		if (feed->ts_type & TS_DECODER &&
-		    feed->pes_type < DMX_TS_PES_OTHER) {
-			ret = dvb_feed_stop_pid(feed);
-		} else
-			if ((feed->ts_type & TS_PACKET) &&
-			    (demux->dmx.frontend->source != DMX_MEMORY_FE))
-				ret = StopHWFilter(feed->filter);
-	}
-
-	if (av7110->full_ts) {
-		budget_stop_feed(feed);
-		return ret;
-	}
-
-	if (feed->type == DMX_TYPE_SEC) {
-		for (i = 0; i<demux->filternum; i++) {
-			if (demux->filter[i].state == DMX_STATE_GO &&
-			    demux->filter[i].filter.parent == &feed->feed.sec) {
-				demux->filter[i].state = DMX_STATE_READY;
-				if (demux->dmx.frontend->source != DMX_MEMORY_FE) {
-					rc = StopHWFilter(&demux->filter[i]);
-					if (!ret)
-						ret = rc;
-					/* keep going, stop as many filters as possible */
-				}
-			}
-		}
-	}
-
-	return ret;
-}
-
-
-static void restart_feeds(struct av7110 *av7110)
-{
-	struct dvb_demux *dvbdmx = &av7110->demux;
-	struct dvb_demux_feed *feed;
-	int mode;
-	int feeding;
-	int i, j;
-
-	dprintk(4, "%p\n", av7110);
-
-	mode = av7110->playing;
-	av7110->playing = 0;
-	av7110->rec_mode = 0;
-
-	feeding = av7110->feeding1; /* full_ts mod */
-
-	for (i = 0; i < dvbdmx->feednum; i++) {
-		feed = &dvbdmx->feed[i];
-		if (feed->state == DMX_STATE_GO) {
-			if (feed->type == DMX_TYPE_SEC) {
-				for (j = 0; j < dvbdmx->filternum; j++) {
-					if (dvbdmx->filter[j].type != DMX_TYPE_SEC)
-						continue;
-					if (dvbdmx->filter[j].filter.parent != &feed->feed.sec)
-						continue;
-					if (dvbdmx->filter[j].state == DMX_STATE_GO)
-						dvbdmx->filter[j].state = DMX_STATE_READY;
-				}
-			}
-			av7110_start_feed(feed);
-		}
-	}
-
-	av7110->feeding1 = feeding; /* full_ts mod */
-
-	if (mode)
-		av7110_av_start_play(av7110, mode);
-}
-
-static int dvb_get_stc(struct dmx_demux *demux, unsigned int num,
-		       uint64_t *stc, unsigned int *base)
-{
-	int ret;
-	u16 fwstc[4];
-	u16 tag = ((COMTYPE_REQUEST << 8) + ReqSTC);
-	struct dvb_demux *dvbdemux;
-	struct av7110 *av7110;
-
-	/* pointer casting paranoia... */
-	BUG_ON(!demux);
-	dvbdemux = demux->priv;
-	BUG_ON(!dvbdemux);
-	av7110 = dvbdemux->priv;
-
-	dprintk(4, "%p\n", av7110);
-
-	if (num != 0)
-		return -EINVAL;
-
-	ret = av7110_fw_request(av7110, &tag, 0, fwstc, 4);
-	if (ret) {
-		printk(KERN_ERR "%s: av7110_fw_request error\n", __func__);
-		return ret;
-	}
-	dprintk(2, "fwstc = %04hx %04hx %04hx %04hx\n",
-		fwstc[0], fwstc[1], fwstc[2], fwstc[3]);
-
-	*stc =	(((uint64_t) ((fwstc[3] & 0x8000) >> 15)) << 32) |
-		(((uint64_t)  fwstc[1]) << 16) | ((uint64_t) fwstc[0]);
-	*base = 1;
-
-	dprintk(4, "stc = %lu\n", (unsigned long)*stc);
-
-	return 0;
-}
-
-
-/******************************************************************************
- * SEC device file operations
- ******************************************************************************/
-
-
-static int av7110_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
-{
-	struct av7110* av7110 = fe->dvb->priv;
-
-	switch (tone) {
-	case SEC_TONE_ON:
-		return Set22K(av7110, 1);
-
-	case SEC_TONE_OFF:
-		return Set22K(av7110, 0);
-
-	default:
-		return -EINVAL;
-	}
-}
-
-static int av7110_diseqc_send_master_cmd(struct dvb_frontend* fe,
-					 struct dvb_diseqc_master_cmd* cmd)
-{
-	struct av7110* av7110 = fe->dvb->priv;
-
-	return av7110_diseqc_send(av7110, cmd->msg_len, cmd->msg, -1);
-}
-
-static int av7110_diseqc_send_burst(struct dvb_frontend* fe,
-				    fe_sec_mini_cmd_t minicmd)
-{
-	struct av7110* av7110 = fe->dvb->priv;
-
-	return av7110_diseqc_send(av7110, 0, NULL, minicmd);
-}
-
-/* simplified code from budget-core.c */
-static int stop_ts_capture(struct av7110 *budget)
-{
-	dprintk(2, "budget: %p\n", budget);
-
-	if (--budget->feeding1)
-		return budget->feeding1;
-	saa7146_write(budget->dev, MC1, MASK_20);	/* DMA3 off */
-	SAA7146_IER_DISABLE(budget->dev, MASK_10);
-	SAA7146_ISR_CLEAR(budget->dev, MASK_10);
-	return 0;
-}
-
-static int start_ts_capture(struct av7110 *budget)
-{
-	dprintk(2, "budget: %p\n", budget);
-
-	if (budget->feeding1)
-		return ++budget->feeding1;
-	memset(budget->grabbing, 0x00, TS_BUFLEN);
-	budget->ttbp = 0;
-	SAA7146_ISR_CLEAR(budget->dev, MASK_10);  /* VPE */
-	SAA7146_IER_ENABLE(budget->dev, MASK_10); /* VPE */
-	saa7146_write(budget->dev, MC1, (MASK_04 | MASK_20)); /* DMA3 on */
-	return ++budget->feeding1;
-}
-
-static int budget_start_feed(struct dvb_demux_feed *feed)
-{
-	struct dvb_demux *demux = feed->demux;
-	struct av7110 *budget = demux->priv;
-	int status;
-
-	dprintk(2, "av7110: %p\n", budget);
-
-	spin_lock(&budget->feedlock1);
-	feed->pusi_seen = 0; /* have a clean section start */
-	status = start_ts_capture(budget);
-	spin_unlock(&budget->feedlock1);
-	return status;
-}
-
-static int budget_stop_feed(struct dvb_demux_feed *feed)
-{
-	struct dvb_demux *demux = feed->demux;
-	struct av7110 *budget = demux->priv;
-	int status;
-
-	dprintk(2, "budget: %p\n", budget);
-
-	spin_lock(&budget->feedlock1);
-	status = stop_ts_capture(budget);
-	spin_unlock(&budget->feedlock1);
-	return status;
-}
-
-static void vpeirq(unsigned long cookie)
-{
-	struct av7110 *budget = (struct av7110 *)cookie;
-	u8 *mem = (u8 *) (budget->grabbing);
-	u32 olddma = budget->ttbp;
-	u32 newdma = saa7146_read(budget->dev, PCI_VDP3);
-	struct dvb_demux *demux = budget->full_ts ? &budget->demux : &budget->demux1;
-
-	/* nearest lower position divisible by 188 */
-	newdma -= newdma % 188;
-
-	if (newdma >= TS_BUFLEN)
-		return;
-
-	budget->ttbp = newdma;
-
-	if (!budget->feeding1 || (newdma == olddma))
-		return;
-
-	/* Ensure streamed PCI data is synced to CPU */
-	pci_dma_sync_sg_for_cpu(budget->dev->pci, budget->pt.slist, budget->pt.nents, PCI_DMA_FROMDEVICE);
-
-#if 0
-	/* track rps1 activity */
-	printk("vpeirq: %02x Event Counter 1 0x%04x\n",
-	       mem[olddma],
-	       saa7146_read(budget->dev, EC1R) & 0x3fff);
-#endif
-
-	if (newdma > olddma)
-		/* no wraparound, dump olddma..newdma */
-		dvb_dmx_swfilter_packets(demux, mem + olddma, (newdma - olddma) / 188);
-	else {
-		/* wraparound, dump olddma..buflen and 0..newdma */
-		dvb_dmx_swfilter_packets(demux, mem + olddma, (TS_BUFLEN - olddma) / 188);
-		dvb_dmx_swfilter_packets(demux, mem, newdma / 188);
-	}
-}
-
-static int av7110_register(struct av7110 *av7110)
-{
-	int ret, i;
-	struct dvb_demux *dvbdemux = &av7110->demux;
-	struct dvb_demux *dvbdemux1 = &av7110->demux1;
-
-	dprintk(4, "%p\n", av7110);
-
-	if (av7110->registered)
-		return -1;
-
-	av7110->registered = 1;
-
-	dvbdemux->priv = (void *) av7110;
-
-	for (i = 0; i < 32; i++)
-		av7110->handle2filter[i] = NULL;
-
-	dvbdemux->filternum = (av7110->full_ts) ? 256 : 32;
-	dvbdemux->feednum = (av7110->full_ts) ? 256 : 32;
-	dvbdemux->start_feed = av7110_start_feed;
-	dvbdemux->stop_feed = av7110_stop_feed;
-	dvbdemux->write_to_decoder = av7110_write_to_decoder;
-	dvbdemux->dmx.capabilities = (DMX_TS_FILTERING | DMX_SECTION_FILTERING |
-				      DMX_MEMORY_BASED_FILTERING);
-
-	dvb_dmx_init(&av7110->demux);
-	av7110->demux.dmx.get_stc = dvb_get_stc;
-
-	av7110->dmxdev.filternum = (av7110->full_ts) ? 256 : 32;
-	av7110->dmxdev.demux = &dvbdemux->dmx;
-	av7110->dmxdev.capabilities = 0;
-
-	dvb_dmxdev_init(&av7110->dmxdev, &av7110->dvb_adapter);
-
-	av7110->hw_frontend.source = DMX_FRONTEND_0;
-
-	ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &av7110->hw_frontend);
-
-	if (ret < 0)
-		return ret;
-
-	av7110->mem_frontend.source = DMX_MEMORY_FE;
-
-	ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &av7110->mem_frontend);
-
-	if (ret < 0)
-		return ret;
-
-	ret = dvbdemux->dmx.connect_frontend(&dvbdemux->dmx,
-					     &av7110->hw_frontend);
-	if (ret < 0)
-		return ret;
-
-	av7110_av_register(av7110);
-	av7110_ca_register(av7110);
-
-#ifdef CONFIG_DVB_AV7110_OSD
-	dvb_register_device(&av7110->dvb_adapter, &av7110->osd_dev,
-			    &dvbdev_osd, av7110, DVB_DEVICE_OSD);
-#endif
-
-	dvb_net_init(&av7110->dvb_adapter, &av7110->dvb_net, &dvbdemux->dmx);
-
-	if (budgetpatch) {
-		/* initialize software demux1 without its own frontend
-		 * demux1 hardware is connected to frontend0 of demux0
-		 */
-		dvbdemux1->priv = (void *) av7110;
-
-		dvbdemux1->filternum = 256;
-		dvbdemux1->feednum = 256;
-		dvbdemux1->start_feed = budget_start_feed;
-		dvbdemux1->stop_feed = budget_stop_feed;
-		dvbdemux1->write_to_decoder = NULL;
-
-		dvbdemux1->dmx.capabilities = (DMX_TS_FILTERING | DMX_SECTION_FILTERING |
-					       DMX_MEMORY_BASED_FILTERING);
-
-		dvb_dmx_init(&av7110->demux1);
-
-		av7110->dmxdev1.filternum = 256;
-		av7110->dmxdev1.demux = &dvbdemux1->dmx;
-		av7110->dmxdev1.capabilities = 0;
-
-		dvb_dmxdev_init(&av7110->dmxdev1, &av7110->dvb_adapter);
-
-		dvb_net_init(&av7110->dvb_adapter, &av7110->dvb_net1, &dvbdemux1->dmx);
-		printk("dvb-ttpci: additional demux1 for budget-patch registered\n");
-	}
-	return 0;
-}
-
-
-static void dvb_unregister(struct av7110 *av7110)
-{
-	struct dvb_demux *dvbdemux = &av7110->demux;
-	struct dvb_demux *dvbdemux1 = &av7110->demux1;
-
-	dprintk(4, "%p\n", av7110);
-
-	if (!av7110->registered)
-		return;
-
-	if (budgetpatch) {
-		dvb_net_release(&av7110->dvb_net1);
-		dvbdemux->dmx.close(&dvbdemux1->dmx);
-		dvb_dmxdev_release(&av7110->dmxdev1);
-		dvb_dmx_release(&av7110->demux1);
-	}
-
-	dvb_net_release(&av7110->dvb_net);
-
-	dvbdemux->dmx.close(&dvbdemux->dmx);
-	dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &av7110->hw_frontend);
-	dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &av7110->mem_frontend);
-
-	dvb_dmxdev_release(&av7110->dmxdev);
-	dvb_dmx_release(&av7110->demux);
-
-	if (av7110->fe != NULL) {
-		dvb_unregister_frontend(av7110->fe);
-		dvb_frontend_detach(av7110->fe);
-	}
-	dvb_unregister_device(av7110->osd_dev);
-	av7110_av_unregister(av7110);
-	av7110_ca_unregister(av7110);
-}
-
-
-/****************************************************************************
- * I2C client commands
- ****************************************************************************/
-
-int i2c_writereg(struct av7110 *av7110, u8 id, u8 reg, u8 val)
-{
-	u8 msg[2] = { reg, val };
-	struct i2c_msg msgs;
-
-	msgs.flags = 0;
-	msgs.addr = id / 2;
-	msgs.len = 2;
-	msgs.buf = msg;
-	return i2c_transfer(&av7110->i2c_adap, &msgs, 1);
-}
-
-u8 i2c_readreg(struct av7110 *av7110, u8 id, u8 reg)
-{
-	u8 mm1[] = {0x00};
-	u8 mm2[] = {0x00};
-	struct i2c_msg msgs[2];
-
-	msgs[0].flags = 0;
-	msgs[1].flags = I2C_M_RD;
-	msgs[0].addr = msgs[1].addr = id / 2;
-	mm1[0] = reg;
-	msgs[0].len = 1; msgs[1].len = 1;
-	msgs[0].buf = mm1; msgs[1].buf = mm2;
-	i2c_transfer(&av7110->i2c_adap, msgs, 2);
-
-	return mm2[0];
-}
-
-/****************************************************************************
- * INITIALIZATION
- ****************************************************************************/
-
-
-static int check_firmware(struct av7110* av7110)
-{
-	u32 crc = 0, len = 0;
-	unsigned char *ptr;
-
-	/* check for firmware magic */
-	ptr = av7110->bin_fw;
-	if (ptr[0] != 'A' || ptr[1] != 'V' ||
-	    ptr[2] != 'F' || ptr[3] != 'W') {
-		printk("dvb-ttpci: this is not an av7110 firmware\n");
-		return -EINVAL;
-	}
-	ptr += 4;
-
-	/* check dpram file */
-	crc = get_unaligned_be32(ptr);
-	ptr += 4;
-	len = get_unaligned_be32(ptr);
-	ptr += 4;
-	if (len >= 512) {
-		printk("dvb-ttpci: dpram file is way too big.\n");
-		return -EINVAL;
-	}
-	if (crc != crc32_le(0, ptr, len)) {
-		printk("dvb-ttpci: crc32 of dpram file does not match.\n");
-		return -EINVAL;
-	}
-	av7110->bin_dpram = ptr;
-	av7110->size_dpram = len;
-	ptr += len;
-
-	/* check root file */
-	crc = get_unaligned_be32(ptr);
-	ptr += 4;
-	len = get_unaligned_be32(ptr);
-	ptr += 4;
-
-	if (len <= 200000 || len >= 300000 ||
-	    len > ((av7110->bin_fw + av7110->size_fw) - ptr)) {
-		printk("dvb-ttpci: root file has strange size (%d). aborting.\n", len);
-		return -EINVAL;
-	}
-	if( crc != crc32_le(0, ptr, len)) {
-		printk("dvb-ttpci: crc32 of root file does not match.\n");
-		return -EINVAL;
-	}
-	av7110->bin_root = ptr;
-	av7110->size_root = len;
-	return 0;
-}
-
-static void put_firmware(struct av7110* av7110)
-{
-	vfree(av7110->bin_fw);
-}
-
-static int get_firmware(struct av7110* av7110)
-{
-	int ret;
-	const struct firmware *fw;
-
-	/* request the av7110 firmware, this will block until someone uploads it */
-	ret = request_firmware(&fw, "dvb-ttpci-01.fw", &av7110->dev->pci->dev);
-	if (ret) {
-		if (ret == -ENOENT) {
-			printk(KERN_ERR "dvb-ttpci: could not load firmware,"
-			       " file not found: dvb-ttpci-01.fw\n");
-			printk(KERN_ERR "dvb-ttpci: usually this should be in "
-			       "/usr/lib/hotplug/firmware or /lib/firmware\n");
-			printk(KERN_ERR "dvb-ttpci: and can be downloaded from"
-			       " http://www.linuxtv.org/download/dvb/firmware/\n");
-		} else
-			printk(KERN_ERR "dvb-ttpci: cannot request firmware"
-			       " (error %i)\n", ret);
-		return -EINVAL;
-	}
-
-	if (fw->size <= 200000) {
-		printk("dvb-ttpci: this firmware is way too small.\n");
-		release_firmware(fw);
-		return -EINVAL;
-	}
-
-	/* check if the firmware is available */
-	av7110->bin_fw = vmalloc(fw->size);
-	if (NULL == av7110->bin_fw) {
-		dprintk(1, "out of memory\n");
-		release_firmware(fw);
-		return -ENOMEM;
-	}
-
-	memcpy(av7110->bin_fw, fw->data, fw->size);
-	av7110->size_fw = fw->size;
-	if ((ret = check_firmware(av7110)))
-		vfree(av7110->bin_fw);
-
-	release_firmware(fw);
-	return ret;
-}
-
-static int alps_bsrv2_tuner_set_params(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct av7110* av7110 = fe->dvb->priv;
-	u8 pwr = 0;
-	u8 buf[4];
-	struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
-	u32 div = (p->frequency + 479500) / 125;
-
-	if (p->frequency > 2000000)
-		pwr = 3;
-	else if (p->frequency > 1800000)
-		pwr = 2;
-	else if (p->frequency > 1600000)
-		pwr = 1;
-	else if (p->frequency > 1200000)
-		pwr = 0;
-	else if (p->frequency >= 1100000)
-		pwr = 1;
-	else
-		pwr = 2;
-
-	buf[0] = (div >> 8) & 0x7f;
-	buf[1] = div & 0xff;
-	buf[2] = ((div & 0x18000) >> 10) | 0x95;
-	buf[3] = (pwr << 6) | 0x30;
-
-	// NOTE: since we're using a prescaler of 2, we set the
-	// divisor frequency to 62.5kHz and divide by 125 above
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1)
-		return -EIO;
-	return 0;
-}
-
-static struct ves1x93_config alps_bsrv2_config = {
-	.demod_address = 0x08,
-	.xin = 90100000UL,
-	.invert_pwm = 0,
-};
-
-static int alps_tdbe2_tuner_set_params(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct av7110* av7110 = fe->dvb->priv;
-	u32 div;
-	u8 data[4];
-	struct i2c_msg msg = { .addr = 0x62, .flags = 0, .buf = data, .len = sizeof(data) };
-
-	div = (p->frequency + 35937500 + 31250) / 62500;
-
-	data[0] = (div >> 8) & 0x7f;
-	data[1] = div & 0xff;
-	data[2] = 0x85 | ((div >> 10) & 0x60);
-	data[3] = (p->frequency < 174000000 ? 0x88 : p->frequency < 470000000 ? 0x84 : 0x81);
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
-		return -EIO;
-	return 0;
-}
-
-static struct ves1820_config alps_tdbe2_config = {
-	.demod_address = 0x09,
-	.xin = 57840000UL,
-	.invert = 1,
-	.selagc = VES1820_SELAGC_SIGNAMPERR,
-};
-
-
-
-
-static int grundig_29504_451_tuner_set_params(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct av7110* av7110 = fe->dvb->priv;
-	u32 div;
-	u8 data[4];
-	struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
-
-	div = p->frequency / 125;
-	data[0] = (div >> 8) & 0x7f;
-	data[1] = div & 0xff;
-	data[2] = 0x8e;
-	data[3] = 0x00;
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
-		return -EIO;
-	return 0;
-}
-
-static struct tda8083_config grundig_29504_451_config = {
-	.demod_address = 0x68,
-};
-
-
-
-static int philips_cd1516_tuner_set_params(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct av7110* av7110 = fe->dvb->priv;
-	u32 div;
-	u32 f = p->frequency;
-	u8 data[4];
-	struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
-
-	div = (f + 36125000 + 31250) / 62500;
-
-	data[0] = (div >> 8) & 0x7f;
-	data[1] = div & 0xff;
-	data[2] = 0x8e;
-	data[3] = (f < 174000000 ? 0xa1 : f < 470000000 ? 0x92 : 0x34);
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
-		return -EIO;
-	return 0;
-}
-
-static struct ves1820_config philips_cd1516_config = {
-	.demod_address = 0x09,
-	.xin = 57840000UL,
-	.invert = 1,
-	.selagc = VES1820_SELAGC_SIGNAMPERR,
-};
-
-
-
-static int alps_tdlb7_tuner_set_params(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct av7110* av7110 = fe->dvb->priv;
-	u32 div, pwr;
-	u8 data[4];
-	struct i2c_msg msg = { .addr = 0x60, .flags = 0, .buf = data, .len = sizeof(data) };
-
-	div = (p->frequency + 36200000) / 166666;
-
-	if (p->frequency <= 782000000)
-		pwr = 1;
-	else
-		pwr = 2;
-
-	data[0] = (div >> 8) & 0x7f;
-	data[1] = div & 0xff;
-	data[2] = 0x85;
-	data[3] = pwr << 6;
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
-		return -EIO;
-	return 0;
-}
-
-static int alps_tdlb7_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name)
-{
-#if defined(CONFIG_DVB_SP8870) || defined(CONFIG_DVB_SP8870_MODULE)
-	struct av7110* av7110 = fe->dvb->priv;
-
-	return request_firmware(fw, name, &av7110->dev->pci->dev);
-#else
-	return -EINVAL;
-#endif
-}
-
-static struct sp8870_config alps_tdlb7_config = {
-
-	.demod_address = 0x71,
-	.request_firmware = alps_tdlb7_request_firmware,
-};
-
-
-static u8 nexusca_stv0297_inittab[] = {
-	0x80, 0x01,
-	0x80, 0x00,
-	0x81, 0x01,
-	0x81, 0x00,
-	0x00, 0x09,
-	0x01, 0x69,
-	0x03, 0x00,
-	0x04, 0x00,
-	0x07, 0x00,
-	0x08, 0x00,
-	0x20, 0x00,
-	0x21, 0x40,
-	0x22, 0x00,
-	0x23, 0x00,
-	0x24, 0x40,
-	0x25, 0x88,
-	0x30, 0xff,
-	0x31, 0x00,
-	0x32, 0xff,
-	0x33, 0x00,
-	0x34, 0x50,
-	0x35, 0x7f,
-	0x36, 0x00,
-	0x37, 0x20,
-	0x38, 0x00,
-	0x40, 0x1c,
-	0x41, 0xff,
-	0x42, 0x29,
-	0x43, 0x00,
-	0x44, 0xff,
-	0x45, 0x00,
-	0x46, 0x00,
-	0x49, 0x04,
-	0x4a, 0x00,
-	0x4b, 0x7b,
-	0x52, 0x30,
-	0x55, 0xae,
-	0x56, 0x47,
-	0x57, 0xe1,
-	0x58, 0x3a,
-	0x5a, 0x1e,
-	0x5b, 0x34,
-	0x60, 0x00,
-	0x63, 0x00,
-	0x64, 0x00,
-	0x65, 0x00,
-	0x66, 0x00,
-	0x67, 0x00,
-	0x68, 0x00,
-	0x69, 0x00,
-	0x6a, 0x02,
-	0x6b, 0x00,
-	0x70, 0xff,
-	0x71, 0x00,
-	0x72, 0x00,
-	0x73, 0x00,
-	0x74, 0x0c,
-	0x80, 0x00,
-	0x81, 0x00,
-	0x82, 0x00,
-	0x83, 0x00,
-	0x84, 0x04,
-	0x85, 0x80,
-	0x86, 0x24,
-	0x87, 0x78,
-	0x88, 0x10,
-	0x89, 0x00,
-	0x90, 0x01,
-	0x91, 0x01,
-	0xa0, 0x04,
-	0xa1, 0x00,
-	0xa2, 0x00,
-	0xb0, 0x91,
-	0xb1, 0x0b,
-	0xc0, 0x53,
-	0xc1, 0x70,
-	0xc2, 0x12,
-	0xd0, 0x00,
-	0xd1, 0x00,
-	0xd2, 0x00,
-	0xd3, 0x00,
-	0xd4, 0x00,
-	0xd5, 0x00,
-	0xde, 0x00,
-	0xdf, 0x00,
-	0x61, 0x49,
-	0x62, 0x0b,
-	0x53, 0x08,
-	0x59, 0x08,
-	0xff, 0xff,
-};
-
-static int nexusca_stv0297_tuner_set_params(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct av7110* av7110 = fe->dvb->priv;
-	u32 div;
-	u8 data[4];
-	struct i2c_msg msg = { .addr = 0x63, .flags = 0, .buf = data, .len = sizeof(data) };
-	struct i2c_msg readmsg = { .addr = 0x63, .flags = I2C_M_RD, .buf = data, .len = 1 };
-	int i;
-
-	div = (p->frequency + 36150000 + 31250) / 62500;
-
-	data[0] = (div >> 8) & 0x7f;
-	data[1] = div & 0xff;
-	data[2] = 0xce;
-
-	if (p->frequency < 45000000)
-		return -EINVAL;
-	else if (p->frequency < 137000000)
-		data[3] = 0x01;
-	else if (p->frequency < 403000000)
-		data[3] = 0x02;
-	else if (p->frequency < 860000000)
-		data[3] = 0x04;
-	else
-		return -EINVAL;
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1) {
-		printk("nexusca: pll transfer failed!\n");
-		return -EIO;
-	}
-
-	// wait for PLL lock
-	for(i = 0; i < 20; i++) {
-		if (fe->ops.i2c_gate_ctrl)
-			fe->ops.i2c_gate_ctrl(fe, 1);
-		if (i2c_transfer(&av7110->i2c_adap, &readmsg, 1) == 1)
-			if (data[0] & 0x40) break;
-		msleep(10);
-	}
-
-	return 0;
-}
-
-static struct stv0297_config nexusca_stv0297_config = {
-
-	.demod_address = 0x1C,
-	.inittab = nexusca_stv0297_inittab,
-	.invert = 1,
-	.stop_during_read = 1,
-};
-
-
-
-static int grundig_29504_401_tuner_set_params(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct av7110* av7110 = fe->dvb->priv;
-	u32 div;
-	u8 cfg, cpump, band_select;
-	u8 data[4];
-	struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
-
-	div = (36125000 + p->frequency) / 166666;
-
-	cfg = 0x88;
-
-	if (p->frequency < 175000000)
-		cpump = 2;
-	else if (p->frequency < 390000000)
-		cpump = 1;
-	else if (p->frequency < 470000000)
-		cpump = 2;
-	else if (p->frequency < 750000000)
-		cpump = 1;
-	else
-		cpump = 3;
-
-	if (p->frequency < 175000000)
-		band_select = 0x0e;
-	else if (p->frequency < 470000000)
-		band_select = 0x05;
-	else
-		band_select = 0x03;
-
-	data[0] = (div >> 8) & 0x7f;
-	data[1] = div & 0xff;
-	data[2] = ((div >> 10) & 0x60) | cfg;
-	data[3] = (cpump << 6) | band_select;
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1) return -EIO;
-	return 0;
-}
-
-static struct l64781_config grundig_29504_401_config = {
-	.demod_address = 0x55,
-};
-
-
-
-static int av7110_fe_lock_fix(struct av7110* av7110, fe_status_t status)
-{
-	int ret = 0;
-	int synced = (status & FE_HAS_LOCK) ? 1 : 0;
-
-	av7110->fe_status = status;
-
-	if (av7110->fe_synced == synced)
-		return 0;
-
-	if (av7110->playing) {
-		av7110->fe_synced = synced;
-		return 0;
-	}
-
-	if (mutex_lock_interruptible(&av7110->pid_mutex))
-		return -ERESTARTSYS;
-
-	if (synced) {
-		ret = SetPIDs(av7110, av7110->pids[DMX_PES_VIDEO],
-			av7110->pids[DMX_PES_AUDIO],
-			av7110->pids[DMX_PES_TELETEXT], 0,
-			av7110->pids[DMX_PES_PCR]);
-		if (!ret)
-			ret = av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, Scan, 0);
-	} else {
-		ret = SetPIDs(av7110, 0, 0, 0, 0, 0);
-		if (!ret) {
-			ret = av7110_fw_cmd(av7110, COMTYPE_PID_FILTER, FlushTSQueue, 0);
-			if (!ret)
-				ret = av7110_wait_msgstate(av7110, GPMQBusy);
-		}
-	}
-
-	if (!ret)
-		av7110->fe_synced = synced;
-
-	mutex_unlock(&av7110->pid_mutex);
-	return ret;
-}
-
-static int av7110_fe_set_frontend(struct dvb_frontend *fe)
-{
-	struct av7110* av7110 = fe->dvb->priv;
-
-	int ret = av7110_fe_lock_fix(av7110, 0);
-	if (!ret)
-		ret = av7110->fe_set_frontend(fe);
-
-	return ret;
-}
-
-static int av7110_fe_init(struct dvb_frontend* fe)
-{
-	struct av7110* av7110 = fe->dvb->priv;
-
-	int ret = av7110_fe_lock_fix(av7110, 0);
-	if (!ret)
-		ret = av7110->fe_init(fe);
-	return ret;
-}
-
-static int av7110_fe_read_status(struct dvb_frontend* fe, fe_status_t* status)
-{
-	struct av7110* av7110 = fe->dvb->priv;
-
-	/* call the real implementation */
-	int ret = av7110->fe_read_status(fe, status);
-	if (!ret)
-		if (((*status ^ av7110->fe_status) & FE_HAS_LOCK) && (*status & FE_HAS_LOCK))
-			ret = av7110_fe_lock_fix(av7110, *status);
-	return ret;
-}
-
-static int av7110_fe_diseqc_reset_overload(struct dvb_frontend* fe)
-{
-	struct av7110* av7110 = fe->dvb->priv;
-
-	int ret = av7110_fe_lock_fix(av7110, 0);
-	if (!ret)
-		ret = av7110->fe_diseqc_reset_overload(fe);
-	return ret;
-}
-
-static int av7110_fe_diseqc_send_master_cmd(struct dvb_frontend* fe,
-					    struct dvb_diseqc_master_cmd* cmd)
-{
-	struct av7110* av7110 = fe->dvb->priv;
-
-	int ret = av7110_fe_lock_fix(av7110, 0);
-	if (!ret) {
-		av7110->saved_master_cmd = *cmd;
-		ret = av7110->fe_diseqc_send_master_cmd(fe, cmd);
-	}
-	return ret;
-}
-
-static int av7110_fe_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd)
-{
-	struct av7110* av7110 = fe->dvb->priv;
-
-	int ret = av7110_fe_lock_fix(av7110, 0);
-	if (!ret) {
-		av7110->saved_minicmd = minicmd;
-		ret = av7110->fe_diseqc_send_burst(fe, minicmd);
-	}
-	return ret;
-}
-
-static int av7110_fe_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
-{
-	struct av7110* av7110 = fe->dvb->priv;
-
-	int ret = av7110_fe_lock_fix(av7110, 0);
-	if (!ret) {
-		av7110->saved_tone = tone;
-		ret = av7110->fe_set_tone(fe, tone);
-	}
-	return ret;
-}
-
-static int av7110_fe_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
-{
-	struct av7110* av7110 = fe->dvb->priv;
-
-	int ret = av7110_fe_lock_fix(av7110, 0);
-	if (!ret) {
-		av7110->saved_voltage = voltage;
-		ret = av7110->fe_set_voltage(fe, voltage);
-	}
-	return ret;
-}
-
-static int av7110_fe_dishnetwork_send_legacy_command(struct dvb_frontend* fe, unsigned long cmd)
-{
-	struct av7110* av7110 = fe->dvb->priv;
-
-	int ret = av7110_fe_lock_fix(av7110, 0);
-	if (!ret)
-		ret = av7110->fe_dishnetwork_send_legacy_command(fe, cmd);
-	return ret;
-}
-
-static void dvb_s_recover(struct av7110* av7110)
-{
-	av7110_fe_init(av7110->fe);
-
-	av7110_fe_set_voltage(av7110->fe, av7110->saved_voltage);
-	if (av7110->saved_master_cmd.msg_len) {
-		msleep(20);
-		av7110_fe_diseqc_send_master_cmd(av7110->fe, &av7110->saved_master_cmd);
-	}
-	msleep(20);
-	av7110_fe_diseqc_send_burst(av7110->fe, av7110->saved_minicmd);
-	msleep(20);
-	av7110_fe_set_tone(av7110->fe, av7110->saved_tone);
-
-	av7110_fe_set_frontend(av7110->fe);
-}
-
-static u8 read_pwm(struct av7110* av7110)
-{
-	u8 b = 0xff;
-	u8 pwm;
-	struct i2c_msg msg[] = { { .addr = 0x50,.flags = 0,.buf = &b,.len = 1 },
-				 { .addr = 0x50,.flags = I2C_M_RD,.buf = &pwm,.len = 1} };
-
-	if ((i2c_transfer(&av7110->i2c_adap, msg, 2) != 2) || (pwm == 0xff))
-		pwm = 0x48;
-
-	return pwm;
-}
-
-static int frontend_init(struct av7110 *av7110)
-{
-	int ret;
-
-	if (av7110->dev->pci->subsystem_vendor == 0x110a) {
-		switch(av7110->dev->pci->subsystem_device) {
-		case 0x0000: // Fujitsu/Siemens DVB-Cable (ves1820/Philips CD1516(??))
-			av7110->fe = dvb_attach(ves1820_attach, &philips_cd1516_config,
-						    &av7110->i2c_adap, read_pwm(av7110));
-			if (av7110->fe) {
-				av7110->fe->ops.tuner_ops.set_params = philips_cd1516_tuner_set_params;
-			}
-			break;
-		}
-
-	} else if (av7110->dev->pci->subsystem_vendor == 0x13c2) {
-		switch(av7110->dev->pci->subsystem_device) {
-		case 0x0000: // Hauppauge/TT WinTV DVB-S rev1.X
-		case 0x0003: // Hauppauge/TT WinTV Nexus-S Rev 2.X
-		case 0x1002: // Hauppauge/TT WinTV DVB-S rev1.3SE
-
-			// try the ALPS BSRV2 first of all
-			av7110->fe = dvb_attach(ves1x93_attach, &alps_bsrv2_config, &av7110->i2c_adap);
-			if (av7110->fe) {
-				av7110->fe->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params;
-				av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
-				av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
-				av7110->fe->ops.set_tone = av7110_set_tone;
-				av7110->recover = dvb_s_recover;
-				break;
-			}
-
-			// try the ALPS BSRU6 now
-			av7110->fe = dvb_attach(stv0299_attach, &alps_bsru6_config, &av7110->i2c_adap);
-			if (av7110->fe) {
-				av7110->fe->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
-				av7110->fe->tuner_priv = &av7110->i2c_adap;
-
-				av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
-				av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
-				av7110->fe->ops.set_tone = av7110_set_tone;
-				av7110->recover = dvb_s_recover;
-				break;
-			}
-
-			// Try the grundig 29504-451
-			av7110->fe = dvb_attach(tda8083_attach, &grundig_29504_451_config, &av7110->i2c_adap);
-			if (av7110->fe) {
-				av7110->fe->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params;
-				av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
-				av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
-				av7110->fe->ops.set_tone = av7110_set_tone;
-				av7110->recover = dvb_s_recover;
-				break;
-			}
-
-			/* Try DVB-C cards */
-			switch(av7110->dev->pci->subsystem_device) {
-			case 0x0000:
-				/* Siemens DVB-C (full-length card) VES1820/Philips CD1516 */
-				av7110->fe = dvb_attach(ves1820_attach, &philips_cd1516_config, &av7110->i2c_adap,
-							read_pwm(av7110));
-				if (av7110->fe) {
-					av7110->fe->ops.tuner_ops.set_params = philips_cd1516_tuner_set_params;
-				}
-				break;
-			case 0x0003:
-				/* Hauppauge DVB-C 2.1 VES1820/ALPS TDBE2 */
-				av7110->fe = dvb_attach(ves1820_attach, &alps_tdbe2_config, &av7110->i2c_adap,
-							read_pwm(av7110));
-				if (av7110->fe) {
-					av7110->fe->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params;
-				}
-				break;
-			}
-			break;
-
-		case 0x0001: // Hauppauge/TT Nexus-T premium rev1.X
-			// try ALPS TDLB7 first, then Grundig 29504-401
-			av7110->fe = dvb_attach(sp8870_attach, &alps_tdlb7_config, &av7110->i2c_adap);
-			if (av7110->fe) {
-				av7110->fe->ops.tuner_ops.set_params = alps_tdlb7_tuner_set_params;
-				break;
-			}
-			/* fall-thru */
-
-		case 0x0008: // Hauppauge/TT DVB-T
-			// Grundig 29504-401
-			av7110->fe = dvb_attach(l64781_attach, &grundig_29504_401_config, &av7110->i2c_adap);
-			if (av7110->fe)
-				av7110->fe->ops.tuner_ops.set_params = grundig_29504_401_tuner_set_params;
-			break;
-
-		case 0x0002: // Hauppauge/TT DVB-C premium rev2.X
-
-			av7110->fe = dvb_attach(ves1820_attach, &alps_tdbe2_config, &av7110->i2c_adap, read_pwm(av7110));
-			if (av7110->fe) {
-				av7110->fe->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params;
-			}
-			break;
-
-		case 0x0004: // Galaxis DVB-S rev1.3
-			/* ALPS BSRV2 */
-			av7110->fe = dvb_attach(ves1x93_attach, &alps_bsrv2_config, &av7110->i2c_adap);
-			if (av7110->fe) {
-				av7110->fe->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params;
-				av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
-				av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
-				av7110->fe->ops.set_tone = av7110_set_tone;
-				av7110->recover = dvb_s_recover;
-			}
-			break;
-
-		case 0x0006: /* Fujitsu-Siemens DVB-S rev 1.6 */
-			/* Grundig 29504-451 */
-			av7110->fe = dvb_attach(tda8083_attach, &grundig_29504_451_config, &av7110->i2c_adap);
-			if (av7110->fe) {
-				av7110->fe->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params;
-				av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
-				av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
-				av7110->fe->ops.set_tone = av7110_set_tone;
-				av7110->recover = dvb_s_recover;
-			}
-			break;
-
-		case 0x000A: // Hauppauge/TT Nexus-CA rev1.X
-
-			av7110->fe = dvb_attach(stv0297_attach, &nexusca_stv0297_config, &av7110->i2c_adap);
-			if (av7110->fe) {
-				av7110->fe->ops.tuner_ops.set_params = nexusca_stv0297_tuner_set_params;
-
-				/* set TDA9819 into DVB mode */
-				saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTLO); // TDA9819 pin9(STD)
-				saa7146_setgpio(av7110->dev, 3, SAA7146_GPIO_OUTLO); // TDA9819 pin30(VIF)
-
-				/* tuner on this needs a slower i2c bus speed */
-				av7110->dev->i2c_bitrate = SAA7146_I2C_BUS_BIT_RATE_240;
-				break;
-			}
-			break;
-
-		case 0x000E: /* Hauppauge/TT Nexus-S rev 2.3 */
-			/* ALPS BSBE1 */
-			av7110->fe = dvb_attach(stv0299_attach, &alps_bsbe1_config, &av7110->i2c_adap);
-			if (av7110->fe) {
-				av7110->fe->ops.tuner_ops.set_params = alps_bsbe1_tuner_set_params;
-				av7110->fe->tuner_priv = &av7110->i2c_adap;
-
-				if (dvb_attach(lnbp21_attach, av7110->fe, &av7110->i2c_adap, 0, 0) == NULL) {
-					printk("dvb-ttpci: LNBP21 not found!\n");
-					if (av7110->fe->ops.release)
-						av7110->fe->ops.release(av7110->fe);
-					av7110->fe = NULL;
-				} else {
-					av7110->fe->ops.dishnetwork_send_legacy_command = NULL;
-					av7110->recover = dvb_s_recover;
-				}
-			}
-			break;
-		}
-	}
-
-	if (!av7110->fe) {
-		/* FIXME: propagate the failure code from the lower layers */
-		ret = -ENOMEM;
-		printk("dvb-ttpci: A frontend driver was not found for device [%04x:%04x] subsystem [%04x:%04x]\n",
-		       av7110->dev->pci->vendor,
-		       av7110->dev->pci->device,
-		       av7110->dev->pci->subsystem_vendor,
-		       av7110->dev->pci->subsystem_device);
-	} else {
-		FE_FUNC_OVERRIDE(av7110->fe->ops.init, av7110->fe_init, av7110_fe_init);
-		FE_FUNC_OVERRIDE(av7110->fe->ops.read_status, av7110->fe_read_status, av7110_fe_read_status);
-		FE_FUNC_OVERRIDE(av7110->fe->ops.diseqc_reset_overload, av7110->fe_diseqc_reset_overload, av7110_fe_diseqc_reset_overload);
-		FE_FUNC_OVERRIDE(av7110->fe->ops.diseqc_send_master_cmd, av7110->fe_diseqc_send_master_cmd, av7110_fe_diseqc_send_master_cmd);
-		FE_FUNC_OVERRIDE(av7110->fe->ops.diseqc_send_burst, av7110->fe_diseqc_send_burst, av7110_fe_diseqc_send_burst);
-		FE_FUNC_OVERRIDE(av7110->fe->ops.set_tone, av7110->fe_set_tone, av7110_fe_set_tone);
-		FE_FUNC_OVERRIDE(av7110->fe->ops.set_voltage, av7110->fe_set_voltage, av7110_fe_set_voltage);
-		FE_FUNC_OVERRIDE(av7110->fe->ops.dishnetwork_send_legacy_command, av7110->fe_dishnetwork_send_legacy_command, av7110_fe_dishnetwork_send_legacy_command);
-		FE_FUNC_OVERRIDE(av7110->fe->ops.set_frontend, av7110->fe_set_frontend, av7110_fe_set_frontend);
-
-		ret = dvb_register_frontend(&av7110->dvb_adapter, av7110->fe);
-		if (ret < 0) {
-			printk("av7110: Frontend registration failed!\n");
-			dvb_frontend_detach(av7110->fe);
-			av7110->fe = NULL;
-		}
-	}
-	return ret;
-}
-
-/* Budgetpatch note:
- * Original hardware design by Roberto Deza:
- * There is a DVB_Wiki at
- * http://www.linuxtv.org/
- *
- * New software triggering design by Emard that works on
- * original Roberto Deza's hardware:
- *
- * rps1 code for budgetpatch will copy internal HS event to GPIO3 pin.
- * GPIO3 is in budget-patch hardware connectd to port B VSYNC
- * HS is an internal event of 7146, accessible with RPS
- * and temporarily raised high every n lines
- * (n in defined in the RPS_THRESH1 counter threshold)
- * I think HS is raised high on the beginning of the n-th line
- * and remains high until this n-th line that triggered
- * it is completely received. When the receiption of n-th line
- * ends, HS is lowered.
- *
- * To transmit data over DMA, 7146 needs changing state at
- * port B VSYNC pin. Any changing of port B VSYNC will
- * cause some DMA data transfer, with more or less packets loss.
- * It depends on the phase and frequency of VSYNC and
- * the way of 7146 is instructed to trigger on port B (defined
- * in DD1_INIT register, 3rd nibble from the right valid
- * numbers are 0-7, see datasheet)
- *
- * The correct triggering can minimize packet loss,
- * dvbtraffic should give this stable bandwidths:
- *   22k transponder = 33814 kbit/s
- * 27.5k transponder = 38045 kbit/s
- * by experiment it is found that the best results
- * (stable bandwidths and almost no packet loss)
- * are obtained using DD1_INIT triggering number 2
- * (Va at rising edge of VS Fa = HS x VS-failing forced toggle)
- * and a VSYNC phase that occurs in the middle of DMA transfer
- * (about byte 188*512=96256 in the DMA window).
- *
- * Phase of HS is still not clear to me how to control,
- * It just happens to be so. It can be seen if one enables
- * RPS_IRQ and print Event Counter 1 in vpeirq(). Every
- * time RPS_INTERRUPT is called, the Event Counter 1 will
- * increment. That's how the 7146 is programmed to do event
- * counting in this budget-patch.c
- * I *think* HPS setting has something to do with the phase
- * of HS but I can't be 100% sure in that.
- *
- * hardware debug note: a working budget card (including budget patch)
- * with vpeirq() interrupt setup in mode "0x90" (every 64K) will
- * generate 3 interrupts per 25-Hz DMA frame of 2*188*512 bytes
- * and that means 3*25=75 Hz of interrupt freqency, as seen by
- * watch cat /proc/interrupts
- *
- * If this frequency is 3x lower (and data received in the DMA
- * buffer don't start with 0x47, but in the middle of packets,
- * whose lengths appear to be like 188 292 188 104 etc.
- * this means VSYNC line is not connected in the hardware.
- * (check soldering pcb and pins)
- * The same behaviour of missing VSYNC can be duplicated on budget
- * cards, by seting DD1_INIT trigger mode 7 in 3rd nibble.
- */
-static int __devinit av7110_attach(struct saa7146_dev* dev,
-				   struct saa7146_pci_extension_data *pci_ext)
-{
-	const int length = TS_WIDTH * TS_HEIGHT;
-	struct pci_dev *pdev = dev->pci;
-	struct av7110 *av7110;
-	struct task_struct *thread;
-	int ret, count = 0;
-
-	dprintk(4, "dev: %p\n", dev);
-
-	/* Set RPS_IRQ to 1 to track rps1 activity.
-	 * Enabling this won't send any interrupt to PC CPU.
-	 */
-#define RPS_IRQ 0
-
-	if (budgetpatch == 1) {
-		budgetpatch = 0;
-		/* autodetect the presence of budget patch
-		 * this only works if saa7146 has been recently
-		 * reset with with MASK_31 to MC1
-		 *
-		 * will wait for VBI_B event (vertical blank at port B)
-		 * and will reset GPIO3 after VBI_B is detected.
-		 * (GPIO3 should be raised high by CPU to
-		 * test if GPIO3 will generate vertical blank signal
-		 * in budget patch GPIO3 is connected to VSYNC_B
-		 */
-
-		/* RESET SAA7146 */
-		saa7146_write(dev, MC1, MASK_31);
-		/* autodetection success seems to be time-dependend after reset */
-
-		/* Fix VSYNC level */
-		saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
-		/* set vsync_b triggering */
-		saa7146_write(dev, DD1_STREAM_B, 0);
-		/* port B VSYNC at rising edge */
-		saa7146_write(dev, DD1_INIT, 0x00000200);
-		saa7146_write(dev, BRS_CTRL, 0x00000000);  // VBI
-		saa7146_write(dev, MC2,
-			      1 * (MASK_08 | MASK_24)  |   // BRS control
-			      0 * (MASK_09 | MASK_25)  |   // a
-			      1 * (MASK_10 | MASK_26)  |   // b
-			      0 * (MASK_06 | MASK_22)  |   // HPS_CTRL1
-			      0 * (MASK_05 | MASK_21)  |   // HPS_CTRL2
-			      0 * (MASK_01 | MASK_15)      // DEBI
-		);
-
-		/* start writing RPS1 code from beginning */
-		count = 0;
-		/* Disable RPS1 */
-		saa7146_write(dev, MC1, MASK_29);
-		/* RPS1 timeout disable */
-		saa7146_write(dev, RPS_TOV1, 0);
-		WRITE_RPS1(CMD_PAUSE | EVT_VBI_B);
-		WRITE_RPS1(CMD_WR_REG_MASK | (GPIO_CTRL>>2));
-		WRITE_RPS1(GPIO3_MSK);
-		WRITE_RPS1(SAA7146_GPIO_OUTLO<<24);
-#if RPS_IRQ
-		/* issue RPS1 interrupt to increment counter */
-		WRITE_RPS1(CMD_INTERRUPT);
-#endif
-		WRITE_RPS1(CMD_STOP);
-		/* Jump to begin of RPS program as safety measure               (p37) */
-		WRITE_RPS1(CMD_JUMP);
-		WRITE_RPS1(dev->d_rps1.dma_handle);
-
-#if RPS_IRQ
-		/* set event counter 1 source as RPS1 interrupt (0x03)          (rE4 p53)
-		 * use 0x03 to track RPS1 interrupts - increase by 1 every gpio3 is toggled
-		 * use 0x15 to track VPE  interrupts - increase by 1 every vpeirq() is called
-		 */
-		saa7146_write(dev, EC1SSR, (0x03<<2) | 3 );
-		/* set event counter 1 threshold to maximum allowed value        (rEC p55) */
-		saa7146_write(dev, ECT1R,  0x3fff );
-#endif
-		/* Set RPS1 Address register to point to RPS code               (r108 p42) */
-		saa7146_write(dev, RPS_ADDR1, dev->d_rps1.dma_handle);
-		/* Enable RPS1,                                                 (rFC p33) */
-		saa7146_write(dev, MC1, (MASK_13 | MASK_29 ));
-
-		mdelay(10);
-		/* now send VSYNC_B to rps1 by rising GPIO3 */
-		saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI);
-		mdelay(10);
-		/* if rps1 responded by lowering the GPIO3,
-		 * then we have budgetpatch hardware
-		 */
-		if ((saa7146_read(dev, GPIO_CTRL) & 0x10000000) == 0) {
-			budgetpatch = 1;
-			printk("dvb-ttpci: BUDGET-PATCH DETECTED.\n");
-		}
-		/* Disable RPS1 */
-		saa7146_write(dev, MC1, ( MASK_29 ));
-#if RPS_IRQ
-		printk("dvb-ttpci: Event Counter 1 0x%04x\n", saa7146_read(dev, EC1R) & 0x3fff );
-#endif
-	}
-
-	/* prepare the av7110 device struct */
-	av7110 = kzalloc(sizeof(struct av7110), GFP_KERNEL);
-	if (!av7110) {
-		dprintk(1, "out of memory\n");
-		return -ENOMEM;
-	}
-
-	av7110->card_name = (char*) pci_ext->ext_priv;
-	av7110->dev = dev;
-	dev->ext_priv = av7110;
-
-	ret = get_firmware(av7110);
-	if (ret < 0)
-		goto err_kfree_0;
-
-	ret = dvb_register_adapter(&av7110->dvb_adapter, av7110->card_name,
-				   THIS_MODULE, &dev->pci->dev, adapter_nr);
-	if (ret < 0)
-		goto err_put_firmware_1;
-
-	/* the Siemens DVB needs this if you want to have the i2c chips
-	   get recognized before the main driver is fully loaded */
-	saa7146_write(dev, GPIO_CTRL, 0x500000);
-
-	strlcpy(av7110->i2c_adap.name, pci_ext->ext_priv, sizeof(av7110->i2c_adap.name));
-
-	saa7146_i2c_adapter_prepare(dev, &av7110->i2c_adap, SAA7146_I2C_BUS_BIT_RATE_120); /* 275 kHz */
-
-	ret = i2c_add_adapter(&av7110->i2c_adap);
-	if (ret < 0)
-		goto err_dvb_unregister_adapter_2;
-
-	ttpci_eeprom_parse_mac(&av7110->i2c_adap,
-			       av7110->dvb_adapter.proposed_mac);
-	ret = -ENOMEM;
-
-	/* full-ts mod? */
-	if (full_ts)
-		av7110->full_ts = true;
-
-	/* check for full-ts flag in eeprom */
-	if (i2c_readreg(av7110, 0xaa, 0) == 0x4f && i2c_readreg(av7110, 0xaa, 1) == 0x45) {
-		u8 flags = i2c_readreg(av7110, 0xaa, 2);
-		if (flags != 0xff && (flags & 0x01))
-			av7110->full_ts = true;
-	}
-
-	if (av7110->full_ts) {
-		printk(KERN_INFO "dvb-ttpci: full-ts mode enabled for saa7146 port B\n");
-		spin_lock_init(&av7110->feedlock1);
-		av7110->grabbing = saa7146_vmalloc_build_pgtable(pdev, length,
-								 &av7110->pt);
-		if (!av7110->grabbing)
-			goto err_i2c_del_3;
-
-		saa7146_write(dev, DD1_STREAM_B, 0x00000000);
-		saa7146_write(dev, MC2, (MASK_10 | MASK_26));
-
-		saa7146_write(dev, DD1_INIT, 0x00000600);
-		saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
-
-		saa7146_write(dev, BRS_CTRL, 0x60000000);
-		saa7146_write(dev, MC2, MASK_08 | MASK_24);
-
-		/* dma3 */
-		saa7146_write(dev, PCI_BT_V1, 0x001c0000 | (saa7146_read(dev, PCI_BT_V1) & ~0x001f0000));
-		saa7146_write(dev, BASE_ODD3, 0);
-		saa7146_write(dev, BASE_EVEN3, 0);
-		saa7146_write(dev, PROT_ADDR3, TS_WIDTH * TS_HEIGHT);
-		saa7146_write(dev, PITCH3, TS_WIDTH);
-		saa7146_write(dev, BASE_PAGE3, av7110->pt.dma | ME1 | 0x90);
-		saa7146_write(dev, NUM_LINE_BYTE3, (TS_HEIGHT << 16) | TS_WIDTH);
-		saa7146_write(dev, MC2, MASK_04 | MASK_20);
-
-		tasklet_init(&av7110->vpe_tasklet, vpeirq, (unsigned long) av7110);
-
-	} else if (budgetpatch) {
-		spin_lock_init(&av7110->feedlock1);
-		av7110->grabbing = saa7146_vmalloc_build_pgtable(pdev, length,
-								 &av7110->pt);
-		if (!av7110->grabbing)
-			goto err_i2c_del_3;
-
-		saa7146_write(dev, PCI_BT_V1, 0x1c1f101f);
-		saa7146_write(dev, BCS_CTRL, 0x80400040);
-		/* set dd1 stream a & b */
-		saa7146_write(dev, DD1_STREAM_B, 0x00000000);
-		saa7146_write(dev, DD1_INIT, 0x03000200);
-		saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
-		saa7146_write(dev, BRS_CTRL, 0x60000000);
-		saa7146_write(dev, BASE_ODD3, 0);
-		saa7146_write(dev, BASE_EVEN3, 0);
-		saa7146_write(dev, PROT_ADDR3, TS_WIDTH * TS_HEIGHT);
-		saa7146_write(dev, BASE_PAGE3, av7110->pt.dma | ME1 | 0x90);
-
-		saa7146_write(dev, PITCH3, TS_WIDTH);
-		saa7146_write(dev, NUM_LINE_BYTE3, (TS_HEIGHT << 16) | TS_WIDTH);
-
-		/* upload all */
-		saa7146_write(dev, MC2, 0x077c077c);
-		saa7146_write(dev, GPIO_CTRL, 0x000000);
-#if RPS_IRQ
-		/* set event counter 1 source as RPS1 interrupt (0x03)          (rE4 p53)
-		 * use 0x03 to track RPS1 interrupts - increase by 1 every gpio3 is toggled
-		 * use 0x15 to track VPE  interrupts - increase by 1 every vpeirq() is called
-		 */
-		saa7146_write(dev, EC1SSR, (0x03<<2) | 3 );
-		/* set event counter 1 threshold to maximum allowed value        (rEC p55) */
-		saa7146_write(dev, ECT1R,  0x3fff );
-#endif
-		/* Setup BUDGETPATCH MAIN RPS1 "program" (p35) */
-		count = 0;
-
-		/* Wait Source Line Counter Threshold                           (p36) */
-		WRITE_RPS1(CMD_PAUSE | EVT_HS);
-		/* Set GPIO3=1                                                  (p42) */
-		WRITE_RPS1(CMD_WR_REG_MASK | (GPIO_CTRL>>2));
-		WRITE_RPS1(GPIO3_MSK);
-		WRITE_RPS1(SAA7146_GPIO_OUTHI<<24);
-#if RPS_IRQ
-		/* issue RPS1 interrupt */
-		WRITE_RPS1(CMD_INTERRUPT);
-#endif
-		/* Wait reset Source Line Counter Threshold                     (p36) */
-		WRITE_RPS1(CMD_PAUSE | RPS_INV | EVT_HS);
-		/* Set GPIO3=0                                                  (p42) */
-		WRITE_RPS1(CMD_WR_REG_MASK | (GPIO_CTRL>>2));
-		WRITE_RPS1(GPIO3_MSK);
-		WRITE_RPS1(SAA7146_GPIO_OUTLO<<24);
-#if RPS_IRQ
-		/* issue RPS1 interrupt */
-		WRITE_RPS1(CMD_INTERRUPT);
-#endif
-		/* Jump to begin of RPS program                                 (p37) */
-		WRITE_RPS1(CMD_JUMP);
-		WRITE_RPS1(dev->d_rps1.dma_handle);
-
-		/* Fix VSYNC level */
-		saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
-		/* Set RPS1 Address register to point to RPS code               (r108 p42) */
-		saa7146_write(dev, RPS_ADDR1, dev->d_rps1.dma_handle);
-		/* Set Source Line Counter Threshold, using BRS                 (rCC p43)
-		 * It generates HS event every TS_HEIGHT lines
-		 * this is related to TS_WIDTH set in register
-		 * NUM_LINE_BYTE3. If NUM_LINE_BYTE low 16 bits
-		 * are set to TS_WIDTH bytes (TS_WIDTH=2*188),
-		 * then RPS_THRESH1 should be set to trigger
-		 * every TS_HEIGHT (512) lines.
-		 */
-		saa7146_write(dev, RPS_THRESH1, (TS_HEIGHT*1) | MASK_12 );
-
-		/* Enable RPS1                                                  (rFC p33) */
-		saa7146_write(dev, MC1, (MASK_13 | MASK_29));
-
-		/* end of budgetpatch register initialization */
-		tasklet_init (&av7110->vpe_tasklet,  vpeirq,  (unsigned long) av7110);
-	} else {
-		saa7146_write(dev, PCI_BT_V1, 0x1c00101f);
-		saa7146_write(dev, BCS_CTRL, 0x80400040);
-
-		/* set dd1 stream a & b */
-		saa7146_write(dev, DD1_STREAM_B, 0x00000000);
-		saa7146_write(dev, DD1_INIT, 0x03000000);
-		saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
-
-		/* upload all */
-		saa7146_write(dev, MC2, 0x077c077c);
-		saa7146_write(dev, GPIO_CTRL, 0x000000);
-	}
-
-	tasklet_init (&av7110->debi_tasklet, debiirq, (unsigned long) av7110);
-	tasklet_init (&av7110->gpio_tasklet, gpioirq, (unsigned long) av7110);
-
-	mutex_init(&av7110->pid_mutex);
-
-	/* locks for data transfers from/to AV7110 */
-	spin_lock_init(&av7110->debilock);
-	mutex_init(&av7110->dcomlock);
-	av7110->debitype = -1;
-
-	/* default OSD window */
-	av7110->osdwin = 1;
-	mutex_init(&av7110->osd_mutex);
-
-	/* TV standard */
-	av7110->vidmode = tv_standard == 1 ? AV7110_VIDEO_MODE_NTSC
-					   : AV7110_VIDEO_MODE_PAL;
-
-	/* ARM "watchdog" */
-	init_waitqueue_head(&av7110->arm_wait);
-	av7110->arm_thread = NULL;
-
-	/* allocate and init buffers */
-	av7110->debi_virt = pci_alloc_consistent(pdev, 8192, &av7110->debi_bus);
-	if (!av7110->debi_virt)
-		goto err_saa71466_vfree_4;
-
-
-	av7110->iobuf = vmalloc(AVOUTLEN+AOUTLEN+BMPLEN+4*IPACKS);
-	if (!av7110->iobuf)
-		goto err_pci_free_5;
-
-	ret = av7110_av_init(av7110);
-	if (ret < 0)
-		goto err_iobuf_vfree_6;
-
-	/* init BMP buffer */
-	av7110->bmpbuf = av7110->iobuf+AVOUTLEN+AOUTLEN;
-	init_waitqueue_head(&av7110->bmpq);
-
-	ret = av7110_ca_init(av7110);
-	if (ret < 0)
-		goto err_av7110_av_exit_7;
-
-	/* load firmware into AV7110 cards */
-	ret = av7110_bootarm(av7110);
-	if (ret < 0)
-		goto err_av7110_ca_exit_8;
-
-	ret = av7110_firmversion(av7110);
-	if (ret < 0)
-		goto err_stop_arm_9;
-
-	if (FW_VERSION(av7110->arm_app)<0x2501)
-		printk ("dvb-ttpci: Warning, firmware version 0x%04x is too old. "
-			"System might be unstable!\n", FW_VERSION(av7110->arm_app));
-
-	thread = kthread_run(arm_thread, (void *) av7110, "arm_mon");
-	if (IS_ERR(thread)) {
-		ret = PTR_ERR(thread);
-		goto err_stop_arm_9;
-	}
-	av7110->arm_thread = thread;
-
-	/* set initial volume in mixer struct */
-	av7110->mixer.volume_left  = volume;
-	av7110->mixer.volume_right = volume;
-
-	ret = av7110_register(av7110);
-	if (ret < 0)
-		goto err_arm_thread_stop_10;
-
-	init_av7110_av(av7110);
-
-	/* 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... */
-	ret = av7110_init_v4l(av7110);
-	if (ret < 0)
-		goto err_av7110_unregister_11;
-
-	av7110->dvb_adapter.priv = av7110;
-	ret = frontend_init(av7110);
-	if (ret < 0)
-		goto err_av7110_exit_v4l_12;
-
-#if defined(CONFIG_INPUT_EVDEV) || defined(CONFIG_INPUT_EVDEV_MODULE)
-	av7110_ir_init(av7110);
-#endif
-	printk(KERN_INFO "dvb-ttpci: found av7110-%d.\n", av7110_num);
-	av7110_num++;
-out:
-	return ret;
-
-err_av7110_exit_v4l_12:
-	av7110_exit_v4l(av7110);
-err_av7110_unregister_11:
-	dvb_unregister(av7110);
-err_arm_thread_stop_10:
-	av7110_arm_sync(av7110);
-err_stop_arm_9:
-	/* Nothing to do. Rejoice. */
-err_av7110_ca_exit_8:
-	av7110_ca_exit(av7110);
-err_av7110_av_exit_7:
-	av7110_av_exit(av7110);
-err_iobuf_vfree_6:
-	vfree(av7110->iobuf);
-err_pci_free_5:
-	pci_free_consistent(pdev, 8192, av7110->debi_virt, av7110->debi_bus);
-err_saa71466_vfree_4:
-	if (av7110->grabbing)
-		saa7146_vfree_destroy_pgtable(pdev, av7110->grabbing, &av7110->pt);
-err_i2c_del_3:
-	i2c_del_adapter(&av7110->i2c_adap);
-err_dvb_unregister_adapter_2:
-	dvb_unregister_adapter(&av7110->dvb_adapter);
-err_put_firmware_1:
-	put_firmware(av7110);
-err_kfree_0:
-	kfree(av7110);
-	goto out;
-}
-
-static int __devexit av7110_detach(struct saa7146_dev* saa)
-{
-	struct av7110 *av7110 = saa->ext_priv;
-	dprintk(4, "%p\n", av7110);
-
-#if defined(CONFIG_INPUT_EVDEV) || defined(CONFIG_INPUT_EVDEV_MODULE)
-	av7110_ir_exit(av7110);
-#endif
-	if (budgetpatch || av7110->full_ts) {
-		if (budgetpatch) {
-			/* Disable RPS1 */
-			saa7146_write(saa, MC1, MASK_29);
-			/* VSYNC LOW (inactive) */
-			saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
-		}
-		saa7146_write(saa, MC1, MASK_20);	/* DMA3 off */
-		SAA7146_IER_DISABLE(saa, MASK_10);
-		SAA7146_ISR_CLEAR(saa, MASK_10);
-		msleep(50);
-		tasklet_kill(&av7110->vpe_tasklet);
-		saa7146_vfree_destroy_pgtable(saa->pci, av7110->grabbing, &av7110->pt);
-	}
-	av7110_exit_v4l(av7110);
-
-	av7110_arm_sync(av7110);
-
-	tasklet_kill(&av7110->debi_tasklet);
-	tasklet_kill(&av7110->gpio_tasklet);
-
-	dvb_unregister(av7110);
-
-	SAA7146_IER_DISABLE(saa, MASK_19 | MASK_03);
-	SAA7146_ISR_CLEAR(saa, MASK_19 | MASK_03);
-
-	av7110_ca_exit(av7110);
-	av7110_av_exit(av7110);
-
-	vfree(av7110->iobuf);
-	pci_free_consistent(saa->pci, 8192, av7110->debi_virt,
-			    av7110->debi_bus);
-
-	i2c_del_adapter(&av7110->i2c_adap);
-
-	dvb_unregister_adapter (&av7110->dvb_adapter);
-
-	av7110_num--;
-
-	put_firmware(av7110);
-
-	kfree(av7110);
-
-	saa->ext_priv = NULL;
-
-	return 0;
-}
-
-
-static void av7110_irq(struct saa7146_dev* dev, u32 *isr)
-{
-	struct av7110 *av7110 = dev->ext_priv;
-
-	//print_time("av7110_irq");
-
-	/* Note: Don't try to handle the DEBI error irq (MASK_18), in
-	 * intel mode the timeout is asserted all the time...
-	 */
-
-	if (*isr & MASK_19) {
-		//printk("av7110_irq: DEBI\n");
-		/* Note 1: The DEBI irq is level triggered: We must enable it
-		 * only after we started a DMA xfer, and disable it here
-		 * immediately, or it will be signalled all the time while
-		 * DEBI is idle.
-		 * Note 2: You would think that an irq which is masked is
-		 * not signalled by the hardware. Not so for the SAA7146:
-		 * An irq is signalled as long as the corresponding bit
-		 * in the ISR is set, and disabling irqs just prevents the
-		 * hardware from setting the ISR bit. This means a) that we
-		 * must clear the ISR *after* disabling the irq (which is why
-		 * we must do it here even though saa7146_core did it already),
-		 * and b) that if we were to disable an edge triggered irq
-		 * (like the gpio irqs sadly are) temporarily we would likely
-		 * loose some. This sucks :-(
-		 */
-		SAA7146_IER_DISABLE(av7110->dev, MASK_19);
-		SAA7146_ISR_CLEAR(av7110->dev, MASK_19);
-		tasklet_schedule(&av7110->debi_tasklet);
-	}
-
-	if (*isr & MASK_03) {
-		//printk("av7110_irq: GPIO\n");
-		tasklet_schedule(&av7110->gpio_tasklet);
-	}
-
-	if (*isr & MASK_10)
-		tasklet_schedule(&av7110->vpe_tasklet);
-}
-
-
-static struct saa7146_extension av7110_extension_driver;
-
-#define MAKE_AV7110_INFO(x_var,x_name) \
-static struct saa7146_pci_extension_data x_var = { \
-	.ext_priv = x_name, \
-	.ext = &av7110_extension_driver }
-
-MAKE_AV7110_INFO(tts_1_X_fsc,"Technotrend/Hauppauge WinTV DVB-S rev1.X or Fujitsu Siemens DVB-C");
-MAKE_AV7110_INFO(ttt_1_X,    "Technotrend/Hauppauge WinTV DVB-T rev1.X");
-MAKE_AV7110_INFO(ttc_1_X,    "Technotrend/Hauppauge WinTV Nexus-CA rev1.X");
-MAKE_AV7110_INFO(ttc_2_X,    "Technotrend/Hauppauge WinTV DVB-C rev2.X");
-MAKE_AV7110_INFO(tts_2_X,    "Technotrend/Hauppauge WinTV Nexus-S rev2.X");
-MAKE_AV7110_INFO(tts_2_3,    "Technotrend/Hauppauge WinTV Nexus-S rev2.3");
-MAKE_AV7110_INFO(tts_1_3se,  "Technotrend/Hauppauge WinTV DVB-S rev1.3 SE");
-MAKE_AV7110_INFO(ttt,        "Technotrend/Hauppauge DVB-T");
-MAKE_AV7110_INFO(fsc,        "Fujitsu Siemens DVB-C");
-MAKE_AV7110_INFO(fss,        "Fujitsu Siemens DVB-S rev1.6");
-MAKE_AV7110_INFO(gxs_1_3,    "Galaxis DVB-S rev1.3");
-
-static struct pci_device_id pci_tbl[] = {
-	MAKE_EXTENSION_PCI(fsc,         0x110a, 0x0000),
-	MAKE_EXTENSION_PCI(tts_1_X_fsc, 0x13c2, 0x0000),
-	MAKE_EXTENSION_PCI(ttt_1_X,     0x13c2, 0x0001),
-	MAKE_EXTENSION_PCI(ttc_2_X,     0x13c2, 0x0002),
-	MAKE_EXTENSION_PCI(tts_2_X,     0x13c2, 0x0003),
-	MAKE_EXTENSION_PCI(gxs_1_3,     0x13c2, 0x0004),
-	MAKE_EXTENSION_PCI(fss,         0x13c2, 0x0006),
-	MAKE_EXTENSION_PCI(ttt,         0x13c2, 0x0008),
-	MAKE_EXTENSION_PCI(ttc_1_X,     0x13c2, 0x000a),
-	MAKE_EXTENSION_PCI(tts_2_3,     0x13c2, 0x000e),
-	MAKE_EXTENSION_PCI(tts_1_3se,   0x13c2, 0x1002),
-
-/*	MAKE_EXTENSION_PCI(???, 0x13c2, 0x0005), UNDEFINED CARD */ // Technisat SkyStar1
-/*	MAKE_EXTENSION_PCI(???, 0x13c2, 0x0009), UNDEFINED CARD */ // TT/Hauppauge WinTV Nexus-CA v????
-
-	{
-		.vendor    = 0,
-	}
-};
-
-MODULE_DEVICE_TABLE(pci, pci_tbl);
-
-
-static struct saa7146_extension av7110_extension_driver = {
-	.name		= "av7110",
-	.flags		= SAA7146_USE_I2C_IRQ,
-
-	.module		= THIS_MODULE,
-	.pci_tbl	= &pci_tbl[0],
-	.attach		= av7110_attach,
-	.detach		= __devexit_p(av7110_detach),
-
-	.irq_mask	= MASK_19 | MASK_03 | MASK_10,
-	.irq_func	= av7110_irq,
-};
-
-
-static int __init av7110_init(void)
-{
-	int retval;
-	retval = saa7146_register_extension(&av7110_extension_driver);
-	return retval;
-}
-
-
-static void __exit av7110_exit(void)
-{
-	saa7146_unregister_extension(&av7110_extension_driver);
-}
-
-module_init(av7110_init);
-module_exit(av7110_exit);
-
-MODULE_DESCRIPTION("driver for the SAA7146 based AV110 PCI DVB cards by "
-		   "Siemens, Technotrend, Hauppauge");
-MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, others");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/ttpci/av7110.h b/drivers/media/dvb/ttpci/av7110.h
deleted file mode 100644
index 88b3b2d..0000000
--- a/drivers/media/dvb/ttpci/av7110.h
+++ /dev/null
@@ -1,314 +0,0 @@
-#ifndef _AV7110_H_
-#define _AV7110_H_
-
-#include <linux/interrupt.h>
-#include <linux/socket.h>
-#include <linux/netdevice.h>
-#include <linux/i2c.h>
-#include <linux/input.h>
-
-#include <linux/dvb/video.h>
-#include <linux/dvb/audio.h>
-#include <linux/dvb/dmx.h>
-#include <linux/dvb/ca.h>
-#include <linux/dvb/osd.h>
-#include <linux/dvb/net.h>
-#include <linux/mutex.h>
-
-#include "dvbdev.h"
-#include "demux.h"
-#include "dvb_demux.h"
-#include "dmxdev.h"
-#include "dvb_filter.h"
-#include "dvb_net.h"
-#include "dvb_ringbuffer.h"
-#include "dvb_frontend.h"
-#include "ves1820.h"
-#include "ves1x93.h"
-#include "stv0299.h"
-#include "tda8083.h"
-#include "sp8870.h"
-#include "stv0297.h"
-#include "l64781.h"
-
-#include <media/saa7146_vv.h>
-
-
-#define ANALOG_TUNER_VES1820 1
-#define ANALOG_TUNER_STV0297 2
-
-extern int av7110_debug;
-
-#define dprintk(level,args...) \
-	    do { if ((av7110_debug & level)) { printk("dvb-ttpci: %s(): ", __func__); printk(args); } } while (0)
-
-#define MAXFILT 32
-
-enum {AV_PES_STREAM, PS_STREAM, TS_STREAM, PES_STREAM};
-
-enum av7110_video_mode {
-	AV7110_VIDEO_MODE_PAL 	= 0,
-	AV7110_VIDEO_MODE_NTSC	= 1
-};
-
-struct av7110_p2t {
-	u8		  pes[TS_SIZE];
-	u8		  counter;
-	long int	  pos;
-	int		  frags;
-	struct dvb_demux_feed *feed;
-};
-
-/* video MPEG decoder events: */
-/* (code copied from dvb_frontend.c, should maybe be factored out...) */
-#define MAX_VIDEO_EVENT 8
-struct dvb_video_events {
-	struct video_event	  events[MAX_VIDEO_EVENT];
-	int			  eventw;
-	int			  eventr;
-	int			  overflow;
-	wait_queue_head_t	  wait_queue;
-	spinlock_t		  lock;
-};
-
-
-struct av7110;
-
-/* infrared remote control */
-struct infrared {
-	u16	key_map[256];
-	struct input_dev	*input_dev;
-	char			input_phys[32];
-	struct timer_list	keyup_timer;
-	struct tasklet_struct	ir_tasklet;
-	void			(*ir_handler)(struct av7110 *av7110, u32 ircom);
-	u32			ir_command;
-	u32			ir_config;
-	u32			device_mask;
-	u8			protocol;
-	u8			inversion;
-	u16			last_key;
-	u16			last_toggle;
-	u8			delay_timer_finished;
-};
-
-
-/* place to store all the necessary device information */
-struct av7110 {
-
-	/* devices */
-
-	struct dvb_device	dvb_dev;
-	struct dvb_net		dvb_net;
-
-	struct video_device	*v4l_dev;
-	struct video_device	*vbi_dev;
-
-	struct saa7146_dev	*dev;
-
-	struct i2c_adapter	i2c_adap;
-
-	char			*card_name;
-
-	/* support for analog module of dvb-c */
-	int			analog_tuner_flags;
-	int			current_input;
-	u32			current_freq;
-
-	struct tasklet_struct	debi_tasklet;
-	struct tasklet_struct	gpio_tasklet;
-
-	int adac_type;	       /* audio DAC type */
-#define DVB_ADAC_TI	  0
-#define DVB_ADAC_CRYSTAL  1
-#define DVB_ADAC_MSP34x0  2
-#define DVB_ADAC_MSP34x5  3
-#define DVB_ADAC_NONE	 -1
-
-
-	/* buffers */
-
-	void		       *iobuf;	 /* memory for all buffers */
-	struct dvb_ringbuffer	avout;   /* buffer for video or A/V mux */
-#define AVOUTLEN (128*1024)
-	struct dvb_ringbuffer	aout;    /* buffer for audio */
-#define AOUTLEN (64*1024)
-	void		       *bmpbuf;
-#define BMPLEN (8*32768+1024)
-
-	/* bitmap buffers and states */
-
-	int			bmpp;
-	int			bmplen;
-	volatile int		bmp_state;
-#define BMP_NONE     0
-#define BMP_LOADING  1
-#define BMP_LOADED   2
-	wait_queue_head_t	bmpq;
-
-
-	/* DEBI and polled command interface */
-
-	spinlock_t		debilock;
-	struct mutex		dcomlock;
-	volatile int		debitype;
-	volatile int		debilen;
-
-
-	/* Recording and playback flags */
-
-	int			rec_mode;
-	int			playing;
-#define RP_NONE  0
-#define RP_VIDEO 1
-#define RP_AUDIO 2
-#define RP_AV	 3
-
-
-	/* OSD */
-
-	int			osdwin;      /* currently active window */
-	u16			osdbpp[8];
-	struct mutex		osd_mutex;
-
-	/* CA */
-
-	ca_slot_info_t		ci_slot[2];
-
-	enum av7110_video_mode	vidmode;
-	struct dmxdev		dmxdev;
-	struct dvb_demux	demux;
-
-	struct dmx_frontend	hw_frontend;
-	struct dmx_frontend	mem_frontend;
-
-	/* for budget mode demux1 */
-	struct dmxdev		dmxdev1;
-	struct dvb_demux	demux1;
-	struct dvb_net		dvb_net1;
-	spinlock_t		feedlock1;
-	int			feeding1;
-	u32			ttbp;
-	unsigned char           *grabbing;
-	struct saa7146_pgtable  pt;
-	struct tasklet_struct   vpe_tasklet;
-	bool			full_ts;
-
-	int			fe_synced;
-	struct mutex		pid_mutex;
-
-	int			video_blank;
-	struct video_status	videostate;
-	u16			display_panscan;
-	int			display_ar;
-	int			trickmode;
-#define TRICK_NONE   0
-#define TRICK_FAST   1
-#define TRICK_SLOW   2
-#define TRICK_FREEZE 3
-	struct audio_status	audiostate;
-
-	struct dvb_demux_filter *handle2filter[32];
-	struct av7110_p2t	 p2t_filter[MAXFILT];
-	struct dvb_filter_pes2ts p2t[2];
-	struct ipack		 ipack[2];
-	u8			*kbuf[2];
-
-	int sinfo;
-	int feeding;
-
-	int arm_errors;
-	int registered;
-
-
-	/* AV711X */
-
-	u32		    arm_fw;
-	u32		    arm_rtsl;
-	u32		    arm_vid;
-	u32		    arm_app;
-	u32		    avtype;
-	int		    arm_ready;
-	struct task_struct *arm_thread;
-	wait_queue_head_t   arm_wait;
-	u16		    arm_loops;
-
-	void		   *debi_virt;
-	dma_addr_t	    debi_bus;
-
-	u16		    pids[DMX_PES_OTHER];
-
-	struct dvb_ringbuffer	 ci_rbuffer;
-	struct dvb_ringbuffer	 ci_wbuffer;
-
-	struct audio_mixer	mixer;
-
-	struct dvb_adapter	 dvb_adapter;
-	struct dvb_device	 *video_dev;
-	struct dvb_device	 *audio_dev;
-	struct dvb_device	 *ca_dev;
-	struct dvb_device	 *osd_dev;
-
-	struct dvb_video_events  video_events;
-	video_size_t		 video_size;
-
-	u16			wssMode;
-	u16			wssData;
-
-	struct infrared		ir;
-
-	/* firmware stuff */
-	unsigned char *bin_fw;
-	unsigned long size_fw;
-
-	unsigned char *bin_dpram;
-	unsigned long size_dpram;
-
-	unsigned char *bin_root;
-	unsigned long size_root;
-
-	struct dvb_frontend* fe;
-	fe_status_t fe_status;
-
-	/* crash recovery */
-	void				(*recover)(struct av7110* av7110);
-	fe_sec_voltage_t		saved_voltage;
-	fe_sec_tone_mode_t		saved_tone;
-	struct dvb_diseqc_master_cmd	saved_master_cmd;
-	fe_sec_mini_cmd_t		saved_minicmd;
-
-	int (*fe_init)(struct dvb_frontend* fe);
-	int (*fe_read_status)(struct dvb_frontend* fe, fe_status_t* status);
-	int (*fe_diseqc_reset_overload)(struct dvb_frontend* fe);
-	int (*fe_diseqc_send_master_cmd)(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd);
-	int (*fe_diseqc_send_burst)(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd);
-	int (*fe_set_tone)(struct dvb_frontend* fe, fe_sec_tone_mode_t tone);
-	int (*fe_set_voltage)(struct dvb_frontend* fe, fe_sec_voltage_t voltage);
-	int (*fe_dishnetwork_send_legacy_command)(struct dvb_frontend* fe, unsigned long cmd);
-	int (*fe_set_frontend)(struct dvb_frontend *fe);
-};
-
-
-extern int ChangePIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid,
-		       u16 subpid, u16 pcrpid);
-
-extern int av7110_check_ir_config(struct av7110 *av7110, int force);
-extern int av7110_ir_init(struct av7110 *av7110);
-extern void av7110_ir_exit(struct av7110 *av7110);
-
-/* msp3400 i2c subaddresses */
-#define MSP_WR_DEM 0x10
-#define MSP_RD_DEM 0x11
-#define MSP_WR_DSP 0x12
-#define MSP_RD_DSP 0x13
-
-extern int i2c_writereg(struct av7110 *av7110, u8 id, u8 reg, u8 val);
-extern u8 i2c_readreg(struct av7110 *av7110, u8 id, u8 reg);
-extern int msp_writereg(struct av7110 *av7110, u8 dev, u16 reg, u16 val);
-
-
-extern int av7110_init_analog_module(struct av7110 *av7110);
-extern int av7110_init_v4l(struct av7110 *av7110);
-extern int av7110_exit_v4l(struct av7110 *av7110);
-
-#endif /* _AV7110_H_ */
diff --git a/drivers/media/dvb/ttpci/av7110_av.c b/drivers/media/dvb/ttpci/av7110_av.c
deleted file mode 100644
index 952b33d..0000000
--- a/drivers/media/dvb/ttpci/av7110_av.c
+++ /dev/null
@@ -1,1626 +0,0 @@
-/*
- * av7110_av.c: audio and video MPEG decoder stuff
- *
- * Copyright (C) 1999-2002 Ralph  Metzler
- *                       & Marcus Metzler for convergence integrated media GmbH
- *
- * originally based on code by:
- * Copyright (C) 1998,1999 Christian Theiss <mistert@rz.fh-augsburg.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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- *
- *
- * the project's page is at http://www.linuxtv.org/ 
- */
-
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/delay.h>
-#include <linux/fs.h>
-
-#include "av7110.h"
-#include "av7110_hw.h"
-#include "av7110_av.h"
-#include "av7110_ipack.h"
-
-/* MPEG-2 (ISO 13818 / H.222.0) stream types */
-#define PROG_STREAM_MAP  0xBC
-#define PRIVATE_STREAM1  0xBD
-#define PADDING_STREAM	 0xBE
-#define PRIVATE_STREAM2  0xBF
-#define AUDIO_STREAM_S	 0xC0
-#define AUDIO_STREAM_E	 0xDF
-#define VIDEO_STREAM_S	 0xE0
-#define VIDEO_STREAM_E	 0xEF
-#define ECM_STREAM	 0xF0
-#define EMM_STREAM	 0xF1
-#define DSM_CC_STREAM	 0xF2
-#define ISO13522_STREAM  0xF3
-#define PROG_STREAM_DIR  0xFF
-
-#define PTS_DTS_FLAGS	 0xC0
-
-//pts_dts flags
-#define PTS_ONLY	 0x80
-#define PTS_DTS		 0xC0
-#define TS_SIZE		 188
-#define TRANS_ERROR	 0x80
-#define PAY_START	 0x40
-#define TRANS_PRIO	 0x20
-#define PID_MASK_HI	 0x1F
-//flags
-#define TRANS_SCRMBL1	 0x80
-#define TRANS_SCRMBL2	 0x40
-#define ADAPT_FIELD	 0x20
-#define PAYLOAD		 0x10
-#define COUNT_MASK	 0x0F
-
-// adaptation flags
-#define DISCON_IND	 0x80
-#define RAND_ACC_IND	 0x40
-#define ES_PRI_IND	 0x20
-#define PCR_FLAG	 0x10
-#define OPCR_FLAG	 0x08
-#define SPLICE_FLAG	 0x04
-#define TRANS_PRIV	 0x02
-#define ADAP_EXT_FLAG	 0x01
-
-// adaptation extension flags
-#define LTW_FLAG	 0x80
-#define PIECE_RATE	 0x40
-#define SEAM_SPLICE	 0x20
-
-
-static void p_to_t(u8 const *buf, long int length, u16 pid,
-		   u8 *counter, struct dvb_demux_feed *feed);
-static int write_ts_to_decoder(struct av7110 *av7110, int type, const u8 *buf, size_t len);
-
-
-int av7110_record_cb(struct dvb_filter_pes2ts *p2t, u8 *buf, size_t len)
-{
-	struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *) p2t->priv;
-
-	if (!(dvbdmxfeed->ts_type & TS_PACKET))
-		return 0;
-	if (buf[3] == 0xe0)	 // video PES do not have a length in TS
-		buf[4] = buf[5] = 0;
-	if (dvbdmxfeed->ts_type & TS_PAYLOAD_ONLY)
-		return dvbdmxfeed->cb.ts(buf, len, NULL, 0,
-					 &dvbdmxfeed->feed.ts, DMX_OK);
-	else
-		return dvb_filter_pes2ts(p2t, buf, len, 1);
-}
-
-static int dvb_filter_pes2ts_cb(void *priv, unsigned char *data)
-{
-	struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *) priv;
-
-	dvbdmxfeed->cb.ts(data, 188, NULL, 0,
-			  &dvbdmxfeed->feed.ts, DMX_OK);
-	return 0;
-}
-
-int av7110_av_start_record(struct av7110 *av7110, int av,
-			   struct dvb_demux_feed *dvbdmxfeed)
-{
-	int ret = 0;
-	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
-
-	dprintk(2, "av7110:%p, , dvb_demux_feed:%p\n", av7110, dvbdmxfeed);
-
-	if (av7110->playing || (av7110->rec_mode & av))
-		return -EBUSY;
-	av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Stop, 0);
-	dvbdmx->recording = 1;
-	av7110->rec_mode |= av;
-
-	switch (av7110->rec_mode) {
-	case RP_AUDIO:
-		dvb_filter_pes2ts_init(&av7110->p2t[0],
-				       dvbdmx->pesfilter[0]->pid,
-				       dvb_filter_pes2ts_cb,
-				       (void *) dvbdmx->pesfilter[0]);
-		ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Record, 2, AudioPES, 0);
-		break;
-
-	case RP_VIDEO:
-		dvb_filter_pes2ts_init(&av7110->p2t[1],
-				       dvbdmx->pesfilter[1]->pid,
-				       dvb_filter_pes2ts_cb,
-				       (void *) dvbdmx->pesfilter[1]);
-		ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Record, 2, VideoPES, 0);
-		break;
-
-	case RP_AV:
-		dvb_filter_pes2ts_init(&av7110->p2t[0],
-				       dvbdmx->pesfilter[0]->pid,
-				       dvb_filter_pes2ts_cb,
-				       (void *) dvbdmx->pesfilter[0]);
-		dvb_filter_pes2ts_init(&av7110->p2t[1],
-				       dvbdmx->pesfilter[1]->pid,
-				       dvb_filter_pes2ts_cb,
-				       (void *) dvbdmx->pesfilter[1]);
-		ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Record, 2, AV_PES, 0);
-		break;
-	}
-	return ret;
-}
-
-int av7110_av_start_play(struct av7110 *av7110, int av)
-{
-	int ret = 0;
-	dprintk(2, "av7110:%p, \n", av7110);
-
-	if (av7110->rec_mode)
-		return -EBUSY;
-	if (av7110->playing & av)
-		return -EBUSY;
-
-	av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Stop, 0);
-
-	if (av7110->playing == RP_NONE) {
-		av7110_ipack_reset(&av7110->ipack[0]);
-		av7110_ipack_reset(&av7110->ipack[1]);
-	}
-
-	av7110->playing |= av;
-	switch (av7110->playing) {
-	case RP_AUDIO:
-		ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Play, 2, AudioPES, 0);
-		break;
-	case RP_VIDEO:
-		ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Play, 2, VideoPES, 0);
-		av7110->sinfo = 0;
-		break;
-	case RP_AV:
-		av7110->sinfo = 0;
-		ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Play, 2, AV_PES, 0);
-		break;
-	}
-	return ret;
-}
-
-int av7110_av_stop(struct av7110 *av7110, int av)
-{
-	int ret = 0;
-	dprintk(2, "av7110:%p, \n", av7110);
-
-	if (!(av7110->playing & av) && !(av7110->rec_mode & av))
-		return 0;
-	av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Stop, 0);
-	if (av7110->playing) {
-		av7110->playing &= ~av;
-		switch (av7110->playing) {
-		case RP_AUDIO:
-			ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Play, 2, AudioPES, 0);
-			break;
-		case RP_VIDEO:
-			ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Play, 2, VideoPES, 0);
-			break;
-		case RP_NONE:
-			ret = av7110_set_vidmode(av7110, av7110->vidmode);
-			break;
-		}
-	} else {
-		av7110->rec_mode &= ~av;
-		switch (av7110->rec_mode) {
-		case RP_AUDIO:
-			ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Record, 2, AudioPES, 0);
-			break;
-		case RP_VIDEO:
-			ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Record, 2, VideoPES, 0);
-			break;
-		case RP_NONE:
-			break;
-		}
-	}
-	return ret;
-}
-
-
-int av7110_pes_play(void *dest, struct dvb_ringbuffer *buf, int dlen)
-{
-	int len;
-	u32 sync;
-	u16 blen;
-
-	if (!dlen) {
-		wake_up(&buf->queue);
-		return -1;
-	}
-	while (1) {
-		len = dvb_ringbuffer_avail(buf);
-		if (len < 6) {
-			wake_up(&buf->queue);
-			return -1;
-		}
-		sync =  DVB_RINGBUFFER_PEEK(buf, 0) << 24;
-		sync |= DVB_RINGBUFFER_PEEK(buf, 1) << 16;
-		sync |= DVB_RINGBUFFER_PEEK(buf, 2) << 8;
-		sync |= DVB_RINGBUFFER_PEEK(buf, 3);
-
-		if (((sync &~ 0x0f) == 0x000001e0) ||
-		    ((sync &~ 0x1f) == 0x000001c0) ||
-		    (sync == 0x000001bd))
-			break;
-		printk("resync\n");
-		DVB_RINGBUFFER_SKIP(buf, 1);
-	}
-	blen =  DVB_RINGBUFFER_PEEK(buf, 4) << 8;
-	blen |= DVB_RINGBUFFER_PEEK(buf, 5);
-	blen += 6;
-	if (len < blen || blen > dlen) {
-		//printk("buffer empty - avail %d blen %u dlen %d\n", len, blen, dlen);
-		wake_up(&buf->queue);
-		return -1;
-	}
-
-	dvb_ringbuffer_read(buf, dest, (size_t) blen);
-
-	dprintk(2, "pread=0x%08lx, pwrite=0x%08lx\n",
-	       (unsigned long) buf->pread, (unsigned long) buf->pwrite);
-	wake_up(&buf->queue);
-	return blen;
-}
-
-
-int av7110_set_volume(struct av7110 *av7110, int volleft, int volright)
-{
-	int err, vol, val, balance = 0;
-
-	dprintk(2, "av7110:%p, \n", av7110);
-
-	av7110->mixer.volume_left = volleft;
-	av7110->mixer.volume_right = volright;
-
-	switch (av7110->adac_type) {
-	case DVB_ADAC_TI:
-		volleft = (volleft * 256) / 1036;
-		volright = (volright * 256) / 1036;
-		if (volleft > 0x3f)
-			volleft = 0x3f;
-		if (volright > 0x3f)
-			volright = 0x3f;
-		if ((err = SendDAC(av7110, 3, 0x80 + volleft)))
-			return err;
-		return SendDAC(av7110, 4, volright);
-
-	case DVB_ADAC_CRYSTAL:
-		volleft = 127 - volleft / 2;
-		volright = 127 - volright / 2;
-		i2c_writereg(av7110, 0x20, 0x03, volleft);
-		i2c_writereg(av7110, 0x20, 0x04, volright);
-		return 0;
-
-	case DVB_ADAC_MSP34x0:
-		vol  = (volleft > volright) ? volleft : volright;
-		val	= (vol * 0x73 / 255) << 8;
-		if (vol > 0)
-		       balance = ((volright - volleft) * 127) / vol;
-		msp_writereg(av7110, MSP_WR_DSP, 0x0001, balance << 8);
-		msp_writereg(av7110, MSP_WR_DSP, 0x0000, val); /* loudspeaker */
-		msp_writereg(av7110, MSP_WR_DSP, 0x0006, val); /* headphonesr */
-		return 0;
-
-	case DVB_ADAC_MSP34x5:
-		vol = (volleft > volright) ? volleft : volright;
-		val = (vol * 0x73 / 255) << 8;
-		if (vol > 0)
-			balance = ((volright - volleft) * 127) / vol;
-		msp_writereg(av7110, MSP_WR_DSP, 0x0001, balance << 8);
-		msp_writereg(av7110, MSP_WR_DSP, 0x0000, val); /* loudspeaker */
-		return 0;
-	}
-
-	return 0;
-}
-
-int av7110_set_vidmode(struct av7110 *av7110, enum av7110_video_mode mode)
-{
-	int ret;
-	dprintk(2, "av7110:%p, \n", av7110);
-
-	ret = av7110_fw_cmd(av7110, COMTYPE_ENCODER, LoadVidCode, 1, mode);
-
-	if (!ret && !av7110->playing) {
-		ret = ChangePIDs(av7110, av7110->pids[DMX_PES_VIDEO],
-			   av7110->pids[DMX_PES_AUDIO],
-			   av7110->pids[DMX_PES_TELETEXT],
-			   0, av7110->pids[DMX_PES_PCR]);
-		if (!ret)
-			ret = av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, Scan, 0);
-	}
-	return ret;
-}
-
-
-static enum av7110_video_mode sw2mode[16] = {
-	AV7110_VIDEO_MODE_PAL, AV7110_VIDEO_MODE_NTSC,
-	AV7110_VIDEO_MODE_NTSC, AV7110_VIDEO_MODE_PAL,
-	AV7110_VIDEO_MODE_NTSC, AV7110_VIDEO_MODE_NTSC,
-	AV7110_VIDEO_MODE_PAL, AV7110_VIDEO_MODE_NTSC,
-	AV7110_VIDEO_MODE_PAL, AV7110_VIDEO_MODE_PAL,
-	AV7110_VIDEO_MODE_PAL, AV7110_VIDEO_MODE_PAL,
-	AV7110_VIDEO_MODE_PAL, AV7110_VIDEO_MODE_PAL,
-	AV7110_VIDEO_MODE_PAL, AV7110_VIDEO_MODE_PAL,
-};
-
-static int get_video_format(struct av7110 *av7110, u8 *buf, int count)
-{
-	int i;
-	int hsize, vsize;
-	int sw;
-	u8 *p;
-	int ret = 0;
-
-	dprintk(2, "av7110:%p, \n", av7110);
-
-	if (av7110->sinfo)
-		return 0;
-	for (i = 7; i < count - 10; i++) {
-		p = buf + i;
-		if (p[0] || p[1] || p[2] != 0x01 || p[3] != 0xb3)
-			continue;
-		p += 4;
-		hsize = ((p[1] &0xF0) >> 4) | (p[0] << 4);
-		vsize = ((p[1] &0x0F) << 8) | (p[2]);
-		sw = (p[3] & 0x0F);
-		ret = av7110_set_vidmode(av7110, sw2mode[sw]);
-		if (!ret) {
-			dprintk(2, "playback %dx%d fr=%d\n", hsize, vsize, sw);
-			av7110->sinfo = 1;
-		}
-		break;
-	}
-	return ret;
-}
-
-
-/****************************************************************************
- * I/O buffer management and control
- ****************************************************************************/
-
-static inline long aux_ring_buffer_write(struct dvb_ringbuffer *rbuf,
-					 const u8 *buf, unsigned long count)
-{
-	unsigned long todo = count;
-	int free;
-
-	while (todo > 0) {
-		if (dvb_ringbuffer_free(rbuf) < 2048) {
-			if (wait_event_interruptible(rbuf->queue,
-						     (dvb_ringbuffer_free(rbuf) >= 2048)))
-				return count - todo;
-		}
-		free = dvb_ringbuffer_free(rbuf);
-		if (free > todo)
-			free = todo;
-		dvb_ringbuffer_write(rbuf, buf, free);
-		todo -= free;
-		buf += free;
-	}
-
-	return count - todo;
-}
-
-static void play_video_cb(u8 *buf, int count, void *priv)
-{
-	struct av7110 *av7110 = (struct av7110 *) priv;
-	dprintk(2, "av7110:%p, \n", av7110);
-
-	if ((buf[3] & 0xe0) == 0xe0) {
-		get_video_format(av7110, buf, count);
-		aux_ring_buffer_write(&av7110->avout, buf, count);
-	} else
-		aux_ring_buffer_write(&av7110->aout, buf, count);
-}
-
-static void play_audio_cb(u8 *buf, int count, void *priv)
-{
-	struct av7110 *av7110 = (struct av7110 *) priv;
-	dprintk(2, "av7110:%p, \n", av7110);
-
-	aux_ring_buffer_write(&av7110->aout, buf, count);
-}
-
-
-#define FREE_COND_TS (dvb_ringbuffer_free(rb) >= 4096)
-
-static ssize_t ts_play(struct av7110 *av7110, const char __user *buf,
-		       unsigned long count, int nonblock, int type)
-{
-	struct dvb_ringbuffer *rb;
-	u8 *kb;
-	unsigned long todo = count;
-
-	dprintk(2, "%s: type %d cnt %lu\n", __func__, type, count);
-
-	rb = (type) ? &av7110->avout : &av7110->aout;
-	kb = av7110->kbuf[type];
-
-	if (!kb)
-		return -ENOBUFS;
-
-	if (nonblock && !FREE_COND_TS)
-		return -EWOULDBLOCK;
-
-	while (todo >= TS_SIZE) {
-		if (!FREE_COND_TS) {
-			if (nonblock)
-				return count - todo;
-			if (wait_event_interruptible(rb->queue, FREE_COND_TS))
-				return count - todo;
-		}
-		if (copy_from_user(kb, buf, TS_SIZE))
-			return -EFAULT;
-		write_ts_to_decoder(av7110, type, kb, TS_SIZE);
-		todo -= TS_SIZE;
-		buf += TS_SIZE;
-	}
-
-	return count - todo;
-}
-
-
-#define FREE_COND (dvb_ringbuffer_free(&av7110->avout) >= 20 * 1024 && \
-		   dvb_ringbuffer_free(&av7110->aout) >= 20 * 1024)
-
-static ssize_t dvb_play(struct av7110 *av7110, const char __user *buf,
-			unsigned long count, int nonblock, int type)
-{
-	unsigned long todo = count, n;
-	dprintk(2, "av7110:%p, \n", av7110);
-
-	if (!av7110->kbuf[type])
-		return -ENOBUFS;
-
-	if (nonblock && !FREE_COND)
-		return -EWOULDBLOCK;
-
-	while (todo > 0) {
-		if (!FREE_COND) {
-			if (nonblock)
-				return count - todo;
-			if (wait_event_interruptible(av7110->avout.queue,
-						     FREE_COND))
-				return count - todo;
-		}
-		n = todo;
-		if (n > IPACKS * 2)
-			n = IPACKS * 2;
-		if (copy_from_user(av7110->kbuf[type], buf, n))
-			return -EFAULT;
-		av7110_ipack_instant_repack(av7110->kbuf[type], n,
-					    &av7110->ipack[type]);
-		todo -= n;
-		buf += n;
-	}
-	return count - todo;
-}
-
-static ssize_t dvb_play_kernel(struct av7110 *av7110, const u8 *buf,
-			unsigned long count, int nonblock, int type)
-{
-	unsigned long todo = count, n;
-	dprintk(2, "av7110:%p, \n", av7110);
-
-	if (!av7110->kbuf[type])
-		return -ENOBUFS;
-
-	if (nonblock && !FREE_COND)
-		return -EWOULDBLOCK;
-
-	while (todo > 0) {
-		if (!FREE_COND) {
-			if (nonblock)
-				return count - todo;
-			if (wait_event_interruptible(av7110->avout.queue,
-						     FREE_COND))
-				return count - todo;
-		}
-		n = todo;
-		if (n > IPACKS * 2)
-			n = IPACKS * 2;
-		av7110_ipack_instant_repack(buf, n, &av7110->ipack[type]);
-		todo -= n;
-		buf += n;
-	}
-	return count - todo;
-}
-
-static ssize_t dvb_aplay(struct av7110 *av7110, const char __user *buf,
-			 unsigned long count, int nonblock, int type)
-{
-	unsigned long todo = count, n;
-	dprintk(2, "av7110:%p, \n", av7110);
-
-	if (!av7110->kbuf[type])
-		return -ENOBUFS;
-	if (nonblock && dvb_ringbuffer_free(&av7110->aout) < 20 * 1024)
-		return -EWOULDBLOCK;
-
-	while (todo > 0) {
-		if (dvb_ringbuffer_free(&av7110->aout) < 20 * 1024) {
-			if (nonblock)
-				return count - todo;
-			if (wait_event_interruptible(av7110->aout.queue,
-					(dvb_ringbuffer_free(&av7110->aout) >= 20 * 1024)))
-				return count-todo;
-		}
-		n = todo;
-		if (n > IPACKS * 2)
-			n = IPACKS * 2;
-		if (copy_from_user(av7110->kbuf[type], buf, n))
-			return -EFAULT;
-		av7110_ipack_instant_repack(av7110->kbuf[type], n,
-					    &av7110->ipack[type]);
-		todo -= n;
-		buf += n;
-	}
-	return count - todo;
-}
-
-void av7110_p2t_init(struct av7110_p2t *p, struct dvb_demux_feed *feed)
-{
-	memset(p->pes, 0, TS_SIZE);
-	p->counter = 0;
-	p->pos = 0;
-	p->frags = 0;
-	if (feed)
-		p->feed = feed;
-}
-
-static void clear_p2t(struct av7110_p2t *p)
-{
-	memset(p->pes, 0, TS_SIZE);
-//	p->counter = 0;
-	p->pos = 0;
-	p->frags = 0;
-}
-
-
-static int find_pes_header(u8 const *buf, long int length, int *frags)
-{
-	int c = 0;
-	int found = 0;
-
-	*frags = 0;
-
-	while (c < length - 3 && !found) {
-		if (buf[c] == 0x00 && buf[c + 1] == 0x00 &&
-		    buf[c + 2] == 0x01) {
-			switch ( buf[c + 3] ) {
-			case PROG_STREAM_MAP:
-			case PRIVATE_STREAM2:
-			case PROG_STREAM_DIR:
-			case ECM_STREAM     :
-			case EMM_STREAM     :
-			case PADDING_STREAM :
-			case DSM_CC_STREAM  :
-			case ISO13522_STREAM:
-			case PRIVATE_STREAM1:
-			case AUDIO_STREAM_S ... AUDIO_STREAM_E:
-			case VIDEO_STREAM_S ... VIDEO_STREAM_E:
-				found = 1;
-				break;
-
-			default:
-				c++;
-				break;
-			}
-		} else
-			c++;
-	}
-	if (c == length - 3 && !found) {
-		if (buf[length - 1] == 0x00)
-			*frags = 1;
-		if (buf[length - 2] == 0x00 &&
-		    buf[length - 1] == 0x00)
-			*frags = 2;
-		if (buf[length - 3] == 0x00 &&
-		    buf[length - 2] == 0x00 &&
-		    buf[length - 1] == 0x01)
-			*frags = 3;
-		return -1;
-	}
-
-	return c;
-}
-
-void av7110_p2t_write(u8 const *buf, long int length, u16 pid, struct av7110_p2t *p)
-{
-	int c, c2, l, add;
-	int check, rest;
-
-	c = 0;
-	c2 = 0;
-	if (p->frags){
-		check = 0;
-		switch(p->frags) {
-		case 1:
-			if (buf[c] == 0x00 && buf[c + 1] == 0x01) {
-				check = 1;
-				c += 2;
-			}
-			break;
-		case 2:
-			if (buf[c] == 0x01) {
-				check = 1;
-				c++;
-			}
-			break;
-		case 3:
-			check = 1;
-		}
-		if (check) {
-			switch (buf[c]) {
-			case PROG_STREAM_MAP:
-			case PRIVATE_STREAM2:
-			case PROG_STREAM_DIR:
-			case ECM_STREAM     :
-			case EMM_STREAM     :
-			case PADDING_STREAM :
-			case DSM_CC_STREAM  :
-			case ISO13522_STREAM:
-			case PRIVATE_STREAM1:
-			case AUDIO_STREAM_S ... AUDIO_STREAM_E:
-			case VIDEO_STREAM_S ... VIDEO_STREAM_E:
-				p->pes[0] = 0x00;
-				p->pes[1] = 0x00;
-				p->pes[2] = 0x01;
-				p->pes[3] = buf[c];
-				p->pos = 4;
-				memcpy(p->pes + p->pos, buf + c, (TS_SIZE - 4) - p->pos);
-				c += (TS_SIZE - 4) - p->pos;
-				p_to_t(p->pes, (TS_SIZE - 4), pid, &p->counter, p->feed);
-				clear_p2t(p);
-				break;
-
-			default:
-				c = 0;
-				break;
-			}
-		}
-		p->frags = 0;
-	}
-
-	if (p->pos) {
-		c2 = find_pes_header(buf + c, length - c, &p->frags);
-		if (c2 >= 0 && c2 < (TS_SIZE - 4) - p->pos)
-			l = c2+c;
-		else
-			l = (TS_SIZE - 4) - p->pos;
-		memcpy(p->pes + p->pos, buf, l);
-		c += l;
-		p->pos += l;
-		p_to_t(p->pes, p->pos, pid, &p->counter, p->feed);
-		clear_p2t(p);
-	}
-
-	add = 0;
-	while (c < length) {
-		c2 = find_pes_header(buf + c + add, length - c - add, &p->frags);
-		if (c2 >= 0) {
-			c2 += c + add;
-			if (c2 > c){
-				p_to_t(buf + c, c2 - c, pid, &p->counter, p->feed);
-				c = c2;
-				clear_p2t(p);
-				add = 0;
-			} else
-				add = 1;
-		} else {
-			l = length - c;
-			rest = l % (TS_SIZE - 4);
-			l -= rest;
-			p_to_t(buf + c, l, pid, &p->counter, p->feed);
-			memcpy(p->pes, buf + c + l, rest);
-			p->pos = rest;
-			c = length;
-		}
-	}
-}
-
-
-static int write_ts_header2(u16 pid, u8 *counter, int pes_start, u8 *buf, u8 length)
-{
-	int i;
-	int c = 0;
-	int fill;
-	u8 tshead[4] = { 0x47, 0x00, 0x00, 0x10 };
-
-	fill = (TS_SIZE - 4) - length;
-	if (pes_start)
-		tshead[1] = 0x40;
-	if (fill)
-		tshead[3] = 0x30;
-	tshead[1] |= (u8)((pid & 0x1F00) >> 8);
-	tshead[2] |= (u8)(pid & 0x00FF);
-	tshead[3] |= ((*counter)++ & 0x0F);
-	memcpy(buf, tshead, 4);
-	c += 4;
-
-	if (fill) {
-		buf[4] = fill - 1;
-		c++;
-		if (fill > 1) {
-			buf[5] = 0x00;
-			c++;
-		}
-		for (i = 6; i < fill + 4; i++) {
-			buf[i] = 0xFF;
-			c++;
-		}
-	}
-
-	return c;
-}
-
-
-static void p_to_t(u8 const *buf, long int length, u16 pid, u8 *counter,
-		   struct dvb_demux_feed *feed)
-{
-	int l, pes_start;
-	u8 obuf[TS_SIZE];
-	long c = 0;
-
-	pes_start = 0;
-	if (length > 3 &&
-	     buf[0] == 0x00 && buf[1] == 0x00 && buf[2] == 0x01)
-		switch (buf[3]) {
-			case PROG_STREAM_MAP:
-			case PRIVATE_STREAM2:
-			case PROG_STREAM_DIR:
-			case ECM_STREAM     :
-			case EMM_STREAM     :
-			case PADDING_STREAM :
-			case DSM_CC_STREAM  :
-			case ISO13522_STREAM:
-			case PRIVATE_STREAM1:
-			case AUDIO_STREAM_S ... AUDIO_STREAM_E:
-			case VIDEO_STREAM_S ... VIDEO_STREAM_E:
-				pes_start = 1;
-				break;
-
-			default:
-				break;
-		}
-
-	while (c < length) {
-		memset(obuf, 0, TS_SIZE);
-		if (length - c >= (TS_SIZE - 4)){
-			l = write_ts_header2(pid, counter, pes_start,
-					     obuf, (TS_SIZE - 4));
-			memcpy(obuf + l, buf + c, TS_SIZE - l);
-			c += TS_SIZE - l;
-		} else {
-			l = write_ts_header2(pid, counter, pes_start,
-					     obuf, length - c);
-			memcpy(obuf + l, buf + c, TS_SIZE - l);
-			c = length;
-		}
-		feed->cb.ts(obuf, 188, NULL, 0, &feed->feed.ts, DMX_OK);
-		pes_start = 0;
-	}
-}
-
-
-static int write_ts_to_decoder(struct av7110 *av7110, int type, const u8 *buf, size_t len)
-{
-	struct ipack *ipack = &av7110->ipack[type];
-
-	if (buf[1] & TRANS_ERROR) {
-		av7110_ipack_reset(ipack);
-		return -1;
-	}
-
-	if (!(buf[3] & PAYLOAD))
-		return -1;
-
-	if (buf[1] & PAY_START)
-		av7110_ipack_flush(ipack);
-
-	if (buf[3] & ADAPT_FIELD) {
-		len -= buf[4] + 1;
-		buf += buf[4] + 1;
-		if (!len)
-			return 0;
-	}
-
-	av7110_ipack_instant_repack(buf + 4, len - 4, ipack);
-	return 0;
-}
-
-
-int av7110_write_to_decoder(struct dvb_demux_feed *feed, const u8 *buf, size_t len)
-{
-	struct dvb_demux *demux = feed->demux;
-	struct av7110 *av7110 = (struct av7110 *) demux->priv;
-
-	dprintk(2, "av7110:%p, \n", av7110);
-
-	if (av7110->full_ts && demux->dmx.frontend->source != DMX_MEMORY_FE)
-		return 0;
-
-	switch (feed->pes_type) {
-	case 0:
-		if (av7110->audiostate.stream_source == AUDIO_SOURCE_MEMORY)
-			return -EINVAL;
-		break;
-	case 1:
-		if (av7110->videostate.stream_source == VIDEO_SOURCE_MEMORY)
-			return -EINVAL;
-		break;
-	default:
-		return -1;
-	}
-
-	return write_ts_to_decoder(av7110, feed->pes_type, buf, len);
-}
-
-
-
-/******************************************************************************
- * Video MPEG decoder events
- ******************************************************************************/
-void dvb_video_add_event(struct av7110 *av7110, struct video_event *event)
-{
-	struct dvb_video_events *events = &av7110->video_events;
-	int wp;
-
-	spin_lock_bh(&events->lock);
-
-	wp = (events->eventw + 1) % MAX_VIDEO_EVENT;
-	if (wp == events->eventr) {
-		events->overflow = 1;
-		events->eventr = (events->eventr + 1) % MAX_VIDEO_EVENT;
-	}
-
-	//FIXME: timestamp?
-	memcpy(&events->events[events->eventw], event, sizeof(struct video_event));
-	events->eventw = wp;
-
-	spin_unlock_bh(&events->lock);
-
-	wake_up_interruptible(&events->wait_queue);
-}
-
-
-static int dvb_video_get_event (struct av7110 *av7110, struct video_event *event, int flags)
-{
-	struct dvb_video_events *events = &av7110->video_events;
-
-	if (events->overflow) {
-		events->overflow = 0;
-		return -EOVERFLOW;
-	}
-	if (events->eventw == events->eventr) {
-		int ret;
-
-		if (flags & O_NONBLOCK)
-			return -EWOULDBLOCK;
-
-		ret = wait_event_interruptible(events->wait_queue,
-					       events->eventw != events->eventr);
-		if (ret < 0)
-			return ret;
-	}
-
-	spin_lock_bh(&events->lock);
-
-	memcpy(event, &events->events[events->eventr],
-	       sizeof(struct video_event));
-	events->eventr = (events->eventr + 1) % MAX_VIDEO_EVENT;
-
-	spin_unlock_bh(&events->lock);
-
-	return 0;
-}
-
-
-/******************************************************************************
- * DVB device file operations
- ******************************************************************************/
-
-static unsigned int dvb_video_poll(struct file *file, poll_table *wait)
-{
-	struct dvb_device *dvbdev = file->private_data;
-	struct av7110 *av7110 = dvbdev->priv;
-	unsigned int mask = 0;
-
-	dprintk(2, "av7110:%p, \n", av7110);
-
-	if ((file->f_flags & O_ACCMODE) != O_RDONLY)
-		poll_wait(file, &av7110->avout.queue, wait);
-
-	poll_wait(file, &av7110->video_events.wait_queue, wait);
-
-	if (av7110->video_events.eventw != av7110->video_events.eventr)
-		mask = POLLPRI;
-
-	if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
-		if (av7110->playing) {
-			if (FREE_COND)
-				mask |= (POLLOUT | POLLWRNORM);
-			} else /* if not playing: may play if asked for */
-				mask |= (POLLOUT | POLLWRNORM);
-	}
-
-	return mask;
-}
-
-static ssize_t dvb_video_write(struct file *file, const char __user *buf,
-			       size_t count, loff_t *ppos)
-{
-	struct dvb_device *dvbdev = file->private_data;
-	struct av7110 *av7110 = dvbdev->priv;
-	unsigned char c;
-
-	dprintk(2, "av7110:%p, \n", av7110);
-
-	if ((file->f_flags & O_ACCMODE) == O_RDONLY)
-		return -EPERM;
-
-	if (av7110->videostate.stream_source != VIDEO_SOURCE_MEMORY)
-		return -EPERM;
-
-	if (get_user(c, buf))
-		return -EFAULT;
-	if (c == 0x47 && count % TS_SIZE == 0)
-		return ts_play(av7110, buf, count, file->f_flags & O_NONBLOCK, 1);
-	else
-		return dvb_play(av7110, buf, count, file->f_flags & O_NONBLOCK, 1);
-}
-
-static unsigned int dvb_audio_poll(struct file *file, poll_table *wait)
-{
-	struct dvb_device *dvbdev = file->private_data;
-	struct av7110 *av7110 = dvbdev->priv;
-	unsigned int mask = 0;
-
-	dprintk(2, "av7110:%p, \n", av7110);
-
-	poll_wait(file, &av7110->aout.queue, wait);
-
-	if (av7110->playing) {
-		if (dvb_ringbuffer_free(&av7110->aout) >= 20 * 1024)
-			mask |= (POLLOUT | POLLWRNORM);
-	} else /* if not playing: may play if asked for */
-		mask = (POLLOUT | POLLWRNORM);
-
-	return mask;
-}
-
-static ssize_t dvb_audio_write(struct file *file, const char __user *buf,
-			       size_t count, loff_t *ppos)
-{
-	struct dvb_device *dvbdev = file->private_data;
-	struct av7110 *av7110 = dvbdev->priv;
-	unsigned char c;
-
-	dprintk(2, "av7110:%p, \n", av7110);
-
-	if (av7110->audiostate.stream_source != AUDIO_SOURCE_MEMORY) {
-		printk(KERN_ERR "not audio source memory\n");
-		return -EPERM;
-	}
-
-	if (get_user(c, buf))
-		return -EFAULT;
-	if (c == 0x47 && count % TS_SIZE == 0)
-		return ts_play(av7110, buf, count, file->f_flags & O_NONBLOCK, 0);
-	else
-		return dvb_aplay(av7110, buf, count, file->f_flags & O_NONBLOCK, 0);
-}
-
-static u8 iframe_header[] = { 0x00, 0x00, 0x01, 0xe0, 0x00, 0x00, 0x80, 0x00, 0x00 };
-
-#define MIN_IFRAME 400000
-
-static int play_iframe(struct av7110 *av7110, char __user *buf, unsigned int len, int nonblock)
-{
-	unsigned i, n;
-	int progressive = 0;
-	int match = 0;
-
-	dprintk(2, "av7110:%p, \n", av7110);
-
-	if (!(av7110->playing & RP_VIDEO)) {
-		if (av7110_av_start_play(av7110, RP_VIDEO) < 0)
-			return -EBUSY;
-	}
-
-	/* search in buf for instances of 00 00 01 b5 1? */
-	for (i = 0; i < len; i++) {
-		unsigned char c;
-		if (get_user(c, buf + i))
-			return -EFAULT;
-		if (match == 5) {
-			progressive = c & 0x08;
-			match = 0;
-		}
-		if (c == 0x00) {
-			match = (match == 1 || match == 2) ? 2 : 1;
-			continue;
-		}
-		switch (match++) {
-		case 2: if (c == 0x01)
-				continue;
-			break;
-		case 3: if (c == 0xb5)
-				continue;
-			break;
-		case 4: if ((c & 0xf0) == 0x10)
-				continue;
-			break;
-		}
-		match = 0;
-	}
-
-	/* setting n always > 1, fixes problems when playing stillframes
-	   consisting of I- and P-Frames */
-	n = MIN_IFRAME / len + 1;
-
-	/* FIXME: nonblock? */
-	dvb_play_kernel(av7110, iframe_header, sizeof(iframe_header), 0, 1);
-
-	for (i = 0; i < n; i++)
-		dvb_play(av7110, buf, len, 0, 1);
-
-	av7110_ipack_flush(&av7110->ipack[1]);
-
-	if (progressive)
-		return vidcom(av7110, AV_VIDEO_CMD_FREEZE, 1);
-	else
-		return 0;
-}
-
-
-static int dvb_video_ioctl(struct file *file,
-			   unsigned int cmd, void *parg)
-{
-	struct dvb_device *dvbdev = file->private_data;
-	struct av7110 *av7110 = dvbdev->priv;
-	unsigned long arg = (unsigned long) parg;
-	int ret = 0;
-
-	dprintk(1, "av7110:%p, cmd=%04x\n", av7110,cmd);
-
-	if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
-		if ( cmd != VIDEO_GET_STATUS && cmd != VIDEO_GET_EVENT &&
-		     cmd != VIDEO_GET_SIZE ) {
-			return -EPERM;
-		}
-	}
-
-	switch (cmd) {
-	case VIDEO_STOP:
-		av7110->videostate.play_state = VIDEO_STOPPED;
-		if (av7110->videostate.stream_source == VIDEO_SOURCE_MEMORY)
-			ret = av7110_av_stop(av7110, RP_VIDEO);
-		else
-			ret = vidcom(av7110, AV_VIDEO_CMD_STOP,
-			       av7110->videostate.video_blank ? 0 : 1);
-		if (!ret)
-			av7110->trickmode = TRICK_NONE;
-		break;
-
-	case VIDEO_PLAY:
-		av7110->trickmode = TRICK_NONE;
-		if (av7110->videostate.play_state == VIDEO_FREEZED) {
-			av7110->videostate.play_state = VIDEO_PLAYING;
-			ret = vidcom(av7110, AV_VIDEO_CMD_PLAY, 0);
-			if (ret)
-				break;
-		}
-		if (av7110->videostate.stream_source == VIDEO_SOURCE_MEMORY) {
-			if (av7110->playing == RP_AV) {
-				ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Stop, 0);
-				if (ret)
-					break;
-				av7110->playing &= ~RP_VIDEO;
-			}
-			ret = av7110_av_start_play(av7110, RP_VIDEO);
-		}
-		if (!ret)
-			ret = vidcom(av7110, AV_VIDEO_CMD_PLAY, 0);
-		if (!ret)
-			av7110->videostate.play_state = VIDEO_PLAYING;
-		break;
-
-	case VIDEO_FREEZE:
-		av7110->videostate.play_state = VIDEO_FREEZED;
-		if (av7110->playing & RP_VIDEO)
-			ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Pause, 0);
-		else
-			ret = vidcom(av7110, AV_VIDEO_CMD_FREEZE, 1);
-		if (!ret)
-			av7110->trickmode = TRICK_FREEZE;
-		break;
-
-	case VIDEO_CONTINUE:
-		if (av7110->playing & RP_VIDEO)
-			ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Continue, 0);
-		if (!ret)
-			ret = vidcom(av7110, AV_VIDEO_CMD_PLAY, 0);
-		if (!ret) {
-			av7110->videostate.play_state = VIDEO_PLAYING;
-			av7110->trickmode = TRICK_NONE;
-		}
-		break;
-
-	case VIDEO_SELECT_SOURCE:
-		av7110->videostate.stream_source = (video_stream_source_t) arg;
-		break;
-
-	case VIDEO_SET_BLANK:
-		av7110->videostate.video_blank = (int) arg;
-		break;
-
-	case VIDEO_GET_STATUS:
-		memcpy(parg, &av7110->videostate, sizeof(struct video_status));
-		break;
-
-	case VIDEO_GET_EVENT:
-		ret = dvb_video_get_event(av7110, parg, file->f_flags);
-		break;
-
-	case VIDEO_GET_SIZE:
-		memcpy(parg, &av7110->video_size, sizeof(video_size_t));
-		break;
-
-	case VIDEO_SET_DISPLAY_FORMAT:
-	{
-		video_displayformat_t format = (video_displayformat_t) arg;
-		switch (format) {
-		case VIDEO_PAN_SCAN:
-			av7110->display_panscan = VID_PAN_SCAN_PREF;
-			break;
-		case VIDEO_LETTER_BOX:
-			av7110->display_panscan = VID_VC_AND_PS_PREF;
-			break;
-		case VIDEO_CENTER_CUT_OUT:
-			av7110->display_panscan = VID_CENTRE_CUT_PREF;
-			break;
-		default:
-			ret = -EINVAL;
-		}
-		if (ret < 0)
-			break;
-		av7110->videostate.display_format = format;
-		ret = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetPanScanType,
-				    1, av7110->display_panscan);
-		break;
-	}
-
-	case VIDEO_SET_FORMAT:
-		if (arg > 1) {
-			ret = -EINVAL;
-			break;
-		}
-		av7110->display_ar = arg;
-		ret = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetMonitorType,
-				    1, (u16) arg);
-		break;
-
-	case VIDEO_STILLPICTURE:
-	{
-		struct video_still_picture *pic =
-			(struct video_still_picture *) parg;
-		av7110->videostate.stream_source = VIDEO_SOURCE_MEMORY;
-		dvb_ringbuffer_flush_spinlock_wakeup(&av7110->avout);
-		ret = play_iframe(av7110, pic->iFrame, pic->size,
-				  file->f_flags & O_NONBLOCK);
-		break;
-	}
-
-	case VIDEO_FAST_FORWARD:
-		//note: arg is ignored by firmware
-		if (av7110->playing & RP_VIDEO)
-			ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY,
-					    __Scan_I, 2, AV_PES, 0);
-		else
-			ret = vidcom(av7110, AV_VIDEO_CMD_FFWD, arg);
-		if (!ret) {
-			av7110->trickmode = TRICK_FAST;
-			av7110->videostate.play_state = VIDEO_PLAYING;
-		}
-		break;
-
-	case VIDEO_SLOWMOTION:
-		if (av7110->playing&RP_VIDEO) {
-			if (av7110->trickmode != TRICK_SLOW)
-				ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY, __Slow, 2, 0, 0);
-			if (!ret)
-				ret = vidcom(av7110, AV_VIDEO_CMD_SLOW, arg);
-		} else {
-			ret = vidcom(av7110, AV_VIDEO_CMD_PLAY, 0);
-			if (!ret)
-				ret = vidcom(av7110, AV_VIDEO_CMD_STOP, 0);
-			if (!ret)
-				ret = vidcom(av7110, AV_VIDEO_CMD_SLOW, arg);
-		}
-		if (!ret) {
-			av7110->trickmode = TRICK_SLOW;
-			av7110->videostate.play_state = VIDEO_PLAYING;
-		}
-		break;
-
-	case VIDEO_GET_CAPABILITIES:
-		*(int *)parg = VIDEO_CAP_MPEG1 | VIDEO_CAP_MPEG2 |
-			VIDEO_CAP_SYS | VIDEO_CAP_PROG;
-		break;
-
-	case VIDEO_CLEAR_BUFFER:
-		dvb_ringbuffer_flush_spinlock_wakeup(&av7110->avout);
-		av7110_ipack_reset(&av7110->ipack[1]);
-		if (av7110->playing == RP_AV) {
-			ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY,
-					    __Play, 2, AV_PES, 0);
-			if (ret)
-				break;
-			if (av7110->trickmode == TRICK_FAST)
-				ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY,
-						    __Scan_I, 2, AV_PES, 0);
-			if (av7110->trickmode == TRICK_SLOW) {
-				ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY,
-						    __Slow, 2, 0, 0);
-				if (!ret)
-					ret = vidcom(av7110, AV_VIDEO_CMD_SLOW, arg);
-			}
-			if (av7110->trickmode == TRICK_FREEZE)
-				ret = vidcom(av7110, AV_VIDEO_CMD_STOP, 1);
-		}
-		break;
-
-	case VIDEO_SET_STREAMTYPE:
-		break;
-
-	default:
-		ret = -ENOIOCTLCMD;
-		break;
-	}
-
-	return ret;
-}
-
-static int dvb_audio_ioctl(struct file *file,
-			   unsigned int cmd, void *parg)
-{
-	struct dvb_device *dvbdev = file->private_data;
-	struct av7110 *av7110 = dvbdev->priv;
-	unsigned long arg = (unsigned long) parg;
-	int ret = 0;
-
-	dprintk(1, "av7110:%p, cmd=%04x\n", av7110,cmd);
-
-	if (((file->f_flags & O_ACCMODE) == O_RDONLY) &&
-	    (cmd != AUDIO_GET_STATUS))
-		return -EPERM;
-
-	switch (cmd) {
-	case AUDIO_STOP:
-		if (av7110->audiostate.stream_source == AUDIO_SOURCE_MEMORY)
-			ret = av7110_av_stop(av7110, RP_AUDIO);
-		else
-			ret = audcom(av7110, AUDIO_CMD_MUTE);
-		if (!ret)
-			av7110->audiostate.play_state = AUDIO_STOPPED;
-		break;
-
-	case AUDIO_PLAY:
-		if (av7110->audiostate.stream_source == AUDIO_SOURCE_MEMORY)
-			ret = av7110_av_start_play(av7110, RP_AUDIO);
-		if (!ret)
-			ret = audcom(av7110, AUDIO_CMD_UNMUTE);
-		if (!ret)
-			av7110->audiostate.play_state = AUDIO_PLAYING;
-		break;
-
-	case AUDIO_PAUSE:
-		ret = audcom(av7110, AUDIO_CMD_MUTE);
-		if (!ret)
-			av7110->audiostate.play_state = AUDIO_PAUSED;
-		break;
-
-	case AUDIO_CONTINUE:
-		if (av7110->audiostate.play_state == AUDIO_PAUSED) {
-			av7110->audiostate.play_state = AUDIO_PLAYING;
-			ret = audcom(av7110, AUDIO_CMD_UNMUTE | AUDIO_CMD_PCM16);
-		}
-		break;
-
-	case AUDIO_SELECT_SOURCE:
-		av7110->audiostate.stream_source = (audio_stream_source_t) arg;
-		break;
-
-	case AUDIO_SET_MUTE:
-	{
-		ret = audcom(av7110, arg ? AUDIO_CMD_MUTE : AUDIO_CMD_UNMUTE);
-		if (!ret)
-			av7110->audiostate.mute_state = (int) arg;
-		break;
-	}
-
-	case AUDIO_SET_AV_SYNC:
-		av7110->audiostate.AV_sync_state = (int) arg;
-		ret = audcom(av7110, arg ? AUDIO_CMD_SYNC_ON : AUDIO_CMD_SYNC_OFF);
-		break;
-
-	case AUDIO_SET_BYPASS_MODE:
-		if (FW_VERSION(av7110->arm_app) < 0x2621)
-			ret = -EINVAL;
-		av7110->audiostate.bypass_mode = (int)arg;
-		break;
-
-	case AUDIO_CHANNEL_SELECT:
-		av7110->audiostate.channel_select = (audio_channel_select_t) arg;
-		switch(av7110->audiostate.channel_select) {
-		case AUDIO_STEREO:
-			ret = audcom(av7110, AUDIO_CMD_STEREO);
-			if (!ret) {
-				if (av7110->adac_type == DVB_ADAC_CRYSTAL)
-					i2c_writereg(av7110, 0x20, 0x02, 0x49);
-				else if (av7110->adac_type == DVB_ADAC_MSP34x5)
-					msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0220);
-			}
-			break;
-		case AUDIO_MONO_LEFT:
-			ret = audcom(av7110, AUDIO_CMD_MONO_L);
-			if (!ret) {
-				if (av7110->adac_type == DVB_ADAC_CRYSTAL)
-					i2c_writereg(av7110, 0x20, 0x02, 0x4a);
-				else if (av7110->adac_type == DVB_ADAC_MSP34x5)
-					msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0200);
-			}
-			break;
-		case AUDIO_MONO_RIGHT:
-			ret = audcom(av7110, AUDIO_CMD_MONO_R);
-			if (!ret) {
-				if (av7110->adac_type == DVB_ADAC_CRYSTAL)
-					i2c_writereg(av7110, 0x20, 0x02, 0x45);
-				else if (av7110->adac_type == DVB_ADAC_MSP34x5)
-					msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0210);
-			}
-			break;
-		default:
-			ret = -EINVAL;
-			break;
-		}
-		break;
-
-	case AUDIO_GET_STATUS:
-		memcpy(parg, &av7110->audiostate, sizeof(struct audio_status));
-		break;
-
-	case AUDIO_GET_CAPABILITIES:
-		if (FW_VERSION(av7110->arm_app) < 0x2621)
-			*(unsigned int *)parg = AUDIO_CAP_LPCM | AUDIO_CAP_MP1 | AUDIO_CAP_MP2;
-		else
-			*(unsigned int *)parg = AUDIO_CAP_LPCM | AUDIO_CAP_DTS | AUDIO_CAP_AC3 |
-						AUDIO_CAP_MP1 | AUDIO_CAP_MP2;
-		break;
-
-	case AUDIO_CLEAR_BUFFER:
-		dvb_ringbuffer_flush_spinlock_wakeup(&av7110->aout);
-		av7110_ipack_reset(&av7110->ipack[0]);
-		if (av7110->playing == RP_AV)
-			ret = av7110_fw_cmd(av7110, COMTYPE_REC_PLAY,
-					    __Play, 2, AV_PES, 0);
-		break;
-
-	case AUDIO_SET_ID:
-		break;
-
-	case AUDIO_SET_MIXER:
-	{
-		struct audio_mixer *amix = (struct audio_mixer *)parg;
-		ret = av7110_set_volume(av7110, amix->volume_left, amix->volume_right);
-		break;
-	}
-
-	case AUDIO_SET_STREAMTYPE:
-		break;
-
-	default:
-		ret = -ENOIOCTLCMD;
-	}
-
-	return ret;
-}
-
-
-static int dvb_video_open(struct inode *inode, struct file *file)
-{
-	struct dvb_device *dvbdev = file->private_data;
-	struct av7110 *av7110 = dvbdev->priv;
-	int err;
-
-	dprintk(2, "av7110:%p, \n", av7110);
-
-	if ((err = dvb_generic_open(inode, file)) < 0)
-		return err;
-
-	if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
-		dvb_ringbuffer_flush_spinlock_wakeup(&av7110->aout);
-		dvb_ringbuffer_flush_spinlock_wakeup(&av7110->avout);
-		av7110->video_blank = 1;
-		av7110->audiostate.AV_sync_state = 1;
-		av7110->videostate.stream_source = VIDEO_SOURCE_DEMUX;
-
-		/*  empty event queue */
-		av7110->video_events.eventr = av7110->video_events.eventw = 0;
-	}
-
-	return 0;
-}
-
-static int dvb_video_release(struct inode *inode, struct file *file)
-{
-	struct dvb_device *dvbdev = file->private_data;
-	struct av7110 *av7110 = dvbdev->priv;
-
-	dprintk(2, "av7110:%p, \n", av7110);
-
-	if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
-		av7110_av_stop(av7110, RP_VIDEO);
-	}
-
-	return dvb_generic_release(inode, file);
-}
-
-static int dvb_audio_open(struct inode *inode, struct file *file)
-{
-	struct dvb_device *dvbdev = file->private_data;
-	struct av7110 *av7110 = dvbdev->priv;
-	int err = dvb_generic_open(inode, file);
-
-	dprintk(2, "av7110:%p, \n", av7110);
-
-	if (err < 0)
-		return err;
-	dvb_ringbuffer_flush_spinlock_wakeup(&av7110->aout);
-	av7110->audiostate.stream_source = AUDIO_SOURCE_DEMUX;
-	return 0;
-}
-
-static int dvb_audio_release(struct inode *inode, struct file *file)
-{
-	struct dvb_device *dvbdev = file->private_data;
-	struct av7110 *av7110 = dvbdev->priv;
-
-	dprintk(2, "av7110:%p, \n", av7110);
-
-	av7110_av_stop(av7110, RP_AUDIO);
-	return dvb_generic_release(inode, file);
-}
-
-
-
-/******************************************************************************
- * driver registration
- ******************************************************************************/
-
-static const struct file_operations dvb_video_fops = {
-	.owner		= THIS_MODULE,
-	.write		= dvb_video_write,
-	.unlocked_ioctl	= dvb_generic_ioctl,
-	.open		= dvb_video_open,
-	.release	= dvb_video_release,
-	.poll		= dvb_video_poll,
-	.llseek		= noop_llseek,
-};
-
-static struct dvb_device dvbdev_video = {
-	.priv		= NULL,
-	.users		= 6,
-	.readers	= 5,	/* arbitrary */
-	.writers	= 1,
-	.fops		= &dvb_video_fops,
-	.kernel_ioctl	= dvb_video_ioctl,
-};
-
-static const struct file_operations dvb_audio_fops = {
-	.owner		= THIS_MODULE,
-	.write		= dvb_audio_write,
-	.unlocked_ioctl	= dvb_generic_ioctl,
-	.open		= dvb_audio_open,
-	.release	= dvb_audio_release,
-	.poll		= dvb_audio_poll,
-	.llseek		= noop_llseek,
-};
-
-static struct dvb_device dvbdev_audio = {
-	.priv		= NULL,
-	.users		= 1,
-	.writers	= 1,
-	.fops		= &dvb_audio_fops,
-	.kernel_ioctl	= dvb_audio_ioctl,
-};
-
-
-int av7110_av_register(struct av7110 *av7110)
-{
-	av7110->audiostate.AV_sync_state = 0;
-	av7110->audiostate.mute_state = 0;
-	av7110->audiostate.play_state = AUDIO_STOPPED;
-	av7110->audiostate.stream_source = AUDIO_SOURCE_DEMUX;
-	av7110->audiostate.channel_select = AUDIO_STEREO;
-	av7110->audiostate.bypass_mode = 0;
-
-	av7110->videostate.video_blank = 0;
-	av7110->videostate.play_state = VIDEO_STOPPED;
-	av7110->videostate.stream_source = VIDEO_SOURCE_DEMUX;
-	av7110->videostate.video_format = VIDEO_FORMAT_4_3;
-	av7110->videostate.display_format = VIDEO_LETTER_BOX;
-	av7110->display_ar = VIDEO_FORMAT_4_3;
-	av7110->display_panscan = VID_VC_AND_PS_PREF;
-
-	init_waitqueue_head(&av7110->video_events.wait_queue);
-	spin_lock_init(&av7110->video_events.lock);
-	av7110->video_events.eventw = av7110->video_events.eventr = 0;
-	av7110->video_events.overflow = 0;
-	memset(&av7110->video_size, 0, sizeof (video_size_t));
-
-	dvb_register_device(&av7110->dvb_adapter, &av7110->video_dev,
-			    &dvbdev_video, av7110, DVB_DEVICE_VIDEO);
-
-	dvb_register_device(&av7110->dvb_adapter, &av7110->audio_dev,
-			    &dvbdev_audio, av7110, DVB_DEVICE_AUDIO);
-
-	return 0;
-}
-
-void av7110_av_unregister(struct av7110 *av7110)
-{
-	dvb_unregister_device(av7110->audio_dev);
-	dvb_unregister_device(av7110->video_dev);
-}
-
-int av7110_av_init(struct av7110 *av7110)
-{
-	void (*play[])(u8 *, int, void *) = { play_audio_cb, play_video_cb };
-	int i, ret;
-
-	for (i = 0; i < 2; i++) {
-		struct ipack *ipack = av7110->ipack + i;
-
-		ret = av7110_ipack_init(ipack, IPACKS, play[i]);
-		if (ret < 0) {
-			if (i)
-				av7110_ipack_free(--ipack);
-			goto out;
-		}
-		ipack->data = av7110;
-	}
-
-	dvb_ringbuffer_init(&av7110->avout, av7110->iobuf, AVOUTLEN);
-	dvb_ringbuffer_init(&av7110->aout, av7110->iobuf + AVOUTLEN, AOUTLEN);
-
-	av7110->kbuf[0] = (u8 *)(av7110->iobuf + AVOUTLEN + AOUTLEN + BMPLEN);
-	av7110->kbuf[1] = av7110->kbuf[0] + 2 * IPACKS;
-out:
-	return ret;
-}
-
-void av7110_av_exit(struct av7110 *av7110)
-{
-	av7110_ipack_free(&av7110->ipack[0]);
-	av7110_ipack_free(&av7110->ipack[1]);
-}
diff --git a/drivers/media/dvb/ttpci/av7110_av.h b/drivers/media/dvb/ttpci/av7110_av.h
deleted file mode 100644
index 5f02ef8..0000000
--- a/drivers/media/dvb/ttpci/av7110_av.h
+++ /dev/null
@@ -1,30 +0,0 @@
-#ifndef _AV7110_AV_H_
-#define _AV7110_AV_H_
-
-struct av7110;
-
-extern int av7110_set_vidmode(struct av7110 *av7110,
-			      enum av7110_video_mode mode);
-
-extern int av7110_record_cb(struct dvb_filter_pes2ts *p2t, u8 *buf, size_t len);
-extern int av7110_pes_play(void *dest, struct dvb_ringbuffer *buf, int dlen);
-extern int av7110_write_to_decoder(struct dvb_demux_feed *feed, const u8 *buf, size_t len);
-
-extern int av7110_set_volume(struct av7110 *av7110, int volleft, int volright);
-extern int av7110_av_stop(struct av7110 *av7110, int av);
-extern int av7110_av_start_record(struct av7110 *av7110, int av,
-			  struct dvb_demux_feed *dvbdmxfeed);
-extern int av7110_av_start_play(struct av7110 *av7110, int av);
-
-extern void dvb_video_add_event(struct av7110 *av7110, struct video_event *event);
-
-extern void av7110_p2t_init(struct av7110_p2t *p, struct dvb_demux_feed *feed);
-extern void av7110_p2t_write(u8 const *buf, long int length, u16 pid, struct av7110_p2t *p);
-
-extern int av7110_av_register(struct av7110 *av7110);
-extern void av7110_av_unregister(struct av7110 *av7110);
-extern int av7110_av_init(struct av7110 *av7110);
-extern void av7110_av_exit(struct av7110 *av7110);
-
-
-#endif /* _AV7110_AV_H_ */
diff --git a/drivers/media/dvb/ttpci/av7110_ca.c b/drivers/media/dvb/ttpci/av7110_ca.c
deleted file mode 100644
index 9fc1dd0..0000000
--- a/drivers/media/dvb/ttpci/av7110_ca.c
+++ /dev/null
@@ -1,387 +0,0 @@
-/*
- * av7110_ca.c: CA and CI stuff
- *
- * Copyright (C) 1999-2002 Ralph  Metzler
- *                       & Marcus Metzler for convergence integrated media GmbH
- *
- * originally based on code by:
- * Copyright (C) 1998,1999 Christian Theiss <mistert@rz.fh-augsburg.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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- *
- *
- * the project's page is at http://www.linuxtv.org/ 
- */
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/delay.h>
-#include <linux/fs.h>
-#include <linux/timer.h>
-#include <linux/poll.h>
-#include <linux/gfp.h>
-
-#include "av7110.h"
-#include "av7110_hw.h"
-#include "av7110_ca.h"
-
-
-void CI_handle(struct av7110 *av7110, u8 *data, u16 len)
-{
-	dprintk(8, "av7110:%p\n",av7110);
-
-	if (len < 3)
-		return;
-	switch (data[0]) {
-	case CI_MSG_CI_INFO:
-		if (data[2] != 1 && data[2] != 2)
-			break;
-		switch (data[1]) {
-		case 0:
-			av7110->ci_slot[data[2] - 1].flags = 0;
-			break;
-		case 1:
-			av7110->ci_slot[data[2] - 1].flags |= CA_CI_MODULE_PRESENT;
-			break;
-		case 2:
-			av7110->ci_slot[data[2] - 1].flags |= CA_CI_MODULE_READY;
-			break;
-		}
-		break;
-	case CI_SWITCH_PRG_REPLY:
-		//av7110->ci_stat=data[1];
-		break;
-	default:
-		break;
-	}
-}
-
-
-void ci_get_data(struct dvb_ringbuffer *cibuf, u8 *data, int len)
-{
-	if (dvb_ringbuffer_free(cibuf) < len + 2)
-		return;
-
-	DVB_RINGBUFFER_WRITE_BYTE(cibuf, len >> 8);
-	DVB_RINGBUFFER_WRITE_BYTE(cibuf, len & 0xff);
-	dvb_ringbuffer_write(cibuf, data, len);
-	wake_up_interruptible(&cibuf->queue);
-}
-
-
-/******************************************************************************
- * CI link layer file ops
- ******************************************************************************/
-
-static int ci_ll_init(struct dvb_ringbuffer *cirbuf, struct dvb_ringbuffer *ciwbuf, int size)
-{
-	struct dvb_ringbuffer *tab[] = { cirbuf, ciwbuf, NULL }, **p;
-	void *data;
-
-	for (p = tab; *p; p++) {
-		data = vmalloc(size);
-		if (!data) {
-			while (p-- != tab) {
-				vfree(p[0]->data);
-				p[0]->data = NULL;
-			}
-			return -ENOMEM;
-		}
-		dvb_ringbuffer_init(*p, data, size);
-	}
-	return 0;
-}
-
-static void ci_ll_flush(struct dvb_ringbuffer *cirbuf, struct dvb_ringbuffer *ciwbuf)
-{
-	dvb_ringbuffer_flush_spinlock_wakeup(cirbuf);
-	dvb_ringbuffer_flush_spinlock_wakeup(ciwbuf);
-}
-
-static void ci_ll_release(struct dvb_ringbuffer *cirbuf, struct dvb_ringbuffer *ciwbuf)
-{
-	vfree(cirbuf->data);
-	cirbuf->data = NULL;
-	vfree(ciwbuf->data);
-	ciwbuf->data = NULL;
-}
-
-static int ci_ll_reset(struct dvb_ringbuffer *cibuf, struct file *file,
-		       int slots, ca_slot_info_t *slot)
-{
-	int i;
-	int len = 0;
-	u8 msg[8] = { 0x00, 0x06, 0x00, 0x00, 0xff, 0x02, 0x00, 0x00 };
-
-	for (i = 0; i < 2; i++) {
-		if (slots & (1 << i))
-			len += 8;
-	}
-
-	if (dvb_ringbuffer_free(cibuf) < len)
-		return -EBUSY;
-
-	for (i = 0; i < 2; i++) {
-		if (slots & (1 << i)) {
-			msg[2] = i;
-			dvb_ringbuffer_write(cibuf, msg, 8);
-			slot[i].flags = 0;
-		}
-	}
-
-	return 0;
-}
-
-static ssize_t ci_ll_write(struct dvb_ringbuffer *cibuf, struct file *file,
-			   const char __user *buf, size_t count, loff_t *ppos)
-{
-	int free;
-	int non_blocking = file->f_flags & O_NONBLOCK;
-	u8 *page = (u8 *)__get_free_page(GFP_USER);
-	int res;
-
-	if (!page)
-		return -ENOMEM;
-
-	res = -EINVAL;
-	if (count > 2048)
-		goto out;
-
-	res = -EFAULT;
-	if (copy_from_user(page, buf, count))
-		goto out;
-
-	free = dvb_ringbuffer_free(cibuf);
-	if (count + 2 > free) {
-		res = -EWOULDBLOCK;
-		if (non_blocking)
-			goto out;
-		res = -ERESTARTSYS;
-		if (wait_event_interruptible(cibuf->queue,
-					     (dvb_ringbuffer_free(cibuf) >= count + 2)))
-			goto out;
-	}
-
-	DVB_RINGBUFFER_WRITE_BYTE(cibuf, count >> 8);
-	DVB_RINGBUFFER_WRITE_BYTE(cibuf, count & 0xff);
-
-	res = dvb_ringbuffer_write(cibuf, page, count);
-out:
-	free_page((unsigned long)page);
-	return res;
-}
-
-static ssize_t ci_ll_read(struct dvb_ringbuffer *cibuf, struct file *file,
-			  char __user *buf, size_t count, loff_t *ppos)
-{
-	int avail;
-	int non_blocking = file->f_flags & O_NONBLOCK;
-	ssize_t len;
-
-	if (!cibuf->data || !count)
-		return 0;
-	if (non_blocking && (dvb_ringbuffer_empty(cibuf)))
-		return -EWOULDBLOCK;
-	if (wait_event_interruptible(cibuf->queue,
-				     !dvb_ringbuffer_empty(cibuf)))
-		return -ERESTARTSYS;
-	avail = dvb_ringbuffer_avail(cibuf);
-	if (avail < 4)
-		return 0;
-	len = DVB_RINGBUFFER_PEEK(cibuf, 0) << 8;
-	len |= DVB_RINGBUFFER_PEEK(cibuf, 1);
-	if (avail < len + 2 || count < len)
-		return -EINVAL;
-	DVB_RINGBUFFER_SKIP(cibuf, 2);
-
-	return dvb_ringbuffer_read_user(cibuf, buf, len);
-}
-
-static int dvb_ca_open(struct inode *inode, struct file *file)
-{
-	struct dvb_device *dvbdev = file->private_data;
-	struct av7110 *av7110 = dvbdev->priv;
-	int err = dvb_generic_open(inode, file);
-
-	dprintk(8, "av7110:%p\n",av7110);
-
-	if (err < 0)
-		return err;
-	ci_ll_flush(&av7110->ci_rbuffer, &av7110->ci_wbuffer);
-	return 0;
-}
-
-static unsigned int dvb_ca_poll (struct file *file, poll_table *wait)
-{
-	struct dvb_device *dvbdev = file->private_data;
-	struct av7110 *av7110 = dvbdev->priv;
-	struct dvb_ringbuffer *rbuf = &av7110->ci_rbuffer;
-	struct dvb_ringbuffer *wbuf = &av7110->ci_wbuffer;
-	unsigned int mask = 0;
-
-	dprintk(8, "av7110:%p\n",av7110);
-
-	poll_wait(file, &rbuf->queue, wait);
-	poll_wait(file, &wbuf->queue, wait);
-
-	if (!dvb_ringbuffer_empty(rbuf))
-		mask |= (POLLIN | POLLRDNORM);
-
-	if (dvb_ringbuffer_free(wbuf) > 1024)
-		mask |= (POLLOUT | POLLWRNORM);
-
-	return mask;
-}
-
-static int dvb_ca_ioctl(struct file *file, unsigned int cmd, void *parg)
-{
-	struct dvb_device *dvbdev = file->private_data;
-	struct av7110 *av7110 = dvbdev->priv;
-	unsigned long arg = (unsigned long) parg;
-
-	dprintk(8, "av7110:%p\n",av7110);
-
-	switch (cmd) {
-	case CA_RESET:
-		return ci_ll_reset(&av7110->ci_wbuffer, file, arg, &av7110->ci_slot[0]);
-		break;
-	case CA_GET_CAP:
-	{
-		ca_caps_t cap;
-
-		cap.slot_num = 2;
-		cap.slot_type = (FW_CI_LL_SUPPORT(av7110->arm_app) ?
-				 CA_CI_LINK : CA_CI) | CA_DESCR;
-		cap.descr_num = 16;
-		cap.descr_type = CA_ECD;
-		memcpy(parg, &cap, sizeof(cap));
-		break;
-	}
-
-	case CA_GET_SLOT_INFO:
-	{
-		ca_slot_info_t *info=(ca_slot_info_t *)parg;
-
-		if (info->num < 0 || info->num > 1)
-			return -EINVAL;
-		av7110->ci_slot[info->num].num = info->num;
-		av7110->ci_slot[info->num].type = FW_CI_LL_SUPPORT(av7110->arm_app) ?
-							CA_CI_LINK : CA_CI;
-		memcpy(info, &av7110->ci_slot[info->num], sizeof(ca_slot_info_t));
-		break;
-	}
-
-	case CA_GET_MSG:
-		break;
-
-	case CA_SEND_MSG:
-		break;
-
-	case CA_GET_DESCR_INFO:
-	{
-		ca_descr_info_t info;
-
-		info.num = 16;
-		info.type = CA_ECD;
-		memcpy(parg, &info, sizeof (info));
-		break;
-	}
-
-	case CA_SET_DESCR:
-	{
-		ca_descr_t *descr = (ca_descr_t*) parg;
-
-		if (descr->index >= 16)
-			return -EINVAL;
-		if (descr->parity > 1)
-			return -EINVAL;
-		av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, SetDescr, 5,
-			      (descr->index<<8)|descr->parity,
-			      (descr->cw[0]<<8)|descr->cw[1],
-			      (descr->cw[2]<<8)|descr->cw[3],
-			      (descr->cw[4]<<8)|descr->cw[5],
-			      (descr->cw[6]<<8)|descr->cw[7]);
-		break;
-	}
-
-	default:
-		return -EINVAL;
-	}
-	return 0;
-}
-
-static ssize_t dvb_ca_write(struct file *file, const char __user *buf,
-			    size_t count, loff_t *ppos)
-{
-	struct dvb_device *dvbdev = file->private_data;
-	struct av7110 *av7110 = dvbdev->priv;
-
-	dprintk(8, "av7110:%p\n",av7110);
-	return ci_ll_write(&av7110->ci_wbuffer, file, buf, count, ppos);
-}
-
-static ssize_t dvb_ca_read(struct file *file, char __user *buf,
-			   size_t count, loff_t *ppos)
-{
-	struct dvb_device *dvbdev = file->private_data;
-	struct av7110 *av7110 = dvbdev->priv;
-
-	dprintk(8, "av7110:%p\n",av7110);
-	return ci_ll_read(&av7110->ci_rbuffer, file, buf, count, ppos);
-}
-
-static const struct file_operations dvb_ca_fops = {
-	.owner		= THIS_MODULE,
-	.read		= dvb_ca_read,
-	.write		= dvb_ca_write,
-	.unlocked_ioctl	= dvb_generic_ioctl,
-	.open		= dvb_ca_open,
-	.release	= dvb_generic_release,
-	.poll		= dvb_ca_poll,
-	.llseek		= default_llseek,
-};
-
-static struct dvb_device dvbdev_ca = {
-	.priv		= NULL,
-	.users		= 1,
-	.writers	= 1,
-	.fops		= &dvb_ca_fops,
-	.kernel_ioctl	= dvb_ca_ioctl,
-};
-
-
-int av7110_ca_register(struct av7110 *av7110)
-{
-	return dvb_register_device(&av7110->dvb_adapter, &av7110->ca_dev,
-				   &dvbdev_ca, av7110, DVB_DEVICE_CA);
-}
-
-void av7110_ca_unregister(struct av7110 *av7110)
-{
-	dvb_unregister_device(av7110->ca_dev);
-}
-
-int av7110_ca_init(struct av7110* av7110)
-{
-	return ci_ll_init(&av7110->ci_rbuffer, &av7110->ci_wbuffer, 8192);
-}
-
-void av7110_ca_exit(struct av7110* av7110)
-{
-	ci_ll_release(&av7110->ci_rbuffer, &av7110->ci_wbuffer);
-}
diff --git a/drivers/media/dvb/ttpci/av7110_ca.h b/drivers/media/dvb/ttpci/av7110_ca.h
deleted file mode 100644
index 70ee855..0000000
--- a/drivers/media/dvb/ttpci/av7110_ca.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef _AV7110_CA_H_
-#define _AV7110_CA_H_
-
-struct av7110;
-
-extern void CI_handle(struct av7110 *av7110, u8 *data, u16 len);
-extern void ci_get_data(struct dvb_ringbuffer *cibuf, u8 *data, int len);
-
-extern int av7110_ca_register(struct av7110 *av7110);
-extern void av7110_ca_unregister(struct av7110 *av7110);
-extern int av7110_ca_init(struct av7110* av7110);
-extern void av7110_ca_exit(struct av7110* av7110);
-
-#endif /* _AV7110_CA_H_ */
diff --git a/drivers/media/dvb/ttpci/av7110_hw.c b/drivers/media/dvb/ttpci/av7110_hw.c
deleted file mode 100644
index f1cbfe5..0000000
--- a/drivers/media/dvb/ttpci/av7110_hw.c
+++ /dev/null
@@ -1,1208 +0,0 @@
-/*
- * av7110_hw.c: av7110 low level hardware access and firmware interface
- *
- * Copyright (C) 1999-2002 Ralph  Metzler
- *                       & Marcus Metzler for convergence integrated media GmbH
- *
- * originally based on code by:
- * Copyright (C) 1998,1999 Christian Theiss <mistert@rz.fh-augsburg.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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- *
- * the project's page is at http://www.linuxtv.org/ 
- */
-
-/* for debugging ARM communication: */
-//#define COM_DEBUG
-
-#include <stdarg.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/delay.h>
-#include <linux/fs.h>
-
-#include "av7110.h"
-#include "av7110_hw.h"
-
-#define _NOHANDSHAKE
-
-/****************************************************************************
- * DEBI functions
- ****************************************************************************/
-
-/* This DEBI code is based on the Stradis driver
-   by Nathan Laredo <laredo@gnu.org> */
-
-int av7110_debiwrite(struct av7110 *av7110, u32 config,
-		     int addr, u32 val, int count)
-{
-	struct saa7146_dev *dev = av7110->dev;
-
-	if (count <= 0 || count > 32764) {
-		printk("%s: invalid count %d\n", __func__, count);
-		return -1;
-	}
-	if (saa7146_wait_for_debi_done(av7110->dev, 0) < 0) {
-		printk("%s: wait_for_debi_done failed\n", __func__);
-		return -1;
-	}
-	saa7146_write(dev, DEBI_CONFIG, config);
-	if (count <= 4)		/* immediate transfer */
-		saa7146_write(dev, DEBI_AD, val);
-	else			/* block transfer */
-		saa7146_write(dev, DEBI_AD, av7110->debi_bus);
-	saa7146_write(dev, DEBI_COMMAND, (count << 17) | (addr & 0xffff));
-	saa7146_write(dev, MC2, (2 << 16) | 2);
-	return 0;
-}
-
-u32 av7110_debiread(struct av7110 *av7110, u32 config, int addr, int count)
-{
-	struct saa7146_dev *dev = av7110->dev;
-	u32 result = 0;
-
-	if (count > 32764 || count <= 0) {
-		printk("%s: invalid count %d\n", __func__, count);
-		return 0;
-	}
-	if (saa7146_wait_for_debi_done(av7110->dev, 0) < 0) {
-		printk("%s: wait_for_debi_done #1 failed\n", __func__);
-		return 0;
-	}
-	saa7146_write(dev, DEBI_AD, av7110->debi_bus);
-	saa7146_write(dev, DEBI_COMMAND, (count << 17) | 0x10000 | (addr & 0xffff));
-
-	saa7146_write(dev, DEBI_CONFIG, config);
-	saa7146_write(dev, MC2, (2 << 16) | 2);
-	if (count > 4)
-		return count;
-	if (saa7146_wait_for_debi_done(av7110->dev, 0) < 0) {
-		printk("%s: wait_for_debi_done #2 failed\n", __func__);
-		return 0;
-	}
-
-	result = saa7146_read(dev, DEBI_AD);
-	result &= (0xffffffffUL >> ((4 - count) * 8));
-	return result;
-}
-
-
-
-/* av7110 ARM core boot stuff */
-#if 0
-void av7110_reset_arm(struct av7110 *av7110)
-{
-	saa7146_setgpio(av7110->dev, RESET_LINE, SAA7146_GPIO_OUTLO);
-
-	/* Disable DEBI and GPIO irq */
-	SAA7146_IER_DISABLE(av7110->dev, MASK_19 | MASK_03);
-	SAA7146_ISR_CLEAR(av7110->dev, MASK_19 | MASK_03);
-
-	saa7146_setgpio(av7110->dev, RESET_LINE, SAA7146_GPIO_OUTHI);
-	msleep(30);	/* the firmware needs some time to initialize */
-
-	ARM_ResetMailBox(av7110);
-
-	SAA7146_ISR_CLEAR(av7110->dev, MASK_19 | MASK_03);
-	SAA7146_IER_ENABLE(av7110->dev, MASK_03);
-
-	av7110->arm_ready = 1;
-	dprintk(1, "reset ARM\n");
-}
-#endif  /*  0  */
-
-static int waitdebi(struct av7110 *av7110, int adr, int state)
-{
-	int k;
-
-	dprintk(4, "%p\n", av7110);
-
-	for (k = 0; k < 100; k++) {
-		if (irdebi(av7110, DEBINOSWAP, adr, 0, 2) == state)
-			return 0;
-		udelay(5);
-	}
-	return -ETIMEDOUT;
-}
-
-static int load_dram(struct av7110 *av7110, u32 *data, int len)
-{
-	int i;
-	int blocks, rest;
-	u32 base, bootblock = AV7110_BOOT_BLOCK;
-
-	dprintk(4, "%p\n", av7110);
-
-	blocks = len / AV7110_BOOT_MAX_SIZE;
-	rest = len % AV7110_BOOT_MAX_SIZE;
-	base = DRAM_START_CODE;
-
-	for (i = 0; i < blocks; i++) {
-		if (waitdebi(av7110, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) {
-			printk(KERN_ERR "dvb-ttpci: load_dram(): timeout at block %d\n", i);
-			return -ETIMEDOUT;
-		}
-		dprintk(4, "writing DRAM block %d\n", i);
-		mwdebi(av7110, DEBISWAB, bootblock,
-		       ((u8 *)data) + i * AV7110_BOOT_MAX_SIZE, AV7110_BOOT_MAX_SIZE);
-		bootblock ^= 0x1400;
-		iwdebi(av7110, DEBISWAB, AV7110_BOOT_BASE, swab32(base), 4);
-		iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_SIZE, AV7110_BOOT_MAX_SIZE, 2);
-		iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
-		base += AV7110_BOOT_MAX_SIZE;
-	}
-
-	if (rest > 0) {
-		if (waitdebi(av7110, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) {
-			printk(KERN_ERR "dvb-ttpci: load_dram(): timeout at last block\n");
-			return -ETIMEDOUT;
-		}
-		if (rest > 4)
-			mwdebi(av7110, DEBISWAB, bootblock,
-			       ((u8 *)data) + i * AV7110_BOOT_MAX_SIZE, rest);
-		else
-			mwdebi(av7110, DEBISWAB, bootblock,
-			       ((u8 *)data) + i * AV7110_BOOT_MAX_SIZE - 4, rest + 4);
-
-		iwdebi(av7110, DEBISWAB, AV7110_BOOT_BASE, swab32(base), 4);
-		iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_SIZE, rest, 2);
-		iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
-	}
-	if (waitdebi(av7110, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_EMPTY) < 0) {
-		printk(KERN_ERR "dvb-ttpci: load_dram(): timeout after last block\n");
-		return -ETIMEDOUT;
-	}
-	iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_SIZE, 0, 2);
-	iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
-	if (waitdebi(av7110, AV7110_BOOT_STATE, BOOTSTATE_AV7110_BOOT_COMPLETE) < 0) {
-		printk(KERN_ERR "dvb-ttpci: load_dram(): final handshake timeout\n");
-		return -ETIMEDOUT;
-	}
-	return 0;
-}
-
-
-/* we cannot write av7110 DRAM directly, so load a bootloader into
- * the DPRAM which implements a simple boot protocol */
-int av7110_bootarm(struct av7110 *av7110)
-{
-	const struct firmware *fw;
-	const char *fw_name = "av7110/bootcode.bin";
-	struct saa7146_dev *dev = av7110->dev;
-	u32 ret;
-	int i;
-
-	dprintk(4, "%p\n", av7110);
-
-	av7110->arm_ready = 0;
-
-	saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTLO);
-
-	/* Disable DEBI and GPIO irq */
-	SAA7146_IER_DISABLE(av7110->dev, MASK_03 | MASK_19);
-	SAA7146_ISR_CLEAR(av7110->dev, MASK_19 | MASK_03);
-
-	/* enable DEBI */
-	saa7146_write(av7110->dev, MC1, 0x08800880);
-	saa7146_write(av7110->dev, DD1_STREAM_B, 0x00000000);
-	saa7146_write(av7110->dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
-
-	/* test DEBI */
-	iwdebi(av7110, DEBISWAP, DPRAM_BASE, 0x76543210, 4);
-	/* FIXME: Why does Nexus CA require 2x iwdebi for first init? */
-	iwdebi(av7110, DEBISWAP, DPRAM_BASE, 0x76543210, 4);
-
-	if ((ret=irdebi(av7110, DEBINOSWAP, DPRAM_BASE, 0, 4)) != 0x10325476) {
-		printk(KERN_ERR "dvb-ttpci: debi test in av7110_bootarm() failed: "
-		       "%08x != %08x (check your BIOS 'Plug&Play OS' settings)\n",
-		       ret, 0x10325476);
-		return -1;
-	}
-	for (i = 0; i < 8192; i += 4)
-		iwdebi(av7110, DEBISWAP, DPRAM_BASE + i, 0x00, 4);
-	dprintk(2, "debi test OK\n");
-
-	/* boot */
-	dprintk(1, "load boot code\n");
-	saa7146_setgpio(dev, ARM_IRQ_LINE, SAA7146_GPIO_IRQLO);
-	//saa7146_setgpio(dev, DEBI_DONE_LINE, SAA7146_GPIO_INPUT);
-	//saa7146_setgpio(dev, 3, SAA7146_GPIO_INPUT);
-
-	ret = request_firmware(&fw, fw_name, &dev->pci->dev);
-	if (ret) {
-		printk(KERN_ERR "dvb-ttpci: Failed to load firmware \"%s\"\n",
-			fw_name);
-		return ret;
-	}
-
-	mwdebi(av7110, DEBISWAB, DPRAM_BASE, fw->data, fw->size);
-	release_firmware(fw);
-	iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
-
-	if (saa7146_wait_for_debi_done(av7110->dev, 1)) {
-		printk(KERN_ERR "dvb-ttpci: av7110_bootarm(): "
-		       "saa7146_wait_for_debi_done() timed out\n");
-		return -ETIMEDOUT;
-	}
-	saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTHI);
-	mdelay(1);
-
-	dprintk(1, "load dram code\n");
-	if (load_dram(av7110, (u32 *)av7110->bin_root, av7110->size_root) < 0) {
-		printk(KERN_ERR "dvb-ttpci: av7110_bootarm(): "
-		       "load_dram() failed\n");
-		return -1;
-	}
-
-	saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTLO);
-	mdelay(1);
-
-	dprintk(1, "load dpram code\n");
-	mwdebi(av7110, DEBISWAB, DPRAM_BASE, av7110->bin_dpram, av7110->size_dpram);
-
-	if (saa7146_wait_for_debi_done(av7110->dev, 1)) {
-		printk(KERN_ERR "dvb-ttpci: av7110_bootarm(): "
-		       "saa7146_wait_for_debi_done() timed out after loading DRAM\n");
-		return -ETIMEDOUT;
-	}
-	saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTHI);
-	msleep(30);	/* the firmware needs some time to initialize */
-
-	//ARM_ClearIrq(av7110);
-	ARM_ResetMailBox(av7110);
-	SAA7146_ISR_CLEAR(av7110->dev, MASK_19 | MASK_03);
-	SAA7146_IER_ENABLE(av7110->dev, MASK_03);
-
-	av7110->arm_errors = 0;
-	av7110->arm_ready = 1;
-	return 0;
-}
-MODULE_FIRMWARE("av7110/bootcode.bin");
-
-/****************************************************************************
- * DEBI command polling
- ****************************************************************************/
-
-int av7110_wait_msgstate(struct av7110 *av7110, u16 flags)
-{
-	unsigned long start;
-	u32 stat;
-	int err;
-
-	if (FW_VERSION(av7110->arm_app) <= 0x261c) {
-		/* not supported by old firmware */
-		msleep(50);
-		return 0;
-	}
-
-	/* new firmware */
-	start = jiffies;
-	for (;;) {
-		err = time_after(jiffies, start + ARM_WAIT_FREE);
-		if (mutex_lock_interruptible(&av7110->dcomlock))
-			return -ERESTARTSYS;
-		stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
-		mutex_unlock(&av7110->dcomlock);
-		if ((stat & flags) == 0)
-			break;
-		if (err) {
-			printk(KERN_ERR "%s: timeout waiting for MSGSTATE %04x\n",
-				__func__, stat & flags);
-			return -ETIMEDOUT;
-		}
-		msleep(1);
-	}
-	return 0;
-}
-
-static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
-{
-	int i;
-	unsigned long start;
-	char *type = NULL;
-	u16 flags[2] = {0, 0};
-	u32 stat;
-	int err;
-
-//	dprintk(4, "%p\n", av7110);
-
-	if (!av7110->arm_ready) {
-		dprintk(1, "arm not ready.\n");
-		return -ENXIO;
-	}
-
-	start = jiffies;
-	while (1) {
-		err = time_after(jiffies, start + ARM_WAIT_FREE);
-		if (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2) == 0)
-			break;
-		if (err) {
-			printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND idle\n", __func__);
-			av7110->arm_errors++;
-			return -ETIMEDOUT;
-		}
-		msleep(1);
-	}
-
-	if (FW_VERSION(av7110->arm_app) <= 0x261f)
-		wdebi(av7110, DEBINOSWAP, COM_IF_LOCK, 0xffff, 2);
-
-#ifndef _NOHANDSHAKE
-	start = jiffies;
-	while (1) {
-		err = time_after(jiffies, start + ARM_WAIT_SHAKE);
-		if (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2) == 0)
-			break;
-		if (err) {
-			printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for HANDSHAKE_REG\n", __func__);
-			return -ETIMEDOUT;
-		}
-		msleep(1);
-	}
-#endif
-
-	switch ((buf[0] >> 8) & 0xff) {
-	case COMTYPE_PIDFILTER:
-	case COMTYPE_ENCODER:
-	case COMTYPE_REC_PLAY:
-	case COMTYPE_MPEGDECODER:
-		type = "MSG";
-		flags[0] = GPMQOver;
-		flags[1] = GPMQFull;
-		break;
-	case COMTYPE_OSD:
-		type = "OSD";
-		flags[0] = OSDQOver;
-		flags[1] = OSDQFull;
-		break;
-	case COMTYPE_MISC:
-		if (FW_VERSION(av7110->arm_app) >= 0x261d) {
-			type = "MSG";
-			flags[0] = GPMQOver;
-			flags[1] = GPMQBusy;
-		}
-		break;
-	default:
-		break;
-	}
-
-	if (type != NULL) {
-		/* non-immediate COMMAND type */
-		start = jiffies;
-		for (;;) {
-			err = time_after(jiffies, start + ARM_WAIT_FREE);
-			stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
-			if (stat & flags[0]) {
-				printk(KERN_ERR "%s: %s QUEUE overflow\n",
-					__func__, type);
-				return -1;
-			}
-			if ((stat & flags[1]) == 0)
-				break;
-			if (err) {
-				printk(KERN_ERR "%s: timeout waiting on busy %s QUEUE\n",
-					__func__, type);
-				av7110->arm_errors++;
-				return -ETIMEDOUT;
-			}
-			msleep(1);
-		}
-	}
-
-	for (i = 2; i < length; i++)
-		wdebi(av7110, DEBINOSWAP, COMMAND + 2 * i, (u32) buf[i], 2);
-
-	if (length)
-		wdebi(av7110, DEBINOSWAP, COMMAND + 2, (u32) buf[1], 2);
-	else
-		wdebi(av7110, DEBINOSWAP, COMMAND + 2, 0, 2);
-
-	wdebi(av7110, DEBINOSWAP, COMMAND, (u32) buf[0], 2);
-
-	if (FW_VERSION(av7110->arm_app) <= 0x261f)
-		wdebi(av7110, DEBINOSWAP, COM_IF_LOCK, 0x0000, 2);
-
-#ifdef COM_DEBUG
-	start = jiffies;
-	while (1) {
-		err = time_after(jiffies, start + ARM_WAIT_FREE);
-		if (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2) == 0)
-			break;
-		if (err) {
-			printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for COMMAND %d to complete\n",
-			       __func__, (buf[0] >> 8) & 0xff);
-			return -ETIMEDOUT;
-		}
-		msleep(1);
-	}
-
-	stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
-	if (stat & GPMQOver) {
-		printk(KERN_ERR "dvb-ttpci: %s(): GPMQOver\n", __func__);
-		return -ENOSPC;
-	}
-	else if (stat & OSDQOver) {
-		printk(KERN_ERR "dvb-ttpci: %s(): OSDQOver\n", __func__);
-		return -ENOSPC;
-	}
-#endif
-
-	return 0;
-}
-
-static int av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
-{
-	int ret;
-
-//	dprintk(4, "%p\n", av7110);
-
-	if (!av7110->arm_ready) {
-		dprintk(1, "arm not ready.\n");
-		return -1;
-	}
-	if (mutex_lock_interruptible(&av7110->dcomlock))
-		return -ERESTARTSYS;
-
-	ret = __av7110_send_fw_cmd(av7110, buf, length);
-	mutex_unlock(&av7110->dcomlock);
-	if (ret && ret!=-ERESTARTSYS)
-		printk(KERN_ERR "dvb-ttpci: %s(): av7110_send_fw_cmd error %d\n",
-		       __func__, ret);
-	return ret;
-}
-
-int av7110_fw_cmd(struct av7110 *av7110, int type, int com, int num, ...)
-{
-	va_list args;
-	u16 buf[num + 2];
-	int i, ret;
-
-//	dprintk(4, "%p\n", av7110);
-
-	buf[0] = ((type << 8) | com);
-	buf[1] = num;
-
-	if (num) {
-		va_start(args, num);
-		for (i = 0; i < num; i++)
-			buf[i + 2] = va_arg(args, u32);
-		va_end(args);
-	}
-
-	ret = av7110_send_fw_cmd(av7110, buf, num + 2);
-	if (ret && ret != -ERESTARTSYS)
-		printk(KERN_ERR "dvb-ttpci: av7110_fw_cmd error %d\n", ret);
-	return ret;
-}
-
-#if 0
-int av7110_send_ci_cmd(struct av7110 *av7110, u8 subcom, u8 *buf, u8 len)
-{
-	int i, ret;
-	u16 cmd[18] = { ((COMTYPE_COMMON_IF << 8) + subcom),
-		16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-
-	dprintk(4, "%p\n", av7110);
-
-	for(i = 0; i < len && i < 32; i++)
-	{
-		if(i % 2 == 0)
-			cmd[(i / 2) + 2] = (u16)(buf[i]) << 8;
-		else
-			cmd[(i / 2) + 2] |= buf[i];
-	}
-
-	ret = av7110_send_fw_cmd(av7110, cmd, 18);
-	if (ret && ret != -ERESTARTSYS)
-		printk(KERN_ERR "dvb-ttpci: av7110_send_ci_cmd error %d\n", ret);
-	return ret;
-}
-#endif  /*  0  */
-
-int av7110_fw_request(struct av7110 *av7110, u16 *request_buf,
-		      int request_buf_len, u16 *reply_buf, int reply_buf_len)
-{
-	int err;
-	s16 i;
-	unsigned long start;
-#ifdef COM_DEBUG
-	u32 stat;
-#endif
-
-	dprintk(4, "%p\n", av7110);
-
-	if (!av7110->arm_ready) {
-		dprintk(1, "arm not ready.\n");
-		return -1;
-	}
-
-	if (mutex_lock_interruptible(&av7110->dcomlock))
-		return -ERESTARTSYS;
-
-	if ((err = __av7110_send_fw_cmd(av7110, request_buf, request_buf_len)) < 0) {
-		mutex_unlock(&av7110->dcomlock);
-		printk(KERN_ERR "dvb-ttpci: av7110_fw_request error %d\n", err);
-		return err;
-	}
-
-	start = jiffies;
-	while (1) {
-		err = time_after(jiffies, start + ARM_WAIT_FREE);
-		if (rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2) == 0)
-			break;
-		if (err) {
-			printk(KERN_ERR "%s: timeout waiting for COMMAND to complete\n", __func__);
-			mutex_unlock(&av7110->dcomlock);
-			return -ETIMEDOUT;
-		}
-#ifdef _NOHANDSHAKE
-		msleep(1);
-#endif
-	}
-
-#ifndef _NOHANDSHAKE
-	start = jiffies;
-	while (1) {
-		err = time_after(jiffies, start + ARM_WAIT_SHAKE);
-		if (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2) == 0)
-			break;
-		if (err) {
-			printk(KERN_ERR "%s: timeout waiting for HANDSHAKE_REG\n", __func__);
-			mutex_unlock(&av7110->dcomlock);
-			return -ETIMEDOUT;
-		}
-		msleep(1);
-	}
-#endif
-
-#ifdef COM_DEBUG
-	stat = rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2);
-	if (stat & GPMQOver) {
-		printk(KERN_ERR "%s: GPMQOver\n", __func__);
-		mutex_unlock(&av7110->dcomlock);
-		return -1;
-	}
-	else if (stat & OSDQOver) {
-		printk(KERN_ERR "%s: OSDQOver\n", __func__);
-		mutex_unlock(&av7110->dcomlock);
-		return -1;
-	}
-#endif
-
-	for (i = 0; i < reply_buf_len; i++)
-		reply_buf[i] = rdebi(av7110, DEBINOSWAP, COM_BUFF + 2 * i, 0, 2);
-
-	mutex_unlock(&av7110->dcomlock);
-	return 0;
-}
-
-static int av7110_fw_query(struct av7110 *av7110, u16 tag, u16* buf, s16 length)
-{
-	int ret;
-	ret = av7110_fw_request(av7110, &tag, 0, buf, length);
-	if (ret)
-		printk(KERN_ERR "dvb-ttpci: av7110_fw_query error %d\n", ret);
-	return ret;
-}
-
-
-/****************************************************************************
- * Firmware commands
- ****************************************************************************/
-
-/* get version of the firmware ROM, RTSL, video ucode and ARM application  */
-int av7110_firmversion(struct av7110 *av7110)
-{
-	u16 buf[20];
-	u16 tag = ((COMTYPE_REQUEST << 8) + ReqVersion);
-
-	dprintk(4, "%p\n", av7110);
-
-	if (av7110_fw_query(av7110, tag, buf, 16)) {
-		printk("dvb-ttpci: failed to boot firmware @ card %d\n",
-		       av7110->dvb_adapter.num);
-		return -EIO;
-	}
-
-	av7110->arm_fw = (buf[0] << 16) + buf[1];
-	av7110->arm_rtsl = (buf[2] << 16) + buf[3];
-	av7110->arm_vid = (buf[4] << 16) + buf[5];
-	av7110->arm_app = (buf[6] << 16) + buf[7];
-	av7110->avtype = (buf[8] << 16) + buf[9];
-
-	printk("dvb-ttpci: info @ card %d: firm %08x, rtsl %08x, vid %08x, app %08x\n",
-	       av7110->dvb_adapter.num, av7110->arm_fw,
-	       av7110->arm_rtsl, av7110->arm_vid, av7110->arm_app);
-
-	/* print firmware capabilities */
-	if (FW_CI_LL_SUPPORT(av7110->arm_app))
-		printk("dvb-ttpci: firmware @ card %d supports CI link layer interface\n",
-		       av7110->dvb_adapter.num);
-	else
-		printk("dvb-ttpci: no firmware support for CI link layer interface @ card %d\n",
-		       av7110->dvb_adapter.num);
-
-	return 0;
-}
-
-
-int av7110_diseqc_send(struct av7110 *av7110, int len, u8 *msg, unsigned long burst)
-{
-	int i, ret;
-	u16 buf[18] = { ((COMTYPE_AUDIODAC << 8) + SendDiSEqC),
-			16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-
-	dprintk(4, "%p\n", av7110);
-
-	if (len > 10)
-		len = 10;
-
-	buf[1] = len + 2;
-	buf[2] = len;
-
-	if (burst != -1)
-		buf[3] = burst ? 0x01 : 0x00;
-	else
-		buf[3] = 0xffff;
-
-	for (i = 0; i < len; i++)
-		buf[i + 4] = msg[i];
-
-	ret = av7110_send_fw_cmd(av7110, buf, 18);
-	if (ret && ret!=-ERESTARTSYS)
-		printk(KERN_ERR "dvb-ttpci: av7110_diseqc_send error %d\n", ret);
-	return ret;
-}
-
-
-#ifdef CONFIG_DVB_AV7110_OSD
-
-static inline int SetColorBlend(struct av7110 *av7110, u8 windownr)
-{
-	return av7110_fw_cmd(av7110, COMTYPE_OSD, SetCBlend, 1, windownr);
-}
-
-static inline int SetBlend_(struct av7110 *av7110, u8 windownr,
-		     enum av7110_osd_palette_type colordepth, u16 index, u8 blending)
-{
-	return av7110_fw_cmd(av7110, COMTYPE_OSD, SetBlend, 4,
-			     windownr, colordepth, index, blending);
-}
-
-static inline int SetColor_(struct av7110 *av7110, u8 windownr,
-		     enum av7110_osd_palette_type colordepth, u16 index, u16 colorhi, u16 colorlo)
-{
-	return av7110_fw_cmd(av7110, COMTYPE_OSD, SetColor, 5,
-			     windownr, colordepth, index, colorhi, colorlo);
-}
-
-static inline int SetFont(struct av7110 *av7110, u8 windownr, u8 fontsize,
-			  u16 colorfg, u16 colorbg)
-{
-	return av7110_fw_cmd(av7110, COMTYPE_OSD, Set_Font, 4,
-			     windownr, fontsize, colorfg, colorbg);
-}
-
-static int FlushText(struct av7110 *av7110)
-{
-	unsigned long start;
-	int err;
-
-	if (mutex_lock_interruptible(&av7110->dcomlock))
-		return -ERESTARTSYS;
-	start = jiffies;
-	while (1) {
-		err = time_after(jiffies, start + ARM_WAIT_OSD);
-		if (rdebi(av7110, DEBINOSWAP, BUFF1_BASE, 0, 2) == 0)
-			break;
-		if (err) {
-			printk(KERN_ERR "dvb-ttpci: %s(): timeout waiting for BUFF1_BASE == 0\n",
-			       __func__);
-			mutex_unlock(&av7110->dcomlock);
-			return -ETIMEDOUT;
-		}
-		msleep(1);
-	}
-	mutex_unlock(&av7110->dcomlock);
-	return 0;
-}
-
-static int WriteText(struct av7110 *av7110, u8 win, u16 x, u16 y, char *buf)
-{
-	int i, ret;
-	unsigned long start;
-	int length = strlen(buf) + 1;
-	u16 cbuf[5] = { (COMTYPE_OSD << 8) + DText, 3, win, x, y };
-
-	if (mutex_lock_interruptible(&av7110->dcomlock))
-		return -ERESTARTSYS;
-
-	start = jiffies;
-	while (1) {
-		ret = time_after(jiffies, start + ARM_WAIT_OSD);
-		if (rdebi(av7110, DEBINOSWAP, BUFF1_BASE, 0, 2) == 0)
-			break;
-		if (ret) {
-			printk(KERN_ERR "dvb-ttpci: %s: timeout waiting for BUFF1_BASE == 0\n",
-			       __func__);
-			mutex_unlock(&av7110->dcomlock);
-			return -ETIMEDOUT;
-		}
-		msleep(1);
-	}
-#ifndef _NOHANDSHAKE
-	start = jiffies;
-	while (1) {
-		ret = time_after(jiffies, start + ARM_WAIT_SHAKE);
-		if (rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2) == 0)
-			break;
-		if (ret) {
-			printk(KERN_ERR "dvb-ttpci: %s: timeout waiting for HANDSHAKE_REG\n",
-			       __func__);
-			mutex_unlock(&av7110->dcomlock);
-			return -ETIMEDOUT;
-		}
-		msleep(1);
-	}
-#endif
-	for (i = 0; i < length / 2; i++)
-		wdebi(av7110, DEBINOSWAP, BUFF1_BASE + i * 2,
-		      swab16(*(u16 *)(buf + 2 * i)), 2);
-	if (length & 1)
-		wdebi(av7110, DEBINOSWAP, BUFF1_BASE + i * 2, 0, 2);
-	ret = __av7110_send_fw_cmd(av7110, cbuf, 5);
-	mutex_unlock(&av7110->dcomlock);
-	if (ret && ret!=-ERESTARTSYS)
-		printk(KERN_ERR "dvb-ttpci: WriteText error %d\n", ret);
-	return ret;
-}
-
-static inline int DrawLine(struct av7110 *av7110, u8 windownr,
-			   u16 x, u16 y, u16 dx, u16 dy, u16 color)
-{
-	return av7110_fw_cmd(av7110, COMTYPE_OSD, DLine, 6,
-			     windownr, x, y, dx, dy, color);
-}
-
-static inline int DrawBlock(struct av7110 *av7110, u8 windownr,
-			    u16 x, u16 y, u16 dx, u16 dy, u16 color)
-{
-	return av7110_fw_cmd(av7110, COMTYPE_OSD, DBox, 6,
-			     windownr, x, y, dx, dy, color);
-}
-
-static inline int HideWindow(struct av7110 *av7110, u8 windownr)
-{
-	return av7110_fw_cmd(av7110, COMTYPE_OSD, WHide, 1, windownr);
-}
-
-static inline int MoveWindowRel(struct av7110 *av7110, u8 windownr, u16 x, u16 y)
-{
-	return av7110_fw_cmd(av7110, COMTYPE_OSD, WMoveD, 3, windownr, x, y);
-}
-
-static inline int MoveWindowAbs(struct av7110 *av7110, u8 windownr, u16 x, u16 y)
-{
-	return av7110_fw_cmd(av7110, COMTYPE_OSD, WMoveA, 3, windownr, x, y);
-}
-
-static inline int DestroyOSDWindow(struct av7110 *av7110, u8 windownr)
-{
-	return av7110_fw_cmd(av7110, COMTYPE_OSD, WDestroy, 1, windownr);
-}
-
-static inline int CreateOSDWindow(struct av7110 *av7110, u8 windownr,
-				  osd_raw_window_t disptype,
-				  u16 width, u16 height)
-{
-	return av7110_fw_cmd(av7110, COMTYPE_OSD, WCreate, 4,
-			     windownr, disptype, width, height);
-}
-
-
-static enum av7110_osd_palette_type bpp2pal[8] = {
-	Pal1Bit, Pal2Bit, 0, Pal4Bit, 0, 0, 0, Pal8Bit
-};
-static osd_raw_window_t bpp2bit[8] = {
-	OSD_BITMAP1, OSD_BITMAP2, 0, OSD_BITMAP4, 0, 0, 0, OSD_BITMAP8
-};
-
-static inline int WaitUntilBmpLoaded(struct av7110 *av7110)
-{
-	int ret = wait_event_timeout(av7110->bmpq,
-				av7110->bmp_state != BMP_LOADING, 10*HZ);
-	if (ret == 0) {
-		printk("dvb-ttpci: warning: timeout waiting in LoadBitmap: %d, %d\n",
-		       ret, av7110->bmp_state);
-		av7110->bmp_state = BMP_NONE;
-		return -ETIMEDOUT;
-	}
-	return 0;
-}
-
-static inline int LoadBitmap(struct av7110 *av7110,
-			     u16 dx, u16 dy, int inc, u8 __user * data)
-{
-	u16 format;
-	int bpp;
-	int i;
-	int d, delta;
-	u8 c;
-	int ret;
-
-	dprintk(4, "%p\n", av7110);
-
-	format = bpp2bit[av7110->osdbpp[av7110->osdwin]];
-
-	av7110->bmp_state = BMP_LOADING;
-	if	(format == OSD_BITMAP8) {
-		bpp=8; delta = 1;
-	} else if (format == OSD_BITMAP4) {
-		bpp=4; delta = 2;
-	} else if (format == OSD_BITMAP2) {
-		bpp=2; delta = 4;
-	} else if (format == OSD_BITMAP1) {
-		bpp=1; delta = 8;
-	} else {
-		av7110->bmp_state = BMP_NONE;
-		return -EINVAL;
-	}
-	av7110->bmplen = ((dx * dy * bpp + 7) & ~7) / 8;
-	av7110->bmpp = 0;
-	if (av7110->bmplen > 32768) {
-		av7110->bmp_state = BMP_NONE;
-		return -EINVAL;
-	}
-	for (i = 0; i < dy; i++) {
-		if (copy_from_user(av7110->bmpbuf + 1024 + i * dx, data + i * inc, dx)) {
-			av7110->bmp_state = BMP_NONE;
-			return -EINVAL;
-		}
-	}
-	if (format != OSD_BITMAP8) {
-		for (i = 0; i < dx * dy / delta; i++) {
-			c = ((u8 *)av7110->bmpbuf)[1024 + i * delta + delta - 1];
-			for (d = delta - 2; d >= 0; d--) {
-				c |= (((u8 *)av7110->bmpbuf)[1024 + i * delta + d]
-				      << ((delta - d - 1) * bpp));
-				((u8 *)av7110->bmpbuf)[1024 + i] = c;
-			}
-		}
-	}
-	av7110->bmplen += 1024;
-	dprintk(4, "av7110_fw_cmd: LoadBmp size %d\n", av7110->bmplen);
-	ret = av7110_fw_cmd(av7110, COMTYPE_OSD, LoadBmp, 3, format, dx, dy);
-	if (!ret)
-		ret = WaitUntilBmpLoaded(av7110);
-	return ret;
-}
-
-static int BlitBitmap(struct av7110 *av7110, u16 x, u16 y)
-{
-	dprintk(4, "%p\n", av7110);
-
-	return av7110_fw_cmd(av7110, COMTYPE_OSD, BlitBmp, 4, av7110->osdwin, x, y, 0);
-}
-
-static inline int ReleaseBitmap(struct av7110 *av7110)
-{
-	dprintk(4, "%p\n", av7110);
-
-	if (av7110->bmp_state != BMP_LOADED && FW_VERSION(av7110->arm_app) < 0x261e)
-		return -1;
-	if (av7110->bmp_state == BMP_LOADING)
-		dprintk(1,"ReleaseBitmap called while BMP_LOADING\n");
-	av7110->bmp_state = BMP_NONE;
-	return av7110_fw_cmd(av7110, COMTYPE_OSD, ReleaseBmp, 0);
-}
-
-static u32 RGB2YUV(u16 R, u16 G, u16 B)
-{
-	u16 y, u, v;
-	u16 Y, Cr, Cb;
-
-	y = R * 77 + G * 150 + B * 29;	/* Luma=0.299R+0.587G+0.114B 0..65535 */
-	u = 2048 + B * 8 -(y >> 5);	/* Cr 0..4095 */
-	v = 2048 + R * 8 -(y >> 5);	/* Cb 0..4095 */
-
-	Y = y / 256;
-	Cb = u / 16;
-	Cr = v / 16;
-
-	return Cr | (Cb << 16) | (Y << 8);
-}
-
-static int OSDSetColor(struct av7110 *av7110, u8 color, u8 r, u8 g, u8 b, u8 blend)
-{
-	int ret;
-
-	u16 ch, cl;
-	u32 yuv;
-
-	yuv = blend ? RGB2YUV(r,g,b) : 0;
-	cl = (yuv & 0xffff);
-	ch = ((yuv >> 16) & 0xffff);
-	ret = SetColor_(av7110, av7110->osdwin, bpp2pal[av7110->osdbpp[av7110->osdwin]],
-			color, ch, cl);
-	if (!ret)
-		ret = SetBlend_(av7110, av7110->osdwin, bpp2pal[av7110->osdbpp[av7110->osdwin]],
-				color, ((blend >> 4) & 0x0f));
-	return ret;
-}
-
-static int OSDSetPalette(struct av7110 *av7110, u32 __user * colors, u8 first, u8 last)
-{
-	int i;
-	int length = last - first + 1;
-
-	if (length * 4 > DATA_BUFF3_SIZE)
-		return -EINVAL;
-
-	for (i = 0; i < length; i++) {
-		u32 color, blend, yuv;
-
-		if (get_user(color, colors + i))
-			return -EFAULT;
-		blend = (color & 0xF0000000) >> 4;
-		yuv = blend ? RGB2YUV(color & 0xFF, (color >> 8) & 0xFF,
-				     (color >> 16) & 0xFF) | blend : 0;
-		yuv = ((yuv & 0xFFFF0000) >> 16) | ((yuv & 0x0000FFFF) << 16);
-		wdebi(av7110, DEBINOSWAP, DATA_BUFF3_BASE + i * 4, yuv, 4);
-	}
-	return av7110_fw_cmd(av7110, COMTYPE_OSD, Set_Palette, 4,
-			    av7110->osdwin,
-			    bpp2pal[av7110->osdbpp[av7110->osdwin]],
-			    first, last);
-}
-
-static int OSDSetBlock(struct av7110 *av7110, int x0, int y0,
-		       int x1, int y1, int inc, u8 __user * data)
-{
-	uint w, h, bpp, bpl, size, lpb, bnum, brest;
-	int i;
-	int rc,release_rc;
-
-	w = x1 - x0 + 1;
-	h = y1 - y0 + 1;
-	if (inc <= 0)
-		inc = w;
-	if (w <= 0 || w > 720 || h <= 0 || h > 576)
-		return -EINVAL;
-	bpp = av7110->osdbpp[av7110->osdwin] + 1;
-	bpl = ((w * bpp + 7) & ~7) / 8;
-	size = h * bpl;
-	lpb = (32 * 1024) / bpl;
-	bnum = size / (lpb * bpl);
-	brest = size - bnum * lpb * bpl;
-
-	if (av7110->bmp_state == BMP_LOADING) {
-		/* possible if syscall is repeated by -ERESTARTSYS and if firmware cannot abort */
-		BUG_ON (FW_VERSION(av7110->arm_app) >= 0x261e);
-		rc = WaitUntilBmpLoaded(av7110);
-		if (rc)
-			return rc;
-		/* just continue. This should work for all fw versions
-		 * if bnum==1 && !brest && LoadBitmap was successful
-		 */
-	}
-
-	rc = 0;
-	for (i = 0; i < bnum; i++) {
-		rc = LoadBitmap(av7110, w, lpb, inc, data);
-		if (rc)
-			break;
-		rc = BlitBitmap(av7110, x0, y0 + i * lpb);
-		if (rc)
-			break;
-		data += lpb * inc;
-	}
-	if (!rc && brest) {
-		rc = LoadBitmap(av7110, w, brest / bpl, inc, data);
-		if (!rc)
-			rc = BlitBitmap(av7110, x0, y0 + bnum * lpb);
-	}
-	release_rc = ReleaseBitmap(av7110);
-	if (!rc)
-		rc = release_rc;
-	if (rc)
-		dprintk(1,"returns %d\n",rc);
-	return rc;
-}
-
-int av7110_osd_cmd(struct av7110 *av7110, osd_cmd_t *dc)
-{
-	int ret;
-
-	if (mutex_lock_interruptible(&av7110->osd_mutex))
-		return -ERESTARTSYS;
-
-	switch (dc->cmd) {
-	case OSD_Close:
-		ret = DestroyOSDWindow(av7110, av7110->osdwin);
-		break;
-	case OSD_Open:
-		av7110->osdbpp[av7110->osdwin] = (dc->color - 1) & 7;
-		ret = CreateOSDWindow(av7110, av7110->osdwin,
-				bpp2bit[av7110->osdbpp[av7110->osdwin]],
-				dc->x1 - dc->x0 + 1, dc->y1 - dc->y0 + 1);
-		if (ret)
-			break;
-		if (!dc->data) {
-			ret = MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0);
-			if (ret)
-				break;
-			ret = SetColorBlend(av7110, av7110->osdwin);
-		}
-		break;
-	case OSD_Show:
-		ret = MoveWindowRel(av7110, av7110->osdwin, 0, 0);
-		break;
-	case OSD_Hide:
-		ret = HideWindow(av7110, av7110->osdwin);
-		break;
-	case OSD_Clear:
-		ret = DrawBlock(av7110, av7110->osdwin, 0, 0, 720, 576, 0);
-		break;
-	case OSD_Fill:
-		ret = DrawBlock(av7110, av7110->osdwin, 0, 0, 720, 576, dc->color);
-		break;
-	case OSD_SetColor:
-		ret = OSDSetColor(av7110, dc->color, dc->x0, dc->y0, dc->x1, dc->y1);
-		break;
-	case OSD_SetPalette:
-		if (FW_VERSION(av7110->arm_app) >= 0x2618)
-			ret = OSDSetPalette(av7110, dc->data, dc->color, dc->x0);
-		else {
-			int i, len = dc->x0-dc->color+1;
-			u8 __user *colors = (u8 __user *)dc->data;
-			u8 r, g = 0, b = 0, blend = 0;
-			ret = 0;
-			for (i = 0; i<len; i++) {
-				if (get_user(r, colors + i * 4) ||
-				    get_user(g, colors + i * 4 + 1) ||
-				    get_user(b, colors + i * 4 + 2) ||
-				    get_user(blend, colors + i * 4 + 3)) {
-					ret = -EFAULT;
-					break;
-				    }
-				ret = OSDSetColor(av7110, dc->color + i, r, g, b, blend);
-				if (ret)
-					break;
-			}
-		}
-		break;
-	case OSD_SetPixel:
-		ret = DrawLine(av7110, av7110->osdwin,
-			 dc->x0, dc->y0, 0, 0, dc->color);
-		break;
-	case OSD_SetRow:
-		dc->y1 = dc->y0;
-		/* fall through */
-	case OSD_SetBlock:
-		ret = OSDSetBlock(av7110, dc->x0, dc->y0, dc->x1, dc->y1, dc->color, dc->data);
-		break;
-	case OSD_FillRow:
-		ret = DrawBlock(av7110, av7110->osdwin, dc->x0, dc->y0,
-			  dc->x1-dc->x0+1, dc->y1, dc->color);
-		break;
-	case OSD_FillBlock:
-		ret = DrawBlock(av7110, av7110->osdwin, dc->x0, dc->y0,
-			  dc->x1 - dc->x0 + 1, dc->y1 - dc->y0 + 1, dc->color);
-		break;
-	case OSD_Line:
-		ret = DrawLine(av7110, av7110->osdwin,
-			 dc->x0, dc->y0, dc->x1 - dc->x0, dc->y1 - dc->y0, dc->color);
-		break;
-	case OSD_Text:
-	{
-		char textbuf[240];
-
-		if (strncpy_from_user(textbuf, dc->data, 240) < 0) {
-			ret = -EFAULT;
-			break;
-		}
-		textbuf[239] = 0;
-		if (dc->x1 > 3)
-			dc->x1 = 3;
-		ret = SetFont(av7110, av7110->osdwin, dc->x1,
-			(u16) (dc->color & 0xffff), (u16) (dc->color >> 16));
-		if (!ret)
-			ret = FlushText(av7110);
-		if (!ret)
-			ret = WriteText(av7110, av7110->osdwin, dc->x0, dc->y0, textbuf);
-		break;
-	}
-	case OSD_SetWindow:
-		if (dc->x0 < 1 || dc->x0 > 7)
-			ret = -EINVAL;
-		else {
-			av7110->osdwin = dc->x0;
-			ret = 0;
-		}
-		break;
-	case OSD_MoveWindow:
-		ret = MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0);
-		if (!ret)
-			ret = SetColorBlend(av7110, av7110->osdwin);
-		break;
-	case OSD_OpenRaw:
-		if (dc->color < OSD_BITMAP1 || dc->color > OSD_CURSOR) {
-			ret = -EINVAL;
-			break;
-		}
-		if (dc->color >= OSD_BITMAP1 && dc->color <= OSD_BITMAP8HR)
-			av7110->osdbpp[av7110->osdwin] = (1 << (dc->color & 3)) - 1;
-		else
-			av7110->osdbpp[av7110->osdwin] = 0;
-		ret = CreateOSDWindow(av7110, av7110->osdwin, (osd_raw_window_t)dc->color,
-				dc->x1 - dc->x0 + 1, dc->y1 - dc->y0 + 1);
-		if (ret)
-			break;
-		if (!dc->data) {
-			ret = MoveWindowAbs(av7110, av7110->osdwin, dc->x0, dc->y0);
-			if (!ret)
-				ret = SetColorBlend(av7110, av7110->osdwin);
-		}
-		break;
-	default:
-		ret = -EINVAL;
-		break;
-	}
-
-	mutex_unlock(&av7110->osd_mutex);
-	if (ret==-ERESTARTSYS)
-		dprintk(1, "av7110_osd_cmd(%d) returns with -ERESTARTSYS\n",dc->cmd);
-	else if (ret)
-		dprintk(1, "av7110_osd_cmd(%d) returns with %d\n",dc->cmd,ret);
-
-	return ret;
-}
-
-int av7110_osd_capability(struct av7110 *av7110, osd_cap_t *cap)
-{
-	switch (cap->cmd) {
-	case OSD_CAP_MEMSIZE:
-		if (FW_4M_SDRAM(av7110->arm_app))
-			cap->val = 1000000;
-		else
-			cap->val = 92000;
-		return 0;
-	default:
-		return -EINVAL;
-	}
-}
-#endif /* CONFIG_DVB_AV7110_OSD */
diff --git a/drivers/media/dvb/ttpci/av7110_hw.h b/drivers/media/dvb/ttpci/av7110_hw.h
deleted file mode 100644
index 1634aba..0000000
--- a/drivers/media/dvb/ttpci/av7110_hw.h
+++ /dev/null
@@ -1,495 +0,0 @@
-#ifndef _AV7110_HW_H_
-#define _AV7110_HW_H_
-
-#include "av7110.h"
-
-/* DEBI transfer mode defs */
-
-#define DEBINOSWAP 0x000e0000
-#define DEBISWAB   0x001e0000
-#define DEBISWAP   0x002e0000
-
-#define ARM_WAIT_FREE  (HZ)
-#define ARM_WAIT_SHAKE (HZ/5)
-#define ARM_WAIT_OSD (HZ)
-
-
-enum av7110_bootstate
-{
-	BOOTSTATE_BUFFER_EMPTY	= 0,
-	BOOTSTATE_BUFFER_FULL	= 1,
-	BOOTSTATE_AV7110_BOOT_COMPLETE	= 2
-};
-
-enum av7110_type_rec_play_format
-{	RP_None,
-	AudioPES,
-	AudioMp2,
-	AudioPCM,
-	VideoPES,
-	AV_PES
-};
-
-enum av7110_osd_palette_type
-{
-	NoPalet =  0,	   /* No palette */
-	Pal1Bit =  2,	   /* 2 colors for 1 Bit Palette    */
-	Pal2Bit =  4,	   /* 4 colors for 2 bit palette    */
-	Pal4Bit =  16,	   /* 16 colors for 4 bit palette   */
-	Pal8Bit =  256	   /* 256 colors for 16 bit palette */
-};
-
-/* switch defines */
-#define SB_GPIO 3
-#define SB_OFF	SAA7146_GPIO_OUTLO  /* SlowBlank off (TV-Mode) */
-#define SB_ON	SAA7146_GPIO_INPUT  /* SlowBlank on  (AV-Mode) */
-#define SB_WIDE SAA7146_GPIO_OUTHI  /* SlowBlank 6V  (16/9-Mode) (not implemented) */
-
-#define FB_GPIO 1
-#define FB_OFF	SAA7146_GPIO_LO     /* FastBlank off (CVBS-Mode) */
-#define FB_ON	SAA7146_GPIO_OUTHI  /* FastBlank on  (RGB-Mode) */
-#define FB_LOOP	SAA7146_GPIO_INPUT  /* FastBlank loop-through (PC graphics ???) */
-
-enum av7110_video_output_mode
-{
-	NO_OUT	     = 0,		/* disable analog output */
-	CVBS_RGB_OUT = 1,
-	CVBS_YC_OUT  = 2,
-	YC_OUT	     = 3
-};
-
-/* firmware internal msg q status: */
-#define GPMQFull	0x0001		/* Main Message Queue Full */
-#define GPMQOver	0x0002		/* Main Message Queue Overflow */
-#define HPQFull		0x0004		/* High Priority Msg Queue Full */
-#define HPQOver		0x0008
-#define OSDQFull	0x0010		/* OSD Queue Full */
-#define OSDQOver	0x0020
-#define GPMQBusy	0x0040		/* Queue not empty, FW >= 261d */
-#define HPQBusy		0x0080
-#define OSDQBusy	0x0100
-
-/* hw section filter flags */
-#define	SECTION_EIT		0x01
-#define	SECTION_SINGLE		0x00
-#define	SECTION_CYCLE		0x02
-#define	SECTION_CONTINUOS	0x04
-#define	SECTION_MODE		0x06
-#define SECTION_IPMPE		0x0C	/* size up to 4k */
-#define SECTION_HIGH_SPEED	0x1C	/* larger buffer */
-#define DATA_PIPING_FLAG	0x20	/* for Data Piping Filter */
-
-#define	PBUFSIZE_NONE 0x0000
-#define	PBUFSIZE_1P   0x0100
-#define	PBUFSIZE_2P   0x0200
-#define	PBUFSIZE_1K   0x0300
-#define	PBUFSIZE_2K   0x0400
-#define	PBUFSIZE_4K   0x0500
-#define	PBUFSIZE_8K   0x0600
-#define PBUFSIZE_16K  0x0700
-#define PBUFSIZE_32K  0x0800
-
-
-/* firmware command codes */
-enum av7110_osd_command {
-	WCreate,
-	WDestroy,
-	WMoveD,
-	WMoveA,
-	WHide,
-	WTop,
-	DBox,
-	DLine,
-	DText,
-	Set_Font,
-	SetColor,
-	SetBlend,
-	SetWBlend,
-	SetCBlend,
-	SetNonBlend,
-	LoadBmp,
-	BlitBmp,
-	ReleaseBmp,
-	SetWTrans,
-	SetWNoTrans,
-	Set_Palette
-};
-
-enum av7110_pid_command {
-	MultiPID,
-	VideoPID,
-	AudioPID,
-	InitFilt,
-	FiltError,
-	NewVersion,
-	CacheError,
-	AddPIDFilter,
-	DelPIDFilter,
-	Scan,
-	SetDescr,
-	SetIR,
-	FlushTSQueue
-};
-
-enum av7110_mpeg_command {
-	SelAudChannels
-};
-
-enum av7110_audio_command {
-	AudioDAC,
-	CabADAC,
-	ON22K,
-	OFF22K,
-	MainSwitch,
-	ADSwitch,
-	SendDiSEqC,
-	SetRegister,
-	SpdifSwitch
-};
-
-enum av7110_request_command {
-	AudioState,
-	AudioBuffState,
-	VideoState1,
-	VideoState2,
-	VideoState3,
-	CrashCounter,
-	ReqVersion,
-	ReqVCXO,
-	ReqRegister,
-	ReqSecFilterError,
-	ReqSTC
-};
-
-enum av7110_encoder_command {
-	SetVidMode,
-	SetTestMode,
-	LoadVidCode,
-	SetMonitorType,
-	SetPanScanType,
-	SetFreezeMode,
-	SetWSSConfig
-};
-
-enum av7110_rec_play_state {
-	__Record,
-	__Stop,
-	__Play,
-	__Pause,
-	__Slow,
-	__FF_IP,
-	__Scan_I,
-	__Continue
-};
-
-enum av7110_fw_cmd_misc {
-	AV7110_FW_VIDEO_ZOOM = 1,
-	AV7110_FW_VIDEO_COMMAND,
-	AV7110_FW_AUDIO_COMMAND
-};
-
-enum av7110_command_type {
-	COMTYPE_NOCOM,
-	COMTYPE_PIDFILTER,
-	COMTYPE_MPEGDECODER,
-	COMTYPE_OSD,
-	COMTYPE_BMP,
-	COMTYPE_ENCODER,
-	COMTYPE_AUDIODAC,
-	COMTYPE_REQUEST,
-	COMTYPE_SYSTEM,
-	COMTYPE_REC_PLAY,
-	COMTYPE_COMMON_IF,
-	COMTYPE_PID_FILTER,
-	COMTYPE_PES,
-	COMTYPE_TS,
-	COMTYPE_VIDEO,
-	COMTYPE_AUDIO,
-	COMTYPE_CI_LL,
-	COMTYPE_MISC = 0x80
-};
-
-#define VID_NONE_PREF		0x00	/* No aspect ration processing preferred */
-#define VID_PAN_SCAN_PREF	0x01	/* Pan and Scan Display preferred */
-#define VID_VERT_COMP_PREF	0x02	/* Vertical compression display preferred */
-#define VID_VC_AND_PS_PREF	0x03	/* PanScan and vertical Compression if allowed */
-#define VID_CENTRE_CUT_PREF	0x05	/* PanScan with zero vector */
-
-/* MPEG video decoder commands */
-#define AV_VIDEO_CMD_STOP	0x000e
-#define AV_VIDEO_CMD_PLAY	0x000d
-#define AV_VIDEO_CMD_FREEZE	0x0102
-#define AV_VIDEO_CMD_FFWD	0x0016
-#define AV_VIDEO_CMD_SLOW	0x0022
-
-/* MPEG audio decoder commands */
-#define AUDIO_CMD_MUTE		0x0001
-#define AUDIO_CMD_UNMUTE	0x0002
-#define AUDIO_CMD_PCM16		0x0010
-#define AUDIO_CMD_STEREO	0x0080
-#define AUDIO_CMD_MONO_L	0x0100
-#define AUDIO_CMD_MONO_R	0x0200
-#define AUDIO_CMD_SYNC_OFF	0x000e
-#define AUDIO_CMD_SYNC_ON	0x000f
-
-/* firmware data interface codes */
-#define DATA_NONE		 0x00
-#define DATA_FSECTION		 0x01
-#define DATA_IPMPE		 0x02
-#define DATA_MPEG_RECORD	 0x03
-#define DATA_DEBUG_MESSAGE	 0x04
-#define DATA_COMMON_INTERFACE	 0x05
-#define DATA_MPEG_PLAY		 0x06
-#define DATA_BMP_LOAD		 0x07
-#define DATA_IRCOMMAND		 0x08
-#define DATA_PIPING		 0x09
-#define DATA_STREAMING		 0x0a
-#define DATA_CI_GET		 0x0b
-#define DATA_CI_PUT		 0x0c
-#define DATA_MPEG_VIDEO_EVENT	 0x0d
-
-#define DATA_PES_RECORD		 0x10
-#define DATA_PES_PLAY		 0x11
-#define DATA_TS_RECORD		 0x12
-#define DATA_TS_PLAY		 0x13
-
-/* ancient CI command codes, only two are actually still used
- * by the link level CI firmware */
-#define CI_CMD_ERROR		 0x00
-#define CI_CMD_ACK		 0x01
-#define CI_CMD_SYSTEM_READY	 0x02
-#define CI_CMD_KEYPRESS		 0x03
-#define CI_CMD_ON_TUNED		 0x04
-#define CI_CMD_ON_SWITCH_PROGRAM 0x05
-#define CI_CMD_SECTION_ARRIVED	 0x06
-#define CI_CMD_SECTION_TIMEOUT	 0x07
-#define CI_CMD_TIME		 0x08
-#define CI_CMD_ENTER_MENU	 0x09
-#define CI_CMD_FAST_PSI		 0x0a
-#define CI_CMD_GET_SLOT_INFO	 0x0b
-
-#define CI_MSG_NONE		 0x00
-#define CI_MSG_CI_INFO		 0x01
-#define CI_MSG_MENU		 0x02
-#define CI_MSG_LIST		 0x03
-#define CI_MSG_TEXT		 0x04
-#define CI_MSG_REQUEST_INPUT	 0x05
-#define CI_MSG_INPUT_COMPLETE	 0x06
-#define CI_MSG_LIST_MORE	 0x07
-#define CI_MSG_MENU_MORE	 0x08
-#define CI_MSG_CLOSE_MMI_IMM	 0x09
-#define CI_MSG_SECTION_REQUEST	 0x0a
-#define CI_MSG_CLOSE_FILTER	 0x0b
-#define CI_PSI_COMPLETE		 0x0c
-#define CI_MODULE_READY		 0x0d
-#define CI_SWITCH_PRG_REPLY	 0x0e
-#define CI_MSG_TEXT_MORE	 0x0f
-
-#define CI_MSG_CA_PMT		 0xe0
-#define CI_MSG_ERROR		 0xf0
-
-
-/* base address of the dual ported RAM which serves as communication
- * area between PCI bus and av7110,
- * as seen by the DEBI bus of the saa7146 */
-#define	DPRAM_BASE 0x4000
-
-/* boot protocol area */
-#define AV7110_BOOT_STATE	(DPRAM_BASE + 0x3F8)
-#define AV7110_BOOT_SIZE	(DPRAM_BASE + 0x3FA)
-#define AV7110_BOOT_BASE	(DPRAM_BASE + 0x3FC)
-#define AV7110_BOOT_BLOCK	(DPRAM_BASE + 0x400)
-#define AV7110_BOOT_MAX_SIZE	0xc00
-
-/* firmware command protocol area */
-#define IRQ_STATE	(DPRAM_BASE + 0x0F4)
-#define IRQ_STATE_EXT	(DPRAM_BASE + 0x0F6)
-#define MSGSTATE	(DPRAM_BASE + 0x0F8)
-#define COMMAND		(DPRAM_BASE + 0x0FC)
-#define COM_BUFF	(DPRAM_BASE + 0x100)
-#define COM_BUFF_SIZE	0x20
-
-/* various data buffers */
-#define BUFF1_BASE	(DPRAM_BASE + 0x120)
-#define BUFF1_SIZE	0xE0
-
-#define DATA_BUFF0_BASE	(DPRAM_BASE + 0x200)
-#define DATA_BUFF0_SIZE	0x0800
-
-#define DATA_BUFF1_BASE	(DATA_BUFF0_BASE+DATA_BUFF0_SIZE)
-#define DATA_BUFF1_SIZE	0x0800
-
-#define DATA_BUFF2_BASE	(DATA_BUFF1_BASE+DATA_BUFF1_SIZE)
-#define DATA_BUFF2_SIZE	0x0800
-
-#define DATA_BUFF3_BASE (DATA_BUFF2_BASE+DATA_BUFF2_SIZE)
-#define DATA_BUFF3_SIZE 0x0400
-
-#define Reserved	(DPRAM_BASE + 0x1E00)
-#define Reserved_SIZE	0x1C0
-
-
-/* firmware status area */
-#define STATUS_BASE	(DPRAM_BASE + 0x1FC0)
-#define STATUS_LOOPS	(STATUS_BASE + 0x08)
-
-#define STATUS_MPEG_WIDTH     (STATUS_BASE + 0x0C)
-/* ((aspect_ratio & 0xf) << 12) | (height & 0xfff) */
-#define STATUS_MPEG_HEIGHT_AR (STATUS_BASE + 0x0E)
-
-/* firmware data protocol area */
-#define RX_TYPE		(DPRAM_BASE + 0x1FE8)
-#define RX_LEN		(DPRAM_BASE + 0x1FEA)
-#define TX_TYPE		(DPRAM_BASE + 0x1FEC)
-#define TX_LEN		(DPRAM_BASE + 0x1FEE)
-
-#define RX_BUFF		(DPRAM_BASE + 0x1FF4)
-#define TX_BUFF		(DPRAM_BASE + 0x1FF6)
-
-#define HANDSHAKE_REG	(DPRAM_BASE + 0x1FF8)
-#define COM_IF_LOCK	(DPRAM_BASE + 0x1FFA)
-
-#define IRQ_RX		(DPRAM_BASE + 0x1FFC)
-#define IRQ_TX		(DPRAM_BASE + 0x1FFE)
-
-/* used by boot protocol to load firmware into av7110 DRAM */
-#define DRAM_START_CODE		0x2e000404
-#define DRAM_MAX_CODE_SIZE	0x00100000
-
-/* saa7146 gpio lines */
-#define RESET_LINE		2
-#define DEBI_DONE_LINE		1
-#define ARM_IRQ_LINE		0
-
-
-
-extern int av7110_bootarm(struct av7110 *av7110);
-extern int av7110_firmversion(struct av7110 *av7110);
-#define FW_CI_LL_SUPPORT(arm_app) ((arm_app) & 0x80000000)
-#define FW_4M_SDRAM(arm_app)      ((arm_app) & 0x40000000)
-#define FW_VERSION(arm_app)	  ((arm_app) & 0x0000FFFF)
-
-extern int av7110_wait_msgstate(struct av7110 *av7110, u16 flags);
-extern int av7110_fw_cmd(struct av7110 *av7110, int type, int com, int num, ...);
-extern int av7110_fw_request(struct av7110 *av7110, u16 *request_buf,
-			     int request_buf_len, u16 *reply_buf, int reply_buf_len);
-
-
-/* DEBI (saa7146 data extension bus interface) access */
-extern int av7110_debiwrite(struct av7110 *av7110, u32 config,
-			    int addr, u32 val, int count);
-extern u32 av7110_debiread(struct av7110 *av7110, u32 config,
-			   int addr, int count);
-
-
-/* DEBI during interrupt */
-/* single word writes */
-static inline void iwdebi(struct av7110 *av7110, u32 config, int addr, u32 val, int count)
-{
-	av7110_debiwrite(av7110, config, addr, val, count);
-}
-
-/* buffer writes */
-static inline void mwdebi(struct av7110 *av7110, u32 config, int addr,
-			  const u8 *val, int count)
-{
-	memcpy(av7110->debi_virt, val, count);
-	av7110_debiwrite(av7110, config, addr, 0, count);
-}
-
-static inline u32 irdebi(struct av7110 *av7110, u32 config, int addr, u32 val, int count)
-{
-	u32 res;
-
-	res=av7110_debiread(av7110, config, addr, count);
-	if (count<=4)
-		memcpy(av7110->debi_virt, (char *) &res, count);
-	return res;
-}
-
-/* DEBI outside interrupts, only for count <= 4! */
-static inline void wdebi(struct av7110 *av7110, u32 config, int addr, u32 val, int count)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&av7110->debilock, flags);
-	av7110_debiwrite(av7110, config, addr, val, count);
-	spin_unlock_irqrestore(&av7110->debilock, flags);
-}
-
-static inline u32 rdebi(struct av7110 *av7110, u32 config, int addr, u32 val, int count)
-{
-	unsigned long flags;
-	u32 res;
-
-	spin_lock_irqsave(&av7110->debilock, flags);
-	res=av7110_debiread(av7110, config, addr, count);
-	spin_unlock_irqrestore(&av7110->debilock, flags);
-	return res;
-}
-
-/* handle mailbox registers of the dual ported RAM */
-static inline void ARM_ResetMailBox(struct av7110 *av7110)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&av7110->debilock, flags);
-	av7110_debiread(av7110, DEBINOSWAP, IRQ_RX, 2);
-	av7110_debiwrite(av7110, DEBINOSWAP, IRQ_RX, 0, 2);
-	spin_unlock_irqrestore(&av7110->debilock, flags);
-}
-
-static inline void ARM_ClearMailBox(struct av7110 *av7110)
-{
-	iwdebi(av7110, DEBINOSWAP, IRQ_RX, 0, 2);
-}
-
-static inline void ARM_ClearIrq(struct av7110 *av7110)
-{
-	irdebi(av7110, DEBINOSWAP, IRQ_RX, 0, 2);
-}
-
-/****************************************************************************
- * Firmware commands
- ****************************************************************************/
-
-static inline int SendDAC(struct av7110 *av7110, u8 addr, u8 data)
-{
-	return av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, AudioDAC, 2, addr, data);
-}
-
-static inline int av7710_set_video_mode(struct av7110 *av7110, int mode)
-{
-	return av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetVidMode, 1, mode);
-}
-
-static inline int vidcom(struct av7110 *av7110, u32 com, u32 arg)
-{
-	return av7110_fw_cmd(av7110, COMTYPE_MISC, AV7110_FW_VIDEO_COMMAND, 4,
-			     (com>>16), (com&0xffff),
-			     (arg>>16), (arg&0xffff));
-}
-
-static inline int audcom(struct av7110 *av7110, u32 com)
-{
-	return av7110_fw_cmd(av7110, COMTYPE_MISC, AV7110_FW_AUDIO_COMMAND, 2,
-			     (com>>16), (com&0xffff));
-}
-
-static inline int Set22K(struct av7110 *av7110, int state)
-{
-	return av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, (state ? ON22K : OFF22K), 0);
-}
-
-
-extern int av7110_diseqc_send(struct av7110 *av7110, int len, u8 *msg, unsigned long burst);
-
-
-#ifdef CONFIG_DVB_AV7110_OSD
-extern int av7110_osd_cmd(struct av7110 *av7110, osd_cmd_t *dc);
-extern int av7110_osd_capability(struct av7110 *av7110, osd_cap_t *cap);
-#endif /* CONFIG_DVB_AV7110_OSD */
-
-
-
-#endif /* _AV7110_HW_H_ */
diff --git a/drivers/media/dvb/ttpci/av7110_ipack.c b/drivers/media/dvb/ttpci/av7110_ipack.c
deleted file mode 100644
index 699ef8b..0000000
--- a/drivers/media/dvb/ttpci/av7110_ipack.c
+++ /dev/null
@@ -1,403 +0,0 @@
-#include "dvb_filter.h"
-#include "av7110_ipack.h"
-#include <linux/string.h>	/* for memcpy() */
-#include <linux/vmalloc.h>
-
-
-void av7110_ipack_reset(struct ipack *p)
-{
-	p->found = 0;
-	p->cid = 0;
-	p->plength = 0;
-	p->flag1 = 0;
-	p->flag2 = 0;
-	p->hlength = 0;
-	p->mpeg = 0;
-	p->check = 0;
-	p->which = 0;
-	p->done = 0;
-	p->count = 0;
-}
-
-
-int av7110_ipack_init(struct ipack *p, int size,
-		      void (*func)(u8 *buf, int size, void *priv))
-{
-	if (!(p->buf = vmalloc(size*sizeof(u8)))) {
-		printk(KERN_WARNING "Couldn't allocate memory for ipack\n");
-		return -ENOMEM;
-	}
-	p->size = size;
-	p->func = func;
-	p->repack_subids = 0;
-	av7110_ipack_reset(p);
-	return 0;
-}
-
-
-void av7110_ipack_free(struct ipack *p)
-{
-	vfree(p->buf);
-}
-
-
-static void send_ipack(struct ipack *p)
-{
-	int off;
-	struct dvb_audio_info ai;
-	int ac3_off = 0;
-	int streamid = 0;
-	int nframes = 0;
-	int f = 0;
-
-	switch (p->mpeg) {
-	case 2:
-		if (p->count < 10)
-			return;
-		p->buf[3] = p->cid;
-		p->buf[4] = (u8)(((p->count - 6) & 0xff00) >> 8);
-		p->buf[5] = (u8)((p->count - 6) & 0x00ff);
-		if (p->repack_subids && p->cid == PRIVATE_STREAM1) {
-			off = 9 + p->buf[8];
-			streamid = p->buf[off];
-			if ((streamid & 0xf8) == 0x80) {
-				ai.off = 0;
-				ac3_off = ((p->buf[off + 2] << 8)|
-					   p->buf[off + 3]);
-				if (ac3_off < p->count)
-					f = dvb_filter_get_ac3info(p->buf + off + 3 + ac3_off,
-								   p->count - ac3_off, &ai, 0);
-				if (!f) {
-					nframes = (p->count - off - 3 - ac3_off) /
-						ai.framesize + 1;
-					p->buf[off + 2] = (ac3_off >> 8) & 0xff;
-					p->buf[off + 3] = (ac3_off) & 0xff;
-					p->buf[off + 1] = nframes;
-					ac3_off +=  nframes * ai.framesize - p->count;
-				}
-			}
-		}
-		p->func(p->buf, p->count, p->data);
-
-		p->buf[6] = 0x80;
-		p->buf[7] = 0x00;
-		p->buf[8] = 0x00;
-		p->count = 9;
-		if (p->repack_subids && p->cid == PRIVATE_STREAM1
-		    && (streamid & 0xf8) == 0x80) {
-			p->count += 4;
-			p->buf[9] = streamid;
-			p->buf[10] = (ac3_off >> 8) & 0xff;
-			p->buf[11] = (ac3_off) & 0xff;
-			p->buf[12] = 0;
-		}
-		break;
-
-	case 1:
-		if (p->count < 8)
-			return;
-		p->buf[3] = p->cid;
-		p->buf[4] = (u8)(((p->count - 6) & 0xff00) >> 8);
-		p->buf[5] = (u8)((p->count - 6) & 0x00ff);
-		p->func(p->buf, p->count, p->data);
-
-		p->buf[6] = 0x0f;
-		p->count = 7;
-		break;
-	}
-}
-
-
-void av7110_ipack_flush(struct ipack *p)
-{
-	if (p->plength != MMAX_PLENGTH - 6 || p->found <= 6)
-		return;
-	p->plength = p->found - 6;
-	p->found = 0;
-	send_ipack(p);
-	av7110_ipack_reset(p);
-}
-
-
-static void write_ipack(struct ipack *p, const u8 *data, int count)
-{
-	u8 headr[3] = { 0x00, 0x00, 0x01 };
-
-	if (p->count < 6) {
-		memcpy(p->buf, headr, 3);
-		p->count = 6;
-	}
-
-	if (p->count + count < p->size){
-		memcpy(p->buf+p->count, data, count);
-		p->count += count;
-	} else {
-		int rest = p->size - p->count;
-		memcpy(p->buf+p->count, data, rest);
-		p->count += rest;
-		send_ipack(p);
-		if (count - rest > 0)
-			write_ipack(p, data + rest, count - rest);
-	}
-}
-
-
-int av7110_ipack_instant_repack (const u8 *buf, int count, struct ipack *p)
-{
-	int l;
-	int c = 0;
-
-	while (c < count && (p->mpeg == 0 ||
-			     (p->mpeg == 1 && p->found < 7) ||
-			     (p->mpeg == 2 && p->found < 9))
-	       &&  (p->found < 5 || !p->done)) {
-		switch (p->found) {
-		case 0:
-		case 1:
-			if (buf[c] == 0x00)
-				p->found++;
-			else
-				p->found = 0;
-			c++;
-			break;
-		case 2:
-			if (buf[c] == 0x01)
-				p->found++;
-			else if (buf[c] == 0)
-				p->found = 2;
-			else
-				p->found = 0;
-			c++;
-			break;
-		case 3:
-			p->cid = 0;
-			switch (buf[c]) {
-			case PROG_STREAM_MAP:
-			case PRIVATE_STREAM2:
-			case PROG_STREAM_DIR:
-			case ECM_STREAM     :
-			case EMM_STREAM     :
-			case PADDING_STREAM :
-			case DSM_CC_STREAM  :
-			case ISO13522_STREAM:
-				p->done = 1;
-				/* fall through */
-			case PRIVATE_STREAM1:
-			case VIDEO_STREAM_S ... VIDEO_STREAM_E:
-			case AUDIO_STREAM_S ... AUDIO_STREAM_E:
-				p->found++;
-				p->cid = buf[c];
-				c++;
-				break;
-			default:
-				p->found = 0;
-				break;
-			}
-			break;
-
-		case 4:
-			if (count-c > 1) {
-				p->plen[0] = buf[c];
-				c++;
-				p->plen[1] = buf[c];
-				c++;
-				p->found += 2;
-				p->plength = (p->plen[0] << 8) | p->plen[1];
-			} else {
-				p->plen[0] = buf[c];
-				p->found++;
-				return count;
-			}
-			break;
-		case 5:
-			p->plen[1] = buf[c];
-			c++;
-			p->found++;
-			p->plength = (p->plen[0] << 8) | p->plen[1];
-			break;
-		case 6:
-			if (!p->done) {
-				p->flag1 = buf[c];
-				c++;
-				p->found++;
-				if ((p->flag1 & 0xc0) == 0x80)
-					p->mpeg = 2;
-				else {
-					p->hlength = 0;
-					p->which = 0;
-					p->mpeg = 1;
-					p->flag2 = 0;
-				}
-			}
-			break;
-
-		case 7:
-			if (!p->done && p->mpeg == 2) {
-				p->flag2 = buf[c];
-				c++;
-				p->found++;
-			}
-			break;
-
-		case 8:
-			if (!p->done && p->mpeg == 2) {
-				p->hlength = buf[c];
-				c++;
-				p->found++;
-			}
-			break;
-		}
-	}
-
-	if (c == count)
-		return count;
-
-	if (!p->plength)
-		p->plength = MMAX_PLENGTH - 6;
-
-	if (p->done || ((p->mpeg == 2 && p->found >= 9) ||
-			(p->mpeg == 1 && p->found >= 7))) {
-		switch (p->cid) {
-		case AUDIO_STREAM_S ... AUDIO_STREAM_E:
-		case VIDEO_STREAM_S ... VIDEO_STREAM_E:
-		case PRIVATE_STREAM1:
-			if (p->mpeg == 2 && p->found == 9) {
-				write_ipack(p, &p->flag1, 1);
-				write_ipack(p, &p->flag2, 1);
-				write_ipack(p, &p->hlength, 1);
-			}
-
-			if (p->mpeg == 1 && p->found == 7)
-				write_ipack(p, &p->flag1, 1);
-
-			if (p->mpeg == 2 && (p->flag2 & PTS_ONLY) &&
-			    p->found < 14) {
-				while (c < count && p->found < 14) {
-					p->pts[p->found - 9] = buf[c];
-					write_ipack(p, buf + c, 1);
-					c++;
-					p->found++;
-				}
-				if (c == count)
-					return count;
-			}
-
-			if (p->mpeg == 1 && p->which < 2000) {
-
-				if (p->found == 7) {
-					p->check = p->flag1;
-					p->hlength = 1;
-				}
-
-				while (!p->which && c < count &&
-				       p->check == 0xff){
-					p->check = buf[c];
-					write_ipack(p, buf + c, 1);
-					c++;
-					p->found++;
-					p->hlength++;
-				}
-
-				if (c == count)
-					return count;
-
-				if ((p->check & 0xc0) == 0x40 && !p->which) {
-					p->check = buf[c];
-					write_ipack(p, buf + c, 1);
-					c++;
-					p->found++;
-					p->hlength++;
-
-					p->which = 1;
-					if (c == count)
-						return count;
-					p->check = buf[c];
-					write_ipack(p, buf + c, 1);
-					c++;
-					p->found++;
-					p->hlength++;
-					p->which = 2;
-					if (c == count)
-						return count;
-				}
-
-				if (p->which == 1) {
-					p->check = buf[c];
-					write_ipack(p, buf + c, 1);
-					c++;
-					p->found++;
-					p->hlength++;
-					p->which = 2;
-					if (c == count)
-						return count;
-				}
-
-				if ((p->check & 0x30) && p->check != 0xff) {
-					p->flag2 = (p->check & 0xf0) << 2;
-					p->pts[0] = p->check;
-					p->which = 3;
-				}
-
-				if (c == count)
-					return count;
-				if (p->which > 2){
-					if ((p->flag2 & PTS_DTS_FLAGS) == PTS_ONLY) {
-						while (c < count && p->which < 7) {
-							p->pts[p->which - 2] = buf[c];
-							write_ipack(p, buf + c, 1);
-							c++;
-							p->found++;
-							p->which++;
-							p->hlength++;
-						}
-						if (c == count)
-							return count;
-					} else if ((p->flag2 & PTS_DTS_FLAGS) == PTS_DTS) {
-						while (c < count && p->which < 12) {
-							if (p->which < 7)
-								p->pts[p->which - 2] = buf[c];
-							write_ipack(p, buf + c, 1);
-							c++;
-							p->found++;
-							p->which++;
-							p->hlength++;
-						}
-						if (c == count)
-							return count;
-					}
-					p->which = 2000;
-				}
-
-			}
-
-			while (c < count && p->found < p->plength + 6) {
-				l = count - c;
-				if (l + p->found > p->plength + 6)
-					l = p->plength + 6 - p->found;
-				write_ipack(p, buf + c, l);
-				p->found += l;
-				c += l;
-			}
-			break;
-		}
-
-
-		if (p->done) {
-			if (p->found + count - c < p->plength + 6) {
-				p->found += count - c;
-				c = count;
-			} else {
-				c += p->plength + 6 - p->found;
-				p->found = p->plength + 6;
-			}
-		}
-
-		if (p->plength && p->found == p->plength + 6) {
-			send_ipack(p);
-			av7110_ipack_reset(p);
-			if (c < count)
-				av7110_ipack_instant_repack(buf + c, count - c, p);
-		}
-	}
-	return count;
-}
diff --git a/drivers/media/dvb/ttpci/av7110_ipack.h b/drivers/media/dvb/ttpci/av7110_ipack.h
deleted file mode 100644
index becf94d..0000000
--- a/drivers/media/dvb/ttpci/av7110_ipack.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef _AV7110_IPACK_H_
-#define _AV7110_IPACK_H_
-
-extern int av7110_ipack_init(struct ipack *p, int size,
-			     void (*func)(u8 *buf,  int size, void *priv));
-
-extern void av7110_ipack_reset(struct ipack *p);
-extern int  av7110_ipack_instant_repack(const u8 *buf, int count, struct ipack *p);
-extern void av7110_ipack_free(struct ipack * p);
-extern void av7110_ipack_flush(struct ipack *p);
-
-#endif
diff --git a/drivers/media/dvb/ttpci/av7110_ir.c b/drivers/media/dvb/ttpci/av7110_ir.c
deleted file mode 100644
index 908f272..0000000
--- a/drivers/media/dvb/ttpci/av7110_ir.c
+++ /dev/null
@@ -1,415 +0,0 @@
-/*
- * Driver for the remote control of SAA7146 based AV7110 cards
- *
- * Copyright (C) 1999-2003 Holger Waechtler <holger@convergence.de>
- * Copyright (C) 2003-2007 Oliver Endriss <o.endriss@gmx.de>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * 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.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- *
- */
-
-
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/proc_fs.h>
-#include <linux/kernel.h>
-#include <linux/bitops.h>
-
-#include "av7110.h"
-#include "av7110_hw.h"
-
-
-#define AV_CNT		4
-
-#define IR_RC5		0
-#define IR_RCMM		1
-#define IR_RC5_EXT	2 /* internal only */
-
-#define IR_ALL		0xffffffff
-
-#define UP_TIMEOUT	(HZ*7/25)
-
-
-/* Note: enable ir debugging by or'ing debug with 16 */
-
-static int ir_protocol[AV_CNT] = { IR_RCMM, IR_RCMM, IR_RCMM, IR_RCMM};
-module_param_array(ir_protocol, int, NULL, 0644);
-MODULE_PARM_DESC(ir_protocol, "Infrared protocol: 0 RC5, 1 RCMM (default)");
-
-static int ir_inversion[AV_CNT];
-module_param_array(ir_inversion, int, NULL, 0644);
-MODULE_PARM_DESC(ir_inversion, "Inversion of infrared signal: 0 not inverted (default), 1 inverted");
-
-static uint ir_device_mask[AV_CNT] = { IR_ALL, IR_ALL, IR_ALL, IR_ALL };
-module_param_array(ir_device_mask, uint, NULL, 0644);
-MODULE_PARM_DESC(ir_device_mask, "Bitmask of infrared devices: bit 0..31 = device 0..31 (default: all)");
-
-
-static int av_cnt;
-static struct av7110 *av_list[AV_CNT];
-
-static u16 default_key_map [256] = {
-	KEY_0, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7,
-	KEY_8, KEY_9, KEY_BACK, 0, KEY_POWER, KEY_MUTE, 0, KEY_INFO,
-	KEY_VOLUMEUP, KEY_VOLUMEDOWN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-	KEY_CHANNELUP, KEY_CHANNELDOWN, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, KEY_TEXT, 0, 0, KEY_TV, 0, 0, 0, 0, 0, KEY_SETUP, 0, 0,
-	0, 0, 0, KEY_SUBTITLE, 0, 0, KEY_LANGUAGE, 0,
-	KEY_RADIO, 0, 0, 0, 0, KEY_EXIT, 0, 0,
-	KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT, KEY_OK, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_RED, KEY_GREEN, KEY_YELLOW,
-	KEY_BLUE, 0, 0, 0, 0, 0, 0, 0, KEY_MENU, KEY_LIST, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, KEY_UP, KEY_UP, KEY_DOWN, KEY_DOWN,
-	0, 0, 0, 0, KEY_EPG, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_VCR
-};
-
-
-/* key-up timer */
-static void av7110_emit_keyup(unsigned long parm)
-{
-	struct infrared *ir = (struct infrared *) parm;
-
-	if (!ir || !test_bit(ir->last_key, ir->input_dev->key))
-		return;
-
-	input_report_key(ir->input_dev, ir->last_key, 0);
-	input_sync(ir->input_dev);
-}
-
-
-/* tasklet */
-static void av7110_emit_key(unsigned long parm)
-{
-	struct infrared *ir = (struct infrared *) parm;
-	u32 ircom = ir->ir_command;
-	u8 data;
-	u8 addr;
-	u16 toggle;
-	u16 keycode;
-
-	/* extract device address and data */
-	switch (ir->protocol) {
-	case IR_RC5: /* RC5: 5 bits device address, 6 bits data */
-		data = ircom & 0x3f;
-		addr = (ircom >> 6) & 0x1f;
-		toggle = ircom & 0x0800;
-		break;
-
-	case IR_RCMM: /* RCMM: ? bits device address, ? bits data */
-		data = ircom & 0xff;
-		addr = (ircom >> 8) & 0x1f;
-		toggle = ircom & 0x8000;
-		break;
-
-	case IR_RC5_EXT: /* extended RC5: 5 bits device address, 7 bits data */
-		data = ircom & 0x3f;
-		addr = (ircom >> 6) & 0x1f;
-		/* invert 7th data bit for backward compatibility with RC5 keymaps */
-		if (!(ircom & 0x1000))
-			data |= 0x40;
-		toggle = ircom & 0x0800;
-		break;
-
-	default:
-		printk("%s invalid protocol %x\n", __func__, ir->protocol);
-		return;
-	}
-
-	input_event(ir->input_dev, EV_MSC, MSC_RAW, (addr << 16) | data);
-	input_event(ir->input_dev, EV_MSC, MSC_SCAN, data);
-
-	keycode = ir->key_map[data];
-
-	dprintk(16, "%s: code %08x -> addr %i data 0x%02x -> keycode %i\n",
-		__func__, ircom, addr, data, keycode);
-
-	/* check device address */
-	if (!(ir->device_mask & (1 << addr)))
-		return;
-
-	if (!keycode) {
-		printk ("%s: code %08x -> addr %i data 0x%02x -> unknown key!\n",
-			__func__, ircom, addr, data);
-		return;
-	}
-
-	if (timer_pending(&ir->keyup_timer)) {
-		del_timer(&ir->keyup_timer);
-		if (ir->last_key != keycode || toggle != ir->last_toggle) {
-			ir->delay_timer_finished = 0;
-			input_event(ir->input_dev, EV_KEY, ir->last_key, 0);
-			input_event(ir->input_dev, EV_KEY, keycode, 1);
-			input_sync(ir->input_dev);
-		} else if (ir->delay_timer_finished) {
-			input_event(ir->input_dev, EV_KEY, keycode, 2);
-			input_sync(ir->input_dev);
-		}
-	} else {
-		ir->delay_timer_finished = 0;
-		input_event(ir->input_dev, EV_KEY, keycode, 1);
-		input_sync(ir->input_dev);
-	}
-
-	ir->last_key = keycode;
-	ir->last_toggle = toggle;
-
-	ir->keyup_timer.expires = jiffies + UP_TIMEOUT;
-	add_timer(&ir->keyup_timer);
-
-}
-
-
-/* register with input layer */
-static void input_register_keys(struct infrared *ir)
-{
-	int i;
-
-	set_bit(EV_KEY, ir->input_dev->evbit);
-	set_bit(EV_REP, ir->input_dev->evbit);
-	set_bit(EV_MSC, ir->input_dev->evbit);
-
-	set_bit(MSC_RAW, ir->input_dev->mscbit);
-	set_bit(MSC_SCAN, ir->input_dev->mscbit);
-
-	memset(ir->input_dev->keybit, 0, sizeof(ir->input_dev->keybit));
-
-	for (i = 0; i < ARRAY_SIZE(ir->key_map); i++) {
-		if (ir->key_map[i] > KEY_MAX)
-			ir->key_map[i] = 0;
-		else if (ir->key_map[i] > KEY_RESERVED)
-			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);
-}
-
-
-/* called by the input driver after rep[REP_DELAY] ms */
-static void input_repeat_key(unsigned long parm)
-{
-	struct infrared *ir = (struct infrared *) parm;
-
-	ir->delay_timer_finished = 1;
-}
-
-
-/* check for configuration changes */
-int av7110_check_ir_config(struct av7110 *av7110, int force)
-{
-	int i;
-	int modified = force;
-	int ret = -ENODEV;
-
-	for (i = 0; i < av_cnt; i++)
-		if (av7110 == av_list[i])
-			break;
-
-	if (i < av_cnt && av7110) {
-		if ((av7110->ir.protocol & 1) != ir_protocol[i] ||
-		    av7110->ir.inversion != ir_inversion[i])
-			modified = true;
-
-		if (modified) {
-			/* protocol */
-			if (ir_protocol[i]) {
-				ir_protocol[i] = 1;
-				av7110->ir.protocol = IR_RCMM;
-				av7110->ir.ir_config = 0x0001;
-			} else if (FW_VERSION(av7110->arm_app) >= 0x2620) {
-				av7110->ir.protocol = IR_RC5_EXT;
-				av7110->ir.ir_config = 0x0002;
-			} else {
-				av7110->ir.protocol = IR_RC5;
-				av7110->ir.ir_config = 0x0000;
-			}
-			/* inversion */
-			if (ir_inversion[i]) {
-				ir_inversion[i] = 1;
-				av7110->ir.ir_config |= 0x8000;
-			}
-			av7110->ir.inversion = ir_inversion[i];
-			/* update ARM */
-			ret = av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, SetIR, 1,
-						av7110->ir.ir_config);
-		} else
-			ret = 0;
-
-		/* address */
-		if (av7110->ir.device_mask != ir_device_mask[i])
-			av7110->ir.device_mask = ir_device_mask[i];
-	}
-
-	return ret;
-}
-
-
-/* /proc/av7110_ir interface */
-static ssize_t av7110_ir_proc_write(struct file *file, const char __user *buffer,
-				    size_t count, loff_t *pos)
-{
-	char *page;
-	u32 ir_config;
-	int size = sizeof ir_config + sizeof av_list[0]->ir.key_map;
-	int i;
-
-	if (count < size)
-		return -EINVAL;
-
-	page = vmalloc(size);
-	if (!page)
-		return -ENOMEM;
-
-	if (copy_from_user(page, buffer, size)) {
-		vfree(page);
-		return -EFAULT;
-	}
-
-	memcpy(&ir_config, page, sizeof ir_config);
-
-	for (i = 0; i < av_cnt; i++) {
-		/* keymap */
-		memcpy(av_list[i]->ir.key_map, page + sizeof ir_config,
-			sizeof(av_list[i]->ir.key_map));
-		/* protocol, inversion, address */
-		ir_protocol[i] = ir_config & 0x0001;
-		ir_inversion[i] = ir_config & 0x8000 ? 1 : 0;
-		if (ir_config & 0x4000)
-			ir_device_mask[i] = 1 << ((ir_config >> 16) & 0x1f);
-		else
-			ir_device_mask[i] = IR_ALL;
-		/* update configuration */
-		av7110_check_ir_config(av_list[i], false);
-		input_register_keys(&av_list[i]->ir);
-	}
-	vfree(page);
-	return count;
-}
-
-static const struct file_operations av7110_ir_proc_fops = {
-	.owner		= THIS_MODULE,
-	.write		= av7110_ir_proc_write,
-	.llseek		= noop_llseek,
-};
-
-/* interrupt handler */
-static void ir_handler(struct av7110 *av7110, u32 ircom)
-{
-	dprintk(4, "ir command = %08x\n", ircom);
-	av7110->ir.ir_command = ircom;
-	tasklet_schedule(&av7110->ir.ir_tasklet);
-}
-
-
-int __devinit av7110_ir_init(struct av7110 *av7110)
-{
-	struct input_dev *input_dev;
-	static struct proc_dir_entry *e;
-	int err;
-
-	if (av_cnt >= ARRAY_SIZE(av_list))
-		return -ENOSPC;
-
-	av_list[av_cnt++] = av7110;
-	av7110_check_ir_config(av7110, true);
-
-	init_timer(&av7110->ir.keyup_timer);
-	av7110->ir.keyup_timer.function = av7110_emit_keyup;
-	av7110->ir.keyup_timer.data = (unsigned long) &av7110->ir;
-
-	input_dev = input_allocate_device();
-	if (!input_dev)
-		return -ENOMEM;
-
-	av7110->ir.input_dev = input_dev;
-	snprintf(av7110->ir.input_phys, sizeof(av7110->ir.input_phys),
-		"pci-%s/ir0", pci_name(av7110->dev->pci));
-
-	input_dev->name = "DVB on-card IR receiver";
-
-	input_dev->phys = av7110->ir.input_phys;
-	input_dev->id.bustype = BUS_PCI;
-	input_dev->id.version = 2;
-	if (av7110->dev->pci->subsystem_vendor) {
-		input_dev->id.vendor = av7110->dev->pci->subsystem_vendor;
-		input_dev->id.product = av7110->dev->pci->subsystem_device;
-	} else {
-		input_dev->id.vendor = av7110->dev->pci->vendor;
-		input_dev->id.product = av7110->dev->pci->device;
-	}
-	input_dev->dev.parent = &av7110->dev->pci->dev;
-	/* initial keymap */
-	memcpy(av7110->ir.key_map, default_key_map, sizeof av7110->ir.key_map);
-	input_register_keys(&av7110->ir);
-	err = input_register_device(input_dev);
-	if (err) {
-		input_free_device(input_dev);
-		return err;
-	}
-	input_dev->timer.function = input_repeat_key;
-	input_dev->timer.data = (unsigned long) &av7110->ir;
-
-	if (av_cnt == 1) {
-		e = proc_create("av7110_ir", S_IWUSR, NULL, &av7110_ir_proc_fops);
-		if (e)
-			e->size = 4 + 256 * sizeof(u16);
-	}
-
-	tasklet_init(&av7110->ir.ir_tasklet, av7110_emit_key, (unsigned long) &av7110->ir);
-	av7110->ir.ir_handler = ir_handler;
-
-	return 0;
-}
-
-
-void __devexit av7110_ir_exit(struct av7110 *av7110)
-{
-	int i;
-
-	if (av_cnt == 0)
-		return;
-
-	del_timer_sync(&av7110->ir.keyup_timer);
-	av7110->ir.ir_handler = NULL;
-	tasklet_kill(&av7110->ir.ir_tasklet);
-
-	for (i = 0; i < av_cnt; i++)
-		if (av_list[i] == av7110) {
-			av_list[i] = av_list[av_cnt-1];
-			av_list[av_cnt-1] = NULL;
-			break;
-		}
-
-	if (av_cnt == 1)
-		remove_proc_entry("av7110_ir", NULL);
-
-	input_unregister_device(av7110->ir.input_dev);
-
-	av_cnt--;
-}
-
-//MODULE_AUTHOR("Holger Waechtler <holger@convergence.de>, Oliver Endriss <o.endriss@gmx.de>");
-//MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/ttpci/av7110_v4l.c b/drivers/media/dvb/ttpci/av7110_v4l.c
deleted file mode 100644
index 1b2d151..0000000
--- a/drivers/media/dvb/ttpci/av7110_v4l.c
+++ /dev/null
@@ -1,966 +0,0 @@
-/*
- * av7110_v4l.c: av7110 video4linux interface for DVB and Siemens DVB-C analog module
- *
- * Copyright (C) 1999-2002 Ralph  Metzler
- *                       & Marcus Metzler for convergence integrated media GmbH
- *
- * originally based on code by:
- * Copyright (C) 1998,1999 Christian Theiss <mistert@rz.fh-augsburg.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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- *
- * the project's page is at http://www.linuxtv.org/ 
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/delay.h>
-#include <linux/fs.h>
-#include <linux/timer.h>
-#include <linux/poll.h>
-
-#include "av7110.h"
-#include "av7110_hw.h"
-#include "av7110_av.h"
-
-int msp_writereg(struct av7110 *av7110, u8 dev, u16 reg, u16 val)
-{
-	u8 msg[5] = { dev, reg >> 8, reg & 0xff, val >> 8 , val & 0xff };
-	struct i2c_msg msgs = { .flags = 0, .len = 5, .buf = msg };
-
-	switch (av7110->adac_type) {
-	case DVB_ADAC_MSP34x0:
-		msgs.addr = 0x40;
-		break;
-	case DVB_ADAC_MSP34x5:
-		msgs.addr = 0x42;
-		break;
-	default:
-		return 0;
-	}
-
-	if (i2c_transfer(&av7110->i2c_adap, &msgs, 1) != 1) {
-		dprintk(1, "dvb-ttpci: failed @ card %d, %u = %u\n",
-		       av7110->dvb_adapter.num, reg, val);
-		return -EIO;
-	}
-	return 0;
-}
-
-static int msp_readreg(struct av7110 *av7110, u8 dev, u16 reg, u16 *val)
-{
-	u8 msg1[3] = { dev, reg >> 8, reg & 0xff };
-	u8 msg2[2];
-	struct i2c_msg msgs[2] = {
-		{ .flags = 0	   , .len = 3, .buf = msg1 },
-		{ .flags = I2C_M_RD, .len = 2, .buf = msg2 }
-	};
-
-	switch (av7110->adac_type) {
-	case DVB_ADAC_MSP34x0:
-		msgs[0].addr = 0x40;
-		msgs[1].addr = 0x40;
-		break;
-	case DVB_ADAC_MSP34x5:
-		msgs[0].addr = 0x42;
-		msgs[1].addr = 0x42;
-		break;
-	default:
-		return 0;
-	}
-
-	if (i2c_transfer(&av7110->i2c_adap, &msgs[0], 2) != 2) {
-		dprintk(1, "dvb-ttpci: failed @ card %d, %u\n",
-		       av7110->dvb_adapter.num, reg);
-		return -EIO;
-	}
-	*val = (msg2[0] << 8) | msg2[1];
-	return 0;
-}
-
-static struct v4l2_input inputs[4] = {
-	{
-		.index		= 0,
-		.name		= "DVB",
-		.type		= V4L2_INPUT_TYPE_CAMERA,
-		.audioset	= 1,
-		.tuner		= 0, /* ignored */
-		.std		= V4L2_STD_PAL_BG|V4L2_STD_NTSC_M,
-		.status		= 0,
-		.capabilities	= V4L2_IN_CAP_STD,
-	}, {
-		.index		= 1,
-		.name		= "Television",
-		.type		= V4L2_INPUT_TYPE_TUNER,
-		.audioset	= 1,
-		.tuner		= 0,
-		.std		= V4L2_STD_PAL_BG|V4L2_STD_NTSC_M,
-		.status		= 0,
-		.capabilities	= V4L2_IN_CAP_STD,
-	}, {
-		.index		= 2,
-		.name		= "Video",
-		.type		= V4L2_INPUT_TYPE_CAMERA,
-		.audioset	= 0,
-		.tuner		= 0,
-		.std		= V4L2_STD_PAL_BG|V4L2_STD_NTSC_M,
-		.status		= 0,
-		.capabilities	= V4L2_IN_CAP_STD,
-	}, {
-		.index		= 3,
-		.name		= "Y/C",
-		.type		= V4L2_INPUT_TYPE_CAMERA,
-		.audioset	= 0,
-		.tuner		= 0,
-		.std		= V4L2_STD_PAL_BG|V4L2_STD_NTSC_M,
-		.status		= 0,
-		.capabilities	= V4L2_IN_CAP_STD,
-	}
-};
-
-static int ves1820_writereg(struct saa7146_dev *dev, u8 addr, u8 reg, u8 data)
-{
-	struct av7110 *av7110 = dev->ext_priv;
-	u8 buf[] = { 0x00, reg, data };
-	struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = buf, .len = 3 };
-
-	dprintk(4, "dev: %p\n", dev);
-
-	if (1 != i2c_transfer(&av7110->i2c_adap, &msg, 1))
-		return -1;
-	return 0;
-}
-
-static int tuner_write(struct saa7146_dev *dev, u8 addr, u8 data [4])
-{
-	struct av7110 *av7110 = dev->ext_priv;
-	struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = data, .len = 4 };
-
-	dprintk(4, "dev: %p\n", dev);
-
-	if (1 != i2c_transfer(&av7110->i2c_adap, &msg, 1))
-		return -1;
-	return 0;
-}
-
-static int ves1820_set_tv_freq(struct saa7146_dev *dev, u32 freq)
-{
-	u32 div;
-	u8 config;
-	u8 buf[4];
-
-	dprintk(4, "freq: 0x%08x\n", freq);
-
-	/* magic number: 614. tuning with the frequency given by v4l2
-	   is always off by 614*62.5 = 38375 kHz...*/
-	div = freq + 614;
-
-	buf[0] = (div >> 8) & 0x7f;
-	buf[1] = div & 0xff;
-	buf[2] = 0x8e;
-
-	if (freq < (u32) (16 * 168.25))
-		config = 0xa0;
-	else if (freq < (u32) (16 * 447.25))
-		config = 0x90;
-	else
-		config = 0x30;
-	config &= ~0x02;
-
-	buf[3] = config;
-
-	return tuner_write(dev, 0x61, buf);
-}
-
-static int stv0297_set_tv_freq(struct saa7146_dev *dev, u32 freq)
-{
-	struct av7110 *av7110 = (struct av7110*)dev->ext_priv;
-	u32 div;
-	u8 data[4];
-
-	div = (freq + 38900000 + 31250) / 62500;
-
-	data[0] = (div >> 8) & 0x7f;
-	data[1] = div & 0xff;
-	data[2] = 0xce;
-
-	if (freq < 45000000)
-		return -EINVAL;
-	else if (freq < 137000000)
-		data[3] = 0x01;
-	else if (freq < 403000000)
-		data[3] = 0x02;
-	else if (freq < 860000000)
-		data[3] = 0x04;
-	else
-		return -EINVAL;
-
-	if (av7110->fe->ops.i2c_gate_ctrl)
-		av7110->fe->ops.i2c_gate_ctrl(av7110->fe, 1);
-	return tuner_write(dev, 0x63, data);
-}
-
-
-
-static struct saa7146_standard analog_standard[];
-static struct saa7146_standard dvb_standard[];
-static struct saa7146_standard standard[];
-
-static struct v4l2_audio msp3400_v4l2_audio = {
-	.index = 0,
-	.name = "Television",
-	.capability = V4L2_AUDCAP_STEREO
-};
-
-static int av7110_dvb_c_switch(struct saa7146_fh *fh)
-{
-	struct saa7146_dev *dev = fh->dev;
-	struct saa7146_vv *vv = dev->vv_data;
-	struct av7110 *av7110 = (struct av7110*)dev->ext_priv;
-	u16 adswitch;
-	int source, sync, err;
-
-	dprintk(4, "%p\n", av7110);
-
-	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 (err != 0) {
-			dprintk(2, "suspending video failed\n");
-			vv->ov_suspend = NULL;
-		}
-	}
-
-	if (0 != av7110->current_input) {
-		dprintk(1, "switching to analog TV:\n");
-		adswitch = 1;
-		source = SAA7146_HPS_SOURCE_PORT_B;
-		sync = SAA7146_HPS_SYNC_PORT_B;
-		memcpy(standard, analog_standard, sizeof(struct saa7146_standard) * 2);
-
-		switch (av7110->current_input) {
-		case 1:
-			dprintk(1, "switching SAA7113 to Analog Tuner Input\n");
-			msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0000); // loudspeaker source
-			msp_writereg(av7110, MSP_WR_DSP, 0x0009, 0x0000); // headphone source
-			msp_writereg(av7110, MSP_WR_DSP, 0x000a, 0x0000); // SCART 1 source
-			msp_writereg(av7110, MSP_WR_DSP, 0x000e, 0x3000); // FM matrix, mono
-			msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0x4f00); // loudspeaker + headphone
-			msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0x4f00); // SCART 1 volume
-
-			if (av7110->analog_tuner_flags & ANALOG_TUNER_VES1820) {
-				if (ves1820_writereg(dev, 0x09, 0x0f, 0x60))
-					dprintk(1, "setting band in demodulator failed\n");
-			} else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) {
-				saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); // TDA9819 pin9(STD)
-				saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI); // TDA9819 pin30(VIF)
-			}
-			if (i2c_writereg(av7110, 0x48, 0x02, 0xd0) != 1)
-				dprintk(1, "saa7113 write failed @ card %d", av7110->dvb_adapter.num);
-			break;
-		case 2:
-			dprintk(1, "switching SAA7113 to Video AV CVBS Input\n");
-			if (i2c_writereg(av7110, 0x48, 0x02, 0xd2) != 1)
-				dprintk(1, "saa7113 write failed @ card %d", av7110->dvb_adapter.num);
-			break;
-		case 3:
-			dprintk(1, "switching SAA7113 to Video AV Y/C Input\n");
-			if (i2c_writereg(av7110, 0x48, 0x02, 0xd9) != 1)
-				dprintk(1, "saa7113 write failed @ card %d", av7110->dvb_adapter.num);
-			break;
-		default:
-			dprintk(1, "switching SAA7113 to Input: AV7110: SAA7113: invalid input\n");
-		}
-	} else {
-		adswitch = 0;
-		source = SAA7146_HPS_SOURCE_PORT_A;
-		sync = SAA7146_HPS_SYNC_PORT_A;
-		memcpy(standard, dvb_standard, sizeof(struct saa7146_standard) * 2);
-		dprintk(1, "switching DVB mode\n");
-		msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0220); // loudspeaker source
-		msp_writereg(av7110, MSP_WR_DSP, 0x0009, 0x0220); // headphone source
-		msp_writereg(av7110, MSP_WR_DSP, 0x000a, 0x0220); // SCART 1 source
-		msp_writereg(av7110, MSP_WR_DSP, 0x000e, 0x3000); // FM matrix, mono
-		msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0x7f00); // loudspeaker + headphone
-		msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0x7f00); // SCART 1 volume
-
-		if (av7110->analog_tuner_flags & ANALOG_TUNER_VES1820) {
-			if (ves1820_writereg(dev, 0x09, 0x0f, 0x20))
-				dprintk(1, "setting band in demodulator failed\n");
-		} else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) {
-			saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTLO); // TDA9819 pin9(STD)
-			saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); // TDA9819 pin30(VIF)
-		}
-	}
-
-	/* hmm, this does not do anything!? */
-	if (av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, ADSwitch, 1, adswitch))
-		dprintk(1, "ADSwitch error\n");
-
-	saa7146_set_hps_source_and_sync(dev, source, sync);
-
-	if (vv->ov_suspend != NULL) {
-		saa7146_start_preview(vv->ov_suspend);
-		vv->ov_suspend = NULL;
-	}
-
-	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 av7110 *av7110 = (struct av7110 *)dev->ext_priv;
-	u16 stereo_det;
-	s8 stereo;
-
-	dprintk(2, "VIDIOC_G_TUNER: %d\n", t->index);
-
-	if (!av7110->analog_tuner_flags || t->index != 0)
-		return -EINVAL;
-
-	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;
-
-	/* 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;
-}
-
-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;
-
-	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;
-}
-
-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 >= 4)
-			return -EINVAL;
-	} else {
-		if (i->index != 0)
-			return -EINVAL;
-	}
-
-	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 input ? -EINVAL : 0;
-
-	if (input >= 4)
-		return -EINVAL;
-
-	av7110->current_input = input;
-	return av7110_dvb_c_switch(fh);
-}
-
-static int vidioc_enumaudio(struct file *file, void *fh, struct v4l2_audio *a)
-{
-	dprintk(2, "VIDIOC_G_AUDIO: %d\n", a->index);
-	if (a->index != 0)
-		return -EINVAL;
-	*a = msp3400_v4l2_audio;
-	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 av7110 *av7110 = (struct av7110 *)dev->ext_priv;
-
-	dprintk(2, "VIDIOC_G_AUDIO: %d\n", a->index);
-	if (a->index != 0)
-		return -EINVAL;
-	if (av7110->current_input >= 2)
-		return -EINVAL;
-	*a = msp3400_v4l2_audio;
-	return 0;
-}
-
-static int vidioc_s_audio(struct file *file, void *fh, struct v4l2_audio *a)
-{
-	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
-	struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
-
-	dprintk(2, "VIDIOC_S_AUDIO: %d\n", a->index);
-	if (av7110->current_input >= 2)
-		return -EINVAL;
-	return a->index ? -EINVAL : 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;
-	}
-	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);
-	}
-	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;
-}
-
-static int av7110_vbi_reset(struct file *file)
-{
-	struct saa7146_fh *fh = file->private_data;
-	struct saa7146_dev *dev = fh->dev;
-	struct av7110 *av7110 = (struct av7110*) dev->ext_priv;
-
-	dprintk(2, "%s\n", __func__);
-	av7110->wssMode = 0;
-	av7110->wssData = 0;
-	if (FW_VERSION(av7110->arm_app) < 0x2623)
-		return 0;
-	else
-		return av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig, 1, 0);
-}
-
-static ssize_t av7110_vbi_write(struct file *file, const char __user *data, size_t count, loff_t *ppos)
-{
-	struct saa7146_fh *fh = file->private_data;
-	struct saa7146_dev *dev = fh->dev;
-	struct av7110 *av7110 = (struct av7110*) dev->ext_priv;
-	struct v4l2_sliced_vbi_data d;
-	int rc;
-
-	dprintk(2, "%s\n", __func__);
-	if (FW_VERSION(av7110->arm_app) < 0x2623 || !av7110->wssMode || count != sizeof d)
-		return -EINVAL;
-	if (copy_from_user(&d, data, count))
-		return -EFAULT;
-	if ((d.id != 0 && d.id != V4L2_SLICED_WSS_625) || d.field != 0 || d.line != 23)
-		return -EINVAL;
-	if (d.id)
-		av7110->wssData = ((d.data[1] << 8) & 0x3f00) | d.data[0];
-	else
-		av7110->wssData = 0x8000;
-	rc = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetWSSConfig, 2, 1, av7110->wssData);
-	return (rc < 0) ? rc : count;
-}
-
-/****************************************************************************
- * INITIALIZATION
- ****************************************************************************/
-
-static u8 saa7113_init_regs[] = {
-	0x02, 0xd0,
-	0x03, 0x23,
-	0x04, 0x00,
-	0x05, 0x00,
-	0x06, 0xe9,
-	0x07, 0x0d,
-	0x08, 0x98,
-	0x09, 0x02,
-	0x0a, 0x80,
-	0x0b, 0x40,
-	0x0c, 0x40,
-	0x0d, 0x00,
-	0x0e, 0x01,
-	0x0f, 0x7c,
-	0x10, 0x48,
-	0x11, 0x0c,
-	0x12, 0x8b,
-	0x13, 0x1a,
-	0x14, 0x00,
-	0x15, 0x00,
-	0x16, 0x00,
-	0x17, 0x00,
-	0x18, 0x00,
-	0x19, 0x00,
-	0x1a, 0x00,
-	0x1b, 0x00,
-	0x1c, 0x00,
-	0x1d, 0x00,
-	0x1e, 0x00,
-
-	0x41, 0x77,
-	0x42, 0x77,
-	0x43, 0x77,
-	0x44, 0x77,
-	0x45, 0x77,
-	0x46, 0x77,
-	0x47, 0x77,
-	0x48, 0x77,
-	0x49, 0x77,
-	0x4a, 0x77,
-	0x4b, 0x77,
-	0x4c, 0x77,
-	0x4d, 0x77,
-	0x4e, 0x77,
-	0x4f, 0x77,
-	0x50, 0x77,
-	0x51, 0x77,
-	0x52, 0x77,
-	0x53, 0x77,
-	0x54, 0x77,
-	0x55, 0x77,
-	0x56, 0x77,
-	0x57, 0xff,
-
-	0xff
-};
-
-
-static struct saa7146_ext_vv av7110_vv_data_st;
-static struct saa7146_ext_vv av7110_vv_data_c;
-
-int av7110_init_analog_module(struct av7110 *av7110)
-{
-	u16 version1, version2;
-
-	if (i2c_writereg(av7110, 0x80, 0x0, 0x80) == 1 &&
-	    i2c_writereg(av7110, 0x80, 0x0, 0) == 1) {
-		pr_info("DVB-C analog module @ card %d detected, initializing MSP3400\n",
-			av7110->dvb_adapter.num);
-		av7110->adac_type = DVB_ADAC_MSP34x0;
-	} else if (i2c_writereg(av7110, 0x84, 0x0, 0x80) == 1 &&
-		   i2c_writereg(av7110, 0x84, 0x0, 0) == 1) {
-		pr_info("DVB-C analog module @ card %d detected, initializing MSP3415\n",
-			av7110->dvb_adapter.num);
-		av7110->adac_type = DVB_ADAC_MSP34x5;
-	} else
-		return -ENODEV;
-
-	msleep(100); // the probing above resets the msp...
-	msp_readreg(av7110, MSP_RD_DSP, 0x001e, &version1);
-	msp_readreg(av7110, MSP_RD_DSP, 0x001f, &version2);
-	dprintk(1, "dvb-ttpci: @ card %d MSP34xx version 0x%04x 0x%04x\n",
-		av7110->dvb_adapter.num, version1, version2);
-	msp_writereg(av7110, MSP_WR_DSP, 0x0013, 0x0c00);
-	msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0x7f00); // loudspeaker + headphone
-	msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0220); // loudspeaker source
-	msp_writereg(av7110, MSP_WR_DSP, 0x0009, 0x0220); // headphone source
-	msp_writereg(av7110, MSP_WR_DSP, 0x0004, 0x7f00); // loudspeaker volume
-	msp_writereg(av7110, MSP_WR_DSP, 0x000a, 0x0220); // SCART 1 source
-	msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0x7f00); // SCART 1 volume
-	msp_writereg(av7110, MSP_WR_DSP, 0x000d, 0x1900); // prescale SCART
-
-	if (i2c_writereg(av7110, 0x48, 0x01, 0x00)!=1) {
-		pr_info("saa7113 not accessible\n");
-	} else {
-		u8 *i = saa7113_init_regs;
-
-		if ((av7110->dev->pci->subsystem_vendor == 0x110a) && (av7110->dev->pci->subsystem_device == 0x0000)) {
-			/* Fujitsu/Siemens DVB-Cable */
-			av7110->analog_tuner_flags |= ANALOG_TUNER_VES1820;
-		} else if ((av7110->dev->pci->subsystem_vendor == 0x13c2) && (av7110->dev->pci->subsystem_device == 0x0002)) {
-			/* Hauppauge/TT DVB-C premium */
-			av7110->analog_tuner_flags |= ANALOG_TUNER_VES1820;
-		} else if ((av7110->dev->pci->subsystem_vendor == 0x13c2) && (av7110->dev->pci->subsystem_device == 0x000A)) {
-			/* Hauppauge/TT DVB-C premium */
-			av7110->analog_tuner_flags |= ANALOG_TUNER_STV0297;
-		}
-
-		/* setup for DVB by default */
-		if (av7110->analog_tuner_flags & ANALOG_TUNER_VES1820) {
-			if (ves1820_writereg(av7110->dev, 0x09, 0x0f, 0x20))
-				dprintk(1, "setting band in demodulator failed\n");
-		} else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) {
-			saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTLO); // TDA9819 pin9(STD)
-			saa7146_setgpio(av7110->dev, 3, SAA7146_GPIO_OUTLO); // TDA9819 pin30(VIF)
-		}
-
-		/* init the saa7113 */
-		while (*i != 0xff) {
-			if (i2c_writereg(av7110, 0x48, i[0], i[1]) != 1) {
-				dprintk(1, "saa7113 initialization failed @ card %d", av7110->dvb_adapter.num);
-				break;
-			}
-			i += 2;
-		}
-		/* setup msp for analog sound: B/G Dual-FM */
-		msp_writereg(av7110, MSP_WR_DEM, 0x00bb, 0x02d0); // AD_CV
-		msp_writereg(av7110, MSP_WR_DEM, 0x0001,  3); // FIR1
-		msp_writereg(av7110, MSP_WR_DEM, 0x0001, 18); // FIR1
-		msp_writereg(av7110, MSP_WR_DEM, 0x0001, 27); // FIR1
-		msp_writereg(av7110, MSP_WR_DEM, 0x0001, 48); // FIR1
-		msp_writereg(av7110, MSP_WR_DEM, 0x0001, 66); // FIR1
-		msp_writereg(av7110, MSP_WR_DEM, 0x0001, 72); // FIR1
-		msp_writereg(av7110, MSP_WR_DEM, 0x0005,  4); // FIR2
-		msp_writereg(av7110, MSP_WR_DEM, 0x0005, 64); // FIR2
-		msp_writereg(av7110, MSP_WR_DEM, 0x0005,  0); // FIR2
-		msp_writereg(av7110, MSP_WR_DEM, 0x0005,  3); // FIR2
-		msp_writereg(av7110, MSP_WR_DEM, 0x0005, 18); // FIR2
-		msp_writereg(av7110, MSP_WR_DEM, 0x0005, 27); // FIR2
-		msp_writereg(av7110, MSP_WR_DEM, 0x0005, 48); // FIR2
-		msp_writereg(av7110, MSP_WR_DEM, 0x0005, 66); // FIR2
-		msp_writereg(av7110, MSP_WR_DEM, 0x0005, 72); // FIR2
-		msp_writereg(av7110, MSP_WR_DEM, 0x0083, 0xa000); // MODE_REG
-		msp_writereg(av7110, MSP_WR_DEM, 0x0093, 0x00aa); // DCO1_LO 5.74MHz
-		msp_writereg(av7110, MSP_WR_DEM, 0x009b, 0x04fc); // DCO1_HI
-		msp_writereg(av7110, MSP_WR_DEM, 0x00a3, 0x038e); // DCO2_LO 5.5MHz
-		msp_writereg(av7110, MSP_WR_DEM, 0x00ab, 0x04c6); // DCO2_HI
-		msp_writereg(av7110, MSP_WR_DEM, 0x0056, 0); // LOAD_REG 1/2
-	}
-
-	memcpy(standard, dvb_standard, sizeof(struct saa7146_standard) * 2);
-	/* set dd1 stream a & b */
-	saa7146_write(av7110->dev, DD1_STREAM_B, 0x00000000);
-	saa7146_write(av7110->dev, DD1_INIT, 0x03000700);
-	saa7146_write(av7110->dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
-
-	return 0;
-}
-
-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)
-		vv_data = &av7110_vv_data_c;
-	else
-		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->vid_ops.vidioc_enum_input = vidioc_enum_input;
-	vv_data->vid_ops.vidioc_g_input = vidioc_g_input;
-	vv_data->vid_ops.vidioc_s_input = vidioc_s_input;
-	vv_data->vid_ops.vidioc_g_tuner = vidioc_g_tuner;
-	vv_data->vid_ops.vidioc_s_tuner = vidioc_s_tuner;
-	vv_data->vid_ops.vidioc_g_frequency = vidioc_g_frequency;
-	vv_data->vid_ops.vidioc_s_frequency = vidioc_s_frequency;
-	vv_data->vid_ops.vidioc_enumaudio = vidioc_enumaudio;
-	vv_data->vid_ops.vidioc_g_audio = vidioc_g_audio;
-	vv_data->vid_ops.vidioc_s_audio = vidioc_s_audio;
-	vv_data->vid_ops.vidioc_g_fmt_vbi_cap = NULL;
-
-	vv_data->vbi_ops.vidioc_g_tuner = vidioc_g_tuner;
-	vv_data->vbi_ops.vidioc_s_tuner = vidioc_s_tuner;
-	vv_data->vbi_ops.vidioc_g_frequency = vidioc_g_frequency;
-	vv_data->vbi_ops.vidioc_s_frequency = vidioc_s_frequency;
-	vv_data->vbi_ops.vidioc_g_fmt_vbi_cap = NULL;
-	vv_data->vbi_ops.vidioc_g_sliced_vbi_cap = vidioc_g_sliced_vbi_cap;
-	vv_data->vbi_ops.vidioc_g_fmt_sliced_vbi_out = vidioc_g_fmt_sliced_vbi_out;
-	vv_data->vbi_ops.vidioc_s_fmt_sliced_vbi_out = vidioc_s_fmt_sliced_vbi_out;
-
-	if (FW_VERSION(av7110->arm_app) < 0x2623)
-		vv_data->capabilities &= ~V4L2_CAP_SLICED_VBI_OUTPUT;
-
-	if (saa7146_register_device(&av7110->v4l_dev, dev, "av7110", VFL_TYPE_GRABBER)) {
-		ERR("cannot register capture device. skipping\n");
-		saa7146_vv_release(dev);
-		return -ENODEV;
-	}
-	if (FW_VERSION(av7110->arm_app) >= 0x2623) {
-		if (saa7146_register_device(&av7110->vbi_dev, dev, "av7110", VFL_TYPE_VBI))
-			ERR("cannot register vbi v4l2 device. skipping\n");
-	}
-	return 0;
-}
-
-int av7110_exit_v4l(struct av7110 *av7110)
-{
-	struct saa7146_dev* dev = av7110->dev;
-
-	saa7146_unregister_device(&av7110->v4l_dev, av7110->dev);
-	saa7146_unregister_device(&av7110->vbi_dev, av7110->dev);
-
-	saa7146_vv_release(dev);
-
-	return 0;
-}
-
-
-
-/* FIXME: these values are experimental values that look better than the
-   values from the latest "official" driver -- at least for me... (MiHu) */
-static struct saa7146_standard standard[] = {
-	{
-		.name	= "PAL",	.id		= V4L2_STD_PAL_BG,
-		.v_offset	= 0x15,	.v_field	= 288,
-		.h_offset	= 0x48,	.h_pixels	= 708,
-		.v_max_out	= 576,	.h_max_out	= 768,
-	}, {
-		.name	= "NTSC",	.id		= V4L2_STD_NTSC,
-		.v_offset	= 0x10,	.v_field	= 244,
-		.h_offset	= 0x40,	.h_pixels	= 708,
-		.v_max_out	= 480,	.h_max_out	= 640,
-	}
-};
-
-static struct saa7146_standard analog_standard[] = {
-	{
-		.name	= "PAL",	.id		= V4L2_STD_PAL_BG,
-		.v_offset	= 0x1b,	.v_field	= 288,
-		.h_offset	= 0x08,	.h_pixels	= 708,
-		.v_max_out	= 576,	.h_max_out	= 768,
-	}, {
-		.name	= "NTSC",	.id		= V4L2_STD_NTSC,
-		.v_offset	= 0x10,	.v_field	= 244,
-		.h_offset	= 0x40,	.h_pixels	= 708,
-		.v_max_out	= 480,	.h_max_out	= 640,
-	}
-};
-
-static struct saa7146_standard dvb_standard[] = {
-	{
-		.name	= "PAL",	.id		= V4L2_STD_PAL_BG,
-		.v_offset	= 0x14,	.v_field	= 288,
-		.h_offset	= 0x48,	.h_pixels	= 708,
-		.v_max_out	= 576,	.h_max_out	= 768,
-	}, {
-		.name	= "NTSC",	.id		= V4L2_STD_NTSC,
-		.v_offset	= 0x10,	.v_field	= 244,
-		.h_offset	= 0x40,	.h_pixels	= 708,
-		.v_max_out	= 480,	.h_max_out	= 640,
-	}
-};
-
-static int std_callback(struct saa7146_dev* dev, struct saa7146_standard *std)
-{
-	struct av7110 *av7110 = (struct av7110*) dev->ext_priv;
-
-	if (std->id & V4L2_STD_PAL) {
-		av7110->vidmode = AV7110_VIDEO_MODE_PAL;
-		av7110_set_vidmode(av7110, av7110->vidmode);
-	}
-	else if (std->id & V4L2_STD_NTSC) {
-		av7110->vidmode = AV7110_VIDEO_MODE_NTSC;
-		av7110_set_vidmode(av7110, av7110->vidmode);
-	}
-	else
-		return -1;
-
-	return 0;
-}
-
-
-static struct saa7146_ext_vv av7110_vv_data_st = {
-	.inputs		= 1,
-	.audios		= 1,
-	.capabilities	= V4L2_CAP_SLICED_VBI_OUTPUT | V4L2_CAP_AUDIO,
-	.flags		= 0,
-
-	.stds		= &standard[0],
-	.num_stds	= ARRAY_SIZE(standard),
-	.std_callback	= &std_callback,
-
-	.vbi_fops.open	= av7110_vbi_reset,
-	.vbi_fops.release = av7110_vbi_reset,
-	.vbi_fops.write	= av7110_vbi_write,
-};
-
-static struct saa7146_ext_vv av7110_vv_data_c = {
-	.inputs		= 1,
-	.audios		= 1,
-	.capabilities	= V4L2_CAP_TUNER | V4L2_CAP_SLICED_VBI_OUTPUT | V4L2_CAP_AUDIO,
-	.flags		= SAA7146_USE_PORT_B_FOR_VBI,
-
-	.stds		= &standard[0],
-	.num_stds	= ARRAY_SIZE(standard),
-	.std_callback	= &std_callback,
-
-	.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
deleted file mode 100644
index 12ddb53..0000000
--- a/drivers/media/dvb/ttpci/budget-av.c
+++ /dev/null
@@ -1,1640 +0,0 @@
-/*
- * budget-av.c: driver for the SAA7146 based Budget DVB cards
- *              with analog video in
- *
- * Compiled from various sources by Michael Hunold <michael@mihu.de>
- *
- * CI interface support (c) 2004 Olivier Gournet <ogournet@anevia.com> &
- *                               Andrew de Quincey <adq_dvb@lidskialf.net>
- *
- * Copyright (C) 2002 Ralph Metzler <rjkm@metzlerbros.de>
- *
- * Copyright (C) 1999-2002 Ralph  Metzler
- *                       & Marcus Metzler for convergence integrated media GmbH
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the 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.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- *
- *
- * the project's page is at http://www.linuxtv.org/ 
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include "budget.h"
-#include "stv0299.h"
-#include "stb0899_drv.h"
-#include "stb0899_reg.h"
-#include "stb0899_cfg.h"
-#include "tda8261.h"
-#include "tda8261_cfg.h"
-#include "tda1002x.h"
-#include "tda1004x.h"
-#include "tua6100.h"
-#include "dvb-pll.h"
-#include <media/saa7146_vv.h>
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/input.h>
-#include <linux/spinlock.h>
-
-#include "dvb_ca_en50221.h"
-
-#define DEBICICAM		0x02420000
-
-#define SLOTSTATUS_NONE         1
-#define SLOTSTATUS_PRESENT      2
-#define SLOTSTATUS_RESET        4
-#define SLOTSTATUS_READY        8
-#define SLOTSTATUS_OCCUPIED     (SLOTSTATUS_PRESENT|SLOTSTATUS_RESET|SLOTSTATUS_READY)
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-struct budget_av {
-	struct budget budget;
-	struct video_device *vd;
-	int cur_input;
-	int has_saa7113;
-	struct tasklet_struct ciintf_irq_tasklet;
-	int slot_status;
-	struct dvb_ca_en50221 ca;
-	u8 reinitialise_demod:1;
-};
-
-static int ciintf_slot_shutdown(struct dvb_ca_en50221 *ca, int slot);
-
-
-/* GPIO Connections:
- * 0 - Vcc/Reset (Reset is controlled by capacitor). Resets the frontend *AS WELL*!
- * 1 - CI memory select 0=>IO memory, 1=>Attribute Memory
- * 2 - CI Card Enable (Active Low)
- * 3 - CI Card Detect
- */
-
-/****************************************************************************
- * INITIALIZATION
- ****************************************************************************/
-
-static u8 i2c_readreg(struct i2c_adapter *i2c, u8 id, u8 reg)
-{
-	u8 mm1[] = { 0x00 };
-	u8 mm2[] = { 0x00 };
-	struct i2c_msg msgs[2];
-
-	msgs[0].flags = 0;
-	msgs[1].flags = I2C_M_RD;
-	msgs[0].addr = msgs[1].addr = id / 2;
-	mm1[0] = reg;
-	msgs[0].len = 1;
-	msgs[1].len = 1;
-	msgs[0].buf = mm1;
-	msgs[1].buf = mm2;
-
-	i2c_transfer(i2c, msgs, 2);
-
-	return mm2[0];
-}
-
-static int i2c_readregs(struct i2c_adapter *i2c, u8 id, u8 reg, u8 * buf, u8 len)
-{
-	u8 mm1[] = { reg };
-	struct i2c_msg msgs[2] = {
-		{.addr = id / 2,.flags = 0,.buf = mm1,.len = 1},
-		{.addr = id / 2,.flags = I2C_M_RD,.buf = buf,.len = len}
-	};
-
-	if (i2c_transfer(i2c, msgs, 2) != 2)
-		return -EIO;
-
-	return 0;
-}
-
-static int i2c_writereg(struct i2c_adapter *i2c, u8 id, u8 reg, u8 val)
-{
-	u8 msg[2] = { reg, val };
-	struct i2c_msg msgs;
-
-	msgs.flags = 0;
-	msgs.addr = id / 2;
-	msgs.len = 2;
-	msgs.buf = msg;
-	return i2c_transfer(i2c, &msgs, 1);
-}
-
-static int ciintf_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address)
-{
-	struct budget_av *budget_av = (struct budget_av *) ca->data;
-	int result;
-
-	if (slot != 0)
-		return -EINVAL;
-
-	saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTHI);
-	udelay(1);
-
-	result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 0xfff, 1, 0, 1);
-	if (result == -ETIMEDOUT) {
-		ciintf_slot_shutdown(ca, slot);
-		pr_info("cam ejected 1\n");
-	}
-	return result;
-}
-
-static int ciintf_write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address, u8 value)
-{
-	struct budget_av *budget_av = (struct budget_av *) ca->data;
-	int result;
-
-	if (slot != 0)
-		return -EINVAL;
-
-	saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTHI);
-	udelay(1);
-
-	result = ttpci_budget_debiwrite(&budget_av->budget, DEBICICAM, address & 0xfff, 1, value, 0, 1);
-	if (result == -ETIMEDOUT) {
-		ciintf_slot_shutdown(ca, slot);
-		pr_info("cam ejected 2\n");
-	}
-	return result;
-}
-
-static int ciintf_read_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address)
-{
-	struct budget_av *budget_av = (struct budget_av *) ca->data;
-	int result;
-
-	if (slot != 0)
-		return -EINVAL;
-
-	saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO);
-	udelay(1);
-
-	result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 3, 1, 0, 0);
-	if (result == -ETIMEDOUT) {
-		ciintf_slot_shutdown(ca, slot);
-		pr_info("cam ejected 3\n");
-		return -ETIMEDOUT;
-	}
-	return result;
-}
-
-static int ciintf_write_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address, u8 value)
-{
-	struct budget_av *budget_av = (struct budget_av *) ca->data;
-	int result;
-
-	if (slot != 0)
-		return -EINVAL;
-
-	saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO);
-	udelay(1);
-
-	result = ttpci_budget_debiwrite(&budget_av->budget, DEBICICAM, address & 3, 1, value, 0, 0);
-	if (result == -ETIMEDOUT) {
-		ciintf_slot_shutdown(ca, slot);
-		pr_info("cam ejected 5\n");
-	}
-	return result;
-}
-
-static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot)
-{
-	struct budget_av *budget_av = (struct budget_av *) ca->data;
-	struct saa7146_dev *saa = budget_av->budget.dev;
-
-	if (slot != 0)
-		return -EINVAL;
-
-	dprintk(1, "ciintf_slot_reset\n");
-	budget_av->slot_status = SLOTSTATUS_RESET;
-
-	saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTHI); /* disable card */
-
-	saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTHI); /* Vcc off */
-	msleep(2);
-	saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO); /* Vcc on */
-	msleep(20); /* 20 ms Vcc settling time */
-
-	saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTLO); /* enable card */
-	ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
-	msleep(20);
-
-	/* reinitialise the frontend if necessary */
-	if (budget_av->reinitialise_demod)
-		dvb_frontend_reinitialise(budget_av->budget.dvb_frontend);
-
-	return 0;
-}
-
-static int ciintf_slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
-{
-	struct budget_av *budget_av = (struct budget_av *) ca->data;
-	struct saa7146_dev *saa = budget_av->budget.dev;
-
-	if (slot != 0)
-		return -EINVAL;
-
-	dprintk(1, "ciintf_slot_shutdown\n");
-
-	ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
-	budget_av->slot_status = SLOTSTATUS_NONE;
-
-	return 0;
-}
-
-static int ciintf_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
-{
-	struct budget_av *budget_av = (struct budget_av *) ca->data;
-	struct saa7146_dev *saa = budget_av->budget.dev;
-
-	if (slot != 0)
-		return -EINVAL;
-
-	dprintk(1, "ciintf_slot_ts_enable: %d\n", budget_av->slot_status);
-
-	ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTA);
-
-	return 0;
-}
-
-static int ciintf_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open)
-{
-	struct budget_av *budget_av = (struct budget_av *) ca->data;
-	struct saa7146_dev *saa = budget_av->budget.dev;
-	int result;
-
-	if (slot != 0)
-		return -EINVAL;
-
-	/* test the card detect line - needs to be done carefully
-	 * since it never goes high for some CAMs on this interface (e.g. topuptv) */
-	if (budget_av->slot_status == SLOTSTATUS_NONE) {
-		saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
-		udelay(1);
-		if (saa7146_read(saa, PSR) & MASK_06) {
-			if (budget_av->slot_status == SLOTSTATUS_NONE) {
-				budget_av->slot_status = SLOTSTATUS_PRESENT;
-				pr_info("cam inserted A\n");
-			}
-		}
-		saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
-	}
-
-	/* We also try and read from IO memory to work round the above detection bug. If
-	 * there is no CAM, we will get a timeout. Only done if there is no cam
-	 * present, since this test actually breaks some cams :(
-	 *
-	 * if the CI interface is not open, we also do the above test since we
-	 * don't care if the cam has problems - we'll be resetting it on open() anyway */
-	if ((budget_av->slot_status == SLOTSTATUS_NONE) || (!open)) {
-		saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO);
-		result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, 0, 1, 0, 1);
-		if ((result >= 0) && (budget_av->slot_status == SLOTSTATUS_NONE)) {
-			budget_av->slot_status = SLOTSTATUS_PRESENT;
-			pr_info("cam inserted B\n");
-		} else if (result < 0) {
-			if (budget_av->slot_status != SLOTSTATUS_NONE) {
-				ciintf_slot_shutdown(ca, slot);
-				pr_info("cam ejected 5\n");
-				return 0;
-			}
-		}
-	}
-
-	/* read from attribute memory in reset/ready state to know when the CAM is ready */
-	if (budget_av->slot_status == SLOTSTATUS_RESET) {
-		result = ciintf_read_attribute_mem(ca, slot, 0);
-		if (result == 0x1d) {
-			budget_av->slot_status = SLOTSTATUS_READY;
-		}
-	}
-
-	/* work out correct return code */
-	if (budget_av->slot_status != SLOTSTATUS_NONE) {
-		if (budget_av->slot_status & SLOTSTATUS_READY) {
-			return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY;
-		}
-		return DVB_CA_EN50221_POLL_CAM_PRESENT;
-	}
-	return 0;
-}
-
-static int ciintf_init(struct budget_av *budget_av)
-{
-	struct saa7146_dev *saa = budget_av->budget.dev;
-	int result;
-
-	memset(&budget_av->ca, 0, sizeof(struct dvb_ca_en50221));
-
-	saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO);
-	saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTLO);
-	saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTLO);
-	saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
-
-	/* Enable DEBI pins */
-	saa7146_write(saa, MC1, MASK_27 | MASK_11);
-
-	/* register CI interface */
-	budget_av->ca.owner = THIS_MODULE;
-	budget_av->ca.read_attribute_mem = ciintf_read_attribute_mem;
-	budget_av->ca.write_attribute_mem = ciintf_write_attribute_mem;
-	budget_av->ca.read_cam_control = ciintf_read_cam_control;
-	budget_av->ca.write_cam_control = ciintf_write_cam_control;
-	budget_av->ca.slot_reset = ciintf_slot_reset;
-	budget_av->ca.slot_shutdown = ciintf_slot_shutdown;
-	budget_av->ca.slot_ts_enable = ciintf_slot_ts_enable;
-	budget_av->ca.poll_slot_status = ciintf_poll_slot_status;
-	budget_av->ca.data = budget_av;
-	budget_av->budget.ci_present = 1;
-	budget_av->slot_status = SLOTSTATUS_NONE;
-
-	if ((result = dvb_ca_en50221_init(&budget_av->budget.dvb_adapter,
-					  &budget_av->ca, 0, 1)) != 0) {
-		pr_err("ci initialisation failed\n");
-		goto error;
-	}
-
-	pr_info("ci interface initialised\n");
-	return 0;
-
-error:
-	saa7146_write(saa, MC1, MASK_27);
-	return result;
-}
-
-static void ciintf_deinit(struct budget_av *budget_av)
-{
-	struct saa7146_dev *saa = budget_av->budget.dev;
-
-	saa7146_setgpio(saa, 0, SAA7146_GPIO_INPUT);
-	saa7146_setgpio(saa, 1, SAA7146_GPIO_INPUT);
-	saa7146_setgpio(saa, 2, SAA7146_GPIO_INPUT);
-	saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
-
-	/* release the CA device */
-	dvb_ca_en50221_release(&budget_av->ca);
-
-	/* disable DEBI pins */
-	saa7146_write(saa, MC1, MASK_27);
-}
-
-
-static const u8 saa7113_tab[] = {
-	0x01, 0x08,
-	0x02, 0xc0,
-	0x03, 0x33,
-	0x04, 0x00,
-	0x05, 0x00,
-	0x06, 0xeb,
-	0x07, 0xe0,
-	0x08, 0x28,
-	0x09, 0x00,
-	0x0a, 0x80,
-	0x0b, 0x47,
-	0x0c, 0x40,
-	0x0d, 0x00,
-	0x0e, 0x01,
-	0x0f, 0x44,
-
-	0x10, 0x08,
-	0x11, 0x0c,
-	0x12, 0x7b,
-	0x13, 0x00,
-	0x15, 0x00, 0x16, 0x00, 0x17, 0x00,
-
-	0x57, 0xff,
-	0x40, 0x82, 0x58, 0x00, 0x59, 0x54, 0x5a, 0x07,
-	0x5b, 0x83, 0x5e, 0x00,
-	0xff
-};
-
-static int saa7113_init(struct budget_av *budget_av)
-{
-	struct budget *budget = &budget_av->budget;
-	struct saa7146_dev *saa = budget->dev;
-	const u8 *data = saa7113_tab;
-
-	saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTHI);
-	msleep(200);
-
-	if (i2c_writereg(&budget->i2c_adap, 0x4a, 0x01, 0x08) != 1) {
-		dprintk(1, "saa7113 not found on KNC card\n");
-		return -ENODEV;
-	}
-
-	dprintk(1, "saa7113 detected and initializing\n");
-
-	while (*data != 0xff) {
-		i2c_writereg(&budget->i2c_adap, 0x4a, *data, *(data + 1));
-		data += 2;
-	}
-
-	dprintk(1, "saa7113  status=%02x\n", i2c_readreg(&budget->i2c_adap, 0x4a, 0x1f));
-
-	return 0;
-}
-
-static int saa7113_setinput(struct budget_av *budget_av, int input)
-{
-	struct budget *budget = &budget_av->budget;
-
-	if (1 != budget_av->has_saa7113)
-		return -ENODEV;
-
-	if (input == 1) {
-		i2c_writereg(&budget->i2c_adap, 0x4a, 0x02, 0xc7);
-		i2c_writereg(&budget->i2c_adap, 0x4a, 0x09, 0x80);
-	} else if (input == 0) {
-		i2c_writereg(&budget->i2c_adap, 0x4a, 0x02, 0xc0);
-		i2c_writereg(&budget->i2c_adap, 0x4a, 0x09, 0x00);
-	} else
-		return -EINVAL;
-
-	budget_av->cur_input = input;
-	return 0;
-}
-
-
-static int philips_su1278_ty_ci_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ratio)
-{
-	u8 aclk = 0;
-	u8 bclk = 0;
-	u8 m1;
-
-	aclk = 0xb5;
-	if (srate < 2000000)
-		bclk = 0x86;
-	else if (srate < 5000000)
-		bclk = 0x89;
-	else if (srate < 15000000)
-		bclk = 0x8f;
-	else if (srate < 45000000)
-		bclk = 0x95;
-
-	m1 = 0x14;
-	if (srate < 4000000)
-		m1 = 0x10;
-
-	stv0299_writereg(fe, 0x13, aclk);
-	stv0299_writereg(fe, 0x14, bclk);
-	stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
-	stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff);
-	stv0299_writereg(fe, 0x21, (ratio) & 0xf0);
-	stv0299_writereg(fe, 0x0f, 0x80 | m1);
-
-	return 0;
-}
-
-static int philips_su1278_ty_ci_tuner_set_params(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	u32 div;
-	u8 buf[4];
-	struct budget *budget = (struct budget *) fe->dvb->priv;
-	struct i2c_msg msg = {.addr = 0x61,.flags = 0,.buf = buf,.len = sizeof(buf) };
-
-	if ((c->frequency < 950000) || (c->frequency > 2150000))
-		return -EINVAL;
-
-	div = (c->frequency + (125 - 1)) / 125;	/* round correctly */
-	buf[0] = (div >> 8) & 0x7f;
-	buf[1] = div & 0xff;
-	buf[2] = 0x80 | ((div & 0x18000) >> 10) | 4;
-	buf[3] = 0x20;
-
-	if (c->symbol_rate < 4000000)
-		buf[3] |= 1;
-
-	if (c->frequency < 1250000)
-		buf[3] |= 0;
-	else if (c->frequency < 1550000)
-		buf[3] |= 0x40;
-	else if (c->frequency < 2050000)
-		buf[3] |= 0x80;
-	else if (c->frequency < 2150000)
-		buf[3] |= 0xC0;
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	if (i2c_transfer(&budget->i2c_adap, &msg, 1) != 1)
-		return -EIO;
-	return 0;
-}
-
-static u8 typhoon_cinergy1200s_inittab[] = {
-	0x01, 0x15,
-	0x02, 0x30,
-	0x03, 0x00,
-	0x04, 0x7d,		/* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */
-	0x05, 0x35,		/* I2CT = 0, SCLT = 1, SDAT = 1 */
-	0x06, 0x40,		/* DAC not used, set to high impendance mode */
-	0x07, 0x00,		/* DAC LSB */
-	0x08, 0x40,		/* DiSEqC off */
-	0x09, 0x00,		/* FIFO */
-	0x0c, 0x51,		/* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */
-	0x0d, 0x82,		/* DC offset compensation = ON, beta_agc1 = 2 */
-	0x0e, 0x23,		/* alpha_tmg = 2, beta_tmg = 3 */
-	0x10, 0x3f,		// AGC2  0x3d
-	0x11, 0x84,
-	0x12, 0xb9,
-	0x15, 0xc9,		// lock detector threshold
-	0x16, 0x00,
-	0x17, 0x00,
-	0x18, 0x00,
-	0x19, 0x00,
-	0x1a, 0x00,
-	0x1f, 0x50,
-	0x20, 0x00,
-	0x21, 0x00,
-	0x22, 0x00,
-	0x23, 0x00,
-	0x28, 0x00,		// out imp: normal  out type: parallel FEC mode:0
-	0x29, 0x1e,		// 1/2 threshold
-	0x2a, 0x14,		// 2/3 threshold
-	0x2b, 0x0f,		// 3/4 threshold
-	0x2c, 0x09,		// 5/6 threshold
-	0x2d, 0x05,		// 7/8 threshold
-	0x2e, 0x01,
-	0x31, 0x1f,		// test all FECs
-	0x32, 0x19,		// viterbi and synchro search
-	0x33, 0xfc,		// rs control
-	0x34, 0x93,		// error control
-	0x0f, 0x92,
-	0xff, 0xff
-};
-
-static struct stv0299_config typhoon_config = {
-	.demod_address = 0x68,
-	.inittab = typhoon_cinergy1200s_inittab,
-	.mclk = 88000000UL,
-	.invert = 0,
-	.skip_reinit = 0,
-	.lock_output = STV0299_LOCKOUTPUT_1,
-	.volt13_op0_op1 = STV0299_VOLT13_OP0,
-	.min_delay_ms = 100,
-	.set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate,
-};
-
-
-static struct stv0299_config cinergy_1200s_config = {
-	.demod_address = 0x68,
-	.inittab = typhoon_cinergy1200s_inittab,
-	.mclk = 88000000UL,
-	.invert = 0,
-	.skip_reinit = 0,
-	.lock_output = STV0299_LOCKOUTPUT_0,
-	.volt13_op0_op1 = STV0299_VOLT13_OP0,
-	.min_delay_ms = 100,
-	.set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate,
-};
-
-static struct stv0299_config cinergy_1200s_1894_0010_config = {
-	.demod_address = 0x68,
-	.inittab = typhoon_cinergy1200s_inittab,
-	.mclk = 88000000UL,
-	.invert = 1,
-	.skip_reinit = 0,
-	.lock_output = STV0299_LOCKOUTPUT_1,
-	.volt13_op0_op1 = STV0299_VOLT13_OP0,
-	.min_delay_ms = 100,
-	.set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate,
-};
-
-static int philips_cu1216_tuner_set_params(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	struct budget *budget = (struct budget *) fe->dvb->priv;
-	u8 buf[6];
-	struct i2c_msg msg = {.addr = 0x60,.flags = 0,.buf = buf,.len = sizeof(buf) };
-	int i;
-
-#define CU1216_IF 36125000
-#define TUNER_MUL 62500
-
-	u32 div = (c->frequency + CU1216_IF + TUNER_MUL / 2) / TUNER_MUL;
-
-	buf[0] = (div >> 8) & 0x7f;
-	buf[1] = div & 0xff;
-	buf[2] = 0xce;
-	buf[3] = (c->frequency < 150000000 ? 0x01 :
-		  c->frequency < 445000000 ? 0x02 : 0x04);
-	buf[4] = 0xde;
-	buf[5] = 0x20;
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	if (i2c_transfer(&budget->i2c_adap, &msg, 1) != 1)
-		return -EIO;
-
-	/* wait for the pll lock */
-	msg.flags = I2C_M_RD;
-	msg.len = 1;
-	for (i = 0; i < 20; i++) {
-		if (fe->ops.i2c_gate_ctrl)
-			fe->ops.i2c_gate_ctrl(fe, 1);
-		if (i2c_transfer(&budget->i2c_adap, &msg, 1) == 1 && (buf[0] & 0x40))
-			break;
-		msleep(10);
-	}
-
-	/* switch the charge pump to the lower current */
-	msg.flags = 0;
-	msg.len = 2;
-	msg.buf = &buf[2];
-	buf[2] &= ~0x40;
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	if (i2c_transfer(&budget->i2c_adap, &msg, 1) != 1)
-		return -EIO;
-
-	return 0;
-}
-
-static struct tda1002x_config philips_cu1216_config = {
-	.demod_address = 0x0c,
-	.invert = 1,
-};
-
-static struct tda1002x_config philips_cu1216_config_altaddress = {
-	.demod_address = 0x0d,
-	.invert = 0,
-};
-
-static struct tda10023_config philips_cu1216_tda10023_config = {
-	.demod_address = 0x0c,
-	.invert = 1,
-};
-
-static int philips_tu1216_tuner_init(struct dvb_frontend *fe)
-{
-	struct budget *budget = (struct budget *) fe->dvb->priv;
-	static u8 tu1216_init[] = { 0x0b, 0xf5, 0x85, 0xab };
-	struct i2c_msg tuner_msg = {.addr = 0x60,.flags = 0,.buf = tu1216_init,.len = sizeof(tu1216_init) };
-
-	// setup PLL configuration
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	if (i2c_transfer(&budget->i2c_adap, &tuner_msg, 1) != 1)
-		return -EIO;
-	msleep(1);
-
-	return 0;
-}
-
-static int philips_tu1216_tuner_set_params(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	struct budget *budget = (struct budget *) fe->dvb->priv;
-	u8 tuner_buf[4];
-	struct i2c_msg tuner_msg = {.addr = 0x60,.flags = 0,.buf = tuner_buf,.len =
-			sizeof(tuner_buf) };
-	int tuner_frequency = 0;
-	u8 band, cp, filter;
-
-	// determine charge pump
-	tuner_frequency = c->frequency + 36166000;
-	if (tuner_frequency < 87000000)
-		return -EINVAL;
-	else if (tuner_frequency < 130000000)
-		cp = 3;
-	else if (tuner_frequency < 160000000)
-		cp = 5;
-	else if (tuner_frequency < 200000000)
-		cp = 6;
-	else if (tuner_frequency < 290000000)
-		cp = 3;
-	else if (tuner_frequency < 420000000)
-		cp = 5;
-	else if (tuner_frequency < 480000000)
-		cp = 6;
-	else if (tuner_frequency < 620000000)
-		cp = 3;
-	else if (tuner_frequency < 830000000)
-		cp = 5;
-	else if (tuner_frequency < 895000000)
-		cp = 7;
-	else
-		return -EINVAL;
-
-	// determine band
-	if (c->frequency < 49000000)
-		return -EINVAL;
-	else if (c->frequency < 161000000)
-		band = 1;
-	else if (c->frequency < 444000000)
-		band = 2;
-	else if (c->frequency < 861000000)
-		band = 4;
-	else
-		return -EINVAL;
-
-	// setup PLL filter
-	switch (c->bandwidth_hz) {
-	case 6000000:
-		filter = 0;
-		break;
-
-	case 7000000:
-		filter = 0;
-		break;
-
-	case 8000000:
-		filter = 1;
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	// calculate divisor
-	// ((36166000+((1000000/6)/2)) + Finput)/(1000000/6)
-	tuner_frequency = (((c->frequency / 1000) * 6) + 217496) / 1000;
-
-	// setup tuner buffer
-	tuner_buf[0] = (tuner_frequency >> 8) & 0x7f;
-	tuner_buf[1] = tuner_frequency & 0xff;
-	tuner_buf[2] = 0xca;
-	tuner_buf[3] = (cp << 5) | (filter << 3) | band;
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	if (i2c_transfer(&budget->i2c_adap, &tuner_msg, 1) != 1)
-		return -EIO;
-
-	msleep(1);
-	return 0;
-}
-
-static int philips_tu1216_request_firmware(struct dvb_frontend *fe,
-					   const struct firmware **fw, char *name)
-{
-	struct budget *budget = (struct budget *) fe->dvb->priv;
-
-	return request_firmware(fw, name, &budget->dev->pci->dev);
-}
-
-static struct tda1004x_config philips_tu1216_config = {
-
-	.demod_address = 0x8,
-	.invert = 1,
-	.invert_oclk = 1,
-	.xtal_freq = TDA10046_XTAL_4M,
-	.agc_config = TDA10046_AGC_DEFAULT,
-	.if_freq = TDA10046_FREQ_3617,
-	.request_firmware = philips_tu1216_request_firmware,
-};
-
-static u8 philips_sd1878_inittab[] = {
-	0x01, 0x15,
-	0x02, 0x30,
-	0x03, 0x00,
-	0x04, 0x7d,
-	0x05, 0x35,
-	0x06, 0x40,
-	0x07, 0x00,
-	0x08, 0x43,
-	0x09, 0x02,
-	0x0C, 0x51,
-	0x0D, 0x82,
-	0x0E, 0x23,
-	0x10, 0x3f,
-	0x11, 0x84,
-	0x12, 0xb9,
-	0x15, 0xc9,
-	0x16, 0x19,
-	0x17, 0x8c,
-	0x18, 0x59,
-	0x19, 0xf8,
-	0x1a, 0xfe,
-	0x1c, 0x7f,
-	0x1d, 0x00,
-	0x1e, 0x00,
-	0x1f, 0x50,
-	0x20, 0x00,
-	0x21, 0x00,
-	0x22, 0x00,
-	0x23, 0x00,
-	0x28, 0x00,
-	0x29, 0x28,
-	0x2a, 0x14,
-	0x2b, 0x0f,
-	0x2c, 0x09,
-	0x2d, 0x09,
-	0x31, 0x1f,
-	0x32, 0x19,
-	0x33, 0xfc,
-	0x34, 0x93,
-	0xff, 0xff
-};
-
-static int philips_sd1878_ci_set_symbol_rate(struct dvb_frontend *fe,
-		u32 srate, u32 ratio)
-{
-	u8 aclk = 0;
-	u8 bclk = 0;
-	u8 m1;
-
-	aclk = 0xb5;
-	if (srate < 2000000)
-		bclk = 0x86;
-	else if (srate < 5000000)
-		bclk = 0x89;
-	else if (srate < 15000000)
-		bclk = 0x8f;
-	else if (srate < 45000000)
-		bclk = 0x95;
-
-	m1 = 0x14;
-	if (srate < 4000000)
-		m1 = 0x10;
-
-	stv0299_writereg(fe, 0x0e, 0x23);
-	stv0299_writereg(fe, 0x0f, 0x94);
-	stv0299_writereg(fe, 0x10, 0x39);
-	stv0299_writereg(fe, 0x13, aclk);
-	stv0299_writereg(fe, 0x14, bclk);
-	stv0299_writereg(fe, 0x15, 0xc9);
-	stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
-	stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff);
-	stv0299_writereg(fe, 0x21, (ratio) & 0xf0);
-	stv0299_writereg(fe, 0x0f, 0x80 | m1);
-
-	return 0;
-}
-
-static struct stv0299_config philips_sd1878_config = {
-	.demod_address = 0x68,
-     .inittab = philips_sd1878_inittab,
-	.mclk = 88000000UL,
-	.invert = 0,
-	.skip_reinit = 0,
-	.lock_output = STV0299_LOCKOUTPUT_1,
-	.volt13_op0_op1 = STV0299_VOLT13_OP0,
-	.min_delay_ms = 100,
-	.set_symbol_rate = philips_sd1878_ci_set_symbol_rate,
-};
-
-/* KNC1 DVB-S (STB0899) Inittab	*/
-static const struct stb0899_s1_reg knc1_stb0899_s1_init_1[] = {
-
-	{ STB0899_DEV_ID		, 0x81 },
-	{ STB0899_DISCNTRL1		, 0x32 },
-	{ STB0899_DISCNTRL2		, 0x80 },
-	{ STB0899_DISRX_ST0		, 0x04 },
-	{ STB0899_DISRX_ST1		, 0x00 },
-	{ STB0899_DISPARITY		, 0x00 },
-	{ STB0899_DISSTATUS		, 0x20 },
-	{ STB0899_DISF22		, 0x8c },
-	{ STB0899_DISF22RX		, 0x9a },
-	{ STB0899_SYSREG		, 0x0b },
-	{ STB0899_ACRPRESC		, 0x11 },
-	{ STB0899_ACRDIV1		, 0x0a },
-	{ STB0899_ACRDIV2		, 0x05 },
-	{ STB0899_DACR1			, 0x00 },
-	{ STB0899_DACR2			, 0x00 },
-	{ STB0899_OUTCFG		, 0x00 },
-	{ STB0899_MODECFG		, 0x00 },
-	{ STB0899_IRQSTATUS_3		, 0x30 },
-	{ STB0899_IRQSTATUS_2		, 0x00 },
-	{ STB0899_IRQSTATUS_1		, 0x00 },
-	{ STB0899_IRQSTATUS_0		, 0x00 },
-	{ STB0899_IRQMSK_3		, 0xf3 },
-	{ STB0899_IRQMSK_2		, 0xfc },
-	{ STB0899_IRQMSK_1		, 0xff },
-	{ STB0899_IRQMSK_0		, 0xff },
-	{ STB0899_IRQCFG		, 0x00 },
-	{ STB0899_I2CCFG		, 0x88 },
-	{ STB0899_I2CRPT		, 0x58 }, /* Repeater=8, Stop=disabled */
-	{ STB0899_IOPVALUE5		, 0x00 },
-	{ STB0899_IOPVALUE4		, 0x20 },
-	{ STB0899_IOPVALUE3		, 0xc9 },
-	{ STB0899_IOPVALUE2		, 0x90 },
-	{ STB0899_IOPVALUE1		, 0x40 },
-	{ STB0899_IOPVALUE0		, 0x00 },
-	{ STB0899_GPIO00CFG		, 0x82 },
-	{ STB0899_GPIO01CFG		, 0x82 },
-	{ STB0899_GPIO02CFG		, 0x82 },
-	{ STB0899_GPIO03CFG		, 0x82 },
-	{ STB0899_GPIO04CFG		, 0x82 },
-	{ STB0899_GPIO05CFG		, 0x82 },
-	{ STB0899_GPIO06CFG		, 0x82 },
-	{ STB0899_GPIO07CFG		, 0x82 },
-	{ STB0899_GPIO08CFG		, 0x82 },
-	{ STB0899_GPIO09CFG		, 0x82 },
-	{ STB0899_GPIO10CFG		, 0x82 },
-	{ STB0899_GPIO11CFG		, 0x82 },
-	{ STB0899_GPIO12CFG		, 0x82 },
-	{ STB0899_GPIO13CFG		, 0x82 },
-	{ STB0899_GPIO14CFG		, 0x82 },
-	{ STB0899_GPIO15CFG		, 0x82 },
-	{ STB0899_GPIO16CFG		, 0x82 },
-	{ STB0899_GPIO17CFG		, 0x82 },
-	{ STB0899_GPIO18CFG		, 0x82 },
-	{ STB0899_GPIO19CFG		, 0x82 },
-	{ STB0899_GPIO20CFG		, 0x82 },
-	{ STB0899_SDATCFG		, 0xb8 },
-	{ STB0899_SCLTCFG		, 0xba },
-	{ STB0899_AGCRFCFG		, 0x08 }, /* 0x1c */
-	{ STB0899_GPIO22		, 0x82 }, /* AGCBB2CFG */
-	{ STB0899_GPIO21		, 0x91 }, /* AGCBB1CFG */
-	{ STB0899_DIRCLKCFG		, 0x82 },
-	{ STB0899_CLKOUT27CFG		, 0x7e },
-	{ STB0899_STDBYCFG		, 0x82 },
-	{ STB0899_CS0CFG		, 0x82 },
-	{ STB0899_CS1CFG		, 0x82 },
-	{ STB0899_DISEQCOCFG		, 0x20 },
-	{ STB0899_GPIO32CFG		, 0x82 },
-	{ STB0899_GPIO33CFG		, 0x82 },
-	{ STB0899_GPIO34CFG		, 0x82 },
-	{ STB0899_GPIO35CFG		, 0x82 },
-	{ STB0899_GPIO36CFG		, 0x82 },
-	{ STB0899_GPIO37CFG		, 0x82 },
-	{ STB0899_GPIO38CFG		, 0x82 },
-	{ STB0899_GPIO39CFG		, 0x82 },
-	{ STB0899_NCOARSE		, 0x15 }, /* 0x15 = 27 Mhz Clock, F/3 = 198MHz, F/6 = 99MHz */
-	{ STB0899_SYNTCTRL		, 0x02 }, /* 0x00 = CLK from CLKI, 0x02 = CLK from XTALI */
-	{ STB0899_FILTCTRL		, 0x00 },
-	{ STB0899_SYSCTRL		, 0x00 },
-	{ STB0899_STOPCLK1		, 0x20 },
-	{ STB0899_STOPCLK2		, 0x00 },
-	{ STB0899_INTBUFSTATUS		, 0x00 },
-	{ STB0899_INTBUFCTRL		, 0x0a },
-	{ 0xffff			, 0xff },
-};
-
-static const struct stb0899_s1_reg knc1_stb0899_s1_init_3[] = {
-	{ STB0899_DEMOD			, 0x00 },
-	{ STB0899_RCOMPC		, 0xc9 },
-	{ STB0899_AGC1CN		, 0x41 },
-	{ STB0899_AGC1REF		, 0x08 },
-	{ STB0899_RTC			, 0x7a },
-	{ STB0899_TMGCFG		, 0x4e },
-	{ STB0899_AGC2REF		, 0x33 },
-	{ STB0899_TLSR			, 0x84 },
-	{ STB0899_CFD			, 0xee },
-	{ STB0899_ACLC			, 0x87 },
-	{ STB0899_BCLC			, 0x94 },
-	{ STB0899_EQON			, 0x41 },
-	{ STB0899_LDT			, 0xdd },
-	{ STB0899_LDT2			, 0xc9 },
-	{ STB0899_EQUALREF		, 0xb4 },
-	{ STB0899_TMGRAMP		, 0x10 },
-	{ STB0899_TMGTHD		, 0x30 },
-	{ STB0899_IDCCOMP		, 0xfb },
-	{ STB0899_QDCCOMP		, 0x03 },
-	{ STB0899_POWERI		, 0x3b },
-	{ STB0899_POWERQ		, 0x3d },
-	{ STB0899_RCOMP			, 0x81 },
-	{ STB0899_AGCIQIN		, 0x80 },
-	{ STB0899_AGC2I1		, 0x04 },
-	{ STB0899_AGC2I2		, 0xf5 },
-	{ STB0899_TLIR			, 0x25 },
-	{ STB0899_RTF			, 0x80 },
-	{ STB0899_DSTATUS		, 0x00 },
-	{ STB0899_LDI			, 0xca },
-	{ STB0899_CFRM			, 0xf1 },
-	{ STB0899_CFRL			, 0xf3 },
-	{ STB0899_NIRM			, 0x2a },
-	{ STB0899_NIRL			, 0x05 },
-	{ STB0899_ISYMB			, 0x17 },
-	{ STB0899_QSYMB			, 0xfa },
-	{ STB0899_SFRH			, 0x2f },
-	{ STB0899_SFRM			, 0x68 },
-	{ STB0899_SFRL			, 0x40 },
-	{ STB0899_SFRUPH		, 0x2f },
-	{ STB0899_SFRUPM		, 0x68 },
-	{ STB0899_SFRUPL		, 0x40 },
-	{ STB0899_EQUAI1		, 0xfd },
-	{ STB0899_EQUAQ1		, 0x04 },
-	{ STB0899_EQUAI2		, 0x0f },
-	{ STB0899_EQUAQ2		, 0xff },
-	{ STB0899_EQUAI3		, 0xdf },
-	{ STB0899_EQUAQ3		, 0xfa },
-	{ STB0899_EQUAI4		, 0x37 },
-	{ STB0899_EQUAQ4		, 0x0d },
-	{ STB0899_EQUAI5		, 0xbd },
-	{ STB0899_EQUAQ5		, 0xf7 },
-	{ STB0899_DSTATUS2		, 0x00 },
-	{ STB0899_VSTATUS		, 0x00 },
-	{ STB0899_VERROR		, 0xff },
-	{ STB0899_IQSWAP		, 0x2a },
-	{ STB0899_ECNT1M		, 0x00 },
-	{ STB0899_ECNT1L		, 0x00 },
-	{ STB0899_ECNT2M		, 0x00 },
-	{ STB0899_ECNT2L		, 0x00 },
-	{ STB0899_ECNT3M		, 0x00 },
-	{ STB0899_ECNT3L		, 0x00 },
-	{ STB0899_FECAUTO1		, 0x06 },
-	{ STB0899_FECM			, 0x01 },
-	{ STB0899_VTH12			, 0xf0 },
-	{ STB0899_VTH23			, 0xa0 },
-	{ STB0899_VTH34			, 0x78 },
-	{ STB0899_VTH56			, 0x4e },
-	{ STB0899_VTH67			, 0x48 },
-	{ STB0899_VTH78			, 0x38 },
-	{ STB0899_PRVIT			, 0xff },
-	{ STB0899_VITSYNC		, 0x19 },
-	{ STB0899_RSULC			, 0xb1 }, /* DVB = 0xb1, DSS = 0xa1 */
-	{ STB0899_TSULC			, 0x42 },
-	{ STB0899_RSLLC			, 0x40 },
-	{ STB0899_TSLPL			, 0x12 },
-	{ STB0899_TSCFGH		, 0x0c },
-	{ STB0899_TSCFGM		, 0x00 },
-	{ STB0899_TSCFGL		, 0x0c },
-	{ STB0899_TSOUT			, 0x4d }, /* 0x0d for CAM */
-	{ STB0899_RSSYNCDEL		, 0x00 },
-	{ STB0899_TSINHDELH		, 0x02 },
-	{ STB0899_TSINHDELM		, 0x00 },
-	{ STB0899_TSINHDELL		, 0x00 },
-	{ STB0899_TSLLSTKM		, 0x00 },
-	{ STB0899_TSLLSTKL		, 0x00 },
-	{ STB0899_TSULSTKM		, 0x00 },
-	{ STB0899_TSULSTKL		, 0xab },
-	{ STB0899_PCKLENUL		, 0x00 },
-	{ STB0899_PCKLENLL		, 0xcc },
-	{ STB0899_RSPCKLEN		, 0xcc },
-	{ STB0899_TSSTATUS		, 0x80 },
-	{ STB0899_ERRCTRL1		, 0xb6 },
-	{ STB0899_ERRCTRL2		, 0x96 },
-	{ STB0899_ERRCTRL3		, 0x89 },
-	{ STB0899_DMONMSK1		, 0x27 },
-	{ STB0899_DMONMSK0		, 0x03 },
-	{ STB0899_DEMAPVIT		, 0x5c },
-	{ STB0899_PLPARM		, 0x1f },
-	{ STB0899_PDELCTRL		, 0x48 },
-	{ STB0899_PDELCTRL2		, 0x00 },
-	{ STB0899_BBHCTRL1		, 0x00 },
-	{ STB0899_BBHCTRL2		, 0x00 },
-	{ STB0899_HYSTTHRESH		, 0x77 },
-	{ STB0899_MATCSTM		, 0x00 },
-	{ STB0899_MATCSTL		, 0x00 },
-	{ STB0899_UPLCSTM		, 0x00 },
-	{ STB0899_UPLCSTL		, 0x00 },
-	{ STB0899_DFLCSTM		, 0x00 },
-	{ STB0899_DFLCSTL		, 0x00 },
-	{ STB0899_SYNCCST		, 0x00 },
-	{ STB0899_SYNCDCSTM		, 0x00 },
-	{ STB0899_SYNCDCSTL		, 0x00 },
-	{ STB0899_ISI_ENTRY		, 0x00 },
-	{ STB0899_ISI_BIT_EN		, 0x00 },
-	{ STB0899_MATSTRM		, 0x00 },
-	{ STB0899_MATSTRL		, 0x00 },
-	{ STB0899_UPLSTRM		, 0x00 },
-	{ STB0899_UPLSTRL		, 0x00 },
-	{ STB0899_DFLSTRM		, 0x00 },
-	{ STB0899_DFLSTRL		, 0x00 },
-	{ STB0899_SYNCSTR		, 0x00 },
-	{ STB0899_SYNCDSTRM		, 0x00 },
-	{ STB0899_SYNCDSTRL		, 0x00 },
-	{ STB0899_CFGPDELSTATUS1	, 0x10 },
-	{ STB0899_CFGPDELSTATUS2	, 0x00 },
-	{ STB0899_BBFERRORM		, 0x00 },
-	{ STB0899_BBFERRORL		, 0x00 },
-	{ STB0899_UPKTERRORM		, 0x00 },
-	{ STB0899_UPKTERRORL		, 0x00 },
-	{ 0xffff			, 0xff },
-};
-
-/* STB0899 demodulator config for the KNC1 and clones */
-static struct stb0899_config knc1_dvbs2_config = {
-	.init_dev		= knc1_stb0899_s1_init_1,
-	.init_s2_demod		= stb0899_s2_init_2,
-	.init_s1_demod		= knc1_stb0899_s1_init_3,
-	.init_s2_fec		= stb0899_s2_init_4,
-	.init_tst		= stb0899_s1_init_5,
-
-	.postproc		= NULL,
-
-	.demod_address		= 0x68,
-//	.ts_output_mode		= STB0899_OUT_PARALLEL,	/* types = SERIAL/PARALLEL	*/
-	.block_sync_mode	= STB0899_SYNC_FORCED,	/* DSS, SYNC_FORCED/UNSYNCED	*/
-//	.ts_pfbit_toggle	= STB0899_MPEG_NORMAL,	/* DirecTV, MPEG toggling seq	*/
-
-	.xtal_freq		= 27000000,
-	.inversion		= IQ_SWAP_OFF, /* 1 */
-
-	.lo_clk			= 76500000,
-	.hi_clk			= 90000000,
-
-	.esno_ave		= STB0899_DVBS2_ESNO_AVE,
-	.esno_quant		= STB0899_DVBS2_ESNO_QUANT,
-	.avframes_coarse	= STB0899_DVBS2_AVFRAMES_COARSE,
-	.avframes_fine		= STB0899_DVBS2_AVFRAMES_FINE,
-	.miss_threshold		= STB0899_DVBS2_MISS_THRESHOLD,
-	.uwp_threshold_acq	= STB0899_DVBS2_UWP_THRESHOLD_ACQ,
-	.uwp_threshold_track	= STB0899_DVBS2_UWP_THRESHOLD_TRACK,
-	.uwp_threshold_sof	= STB0899_DVBS2_UWP_THRESHOLD_SOF,
-	.sof_search_timeout	= STB0899_DVBS2_SOF_SEARCH_TIMEOUT,
-
-	.btr_nco_bits		= STB0899_DVBS2_BTR_NCO_BITS,
-	.btr_gain_shift_offset	= STB0899_DVBS2_BTR_GAIN_SHIFT_OFFSET,
-	.crl_nco_bits		= STB0899_DVBS2_CRL_NCO_BITS,
-	.ldpc_max_iter		= STB0899_DVBS2_LDPC_MAX_ITER,
-
-	.tuner_get_frequency	= tda8261_get_frequency,
-	.tuner_set_frequency	= tda8261_set_frequency,
-	.tuner_set_bandwidth	= NULL,
-	.tuner_get_bandwidth	= tda8261_get_bandwidth,
-	.tuner_set_rfsiggain	= NULL
-};
-
-/*
- * SD1878/SHA tuner config
- * 1F, Single I/P, Horizontal mount, High Sensitivity
- */
-static const struct tda8261_config sd1878c_config = {
-//	.name		= "SD1878/SHA",
-	.addr		= 0x60,
-	.step_size	= TDA8261_STEP_1000 /* kHz */
-};
-
-static u8 read_pwm(struct budget_av *budget_av)
-{
-	u8 b = 0xff;
-	u8 pwm;
-	struct i2c_msg msg[] = { {.addr = 0x50,.flags = 0,.buf = &b,.len = 1},
-	{.addr = 0x50,.flags = I2C_M_RD,.buf = &pwm,.len = 1}
-	};
-
-	if ((i2c_transfer(&budget_av->budget.i2c_adap, msg, 2) != 2)
-	    || (pwm == 0xff))
-		pwm = 0x48;
-
-	return pwm;
-}
-
-#define SUBID_DVBS_KNC1			0x0010
-#define SUBID_DVBS_KNC1_PLUS		0x0011
-#define SUBID_DVBS_TYPHOON		0x4f56
-#define SUBID_DVBS_CINERGY1200		0x1154
-#define SUBID_DVBS_CYNERGY1200N 	0x1155
-#define SUBID_DVBS_TV_STAR		0x0014
-#define SUBID_DVBS_TV_STAR_PLUS_X4	0x0015
-#define SUBID_DVBS_TV_STAR_CI		0x0016
-#define SUBID_DVBS2_KNC1		0x0018
-#define SUBID_DVBS2_KNC1_OEM		0x0019
-#define SUBID_DVBS_EASYWATCH_1  	0x001a
-#define SUBID_DVBS_EASYWATCH_2  	0x001b
-#define SUBID_DVBS2_EASYWATCH		0x001d
-#define SUBID_DVBS_EASYWATCH		0x001e
-
-#define SUBID_DVBC_EASYWATCH		0x002a
-#define SUBID_DVBC_EASYWATCH_MK3	0x002c
-#define SUBID_DVBC_KNC1			0x0020
-#define SUBID_DVBC_KNC1_PLUS		0x0021
-#define SUBID_DVBC_KNC1_MK3		0x0022
-#define SUBID_DVBC_KNC1_TDA10024	0x0028
-#define SUBID_DVBC_KNC1_PLUS_MK3	0x0023
-#define SUBID_DVBC_CINERGY1200		0x1156
-#define SUBID_DVBC_CINERGY1200_MK3	0x1176
-
-#define SUBID_DVBT_EASYWATCH		0x003a
-#define SUBID_DVBT_KNC1_PLUS		0x0031
-#define SUBID_DVBT_KNC1			0x0030
-#define SUBID_DVBT_CINERGY1200		0x1157
-
-static void frontend_init(struct budget_av *budget_av)
-{
-	struct saa7146_dev * saa = budget_av->budget.dev;
-	struct dvb_frontend * fe = NULL;
-
-	/* Enable / PowerON Frontend */
-	saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO);
-
-	/* Wait for PowerON */
-	msleep(100);
-
-	/* additional setup necessary for the PLUS cards */
-	switch (saa->pci->subsystem_device) {
-		case SUBID_DVBS_KNC1_PLUS:
-		case SUBID_DVBC_KNC1_PLUS:
-		case SUBID_DVBT_KNC1_PLUS:
-		case SUBID_DVBC_EASYWATCH:
-		case SUBID_DVBC_KNC1_PLUS_MK3:
-		case SUBID_DVBS2_KNC1:
-		case SUBID_DVBS2_KNC1_OEM:
-		case SUBID_DVBS2_EASYWATCH:
-			saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTHI);
-			break;
-	}
-
-	switch (saa->pci->subsystem_device) {
-
-	case SUBID_DVBS_KNC1:
-		/*
-		 * maybe that setting is needed for other dvb-s cards as well,
-		 * but so far it has been only confirmed for this type
-		 */
-		budget_av->reinitialise_demod = 1;
-		/* fall through */
-	case SUBID_DVBS_KNC1_PLUS:
-	case SUBID_DVBS_EASYWATCH_1:
-		if (saa->pci->subsystem_vendor == 0x1894) {
-			fe = dvb_attach(stv0299_attach, &cinergy_1200s_1894_0010_config,
-					     &budget_av->budget.i2c_adap);
-			if (fe) {
-				dvb_attach(tua6100_attach, fe, 0x60, &budget_av->budget.i2c_adap);
-			}
-		} else {
-			fe = dvb_attach(stv0299_attach, &typhoon_config,
-					     &budget_av->budget.i2c_adap);
-			if (fe) {
-				fe->ops.tuner_ops.set_params = philips_su1278_ty_ci_tuner_set_params;
-			}
-		}
-		break;
-
-	case SUBID_DVBS_TV_STAR:
-	case SUBID_DVBS_TV_STAR_PLUS_X4:
-	case SUBID_DVBS_TV_STAR_CI:
-	case SUBID_DVBS_CYNERGY1200N:
-	case SUBID_DVBS_EASYWATCH:
-	case SUBID_DVBS_EASYWATCH_2:
-		fe = dvb_attach(stv0299_attach, &philips_sd1878_config,
-				&budget_av->budget.i2c_adap);
-		if (fe) {
-			dvb_attach(dvb_pll_attach, fe, 0x60,
-				   &budget_av->budget.i2c_adap,
-				   DVB_PLL_PHILIPS_SD1878_TDA8261);
-		}
-		break;
-
-	case SUBID_DVBS_TYPHOON:
-		fe = dvb_attach(stv0299_attach, &typhoon_config,
-				    &budget_av->budget.i2c_adap);
-		if (fe) {
-			fe->ops.tuner_ops.set_params = philips_su1278_ty_ci_tuner_set_params;
-		}
-		break;
-	case SUBID_DVBS2_KNC1:
-	case SUBID_DVBS2_KNC1_OEM:
-	case SUBID_DVBS2_EASYWATCH:
-		budget_av->reinitialise_demod = 1;
-		if ((fe = dvb_attach(stb0899_attach, &knc1_dvbs2_config, &budget_av->budget.i2c_adap)))
-			dvb_attach(tda8261_attach, fe, &sd1878c_config, &budget_av->budget.i2c_adap);
-
-		break;
-	case SUBID_DVBS_CINERGY1200:
-		fe = dvb_attach(stv0299_attach, &cinergy_1200s_config,
-				    &budget_av->budget.i2c_adap);
-		if (fe) {
-			fe->ops.tuner_ops.set_params = philips_su1278_ty_ci_tuner_set_params;
-		}
-		break;
-
-	case SUBID_DVBC_KNC1:
-	case SUBID_DVBC_KNC1_PLUS:
-	case SUBID_DVBC_CINERGY1200:
-	case SUBID_DVBC_EASYWATCH:
-		budget_av->reinitialise_demod = 1;
-		budget_av->budget.dev->i2c_bitrate = SAA7146_I2C_BUS_BIT_RATE_240;
-		fe = dvb_attach(tda10021_attach, &philips_cu1216_config,
-				     &budget_av->budget.i2c_adap,
-				     read_pwm(budget_av));
-		if (fe == NULL)
-			fe = dvb_attach(tda10021_attach, &philips_cu1216_config_altaddress,
-					     &budget_av->budget.i2c_adap,
-					     read_pwm(budget_av));
-		if (fe) {
-			fe->ops.tuner_ops.set_params = philips_cu1216_tuner_set_params;
-		}
-		break;
-
-	case SUBID_DVBC_EASYWATCH_MK3:
-	case SUBID_DVBC_CINERGY1200_MK3:
-	case SUBID_DVBC_KNC1_MK3:
-	case SUBID_DVBC_KNC1_TDA10024:
-	case SUBID_DVBC_KNC1_PLUS_MK3:
-		budget_av->reinitialise_demod = 1;
-		budget_av->budget.dev->i2c_bitrate = SAA7146_I2C_BUS_BIT_RATE_240;
-		fe = dvb_attach(tda10023_attach,
-			&philips_cu1216_tda10023_config,
-			&budget_av->budget.i2c_adap,
-			read_pwm(budget_av));
-		if (fe) {
-			fe->ops.tuner_ops.set_params = philips_cu1216_tuner_set_params;
-		}
-		break;
-
-	case SUBID_DVBT_EASYWATCH:
-	case SUBID_DVBT_KNC1:
-	case SUBID_DVBT_KNC1_PLUS:
-	case SUBID_DVBT_CINERGY1200:
-		budget_av->reinitialise_demod = 1;
-		fe = dvb_attach(tda10046_attach, &philips_tu1216_config,
-				     &budget_av->budget.i2c_adap);
-		if (fe) {
-			fe->ops.tuner_ops.init = philips_tu1216_tuner_init;
-			fe->ops.tuner_ops.set_params = philips_tu1216_tuner_set_params;
-		}
-		break;
-	}
-
-	if (fe == NULL) {
-		pr_err("A frontend driver was not found for device [%04x:%04x] subsystem [%04x:%04x]\n",
-		       saa->pci->vendor,
-		       saa->pci->device,
-		       saa->pci->subsystem_vendor,
-		       saa->pci->subsystem_device);
-		return;
-	}
-
-	budget_av->budget.dvb_frontend = fe;
-
-	if (dvb_register_frontend(&budget_av->budget.dvb_adapter,
-				  budget_av->budget.dvb_frontend)) {
-		pr_err("Frontend registration failed!\n");
-		dvb_frontend_detach(budget_av->budget.dvb_frontend);
-		budget_av->budget.dvb_frontend = NULL;
-	}
-}
-
-
-static void budget_av_irq(struct saa7146_dev *dev, u32 * isr)
-{
-	struct budget_av *budget_av = (struct budget_av *) dev->ext_priv;
-
-	dprintk(8, "dev: %p, budget_av: %p\n", dev, budget_av);
-
-	if (*isr & MASK_10)
-		ttpci_budget_irq10_handler(dev, isr);
-}
-
-static int budget_av_detach(struct saa7146_dev *dev)
-{
-	struct budget_av *budget_av = (struct budget_av *) dev->ext_priv;
-	int err;
-
-	dprintk(2, "dev: %p\n", dev);
-
-	if (1 == budget_av->has_saa7113) {
-		saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTLO);
-
-		msleep(200);
-
-		saa7146_unregister_device(&budget_av->vd, dev);
-
-		saa7146_vv_release(dev);
-	}
-
-	if (budget_av->budget.ci_present)
-		ciintf_deinit(budget_av);
-
-	if (budget_av->budget.dvb_frontend != NULL) {
-		dvb_unregister_frontend(budget_av->budget.dvb_frontend);
-		dvb_frontend_detach(budget_av->budget.dvb_frontend);
-	}
-	err = ttpci_budget_deinit(&budget_av->budget);
-
-	kfree(budget_av);
-
-	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, V4L2_IN_CAP_STD },
-	{ 1, "S-Video", V4L2_INPUT_TYPE_CAMERA, 2, 0,
-		V4L2_STD_PAL_BG | V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD },
-};
-
-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 >= 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)
-{
-	struct budget_av *budget_av;
-	u8 *mac;
-	int err;
-
-	dprintk(2, "dev: %p\n", dev);
-
-	if (!(budget_av = kzalloc(sizeof(struct budget_av), GFP_KERNEL)))
-		return -ENOMEM;
-
-	budget_av->has_saa7113 = 0;
-	budget_av->budget.ci_present = 0;
-
-	dev->ext_priv = budget_av;
-
-	err = ttpci_budget_init(&budget_av->budget, dev, info, THIS_MODULE,
-				adapter_nr);
-	if (err) {
-		kfree(budget_av);
-		return err;
-	}
-
-	/* knc1 initialization */
-	saa7146_write(dev, DD1_STREAM_B, 0x04000000);
-	saa7146_write(dev, DD1_INIT, 0x07000600);
-	saa7146_write(dev, MC2, MASK_09 | MASK_25 | MASK_10 | MASK_26);
-
-	if (saa7113_init(budget_av) == 0) {
-		budget_av->has_saa7113 = 1;
-
-		if (0 != saa7146_vv_init(dev, &vv_data)) {
-			/* fixme: proper cleanup here */
-			ERR("cannot init vv subsystem\n");
-			return err;
-		}
-		vv_data.vid_ops.vidioc_enum_input = vidioc_enum_input;
-		vv_data.vid_ops.vidioc_g_input = vidioc_g_input;
-		vv_data.vid_ops.vidioc_s_input = vidioc_s_input;
-
-		if ((err = saa7146_register_device(&budget_av->vd, dev, "knc1", VFL_TYPE_GRABBER))) {
-			/* fixme: proper cleanup here */
-			ERR("cannot register capture v4l2 device\n");
-			saa7146_vv_release(dev);
-			return err;
-		}
-
-		/* beware: this modifies dev->vv ... */
-		saa7146_set_hps_source_and_sync(dev, SAA7146_HPS_SOURCE_PORT_A,
-						SAA7146_HPS_SYNC_PORT_A);
-
-		saa7113_setinput(budget_av, 0);
-	}
-
-	/* fixme: find some sane values here... */
-	saa7146_write(dev, PCI_BT_V1, 0x1c00101f);
-
-	mac = budget_av->budget.dvb_adapter.proposed_mac;
-	if (i2c_readregs(&budget_av->budget.i2c_adap, 0xa0, 0x30, mac, 6)) {
-		pr_err("KNC1-%d: Could not read MAC from KNC1 card\n",
-		       budget_av->budget.dvb_adapter.num);
-		memset(mac, 0, 6);
-	} else {
-		pr_info("KNC1-%d: MAC addr = %pM\n",
-			budget_av->budget.dvb_adapter.num, mac);
-	}
-
-	budget_av->budget.dvb_adapter.priv = budget_av;
-	frontend_init(budget_av);
-	ciintf_init(budget_av);
-
-	ttpci_budget_init_hooks(&budget_av->budget);
-
-	return 0;
-}
-
-static struct saa7146_standard standard[] = {
-	{.name = "PAL",.id = V4L2_STD_PAL,
-	 .v_offset = 0x17,.v_field = 288,
-	 .h_offset = 0x14,.h_pixels = 680,
-	 .v_max_out = 576,.h_max_out = 768 },
-
-	{.name = "NTSC",.id = V4L2_STD_NTSC,
-	 .v_offset = 0x16,.v_field = 240,
-	 .h_offset = 0x06,.h_pixels = 708,
-	 .v_max_out = 480,.h_max_out = 640, },
-};
-
-static struct saa7146_ext_vv vv_data = {
-	.inputs = 2,
-	.capabilities = 0,	// perhaps later: V4L2_CAP_VBI_CAPTURE, but that need tweaking with the saa7113
-	.flags = 0,
-	.stds = &standard[0],
-	.num_stds = ARRAY_SIZE(standard),
-};
-
-static struct saa7146_extension budget_extension;
-
-MAKE_BUDGET_INFO(knc1s, "KNC1 DVB-S", BUDGET_KNC1S);
-MAKE_BUDGET_INFO(knc1s2,"KNC1 DVB-S2", BUDGET_KNC1S2);
-MAKE_BUDGET_INFO(sates2,"Satelco EasyWatch DVB-S2", BUDGET_KNC1S2);
-MAKE_BUDGET_INFO(knc1c, "KNC1 DVB-C", BUDGET_KNC1C);
-MAKE_BUDGET_INFO(knc1t, "KNC1 DVB-T", BUDGET_KNC1T);
-MAKE_BUDGET_INFO(kncxs, "KNC TV STAR DVB-S", BUDGET_TVSTAR);
-MAKE_BUDGET_INFO(satewpls, "Satelco EasyWatch DVB-S light", BUDGET_TVSTAR);
-MAKE_BUDGET_INFO(satewpls1, "Satelco EasyWatch DVB-S light", BUDGET_KNC1S);
-MAKE_BUDGET_INFO(satewps, "Satelco EasyWatch DVB-S", BUDGET_KNC1S);
-MAKE_BUDGET_INFO(satewplc, "Satelco EasyWatch DVB-C", BUDGET_KNC1CP);
-MAKE_BUDGET_INFO(satewcmk3, "Satelco EasyWatch DVB-C MK3", BUDGET_KNC1C_MK3);
-MAKE_BUDGET_INFO(satewt, "Satelco EasyWatch DVB-T", BUDGET_KNC1T);
-MAKE_BUDGET_INFO(knc1sp, "KNC1 DVB-S Plus", BUDGET_KNC1SP);
-MAKE_BUDGET_INFO(knc1spx4, "KNC1 DVB-S Plus X4", BUDGET_KNC1SP);
-MAKE_BUDGET_INFO(knc1cp, "KNC1 DVB-C Plus", BUDGET_KNC1CP);
-MAKE_BUDGET_INFO(knc1cmk3, "KNC1 DVB-C MK3", BUDGET_KNC1C_MK3);
-MAKE_BUDGET_INFO(knc1ctda10024, "KNC1 DVB-C TDA10024", BUDGET_KNC1C_TDA10024);
-MAKE_BUDGET_INFO(knc1cpmk3, "KNC1 DVB-C Plus MK3", BUDGET_KNC1CP_MK3);
-MAKE_BUDGET_INFO(knc1tp, "KNC1 DVB-T Plus", BUDGET_KNC1TP);
-MAKE_BUDGET_INFO(cin1200s, "TerraTec Cinergy 1200 DVB-S", BUDGET_CIN1200S);
-MAKE_BUDGET_INFO(cin1200sn, "TerraTec Cinergy 1200 DVB-S", BUDGET_CIN1200S);
-MAKE_BUDGET_INFO(cin1200c, "Terratec Cinergy 1200 DVB-C", BUDGET_CIN1200C);
-MAKE_BUDGET_INFO(cin1200cmk3, "Terratec Cinergy 1200 DVB-C MK3", BUDGET_CIN1200C_MK3);
-MAKE_BUDGET_INFO(cin1200t, "Terratec Cinergy 1200 DVB-T", BUDGET_CIN1200T);
-
-static struct pci_device_id pci_tbl[] = {
-	MAKE_EXTENSION_PCI(knc1s, 0x1131, 0x4f56),
-	MAKE_EXTENSION_PCI(knc1s, 0x1131, 0x0010),
-	MAKE_EXTENSION_PCI(knc1s, 0x1894, 0x0010),
-	MAKE_EXTENSION_PCI(knc1sp, 0x1131, 0x0011),
-	MAKE_EXTENSION_PCI(knc1sp, 0x1894, 0x0011),
-	MAKE_EXTENSION_PCI(kncxs, 0x1894, 0x0014),
-	MAKE_EXTENSION_PCI(knc1spx4, 0x1894, 0x0015),
-	MAKE_EXTENSION_PCI(kncxs, 0x1894, 0x0016),
-	MAKE_EXTENSION_PCI(knc1s2, 0x1894, 0x0018),
-	MAKE_EXTENSION_PCI(knc1s2, 0x1894, 0x0019),
-	MAKE_EXTENSION_PCI(sates2, 0x1894, 0x001d),
-	MAKE_EXTENSION_PCI(satewpls, 0x1894, 0x001e),
-	MAKE_EXTENSION_PCI(satewpls1, 0x1894, 0x001a),
-	MAKE_EXTENSION_PCI(satewps, 0x1894, 0x001b),
-	MAKE_EXTENSION_PCI(satewplc, 0x1894, 0x002a),
-	MAKE_EXTENSION_PCI(satewcmk3, 0x1894, 0x002c),
-	MAKE_EXTENSION_PCI(satewt, 0x1894, 0x003a),
-	MAKE_EXTENSION_PCI(knc1c, 0x1894, 0x0020),
-	MAKE_EXTENSION_PCI(knc1cp, 0x1894, 0x0021),
-	MAKE_EXTENSION_PCI(knc1cmk3, 0x1894, 0x0022),
-	MAKE_EXTENSION_PCI(knc1ctda10024, 0x1894, 0x0028),
-	MAKE_EXTENSION_PCI(knc1cpmk3, 0x1894, 0x0023),
-	MAKE_EXTENSION_PCI(knc1t, 0x1894, 0x0030),
-	MAKE_EXTENSION_PCI(knc1tp, 0x1894, 0x0031),
-	MAKE_EXTENSION_PCI(cin1200s, 0x153b, 0x1154),
-	MAKE_EXTENSION_PCI(cin1200sn, 0x153b, 0x1155),
-	MAKE_EXTENSION_PCI(cin1200c, 0x153b, 0x1156),
-	MAKE_EXTENSION_PCI(cin1200cmk3, 0x153b, 0x1176),
-	MAKE_EXTENSION_PCI(cin1200t, 0x153b, 0x1157),
-	{
-	 .vendor = 0,
-	}
-};
-
-MODULE_DEVICE_TABLE(pci, pci_tbl);
-
-static struct saa7146_extension budget_extension = {
-	.name = "budget_av",
-	.flags = SAA7146_USE_I2C_IRQ,
-
-	.pci_tbl = pci_tbl,
-
-	.module = THIS_MODULE,
-	.attach = budget_av_attach,
-	.detach = budget_av_detach,
-
-	.irq_mask = MASK_10,
-	.irq_func = budget_av_irq,
-};
-
-static int __init budget_av_init(void)
-{
-	return saa7146_register_extension(&budget_extension);
-}
-
-static void __exit budget_av_exit(void)
-{
-	saa7146_unregister_extension(&budget_extension);
-}
-
-module_init(budget_av_init);
-module_exit(budget_av_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, Michael Hunold, others");
-MODULE_DESCRIPTION("driver for the SAA7146 based so-called "
-		   "budget PCI DVB w/ analog input and CI-module (e.g. the KNC cards)");
diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c
deleted file mode 100644
index 98e5241..0000000
--- a/drivers/media/dvb/ttpci/budget-ci.c
+++ /dev/null
@@ -1,1591 +0,0 @@
-/*
- * budget-ci.c: driver for the SAA7146 based Budget DVB cards
- *
- * Compiled from various sources by Michael Hunold <michael@mihu.de>
- *
- *     msp430 IR support contributed by Jack Thomasson <jkt@Helius.COM>
- *     partially based on the Siemens DVB driver by Ralph+Marcus Metzler
- *
- * CI interface support (c) 2004 Andrew de Quincey <adq_dvb@lidskialf.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 program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
- * GNU General Public License for more details.
- *
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- *
- *
- * the project's page is at http://www.linuxtv.org/
- */
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
-#include <media/rc-core.h>
-
-#include "budget.h"
-
-#include "dvb_ca_en50221.h"
-#include "stv0299.h"
-#include "stv0297.h"
-#include "tda1004x.h"
-#include "stb0899_drv.h"
-#include "stb0899_reg.h"
-#include "stb0899_cfg.h"
-#include "stb6100.h"
-#include "stb6100_cfg.h"
-#include "lnbp21.h"
-#include "bsbe1.h"
-#include "bsru6.h"
-#include "tda1002x.h"
-#include "tda827x.h"
-#include "bsbe1-d01a.h"
-
-#define MODULE_NAME "budget_ci"
-
-/*
- * Regarding DEBIADDR_IR:
- * Some CI modules hang if random addresses are read.
- * Using address 0x4000 for the IR read means that we
- * use the same address as for CI version, which should
- * be a safe default.
- */
-#define DEBIADDR_IR		0x4000
-#define DEBIADDR_CICONTROL	0x0000
-#define DEBIADDR_CIVERSION	0x4000
-#define DEBIADDR_IO		0x1000
-#define DEBIADDR_ATTR		0x3000
-
-#define CICONTROL_RESET		0x01
-#define CICONTROL_ENABLETS	0x02
-#define CICONTROL_CAMDETECT	0x08
-
-#define DEBICICTL		0x00420000
-#define DEBICICAM		0x02420000
-
-#define SLOTSTATUS_NONE		1
-#define SLOTSTATUS_PRESENT	2
-#define SLOTSTATUS_RESET	4
-#define SLOTSTATUS_READY	8
-#define SLOTSTATUS_OCCUPIED	(SLOTSTATUS_PRESENT|SLOTSTATUS_RESET|SLOTSTATUS_READY)
-
-/* RC5 device wildcard */
-#define IR_DEVICE_ANY		255
-
-static int rc5_device = -1;
-module_param(rc5_device, int, 0644);
-MODULE_PARM_DESC(rc5_device, "only IR commands to given RC5 device (device = 0 - 31, any device = 255, default: autodetect)");
-
-static int ir_debug;
-module_param(ir_debug, int, 0644);
-MODULE_PARM_DESC(ir_debug, "enable debugging information for IR decoding");
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-struct budget_ci_ir {
-	struct rc_dev *dev;
-	struct tasklet_struct msp430_irq_tasklet;
-	char name[72]; /* 40 + 32 for (struct saa7146_dev).name */
-	char phys[32];
-	int rc5_device;
-	u32 ir_key;
-	bool have_command;
-	bool full_rc5;		/* Outputs a full RC5 code */
-};
-
-struct budget_ci {
-	struct budget budget;
-	struct tasklet_struct ciintf_irq_tasklet;
-	int slot_status;
-	int ci_irq;
-	struct dvb_ca_en50221 ca;
-	struct budget_ci_ir ir;
-	u8 tuner_pll_address; /* used for philips_tdm1316l configs */
-};
-
-static void msp430_ir_interrupt(unsigned long data)
-{
-	struct budget_ci *budget_ci = (struct budget_ci *) data;
-	struct rc_dev *dev = budget_ci->ir.dev;
-	u32 command = ttpci_budget_debiread(&budget_ci->budget, DEBINOSWAP, DEBIADDR_IR, 2, 1, 0) >> 8;
-
-	/*
-	 * The msp430 chip can generate two different bytes, command and device
-	 *
-	 * type1: X1CCCCCC, C = command bits (0 - 63)
-	 * type2: X0TDDDDD, D = device bits (0 - 31), T = RC5 toggle bit
-	 *
-	 * Each signal from the remote control can generate one or more command
-	 * bytes and one or more device bytes. For the repeated bytes, the
-	 * highest bit (X) is set. The first command byte is always generated
-	 * before the first device byte. Other than that, no specific order
-	 * seems to apply. To make life interesting, bytes can also be lost.
-	 *
-	 * Only when we have a command and device byte, a keypress is
-	 * generated.
-	 */
-
-	if (ir_debug)
-		printk("budget_ci: received byte 0x%02x\n", command);
-
-	/* Remove repeat bit, we use every command */
-	command = command & 0x7f;
-
-	/* Is this a RC5 command byte? */
-	if (command & 0x40) {
-		budget_ci->ir.have_command = true;
-		budget_ci->ir.ir_key = command & 0x3f;
-		return;
-	}
-
-	/* It's a RC5 device byte */
-	if (!budget_ci->ir.have_command)
-		return;
-	budget_ci->ir.have_command = false;
-
-	if (budget_ci->ir.rc5_device != IR_DEVICE_ANY &&
-	    budget_ci->ir.rc5_device != (command & 0x1f))
-		return;
-
-	if (budget_ci->ir.full_rc5) {
-		rc_keydown(dev,
-			   budget_ci->ir.rc5_device <<8 | budget_ci->ir.ir_key,
-			   (command & 0x20) ? 1 : 0);
-		return;
-	}
-
-	/* FIXME: We should generate complete scancodes for all devices */
-	rc_keydown(dev, budget_ci->ir.ir_key, (command & 0x20) ? 1 : 0);
-}
-
-static int msp430_ir_init(struct budget_ci *budget_ci)
-{
-	struct saa7146_dev *saa = budget_ci->budget.dev;
-	struct rc_dev *dev;
-	int error;
-
-	dev = rc_allocate_device();
-	if (!dev) {
-		printk(KERN_ERR "budget_ci: IR interface initialisation failed\n");
-		return -ENOMEM;
-	}
-
-	snprintf(budget_ci->ir.name, sizeof(budget_ci->ir.name),
-		 "Budget-CI dvb ir receiver %s", saa->name);
-	snprintf(budget_ci->ir.phys, sizeof(budget_ci->ir.phys),
-		 "pci-%s/ir0", pci_name(saa->pci));
-
-	dev->driver_name = MODULE_NAME;
-	dev->input_name = budget_ci->ir.name;
-	dev->input_phys = budget_ci->ir.phys;
-	dev->input_id.bustype = BUS_PCI;
-	dev->input_id.version = 1;
-	if (saa->pci->subsystem_vendor) {
-		dev->input_id.vendor = saa->pci->subsystem_vendor;
-		dev->input_id.product = saa->pci->subsystem_device;
-	} else {
-		dev->input_id.vendor = saa->pci->vendor;
-		dev->input_id.product = saa->pci->device;
-	}
-	dev->dev.parent = &saa->pci->dev;
-
-	if (rc5_device < 0)
-		budget_ci->ir.rc5_device = IR_DEVICE_ANY;
-	else
-		budget_ci->ir.rc5_device = rc5_device;
-
-	/* Select keymap and address */
-	switch (budget_ci->budget.dev->pci->subsystem_device) {
-	case 0x100c:
-	case 0x100f:
-	case 0x1011:
-	case 0x1012:
-		/* The hauppauge keymap is a superset of these remotes */
-		dev->map_name = RC_MAP_HAUPPAUGE;
-		budget_ci->ir.full_rc5 = true;
-
-		if (rc5_device < 0)
-			budget_ci->ir.rc5_device = 0x1f;
-		break;
-	case 0x1010:
-	case 0x1017:
-	case 0x1019:
-	case 0x101a:
-	case 0x101b:
-		/* for the Technotrend 1500 bundled remote */
-		dev->map_name = RC_MAP_TT_1500;
-		break;
-	default:
-		/* unknown remote */
-		dev->map_name = RC_MAP_BUDGET_CI_OLD;
-		break;
-	}
-	if (!budget_ci->ir.full_rc5)
-		dev->scanmask = 0xff;
-
-	error = rc_register_device(dev);
-	if (error) {
-		printk(KERN_ERR "budget_ci: could not init driver for IR device (code %d)\n", error);
-		rc_free_device(dev);
-		return error;
-	}
-
-	budget_ci->ir.dev = dev;
-
-	tasklet_init(&budget_ci->ir.msp430_irq_tasklet, msp430_ir_interrupt,
-		     (unsigned long) budget_ci);
-
-	SAA7146_IER_ENABLE(saa, MASK_06);
-	saa7146_setgpio(saa, 3, SAA7146_GPIO_IRQHI);
-
-	return 0;
-}
-
-static void msp430_ir_deinit(struct budget_ci *budget_ci)
-{
-	struct saa7146_dev *saa = budget_ci->budget.dev;
-
-	SAA7146_IER_DISABLE(saa, MASK_06);
-	saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
-	tasklet_kill(&budget_ci->ir.msp430_irq_tasklet);
-
-	rc_unregister_device(budget_ci->ir.dev);
-}
-
-static int ciintf_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address)
-{
-	struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
-
-	if (slot != 0)
-		return -EINVAL;
-
-	return ttpci_budget_debiread(&budget_ci->budget, DEBICICAM,
-				     DEBIADDR_ATTR | (address & 0xfff), 1, 1, 0);
-}
-
-static int ciintf_write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address, u8 value)
-{
-	struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
-
-	if (slot != 0)
-		return -EINVAL;
-
-	return ttpci_budget_debiwrite(&budget_ci->budget, DEBICICAM,
-				      DEBIADDR_ATTR | (address & 0xfff), 1, value, 1, 0);
-}
-
-static int ciintf_read_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address)
-{
-	struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
-
-	if (slot != 0)
-		return -EINVAL;
-
-	return ttpci_budget_debiread(&budget_ci->budget, DEBICICAM,
-				     DEBIADDR_IO | (address & 3), 1, 1, 0);
-}
-
-static int ciintf_write_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address, u8 value)
-{
-	struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
-
-	if (slot != 0)
-		return -EINVAL;
-
-	return ttpci_budget_debiwrite(&budget_ci->budget, DEBICICAM,
-				      DEBIADDR_IO | (address & 3), 1, value, 1, 0);
-}
-
-static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot)
-{
-	struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
-	struct saa7146_dev *saa = budget_ci->budget.dev;
-
-	if (slot != 0)
-		return -EINVAL;
-
-	if (budget_ci->ci_irq) {
-		// trigger on RISING edge during reset so we know when READY is re-asserted
-		saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);
-	}
-	budget_ci->slot_status = SLOTSTATUS_RESET;
-	ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 0, 1, 0);
-	msleep(1);
-	ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
-			       CICONTROL_RESET, 1, 0);
-
-	saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTHI);
-	ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
-	return 0;
-}
-
-static int ciintf_slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
-{
-	struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
-	struct saa7146_dev *saa = budget_ci->budget.dev;
-
-	if (slot != 0)
-		return -EINVAL;
-
-	saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTHI);
-	ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
-	return 0;
-}
-
-static int ciintf_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
-{
-	struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
-	struct saa7146_dev *saa = budget_ci->budget.dev;
-	int tmp;
-
-	if (slot != 0)
-		return -EINVAL;
-
-	saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTLO);
-
-	tmp = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
-	ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
-			       tmp | CICONTROL_ENABLETS, 1, 0);
-
-	ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTA);
-	return 0;
-}
-
-static void ciintf_interrupt(unsigned long data)
-{
-	struct budget_ci *budget_ci = (struct budget_ci *) data;
-	struct saa7146_dev *saa = budget_ci->budget.dev;
-	unsigned int flags;
-
-	// ensure we don't get spurious IRQs during initialisation
-	if (!budget_ci->budget.ci_present)
-		return;
-
-	// read the CAM status
-	flags = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
-	if (flags & CICONTROL_CAMDETECT) {
-
-		// GPIO should be set to trigger on falling edge if a CAM is present
-		saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQLO);
-
-		if (budget_ci->slot_status & SLOTSTATUS_NONE) {
-			// CAM insertion IRQ
-			budget_ci->slot_status = SLOTSTATUS_PRESENT;
-			dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0,
-						     DVB_CA_EN50221_CAMCHANGE_INSERTED);
-
-		} else if (budget_ci->slot_status & SLOTSTATUS_RESET) {
-			// CAM ready (reset completed)
-			budget_ci->slot_status = SLOTSTATUS_READY;
-			dvb_ca_en50221_camready_irq(&budget_ci->ca, 0);
-
-		} else if (budget_ci->slot_status & SLOTSTATUS_READY) {
-			// FR/DA IRQ
-			dvb_ca_en50221_frda_irq(&budget_ci->ca, 0);
-		}
-	} else {
-
-		// trigger on rising edge if a CAM is not present - when a CAM is inserted, we
-		// only want to get the IRQ when it sets READY. If we trigger on the falling edge,
-		// the CAM might not actually be ready yet.
-		saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);
-
-		// generate a CAM removal IRQ if we haven't already
-		if (budget_ci->slot_status & SLOTSTATUS_OCCUPIED) {
-			// CAM removal IRQ
-			budget_ci->slot_status = SLOTSTATUS_NONE;
-			dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0,
-						     DVB_CA_EN50221_CAMCHANGE_REMOVED);
-		}
-	}
-}
-
-static int ciintf_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open)
-{
-	struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
-	unsigned int flags;
-
-	// ensure we don't get spurious IRQs during initialisation
-	if (!budget_ci->budget.ci_present)
-		return -EINVAL;
-
-	// read the CAM status
-	flags = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
-	if (flags & CICONTROL_CAMDETECT) {
-		// mark it as present if it wasn't before
-		if (budget_ci->slot_status & SLOTSTATUS_NONE) {
-			budget_ci->slot_status = SLOTSTATUS_PRESENT;
-		}
-
-		// during a RESET, we check if we can read from IO memory to see when CAM is ready
-		if (budget_ci->slot_status & SLOTSTATUS_RESET) {
-			if (ciintf_read_attribute_mem(ca, slot, 0) == 0x1d) {
-				budget_ci->slot_status = SLOTSTATUS_READY;
-			}
-		}
-	} else {
-		budget_ci->slot_status = SLOTSTATUS_NONE;
-	}
-
-	if (budget_ci->slot_status != SLOTSTATUS_NONE) {
-		if (budget_ci->slot_status & SLOTSTATUS_READY) {
-			return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY;
-		}
-		return DVB_CA_EN50221_POLL_CAM_PRESENT;
-	}
-
-	return 0;
-}
-
-static int ciintf_init(struct budget_ci *budget_ci)
-{
-	struct saa7146_dev *saa = budget_ci->budget.dev;
-	int flags;
-	int result;
-	int ci_version;
-	int ca_flags;
-
-	memset(&budget_ci->ca, 0, sizeof(struct dvb_ca_en50221));
-
-	// enable DEBI pins
-	saa7146_write(saa, MC1, MASK_27 | MASK_11);
-
-	// test if it is there
-	ci_version = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CIVERSION, 1, 1, 0);
-	if ((ci_version & 0xa0) != 0xa0) {
-		result = -ENODEV;
-		goto error;
-	}
-
-	// determine whether a CAM is present or not
-	flags = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
-	budget_ci->slot_status = SLOTSTATUS_NONE;
-	if (flags & CICONTROL_CAMDETECT)
-		budget_ci->slot_status = SLOTSTATUS_PRESENT;
-
-	// version 0xa2 of the CI firmware doesn't generate interrupts
-	if (ci_version == 0xa2) {
-		ca_flags = 0;
-		budget_ci->ci_irq = 0;
-	} else {
-		ca_flags = DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE |
-				DVB_CA_EN50221_FLAG_IRQ_FR |
-				DVB_CA_EN50221_FLAG_IRQ_DA;
-		budget_ci->ci_irq = 1;
-	}
-
-	// register CI interface
-	budget_ci->ca.owner = THIS_MODULE;
-	budget_ci->ca.read_attribute_mem = ciintf_read_attribute_mem;
-	budget_ci->ca.write_attribute_mem = ciintf_write_attribute_mem;
-	budget_ci->ca.read_cam_control = ciintf_read_cam_control;
-	budget_ci->ca.write_cam_control = ciintf_write_cam_control;
-	budget_ci->ca.slot_reset = ciintf_slot_reset;
-	budget_ci->ca.slot_shutdown = ciintf_slot_shutdown;
-	budget_ci->ca.slot_ts_enable = ciintf_slot_ts_enable;
-	budget_ci->ca.poll_slot_status = ciintf_poll_slot_status;
-	budget_ci->ca.data = budget_ci;
-	if ((result = dvb_ca_en50221_init(&budget_ci->budget.dvb_adapter,
-					  &budget_ci->ca,
-					  ca_flags, 1)) != 0) {
-		printk("budget_ci: CI interface detected, but initialisation failed.\n");
-		goto error;
-	}
-
-	// Setup CI slot IRQ
-	if (budget_ci->ci_irq) {
-		tasklet_init(&budget_ci->ciintf_irq_tasklet, ciintf_interrupt, (unsigned long) budget_ci);
-		if (budget_ci->slot_status != SLOTSTATUS_NONE) {
-			saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQLO);
-		} else {
-			saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);
-		}
-		SAA7146_IER_ENABLE(saa, MASK_03);
-	}
-
-	// enable interface
-	ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
-			       CICONTROL_RESET, 1, 0);
-
-	// success!
-	printk("budget_ci: CI interface initialised\n");
-	budget_ci->budget.ci_present = 1;
-
-	// forge a fake CI IRQ so the CAM state is setup correctly
-	if (budget_ci->ci_irq) {
-		flags = DVB_CA_EN50221_CAMCHANGE_REMOVED;
-		if (budget_ci->slot_status != SLOTSTATUS_NONE)
-			flags = DVB_CA_EN50221_CAMCHANGE_INSERTED;
-		dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0, flags);
-	}
-
-	return 0;
-
-error:
-	saa7146_write(saa, MC1, MASK_27);
-	return result;
-}
-
-static void ciintf_deinit(struct budget_ci *budget_ci)
-{
-	struct saa7146_dev *saa = budget_ci->budget.dev;
-
-	// disable CI interrupts
-	if (budget_ci->ci_irq) {
-		SAA7146_IER_DISABLE(saa, MASK_03);
-		saa7146_setgpio(saa, 0, SAA7146_GPIO_INPUT);
-		tasklet_kill(&budget_ci->ciintf_irq_tasklet);
-	}
-
-	// reset interface
-	ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 0, 1, 0);
-	msleep(1);
-	ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
-			       CICONTROL_RESET, 1, 0);
-
-	// disable TS data stream to CI interface
-	saa7146_setgpio(saa, 1, SAA7146_GPIO_INPUT);
-
-	// release the CA device
-	dvb_ca_en50221_release(&budget_ci->ca);
-
-	// disable DEBI pins
-	saa7146_write(saa, MC1, MASK_27);
-}
-
-static void budget_ci_irq(struct saa7146_dev *dev, u32 * isr)
-{
-	struct budget_ci *budget_ci = (struct budget_ci *) dev->ext_priv;
-
-	dprintk(8, "dev: %p, budget_ci: %p\n", dev, budget_ci);
-
-	if (*isr & MASK_06)
-		tasklet_schedule(&budget_ci->ir.msp430_irq_tasklet);
-
-	if (*isr & MASK_10)
-		ttpci_budget_irq10_handler(dev, isr);
-
-	if ((*isr & MASK_03) && (budget_ci->budget.ci_present) && (budget_ci->ci_irq))
-		tasklet_schedule(&budget_ci->ciintf_irq_tasklet);
-}
-
-static u8 philips_su1278_tt_inittab[] = {
-	0x01, 0x0f,
-	0x02, 0x30,
-	0x03, 0x00,
-	0x04, 0x5b,
-	0x05, 0x85,
-	0x06, 0x02,
-	0x07, 0x00,
-	0x08, 0x02,
-	0x09, 0x00,
-	0x0C, 0x01,
-	0x0D, 0x81,
-	0x0E, 0x44,
-	0x0f, 0x14,
-	0x10, 0x3c,
-	0x11, 0x84,
-	0x12, 0xda,
-	0x13, 0x97,
-	0x14, 0x95,
-	0x15, 0xc9,
-	0x16, 0x19,
-	0x17, 0x8c,
-	0x18, 0x59,
-	0x19, 0xf8,
-	0x1a, 0xfe,
-	0x1c, 0x7f,
-	0x1d, 0x00,
-	0x1e, 0x00,
-	0x1f, 0x50,
-	0x20, 0x00,
-	0x21, 0x00,
-	0x22, 0x00,
-	0x23, 0x00,
-	0x28, 0x00,
-	0x29, 0x28,
-	0x2a, 0x14,
-	0x2b, 0x0f,
-	0x2c, 0x09,
-	0x2d, 0x09,
-	0x31, 0x1f,
-	0x32, 0x19,
-	0x33, 0xfc,
-	0x34, 0x93,
-	0xff, 0xff
-};
-
-static int philips_su1278_tt_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ratio)
-{
-	stv0299_writereg(fe, 0x0e, 0x44);
-	if (srate >= 10000000) {
-		stv0299_writereg(fe, 0x13, 0x97);
-		stv0299_writereg(fe, 0x14, 0x95);
-		stv0299_writereg(fe, 0x15, 0xc9);
-		stv0299_writereg(fe, 0x17, 0x8c);
-		stv0299_writereg(fe, 0x1a, 0xfe);
-		stv0299_writereg(fe, 0x1c, 0x7f);
-		stv0299_writereg(fe, 0x2d, 0x09);
-	} else {
-		stv0299_writereg(fe, 0x13, 0x99);
-		stv0299_writereg(fe, 0x14, 0x8d);
-		stv0299_writereg(fe, 0x15, 0xce);
-		stv0299_writereg(fe, 0x17, 0x43);
-		stv0299_writereg(fe, 0x1a, 0x1d);
-		stv0299_writereg(fe, 0x1c, 0x12);
-		stv0299_writereg(fe, 0x2d, 0x05);
-	}
-	stv0299_writereg(fe, 0x0e, 0x23);
-	stv0299_writereg(fe, 0x0f, 0x94);
-	stv0299_writereg(fe, 0x10, 0x39);
-	stv0299_writereg(fe, 0x15, 0xc9);
-
-	stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
-	stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff);
-	stv0299_writereg(fe, 0x21, (ratio) & 0xf0);
-
-	return 0;
-}
-
-static int philips_su1278_tt_tuner_set_params(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
-	u32 div;
-	u8 buf[4];
-	struct i2c_msg msg = {.addr = 0x60,.flags = 0,.buf = buf,.len = sizeof(buf) };
-
-	if ((p->frequency < 950000) || (p->frequency > 2150000))
-		return -EINVAL;
-
-	div = (p->frequency + (500 - 1)) / 500;	/* round correctly */
-	buf[0] = (div >> 8) & 0x7f;
-	buf[1] = div & 0xff;
-	buf[2] = 0x80 | ((div & 0x18000) >> 10) | 2;
-	buf[3] = 0x20;
-
-	if (p->symbol_rate < 4000000)
-		buf[3] |= 1;
-
-	if (p->frequency < 1250000)
-		buf[3] |= 0;
-	else if (p->frequency < 1550000)
-		buf[3] |= 0x40;
-	else if (p->frequency < 2050000)
-		buf[3] |= 0x80;
-	else if (p->frequency < 2150000)
-		buf[3] |= 0xC0;
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	if (i2c_transfer(&budget_ci->budget.i2c_adap, &msg, 1) != 1)
-		return -EIO;
-	return 0;
-}
-
-static struct stv0299_config philips_su1278_tt_config = {
-
-	.demod_address = 0x68,
-	.inittab = philips_su1278_tt_inittab,
-	.mclk = 64000000UL,
-	.invert = 0,
-	.skip_reinit = 1,
-	.lock_output = STV0299_LOCKOUTPUT_1,
-	.volt13_op0_op1 = STV0299_VOLT13_OP1,
-	.min_delay_ms = 50,
-	.set_symbol_rate = philips_su1278_tt_set_symbol_rate,
-};
-
-
-
-static int philips_tdm1316l_tuner_init(struct dvb_frontend *fe)
-{
-	struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
-	static u8 td1316_init[] = { 0x0b, 0xf5, 0x85, 0xab };
-	static u8 disable_mc44BC374c[] = { 0x1d, 0x74, 0xa0, 0x68 };
-	struct i2c_msg tuner_msg = {.addr = budget_ci->tuner_pll_address,.flags = 0,.buf = td1316_init,.len =
-			sizeof(td1316_init) };
-
-	// setup PLL configuration
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
-		return -EIO;
-	msleep(1);
-
-	// disable the mc44BC374c (do not check for errors)
-	tuner_msg.addr = 0x65;
-	tuner_msg.buf = disable_mc44BC374c;
-	tuner_msg.len = sizeof(disable_mc44BC374c);
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1) {
-		if (fe->ops.i2c_gate_ctrl)
-			fe->ops.i2c_gate_ctrl(fe, 1);
-		i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1);
-	}
-
-	return 0;
-}
-
-static int philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
-	u8 tuner_buf[4];
-	struct i2c_msg tuner_msg = {.addr = budget_ci->tuner_pll_address,.flags = 0,.buf = tuner_buf,.len = sizeof(tuner_buf) };
-	int tuner_frequency = 0;
-	u8 band, cp, filter;
-
-	// determine charge pump
-	tuner_frequency = p->frequency + 36130000;
-	if (tuner_frequency < 87000000)
-		return -EINVAL;
-	else if (tuner_frequency < 130000000)
-		cp = 3;
-	else if (tuner_frequency < 160000000)
-		cp = 5;
-	else if (tuner_frequency < 200000000)
-		cp = 6;
-	else if (tuner_frequency < 290000000)
-		cp = 3;
-	else if (tuner_frequency < 420000000)
-		cp = 5;
-	else if (tuner_frequency < 480000000)
-		cp = 6;
-	else if (tuner_frequency < 620000000)
-		cp = 3;
-	else if (tuner_frequency < 830000000)
-		cp = 5;
-	else if (tuner_frequency < 895000000)
-		cp = 7;
-	else
-		return -EINVAL;
-
-	// determine band
-	if (p->frequency < 49000000)
-		return -EINVAL;
-	else if (p->frequency < 159000000)
-		band = 1;
-	else if (p->frequency < 444000000)
-		band = 2;
-	else if (p->frequency < 861000000)
-		band = 4;
-	else
-		return -EINVAL;
-
-	// setup PLL filter and TDA9889
-	switch (p->bandwidth_hz) {
-	case 6000000:
-		tda1004x_writereg(fe, 0x0C, 0x14);
-		filter = 0;
-		break;
-
-	case 7000000:
-		tda1004x_writereg(fe, 0x0C, 0x80);
-		filter = 0;
-		break;
-
-	case 8000000:
-		tda1004x_writereg(fe, 0x0C, 0x14);
-		filter = 1;
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	// calculate divisor
-	// ((36130000+((1000000/6)/2)) + Finput)/(1000000/6)
-	tuner_frequency = (((p->frequency / 1000) * 6) + 217280) / 1000;
-
-	// setup tuner buffer
-	tuner_buf[0] = tuner_frequency >> 8;
-	tuner_buf[1] = tuner_frequency & 0xff;
-	tuner_buf[2] = 0xca;
-	tuner_buf[3] = (cp << 5) | (filter << 3) | band;
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
-		return -EIO;
-
-	msleep(1);
-	return 0;
-}
-
-static int philips_tdm1316l_request_firmware(struct dvb_frontend *fe,
-					     const struct firmware **fw, char *name)
-{
-	struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
-
-	return request_firmware(fw, name, &budget_ci->budget.dev->pci->dev);
-}
-
-static struct tda1004x_config philips_tdm1316l_config = {
-
-	.demod_address = 0x8,
-	.invert = 0,
-	.invert_oclk = 0,
-	.xtal_freq = TDA10046_XTAL_4M,
-	.agc_config = TDA10046_AGC_DEFAULT,
-	.if_freq = TDA10046_FREQ_3617,
-	.request_firmware = philips_tdm1316l_request_firmware,
-};
-
-static struct tda1004x_config philips_tdm1316l_config_invert = {
-
-	.demod_address = 0x8,
-	.invert = 1,
-	.invert_oclk = 0,
-	.xtal_freq = TDA10046_XTAL_4M,
-	.agc_config = TDA10046_AGC_DEFAULT,
-	.if_freq = TDA10046_FREQ_3617,
-	.request_firmware = philips_tdm1316l_request_firmware,
-};
-
-static int dvbc_philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
-	u8 tuner_buf[5];
-	struct i2c_msg tuner_msg = {.addr = budget_ci->tuner_pll_address,
-				    .flags = 0,
-				    .buf = tuner_buf,
-				    .len = sizeof(tuner_buf) };
-	int tuner_frequency = 0;
-	u8 band, cp, filter;
-
-	// determine charge pump
-	tuner_frequency = p->frequency + 36125000;
-	if (tuner_frequency < 87000000)
-		return -EINVAL;
-	else if (tuner_frequency < 130000000) {
-		cp = 3;
-		band = 1;
-	} else if (tuner_frequency < 160000000) {
-		cp = 5;
-		band = 1;
-	} else if (tuner_frequency < 200000000) {
-		cp = 6;
-		band = 1;
-	} else if (tuner_frequency < 290000000) {
-		cp = 3;
-		band = 2;
-	} else if (tuner_frequency < 420000000) {
-		cp = 5;
-		band = 2;
-	} else if (tuner_frequency < 480000000) {
-		cp = 6;
-		band = 2;
-	} else if (tuner_frequency < 620000000) {
-		cp = 3;
-		band = 4;
-	} else if (tuner_frequency < 830000000) {
-		cp = 5;
-		band = 4;
-	} else if (tuner_frequency < 895000000) {
-		cp = 7;
-		band = 4;
-	} else
-		return -EINVAL;
-
-	// assume PLL filter should always be 8MHz for the moment.
-	filter = 1;
-
-	// calculate divisor
-	tuner_frequency = (p->frequency + 36125000 + (62500/2)) / 62500;
-
-	// setup tuner buffer
-	tuner_buf[0] = tuner_frequency >> 8;
-	tuner_buf[1] = tuner_frequency & 0xff;
-	tuner_buf[2] = 0xc8;
-	tuner_buf[3] = (cp << 5) | (filter << 3) | band;
-	tuner_buf[4] = 0x80;
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
-		return -EIO;
-
-	msleep(50);
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
-		return -EIO;
-
-	msleep(1);
-
-	return 0;
-}
-
-static u8 dvbc_philips_tdm1316l_inittab[] = {
-	0x80, 0x01,
-	0x80, 0x00,
-	0x81, 0x01,
-	0x81, 0x00,
-	0x00, 0x09,
-	0x01, 0x69,
-	0x03, 0x00,
-	0x04, 0x00,
-	0x07, 0x00,
-	0x08, 0x00,
-	0x20, 0x00,
-	0x21, 0x40,
-	0x22, 0x00,
-	0x23, 0x00,
-	0x24, 0x40,
-	0x25, 0x88,
-	0x30, 0xff,
-	0x31, 0x00,
-	0x32, 0xff,
-	0x33, 0x00,
-	0x34, 0x50,
-	0x35, 0x7f,
-	0x36, 0x00,
-	0x37, 0x20,
-	0x38, 0x00,
-	0x40, 0x1c,
-	0x41, 0xff,
-	0x42, 0x29,
-	0x43, 0x20,
-	0x44, 0xff,
-	0x45, 0x00,
-	0x46, 0x00,
-	0x49, 0x04,
-	0x4a, 0x00,
-	0x4b, 0x7b,
-	0x52, 0x30,
-	0x55, 0xae,
-	0x56, 0x47,
-	0x57, 0xe1,
-	0x58, 0x3a,
-	0x5a, 0x1e,
-	0x5b, 0x34,
-	0x60, 0x00,
-	0x63, 0x00,
-	0x64, 0x00,
-	0x65, 0x00,
-	0x66, 0x00,
-	0x67, 0x00,
-	0x68, 0x00,
-	0x69, 0x00,
-	0x6a, 0x02,
-	0x6b, 0x00,
-	0x70, 0xff,
-	0x71, 0x00,
-	0x72, 0x00,
-	0x73, 0x00,
-	0x74, 0x0c,
-	0x80, 0x00,
-	0x81, 0x00,
-	0x82, 0x00,
-	0x83, 0x00,
-	0x84, 0x04,
-	0x85, 0x80,
-	0x86, 0x24,
-	0x87, 0x78,
-	0x88, 0x10,
-	0x89, 0x00,
-	0x90, 0x01,
-	0x91, 0x01,
-	0xa0, 0x04,
-	0xa1, 0x00,
-	0xa2, 0x00,
-	0xb0, 0x91,
-	0xb1, 0x0b,
-	0xc0, 0x53,
-	0xc1, 0x70,
-	0xc2, 0x12,
-	0xd0, 0x00,
-	0xd1, 0x00,
-	0xd2, 0x00,
-	0xd3, 0x00,
-	0xd4, 0x00,
-	0xd5, 0x00,
-	0xde, 0x00,
-	0xdf, 0x00,
-	0x61, 0x38,
-	0x62, 0x0a,
-	0x53, 0x13,
-	0x59, 0x08,
-	0xff, 0xff,
-};
-
-static struct stv0297_config dvbc_philips_tdm1316l_config = {
-	.demod_address = 0x1c,
-	.inittab = dvbc_philips_tdm1316l_inittab,
-	.invert = 0,
-	.stop_during_read = 1,
-};
-
-static struct tda10023_config tda10023_config = {
-	.demod_address = 0xc,
-	.invert = 0,
-	.xtal = 16000000,
-	.pll_m = 11,
-	.pll_p = 3,
-	.pll_n = 1,
-	.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[] = {
-
-	{ STB0899_DEV_ID		, 0x81 },
-	{ STB0899_DISCNTRL1		, 0x32 },
-	{ STB0899_DISCNTRL2     	, 0x80 },
-	{ STB0899_DISRX_ST0     	, 0x04 },
-	{ STB0899_DISRX_ST1     	, 0x00 },
-	{ STB0899_DISPARITY     	, 0x00 },
-	{ STB0899_DISSTATUS		, 0x20 },
-	{ STB0899_DISF22        	, 0x8c },
-	{ STB0899_DISF22RX      	, 0x9a },
-	{ STB0899_SYSREG		, 0x0b },
-	{ STB0899_ACRPRESC      	, 0x11 },
-	{ STB0899_ACRDIV1       	, 0x0a },
-	{ STB0899_ACRDIV2       	, 0x05 },
-	{ STB0899_DACR1         	, 0x00 },
-	{ STB0899_DACR2         	, 0x00 },
-	{ STB0899_OUTCFG        	, 0x00 },
-	{ STB0899_MODECFG       	, 0x00 },
-	{ STB0899_IRQSTATUS_3		, 0x30 },
-	{ STB0899_IRQSTATUS_2		, 0x00 },
-	{ STB0899_IRQSTATUS_1		, 0x00 },
-	{ STB0899_IRQSTATUS_0		, 0x00 },
-	{ STB0899_IRQMSK_3      	, 0xf3 },
-	{ STB0899_IRQMSK_2      	, 0xfc },
-	{ STB0899_IRQMSK_1      	, 0xff },
-	{ STB0899_IRQMSK_0		, 0xff },
-	{ STB0899_IRQCFG		, 0x00 },
-	{ STB0899_I2CCFG        	, 0x88 },
-	{ STB0899_I2CRPT        	, 0x48 }, /* 12k Pullup, Repeater=16, Stop=disabled */
-	{ STB0899_IOPVALUE5		, 0x00 },
-	{ STB0899_IOPVALUE4		, 0x20 },
-	{ STB0899_IOPVALUE3		, 0xc9 },
-	{ STB0899_IOPVALUE2		, 0x90 },
-	{ STB0899_IOPVALUE1		, 0x40 },
-	{ STB0899_IOPVALUE0		, 0x00 },
-	{ STB0899_GPIO00CFG     	, 0x82 },
-	{ STB0899_GPIO01CFG     	, 0x82 },
-	{ STB0899_GPIO02CFG     	, 0x82 },
-	{ STB0899_GPIO03CFG     	, 0x82 },
-	{ STB0899_GPIO04CFG     	, 0x82 },
-	{ STB0899_GPIO05CFG     	, 0x82 },
-	{ STB0899_GPIO06CFG     	, 0x82 },
-	{ STB0899_GPIO07CFG     	, 0x82 },
-	{ STB0899_GPIO08CFG     	, 0x82 },
-	{ STB0899_GPIO09CFG     	, 0x82 },
-	{ STB0899_GPIO10CFG     	, 0x82 },
-	{ STB0899_GPIO11CFG     	, 0x82 },
-	{ STB0899_GPIO12CFG     	, 0x82 },
-	{ STB0899_GPIO13CFG     	, 0x82 },
-	{ STB0899_GPIO14CFG     	, 0x82 },
-	{ STB0899_GPIO15CFG     	, 0x82 },
-	{ STB0899_GPIO16CFG     	, 0x82 },
-	{ STB0899_GPIO17CFG     	, 0x82 },
-	{ STB0899_GPIO18CFG     	, 0x82 },
-	{ STB0899_GPIO19CFG     	, 0x82 },
-	{ STB0899_GPIO20CFG     	, 0x82 },
-	{ STB0899_SDATCFG       	, 0xb8 },
-	{ STB0899_SCLTCFG       	, 0xba },
-	{ STB0899_AGCRFCFG      	, 0x1c }, /* 0x11 */
-	{ STB0899_GPIO22        	, 0x82 }, /* AGCBB2CFG */
-	{ STB0899_GPIO21        	, 0x91 }, /* AGCBB1CFG */
-	{ STB0899_DIRCLKCFG     	, 0x82 },
-	{ STB0899_CLKOUT27CFG   	, 0x7e },
-	{ STB0899_STDBYCFG      	, 0x82 },
-	{ STB0899_CS0CFG        	, 0x82 },
-	{ STB0899_CS1CFG        	, 0x82 },
-	{ STB0899_DISEQCOCFG    	, 0x20 },
-	{ STB0899_GPIO32CFG		, 0x82 },
-	{ STB0899_GPIO33CFG		, 0x82 },
-	{ STB0899_GPIO34CFG		, 0x82 },
-	{ STB0899_GPIO35CFG		, 0x82 },
-	{ STB0899_GPIO36CFG		, 0x82 },
-	{ STB0899_GPIO37CFG		, 0x82 },
-	{ STB0899_GPIO38CFG		, 0x82 },
-	{ STB0899_GPIO39CFG		, 0x82 },
-	{ STB0899_NCOARSE       	, 0x15 }, /* 0x15 = 27 Mhz Clock, F/3 = 198MHz, F/6 = 99MHz */
-	{ STB0899_SYNTCTRL      	, 0x02 }, /* 0x00 = CLK from CLKI, 0x02 = CLK from XTALI */
-	{ STB0899_FILTCTRL      	, 0x00 },
-	{ STB0899_SYSCTRL       	, 0x00 },
-	{ STB0899_STOPCLK1      	, 0x20 },
-	{ STB0899_STOPCLK2      	, 0x00 },
-	{ STB0899_INTBUFSTATUS		, 0x00 },
-	{ STB0899_INTBUFCTRL    	, 0x0a },
-	{ 0xffff			, 0xff },
-};
-
-static const struct stb0899_s1_reg tt3200_stb0899_s1_init_3[] = {
-	{ STB0899_DEMOD         	, 0x00 },
-	{ STB0899_RCOMPC        	, 0xc9 },
-	{ STB0899_AGC1CN        	, 0x41 },
-	{ STB0899_AGC1REF       	, 0x10 },
-	{ STB0899_RTC			, 0x7a },
-	{ STB0899_TMGCFG        	, 0x4e },
-	{ STB0899_AGC2REF       	, 0x34 },
-	{ STB0899_TLSR          	, 0x84 },
-	{ STB0899_CFD           	, 0xc7 },
-	{ STB0899_ACLC			, 0x87 },
-	{ STB0899_BCLC          	, 0x94 },
-	{ STB0899_EQON          	, 0x41 },
-	{ STB0899_LDT           	, 0xdd },
-	{ STB0899_LDT2          	, 0xc9 },
-	{ STB0899_EQUALREF      	, 0xb4 },
-	{ STB0899_TMGRAMP       	, 0x10 },
-	{ STB0899_TMGTHD        	, 0x30 },
-	{ STB0899_IDCCOMP		, 0xfb },
-	{ STB0899_QDCCOMP		, 0x03 },
-	{ STB0899_POWERI		, 0x3b },
-	{ STB0899_POWERQ		, 0x3d },
-	{ STB0899_RCOMP			, 0x81 },
-	{ STB0899_AGCIQIN		, 0x80 },
-	{ STB0899_AGC2I1		, 0x04 },
-	{ STB0899_AGC2I2		, 0xf5 },
-	{ STB0899_TLIR			, 0x25 },
-	{ STB0899_RTF			, 0x80 },
-	{ STB0899_DSTATUS		, 0x00 },
-	{ STB0899_LDI			, 0xca },
-	{ STB0899_CFRM			, 0xf1 },
-	{ STB0899_CFRL			, 0xf3 },
-	{ STB0899_NIRM			, 0x2a },
-	{ STB0899_NIRL			, 0x05 },
-	{ STB0899_ISYMB			, 0x17 },
-	{ STB0899_QSYMB			, 0xfa },
-	{ STB0899_SFRH          	, 0x2f },
-	{ STB0899_SFRM          	, 0x68 },
-	{ STB0899_SFRL          	, 0x40 },
-	{ STB0899_SFRUPH        	, 0x2f },
-	{ STB0899_SFRUPM        	, 0x68 },
-	{ STB0899_SFRUPL        	, 0x40 },
-	{ STB0899_EQUAI1		, 0xfd },
-	{ STB0899_EQUAQ1		, 0x04 },
-	{ STB0899_EQUAI2		, 0x0f },
-	{ STB0899_EQUAQ2		, 0xff },
-	{ STB0899_EQUAI3		, 0xdf },
-	{ STB0899_EQUAQ3		, 0xfa },
-	{ STB0899_EQUAI4		, 0x37 },
-	{ STB0899_EQUAQ4		, 0x0d },
-	{ STB0899_EQUAI5		, 0xbd },
-	{ STB0899_EQUAQ5		, 0xf7 },
-	{ STB0899_DSTATUS2		, 0x00 },
-	{ STB0899_VSTATUS       	, 0x00 },
-	{ STB0899_VERROR		, 0xff },
-	{ STB0899_IQSWAP		, 0x2a },
-	{ STB0899_ECNT1M		, 0x00 },
-	{ STB0899_ECNT1L		, 0x00 },
-	{ STB0899_ECNT2M		, 0x00 },
-	{ STB0899_ECNT2L		, 0x00 },
-	{ STB0899_ECNT3M		, 0x00 },
-	{ STB0899_ECNT3L		, 0x00 },
-	{ STB0899_FECAUTO1      	, 0x06 },
-	{ STB0899_FECM			, 0x01 },
-	{ STB0899_VTH12         	, 0xf0 },
-	{ STB0899_VTH23         	, 0xa0 },
-	{ STB0899_VTH34			, 0x78 },
-	{ STB0899_VTH56         	, 0x4e },
-	{ STB0899_VTH67         	, 0x48 },
-	{ STB0899_VTH78         	, 0x38 },
-	{ STB0899_PRVIT         	, 0xff },
-	{ STB0899_VITSYNC       	, 0x19 },
-	{ STB0899_RSULC         	, 0xb1 }, /* DVB = 0xb1, DSS = 0xa1 */
-	{ STB0899_TSULC         	, 0x42 },
-	{ STB0899_RSLLC         	, 0x40 },
-	{ STB0899_TSLPL			, 0x12 },
-	{ STB0899_TSCFGH        	, 0x0c },
-	{ STB0899_TSCFGM        	, 0x00 },
-	{ STB0899_TSCFGL        	, 0x0c },
-	{ STB0899_TSOUT			, 0x4d }, /* 0x0d for CAM */
-	{ STB0899_RSSYNCDEL     	, 0x00 },
-	{ STB0899_TSINHDELH     	, 0x02 },
-	{ STB0899_TSINHDELM		, 0x00 },
-	{ STB0899_TSINHDELL		, 0x00 },
-	{ STB0899_TSLLSTKM		, 0x00 },
-	{ STB0899_TSLLSTKL		, 0x00 },
-	{ STB0899_TSULSTKM		, 0x00 },
-	{ STB0899_TSULSTKL		, 0xab },
-	{ STB0899_PCKLENUL		, 0x00 },
-	{ STB0899_PCKLENLL		, 0xcc },
-	{ STB0899_RSPCKLEN		, 0xcc },
-	{ STB0899_TSSTATUS		, 0x80 },
-	{ STB0899_ERRCTRL1      	, 0xb6 },
-	{ STB0899_ERRCTRL2      	, 0x96 },
-	{ STB0899_ERRCTRL3      	, 0x89 },
-	{ STB0899_DMONMSK1		, 0x27 },
-	{ STB0899_DMONMSK0		, 0x03 },
-	{ STB0899_DEMAPVIT      	, 0x5c },
-	{ STB0899_PLPARM		, 0x1f },
-	{ STB0899_PDELCTRL      	, 0x48 },
-	{ STB0899_PDELCTRL2     	, 0x00 },
-	{ STB0899_BBHCTRL1      	, 0x00 },
-	{ STB0899_BBHCTRL2      	, 0x00 },
-	{ STB0899_HYSTTHRESH    	, 0x77 },
-	{ STB0899_MATCSTM		, 0x00 },
-	{ STB0899_MATCSTL		, 0x00 },
-	{ STB0899_UPLCSTM		, 0x00 },
-	{ STB0899_UPLCSTL		, 0x00 },
-	{ STB0899_DFLCSTM		, 0x00 },
-	{ STB0899_DFLCSTL		, 0x00 },
-	{ STB0899_SYNCCST		, 0x00 },
-	{ STB0899_SYNCDCSTM		, 0x00 },
-	{ STB0899_SYNCDCSTL		, 0x00 },
-	{ STB0899_ISI_ENTRY		, 0x00 },
-	{ STB0899_ISI_BIT_EN		, 0x00 },
-	{ STB0899_MATSTRM		, 0x00 },
-	{ STB0899_MATSTRL		, 0x00 },
-	{ STB0899_UPLSTRM		, 0x00 },
-	{ STB0899_UPLSTRL		, 0x00 },
-	{ STB0899_DFLSTRM		, 0x00 },
-	{ STB0899_DFLSTRL		, 0x00 },
-	{ STB0899_SYNCSTR		, 0x00 },
-	{ STB0899_SYNCDSTRM		, 0x00 },
-	{ STB0899_SYNCDSTRL		, 0x00 },
-	{ STB0899_CFGPDELSTATUS1	, 0x10 },
-	{ STB0899_CFGPDELSTATUS2	, 0x00 },
-	{ STB0899_BBFERRORM		, 0x00 },
-	{ STB0899_BBFERRORL		, 0x00 },
-	{ STB0899_UPKTERRORM		, 0x00 },
-	{ STB0899_UPKTERRORL		, 0x00 },
-	{ 0xffff			, 0xff },
-};
-
-static struct stb0899_config tt3200_config = {
-	.init_dev		= tt3200_stb0899_s1_init_1,
-	.init_s2_demod		= stb0899_s2_init_2,
-	.init_s1_demod		= tt3200_stb0899_s1_init_3,
-	.init_s2_fec		= stb0899_s2_init_4,
-	.init_tst		= stb0899_s1_init_5,
-
-	.postproc		= NULL,
-
-	.demod_address 		= 0x68,
-
-	.xtal_freq		= 27000000,
-	.inversion		= IQ_SWAP_ON, /* 1 */
-
-	.lo_clk			= 76500000,
-	.hi_clk			= 99000000,
-
-	.esno_ave		= STB0899_DVBS2_ESNO_AVE,
-	.esno_quant		= STB0899_DVBS2_ESNO_QUANT,
-	.avframes_coarse	= STB0899_DVBS2_AVFRAMES_COARSE,
-	.avframes_fine		= STB0899_DVBS2_AVFRAMES_FINE,
-	.miss_threshold		= STB0899_DVBS2_MISS_THRESHOLD,
-	.uwp_threshold_acq	= STB0899_DVBS2_UWP_THRESHOLD_ACQ,
-	.uwp_threshold_track	= STB0899_DVBS2_UWP_THRESHOLD_TRACK,
-	.uwp_threshold_sof	= STB0899_DVBS2_UWP_THRESHOLD_SOF,
-	.sof_search_timeout	= STB0899_DVBS2_SOF_SEARCH_TIMEOUT,
-
-	.btr_nco_bits		= STB0899_DVBS2_BTR_NCO_BITS,
-	.btr_gain_shift_offset	= STB0899_DVBS2_BTR_GAIN_SHIFT_OFFSET,
-	.crl_nco_bits		= STB0899_DVBS2_CRL_NCO_BITS,
-	.ldpc_max_iter		= STB0899_DVBS2_LDPC_MAX_ITER,
-
-	.tuner_get_frequency	= stb6100_get_frequency,
-	.tuner_set_frequency	= stb6100_set_frequency,
-	.tuner_set_bandwidth	= stb6100_set_bandwidth,
-	.tuner_get_bandwidth	= stb6100_get_bandwidth,
-	.tuner_set_rfsiggain	= NULL
-};
-
-static struct stb6100_config tt3200_stb6100_config = {
-	.tuner_address	= 0x60,
-	.refclock	= 27000000,
-};
-
-static void frontend_init(struct budget_ci *budget_ci)
-{
-	switch (budget_ci->budget.dev->pci->subsystem_device) {
-	case 0x100c:		// Hauppauge/TT Nova-CI budget (stv0299/ALPS BSRU6(tsa5059))
-		budget_ci->budget.dvb_frontend =
-			dvb_attach(stv0299_attach, &alps_bsru6_config, &budget_ci->budget.i2c_adap);
-		if (budget_ci->budget.dvb_frontend) {
-			budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
-			budget_ci->budget.dvb_frontend->tuner_priv = &budget_ci->budget.i2c_adap;
-			break;
-		}
-		break;
-
-	case 0x100f:		// Hauppauge/TT Nova-CI budget (stv0299b/Philips su1278(tsa5059))
-		budget_ci->budget.dvb_frontend =
-			dvb_attach(stv0299_attach, &philips_su1278_tt_config, &budget_ci->budget.i2c_adap);
-		if (budget_ci->budget.dvb_frontend) {
-			budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_su1278_tt_tuner_set_params;
-			break;
-		}
-		break;
-
-	case 0x1010:		// TT DVB-C CI budget (stv0297/Philips tdm1316l(tda6651tt))
-		budget_ci->tuner_pll_address = 0x61;
-		budget_ci->budget.dvb_frontend =
-			dvb_attach(stv0297_attach, &dvbc_philips_tdm1316l_config, &budget_ci->budget.i2c_adap);
-		if (budget_ci->budget.dvb_frontend) {
-			budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = dvbc_philips_tdm1316l_tuner_set_params;
-			break;
-		}
-		break;
-
-	case 0x1011:		// Hauppauge/TT Nova-T budget (tda10045/Philips tdm1316l(tda6651tt) + TDA9889)
-		budget_ci->tuner_pll_address = 0x63;
-		budget_ci->budget.dvb_frontend =
-			dvb_attach(tda10045_attach, &philips_tdm1316l_config, &budget_ci->budget.i2c_adap);
-		if (budget_ci->budget.dvb_frontend) {
-			budget_ci->budget.dvb_frontend->ops.tuner_ops.init = philips_tdm1316l_tuner_init;
-			budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_tdm1316l_tuner_set_params;
-			break;
-		}
-		break;
-
-	case 0x1012:		// TT DVB-T CI budget (tda10046/Philips tdm1316l(tda6651tt))
-		budget_ci->tuner_pll_address = 0x60;
-		budget_ci->budget.dvb_frontend =
-			dvb_attach(tda10046_attach, &philips_tdm1316l_config_invert, &budget_ci->budget.i2c_adap);
-		if (budget_ci->budget.dvb_frontend) {
-			budget_ci->budget.dvb_frontend->ops.tuner_ops.init = philips_tdm1316l_tuner_init;
-			budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_tdm1316l_tuner_set_params;
-			break;
-		}
-		break;
-
-	case 0x1017:		// TT S-1500 PCI
-		budget_ci->budget.dvb_frontend = dvb_attach(stv0299_attach, &alps_bsbe1_config, &budget_ci->budget.i2c_adap);
-		if (budget_ci->budget.dvb_frontend) {
-			budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = alps_bsbe1_tuner_set_params;
-			budget_ci->budget.dvb_frontend->tuner_priv = &budget_ci->budget.i2c_adap;
-
-			budget_ci->budget.dvb_frontend->ops.dishnetwork_send_legacy_command = NULL;
-			if (dvb_attach(lnbp21_attach, budget_ci->budget.dvb_frontend, &budget_ci->budget.i2c_adap, LNBP21_LLC, 0) == NULL) {
-				printk("%s: No LNBP21 found!\n", __func__);
-				dvb_frontend_detach(budget_ci->budget.dvb_frontend);
-				budget_ci->budget.dvb_frontend = NULL;
-			}
-		}
-		break;
-
-	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, &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;
-			}
-		}
-		break;
-
-	case 0x101b: /* TT S-1500B (BSBE1-D01A - STV0288/STB6000/LNBP21) */
-		budget_ci->budget.dvb_frontend = dvb_attach(stv0288_attach, &stv0288_bsbe1_d01a_config, &budget_ci->budget.i2c_adap);
-		if (budget_ci->budget.dvb_frontend) {
-			if (dvb_attach(stb6000_attach, budget_ci->budget.dvb_frontend, 0x63, &budget_ci->budget.i2c_adap)) {
-				if (!dvb_attach(lnbp21_attach, budget_ci->budget.dvb_frontend, &budget_ci->budget.i2c_adap, 0, 0)) {
-					printk(KERN_ERR "%s: No LNBP21 found!\n", __func__);
-					dvb_frontend_detach(budget_ci->budget.dvb_frontend);
-					budget_ci->budget.dvb_frontend = NULL;
-				}
-			} else {
-				printk(KERN_ERR "%s: No STB6000 found!\n", __func__);
-				dvb_frontend_detach(budget_ci->budget.dvb_frontend);
-				budget_ci->budget.dvb_frontend = NULL;
-			}
-		}
-		break;
-
-	case 0x1019:		// TT S2-3200 PCI
-		/*
-		 * NOTE! on some STB0899 versions, the internal PLL takes a longer time
-		 * to settle, aka LOCK. On the older revisions of the chip, we don't see
-		 * this, as a result on the newer chips the entire clock tree, will not
-		 * be stable after a freshly POWER 'ed up situation.
-		 * In this case, we should RESET the STB0899 (Active LOW) and wait for
-		 * PLL stabilization.
-		 *
-		 * On the TT S2 3200 and clones, the STB0899 demodulator's RESETB is
-		 * connected to the SAA7146 GPIO, GPIO2, Pin 142
-		 */
-		/* Reset Demodulator */
-		saa7146_setgpio(budget_ci->budget.dev, 2, SAA7146_GPIO_OUTLO);
-		/* Wait for everything to die */
-		msleep(50);
-		/* Pull it up out of Reset state */
-		saa7146_setgpio(budget_ci->budget.dev, 2, SAA7146_GPIO_OUTHI);
-		/* Wait for PLL to stabilize */
-		msleep(250);
-		/*
-		 * PLL state should be stable now. Ideally, we should check
-		 * for PLL LOCK status. But well, never mind!
-		 */
-		budget_ci->budget.dvb_frontend = dvb_attach(stb0899_attach, &tt3200_config, &budget_ci->budget.i2c_adap);
-		if (budget_ci->budget.dvb_frontend) {
-			if (dvb_attach(stb6100_attach, budget_ci->budget.dvb_frontend, &tt3200_stb6100_config, &budget_ci->budget.i2c_adap)) {
-				if (!dvb_attach(lnbp21_attach, budget_ci->budget.dvb_frontend, &budget_ci->budget.i2c_adap, 0, 0)) {
-					printk("%s: No LNBP21 found!\n", __func__);
-					dvb_frontend_detach(budget_ci->budget.dvb_frontend);
-					budget_ci->budget.dvb_frontend = NULL;
-				}
-			} else {
-					dvb_frontend_detach(budget_ci->budget.dvb_frontend);
-					budget_ci->budget.dvb_frontend = NULL;
-			}
-		}
-		break;
-
-	}
-
-	if (budget_ci->budget.dvb_frontend == NULL) {
-		printk("budget-ci: A frontend driver was not found for device [%04x:%04x] subsystem [%04x:%04x]\n",
-		       budget_ci->budget.dev->pci->vendor,
-		       budget_ci->budget.dev->pci->device,
-		       budget_ci->budget.dev->pci->subsystem_vendor,
-		       budget_ci->budget.dev->pci->subsystem_device);
-	} else {
-		if (dvb_register_frontend
-		    (&budget_ci->budget.dvb_adapter, budget_ci->budget.dvb_frontend)) {
-			printk("budget-ci: Frontend registration failed!\n");
-			dvb_frontend_detach(budget_ci->budget.dvb_frontend);
-			budget_ci->budget.dvb_frontend = NULL;
-		}
-	}
-}
-
-static int budget_ci_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
-{
-	struct budget_ci *budget_ci;
-	int err;
-
-	budget_ci = kzalloc(sizeof(struct budget_ci), GFP_KERNEL);
-	if (!budget_ci) {
-		err = -ENOMEM;
-		goto out1;
-	}
-
-	dprintk(2, "budget_ci: %p\n", budget_ci);
-
-	dev->ext_priv = budget_ci;
-
-	err = ttpci_budget_init(&budget_ci->budget, dev, info, THIS_MODULE,
-				adapter_nr);
-	if (err)
-		goto out2;
-
-	err = msp430_ir_init(budget_ci);
-	if (err)
-		goto out3;
-
-	ciintf_init(budget_ci);
-
-	budget_ci->budget.dvb_adapter.priv = budget_ci;
-	frontend_init(budget_ci);
-
-	ttpci_budget_init_hooks(&budget_ci->budget);
-
-	return 0;
-
-out3:
-	ttpci_budget_deinit(&budget_ci->budget);
-out2:
-	kfree(budget_ci);
-out1:
-	return err;
-}
-
-static int budget_ci_detach(struct saa7146_dev *dev)
-{
-	struct budget_ci *budget_ci = (struct budget_ci *) dev->ext_priv;
-	struct saa7146_dev *saa = budget_ci->budget.dev;
-	int err;
-
-	if (budget_ci->budget.ci_present)
-		ciintf_deinit(budget_ci);
-	msp430_ir_deinit(budget_ci);
-	if (budget_ci->budget.dvb_frontend) {
-		dvb_unregister_frontend(budget_ci->budget.dvb_frontend);
-		dvb_frontend_detach(budget_ci->budget.dvb_frontend);
-	}
-	err = ttpci_budget_deinit(&budget_ci->budget);
-
-	// disable frontend and CI interface
-	saa7146_setgpio(saa, 2, SAA7146_GPIO_INPUT);
-
-	kfree(budget_ci);
-
-	return err;
-}
-
-static struct saa7146_extension budget_extension;
-
-MAKE_BUDGET_INFO(ttbs2, "TT-Budget/S-1500 PCI", BUDGET_TT);
-MAKE_BUDGET_INFO(ttbci, "TT-Budget/WinTV-NOVA-CI PCI", BUDGET_TT_HW_DISEQC);
-MAKE_BUDGET_INFO(ttbt2, "TT-Budget/WinTV-NOVA-T	 PCI", BUDGET_TT);
-MAKE_BUDGET_INFO(ttbtci, "TT-Budget-T-CI PCI", BUDGET_TT);
-MAKE_BUDGET_INFO(ttbcci, "TT-Budget-C-CI PCI", BUDGET_TT);
-MAKE_BUDGET_INFO(ttc1501, "TT-Budget C-1501 PCI", BUDGET_TT);
-MAKE_BUDGET_INFO(tt3200, "TT-Budget S2-3200 PCI", BUDGET_TT);
-MAKE_BUDGET_INFO(ttbs1500b, "TT-Budget S-1500B PCI", BUDGET_TT);
-
-static struct pci_device_id pci_tbl[] = {
-	MAKE_EXTENSION_PCI(ttbci, 0x13c2, 0x100c),
-	MAKE_EXTENSION_PCI(ttbci, 0x13c2, 0x100f),
-	MAKE_EXTENSION_PCI(ttbcci, 0x13c2, 0x1010),
-	MAKE_EXTENSION_PCI(ttbt2, 0x13c2, 0x1011),
-	MAKE_EXTENSION_PCI(ttbtci, 0x13c2, 0x1012),
-	MAKE_EXTENSION_PCI(ttbs2, 0x13c2, 0x1017),
-	MAKE_EXTENSION_PCI(ttc1501, 0x13c2, 0x101a),
-	MAKE_EXTENSION_PCI(tt3200, 0x13c2, 0x1019),
-	MAKE_EXTENSION_PCI(ttbs1500b, 0x13c2, 0x101b),
-	{
-	 .vendor = 0,
-	 }
-};
-
-MODULE_DEVICE_TABLE(pci, pci_tbl);
-
-static struct saa7146_extension budget_extension = {
-	.name = "budget_ci dvb",
-	.flags = SAA7146_USE_I2C_IRQ,
-
-	.module = THIS_MODULE,
-	.pci_tbl = &pci_tbl[0],
-	.attach = budget_ci_attach,
-	.detach = budget_ci_detach,
-
-	.irq_mask = MASK_03 | MASK_06 | MASK_10,
-	.irq_func = budget_ci_irq,
-};
-
-static int __init budget_ci_init(void)
-{
-	return saa7146_register_extension(&budget_extension);
-}
-
-static void __exit budget_ci_exit(void)
-{
-	saa7146_unregister_extension(&budget_extension);
-}
-
-module_init(budget_ci_init);
-module_exit(budget_ci_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Michael Hunold, Jack Thomasson, Andrew de Quincey, others");
-MODULE_DESCRIPTION("driver for the SAA7146 based so-called "
-		   "budget PCI DVB cards w/ CI-module produced by "
-		   "Siemens, Technotrend, Hauppauge");
diff --git a/drivers/media/dvb/ttpci/budget-core.c b/drivers/media/dvb/ttpci/budget-core.c
deleted file mode 100644
index 37d02fe..0000000
--- a/drivers/media/dvb/ttpci/budget-core.c
+++ /dev/null
@@ -1,602 +0,0 @@
-/*
- * budget-core.c: driver for the SAA7146 based Budget DVB cards
- *
- * Compiled from various sources by Michael Hunold <michael@mihu.de>
- *
- * Copyright (C) 2002 Ralph Metzler <rjkm@metzlerbros.de>
- *
- * Copyright (C) 1999-2002 Ralph  Metzler
- *			 & Marcus Metzler for convergence integrated media GmbH
- *
- * 26feb2004 Support for FS Activy Card (Grundig tuner) by
- *	     Michael Dreher <michael@5dot1.de>,
- *	     Oliver Endriss <o.endriss@gmx.de>,
- *	     Andreas 'randy' Weinberger
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the 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.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- *
- *
- * the project's page is at http://www.linuxtv.org/ 
- */
-
-
-#include "budget.h"
-#include "ttpci-eeprom.h"
-
-#define TS_WIDTH		(2 * TS_SIZE)
-#define TS_WIDTH_ACTIVY		TS_SIZE
-#define TS_WIDTH_DVBC		TS_SIZE
-#define TS_HEIGHT_MASK		0xf00
-#define TS_HEIGHT_MASK_ACTIVY	0xc00
-#define TS_HEIGHT_MASK_DVBC	0xe00
-#define TS_MIN_BUFSIZE_K	188
-#define TS_MAX_BUFSIZE_K	1410
-#define TS_MAX_BUFSIZE_K_ACTIVY	564
-#define TS_MAX_BUFSIZE_K_DVBC	1316
-#define BUFFER_WARNING_WAIT	(30*HZ)
-
-int budget_debug;
-static int dma_buffer_size = TS_MIN_BUFSIZE_K;
-module_param_named(debug, budget_debug, int, 0644);
-module_param_named(bufsize, dma_buffer_size, int, 0444);
-MODULE_PARM_DESC(debug, "Turn on/off budget debugging (default:off).");
-MODULE_PARM_DESC(bufsize, "DMA buffer size in KB, default: 188, min: 188, max: 1410 (Activy: 564)");
-
-/****************************************************************************
- * TT budget / WinTV Nova
- ****************************************************************************/
-
-static int stop_ts_capture(struct budget *budget)
-{
-	dprintk(2, "budget: %p\n", budget);
-
-	saa7146_write(budget->dev, MC1, MASK_20);	// DMA3 off
-	SAA7146_IER_DISABLE(budget->dev, MASK_10);
-	return 0;
-}
-
-static int start_ts_capture(struct budget *budget)
-{
-	struct saa7146_dev *dev = budget->dev;
-
-	dprintk(2, "budget: %p\n", budget);
-
-	if (!budget->feeding || !budget->fe_synced)
-		return 0;
-
-	saa7146_write(dev, MC1, MASK_20);	// DMA3 off
-
-	memset(budget->grabbing, 0x00, budget->buffer_size);
-
-	saa7146_write(dev, PCI_BT_V1, 0x001c0000 | (saa7146_read(dev, PCI_BT_V1) & ~0x001f0000));
-
-	budget->ttbp = 0;
-
-	/*
-	 *  Signal path on the Activy:
-	 *
-	 *  tuner -> SAA7146 port A -> SAA7146 BRS -> SAA7146 DMA3 -> memory
-	 *
-	 *  Since the tuner feeds 204 bytes packets into the SAA7146,
-	 *  DMA3 is configured to strip the trailing 16 FEC bytes:
-	 *      Pitch: 188, NumBytes3: 188, NumLines3: 1024
-	 */
-
-	switch(budget->card->type) {
-	case BUDGET_FS_ACTIVY:
-		saa7146_write(dev, DD1_INIT, 0x04000000);
-		saa7146_write(dev, MC2, (MASK_09 | MASK_25));
-		saa7146_write(dev, BRS_CTRL, 0x00000000);
-		break;
-	case BUDGET_PATCH:
-		saa7146_write(dev, DD1_INIT, 0x00000200);
-		saa7146_write(dev, MC2, (MASK_10 | MASK_26));
-		saa7146_write(dev, BRS_CTRL, 0x60000000);
-		break;
-	case BUDGET_CIN1200C_MK3:
-	case BUDGET_KNC1C_MK3:
-	case BUDGET_KNC1C_TDA10024:
-	case BUDGET_KNC1CP_MK3:
-		if (budget->video_port == BUDGET_VIDEO_PORTA) {
-			saa7146_write(dev, DD1_INIT, 0x06000200);
-			saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
-			saa7146_write(dev, BRS_CTRL, 0x00000000);
-		} else {
-			saa7146_write(dev, DD1_INIT, 0x00000600);
-			saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
-			saa7146_write(dev, BRS_CTRL, 0x60000000);
-		}
-		break;
-	default:
-		if (budget->video_port == BUDGET_VIDEO_PORTA) {
-			saa7146_write(dev, DD1_INIT, 0x06000200);
-			saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
-			saa7146_write(dev, BRS_CTRL, 0x00000000);
-		} else {
-			saa7146_write(dev, DD1_INIT, 0x02000600);
-			saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
-			saa7146_write(dev, BRS_CTRL, 0x60000000);
-		}
-	}
-
-	saa7146_write(dev, MC2, (MASK_08 | MASK_24));
-	mdelay(10);
-
-	saa7146_write(dev, BASE_ODD3, 0);
-	if (budget->buffer_size > budget->buffer_height * budget->buffer_width) {
-		// using odd/even buffers
-		saa7146_write(dev, BASE_EVEN3, budget->buffer_height * budget->buffer_width);
-	} else {
-		// using a single buffer
-		saa7146_write(dev, BASE_EVEN3, 0);
-	}
-	saa7146_write(dev, PROT_ADDR3, budget->buffer_size);
-	saa7146_write(dev, BASE_PAGE3, budget->pt.dma | ME1 | 0x90);
-
-	saa7146_write(dev, PITCH3, budget->buffer_width);
-	saa7146_write(dev, NUM_LINE_BYTE3,
-			(budget->buffer_height << 16) | budget->buffer_width);
-
-	saa7146_write(dev, MC2, (MASK_04 | MASK_20));
-
-	SAA7146_ISR_CLEAR(budget->dev, MASK_10);	/* VPE */
-	SAA7146_IER_ENABLE(budget->dev, MASK_10);	/* VPE */
-	saa7146_write(dev, MC1, (MASK_04 | MASK_20));	/* DMA3 on */
-
-	return 0;
-}
-
-static int budget_read_fe_status(struct dvb_frontend *fe, fe_status_t *status)
-{
-	struct budget *budget = (struct budget *) fe->dvb->priv;
-	int synced;
-	int ret;
-
-	if (budget->read_fe_status)
-		ret = budget->read_fe_status(fe, status);
-	else
-		ret = -EINVAL;
-
-	if (!ret) {
-		synced = (*status & FE_HAS_LOCK);
-		if (synced != budget->fe_synced) {
-			budget->fe_synced = synced;
-			spin_lock(&budget->feedlock);
-			if (synced)
-				start_ts_capture(budget);
-			else
-				stop_ts_capture(budget);
-			spin_unlock(&budget->feedlock);
-		}
-	}
-	return ret;
-}
-
-static void vpeirq(unsigned long data)
-{
-	struct budget *budget = (struct budget *) data;
-	u8 *mem = (u8 *) (budget->grabbing);
-	u32 olddma = budget->ttbp;
-	u32 newdma = saa7146_read(budget->dev, PCI_VDP3);
-	u32 count;
-
-	/* Ensure streamed PCI data is synced to CPU */
-	pci_dma_sync_sg_for_cpu(budget->dev->pci, budget->pt.slist, budget->pt.nents, PCI_DMA_FROMDEVICE);
-
-	/* nearest lower position divisible by 188 */
-	newdma -= newdma % 188;
-
-	if (newdma >= budget->buffer_size)
-		return;
-
-	budget->ttbp = newdma;
-
-	if (budget->feeding == 0 || newdma == olddma)
-		return;
-
-	if (newdma > olddma) {	/* no wraparound, dump olddma..newdma */
-		count = newdma - olddma;
-		dvb_dmx_swfilter_packets(&budget->demux, mem + olddma, count / 188);
-	} else {		/* wraparound, dump olddma..buflen and 0..newdma */
-		count = budget->buffer_size - olddma;
-		dvb_dmx_swfilter_packets(&budget->demux, mem + olddma, count / 188);
-		count += newdma;
-		dvb_dmx_swfilter_packets(&budget->demux, mem, newdma / 188);
-	}
-
-	if (count > budget->buffer_warning_threshold)
-		budget->buffer_warnings++;
-
-	if (budget->buffer_warnings && time_after(jiffies, budget->buffer_warning_time)) {
-		printk("%s %s: used %d times >80%% of buffer (%u bytes now)\n",
-			budget->dev->name, __func__, budget->buffer_warnings, count);
-		budget->buffer_warning_time = jiffies + BUFFER_WARNING_WAIT;
-		budget->buffer_warnings = 0;
-	}
-}
-
-
-int ttpci_budget_debiread(struct budget *budget, u32 config, int addr, int count,
-			  int uselocks, int nobusyloop)
-{
-	struct saa7146_dev *saa = budget->dev;
-	int result = 0;
-	unsigned long flags = 0;
-
-	if (count > 4 || count <= 0)
-		return 0;
-
-	if (uselocks)
-		spin_lock_irqsave(&budget->debilock, flags);
-
-	if ((result = saa7146_wait_for_debi_done(saa, nobusyloop)) < 0) {
-		if (uselocks)
-			spin_unlock_irqrestore(&budget->debilock, flags);
-		return result;
-	}
-
-	saa7146_write(saa, DEBI_COMMAND, (count << 17) | 0x10000 | (addr & 0xffff));
-	saa7146_write(saa, DEBI_CONFIG, config);
-	saa7146_write(saa, DEBI_PAGE, 0);
-	saa7146_write(saa, MC2, (2 << 16) | 2);
-
-	if ((result = saa7146_wait_for_debi_done(saa, nobusyloop)) < 0) {
-		if (uselocks)
-			spin_unlock_irqrestore(&budget->debilock, flags);
-		return result;
-	}
-
-	result = saa7146_read(saa, DEBI_AD);
-	result &= (0xffffffffUL >> ((4 - count) * 8));
-
-	if (uselocks)
-		spin_unlock_irqrestore(&budget->debilock, flags);
-
-	return result;
-}
-
-int ttpci_budget_debiwrite(struct budget *budget, u32 config, int addr,
-			   int count, u32 value, int uselocks, int nobusyloop)
-{
-	struct saa7146_dev *saa = budget->dev;
-	unsigned long flags = 0;
-	int result;
-
-	if (count > 4 || count <= 0)
-		return 0;
-
-	if (uselocks)
-		spin_lock_irqsave(&budget->debilock, flags);
-
-	if ((result = saa7146_wait_for_debi_done(saa, nobusyloop)) < 0) {
-		if (uselocks)
-			spin_unlock_irqrestore(&budget->debilock, flags);
-		return result;
-	}
-
-	saa7146_write(saa, DEBI_COMMAND, (count << 17) | 0x00000 | (addr & 0xffff));
-	saa7146_write(saa, DEBI_CONFIG, config);
-	saa7146_write(saa, DEBI_PAGE, 0);
-	saa7146_write(saa, DEBI_AD, value);
-	saa7146_write(saa, MC2, (2 << 16) | 2);
-
-	if ((result = saa7146_wait_for_debi_done(saa, nobusyloop)) < 0) {
-		if (uselocks)
-			spin_unlock_irqrestore(&budget->debilock, flags);
-		return result;
-	}
-
-	if (uselocks)
-		spin_unlock_irqrestore(&budget->debilock, flags);
-	return 0;
-}
-
-
-/****************************************************************************
- * DVB API SECTION
- ****************************************************************************/
-
-static int budget_start_feed(struct dvb_demux_feed *feed)
-{
-	struct dvb_demux *demux = feed->demux;
-	struct budget *budget = (struct budget *) demux->priv;
-	int status = 0;
-
-	dprintk(2, "budget: %p\n", budget);
-
-	if (!demux->dmx.frontend)
-		return -EINVAL;
-
-	spin_lock(&budget->feedlock);
-	feed->pusi_seen = 0; /* have a clean section start */
-	if (budget->feeding++ == 0)
-		status = start_ts_capture(budget);
-	spin_unlock(&budget->feedlock);
-	return status;
-}
-
-static int budget_stop_feed(struct dvb_demux_feed *feed)
-{
-	struct dvb_demux *demux = feed->demux;
-	struct budget *budget = (struct budget *) demux->priv;
-	int status = 0;
-
-	dprintk(2, "budget: %p\n", budget);
-
-	spin_lock(&budget->feedlock);
-	if (--budget->feeding == 0)
-		status = stop_ts_capture(budget);
-	spin_unlock(&budget->feedlock);
-	return status;
-}
-
-static int budget_register(struct budget *budget)
-{
-	struct dvb_demux *dvbdemux = &budget->demux;
-	int ret;
-
-	dprintk(2, "budget: %p\n", budget);
-
-	dvbdemux->priv = (void *) budget;
-
-	dvbdemux->filternum = 256;
-	dvbdemux->feednum = 256;
-	dvbdemux->start_feed = budget_start_feed;
-	dvbdemux->stop_feed = budget_stop_feed;
-	dvbdemux->write_to_decoder = NULL;
-
-	dvbdemux->dmx.capabilities = (DMX_TS_FILTERING | DMX_SECTION_FILTERING |
-				      DMX_MEMORY_BASED_FILTERING);
-
-	dvb_dmx_init(&budget->demux);
-
-	budget->dmxdev.filternum = 256;
-	budget->dmxdev.demux = &dvbdemux->dmx;
-	budget->dmxdev.capabilities = 0;
-
-	dvb_dmxdev_init(&budget->dmxdev, &budget->dvb_adapter);
-
-	budget->hw_frontend.source = DMX_FRONTEND_0;
-
-	ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &budget->hw_frontend);
-
-	if (ret < 0)
-		return ret;
-
-	budget->mem_frontend.source = DMX_MEMORY_FE;
-	ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &budget->mem_frontend);
-	if (ret < 0)
-		return ret;
-
-	ret = dvbdemux->dmx.connect_frontend(&dvbdemux->dmx, &budget->hw_frontend);
-	if (ret < 0)
-		return ret;
-
-	dvb_net_init(&budget->dvb_adapter, &budget->dvb_net, &dvbdemux->dmx);
-
-	return 0;
-}
-
-static void budget_unregister(struct budget *budget)
-{
-	struct dvb_demux *dvbdemux = &budget->demux;
-
-	dprintk(2, "budget: %p\n", budget);
-
-	dvb_net_release(&budget->dvb_net);
-
-	dvbdemux->dmx.close(&dvbdemux->dmx);
-	dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &budget->hw_frontend);
-	dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &budget->mem_frontend);
-
-	dvb_dmxdev_release(&budget->dmxdev);
-	dvb_dmx_release(&budget->demux);
-}
-
-int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev,
-		      struct saa7146_pci_extension_data *info,
-		      struct module *owner, short *adapter_nums)
-{
-	int ret = 0;
-	struct budget_info *bi = info->ext_priv;
-	int max_bufsize;
-	int height_mask;
-
-	memset(budget, 0, sizeof(struct budget));
-
-	dprintk(2, "dev: %p, budget: %p\n", dev, budget);
-
-	budget->card = bi;
-	budget->dev = (struct saa7146_dev *) dev;
-
-	switch(budget->card->type) {
-	case BUDGET_FS_ACTIVY:
-		budget->buffer_width = TS_WIDTH_ACTIVY;
-		max_bufsize = TS_MAX_BUFSIZE_K_ACTIVY;
-		height_mask = TS_HEIGHT_MASK_ACTIVY;
-		break;
-
-	case BUDGET_KNC1C:
-	case BUDGET_KNC1CP:
-	case BUDGET_CIN1200C:
-	case BUDGET_KNC1C_MK3:
-	case BUDGET_KNC1C_TDA10024:
-	case BUDGET_KNC1CP_MK3:
-	case BUDGET_CIN1200C_MK3:
-		budget->buffer_width = TS_WIDTH_DVBC;
-		max_bufsize = TS_MAX_BUFSIZE_K_DVBC;
-		height_mask = TS_HEIGHT_MASK_DVBC;
-		break;
-
-	default:
-		budget->buffer_width = TS_WIDTH;
-		max_bufsize = TS_MAX_BUFSIZE_K;
-		height_mask = TS_HEIGHT_MASK;
-	}
-
-	if (dma_buffer_size < TS_MIN_BUFSIZE_K)
-		dma_buffer_size = TS_MIN_BUFSIZE_K;
-	else if (dma_buffer_size > max_bufsize)
-		dma_buffer_size = max_bufsize;
-
-	budget->buffer_height = dma_buffer_size * 1024 / budget->buffer_width;
-	if (budget->buffer_height > 0xfff) {
-		budget->buffer_height /= 2;
-		budget->buffer_height &= height_mask;
-		budget->buffer_size = 2 * budget->buffer_height * budget->buffer_width;
-	} else {
-		budget->buffer_height &= height_mask;
-		budget->buffer_size = budget->buffer_height * budget->buffer_width;
-	}
-	budget->buffer_warning_threshold = budget->buffer_size * 80/100;
-	budget->buffer_warnings = 0;
-	budget->buffer_warning_time = jiffies;
-
-	dprintk(2, "%s: buffer type = %s, width = %d, height = %d\n",
-		budget->dev->name,
-		budget->buffer_size > budget->buffer_width * budget->buffer_height ? "odd/even" : "single",
-		budget->buffer_width, budget->buffer_height);
-	printk("%s: dma buffer size %u\n", budget->dev->name, budget->buffer_size);
-
-	ret = dvb_register_adapter(&budget->dvb_adapter, budget->card->name,
-				   owner, &budget->dev->pci->dev, adapter_nums);
-	if (ret < 0)
-		return ret;
-
-	/* set dd1 stream a & b */
-	saa7146_write(dev, DD1_STREAM_B, 0x00000000);
-	saa7146_write(dev, MC2, (MASK_09 | MASK_25));
-	saa7146_write(dev, MC2, (MASK_10 | MASK_26));
-	saa7146_write(dev, DD1_INIT, 0x02000000);
-	saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));
-
-	if (bi->type != BUDGET_FS_ACTIVY)
-		budget->video_port = BUDGET_VIDEO_PORTB;
-	else
-		budget->video_port = BUDGET_VIDEO_PORTA;
-	spin_lock_init(&budget->feedlock);
-	spin_lock_init(&budget->debilock);
-
-	/* the Siemens DVB needs this if you want to have the i2c chips
-	   get recognized before the main driver is loaded */
-	if (bi->type != BUDGET_FS_ACTIVY)
-		saa7146_write(dev, GPIO_CTRL, 0x500000);	/* GPIO 3 = 1 */
-
-	strlcpy(budget->i2c_adap.name, budget->card->name, sizeof(budget->i2c_adap.name));
-
-	saa7146_i2c_adapter_prepare(dev, &budget->i2c_adap, SAA7146_I2C_BUS_BIT_RATE_120);
-	strcpy(budget->i2c_adap.name, budget->card->name);
-
-	if (i2c_add_adapter(&budget->i2c_adap) < 0) {
-		ret = -ENOMEM;
-		goto err_dvb_unregister;
-	}
-
-	ttpci_eeprom_parse_mac(&budget->i2c_adap, budget->dvb_adapter.proposed_mac);
-
-	budget->grabbing = saa7146_vmalloc_build_pgtable(dev->pci, budget->buffer_size, &budget->pt);
-	if (NULL == budget->grabbing) {
-		ret = -ENOMEM;
-		goto err_del_i2c;
-	}
-
-	saa7146_write(dev, PCI_BT_V1, 0x001c0000);
-	/* upload all */
-	saa7146_write(dev, GPIO_CTRL, 0x000000);
-
-	tasklet_init(&budget->vpe_tasklet, vpeirq, (unsigned long) budget);
-
-	/* frontend power on */
-	if (bi->type != BUDGET_FS_ACTIVY)
-		saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI);
-
-	if ((ret = budget_register(budget)) == 0)
-		return 0; /* Everything OK */
-
-	/* An error occurred, cleanup resources */
-	saa7146_vfree_destroy_pgtable(dev->pci, budget->grabbing, &budget->pt);
-
-err_del_i2c:
-	i2c_del_adapter(&budget->i2c_adap);
-
-err_dvb_unregister:
-	dvb_unregister_adapter(&budget->dvb_adapter);
-
-	return ret;
-}
-
-void ttpci_budget_init_hooks(struct budget *budget)
-{
-	if (budget->dvb_frontend && !budget->read_fe_status) {
-		budget->read_fe_status = budget->dvb_frontend->ops.read_status;
-		budget->dvb_frontend->ops.read_status = budget_read_fe_status;
-	}
-}
-
-int ttpci_budget_deinit(struct budget *budget)
-{
-	struct saa7146_dev *dev = budget->dev;
-
-	dprintk(2, "budget: %p\n", budget);
-
-	budget_unregister(budget);
-
-	tasklet_kill(&budget->vpe_tasklet);
-
-	saa7146_vfree_destroy_pgtable(dev->pci, budget->grabbing, &budget->pt);
-
-	i2c_del_adapter(&budget->i2c_adap);
-
-	dvb_unregister_adapter(&budget->dvb_adapter);
-
-	return 0;
-}
-
-void ttpci_budget_irq10_handler(struct saa7146_dev *dev, u32 * isr)
-{
-	struct budget *budget = (struct budget *) dev->ext_priv;
-
-	dprintk(8, "dev: %p, budget: %p\n", dev, budget);
-
-	if (*isr & MASK_10)
-		tasklet_schedule(&budget->vpe_tasklet);
-}
-
-void ttpci_budget_set_video_port(struct saa7146_dev *dev, int video_port)
-{
-	struct budget *budget = (struct budget *) dev->ext_priv;
-
-	spin_lock(&budget->feedlock);
-	budget->video_port = video_port;
-	if (budget->feeding) {
-		stop_ts_capture(budget);
-		start_ts_capture(budget);
-	}
-	spin_unlock(&budget->feedlock);
-}
-
-EXPORT_SYMBOL_GPL(ttpci_budget_debiread);
-EXPORT_SYMBOL_GPL(ttpci_budget_debiwrite);
-EXPORT_SYMBOL_GPL(ttpci_budget_init);
-EXPORT_SYMBOL_GPL(ttpci_budget_init_hooks);
-EXPORT_SYMBOL_GPL(ttpci_budget_deinit);
-EXPORT_SYMBOL_GPL(ttpci_budget_irq10_handler);
-EXPORT_SYMBOL_GPL(ttpci_budget_set_video_port);
-EXPORT_SYMBOL_GPL(budget_debug);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/ttpci/budget-patch.c b/drivers/media/dvb/ttpci/budget-patch.c
deleted file mode 100644
index 2cb35c2..0000000
--- a/drivers/media/dvb/ttpci/budget-patch.c
+++ /dev/null
@@ -1,680 +0,0 @@
-/*
- * budget-patch.c: driver for Budget Patch,
- * hardware modification of DVB-S cards enabling full TS
- *
- * Written by Emard <emard@softhome.net>
- *
- * Original idea by Roberto Deza <rdeza@unav.es>
- *
- * Special thanks to Holger Waechtler, Michael Hunold, Marian Durkovic
- * and Metzlerbros
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the 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.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- *
- *
- * the project's page is at http://www.linuxtv.org/ 
- */
-
-#include "av7110.h"
-#include "av7110_hw.h"
-#include "budget.h"
-#include "stv0299.h"
-#include "ves1x93.h"
-#include "tda8083.h"
-
-#include "bsru6.h"
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-#define budget_patch budget
-
-static struct saa7146_extension budget_extension;
-
-MAKE_BUDGET_INFO(ttbp, "TT-Budget/Patch DVB-S 1.x PCI", BUDGET_PATCH);
-//MAKE_BUDGET_INFO(satel,"TT-Budget/Patch SATELCO PCI", BUDGET_TT_HW_DISEQC);
-
-static struct pci_device_id pci_tbl[] = {
-	MAKE_EXTENSION_PCI(ttbp,0x13c2, 0x0000),
-//        MAKE_EXTENSION_PCI(satel, 0x13c2, 0x1013),
-	{
-		.vendor    = 0,
-	}
-};
-
-/* those lines are for budget-patch to be tried
-** on a true budget card and observe the
-** behaviour of VSYNC generated by rps1.
-** this code was shamelessly copy/pasted from budget.c
-*/
-static void gpio_Set22K (struct budget *budget, int state)
-{
-	struct saa7146_dev *dev=budget->dev;
-	dprintk(2, "budget: %p\n", budget);
-	saa7146_setgpio(dev, 3, (state ? SAA7146_GPIO_OUTHI : SAA7146_GPIO_OUTLO));
-}
-
-/* Diseqc functions only for TT Budget card */
-/* taken from the Skyvision DVB driver by
-   Ralph Metzler <rjkm@metzlerbros.de> */
-
-static void DiseqcSendBit (struct budget *budget, int data)
-{
-	struct saa7146_dev *dev=budget->dev;
-	dprintk(2, "budget: %p\n", budget);
-
-	saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI);
-	udelay(data ? 500 : 1000);
-	saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
-	udelay(data ? 1000 : 500);
-}
-
-static void DiseqcSendByte (struct budget *budget, int data)
-{
-	int i, par=1, d;
-
-	dprintk(2, "budget: %p\n", budget);
-
-	for (i=7; i>=0; i--) {
-		d = (data>>i)&1;
-		par ^= d;
-		DiseqcSendBit(budget, d);
-	}
-
-	DiseqcSendBit(budget, par);
-}
-
-static int SendDiSEqCMsg (struct budget *budget, int len, u8 *msg, unsigned long burst)
-{
-	struct saa7146_dev *dev=budget->dev;
-	int i;
-
-	dprintk(2, "budget: %p\n", budget);
-
-	saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
-	mdelay(16);
-
-	for (i=0; i<len; i++)
-		DiseqcSendByte(budget, msg[i]);
-
-	mdelay(16);
-
-	if (burst!=-1) {
-		if (burst)
-			DiseqcSendByte(budget, 0xff);
-		else {
-			saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI);
-			mdelay(12);
-			udelay(500);
-			saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
-		}
-		msleep(20);
-	}
-
-	return 0;
-}
-
-/* shamelessly copy/pasted from budget.c
-*/
-static int budget_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
-{
-	struct budget* budget = (struct budget*) fe->dvb->priv;
-
-	switch (tone) {
-	case SEC_TONE_ON:
-		gpio_Set22K (budget, 1);
-		break;
-
-	case SEC_TONE_OFF:
-		gpio_Set22K (budget, 0);
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int budget_diseqc_send_master_cmd(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd)
-{
-	struct budget* budget = (struct budget*) fe->dvb->priv;
-
-	SendDiSEqCMsg (budget, cmd->msg_len, cmd->msg, 0);
-
-	return 0;
-}
-
-static int budget_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd)
-{
-	struct budget* budget = (struct budget*) fe->dvb->priv;
-
-	SendDiSEqCMsg (budget, 0, NULL, minicmd);
-
-	return 0;
-}
-
-static int budget_av7110_send_fw_cmd(struct budget_patch *budget, u16* buf, int length)
-{
-	int i;
-
-	dprintk(2, "budget: %p\n", budget);
-
-	for (i = 2; i < length; i++)
-	{
-		  ttpci_budget_debiwrite(budget, DEBINOSWAP, COMMAND + 2*i, 2, (u32) buf[i], 0,0);
-		  msleep(5);
-	}
-	if (length)
-		  ttpci_budget_debiwrite(budget, DEBINOSWAP, COMMAND + 2, 2, (u32) buf[1], 0,0);
-	else
-		  ttpci_budget_debiwrite(budget, DEBINOSWAP, COMMAND + 2, 2, 0, 0,0);
-	msleep(5);
-	ttpci_budget_debiwrite(budget, DEBINOSWAP, COMMAND, 2, (u32) buf[0], 0,0);
-	msleep(5);
-	return 0;
-}
-
-static void av7110_set22k(struct budget_patch *budget, int state)
-{
-	u16 buf[2] = {( COMTYPE_AUDIODAC << 8) | (state ? ON22K : OFF22K), 0};
-
-	dprintk(2, "budget: %p\n", budget);
-	budget_av7110_send_fw_cmd(budget, buf, 2);
-}
-
-static int av7110_send_diseqc_msg(struct budget_patch *budget, int len, u8 *msg, int burst)
-{
-	int i;
-	u16 buf[18] = { ((COMTYPE_AUDIODAC << 8) | SendDiSEqC),
-		16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-
-	dprintk(2, "budget: %p\n", budget);
-
-	if (len>10)
-		len=10;
-
-	buf[1] = len+2;
-	buf[2] = len;
-
-	if (burst != -1)
-		buf[3]=burst ? 0x01 : 0x00;
-	else
-		buf[3]=0xffff;
-
-	for (i=0; i<len; i++)
-		buf[i+4]=msg[i];
-
-	budget_av7110_send_fw_cmd(budget, buf, 18);
-	return 0;
-}
-
-static int budget_patch_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
-{
-	struct budget_patch* budget = (struct budget_patch*) fe->dvb->priv;
-
-	switch (tone) {
-	case SEC_TONE_ON:
-		av7110_set22k (budget, 1);
-		break;
-
-	case SEC_TONE_OFF:
-		av7110_set22k (budget, 0);
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int budget_patch_diseqc_send_master_cmd(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd)
-{
-	struct budget_patch* budget = (struct budget_patch*) fe->dvb->priv;
-
-	av7110_send_diseqc_msg (budget, cmd->msg_len, cmd->msg, 0);
-
-	return 0;
-}
-
-static int budget_patch_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd)
-{
-	struct budget_patch* budget = (struct budget_patch*) fe->dvb->priv;
-
-	av7110_send_diseqc_msg (budget, 0, NULL, minicmd);
-
-	return 0;
-}
-
-static int alps_bsrv2_tuner_set_params(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct budget_patch* budget = (struct budget_patch*) fe->dvb->priv;
-	u8 pwr = 0;
-	u8 buf[4];
-	struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
-	u32 div = (p->frequency + 479500) / 125;
-
-	if (p->frequency > 2000000)
-		pwr = 3;
-	else if (p->frequency > 1800000)
-		pwr = 2;
-	else if (p->frequency > 1600000)
-		pwr = 1;
-	else if (p->frequency > 1200000)
-		pwr = 0;
-	else if (p->frequency >= 1100000)
-		pwr = 1;
-	else pwr = 2;
-
-	buf[0] = (div >> 8) & 0x7f;
-	buf[1] = div & 0xff;
-	buf[2] = ((div & 0x18000) >> 10) | 0x95;
-	buf[3] = (pwr << 6) | 0x30;
-
-	// NOTE: since we're using a prescaler of 2, we set the
-	// divisor frequency to 62.5kHz and divide by 125 above
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1)
-		return -EIO;
-	return 0;
-}
-
-static struct ves1x93_config alps_bsrv2_config = {
-	.demod_address = 0x08,
-	.xin = 90100000UL,
-	.invert_pwm = 0,
-};
-
-static int grundig_29504_451_tuner_set_params(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct budget_patch* budget = (struct budget_patch*) fe->dvb->priv;
-	u32 div;
-	u8 data[4];
-	struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
-
-	div = p->frequency / 125;
-	data[0] = (div >> 8) & 0x7f;
-	data[1] = div & 0xff;
-	data[2] = 0x8e;
-	data[3] = 0x00;
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1)
-		return -EIO;
-	return 0;
-}
-
-static struct tda8083_config grundig_29504_451_config = {
-	.demod_address = 0x68,
-};
-
-static void frontend_init(struct budget_patch* budget)
-{
-	switch(budget->dev->pci->subsystem_device) {
-	case 0x0000: // Hauppauge/TT WinTV DVB-S rev1.X
-	case 0x1013: // SATELCO Multimedia PCI
-
-		// try the ALPS BSRV2 first of all
-		budget->dvb_frontend = dvb_attach(ves1x93_attach, &alps_bsrv2_config, &budget->i2c_adap);
-		if (budget->dvb_frontend) {
-			budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params;
-			budget->dvb_frontend->ops.diseqc_send_master_cmd = budget_patch_diseqc_send_master_cmd;
-			budget->dvb_frontend->ops.diseqc_send_burst = budget_patch_diseqc_send_burst;
-			budget->dvb_frontend->ops.set_tone = budget_patch_set_tone;
-			break;
-		}
-
-		// try the ALPS BSRU6 now
-		budget->dvb_frontend = dvb_attach(stv0299_attach, &alps_bsru6_config, &budget->i2c_adap);
-		if (budget->dvb_frontend) {
-			budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
-			budget->dvb_frontend->tuner_priv = &budget->i2c_adap;
-
-			budget->dvb_frontend->ops.diseqc_send_master_cmd = budget_diseqc_send_master_cmd;
-			budget->dvb_frontend->ops.diseqc_send_burst = budget_diseqc_send_burst;
-			budget->dvb_frontend->ops.set_tone = budget_set_tone;
-			break;
-		}
-
-		// Try the grundig 29504-451
-		budget->dvb_frontend = dvb_attach(tda8083_attach, &grundig_29504_451_config, &budget->i2c_adap);
-		if (budget->dvb_frontend) {
-			budget->dvb_frontend->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params;
-			budget->dvb_frontend->ops.diseqc_send_master_cmd = budget_diseqc_send_master_cmd;
-			budget->dvb_frontend->ops.diseqc_send_burst = budget_diseqc_send_burst;
-			budget->dvb_frontend->ops.set_tone = budget_set_tone;
-			break;
-		}
-		break;
-	}
-
-	if (budget->dvb_frontend == NULL) {
-		printk("dvb-ttpci: A frontend driver was not found for device [%04x:%04x] subsystem [%04x:%04x]\n",
-		       budget->dev->pci->vendor,
-		       budget->dev->pci->device,
-		       budget->dev->pci->subsystem_vendor,
-		       budget->dev->pci->subsystem_device);
-	} else {
-		if (dvb_register_frontend(&budget->dvb_adapter, budget->dvb_frontend)) {
-			printk("budget-av: Frontend registration failed!\n");
-			dvb_frontend_detach(budget->dvb_frontend);
-			budget->dvb_frontend = NULL;
-		}
-	}
-}
-
-/* written by Emard */
-static int budget_patch_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_data *info)
-{
-	struct budget_patch *budget;
-	int err;
-	int count = 0;
-	int detected = 0;
-
-#define PATCH_RESET 0
-#define RPS_IRQ 0
-#define HPS_SETUP 0
-#if PATCH_RESET
-	saa7146_write(dev, MC1, MASK_31);
-	msleep(40);
-#endif
-#if HPS_SETUP
-	// initialize registers. Better to have it like this
-	// than leaving something unconfigured
-	saa7146_write(dev, DD1_STREAM_B, 0);
-	// port B VSYNC at rising edge
-	saa7146_write(dev, DD1_INIT, 0x00000200);  // have this in budget-core too!
-	saa7146_write(dev, BRS_CTRL, 0x00000000);  // VBI
-
-	// debi config
-	// saa7146_write(dev, DEBI_CONFIG, MASK_30|MASK_28|MASK_18);
-
-	// zero all HPS registers
-	saa7146_write(dev, HPS_H_PRESCALE, 0);                  // r68
-	saa7146_write(dev, HPS_H_SCALE, 0);                     // r6c
-	saa7146_write(dev, BCS_CTRL, 0);                        // r70
-	saa7146_write(dev, HPS_V_SCALE, 0);                     // r60
-	saa7146_write(dev, HPS_V_GAIN, 0);                      // r64
-	saa7146_write(dev, CHROMA_KEY_RANGE, 0);                // r74
-	saa7146_write(dev, CLIP_FORMAT_CTRL, 0);                // r78
-	// Set HPS prescaler for port B input
-	saa7146_write(dev, HPS_CTRL, (1<<30) | (0<<29) | (1<<28) | (0<<12) );
-	saa7146_write(dev, MC2,
-	  0 * (MASK_08 | MASK_24)  |   // BRS control
-	  0 * (MASK_09 | MASK_25)  |   // a
-	  0 * (MASK_10 | MASK_26)  |   // b
-	  1 * (MASK_06 | MASK_22)  |   // HPS_CTRL1
-	  1 * (MASK_05 | MASK_21)  |   // HPS_CTRL2
-	  0 * (MASK_01 | MASK_15)      // DEBI
-	   );
-#endif
-	// Disable RPS1 and RPS0
-	saa7146_write(dev, MC1, ( MASK_29 | MASK_28));
-	// RPS1 timeout disable
-	saa7146_write(dev, RPS_TOV1, 0);
-
-	// code for autodetection
-	// will wait for VBI_B event (vertical blank at port B)
-	// and will reset GPIO3 after VBI_B is detected.
-	// (GPIO3 should be raised high by CPU to
-	// test if GPIO3 will generate vertical blank signal
-	// in budget patch GPIO3 is connected to VSYNC_B
-	count = 0;
-#if 0
-	WRITE_RPS1(CMD_UPLOAD |
-	  MASK_10 | MASK_09 | MASK_08 | MASK_06 | MASK_05 | MASK_04 | MASK_03 | MASK_02 );
-#endif
-	WRITE_RPS1(CMD_PAUSE | EVT_VBI_B);
-	WRITE_RPS1(CMD_WR_REG_MASK | (GPIO_CTRL>>2));
-	WRITE_RPS1(GPIO3_MSK);
-	WRITE_RPS1(SAA7146_GPIO_OUTLO<<24);
-#if RPS_IRQ
-	// issue RPS1 interrupt to increment counter
-	WRITE_RPS1(CMD_INTERRUPT);
-	// at least a NOP is neede between two interrupts
-	WRITE_RPS1(CMD_NOP);
-	// interrupt again
-	WRITE_RPS1(CMD_INTERRUPT);
-#endif
-	WRITE_RPS1(CMD_STOP);
-
-#if RPS_IRQ
-	// set event counter 1 source as RPS1 interrupt (0x03)          (rE4 p53)
-	// use 0x03 to track RPS1 interrupts - increase by 1 every gpio3 is toggled
-	// use 0x15 to track VPE  interrupts - increase by 1 every vpeirq() is called
-	saa7146_write(dev, EC1SSR, (0x03<<2) | 3 );
-	// set event counter 1 threshold to maximum allowed value        (rEC p55)
-	saa7146_write(dev, ECT1R,  0x3fff );
-#endif
-	// Fix VSYNC level
-	saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
-	// Set RPS1 Address register to point to RPS code               (r108 p42)
-	saa7146_write(dev, RPS_ADDR1, dev->d_rps1.dma_handle);
-	// Enable RPS1,                                                 (rFC p33)
-	saa7146_write(dev, MC1, (MASK_13 | MASK_29 ));
-
-
-	mdelay(50);
-	saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI);
-	mdelay(150);
-
-
-	if( (saa7146_read(dev, GPIO_CTRL) & 0x10000000) == 0)
-		detected = 1;
-
-#if RPS_IRQ
-	printk("Event Counter 1 0x%04x\n", saa7146_read(dev, EC1R) & 0x3fff );
-#endif
-	// Disable RPS1
-	saa7146_write(dev, MC1, ( MASK_29 ));
-
-	if(detected == 0)
-		printk("budget-patch not detected or saa7146 in non-default state.\n"
-		       "try enabling ressetting of 7146 with MASK_31 in MC1 register\n");
-
-	else
-		printk("BUDGET-PATCH DETECTED.\n");
-
-
-/*      OLD (Original design by Roberto Deza):
-**      This code will setup the SAA7146_RPS1 to generate a square
-**      wave on GPIO3, changing when a field (TS_HEIGHT/2 "lines" of
-**      TS_WIDTH packets) has been acquired on SAA7146_D1B video port;
-**      then, this GPIO3 output which is connected to the D1B_VSYNC
-**      input, will trigger the acquisition of the alternate field
-**      and so on.
-**      Currently, the TT_budget / WinTV_Nova cards have two ICs
-**      (74HCT4040, LVC74) for the generation of this VSYNC signal,
-**      which seems that can be done perfectly without this :-)).
-*/
-
-/*      New design (By Emard)
-**      this rps1 code will copy internal HS event to GPIO3 pin.
-**      GPIO3 is in budget-patch hardware connected to port B VSYNC
-
-**      HS is an internal event of 7146, accessible with RPS
-**      and temporarily raised high every n lines
-**      (n in defined in the RPS_THRESH1 counter threshold)
-**      I think HS is raised high on the beginning of the n-th line
-**      and remains high until this n-th line that triggered
-**      it is completely received. When the reception of n-th line
-**      ends, HS is lowered.
-
-**      To transmit data over DMA, 7146 needs changing state at
-**      port B VSYNC pin. Any changing of port B VSYNC will
-**      cause some DMA data transfer, with more or less packets loss.
-**      It depends on the phase and frequency of VSYNC and
-**      the way of 7146 is instructed to trigger on port B (defined
-**      in DD1_INIT register, 3rd nibble from the right valid
-**      numbers are 0-7, see datasheet)
-**
-**      The correct triggering can minimize packet loss,
-**      dvbtraffic should give this stable bandwidths:
-**        22k transponder = 33814 kbit/s
-**      27.5k transponder = 38045 kbit/s
-**      by experiment it is found that the best results
-**      (stable bandwidths and almost no packet loss)
-**      are obtained using DD1_INIT triggering number 2
-**      (Va at rising edge of VS Fa = HS x VS-failing forced toggle)
-**      and a VSYNC phase that occurs in the middle of DMA transfer
-**      (about byte 188*512=96256 in the DMA window).
-**
-**      Phase of HS is still not clear to me how to control,
-**      It just happens to be so. It can be seen if one enables
-**      RPS_IRQ and print Event Counter 1 in vpeirq(). Every
-**      time RPS_INTERRUPT is called, the Event Counter 1 will
-**      increment. That's how the 7146 is programmed to do event
-**      counting in this budget-patch.c
-**      I *think* HPS setting has something to do with the phase
-**      of HS but I can't be 100% sure in that.
-
-**      hardware debug note: a working budget card (including budget patch)
-**      with vpeirq() interrupt setup in mode "0x90" (every 64K) will
-**      generate 3 interrupts per 25-Hz DMA frame of 2*188*512 bytes
-**      and that means 3*25=75 Hz of interrupt frequency, as seen by
-**      watch cat /proc/interrupts
-**
-**      If this frequency is 3x lower (and data received in the DMA
-**      buffer don't start with 0x47, but in the middle of packets,
-**      whose lengths appear to be like 188 292 188 104 etc.
-**      this means VSYNC line is not connected in the hardware.
-**      (check soldering pcb and pins)
-**      The same behaviour of missing VSYNC can be duplicated on budget
-**      cards, by setting DD1_INIT trigger mode 7 in 3rd nibble.
-*/
-
-	// Setup RPS1 "program" (p35)
-	count = 0;
-
-
-	// Wait Source Line Counter Threshold                           (p36)
-	WRITE_RPS1(CMD_PAUSE | EVT_HS);
-	// Set GPIO3=1                                                  (p42)
-	WRITE_RPS1(CMD_WR_REG_MASK | (GPIO_CTRL>>2));
-	WRITE_RPS1(GPIO3_MSK);
-	WRITE_RPS1(SAA7146_GPIO_OUTHI<<24);
-#if RPS_IRQ
-	// issue RPS1 interrupt
-	WRITE_RPS1(CMD_INTERRUPT);
-#endif
-	// Wait reset Source Line Counter Threshold                     (p36)
-	WRITE_RPS1(CMD_PAUSE | RPS_INV | EVT_HS);
-	// Set GPIO3=0                                                  (p42)
-	WRITE_RPS1(CMD_WR_REG_MASK | (GPIO_CTRL>>2));
-	WRITE_RPS1(GPIO3_MSK);
-	WRITE_RPS1(SAA7146_GPIO_OUTLO<<24);
-#if RPS_IRQ
-	// issue RPS1 interrupt
-	WRITE_RPS1(CMD_INTERRUPT);
-#endif
-	// Jump to begin of RPS program                                 (p37)
-	WRITE_RPS1(CMD_JUMP);
-	WRITE_RPS1(dev->d_rps1.dma_handle);
-
-	// Fix VSYNC level
-	saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
-	// Set RPS1 Address register to point to RPS code               (r108 p42)
-	saa7146_write(dev, RPS_ADDR1, dev->d_rps1.dma_handle);
-
-	if (!(budget = kmalloc (sizeof(struct budget_patch), GFP_KERNEL)))
-		return -ENOMEM;
-
-	dprintk(2, "budget: %p\n", budget);
-
-	err = ttpci_budget_init(budget, dev, info, THIS_MODULE, adapter_nr);
-	if (err) {
-		kfree(budget);
-		return err;
-	}
-
-	// Set Source Line Counter Threshold, using BRS                 (rCC p43)
-	// It generates HS event every TS_HEIGHT lines
-	// this is related to TS_WIDTH set in register
-	// NUM_LINE_BYTE3 in budget-core.c. If NUM_LINE_BYTE
-	// low 16 bits are set to TS_WIDTH bytes (TS_WIDTH=2*188
-	//,then RPS_THRESH1
-	// should be set to trigger every TS_HEIGHT (512) lines.
-	//
-	saa7146_write(dev, RPS_THRESH1, budget->buffer_height | MASK_12 );
-
-	// saa7146_write(dev, RPS_THRESH0, ((TS_HEIGHT/2)<<16) |MASK_28| (TS_HEIGHT/2) |MASK_12 );
-	// Enable RPS1                                                  (rFC p33)
-	saa7146_write(dev, MC1, (MASK_13 | MASK_29));
-
-
-	dev->ext_priv = budget;
-
-	budget->dvb_adapter.priv = budget;
-	frontend_init(budget);
-
-	ttpci_budget_init_hooks(budget);
-
-	return 0;
-}
-
-static int budget_patch_detach (struct saa7146_dev* dev)
-{
-	struct budget_patch *budget = (struct budget_patch*) dev->ext_priv;
-	int err;
-
-	if (budget->dvb_frontend) {
-		dvb_unregister_frontend(budget->dvb_frontend);
-		dvb_frontend_detach(budget->dvb_frontend);
-	}
-	err = ttpci_budget_deinit (budget);
-
-	kfree (budget);
-
-	return err;
-}
-
-static int __init budget_patch_init(void)
-{
-	return saa7146_register_extension(&budget_extension);
-}
-
-static void __exit budget_patch_exit(void)
-{
-	saa7146_unregister_extension(&budget_extension);
-}
-
-static struct saa7146_extension budget_extension = {
-	.name           = "budget_patch dvb",
-	.flags          = 0,
-
-	.module         = THIS_MODULE,
-	.pci_tbl        = pci_tbl,
-	.attach         = budget_patch_attach,
-	.detach         = budget_patch_detach,
-
-	.irq_mask       = MASK_10,
-	.irq_func       = ttpci_budget_irq10_handler,
-};
-
-module_init(budget_patch_init);
-module_exit(budget_patch_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Emard, Roberto Deza, Holger Waechtler, Michael Hunold, others");
-MODULE_DESCRIPTION("Driver for full TS modified DVB-S SAA7146+AV7110 "
-		   "based so-called Budget Patch cards");
diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c
deleted file mode 100644
index b21bcce..0000000
--- a/drivers/media/dvb/ttpci/budget.c
+++ /dev/null
@@ -1,811 +0,0 @@
-/*
- * budget.c: driver for the SAA7146 based Budget DVB cards
- *
- * Compiled from various sources by Michael Hunold <michael@mihu.de>
- *
- * Copyright (C) 2002 Ralph Metzler <rjkm@metzlerbros.de>
- *
- * Copyright (C) 1999-2002 Ralph  Metzler
- *                       & Marcus Metzler for convergence integrated media GmbH
- *
- * 26feb2004 Support for FS Activy Card (Grundig tuner) by
- *           Michael Dreher <michael@5dot1.de>,
- *           Oliver Endriss <o.endriss@gmx.de> and
- *           Andreas 'randy' Weinberger
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the 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.
- * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- *
- *
- * the project's page is at http://www.linuxtv.org/ 
- */
-
-#include "budget.h"
-#include "stv0299.h"
-#include "ves1x93.h"
-#include "ves1820.h"
-#include "l64781.h"
-#include "tda8083.h"
-#include "s5h1420.h"
-#include "tda10086.h"
-#include "tda826x.h"
-#include "lnbp21.h"
-#include "bsru6.h"
-#include "bsbe1.h"
-#include "tdhd1.h"
-#include "stv6110x.h"
-#include "stv090x.h"
-#include "isl6423.h"
-
-static int diseqc_method;
-module_param(diseqc_method, int, 0444);
-MODULE_PARM_DESC(diseqc_method, "Select DiSEqC method for subsystem id 13c2:1003, 0: default, 1: more reliable (for newer revisions only)");
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-static void Set22K (struct budget *budget, int state)
-{
-	struct saa7146_dev *dev=budget->dev;
-	dprintk(2, "budget: %p\n", budget);
-	saa7146_setgpio(dev, 3, (state ? SAA7146_GPIO_OUTHI : SAA7146_GPIO_OUTLO));
-}
-
-/* Diseqc functions only for TT Budget card */
-/* taken from the Skyvision DVB driver by
-   Ralph Metzler <rjkm@metzlerbros.de> */
-
-static void DiseqcSendBit (struct budget *budget, int data)
-{
-	struct saa7146_dev *dev=budget->dev;
-	dprintk(2, "budget: %p\n", budget);
-
-	saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI);
-	udelay(data ? 500 : 1000);
-	saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
-	udelay(data ? 1000 : 500);
-}
-
-static void DiseqcSendByte (struct budget *budget, int data)
-{
-	int i, par=1, d;
-
-	dprintk(2, "budget: %p\n", budget);
-
-	for (i=7; i>=0; i--) {
-		d = (data>>i)&1;
-		par ^= d;
-		DiseqcSendBit(budget, d);
-	}
-
-	DiseqcSendBit(budget, par);
-}
-
-static int SendDiSEqCMsg (struct budget *budget, int len, u8 *msg, unsigned long burst)
-{
-	struct saa7146_dev *dev=budget->dev;
-	int i;
-
-	dprintk(2, "budget: %p\n", budget);
-
-	saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
-	mdelay(16);
-
-	for (i=0; i<len; i++)
-		DiseqcSendByte(budget, msg[i]);
-
-	mdelay(16);
-
-	if (burst!=-1) {
-		if (burst)
-			DiseqcSendByte(budget, 0xff);
-		else {
-			saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI);
-			mdelay(12);
-			udelay(500);
-			saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO);
-		}
-		msleep(20);
-	}
-
-	return 0;
-}
-
-/*
- *   Routines for the Fujitsu Siemens Activy budget card
- *   22 kHz tone and DiSEqC are handled by the frontend.
- *   Voltage must be set here.
- *   GPIO 1: LNBP EN, GPIO 2: LNBP VSEL
- */
-static int SetVoltage_Activy (struct budget *budget, fe_sec_voltage_t voltage)
-{
-	struct saa7146_dev *dev=budget->dev;
-
-	dprintk(2, "budget: %p\n", budget);
-
-	switch (voltage) {
-		case SEC_VOLTAGE_13:
-			saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI);
-			saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTLO);
-			break;
-		case SEC_VOLTAGE_18:
-			saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI);
-			saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI);
-			break;
-		case SEC_VOLTAGE_OFF:
-			saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTLO);
-			break;
-		default:
-			return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int siemens_budget_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
-{
-	struct budget* budget = (struct budget*) fe->dvb->priv;
-
-	return SetVoltage_Activy (budget, voltage);
-}
-
-static int budget_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
-{
-	struct budget* budget = (struct budget*) fe->dvb->priv;
-
-	switch (tone) {
-	case SEC_TONE_ON:
-		Set22K (budget, 1);
-		break;
-
-	case SEC_TONE_OFF:
-		Set22K (budget, 0);
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int budget_diseqc_send_master_cmd(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd)
-{
-	struct budget* budget = (struct budget*) fe->dvb->priv;
-
-	SendDiSEqCMsg (budget, cmd->msg_len, cmd->msg, 0);
-
-	return 0;
-}
-
-static int budget_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd)
-{
-	struct budget* budget = (struct budget*) fe->dvb->priv;
-
-	SendDiSEqCMsg (budget, 0, NULL, minicmd);
-
-	return 0;
-}
-
-static int alps_bsrv2_tuner_set_params(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	struct budget* budget = (struct budget*) fe->dvb->priv;
-	u8 pwr = 0;
-	u8 buf[4];
-	struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
-	u32 div = (c->frequency + 479500) / 125;
-
-	if (c->frequency > 2000000)
-		pwr = 3;
-	else if (c->frequency > 1800000)
-		pwr = 2;
-	else if (c->frequency > 1600000)
-		pwr = 1;
-	else if (c->frequency > 1200000)
-		pwr = 0;
-	else if (c->frequency >= 1100000)
-		pwr = 1;
-	else pwr = 2;
-
-	buf[0] = (div >> 8) & 0x7f;
-	buf[1] = div & 0xff;
-	buf[2] = ((div & 0x18000) >> 10) | 0x95;
-	buf[3] = (pwr << 6) | 0x30;
-
-	// NOTE: since we're using a prescaler of 2, we set the
-	// divisor frequency to 62.5kHz and divide by 125 above
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
-	return 0;
-}
-
-static struct ves1x93_config alps_bsrv2_config =
-{
-	.demod_address = 0x08,
-	.xin = 90100000UL,
-	.invert_pwm = 0,
-};
-
-static int alps_tdbe2_tuner_set_params(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	struct budget* budget = (struct budget*) fe->dvb->priv;
-	u32 div;
-	u8 data[4];
-	struct i2c_msg msg = { .addr = 0x62, .flags = 0, .buf = data, .len = sizeof(data) };
-
-	div = (c->frequency + 35937500 + 31250) / 62500;
-
-	data[0] = (div >> 8) & 0x7f;
-	data[1] = div & 0xff;
-	data[2] = 0x85 | ((div >> 10) & 0x60);
-	data[3] = (c->frequency < 174000000 ? 0x88 : c->frequency < 470000000 ? 0x84 : 0x81);
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
-	return 0;
-}
-
-static struct ves1820_config alps_tdbe2_config = {
-	.demod_address = 0x09,
-	.xin = 57840000UL,
-	.invert = 1,
-	.selagc = VES1820_SELAGC_SIGNAMPERR,
-};
-
-static int grundig_29504_401_tuner_set_params(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	struct budget *budget = fe->dvb->priv;
-	u8 *tuner_addr = fe->tuner_priv;
-	u32 div;
-	u8 cfg, cpump, band_select;
-	u8 data[4];
-	struct i2c_msg msg = { .flags = 0, .buf = data, .len = sizeof(data) };
-
-	if (tuner_addr)
-		msg.addr = *tuner_addr;
-	else
-		msg.addr = 0x61;
-
-	div = (36125000 + c->frequency) / 166666;
-
-	cfg = 0x88;
-
-	if (c->frequency < 175000000)
-		cpump = 2;
-	else if (c->frequency < 390000000)
-		cpump = 1;
-	else if (c->frequency < 470000000)
-		cpump = 2;
-	else if (c->frequency < 750000000)
-		cpump = 1;
-	else
-		cpump = 3;
-
-	if (c->frequency < 175000000)
-		band_select = 0x0e;
-	else if (c->frequency < 470000000)
-		band_select = 0x05;
-	else
-		band_select = 0x03;
-
-	data[0] = (div >> 8) & 0x7f;
-	data[1] = div & 0xff;
-	data[2] = ((div >> 10) & 0x60) | cfg;
-	data[3] = (cpump << 6) | band_select;
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
-	return 0;
-}
-
-static struct l64781_config grundig_29504_401_config = {
-	.demod_address = 0x55,
-};
-
-static struct l64781_config grundig_29504_401_config_activy = {
-	.demod_address = 0x54,
-};
-
-static u8 tuner_address_grundig_29504_401_activy = 0x60;
-
-static int grundig_29504_451_tuner_set_params(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	struct budget* budget = (struct budget*) fe->dvb->priv;
-	u32 div;
-	u8 data[4];
-	struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
-
-	div = c->frequency / 125;
-	data[0] = (div >> 8) & 0x7f;
-	data[1] = div & 0xff;
-	data[2] = 0x8e;
-	data[3] = 0x00;
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
-	return 0;
-}
-
-static struct tda8083_config grundig_29504_451_config = {
-	.demod_address = 0x68,
-};
-
-static int s5h1420_tuner_set_params(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	struct budget* budget = (struct budget*) fe->dvb->priv;
-	u32 div;
-	u8 data[4];
-	struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
-
-	div = c->frequency / 1000;
-	data[0] = (div >> 8) & 0x7f;
-	data[1] = div & 0xff;
-	data[2] = 0xc2;
-
-	if (div < 1450)
-		data[3] = 0x00;
-	else if (div < 1850)
-		data[3] = 0x40;
-	else if (div < 2000)
-		data[3] = 0x80;
-	else
-		data[3] = 0xc0;
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
-
-	return 0;
-}
-
-static struct s5h1420_config s5h1420_config = {
-	.demod_address = 0x53,
-	.invert = 1,
-	.cdclk_polarity = 1,
-};
-
-static struct tda10086_config tda10086_config = {
-	.demod_address = 0x0e,
-	.invert = 0,
-	.diseqc_tone = 1,
-	.xtal_freq = TDA10086_XTAL_16M,
-};
-
-static struct stv0299_config alps_bsru6_config_activy = {
-	.demod_address = 0x68,
-	.inittab = alps_bsru6_inittab,
-	.mclk = 88000000UL,
-	.invert = 1,
-	.op0_off = 1,
-	.min_delay_ms = 100,
-	.set_symbol_rate = alps_bsru6_set_symbol_rate,
-};
-
-static struct stv0299_config alps_bsbe1_config_activy = {
-	.demod_address = 0x68,
-	.inittab = alps_bsbe1_inittab,
-	.mclk = 88000000UL,
-	.invert = 1,
-	.op0_off = 1,
-	.min_delay_ms = 100,
-	.set_symbol_rate = alps_bsbe1_set_symbol_rate,
-};
-
-static int alps_tdhd1_204_request_firmware(struct dvb_frontend *fe, const struct firmware **fw, char *name)
-{
-	struct budget *budget = (struct budget *)fe->dvb->priv;
-
-	return request_firmware(fw, name, &budget->dev->pci->dev);
-}
-
-
-static int i2c_readreg(struct i2c_adapter *i2c, u8 adr, u8 reg)
-{
-	u8 val;
-	struct i2c_msg msg[] = {
-		{ .addr = adr, .flags = 0, .buf = &reg, .len = 1 },
-		{ .addr = adr, .flags = I2C_M_RD, .buf = &val, .len = 1 }
-	};
-
-	return (i2c_transfer(i2c, msg, 2) != 2) ? -EIO : val;
-}
-
-static u8 read_pwm(struct budget* budget)
-{
-	u8 b = 0xff;
-	u8 pwm;
-	struct i2c_msg msg[] = { { .addr = 0x50,.flags = 0,.buf = &b,.len = 1 },
-				 { .addr = 0x50,.flags = I2C_M_RD,.buf = &pwm,.len = 1} };
-
-	if ((i2c_transfer(&budget->i2c_adap, msg, 2) != 2) || (pwm == 0xff))
-		pwm = 0x48;
-
-	return pwm;
-}
-
-static struct stv090x_config tt1600_stv090x_config = {
-	.device			= STV0903,
-	.demod_mode		= STV090x_SINGLE,
-	.clk_mode		= STV090x_CLK_EXT,
-
-	.xtal			= 13500000,
-	.address		= 0x68,
-
-	.ts1_mode		= STV090x_TSMODE_DVBCI,
-	.ts2_mode		= STV090x_TSMODE_SERIAL_CONTINUOUS,
-
-	.repeater_level		= STV090x_RPTLEVEL_16,
-
-	.tuner_init		= NULL,
-	.tuner_sleep		= NULL,
-	.tuner_set_mode		= NULL,
-	.tuner_set_frequency	= NULL,
-	.tuner_get_frequency	= NULL,
-	.tuner_set_bandwidth	= NULL,
-	.tuner_get_bandwidth	= NULL,
-	.tuner_set_bbgain	= NULL,
-	.tuner_get_bbgain	= NULL,
-	.tuner_set_refclk	= NULL,
-	.tuner_get_status	= NULL,
-};
-
-static struct stv6110x_config tt1600_stv6110x_config = {
-	.addr			= 0x60,
-	.refclk			= 27000000,
-	.clk_div		= 2,
-};
-
-static struct isl6423_config tt1600_isl6423_config = {
-	.current_max		= SEC_CURRENT_515m,
-	.curlim			= SEC_CURRENT_LIM_ON,
-	.mod_extern		= 1,
-	.addr			= 0x08,
-};
-
-static void frontend_init(struct budget *budget)
-{
-	(void)alps_bsbe1_config; /* avoid warning */
-
-	switch(budget->dev->pci->subsystem_device) {
-	case 0x1003: // Hauppauge/TT Nova budget (stv0299/ALPS BSRU6(tsa5059) OR ves1893/ALPS BSRV2(sp5659))
-	case 0x1013:
-		// try the ALPS BSRV2 first of all
-		budget->dvb_frontend = dvb_attach(ves1x93_attach, &alps_bsrv2_config, &budget->i2c_adap);
-		if (budget->dvb_frontend) {
-			budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params;
-			budget->dvb_frontend->ops.diseqc_send_master_cmd = budget_diseqc_send_master_cmd;
-			budget->dvb_frontend->ops.diseqc_send_burst = budget_diseqc_send_burst;
-			budget->dvb_frontend->ops.set_tone = budget_set_tone;
-			break;
-		}
-
-		// try the ALPS BSRU6 now
-		budget->dvb_frontend = dvb_attach(stv0299_attach, &alps_bsru6_config, &budget->i2c_adap);
-		if (budget->dvb_frontend) {
-			budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
-			budget->dvb_frontend->tuner_priv = &budget->i2c_adap;
-			if (budget->dev->pci->subsystem_device == 0x1003 && diseqc_method == 0) {
-				budget->dvb_frontend->ops.diseqc_send_master_cmd = budget_diseqc_send_master_cmd;
-				budget->dvb_frontend->ops.diseqc_send_burst = budget_diseqc_send_burst;
-				budget->dvb_frontend->ops.set_tone = budget_set_tone;
-			}
-			break;
-		}
-		break;
-
-	case 0x1004: // Hauppauge/TT DVB-C budget (ves1820/ALPS TDBE2(sp5659))
-
-		budget->dvb_frontend = dvb_attach(ves1820_attach, &alps_tdbe2_config, &budget->i2c_adap, read_pwm(budget));
-		if (budget->dvb_frontend) {
-			budget->dvb_frontend->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params;
-			break;
-		}
-		break;
-
-	case 0x1005: // Hauppauge/TT Nova-T budget (L64781/Grundig 29504-401(tsa5060))
-
-		budget->dvb_frontend = dvb_attach(l64781_attach, &grundig_29504_401_config, &budget->i2c_adap);
-		if (budget->dvb_frontend) {
-			budget->dvb_frontend->ops.tuner_ops.set_params = grundig_29504_401_tuner_set_params;
-			budget->dvb_frontend->tuner_priv = NULL;
-			break;
-		}
-		break;
-
-	case 0x4f60: /* Fujitsu Siemens Activy Budget-S PCI rev AL (stv0299/tsa5059) */
-	{
-		int subtype = i2c_readreg(&budget->i2c_adap, 0x50, 0x67);
-
-		if (subtype < 0)
-			break;
-		/* fixme: find a better way to identify the card */
-		if (subtype < 0x36) {
-			/* assume ALPS BSRU6 */
-			budget->dvb_frontend = dvb_attach(stv0299_attach, &alps_bsru6_config_activy, &budget->i2c_adap);
-			if (budget->dvb_frontend) {
-				printk(KERN_INFO "budget: tuner ALPS BSRU6 detected\n");
-				budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
-				budget->dvb_frontend->tuner_priv = &budget->i2c_adap;
-				budget->dvb_frontend->ops.set_voltage = siemens_budget_set_voltage;
-				budget->dvb_frontend->ops.dishnetwork_send_legacy_command = NULL;
-				break;
-			}
-		} else {
-			/* assume ALPS BSBE1 */
-			/* reset tuner */
-			saa7146_setgpio(budget->dev, 3, SAA7146_GPIO_OUTLO);
-			msleep(50);
-			saa7146_setgpio(budget->dev, 3, SAA7146_GPIO_OUTHI);
-			msleep(250);
-			budget->dvb_frontend = dvb_attach(stv0299_attach, &alps_bsbe1_config_activy, &budget->i2c_adap);
-			if (budget->dvb_frontend) {
-				printk(KERN_INFO "budget: tuner ALPS BSBE1 detected\n");
-				budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsbe1_tuner_set_params;
-				budget->dvb_frontend->tuner_priv = &budget->i2c_adap;
-				budget->dvb_frontend->ops.set_voltage = siemens_budget_set_voltage;
-				budget->dvb_frontend->ops.dishnetwork_send_legacy_command = NULL;
-				break;
-			}
-		}
-		break;
-	}
-
-	case 0x4f61: // Fujitsu Siemens Activy Budget-S PCI rev GR (tda8083/Grundig 29504-451(tsa5522))
-		budget->dvb_frontend = dvb_attach(tda8083_attach, &grundig_29504_451_config, &budget->i2c_adap);
-		if (budget->dvb_frontend) {
-			budget->dvb_frontend->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params;
-			budget->dvb_frontend->ops.set_voltage = siemens_budget_set_voltage;
-			budget->dvb_frontend->ops.dishnetwork_send_legacy_command = NULL;
-		}
-		break;
-
-	case 0x5f60: /* Fujitsu Siemens Activy Budget-T PCI rev AL (tda10046/ALPS TDHD1-204A) */
-		budget->dvb_frontend = dvb_attach(tda10046_attach, &alps_tdhd1_204a_config, &budget->i2c_adap);
-		if (budget->dvb_frontend) {
-			budget->dvb_frontend->ops.tuner_ops.set_params = alps_tdhd1_204a_tuner_set_params;
-			budget->dvb_frontend->tuner_priv = &budget->i2c_adap;
-		}
-		break;
-
-	case 0x5f61: /* Fujitsu Siemens Activy Budget-T PCI rev GR (L64781/Grundig 29504-401(tsa5060)) */
-		budget->dvb_frontend = dvb_attach(l64781_attach, &grundig_29504_401_config_activy, &budget->i2c_adap);
-		if (budget->dvb_frontend) {
-			budget->dvb_frontend->tuner_priv = &tuner_address_grundig_29504_401_activy;
-			budget->dvb_frontend->ops.tuner_ops.set_params = grundig_29504_401_tuner_set_params;
-		}
-		break;
-
-	case 0x1016: // Hauppauge/TT Nova-S SE (samsung s5h1420/????(tda8260))
-		budget->dvb_frontend = dvb_attach(s5h1420_attach, &s5h1420_config, &budget->i2c_adap);
-		if (budget->dvb_frontend) {
-			budget->dvb_frontend->ops.tuner_ops.set_params = s5h1420_tuner_set_params;
-			if (dvb_attach(lnbp21_attach, budget->dvb_frontend, &budget->i2c_adap, 0, 0) == NULL) {
-				printk("%s: No LNBP21 found!\n", __func__);
-				goto error_out;
-			}
-			break;
-		}
-
-	case 0x1018: // TT Budget-S-1401 (philips tda10086/philips tda8262)
-		// gpio2 is connected to CLB - reset it + leave it high
-		saa7146_setgpio(budget->dev, 2, SAA7146_GPIO_OUTLO);
-		msleep(1);
-		saa7146_setgpio(budget->dev, 2, SAA7146_GPIO_OUTHI);
-		msleep(1);
-
-		budget->dvb_frontend = dvb_attach(tda10086_attach, &tda10086_config, &budget->i2c_adap);
-		if (budget->dvb_frontend) {
-			if (dvb_attach(tda826x_attach, budget->dvb_frontend, 0x60, &budget->i2c_adap, 0) == NULL)
-				printk("%s: No tda826x found!\n", __func__);
-			if (dvb_attach(lnbp21_attach, budget->dvb_frontend, &budget->i2c_adap, 0, 0) == NULL) {
-				printk("%s: No LNBP21 found!\n", __func__);
-				goto error_out;
-			}
-			break;
-		}
-
-	case 0x101c: { /* TT S2-1600 */
-			struct stv6110x_devctl *ctl;
-			saa7146_setgpio(budget->dev, 2, SAA7146_GPIO_OUTLO);
-			msleep(50);
-			saa7146_setgpio(budget->dev, 2, SAA7146_GPIO_OUTHI);
-			msleep(250);
-
-			budget->dvb_frontend = dvb_attach(stv090x_attach,
-							  &tt1600_stv090x_config,
-							  &budget->i2c_adap,
-							  STV090x_DEMODULATOR_0);
-
-			if (budget->dvb_frontend) {
-
-				ctl = dvb_attach(stv6110x_attach,
-						 budget->dvb_frontend,
-						 &tt1600_stv6110x_config,
-						 &budget->i2c_adap);
-
-				if (ctl) {
-					tt1600_stv090x_config.tuner_init	  = ctl->tuner_init;
-					tt1600_stv090x_config.tuner_sleep	  = ctl->tuner_sleep;
-					tt1600_stv090x_config.tuner_set_mode	  = ctl->tuner_set_mode;
-					tt1600_stv090x_config.tuner_set_frequency = ctl->tuner_set_frequency;
-					tt1600_stv090x_config.tuner_get_frequency = ctl->tuner_get_frequency;
-					tt1600_stv090x_config.tuner_set_bandwidth = ctl->tuner_set_bandwidth;
-					tt1600_stv090x_config.tuner_get_bandwidth = ctl->tuner_get_bandwidth;
-					tt1600_stv090x_config.tuner_set_bbgain	  = ctl->tuner_set_bbgain;
-					tt1600_stv090x_config.tuner_get_bbgain	  = ctl->tuner_get_bbgain;
-					tt1600_stv090x_config.tuner_set_refclk	  = ctl->tuner_set_refclk;
-					tt1600_stv090x_config.tuner_get_status	  = ctl->tuner_get_status;
-
-					/* call the init function once to initialize
-					   tuner's clock output divider and demod's
-					   master clock */
-					if (budget->dvb_frontend->ops.init)
-						budget->dvb_frontend->ops.init(budget->dvb_frontend);
-
-					if (dvb_attach(isl6423_attach,
-						       budget->dvb_frontend,
-						       &budget->i2c_adap,
-						       &tt1600_isl6423_config) == NULL) {
-						printk(KERN_ERR "%s: No Intersil ISL6423 found!\n", __func__);
-						goto error_out;
-					}
-				} else {
-					printk(KERN_ERR "%s: No STV6110(A) Silicon Tuner found!\n", __func__);
-					goto error_out;
-				}
-			}
-		}
-		break;
-	}
-
-	if (budget->dvb_frontend == NULL) {
-		printk("budget: A frontend driver was not found for device [%04x:%04x] subsystem [%04x:%04x]\n",
-		       budget->dev->pci->vendor,
-		       budget->dev->pci->device,
-		       budget->dev->pci->subsystem_vendor,
-		       budget->dev->pci->subsystem_device);
-	} else {
-		if (dvb_register_frontend(&budget->dvb_adapter, budget->dvb_frontend))
-			goto error_out;
-	}
-	return;
-
-error_out:
-	printk("budget: Frontend registration failed!\n");
-	dvb_frontend_detach(budget->dvb_frontend);
-	budget->dvb_frontend = NULL;
-	return;
-}
-
-static int budget_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_data *info)
-{
-	struct budget *budget = NULL;
-	int err;
-
-	budget = kmalloc(sizeof(struct budget), GFP_KERNEL);
-	if( NULL == budget ) {
-		return -ENOMEM;
-	}
-
-	dprintk(2, "dev:%p, info:%p, budget:%p\n", dev, info, budget);
-
-	dev->ext_priv = budget;
-
-	err = ttpci_budget_init(budget, dev, info, THIS_MODULE, adapter_nr);
-	if (err) {
-		printk("==> failed\n");
-		kfree (budget);
-		return err;
-	}
-
-	budget->dvb_adapter.priv = budget;
-	frontend_init(budget);
-
-	ttpci_budget_init_hooks(budget);
-
-	return 0;
-}
-
-static int budget_detach (struct saa7146_dev* dev)
-{
-	struct budget *budget = (struct budget*) dev->ext_priv;
-	int err;
-
-	if (budget->dvb_frontend) {
-		dvb_unregister_frontend(budget->dvb_frontend);
-		dvb_frontend_detach(budget->dvb_frontend);
-	}
-
-	err = ttpci_budget_deinit (budget);
-
-	kfree (budget);
-	dev->ext_priv = NULL;
-
-	return err;
-}
-
-static struct saa7146_extension budget_extension;
-
-MAKE_BUDGET_INFO(ttbs,	"TT-Budget/WinTV-NOVA-S  PCI",	BUDGET_TT);
-MAKE_BUDGET_INFO(ttbc,	"TT-Budget/WinTV-NOVA-C  PCI",	BUDGET_TT);
-MAKE_BUDGET_INFO(ttbt,	"TT-Budget/WinTV-NOVA-T  PCI",	BUDGET_TT);
-MAKE_BUDGET_INFO(satel,	"SATELCO Multimedia PCI",	BUDGET_TT_HW_DISEQC);
-MAKE_BUDGET_INFO(ttbs1401, "TT-Budget-S-1401 PCI", BUDGET_TT);
-MAKE_BUDGET_INFO(tt1600, "TT-Budget S2-1600 PCI", BUDGET_TT);
-MAKE_BUDGET_INFO(fsacs0, "Fujitsu Siemens Activy Budget-S PCI (rev GR/grundig frontend)", BUDGET_FS_ACTIVY);
-MAKE_BUDGET_INFO(fsacs1, "Fujitsu Siemens Activy Budget-S PCI (rev AL/alps frontend)", BUDGET_FS_ACTIVY);
-MAKE_BUDGET_INFO(fsact,	 "Fujitsu Siemens Activy Budget-T PCI (rev GR/Grundig frontend)", BUDGET_FS_ACTIVY);
-MAKE_BUDGET_INFO(fsact1, "Fujitsu Siemens Activy Budget-T PCI (rev AL/ALPS TDHD1-204A)", BUDGET_FS_ACTIVY);
-
-static struct pci_device_id pci_tbl[] = {
-	MAKE_EXTENSION_PCI(ttbs,  0x13c2, 0x1003),
-	MAKE_EXTENSION_PCI(ttbc,  0x13c2, 0x1004),
-	MAKE_EXTENSION_PCI(ttbt,  0x13c2, 0x1005),
-	MAKE_EXTENSION_PCI(satel, 0x13c2, 0x1013),
-	MAKE_EXTENSION_PCI(ttbs,  0x13c2, 0x1016),
-	MAKE_EXTENSION_PCI(ttbs1401, 0x13c2, 0x1018),
-	MAKE_EXTENSION_PCI(tt1600, 0x13c2, 0x101c),
-	MAKE_EXTENSION_PCI(fsacs1,0x1131, 0x4f60),
-	MAKE_EXTENSION_PCI(fsacs0,0x1131, 0x4f61),
-	MAKE_EXTENSION_PCI(fsact1, 0x1131, 0x5f60),
-	MAKE_EXTENSION_PCI(fsact, 0x1131, 0x5f61),
-	{
-		.vendor    = 0,
-	}
-};
-
-MODULE_DEVICE_TABLE(pci, pci_tbl);
-
-static struct saa7146_extension budget_extension = {
-	.name		= "budget dvb",
-	.flags		= SAA7146_USE_I2C_IRQ,
-
-	.module		= THIS_MODULE,
-	.pci_tbl	= pci_tbl,
-	.attach		= budget_attach,
-	.detach		= budget_detach,
-
-	.irq_mask	= MASK_10,
-	.irq_func	= ttpci_budget_irq10_handler,
-};
-
-static int __init budget_init(void)
-{
-	return saa7146_register_extension(&budget_extension);
-}
-
-static void __exit budget_exit(void)
-{
-	saa7146_unregister_extension(&budget_extension);
-}
-
-module_init(budget_init);
-module_exit(budget_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, Michael Hunold, others");
-MODULE_DESCRIPTION("driver for the SAA7146 based so-called "
-		   "budget PCI DVB cards by Siemens, Technotrend, Hauppauge");
diff --git a/drivers/media/dvb/ttpci/budget.h b/drivers/media/dvb/ttpci/budget.h
deleted file mode 100644
index 3d8a806..0000000
--- a/drivers/media/dvb/ttpci/budget.h
+++ /dev/null
@@ -1,124 +0,0 @@
-
-#ifndef __BUDGET_DVB__
-#define __BUDGET_DVB__
-
-#include "dvb_frontend.h"
-#include "dvbdev.h"
-#include "demux.h"
-#include "dvb_demux.h"
-#include "dmxdev.h"
-#include "dvb_filter.h"
-#include "dvb_net.h"
-
-#include <linux/module.h>
-#include <linux/mutex.h>
-
-#include <media/saa7146.h>
-
-extern int budget_debug;
-
-#ifdef dprintk
-#undef dprintk
-#endif
-
-#define dprintk(level,args...) \
-	    do { if ((budget_debug & level)) { printk("%s: %s(): ", KBUILD_MODNAME, __func__); printk(args); } } while (0)
-
-struct budget_info {
-	char *name;
-	int type;
-};
-
-/* place to store all the necessary device information */
-struct budget {
-
-	/* devices */
-	struct dvb_device dvb_dev;
-	struct dvb_net dvb_net;
-
-	struct saa7146_dev *dev;
-
-	struct i2c_adapter i2c_adap;
-	struct budget_info *card;
-
-	unsigned char *grabbing;
-	struct saa7146_pgtable pt;
-
-	struct tasklet_struct fidb_tasklet;
-	struct tasklet_struct vpe_tasklet;
-
-	struct dmxdev dmxdev;
-	struct dvb_demux demux;
-
-	struct dmx_frontend hw_frontend;
-	struct dmx_frontend mem_frontend;
-
-	int ci_present;
-	int video_port;
-
-	u32 buffer_width;
-	u32 buffer_height;
-	u32 buffer_size;
-	u32 buffer_warning_threshold;
-	u32 buffer_warnings;
-	unsigned long buffer_warning_time;
-
-	u32 ttbp;
-	int feeding;
-
-	spinlock_t feedlock;
-
-	spinlock_t debilock;
-
-	struct dvb_adapter dvb_adapter;
-	struct dvb_frontend *dvb_frontend;
-	int (*read_fe_status)(struct dvb_frontend *fe, fe_status_t *status);
-	int fe_synced;
-
-	void *priv;
-};
-
-#define MAKE_BUDGET_INFO(x_var,x_name,x_type) \
-static struct budget_info x_var ## _info = { \
-	.name=x_name,	\
-	.type=x_type };	\
-static struct saa7146_pci_extension_data x_var = { \
-	.ext_priv = &x_var ## _info, \
-	.ext = &budget_extension };
-
-#define BUDGET_TT		   0
-#define BUDGET_TT_HW_DISEQC	   1
-#define BUDGET_PATCH		   3
-#define BUDGET_FS_ACTIVY	   4
-#define BUDGET_CIN1200S		   5
-#define BUDGET_CIN1200C		   6
-#define BUDGET_CIN1200T		   7
-#define BUDGET_KNC1S		   8
-#define BUDGET_KNC1C		   9
-#define BUDGET_KNC1T		   10
-#define BUDGET_KNC1SP		   11
-#define BUDGET_KNC1CP		   12
-#define BUDGET_KNC1TP		   13
-#define BUDGET_TVSTAR		   14
-#define BUDGET_CIN1200C_MK3	   15
-#define BUDGET_KNC1C_MK3	   16
-#define BUDGET_KNC1CP_MK3	   17
-#define BUDGET_KNC1S2              18
-#define BUDGET_KNC1C_TDA10024	   19
-
-#define BUDGET_VIDEO_PORTA         0
-#define BUDGET_VIDEO_PORTB         1
-
-extern int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev,
-			     struct saa7146_pci_extension_data *info,
-			     struct module *owner, short *adapter_nums);
-extern void ttpci_budget_init_hooks(struct budget *budget);
-extern int ttpci_budget_deinit(struct budget *budget);
-extern void ttpci_budget_irq10_handler(struct saa7146_dev *dev, u32 * isr);
-extern void ttpci_budget_set_video_port(struct saa7146_dev *dev, int video_port);
-extern int ttpci_budget_debiread(struct budget *budget, u32 config, int addr, int count,
-				 int uselocks, int nobusyloop);
-extern int ttpci_budget_debiwrite(struct budget *budget, u32 config, int addr, int count, u32 value,
-				  int uselocks, int nobusyloop);
-
-#endif
diff --git a/drivers/media/dvb/ttpci/ttpci-eeprom.c b/drivers/media/dvb/ttpci/ttpci-eeprom.c
deleted file mode 100644
index 32d4315..0000000
--- a/drivers/media/dvb/ttpci/ttpci-eeprom.c
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
-    Retrieve encoded MAC address from 24C16 serial 2-wire EEPROM,
-    decode it and store it in the associated adapter struct for
-    use by dvb_net.c
-
-    This card appear to have the 24C16 write protect held to ground,
-    thus permitting normal read/write operation. Theoretically it
-    would be possible to write routines to burn a different (encoded)
-    MAC address into the EEPROM.
-
-    Robert Schlabbach	GMX
-    Michael Glaum	KVH Industries
-    Holger Waechtler	Convergence
-
-    Copyright (C) 2002-2003 Ralph Metzler <rjkm@metzlerbros.de>
-			    Metzler Brothers Systementwicklung GbR
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the 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 <asm/errno.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/i2c.h>
-
-#include "ttpci-eeprom.h"
-
-#if 1
-#define dprintk(x...) do { printk(x); } while (0)
-#else
-#define dprintk(x...) do { } while (0)
-#endif
-
-
-static int check_mac_tt(u8 *buf)
-{
-	int i;
-	u16 tmp = 0xffff;
-
-	for (i = 0; i < 8; i++) {
-		tmp  = (tmp << 8) | ((tmp >> 8) ^ buf[i]);
-		tmp ^= (tmp >> 4) & 0x0f;
-		tmp ^= (tmp << 12) ^ ((tmp & 0xff) << 5);
-	}
-	tmp ^= 0xffff;
-	return (((tmp >> 8) ^ buf[8]) | ((tmp & 0xff) ^ buf[9]));
-}
-
-static int getmac_tt(u8 * decodedMAC, u8 * encodedMAC)
-{
-	u8 xor[20] = { 0x72, 0x23, 0x68, 0x19, 0x5c, 0xa8, 0x71, 0x2c,
-		       0x54, 0xd3, 0x7b, 0xf1, 0x9E, 0x23, 0x16, 0xf6,
-		       0x1d, 0x36, 0x64, 0x78};
-	u8 data[20];
-	int i;
-
-	/* In case there is a sig check failure have the orig contents available */
-	memcpy(data, encodedMAC, 20);
-
-	for (i = 0; i < 20; i++)
-		data[i] ^= xor[i];
-	for (i = 0; i < 10; i++)
-		data[i] = ((data[2 * i + 1] << 8) | data[2 * i])
-			>> ((data[2 * i + 1] >> 6) & 3);
-
-	if (check_mac_tt(data))
-		return -ENODEV;
-
-	decodedMAC[0] = data[2]; decodedMAC[1] = data[1]; decodedMAC[2] = data[0];
-	decodedMAC[3] = data[6]; decodedMAC[4] = data[5]; decodedMAC[5] = data[4];
-	return 0;
-}
-
-int ttpci_eeprom_decode_mac(u8 *decodedMAC, u8 *encodedMAC)
-{
-	u8 xor[20] = { 0x72, 0x23, 0x68, 0x19, 0x5c, 0xa8, 0x71, 0x2c,
-		       0x54, 0xd3, 0x7b, 0xf1, 0x9E, 0x23, 0x16, 0xf6,
-		       0x1d, 0x36, 0x64, 0x78};
-	u8 data[20];
-	int i;
-
-	memcpy(data, encodedMAC, 20);
-
-	for (i = 0; i < 20; i++)
-		data[i] ^= xor[i];
-	for (i = 0; i < 10; i++)
-		data[i] = ((data[2 * i + 1] << 8) | data[2 * i])
-			>> ((data[2 * i + 1] >> 6) & 3);
-
-	if (check_mac_tt(data))
-		return -ENODEV;
-
-	decodedMAC[0] = data[2];
-	decodedMAC[1] = data[1];
-	decodedMAC[2] = data[0];
-	decodedMAC[3] = data[6];
-	decodedMAC[4] = data[5];
-	decodedMAC[5] = data[4];
-	return 0;
-}
-EXPORT_SYMBOL(ttpci_eeprom_decode_mac);
-
-static int ttpci_eeprom_read_encodedMAC(struct i2c_adapter *adapter, u8 * encodedMAC)
-{
-	int ret;
-	u8 b0[] = { 0xcc };
-
-	struct i2c_msg msg[] = {
-		{ .addr = 0x50, .flags = 0, .buf = b0, .len = 1 },
-		{ .addr = 0x50, .flags = I2C_M_RD, .buf = encodedMAC, .len = 20 }
-	};
-
-	/* dprintk("%s\n", __func__); */
-
-	ret = i2c_transfer(adapter, msg, 2);
-
-	if (ret != 2)		/* Assume EEPROM isn't there */
-		return (-ENODEV);
-
-	return 0;
-}
-
-
-int ttpci_eeprom_parse_mac(struct i2c_adapter *adapter, u8 *proposed_mac)
-{
-	int ret, i;
-	u8 encodedMAC[20];
-	u8 decodedMAC[6];
-
-	ret = ttpci_eeprom_read_encodedMAC(adapter, encodedMAC);
-
-	if (ret != 0) {		/* Will only be -ENODEV */
-		dprintk("Couldn't read from EEPROM: not there?\n");
-		memset(proposed_mac, 0, 6);
-		return ret;
-	}
-
-	ret = getmac_tt(decodedMAC, encodedMAC);
-	if( ret != 0 ) {
-		dprintk("adapter failed MAC signature check\n");
-		dprintk("encoded MAC from EEPROM was " );
-		for(i=0; i<19; i++) {
-			dprintk( "%.2x:", encodedMAC[i]);
-		}
-		dprintk("%.2x\n", encodedMAC[19]);
-		memset(proposed_mac, 0, 6);
-		return ret;
-	}
-
-	memcpy(proposed_mac, decodedMAC, 6);
-	dprintk("adapter has MAC addr = %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
-		decodedMAC[0], decodedMAC[1], decodedMAC[2],
-		decodedMAC[3], decodedMAC[4], decodedMAC[5]);
-	return 0;
-}
-
-EXPORT_SYMBOL(ttpci_eeprom_parse_mac);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, others");
-MODULE_DESCRIPTION("Decode dvb_net MAC address from EEPROM of PCI DVB cards "
-		"made by Siemens, Technotrend, Hauppauge");
diff --git a/drivers/media/dvb/ttpci/ttpci-eeprom.h b/drivers/media/dvb/ttpci/ttpci-eeprom.h
deleted file mode 100644
index dcc33d5..0000000
--- a/drivers/media/dvb/ttpci/ttpci-eeprom.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
-    Retrieve encoded MAC address from ATMEL ttpci_eeprom serial 2-wire EEPROM,
-    decode it and store it in associated adapter net device
-
-    Robert Schlabbach	GMX
-    Michael Glaum	KVH Industries
-    Holger Waechtler	Convergence
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the 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 __TTPCI_EEPROM_H__
-#define __TTPCI_EEPROM_H__
-
-#include <linux/types.h>
-#include <linux/i2c.h>
-
-extern int ttpci_eeprom_decode_mac(u8 *decodedMAC, u8 *encodedMAC);
-extern int ttpci_eeprom_parse_mac(struct i2c_adapter *adapter, u8 *propsed_mac);
-
-#endif
diff --git a/drivers/media/dvb/ttusb-budget/Kconfig b/drivers/media/dvb/ttusb-budget/Kconfig
deleted file mode 100644
index 2663ae3..0000000
--- a/drivers/media/dvb/ttusb-budget/Kconfig
+++ /dev/null
@@ -1,18 +0,0 @@
-config DVB_TTUSB_BUDGET
-	tristate "Technotrend/Hauppauge Nova-USB devices"
-	depends on DVB_CORE && USB && I2C && PCI
-	select DVB_CX22700 if !DVB_FE_CUSTOMISE
-	select DVB_TDA1004X if !DVB_FE_CUSTOMISE
-	select DVB_VES1820 if !DVB_FE_CUSTOMISE
-	select DVB_TDA8083 if !DVB_FE_CUSTOMISE
-	select DVB_STV0299 if !DVB_FE_CUSTOMISE
-	select DVB_STV0297 if !DVB_FE_CUSTOMISE
-	select DVB_LNBP21 if !DVB_FE_CUSTOMISE
-	help
-	  Support for external USB adapters designed by Technotrend and
-	  produced by Hauppauge, shipped under the brand name 'Nova-USB'.
-
-	  These devices don't have a MPEG decoder built in, so you need
-	  an external software decoder to watch TV.
-
-	  Say Y if you own such a device and want to use it.
diff --git a/drivers/media/dvb/ttusb-budget/Makefile b/drivers/media/dvb/ttusb-budget/Makefile
deleted file mode 100644
index 8d6c4ac..0000000
--- a/drivers/media/dvb/ttusb-budget/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-obj-$(CONFIG_DVB_TTUSB_BUDGET) += dvb-ttusb-budget.o
-
-ccflags-y += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends
diff --git a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
deleted file mode 100644
index 5b682cc..0000000
--- a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
+++ /dev/null
@@ -1,1816 +0,0 @@
-/*
- * TTUSB DVB driver
- *
- * Copyright (c) 2002 Holger Waechtler <holger@convergence.de>
- * Copyright (c) 2003 Felix Domke <tmbinc@elitedvb.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.
- */
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/wait.h>
-#include <linux/fs.h>
-#include <linux/module.h>
-#include <linux/usb.h>
-#include <linux/delay.h>
-#include <linux/time.h>
-#include <linux/errno.h>
-#include <linux/jiffies.h>
-#include <linux/mutex.h>
-#include <linux/firmware.h>
-
-#include "dvb_frontend.h"
-#include "dmxdev.h"
-#include "dvb_demux.h"
-#include "dvb_net.h"
-#include "ves1820.h"
-#include "cx22700.h"
-#include "tda1004x.h"
-#include "stv0299.h"
-#include "tda8083.h"
-#include "stv0297.h"
-#include "lnbp21.h"
-
-#include <linux/dvb/frontend.h>
-#include <linux/dvb/dmx.h>
-#include <linux/pci.h>
-
-/*
-  TTUSB_HWSECTIONS:
-    the DSP supports filtering in hardware, however, since the "muxstream"
-    is a bit braindead (no matching channel masks or no matching filter mask),
-    we won't support this - yet. it doesn't event support negative filters,
-    so the best way is maybe to keep TTUSB_HWSECTIONS undef'd and just
-    parse TS data. USB bandwidth will be a problem when having large
-    datastreams, especially for dvb-net, but hey, that's not my problem.
-
-  TTUSB_DISEQC, TTUSB_TONE:
-    let the STC do the diseqc/tone stuff. this isn't supported at least with
-    my TTUSB, so let it undef'd unless you want to implement another
-    frontend. never tested.
-
-  debug:
-    define it to > 3 for really hardcore debugging. you probably don't want
-    this unless the device doesn't load at all. > 2 for bandwidth statistics.
-*/
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-#define dprintk(x...) do { if (debug) printk(KERN_DEBUG x); } while (0)
-
-#define ISO_BUF_COUNT      4
-#define FRAMES_PER_ISO_BUF 4
-#define ISO_FRAME_SIZE     912
-#define TTUSB_MAXCHANNEL   32
-#ifdef TTUSB_HWSECTIONS
-#define TTUSB_MAXFILTER    16	/* ??? */
-#endif
-
-#define TTUSB_REV_2_2	0x22
-#define TTUSB_BUDGET_NAME "ttusb_stc_fw"
-
-/**
- *  since we're casting (struct ttusb*) <-> (struct dvb_demux*) around
- *  the dvb_demux field must be the first in struct!!
- */
-struct ttusb {
-	struct dvb_demux dvb_demux;
-	struct dmxdev dmxdev;
-	struct dvb_net dvbnet;
-
-	/* and one for USB access. */
-	struct mutex semi2c;
-	struct mutex semusb;
-
-	struct dvb_adapter adapter;
-	struct usb_device *dev;
-
-	struct i2c_adapter i2c_adap;
-
-	int disconnecting;
-	int iso_streaming;
-
-	unsigned int bulk_out_pipe;
-	unsigned int bulk_in_pipe;
-	unsigned int isoc_in_pipe;
-
-	void *iso_buffer;
-	dma_addr_t iso_dma_handle;
-
-	struct urb *iso_urb[ISO_BUF_COUNT];
-
-	int running_feed_count;
-	int last_channel;
-	int last_filter;
-
-	u8 c;			/* transaction counter, wraps around...  */
-	fe_sec_tone_mode_t tone;
-	fe_sec_voltage_t voltage;
-
-	int mux_state;		// 0..2 - MuxSyncWord, 3 - nMuxPacks,    4 - muxpack
-	u8 mux_npacks;
-	u8 muxpack[256 + 8];
-	int muxpack_ptr, muxpack_len;
-
-	int insync;
-
-	int cc;			/* MuxCounter - will increment on EVERY MUX PACKET */
-	/* (including stuffing. yes. really.) */
-
-	u8 last_result[32];
-
-	int revision;
-
-	struct dvb_frontend* fe;
-};
-
-/* ugly workaround ... don't know why it's necessary to read */
-/* all result codes. */
-
-static int ttusb_cmd(struct ttusb *ttusb,
-	      const u8 * data, int len, int needresult)
-{
-	int actual_len;
-	int err;
-	int i;
-
-	if (debug >= 3) {
-		printk(KERN_DEBUG ">");
-		for (i = 0; i < len; ++i)
-			printk(KERN_CONT " %02x", data[i]);
-		printk(KERN_CONT "\n");
-	}
-
-	if (mutex_lock_interruptible(&ttusb->semusb) < 0)
-		return -EAGAIN;
-
-	err = usb_bulk_msg(ttusb->dev, ttusb->bulk_out_pipe,
-			   (u8 *) data, len, &actual_len, 1000);
-	if (err != 0) {
-		dprintk("%s: usb_bulk_msg(send) failed, err == %i!\n",
-			__func__, err);
-		mutex_unlock(&ttusb->semusb);
-		return err;
-	}
-	if (actual_len != len) {
-		dprintk("%s: only wrote %d of %d bytes\n", __func__,
-			actual_len, len);
-		mutex_unlock(&ttusb->semusb);
-		return -1;
-	}
-
-	err = usb_bulk_msg(ttusb->dev, ttusb->bulk_in_pipe,
-			   ttusb->last_result, 32, &actual_len, 1000);
-
-	if (err != 0) {
-		printk("%s: failed, receive error %d\n", __func__,
-		       err);
-		mutex_unlock(&ttusb->semusb);
-		return err;
-	}
-
-	if (debug >= 3) {
-		actual_len = ttusb->last_result[3] + 4;
-		printk(KERN_DEBUG "<");
-		for (i = 0; i < actual_len; ++i)
-			printk(KERN_CONT " %02x", ttusb->last_result[i]);
-		printk(KERN_CONT "\n");
-	}
-
-	if (!needresult)
-		mutex_unlock(&ttusb->semusb);
-	return 0;
-}
-
-static int ttusb_result(struct ttusb *ttusb, u8 * data, int len)
-{
-	memcpy(data, ttusb->last_result, len);
-	mutex_unlock(&ttusb->semusb);
-	return 0;
-}
-
-static int ttusb_i2c_msg(struct ttusb *ttusb,
-		  u8 addr, u8 * snd_buf, u8 snd_len, u8 * rcv_buf,
-		  u8 rcv_len)
-{
-	u8 b[0x28];
-	u8 id = ++ttusb->c;
-	int i, err;
-
-	if (snd_len > 0x28 - 7 || rcv_len > 0x20 - 7)
-		return -EINVAL;
-
-	b[0] = 0xaa;
-	b[1] = id;
-	b[2] = 0x31;
-	b[3] = snd_len + 3;
-	b[4] = addr << 1;
-	b[5] = snd_len;
-	b[6] = rcv_len;
-
-	for (i = 0; i < snd_len; i++)
-		b[7 + i] = snd_buf[i];
-
-	err = ttusb_cmd(ttusb, b, snd_len + 7, 1);
-
-	if (err)
-		return -EREMOTEIO;
-
-	err = ttusb_result(ttusb, b, 0x20);
-
-	/* check if the i2c transaction was successful */
-	if ((snd_len != b[5]) || (rcv_len != b[6])) return -EREMOTEIO;
-
-	if (rcv_len > 0) {
-
-		if (err || b[0] != 0x55 || b[1] != id) {
-			dprintk
-			    ("%s: usb_bulk_msg(recv) failed, err == %i, id == %02x, b == ",
-			     __func__, err, id);
-			return -EREMOTEIO;
-		}
-
-		for (i = 0; i < rcv_len; i++)
-			rcv_buf[i] = b[7 + i];
-	}
-
-	return rcv_len;
-}
-
-static int master_xfer(struct i2c_adapter* adapter, struct i2c_msg *msg, int num)
-{
-	struct ttusb *ttusb = i2c_get_adapdata(adapter);
-	int i = 0;
-	int inc;
-
-	if (mutex_lock_interruptible(&ttusb->semi2c) < 0)
-		return -EAGAIN;
-
-	while (i < num) {
-		u8 addr, snd_len, rcv_len, *snd_buf, *rcv_buf;
-		int err;
-
-		if (num > i + 1 && (msg[i + 1].flags & I2C_M_RD)) {
-			addr = msg[i].addr;
-			snd_buf = msg[i].buf;
-			snd_len = msg[i].len;
-			rcv_buf = msg[i + 1].buf;
-			rcv_len = msg[i + 1].len;
-			inc = 2;
-		} else {
-			addr = msg[i].addr;
-			snd_buf = msg[i].buf;
-			snd_len = msg[i].len;
-			rcv_buf = NULL;
-			rcv_len = 0;
-			inc = 1;
-		}
-
-		err = ttusb_i2c_msg(ttusb, addr,
-				    snd_buf, snd_len, rcv_buf, rcv_len);
-
-		if (err < rcv_len) {
-			dprintk("%s: i == %i\n", __func__, i);
-			break;
-		}
-
-		i += inc;
-	}
-
-	mutex_unlock(&ttusb->semi2c);
-	return i;
-}
-
-static int ttusb_boot_dsp(struct ttusb *ttusb)
-{
-	const struct firmware *fw;
-	int i, err;
-	u8 b[40];
-
-	err = request_firmware(&fw, "ttusb-budget/dspbootcode.bin",
-			       &ttusb->dev->dev);
-	if (err) {
-		printk(KERN_ERR "ttusb-budget: failed to request firmware\n");
-		return err;
-	}
-
-	/* BootBlock */
-	b[0] = 0xaa;
-	b[2] = 0x13;
-	b[3] = 28;
-
-	/* upload dsp code in 32 byte steps (36 didn't work for me ...) */
-	/* 32 is max packet size, no messages should be splitted. */
-	for (i = 0; i < fw->size; i += 28) {
-		memcpy(&b[4], &fw->data[i], 28);
-
-		b[1] = ++ttusb->c;
-
-		err = ttusb_cmd(ttusb, b, 32, 0);
-		if (err)
-			goto done;
-	}
-
-	/* last block ... */
-	b[1] = ++ttusb->c;
-	b[2] = 0x13;
-	b[3] = 0;
-
-	err = ttusb_cmd(ttusb, b, 4, 0);
-	if (err)
-		goto done;
-
-	/* BootEnd */
-	b[1] = ++ttusb->c;
-	b[2] = 0x14;
-	b[3] = 0;
-
-	err = ttusb_cmd(ttusb, b, 4, 0);
-
-      done:
-	release_firmware(fw);
-	if (err) {
-		dprintk("%s: usb_bulk_msg() failed, return value %i!\n",
-			__func__, err);
-	}
-
-	return err;
-}
-
-static int ttusb_set_channel(struct ttusb *ttusb, int chan_id, int filter_type,
-		      int pid)
-{
-	int err;
-	/* SetChannel */
-	u8 b[] = { 0xaa, ++ttusb->c, 0x22, 4, chan_id, filter_type,
-		(pid >> 8) & 0xff, pid & 0xff
-	};
-
-	err = ttusb_cmd(ttusb, b, sizeof(b), 0);
-	return err;
-}
-
-static int ttusb_del_channel(struct ttusb *ttusb, int channel_id)
-{
-	int err;
-	/* DelChannel */
-	u8 b[] = { 0xaa, ++ttusb->c, 0x23, 1, channel_id };
-
-	err = ttusb_cmd(ttusb, b, sizeof(b), 0);
-	return err;
-}
-
-#ifdef TTUSB_HWSECTIONS
-static int ttusb_set_filter(struct ttusb *ttusb, int filter_id,
-		     int associated_chan, u8 filter[8], u8 mask[8])
-{
-	int err;
-	/* SetFilter */
-	u8 b[] = { 0xaa, 0, 0x24, 0x1a, filter_id, associated_chan,
-		filter[0], filter[1], filter[2], filter[3],
-		filter[4], filter[5], filter[6], filter[7],
-		filter[8], filter[9], filter[10], filter[11],
-		mask[0], mask[1], mask[2], mask[3],
-		mask[4], mask[5], mask[6], mask[7],
-		mask[8], mask[9], mask[10], mask[11]
-	};
-
-	err = ttusb_cmd(ttusb, b, sizeof(b), 0);
-	return err;
-}
-
-static int ttusb_del_filter(struct ttusb *ttusb, int filter_id)
-{
-	int err;
-	/* DelFilter */
-	u8 b[] = { 0xaa, ++ttusb->c, 0x25, 1, filter_id };
-
-	err = ttusb_cmd(ttusb, b, sizeof(b), 0);
-	return err;
-}
-#endif
-
-static int ttusb_init_controller(struct ttusb *ttusb)
-{
-	u8 b0[] = { 0xaa, ++ttusb->c, 0x15, 1, 0 };
-	u8 b1[] = { 0xaa, ++ttusb->c, 0x15, 1, 1 };
-	u8 b2[] = { 0xaa, ++ttusb->c, 0x32, 1, 0 };
-	/* i2c write read: 5 bytes, addr 0x10, 0x02 bytes write, 1 bytes read. */
-	u8 b3[] =
-	    { 0xaa, ++ttusb->c, 0x31, 5, 0x10, 0x02, 0x01, 0x00, 0x1e };
-	u8 b4[] =
-	    { 0x55, ttusb->c, 0x31, 4, 0x10, 0x02, 0x01, 0x00, 0x1e };
-
-	u8 get_version[] = { 0xaa, ++ttusb->c, 0x17, 5, 0, 0, 0, 0, 0 };
-	u8 get_dsp_version[0x20] =
-	    { 0xaa, ++ttusb->c, 0x26, 28, 0, 0, 0, 0, 0 };
-	int err;
-
-	/* reset board */
-	if ((err = ttusb_cmd(ttusb, b0, sizeof(b0), 0)))
-		return err;
-
-	/* reset board (again?) */
-	if ((err = ttusb_cmd(ttusb, b1, sizeof(b1), 0)))
-		return err;
-
-	ttusb_boot_dsp(ttusb);
-
-	/* set i2c bit rate */
-	if ((err = ttusb_cmd(ttusb, b2, sizeof(b2), 0)))
-		return err;
-
-	if ((err = ttusb_cmd(ttusb, b3, sizeof(b3), 1)))
-		return err;
-
-	err = ttusb_result(ttusb, b4, sizeof(b4));
-
-	if ((err = ttusb_cmd(ttusb, get_version, sizeof(get_version), 1)))
-		return err;
-
-	if ((err = ttusb_result(ttusb, get_version, sizeof(get_version))))
-		return err;
-
-	dprintk("%s: stc-version: %c%c%c%c%c\n", __func__,
-		get_version[4], get_version[5], get_version[6],
-		get_version[7], get_version[8]);
-
-	if (memcmp(get_version + 4, "V 0.0", 5) &&
-	    memcmp(get_version + 4, "V 1.1", 5) &&
-	    memcmp(get_version + 4, "V 2.1", 5) &&
-	    memcmp(get_version + 4, "V 2.2", 5)) {
-		printk
-		    ("%s: unknown STC version %c%c%c%c%c, please report!\n",
-		     __func__, get_version[4], get_version[5],
-		     get_version[6], get_version[7], get_version[8]);
-	}
-
-	ttusb->revision = ((get_version[6] - '0') << 4) |
-			   (get_version[8] - '0');
-
-	err =
-	    ttusb_cmd(ttusb, get_dsp_version, sizeof(get_dsp_version), 1);
-	if (err)
-		return err;
-
-	err =
-	    ttusb_result(ttusb, get_dsp_version, sizeof(get_dsp_version));
-	if (err)
-		return err;
-	printk("%s: dsp-version: %c%c%c\n", __func__,
-	       get_dsp_version[4], get_dsp_version[5], get_dsp_version[6]);
-	return 0;
-}
-
-#ifdef TTUSB_DISEQC
-static int ttusb_send_diseqc(struct dvb_frontend* fe,
-			     const struct dvb_diseqc_master_cmd *cmd)
-{
-	struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv;
-	u8 b[12] = { 0xaa, ++ttusb->c, 0x18 };
-
-	int err;
-
-	b[3] = 4 + 2 + cmd->msg_len;
-	b[4] = 0xFF;		/* send diseqc master, not burst */
-	b[5] = cmd->msg_len;
-
-	memcpy(b + 5, cmd->msg, cmd->msg_len);
-
-	/* Diseqc */
-	if ((err = ttusb_cmd(ttusb, b, 4 + b[3], 0))) {
-		dprintk("%s: usb_bulk_msg() failed, return value %i!\n",
-			__func__, err);
-	}
-
-	return err;
-}
-#endif
-
-static int ttusb_update_lnb(struct ttusb *ttusb)
-{
-	u8 b[] = { 0xaa, ++ttusb->c, 0x16, 5, /*power: */ 1,
-		ttusb->voltage == SEC_VOLTAGE_18 ? 0 : 1,
-		ttusb->tone == SEC_TONE_ON ? 1 : 0, 1, 1
-	};
-	int err;
-
-	/* SetLNB */
-	if ((err = ttusb_cmd(ttusb, b, sizeof(b), 0))) {
-		dprintk("%s: usb_bulk_msg() failed, return value %i!\n",
-			__func__, err);
-	}
-
-	return err;
-}
-
-static int ttusb_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
-{
-	struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv;
-
-	ttusb->voltage = voltage;
-	return ttusb_update_lnb(ttusb);
-}
-
-#ifdef TTUSB_TONE
-static int ttusb_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
-{
-	struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv;
-
-	ttusb->tone = tone;
-	return ttusb_update_lnb(ttusb);
-}
-#endif
-
-
-#if 0
-static void ttusb_set_led_freq(struct ttusb *ttusb, u8 freq)
-{
-	u8 b[] = { 0xaa, ++ttusb->c, 0x19, 1, freq };
-	int err, actual_len;
-
-	err = ttusb_cmd(ttusb, b, sizeof(b), 0);
-	if (err) {
-		dprintk("%s: usb_bulk_msg() failed, return value %i!\n",
-			__func__, err);
-	}
-}
-#endif
-
-/*****************************************************************************/
-
-#ifdef TTUSB_HWSECTIONS
-static void ttusb_handle_ts_data(struct ttusb_channel *channel,
-				 const u8 * data, int len);
-static void ttusb_handle_sec_data(struct ttusb_channel *channel,
-				  const u8 * data, int len);
-#endif
-
-static int numpkt, numts, numstuff, numsec, numinvalid;
-static unsigned long lastj;
-
-static void ttusb_process_muxpack(struct ttusb *ttusb, const u8 * muxpack,
-			   int len)
-{
-	u16 csum = 0, cc;
-	int i;
-	for (i = 0; i < len; i += 2)
-		csum ^= le16_to_cpup((__le16 *) (muxpack + i));
-	if (csum) {
-		printk("%s: muxpack with incorrect checksum, ignoring\n",
-		       __func__);
-		numinvalid++;
-		return;
-	}
-
-	cc = (muxpack[len - 4] << 8) | muxpack[len - 3];
-	cc &= 0x7FFF;
-	if ((cc != ttusb->cc) && (ttusb->cc != -1))
-		printk("%s: cc discontinuity (%d frames missing)\n",
-		       __func__, (cc - ttusb->cc) & 0x7FFF);
-	ttusb->cc = (cc + 1) & 0x7FFF;
-	if (muxpack[0] & 0x80) {
-#ifdef TTUSB_HWSECTIONS
-		/* section data */
-		int pusi = muxpack[0] & 0x40;
-		int channel = muxpack[0] & 0x1F;
-		int payload = muxpack[1];
-		const u8 *data = muxpack + 2;
-		/* check offset flag */
-		if (muxpack[0] & 0x20)
-			data++;
-
-		ttusb_handle_sec_data(ttusb->channel + channel, data,
-				      payload);
-		data += payload;
-
-		if ((!!(ttusb->muxpack[0] & 0x20)) ^
-		    !!(ttusb->muxpack[1] & 1))
-			data++;
-#warning TODO: pusi
-		printk("cc: %04x\n", (data[0] << 8) | data[1]);
-#endif
-		numsec++;
-	} else if (muxpack[0] == 0x47) {
-#ifdef TTUSB_HWSECTIONS
-		/* we have TS data here! */
-		int pid = ((muxpack[1] & 0x0F) << 8) | muxpack[2];
-		int channel;
-		for (channel = 0; channel < TTUSB_MAXCHANNEL; ++channel)
-			if (ttusb->channel[channel].active
-			    && (pid == ttusb->channel[channel].pid))
-				ttusb_handle_ts_data(ttusb->channel +
-						     channel, muxpack,
-						     188);
-#endif
-		numts++;
-		dvb_dmx_swfilter_packets(&ttusb->dvb_demux, muxpack, 1);
-	} else if (muxpack[0] != 0) {
-		numinvalid++;
-		printk("illegal muxpack type %02x\n", muxpack[0]);
-	} else
-		numstuff++;
-}
-
-static void ttusb_process_frame(struct ttusb *ttusb, u8 * data, int len)
-{
-	int maxwork = 1024;
-	while (len) {
-		if (!(maxwork--)) {
-			printk("%s: too much work\n", __func__);
-			break;
-		}
-
-		switch (ttusb->mux_state) {
-		case 0:
-		case 1:
-		case 2:
-			len--;
-			if (*data++ == 0xAA)
-				++ttusb->mux_state;
-			else {
-				ttusb->mux_state = 0;
-				if (ttusb->insync) {
-					dprintk("%s: %02x\n",
-						__func__, data[-1]);
-					printk(KERN_INFO "%s: lost sync.\n",
-					       __func__);
-					ttusb->insync = 0;
-				}
-			}
-			break;
-		case 3:
-			ttusb->insync = 1;
-			len--;
-			ttusb->mux_npacks = *data++;
-			++ttusb->mux_state;
-			ttusb->muxpack_ptr = 0;
-			/* maximum bytes, until we know the length */
-			ttusb->muxpack_len = 2;
-			break;
-		case 4:
-			{
-				int avail;
-				avail = len;
-				if (avail >
-				    (ttusb->muxpack_len -
-				     ttusb->muxpack_ptr))
-					avail =
-					    ttusb->muxpack_len -
-					    ttusb->muxpack_ptr;
-				memcpy(ttusb->muxpack + ttusb->muxpack_ptr,
-				       data, avail);
-				ttusb->muxpack_ptr += avail;
-				BUG_ON(ttusb->muxpack_ptr > 264);
-				data += avail;
-				len -= avail;
-				/* determine length */
-				if (ttusb->muxpack_ptr == 2) {
-					if (ttusb->muxpack[0] & 0x80) {
-						ttusb->muxpack_len =
-						    ttusb->muxpack[1] + 2;
-						if (ttusb->
-						    muxpack[0] & 0x20)
-							ttusb->
-							    muxpack_len++;
-						if ((!!
-						     (ttusb->
-						      muxpack[0] & 0x20)) ^
-						    !!(ttusb->
-						       muxpack[1] & 1))
-							ttusb->
-							    muxpack_len++;
-						ttusb->muxpack_len += 4;
-					} else if (ttusb->muxpack[0] ==
-						   0x47)
-						ttusb->muxpack_len =
-						    188 + 4;
-					else if (ttusb->muxpack[0] == 0x00)
-						ttusb->muxpack_len =
-						    ttusb->muxpack[1] + 2 +
-						    4;
-					else {
-						dprintk
-						    ("%s: invalid state: first byte is %x\n",
-						     __func__,
-						     ttusb->muxpack[0]);
-						ttusb->mux_state = 0;
-					}
-				}
-
-			/**
-			 * if length is valid and we reached the end:
-			 * goto next muxpack
-			 */
-				if ((ttusb->muxpack_ptr >= 2) &&
-				    (ttusb->muxpack_ptr ==
-				     ttusb->muxpack_len)) {
-					ttusb_process_muxpack(ttusb,
-							      ttusb->
-							      muxpack,
-							      ttusb->
-							      muxpack_ptr);
-					ttusb->muxpack_ptr = 0;
-					/* maximum bytes, until we know the length */
-					ttusb->muxpack_len = 2;
-
-				/**
-				 * no muxpacks left?
-				 * return to search-sync state
-				 */
-					if (!ttusb->mux_npacks--) {
-						ttusb->mux_state = 0;
-						break;
-					}
-				}
-				break;
-			}
-		default:
-			BUG();
-			break;
-		}
-	}
-}
-
-static void ttusb_iso_irq(struct urb *urb)
-{
-	struct ttusb *ttusb = urb->context;
-	struct usb_iso_packet_descriptor *d;
-	u8 *data;
-	int len, i;
-
-	if (!ttusb->iso_streaming)
-		return;
-
-#if 0
-	printk("%s: status %d, errcount == %d, length == %i\n",
-	       __func__,
-	       urb->status, urb->error_count, urb->actual_length);
-#endif
-
-	if (!urb->status) {
-		for (i = 0; i < urb->number_of_packets; ++i) {
-			numpkt++;
-			if (time_after_eq(jiffies, lastj + HZ)) {
-				dprintk("frames/s: %lu (ts: %d, stuff %d, "
-					"sec: %d, invalid: %d, all: %d)\n",
-					numpkt * HZ / (jiffies - lastj),
-					numts, numstuff, numsec, numinvalid,
-					numts + numstuff + numsec + numinvalid);
-				numts = numstuff = numsec = numinvalid = 0;
-				lastj = jiffies;
-				numpkt = 0;
-			}
-			d = &urb->iso_frame_desc[i];
-			data = urb->transfer_buffer + d->offset;
-			len = d->actual_length;
-			d->actual_length = 0;
-			d->status = 0;
-			ttusb_process_frame(ttusb, data, len);
-		}
-	}
-	usb_submit_urb(urb, GFP_ATOMIC);
-}
-
-static void ttusb_free_iso_urbs(struct ttusb *ttusb)
-{
-	int i;
-
-	for (i = 0; i < ISO_BUF_COUNT; i++)
-		if (ttusb->iso_urb[i])
-			usb_free_urb(ttusb->iso_urb[i]);
-
-	pci_free_consistent(NULL,
-			    ISO_FRAME_SIZE * FRAMES_PER_ISO_BUF *
-			    ISO_BUF_COUNT, ttusb->iso_buffer,
-			    ttusb->iso_dma_handle);
-}
-
-static int ttusb_alloc_iso_urbs(struct ttusb *ttusb)
-{
-	int i;
-
-	ttusb->iso_buffer = pci_alloc_consistent(NULL,
-						 ISO_FRAME_SIZE *
-						 FRAMES_PER_ISO_BUF *
-						 ISO_BUF_COUNT,
-						 &ttusb->iso_dma_handle);
-
-	if (!ttusb->iso_buffer) {
-		dprintk("%s: pci_alloc_consistent - not enough memory\n",
-			__func__);
-		return -ENOMEM;
-	}
-
-	memset(ttusb->iso_buffer, 0,
-	       ISO_FRAME_SIZE * FRAMES_PER_ISO_BUF * ISO_BUF_COUNT);
-
-	for (i = 0; i < ISO_BUF_COUNT; i++) {
-		struct urb *urb;
-
-		if (!
-		    (urb =
-		     usb_alloc_urb(FRAMES_PER_ISO_BUF, GFP_ATOMIC))) {
-			ttusb_free_iso_urbs(ttusb);
-			return -ENOMEM;
-		}
-
-		ttusb->iso_urb[i] = urb;
-	}
-
-	return 0;
-}
-
-static void ttusb_stop_iso_xfer(struct ttusb *ttusb)
-{
-	int i;
-
-	for (i = 0; i < ISO_BUF_COUNT; i++)
-		usb_kill_urb(ttusb->iso_urb[i]);
-
-	ttusb->iso_streaming = 0;
-}
-
-static int ttusb_start_iso_xfer(struct ttusb *ttusb)
-{
-	int i, j, err, buffer_offset = 0;
-
-	if (ttusb->iso_streaming) {
-		printk("%s: iso xfer already running!\n", __func__);
-		return 0;
-	}
-
-	ttusb->cc = -1;
-	ttusb->insync = 0;
-	ttusb->mux_state = 0;
-
-	for (i = 0; i < ISO_BUF_COUNT; i++) {
-		int frame_offset = 0;
-		struct urb *urb = ttusb->iso_urb[i];
-
-		urb->dev = ttusb->dev;
-		urb->context = ttusb;
-		urb->complete = ttusb_iso_irq;
-		urb->pipe = ttusb->isoc_in_pipe;
-		urb->transfer_flags = URB_ISO_ASAP;
-		urb->interval = 1;
-		urb->number_of_packets = FRAMES_PER_ISO_BUF;
-		urb->transfer_buffer_length =
-		    ISO_FRAME_SIZE * FRAMES_PER_ISO_BUF;
-		urb->transfer_buffer = ttusb->iso_buffer + buffer_offset;
-		buffer_offset += ISO_FRAME_SIZE * FRAMES_PER_ISO_BUF;
-
-		for (j = 0; j < FRAMES_PER_ISO_BUF; j++) {
-			urb->iso_frame_desc[j].offset = frame_offset;
-			urb->iso_frame_desc[j].length = ISO_FRAME_SIZE;
-			frame_offset += ISO_FRAME_SIZE;
-		}
-	}
-
-	for (i = 0; i < ISO_BUF_COUNT; i++) {
-		if ((err = usb_submit_urb(ttusb->iso_urb[i], GFP_ATOMIC))) {
-			ttusb_stop_iso_xfer(ttusb);
-			printk
-			    ("%s: failed urb submission (%i: err = %i)!\n",
-			     __func__, i, err);
-			return err;
-		}
-	}
-
-	ttusb->iso_streaming = 1;
-
-	return 0;
-}
-
-#ifdef TTUSB_HWSECTIONS
-static void ttusb_handle_ts_data(struct dvb_demux_feed *dvbdmxfeed, const u8 * data,
-			  int len)
-{
-	dvbdmxfeed->cb.ts(data, len, 0, 0, &dvbdmxfeed->feed.ts, 0);
-}
-
-static void ttusb_handle_sec_data(struct dvb_demux_feed *dvbdmxfeed, const u8 * data,
-			   int len)
-{
-//      struct dvb_demux_feed *dvbdmxfeed = channel->dvbdmxfeed;
-#error TODO: handle ugly stuff
-//      dvbdmxfeed->cb.sec(data, len, 0, 0, &dvbdmxfeed->feed.sec, 0);
-}
-#endif
-
-static int ttusb_start_feed(struct dvb_demux_feed *dvbdmxfeed)
-{
-	struct ttusb *ttusb = (struct ttusb *) dvbdmxfeed->demux;
-	int feed_type = 1;
-
-	dprintk("ttusb_start_feed\n");
-
-	switch (dvbdmxfeed->type) {
-	case DMX_TYPE_TS:
-		break;
-	case DMX_TYPE_SEC:
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	if (dvbdmxfeed->type == DMX_TYPE_TS) {
-		switch (dvbdmxfeed->pes_type) {
-		case DMX_TS_PES_VIDEO:
-		case DMX_TS_PES_AUDIO:
-		case DMX_TS_PES_TELETEXT:
-		case DMX_TS_PES_PCR:
-		case DMX_TS_PES_OTHER:
-			break;
-		default:
-			return -EINVAL;
-		}
-	}
-
-#ifdef TTUSB_HWSECTIONS
-#error TODO: allocate filters
-	if (dvbdmxfeed->type == DMX_TYPE_TS) {
-		feed_type = 1;
-	} else if (dvbdmxfeed->type == DMX_TYPE_SEC) {
-		feed_type = 2;
-	}
-#endif
-
-	ttusb_set_channel(ttusb, dvbdmxfeed->index, feed_type, dvbdmxfeed->pid);
-
-	if (0 == ttusb->running_feed_count++)
-		ttusb_start_iso_xfer(ttusb);
-
-	return 0;
-}
-
-static int ttusb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
-{
-	struct ttusb *ttusb = (struct ttusb *) dvbdmxfeed->demux;
-
-	ttusb_del_channel(ttusb, dvbdmxfeed->index);
-
-	if (--ttusb->running_feed_count == 0)
-		ttusb_stop_iso_xfer(ttusb);
-
-	return 0;
-}
-
-static int ttusb_setup_interfaces(struct ttusb *ttusb)
-{
-	usb_set_interface(ttusb->dev, 1, 1);
-
-	ttusb->bulk_out_pipe = usb_sndbulkpipe(ttusb->dev, 1);
-	ttusb->bulk_in_pipe = usb_rcvbulkpipe(ttusb->dev, 1);
-	ttusb->isoc_in_pipe = usb_rcvisocpipe(ttusb->dev, 2);
-
-	return 0;
-}
-
-#if 0
-static u8 stc_firmware[8192];
-
-static int stc_open(struct inode *inode, struct file *file)
-{
-	struct ttusb *ttusb = file->private_data;
-	int addr;
-
-	for (addr = 0; addr < 8192; addr += 16) {
-		u8 snd_buf[2] = { addr >> 8, addr & 0xFF };
-		ttusb_i2c_msg(ttusb, 0x50, snd_buf, 2, stc_firmware + addr,
-			      16);
-	}
-
-	return 0;
-}
-
-static ssize_t stc_read(struct file *file, char *buf, size_t count,
-		 loff_t *offset)
-{
-	return simple_read_from_buffer(buf, count, offset, stc_firmware, 8192);
-}
-
-static int stc_release(struct inode *inode, struct file *file)
-{
-	return 0;
-}
-
-static const struct file_operations stc_fops = {
-	.owner = THIS_MODULE,
-	.read = stc_read,
-	.open = stc_open,
-	.release = stc_release,
-};
-#endif
-
-static u32 functionality(struct i2c_adapter *adapter)
-{
-	return I2C_FUNC_I2C;
-}
-
-
-
-static int alps_tdmb7_tuner_set_params(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv;
-	u8 data[4];
-	struct i2c_msg msg = {.addr=0x61, .flags=0, .buf=data, .len=sizeof(data) };
-	u32 div;
-
-	div = (p->frequency + 36166667) / 166667;
-
-	data[0] = (div >> 8) & 0x7f;
-	data[1] = div & 0xff;
-	data[2] = ((div >> 10) & 0x60) | 0x85;
-	data[3] = p->frequency < 592000000 ? 0x40 : 0x80;
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	if (i2c_transfer(&ttusb->i2c_adap, &msg, 1) != 1) return -EIO;
-	return 0;
-}
-
-static struct cx22700_config alps_tdmb7_config = {
-	.demod_address = 0x43,
-};
-
-
-
-
-
-static int philips_tdm1316l_tuner_init(struct dvb_frontend* fe)
-{
-	struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv;
-	static u8 td1316_init[] = { 0x0b, 0xf5, 0x85, 0xab };
-	static u8 disable_mc44BC374c[] = { 0x1d, 0x74, 0xa0, 0x68 };
-	struct i2c_msg tuner_msg = { .addr=0x60, .flags=0, .buf=td1316_init, .len=sizeof(td1316_init) };
-
-	// setup PLL configuration
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	if (i2c_transfer(&ttusb->i2c_adap, &tuner_msg, 1) != 1) return -EIO;
-	msleep(1);
-
-	// disable the mc44BC374c (do not check for errors)
-	tuner_msg.addr = 0x65;
-	tuner_msg.buf = disable_mc44BC374c;
-	tuner_msg.len = sizeof(disable_mc44BC374c);
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	if (i2c_transfer(&ttusb->i2c_adap, &tuner_msg, 1) != 1) {
-		i2c_transfer(&ttusb->i2c_adap, &tuner_msg, 1);
-	}
-
-	return 0;
-}
-
-static int philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv;
-	u8 tuner_buf[4];
-	struct i2c_msg tuner_msg = {.addr=0x60, .flags=0, .buf=tuner_buf, .len=sizeof(tuner_buf) };
-	int tuner_frequency = 0;
-	u8 band, cp, filter;
-
-	// determine charge pump
-	tuner_frequency = p->frequency + 36130000;
-	if (tuner_frequency < 87000000) return -EINVAL;
-	else if (tuner_frequency < 130000000) cp = 3;
-	else if (tuner_frequency < 160000000) cp = 5;
-	else if (tuner_frequency < 200000000) cp = 6;
-	else if (tuner_frequency < 290000000) cp = 3;
-	else if (tuner_frequency < 420000000) cp = 5;
-	else if (tuner_frequency < 480000000) cp = 6;
-	else if (tuner_frequency < 620000000) cp = 3;
-	else if (tuner_frequency < 830000000) cp = 5;
-	else if (tuner_frequency < 895000000) cp = 7;
-	else return -EINVAL;
-
-	// determine band
-	if (p->frequency < 49000000)
-		return -EINVAL;
-	else if (p->frequency < 159000000)
-		band = 1;
-	else if (p->frequency < 444000000)
-		band = 2;
-	else if (p->frequency < 861000000)
-		band = 4;
-	else return -EINVAL;
-
-	// setup PLL filter
-	switch (p->bandwidth_hz) {
-	case 6000000:
-		tda1004x_writereg(fe, 0x0C, 0);
-		filter = 0;
-		break;
-
-	case 7000000:
-		tda1004x_writereg(fe, 0x0C, 0);
-		filter = 0;
-		break;
-
-	case 8000000:
-		tda1004x_writereg(fe, 0x0C, 0xFF);
-		filter = 1;
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	// calculate divisor
-	// ((36130000+((1000000/6)/2)) + Finput)/(1000000/6)
-	tuner_frequency = (((p->frequency / 1000) * 6) + 217280) / 1000;
-
-	// setup tuner buffer
-	tuner_buf[0] = tuner_frequency >> 8;
-	tuner_buf[1] = tuner_frequency & 0xff;
-	tuner_buf[2] = 0xca;
-	tuner_buf[3] = (cp << 5) | (filter << 3) | band;
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	if (i2c_transfer(&ttusb->i2c_adap, &tuner_msg, 1) != 1)
-		return -EIO;
-
-	msleep(1);
-	return 0;
-}
-
-static int philips_tdm1316l_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name)
-{
-	struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv;
-
-	return request_firmware(fw, name, &ttusb->dev->dev);
-}
-
-static struct tda1004x_config philips_tdm1316l_config = {
-
-	.demod_address = 0x8,
-	.invert = 1,
-	.invert_oclk = 0,
-	.request_firmware = philips_tdm1316l_request_firmware,
-};
-
-static u8 alps_bsbe1_inittab[] = {
-	0x01, 0x15,
-	0x02, 0x30,
-	0x03, 0x00,
-	0x04, 0x7d,             /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */
-	0x05, 0x35,             /* I2CT = 0, SCLT = 1, SDAT = 1 */
-	0x06, 0x40,             /* DAC not used, set to high impendance mode */
-	0x07, 0x00,             /* DAC LSB */
-	0x08, 0x40,             /* DiSEqC off, LNB power on OP2/LOCK pin on */
-	0x09, 0x00,             /* FIFO */
-	0x0c, 0x51,             /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */
-	0x0d, 0x82,             /* DC offset compensation = ON, beta_agc1 = 2 */
-	0x0e, 0x23,             /* alpha_tmg = 2, beta_tmg = 3 */
-	0x10, 0x3f,             // AGC2  0x3d
-	0x11, 0x84,
-	0x12, 0xb9,
-	0x15, 0xc9,             // lock detector threshold
-	0x16, 0x00,
-	0x17, 0x00,
-	0x18, 0x00,
-	0x19, 0x00,
-	0x1a, 0x00,
-	0x1f, 0x50,
-	0x20, 0x00,
-	0x21, 0x00,
-	0x22, 0x00,
-	0x23, 0x00,
-	0x28, 0x00,             // out imp: normal  out type: parallel FEC mode:0
-	0x29, 0x1e,             // 1/2 threshold
-	0x2a, 0x14,             // 2/3 threshold
-	0x2b, 0x0f,             // 3/4 threshold
-	0x2c, 0x09,             // 5/6 threshold
-	0x2d, 0x05,             // 7/8 threshold
-	0x2e, 0x01,
-	0x31, 0x1f,             // test all FECs
-	0x32, 0x19,             // viterbi and synchro search
-	0x33, 0xfc,             // rs control
-	0x34, 0x93,             // error control
-	0x0f, 0x92,
-	0xff, 0xff
-};
-
-static u8 alps_bsru6_inittab[] = {
-	0x01, 0x15,
-	0x02, 0x30,
-	0x03, 0x00,
-	0x04, 0x7d,		/* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */
-	0x05, 0x35,		/* I2CT = 0, SCLT = 1, SDAT = 1 */
-	0x06, 0x40,		/* DAC not used, set to high impendance mode */
-	0x07, 0x00,		/* DAC LSB */
-	0x08, 0x40,		/* DiSEqC off, LNB power on OP2/LOCK pin on */
-	0x09, 0x00,		/* FIFO */
-	0x0c, 0x51,		/* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */
-	0x0d, 0x82,		/* DC offset compensation = ON, beta_agc1 = 2 */
-	0x0e, 0x23,		/* alpha_tmg = 2, beta_tmg = 3 */
-	0x10, 0x3f,		// AGC2  0x3d
-	0x11, 0x84,
-	0x12, 0xb9,
-	0x15, 0xc9,		// lock detector threshold
-	0x16, 0x00,
-	0x17, 0x00,
-	0x18, 0x00,
-	0x19, 0x00,
-	0x1a, 0x00,
-	0x1f, 0x50,
-	0x20, 0x00,
-	0x21, 0x00,
-	0x22, 0x00,
-	0x23, 0x00,
-	0x28, 0x00,		// out imp: normal  out type: parallel FEC mode:0
-	0x29, 0x1e,		// 1/2 threshold
-	0x2a, 0x14,		// 2/3 threshold
-	0x2b, 0x0f,		// 3/4 threshold
-	0x2c, 0x09,		// 5/6 threshold
-	0x2d, 0x05,		// 7/8 threshold
-	0x2e, 0x01,
-	0x31, 0x1f,		// test all FECs
-	0x32, 0x19,		// viterbi and synchro search
-	0x33, 0xfc,		// rs control
-	0x34, 0x93,		// error control
-	0x0f, 0x52,
-	0xff, 0xff
-};
-
-static int alps_stv0299_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ratio)
-{
-	u8 aclk = 0;
-	u8 bclk = 0;
-
-	if (srate < 1500000) {
-		aclk = 0xb7;
-		bclk = 0x47;
-	} else if (srate < 3000000) {
-		aclk = 0xb7;
-		bclk = 0x4b;
-	} else if (srate < 7000000) {
-		aclk = 0xb7;
-		bclk = 0x4f;
-	} else if (srate < 14000000) {
-		aclk = 0xb7;
-		bclk = 0x53;
-	} else if (srate < 30000000) {
-		aclk = 0xb6;
-		bclk = 0x53;
-	} else if (srate < 45000000) {
-		aclk = 0xb4;
-		bclk = 0x51;
-	}
-
-	stv0299_writereg(fe, 0x13, aclk);
-	stv0299_writereg(fe, 0x14, bclk);
-	stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
-	stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff);
-	stv0299_writereg(fe, 0x21, (ratio) & 0xf0);
-
-	return 0;
-}
-
-static int philips_tsa5059_tuner_set_params(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv;
-	u8 buf[4];
-	u32 div;
-	struct i2c_msg msg = {.addr = 0x61,.flags = 0,.buf = buf,.len = sizeof(buf) };
-
-	if ((p->frequency < 950000) || (p->frequency > 2150000))
-		return -EINVAL;
-
-	div = (p->frequency + (125 - 1)) / 125;	/* round correctly */
-	buf[0] = (div >> 8) & 0x7f;
-	buf[1] = div & 0xff;
-	buf[2] = 0x80 | ((div & 0x18000) >> 10) | 4;
-	buf[3] = 0xC4;
-
-	if (p->frequency > 1530000)
-		buf[3] = 0xC0;
-
-	/* BSBE1 wants XCE bit set */
-	if (ttusb->revision == TTUSB_REV_2_2)
-		buf[3] |= 0x20;
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	if (i2c_transfer(&ttusb->i2c_adap, &msg, 1) != 1)
-		return -EIO;
-
-	return 0;
-}
-
-static struct stv0299_config alps_stv0299_config = {
-	.demod_address = 0x68,
-	.inittab = alps_bsru6_inittab,
-	.mclk = 88000000UL,
-	.invert = 1,
-	.skip_reinit = 0,
-	.lock_output = STV0299_LOCKOUTPUT_1,
-	.volt13_op0_op1 = STV0299_VOLT13_OP1,
-	.min_delay_ms = 100,
-	.set_symbol_rate = alps_stv0299_set_symbol_rate,
-};
-
-static int ttusb_novas_grundig_29504_491_tuner_set_params(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv;
-	u8 buf[4];
-	u32 div;
-	struct i2c_msg msg = {.addr = 0x61,.flags = 0,.buf = buf,.len = sizeof(buf) };
-
-	div = p->frequency / 125;
-
-	buf[0] = (div >> 8) & 0x7f;
-	buf[1] = div & 0xff;
-	buf[2] = 0x8e;
-	buf[3] = 0x00;
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	if (i2c_transfer(&ttusb->i2c_adap, &msg, 1) != 1)
-		return -EIO;
-
-	return 0;
-}
-
-static struct tda8083_config ttusb_novas_grundig_29504_491_config = {
-
-	.demod_address = 0x68,
-};
-
-static int alps_tdbe2_tuner_set_params(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct ttusb* ttusb = fe->dvb->priv;
-	u32 div;
-	u8 data[4];
-	struct i2c_msg msg = { .addr = 0x62, .flags = 0, .buf = data, .len = sizeof(data) };
-
-	div = (p->frequency + 35937500 + 31250) / 62500;
-
-	data[0] = (div >> 8) & 0x7f;
-	data[1] = div & 0xff;
-	data[2] = 0x85 | ((div >> 10) & 0x60);
-	data[3] = (p->frequency < 174000000 ? 0x88 : p->frequency < 470000000 ? 0x84 : 0x81);
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	if (i2c_transfer (&ttusb->i2c_adap, &msg, 1) != 1)
-		return -EIO;
-
-	return 0;
-}
-
-
-static struct ves1820_config alps_tdbe2_config = {
-	.demod_address = 0x09,
-	.xin = 57840000UL,
-	.invert = 1,
-	.selagc = VES1820_SELAGC_SIGNAMPERR,
-};
-
-static u8 read_pwm(struct ttusb* ttusb)
-{
-	u8 b = 0xff;
-	u8 pwm;
-	struct i2c_msg msg[] = { { .addr = 0x50,.flags = 0,.buf = &b,.len = 1 },
-				{ .addr = 0x50,.flags = I2C_M_RD,.buf = &pwm,.len = 1} };
-
-	if ((i2c_transfer(&ttusb->i2c_adap, msg, 2) != 2) || (pwm == 0xff))
-		pwm = 0x48;
-
-	return pwm;
-}
-
-
-static int dvbc_philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct ttusb *ttusb = (struct ttusb *) fe->dvb->priv;
-	u8 tuner_buf[5];
-	struct i2c_msg tuner_msg = {.addr = 0x60,
-				    .flags = 0,
-				    .buf = tuner_buf,
-				    .len = sizeof(tuner_buf) };
-	int tuner_frequency = 0;
-	u8 band, cp, filter;
-
-	// determine charge pump
-	tuner_frequency = p->frequency;
-	if      (tuner_frequency <  87000000) {return -EINVAL;}
-	else if (tuner_frequency < 130000000) {cp = 3; band = 1;}
-	else if (tuner_frequency < 160000000) {cp = 5; band = 1;}
-	else if (tuner_frequency < 200000000) {cp = 6; band = 1;}
-	else if (tuner_frequency < 290000000) {cp = 3; band = 2;}
-	else if (tuner_frequency < 420000000) {cp = 5; band = 2;}
-	else if (tuner_frequency < 480000000) {cp = 6; band = 2;}
-	else if (tuner_frequency < 620000000) {cp = 3; band = 4;}
-	else if (tuner_frequency < 830000000) {cp = 5; band = 4;}
-	else if (tuner_frequency < 895000000) {cp = 7; band = 4;}
-	else {return -EINVAL;}
-
-	// assume PLL filter should always be 8MHz for the moment.
-	filter = 1;
-
-	// calculate divisor
-	// (Finput + Fif)/Fref; Fif = 36125000 Hz, Fref = 62500 Hz
-	tuner_frequency = ((p->frequency + 36125000) / 62500);
-
-	// setup tuner buffer
-	tuner_buf[0] = tuner_frequency >> 8;
-	tuner_buf[1] = tuner_frequency & 0xff;
-	tuner_buf[2] = 0xc8;
-	tuner_buf[3] = (cp << 5) | (filter << 3) | band;
-	tuner_buf[4] = 0x80;
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	if (i2c_transfer(&ttusb->i2c_adap, &tuner_msg, 1) != 1) {
-		printk("dvb-ttusb-budget: dvbc_philips_tdm1316l_pll_set Error 1\n");
-		return -EIO;
-	}
-
-	msleep(50);
-
-	if (fe->ops.i2c_gate_ctrl)
-		fe->ops.i2c_gate_ctrl(fe, 1);
-	if (i2c_transfer(&ttusb->i2c_adap, &tuner_msg, 1) != 1) {
-		printk("dvb-ttusb-budget: dvbc_philips_tdm1316l_pll_set Error 2\n");
-		return -EIO;
-	}
-
-	msleep(1);
-
-	return 0;
-}
-
-static u8 dvbc_philips_tdm1316l_inittab[] = {
-	0x80, 0x21,
-	0x80, 0x20,
-	0x81, 0x01,
-	0x81, 0x00,
-	0x00, 0x09,
-	0x01, 0x69,
-	0x03, 0x00,
-	0x04, 0x00,
-	0x07, 0x00,
-	0x08, 0x00,
-	0x20, 0x00,
-	0x21, 0x40,
-	0x22, 0x00,
-	0x23, 0x00,
-	0x24, 0x40,
-	0x25, 0x88,
-	0x30, 0xff,
-	0x31, 0x00,
-	0x32, 0xff,
-	0x33, 0x00,
-	0x34, 0x50,
-	0x35, 0x7f,
-	0x36, 0x00,
-	0x37, 0x20,
-	0x38, 0x00,
-	0x40, 0x1c,
-	0x41, 0xff,
-	0x42, 0x29,
-	0x43, 0x20,
-	0x44, 0xff,
-	0x45, 0x00,
-	0x46, 0x00,
-	0x49, 0x04,
-	0x4a, 0xff,
-	0x4b, 0x7f,
-	0x52, 0x30,
-	0x55, 0xae,
-	0x56, 0x47,
-	0x57, 0xe1,
-	0x58, 0x3a,
-	0x5a, 0x1e,
-	0x5b, 0x34,
-	0x60, 0x00,
-	0x63, 0x00,
-	0x64, 0x00,
-	0x65, 0x00,
-	0x66, 0x00,
-	0x67, 0x00,
-	0x68, 0x00,
-	0x69, 0x00,
-	0x6a, 0x02,
-	0x6b, 0x00,
-	0x70, 0xff,
-	0x71, 0x00,
-	0x72, 0x00,
-	0x73, 0x00,
-	0x74, 0x0c,
-	0x80, 0x00,
-	0x81, 0x00,
-	0x82, 0x00,
-	0x83, 0x00,
-	0x84, 0x04,
-	0x85, 0x80,
-	0x86, 0x24,
-	0x87, 0x78,
-	0x88, 0x00,
-	0x89, 0x00,
-	0x90, 0x01,
-	0x91, 0x01,
-	0xa0, 0x00,
-	0xa1, 0x00,
-	0xa2, 0x00,
-	0xb0, 0x91,
-	0xb1, 0x0b,
-	0xc0, 0x4b,
-	0xc1, 0x00,
-	0xc2, 0x00,
-	0xd0, 0x00,
-	0xd1, 0x00,
-	0xd2, 0x00,
-	0xd3, 0x00,
-	0xd4, 0x00,
-	0xd5, 0x00,
-	0xde, 0x00,
-	0xdf, 0x00,
-	0x61, 0x38,
-	0x62, 0x0a,
-	0x53, 0x13,
-	0x59, 0x08,
-	0x55, 0x00,
-	0x56, 0x40,
-	0x57, 0x08,
-	0x58, 0x3d,
-	0x88, 0x10,
-	0xa0, 0x00,
-	0xa0, 0x00,
-	0xa0, 0x00,
-	0xa0, 0x04,
-	0xff, 0xff,
-};
-
-static struct stv0297_config dvbc_philips_tdm1316l_config = {
-	.demod_address = 0x1c,
-	.inittab = dvbc_philips_tdm1316l_inittab,
-	.invert = 0,
-};
-
-static void frontend_init(struct ttusb* ttusb)
-{
-	switch(le16_to_cpu(ttusb->dev->descriptor.idProduct)) {
-	case 0x1003: // Hauppauge/TT Nova-USB-S budget (stv0299/ALPS BSRU6|BSBE1(tsa5059))
-		// try the stv0299 based first
-		ttusb->fe = dvb_attach(stv0299_attach, &alps_stv0299_config, &ttusb->i2c_adap);
-		if (ttusb->fe != NULL) {
-			ttusb->fe->ops.tuner_ops.set_params = philips_tsa5059_tuner_set_params;
-
-			if(ttusb->revision == TTUSB_REV_2_2) { // ALPS BSBE1
-				alps_stv0299_config.inittab = alps_bsbe1_inittab;
-				dvb_attach(lnbp21_attach, ttusb->fe, &ttusb->i2c_adap, 0, 0);
-			} else { // ALPS BSRU6
-				ttusb->fe->ops.set_voltage = ttusb_set_voltage;
-			}
-			break;
-		}
-
-		// Grundig 29504-491
-		ttusb->fe = dvb_attach(tda8083_attach, &ttusb_novas_grundig_29504_491_config, &ttusb->i2c_adap);
-		if (ttusb->fe != NULL) {
-			ttusb->fe->ops.tuner_ops.set_params = ttusb_novas_grundig_29504_491_tuner_set_params;
-			ttusb->fe->ops.set_voltage = ttusb_set_voltage;
-			break;
-		}
-		break;
-
-	case 0x1004: // Hauppauge/TT DVB-C budget (ves1820/ALPS TDBE2(sp5659))
-		ttusb->fe = dvb_attach(ves1820_attach, &alps_tdbe2_config, &ttusb->i2c_adap, read_pwm(ttusb));
-		if (ttusb->fe != NULL) {
-			ttusb->fe->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params;
-			break;
-		}
-
-		ttusb->fe = dvb_attach(stv0297_attach, &dvbc_philips_tdm1316l_config, &ttusb->i2c_adap);
-		if (ttusb->fe != NULL) {
-			ttusb->fe->ops.tuner_ops.set_params = dvbc_philips_tdm1316l_tuner_set_params;
-			break;
-		}
-		break;
-
-	case 0x1005: // Hauppauge/TT Nova-USB-t budget (tda10046/Philips td1316(tda6651tt) OR cx22700/ALPS TDMB7(??))
-		// try the ALPS TDMB7 first
-		ttusb->fe = dvb_attach(cx22700_attach, &alps_tdmb7_config, &ttusb->i2c_adap);
-		if (ttusb->fe != NULL) {
-			ttusb->fe->ops.tuner_ops.set_params = alps_tdmb7_tuner_set_params;
-			break;
-		}
-
-		// Philips td1316
-		ttusb->fe = dvb_attach(tda10046_attach, &philips_tdm1316l_config, &ttusb->i2c_adap);
-		if (ttusb->fe != NULL) {
-			ttusb->fe->ops.tuner_ops.init = philips_tdm1316l_tuner_init;
-			ttusb->fe->ops.tuner_ops.set_params = philips_tdm1316l_tuner_set_params;
-			break;
-		}
-		break;
-	}
-
-	if (ttusb->fe == NULL) {
-		printk("dvb-ttusb-budget: A frontend driver was not found for device [%04x:%04x]\n",
-		       le16_to_cpu(ttusb->dev->descriptor.idVendor),
-		       le16_to_cpu(ttusb->dev->descriptor.idProduct));
-	} else {
-		if (dvb_register_frontend(&ttusb->adapter, ttusb->fe)) {
-			printk("dvb-ttusb-budget: Frontend registration failed!\n");
-			dvb_frontend_detach(ttusb->fe);
-			ttusb->fe = NULL;
-		}
-	}
-}
-
-
-
-static struct i2c_algorithm ttusb_dec_algo = {
-	.master_xfer	= master_xfer,
-	.functionality	= functionality,
-};
-
-static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *id)
-{
-	struct usb_device *udev;
-	struct ttusb *ttusb;
-	int result;
-
-	dprintk("%s: TTUSB DVB connected\n", __func__);
-
-	udev = interface_to_usbdev(intf);
-
-	if (intf->altsetting->desc.bInterfaceNumber != 1) return -ENODEV;
-
-	if (!(ttusb = kzalloc(sizeof(struct ttusb), GFP_KERNEL)))
-		return -ENOMEM;
-
-	ttusb->dev = udev;
-	ttusb->c = 0;
-	ttusb->mux_state = 0;
-	mutex_init(&ttusb->semi2c);
-
-	mutex_lock(&ttusb->semi2c);
-
-	mutex_init(&ttusb->semusb);
-
-	ttusb_setup_interfaces(ttusb);
-
-	result = ttusb_alloc_iso_urbs(ttusb);
-	if (result < 0) {
-		dprintk("%s: ttusb_alloc_iso_urbs - failed\n", __func__);
-		mutex_unlock(&ttusb->semi2c);
-		kfree(ttusb);
-		return result;
-	}
-
-	if (ttusb_init_controller(ttusb))
-		printk("ttusb_init_controller: error\n");
-
-	mutex_unlock(&ttusb->semi2c);
-
-	result = dvb_register_adapter(&ttusb->adapter,
-				      "Technotrend/Hauppauge Nova-USB",
-				      THIS_MODULE, &udev->dev, adapter_nr);
-	if (result < 0) {
-		ttusb_free_iso_urbs(ttusb);
-		kfree(ttusb);
-		return result;
-	}
-	ttusb->adapter.priv = ttusb;
-
-	/* i2c */
-	memset(&ttusb->i2c_adap, 0, sizeof(struct i2c_adapter));
-	strcpy(ttusb->i2c_adap.name, "TTUSB DEC");
-
-	i2c_set_adapdata(&ttusb->i2c_adap, ttusb);
-
-	ttusb->i2c_adap.algo              = &ttusb_dec_algo;
-	ttusb->i2c_adap.algo_data         = NULL;
-	ttusb->i2c_adap.dev.parent	  = &udev->dev;
-
-	result = i2c_add_adapter(&ttusb->i2c_adap);
-	if (result)
-		goto err_unregister_adapter;
-
-	memset(&ttusb->dvb_demux, 0, sizeof(ttusb->dvb_demux));
-
-	ttusb->dvb_demux.dmx.capabilities =
-	    DMX_TS_FILTERING | DMX_SECTION_FILTERING;
-	ttusb->dvb_demux.priv = NULL;
-#ifdef TTUSB_HWSECTIONS
-	ttusb->dvb_demux.filternum = TTUSB_MAXFILTER;
-#else
-	ttusb->dvb_demux.filternum = 32;
-#endif
-	ttusb->dvb_demux.feednum = TTUSB_MAXCHANNEL;
-	ttusb->dvb_demux.start_feed = ttusb_start_feed;
-	ttusb->dvb_demux.stop_feed = ttusb_stop_feed;
-	ttusb->dvb_demux.write_to_decoder = NULL;
-
-	result = dvb_dmx_init(&ttusb->dvb_demux);
-	if (result < 0) {
-		printk("ttusb_dvb: dvb_dmx_init failed (errno = %d)\n", result);
-		result = -ENODEV;
-		goto err_i2c_del_adapter;
-	}
-//FIXME dmxdev (nur WAS?)
-	ttusb->dmxdev.filternum = ttusb->dvb_demux.filternum;
-	ttusb->dmxdev.demux = &ttusb->dvb_demux.dmx;
-	ttusb->dmxdev.capabilities = 0;
-
-	result = dvb_dmxdev_init(&ttusb->dmxdev, &ttusb->adapter);
-	if (result < 0) {
-		printk("ttusb_dvb: dvb_dmxdev_init failed (errno = %d)\n",
-		       result);
-		result = -ENODEV;
-		goto err_release_dmx;
-	}
-
-	if (dvb_net_init(&ttusb->adapter, &ttusb->dvbnet, &ttusb->dvb_demux.dmx)) {
-		printk("ttusb_dvb: dvb_net_init failed!\n");
-		result = -ENODEV;
-		goto err_release_dmxdev;
-	}
-
-	usb_set_intfdata(intf, (void *) ttusb);
-
-	frontend_init(ttusb);
-
-	return 0;
-
-err_release_dmxdev:
-	dvb_dmxdev_release(&ttusb->dmxdev);
-err_release_dmx:
-	dvb_dmx_release(&ttusb->dvb_demux);
-err_i2c_del_adapter:
-	i2c_del_adapter(&ttusb->i2c_adap);
-err_unregister_adapter:
-	dvb_unregister_adapter (&ttusb->adapter);
-	return result;
-}
-
-static void ttusb_disconnect(struct usb_interface *intf)
-{
-	struct ttusb *ttusb = usb_get_intfdata(intf);
-
-	usb_set_intfdata(intf, NULL);
-
-	ttusb->disconnecting = 1;
-
-	ttusb_stop_iso_xfer(ttusb);
-
-	ttusb->dvb_demux.dmx.close(&ttusb->dvb_demux.dmx);
-	dvb_net_release(&ttusb->dvbnet);
-	dvb_dmxdev_release(&ttusb->dmxdev);
-	dvb_dmx_release(&ttusb->dvb_demux);
-	if (ttusb->fe != NULL) {
-		dvb_unregister_frontend(ttusb->fe);
-		dvb_frontend_detach(ttusb->fe);
-	}
-	i2c_del_adapter(&ttusb->i2c_adap);
-	dvb_unregister_adapter(&ttusb->adapter);
-
-	ttusb_free_iso_urbs(ttusb);
-
-	kfree(ttusb);
-
-	dprintk("%s: TTUSB DVB disconnected\n", __func__);
-}
-
-static struct usb_device_id ttusb_table[] = {
-	{USB_DEVICE(0xb48, 0x1003)},
-	{USB_DEVICE(0xb48, 0x1004)},
-	{USB_DEVICE(0xb48, 0x1005)},
-	{}
-};
-
-MODULE_DEVICE_TABLE(usb, ttusb_table);
-
-static struct usb_driver ttusb_driver = {
-      .name		= "ttusb",
-      .probe		= ttusb_probe,
-      .disconnect	= ttusb_disconnect,
-      .id_table		= ttusb_table,
-};
-
-module_usb_driver(ttusb_driver);
-
-MODULE_AUTHOR("Holger Waechtler <holger@convergence.de>");
-MODULE_DESCRIPTION("TTUSB DVB Driver");
-MODULE_LICENSE("GPL");
-MODULE_FIRMWARE("ttusb-budget/dspbootcode.bin");
diff --git a/drivers/media/dvb/ttusb-dec/Kconfig b/drivers/media/dvb/ttusb-dec/Kconfig
deleted file mode 100644
index 290254a..0000000
--- a/drivers/media/dvb/ttusb-dec/Kconfig
+++ /dev/null
@@ -1,21 +0,0 @@
-config DVB_TTUSB_DEC
-	tristate "Technotrend/Hauppauge USB DEC devices"
-	depends on DVB_CORE && USB && INPUT && PCI
-	select CRC32
-	help
-	  Support for external USB adapters designed by Technotrend and
-	  produced by Hauppauge, shipped under the brand name 'DEC2000-t'
-	  and 'DEC3000-s'.
-
-	  Even if these devices have a MPEG decoder built in, they transmit
-	  only compressed MPEG data over the USB bus, so you need
-	  an external software decoder to watch TV on your computer.
-
-	  This driver needs external firmware. Please use the commands
-	  "<kerneldir>/Documentation/dvb/get_dvb_firmware dec2000t",
-	  "<kerneldir>/Documentation/dvb/get_dvb_firmware dec2540t",
-	  "<kerneldir>/Documentation/dvb/get_dvb_firmware dec3000s",
-	  download/extract them, and then copy them to /usr/lib/hotplug/firmware
-	  or /lib/firmware (depending on configuration of firmware hotplug).
-
-	  Say Y if you own such a device and want to use it.
diff --git a/drivers/media/dvb/ttusb-dec/Makefile b/drivers/media/dvb/ttusb-dec/Makefile
deleted file mode 100644
index ed28b53..0000000
--- a/drivers/media/dvb/ttusb-dec/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-obj-$(CONFIG_DVB_TTUSB_DEC) += ttusb_dec.o ttusbdecfe.o
-
-ccflags-y += -Idrivers/media/dvb/dvb-core/
diff --git a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/dvb/ttusb-dec/ttusb_dec.c
deleted file mode 100644
index 504c812..0000000
--- a/drivers/media/dvb/ttusb-dec/ttusb_dec.c
+++ /dev/null
@@ -1,1764 +0,0 @@
-/*
- * TTUSB DEC Driver
- *
- * Copyright (C) 2003-2004 Alex Woods <linux-dvb@giblets.org>
- * IR support by Peter Beutner <p.beutner@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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You 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/list.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/usb.h>
-#include <linux/interrupt.h>
-#include <linux/firmware.h>
-#include <linux/crc32.h>
-#include <linux/init.h>
-#include <linux/input.h>
-
-#include <linux/mutex.h>
-
-#include "dmxdev.h"
-#include "dvb_demux.h"
-#include "dvb_filter.h"
-#include "dvb_frontend.h"
-#include "dvb_net.h"
-#include "ttusbdecfe.h"
-
-static int debug;
-static int output_pva;
-static int enable_rc;
-
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
-module_param(output_pva, int, 0444);
-MODULE_PARM_DESC(output_pva, "Output PVA from dvr device (default:off)");
-module_param(enable_rc, int, 0644);
-MODULE_PARM_DESC(enable_rc, "Turn on/off IR remote control(default: off)");
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-#define dprintk	if (debug) printk
-
-#define DRIVER_NAME		"TechnoTrend/Hauppauge DEC USB"
-
-#define COMMAND_PIPE		0x03
-#define RESULT_PIPE		0x04
-#define IN_PIPE			0x08
-#define OUT_PIPE		0x07
-#define IRQ_PIPE		0x0A
-
-#define COMMAND_PACKET_SIZE	0x3c
-#define ARM_PACKET_SIZE		0x1000
-#define IRQ_PACKET_SIZE		0x8
-
-#define ISO_BUF_COUNT		0x04
-#define FRAMES_PER_ISO_BUF	0x04
-#define ISO_FRAME_SIZE		0x0380
-
-#define	MAX_PVA_LENGTH		6144
-
-enum ttusb_dec_model {
-	TTUSB_DEC2000T,
-	TTUSB_DEC2540T,
-	TTUSB_DEC3000S
-};
-
-enum ttusb_dec_packet_type {
-	TTUSB_DEC_PACKET_PVA,
-	TTUSB_DEC_PACKET_SECTION,
-	TTUSB_DEC_PACKET_EMPTY
-};
-
-enum ttusb_dec_interface {
-	TTUSB_DEC_INTERFACE_INITIAL,
-	TTUSB_DEC_INTERFACE_IN,
-	TTUSB_DEC_INTERFACE_OUT
-};
-
-struct ttusb_dec {
-	enum ttusb_dec_model		model;
-	char				*model_name;
-	char				*firmware_name;
-	int				can_playback;
-
-	/* DVB bits */
-	struct dvb_adapter		adapter;
-	struct dmxdev			dmxdev;
-	struct dvb_demux		demux;
-	struct dmx_frontend		frontend;
-	struct dvb_net			dvb_net;
-	struct dvb_frontend*		fe;
-
-	u16			pid[DMX_PES_OTHER];
-
-	/* USB bits */
-	struct usb_device		*udev;
-	u8				trans_count;
-	unsigned int			command_pipe;
-	unsigned int			result_pipe;
-	unsigned int			in_pipe;
-	unsigned int			out_pipe;
-	unsigned int			irq_pipe;
-	enum ttusb_dec_interface	interface;
-	struct mutex			usb_mutex;
-
-	void			*irq_buffer;
-	struct urb		*irq_urb;
-	dma_addr_t		irq_dma_handle;
-	void			*iso_buffer;
-	dma_addr_t		iso_dma_handle;
-	struct urb		*iso_urb[ISO_BUF_COUNT];
-	int			iso_stream_count;
-	struct mutex		iso_mutex;
-
-	u8				packet[MAX_PVA_LENGTH + 4];
-	enum ttusb_dec_packet_type	packet_type;
-	int				packet_state;
-	int				packet_length;
-	int				packet_payload_length;
-	u16				next_packet_id;
-
-	int				pva_stream_count;
-	int				filter_stream_count;
-
-	struct dvb_filter_pes2ts	a_pes2ts;
-	struct dvb_filter_pes2ts	v_pes2ts;
-
-	u8			v_pes[16 + MAX_PVA_LENGTH];
-	int			v_pes_length;
-	int			v_pes_postbytes;
-
-	struct list_head	urb_frame_list;
-	struct tasklet_struct	urb_tasklet;
-	spinlock_t		urb_frame_list_lock;
-
-	struct dvb_demux_filter	*audio_filter;
-	struct dvb_demux_filter	*video_filter;
-	struct list_head	filter_info_list;
-	spinlock_t		filter_info_list_lock;
-
-	struct input_dev	*rc_input_dev;
-	char			rc_phys[64];
-
-	int			active; /* Loaded successfully */
-};
-
-struct urb_frame {
-	u8			data[ISO_FRAME_SIZE];
-	int			length;
-	struct list_head	urb_frame_list;
-};
-
-struct filter_info {
-	u8			stream_id;
-	struct dvb_demux_filter	*filter;
-	struct list_head	filter_info_list;
-};
-
-static u16 rc_keys[] = {
-	KEY_POWER,
-	KEY_MUTE,
-	KEY_1,
-	KEY_2,
-	KEY_3,
-	KEY_4,
-	KEY_5,
-	KEY_6,
-	KEY_7,
-	KEY_8,
-	KEY_9,
-	KEY_0,
-	KEY_CHANNELUP,
-	KEY_VOLUMEDOWN,
-	KEY_OK,
-	KEY_VOLUMEUP,
-	KEY_CHANNELDOWN,
-	KEY_PREVIOUS,
-	KEY_ESC,
-	KEY_RED,
-	KEY_GREEN,
-	KEY_YELLOW,
-	KEY_BLUE,
-	KEY_OPTION,
-	KEY_M,
-	KEY_RADIO
-};
-
-static void ttusb_dec_set_model(struct ttusb_dec *dec,
-				enum ttusb_dec_model model);
-
-static void ttusb_dec_handle_irq( struct urb *urb)
-{
-	struct ttusb_dec * dec = urb->context;
-	char *buffer = dec->irq_buffer;
-	int retval;
-
-	switch(urb->status) {
-		case 0: /*success*/
-			break;
-		case -ECONNRESET:
-		case -ENOENT:
-		case -ESHUTDOWN:
-		case -ETIME:
-			/* this urb is dead, cleanup */
-			dprintk("%s:urb shutting down with status: %d\n",
-					__func__, urb->status);
-			return;
-		default:
-			dprintk("%s:nonzero status received: %d\n",
-					__func__,urb->status);
-			goto exit;
-	}
-
-	if( (buffer[0] == 0x1) && (buffer[2] == 0x15) )  {
-		/* IR - Event */
-		/* this is an fact a bit too simple implementation;
-		 * the box also reports a keyrepeat signal
-		 * (with buffer[3] == 0x40) in an intervall of ~100ms.
-		 * But to handle this correctly we had to imlemenent some
-		 * kind of timer which signals a 'key up' event if no
-		 * keyrepeat signal is received for lets say 200ms.
-		 * this should/could be added later ...
-		 * for now lets report each signal as a key down and up*/
-		dprintk("%s:rc signal:%d\n", __func__, buffer[4]);
-		input_report_key(dec->rc_input_dev, rc_keys[buffer[4] - 1], 1);
-		input_sync(dec->rc_input_dev);
-		input_report_key(dec->rc_input_dev, rc_keys[buffer[4] - 1], 0);
-		input_sync(dec->rc_input_dev);
-	}
-
-exit:	retval = usb_submit_urb(urb, GFP_ATOMIC);
-	if(retval)
-		printk("%s - usb_commit_urb failed with result: %d\n",
-			__func__, retval);
-}
-
-static u16 crc16(u16 crc, const u8 *buf, size_t len)
-{
-	u16 tmp;
-
-	while (len--) {
-		crc ^= *buf++;
-		crc ^= (u8)crc >> 4;
-		tmp = (u8)crc;
-		crc ^= (tmp ^ (tmp << 1)) << 4;
-	}
-	return crc;
-}
-
-static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command,
-				  int param_length, const u8 params[],
-				  int *result_length, u8 cmd_result[])
-{
-	int result, actual_len, i;
-	u8 *b;
-
-	dprintk("%s\n", __func__);
-
-	b = kmalloc(COMMAND_PACKET_SIZE + 4, GFP_KERNEL);
-	if (!b)
-		return -ENOMEM;
-
-	if ((result = mutex_lock_interruptible(&dec->usb_mutex))) {
-		kfree(b);
-		printk("%s: Failed to lock usb mutex.\n", __func__);
-		return result;
-	}
-
-	b[0] = 0xaa;
-	b[1] = ++dec->trans_count;
-	b[2] = command;
-	b[3] = param_length;
-
-	if (params)
-		memcpy(&b[4], params, param_length);
-
-	if (debug) {
-		printk("%s: command: ", __func__);
-		for (i = 0; i < param_length + 4; i++)
-			printk("0x%02X ", b[i]);
-		printk("\n");
-	}
-
-	result = usb_bulk_msg(dec->udev, dec->command_pipe, b,
-			      COMMAND_PACKET_SIZE + 4, &actual_len, 1000);
-
-	if (result) {
-		printk("%s: command bulk message failed: error %d\n",
-		       __func__, result);
-		mutex_unlock(&dec->usb_mutex);
-		kfree(b);
-		return result;
-	}
-
-	result = usb_bulk_msg(dec->udev, dec->result_pipe, b,
-			      COMMAND_PACKET_SIZE + 4, &actual_len, 1000);
-
-	if (result) {
-		printk("%s: result bulk message failed: error %d\n",
-		       __func__, result);
-		mutex_unlock(&dec->usb_mutex);
-		kfree(b);
-		return result;
-	} else {
-		if (debug) {
-			printk("%s: result: ", __func__);
-			for (i = 0; i < actual_len; i++)
-				printk("0x%02X ", b[i]);
-			printk("\n");
-		}
-
-		if (result_length)
-			*result_length = b[3];
-		if (cmd_result && b[3] > 0)
-			memcpy(cmd_result, &b[4], b[3]);
-
-		mutex_unlock(&dec->usb_mutex);
-
-		kfree(b);
-		return 0;
-	}
-}
-
-static int ttusb_dec_get_stb_state (struct ttusb_dec *dec, unsigned int *mode,
-				    unsigned int *model, unsigned int *version)
-{
-	u8 c[COMMAND_PACKET_SIZE];
-	int c_length;
-	int result;
-	__be32 tmp;
-
-	dprintk("%s\n", __func__);
-
-	result = ttusb_dec_send_command(dec, 0x08, 0, NULL, &c_length, c);
-	if (result)
-		return result;
-
-	if (c_length >= 0x0c) {
-		if (mode != NULL) {
-			memcpy(&tmp, c, 4);
-			*mode = ntohl(tmp);
-		}
-		if (model != NULL) {
-			memcpy(&tmp, &c[4], 4);
-			*model = ntohl(tmp);
-		}
-		if (version != NULL) {
-			memcpy(&tmp, &c[8], 4);
-			*version = ntohl(tmp);
-		}
-		return 0;
-	} else {
-		return -1;
-	}
-}
-
-static int ttusb_dec_audio_pes2ts_cb(void *priv, unsigned char *data)
-{
-	struct ttusb_dec *dec = priv;
-
-	dec->audio_filter->feed->cb.ts(data, 188, NULL, 0,
-				       &dec->audio_filter->feed->feed.ts,
-				       DMX_OK);
-
-	return 0;
-}
-
-static int ttusb_dec_video_pes2ts_cb(void *priv, unsigned char *data)
-{
-	struct ttusb_dec *dec = priv;
-
-	dec->video_filter->feed->cb.ts(data, 188, NULL, 0,
-				       &dec->video_filter->feed->feed.ts,
-				       DMX_OK);
-
-	return 0;
-}
-
-static void ttusb_dec_set_pids(struct ttusb_dec *dec)
-{
-	u8 b[] = { 0x00, 0x00, 0x00, 0x00,
-		   0x00, 0x00, 0xff, 0xff,
-		   0xff, 0xff, 0xff, 0xff };
-
-	__be16 pcr = htons(dec->pid[DMX_PES_PCR]);
-	__be16 audio = htons(dec->pid[DMX_PES_AUDIO]);
-	__be16 video = htons(dec->pid[DMX_PES_VIDEO]);
-
-	dprintk("%s\n", __func__);
-
-	memcpy(&b[0], &pcr, 2);
-	memcpy(&b[2], &audio, 2);
-	memcpy(&b[4], &video, 2);
-
-	ttusb_dec_send_command(dec, 0x50, sizeof(b), b, NULL, NULL);
-
-	dvb_filter_pes2ts_init(&dec->a_pes2ts, dec->pid[DMX_PES_AUDIO],
-			       ttusb_dec_audio_pes2ts_cb, dec);
-	dvb_filter_pes2ts_init(&dec->v_pes2ts, dec->pid[DMX_PES_VIDEO],
-			       ttusb_dec_video_pes2ts_cb, dec);
-	dec->v_pes_length = 0;
-	dec->v_pes_postbytes = 0;
-}
-
-static void ttusb_dec_process_pva(struct ttusb_dec *dec, u8 *pva, int length)
-{
-	if (length < 8) {
-		printk("%s: packet too short - discarding\n", __func__);
-		return;
-	}
-
-	if (length > 8 + MAX_PVA_LENGTH) {
-		printk("%s: packet too long - discarding\n", __func__);
-		return;
-	}
-
-	switch (pva[2]) {
-
-	case 0x01: {		/* VideoStream */
-		int prebytes = pva[5] & 0x03;
-		int postbytes = (pva[5] & 0x0c) >> 2;
-		__be16 v_pes_payload_length;
-
-		if (output_pva) {
-			dec->video_filter->feed->cb.ts(pva, length, NULL, 0,
-				&dec->video_filter->feed->feed.ts, DMX_OK);
-			return;
-		}
-
-		if (dec->v_pes_postbytes > 0 &&
-		    dec->v_pes_postbytes == prebytes) {
-			memcpy(&dec->v_pes[dec->v_pes_length],
-			       &pva[12], prebytes);
-
-			dvb_filter_pes2ts(&dec->v_pes2ts, dec->v_pes,
-					  dec->v_pes_length + prebytes, 1);
-		}
-
-		if (pva[5] & 0x10) {
-			dec->v_pes[7] = 0x80;
-			dec->v_pes[8] = 0x05;
-
-			dec->v_pes[9] = 0x21 | ((pva[8] & 0xc0) >> 5);
-			dec->v_pes[10] = ((pva[8] & 0x3f) << 2) |
-					 ((pva[9] & 0xc0) >> 6);
-			dec->v_pes[11] = 0x01 |
-					 ((pva[9] & 0x3f) << 2) |
-					 ((pva[10] & 0x80) >> 6);
-			dec->v_pes[12] = ((pva[10] & 0x7f) << 1) |
-					 ((pva[11] & 0xc0) >> 7);
-			dec->v_pes[13] = 0x01 | ((pva[11] & 0x7f) << 1);
-
-			memcpy(&dec->v_pes[14], &pva[12 + prebytes],
-			       length - 12 - prebytes);
-			dec->v_pes_length = 14 + length - 12 - prebytes;
-		} else {
-			dec->v_pes[7] = 0x00;
-			dec->v_pes[8] = 0x00;
-
-			memcpy(&dec->v_pes[9], &pva[8], length - 8);
-			dec->v_pes_length = 9 + length - 8;
-		}
-
-		dec->v_pes_postbytes = postbytes;
-
-		if (dec->v_pes[9 + dec->v_pes[8]] == 0x00 &&
-		    dec->v_pes[10 + dec->v_pes[8]] == 0x00 &&
-		    dec->v_pes[11 + dec->v_pes[8]] == 0x01)
-			dec->v_pes[6] = 0x84;
-		else
-			dec->v_pes[6] = 0x80;
-
-		v_pes_payload_length = htons(dec->v_pes_length - 6 +
-					     postbytes);
-		memcpy(&dec->v_pes[4], &v_pes_payload_length, 2);
-
-		if (postbytes == 0)
-			dvb_filter_pes2ts(&dec->v_pes2ts, dec->v_pes,
-					  dec->v_pes_length, 1);
-
-		break;
-	}
-
-	case 0x02:		/* MainAudioStream */
-		if (output_pva) {
-			dec->audio_filter->feed->cb.ts(pva, length, NULL, 0,
-				&dec->audio_filter->feed->feed.ts, DMX_OK);
-			return;
-		}
-
-		dvb_filter_pes2ts(&dec->a_pes2ts, &pva[8], length - 8,
-				  pva[5] & 0x10);
-		break;
-
-	default:
-		printk("%s: unknown PVA type: %02x.\n", __func__,
-		       pva[2]);
-		break;
-	}
-}
-
-static void ttusb_dec_process_filter(struct ttusb_dec *dec, u8 *packet,
-				     int length)
-{
-	struct list_head *item;
-	struct filter_info *finfo;
-	struct dvb_demux_filter *filter = NULL;
-	unsigned long flags;
-	u8 sid;
-
-	sid = packet[1];
-	spin_lock_irqsave(&dec->filter_info_list_lock, flags);
-	for (item = dec->filter_info_list.next; item != &dec->filter_info_list;
-	     item = item->next) {
-		finfo = list_entry(item, struct filter_info, filter_info_list);
-		if (finfo->stream_id == sid) {
-			filter = finfo->filter;
-			break;
-		}
-	}
-	spin_unlock_irqrestore(&dec->filter_info_list_lock, flags);
-
-	if (filter)
-		filter->feed->cb.sec(&packet[2], length - 2, NULL, 0,
-				     &filter->filter, DMX_OK);
-}
-
-static void ttusb_dec_process_packet(struct ttusb_dec *dec)
-{
-	int i;
-	u16 csum = 0;
-	u16 packet_id;
-
-	if (dec->packet_length % 2) {
-		printk("%s: odd sized packet - discarding\n", __func__);
-		return;
-	}
-
-	for (i = 0; i < dec->packet_length; i += 2)
-		csum ^= ((dec->packet[i] << 8) + dec->packet[i + 1]);
-
-	if (csum) {
-		printk("%s: checksum failed - discarding\n", __func__);
-		return;
-	}
-
-	packet_id = dec->packet[dec->packet_length - 4] << 8;
-	packet_id += dec->packet[dec->packet_length - 3];
-
-	if ((packet_id != dec->next_packet_id) && dec->next_packet_id) {
-		printk("%s: warning: lost packets between %u and %u\n",
-		       __func__, dec->next_packet_id - 1, packet_id);
-	}
-
-	if (packet_id == 0xffff)
-		dec->next_packet_id = 0x8000;
-	else
-		dec->next_packet_id = packet_id + 1;
-
-	switch (dec->packet_type) {
-	case TTUSB_DEC_PACKET_PVA:
-		if (dec->pva_stream_count)
-			ttusb_dec_process_pva(dec, dec->packet,
-					      dec->packet_payload_length);
-		break;
-
-	case TTUSB_DEC_PACKET_SECTION:
-		if (dec->filter_stream_count)
-			ttusb_dec_process_filter(dec, dec->packet,
-						 dec->packet_payload_length);
-		break;
-
-	case TTUSB_DEC_PACKET_EMPTY:
-		break;
-	}
-}
-
-static void swap_bytes(u8 *b, int length)
-{
-	u8 c;
-
-	length -= length % 2;
-	for (; length; b += 2, length -= 2) {
-		c = *b;
-		*b = *(b + 1);
-		*(b + 1) = c;
-	}
-}
-
-static void ttusb_dec_process_urb_frame(struct ttusb_dec *dec, u8 *b,
-					int length)
-{
-	swap_bytes(b, length);
-
-	while (length) {
-		switch (dec->packet_state) {
-
-		case 0:
-		case 1:
-		case 2:
-			if (*b++ == 0xaa)
-				dec->packet_state++;
-			else
-				dec->packet_state = 0;
-
-			length--;
-			break;
-
-		case 3:
-			if (*b == 0x00) {
-				dec->packet_state++;
-				dec->packet_length = 0;
-			} else if (*b != 0xaa) {
-				dec->packet_state = 0;
-			}
-
-			b++;
-			length--;
-			break;
-
-		case 4:
-			dec->packet[dec->packet_length++] = *b++;
-
-			if (dec->packet_length == 2) {
-				if (dec->packet[0] == 'A' &&
-				    dec->packet[1] == 'V') {
-					dec->packet_type =
-						TTUSB_DEC_PACKET_PVA;
-					dec->packet_state++;
-				} else if (dec->packet[0] == 'S') {
-					dec->packet_type =
-						TTUSB_DEC_PACKET_SECTION;
-					dec->packet_state++;
-				} else if (dec->packet[0] == 0x00) {
-					dec->packet_type =
-						TTUSB_DEC_PACKET_EMPTY;
-					dec->packet_payload_length = 2;
-					dec->packet_state = 7;
-				} else {
-					printk("%s: unknown packet type: "
-					       "%02x%02x\n", __func__,
-					       dec->packet[0], dec->packet[1]);
-					dec->packet_state = 0;
-				}
-			}
-
-			length--;
-			break;
-
-		case 5:
-			dec->packet[dec->packet_length++] = *b++;
-
-			if (dec->packet_type == TTUSB_DEC_PACKET_PVA &&
-			    dec->packet_length == 8) {
-				dec->packet_state++;
-				dec->packet_payload_length = 8 +
-					(dec->packet[6] << 8) +
-					dec->packet[7];
-			} else if (dec->packet_type ==
-					TTUSB_DEC_PACKET_SECTION &&
-				   dec->packet_length == 5) {
-				dec->packet_state++;
-				dec->packet_payload_length = 5 +
-					((dec->packet[3] & 0x0f) << 8) +
-					dec->packet[4];
-			}
-
-			length--;
-			break;
-
-		case 6: {
-			int remainder = dec->packet_payload_length -
-					dec->packet_length;
-
-			if (length >= remainder) {
-				memcpy(dec->packet + dec->packet_length,
-				       b, remainder);
-				dec->packet_length += remainder;
-				b += remainder;
-				length -= remainder;
-				dec->packet_state++;
-			} else {
-				memcpy(&dec->packet[dec->packet_length],
-				       b, length);
-				dec->packet_length += length;
-				length = 0;
-			}
-
-			break;
-		}
-
-		case 7: {
-			int tail = 4;
-
-			dec->packet[dec->packet_length++] = *b++;
-
-			if (dec->packet_type == TTUSB_DEC_PACKET_SECTION &&
-			    dec->packet_payload_length % 2)
-				tail++;
-
-			if (dec->packet_length ==
-			    dec->packet_payload_length + tail) {
-				ttusb_dec_process_packet(dec);
-				dec->packet_state = 0;
-			}
-
-			length--;
-			break;
-		}
-
-		default:
-			printk("%s: illegal packet state encountered.\n",
-			       __func__);
-			dec->packet_state = 0;
-		}
-	}
-}
-
-static void ttusb_dec_process_urb_frame_list(unsigned long data)
-{
-	struct ttusb_dec *dec = (struct ttusb_dec *)data;
-	struct list_head *item;
-	struct urb_frame *frame;
-	unsigned long flags;
-
-	while (1) {
-		spin_lock_irqsave(&dec->urb_frame_list_lock, flags);
-		if ((item = dec->urb_frame_list.next) != &dec->urb_frame_list) {
-			frame = list_entry(item, struct urb_frame,
-					   urb_frame_list);
-			list_del(&frame->urb_frame_list);
-		} else {
-			spin_unlock_irqrestore(&dec->urb_frame_list_lock,
-					       flags);
-			return;
-		}
-		spin_unlock_irqrestore(&dec->urb_frame_list_lock, flags);
-
-		ttusb_dec_process_urb_frame(dec, frame->data, frame->length);
-		kfree(frame);
-	}
-}
-
-static void ttusb_dec_process_urb(struct urb *urb)
-{
-	struct ttusb_dec *dec = urb->context;
-
-	if (!urb->status) {
-		int i;
-
-		for (i = 0; i < FRAMES_PER_ISO_BUF; i++) {
-			struct usb_iso_packet_descriptor *d;
-			u8 *b;
-			int length;
-			struct urb_frame *frame;
-
-			d = &urb->iso_frame_desc[i];
-			b = urb->transfer_buffer + d->offset;
-			length = d->actual_length;
-
-			if ((frame = kmalloc(sizeof(struct urb_frame),
-					     GFP_ATOMIC))) {
-				unsigned long flags;
-
-				memcpy(frame->data, b, length);
-				frame->length = length;
-
-				spin_lock_irqsave(&dec->urb_frame_list_lock,
-						     flags);
-				list_add_tail(&frame->urb_frame_list,
-					      &dec->urb_frame_list);
-				spin_unlock_irqrestore(&dec->urb_frame_list_lock,
-						       flags);
-
-				tasklet_schedule(&dec->urb_tasklet);
-			}
-		}
-	} else {
-		 /* -ENOENT is expected when unlinking urbs */
-		if (urb->status != -ENOENT)
-			dprintk("%s: urb error: %d\n", __func__,
-				urb->status);
-	}
-
-	if (dec->iso_stream_count)
-		usb_submit_urb(urb, GFP_ATOMIC);
-}
-
-static void ttusb_dec_setup_urbs(struct ttusb_dec *dec)
-{
-	int i, j, buffer_offset = 0;
-
-	dprintk("%s\n", __func__);
-
-	for (i = 0; i < ISO_BUF_COUNT; i++) {
-		int frame_offset = 0;
-		struct urb *urb = dec->iso_urb[i];
-
-		urb->dev = dec->udev;
-		urb->context = dec;
-		urb->complete = ttusb_dec_process_urb;
-		urb->pipe = dec->in_pipe;
-		urb->transfer_flags = URB_ISO_ASAP;
-		urb->interval = 1;
-		urb->number_of_packets = FRAMES_PER_ISO_BUF;
-		urb->transfer_buffer_length = ISO_FRAME_SIZE *
-					      FRAMES_PER_ISO_BUF;
-		urb->transfer_buffer = dec->iso_buffer + buffer_offset;
-		buffer_offset += ISO_FRAME_SIZE * FRAMES_PER_ISO_BUF;
-
-		for (j = 0; j < FRAMES_PER_ISO_BUF; j++) {
-			urb->iso_frame_desc[j].offset = frame_offset;
-			urb->iso_frame_desc[j].length = ISO_FRAME_SIZE;
-			frame_offset += ISO_FRAME_SIZE;
-		}
-	}
-}
-
-static void ttusb_dec_stop_iso_xfer(struct ttusb_dec *dec)
-{
-	int i;
-
-	dprintk("%s\n", __func__);
-
-	if (mutex_lock_interruptible(&dec->iso_mutex))
-		return;
-
-	dec->iso_stream_count--;
-
-	if (!dec->iso_stream_count) {
-		for (i = 0; i < ISO_BUF_COUNT; i++)
-			usb_kill_urb(dec->iso_urb[i]);
-	}
-
-	mutex_unlock(&dec->iso_mutex);
-}
-
-/* Setting the interface of the DEC tends to take down the USB communications
- * for a short period, so it's important not to call this function just before
- * trying to talk to it.
- */
-static int ttusb_dec_set_interface(struct ttusb_dec *dec,
-				   enum ttusb_dec_interface interface)
-{
-	int result = 0;
-	u8 b[] = { 0x05 };
-
-	if (interface != dec->interface) {
-		switch (interface) {
-		case TTUSB_DEC_INTERFACE_INITIAL:
-			result = usb_set_interface(dec->udev, 0, 0);
-			break;
-		case TTUSB_DEC_INTERFACE_IN:
-			result = ttusb_dec_send_command(dec, 0x80, sizeof(b),
-							b, NULL, NULL);
-			if (result)
-				return result;
-			result = usb_set_interface(dec->udev, 0, 8);
-			break;
-		case TTUSB_DEC_INTERFACE_OUT:
-			result = usb_set_interface(dec->udev, 0, 1);
-			break;
-		}
-
-		if (result)
-			return result;
-
-		dec->interface = interface;
-	}
-
-	return 0;
-}
-
-static int ttusb_dec_start_iso_xfer(struct ttusb_dec *dec)
-{
-	int i, result;
-
-	dprintk("%s\n", __func__);
-
-	if (mutex_lock_interruptible(&dec->iso_mutex))
-		return -EAGAIN;
-
-	if (!dec->iso_stream_count) {
-		ttusb_dec_setup_urbs(dec);
-
-		dec->packet_state = 0;
-		dec->v_pes_postbytes = 0;
-		dec->next_packet_id = 0;
-
-		for (i = 0; i < ISO_BUF_COUNT; i++) {
-			if ((result = usb_submit_urb(dec->iso_urb[i],
-						     GFP_ATOMIC))) {
-				printk("%s: failed urb submission %d: "
-				       "error %d\n", __func__, i, result);
-
-				while (i) {
-					usb_kill_urb(dec->iso_urb[i - 1]);
-					i--;
-				}
-
-				mutex_unlock(&dec->iso_mutex);
-				return result;
-			}
-		}
-	}
-
-	dec->iso_stream_count++;
-
-	mutex_unlock(&dec->iso_mutex);
-
-	return 0;
-}
-
-static int ttusb_dec_start_ts_feed(struct dvb_demux_feed *dvbdmxfeed)
-{
-	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
-	struct ttusb_dec *dec = dvbdmx->priv;
-	u8 b0[] = { 0x05 };
-	int result = 0;
-
-	dprintk("%s\n", __func__);
-
-	dprintk("  ts_type:");
-
-	if (dvbdmxfeed->ts_type & TS_DECODER)
-		dprintk(" TS_DECODER");
-
-	if (dvbdmxfeed->ts_type & TS_PACKET)
-		dprintk(" TS_PACKET");
-
-	if (dvbdmxfeed->ts_type & TS_PAYLOAD_ONLY)
-		dprintk(" TS_PAYLOAD_ONLY");
-
-	dprintk("\n");
-
-	switch (dvbdmxfeed->pes_type) {
-
-	case DMX_TS_PES_VIDEO:
-		dprintk("  pes_type: DMX_TS_PES_VIDEO\n");
-		dec->pid[DMX_PES_PCR] = dvbdmxfeed->pid;
-		dec->pid[DMX_PES_VIDEO] = dvbdmxfeed->pid;
-		dec->video_filter = dvbdmxfeed->filter;
-		ttusb_dec_set_pids(dec);
-		break;
-
-	case DMX_TS_PES_AUDIO:
-		dprintk("  pes_type: DMX_TS_PES_AUDIO\n");
-		dec->pid[DMX_PES_AUDIO] = dvbdmxfeed->pid;
-		dec->audio_filter = dvbdmxfeed->filter;
-		ttusb_dec_set_pids(dec);
-		break;
-
-	case DMX_TS_PES_TELETEXT:
-		dec->pid[DMX_PES_TELETEXT] = dvbdmxfeed->pid;
-		dprintk("  pes_type: DMX_TS_PES_TELETEXT(not supported)\n");
-		return -ENOSYS;
-
-	case DMX_TS_PES_PCR:
-		dprintk("  pes_type: DMX_TS_PES_PCR\n");
-		dec->pid[DMX_PES_PCR] = dvbdmxfeed->pid;
-		ttusb_dec_set_pids(dec);
-		break;
-
-	case DMX_TS_PES_OTHER:
-		dprintk("  pes_type: DMX_TS_PES_OTHER(not supported)\n");
-		return -ENOSYS;
-
-	default:
-		dprintk("  pes_type: unknown (%d)\n", dvbdmxfeed->pes_type);
-		return -EINVAL;
-
-	}
-
-	result = ttusb_dec_send_command(dec, 0x80, sizeof(b0), b0, NULL, NULL);
-	if (result)
-		return result;
-
-	dec->pva_stream_count++;
-	return ttusb_dec_start_iso_xfer(dec);
-}
-
-static int ttusb_dec_start_sec_feed(struct dvb_demux_feed *dvbdmxfeed)
-{
-	struct ttusb_dec *dec = dvbdmxfeed->demux->priv;
-	u8 b0[] = { 0x00, 0x00, 0x00, 0x01,
-		    0x00, 0x00, 0x00, 0x00,
-		    0x00, 0x00, 0x00, 0x00,
-		    0x00, 0x00, 0x00, 0x00,
-		    0x00, 0xff, 0x00, 0x00,
-		    0x00, 0x00, 0x00, 0x00,
-		    0x00, 0x00, 0x00, 0x00,
-		    0x00 };
-	__be16 pid;
-	u8 c[COMMAND_PACKET_SIZE];
-	int c_length;
-	int result;
-	struct filter_info *finfo;
-	unsigned long flags;
-	u8 x = 1;
-
-	dprintk("%s\n", __func__);
-
-	pid = htons(dvbdmxfeed->pid);
-	memcpy(&b0[0], &pid, 2);
-	memcpy(&b0[4], &x, 1);
-	memcpy(&b0[5], &dvbdmxfeed->filter->filter.filter_value[0], 1);
-
-	result = ttusb_dec_send_command(dec, 0x60, sizeof(b0), b0,
-					&c_length, c);
-
-	if (!result) {
-		if (c_length == 2) {
-			if (!(finfo = kmalloc(sizeof(struct filter_info),
-					      GFP_ATOMIC)))
-				return -ENOMEM;
-
-			finfo->stream_id = c[1];
-			finfo->filter = dvbdmxfeed->filter;
-
-			spin_lock_irqsave(&dec->filter_info_list_lock, flags);
-			list_add_tail(&finfo->filter_info_list,
-				      &dec->filter_info_list);
-			spin_unlock_irqrestore(&dec->filter_info_list_lock,
-					       flags);
-
-			dvbdmxfeed->priv = finfo;
-
-			dec->filter_stream_count++;
-			return ttusb_dec_start_iso_xfer(dec);
-		}
-
-		return -EAGAIN;
-	} else
-		return result;
-}
-
-static int ttusb_dec_start_feed(struct dvb_demux_feed *dvbdmxfeed)
-{
-	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
-
-	dprintk("%s\n", __func__);
-
-	if (!dvbdmx->dmx.frontend)
-		return -EINVAL;
-
-	dprintk("  pid: 0x%04X\n", dvbdmxfeed->pid);
-
-	switch (dvbdmxfeed->type) {
-
-	case DMX_TYPE_TS:
-		return ttusb_dec_start_ts_feed(dvbdmxfeed);
-		break;
-
-	case DMX_TYPE_SEC:
-		return ttusb_dec_start_sec_feed(dvbdmxfeed);
-		break;
-
-	default:
-		dprintk("  type: unknown (%d)\n", dvbdmxfeed->type);
-		return -EINVAL;
-
-	}
-}
-
-static int ttusb_dec_stop_ts_feed(struct dvb_demux_feed *dvbdmxfeed)
-{
-	struct ttusb_dec *dec = dvbdmxfeed->demux->priv;
-	u8 b0[] = { 0x00 };
-
-	ttusb_dec_send_command(dec, 0x81, sizeof(b0), b0, NULL, NULL);
-
-	dec->pva_stream_count--;
-
-	ttusb_dec_stop_iso_xfer(dec);
-
-	return 0;
-}
-
-static int ttusb_dec_stop_sec_feed(struct dvb_demux_feed *dvbdmxfeed)
-{
-	struct ttusb_dec *dec = dvbdmxfeed->demux->priv;
-	u8 b0[] = { 0x00, 0x00 };
-	struct filter_info *finfo = (struct filter_info *)dvbdmxfeed->priv;
-	unsigned long flags;
-
-	b0[1] = finfo->stream_id;
-	spin_lock_irqsave(&dec->filter_info_list_lock, flags);
-	list_del(&finfo->filter_info_list);
-	spin_unlock_irqrestore(&dec->filter_info_list_lock, flags);
-	kfree(finfo);
-	ttusb_dec_send_command(dec, 0x62, sizeof(b0), b0, NULL, NULL);
-
-	dec->filter_stream_count--;
-
-	ttusb_dec_stop_iso_xfer(dec);
-
-	return 0;
-}
-
-static int ttusb_dec_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
-{
-	dprintk("%s\n", __func__);
-
-	switch (dvbdmxfeed->type) {
-	case DMX_TYPE_TS:
-		return ttusb_dec_stop_ts_feed(dvbdmxfeed);
-		break;
-
-	case DMX_TYPE_SEC:
-		return ttusb_dec_stop_sec_feed(dvbdmxfeed);
-		break;
-	}
-
-	return 0;
-}
-
-static void ttusb_dec_free_iso_urbs(struct ttusb_dec *dec)
-{
-	int i;
-
-	dprintk("%s\n", __func__);
-
-	for (i = 0; i < ISO_BUF_COUNT; i++)
-		usb_free_urb(dec->iso_urb[i]);
-
-	pci_free_consistent(NULL,
-			    ISO_FRAME_SIZE * (FRAMES_PER_ISO_BUF *
-					      ISO_BUF_COUNT),
-			    dec->iso_buffer, dec->iso_dma_handle);
-}
-
-static int ttusb_dec_alloc_iso_urbs(struct ttusb_dec *dec)
-{
-	int i;
-
-	dprintk("%s\n", __func__);
-
-	dec->iso_buffer = pci_alloc_consistent(NULL,
-					       ISO_FRAME_SIZE *
-					       (FRAMES_PER_ISO_BUF *
-						ISO_BUF_COUNT),
-					       &dec->iso_dma_handle);
-
-	if (!dec->iso_buffer) {
-		dprintk("%s: pci_alloc_consistent - not enough memory\n",
-			__func__);
-		return -ENOMEM;
-	}
-
-	memset(dec->iso_buffer, 0,
-	       ISO_FRAME_SIZE * (FRAMES_PER_ISO_BUF * ISO_BUF_COUNT));
-
-	for (i = 0; i < ISO_BUF_COUNT; i++) {
-		struct urb *urb;
-
-		if (!(urb = usb_alloc_urb(FRAMES_PER_ISO_BUF, GFP_ATOMIC))) {
-			ttusb_dec_free_iso_urbs(dec);
-			return -ENOMEM;
-		}
-
-		dec->iso_urb[i] = urb;
-	}
-
-	ttusb_dec_setup_urbs(dec);
-
-	return 0;
-}
-
-static void ttusb_dec_init_tasklet(struct ttusb_dec *dec)
-{
-	spin_lock_init(&dec->urb_frame_list_lock);
-	INIT_LIST_HEAD(&dec->urb_frame_list);
-	tasklet_init(&dec->urb_tasklet, ttusb_dec_process_urb_frame_list,
-		     (unsigned long)dec);
-}
-
-static int ttusb_init_rc( struct ttusb_dec *dec)
-{
-	struct input_dev *input_dev;
-	u8 b[] = { 0x00, 0x01 };
-	int i;
-	int err;
-
-	usb_make_path(dec->udev, dec->rc_phys, sizeof(dec->rc_phys));
-	strlcat(dec->rc_phys, "/input0", sizeof(dec->rc_phys));
-
-	input_dev = input_allocate_device();
-	if (!input_dev)
-		return -ENOMEM;
-
-	input_dev->name = "ttusb_dec remote control";
-	input_dev->phys = dec->rc_phys;
-	input_dev->evbit[0] = BIT_MASK(EV_KEY);
-	input_dev->keycodesize = sizeof(u16);
-	input_dev->keycodemax = 0x1a;
-	input_dev->keycode = rc_keys;
-
-	for (i = 0; i < ARRAY_SIZE(rc_keys); i++)
-		  set_bit(rc_keys[i], input_dev->keybit);
-
-	err = input_register_device(input_dev);
-	if (err) {
-		input_free_device(input_dev);
-		return err;
-	}
-
-	dec->rc_input_dev = input_dev;
-	if (usb_submit_urb(dec->irq_urb, GFP_KERNEL))
-		printk("%s: usb_submit_urb failed\n",__func__);
-	/* enable irq pipe */
-	ttusb_dec_send_command(dec,0xb0,sizeof(b),b,NULL,NULL);
-
-	return 0;
-}
-
-static void ttusb_dec_init_v_pes(struct ttusb_dec *dec)
-{
-	dprintk("%s\n", __func__);
-
-	dec->v_pes[0] = 0x00;
-	dec->v_pes[1] = 0x00;
-	dec->v_pes[2] = 0x01;
-	dec->v_pes[3] = 0xe0;
-}
-
-static int ttusb_dec_init_usb(struct ttusb_dec *dec)
-{
-	dprintk("%s\n", __func__);
-
-	mutex_init(&dec->usb_mutex);
-	mutex_init(&dec->iso_mutex);
-
-	dec->command_pipe = usb_sndbulkpipe(dec->udev, COMMAND_PIPE);
-	dec->result_pipe = usb_rcvbulkpipe(dec->udev, RESULT_PIPE);
-	dec->in_pipe = usb_rcvisocpipe(dec->udev, IN_PIPE);
-	dec->out_pipe = usb_sndisocpipe(dec->udev, OUT_PIPE);
-	dec->irq_pipe = usb_rcvintpipe(dec->udev, IRQ_PIPE);
-
-	if(enable_rc) {
-		dec->irq_urb = usb_alloc_urb(0, GFP_KERNEL);
-		if(!dec->irq_urb) {
-			return -ENOMEM;
-		}
-		dec->irq_buffer = usb_alloc_coherent(dec->udev,IRQ_PACKET_SIZE,
-					GFP_ATOMIC, &dec->irq_dma_handle);
-		if(!dec->irq_buffer) {
-			usb_free_urb(dec->irq_urb);
-			return -ENOMEM;
-		}
-		usb_fill_int_urb(dec->irq_urb, dec->udev,dec->irq_pipe,
-				 dec->irq_buffer, IRQ_PACKET_SIZE,
-				 ttusb_dec_handle_irq, dec, 1);
-		dec->irq_urb->transfer_dma = dec->irq_dma_handle;
-		dec->irq_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
-	}
-
-	return ttusb_dec_alloc_iso_urbs(dec);
-}
-
-static int ttusb_dec_boot_dsp(struct ttusb_dec *dec)
-{
-	int i, j, actual_len, result, size, trans_count;
-	u8 b0[] = { 0x00, 0x00, 0x00, 0x00,
-		    0x00, 0x00, 0x00, 0x00,
-		    0x61, 0x00 };
-	u8 b1[] = { 0x61 };
-	u8 *b;
-	char idstring[21];
-	const u8 *firmware = NULL;
-	size_t firmware_size = 0;
-	u16 firmware_csum = 0;
-	__be16 firmware_csum_ns;
-	__be32 firmware_size_nl;
-	u32 crc32_csum, crc32_check;
-	__be32 tmp;
-	const struct firmware *fw_entry = NULL;
-
-	dprintk("%s\n", __func__);
-
-	if (request_firmware(&fw_entry, dec->firmware_name, &dec->udev->dev)) {
-		printk(KERN_ERR "%s: Firmware (%s) unavailable.\n",
-		       __func__, dec->firmware_name);
-		return 1;
-	}
-
-	firmware = fw_entry->data;
-	firmware_size = fw_entry->size;
-
-	if (firmware_size < 60) {
-		printk("%s: firmware size too small for DSP code (%zu < 60).\n",
-			__func__, firmware_size);
-		release_firmware(fw_entry);
-		return -1;
-	}
-
-	/* a 32 bit checksum over the first 56 bytes of the DSP Code is stored
-	   at offset 56 of file, so use it to check if the firmware file is
-	   valid. */
-	crc32_csum = crc32(~0L, firmware, 56) ^ ~0L;
-	memcpy(&tmp, &firmware[56], 4);
-	crc32_check = ntohl(tmp);
-	if (crc32_csum != crc32_check) {
-		printk("%s: crc32 check of DSP code failed (calculated "
-		       "0x%08x != 0x%08x in file), file invalid.\n",
-			__func__, crc32_csum, crc32_check);
-		release_firmware(fw_entry);
-		return -1;
-	}
-	memcpy(idstring, &firmware[36], 20);
-	idstring[20] = '\0';
-	printk(KERN_INFO "ttusb_dec: found DSP code \"%s\".\n", idstring);
-
-	firmware_size_nl = htonl(firmware_size);
-	memcpy(b0, &firmware_size_nl, 4);
-	firmware_csum = crc16(~0, firmware, firmware_size) ^ ~0;
-	firmware_csum_ns = htons(firmware_csum);
-	memcpy(&b0[6], &firmware_csum_ns, 2);
-
-	result = ttusb_dec_send_command(dec, 0x41, sizeof(b0), b0, NULL, NULL);
-
-	if (result) {
-		release_firmware(fw_entry);
-		return result;
-	}
-
-	trans_count = 0;
-	j = 0;
-
-	b = kmalloc(ARM_PACKET_SIZE, GFP_KERNEL);
-	if (b == NULL) {
-		release_firmware(fw_entry);
-		return -ENOMEM;
-	}
-
-	for (i = 0; i < firmware_size; i += COMMAND_PACKET_SIZE) {
-		size = firmware_size - i;
-		if (size > COMMAND_PACKET_SIZE)
-			size = COMMAND_PACKET_SIZE;
-
-		b[j + 0] = 0xaa;
-		b[j + 1] = trans_count++;
-		b[j + 2] = 0xf0;
-		b[j + 3] = size;
-		memcpy(&b[j + 4], &firmware[i], size);
-
-		j += COMMAND_PACKET_SIZE + 4;
-
-		if (j >= ARM_PACKET_SIZE) {
-			result = usb_bulk_msg(dec->udev, dec->command_pipe, b,
-					      ARM_PACKET_SIZE, &actual_len,
-					      100);
-			j = 0;
-		} else if (size < COMMAND_PACKET_SIZE) {
-			result = usb_bulk_msg(dec->udev, dec->command_pipe, b,
-					      j - COMMAND_PACKET_SIZE + size,
-					      &actual_len, 100);
-		}
-	}
-
-	result = ttusb_dec_send_command(dec, 0x43, sizeof(b1), b1, NULL, NULL);
-
-	release_firmware(fw_entry);
-	kfree(b);
-
-	return result;
-}
-
-static int ttusb_dec_init_stb(struct ttusb_dec *dec)
-{
-	int result;
-	unsigned int mode = 0, model = 0, version = 0;
-
-	dprintk("%s\n", __func__);
-
-	result = ttusb_dec_get_stb_state(dec, &mode, &model, &version);
-
-	if (!result) {
-		if (!mode) {
-			if (version == 0xABCDEFAB)
-				printk(KERN_INFO "ttusb_dec: no version "
-				       "info in Firmware\n");
-			else
-				printk(KERN_INFO "ttusb_dec: Firmware "
-				       "%x.%02x%c%c\n",
-				       version >> 24, (version >> 16) & 0xff,
-				       (version >> 8) & 0xff, version & 0xff);
-
-			result = ttusb_dec_boot_dsp(dec);
-			if (result)
-				return result;
-			else
-				return 1;
-		} else {
-			/* We can't trust the USB IDs that some firmwares
-			   give the box */
-			switch (model) {
-			case 0x00070001:
-			case 0x00070008:
-			case 0x0007000c:
-				ttusb_dec_set_model(dec, TTUSB_DEC3000S);
-				break;
-			case 0x00070009:
-			case 0x00070013:
-				ttusb_dec_set_model(dec, TTUSB_DEC2000T);
-				break;
-			case 0x00070011:
-				ttusb_dec_set_model(dec, TTUSB_DEC2540T);
-				break;
-			default:
-				printk(KERN_ERR "%s: unknown model returned "
-				       "by firmware (%08x) - please report\n",
-				       __func__, model);
-				return -1;
-				break;
-			}
-
-			if (version >= 0x01770000)
-				dec->can_playback = 1;
-
-			return 0;
-		}
-	}
-	else
-		return result;
-}
-
-static int ttusb_dec_init_dvb(struct ttusb_dec *dec)
-{
-	int result;
-
-	dprintk("%s\n", __func__);
-
-	if ((result = dvb_register_adapter(&dec->adapter,
-					   dec->model_name, THIS_MODULE,
-					   &dec->udev->dev,
-					   adapter_nr)) < 0) {
-		printk("%s: dvb_register_adapter failed: error %d\n",
-		       __func__, result);
-
-		return result;
-	}
-
-	dec->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING;
-
-	dec->demux.priv = (void *)dec;
-	dec->demux.filternum = 31;
-	dec->demux.feednum = 31;
-	dec->demux.start_feed = ttusb_dec_start_feed;
-	dec->demux.stop_feed = ttusb_dec_stop_feed;
-	dec->demux.write_to_decoder = NULL;
-
-	if ((result = dvb_dmx_init(&dec->demux)) < 0) {
-		printk("%s: dvb_dmx_init failed: error %d\n", __func__,
-		       result);
-
-		dvb_unregister_adapter(&dec->adapter);
-
-		return result;
-	}
-
-	dec->dmxdev.filternum = 32;
-	dec->dmxdev.demux = &dec->demux.dmx;
-	dec->dmxdev.capabilities = 0;
-
-	if ((result = dvb_dmxdev_init(&dec->dmxdev, &dec->adapter)) < 0) {
-		printk("%s: dvb_dmxdev_init failed: error %d\n",
-		       __func__, result);
-
-		dvb_dmx_release(&dec->demux);
-		dvb_unregister_adapter(&dec->adapter);
-
-		return result;
-	}
-
-	dec->frontend.source = DMX_FRONTEND_0;
-
-	if ((result = dec->demux.dmx.add_frontend(&dec->demux.dmx,
-						  &dec->frontend)) < 0) {
-		printk("%s: dvb_dmx_init failed: error %d\n", __func__,
-		       result);
-
-		dvb_dmxdev_release(&dec->dmxdev);
-		dvb_dmx_release(&dec->demux);
-		dvb_unregister_adapter(&dec->adapter);
-
-		return result;
-	}
-
-	if ((result = dec->demux.dmx.connect_frontend(&dec->demux.dmx,
-						      &dec->frontend)) < 0) {
-		printk("%s: dvb_dmx_init failed: error %d\n", __func__,
-		       result);
-
-		dec->demux.dmx.remove_frontend(&dec->demux.dmx, &dec->frontend);
-		dvb_dmxdev_release(&dec->dmxdev);
-		dvb_dmx_release(&dec->demux);
-		dvb_unregister_adapter(&dec->adapter);
-
-		return result;
-	}
-
-	dvb_net_init(&dec->adapter, &dec->dvb_net, &dec->demux.dmx);
-
-	return 0;
-}
-
-static void ttusb_dec_exit_dvb(struct ttusb_dec *dec)
-{
-	dprintk("%s\n", __func__);
-
-	dvb_net_release(&dec->dvb_net);
-	dec->demux.dmx.close(&dec->demux.dmx);
-	dec->demux.dmx.remove_frontend(&dec->demux.dmx, &dec->frontend);
-	dvb_dmxdev_release(&dec->dmxdev);
-	dvb_dmx_release(&dec->demux);
-	if (dec->fe) {
-		dvb_unregister_frontend(dec->fe);
-		if (dec->fe->ops.release)
-			dec->fe->ops.release(dec->fe);
-	}
-	dvb_unregister_adapter(&dec->adapter);
-}
-
-static void ttusb_dec_exit_rc(struct ttusb_dec *dec)
-{
-
-	dprintk("%s\n", __func__);
-	/* we have to check whether the irq URB is already submitted.
-	  * As the irq is submitted after the interface is changed,
-	  * this is the best method i figured out.
-	  * Any others?*/
-	if (dec->interface == TTUSB_DEC_INTERFACE_IN)
-		usb_kill_urb(dec->irq_urb);
-
-	usb_free_urb(dec->irq_urb);
-
-	usb_free_coherent(dec->udev,IRQ_PACKET_SIZE,
-			  dec->irq_buffer, dec->irq_dma_handle);
-
-	if (dec->rc_input_dev) {
-		input_unregister_device(dec->rc_input_dev);
-		dec->rc_input_dev = NULL;
-	}
-}
-
-
-static void ttusb_dec_exit_usb(struct ttusb_dec *dec)
-{
-	int i;
-
-	dprintk("%s\n", __func__);
-
-	dec->iso_stream_count = 0;
-
-	for (i = 0; i < ISO_BUF_COUNT; i++)
-		usb_kill_urb(dec->iso_urb[i]);
-
-	ttusb_dec_free_iso_urbs(dec);
-}
-
-static void ttusb_dec_exit_tasklet(struct ttusb_dec *dec)
-{
-	struct list_head *item;
-	struct urb_frame *frame;
-
-	tasklet_kill(&dec->urb_tasklet);
-
-	while ((item = dec->urb_frame_list.next) != &dec->urb_frame_list) {
-		frame = list_entry(item, struct urb_frame, urb_frame_list);
-		list_del(&frame->urb_frame_list);
-		kfree(frame);
-	}
-}
-
-static void ttusb_dec_init_filters(struct ttusb_dec *dec)
-{
-	INIT_LIST_HEAD(&dec->filter_info_list);
-	spin_lock_init(&dec->filter_info_list_lock);
-}
-
-static void ttusb_dec_exit_filters(struct ttusb_dec *dec)
-{
-	struct list_head *item;
-	struct filter_info *finfo;
-
-	while ((item = dec->filter_info_list.next) != &dec->filter_info_list) {
-		finfo = list_entry(item, struct filter_info, filter_info_list);
-		list_del(&finfo->filter_info_list);
-		kfree(finfo);
-	}
-}
-
-static int fe_send_command(struct dvb_frontend* fe, const u8 command,
-			   int param_length, const u8 params[],
-			   int *result_length, u8 cmd_result[])
-{
-	struct ttusb_dec* dec = fe->dvb->priv;
-	return ttusb_dec_send_command(dec, command, param_length, params, result_length, cmd_result);
-}
-
-static struct ttusbdecfe_config fe_config = {
-	.send_command = fe_send_command
-};
-
-static int ttusb_dec_probe(struct usb_interface *intf,
-			   const struct usb_device_id *id)
-{
-	struct usb_device *udev;
-	struct ttusb_dec *dec;
-
-	dprintk("%s\n", __func__);
-
-	udev = interface_to_usbdev(intf);
-
-	if (!(dec = kzalloc(sizeof(struct ttusb_dec), GFP_KERNEL))) {
-		printk("%s: couldn't allocate memory.\n", __func__);
-		return -ENOMEM;
-	}
-
-	usb_set_intfdata(intf, (void *)dec);
-
-	switch (id->idProduct) {
-	case 0x1006:
-		ttusb_dec_set_model(dec, TTUSB_DEC3000S);
-		break;
-
-	case 0x1008:
-		ttusb_dec_set_model(dec, TTUSB_DEC2000T);
-		break;
-
-	case 0x1009:
-		ttusb_dec_set_model(dec, TTUSB_DEC2540T);
-		break;
-	}
-
-	dec->udev = udev;
-
-	if (ttusb_dec_init_usb(dec))
-		return 0;
-	if (ttusb_dec_init_stb(dec)) {
-		ttusb_dec_exit_usb(dec);
-		return 0;
-	}
-	ttusb_dec_init_dvb(dec);
-
-	dec->adapter.priv = dec;
-	switch (id->idProduct) {
-	case 0x1006:
-		dec->fe = ttusbdecfe_dvbs_attach(&fe_config);
-		break;
-
-	case 0x1008:
-	case 0x1009:
-		dec->fe = ttusbdecfe_dvbt_attach(&fe_config);
-		break;
-	}
-
-	if (dec->fe == NULL) {
-		printk("dvb-ttusb-dec: A frontend driver was not found for device [%04x:%04x]\n",
-		       le16_to_cpu(dec->udev->descriptor.idVendor),
-		       le16_to_cpu(dec->udev->descriptor.idProduct));
-	} else {
-		if (dvb_register_frontend(&dec->adapter, dec->fe)) {
-			printk("budget-ci: Frontend registration failed!\n");
-			if (dec->fe->ops.release)
-				dec->fe->ops.release(dec->fe);
-			dec->fe = NULL;
-		}
-	}
-
-	ttusb_dec_init_v_pes(dec);
-	ttusb_dec_init_filters(dec);
-	ttusb_dec_init_tasklet(dec);
-
-	dec->active = 1;
-
-	ttusb_dec_set_interface(dec, TTUSB_DEC_INTERFACE_IN);
-
-	if (enable_rc)
-		ttusb_init_rc(dec);
-
-	return 0;
-}
-
-static void ttusb_dec_disconnect(struct usb_interface *intf)
-{
-	struct ttusb_dec *dec = usb_get_intfdata(intf);
-
-	usb_set_intfdata(intf, NULL);
-
-	dprintk("%s\n", __func__);
-
-	if (dec->active) {
-		ttusb_dec_exit_tasklet(dec);
-		ttusb_dec_exit_filters(dec);
-		if(enable_rc)
-			ttusb_dec_exit_rc(dec);
-		ttusb_dec_exit_usb(dec);
-		ttusb_dec_exit_dvb(dec);
-	}
-
-	kfree(dec);
-}
-
-static void ttusb_dec_set_model(struct ttusb_dec *dec,
-				enum ttusb_dec_model model)
-{
-	dec->model = model;
-
-	switch (model) {
-	case TTUSB_DEC2000T:
-		dec->model_name = "DEC2000-t";
-		dec->firmware_name = "dvb-ttusb-dec-2000t.fw";
-		break;
-
-	case TTUSB_DEC2540T:
-		dec->model_name = "DEC2540-t";
-		dec->firmware_name = "dvb-ttusb-dec-2540t.fw";
-		break;
-
-	case TTUSB_DEC3000S:
-		dec->model_name = "DEC3000-s";
-		dec->firmware_name = "dvb-ttusb-dec-3000s.fw";
-		break;
-	}
-}
-
-static struct usb_device_id ttusb_dec_table[] = {
-	{USB_DEVICE(0x0b48, 0x1006)},	/* DEC3000-s */
-	/*{USB_DEVICE(0x0b48, 0x1007)},	   Unconfirmed */
-	{USB_DEVICE(0x0b48, 0x1008)},	/* DEC2000-t */
-	{USB_DEVICE(0x0b48, 0x1009)},	/* DEC2540-t */
-	{}
-};
-
-static struct usb_driver ttusb_dec_driver = {
-	.name		= "ttusb-dec",
-	.probe		= ttusb_dec_probe,
-	.disconnect	= ttusb_dec_disconnect,
-	.id_table	= ttusb_dec_table,
-};
-
-module_usb_driver(ttusb_dec_driver);
-
-MODULE_AUTHOR("Alex Woods <linux-dvb@giblets.org>");
-MODULE_DESCRIPTION(DRIVER_NAME);
-MODULE_LICENSE("GPL");
-MODULE_DEVICE_TABLE(usb, ttusb_dec_table);
diff --git a/drivers/media/dvb/ttusb-dec/ttusbdecfe.c b/drivers/media/dvb/ttusb-dec/ttusbdecfe.c
deleted file mode 100644
index 5c45c9d..0000000
--- a/drivers/media/dvb/ttusb-dec/ttusbdecfe.c
+++ /dev/null
@@ -1,298 +0,0 @@
-/*
- * TTUSB DEC Frontend Driver
- *
- * Copyright (C) 2003-2004 Alex Woods <linux-dvb@giblets.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 "dvb_frontend.h"
-#include "ttusbdecfe.h"
-
-
-#define LOF_HI			10600000
-#define LOF_LO			9750000
-
-struct ttusbdecfe_state {
-
-	/* configuration settings */
-	const struct ttusbdecfe_config* config;
-
-	struct dvb_frontend frontend;
-
-	u8 hi_band;
-	u8 voltage;
-};
-
-
-static int ttusbdecfe_dvbs_read_status(struct dvb_frontend *fe,
-	fe_status_t *status)
-{
-	*status = FE_HAS_SIGNAL | FE_HAS_VITERBI |
-		FE_HAS_SYNC | FE_HAS_CARRIER | FE_HAS_LOCK;
-	return 0;
-}
-
-
-static int ttusbdecfe_dvbt_read_status(struct dvb_frontend *fe,
-	fe_status_t *status)
-{
-	struct ttusbdecfe_state* state = fe->demodulator_priv;
-	u8 b[] = { 0x00, 0x00, 0x00, 0x00,
-		   0x00, 0x00, 0x00, 0x00 };
-	u8 result[4];
-	int len, ret;
-
-	*status=0;
-
-	ret=state->config->send_command(fe, 0x73, sizeof(b), b, &len, result);
-	if(ret)
-		return ret;
-
-	if(len != 4) {
-		printk(KERN_ERR "%s: unexpected reply\n", __func__);
-		return -EIO;
-	}
-
-	switch(result[3]) {
-		case 1:  /* not tuned yet */
-		case 2:  /* no signal/no lock*/
-			break;
-		case 3:	 /* signal found and locked*/
-			*status = FE_HAS_SIGNAL | FE_HAS_VITERBI |
-			FE_HAS_SYNC | FE_HAS_CARRIER | FE_HAS_LOCK;
-			break;
-		case 4:
-			*status = FE_TIMEDOUT;
-			break;
-		default:
-			pr_info("%s: returned unknown value: %d\n",
-				__func__, result[3]);
-			return -EIO;
-	}
-
-	return 0;
-}
-
-static int ttusbdecfe_dvbt_set_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct ttusbdecfe_state* state = (struct ttusbdecfe_state*) fe->demodulator_priv;
-	u8 b[] = { 0x00, 0x00, 0x00, 0x03,
-		   0x00, 0x00, 0x00, 0x00,
-		   0x00, 0x00, 0x00, 0x01,
-		   0x00, 0x00, 0x00, 0xff,
-		   0x00, 0x00, 0x00, 0xff };
-
-	__be32 freq = htonl(p->frequency / 1000);
-	memcpy(&b[4], &freq, sizeof (u32));
-	state->config->send_command(fe, 0x71, sizeof(b), b, NULL, NULL);
-
-	return 0;
-}
-
-static int ttusbdecfe_dvbt_get_tune_settings(struct dvb_frontend* fe,
-					struct dvb_frontend_tune_settings* fesettings)
-{
-		fesettings->min_delay_ms = 1500;
-		/* Drift compensation makes no sense for DVB-T */
-		fesettings->step_size = 0;
-		fesettings->max_drift = 0;
-		return 0;
-}
-
-static int ttusbdecfe_dvbs_set_frontend(struct dvb_frontend *fe)
-{
-	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
-	struct ttusbdecfe_state* state = (struct ttusbdecfe_state*) fe->demodulator_priv;
-
-	u8 b[] = { 0x00, 0x00, 0x00, 0x01,
-		   0x00, 0x00, 0x00, 0x00,
-		   0x00, 0x00, 0x00, 0x01,
-		   0x00, 0x00, 0x00, 0x00,
-		   0x00, 0x00, 0x00, 0x00,
-		   0x00, 0x00, 0x00, 0x00,
-		   0x00, 0x00, 0x00, 0x00,
-		   0x00, 0x00, 0x00, 0x00,
-		   0x00, 0x00, 0x00, 0x00,
-		   0x00, 0x00, 0x00, 0x00 };
-	__be32 freq;
-	__be32 sym_rate;
-	__be32 band;
-	__be32 lnb_voltage;
-
-	freq = htonl(p->frequency +
-	       (state->hi_band ? LOF_HI : LOF_LO));
-	memcpy(&b[4], &freq, sizeof(u32));
-	sym_rate = htonl(p->symbol_rate);
-	memcpy(&b[12], &sym_rate, sizeof(u32));
-	band = htonl(state->hi_band ? LOF_HI : LOF_LO);
-	memcpy(&b[24], &band, sizeof(u32));
-	lnb_voltage = htonl(state->voltage);
-	memcpy(&b[28], &lnb_voltage, sizeof(u32));
-
-	state->config->send_command(fe, 0x71, sizeof(b), b, NULL, NULL);
-
-	return 0;
-}
-
-static int ttusbdecfe_dvbs_diseqc_send_master_cmd(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd *cmd)
-{
-	struct ttusbdecfe_state* state = (struct ttusbdecfe_state*) fe->demodulator_priv;
-	u8 b[] = { 0x00, 0xff, 0x00, 0x00,
-		   0x00, 0x00, 0x00, 0x00,
-		   0x00, 0x00 };
-
-	memcpy(&b[4], cmd->msg, cmd->msg_len);
-
-	state->config->send_command(fe, 0x72,
-				    sizeof(b) - (6 - cmd->msg_len), b,
-				    NULL, NULL);
-
-	return 0;
-}
-
-
-static int ttusbdecfe_dvbs_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
-{
-	struct ttusbdecfe_state* state = (struct ttusbdecfe_state*) fe->demodulator_priv;
-
-	state->hi_band = (SEC_TONE_ON == tone);
-
-	return 0;
-}
-
-
-static int ttusbdecfe_dvbs_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
-{
-	struct ttusbdecfe_state* state = (struct ttusbdecfe_state*) fe->demodulator_priv;
-
-	switch (voltage) {
-	case SEC_VOLTAGE_13:
-		state->voltage = 13;
-		break;
-	case SEC_VOLTAGE_18:
-		state->voltage = 18;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static void ttusbdecfe_release(struct dvb_frontend* fe)
-{
-	struct ttusbdecfe_state* state = (struct ttusbdecfe_state*) fe->demodulator_priv;
-	kfree(state);
-}
-
-static struct dvb_frontend_ops ttusbdecfe_dvbt_ops;
-
-struct dvb_frontend* ttusbdecfe_dvbt_attach(const struct ttusbdecfe_config* config)
-{
-	struct ttusbdecfe_state* state = NULL;
-
-	/* allocate memory for the internal state */
-	state = kmalloc(sizeof(struct ttusbdecfe_state), GFP_KERNEL);
-	if (state == NULL)
-		return NULL;
-
-	/* setup the state */
-	state->config = config;
-
-	/* create dvb_frontend */
-	memcpy(&state->frontend.ops, &ttusbdecfe_dvbt_ops, sizeof(struct dvb_frontend_ops));
-	state->frontend.demodulator_priv = state;
-	return &state->frontend;
-}
-
-static struct dvb_frontend_ops ttusbdecfe_dvbs_ops;
-
-struct dvb_frontend* ttusbdecfe_dvbs_attach(const struct ttusbdecfe_config* config)
-{
-	struct ttusbdecfe_state* state = NULL;
-
-	/* allocate memory for the internal state */
-	state = kmalloc(sizeof(struct ttusbdecfe_state), GFP_KERNEL);
-	if (state == NULL)
-		return NULL;
-
-	/* setup the state */
-	state->config = config;
-	state->voltage = 0;
-	state->hi_band = 0;
-
-	/* create dvb_frontend */
-	memcpy(&state->frontend.ops, &ttusbdecfe_dvbs_ops, sizeof(struct dvb_frontend_ops));
-	state->frontend.demodulator_priv = state;
-	return &state->frontend;
-}
-
-static struct dvb_frontend_ops ttusbdecfe_dvbt_ops = {
-	.delsys = { SYS_DVBT },
-	.info = {
-		.name			= "TechnoTrend/Hauppauge DEC2000-t Frontend",
-		.frequency_min		= 51000000,
-		.frequency_max		= 858000000,
-		.frequency_stepsize	= 62500,
-		.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_FEC_AUTO |
-			FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
-			FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |
-			FE_CAN_HIERARCHY_AUTO,
-	},
-
-	.release = ttusbdecfe_release,
-
-	.set_frontend = ttusbdecfe_dvbt_set_frontend,
-
-	.get_tune_settings = ttusbdecfe_dvbt_get_tune_settings,
-
-	.read_status = ttusbdecfe_dvbt_read_status,
-};
-
-static struct dvb_frontend_ops ttusbdecfe_dvbs_ops = {
-	.delsys = { SYS_DVBS },
-	.info = {
-		.name			= "TechnoTrend/Hauppauge DEC3000-s Frontend",
-		.frequency_min		= 950000,
-		.frequency_max		= 2150000,
-		.frequency_stepsize	= 125,
-		.symbol_rate_min        = 1000000,  /* guessed */
-		.symbol_rate_max        = 45000000, /* guessed */
-		.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_FEC_AUTO |
-			FE_CAN_QPSK
-	},
-
-	.release = ttusbdecfe_release,
-
-	.set_frontend = ttusbdecfe_dvbs_set_frontend,
-
-	.read_status = ttusbdecfe_dvbs_read_status,
-
-	.diseqc_send_master_cmd = ttusbdecfe_dvbs_diseqc_send_master_cmd,
-	.set_voltage = ttusbdecfe_dvbs_set_voltage,
-	.set_tone = ttusbdecfe_dvbs_set_tone,
-};
-
-MODULE_DESCRIPTION("TTUSB DEC DVB-T/S Demodulator driver");
-MODULE_AUTHOR("Alex Woods/Andrew de Quincey");
-MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(ttusbdecfe_dvbt_attach);
-EXPORT_SYMBOL(ttusbdecfe_dvbs_attach);
diff --git a/drivers/media/dvb/ttusb-dec/ttusbdecfe.h b/drivers/media/dvb/ttusb-dec/ttusbdecfe.h
deleted file mode 100644
index 15ccc3d..0000000
--- a/drivers/media/dvb/ttusb-dec/ttusbdecfe.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * TTUSB DEC Driver
- *
- * Copyright (C) 2003-2004 Alex Woods <linux-dvb@giblets.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 TTUSBDECFE_H
-#define TTUSBDECFE_H
-
-#include <linux/dvb/frontend.h>
-
-struct ttusbdecfe_config
-{
-	int (*send_command)(struct dvb_frontend* fe, const u8 command,
-			    int param_length, const u8 params[],
-			    int *result_length, u8 cmd_result[]);
-};
-
-extern struct dvb_frontend* ttusbdecfe_dvbs_attach(const struct ttusbdecfe_config* config);
-
-extern struct dvb_frontend* ttusbdecfe_dvbt_attach(const struct ttusbdecfe_config* config);
-
-#endif // TTUSBDECFE_H
diff --git a/drivers/media/firewire/Kconfig b/drivers/media/firewire/Kconfig
new file mode 100644
index 0000000..f3e9448
--- /dev/null
+++ b/drivers/media/firewire/Kconfig
@@ -0,0 +1,19 @@
+config DVB_FIREDTV
+	tristate "FireDTV and FloppyDTV"
+	depends on DVB_CORE && FIREWIRE
+	help
+	  Support for DVB receivers from Digital Everywhere
+	  which are connected via IEEE 1394 (FireWire).
+
+	  These devices don't have an MPEG decoder built in,
+	  so you need an external software decoder to watch TV.
+
+	  To compile this driver as a module, say M here:
+	  the module will be called firedtv.
+
+if DVB_FIREDTV
+
+config DVB_FIREDTV_INPUT
+	def_bool INPUT = y || (INPUT = m && DVB_FIREDTV = m)
+
+endif # DVB_FIREDTV
diff --git a/drivers/media/firewire/Makefile b/drivers/media/firewire/Makefile
new file mode 100644
index 0000000..2394813
--- /dev/null
+++ b/drivers/media/firewire/Makefile
@@ -0,0 +1,6 @@
+obj-$(CONFIG_DVB_FIREDTV) += firedtv.o
+
+firedtv-y += firedtv-avc.o firedtv-ci.o firedtv-dvb.o firedtv-fe.o firedtv-fw.o
+firedtv-$(CONFIG_DVB_FIREDTV_INPUT)    += firedtv-rc.o
+
+ccflags-y += -Idrivers/media/dvb-core
diff --git a/drivers/media/firewire/firedtv-avc.c b/drivers/media/firewire/firedtv-avc.c
new file mode 100644
index 0000000..d1a1a13
--- /dev/null
+++ b/drivers/media/firewire/firedtv-avc.c
@@ -0,0 +1,1457 @@
+/*
+ * FireDTV driver (formerly known as FireSAT)
+ *
+ * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com>
+ * Copyright (C) 2008 Ben Backx <ben@bbackx.com>
+ * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se>
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the 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/bug.h>
+#include <linux/crc32.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/jiffies.h>
+#include <linux/kernel.h>
+#include <linux/moduleparam.h>
+#include <linux/mutex.h>
+#include <linux/string.h>
+#include <linux/stringify.h>
+#include <linux/wait.h>
+#include <linux/workqueue.h>
+
+#include <dvb_frontend.h>
+
+#include "firedtv.h"
+
+#define FCP_COMMAND_REGISTER		0xfffff0000b00ULL
+
+#define AVC_CTYPE_CONTROL		0x0
+#define AVC_CTYPE_STATUS		0x1
+#define AVC_CTYPE_NOTIFY		0x3
+
+#define AVC_RESPONSE_ACCEPTED		0x9
+#define AVC_RESPONSE_STABLE		0xc
+#define AVC_RESPONSE_CHANGED		0xd
+#define AVC_RESPONSE_INTERIM		0xf
+
+#define AVC_SUBUNIT_TYPE_TUNER		(0x05 << 3)
+#define AVC_SUBUNIT_TYPE_UNIT		(0x1f << 3)
+
+#define AVC_OPCODE_VENDOR		0x00
+#define AVC_OPCODE_READ_DESCRIPTOR	0x09
+#define AVC_OPCODE_DSIT			0xc8
+#define AVC_OPCODE_DSD			0xcb
+
+#define DESCRIPTOR_TUNER_STATUS 	0x80
+#define DESCRIPTOR_SUBUNIT_IDENTIFIER	0x00
+
+#define SFE_VENDOR_DE_COMPANYID_0	0x00 /* OUI of Digital Everywhere */
+#define SFE_VENDOR_DE_COMPANYID_1	0x12
+#define SFE_VENDOR_DE_COMPANYID_2	0x87
+
+#define SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL 0x0a
+#define SFE_VENDOR_OPCODE_LNB_CONTROL		0x52
+#define SFE_VENDOR_OPCODE_TUNE_QPSK		0x58 /* for DVB-S */
+
+#define SFE_VENDOR_OPCODE_GET_FIRMWARE_VERSION	0x00
+#define SFE_VENDOR_OPCODE_HOST2CA		0x56
+#define SFE_VENDOR_OPCODE_CA2HOST		0x57
+#define SFE_VENDOR_OPCODE_CISTATUS		0x59
+#define SFE_VENDOR_OPCODE_TUNE_QPSK2		0x60 /* for DVB-S2 */
+
+#define SFE_VENDOR_TAG_CA_RESET			0x00
+#define SFE_VENDOR_TAG_CA_APPLICATION_INFO	0x01
+#define SFE_VENDOR_TAG_CA_PMT			0x02
+#define SFE_VENDOR_TAG_CA_DATE_TIME		0x04
+#define SFE_VENDOR_TAG_CA_MMI			0x05
+#define SFE_VENDOR_TAG_CA_ENTER_MENU		0x07
+
+#define EN50221_LIST_MANAGEMENT_ONLY	0x03
+#define EN50221_TAG_APP_INFO		0x9f8021
+#define EN50221_TAG_CA_INFO		0x9f8031
+
+struct avc_command_frame {
+	u8 ctype;
+	u8 subunit;
+	u8 opcode;
+	u8 operand[509];
+};
+
+struct avc_response_frame {
+	u8 response;
+	u8 subunit;
+	u8 opcode;
+	u8 operand[509];
+};
+
+#define LAST_OPERAND (509 - 1)
+
+static inline void clear_operands(struct avc_command_frame *c, int from, int to)
+{
+	memset(&c->operand[from], 0, to - from + 1);
+}
+
+static void pad_operands(struct avc_command_frame *c, int from)
+{
+	int to = ALIGN(from, 4);
+
+	if (from <= to && to <= LAST_OPERAND)
+		clear_operands(c, from, to);
+}
+
+#define AVC_DEBUG_READ_DESCRIPTOR              0x0001
+#define AVC_DEBUG_DSIT                         0x0002
+#define AVC_DEBUG_DSD                          0x0004
+#define AVC_DEBUG_REGISTER_REMOTE_CONTROL      0x0008
+#define AVC_DEBUG_LNB_CONTROL                  0x0010
+#define AVC_DEBUG_TUNE_QPSK                    0x0020
+#define AVC_DEBUG_TUNE_QPSK2                   0x0040
+#define AVC_DEBUG_HOST2CA                      0x0080
+#define AVC_DEBUG_CA2HOST                      0x0100
+#define AVC_DEBUG_APPLICATION_PMT              0x4000
+#define AVC_DEBUG_FCP_PAYLOADS                 0x8000
+
+static int avc_debug;
+module_param_named(debug, avc_debug, int, 0644);
+MODULE_PARM_DESC(debug, "Verbose logging (none = 0"
+	", FCP subactions"
+	": READ DESCRIPTOR = "		__stringify(AVC_DEBUG_READ_DESCRIPTOR)
+	", DSIT = "			__stringify(AVC_DEBUG_DSIT)
+	", REGISTER_REMOTE_CONTROL = "	__stringify(AVC_DEBUG_REGISTER_REMOTE_CONTROL)
+	", LNB CONTROL = "		__stringify(AVC_DEBUG_LNB_CONTROL)
+	", TUNE QPSK = "		__stringify(AVC_DEBUG_TUNE_QPSK)
+	", TUNE QPSK2 = "		__stringify(AVC_DEBUG_TUNE_QPSK2)
+	", HOST2CA = "			__stringify(AVC_DEBUG_HOST2CA)
+	", CA2HOST = "			__stringify(AVC_DEBUG_CA2HOST)
+	"; Application sent PMT = "	__stringify(AVC_DEBUG_APPLICATION_PMT)
+	", FCP payloads = "		__stringify(AVC_DEBUG_FCP_PAYLOADS)
+	", or a combination, or all = -1)");
+
+/*
+ * This is a workaround since there is no vendor specific command to retrieve
+ * ca_info using AVC. If this parameter is not used, ca_system_id will be
+ * filled with application_manufacturer from ca_app_info.
+ * Digital Everywhere have said that adding ca_info is on their TODO list.
+ */
+static unsigned int num_fake_ca_system_ids;
+static int fake_ca_system_ids[4] = { -1, -1, -1, -1 };
+module_param_array(fake_ca_system_ids, int, &num_fake_ca_system_ids, 0644);
+MODULE_PARM_DESC(fake_ca_system_ids, "If your CAM application manufacturer "
+		 "does not have the same ca_system_id as your CAS, you can "
+		 "override what ca_system_ids are presented to the "
+		 "application by setting this field to an array of ids.");
+
+static const char *debug_fcp_ctype(unsigned int ctype)
+{
+	static const char *ctypes[] = {
+		[0x0] = "CONTROL",		[0x1] = "STATUS",
+		[0x2] = "SPECIFIC INQUIRY",	[0x3] = "NOTIFY",
+		[0x4] = "GENERAL INQUIRY",	[0x8] = "NOT IMPLEMENTED",
+		[0x9] = "ACCEPTED",		[0xa] = "REJECTED",
+		[0xb] = "IN TRANSITION",	[0xc] = "IMPLEMENTED/STABLE",
+		[0xd] = "CHANGED",		[0xf] = "INTERIM",
+	};
+	const char *ret = ctype < ARRAY_SIZE(ctypes) ? ctypes[ctype] : NULL;
+
+	return ret ? ret : "?";
+}
+
+static const char *debug_fcp_opcode(unsigned int opcode,
+				    const u8 *data, int length)
+{
+	switch (opcode) {
+	case AVC_OPCODE_VENDOR:
+		break;
+	case AVC_OPCODE_READ_DESCRIPTOR:
+		return avc_debug & AVC_DEBUG_READ_DESCRIPTOR ?
+				"ReadDescriptor" : NULL;
+	case AVC_OPCODE_DSIT:
+		return avc_debug & AVC_DEBUG_DSIT ?
+				"DirectSelectInfo.Type" : NULL;
+	case AVC_OPCODE_DSD:
+		return avc_debug & AVC_DEBUG_DSD ? "DirectSelectData" : NULL;
+	default:
+		return "Unknown";
+	}
+
+	if (length < 7 ||
+	    data[3] != SFE_VENDOR_DE_COMPANYID_0 ||
+	    data[4] != SFE_VENDOR_DE_COMPANYID_1 ||
+	    data[5] != SFE_VENDOR_DE_COMPANYID_2)
+		return "Vendor/Unknown";
+
+	switch (data[6]) {
+	case SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL:
+		return avc_debug & AVC_DEBUG_REGISTER_REMOTE_CONTROL ?
+				"RegisterRC" : NULL;
+	case SFE_VENDOR_OPCODE_LNB_CONTROL:
+		return avc_debug & AVC_DEBUG_LNB_CONTROL ? "LNBControl" : NULL;
+	case SFE_VENDOR_OPCODE_TUNE_QPSK:
+		return avc_debug & AVC_DEBUG_TUNE_QPSK ? "TuneQPSK" : NULL;
+	case SFE_VENDOR_OPCODE_TUNE_QPSK2:
+		return avc_debug & AVC_DEBUG_TUNE_QPSK2 ? "TuneQPSK2" : NULL;
+	case SFE_VENDOR_OPCODE_HOST2CA:
+		return avc_debug & AVC_DEBUG_HOST2CA ? "Host2CA" : NULL;
+	case SFE_VENDOR_OPCODE_CA2HOST:
+		return avc_debug & AVC_DEBUG_CA2HOST ? "CA2Host" : NULL;
+	}
+	return "Vendor/Unknown";
+}
+
+static void debug_fcp(const u8 *data, int length)
+{
+	unsigned int subunit_type, subunit_id, opcode;
+	const char *op, *prefix;
+
+	prefix       = data[0] > 7 ? "FCP <- " : "FCP -> ";
+	subunit_type = data[1] >> 3;
+	subunit_id   = data[1] & 7;
+	opcode       = subunit_type == 0x1e || subunit_id == 5 ? ~0 : data[2];
+	op           = debug_fcp_opcode(opcode, data, length);
+
+	if (op) {
+		printk(KERN_INFO "%ssu=%x.%x l=%d: %-8s - %s\n",
+		       prefix, subunit_type, subunit_id, length,
+		       debug_fcp_ctype(data[0]), op);
+		if (avc_debug & AVC_DEBUG_FCP_PAYLOADS)
+			print_hex_dump(KERN_INFO, prefix, DUMP_PREFIX_NONE,
+				       16, 1, data, length, false);
+	}
+}
+
+static void debug_pmt(char *msg, int length)
+{
+	printk(KERN_INFO "APP PMT -> l=%d\n", length);
+	print_hex_dump(KERN_INFO, "APP PMT -> ", DUMP_PREFIX_NONE,
+		       16, 1, msg, length, false);
+}
+
+static int avc_write(struct firedtv *fdtv)
+{
+	int err, retry;
+
+	fdtv->avc_reply_received = false;
+
+	for (retry = 0; retry < 6; retry++) {
+		if (unlikely(avc_debug))
+			debug_fcp(fdtv->avc_data, fdtv->avc_data_length);
+
+		err = fdtv_write(fdtv, FCP_COMMAND_REGISTER,
+				 fdtv->avc_data, fdtv->avc_data_length);
+		if (err) {
+			dev_err(fdtv->device, "FCP command write failed\n");
+
+			return err;
+		}
+
+		/*
+		 * AV/C specs say that answers should be sent within 150 ms.
+		 * Time out after 200 ms.
+		 */
+		if (wait_event_timeout(fdtv->avc_wait,
+				       fdtv->avc_reply_received,
+				       msecs_to_jiffies(200)) != 0)
+			return 0;
+	}
+	dev_err(fdtv->device, "FCP response timed out\n");
+
+	return -ETIMEDOUT;
+}
+
+static bool is_register_rc(struct avc_response_frame *r)
+{
+	return r->opcode     == AVC_OPCODE_VENDOR &&
+	       r->operand[0] == SFE_VENDOR_DE_COMPANYID_0 &&
+	       r->operand[1] == SFE_VENDOR_DE_COMPANYID_1 &&
+	       r->operand[2] == SFE_VENDOR_DE_COMPANYID_2 &&
+	       r->operand[3] == SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL;
+}
+
+int avc_recv(struct firedtv *fdtv, void *data, size_t length)
+{
+	struct avc_response_frame *r = data;
+
+	if (unlikely(avc_debug))
+		debug_fcp(data, length);
+
+	if (length >= 8 && is_register_rc(r)) {
+		switch (r->response) {
+		case AVC_RESPONSE_CHANGED:
+			fdtv_handle_rc(fdtv, r->operand[4] << 8 | r->operand[5]);
+			schedule_work(&fdtv->remote_ctrl_work);
+			break;
+		case AVC_RESPONSE_INTERIM:
+			if (is_register_rc((void *)fdtv->avc_data))
+				goto wake;
+			break;
+		default:
+			dev_info(fdtv->device,
+				 "remote control result = %d\n", r->response);
+		}
+		return 0;
+	}
+
+	if (fdtv->avc_reply_received) {
+		dev_err(fdtv->device, "out-of-order AVC response, ignored\n");
+		return -EIO;
+	}
+
+	memcpy(fdtv->avc_data, data, length);
+	fdtv->avc_data_length = length;
+wake:
+	fdtv->avc_reply_received = true;
+	wake_up(&fdtv->avc_wait);
+
+	return 0;
+}
+
+static int add_pid_filter(struct firedtv *fdtv, u8 *operand)
+{
+	int i, n, pos = 1;
+
+	for (i = 0, n = 0; i < 16; i++) {
+		if (test_bit(i, &fdtv->channel_active)) {
+			operand[pos++] = 0x13; /* flowfunction relay */
+			operand[pos++] = 0x80; /* dsd_sel_spec_valid_flags -> PID */
+			operand[pos++] = (fdtv->channel_pid[i] >> 8) & 0x1f;
+			operand[pos++] = fdtv->channel_pid[i] & 0xff;
+			operand[pos++] = 0x00; /* tableID */
+			operand[pos++] = 0x00; /* filter_length */
+			n++;
+		}
+	}
+	operand[0] = n;
+
+	return pos;
+}
+
+/*
+ * tuning command for setting the relative LNB frequency
+ * (not supported by the AVC standard)
+ */
+static int avc_tuner_tuneqpsk(struct firedtv *fdtv,
+			      struct dtv_frontend_properties *p)
+{
+	struct avc_command_frame *c = (void *)fdtv->avc_data;
+
+	c->opcode = AVC_OPCODE_VENDOR;
+
+	c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
+	c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
+	c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
+	if (fdtv->type == FIREDTV_DVB_S2)
+		c->operand[3] = SFE_VENDOR_OPCODE_TUNE_QPSK2;
+	else
+		c->operand[3] = SFE_VENDOR_OPCODE_TUNE_QPSK;
+
+	c->operand[4] = (p->frequency >> 24) & 0xff;
+	c->operand[5] = (p->frequency >> 16) & 0xff;
+	c->operand[6] = (p->frequency >> 8) & 0xff;
+	c->operand[7] = p->frequency & 0xff;
+
+	c->operand[8] = ((p->symbol_rate / 1000) >> 8) & 0xff;
+	c->operand[9] = (p->symbol_rate / 1000) & 0xff;
+
+	switch (p->fec_inner) {
+	case FEC_1_2:	c->operand[10] = 0x1; break;
+	case FEC_2_3:	c->operand[10] = 0x2; break;
+	case FEC_3_4:	c->operand[10] = 0x3; break;
+	case FEC_5_6:	c->operand[10] = 0x4; break;
+	case FEC_7_8:	c->operand[10] = 0x5; break;
+	case FEC_4_5:
+	case FEC_8_9:
+	case FEC_AUTO:
+	default:	c->operand[10] = 0x0;
+	}
+
+	if (fdtv->voltage == 0xff)
+		c->operand[11] = 0xff;
+	else if (fdtv->voltage == SEC_VOLTAGE_18) /* polarisation */
+		c->operand[11] = 0;
+	else
+		c->operand[11] = 1;
+
+	if (fdtv->tone == 0xff)
+		c->operand[12] = 0xff;
+	else if (fdtv->tone == SEC_TONE_ON) /* band */
+		c->operand[12] = 1;
+	else
+		c->operand[12] = 0;
+
+	if (fdtv->type == FIREDTV_DVB_S2) {
+		if (fdtv->fe.dtv_property_cache.delivery_system == SYS_DVBS2) {
+			switch (fdtv->fe.dtv_property_cache.modulation) {
+			case QAM_16:		c->operand[13] = 0x1; break;
+			case QPSK:		c->operand[13] = 0x2; break;
+			case PSK_8:		c->operand[13] = 0x3; break;
+			default:		c->operand[13] = 0x2; break;
+			}
+			switch (fdtv->fe.dtv_property_cache.rolloff) {
+			case ROLLOFF_35:	c->operand[14] = 0x2; break;
+			case ROLLOFF_20:	c->operand[14] = 0x0; break;
+			case ROLLOFF_25:	c->operand[14] = 0x1; break;
+			case ROLLOFF_AUTO:
+			default:		c->operand[14] = 0x2; break;
+			/* case ROLLOFF_NONE:	c->operand[14] = 0xff; break; */
+			}
+			switch (fdtv->fe.dtv_property_cache.pilot) {
+			case PILOT_AUTO:	c->operand[15] = 0x0; break;
+			case PILOT_OFF:		c->operand[15] = 0x0; break;
+			case PILOT_ON:		c->operand[15] = 0x1; break;
+			}
+		} else {
+			c->operand[13] = 0x1;  /* auto modulation */
+			c->operand[14] = 0xff; /* disable rolloff */
+			c->operand[15] = 0xff; /* disable pilot */
+		}
+		return 16;
+	} else {
+		return 13;
+	}
+}
+
+static int avc_tuner_dsd_dvb_c(struct firedtv *fdtv,
+			       struct dtv_frontend_properties *p)
+{
+	struct avc_command_frame *c = (void *)fdtv->avc_data;
+
+	c->opcode = AVC_OPCODE_DSD;
+
+	c->operand[0] = 0;    /* source plug */
+	c->operand[1] = 0xd2; /* subfunction replace */
+	c->operand[2] = 0x20; /* system id = DVB */
+	c->operand[3] = 0x00; /* antenna number */
+	c->operand[4] = 0x11; /* system_specific_multiplex selection_length */
+
+	/* multiplex_valid_flags, high byte */
+	c->operand[5] =   0 << 7 /* reserved */
+			| 0 << 6 /* Polarisation */
+			| 0 << 5 /* Orbital_Pos */
+			| 1 << 4 /* Frequency */
+			| 1 << 3 /* Symbol_Rate */
+			| 0 << 2 /* FEC_outer */
+			| (p->fec_inner  != FEC_AUTO ? 1 << 1 : 0)
+			| (p->modulation != QAM_AUTO ? 1 << 0 : 0);
+
+	/* multiplex_valid_flags, low byte */
+	c->operand[6] =   0 << 7 /* NetworkID */
+			| 0 << 0 /* reserved */ ;
+
+	c->operand[7]  = 0x00;
+	c->operand[8]  = 0x00;
+	c->operand[9]  = 0x00;
+	c->operand[10] = 0x00;
+
+	c->operand[11] = (((p->frequency / 4000) >> 16) & 0xff) | (2 << 6);
+	c->operand[12] = ((p->frequency / 4000) >> 8) & 0xff;
+	c->operand[13] = (p->frequency / 4000) & 0xff;
+	c->operand[14] = ((p->symbol_rate / 1000) >> 12) & 0xff;
+	c->operand[15] = ((p->symbol_rate / 1000) >> 4) & 0xff;
+	c->operand[16] = ((p->symbol_rate / 1000) << 4) & 0xf0;
+	c->operand[17] = 0x00;
+
+	switch (p->fec_inner) {
+	case FEC_1_2:	c->operand[18] = 0x1; break;
+	case FEC_2_3:	c->operand[18] = 0x2; break;
+	case FEC_3_4:	c->operand[18] = 0x3; break;
+	case FEC_5_6:	c->operand[18] = 0x4; break;
+	case FEC_7_8:	c->operand[18] = 0x5; break;
+	case FEC_8_9:	c->operand[18] = 0x6; break;
+	case FEC_4_5:	c->operand[18] = 0x8; break;
+	case FEC_AUTO:
+	default:	c->operand[18] = 0x0;
+	}
+
+	switch (p->modulation) {
+	case QAM_16:	c->operand[19] = 0x08; break;
+	case QAM_32:	c->operand[19] = 0x10; break;
+	case QAM_64:	c->operand[19] = 0x18; break;
+	case QAM_128:	c->operand[19] = 0x20; break;
+	case QAM_256:	c->operand[19] = 0x28; break;
+	case QAM_AUTO:
+	default:	c->operand[19] = 0x00;
+	}
+
+	c->operand[20] = 0x00;
+	c->operand[21] = 0x00;
+
+	return 22 + add_pid_filter(fdtv, &c->operand[22]);
+}
+
+static int avc_tuner_dsd_dvb_t(struct firedtv *fdtv,
+			       struct dtv_frontend_properties *p)
+{
+	struct avc_command_frame *c = (void *)fdtv->avc_data;
+
+	c->opcode = AVC_OPCODE_DSD;
+
+	c->operand[0] = 0;    /* source plug */
+	c->operand[1] = 0xd2; /* subfunction replace */
+	c->operand[2] = 0x20; /* system id = DVB */
+	c->operand[3] = 0x00; /* antenna number */
+	c->operand[4] = 0x0c; /* system_specific_multiplex selection_length */
+
+	/* multiplex_valid_flags, high byte */
+	c->operand[5] =
+	      0 << 7 /* reserved */
+	    | 1 << 6 /* CenterFrequency */
+	    | (p->bandwidth_hz != 0        ? 1 << 5 : 0)
+	    | (p->modulation  != QAM_AUTO              ? 1 << 4 : 0)
+	    | (p->hierarchy != HIERARCHY_AUTO ? 1 << 3 : 0)
+	    | (p->code_rate_HP   != FEC_AUTO              ? 1 << 2 : 0)
+	    | (p->code_rate_LP   != FEC_AUTO              ? 1 << 1 : 0)
+	    | (p->guard_interval != GUARD_INTERVAL_AUTO   ? 1 << 0 : 0);
+
+	/* multiplex_valid_flags, low byte */
+	c->operand[6] =
+	      0 << 7 /* NetworkID */
+	    | (p->transmission_mode != TRANSMISSION_MODE_AUTO ? 1 << 6 : 0)
+	    | 0 << 5 /* OtherFrequencyFlag */
+	    | 0 << 0 /* reserved */ ;
+
+	c->operand[7]  = 0x0;
+	c->operand[8]  = (p->frequency / 10) >> 24;
+	c->operand[9]  = ((p->frequency / 10) >> 16) & 0xff;
+	c->operand[10] = ((p->frequency / 10) >>  8) & 0xff;
+	c->operand[11] = (p->frequency / 10) & 0xff;
+
+	switch (p->bandwidth_hz) {
+	case 7000000:	c->operand[12] = 0x20; break;
+	case 8000000:
+	case 6000000:	/* not defined by AVC spec */
+	case 0:
+	default:		c->operand[12] = 0x00;
+	}
+
+	switch (p->modulation) {
+	case QAM_16:	c->operand[13] = 1 << 6; break;
+	case QAM_64:	c->operand[13] = 2 << 6; break;
+	case QPSK:
+	default:	c->operand[13] = 0x00;
+	}
+
+	switch (p->hierarchy) {
+	case HIERARCHY_1:	c->operand[13] |= 1 << 3; break;
+	case HIERARCHY_2:	c->operand[13] |= 2 << 3; break;
+	case HIERARCHY_4:	c->operand[13] |= 3 << 3; break;
+	case HIERARCHY_AUTO:
+	case HIERARCHY_NONE:
+	default:		break;
+	}
+
+	switch (p->code_rate_HP) {
+	case FEC_2_3:	c->operand[13] |= 1; break;
+	case FEC_3_4:	c->operand[13] |= 2; break;
+	case FEC_5_6:	c->operand[13] |= 3; break;
+	case FEC_7_8:	c->operand[13] |= 4; break;
+	case FEC_1_2:
+	default:	break;
+	}
+
+	switch (p->code_rate_LP) {
+	case FEC_2_3:	c->operand[14] = 1 << 5; break;
+	case FEC_3_4:	c->operand[14] = 2 << 5; break;
+	case FEC_5_6:	c->operand[14] = 3 << 5; break;
+	case FEC_7_8:	c->operand[14] = 4 << 5; break;
+	case FEC_1_2:
+	default:	c->operand[14] = 0x00; break;
+	}
+
+	switch (p->guard_interval) {
+	case GUARD_INTERVAL_1_16:	c->operand[14] |= 1 << 3; break;
+	case GUARD_INTERVAL_1_8:	c->operand[14] |= 2 << 3; break;
+	case GUARD_INTERVAL_1_4:	c->operand[14] |= 3 << 3; break;
+	case GUARD_INTERVAL_1_32:
+	case GUARD_INTERVAL_AUTO:
+	default:			break;
+	}
+
+	switch (p->transmission_mode) {
+	case TRANSMISSION_MODE_8K:	c->operand[14] |= 1 << 1; break;
+	case TRANSMISSION_MODE_2K:
+	case TRANSMISSION_MODE_AUTO:
+	default:			break;
+	}
+
+	c->operand[15] = 0x00; /* network_ID[0] */
+	c->operand[16] = 0x00; /* network_ID[1] */
+
+	return 17 + add_pid_filter(fdtv, &c->operand[17]);
+}
+
+int avc_tuner_dsd(struct firedtv *fdtv,
+		  struct dtv_frontend_properties *p)
+{
+	struct avc_command_frame *c = (void *)fdtv->avc_data;
+	int pos, ret;
+
+	mutex_lock(&fdtv->avc_mutex);
+
+	c->ctype   = AVC_CTYPE_CONTROL;
+	c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
+
+	switch (fdtv->type) {
+	case FIREDTV_DVB_S:
+	case FIREDTV_DVB_S2: pos = avc_tuner_tuneqpsk(fdtv, p); break;
+	case FIREDTV_DVB_C: pos = avc_tuner_dsd_dvb_c(fdtv, p); break;
+	case FIREDTV_DVB_T: pos = avc_tuner_dsd_dvb_t(fdtv, p); break;
+	default:
+		BUG();
+	}
+	pad_operands(c, pos);
+
+	fdtv->avc_data_length = ALIGN(3 + pos, 4);
+	ret = avc_write(fdtv);
+#if 0
+	/*
+	 * FIXME:
+	 * u8 *status was an out-parameter of avc_tuner_dsd, unused by caller.
+	 * Check for AVC_RESPONSE_ACCEPTED here instead?
+	 */
+	if (status)
+		*status = r->operand[2];
+#endif
+	mutex_unlock(&fdtv->avc_mutex);
+
+	if (ret == 0)
+		msleep(500);
+
+	return ret;
+}
+
+int avc_tuner_set_pids(struct firedtv *fdtv, unsigned char pidc, u16 pid[])
+{
+	struct avc_command_frame *c = (void *)fdtv->avc_data;
+	int ret, pos, k;
+
+	if (pidc > 16 && pidc != 0xff)
+		return -EINVAL;
+
+	mutex_lock(&fdtv->avc_mutex);
+
+	c->ctype   = AVC_CTYPE_CONTROL;
+	c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
+	c->opcode  = AVC_OPCODE_DSD;
+
+	c->operand[0] = 0;	/* source plug */
+	c->operand[1] = 0xd2;	/* subfunction replace */
+	c->operand[2] = 0x20;	/* system id = DVB */
+	c->operand[3] = 0x00;	/* antenna number */
+	c->operand[4] = 0x00;	/* system_specific_multiplex selection_length */
+	c->operand[5] = pidc;	/* Nr_of_dsd_sel_specs */
+
+	pos = 6;
+	if (pidc != 0xff)
+		for (k = 0; k < pidc; k++) {
+			c->operand[pos++] = 0x13; /* flowfunction relay */
+			c->operand[pos++] = 0x80; /* dsd_sel_spec_valid_flags -> PID */
+			c->operand[pos++] = (pid[k] >> 8) & 0x1f;
+			c->operand[pos++] = pid[k] & 0xff;
+			c->operand[pos++] = 0x00; /* tableID */
+			c->operand[pos++] = 0x00; /* filter_length */
+		}
+	pad_operands(c, pos);
+
+	fdtv->avc_data_length = ALIGN(3 + pos, 4);
+	ret = avc_write(fdtv);
+
+	/* FIXME: check response code? */
+
+	mutex_unlock(&fdtv->avc_mutex);
+
+	if (ret == 0)
+		msleep(50);
+
+	return ret;
+}
+
+int avc_tuner_get_ts(struct firedtv *fdtv)
+{
+	struct avc_command_frame *c = (void *)fdtv->avc_data;
+	int ret, sl;
+
+	mutex_lock(&fdtv->avc_mutex);
+
+	c->ctype   = AVC_CTYPE_CONTROL;
+	c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
+	c->opcode  = AVC_OPCODE_DSIT;
+
+	sl = fdtv->type == FIREDTV_DVB_T ? 0x0c : 0x11;
+
+	c->operand[0] = 0;	/* source plug */
+	c->operand[1] = 0xd2;	/* subfunction replace */
+	c->operand[2] = 0xff;	/* status */
+	c->operand[3] = 0x20;	/* system id = DVB */
+	c->operand[4] = 0x00;	/* antenna number */
+	c->operand[5] = 0x0; 	/* system_specific_search_flags */
+	c->operand[6] = sl;	/* system_specific_multiplex selection_length */
+	/*
+	 * operand[7]: valid_flags[0]
+	 * operand[8]: valid_flags[1]
+	 * operand[7 + sl]: nr_of_dsit_sel_specs (always 0)
+	 */
+	clear_operands(c, 7, 24);
+
+	fdtv->avc_data_length = fdtv->type == FIREDTV_DVB_T ? 24 : 28;
+	ret = avc_write(fdtv);
+
+	/* FIXME: check response code? */
+
+	mutex_unlock(&fdtv->avc_mutex);
+
+	if (ret == 0)
+		msleep(250);
+
+	return ret;
+}
+
+int avc_identify_subunit(struct firedtv *fdtv)
+{
+	struct avc_command_frame *c = (void *)fdtv->avc_data;
+	struct avc_response_frame *r = (void *)fdtv->avc_data;
+	int ret;
+
+	mutex_lock(&fdtv->avc_mutex);
+
+	c->ctype   = AVC_CTYPE_CONTROL;
+	c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
+	c->opcode  = AVC_OPCODE_READ_DESCRIPTOR;
+
+	c->operand[0] = DESCRIPTOR_SUBUNIT_IDENTIFIER;
+	c->operand[1] = 0xff;
+	c->operand[2] = 0x00;
+	c->operand[3] = 0x00; /* length highbyte */
+	c->operand[4] = 0x08; /* length lowbyte  */
+	c->operand[5] = 0x00; /* offset highbyte */
+	c->operand[6] = 0x0d; /* offset lowbyte  */
+	clear_operands(c, 7, 8); /* padding */
+
+	fdtv->avc_data_length = 12;
+	ret = avc_write(fdtv);
+	if (ret < 0)
+		goto out;
+
+	if ((r->response != AVC_RESPONSE_STABLE &&
+	     r->response != AVC_RESPONSE_ACCEPTED) ||
+	    (r->operand[3] << 8) + r->operand[4] != 8) {
+		dev_err(fdtv->device, "cannot read subunit identifier\n");
+		ret = -EINVAL;
+	}
+out:
+	mutex_unlock(&fdtv->avc_mutex);
+
+	return ret;
+}
+
+#define SIZEOF_ANTENNA_INPUT_INFO 22
+
+int avc_tuner_status(struct firedtv *fdtv, struct firedtv_tuner_status *stat)
+{
+	struct avc_command_frame *c = (void *)fdtv->avc_data;
+	struct avc_response_frame *r = (void *)fdtv->avc_data;
+	int length, ret;
+
+	mutex_lock(&fdtv->avc_mutex);
+
+	c->ctype   = AVC_CTYPE_CONTROL;
+	c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
+	c->opcode  = AVC_OPCODE_READ_DESCRIPTOR;
+
+	c->operand[0] = DESCRIPTOR_TUNER_STATUS;
+	c->operand[1] = 0xff;	/* read_result_status */
+	/*
+	 * operand[2]: reserved
+	 * operand[3]: SIZEOF_ANTENNA_INPUT_INFO >> 8
+	 * operand[4]: SIZEOF_ANTENNA_INPUT_INFO & 0xff
+	 */
+	clear_operands(c, 2, 31);
+
+	fdtv->avc_data_length = 12;
+	ret = avc_write(fdtv);
+	if (ret < 0)
+		goto out;
+
+	if (r->response != AVC_RESPONSE_STABLE &&
+	    r->response != AVC_RESPONSE_ACCEPTED) {
+		dev_err(fdtv->device, "cannot read tuner status\n");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	length = r->operand[9];
+	if (r->operand[1] != 0x10 || length != SIZEOF_ANTENNA_INPUT_INFO) {
+		dev_err(fdtv->device, "got invalid tuner status\n");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	stat->active_system		= r->operand[10];
+	stat->searching			= r->operand[11] >> 7 & 1;
+	stat->moving			= r->operand[11] >> 6 & 1;
+	stat->no_rf			= r->operand[11] >> 5 & 1;
+	stat->input			= r->operand[12] >> 7 & 1;
+	stat->selected_antenna		= r->operand[12] & 0x7f;
+	stat->ber			= r->operand[13] << 24 |
+					  r->operand[14] << 16 |
+					  r->operand[15] << 8 |
+					  r->operand[16];
+	stat->signal_strength		= r->operand[17];
+	stat->raster_frequency		= r->operand[18] >> 6 & 2;
+	stat->rf_frequency		= (r->operand[18] & 0x3f) << 16 |
+					  r->operand[19] << 8 |
+					  r->operand[20];
+	stat->man_dep_info_length	= r->operand[21];
+	stat->front_end_error		= r->operand[22] >> 4 & 1;
+	stat->antenna_error		= r->operand[22] >> 3 & 1;
+	stat->front_end_power_status	= r->operand[22] >> 1 & 1;
+	stat->power_supply		= r->operand[22] & 1;
+	stat->carrier_noise_ratio	= r->operand[23] << 8 |
+					  r->operand[24];
+	stat->power_supply_voltage	= r->operand[27];
+	stat->antenna_voltage		= r->operand[28];
+	stat->firewire_bus_voltage	= r->operand[29];
+	stat->ca_mmi			= r->operand[30] & 1;
+	stat->ca_pmt_reply		= r->operand[31] >> 7 & 1;
+	stat->ca_date_time_request	= r->operand[31] >> 6 & 1;
+	stat->ca_application_info	= r->operand[31] >> 5 & 1;
+	stat->ca_module_present_status	= r->operand[31] >> 4 & 1;
+	stat->ca_dvb_flag		= r->operand[31] >> 3 & 1;
+	stat->ca_error_flag		= r->operand[31] >> 2 & 1;
+	stat->ca_initialization_status	= r->operand[31] >> 1 & 1;
+out:
+	mutex_unlock(&fdtv->avc_mutex);
+
+	return ret;
+}
+
+int avc_lnb_control(struct firedtv *fdtv, char voltage, char burst,
+		    char conttone, char nrdiseq,
+		    struct dvb_diseqc_master_cmd *diseqcmd)
+{
+	struct avc_command_frame *c = (void *)fdtv->avc_data;
+	struct avc_response_frame *r = (void *)fdtv->avc_data;
+	int pos, j, k, ret;
+
+	mutex_lock(&fdtv->avc_mutex);
+
+	c->ctype   = AVC_CTYPE_CONTROL;
+	c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
+	c->opcode  = AVC_OPCODE_VENDOR;
+
+	c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
+	c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
+	c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
+	c->operand[3] = SFE_VENDOR_OPCODE_LNB_CONTROL;
+	c->operand[4] = voltage;
+	c->operand[5] = nrdiseq;
+
+	pos = 6;
+	for (j = 0; j < nrdiseq; j++) {
+		c->operand[pos++] = diseqcmd[j].msg_len;
+
+		for (k = 0; k < diseqcmd[j].msg_len; k++)
+			c->operand[pos++] = diseqcmd[j].msg[k];
+	}
+	c->operand[pos++] = burst;
+	c->operand[pos++] = conttone;
+	pad_operands(c, pos);
+
+	fdtv->avc_data_length = ALIGN(3 + pos, 4);
+	ret = avc_write(fdtv);
+	if (ret < 0)
+		goto out;
+
+	if (r->response != AVC_RESPONSE_ACCEPTED) {
+		dev_err(fdtv->device, "LNB control failed\n");
+		ret = -EINVAL;
+	}
+out:
+	mutex_unlock(&fdtv->avc_mutex);
+
+	return ret;
+}
+
+int avc_register_remote_control(struct firedtv *fdtv)
+{
+	struct avc_command_frame *c = (void *)fdtv->avc_data;
+	int ret;
+
+	mutex_lock(&fdtv->avc_mutex);
+
+	c->ctype   = AVC_CTYPE_NOTIFY;
+	c->subunit = AVC_SUBUNIT_TYPE_UNIT | 7;
+	c->opcode  = AVC_OPCODE_VENDOR;
+
+	c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
+	c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
+	c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
+	c->operand[3] = SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL;
+	c->operand[4] = 0; /* padding */
+
+	fdtv->avc_data_length = 8;
+	ret = avc_write(fdtv);
+
+	/* FIXME: check response code? */
+
+	mutex_unlock(&fdtv->avc_mutex);
+
+	return ret;
+}
+
+void avc_remote_ctrl_work(struct work_struct *work)
+{
+	struct firedtv *fdtv =
+			container_of(work, struct firedtv, remote_ctrl_work);
+
+	/* Should it be rescheduled in failure cases? */
+	avc_register_remote_control(fdtv);
+}
+
+#if 0 /* FIXME: unused */
+int avc_tuner_host2ca(struct firedtv *fdtv)
+{
+	struct avc_command_frame *c = (void *)fdtv->avc_data;
+	int ret;
+
+	mutex_lock(&fdtv->avc_mutex);
+
+	c->ctype   = AVC_CTYPE_CONTROL;
+	c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
+	c->opcode  = AVC_OPCODE_VENDOR;
+
+	c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
+	c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
+	c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
+	c->operand[3] = SFE_VENDOR_OPCODE_HOST2CA;
+	c->operand[4] = 0; /* slot */
+	c->operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; /* ca tag */
+	clear_operands(c, 6, 8);
+
+	fdtv->avc_data_length = 12;
+	ret = avc_write(fdtv);
+
+	/* FIXME: check response code? */
+
+	mutex_unlock(&fdtv->avc_mutex);
+
+	return ret;
+}
+#endif
+
+static int get_ca_object_pos(struct avc_response_frame *r)
+{
+	int length = 1;
+
+	/* Check length of length field */
+	if (r->operand[7] & 0x80)
+		length = (r->operand[7] & 0x7f) + 1;
+	return length + 7;
+}
+
+static int get_ca_object_length(struct avc_response_frame *r)
+{
+#if 0 /* FIXME: unused */
+	int size = 0;
+	int i;
+
+	if (r->operand[7] & 0x80)
+		for (i = 0; i < (r->operand[7] & 0x7f); i++) {
+			size <<= 8;
+			size += r->operand[8 + i];
+		}
+#endif
+	return r->operand[7];
+}
+
+int avc_ca_app_info(struct firedtv *fdtv, char *app_info, unsigned int *len)
+{
+	struct avc_command_frame *c = (void *)fdtv->avc_data;
+	struct avc_response_frame *r = (void *)fdtv->avc_data;
+	int pos, ret;
+
+	mutex_lock(&fdtv->avc_mutex);
+
+	c->ctype   = AVC_CTYPE_STATUS;
+	c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
+	c->opcode  = AVC_OPCODE_VENDOR;
+
+	c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
+	c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
+	c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
+	c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST;
+	c->operand[4] = 0; /* slot */
+	c->operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; /* ca tag */
+	clear_operands(c, 6, LAST_OPERAND);
+
+	fdtv->avc_data_length = 12;
+	ret = avc_write(fdtv);
+	if (ret < 0)
+		goto out;
+
+	/* FIXME: check response code and validate response data */
+
+	pos = get_ca_object_pos(r);
+	app_info[0] = (EN50221_TAG_APP_INFO >> 16) & 0xff;
+	app_info[1] = (EN50221_TAG_APP_INFO >>  8) & 0xff;
+	app_info[2] = (EN50221_TAG_APP_INFO >>  0) & 0xff;
+	app_info[3] = 6 + r->operand[pos + 4];
+	app_info[4] = 0x01;
+	memcpy(&app_info[5], &r->operand[pos], 5 + r->operand[pos + 4]);
+	*len = app_info[3] + 4;
+out:
+	mutex_unlock(&fdtv->avc_mutex);
+
+	return ret;
+}
+
+int avc_ca_info(struct firedtv *fdtv, char *app_info, unsigned int *len)
+{
+	struct avc_command_frame *c = (void *)fdtv->avc_data;
+	struct avc_response_frame *r = (void *)fdtv->avc_data;
+	int i, pos, ret;
+
+	mutex_lock(&fdtv->avc_mutex);
+
+	c->ctype   = AVC_CTYPE_STATUS;
+	c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
+	c->opcode  = AVC_OPCODE_VENDOR;
+
+	c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
+	c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
+	c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
+	c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST;
+	c->operand[4] = 0; /* slot */
+	c->operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; /* ca tag */
+	clear_operands(c, 6, LAST_OPERAND);
+
+	fdtv->avc_data_length = 12;
+	ret = avc_write(fdtv);
+	if (ret < 0)
+		goto out;
+
+	/* FIXME: check response code and validate response data */
+
+	pos = get_ca_object_pos(r);
+	app_info[0] = (EN50221_TAG_CA_INFO >> 16) & 0xff;
+	app_info[1] = (EN50221_TAG_CA_INFO >>  8) & 0xff;
+	app_info[2] = (EN50221_TAG_CA_INFO >>  0) & 0xff;
+	if (num_fake_ca_system_ids == 0) {
+		app_info[3] = 2;
+		app_info[4] = r->operand[pos + 0];
+		app_info[5] = r->operand[pos + 1];
+	} else {
+		app_info[3] = num_fake_ca_system_ids * 2;
+		for (i = 0; i < num_fake_ca_system_ids; i++) {
+			app_info[4 + i * 2] =
+				(fake_ca_system_ids[i] >> 8) & 0xff;
+			app_info[5 + i * 2] = fake_ca_system_ids[i] & 0xff;
+		}
+	}
+	*len = app_info[3] + 4;
+out:
+	mutex_unlock(&fdtv->avc_mutex);
+
+	return ret;
+}
+
+int avc_ca_reset(struct firedtv *fdtv)
+{
+	struct avc_command_frame *c = (void *)fdtv->avc_data;
+	int ret;
+
+	mutex_lock(&fdtv->avc_mutex);
+
+	c->ctype   = AVC_CTYPE_CONTROL;
+	c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
+	c->opcode  = AVC_OPCODE_VENDOR;
+
+	c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
+	c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
+	c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
+	c->operand[3] = SFE_VENDOR_OPCODE_HOST2CA;
+	c->operand[4] = 0; /* slot */
+	c->operand[5] = SFE_VENDOR_TAG_CA_RESET; /* ca tag */
+	c->operand[6] = 0; /* more/last */
+	c->operand[7] = 1; /* length */
+	c->operand[8] = 0; /* force hardware reset */
+
+	fdtv->avc_data_length = 12;
+	ret = avc_write(fdtv);
+
+	/* FIXME: check response code? */
+
+	mutex_unlock(&fdtv->avc_mutex);
+
+	return ret;
+}
+
+int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length)
+{
+	struct avc_command_frame *c = (void *)fdtv->avc_data;
+	struct avc_response_frame *r = (void *)fdtv->avc_data;
+	int list_management;
+	int program_info_length;
+	int pmt_cmd_id;
+	int read_pos;
+	int write_pos;
+	int es_info_length;
+	int crc32_csum;
+	int ret;
+
+	if (unlikely(avc_debug & AVC_DEBUG_APPLICATION_PMT))
+		debug_pmt(msg, length);
+
+	mutex_lock(&fdtv->avc_mutex);
+
+	c->ctype   = AVC_CTYPE_CONTROL;
+	c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
+	c->opcode  = AVC_OPCODE_VENDOR;
+
+	if (msg[0] != EN50221_LIST_MANAGEMENT_ONLY) {
+		dev_info(fdtv->device, "forcing list_management to ONLY\n");
+		msg[0] = EN50221_LIST_MANAGEMENT_ONLY;
+	}
+	/* We take the cmd_id from the programme level only! */
+	list_management = msg[0];
+	program_info_length = ((msg[4] & 0x0f) << 8) + msg[5];
+	if (program_info_length > 0)
+		program_info_length--; /* Remove pmt_cmd_id */
+	pmt_cmd_id = msg[6];
+
+	c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
+	c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
+	c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
+	c->operand[3] = SFE_VENDOR_OPCODE_HOST2CA;
+	c->operand[4] = 0; /* slot */
+	c->operand[5] = SFE_VENDOR_TAG_CA_PMT; /* ca tag */
+	c->operand[6] = 0; /* more/last */
+	/* Use three bytes for length field in case length > 127 */
+	c->operand[10] = list_management;
+	c->operand[11] = 0x01; /* pmt_cmd=OK_descramble */
+
+	/* TS program map table */
+
+	c->operand[12] = 0x02; /* Table id=2 */
+	c->operand[13] = 0x80; /* Section syntax + length */
+
+	c->operand[15] = msg[1]; /* Program number */
+	c->operand[16] = msg[2];
+	c->operand[17] = msg[3]; /* Version number and current/next */
+	c->operand[18] = 0x00; /* Section number=0 */
+	c->operand[19] = 0x00; /* Last section number=0 */
+	c->operand[20] = 0x1f; /* PCR_PID=1FFF */
+	c->operand[21] = 0xff;
+	c->operand[22] = (program_info_length >> 8); /* Program info length */
+	c->operand[23] = (program_info_length & 0xff);
+
+	/* CA descriptors at programme level */
+	read_pos = 6;
+	write_pos = 24;
+	if (program_info_length > 0) {
+		pmt_cmd_id = msg[read_pos++];
+		if (pmt_cmd_id != 1 && pmt_cmd_id != 4)
+			dev_err(fdtv->device,
+				"invalid pmt_cmd_id %d\n", pmt_cmd_id);
+
+		memcpy(&c->operand[write_pos], &msg[read_pos],
+		       program_info_length);
+		read_pos += program_info_length;
+		write_pos += program_info_length;
+	}
+	while (read_pos < length) {
+		c->operand[write_pos++] = msg[read_pos++];
+		c->operand[write_pos++] = msg[read_pos++];
+		c->operand[write_pos++] = msg[read_pos++];
+		es_info_length =
+			((msg[read_pos] & 0x0f) << 8) + msg[read_pos + 1];
+		read_pos += 2;
+		if (es_info_length > 0)
+			es_info_length--; /* Remove pmt_cmd_id */
+		c->operand[write_pos++] = es_info_length >> 8;
+		c->operand[write_pos++] = es_info_length & 0xff;
+		if (es_info_length > 0) {
+			pmt_cmd_id = msg[read_pos++];
+			if (pmt_cmd_id != 1 && pmt_cmd_id != 4)
+				dev_err(fdtv->device, "invalid pmt_cmd_id %d "
+					"at stream level\n", pmt_cmd_id);
+
+			memcpy(&c->operand[write_pos], &msg[read_pos],
+			       es_info_length);
+			read_pos += es_info_length;
+			write_pos += es_info_length;
+		}
+	}
+	write_pos += 4; /* CRC */
+
+	c->operand[7] = 0x82;
+	c->operand[8] = (write_pos - 10) >> 8;
+	c->operand[9] = (write_pos - 10) & 0xff;
+	c->operand[14] = write_pos - 15;
+
+	crc32_csum = crc32_be(0, &c->operand[10], c->operand[12] - 1);
+	c->operand[write_pos - 4] = (crc32_csum >> 24) & 0xff;
+	c->operand[write_pos - 3] = (crc32_csum >> 16) & 0xff;
+	c->operand[write_pos - 2] = (crc32_csum >>  8) & 0xff;
+	c->operand[write_pos - 1] = (crc32_csum >>  0) & 0xff;
+	pad_operands(c, write_pos);
+
+	fdtv->avc_data_length = ALIGN(3 + write_pos, 4);
+	ret = avc_write(fdtv);
+	if (ret < 0)
+		goto out;
+
+	if (r->response != AVC_RESPONSE_ACCEPTED) {
+		dev_err(fdtv->device,
+			"CA PMT failed with response 0x%x\n", r->response);
+		ret = -EACCES;
+	}
+out:
+	mutex_unlock(&fdtv->avc_mutex);
+
+	return ret;
+}
+
+int avc_ca_get_time_date(struct firedtv *fdtv, int *interval)
+{
+	struct avc_command_frame *c = (void *)fdtv->avc_data;
+	struct avc_response_frame *r = (void *)fdtv->avc_data;
+	int ret;
+
+	mutex_lock(&fdtv->avc_mutex);
+
+	c->ctype   = AVC_CTYPE_STATUS;
+	c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
+	c->opcode  = AVC_OPCODE_VENDOR;
+
+	c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
+	c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
+	c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
+	c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST;
+	c->operand[4] = 0; /* slot */
+	c->operand[5] = SFE_VENDOR_TAG_CA_DATE_TIME; /* ca tag */
+	clear_operands(c, 6, LAST_OPERAND);
+
+	fdtv->avc_data_length = 12;
+	ret = avc_write(fdtv);
+	if (ret < 0)
+		goto out;
+
+	/* FIXME: check response code and validate response data */
+
+	*interval = r->operand[get_ca_object_pos(r)];
+out:
+	mutex_unlock(&fdtv->avc_mutex);
+
+	return ret;
+}
+
+int avc_ca_enter_menu(struct firedtv *fdtv)
+{
+	struct avc_command_frame *c = (void *)fdtv->avc_data;
+	int ret;
+
+	mutex_lock(&fdtv->avc_mutex);
+
+	c->ctype   = AVC_CTYPE_STATUS;
+	c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
+	c->opcode  = AVC_OPCODE_VENDOR;
+
+	c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
+	c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
+	c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
+	c->operand[3] = SFE_VENDOR_OPCODE_HOST2CA;
+	c->operand[4] = 0; /* slot */
+	c->operand[5] = SFE_VENDOR_TAG_CA_ENTER_MENU;
+	clear_operands(c, 6, 8);
+
+	fdtv->avc_data_length = 12;
+	ret = avc_write(fdtv);
+
+	/* FIXME: check response code? */
+
+	mutex_unlock(&fdtv->avc_mutex);
+
+	return ret;
+}
+
+int avc_ca_get_mmi(struct firedtv *fdtv, char *mmi_object, unsigned int *len)
+{
+	struct avc_command_frame *c = (void *)fdtv->avc_data;
+	struct avc_response_frame *r = (void *)fdtv->avc_data;
+	int ret;
+
+	mutex_lock(&fdtv->avc_mutex);
+
+	c->ctype   = AVC_CTYPE_STATUS;
+	c->subunit = AVC_SUBUNIT_TYPE_TUNER | fdtv->subunit;
+	c->opcode  = AVC_OPCODE_VENDOR;
+
+	c->operand[0] = SFE_VENDOR_DE_COMPANYID_0;
+	c->operand[1] = SFE_VENDOR_DE_COMPANYID_1;
+	c->operand[2] = SFE_VENDOR_DE_COMPANYID_2;
+	c->operand[3] = SFE_VENDOR_OPCODE_CA2HOST;
+	c->operand[4] = 0; /* slot */
+	c->operand[5] = SFE_VENDOR_TAG_CA_MMI;
+	clear_operands(c, 6, LAST_OPERAND);
+
+	fdtv->avc_data_length = 12;
+	ret = avc_write(fdtv);
+	if (ret < 0)
+		goto out;
+
+	/* FIXME: check response code and validate response data */
+
+	*len = get_ca_object_length(r);
+	memcpy(mmi_object, &r->operand[get_ca_object_pos(r)], *len);
+out:
+	mutex_unlock(&fdtv->avc_mutex);
+
+	return ret;
+}
+
+#define CMP_OUTPUT_PLUG_CONTROL_REG_0	0xfffff0000904ULL
+
+static int cmp_read(struct firedtv *fdtv, u64 addr, __be32 *data)
+{
+	int ret;
+
+	ret = fdtv_read(fdtv, addr, data);
+	if (ret < 0)
+		dev_err(fdtv->device, "CMP: read I/O error\n");
+
+	return ret;
+}
+
+static int cmp_lock(struct firedtv *fdtv, u64 addr, __be32 data[])
+{
+	int ret;
+
+	ret = fdtv_lock(fdtv, addr, data);
+	if (ret < 0)
+		dev_err(fdtv->device, "CMP: lock I/O error\n");
+
+	return ret;
+}
+
+static inline u32 get_opcr(__be32 opcr, u32 mask, u32 shift)
+{
+	return (be32_to_cpu(opcr) >> shift) & mask;
+}
+
+static inline void set_opcr(__be32 *opcr, u32 value, u32 mask, u32 shift)
+{
+	*opcr &= ~cpu_to_be32(mask << shift);
+	*opcr |= cpu_to_be32((value & mask) << shift);
+}
+
+#define get_opcr_online(v)		get_opcr((v), 0x1, 31)
+#define get_opcr_p2p_connections(v)	get_opcr((v), 0x3f, 24)
+#define get_opcr_channel(v)		get_opcr((v), 0x3f, 16)
+
+#define set_opcr_p2p_connections(p, v)	set_opcr((p), (v), 0x3f, 24)
+#define set_opcr_channel(p, v)		set_opcr((p), (v), 0x3f, 16)
+#define set_opcr_data_rate(p, v)	set_opcr((p), (v), 0x3, 14)
+#define set_opcr_overhead_id(p, v)	set_opcr((p), (v), 0xf, 10)
+
+int cmp_establish_pp_connection(struct firedtv *fdtv, int plug, int channel)
+{
+	__be32 old_opcr, opcr[2];
+	u64 opcr_address = CMP_OUTPUT_PLUG_CONTROL_REG_0 + (plug << 2);
+	int attempts = 0;
+	int ret;
+
+	ret = cmp_read(fdtv, opcr_address, opcr);
+	if (ret < 0)
+		return ret;
+
+repeat:
+	if (!get_opcr_online(*opcr)) {
+		dev_err(fdtv->device, "CMP: output offline\n");
+		return -EBUSY;
+	}
+
+	old_opcr = *opcr;
+
+	if (get_opcr_p2p_connections(*opcr)) {
+		if (get_opcr_channel(*opcr) != channel) {
+			dev_err(fdtv->device, "CMP: cannot change channel\n");
+			return -EBUSY;
+		}
+		dev_info(fdtv->device, "CMP: overlaying connection\n");
+
+		/* We don't allocate isochronous resources. */
+	} else {
+		set_opcr_channel(opcr, channel);
+		set_opcr_data_rate(opcr, 2); /* S400 */
+
+		/* FIXME: this is for the worst case - optimize */
+		set_opcr_overhead_id(opcr, 0);
+
+		/* FIXME: allocate isochronous channel and bandwidth at IRM */
+	}
+
+	set_opcr_p2p_connections(opcr, get_opcr_p2p_connections(*opcr) + 1);
+
+	opcr[1] = *opcr;
+	opcr[0] = old_opcr;
+
+	ret = cmp_lock(fdtv, opcr_address, opcr);
+	if (ret < 0)
+		return ret;
+
+	if (old_opcr != *opcr) {
+		/*
+		 * FIXME: if old_opcr.P2P_Connections > 0,
+		 * deallocate isochronous channel and bandwidth at IRM
+		 */
+
+		if (++attempts < 6) /* arbitrary limit */
+			goto repeat;
+		return -EBUSY;
+	}
+
+	return 0;
+}
+
+void cmp_break_pp_connection(struct firedtv *fdtv, int plug, int channel)
+{
+	__be32 old_opcr, opcr[2];
+	u64 opcr_address = CMP_OUTPUT_PLUG_CONTROL_REG_0 + (plug << 2);
+	int attempts = 0;
+
+	if (cmp_read(fdtv, opcr_address, opcr) < 0)
+		return;
+
+repeat:
+	if (!get_opcr_online(*opcr) || !get_opcr_p2p_connections(*opcr) ||
+	    get_opcr_channel(*opcr) != channel) {
+		dev_err(fdtv->device, "CMP: no connection to break\n");
+		return;
+	}
+
+	old_opcr = *opcr;
+	set_opcr_p2p_connections(opcr, get_opcr_p2p_connections(*opcr) - 1);
+
+	opcr[1] = *opcr;
+	opcr[0] = old_opcr;
+
+	if (cmp_lock(fdtv, opcr_address, opcr) < 0)
+		return;
+
+	if (old_opcr != *opcr) {
+		/*
+		 * FIXME: if old_opcr.P2P_Connections == 1, i.e. we were last
+		 * owner, deallocate isochronous channel and bandwidth at IRM
+		 * if (...)
+		 *	fdtv->backend->dealloc_resources(fdtv, channel, bw);
+		 */
+
+		if (++attempts < 6) /* arbitrary limit */
+			goto repeat;
+	}
+}
diff --git a/drivers/media/firewire/firedtv-ci.c b/drivers/media/firewire/firedtv-ci.c
new file mode 100644
index 0000000..e5ebdbf
--- /dev/null
+++ b/drivers/media/firewire/firedtv-ci.c
@@ -0,0 +1,258 @@
+/*
+ * FireDTV driver (formerly known as FireSAT)
+ *
+ * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com>
+ * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se>
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License as
+ *	published by the Free Software Foundation; either version 2 of
+ *	the License, or (at your option) any later version.
+ */
+
+#include <linux/device.h>
+#include <linux/dvb/ca.h>
+#include <linux/fs.h>
+#include <linux/module.h>
+
+#include <dvbdev.h>
+
+#include "firedtv.h"
+
+#define EN50221_TAG_APP_INFO_ENQUIRY	0x9f8020
+#define EN50221_TAG_CA_INFO_ENQUIRY	0x9f8030
+#define EN50221_TAG_CA_PMT		0x9f8032
+#define EN50221_TAG_ENTER_MENU		0x9f8022
+
+static int fdtv_ca_ready(struct firedtv_tuner_status *stat)
+{
+	return stat->ca_initialization_status	== 1 &&
+	       stat->ca_error_flag		== 0 &&
+	       stat->ca_dvb_flag		== 1 &&
+	       stat->ca_module_present_status	== 1;
+}
+
+static int fdtv_get_ca_flags(struct firedtv_tuner_status *stat)
+{
+	int flags = 0;
+
+	if (stat->ca_module_present_status == 1)
+		flags |= CA_CI_MODULE_PRESENT;
+	if (stat->ca_initialization_status == 1 &&
+	    stat->ca_error_flag            == 0 &&
+	    stat->ca_dvb_flag              == 1)
+		flags |= CA_CI_MODULE_READY;
+	return flags;
+}
+
+static int fdtv_ca_get_caps(void *arg)
+{
+	struct ca_caps *cap = arg;
+
+	cap->slot_num = 1;
+	cap->slot_type = CA_CI;
+	cap->descr_num = 1;
+	cap->descr_type = CA_ECD;
+	return 0;
+}
+
+static int fdtv_ca_get_slot_info(struct firedtv *fdtv, void *arg)
+{
+	struct firedtv_tuner_status stat;
+	struct ca_slot_info *slot = arg;
+	int err;
+
+	err = avc_tuner_status(fdtv, &stat);
+	if (err)
+		return err;
+
+	if (slot->num != 0)
+		return -EACCES;
+
+	slot->type = CA_CI;
+	slot->flags = fdtv_get_ca_flags(&stat);
+	return 0;
+}
+
+static int fdtv_ca_app_info(struct firedtv *fdtv, void *arg)
+{
+	struct ca_msg *reply = arg;
+
+	return avc_ca_app_info(fdtv, reply->msg, &reply->length);
+}
+
+static int fdtv_ca_info(struct firedtv *fdtv, void *arg)
+{
+	struct ca_msg *reply = arg;
+
+	return avc_ca_info(fdtv, reply->msg, &reply->length);
+}
+
+static int fdtv_ca_get_mmi(struct firedtv *fdtv, void *arg)
+{
+	struct ca_msg *reply = arg;
+
+	return avc_ca_get_mmi(fdtv, reply->msg, &reply->length);
+}
+
+static int fdtv_ca_get_msg(struct firedtv *fdtv, void *arg)
+{
+	struct firedtv_tuner_status stat;
+	int err;
+
+	switch (fdtv->ca_last_command) {
+	case EN50221_TAG_APP_INFO_ENQUIRY:
+		err = fdtv_ca_app_info(fdtv, arg);
+		break;
+	case EN50221_TAG_CA_INFO_ENQUIRY:
+		err = fdtv_ca_info(fdtv, arg);
+		break;
+	default:
+		err = avc_tuner_status(fdtv, &stat);
+		if (err)
+			break;
+		if (stat.ca_mmi == 1)
+			err = fdtv_ca_get_mmi(fdtv, arg);
+		else {
+			dev_info(fdtv->device, "unhandled CA message 0x%08x\n",
+				 fdtv->ca_last_command);
+			err = -EACCES;
+		}
+	}
+	fdtv->ca_last_command = 0;
+	return err;
+}
+
+static int fdtv_ca_pmt(struct firedtv *fdtv, void *arg)
+{
+	struct ca_msg *msg = arg;
+	int data_pos;
+	int data_length;
+	int i;
+
+	data_pos = 4;
+	if (msg->msg[3] & 0x80) {
+		data_length = 0;
+		for (i = 0; i < (msg->msg[3] & 0x7f); i++)
+			data_length = (data_length << 8) + msg->msg[data_pos++];
+	} else {
+		data_length = msg->msg[3];
+	}
+
+	return avc_ca_pmt(fdtv, &msg->msg[data_pos], data_length);
+}
+
+static int fdtv_ca_send_msg(struct firedtv *fdtv, void *arg)
+{
+	struct ca_msg *msg = arg;
+	int err;
+
+	/* Do we need a semaphore for this? */
+	fdtv->ca_last_command =
+		(msg->msg[0] << 16) + (msg->msg[1] << 8) + msg->msg[2];
+	switch (fdtv->ca_last_command) {
+	case EN50221_TAG_CA_PMT:
+		err = fdtv_ca_pmt(fdtv, arg);
+		break;
+	case EN50221_TAG_APP_INFO_ENQUIRY:
+		/* handled in ca_get_msg */
+		err = 0;
+		break;
+	case EN50221_TAG_CA_INFO_ENQUIRY:
+		/* handled in ca_get_msg */
+		err = 0;
+		break;
+	case EN50221_TAG_ENTER_MENU:
+		err = avc_ca_enter_menu(fdtv);
+		break;
+	default:
+		dev_err(fdtv->device, "unhandled CA message 0x%08x\n",
+			fdtv->ca_last_command);
+		err = -EACCES;
+	}
+	return err;
+}
+
+static int fdtv_ca_ioctl(struct file *file, unsigned int cmd, void *arg)
+{
+	struct dvb_device *dvbdev = file->private_data;
+	struct firedtv *fdtv = dvbdev->priv;
+	struct firedtv_tuner_status stat;
+	int err;
+
+	switch (cmd) {
+	case CA_RESET:
+		err = avc_ca_reset(fdtv);
+		break;
+	case CA_GET_CAP:
+		err = fdtv_ca_get_caps(arg);
+		break;
+	case CA_GET_SLOT_INFO:
+		err = fdtv_ca_get_slot_info(fdtv, arg);
+		break;
+	case CA_GET_MSG:
+		err = fdtv_ca_get_msg(fdtv, arg);
+		break;
+	case CA_SEND_MSG:
+		err = fdtv_ca_send_msg(fdtv, arg);
+		break;
+	default:
+		dev_info(fdtv->device, "unhandled CA ioctl %u\n", cmd);
+		err = -EOPNOTSUPP;
+	}
+
+	/* FIXME Is this necessary? */
+	avc_tuner_status(fdtv, &stat);
+
+	return err;
+}
+
+static unsigned int fdtv_ca_io_poll(struct file *file, poll_table *wait)
+{
+	return POLLIN;
+}
+
+static const struct file_operations fdtv_ca_fops = {
+	.owner		= THIS_MODULE,
+	.unlocked_ioctl	= dvb_generic_ioctl,
+	.open		= dvb_generic_open,
+	.release	= dvb_generic_release,
+	.poll		= fdtv_ca_io_poll,
+	.llseek		= noop_llseek,
+};
+
+static struct dvb_device fdtv_ca = {
+	.users		= 1,
+	.readers	= 1,
+	.writers	= 1,
+	.fops		= &fdtv_ca_fops,
+	.kernel_ioctl	= fdtv_ca_ioctl,
+};
+
+int fdtv_ca_register(struct firedtv *fdtv)
+{
+	struct firedtv_tuner_status stat;
+	int err;
+
+	if (avc_tuner_status(fdtv, &stat))
+		return -EINVAL;
+
+	if (!fdtv_ca_ready(&stat))
+		return -EFAULT;
+
+	err = dvb_register_device(&fdtv->adapter, &fdtv->cadev,
+				  &fdtv_ca, fdtv, DVB_DEVICE_CA);
+
+	if (stat.ca_application_info == 0)
+		dev_err(fdtv->device, "CaApplicationInfo is not set\n");
+	if (stat.ca_date_time_request == 1)
+		avc_ca_get_time_date(fdtv, &fdtv->ca_time_interval);
+
+	return err;
+}
+
+void fdtv_ca_release(struct firedtv *fdtv)
+{
+	if (fdtv->cadev)
+		dvb_unregister_device(fdtv->cadev);
+}
diff --git a/drivers/media/firewire/firedtv-dvb.c b/drivers/media/firewire/firedtv-dvb.c
new file mode 100644
index 0000000..eb7496e
--- /dev/null
+++ b/drivers/media/firewire/firedtv-dvb.c
@@ -0,0 +1,248 @@
+/*
+ * FireDTV driver (formerly known as FireSAT)
+ *
+ * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com>
+ * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se>
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the 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/bitops.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/types.h>
+
+#include <dmxdev.h>
+#include <dvb_demux.h>
+#include <dvbdev.h>
+#include <dvb_frontend.h>
+
+#include "firedtv.h"
+
+static int alloc_channel(struct firedtv *fdtv)
+{
+	int i;
+
+	for (i = 0; i < 16; i++)
+		if (!__test_and_set_bit(i, &fdtv->channel_active))
+			break;
+	return i;
+}
+
+static void collect_channels(struct firedtv *fdtv, int *pidc, u16 pid[])
+{
+	int i, n;
+
+	for (i = 0, n = 0; i < 16; i++)
+		if (test_bit(i, &fdtv->channel_active))
+			pid[n++] = fdtv->channel_pid[i];
+	*pidc = n;
+}
+
+static inline void dealloc_channel(struct firedtv *fdtv, int i)
+{
+	__clear_bit(i, &fdtv->channel_active);
+}
+
+int fdtv_start_feed(struct dvb_demux_feed *dvbdmxfeed)
+{
+	struct firedtv *fdtv = dvbdmxfeed->demux->priv;
+	int pidc, c, ret;
+	u16 pids[16];
+
+	switch (dvbdmxfeed->type) {
+	case DMX_TYPE_TS:
+	case DMX_TYPE_SEC:
+		break;
+	default:
+		dev_err(fdtv->device, "can't start dmx feed: invalid type %u\n",
+			dvbdmxfeed->type);
+		return -EINVAL;
+	}
+
+	if (mutex_lock_interruptible(&fdtv->demux_mutex))
+		return -EINTR;
+
+	if (dvbdmxfeed->type == DMX_TYPE_TS) {
+		switch (dvbdmxfeed->pes_type) {
+		case DMX_TS_PES_VIDEO:
+		case DMX_TS_PES_AUDIO:
+		case DMX_TS_PES_TELETEXT:
+		case DMX_TS_PES_PCR:
+		case DMX_TS_PES_OTHER:
+			c = alloc_channel(fdtv);
+			break;
+		default:
+			dev_err(fdtv->device,
+				"can't start dmx feed: invalid pes type %u\n",
+				dvbdmxfeed->pes_type);
+			ret = -EINVAL;
+			goto out;
+		}
+	} else {
+		c = alloc_channel(fdtv);
+	}
+
+	if (c > 15) {
+		dev_err(fdtv->device, "can't start dmx feed: busy\n");
+		ret = -EBUSY;
+		goto out;
+	}
+
+	dvbdmxfeed->priv = (typeof(dvbdmxfeed->priv))(unsigned long)c;
+	fdtv->channel_pid[c] = dvbdmxfeed->pid;
+	collect_channels(fdtv, &pidc, pids);
+
+	if (dvbdmxfeed->pid == 8192) {
+		ret = avc_tuner_get_ts(fdtv);
+		if (ret) {
+			dealloc_channel(fdtv, c);
+			dev_err(fdtv->device, "can't get TS\n");
+			goto out;
+		}
+	} else {
+		ret = avc_tuner_set_pids(fdtv, pidc, pids);
+		if (ret) {
+			dealloc_channel(fdtv, c);
+			dev_err(fdtv->device, "can't set PIDs\n");
+			goto out;
+		}
+	}
+out:
+	mutex_unlock(&fdtv->demux_mutex);
+
+	return ret;
+}
+
+int fdtv_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
+{
+	struct dvb_demux *demux = dvbdmxfeed->demux;
+	struct firedtv *fdtv = demux->priv;
+	int pidc, c, ret;
+	u16 pids[16];
+
+	if (dvbdmxfeed->type == DMX_TYPE_TS &&
+	    !((dvbdmxfeed->ts_type & TS_PACKET) &&
+	      (demux->dmx.frontend->source != DMX_MEMORY_FE))) {
+
+		if (dvbdmxfeed->ts_type & TS_DECODER) {
+			if (dvbdmxfeed->pes_type >= DMX_TS_PES_OTHER ||
+			    !demux->pesfilter[dvbdmxfeed->pes_type])
+				return -EINVAL;
+
+			demux->pids[dvbdmxfeed->pes_type] |= 0x8000;
+			demux->pesfilter[dvbdmxfeed->pes_type] = NULL;
+		}
+
+		if (!(dvbdmxfeed->ts_type & TS_DECODER &&
+		      dvbdmxfeed->pes_type < DMX_TS_PES_OTHER))
+			return 0;
+	}
+
+	if (mutex_lock_interruptible(&fdtv->demux_mutex))
+		return -EINTR;
+
+	c = (unsigned long)dvbdmxfeed->priv;
+	dealloc_channel(fdtv, c);
+	collect_channels(fdtv, &pidc, pids);
+
+	ret = avc_tuner_set_pids(fdtv, pidc, pids);
+
+	mutex_unlock(&fdtv->demux_mutex);
+
+	return ret;
+}
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+int fdtv_dvb_register(struct firedtv *fdtv, const char *name)
+{
+	int err;
+
+	err = dvb_register_adapter(&fdtv->adapter, name,
+				   THIS_MODULE, fdtv->device, adapter_nr);
+	if (err < 0)
+		goto fail_log;
+
+	/*DMX_TS_FILTERING | DMX_SECTION_FILTERING*/
+	fdtv->demux.dmx.capabilities = 0;
+
+	fdtv->demux.priv	= fdtv;
+	fdtv->demux.filternum	= 16;
+	fdtv->demux.feednum	= 16;
+	fdtv->demux.start_feed	= fdtv_start_feed;
+	fdtv->demux.stop_feed	= fdtv_stop_feed;
+	fdtv->demux.write_to_decoder = NULL;
+
+	err = dvb_dmx_init(&fdtv->demux);
+	if (err)
+		goto fail_unreg_adapter;
+
+	fdtv->dmxdev.filternum    = 16;
+	fdtv->dmxdev.demux        = &fdtv->demux.dmx;
+	fdtv->dmxdev.capabilities = 0;
+
+	err = dvb_dmxdev_init(&fdtv->dmxdev, &fdtv->adapter);
+	if (err)
+		goto fail_dmx_release;
+
+	fdtv->frontend.source = DMX_FRONTEND_0;
+
+	err = fdtv->demux.dmx.add_frontend(&fdtv->demux.dmx, &fdtv->frontend);
+	if (err)
+		goto fail_dmxdev_release;
+
+	err = fdtv->demux.dmx.connect_frontend(&fdtv->demux.dmx,
+					       &fdtv->frontend);
+	if (err)
+		goto fail_rem_frontend;
+
+	err = dvb_net_init(&fdtv->adapter, &fdtv->dvbnet, &fdtv->demux.dmx);
+	if (err)
+		goto fail_disconnect_frontend;
+
+	fdtv_frontend_init(fdtv, name);
+	err = dvb_register_frontend(&fdtv->adapter, &fdtv->fe);
+	if (err)
+		goto fail_net_release;
+
+	err = fdtv_ca_register(fdtv);
+	if (err)
+		dev_info(fdtv->device,
+			 "Conditional Access Module not enabled\n");
+	return 0;
+
+fail_net_release:
+	dvb_net_release(&fdtv->dvbnet);
+fail_disconnect_frontend:
+	fdtv->demux.dmx.close(&fdtv->demux.dmx);
+fail_rem_frontend:
+	fdtv->demux.dmx.remove_frontend(&fdtv->demux.dmx, &fdtv->frontend);
+fail_dmxdev_release:
+	dvb_dmxdev_release(&fdtv->dmxdev);
+fail_dmx_release:
+	dvb_dmx_release(&fdtv->demux);
+fail_unreg_adapter:
+	dvb_unregister_adapter(&fdtv->adapter);
+fail_log:
+	dev_err(fdtv->device, "DVB initialization failed\n");
+	return err;
+}
+
+void fdtv_dvb_unregister(struct firedtv *fdtv)
+{
+	fdtv_ca_release(fdtv);
+	dvb_unregister_frontend(&fdtv->fe);
+	dvb_net_release(&fdtv->dvbnet);
+	fdtv->demux.dmx.close(&fdtv->demux.dmx);
+	fdtv->demux.dmx.remove_frontend(&fdtv->demux.dmx, &fdtv->frontend);
+	dvb_dmxdev_release(&fdtv->dmxdev);
+	dvb_dmx_release(&fdtv->demux);
+	dvb_unregister_adapter(&fdtv->adapter);
+}
diff --git a/drivers/media/firewire/firedtv-fe.c b/drivers/media/firewire/firedtv-fe.c
new file mode 100644
index 0000000..6fe9793
--- /dev/null
+++ b/drivers/media/firewire/firedtv-fe.c
@@ -0,0 +1,254 @@
+/*
+ * FireDTV driver (formerly known as FireSAT)
+ *
+ * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com>
+ * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se>
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License as
+ *	published by the Free Software Foundation; either version 2 of
+ *	the License, or (at your option) any later version.
+ */
+
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/types.h>
+
+#include <dvb_frontend.h>
+
+#include "firedtv.h"
+
+static int fdtv_dvb_init(struct dvb_frontend *fe)
+{
+	struct firedtv *fdtv = fe->sec_priv;
+	int err;
+
+	/* FIXME - allocate free channel at IRM */
+	fdtv->isochannel = fdtv->adapter.num;
+
+	err = cmp_establish_pp_connection(fdtv, fdtv->subunit,
+					  fdtv->isochannel);
+	if (err) {
+		dev_err(fdtv->device,
+			"could not establish point to point connection\n");
+		return err;
+	}
+
+	return fdtv_start_iso(fdtv);
+}
+
+static int fdtv_sleep(struct dvb_frontend *fe)
+{
+	struct firedtv *fdtv = fe->sec_priv;
+
+	fdtv_stop_iso(fdtv);
+	cmp_break_pp_connection(fdtv, fdtv->subunit, fdtv->isochannel);
+	fdtv->isochannel = -1;
+	return 0;
+}
+
+#define LNBCONTROL_DONTCARE 0xff
+
+static int fdtv_diseqc_send_master_cmd(struct dvb_frontend *fe,
+				       struct dvb_diseqc_master_cmd *cmd)
+{
+	struct firedtv *fdtv = fe->sec_priv;
+
+	return avc_lnb_control(fdtv, LNBCONTROL_DONTCARE, LNBCONTROL_DONTCARE,
+			       LNBCONTROL_DONTCARE, 1, cmd);
+}
+
+static int fdtv_diseqc_send_burst(struct dvb_frontend *fe,
+				  fe_sec_mini_cmd_t minicmd)
+{
+	return 0;
+}
+
+static int fdtv_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
+{
+	struct firedtv *fdtv = fe->sec_priv;
+
+	fdtv->tone = tone;
+	return 0;
+}
+
+static int fdtv_set_voltage(struct dvb_frontend *fe,
+			    fe_sec_voltage_t voltage)
+{
+	struct firedtv *fdtv = fe->sec_priv;
+
+	fdtv->voltage = voltage;
+	return 0;
+}
+
+static int fdtv_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+	struct firedtv *fdtv = fe->sec_priv;
+	struct firedtv_tuner_status stat;
+
+	if (avc_tuner_status(fdtv, &stat))
+		return -EINVAL;
+
+	if (stat.no_rf)
+		*status = 0;
+	else
+		*status = FE_HAS_SIGNAL | FE_HAS_VITERBI | FE_HAS_SYNC |
+			  FE_HAS_CARRIER | FE_HAS_LOCK;
+	return 0;
+}
+
+static int fdtv_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+	struct firedtv *fdtv = fe->sec_priv;
+	struct firedtv_tuner_status stat;
+
+	if (avc_tuner_status(fdtv, &stat))
+		return -EINVAL;
+
+	*ber = stat.ber;
+	return 0;
+}
+
+static int fdtv_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
+{
+	struct firedtv *fdtv = fe->sec_priv;
+	struct firedtv_tuner_status stat;
+
+	if (avc_tuner_status(fdtv, &stat))
+		return -EINVAL;
+
+	*strength = stat.signal_strength << 8;
+	return 0;
+}
+
+static int fdtv_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+	struct firedtv *fdtv = fe->sec_priv;
+	struct firedtv_tuner_status stat;
+
+	if (avc_tuner_status(fdtv, &stat))
+		return -EINVAL;
+
+	/* C/N[dB] = -10 * log10(snr / 65535) */
+	*snr = stat.carrier_noise_ratio * 257;
+	return 0;
+}
+
+static int fdtv_read_uncorrected_blocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+	return -EOPNOTSUPP;
+}
+
+static int fdtv_set_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct firedtv *fdtv = fe->sec_priv;
+
+	return avc_tuner_dsd(fdtv, p);
+}
+
+void fdtv_frontend_init(struct firedtv *fdtv, const char *name)
+{
+	struct dvb_frontend_ops *ops = &fdtv->fe.ops;
+	struct dvb_frontend_info *fi = &ops->info;
+
+	ops->init			= fdtv_dvb_init;
+	ops->sleep			= fdtv_sleep;
+
+	ops->set_frontend		= fdtv_set_frontend;
+
+	ops->read_status		= fdtv_read_status;
+	ops->read_ber			= fdtv_read_ber;
+	ops->read_signal_strength	= fdtv_read_signal_strength;
+	ops->read_snr			= fdtv_read_snr;
+	ops->read_ucblocks		= fdtv_read_uncorrected_blocks;
+
+	ops->diseqc_send_master_cmd 	= fdtv_diseqc_send_master_cmd;
+	ops->diseqc_send_burst		= fdtv_diseqc_send_burst;
+	ops->set_tone			= fdtv_set_tone;
+	ops->set_voltage		= fdtv_set_voltage;
+
+	switch (fdtv->type) {
+	case FIREDTV_DVB_S:
+		ops->delsys[0]		= SYS_DVBS;
+
+		fi->frequency_min	= 950000;
+		fi->frequency_max	= 2150000;
+		fi->frequency_stepsize	= 125;
+		fi->symbol_rate_min	= 1000000;
+		fi->symbol_rate_max	= 40000000;
+
+		fi->caps		= FE_CAN_INVERSION_AUTO |
+					  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_FEC_AUTO	|
+					  FE_CAN_QPSK;
+		break;
+
+	case FIREDTV_DVB_S2:
+		ops->delsys[0]		= SYS_DVBS;
+		ops->delsys[1]		= SYS_DVBS2;
+
+		fi->frequency_min	= 950000;
+		fi->frequency_max	= 2150000;
+		fi->frequency_stepsize	= 125;
+		fi->symbol_rate_min	= 1000000;
+		fi->symbol_rate_max	= 40000000;
+
+		fi->caps		= FE_CAN_INVERSION_AUTO |
+					  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_FEC_AUTO       |
+					  FE_CAN_QPSK           |
+					  FE_CAN_2G_MODULATION;
+		break;
+
+	case FIREDTV_DVB_C:
+		ops->delsys[0]		= SYS_DVBC_ANNEX_A;
+
+		fi->frequency_min	= 47000000;
+		fi->frequency_max	= 866000000;
+		fi->frequency_stepsize	= 62500;
+		fi->symbol_rate_min	= 870000;
+		fi->symbol_rate_max	= 6900000;
+
+		fi->caps 		= FE_CAN_INVERSION_AUTO |
+					  FE_CAN_QAM_16		|
+					  FE_CAN_QAM_32		|
+					  FE_CAN_QAM_64		|
+					  FE_CAN_QAM_128	|
+					  FE_CAN_QAM_256	|
+					  FE_CAN_QAM_AUTO;
+		break;
+
+	case FIREDTV_DVB_T:
+		ops->delsys[0]		= SYS_DVBT;
+
+		fi->frequency_min	= 49000000;
+		fi->frequency_max	= 861000000;
+		fi->frequency_stepsize	= 62500;
+
+		fi->caps 		= FE_CAN_INVERSION_AUTO		|
+					  FE_CAN_FEC_2_3		|
+					  FE_CAN_TRANSMISSION_MODE_AUTO |
+					  FE_CAN_GUARD_INTERVAL_AUTO	|
+					  FE_CAN_HIERARCHY_AUTO;
+		break;
+
+	default:
+		dev_err(fdtv->device, "no frontend for model type %d\n",
+			fdtv->type);
+	}
+	strcpy(fi->name, name);
+
+	fdtv->fe.dvb = &fdtv->adapter;
+	fdtv->fe.sec_priv = fdtv;
+}
diff --git a/drivers/media/firewire/firedtv-fw.c b/drivers/media/firewire/firedtv-fw.c
new file mode 100644
index 0000000..e24ec53
--- /dev/null
+++ b/drivers/media/firewire/firedtv-fw.c
@@ -0,0 +1,429 @@
+/*
+ * FireDTV driver -- firewire I/O backend
+ */
+
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/firewire.h>
+#include <linux/firewire-constants.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/mm.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/wait.h>
+#include <linux/workqueue.h>
+
+#include <asm/page.h>
+
+#include <dvb_demux.h>
+
+#include "firedtv.h"
+
+static LIST_HEAD(node_list);
+static DEFINE_SPINLOCK(node_list_lock);
+
+static inline struct fw_device *device_of(struct firedtv *fdtv)
+{
+	return fw_device(fdtv->device->parent);
+}
+
+static int node_req(struct firedtv *fdtv, u64 addr, void *data, size_t len,
+		    int tcode)
+{
+	struct fw_device *device = device_of(fdtv);
+	int rcode, generation = device->generation;
+
+	smp_rmb(); /* node_id vs. generation */
+
+	rcode = fw_run_transaction(device->card, tcode, device->node_id,
+			generation, device->max_speed, addr, data, len);
+
+	return rcode != RCODE_COMPLETE ? -EIO : 0;
+}
+
+int fdtv_lock(struct firedtv *fdtv, u64 addr, void *data)
+{
+	return node_req(fdtv, addr, data, 8, TCODE_LOCK_COMPARE_SWAP);
+}
+
+int fdtv_read(struct firedtv *fdtv, u64 addr, void *data)
+{
+	return node_req(fdtv, addr, data, 4, TCODE_READ_QUADLET_REQUEST);
+}
+
+int fdtv_write(struct firedtv *fdtv, u64 addr, void *data, size_t len)
+{
+	return node_req(fdtv, addr, data, len, TCODE_WRITE_BLOCK_REQUEST);
+}
+
+#define ISO_HEADER_SIZE			4
+#define CIP_HEADER_SIZE			8
+#define MPEG2_TS_HEADER_SIZE		4
+#define MPEG2_TS_SOURCE_PACKET_SIZE	(4 + 188)
+
+#define MAX_PACKET_SIZE		1024  /* 776, rounded up to 2^n */
+#define PACKETS_PER_PAGE	(PAGE_SIZE / MAX_PACKET_SIZE)
+#define N_PACKETS		64    /* buffer size */
+#define N_PAGES			DIV_ROUND_UP(N_PACKETS, PACKETS_PER_PAGE)
+#define IRQ_INTERVAL		16
+
+struct fdtv_ir_context {
+	struct fw_iso_context *context;
+	struct fw_iso_buffer buffer;
+	int interrupt_packet;
+	int current_packet;
+	char *pages[N_PAGES];
+};
+
+static int queue_iso(struct fdtv_ir_context *ctx, int index)
+{
+	struct fw_iso_packet p;
+
+	p.payload_length = MAX_PACKET_SIZE;
+	p.interrupt = !(++ctx->interrupt_packet & (IRQ_INTERVAL - 1));
+	p.skip = 0;
+	p.header_length = ISO_HEADER_SIZE;
+
+	return fw_iso_context_queue(ctx->context, &p, &ctx->buffer,
+				    index * MAX_PACKET_SIZE);
+}
+
+static void handle_iso(struct fw_iso_context *context, u32 cycle,
+		       size_t header_length, void *header, void *data)
+{
+	struct firedtv *fdtv = data;
+	struct fdtv_ir_context *ctx = fdtv->ir_context;
+	__be32 *h, *h_end;
+	int length, err, i = ctx->current_packet;
+	char *p, *p_end;
+
+	for (h = header, h_end = h + header_length / 4; h < h_end; h++) {
+		length = be32_to_cpup(h) >> 16;
+		if (unlikely(length > MAX_PACKET_SIZE)) {
+			dev_err(fdtv->device, "length = %d\n", length);
+			length = MAX_PACKET_SIZE;
+		}
+
+		p = ctx->pages[i / PACKETS_PER_PAGE]
+				+ (i % PACKETS_PER_PAGE) * MAX_PACKET_SIZE;
+		p_end = p + length;
+
+		for (p += CIP_HEADER_SIZE + MPEG2_TS_HEADER_SIZE; p < p_end;
+		     p += MPEG2_TS_SOURCE_PACKET_SIZE)
+			dvb_dmx_swfilter_packets(&fdtv->demux, p, 1);
+
+		err = queue_iso(ctx, i);
+		if (unlikely(err))
+			dev_err(fdtv->device, "requeue failed\n");
+
+		i = (i + 1) & (N_PACKETS - 1);
+	}
+	fw_iso_context_queue_flush(ctx->context);
+	ctx->current_packet = i;
+}
+
+int fdtv_start_iso(struct firedtv *fdtv)
+{
+	struct fdtv_ir_context *ctx;
+	struct fw_device *device = device_of(fdtv);
+	int i, err;
+
+	ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
+	if (!ctx)
+		return -ENOMEM;
+
+	ctx->context = fw_iso_context_create(device->card,
+			FW_ISO_CONTEXT_RECEIVE, fdtv->isochannel,
+			device->max_speed, ISO_HEADER_SIZE, handle_iso, fdtv);
+	if (IS_ERR(ctx->context)) {
+		err = PTR_ERR(ctx->context);
+		goto fail_free;
+	}
+
+	err = fw_iso_buffer_init(&ctx->buffer, device->card,
+				 N_PAGES, DMA_FROM_DEVICE);
+	if (err)
+		goto fail_context_destroy;
+
+	ctx->interrupt_packet = 0;
+	ctx->current_packet = 0;
+
+	for (i = 0; i < N_PAGES; i++)
+		ctx->pages[i] = page_address(ctx->buffer.pages[i]);
+
+	for (i = 0; i < N_PACKETS; i++) {
+		err = queue_iso(ctx, i);
+		if (err)
+			goto fail;
+	}
+
+	err = fw_iso_context_start(ctx->context, -1, 0,
+				   FW_ISO_CONTEXT_MATCH_ALL_TAGS);
+	if (err)
+		goto fail;
+
+	fdtv->ir_context = ctx;
+
+	return 0;
+fail:
+	fw_iso_buffer_destroy(&ctx->buffer, device->card);
+fail_context_destroy:
+	fw_iso_context_destroy(ctx->context);
+fail_free:
+	kfree(ctx);
+
+	return err;
+}
+
+void fdtv_stop_iso(struct firedtv *fdtv)
+{
+	struct fdtv_ir_context *ctx = fdtv->ir_context;
+
+	fw_iso_context_stop(ctx->context);
+	fw_iso_buffer_destroy(&ctx->buffer, device_of(fdtv)->card);
+	fw_iso_context_destroy(ctx->context);
+	kfree(ctx);
+}
+
+static void handle_fcp(struct fw_card *card, struct fw_request *request,
+		       int tcode, int destination, int source, int generation,
+		       unsigned long long offset, void *payload, size_t length,
+		       void *callback_data)
+{
+	struct firedtv *f, *fdtv = NULL;
+	struct fw_device *device;
+	unsigned long flags;
+	int su;
+
+	if (length < 2 || (((u8 *)payload)[0] & 0xf0) != 0)
+		return;
+
+	su = ((u8 *)payload)[1] & 0x7;
+
+	spin_lock_irqsave(&node_list_lock, flags);
+	list_for_each_entry(f, &node_list, list) {
+		device = device_of(f);
+		if (device->generation != generation)
+			continue;
+
+		smp_rmb(); /* node_id vs. generation */
+
+		if (device->card == card &&
+		    device->node_id == source &&
+		    (f->subunit == su || (f->subunit == 0 && su == 0x7))) {
+			fdtv = f;
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&node_list_lock, flags);
+
+	if (fdtv)
+		avc_recv(fdtv, payload, length);
+}
+
+static struct fw_address_handler fcp_handler = {
+	.length           = CSR_FCP_END - CSR_FCP_RESPONSE,
+	.address_callback = handle_fcp,
+};
+
+static const struct fw_address_region fcp_region = {
+	.start	= CSR_REGISTER_BASE + CSR_FCP_RESPONSE,
+	.end	= CSR_REGISTER_BASE + CSR_FCP_END,
+};
+
+static const char * const model_names[] = {
+	[FIREDTV_UNKNOWN] = "unknown type",
+	[FIREDTV_DVB_S]   = "FireDTV S/CI",
+	[FIREDTV_DVB_C]   = "FireDTV C/CI",
+	[FIREDTV_DVB_T]   = "FireDTV T/CI",
+	[FIREDTV_DVB_S2]  = "FireDTV S2  ",
+};
+
+/* Adjust the template string if models with longer names appear. */
+#define MAX_MODEL_NAME_LEN sizeof("FireDTV ????")
+
+static int node_probe(struct device *dev)
+{
+	struct firedtv *fdtv;
+	char name[MAX_MODEL_NAME_LEN];
+	int name_len, i, err;
+
+	fdtv = kzalloc(sizeof(*fdtv), GFP_KERNEL);
+	if (!fdtv)
+		return -ENOMEM;
+
+	dev_set_drvdata(dev, fdtv);
+	fdtv->device		= dev;
+	fdtv->isochannel	= -1;
+	fdtv->voltage		= 0xff;
+	fdtv->tone		= 0xff;
+
+	mutex_init(&fdtv->avc_mutex);
+	init_waitqueue_head(&fdtv->avc_wait);
+	mutex_init(&fdtv->demux_mutex);
+	INIT_WORK(&fdtv->remote_ctrl_work, avc_remote_ctrl_work);
+
+	name_len = fw_csr_string(fw_unit(dev)->directory, CSR_MODEL,
+				 name, sizeof(name));
+	for (i = ARRAY_SIZE(model_names); --i; )
+		if (strlen(model_names[i]) <= name_len &&
+		    strncmp(name, model_names[i], name_len) == 0)
+			break;
+	fdtv->type = i;
+
+	err = fdtv_register_rc(fdtv, dev);
+	if (err)
+		goto fail_free;
+
+	spin_lock_irq(&node_list_lock);
+	list_add_tail(&fdtv->list, &node_list);
+	spin_unlock_irq(&node_list_lock);
+
+	err = avc_identify_subunit(fdtv);
+	if (err)
+		goto fail;
+
+	err = fdtv_dvb_register(fdtv, model_names[fdtv->type]);
+	if (err)
+		goto fail;
+
+	avc_register_remote_control(fdtv);
+
+	return 0;
+fail:
+	spin_lock_irq(&node_list_lock);
+	list_del(&fdtv->list);
+	spin_unlock_irq(&node_list_lock);
+	fdtv_unregister_rc(fdtv);
+fail_free:
+	kfree(fdtv);
+
+	return err;
+}
+
+static int node_remove(struct device *dev)
+{
+	struct firedtv *fdtv = dev_get_drvdata(dev);
+
+	fdtv_dvb_unregister(fdtv);
+
+	spin_lock_irq(&node_list_lock);
+	list_del(&fdtv->list);
+	spin_unlock_irq(&node_list_lock);
+
+	fdtv_unregister_rc(fdtv);
+
+	kfree(fdtv);
+	return 0;
+}
+
+static void node_update(struct fw_unit *unit)
+{
+	struct firedtv *fdtv = dev_get_drvdata(&unit->device);
+
+	if (fdtv->isochannel >= 0)
+		cmp_establish_pp_connection(fdtv, fdtv->subunit,
+					    fdtv->isochannel);
+}
+
+#define MATCH_FLAGS (IEEE1394_MATCH_VENDOR_ID | IEEE1394_MATCH_MODEL_ID | \
+		     IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION)
+
+#define DIGITAL_EVERYWHERE_OUI	0x001287
+#define AVC_UNIT_SPEC_ID_ENTRY	0x00a02d
+#define AVC_SW_VERSION_ENTRY	0x010001
+
+static const struct ieee1394_device_id fdtv_id_table[] = {
+	{
+		/* FloppyDTV S/CI and FloppyDTV S2 */
+		.match_flags	= MATCH_FLAGS,
+		.vendor_id	= DIGITAL_EVERYWHERE_OUI,
+		.model_id	= 0x000024,
+		.specifier_id	= AVC_UNIT_SPEC_ID_ENTRY,
+		.version	= AVC_SW_VERSION_ENTRY,
+	}, {
+		/* FloppyDTV T/CI */
+		.match_flags	= MATCH_FLAGS,
+		.vendor_id	= DIGITAL_EVERYWHERE_OUI,
+		.model_id	= 0x000025,
+		.specifier_id	= AVC_UNIT_SPEC_ID_ENTRY,
+		.version	= AVC_SW_VERSION_ENTRY,
+	}, {
+		/* FloppyDTV C/CI */
+		.match_flags	= MATCH_FLAGS,
+		.vendor_id	= DIGITAL_EVERYWHERE_OUI,
+		.model_id	= 0x000026,
+		.specifier_id	= AVC_UNIT_SPEC_ID_ENTRY,
+		.version	= AVC_SW_VERSION_ENTRY,
+	}, {
+		/* FireDTV S/CI and FloppyDTV S2 */
+		.match_flags	= MATCH_FLAGS,
+		.vendor_id	= DIGITAL_EVERYWHERE_OUI,
+		.model_id	= 0x000034,
+		.specifier_id	= AVC_UNIT_SPEC_ID_ENTRY,
+		.version	= AVC_SW_VERSION_ENTRY,
+	}, {
+		/* FireDTV T/CI */
+		.match_flags	= MATCH_FLAGS,
+		.vendor_id	= DIGITAL_EVERYWHERE_OUI,
+		.model_id	= 0x000035,
+		.specifier_id	= AVC_UNIT_SPEC_ID_ENTRY,
+		.version	= AVC_SW_VERSION_ENTRY,
+	}, {
+		/* FireDTV C/CI */
+		.match_flags	= MATCH_FLAGS,
+		.vendor_id	= DIGITAL_EVERYWHERE_OUI,
+		.model_id	= 0x000036,
+		.specifier_id	= AVC_UNIT_SPEC_ID_ENTRY,
+		.version	= AVC_SW_VERSION_ENTRY,
+	}, {}
+};
+MODULE_DEVICE_TABLE(ieee1394, fdtv_id_table);
+
+static struct fw_driver fdtv_driver = {
+	.driver   = {
+		.owner  = THIS_MODULE,
+		.name   = "firedtv",
+		.bus    = &fw_bus_type,
+		.probe  = node_probe,
+		.remove = node_remove,
+	},
+	.update   = node_update,
+	.id_table = fdtv_id_table,
+};
+
+static int __init fdtv_init(void)
+{
+	int ret;
+
+	ret = fw_core_add_address_handler(&fcp_handler, &fcp_region);
+	if (ret < 0)
+		return ret;
+
+	ret = driver_register(&fdtv_driver.driver);
+	if (ret < 0)
+		fw_core_remove_address_handler(&fcp_handler);
+
+	return ret;
+}
+
+static void __exit fdtv_exit(void)
+{
+	driver_unregister(&fdtv_driver.driver);
+	fw_core_remove_address_handler(&fcp_handler);
+}
+
+module_init(fdtv_init);
+module_exit(fdtv_exit);
+
+MODULE_AUTHOR("Andreas Monitzer <andy@monitzer.com>");
+MODULE_AUTHOR("Ben Backx <ben@bbackx.com>");
+MODULE_DESCRIPTION("FireDTV DVB Driver");
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("FireDTV DVB");
diff --git a/drivers/media/firewire/firedtv-rc.c b/drivers/media/firewire/firedtv-rc.c
new file mode 100644
index 0000000..f82d4a9
--- /dev/null
+++ b/drivers/media/firewire/firedtv-rc.c
@@ -0,0 +1,196 @@
+/*
+ * FireDTV driver (formerly known as FireSAT)
+ *
+ * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.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/bitops.h>
+#include <linux/input.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/workqueue.h>
+
+#include "firedtv.h"
+
+/* fixed table with older keycodes, geared towards MythTV */
+static const u16 oldtable[] = {
+
+	/* code from device: 0x4501...0x451f */
+
+	KEY_ESC,
+	KEY_F9,
+	KEY_1,
+	KEY_2,
+	KEY_3,
+	KEY_4,
+	KEY_5,
+	KEY_6,
+	KEY_7,
+	KEY_8,
+	KEY_9,
+	KEY_I,
+	KEY_0,
+	KEY_ENTER,
+	KEY_RED,
+	KEY_UP,
+	KEY_GREEN,
+	KEY_F10,
+	KEY_SPACE,
+	KEY_F11,
+	KEY_YELLOW,
+	KEY_DOWN,
+	KEY_BLUE,
+	KEY_Z,
+	KEY_P,
+	KEY_PAGEDOWN,
+	KEY_LEFT,
+	KEY_W,
+	KEY_RIGHT,
+	KEY_P,
+	KEY_M,
+
+	/* code from device: 0x4540...0x4542 */
+
+	KEY_R,
+	KEY_V,
+	KEY_C,
+};
+
+/* user-modifiable table for a remote as sold in 2008 */
+static const u16 keytable[] = {
+
+	/* code from device: 0x0300...0x031f */
+
+	[0x00] = KEY_POWER,
+	[0x01] = KEY_SLEEP,
+	[0x02] = KEY_STOP,
+	[0x03] = KEY_OK,
+	[0x04] = KEY_RIGHT,
+	[0x05] = KEY_1,
+	[0x06] = KEY_2,
+	[0x07] = KEY_3,
+	[0x08] = KEY_LEFT,
+	[0x09] = KEY_4,
+	[0x0a] = KEY_5,
+	[0x0b] = KEY_6,
+	[0x0c] = KEY_UP,
+	[0x0d] = KEY_7,
+	[0x0e] = KEY_8,
+	[0x0f] = KEY_9,
+	[0x10] = KEY_DOWN,
+	[0x11] = KEY_TITLE,	/* "OSD" - fixme */
+	[0x12] = KEY_0,
+	[0x13] = KEY_F20,	/* "16:9" - fixme */
+	[0x14] = KEY_SCREEN,	/* "FULL" - fixme */
+	[0x15] = KEY_MUTE,
+	[0x16] = KEY_SUBTITLE,
+	[0x17] = KEY_RECORD,
+	[0x18] = KEY_TEXT,
+	[0x19] = KEY_AUDIO,
+	[0x1a] = KEY_RED,
+	[0x1b] = KEY_PREVIOUS,
+	[0x1c] = KEY_REWIND,
+	[0x1d] = KEY_PLAYPAUSE,
+	[0x1e] = KEY_NEXT,
+	[0x1f] = KEY_VOLUMEUP,
+
+	/* code from device: 0x0340...0x0354 */
+
+	[0x20] = KEY_CHANNELUP,
+	[0x21] = KEY_F21,	/* "4:3" - fixme */
+	[0x22] = KEY_TV,
+	[0x23] = KEY_DVD,
+	[0x24] = KEY_VCR,
+	[0x25] = KEY_AUX,
+	[0x26] = KEY_GREEN,
+	[0x27] = KEY_YELLOW,
+	[0x28] = KEY_BLUE,
+	[0x29] = KEY_CHANNEL,	/* "CH.LIST" */
+	[0x2a] = KEY_VENDOR,	/* "CI" - fixme */
+	[0x2b] = KEY_VOLUMEDOWN,
+	[0x2c] = KEY_CHANNELDOWN,
+	[0x2d] = KEY_LAST,
+	[0x2e] = KEY_INFO,
+	[0x2f] = KEY_FORWARD,
+	[0x30] = KEY_LIST,
+	[0x31] = KEY_FAVORITES,
+	[0x32] = KEY_MENU,
+	[0x33] = KEY_EPG,
+	[0x34] = KEY_EXIT,
+};
+
+int fdtv_register_rc(struct firedtv *fdtv, struct device *dev)
+{
+	struct input_dev *idev;
+	int i, err;
+
+	idev = input_allocate_device();
+	if (!idev)
+		return -ENOMEM;
+
+	fdtv->remote_ctrl_dev = idev;
+	idev->name = "FireDTV remote control";
+	idev->dev.parent = dev;
+	idev->evbit[0] = BIT_MASK(EV_KEY);
+	idev->keycode = kmemdup(keytable, sizeof(keytable), GFP_KERNEL);
+	if (!idev->keycode) {
+		err = -ENOMEM;
+		goto fail;
+	}
+	idev->keycodesize = sizeof(keytable[0]);
+	idev->keycodemax = ARRAY_SIZE(keytable);
+
+	for (i = 0; i < ARRAY_SIZE(keytable); i++)
+		set_bit(keytable[i], idev->keybit);
+
+	err = input_register_device(idev);
+	if (err)
+		goto fail_free_keymap;
+
+	return 0;
+
+fail_free_keymap:
+	kfree(idev->keycode);
+fail:
+	input_free_device(idev);
+	return err;
+}
+
+void fdtv_unregister_rc(struct firedtv *fdtv)
+{
+	cancel_work_sync(&fdtv->remote_ctrl_work);
+	kfree(fdtv->remote_ctrl_dev->keycode);
+	input_unregister_device(fdtv->remote_ctrl_dev);
+}
+
+void fdtv_handle_rc(struct firedtv *fdtv, unsigned int code)
+{
+	struct input_dev *idev = fdtv->remote_ctrl_dev;
+	u16 *keycode = idev->keycode;
+
+	if (code >= 0x0300 && code <= 0x031f)
+		code = keycode[code - 0x0300];
+	else if (code >= 0x0340 && code <= 0x0354)
+		code = keycode[code - 0x0320];
+	else if (code >= 0x4501 && code <= 0x451f)
+		code = oldtable[code - 0x4501];
+	else if (code >= 0x4540 && code <= 0x4542)
+		code = oldtable[code - 0x4521];
+	else {
+		printk(KERN_DEBUG "firedtv: invalid key code 0x%04x "
+		       "from remote control\n", code);
+		return;
+	}
+
+	input_report_key(idev, code, 1);
+	input_sync(idev);
+	input_report_key(idev, code, 0);
+	input_sync(idev);
+}
diff --git a/drivers/media/firewire/firedtv.h b/drivers/media/firewire/firedtv.h
new file mode 100644
index 0000000..4fdcd8c
--- /dev/null
+++ b/drivers/media/firewire/firedtv.h
@@ -0,0 +1,168 @@
+/*
+ * FireDTV driver (formerly known as FireSAT)
+ *
+ * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com>
+ * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se>
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the 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 _FIREDTV_H
+#define _FIREDTV_H
+
+#include <linux/dvb/dmx.h>
+#include <linux/dvb/frontend.h>
+#include <linux/list.h>
+#include <linux/mod_devicetable.h>
+#include <linux/mutex.h>
+#include <linux/spinlock_types.h>
+#include <linux/types.h>
+#include <linux/wait.h>
+#include <linux/workqueue.h>
+
+#include <demux.h>
+#include <dmxdev.h>
+#include <dvb_demux.h>
+#include <dvb_frontend.h>
+#include <dvb_net.h>
+#include <dvbdev.h>
+
+struct firedtv_tuner_status {
+	unsigned active_system:8;
+	unsigned searching:1;
+	unsigned moving:1;
+	unsigned no_rf:1;
+	unsigned input:1;
+	unsigned selected_antenna:7;
+	unsigned ber:32;
+	unsigned signal_strength:8;
+	unsigned raster_frequency:2;
+	unsigned rf_frequency:22;
+	unsigned man_dep_info_length:8;
+	unsigned front_end_error:1;
+	unsigned antenna_error:1;
+	unsigned front_end_power_status:1;
+	unsigned power_supply:1;
+	unsigned carrier_noise_ratio:16;
+	unsigned power_supply_voltage:8;
+	unsigned antenna_voltage:8;
+	unsigned firewire_bus_voltage:8;
+	unsigned ca_mmi:1;
+	unsigned ca_pmt_reply:1;
+	unsigned ca_date_time_request:1;
+	unsigned ca_application_info:1;
+	unsigned ca_module_present_status:1;
+	unsigned ca_dvb_flag:1;
+	unsigned ca_error_flag:1;
+	unsigned ca_initialization_status:1;
+};
+
+enum model_type {
+	FIREDTV_UNKNOWN = 0,
+	FIREDTV_DVB_S   = 1,
+	FIREDTV_DVB_C   = 2,
+	FIREDTV_DVB_T   = 3,
+	FIREDTV_DVB_S2  = 4,
+};
+
+struct device;
+struct input_dev;
+struct fdtv_ir_context;
+
+struct firedtv {
+	struct device *device;
+	struct list_head list;
+
+	struct dvb_adapter	adapter;
+	struct dmxdev		dmxdev;
+	struct dvb_demux	demux;
+	struct dmx_frontend	frontend;
+	struct dvb_net		dvbnet;
+	struct dvb_frontend	fe;
+
+	struct dvb_device	*cadev;
+	int			ca_last_command;
+	int			ca_time_interval;
+
+	struct mutex		avc_mutex;
+	wait_queue_head_t	avc_wait;
+	bool			avc_reply_received;
+	struct work_struct	remote_ctrl_work;
+	struct input_dev	*remote_ctrl_dev;
+
+	enum model_type		type;
+	char			subunit;
+	char			isochannel;
+	struct fdtv_ir_context	*ir_context;
+
+	fe_sec_voltage_t	voltage;
+	fe_sec_tone_mode_t	tone;
+
+	struct mutex		demux_mutex;
+	unsigned long		channel_active;
+	u16			channel_pid[16];
+
+	int			avc_data_length;
+	u8			avc_data[512];
+};
+
+/* firedtv-avc.c */
+int avc_recv(struct firedtv *fdtv, void *data, size_t length);
+int avc_tuner_status(struct firedtv *fdtv, struct firedtv_tuner_status *stat);
+struct dtv_frontend_properties;
+int avc_tuner_dsd(struct firedtv *fdtv, struct dtv_frontend_properties *params);
+int avc_tuner_set_pids(struct firedtv *fdtv, unsigned char pidc, u16 pid[]);
+int avc_tuner_get_ts(struct firedtv *fdtv);
+int avc_identify_subunit(struct firedtv *fdtv);
+struct dvb_diseqc_master_cmd;
+int avc_lnb_control(struct firedtv *fdtv, char voltage, char burst,
+		    char conttone, char nrdiseq,
+		    struct dvb_diseqc_master_cmd *diseqcmd);
+void avc_remote_ctrl_work(struct work_struct *work);
+int avc_register_remote_control(struct firedtv *fdtv);
+int avc_ca_app_info(struct firedtv *fdtv, char *app_info, unsigned int *len);
+int avc_ca_info(struct firedtv *fdtv, char *app_info, unsigned int *len);
+int avc_ca_reset(struct firedtv *fdtv);
+int avc_ca_pmt(struct firedtv *fdtv, char *app_info, int length);
+int avc_ca_get_time_date(struct firedtv *fdtv, int *interval);
+int avc_ca_enter_menu(struct firedtv *fdtv);
+int avc_ca_get_mmi(struct firedtv *fdtv, char *mmi_object, unsigned int *len);
+int cmp_establish_pp_connection(struct firedtv *fdtv, int plug, int channel);
+void cmp_break_pp_connection(struct firedtv *fdtv, int plug, int channel);
+
+/* firedtv-ci.c */
+int fdtv_ca_register(struct firedtv *fdtv);
+void fdtv_ca_release(struct firedtv *fdtv);
+
+/* firedtv-dvb.c */
+int fdtv_start_feed(struct dvb_demux_feed *dvbdmxfeed);
+int fdtv_stop_feed(struct dvb_demux_feed *dvbdmxfeed);
+int fdtv_dvb_register(struct firedtv *fdtv, const char *name);
+void fdtv_dvb_unregister(struct firedtv *fdtv);
+
+/* firedtv-fe.c */
+void fdtv_frontend_init(struct firedtv *fdtv, const char *name);
+
+/* firedtv-fw.c */
+int fdtv_lock(struct firedtv *fdtv, u64 addr, void *data);
+int fdtv_read(struct firedtv *fdtv, u64 addr, void *data);
+int fdtv_write(struct firedtv *fdtv, u64 addr, void *data, size_t len);
+int fdtv_start_iso(struct firedtv *fdtv);
+void fdtv_stop_iso(struct firedtv *fdtv);
+
+/* firedtv-rc.c */
+#ifdef CONFIG_DVB_FIREDTV_INPUT
+int fdtv_register_rc(struct firedtv *fdtv, struct device *dev);
+void fdtv_unregister_rc(struct firedtv *fdtv);
+void fdtv_handle_rc(struct firedtv *fdtv, unsigned int code);
+#else
+static inline int fdtv_register_rc(struct firedtv *fdtv,
+				   struct device *dev) { return 0; }
+static inline void fdtv_unregister_rc(struct firedtv *fdtv) {}
+static inline void fdtv_handle_rc(struct firedtv *fdtv, unsigned int code) {}
+#endif
+
+#endif /* _FIREDTV_H */
diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
new file mode 100644
index 0000000..0e0793a
--- /dev/null
+++ b/drivers/media/i2c/Kconfig
@@ -0,0 +1,584 @@
+#
+# Generic video config states
+#
+
+config VIDEO_BTCX
+	depends on PCI
+	tristate
+
+config VIDEO_TVEEPROM
+	tristate
+	depends on I2C
+
+#
+# Multimedia Video device configuration
+#
+
+if VIDEO_V4L2
+
+config VIDEO_IR_I2C
+	tristate "I2C module for IR" if !MEDIA_SUBDRV_AUTOSELECT
+	depends on I2C && RC_CORE
+	default y
+	---help---
+	  Most boards have an IR chip directly connected via GPIO. However,
+	  some video boards have the IR connected via I2C bus.
+
+	  If your board doesn't have an I2C IR chip, you may disable this
+	  option.
+
+	  In doubt, say Y.
+
+#
+# Encoder / Decoder module configuration
+#
+
+menu "Encoders, decoders, sensors and other helper chips"
+	visible if !MEDIA_SUBDRV_AUTOSELECT
+
+comment "Audio decoders, processors and mixers"
+
+config VIDEO_TVAUDIO
+	tristate "Simple audio decoder chips"
+	depends on VIDEO_V4L2 && I2C
+	---help---
+	  Support for several audio decoder chips found on some bt8xx boards:
+	  Philips: tda9840, tda9873h, tda9874h/a, tda9850, tda985x, tea6300,
+		   tea6320, tea6420, tda8425, ta8874z.
+	  Microchip: pic16c54 based design on ProVideo PV951 board.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called tvaudio.
+
+config VIDEO_TDA7432
+	tristate "Philips TDA7432 audio processor"
+	depends on VIDEO_V4L2 && I2C
+	---help---
+	  Support for tda7432 audio decoder chip found on some bt8xx boards.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called tda7432.
+
+config VIDEO_TDA9840
+	tristate "Philips TDA9840 audio processor"
+	depends on I2C
+	---help---
+	  Support for tda9840 audio decoder chip found on some Zoran boards.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called tda9840.
+
+config VIDEO_TEA6415C
+	tristate "Philips TEA6415C audio processor"
+	depends on I2C
+	---help---
+	  Support for tea6415c audio decoder chip found on some bt8xx boards.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called tea6415c.
+
+config VIDEO_TEA6420
+	tristate "Philips TEA6420 audio processor"
+	depends on I2C
+	---help---
+	  Support for tea6420 audio decoder chip found on some bt8xx boards.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called tea6420.
+
+config VIDEO_MSP3400
+	tristate "Micronas MSP34xx audio decoders"
+	depends on VIDEO_V4L2 && I2C
+	---help---
+	  Support for the Micronas MSP34xx series of audio decoders.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called msp3400.
+
+config VIDEO_CS5345
+	tristate "Cirrus Logic CS5345 audio ADC"
+	depends on VIDEO_V4L2 && I2C
+	---help---
+	  Support for the Cirrus Logic CS5345 24-bit, 192 kHz
+	  stereo A/D converter.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called cs5345.
+
+config VIDEO_CS53L32A
+	tristate "Cirrus Logic CS53L32A audio ADC"
+	depends on VIDEO_V4L2 && I2C
+	---help---
+	  Support for the Cirrus Logic CS53L32A low voltage
+	  stereo A/D converter.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called cs53l32a.
+
+config VIDEO_TLV320AIC23B
+	tristate "Texas Instruments TLV320AIC23B audio codec"
+	depends on VIDEO_V4L2 && I2C && EXPERIMENTAL
+	---help---
+	  Support for the Texas Instruments TLV320AIC23B audio codec.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called tlv320aic23b.
+
+config VIDEO_WM8775
+	tristate "Wolfson Microelectronics WM8775 audio ADC with input mixer"
+	depends on VIDEO_V4L2 && I2C
+	---help---
+	  Support for the Wolfson Microelectronics WM8775 high
+	  performance stereo A/D Converter with a 4 channel input mixer.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called wm8775.
+
+config VIDEO_WM8739
+	tristate "Wolfson Microelectronics WM8739 stereo audio ADC"
+	depends on VIDEO_V4L2 && I2C
+	---help---
+	  Support for the Wolfson Microelectronics WM8739
+	  stereo A/D Converter.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called wm8739.
+
+config VIDEO_VP27SMPX
+	tristate "Panasonic VP27s internal MPX"
+	depends on VIDEO_V4L2 && I2C
+	---help---
+	  Support for the internal MPX of the Panasonic VP27s tuner.
+
+	  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_ADV7180
+	tristate "Analog Devices ADV7180 decoder"
+	depends on VIDEO_V4L2 && I2C
+	---help---
+	  Support for the Analog Devices ADV7180 video decoder.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called adv7180.
+
+config VIDEO_ADV7183
+	tristate "Analog Devices ADV7183 decoder"
+	depends on VIDEO_V4L2 && I2C
+	---help---
+	  V4l2 subdevice driver for the Analog Devices
+	  ADV7183 video decoder.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called adv7183.
+
+config VIDEO_ADV7604
+	tristate "Analog Devices ADV7604 decoder"
+	depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API
+	---help---
+	  Support for the Analog Devices ADV7604 video decoder.
+
+	  This is a Analog Devices Component/Graphics Digitizer
+	  with 4:1 Multiplexed HDMI Receiver.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called adv7604.
+
+config VIDEO_BT819
+	tristate "BT819A VideoStream decoder"
+	depends on VIDEO_V4L2 && I2C
+	---help---
+	  Support for BT819A video decoder.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called bt819.
+
+config VIDEO_BT856
+	tristate "BT856 VideoStream decoder"
+	depends on VIDEO_V4L2 && I2C
+	---help---
+	  Support for BT856 video decoder.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called bt856.
+
+config VIDEO_BT866
+	tristate "BT866 VideoStream decoder"
+	depends on VIDEO_V4L2 && I2C
+	---help---
+	  Support for BT866 video decoder.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called bt866.
+
+config VIDEO_KS0127
+	tristate "KS0127 video decoder"
+	depends on VIDEO_V4L2 && I2C
+	---help---
+	  Support for KS0127 video decoder.
+
+	  This chip is used on AverMedia AVS6EYES Zoran-based MJPEG
+	  cards.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ks0127.
+
+config VIDEO_SAA7110
+	tristate "Philips SAA7110 video decoder"
+	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_SAA711X
+	tristate "Philips SAA7111/3/4/5 video decoders"
+	depends on VIDEO_V4L2 && I2C
+	---help---
+	  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.
+
+config VIDEO_SAA7191
+	tristate "Philips SAA7191 video decoder"
+	depends on VIDEO_V4L2 && I2C
+	---help---
+	  Support for the Philips SAA7191 video decoder.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called saa7191.
+
+config VIDEO_TVP514X
+	tristate "Texas Instruments TVP514x video decoder"
+	depends on VIDEO_V4L2 && I2C
+	---help---
+	  This is a Video4Linux2 sensor-level driver for the TI TVP5146/47
+	  decoder. It is currently working with the TI OMAP3 camera
+	  controller.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called tvp514x.
+
+config VIDEO_TVP5150
+	tristate "Texas Instruments TVP5150 video decoder"
+	depends on VIDEO_V4L2 && I2C
+	---help---
+	  Support for the Texas Instruments TVP5150 video decoder.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called tvp5150.
+
+config VIDEO_TVP7002
+	tristate "Texas Instruments TVP7002 video decoder"
+	depends on VIDEO_V4L2 && I2C
+	---help---
+	  Support for the Texas Instruments TVP7002 video decoder.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called tvp7002.
+
+config VIDEO_VPX3220
+	tristate "vpx3220a, vpx3216b & vpx3214c video decoders"
+	depends on VIDEO_V4L2 && I2C
+	---help---
+	  Support for VPX322x video decoders.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called vpx3220.
+
+comment "Video and audio decoders"
+
+config VIDEO_SAA717X
+	tristate "Philips SAA7171/3/4 audio/video decoders"
+	depends on VIDEO_V4L2 && I2C
+	---help---
+	  Support for the Philips SAA7171/3/4 audio/video decoders.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called saa717x.
+
+source "drivers/media/i2c/cx25840/Kconfig"
+
+comment "MPEG video encoders"
+
+config VIDEO_CX2341X
+	tristate "Conexant CX2341x MPEG encoders"
+	depends on VIDEO_V4L2
+	---help---
+	  Support for the Conexant CX23416 MPEG encoders
+	  and CX23415 MPEG encoder/decoders.
+
+	  This module currently supports the encoding functions only.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called cx2341x.
+
+comment "Video encoders"
+
+config VIDEO_SAA7127
+	tristate "Philips SAA7127/9 digital video encoders"
+	depends on VIDEO_V4L2 && I2C
+	---help---
+	  Support for the Philips SAA7127/9 digital video encoders.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called saa7127.
+
+config VIDEO_SAA7185
+	tristate "Philips SAA7185 video encoder"
+	depends on VIDEO_V4L2 && I2C
+	---help---
+	  Support for the Philips SAA7185 video encoder.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called saa7185.
+
+config VIDEO_ADV7170
+	tristate "Analog Devices ADV7170 video encoder"
+	depends on VIDEO_V4L2 && I2C
+	---help---
+	  Support for the Analog Devices ADV7170 video encoder driver
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called adv7170.
+
+config VIDEO_ADV7175
+	tristate "Analog Devices ADV7175 video encoder"
+	depends on VIDEO_V4L2 && I2C
+	---help---
+	  Support for the Analog Devices ADV7175 video encoder driver
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called adv7175.
+
+config VIDEO_ADV7343
+	tristate "ADV7343 video encoder"
+	depends on I2C
+	help
+	  Support for Analog Devices I2C bus based ADV7343 encoder.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called adv7343.
+
+config VIDEO_ADV7393
+	tristate "ADV7393 video encoder"
+	depends on I2C
+	help
+	  Support for Analog Devices I2C bus based ADV7393 encoder.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called adv7393.
+
+config VIDEO_AD9389B
+	tristate "Analog Devices AD9389B encoder"
+	depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API
+	---help---
+	  Support for the Analog Devices AD9389B video encoder.
+
+	  This is a Analog Devices HDMI transmitter.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ad9389b.
+
+config VIDEO_AK881X
+	tristate "AK8813/AK8814 video encoders"
+	depends on I2C
+	help
+	  Video output driver for AKM AK8813 and AK8814 TV encoders
+
+comment "Camera sensor devices"
+
+config VIDEO_APTINA_PLL
+	tristate
+
+config VIDEO_SMIAPP_PLL
+	tristate
+
+config VIDEO_OV7670
+	tristate "OmniVision OV7670 sensor support"
+	depends on I2C && VIDEO_V4L2
+	depends on MEDIA_CAMERA_SUPPORT
+	---help---
+	  This is a Video4Linux2 sensor-level driver for the OmniVision
+	  OV7670 VGA camera.  It currently only works with the M88ALP01
+	  controller.
+
+config VIDEO_VS6624
+	tristate "ST VS6624 sensor support"
+	depends on VIDEO_V4L2 && I2C
+	depends on MEDIA_CAMERA_SUPPORT
+	---help---
+	  This is a Video4Linux2 sensor-level driver for the ST VS6624
+	  camera.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called vs6624.
+
+config VIDEO_MT9M032
+	tristate "MT9M032 camera sensor support"
+	depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
+	depends on MEDIA_CAMERA_SUPPORT
+	select VIDEO_APTINA_PLL
+	---help---
+	  This driver supports MT9M032 camera sensors from Aptina, monochrome
+	  models only.
+
+config VIDEO_MT9P031
+	tristate "Aptina MT9P031 support"
+	depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
+	depends on MEDIA_CAMERA_SUPPORT
+	select VIDEO_APTINA_PLL
+	---help---
+	  This is a Video4Linux2 sensor-level driver for the Aptina
+	  (Micron) mt9p031 5 Mpixel camera.
+
+config VIDEO_MT9T001
+	tristate "Aptina MT9T001 support"
+	depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
+	depends on MEDIA_CAMERA_SUPPORT
+	---help---
+	  This is a Video4Linux2 sensor-level driver for the Aptina
+	  (Micron) mt0t001 3 Mpixel camera.
+
+config VIDEO_MT9V011
+	tristate "Micron mt9v011 sensor support"
+	depends on I2C && VIDEO_V4L2
+	depends on MEDIA_CAMERA_SUPPORT
+	---help---
+	  This is a Video4Linux2 sensor-level driver for the Micron
+	  mt0v011 1.3 Mpixel camera.  It currently only works with the
+	  em28xx driver.
+
+config VIDEO_MT9V032
+	tristate "Micron MT9V032 sensor support"
+	depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
+	depends on MEDIA_CAMERA_SUPPORT
+	---help---
+	  This is a Video4Linux2 sensor-level driver for the Micron
+	  MT9V032 752x480 CMOS sensor.
+
+config VIDEO_TCM825X
+	tristate "TCM825x camera sensor support"
+	depends on I2C && VIDEO_V4L2
+	depends on MEDIA_CAMERA_SUPPORT
+	---help---
+	  This is a driver for the Toshiba TCM825x VGA camera sensor.
+	  It is used for example in Nokia N800.
+
+config VIDEO_SR030PC30
+	tristate "Siliconfile SR030PC30 sensor support"
+	depends on I2C && VIDEO_V4L2
+	depends on MEDIA_CAMERA_SUPPORT
+	---help---
+	  This driver supports SR030PC30 VGA camera from Siliconfile
+
+config VIDEO_NOON010PC30
+	tristate "Siliconfile NOON010PC30 sensor support"
+	depends on I2C && VIDEO_V4L2 && EXPERIMENTAL && VIDEO_V4L2_SUBDEV_API
+	depends on MEDIA_CAMERA_SUPPORT
+	---help---
+	  This driver supports NOON010PC30 CIF camera from Siliconfile
+
+source "drivers/media/i2c/m5mols/Kconfig"
+
+config VIDEO_S5K6AA
+	tristate "Samsung S5K6AAFX sensor support"
+	depends on MEDIA_CAMERA_SUPPORT
+	depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
+	---help---
+	  This is a V4L2 sensor-level driver for Samsung S5K6AA(FX) 1.3M
+	  camera sensor with an embedded SoC image signal processor.
+
+source "drivers/media/i2c/smiapp/Kconfig"
+
+comment "Flash devices"
+
+config VIDEO_ADP1653
+	tristate "ADP1653 flash support"
+	depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER
+	depends on MEDIA_CAMERA_SUPPORT
+	---help---
+	  This is a driver for the ADP1653 flash controller. It is used for
+	  example in Nokia N900.
+
+config VIDEO_AS3645A
+	tristate "AS3645A flash driver support"
+	depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER
+	depends on MEDIA_CAMERA_SUPPORT
+	---help---
+	  This is a driver for the AS3645A and LM3555 flash controllers. It has
+	  build in control for flash, torch and indicator LEDs.
+
+comment "Video improvement chips"
+
+config VIDEO_UPD64031A
+	tristate "NEC Electronics uPD64031A Ghost Reduction"
+	depends on VIDEO_V4L2 && I2C
+	---help---
+	  Support for the NEC Electronics uPD64031A Ghost Reduction
+	  video chip. It is most often found in NTSC TV cards made for
+	  Japan and is used to reduce the 'ghosting' effect that can
+	  be present in analog TV broadcasts.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called upd64031a.
+
+config VIDEO_UPD64083
+	tristate "NEC Electronics uPD64083 3-Dimensional Y/C separation"
+	depends on VIDEO_V4L2 && I2C
+	---help---
+	  Support for the NEC Electronics uPD64083 3-Dimensional Y/C
+	  separation video chip. It is used to improve the quality of
+	  the colors of a composite signal.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called upd64083.
+
+comment "Miscelaneous helper chips"
+
+config VIDEO_THS7303
+	tristate "THS7303 Video Amplifier"
+	depends on I2C
+	help
+	  Support for TI THS7303 video amplifier
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ths7303.
+
+config VIDEO_M52790
+	tristate "Mitsubishi M52790 A/V switch"
+	depends on VIDEO_V4L2 && I2C
+	---help---
+	 Support for the Mitsubishi M52790 A/V switch.
+
+	 To compile this driver as a module, choose M here: the
+	 module will be called m52790.
+endmenu
+
+menu "Sensors used on soc_camera driver"
+
+if SOC_CAMERA
+	source "drivers/media/i2c/soc_camera/Kconfig"
+endif
+
+endmenu
+
+endif
diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile
new file mode 100644
index 0000000..4a270f7
--- /dev/null
+++ b/drivers/media/i2c/Makefile
@@ -0,0 +1,66 @@
+msp3400-objs	:=	msp3400-driver.o msp3400-kthreads.o
+obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o
+
+obj-$(CONFIG_VIDEO_SMIAPP)	+= smiapp/
+obj-$(CONFIG_VIDEO_CX25840) += cx25840/
+obj-$(CONFIG_VIDEO_M5MOLS)	+= m5mols/
+obj-y				+= soc_camera/
+
+obj-$(CONFIG_VIDEO_APTINA_PLL) += aptina-pll.o
+obj-$(CONFIG_VIDEO_TVAUDIO) += tvaudio.o
+obj-$(CONFIG_VIDEO_TDA7432) += tda7432.o
+obj-$(CONFIG_VIDEO_SAA6588) += saa6588.o
+obj-$(CONFIG_VIDEO_TDA9840) += tda9840.o
+obj-$(CONFIG_VIDEO_TEA6415C) += tea6415c.o
+obj-$(CONFIG_VIDEO_TEA6420) += tea6420.o
+obj-$(CONFIG_VIDEO_SAA7110) += saa7110.o
+obj-$(CONFIG_VIDEO_SAA711X) += saa7115.o
+obj-$(CONFIG_VIDEO_SAA717X) += saa717x.o
+obj-$(CONFIG_VIDEO_SAA7127) += saa7127.o
+obj-$(CONFIG_VIDEO_SAA7185) += saa7185.o
+obj-$(CONFIG_VIDEO_SAA7191) += saa7191.o
+obj-$(CONFIG_VIDEO_ADV7170) += adv7170.o
+obj-$(CONFIG_VIDEO_ADV7175) += adv7175.o
+obj-$(CONFIG_VIDEO_ADV7180) += adv7180.o
+obj-$(CONFIG_VIDEO_ADV7183) += adv7183.o
+obj-$(CONFIG_VIDEO_ADV7343) += adv7343.o
+obj-$(CONFIG_VIDEO_ADV7393) += adv7393.o
+obj-$(CONFIG_VIDEO_ADV7604) += adv7604.o
+obj-$(CONFIG_VIDEO_AD9389B) += ad9389b.o
+obj-$(CONFIG_VIDEO_VPX3220) += vpx3220.o
+obj-$(CONFIG_VIDEO_VS6624)  += vs6624.o
+obj-$(CONFIG_VIDEO_BT819) += bt819.o
+obj-$(CONFIG_VIDEO_BT856) += bt856.o
+obj-$(CONFIG_VIDEO_BT866) += bt866.o
+obj-$(CONFIG_VIDEO_KS0127) += ks0127.o
+obj-$(CONFIG_VIDEO_THS7303) += ths7303.o
+obj-$(CONFIG_VIDEO_TVP5150) += tvp5150.o
+obj-$(CONFIG_VIDEO_TVP514X) += tvp514x.o
+obj-$(CONFIG_VIDEO_TVP7002) += tvp7002.o
+obj-$(CONFIG_VIDEO_CS5345) += cs5345.o
+obj-$(CONFIG_VIDEO_CS53L32A) += cs53l32a.o
+obj-$(CONFIG_VIDEO_M52790) += m52790.o
+obj-$(CONFIG_VIDEO_TLV320AIC23B) += tlv320aic23b.o
+obj-$(CONFIG_VIDEO_WM8775) += wm8775.o
+obj-$(CONFIG_VIDEO_WM8739) += wm8739.o
+obj-$(CONFIG_VIDEO_VP27SMPX) += vp27smpx.o
+obj-$(CONFIG_VIDEO_UPD64031A) += upd64031a.o
+obj-$(CONFIG_VIDEO_UPD64083) += upd64083.o
+obj-$(CONFIG_VIDEO_OV7670) 	+= ov7670.o
+obj-$(CONFIG_VIDEO_TCM825X) += tcm825x.o
+obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o
+obj-$(CONFIG_VIDEO_MT9M032) += mt9m032.o
+obj-$(CONFIG_VIDEO_MT9P031) += mt9p031.o
+obj-$(CONFIG_VIDEO_MT9T001) += mt9t001.o
+obj-$(CONFIG_VIDEO_MT9V011) += mt9v011.o
+obj-$(CONFIG_VIDEO_MT9V032) += mt9v032.o
+obj-$(CONFIG_VIDEO_SR030PC30)	+= sr030pc30.o
+obj-$(CONFIG_VIDEO_NOON010PC30)	+= noon010pc30.o
+obj-$(CONFIG_VIDEO_S5K6AA)	+= s5k6aa.o
+obj-$(CONFIG_VIDEO_ADP1653)	+= adp1653.o
+obj-$(CONFIG_VIDEO_AS3645A)	+= as3645a.o
+obj-$(CONFIG_VIDEO_SMIAPP_PLL)	+= smiapp-pll.o
+obj-$(CONFIG_VIDEO_BTCX)  += btcx-risc.o
+obj-$(CONFIG_VIDEO_CX2341X) += cx2341x.o
+obj-$(CONFIG_VIDEO_AK881X)		+= ak881x.o
+obj-$(CONFIG_VIDEO_IR_I2C)  += ir-kbd-i2c.o
diff --git a/drivers/media/i2c/ad9389b.c b/drivers/media/i2c/ad9389b.c
new file mode 100644
index 0000000..c2886b6
--- /dev/null
+++ b/drivers/media/i2c/ad9389b.c
@@ -0,0 +1,1328 @@
+/*
+ * Analog Devices AD9389B/AD9889B video encoder driver
+ *
+ * Copyright 2012 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/*
+ * References (c = chapter, p = page):
+ * REF_01 - Analog Devices, Programming Guide, AD9889B/AD9389B,
+ * HDMI Transitter, Rev. A, October 2010
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/videodev2.h>
+#include <linux/workqueue.h>
+#include <linux/v4l2-dv-timings.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ctrls.h>
+#include <media/ad9389b.h>
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "debug level (0-2)");
+
+MODULE_DESCRIPTION("Analog Devices AD9389B/AD9889B video encoder driver");
+MODULE_AUTHOR("Hans Verkuil <hans.verkuil@cisco.com>");
+MODULE_AUTHOR("Martin Bugge <marbugge@cisco.com>");
+MODULE_LICENSE("GPL");
+
+#define MASK_AD9389B_EDID_RDY_INT   0x04
+#define MASK_AD9389B_MSEN_INT       0x40
+#define MASK_AD9389B_HPD_INT        0x80
+
+#define MASK_AD9389B_HPD_DETECT     0x40
+#define MASK_AD9389B_MSEN_DETECT    0x20
+#define MASK_AD9389B_EDID_RDY       0x10
+
+#define EDID_MAX_RETRIES (8)
+#define EDID_DELAY 250
+#define EDID_MAX_SEGM 8
+
+/*
+**********************************************************************
+*
+*  Arrays with configuration parameters for the AD9389B
+*
+**********************************************************************
+*/
+
+struct i2c_reg_value {
+	u8 reg;
+	u8 value;
+};
+
+struct ad9389b_state_edid {
+	/* total number of blocks */
+	u32 blocks;
+	/* Number of segments read */
+	u32 segments;
+	u8 data[EDID_MAX_SEGM * 256];
+	/* Number of EDID read retries left */
+	unsigned read_retries;
+};
+
+struct ad9389b_state {
+	struct ad9389b_platform_data pdata;
+	struct v4l2_subdev sd;
+	struct media_pad pad;
+	struct v4l2_ctrl_handler hdl;
+	int chip_revision;
+	/* Is the ad9389b powered on? */
+	bool power_on;
+	/* Did we receive hotplug and rx-sense signals? */
+	bool have_monitor;
+	/* timings from s_dv_timings */
+	struct v4l2_dv_timings dv_timings;
+	/* controls */
+	struct v4l2_ctrl *hdmi_mode_ctrl;
+	struct v4l2_ctrl *hotplug_ctrl;
+	struct v4l2_ctrl *rx_sense_ctrl;
+	struct v4l2_ctrl *have_edid0_ctrl;
+	struct v4l2_ctrl *rgb_quantization_range_ctrl;
+	struct i2c_client *edid_i2c_client;
+	struct ad9389b_state_edid edid;
+	/* Running counter of the number of detected EDIDs (for debugging) */
+	unsigned edid_detect_counter;
+	struct workqueue_struct *work_queue;
+	struct delayed_work edid_handler; /* work entry */
+};
+
+static void ad9389b_check_monitor_present_status(struct v4l2_subdev *sd);
+static bool ad9389b_check_edid_status(struct v4l2_subdev *sd);
+static void ad9389b_setup(struct v4l2_subdev *sd);
+static int ad9389b_s_i2s_clock_freq(struct v4l2_subdev *sd, u32 freq);
+static int ad9389b_s_clock_freq(struct v4l2_subdev *sd, u32 freq);
+
+static inline struct ad9389b_state *get_ad9389b_state(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct ad9389b_state, sd);
+}
+
+static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
+{
+	return &container_of(ctrl->handler, struct ad9389b_state, hdl)->sd;
+}
+
+/* ------------------------ I2C ----------------------------------------------- */
+
+static int ad9389b_rd(struct v4l2_subdev *sd, u8 reg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	return i2c_smbus_read_byte_data(client, reg);
+}
+
+static int ad9389b_wr(struct v4l2_subdev *sd, u8 reg, u8 val)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	int ret;
+	int i;
+
+	for (i = 0; i < 3; i++) {
+		ret = i2c_smbus_write_byte_data(client, reg, val);
+		if (ret == 0)
+			return 0;
+	}
+	v4l2_err(sd, "I2C Write Problem\n");
+	return ret;
+}
+
+/* To set specific bits in the register, a clear-mask is given (to be AND-ed),
+   and then the value-mask (to be OR-ed). */
+static inline void ad9389b_wr_and_or(struct v4l2_subdev *sd, u8 reg,
+						u8 clr_mask, u8 val_mask)
+{
+	ad9389b_wr(sd, reg, (ad9389b_rd(sd, reg) & clr_mask) | val_mask);
+}
+
+static void ad9389b_edid_rd(struct v4l2_subdev *sd, u16 len, u8 *buf)
+{
+	struct ad9389b_state *state = get_ad9389b_state(sd);
+	int i;
+
+	v4l2_dbg(1, debug, sd, "%s:\n", __func__);
+
+	for (i = 0; i < len; i++)
+		buf[i] = i2c_smbus_read_byte_data(state->edid_i2c_client, i);
+}
+
+static inline bool ad9389b_have_hotplug(struct v4l2_subdev *sd)
+{
+	return ad9389b_rd(sd, 0x42) & MASK_AD9389B_HPD_DETECT;
+}
+
+static inline bool ad9389b_have_rx_sense(struct v4l2_subdev *sd)
+{
+	return ad9389b_rd(sd, 0x42) & MASK_AD9389B_MSEN_DETECT;
+}
+
+static void ad9389b_csc_conversion_mode(struct v4l2_subdev *sd, u8 mode)
+{
+	ad9389b_wr_and_or(sd, 0x17, 0xe7, (mode & 0x3)<<3);
+	ad9389b_wr_and_or(sd, 0x18, 0x9f, (mode & 0x3)<<5);
+}
+
+static void ad9389b_csc_coeff(struct v4l2_subdev *sd,
+			      u16 A1, u16 A2, u16 A3, u16 A4,
+			      u16 B1, u16 B2, u16 B3, u16 B4,
+			      u16 C1, u16 C2, u16 C3, u16 C4)
+{
+	/* A */
+	ad9389b_wr_and_or(sd, 0x18, 0xe0, A1>>8);
+	ad9389b_wr(sd, 0x19, A1);
+	ad9389b_wr_and_or(sd, 0x1A, 0xe0, A2>>8);
+	ad9389b_wr(sd, 0x1B, A2);
+	ad9389b_wr_and_or(sd, 0x1c, 0xe0, A3>>8);
+	ad9389b_wr(sd, 0x1d, A3);
+	ad9389b_wr_and_or(sd, 0x1e, 0xe0, A4>>8);
+	ad9389b_wr(sd, 0x1f, A4);
+
+	/* B */
+	ad9389b_wr_and_or(sd, 0x20, 0xe0, B1>>8);
+	ad9389b_wr(sd, 0x21, B1);
+	ad9389b_wr_and_or(sd, 0x22, 0xe0, B2>>8);
+	ad9389b_wr(sd, 0x23, B2);
+	ad9389b_wr_and_or(sd, 0x24, 0xe0, B3>>8);
+	ad9389b_wr(sd, 0x25, B3);
+	ad9389b_wr_and_or(sd, 0x26, 0xe0, B4>>8);
+	ad9389b_wr(sd, 0x27, B4);
+
+	/* C */
+	ad9389b_wr_and_or(sd, 0x28, 0xe0, C1>>8);
+	ad9389b_wr(sd, 0x29, C1);
+	ad9389b_wr_and_or(sd, 0x2A, 0xe0, C2>>8);
+	ad9389b_wr(sd, 0x2B, C2);
+	ad9389b_wr_and_or(sd, 0x2C, 0xe0, C3>>8);
+	ad9389b_wr(sd, 0x2D, C3);
+	ad9389b_wr_and_or(sd, 0x2E, 0xe0, C4>>8);
+	ad9389b_wr(sd, 0x2F, C4);
+}
+
+static void ad9389b_csc_rgb_full2limit(struct v4l2_subdev *sd, bool enable)
+{
+	if (enable) {
+		u8 csc_mode = 0;
+
+		ad9389b_csc_conversion_mode(sd, csc_mode);
+		ad9389b_csc_coeff(sd,
+				  4096-564, 0, 0, 256,
+				  0, 4096-564, 0, 256,
+				  0, 0, 4096-564, 256);
+		/* enable CSC */
+		ad9389b_wr_and_or(sd, 0x3b, 0xfe, 0x1);
+		/* AVI infoframe: Limited range RGB (16-235) */
+		ad9389b_wr_and_or(sd, 0xcd, 0xf9, 0x02);
+	} else {
+		/* disable CSC */
+		ad9389b_wr_and_or(sd, 0x3b, 0xfe, 0x0);
+		/* AVI infoframe: Full range RGB (0-255) */
+		ad9389b_wr_and_or(sd, 0xcd, 0xf9, 0x04);
+	}
+}
+
+static void ad9389b_set_IT_content_AVI_InfoFrame(struct v4l2_subdev *sd)
+{
+	struct ad9389b_state *state = get_ad9389b_state(sd);
+
+	if (state->dv_timings.bt.standards & V4L2_DV_BT_STD_CEA861) {
+		/* CEA format, not IT  */
+		ad9389b_wr_and_or(sd, 0xcd, 0xbf, 0x00);
+	} else {
+		/* IT format */
+		ad9389b_wr_and_or(sd, 0xcd, 0xbf, 0x40);
+	}
+}
+
+static int ad9389b_set_rgb_quantization_mode(struct v4l2_subdev *sd, struct v4l2_ctrl *ctrl)
+{
+	struct ad9389b_state *state = get_ad9389b_state(sd);
+
+	switch (ctrl->val) {
+	case V4L2_DV_RGB_RANGE_AUTO:
+		/* automatic */
+		if (state->dv_timings.bt.standards & V4L2_DV_BT_STD_CEA861) {
+			/* cea format, RGB limited range (16-235) */
+			ad9389b_csc_rgb_full2limit(sd, true);
+		} else {
+			/* not cea format, RGB full range (0-255) */
+			ad9389b_csc_rgb_full2limit(sd, false);
+		}
+		break;
+	case V4L2_DV_RGB_RANGE_LIMITED:
+		/* RGB limited range (16-235) */
+		ad9389b_csc_rgb_full2limit(sd, true);
+		break;
+	case V4L2_DV_RGB_RANGE_FULL:
+		/* RGB full range (0-255) */
+		ad9389b_csc_rgb_full2limit(sd, false);
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static void ad9389b_set_manual_pll_gear(struct v4l2_subdev *sd, u32 pixelclock)
+{
+	u8 gear;
+
+	/* Workaround for TMDS PLL problem
+	 * The TMDS PLL in AD9389b change gear when the chip is heated above a
+	 * certain temperature. The output is disabled when the PLL change gear
+	 * so the monitor has to lock on the signal again. A workaround for
+	 * this is to use the manual PLL gears. This is a solution from Analog
+	 * Devices that is not documented in the datasheets.
+	 * 0x98 [7] = enable manual gearing. 0x98 [6:4] = gear
+	 *
+	 * The pixel frequency ranges are based on readout of the gear the
+	 * automatic gearing selects for different pixel clocks
+	 * (read from 0x9e [3:1]).
+	 */
+
+	if (pixelclock > 140000000)
+		gear = 0xc0; /* 4th gear */
+	else if (pixelclock > 117000000)
+		gear = 0xb0; /* 3rd gear */
+	else if (pixelclock > 87000000)
+		gear = 0xa0; /* 2nd gear */
+	else if (pixelclock > 60000000)
+		gear = 0x90; /* 1st gear */
+	else
+		gear = 0x80; /* 0th gear */
+
+	ad9389b_wr_and_or(sd, 0x98, 0x0f, gear);
+}
+
+/* ------------------------------ CTRL OPS ------------------------------ */
+
+static int ad9389b_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct v4l2_subdev *sd = to_sd(ctrl);
+	struct ad9389b_state *state = get_ad9389b_state(sd);
+
+	v4l2_dbg(1, debug, sd,
+		"%s: ctrl id: %d, ctrl->val %d\n", __func__, ctrl->id, ctrl->val);
+
+	if (state->hdmi_mode_ctrl == ctrl) {
+		/* Set HDMI or DVI-D */
+		ad9389b_wr_and_or(sd, 0xaf, 0xfd,
+				ctrl->val == V4L2_DV_TX_MODE_HDMI ? 0x02 : 0x00);
+		return 0;
+	}
+	if (state->rgb_quantization_range_ctrl == ctrl)
+		return ad9389b_set_rgb_quantization_mode(sd, ctrl);
+	return -EINVAL;
+}
+
+static const struct v4l2_ctrl_ops ad9389b_ctrl_ops = {
+	.s_ctrl = ad9389b_s_ctrl,
+};
+
+/* ---------------------------- CORE OPS ------------------------------------------- */
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int ad9389b_g_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;
+	reg->val = ad9389b_rd(sd, reg->reg & 0xff);
+	reg->size = 1;
+	return 0;
+}
+
+static int ad9389b_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;
+	ad9389b_wr(sd, reg->reg & 0xff, reg->val & 0xff);
+	return 0;
+}
+#endif
+
+static int ad9389b_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_AD9389B, 0);
+}
+
+static int ad9389b_log_status(struct v4l2_subdev *sd)
+{
+	struct ad9389b_state *state = get_ad9389b_state(sd);
+	struct ad9389b_state_edid *edid = &state->edid;
+
+	static const char * const states[] = {
+		"in reset",
+		"reading EDID",
+		"idle",
+		"initializing HDCP",
+		"HDCP enabled",
+		"initializing HDCP repeater",
+		"6", "7", "8", "9", "A", "B", "C", "D", "E", "F"
+	};
+	static const char * const errors[] = {
+		"no error",
+		"bad receiver BKSV",
+		"Ri mismatch",
+		"Pj mismatch",
+		"i2c error",
+		"timed out",
+		"max repeater cascade exceeded",
+		"hash check failed",
+		"too many devices",
+		"9", "A", "B", "C", "D", "E", "F"
+	};
+
+	u8 manual_gear;
+
+	v4l2_info(sd, "chip revision %d\n", state->chip_revision);
+	v4l2_info(sd, "power %s\n", state->power_on ? "on" : "off");
+	v4l2_info(sd, "%s hotplug, %s Rx Sense, %s EDID (%d block(s))\n",
+			(ad9389b_rd(sd, 0x42) & MASK_AD9389B_HPD_DETECT) ?
+							"detected" : "no",
+			(ad9389b_rd(sd, 0x42) & MASK_AD9389B_MSEN_DETECT) ?
+							"detected" : "no",
+			edid->segments ? "found" : "no", edid->blocks);
+	if (state->have_monitor) {
+		v4l2_info(sd, "%s output %s\n",
+				  (ad9389b_rd(sd, 0xaf) & 0x02) ?
+				  "HDMI" : "DVI-D",
+				  (ad9389b_rd(sd, 0xa1) & 0x3c) ?
+				  "disabled" : "enabled");
+	}
+	v4l2_info(sd, "ad9389b: %s\n", (ad9389b_rd(sd, 0xb8) & 0x40) ?
+					"encrypted" : "no encryption");
+	v4l2_info(sd, "state: %s, error: %s, detect count: %u, msk/irq: %02x/%02x\n",
+			states[ad9389b_rd(sd, 0xc8) & 0xf],
+			errors[ad9389b_rd(sd, 0xc8) >> 4],
+			state->edid_detect_counter,
+			ad9389b_rd(sd, 0x94), ad9389b_rd(sd, 0x96));
+	manual_gear = ad9389b_rd(sd, 0x98) & 0x80;
+	v4l2_info(sd, "ad9389b: RGB quantization: %s range\n",
+			ad9389b_rd(sd, 0x3b) & 0x01 ? "limited" : "full");
+	v4l2_info(sd, "ad9389b: %s gear %d\n",
+		  manual_gear ? "manual" : "automatic",
+		  manual_gear ? ((ad9389b_rd(sd, 0x98) & 0x70) >> 4) :
+				((ad9389b_rd(sd, 0x9e) & 0x0e) >> 1));
+	if (state->have_monitor) {
+		if (ad9389b_rd(sd, 0xaf) & 0x02) {
+			/* HDMI only */
+			u8 manual_cts = ad9389b_rd(sd, 0x0a) & 0x80;
+			u32 N = (ad9389b_rd(sd, 0x01) & 0xf) << 16 |
+				 ad9389b_rd(sd, 0x02) << 8 |
+				 ad9389b_rd(sd, 0x03);
+			u8 vic_detect = ad9389b_rd(sd, 0x3e) >> 2;
+			u8 vic_sent = ad9389b_rd(sd, 0x3d) & 0x3f;
+			u32 CTS;
+
+			if (manual_cts)
+				CTS = (ad9389b_rd(sd, 0x07) & 0xf) << 16 |
+				       ad9389b_rd(sd, 0x08) << 8 |
+				       ad9389b_rd(sd, 0x09);
+			else
+				CTS = (ad9389b_rd(sd, 0x04) & 0xf) << 16 |
+				       ad9389b_rd(sd, 0x05) << 8 |
+				       ad9389b_rd(sd, 0x06);
+			N = (ad9389b_rd(sd, 0x01) & 0xf) << 16 |
+			     ad9389b_rd(sd, 0x02) << 8 |
+			     ad9389b_rd(sd, 0x03);
+
+			v4l2_info(sd, "ad9389b: CTS %s mode: N %d, CTS %d\n",
+				manual_cts ? "manual" : "automatic", N, CTS);
+
+			v4l2_info(sd, "ad9389b: VIC: detected %d, sent %d\n",
+				vic_detect, vic_sent);
+		}
+	}
+	if (state->dv_timings.type == V4L2_DV_BT_656_1120) {
+		struct v4l2_bt_timings *bt = bt = &state->dv_timings.bt;
+		u32 frame_width = bt->width + bt->hfrontporch +
+			bt->hsync + bt->hbackporch;
+		u32 frame_height = bt->height + bt->vfrontporch +
+			bt->vsync + bt->vbackporch;
+		u32 frame_size = frame_width * frame_height;
+
+		v4l2_info(sd, "timings: %ux%u%s%u (%ux%u). Pix freq. = %u Hz. Polarities = 0x%x\n",
+			bt->width, bt->height, bt->interlaced ? "i" : "p",
+			frame_size > 0 ?  (unsigned)bt->pixelclock / frame_size : 0,
+			frame_width, frame_height,
+			(unsigned)bt->pixelclock, bt->polarities);
+	} else {
+		v4l2_info(sd, "no timings set\n");
+	}
+	return 0;
+}
+
+/* Power up/down ad9389b */
+static int ad9389b_s_power(struct v4l2_subdev *sd, int on)
+{
+	struct ad9389b_state *state = get_ad9389b_state(sd);
+	struct ad9389b_platform_data *pdata = &state->pdata;
+	const int retries = 20;
+	int i;
+
+	v4l2_dbg(1, debug, sd, "%s: power %s\n", __func__, on ? "on" : "off");
+
+	state->power_on = on;
+
+	if (!on) {
+		/* Power down */
+		ad9389b_wr_and_or(sd, 0x41, 0xbf, 0x40);
+		return true;
+	}
+
+	/* Power up */
+	/* The ad9389b does not always come up immediately.
+	   Retry multiple times. */
+	for (i = 0; i < retries; i++) {
+		ad9389b_wr_and_or(sd, 0x41, 0xbf, 0x0);
+		if ((ad9389b_rd(sd, 0x41) & 0x40) == 0)
+			break;
+		ad9389b_wr_and_or(sd, 0x41, 0xbf, 0x40);
+		msleep(10);
+	}
+	if (i == retries) {
+		v4l2_dbg(1, debug, sd, "failed to powerup the ad9389b\n");
+		ad9389b_s_power(sd, 0);
+		return false;
+	}
+	if (i > 1)
+		v4l2_dbg(1, debug, sd,
+			"needed %d retries to powerup the ad9389b\n", i);
+
+	/* Select chip: AD9389B */
+	ad9389b_wr_and_or(sd, 0xba, 0xef, 0x10);
+
+	/* Reserved registers that must be set according to REF_01 p. 11*/
+	ad9389b_wr_and_or(sd, 0x98, 0xf0, 0x07);
+	ad9389b_wr(sd, 0x9c, 0x38);
+	ad9389b_wr_and_or(sd, 0x9d, 0xfc, 0x01);
+
+	/* Differential output drive strength */
+	if (pdata->diff_data_drive_strength > 0)
+		ad9389b_wr(sd, 0xa2, pdata->diff_data_drive_strength);
+	else
+		ad9389b_wr(sd, 0xa2, 0x87);
+
+	if (pdata->diff_clk_drive_strength > 0)
+		ad9389b_wr(sd, 0xa3, pdata->diff_clk_drive_strength);
+	else
+		ad9389b_wr(sd, 0xa3, 0x87);
+
+	ad9389b_wr(sd, 0x0a, 0x01);
+	ad9389b_wr(sd, 0xbb, 0xff);
+
+	/* Set number of attempts to read the EDID */
+	ad9389b_wr(sd, 0xc9, 0xf);
+	return true;
+}
+
+/* Enable interrupts */
+static void ad9389b_set_isr(struct v4l2_subdev *sd, bool enable)
+{
+	u8 irqs = MASK_AD9389B_HPD_INT | MASK_AD9389B_MSEN_INT;
+	u8 irqs_rd;
+	int retries = 100;
+
+	/* The datasheet says that the EDID ready interrupt should be
+	   disabled if there is no hotplug. */
+	if (!enable)
+		irqs = 0;
+	else if (ad9389b_have_hotplug(sd))
+		irqs |= MASK_AD9389B_EDID_RDY_INT;
+
+	/*
+	 * This i2c write can fail (approx. 1 in 1000 writes). But it
+	 * is essential that this register is correct, so retry it
+	 * multiple times.
+	 *
+	 * Note that the i2c write does not report an error, but the readback
+	 * clearly shows the wrong value.
+	 */
+	do {
+		ad9389b_wr(sd, 0x94, irqs);
+		irqs_rd = ad9389b_rd(sd, 0x94);
+	} while (retries-- && irqs_rd != irqs);
+
+	if (irqs_rd != irqs)
+		v4l2_err(sd, "Could not set interrupts: hw failure?\n");
+}
+
+/* Interrupt handler */
+static int ad9389b_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
+{
+	u8 irq_status;
+
+	/* disable interrupts to prevent a race condition */
+	ad9389b_set_isr(sd, false);
+	irq_status = ad9389b_rd(sd, 0x96);
+	/* clear detected interrupts */
+	ad9389b_wr(sd, 0x96, irq_status);
+
+	if (irq_status & (MASK_AD9389B_HPD_INT | MASK_AD9389B_MSEN_INT))
+		ad9389b_check_monitor_present_status(sd);
+	if (irq_status & MASK_AD9389B_EDID_RDY_INT)
+		ad9389b_check_edid_status(sd);
+
+	/* enable interrupts */
+	ad9389b_set_isr(sd, true);
+	*handled = true;
+	return 0;
+}
+
+static const struct v4l2_subdev_core_ops ad9389b_core_ops = {
+	.log_status = ad9389b_log_status,
+	.g_chip_ident = ad9389b_g_chip_ident,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.g_register = ad9389b_g_register,
+	.s_register = ad9389b_s_register,
+#endif
+	.s_power = ad9389b_s_power,
+	.interrupt_service_routine = ad9389b_isr,
+};
+
+/* ------------------------------ PAD OPS ------------------------------ */
+
+static int ad9389b_get_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edid)
+{
+	struct ad9389b_state *state = get_ad9389b_state(sd);
+
+	if (edid->pad != 0)
+		return -EINVAL;
+	if (edid->blocks == 0 || edid->blocks > 256)
+		return -EINVAL;
+	if (!edid->edid)
+		return -EINVAL;
+	if (!state->edid.segments) {
+		v4l2_dbg(1, debug, sd, "EDID segment 0 not found\n");
+		return -ENODATA;
+	}
+	if (edid->start_block >= state->edid.segments * 2)
+		return -E2BIG;
+	if (edid->blocks + edid->start_block >= state->edid.segments * 2)
+		edid->blocks = state->edid.segments * 2 - edid->start_block;
+	memcpy(edid->edid, &state->edid.data[edid->start_block * 128],
+				128 * edid->blocks);
+	return 0;
+}
+
+static const struct v4l2_subdev_pad_ops ad9389b_pad_ops = {
+	.get_edid = ad9389b_get_edid,
+};
+
+/* ------------------------------ VIDEO OPS ------------------------------ */
+
+/* Enable/disable ad9389b output */
+static int ad9389b_s_stream(struct v4l2_subdev *sd, int enable)
+{
+	struct ad9389b_state *state = get_ad9389b_state(sd);
+
+	v4l2_dbg(1, debug, sd, "%s: %sable\n", __func__, (enable ? "en" : "dis"));
+
+	ad9389b_wr_and_or(sd, 0xa1, ~0x3c, (enable ? 0 : 0x3c));
+	if (enable) {
+		ad9389b_check_monitor_present_status(sd);
+	} else {
+		ad9389b_s_power(sd, 0);
+		state->have_monitor = false;
+	}
+	return 0;
+}
+
+static const struct v4l2_dv_timings ad9389b_timings[] = {
+	V4L2_DV_BT_CEA_720X480P59_94,
+	V4L2_DV_BT_CEA_720X576P50,
+	V4L2_DV_BT_CEA_1280X720P24,
+	V4L2_DV_BT_CEA_1280X720P25,
+	V4L2_DV_BT_CEA_1280X720P30,
+	V4L2_DV_BT_CEA_1280X720P50,
+	V4L2_DV_BT_CEA_1280X720P60,
+	V4L2_DV_BT_CEA_1920X1080P24,
+	V4L2_DV_BT_CEA_1920X1080P25,
+	V4L2_DV_BT_CEA_1920X1080P30,
+	V4L2_DV_BT_CEA_1920X1080P50,
+	V4L2_DV_BT_CEA_1920X1080P60,
+
+	V4L2_DV_BT_DMT_640X350P85,
+	V4L2_DV_BT_DMT_640X400P85,
+	V4L2_DV_BT_DMT_720X400P85,
+	V4L2_DV_BT_DMT_640X480P60,
+	V4L2_DV_BT_DMT_640X480P72,
+	V4L2_DV_BT_DMT_640X480P75,
+	V4L2_DV_BT_DMT_640X480P85,
+	V4L2_DV_BT_DMT_800X600P56,
+	V4L2_DV_BT_DMT_800X600P60,
+	V4L2_DV_BT_DMT_800X600P72,
+	V4L2_DV_BT_DMT_800X600P75,
+	V4L2_DV_BT_DMT_800X600P85,
+	V4L2_DV_BT_DMT_848X480P60,
+	V4L2_DV_BT_DMT_1024X768P60,
+	V4L2_DV_BT_DMT_1024X768P70,
+	V4L2_DV_BT_DMT_1024X768P75,
+	V4L2_DV_BT_DMT_1024X768P85,
+	V4L2_DV_BT_DMT_1152X864P75,
+	V4L2_DV_BT_DMT_1280X768P60_RB,
+	V4L2_DV_BT_DMT_1280X768P60,
+	V4L2_DV_BT_DMT_1280X768P75,
+	V4L2_DV_BT_DMT_1280X768P85,
+	V4L2_DV_BT_DMT_1280X800P60_RB,
+	V4L2_DV_BT_DMT_1280X800P60,
+	V4L2_DV_BT_DMT_1280X800P75,
+	V4L2_DV_BT_DMT_1280X800P85,
+	V4L2_DV_BT_DMT_1280X960P60,
+	V4L2_DV_BT_DMT_1280X960P85,
+	V4L2_DV_BT_DMT_1280X1024P60,
+	V4L2_DV_BT_DMT_1280X1024P75,
+	V4L2_DV_BT_DMT_1280X1024P85,
+	V4L2_DV_BT_DMT_1360X768P60,
+	V4L2_DV_BT_DMT_1400X1050P60_RB,
+	V4L2_DV_BT_DMT_1400X1050P60,
+	V4L2_DV_BT_DMT_1400X1050P75,
+	V4L2_DV_BT_DMT_1400X1050P85,
+	V4L2_DV_BT_DMT_1440X900P60_RB,
+	V4L2_DV_BT_DMT_1440X900P60,
+	V4L2_DV_BT_DMT_1600X1200P60,
+	V4L2_DV_BT_DMT_1680X1050P60_RB,
+	V4L2_DV_BT_DMT_1680X1050P60,
+	V4L2_DV_BT_DMT_1792X1344P60,
+	V4L2_DV_BT_DMT_1856X1392P60,
+	V4L2_DV_BT_DMT_1920X1200P60_RB,
+	V4L2_DV_BT_DMT_1366X768P60,
+	V4L2_DV_BT_DMT_1920X1080P60,
+	{},
+};
+
+static int ad9389b_s_dv_timings(struct v4l2_subdev *sd,
+				struct v4l2_dv_timings *timings)
+{
+	struct ad9389b_state *state = get_ad9389b_state(sd);
+	int i;
+
+	v4l2_dbg(1, debug, sd, "%s:\n", __func__);
+
+	/* quick sanity check */
+	if (timings->type != V4L2_DV_BT_656_1120)
+		return -EINVAL;
+
+	if (timings->bt.interlaced)
+		return -EINVAL;
+	if (timings->bt.pixelclock < 27000000 ||
+	    timings->bt.pixelclock > 170000000)
+		return -EINVAL;
+
+	/* Fill the optional fields .standards and .flags in struct v4l2_dv_timings
+	   if the format is listed in ad9389b_timings[] */
+	for (i = 0; ad9389b_timings[i].bt.width; i++) {
+		if (v4l_match_dv_timings(timings, &ad9389b_timings[i], 0)) {
+			*timings = ad9389b_timings[i];
+			break;
+		}
+	}
+
+	timings->bt.flags &= ~V4L2_DV_FL_REDUCED_FPS;
+
+	/* save timings */
+	state->dv_timings = *timings;
+
+	/* update quantization range based on new dv_timings */
+	ad9389b_set_rgb_quantization_mode(sd, state->rgb_quantization_range_ctrl);
+
+	/* update PLL gear based on new dv_timings */
+	if (state->pdata.tmds_pll_gear == AD9389B_TMDS_PLL_GEAR_SEMI_AUTOMATIC)
+		ad9389b_set_manual_pll_gear(sd, (u32)timings->bt.pixelclock);
+
+	/* update AVI infoframe */
+	ad9389b_set_IT_content_AVI_InfoFrame(sd);
+
+	return 0;
+}
+
+static int ad9389b_g_dv_timings(struct v4l2_subdev *sd,
+				struct v4l2_dv_timings *timings)
+{
+	struct ad9389b_state *state = get_ad9389b_state(sd);
+
+	v4l2_dbg(1, debug, sd, "%s:\n", __func__);
+
+	if (!timings)
+		return -EINVAL;
+
+	*timings = state->dv_timings;
+
+	return 0;
+}
+
+static int ad9389b_enum_dv_timings(struct v4l2_subdev *sd,
+			struct v4l2_enum_dv_timings *timings)
+{
+	if (timings->index >= ARRAY_SIZE(ad9389b_timings))
+		return -EINVAL;
+
+	memset(timings->reserved, 0, sizeof(timings->reserved));
+	timings->timings = ad9389b_timings[timings->index];
+	return 0;
+}
+
+static int ad9389b_dv_timings_cap(struct v4l2_subdev *sd,
+			struct v4l2_dv_timings_cap *cap)
+{
+	cap->type = V4L2_DV_BT_656_1120;
+	cap->bt.max_width = 1920;
+	cap->bt.max_height = 1200;
+	cap->bt.min_pixelclock = 27000000;
+	cap->bt.max_pixelclock = 170000000;
+	cap->bt.standards = V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT |
+			 V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT;
+	cap->bt.capabilities = V4L2_DV_BT_CAP_PROGRESSIVE |
+		V4L2_DV_BT_CAP_REDUCED_BLANKING | V4L2_DV_BT_CAP_CUSTOM;
+	return 0;
+}
+
+static const struct v4l2_subdev_video_ops ad9389b_video_ops = {
+	.s_stream = ad9389b_s_stream,
+	.s_dv_timings = ad9389b_s_dv_timings,
+	.g_dv_timings = ad9389b_g_dv_timings,
+	.enum_dv_timings = ad9389b_enum_dv_timings,
+	.dv_timings_cap = ad9389b_dv_timings_cap,
+};
+
+static int ad9389b_s_audio_stream(struct v4l2_subdev *sd, int enable)
+{
+	v4l2_dbg(1, debug, sd, "%s: %sable\n", __func__, (enable ? "en" : "dis"));
+
+	if (enable)
+		ad9389b_wr_and_or(sd, 0x45, 0x3f, 0x80);
+	else
+		ad9389b_wr_and_or(sd, 0x45, 0x3f, 0x40);
+
+	return 0;
+}
+
+static int ad9389b_s_clock_freq(struct v4l2_subdev *sd, u32 freq)
+{
+	u32 N;
+
+	switch (freq) {
+	case 32000: N = 4096; break;
+	case 44100: N = 6272; break;
+	case 48000: N = 6144; break;
+	case 88200: N = 12544; break;
+	case 96000: N = 12288; break;
+	case 176400: N = 25088; break;
+	case 192000: N = 24576; break;
+	default:
+		return -EINVAL;
+	}
+
+	/* Set N (used with CTS to regenerate the audio clock) */
+	ad9389b_wr(sd, 0x01, (N >> 16) & 0xf);
+	ad9389b_wr(sd, 0x02, (N >> 8) & 0xff);
+	ad9389b_wr(sd, 0x03, N & 0xff);
+
+	return 0;
+}
+
+static int ad9389b_s_i2s_clock_freq(struct v4l2_subdev *sd, u32 freq)
+{
+	u32 i2s_sf;
+
+	switch (freq) {
+	case 32000: i2s_sf = 0x30; break;
+	case 44100: i2s_sf = 0x00; break;
+	case 48000: i2s_sf = 0x20; break;
+	case 88200: i2s_sf = 0x80; break;
+	case 96000: i2s_sf = 0xa0; break;
+	case 176400: i2s_sf = 0xc0; break;
+	case 192000: i2s_sf = 0xe0; break;
+	default:
+		return -EINVAL;
+	}
+
+	/* Set sampling frequency for I2S audio to 48 kHz */
+	ad9389b_wr_and_or(sd, 0x15, 0xf, i2s_sf);
+
+	return 0;
+}
+
+static int ad9389b_s_routing(struct v4l2_subdev *sd, u32 input, u32 output, u32 config)
+{
+	/* TODO based on input/output/config */
+	/* TODO See datasheet "Programmers guide" p. 39-40 */
+
+	/* Only 2 channels in use for application */
+	ad9389b_wr_and_or(sd, 0x50, 0x1f, 0x20);
+	/* Speaker mapping */
+	ad9389b_wr(sd, 0x51, 0x00);
+
+	/* TODO Where should this be placed? */
+	/* 16 bit audio word length */
+	ad9389b_wr_and_or(sd, 0x14, 0xf0, 0x02);
+
+	return 0;
+}
+
+static const struct v4l2_subdev_audio_ops ad9389b_audio_ops = {
+	.s_stream = ad9389b_s_audio_stream,
+	.s_clock_freq = ad9389b_s_clock_freq,
+	.s_i2s_clock_freq = ad9389b_s_i2s_clock_freq,
+	.s_routing = ad9389b_s_routing,
+};
+
+/* --------------------- SUBDEV OPS --------------------------------------- */
+
+static const struct v4l2_subdev_ops ad9389b_ops = {
+	.core  = &ad9389b_core_ops,
+	.video = &ad9389b_video_ops,
+	.audio = &ad9389b_audio_ops,
+	.pad = &ad9389b_pad_ops,
+};
+
+/* ----------------------------------------------------------------------- */
+static void ad9389b_dbg_dump_edid(int lvl, int debug, struct v4l2_subdev *sd,
+							int segment, u8 *buf)
+{
+	int i, j;
+
+	if (debug < lvl)
+		return;
+
+	v4l2_dbg(lvl, debug, sd, "edid segment %d\n", segment);
+	for (i = 0; i < 256; i += 16) {
+		u8 b[128];
+		u8 *bp = b;
+
+		if (i == 128)
+			v4l2_dbg(lvl, debug, sd, "\n");
+		for (j = i; j < i + 16; j++) {
+			sprintf(bp, "0x%02x, ", buf[j]);
+			bp += 6;
+		}
+		bp[0] = '\0';
+		v4l2_dbg(lvl, debug, sd, "%s\n", b);
+	}
+}
+
+static void ad9389b_edid_handler(struct work_struct *work)
+{
+	struct delayed_work *dwork = to_delayed_work(work);
+	struct ad9389b_state *state = container_of(dwork,
+			struct ad9389b_state, edid_handler);
+	struct v4l2_subdev *sd = &state->sd;
+	struct ad9389b_edid_detect ed;
+
+	v4l2_dbg(1, debug, sd, "%s:\n", __func__);
+
+	if (ad9389b_check_edid_status(sd)) {
+		/* Return if we received the EDID. */
+		return;
+	}
+
+	if (ad9389b_have_hotplug(sd)) {
+		/* We must retry reading the EDID several times, it is possible
+		 * that initially the EDID couldn't be read due to i2c errors
+		 * (DVI connectors are particularly prone to this problem). */
+		if (state->edid.read_retries) {
+			state->edid.read_retries--;
+			/* EDID read failed, trigger a retry */
+			ad9389b_wr(sd, 0xc9, 0xf);
+			queue_delayed_work(state->work_queue,
+					&state->edid_handler, EDID_DELAY);
+			return;
+		}
+	}
+
+	/* We failed to read the EDID, so send an event for this. */
+	ed.present = false;
+	ed.segment = ad9389b_rd(sd, 0xc4);
+	v4l2_subdev_notify(sd, AD9389B_EDID_DETECT, (void *)&ed);
+	v4l2_dbg(1, debug, sd, "%s: no edid found\n", __func__);
+}
+
+static void ad9389b_audio_setup(struct v4l2_subdev *sd)
+{
+	v4l2_dbg(1, debug, sd, "%s\n", __func__);
+
+	ad9389b_s_i2s_clock_freq(sd, 48000);
+	ad9389b_s_clock_freq(sd, 48000);
+	ad9389b_s_routing(sd, 0, 0, 0);
+}
+
+/* Initial setup of AD9389b */
+
+/* Configure hdmi transmitter. */
+static void ad9389b_setup(struct v4l2_subdev *sd)
+{
+	struct ad9389b_state *state = get_ad9389b_state(sd);
+
+	v4l2_dbg(1, debug, sd, "%s\n", __func__);
+
+	/* Input format: RGB 4:4:4 */
+	ad9389b_wr_and_or(sd, 0x15, 0xf1, 0x0);
+	/* Output format: RGB 4:4:4 */
+	ad9389b_wr_and_or(sd, 0x16, 0x3f, 0x0);
+	/* CSC fixed point: +/-2, 1st order interpolation 4:2:2 -> 4:4:4 up
+	   conversion, Aspect ratio: 16:9 */
+	ad9389b_wr_and_or(sd, 0x17, 0xe1, 0x0e);
+	/* Disable pixel repetition and CSC */
+	ad9389b_wr_and_or(sd, 0x3b, 0x9e, 0x0);
+	/* Output format: RGB 4:4:4, Active Format Information is valid. */
+	ad9389b_wr_and_or(sd, 0x45, 0xc7, 0x08);
+	/* Underscanned */
+	ad9389b_wr_and_or(sd, 0x46, 0x3f, 0x80);
+	/* Setup video format */
+	ad9389b_wr(sd, 0x3c, 0x0);
+	/* Active format aspect ratio: same as picure. */
+	ad9389b_wr(sd, 0x47, 0x80);
+	/* No encryption */
+	ad9389b_wr_and_or(sd, 0xaf, 0xef, 0x0);
+	/* Positive clk edge capture for input video clock */
+	ad9389b_wr_and_or(sd, 0xba, 0x1f, 0x60);
+
+	ad9389b_audio_setup(sd);
+
+	v4l2_ctrl_handler_setup(&state->hdl);
+
+	ad9389b_set_IT_content_AVI_InfoFrame(sd);
+}
+
+static void ad9389b_notify_monitor_detect(struct v4l2_subdev *sd)
+{
+	struct ad9389b_monitor_detect mdt;
+	struct ad9389b_state *state = get_ad9389b_state(sd);
+
+	mdt.present = state->have_monitor;
+	v4l2_subdev_notify(sd, AD9389B_MONITOR_DETECT, (void *)&mdt);
+}
+
+static void ad9389b_check_monitor_present_status(struct v4l2_subdev *sd)
+{
+	struct ad9389b_state *state = get_ad9389b_state(sd);
+	/* read hotplug and rx-sense state */
+	u8 status = ad9389b_rd(sd, 0x42);
+
+	v4l2_dbg(1, debug, sd, "%s: status: 0x%x%s%s\n",
+			 __func__,
+			 status,
+			 status & MASK_AD9389B_HPD_DETECT ? ", hotplug" : "",
+			 status & MASK_AD9389B_MSEN_DETECT ? ", rx-sense" : "");
+
+	if ((status & MASK_AD9389B_HPD_DETECT) &&
+	    ((status & MASK_AD9389B_MSEN_DETECT) || state->edid.segments)) {
+		v4l2_dbg(1, debug, sd,
+				"%s: hotplug and (rx-sense or edid)\n", __func__);
+		if (!state->have_monitor) {
+			v4l2_dbg(1, debug, sd, "%s: monitor detected\n", __func__);
+			state->have_monitor = true;
+			ad9389b_set_isr(sd, true);
+			if (!ad9389b_s_power(sd, true)) {
+				v4l2_dbg(1, debug, sd,
+					"%s: monitor detected, powerup failed\n", __func__);
+				return;
+			}
+			ad9389b_setup(sd);
+			ad9389b_notify_monitor_detect(sd);
+			state->edid.read_retries = EDID_MAX_RETRIES;
+			queue_delayed_work(state->work_queue,
+					&state->edid_handler, EDID_DELAY);
+		}
+	} else if (status & MASK_AD9389B_HPD_DETECT) {
+		v4l2_dbg(1, debug, sd, "%s: hotplug detected\n", __func__);
+		state->edid.read_retries = EDID_MAX_RETRIES;
+		queue_delayed_work(state->work_queue,
+				&state->edid_handler, EDID_DELAY);
+	} else if (!(status & MASK_AD9389B_HPD_DETECT)) {
+		v4l2_dbg(1, debug, sd, "%s: hotplug not detected\n", __func__);
+		if (state->have_monitor) {
+			v4l2_dbg(1, debug, sd, "%s: monitor not detected\n", __func__);
+			state->have_monitor = false;
+			ad9389b_notify_monitor_detect(sd);
+		}
+		ad9389b_s_power(sd, false);
+		memset(&state->edid, 0, sizeof(struct ad9389b_state_edid));
+	}
+
+	/* update read only ctrls */
+	v4l2_ctrl_s_ctrl(state->hotplug_ctrl, ad9389b_have_hotplug(sd) ? 0x1 : 0x0);
+	v4l2_ctrl_s_ctrl(state->rx_sense_ctrl, ad9389b_have_rx_sense(sd) ? 0x1 : 0x0);
+	v4l2_ctrl_s_ctrl(state->have_edid0_ctrl, state->edid.segments ? 0x1 : 0x0);
+}
+
+static bool edid_block_verify_crc(u8 *edid_block)
+{
+	int i;
+	u8 sum = 0;
+
+	for (i = 0; i < 127; i++)
+		sum += *(edid_block + i);
+	return ((255 - sum + 1) == edid_block[127]);
+}
+
+static bool edid_segment_verify_crc(struct v4l2_subdev *sd, u32 segment)
+{
+	struct ad9389b_state *state = get_ad9389b_state(sd);
+	u32 blocks = state->edid.blocks;
+	u8 *data = state->edid.data;
+
+	if (edid_block_verify_crc(&data[segment * 256])) {
+		if ((segment + 1) * 2 <= blocks)
+			return edid_block_verify_crc(&data[segment * 256 + 128]);
+		return true;
+	}
+	return false;
+}
+
+static bool ad9389b_check_edid_status(struct v4l2_subdev *sd)
+{
+	struct ad9389b_state *state = get_ad9389b_state(sd);
+	struct ad9389b_edid_detect ed;
+	int segment;
+	u8 edidRdy = ad9389b_rd(sd, 0xc5);
+
+	v4l2_dbg(1, debug, sd, "%s: edid ready (retries: %d)\n",
+			 __func__, EDID_MAX_RETRIES - state->edid.read_retries);
+
+	if (!(edidRdy & MASK_AD9389B_EDID_RDY))
+		return false;
+
+	segment = ad9389b_rd(sd, 0xc4);
+	if (segment >= EDID_MAX_SEGM) {
+		v4l2_err(sd, "edid segment number too big\n");
+		return false;
+	}
+	v4l2_dbg(1, debug, sd, "%s: got segment %d\n", __func__, segment);
+	ad9389b_edid_rd(sd, 256, &state->edid.data[segment * 256]);
+	ad9389b_dbg_dump_edid(2, debug, sd, segment,
+			&state->edid.data[segment * 256]);
+	if (segment == 0) {
+		state->edid.blocks = state->edid.data[0x7e] + 1;
+		v4l2_dbg(1, debug, sd, "%s: %d blocks in total\n",
+				__func__, state->edid.blocks);
+	}
+	if (!edid_segment_verify_crc(sd, segment)) {
+		/* edid crc error, force reread of edid segment */
+		ad9389b_s_power(sd, false);
+		ad9389b_s_power(sd, true);
+		return false;
+	}
+	/* one more segment read ok */
+	state->edid.segments = segment + 1;
+	if (((state->edid.data[0x7e] >> 1) + 1) > state->edid.segments) {
+		/* Request next EDID segment */
+		v4l2_dbg(1, debug, sd, "%s: request segment %d\n",
+				__func__, state->edid.segments);
+		ad9389b_wr(sd, 0xc9, 0xf);
+		ad9389b_wr(sd, 0xc4, state->edid.segments);
+		state->edid.read_retries = EDID_MAX_RETRIES;
+		queue_delayed_work(state->work_queue,
+				&state->edid_handler, EDID_DELAY);
+		return false;
+	}
+
+	/* report when we have all segments but report only for segment 0 */
+	ed.present = true;
+	ed.segment = 0;
+	v4l2_subdev_notify(sd, AD9389B_EDID_DETECT, (void *)&ed);
+	state->edid_detect_counter++;
+	v4l2_ctrl_s_ctrl(state->have_edid0_ctrl, state->edid.segments ? 0x1 : 0x0);
+	return ed.present;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static void ad9389b_init_setup(struct v4l2_subdev *sd)
+{
+	struct ad9389b_state *state = get_ad9389b_state(sd);
+	struct ad9389b_state_edid *edid = &state->edid;
+
+	v4l2_dbg(1, debug, sd, "%s\n", __func__);
+
+	/* clear all interrupts */
+	ad9389b_wr(sd, 0x96, 0xff);
+
+	memset(edid, 0, sizeof(struct ad9389b_state_edid));
+	state->have_monitor = false;
+	ad9389b_set_isr(sd, false);
+}
+
+static int ad9389b_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+	const struct v4l2_dv_timings dv1080p60 = V4L2_DV_BT_CEA_1920X1080P60;
+	struct ad9389b_state *state;
+	struct ad9389b_platform_data *pdata = client->dev.platform_data;
+	struct v4l2_ctrl_handler *hdl;
+	struct v4l2_subdev *sd;
+	int err = -EIO;
+
+	/* Check if the adapter supports the needed features */
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		return -EIO;
+
+	v4l_dbg(1, debug, client, "detecting ad9389b client on address 0x%x\n",
+			client->addr << 1);
+
+	state = kzalloc(sizeof(struct ad9389b_state), GFP_KERNEL);
+	if (!state)
+		return -ENOMEM;
+
+	/* Platform data */
+	if (pdata == NULL) {
+		v4l_err(client, "No platform data!\n");
+		err = -ENODEV;
+		goto err_free;
+	}
+	memcpy(&state->pdata, pdata, sizeof(state->pdata));
+
+	sd = &state->sd;
+	v4l2_i2c_subdev_init(sd, client, &ad9389b_ops);
+	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+	hdl = &state->hdl;
+	v4l2_ctrl_handler_init(hdl, 5);
+
+	/* private controls */
+
+	state->hdmi_mode_ctrl = v4l2_ctrl_new_std_menu(hdl, &ad9389b_ctrl_ops,
+			V4L2_CID_DV_TX_MODE, V4L2_DV_TX_MODE_HDMI,
+			0, V4L2_DV_TX_MODE_DVI_D);
+	state->hdmi_mode_ctrl->is_private = true;
+	state->hotplug_ctrl = v4l2_ctrl_new_std(hdl, NULL,
+			V4L2_CID_DV_TX_HOTPLUG, 0, 1, 0, 0);
+	state->hotplug_ctrl->is_private = true;
+	state->rx_sense_ctrl = v4l2_ctrl_new_std(hdl, NULL,
+			V4L2_CID_DV_TX_RXSENSE, 0, 1, 0, 0);
+	state->rx_sense_ctrl->is_private = true;
+	state->have_edid0_ctrl = v4l2_ctrl_new_std(hdl, NULL,
+			V4L2_CID_DV_TX_EDID_PRESENT, 0, 1, 0, 0);
+	state->have_edid0_ctrl->is_private = true;
+	state->rgb_quantization_range_ctrl =
+		v4l2_ctrl_new_std_menu(hdl, &ad9389b_ctrl_ops,
+			V4L2_CID_DV_TX_RGB_RANGE, V4L2_DV_RGB_RANGE_FULL,
+			0, V4L2_DV_RGB_RANGE_AUTO);
+	state->rgb_quantization_range_ctrl->is_private = true;
+	sd->ctrl_handler = hdl;
+	if (hdl->error) {
+		err = hdl->error;
+
+		goto err_hdl;
+	}
+
+	state->pad.flags = MEDIA_PAD_FL_SINK;
+	err = media_entity_init(&sd->entity, 1, &state->pad, 0);
+	if (err)
+		goto err_hdl;
+
+	state->chip_revision = ad9389b_rd(sd, 0x0);
+	if (state->chip_revision != 2) {
+		v4l2_err(sd, "chip_revision %d != 2\n", state->chip_revision);
+		err = -EIO;
+		goto err_entity;
+	}
+	v4l2_dbg(1, debug, sd, "reg 0x41 0x%x, chip version (reg 0x00) 0x%x\n",
+			ad9389b_rd(sd, 0x41), state->chip_revision);
+
+	state->edid_i2c_client = i2c_new_dummy(client->adapter, (0x7e>>1));
+	if (state->edid_i2c_client == NULL) {
+		v4l2_err(sd, "failed to register edid i2c client\n");
+		goto err_entity;
+	}
+
+	state->work_queue = create_singlethread_workqueue(sd->name);
+	if (state->work_queue == NULL) {
+		v4l2_err(sd, "could not create workqueue\n");
+		goto err_unreg;
+	}
+
+	INIT_DELAYED_WORK(&state->edid_handler, ad9389b_edid_handler);
+	state->dv_timings = dv1080p60;
+
+	ad9389b_init_setup(sd);
+	ad9389b_set_isr(sd, true);
+
+	v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name,
+			  client->addr << 1, client->adapter->name);
+	return 0;
+
+err_unreg:
+	i2c_unregister_device(state->edid_i2c_client);
+err_entity:
+	media_entity_cleanup(&sd->entity);
+err_hdl:
+	v4l2_ctrl_handler_free(&state->hdl);
+err_free:
+	kfree(state);
+	return err;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static int ad9389b_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct ad9389b_state *state = get_ad9389b_state(sd);
+
+	state->chip_revision = -1;
+
+	v4l2_dbg(1, debug, sd, "%s removed @ 0x%x (%s)\n", client->name,
+		 client->addr << 1, client->adapter->name);
+
+	ad9389b_s_stream(sd, false);
+	ad9389b_s_audio_stream(sd, false);
+	ad9389b_init_setup(sd);
+	cancel_delayed_work(&state->edid_handler);
+	i2c_unregister_device(state->edid_i2c_client);
+	destroy_workqueue(state->work_queue);
+	v4l2_device_unregister_subdev(sd);
+	media_entity_cleanup(&sd->entity);
+	v4l2_ctrl_handler_free(sd->ctrl_handler);
+	kfree(get_ad9389b_state(sd));
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static struct i2c_device_id ad9389b_id[] = {
+	{ "ad9389b", V4L2_IDENT_AD9389B },
+	{ "ad9889b", V4L2_IDENT_AD9389B },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, ad9389b_id);
+
+static struct i2c_driver ad9389b_driver = {
+	.driver = {
+		.owner = THIS_MODULE,
+		.name = "ad9389b",
+	},
+	.probe = ad9389b_probe,
+	.remove = ad9389b_remove,
+	.id_table = ad9389b_id,
+};
+
+module_i2c_driver(ad9389b_driver);
diff --git a/drivers/media/i2c/adp1653.c b/drivers/media/i2c/adp1653.c
new file mode 100644
index 0000000..18a38b3
--- /dev/null
+++ b/drivers/media/i2c/adp1653.c
@@ -0,0 +1,487 @@
+/*
+ * drivers/media/i2c/adp1653.c
+ *
+ * Copyright (C) 2008--2011 Nokia Corporation
+ *
+ * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ *
+ * Contributors:
+ *	Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ *	Tuukka Toivonen <tuukkat76@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.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ * TODO:
+ * - fault interrupt handling
+ * - hardware strobe
+ * - power doesn't need to be ON if all lights are off
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <media/adp1653.h>
+#include <media/v4l2-device.h>
+
+#define TIMEOUT_MAX		820000
+#define TIMEOUT_STEP		54600
+#define TIMEOUT_MIN		(TIMEOUT_MAX - ADP1653_REG_CONFIG_TMR_SET_MAX \
+				 * TIMEOUT_STEP)
+#define TIMEOUT_US_TO_CODE(t)	((TIMEOUT_MAX + (TIMEOUT_STEP / 2) - (t)) \
+				 / TIMEOUT_STEP)
+#define TIMEOUT_CODE_TO_US(c)	(TIMEOUT_MAX - (c) * TIMEOUT_STEP)
+
+/* Write values into ADP1653 registers. */
+static int adp1653_update_hw(struct adp1653_flash *flash)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&flash->subdev);
+	u8 out_sel;
+	u8 config = 0;
+	int rval;
+
+	out_sel = ADP1653_INDICATOR_INTENSITY_uA_TO_REG(
+		flash->indicator_intensity->val)
+		<< ADP1653_REG_OUT_SEL_ILED_SHIFT;
+
+	switch (flash->led_mode->val) {
+	case V4L2_FLASH_LED_MODE_NONE:
+		break;
+	case V4L2_FLASH_LED_MODE_FLASH:
+		/* Flash mode, light on with strobe, duration from timer */
+		config = ADP1653_REG_CONFIG_TMR_CFG;
+		config |= TIMEOUT_US_TO_CODE(flash->flash_timeout->val)
+			  << ADP1653_REG_CONFIG_TMR_SET_SHIFT;
+		break;
+	case V4L2_FLASH_LED_MODE_TORCH:
+		/* Torch mode, light immediately on, duration indefinite */
+		out_sel |= ADP1653_FLASH_INTENSITY_mA_TO_REG(
+			flash->torch_intensity->val)
+			<< ADP1653_REG_OUT_SEL_HPLED_SHIFT;
+		break;
+	}
+
+	rval = i2c_smbus_write_byte_data(client, ADP1653_REG_OUT_SEL, out_sel);
+	if (rval < 0)
+		return rval;
+
+	rval = i2c_smbus_write_byte_data(client, ADP1653_REG_CONFIG, config);
+	if (rval < 0)
+		return rval;
+
+	return 0;
+}
+
+static int adp1653_get_fault(struct adp1653_flash *flash)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&flash->subdev);
+	int fault;
+	int rval;
+
+	fault = i2c_smbus_read_byte_data(client, ADP1653_REG_FAULT);
+	if (IS_ERR_VALUE(fault))
+		return fault;
+
+	flash->fault |= fault;
+
+	if (!flash->fault)
+		return 0;
+
+	/* Clear faults. */
+	rval = i2c_smbus_write_byte_data(client, ADP1653_REG_OUT_SEL, 0);
+	if (IS_ERR_VALUE(rval))
+		return rval;
+
+	flash->led_mode->val = V4L2_FLASH_LED_MODE_NONE;
+
+	rval = adp1653_update_hw(flash);
+	if (IS_ERR_VALUE(rval))
+		return rval;
+
+	return flash->fault;
+}
+
+static int adp1653_strobe(struct adp1653_flash *flash, int enable)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&flash->subdev);
+	u8 out_sel = ADP1653_INDICATOR_INTENSITY_uA_TO_REG(
+		flash->indicator_intensity->val)
+		<< ADP1653_REG_OUT_SEL_ILED_SHIFT;
+	int rval;
+
+	if (flash->led_mode->val != V4L2_FLASH_LED_MODE_FLASH)
+		return -EBUSY;
+
+	if (!enable)
+		return i2c_smbus_write_byte_data(client, ADP1653_REG_OUT_SEL,
+						 out_sel);
+
+	out_sel |= ADP1653_FLASH_INTENSITY_mA_TO_REG(
+		flash->flash_intensity->val)
+		<< ADP1653_REG_OUT_SEL_HPLED_SHIFT;
+	rval = i2c_smbus_write_byte_data(client, ADP1653_REG_OUT_SEL, out_sel);
+	if (rval)
+		return rval;
+
+	/* Software strobe using i2c */
+	rval = i2c_smbus_write_byte_data(client, ADP1653_REG_SW_STROBE,
+		ADP1653_REG_SW_STROBE_SW_STROBE);
+	if (rval)
+		return rval;
+	return i2c_smbus_write_byte_data(client, ADP1653_REG_SW_STROBE, 0);
+}
+
+/* --------------------------------------------------------------------------
+ * V4L2 controls
+ */
+
+static int adp1653_get_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct adp1653_flash *flash =
+		container_of(ctrl->handler, struct adp1653_flash, ctrls);
+	int rval;
+
+	rval = adp1653_get_fault(flash);
+	if (IS_ERR_VALUE(rval))
+		return rval;
+
+	ctrl->cur.val = 0;
+
+	if (flash->fault & ADP1653_REG_FAULT_FLT_SCP)
+		ctrl->cur.val |= V4L2_FLASH_FAULT_SHORT_CIRCUIT;
+	if (flash->fault & ADP1653_REG_FAULT_FLT_OT)
+		ctrl->cur.val |= V4L2_FLASH_FAULT_OVER_TEMPERATURE;
+	if (flash->fault & ADP1653_REG_FAULT_FLT_TMR)
+		ctrl->cur.val |= V4L2_FLASH_FAULT_TIMEOUT;
+	if (flash->fault & ADP1653_REG_FAULT_FLT_OV)
+		ctrl->cur.val |= V4L2_FLASH_FAULT_OVER_VOLTAGE;
+
+	flash->fault = 0;
+
+	return 0;
+}
+
+static int adp1653_set_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct adp1653_flash *flash =
+		container_of(ctrl->handler, struct adp1653_flash, ctrls);
+	int rval;
+
+	rval = adp1653_get_fault(flash);
+	if (IS_ERR_VALUE(rval))
+		return rval;
+	if ((rval & (ADP1653_REG_FAULT_FLT_SCP |
+		     ADP1653_REG_FAULT_FLT_OT |
+		     ADP1653_REG_FAULT_FLT_OV)) &&
+	    (ctrl->id == V4L2_CID_FLASH_STROBE ||
+	     ctrl->id == V4L2_CID_FLASH_TORCH_INTENSITY ||
+	     ctrl->id == V4L2_CID_FLASH_LED_MODE))
+		return -EBUSY;
+
+	switch (ctrl->id) {
+	case V4L2_CID_FLASH_STROBE:
+		return adp1653_strobe(flash, 1);
+	case V4L2_CID_FLASH_STROBE_STOP:
+		return adp1653_strobe(flash, 0);
+	}
+
+	return adp1653_update_hw(flash);
+}
+
+static const struct v4l2_ctrl_ops adp1653_ctrl_ops = {
+	.g_volatile_ctrl = adp1653_get_ctrl,
+	.s_ctrl = adp1653_set_ctrl,
+};
+
+static int adp1653_init_controls(struct adp1653_flash *flash)
+{
+	struct v4l2_ctrl *fault;
+
+	v4l2_ctrl_handler_init(&flash->ctrls, 9);
+
+	flash->led_mode =
+		v4l2_ctrl_new_std_menu(&flash->ctrls, &adp1653_ctrl_ops,
+				       V4L2_CID_FLASH_LED_MODE,
+				       V4L2_FLASH_LED_MODE_TORCH, ~0x7, 0);
+	v4l2_ctrl_new_std_menu(&flash->ctrls, &adp1653_ctrl_ops,
+			       V4L2_CID_FLASH_STROBE_SOURCE,
+			       V4L2_FLASH_STROBE_SOURCE_SOFTWARE, ~0x1, 0);
+	v4l2_ctrl_new_std(&flash->ctrls, &adp1653_ctrl_ops,
+			  V4L2_CID_FLASH_STROBE, 0, 0, 0, 0);
+	v4l2_ctrl_new_std(&flash->ctrls, &adp1653_ctrl_ops,
+			  V4L2_CID_FLASH_STROBE_STOP, 0, 0, 0, 0);
+	flash->flash_timeout =
+		v4l2_ctrl_new_std(&flash->ctrls, &adp1653_ctrl_ops,
+				  V4L2_CID_FLASH_TIMEOUT, TIMEOUT_MIN,
+				  flash->platform_data->max_flash_timeout,
+				  TIMEOUT_STEP,
+				  flash->platform_data->max_flash_timeout);
+	flash->flash_intensity =
+		v4l2_ctrl_new_std(&flash->ctrls, &adp1653_ctrl_ops,
+				  V4L2_CID_FLASH_INTENSITY,
+				  ADP1653_FLASH_INTENSITY_MIN,
+				  flash->platform_data->max_flash_intensity,
+				  1, flash->platform_data->max_flash_intensity);
+	flash->torch_intensity =
+		v4l2_ctrl_new_std(&flash->ctrls, &adp1653_ctrl_ops,
+				  V4L2_CID_FLASH_TORCH_INTENSITY,
+				  ADP1653_TORCH_INTENSITY_MIN,
+				  flash->platform_data->max_torch_intensity,
+				  ADP1653_FLASH_INTENSITY_STEP,
+				  flash->platform_data->max_torch_intensity);
+	flash->indicator_intensity =
+		v4l2_ctrl_new_std(&flash->ctrls, &adp1653_ctrl_ops,
+				  V4L2_CID_FLASH_INDICATOR_INTENSITY,
+				  ADP1653_INDICATOR_INTENSITY_MIN,
+				  flash->platform_data->max_indicator_intensity,
+				  ADP1653_INDICATOR_INTENSITY_STEP,
+				  ADP1653_INDICATOR_INTENSITY_MIN);
+	fault = v4l2_ctrl_new_std(&flash->ctrls, &adp1653_ctrl_ops,
+				  V4L2_CID_FLASH_FAULT, 0,
+				  V4L2_FLASH_FAULT_OVER_VOLTAGE
+				  | V4L2_FLASH_FAULT_OVER_TEMPERATURE
+				  | V4L2_FLASH_FAULT_SHORT_CIRCUIT, 0, 0);
+
+	if (flash->ctrls.error)
+		return flash->ctrls.error;
+
+	fault->flags |= V4L2_CTRL_FLAG_VOLATILE;
+
+	flash->subdev.ctrl_handler = &flash->ctrls;
+	return 0;
+}
+
+/* --------------------------------------------------------------------------
+ * V4L2 subdev operations
+ */
+
+static int
+adp1653_init_device(struct adp1653_flash *flash)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&flash->subdev);
+	int rval;
+
+	/* Clear FAULT register by writing zero to OUT_SEL */
+	rval = i2c_smbus_write_byte_data(client, ADP1653_REG_OUT_SEL, 0);
+	if (rval < 0) {
+		dev_err(&client->dev, "failed writing fault register\n");
+		return -EIO;
+	}
+
+	mutex_lock(flash->ctrls.lock);
+	/* Reset faults before reading new ones. */
+	flash->fault = 0;
+	rval = adp1653_get_fault(flash);
+	mutex_unlock(flash->ctrls.lock);
+	if (rval > 0) {
+		dev_err(&client->dev, "faults detected: 0x%1.1x\n", rval);
+		return -EIO;
+	}
+
+	mutex_lock(flash->ctrls.lock);
+	rval = adp1653_update_hw(flash);
+	mutex_unlock(flash->ctrls.lock);
+	if (rval) {
+		dev_err(&client->dev,
+			"adp1653_update_hw failed at %s\n", __func__);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int
+__adp1653_set_power(struct adp1653_flash *flash, int on)
+{
+	int ret;
+
+	ret = flash->platform_data->power(&flash->subdev, on);
+	if (ret < 0)
+		return ret;
+
+	if (!on)
+		return 0;
+
+	ret = adp1653_init_device(flash);
+	if (ret < 0)
+		flash->platform_data->power(&flash->subdev, 0);
+
+	return ret;
+}
+
+static int
+adp1653_set_power(struct v4l2_subdev *subdev, int on)
+{
+	struct adp1653_flash *flash = to_adp1653_flash(subdev);
+	int ret = 0;
+
+	mutex_lock(&flash->power_lock);
+
+	/* If the power count is modified from 0 to != 0 or from != 0 to 0,
+	 * update the power state.
+	 */
+	if (flash->power_count == !on) {
+		ret = __adp1653_set_power(flash, !!on);
+		if (ret < 0)
+			goto done;
+	}
+
+	/* Update the power count. */
+	flash->power_count += on ? 1 : -1;
+	WARN_ON(flash->power_count < 0);
+
+done:
+	mutex_unlock(&flash->power_lock);
+	return ret;
+}
+
+static int adp1653_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+	return adp1653_set_power(sd, 1);
+}
+
+static int adp1653_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+	return adp1653_set_power(sd, 0);
+}
+
+static const struct v4l2_subdev_core_ops adp1653_core_ops = {
+	.s_power = adp1653_set_power,
+};
+
+static const struct v4l2_subdev_ops adp1653_ops = {
+	.core = &adp1653_core_ops,
+};
+
+static const struct v4l2_subdev_internal_ops adp1653_internal_ops = {
+	.open = adp1653_open,
+	.close = adp1653_close,
+};
+
+/* --------------------------------------------------------------------------
+ * I2C driver
+ */
+#ifdef CONFIG_PM
+
+static int adp1653_suspend(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct v4l2_subdev *subdev = i2c_get_clientdata(client);
+	struct adp1653_flash *flash = to_adp1653_flash(subdev);
+
+	if (!flash->power_count)
+		return 0;
+
+	return __adp1653_set_power(flash, 0);
+}
+
+static int adp1653_resume(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct v4l2_subdev *subdev = i2c_get_clientdata(client);
+	struct adp1653_flash *flash = to_adp1653_flash(subdev);
+
+	if (!flash->power_count)
+		return 0;
+
+	return __adp1653_set_power(flash, 1);
+}
+
+#else
+
+#define adp1653_suspend	NULL
+#define adp1653_resume	NULL
+
+#endif /* CONFIG_PM */
+
+static int adp1653_probe(struct i2c_client *client,
+			 const struct i2c_device_id *devid)
+{
+	struct adp1653_flash *flash;
+	int ret;
+
+	/* we couldn't work without platform data */
+	if (client->dev.platform_data == NULL)
+		return -ENODEV;
+
+	flash = kzalloc(sizeof(*flash), GFP_KERNEL);
+	if (flash == NULL)
+		return -ENOMEM;
+
+	flash->platform_data = client->dev.platform_data;
+
+	mutex_init(&flash->power_lock);
+
+	v4l2_i2c_subdev_init(&flash->subdev, client, &adp1653_ops);
+	flash->subdev.internal_ops = &adp1653_internal_ops;
+	flash->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+	ret = adp1653_init_controls(flash);
+	if (ret)
+		goto free_and_quit;
+
+	ret = media_entity_init(&flash->subdev.entity, 0, NULL, 0);
+	if (ret < 0)
+		goto free_and_quit;
+
+	flash->subdev.entity.type = MEDIA_ENT_T_V4L2_SUBDEV_FLASH;
+
+	return 0;
+
+free_and_quit:
+	v4l2_ctrl_handler_free(&flash->ctrls);
+	kfree(flash);
+	return ret;
+}
+
+static int __exit adp1653_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *subdev = i2c_get_clientdata(client);
+	struct adp1653_flash *flash = to_adp1653_flash(subdev);
+
+	v4l2_device_unregister_subdev(&flash->subdev);
+	v4l2_ctrl_handler_free(&flash->ctrls);
+	media_entity_cleanup(&flash->subdev.entity);
+	kfree(flash);
+	return 0;
+}
+
+static const struct i2c_device_id adp1653_id_table[] = {
+	{ ADP1653_NAME, 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, adp1653_id_table);
+
+static struct dev_pm_ops adp1653_pm_ops = {
+	.suspend	= adp1653_suspend,
+	.resume		= adp1653_resume,
+};
+
+static struct i2c_driver adp1653_i2c_driver = {
+	.driver		= {
+		.name	= ADP1653_NAME,
+		.pm	= &adp1653_pm_ops,
+	},
+	.probe		= adp1653_probe,
+	.remove		= __exit_p(adp1653_remove),
+	.id_table	= adp1653_id_table,
+};
+
+module_i2c_driver(adp1653_i2c_driver);
+
+MODULE_AUTHOR("Sakari Ailus <sakari.ailus@nokia.com>");
+MODULE_DESCRIPTION("Analog Devices ADP1653 LED flash driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/i2c/adv7170.c b/drivers/media/i2c/adv7170.c
new file mode 100644
index 0000000..6bc01fb
--- /dev/null
+++ b/drivers/media/i2c/adv7170.c
@@ -0,0 +1,410 @@
+/*
+ * adv7170 - adv7170, adv7171 video encoder driver version 0.0.1
+ *
+ * Copyright (C) 2002 Maxim Yevtyushkin <max@linuxmedialabs.com>
+ *
+ * Based on adv7176 driver by:
+ *
+ * Copyright (C) 1998 Dave Perks <dperks@ibm.net>
+ * Copyright (C) 1999 Wolfgang Scherr <scherr@net4you.net>
+ * Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
+ *    - some corrections for Pinnacle Systems Inc. DC10plus card.
+ *
+ * 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/slab.h>
+#include <linux/ioctl.h>
+#include <asm/uaccess.h>
+#include <linux/i2c.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-chip-ident.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)");
+
+/* ----------------------------------------------------------------------- */
+
+struct adv7170 {
+	struct v4l2_subdev sd;
+	unsigned char reg[128];
+
+	v4l2_std_id norm;
+	int input;
+};
+
+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 enum v4l2_mbus_pixelcode adv7170_codes[] = {
+	V4L2_MBUS_FMT_UYVY8_2X8,
+	V4L2_MBUS_FMT_UYVY8_1X16,
+};
+
+/* ----------------------------------------------------------------------- */
+
+static inline int adv7170_write(struct v4l2_subdev *sd, u8 reg, u8 value)
+{
+	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 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 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;
+
+	/* the adv7170 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++] =
+				    encoder->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 = adv7170_write(sd, reg, *data++);
+			if (ret < 0)
+				break;
+			len -= 2;
+		}
+	}
+	return ret;
+}
+
+/* ----------------------------------------------------------------------- */
+
+#define TR0MODE     0x4c
+#define TR0RST	    0x80
+
+#define TR1CAPT	    0x00
+#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 */
+};
+
+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 */
+};
+
+
+static int adv7170_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std)
+{
+	struct adv7170 *encoder = to_adv7170(sd);
+
+	v4l2_dbg(1, debug, sd, "set norm %llx\n", (unsigned long long)std);
+
+	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,
+			     u32 input, u32 output, u32 config)
+{
+	struct adv7170 *encoder = to_adv7170(sd);
+
+	/* RJ: input = 0: input is from decoder
+	   input = 1: input is from ZR36060
+	   input = 2: color bar */
+
+	v4l2_dbg(1, debug, sd, "set input from %s\n",
+			input == 0 ? "decoder" : "ZR36060");
+
+	switch (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", input);
+		return -EINVAL;
+	}
+	v4l2_dbg(1, debug, sd, "switched to %s\n", inputs[input]);
+	encoder->input = input;
+	return 0;
+}
+
+static int adv7170_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
+				enum v4l2_mbus_pixelcode *code)
+{
+	if (index >= ARRAY_SIZE(adv7170_codes))
+		return -EINVAL;
+
+	*code = adv7170_codes[index];
+	return 0;
+}
+
+static int adv7170_g_fmt(struct v4l2_subdev *sd,
+				struct v4l2_mbus_framefmt *mf)
+{
+	u8 val = adv7170_read(sd, 0x7);
+
+	if ((val & 0x40) == (1 << 6))
+		mf->code = V4L2_MBUS_FMT_UYVY8_1X16;
+	else
+		mf->code = V4L2_MBUS_FMT_UYVY8_2X8;
+
+	mf->colorspace  = V4L2_COLORSPACE_SMPTE170M;
+	mf->width       = 0;
+	mf->height      = 0;
+	mf->field       = V4L2_FIELD_ANY;
+
+	return 0;
+}
+
+static int adv7170_s_fmt(struct v4l2_subdev *sd,
+				struct v4l2_mbus_framefmt *mf)
+{
+	u8 val = adv7170_read(sd, 0x7);
+	int ret;
+
+	switch (mf->code) {
+	case V4L2_MBUS_FMT_UYVY8_2X8:
+		val &= ~0x40;
+		break;
+
+	case V4L2_MBUS_FMT_UYVY8_1X16:
+		val |= 0x40;
+		break;
+
+	default:
+		v4l2_dbg(1, debug, sd,
+			"illegal v4l2_mbus_framefmt code: %d\n", mf->code);
+		return -EINVAL;
+	}
+
+	ret = adv7170_write(sd, 0x7, val);
+
+	return ret;
+}
+
+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 const struct v4l2_subdev_core_ops adv7170_core_ops = {
+	.g_chip_ident = adv7170_g_chip_ident,
+};
+
+static const struct v4l2_subdev_video_ops adv7170_video_ops = {
+	.s_std_output = adv7170_s_std_output,
+	.s_routing = adv7170_s_routing,
+	.s_mbus_fmt = adv7170_s_fmt,
+	.g_mbus_fmt = adv7170_g_fmt,
+	.enum_mbus_fmt  = adv7170_enum_fmt,
+};
+
+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 */
+	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);
+
+	encoder = kzalloc(sizeof(struct adv7170), GFP_KERNEL);
+	if (encoder == NULL)
+		return -ENOMEM;
+	sd = &encoder->sd;
+	v4l2_i2c_subdev_init(sd, client, &adv7170_ops);
+	encoder->norm = V4L2_STD_NTSC;
+	encoder->input = 0;
+
+	i = adv7170_write_block(sd, init_NTSC, sizeof(init_NTSC));
+	if (i >= 0) {
+		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)
+		v4l2_dbg(1, debug, sd, "init error 0x%x\n", i);
+	return 0;
+}
+
+static int adv7170_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+
+	v4l2_device_unregister_subdev(sd);
+	kfree(to_adv7170(sd));
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static const struct i2c_device_id adv7170_id[] = {
+	{ "adv7170", 0 },
+	{ "adv7171", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, adv7170_id);
+
+static struct i2c_driver adv7170_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "adv7170",
+	},
+	.probe		= adv7170_probe,
+	.remove		= adv7170_remove,
+	.id_table	= adv7170_id,
+};
+
+module_i2c_driver(adv7170_driver);
diff --git a/drivers/media/i2c/adv7175.c b/drivers/media/i2c/adv7175.c
new file mode 100644
index 0000000..c7640fa
--- /dev/null
+++ b/drivers/media/i2c/adv7175.c
@@ -0,0 +1,460 @@
+/*
+ *  adv7175 - adv7175a video encoder driver version 0.0.3
+ *
+ * Copyright (C) 1998 Dave Perks <dperks@ibm.net>
+ * Copyright (C) 1999 Wolfgang Scherr <scherr@net4you.net>
+ * Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
+ *    - some corrections for Pinnacle Systems Inc. DC10plus card.
+ *
+ * Changes by Ronald Bultje <rbultje@ronald.bitfreak.net>
+ *    - moved over to linux>=2.4.x i2c protocol (9/9/2002)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/slab.h>
+#include <linux/ioctl.h>
+#include <asm/uaccess.h>
+#include <linux/i2c.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-chip-ident.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)");
+
+/* ----------------------------------------------------------------------- */
+
+struct adv7175 {
+	struct v4l2_subdev sd;
+	v4l2_std_id norm;
+	int input;
+};
+
+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 enum v4l2_mbus_pixelcode adv7175_codes[] = {
+	V4L2_MBUS_FMT_UYVY8_2X8,
+	V4L2_MBUS_FMT_UYVY8_1X16,
+};
+
+/* ----------------------------------------------------------------------- */
+
+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 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 v4l2_subdev *sd,
+		     const u8 *data, unsigned int len)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	int ret = -1;
+	u8 reg;
+
+	/* the adv7175 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 = adv7175_write(sd, reg, *data++);
+			if (ret < 0)
+				break;
+			len -= 2;
+		}
+	}
+
+	return ret;
+}
+
+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(sd, 0x02, 0x00);
+	else
+		adv7175_write(sd, 0x02, 0x55);
+
+	adv7175_write(sd, 0x03, 0x55);
+	adv7175_write(sd, 0x04, 0x55);
+	adv7175_write(sd, 0x05, 0x25);
+}
+
+/* ----------------------------------------------------------------------- */
+/* Output filter:  S-Video  Composite */
+
+#define MR050       0x11	/* 0x09 */
+#define MR060       0x14	/* 0x0c */
+
+/* ----------------------------------------------------------------------- */
+
+#define TR0MODE     0x46
+#define TR0RST	    0x80
+
+#define TR1CAPT	    0x80
+#define TR1PLAY	    0x00
+
+static const unsigned char init_common[] = {
+
+	0x00, MR050,		/* MR0, PAL enabled */
+	0x01, 0x00,		/* MR1 */
+	0x02, 0x0c,		/* subc. freq. */
+	0x03, 0x8c,		/* subc. freq. */
+	0x04, 0x79,		/* subc. freq. */
+	0x05, 0x26,		/* subc. freq. */
+	0x06, 0x40,		/* subc. phase */
+
+	0x07, TR0MODE,		/* TR0, 16bit */
+	0x08, 0x21,		/*  */
+	0x09, 0x00,		/*  */
+	0x0a, 0x00,		/*  */
+	0x0b, 0x00,		/*  */
+	0x0c, TR1CAPT,		/* TR1 */
+	0x0d, 0x4f,		/* MR2 */
+	0x0e, 0x00,		/*  */
+	0x0f, 0x00,		/*  */
+	0x10, 0x00,		/*  */
+	0x11, 0x00,		/*  */
+};
+
+static const unsigned char init_pal[] = {
+	0x00, MR050,		/* MR0, PAL enabled */
+	0x01, 0x00,		/* MR1 */
+	0x02, 0x0c,		/* subc. freq. */
+	0x03, 0x8c,		/* subc. freq. */
+	0x04, 0x79,		/* subc. freq. */
+	0x05, 0x26,		/* subc. freq. */
+	0x06, 0x40,		/* subc. phase */
+};
+
+static const unsigned char init_ntsc[] = {
+	0x00, MR060,		/* MR0, NTSC enabled */
+	0x01, 0x00,		/* MR1 */
+	0x02, 0x55,		/* subc. freq. */
+	0x03, 0x55,		/* subc. freq. */
+	0x04, 0x55,		/* subc. freq. */
+	0x05, 0x25,		/* subc. freq. */
+	0x06, 0x1a,		/* subc. phase */
+};
+
+static int adv7175_init(struct v4l2_subdev *sd, u32 val)
+{
+	/* 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;
+}
+
+static int adv7175_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std)
+{
+	struct adv7175 *encoder = to_adv7175(sd);
+
+	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,
+			     u32 input, u32 output, u32 config)
+{
+	struct adv7175 *encoder = to_adv7175(sd);
+
+	/* RJ: input = 0: input is from decoder
+	   input = 1: input is from ZR36060
+	   input = 2: color bar */
+
+	switch (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", input);
+		return -EINVAL;
+	}
+	v4l2_dbg(1, debug, sd, "switched to %s\n", inputs[input]);
+	encoder->input = input;
+	return 0;
+}
+
+static int adv7175_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
+				enum v4l2_mbus_pixelcode *code)
+{
+	if (index >= ARRAY_SIZE(adv7175_codes))
+		return -EINVAL;
+
+	*code = adv7175_codes[index];
+	return 0;
+}
+
+static int adv7175_g_fmt(struct v4l2_subdev *sd,
+				struct v4l2_mbus_framefmt *mf)
+{
+	u8 val = adv7175_read(sd, 0x7);
+
+	if ((val & 0x40) == (1 << 6))
+		mf->code = V4L2_MBUS_FMT_UYVY8_1X16;
+	else
+		mf->code = V4L2_MBUS_FMT_UYVY8_2X8;
+
+	mf->colorspace  = V4L2_COLORSPACE_SMPTE170M;
+	mf->width       = 0;
+	mf->height      = 0;
+	mf->field       = V4L2_FIELD_ANY;
+
+	return 0;
+}
+
+static int adv7175_s_fmt(struct v4l2_subdev *sd,
+				struct v4l2_mbus_framefmt *mf)
+{
+	u8 val = adv7175_read(sd, 0x7);
+	int ret;
+
+	switch (mf->code) {
+	case V4L2_MBUS_FMT_UYVY8_2X8:
+		val &= ~0x40;
+		break;
+
+	case V4L2_MBUS_FMT_UYVY8_1X16:
+		val |= 0x40;
+		break;
+
+	default:
+		v4l2_dbg(1, debug, sd,
+			"illegal v4l2_mbus_framefmt code: %d\n", mf->code);
+		return -EINVAL;
+	}
+
+	ret = adv7175_write(sd, 0x7, val);
+
+	return ret;
+}
+
+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);
+}
+
+static int adv7175_s_power(struct v4l2_subdev *sd, int on)
+{
+	if (on)
+		adv7175_write(sd, 0x01, 0x00);
+	else
+		adv7175_write(sd, 0x01, 0x78);
+
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static const struct v4l2_subdev_core_ops adv7175_core_ops = {
+	.g_chip_ident = adv7175_g_chip_ident,
+	.init = adv7175_init,
+	.s_power = adv7175_s_power,
+};
+
+static const struct v4l2_subdev_video_ops adv7175_video_ops = {
+	.s_std_output = adv7175_s_std_output,
+	.s_routing = adv7175_s_routing,
+	.s_mbus_fmt = adv7175_s_fmt,
+	.g_mbus_fmt = adv7175_g_fmt,
+	.enum_mbus_fmt  = adv7175_enum_fmt,
+};
+
+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))
+		return -ENODEV;
+
+	v4l_info(client, "chip found @ 0x%x (%s)\n",
+			client->addr << 1, client->adapter->name);
+
+	encoder = kzalloc(sizeof(struct adv7175), GFP_KERNEL);
+	if (encoder == NULL)
+		return -ENOMEM;
+	sd = &encoder->sd;
+	v4l2_i2c_subdev_init(sd, client, &adv7175_ops);
+	encoder->norm = V4L2_STD_NTSC;
+	encoder->input = 0;
+
+	i = adv7175_write_block(sd, init_common, sizeof(init_common));
+	if (i >= 0) {
+		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)
+		v4l2_dbg(1, debug, sd, "init error 0x%x\n", i);
+	return 0;
+}
+
+static int adv7175_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+
+	v4l2_device_unregister_subdev(sd);
+	kfree(to_adv7175(sd));
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static const struct i2c_device_id adv7175_id[] = {
+	{ "adv7175", 0 },
+	{ "adv7176", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, adv7175_id);
+
+static struct i2c_driver adv7175_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "adv7175",
+	},
+	.probe		= adv7175_probe,
+	.remove		= adv7175_remove,
+	.id_table	= adv7175_id,
+};
+
+module_i2c_driver(adv7175_driver);
diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c
new file mode 100644
index 0000000..45ecf8d
--- /dev/null
+++ b/drivers/media/i2c/adv7180.c
@@ -0,0 +1,667 @@
+/*
+ * adv7180.c Analog Devices ADV7180 video decoder driver
+ * Copyright (c) 2009 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You 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/init.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <media/v4l2-ioctl.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-chip-ident.h>
+#include <linux/mutex.h>
+
+#define ADV7180_INPUT_CONTROL_REG			0x00
+#define ADV7180_INPUT_CONTROL_AD_PAL_BG_NTSC_J_SECAM	0x00
+#define ADV7180_INPUT_CONTROL_AD_PAL_BG_NTSC_J_SECAM_PED 0x10
+#define ADV7180_INPUT_CONTROL_AD_PAL_N_NTSC_J_SECAM	0x20
+#define ADV7180_INPUT_CONTROL_AD_PAL_N_NTSC_M_SECAM	0x30
+#define ADV7180_INPUT_CONTROL_NTSC_J			0x40
+#define ADV7180_INPUT_CONTROL_NTSC_M			0x50
+#define ADV7180_INPUT_CONTROL_PAL60			0x60
+#define ADV7180_INPUT_CONTROL_NTSC_443			0x70
+#define ADV7180_INPUT_CONTROL_PAL_BG			0x80
+#define ADV7180_INPUT_CONTROL_PAL_N			0x90
+#define ADV7180_INPUT_CONTROL_PAL_M			0xa0
+#define ADV7180_INPUT_CONTROL_PAL_M_PED			0xb0
+#define ADV7180_INPUT_CONTROL_PAL_COMB_N		0xc0
+#define ADV7180_INPUT_CONTROL_PAL_COMB_N_PED		0xd0
+#define ADV7180_INPUT_CONTROL_PAL_SECAM			0xe0
+#define ADV7180_INPUT_CONTROL_PAL_SECAM_PED		0xf0
+#define ADV7180_INPUT_CONTROL_INSEL_MASK		0x0f
+
+#define ADV7180_EXTENDED_OUTPUT_CONTROL_REG		0x04
+#define ADV7180_EXTENDED_OUTPUT_CONTROL_NTSCDIS		0xC5
+
+#define ADV7180_AUTODETECT_ENABLE_REG			0x07
+#define ADV7180_AUTODETECT_DEFAULT			0x7f
+/* Contrast */
+#define ADV7180_CON_REG		0x08	/*Unsigned */
+#define ADV7180_CON_MIN		0
+#define ADV7180_CON_DEF		128
+#define ADV7180_CON_MAX		255
+/* Brightness*/
+#define ADV7180_BRI_REG		0x0a	/*Signed */
+#define ADV7180_BRI_MIN		-128
+#define ADV7180_BRI_DEF		0
+#define ADV7180_BRI_MAX		127
+/* Hue */
+#define ADV7180_HUE_REG		0x0b	/*Signed, inverted */
+#define ADV7180_HUE_MIN		-127
+#define ADV7180_HUE_DEF		0
+#define ADV7180_HUE_MAX		128
+
+#define ADV7180_ADI_CTRL_REG				0x0e
+#define ADV7180_ADI_CTRL_IRQ_SPACE			0x20
+
+#define ADV7180_PWR_MAN_REG		0x0f
+#define ADV7180_PWR_MAN_ON		0x04
+#define ADV7180_PWR_MAN_OFF		0x24
+#define ADV7180_PWR_MAN_RES		0x80
+
+#define ADV7180_STATUS1_REG				0x10
+#define ADV7180_STATUS1_IN_LOCK		0x01
+#define ADV7180_STATUS1_AUTOD_MASK	0x70
+#define ADV7180_STATUS1_AUTOD_NTSM_M_J	0x00
+#define ADV7180_STATUS1_AUTOD_NTSC_4_43 0x10
+#define ADV7180_STATUS1_AUTOD_PAL_M	0x20
+#define ADV7180_STATUS1_AUTOD_PAL_60	0x30
+#define ADV7180_STATUS1_AUTOD_PAL_B_G	0x40
+#define ADV7180_STATUS1_AUTOD_SECAM	0x50
+#define ADV7180_STATUS1_AUTOD_PAL_COMB	0x60
+#define ADV7180_STATUS1_AUTOD_SECAM_525	0x70
+
+#define ADV7180_IDENT_REG 0x11
+#define ADV7180_ID_7180 0x18
+
+#define ADV7180_ICONF1_ADI		0x40
+#define ADV7180_ICONF1_ACTIVE_LOW	0x01
+#define ADV7180_ICONF1_PSYNC_ONLY	0x10
+#define ADV7180_ICONF1_ACTIVE_TO_CLR	0xC0
+/* Saturation */
+#define ADV7180_SD_SAT_CB_REG	0xe3	/*Unsigned */
+#define ADV7180_SD_SAT_CR_REG	0xe4	/*Unsigned */
+#define ADV7180_SAT_MIN		0
+#define ADV7180_SAT_DEF		128
+#define ADV7180_SAT_MAX		255
+
+#define ADV7180_IRQ1_LOCK	0x01
+#define ADV7180_IRQ1_UNLOCK	0x02
+#define ADV7180_ISR1_ADI	0x42
+#define ADV7180_ICR1_ADI	0x43
+#define ADV7180_IMR1_ADI	0x44
+#define ADV7180_IMR2_ADI	0x48
+#define ADV7180_IRQ3_AD_CHANGE	0x08
+#define ADV7180_ISR3_ADI	0x4A
+#define ADV7180_ICR3_ADI	0x4B
+#define ADV7180_IMR3_ADI	0x4C
+#define ADV7180_IMR4_ADI	0x50
+
+#define ADV7180_NTSC_V_BIT_END_REG	0xE6
+#define ADV7180_NTSC_V_BIT_END_MANUAL_NVEND	0x4F
+
+struct adv7180_state {
+	struct v4l2_ctrl_handler ctrl_hdl;
+	struct v4l2_subdev	sd;
+	struct work_struct	work;
+	struct mutex		mutex; /* mutual excl. when accessing chip */
+	int			irq;
+	v4l2_std_id		curr_norm;
+	bool			autodetect;
+	u8			input;
+};
+#define to_adv7180_sd(_ctrl) (&container_of(_ctrl->handler,		\
+					    struct adv7180_state,	\
+					    ctrl_hdl)->sd)
+
+static v4l2_std_id adv7180_std_to_v4l2(u8 status1)
+{
+	switch (status1 & ADV7180_STATUS1_AUTOD_MASK) {
+	case ADV7180_STATUS1_AUTOD_NTSM_M_J:
+		return V4L2_STD_NTSC;
+	case ADV7180_STATUS1_AUTOD_NTSC_4_43:
+		return V4L2_STD_NTSC_443;
+	case ADV7180_STATUS1_AUTOD_PAL_M:
+		return V4L2_STD_PAL_M;
+	case ADV7180_STATUS1_AUTOD_PAL_60:
+		return V4L2_STD_PAL_60;
+	case ADV7180_STATUS1_AUTOD_PAL_B_G:
+		return V4L2_STD_PAL;
+	case ADV7180_STATUS1_AUTOD_SECAM:
+		return V4L2_STD_SECAM;
+	case ADV7180_STATUS1_AUTOD_PAL_COMB:
+		return V4L2_STD_PAL_Nc | V4L2_STD_PAL_N;
+	case ADV7180_STATUS1_AUTOD_SECAM_525:
+		return V4L2_STD_SECAM;
+	default:
+		return V4L2_STD_UNKNOWN;
+	}
+}
+
+static int v4l2_std_to_adv7180(v4l2_std_id std)
+{
+	if (std == V4L2_STD_PAL_60)
+		return ADV7180_INPUT_CONTROL_PAL60;
+	if (std == V4L2_STD_NTSC_443)
+		return ADV7180_INPUT_CONTROL_NTSC_443;
+	if (std == V4L2_STD_PAL_N)
+		return ADV7180_INPUT_CONTROL_PAL_N;
+	if (std == V4L2_STD_PAL_M)
+		return ADV7180_INPUT_CONTROL_PAL_M;
+	if (std == V4L2_STD_PAL_Nc)
+		return ADV7180_INPUT_CONTROL_PAL_COMB_N;
+
+	if (std & V4L2_STD_PAL)
+		return ADV7180_INPUT_CONTROL_PAL_BG;
+	if (std & V4L2_STD_NTSC)
+		return ADV7180_INPUT_CONTROL_NTSC_M;
+	if (std & V4L2_STD_SECAM)
+		return ADV7180_INPUT_CONTROL_PAL_SECAM;
+
+	return -EINVAL;
+}
+
+static u32 adv7180_status_to_v4l2(u8 status1)
+{
+	if (!(status1 & ADV7180_STATUS1_IN_LOCK))
+		return V4L2_IN_ST_NO_SIGNAL;
+
+	return 0;
+}
+
+static int __adv7180_status(struct i2c_client *client, u32 *status,
+			    v4l2_std_id *std)
+{
+	int status1 = i2c_smbus_read_byte_data(client, ADV7180_STATUS1_REG);
+
+	if (status1 < 0)
+		return status1;
+
+	if (status)
+		*status = adv7180_status_to_v4l2(status1);
+	if (std)
+		*std = adv7180_std_to_v4l2(status1);
+
+	return 0;
+}
+
+static inline struct adv7180_state *to_state(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct adv7180_state, sd);
+}
+
+static int adv7180_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
+{
+	struct adv7180_state *state = to_state(sd);
+	int err = mutex_lock_interruptible(&state->mutex);
+	if (err)
+		return err;
+
+	/* when we are interrupt driven we know the state */
+	if (!state->autodetect || state->irq > 0)
+		*std = state->curr_norm;
+	else
+		err = __adv7180_status(v4l2_get_subdevdata(sd), NULL, std);
+
+	mutex_unlock(&state->mutex);
+	return err;
+}
+
+static int adv7180_s_routing(struct v4l2_subdev *sd, u32 input,
+			     u32 output, u32 config)
+{
+	struct adv7180_state *state = to_state(sd);
+	int ret = mutex_lock_interruptible(&state->mutex);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	if (ret)
+		return ret;
+
+	/* We cannot discriminate between LQFP and 40-pin LFCSP, so accept
+	 * all inputs and let the card driver take care of validation
+	 */
+	if ((input & ADV7180_INPUT_CONTROL_INSEL_MASK) != input)
+		goto out;
+
+	ret = i2c_smbus_read_byte_data(client, ADV7180_INPUT_CONTROL_REG);
+
+	if (ret < 0)
+		goto out;
+
+	ret &= ~ADV7180_INPUT_CONTROL_INSEL_MASK;
+	ret = i2c_smbus_write_byte_data(client,
+					ADV7180_INPUT_CONTROL_REG, ret | input);
+	state->input = input;
+out:
+	mutex_unlock(&state->mutex);
+	return ret;
+}
+
+static int adv7180_g_input_status(struct v4l2_subdev *sd, u32 *status)
+{
+	struct adv7180_state *state = to_state(sd);
+	int ret = mutex_lock_interruptible(&state->mutex);
+	if (ret)
+		return ret;
+
+	ret = __adv7180_status(v4l2_get_subdevdata(sd), status, NULL);
+	mutex_unlock(&state->mutex);
+	return ret;
+}
+
+static int adv7180_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_ADV7180, 0);
+}
+
+static int adv7180_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
+{
+	struct adv7180_state *state = to_state(sd);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	int ret = mutex_lock_interruptible(&state->mutex);
+	if (ret)
+		return ret;
+
+	/* all standards -> autodetect */
+	if (std == V4L2_STD_ALL) {
+		ret =
+		    i2c_smbus_write_byte_data(client, ADV7180_INPUT_CONTROL_REG,
+				ADV7180_INPUT_CONTROL_AD_PAL_BG_NTSC_J_SECAM
+					      | state->input);
+		if (ret < 0)
+			goto out;
+
+		__adv7180_status(client, NULL, &state->curr_norm);
+		state->autodetect = true;
+	} else {
+		ret = v4l2_std_to_adv7180(std);
+		if (ret < 0)
+			goto out;
+
+		ret = i2c_smbus_write_byte_data(client,
+						ADV7180_INPUT_CONTROL_REG,
+						ret | state->input);
+		if (ret < 0)
+			goto out;
+
+		state->curr_norm = std;
+		state->autodetect = false;
+	}
+	ret = 0;
+out:
+	mutex_unlock(&state->mutex);
+	return ret;
+}
+
+static int adv7180_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct v4l2_subdev *sd = to_adv7180_sd(ctrl);
+	struct adv7180_state *state = to_state(sd);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	int ret = mutex_lock_interruptible(&state->mutex);
+	int val;
+
+	if (ret)
+		return ret;
+	val = ctrl->val;
+	switch (ctrl->id) {
+	case V4L2_CID_BRIGHTNESS:
+		ret = i2c_smbus_write_byte_data(client, ADV7180_BRI_REG, val);
+		break;
+	case V4L2_CID_HUE:
+		/*Hue is inverted according to HSL chart */
+		ret = i2c_smbus_write_byte_data(client, ADV7180_HUE_REG, -val);
+		break;
+	case V4L2_CID_CONTRAST:
+		ret = i2c_smbus_write_byte_data(client, ADV7180_CON_REG, val);
+		break;
+	case V4L2_CID_SATURATION:
+		/*
+		 *This could be V4L2_CID_BLUE_BALANCE/V4L2_CID_RED_BALANCE
+		 *Let's not confuse the user, everybody understands saturation
+		 */
+		ret = i2c_smbus_write_byte_data(client, ADV7180_SD_SAT_CB_REG,
+						val);
+		if (ret < 0)
+			break;
+		ret = i2c_smbus_write_byte_data(client, ADV7180_SD_SAT_CR_REG,
+						val);
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	mutex_unlock(&state->mutex);
+	return ret;
+}
+
+static const struct v4l2_ctrl_ops adv7180_ctrl_ops = {
+	.s_ctrl = adv7180_s_ctrl,
+};
+
+static int adv7180_init_controls(struct adv7180_state *state)
+{
+	v4l2_ctrl_handler_init(&state->ctrl_hdl, 4);
+
+	v4l2_ctrl_new_std(&state->ctrl_hdl, &adv7180_ctrl_ops,
+			  V4L2_CID_BRIGHTNESS, ADV7180_BRI_MIN,
+			  ADV7180_BRI_MAX, 1, ADV7180_BRI_DEF);
+	v4l2_ctrl_new_std(&state->ctrl_hdl, &adv7180_ctrl_ops,
+			  V4L2_CID_CONTRAST, ADV7180_CON_MIN,
+			  ADV7180_CON_MAX, 1, ADV7180_CON_DEF);
+	v4l2_ctrl_new_std(&state->ctrl_hdl, &adv7180_ctrl_ops,
+			  V4L2_CID_SATURATION, ADV7180_SAT_MIN,
+			  ADV7180_SAT_MAX, 1, ADV7180_SAT_DEF);
+	v4l2_ctrl_new_std(&state->ctrl_hdl, &adv7180_ctrl_ops,
+			  V4L2_CID_HUE, ADV7180_HUE_MIN,
+			  ADV7180_HUE_MAX, 1, ADV7180_HUE_DEF);
+	state->sd.ctrl_handler = &state->ctrl_hdl;
+	if (state->ctrl_hdl.error) {
+		int err = state->ctrl_hdl.error;
+
+		v4l2_ctrl_handler_free(&state->ctrl_hdl);
+		return err;
+	}
+	v4l2_ctrl_handler_setup(&state->ctrl_hdl);
+
+	return 0;
+}
+static void adv7180_exit_controls(struct adv7180_state *state)
+{
+	v4l2_ctrl_handler_free(&state->ctrl_hdl);
+}
+
+static const struct v4l2_subdev_video_ops adv7180_video_ops = {
+	.querystd = adv7180_querystd,
+	.g_input_status = adv7180_g_input_status,
+	.s_routing = adv7180_s_routing,
+};
+
+static const struct v4l2_subdev_core_ops adv7180_core_ops = {
+	.g_chip_ident = adv7180_g_chip_ident,
+	.s_std = adv7180_s_std,
+	.queryctrl = v4l2_subdev_queryctrl,
+	.g_ctrl = v4l2_subdev_g_ctrl,
+	.s_ctrl = v4l2_subdev_s_ctrl,
+};
+
+static const struct v4l2_subdev_ops adv7180_ops = {
+	.core = &adv7180_core_ops,
+	.video = &adv7180_video_ops,
+};
+
+static void adv7180_work(struct work_struct *work)
+{
+	struct adv7180_state *state = container_of(work, struct adv7180_state,
+						   work);
+	struct i2c_client *client = v4l2_get_subdevdata(&state->sd);
+	u8 isr3;
+
+	mutex_lock(&state->mutex);
+	i2c_smbus_write_byte_data(client, ADV7180_ADI_CTRL_REG,
+				  ADV7180_ADI_CTRL_IRQ_SPACE);
+	isr3 = i2c_smbus_read_byte_data(client, ADV7180_ISR3_ADI);
+	/* clear */
+	i2c_smbus_write_byte_data(client, ADV7180_ICR3_ADI, isr3);
+	i2c_smbus_write_byte_data(client, ADV7180_ADI_CTRL_REG, 0);
+
+	if (isr3 & ADV7180_IRQ3_AD_CHANGE && state->autodetect)
+		__adv7180_status(client, NULL, &state->curr_norm);
+	mutex_unlock(&state->mutex);
+
+	enable_irq(state->irq);
+}
+
+static irqreturn_t adv7180_irq(int irq, void *devid)
+{
+	struct adv7180_state *state = devid;
+
+	schedule_work(&state->work);
+
+	disable_irq_nosync(state->irq);
+
+	return IRQ_HANDLED;
+}
+
+static int init_device(struct i2c_client *client, struct adv7180_state *state)
+{
+	int ret;
+
+	/* Initialize adv7180 */
+	/* Enable autodetection */
+	if (state->autodetect) {
+		ret =
+		    i2c_smbus_write_byte_data(client, ADV7180_INPUT_CONTROL_REG,
+				ADV7180_INPUT_CONTROL_AD_PAL_BG_NTSC_J_SECAM
+					      | state->input);
+		if (ret < 0)
+			return ret;
+
+		ret =
+		    i2c_smbus_write_byte_data(client,
+					      ADV7180_AUTODETECT_ENABLE_REG,
+					      ADV7180_AUTODETECT_DEFAULT);
+		if (ret < 0)
+			return ret;
+	} else {
+		ret = v4l2_std_to_adv7180(state->curr_norm);
+		if (ret < 0)
+			return ret;
+
+		ret =
+		    i2c_smbus_write_byte_data(client, ADV7180_INPUT_CONTROL_REG,
+					      ret | state->input);
+		if (ret < 0)
+			return ret;
+
+	}
+	/* ITU-R BT.656-4 compatible */
+	ret = i2c_smbus_write_byte_data(client,
+			ADV7180_EXTENDED_OUTPUT_CONTROL_REG,
+			ADV7180_EXTENDED_OUTPUT_CONTROL_NTSCDIS);
+	if (ret < 0)
+		return ret;
+
+	/* Manually set V bit end position in NTSC mode */
+	ret = i2c_smbus_write_byte_data(client,
+					ADV7180_NTSC_V_BIT_END_REG,
+					ADV7180_NTSC_V_BIT_END_MANUAL_NVEND);
+	if (ret < 0)
+		return ret;
+
+	/* read current norm */
+	__adv7180_status(client, NULL, &state->curr_norm);
+
+	/* register for interrupts */
+	if (state->irq > 0) {
+		ret = request_irq(state->irq, adv7180_irq, 0, KBUILD_MODNAME,
+				  state);
+		if (ret)
+			return ret;
+
+		ret = i2c_smbus_write_byte_data(client, ADV7180_ADI_CTRL_REG,
+						ADV7180_ADI_CTRL_IRQ_SPACE);
+		if (ret < 0)
+			return ret;
+
+		/* config the Interrupt pin to be active low */
+		ret = i2c_smbus_write_byte_data(client, ADV7180_ICONF1_ADI,
+						ADV7180_ICONF1_ACTIVE_LOW |
+						ADV7180_ICONF1_PSYNC_ONLY);
+		if (ret < 0)
+			return ret;
+
+		ret = i2c_smbus_write_byte_data(client, ADV7180_IMR1_ADI, 0);
+		if (ret < 0)
+			return ret;
+
+		ret = i2c_smbus_write_byte_data(client, ADV7180_IMR2_ADI, 0);
+		if (ret < 0)
+			return ret;
+
+		/* enable AD change interrupts interrupts */
+		ret = i2c_smbus_write_byte_data(client, ADV7180_IMR3_ADI,
+						ADV7180_IRQ3_AD_CHANGE);
+		if (ret < 0)
+			return ret;
+
+		ret = i2c_smbus_write_byte_data(client, ADV7180_IMR4_ADI, 0);
+		if (ret < 0)
+			return ret;
+
+		ret = i2c_smbus_write_byte_data(client, ADV7180_ADI_CTRL_REG,
+						0);
+		if (ret < 0)
+			return ret;
+	}
+
+	return 0;
+}
+
+static __devinit int adv7180_probe(struct i2c_client *client,
+				   const struct i2c_device_id *id)
+{
+	struct adv7180_state *state;
+	struct v4l2_subdev *sd;
+	int ret;
+
+	/* Check if the adapter supports the needed features */
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		return -EIO;
+
+	v4l_info(client, "chip found @ 0x%02x (%s)\n",
+		 client->addr, client->adapter->name);
+
+	state = kzalloc(sizeof(struct adv7180_state), GFP_KERNEL);
+	if (state == NULL) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	state->irq = client->irq;
+	INIT_WORK(&state->work, adv7180_work);
+	mutex_init(&state->mutex);
+	state->autodetect = true;
+	state->input = 0;
+	sd = &state->sd;
+	v4l2_i2c_subdev_init(sd, client, &adv7180_ops);
+
+	ret = adv7180_init_controls(state);
+	if (ret)
+		goto err_unreg_subdev;
+	ret = init_device(client, state);
+	if (ret)
+		goto err_free_ctrl;
+	return 0;
+
+err_free_ctrl:
+	adv7180_exit_controls(state);
+err_unreg_subdev:
+	mutex_destroy(&state->mutex);
+	v4l2_device_unregister_subdev(sd);
+	kfree(state);
+err:
+	printk(KERN_ERR KBUILD_MODNAME ": Failed to probe: %d\n", ret);
+	return ret;
+}
+
+static __devexit int adv7180_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct adv7180_state *state = to_state(sd);
+
+	if (state->irq > 0) {
+		free_irq(client->irq, state);
+		if (cancel_work_sync(&state->work)) {
+			/*
+			 * Work was pending, therefore we need to enable
+			 * IRQ here to balance the disable_irq() done in the
+			 * interrupt handler.
+			 */
+			enable_irq(state->irq);
+		}
+	}
+
+	mutex_destroy(&state->mutex);
+	v4l2_device_unregister_subdev(sd);
+	kfree(to_state(sd));
+	return 0;
+}
+
+static const struct i2c_device_id adv7180_id[] = {
+	{KBUILD_MODNAME, 0},
+	{},
+};
+
+#ifdef CONFIG_PM
+static int adv7180_suspend(struct i2c_client *client, pm_message_t state)
+{
+	int ret;
+
+	ret = i2c_smbus_write_byte_data(client, ADV7180_PWR_MAN_REG,
+					ADV7180_PWR_MAN_OFF);
+	if (ret < 0)
+		return ret;
+	return 0;
+}
+
+static int adv7180_resume(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct adv7180_state *state = to_state(sd);
+	int ret;
+
+	ret = i2c_smbus_write_byte_data(client, ADV7180_PWR_MAN_REG,
+					ADV7180_PWR_MAN_ON);
+	if (ret < 0)
+		return ret;
+	ret = init_device(client, state);
+	if (ret < 0)
+		return ret;
+	return 0;
+}
+#endif
+
+MODULE_DEVICE_TABLE(i2c, adv7180_id);
+
+static struct i2c_driver adv7180_driver = {
+	.driver = {
+		   .owner = THIS_MODULE,
+		   .name = KBUILD_MODNAME,
+		   },
+	.probe = adv7180_probe,
+	.remove = __devexit_p(adv7180_remove),
+#ifdef CONFIG_PM
+	.suspend = adv7180_suspend,
+	.resume = adv7180_resume,
+#endif
+	.id_table = adv7180_id,
+};
+
+module_i2c_driver(adv7180_driver);
+
+MODULE_DESCRIPTION("Analog Devices ADV7180 video decoder driver");
+MODULE_AUTHOR("Mocean Laboratories");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/i2c/adv7183.c b/drivers/media/i2c/adv7183.c
new file mode 100644
index 0000000..e1d4c89
--- /dev/null
+++ b/drivers/media/i2c/adv7183.c
@@ -0,0 +1,699 @@
+/*
+ * adv7183.c Analog Devices ADV7183 video decoder driver
+ *
+ * Copyright (c) 2011 Analog Devices Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/videodev2.h>
+
+#include <media/adv7183.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+
+#include "adv7183_regs.h"
+
+struct adv7183 {
+	struct v4l2_subdev sd;
+	struct v4l2_ctrl_handler hdl;
+
+	v4l2_std_id std; /* Current set standard */
+	u32 input;
+	u32 output;
+	unsigned reset_pin;
+	unsigned oe_pin;
+	struct v4l2_mbus_framefmt fmt;
+};
+
+/* EXAMPLES USING 27 MHz CLOCK
+ * Mode 1 CVBS Input (Composite Video on AIN5)
+ * All standards are supported through autodetect, 8-bit, 4:2:2, ITU-R BT.656 output on P15 to P8.
+ */
+static const unsigned char adv7183_init_regs[] = {
+	ADV7183_IN_CTRL, 0x04,           /* CVBS input on AIN5 */
+	ADV7183_DIGI_CLAMP_CTRL_1, 0x00, /* Slow down digital clamps */
+	ADV7183_SHAP_FILT_CTRL, 0x41,    /* Set CSFM to SH1 */
+	ADV7183_ADC_CTRL, 0x16,          /* Power down ADC 1 and ADC 2 */
+	ADV7183_CTI_DNR_CTRL_4, 0x04,    /* Set DNR threshold to 4 for flat response */
+	/* ADI recommended programming sequence */
+	ADV7183_ADI_CTRL, 0x80,
+	ADV7183_CTI_DNR_CTRL_4, 0x20,
+	0x52, 0x18,
+	0x58, 0xED,
+	0x77, 0xC5,
+	0x7C, 0x93,
+	0x7D, 0x00,
+	0xD0, 0x48,
+	0xD5, 0xA0,
+	0xD7, 0xEA,
+	ADV7183_SD_SATURATION_CR, 0x3E,
+	ADV7183_PAL_V_END, 0x3E,
+	ADV7183_PAL_F_TOGGLE, 0x0F,
+	ADV7183_ADI_CTRL, 0x00,
+};
+
+static inline struct adv7183 *to_adv7183(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct adv7183, sd);
+}
+static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
+{
+	return &container_of(ctrl->handler, struct adv7183, hdl)->sd;
+}
+
+static inline int adv7183_read(struct v4l2_subdev *sd, unsigned char reg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	return i2c_smbus_read_byte_data(client, reg);
+}
+
+static inline int adv7183_write(struct v4l2_subdev *sd, unsigned char reg,
+				unsigned char value)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	return i2c_smbus_write_byte_data(client, reg, value);
+}
+
+static int adv7183_writeregs(struct v4l2_subdev *sd,
+		const unsigned char *regs, unsigned int num)
+{
+	unsigned char reg, data;
+	unsigned int cnt = 0;
+
+	if (num & 0x1) {
+		v4l2_err(sd, "invalid regs array\n");
+		return -1;
+	}
+
+	while (cnt < num) {
+		reg = *regs++;
+		data = *regs++;
+		cnt += 2;
+
+		adv7183_write(sd, reg, data);
+	}
+	return 0;
+}
+
+static int adv7183_log_status(struct v4l2_subdev *sd)
+{
+	struct adv7183 *decoder = to_adv7183(sd);
+
+	v4l2_info(sd, "adv7183: Input control = 0x%02x\n",
+			adv7183_read(sd, ADV7183_IN_CTRL));
+	v4l2_info(sd, "adv7183: Video selection = 0x%02x\n",
+			adv7183_read(sd, ADV7183_VD_SEL));
+	v4l2_info(sd, "adv7183: Output control = 0x%02x\n",
+			adv7183_read(sd, ADV7183_OUT_CTRL));
+	v4l2_info(sd, "adv7183: Extended output control = 0x%02x\n",
+			adv7183_read(sd, ADV7183_EXT_OUT_CTRL));
+	v4l2_info(sd, "adv7183: Autodetect enable = 0x%02x\n",
+			adv7183_read(sd, ADV7183_AUTO_DET_EN));
+	v4l2_info(sd, "adv7183: Contrast = 0x%02x\n",
+			adv7183_read(sd, ADV7183_CONTRAST));
+	v4l2_info(sd, "adv7183: Brightness = 0x%02x\n",
+			adv7183_read(sd, ADV7183_BRIGHTNESS));
+	v4l2_info(sd, "adv7183: Hue = 0x%02x\n",
+			adv7183_read(sd, ADV7183_HUE));
+	v4l2_info(sd, "adv7183: Default value Y = 0x%02x\n",
+			adv7183_read(sd, ADV7183_DEF_Y));
+	v4l2_info(sd, "adv7183: Default value C = 0x%02x\n",
+			adv7183_read(sd, ADV7183_DEF_C));
+	v4l2_info(sd, "adv7183: ADI control = 0x%02x\n",
+			adv7183_read(sd, ADV7183_ADI_CTRL));
+	v4l2_info(sd, "adv7183: Power Management = 0x%02x\n",
+			adv7183_read(sd, ADV7183_POW_MANAGE));
+	v4l2_info(sd, "adv7183: Status 1 2 and 3 = 0x%02x 0x%02x 0x%02x\n",
+			adv7183_read(sd, ADV7183_STATUS_1),
+			adv7183_read(sd, ADV7183_STATUS_2),
+			adv7183_read(sd, ADV7183_STATUS_3));
+	v4l2_info(sd, "adv7183: Ident = 0x%02x\n",
+			adv7183_read(sd, ADV7183_IDENT));
+	v4l2_info(sd, "adv7183: Analog clamp control = 0x%02x\n",
+			adv7183_read(sd, ADV7183_ANAL_CLAMP_CTRL));
+	v4l2_info(sd, "adv7183: Digital clamp control 1 = 0x%02x\n",
+			adv7183_read(sd, ADV7183_DIGI_CLAMP_CTRL_1));
+	v4l2_info(sd, "adv7183: Shaping filter control 1 and 2 = 0x%02x 0x%02x\n",
+			adv7183_read(sd, ADV7183_SHAP_FILT_CTRL),
+			adv7183_read(sd, ADV7183_SHAP_FILT_CTRL_2));
+	v4l2_info(sd, "adv7183: Comb filter control = 0x%02x\n",
+			adv7183_read(sd, ADV7183_COMB_FILT_CTRL));
+	v4l2_info(sd, "adv7183: ADI control 2 = 0x%02x\n",
+			adv7183_read(sd, ADV7183_ADI_CTRL_2));
+	v4l2_info(sd, "adv7183: Pixel delay control = 0x%02x\n",
+			adv7183_read(sd, ADV7183_PIX_DELAY_CTRL));
+	v4l2_info(sd, "adv7183: Misc gain control = 0x%02x\n",
+			adv7183_read(sd, ADV7183_MISC_GAIN_CTRL));
+	v4l2_info(sd, "adv7183: AGC mode control = 0x%02x\n",
+			adv7183_read(sd, ADV7183_AGC_MODE_CTRL));
+	v4l2_info(sd, "adv7183: Chroma gain control 1 and 2 = 0x%02x 0x%02x\n",
+			adv7183_read(sd, ADV7183_CHRO_GAIN_CTRL_1),
+			adv7183_read(sd, ADV7183_CHRO_GAIN_CTRL_2));
+	v4l2_info(sd, "adv7183: Luma gain control 1 and 2 = 0x%02x 0x%02x\n",
+			adv7183_read(sd, ADV7183_LUMA_GAIN_CTRL_1),
+			adv7183_read(sd, ADV7183_LUMA_GAIN_CTRL_2));
+	v4l2_info(sd, "adv7183: Vsync field control 1 2 and 3 = 0x%02x 0x%02x 0x%02x\n",
+			adv7183_read(sd, ADV7183_VS_FIELD_CTRL_1),
+			adv7183_read(sd, ADV7183_VS_FIELD_CTRL_2),
+			adv7183_read(sd, ADV7183_VS_FIELD_CTRL_3));
+	v4l2_info(sd, "adv7183: Hsync positon control 1 2 and 3 = 0x%02x 0x%02x 0x%02x\n",
+			adv7183_read(sd, ADV7183_HS_POS_CTRL_1),
+			adv7183_read(sd, ADV7183_HS_POS_CTRL_2),
+			adv7183_read(sd, ADV7183_HS_POS_CTRL_3));
+	v4l2_info(sd, "adv7183: Polarity = 0x%02x\n",
+			adv7183_read(sd, ADV7183_POLARITY));
+	v4l2_info(sd, "adv7183: ADC control = 0x%02x\n",
+			adv7183_read(sd, ADV7183_ADC_CTRL));
+	v4l2_info(sd, "adv7183: SD offset Cb and Cr = 0x%02x 0x%02x\n",
+			adv7183_read(sd, ADV7183_SD_OFFSET_CB),
+			adv7183_read(sd, ADV7183_SD_OFFSET_CR));
+	v4l2_info(sd, "adv7183: SD saturation Cb and Cr = 0x%02x 0x%02x\n",
+			adv7183_read(sd, ADV7183_SD_SATURATION_CB),
+			adv7183_read(sd, ADV7183_SD_SATURATION_CR));
+	v4l2_info(sd, "adv7183: Drive strength = 0x%02x\n",
+			adv7183_read(sd, ADV7183_DRIVE_STR));
+	v4l2_ctrl_handler_log_status(&decoder->hdl, sd->name);
+	return 0;
+}
+
+static int adv7183_g_std(struct v4l2_subdev *sd, v4l2_std_id *std)
+{
+	struct adv7183 *decoder = to_adv7183(sd);
+
+	*std = decoder->std;
+	return 0;
+}
+
+static int adv7183_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
+{
+	struct adv7183 *decoder = to_adv7183(sd);
+	int reg;
+
+	reg = adv7183_read(sd, ADV7183_IN_CTRL) & 0xF;
+	if (std == V4L2_STD_PAL_60)
+		reg |= 0x60;
+	else if (std == V4L2_STD_NTSC_443)
+		reg |= 0x70;
+	else if (std == V4L2_STD_PAL_N)
+		reg |= 0x90;
+	else if (std == V4L2_STD_PAL_M)
+		reg |= 0xA0;
+	else if (std == V4L2_STD_PAL_Nc)
+		reg |= 0xC0;
+	else if (std & V4L2_STD_PAL)
+		reg |= 0x80;
+	else if (std & V4L2_STD_NTSC)
+		reg |= 0x50;
+	else if (std & V4L2_STD_SECAM)
+		reg |= 0xE0;
+	else
+		return -EINVAL;
+	adv7183_write(sd, ADV7183_IN_CTRL, reg);
+
+	decoder->std = std;
+
+	return 0;
+}
+
+static int adv7183_reset(struct v4l2_subdev *sd, u32 val)
+{
+	int reg;
+
+	reg = adv7183_read(sd, ADV7183_POW_MANAGE) | 0x80;
+	adv7183_write(sd, ADV7183_POW_MANAGE, reg);
+	/* wait 5ms before any further i2c writes are performed */
+	usleep_range(5000, 10000);
+	return 0;
+}
+
+static int adv7183_s_routing(struct v4l2_subdev *sd,
+				u32 input, u32 output, u32 config)
+{
+	struct adv7183 *decoder = to_adv7183(sd);
+	int reg;
+
+	if ((input > ADV7183_COMPONENT1) || (output > ADV7183_16BIT_OUT))
+		return -EINVAL;
+
+	if (input != decoder->input) {
+		decoder->input = input;
+		reg = adv7183_read(sd, ADV7183_IN_CTRL) & 0xF0;
+		switch (input) {
+		case ADV7183_COMPOSITE1:
+			reg |= 0x1;
+			break;
+		case ADV7183_COMPOSITE2:
+			reg |= 0x2;
+			break;
+		case ADV7183_COMPOSITE3:
+			reg |= 0x3;
+			break;
+		case ADV7183_COMPOSITE4:
+			reg |= 0x4;
+			break;
+		case ADV7183_COMPOSITE5:
+			reg |= 0x5;
+			break;
+		case ADV7183_COMPOSITE6:
+			reg |= 0xB;
+			break;
+		case ADV7183_COMPOSITE7:
+			reg |= 0xC;
+			break;
+		case ADV7183_COMPOSITE8:
+			reg |= 0xD;
+			break;
+		case ADV7183_COMPOSITE9:
+			reg |= 0xE;
+			break;
+		case ADV7183_COMPOSITE10:
+			reg |= 0xF;
+			break;
+		case ADV7183_SVIDEO0:
+			reg |= 0x6;
+			break;
+		case ADV7183_SVIDEO1:
+			reg |= 0x7;
+			break;
+		case ADV7183_SVIDEO2:
+			reg |= 0x8;
+			break;
+		case ADV7183_COMPONENT0:
+			reg |= 0x9;
+			break;
+		case ADV7183_COMPONENT1:
+			reg |= 0xA;
+			break;
+		default:
+			break;
+		}
+		adv7183_write(sd, ADV7183_IN_CTRL, reg);
+	}
+
+	if (output != decoder->output) {
+		decoder->output = output;
+		reg = adv7183_read(sd, ADV7183_OUT_CTRL) & 0xC0;
+		switch (output) {
+		case ADV7183_16BIT_OUT:
+			reg |= 0x9;
+			break;
+		default:
+			reg |= 0xC;
+			break;
+		}
+		adv7183_write(sd, ADV7183_OUT_CTRL, reg);
+	}
+
+	return 0;
+}
+
+static int adv7183_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct v4l2_subdev *sd = to_sd(ctrl);
+	int val = ctrl->val;
+
+	switch (ctrl->id) {
+	case V4L2_CID_BRIGHTNESS:
+		if (val < 0)
+			val = 127 - val;
+		adv7183_write(sd, ADV7183_BRIGHTNESS, val);
+		break;
+	case V4L2_CID_CONTRAST:
+		adv7183_write(sd, ADV7183_CONTRAST, val);
+		break;
+	case V4L2_CID_SATURATION:
+		adv7183_write(sd, ADV7183_SD_SATURATION_CB, val >> 8);
+		adv7183_write(sd, ADV7183_SD_SATURATION_CR, (val & 0xFF));
+		break;
+	case V4L2_CID_HUE:
+		adv7183_write(sd, ADV7183_SD_OFFSET_CB, val >> 8);
+		adv7183_write(sd, ADV7183_SD_OFFSET_CR, (val & 0xFF));
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int adv7183_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
+{
+	struct adv7183 *decoder = to_adv7183(sd);
+	int reg;
+
+	/* enable autodetection block */
+	reg = adv7183_read(sd, ADV7183_IN_CTRL) & 0xF;
+	adv7183_write(sd, ADV7183_IN_CTRL, reg);
+
+	/* wait autodetection switch */
+	mdelay(10);
+
+	/* get autodetection result */
+	reg = adv7183_read(sd, ADV7183_STATUS_1);
+	switch ((reg >> 0x4) & 0x7) {
+	case 0:
+		*std = V4L2_STD_NTSC;
+		break;
+	case 1:
+		*std = V4L2_STD_NTSC_443;
+		break;
+	case 2:
+		*std = V4L2_STD_PAL_M;
+		break;
+	case 3:
+		*std = V4L2_STD_PAL_60;
+		break;
+	case 4:
+		*std = V4L2_STD_PAL;
+		break;
+	case 5:
+		*std = V4L2_STD_SECAM;
+		break;
+	case 6:
+		*std = V4L2_STD_PAL_Nc;
+		break;
+	case 7:
+		*std = V4L2_STD_SECAM;
+		break;
+	default:
+		*std = V4L2_STD_UNKNOWN;
+		break;
+	}
+
+	/* after std detection, write back user set std */
+	adv7183_s_std(sd, decoder->std);
+	return 0;
+}
+
+static int adv7183_g_input_status(struct v4l2_subdev *sd, u32 *status)
+{
+	int reg;
+
+	*status = V4L2_IN_ST_NO_SIGNAL;
+	reg = adv7183_read(sd, ADV7183_STATUS_1);
+	if (reg < 0)
+		return reg;
+	if (reg & 0x1)
+		*status = 0;
+	return 0;
+}
+
+static int adv7183_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index,
+				enum v4l2_mbus_pixelcode *code)
+{
+	if (index > 0)
+		return -EINVAL;
+
+	*code = V4L2_MBUS_FMT_UYVY8_2X8;
+	return 0;
+}
+
+static int adv7183_try_mbus_fmt(struct v4l2_subdev *sd,
+				struct v4l2_mbus_framefmt *fmt)
+{
+	struct adv7183 *decoder = to_adv7183(sd);
+
+	fmt->code = V4L2_MBUS_FMT_UYVY8_2X8;
+	fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
+	if (decoder->std & V4L2_STD_525_60) {
+		fmt->field = V4L2_FIELD_SEQ_TB;
+		fmt->width = 720;
+		fmt->height = 480;
+	} else {
+		fmt->field = V4L2_FIELD_SEQ_BT;
+		fmt->width = 720;
+		fmt->height = 576;
+	}
+	return 0;
+}
+
+static int adv7183_s_mbus_fmt(struct v4l2_subdev *sd,
+				struct v4l2_mbus_framefmt *fmt)
+{
+	struct adv7183 *decoder = to_adv7183(sd);
+
+	adv7183_try_mbus_fmt(sd, fmt);
+	decoder->fmt = *fmt;
+	return 0;
+}
+
+static int adv7183_g_mbus_fmt(struct v4l2_subdev *sd,
+				struct v4l2_mbus_framefmt *fmt)
+{
+	struct adv7183 *decoder = to_adv7183(sd);
+
+	*fmt = decoder->fmt;
+	return 0;
+}
+
+static int adv7183_s_stream(struct v4l2_subdev *sd, int enable)
+{
+	struct adv7183 *decoder = to_adv7183(sd);
+
+	if (enable)
+		gpio_direction_output(decoder->oe_pin, 0);
+	else
+		gpio_direction_output(decoder->oe_pin, 1);
+	udelay(1);
+	return 0;
+}
+
+static int adv7183_g_chip_ident(struct v4l2_subdev *sd,
+		struct v4l2_dbg_chip_ident *chip)
+{
+	int rev;
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	/* 0x11 for adv7183, 0x13 for adv7183b */
+	rev = adv7183_read(sd, ADV7183_IDENT);
+
+	return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_ADV7183, rev);
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int adv7183_g_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;
+	reg->val = adv7183_read(sd, reg->reg & 0xff);
+	reg->size = 1;
+	return 0;
+}
+
+static int adv7183_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;
+	adv7183_write(sd, reg->reg & 0xff, reg->val & 0xff);
+	return 0;
+}
+#endif
+
+static const struct v4l2_ctrl_ops adv7183_ctrl_ops = {
+	.s_ctrl = adv7183_s_ctrl,
+};
+
+static const struct v4l2_subdev_core_ops adv7183_core_ops = {
+	.log_status = adv7183_log_status,
+	.g_std = adv7183_g_std,
+	.s_std = adv7183_s_std,
+	.reset = adv7183_reset,
+	.g_chip_ident = adv7183_g_chip_ident,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.g_register = adv7183_g_register,
+	.s_register = adv7183_s_register,
+#endif
+};
+
+static const struct v4l2_subdev_video_ops adv7183_video_ops = {
+	.s_routing = adv7183_s_routing,
+	.querystd = adv7183_querystd,
+	.g_input_status = adv7183_g_input_status,
+	.enum_mbus_fmt = adv7183_enum_mbus_fmt,
+	.try_mbus_fmt = adv7183_try_mbus_fmt,
+	.s_mbus_fmt = adv7183_s_mbus_fmt,
+	.g_mbus_fmt = adv7183_g_mbus_fmt,
+	.s_stream = adv7183_s_stream,
+};
+
+static const struct v4l2_subdev_ops adv7183_ops = {
+	.core = &adv7183_core_ops,
+	.video = &adv7183_video_ops,
+};
+
+static int adv7183_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	struct adv7183 *decoder;
+	struct v4l2_subdev *sd;
+	struct v4l2_ctrl_handler *hdl;
+	int ret;
+	struct v4l2_mbus_framefmt fmt;
+	const unsigned *pin_array;
+
+	/* Check if the adapter supports the needed features */
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		return -EIO;
+
+	v4l_info(client, "chip found @ 0x%02x (%s)\n",
+			client->addr << 1, client->adapter->name);
+
+	pin_array = client->dev.platform_data;
+	if (pin_array == NULL)
+		return -EINVAL;
+
+	decoder = kzalloc(sizeof(struct adv7183), GFP_KERNEL);
+	if (decoder == NULL)
+		return -ENOMEM;
+
+	decoder->reset_pin = pin_array[0];
+	decoder->oe_pin = pin_array[1];
+
+	if (gpio_request(decoder->reset_pin, "ADV7183 Reset")) {
+		v4l_err(client, "failed to request GPIO %d\n", decoder->reset_pin);
+		ret = -EBUSY;
+		goto err_free_decoder;
+	}
+
+	if (gpio_request(decoder->oe_pin, "ADV7183 Output Enable")) {
+		v4l_err(client, "failed to request GPIO %d\n", decoder->oe_pin);
+		ret = -EBUSY;
+		goto err_free_reset;
+	}
+
+	sd = &decoder->sd;
+	v4l2_i2c_subdev_init(sd, client, &adv7183_ops);
+
+	hdl = &decoder->hdl;
+	v4l2_ctrl_handler_init(hdl, 4);
+	v4l2_ctrl_new_std(hdl, &adv7183_ctrl_ops,
+			V4L2_CID_BRIGHTNESS, -128, 127, 1, 0);
+	v4l2_ctrl_new_std(hdl, &adv7183_ctrl_ops,
+			V4L2_CID_CONTRAST, 0, 0xFF, 1, 0x80);
+	v4l2_ctrl_new_std(hdl, &adv7183_ctrl_ops,
+			V4L2_CID_SATURATION, 0, 0xFFFF, 1, 0x8080);
+	v4l2_ctrl_new_std(hdl, &adv7183_ctrl_ops,
+			V4L2_CID_HUE, 0, 0xFFFF, 1, 0x8080);
+	/* hook the control handler into the driver */
+	sd->ctrl_handler = hdl;
+	if (hdl->error) {
+		ret = hdl->error;
+
+		v4l2_ctrl_handler_free(hdl);
+		goto err_free_oe;
+	}
+
+	/* v4l2 doesn't support an autodetect standard, pick PAL as default */
+	decoder->std = V4L2_STD_PAL;
+	decoder->input = ADV7183_COMPOSITE4;
+	decoder->output = ADV7183_8BIT_OUT;
+
+	gpio_direction_output(decoder->oe_pin, 1);
+	/* reset chip */
+	gpio_direction_output(decoder->reset_pin, 0);
+	/* reset pulse width at least 5ms */
+	mdelay(10);
+	gpio_direction_output(decoder->reset_pin, 1);
+	/* wait 5ms before any further i2c writes are performed */
+	mdelay(5);
+
+	adv7183_writeregs(sd, adv7183_init_regs, ARRAY_SIZE(adv7183_init_regs));
+	adv7183_s_std(sd, decoder->std);
+	fmt.width = 720;
+	fmt.height = 576;
+	adv7183_s_mbus_fmt(sd, &fmt);
+
+	/* initialize the hardware to the default control values */
+	ret = v4l2_ctrl_handler_setup(hdl);
+	if (ret) {
+		v4l2_ctrl_handler_free(hdl);
+		goto err_free_oe;
+	}
+
+	return 0;
+err_free_oe:
+	gpio_free(decoder->oe_pin);
+err_free_reset:
+	gpio_free(decoder->reset_pin);
+err_free_decoder:
+	kfree(decoder);
+	return ret;
+}
+
+static int adv7183_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct adv7183 *decoder = to_adv7183(sd);
+
+	v4l2_device_unregister_subdev(sd);
+	v4l2_ctrl_handler_free(sd->ctrl_handler);
+	gpio_free(decoder->oe_pin);
+	gpio_free(decoder->reset_pin);
+	kfree(decoder);
+	return 0;
+}
+
+static const struct i2c_device_id adv7183_id[] = {
+	{"adv7183", 0},
+	{},
+};
+
+MODULE_DEVICE_TABLE(i2c, adv7183_id);
+
+static struct i2c_driver adv7183_driver = {
+	.driver = {
+		.owner  = THIS_MODULE,
+		.name   = "adv7183",
+	},
+	.probe          = adv7183_probe,
+	.remove         = __devexit_p(adv7183_remove),
+	.id_table       = adv7183_id,
+};
+
+static __init int adv7183_init(void)
+{
+	return i2c_add_driver(&adv7183_driver);
+}
+
+static __exit void adv7183_exit(void)
+{
+	i2c_del_driver(&adv7183_driver);
+}
+
+module_init(adv7183_init);
+module_exit(adv7183_exit);
+
+MODULE_DESCRIPTION("Analog Devices ADV7183 video decoder driver");
+MODULE_AUTHOR("Scott Jiang <Scott.Jiang.Linux@gmail.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/i2c/adv7183_regs.h b/drivers/media/i2c/adv7183_regs.h
new file mode 100644
index 0000000..4a5b7d2
--- /dev/null
+++ b/drivers/media/i2c/adv7183_regs.h
@@ -0,0 +1,107 @@
+/*
+ * adv7183 - Analog Devices ADV7183 video decoder registers
+ *
+ * Copyright (c) 2011 Analog Devices Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _ADV7183_REGS_H_
+#define _ADV7183_REGS_H_
+
+#define ADV7183_IN_CTRL            0x00 /* Input control */
+#define ADV7183_VD_SEL             0x01 /* Video selection */
+#define ADV7183_OUT_CTRL           0x03 /* Output control */
+#define ADV7183_EXT_OUT_CTRL       0x04 /* Extended output control */
+#define ADV7183_AUTO_DET_EN        0x07 /* Autodetect enable */
+#define ADV7183_CONTRAST           0x08 /* Contrast */
+#define ADV7183_BRIGHTNESS         0x0A /* Brightness */
+#define ADV7183_HUE                0x0B /* Hue */
+#define ADV7183_DEF_Y              0x0C /* Default value Y */
+#define ADV7183_DEF_C              0x0D /* Default value C */
+#define ADV7183_ADI_CTRL           0x0E /* ADI control */
+#define ADV7183_POW_MANAGE         0x0F /* Power Management */
+#define ADV7183_STATUS_1           0x10 /* Status 1 */
+#define ADV7183_IDENT              0x11 /* Ident */
+#define ADV7183_STATUS_2           0x12 /* Status 2 */
+#define ADV7183_STATUS_3           0x13 /* Status 3 */
+#define ADV7183_ANAL_CLAMP_CTRL    0x14 /* Analog clamp control */
+#define ADV7183_DIGI_CLAMP_CTRL_1  0x15 /* Digital clamp control 1 */
+#define ADV7183_SHAP_FILT_CTRL     0x17 /* Shaping filter control */
+#define ADV7183_SHAP_FILT_CTRL_2   0x18 /* Shaping filter control 2 */
+#define ADV7183_COMB_FILT_CTRL     0x19 /* Comb filter control */
+#define ADV7183_ADI_CTRL_2         0x1D /* ADI control 2 */
+#define ADV7183_PIX_DELAY_CTRL     0x27 /* Pixel delay control */
+#define ADV7183_MISC_GAIN_CTRL     0x2B /* Misc gain control */
+#define ADV7183_AGC_MODE_CTRL      0x2C /* AGC mode control */
+#define ADV7183_CHRO_GAIN_CTRL_1   0x2D /* Chroma gain control 1 */
+#define ADV7183_CHRO_GAIN_CTRL_2   0x2E /* Chroma gain control 2 */
+#define ADV7183_LUMA_GAIN_CTRL_1   0x2F /* Luma gain control 1 */
+#define ADV7183_LUMA_GAIN_CTRL_2   0x30 /* Luma gain control 2 */
+#define ADV7183_VS_FIELD_CTRL_1    0x31 /* Vsync field control 1 */
+#define ADV7183_VS_FIELD_CTRL_2    0x32 /* Vsync field control 2 */
+#define ADV7183_VS_FIELD_CTRL_3    0x33 /* Vsync field control 3 */
+#define ADV7183_HS_POS_CTRL_1      0x34 /* Hsync positon control 1 */
+#define ADV7183_HS_POS_CTRL_2      0x35 /* Hsync positon control 2 */
+#define ADV7183_HS_POS_CTRL_3      0x36 /* Hsync positon control 3 */
+#define ADV7183_POLARITY           0x37 /* Polarity */
+#define ADV7183_NTSC_COMB_CTRL     0x38 /* NTSC comb control */
+#define ADV7183_PAL_COMB_CTRL      0x39 /* PAL comb control */
+#define ADV7183_ADC_CTRL           0x3A /* ADC control */
+#define ADV7183_MAN_WIN_CTRL       0x3D /* Manual window control */
+#define ADV7183_RESAMPLE_CTRL      0x41 /* Resample control */
+#define ADV7183_GEMSTAR_CTRL_1     0x48 /* Gemstar ctrl 1 */
+#define ADV7183_GEMSTAR_CTRL_2     0x49 /* Gemstar ctrl 2 */
+#define ADV7183_GEMSTAR_CTRL_3     0x4A /* Gemstar ctrl 3 */
+#define ADV7183_GEMSTAR_CTRL_4     0x4B /* Gemstar ctrl 4 */
+#define ADV7183_GEMSTAR_CTRL_5     0x4C /* Gemstar ctrl 5 */
+#define ADV7183_CTI_DNR_CTRL_1     0x4D /* CTI DNR ctrl 1 */
+#define ADV7183_CTI_DNR_CTRL_2     0x4E /* CTI DNR ctrl 2 */
+#define ADV7183_CTI_DNR_CTRL_4     0x50 /* CTI DNR ctrl 4 */
+#define ADV7183_LOCK_CNT           0x51 /* Lock count */
+#define ADV7183_FREE_LINE_LEN      0x8F /* Free-Run line length 1 */
+#define ADV7183_VBI_INFO           0x90 /* VBI info */
+#define ADV7183_WSS_1              0x91 /* WSS 1 */
+#define ADV7183_WSS_2              0x92 /* WSS 2 */
+#define ADV7183_EDTV_1             0x93 /* EDTV 1 */
+#define ADV7183_EDTV_2             0x94 /* EDTV 2 */
+#define ADV7183_EDTV_3             0x95 /* EDTV 3 */
+#define ADV7183_CGMS_1             0x96 /* CGMS 1 */
+#define ADV7183_CGMS_2             0x97 /* CGMS 2 */
+#define ADV7183_CGMS_3             0x98 /* CGMS 3 */
+#define ADV7183_CCAP_1             0x99 /* CCAP 1 */
+#define ADV7183_CCAP_2             0x9A /* CCAP 2 */
+#define ADV7183_LETTERBOX_1        0x9B /* Letterbox 1 */
+#define ADV7183_LETTERBOX_2        0x9C /* Letterbox 2 */
+#define ADV7183_LETTERBOX_3        0x9D /* Letterbox 3 */
+#define ADV7183_CRC_EN             0xB2 /* CRC enable */
+#define ADV7183_ADC_SWITCH_1       0xC3 /* ADC switch 1 */
+#define ADV7183_ADC_SWITCH_2       0xC4 /* ADC swithc 2 */
+#define ADV7183_LETTERBOX_CTRL_1   0xDC /* Letterbox control 1 */
+#define ADV7183_LETTERBOX_CTRL_2   0xDD /* Letterbox control 2 */
+#define ADV7183_SD_OFFSET_CB       0xE1 /* SD offset Cb */
+#define ADV7183_SD_OFFSET_CR       0xE2 /* SD offset Cr */
+#define ADV7183_SD_SATURATION_CB   0xE3 /* SD saturation Cb */
+#define ADV7183_SD_SATURATION_CR   0xE4 /* SD saturation Cr */
+#define ADV7183_NTSC_V_BEGIN       0xE5 /* NTSC V bit begin */
+#define ADV7183_NTSC_V_END         0xE6 /* NTSC V bit end */
+#define ADV7183_NTSC_F_TOGGLE      0xE7 /* NTSC F bit toggle */
+#define ADV7183_PAL_V_BEGIN        0xE8 /* PAL V bit begin */
+#define ADV7183_PAL_V_END          0xE9 /* PAL V bit end */
+#define ADV7183_PAL_F_TOGGLE       0xEA /* PAL F bit toggle */
+#define ADV7183_DRIVE_STR          0xF4 /* Drive strength */
+#define ADV7183_IF_COMP_CTRL       0xF8 /* IF comp control */
+#define ADV7183_VS_MODE_CTRL       0xF9 /* VS mode control */
+
+#endif
diff --git a/drivers/media/i2c/adv7343.c b/drivers/media/i2c/adv7343.c
new file mode 100644
index 0000000..2b5aa67
--- /dev/null
+++ b/drivers/media/i2c/adv7343.c
@@ -0,0 +1,476 @@
+/*
+ * adv7343 - ADV7343 Video Encoder Driver
+ *
+ * The encoder hardware does not support SECAM.
+ *
+ * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed .as is. WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/ctype.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/videodev2.h>
+#include <linux/uaccess.h>
+
+#include <media/adv7343.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-ctrls.h>
+
+#include "adv7343_regs.h"
+
+MODULE_DESCRIPTION("ADV7343 video encoder driver");
+MODULE_LICENSE("GPL");
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Debug level 0-1");
+
+struct adv7343_state {
+	struct v4l2_subdev sd;
+	struct v4l2_ctrl_handler hdl;
+	u8 reg00;
+	u8 reg01;
+	u8 reg02;
+	u8 reg35;
+	u8 reg80;
+	u8 reg82;
+	u32 output;
+	v4l2_std_id std;
+};
+
+static inline struct adv7343_state *to_state(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct adv7343_state, sd);
+}
+
+static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
+{
+	return &container_of(ctrl->handler, struct adv7343_state, hdl)->sd;
+}
+
+static inline int adv7343_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 const u8 adv7343_init_reg_val[] = {
+	ADV7343_SOFT_RESET, ADV7343_SOFT_RESET_DEFAULT,
+	ADV7343_POWER_MODE_REG, ADV7343_POWER_MODE_REG_DEFAULT,
+
+	ADV7343_HD_MODE_REG1, ADV7343_HD_MODE_REG1_DEFAULT,
+	ADV7343_HD_MODE_REG2, ADV7343_HD_MODE_REG2_DEFAULT,
+	ADV7343_HD_MODE_REG3, ADV7343_HD_MODE_REG3_DEFAULT,
+	ADV7343_HD_MODE_REG4, ADV7343_HD_MODE_REG4_DEFAULT,
+	ADV7343_HD_MODE_REG5, ADV7343_HD_MODE_REG5_DEFAULT,
+	ADV7343_HD_MODE_REG6, ADV7343_HD_MODE_REG6_DEFAULT,
+	ADV7343_HD_MODE_REG7, ADV7343_HD_MODE_REG7_DEFAULT,
+
+	ADV7343_SD_MODE_REG1, ADV7343_SD_MODE_REG1_DEFAULT,
+	ADV7343_SD_MODE_REG2, ADV7343_SD_MODE_REG2_DEFAULT,
+	ADV7343_SD_MODE_REG3, ADV7343_SD_MODE_REG3_DEFAULT,
+	ADV7343_SD_MODE_REG4, ADV7343_SD_MODE_REG4_DEFAULT,
+	ADV7343_SD_MODE_REG5, ADV7343_SD_MODE_REG5_DEFAULT,
+	ADV7343_SD_MODE_REG6, ADV7343_SD_MODE_REG6_DEFAULT,
+	ADV7343_SD_MODE_REG7, ADV7343_SD_MODE_REG7_DEFAULT,
+	ADV7343_SD_MODE_REG8, ADV7343_SD_MODE_REG8_DEFAULT,
+
+	ADV7343_SD_HUE_REG, ADV7343_SD_HUE_REG_DEFAULT,
+	ADV7343_SD_CGMS_WSS0, ADV7343_SD_CGMS_WSS0_DEFAULT,
+	ADV7343_SD_BRIGHTNESS_WSS, ADV7343_SD_BRIGHTNESS_WSS_DEFAULT,
+};
+
+/*
+ * 			    2^32
+ * FSC(reg) =  FSC (HZ) * --------
+ *			  27000000
+ */
+static const struct adv7343_std_info stdinfo[] = {
+	{
+		/* FSC(Hz) = 3,579,545.45 Hz */
+		SD_STD_NTSC, 569408542, V4L2_STD_NTSC,
+	}, {
+		/* FSC(Hz) = 3,575,611.00 Hz */
+		SD_STD_PAL_M, 568782678, V4L2_STD_PAL_M,
+	}, {
+		/* FSC(Hz) = 3,582,056.00 */
+		SD_STD_PAL_N, 569807903, V4L2_STD_PAL_Nc,
+	}, {
+		/* FSC(Hz) = 4,433,618.75 Hz */
+		SD_STD_PAL_N, 705268427, V4L2_STD_PAL_N,
+	}, {
+		/* FSC(Hz) = 4,433,618.75 Hz */
+		SD_STD_PAL_BDGHI, 705268427, V4L2_STD_PAL,
+	}, {
+		/* FSC(Hz) = 4,433,618.75 Hz */
+		SD_STD_NTSC, 705268427, V4L2_STD_NTSC_443,
+	}, {
+		/* FSC(Hz) = 4,433,618.75 Hz */
+		SD_STD_PAL_M, 705268427, V4L2_STD_PAL_60,
+	},
+};
+
+static int adv7343_setstd(struct v4l2_subdev *sd, v4l2_std_id std)
+{
+	struct adv7343_state *state = to_state(sd);
+	struct adv7343_std_info *std_info;
+	int num_std;
+	char *fsc_ptr;
+	u8 reg, val;
+	int err = 0;
+	int i = 0;
+
+	std_info = (struct adv7343_std_info *)stdinfo;
+	num_std = ARRAY_SIZE(stdinfo);
+
+	for (i = 0; i < num_std; i++) {
+		if (std_info[i].stdid & std)
+			break;
+	}
+
+	if (i == num_std) {
+		v4l2_dbg(1, debug, sd,
+				"Invalid std or std is not supported: %llx\n",
+						(unsigned long long)std);
+		return -EINVAL;
+	}
+
+	/* Set the standard */
+	val = state->reg80 & (~(SD_STD_MASK));
+	val |= std_info[i].standard_val3;
+	err = adv7343_write(sd, ADV7343_SD_MODE_REG1, val);
+	if (err < 0)
+		goto setstd_exit;
+
+	state->reg80 = val;
+
+	/* Configure the input mode register */
+	val = state->reg01 & (~((u8) INPUT_MODE_MASK));
+	val |= SD_INPUT_MODE;
+	err = adv7343_write(sd, ADV7343_MODE_SELECT_REG, val);
+	if (err < 0)
+		goto setstd_exit;
+
+	state->reg01 = val;
+
+	/* Program the sub carrier frequency registers */
+	fsc_ptr = (unsigned char *)&std_info[i].fsc_val;
+	reg = ADV7343_FSC_REG0;
+	for (i = 0; i < 4; i++, reg++, fsc_ptr++) {
+		err = adv7343_write(sd, reg, *fsc_ptr);
+		if (err < 0)
+			goto setstd_exit;
+	}
+
+	val = state->reg80;
+
+	/* Filter settings */
+	if (std & (V4L2_STD_NTSC | V4L2_STD_NTSC_443))
+		val &= 0x03;
+	else if (std & ~V4L2_STD_SECAM)
+		val |= 0x04;
+
+	err = adv7343_write(sd, ADV7343_SD_MODE_REG1, val);
+	if (err < 0)
+		goto setstd_exit;
+
+	state->reg80 = val;
+
+setstd_exit:
+	if (err != 0)
+		v4l2_err(sd, "Error setting std, write failed\n");
+
+	return err;
+}
+
+static int adv7343_setoutput(struct v4l2_subdev *sd, u32 output_type)
+{
+	struct adv7343_state *state = to_state(sd);
+	unsigned char val;
+	int err = 0;
+
+	if (output_type > ADV7343_SVIDEO_ID) {
+		v4l2_dbg(1, debug, sd,
+			"Invalid output type or output type not supported:%d\n",
+								output_type);
+		return -EINVAL;
+	}
+
+	/* Enable Appropriate DAC */
+	val = state->reg00 & 0x03;
+
+	if (output_type == ADV7343_COMPOSITE_ID)
+		val |= ADV7343_COMPOSITE_POWER_VALUE;
+	else if (output_type == ADV7343_COMPONENT_ID)
+		val |= ADV7343_COMPONENT_POWER_VALUE;
+	else
+		val |= ADV7343_SVIDEO_POWER_VALUE;
+
+	err = adv7343_write(sd, ADV7343_POWER_MODE_REG, val);
+	if (err < 0)
+		goto setoutput_exit;
+
+	state->reg00 = val;
+
+	/* Enable YUV output */
+	val = state->reg02 | YUV_OUTPUT_SELECT;
+	err = adv7343_write(sd, ADV7343_MODE_REG0, val);
+	if (err < 0)
+		goto setoutput_exit;
+
+	state->reg02 = val;
+
+	/* configure SD DAC Output 2 and SD DAC Output 1 bit to zero */
+	val = state->reg82 & (SD_DAC_1_DI & SD_DAC_2_DI);
+	err = adv7343_write(sd, ADV7343_SD_MODE_REG2, val);
+	if (err < 0)
+		goto setoutput_exit;
+
+	state->reg82 = val;
+
+	/* configure ED/HD Color DAC Swap and ED/HD RGB Input Enable bit to
+	 * zero */
+	val = state->reg35 & (HD_RGB_INPUT_DI & HD_DAC_SWAP_DI);
+	err = adv7343_write(sd, ADV7343_HD_MODE_REG6, val);
+	if (err < 0)
+		goto setoutput_exit;
+
+	state->reg35 = val;
+
+setoutput_exit:
+	if (err != 0)
+		v4l2_err(sd, "Error setting output, write failed\n");
+
+	return err;
+}
+
+static int adv7343_log_status(struct v4l2_subdev *sd)
+{
+	struct adv7343_state *state = to_state(sd);
+
+	v4l2_info(sd, "Standard: %llx\n", (unsigned long long)state->std);
+	v4l2_info(sd, "Output: %s\n", (state->output == 0) ? "Composite" :
+			((state->output == 1) ? "Component" : "S-Video"));
+	return 0;
+}
+
+static int adv7343_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct v4l2_subdev *sd = to_sd(ctrl);
+
+	switch (ctrl->id) {
+	case V4L2_CID_BRIGHTNESS:
+		return adv7343_write(sd, ADV7343_SD_BRIGHTNESS_WSS,
+					ctrl->val);
+
+	case V4L2_CID_HUE:
+		return adv7343_write(sd, ADV7343_SD_HUE_REG, ctrl->val);
+
+	case V4L2_CID_GAIN:
+		return adv7343_write(sd, ADV7343_DAC2_OUTPUT_LEVEL, ctrl->val);
+	}
+	return -EINVAL;
+}
+
+static int adv7343_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_ADV7343, 0);
+}
+
+static const struct v4l2_ctrl_ops adv7343_ctrl_ops = {
+	.s_ctrl = adv7343_s_ctrl,
+};
+
+static const struct v4l2_subdev_core_ops adv7343_core_ops = {
+	.log_status = adv7343_log_status,
+	.g_chip_ident = adv7343_g_chip_ident,
+	.g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
+	.try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
+	.s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
+	.g_ctrl = v4l2_subdev_g_ctrl,
+	.s_ctrl = v4l2_subdev_s_ctrl,
+	.queryctrl = v4l2_subdev_queryctrl,
+	.querymenu = v4l2_subdev_querymenu,
+};
+
+static int adv7343_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std)
+{
+	struct adv7343_state *state = to_state(sd);
+	int err = 0;
+
+	if (state->std == std)
+		return 0;
+
+	err = adv7343_setstd(sd, std);
+	if (!err)
+		state->std = std;
+
+	return err;
+}
+
+static int adv7343_s_routing(struct v4l2_subdev *sd,
+		u32 input, u32 output, u32 config)
+{
+	struct adv7343_state *state = to_state(sd);
+	int err = 0;
+
+	if (state->output == output)
+		return 0;
+
+	err = adv7343_setoutput(sd, output);
+	if (!err)
+		state->output = output;
+
+	return err;
+}
+
+static const struct v4l2_subdev_video_ops adv7343_video_ops = {
+	.s_std_output	= adv7343_s_std_output,
+	.s_routing	= adv7343_s_routing,
+};
+
+static const struct v4l2_subdev_ops adv7343_ops = {
+	.core	= &adv7343_core_ops,
+	.video	= &adv7343_video_ops,
+};
+
+static int adv7343_initialize(struct v4l2_subdev *sd)
+{
+	struct adv7343_state *state = to_state(sd);
+	int err = 0;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(adv7343_init_reg_val); i += 2) {
+
+		err = adv7343_write(sd, adv7343_init_reg_val[i],
+					adv7343_init_reg_val[i+1]);
+		if (err) {
+			v4l2_err(sd, "Error initializing\n");
+			return err;
+		}
+	}
+
+	/* Configure for default video standard */
+	err = adv7343_setoutput(sd, state->output);
+	if (err < 0) {
+		v4l2_err(sd, "Error setting output during init\n");
+		return -EINVAL;
+	}
+
+	err = adv7343_setstd(sd, state->std);
+	if (err < 0) {
+		v4l2_err(sd, "Error setting std during init\n");
+		return -EINVAL;
+	}
+
+	return err;
+}
+
+static int adv7343_probe(struct i2c_client *client,
+				const struct i2c_device_id *id)
+{
+	struct adv7343_state *state;
+	int err;
+
+	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);
+
+	state = kzalloc(sizeof(struct adv7343_state), GFP_KERNEL);
+	if (state == NULL)
+		return -ENOMEM;
+
+	state->reg00	= 0x80;
+	state->reg01	= 0x00;
+	state->reg02	= 0x20;
+	state->reg35	= 0x00;
+	state->reg80	= ADV7343_SD_MODE_REG1_DEFAULT;
+	state->reg82	= ADV7343_SD_MODE_REG2_DEFAULT;
+
+	state->output = ADV7343_COMPOSITE_ID;
+	state->std = V4L2_STD_NTSC;
+
+	v4l2_i2c_subdev_init(&state->sd, client, &adv7343_ops);
+
+	v4l2_ctrl_handler_init(&state->hdl, 2);
+	v4l2_ctrl_new_std(&state->hdl, &adv7343_ctrl_ops,
+			V4L2_CID_BRIGHTNESS, ADV7343_BRIGHTNESS_MIN,
+					     ADV7343_BRIGHTNESS_MAX, 1,
+					     ADV7343_BRIGHTNESS_DEF);
+	v4l2_ctrl_new_std(&state->hdl, &adv7343_ctrl_ops,
+			V4L2_CID_HUE, ADV7343_HUE_MIN,
+				      ADV7343_HUE_MAX, 1,
+				      ADV7343_HUE_DEF);
+	v4l2_ctrl_new_std(&state->hdl, &adv7343_ctrl_ops,
+			V4L2_CID_GAIN, ADV7343_GAIN_MIN,
+				       ADV7343_GAIN_MAX, 1,
+				       ADV7343_GAIN_DEF);
+	state->sd.ctrl_handler = &state->hdl;
+	if (state->hdl.error) {
+		int err = state->hdl.error;
+
+		v4l2_ctrl_handler_free(&state->hdl);
+		kfree(state);
+		return err;
+	}
+	v4l2_ctrl_handler_setup(&state->hdl);
+
+	err = adv7343_initialize(&state->sd);
+	if (err) {
+		v4l2_ctrl_handler_free(&state->hdl);
+		kfree(state);
+	}
+	return err;
+}
+
+static int adv7343_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct adv7343_state *state = to_state(sd);
+
+	v4l2_device_unregister_subdev(sd);
+	v4l2_ctrl_handler_free(&state->hdl);
+	kfree(state);
+
+	return 0;
+}
+
+static const struct i2c_device_id adv7343_id[] = {
+	{"adv7343", 0},
+	{},
+};
+
+MODULE_DEVICE_TABLE(i2c, adv7343_id);
+
+static struct i2c_driver adv7343_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "adv7343",
+	},
+	.probe		= adv7343_probe,
+	.remove		= adv7343_remove,
+	.id_table	= adv7343_id,
+};
+
+module_i2c_driver(adv7343_driver);
diff --git a/drivers/media/i2c/adv7343_regs.h b/drivers/media/i2c/adv7343_regs.h
new file mode 100644
index 0000000..4466067
--- /dev/null
+++ b/drivers/media/i2c/adv7343_regs.h
@@ -0,0 +1,181 @@
+/*
+ * ADV7343 encoder related structure and register definitions
+ *
+ * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed .as is. WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef ADV7343_REG_H
+#define ADV7343_REGS_H
+
+struct adv7343_std_info {
+	u32 standard_val3;
+	u32 fsc_val;
+	v4l2_std_id stdid;
+};
+
+/* Register offset macros */
+#define ADV7343_POWER_MODE_REG		(0x00)
+#define ADV7343_MODE_SELECT_REG		(0x01)
+#define ADV7343_MODE_REG0		(0x02)
+
+#define ADV7343_DAC2_OUTPUT_LEVEL	(0x0b)
+
+#define ADV7343_SOFT_RESET		(0x17)
+
+#define ADV7343_HD_MODE_REG1		(0x30)
+#define ADV7343_HD_MODE_REG2		(0x31)
+#define ADV7343_HD_MODE_REG3		(0x32)
+#define ADV7343_HD_MODE_REG4		(0x33)
+#define ADV7343_HD_MODE_REG5		(0x34)
+#define ADV7343_HD_MODE_REG6		(0x35)
+
+#define ADV7343_HD_MODE_REG7		(0x39)
+
+#define ADV7343_SD_MODE_REG1		(0x80)
+#define ADV7343_SD_MODE_REG2		(0x82)
+#define ADV7343_SD_MODE_REG3		(0x83)
+#define ADV7343_SD_MODE_REG4		(0x84)
+#define ADV7343_SD_MODE_REG5		(0x86)
+#define ADV7343_SD_MODE_REG6		(0x87)
+#define ADV7343_SD_MODE_REG7		(0x88)
+#define ADV7343_SD_MODE_REG8		(0x89)
+
+#define ADV7343_FSC_REG0		(0x8C)
+#define ADV7343_FSC_REG1		(0x8D)
+#define ADV7343_FSC_REG2		(0x8E)
+#define ADV7343_FSC_REG3		(0x8F)
+
+#define ADV7343_SD_CGMS_WSS0		(0x99)
+
+#define ADV7343_SD_HUE_REG		(0xA0)
+#define ADV7343_SD_BRIGHTNESS_WSS	(0xA1)
+
+/* Default values for the registers */
+#define ADV7343_POWER_MODE_REG_DEFAULT		(0x10)
+#define ADV7343_HD_MODE_REG1_DEFAULT		(0x3C)	/* Changed Default
+							   720p EAVSAV code*/
+#define ADV7343_HD_MODE_REG2_DEFAULT		(0x01)	/* Changed Pixel data
+							   valid */
+#define ADV7343_HD_MODE_REG3_DEFAULT		(0x00)	/* Color delay 0 clks */
+#define ADV7343_HD_MODE_REG4_DEFAULT		(0xE8)	/* Changed */
+#define ADV7343_HD_MODE_REG5_DEFAULT		(0x08)
+#define ADV7343_HD_MODE_REG6_DEFAULT		(0x00)
+#define ADV7343_HD_MODE_REG7_DEFAULT		(0x00)
+#define ADV7343_SD_MODE_REG8_DEFAULT		(0x00)
+#define ADV7343_SOFT_RESET_DEFAULT		(0x02)
+#define ADV7343_COMPOSITE_POWER_VALUE		(0x80)
+#define ADV7343_COMPONENT_POWER_VALUE		(0x1C)
+#define ADV7343_SVIDEO_POWER_VALUE		(0x60)
+#define ADV7343_SD_HUE_REG_DEFAULT		(127)
+#define ADV7343_SD_BRIGHTNESS_WSS_DEFAULT	(0x03)
+
+#define ADV7343_SD_CGMS_WSS0_DEFAULT		(0x10)
+
+#define ADV7343_SD_MODE_REG1_DEFAULT		(0x00)
+#define ADV7343_SD_MODE_REG2_DEFAULT		(0xC9)
+#define ADV7343_SD_MODE_REG3_DEFAULT		(0x10)
+#define ADV7343_SD_MODE_REG4_DEFAULT		(0x01)
+#define ADV7343_SD_MODE_REG5_DEFAULT		(0x02)
+#define ADV7343_SD_MODE_REG6_DEFAULT		(0x0C)
+#define ADV7343_SD_MODE_REG7_DEFAULT		(0x04)
+#define ADV7343_SD_MODE_REG8_DEFAULT		(0x00)
+
+/* Bit masks for Mode Select Register */
+#define INPUT_MODE_MASK			(0x70)
+#define SD_INPUT_MODE			(0x00)
+#define HD_720P_INPUT_MODE		(0x10)
+#define HD_1080I_INPUT_MODE		(0x10)
+
+/* Bit masks for Mode Register 0 */
+#define TEST_PATTERN_BLACK_BAR_EN	(0x04)
+#define YUV_OUTPUT_SELECT		(0x20)
+#define RGB_OUTPUT_SELECT		(0xDF)
+
+/* Bit masks for DAC output levels */
+#define DAC_OUTPUT_LEVEL_MASK		(0xFF)
+
+/* Bit masks for soft reset register */
+#define SOFT_RESET			(0x02)
+
+/* Bit masks for HD Mode Register 1 */
+#define OUTPUT_STD_MASK		(0x03)
+#define OUTPUT_STD_SHIFT	(0)
+#define OUTPUT_STD_EIA0_2	(0x00)
+#define OUTPUT_STD_EIA0_1	(0x01)
+#define OUTPUT_STD_FULL		(0x02)
+#define EMBEDDED_SYNC		(0x04)
+#define EXTERNAL_SYNC		(0xFB)
+#define STD_MODE_SHIFT		(3)
+#define STD_MODE_MASK		(0x1F)
+#define STD_MODE_720P		(0x05)
+#define STD_MODE_720P_25	(0x08)
+#define STD_MODE_720P_30	(0x07)
+#define STD_MODE_720P_50	(0x06)
+#define STD_MODE_1080I		(0x0D)
+#define STD_MODE_1080I_25fps	(0x0E)
+#define STD_MODE_1080P_24	(0x12)
+#define STD_MODE_1080P_25	(0x10)
+#define STD_MODE_1080P_30	(0x0F)
+#define STD_MODE_525P		(0x00)
+#define STD_MODE_625P		(0x03)
+
+/* Bit masks for SD Mode Register 1 */
+#define SD_STD_MASK		(0x03)
+#define SD_STD_NTSC		(0x00)
+#define SD_STD_PAL_BDGHI	(0x01)
+#define SD_STD_PAL_M		(0x02)
+#define SD_STD_PAL_N		(0x03)
+#define SD_LUMA_FLTR_MASK	(0x7)
+#define SD_LUMA_FLTR_SHIFT	(0x2)
+#define SD_CHROMA_FLTR_MASK	(0x7)
+#define SD_CHROMA_FLTR_SHIFT	(0x5)
+
+/* Bit masks for SD Mode Register 2 */
+#define SD_PBPR_SSAF_EN		(0x01)
+#define SD_PBPR_SSAF_DI		(0xFE)
+#define SD_DAC_1_DI		(0xFD)
+#define SD_DAC_2_DI		(0xFB)
+#define SD_PEDESTAL_EN		(0x08)
+#define SD_PEDESTAL_DI		(0xF7)
+#define SD_SQUARE_PIXEL_EN	(0x10)
+#define SD_SQUARE_PIXEL_DI	(0xEF)
+#define SD_PIXEL_DATA_VALID	(0x40)
+#define SD_ACTIVE_EDGE_EN	(0x80)
+#define SD_ACTIVE_EDGE_DI	(0x7F)
+
+/* Bit masks for HD Mode Register 6 */
+#define HD_RGB_INPUT_EN		(0x02)
+#define HD_RGB_INPUT_DI		(0xFD)
+#define HD_PBPR_SYNC_EN		(0x04)
+#define HD_PBPR_SYNC_DI		(0xFB)
+#define HD_DAC_SWAP_EN		(0x08)
+#define HD_DAC_SWAP_DI		(0xF7)
+#define HD_GAMMA_CURVE_A	(0xEF)
+#define HD_GAMMA_CURVE_B	(0x10)
+#define HD_GAMMA_EN		(0x20)
+#define HD_GAMMA_DI		(0xDF)
+#define HD_ADPT_FLTR_MODEB	(0x40)
+#define HD_ADPT_FLTR_MODEA	(0xBF)
+#define HD_ADPT_FLTR_EN		(0x80)
+#define HD_ADPT_FLTR_DI		(0x7F)
+
+#define ADV7343_BRIGHTNESS_MAX	(127)
+#define ADV7343_BRIGHTNESS_MIN	(0)
+#define ADV7343_BRIGHTNESS_DEF	(3)
+#define ADV7343_HUE_MAX		(255)
+#define ADV7343_HUE_MIN		(0)
+#define ADV7343_HUE_DEF		(127)
+#define ADV7343_GAIN_MAX	(64)
+#define ADV7343_GAIN_MIN	(-64)
+#define ADV7343_GAIN_DEF	(0)
+
+#endif
diff --git a/drivers/media/i2c/adv7393.c b/drivers/media/i2c/adv7393.c
new file mode 100644
index 0000000..3dc6098
--- /dev/null
+++ b/drivers/media/i2c/adv7393.c
@@ -0,0 +1,487 @@
+/*
+ * adv7393 - ADV7393 Video Encoder Driver
+ *
+ * The encoder hardware does not support SECAM.
+ *
+ * Copyright (C) 2010-2012 ADVANSEE - http://www.advansee.com/
+ * Benoît Thébaudeau <benoit.thebaudeau@advansee.com>
+ *
+ * Based on ADV7343 driver,
+ *
+ * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed .as is. WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/ctype.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/videodev2.h>
+#include <linux/uaccess.h>
+
+#include <media/adv7393.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-ctrls.h>
+
+#include "adv7393_regs.h"
+
+MODULE_DESCRIPTION("ADV7393 video encoder driver");
+MODULE_LICENSE("GPL");
+
+static bool debug;
+module_param(debug, bool, 0644);
+MODULE_PARM_DESC(debug, "Debug level 0-1");
+
+struct adv7393_state {
+	struct v4l2_subdev sd;
+	struct v4l2_ctrl_handler hdl;
+	u8 reg00;
+	u8 reg01;
+	u8 reg02;
+	u8 reg35;
+	u8 reg80;
+	u8 reg82;
+	u32 output;
+	v4l2_std_id std;
+};
+
+static inline struct adv7393_state *to_state(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct adv7393_state, sd);
+}
+
+static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
+{
+	return &container_of(ctrl->handler, struct adv7393_state, hdl)->sd;
+}
+
+static inline int adv7393_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 const u8 adv7393_init_reg_val[] = {
+	ADV7393_SOFT_RESET, ADV7393_SOFT_RESET_DEFAULT,
+	ADV7393_POWER_MODE_REG, ADV7393_POWER_MODE_REG_DEFAULT,
+
+	ADV7393_HD_MODE_REG1, ADV7393_HD_MODE_REG1_DEFAULT,
+	ADV7393_HD_MODE_REG2, ADV7393_HD_MODE_REG2_DEFAULT,
+	ADV7393_HD_MODE_REG3, ADV7393_HD_MODE_REG3_DEFAULT,
+	ADV7393_HD_MODE_REG4, ADV7393_HD_MODE_REG4_DEFAULT,
+	ADV7393_HD_MODE_REG5, ADV7393_HD_MODE_REG5_DEFAULT,
+	ADV7393_HD_MODE_REG6, ADV7393_HD_MODE_REG6_DEFAULT,
+	ADV7393_HD_MODE_REG7, ADV7393_HD_MODE_REG7_DEFAULT,
+
+	ADV7393_SD_MODE_REG1, ADV7393_SD_MODE_REG1_DEFAULT,
+	ADV7393_SD_MODE_REG2, ADV7393_SD_MODE_REG2_DEFAULT,
+	ADV7393_SD_MODE_REG3, ADV7393_SD_MODE_REG3_DEFAULT,
+	ADV7393_SD_MODE_REG4, ADV7393_SD_MODE_REG4_DEFAULT,
+	ADV7393_SD_MODE_REG5, ADV7393_SD_MODE_REG5_DEFAULT,
+	ADV7393_SD_MODE_REG6, ADV7393_SD_MODE_REG6_DEFAULT,
+	ADV7393_SD_MODE_REG7, ADV7393_SD_MODE_REG7_DEFAULT,
+	ADV7393_SD_MODE_REG8, ADV7393_SD_MODE_REG8_DEFAULT,
+
+	ADV7393_SD_TIMING_REG0, ADV7393_SD_TIMING_REG0_DEFAULT,
+
+	ADV7393_SD_HUE_ADJUST, ADV7393_SD_HUE_ADJUST_DEFAULT,
+	ADV7393_SD_CGMS_WSS0, ADV7393_SD_CGMS_WSS0_DEFAULT,
+	ADV7393_SD_BRIGHTNESS_WSS, ADV7393_SD_BRIGHTNESS_WSS_DEFAULT,
+};
+
+/*
+ * 			    2^32
+ * FSC(reg) =  FSC (HZ) * --------
+ *			  27000000
+ */
+static const struct adv7393_std_info stdinfo[] = {
+	{
+		/* FSC(Hz) = 4,433,618.75 Hz */
+		SD_STD_NTSC, 705268427, V4L2_STD_NTSC_443,
+	}, {
+		/* FSC(Hz) = 3,579,545.45 Hz */
+		SD_STD_NTSC, 569408542, V4L2_STD_NTSC,
+	}, {
+		/* FSC(Hz) = 3,575,611.00 Hz */
+		SD_STD_PAL_M, 568782678, V4L2_STD_PAL_M,
+	}, {
+		/* FSC(Hz) = 3,582,056.00 Hz */
+		SD_STD_PAL_N, 569807903, V4L2_STD_PAL_Nc,
+	}, {
+		/* FSC(Hz) = 4,433,618.75 Hz */
+		SD_STD_PAL_N, 705268427, V4L2_STD_PAL_N,
+	}, {
+		/* FSC(Hz) = 4,433,618.75 Hz */
+		SD_STD_PAL_M, 705268427, V4L2_STD_PAL_60,
+	}, {
+		/* FSC(Hz) = 4,433,618.75 Hz */
+		SD_STD_PAL_BDGHI, 705268427, V4L2_STD_PAL,
+	},
+};
+
+static int adv7393_setstd(struct v4l2_subdev *sd, v4l2_std_id std)
+{
+	struct adv7393_state *state = to_state(sd);
+	const struct adv7393_std_info *std_info;
+	int num_std;
+	u8 reg;
+	u32 val;
+	int err = 0;
+	int i;
+
+	num_std = ARRAY_SIZE(stdinfo);
+
+	for (i = 0; i < num_std; i++) {
+		if (stdinfo[i].stdid & std)
+			break;
+	}
+
+	if (i == num_std) {
+		v4l2_dbg(1, debug, sd,
+				"Invalid std or std is not supported: %llx\n",
+						(unsigned long long)std);
+		return -EINVAL;
+	}
+
+	std_info = &stdinfo[i];
+
+	/* Set the standard */
+	val = state->reg80 & ~SD_STD_MASK;
+	val |= std_info->standard_val3;
+	err = adv7393_write(sd, ADV7393_SD_MODE_REG1, val);
+	if (err < 0)
+		goto setstd_exit;
+
+	state->reg80 = val;
+
+	/* Configure the input mode register */
+	val = state->reg01 & ~INPUT_MODE_MASK;
+	val |= SD_INPUT_MODE;
+	err = adv7393_write(sd, ADV7393_MODE_SELECT_REG, val);
+	if (err < 0)
+		goto setstd_exit;
+
+	state->reg01 = val;
+
+	/* Program the sub carrier frequency registers */
+	val = std_info->fsc_val;
+	for (reg = ADV7393_FSC_REG0; reg <= ADV7393_FSC_REG3; reg++) {
+		err = adv7393_write(sd, reg, val);
+		if (err < 0)
+			goto setstd_exit;
+		val >>= 8;
+	}
+
+	val = state->reg82;
+
+	/* Pedestal settings */
+	if (std & (V4L2_STD_NTSC | V4L2_STD_NTSC_443))
+		val |= SD_PEDESTAL_EN;
+	else
+		val &= SD_PEDESTAL_DI;
+
+	err = adv7393_write(sd, ADV7393_SD_MODE_REG2, val);
+	if (err < 0)
+		goto setstd_exit;
+
+	state->reg82 = val;
+
+setstd_exit:
+	if (err != 0)
+		v4l2_err(sd, "Error setting std, write failed\n");
+
+	return err;
+}
+
+static int adv7393_setoutput(struct v4l2_subdev *sd, u32 output_type)
+{
+	struct adv7393_state *state = to_state(sd);
+	u8 val;
+	int err = 0;
+
+	if (output_type > ADV7393_SVIDEO_ID) {
+		v4l2_dbg(1, debug, sd,
+			"Invalid output type or output type not supported:%d\n",
+								output_type);
+		return -EINVAL;
+	}
+
+	/* Enable Appropriate DAC */
+	val = state->reg00 & 0x03;
+
+	if (output_type == ADV7393_COMPOSITE_ID)
+		val |= ADV7393_COMPOSITE_POWER_VALUE;
+	else if (output_type == ADV7393_COMPONENT_ID)
+		val |= ADV7393_COMPONENT_POWER_VALUE;
+	else
+		val |= ADV7393_SVIDEO_POWER_VALUE;
+
+	err = adv7393_write(sd, ADV7393_POWER_MODE_REG, val);
+	if (err < 0)
+		goto setoutput_exit;
+
+	state->reg00 = val;
+
+	/* Enable YUV output */
+	val = state->reg02 | YUV_OUTPUT_SELECT;
+	err = adv7393_write(sd, ADV7393_MODE_REG0, val);
+	if (err < 0)
+		goto setoutput_exit;
+
+	state->reg02 = val;
+
+	/* configure SD DAC Output 1 bit */
+	val = state->reg82;
+	if (output_type == ADV7393_COMPONENT_ID)
+		val &= SD_DAC_OUT1_DI;
+	else
+		val |= SD_DAC_OUT1_EN;
+	err = adv7393_write(sd, ADV7393_SD_MODE_REG2, val);
+	if (err < 0)
+		goto setoutput_exit;
+
+	state->reg82 = val;
+
+	/* configure ED/HD Color DAC Swap bit to zero */
+	val = state->reg35 & HD_DAC_SWAP_DI;
+	err = adv7393_write(sd, ADV7393_HD_MODE_REG6, val);
+	if (err < 0)
+		goto setoutput_exit;
+
+	state->reg35 = val;
+
+setoutput_exit:
+	if (err != 0)
+		v4l2_err(sd, "Error setting output, write failed\n");
+
+	return err;
+}
+
+static int adv7393_log_status(struct v4l2_subdev *sd)
+{
+	struct adv7393_state *state = to_state(sd);
+
+	v4l2_info(sd, "Standard: %llx\n", (unsigned long long)state->std);
+	v4l2_info(sd, "Output: %s\n", (state->output == 0) ? "Composite" :
+			((state->output == 1) ? "Component" : "S-Video"));
+	return 0;
+}
+
+static int adv7393_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct v4l2_subdev *sd = to_sd(ctrl);
+
+	switch (ctrl->id) {
+	case V4L2_CID_BRIGHTNESS:
+		return adv7393_write(sd, ADV7393_SD_BRIGHTNESS_WSS,
+					ctrl->val & SD_BRIGHTNESS_VALUE_MASK);
+
+	case V4L2_CID_HUE:
+		return adv7393_write(sd, ADV7393_SD_HUE_ADJUST,
+					ctrl->val - ADV7393_HUE_MIN);
+
+	case V4L2_CID_GAIN:
+		return adv7393_write(sd, ADV7393_DAC123_OUTPUT_LEVEL,
+					ctrl->val);
+	}
+	return -EINVAL;
+}
+
+static int adv7393_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_ADV7393, 0);
+}
+
+static const struct v4l2_ctrl_ops adv7393_ctrl_ops = {
+	.s_ctrl = adv7393_s_ctrl,
+};
+
+static const struct v4l2_subdev_core_ops adv7393_core_ops = {
+	.log_status = adv7393_log_status,
+	.g_chip_ident = adv7393_g_chip_ident,
+	.g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
+	.try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
+	.s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
+	.g_ctrl = v4l2_subdev_g_ctrl,
+	.s_ctrl = v4l2_subdev_s_ctrl,
+	.queryctrl = v4l2_subdev_queryctrl,
+	.querymenu = v4l2_subdev_querymenu,
+};
+
+static int adv7393_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std)
+{
+	struct adv7393_state *state = to_state(sd);
+	int err = 0;
+
+	if (state->std == std)
+		return 0;
+
+	err = adv7393_setstd(sd, std);
+	if (!err)
+		state->std = std;
+
+	return err;
+}
+
+static int adv7393_s_routing(struct v4l2_subdev *sd,
+		u32 input, u32 output, u32 config)
+{
+	struct adv7393_state *state = to_state(sd);
+	int err = 0;
+
+	if (state->output == output)
+		return 0;
+
+	err = adv7393_setoutput(sd, output);
+	if (!err)
+		state->output = output;
+
+	return err;
+}
+
+static const struct v4l2_subdev_video_ops adv7393_video_ops = {
+	.s_std_output	= adv7393_s_std_output,
+	.s_routing	= adv7393_s_routing,
+};
+
+static const struct v4l2_subdev_ops adv7393_ops = {
+	.core	= &adv7393_core_ops,
+	.video	= &adv7393_video_ops,
+};
+
+static int adv7393_initialize(struct v4l2_subdev *sd)
+{
+	struct adv7393_state *state = to_state(sd);
+	int err = 0;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(adv7393_init_reg_val); i += 2) {
+
+		err = adv7393_write(sd, adv7393_init_reg_val[i],
+					adv7393_init_reg_val[i+1]);
+		if (err) {
+			v4l2_err(sd, "Error initializing\n");
+			return err;
+		}
+	}
+
+	/* Configure for default video standard */
+	err = adv7393_setoutput(sd, state->output);
+	if (err < 0) {
+		v4l2_err(sd, "Error setting output during init\n");
+		return -EINVAL;
+	}
+
+	err = adv7393_setstd(sd, state->std);
+	if (err < 0) {
+		v4l2_err(sd, "Error setting std during init\n");
+		return -EINVAL;
+	}
+
+	return err;
+}
+
+static int adv7393_probe(struct i2c_client *client,
+				const struct i2c_device_id *id)
+{
+	struct adv7393_state *state;
+	int err;
+
+	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);
+
+	state = kzalloc(sizeof(struct adv7393_state), GFP_KERNEL);
+	if (state == NULL)
+		return -ENOMEM;
+
+	state->reg00	= ADV7393_POWER_MODE_REG_DEFAULT;
+	state->reg01	= 0x00;
+	state->reg02	= 0x20;
+	state->reg35	= ADV7393_HD_MODE_REG6_DEFAULT;
+	state->reg80	= ADV7393_SD_MODE_REG1_DEFAULT;
+	state->reg82	= ADV7393_SD_MODE_REG2_DEFAULT;
+
+	state->output = ADV7393_COMPOSITE_ID;
+	state->std = V4L2_STD_NTSC;
+
+	v4l2_i2c_subdev_init(&state->sd, client, &adv7393_ops);
+
+	v4l2_ctrl_handler_init(&state->hdl, 3);
+	v4l2_ctrl_new_std(&state->hdl, &adv7393_ctrl_ops,
+			V4L2_CID_BRIGHTNESS, ADV7393_BRIGHTNESS_MIN,
+					     ADV7393_BRIGHTNESS_MAX, 1,
+					     ADV7393_BRIGHTNESS_DEF);
+	v4l2_ctrl_new_std(&state->hdl, &adv7393_ctrl_ops,
+			V4L2_CID_HUE, ADV7393_HUE_MIN,
+				      ADV7393_HUE_MAX, 1,
+				      ADV7393_HUE_DEF);
+	v4l2_ctrl_new_std(&state->hdl, &adv7393_ctrl_ops,
+			V4L2_CID_GAIN, ADV7393_GAIN_MIN,
+				       ADV7393_GAIN_MAX, 1,
+				       ADV7393_GAIN_DEF);
+	state->sd.ctrl_handler = &state->hdl;
+	if (state->hdl.error) {
+		int err = state->hdl.error;
+
+		v4l2_ctrl_handler_free(&state->hdl);
+		kfree(state);
+		return err;
+	}
+	v4l2_ctrl_handler_setup(&state->hdl);
+
+	err = adv7393_initialize(&state->sd);
+	if (err) {
+		v4l2_ctrl_handler_free(&state->hdl);
+		kfree(state);
+	}
+	return err;
+}
+
+static int adv7393_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct adv7393_state *state = to_state(sd);
+
+	v4l2_device_unregister_subdev(sd);
+	v4l2_ctrl_handler_free(&state->hdl);
+	kfree(state);
+
+	return 0;
+}
+
+static const struct i2c_device_id adv7393_id[] = {
+	{"adv7393", 0},
+	{},
+};
+MODULE_DEVICE_TABLE(i2c, adv7393_id);
+
+static struct i2c_driver adv7393_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "adv7393",
+	},
+	.probe		= adv7393_probe,
+	.remove		= adv7393_remove,
+	.id_table	= adv7393_id,
+};
+module_i2c_driver(adv7393_driver);
diff --git a/drivers/media/i2c/adv7393_regs.h b/drivers/media/i2c/adv7393_regs.h
new file mode 100644
index 0000000..7896833
--- /dev/null
+++ b/drivers/media/i2c/adv7393_regs.h
@@ -0,0 +1,188 @@
+/*
+ * ADV7393 encoder related structure and register definitions
+ *
+ * Copyright (C) 2010-2012 ADVANSEE - http://www.advansee.com/
+ * Benoît Thébaudeau <benoit.thebaudeau@advansee.com>
+ *
+ * Based on ADV7343 driver,
+ *
+ * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed .as is. WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef ADV7393_REGS_H
+#define ADV7393_REGS_H
+
+struct adv7393_std_info {
+	u32 standard_val3;
+	u32 fsc_val;
+	v4l2_std_id stdid;
+};
+
+/* Register offset macros */
+#define ADV7393_POWER_MODE_REG		(0x00)
+#define ADV7393_MODE_SELECT_REG		(0x01)
+#define ADV7393_MODE_REG0		(0x02)
+
+#define ADV7393_DAC123_OUTPUT_LEVEL	(0x0B)
+
+#define ADV7393_SOFT_RESET		(0x17)
+
+#define ADV7393_HD_MODE_REG1		(0x30)
+#define ADV7393_HD_MODE_REG2		(0x31)
+#define ADV7393_HD_MODE_REG3		(0x32)
+#define ADV7393_HD_MODE_REG4		(0x33)
+#define ADV7393_HD_MODE_REG5		(0x34)
+#define ADV7393_HD_MODE_REG6		(0x35)
+
+#define ADV7393_HD_MODE_REG7		(0x39)
+
+#define ADV7393_SD_MODE_REG1		(0x80)
+#define ADV7393_SD_MODE_REG2		(0x82)
+#define ADV7393_SD_MODE_REG3		(0x83)
+#define ADV7393_SD_MODE_REG4		(0x84)
+#define ADV7393_SD_MODE_REG5		(0x86)
+#define ADV7393_SD_MODE_REG6		(0x87)
+#define ADV7393_SD_MODE_REG7		(0x88)
+#define ADV7393_SD_MODE_REG8		(0x89)
+
+#define ADV7393_SD_TIMING_REG0		(0x8A)
+
+#define ADV7393_FSC_REG0		(0x8C)
+#define ADV7393_FSC_REG1		(0x8D)
+#define ADV7393_FSC_REG2		(0x8E)
+#define ADV7393_FSC_REG3		(0x8F)
+
+#define ADV7393_SD_CGMS_WSS0		(0x99)
+
+#define ADV7393_SD_HUE_ADJUST		(0xA0)
+#define ADV7393_SD_BRIGHTNESS_WSS	(0xA1)
+
+/* Default values for the registers */
+#define ADV7393_POWER_MODE_REG_DEFAULT		(0x10)
+#define ADV7393_HD_MODE_REG1_DEFAULT		(0x3C)	/* Changed Default
+							   720p EAV/SAV code*/
+#define ADV7393_HD_MODE_REG2_DEFAULT		(0x01)	/* Changed Pixel data
+							   valid */
+#define ADV7393_HD_MODE_REG3_DEFAULT		(0x00)	/* Color delay 0 clks */
+#define ADV7393_HD_MODE_REG4_DEFAULT		(0xEC)	/* Changed */
+#define ADV7393_HD_MODE_REG5_DEFAULT		(0x08)
+#define ADV7393_HD_MODE_REG6_DEFAULT		(0x00)
+#define ADV7393_HD_MODE_REG7_DEFAULT		(0x00)
+#define ADV7393_SOFT_RESET_DEFAULT		(0x02)
+#define ADV7393_COMPOSITE_POWER_VALUE		(0x10)
+#define ADV7393_COMPONENT_POWER_VALUE		(0x1C)
+#define ADV7393_SVIDEO_POWER_VALUE		(0x0C)
+#define ADV7393_SD_HUE_ADJUST_DEFAULT		(0x80)
+#define ADV7393_SD_BRIGHTNESS_WSS_DEFAULT	(0x00)
+
+#define ADV7393_SD_CGMS_WSS0_DEFAULT		(0x10)
+
+#define ADV7393_SD_MODE_REG1_DEFAULT		(0x10)
+#define ADV7393_SD_MODE_REG2_DEFAULT		(0xC9)
+#define ADV7393_SD_MODE_REG3_DEFAULT		(0x00)
+#define ADV7393_SD_MODE_REG4_DEFAULT		(0x00)
+#define ADV7393_SD_MODE_REG5_DEFAULT		(0x02)
+#define ADV7393_SD_MODE_REG6_DEFAULT		(0x8C)
+#define ADV7393_SD_MODE_REG7_DEFAULT		(0x14)
+#define ADV7393_SD_MODE_REG8_DEFAULT		(0x00)
+
+#define ADV7393_SD_TIMING_REG0_DEFAULT		(0x0C)
+
+/* Bit masks for Mode Select Register */
+#define INPUT_MODE_MASK			(0x70)
+#define SD_INPUT_MODE			(0x00)
+#define HD_720P_INPUT_MODE		(0x10)
+#define HD_1080I_INPUT_MODE		(0x10)
+
+/* Bit masks for Mode Register 0 */
+#define TEST_PATTERN_BLACK_BAR_EN	(0x04)
+#define YUV_OUTPUT_SELECT		(0x20)
+#define RGB_OUTPUT_SELECT		(0xDF)
+
+/* Bit masks for SD brightness/WSS */
+#define SD_BRIGHTNESS_VALUE_MASK	(0x7F)
+#define SD_BLANK_WSS_DATA_MASK		(0x80)
+
+/* Bit masks for soft reset register */
+#define SOFT_RESET			(0x02)
+
+/* Bit masks for HD Mode Register 1 */
+#define OUTPUT_STD_MASK		(0x03)
+#define OUTPUT_STD_SHIFT	(0)
+#define OUTPUT_STD_EIA0_2	(0x00)
+#define OUTPUT_STD_EIA0_1	(0x01)
+#define OUTPUT_STD_FULL		(0x02)
+#define EMBEDDED_SYNC		(0x04)
+#define EXTERNAL_SYNC		(0xFB)
+#define STD_MODE_MASK		(0x1F)
+#define STD_MODE_SHIFT		(3)
+#define STD_MODE_720P		(0x05)
+#define STD_MODE_720P_25	(0x08)
+#define STD_MODE_720P_30	(0x07)
+#define STD_MODE_720P_50	(0x06)
+#define STD_MODE_1080I		(0x0D)
+#define STD_MODE_1080I_25	(0x0E)
+#define STD_MODE_1080P_24	(0x11)
+#define STD_MODE_1080P_25	(0x10)
+#define STD_MODE_1080P_30	(0x0F)
+#define STD_MODE_525P		(0x00)
+#define STD_MODE_625P		(0x03)
+
+/* Bit masks for SD Mode Register 1 */
+#define SD_STD_MASK		(0x03)
+#define SD_STD_NTSC		(0x00)
+#define SD_STD_PAL_BDGHI	(0x01)
+#define SD_STD_PAL_M		(0x02)
+#define SD_STD_PAL_N		(0x03)
+#define SD_LUMA_FLTR_MASK	(0x07)
+#define SD_LUMA_FLTR_SHIFT	(2)
+#define SD_CHROMA_FLTR_MASK	(0x07)
+#define SD_CHROMA_FLTR_SHIFT	(5)
+
+/* Bit masks for SD Mode Register 2 */
+#define SD_PRPB_SSAF_EN		(0x01)
+#define SD_PRPB_SSAF_DI		(0xFE)
+#define SD_DAC_OUT1_EN		(0x02)
+#define SD_DAC_OUT1_DI		(0xFD)
+#define SD_PEDESTAL_EN		(0x08)
+#define SD_PEDESTAL_DI		(0xF7)
+#define SD_SQUARE_PIXEL_EN	(0x10)
+#define SD_SQUARE_PIXEL_DI	(0xEF)
+#define SD_PIXEL_DATA_VALID	(0x40)
+#define SD_ACTIVE_EDGE_EN	(0x80)
+#define SD_ACTIVE_EDGE_DI	(0x7F)
+
+/* Bit masks for HD Mode Register 6 */
+#define HD_PRPB_SYNC_EN		(0x04)
+#define HD_PRPB_SYNC_DI		(0xFB)
+#define HD_DAC_SWAP_EN		(0x08)
+#define HD_DAC_SWAP_DI		(0xF7)
+#define HD_GAMMA_CURVE_A	(0xEF)
+#define HD_GAMMA_CURVE_B	(0x10)
+#define HD_GAMMA_EN		(0x20)
+#define HD_GAMMA_DI		(0xDF)
+#define HD_ADPT_FLTR_MODEA	(0xBF)
+#define HD_ADPT_FLTR_MODEB	(0x40)
+#define HD_ADPT_FLTR_EN		(0x80)
+#define HD_ADPT_FLTR_DI		(0x7F)
+
+#define ADV7393_BRIGHTNESS_MAX	(63)
+#define ADV7393_BRIGHTNESS_MIN	(-64)
+#define ADV7393_BRIGHTNESS_DEF	(0)
+#define ADV7393_HUE_MAX		(127)
+#define ADV7393_HUE_MIN		(-128)
+#define ADV7393_HUE_DEF		(0)
+#define ADV7393_GAIN_MAX	(64)
+#define ADV7393_GAIN_MIN	(-64)
+#define ADV7393_GAIN_DEF	(0)
+
+#endif
diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
new file mode 100644
index 0000000..109bc9b
--- /dev/null
+++ b/drivers/media/i2c/adv7604.c
@@ -0,0 +1,1959 @@
+/*
+ * adv7604 - Analog Devices ADV7604 video decoder driver
+ *
+ * Copyright 2012 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/*
+ * References (c = chapter, p = page):
+ * REF_01 - Analog devices, ADV7604, Register Settings Recommendations,
+ *		Revision 2.5, June 2010
+ * REF_02 - Analog devices, Register map documentation, Documentation of
+ *		the register maps, Software manual, Rev. F, June 2010
+ * REF_03 - Analog devices, ADV7604, Hardware Manual, Rev. F, August 2010
+ */
+
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/videodev2.h>
+#include <linux/workqueue.h>
+#include <linux/v4l2-dv-timings.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/adv7604.h>
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "debug level (0-2)");
+
+MODULE_DESCRIPTION("Analog Devices ADV7604 video decoder driver");
+MODULE_AUTHOR("Hans Verkuil <hans.verkuil@cisco.com>");
+MODULE_AUTHOR("Mats Randgaard <mats.randgaard@cisco.com>");
+MODULE_LICENSE("GPL");
+
+/* ADV7604 system clock frequency */
+#define ADV7604_fsc (28636360)
+
+#define DIGITAL_INPUT ((state->prim_mode == ADV7604_PRIM_MODE_HDMI_COMP) || \
+			(state->prim_mode == ADV7604_PRIM_MODE_HDMI_GR))
+
+/*
+ **********************************************************************
+ *
+ *  Arrays with configuration parameters for the ADV7604
+ *
+ **********************************************************************
+ */
+struct adv7604_state {
+	struct adv7604_platform_data pdata;
+	struct v4l2_subdev sd;
+	struct media_pad pad;
+	struct v4l2_ctrl_handler hdl;
+	enum adv7604_prim_mode prim_mode;
+	struct v4l2_dv_timings timings;
+	u8 edid[256];
+	unsigned edid_blocks;
+	struct v4l2_fract aspect_ratio;
+	u32 rgb_quantization_range;
+	struct workqueue_struct *work_queues;
+	struct delayed_work delayed_work_enable_hotplug;
+	bool connector_hdmi;
+
+	/* i2c clients */
+	struct i2c_client *i2c_avlink;
+	struct i2c_client *i2c_cec;
+	struct i2c_client *i2c_infoframe;
+	struct i2c_client *i2c_esdp;
+	struct i2c_client *i2c_dpp;
+	struct i2c_client *i2c_afe;
+	struct i2c_client *i2c_repeater;
+	struct i2c_client *i2c_edid;
+	struct i2c_client *i2c_hdmi;
+	struct i2c_client *i2c_test;
+	struct i2c_client *i2c_cp;
+	struct i2c_client *i2c_vdp;
+
+	/* controls */
+	struct v4l2_ctrl *detect_tx_5v_ctrl;
+	struct v4l2_ctrl *analog_sampling_phase_ctrl;
+	struct v4l2_ctrl *free_run_color_manual_ctrl;
+	struct v4l2_ctrl *free_run_color_ctrl;
+	struct v4l2_ctrl *rgb_quantization_range_ctrl;
+};
+
+/* Supported CEA and DMT timings */
+static const struct v4l2_dv_timings adv7604_timings[] = {
+	V4L2_DV_BT_CEA_720X480P59_94,
+	V4L2_DV_BT_CEA_720X576P50,
+	V4L2_DV_BT_CEA_1280X720P24,
+	V4L2_DV_BT_CEA_1280X720P25,
+	V4L2_DV_BT_CEA_1280X720P30,
+	V4L2_DV_BT_CEA_1280X720P50,
+	V4L2_DV_BT_CEA_1280X720P60,
+	V4L2_DV_BT_CEA_1920X1080P24,
+	V4L2_DV_BT_CEA_1920X1080P25,
+	V4L2_DV_BT_CEA_1920X1080P30,
+	V4L2_DV_BT_CEA_1920X1080P50,
+	V4L2_DV_BT_CEA_1920X1080P60,
+
+	V4L2_DV_BT_DMT_640X350P85,
+	V4L2_DV_BT_DMT_640X400P85,
+	V4L2_DV_BT_DMT_720X400P85,
+	V4L2_DV_BT_DMT_640X480P60,
+	V4L2_DV_BT_DMT_640X480P72,
+	V4L2_DV_BT_DMT_640X480P75,
+	V4L2_DV_BT_DMT_640X480P85,
+	V4L2_DV_BT_DMT_800X600P56,
+	V4L2_DV_BT_DMT_800X600P60,
+	V4L2_DV_BT_DMT_800X600P72,
+	V4L2_DV_BT_DMT_800X600P75,
+	V4L2_DV_BT_DMT_800X600P85,
+	V4L2_DV_BT_DMT_848X480P60,
+	V4L2_DV_BT_DMT_1024X768P60,
+	V4L2_DV_BT_DMT_1024X768P70,
+	V4L2_DV_BT_DMT_1024X768P75,
+	V4L2_DV_BT_DMT_1024X768P85,
+	V4L2_DV_BT_DMT_1152X864P75,
+	V4L2_DV_BT_DMT_1280X768P60_RB,
+	V4L2_DV_BT_DMT_1280X768P60,
+	V4L2_DV_BT_DMT_1280X768P75,
+	V4L2_DV_BT_DMT_1280X768P85,
+	V4L2_DV_BT_DMT_1280X800P60_RB,
+	V4L2_DV_BT_DMT_1280X800P60,
+	V4L2_DV_BT_DMT_1280X800P75,
+	V4L2_DV_BT_DMT_1280X800P85,
+	V4L2_DV_BT_DMT_1280X960P60,
+	V4L2_DV_BT_DMT_1280X960P85,
+	V4L2_DV_BT_DMT_1280X1024P60,
+	V4L2_DV_BT_DMT_1280X1024P75,
+	V4L2_DV_BT_DMT_1280X1024P85,
+	V4L2_DV_BT_DMT_1360X768P60,
+	V4L2_DV_BT_DMT_1400X1050P60_RB,
+	V4L2_DV_BT_DMT_1400X1050P60,
+	V4L2_DV_BT_DMT_1400X1050P75,
+	V4L2_DV_BT_DMT_1400X1050P85,
+	V4L2_DV_BT_DMT_1440X900P60_RB,
+	V4L2_DV_BT_DMT_1440X900P60,
+	V4L2_DV_BT_DMT_1600X1200P60,
+	V4L2_DV_BT_DMT_1680X1050P60_RB,
+	V4L2_DV_BT_DMT_1680X1050P60,
+	V4L2_DV_BT_DMT_1792X1344P60,
+	V4L2_DV_BT_DMT_1856X1392P60,
+	V4L2_DV_BT_DMT_1920X1200P60_RB,
+	V4L2_DV_BT_DMT_1366X768P60,
+	V4L2_DV_BT_DMT_1920X1080P60,
+	{ },
+};
+
+/* ----------------------------------------------------------------------- */
+
+static inline struct adv7604_state *to_state(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct adv7604_state, sd);
+}
+
+static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
+{
+	return &container_of(ctrl->handler, struct adv7604_state, hdl)->sd;
+}
+
+static inline unsigned hblanking(const struct v4l2_bt_timings *t)
+{
+	return t->hfrontporch + t->hsync + t->hbackporch;
+}
+
+static inline unsigned htotal(const struct v4l2_bt_timings *t)
+{
+	return t->width + t->hfrontporch + t->hsync + t->hbackporch;
+}
+
+static inline unsigned vblanking(const struct v4l2_bt_timings *t)
+{
+	return t->vfrontporch + t->vsync + t->vbackporch;
+}
+
+static inline unsigned vtotal(const struct v4l2_bt_timings *t)
+{
+	return t->height + t->vfrontporch + t->vsync + t->vbackporch;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static s32 adv_smbus_read_byte_data_check(struct i2c_client *client,
+		u8 command, bool check)
+{
+	union i2c_smbus_data data;
+
+	if (!i2c_smbus_xfer(client->adapter, client->addr, client->flags,
+			I2C_SMBUS_READ, command,
+			I2C_SMBUS_BYTE_DATA, &data))
+		return data.byte;
+	if (check)
+		v4l_err(client, "error reading %02x, %02x\n",
+				client->addr, command);
+	return -EIO;
+}
+
+static s32 adv_smbus_read_byte_data(struct i2c_client *client, u8 command)
+{
+	return adv_smbus_read_byte_data_check(client, command, true);
+}
+
+static s32 adv_smbus_write_byte_data(struct i2c_client *client,
+					u8 command, u8 value)
+{
+	union i2c_smbus_data data;
+	int err;
+	int i;
+
+	data.byte = value;
+	for (i = 0; i < 3; i++) {
+		err = i2c_smbus_xfer(client->adapter, client->addr,
+				client->flags,
+				I2C_SMBUS_WRITE, command,
+				I2C_SMBUS_BYTE_DATA, &data);
+		if (!err)
+			break;
+	}
+	if (err < 0)
+		v4l_err(client, "error writing %02x, %02x, %02x\n",
+				client->addr, command, value);
+	return err;
+}
+
+static s32 adv_smbus_write_i2c_block_data(struct i2c_client *client,
+	       u8 command, unsigned length, const u8 *values)
+{
+	union i2c_smbus_data data;
+
+	if (length > I2C_SMBUS_BLOCK_MAX)
+		length = I2C_SMBUS_BLOCK_MAX;
+	data.block[0] = length;
+	memcpy(data.block + 1, values, length);
+	return i2c_smbus_xfer(client->adapter, client->addr, client->flags,
+			      I2C_SMBUS_WRITE, command,
+			      I2C_SMBUS_I2C_BLOCK_DATA, &data);
+}
+
+/* ----------------------------------------------------------------------- */
+
+static inline int io_read(struct v4l2_subdev *sd, u8 reg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	return adv_smbus_read_byte_data(client, reg);
+}
+
+static inline int io_write(struct v4l2_subdev *sd, u8 reg, u8 val)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	return adv_smbus_write_byte_data(client, reg, val);
+}
+
+static inline int io_write_and_or(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val)
+{
+	return io_write(sd, reg, (io_read(sd, reg) & mask) | val);
+}
+
+static inline int avlink_read(struct v4l2_subdev *sd, u8 reg)
+{
+	struct adv7604_state *state = to_state(sd);
+
+	return adv_smbus_read_byte_data(state->i2c_avlink, reg);
+}
+
+static inline int avlink_write(struct v4l2_subdev *sd, u8 reg, u8 val)
+{
+	struct adv7604_state *state = to_state(sd);
+
+	return adv_smbus_write_byte_data(state->i2c_avlink, reg, val);
+}
+
+static inline int cec_read(struct v4l2_subdev *sd, u8 reg)
+{
+	struct adv7604_state *state = to_state(sd);
+
+	return adv_smbus_read_byte_data(state->i2c_cec, reg);
+}
+
+static inline int cec_write(struct v4l2_subdev *sd, u8 reg, u8 val)
+{
+	struct adv7604_state *state = to_state(sd);
+
+	return adv_smbus_write_byte_data(state->i2c_cec, reg, val);
+}
+
+static inline int cec_write_and_or(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val)
+{
+	return cec_write(sd, reg, (cec_read(sd, reg) & mask) | val);
+}
+
+static inline int infoframe_read(struct v4l2_subdev *sd, u8 reg)
+{
+	struct adv7604_state *state = to_state(sd);
+
+	return adv_smbus_read_byte_data(state->i2c_infoframe, reg);
+}
+
+static inline int infoframe_write(struct v4l2_subdev *sd, u8 reg, u8 val)
+{
+	struct adv7604_state *state = to_state(sd);
+
+	return adv_smbus_write_byte_data(state->i2c_infoframe, reg, val);
+}
+
+static inline int esdp_read(struct v4l2_subdev *sd, u8 reg)
+{
+	struct adv7604_state *state = to_state(sd);
+
+	return adv_smbus_read_byte_data(state->i2c_esdp, reg);
+}
+
+static inline int esdp_write(struct v4l2_subdev *sd, u8 reg, u8 val)
+{
+	struct adv7604_state *state = to_state(sd);
+
+	return adv_smbus_write_byte_data(state->i2c_esdp, reg, val);
+}
+
+static inline int dpp_read(struct v4l2_subdev *sd, u8 reg)
+{
+	struct adv7604_state *state = to_state(sd);
+
+	return adv_smbus_read_byte_data(state->i2c_dpp, reg);
+}
+
+static inline int dpp_write(struct v4l2_subdev *sd, u8 reg, u8 val)
+{
+	struct adv7604_state *state = to_state(sd);
+
+	return adv_smbus_write_byte_data(state->i2c_dpp, reg, val);
+}
+
+static inline int afe_read(struct v4l2_subdev *sd, u8 reg)
+{
+	struct adv7604_state *state = to_state(sd);
+
+	return adv_smbus_read_byte_data(state->i2c_afe, reg);
+}
+
+static inline int afe_write(struct v4l2_subdev *sd, u8 reg, u8 val)
+{
+	struct adv7604_state *state = to_state(sd);
+
+	return adv_smbus_write_byte_data(state->i2c_afe, reg, val);
+}
+
+static inline int rep_read(struct v4l2_subdev *sd, u8 reg)
+{
+	struct adv7604_state *state = to_state(sd);
+
+	return adv_smbus_read_byte_data(state->i2c_repeater, reg);
+}
+
+static inline int rep_write(struct v4l2_subdev *sd, u8 reg, u8 val)
+{
+	struct adv7604_state *state = to_state(sd);
+
+	return adv_smbus_write_byte_data(state->i2c_repeater, reg, val);
+}
+
+static inline int rep_write_and_or(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val)
+{
+	return rep_write(sd, reg, (rep_read(sd, reg) & mask) | val);
+}
+
+static inline int edid_read(struct v4l2_subdev *sd, u8 reg)
+{
+	struct adv7604_state *state = to_state(sd);
+
+	return adv_smbus_read_byte_data(state->i2c_edid, reg);
+}
+
+static inline int edid_write(struct v4l2_subdev *sd, u8 reg, u8 val)
+{
+	struct adv7604_state *state = to_state(sd);
+
+	return adv_smbus_write_byte_data(state->i2c_edid, reg, val);
+}
+
+static inline int edid_read_block(struct v4l2_subdev *sd, unsigned len, u8 *val)
+{
+	struct adv7604_state *state = to_state(sd);
+	struct i2c_client *client = state->i2c_edid;
+	u8 msgbuf0[1] = { 0 };
+	u8 msgbuf1[256];
+	struct i2c_msg msg[2] = { { client->addr, 0, 1, msgbuf0 },
+				  { client->addr, 0 | I2C_M_RD, len, msgbuf1 }
+				};
+
+	if (i2c_transfer(client->adapter, msg, 2) < 0)
+		return -EIO;
+	memcpy(val, msgbuf1, len);
+	return 0;
+}
+
+static void adv7604_delayed_work_enable_hotplug(struct work_struct *work)
+{
+	struct delayed_work *dwork = to_delayed_work(work);
+	struct adv7604_state *state = container_of(dwork, struct adv7604_state,
+						delayed_work_enable_hotplug);
+	struct v4l2_subdev *sd = &state->sd;
+
+	v4l2_dbg(2, debug, sd, "%s: enable hotplug\n", __func__);
+
+	v4l2_subdev_notify(sd, ADV7604_HOTPLUG, (void *)1);
+}
+
+static inline int edid_write_block(struct v4l2_subdev *sd,
+					unsigned len, const u8 *val)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct adv7604_state *state = to_state(sd);
+	int err = 0;
+	int i;
+
+	v4l2_dbg(2, debug, sd, "%s: write EDID block (%d byte)\n", __func__, len);
+
+	v4l2_subdev_notify(sd, ADV7604_HOTPLUG, (void *)0);
+
+	/* Disables I2C access to internal EDID ram from DDC port */
+	rep_write_and_or(sd, 0x77, 0xf0, 0x0);
+
+	for (i = 0; !err && i < len; i += I2C_SMBUS_BLOCK_MAX)
+		err = adv_smbus_write_i2c_block_data(state->i2c_edid, i,
+				I2C_SMBUS_BLOCK_MAX, val + i);
+	if (err)
+		return err;
+
+	/* adv7604 calculates the checksums and enables I2C access to internal
+	   EDID ram from DDC port. */
+	rep_write_and_or(sd, 0x77, 0xf0, 0x1);
+
+	for (i = 0; i < 1000; i++) {
+		if (rep_read(sd, 0x7d) & 1)
+			break;
+		mdelay(1);
+	}
+	if (i == 1000) {
+		v4l_err(client, "error enabling edid\n");
+		return -EIO;
+	}
+
+	/* enable hotplug after 100 ms */
+	queue_delayed_work(state->work_queues,
+			&state->delayed_work_enable_hotplug, HZ / 10);
+	return 0;
+}
+
+static inline int hdmi_read(struct v4l2_subdev *sd, u8 reg)
+{
+	struct adv7604_state *state = to_state(sd);
+
+	return adv_smbus_read_byte_data(state->i2c_hdmi, reg);
+}
+
+static inline int hdmi_write(struct v4l2_subdev *sd, u8 reg, u8 val)
+{
+	struct adv7604_state *state = to_state(sd);
+
+	return adv_smbus_write_byte_data(state->i2c_hdmi, reg, val);
+}
+
+static inline int test_read(struct v4l2_subdev *sd, u8 reg)
+{
+	struct adv7604_state *state = to_state(sd);
+
+	return adv_smbus_read_byte_data(state->i2c_test, reg);
+}
+
+static inline int test_write(struct v4l2_subdev *sd, u8 reg, u8 val)
+{
+	struct adv7604_state *state = to_state(sd);
+
+	return adv_smbus_write_byte_data(state->i2c_test, reg, val);
+}
+
+static inline int cp_read(struct v4l2_subdev *sd, u8 reg)
+{
+	struct adv7604_state *state = to_state(sd);
+
+	return adv_smbus_read_byte_data(state->i2c_cp, reg);
+}
+
+static inline int cp_write(struct v4l2_subdev *sd, u8 reg, u8 val)
+{
+	struct adv7604_state *state = to_state(sd);
+
+	return adv_smbus_write_byte_data(state->i2c_cp, reg, val);
+}
+
+static inline int cp_write_and_or(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val)
+{
+	return cp_write(sd, reg, (cp_read(sd, reg) & mask) | val);
+}
+
+static inline int vdp_read(struct v4l2_subdev *sd, u8 reg)
+{
+	struct adv7604_state *state = to_state(sd);
+
+	return adv_smbus_read_byte_data(state->i2c_vdp, reg);
+}
+
+static inline int vdp_write(struct v4l2_subdev *sd, u8 reg, u8 val)
+{
+	struct adv7604_state *state = to_state(sd);
+
+	return adv_smbus_write_byte_data(state->i2c_vdp, reg, val);
+}
+
+/* ----------------------------------------------------------------------- */
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static void adv7604_inv_register(struct v4l2_subdev *sd)
+{
+	v4l2_info(sd, "0x000-0x0ff: IO Map\n");
+	v4l2_info(sd, "0x100-0x1ff: AVLink Map\n");
+	v4l2_info(sd, "0x200-0x2ff: CEC Map\n");
+	v4l2_info(sd, "0x300-0x3ff: InfoFrame Map\n");
+	v4l2_info(sd, "0x400-0x4ff: ESDP Map\n");
+	v4l2_info(sd, "0x500-0x5ff: DPP Map\n");
+	v4l2_info(sd, "0x600-0x6ff: AFE Map\n");
+	v4l2_info(sd, "0x700-0x7ff: Repeater Map\n");
+	v4l2_info(sd, "0x800-0x8ff: EDID Map\n");
+	v4l2_info(sd, "0x900-0x9ff: HDMI Map\n");
+	v4l2_info(sd, "0xa00-0xaff: Test Map\n");
+	v4l2_info(sd, "0xb00-0xbff: CP Map\n");
+	v4l2_info(sd, "0xc00-0xcff: VDP Map\n");
+}
+
+static int adv7604_g_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;
+	reg->size = 1;
+	switch (reg->reg >> 8) {
+	case 0:
+		reg->val = io_read(sd, reg->reg & 0xff);
+		break;
+	case 1:
+		reg->val = avlink_read(sd, reg->reg & 0xff);
+		break;
+	case 2:
+		reg->val = cec_read(sd, reg->reg & 0xff);
+		break;
+	case 3:
+		reg->val = infoframe_read(sd, reg->reg & 0xff);
+		break;
+	case 4:
+		reg->val = esdp_read(sd, reg->reg & 0xff);
+		break;
+	case 5:
+		reg->val = dpp_read(sd, reg->reg & 0xff);
+		break;
+	case 6:
+		reg->val = afe_read(sd, reg->reg & 0xff);
+		break;
+	case 7:
+		reg->val = rep_read(sd, reg->reg & 0xff);
+		break;
+	case 8:
+		reg->val = edid_read(sd, reg->reg & 0xff);
+		break;
+	case 9:
+		reg->val = hdmi_read(sd, reg->reg & 0xff);
+		break;
+	case 0xa:
+		reg->val = test_read(sd, reg->reg & 0xff);
+		break;
+	case 0xb:
+		reg->val = cp_read(sd, reg->reg & 0xff);
+		break;
+	case 0xc:
+		reg->val = vdp_read(sd, reg->reg & 0xff);
+		break;
+	default:
+		v4l2_info(sd, "Register %03llx not supported\n", reg->reg);
+		adv7604_inv_register(sd);
+		break;
+	}
+	return 0;
+}
+
+static int adv7604_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;
+	switch (reg->reg >> 8) {
+	case 0:
+		io_write(sd, reg->reg & 0xff, reg->val & 0xff);
+		break;
+	case 1:
+		avlink_write(sd, reg->reg & 0xff, reg->val & 0xff);
+		break;
+	case 2:
+		cec_write(sd, reg->reg & 0xff, reg->val & 0xff);
+		break;
+	case 3:
+		infoframe_write(sd, reg->reg & 0xff, reg->val & 0xff);
+		break;
+	case 4:
+		esdp_write(sd, reg->reg & 0xff, reg->val & 0xff);
+		break;
+	case 5:
+		dpp_write(sd, reg->reg & 0xff, reg->val & 0xff);
+		break;
+	case 6:
+		afe_write(sd, reg->reg & 0xff, reg->val & 0xff);
+		break;
+	case 7:
+		rep_write(sd, reg->reg & 0xff, reg->val & 0xff);
+		break;
+	case 8:
+		edid_write(sd, reg->reg & 0xff, reg->val & 0xff);
+		break;
+	case 9:
+		hdmi_write(sd, reg->reg & 0xff, reg->val & 0xff);
+		break;
+	case 0xa:
+		test_write(sd, reg->reg & 0xff, reg->val & 0xff);
+		break;
+	case 0xb:
+		cp_write(sd, reg->reg & 0xff, reg->val & 0xff);
+		break;
+	case 0xc:
+		vdp_write(sd, reg->reg & 0xff, reg->val & 0xff);
+		break;
+	default:
+		v4l2_info(sd, "Register %03llx not supported\n", reg->reg);
+		adv7604_inv_register(sd);
+		break;
+	}
+	return 0;
+}
+#endif
+
+static int adv7604_s_detect_tx_5v_ctrl(struct v4l2_subdev *sd)
+{
+	struct adv7604_state *state = to_state(sd);
+
+	/* port A only */
+	return v4l2_ctrl_s_ctrl(state->detect_tx_5v_ctrl,
+				((io_read(sd, 0x6f) & 0x10) >> 4));
+}
+
+static void configure_free_run(struct v4l2_subdev *sd, const struct v4l2_bt_timings *timings)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	u32 width = htotal(timings);
+	u32 height = vtotal(timings);
+	u16 ch1_fr_ll = (((u32)timings->pixelclock / 100) > 0) ?
+		((width * (ADV7604_fsc / 100)) / ((u32)timings->pixelclock / 100)) : 0;
+
+	v4l2_dbg(2, debug, sd, "%s\n", __func__);
+
+	cp_write(sd, 0x8f, (ch1_fr_ll >> 8) & 0x7);	/* CH1_FR_LL */
+	cp_write(sd, 0x90, ch1_fr_ll & 0xff);		/* CH1_FR_LL */
+	cp_write(sd, 0xab, (height >> 4) & 0xff); /* CP_LCOUNT_MAX */
+	cp_write(sd, 0xac, (height & 0x0f) << 4); /* CP_LCOUNT_MAX */
+	/* TODO support interlaced */
+	cp_write(sd, 0x91, 0x10);	/* INTERLACED */
+
+	/* Should only be set in auto-graphics mode [REF_02 p. 91-92] */
+	if ((io_read(sd, 0x00) == 0x07) && (io_read(sd, 0x01) == 0x02)) {
+		u16 cp_start_sav, cp_start_eav, cp_start_vbi, cp_end_vbi;
+		const u8 pll[2] = {
+			(0xc0 | ((width >> 8) & 0x1f)),
+			(width & 0xff)
+		};
+
+		/* setup PLL_DIV_MAN_EN and PLL_DIV_RATIO */
+		/* IO-map reg. 0x16 and 0x17 should be written in sequence */
+		if (adv_smbus_write_i2c_block_data(client, 0x16, 2, pll)) {
+			v4l2_err(sd, "writing to reg 0x16 and 0x17 failed\n");
+			return;
+		}
+
+		/* active video - horizontal timing */
+		cp_start_sav = timings->hsync + timings->hbackporch - 4;
+		cp_start_eav = width - timings->hfrontporch;
+		cp_write(sd, 0xa2, (cp_start_sav >> 4) & 0xff);
+		cp_write(sd, 0xa3, ((cp_start_sav & 0x0f) << 4) | ((cp_start_eav >> 8) & 0x0f));
+		cp_write(sd, 0xa4, cp_start_eav & 0xff);
+
+		/* active video - vertical timing */
+		cp_start_vbi = height - timings->vfrontporch;
+		cp_end_vbi = timings->vsync + timings->vbackporch;
+		cp_write(sd, 0xa5, (cp_start_vbi >> 4) & 0xff);
+		cp_write(sd, 0xa6, ((cp_start_vbi & 0xf) << 4) | ((cp_end_vbi >> 8) & 0xf));
+		cp_write(sd, 0xa7, cp_end_vbi & 0xff);
+	} else {
+		/* reset to default values */
+		io_write(sd, 0x16, 0x43);
+		io_write(sd, 0x17, 0x5a);
+		cp_write(sd, 0xa2, 0x00);
+		cp_write(sd, 0xa3, 0x00);
+		cp_write(sd, 0xa4, 0x00);
+		cp_write(sd, 0xa5, 0x00);
+		cp_write(sd, 0xa6, 0x00);
+		cp_write(sd, 0xa7, 0x00);
+	}
+}
+
+
+static void set_rgb_quantization_range(struct v4l2_subdev *sd)
+{
+	struct adv7604_state *state = to_state(sd);
+
+	switch (state->rgb_quantization_range) {
+	case V4L2_DV_RGB_RANGE_AUTO:
+		/* automatic */
+		if ((hdmi_read(sd, 0x05) & 0x80) ||
+				(state->prim_mode == ADV7604_PRIM_MODE_COMP) ||
+				(state->prim_mode == ADV7604_PRIM_MODE_RGB)) {
+			/* receiving HDMI or analog signal */
+			io_write_and_or(sd, 0x02, 0x0f, 0xf0);
+		} else {
+			/* receiving DVI-D signal */
+
+			/* ADV7604 selects RGB limited range regardless of
+			   input format (CE/IT) in automatic mode */
+			if (state->timings.bt.standards & V4L2_DV_BT_STD_CEA861) {
+				/* RGB limited range (16-235) */
+				io_write_and_or(sd, 0x02, 0x0f, 0x00);
+
+			} else {
+				/* RGB full range (0-255) */
+				io_write_and_or(sd, 0x02, 0x0f, 0x10);
+			}
+		}
+		break;
+	case V4L2_DV_RGB_RANGE_LIMITED:
+		/* RGB limited range (16-235) */
+		io_write_and_or(sd, 0x02, 0x0f, 0x00);
+		break;
+	case V4L2_DV_RGB_RANGE_FULL:
+		/* RGB full range (0-255) */
+		io_write_and_or(sd, 0x02, 0x0f, 0x10);
+		break;
+	}
+}
+
+
+static int adv7604_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct v4l2_subdev *sd = to_sd(ctrl);
+	struct adv7604_state *state = to_state(sd);
+
+	switch (ctrl->id) {
+	case V4L2_CID_BRIGHTNESS:
+		cp_write(sd, 0x3c, ctrl->val);
+		return 0;
+	case V4L2_CID_CONTRAST:
+		cp_write(sd, 0x3a, ctrl->val);
+		return 0;
+	case V4L2_CID_SATURATION:
+		cp_write(sd, 0x3b, ctrl->val);
+		return 0;
+	case V4L2_CID_HUE:
+		cp_write(sd, 0x3d, ctrl->val);
+		return 0;
+	case  V4L2_CID_DV_RX_RGB_RANGE:
+		state->rgb_quantization_range = ctrl->val;
+		set_rgb_quantization_range(sd);
+		return 0;
+	case V4L2_CID_ADV_RX_ANALOG_SAMPLING_PHASE:
+		/* Set the analog sampling phase. This is needed to find the
+		   best sampling phase for analog video: an application or
+		   driver has to try a number of phases and analyze the picture
+		   quality before settling on the best performing phase. */
+		afe_write(sd, 0xc8, ctrl->val);
+		return 0;
+	case V4L2_CID_ADV_RX_FREE_RUN_COLOR_MANUAL:
+		/* Use the default blue color for free running mode,
+		   or supply your own. */
+		cp_write_and_or(sd, 0xbf, ~0x04, (ctrl->val << 2));
+		return 0;
+	case V4L2_CID_ADV_RX_FREE_RUN_COLOR:
+		cp_write(sd, 0xc0, (ctrl->val & 0xff0000) >> 16);
+		cp_write(sd, 0xc1, (ctrl->val & 0x00ff00) >> 8);
+		cp_write(sd, 0xc2, (u8)(ctrl->val & 0x0000ff));
+		return 0;
+	}
+	return -EINVAL;
+}
+
+static int adv7604_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_ADV7604, 0);
+}
+
+/* ----------------------------------------------------------------------- */
+
+static inline bool no_power(struct v4l2_subdev *sd)
+{
+	/* Entire chip or CP powered off */
+	return io_read(sd, 0x0c) & 0x24;
+}
+
+static inline bool no_signal_tmds(struct v4l2_subdev *sd)
+{
+	/* TODO port B, C and D */
+	return !(io_read(sd, 0x6a) & 0x10);
+}
+
+static inline bool no_lock_tmds(struct v4l2_subdev *sd)
+{
+	return (io_read(sd, 0x6a) & 0xe0) != 0xe0;
+}
+
+static inline bool no_lock_sspd(struct v4l2_subdev *sd)
+{
+	/* TODO channel 2 */
+	return ((cp_read(sd, 0xb5) & 0xd0) != 0xd0);
+}
+
+static inline bool no_lock_stdi(struct v4l2_subdev *sd)
+{
+	/* TODO channel 2 */
+	return !(cp_read(sd, 0xb1) & 0x80);
+}
+
+static inline bool no_signal(struct v4l2_subdev *sd)
+{
+	struct adv7604_state *state = to_state(sd);
+	bool ret;
+
+	ret = no_power(sd);
+
+	ret |= no_lock_stdi(sd);
+	ret |= no_lock_sspd(sd);
+
+	if (DIGITAL_INPUT) {
+		ret |= no_lock_tmds(sd);
+		ret |= no_signal_tmds(sd);
+	}
+
+	return ret;
+}
+
+static inline bool no_lock_cp(struct v4l2_subdev *sd)
+{
+	/* CP has detected a non standard number of lines on the incoming
+	   video compared to what it is configured to receive by s_dv_timings */
+	return io_read(sd, 0x12) & 0x01;
+}
+
+static int adv7604_g_input_status(struct v4l2_subdev *sd, u32 *status)
+{
+	struct adv7604_state *state = to_state(sd);
+
+	*status = 0;
+	*status |= no_power(sd) ? V4L2_IN_ST_NO_POWER : 0;
+	*status |= no_signal(sd) ? V4L2_IN_ST_NO_SIGNAL : 0;
+	if (no_lock_cp(sd))
+		*status |= DIGITAL_INPUT ? V4L2_IN_ST_NO_SYNC : V4L2_IN_ST_NO_H_LOCK;
+
+	v4l2_dbg(1, debug, sd, "%s: status = 0x%x\n", __func__, *status);
+
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static void adv7604_print_timings(struct v4l2_subdev *sd,
+	struct v4l2_dv_timings *timings, const char *txt, bool detailed)
+{
+	struct v4l2_bt_timings *bt = &timings->bt;
+	u32 htot, vtot;
+
+	if (timings->type != V4L2_DV_BT_656_1120)
+		return;
+
+	htot = htotal(bt);
+	vtot = vtotal(bt);
+
+	v4l2_info(sd, "%s %dx%d%s%d (%dx%d)",
+			txt, bt->width, bt->height, bt->interlaced ? "i" : "p",
+			(htot * vtot) > 0 ? ((u32)bt->pixelclock /
+				(htot * vtot)) : 0,
+			htot, vtot);
+
+	if (detailed) {
+		v4l2_info(sd, "    horizontal: fp = %d, %ssync = %d, bp = %d\n",
+				bt->hfrontporch,
+				(bt->polarities & V4L2_DV_HSYNC_POS_POL) ? "+" : "-",
+				bt->hsync, bt->hbackporch);
+		v4l2_info(sd, "    vertical: fp = %d, %ssync = %d, bp = %d\n",
+				bt->vfrontporch,
+				(bt->polarities & V4L2_DV_VSYNC_POS_POL) ? "+" : "-",
+				bt->vsync, bt->vbackporch);
+		v4l2_info(sd, "    pixelclock: %lld, flags: 0x%x, standards: 0x%x\n",
+				bt->pixelclock, bt->flags, bt->standards);
+	}
+}
+
+struct stdi_readback {
+	u16 bl, lcf, lcvs;
+	u8 hs_pol, vs_pol;
+	bool interlaced;
+};
+
+static int stdi2dv_timings(struct v4l2_subdev *sd,
+		struct stdi_readback *stdi,
+		struct v4l2_dv_timings *timings)
+{
+	struct adv7604_state *state = to_state(sd);
+	u32 hfreq = (ADV7604_fsc * 8) / stdi->bl;
+	u32 pix_clk;
+	int i;
+
+	for (i = 0; adv7604_timings[i].bt.height; i++) {
+		if (vtotal(&adv7604_timings[i].bt) != stdi->lcf + 1)
+			continue;
+		if (adv7604_timings[i].bt.vsync != stdi->lcvs)
+			continue;
+
+		pix_clk = hfreq * htotal(&adv7604_timings[i].bt);
+
+		if ((pix_clk < adv7604_timings[i].bt.pixelclock + 1000000) &&
+		    (pix_clk > adv7604_timings[i].bt.pixelclock - 1000000)) {
+			*timings = adv7604_timings[i];
+			return 0;
+		}
+	}
+
+	if (v4l2_detect_cvt(stdi->lcf + 1, hfreq, stdi->lcvs,
+			(stdi->hs_pol == '+' ? V4L2_DV_HSYNC_POS_POL : 0) |
+			(stdi->vs_pol == '+' ? V4L2_DV_VSYNC_POS_POL : 0),
+			timings))
+		return 0;
+	if (v4l2_detect_gtf(stdi->lcf + 1, hfreq, stdi->lcvs,
+			(stdi->hs_pol == '+' ? V4L2_DV_HSYNC_POS_POL : 0) |
+			(stdi->vs_pol == '+' ? V4L2_DV_VSYNC_POS_POL : 0),
+			state->aspect_ratio, timings))
+		return 0;
+
+	v4l2_dbg(2, debug, sd, "%s: No format candidate found for lcf=%d, bl = %d\n",
+			__func__, stdi->lcf, stdi->bl);
+	return -1;
+}
+
+static int read_stdi(struct v4l2_subdev *sd, struct stdi_readback *stdi)
+{
+	if (no_lock_stdi(sd) || no_lock_sspd(sd)) {
+		v4l2_dbg(2, debug, sd, "%s: STDI and/or SSPD not locked\n", __func__);
+		return -1;
+	}
+
+	/* read STDI */
+	stdi->bl = ((cp_read(sd, 0xb1) & 0x3f) << 8) | cp_read(sd, 0xb2);
+	stdi->lcf = ((cp_read(sd, 0xb3) & 0x7) << 8) | cp_read(sd, 0xb4);
+	stdi->lcvs = cp_read(sd, 0xb3) >> 3;
+	stdi->interlaced = io_read(sd, 0x12) & 0x10;
+
+	/* read SSPD */
+	if ((cp_read(sd, 0xb5) & 0x03) == 0x01) {
+		stdi->hs_pol = ((cp_read(sd, 0xb5) & 0x10) ?
+				((cp_read(sd, 0xb5) & 0x08) ? '+' : '-') : 'x');
+		stdi->vs_pol = ((cp_read(sd, 0xb5) & 0x40) ?
+				((cp_read(sd, 0xb5) & 0x20) ? '+' : '-') : 'x');
+	} else {
+		stdi->hs_pol = 'x';
+		stdi->vs_pol = 'x';
+	}
+
+	if (no_lock_stdi(sd) || no_lock_sspd(sd)) {
+		v4l2_dbg(2, debug, sd,
+			"%s: signal lost during readout of STDI/SSPD\n", __func__);
+		return -1;
+	}
+
+	if (stdi->lcf < 239 || stdi->bl < 8 || stdi->bl == 0x3fff) {
+		v4l2_dbg(2, debug, sd, "%s: invalid signal\n", __func__);
+		memset(stdi, 0, sizeof(struct stdi_readback));
+		return -1;
+	}
+
+	v4l2_dbg(2, debug, sd,
+		"%s: lcf (frame height - 1) = %d, bl = %d, lcvs (vsync) = %d, %chsync, %cvsync, %s\n",
+		__func__, stdi->lcf, stdi->bl, stdi->lcvs,
+		stdi->hs_pol, stdi->vs_pol,
+		stdi->interlaced ? "interlaced" : "progressive");
+
+	return 0;
+}
+
+static int adv7604_enum_dv_timings(struct v4l2_subdev *sd,
+			struct v4l2_enum_dv_timings *timings)
+{
+	if (timings->index >= ARRAY_SIZE(adv7604_timings) - 1)
+		return -EINVAL;
+	memset(timings->reserved, 0, sizeof(timings->reserved));
+	timings->timings = adv7604_timings[timings->index];
+	return 0;
+}
+
+static int adv7604_dv_timings_cap(struct v4l2_subdev *sd,
+			struct v4l2_dv_timings_cap *cap)
+{
+	struct adv7604_state *state = to_state(sd);
+
+	cap->type = V4L2_DV_BT_656_1120;
+	cap->bt.max_width = 1920;
+	cap->bt.max_height = 1200;
+	cap->bt.min_pixelclock = 27000000;
+	if (DIGITAL_INPUT)
+		cap->bt.max_pixelclock = 225000000;
+	else
+		cap->bt.max_pixelclock = 170000000;
+	cap->bt.standards = V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT |
+			 V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT;
+	cap->bt.capabilities = V4L2_DV_BT_CAP_PROGRESSIVE |
+		V4L2_DV_BT_CAP_REDUCED_BLANKING | V4L2_DV_BT_CAP_CUSTOM;
+	return 0;
+}
+
+/* Fill the optional fields .standards and .flags in struct v4l2_dv_timings
+   if the format is listed in adv7604_timings[] */
+static void adv7604_fill_optional_dv_timings_fields(struct v4l2_subdev *sd,
+		struct v4l2_dv_timings *timings)
+{
+	struct adv7604_state *state = to_state(sd);
+	int i;
+
+	for (i = 0; adv7604_timings[i].bt.width; i++) {
+		if (v4l_match_dv_timings(timings, &adv7604_timings[i],
+					DIGITAL_INPUT ? 250000 : 1000000)) {
+			*timings = adv7604_timings[i];
+			break;
+		}
+	}
+}
+
+static int adv7604_query_dv_timings(struct v4l2_subdev *sd,
+			struct v4l2_dv_timings *timings)
+{
+	struct adv7604_state *state = to_state(sd);
+	struct v4l2_bt_timings *bt = &timings->bt;
+	struct stdi_readback stdi;
+
+	if (!timings)
+		return -EINVAL;
+
+	memset(timings, 0, sizeof(struct v4l2_dv_timings));
+
+	if (no_signal(sd)) {
+		v4l2_dbg(1, debug, sd, "%s: no valid signal\n", __func__);
+		return -ENOLINK;
+	}
+
+	/* read STDI */
+	if (read_stdi(sd, &stdi)) {
+		v4l2_dbg(1, debug, sd, "%s: STDI/SSPD not locked\n", __func__);
+		return -ENOLINK;
+	}
+	bt->interlaced = stdi.interlaced ?
+		V4L2_DV_INTERLACED : V4L2_DV_PROGRESSIVE;
+
+	if (DIGITAL_INPUT) {
+		timings->type = V4L2_DV_BT_656_1120;
+
+		bt->width = (hdmi_read(sd, 0x07) & 0x0f) * 256 + hdmi_read(sd, 0x08);
+		bt->height = (hdmi_read(sd, 0x09) & 0x0f) * 256 + hdmi_read(sd, 0x0a);
+		bt->pixelclock = (hdmi_read(sd, 0x06) * 1000000) +
+			((hdmi_read(sd, 0x3b) & 0x30) >> 4) * 250000;
+		bt->hfrontporch = (hdmi_read(sd, 0x20) & 0x03) * 256 +
+			hdmi_read(sd, 0x21);
+		bt->hsync = (hdmi_read(sd, 0x22) & 0x03) * 256 +
+			hdmi_read(sd, 0x23);
+		bt->hbackporch = (hdmi_read(sd, 0x24) & 0x03) * 256 +
+			hdmi_read(sd, 0x25);
+		bt->vfrontporch = ((hdmi_read(sd, 0x2a) & 0x1f) * 256 +
+			hdmi_read(sd, 0x2b)) / 2;
+		bt->vsync = ((hdmi_read(sd, 0x2e) & 0x1f) * 256 +
+			hdmi_read(sd, 0x2f)) / 2;
+		bt->vbackporch = ((hdmi_read(sd, 0x32) & 0x1f) * 256 +
+			hdmi_read(sd, 0x33)) / 2;
+		bt->polarities = ((hdmi_read(sd, 0x05) & 0x10) ? V4L2_DV_VSYNC_POS_POL : 0) |
+			((hdmi_read(sd, 0x05) & 0x20) ? V4L2_DV_HSYNC_POS_POL : 0);
+		if (bt->interlaced == V4L2_DV_INTERLACED) {
+			bt->height += (hdmi_read(sd, 0x0b) & 0x0f) * 256 +
+					hdmi_read(sd, 0x0c);
+			bt->il_vfrontporch = ((hdmi_read(sd, 0x2c) & 0x1f) * 256 +
+					hdmi_read(sd, 0x2d)) / 2;
+			bt->il_vsync = ((hdmi_read(sd, 0x30) & 0x1f) * 256 +
+					hdmi_read(sd, 0x31)) / 2;
+			bt->vbackporch = ((hdmi_read(sd, 0x34) & 0x1f) * 256 +
+					hdmi_read(sd, 0x35)) / 2;
+		}
+		adv7604_fill_optional_dv_timings_fields(sd, timings);
+	} else {
+		/* find format
+		 * Since LCVS values are inaccurate (REF_03, page 275-276),
+		 * stdi2dv_timings() is called with lcvs +-1 if the first attempt fails.
+		 */
+		if (!stdi2dv_timings(sd, &stdi, timings))
+			goto found;
+		stdi.lcvs += 1;
+		v4l2_dbg(1, debug, sd, "%s: lcvs + 1 = %d\n", __func__, stdi.lcvs);
+		if (!stdi2dv_timings(sd, &stdi, timings))
+			goto found;
+		stdi.lcvs -= 2;
+		v4l2_dbg(1, debug, sd, "%s: lcvs - 1 = %d\n", __func__, stdi.lcvs);
+		if (stdi2dv_timings(sd, &stdi, timings)) {
+			v4l2_dbg(1, debug, sd, "%s: format not supported\n", __func__);
+			return -ERANGE;
+		}
+	}
+found:
+
+	if (no_signal(sd)) {
+		v4l2_dbg(1, debug, sd, "%s: signal lost during readout\n", __func__);
+		memset(timings, 0, sizeof(struct v4l2_dv_timings));
+		return -ENOLINK;
+	}
+
+	if ((!DIGITAL_INPUT && bt->pixelclock > 170000000) ||
+			(DIGITAL_INPUT && bt->pixelclock > 225000000)) {
+		v4l2_dbg(1, debug, sd, "%s: pixelclock out of range %d\n",
+				__func__, (u32)bt->pixelclock);
+		return -ERANGE;
+	}
+
+	if (debug > 1)
+		adv7604_print_timings(sd, timings,
+				"adv7604_query_dv_timings:", true);
+
+	return 0;
+}
+
+static int adv7604_s_dv_timings(struct v4l2_subdev *sd,
+		struct v4l2_dv_timings *timings)
+{
+	struct adv7604_state *state = to_state(sd);
+	struct v4l2_bt_timings *bt;
+
+	if (!timings)
+		return -EINVAL;
+
+	bt = &timings->bt;
+
+	if ((!DIGITAL_INPUT && bt->pixelclock > 170000000) ||
+			(DIGITAL_INPUT && bt->pixelclock > 225000000)) {
+		v4l2_dbg(1, debug, sd, "%s: pixelclock out of range %d\n",
+				__func__, (u32)bt->pixelclock);
+		return -ERANGE;
+	}
+	adv7604_fill_optional_dv_timings_fields(sd, timings);
+
+	state->timings = *timings;
+
+	/* freerun */
+	configure_free_run(sd, bt);
+
+	set_rgb_quantization_range(sd);
+
+
+	if (debug > 1)
+		adv7604_print_timings(sd, timings,
+				"adv7604_s_dv_timings:", true);
+	return 0;
+}
+
+static int adv7604_g_dv_timings(struct v4l2_subdev *sd,
+		struct v4l2_dv_timings *timings)
+{
+	struct adv7604_state *state = to_state(sd);
+
+	*timings = state->timings;
+	return 0;
+}
+
+static void enable_input(struct v4l2_subdev *sd, enum adv7604_prim_mode prim_mode)
+{
+	switch (prim_mode) {
+	case ADV7604_PRIM_MODE_COMP:
+	case ADV7604_PRIM_MODE_RGB:
+		/* enable */
+		io_write(sd, 0x15, 0xb0);   /* Disable Tristate of Pins (no audio) */
+		break;
+	case ADV7604_PRIM_MODE_HDMI_COMP:
+	case ADV7604_PRIM_MODE_HDMI_GR:
+		/* enable */
+		hdmi_write(sd, 0x1a, 0x0a); /* Unmute audio */
+		hdmi_write(sd, 0x01, 0x00); /* Enable HDMI clock terminators */
+		io_write(sd, 0x15, 0xa0);   /* Disable Tristate of Pins */
+		break;
+	default:
+		v4l2_err(sd, "%s: reserved primary mode 0x%0x\n",
+				__func__, prim_mode);
+		break;
+	}
+}
+
+static void disable_input(struct v4l2_subdev *sd)
+{
+	/* disable */
+	io_write(sd, 0x15, 0xbe);   /* Tristate all outputs from video core */
+	hdmi_write(sd, 0x1a, 0x1a); /* Mute audio */
+	hdmi_write(sd, 0x01, 0x78); /* Disable HDMI clock terminators */
+}
+
+static void select_input(struct v4l2_subdev *sd, enum adv7604_prim_mode prim_mode)
+{
+	switch (prim_mode) {
+	case ADV7604_PRIM_MODE_COMP:
+	case ADV7604_PRIM_MODE_RGB:
+		/* set mode and select free run resolution */
+		io_write(sd, 0x00, 0x07); /* video std */
+		io_write(sd, 0x01, 0x02); /* prim mode */
+		/* enable embedded syncs for auto graphics mode */
+		cp_write_and_or(sd, 0x81, 0xef, 0x10);
+
+		/* reset ADI recommended settings for HDMI: */
+		/* "ADV7604 Register Settings Recommendations (rev. 2.5, June 2010)" p. 4. */
+		hdmi_write(sd, 0x0d, 0x04); /* HDMI filter optimization */
+		hdmi_write(sd, 0x3d, 0x00); /* DDC bus active pull-up control */
+		hdmi_write(sd, 0x3e, 0x74); /* TMDS PLL optimization */
+		hdmi_write(sd, 0x4e, 0x3b); /* TMDS PLL optimization */
+		hdmi_write(sd, 0x57, 0x74); /* TMDS PLL optimization */
+		hdmi_write(sd, 0x58, 0x63); /* TMDS PLL optimization */
+		hdmi_write(sd, 0x8d, 0x18); /* equaliser */
+		hdmi_write(sd, 0x8e, 0x34); /* equaliser */
+		hdmi_write(sd, 0x93, 0x88); /* equaliser */
+		hdmi_write(sd, 0x94, 0x2e); /* equaliser */
+		hdmi_write(sd, 0x96, 0x00); /* enable automatic EQ changing */
+
+		afe_write(sd, 0x00, 0x08); /* power up ADC */
+		afe_write(sd, 0x01, 0x06); /* power up Analog Front End */
+		afe_write(sd, 0xc8, 0x00); /* phase control */
+
+		/* set ADI recommended settings for digitizer */
+		/* "ADV7604 Register Settings Recommendations (rev. 2.5, June 2010)" p. 17. */
+		afe_write(sd, 0x12, 0x7b); /* ADC noise shaping filter controls */
+		afe_write(sd, 0x0c, 0x1f); /* CP core gain controls */
+		cp_write(sd, 0x3e, 0x04); /* CP core pre-gain control */
+		cp_write(sd, 0xc3, 0x39); /* CP coast control. Graphics mode */
+		cp_write(sd, 0x40, 0x5c); /* CP core pre-gain control. Graphics mode */
+		break;
+
+	case ADV7604_PRIM_MODE_HDMI_COMP:
+	case ADV7604_PRIM_MODE_HDMI_GR:
+		/* set mode and select free run resolution */
+		/* video std */
+		io_write(sd, 0x00,
+			(prim_mode == ADV7604_PRIM_MODE_HDMI_GR) ? 0x02 : 0x1e);
+		io_write(sd, 0x01, prim_mode); /* prim mode */
+		/* disable embedded syncs for auto graphics mode */
+		cp_write_and_or(sd, 0x81, 0xef, 0x00);
+
+		/* set ADI recommended settings for HDMI: */
+		/* "ADV7604 Register Settings Recommendations (rev. 2.5, June 2010)" p. 4. */
+		hdmi_write(sd, 0x0d, 0x84); /* HDMI filter optimization */
+		hdmi_write(sd, 0x3d, 0x10); /* DDC bus active pull-up control */
+		hdmi_write(sd, 0x3e, 0x39); /* TMDS PLL optimization */
+		hdmi_write(sd, 0x4e, 0x3b); /* TMDS PLL optimization */
+		hdmi_write(sd, 0x57, 0xb6); /* TMDS PLL optimization */
+		hdmi_write(sd, 0x58, 0x03); /* TMDS PLL optimization */
+		hdmi_write(sd, 0x8d, 0x18); /* equaliser */
+		hdmi_write(sd, 0x8e, 0x34); /* equaliser */
+		hdmi_write(sd, 0x93, 0x8b); /* equaliser */
+		hdmi_write(sd, 0x94, 0x2d); /* equaliser */
+		hdmi_write(sd, 0x96, 0x01); /* enable automatic EQ changing */
+
+		afe_write(sd, 0x00, 0xff); /* power down ADC */
+		afe_write(sd, 0x01, 0xfe); /* power down Analog Front End */
+		afe_write(sd, 0xc8, 0x40); /* phase control */
+
+		/* reset ADI recommended settings for digitizer */
+		/* "ADV7604 Register Settings Recommendations (rev. 2.5, June 2010)" p. 17. */
+		afe_write(sd, 0x12, 0xfb); /* ADC noise shaping filter controls */
+		afe_write(sd, 0x0c, 0x0d); /* CP core gain controls */
+		cp_write(sd, 0x3e, 0x00); /* CP core pre-gain control */
+		cp_write(sd, 0xc3, 0x39); /* CP coast control. Graphics mode */
+		cp_write(sd, 0x40, 0x80); /* CP core pre-gain control. Graphics mode */
+
+		break;
+	default:
+		v4l2_err(sd, "%s: reserved primary mode 0x%0x\n", __func__, prim_mode);
+		break;
+	}
+}
+
+static int adv7604_s_routing(struct v4l2_subdev *sd,
+		u32 input, u32 output, u32 config)
+{
+	struct adv7604_state *state = to_state(sd);
+
+	v4l2_dbg(2, debug, sd, "%s: input %d", __func__, input);
+
+	switch (input) {
+	case 0:
+		/* TODO select HDMI_COMP or HDMI_GR */
+		state->prim_mode = ADV7604_PRIM_MODE_HDMI_COMP;
+		break;
+	case 1:
+		state->prim_mode = ADV7604_PRIM_MODE_RGB;
+		break;
+	case 2:
+		state->prim_mode = ADV7604_PRIM_MODE_COMP;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	disable_input(sd);
+
+	select_input(sd, state->prim_mode);
+
+	enable_input(sd, state->prim_mode);
+
+	return 0;
+}
+
+static int adv7604_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned int index,
+			     enum v4l2_mbus_pixelcode *code)
+{
+	if (index)
+		return -EINVAL;
+	/* Good enough for now */
+	*code = V4L2_MBUS_FMT_FIXED;
+	return 0;
+}
+
+static int adv7604_g_mbus_fmt(struct v4l2_subdev *sd,
+		struct v4l2_mbus_framefmt *fmt)
+{
+	struct adv7604_state *state = to_state(sd);
+
+	fmt->width = state->timings.bt.width;
+	fmt->height = state->timings.bt.height;
+	fmt->code = V4L2_MBUS_FMT_FIXED;
+	fmt->field = V4L2_FIELD_NONE;
+	if (state->timings.bt.standards & V4L2_DV_BT_STD_CEA861) {
+		fmt->colorspace = (state->timings.bt.height <= 576) ?
+			V4L2_COLORSPACE_SMPTE170M : V4L2_COLORSPACE_REC709;
+	}
+	return 0;
+}
+
+static int adv7604_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
+{
+	struct adv7604_state *state = to_state(sd);
+	u8 fmt_change, fmt_change_digital, tx_5v;
+
+	/* format change */
+	fmt_change = io_read(sd, 0x43) & 0x98;
+	if (fmt_change)
+		io_write(sd, 0x44, fmt_change);
+	fmt_change_digital = DIGITAL_INPUT ? (io_read(sd, 0x6b) & 0xc0) : 0;
+	if (fmt_change_digital)
+		io_write(sd, 0x6c, fmt_change_digital);
+	if (fmt_change || fmt_change_digital) {
+		v4l2_dbg(1, debug, sd,
+			"%s: ADV7604_FMT_CHANGE, fmt_change = 0x%x, fmt_change_digital = 0x%x\n",
+			__func__, fmt_change, fmt_change_digital);
+		v4l2_subdev_notify(sd, ADV7604_FMT_CHANGE, NULL);
+		if (handled)
+			*handled = true;
+	}
+	/* tx 5v detect */
+	tx_5v = io_read(sd, 0x70) & 0x10;
+	if (tx_5v) {
+		v4l2_dbg(1, debug, sd, "%s: tx_5v: 0x%x\n", __func__, tx_5v);
+		io_write(sd, 0x71, tx_5v);
+		adv7604_s_detect_tx_5v_ctrl(sd);
+		if (handled)
+			*handled = true;
+	}
+	return 0;
+}
+
+static int adv7604_get_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edid)
+{
+	struct adv7604_state *state = to_state(sd);
+
+	if (edid->pad != 0)
+		return -EINVAL;
+	if (edid->blocks == 0)
+		return -EINVAL;
+	if (edid->start_block >= state->edid_blocks)
+		return -EINVAL;
+	if (edid->start_block + edid->blocks > state->edid_blocks)
+		edid->blocks = state->edid_blocks - edid->start_block;
+	if (!edid->edid)
+		return -EINVAL;
+	memcpy(edid->edid + edid->start_block * 128,
+	       state->edid + edid->start_block * 128,
+	       edid->blocks * 128);
+	return 0;
+}
+
+static int adv7604_set_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edid)
+{
+	struct adv7604_state *state = to_state(sd);
+	int err;
+
+	if (edid->pad != 0)
+		return -EINVAL;
+	if (edid->start_block != 0)
+		return -EINVAL;
+	if (edid->blocks == 0) {
+		/* Pull down the hotplug pin */
+		v4l2_subdev_notify(sd, ADV7604_HOTPLUG, (void *)0);
+		/* Disables I2C access to internal EDID ram from DDC port */
+		rep_write_and_or(sd, 0x77, 0xf0, 0x0);
+		state->edid_blocks = 0;
+		/* Fall back to a 16:9 aspect ratio */
+		state->aspect_ratio.numerator = 16;
+		state->aspect_ratio.denominator = 9;
+		return 0;
+	}
+	if (edid->blocks > 2)
+		return -E2BIG;
+	if (!edid->edid)
+		return -EINVAL;
+	memcpy(state->edid, edid->edid, 128 * edid->blocks);
+	state->edid_blocks = edid->blocks;
+	state->aspect_ratio = v4l2_calc_aspect_ratio(edid->edid[0x15],
+			edid->edid[0x16]);
+	err = edid_write_block(sd, 128 * edid->blocks, state->edid);
+	if (err < 0)
+		v4l2_err(sd, "error %d writing edid\n", err);
+	return err;
+}
+
+/*********** avi info frame CEA-861-E **************/
+
+static void print_avi_infoframe(struct v4l2_subdev *sd)
+{
+	int i;
+	u8 buf[14];
+	u8 avi_len;
+	u8 avi_ver;
+
+	if (!(hdmi_read(sd, 0x05) & 0x80)) {
+		v4l2_info(sd, "receive DVI-D signal (AVI infoframe not supported)\n");
+		return;
+	}
+	if (!(io_read(sd, 0x60) & 0x01)) {
+		v4l2_info(sd, "AVI infoframe not received\n");
+		return;
+	}
+
+	if (io_read(sd, 0x83) & 0x01) {
+		v4l2_info(sd, "AVI infoframe checksum error has occurred earlier\n");
+		io_write(sd, 0x85, 0x01); /* clear AVI_INF_CKS_ERR_RAW */
+		if (io_read(sd, 0x83) & 0x01) {
+			v4l2_info(sd, "AVI infoframe checksum error still present\n");
+			io_write(sd, 0x85, 0x01); /* clear AVI_INF_CKS_ERR_RAW */
+		}
+	}
+
+	avi_len = infoframe_read(sd, 0xe2);
+	avi_ver = infoframe_read(sd, 0xe1);
+	v4l2_info(sd, "AVI infoframe version %d (%d byte)\n",
+			avi_ver, avi_len);
+
+	if (avi_ver != 0x02)
+		return;
+
+	for (i = 0; i < 14; i++)
+		buf[i] = infoframe_read(sd, i);
+
+	v4l2_info(sd,
+		"\t%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
+		buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7],
+		buf[8], buf[9], buf[10], buf[11], buf[12], buf[13]);
+}
+
+static int adv7604_log_status(struct v4l2_subdev *sd)
+{
+	struct adv7604_state *state = to_state(sd);
+	struct v4l2_dv_timings timings;
+	struct stdi_readback stdi;
+	u8 reg_io_0x02 = io_read(sd, 0x02);
+
+	char *csc_coeff_sel_rb[16] = {
+		"bypassed", "YPbPr601 -> RGB", "reserved", "YPbPr709 -> RGB",
+		"reserved", "RGB -> YPbPr601", "reserved", "RGB -> YPbPr709",
+		"reserved", "YPbPr709 -> YPbPr601", "YPbPr601 -> YPbPr709",
+		"reserved", "reserved", "reserved", "reserved", "manual"
+	};
+	char *input_color_space_txt[16] = {
+		"RGB limited range (16-235)", "RGB full range (0-255)",
+		"YCbCr Bt.601 (16-235)", "YCbCr Bt.709 (16-235)",
+		"XvYCC Bt.601", "XvYCC Bt.709",
+		"YCbCr Bt.601 (0-255)", "YCbCr Bt.709 (0-255)",
+		"invalid", "invalid", "invalid", "invalid", "invalid",
+		"invalid", "invalid", "automatic"
+	};
+	char *rgb_quantization_range_txt[] = {
+		"Automatic",
+		"RGB limited range (16-235)",
+		"RGB full range (0-255)",
+	};
+
+	v4l2_info(sd, "-----Chip status-----\n");
+	v4l2_info(sd, "Chip power: %s\n", no_power(sd) ? "off" : "on");
+	v4l2_info(sd, "Connector type: %s\n", state->connector_hdmi ?
+			"HDMI" : (DIGITAL_INPUT ? "DVI-D" : "DVI-A"));
+	v4l2_info(sd, "EDID: %s\n", ((rep_read(sd, 0x7d) & 0x01) &&
+			(rep_read(sd, 0x77) & 0x01)) ? "enabled" : "disabled ");
+	v4l2_info(sd, "CEC: %s\n", !!(cec_read(sd, 0x2a) & 0x01) ?
+			"enabled" : "disabled");
+
+	v4l2_info(sd, "-----Signal status-----\n");
+	v4l2_info(sd, "Cable detected (+5V power): %s\n",
+			(io_read(sd, 0x6f) & 0x10) ? "true" : "false");
+	v4l2_info(sd, "TMDS signal detected: %s\n",
+			no_signal_tmds(sd) ? "false" : "true");
+	v4l2_info(sd, "TMDS signal locked: %s\n",
+			no_lock_tmds(sd) ? "false" : "true");
+	v4l2_info(sd, "SSPD locked: %s\n", no_lock_sspd(sd) ? "false" : "true");
+	v4l2_info(sd, "STDI locked: %s\n", no_lock_stdi(sd) ? "false" : "true");
+	v4l2_info(sd, "CP locked: %s\n", no_lock_cp(sd) ? "false" : "true");
+	v4l2_info(sd, "CP free run: %s\n",
+			(!!(cp_read(sd, 0xff) & 0x10) ? "on" : "off"));
+	v4l2_info(sd, "Prim-mode = 0x%x, video std = 0x%x\n",
+			io_read(sd, 0x01) & 0x0f, io_read(sd, 0x00) & 0x3f);
+
+	v4l2_info(sd, "-----Video Timings-----\n");
+	if (read_stdi(sd, &stdi))
+		v4l2_info(sd, "STDI: not locked\n");
+	else
+		v4l2_info(sd, "STDI: lcf (frame height - 1) = %d, bl = %d, lcvs (vsync) = %d, %s, %chsync, %cvsync\n",
+				stdi.lcf, stdi.bl, stdi.lcvs,
+				stdi.interlaced ? "interlaced" : "progressive",
+				stdi.hs_pol, stdi.vs_pol);
+	if (adv7604_query_dv_timings(sd, &timings))
+		v4l2_info(sd, "No video detected\n");
+	else
+		adv7604_print_timings(sd, &timings, "Detected format:", true);
+	adv7604_print_timings(sd, &state->timings, "Configured format:", true);
+
+	v4l2_info(sd, "-----Color space-----\n");
+	v4l2_info(sd, "RGB quantization range ctrl: %s\n",
+			rgb_quantization_range_txt[state->rgb_quantization_range]);
+	v4l2_info(sd, "Input color space: %s\n",
+			input_color_space_txt[reg_io_0x02 >> 4]);
+	v4l2_info(sd, "Output color space: %s %s, saturator %s\n",
+			(reg_io_0x02 & 0x02) ? "RGB" : "YCbCr",
+			(reg_io_0x02 & 0x04) ? "(16-235)" : "(0-255)",
+			((reg_io_0x02 & 0x04) ^ (reg_io_0x02 & 0x01)) ?
+					"enabled" : "disabled");
+	v4l2_info(sd, "Color space conversion: %s\n",
+			csc_coeff_sel_rb[cp_read(sd, 0xfc) >> 4]);
+
+	/* Digital video */
+	if (DIGITAL_INPUT) {
+		v4l2_info(sd, "-----HDMI status-----\n");
+		v4l2_info(sd, "HDCP encrypted content: %s\n",
+				hdmi_read(sd, 0x05) & 0x40 ? "true" : "false");
+
+		print_avi_infoframe(sd);
+	}
+
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static const struct v4l2_ctrl_ops adv7604_ctrl_ops = {
+	.s_ctrl = adv7604_s_ctrl,
+};
+
+static const struct v4l2_subdev_core_ops adv7604_core_ops = {
+	.log_status = adv7604_log_status,
+	.g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
+	.try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
+	.s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
+	.g_ctrl = v4l2_subdev_g_ctrl,
+	.s_ctrl = v4l2_subdev_s_ctrl,
+	.queryctrl = v4l2_subdev_queryctrl,
+	.querymenu = v4l2_subdev_querymenu,
+	.g_chip_ident = adv7604_g_chip_ident,
+	.interrupt_service_routine = adv7604_isr,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.g_register = adv7604_g_register,
+	.s_register = adv7604_s_register,
+#endif
+};
+
+static const struct v4l2_subdev_video_ops adv7604_video_ops = {
+	.s_routing = adv7604_s_routing,
+	.g_input_status = adv7604_g_input_status,
+	.s_dv_timings = adv7604_s_dv_timings,
+	.g_dv_timings = adv7604_g_dv_timings,
+	.query_dv_timings = adv7604_query_dv_timings,
+	.enum_dv_timings = adv7604_enum_dv_timings,
+	.dv_timings_cap = adv7604_dv_timings_cap,
+	.enum_mbus_fmt = adv7604_enum_mbus_fmt,
+	.g_mbus_fmt = adv7604_g_mbus_fmt,
+	.try_mbus_fmt = adv7604_g_mbus_fmt,
+	.s_mbus_fmt = adv7604_g_mbus_fmt,
+};
+
+static const struct v4l2_subdev_pad_ops adv7604_pad_ops = {
+	.get_edid = adv7604_get_edid,
+	.set_edid = adv7604_set_edid,
+};
+
+static const struct v4l2_subdev_ops adv7604_ops = {
+	.core = &adv7604_core_ops,
+	.video = &adv7604_video_ops,
+	.pad = &adv7604_pad_ops,
+};
+
+/* -------------------------- custom ctrls ---------------------------------- */
+
+static const struct v4l2_ctrl_config adv7604_ctrl_analog_sampling_phase = {
+	.ops = &adv7604_ctrl_ops,
+	.id = V4L2_CID_ADV_RX_ANALOG_SAMPLING_PHASE,
+	.name = "Analog Sampling Phase",
+	.type = V4L2_CTRL_TYPE_INTEGER,
+	.min = 0,
+	.max = 0x1f,
+	.step = 1,
+	.def = 0,
+};
+
+static const struct v4l2_ctrl_config adv7604_ctrl_free_run_color_manual = {
+	.ops = &adv7604_ctrl_ops,
+	.id = V4L2_CID_ADV_RX_FREE_RUN_COLOR_MANUAL,
+	.name = "Free Running Color, Manual",
+	.type = V4L2_CTRL_TYPE_BOOLEAN,
+	.min = false,
+	.max = true,
+	.step = 1,
+	.def = false,
+};
+
+static const struct v4l2_ctrl_config adv7604_ctrl_free_run_color = {
+	.ops = &adv7604_ctrl_ops,
+	.id = V4L2_CID_ADV_RX_FREE_RUN_COLOR,
+	.name = "Free Running Color",
+	.type = V4L2_CTRL_TYPE_INTEGER,
+	.min = 0x0,
+	.max = 0xffffff,
+	.step = 0x1,
+	.def = 0x0,
+};
+
+/* ----------------------------------------------------------------------- */
+
+static int adv7604_core_init(struct v4l2_subdev *sd)
+{
+	struct adv7604_state *state = to_state(sd);
+	struct adv7604_platform_data *pdata = &state->pdata;
+
+	hdmi_write(sd, 0x48,
+		(pdata->disable_pwrdnb ? 0x80 : 0) |
+		(pdata->disable_cable_det_rst ? 0x40 : 0));
+
+	disable_input(sd);
+
+	/* power */
+	io_write(sd, 0x0c, 0x42);   /* Power up part and power down VDP */
+	io_write(sd, 0x0b, 0x44);   /* Power down ESDP block */
+	cp_write(sd, 0xcf, 0x01);   /* Power down macrovision */
+
+	/* video format */
+	io_write_and_or(sd, 0x02, 0xf0,
+			pdata->alt_gamma << 3 |
+			pdata->op_656_range << 2 |
+			pdata->rgb_out << 1 |
+			pdata->alt_data_sat << 0);
+	io_write(sd, 0x03, pdata->op_format_sel);
+	io_write_and_or(sd, 0x04, 0x1f, pdata->op_ch_sel << 5);
+	io_write_and_or(sd, 0x05, 0xf0, pdata->blank_data << 3 |
+					pdata->insert_av_codes << 2 |
+					pdata->replicate_av_codes << 1 |
+					pdata->invert_cbcr << 0);
+
+	/* TODO from platform data */
+	cp_write(sd, 0x69, 0x30);   /* Enable CP CSC */
+	io_write(sd, 0x06, 0xa6);   /* positive VS and HS */
+	io_write(sd, 0x14, 0x7f);   /* Drive strength adjusted to max */
+	cp_write(sd, 0xba, (pdata->hdmi_free_run_mode << 1) | 0x01); /* HDMI free run */
+	cp_write(sd, 0xf3, 0xdc); /* Low threshold to enter/exit free run mode */
+	cp_write(sd, 0xf9, 0x23); /*  STDI ch. 1 - LCVS change threshold -
+				      ADI recommended setting [REF_01 c. 2.3.3] */
+	cp_write(sd, 0x45, 0x23); /*  STDI ch. 2 - LCVS change threshold -
+				      ADI recommended setting [REF_01 c. 2.3.3] */
+	cp_write(sd, 0xc9, 0x2d); /* use prim_mode and vid_std as free run resolution
+				     for digital formats */
+
+	/* TODO from platform data */
+	afe_write(sd, 0xb5, 0x01);  /* Setting MCLK to 256Fs */
+
+	afe_write(sd, 0x02, pdata->ain_sel); /* Select analog input muxing mode */
+	io_write_and_or(sd, 0x30, ~(1 << 4), pdata->output_bus_lsb_to_msb << 4);
+
+	state->prim_mode = pdata->prim_mode;
+	select_input(sd, pdata->prim_mode);
+
+	enable_input(sd, pdata->prim_mode);
+
+	/* interrupts */
+	io_write(sd, 0x40, 0xc2); /* Configure INT1 */
+	io_write(sd, 0x41, 0xd7); /* STDI irq for any change, disable INT2 */
+	io_write(sd, 0x46, 0x98); /* Enable SSPD, STDI and CP unlocked interrupts */
+	io_write(sd, 0x6e, 0xc0); /* Enable V_LOCKED and DE_REGEN_LCK interrupts */
+	io_write(sd, 0x73, 0x10); /* Enable CABLE_DET_A_ST (+5v) interrupt */
+
+	return v4l2_ctrl_handler_setup(sd->ctrl_handler);
+}
+
+static void adv7604_unregister_clients(struct adv7604_state *state)
+{
+	if (state->i2c_avlink)
+		i2c_unregister_device(state->i2c_avlink);
+	if (state->i2c_cec)
+		i2c_unregister_device(state->i2c_cec);
+	if (state->i2c_infoframe)
+		i2c_unregister_device(state->i2c_infoframe);
+	if (state->i2c_esdp)
+		i2c_unregister_device(state->i2c_esdp);
+	if (state->i2c_dpp)
+		i2c_unregister_device(state->i2c_dpp);
+	if (state->i2c_afe)
+		i2c_unregister_device(state->i2c_afe);
+	if (state->i2c_repeater)
+		i2c_unregister_device(state->i2c_repeater);
+	if (state->i2c_edid)
+		i2c_unregister_device(state->i2c_edid);
+	if (state->i2c_hdmi)
+		i2c_unregister_device(state->i2c_hdmi);
+	if (state->i2c_test)
+		i2c_unregister_device(state->i2c_test);
+	if (state->i2c_cp)
+		i2c_unregister_device(state->i2c_cp);
+	if (state->i2c_vdp)
+		i2c_unregister_device(state->i2c_vdp);
+}
+
+static struct i2c_client *adv7604_dummy_client(struct v4l2_subdev *sd,
+							u8 addr, u8 io_reg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	if (addr)
+		io_write(sd, io_reg, addr << 1);
+	return i2c_new_dummy(client->adapter, io_read(sd, io_reg) >> 1);
+}
+
+static int adv7604_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
+{
+	struct adv7604_state *state;
+	struct adv7604_platform_data *pdata = client->dev.platform_data;
+	struct v4l2_ctrl_handler *hdl;
+	struct v4l2_subdev *sd;
+	int err;
+
+	/* Check if the adapter supports the needed features */
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		return -EIO;
+	v4l_dbg(1, debug, client, "detecting adv7604 client on address 0x%x\n",
+			client->addr << 1);
+
+	state = kzalloc(sizeof(struct adv7604_state), GFP_KERNEL);
+	if (!state) {
+		v4l_err(client, "Could not allocate adv7604_state memory!\n");
+		return -ENOMEM;
+	}
+
+	/* platform data */
+	if (!pdata) {
+		v4l_err(client, "No platform data!\n");
+		err = -ENODEV;
+		goto err_state;
+	}
+	memcpy(&state->pdata, pdata, sizeof(state->pdata));
+
+	sd = &state->sd;
+	v4l2_i2c_subdev_init(sd, client, &adv7604_ops);
+	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+	state->connector_hdmi = pdata->connector_hdmi;
+
+	/* i2c access to adv7604? */
+	if (adv_smbus_read_byte_data_check(client, 0xfb, false) != 0x68) {
+		v4l2_info(sd, "not an adv7604 on address 0x%x\n",
+				client->addr << 1);
+		err = -ENODEV;
+		goto err_state;
+	}
+
+	/* control handlers */
+	hdl = &state->hdl;
+	v4l2_ctrl_handler_init(hdl, 9);
+
+	v4l2_ctrl_new_std(hdl, &adv7604_ctrl_ops,
+			V4L2_CID_BRIGHTNESS, -128, 127, 1, 0);
+	v4l2_ctrl_new_std(hdl, &adv7604_ctrl_ops,
+			V4L2_CID_CONTRAST, 0, 255, 1, 128);
+	v4l2_ctrl_new_std(hdl, &adv7604_ctrl_ops,
+			V4L2_CID_SATURATION, 0, 255, 1, 128);
+	v4l2_ctrl_new_std(hdl, &adv7604_ctrl_ops,
+			V4L2_CID_HUE, 0, 128, 1, 0);
+
+	/* private controls */
+	state->detect_tx_5v_ctrl = v4l2_ctrl_new_std(hdl, NULL,
+			V4L2_CID_DV_RX_POWER_PRESENT, 0, 1, 0, 0);
+	state->detect_tx_5v_ctrl->is_private = true;
+	state->rgb_quantization_range_ctrl =
+		v4l2_ctrl_new_std_menu(hdl, &adv7604_ctrl_ops,
+			V4L2_CID_DV_RX_RGB_RANGE, V4L2_DV_RGB_RANGE_FULL,
+			0, V4L2_DV_RGB_RANGE_AUTO);
+	state->rgb_quantization_range_ctrl->is_private = true;
+
+	/* custom controls */
+	state->analog_sampling_phase_ctrl =
+		v4l2_ctrl_new_custom(hdl, &adv7604_ctrl_analog_sampling_phase, NULL);
+	state->analog_sampling_phase_ctrl->is_private = true;
+	state->free_run_color_manual_ctrl =
+		v4l2_ctrl_new_custom(hdl, &adv7604_ctrl_free_run_color_manual, NULL);
+	state->free_run_color_manual_ctrl->is_private = true;
+	state->free_run_color_ctrl =
+		v4l2_ctrl_new_custom(hdl, &adv7604_ctrl_free_run_color, NULL);
+	state->free_run_color_ctrl->is_private = true;
+
+	sd->ctrl_handler = hdl;
+	if (hdl->error) {
+		err = hdl->error;
+		goto err_hdl;
+	}
+	if (adv7604_s_detect_tx_5v_ctrl(sd)) {
+		err = -ENODEV;
+		goto err_hdl;
+	}
+
+	state->i2c_avlink = adv7604_dummy_client(sd, pdata->i2c_avlink, 0xf3);
+	state->i2c_cec = adv7604_dummy_client(sd, pdata->i2c_cec, 0xf4);
+	state->i2c_infoframe = adv7604_dummy_client(sd, pdata->i2c_infoframe, 0xf5);
+	state->i2c_esdp = adv7604_dummy_client(sd, pdata->i2c_esdp, 0xf6);
+	state->i2c_dpp = adv7604_dummy_client(sd, pdata->i2c_dpp, 0xf7);
+	state->i2c_afe = adv7604_dummy_client(sd, pdata->i2c_afe, 0xf8);
+	state->i2c_repeater = adv7604_dummy_client(sd, pdata->i2c_repeater, 0xf9);
+	state->i2c_edid = adv7604_dummy_client(sd, pdata->i2c_edid, 0xfa);
+	state->i2c_hdmi = adv7604_dummy_client(sd, pdata->i2c_hdmi, 0xfb);
+	state->i2c_test = adv7604_dummy_client(sd, pdata->i2c_test, 0xfc);
+	state->i2c_cp = adv7604_dummy_client(sd, pdata->i2c_cp, 0xfd);
+	state->i2c_vdp = adv7604_dummy_client(sd, pdata->i2c_vdp, 0xfe);
+	if (!state->i2c_avlink || !state->i2c_cec || !state->i2c_infoframe ||
+	    !state->i2c_esdp || !state->i2c_dpp || !state->i2c_afe ||
+	    !state->i2c_repeater || !state->i2c_edid || !state->i2c_hdmi ||
+	    !state->i2c_test || !state->i2c_cp || !state->i2c_vdp) {
+		err = -ENOMEM;
+		v4l2_err(sd, "failed to create all i2c clients\n");
+		goto err_i2c;
+	}
+
+	/* work queues */
+	state->work_queues = create_singlethread_workqueue(client->name);
+	if (!state->work_queues) {
+		v4l2_err(sd, "Could not create work queue\n");
+		err = -ENOMEM;
+		goto err_i2c;
+	}
+
+	INIT_DELAYED_WORK(&state->delayed_work_enable_hotplug,
+			adv7604_delayed_work_enable_hotplug);
+
+	state->pad.flags = MEDIA_PAD_FL_SOURCE;
+	err = media_entity_init(&sd->entity, 1, &state->pad, 0);
+	if (err)
+		goto err_work_queues;
+
+	err = adv7604_core_init(sd);
+	if (err)
+		goto err_entity;
+	v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name,
+			client->addr << 1, client->adapter->name);
+	return 0;
+
+err_entity:
+	media_entity_cleanup(&sd->entity);
+err_work_queues:
+	cancel_delayed_work(&state->delayed_work_enable_hotplug);
+	destroy_workqueue(state->work_queues);
+err_i2c:
+	adv7604_unregister_clients(state);
+err_hdl:
+	v4l2_ctrl_handler_free(hdl);
+err_state:
+	kfree(state);
+	return err;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static int adv7604_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct adv7604_state *state = to_state(sd);
+
+	cancel_delayed_work(&state->delayed_work_enable_hotplug);
+	destroy_workqueue(state->work_queues);
+	v4l2_device_unregister_subdev(sd);
+	media_entity_cleanup(&sd->entity);
+	adv7604_unregister_clients(to_state(sd));
+	v4l2_ctrl_handler_free(sd->ctrl_handler);
+	kfree(to_state(sd));
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static struct i2c_device_id adv7604_id[] = {
+	{ "adv7604", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, adv7604_id);
+
+static struct i2c_driver adv7604_driver = {
+	.driver = {
+		.owner = THIS_MODULE,
+		.name = "adv7604",
+	},
+	.probe = adv7604_probe,
+	.remove = adv7604_remove,
+	.id_table = adv7604_id,
+};
+
+module_i2c_driver(adv7604_driver);
diff --git a/drivers/media/i2c/ak881x.c b/drivers/media/i2c/ak881x.c
new file mode 100644
index 0000000..ba67465
--- /dev/null
+++ b/drivers/media/i2c/ak881x.c
@@ -0,0 +1,359 @@
+/*
+ * Driver for AK8813 / AK8814 TV-ecoders from Asahi Kasei Microsystems Co., Ltd. (AKM)
+ *
+ * Copyright (C) 2010, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/videodev2.h>
+#include <linux/module.h>
+
+#include <media/ak881x.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-device.h>
+
+#define AK881X_INTERFACE_MODE	0
+#define AK881X_VIDEO_PROCESS1	1
+#define AK881X_VIDEO_PROCESS2	2
+#define AK881X_VIDEO_PROCESS3	3
+#define AK881X_DAC_MODE		5
+#define AK881X_STATUS		0x24
+#define AK881X_DEVICE_ID	0x25
+#define AK881X_DEVICE_REVISION	0x26
+
+struct ak881x {
+	struct v4l2_subdev subdev;
+	struct ak881x_pdata *pdata;
+	unsigned int lines;
+	int id;	/* DEVICE_ID code V4L2_IDENT_AK881X code from v4l2-chip-ident.h */
+	char revision;	/* DEVICE_REVISION content */
+};
+
+static int reg_read(struct i2c_client *client, const u8 reg)
+{
+	return i2c_smbus_read_byte_data(client, reg);
+}
+
+static int reg_write(struct i2c_client *client, const u8 reg,
+		     const u8 data)
+{
+	return i2c_smbus_write_byte_data(client, reg, data);
+}
+
+static int reg_set(struct i2c_client *client, const u8 reg,
+		   const u8 data, u8 mask)
+{
+	int ret = reg_read(client, reg);
+	if (ret < 0)
+		return ret;
+	return reg_write(client, reg, (ret & ~mask) | (data & mask));
+}
+
+static struct ak881x *to_ak881x(const struct i2c_client *client)
+{
+	return container_of(i2c_get_clientdata(client), struct ak881x, subdev);
+}
+
+static int ak881x_g_chip_ident(struct v4l2_subdev *sd,
+			       struct v4l2_dbg_chip_ident *id)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct ak881x *ak881x = to_ak881x(client);
+
+	if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
+		return -EINVAL;
+
+	if (id->match.addr != client->addr)
+		return -ENODEV;
+
+	id->ident	= ak881x->id;
+	id->revision	= ak881x->revision;
+
+	return 0;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int ak881x_g_register(struct v4l2_subdev *sd,
+			     struct v4l2_dbg_register *reg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x26)
+		return -EINVAL;
+
+	if (reg->match.addr != client->addr)
+		return -ENODEV;
+
+	reg->val = reg_read(client, reg->reg);
+
+	if (reg->val > 0xffff)
+		return -EIO;
+
+	return 0;
+}
+
+static int ak881x_s_register(struct v4l2_subdev *sd,
+			     struct v4l2_dbg_register *reg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x26)
+		return -EINVAL;
+
+	if (reg->match.addr != client->addr)
+		return -ENODEV;
+
+	if (reg_write(client, reg->reg, reg->val) < 0)
+		return -EIO;
+
+	return 0;
+}
+#endif
+
+static int ak881x_try_g_mbus_fmt(struct v4l2_subdev *sd,
+				 struct v4l2_mbus_framefmt *mf)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct ak881x *ak881x = to_ak881x(client);
+
+	v4l_bound_align_image(&mf->width, 0, 720, 2,
+			      &mf->height, 0, ak881x->lines, 1, 0);
+	mf->field	= V4L2_FIELD_INTERLACED;
+	mf->code	= V4L2_MBUS_FMT_YUYV8_2X8;
+	mf->colorspace	= V4L2_COLORSPACE_SMPTE170M;
+
+	return 0;
+}
+
+static int ak881x_s_mbus_fmt(struct v4l2_subdev *sd,
+			     struct v4l2_mbus_framefmt *mf)
+{
+	if (mf->field != V4L2_FIELD_INTERLACED ||
+	    mf->code != V4L2_MBUS_FMT_YUYV8_2X8)
+		return -EINVAL;
+
+	return ak881x_try_g_mbus_fmt(sd, mf);
+}
+
+static int ak881x_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned int index,
+				enum v4l2_mbus_pixelcode *code)
+{
+	if (index)
+		return -EINVAL;
+
+	*code = V4L2_MBUS_FMT_YUYV8_2X8;
+	return 0;
+}
+
+static int ak881x_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct ak881x *ak881x = to_ak881x(client);
+
+	a->bounds.left			= 0;
+	a->bounds.top			= 0;
+	a->bounds.width			= 720;
+	a->bounds.height		= ak881x->lines;
+	a->defrect			= a->bounds;
+	a->type				= V4L2_BUF_TYPE_VIDEO_OUTPUT;
+	a->pixelaspect.numerator	= 1;
+	a->pixelaspect.denominator	= 1;
+
+	return 0;
+}
+
+static int ak881x_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct ak881x *ak881x = to_ak881x(client);
+	u8 vp1;
+
+	if (std == V4L2_STD_NTSC_443) {
+		vp1 = 3;
+		ak881x->lines = 480;
+	} else if (std == V4L2_STD_PAL_M) {
+		vp1 = 5;
+		ak881x->lines = 480;
+	} else if (std == V4L2_STD_PAL_60) {
+		vp1 = 7;
+		ak881x->lines = 480;
+	} else if (std && !(std & ~V4L2_STD_PAL)) {
+		vp1 = 0xf;
+		ak881x->lines = 576;
+	} else if (std && !(std & ~V4L2_STD_NTSC)) {
+		vp1 = 0;
+		ak881x->lines = 480;
+	} else {
+		/* No SECAM or PAL_N/Nc supported */
+		return -EINVAL;
+	}
+
+	reg_set(client, AK881X_VIDEO_PROCESS1, vp1, 0xf);
+
+	return 0;
+}
+
+static int ak881x_s_stream(struct v4l2_subdev *sd, int enable)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct ak881x *ak881x = to_ak881x(client);
+
+	if (enable) {
+		u8 dac;
+		/* For colour-bar testing set bit 6 of AK881X_VIDEO_PROCESS1 */
+		/* Default: composite output */
+		if (ak881x->pdata->flags & AK881X_COMPONENT)
+			dac = 3;
+		else
+			dac = 4;
+		/* Turn on the DAC(s) */
+		reg_write(client, AK881X_DAC_MODE, dac);
+		dev_dbg(&client->dev, "chip status 0x%x\n",
+			reg_read(client, AK881X_STATUS));
+	} else {
+		/* ...and clear bit 6 of AK881X_VIDEO_PROCESS1 here */
+		reg_write(client, AK881X_DAC_MODE, 0);
+		dev_dbg(&client->dev, "chip status 0x%x\n",
+			reg_read(client, AK881X_STATUS));
+	}
+
+	return 0;
+}
+
+static struct v4l2_subdev_core_ops ak881x_subdev_core_ops = {
+	.g_chip_ident	= ak881x_g_chip_ident,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.g_register	= ak881x_g_register,
+	.s_register	= ak881x_s_register,
+#endif
+};
+
+static struct v4l2_subdev_video_ops ak881x_subdev_video_ops = {
+	.s_mbus_fmt	= ak881x_s_mbus_fmt,
+	.g_mbus_fmt	= ak881x_try_g_mbus_fmt,
+	.try_mbus_fmt	= ak881x_try_g_mbus_fmt,
+	.cropcap	= ak881x_cropcap,
+	.enum_mbus_fmt	= ak881x_enum_mbus_fmt,
+	.s_std_output	= ak881x_s_std_output,
+	.s_stream	= ak881x_s_stream,
+};
+
+static struct v4l2_subdev_ops ak881x_subdev_ops = {
+	.core	= &ak881x_subdev_core_ops,
+	.video	= &ak881x_subdev_video_ops,
+};
+
+static int ak881x_probe(struct i2c_client *client,
+			const struct i2c_device_id *did)
+{
+	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+	struct ak881x *ak881x;
+	u8 ifmode, data;
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
+		dev_warn(&adapter->dev,
+			 "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n");
+		return -EIO;
+	}
+
+	ak881x = kzalloc(sizeof(struct ak881x), GFP_KERNEL);
+	if (!ak881x)
+		return -ENOMEM;
+
+	v4l2_i2c_subdev_init(&ak881x->subdev, client, &ak881x_subdev_ops);
+
+	data = reg_read(client, AK881X_DEVICE_ID);
+
+	switch (data) {
+	case 0x13:
+		ak881x->id = V4L2_IDENT_AK8813;
+		break;
+	case 0x14:
+		ak881x->id = V4L2_IDENT_AK8814;
+		break;
+	default:
+		dev_err(&client->dev,
+			"No ak881x chip detected, register read %x\n", data);
+		kfree(ak881x);
+		return -ENODEV;
+	}
+
+	ak881x->revision = reg_read(client, AK881X_DEVICE_REVISION);
+	ak881x->pdata = client->dev.platform_data;
+
+	if (ak881x->pdata) {
+		if (ak881x->pdata->flags & AK881X_FIELD)
+			ifmode = 4;
+		else
+			ifmode = 0;
+
+		switch (ak881x->pdata->flags & AK881X_IF_MODE_MASK) {
+		case AK881X_IF_MODE_BT656:
+			ifmode |= 1;
+			break;
+		case AK881X_IF_MODE_MASTER:
+			ifmode |= 2;
+			break;
+		case AK881X_IF_MODE_SLAVE:
+		default:
+			break;
+		}
+
+		dev_dbg(&client->dev, "IF mode %x\n", ifmode);
+
+		/*
+		 * "Line Blanking No." seems to be the same as the number of
+		 * "black" lines on, e.g., SuperH VOU, whose default value of 20
+		 * "incidentally" matches ak881x' default
+		 */
+		reg_write(client, AK881X_INTERFACE_MODE, ifmode | (20 << 3));
+	}
+
+	/* Hardware default: NTSC-M */
+	ak881x->lines = 480;
+
+	dev_info(&client->dev, "Detected an ak881x chip ID %x, revision %x\n",
+		 data, ak881x->revision);
+
+	return 0;
+}
+
+static int ak881x_remove(struct i2c_client *client)
+{
+	struct ak881x *ak881x = to_ak881x(client);
+
+	v4l2_device_unregister_subdev(&ak881x->subdev);
+	kfree(ak881x);
+
+	return 0;
+}
+
+static const struct i2c_device_id ak881x_id[] = {
+	{ "ak8813", 0 },
+	{ "ak8814", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, ak881x_id);
+
+static struct i2c_driver ak881x_i2c_driver = {
+	.driver = {
+		.name = "ak881x",
+	},
+	.probe		= ak881x_probe,
+	.remove		= ak881x_remove,
+	.id_table	= ak881x_id,
+};
+
+module_i2c_driver(ak881x_i2c_driver);
+
+MODULE_DESCRIPTION("TV-output driver for ak8813/ak8814");
+MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/i2c/aptina-pll.c b/drivers/media/i2c/aptina-pll.c
new file mode 100644
index 0000000..8153a44
--- /dev/null
+++ b/drivers/media/i2c/aptina-pll.c
@@ -0,0 +1,173 @@
+/*
+ * Aptina Sensor PLL Configuration
+ *
+ * Copyright (C) 2012 Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <linux/device.h>
+#include <linux/gcd.h>
+#include <linux/kernel.h>
+#include <linux/lcm.h>
+#include <linux/module.h>
+
+#include "aptina-pll.h"
+
+int aptina_pll_calculate(struct device *dev,
+			 const struct aptina_pll_limits *limits,
+			 struct aptina_pll *pll)
+{
+	unsigned int mf_min;
+	unsigned int mf_max;
+	unsigned int p1_min;
+	unsigned int p1_max;
+	unsigned int p1;
+	unsigned int div;
+
+	dev_dbg(dev, "PLL: ext clock %u pix clock %u\n",
+		pll->ext_clock, pll->pix_clock);
+
+	if (pll->ext_clock < limits->ext_clock_min ||
+	    pll->ext_clock > limits->ext_clock_max) {
+		dev_err(dev, "pll: invalid external clock frequency.\n");
+		return -EINVAL;
+	}
+
+	if (pll->pix_clock == 0 || pll->pix_clock > limits->pix_clock_max) {
+		dev_err(dev, "pll: invalid pixel clock frequency.\n");
+		return -EINVAL;
+	}
+
+	/* Compute the multiplier M and combined N*P1 divisor. */
+	div = gcd(pll->pix_clock, pll->ext_clock);
+	pll->m = pll->pix_clock / div;
+	div = pll->ext_clock / div;
+
+	/* We now have the smallest M and N*P1 values that will result in the
+	 * desired pixel clock frequency, but they might be out of the valid
+	 * range. Compute the factor by which we should multiply them given the
+	 * following constraints:
+	 *
+	 * - minimum/maximum multiplier
+	 * - minimum/maximum multiplier output clock frequency assuming the
+	 *   minimum/maximum N value
+	 * - minimum/maximum combined N*P1 divisor
+	 */
+	mf_min = DIV_ROUND_UP(limits->m_min, pll->m);
+	mf_min = max(mf_min, limits->out_clock_min /
+		     (pll->ext_clock / limits->n_min * pll->m));
+	mf_min = max(mf_min, limits->n_min * limits->p1_min / div);
+	mf_max = limits->m_max / pll->m;
+	mf_max = min(mf_max, limits->out_clock_max /
+		    (pll->ext_clock / limits->n_max * pll->m));
+	mf_max = min(mf_max, DIV_ROUND_UP(limits->n_max * limits->p1_max, div));
+
+	dev_dbg(dev, "pll: mf min %u max %u\n", mf_min, mf_max);
+	if (mf_min > mf_max) {
+		dev_err(dev, "pll: no valid combined N*P1 divisor.\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * We're looking for the highest acceptable P1 value for which a
+	 * multiplier factor MF exists that fulfills the following conditions:
+	 *
+	 * 1. p1 is in the [p1_min, p1_max] range given by the limits and is
+	 *    even
+	 * 2. mf is in the [mf_min, mf_max] range computed above
+	 * 3. div * mf is a multiple of p1, in order to compute
+	 *	n = div * mf / p1
+	 *	m = pll->m * mf
+	 * 4. the internal clock frequency, given by ext_clock / n, is in the
+	 *    [int_clock_min, int_clock_max] range given by the limits
+	 * 5. the output clock frequency, given by ext_clock / n * m, is in the
+	 *    [out_clock_min, out_clock_max] range given by the limits
+	 *
+	 * The first naive approach is to iterate over all p1 values acceptable
+	 * according to (1) and all mf values acceptable according to (2), and
+	 * stop at the first combination that fulfills (3), (4) and (5). This
+	 * has a O(n^2) complexity.
+	 *
+	 * Instead of iterating over all mf values in the [mf_min, mf_max] range
+	 * we can compute the mf increment between two acceptable values
+	 * according to (3) with
+	 *
+	 *	mf_inc = p1 / gcd(div, p1)			(6)
+	 *
+	 * and round the minimum up to the nearest multiple of mf_inc. This will
+	 * restrict the number of mf values to be checked.
+	 *
+	 * Furthermore, conditions (4) and (5) only restrict the range of
+	 * acceptable p1 and mf values by modifying the minimum and maximum
+	 * limits. (5) can be expressed as
+	 *
+	 *	ext_clock / (div * mf / p1) * m * mf >= out_clock_min
+	 *	ext_clock / (div * mf / p1) * m * mf <= out_clock_max
+	 *
+	 * or
+	 *
+	 *	p1 >= out_clock_min * div / (ext_clock * m)	(7)
+	 *	p1 <= out_clock_max * div / (ext_clock * m)
+	 *
+	 * Similarly, (4) can be expressed as
+	 *
+	 *	mf >= ext_clock * p1 / (int_clock_max * div)	(8)
+	 *	mf <= ext_clock * p1 / (int_clock_min * div)
+	 *
+	 * We can thus iterate over the restricted p1 range defined by the
+	 * combination of (1) and (7), and then compute the restricted mf range
+	 * defined by the combination of (2), (6) and (8). If the resulting mf
+	 * range is not empty, any value in the mf range is acceptable. We thus
+	 * select the mf lwoer bound and the corresponding p1 value.
+	 */
+	if (limits->p1_min == 0) {
+		dev_err(dev, "pll: P1 minimum value must be >0.\n");
+		return -EINVAL;
+	}
+
+	p1_min = max(limits->p1_min, DIV_ROUND_UP(limits->out_clock_min * div,
+		     pll->ext_clock * pll->m));
+	p1_max = min(limits->p1_max, limits->out_clock_max * div /
+		     (pll->ext_clock * pll->m));
+
+	for (p1 = p1_max & ~1; p1 >= p1_min; p1 -= 2) {
+		unsigned int mf_inc = p1 / gcd(div, p1);
+		unsigned int mf_high;
+		unsigned int mf_low;
+
+		mf_low = roundup(max(mf_min, DIV_ROUND_UP(pll->ext_clock * p1,
+					limits->int_clock_max * div)), mf_inc);
+		mf_high = min(mf_max, pll->ext_clock * p1 /
+			      (limits->int_clock_min * div));
+
+		if (mf_low > mf_high)
+			continue;
+
+		pll->n = div * mf_low / p1;
+		pll->m *= mf_low;
+		pll->p1 = p1;
+		dev_dbg(dev, "PLL: N %u M %u P1 %u\n", pll->n, pll->m, pll->p1);
+		return 0;
+	}
+
+	dev_err(dev, "pll: no valid N and P1 divisors found.\n");
+	return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(aptina_pll_calculate);
+
+MODULE_DESCRIPTION("Aptina PLL Helpers");
+MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/i2c/aptina-pll.h b/drivers/media/i2c/aptina-pll.h
new file mode 100644
index 0000000..b370e34
--- /dev/null
+++ b/drivers/media/i2c/aptina-pll.h
@@ -0,0 +1,56 @@
+/*
+ * Aptina Sensor PLL Configuration
+ *
+ * Copyright (C) 2012 Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#ifndef __APTINA_PLL_H
+#define __APTINA_PLL_H
+
+struct aptina_pll {
+	unsigned int ext_clock;
+	unsigned int pix_clock;
+
+	unsigned int n;
+	unsigned int m;
+	unsigned int p1;
+};
+
+struct aptina_pll_limits {
+	unsigned int ext_clock_min;
+	unsigned int ext_clock_max;
+	unsigned int int_clock_min;
+	unsigned int int_clock_max;
+	unsigned int out_clock_min;
+	unsigned int out_clock_max;
+	unsigned int pix_clock_max;
+
+	unsigned int n_min;
+	unsigned int n_max;
+	unsigned int m_min;
+	unsigned int m_max;
+	unsigned int p1_min;
+	unsigned int p1_max;
+};
+
+struct device;
+
+int aptina_pll_calculate(struct device *dev,
+			 const struct aptina_pll_limits *limits,
+			 struct aptina_pll *pll);
+
+#endif /* __APTINA_PLL_H */
diff --git a/drivers/media/i2c/as3645a.c b/drivers/media/i2c/as3645a.c
new file mode 100644
index 0000000..3bfdbf9
--- /dev/null
+++ b/drivers/media/i2c/as3645a.c
@@ -0,0 +1,888 @@
+/*
+ * drivers/media/i2c/as3645a.c - AS3645A and LM3555 flash controllers driver
+ *
+ * Copyright (C) 2008-2011 Nokia Corporation
+ * Copyright (c) 2011, Intel Corporation.
+ *
+ * Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ * TODO:
+ * - Check hardware FSTROBE control when sensor driver add support for this
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+
+#include <media/as3645a.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+
+#define AS_TIMER_MS_TO_CODE(t)			(((t) - 100) / 50)
+#define AS_TIMER_CODE_TO_MS(c)			(50 * (c) + 100)
+
+/* Register definitions */
+
+/* Read-only Design info register: Reset state: xxxx 0001 */
+#define AS_DESIGN_INFO_REG			0x00
+#define AS_DESIGN_INFO_FACTORY(x)		(((x) >> 4))
+#define AS_DESIGN_INFO_MODEL(x)			((x) & 0x0f)
+
+/* Read-only Version control register: Reset state: 0000 0000
+ * for first engineering samples
+ */
+#define AS_VERSION_CONTROL_REG			0x01
+#define AS_VERSION_CONTROL_RFU(x)		(((x) >> 4))
+#define AS_VERSION_CONTROL_VERSION(x)		((x) & 0x0f)
+
+/* Read / Write	(Indicator and timer register): Reset state: 0000 1111 */
+#define AS_INDICATOR_AND_TIMER_REG		0x02
+#define AS_INDICATOR_AND_TIMER_TIMEOUT_SHIFT	0
+#define AS_INDICATOR_AND_TIMER_VREF_SHIFT	4
+#define AS_INDICATOR_AND_TIMER_INDICATOR_SHIFT	6
+
+/* Read / Write	(Current set register): Reset state: 0110 1001 */
+#define AS_CURRENT_SET_REG			0x03
+#define AS_CURRENT_ASSIST_LIGHT_SHIFT		0
+#define AS_CURRENT_LED_DET_ON			(1 << 3)
+#define AS_CURRENT_FLASH_CURRENT_SHIFT		4
+
+/* Read / Write	(Control register): Reset state: 1011 0100 */
+#define AS_CONTROL_REG				0x04
+#define AS_CONTROL_MODE_SETTING_SHIFT		0
+#define AS_CONTROL_STROBE_ON			(1 << 2)
+#define AS_CONTROL_OUT_ON			(1 << 3)
+#define AS_CONTROL_EXT_TORCH_ON			(1 << 4)
+#define AS_CONTROL_STROBE_TYPE_EDGE		(0 << 5)
+#define AS_CONTROL_STROBE_TYPE_LEVEL		(1 << 5)
+#define AS_CONTROL_COIL_PEAK_SHIFT		6
+
+/* Read only (D3 is read / write) (Fault and info): Reset state: 0000 x000 */
+#define AS_FAULT_INFO_REG			0x05
+#define AS_FAULT_INFO_INDUCTOR_PEAK_LIMIT	(1 << 1)
+#define AS_FAULT_INFO_INDICATOR_LED		(1 << 2)
+#define AS_FAULT_INFO_LED_AMOUNT		(1 << 3)
+#define AS_FAULT_INFO_TIMEOUT			(1 << 4)
+#define AS_FAULT_INFO_OVER_TEMPERATURE		(1 << 5)
+#define AS_FAULT_INFO_SHORT_CIRCUIT		(1 << 6)
+#define AS_FAULT_INFO_OVER_VOLTAGE		(1 << 7)
+
+/* Boost register */
+#define AS_BOOST_REG				0x0d
+#define AS_BOOST_CURRENT_DISABLE		(0 << 0)
+#define AS_BOOST_CURRENT_ENABLE			(1 << 0)
+
+/* Password register is used to unlock boost register writing */
+#define AS_PASSWORD_REG				0x0f
+#define AS_PASSWORD_UNLOCK_VALUE		0x55
+
+enum as_mode {
+	AS_MODE_EXT_TORCH = 0 << AS_CONTROL_MODE_SETTING_SHIFT,
+	AS_MODE_INDICATOR = 1 << AS_CONTROL_MODE_SETTING_SHIFT,
+	AS_MODE_ASSIST = 2 << AS_CONTROL_MODE_SETTING_SHIFT,
+	AS_MODE_FLASH = 3 << AS_CONTROL_MODE_SETTING_SHIFT,
+};
+
+/*
+ * struct as3645a
+ *
+ * @subdev:		V4L2 subdev
+ * @pdata:		Flash platform data
+ * @power_lock:		Protects power_count
+ * @power_count:	Power reference count
+ * @led_mode:		V4L2 flash LED mode
+ * @timeout:		Flash timeout in microseconds
+ * @flash_current:	Flash current (0=200mA ... 15=500mA). Maximum
+ *			values are 400mA for two LEDs and 500mA for one LED.
+ * @assist_current:	Torch/Assist light current (0=20mA, 1=40mA ... 7=160mA)
+ * @indicator_current:	Indicator LED current (0=0mA, 1=2.5mA ... 4=10mA)
+ * @strobe_source:	Flash strobe source (software or external)
+ */
+struct as3645a {
+	struct v4l2_subdev subdev;
+	const struct as3645a_platform_data *pdata;
+
+	struct mutex power_lock;
+	int power_count;
+
+	/* Controls */
+	struct v4l2_ctrl_handler ctrls;
+
+	enum v4l2_flash_led_mode led_mode;
+	unsigned int timeout;
+	u8 flash_current;
+	u8 assist_current;
+	u8 indicator_current;
+	enum v4l2_flash_strobe_source strobe_source;
+};
+
+#define to_as3645a(sd) container_of(sd, struct as3645a, subdev)
+
+/* Return negative errno else zero on success */
+static int as3645a_write(struct as3645a *flash, u8 addr, u8 val)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&flash->subdev);
+	int rval;
+
+	rval = i2c_smbus_write_byte_data(client, addr, val);
+
+	dev_dbg(&client->dev, "Write Addr:%02X Val:%02X %s\n", addr, val,
+		rval < 0 ? "fail" : "ok");
+
+	return rval;
+}
+
+/* Return negative errno else a data byte received from the device. */
+static int as3645a_read(struct as3645a *flash, u8 addr)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&flash->subdev);
+	int rval;
+
+	rval = i2c_smbus_read_byte_data(client, addr);
+
+	dev_dbg(&client->dev, "Read Addr:%02X Val:%02X %s\n", addr, rval,
+		rval < 0 ? "fail" : "ok");
+
+	return rval;
+}
+
+/* -----------------------------------------------------------------------------
+ * Hardware configuration and trigger
+ */
+
+/*
+ * as3645a_set_config - Set flash configuration registers
+ * @flash: The flash
+ *
+ * Configure the hardware with flash, assist and indicator currents, as well as
+ * flash timeout.
+ *
+ * Return 0 on success, or a negative error code if an I2C communication error
+ * occurred.
+ */
+static int as3645a_set_config(struct as3645a *flash)
+{
+	int ret;
+	u8 val;
+
+	val = (flash->flash_current << AS_CURRENT_FLASH_CURRENT_SHIFT)
+	    | (flash->assist_current << AS_CURRENT_ASSIST_LIGHT_SHIFT)
+	    | AS_CURRENT_LED_DET_ON;
+
+	ret = as3645a_write(flash, AS_CURRENT_SET_REG, val);
+	if (ret < 0)
+		return ret;
+
+	val = AS_TIMER_MS_TO_CODE(flash->timeout / 1000)
+		    << AS_INDICATOR_AND_TIMER_TIMEOUT_SHIFT;
+
+	val |= (flash->pdata->vref << AS_INDICATOR_AND_TIMER_VREF_SHIFT)
+	    |  ((flash->indicator_current ? flash->indicator_current - 1 : 0)
+		 << AS_INDICATOR_AND_TIMER_INDICATOR_SHIFT);
+
+	return as3645a_write(flash, AS_INDICATOR_AND_TIMER_REG, val);
+}
+
+/*
+ * as3645a_set_control - Set flash control register
+ * @flash: The flash
+ * @mode: Desired output mode
+ * @on: Desired output state
+ *
+ * Configure the hardware with output mode and state.
+ *
+ * Return 0 on success, or a negative error code if an I2C communication error
+ * occurred.
+ */
+static int
+as3645a_set_control(struct as3645a *flash, enum as_mode mode, bool on)
+{
+	u8 reg;
+
+	/* Configure output parameters and operation mode. */
+	reg = (flash->pdata->peak << AS_CONTROL_COIL_PEAK_SHIFT)
+	    | (on ? AS_CONTROL_OUT_ON : 0)
+	    | mode;
+
+	if (flash->led_mode == V4L2_FLASH_LED_MODE_FLASH &&
+	    flash->strobe_source == V4L2_FLASH_STROBE_SOURCE_EXTERNAL) {
+		reg |= AS_CONTROL_STROBE_TYPE_LEVEL
+		    |  AS_CONTROL_STROBE_ON;
+	}
+
+	return as3645a_write(flash, AS_CONTROL_REG, reg);
+}
+
+/*
+ * as3645a_set_output - Configure output and operation mode
+ * @flash: Flash controller
+ * @strobe: Strobe the flash (only valid in flash mode)
+ *
+ * Turn the LEDs output on/off and set the operation mode based on the current
+ * parameters.
+ *
+ * The AS3645A can't control the indicator LED independently of the flash/torch
+ * LED. If the flash controller is in V4L2_FLASH_LED_MODE_NONE mode, set the
+ * chip to indicator mode. Otherwise set it to assist light (torch) or flash
+ * mode.
+ *
+ * In indicator and assist modes, turn the output on/off based on the indicator
+ * and torch currents. In software strobe flash mode, turn the output on/off
+ * based on the strobe parameter.
+ */
+static int as3645a_set_output(struct as3645a *flash, bool strobe)
+{
+	enum as_mode mode;
+	bool on;
+
+	switch (flash->led_mode) {
+	case V4L2_FLASH_LED_MODE_NONE:
+		on = flash->indicator_current != 0;
+		mode = AS_MODE_INDICATOR;
+		break;
+	case V4L2_FLASH_LED_MODE_TORCH:
+		on = true;
+		mode = AS_MODE_ASSIST;
+		break;
+	case V4L2_FLASH_LED_MODE_FLASH:
+		on = strobe;
+		mode = AS_MODE_FLASH;
+		break;
+	default:
+		BUG();
+	}
+
+	/* Configure output parameters and operation mode. */
+	return as3645a_set_control(flash, mode, on);
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 controls
+ */
+
+static int as3645a_is_active(struct as3645a *flash)
+{
+	int ret;
+
+	ret = as3645a_read(flash, AS_CONTROL_REG);
+	return ret < 0 ? ret : !!(ret & AS_CONTROL_OUT_ON);
+}
+
+static int as3645a_read_fault(struct as3645a *flash)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&flash->subdev);
+	int rval;
+
+	/* NOTE: reading register clear fault status */
+	rval = as3645a_read(flash, AS_FAULT_INFO_REG);
+	if (rval < 0)
+		return rval;
+
+	if (rval & AS_FAULT_INFO_INDUCTOR_PEAK_LIMIT)
+		dev_dbg(&client->dev, "Inductor Peak limit fault\n");
+
+	if (rval & AS_FAULT_INFO_INDICATOR_LED)
+		dev_dbg(&client->dev, "Indicator LED fault: "
+			"Short circuit or open loop\n");
+
+	dev_dbg(&client->dev, "%u connected LEDs\n",
+		rval & AS_FAULT_INFO_LED_AMOUNT ? 2 : 1);
+
+	if (rval & AS_FAULT_INFO_TIMEOUT)
+		dev_dbg(&client->dev, "Timeout fault\n");
+
+	if (rval & AS_FAULT_INFO_OVER_TEMPERATURE)
+		dev_dbg(&client->dev, "Over temperature fault\n");
+
+	if (rval & AS_FAULT_INFO_SHORT_CIRCUIT)
+		dev_dbg(&client->dev, "Short circuit fault\n");
+
+	if (rval & AS_FAULT_INFO_OVER_VOLTAGE)
+		dev_dbg(&client->dev, "Over voltage fault: "
+			"Indicates missing capacitor or open connection\n");
+
+	return rval;
+}
+
+static int as3645a_get_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct as3645a *flash =
+		container_of(ctrl->handler, struct as3645a, ctrls);
+	struct i2c_client *client = v4l2_get_subdevdata(&flash->subdev);
+	int value;
+
+	switch (ctrl->id) {
+	case V4L2_CID_FLASH_FAULT:
+		value = as3645a_read_fault(flash);
+		if (value < 0)
+			return value;
+
+		ctrl->cur.val = 0;
+		if (value & AS_FAULT_INFO_SHORT_CIRCUIT)
+			ctrl->cur.val |= V4L2_FLASH_FAULT_SHORT_CIRCUIT;
+		if (value & AS_FAULT_INFO_OVER_TEMPERATURE)
+			ctrl->cur.val |= V4L2_FLASH_FAULT_OVER_TEMPERATURE;
+		if (value & AS_FAULT_INFO_TIMEOUT)
+			ctrl->cur.val |= V4L2_FLASH_FAULT_TIMEOUT;
+		if (value & AS_FAULT_INFO_OVER_VOLTAGE)
+			ctrl->cur.val |= V4L2_FLASH_FAULT_OVER_VOLTAGE;
+		if (value & AS_FAULT_INFO_INDUCTOR_PEAK_LIMIT)
+			ctrl->cur.val |= V4L2_FLASH_FAULT_OVER_CURRENT;
+		if (value & AS_FAULT_INFO_INDICATOR_LED)
+			ctrl->cur.val |= V4L2_FLASH_FAULT_INDICATOR;
+		break;
+
+	case V4L2_CID_FLASH_STROBE_STATUS:
+		if (flash->led_mode != V4L2_FLASH_LED_MODE_FLASH) {
+			ctrl->cur.val = 0;
+			break;
+		}
+
+		value = as3645a_is_active(flash);
+		if (value < 0)
+			return value;
+
+		ctrl->cur.val = value;
+		break;
+	}
+
+	dev_dbg(&client->dev, "G_CTRL %08x:%d\n", ctrl->id, ctrl->cur.val);
+
+	return 0;
+}
+
+static int as3645a_set_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct as3645a *flash =
+		container_of(ctrl->handler, struct as3645a, ctrls);
+	struct i2c_client *client = v4l2_get_subdevdata(&flash->subdev);
+	int ret;
+
+	dev_dbg(&client->dev, "S_CTRL %08x:%d\n", ctrl->id, ctrl->val);
+
+	/* If a control that doesn't apply to the current mode is modified,
+	 * we store the value and return immediately. The setting will be
+	 * applied when the LED mode is changed. Otherwise we apply the setting
+	 * immediately.
+	 */
+
+	switch (ctrl->id) {
+	case V4L2_CID_FLASH_LED_MODE:
+		if (flash->indicator_current)
+			return -EBUSY;
+
+		ret = as3645a_set_config(flash);
+		if (ret < 0)
+			return ret;
+
+		flash->led_mode = ctrl->val;
+		return as3645a_set_output(flash, false);
+
+	case V4L2_CID_FLASH_STROBE_SOURCE:
+		flash->strobe_source = ctrl->val;
+
+		/* Applies to flash mode only. */
+		if (flash->led_mode != V4L2_FLASH_LED_MODE_FLASH)
+			break;
+
+		return as3645a_set_output(flash, false);
+
+	case V4L2_CID_FLASH_STROBE:
+		if (flash->led_mode != V4L2_FLASH_LED_MODE_FLASH)
+			return -EBUSY;
+
+		return as3645a_set_output(flash, true);
+
+	case V4L2_CID_FLASH_STROBE_STOP:
+		if (flash->led_mode != V4L2_FLASH_LED_MODE_FLASH)
+			return -EBUSY;
+
+		return as3645a_set_output(flash, false);
+
+	case V4L2_CID_FLASH_TIMEOUT:
+		flash->timeout = ctrl->val;
+
+		/* Applies to flash mode only. */
+		if (flash->led_mode != V4L2_FLASH_LED_MODE_FLASH)
+			break;
+
+		return as3645a_set_config(flash);
+
+	case V4L2_CID_FLASH_INTENSITY:
+		flash->flash_current = (ctrl->val - AS3645A_FLASH_INTENSITY_MIN)
+				     / AS3645A_FLASH_INTENSITY_STEP;
+
+		/* Applies to flash mode only. */
+		if (flash->led_mode != V4L2_FLASH_LED_MODE_FLASH)
+			break;
+
+		return as3645a_set_config(flash);
+
+	case V4L2_CID_FLASH_TORCH_INTENSITY:
+		flash->assist_current =
+			(ctrl->val - AS3645A_TORCH_INTENSITY_MIN)
+			/ AS3645A_TORCH_INTENSITY_STEP;
+
+		/* Applies to torch mode only. */
+		if (flash->led_mode != V4L2_FLASH_LED_MODE_TORCH)
+			break;
+
+		return as3645a_set_config(flash);
+
+	case V4L2_CID_FLASH_INDICATOR_INTENSITY:
+		if (flash->led_mode != V4L2_FLASH_LED_MODE_NONE)
+			return -EBUSY;
+
+		flash->indicator_current =
+			(ctrl->val - AS3645A_INDICATOR_INTENSITY_MIN)
+			/ AS3645A_INDICATOR_INTENSITY_STEP;
+
+		ret = as3645a_set_config(flash);
+		if (ret < 0)
+			return ret;
+
+		if ((ctrl->val == 0) == (ctrl->cur.val == 0))
+			break;
+
+		return as3645a_set_output(flash, false);
+	}
+
+	return 0;
+}
+
+static const struct v4l2_ctrl_ops as3645a_ctrl_ops = {
+	.g_volatile_ctrl = as3645a_get_ctrl,
+	.s_ctrl = as3645a_set_ctrl,
+};
+
+/* -----------------------------------------------------------------------------
+ * V4L2 subdev core operations
+ */
+
+/* Put device into know state. */
+static int as3645a_setup(struct as3645a *flash)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&flash->subdev);
+	int ret;
+
+	/* clear errors */
+	ret = as3645a_read(flash, AS_FAULT_INFO_REG);
+	if (ret < 0)
+		return ret;
+
+	dev_dbg(&client->dev, "Fault info: %02x\n", ret);
+
+	ret = as3645a_set_config(flash);
+	if (ret < 0)
+		return ret;
+
+	ret = as3645a_set_output(flash, false);
+	if (ret < 0)
+		return ret;
+
+	/* read status */
+	ret = as3645a_read_fault(flash);
+	if (ret < 0)
+		return ret;
+
+	dev_dbg(&client->dev, "AS_INDICATOR_AND_TIMER_REG: %02x\n",
+		as3645a_read(flash, AS_INDICATOR_AND_TIMER_REG));
+	dev_dbg(&client->dev, "AS_CURRENT_SET_REG: %02x\n",
+		as3645a_read(flash, AS_CURRENT_SET_REG));
+	dev_dbg(&client->dev, "AS_CONTROL_REG: %02x\n",
+		as3645a_read(flash, AS_CONTROL_REG));
+
+	return ret & ~AS_FAULT_INFO_LED_AMOUNT ? -EIO : 0;
+}
+
+static int __as3645a_set_power(struct as3645a *flash, int on)
+{
+	int ret;
+
+	if (!on)
+		as3645a_set_control(flash, AS_MODE_EXT_TORCH, false);
+
+	if (flash->pdata->set_power) {
+		ret = flash->pdata->set_power(&flash->subdev, on);
+		if (ret < 0)
+			return ret;
+	}
+
+	if (!on)
+		return 0;
+
+	ret = as3645a_setup(flash);
+	if (ret < 0) {
+		if (flash->pdata->set_power)
+			flash->pdata->set_power(&flash->subdev, 0);
+	}
+
+	return ret;
+}
+
+static int as3645a_set_power(struct v4l2_subdev *sd, int on)
+{
+	struct as3645a *flash = to_as3645a(sd);
+	int ret = 0;
+
+	mutex_lock(&flash->power_lock);
+
+	if (flash->power_count == !on) {
+		ret = __as3645a_set_power(flash, !!on);
+		if (ret < 0)
+			goto done;
+	}
+
+	flash->power_count += on ? 1 : -1;
+	WARN_ON(flash->power_count < 0);
+
+done:
+	mutex_unlock(&flash->power_lock);
+	return ret;
+}
+
+static int as3645a_registered(struct v4l2_subdev *sd)
+{
+	struct as3645a *flash = to_as3645a(sd);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	int rval, man, model, rfu, version;
+	const char *vendor;
+
+	/* Power up the flash driver and read manufacturer ID, model ID, RFU
+	 * and version.
+	 */
+	rval = as3645a_set_power(&flash->subdev, 1);
+	if (rval < 0)
+		return rval;
+
+	rval = as3645a_read(flash, AS_DESIGN_INFO_REG);
+	if (rval < 0)
+		goto power_off;
+
+	man = AS_DESIGN_INFO_FACTORY(rval);
+	model = AS_DESIGN_INFO_MODEL(rval);
+
+	rval = as3645a_read(flash, AS_VERSION_CONTROL_REG);
+	if (rval < 0)
+		goto power_off;
+
+	rfu = AS_VERSION_CONTROL_RFU(rval);
+	version = AS_VERSION_CONTROL_VERSION(rval);
+
+	/* Verify the chip model and version. */
+	if (model != 0x01 || rfu != 0x00) {
+		dev_err(&client->dev, "AS3645A not detected "
+			"(model %d rfu %d)\n", model, rfu);
+		rval = -ENODEV;
+		goto power_off;
+	}
+
+	switch (man) {
+	case 1:
+		vendor = "AMS, Austria Micro Systems";
+		break;
+	case 2:
+		vendor = "ADI, Analog Devices Inc.";
+		break;
+	case 3:
+		vendor = "NSC, National Semiconductor";
+		break;
+	case 4:
+		vendor = "NXP";
+		break;
+	case 5:
+		vendor = "TI, Texas Instrument";
+		break;
+	default:
+		vendor = "Unknown";
+	}
+
+	dev_info(&client->dev, "Chip vendor: %s (%d) Version: %d\n", vendor,
+		 man, version);
+
+	rval = as3645a_write(flash, AS_PASSWORD_REG, AS_PASSWORD_UNLOCK_VALUE);
+	if (rval < 0)
+		goto power_off;
+
+	rval = as3645a_write(flash, AS_BOOST_REG, AS_BOOST_CURRENT_DISABLE);
+	if (rval < 0)
+		goto power_off;
+
+	/* Setup default values. This makes sure that the chip is in a known
+	 * state, in case the power rail can't be controlled.
+	 */
+	rval = as3645a_setup(flash);
+
+power_off:
+	as3645a_set_power(&flash->subdev, 0);
+
+	return rval;
+}
+
+static int as3645a_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+	return as3645a_set_power(sd, 1);
+}
+
+static int as3645a_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+	return as3645a_set_power(sd, 0);
+}
+
+static const struct v4l2_subdev_core_ops as3645a_core_ops = {
+	.s_power		= as3645a_set_power,
+};
+
+static const struct v4l2_subdev_ops as3645a_ops = {
+	.core = &as3645a_core_ops,
+};
+
+static const struct v4l2_subdev_internal_ops as3645a_internal_ops = {
+	.registered = as3645a_registered,
+	.open = as3645a_open,
+	.close = as3645a_close,
+};
+
+/* -----------------------------------------------------------------------------
+ *  I2C driver
+ */
+#ifdef CONFIG_PM
+
+static int as3645a_suspend(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct v4l2_subdev *subdev = i2c_get_clientdata(client);
+	struct as3645a *flash = to_as3645a(subdev);
+	int rval;
+
+	if (flash->power_count == 0)
+		return 0;
+
+	rval = __as3645a_set_power(flash, 0);
+
+	dev_dbg(&client->dev, "Suspend %s\n", rval < 0 ? "failed" : "ok");
+
+	return rval;
+}
+
+static int as3645a_resume(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct v4l2_subdev *subdev = i2c_get_clientdata(client);
+	struct as3645a *flash = to_as3645a(subdev);
+	int rval;
+
+	if (flash->power_count == 0)
+		return 0;
+
+	rval = __as3645a_set_power(flash, 1);
+
+	dev_dbg(&client->dev, "Resume %s\n", rval < 0 ? "fail" : "ok");
+
+	return rval;
+}
+
+#else
+
+#define as3645a_suspend	NULL
+#define as3645a_resume	NULL
+
+#endif /* CONFIG_PM */
+
+/*
+ * as3645a_init_controls - Create controls
+ * @flash: The flash
+ *
+ * The number of LEDs reported in platform data is used to compute default
+ * limits. Parameters passed through platform data can override those limits.
+ */
+static int __devinit as3645a_init_controls(struct as3645a *flash)
+{
+	const struct as3645a_platform_data *pdata = flash->pdata;
+	struct v4l2_ctrl *ctrl;
+	int maximum;
+
+	v4l2_ctrl_handler_init(&flash->ctrls, 10);
+
+	/* V4L2_CID_FLASH_LED_MODE */
+	v4l2_ctrl_new_std_menu(&flash->ctrls, &as3645a_ctrl_ops,
+			       V4L2_CID_FLASH_LED_MODE, 2, ~7,
+			       V4L2_FLASH_LED_MODE_NONE);
+
+	/* V4L2_CID_FLASH_STROBE_SOURCE */
+	v4l2_ctrl_new_std_menu(&flash->ctrls, &as3645a_ctrl_ops,
+			       V4L2_CID_FLASH_STROBE_SOURCE,
+			       pdata->ext_strobe ? 1 : 0,
+			       pdata->ext_strobe ? ~3 : ~1,
+			       V4L2_FLASH_STROBE_SOURCE_SOFTWARE);
+
+	flash->strobe_source = V4L2_FLASH_STROBE_SOURCE_SOFTWARE;
+
+	/* V4L2_CID_FLASH_STROBE */
+	v4l2_ctrl_new_std(&flash->ctrls, &as3645a_ctrl_ops,
+			  V4L2_CID_FLASH_STROBE, 0, 0, 0, 0);
+
+	/* V4L2_CID_FLASH_STROBE_STOP */
+	v4l2_ctrl_new_std(&flash->ctrls, &as3645a_ctrl_ops,
+			  V4L2_CID_FLASH_STROBE_STOP, 0, 0, 0, 0);
+
+	/* V4L2_CID_FLASH_STROBE_STATUS */
+	ctrl = v4l2_ctrl_new_std(&flash->ctrls, &as3645a_ctrl_ops,
+				 V4L2_CID_FLASH_STROBE_STATUS, 0, 1, 1, 1);
+	if (ctrl != NULL)
+		ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
+
+	/* V4L2_CID_FLASH_TIMEOUT */
+	maximum = pdata->timeout_max;
+
+	v4l2_ctrl_new_std(&flash->ctrls, &as3645a_ctrl_ops,
+			  V4L2_CID_FLASH_TIMEOUT, AS3645A_FLASH_TIMEOUT_MIN,
+			  maximum, AS3645A_FLASH_TIMEOUT_STEP, maximum);
+
+	flash->timeout = maximum;
+
+	/* V4L2_CID_FLASH_INTENSITY */
+	maximum = pdata->flash_max_current;
+
+	v4l2_ctrl_new_std(&flash->ctrls, &as3645a_ctrl_ops,
+			  V4L2_CID_FLASH_INTENSITY, AS3645A_FLASH_INTENSITY_MIN,
+			  maximum, AS3645A_FLASH_INTENSITY_STEP, maximum);
+
+	flash->flash_current = (maximum - AS3645A_FLASH_INTENSITY_MIN)
+			     / AS3645A_FLASH_INTENSITY_STEP;
+
+	/* V4L2_CID_FLASH_TORCH_INTENSITY */
+	maximum = pdata->torch_max_current;
+
+	v4l2_ctrl_new_std(&flash->ctrls, &as3645a_ctrl_ops,
+			  V4L2_CID_FLASH_TORCH_INTENSITY,
+			  AS3645A_TORCH_INTENSITY_MIN, maximum,
+			  AS3645A_TORCH_INTENSITY_STEP,
+			  AS3645A_TORCH_INTENSITY_MIN);
+
+	flash->assist_current = 0;
+
+	/* V4L2_CID_FLASH_INDICATOR_INTENSITY */
+	v4l2_ctrl_new_std(&flash->ctrls, &as3645a_ctrl_ops,
+			  V4L2_CID_FLASH_INDICATOR_INTENSITY,
+			  AS3645A_INDICATOR_INTENSITY_MIN,
+			  AS3645A_INDICATOR_INTENSITY_MAX,
+			  AS3645A_INDICATOR_INTENSITY_STEP,
+			  AS3645A_INDICATOR_INTENSITY_MIN);
+
+	flash->indicator_current = 0;
+
+	/* V4L2_CID_FLASH_FAULT */
+	ctrl = v4l2_ctrl_new_std(&flash->ctrls, &as3645a_ctrl_ops,
+				 V4L2_CID_FLASH_FAULT, 0,
+				 V4L2_FLASH_FAULT_OVER_VOLTAGE |
+				 V4L2_FLASH_FAULT_TIMEOUT |
+				 V4L2_FLASH_FAULT_OVER_TEMPERATURE |
+				 V4L2_FLASH_FAULT_SHORT_CIRCUIT, 0, 0);
+	if (ctrl != NULL)
+		ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
+
+	flash->subdev.ctrl_handler = &flash->ctrls;
+
+	return flash->ctrls.error;
+}
+
+static int __devinit as3645a_probe(struct i2c_client *client,
+				   const struct i2c_device_id *devid)
+{
+	struct as3645a *flash;
+	int ret;
+
+	if (client->dev.platform_data == NULL)
+		return -ENODEV;
+
+	flash = kzalloc(sizeof(*flash), GFP_KERNEL);
+	if (flash == NULL)
+		return -ENOMEM;
+
+	flash->pdata = client->dev.platform_data;
+
+	v4l2_i2c_subdev_init(&flash->subdev, client, &as3645a_ops);
+	flash->subdev.internal_ops = &as3645a_internal_ops;
+	flash->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+	ret = as3645a_init_controls(flash);
+	if (ret < 0)
+		goto done;
+
+	ret = media_entity_init(&flash->subdev.entity, 0, NULL, 0);
+	if (ret < 0)
+		goto done;
+
+	flash->subdev.entity.type = MEDIA_ENT_T_V4L2_SUBDEV_FLASH;
+
+	mutex_init(&flash->power_lock);
+
+	flash->led_mode = V4L2_FLASH_LED_MODE_NONE;
+
+done:
+	if (ret < 0) {
+		v4l2_ctrl_handler_free(&flash->ctrls);
+		kfree(flash);
+	}
+
+	return ret;
+}
+
+static int __devexit as3645a_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *subdev = i2c_get_clientdata(client);
+	struct as3645a *flash = to_as3645a(subdev);
+
+	v4l2_device_unregister_subdev(subdev);
+	v4l2_ctrl_handler_free(&flash->ctrls);
+	media_entity_cleanup(&flash->subdev.entity);
+	mutex_destroy(&flash->power_lock);
+	kfree(flash);
+
+	return 0;
+}
+
+static const struct i2c_device_id as3645a_id_table[] = {
+	{ AS3645A_NAME, 0 },
+	{ },
+};
+MODULE_DEVICE_TABLE(i2c, as3645a_id_table);
+
+static const struct dev_pm_ops as3645a_pm_ops = {
+	.suspend = as3645a_suspend,
+	.resume = as3645a_resume,
+};
+
+static struct i2c_driver as3645a_i2c_driver = {
+	.driver	= {
+		.name = AS3645A_NAME,
+		.pm   = &as3645a_pm_ops,
+	},
+	.probe	= as3645a_probe,
+	.remove	= __devexit_p(as3645a_remove),
+	.id_table = as3645a_id_table,
+};
+
+module_i2c_driver(as3645a_i2c_driver);
+
+MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
+MODULE_DESCRIPTION("LED flash driver for AS3645A, LM3555 and their clones");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/i2c/bt819.c b/drivers/media/i2c/bt819.c
new file mode 100644
index 0000000..377bf05
--- /dev/null
+++ b/drivers/media/i2c/bt819.c
@@ -0,0 +1,517 @@
+/*
+ *  bt819 - BT819A VideoStream Decoder (Rockwell Part)
+ *
+ * Copyright (C) 1999 Mike Bernson <mike@mlb.org>
+ * Copyright (C) 1998 Dave Perks <dperks@ibm.net>
+ *
+ * Modifications for LML33/DC10plus unified driver
+ * Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
+ *
+ * Changes by Ronald Bultje <rbultje@ronald.bitfreak.net>
+ *    - moved over to linux>=2.4.x i2c protocol (9/9/2002)
+ *
+ * This code was modify/ported from the saa7111 driver written
+ * by Dave Perks.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/videodev2.h>
+#include <linux/slab.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-ctrls.h>
+#include <media/bt819.h>
+
+MODULE_DESCRIPTION("Brooktree-819 video decoder driver");
+MODULE_AUTHOR("Mike Bernson & Dave Perks");
+MODULE_LICENSE("GPL");
+
+static int debug;
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "Debug level (0-1)");
+
+
+/* ----------------------------------------------------------------------- */
+
+struct bt819 {
+	struct v4l2_subdev sd;
+	struct v4l2_ctrl_handler hdl;
+	unsigned char reg[32];
+
+	v4l2_std_id norm;
+	int ident;
+	int input;
+	int enable;
+};
+
+static inline struct bt819 *to_bt819(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct bt819, sd);
+}
+
+static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
+{
+	return &container_of(ctrl->handler, struct bt819, hdl)->sd;
+}
+
+struct timing {
+	int hactive;
+	int hdelay;
+	int vactive;
+	int vdelay;
+	int hscale;
+	int vscale;
+};
+
+/* for values, see the bt819 datasheet */
+static struct timing timing_data[] = {
+	{864 - 24, 20, 625 - 2, 1, 0x0504, 0x0000},
+	{858 - 24, 20, 525 - 2, 1, 0x00f8, 0x0000},
+};
+
+/* ----------------------------------------------------------------------- */
+
+static inline int bt819_write(struct bt819 *decoder, u8 reg, u8 value)
+{
+	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 bt819 *decoder, u8 reg, u8 bit, u8 value)
+{
+	return bt819_write(decoder, reg,
+		(decoder->reg[reg] & ~(1 << bit)) | (value ? (1 << bit) : 0));
+}
+
+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;
+
+	/* the bt819 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++] =
+				    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 = bt819_write(decoder, reg, *data++);
+			if (ret < 0)
+				break;
+			len -= 2;
+		}
+	}
+
+	return ret;
+}
+
+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 v4l2_subdev *sd)
+{
+	static unsigned char init[] = {
+		/*0x1f, 0x00,*/     /* Reset */
+		0x01, 0x59,	/* 0x01 input format */
+		0x02, 0x00,	/* 0x02 temporal decimation */
+		0x03, 0x12,	/* 0x03 Cropping msb */
+		0x04, 0x16,	/* 0x04 Vertical Delay, lsb */
+		0x05, 0xe0,	/* 0x05 Vertical Active lsb */
+		0x06, 0x80,	/* 0x06 Horizontal Delay lsb */
+		0x07, 0xd0,	/* 0x07 Horizontal Active lsb */
+		0x08, 0x00,	/* 0x08 Horizontal Scaling msb */
+		0x09, 0xf8,	/* 0x09 Horizontal Scaling lsb */
+		0x0a, 0x00,	/* 0x0a Brightness control */
+		0x0b, 0x30,	/* 0x0b Miscellaneous control */
+		0x0c, 0xd8,	/* 0x0c Luma Gain lsb */
+		0x0d, 0xfe,	/* 0x0d Chroma Gain (U) lsb */
+		0x0e, 0xb4,	/* 0x0e Chroma Gain (V) msb */
+		0x0f, 0x00,	/* 0x0f Hue control */
+		0x12, 0x04,	/* 0x12 Output Format */
+		0x13, 0x20,	/* 0x13 Vertial Scaling msb 0x00
+					   chroma comb OFF, line drop scaling, interlace scaling
+					   BUG? Why does turning the chroma comb on fuck up color?
+					   Bug in the bt819 stepping on my board?
+					*/
+		0x14, 0x00,	/* 0x14 Vertial Scaling lsb */
+		0x16, 0x07,	/* 0x16 Video Timing Polarity
+					   ACTIVE=active low
+					   FIELD: high=odd,
+					   vreset=active high,
+					   hreset=active high */
+		0x18, 0x68,	/* 0x18 AGC Delay */
+		0x19, 0x5d,	/* 0x19 Burst Gate Delay */
+		0x1a, 0x80,	/* 0x1a ADC Interface */
+	};
+
+	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) |
+	    (((timing->vactive >> 8) & 0x03) << 4) |
+	    (((timing->hdelay >> 8) & 0x03) << 2) |
+	    ((timing->hactive >> 8) & 0x03);
+	init[0x04 * 2 - 1] = timing->vdelay & 0xff;
+	init[0x05 * 2 - 1] = timing->vactive & 0xff;
+	init[0x06 * 2 - 1] = timing->hdelay & 0xff;
+	init[0x07 * 2 - 1] = timing->hactive & 0xff;
+	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 & V4L2_STD_625_50) ? 115 : 93;	/* Chroma burst delay */
+	/* reset */
+	bt819_write(decoder, 0x1f, 0x00);
+	mdelay(1);
+
+	/* init */
+	return bt819_write_block(decoder, init, sizeof(init));
+}
+
+/* ----------------------------------------------------------------------- */
+
+static int bt819_status(struct v4l2_subdev *sd, u32 *pstatus, v4l2_std_id *pstd)
+{
+	struct bt819 *decoder = to_bt819(sd);
+	int status = bt819_read(decoder, 0x00);
+	int res = V4L2_IN_ST_NO_SIGNAL;
+	v4l2_std_id std;
+
+	if ((status & 0x80))
+		res = 0;
+
+	if ((status & 0x10))
+		std = V4L2_STD_PAL;
+	else
+		std = V4L2_STD_NTSC;
+	if (pstd)
+		*pstd = std;
+	if (pstatus)
+		*pstatus = res;
+
+	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, NULL);
+		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, NULL);
+		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, NULL);
+	return 0;
+}
+
+static int bt819_s_routing(struct v4l2_subdev *sd,
+			   u32 input, u32 output, u32 config)
+{
+	struct bt819 *decoder = to_bt819(sd);
+
+	v4l2_dbg(1, debug, sd, "set input %x\n", input);
+
+	if (input > 7)
+		return -EINVAL;
+
+	if (sd->v4l2_dev == NULL || sd->v4l2_dev->notify == NULL)
+		v4l2_err(sd, "no notify found!\n");
+
+	if (decoder->input != input) {
+		v4l2_subdev_notify(sd, BT819_FIFO_RESET_LOW, NULL);
+		decoder->input = 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);
+		}
+		v4l2_subdev_notify(sd, BT819_FIFO_RESET_HIGH, NULL);
+	}
+	return 0;
+}
+
+static int bt819_s_stream(struct v4l2_subdev *sd, int enable)
+{
+	struct bt819 *decoder = to_bt819(sd);
+
+	v4l2_dbg(1, debug, sd, "enable output %x\n", enable);
+
+	if (decoder->enable != enable) {
+		decoder->enable = enable;
+		bt819_setbit(decoder, 0x16, 7, !enable);
+	}
+	return 0;
+}
+
+static int bt819_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct v4l2_subdev *sd = to_sd(ctrl);
+	struct bt819 *decoder = to_bt819(sd);
+	int temp;
+
+	switch (ctrl->id) {
+	case V4L2_CID_BRIGHTNESS:
+		bt819_write(decoder, 0x0a, ctrl->val);
+		break;
+
+	case V4L2_CID_CONTRAST:
+		bt819_write(decoder, 0x0c, ctrl->val & 0xff);
+		bt819_setbit(decoder, 0x0b, 2, ((ctrl->val >> 8) & 0x01));
+		break;
+
+	case V4L2_CID_SATURATION:
+		bt819_write(decoder, 0x0d, (ctrl->val >> 7) & 0xff);
+		bt819_setbit(decoder, 0x0b, 1, ((ctrl->val >> 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 = (ctrl->val * 180) / 254;
+		bt819_write(decoder, 0x0e, (temp >> 7) & 0xff);
+		bt819_setbit(decoder, 0x0b, 0, (temp >> 15) & 0x01);
+		break;
+
+	case V4L2_CID_HUE:
+		bt819_write(decoder, 0x0f, ctrl->val);
+		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 const struct v4l2_ctrl_ops bt819_ctrl_ops = {
+	.s_ctrl = bt819_s_ctrl,
+};
+
+static const struct v4l2_subdev_core_ops bt819_core_ops = {
+	.g_chip_ident = bt819_g_chip_ident,
+	.g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
+	.try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
+	.s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
+	.g_ctrl = v4l2_subdev_g_ctrl,
+	.s_ctrl = v4l2_subdev_s_ctrl,
+	.queryctrl = v4l2_subdev_queryctrl,
+	.querymenu = v4l2_subdev_querymenu,
+	.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,
+	.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;
+
+	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:
+		v4l2_dbg(1, debug, sd,
+			"unknown chip version 0x%02x\n", ver);
+		return -ENODEV;
+	}
+
+	v4l_info(client, "%s found @ 0x%x (%s)\n", name,
+			client->addr << 1, client->adapter->name);
+
+	decoder->norm = V4L2_STD_NTSC;
+	decoder->input = 0;
+	decoder->enable = 1;
+
+	i = bt819_init(sd);
+	if (i < 0)
+		v4l2_dbg(1, debug, sd, "init status %d\n", i);
+
+	v4l2_ctrl_handler_init(&decoder->hdl, 4);
+	v4l2_ctrl_new_std(&decoder->hdl, &bt819_ctrl_ops,
+			V4L2_CID_BRIGHTNESS, -128, 127, 1, 0);
+	v4l2_ctrl_new_std(&decoder->hdl, &bt819_ctrl_ops,
+			V4L2_CID_CONTRAST, 0, 511, 1, 0xd8);
+	v4l2_ctrl_new_std(&decoder->hdl, &bt819_ctrl_ops,
+			V4L2_CID_SATURATION, 0, 511, 1, 0xfe);
+	v4l2_ctrl_new_std(&decoder->hdl, &bt819_ctrl_ops,
+			V4L2_CID_HUE, -128, 127, 1, 0);
+	sd->ctrl_handler = &decoder->hdl;
+	if (decoder->hdl.error) {
+		int err = decoder->hdl.error;
+
+		v4l2_ctrl_handler_free(&decoder->hdl);
+		kfree(decoder);
+		return err;
+	}
+	v4l2_ctrl_handler_setup(&decoder->hdl);
+	return 0;
+}
+
+static int bt819_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct bt819 *decoder = to_bt819(sd);
+
+	v4l2_device_unregister_subdev(sd);
+	v4l2_ctrl_handler_free(&decoder->hdl);
+	kfree(decoder);
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static const struct i2c_device_id bt819_id[] = {
+	{ "bt819a", 0 },
+	{ "bt817a", 0 },
+	{ "bt815a", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, bt819_id);
+
+static struct i2c_driver bt819_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "bt819",
+	},
+	.probe		= bt819_probe,
+	.remove		= bt819_remove,
+	.id_table	= bt819_id,
+};
+
+module_i2c_driver(bt819_driver);
diff --git a/drivers/media/i2c/bt856.c b/drivers/media/i2c/bt856.c
new file mode 100644
index 0000000..7e5bd36
--- /dev/null
+++ b/drivers/media/i2c/bt856.c
@@ -0,0 +1,273 @@
+/*
+ * bt856 - BT856A Digital Video Encoder (Rockwell Part)
+ *
+ * Copyright (C) 1999 Mike Bernson <mike@mlb.org>
+ * Copyright (C) 1998 Dave Perks <dperks@ibm.net>
+ *
+ * Modifications for LML33/DC10plus unified driver
+ * Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
+ *
+ * This code was modify/ported from the saa7111 driver written
+ * by Dave Perks.
+ *
+ * Changes by Ronald Bultje <rbultje@ronald.bitfreak.net>
+ *   - moved over to linux>=2.4.x i2c protocol (9/9/2002)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/slab.h>
+#include <linux/ioctl.h>
+#include <asm/uaccess.h>
+#include <linux/i2c.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-chip-ident.h>
+
+MODULE_DESCRIPTION("Brooktree-856A video encoder driver");
+MODULE_AUTHOR("Mike Bernson & Dave Perks");
+MODULE_LICENSE("GPL");
+
+static int debug;
+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];
+
+	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 bt856 *encoder, u8 reg, u8 value)
+{
+	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 bt856 *encoder, u8 reg, u8 bit, u8 value)
+{
+	return bt856_write(encoder, reg,
+		(encoder->reg[reg - BT856_REG_OFFSET] & ~(1 << bit)) |
+				(value ? (1 << bit) : 0));
+}
+
+static void bt856_dump(struct bt856 *encoder)
+{
+	int i;
+
+	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");
+}
+
+/* ----------------------------------------------------------------------- */
+
+static int bt856_init(struct v4l2_subdev *sd, u32 arg)
+{
+	struct bt856 *encoder = to_bt856(sd);
+
+	/* 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,
+			   u32 input, u32 output, u32 config)
+{
+	struct bt856 *encoder = to_bt856(sd);
+
+	v4l2_dbg(1, debug, sd, "set input %d\n", input);
+
+	/* We only have video bus.
+	 * input= 0: input is from bt819
+	 * input= 1: input is from ZR36060 */
+	switch (input) {
+	case 0:
+		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 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 2:	/* Color bar */
+		bt856_setbit(encoder, 0xdc, 3, 0);
+		bt856_setbit(encoder, 0xde, 4, 1);
+		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 const struct v4l2_subdev_core_ops bt856_core_ops = {
+	.g_chip_ident = bt856_g_chip_ident,
+	.init = bt856_init,
+};
+
+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))
+		return -ENODEV;
+
+	v4l_info(client, "chip found @ 0x%x (%s)\n",
+			client->addr << 1, client->adapter->name);
+
+	encoder = kzalloc(sizeof(struct bt856), GFP_KERNEL);
+	if (encoder == NULL)
+		return -ENOMEM;
+	sd = &encoder->sd;
+	v4l2_i2c_subdev_init(sd, client, &bt856_ops);
+	encoder->norm = V4L2_STD_NTSC;
+
+	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_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+
+	v4l2_device_unregister_subdev(sd);
+	kfree(to_bt856(sd));
+	return 0;
+}
+
+static const struct i2c_device_id bt856_id[] = {
+	{ "bt856", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, bt856_id);
+
+static struct i2c_driver bt856_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "bt856",
+	},
+	.probe		= bt856_probe,
+	.remove		= bt856_remove,
+	.id_table	= bt856_id,
+};
+
+module_i2c_driver(bt856_driver);
diff --git a/drivers/media/i2c/bt866.c b/drivers/media/i2c/bt866.c
new file mode 100644
index 0000000..905320b
--- /dev/null
+++ b/drivers/media/i2c/bt866.c
@@ -0,0 +1,243 @@
+/*
+    bt866 - BT866 Digital Video Encoder (Rockwell Part)
+
+    Copyright (C) 1999 Mike Bernson <mike@mlb.org>
+    Copyright (C) 1998 Dave Perks <dperks@ibm.net>
+
+    Modifications for LML33/DC10plus unified driver
+    Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
+
+    This code was modify/ported from the saa7111 driver written
+    by Dave Perks.
+
+    This code was adapted for the bt866 by Christer Weinigel and ported
+    to 2.6 by Martin Samuelsson.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the 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/slab.h>
+#include <linux/ioctl.h>
+#include <asm/uaccess.h>
+#include <linux/i2c.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-chip-ident.h>
+
+MODULE_DESCRIPTION("Brooktree-866 video encoder driver");
+MODULE_AUTHOR("Mike Bernson & Dave Perks");
+MODULE_LICENSE("GPL");
+
+static int debug;
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "Debug level (0-1)");
+
+
+/* ----------------------------------------------------------------------- */
+
+struct bt866 {
+	struct v4l2_subdev sd;
+	u8 reg[256];
+};
+
+static inline struct bt866 *to_bt866(struct v4l2_subdev *sd)
+{
+	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;
+
+	buffer[0] = subaddr;
+	buffer[1] = data;
+
+	encoder->reg[subaddr] = data;
+
+	v4l_dbg(1, debug, client, "write 0x%02x = 0x%02x\n", subaddr, data);
+
+	for (err = 0; err < 3;) {
+		if (i2c_master_send(client, buffer, 2) == 2)
+			break;
+		err++;
+		v4l_warn(client, "error #%d writing to 0x%02x\n",
+				err, subaddr);
+		schedule_timeout_interruptible(msecs_to_jiffies(100));
+	}
+	if (err == 3) {
+		v4l_warn(client, "giving up\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+static int bt866_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std)
+{
+	v4l2_dbg(1, debug, sd, "set norm %llx\n", (unsigned long long)std);
+
+	/* Only PAL supported by this driver at the moment! */
+	if (!(std & V4L2_STD_NTSC))
+		return -EINVAL;
+	return 0;
+}
+
+static int bt866_s_routing(struct v4l2_subdev *sd,
+			   u32 input, u32 output, u32 config)
+{
+	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 */
+	};
+	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 (input == 0)
+		val |= 0x40; /* CBSWAP */
+	else
+		val &= ~0x40; /* !CBSWAP */
+
+	bt866_write(encoder, 0xdc, val);
+
+	val = encoder->reg[0xcc];
+	if (input == 2)
+		val |= 0x01; /* OSDBAR */
+	else
+		val &= ~0x01; /* !OSDBAR */
+	bt866_write(encoder, 0xcc, val);
+
+	v4l2_dbg(1, debug, sd, "set input %d\n", input);
+
+	switch (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);
+
+	encoder = kzalloc(sizeof(*encoder), GFP_KERNEL);
+	if (encoder == NULL)
+		return -ENOMEM;
+	sd = &encoder->sd;
+	v4l2_i2c_subdev_init(sd, client, &bt866_ops);
+	return 0;
+}
+
+static int bt866_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+
+	v4l2_device_unregister_subdev(sd);
+	kfree(to_bt866(sd));
+	return 0;
+}
+
+static const struct i2c_device_id bt866_id[] = {
+	{ "bt866", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, bt866_id);
+
+static struct i2c_driver bt866_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "bt866",
+	},
+	.probe		= bt866_probe,
+	.remove		= bt866_remove,
+	.id_table	= bt866_id,
+};
+
+module_i2c_driver(bt866_driver);
diff --git a/drivers/media/i2c/btcx-risc.c b/drivers/media/i2c/btcx-risc.c
new file mode 100644
index 0000000..ac1b268
--- /dev/null
+++ b/drivers/media/i2c/btcx-risc.c
@@ -0,0 +1,260 @@
+/*
+
+    btcx-risc.c
+
+    bt848/bt878/cx2388x risc code generator.
+
+    (c) 2000-03 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the 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/init.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/videodev2.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
+#include "btcx-risc.h"
+
+MODULE_DESCRIPTION("some code shared by bttv and cx88xx drivers");
+MODULE_AUTHOR("Gerd Knorr");
+MODULE_LICENSE("GPL");
+
+static unsigned int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug,"debug messages, default is 0 (no)");
+
+/* ---------------------------------------------------------- */
+/* allocate/free risc memory                                  */
+
+static int memcnt;
+
+void btcx_riscmem_free(struct pci_dev *pci,
+		       struct btcx_riscmem *risc)
+{
+	if (NULL == risc->cpu)
+		return;
+	if (debug) {
+		memcnt--;
+		printk("btcx: riscmem free [%d] dma=%lx\n",
+		       memcnt, (unsigned long)risc->dma);
+	}
+	pci_free_consistent(pci, risc->size, risc->cpu, risc->dma);
+	memset(risc,0,sizeof(*risc));
+}
+
+int btcx_riscmem_alloc(struct pci_dev *pci,
+		       struct btcx_riscmem *risc,
+		       unsigned int size)
+{
+	__le32 *cpu;
+	dma_addr_t dma = 0;
+
+	if (NULL != risc->cpu && risc->size < size)
+		btcx_riscmem_free(pci,risc);
+	if (NULL == risc->cpu) {
+		cpu = pci_alloc_consistent(pci, size, &dma);
+		if (NULL == cpu)
+			return -ENOMEM;
+		risc->cpu  = cpu;
+		risc->dma  = dma;
+		risc->size = size;
+		if (debug) {
+			memcnt++;
+			printk("btcx: riscmem alloc [%d] dma=%lx cpu=%p size=%d\n",
+			       memcnt, (unsigned long)dma, cpu, size);
+		}
+	}
+	memset(risc->cpu,0,risc->size);
+	return 0;
+}
+
+/* ---------------------------------------------------------- */
+/* screen overlay helpers                                     */
+
+int
+btcx_screen_clips(int swidth, int sheight, struct v4l2_rect *win,
+		  struct v4l2_clip *clips, unsigned int n)
+{
+	if (win->left < 0) {
+		/* left */
+		clips[n].c.left = 0;
+		clips[n].c.top = 0;
+		clips[n].c.width  = -win->left;
+		clips[n].c.height = win->height;
+		n++;
+	}
+	if (win->left + win->width > swidth) {
+		/* right */
+		clips[n].c.left   = swidth - win->left;
+		clips[n].c.top    = 0;
+		clips[n].c.width  = win->width - clips[n].c.left;
+		clips[n].c.height = win->height;
+		n++;
+	}
+	if (win->top < 0) {
+		/* top */
+		clips[n].c.left = 0;
+		clips[n].c.top = 0;
+		clips[n].c.width  = win->width;
+		clips[n].c.height = -win->top;
+		n++;
+	}
+	if (win->top + win->height > sheight) {
+		/* bottom */
+		clips[n].c.left = 0;
+		clips[n].c.top = sheight - win->top;
+		clips[n].c.width  = win->width;
+		clips[n].c.height = win->height - clips[n].c.top;
+		n++;
+	}
+	return n;
+}
+
+int
+btcx_align(struct v4l2_rect *win, struct v4l2_clip *clips, unsigned int n, int mask)
+{
+	s32 nx,nw,dx;
+	unsigned int i;
+
+	/* fixup window */
+	nx = (win->left + mask) & ~mask;
+	nw = (win->width) & ~mask;
+	if (nx + nw > win->left + win->width)
+		nw -= mask+1;
+	dx = nx - win->left;
+	win->left  = nx;
+	win->width = nw;
+	if (debug)
+		printk(KERN_DEBUG "btcx: window align %dx%d+%d+%d [dx=%d]\n",
+		       win->width, win->height, win->left, win->top, dx);
+
+	/* fixup clips */
+	for (i = 0; i < n; i++) {
+		nx = (clips[i].c.left-dx) & ~mask;
+		nw = (clips[i].c.width) & ~mask;
+		if (nx + nw < clips[i].c.left-dx + clips[i].c.width)
+			nw += mask+1;
+		clips[i].c.left  = nx;
+		clips[i].c.width = nw;
+		if (debug)
+			printk(KERN_DEBUG "btcx:   clip align %dx%d+%d+%d\n",
+			       clips[i].c.width, clips[i].c.height,
+			       clips[i].c.left, clips[i].c.top);
+	}
+	return 0;
+}
+
+void
+btcx_sort_clips(struct v4l2_clip *clips, unsigned int nclips)
+{
+	struct v4l2_clip swap;
+	int i,j,n;
+
+	if (nclips < 2)
+		return;
+	for (i = nclips-2; i >= 0; i--) {
+		for (n = 0, j = 0; j <= i; j++) {
+			if (clips[j].c.left > clips[j+1].c.left) {
+				swap = clips[j];
+				clips[j] = clips[j+1];
+				clips[j+1] = swap;
+				n++;
+			}
+		}
+		if (0 == n)
+			break;
+	}
+}
+
+void
+btcx_calc_skips(int line, int width, int *maxy,
+		struct btcx_skiplist *skips, unsigned int *nskips,
+		const struct v4l2_clip *clips, unsigned int nclips)
+{
+	unsigned int clip,skip;
+	int end, maxline;
+
+	skip=0;
+	maxline = 9999;
+	for (clip = 0; clip < nclips; clip++) {
+
+		/* sanity checks */
+		if (clips[clip].c.left + clips[clip].c.width <= 0)
+			continue;
+		if (clips[clip].c.left > (signed)width)
+			break;
+
+		/* vertical range */
+		if (line > clips[clip].c.top+clips[clip].c.height-1)
+			continue;
+		if (line < clips[clip].c.top) {
+			if (maxline > clips[clip].c.top-1)
+				maxline = clips[clip].c.top-1;
+			continue;
+		}
+		if (maxline > clips[clip].c.top+clips[clip].c.height-1)
+			maxline = clips[clip].c.top+clips[clip].c.height-1;
+
+		/* horizontal range */
+		if (0 == skip || clips[clip].c.left > skips[skip-1].end) {
+			/* new one */
+			skips[skip].start = clips[clip].c.left;
+			if (skips[skip].start < 0)
+				skips[skip].start = 0;
+			skips[skip].end = clips[clip].c.left + clips[clip].c.width;
+			if (skips[skip].end > width)
+				skips[skip].end = width;
+			skip++;
+		} else {
+			/* overlaps -- expand last one */
+			end = clips[clip].c.left + clips[clip].c.width;
+			if (skips[skip-1].end < end)
+				skips[skip-1].end = end;
+			if (skips[skip-1].end > width)
+				skips[skip-1].end = width;
+		}
+	}
+	*nskips = skip;
+	*maxy = maxline;
+
+	if (debug) {
+		printk(KERN_DEBUG "btcx: skips line %d-%d:",line,maxline);
+		for (skip = 0; skip < *nskips; skip++) {
+			printk(" %d-%d",skips[skip].start,skips[skip].end);
+		}
+		printk("\n");
+	}
+}
+
+/* ---------------------------------------------------------- */
+
+EXPORT_SYMBOL(btcx_riscmem_alloc);
+EXPORT_SYMBOL(btcx_riscmem_free);
+
+EXPORT_SYMBOL(btcx_screen_clips);
+EXPORT_SYMBOL(btcx_align);
+EXPORT_SYMBOL(btcx_sort_clips);
+EXPORT_SYMBOL(btcx_calc_skips);
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/i2c/btcx-risc.h b/drivers/media/i2c/btcx-risc.h
new file mode 100644
index 0000000..f8bc6e8
--- /dev/null
+++ b/drivers/media/i2c/btcx-risc.h
@@ -0,0 +1,34 @@
+/*
+ */
+struct btcx_riscmem {
+	unsigned int   size;
+	__le32         *cpu;
+	__le32         *jmp;
+	dma_addr_t     dma;
+};
+
+struct btcx_skiplist {
+	int start;
+	int end;
+};
+
+int  btcx_riscmem_alloc(struct pci_dev *pci,
+			struct btcx_riscmem *risc,
+			unsigned int size);
+void btcx_riscmem_free(struct pci_dev *pci,
+		       struct btcx_riscmem *risc);
+
+int btcx_screen_clips(int swidth, int sheight, struct v4l2_rect *win,
+		      struct v4l2_clip *clips, unsigned int n);
+int btcx_align(struct v4l2_rect *win, struct v4l2_clip *clips,
+	       unsigned int n, int mask);
+void btcx_sort_clips(struct v4l2_clip *clips, unsigned int nclips);
+void btcx_calc_skips(int line, int width, int *maxy,
+		     struct btcx_skiplist *skips, unsigned int *nskips,
+		     const struct v4l2_clip *clips, unsigned int nclips);
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/i2c/cs5345.c b/drivers/media/i2c/cs5345.c
new file mode 100644
index 0000000..c8581e2
--- /dev/null
+++ b/drivers/media/i2c/cs5345.c
@@ -0,0 +1,252 @@
+/*
+ * cs5345 Cirrus Logic 24-bit, 192 kHz Stereo Audio ADC
+ * Copyright (C) 2007 Hans Verkuil
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+#include <linux/videodev2.h>
+#include <linux/slab.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-ctrls.h>
+
+MODULE_DESCRIPTION("i2c device driver for cs5345 Audio ADC");
+MODULE_AUTHOR("Hans Verkuil");
+MODULE_LICENSE("GPL");
+
+static bool debug;
+
+module_param(debug, bool, 0644);
+
+MODULE_PARM_DESC(debug, "Debugging messages, 0=Off (default), 1=On");
+
+struct cs5345_state {
+	struct v4l2_subdev sd;
+	struct v4l2_ctrl_handler hdl;
+};
+
+static inline struct cs5345_state *to_state(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct cs5345_state, sd);
+}
+
+static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
+{
+	return &container_of(ctrl->handler, struct cs5345_state, hdl)->sd;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static inline int cs5345_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 cs5345_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 cs5345_s_routing(struct v4l2_subdev *sd,
+			    u32 input, u32 output, u32 config)
+{
+	if ((input & 0xf) > 6) {
+		v4l2_err(sd, "Invalid input %d.\n", input);
+		return -EINVAL;
+	}
+	cs5345_write(sd, 0x09, input & 0xf);
+	cs5345_write(sd, 0x05, input & 0xf0);
+	return 0;
+}
+
+static int cs5345_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct v4l2_subdev *sd = to_sd(ctrl);
+
+	switch (ctrl->id) {
+	case V4L2_CID_AUDIO_MUTE:
+		cs5345_write(sd, 0x04, ctrl->val ? 0x80 : 0);
+		return 0;
+	case V4L2_CID_AUDIO_VOLUME:
+		cs5345_write(sd, 0x07, ((u8)ctrl->val) & 0x3f);
+		cs5345_write(sd, 0x08, ((u8)ctrl->val) & 0x3f);
+		return 0;
+	}
+	return -EINVAL;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int cs5345_g_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;
+	reg->size = 1;
+	reg->val = cs5345_read(sd, reg->reg & 0x1f);
+	return 0;
+}
+
+static int cs5345_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;
+	cs5345_write(sd, reg->reg & 0x1f, reg->val & 0xff);
+	return 0;
+}
+#endif
+
+static int cs5345_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_CS5345, 0);
+}
+
+static int cs5345_log_status(struct v4l2_subdev *sd)
+{
+	u8 v = cs5345_read(sd, 0x09) & 7;
+	u8 m = cs5345_read(sd, 0x04);
+	int vol = cs5345_read(sd, 0x08) & 0x3f;
+
+	v4l2_info(sd, "Input:  %d%s\n", v,
+			(m & 0x80) ? " (muted)" : "");
+	if (vol >= 32)
+		vol = vol - 64;
+	v4l2_info(sd, "Volume: %d dB\n", vol);
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static const struct v4l2_ctrl_ops cs5345_ctrl_ops = {
+	.s_ctrl = cs5345_s_ctrl,
+};
+
+static const struct v4l2_subdev_core_ops cs5345_core_ops = {
+	.log_status = cs5345_log_status,
+	.g_chip_ident = cs5345_g_chip_ident,
+	.g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
+	.try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
+	.s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
+	.g_ctrl = v4l2_subdev_g_ctrl,
+	.s_ctrl = v4l2_subdev_s_ctrl,
+	.queryctrl = v4l2_subdev_queryctrl,
+	.querymenu = v4l2_subdev_querymenu,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.g_register = cs5345_g_register,
+	.s_register = cs5345_s_register,
+#endif
+};
+
+static const struct v4l2_subdev_audio_ops cs5345_audio_ops = {
+	.s_routing = cs5345_s_routing,
+};
+
+static const struct v4l2_subdev_ops cs5345_ops = {
+	.core = &cs5345_core_ops,
+	.audio = &cs5345_audio_ops,
+};
+
+/* ----------------------------------------------------------------------- */
+
+static int cs5345_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	struct cs5345_state *state;
+	struct v4l2_subdev *sd;
+
+	/* Check if the adapter supports the needed features */
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		return -EIO;
+
+	v4l_info(client, "chip found @ 0x%x (%s)\n",
+			client->addr << 1, client->adapter->name);
+
+	state = kzalloc(sizeof(struct cs5345_state), GFP_KERNEL);
+	if (state == NULL)
+		return -ENOMEM;
+	sd = &state->sd;
+	v4l2_i2c_subdev_init(sd, client, &cs5345_ops);
+
+	v4l2_ctrl_handler_init(&state->hdl, 2);
+	v4l2_ctrl_new_std(&state->hdl, &cs5345_ctrl_ops,
+			V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0);
+	v4l2_ctrl_new_std(&state->hdl, &cs5345_ctrl_ops,
+			V4L2_CID_AUDIO_VOLUME, -24, 24, 1, 0);
+	sd->ctrl_handler = &state->hdl;
+	if (state->hdl.error) {
+		int err = state->hdl.error;
+
+		v4l2_ctrl_handler_free(&state->hdl);
+		kfree(state);
+		return err;
+	}
+	/* set volume/mute */
+	v4l2_ctrl_handler_setup(&state->hdl);
+
+	cs5345_write(sd, 0x02, 0x00);
+	cs5345_write(sd, 0x04, 0x01);
+	cs5345_write(sd, 0x09, 0x01);
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static int cs5345_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct cs5345_state *state = to_state(sd);
+
+	v4l2_device_unregister_subdev(sd);
+	v4l2_ctrl_handler_free(&state->hdl);
+	kfree(state);
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static const struct i2c_device_id cs5345_id[] = {
+	{ "cs5345", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, cs5345_id);
+
+static struct i2c_driver cs5345_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "cs5345",
+	},
+	.probe		= cs5345_probe,
+	.remove		= cs5345_remove,
+	.id_table	= cs5345_id,
+};
+
+module_i2c_driver(cs5345_driver);
diff --git a/drivers/media/i2c/cs53l32a.c b/drivers/media/i2c/cs53l32a.c
new file mode 100644
index 0000000..b293912
--- /dev/null
+++ b/drivers/media/i2c/cs53l32a.c
@@ -0,0 +1,251 @@
+/*
+ * cs53l32a (Adaptec AVC-2010 and AVC-2410) i2c ivtv driver.
+ * Copyright (C) 2005  Martin Vaughan
+ *
+ * Audio source switching for Adaptec AVC-2410 added by Trev Jackson
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/slab.h>
+#include <linux/ioctl.h>
+#include <asm/uaccess.h>
+#include <linux/i2c.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-ctrls.h>
+
+MODULE_DESCRIPTION("i2c device driver for cs53l32a Audio ADC");
+MODULE_AUTHOR("Martin Vaughan");
+MODULE_LICENSE("GPL");
+
+static bool debug;
+
+module_param(debug, bool, 0644);
+
+MODULE_PARM_DESC(debug, "Debugging messages, 0=Off (default), 1=On");
+
+
+struct cs53l32a_state {
+	struct v4l2_subdev sd;
+	struct v4l2_ctrl_handler hdl;
+};
+
+static inline struct cs53l32a_state *to_state(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct cs53l32a_state, sd);
+}
+
+static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
+{
+	return &container_of(ctrl->handler, struct cs53l32a_state, hdl)->sd;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static int cs53l32a_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 int cs53l32a_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 cs53l32a_s_routing(struct v4l2_subdev *sd,
+			      u32 input, u32 output, u32 config)
+{
+	/* There are 2 physical inputs, but the second input can be
+	   placed in two modes, the first mode bypasses the PGA (gain),
+	   the second goes through the PGA. Hence there are three
+	   possible inputs to choose from. */
+	if (input > 2) {
+		v4l2_err(sd, "Invalid input %d.\n", input);
+		return -EINVAL;
+	}
+	cs53l32a_write(sd, 0x01, 0x01 + (input << 4));
+	return 0;
+}
+
+static int cs53l32a_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct v4l2_subdev *sd = to_sd(ctrl);
+
+	switch (ctrl->id) {
+	case V4L2_CID_AUDIO_MUTE:
+		cs53l32a_write(sd, 0x03, ctrl->val ? 0xf0 : 0x30);
+		return 0;
+	case V4L2_CID_AUDIO_VOLUME:
+		cs53l32a_write(sd, 0x04, (u8)ctrl->val);
+		cs53l32a_write(sd, 0x05, (u8)ctrl->val);
+		return 0;
+	}
+	return -EINVAL;
+}
+
+static int cs53l32a_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_CS53l32A, 0);
+}
+
+static int cs53l32a_log_status(struct v4l2_subdev *sd)
+{
+	struct cs53l32a_state *state = to_state(sd);
+	u8 v = cs53l32a_read(sd, 0x01);
+
+	v4l2_info(sd, "Input:  %d\n", (v >> 4) & 3);
+	v4l2_ctrl_handler_log_status(&state->hdl, sd->name);
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static const struct v4l2_ctrl_ops cs53l32a_ctrl_ops = {
+	.s_ctrl = cs53l32a_s_ctrl,
+};
+
+static const struct v4l2_subdev_core_ops cs53l32a_core_ops = {
+	.log_status = cs53l32a_log_status,
+	.g_chip_ident = cs53l32a_g_chip_ident,
+	.g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
+	.try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
+	.s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
+	.g_ctrl = v4l2_subdev_g_ctrl,
+	.s_ctrl = v4l2_subdev_s_ctrl,
+	.queryctrl = v4l2_subdev_queryctrl,
+	.querymenu = v4l2_subdev_querymenu,
+};
+
+static const struct v4l2_subdev_audio_ops cs53l32a_audio_ops = {
+	.s_routing = cs53l32a_s_routing,
+};
+
+static const struct v4l2_subdev_ops cs53l32a_ops = {
+	.core = &cs53l32a_core_ops,
+	.audio = &cs53l32a_audio_ops,
+};
+
+/* ----------------------------------------------------------------------- */
+
+/* i2c implementation */
+
+/*
+ * Generic i2c probe
+ * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
+ */
+
+static int cs53l32a_probe(struct i2c_client *client,
+			  const struct i2c_device_id *id)
+{
+	struct cs53l32a_state *state;
+	struct v4l2_subdev *sd;
+	int i;
+
+	/* Check if the adapter supports the needed features */
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		return -EIO;
+
+	if (!id)
+		strlcpy(client->name, "cs53l32a", sizeof(client->name));
+
+	v4l_info(client, "chip found @ 0x%x (%s)\n",
+			client->addr << 1, client->adapter->name);
+
+	state = kzalloc(sizeof(struct cs53l32a_state), GFP_KERNEL);
+	if (state == NULL)
+		return -ENOMEM;
+	sd = &state->sd;
+	v4l2_i2c_subdev_init(sd, client, &cs53l32a_ops);
+
+	for (i = 1; i <= 7; i++) {
+		u8 v = cs53l32a_read(sd, i);
+
+		v4l2_dbg(1, debug, sd, "Read Reg %d %02x\n", i, v);
+	}
+
+	v4l2_ctrl_handler_init(&state->hdl, 2);
+	v4l2_ctrl_new_std(&state->hdl, &cs53l32a_ctrl_ops,
+			V4L2_CID_AUDIO_VOLUME, -96, 12, 1, 0);
+	v4l2_ctrl_new_std(&state->hdl, &cs53l32a_ctrl_ops,
+			V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0);
+	sd->ctrl_handler = &state->hdl;
+	if (state->hdl.error) {
+		int err = state->hdl.error;
+
+		v4l2_ctrl_handler_free(&state->hdl);
+		kfree(state);
+		return err;
+	}
+
+	/* Set cs53l32a internal register for Adaptec 2010/2410 setup */
+
+	cs53l32a_write(sd, 0x01, 0x21);
+	cs53l32a_write(sd, 0x02, 0x29);
+	cs53l32a_write(sd, 0x03, 0x30);
+	cs53l32a_write(sd, 0x04, 0x00);
+	cs53l32a_write(sd, 0x05, 0x00);
+	cs53l32a_write(sd, 0x06, 0x00);
+	cs53l32a_write(sd, 0x07, 0x00);
+
+	/* Display results, should be 0x21,0x29,0x30,0x00,0x00,0x00,0x00 */
+
+	for (i = 1; i <= 7; i++) {
+		u8 v = cs53l32a_read(sd, i);
+
+		v4l2_dbg(1, debug, sd, "Read Reg %d %02x\n", i, v);
+	}
+	return 0;
+}
+
+static int cs53l32a_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct cs53l32a_state *state = to_state(sd);
+
+	v4l2_device_unregister_subdev(sd);
+	v4l2_ctrl_handler_free(&state->hdl);
+	kfree(state);
+	return 0;
+}
+
+static const struct i2c_device_id cs53l32a_id[] = {
+	{ "cs53l32a", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, cs53l32a_id);
+
+static struct i2c_driver cs53l32a_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "cs53l32a",
+	},
+	.probe		= cs53l32a_probe,
+	.remove		= cs53l32a_remove,
+	.id_table	= cs53l32a_id,
+};
+
+module_i2c_driver(cs53l32a_driver);
diff --git a/drivers/media/i2c/cx2341x.c b/drivers/media/i2c/cx2341x.c
new file mode 100644
index 0000000..103ef6b
--- /dev/null
+++ b/drivers/media/i2c/cx2341x.c
@@ -0,0 +1,1726 @@
+/*
+ * cx2341x - generic code for cx23415/6/8 based devices
+ *
+ * Copyright (C) 2006 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.
+ */
+
+
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/videodev2.h>
+
+#include <media/tuner.h>
+#include <media/cx2341x.h>
+#include <media/v4l2-common.h>
+
+MODULE_DESCRIPTION("cx23415/6/8 driver");
+MODULE_AUTHOR("Hans Verkuil");
+MODULE_LICENSE("GPL");
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Debug level (0-1)");
+
+/********************** COMMON CODE *********************/
+
+/* 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 const char *cx2341x_get_name(u32 id)
+{
+	switch (id) {
+	case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
+		return "Spatial Filter Mode";
+	case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
+		return "Spatial Filter";
+	case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
+		return "Spatial Luma Filter Type";
+	case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
+		return "Spatial Chroma Filter Type";
+	case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
+		return "Temporal Filter Mode";
+	case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
+		return "Temporal Filter";
+	case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
+		return "Median Filter Type";
+	case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
+		return "Median Luma Filter Maximum";
+	case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
+		return "Median Luma Filter Minimum";
+	case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
+		return "Median Chroma Filter Maximum";
+	case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
+		return "Median Chroma Filter Minimum";
+	case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
+		return "Insert Navigation Packets";
+	}
+	return NULL;
+}
+
+static const char **cx2341x_get_menu(u32 id)
+{
+	static const char *cx2341x_video_spatial_filter_mode_menu[] = {
+		"Manual",
+		"Auto",
+		NULL
+	};
+
+	static const char *cx2341x_video_luma_spatial_filter_type_menu[] = {
+		"Off",
+		"1D Horizontal",
+		"1D Vertical",
+		"2D H/V Separable",
+		"2D Symmetric non-separable",
+		NULL
+	};
+
+	static const char *cx2341x_video_chroma_spatial_filter_type_menu[] = {
+		"Off",
+		"1D Horizontal",
+		NULL
+	};
+
+	static const char *cx2341x_video_temporal_filter_mode_menu[] = {
+		"Manual",
+		"Auto",
+		NULL
+	};
+
+	static const char *cx2341x_video_median_filter_type_menu[] = {
+		"Off",
+		"Horizontal",
+		"Vertical",
+		"Horizontal/Vertical",
+		"Diagonal",
+		NULL
+	};
+
+	switch (id) {
+	case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
+		return cx2341x_video_spatial_filter_mode_menu;
+	case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
+		return cx2341x_video_luma_spatial_filter_type_menu;
+	case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
+		return cx2341x_video_chroma_spatial_filter_type_menu;
+	case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
+		return cx2341x_video_temporal_filter_mode_menu;
+	case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
+		return cx2341x_video_median_filter_type_menu;
+	}
+	return NULL;
+}
+
+static void cx2341x_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
+		    s32 *min, s32 *max, s32 *step, s32 *def, u32 *flags)
+{
+	*name = cx2341x_get_name(id);
+	*flags = 0;
+
+	switch (id) {
+	case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
+	case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
+	case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
+	case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
+	case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
+		*type = V4L2_CTRL_TYPE_MENU;
+		*min = 0;
+		*step = 0;
+		break;
+	case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
+		*type = V4L2_CTRL_TYPE_BOOLEAN;
+		*min = 0;
+		*max = *step = 1;
+		break;
+	default:
+		*type = V4L2_CTRL_TYPE_INTEGER;
+		break;
+	}
+	switch (id) {
+	case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
+	case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
+	case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
+		*flags |= V4L2_CTRL_FLAG_UPDATE;
+		break;
+	case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
+	case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
+	case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
+	case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
+	case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
+	case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
+		*flags |= V4L2_CTRL_FLAG_SLIDER;
+		break;
+	case V4L2_CID_MPEG_VIDEO_ENCODING:
+		*flags |= V4L2_CTRL_FLAG_READ_ONLY;
+		break;
+	}
+}
+
+
+/********************** OLD CODE *********************/
+
+/* Must be sorted from low to high control ID! */
+const u32 cx2341x_mpeg_ctrls[] = {
+	V4L2_CID_MPEG_CLASS,
+	V4L2_CID_MPEG_STREAM_TYPE,
+	V4L2_CID_MPEG_STREAM_VBI_FMT,
+	V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ,
+	V4L2_CID_MPEG_AUDIO_ENCODING,
+	V4L2_CID_MPEG_AUDIO_L2_BITRATE,
+	V4L2_CID_MPEG_AUDIO_MODE,
+	V4L2_CID_MPEG_AUDIO_MODE_EXTENSION,
+	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,
+	V4L2_CID_MPEG_VIDEO_GOP_SIZE,
+	V4L2_CID_MPEG_VIDEO_GOP_CLOSURE,
+	V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
+	V4L2_CID_MPEG_VIDEO_BITRATE,
+	V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
+	V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION,
+	V4L2_CID_MPEG_VIDEO_MUTE,
+	V4L2_CID_MPEG_VIDEO_MUTE_YUV,
+	V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE,
+	V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER,
+	V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE,
+	V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE,
+	V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE,
+	V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER,
+	V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE,
+	V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM,
+	V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP,
+	V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM,
+	V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP,
+	V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS,
+	0
+};
+EXPORT_SYMBOL(cx2341x_mpeg_ctrls);
+
+static const struct cx2341x_mpeg_params default_params = {
+	/* misc */
+	.capabilities = 0,
+	.port = CX2341X_PORT_MEMORY,
+	.width = 720,
+	.height = 480,
+	.is_50hz = 0,
+
+	/* stream */
+	.stream_type = V4L2_MPEG_STREAM_TYPE_MPEG2_PS,
+	.stream_vbi_fmt = V4L2_MPEG_STREAM_VBI_FMT_NONE,
+	.stream_insert_nav_packets = 0,
+
+	/* audio */
+	.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,
+	.audio_crc = V4L2_MPEG_AUDIO_CRC_NONE,
+	.audio_mute = 0,
+
+	/* video */
+	.video_encoding = V4L2_MPEG_VIDEO_ENCODING_MPEG_2,
+	.video_aspect = V4L2_MPEG_VIDEO_ASPECT_4x3,
+	.video_b_frames = 2,
+	.video_gop_size = 12,
+	.video_gop_closure = 1,
+	.video_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
+	.video_bitrate = 6000000,
+	.video_bitrate_peak = 8000000,
+	.video_temporal_decimation = 0,
+	.video_mute = 0,
+	.video_mute_yuv = 0x008080,  /* YCbCr value for black */
+
+	/* encoding filters */
+	.video_spatial_filter_mode =
+		V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL,
+	.video_spatial_filter = 0,
+	.video_luma_spatial_filter_type =
+		V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_HOR,
+	.video_chroma_spatial_filter_type =
+		V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR,
+	.video_temporal_filter_mode =
+		V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL,
+	.video_temporal_filter = 8,
+	.video_median_filter_type =
+		V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF,
+	.video_luma_median_filter_top = 255,
+	.video_luma_median_filter_bottom = 0,
+	.video_chroma_median_filter_top = 255,
+	.video_chroma_median_filter_bottom = 0,
+};
+/* Map the control ID to the correct field in the cx2341x_mpeg_params
+   struct. Return -EINVAL if the ID is unknown, else return 0. */
+static int cx2341x_get_ctrl(const struct cx2341x_mpeg_params *params,
+		struct v4l2_ext_control *ctrl)
+{
+	switch (ctrl->id) {
+	case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
+		ctrl->value = params->audio_sampling_freq;
+		break;
+	case V4L2_CID_MPEG_AUDIO_ENCODING:
+		ctrl->value = params->audio_encoding;
+		break;
+	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;
+	case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
+		ctrl->value = params->audio_mode_extension;
+		break;
+	case V4L2_CID_MPEG_AUDIO_EMPHASIS:
+		ctrl->value = params->audio_emphasis;
+		break;
+	case V4L2_CID_MPEG_AUDIO_CRC:
+		ctrl->value = params->audio_crc;
+		break;
+	case V4L2_CID_MPEG_AUDIO_MUTE:
+		ctrl->value = params->audio_mute;
+		break;
+	case V4L2_CID_MPEG_VIDEO_ENCODING:
+		ctrl->value = params->video_encoding;
+		break;
+	case V4L2_CID_MPEG_VIDEO_ASPECT:
+		ctrl->value = params->video_aspect;
+		break;
+	case V4L2_CID_MPEG_VIDEO_B_FRAMES:
+		ctrl->value = params->video_b_frames;
+		break;
+	case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
+		ctrl->value = params->video_gop_size;
+		break;
+	case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
+		ctrl->value = params->video_gop_closure;
+		break;
+	case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
+		ctrl->value = params->video_bitrate_mode;
+		break;
+	case V4L2_CID_MPEG_VIDEO_BITRATE:
+		ctrl->value = params->video_bitrate;
+		break;
+	case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
+		ctrl->value = params->video_bitrate_peak;
+		break;
+	case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION:
+		ctrl->value = params->video_temporal_decimation;
+		break;
+	case V4L2_CID_MPEG_VIDEO_MUTE:
+		ctrl->value = params->video_mute;
+		break;
+	case V4L2_CID_MPEG_VIDEO_MUTE_YUV:
+		ctrl->value = params->video_mute_yuv;
+		break;
+	case V4L2_CID_MPEG_STREAM_TYPE:
+		ctrl->value = params->stream_type;
+		break;
+	case V4L2_CID_MPEG_STREAM_VBI_FMT:
+		ctrl->value = params->stream_vbi_fmt;
+		break;
+	case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
+		ctrl->value = params->video_spatial_filter_mode;
+		break;
+	case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
+		ctrl->value = params->video_spatial_filter;
+		break;
+	case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
+		ctrl->value = params->video_luma_spatial_filter_type;
+		break;
+	case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
+		ctrl->value = params->video_chroma_spatial_filter_type;
+		break;
+	case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
+		ctrl->value = params->video_temporal_filter_mode;
+		break;
+	case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
+		ctrl->value = params->video_temporal_filter;
+		break;
+	case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
+		ctrl->value = params->video_median_filter_type;
+		break;
+	case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
+		ctrl->value = params->video_luma_median_filter_top;
+		break;
+	case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
+		ctrl->value = params->video_luma_median_filter_bottom;
+		break;
+	case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
+		ctrl->value = params->video_chroma_median_filter_top;
+		break;
+	case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
+		ctrl->value = params->video_chroma_median_filter_bottom;
+		break;
+	case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
+		ctrl->value = params->stream_insert_nav_packets;
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+/* Map the control ID to the correct field in the cx2341x_mpeg_params
+   struct. Return -EINVAL if the ID is unknown, else return 0. */
+static int cx2341x_set_ctrl(struct cx2341x_mpeg_params *params, int busy,
+		struct v4l2_ext_control *ctrl)
+{
+	switch (ctrl->id) {
+	case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
+		if (busy)
+			return -EBUSY;
+		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:
+		if (busy)
+			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;
+	case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
+		params->audio_mode_extension = ctrl->value;
+		break;
+	case V4L2_CID_MPEG_AUDIO_EMPHASIS:
+		params->audio_emphasis = ctrl->value;
+		break;
+	case V4L2_CID_MPEG_AUDIO_CRC:
+		params->audio_crc = ctrl->value;
+		break;
+	case V4L2_CID_MPEG_AUDIO_MUTE:
+		params->audio_mute = ctrl->value;
+		break;
+	case V4L2_CID_MPEG_VIDEO_ASPECT:
+		params->video_aspect = ctrl->value;
+		break;
+	case V4L2_CID_MPEG_VIDEO_B_FRAMES: {
+		int b = ctrl->value + 1;
+		int gop = params->video_gop_size;
+		params->video_b_frames = ctrl->value;
+		params->video_gop_size = b * ((gop + b - 1) / b);
+		/* Max GOP size = 34 */
+		while (params->video_gop_size > 34)
+			params->video_gop_size -= b;
+		break;
+	}
+	case V4L2_CID_MPEG_VIDEO_GOP_SIZE: {
+		int b = params->video_b_frames + 1;
+		int gop = ctrl->value;
+		params->video_gop_size = b * ((gop + b - 1) / b);
+		/* Max GOP size = 34 */
+		while (params->video_gop_size > 34)
+			params->video_gop_size -= b;
+		ctrl->value = params->video_gop_size;
+		break;
+	}
+	case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
+		params->video_gop_closure = ctrl->value;
+		break;
+	case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
+		if (busy)
+			return -EBUSY;
+		/* MPEG-1 only allows CBR */
+		if (params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1 &&
+		    ctrl->value != V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
+			return -EINVAL;
+		params->video_bitrate_mode = ctrl->value;
+		break;
+	case V4L2_CID_MPEG_VIDEO_BITRATE:
+		if (busy)
+			return -EBUSY;
+		params->video_bitrate = ctrl->value;
+		break;
+	case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
+		if (busy)
+			return -EBUSY;
+		params->video_bitrate_peak = ctrl->value;
+		break;
+	case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION:
+		params->video_temporal_decimation = ctrl->value;
+		break;
+	case V4L2_CID_MPEG_VIDEO_MUTE:
+		params->video_mute = (ctrl->value != 0);
+		break;
+	case V4L2_CID_MPEG_VIDEO_MUTE_YUV:
+		params->video_mute_yuv = ctrl->value;
+		break;
+	case V4L2_CID_MPEG_STREAM_TYPE:
+		if (busy)
+			return -EBUSY;
+		params->stream_type = ctrl->value;
+		params->video_encoding =
+		    (params->stream_type == V4L2_MPEG_STREAM_TYPE_MPEG1_SS ||
+		     params->stream_type == V4L2_MPEG_STREAM_TYPE_MPEG1_VCD) ?
+			V4L2_MPEG_VIDEO_ENCODING_MPEG_1 :
+			V4L2_MPEG_VIDEO_ENCODING_MPEG_2;
+		if (params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)
+			/* MPEG-1 implies CBR */
+			params->video_bitrate_mode =
+				V4L2_MPEG_VIDEO_BITRATE_MODE_CBR;
+		break;
+	case V4L2_CID_MPEG_STREAM_VBI_FMT:
+		params->stream_vbi_fmt = ctrl->value;
+		break;
+	case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
+		params->video_spatial_filter_mode = ctrl->value;
+		break;
+	case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
+		params->video_spatial_filter = ctrl->value;
+		break;
+	case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
+		params->video_luma_spatial_filter_type = ctrl->value;
+		break;
+	case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
+		params->video_chroma_spatial_filter_type = ctrl->value;
+		break;
+	case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
+		params->video_temporal_filter_mode = ctrl->value;
+		break;
+	case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
+		params->video_temporal_filter = ctrl->value;
+		break;
+	case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
+		params->video_median_filter_type = ctrl->value;
+		break;
+	case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
+		params->video_luma_median_filter_top = ctrl->value;
+		break;
+	case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
+		params->video_luma_median_filter_bottom = ctrl->value;
+		break;
+	case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
+		params->video_chroma_median_filter_top = ctrl->value;
+		break;
+	case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
+		params->video_chroma_median_filter_bottom = ctrl->value;
+		break;
+	case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
+		params->stream_insert_nav_packets = ctrl->value;
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int cx2341x_ctrl_query_fill(struct v4l2_queryctrl *qctrl,
+				   s32 min, s32 max, s32 step, s32 def)
+{
+	const char *name;
+
+	switch (qctrl->id) {
+	/* MPEG controls */
+	case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
+	case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
+	case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
+	case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
+	case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
+	case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
+	case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
+	case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
+	case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
+	case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
+	case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
+	case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
+		cx2341x_ctrl_fill(qctrl->id, &name, &qctrl->type,
+				&min, &max, &step, &def, &qctrl->flags);
+		qctrl->minimum = min;
+		qctrl->maximum = max;
+		qctrl->step = step;
+		qctrl->default_value = def;
+		qctrl->reserved[0] = qctrl->reserved[1] = 0;
+		strlcpy(qctrl->name, name, sizeof(qctrl->name));
+		return 0;
+
+	default:
+		return v4l2_ctrl_query_fill(qctrl, min, max, step, def);
+	}
+}
+
+int cx2341x_ctrl_query(const struct cx2341x_mpeg_params *params,
+		       struct v4l2_queryctrl *qctrl)
+{
+	int err;
+
+	switch (qctrl->id) {
+	case V4L2_CID_MPEG_CLASS:
+		return v4l2_ctrl_query_fill(qctrl, 0, 0, 0, 0);
+	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:
+		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_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(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
+		   MPEG-1/2 setting */
+		err = v4l2_ctrl_query_fill(qctrl,
+					   V4L2_MPEG_VIDEO_ENCODING_MPEG_1,
+					   V4L2_MPEG_VIDEO_ENCODING_MPEG_2, 1,
+					   V4L2_MPEG_VIDEO_ENCODING_MPEG_2);
+		if (err == 0)
+			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(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(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_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);
+
+	/* CX23415/6 specific */
+	case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
+		return cx2341x_ctrl_query_fill(qctrl,
+			V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL,
+			V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO, 1,
+			default_params.video_spatial_filter_mode);
+
+	case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
+		cx2341x_ctrl_query_fill(qctrl, 0, 15, 1,
+				default_params.video_spatial_filter);
+		qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
+		if (params->video_spatial_filter_mode ==
+			    V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
+			qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
+		return 0;
+
+	case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
+		cx2341x_ctrl_query_fill(qctrl,
+			V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF,
+			V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_SYM_NON_SEPARABLE,
+			1,
+			default_params.video_luma_spatial_filter_type);
+		if (params->video_spatial_filter_mode ==
+			    V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
+			qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
+		return 0;
+
+	case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
+		cx2341x_ctrl_query_fill(qctrl,
+		    V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF,
+		    V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR,
+		    1,
+		    default_params.video_chroma_spatial_filter_type);
+		if (params->video_spatial_filter_mode ==
+			V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
+			qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
+		return 0;
+
+	case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
+		return cx2341x_ctrl_query_fill(qctrl,
+			V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL,
+			V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO, 1,
+			default_params.video_temporal_filter_mode);
+
+	case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
+		cx2341x_ctrl_query_fill(qctrl, 0, 31, 1,
+				default_params.video_temporal_filter);
+		qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
+		if (params->video_temporal_filter_mode ==
+			V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO)
+			qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
+		return 0;
+
+	case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
+		return cx2341x_ctrl_query_fill(qctrl,
+			V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF,
+			V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_DIAG, 1,
+			default_params.video_median_filter_type);
+
+	case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
+		cx2341x_ctrl_query_fill(qctrl, 0, 255, 1,
+				default_params.video_luma_median_filter_top);
+		qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
+		if (params->video_median_filter_type ==
+				V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
+			qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
+		return 0;
+
+	case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
+		cx2341x_ctrl_query_fill(qctrl, 0, 255, 1,
+				default_params.video_luma_median_filter_bottom);
+		qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
+		if (params->video_median_filter_type ==
+				V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
+			qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
+		return 0;
+
+	case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
+		cx2341x_ctrl_query_fill(qctrl, 0, 255, 1,
+				default_params.video_chroma_median_filter_top);
+		qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
+		if (params->video_median_filter_type ==
+				V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
+			qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
+		return 0;
+
+	case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
+		cx2341x_ctrl_query_fill(qctrl, 0, 255, 1,
+			default_params.video_chroma_median_filter_bottom);
+		qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
+		if (params->video_median_filter_type ==
+				V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
+			qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
+		return 0;
+
+	case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
+		return cx2341x_ctrl_query_fill(qctrl, 0, 1, 1,
+				default_params.stream_insert_nav_packets);
+
+	default:
+		return -EINVAL;
+
+	}
+}
+EXPORT_SYMBOL(cx2341x_ctrl_query);
+
+const char * const *cx2341x_ctrl_get_menu(const struct cx2341x_mpeg_params *p, u32 id)
+{
+	static const char * const mpeg_stream_type_without_ts[] = {
+		"MPEG-2 Program Stream",
+		"",
+		"MPEG-1 System Stream",
+		"MPEG-2 DVD-compatible Stream",
+		"MPEG-1 VCD-compatible Stream",
+		"MPEG-2 SVCD-compatible Stream",
+		NULL
+	};
+
+	static const char *mpeg_stream_type_with_ts[] = {
+		"MPEG-2 Program Stream",
+		"MPEG-2 Transport Stream",
+		"MPEG-1 System Stream",
+		"MPEG-2 DVD-compatible Stream",
+		"MPEG-1 VCD-compatible Stream",
+		"MPEG-2 SVCD-compatible Stream",
+		NULL
+	};
+
+	static const char *mpeg_audio_encoding_l2_ac3[] = {
+		"",
+		"MPEG-1/2 Layer II",
+		"",
+		"",
+		"AC-3",
+		NULL
+	};
+
+	switch (id) {
+	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;
+	case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
+	case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
+	case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
+	case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
+	case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
+		return cx2341x_get_menu(id);
+	default:
+		return v4l2_ctrl_get_menu(id);
+	}
+}
+EXPORT_SYMBOL(cx2341x_ctrl_get_menu);
+
+static void cx2341x_calc_audio_properties(struct cx2341x_mpeg_params *params)
+{
+	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,
+		  struct v4l2_ext_controls *ctrls, unsigned int cmd)
+{
+	int err = 0;
+	int i;
+
+	if (cmd == VIDIOC_G_EXT_CTRLS) {
+		for (i = 0; i < ctrls->count; i++) {
+			struct v4l2_ext_control *ctrl = ctrls->controls + i;
+
+			err = cx2341x_get_ctrl(params, ctrl);
+			if (err) {
+				ctrls->error_idx = i;
+				break;
+			}
+		}
+		return err;
+	}
+	for (i = 0; i < ctrls->count; i++) {
+		struct v4l2_ext_control *ctrl = ctrls->controls + i;
+		struct v4l2_queryctrl qctrl;
+		const char * const *menu_items = NULL;
+
+		qctrl.id = ctrl->id;
+		err = cx2341x_ctrl_query(params, &qctrl);
+		if (err)
+			break;
+		if (qctrl.type == V4L2_CTRL_TYPE_MENU)
+			menu_items = cx2341x_ctrl_get_menu(params, qctrl.id);
+		err = v4l2_ctrl_check(ctrl, &qctrl, menu_items);
+		if (err)
+			break;
+		err = cx2341x_set_ctrl(params, busy, ctrl);
+		if (err)
+			break;
+	}
+	if (err == 0 &&
+	    params->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR &&
+	    params->video_bitrate_peak < params->video_bitrate) {
+		err = -ERANGE;
+		ctrls->error_idx = ctrls->count;
+	}
+	if (err)
+		ctrls->error_idx = i;
+	else
+		cx2341x_calc_audio_properties(params);
+	return err;
+}
+EXPORT_SYMBOL(cx2341x_ext_ctrls);
+
+void cx2341x_fill_defaults(struct cx2341x_mpeg_params *p)
+{
+	*p = default_params;
+	cx2341x_calc_audio_properties(p);
+}
+EXPORT_SYMBOL(cx2341x_fill_defaults);
+
+static int cx2341x_api(void *priv, cx2341x_mbox_func func,
+		       u32 cmd, int args, ...)
+{
+	u32 data[CX2341X_MBOX_MAX_DATA];
+	va_list vargs;
+	int i;
+
+	va_start(vargs, args);
+
+	for (i = 0; i < args; i++)
+		data[i] = va_arg(vargs, int);
+	va_end(vargs);
+	return func(priv, cmd, args, 0, data);
+}
+
+#define NEQ(field) (old->field != new->field)
+
+int cx2341x_update(void *priv, cx2341x_mbox_func func,
+		   const struct cx2341x_mpeg_params *old,
+		   const struct cx2341x_mpeg_params *new)
+{
+	static int mpeg_stream_type[] = {
+		0,	/* MPEG-2 PS */
+		1,	/* MPEG-2 TS */
+		2,	/* MPEG-1 SS */
+		14,	/* DVD */
+		11,	/* VCD */
+		12,	/* SVCD */
+	};
+
+	int err = 0;
+	int force = (old == NULL);
+	u16 temporal = new->video_temporal_filter;
+
+	cx2341x_api(priv, func, CX2341X_ENC_SET_OUTPUT_PORT, 2, new->port, 0);
+
+	if (force || NEQ(is_50hz)) {
+		err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_RATE, 1,
+				  new->is_50hz);
+		if (err) return err;
+	}
+
+	if (force || NEQ(width) || NEQ(height) || NEQ(video_encoding)) {
+		u16 w = new->width;
+		u16 h = new->height;
+
+		if (new->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) {
+			w /= 2;
+			h /= 2;
+		}
+		err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_SIZE, 2,
+				  h, w);
+		if (err) return err;
+	}
+	if (force || NEQ(stream_type)) {
+		err = cx2341x_api(priv, func, CX2341X_ENC_SET_STREAM_TYPE, 1,
+				  mpeg_stream_type[new->stream_type]);
+		if (err) return err;
+	}
+	if (force || NEQ(video_aspect)) {
+		err = cx2341x_api(priv, func, CX2341X_ENC_SET_ASPECT_RATIO, 1,
+				  1 + new->video_aspect);
+		if (err) return err;
+	}
+	if (force || NEQ(video_b_frames) || NEQ(video_gop_size)) {
+		err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_PROPERTIES, 2,
+				new->video_gop_size, new->video_b_frames + 1);
+		if (err) return err;
+	}
+	if (force || NEQ(video_gop_closure)) {
+		err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_CLOSURE, 1,
+				  new->video_gop_closure);
+		if (err) return err;
+	}
+	if (force || NEQ(audio_properties)) {
+		err = cx2341x_api(priv, func, CX2341X_ENC_SET_AUDIO_PROPERTIES,
+				  1, new->audio_properties);
+		if (err) return err;
+	}
+	if (force || NEQ(audio_mute)) {
+		err = cx2341x_api(priv, func, CX2341X_ENC_MUTE_AUDIO, 1,
+				  new->audio_mute);
+		if (err) return err;
+	}
+	if (force || NEQ(video_bitrate_mode) || NEQ(video_bitrate) ||
+						NEQ(video_bitrate_peak)) {
+		err = cx2341x_api(priv, func, CX2341X_ENC_SET_BIT_RATE, 5,
+				new->video_bitrate_mode, new->video_bitrate,
+				new->video_bitrate_peak / 400, 0, 0);
+		if (err) return err;
+	}
+	if (force || NEQ(video_spatial_filter_mode) ||
+		     NEQ(video_temporal_filter_mode) ||
+		     NEQ(video_median_filter_type)) {
+		err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_MODE,
+				  2, new->video_spatial_filter_mode |
+					(new->video_temporal_filter_mode << 1),
+				new->video_median_filter_type);
+		if (err) return err;
+	}
+	if (force || NEQ(video_luma_median_filter_bottom) ||
+		     NEQ(video_luma_median_filter_top) ||
+		     NEQ(video_chroma_median_filter_bottom) ||
+		     NEQ(video_chroma_median_filter_top)) {
+		err = cx2341x_api(priv, func, CX2341X_ENC_SET_CORING_LEVELS, 4,
+				new->video_luma_median_filter_bottom,
+				new->video_luma_median_filter_top,
+				new->video_chroma_median_filter_bottom,
+				new->video_chroma_median_filter_top);
+		if (err) return err;
+	}
+	if (force || NEQ(video_luma_spatial_filter_type) ||
+		     NEQ(video_chroma_spatial_filter_type)) {
+		err = cx2341x_api(priv, func,
+				  CX2341X_ENC_SET_SPATIAL_FILTER_TYPE,
+				  2, new->video_luma_spatial_filter_type,
+				  new->video_chroma_spatial_filter_type);
+		if (err) return err;
+	}
+	if (force || NEQ(video_spatial_filter) ||
+		     old->video_temporal_filter != temporal) {
+		err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_PROPS,
+				  2, new->video_spatial_filter, temporal);
+		if (err) return err;
+	}
+	if (force || NEQ(video_temporal_decimation)) {
+		err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_DROP_RATE,
+				  1, new->video_temporal_decimation);
+		if (err) return err;
+	}
+	if (force || NEQ(video_mute) ||
+		(new->video_mute && NEQ(video_mute_yuv))) {
+		err = cx2341x_api(priv, func, CX2341X_ENC_MUTE_VIDEO, 1,
+				new->video_mute | (new->video_mute_yuv << 8));
+		if (err) return err;
+	}
+	if (force || NEQ(stream_insert_nav_packets)) {
+		err = cx2341x_api(priv, func, CX2341X_ENC_MISC, 2,
+				7, new->stream_insert_nav_packets);
+		if (err) return err;
+	}
+	return 0;
+}
+EXPORT_SYMBOL(cx2341x_update);
+
+static const char *cx2341x_menu_item(const struct cx2341x_mpeg_params *p, u32 id)
+{
+	const char * const *menu = cx2341x_ctrl_get_menu(p, id);
+	struct v4l2_ext_control ctrl;
+
+	if (menu == NULL)
+		goto invalid;
+	ctrl.id = id;
+	if (cx2341x_get_ctrl(p, &ctrl))
+		goto invalid;
+	while (ctrl.value-- && *menu) menu++;
+	if (*menu == NULL)
+		goto invalid;
+	return *menu;
+
+invalid:
+	return "<invalid>";
+}
+
+void cx2341x_log_status(const struct cx2341x_mpeg_params *p, const char *prefix)
+{
+	int is_mpeg1 = p->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
+
+	/* Stream */
+	printk(KERN_INFO "%s: Stream: %s",
+		prefix,
+		cx2341x_menu_item(p, V4L2_CID_MPEG_STREAM_TYPE));
+	if (p->stream_insert_nav_packets)
+		printk(" (with navigation packets)");
+	printk("\n");
+	printk(KERN_INFO "%s: VBI Format: %s\n",
+		prefix,
+		cx2341x_menu_item(p, V4L2_CID_MPEG_STREAM_VBI_FMT));
+
+	/* Video */
+	printk(KERN_INFO "%s: Video:  %dx%d, %d fps%s\n",
+		prefix,
+		p->width / (is_mpeg1 ? 2 : 1), p->height / (is_mpeg1 ? 2 : 1),
+		p->is_50hz ? 25 : 30,
+		(p->video_mute) ? " (muted)" : "");
+	printk(KERN_INFO "%s: Video:  %s, %s, %s, %d",
+		prefix,
+		cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ENCODING),
+		cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ASPECT),
+		cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_BITRATE_MODE),
+		p->video_bitrate);
+	if (p->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR)
+		printk(", Peak %d", p->video_bitrate_peak);
+	printk("\n");
+	printk(KERN_INFO
+		"%s: Video:  GOP Size %d, %d B-Frames, %sGOP Closure\n",
+		prefix,
+		p->video_gop_size, p->video_b_frames,
+		p->video_gop_closure ? "" : "No ");
+	if (p->video_temporal_decimation)
+		printk(KERN_INFO "%s: Video: Temporal Decimation %d\n",
+			prefix, p->video_temporal_decimation);
+
+	/* Audio */
+	printk(KERN_INFO "%s: Audio:  %s, %s, %s, %s%s",
+		prefix,
+		cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ),
+		cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_ENCODING),
+		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)
+		printk(", %s", cx2341x_menu_item(p,
+				V4L2_CID_MPEG_AUDIO_MODE_EXTENSION));
+	printk(", %s, %s\n",
+		cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_EMPHASIS),
+		cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_CRC));
+
+	/* Encoding filters */
+	printk(KERN_INFO "%s: Spatial Filter:  %s, Luma %s, Chroma %s, %d\n",
+		prefix,
+		cx2341x_menu_item(p,
+		    V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE),
+		cx2341x_menu_item(p,
+		    V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE),
+		cx2341x_menu_item(p,
+		    V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE),
+		p->video_spatial_filter);
+
+	printk(KERN_INFO "%s: Temporal Filter: %s, %d\n",
+		prefix,
+		cx2341x_menu_item(p,
+			V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE),
+		p->video_temporal_filter);
+	printk(KERN_INFO
+		"%s: Median Filter:   %s, Luma [%d, %d], Chroma [%d, %d]\n",
+		prefix,
+		cx2341x_menu_item(p,
+			V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE),
+		p->video_luma_median_filter_bottom,
+		p->video_luma_median_filter_top,
+		p->video_chroma_median_filter_bottom,
+		p->video_chroma_median_filter_top);
+}
+EXPORT_SYMBOL(cx2341x_log_status);
+
+
+
+/********************** NEW CODE *********************/
+
+static inline struct cx2341x_handler *to_cxhdl(struct v4l2_ctrl *ctrl)
+{
+	return container_of(ctrl->handler, struct cx2341x_handler, hdl);
+}
+
+static int cx2341x_hdl_api(struct cx2341x_handler *hdl,
+		       u32 cmd, int args, ...)
+{
+	u32 data[CX2341X_MBOX_MAX_DATA];
+	va_list vargs;
+	int i;
+
+	va_start(vargs, args);
+
+	for (i = 0; i < args; i++)
+		data[i] = va_arg(vargs, int);
+	va_end(vargs);
+	return hdl->func(hdl->priv, cmd, args, 0, data);
+}
+
+/* ctrl->handler->lock is held, so it is safe to access cur.val */
+static inline int cx2341x_neq(struct v4l2_ctrl *ctrl)
+{
+	return ctrl && ctrl->val != ctrl->cur.val;
+}
+
+static int cx2341x_try_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct cx2341x_handler *hdl = to_cxhdl(ctrl);
+	s32 val = ctrl->val;
+
+	switch (ctrl->id) {
+	case V4L2_CID_MPEG_VIDEO_B_FRAMES: {
+		/* video gop cluster */
+		int b = val + 1;
+		int gop = hdl->video_gop_size->val;
+
+		gop = b * ((gop + b - 1) / b);
+
+		/* Max GOP size = 34 */
+		while (gop > 34)
+			gop -= b;
+		hdl->video_gop_size->val = gop;
+		break;
+	}
+
+	case V4L2_CID_MPEG_STREAM_TYPE:
+		/* stream type cluster */
+		hdl->video_encoding->val =
+		    (hdl->stream_type->val == V4L2_MPEG_STREAM_TYPE_MPEG1_SS ||
+		     hdl->stream_type->val == V4L2_MPEG_STREAM_TYPE_MPEG1_VCD) ?
+			V4L2_MPEG_VIDEO_ENCODING_MPEG_1 :
+			V4L2_MPEG_VIDEO_ENCODING_MPEG_2;
+		if (hdl->video_encoding->val == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)
+			/* MPEG-1 implies CBR */
+			hdl->video_bitrate_mode->val =
+				V4L2_MPEG_VIDEO_BITRATE_MODE_CBR;
+		/* peak bitrate shall be >= normal bitrate */
+		if (hdl->video_bitrate_mode->val == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR &&
+		    hdl->video_bitrate_peak->val < hdl->video_bitrate->val)
+			hdl->video_bitrate_peak->val = hdl->video_bitrate->val;
+		break;
+	}
+	return 0;
+}
+
+static int cx2341x_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	static const int mpeg_stream_type[] = {
+		0,	/* MPEG-2 PS */
+		1,	/* MPEG-2 TS */
+		2,	/* MPEG-1 SS */
+		14,	/* DVD */
+		11,	/* VCD */
+		12,	/* SVCD */
+	};
+	struct cx2341x_handler *hdl = to_cxhdl(ctrl);
+	s32 val = ctrl->val;
+	u32 props;
+	int err;
+
+	switch (ctrl->id) {
+	case V4L2_CID_MPEG_STREAM_VBI_FMT:
+		if (hdl->ops && hdl->ops->s_stream_vbi_fmt)
+			return hdl->ops->s_stream_vbi_fmt(hdl, val);
+		return 0;
+
+	case V4L2_CID_MPEG_VIDEO_ASPECT:
+		return cx2341x_hdl_api(hdl,
+			CX2341X_ENC_SET_ASPECT_RATIO, 1, val + 1);
+
+	case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
+		return cx2341x_hdl_api(hdl, CX2341X_ENC_SET_GOP_CLOSURE, 1, val);
+
+	case V4L2_CID_MPEG_AUDIO_MUTE:
+		return cx2341x_hdl_api(hdl, CX2341X_ENC_MUTE_AUDIO, 1, val);
+
+	case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION:
+		return cx2341x_hdl_api(hdl,
+			CX2341X_ENC_SET_FRAME_DROP_RATE, 1, val);
+
+	case V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS:
+		return cx2341x_hdl_api(hdl, CX2341X_ENC_MISC, 2, 7, val);
+
+	case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
+		/* audio properties cluster */
+		props = (hdl->audio_sampling_freq->val << 0) |
+			(hdl->audio_mode->val << 8) |
+			(hdl->audio_mode_extension->val << 10) |
+			(hdl->audio_crc->val << 14);
+		if (hdl->audio_emphasis->val == V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17)
+			props |= 3 << 12;
+		else
+			props |= hdl->audio_emphasis->val << 12;
+
+		if (hdl->audio_encoding->val == V4L2_MPEG_AUDIO_ENCODING_AC3) {
+			props |=
+#if 1
+				/* Not sure if this MPEG Layer II setting is required */
+				((3 - V4L2_MPEG_AUDIO_ENCODING_LAYER_2) << 2) |
+#endif
+				(hdl->audio_ac3_bitrate->val << 4) |
+				(CX2341X_AUDIO_ENCODING_METHOD_AC3 << 28);
+		} else {
+			/* Assuming MPEG Layer II */
+			props |=
+				((3 - hdl->audio_encoding->val) << 2) |
+				((1 + hdl->audio_l2_bitrate->val) << 4);
+		}
+		err = cx2341x_hdl_api(hdl,
+				CX2341X_ENC_SET_AUDIO_PROPERTIES, 1, props);
+		if (err)
+			return err;
+
+		hdl->audio_properties = props;
+		if (hdl->audio_ac3_bitrate) {
+			int is_ac3 = hdl->audio_encoding->val ==
+						V4L2_MPEG_AUDIO_ENCODING_AC3;
+
+			v4l2_ctrl_activate(hdl->audio_ac3_bitrate, is_ac3);
+			v4l2_ctrl_activate(hdl->audio_l2_bitrate, !is_ac3);
+		}
+		v4l2_ctrl_activate(hdl->audio_mode_extension,
+			hdl->audio_mode->val == V4L2_MPEG_AUDIO_MODE_JOINT_STEREO);
+		if (cx2341x_neq(hdl->audio_sampling_freq) &&
+		    hdl->ops && hdl->ops->s_audio_sampling_freq)
+			return hdl->ops->s_audio_sampling_freq(hdl, hdl->audio_sampling_freq->val);
+		if (cx2341x_neq(hdl->audio_mode) &&
+		    hdl->ops && hdl->ops->s_audio_mode)
+			return hdl->ops->s_audio_mode(hdl, hdl->audio_mode->val);
+		return 0;
+
+	case V4L2_CID_MPEG_VIDEO_B_FRAMES:
+		/* video gop cluster */
+		return cx2341x_hdl_api(hdl, CX2341X_ENC_SET_GOP_PROPERTIES, 2,
+				hdl->video_gop_size->val,
+				hdl->video_b_frames->val + 1);
+
+	case V4L2_CID_MPEG_STREAM_TYPE:
+		/* stream type cluster */
+		err = cx2341x_hdl_api(hdl,
+			CX2341X_ENC_SET_STREAM_TYPE, 1, mpeg_stream_type[val]);
+		if (err)
+			return err;
+
+		err = cx2341x_hdl_api(hdl, CX2341X_ENC_SET_BIT_RATE, 5,
+				hdl->video_bitrate_mode->val,
+				hdl->video_bitrate->val,
+				hdl->video_bitrate_peak->val / 400, 0, 0);
+		if (err)
+			return err;
+
+		v4l2_ctrl_activate(hdl->video_bitrate_mode,
+			hdl->video_encoding->val != V4L2_MPEG_VIDEO_ENCODING_MPEG_1);
+		v4l2_ctrl_activate(hdl->video_bitrate_peak,
+			hdl->video_bitrate_mode->val != V4L2_MPEG_VIDEO_BITRATE_MODE_CBR);
+		if (cx2341x_neq(hdl->video_encoding) &&
+		    hdl->ops && hdl->ops->s_video_encoding)
+			return hdl->ops->s_video_encoding(hdl, hdl->video_encoding->val);
+		return 0;
+
+	case V4L2_CID_MPEG_VIDEO_MUTE:
+		/* video mute cluster */
+		return cx2341x_hdl_api(hdl, CX2341X_ENC_MUTE_VIDEO, 1,
+				hdl->video_mute->val |
+					(hdl->video_mute_yuv->val << 8));
+
+	case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE: {
+		int active_filter;
+
+		/* video filter mode */
+		err = cx2341x_hdl_api(hdl, CX2341X_ENC_SET_DNR_FILTER_MODE, 2,
+				hdl->video_spatial_filter_mode->val |
+					(hdl->video_temporal_filter_mode->val << 1),
+				hdl->video_median_filter_type->val);
+		if (err)
+			return err;
+
+		active_filter = hdl->video_spatial_filter_mode->val !=
+				V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO;
+		v4l2_ctrl_activate(hdl->video_spatial_filter, active_filter);
+		v4l2_ctrl_activate(hdl->video_luma_spatial_filter_type, active_filter);
+		v4l2_ctrl_activate(hdl->video_chroma_spatial_filter_type, active_filter);
+		active_filter = hdl->video_temporal_filter_mode->val !=
+				V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO;
+		v4l2_ctrl_activate(hdl->video_temporal_filter, active_filter);
+		active_filter = hdl->video_median_filter_type->val !=
+				V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF;
+		v4l2_ctrl_activate(hdl->video_luma_median_filter_bottom, active_filter);
+		v4l2_ctrl_activate(hdl->video_luma_median_filter_top, active_filter);
+		v4l2_ctrl_activate(hdl->video_chroma_median_filter_bottom, active_filter);
+		v4l2_ctrl_activate(hdl->video_chroma_median_filter_top, active_filter);
+		return 0;
+	}
+
+	case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
+		/* video filter type cluster */
+		return cx2341x_hdl_api(hdl,
+				CX2341X_ENC_SET_SPATIAL_FILTER_TYPE, 2,
+				hdl->video_luma_spatial_filter_type->val,
+				hdl->video_chroma_spatial_filter_type->val);
+
+	case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
+		/* video filter cluster */
+		return cx2341x_hdl_api(hdl, CX2341X_ENC_SET_DNR_FILTER_PROPS, 2,
+				hdl->video_spatial_filter->val,
+				hdl->video_temporal_filter->val);
+
+	case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
+		/* video median cluster */
+		return cx2341x_hdl_api(hdl, CX2341X_ENC_SET_CORING_LEVELS, 4,
+				hdl->video_luma_median_filter_bottom->val,
+				hdl->video_luma_median_filter_top->val,
+				hdl->video_chroma_median_filter_bottom->val,
+				hdl->video_chroma_median_filter_top->val);
+	}
+	return -EINVAL;
+}
+
+static const struct v4l2_ctrl_ops cx2341x_ops = {
+	.try_ctrl = cx2341x_try_ctrl,
+	.s_ctrl = cx2341x_s_ctrl,
+};
+
+static struct v4l2_ctrl *cx2341x_ctrl_new_custom(struct v4l2_ctrl_handler *hdl,
+			u32 id, s32 min, s32 max, s32 step, s32 def)
+{
+	struct v4l2_ctrl_config cfg;
+
+	cx2341x_ctrl_fill(id, &cfg.name, &cfg.type, &min, &max, &step, &def, &cfg.flags);
+	cfg.ops = &cx2341x_ops;
+	cfg.id = id;
+	cfg.min = min;
+	cfg.max = max;
+	cfg.def = def;
+	if (cfg.type == V4L2_CTRL_TYPE_MENU) {
+		cfg.step = 0;
+		cfg.menu_skip_mask = step;
+		cfg.qmenu = cx2341x_get_menu(id);
+	} else {
+		cfg.step = step;
+		cfg.menu_skip_mask = 0;
+	}
+	return v4l2_ctrl_new_custom(hdl, &cfg, NULL);
+}
+
+static struct v4l2_ctrl *cx2341x_ctrl_new_std(struct v4l2_ctrl_handler *hdl,
+			u32 id, s32 min, s32 max, s32 step, s32 def)
+{
+	return v4l2_ctrl_new_std(hdl, &cx2341x_ops, id, min, max, step, def);
+}
+
+static struct v4l2_ctrl *cx2341x_ctrl_new_menu(struct v4l2_ctrl_handler *hdl,
+			u32 id, s32 max, s32 mask, s32 def)
+{
+	return v4l2_ctrl_new_std_menu(hdl, &cx2341x_ops, id, max, mask, def);
+}
+
+int cx2341x_handler_init(struct cx2341x_handler *cxhdl,
+			 unsigned nr_of_controls_hint)
+{
+	struct v4l2_ctrl_handler *hdl = &cxhdl->hdl;
+	u32 caps = cxhdl->capabilities;
+	int has_sliced_vbi = caps & CX2341X_CAP_HAS_SLICED_VBI;
+	int has_ac3 = caps & CX2341X_CAP_HAS_AC3;
+	int has_ts = caps & CX2341X_CAP_HAS_TS;
+
+	cxhdl->width = 720;
+	cxhdl->height = 480;
+
+	v4l2_ctrl_handler_init(hdl, nr_of_controls_hint);
+
+	/* Add controls in ascending control ID order for fastest
+	   insertion time. */
+	cxhdl->stream_type = cx2341x_ctrl_new_menu(hdl,
+			V4L2_CID_MPEG_STREAM_TYPE,
+			V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD, has_ts ? 0 : 2,
+			V4L2_MPEG_STREAM_TYPE_MPEG2_PS);
+	cxhdl->stream_vbi_fmt = cx2341x_ctrl_new_menu(hdl,
+			V4L2_CID_MPEG_STREAM_VBI_FMT,
+			V4L2_MPEG_STREAM_VBI_FMT_IVTV, has_sliced_vbi ? 0 : 2,
+			V4L2_MPEG_STREAM_VBI_FMT_NONE);
+	cxhdl->audio_sampling_freq = cx2341x_ctrl_new_menu(hdl,
+			V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ,
+			V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000, 0,
+			V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000);
+	cxhdl->audio_encoding = cx2341x_ctrl_new_menu(hdl,
+			V4L2_CID_MPEG_AUDIO_ENCODING,
+			V4L2_MPEG_AUDIO_ENCODING_AC3, has_ac3 ? ~0x12 : ~0x2,
+			V4L2_MPEG_AUDIO_ENCODING_LAYER_2);
+	cxhdl->audio_l2_bitrate = cx2341x_ctrl_new_menu(hdl,
+			V4L2_CID_MPEG_AUDIO_L2_BITRATE,
+			V4L2_MPEG_AUDIO_L2_BITRATE_384K, 0x1ff,
+			V4L2_MPEG_AUDIO_L2_BITRATE_224K);
+	cxhdl->audio_mode = cx2341x_ctrl_new_menu(hdl,
+			V4L2_CID_MPEG_AUDIO_MODE,
+			V4L2_MPEG_AUDIO_MODE_MONO, 0,
+			V4L2_MPEG_AUDIO_MODE_STEREO);
+	cxhdl->audio_mode_extension = cx2341x_ctrl_new_menu(hdl,
+			V4L2_CID_MPEG_AUDIO_MODE_EXTENSION,
+			V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_16, 0,
+			V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4);
+	cxhdl->audio_emphasis = cx2341x_ctrl_new_menu(hdl,
+			V4L2_CID_MPEG_AUDIO_EMPHASIS,
+			V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17, 0,
+			V4L2_MPEG_AUDIO_EMPHASIS_NONE);
+	cxhdl->audio_crc = cx2341x_ctrl_new_menu(hdl,
+			V4L2_CID_MPEG_AUDIO_CRC,
+			V4L2_MPEG_AUDIO_CRC_CRC16, 0,
+			V4L2_MPEG_AUDIO_CRC_NONE);
+
+	cx2341x_ctrl_new_std(hdl, V4L2_CID_MPEG_AUDIO_MUTE, 0, 1, 1, 0);
+	if (has_ac3)
+		cxhdl->audio_ac3_bitrate = cx2341x_ctrl_new_menu(hdl,
+				V4L2_CID_MPEG_AUDIO_AC3_BITRATE,
+				V4L2_MPEG_AUDIO_AC3_BITRATE_448K, 0x03,
+				V4L2_MPEG_AUDIO_AC3_BITRATE_224K);
+	cxhdl->video_encoding = cx2341x_ctrl_new_menu(hdl,
+			V4L2_CID_MPEG_VIDEO_ENCODING,
+			V4L2_MPEG_VIDEO_ENCODING_MPEG_2, 0,
+			V4L2_MPEG_VIDEO_ENCODING_MPEG_2);
+	cx2341x_ctrl_new_menu(hdl,
+			V4L2_CID_MPEG_VIDEO_ASPECT,
+			V4L2_MPEG_VIDEO_ASPECT_221x100, 0,
+			V4L2_MPEG_VIDEO_ASPECT_4x3);
+	cxhdl->video_b_frames = cx2341x_ctrl_new_std(hdl,
+			V4L2_CID_MPEG_VIDEO_B_FRAMES, 0, 33, 1, 2);
+	cxhdl->video_gop_size = cx2341x_ctrl_new_std(hdl,
+			V4L2_CID_MPEG_VIDEO_GOP_SIZE,
+			1, 34, 1, cxhdl->is_50hz ? 12 : 15);
+	cx2341x_ctrl_new_std(hdl, V4L2_CID_MPEG_VIDEO_GOP_CLOSURE, 0, 1, 1, 1);
+	cxhdl->video_bitrate_mode = cx2341x_ctrl_new_menu(hdl,
+			V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
+			V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 0,
+			V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
+	cxhdl->video_bitrate = cx2341x_ctrl_new_std(hdl,
+			V4L2_CID_MPEG_VIDEO_BITRATE,
+			0, 27000000, 1, 6000000);
+	cxhdl->video_bitrate_peak = cx2341x_ctrl_new_std(hdl,
+			V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
+			0, 27000000, 1, 8000000);
+	cx2341x_ctrl_new_std(hdl,
+			V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION, 0, 255, 1, 0);
+	cxhdl->video_mute = cx2341x_ctrl_new_std(hdl,
+			V4L2_CID_MPEG_VIDEO_MUTE, 0, 1, 1, 0);
+	cxhdl->video_mute_yuv = cx2341x_ctrl_new_std(hdl,
+			V4L2_CID_MPEG_VIDEO_MUTE_YUV, 0, 0xffffff, 1, 0x008080);
+
+	/* CX23415/6 specific */
+	cxhdl->video_spatial_filter_mode = cx2341x_ctrl_new_custom(hdl,
+			V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE,
+			V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL,
+			V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO, 0,
+			V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL);
+	cxhdl->video_spatial_filter = cx2341x_ctrl_new_custom(hdl,
+			V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER,
+			0, 15, 1, 0);
+	cxhdl->video_luma_spatial_filter_type = cx2341x_ctrl_new_custom(hdl,
+			V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE,
+			V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF,
+			V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_SYM_NON_SEPARABLE,
+			0,
+			V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_HOR);
+	cxhdl->video_chroma_spatial_filter_type = cx2341x_ctrl_new_custom(hdl,
+			V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE,
+			V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF,
+			V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR,
+			0,
+			V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR);
+	cxhdl->video_temporal_filter_mode = cx2341x_ctrl_new_custom(hdl,
+			V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE,
+			V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL,
+			V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO,
+			0,
+			V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL);
+	cxhdl->video_temporal_filter = cx2341x_ctrl_new_custom(hdl,
+			V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER,
+			0, 31, 1, 8);
+	cxhdl->video_median_filter_type = cx2341x_ctrl_new_custom(hdl,
+			V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE,
+			V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF,
+			V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_DIAG,
+			0,
+			V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF);
+	cxhdl->video_luma_median_filter_bottom = cx2341x_ctrl_new_custom(hdl,
+			V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM,
+			0, 255, 1, 0);
+	cxhdl->video_luma_median_filter_top = cx2341x_ctrl_new_custom(hdl,
+			V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP,
+			0, 255, 1, 255);
+	cxhdl->video_chroma_median_filter_bottom = cx2341x_ctrl_new_custom(hdl,
+			V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM,
+			0, 255, 1, 0);
+	cxhdl->video_chroma_median_filter_top = cx2341x_ctrl_new_custom(hdl,
+			V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP,
+			0, 255, 1, 255);
+	cx2341x_ctrl_new_custom(hdl, V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS,
+			0, 1, 1, 0);
+
+	if (hdl->error) {
+		int err = hdl->error;
+
+		v4l2_ctrl_handler_free(hdl);
+		return err;
+	}
+
+	v4l2_ctrl_cluster(8, &cxhdl->audio_sampling_freq);
+	v4l2_ctrl_cluster(2, &cxhdl->video_b_frames);
+	v4l2_ctrl_cluster(5, &cxhdl->stream_type);
+	v4l2_ctrl_cluster(2, &cxhdl->video_mute);
+	v4l2_ctrl_cluster(3, &cxhdl->video_spatial_filter_mode);
+	v4l2_ctrl_cluster(2, &cxhdl->video_luma_spatial_filter_type);
+	v4l2_ctrl_cluster(2, &cxhdl->video_spatial_filter);
+	v4l2_ctrl_cluster(4, &cxhdl->video_luma_median_filter_top);
+
+	return 0;
+}
+EXPORT_SYMBOL(cx2341x_handler_init);
+
+void cx2341x_handler_set_50hz(struct cx2341x_handler *cxhdl, int is_50hz)
+{
+	cxhdl->is_50hz = is_50hz;
+	cxhdl->video_gop_size->default_value = cxhdl->is_50hz ? 12 : 15;
+}
+EXPORT_SYMBOL(cx2341x_handler_set_50hz);
+
+int cx2341x_handler_setup(struct cx2341x_handler *cxhdl)
+{
+	int h = cxhdl->height;
+	int w = cxhdl->width;
+	int err;
+
+	err = cx2341x_hdl_api(cxhdl, CX2341X_ENC_SET_OUTPUT_PORT, 2, cxhdl->port, 0);
+	if (err)
+		return err;
+	err = cx2341x_hdl_api(cxhdl, CX2341X_ENC_SET_FRAME_RATE, 1, cxhdl->is_50hz);
+	if (err)
+		return err;
+
+	if (v4l2_ctrl_g_ctrl(cxhdl->video_encoding) == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) {
+		w /= 2;
+		h /= 2;
+	}
+	err = cx2341x_hdl_api(cxhdl, CX2341X_ENC_SET_FRAME_SIZE, 2, h, w);
+	if (err)
+		return err;
+	return v4l2_ctrl_handler_setup(&cxhdl->hdl);
+}
+EXPORT_SYMBOL(cx2341x_handler_setup);
+
+void cx2341x_handler_set_busy(struct cx2341x_handler *cxhdl, int busy)
+{
+	v4l2_ctrl_grab(cxhdl->audio_sampling_freq, busy);
+	v4l2_ctrl_grab(cxhdl->audio_encoding, busy);
+	v4l2_ctrl_grab(cxhdl->audio_l2_bitrate, busy);
+	v4l2_ctrl_grab(cxhdl->audio_ac3_bitrate, busy);
+	v4l2_ctrl_grab(cxhdl->stream_vbi_fmt, busy);
+	v4l2_ctrl_grab(cxhdl->stream_type, busy);
+	v4l2_ctrl_grab(cxhdl->video_bitrate_mode, busy);
+	v4l2_ctrl_grab(cxhdl->video_bitrate, busy);
+	v4l2_ctrl_grab(cxhdl->video_bitrate_peak, busy);
+}
+EXPORT_SYMBOL(cx2341x_handler_set_busy);
diff --git a/drivers/media/i2c/cx25840/Kconfig b/drivers/media/i2c/cx25840/Kconfig
new file mode 100644
index 0000000..451133a
--- /dev/null
+++ b/drivers/media/i2c/cx25840/Kconfig
@@ -0,0 +1,8 @@
+config VIDEO_CX25840
+	tristate "Conexant CX2584x audio/video decoders"
+	depends on VIDEO_V4L2 && I2C
+	---help---
+	  Support for the Conexant CX2584x audio/video decoders.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called cx25840
diff --git a/drivers/media/i2c/cx25840/Makefile b/drivers/media/i2c/cx25840/Makefile
new file mode 100644
index 0000000..898eb13
--- /dev/null
+++ b/drivers/media/i2c/cx25840/Makefile
@@ -0,0 +1,6 @@
+cx25840-objs    := cx25840-core.o cx25840-audio.o cx25840-firmware.o \
+		   cx25840-vbi.o cx25840-ir.o
+
+obj-$(CONFIG_VIDEO_CX25840) += cx25840.o
+
+ccflags-y += -Idrivers/media/i2c
diff --git a/drivers/media/i2c/cx25840/cx25840-audio.c b/drivers/media/i2c/cx25840/cx25840-audio.c
new file mode 100644
index 0000000..34b96c7
--- /dev/null
+++ b/drivers/media/i2c/cx25840/cx25840-audio.c
@@ -0,0 +1,571 @@
+/* cx25840 audio functions
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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/videodev2.h>
+#include <linux/i2c.h>
+#include <media/v4l2-common.h>
+#include <media/cx25840.h>
+
+#include "cx25840-core.h"
+
+/*
+ * Note: The PLL and SRC parameters are based on a reference frequency that
+ * would ideally be:
+ *
+ * NTSC Color subcarrier freq * 8 = 4.5 MHz/286 * 455/2 * 8 = 28.63636363... MHz
+ *
+ * However, it's not the exact reference frequency that matters, only that the
+ * firmware and modules that comprise the driver for a particular board all
+ * use the same value (close to the ideal value).
+ *
+ * Comments below will note which reference frequency is assumed for various
+ * parameters.  They will usually be one of
+ *
+ *	ref_freq = 28.636360 MHz
+ *		or
+ *	ref_freq = 28.636363 MHz
+ */
+
+static int cx25840_set_audclk_freq(struct i2c_client *client, u32 freq)
+{
+	struct cx25840_state *state = to_state(i2c_get_clientdata(client));
+
+	if (state->aud_input != CX25840_AUDIO_SERIAL) {
+		switch (freq) {
+		case 32000:
+			/*
+			 * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04
+			 * AUX_PLL Integer = 0x06, AUX PLL Post Divider = 0x10
+			 */
+			cx25840_write4(client, 0x108, 0x1006040f);
+
+			/*
+			 * VID_PLL Fraction (register 0x10c) = 0x2be2fe
+			 * 28636360 * 0xf.15f17f0/4 = 108 MHz
+			 * 432 MHz pre-postdivide
+			 */
+
+			/*
+			 * AUX_PLL Fraction = 0x1bb39ee
+			 * 28636363 * 0x6.dd9cf70/0x10 = 32000 * 384
+			 * 196.6 MHz pre-postdivide
+			 * FIXME < 200 MHz is out of specified valid range
+			 * FIXME 28636363 ref_freq doesn't match VID PLL ref
+			 */
+			cx25840_write4(client, 0x110, 0x01bb39ee);
+
+			/*
+			 * SA_MCLK_SEL = 1
+			 * SA_MCLK_DIV = 0x10 = 384/384 * AUX_PLL post dvivider
+			 */
+			cx25840_write(client, 0x127, 0x50);
+
+			if (is_cx2583x(state))
+				break;
+
+			/* src3/4/6_ctl */
+			/* 0x1.f77f = (4 * 28636360/8 * 2/455) / 32000 */
+			cx25840_write4(client, 0x900, 0x0801f77f);
+			cx25840_write4(client, 0x904, 0x0801f77f);
+			cx25840_write4(client, 0x90c, 0x0801f77f);
+			break;
+
+		case 44100:
+			/*
+			 * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04
+			 * AUX_PLL Integer = 0x09, AUX PLL Post Divider = 0x10
+			 */
+			cx25840_write4(client, 0x108, 0x1009040f);
+
+			/*
+			 * VID_PLL Fraction (register 0x10c) = 0x2be2fe
+			 * 28636360 * 0xf.15f17f0/4 = 108 MHz
+			 * 432 MHz pre-postdivide
+			 */
+
+			/*
+			 * AUX_PLL Fraction = 0x0ec6bd6
+			 * 28636363 * 0x9.7635eb0/0x10 = 44100 * 384
+			 * 271 MHz pre-postdivide
+			 * FIXME 28636363 ref_freq doesn't match VID PLL ref
+			 */
+			cx25840_write4(client, 0x110, 0x00ec6bd6);
+
+			/*
+			 * SA_MCLK_SEL = 1
+			 * SA_MCLK_DIV = 0x10 = 384/384 * AUX_PLL post dvivider
+			 */
+			cx25840_write(client, 0x127, 0x50);
+
+			if (is_cx2583x(state))
+				break;
+
+			/* src3/4/6_ctl */
+			/* 0x1.6d59 = (4 * 28636360/8 * 2/455) / 44100 */
+			cx25840_write4(client, 0x900, 0x08016d59);
+			cx25840_write4(client, 0x904, 0x08016d59);
+			cx25840_write4(client, 0x90c, 0x08016d59);
+			break;
+
+		case 48000:
+			/*
+			 * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04
+			 * AUX_PLL Integer = 0x0a, AUX PLL Post Divider = 0x10
+			 */
+			cx25840_write4(client, 0x108, 0x100a040f);
+
+			/*
+			 * VID_PLL Fraction (register 0x10c) = 0x2be2fe
+			 * 28636360 * 0xf.15f17f0/4 = 108 MHz
+			 * 432 MHz pre-postdivide
+			 */
+
+			/*
+			 * AUX_PLL Fraction = 0x098d6e5
+			 * 28636363 * 0xa.4c6b728/0x10 = 48000 * 384
+			 * 295 MHz pre-postdivide
+			 * FIXME 28636363 ref_freq doesn't match VID PLL ref
+			 */
+			cx25840_write4(client, 0x110, 0x0098d6e5);
+
+			/*
+			 * SA_MCLK_SEL = 1
+			 * SA_MCLK_DIV = 0x10 = 384/384 * AUX_PLL post dvivider
+			 */
+			cx25840_write(client, 0x127, 0x50);
+
+			if (is_cx2583x(state))
+				break;
+
+			/* src3/4/6_ctl */
+			/* 0x1.4faa = (4 * 28636360/8 * 2/455) / 48000 */
+			cx25840_write4(client, 0x900, 0x08014faa);
+			cx25840_write4(client, 0x904, 0x08014faa);
+			cx25840_write4(client, 0x90c, 0x08014faa);
+			break;
+		}
+	} else {
+		switch (freq) {
+		case 32000:
+			/*
+			 * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04
+			 * AUX_PLL Integer = 0x08, AUX PLL Post Divider = 0x1e
+			 */
+			cx25840_write4(client, 0x108, 0x1e08040f);
+
+			/*
+			 * VID_PLL Fraction (register 0x10c) = 0x2be2fe
+			 * 28636360 * 0xf.15f17f0/4 = 108 MHz
+			 * 432 MHz pre-postdivide
+			 */
+
+			/*
+			 * AUX_PLL Fraction = 0x12a0869
+			 * 28636363 * 0x8.9504348/0x1e = 32000 * 256
+			 * 246 MHz pre-postdivide
+			 * FIXME 28636363 ref_freq doesn't match VID PLL ref
+			 */
+			cx25840_write4(client, 0x110, 0x012a0869);
+
+			/*
+			 * SA_MCLK_SEL = 1
+			 * SA_MCLK_DIV = 0x14 = 256/384 * AUX_PLL post dvivider
+			 */
+			cx25840_write(client, 0x127, 0x54);
+
+			if (is_cx2583x(state))
+				break;
+
+			/* src1_ctl */
+			/* 0x1.0000 = 32000/32000 */
+			cx25840_write4(client, 0x8f8, 0x08010000);
+
+			/* src3/4/6_ctl */
+			/* 0x2.0000 = 2 * (32000/32000) */
+			cx25840_write4(client, 0x900, 0x08020000);
+			cx25840_write4(client, 0x904, 0x08020000);
+			cx25840_write4(client, 0x90c, 0x08020000);
+			break;
+
+		case 44100:
+			/*
+			 * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04
+			 * AUX_PLL Integer = 0x09, AUX PLL Post Divider = 0x18
+			 */
+			cx25840_write4(client, 0x108, 0x1809040f);
+
+			/*
+			 * VID_PLL Fraction (register 0x10c) = 0x2be2fe
+			 * 28636360 * 0xf.15f17f0/4 = 108 MHz
+			 * 432 MHz pre-postdivide
+			 */
+
+			/*
+			 * AUX_PLL Fraction = 0x0ec6bd6
+			 * 28636363 * 0x9.7635eb0/0x18 = 44100 * 256
+			 * 271 MHz pre-postdivide
+			 * FIXME 28636363 ref_freq doesn't match VID PLL ref
+			 */
+			cx25840_write4(client, 0x110, 0x00ec6bd6);
+
+			/*
+			 * SA_MCLK_SEL = 1
+			 * SA_MCLK_DIV = 0x10 = 256/384 * AUX_PLL post dvivider
+			 */
+			cx25840_write(client, 0x127, 0x50);
+
+			if (is_cx2583x(state))
+				break;
+
+			/* src1_ctl */
+			/* 0x1.60cd = 44100/32000 */
+			cx25840_write4(client, 0x8f8, 0x080160cd);
+
+			/* src3/4/6_ctl */
+			/* 0x1.7385 = 2 * (32000/44100) */
+			cx25840_write4(client, 0x900, 0x08017385);
+			cx25840_write4(client, 0x904, 0x08017385);
+			cx25840_write4(client, 0x90c, 0x08017385);
+			break;
+
+		case 48000:
+			/*
+			 * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04
+			 * AUX_PLL Integer = 0x0a, AUX PLL Post Divider = 0x18
+			 */
+			cx25840_write4(client, 0x108, 0x180a040f);
+
+			/*
+			 * VID_PLL Fraction (register 0x10c) = 0x2be2fe
+			 * 28636360 * 0xf.15f17f0/4 = 108 MHz
+			 * 432 MHz pre-postdivide
+			 */
+
+			/*
+			 * AUX_PLL Fraction = 0x098d6e5
+			 * 28636363 * 0xa.4c6b728/0x18 = 48000 * 256
+			 * 295 MHz pre-postdivide
+			 * FIXME 28636363 ref_freq doesn't match VID PLL ref
+			 */
+			cx25840_write4(client, 0x110, 0x0098d6e5);
+
+			/*
+			 * SA_MCLK_SEL = 1
+			 * SA_MCLK_DIV = 0x10 = 256/384 * AUX_PLL post dvivider
+			 */
+			cx25840_write(client, 0x127, 0x50);
+
+			if (is_cx2583x(state))
+				break;
+
+			/* src1_ctl */
+			/* 0x1.8000 = 48000/32000 */
+			cx25840_write4(client, 0x8f8, 0x08018000);
+
+			/* src3/4/6_ctl */
+			/* 0x1.5555 = 2 * (32000/48000) */
+			cx25840_write4(client, 0x900, 0x08015555);
+			cx25840_write4(client, 0x904, 0x08015555);
+			cx25840_write4(client, 0x90c, 0x08015555);
+			break;
+		}
+	}
+
+	state->audclk_freq = freq;
+
+	return 0;
+}
+
+static inline int cx25836_set_audclk_freq(struct i2c_client *client, u32 freq)
+{
+	return cx25840_set_audclk_freq(client, freq);
+}
+
+static int cx23885_set_audclk_freq(struct i2c_client *client, u32 freq)
+{
+	struct cx25840_state *state = to_state(i2c_get_clientdata(client));
+
+	if (state->aud_input != CX25840_AUDIO_SERIAL) {
+		switch (freq) {
+		case 32000:
+		case 44100:
+		case 48000:
+			/* We don't have register values
+			 * so avoid destroying registers. */
+			/* FIXME return -EINVAL; */
+			break;
+		}
+	} else {
+		switch (freq) {
+		case 32000:
+		case 44100:
+			/* We don't have register values
+			 * so avoid destroying registers. */
+			/* FIXME return -EINVAL; */
+			break;
+
+		case 48000:
+			/* src1_ctl */
+			/* 0x1.867c = 48000 / (2 * 28636360/8 * 2/455) */
+			cx25840_write4(client, 0x8f8, 0x0801867c);
+
+			/* src3/4/6_ctl */
+			/* 0x1.4faa = (4 * 28636360/8 * 2/455) / 48000 */
+			cx25840_write4(client, 0x900, 0x08014faa);
+			cx25840_write4(client, 0x904, 0x08014faa);
+			cx25840_write4(client, 0x90c, 0x08014faa);
+			break;
+		}
+	}
+
+	state->audclk_freq = freq;
+
+	return 0;
+}
+
+static int cx231xx_set_audclk_freq(struct i2c_client *client, u32 freq)
+{
+	struct cx25840_state *state = to_state(i2c_get_clientdata(client));
+
+	if (state->aud_input != CX25840_AUDIO_SERIAL) {
+		switch (freq) {
+		case 32000:
+			/* src3/4/6_ctl */
+			/* 0x1.f77f = (4 * 28636360/8 * 2/455) / 32000 */
+			cx25840_write4(client, 0x900, 0x0801f77f);
+			cx25840_write4(client, 0x904, 0x0801f77f);
+			cx25840_write4(client, 0x90c, 0x0801f77f);
+			break;
+
+		case 44100:
+			/* src3/4/6_ctl */
+			/* 0x1.6d59 = (4 * 28636360/8 * 2/455) / 44100 */
+			cx25840_write4(client, 0x900, 0x08016d59);
+			cx25840_write4(client, 0x904, 0x08016d59);
+			cx25840_write4(client, 0x90c, 0x08016d59);
+			break;
+
+		case 48000:
+			/* src3/4/6_ctl */
+			/* 0x1.4faa = (4 * 28636360/8 * 2/455) / 48000 */
+			cx25840_write4(client, 0x900, 0x08014faa);
+			cx25840_write4(client, 0x904, 0x08014faa);
+			cx25840_write4(client, 0x90c, 0x08014faa);
+			break;
+		}
+	} else {
+		switch (freq) {
+		/* FIXME These cases make different assumptions about audclk */
+		case 32000:
+			/* src1_ctl */
+			/* 0x1.0000 = 32000/32000 */
+			cx25840_write4(client, 0x8f8, 0x08010000);
+
+			/* src3/4/6_ctl */
+			/* 0x2.0000 = 2 * (32000/32000) */
+			cx25840_write4(client, 0x900, 0x08020000);
+			cx25840_write4(client, 0x904, 0x08020000);
+			cx25840_write4(client, 0x90c, 0x08020000);
+			break;
+
+		case 44100:
+			/* src1_ctl */
+			/* 0x1.60cd = 44100/32000 */
+			cx25840_write4(client, 0x8f8, 0x080160cd);
+
+			/* src3/4/6_ctl */
+			/* 0x1.7385 = 2 * (32000/44100) */
+			cx25840_write4(client, 0x900, 0x08017385);
+			cx25840_write4(client, 0x904, 0x08017385);
+			cx25840_write4(client, 0x90c, 0x08017385);
+			break;
+
+		case 48000:
+			/* src1_ctl */
+			/* 0x1.867c = 48000 / (2 * 28636360/8 * 2/455) */
+			cx25840_write4(client, 0x8f8, 0x0801867c);
+
+			/* src3/4/6_ctl */
+			/* 0x1.4faa = (4 * 28636360/8 * 2/455) / 48000 */
+			cx25840_write4(client, 0x900, 0x08014faa);
+			cx25840_write4(client, 0x904, 0x08014faa);
+			cx25840_write4(client, 0x90c, 0x08014faa);
+			break;
+		}
+	}
+
+	state->audclk_freq = freq;
+
+	return 0;
+}
+
+static int set_audclk_freq(struct i2c_client *client, u32 freq)
+{
+	struct cx25840_state *state = to_state(i2c_get_clientdata(client));
+
+	if (freq != 32000 && freq != 44100 && freq != 48000)
+		return -EINVAL;
+
+	if (is_cx231xx(state))
+		return cx231xx_set_audclk_freq(client, freq);
+
+	if (is_cx2388x(state))
+		return cx23885_set_audclk_freq(client, freq);
+
+	if (is_cx2583x(state))
+		return cx25836_set_audclk_freq(client, freq);
+
+	return cx25840_set_audclk_freq(client, freq);
+}
+
+void cx25840_audio_set_path(struct i2c_client *client)
+{
+	struct cx25840_state *state = to_state(i2c_get_clientdata(client));
+
+	if (!is_cx2583x(state)) {
+		/* assert soft reset */
+		cx25840_and_or(client, 0x810, ~0x1, 0x01);
+
+		/* stop microcontroller */
+		cx25840_and_or(client, 0x803, ~0x10, 0);
+
+		/* Mute everything to prevent the PFFT! */
+		cx25840_write(client, 0x8d3, 0x1f);
+
+		if (state->aud_input == CX25840_AUDIO_SERIAL) {
+			/* Set Path1 to Serial Audio Input */
+			cx25840_write4(client, 0x8d0, 0x01011012);
+
+			/* The microcontroller should not be started for the
+			 * non-tuner inputs: autodetection is specific for
+			 * TV audio. */
+		} else {
+			/* Set Path1 to Analog Demod Main Channel */
+			cx25840_write4(client, 0x8d0, 0x1f063870);
+		}
+	}
+
+	set_audclk_freq(client, state->audclk_freq);
+
+	if (!is_cx2583x(state)) {
+		if (state->aud_input != CX25840_AUDIO_SERIAL) {
+			/* When the microcontroller detects the
+			 * audio format, it will unmute the lines */
+			cx25840_and_or(client, 0x803, ~0x10, 0x10);
+		}
+
+		/* deassert soft reset */
+		cx25840_and_or(client, 0x810, ~0x1, 0x00);
+
+		/* Ensure the controller is running when we exit */
+		if (is_cx2388x(state) || is_cx231xx(state))
+			cx25840_and_or(client, 0x803, ~0x10, 0x10);
+	}
+}
+
+static void set_volume(struct i2c_client *client, int volume)
+{
+	int vol;
+
+	/* Convert the volume to msp3400 values (0-127) */
+	vol = volume >> 9;
+
+	/* now scale it up to cx25840 values
+	 * -114dB to -96dB maps to 0
+	 * this should be 19, but in my testing that was 4dB too loud */
+	if (vol <= 23) {
+		vol = 0;
+	} else {
+		vol -= 23;
+	}
+
+	/* PATH1_VOLUME */
+	cx25840_write(client, 0x8d4, 228 - (vol * 2));
+}
+
+static void set_balance(struct i2c_client *client, int balance)
+{
+	int bal = balance >> 8;
+	if (bal > 0x80) {
+		/* PATH1_BAL_LEFT */
+		cx25840_and_or(client, 0x8d5, 0x7f, 0x80);
+		/* PATH1_BAL_LEVEL */
+		cx25840_and_or(client, 0x8d5, ~0x7f, bal & 0x7f);
+	} else {
+		/* PATH1_BAL_LEFT */
+		cx25840_and_or(client, 0x8d5, 0x7f, 0x00);
+		/* PATH1_BAL_LEVEL */
+		cx25840_and_or(client, 0x8d5, ~0x7f, 0x80 - bal);
+	}
+}
+
+int cx25840_s_clock_freq(struct v4l2_subdev *sd, u32 freq)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct cx25840_state *state = to_state(sd);
+	int retval;
+
+	if (!is_cx2583x(state))
+		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 (!is_cx2583x(state))
+		cx25840_and_or(client, 0x810, ~0x1, 0);
+	return retval;
+}
+
+static int cx25840_audio_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct v4l2_subdev *sd = to_sd(ctrl);
+	struct cx25840_state *state = to_state(sd);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	switch (ctrl->id) {
+	case V4L2_CID_AUDIO_VOLUME:
+		if (state->mute->val)
+			set_volume(client, 0);
+		else
+			set_volume(client, state->volume->val);
+		break;
+	case V4L2_CID_AUDIO_BASS:
+		/* PATH1_EQ_BASS_VOL */
+		cx25840_and_or(client, 0x8d9, ~0x3f,
+					48 - (ctrl->val * 48 / 0xffff));
+		break;
+	case V4L2_CID_AUDIO_TREBLE:
+		/* PATH1_EQ_TREBLE_VOL */
+		cx25840_and_or(client, 0x8db, ~0x3f,
+					48 - (ctrl->val * 48 / 0xffff));
+		break;
+	case V4L2_CID_AUDIO_BALANCE:
+		set_balance(client, ctrl->val);
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+const struct v4l2_ctrl_ops cx25840_audio_ctrl_ops = {
+	.s_ctrl = cx25840_audio_s_ctrl,
+};
diff --git a/drivers/media/i2c/cx25840/cx25840-core.c b/drivers/media/i2c/cx25840/cx25840-core.c
new file mode 100644
index 0000000..d8eac3e
--- /dev/null
+++ b/drivers/media/i2c/cx25840/cx25840-core.c
@@ -0,0 +1,5340 @@
+/* cx25840 - Conexant CX25840 audio/video decoder driver
+ *
+ * Copyright (C) 2004 Ulf Eklund
+ *
+ * Based on the saa7115 driver and on the first version of Chris Kennedy's
+ * cx25840 driver.
+ *
+ * Changes by Tyler Trafford <tatrafford@comcast.net>
+ *    - cleanup/rewrite for V4L2 API (2005)
+ *
+ * VBI support by Hans Verkuil <hverkuil@xs4all.nl>.
+ *
+ * NTSC sliced VBI support by Christopher Neufeld <television@cneufeld.ca>
+ * with additional fixes by Hans Verkuil <hverkuil@xs4all.nl>.
+ *
+ * CX23885 support by Steven Toth <stoth@linuxtv.org>.
+ *
+ * CX2388[578] IRQ handling, IO Pin mux configuration and other small fixes are
+ * Copyright (C) 2010 Andy Walls <awalls@md.metrocast.net>
+ *
+ * CX23888 DIF support for the HVR1850
+ * Copyright (C) 2011 Steven Toth <stoth@kernellabs.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/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/videodev2.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/math64.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/cx25840.h>
+
+#include "cx25840-core.h"
+
+MODULE_DESCRIPTION("Conexant CX25840 audio/video decoder driver");
+MODULE_AUTHOR("Ulf Eklund, Chris Kennedy, Hans Verkuil, Tyler Trafford");
+MODULE_LICENSE("GPL");
+
+#define CX25840_VID_INT_STAT_REG 0x410
+#define CX25840_VID_INT_STAT_BITS 0x0000ffff
+#define CX25840_VID_INT_MASK_BITS 0xffff0000
+#define CX25840_VID_INT_MASK_SHFT 16
+#define CX25840_VID_INT_MASK_REG 0x412
+
+#define CX23885_AUD_MC_INT_MASK_REG 0x80c
+#define CX23885_AUD_MC_INT_STAT_BITS 0xffff0000
+#define CX23885_AUD_MC_INT_CTRL_BITS 0x0000ffff
+#define CX23885_AUD_MC_INT_STAT_SHFT 16
+
+#define CX25840_AUD_INT_CTRL_REG 0x812
+#define CX25840_AUD_INT_STAT_REG 0x813
+
+#define CX23885_PIN_CTRL_IRQ_REG 0x123
+#define CX23885_PIN_CTRL_IRQ_IR_STAT  0x40
+#define CX23885_PIN_CTRL_IRQ_AUD_STAT 0x20
+#define CX23885_PIN_CTRL_IRQ_VID_STAT 0x10
+
+#define CX25840_IR_STATS_REG	0x210
+#define CX25840_IR_IRQEN_REG	0x214
+
+static int cx25840_debug;
+
+module_param_named(debug,cx25840_debug, int, 0644);
+
+MODULE_PARM_DESC(debug, "Debugging messages [0=Off (default) 1=On]");
+
+
+/* ----------------------------------------------------------------------- */
+static void cx23888_std_setup(struct i2c_client *client);
+
+int cx25840_write(struct i2c_client *client, u16 addr, u8 value)
+{
+	u8 buffer[3];
+	buffer[0] = addr >> 8;
+	buffer[1] = addr & 0xff;
+	buffer[2] = value;
+	return i2c_master_send(client, buffer, 3);
+}
+
+int cx25840_write4(struct i2c_client *client, u16 addr, u32 value)
+{
+	u8 buffer[6];
+	buffer[0] = addr >> 8;
+	buffer[1] = addr & 0xff;
+	buffer[2] = value & 0xff;
+	buffer[3] = (value >> 8) & 0xff;
+	buffer[4] = (value >> 16) & 0xff;
+	buffer[5] = value >> 24;
+	return i2c_master_send(client, buffer, 6);
+}
+
+u8 cx25840_read(struct i2c_client * client, u16 addr)
+{
+	struct i2c_msg msgs[2];
+	u8 tx_buf[2], rx_buf[1];
+
+	/* Write register address */
+	tx_buf[0] = addr >> 8;
+	tx_buf[1] = addr & 0xff;
+	msgs[0].addr = client->addr;
+	msgs[0].flags = 0;
+	msgs[0].len = 2;
+	msgs[0].buf = (char *) tx_buf;
+
+	/* Read data from register */
+	msgs[1].addr = client->addr;
+	msgs[1].flags = I2C_M_RD;
+	msgs[1].len = 1;
+	msgs[1].buf = (char *) rx_buf;
+
+	if (i2c_transfer(client->adapter, msgs, 2) < 2)
+		return 0;
+
+	return rx_buf[0];
+}
+
+u32 cx25840_read4(struct i2c_client * client, u16 addr)
+{
+	struct i2c_msg msgs[2];
+	u8 tx_buf[2], rx_buf[4];
+
+	/* Write register address */
+	tx_buf[0] = addr >> 8;
+	tx_buf[1] = addr & 0xff;
+	msgs[0].addr = client->addr;
+	msgs[0].flags = 0;
+	msgs[0].len = 2;
+	msgs[0].buf = (char *) tx_buf;
+
+	/* Read data from registers */
+	msgs[1].addr = client->addr;
+	msgs[1].flags = I2C_M_RD;
+	msgs[1].len = 4;
+	msgs[1].buf = (char *) rx_buf;
+
+	if (i2c_transfer(client->adapter, msgs, 2) < 2)
+		return 0;
+
+	return (rx_buf[3] << 24) | (rx_buf[2] << 16) | (rx_buf[1] << 8) |
+		rx_buf[0];
+}
+
+int cx25840_and_or(struct i2c_client *client, u16 addr, unsigned and_mask,
+		   u8 or_value)
+{
+	return cx25840_write(client, addr,
+			     (cx25840_read(client, addr) & and_mask) |
+			     or_value);
+}
+
+int cx25840_and_or4(struct i2c_client *client, u16 addr, u32 and_mask,
+		    u32 or_value)
+{
+	return cx25840_write4(client, addr,
+			      (cx25840_read4(client, addr) & and_mask) |
+			      or_value);
+}
+
+/* ----------------------------------------------------------------------- */
+
+static int set_input(struct i2c_client *client, enum cx25840_video_input vid_input,
+						enum cx25840_audio_input aud_input);
+
+/* ----------------------------------------------------------------------- */
+
+static int cx23885_s_io_pin_config(struct v4l2_subdev *sd, size_t n,
+				      struct v4l2_subdev_io_pin_config *p)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	int i;
+	u32 pin_ctrl;
+	u8 gpio_oe, gpio_data, strength;
+
+	pin_ctrl = cx25840_read4(client, 0x120);
+	gpio_oe = cx25840_read(client, 0x160);
+	gpio_data = cx25840_read(client, 0x164);
+
+	for (i = 0; i < n; i++) {
+		strength = p[i].strength;
+		if (strength > CX25840_PIN_DRIVE_FAST)
+			strength = CX25840_PIN_DRIVE_FAST;
+
+		switch (p[i].pin) {
+		case CX23885_PIN_IRQ_N_GPIO16:
+			if (p[i].function != CX23885_PAD_IRQ_N) {
+				/* GPIO16 */
+				pin_ctrl &= ~(0x1 << 25);
+			} else {
+				/* IRQ_N */
+				if (p[i].flags &
+					(V4L2_SUBDEV_IO_PIN_DISABLE |
+					 V4L2_SUBDEV_IO_PIN_INPUT)) {
+					pin_ctrl &= ~(0x1 << 25);
+				} else {
+					pin_ctrl |= (0x1 << 25);
+				}
+				if (p[i].flags &
+					V4L2_SUBDEV_IO_PIN_ACTIVE_LOW) {
+					pin_ctrl &= ~(0x1 << 24);
+				} else {
+					pin_ctrl |= (0x1 << 24);
+				}
+			}
+			break;
+		case CX23885_PIN_IR_RX_GPIO19:
+			if (p[i].function != CX23885_PAD_GPIO19) {
+				/* IR_RX */
+				gpio_oe |= (0x1 << 0);
+				pin_ctrl &= ~(0x3 << 18);
+				pin_ctrl |= (strength << 18);
+			} else {
+				/* GPIO19 */
+				gpio_oe &= ~(0x1 << 0);
+				if (p[i].flags & V4L2_SUBDEV_IO_PIN_SET_VALUE) {
+					gpio_data &= ~(0x1 << 0);
+					gpio_data |= ((p[i].value & 0x1) << 0);
+				}
+				pin_ctrl &= ~(0x3 << 12);
+				pin_ctrl |= (strength << 12);
+			}
+			break;
+		case CX23885_PIN_IR_TX_GPIO20:
+			if (p[i].function != CX23885_PAD_GPIO20) {
+				/* IR_TX */
+				gpio_oe |= (0x1 << 1);
+				if (p[i].flags & V4L2_SUBDEV_IO_PIN_DISABLE)
+					pin_ctrl &= ~(0x1 << 10);
+				else
+					pin_ctrl |= (0x1 << 10);
+				pin_ctrl &= ~(0x3 << 18);
+				pin_ctrl |= (strength << 18);
+			} else {
+				/* GPIO20 */
+				gpio_oe &= ~(0x1 << 1);
+				if (p[i].flags & V4L2_SUBDEV_IO_PIN_SET_VALUE) {
+					gpio_data &= ~(0x1 << 1);
+					gpio_data |= ((p[i].value & 0x1) << 1);
+				}
+				pin_ctrl &= ~(0x3 << 12);
+				pin_ctrl |= (strength << 12);
+			}
+			break;
+		case CX23885_PIN_I2S_SDAT_GPIO21:
+			if (p[i].function != CX23885_PAD_GPIO21) {
+				/* I2S_SDAT */
+				/* TODO: Input or Output config */
+				gpio_oe |= (0x1 << 2);
+				pin_ctrl &= ~(0x3 << 22);
+				pin_ctrl |= (strength << 22);
+			} else {
+				/* GPIO21 */
+				gpio_oe &= ~(0x1 << 2);
+				if (p[i].flags & V4L2_SUBDEV_IO_PIN_SET_VALUE) {
+					gpio_data &= ~(0x1 << 2);
+					gpio_data |= ((p[i].value & 0x1) << 2);
+				}
+				pin_ctrl &= ~(0x3 << 12);
+				pin_ctrl |= (strength << 12);
+			}
+			break;
+		case CX23885_PIN_I2S_WCLK_GPIO22:
+			if (p[i].function != CX23885_PAD_GPIO22) {
+				/* I2S_WCLK */
+				/* TODO: Input or Output config */
+				gpio_oe |= (0x1 << 3);
+				pin_ctrl &= ~(0x3 << 22);
+				pin_ctrl |= (strength << 22);
+			} else {
+				/* GPIO22 */
+				gpio_oe &= ~(0x1 << 3);
+				if (p[i].flags & V4L2_SUBDEV_IO_PIN_SET_VALUE) {
+					gpio_data &= ~(0x1 << 3);
+					gpio_data |= ((p[i].value & 0x1) << 3);
+				}
+				pin_ctrl &= ~(0x3 << 12);
+				pin_ctrl |= (strength << 12);
+			}
+			break;
+		case CX23885_PIN_I2S_BCLK_GPIO23:
+			if (p[i].function != CX23885_PAD_GPIO23) {
+				/* I2S_BCLK */
+				/* TODO: Input or Output config */
+				gpio_oe |= (0x1 << 4);
+				pin_ctrl &= ~(0x3 << 22);
+				pin_ctrl |= (strength << 22);
+			} else {
+				/* GPIO23 */
+				gpio_oe &= ~(0x1 << 4);
+				if (p[i].flags & V4L2_SUBDEV_IO_PIN_SET_VALUE) {
+					gpio_data &= ~(0x1 << 4);
+					gpio_data |= ((p[i].value & 0x1) << 4);
+				}
+				pin_ctrl &= ~(0x3 << 12);
+				pin_ctrl |= (strength << 12);
+			}
+			break;
+		}
+	}
+
+	cx25840_write(client, 0x164, gpio_data);
+	cx25840_write(client, 0x160, gpio_oe);
+	cx25840_write4(client, 0x120, pin_ctrl);
+	return 0;
+}
+
+static int common_s_io_pin_config(struct v4l2_subdev *sd, size_t n,
+				      struct v4l2_subdev_io_pin_config *pincfg)
+{
+	struct cx25840_state *state = to_state(sd);
+
+	if (is_cx2388x(state))
+		return cx23885_s_io_pin_config(sd, n, pincfg);
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static void init_dll1(struct i2c_client *client)
+{
+	/* This is the Hauppauge sequence used to
+	 * initialize the Delay Lock Loop 1 (ADC DLL). */
+	cx25840_write(client, 0x159, 0x23);
+	cx25840_write(client, 0x15a, 0x87);
+	cx25840_write(client, 0x15b, 0x06);
+	udelay(10);
+	cx25840_write(client, 0x159, 0xe1);
+	udelay(10);
+	cx25840_write(client, 0x15a, 0x86);
+	cx25840_write(client, 0x159, 0xe0);
+	cx25840_write(client, 0x159, 0xe1);
+	cx25840_write(client, 0x15b, 0x10);
+}
+
+static void init_dll2(struct i2c_client *client)
+{
+	/* This is the Hauppauge sequence used to
+	 * initialize the Delay Lock Loop 2 (ADC DLL). */
+	cx25840_write(client, 0x15d, 0xe3);
+	cx25840_write(client, 0x15e, 0x86);
+	cx25840_write(client, 0x15f, 0x06);
+	udelay(10);
+	cx25840_write(client, 0x15d, 0xe1);
+	cx25840_write(client, 0x15d, 0xe0);
+	cx25840_write(client, 0x15d, 0xe1);
+}
+
+static void cx25836_initialize(struct i2c_client *client)
+{
+	/* reset configuration is described on page 3-77 of the CX25836 datasheet */
+	/* 2. */
+	cx25840_and_or(client, 0x000, ~0x01, 0x01);
+	cx25840_and_or(client, 0x000, ~0x01, 0x00);
+	/* 3a. */
+	cx25840_and_or(client, 0x15a, ~0x70, 0x00);
+	/* 3b. */
+	cx25840_and_or(client, 0x15b, ~0x1e, 0x06);
+	/* 3c. */
+	cx25840_and_or(client, 0x159, ~0x02, 0x02);
+	/* 3d. */
+	udelay(10);
+	/* 3e. */
+	cx25840_and_or(client, 0x159, ~0x02, 0x00);
+	/* 3f. */
+	cx25840_and_or(client, 0x159, ~0xc0, 0xc0);
+	/* 3g. */
+	cx25840_and_or(client, 0x159, ~0x01, 0x00);
+	cx25840_and_or(client, 0x159, ~0x01, 0x01);
+	/* 3h. */
+	cx25840_and_or(client, 0x15b, ~0x1e, 0x10);
+}
+
+static void cx25840_work_handler(struct work_struct *work)
+{
+	struct cx25840_state *state = container_of(work, struct cx25840_state, fw_work);
+	cx25840_loadfw(state->c);
+	wake_up(&state->fw_wait);
+}
+
+static void cx25840_initialize(struct i2c_client *client)
+{
+	DEFINE_WAIT(wait);
+	struct cx25840_state *state = to_state(i2c_get_clientdata(client));
+	struct workqueue_struct *q;
+
+	/* datasheet startup in numbered steps, refer to page 3-77 */
+	/* 2. */
+	cx25840_and_or(client, 0x803, ~0x10, 0x00);
+	/* The default of this register should be 4, but I get 0 instead.
+	 * Set this register to 4 manually. */
+	cx25840_write(client, 0x000, 0x04);
+	/* 3. */
+	init_dll1(client);
+	init_dll2(client);
+	cx25840_write(client, 0x136, 0x0a);
+	/* 4. */
+	cx25840_write(client, 0x13c, 0x01);
+	cx25840_write(client, 0x13c, 0x00);
+	/* 5. */
+	/* Do the firmware load in a work handler to prevent.
+	   Otherwise the kernel is blocked waiting for the
+	   bit-banging i2c interface to finish uploading the
+	   firmware. */
+	INIT_WORK(&state->fw_work, cx25840_work_handler);
+	init_waitqueue_head(&state->fw_wait);
+	q = create_singlethread_workqueue("cx25840_fw");
+	prepare_to_wait(&state->fw_wait, &wait, TASK_UNINTERRUPTIBLE);
+	queue_work(q, &state->fw_work);
+	schedule();
+	finish_wait(&state->fw_wait, &wait);
+	destroy_workqueue(q);
+
+	/* 6. */
+	cx25840_write(client, 0x115, 0x8c);
+	cx25840_write(client, 0x116, 0x07);
+	cx25840_write(client, 0x118, 0x02);
+	/* 7. */
+	cx25840_write(client, 0x4a5, 0x80);
+	cx25840_write(client, 0x4a5, 0x00);
+	cx25840_write(client, 0x402, 0x00);
+	/* 8. */
+	cx25840_and_or(client, 0x401, ~0x18, 0);
+	cx25840_and_or(client, 0x4a2, ~0x10, 0x10);
+	/* steps 8c and 8d are done in change_input() */
+	/* 10. */
+	cx25840_write(client, 0x8d3, 0x1f);
+	cx25840_write(client, 0x8e3, 0x03);
+
+	cx25840_std_setup(client);
+
+	/* trial and error says these are needed to get audio */
+	cx25840_write(client, 0x914, 0xa0);
+	cx25840_write(client, 0x918, 0xa0);
+	cx25840_write(client, 0x919, 0x01);
+
+	/* stereo preferred */
+	cx25840_write(client, 0x809, 0x04);
+	/* AC97 shift */
+	cx25840_write(client, 0x8cf, 0x0f);
+
+	/* (re)set input */
+	set_input(client, state->vid_input, state->aud_input);
+
+	/* start microcontroller */
+	cx25840_and_or(client, 0x803, ~0x10, 0x10);
+}
+
+static void cx23885_initialize(struct i2c_client *client)
+{
+	DEFINE_WAIT(wait);
+	struct cx25840_state *state = to_state(i2c_get_clientdata(client));
+	struct workqueue_struct *q;
+
+	/*
+	 * Come out of digital power down
+	 * The CX23888, at least, needs this, otherwise registers aside from
+	 * 0x0-0x2 can't be read or written.
+	 */
+	cx25840_write(client, 0x000, 0);
+
+	/* Internal Reset */
+	cx25840_and_or(client, 0x102, ~0x01, 0x01);
+	cx25840_and_or(client, 0x102, ~0x01, 0x00);
+
+	/* Stop microcontroller */
+	cx25840_and_or(client, 0x803, ~0x10, 0x00);
+
+	/* DIF in reset? */
+	cx25840_write(client, 0x398, 0);
+
+	/*
+	 * Trust the default xtal, no division
+	 * '885: 28.636363... MHz
+	 * '887: 25.000000 MHz
+	 * '888: 50.000000 MHz
+	 */
+	cx25840_write(client, 0x2, 0x76);
+
+	/* Power up all the PLL's and DLL */
+	cx25840_write(client, 0x1, 0x40);
+
+	/* Sys PLL */
+	switch (state->id) {
+	case V4L2_IDENT_CX23888_AV:
+		/*
+		 * 50.0 MHz * (0xb + 0xe8ba26/0x2000000)/4 = 5 * 28.636363 MHz
+		 * 572.73 MHz before post divide
+		 */
+		/* HVR1850 or 50MHz xtal */
+		cx25840_write(client, 0x2, 0x71);
+		cx25840_write4(client, 0x11c, 0x01d1744c);
+		cx25840_write4(client, 0x118, 0x00000416);
+		cx25840_write4(client, 0x404, 0x0010253e);
+		cx25840_write4(client, 0x42c, 0x42600000);
+		cx25840_write4(client, 0x44c, 0x161f1000);
+		break;
+	case V4L2_IDENT_CX23887_AV:
+		/*
+		 * 25.0 MHz * (0x16 + 0x1d1744c/0x2000000)/4 = 5 * 28.636363 MHz
+		 * 572.73 MHz before post divide
+		 */
+		cx25840_write4(client, 0x11c, 0x01d1744c);
+		cx25840_write4(client, 0x118, 0x00000416);
+		break;
+	case V4L2_IDENT_CX23885_AV:
+	default:
+		/*
+		 * 28.636363 MHz * (0x14 + 0x0/0x2000000)/4 = 5 * 28.636363 MHz
+		 * 572.73 MHz before post divide
+		 */
+		cx25840_write4(client, 0x11c, 0x00000000);
+		cx25840_write4(client, 0x118, 0x00000414);
+		break;
+	}
+
+	/* Disable DIF bypass */
+	cx25840_write4(client, 0x33c, 0x00000001);
+
+	/* DIF Src phase inc */
+	cx25840_write4(client, 0x340, 0x0df7df83);
+
+	/*
+	 * Vid PLL
+	 * Setup for a BT.656 pixel clock of 13.5 Mpixels/second
+	 *
+	 * 28.636363 MHz * (0xf + 0x02be2c9/0x2000000)/4 = 8 * 13.5 MHz
+	 * 432.0 MHz before post divide
+	 */
+
+	/* HVR1850 */
+	switch (state->id) {
+	case V4L2_IDENT_CX23888_AV:
+		/* 888/HVR1250 specific */
+		cx25840_write4(client, 0x10c, 0x13333333);
+		cx25840_write4(client, 0x108, 0x00000515);
+		break;
+	default:
+		cx25840_write4(client, 0x10c, 0x002be2c9);
+		cx25840_write4(client, 0x108, 0x0000040f);
+	}
+
+	/* Luma */
+	cx25840_write4(client, 0x414, 0x00107d12);
+
+	/* Chroma */
+	cx25840_write4(client, 0x420, 0x3d008282);
+
+	/*
+	 * Aux PLL
+	 * Initial setup for audio sample clock:
+	 * 48 ksps, 16 bits/sample, x160 multiplier = 122.88 MHz
+	 * Initial I2S output/master clock(?):
+	 * 48 ksps, 16 bits/sample, x16 multiplier = 12.288 MHz
+	 */
+	switch (state->id) {
+	case V4L2_IDENT_CX23888_AV:
+		/*
+		 * 50.0 MHz * (0x7 + 0x0bedfa4/0x2000000)/3 = 122.88 MHz
+		 * 368.64 MHz before post divide
+		 * 122.88 MHz / 0xa = 12.288 MHz
+		 */
+		/* HVR1850  or 50MHz xtal */
+		cx25840_write4(client, 0x114, 0x017dbf48);
+		cx25840_write4(client, 0x110, 0x000a030e);
+		break;
+	case V4L2_IDENT_CX23887_AV:
+		/*
+		 * 25.0 MHz * (0xe + 0x17dbf48/0x2000000)/3 = 122.88 MHz
+		 * 368.64 MHz before post divide
+		 * 122.88 MHz / 0xa = 12.288 MHz
+		 */
+		cx25840_write4(client, 0x114, 0x017dbf48);
+		cx25840_write4(client, 0x110, 0x000a030e);
+		break;
+	case V4L2_IDENT_CX23885_AV:
+	default:
+		/*
+		 * 28.636363 MHz * (0xc + 0x1bf0c9e/0x2000000)/3 = 122.88 MHz
+		 * 368.64 MHz before post divide
+		 * 122.88 MHz / 0xa = 12.288 MHz
+		 */
+		cx25840_write4(client, 0x114, 0x01bf0c9e);
+		cx25840_write4(client, 0x110, 0x000a030c);
+		break;
+	};
+
+	/* ADC2 input select */
+	cx25840_write(client, 0x102, 0x10);
+
+	/* VIN1 & VIN5 */
+	cx25840_write(client, 0x103, 0x11);
+
+	/* Enable format auto detect */
+	cx25840_write(client, 0x400, 0);
+	/* Fast subchroma lock */
+	/* White crush, Chroma AGC & Chroma Killer enabled */
+	cx25840_write(client, 0x401, 0xe8);
+
+	/* Select AFE clock pad output source */
+	cx25840_write(client, 0x144, 0x05);
+
+	/* Drive GPIO2 direction and values for HVR1700
+	 * where an onboard mux selects the output of demodulator
+	 * vs the 417. Failure to set this results in no DTV.
+	 * It's safe to set this across all Hauppauge boards
+	 * currently, regardless of the board type.
+	 */
+	cx25840_write(client, 0x160, 0x1d);
+	cx25840_write(client, 0x164, 0x00);
+
+	/* Do the firmware load in a work handler to prevent.
+	   Otherwise the kernel is blocked waiting for the
+	   bit-banging i2c interface to finish uploading the
+	   firmware. */
+	INIT_WORK(&state->fw_work, cx25840_work_handler);
+	init_waitqueue_head(&state->fw_wait);
+	q = create_singlethread_workqueue("cx25840_fw");
+	prepare_to_wait(&state->fw_wait, &wait, TASK_UNINTERRUPTIBLE);
+	queue_work(q, &state->fw_work);
+	schedule();
+	finish_wait(&state->fw_wait, &wait);
+	destroy_workqueue(q);
+
+	/* Call the cx23888 specific std setup func, we no longer rely on
+	 * the generic cx24840 func.
+	 */
+	if (is_cx23888(state))
+		cx23888_std_setup(client);
+	else
+		cx25840_std_setup(client);
+
+	/* (re)set input */
+	set_input(client, state->vid_input, state->aud_input);
+
+	/* start microcontroller */
+	cx25840_and_or(client, 0x803, ~0x10, 0x10);
+
+	/* Disable and clear video interrupts - we don't use them */
+	cx25840_write4(client, CX25840_VID_INT_STAT_REG, 0xffffffff);
+
+	/* Disable and clear audio interrupts - we don't use them */
+	cx25840_write(client, CX25840_AUD_INT_CTRL_REG, 0xff);
+	cx25840_write(client, CX25840_AUD_INT_STAT_REG, 0xff);
+
+	/* CC raw enable */
+	/*  - VIP 1.1 control codes - 10bit, blue field enable.
+	 *  - enable raw data during vertical blanking.
+	 *  - enable ancillary Data insertion for 656 or VIP.
+	 */
+	cx25840_write4(client, 0x404, 0x0010253e);
+
+	/* CC on  - Undocumented Register */
+	cx25840_write(client, 0x42f, 0x66);
+
+	/* HVR-1250 / HVR1850 DIF related */
+	/* Power everything up */
+	cx25840_write4(client, 0x130, 0x0);
+
+	/* Undocumented */
+	cx25840_write4(client, 0x478, 0x6628021F);
+
+	/* AFE_CLK_OUT_CTRL - Select the clock output source as output */
+	cx25840_write4(client, 0x144, 0x5);
+
+	/* I2C_OUT_CTL - I2S output configuration as
+	 * Master, Sony, Left justified, left sample on WS=1
+	 */
+	cx25840_write4(client, 0x918, 0x1a0);
+
+	/* AFE_DIAG_CTRL1 */
+	cx25840_write4(client, 0x134, 0x000a1800);
+
+	/* AFE_DIAG_CTRL3 - Inverted Polarity for Audio and Video */
+	cx25840_write4(client, 0x13c, 0x00310000);
+}
+
+/* ----------------------------------------------------------------------- */
+
+static void cx231xx_initialize(struct i2c_client *client)
+{
+	DEFINE_WAIT(wait);
+	struct cx25840_state *state = to_state(i2c_get_clientdata(client));
+	struct workqueue_struct *q;
+
+	/* Internal Reset */
+	cx25840_and_or(client, 0x102, ~0x01, 0x01);
+	cx25840_and_or(client, 0x102, ~0x01, 0x00);
+
+	/* Stop microcontroller */
+	cx25840_and_or(client, 0x803, ~0x10, 0x00);
+
+	/* DIF in reset? */
+	cx25840_write(client, 0x398, 0);
+
+	/* Trust the default xtal, no division */
+	/* This changes for the cx23888 products */
+	cx25840_write(client, 0x2, 0x76);
+
+	/* Bring down the regulator for AUX clk */
+	cx25840_write(client, 0x1, 0x40);
+
+	/* Disable DIF bypass */
+	cx25840_write4(client, 0x33c, 0x00000001);
+
+	/* DIF Src phase inc */
+	cx25840_write4(client, 0x340, 0x0df7df83);
+
+	/* Luma */
+	cx25840_write4(client, 0x414, 0x00107d12);
+
+	/* Chroma */
+	cx25840_write4(client, 0x420, 0x3d008282);
+
+	/* ADC2 input select */
+	cx25840_write(client, 0x102, 0x10);
+
+	/* VIN1 & VIN5 */
+	cx25840_write(client, 0x103, 0x11);
+
+	/* Enable format auto detect */
+	cx25840_write(client, 0x400, 0);
+	/* Fast subchroma lock */
+	/* White crush, Chroma AGC & Chroma Killer enabled */
+	cx25840_write(client, 0x401, 0xe8);
+
+	/* Do the firmware load in a work handler to prevent.
+	   Otherwise the kernel is blocked waiting for the
+	   bit-banging i2c interface to finish uploading the
+	   firmware. */
+	INIT_WORK(&state->fw_work, cx25840_work_handler);
+	init_waitqueue_head(&state->fw_wait);
+	q = create_singlethread_workqueue("cx25840_fw");
+	prepare_to_wait(&state->fw_wait, &wait, TASK_UNINTERRUPTIBLE);
+	queue_work(q, &state->fw_work);
+	schedule();
+	finish_wait(&state->fw_wait, &wait);
+	destroy_workqueue(q);
+
+	cx25840_std_setup(client);
+
+	/* (re)set input */
+	set_input(client, state->vid_input, state->aud_input);
+
+	/* start microcontroller */
+	cx25840_and_or(client, 0x803, ~0x10, 0x10);
+
+	/* CC raw enable */
+	cx25840_write(client, 0x404, 0x0b);
+
+	/* CC on */
+	cx25840_write(client, 0x42f, 0x66);
+	cx25840_write4(client, 0x474, 0x1e1e601a);
+}
+
+/* ----------------------------------------------------------------------- */
+
+void cx25840_std_setup(struct i2c_client *client)
+{
+	struct cx25840_state *state = to_state(i2c_get_clientdata(client));
+	v4l2_std_id std = state->std;
+	int hblank, hactive, burst, vblank, vactive, sc;
+	int vblank656, src_decimation;
+	int luma_lpf, uv_lpf, comb;
+	u32 pll_int, pll_frac, pll_post;
+
+	/* datasheet startup, step 8d */
+	if (std & ~V4L2_STD_NTSC)
+		cx25840_write(client, 0x49f, 0x11);
+	else
+		cx25840_write(client, 0x49f, 0x14);
+
+	if (std & V4L2_STD_625_50) {
+		hblank = 132;
+		hactive = 720;
+		burst = 93;
+		vblank = 36;
+		vactive = 580;
+		vblank656 = 40;
+		src_decimation = 0x21f;
+		luma_lpf = 2;
+
+		if (std & V4L2_STD_SECAM) {
+			uv_lpf = 0;
+			comb = 0;
+			sc = 0x0a425f;
+		} else if (std == V4L2_STD_PAL_Nc) {
+			uv_lpf = 1;
+			comb = 0x20;
+			sc = 556453;
+		} else {
+			uv_lpf = 1;
+			comb = 0x20;
+			sc = 688739;
+		}
+	} else {
+		hactive = 720;
+		hblank = 122;
+		vactive = 487;
+		luma_lpf = 1;
+		uv_lpf = 1;
+
+		src_decimation = 0x21f;
+		if (std == V4L2_STD_PAL_60) {
+			vblank = 26;
+			vblank656 = 26;
+			burst = 0x5b;
+			luma_lpf = 2;
+			comb = 0x20;
+			sc = 688739;
+		} else if (std == V4L2_STD_PAL_M) {
+			vblank = 20;
+			vblank656 = 24;
+			burst = 0x61;
+			comb = 0x20;
+			sc = 555452;
+		} else {
+			vblank = 26;
+			vblank656 = 26;
+			burst = 0x5b;
+			comb = 0x66;
+			sc = 556063;
+		}
+	}
+
+	/* DEBUG: Displays configured PLL frequency */
+	if (!is_cx231xx(state)) {
+		pll_int = cx25840_read(client, 0x108);
+		pll_frac = cx25840_read4(client, 0x10c) & 0x1ffffff;
+		pll_post = cx25840_read(client, 0x109);
+		v4l_dbg(1, cx25840_debug, client,
+			"PLL regs = int: %u, frac: %u, post: %u\n",
+			pll_int, pll_frac, pll_post);
+
+		if (pll_post) {
+			int fin, fsc;
+			int pll = (28636363L * ((((u64)pll_int) << 25L) + pll_frac)) >> 25L;
+
+			pll /= pll_post;
+			v4l_dbg(1, cx25840_debug, client, "PLL = %d.%06d MHz\n",
+					pll / 1000000, pll % 1000000);
+			v4l_dbg(1, cx25840_debug, client, "PLL/8 = %d.%06d MHz\n",
+					pll / 8000000, (pll / 8) % 1000000);
+
+			fin = ((u64)src_decimation * pll) >> 12;
+			v4l_dbg(1, cx25840_debug, client,
+					"ADC Sampling freq = %d.%06d MHz\n",
+					fin / 1000000, fin % 1000000);
+
+			fsc = (((u64)sc) * pll) >> 24L;
+			v4l_dbg(1, cx25840_debug, client,
+					"Chroma sub-carrier freq = %d.%06d MHz\n",
+					fsc / 1000000, fsc % 1000000);
+
+			v4l_dbg(1, cx25840_debug, client, "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 */
+	cx25840_write(client, 0x470, hblank);
+	cx25840_write(client, 0x471,
+			0xff & (((hblank >> 8) & 0x3) | (hactive << 4)));
+	cx25840_write(client, 0x472, hactive >> 4);
+
+	/* Sets burst gate delay */
+	cx25840_write(client, 0x473, burst);
+
+	/* Sets vertical blanking delay and active duration */
+	cx25840_write(client, 0x474, vblank);
+	cx25840_write(client, 0x475,
+			0xff & (((vblank >> 8) & 0x3) | (vactive << 4)));
+	cx25840_write(client, 0x476, vactive >> 4);
+	cx25840_write(client, 0x477, vblank656);
+
+	/* Sets src decimation rate */
+	cx25840_write(client, 0x478, 0xff & src_decimation);
+	cx25840_write(client, 0x479, 0xff & (src_decimation >> 8));
+
+	/* Sets Luma and UV Low pass filters */
+	cx25840_write(client, 0x47a, luma_lpf << 6 | ((uv_lpf << 4) & 0x30));
+
+	/* Enables comb filters */
+	cx25840_write(client, 0x47b, comb);
+
+	/* Sets SC Step*/
+	cx25840_write(client, 0x47c, sc);
+	cx25840_write(client, 0x47d, 0xff & sc >> 8);
+	cx25840_write(client, 0x47e, 0xff & sc >> 16);
+
+	/* Sets VBI parameters */
+	if (std & V4L2_STD_625_50) {
+		cx25840_write(client, 0x47f, 0x01);
+		state->vbi_line_offset = 5;
+	} else {
+		cx25840_write(client, 0x47f, 0x00);
+		state->vbi_line_offset = 8;
+	}
+}
+
+/* ----------------------------------------------------------------------- */
+
+static void input_change(struct i2c_client *client)
+{
+	struct cx25840_state *state = to_state(i2c_get_clientdata(client));
+	v4l2_std_id std = state->std;
+
+	/* Follow step 8c and 8d of section 3.16 in the cx25840 datasheet */
+	if (std & V4L2_STD_SECAM) {
+		cx25840_write(client, 0x402, 0);
+	}
+	else {
+		cx25840_write(client, 0x402, 0x04);
+		cx25840_write(client, 0x49f, (std & V4L2_STD_NTSC) ? 0x14 : 0x11);
+	}
+	cx25840_and_or(client, 0x401, ~0x60, 0);
+	cx25840_and_or(client, 0x401, ~0x60, 0x60);
+
+	/* Don't write into audio registers on cx2583x chips */
+	if (is_cx2583x(state))
+		return;
+
+	cx25840_and_or(client, 0x810, ~0x01, 1);
+
+	if (state->radio) {
+		cx25840_write(client, 0x808, 0xf9);
+		cx25840_write(client, 0x80b, 0x00);
+	}
+	else if (std & V4L2_STD_525_60) {
+		/* Certain Hauppauge PVR150 models have a hardware bug
+		   that causes audio to drop out. For these models the
+		   audio standard must be set explicitly.
+		   To be precise: it affects cards with tuner models
+		   85, 99 and 112 (model numbers from tveeprom). */
+		int hw_fix = state->pvr150_workaround;
+
+		if (std == V4L2_STD_NTSC_M_JP) {
+			/* Japan uses EIAJ audio standard */
+			cx25840_write(client, 0x808, hw_fix ? 0x2f : 0xf7);
+		} else if (std == V4L2_STD_NTSC_M_KR) {
+			/* South Korea uses A2 audio standard */
+			cx25840_write(client, 0x808, hw_fix ? 0x3f : 0xf8);
+		} else {
+			/* Others use the BTSC audio standard */
+			cx25840_write(client, 0x808, hw_fix ? 0x1f : 0xf6);
+		}
+		cx25840_write(client, 0x80b, 0x00);
+	} else if (std & V4L2_STD_PAL) {
+		/* Autodetect audio standard and audio system */
+		cx25840_write(client, 0x808, 0xff);
+		/* Since system PAL-L is pretty much non-existent and
+		   not used by any public broadcast network, force
+		   6.5 MHz carrier to be interpreted as System DK,
+		   this avoids DK audio detection instability */
+	       cx25840_write(client, 0x80b, 0x00);
+	} else if (std & V4L2_STD_SECAM) {
+		/* Autodetect audio standard and audio system */
+		cx25840_write(client, 0x808, 0xff);
+		/* If only one of SECAM-DK / SECAM-L is required, then force
+		  6.5MHz carrier, else autodetect it */
+		if ((std & V4L2_STD_SECAM_DK) &&
+		    !(std & (V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC))) {
+			/* 6.5 MHz carrier to be interpreted as System DK */
+			cx25840_write(client, 0x80b, 0x00);
+	       } else if (!(std & V4L2_STD_SECAM_DK) &&
+			  (std & (V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC))) {
+			/* 6.5 MHz carrier to be interpreted as System L */
+			cx25840_write(client, 0x80b, 0x08);
+	       } else {
+			/* 6.5 MHz carrier to be autodetected */
+			cx25840_write(client, 0x80b, 0x10);
+	       }
+	}
+
+	cx25840_and_or(client, 0x810, ~0x01, 0);
+}
+
+static int set_input(struct i2c_client *client, enum cx25840_video_input vid_input,
+						enum cx25840_audio_input aud_input)
+{
+	struct cx25840_state *state = to_state(i2c_get_clientdata(client));
+	u8 is_composite = (vid_input >= CX25840_COMPOSITE1 &&
+			   vid_input <= CX25840_COMPOSITE8);
+	u8 is_component = (vid_input & CX25840_COMPONENT_ON) ==
+			CX25840_COMPONENT_ON;
+	u8 is_dif = (vid_input & CX25840_DIF_ON) ==
+			CX25840_DIF_ON;
+	u8 is_svideo = (vid_input & CX25840_SVIDEO_ON) ==
+			CX25840_SVIDEO_ON;
+	int luma = vid_input & 0xf0;
+	int chroma = vid_input & 0xf00;
+	u8 reg;
+	u32 val;
+
+	v4l_dbg(1, cx25840_debug, client,
+		"decoder set video input %d, audio input %d\n",
+		vid_input, aud_input);
+
+	if (vid_input >= CX25840_VIN1_CH1) {
+		v4l_dbg(1, cx25840_debug, client, "vid_input 0x%x\n",
+			vid_input);
+		reg = vid_input & 0xff;
+		is_composite = !is_component &&
+			((vid_input & CX25840_SVIDEO_ON) != CX25840_SVIDEO_ON);
+
+		v4l_dbg(1, cx25840_debug, client, "mux cfg 0x%x comp=%d\n",
+			reg, is_composite);
+	} else if (is_composite) {
+		reg = 0xf0 + (vid_input - CX25840_COMPOSITE1);
+	} else {
+		if ((vid_input & ~0xff0) ||
+		    luma < CX25840_SVIDEO_LUMA1 || luma > CX25840_SVIDEO_LUMA8 ||
+		    chroma < CX25840_SVIDEO_CHROMA4 || chroma > CX25840_SVIDEO_CHROMA8) {
+			v4l_err(client, "0x%04x is not a valid video input!\n",
+				vid_input);
+			return -EINVAL;
+		}
+		reg = 0xf0 + ((luma - CX25840_SVIDEO_LUMA1) >> 4);
+		if (chroma >= CX25840_SVIDEO_CHROMA7) {
+			reg &= 0x3f;
+			reg |= (chroma - CX25840_SVIDEO_CHROMA7) >> 2;
+		} else {
+			reg &= 0xcf;
+			reg |= (chroma - CX25840_SVIDEO_CHROMA4) >> 4;
+		}
+	}
+
+	/* The caller has previously prepared the correct routing
+	 * configuration in reg (for the cx23885) so we have no
+	 * need to attempt to flip bits for earlier av decoders.
+	 */
+	if (!is_cx2388x(state) && !is_cx231xx(state)) {
+		switch (aud_input) {
+		case CX25840_AUDIO_SERIAL:
+			/* do nothing, use serial audio input */
+			break;
+		case CX25840_AUDIO4: reg &= ~0x30; break;
+		case CX25840_AUDIO5: reg &= ~0x30; reg |= 0x10; break;
+		case CX25840_AUDIO6: reg &= ~0x30; reg |= 0x20; break;
+		case CX25840_AUDIO7: reg &= ~0xc0; break;
+		case CX25840_AUDIO8: reg &= ~0xc0; reg |= 0x40; break;
+
+		default:
+			v4l_err(client, "0x%04x is not a valid audio input!\n",
+				aud_input);
+			return -EINVAL;
+		}
+	}
+
+	cx25840_write(client, 0x103, reg);
+
+	/* Set INPUT_MODE to Composite, S-Video or Component */
+	if (is_component)
+		cx25840_and_or(client, 0x401, ~0x6, 0x6);
+	else
+		cx25840_and_or(client, 0x401, ~0x6, is_composite ? 0 : 0x02);
+
+	if (is_cx2388x(state)) {
+
+		/* Enable or disable the DIF for tuner use */
+		if (is_dif) {
+			cx25840_and_or(client, 0x102, ~0x80, 0x80);
+
+			/* Set of defaults for NTSC and PAL */
+			cx25840_write4(client, 0x31c, 0xc2262600);
+			cx25840_write4(client, 0x320, 0xc2262600);
+
+			/* 18271 IF - Nobody else yet uses a different
+			 * tuner with the DIF, so these are reasonable
+			 * assumptions (HVR1250 and HVR1850 specific).
+			 */
+			cx25840_write4(client, 0x318, 0xda262600);
+			cx25840_write4(client, 0x33c, 0x2a24c800);
+			cx25840_write4(client, 0x104, 0x0704dd00);
+		} else {
+			cx25840_write4(client, 0x300, 0x015c28f5);
+
+			cx25840_and_or(client, 0x102, ~0x80, 0);
+			cx25840_write4(client, 0x340, 0xdf7df83);
+			cx25840_write4(client, 0x104, 0x0704dd80);
+			cx25840_write4(client, 0x314, 0x22400600);
+			cx25840_write4(client, 0x318, 0x40002600);
+			cx25840_write4(client, 0x324, 0x40002600);
+			cx25840_write4(client, 0x32c, 0x0250e620);
+			cx25840_write4(client, 0x39c, 0x01FF0B00);
+
+			cx25840_write4(client, 0x410, 0xffff0dbf);
+			cx25840_write4(client, 0x414, 0x00137d03);
+
+			/* on the 887, 0x418 is HSCALE_CTRL, on the 888 it is 
+			   CHROMA_CTRL */
+			if (is_cx23888(state))
+				cx25840_write4(client, 0x418, 0x01008080);
+			else
+				cx25840_write4(client, 0x418, 0x01000000);
+
+			cx25840_write4(client, 0x41c, 0x00000000);
+
+			/* on the 887, 0x420 is CHROMA_CTRL, on the 888 it is 
+			   CRUSH_CTRL */
+			if (is_cx23888(state))
+				cx25840_write4(client, 0x420, 0x001c3e0f);
+			else
+				cx25840_write4(client, 0x420, 0x001c8282);
+
+			cx25840_write4(client, 0x42c, 0x42600000);
+			cx25840_write4(client, 0x430, 0x0000039b);
+			cx25840_write4(client, 0x438, 0x00000000);
+
+			cx25840_write4(client, 0x440, 0xF8E3E824);
+			cx25840_write4(client, 0x444, 0x401040dc);
+			cx25840_write4(client, 0x448, 0xcd3f02a0);
+			cx25840_write4(client, 0x44c, 0x161f1000);
+			cx25840_write4(client, 0x450, 0x00000802);
+
+			cx25840_write4(client, 0x91c, 0x01000000);
+			cx25840_write4(client, 0x8e0, 0x03063870);
+			cx25840_write4(client, 0x8d4, 0x7FFF0024);
+			cx25840_write4(client, 0x8d0, 0x00063073);
+
+			cx25840_write4(client, 0x8c8, 0x00010000);
+			cx25840_write4(client, 0x8cc, 0x00080023);
+
+			/* DIF BYPASS */
+			cx25840_write4(client, 0x33c, 0x2a04c800);
+		}
+
+		/* Reset the DIF */
+		cx25840_write4(client, 0x398, 0);
+	}
+
+	if (!is_cx2388x(state) && !is_cx231xx(state)) {
+		/* Set CH_SEL_ADC2 to 1 if input comes from CH3 */
+		cx25840_and_or(client, 0x102, ~0x2, (reg & 0x80) == 0 ? 2 : 0);
+		/* Set DUAL_MODE_ADC2 to 1 if input comes from both CH2&CH3 */
+		if ((reg & 0xc0) != 0xc0 && (reg & 0x30) != 0x30)
+			cx25840_and_or(client, 0x102, ~0x4, 4);
+		else
+			cx25840_and_or(client, 0x102, ~0x4, 0);
+	} else {
+		/* Set DUAL_MODE_ADC2 to 1 if component*/
+		cx25840_and_or(client, 0x102, ~0x4, is_component ? 0x4 : 0x0);
+		if (is_composite) {
+			/* ADC2 input select channel 2 */
+			cx25840_and_or(client, 0x102, ~0x2, 0);
+		} else if (!is_component) {
+			/* S-Video */
+			if (chroma >= CX25840_SVIDEO_CHROMA7) {
+				/* ADC2 input select channel 3 */
+				cx25840_and_or(client, 0x102, ~0x2, 2);
+			} else {
+				/* ADC2 input select channel 2 */
+				cx25840_and_or(client, 0x102, ~0x2, 0);
+			}
+		}
+
+		/* cx23885 / SVIDEO */
+		if (is_cx2388x(state) && is_svideo) {
+#define AFE_CTRL  (0x104)
+#define MODE_CTRL (0x400)
+			cx25840_and_or(client, 0x102, ~0x2, 0x2);
+
+			val = cx25840_read4(client, MODE_CTRL);
+			val &= 0xFFFFF9FF;
+
+			/* YC */
+			val |= 0x00000200;
+			val &= ~0x2000;
+			cx25840_write4(client, MODE_CTRL, val);
+
+			val = cx25840_read4(client, AFE_CTRL);
+
+			/* Chroma in select */
+			val |= 0x00001000;
+			val &= 0xfffffe7f;
+			/* Clear VGA_SEL_CH2 and VGA_SEL_CH3 (bits 7 and 8).
+			 * This sets them to use video rather than audio.
+			 * Only one of the two will be in use.
+			 */
+			cx25840_write4(client, AFE_CTRL, val);
+		} else
+			cx25840_and_or(client, 0x102, ~0x2, 0);
+	}
+
+	state->vid_input = vid_input;
+	state->aud_input = aud_input;
+	cx25840_audio_set_path(client);
+	input_change(client);
+
+	if (is_cx2388x(state)) {
+		/* Audio channel 1 src : Parallel 1 */
+		cx25840_write(client, 0x124, 0x03);
+
+		/* Select AFE clock pad output source */
+		cx25840_write(client, 0x144, 0x05);
+
+		/* I2S_IN_CTL: I2S_IN_SONY_MODE, LEFT SAMPLE on WS=1 */
+		cx25840_write(client, 0x914, 0xa0);
+
+		/* I2S_OUT_CTL:
+		 * I2S_IN_SONY_MODE, LEFT SAMPLE on WS=1
+		 * I2S_OUT_MASTER_MODE = Master
+		 */
+		cx25840_write(client, 0x918, 0xa0);
+		cx25840_write(client, 0x919, 0x01);
+	} else if (is_cx231xx(state)) {
+		/* Audio channel 1 src : Parallel 1 */
+		cx25840_write(client, 0x124, 0x03);
+
+		/* I2S_IN_CTL: I2S_IN_SONY_MODE, LEFT SAMPLE on WS=1 */
+		cx25840_write(client, 0x914, 0xa0);
+
+		/* I2S_OUT_CTL:
+		 * I2S_IN_SONY_MODE, LEFT SAMPLE on WS=1
+		 * I2S_OUT_MASTER_MODE = Master
+		 */
+		cx25840_write(client, 0x918, 0xa0);
+		cx25840_write(client, 0x919, 0x01);
+	}
+
+	if (is_cx2388x(state) && ((aud_input == CX25840_AUDIO7) ||
+		(aud_input == CX25840_AUDIO6))) {
+		/* Configure audio from LR1 or LR2 input */
+		cx25840_write4(client, 0x910, 0);
+		cx25840_write4(client, 0x8d0, 0x63073);
+	} else
+	if (is_cx2388x(state) && (aud_input == CX25840_AUDIO8)) {
+		/* Configure audio from tuner/sif input */
+		cx25840_write4(client, 0x910, 0x12b000c9);
+		cx25840_write4(client, 0x8d0, 0x1f063870);
+	}
+
+	if (is_cx23888(state)) {
+		/* HVR1850 */
+		/* AUD_IO_CTRL - I2S Input, Parallel1*/
+		/*  - Channel 1 src - Parallel1 (Merlin out) */
+		/*  - Channel 2 src - Parallel2 (Merlin out) */
+		/*  - Channel 3 src - Parallel3 (Merlin AC97 out) */
+		/*  - I2S source and dir - Merlin, output */
+		cx25840_write4(client, 0x124, 0x100);
+
+		if (!is_dif) {
+			/* Stop microcontroller if we don't need it
+			 * to avoid audio popping on svideo/composite use.
+			 */
+			cx25840_and_or(client, 0x803, ~0x10, 0x00);
+		}
+	}
+
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static int set_v4lstd(struct i2c_client *client)
+{
+	struct cx25840_state *state = to_state(i2c_get_clientdata(client));
+	u8 fmt = 0; 	/* zero is autodetect */
+	u8 pal_m = 0;
+
+	/* First tests should be against specific std */
+	if (state->std == V4L2_STD_NTSC_M_JP) {
+		fmt = 0x2;
+	} else if (state->std == V4L2_STD_NTSC_443) {
+		fmt = 0x3;
+	} else if (state->std == V4L2_STD_PAL_M) {
+		pal_m = 1;
+		fmt = 0x5;
+	} else if (state->std == V4L2_STD_PAL_N) {
+		fmt = 0x6;
+	} else if (state->std == V4L2_STD_PAL_Nc) {
+		fmt = 0x7;
+	} else if (state->std == V4L2_STD_PAL_60) {
+		fmt = 0x8;
+	} else {
+		/* Then, test against generic ones */
+		if (state->std & V4L2_STD_NTSC)
+			fmt = 0x1;
+		else if (state->std & V4L2_STD_PAL)
+			fmt = 0x4;
+		else if (state->std & V4L2_STD_SECAM)
+			fmt = 0xc;
+	}
+
+	v4l_dbg(1, cx25840_debug, client, "changing video std to fmt %i\n",fmt);
+
+	/* Follow step 9 of section 3.16 in the cx25840 datasheet.
+	   Without this PAL may display a vertical ghosting effect.
+	   This happens for example with the Yuan MPC622. */
+	if (fmt >= 4 && fmt < 8) {
+		/* Set format to NTSC-M */
+		cx25840_and_or(client, 0x400, ~0xf, 1);
+		/* Turn off LCOMB */
+		cx25840_and_or(client, 0x47b, ~6, 0);
+	}
+	cx25840_and_or(client, 0x400, ~0xf, fmt);
+	cx25840_and_or(client, 0x403, ~0x3, pal_m);
+	if (is_cx23888(state))
+		cx23888_std_setup(client);
+	else
+		cx25840_std_setup(client);
+	if (!is_cx2583x(state))
+		input_change(client);
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static int cx25840_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct v4l2_subdev *sd = to_sd(ctrl);
+	struct cx25840_state *state = to_state(sd);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	switch (ctrl->id) {
+	case V4L2_CID_BRIGHTNESS:
+		cx25840_write(client, 0x414, ctrl->val - 128);
+		break;
+
+	case V4L2_CID_CONTRAST:
+		cx25840_write(client, 0x415, ctrl->val << 1);
+		break;
+
+	case V4L2_CID_SATURATION:
+		if (is_cx23888(state)) {
+			cx25840_write(client, 0x418, ctrl->val << 1);
+			cx25840_write(client, 0x419, ctrl->val << 1);
+		} else {
+			cx25840_write(client, 0x420, ctrl->val << 1);
+			cx25840_write(client, 0x421, ctrl->val << 1);
+		}
+		break;
+
+	case V4L2_CID_HUE:
+		if (is_cx23888(state))
+			cx25840_write(client, 0x41a, ctrl->val);
+		else
+			cx25840_write(client, 0x422, ctrl->val);
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static int cx25840_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
+{
+	struct cx25840_state *state = to_state(sd);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	int HSC, VSC, Vsrc, Hsrc, filter, Vlines;
+	int is_50Hz = !(state->std & V4L2_STD_525_60);
+
+	if (fmt->code != V4L2_MBUS_FMT_FIXED)
+		return -EINVAL;
+
+	fmt->field = V4L2_FIELD_INTERLACED;
+	fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
+
+	if (is_cx23888(state)) {
+		Vsrc = (cx25840_read(client, 0x42a) & 0x3f) << 4;
+		Vsrc |= (cx25840_read(client, 0x429) & 0xf0) >> 4;
+	} else {
+		Vsrc = (cx25840_read(client, 0x476) & 0x3f) << 4;
+		Vsrc |= (cx25840_read(client, 0x475) & 0xf0) >> 4;
+	}
+
+	if (is_cx23888(state)) {
+		Hsrc = (cx25840_read(client, 0x426) & 0x3f) << 4;
+		Hsrc |= (cx25840_read(client, 0x425) & 0xf0) >> 4;
+	} else {
+		Hsrc = (cx25840_read(client, 0x472) & 0x3f) << 4;
+		Hsrc |= (cx25840_read(client, 0x471) & 0xf0) >> 4;
+	}
+
+	Vlines = fmt->height + (is_50Hz ? 4 : 7);
+
+	if ((fmt->width * 16 < Hsrc) || (Hsrc < fmt->width) ||
+			(Vlines * 8 < Vsrc) || (Vsrc < Vlines)) {
+		v4l_err(client, "%dx%d is not a valid size!\n",
+				fmt->width, fmt->height);
+		return -ERANGE;
+	}
+
+	HSC = (Hsrc * (1 << 20)) / fmt->width - (1 << 20);
+	VSC = (1 << 16) - (Vsrc * (1 << 9) / Vlines - (1 << 9));
+	VSC &= 0x1fff;
+
+	if (fmt->width >= 385)
+		filter = 0;
+	else if (fmt->width > 192)
+		filter = 1;
+	else if (fmt->width > 96)
+		filter = 2;
+	else
+		filter = 3;
+
+	v4l_dbg(1, cx25840_debug, client, "decoder set size %dx%d -> scale  %ux%u\n",
+			fmt->width, fmt->height, HSC, VSC);
+
+	/* HSCALE=HSC */
+	cx25840_write(client, 0x418, HSC & 0xff);
+	cx25840_write(client, 0x419, (HSC >> 8) & 0xff);
+	cx25840_write(client, 0x41a, HSC >> 16);
+	/* VSCALE=VSC */
+	cx25840_write(client, 0x41c, VSC & 0xff);
+	cx25840_write(client, 0x41d, VSC >> 8);
+	/* VS_INTRLACE=1 VFILT=filter */
+	cx25840_write(client, 0x41e, 0x8 | filter);
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static void log_video_status(struct i2c_client *client)
+{
+	static const char *const fmt_strs[] = {
+		"0x0",
+		"NTSC-M", "NTSC-J", "NTSC-4.43",
+		"PAL-BDGHI", "PAL-M", "PAL-N", "PAL-Nc", "PAL-60",
+		"0x9", "0xA", "0xB",
+		"SECAM",
+		"0xD", "0xE", "0xF"
+	};
+
+	struct cx25840_state *state = to_state(i2c_get_clientdata(client));
+	u8 vidfmt_sel = cx25840_read(client, 0x400) & 0xf;
+	u8 gen_stat1 = cx25840_read(client, 0x40d);
+	u8 gen_stat2 = cx25840_read(client, 0x40e);
+	int vid_input = state->vid_input;
+
+	v4l_info(client, "Video signal:              %spresent\n",
+		    (gen_stat2 & 0x20) ? "" : "not ");
+	v4l_info(client, "Detected format:           %s\n",
+		    fmt_strs[gen_stat1 & 0xf]);
+
+	v4l_info(client, "Specified standard:        %s\n",
+		    vidfmt_sel ? fmt_strs[vidfmt_sel] : "automatic detection");
+
+	if (vid_input >= CX25840_COMPOSITE1 &&
+	    vid_input <= CX25840_COMPOSITE8) {
+		v4l_info(client, "Specified video input:     Composite %d\n",
+			vid_input - CX25840_COMPOSITE1 + 1);
+	} else {
+		v4l_info(client, "Specified video input:     S-Video (Luma In%d, Chroma In%d)\n",
+			(vid_input & 0xf0) >> 4, (vid_input & 0xf00) >> 8);
+	}
+
+	v4l_info(client, "Specified audioclock freq: %d Hz\n", state->audclk_freq);
+}
+
+/* ----------------------------------------------------------------------- */
+
+static void log_audio_status(struct i2c_client *client)
+{
+	struct cx25840_state *state = to_state(i2c_get_clientdata(client));
+	u8 download_ctl = cx25840_read(client, 0x803);
+	u8 mod_det_stat0 = cx25840_read(client, 0x804);
+	u8 mod_det_stat1 = cx25840_read(client, 0x805);
+	u8 audio_config = cx25840_read(client, 0x808);
+	u8 pref_mode = cx25840_read(client, 0x809);
+	u8 afc0 = cx25840_read(client, 0x80b);
+	u8 mute_ctl = cx25840_read(client, 0x8d3);
+	int aud_input = state->aud_input;
+	char *p;
+
+	switch (mod_det_stat0) {
+	case 0x00: p = "mono"; break;
+	case 0x01: p = "stereo"; break;
+	case 0x02: p = "dual"; break;
+	case 0x04: p = "tri"; break;
+	case 0x10: p = "mono with SAP"; break;
+	case 0x11: p = "stereo with SAP"; break;
+	case 0x12: p = "dual with SAP"; break;
+	case 0x14: p = "tri with SAP"; break;
+	case 0xfe: p = "forced mode"; break;
+	default: p = "not defined";
+	}
+	v4l_info(client, "Detected audio mode:       %s\n", p);
+
+	switch (mod_det_stat1) {
+	case 0x00: p = "not defined"; break;
+	case 0x01: p = "EIAJ"; break;
+	case 0x02: p = "A2-M"; break;
+	case 0x03: p = "A2-BG"; break;
+	case 0x04: p = "A2-DK1"; break;
+	case 0x05: p = "A2-DK2"; break;
+	case 0x06: p = "A2-DK3"; break;
+	case 0x07: p = "A1 (6.0 MHz FM Mono)"; break;
+	case 0x08: p = "AM-L"; break;
+	case 0x09: p = "NICAM-BG"; break;
+	case 0x0a: p = "NICAM-DK"; break;
+	case 0x0b: p = "NICAM-I"; break;
+	case 0x0c: p = "NICAM-L"; break;
+	case 0x0d: p = "BTSC/EIAJ/A2-M Mono (4.5 MHz FMMono)"; break;
+	case 0x0e: p = "IF FM Radio"; break;
+	case 0x0f: p = "BTSC"; break;
+	case 0x10: p = "high-deviation FM"; break;
+	case 0x11: p = "very high-deviation FM"; break;
+	case 0xfd: p = "unknown audio standard"; break;
+	case 0xfe: p = "forced audio standard"; break;
+	case 0xff: p = "no detected audio standard"; break;
+	default: p = "not defined";
+	}
+	v4l_info(client, "Detected audio standard:   %s\n", p);
+	v4l_info(client, "Audio microcontroller:     %s\n",
+		    (download_ctl & 0x10) ?
+				((mute_ctl & 0x2) ? "detecting" : "running") : "stopped");
+
+	switch (audio_config >> 4) {
+	case 0x00: p = "undefined"; break;
+	case 0x01: p = "BTSC"; break;
+	case 0x02: p = "EIAJ"; break;
+	case 0x03: p = "A2-M"; break;
+	case 0x04: p = "A2-BG"; break;
+	case 0x05: p = "A2-DK1"; break;
+	case 0x06: p = "A2-DK2"; break;
+	case 0x07: p = "A2-DK3"; break;
+	case 0x08: p = "A1 (6.0 MHz FM Mono)"; break;
+	case 0x09: p = "AM-L"; break;
+	case 0x0a: p = "NICAM-BG"; break;
+	case 0x0b: p = "NICAM-DK"; break;
+	case 0x0c: p = "NICAM-I"; break;
+	case 0x0d: p = "NICAM-L"; break;
+	case 0x0e: p = "FM radio"; break;
+	case 0x0f: p = "automatic detection"; break;
+	default: p = "undefined";
+	}
+	v4l_info(client, "Configured audio standard: %s\n", p);
+
+	if ((audio_config >> 4) < 0xF) {
+		switch (audio_config & 0xF) {
+		case 0x00: p = "MONO1 (LANGUAGE A/Mono L+R channel for BTSC, EIAJ, A2)"; break;
+		case 0x01: p = "MONO2 (LANGUAGE B)"; break;
+		case 0x02: p = "MONO3 (STEREO forced MONO)"; break;
+		case 0x03: p = "MONO4 (NICAM ANALOG-Language C/Analog Fallback)"; break;
+		case 0x04: p = "STEREO"; break;
+		case 0x05: p = "DUAL1 (AB)"; break;
+		case 0x06: p = "DUAL2 (AC) (FM)"; break;
+		case 0x07: p = "DUAL3 (BC) (FM)"; break;
+		case 0x08: p = "DUAL4 (AC) (AM)"; break;
+		case 0x09: p = "DUAL5 (BC) (AM)"; break;
+		case 0x0a: p = "SAP"; break;
+		default: p = "undefined";
+		}
+		v4l_info(client, "Configured audio mode:     %s\n", p);
+	} else {
+		switch (audio_config & 0xF) {
+		case 0x00: p = "BG"; break;
+		case 0x01: p = "DK1"; break;
+		case 0x02: p = "DK2"; break;
+		case 0x03: p = "DK3"; break;
+		case 0x04: p = "I"; break;
+		case 0x05: p = "L"; break;
+		case 0x06: p = "BTSC"; break;
+		case 0x07: p = "EIAJ"; break;
+		case 0x08: p = "A2-M"; break;
+		case 0x09: p = "FM Radio"; break;
+		case 0x0f: p = "automatic standard and mode detection"; break;
+		default: p = "undefined";
+		}
+		v4l_info(client, "Configured audio system:   %s\n", p);
+	}
+
+	if (aud_input) {
+		v4l_info(client, "Specified audio input:     Tuner (In%d)\n", aud_input);
+	} else {
+		v4l_info(client, "Specified audio input:     External\n");
+	}
+
+	switch (pref_mode & 0xf) {
+	case 0: p = "mono/language A"; break;
+	case 1: p = "language B"; break;
+	case 2: p = "language C"; break;
+	case 3: p = "analog fallback"; break;
+	case 4: p = "stereo"; break;
+	case 5: p = "language AC"; break;
+	case 6: p = "language BC"; break;
+	case 7: p = "language AB"; break;
+	default: p = "undefined";
+	}
+	v4l_info(client, "Preferred audio mode:      %s\n", p);
+
+	if ((audio_config & 0xf) == 0xf) {
+		switch ((afc0 >> 3) & 0x3) {
+		case 0: p = "system DK"; break;
+		case 1: p = "system L"; break;
+		case 2: p = "autodetect"; break;
+		default: p = "undefined";
+		}
+		v4l_info(client, "Selected 65 MHz format:    %s\n", p);
+
+		switch (afc0 & 0x7) {
+		case 0: p = "chroma"; break;
+		case 1: p = "BTSC"; break;
+		case 2: p = "EIAJ"; break;
+		case 3: p = "A2-M"; break;
+		case 4: p = "autodetect"; break;
+		default: p = "undefined";
+		}
+		v4l_info(client, "Selected 45 MHz format:    %s\n", p);
+	}
+}
+
+/* ----------------------------------------------------------------------- */
+
+/* This load_fw 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_load_fw(struct v4l2_subdev *sd)
+{
+	struct cx25840_state *state = to_state(sd);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	if (!state->is_initialized) {
+		/* initialize and load firmware */
+		state->is_initialized = 1;
+		if (is_cx2583x(state))
+			cx25836_initialize(client);
+		else if (is_cx2388x(state))
+			cx23885_initialize(client);
+		else if (is_cx231xx(state))
+			cx231xx_initialize(client);
+		else
+			cx25840_initialize(client);
+	}
+	return 0;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int cx25840_g_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;
+	reg->size = 1;
+	reg->val = cx25840_read(client, reg->reg & 0x0fff);
+	return 0;
+}
+
+static int cx25840_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;
+	cx25840_write(client, reg->reg & 0x0fff, reg->val & 0xff);
+	return 0;
+}
+#endif
+
+static int cx25840_s_audio_stream(struct v4l2_subdev *sd, int enable)
+{
+	struct cx25840_state *state = to_state(sd);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	u8 v;
+
+	if (is_cx2583x(state) || is_cx2388x(state) || is_cx231xx(state))
+		return 0;
+
+	v4l_dbg(1, cx25840_debug, client, "%s audio output\n",
+			enable ? "enable" : "disable");
+
+	if (enable) {
+		v = cx25840_read(client, 0x115) | 0x80;
+		cx25840_write(client, 0x115, v);
+		v = cx25840_read(client, 0x116) | 0x03;
+		cx25840_write(client, 0x116, v);
+	} else {
+		v = cx25840_read(client, 0x115) & ~(0x80);
+		cx25840_write(client, 0x115, v);
+		v = cx25840_read(client, 0x116) & ~(0x03);
+		cx25840_write(client, 0x116, v);
+	}
+	return 0;
+}
+
+static int cx25840_s_stream(struct v4l2_subdev *sd, int enable)
+{
+	struct cx25840_state *state = to_state(sd);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	u8 v;
+
+	v4l_dbg(1, cx25840_debug, client, "%s video output\n",
+			enable ? "enable" : "disable");
+	if (enable) {
+		if (is_cx2388x(state) || is_cx231xx(state)) {
+			v = cx25840_read(client, 0x421) | 0x0b;
+			cx25840_write(client, 0x421, v);
+		} else {
+			v = cx25840_read(client, 0x115) | 0x0c;
+			cx25840_write(client, 0x115, v);
+			v = cx25840_read(client, 0x116) | 0x04;
+			cx25840_write(client, 0x116, v);
+		}
+	} else {
+		if (is_cx2388x(state) || is_cx231xx(state)) {
+			v = cx25840_read(client, 0x421) & ~(0x0b);
+			cx25840_write(client, 0x421, v);
+		} else {
+			v = cx25840_read(client, 0x115) & ~(0x0c);
+			cx25840_write(client, 0x115, v);
+			v = cx25840_read(client, 0x116) & ~(0x04);
+			cx25840_write(client, 0x116, v);
+		}
+	}
+	return 0;
+}
+
+/* Query the current detected video format */
+static int cx25840_g_std(struct v4l2_subdev *sd, v4l2_std_id *std)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	v4l2_std_id stds[] = {
+		/* 0000 */ V4L2_STD_UNKNOWN,
+
+		/* 0001 */ V4L2_STD_NTSC_M,
+		/* 0010 */ V4L2_STD_NTSC_M_JP,
+		/* 0011 */ V4L2_STD_NTSC_443,
+		/* 0100 */ V4L2_STD_PAL,
+		/* 0101 */ V4L2_STD_PAL_M,
+		/* 0110 */ V4L2_STD_PAL_N,
+		/* 0111 */ V4L2_STD_PAL_Nc,
+		/* 1000 */ V4L2_STD_PAL_60,
+
+		/* 1001 */ V4L2_STD_UNKNOWN,
+		/* 1010 */ V4L2_STD_UNKNOWN,
+		/* 1001 */ V4L2_STD_UNKNOWN,
+		/* 1010 */ V4L2_STD_UNKNOWN,
+		/* 1011 */ V4L2_STD_UNKNOWN,
+		/* 1110 */ V4L2_STD_UNKNOWN,
+		/* 1111 */ V4L2_STD_UNKNOWN
+	};
+
+	u32 fmt = (cx25840_read4(client, 0x40c) >> 8) & 0xf;
+	*std = stds[ fmt ];
+
+	v4l_dbg(1, cx25840_debug, client, "g_std fmt = %x, v4l2_std_id = 0x%x\n",
+		fmt, (unsigned int)stds[ fmt ]);
+
+	return 0;
+}
+
+static int cx25840_g_input_status(struct v4l2_subdev *sd, u32 *status)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	/* A limited function that checks for signal status and returns
+	 * the state.
+	 */
+
+	/* Check for status of Horizontal lock (SRC lock isn't reliable) */
+	if ((cx25840_read4(client, 0x40c) & 0x00010000) == 0)
+		*status |= V4L2_IN_ST_NO_SIGNAL;
+
+	return 0;
+}
+
+static int cx25840_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
+{
+	struct cx25840_state *state = to_state(sd);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	if (state->radio == 0 && state->std == std)
+		return 0;
+	state->radio = 0;
+	state->std = std;
+	return set_v4lstd(client);
+}
+
+static int cx25840_s_radio(struct v4l2_subdev *sd)
+{
+	struct cx25840_state *state = to_state(sd);
+
+	state->radio = 1;
+	return 0;
+}
+
+static int cx25840_s_video_routing(struct v4l2_subdev *sd,
+				   u32 input, u32 output, u32 config)
+{
+	struct cx25840_state *state = to_state(sd);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	if (is_cx23888(state))
+		cx23888_std_setup(client);
+
+	return set_input(client, input, state->aud_input);
+}
+
+static int cx25840_s_audio_routing(struct v4l2_subdev *sd,
+				   u32 input, u32 output, u32 config)
+{
+	struct cx25840_state *state = to_state(sd);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	if (is_cx23888(state))
+		cx23888_std_setup(client);
+	return set_input(client, state->vid_input, input);
+}
+
+static int cx25840_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *freq)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	input_change(client);
+	return 0;
+}
+
+static int cx25840_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
+{
+	struct cx25840_state *state = to_state(sd);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	u8 vpres = cx25840_read(client, 0x40e) & 0x20;
+	u8 mode;
+	int val = 0;
+
+	if (state->radio)
+		return 0;
+
+	vt->signal = vpres ? 0xffff : 0x0;
+	if (is_cx2583x(state))
+		return 0;
+
+	vt->capability |=
+		V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 |
+		V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;
+
+	mode = cx25840_read(client, 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 cx25840_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
+{
+	struct cx25840_state *state = to_state(sd);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	if (state->radio || is_cx2583x(state))
+		return 0;
+
+	switch (vt->audmode) {
+		case V4L2_TUNER_MODE_MONO:
+			/* mono      -> mono
+			   stereo    -> mono
+			   bilingual -> lang1 */
+			cx25840_and_or(client, 0x809, ~0xf, 0x00);
+			break;
+		case V4L2_TUNER_MODE_STEREO:
+		case V4L2_TUNER_MODE_LANG1:
+			/* mono      -> mono
+			   stereo    -> stereo
+			   bilingual -> lang1 */
+			cx25840_and_or(client, 0x809, ~0xf, 0x04);
+			break;
+		case V4L2_TUNER_MODE_LANG1_LANG2:
+			/* mono      -> mono
+			   stereo    -> stereo
+			   bilingual -> lang1/lang2 */
+			cx25840_and_or(client, 0x809, ~0xf, 0x07);
+			break;
+		case V4L2_TUNER_MODE_LANG2:
+			/* mono      -> mono
+			   stereo    -> stereo
+			   bilingual -> lang2 */
+			cx25840_and_or(client, 0x809, ~0xf, 0x01);
+			break;
+		default:
+			return -EINVAL;
+	}
+	state->audmode = vt->audmode;
+	return 0;
+}
+
+static int cx25840_reset(struct v4l2_subdev *sd, u32 val)
+{
+	struct cx25840_state *state = to_state(sd);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	if (is_cx2583x(state))
+		cx25836_initialize(client);
+	else if (is_cx2388x(state))
+		cx23885_initialize(client);
+	else if (is_cx231xx(state))
+		cx231xx_initialize(client);
+	else
+		cx25840_initialize(client);
+	return 0;
+}
+
+static int cx25840_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
+{
+	struct cx25840_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 cx25840_log_status(struct v4l2_subdev *sd)
+{
+	struct cx25840_state *state = to_state(sd);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	log_video_status(client);
+	if (!is_cx2583x(state))
+		log_audio_status(client);
+	cx25840_ir_log_status(sd);
+	v4l2_ctrl_handler_log_status(&state->hdl, sd->name);
+	return 0;
+}
+
+static int cx23885_irq_handler(struct v4l2_subdev *sd, u32 status,
+			       bool *handled)
+{
+	struct cx25840_state *state = to_state(sd);
+	struct i2c_client *c = v4l2_get_subdevdata(sd);
+	u8 irq_stat, aud_stat, aud_en, ir_stat, ir_en;
+	u32 vid_stat, aud_mc_stat;
+	bool block_handled;
+	int ret = 0;
+
+	irq_stat = cx25840_read(c, CX23885_PIN_CTRL_IRQ_REG);
+	v4l_dbg(2, cx25840_debug, c, "AV Core IRQ status (entry): %s %s %s\n",
+		irq_stat & CX23885_PIN_CTRL_IRQ_IR_STAT ? "ir" : "  ",
+		irq_stat & CX23885_PIN_CTRL_IRQ_AUD_STAT ? "aud" : "   ",
+		irq_stat & CX23885_PIN_CTRL_IRQ_VID_STAT ? "vid" : "   ");
+
+	if ((is_cx23885(state) || is_cx23887(state))) {
+		ir_stat = cx25840_read(c, CX25840_IR_STATS_REG);
+		ir_en = cx25840_read(c, CX25840_IR_IRQEN_REG);
+		v4l_dbg(2, cx25840_debug, c,
+			"AV Core ir IRQ status: %#04x disables: %#04x\n",
+			ir_stat, ir_en);
+		if (irq_stat & CX23885_PIN_CTRL_IRQ_IR_STAT) {
+			block_handled = false;
+			ret = cx25840_ir_irq_handler(sd,
+						     status, &block_handled);
+			if (block_handled)
+				*handled = true;
+		}
+	}
+
+	aud_stat = cx25840_read(c, CX25840_AUD_INT_STAT_REG);
+	aud_en = cx25840_read(c, CX25840_AUD_INT_CTRL_REG);
+	v4l_dbg(2, cx25840_debug, c,
+		"AV Core audio IRQ status: %#04x disables: %#04x\n",
+		aud_stat, aud_en);
+	aud_mc_stat = cx25840_read4(c, CX23885_AUD_MC_INT_MASK_REG);
+	v4l_dbg(2, cx25840_debug, c,
+		"AV Core audio MC IRQ status: %#06x enables: %#06x\n",
+		aud_mc_stat >> CX23885_AUD_MC_INT_STAT_SHFT,
+		aud_mc_stat & CX23885_AUD_MC_INT_CTRL_BITS);
+	if (irq_stat & CX23885_PIN_CTRL_IRQ_AUD_STAT) {
+		if (aud_stat) {
+			cx25840_write(c, CX25840_AUD_INT_STAT_REG, aud_stat);
+			*handled = true;
+		}
+	}
+
+	vid_stat = cx25840_read4(c, CX25840_VID_INT_STAT_REG);
+	v4l_dbg(2, cx25840_debug, c,
+		"AV Core video IRQ status: %#06x disables: %#06x\n",
+		vid_stat & CX25840_VID_INT_STAT_BITS,
+		vid_stat >> CX25840_VID_INT_MASK_SHFT);
+	if (irq_stat & CX23885_PIN_CTRL_IRQ_VID_STAT) {
+		if (vid_stat & CX25840_VID_INT_STAT_BITS) {
+			cx25840_write4(c, CX25840_VID_INT_STAT_REG, vid_stat);
+			*handled = true;
+		}
+	}
+
+	irq_stat = cx25840_read(c, CX23885_PIN_CTRL_IRQ_REG);
+	v4l_dbg(2, cx25840_debug, c, "AV Core IRQ status (exit): %s %s %s\n",
+		irq_stat & CX23885_PIN_CTRL_IRQ_IR_STAT ? "ir" : "  ",
+		irq_stat & CX23885_PIN_CTRL_IRQ_AUD_STAT ? "aud" : "   ",
+		irq_stat & CX23885_PIN_CTRL_IRQ_VID_STAT ? "vid" : "   ");
+
+	return ret;
+}
+
+static int cx25840_irq_handler(struct v4l2_subdev *sd, u32 status,
+			       bool *handled)
+{
+	struct cx25840_state *state = to_state(sd);
+
+	*handled = false;
+
+	/* Only support the CX2388[578] AV Core for now */
+	if (is_cx2388x(state))
+		return cx23885_irq_handler(sd, status, handled);
+
+	return -ENODEV;
+}
+
+/* ----------------------------------------------------------------------- */
+
+#define DIF_PLL_FREQ_WORD	(0x300)
+#define DIF_BPF_COEFF01		(0x348)
+#define DIF_BPF_COEFF23		(0x34c)
+#define DIF_BPF_COEFF45		(0x350)
+#define DIF_BPF_COEFF67		(0x354)
+#define DIF_BPF_COEFF89		(0x358)
+#define DIF_BPF_COEFF1011	(0x35c)
+#define DIF_BPF_COEFF1213	(0x360)
+#define DIF_BPF_COEFF1415	(0x364)
+#define DIF_BPF_COEFF1617	(0x368)
+#define DIF_BPF_COEFF1819	(0x36c)
+#define DIF_BPF_COEFF2021	(0x370)
+#define DIF_BPF_COEFF2223	(0x374)
+#define DIF_BPF_COEFF2425	(0x378)
+#define DIF_BPF_COEFF2627	(0x37c)
+#define DIF_BPF_COEFF2829	(0x380)
+#define DIF_BPF_COEFF3031	(0x384)
+#define DIF_BPF_COEFF3233	(0x388)
+#define DIF_BPF_COEFF3435	(0x38c)
+#define DIF_BPF_COEFF36		(0x390)
+
+void cx23885_dif_setup(struct i2c_client *client, u32 ifHz)
+{
+	u64 pll_freq;
+	u32 pll_freq_word;
+
+	v4l_dbg(1, cx25840_debug, client, "%s(%d)\n", __func__, ifHz);
+
+	/* Assuming TV */
+	/* Calculate the PLL frequency word based on the adjusted ifHz */
+        pll_freq = div_u64((u64)ifHz * 268435456, 50000000);
+        pll_freq_word = (u32)pll_freq;
+
+        cx25840_write4(client, DIF_PLL_FREQ_WORD,  pll_freq_word);
+
+	/* Round down to the nearest 100KHz */
+	ifHz = (ifHz / 100000) * 100000;
+
+	if (ifHz < 3000000)
+		ifHz = 3000000;
+
+	if (ifHz > 16000000)
+		ifHz = 16000000;
+
+	v4l_dbg(1, cx25840_debug, client, "%s(%d) again\n", __func__, ifHz);
+
+	switch (ifHz) {
+	case 3000000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x00000002);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x00080012);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x001e0024);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x001bfff8);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0xffb4ff50);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0xfed8fe68);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe24fe34);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xfebaffc7);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x014d031f);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0x04f0065d);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x07010688);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x04c901d6);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0xfe00f9d3);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0xf600f342);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xf235f337);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xf64efb22);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0x0105070f);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0x0c460fce);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 3100000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x00000001);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x00070012);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x00220032);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x00370026);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0xfff0ff91);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0xff0efe7c);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe01fdcc);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xfe0afedb);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x00440224);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0x0434060c);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x0738074e);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x06090361);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0xff99fb39);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0xf6fef3b6);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xf21af2a5);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xf573fa33);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0x0034067d);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0x0bfb0fb9);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 3200000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x00000000);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x0004000e);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x00200038);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x004c004f);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x002fffdf);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0xff5cfeb6);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe0dfd92);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd7ffe03);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0xff36010a);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0x03410575);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x072607d2);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x071804d5);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x0134fcb7);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0xf81ff451);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xf223f22e);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xf4a7f94b);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xff6405e8);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0x0bae0fa4);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 3300000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x0000ffff);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x00000008);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x001a0036);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x0056006d);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x00670030);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0xffbdff10);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe46fd8d);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd25fd4f);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0xfe35ffe0);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0x0224049f);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x06c9080e);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x07ef0627);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x02c9fe45);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0xf961f513);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xf250f1d2);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xf3ecf869);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xfe930552);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0x0b5f0f8f);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 3400000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0xfffffffe);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0xfffd0001);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x000f002c);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x0054007d);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x0093007c);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x0024ff82);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xfea6fdbb);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd03fcca);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0xfd51feb9);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0x00eb0392);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x06270802);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x08880750);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x044dffdb);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0xfabdf5f8);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xf2a0f193);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xf342f78f);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xfdc404b9);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0x0b0e0f78);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 3500000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0xfffffffd);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0xfffafff9);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x0002001b);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x0046007d);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x00ad00ba);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x00870000);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xff26fe1a);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd1bfc7e);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc99fda4);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xffa5025c);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x054507ad);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x08dd0847);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x05b80172);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0xfc2ef6ff);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xf313f170);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xf2abf6bd);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xfcf6041f);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0x0abc0f61);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 3600000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0xfffffffd);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0xfff8fff3);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0xfff50006);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x002f006c);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x00b200e3);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x00dc007e);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xffb9fea0);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd6bfc71);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc17fcb1);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xfe65010b);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x042d0713);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x08ec0906);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x07020302);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0xfdaff823);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xf3a7f16a);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xf228f5f5);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xfc2a0384);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0x0a670f4a);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 3700000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0xfff7ffef);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0xffe9fff1);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x0010004d);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x00a100f2);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x011a00f0);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0x0053ff44);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xfdedfca2);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0xfbd3fbef);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xfd39ffae);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x02ea0638);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x08b50987);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x08230483);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0xff39f960);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xf45bf180);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xf1b8f537);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xfb6102e7);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0x0a110f32);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 3800000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffe);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0xfff9ffee);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0xffe1ffdd);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0xfff00024);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x007c00e5);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x013a014a);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0x00e6fff8);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xfe98fd0f);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0xfbd3fb67);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xfc32fe54);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x01880525);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x083909c7);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x091505ee);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x00c7fab3);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xf52df1b4);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xf15df484);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xfa9b0249);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0x09ba0f19);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 3900000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x00000000);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0xfffbfff0);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0xffdeffcf);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0xffd1fff6);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x004800be);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x01390184);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0x016300ac);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xff5efdb1);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc17fb23);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xfb5cfd0d);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x001703e4);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x077b09c4);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x09d2073c);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x0251fc18);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xf61cf203);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xf118f3dc);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xf9d801aa);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0x09600eff);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 4000000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x00000001);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0xfffefff4);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0xffe1ffc8);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0xffbaffca);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x000b0082);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x01170198);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0x01c10152);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0x0030fe7b);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc99fb24);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xfac3fbe9);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0xfea5027f);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x0683097f);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x0a560867);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x03d2fd89);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xf723f26f);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xf0e8f341);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xf919010a);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0x09060ee5);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 4100000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x00010002);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x0002fffb);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0xffe8ffca);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0xffacffa4);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0xffcd0036);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x00d70184);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0x01f601dc);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0x00ffff60);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0xfd51fb6d);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa6efaf5);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0xfd410103);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x055708f9);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x0a9e0969);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x0543ff02);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xf842f2f5);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xf0cef2b2);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xf85e006b);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0x08aa0ecb);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 4200000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x00010003);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x00050003);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0xfff3ffd3);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0xffaaff8b);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0xff95ffe5);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x0080014a);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0x01fe023f);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0x01ba0050);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0xfe35fbf8);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa62fa3b);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0xfbf9ff7e);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x04010836);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x0aa90a3d);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x069f007f);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xf975f395);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xf0cbf231);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xf7a9ffcb);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0x084c0eaf);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 4300000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x00010003);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x0008000a);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x0000ffe4);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0xffb4ff81);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0xff6aff96);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x001c00f0);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0x01d70271);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0x0254013b);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0xff36fcbd);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa9ff9c5);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0xfadbfdfe);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x028c073b);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x0a750adf);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x07e101fa);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xfab8f44e);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xf0ddf1be);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xf6f9ff2b);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0x07ed0e94);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 4400000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x0009000f);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x000efff8);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0xffc9ff87);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0xff52ff54);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0xffb5007e);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0x01860270);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0x02c00210);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x0044fdb2);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xfb22f997);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0xf9f2fc90);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x0102060f);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x0a050b4c);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x0902036e);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xfc0af51e);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xf106f15a);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xf64efe8b);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0x078d0e77);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 4500000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x00000002);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x00080012);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x0019000e);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0xffe5ff9e);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0xff4fff25);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0xff560000);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0x0112023b);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0x02f702c0);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x014dfec8);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xfbe5f9b3);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0xf947fb41);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0xff7004b9);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x095a0b81);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x0a0004d8);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xfd65f603);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xf144f104);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xf5aafdec);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0x072b0e5a);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 4600000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x00000001);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x00060012);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x00200022);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x0005ffc1);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0xff61ff10);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0xff09ff82);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0x008601d7);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0x02f50340);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x0241fff0);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xfcddfa19);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0xf8e2fa1e);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0xfde30343);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x08790b7f);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x0ad50631);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xfec7f6fc);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xf198f0bd);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xf50dfd4e);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0x06c90e3d);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 4700000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x0000ffff);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x0003000f);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x00220030);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x0025ffed);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0xff87ff15);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0xfed6ff10);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xffed014c);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0x02b90386);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x03110119);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xfdfefac4);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0xf8c6f92f);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0xfc6701b7);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x07670b44);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x0b7e0776);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0x002df807);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xf200f086);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xf477fcb1);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0x06650e1e);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 4800000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0xfffffffe);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0xffff0009);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x001e0038);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x003f001b);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0xffbcff36);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0xfec2feb6);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xff5600a5);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0x0248038d);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x03b00232);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xff39fbab);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0xf8f4f87f);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0xfb060020);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x062a0ad2);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x0bf908a3);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0x0192f922);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xf27df05e);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xf3e8fc14);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0x06000e00);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 4900000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0xfffffffd);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0xfffc0002);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x00160037);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x00510046);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0xfff9ff6d);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0xfed0fe7c);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xfecefff0);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0x01aa0356);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x0413032b);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0x007ffcc5);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0xf96cf812);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0xf9cefe87);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x04c90a2c);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x0c4309b4);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0x02f3fa4a);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xf30ef046);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xf361fb7a);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0x059b0de0);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 5000000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0xfffffffd);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0xfff9fffa);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x000a002d);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x00570067);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x0037ffb5);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0xfefffe68);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe62ff3d);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0x00ec02e3);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x043503f6);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0x01befe05);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0xfa27f7ee);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0xf8c6fcf8);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x034c0954);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x0c5c0aa4);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0x044cfb7e);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xf3b1f03f);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xf2e2fae1);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0x05340dc0);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 5100000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0xfff8fff4);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0xfffd001e);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x0051007b);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x006e0006);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0xff48fe7c);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe1bfe9a);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0x001d023e);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x04130488);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0x02e6ff5b);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0xfb1ef812);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0xf7f7fb7f);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x01bc084e);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x0c430b72);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0x059afcba);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xf467f046);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xf26cfa4a);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0x04cd0da0);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 5200000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffe);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0xfff8ffef);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0xfff00009);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x003f007f);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x00980056);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0xffa5feb6);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe00fe15);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xff4b0170);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x03b004d7);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0x03e800b9);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0xfc48f87f);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0xf768fa23);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x0022071f);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x0bf90c1b);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0x06dafdfd);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xf52df05e);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xf1fef9b5);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0x04640d7f);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 5300000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x0000ffff);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0xfff9ffee);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0xffe6fff3);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x00250072);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x00af009c);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x000cff10);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe13fdb8);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xfe870089);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x031104e1);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0x04b8020f);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0xfd98f92f);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0xf71df8f0);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0xfe8805ce);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x0b7e0c9c);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0x0808ff44);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xf603f086);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xf19af922);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0x03fb0d5e);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 5400000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x00000001);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0xfffcffef);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0xffe0ffe0);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x00050056);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x00b000d1);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x0071ff82);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe53fd8c);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xfddfff99);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x024104a3);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0x054a034d);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0xff01fa1e);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0xf717f7ed);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0xfcf50461);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x0ad50cf4);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0x0921008d);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xf6e7f0bd);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xf13ff891);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0x03920d3b);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 5500000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x00010002);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0xfffffff3);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0xffdeffd1);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0xffe5002f);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x009c00ed);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x00cb0000);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xfebafd94);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd61feb0);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x014d0422);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0x05970464);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x0074fb41);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0xf759f721);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0xfb7502de);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x0a000d21);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0x0a2201d4);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xf7d9f104);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xf0edf804);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0x03280d19);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 5600000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x00010003);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x0003fffa);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0xffe3ffc9);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0xffc90002);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x007500ef);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x010e007e);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xff3dfdcf);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd16fddd);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x00440365);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0x059b0548);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x01e3fc90);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0xf7dff691);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0xfa0f014d);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x09020d23);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0x0b0a0318);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xf8d7f15a);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xf0a5f779);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0x02bd0cf6);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 5700000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x00010003);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x00060001);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0xffecffc9);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0xffb4ffd4);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x004000d5);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x013600f0);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xffd3fe39);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd04fd31);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0xff360277);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0x055605ef);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x033efdfe);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0xf8a5f642);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0xf8cbffb6);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x07e10cfb);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0x0bd50456);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xf9dff1be);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xf067f6f2);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0x02520cd2);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 5800000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x00080009);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0xfff8ffd2);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0xffaaffac);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x000200a3);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x013c014a);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0x006dfec9);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd2bfcb7);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0xfe350165);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0x04cb0651);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x0477ff7e);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0xf9a5f635);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0xf7b1fe20);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x069f0ca8);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0x0c81058b);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xfaf0f231);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xf033f66d);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0x01e60cae);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 5900000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x00000002);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x0009000e);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x0005ffe1);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0xffacff90);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0xffc5005f);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x01210184);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0x00fcff72);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd8afc77);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0xfd51003f);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0x04020669);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x05830103);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0xfad7f66b);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0xf6c8fc93);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x05430c2b);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0x0d0d06b5);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xfc08f2b2);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xf00af5ec);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0x017b0c89);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 6000000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x00000001);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x00070012);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x0012fff5);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0xffbaff82);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0xff8e000f);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x00e80198);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0x01750028);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xfe18fc75);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc99ff15);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0x03050636);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x0656027f);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0xfc32f6e2);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0xf614fb17);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x03d20b87);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0x0d7707d2);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xfd26f341);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xefeaf56f);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0x010f0c64);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 6100000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0xffff0000);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x00050012);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x001c000b);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0xffd1ff84);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0xff66ffbe);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x00960184);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0x01cd00da);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xfeccfcb2);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc17fdf9);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0x01e005bc);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x06e703e4);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0xfdabf798);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0xf599f9b3);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x02510abd);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0x0dbf08df);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xfe48f3dc);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xefd5f4f6);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0x00a20c3e);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 6200000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0xfffffffe);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x0002000f);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x0021001f);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0xfff0ff97);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0xff50ff74);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x0034014a);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0x01fa0179);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xff97fd2a);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0xfbd3fcfa);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0x00a304fe);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x07310525);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0xff37f886);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0xf55cf86e);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x00c709d0);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0x0de209db);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xff6df484);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xefcbf481);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0x00360c18);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 6300000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0xfffffffd);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0xfffe000a);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x0021002f);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x0010ffb8);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0xff50ff3b);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0xffcc00f0);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0x01fa01fa);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0x0069fdd4);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0xfbd3fc26);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xff5d0407);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x07310638);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x00c9f9a8);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0xf55cf74e);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0xff3908c3);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0x0de20ac3);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0x0093f537);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xefcbf410);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xffca0bf2);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 6400000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0xfffffffd);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0xfffb0003);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x001c0037);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x002fffe2);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0xff66ff17);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0xff6a007e);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0x01cd0251);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0x0134fea5);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc17fb8b);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xfe2002e0);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x06e70713);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x0255faf5);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0xf599f658);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0xfdaf0799);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0x0dbf0b96);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0x01b8f5f5);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xefd5f3a3);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xff5e0bca);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 6500000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0xfff9fffb);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x00120037);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x00460010);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0xff8eff0f);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0xff180000);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0x01750276);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0x01e8ff8d);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc99fb31);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xfcfb0198);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x065607ad);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x03cefc64);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0xf614f592);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0xfc2e0656);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0x0d770c52);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0x02daf6bd);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xefeaf33b);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xfef10ba3);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 6600000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffe);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0xfff7fff5);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x0005002f);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x0054003c);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0xffc5ff22);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0xfedfff82);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0x00fc0267);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0x0276007e);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0xfd51fb1c);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xfbfe003e);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x05830802);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x0529fdec);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0xf6c8f4fe);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0xfabd04ff);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0x0d0d0cf6);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0x03f8f78f);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xf00af2d7);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xfe850b7b);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 6700000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x0000ffff);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0xfff8fff0);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0xfff80020);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x00560060);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x0002ff4e);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0xfec4ff10);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0x006d0225);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0x02d50166);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0xfe35fb4e);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xfb35fee1);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x0477080e);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x065bff82);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0xf7b1f4a0);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0xf9610397);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0x0c810d80);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0x0510f869);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xf033f278);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xfe1a0b52);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 6800000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x00010000);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0xfffaffee);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0xffec000c);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x004c0078);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x0040ff8e);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0xfecafeb6);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xffd301b6);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0x02fc0235);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0xff36fbc5);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xfaaafd90);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x033e07d2);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x075b011b);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0xf8cbf47a);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0xf81f0224);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0x0bd50def);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0x0621f94b);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xf067f21e);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xfdae0b29);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 6900000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x00010001);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0xfffdffef);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0xffe3fff6);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x0037007f);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x0075ffdc);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0xfef2fe7c);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xff3d0122);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0x02ea02dd);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x0044fc79);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa65fc5d);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x01e3074e);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x082102ad);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0xfa0ff48c);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0xf6fe00a9);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0x0b0a0e43);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0x0729fa33);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xf0a5f1c9);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xfd430b00);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 7000000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x00010002);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x0001fff3);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0xffdeffe2);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x001b0076);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x009c002d);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0xff35fe68);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xfeba0076);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0x029f0352);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x014dfd60);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa69fb53);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x00740688);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x08a7042d);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0xfb75f4d6);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0xf600ff2d);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0x0a220e7a);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0x0827fb22);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xf0edf17a);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xfcd80ad6);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 7100000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x0004fff9);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0xffe0ffd2);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0xfffb005e);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x00b0007a);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0xff8ffe7c);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe53ffc1);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0x0221038c);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x0241fe6e);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xfab6fa80);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0xff010587);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x08e90590);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0xfcf5f556);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0xf52bfdb3);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0x09210e95);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0x0919fc15);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xf13ff12f);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xfc6e0aab);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 7200000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x00070000);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0xffe6ffc9);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0xffdb0039);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x00af00b8);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0xfff4feb6);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe13ff10);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0x01790388);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x0311ff92);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xfb48f9ed);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0xfd980453);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x08e306cd);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0xfe88f60a);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0xf482fc40);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0x08080e93);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0x09fdfd0c);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xf19af0ea);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xfc050a81);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 7300000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x00000002);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x00080008);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0xfff0ffc9);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0xffc1000d);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x009800e2);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x005bff10);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe00fe74);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0x00b50345);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x03b000bc);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xfc18f9a1);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0xfc4802f9);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x089807dc);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x0022f6f0);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0xf407fada);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0x06da0e74);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0x0ad3fe06);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xf1fef0ab);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xfb9c0a55);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 7400000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x00000001);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x0008000e);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0xfffdffd0);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0xffafffdf);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x006e00f2);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x00b8ff82);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe1bfdf8);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xffe302c8);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x041301dc);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xfd1af99e);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0xfb1e0183);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x080908b5);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x01bcf801);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0xf3bdf985);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0x059a0e38);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0x0b99ff03);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xf26cf071);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xfb330a2a);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 7500000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0xffff0000);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x00070011);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x000affdf);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0xffa9ffb5);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x003700e6);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x01010000);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe62fda8);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xff140219);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x043502e1);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xfe42f9e6);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0xfa270000);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x073a0953);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x034cf939);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0xf3a4f845);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0x044c0de1);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0x0c4f0000);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xf2e2f03c);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xfacc09fe);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 7600000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0xffffffff);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x00040012);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x0016fff3);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0xffafff95);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0xfff900c0);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x0130007e);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xfecefd89);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xfe560146);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x041303bc);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xff81fa76);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0xf96cfe7d);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x063209b1);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x04c9fa93);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0xf3bdf71e);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0x02f30d6e);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0x0cf200fd);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xf361f00e);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xfa6509d1);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 7700000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0xfffffffe);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x00010010);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x001e0008);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0xffc1ff84);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0xffbc0084);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x013e00f0);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xff56fd9f);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xfdb8005c);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x03b00460);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0x00c7fb45);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0xf8f4fd07);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x04fa09ce);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x062afc07);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0xf407f614);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0x01920ce0);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0x0d8301fa);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xf3e8efe5);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xfa0009a4);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 7800000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0xfffd000b);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x0022001d);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0xffdbff82);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0xff870039);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x012a014a);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xffedfde7);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd47ff6b);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x031104c6);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0x0202fc4c);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0xf8c6fbad);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x039909a7);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x0767fd8e);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0xf482f52b);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0x002d0c39);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0x0e0002f4);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xf477efc2);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xf99b0977);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 7900000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0xfffa0004);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x0020002d);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0xfffbff91);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0xff61ffe8);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x00f70184);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0x0086fe5c);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd0bfe85);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x024104e5);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0x0323fd7d);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0xf8e2fa79);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x021d093f);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x0879ff22);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0xf52bf465);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xfec70b79);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0x0e6803eb);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xf50defa5);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xf937094a);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 8000000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffe);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0xfff8fffd);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x00190036);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x001bffaf);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0xff4fff99);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x00aa0198);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0x0112fef3);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd09fdb9);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x014d04be);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0x041bfecc);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0xf947f978);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x00900897);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x095a00b9);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0xf600f3c5);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xfd650aa3);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0x0ebc04de);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xf5aaef8e);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xf8d5091c);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 8100000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x0000ffff);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0xfff7fff6);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x000e0038);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x0037ffd7);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0xff52ff56);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x004b0184);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0x0186ffa1);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd40fd16);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x00440452);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0x04de0029);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0xf9f2f8b2);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0xfefe07b5);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x0a05024d);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0xf6fef34d);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xfc0a09b8);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0x0efa05cd);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xf64eef7d);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xf87308ed);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 8200000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x00010000);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0xfff8fff0);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x00000031);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x004c0005);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0xff6aff27);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0xffe4014a);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0x01d70057);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xfdacfca6);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0xff3603a7);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0x05610184);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0xfadbf82e);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0xfd74069f);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x0a7503d6);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0xf81ff2ff);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xfab808b9);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0x0f2306b5);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xf6f9ef72);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xf81308bf);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 8300000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x00010001);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0xfffbffee);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0xfff30022);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x00560032);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0xff95ff10);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0xff8000f0);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0x01fe0106);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xfe46fc71);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0xfe3502c7);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0x059e02ce);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0xfbf9f7f2);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0xfbff055b);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x0aa9054c);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0xf961f2db);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xf97507aa);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0x0f350797);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xf7a9ef6d);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xf7b40890);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 8400000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x00010002);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0xfffeffee);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0xffe8000f);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x00540058);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0xffcdff14);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0xff29007e);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0x01f6019e);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xff01fc7c);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0xfd5101bf);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0x059203f6);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0xfd41f7fe);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0xfaa903f3);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x0a9e06a9);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0xfabdf2e2);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xf842068b);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0x0f320871);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xf85eef6e);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xf7560860);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 8500000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x0002fff2);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0xffe1fff9);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x00460073);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x000bff34);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0xfee90000);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0x01c10215);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xffd0fcc5);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc99009d);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0x053d04f1);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0xfea5f853);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0xf97d0270);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x0a5607e4);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0xfc2ef314);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xf723055f);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0x0f180943);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xf919ef75);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xf6fa0830);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 8600000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x0005fff8);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0xffdeffe4);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x002f007f);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x0048ff6b);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0xfec7ff82);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0x0163025f);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0x00a2fd47);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc17ff73);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0x04a405b2);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x0017f8ed);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0xf88500dc);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x09d208f9);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0xfdaff370);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xf61c0429);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0x0ee80a0b);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xf9d8ef82);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xf6a00800);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 8700000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x0007ffff);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0xffe1ffd4);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x0010007a);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x007cffb2);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0xfec6ff10);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0x00e60277);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0x0168fdf9);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0xfbd3fe50);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0x03ce0631);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x0188f9c8);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0xf7c7ff43);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x091509e3);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0xff39f3f6);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xf52d02ea);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0x0ea30ac9);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xfa9bef95);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xf64607d0);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 8800000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x00000002);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x00090007);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0xffe9ffca);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0xfff00065);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x00a10003);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0xfee6feb6);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0x0053025b);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0x0213fed0);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0xfbd3fd46);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0x02c70668);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x02eafadb);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0xf74bfdae);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x08230a9c);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x00c7f4a3);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xf45b01a6);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0x0e480b7c);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xfb61efae);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xf5ef079f);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 8900000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0xffff0000);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x0008000d);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0xfff5ffc8);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0xffd10043);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x00b20053);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0xff24fe7c);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xffb9020c);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0x0295ffbb);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc17fc64);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0x019b0654);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x042dfc1c);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0xf714fc2a);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x07020b21);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x0251f575);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xf3a7005e);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0x0dd80c24);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xfc2aefcd);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xf599076e);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 9000000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0xffffffff);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x00060011);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x0002ffcf);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0xffba0018);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x00ad009a);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0xff79fe68);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xff260192);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0x02e500ab);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc99fbb6);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0x005b05f7);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x0545fd81);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0xf723fabf);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x05b80b70);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x03d2f669);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xf313ff15);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0x0d550cbf);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xfcf6eff2);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xf544073d);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 9100000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0xfffffffe);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x00030012);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x000fffdd);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0xffacffea);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x009300cf);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0xffdcfe7c);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xfea600f7);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0x02fd0190);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0xfd51fb46);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xff150554);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x0627fefd);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0xf778f978);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x044d0b87);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x0543f77d);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xf2a0fdcf);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0x0cbe0d4e);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xfdc4f01d);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xf4f2070b);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 9200000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x00000010);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x001afff0);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0xffaaffbf);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x006700ed);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x0043feb6);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe460047);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0x02db0258);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0xfe35fb1b);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xfddc0473);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x06c90082);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0xf811f85e);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x02c90b66);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x069ff8ad);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xf250fc8d);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0x0c140dcf);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xfe93f04d);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xf4a106d9);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 9300000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0xfffc000c);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x00200006);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0xffb4ff9c);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x002f00ef);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x00a4ff10);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe0dff92);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0x028102f7);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0xff36fb37);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xfcbf035e);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x07260202);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0xf8e8f778);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x01340b0d);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x07e1f9f4);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xf223fb51);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0x0b590e42);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xff64f083);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xf45206a7);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 9400000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0xfff90005);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x0022001a);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0xffc9ff86);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0xfff000d7);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x00f2ff82);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe01fee5);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0x01f60362);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x0044fb99);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xfbcc0222);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x07380370);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0xf9f7f6cc);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0xff990a7e);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x0902fb50);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xf21afa1f);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0x0a8d0ea6);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0x0034f0bf);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xf4050675);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 9500000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffe);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0xfff8fffe);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x001e002b);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0xffe5ff81);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0xffb400a5);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x01280000);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe24fe50);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0x01460390);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x014dfc3a);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xfb1000ce);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x070104bf);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0xfb37f65f);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0xfe0009bc);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x0a00fcbb);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xf235f8f8);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0x09b20efc);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0x0105f101);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xf3ba0642);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 9600000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x0001ffff);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0xfff8fff7);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x00150036);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x0005ff8c);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0xff810061);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x013d007e);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe71fddf);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0x007c0380);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x0241fd13);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa94ff70);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x068005e2);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0xfc9bf633);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0xfc7308ca);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x0ad5fe30);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xf274f7e0);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0x08c90f43);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0x01d4f147);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xf371060f);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 9700000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x00010001);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0xfff9fff1);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x00090038);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x0025ffa7);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0xff5e0012);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x013200f0);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xfee3fd9b);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xffaa0331);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x0311fe15);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa60fe18);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x05bd06d1);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0xfe1bf64a);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0xfafa07ae);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x0b7effab);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xf2d5f6d7);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0x07d30f7a);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0x02a3f194);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xf32905dc);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 9800000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x00010002);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0xfffcffee);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0xfffb0032);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x003fffcd);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0xff4effc1);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x0106014a);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xff6efd8a);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xfedd02aa);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x03b0ff34);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa74fcd7);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x04bf0781);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0xffaaf6a3);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0xf99e066b);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x0bf90128);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xf359f5e1);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0x06d20fa2);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0x0370f1e5);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xf2e405a8);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 9900000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0xffffffee);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0xffef0024);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x0051fffa);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0xff54ff77);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x00be0184);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0x0006fdad);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xfe2701f3);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x0413005e);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xfad1fbba);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x039007ee);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x013bf73d);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0xf868050a);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x0c4302a1);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xf3fdf4fe);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0x05c70fba);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0x043bf23c);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xf2a10575);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 10000000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x0003fff1);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0xffe50011);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x00570027);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0xff70ff3c);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x00620198);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0x009efe01);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd95011a);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x04350183);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xfb71fad0);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x023c0812);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x02c3f811);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0xf75e0390);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x0c5c0411);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xf4c1f432);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0x04b30fc1);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0x0503f297);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xf2610541);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 10100000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x0006fff7);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0xffdffffc);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x00510050);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0xff9dff18);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0xfffc0184);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0x0128fe80);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd32002e);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x04130292);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xfc4dfa21);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x00d107ee);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x0435f91c);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0xf6850205);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x0c430573);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xf5a1f37d);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0x03990fba);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0x05c7f2f8);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xf222050d);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 10200000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x00000002);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x0008fffe);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0xffdfffe7);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x003f006e);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0xffd6ff0f);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0xff96014a);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0x0197ff1f);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd05ff3e);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x03b0037c);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xfd59f9b7);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0xff5d0781);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x0585fa56);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0xf5e4006f);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x0bf906c4);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xf69df2e0);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0x02790fa2);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0x0688f35d);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xf1e604d8);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 10300000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0xffff0001);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x00090005);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0xffe4ffd6);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x0025007e);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x0014ff20);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0xff3c00f0);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0x01e1ffd0);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd12fe5c);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x03110433);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xfe88f996);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0xfdf106d1);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x06aafbb7);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0xf57efed8);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x0b7e07ff);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xf7b0f25e);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0x01560f7a);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0x0745f3c7);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xf1ac04a4);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 10400000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0xffffffff);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x0008000c);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0xffedffcb);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x0005007d);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x0050ff4c);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0xfef6007e);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0x01ff0086);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd58fd97);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x024104ad);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xffcaf9c0);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0xfc9905e2);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x079afd35);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0xf555fd46);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x0ad50920);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xf8d9f1f6);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0x00310f43);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0x07fdf435);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xf174046f);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 10500000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0xfffffffe);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x00050011);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0xfffaffc8);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0xffe5006b);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x0082ff8c);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0xfecc0000);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0x01f00130);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xfdd2fcfc);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x014d04e3);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0x010efa32);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0xfb6404bf);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x084efec5);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0xf569fbc2);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x0a000a23);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xfa15f1ab);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xff0b0efc);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0x08b0f4a7);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xf13f043a);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 10600000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x00020012);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x0007ffcd);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0xffc9004c);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x00a4ffd9);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0xfec3ff82);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0x01b401c1);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xfe76fc97);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x004404d2);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0x0245fae8);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0xfa5f0370);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x08c1005f);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0xf5bcfa52);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x09020b04);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xfb60f17b);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xfde70ea6);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0x095df51e);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xf10c0405);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 10700000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0xffff0011);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x0014ffdb);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0xffb40023);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x00b2002a);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0xfedbff10);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0x0150022d);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xff38fc6f);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0xff36047b);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0x035efbda);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0xf9940202);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x08ee01f5);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0xf649f8fe);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x07e10bc2);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xfcb6f169);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xfcc60e42);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0x0a04f599);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xf0db03d0);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 10800000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0xfffb000d);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x001dffed);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0xffaafff5);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x00aa0077);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0xff13feb6);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0x00ce026b);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0x000afc85);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0xfe3503e3);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0x044cfcfb);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0xf90c0082);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x08d5037f);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0xf710f7cc);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x069f0c59);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xfe16f173);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xfbaa0dcf);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0x0aa5f617);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xf0ad039b);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 10900000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffe);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0xfff90006);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x00210003);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0xffacffc8);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x008e00b6);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0xff63fe7c);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0x003a0275);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0x00dafcda);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0xfd510313);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0x0501fe40);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0xf8cbfefd);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x087604f0);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0xf80af6c2);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x05430cc8);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xff7af19a);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xfa940d4e);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0x0b3ff699);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xf0810365);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 11000000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x0001ffff);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0xfff8ffff);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x00210018);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0xffbaffa3);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x006000e1);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0xffc4fe68);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xffa0024b);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0x019afd66);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc990216);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0x0575ff99);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0xf8d4fd81);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x07d40640);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0xf932f5e6);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x03d20d0d);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0x00dff1de);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xf9860cbf);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0x0bd1f71e);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xf058032f);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 11100000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x00010000);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0xfff8fff8);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x001b0029);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0xffd1ff8a);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x002600f2);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x002cfe7c);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xff0f01f0);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0x023bfe20);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc1700fa);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0x05a200f7);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0xf927fc1c);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x06f40765);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0xfa82f53b);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x02510d27);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0x0243f23d);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xf8810c24);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0x0c5cf7a7);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xf03102fa);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 11200000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x00010002);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0xfffafff2);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x00110035);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0xfff0ff81);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0xffe700e7);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x008ffeb6);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe94016d);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0x02b0fefb);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0xfbd3ffd1);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0x05850249);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0xf9c1fadb);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x05de0858);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0xfbf2f4c4);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x00c70d17);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0x03a0f2b8);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xf7870b7c);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0x0cdff833);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xf00d02c4);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 11300000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0xfffdffee);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x00040038);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x0010ff88);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0xffac00c2);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x00e2ff10);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe3900cb);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0x02f1ffe9);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0xfbd3feaa);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0x05210381);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0xfa9cf9c8);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x04990912);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0xfd7af484);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0xff390cdb);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0x04f4f34d);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xf69a0ac9);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0x0d5af8c1);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xefec028e);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 11400000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x0000ffee);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0xfff60033);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x002fff9f);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0xff7b0087);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x011eff82);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe080018);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0x02f900d8);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc17fd96);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0x04790490);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0xfbadf8ed);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x032f098e);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0xff10f47d);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0xfdaf0c75);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0x063cf3fc);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xf5ba0a0b);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0x0dccf952);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xefcd0258);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 11500000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x0004fff1);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0xffea0026);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x0046ffc3);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0xff5a003c);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x013b0000);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe04ff63);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0x02c801b8);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc99fca6);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0x0397056a);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0xfcecf853);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x01ad09c9);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x00acf4ad);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0xfc2e0be7);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0x0773f4c2);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xf4e90943);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0x0e35f9e6);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xefb10221);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 11600000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x00000002);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x0007fff6);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0xffe20014);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x0054ffee);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0xff4effeb);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x0137007e);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe2efebb);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0x0260027a);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0xfd51fbe6);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0x02870605);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0xfe4af7fe);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x001d09c1);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x0243f515);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0xfabd0b32);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0x0897f59e);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xf4280871);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0x0e95fa7c);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xef9701eb);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 11700000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0xffff0001);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x0008fffd);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0xffdeffff);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x0056001d);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0xff57ff9c);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x011300f0);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe82fe2e);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0x01ca0310);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0xfe35fb62);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0x0155065a);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0xffbaf7f2);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0xfe8c0977);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x03cef5b2);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0xf9610a58);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0x09a5f68f);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xf3790797);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0x0eebfb14);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xef8001b5);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 11800000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0xffff0000);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x00080004);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0xffe0ffe9);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x004c0047);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0xff75ff58);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x00d1014a);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xfef9fdc8);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0x0111036f);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0xff36fb21);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0x00120665);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x012df82e);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0xfd0708ec);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x0542f682);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0xf81f095c);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0x0a9af792);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xf2db06b5);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0x0f38fbad);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xef6c017e);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 11900000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0xffffffff);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x0007000b);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0xffe7ffd8);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x00370068);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0xffa4ff28);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x00790184);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xff87fd91);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0x00430392);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x0044fb26);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xfece0626);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x0294f8b2);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0xfb990825);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x0698f77f);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0xf6fe0842);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0x0b73f8a7);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xf25105cd);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0x0f7bfc48);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xef5a0148);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 12000000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffe);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x00050010);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0xfff2ffcc);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x001b007b);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0xffdfff10);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x00140198);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0x0020fd8e);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xff710375);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x014dfb73);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xfd9a059f);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x03e0f978);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0xfa4e0726);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x07c8f8a7);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0xf600070c);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0x0c2ff9c9);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xf1db04de);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0x0fb4fce5);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xef4b0111);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 12100000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x00010012);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0xffffffc8);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0xfffb007e);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x001dff14);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0xffad0184);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0x00b7fdbe);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xfea9031b);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x0241fc01);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xfc8504d6);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x0504fa79);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0xf93005f6);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x08caf9f2);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0xf52b05c0);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0x0ccbfaf9);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xf17903eb);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0x0fe3fd83);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xef3f00db);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 12200000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0xfffe0011);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x000cffcc);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0xffdb0071);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x0058ff32);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0xff4f014a);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0x013cfe1f);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xfdfb028a);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x0311fcc9);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xfb9d03d6);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x05f4fbad);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0xf848049d);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x0999fb5b);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0xf4820461);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0x0d46fc32);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xf12d02f4);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0x1007fe21);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xef3600a4);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 12300000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffe);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0xfffa000e);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x0017ffd9);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0xffc10055);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x0088ff68);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0xff0400f0);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0x01a6fea7);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd7501cc);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x03b0fdc0);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xfaef02a8);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x06a7fd07);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0xf79d0326);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x0a31fcda);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0xf40702f3);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0x0d9ffd72);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xf0f601fa);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0x1021fec0);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xef2f006d);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 12400000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x0001ffff);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0xfff80007);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x001fffeb);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0xffaf002d);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x00a8ffb0);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0xfed3007e);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0x01e9ff4c);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd2000ee);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x0413fed8);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa82015c);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x0715fe7d);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0xf7340198);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x0a8dfe69);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0xf3bd017c);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0x0dd5feb8);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xf0d500fd);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0x1031ff60);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xef2b0037);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 12500000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x00010000);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0xfff70000);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x00220000);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0xffa90000);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x00b30000);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0xfec20000);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0x02000000);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd030000);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x04350000);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa5e0000);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x073b0000);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0xf7110000);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x0aac0000);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0xf3a40000);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0x0de70000);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xf0c90000);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0x10360000);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xef290000);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 12600000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x00010001);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0xfff8fff9);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x001f0015);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0xffafffd3);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x00a80050);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0xfed3ff82);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0x01e900b4);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd20ff12);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x04130128);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa82fea4);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x07150183);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0xf734fe68);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x0a8d0197);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0xf3bdfe84);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0x0dd50148);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xf0d5ff03);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0x103100a0);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xef2bffc9);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 12700000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x00000002);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0xfffafff2);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x00170027);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0xffc1ffab);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x00880098);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0xff04ff10);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0x01a60159);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd75fe34);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x03b00240);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xfaeffd58);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x06a702f9);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0xf79dfcda);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x0a310326);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0xf407fd0d);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0x0d9f028e);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xf0f6fe06);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0x10210140);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xef2fff93);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 12800000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0xfffeffef);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x000c0034);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0xffdbff8f);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x005800ce);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0xff4ffeb6);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0x013c01e1);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xfdfbfd76);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x03110337);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xfb9dfc2a);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x05f40453);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0xf848fb63);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x099904a5);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0xf482fb9f);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0x0d4603ce);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xf12dfd0c);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0x100701df);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xef36ff5c);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 12900000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x0001ffee);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0xffff0038);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0xfffbff82);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x001d00ec);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0xffadfe7c);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0x00b70242);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xfea9fce5);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x024103ff);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xfc85fb2a);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x05040587);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0xf930fa0a);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x08ca060e);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0xf52bfa40);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0x0ccb0507);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xf179fc15);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0x0fe3027d);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xef3fff25);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 13000000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x00000002);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x0005fff0);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0xfff20034);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x001bff85);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0xffdf00f0);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x0014fe68);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0x00200272);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xff71fc8b);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x014d048d);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xfd9afa61);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x03e00688);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0xfa4ef8da);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x07c80759);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0xf600f8f4);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0x0c2f0637);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xf1dbfb22);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0x0fb4031b);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xef4bfeef);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 13100000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0xffff0001);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x0007fff5);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0xffe70028);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x0037ff98);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0xffa400d8);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x0079fe7c);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xff87026f);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0x0043fc6e);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x004404da);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xfecef9da);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x0294074e);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0xfb99f7db);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x06980881);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0xf6fef7be);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0x0b730759);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xf251fa33);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0x0f7b03b8);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xef5afeb8);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 13200000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0xffff0000);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x0008fffc);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0xffe00017);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x004cffb9);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0xff7500a8);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x00d1feb6);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xfef90238);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0x0111fc91);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0xff3604df);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0x0012f99b);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x012d07d2);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0xfd07f714);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x0542097e);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0xf81ff6a4);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0x0a9a086e);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xf2dbf94b);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0x0f380453);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xef6cfe82);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 13300000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0xffffffff);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x00080003);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0xffde0001);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x0056ffe3);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0xff570064);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x0113ff10);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe8201d2);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0x01cafcf0);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0xfe35049e);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0x0155f9a6);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0xffba080e);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0xfe8cf689);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x03ce0a4e);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0xf961f5a8);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0x09a50971);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xf379f869);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0x0eeb04ec);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xef80fe4b);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 13400000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffe);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x0007000a);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0xffe2ffec);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x00540012);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0xff4e0015);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x0137ff82);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe2e0145);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0x0260fd86);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0xfd51041a);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0x0287f9fb);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0xfe4a0802);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x001df63f);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x02430aeb);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0xfabdf4ce);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0x08970a62);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xf428f78f);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0x0e950584);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xef97fe15);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 13500000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x0004000f);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0xffeaffda);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x0046003d);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0xff5affc4);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x013b0000);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe04009d);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0x02c8fe48);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc99035a);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0x0397fa96);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0xfcec07ad);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x01adf637);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x00ac0b53);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0xfc2ef419);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0x07730b3e);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xf4e9f6bd);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0x0e35061a);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xefb1fddf);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 13600000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x00000012);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0xfff6ffcd);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x002f0061);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0xff7bff79);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x011e007e);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe08ffe8);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0x02f9ff28);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc17026a);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0x0479fb70);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0xfbad0713);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x032ff672);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0xff100b83);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0xfdaff38b);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0x063c0c04);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xf5baf5f5);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0x0dcc06ae);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xefcdfda8);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 13700000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0xfffd0012);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x0004ffc8);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x00100078);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0xffacff3e);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x00e200f0);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe39ff35);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0x02f10017);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0xfbd30156);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0x0521fc7f);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0xfa9c0638);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x0499f6ee);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0xfd7a0b7c);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0xff39f325);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0x04f40cb3);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xf69af537);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0x0d5a073f);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xefecfd72);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 13800000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x0001fffe);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0xfffa000e);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x0011ffcb);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0xfff0007f);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0xffe7ff19);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x008f014a);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe94fe93);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0x02b00105);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0xfbd3002f);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0x0585fdb7);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0xf9c10525);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x05def7a8);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0xfbf20b3c);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x00c7f2e9);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0x03a00d48);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xf787f484);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0x0cdf07cd);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xf00dfd3c);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 13900000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x00010000);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0xfff80008);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x001bffd7);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0xffd10076);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x0026ff0e);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x002c0184);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xff0ffe10);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0x023b01e0);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc17ff06);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0x05a2ff09);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0xf92703e4);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x06f4f89b);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0xfa820ac5);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x0251f2d9);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0x02430dc3);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xf881f3dc);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0x0c5c0859);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xf031fd06);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 14000000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x00010001);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0xfff80001);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x0021ffe8);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0xffba005d);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x0060ff1f);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0xffc40198);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xffa0fdb5);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0x019a029a);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc99fdea);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0x05750067);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0xf8d4027f);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x07d4f9c0);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0xf9320a1a);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x03d2f2f3);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0x00df0e22);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xf986f341);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0x0bd108e2);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xf058fcd1);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 14100000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x00000002);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0xfff9fffa);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x0021fffd);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0xffac0038);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x008eff4a);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0xff630184);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0x003afd8b);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0x00da0326);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0xfd51fced);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0x050101c0);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0xf8cb0103);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x0876fb10);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0xf80a093e);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x0543f338);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xff7a0e66);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xfa94f2b2);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0x0b3f0967);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xf081fc9b);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 14200000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0xfffbfff3);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x001d0013);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0xffaa000b);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x00aaff89);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0xff13014a);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0x00cefd95);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0x000a037b);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0xfe35fc1d);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0x044c0305);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0xf90cff7e);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x08d5fc81);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0xf7100834);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x069ff3a7);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xfe160e8d);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xfbaaf231);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0x0aa509e9);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xf0adfc65);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 14300000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0xffffffef);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x00140025);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0xffb4ffdd);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x00b2ffd6);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0xfedb00f0);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0x0150fdd3);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xff380391);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0xff36fb85);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0x035e0426);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0xf994fdfe);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x08eefe0b);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0xf6490702);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x07e1f43e);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xfcb60e97);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xfcc6f1be);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0x0a040a67);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xf0dbfc30);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 14400000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x0002ffee);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x00070033);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0xffc9ffb4);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x00a40027);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0xfec3007e);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0x01b4fe3f);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xfe760369);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x0044fb2e);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0x02450518);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0xfa5ffc90);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x08c1ffa1);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0xf5bc05ae);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x0902f4fc);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xfb600e85);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xfde7f15a);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0x095d0ae2);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xf10cfbfb);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 14500000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0xffff0002);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x0005ffef);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0xfffa0038);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0xffe5ff95);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x00820074);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0xfecc0000);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0x01f0fed0);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xfdd20304);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x014dfb1d);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0x010e05ce);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0xfb64fb41);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x084e013b);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0xf569043e);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x0a00f5dd);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xfa150e55);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0xff0bf104);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0x08b00b59);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xf13ffbc6);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 14600000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0xffff0001);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x0008fff4);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0xffed0035);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x0005ff83);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x005000b4);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0xfef6ff82);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0x01ffff7a);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd580269);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x0241fb53);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xffca0640);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0xfc99fa1e);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x079a02cb);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0xf55502ba);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x0ad5f6e0);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xf8d90e0a);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0x0031f0bd);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0x07fd0bcb);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xf174fb91);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 14700000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0xffffffff);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x0009fffb);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0xffe4002a);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x0025ff82);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x001400e0);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0xff3cff10);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0x01e10030);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd1201a4);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x0311fbcd);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xfe88066a);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0xfdf1f92f);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x06aa0449);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0xf57e0128);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x0b7ef801);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xf7b00da2);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0x0156f086);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0x07450c39);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xf1acfb5c);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 14800000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffe);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x00080002);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0xffdf0019);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x003fff92);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0xffd600f1);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0xff96feb6);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0x019700e1);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd0500c2);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x03b0fc84);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xfd590649);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0xff5df87f);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x058505aa);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0xf5e4ff91);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x0bf9f93c);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xf69d0d20);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0x0279f05e);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0x06880ca3);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xf1e6fb28);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 14900000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x00060009);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0xffdf0004);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x0051ffb0);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0xff9d00e8);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0xfffcfe7c);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0x01280180);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd32ffd2);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x0413fd6e);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xfc4d05df);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x00d1f812);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x043506e4);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0xf685fdfb);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x0c43fa8d);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xf5a10c83);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0x0399f046);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0x05c70d08);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xf222faf3);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 15000000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x0003000f);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0xffe5ffef);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x0057ffd9);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0xff7000c4);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x0062fe68);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0x009e01ff);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd95fee6);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x0435fe7d);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xfb710530);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x023cf7ee);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x02c307ef);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0xf75efc70);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x0c5cfbef);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xf4c10bce);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0x04b3f03f);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0x05030d69);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xf261fabf);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 15100000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0xffff0012);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0xffefffdc);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x00510006);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0xff540089);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x00befe7c);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0x00060253);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xfe27fe0d);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x0413ffa2);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xfad10446);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x0390f812);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0x013b08c3);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0xf868faf6);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x0c43fd5f);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xf3fd0b02);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0x05c7f046);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0x043b0dc4);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xf2a1fa8b);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 15200000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x0001fffe);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0xfffc0012);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0xfffbffce);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x003f0033);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0xff4e003f);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x0106feb6);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xff6e0276);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xfeddfd56);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x03b000cc);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa740329);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x04bff87f);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0xffaa095d);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0xf99ef995);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x0bf9fed8);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xf3590a1f);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0x06d2f05e);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0x03700e1b);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xf2e4fa58);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 15300000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x0001ffff);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0xfff9000f);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x0009ffc8);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x00250059);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0xff5effee);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x0132ff10);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xfee30265);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0xffaafccf);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x031101eb);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa6001e8);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x05bdf92f);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0xfe1b09b6);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0xfafaf852);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x0b7e0055);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xf2d50929);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0x07d3f086);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0x02a30e6c);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xf329fa24);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 15400000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x00010001);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0xfff80009);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x0015ffca);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0x00050074);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0xff81ff9f);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x013dff82);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe710221);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0x007cfc80);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x024102ed);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa940090);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x0680fa1e);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0xfc9b09cd);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0xfc73f736);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x0ad501d0);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xf2740820);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0x08c9f0bd);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0x01d40eb9);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xf371f9f1);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 15500000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x00000002);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0xfff80002);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x001effd5);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0xffe5007f);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0xffb4ff5b);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x01280000);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe2401b0);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0x0146fc70);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x014d03c6);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xfb10ff32);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x0701fb41);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0xfb3709a1);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0xfe00f644);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x0a000345);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xf2350708);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0x09b2f104);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0x01050eff);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xf3baf9be);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 15600000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0xfff9fffb);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x0022ffe6);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0xffc9007a);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0xfff0ff29);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x00f2007e);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe01011b);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0x01f6fc9e);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0x00440467);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xfbccfdde);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x0738fc90);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0xf9f70934);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0xff99f582);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x090204b0);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xf21a05e1);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0x0a8df15a);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0x00340f41);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xf405f98b);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 15700000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0xfffcfff4);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x0020fffa);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0xffb40064);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x002fff11);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x00a400f0);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe0d006e);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0x0281fd09);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0xff3604c9);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xfcbffca2);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x0726fdfe);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0xf8e80888);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x0134f4f3);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x07e1060c);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xf22304af);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0x0b59f1be);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xff640f7d);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xf452f959);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 15800000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x0000fff0);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x001a0010);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0xffaa0041);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x0067ff13);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0x0043014a);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe46ffb9);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0x02dbfda8);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0xfe3504e5);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xfddcfb8d);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x06c9ff7e);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0xf81107a2);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x02c9f49a);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x069f0753);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xf2500373);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0x0c14f231);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xfe930fb3);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xf4a1f927);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 15900000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0xffff0002);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x0003ffee);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x000f0023);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0xffac0016);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x0093ff31);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0xffdc0184);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xfea6ff09);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0x02fdfe70);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0xfd5104ba);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0xff15faac);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x06270103);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0xf7780688);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x044df479);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x05430883);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xf2a00231);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0x0cbef2b2);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xfdc40fe3);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xf4f2f8f5);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+
+	case 16000000:
+		cx25840_write4(client, DIF_BPF_COEFF01, 0xffff0001);
+		cx25840_write4(client, DIF_BPF_COEFF23, 0x0006ffef);
+		cx25840_write4(client, DIF_BPF_COEFF45, 0x00020031);
+		cx25840_write4(client, DIF_BPF_COEFF67, 0xffbaffe8);
+		cx25840_write4(client, DIF_BPF_COEFF89, 0x00adff66);
+		cx25840_write4(client, DIF_BPF_COEFF1011, 0xff790198);
+		cx25840_write4(client, DIF_BPF_COEFF1213, 0xff26fe6e);
+		cx25840_write4(client, DIF_BPF_COEFF1415, 0x02e5ff55);
+		cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc99044a);
+		cx25840_write4(client, DIF_BPF_COEFF1819, 0x005bfa09);
+		cx25840_write4(client, DIF_BPF_COEFF2021, 0x0545027f);
+		cx25840_write4(client, DIF_BPF_COEFF2223, 0xf7230541);
+		cx25840_write4(client, DIF_BPF_COEFF2425, 0x05b8f490);
+		cx25840_write4(client, DIF_BPF_COEFF2627, 0x03d20997);
+		cx25840_write4(client, DIF_BPF_COEFF2829, 0xf31300eb);
+		cx25840_write4(client, DIF_BPF_COEFF3031, 0x0d55f341);
+		cx25840_write4(client, DIF_BPF_COEFF3233, 0xfcf6100e);
+		cx25840_write4(client, DIF_BPF_COEFF3435, 0xf544f8c3);
+		cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000);
+		break;
+	}
+}
+
+static void cx23888_std_setup(struct i2c_client *client)
+{
+	struct cx25840_state *state = to_state(i2c_get_clientdata(client));
+	v4l2_std_id std = state->std;
+	u32 ifHz;
+
+	cx25840_write4(client, 0x478, 0x6628021F);
+	cx25840_write4(client, 0x400, 0x0);
+	cx25840_write4(client, 0x4b4, 0x20524030);
+	cx25840_write4(client, 0x47c, 0x010a8263);
+
+	if (std & V4L2_STD_NTSC) {
+		v4l_dbg(1, cx25840_debug, client, "%s() Selecting NTSC",
+			__func__);
+
+		/* Horiz / vert timing */
+		cx25840_write4(client, 0x428, 0x1e1e601a);
+		cx25840_write4(client, 0x424, 0x5b2d007a);
+
+		/* DIF NTSC */
+		cx25840_write4(client, 0x304, 0x6503bc0c);
+		cx25840_write4(client, 0x308, 0xbd038c85);
+		cx25840_write4(client, 0x30c, 0x1db4640a);
+		cx25840_write4(client, 0x310, 0x00008800);
+		cx25840_write4(client, 0x314, 0x44400400);
+		cx25840_write4(client, 0x32c, 0x0c800800);
+		cx25840_write4(client, 0x330, 0x27000100);
+		cx25840_write4(client, 0x334, 0x1f296e1f);
+		cx25840_write4(client, 0x338, 0x009f50c1);
+		cx25840_write4(client, 0x340, 0x1befbf06);
+		cx25840_write4(client, 0x344, 0x000035e8);
+
+		/* DIF I/F */
+		ifHz = 5400000;
+
+	} else {
+		v4l_dbg(1, cx25840_debug, client, "%s() Selecting PAL-BG",
+			__func__);
+
+		/* Horiz / vert timing */
+		cx25840_write4(client, 0x428, 0x28244024);
+		cx25840_write4(client, 0x424, 0x5d2d0084);
+
+		/* DIF */
+		cx25840_write4(client, 0x304, 0x6503bc0c);
+		cx25840_write4(client, 0x308, 0xbd038c85);
+		cx25840_write4(client, 0x30c, 0x1db4640a);
+		cx25840_write4(client, 0x310, 0x00008800);
+		cx25840_write4(client, 0x314, 0x44400600);
+		cx25840_write4(client, 0x32c, 0x0c800800);
+		cx25840_write4(client, 0x330, 0x27000100);
+		cx25840_write4(client, 0x334, 0x213530ec);
+		cx25840_write4(client, 0x338, 0x00a65ba8);
+		cx25840_write4(client, 0x340, 0x1befbf06);
+		cx25840_write4(client, 0x344, 0x000035e8);
+
+		/* DIF I/F */
+		ifHz = 6000000;
+	}
+
+	cx23885_dif_setup(client, ifHz);
+
+	/* Explicitly ensure the inputs are reconfigured after
+	 * a standard change.
+	 */
+	set_input(client, state->vid_input, state->aud_input);
+}
+
+/* ----------------------------------------------------------------------- */
+
+static const struct v4l2_ctrl_ops cx25840_ctrl_ops = {
+	.s_ctrl = cx25840_s_ctrl,
+};
+
+static const struct v4l2_subdev_core_ops cx25840_core_ops = {
+	.log_status = cx25840_log_status,
+	.g_chip_ident = cx25840_g_chip_ident,
+	.g_ctrl = v4l2_subdev_g_ctrl,
+	.s_ctrl = v4l2_subdev_s_ctrl,
+	.s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
+	.try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
+	.g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
+	.queryctrl = v4l2_subdev_queryctrl,
+	.querymenu = v4l2_subdev_querymenu,
+	.s_std = cx25840_s_std,
+	.g_std = cx25840_g_std,
+	.reset = cx25840_reset,
+	.load_fw = cx25840_load_fw,
+	.s_io_pin_config = common_s_io_pin_config,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.g_register = cx25840_g_register,
+	.s_register = cx25840_s_register,
+#endif
+	.interrupt_service_routine = cx25840_irq_handler,
+};
+
+static const struct v4l2_subdev_tuner_ops cx25840_tuner_ops = {
+	.s_frequency = cx25840_s_frequency,
+	.s_radio = cx25840_s_radio,
+	.g_tuner = cx25840_g_tuner,
+	.s_tuner = cx25840_s_tuner,
+};
+
+static const struct v4l2_subdev_audio_ops cx25840_audio_ops = {
+	.s_clock_freq = cx25840_s_clock_freq,
+	.s_routing = cx25840_s_audio_routing,
+	.s_stream = cx25840_s_audio_stream,
+};
+
+static const struct v4l2_subdev_video_ops cx25840_video_ops = {
+	.s_routing = cx25840_s_video_routing,
+	.s_mbus_fmt = cx25840_s_mbus_fmt,
+	.s_stream = cx25840_s_stream,
+	.g_input_status = cx25840_g_input_status,
+};
+
+static const struct v4l2_subdev_vbi_ops cx25840_vbi_ops = {
+	.decode_vbi_line = cx25840_decode_vbi_line,
+	.s_raw_fmt = cx25840_s_raw_fmt,
+	.s_sliced_fmt = cx25840_s_sliced_fmt,
+	.g_sliced_fmt = cx25840_g_sliced_fmt,
+};
+
+static const struct v4l2_subdev_ops cx25840_ops = {
+	.core = &cx25840_core_ops,
+	.tuner = &cx25840_tuner_ops,
+	.audio = &cx25840_audio_ops,
+	.video = &cx25840_video_ops,
+	.vbi = &cx25840_vbi_ops,
+	.ir = &cx25840_ir_ops,
+};
+
+/* ----------------------------------------------------------------------- */
+
+static u32 get_cx2388x_ident(struct i2c_client *client)
+{
+	u32 ret;
+
+	/* Come out of digital power down */
+	cx25840_write(client, 0x000, 0);
+
+	/* Detecting whether the part is cx23885/7/8 is more
+	 * difficult than it needs to be. No ID register. Instead we
+	 * probe certain registers indicated in the datasheets to look
+	 * for specific defaults that differ between the silicon designs. */
+
+	/* It's either 885/7 if the IR Tx Clk Divider register exists */
+	if (cx25840_read4(client, 0x204) & 0xffff) {
+		/* CX23885 returns bogus repetitive byte values for the DIF,
+		 * which doesn't exist for it. (Ex. 8a8a8a8a or 31313131) */
+		ret = cx25840_read4(client, 0x300);
+		if (((ret & 0xffff0000) >> 16) == (ret & 0xffff)) {
+			/* No DIF */
+			ret = V4L2_IDENT_CX23885_AV;
+		} else {
+			/* CX23887 has a broken DIF, but the registers
+			 * appear valid (but unused), good enough to detect. */
+			ret = V4L2_IDENT_CX23887_AV;
+		}
+	} else if (cx25840_read4(client, 0x300) & 0x0fffffff) {
+		/* DIF PLL Freq Word reg exists; chip must be a CX23888 */
+		ret = V4L2_IDENT_CX23888_AV;
+	} else {
+		v4l_err(client, "Unable to detect h/w, assuming cx23887\n");
+		ret = V4L2_IDENT_CX23887_AV;
+	}
+
+	/* Back into digital power down */
+	cx25840_write(client, 0x000, 2);
+	return ret;
+}
+
+static int cx25840_probe(struct i2c_client *client,
+			 const struct i2c_device_id *did)
+{
+	struct cx25840_state *state;
+	struct v4l2_subdev *sd;
+	int default_volume;
+	u32 id = V4L2_IDENT_NONE;
+	u16 device_id;
+
+	/* Check if the adapter supports the needed features */
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		return -EIO;
+
+	v4l_dbg(1, cx25840_debug, client, "detecting cx25840 client on address 0x%x\n", client->addr << 1);
+
+	device_id = cx25840_read(client, 0x101) << 8;
+	device_id |= cx25840_read(client, 0x100);
+	v4l_dbg(1, cx25840_debug, client, "device_id = 0x%04x\n", device_id);
+
+	/* The high byte of the device ID should be
+	 * 0x83 for the cx2583x and 0x84 for the cx2584x */
+	if ((device_id & 0xff00) == 0x8300) {
+		id = V4L2_IDENT_CX25836 + ((device_id >> 4) & 0xf) - 6;
+	} else if ((device_id & 0xff00) == 0x8400) {
+		id = V4L2_IDENT_CX25840 + ((device_id >> 4) & 0xf);
+	} else if (device_id == 0x0000) {
+		id = get_cx2388x_ident(client);
+	} else if ((device_id & 0xfff0) == 0x5A30) {
+		/* The CX23100 (0x5A3C = 23100) doesn't have an A/V decoder */
+		id = V4L2_IDENT_CX2310X_AV;
+	} else if ((device_id & 0xff) == (device_id >> 8)) {
+		v4l_err(client,
+			"likely a confused/unresponsive cx2388[578] A/V decoder"
+			" found @ 0x%x (%s)\n",
+			client->addr << 1, client->adapter->name);
+		v4l_err(client, "A method to reset it from the cx25840 driver"
+			" software is not known at this time\n");
+		return -ENODEV;
+	} else {
+		v4l_dbg(1, cx25840_debug, client, "cx25840 not found\n");
+		return -ENODEV;
+	}
+
+	state = kzalloc(sizeof(struct cx25840_state), GFP_KERNEL);
+	if (state == NULL)
+		return -ENOMEM;
+
+	sd = &state->sd;
+	v4l2_i2c_subdev_init(sd, client, &cx25840_ops);
+
+	switch (id) {
+	case V4L2_IDENT_CX23885_AV:
+		v4l_info(client, "cx23885 A/V decoder found @ 0x%x (%s)\n",
+			 client->addr << 1, client->adapter->name);
+		break;
+	case V4L2_IDENT_CX23887_AV:
+		v4l_info(client, "cx23887 A/V decoder found @ 0x%x (%s)\n",
+			 client->addr << 1, client->adapter->name);
+		break;
+	case V4L2_IDENT_CX23888_AV:
+		v4l_info(client, "cx23888 A/V decoder found @ 0x%x (%s)\n",
+			 client->addr << 1, client->adapter->name);
+		break;
+	case V4L2_IDENT_CX2310X_AV:
+		v4l_info(client, "cx%d A/V decoder found @ 0x%x (%s)\n",
+			 device_id, client->addr << 1, client->adapter->name);
+		break;
+	case V4L2_IDENT_CX25840:
+	case V4L2_IDENT_CX25841:
+	case V4L2_IDENT_CX25842:
+	case V4L2_IDENT_CX25843:
+		/* Note: revision '(device_id & 0x0f) == 2' was never built. The
+		   marking skips from 0x1 == 22 to 0x3 == 23. */
+		v4l_info(client, "cx25%3x-2%x found @ 0x%x (%s)\n",
+			 (device_id & 0xfff0) >> 4,
+			 (device_id & 0x0f) < 3 ? (device_id & 0x0f) + 1
+						: (device_id & 0x0f),
+			 client->addr << 1, client->adapter->name);
+		break;
+	case V4L2_IDENT_CX25836:
+	case V4L2_IDENT_CX25837:
+	default:
+		v4l_info(client, "cx25%3x-%x found @ 0x%x (%s)\n",
+			 (device_id & 0xfff0) >> 4, device_id & 0x0f,
+			 client->addr << 1, client->adapter->name);
+		break;
+	}
+
+	state->c = client;
+	state->vid_input = CX25840_COMPOSITE7;
+	state->aud_input = CX25840_AUDIO8;
+	state->audclk_freq = 48000;
+	state->audmode = V4L2_TUNER_MODE_LANG1;
+	state->vbi_line_offset = 8;
+	state->id = id;
+	state->rev = device_id;
+	v4l2_ctrl_handler_init(&state->hdl, 9);
+	v4l2_ctrl_new_std(&state->hdl, &cx25840_ctrl_ops,
+			V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
+	v4l2_ctrl_new_std(&state->hdl, &cx25840_ctrl_ops,
+			V4L2_CID_CONTRAST, 0, 127, 1, 64);
+	v4l2_ctrl_new_std(&state->hdl, &cx25840_ctrl_ops,
+			V4L2_CID_SATURATION, 0, 127, 1, 64);
+	v4l2_ctrl_new_std(&state->hdl, &cx25840_ctrl_ops,
+			V4L2_CID_HUE, -128, 127, 1, 0);
+	if (!is_cx2583x(state)) {
+		default_volume = cx25840_read(client, 0x8d4);
+		/*
+		 * Enforce the legacy PVR-350/MSP3400 to PVR-150/CX25843 volume
+		 * scale mapping limits to avoid -ERANGE errors when
+		 * initializing the volume control
+		 */
+		if (default_volume > 228) {
+			/* Bottom out at -96 dB, v4l2 vol range 0x2e00-0x2fff */
+			default_volume = 228;
+			cx25840_write(client, 0x8d4, 228);
+		}
+		else if (default_volume < 20) {
+			/* Top out at + 8 dB, v4l2 vol range 0xfe00-0xffff */
+			default_volume = 20;
+			cx25840_write(client, 0x8d4, 20);
+		}
+		default_volume = (((228 - default_volume) >> 1) + 23) << 9;
+
+		state->volume = v4l2_ctrl_new_std(&state->hdl,
+			&cx25840_audio_ctrl_ops, V4L2_CID_AUDIO_VOLUME,
+			0, 65535, 65535 / 100, default_volume);
+		state->mute = v4l2_ctrl_new_std(&state->hdl,
+			&cx25840_audio_ctrl_ops, V4L2_CID_AUDIO_MUTE,
+			0, 1, 1, 0);
+		v4l2_ctrl_new_std(&state->hdl, &cx25840_audio_ctrl_ops,
+			V4L2_CID_AUDIO_BALANCE,
+			0, 65535, 65535 / 100, 32768);
+		v4l2_ctrl_new_std(&state->hdl, &cx25840_audio_ctrl_ops,
+			V4L2_CID_AUDIO_BASS,
+			0, 65535, 65535 / 100, 32768);
+		v4l2_ctrl_new_std(&state->hdl, &cx25840_audio_ctrl_ops,
+			V4L2_CID_AUDIO_TREBLE,
+			0, 65535, 65535 / 100, 32768);
+	}
+	sd->ctrl_handler = &state->hdl;
+	if (state->hdl.error) {
+		int err = state->hdl.error;
+
+		v4l2_ctrl_handler_free(&state->hdl);
+		kfree(state);
+		return err;
+	}
+	if (!is_cx2583x(state))
+		v4l2_ctrl_cluster(2, &state->volume);
+	v4l2_ctrl_handler_setup(&state->hdl);
+
+	if (client->dev.platform_data) {
+		struct cx25840_platform_data *pdata = client->dev.platform_data;
+
+		state->pvr150_workaround = pdata->pvr150_workaround;
+	}
+
+	cx25840_ir_probe(sd);
+	return 0;
+}
+
+static int cx25840_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct cx25840_state *state = to_state(sd);
+
+	cx25840_ir_remove(sd);
+	v4l2_device_unregister_subdev(sd);
+	v4l2_ctrl_handler_free(&state->hdl);
+	kfree(state);
+	return 0;
+}
+
+static const struct i2c_device_id cx25840_id[] = {
+	{ "cx25840", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, cx25840_id);
+
+static struct i2c_driver cx25840_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "cx25840",
+	},
+	.probe		= cx25840_probe,
+	.remove		= cx25840_remove,
+	.id_table	= cx25840_id,
+};
+
+module_i2c_driver(cx25840_driver);
diff --git a/drivers/media/i2c/cx25840/cx25840-core.h b/drivers/media/i2c/cx25840/cx25840-core.h
new file mode 100644
index 0000000..bd4ada2
--- /dev/null
+++ b/drivers/media/i2c/cx25840/cx25840-core.h
@@ -0,0 +1,137 @@
+/* cx25840 internal API header
+ *
+ * Copyright (C) 2003-2004 Chris Kennedy
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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 _CX25840_CORE_H_
+#define _CX25840_CORE_H_
+
+
+#include <linux/videodev2.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-ctrls.h>
+#include <linux/i2c.h>
+
+struct cx25840_ir_state;
+
+struct cx25840_state {
+	struct i2c_client *c;
+	struct v4l2_subdev sd;
+	struct v4l2_ctrl_handler hdl;
+	struct {
+		/* volume cluster */
+		struct v4l2_ctrl *volume;
+		struct v4l2_ctrl *mute;
+	};
+	int pvr150_workaround;
+	int radio;
+	v4l2_std_id std;
+	enum cx25840_video_input vid_input;
+	enum cx25840_audio_input aud_input;
+	u32 audclk_freq;
+	int audmode;
+	int vbi_line_offset;
+	u32 id;
+	u32 rev;
+	int is_initialized;
+	wait_queue_head_t fw_wait;    /* wake up when the fw load is finished */
+	struct work_struct fw_work;   /* work entry for fw load */
+	struct cx25840_ir_state *ir_state;
+};
+
+static inline struct cx25840_state *to_state(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct cx25840_state, sd);
+}
+
+static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
+{
+	return &container_of(ctrl->handler, struct cx25840_state, hdl)->sd;
+}
+
+static inline bool is_cx2583x(struct cx25840_state *state)
+{
+	return state->id == V4L2_IDENT_CX25836 ||
+	       state->id == V4L2_IDENT_CX25837;
+}
+
+static inline bool is_cx231xx(struct cx25840_state *state)
+{
+	return state->id == V4L2_IDENT_CX2310X_AV;
+}
+
+static inline bool is_cx2388x(struct cx25840_state *state)
+{
+	return state->id == V4L2_IDENT_CX23885_AV ||
+	       state->id == V4L2_IDENT_CX23887_AV ||
+	       state->id == V4L2_IDENT_CX23888_AV;
+}
+
+static inline bool is_cx23885(struct cx25840_state *state)
+{
+	return state->id == V4L2_IDENT_CX23885_AV;
+}
+
+static inline bool is_cx23887(struct cx25840_state *state)
+{
+	return state->id == V4L2_IDENT_CX23887_AV;
+}
+
+static inline bool is_cx23888(struct cx25840_state *state)
+{
+	return state->id == V4L2_IDENT_CX23888_AV;
+}
+
+/* ----------------------------------------------------------------------- */
+/* cx25850-core.c 							   */
+int cx25840_write(struct i2c_client *client, u16 addr, u8 value);
+int cx25840_write4(struct i2c_client *client, u16 addr, u32 value);
+u8 cx25840_read(struct i2c_client *client, u16 addr);
+u32 cx25840_read4(struct i2c_client *client, u16 addr);
+int cx25840_and_or(struct i2c_client *client, u16 addr, unsigned mask, u8 value);
+int cx25840_and_or4(struct i2c_client *client, u16 addr, u32 and_mask,
+		    u32 or_value);
+void cx25840_std_setup(struct i2c_client *client);
+
+/* ----------------------------------------------------------------------- */
+/* cx25850-firmware.c                                                      */
+int cx25840_loadfw(struct i2c_client *client);
+
+/* ----------------------------------------------------------------------- */
+/* cx25850-audio.c                                                         */
+void cx25840_audio_set_path(struct i2c_client *client);
+int cx25840_s_clock_freq(struct v4l2_subdev *sd, u32 freq);
+
+extern const struct v4l2_ctrl_ops cx25840_audio_ctrl_ops;
+
+/* ----------------------------------------------------------------------- */
+/* cx25850-vbi.c                                                           */
+int cx25840_s_raw_fmt(struct v4l2_subdev *sd, struct v4l2_vbi_format *fmt);
+int cx25840_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt);
+int cx25840_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt);
+int cx25840_decode_vbi_line(struct v4l2_subdev *sd, struct v4l2_decode_vbi_line *vbi);
+
+/* ----------------------------------------------------------------------- */
+/* cx25850-ir.c                                                            */
+extern const struct v4l2_subdev_ir_ops cx25840_ir_ops;
+int cx25840_ir_log_status(struct v4l2_subdev *sd);
+int cx25840_ir_irq_handler(struct v4l2_subdev *sd, u32 status, bool *handled);
+int cx25840_ir_probe(struct v4l2_subdev *sd);
+int cx25840_ir_remove(struct v4l2_subdev *sd);
+
+#endif
diff --git a/drivers/media/i2c/cx25840/cx25840-firmware.c b/drivers/media/i2c/cx25840/cx25840-firmware.c
new file mode 100644
index 0000000..b3169f9
--- /dev/null
+++ b/drivers/media/i2c/cx25840/cx25840-firmware.c
@@ -0,0 +1,175 @@
+/* cx25840 firmware functions
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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/module.h>
+#include <linux/i2c.h>
+#include <linux/firmware.h>
+#include <media/v4l2-common.h>
+#include <media/cx25840.h>
+
+#include "cx25840-core.h"
+
+/*
+ * Mike Isely <isely@pobox.com> - The FWSEND parameter controls the
+ * size of the firmware chunks sent down the I2C bus to the chip.
+ * Previously this had been set to 1024 but unfortunately some I2C
+ * implementations can't transfer data in such big gulps.
+ * Specifically, the pvrusb2 driver has a hard limit of around 60
+ * bytes, due to the encapsulation there of I2C traffic into USB
+ * messages.  So we have to significantly reduce this parameter.
+ */
+#define FWSEND 48
+
+#define FWDEV(x) &((x)->dev)
+
+static char *firmware = "";
+
+module_param(firmware, charp, 0444);
+
+MODULE_PARM_DESC(firmware, "Firmware image to load");
+
+static void start_fw_load(struct i2c_client *client)
+{
+	/* DL_ADDR_LB=0 DL_ADDR_HB=0 */
+	cx25840_write(client, 0x800, 0x00);
+	cx25840_write(client, 0x801, 0x00);
+	// DL_MAP=3 DL_AUTO_INC=0 DL_ENABLE=1
+	cx25840_write(client, 0x803, 0x0b);
+	/* AUTO_INC_DIS=1 */
+	cx25840_write(client, 0x000, 0x20);
+}
+
+static void end_fw_load(struct i2c_client *client)
+{
+	/* AUTO_INC_DIS=0 */
+	cx25840_write(client, 0x000, 0x00);
+	/* DL_ENABLE=0 */
+	cx25840_write(client, 0x803, 0x03);
+}
+
+#define CX2388x_FIRMWARE "v4l-cx23885-avcore-01.fw"
+#define CX231xx_FIRMWARE "v4l-cx231xx-avcore-01.fw"
+#define CX25840_FIRMWARE "v4l-cx25840.fw"
+
+static const char *get_fw_name(struct i2c_client *client)
+{
+	struct cx25840_state *state = to_state(i2c_get_clientdata(client));
+
+	if (firmware[0])
+		return firmware;
+	if (is_cx2388x(state))
+		return CX2388x_FIRMWARE;
+	if (is_cx231xx(state))
+		return CX231xx_FIRMWARE;
+	return CX25840_FIRMWARE;
+}
+
+static int check_fw_load(struct i2c_client *client, int size)
+{
+	/* DL_ADDR_HB DL_ADDR_LB */
+	int s = cx25840_read(client, 0x801) << 8;
+	s |= cx25840_read(client, 0x800);
+
+	if (size != s) {
+		v4l_err(client, "firmware %s load failed\n",
+				get_fw_name(client));
+		return -EINVAL;
+	}
+
+	v4l_info(client, "loaded %s firmware (%d bytes)\n",
+			get_fw_name(client), size);
+	return 0;
+}
+
+static int fw_write(struct i2c_client *client, const u8 *data, int size)
+{
+	if (i2c_master_send(client, data, size) < size) {
+		v4l_err(client, "firmware load i2c failure\n");
+		return -ENOSYS;
+	}
+
+	return 0;
+}
+
+int cx25840_loadfw(struct i2c_client *client)
+{
+	struct cx25840_state *state = to_state(i2c_get_clientdata(client));
+	const struct firmware *fw = NULL;
+	u8 buffer[FWSEND];
+	const u8 *ptr;
+	const char *fwname = get_fw_name(client);
+	int size, retval;
+	int MAX_BUF_SIZE = FWSEND;
+	u32 gpio_oe = 0, gpio_da = 0;
+
+	if (is_cx2388x(state)) {
+		/* Preserve the GPIO OE and output bits */
+		gpio_oe = cx25840_read(client, 0x160);
+		gpio_da = cx25840_read(client, 0x164);
+	}
+
+	if (is_cx231xx(state) && MAX_BUF_SIZE > 16) {
+		v4l_err(client, " Firmware download size changed to 16 bytes max length\n");
+		MAX_BUF_SIZE = 16;  /* cx231xx cannot accept more than 16 bytes at a time */
+	}
+
+	if (request_firmware(&fw, fwname, FWDEV(client)) != 0) {
+		v4l_err(client, "unable to open firmware %s\n", fwname);
+		return -EINVAL;
+	}
+
+	start_fw_load(client);
+
+	buffer[0] = 0x08;
+	buffer[1] = 0x02;
+
+	size = fw->size;
+	ptr = fw->data;
+	while (size > 0) {
+		int len = min(MAX_BUF_SIZE - 2, size);
+
+		memcpy(buffer + 2, ptr, len);
+
+		retval = fw_write(client, buffer, len + 2);
+
+		if (retval < 0) {
+			release_firmware(fw);
+			return retval;
+		}
+
+		size -= len;
+		ptr += len;
+	}
+
+	end_fw_load(client);
+
+	size = fw->size;
+	release_firmware(fw);
+
+	if (is_cx2388x(state)) {
+		/* Restore GPIO configuration after f/w load */
+		cx25840_write(client, 0x160, gpio_oe);
+		cx25840_write(client, 0x164, gpio_da);
+	}
+
+	return check_fw_load(client, size);
+}
+
+MODULE_FIRMWARE(CX2388x_FIRMWARE);
+MODULE_FIRMWARE(CX231xx_FIRMWARE);
+MODULE_FIRMWARE(CX25840_FIRMWARE);
+
diff --git a/drivers/media/i2c/cx25840/cx25840-ir.c b/drivers/media/i2c/cx25840/cx25840-ir.c
new file mode 100644
index 0000000..38ce76e
--- /dev/null
+++ b/drivers/media/i2c/cx25840/cx25840-ir.c
@@ -0,0 +1,1281 @@
+/*
+ *  Driver for the Conexant CX2584x Audio/Video decoder chip and related cores
+ *
+ *  Integrated Consumer Infrared Controller
+ *
+ *  Copyright (C) 2010  Andy Walls <awalls@md.metrocast.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 program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ *  02110-1301, USA.
+ */
+
+#include <linux/slab.h>
+#include <linux/kfifo.h>
+#include <linux/module.h>
+#include <media/cx25840.h>
+#include <media/rc-core.h>
+
+#include "cx25840-core.h"
+
+static unsigned int ir_debug;
+module_param(ir_debug, int, 0644);
+MODULE_PARM_DESC(ir_debug, "enable integrated IR debug messages");
+
+#define CX25840_IR_REG_BASE 	0x200
+
+#define CX25840_IR_CNTRL_REG	0x200
+#define CNTRL_WIN_3_3	0x00000000
+#define CNTRL_WIN_4_3	0x00000001
+#define CNTRL_WIN_3_4	0x00000002
+#define CNTRL_WIN_4_4	0x00000003
+#define CNTRL_WIN	0x00000003
+#define CNTRL_EDG_NONE	0x00000000
+#define CNTRL_EDG_FALL	0x00000004
+#define CNTRL_EDG_RISE	0x00000008
+#define CNTRL_EDG_BOTH	0x0000000C
+#define CNTRL_EDG	0x0000000C
+#define CNTRL_DMD	0x00000010
+#define CNTRL_MOD	0x00000020
+#define CNTRL_RFE	0x00000040
+#define CNTRL_TFE	0x00000080
+#define CNTRL_RXE	0x00000100
+#define CNTRL_TXE	0x00000200
+#define CNTRL_RIC	0x00000400
+#define CNTRL_TIC	0x00000800
+#define CNTRL_CPL	0x00001000
+#define CNTRL_LBM	0x00002000
+#define CNTRL_R		0x00004000
+
+#define CX25840_IR_TXCLK_REG	0x204
+#define TXCLK_TCD	0x0000FFFF
+
+#define CX25840_IR_RXCLK_REG	0x208
+#define RXCLK_RCD	0x0000FFFF
+
+#define CX25840_IR_CDUTY_REG	0x20C
+#define CDUTY_CDC	0x0000000F
+
+#define CX25840_IR_STATS_REG	0x210
+#define STATS_RTO	0x00000001
+#define STATS_ROR	0x00000002
+#define STATS_RBY	0x00000004
+#define STATS_TBY	0x00000008
+#define STATS_RSR	0x00000010
+#define STATS_TSR	0x00000020
+
+#define CX25840_IR_IRQEN_REG	0x214
+#define IRQEN_RTE	0x00000001
+#define IRQEN_ROE	0x00000002
+#define IRQEN_RSE	0x00000010
+#define IRQEN_TSE	0x00000020
+#define IRQEN_MSK	0x00000033
+
+#define CX25840_IR_FILTR_REG	0x218
+#define FILTR_LPF	0x0000FFFF
+
+#define CX25840_IR_FIFO_REG	0x23C
+#define FIFO_RXTX	0x0000FFFF
+#define FIFO_RXTX_LVL	0x00010000
+#define FIFO_RXTX_RTO	0x0001FFFF
+#define FIFO_RX_NDV	0x00020000
+#define FIFO_RX_DEPTH	8
+#define FIFO_TX_DEPTH	8
+
+#define CX25840_VIDCLK_FREQ	108000000 /* 108 MHz, BT.656 */
+#define CX25840_IR_REFCLK_FREQ	(CX25840_VIDCLK_FREQ / 2)
+
+/*
+ * We use this union internally for convenience, but callers to tx_write
+ * and rx_read will be expecting records of type struct ir_raw_event.
+ * Always ensure the size of this union is dictated by struct ir_raw_event.
+ */
+union cx25840_ir_fifo_rec {
+	u32 hw_fifo_data;
+	struct ir_raw_event ir_core_data;
+};
+
+#define CX25840_IR_RX_KFIFO_SIZE    (256 * sizeof(union cx25840_ir_fifo_rec))
+#define CX25840_IR_TX_KFIFO_SIZE    (256 * sizeof(union cx25840_ir_fifo_rec))
+
+struct cx25840_ir_state {
+	struct i2c_client *c;
+
+	struct v4l2_subdev_ir_parameters rx_params;
+	struct mutex rx_params_lock; /* protects Rx parameter settings cache */
+	atomic_t rxclk_divider;
+	atomic_t rx_invert;
+
+	struct kfifo rx_kfifo;
+	spinlock_t rx_kfifo_lock; /* protect Rx data kfifo */
+
+	struct v4l2_subdev_ir_parameters tx_params;
+	struct mutex tx_params_lock; /* protects Tx parameter settings cache */
+	atomic_t txclk_divider;
+};
+
+static inline struct cx25840_ir_state *to_ir_state(struct v4l2_subdev *sd)
+{
+	struct cx25840_state *state = to_state(sd);
+	return state ? state->ir_state : NULL;
+}
+
+
+/*
+ * Rx and Tx Clock Divider register computations
+ *
+ * Note the largest clock divider value of 0xffff corresponds to:
+ * 	(0xffff + 1) * 1000 / 108/2 MHz = 1,213,629.629... ns
+ * which fits in 21 bits, so we'll use unsigned int for time arguments.
+ */
+static inline u16 count_to_clock_divider(unsigned int d)
+{
+	if (d > RXCLK_RCD + 1)
+		d = RXCLK_RCD;
+	else if (d < 2)
+		d = 1;
+	else
+		d--;
+	return (u16) d;
+}
+
+static inline u16 ns_to_clock_divider(unsigned int ns)
+{
+	return count_to_clock_divider(
+		DIV_ROUND_CLOSEST(CX25840_IR_REFCLK_FREQ / 1000000 * ns, 1000));
+}
+
+static inline unsigned int clock_divider_to_ns(unsigned int divider)
+{
+	/* Period of the Rx or Tx clock in ns */
+	return DIV_ROUND_CLOSEST((divider + 1) * 1000,
+				 CX25840_IR_REFCLK_FREQ / 1000000);
+}
+
+static inline u16 carrier_freq_to_clock_divider(unsigned int freq)
+{
+	return count_to_clock_divider(
+			  DIV_ROUND_CLOSEST(CX25840_IR_REFCLK_FREQ, freq * 16));
+}
+
+static inline unsigned int clock_divider_to_carrier_freq(unsigned int divider)
+{
+	return DIV_ROUND_CLOSEST(CX25840_IR_REFCLK_FREQ, (divider + 1) * 16);
+}
+
+static inline u16 freq_to_clock_divider(unsigned int freq,
+					unsigned int rollovers)
+{
+	return count_to_clock_divider(
+		   DIV_ROUND_CLOSEST(CX25840_IR_REFCLK_FREQ, freq * rollovers));
+}
+
+static inline unsigned int clock_divider_to_freq(unsigned int divider,
+						 unsigned int rollovers)
+{
+	return DIV_ROUND_CLOSEST(CX25840_IR_REFCLK_FREQ,
+				 (divider + 1) * rollovers);
+}
+
+/*
+ * Low Pass Filter register calculations
+ *
+ * Note the largest count value of 0xffff corresponds to:
+ * 	0xffff * 1000 / 108/2 MHz = 1,213,611.11... ns
+ * which fits in 21 bits, so we'll use unsigned int for time arguments.
+ */
+static inline u16 count_to_lpf_count(unsigned int d)
+{
+	if (d > FILTR_LPF)
+		d = FILTR_LPF;
+	else if (d < 4)
+		d = 0;
+	return (u16) d;
+}
+
+static inline u16 ns_to_lpf_count(unsigned int ns)
+{
+	return count_to_lpf_count(
+		DIV_ROUND_CLOSEST(CX25840_IR_REFCLK_FREQ / 1000000 * ns, 1000));
+}
+
+static inline unsigned int lpf_count_to_ns(unsigned int count)
+{
+	/* Duration of the Low Pass Filter rejection window in ns */
+	return DIV_ROUND_CLOSEST(count * 1000,
+				 CX25840_IR_REFCLK_FREQ / 1000000);
+}
+
+static inline unsigned int lpf_count_to_us(unsigned int count)
+{
+	/* Duration of the Low Pass Filter rejection window in us */
+	return DIV_ROUND_CLOSEST(count, CX25840_IR_REFCLK_FREQ / 1000000);
+}
+
+/*
+ * FIFO register pulse width count compuations
+ */
+static u32 clock_divider_to_resolution(u16 divider)
+{
+	/*
+	 * Resolution is the duration of 1 tick of the readable portion of
+	 * of the pulse width counter as read from the FIFO.  The two lsb's are
+	 * not readable, hence the << 2.  This function returns ns.
+	 */
+	return DIV_ROUND_CLOSEST((1 << 2)  * ((u32) divider + 1) * 1000,
+				 CX25840_IR_REFCLK_FREQ / 1000000);
+}
+
+static u64 pulse_width_count_to_ns(u16 count, u16 divider)
+{
+	u64 n;
+	u32 rem;
+
+	/*
+	 * The 2 lsb's of the pulse width timer count are not readable, hence
+	 * the (count << 2) | 0x3
+	 */
+	n = (((u64) count << 2) | 0x3) * (divider + 1) * 1000; /* millicycles */
+	rem = do_div(n, CX25840_IR_REFCLK_FREQ / 1000000);     /* / MHz => ns */
+	if (rem >= CX25840_IR_REFCLK_FREQ / 1000000 / 2)
+		n++;
+	return n;
+}
+
+#if 0
+/* Keep as we will need this for Transmit functionality */
+static u16 ns_to_pulse_width_count(u32 ns, u16 divider)
+{
+	u64 n;
+	u32 d;
+	u32 rem;
+
+	/*
+	 * The 2 lsb's of the pulse width timer count are not accessible, hence
+	 * the (1 << 2)
+	 */
+	n = ((u64) ns) * CX25840_IR_REFCLK_FREQ / 1000000; /* millicycles */
+	d = (1 << 2) * ((u32) divider + 1) * 1000; /* millicycles/count */
+	rem = do_div(n, d);
+	if (rem >= d / 2)
+		n++;
+
+	if (n > FIFO_RXTX)
+		n = FIFO_RXTX;
+	else if (n == 0)
+		n = 1;
+	return (u16) n;
+}
+
+#endif
+static unsigned int pulse_width_count_to_us(u16 count, u16 divider)
+{
+	u64 n;
+	u32 rem;
+
+	/*
+	 * The 2 lsb's of the pulse width timer count are not readable, hence
+	 * the (count << 2) | 0x3
+	 */
+	n = (((u64) count << 2) | 0x3) * (divider + 1);    /* cycles      */
+	rem = do_div(n, CX25840_IR_REFCLK_FREQ / 1000000); /* / MHz => us */
+	if (rem >= CX25840_IR_REFCLK_FREQ / 1000000 / 2)
+		n++;
+	return (unsigned int) n;
+}
+
+/*
+ * Pulse Clocks computations: Combined Pulse Width Count & Rx Clock Counts
+ *
+ * The total pulse clock count is an 18 bit pulse width timer count as the most
+ * significant part and (up to) 16 bit clock divider count as a modulus.
+ * When the Rx clock divider ticks down to 0, it increments the 18 bit pulse
+ * width timer count's least significant bit.
+ */
+static u64 ns_to_pulse_clocks(u32 ns)
+{
+	u64 clocks;
+	u32 rem;
+	clocks = CX25840_IR_REFCLK_FREQ / 1000000 * (u64) ns; /* millicycles  */
+	rem = do_div(clocks, 1000);                         /* /1000 = cycles */
+	if (rem >= 1000 / 2)
+		clocks++;
+	return clocks;
+}
+
+static u16 pulse_clocks_to_clock_divider(u64 count)
+{
+	do_div(count, (FIFO_RXTX << 2) | 0x3);
+
+	/* net result needs to be rounded down and decremented by 1 */
+	if (count > RXCLK_RCD + 1)
+		count = RXCLK_RCD;
+	else if (count < 2)
+		count = 1;
+	else
+		count--;
+	return (u16) count;
+}
+
+/*
+ * IR Control Register helpers
+ */
+enum tx_fifo_watermark {
+	TX_FIFO_HALF_EMPTY = 0,
+	TX_FIFO_EMPTY      = CNTRL_TIC,
+};
+
+enum rx_fifo_watermark {
+	RX_FIFO_HALF_FULL = 0,
+	RX_FIFO_NOT_EMPTY = CNTRL_RIC,
+};
+
+static inline void control_tx_irq_watermark(struct i2c_client *c,
+					    enum tx_fifo_watermark level)
+{
+	cx25840_and_or4(c, CX25840_IR_CNTRL_REG, ~CNTRL_TIC, level);
+}
+
+static inline void control_rx_irq_watermark(struct i2c_client *c,
+					    enum rx_fifo_watermark level)
+{
+	cx25840_and_or4(c, CX25840_IR_CNTRL_REG, ~CNTRL_RIC, level);
+}
+
+static inline void control_tx_enable(struct i2c_client *c, bool enable)
+{
+	cx25840_and_or4(c, CX25840_IR_CNTRL_REG, ~(CNTRL_TXE | CNTRL_TFE),
+			enable ? (CNTRL_TXE | CNTRL_TFE) : 0);
+}
+
+static inline void control_rx_enable(struct i2c_client *c, bool enable)
+{
+	cx25840_and_or4(c, CX25840_IR_CNTRL_REG, ~(CNTRL_RXE | CNTRL_RFE),
+			enable ? (CNTRL_RXE | CNTRL_RFE) : 0);
+}
+
+static inline void control_tx_modulation_enable(struct i2c_client *c,
+						bool enable)
+{
+	cx25840_and_or4(c, CX25840_IR_CNTRL_REG, ~CNTRL_MOD,
+			enable ? CNTRL_MOD : 0);
+}
+
+static inline void control_rx_demodulation_enable(struct i2c_client *c,
+						  bool enable)
+{
+	cx25840_and_or4(c, CX25840_IR_CNTRL_REG, ~CNTRL_DMD,
+			enable ? CNTRL_DMD : 0);
+}
+
+static inline void control_rx_s_edge_detection(struct i2c_client *c,
+					       u32 edge_types)
+{
+	cx25840_and_or4(c, CX25840_IR_CNTRL_REG, ~CNTRL_EDG_BOTH,
+			edge_types & CNTRL_EDG_BOTH);
+}
+
+static void control_rx_s_carrier_window(struct i2c_client *c,
+					unsigned int carrier,
+					unsigned int *carrier_range_low,
+					unsigned int *carrier_range_high)
+{
+	u32 v;
+	unsigned int c16 = carrier * 16;
+
+	if (*carrier_range_low < DIV_ROUND_CLOSEST(c16, 16 + 3)) {
+		v = CNTRL_WIN_3_4;
+		*carrier_range_low = DIV_ROUND_CLOSEST(c16, 16 + 4);
+	} else {
+		v = CNTRL_WIN_3_3;
+		*carrier_range_low = DIV_ROUND_CLOSEST(c16, 16 + 3);
+	}
+
+	if (*carrier_range_high > DIV_ROUND_CLOSEST(c16, 16 - 3)) {
+		v |= CNTRL_WIN_4_3;
+		*carrier_range_high = DIV_ROUND_CLOSEST(c16, 16 - 4);
+	} else {
+		v |= CNTRL_WIN_3_3;
+		*carrier_range_high = DIV_ROUND_CLOSEST(c16, 16 - 3);
+	}
+	cx25840_and_or4(c, CX25840_IR_CNTRL_REG, ~CNTRL_WIN, v);
+}
+
+static inline void control_tx_polarity_invert(struct i2c_client *c,
+					      bool invert)
+{
+	cx25840_and_or4(c, CX25840_IR_CNTRL_REG, ~CNTRL_CPL,
+			invert ? CNTRL_CPL : 0);
+}
+
+/*
+ * IR Rx & Tx Clock Register helpers
+ */
+static unsigned int txclk_tx_s_carrier(struct i2c_client *c,
+				       unsigned int freq,
+				       u16 *divider)
+{
+	*divider = carrier_freq_to_clock_divider(freq);
+	cx25840_write4(c, CX25840_IR_TXCLK_REG, *divider);
+	return clock_divider_to_carrier_freq(*divider);
+}
+
+static unsigned int rxclk_rx_s_carrier(struct i2c_client *c,
+				       unsigned int freq,
+				       u16 *divider)
+{
+	*divider = carrier_freq_to_clock_divider(freq);
+	cx25840_write4(c, CX25840_IR_RXCLK_REG, *divider);
+	return clock_divider_to_carrier_freq(*divider);
+}
+
+static u32 txclk_tx_s_max_pulse_width(struct i2c_client *c, u32 ns,
+				      u16 *divider)
+{
+	u64 pulse_clocks;
+
+	if (ns > IR_MAX_DURATION)
+		ns = IR_MAX_DURATION;
+	pulse_clocks = ns_to_pulse_clocks(ns);
+	*divider = pulse_clocks_to_clock_divider(pulse_clocks);
+	cx25840_write4(c, CX25840_IR_TXCLK_REG, *divider);
+	return (u32) pulse_width_count_to_ns(FIFO_RXTX, *divider);
+}
+
+static u32 rxclk_rx_s_max_pulse_width(struct i2c_client *c, u32 ns,
+				      u16 *divider)
+{
+	u64 pulse_clocks;
+
+	if (ns > IR_MAX_DURATION)
+		ns = IR_MAX_DURATION;
+	pulse_clocks = ns_to_pulse_clocks(ns);
+	*divider = pulse_clocks_to_clock_divider(pulse_clocks);
+	cx25840_write4(c, CX25840_IR_RXCLK_REG, *divider);
+	return (u32) pulse_width_count_to_ns(FIFO_RXTX, *divider);
+}
+
+/*
+ * IR Tx Carrier Duty Cycle register helpers
+ */
+static unsigned int cduty_tx_s_duty_cycle(struct i2c_client *c,
+					  unsigned int duty_cycle)
+{
+	u32 n;
+	n = DIV_ROUND_CLOSEST(duty_cycle * 100, 625); /* 16ths of 100% */
+	if (n != 0)
+		n--;
+	if (n > 15)
+		n = 15;
+	cx25840_write4(c, CX25840_IR_CDUTY_REG, n);
+	return DIV_ROUND_CLOSEST((n + 1) * 100, 16);
+}
+
+/*
+ * IR Filter Register helpers
+ */
+static u32 filter_rx_s_min_width(struct i2c_client *c, u32 min_width_ns)
+{
+	u32 count = ns_to_lpf_count(min_width_ns);
+	cx25840_write4(c, CX25840_IR_FILTR_REG, count);
+	return lpf_count_to_ns(count);
+}
+
+/*
+ * IR IRQ Enable Register helpers
+ */
+static inline void irqenable_rx(struct v4l2_subdev *sd, u32 mask)
+{
+	struct cx25840_state *state = to_state(sd);
+
+	if (is_cx23885(state) || is_cx23887(state))
+		mask ^= IRQEN_MSK;
+	mask &= (IRQEN_RTE | IRQEN_ROE | IRQEN_RSE);
+	cx25840_and_or4(state->c, CX25840_IR_IRQEN_REG,
+			~(IRQEN_RTE | IRQEN_ROE | IRQEN_RSE), mask);
+}
+
+static inline void irqenable_tx(struct v4l2_subdev *sd, u32 mask)
+{
+	struct cx25840_state *state = to_state(sd);
+
+	if (is_cx23885(state) || is_cx23887(state))
+		mask ^= IRQEN_MSK;
+	mask &= IRQEN_TSE;
+	cx25840_and_or4(state->c, CX25840_IR_IRQEN_REG, ~IRQEN_TSE, mask);
+}
+
+/*
+ * V4L2 Subdevice IR Ops
+ */
+int cx25840_ir_irq_handler(struct v4l2_subdev *sd, u32 status, bool *handled)
+{
+	struct cx25840_state *state = to_state(sd);
+	struct cx25840_ir_state *ir_state = to_ir_state(sd);
+	struct i2c_client *c = NULL;
+	unsigned long flags;
+
+	union cx25840_ir_fifo_rec rx_data[FIFO_RX_DEPTH];
+	unsigned int i, j, k;
+	u32 events, v;
+	int tsr, rsr, rto, ror, tse, rse, rte, roe, kror;
+	u32 cntrl, irqen, stats;
+
+	*handled = false;
+	if (ir_state == NULL)
+		return -ENODEV;
+
+	c = ir_state->c;
+
+	/* Only support the IR controller for the CX2388[57] AV Core for now */
+	if (!(is_cx23885(state) || is_cx23887(state)))
+		return -ENODEV;
+
+	cntrl = cx25840_read4(c, CX25840_IR_CNTRL_REG);
+	irqen = cx25840_read4(c, CX25840_IR_IRQEN_REG);
+	if (is_cx23885(state) || is_cx23887(state))
+		irqen ^= IRQEN_MSK;
+	stats = cx25840_read4(c, CX25840_IR_STATS_REG);
+
+	tsr = stats & STATS_TSR; /* Tx FIFO Service Request */
+	rsr = stats & STATS_RSR; /* Rx FIFO Service Request */
+	rto = stats & STATS_RTO; /* Rx Pulse Width Timer Time Out */
+	ror = stats & STATS_ROR; /* Rx FIFO Over Run */
+
+	tse = irqen & IRQEN_TSE; /* Tx FIFO Service Request IRQ Enable */
+	rse = irqen & IRQEN_RSE; /* Rx FIFO Service Reuqest IRQ Enable */
+	rte = irqen & IRQEN_RTE; /* Rx Pulse Width Timer Time Out IRQ Enable */
+	roe = irqen & IRQEN_ROE; /* Rx FIFO Over Run IRQ Enable */
+
+	v4l2_dbg(2, ir_debug, sd, "IR IRQ Status:  %s %s %s %s %s %s\n",
+		 tsr ? "tsr" : "   ", rsr ? "rsr" : "   ",
+		 rto ? "rto" : "   ", ror ? "ror" : "   ",
+		 stats & STATS_TBY ? "tby" : "   ",
+		 stats & STATS_RBY ? "rby" : "   ");
+
+	v4l2_dbg(2, ir_debug, sd, "IR IRQ Enables: %s %s %s %s\n",
+		 tse ? "tse" : "   ", rse ? "rse" : "   ",
+		 rte ? "rte" : "   ", roe ? "roe" : "   ");
+
+	/*
+	 * Transmitter interrupt service
+	 */
+	if (tse && tsr) {
+		/*
+		 * TODO:
+		 * Check the watermark threshold setting
+		 * Pull FIFO_TX_DEPTH or FIFO_TX_DEPTH/2 entries from tx_kfifo
+		 * Push the data to the hardware FIFO.
+		 * If there was nothing more to send in the tx_kfifo, disable
+		 *	the TSR IRQ and notify the v4l2_device.
+		 * If there was something in the tx_kfifo, check the tx_kfifo
+		 *      level and notify the v4l2_device, if it is low.
+		 */
+		/* For now, inhibit TSR interrupt until Tx is implemented */
+		irqenable_tx(sd, 0);
+		events = V4L2_SUBDEV_IR_TX_FIFO_SERVICE_REQ;
+		v4l2_subdev_notify(sd, V4L2_SUBDEV_IR_TX_NOTIFY, &events);
+		*handled = true;
+	}
+
+	/*
+	 * Receiver interrupt service
+	 */
+	kror = 0;
+	if ((rse && rsr) || (rte && rto)) {
+		/*
+		 * Receive data on RSR to clear the STATS_RSR.
+		 * Receive data on RTO, since we may not have yet hit the RSR
+		 * watermark when we receive the RTO.
+		 */
+		for (i = 0, v = FIFO_RX_NDV;
+		     (v & FIFO_RX_NDV) && !kror; i = 0) {
+			for (j = 0;
+			     (v & FIFO_RX_NDV) && j < FIFO_RX_DEPTH; j++) {
+				v = cx25840_read4(c, CX25840_IR_FIFO_REG);
+				rx_data[i].hw_fifo_data = v & ~FIFO_RX_NDV;
+				i++;
+			}
+			if (i == 0)
+				break;
+			j = i * sizeof(union cx25840_ir_fifo_rec);
+			k = kfifo_in_locked(&ir_state->rx_kfifo,
+					    (unsigned char *) rx_data, j,
+					    &ir_state->rx_kfifo_lock);
+			if (k != j)
+				kror++; /* rx_kfifo over run */
+		}
+		*handled = true;
+	}
+
+	events = 0;
+	v = 0;
+	if (kror) {
+		events |= V4L2_SUBDEV_IR_RX_SW_FIFO_OVERRUN;
+		v4l2_err(sd, "IR receiver software FIFO overrun\n");
+	}
+	if (roe && ror) {
+		/*
+		 * The RX FIFO Enable (CNTRL_RFE) must be toggled to clear
+		 * the Rx FIFO Over Run status (STATS_ROR)
+		 */
+		v |= CNTRL_RFE;
+		events |= V4L2_SUBDEV_IR_RX_HW_FIFO_OVERRUN;
+		v4l2_err(sd, "IR receiver hardware FIFO overrun\n");
+	}
+	if (rte && rto) {
+		/*
+		 * The IR Receiver Enable (CNTRL_RXE) must be toggled to clear
+		 * the Rx Pulse Width Timer Time Out (STATS_RTO)
+		 */
+		v |= CNTRL_RXE;
+		events |= V4L2_SUBDEV_IR_RX_END_OF_RX_DETECTED;
+	}
+	if (v) {
+		/* Clear STATS_ROR & STATS_RTO as needed by reseting hardware */
+		cx25840_write4(c, CX25840_IR_CNTRL_REG, cntrl & ~v);
+		cx25840_write4(c, CX25840_IR_CNTRL_REG, cntrl);
+		*handled = true;
+	}
+	spin_lock_irqsave(&ir_state->rx_kfifo_lock, flags);
+	if (kfifo_len(&ir_state->rx_kfifo) >= CX25840_IR_RX_KFIFO_SIZE / 2)
+		events |= V4L2_SUBDEV_IR_RX_FIFO_SERVICE_REQ;
+	spin_unlock_irqrestore(&ir_state->rx_kfifo_lock, flags);
+
+	if (events)
+		v4l2_subdev_notify(sd, V4L2_SUBDEV_IR_RX_NOTIFY, &events);
+	return 0;
+}
+
+/* Receiver */
+static int cx25840_ir_rx_read(struct v4l2_subdev *sd, u8 *buf, size_t count,
+			      ssize_t *num)
+{
+	struct cx25840_ir_state *ir_state = to_ir_state(sd);
+	bool invert;
+	u16 divider;
+	unsigned int i, n;
+	union cx25840_ir_fifo_rec *p;
+	unsigned u, v, w;
+
+	if (ir_state == NULL)
+		return -ENODEV;
+
+	invert = (bool) atomic_read(&ir_state->rx_invert);
+	divider = (u16) atomic_read(&ir_state->rxclk_divider);
+
+	n = count / sizeof(union cx25840_ir_fifo_rec)
+		* sizeof(union cx25840_ir_fifo_rec);
+	if (n == 0) {
+		*num = 0;
+		return 0;
+	}
+
+	n = kfifo_out_locked(&ir_state->rx_kfifo, buf, n,
+			     &ir_state->rx_kfifo_lock);
+
+	n /= sizeof(union cx25840_ir_fifo_rec);
+	*num = n * sizeof(union cx25840_ir_fifo_rec);
+
+	for (p = (union cx25840_ir_fifo_rec *) buf, i = 0; i < n; p++, i++) {
+
+		if ((p->hw_fifo_data & FIFO_RXTX_RTO) == FIFO_RXTX_RTO) {
+			/* Assume RTO was because of no IR light input */
+			u = 0;
+			w = 1;
+		} else {
+			u = (p->hw_fifo_data & FIFO_RXTX_LVL) ? 1 : 0;
+			if (invert)
+				u = u ? 0 : 1;
+			w = 0;
+		}
+
+		v = (unsigned) pulse_width_count_to_ns(
+				  (u16) (p->hw_fifo_data & FIFO_RXTX), divider);
+		if (v > IR_MAX_DURATION)
+			v = IR_MAX_DURATION;
+
+		init_ir_raw_event(&p->ir_core_data);
+		p->ir_core_data.pulse = u;
+		p->ir_core_data.duration = v;
+		p->ir_core_data.timeout = w;
+
+		v4l2_dbg(2, ir_debug, sd, "rx read: %10u ns  %s  %s\n",
+			 v, u ? "mark" : "space", w ? "(timed out)" : "");
+		if (w)
+			v4l2_dbg(2, ir_debug, sd, "rx read: end of rx\n");
+	}
+	return 0;
+}
+
+static int cx25840_ir_rx_g_parameters(struct v4l2_subdev *sd,
+				      struct v4l2_subdev_ir_parameters *p)
+{
+	struct cx25840_ir_state *ir_state = to_ir_state(sd);
+
+	if (ir_state == NULL)
+		return -ENODEV;
+
+	mutex_lock(&ir_state->rx_params_lock);
+	memcpy(p, &ir_state->rx_params,
+				      sizeof(struct v4l2_subdev_ir_parameters));
+	mutex_unlock(&ir_state->rx_params_lock);
+	return 0;
+}
+
+static int cx25840_ir_rx_shutdown(struct v4l2_subdev *sd)
+{
+	struct cx25840_ir_state *ir_state = to_ir_state(sd);
+	struct i2c_client *c;
+
+	if (ir_state == NULL)
+		return -ENODEV;
+
+	c = ir_state->c;
+	mutex_lock(&ir_state->rx_params_lock);
+
+	/* Disable or slow down all IR Rx circuits and counters */
+	irqenable_rx(sd, 0);
+	control_rx_enable(c, false);
+	control_rx_demodulation_enable(c, false);
+	control_rx_s_edge_detection(c, CNTRL_EDG_NONE);
+	filter_rx_s_min_width(c, 0);
+	cx25840_write4(c, CX25840_IR_RXCLK_REG, RXCLK_RCD);
+
+	ir_state->rx_params.shutdown = true;
+
+	mutex_unlock(&ir_state->rx_params_lock);
+	return 0;
+}
+
+static int cx25840_ir_rx_s_parameters(struct v4l2_subdev *sd,
+				      struct v4l2_subdev_ir_parameters *p)
+{
+	struct cx25840_ir_state *ir_state = to_ir_state(sd);
+	struct i2c_client *c;
+	struct v4l2_subdev_ir_parameters *o;
+	u16 rxclk_divider;
+
+	if (ir_state == NULL)
+		return -ENODEV;
+
+	if (p->shutdown)
+		return cx25840_ir_rx_shutdown(sd);
+
+	if (p->mode != V4L2_SUBDEV_IR_MODE_PULSE_WIDTH)
+		return -ENOSYS;
+
+	c = ir_state->c;
+	o = &ir_state->rx_params;
+
+	mutex_lock(&ir_state->rx_params_lock);
+
+	o->shutdown = p->shutdown;
+
+	p->mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH;
+	o->mode = p->mode;
+
+	p->bytes_per_data_element = sizeof(union cx25840_ir_fifo_rec);
+	o->bytes_per_data_element = p->bytes_per_data_element;
+
+	/* Before we tweak the hardware, we have to disable the receiver */
+	irqenable_rx(sd, 0);
+	control_rx_enable(c, false);
+
+	control_rx_demodulation_enable(c, p->modulation);
+	o->modulation = p->modulation;
+
+	if (p->modulation) {
+		p->carrier_freq = rxclk_rx_s_carrier(c, p->carrier_freq,
+						     &rxclk_divider);
+
+		o->carrier_freq = p->carrier_freq;
+
+		p->duty_cycle = 50;
+		o->duty_cycle = p->duty_cycle;
+
+		control_rx_s_carrier_window(c, p->carrier_freq,
+					    &p->carrier_range_lower,
+					    &p->carrier_range_upper);
+		o->carrier_range_lower = p->carrier_range_lower;
+		o->carrier_range_upper = p->carrier_range_upper;
+
+		p->max_pulse_width =
+			(u32) pulse_width_count_to_ns(FIFO_RXTX, rxclk_divider);
+	} else {
+		p->max_pulse_width =
+			    rxclk_rx_s_max_pulse_width(c, p->max_pulse_width,
+						       &rxclk_divider);
+	}
+	o->max_pulse_width = p->max_pulse_width;
+	atomic_set(&ir_state->rxclk_divider, rxclk_divider);
+
+	p->noise_filter_min_width =
+			    filter_rx_s_min_width(c, p->noise_filter_min_width);
+	o->noise_filter_min_width = p->noise_filter_min_width;
+
+	p->resolution = clock_divider_to_resolution(rxclk_divider);
+	o->resolution = p->resolution;
+
+	/* FIXME - make this dependent on resolution for better performance */
+	control_rx_irq_watermark(c, RX_FIFO_HALF_FULL);
+
+	control_rx_s_edge_detection(c, CNTRL_EDG_BOTH);
+
+	o->invert_level = p->invert_level;
+	atomic_set(&ir_state->rx_invert, p->invert_level);
+
+	o->interrupt_enable = p->interrupt_enable;
+	o->enable = p->enable;
+	if (p->enable) {
+		unsigned long flags;
+
+		spin_lock_irqsave(&ir_state->rx_kfifo_lock, flags);
+		kfifo_reset(&ir_state->rx_kfifo);
+		spin_unlock_irqrestore(&ir_state->rx_kfifo_lock, flags);
+		if (p->interrupt_enable)
+			irqenable_rx(sd, IRQEN_RSE | IRQEN_RTE | IRQEN_ROE);
+		control_rx_enable(c, p->enable);
+	}
+
+	mutex_unlock(&ir_state->rx_params_lock);
+	return 0;
+}
+
+/* Transmitter */
+static int cx25840_ir_tx_write(struct v4l2_subdev *sd, u8 *buf, size_t count,
+			       ssize_t *num)
+{
+	struct cx25840_ir_state *ir_state = to_ir_state(sd);
+
+	if (ir_state == NULL)
+		return -ENODEV;
+
+#if 0
+	/*
+	 * FIXME - the code below is an incomplete and untested sketch of what
+	 * may need to be done.  The critical part is to get 4 (or 8) pulses
+	 * from the tx_kfifo, or converted from ns to the proper units from the
+	 * input, and push them off to the hardware Tx FIFO right away, if the
+	 * HW TX fifo needs service.  The rest can be pushed to the tx_kfifo in
+	 * a less critical timeframe.  Also watch out for overruning the
+	 * tx_kfifo - don't let it happen and let the caller know not all his
+	 * pulses were written.
+	 */
+	u32 *ns_pulse = (u32 *) buf;
+	unsigned int n;
+	u32 fifo_pulse[FIFO_TX_DEPTH];
+	u32 mark;
+
+	/* Compute how much we can fit in the tx kfifo */
+	n = CX25840_IR_TX_KFIFO_SIZE - kfifo_len(ir_state->tx_kfifo);
+	n = min(n, (unsigned int) count);
+	n /= sizeof(u32);
+
+	/* FIXME - turn on Tx Fifo service interrupt
+	 * check hardware fifo level, and other stuff
+	 */
+	for (i = 0; i < n; ) {
+		for (j = 0; j < FIFO_TX_DEPTH / 2 && i < n; j++) {
+			mark = ns_pulse[i] & LEVEL_MASK;
+			fifo_pulse[j] = ns_to_pulse_width_count(
+					 ns_pulse[i] &
+					       ~LEVEL_MASK,
+					 ir_state->txclk_divider);
+			if (mark)
+				fifo_pulse[j] &= FIFO_RXTX_LVL;
+			i++;
+		}
+		kfifo_put(ir_state->tx_kfifo, (u8 *) fifo_pulse,
+							       j * sizeof(u32));
+	}
+	*num = n * sizeof(u32);
+#else
+	/* For now enable the Tx FIFO Service interrupt & pretend we did work */
+	irqenable_tx(sd, IRQEN_TSE);
+	*num = count;
+#endif
+	return 0;
+}
+
+static int cx25840_ir_tx_g_parameters(struct v4l2_subdev *sd,
+				      struct v4l2_subdev_ir_parameters *p)
+{
+	struct cx25840_ir_state *ir_state = to_ir_state(sd);
+
+	if (ir_state == NULL)
+		return -ENODEV;
+
+	mutex_lock(&ir_state->tx_params_lock);
+	memcpy(p, &ir_state->tx_params,
+				      sizeof(struct v4l2_subdev_ir_parameters));
+	mutex_unlock(&ir_state->tx_params_lock);
+	return 0;
+}
+
+static int cx25840_ir_tx_shutdown(struct v4l2_subdev *sd)
+{
+	struct cx25840_ir_state *ir_state = to_ir_state(sd);
+	struct i2c_client *c;
+
+	if (ir_state == NULL)
+		return -ENODEV;
+
+	c = ir_state->c;
+	mutex_lock(&ir_state->tx_params_lock);
+
+	/* Disable or slow down all IR Tx circuits and counters */
+	irqenable_tx(sd, 0);
+	control_tx_enable(c, false);
+	control_tx_modulation_enable(c, false);
+	cx25840_write4(c, CX25840_IR_TXCLK_REG, TXCLK_TCD);
+
+	ir_state->tx_params.shutdown = true;
+
+	mutex_unlock(&ir_state->tx_params_lock);
+	return 0;
+}
+
+static int cx25840_ir_tx_s_parameters(struct v4l2_subdev *sd,
+				      struct v4l2_subdev_ir_parameters *p)
+{
+	struct cx25840_ir_state *ir_state = to_ir_state(sd);
+	struct i2c_client *c;
+	struct v4l2_subdev_ir_parameters *o;
+	u16 txclk_divider;
+
+	if (ir_state == NULL)
+		return -ENODEV;
+
+	if (p->shutdown)
+		return cx25840_ir_tx_shutdown(sd);
+
+	if (p->mode != V4L2_SUBDEV_IR_MODE_PULSE_WIDTH)
+		return -ENOSYS;
+
+	c = ir_state->c;
+	o = &ir_state->tx_params;
+	mutex_lock(&ir_state->tx_params_lock);
+
+	o->shutdown = p->shutdown;
+
+	p->mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH;
+	o->mode = p->mode;
+
+	p->bytes_per_data_element = sizeof(union cx25840_ir_fifo_rec);
+	o->bytes_per_data_element = p->bytes_per_data_element;
+
+	/* Before we tweak the hardware, we have to disable the transmitter */
+	irqenable_tx(sd, 0);
+	control_tx_enable(c, false);
+
+	control_tx_modulation_enable(c, p->modulation);
+	o->modulation = p->modulation;
+
+	if (p->modulation) {
+		p->carrier_freq = txclk_tx_s_carrier(c, p->carrier_freq,
+						     &txclk_divider);
+		o->carrier_freq = p->carrier_freq;
+
+		p->duty_cycle = cduty_tx_s_duty_cycle(c, p->duty_cycle);
+		o->duty_cycle = p->duty_cycle;
+
+		p->max_pulse_width =
+			(u32) pulse_width_count_to_ns(FIFO_RXTX, txclk_divider);
+	} else {
+		p->max_pulse_width =
+			    txclk_tx_s_max_pulse_width(c, p->max_pulse_width,
+						       &txclk_divider);
+	}
+	o->max_pulse_width = p->max_pulse_width;
+	atomic_set(&ir_state->txclk_divider, txclk_divider);
+
+	p->resolution = clock_divider_to_resolution(txclk_divider);
+	o->resolution = p->resolution;
+
+	/* FIXME - make this dependent on resolution for better performance */
+	control_tx_irq_watermark(c, TX_FIFO_HALF_EMPTY);
+
+	control_tx_polarity_invert(c, p->invert_carrier_sense);
+	o->invert_carrier_sense = p->invert_carrier_sense;
+
+	/*
+	 * FIXME: we don't have hardware help for IO pin level inversion
+	 * here like we have on the CX23888.
+	 * Act on this with some mix of logical inversion of data levels,
+	 * carrier polarity, and carrier duty cycle.
+	 */
+	o->invert_level = p->invert_level;
+
+	o->interrupt_enable = p->interrupt_enable;
+	o->enable = p->enable;
+	if (p->enable) {
+		/* reset tx_fifo here */
+		if (p->interrupt_enable)
+			irqenable_tx(sd, IRQEN_TSE);
+		control_tx_enable(c, p->enable);
+	}
+
+	mutex_unlock(&ir_state->tx_params_lock);
+	return 0;
+}
+
+
+/*
+ * V4L2 Subdevice Core Ops support
+ */
+int cx25840_ir_log_status(struct v4l2_subdev *sd)
+{
+	struct cx25840_state *state = to_state(sd);
+	struct i2c_client *c = state->c;
+	char *s;
+	int i, j;
+	u32 cntrl, txclk, rxclk, cduty, stats, irqen, filtr;
+
+	/* The CX23888 chip doesn't have an IR controller on the A/V core */
+	if (is_cx23888(state))
+		return 0;
+
+	cntrl = cx25840_read4(c, CX25840_IR_CNTRL_REG);
+	txclk = cx25840_read4(c, CX25840_IR_TXCLK_REG) & TXCLK_TCD;
+	rxclk = cx25840_read4(c, CX25840_IR_RXCLK_REG) & RXCLK_RCD;
+	cduty = cx25840_read4(c, CX25840_IR_CDUTY_REG) & CDUTY_CDC;
+	stats = cx25840_read4(c, CX25840_IR_STATS_REG);
+	irqen = cx25840_read4(c, CX25840_IR_IRQEN_REG);
+	if (is_cx23885(state) || is_cx23887(state))
+		irqen ^= IRQEN_MSK;
+	filtr = cx25840_read4(c, CX25840_IR_FILTR_REG) & FILTR_LPF;
+
+	v4l2_info(sd, "IR Receiver:\n");
+	v4l2_info(sd, "\tEnabled:                           %s\n",
+		  cntrl & CNTRL_RXE ? "yes" : "no");
+	v4l2_info(sd, "\tDemodulation from a carrier:       %s\n",
+		  cntrl & CNTRL_DMD ? "enabled" : "disabled");
+	v4l2_info(sd, "\tFIFO:                              %s\n",
+		  cntrl & CNTRL_RFE ? "enabled" : "disabled");
+	switch (cntrl & CNTRL_EDG) {
+	case CNTRL_EDG_NONE:
+		s = "disabled";
+		break;
+	case CNTRL_EDG_FALL:
+		s = "falling edge";
+		break;
+	case CNTRL_EDG_RISE:
+		s = "rising edge";
+		break;
+	case CNTRL_EDG_BOTH:
+		s = "rising & falling edges";
+		break;
+	default:
+		s = "??? edge";
+		break;
+	}
+	v4l2_info(sd, "\tPulse timers' start/stop trigger:  %s\n", s);
+	v4l2_info(sd, "\tFIFO data on pulse timer overflow: %s\n",
+		  cntrl & CNTRL_R ? "not loaded" : "overflow marker");
+	v4l2_info(sd, "\tFIFO interrupt watermark:          %s\n",
+		  cntrl & CNTRL_RIC ? "not empty" : "half full or greater");
+	v4l2_info(sd, "\tLoopback mode:                     %s\n",
+		  cntrl & CNTRL_LBM ? "loopback active" : "normal receive");
+	if (cntrl & CNTRL_DMD) {
+		v4l2_info(sd, "\tExpected carrier (16 clocks):      %u Hz\n",
+			  clock_divider_to_carrier_freq(rxclk));
+		switch (cntrl & CNTRL_WIN) {
+		case CNTRL_WIN_3_3:
+			i = 3;
+			j = 3;
+			break;
+		case CNTRL_WIN_4_3:
+			i = 4;
+			j = 3;
+			break;
+		case CNTRL_WIN_3_4:
+			i = 3;
+			j = 4;
+			break;
+		case CNTRL_WIN_4_4:
+			i = 4;
+			j = 4;
+			break;
+		default:
+			i = 0;
+			j = 0;
+			break;
+		}
+		v4l2_info(sd, "\tNext carrier edge window:          16 clocks "
+			  "-%1d/+%1d, %u to %u Hz\n", i, j,
+			  clock_divider_to_freq(rxclk, 16 + j),
+			  clock_divider_to_freq(rxclk, 16 - i));
+	}
+	v4l2_info(sd, "\tMax measurable pulse width:        %u us, %llu ns\n",
+		  pulse_width_count_to_us(FIFO_RXTX, rxclk),
+		  pulse_width_count_to_ns(FIFO_RXTX, rxclk));
+	v4l2_info(sd, "\tLow pass filter:                   %s\n",
+		  filtr ? "enabled" : "disabled");
+	if (filtr)
+		v4l2_info(sd, "\tMin acceptable pulse width (LPF):  %u us, "
+			  "%u ns\n",
+			  lpf_count_to_us(filtr),
+			  lpf_count_to_ns(filtr));
+	v4l2_info(sd, "\tPulse width timer timed-out:       %s\n",
+		  stats & STATS_RTO ? "yes" : "no");
+	v4l2_info(sd, "\tPulse width timer time-out intr:   %s\n",
+		  irqen & IRQEN_RTE ? "enabled" : "disabled");
+	v4l2_info(sd, "\tFIFO overrun:                      %s\n",
+		  stats & STATS_ROR ? "yes" : "no");
+	v4l2_info(sd, "\tFIFO overrun interrupt:            %s\n",
+		  irqen & IRQEN_ROE ? "enabled" : "disabled");
+	v4l2_info(sd, "\tBusy:                              %s\n",
+		  stats & STATS_RBY ? "yes" : "no");
+	v4l2_info(sd, "\tFIFO service requested:            %s\n",
+		  stats & STATS_RSR ? "yes" : "no");
+	v4l2_info(sd, "\tFIFO service request interrupt:    %s\n",
+		  irqen & IRQEN_RSE ? "enabled" : "disabled");
+
+	v4l2_info(sd, "IR Transmitter:\n");
+	v4l2_info(sd, "\tEnabled:                           %s\n",
+		  cntrl & CNTRL_TXE ? "yes" : "no");
+	v4l2_info(sd, "\tModulation onto a carrier:         %s\n",
+		  cntrl & CNTRL_MOD ? "enabled" : "disabled");
+	v4l2_info(sd, "\tFIFO:                              %s\n",
+		  cntrl & CNTRL_TFE ? "enabled" : "disabled");
+	v4l2_info(sd, "\tFIFO interrupt watermark:          %s\n",
+		  cntrl & CNTRL_TIC ? "not empty" : "half full or less");
+	v4l2_info(sd, "\tCarrier polarity:                  %s\n",
+		  cntrl & CNTRL_CPL ? "space:burst mark:noburst"
+				    : "space:noburst mark:burst");
+	if (cntrl & CNTRL_MOD) {
+		v4l2_info(sd, "\tCarrier (16 clocks):               %u Hz\n",
+			  clock_divider_to_carrier_freq(txclk));
+		v4l2_info(sd, "\tCarrier duty cycle:                %2u/16\n",
+			  cduty + 1);
+	}
+	v4l2_info(sd, "\tMax pulse width:                   %u us, %llu ns\n",
+		  pulse_width_count_to_us(FIFO_RXTX, txclk),
+		  pulse_width_count_to_ns(FIFO_RXTX, txclk));
+	v4l2_info(sd, "\tBusy:                              %s\n",
+		  stats & STATS_TBY ? "yes" : "no");
+	v4l2_info(sd, "\tFIFO service requested:            %s\n",
+		  stats & STATS_TSR ? "yes" : "no");
+	v4l2_info(sd, "\tFIFO service request interrupt:    %s\n",
+		  irqen & IRQEN_TSE ? "enabled" : "disabled");
+
+	return 0;
+}
+
+
+const struct v4l2_subdev_ir_ops cx25840_ir_ops = {
+	.rx_read = cx25840_ir_rx_read,
+	.rx_g_parameters = cx25840_ir_rx_g_parameters,
+	.rx_s_parameters = cx25840_ir_rx_s_parameters,
+
+	.tx_write = cx25840_ir_tx_write,
+	.tx_g_parameters = cx25840_ir_tx_g_parameters,
+	.tx_s_parameters = cx25840_ir_tx_s_parameters,
+};
+
+
+static const struct v4l2_subdev_ir_parameters default_rx_params = {
+	.bytes_per_data_element = sizeof(union cx25840_ir_fifo_rec),
+	.mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH,
+
+	.enable = false,
+	.interrupt_enable = false,
+	.shutdown = true,
+
+	.modulation = true,
+	.carrier_freq = 36000, /* 36 kHz - RC-5, and RC-6 carrier */
+
+	/* RC-5: 666,667 ns = 1/36 kHz * 32 cycles * 1 mark * 0.75 */
+	/* RC-6: 333,333 ns = 1/36 kHz * 16 cycles * 1 mark * 0.75 */
+	.noise_filter_min_width = 333333, /* ns */
+	.carrier_range_lower = 35000,
+	.carrier_range_upper = 37000,
+	.invert_level = false,
+};
+
+static const struct v4l2_subdev_ir_parameters default_tx_params = {
+	.bytes_per_data_element = sizeof(union cx25840_ir_fifo_rec),
+	.mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH,
+
+	.enable = false,
+	.interrupt_enable = false,
+	.shutdown = true,
+
+	.modulation = true,
+	.carrier_freq = 36000, /* 36 kHz - RC-5 carrier */
+	.duty_cycle = 25,      /* 25 %   - RC-5 carrier */
+	.invert_level = false,
+	.invert_carrier_sense = false,
+};
+
+int cx25840_ir_probe(struct v4l2_subdev *sd)
+{
+	struct cx25840_state *state = to_state(sd);
+	struct cx25840_ir_state *ir_state;
+	struct v4l2_subdev_ir_parameters default_params;
+
+	/* Only init the IR controller for the CX2388[57] AV Core for now */
+	if (!(is_cx23885(state) || is_cx23887(state)))
+		return 0;
+
+	ir_state = kzalloc(sizeof(struct cx25840_ir_state), GFP_KERNEL);
+	if (ir_state == NULL)
+		return -ENOMEM;
+
+	spin_lock_init(&ir_state->rx_kfifo_lock);
+	if (kfifo_alloc(&ir_state->rx_kfifo,
+			CX25840_IR_RX_KFIFO_SIZE, GFP_KERNEL)) {
+		kfree(ir_state);
+		return -ENOMEM;
+	}
+
+	ir_state->c = state->c;
+	state->ir_state = ir_state;
+
+	/* Ensure no interrupts arrive yet */
+	if (is_cx23885(state) || is_cx23887(state))
+		cx25840_write4(ir_state->c, CX25840_IR_IRQEN_REG, IRQEN_MSK);
+	else
+		cx25840_write4(ir_state->c, CX25840_IR_IRQEN_REG, 0);
+
+	mutex_init(&ir_state->rx_params_lock);
+	memcpy(&default_params, &default_rx_params,
+		       sizeof(struct v4l2_subdev_ir_parameters));
+	v4l2_subdev_call(sd, ir, rx_s_parameters, &default_params);
+
+	mutex_init(&ir_state->tx_params_lock);
+	memcpy(&default_params, &default_tx_params,
+		       sizeof(struct v4l2_subdev_ir_parameters));
+	v4l2_subdev_call(sd, ir, tx_s_parameters, &default_params);
+
+	return 0;
+}
+
+int cx25840_ir_remove(struct v4l2_subdev *sd)
+{
+	struct cx25840_state *state = to_state(sd);
+	struct cx25840_ir_state *ir_state = to_ir_state(sd);
+
+	if (ir_state == NULL)
+		return -ENODEV;
+
+	cx25840_ir_rx_shutdown(sd);
+	cx25840_ir_tx_shutdown(sd);
+
+	kfifo_free(&ir_state->rx_kfifo);
+	kfree(ir_state);
+	state->ir_state = NULL;
+	return 0;
+}
diff --git a/drivers/media/i2c/cx25840/cx25840-vbi.c b/drivers/media/i2c/cx25840/cx25840-vbi.c
new file mode 100644
index 0000000..64a4004
--- /dev/null
+++ b/drivers/media/i2c/cx25840/cx25840-vbi.c
@@ -0,0 +1,256 @@
+/* cx25840 VBI functions
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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/videodev2.h>
+#include <linux/i2c.h>
+#include <media/v4l2-common.h>
+#include <media/cx25840.h>
+
+#include "cx25840-core.h"
+
+static int odd_parity(u8 c)
+{
+	c ^= (c >> 4);
+	c ^= (c >> 2);
+	c ^= (c >> 1);
+
+	return c & 1;
+}
+
+static int decode_vps(u8 * dst, u8 * p)
+{
+	static const u8 biphase_tbl[] = {
+		0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
+		0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
+		0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96,
+		0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2,
+		0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94,
+		0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0,
+		0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
+		0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
+		0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5,
+		0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1,
+		0xc3, 0x4b, 0x43, 0xc3, 0x87, 0x0f, 0x07, 0x87,
+		0x83, 0x0b, 0x03, 0x83, 0xc3, 0x4b, 0x43, 0xc3,
+		0xc1, 0x49, 0x41, 0xc1, 0x85, 0x0d, 0x05, 0x85,
+		0x81, 0x09, 0x01, 0x81, 0xc1, 0x49, 0x41, 0xc1,
+		0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5,
+		0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1,
+		0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4,
+		0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0,
+		0xc2, 0x4a, 0x42, 0xc2, 0x86, 0x0e, 0x06, 0x86,
+		0x82, 0x0a, 0x02, 0x82, 0xc2, 0x4a, 0x42, 0xc2,
+		0xc0, 0x48, 0x40, 0xc0, 0x84, 0x0c, 0x04, 0x84,
+		0x80, 0x08, 0x00, 0x80, 0xc0, 0x48, 0x40, 0xc0,
+		0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4,
+		0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0,
+		0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
+		0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
+		0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96,
+		0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2,
+		0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94,
+		0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0,
+		0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
+		0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
+	};
+
+	u8 c, err = 0;
+	int i;
+
+	for (i = 0; i < 2 * 13; i += 2) {
+		err |= biphase_tbl[p[i]] | biphase_tbl[p[i + 1]];
+		c = (biphase_tbl[p[i + 1]] & 0xf) |
+		    ((biphase_tbl[p[i]] & 0xf) << 4);
+		dst[i / 2] = c;
+	}
+
+	return err & 0xf0;
+}
+
+int cx25840_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *svbi)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct cx25840_state *state = to_state(sd);
+	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;
+
+	memset(svbi, 0, sizeof(*svbi));
+	/* we're done if raw VBI is active */
+	if ((cx25840_read(client, 0x404) & 0x10) == 0)
+		return 0;
+
+	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];
+		}
+	} 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];
+		}
+	}
+	return 0;
+}
+
+int cx25840_s_raw_fmt(struct v4l2_subdev *sd, struct v4l2_vbi_format *fmt)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct cx25840_state *state = to_state(sd);
+	int is_pal = !(state->std & V4L2_STD_525_60);
+	int vbi_offset = is_pal ? 1 : 0;
+
+	/* Setup standard */
+	cx25840_std_setup(client);
+
+	/* VBI Offset */
+	cx25840_write(client, 0x47f, vbi_offset);
+	cx25840_write(client, 0x404, 0x2e);
+	return 0;
+}
+
+int cx25840_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *svbi)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct cx25840_state *state = to_state(sd);
+	int is_pal = !(state->std & V4L2_STD_525_60);
+	int vbi_offset = is_pal ? 1 : 0;
+	int i, x;
+	u8 lcr[24];
+
+	for (x = 0; x <= 23; x++)
+		lcr[x] = 0x00;
+
+	/* Setup standard */
+	cx25840_std_setup(client);
+
+	/* Sliced VBI */
+	cx25840_write(client, 0x404, 0x32);	/* Ancillary data */
+	cx25840_write(client, 0x406, 0x13);
+	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);
+	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;
+	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/i2c/ir-kbd-i2c.c b/drivers/media/i2c/ir-kbd-i2c.c
new file mode 100644
index 0000000..04f192a
--- /dev/null
+++ b/drivers/media/i2c/ir-kbd-i2c.c
@@ -0,0 +1,489 @@
+/*
+ *
+ * keyboard input driver for i2c IR remote controls
+ *
+ * Copyright (c) 2000-2003 Gerd Knorr <kraxel@bytesex.org>
+ * modified for PixelView (BT878P+W/FM) by
+ *      Michal Kochanowicz <mkochano@pld.org.pl>
+ *      Christoph Bartelmus <lirc@bartelmus.de>
+ * modified for KNC ONE TV Station/Anubis Typhoon TView Tuner by
+ *      Ulrich Mueller <ulrich.mueller42@web.de>
+ * modified for em2820 based USB TV tuners by
+ *      Markus Rechberger <mrechberger@gmail.com>
+ * modified for DViCO Fusion HDTV 5 RT GOLD by
+ *      Chaogui Zhang <czhang1974@gmail.com>
+ * modified for MSI TV@nywhere Plus by
+ *      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
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/workqueue.h>
+
+#include <media/rc-core.h>
+#include <media/ir-kbd-i2c.h>
+
+/* ----------------------------------------------------------------------- */
+/* insmod parameters                                                       */
+
+static int debug;
+module_param(debug, int, 0644);    /* debug level (0,1,2) */
+
+
+#define MODULE_NAME "ir-kbd-i2c"
+#define dprintk(level, fmt, arg...)	if (debug >= level) \
+	printk(KERN_DEBUG MODULE_NAME ": " fmt , ## arg)
+
+/* ----------------------------------------------------------------------- */
+
+static int get_key_haup_common(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw,
+			       int size, int offset)
+{
+	unsigned char buf[6];
+	int start, range, toggle, dev, code, ircode;
+
+	/* poll IR chip */
+	if (size != i2c_master_recv(ir->c, buf, size))
+		return -EIO;
+
+	/* split rc5 data block ... */
+	start  = (buf[offset] >> 7) &    1;
+	range  = (buf[offset] >> 6) &    1;
+	toggle = (buf[offset] >> 5) &    1;
+	dev    =  buf[offset]       & 0x1f;
+	code   = (buf[offset+1] >> 2) & 0x3f;
+
+	/* rc5 has two start bits
+	 * the first bit must be one
+	 * the second bit defines the command range (1 = 0-63, 0 = 64 - 127)
+	 */
+	if (!start)
+		/* no key pressed */
+		return 0;
+	/*
+	 * Hauppauge remotes (black/silver) always use
+	 * specific device ids. If we do not filter the
+	 * device ids then messages destined for devices
+	 * such as TVs (id=0) will get through causing
+	 * mis-fired events.
+	 *
+	 * We also filter out invalid key presses which
+	 * produce annoying debug log entries.
+	 */
+	ircode= (start << 12) | (toggle << 11) | (dev << 6) | code;
+	if ((ircode & 0x1fff)==0x1fff)
+		/* invalid key press */
+		return 0;
+
+	if (!range)
+		code += 64;
+
+	dprintk(1,"ir hauppauge (rc5): s%d r%d t%d dev=%d code=%d\n",
+		start, range, toggle, dev, code);
+
+	/* return key */
+	*ir_key = (dev << 8) | code;
+	*ir_raw = ircode;
+	return 1;
+}
+
+static int get_key_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+{
+	return get_key_haup_common (ir, ir_key, ir_raw, 3, 0);
+}
+
+static int get_key_haup_xvr(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+{
+	int ret;
+	unsigned char buf[1] = { 0 };
+
+	/*
+	 * This is the same apparent "are you ready?" poll command observed
+	 * watching Windows driver traffic and implemented in lirc_zilog. With
+	 * this added, we get far saner remote behavior with z8 chips on usb
+	 * connected devices, even with the default polling interval of 100ms.
+	 */
+	ret = i2c_master_send(ir->c, buf, 1);
+	if (ret != 1)
+		return (ret < 0) ? ret : -EINVAL;
+
+	return get_key_haup_common (ir, ir_key, ir_raw, 6, 3);
+}
+
+static int get_key_pixelview(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+{
+	unsigned char b;
+
+	/* poll IR chip */
+	if (1 != i2c_master_recv(ir->c, &b, 1)) {
+		dprintk(1,"read error\n");
+		return -EIO;
+	}
+	*ir_key = b;
+	*ir_raw = b;
+	return 1;
+}
+
+static int get_key_fusionhdtv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+{
+	unsigned char buf[4];
+
+	/* poll IR chip */
+	if (4 != i2c_master_recv(ir->c, buf, 4)) {
+		dprintk(1,"read error\n");
+		return -EIO;
+	}
+
+	if(buf[0] !=0 || buf[1] !=0 || buf[2] !=0 || buf[3] != 0)
+		dprintk(2, "%s: 0x%2x 0x%2x 0x%2x 0x%2x\n", __func__,
+			buf[0], buf[1], buf[2], buf[3]);
+
+	/* no key pressed or signal from other ir remote */
+	if(buf[0] != 0x1 ||  buf[1] != 0xfe)
+		return 0;
+
+	*ir_key = buf[2];
+	*ir_raw = (buf[2] << 8) | buf[3];
+
+	return 1;
+}
+
+static int get_key_knc1(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+{
+	unsigned char b;
+
+	/* poll IR chip */
+	if (1 != i2c_master_recv(ir->c, &b, 1)) {
+		dprintk(1,"read error\n");
+		return -EIO;
+	}
+
+	/* it seems that 0xFE indicates that a button is still hold
+	   down, while 0xff indicates that no button is hold
+	   down. 0xfe sequences are sometimes interrupted by 0xFF */
+
+	dprintk(2,"key %02x\n", b);
+
+	if (b == 0xff)
+		return 0;
+
+	if (b == 0xfe)
+		/* keep old data */
+		return 1;
+
+	*ir_key = b;
+	*ir_raw = b;
+	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 int ir_key_poll(struct IR_i2c *ir)
+{
+	static u32 ir_key, ir_raw;
+	int rc;
+
+	dprintk(3, "%s\n", __func__);
+	rc = ir->get_key(ir, &ir_key, &ir_raw);
+	if (rc < 0) {
+		dprintk(2,"error\n");
+		return rc;
+	}
+
+	if (rc) {
+		dprintk(1, "%s: keycode = 0x%04x\n", __func__, ir_key);
+		rc_keydown(ir->rc, ir_key, 0);
+	}
+	return 0;
+}
+
+static void ir_work(struct work_struct *work)
+{
+	int rc;
+	struct IR_i2c *ir = container_of(work, struct IR_i2c, work.work);
+
+	rc = ir_key_poll(ir);
+	if (rc == -ENODEV) {
+		rc_unregister_device(ir->rc);
+		ir->rc = NULL;
+		return;
+	}
+
+	schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling_interval));
+}
+
+/* ----------------------------------------------------------------------- */
+
+static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+	char *ir_codes = NULL;
+	const char *name = NULL;
+	u64 rc_type = RC_TYPE_UNKNOWN;
+	struct IR_i2c *ir;
+	struct rc_dev *rc = NULL;
+	struct i2c_adapter *adap = client->adapter;
+	unsigned short addr = client->addr;
+	int err;
+
+	ir = kzalloc(sizeof(struct IR_i2c), GFP_KERNEL);
+	if (!ir)
+		return -ENOMEM;
+
+	ir->c = client;
+	ir->polling_interval = DEFAULT_POLLING_INTERVAL;
+	i2c_set_clientdata(client, ir);
+
+	switch(addr) {
+	case 0x64:
+		name        = "Pixelview";
+		ir->get_key = get_key_pixelview;
+		rc_type     = RC_TYPE_OTHER;
+		ir_codes    = RC_MAP_EMPTY;
+		break;
+	case 0x18:
+	case 0x1f:
+	case 0x1a:
+		name        = "Hauppauge";
+		ir->get_key = get_key_haup;
+		rc_type     = RC_TYPE_RC5;
+		ir_codes    = RC_MAP_HAUPPAUGE;
+		break;
+	case 0x30:
+		name        = "KNC One";
+		ir->get_key = get_key_knc1;
+		rc_type     = RC_TYPE_OTHER;
+		ir_codes    = RC_MAP_EMPTY;
+		break;
+	case 0x6b:
+		name        = "FusionHDTV";
+		ir->get_key = get_key_fusionhdtv;
+		rc_type     = RC_TYPE_RC5;
+		ir_codes    = RC_MAP_FUSIONHDTV_MCE;
+		break;
+	case 0x40:
+		name        = "AVerMedia Cardbus remote";
+		ir->get_key = get_key_avermedia_cardbus;
+		rc_type     = RC_TYPE_OTHER;
+		ir_codes    = RC_MAP_AVERMEDIA_CARDBUS;
+		break;
+	case 0x71:
+		name        = "Hauppauge/Zilog Z8";
+		ir->get_key = get_key_haup_xvr;
+		rc_type     = RC_TYPE_RC5;
+		ir_codes    = RC_MAP_HAUPPAUGE;
+		break;
+	}
+
+	/* Let the caller override settings */
+	if (client->dev.platform_data) {
+		const struct IR_i2c_init_data *init_data =
+						client->dev.platform_data;
+
+		ir_codes = init_data->ir_codes;
+		rc = init_data->rc_dev;
+
+		name = init_data->name;
+		if (init_data->type)
+			rc_type = init_data->type;
+
+		if (init_data->polling_interval)
+			ir->polling_interval = init_data->polling_interval;
+
+		switch (init_data->internal_get_key_func) {
+		case IR_KBD_GET_KEY_CUSTOM:
+			/* The bridge driver provided us its own function */
+			ir->get_key = init_data->get_key;
+			break;
+		case IR_KBD_GET_KEY_PIXELVIEW:
+			ir->get_key = get_key_pixelview;
+			break;
+		case IR_KBD_GET_KEY_HAUP:
+			ir->get_key = get_key_haup;
+			break;
+		case IR_KBD_GET_KEY_KNC1:
+			ir->get_key = get_key_knc1;
+			break;
+		case IR_KBD_GET_KEY_FUSIONHDTV:
+			ir->get_key = get_key_fusionhdtv;
+			break;
+		case IR_KBD_GET_KEY_HAUP_XVR:
+			ir->get_key = get_key_haup_xvr;
+			break;
+		case IR_KBD_GET_KEY_AVERMEDIA_CARDBUS:
+			ir->get_key = get_key_avermedia_cardbus;
+			break;
+		}
+	}
+
+	if (!rc) {
+		/*
+		 * If platform_data doesn't specify rc_dev, initilize it
+		 * internally
+		 */
+		rc = rc_allocate_device();
+		if (!rc) {
+			err = -ENOMEM;
+			goto err_out_free;
+		}
+	}
+	ir->rc = rc;
+
+	/* Make sure we are all setup before going on */
+	if (!name || !ir->get_key || !rc_type || !ir_codes) {
+		dprintk(1, ": Unsupported device at address 0x%02x\n",
+			addr);
+		err = -ENODEV;
+		goto err_out_free;
+	}
+
+	/* Sets name */
+	snprintf(ir->name, sizeof(ir->name), "i2c IR (%s)", name);
+	ir->ir_codes = ir_codes;
+
+	snprintf(ir->phys, sizeof(ir->phys), "%s/%s/ir0",
+		 dev_name(&adap->dev),
+		 dev_name(&client->dev));
+
+	/*
+	 * Initialize input_dev fields
+	 * It doesn't make sense to allow overriding them via platform_data
+	 */
+	rc->input_id.bustype = BUS_I2C;
+	rc->input_phys       = ir->phys;
+	rc->input_name	     = ir->name;
+
+	/*
+	 * Initialize the other fields of rc_dev
+	 */
+	rc->map_name       = ir->ir_codes;
+	rc->allowed_protos = rc_type;
+	if (!rc->driver_name)
+		rc->driver_name = MODULE_NAME;
+
+	err = rc_register_device(rc);
+	if (err)
+		goto err_out_free;
+
+	printk(MODULE_NAME ": %s detected at %s [%s]\n",
+	       ir->name, ir->phys, adap->name);
+
+	/* start polling via eventd */
+	INIT_DELAYED_WORK(&ir->work, ir_work);
+	schedule_delayed_work(&ir->work, 0);
+
+	return 0;
+
+ err_out_free:
+	/* Only frees rc if it were allocated internally */
+	rc_free_device(rc);
+	kfree(ir);
+	return err;
+}
+
+static int ir_remove(struct i2c_client *client)
+{
+	struct IR_i2c *ir = i2c_get_clientdata(client);
+
+	/* kill outstanding polls */
+	cancel_delayed_work_sync(&ir->work);
+
+	/* unregister device */
+	if (ir->rc)
+		rc_unregister_device(ir->rc);
+
+	/* free memory */
+	kfree(ir);
+	return 0;
+}
+
+static const struct i2c_device_id ir_kbd_id[] = {
+	/* Generic entry for any IR receiver */
+	{ "ir_video", 0 },
+	/* IR device specific entries should be added here */
+	{ "ir_rx_z8f0811_haup", 0 },
+	{ "ir_rx_z8f0811_hdpvr", 0 },
+	{ }
+};
+
+static struct i2c_driver ir_kbd_driver = {
+	.driver = {
+		.name   = "ir-kbd-i2c",
+	},
+	.probe          = ir_probe,
+	.remove         = ir_remove,
+	.id_table       = ir_kbd_id,
+};
+
+module_i2c_driver(ir_kbd_driver);
+
+/* ----------------------------------------------------------------------- */
+
+MODULE_AUTHOR("Gerd Knorr, Michal Kochanowicz, Christoph Bartelmus, Ulrich Mueller");
+MODULE_DESCRIPTION("input driver for i2c IR remote controls");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/i2c/ks0127.c b/drivers/media/i2c/ks0127.c
new file mode 100644
index 0000000..ee7ca2d
--- /dev/null
+++ b/drivers/media/i2c/ks0127.c
@@ -0,0 +1,724 @@
+/*
+ * Video Capture Driver (Video for Linux 1/2)
+ * for the Matrox Marvel G200,G400 and Rainbow Runner-G series
+ *
+ * This module is an interface to the KS0127 video decoder chip.
+ *
+ * Copyright (C) 1999  Ryan Drake <stiletto@mediaone.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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ *****************************************************************************
+ *
+ * Modified and extended by
+ *	Mike Bernson <mike@mlb.org>
+ *	Gerard v.d. Horst
+ *	Leon van Stuivenberg <l.vanstuivenberg@chello.nl>
+ *	Gernot Ziegler <gz@lysator.liu.se>
+ *
+ * Version History:
+ * V1.0 Ryan Drake	   Initial version by Ryan Drake
+ * V1.1 Gerard v.d. Horst  Added some debugoutput, reset the video-standard
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+#include <linux/videodev2.h>
+#include <linux/slab.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-chip-ident.h>
+#include "ks0127.h"
+
+MODULE_DESCRIPTION("KS0127 video decoder driver");
+MODULE_AUTHOR("Ryan Drake");
+MODULE_LICENSE("GPL");
+
+/* Addresses */
+#define I2C_KS0127_ADDON   0xD8
+#define I2C_KS0127_ONBOARD 0xDA
+
+
+/* ks0127 control registers */
+#define KS_STAT     0x00
+#define KS_CMDA     0x01
+#define KS_CMDB     0x02
+#define KS_CMDC     0x03
+#define KS_CMDD     0x04
+#define KS_HAVB     0x05
+#define KS_HAVE     0x06
+#define KS_HS1B     0x07
+#define KS_HS1E     0x08
+#define KS_HS2B     0x09
+#define KS_HS2E     0x0a
+#define KS_AGC      0x0b
+#define KS_HXTRA    0x0c
+#define KS_CDEM     0x0d
+#define KS_PORTAB   0x0e
+#define KS_LUMA     0x0f
+#define KS_CON      0x10
+#define KS_BRT      0x11
+#define KS_CHROMA   0x12
+#define KS_CHROMB   0x13
+#define KS_DEMOD    0x14
+#define KS_SAT      0x15
+#define KS_HUE      0x16
+#define KS_VERTIA   0x17
+#define KS_VERTIB   0x18
+#define KS_VERTIC   0x19
+#define KS_HSCLL    0x1a
+#define KS_HSCLH    0x1b
+#define KS_VSCLL    0x1c
+#define KS_VSCLH    0x1d
+#define KS_OFMTA    0x1e
+#define KS_OFMTB    0x1f
+#define KS_VBICTL   0x20
+#define KS_CCDAT2   0x21
+#define KS_CCDAT1   0x22
+#define KS_VBIL30   0x23
+#define KS_VBIL74   0x24
+#define KS_VBIL118  0x25
+#define KS_VBIL1512 0x26
+#define KS_TTFRAM   0x27
+#define KS_TESTA    0x28
+#define KS_UVOFFH   0x29
+#define KS_UVOFFL   0x2a
+#define KS_UGAIN    0x2b
+#define KS_VGAIN    0x2c
+#define KS_VAVB     0x2d
+#define KS_VAVE     0x2e
+#define KS_CTRACK   0x2f
+#define KS_POLCTL   0x30
+#define KS_REFCOD   0x31
+#define KS_INVALY   0x32
+#define KS_INVALU   0x33
+#define KS_INVALV   0x34
+#define KS_UNUSEY   0x35
+#define KS_UNUSEU   0x36
+#define KS_UNUSEV   0x37
+#define KS_USRSAV   0x38
+#define KS_USREAV   0x39
+#define KS_SHS1A    0x3a
+#define KS_SHS1B    0x3b
+#define KS_SHS1C    0x3c
+#define KS_CMDE     0x3d
+#define KS_VSDEL    0x3e
+#define KS_CMDF     0x3f
+#define KS_GAMMA0   0x40
+#define KS_GAMMA1   0x41
+#define KS_GAMMA2   0x42
+#define KS_GAMMA3   0x43
+#define KS_GAMMA4   0x44
+#define KS_GAMMA5   0x45
+#define KS_GAMMA6   0x46
+#define KS_GAMMA7   0x47
+#define KS_GAMMA8   0x48
+#define KS_GAMMA9   0x49
+#define KS_GAMMA10  0x4a
+#define KS_GAMMA11  0x4b
+#define KS_GAMMA12  0x4c
+#define KS_GAMMA13  0x4d
+#define KS_GAMMA14  0x4e
+#define KS_GAMMA15  0x4f
+#define KS_GAMMA16  0x50
+#define KS_GAMMA17  0x51
+#define KS_GAMMA18  0x52
+#define KS_GAMMA19  0x53
+#define KS_GAMMA20  0x54
+#define KS_GAMMA21  0x55
+#define KS_GAMMA22  0x56
+#define KS_GAMMA23  0x57
+#define KS_GAMMA24  0x58
+#define KS_GAMMA25  0x59
+#define KS_GAMMA26  0x5a
+#define KS_GAMMA27  0x5b
+#define KS_GAMMA28  0x5c
+#define KS_GAMMA29  0x5d
+#define KS_GAMMA30  0x5e
+#define KS_GAMMA31  0x5f
+#define KS_GAMMAD0  0x60
+#define KS_GAMMAD1  0x61
+#define KS_GAMMAD2  0x62
+#define KS_GAMMAD3  0x63
+#define KS_GAMMAD4  0x64
+#define KS_GAMMAD5  0x65
+#define KS_GAMMAD6  0x66
+#define KS_GAMMAD7  0x67
+#define KS_GAMMAD8  0x68
+#define KS_GAMMAD9  0x69
+#define KS_GAMMAD10 0x6a
+#define KS_GAMMAD11 0x6b
+#define KS_GAMMAD12 0x6c
+#define KS_GAMMAD13 0x6d
+#define KS_GAMMAD14 0x6e
+#define KS_GAMMAD15 0x6f
+#define KS_GAMMAD16 0x70
+#define KS_GAMMAD17 0x71
+#define KS_GAMMAD18 0x72
+#define KS_GAMMAD19 0x73
+#define KS_GAMMAD20 0x74
+#define KS_GAMMAD21 0x75
+#define KS_GAMMAD22 0x76
+#define KS_GAMMAD23 0x77
+#define KS_GAMMAD24 0x78
+#define KS_GAMMAD25 0x79
+#define KS_GAMMAD26 0x7a
+#define KS_GAMMAD27 0x7b
+#define KS_GAMMAD28 0x7c
+#define KS_GAMMAD29 0x7d
+#define KS_GAMMAD30 0x7e
+#define KS_GAMMAD31 0x7f
+
+
+/****************************************************************************
+* mga_dev : represents one ks0127 chip.
+****************************************************************************/
+
+struct adjust {
+	int	contrast;
+	int	bright;
+	int	hue;
+	int	ugain;
+	int	vgain;
+};
+
+struct ks0127 {
+	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 */
+
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "Debug output");
+
+static u8 reg_defaults[64];
+
+static void init_reg_defaults(void)
+{
+	static int initialized;
+	u8 *table = reg_defaults;
+
+	if (initialized)
+		return;
+	initialized = 1;
+
+	table[KS_CMDA]     = 0x2c;  /* VSE=0, CCIR 601, autodetect standard */
+	table[KS_CMDB]     = 0x12;  /* VALIGN=0, AGC control and input */
+	table[KS_CMDC]     = 0x00;  /* Test options */
+	/* clock & input select, write 1 to PORTA */
+	table[KS_CMDD]     = 0x01;
+	table[KS_HAVB]     = 0x00;  /* HAV Start Control */
+	table[KS_HAVE]     = 0x00;  /* HAV End Control */
+	table[KS_HS1B]     = 0x10;  /* HS1 Start Control */
+	table[KS_HS1E]     = 0x00;  /* HS1 End Control */
+	table[KS_HS2B]     = 0x00;  /* HS2 Start Control */
+	table[KS_HS2E]     = 0x00;  /* HS2 End Control */
+	table[KS_AGC]      = 0x53;  /* Manual setting for AGC */
+	table[KS_HXTRA]    = 0x00;  /* Extra Bits for HAV and HS1/2 */
+	table[KS_CDEM]     = 0x00;  /* Chroma Demodulation Control */
+	table[KS_PORTAB]   = 0x0f;  /* port B is input, port A output GPPORT */
+	table[KS_LUMA]     = 0x01;  /* Luma control */
+	table[KS_CON]      = 0x00;  /* Contrast Control */
+	table[KS_BRT]      = 0x00;  /* Brightness Control */
+	table[KS_CHROMA]   = 0x2a;  /* Chroma control A */
+	table[KS_CHROMB]   = 0x90;  /* Chroma control B */
+	table[KS_DEMOD]    = 0x00;  /* Chroma Demodulation Control & Status */
+	table[KS_SAT]      = 0x00;  /* Color Saturation Control*/
+	table[KS_HUE]      = 0x00;  /* Hue Control */
+	table[KS_VERTIA]   = 0x00;  /* Vertical Processing Control A */
+	/* Vertical Processing Control B, luma 1 line delayed */
+	table[KS_VERTIB]   = 0x12;
+	table[KS_VERTIC]   = 0x0b;  /* Vertical Processing Control C */
+	table[KS_HSCLL]    = 0x00;  /* Horizontal Scaling Ratio Low */
+	table[KS_HSCLH]    = 0x00;  /* Horizontal Scaling Ratio High */
+	table[KS_VSCLL]    = 0x00;  /* Vertical Scaling Ratio Low */
+	table[KS_VSCLH]    = 0x00;  /* Vertical Scaling Ratio High */
+	/* 16 bit YCbCr 4:2:2 output; I can't make the bt866 like 8 bit /Sam */
+	table[KS_OFMTA]    = 0x30;
+	table[KS_OFMTB]    = 0x00;  /* Output Control B */
+	/* VBI Decoder Control; 4bit fmt: avoid Y overflow */
+	table[KS_VBICTL]   = 0x5d;
+	table[KS_CCDAT2]   = 0x00;  /* Read Only register */
+	table[KS_CCDAT1]   = 0x00;  /* Read Only register */
+	table[KS_VBIL30]   = 0xa8;  /* VBI data decoding options */
+	table[KS_VBIL74]   = 0xaa;  /* VBI data decoding options */
+	table[KS_VBIL118]  = 0x2a;  /* VBI data decoding options */
+	table[KS_VBIL1512] = 0x00;  /* VBI data decoding options */
+	table[KS_TTFRAM]   = 0x00;  /* Teletext frame alignment pattern */
+	table[KS_TESTA]    = 0x00;  /* test register, shouldn't be written */
+	table[KS_UVOFFH]   = 0x00;  /* UV Offset Adjustment High */
+	table[KS_UVOFFL]   = 0x00;  /* UV Offset Adjustment Low */
+	table[KS_UGAIN]    = 0x00;  /* U Component Gain Adjustment */
+	table[KS_VGAIN]    = 0x00;  /* V Component Gain Adjustment */
+	table[KS_VAVB]     = 0x07;  /* VAV Begin */
+	table[KS_VAVE]     = 0x00;  /* VAV End */
+	table[KS_CTRACK]   = 0x00;  /* Chroma Tracking Control */
+	table[KS_POLCTL]   = 0x41;  /* Timing Signal Polarity Control */
+	table[KS_REFCOD]   = 0x80;  /* Reference Code Insertion Control */
+	table[KS_INVALY]   = 0x10;  /* Invalid Y Code */
+	table[KS_INVALU]   = 0x80;  /* Invalid U Code */
+	table[KS_INVALV]   = 0x80;  /* Invalid V Code */
+	table[KS_UNUSEY]   = 0x10;  /* Unused Y Code */
+	table[KS_UNUSEU]   = 0x80;  /* Unused U Code */
+	table[KS_UNUSEV]   = 0x80;  /* Unused V Code */
+	table[KS_USRSAV]   = 0x00;  /* reserved */
+	table[KS_USREAV]   = 0x00;  /* reserved */
+	table[KS_SHS1A]    = 0x00;  /* User Defined SHS1 A */
+	/* User Defined SHS1 B, ALT656=1 on 0127B */
+	table[KS_SHS1B]    = 0x80;
+	table[KS_SHS1C]    = 0x00;  /* User Defined SHS1 C */
+	table[KS_CMDE]     = 0x00;  /* Command Register E */
+	table[KS_VSDEL]    = 0x00;  /* VS Delay Control */
+	/* Command Register F, update -immediately- */
+	/* (there might come no vsync)*/
+	table[KS_CMDF]     = 0x02;
+}
+
+
+/* We need to manually read because of a bug in the KS0127 chip.
+ *
+ * An explanation from kayork@mail.utexas.edu:
+ *
+ * During I2C reads, the KS0127 only samples for a stop condition
+ * during the place where the acknowledge bit should be. Any standard
+ * I2C implementation (correctly) throws in another clock transition
+ * at the 9th bit, and the KS0127 will not recognize the stop condition
+ * and will continue to clock out data.
+ *
+ * So we have to do the read ourself.  Big deal.
+ *	   workaround in i2c-algo-bit
+ */
+
+
+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[] = {
+		{ client->addr, 0, sizeof(reg), &reg },
+		{ client->addr, I2C_M_RD | I2C_M_NO_RD_ACK, sizeof(val), &val }
+	};
+	int ret;
+
+	ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
+	if (ret != ARRAY_SIZE(msgs))
+		v4l2_dbg(1, debug, sd, "read error\n");
+
+	return val;
+}
+
+
+static void ks0127_write(struct v4l2_subdev *sd, u8 reg, u8 val)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct ks0127 *ks = to_ks0127(sd);
+	char msg[] = { reg, val };
+
+	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 v4l2_subdev *sd, u8 reg, u8 and_v, u8 or_v)
+{
+	struct ks0127 *ks = to_ks0127(sd);
+
+	u8 val = ks->regs[reg];
+	val = (val & and_v) | or_v;
+	ks0127_write(sd, reg, val);
+}
+
+
+
+/****************************************************************************
+* ks0127 private api
+****************************************************************************/
+static void ks0127_init(struct v4l2_subdev *sd)
+{
+	struct ks0127 *ks = to_ks0127(sd);
+	u8 *table = reg_defaults;
+	int i;
+
+	ks->ident = V4L2_IDENT_KS0127;
+
+	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(sd, i, table[i]);
+
+	for (i = 35; i < 40; i++)
+		ks0127_write(sd, i, table[i]);
+
+	for (i = 41; i < 56; i++)
+		ks0127_write(sd, i, table[i]);
+
+	for (i = 58; i < 64; i++)
+		ks0127_write(sd, i, table[i]);
+
+
+	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(sd, KS_CMDE) & 0x0f) {
+	case 0:
+		v4l2_dbg(1, debug, sd, "ks0127 found\n");
+		break;
+
+	case 9:
+		ks->ident = V4L2_IDENT_KS0127B;
+		v4l2_dbg(1, debug, sd, "ks0127B Revision A found\n");
+		break;
+
+	default:
+		v4l2_dbg(1, debug, sd, "unknown revision\n");
+		break;
+	}
+}
+
+static int ks0127_s_routing(struct v4l2_subdev *sd,
+			    u32 input, u32 output, u32 config)
+{
+	struct ks0127 *ks = to_ks0127(sd);
+
+	switch (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", 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, 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);
+
+		/* 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 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", 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, 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);
+
+		ks0127_and_or(sd, KS_CHROMB, 0x0f,
+			       reg_defaults[KS_CHROMB]&0xf0);
+
+		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 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);
+
+		ks0127_and_or(sd, KS_CMDA,   0xff, 0x40); /* VSE=1 */
+		/* set input line and VALIGN */
+		ks0127_and_or(sd, KS_CMDB,   0xb0, (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;
+
+	default:
+		v4l2_dbg(1, debug, sd,
+			"s_routing: Unknown input %d\n", input);
+		break;
+	}
+
+	/* hack: CDMLPF sometimes spontaneously switches on; */
+	/* force back off */
+	ks0127_write(sd, KS_DEMOD, reg_defaults[KS_DEMOD]);
+	return 0;
+}
+
+static int ks0127_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
+{
+	struct ks0127 *ks = to_ks0127(sd);
+
+	/* 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;
+}
+
+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;
+
+	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,
+	.s_std = ks0127_s_std,
+};
+
+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,
+	.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(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;
+	sd = &ks->sd;
+	v4l2_i2c_subdev_init(sd, client, &ks0127_ops);
+
+	/* power up */
+	init_reg_defaults();
+	ks0127_write(sd, KS_CMDA, 0x2c);
+	mdelay(10);
+
+	/* reset the device */
+	ks0127_init(sd);
+	return 0;
+}
+
+static int ks0127_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+
+	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 const struct i2c_device_id ks0127_id[] = {
+	{ "ks0127", 0 },
+	{ "ks0127b", 0 },
+	{ "ks0122s", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, ks0127_id);
+
+static struct i2c_driver ks0127_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "ks0127",
+	},
+	.probe		= ks0127_probe,
+	.remove		= ks0127_remove,
+	.id_table	= ks0127_id,
+};
+
+module_i2c_driver(ks0127_driver);
diff --git a/drivers/media/i2c/ks0127.h b/drivers/media/i2c/ks0127.h
new file mode 100644
index 0000000..cb8abd5
--- /dev/null
+++ b/drivers/media/i2c/ks0127.h
@@ -0,0 +1,51 @@
+/*
+ * Video Capture Driver ( Video for Linux 1/2 )
+ * for the Matrox Marvel G200,G400 and Rainbow Runner-G series
+ *
+ * This module is an interface to the KS0127 video decoder chip.
+ *
+ * Copyright (C) 1999  Ryan Drake <stiletto@mediaone.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 program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 KS0127_H
+#define KS0127_H
+
+/* input channels */
+#define KS_INPUT_COMPOSITE_1    0
+#define KS_INPUT_COMPOSITE_2    1
+#define KS_INPUT_COMPOSITE_3    2
+#define KS_INPUT_COMPOSITE_4    4
+#define KS_INPUT_COMPOSITE_5    5
+#define KS_INPUT_COMPOSITE_6    6
+
+#define KS_INPUT_SVIDEO_1       8
+#define KS_INPUT_SVIDEO_2       9
+#define KS_INPUT_SVIDEO_3       10
+
+#define KS_INPUT_YUV656		15
+#define KS_INPUT_COUNT          10
+
+/* output channels */
+#define KS_OUTPUT_YUV656E       0
+#define KS_OUTPUT_EXV           1
+
+/* video standards */
+#define KS_STD_NTSC_N           112       /* 50 Hz NTSC */
+#define KS_STD_PAL_M            113       /* 60 Hz PAL  */
+
+#endif /* KS0127_H */
+
diff --git a/drivers/media/i2c/m52790.c b/drivers/media/i2c/m52790.c
new file mode 100644
index 0000000..0991576
--- /dev/null
+++ b/drivers/media/i2c/m52790.c
@@ -0,0 +1,216 @@
+/*
+ * m52790 i2c ivtv driver.
+ * Copyright (C) 2007  Hans Verkuil
+ *
+ * A/V source switching Mitsubishi M52790SP/FP
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/slab.h>
+#include <linux/ioctl.h>
+#include <asm/uaccess.h>
+#include <linux/i2c.h>
+#include <linux/videodev2.h>
+#include <media/m52790.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-chip-ident.h>
+
+MODULE_DESCRIPTION("i2c device driver for m52790 A/V switch");
+MODULE_AUTHOR("Hans Verkuil");
+MODULE_LICENSE("GPL");
+
+
+struct m52790_state {
+	struct v4l2_subdev sd;
+	u16 input;
+	u16 output;
+};
+
+static inline struct m52790_state *to_state(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct m52790_state, sd);
+}
+
+/* ----------------------------------------------------------------------- */
+
+static int m52790_write(struct v4l2_subdev *sd)
+{
+	struct m52790_state *state = to_state(sd);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	u8 sw1 = (state->input | state->output) & 0xff;
+	u8 sw2 = (state->input | state->output) >> 8;
+
+	return i2c_smbus_write_byte_data(client, sw1, sw2);
+}
+
+/* Note: audio and video are linked and cannot be switched separately.
+   So audio and video routing commands are identical for this chip.
+   In theory the video amplifier and audio modes could be handled
+   separately for the output, but that seems to be overkill right now.
+   The same holds for implementing an audio mute control, this is now
+   part of the audio output routing. The normal case is that another
+   chip takes care of the actual muting so making it part of the
+   output routing seems to be the right thing to do for now. */
+static int m52790_s_routing(struct v4l2_subdev *sd,
+			    u32 input, u32 output, u32 config)
+{
+	struct m52790_state *state = to_state(sd);
+
+	state->input = input;
+	state->output = output;
+	m52790_write(sd);
+	return 0;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int m52790_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
+{
+	struct m52790_state *state = to_state(sd);
+	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;
+	if (reg->reg != 0)
+		return -EINVAL;
+	reg->size = 1;
+	reg->val = state->input | state->output;
+	return 0;
+}
+
+static int m52790_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
+{
+	struct m52790_state *state = to_state(sd);
+	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;
+	if (reg->reg != 0)
+		return -EINVAL;
+	state->input = reg->val & 0x0303;
+	state->output = reg->val & ~0x0303;
+	m52790_write(sd);
+	return 0;
+}
+#endif
+
+static int m52790_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_M52790, 0);
+}
+
+static int m52790_log_status(struct v4l2_subdev *sd)
+{
+	struct m52790_state *state = to_state(sd);
+
+	v4l2_info(sd, "Switch 1: %02x\n",
+			(state->input | state->output) & 0xff);
+	v4l2_info(sd, "Switch 2: %02x\n",
+			(state->input | state->output) >> 8);
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static const struct v4l2_subdev_core_ops m52790_core_ops = {
+	.log_status = m52790_log_status,
+	.g_chip_ident = m52790_g_chip_ident,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.g_register = m52790_g_register,
+	.s_register = m52790_s_register,
+#endif
+};
+
+static const struct v4l2_subdev_audio_ops m52790_audio_ops = {
+	.s_routing = m52790_s_routing,
+};
+
+static const struct v4l2_subdev_video_ops m52790_video_ops = {
+	.s_routing = m52790_s_routing,
+};
+
+static const struct v4l2_subdev_ops m52790_ops = {
+	.core = &m52790_core_ops,
+	.audio = &m52790_audio_ops,
+	.video = &m52790_video_ops,
+};
+
+/* ----------------------------------------------------------------------- */
+
+/* i2c implementation */
+
+static int m52790_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	struct m52790_state *state;
+	struct v4l2_subdev *sd;
+
+	/* Check if the adapter supports the needed features */
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		return -EIO;
+
+	v4l_info(client, "chip found @ 0x%x (%s)\n",
+			client->addr << 1, client->adapter->name);
+
+	state = kzalloc(sizeof(struct m52790_state), GFP_KERNEL);
+	if (state == NULL)
+		return -ENOMEM;
+
+	sd = &state->sd;
+	v4l2_i2c_subdev_init(sd, client, &m52790_ops);
+	state->input = M52790_IN_TUNER;
+	state->output = M52790_OUT_STEREO;
+	m52790_write(sd);
+	return 0;
+}
+
+static int m52790_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+
+	v4l2_device_unregister_subdev(sd);
+	kfree(to_state(sd));
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static const struct i2c_device_id m52790_id[] = {
+	{ "m52790", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, m52790_id);
+
+static struct i2c_driver m52790_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "m52790",
+	},
+	.probe		= m52790_probe,
+	.remove		= m52790_remove,
+	.id_table	= m52790_id,
+};
+
+module_i2c_driver(m52790_driver);
diff --git a/drivers/media/i2c/m5mols/Kconfig b/drivers/media/i2c/m5mols/Kconfig
new file mode 100644
index 0000000..dc8c250
--- /dev/null
+++ b/drivers/media/i2c/m5mols/Kconfig
@@ -0,0 +1,6 @@
+config VIDEO_M5MOLS
+	tristate "Fujitsu M-5MOLS 8MP sensor support"
+	depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
+	depends on MEDIA_CAMERA_SUPPORT
+	---help---
+	  This driver supports Fujitsu M-5MOLS camera sensor with ISP
diff --git a/drivers/media/i2c/m5mols/Makefile b/drivers/media/i2c/m5mols/Makefile
new file mode 100644
index 0000000..0a44e02
--- /dev/null
+++ b/drivers/media/i2c/m5mols/Makefile
@@ -0,0 +1,3 @@
+m5mols-objs	:= m5mols_core.o m5mols_controls.o m5mols_capture.o
+
+obj-$(CONFIG_VIDEO_M5MOLS)		+= m5mols.o
diff --git a/drivers/media/i2c/m5mols/m5mols.h b/drivers/media/i2c/m5mols/m5mols.h
new file mode 100644
index 0000000..527e7b2
--- /dev/null
+++ b/drivers/media/i2c/m5mols/m5mols.h
@@ -0,0 +1,334 @@
+/*
+ * Header for M-5MOLS 8M Pixel camera sensor with ISP
+ *
+ * Copyright (C) 2011 Samsung Electronics Co., Ltd.
+ * Author: HeungJun Kim <riverful.kim@samsung.com>
+ *
+ * Copyright (C) 2009 Samsung Electronics Co., Ltd.
+ * Author: Dongsoo Nathaniel Kim <dongsoo45.kim@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef M5MOLS_H
+#define M5MOLS_H
+
+#include <media/v4l2-subdev.h>
+#include "m5mols_reg.h"
+
+extern int m5mols_debug;
+
+enum m5mols_restype {
+	M5MOLS_RESTYPE_MONITOR,
+	M5MOLS_RESTYPE_CAPTURE,
+	M5MOLS_RESTYPE_MAX,
+};
+
+/**
+ * struct m5mols_resolution - structure for the resolution
+ * @type: resolution type according to the pixel code
+ * @width: width of the resolution
+ * @height: height of the resolution
+ * @reg: resolution preset register value
+ */
+struct m5mols_resolution {
+	u8 reg;
+	enum m5mols_restype type;
+	u16 width;
+	u16 height;
+};
+
+/**
+ * struct m5mols_exif - structure for the EXIF information of M-5MOLS
+ * @exposure_time: exposure time register value
+ * @shutter_speed: speed of the shutter register value
+ * @aperture: aperture register value
+ * @exposure_bias: it calls also EV bias
+ * @iso_speed: ISO register value
+ * @flash: status register value of the flash
+ * @sdr: status register value of the Subject Distance Range
+ * @qval: not written exact meaning in document
+ */
+struct m5mols_exif {
+	u32 exposure_time;
+	u32 shutter_speed;
+	u32 aperture;
+	u32 brightness;
+	u32 exposure_bias;
+	u16 iso_speed;
+	u16 flash;
+	u16 sdr;
+	u16 qval;
+};
+
+/**
+ * struct m5mols_capture - Structure for the capture capability
+ * @exif: EXIF information
+ * @main: size in bytes of the main image
+ * @thumb: size in bytes of the thumb image, if it was accompanied
+ * @total: total size in bytes of the produced image
+ */
+struct m5mols_capture {
+	struct m5mols_exif exif;
+	u32 main;
+	u32 thumb;
+	u32 total;
+};
+
+/**
+ * struct m5mols_scenemode - structure for the scenemode capability
+ * @metering: metering light register value
+ * @ev_bias: EV bias register value
+ * @wb_mode: mode which means the WhiteBalance is Auto or Manual
+ * @wb_preset: whitebalance preset register value in the Manual mode
+ * @chroma_en: register value whether the Chroma capability is enabled or not
+ * @chroma_lvl: chroma's level register value
+ * @edge_en: register value Whether the Edge capability is enabled or not
+ * @edge_lvl: edge's level register value
+ * @af_range: Auto Focus's range
+ * @fd_mode: Face Detection mode
+ * @mcc: Multi-axis Color Conversion which means emotion color
+ * @light: status of the Light
+ * @flash: status of the Flash
+ * @tone: Tone color which means Contrast
+ * @iso: ISO register value
+ * @capt_mode: Mode of the Image Stabilization while the camera capturing
+ * @wdr: Wide Dynamic Range register value
+ *
+ * The each value according to each scenemode is recommended in the documents.
+ */
+struct m5mols_scenemode {
+	u8 metering;
+	u8 ev_bias;
+	u8 wb_mode;
+	u8 wb_preset;
+	u8 chroma_en;
+	u8 chroma_lvl;
+	u8 edge_en;
+	u8 edge_lvl;
+	u8 af_range;
+	u8 fd_mode;
+	u8 mcc;
+	u8 light;
+	u8 flash;
+	u8 tone;
+	u8 iso;
+	u8 capt_mode;
+	u8 wdr;
+};
+
+/**
+ * struct m5mols_version - firmware version information
+ * @customer:	customer information
+ * @project:	version of project information according to customer
+ * @fw:		firmware revision
+ * @hw:		hardware revision
+ * @param:	version of the parameter
+ * @awb:	Auto WhiteBalance algorithm version
+ * @str:	information about manufacturer and packaging vendor
+ * @af:		Auto Focus version
+ *
+ * The register offset starts the customer version at 0x0, and it ends
+ * the awb version at 0x09. The customer, project information occupies 1 bytes
+ * each. And also the fw, hw, param, awb each requires 2 bytes. The str is
+ * unique string associated with firmware's version. It includes information
+ * about manufacturer and the vendor of the sensor's packaging. The least
+ * significant 2 bytes of the string indicate packaging manufacturer.
+ */
+#define VERSION_STRING_SIZE	22
+struct m5mols_version {
+	u8	customer;
+	u8	project;
+	u16	fw;
+	u16	hw;
+	u16	param;
+	u16	awb;
+	u8	str[VERSION_STRING_SIZE];
+	u8	af;
+};
+
+/**
+ * struct m5mols_info - M-5MOLS driver data structure
+ * @pdata: platform data
+ * @sd: v4l-subdev instance
+ * @pad: media pad
+ * @ffmt: current fmt according to resolution type
+ * @res_type: current resolution type
+ * @irq_waitq: waitqueue for the capture
+ * @irq_done: set to 1 in the interrupt handler
+ * @handle: control handler
+ * @auto_exposure: auto/manual exposure control
+ * @exposure_bias: exposure compensation control
+ * @exposure: manual exposure control
+ * @metering: exposure metering control
+ * @auto_iso: auto/manual ISO sensitivity control
+ * @iso: manual ISO sensitivity control
+ * @auto_wb: auto white balance control
+ * @lock_3a: 3A lock control
+ * @colorfx: color effect control
+ * @saturation: saturation control
+ * @zoom: zoom control
+ * @wdr: wide dynamic range control
+ * @stabilization: image stabilization control
+ * @jpeg_quality: JPEG compression quality control
+ * @ver: information of the version
+ * @cap: the capture mode attributes
+ * @isp_ready: 1 when the ISP controller has completed booting
+ * @power: current sensor's power status
+ * @ctrl_sync: 1 when the control handler state is restored in H/W
+ * @resolution:	register value for current resolution
+ * @mode: register value for current operation mode
+ * @set_power: optional power callback to the board code
+ */
+struct m5mols_info {
+	const struct m5mols_platform_data *pdata;
+	struct v4l2_subdev sd;
+	struct media_pad pad;
+	struct v4l2_mbus_framefmt ffmt[M5MOLS_RESTYPE_MAX];
+	int res_type;
+
+	wait_queue_head_t irq_waitq;
+	atomic_t irq_done;
+
+	struct v4l2_ctrl_handler handle;
+	struct {
+		/* exposure/exposure bias/auto exposure cluster */
+		struct v4l2_ctrl *auto_exposure;
+		struct v4l2_ctrl *exposure_bias;
+		struct v4l2_ctrl *exposure;
+		struct v4l2_ctrl *metering;
+	};
+	struct {
+		/* iso/auto iso cluster */
+		struct v4l2_ctrl *auto_iso;
+		struct v4l2_ctrl *iso;
+	};
+	struct v4l2_ctrl *auto_wb;
+
+	struct v4l2_ctrl *lock_3a;
+	struct v4l2_ctrl *colorfx;
+	struct v4l2_ctrl *saturation;
+	struct v4l2_ctrl *zoom;
+	struct v4l2_ctrl *wdr;
+	struct v4l2_ctrl *stabilization;
+	struct v4l2_ctrl *jpeg_quality;
+
+	struct m5mols_version ver;
+	struct m5mols_capture cap;
+
+	unsigned int isp_ready:1;
+	unsigned int power:1;
+	unsigned int ctrl_sync:1;
+
+	u8 resolution;
+	u8 mode;
+
+	int (*set_power)(struct device *dev, int on);
+};
+
+#define is_available_af(__info)	(__info->ver.af)
+#define is_code(__code, __type) (__code == m5mols_default_ffmt[__type].code)
+#define is_manufacturer(__info, __manufacturer)	\
+				(__info->ver.str[0] == __manufacturer[0] && \
+				 __info->ver.str[1] == __manufacturer[1])
+/*
+ * I2C operation of the M-5MOLS
+ *
+ * The I2C read operation of the M-5MOLS requires 2 messages. The first
+ * message sends the information about the command, command category, and total
+ * message size. The second message is used to retrieve the data specifed in
+ * the first message
+ *
+ *   1st message                                2nd message
+ *   +-------+---+----------+-----+-------+     +------+------+------+------+
+ *   | size1 | R | category | cmd | size2 |     | d[0] | d[1] | d[2] | d[3] |
+ *   +-------+---+----------+-----+-------+     +------+------+------+------+
+ *   - size1: message data size(5 in this case)
+ *   - size2: desired buffer size of the 2nd message
+ *   - d[0..3]: according to size2
+ *
+ * The I2C write operation needs just one message. The message includes
+ * category, command, total size, and desired data.
+ *
+ *   1st message
+ *   +-------+---+----------+-----+------+------+------+------+
+ *   | size1 | W | category | cmd | d[0] | d[1] | d[2] | d[3] |
+ *   +-------+---+----------+-----+------+------+------+------+
+ *   - d[0..3]: according to size1
+ */
+int m5mols_read_u8(struct v4l2_subdev *sd, u32 reg_comb, u8 *val);
+int m5mols_read_u16(struct v4l2_subdev *sd, u32 reg_comb, u16 *val);
+int m5mols_read_u32(struct v4l2_subdev *sd, u32 reg_comb, u32 *val);
+int m5mols_write(struct v4l2_subdev *sd, u32 reg_comb, u32 val);
+
+int m5mols_busy_wait(struct v4l2_subdev *sd, u32 reg, u32 value, u32 mask,
+		     int timeout);
+
+/* Mask value for busy waiting until M-5MOLS I2C interface is initialized */
+#define M5MOLS_I2C_RDY_WAIT_FL		(1 << 16)
+/* ISP state transition timeout, in ms */
+#define M5MOLS_MODE_CHANGE_TIMEOUT	200
+#define M5MOLS_BUSY_WAIT_DEF_TIMEOUT	250
+
+/*
+ * Mode operation of the M-5MOLS
+ *
+ * Changing the mode of the M-5MOLS is needed right executing order.
+ * There are three modes(PARAMETER, MONITOR, CAPTURE) which can be changed
+ * by user. There are various categories associated with each mode.
+ *
+ * +============================================================+
+ * | mode	| category					|
+ * +============================================================+
+ * | FLASH	| FLASH(only after Stand-by or Power-on)	|
+ * | SYSTEM	| SYSTEM(only after sensor arm-booting)		|
+ * | PARAMETER	| PARAMETER					|
+ * | MONITOR	| MONITOR(preview), Auto Focus, Face Detection	|
+ * | CAPTURE	| Single CAPTURE, Preview(recording)		|
+ * +============================================================+
+ *
+ * The available executing order between each modes are as follows:
+ *   PARAMETER <---> MONITOR <---> CAPTURE
+ */
+int m5mols_set_mode(struct m5mols_info *info, u8 mode);
+
+int m5mols_enable_interrupt(struct v4l2_subdev *sd, u8 reg);
+int m5mols_wait_interrupt(struct v4l2_subdev *sd, u8 condition, u32 timeout);
+int m5mols_restore_controls(struct m5mols_info *info);
+int m5mols_start_capture(struct m5mols_info *info);
+int m5mols_do_scenemode(struct m5mols_info *info, u8 mode);
+int m5mols_lock_3a(struct m5mols_info *info, bool lock);
+int m5mols_set_ctrl(struct v4l2_ctrl *ctrl);
+int m5mols_init_controls(struct v4l2_subdev *sd);
+
+/* The firmware function */
+int m5mols_update_fw(struct v4l2_subdev *sd,
+		     int (*set_power)(struct m5mols_info *, bool));
+
+static inline struct m5mols_info *to_m5mols(struct v4l2_subdev *subdev)
+{
+	return container_of(subdev, struct m5mols_info, sd);
+}
+
+static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
+{
+	struct m5mols_info *info = container_of(ctrl->handler,
+						struct m5mols_info, handle);
+	return &info->sd;
+}
+
+static inline void m5mols_set_ctrl_mode(struct v4l2_ctrl *ctrl,
+					unsigned int mode)
+{
+	ctrl->priv = (void *)(uintptr_t)mode;
+}
+
+static inline unsigned int m5mols_get_ctrl_mode(struct v4l2_ctrl *ctrl)
+{
+	return (unsigned int)(uintptr_t)ctrl->priv;
+}
+
+#endif	/* M5MOLS_H */
diff --git a/drivers/media/i2c/m5mols/m5mols_capture.c b/drivers/media/i2c/m5mols/m5mols_capture.c
new file mode 100644
index 0000000..cb243bd
--- /dev/null
+++ b/drivers/media/i2c/m5mols/m5mols_capture.c
@@ -0,0 +1,155 @@
+
+/*
+ * The Capture code for Fujitsu M-5MOLS ISP
+ *
+ * Copyright (C) 2011 Samsung Electronics Co., Ltd.
+ * Author: HeungJun Kim <riverful.kim@samsung.com>
+ *
+ * Copyright (C) 2009 Samsung Electronics Co., Ltd.
+ * Author: Dongsoo Nathaniel Kim <dongsoo45.kim@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/regulator/consumer.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+#include <media/m5mols.h>
+#include <media/s5p_fimc.h>
+
+#include "m5mols.h"
+#include "m5mols_reg.h"
+
+/**
+ * m5mols_read_rational - I2C read of a rational number
+ *
+ * Read numerator and denominator from registers @addr_num and @addr_den
+ * respectively and return the division result in @val.
+ */
+static int m5mols_read_rational(struct v4l2_subdev *sd, u32 addr_num,
+				u32 addr_den, u32 *val)
+{
+	u32 num, den;
+
+	int ret = m5mols_read_u32(sd, addr_num, &num);
+	if (!ret)
+		ret = m5mols_read_u32(sd, addr_den, &den);
+	if (ret)
+		return ret;
+	*val = den == 0 ? 0 : num / den;
+	return ret;
+}
+
+/**
+ * m5mols_capture_info - Gather captured image information
+ *
+ * For now it gathers only EXIF information and file size.
+ */
+static int m5mols_capture_info(struct m5mols_info *info)
+{
+	struct m5mols_exif *exif = &info->cap.exif;
+	struct v4l2_subdev *sd = &info->sd;
+	int ret;
+
+	ret = m5mols_read_rational(sd, EXIF_INFO_EXPTIME_NU,
+				   EXIF_INFO_EXPTIME_DE, &exif->exposure_time);
+	if (ret)
+		return ret;
+	ret = m5mols_read_rational(sd, EXIF_INFO_TV_NU, EXIF_INFO_TV_DE,
+				   &exif->shutter_speed);
+	if (ret)
+		return ret;
+	ret = m5mols_read_rational(sd, EXIF_INFO_AV_NU, EXIF_INFO_AV_DE,
+				   &exif->aperture);
+	if (ret)
+		return ret;
+	ret = m5mols_read_rational(sd, EXIF_INFO_BV_NU, EXIF_INFO_BV_DE,
+				   &exif->brightness);
+	if (ret)
+		return ret;
+	ret = m5mols_read_rational(sd, EXIF_INFO_EBV_NU, EXIF_INFO_EBV_DE,
+				   &exif->exposure_bias);
+	if (ret)
+		return ret;
+
+	ret = m5mols_read_u16(sd, EXIF_INFO_ISO, &exif->iso_speed);
+	if (!ret)
+		ret = m5mols_read_u16(sd, EXIF_INFO_FLASH, &exif->flash);
+	if (!ret)
+		ret = m5mols_read_u16(sd, EXIF_INFO_SDR, &exif->sdr);
+	if (!ret)
+		ret = m5mols_read_u16(sd, EXIF_INFO_QVAL, &exif->qval);
+	if (ret)
+		return ret;
+
+	if (!ret)
+		ret = m5mols_read_u32(sd, CAPC_IMAGE_SIZE, &info->cap.main);
+	if (!ret)
+		ret = m5mols_read_u32(sd, CAPC_THUMB_SIZE, &info->cap.thumb);
+	if (!ret)
+		info->cap.total = info->cap.main + info->cap.thumb;
+
+	return ret;
+}
+
+int m5mols_start_capture(struct m5mols_info *info)
+{
+	struct v4l2_subdev *sd = &info->sd;
+	int ret;
+
+	/*
+	 * Synchronize the controls, set the capture frame resolution and color
+	 * format. The frame capture is initiated during switching from Monitor
+	 * to Capture mode.
+	 */
+	ret = m5mols_set_mode(info, REG_MONITOR);
+	if (!ret)
+		ret = m5mols_restore_controls(info);
+	if (!ret)
+		ret = m5mols_write(sd, CAPP_YUVOUT_MAIN, REG_JPEG);
+	if (!ret)
+		ret = m5mols_write(sd, CAPP_MAIN_IMAGE_SIZE, info->resolution);
+	if (!ret)
+		ret = m5mols_set_mode(info, REG_CAPTURE);
+	if (!ret)
+		/* Wait until a frame is captured to ISP internal memory */
+		ret = m5mols_wait_interrupt(sd, REG_INT_CAPTURE, 2000);
+	if (ret)
+		return ret;
+
+	/*
+	 * Initiate the captured data transfer to a MIPI-CSI receiver.
+	 */
+	ret = m5mols_write(sd, CAPC_SEL_FRAME, 1);
+	if (!ret)
+		ret = m5mols_write(sd, CAPC_START, REG_CAP_START_MAIN);
+	if (!ret) {
+		bool captured = false;
+		unsigned int size;
+
+		/* Wait for the capture completion interrupt */
+		ret = m5mols_wait_interrupt(sd, REG_INT_CAPTURE, 2000);
+		if (!ret) {
+			captured = true;
+			ret = m5mols_capture_info(info);
+		}
+		size = captured ? info->cap.main : 0;
+		v4l2_dbg(1, m5mols_debug, sd, "%s: size: %d, thumb.: %d B\n",
+			 __func__, size, info->cap.thumb);
+
+		v4l2_subdev_notify(sd, S5P_FIMC_TX_END_NOTIFY, &size);
+	}
+
+	return ret;
+}
diff --git a/drivers/media/i2c/m5mols/m5mols_controls.c b/drivers/media/i2c/m5mols/m5mols_controls.c
new file mode 100644
index 0000000..f34429e
--- /dev/null
+++ b/drivers/media/i2c/m5mols/m5mols_controls.c
@@ -0,0 +1,628 @@
+/*
+ * Controls for M-5MOLS 8M Pixel camera sensor with ISP
+ *
+ * Copyright (C) 2011 Samsung Electronics Co., Ltd.
+ * Author: HeungJun Kim <riverful.kim@samsung.com>
+ *
+ * Copyright (C) 2009 Samsung Electronics Co., Ltd.
+ * Author: Dongsoo Nathaniel Kim <dongsoo45.kim@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-ctrls.h>
+
+#include "m5mols.h"
+#include "m5mols_reg.h"
+
+static struct m5mols_scenemode m5mols_default_scenemode[] = {
+	[REG_SCENE_NORMAL] = {
+		REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
+		REG_CHROMA_ON, 3, REG_EDGE_ON, 5,
+		REG_AF_NORMAL, REG_FD_OFF,
+		REG_MCC_NORMAL, REG_LIGHT_OFF, REG_FLASH_OFF,
+		5, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,
+	},
+	[REG_SCENE_PORTRAIT] = {
+		REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
+		REG_CHROMA_ON, 3, REG_EDGE_ON, 4,
+		REG_AF_NORMAL, BIT_FD_EN | BIT_FD_DRAW_FACE_FRAME,
+		REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
+		6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,
+	},
+	[REG_SCENE_LANDSCAPE] = {
+		REG_AE_ALL, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
+		REG_CHROMA_ON, 4, REG_EDGE_ON, 6,
+		REG_AF_NORMAL, REG_FD_OFF,
+		REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
+		6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,
+	},
+	[REG_SCENE_SPORTS] = {
+		REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
+		REG_CHROMA_ON, 3, REG_EDGE_ON, 5,
+		REG_AF_NORMAL, REG_FD_OFF,
+		REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
+		6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,
+	},
+	[REG_SCENE_PARTY_INDOOR] = {
+		REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
+		REG_CHROMA_ON, 4, REG_EDGE_ON, 5,
+		REG_AF_NORMAL, REG_FD_OFF,
+		REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
+		6, REG_ISO_200, REG_CAP_NONE, REG_WDR_OFF,
+	},
+	[REG_SCENE_BEACH_SNOW] = {
+		REG_AE_CENTER, REG_AE_INDEX_10_POS, REG_AWB_AUTO, 0,
+		REG_CHROMA_ON, 4, REG_EDGE_ON, 5,
+		REG_AF_NORMAL, REG_FD_OFF,
+		REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
+		6, REG_ISO_50, REG_CAP_NONE, REG_WDR_OFF,
+	},
+	[REG_SCENE_SUNSET] = {
+		REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_PRESET,
+		REG_AWB_DAYLIGHT,
+		REG_CHROMA_ON, 3, REG_EDGE_ON, 5,
+		REG_AF_NORMAL, REG_FD_OFF,
+		REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
+		6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,
+	},
+	[REG_SCENE_DAWN_DUSK] = {
+		REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_PRESET,
+		REG_AWB_FLUORESCENT_1,
+		REG_CHROMA_ON, 3, REG_EDGE_ON, 5,
+		REG_AF_NORMAL, REG_FD_OFF,
+		REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
+		6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,
+	},
+	[REG_SCENE_FALL] = {
+		REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
+		REG_CHROMA_ON, 5, REG_EDGE_ON, 5,
+		REG_AF_NORMAL, REG_FD_OFF,
+		REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
+		6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,
+	},
+	[REG_SCENE_NIGHT] = {
+		REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
+		REG_CHROMA_ON, 3, REG_EDGE_ON, 5,
+		REG_AF_NORMAL, REG_FD_OFF,
+		REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
+		6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,
+	},
+	[REG_SCENE_AGAINST_LIGHT] = {
+		REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
+		REG_CHROMA_ON, 3, REG_EDGE_ON, 5,
+		REG_AF_NORMAL, REG_FD_OFF,
+		REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
+		6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,
+	},
+	[REG_SCENE_FIRE] = {
+		REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
+		REG_CHROMA_ON, 3, REG_EDGE_ON, 5,
+		REG_AF_NORMAL, REG_FD_OFF,
+		REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
+		6, REG_ISO_50, REG_CAP_NONE, REG_WDR_OFF,
+	},
+	[REG_SCENE_TEXT] = {
+		REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
+		REG_CHROMA_ON, 3, REG_EDGE_ON, 7,
+		REG_AF_MACRO, REG_FD_OFF,
+		REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
+		6, REG_ISO_AUTO, REG_CAP_ANTI_SHAKE, REG_WDR_ON,
+	},
+	[REG_SCENE_CANDLE] = {
+		REG_AE_CENTER, REG_AE_INDEX_00, REG_AWB_AUTO, 0,
+		REG_CHROMA_ON, 3, REG_EDGE_ON, 5,
+		REG_AF_NORMAL, REG_FD_OFF,
+		REG_MCC_OFF, REG_LIGHT_OFF, REG_FLASH_OFF,
+		6, REG_ISO_AUTO, REG_CAP_NONE, REG_WDR_OFF,
+	},
+};
+
+/**
+ * m5mols_do_scenemode() - Change current scenemode
+ * @mode:	Desired mode of the scenemode
+ *
+ * WARNING: The execution order is important. Do not change the order.
+ */
+int m5mols_do_scenemode(struct m5mols_info *info, u8 mode)
+{
+	struct v4l2_subdev *sd = &info->sd;
+	struct m5mols_scenemode scenemode = m5mols_default_scenemode[mode];
+	int ret;
+
+	if (mode > REG_SCENE_CANDLE)
+		return -EINVAL;
+
+	ret = v4l2_ctrl_s_ctrl(info->lock_3a, 0);
+	if (!ret)
+		ret = m5mols_write(sd, AE_EV_PRESET_MONITOR, mode);
+	if (!ret)
+		ret = m5mols_write(sd, AE_EV_PRESET_CAPTURE, mode);
+	if (!ret)
+		ret = m5mols_write(sd, AE_MODE, scenemode.metering);
+	if (!ret)
+		ret = m5mols_write(sd, AE_INDEX, scenemode.ev_bias);
+	if (!ret)
+		ret = m5mols_write(sd, AWB_MODE, scenemode.wb_mode);
+	if (!ret)
+		ret = m5mols_write(sd, AWB_MANUAL, scenemode.wb_preset);
+	if (!ret)
+		ret = m5mols_write(sd, MON_CHROMA_EN, scenemode.chroma_en);
+	if (!ret)
+		ret = m5mols_write(sd, MON_CHROMA_LVL, scenemode.chroma_lvl);
+	if (!ret)
+		ret = m5mols_write(sd, MON_EDGE_EN, scenemode.edge_en);
+	if (!ret)
+		ret = m5mols_write(sd, MON_EDGE_LVL, scenemode.edge_lvl);
+	if (!ret && is_available_af(info))
+		ret = m5mols_write(sd, AF_MODE, scenemode.af_range);
+	if (!ret && is_available_af(info))
+		ret = m5mols_write(sd, FD_CTL, scenemode.fd_mode);
+	if (!ret)
+		ret = m5mols_write(sd, MON_TONE_CTL, scenemode.tone);
+	if (!ret)
+		ret = m5mols_write(sd, AE_ISO, scenemode.iso);
+	if (!ret)
+		ret = m5mols_set_mode(info, REG_CAPTURE);
+	if (!ret)
+		ret = m5mols_write(sd, CAPP_WDR_EN, scenemode.wdr);
+	if (!ret)
+		ret = m5mols_write(sd, CAPP_MCC_MODE, scenemode.mcc);
+	if (!ret)
+		ret = m5mols_write(sd, CAPP_LIGHT_CTRL, scenemode.light);
+	if (!ret)
+		ret = m5mols_write(sd, CAPP_FLASH_CTRL, scenemode.flash);
+	if (!ret)
+		ret = m5mols_write(sd, CAPC_MODE, scenemode.capt_mode);
+	if (!ret)
+		ret = m5mols_set_mode(info, REG_MONITOR);
+
+	return ret;
+}
+
+static int m5mols_3a_lock(struct m5mols_info *info, struct v4l2_ctrl *ctrl)
+{
+	bool af_lock = ctrl->val & V4L2_LOCK_FOCUS;
+	int ret = 0;
+
+	if ((ctrl->val ^ ctrl->cur.val) & V4L2_LOCK_EXPOSURE) {
+		bool ae_lock = ctrl->val & V4L2_LOCK_EXPOSURE;
+
+		ret = m5mols_write(&info->sd, AE_LOCK, ae_lock ?
+				   REG_AE_LOCK : REG_AE_UNLOCK);
+		if (ret)
+			return ret;
+	}
+
+	if (((ctrl->val ^ ctrl->cur.val) & V4L2_LOCK_WHITE_BALANCE)
+	    && info->auto_wb->val) {
+		bool awb_lock = ctrl->val & V4L2_LOCK_WHITE_BALANCE;
+
+		ret = m5mols_write(&info->sd, AWB_LOCK, awb_lock ?
+				   REG_AWB_LOCK : REG_AWB_UNLOCK);
+		if (ret)
+			return ret;
+	}
+
+	if (!info->ver.af || !af_lock)
+		return ret;
+
+	if ((ctrl->val ^ ctrl->cur.val) & V4L2_LOCK_FOCUS)
+		ret = m5mols_write(&info->sd, AF_EXECUTE, REG_AF_STOP);
+
+	return ret;
+}
+
+static int m5mols_set_metering_mode(struct m5mols_info *info, int mode)
+{
+	unsigned int metering;
+
+	switch (mode) {
+	case V4L2_EXPOSURE_METERING_CENTER_WEIGHTED:
+		metering = REG_AE_CENTER;
+		break;
+	case V4L2_EXPOSURE_METERING_SPOT:
+		metering = REG_AE_SPOT;
+		break;
+	default:
+		metering = REG_AE_ALL;
+		break;
+	}
+
+	return m5mols_write(&info->sd, AE_MODE, metering);
+}
+
+static int m5mols_set_exposure(struct m5mols_info *info, int exposure)
+{
+	struct v4l2_subdev *sd = &info->sd;
+	int ret = 0;
+
+	if (exposure == V4L2_EXPOSURE_AUTO) {
+		/* Unlock auto exposure */
+		info->lock_3a->val &= ~V4L2_LOCK_EXPOSURE;
+		m5mols_3a_lock(info, info->lock_3a);
+
+		ret = m5mols_set_metering_mode(info, info->metering->val);
+		if (ret < 0)
+			return ret;
+
+		v4l2_dbg(1, m5mols_debug, sd,
+			 "%s: exposure bias: %#x, metering: %#x\n",
+			 __func__, info->exposure_bias->val,
+			 info->metering->val);
+
+		return m5mols_write(sd, AE_INDEX, info->exposure_bias->val);
+	}
+
+	if (exposure == V4L2_EXPOSURE_MANUAL) {
+		ret = m5mols_write(sd, AE_MODE, REG_AE_OFF);
+		if (ret == 0)
+			ret = m5mols_write(sd, AE_MAN_GAIN_MON,
+					   info->exposure->val);
+		if (ret == 0)
+			ret = m5mols_write(sd, AE_MAN_GAIN_CAP,
+					   info->exposure->val);
+
+		v4l2_dbg(1, m5mols_debug, sd, "%s: exposure: %#x\n",
+			 __func__, info->exposure->val);
+	}
+
+	return ret;
+}
+
+static int m5mols_set_white_balance(struct m5mols_info *info, int val)
+{
+	static const unsigned short wb[][2] = {
+		{ V4L2_WHITE_BALANCE_INCANDESCENT,  REG_AWB_INCANDESCENT },
+		{ V4L2_WHITE_BALANCE_FLUORESCENT,   REG_AWB_FLUORESCENT_1 },
+		{ V4L2_WHITE_BALANCE_FLUORESCENT_H, REG_AWB_FLUORESCENT_2 },
+		{ V4L2_WHITE_BALANCE_HORIZON,       REG_AWB_HORIZON },
+		{ V4L2_WHITE_BALANCE_DAYLIGHT,      REG_AWB_DAYLIGHT },
+		{ V4L2_WHITE_BALANCE_FLASH,         REG_AWB_LEDLIGHT },
+		{ V4L2_WHITE_BALANCE_CLOUDY,        REG_AWB_CLOUDY },
+		{ V4L2_WHITE_BALANCE_SHADE,         REG_AWB_SHADE },
+		{ V4L2_WHITE_BALANCE_AUTO,          REG_AWB_AUTO },
+	};
+	int i;
+	struct v4l2_subdev *sd = &info->sd;
+	int ret = -EINVAL;
+
+	for (i = 0; i < ARRAY_SIZE(wb); i++) {
+		int awb;
+		if (wb[i][0] != val)
+			continue;
+
+		v4l2_dbg(1, m5mols_debug, sd,
+			 "Setting white balance to: %#x\n", wb[i][0]);
+
+		awb = wb[i][0] == V4L2_WHITE_BALANCE_AUTO;
+		ret = m5mols_write(sd, AWB_MODE, awb ? REG_AWB_AUTO :
+						 REG_AWB_PRESET);
+		if (ret < 0)
+			return ret;
+
+		if (!awb)
+			ret = m5mols_write(sd, AWB_MANUAL, wb[i][1]);
+	}
+
+	return ret;
+}
+
+static int m5mols_set_saturation(struct m5mols_info *info, int val)
+{
+	int ret = m5mols_write(&info->sd, MON_CHROMA_LVL, val);
+	if (ret < 0)
+		return ret;
+
+	return m5mols_write(&info->sd, MON_CHROMA_EN, REG_CHROMA_ON);
+}
+
+static int m5mols_set_color_effect(struct m5mols_info *info, int val)
+{
+	unsigned int m_effect = REG_COLOR_EFFECT_OFF;
+	unsigned int p_effect = REG_EFFECT_OFF;
+	unsigned int cfix_r = 0, cfix_b = 0;
+	struct v4l2_subdev *sd = &info->sd;
+	int ret = 0;
+
+	switch (val) {
+	case V4L2_COLORFX_BW:
+		m_effect = REG_COLOR_EFFECT_ON;
+		break;
+	case V4L2_COLORFX_NEGATIVE:
+		p_effect = REG_EFFECT_NEGA;
+		break;
+	case V4L2_COLORFX_EMBOSS:
+		p_effect = REG_EFFECT_EMBOSS;
+		break;
+	case V4L2_COLORFX_SEPIA:
+		m_effect = REG_COLOR_EFFECT_ON;
+		cfix_r = REG_CFIXR_SEPIA;
+		cfix_b = REG_CFIXB_SEPIA;
+		break;
+	}
+
+	ret = m5mols_write(sd, PARM_EFFECT, p_effect);
+	if (!ret)
+		ret = m5mols_write(sd, MON_EFFECT, m_effect);
+
+	if (ret == 0 && m_effect == REG_COLOR_EFFECT_ON) {
+		ret = m5mols_write(sd, MON_CFIXR, cfix_r);
+		if (!ret)
+			ret = m5mols_write(sd, MON_CFIXB, cfix_b);
+	}
+
+	v4l2_dbg(1, m5mols_debug, sd,
+		 "p_effect: %#x, m_effect: %#x, r: %#x, b: %#x (%d)\n",
+		 p_effect, m_effect, cfix_r, cfix_b, ret);
+
+	return ret;
+}
+
+static int m5mols_set_iso(struct m5mols_info *info, int auto_iso)
+{
+	u32 iso = auto_iso ? 0 : info->iso->val + 1;
+
+	return m5mols_write(&info->sd, AE_ISO, iso);
+}
+
+static int m5mols_set_wdr(struct m5mols_info *info, int wdr)
+{
+	int ret;
+
+	ret = m5mols_write(&info->sd, MON_TONE_CTL, wdr ? 9 : 5);
+	if (ret < 0)
+		return ret;
+
+	ret = m5mols_set_mode(info, REG_CAPTURE);
+	if (ret < 0)
+		return ret;
+
+	return m5mols_write(&info->sd, CAPP_WDR_EN, wdr);
+}
+
+static int m5mols_set_stabilization(struct m5mols_info *info, int val)
+{
+	struct v4l2_subdev *sd = &info->sd;
+	unsigned int evp = val ? 0xe : 0x0;
+	int ret;
+
+	ret = m5mols_write(sd, AE_EV_PRESET_MONITOR, evp);
+	if (ret < 0)
+		return ret;
+
+	return m5mols_write(sd, AE_EV_PRESET_CAPTURE, evp);
+}
+
+static int m5mols_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct v4l2_subdev *sd = to_sd(ctrl);
+	struct m5mols_info *info = to_m5mols(sd);
+	int ret = 0;
+	u8 status;
+
+	v4l2_dbg(1, m5mols_debug, sd, "%s: ctrl: %s (%d)\n",
+		 __func__, ctrl->name, info->isp_ready);
+
+	if (!info->isp_ready)
+		return -EBUSY;
+
+	switch (ctrl->id) {
+	case V4L2_CID_ISO_SENSITIVITY_AUTO:
+		ret = m5mols_read_u8(sd, AE_ISO, &status);
+		if (ret == 0)
+			ctrl->val = !status;
+		if (status != REG_ISO_AUTO)
+			info->iso->val = status - 1;
+		break;
+
+	case V4L2_CID_3A_LOCK:
+		ctrl->val &= ~0x7;
+
+		ret = m5mols_read_u8(sd, AE_LOCK, &status);
+		if (ret)
+			return ret;
+		if (status)
+			info->lock_3a->val |= V4L2_LOCK_EXPOSURE;
+
+		ret = m5mols_read_u8(sd, AWB_LOCK, &status);
+		if (ret)
+			return ret;
+		if (status)
+			info->lock_3a->val |= V4L2_LOCK_EXPOSURE;
+
+		ret = m5mols_read_u8(sd, AF_EXECUTE, &status);
+		if (!status)
+			info->lock_3a->val |= V4L2_LOCK_EXPOSURE;
+		break;
+	}
+
+	return ret;
+}
+
+static int m5mols_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	unsigned int ctrl_mode = m5mols_get_ctrl_mode(ctrl);
+	struct v4l2_subdev *sd = to_sd(ctrl);
+	struct m5mols_info *info = to_m5mols(sd);
+	int last_mode = info->mode;
+	int ret = 0;
+
+	/*
+	 * If needed, defer restoring the controls until
+	 * the device is fully initialized.
+	 */
+	if (!info->isp_ready) {
+		info->ctrl_sync = 0;
+		return 0;
+	}
+
+	v4l2_dbg(1, m5mols_debug, sd, "%s: %s, val: %d, priv: %p\n",
+		 __func__, ctrl->name, ctrl->val, ctrl->priv);
+
+	if (ctrl_mode && ctrl_mode != info->mode) {
+		ret = m5mols_set_mode(info, ctrl_mode);
+		if (ret < 0)
+			return ret;
+	}
+
+	switch (ctrl->id) {
+	case V4L2_CID_3A_LOCK:
+		ret = m5mols_3a_lock(info, ctrl);
+		break;
+
+	case V4L2_CID_ZOOM_ABSOLUTE:
+		ret = m5mols_write(sd, MON_ZOOM, ctrl->val);
+		break;
+
+	case V4L2_CID_EXPOSURE_AUTO:
+		ret = m5mols_set_exposure(info, ctrl->val);
+		break;
+
+	case V4L2_CID_ISO_SENSITIVITY:
+		ret = m5mols_set_iso(info, ctrl->val);
+		break;
+
+	case V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE:
+		ret = m5mols_set_white_balance(info, ctrl->val);
+		break;
+
+	case V4L2_CID_SATURATION:
+		ret = m5mols_set_saturation(info, ctrl->val);
+		break;
+
+	case V4L2_CID_COLORFX:
+		ret = m5mols_set_color_effect(info, ctrl->val);
+		break;
+
+	case V4L2_CID_WIDE_DYNAMIC_RANGE:
+		ret = m5mols_set_wdr(info, ctrl->val);
+		break;
+
+	case V4L2_CID_IMAGE_STABILIZATION:
+		ret = m5mols_set_stabilization(info, ctrl->val);
+		break;
+
+	case V4L2_CID_JPEG_COMPRESSION_QUALITY:
+		ret = m5mols_write(sd, CAPP_JPEG_RATIO, ctrl->val);
+		break;
+	}
+
+	if (ret == 0 && info->mode != last_mode)
+		ret = m5mols_set_mode(info, last_mode);
+
+	return ret;
+}
+
+static const struct v4l2_ctrl_ops m5mols_ctrl_ops = {
+	.g_volatile_ctrl	= m5mols_g_volatile_ctrl,
+	.s_ctrl			= m5mols_s_ctrl,
+};
+
+/* Supported manual ISO values */
+static const s64 iso_qmenu[] = {
+	/* AE_ISO: 0x01...0x07 (ISO: 50...3200) */
+	50000, 100000, 200000, 400000, 800000, 1600000, 3200000
+};
+
+/* Supported Exposure Bias values, -2.0EV...+2.0EV */
+static const s64 ev_bias_qmenu[] = {
+	/* AE_INDEX: 0x00...0x08 */
+	-2000, -1500, -1000, -500, 0, 500, 1000, 1500, 2000
+};
+
+int m5mols_init_controls(struct v4l2_subdev *sd)
+{
+	struct m5mols_info *info = to_m5mols(sd);
+	u16 exposure_max;
+	u16 zoom_step;
+	int ret;
+
+	/* Determine the firmware dependant control range and step values */
+	ret = m5mols_read_u16(sd, AE_MAX_GAIN_MON, &exposure_max);
+	if (ret < 0)
+		return ret;
+
+	zoom_step = is_manufacturer(info, REG_SAMSUNG_OPTICS) ? 31 : 1;
+	v4l2_ctrl_handler_init(&info->handle, 20);
+
+	info->auto_wb = v4l2_ctrl_new_std_menu(&info->handle,
+			&m5mols_ctrl_ops, V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE,
+			9, ~0x3fe, V4L2_WHITE_BALANCE_AUTO);
+
+	/* Exposure control cluster */
+	info->auto_exposure = v4l2_ctrl_new_std_menu(&info->handle,
+			&m5mols_ctrl_ops, V4L2_CID_EXPOSURE_AUTO,
+			1, ~0x03, V4L2_EXPOSURE_AUTO);
+
+	info->exposure = v4l2_ctrl_new_std(&info->handle,
+			&m5mols_ctrl_ops, V4L2_CID_EXPOSURE,
+			0, exposure_max, 1, exposure_max / 2);
+
+	info->exposure_bias = v4l2_ctrl_new_int_menu(&info->handle,
+			&m5mols_ctrl_ops, V4L2_CID_AUTO_EXPOSURE_BIAS,
+			ARRAY_SIZE(ev_bias_qmenu) - 1,
+			ARRAY_SIZE(ev_bias_qmenu)/2 - 1,
+			ev_bias_qmenu);
+
+	info->metering = v4l2_ctrl_new_std_menu(&info->handle,
+			&m5mols_ctrl_ops, V4L2_CID_EXPOSURE_METERING,
+			2, ~0x7, V4L2_EXPOSURE_METERING_AVERAGE);
+
+	/* ISO control cluster */
+	info->auto_iso = v4l2_ctrl_new_std_menu(&info->handle, &m5mols_ctrl_ops,
+			V4L2_CID_ISO_SENSITIVITY_AUTO, 1, ~0x03, 1);
+
+	info->iso = v4l2_ctrl_new_int_menu(&info->handle, &m5mols_ctrl_ops,
+			V4L2_CID_ISO_SENSITIVITY, ARRAY_SIZE(iso_qmenu) - 1,
+			ARRAY_SIZE(iso_qmenu)/2 - 1, iso_qmenu);
+
+	info->saturation = v4l2_ctrl_new_std(&info->handle, &m5mols_ctrl_ops,
+			V4L2_CID_SATURATION, 1, 5, 1, 3);
+
+	info->zoom = v4l2_ctrl_new_std(&info->handle, &m5mols_ctrl_ops,
+			V4L2_CID_ZOOM_ABSOLUTE, 1, 70, zoom_step, 1);
+
+	info->colorfx = v4l2_ctrl_new_std_menu(&info->handle, &m5mols_ctrl_ops,
+			V4L2_CID_COLORFX, 4, 0, V4L2_COLORFX_NONE);
+
+	info->wdr = v4l2_ctrl_new_std(&info->handle, &m5mols_ctrl_ops,
+			V4L2_CID_WIDE_DYNAMIC_RANGE, 0, 1, 1, 0);
+
+	info->stabilization = v4l2_ctrl_new_std(&info->handle, &m5mols_ctrl_ops,
+			V4L2_CID_IMAGE_STABILIZATION, 0, 1, 1, 0);
+
+	info->jpeg_quality = v4l2_ctrl_new_std(&info->handle, &m5mols_ctrl_ops,
+			V4L2_CID_JPEG_COMPRESSION_QUALITY, 1, 100, 1, 80);
+
+	info->lock_3a = v4l2_ctrl_new_std(&info->handle, &m5mols_ctrl_ops,
+			V4L2_CID_3A_LOCK, 0, 0x7, 0, 0);
+
+	if (info->handle.error) {
+		int ret = info->handle.error;
+		v4l2_err(sd, "Failed to initialize controls: %d\n", ret);
+		v4l2_ctrl_handler_free(&info->handle);
+		return ret;
+	}
+
+	v4l2_ctrl_auto_cluster(4, &info->auto_exposure, 1, false);
+	info->auto_iso->flags |= V4L2_CTRL_FLAG_VOLATILE |
+				V4L2_CTRL_FLAG_UPDATE;
+	v4l2_ctrl_auto_cluster(2, &info->auto_iso, 0, false);
+
+	info->lock_3a->flags |= V4L2_CTRL_FLAG_VOLATILE;
+
+	m5mols_set_ctrl_mode(info->auto_exposure, REG_PARAMETER);
+	m5mols_set_ctrl_mode(info->auto_wb, REG_PARAMETER);
+	m5mols_set_ctrl_mode(info->colorfx, REG_MONITOR);
+
+	sd->ctrl_handler = &info->handle;
+
+	return 0;
+}
diff --git a/drivers/media/i2c/m5mols/m5mols_core.c b/drivers/media/i2c/m5mols/m5mols_core.c
new file mode 100644
index 0000000..6ca6a7f
--- /dev/null
+++ b/drivers/media/i2c/m5mols/m5mols_core.c
@@ -0,0 +1,992 @@
+/*
+ * Driver for M-5MOLS 8M Pixel camera sensor with ISP
+ *
+ * Copyright (C) 2011 Samsung Electronics Co., Ltd.
+ * Author: HeungJun Kim <riverful.kim@samsung.com>
+ *
+ * Copyright (C) 2009 Samsung Electronics Co., Ltd.
+ * Author: Dongsoo Nathaniel Kim <dongsoo45.kim@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/regulator/consumer.h>
+#include <linux/videodev2.h>
+#include <linux/module.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+#include <media/m5mols.h>
+
+#include "m5mols.h"
+#include "m5mols_reg.h"
+
+int m5mols_debug;
+module_param(m5mols_debug, int, 0644);
+
+#define MODULE_NAME		"M5MOLS"
+#define M5MOLS_I2C_CHECK_RETRY	500
+
+/* The regulator consumer names for external voltage regulators */
+static struct regulator_bulk_data supplies[] = {
+	{
+		.supply = "core",	/* ARM core power, 1.2V */
+	}, {
+		.supply	= "dig_18",	/* digital power 1, 1.8V */
+	}, {
+		.supply	= "d_sensor",	/* sensor power 1, 1.8V */
+	}, {
+		.supply	= "dig_28",	/* digital power 2, 2.8V */
+	}, {
+		.supply	= "a_sensor",	/* analog power */
+	}, {
+		.supply	= "dig_12",	/* digital power 3, 1.2V */
+	},
+};
+
+static struct v4l2_mbus_framefmt m5mols_default_ffmt[M5MOLS_RESTYPE_MAX] = {
+	[M5MOLS_RESTYPE_MONITOR] = {
+		.width		= 1920,
+		.height		= 1080,
+		.code		= V4L2_MBUS_FMT_VYUY8_2X8,
+		.field		= V4L2_FIELD_NONE,
+		.colorspace	= V4L2_COLORSPACE_JPEG,
+	},
+	[M5MOLS_RESTYPE_CAPTURE] = {
+		.width		= 1920,
+		.height		= 1080,
+		.code		= V4L2_MBUS_FMT_JPEG_1X8,
+		.field		= V4L2_FIELD_NONE,
+		.colorspace	= V4L2_COLORSPACE_JPEG,
+	},
+};
+#define SIZE_DEFAULT_FFMT	ARRAY_SIZE(m5mols_default_ffmt)
+
+static const struct m5mols_resolution m5mols_reg_res[] = {
+	{ 0x01, M5MOLS_RESTYPE_MONITOR, 128, 96 },	/* SUB-QCIF */
+	{ 0x03, M5MOLS_RESTYPE_MONITOR, 160, 120 },	/* QQVGA */
+	{ 0x05, M5MOLS_RESTYPE_MONITOR, 176, 144 },	/* QCIF */
+	{ 0x06, M5MOLS_RESTYPE_MONITOR, 176, 176 },
+	{ 0x08, M5MOLS_RESTYPE_MONITOR, 240, 320 },	/* QVGA */
+	{ 0x09, M5MOLS_RESTYPE_MONITOR, 320, 240 },	/* QVGA */
+	{ 0x0c, M5MOLS_RESTYPE_MONITOR, 240, 400 },	/* WQVGA */
+	{ 0x0d, M5MOLS_RESTYPE_MONITOR, 400, 240 },	/* WQVGA */
+	{ 0x0e, M5MOLS_RESTYPE_MONITOR, 352, 288 },	/* CIF */
+	{ 0x13, M5MOLS_RESTYPE_MONITOR, 480, 360 },
+	{ 0x15, M5MOLS_RESTYPE_MONITOR, 640, 360 },	/* qHD */
+	{ 0x17, M5MOLS_RESTYPE_MONITOR, 640, 480 },	/* VGA */
+	{ 0x18, M5MOLS_RESTYPE_MONITOR, 720, 480 },
+	{ 0x1a, M5MOLS_RESTYPE_MONITOR, 800, 480 },	/* WVGA */
+	{ 0x1f, M5MOLS_RESTYPE_MONITOR, 800, 600 },	/* SVGA */
+	{ 0x21, M5MOLS_RESTYPE_MONITOR, 1280, 720 },	/* HD */
+	{ 0x25, M5MOLS_RESTYPE_MONITOR, 1920, 1080 },	/* 1080p */
+	{ 0x29, M5MOLS_RESTYPE_MONITOR, 3264, 2448 },	/* 2.63fps 8M */
+	{ 0x39, M5MOLS_RESTYPE_MONITOR, 800, 602 },	/* AHS_MON debug */
+
+	{ 0x02, M5MOLS_RESTYPE_CAPTURE, 320, 240 },	/* QVGA */
+	{ 0x04, M5MOLS_RESTYPE_CAPTURE, 400, 240 },	/* WQVGA */
+	{ 0x07, M5MOLS_RESTYPE_CAPTURE, 480, 360 },
+	{ 0x08, M5MOLS_RESTYPE_CAPTURE, 640, 360 },	/* qHD */
+	{ 0x09, M5MOLS_RESTYPE_CAPTURE, 640, 480 },	/* VGA */
+	{ 0x0a, M5MOLS_RESTYPE_CAPTURE, 800, 480 },	/* WVGA */
+	{ 0x10, M5MOLS_RESTYPE_CAPTURE, 1280, 720 },	/* HD */
+	{ 0x14, M5MOLS_RESTYPE_CAPTURE, 1280, 960 },	/* 1M */
+	{ 0x17, M5MOLS_RESTYPE_CAPTURE, 1600, 1200 },	/* 2M */
+	{ 0x19, M5MOLS_RESTYPE_CAPTURE, 1920, 1080 },	/* Full-HD */
+	{ 0x1a, M5MOLS_RESTYPE_CAPTURE, 2048, 1152 },	/* 3Mega */
+	{ 0x1b, M5MOLS_RESTYPE_CAPTURE, 2048, 1536 },
+	{ 0x1c, M5MOLS_RESTYPE_CAPTURE, 2560, 1440 },	/* 4Mega */
+	{ 0x1d, M5MOLS_RESTYPE_CAPTURE, 2560, 1536 },
+	{ 0x1f, M5MOLS_RESTYPE_CAPTURE, 2560, 1920 },	/* 5Mega */
+	{ 0x21, M5MOLS_RESTYPE_CAPTURE, 3264, 1836 },	/* 6Mega */
+	{ 0x22, M5MOLS_RESTYPE_CAPTURE, 3264, 1960 },
+	{ 0x25, M5MOLS_RESTYPE_CAPTURE, 3264, 2448 },	/* 8Mega */
+};
+
+/**
+ * m5mols_swap_byte - an byte array to integer conversion function
+ * @size: size in bytes of I2C packet defined in the M-5MOLS datasheet
+ *
+ * Convert I2C data byte array with performing any required byte
+ * reordering to assure proper values for each data type, regardless
+ * of the architecture endianness.
+ */
+static u32 m5mols_swap_byte(u8 *data, u8 length)
+{
+	if (length == 1)
+		return *data;
+	else if (length == 2)
+		return be16_to_cpu(*((u16 *)data));
+	else
+		return be32_to_cpu(*((u32 *)data));
+}
+
+/**
+ * m5mols_read -  I2C read function
+ * @reg: combination of size, category and command for the I2C packet
+ * @size: desired size of I2C packet
+ * @val: read value
+ *
+ * Returns 0 on success, or else negative errno.
+ */
+static int m5mols_read(struct v4l2_subdev *sd, u32 size, u32 reg, u32 *val)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct m5mols_info *info = to_m5mols(sd);
+	u8 rbuf[M5MOLS_I2C_MAX_SIZE + 1];
+	u8 category = I2C_CATEGORY(reg);
+	u8 cmd = I2C_COMMAND(reg);
+	struct i2c_msg msg[2];
+	u8 wbuf[5];
+	int ret;
+
+	if (!client->adapter)
+		return -ENODEV;
+
+	msg[0].addr = client->addr;
+	msg[0].flags = 0;
+	msg[0].len = 5;
+	msg[0].buf = wbuf;
+	wbuf[0] = 5;
+	wbuf[1] = M5MOLS_BYTE_READ;
+	wbuf[2] = category;
+	wbuf[3] = cmd;
+	wbuf[4] = size;
+
+	msg[1].addr = client->addr;
+	msg[1].flags = I2C_M_RD;
+	msg[1].len = size + 1;
+	msg[1].buf = rbuf;
+
+	/* minimum stabilization time */
+	usleep_range(200, 200);
+
+	ret = i2c_transfer(client->adapter, msg, 2);
+
+	if (ret == 2) {
+		*val = m5mols_swap_byte(&rbuf[1], size);
+		return 0;
+	}
+
+	if (info->isp_ready)
+		v4l2_err(sd, "read failed: size:%d cat:%02x cmd:%02x. %d\n",
+			 size, category, cmd, ret);
+
+	return ret < 0 ? ret : -EIO;
+}
+
+int m5mols_read_u8(struct v4l2_subdev *sd, u32 reg, u8 *val)
+{
+	u32 val_32;
+	int ret;
+
+	if (I2C_SIZE(reg) != 1) {
+		v4l2_err(sd, "Wrong data size\n");
+		return -EINVAL;
+	}
+
+	ret = m5mols_read(sd, I2C_SIZE(reg), reg, &val_32);
+	if (ret)
+		return ret;
+
+	*val = (u8)val_32;
+	return ret;
+}
+
+int m5mols_read_u16(struct v4l2_subdev *sd, u32 reg, u16 *val)
+{
+	u32 val_32;
+	int ret;
+
+	if (I2C_SIZE(reg) != 2) {
+		v4l2_err(sd, "Wrong data size\n");
+		return -EINVAL;
+	}
+
+	ret = m5mols_read(sd, I2C_SIZE(reg), reg, &val_32);
+	if (ret)
+		return ret;
+
+	*val = (u16)val_32;
+	return ret;
+}
+
+int m5mols_read_u32(struct v4l2_subdev *sd, u32 reg, u32 *val)
+{
+	if (I2C_SIZE(reg) != 4) {
+		v4l2_err(sd, "Wrong data size\n");
+		return -EINVAL;
+	}
+
+	return m5mols_read(sd, I2C_SIZE(reg), reg, val);
+}
+
+/**
+ * m5mols_write - I2C command write function
+ * @reg: combination of size, category and command for the I2C packet
+ * @val: value to write
+ *
+ * Returns 0 on success, or else negative errno.
+ */
+int m5mols_write(struct v4l2_subdev *sd, u32 reg, u32 val)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct m5mols_info *info = to_m5mols(sd);
+	u8 wbuf[M5MOLS_I2C_MAX_SIZE + 4];
+	u8 category = I2C_CATEGORY(reg);
+	u8 cmd = I2C_COMMAND(reg);
+	u8 size	= I2C_SIZE(reg);
+	u32 *buf = (u32 *)&wbuf[4];
+	struct i2c_msg msg[1];
+	int ret;
+
+	if (!client->adapter)
+		return -ENODEV;
+
+	if (size != 1 && size != 2 && size != 4) {
+		v4l2_err(sd, "Wrong data size\n");
+		return -EINVAL;
+	}
+
+	msg->addr = client->addr;
+	msg->flags = 0;
+	msg->len = (u16)size + 4;
+	msg->buf = wbuf;
+	wbuf[0] = size + 4;
+	wbuf[1] = M5MOLS_BYTE_WRITE;
+	wbuf[2] = category;
+	wbuf[3] = cmd;
+
+	*buf = m5mols_swap_byte((u8 *)&val, size);
+
+	usleep_range(200, 200);
+
+	ret = i2c_transfer(client->adapter, msg, 1);
+	if (ret == 1)
+		return 0;
+
+	if (info->isp_ready)
+		v4l2_err(sd, "write failed: cat:%02x cmd:%02x ret:%d\n",
+			 category, cmd, ret);
+
+	return ret < 0 ? ret : -EIO;
+}
+
+/**
+ * m5mols_busy_wait - Busy waiting with I2C register polling
+ * @reg: the I2C_REG() address of an 8-bit status register to check
+ * @value: expected status register value
+ * @mask: bit mask for the read status register value
+ * @timeout: timeout in miliseconds, or -1 for default timeout
+ *
+ * The @reg register value is ORed with @mask before comparing with @value.
+ *
+ * Return: 0 if the requested condition became true within less than
+ *         @timeout ms, or else negative errno.
+ */
+int m5mols_busy_wait(struct v4l2_subdev *sd, u32 reg, u32 value, u32 mask,
+		     int timeout)
+{
+	int ms = timeout < 0 ? M5MOLS_BUSY_WAIT_DEF_TIMEOUT : timeout;
+	unsigned long end = jiffies + msecs_to_jiffies(ms);
+	u8 status;
+
+	do {
+		int ret = m5mols_read_u8(sd, reg, &status);
+
+		if (ret < 0 && !(mask & M5MOLS_I2C_RDY_WAIT_FL))
+			return ret;
+		if (!ret && (status & mask & 0xff) == (value & 0xff))
+			return 0;
+		usleep_range(100, 250);
+	} while (ms > 0 && time_is_after_jiffies(end));
+
+	return -EBUSY;
+}
+
+/**
+ * m5mols_enable_interrupt - Clear interrupt pending bits and unmask interrupts
+ *
+ * Before writing desired interrupt value the INT_FACTOR register should
+ * be read to clear pending interrupts.
+ */
+int m5mols_enable_interrupt(struct v4l2_subdev *sd, u8 reg)
+{
+	struct m5mols_info *info = to_m5mols(sd);
+	u8 mask = is_available_af(info) ? REG_INT_AF : 0;
+	u8 dummy;
+	int ret;
+
+	ret = m5mols_read_u8(sd, SYSTEM_INT_FACTOR, &dummy);
+	if (!ret)
+		ret = m5mols_write(sd, SYSTEM_INT_ENABLE, reg & ~mask);
+	return ret;
+}
+
+int m5mols_wait_interrupt(struct v4l2_subdev *sd, u8 irq_mask, u32 timeout)
+{
+	struct m5mols_info *info = to_m5mols(sd);
+
+	int ret = wait_event_interruptible_timeout(info->irq_waitq,
+				atomic_add_unless(&info->irq_done, -1, 0),
+				msecs_to_jiffies(timeout));
+	if (ret <= 0)
+		return ret ? ret : -ETIMEDOUT;
+
+	return m5mols_busy_wait(sd, SYSTEM_INT_FACTOR, irq_mask,
+				M5MOLS_I2C_RDY_WAIT_FL | irq_mask, -1);
+}
+
+/**
+ * m5mols_reg_mode - Write the mode and check busy status
+ *
+ * It always accompanies a little delay changing the M-5MOLS mode, so it is
+ * needed checking current busy status to guarantee right mode.
+ */
+static int m5mols_reg_mode(struct v4l2_subdev *sd, u8 mode)
+{
+	int ret = m5mols_write(sd, SYSTEM_SYSMODE, mode);
+	if (ret < 0)
+		return ret;
+	return m5mols_busy_wait(sd, SYSTEM_SYSMODE, mode, 0xff,
+				M5MOLS_MODE_CHANGE_TIMEOUT);
+}
+
+/**
+ * m5mols_set_mode - set the M-5MOLS controller mode
+ * @mode: the required operation mode
+ *
+ * The commands of M-5MOLS are grouped into specific modes. Each functionality
+ * can be guaranteed only when the sensor is operating in mode which a command
+ * belongs to.
+ */
+int m5mols_set_mode(struct m5mols_info *info, u8 mode)
+{
+	struct v4l2_subdev *sd = &info->sd;
+	int ret = -EINVAL;
+	u8 reg;
+
+	if (mode < REG_PARAMETER || mode > REG_CAPTURE)
+		return ret;
+
+	ret = m5mols_read_u8(sd, SYSTEM_SYSMODE, &reg);
+	if (ret || reg == mode)
+		return ret;
+
+	switch (reg) {
+	case REG_PARAMETER:
+		ret = m5mols_reg_mode(sd, REG_MONITOR);
+		if (mode == REG_MONITOR)
+			break;
+		if (!ret)
+			ret = m5mols_reg_mode(sd, REG_CAPTURE);
+		break;
+
+	case REG_MONITOR:
+		if (mode == REG_PARAMETER) {
+			ret = m5mols_reg_mode(sd, REG_PARAMETER);
+			break;
+		}
+
+		ret = m5mols_reg_mode(sd, REG_CAPTURE);
+		break;
+
+	case REG_CAPTURE:
+		ret = m5mols_reg_mode(sd, REG_MONITOR);
+		if (mode == REG_MONITOR)
+			break;
+		if (!ret)
+			ret = m5mols_reg_mode(sd, REG_PARAMETER);
+		break;
+
+	default:
+		v4l2_warn(sd, "Wrong mode: %d\n", mode);
+	}
+
+	if (!ret)
+		info->mode = mode;
+
+	return ret;
+}
+
+/**
+ * m5mols_get_version - retrieve full revisions information of M-5MOLS
+ *
+ * The version information includes revisions of hardware and firmware,
+ * AutoFocus alghorithm version and the version string.
+ */
+static int m5mols_get_version(struct v4l2_subdev *sd)
+{
+	struct m5mols_info *info = to_m5mols(sd);
+	struct m5mols_version *ver = &info->ver;
+	u8 *str = ver->str;
+	int i;
+	int ret;
+
+	ret = m5mols_read_u8(sd, SYSTEM_VER_CUSTOMER, &ver->customer);
+	if (!ret)
+		ret = m5mols_read_u8(sd, SYSTEM_VER_PROJECT, &ver->project);
+	if (!ret)
+		ret = m5mols_read_u16(sd, SYSTEM_VER_FIRMWARE, &ver->fw);
+	if (!ret)
+		ret = m5mols_read_u16(sd, SYSTEM_VER_HARDWARE, &ver->hw);
+	if (!ret)
+		ret = m5mols_read_u16(sd, SYSTEM_VER_PARAMETER, &ver->param);
+	if (!ret)
+		ret = m5mols_read_u16(sd, SYSTEM_VER_AWB, &ver->awb);
+	if (!ret)
+		ret = m5mols_read_u8(sd, AF_VERSION, &ver->af);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < VERSION_STRING_SIZE; i++) {
+		ret = m5mols_read_u8(sd, SYSTEM_VER_STRING, &str[i]);
+		if (ret)
+			return ret;
+	}
+
+	ver->fw = be16_to_cpu(ver->fw);
+	ver->hw = be16_to_cpu(ver->hw);
+	ver->param = be16_to_cpu(ver->param);
+	ver->awb = be16_to_cpu(ver->awb);
+
+	v4l2_info(sd, "Manufacturer\t[%s]\n",
+			is_manufacturer(info, REG_SAMSUNG_ELECTRO) ?
+			"Samsung Electro-Machanics" :
+			is_manufacturer(info, REG_SAMSUNG_OPTICS) ?
+			"Samsung Fiber-Optics" :
+			is_manufacturer(info, REG_SAMSUNG_TECHWIN) ?
+			"Samsung Techwin" : "None");
+	v4l2_info(sd, "Customer/Project\t[0x%02x/0x%02x]\n",
+			info->ver.customer, info->ver.project);
+
+	if (!is_available_af(info))
+		v4l2_info(sd, "No support Auto Focus on this firmware\n");
+
+	return ret;
+}
+
+/**
+ * __find_restype - Lookup M-5MOLS resolution type according to pixel code
+ * @code: pixel code
+ */
+static enum m5mols_restype __find_restype(enum v4l2_mbus_pixelcode code)
+{
+	enum m5mols_restype type = M5MOLS_RESTYPE_MONITOR;
+
+	do {
+		if (code == m5mols_default_ffmt[type].code)
+			return type;
+	} while (type++ != SIZE_DEFAULT_FFMT);
+
+	return 0;
+}
+
+/**
+ * __find_resolution - Lookup preset and type of M-5MOLS's resolution
+ * @mf: pixel format to find/negotiate the resolution preset for
+ * @type: M-5MOLS resolution type
+ * @resolution:	M-5MOLS resolution preset register value
+ *
+ * Find nearest resolution matching resolution preset and adjust mf
+ * to supported values.
+ */
+static int __find_resolution(struct v4l2_subdev *sd,
+			     struct v4l2_mbus_framefmt *mf,
+			     enum m5mols_restype *type,
+			     u32 *resolution)
+{
+	const struct m5mols_resolution *fsize = &m5mols_reg_res[0];
+	const struct m5mols_resolution *match = NULL;
+	enum m5mols_restype stype = __find_restype(mf->code);
+	int i = ARRAY_SIZE(m5mols_reg_res);
+	unsigned int min_err = ~0;
+
+	while (i--) {
+		int err;
+		if (stype == fsize->type) {
+			err = abs(fsize->width - mf->width)
+				+ abs(fsize->height - mf->height);
+
+			if (err < min_err) {
+				min_err = err;
+				match = fsize;
+			}
+		}
+		fsize++;
+	}
+	if (match) {
+		mf->width  = match->width;
+		mf->height = match->height;
+		*resolution = match->reg;
+		*type = stype;
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+static struct v4l2_mbus_framefmt *__find_format(struct m5mols_info *info,
+				struct v4l2_subdev_fh *fh,
+				enum v4l2_subdev_format_whence which,
+				enum m5mols_restype type)
+{
+	if (which == V4L2_SUBDEV_FORMAT_TRY)
+		return fh ? v4l2_subdev_get_try_format(fh, 0) : NULL;
+
+	return &info->ffmt[type];
+}
+
+static int m5mols_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+			  struct v4l2_subdev_format *fmt)
+{
+	struct m5mols_info *info = to_m5mols(sd);
+	struct v4l2_mbus_framefmt *format;
+
+	format = __find_format(info, fh, fmt->which, info->res_type);
+	if (!format)
+		return -EINVAL;
+
+	fmt->format = *format;
+	return 0;
+}
+
+static int m5mols_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+			  struct v4l2_subdev_format *fmt)
+{
+	struct m5mols_info *info = to_m5mols(sd);
+	struct v4l2_mbus_framefmt *format = &fmt->format;
+	struct v4l2_mbus_framefmt *sfmt;
+	enum m5mols_restype type;
+	u32 resolution = 0;
+	int ret;
+
+	ret = __find_resolution(sd, format, &type, &resolution);
+	if (ret < 0)
+		return ret;
+
+	sfmt = __find_format(info, fh, fmt->which, type);
+	if (!sfmt)
+		return 0;
+
+
+	format->code = m5mols_default_ffmt[type].code;
+	format->colorspace = V4L2_COLORSPACE_JPEG;
+	format->field = V4L2_FIELD_NONE;
+
+	if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
+		*sfmt = *format;
+		info->resolution = resolution;
+		info->res_type = type;
+	}
+
+	return 0;
+}
+
+static int m5mols_enum_mbus_code(struct v4l2_subdev *sd,
+				 struct v4l2_subdev_fh *fh,
+				 struct v4l2_subdev_mbus_code_enum *code)
+{
+	if (!code || code->index >= SIZE_DEFAULT_FFMT)
+		return -EINVAL;
+
+	code->code = m5mols_default_ffmt[code->index].code;
+
+	return 0;
+}
+
+static struct v4l2_subdev_pad_ops m5mols_pad_ops = {
+	.enum_mbus_code	= m5mols_enum_mbus_code,
+	.get_fmt	= m5mols_get_fmt,
+	.set_fmt	= m5mols_set_fmt,
+};
+
+/**
+ * m5mols_restore_controls - Apply current control values to the registers
+ *
+ * m5mols_do_scenemode() handles all parameters for which there is yet no
+ * individual control. It should be replaced at some point by setting each
+ * control individually, in required register set up order.
+ */
+int m5mols_restore_controls(struct m5mols_info *info)
+{
+	int ret;
+
+	if (info->ctrl_sync)
+		return 0;
+
+	ret = m5mols_do_scenemode(info, REG_SCENE_NORMAL);
+	if (ret)
+		return ret;
+
+	ret = v4l2_ctrl_handler_setup(&info->handle);
+	info->ctrl_sync = !ret;
+
+	return ret;
+}
+
+/**
+ * m5mols_start_monitor - Start the monitor mode
+ *
+ * Before applying the controls setup the resolution and frame rate
+ * in PARAMETER mode, and then switch over to MONITOR mode.
+ */
+static int m5mols_start_monitor(struct m5mols_info *info)
+{
+	struct v4l2_subdev *sd = &info->sd;
+	int ret;
+
+	ret = m5mols_set_mode(info, REG_PARAMETER);
+	if (!ret)
+		ret = m5mols_write(sd, PARM_MON_SIZE, info->resolution);
+	if (!ret)
+		ret = m5mols_write(sd, PARM_MON_FPS, REG_FPS_30);
+	if (!ret)
+		ret = m5mols_set_mode(info, REG_MONITOR);
+	if (!ret)
+		ret = m5mols_restore_controls(info);
+
+	return ret;
+}
+
+static int m5mols_s_stream(struct v4l2_subdev *sd, int enable)
+{
+	struct m5mols_info *info = to_m5mols(sd);
+	u32 code = info->ffmt[info->res_type].code;
+
+	if (enable) {
+		int ret = -EINVAL;
+
+		if (is_code(code, M5MOLS_RESTYPE_MONITOR))
+			ret = m5mols_start_monitor(info);
+		if (is_code(code, M5MOLS_RESTYPE_CAPTURE))
+			ret = m5mols_start_capture(info);
+
+		return ret;
+	}
+
+	return m5mols_set_mode(info, REG_PARAMETER);
+}
+
+static const struct v4l2_subdev_video_ops m5mols_video_ops = {
+	.s_stream	= m5mols_s_stream,
+};
+
+static int m5mols_sensor_power(struct m5mols_info *info, bool enable)
+{
+	struct v4l2_subdev *sd = &info->sd;
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	const struct m5mols_platform_data *pdata = info->pdata;
+	int ret;
+
+	if (info->power == enable)
+		return 0;
+
+	if (enable) {
+		if (info->set_power) {
+			ret = info->set_power(&client->dev, 1);
+			if (ret)
+				return ret;
+		}
+
+		ret = regulator_bulk_enable(ARRAY_SIZE(supplies), supplies);
+		if (ret) {
+			info->set_power(&client->dev, 0);
+			return ret;
+		}
+
+		gpio_set_value(pdata->gpio_reset, !pdata->reset_polarity);
+		info->power = 1;
+
+		return ret;
+	}
+
+	ret = regulator_bulk_disable(ARRAY_SIZE(supplies), supplies);
+	if (ret)
+		return ret;
+
+	if (info->set_power)
+		info->set_power(&client->dev, 0);
+
+	gpio_set_value(pdata->gpio_reset, pdata->reset_polarity);
+
+	info->isp_ready = 0;
+	info->power = 0;
+
+	return ret;
+}
+
+/* m5mols_update_fw - optional firmware update routine */
+int __attribute__ ((weak)) m5mols_update_fw(struct v4l2_subdev *sd,
+		int (*set_power)(struct m5mols_info *, bool))
+{
+	return 0;
+}
+
+/**
+ * m5mols_fw_start - M-5MOLS internal ARM controller initialization
+ *
+ * Execute the M-5MOLS internal ARM controller initialization sequence.
+ * This function should be called after the supply voltage has been
+ * applied and before any requests to the device are made.
+ */
+static int m5mols_fw_start(struct v4l2_subdev *sd)
+{
+	struct m5mols_info *info = to_m5mols(sd);
+	int ret;
+
+	atomic_set(&info->irq_done, 0);
+	/* Wait until I2C slave is initialized in Flash Writer mode */
+	ret = m5mols_busy_wait(sd, FLASH_CAM_START, REG_IN_FLASH_MODE,
+			       M5MOLS_I2C_RDY_WAIT_FL | 0xff, -1);
+	if (!ret)
+		ret = m5mols_write(sd, FLASH_CAM_START, REG_START_ARM_BOOT);
+	if (!ret)
+		ret = m5mols_wait_interrupt(sd, REG_INT_MODE, 2000);
+	if (ret < 0)
+		return ret;
+
+	info->isp_ready = 1;
+
+	ret = m5mols_get_version(sd);
+	if (!ret)
+		ret = m5mols_update_fw(sd, m5mols_sensor_power);
+	if (ret)
+		return ret;
+
+	v4l2_dbg(1, m5mols_debug, sd, "Success ARM Booting\n");
+
+	ret = m5mols_write(sd, PARM_INTERFACE, REG_INTERFACE_MIPI);
+	if (!ret)
+		ret = m5mols_enable_interrupt(sd,
+				REG_INT_AF | REG_INT_CAPTURE);
+
+	return ret;
+}
+
+/**
+ * m5mols_s_power - Main sensor power control function
+ *
+ * To prevent breaking the lens when the sensor is powered off the Soft-Landing
+ * algorithm is called where available. The Soft-Landing algorithm availability
+ * dependends on the firmware provider.
+ */
+static int m5mols_s_power(struct v4l2_subdev *sd, int on)
+{
+	struct m5mols_info *info = to_m5mols(sd);
+	int ret;
+
+	if (on) {
+		ret = m5mols_sensor_power(info, true);
+		if (!ret)
+			ret = m5mols_fw_start(sd);
+		return ret;
+	}
+
+	if (is_manufacturer(info, REG_SAMSUNG_TECHWIN)) {
+		ret = m5mols_set_mode(info, REG_MONITOR);
+		if (!ret)
+			ret = m5mols_write(sd, AF_EXECUTE, REG_AF_STOP);
+		if (!ret)
+			ret = m5mols_write(sd, AF_MODE, REG_AF_POWEROFF);
+		if (!ret)
+			ret = m5mols_busy_wait(sd, SYSTEM_STATUS, REG_AF_IDLE,
+					       0xff, -1);
+		if (ret < 0)
+			v4l2_warn(sd, "Soft landing lens failed\n");
+	}
+
+	ret = m5mols_sensor_power(info, false);
+	info->ctrl_sync = 0;
+
+	return ret;
+}
+
+static int m5mols_log_status(struct v4l2_subdev *sd)
+{
+	struct m5mols_info *info = to_m5mols(sd);
+
+	v4l2_ctrl_handler_log_status(&info->handle, sd->name);
+
+	return 0;
+}
+
+static const struct v4l2_subdev_core_ops m5mols_core_ops = {
+	.s_power	= m5mols_s_power,
+	.g_ctrl		= v4l2_subdev_g_ctrl,
+	.s_ctrl		= v4l2_subdev_s_ctrl,
+	.queryctrl	= v4l2_subdev_queryctrl,
+	.querymenu	= v4l2_subdev_querymenu,
+	.g_ext_ctrls	= v4l2_subdev_g_ext_ctrls,
+	.try_ext_ctrls	= v4l2_subdev_try_ext_ctrls,
+	.s_ext_ctrls	= v4l2_subdev_s_ext_ctrls,
+	.log_status	= m5mols_log_status,
+};
+
+/*
+ * V4L2 subdev internal operations
+ */
+static int m5mols_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+	struct v4l2_mbus_framefmt *format = v4l2_subdev_get_try_format(fh, 0);
+
+	*format = m5mols_default_ffmt[0];
+	return 0;
+}
+
+static const struct v4l2_subdev_internal_ops m5mols_subdev_internal_ops = {
+	.open		= m5mols_open,
+};
+
+static const struct v4l2_subdev_ops m5mols_ops = {
+	.core		= &m5mols_core_ops,
+	.pad		= &m5mols_pad_ops,
+	.video		= &m5mols_video_ops,
+};
+
+static irqreturn_t m5mols_irq_handler(int irq, void *data)
+{
+	struct m5mols_info *info = to_m5mols(data);
+
+	atomic_set(&info->irq_done, 1);
+	wake_up_interruptible(&info->irq_waitq);
+
+	return IRQ_HANDLED;
+}
+
+static int __devinit m5mols_probe(struct i2c_client *client,
+				  const struct i2c_device_id *id)
+{
+	const struct m5mols_platform_data *pdata = client->dev.platform_data;
+	struct m5mols_info *info;
+	struct v4l2_subdev *sd;
+	int ret;
+
+	if (pdata == NULL) {
+		dev_err(&client->dev, "No platform data\n");
+		return -EINVAL;
+	}
+
+	if (!gpio_is_valid(pdata->gpio_reset)) {
+		dev_err(&client->dev, "No valid RESET GPIO specified\n");
+		return -EINVAL;
+	}
+
+	if (!client->irq) {
+		dev_err(&client->dev, "Interrupt not assigned\n");
+		return -EINVAL;
+	}
+
+	info = kzalloc(sizeof(struct m5mols_info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	info->pdata = pdata;
+	info->set_power	= pdata->set_power;
+
+	ret = gpio_request(pdata->gpio_reset, "M5MOLS_NRST");
+	if (ret) {
+		dev_err(&client->dev, "Failed to request gpio: %d\n", ret);
+		goto out_free;
+	}
+	gpio_direction_output(pdata->gpio_reset, pdata->reset_polarity);
+
+	ret = regulator_bulk_get(&client->dev, ARRAY_SIZE(supplies), supplies);
+	if (ret) {
+		dev_err(&client->dev, "Failed to get regulators: %d\n", ret);
+		goto out_gpio;
+	}
+
+	sd = &info->sd;
+	v4l2_i2c_subdev_init(sd, client, &m5mols_ops);
+	strlcpy(sd->name, MODULE_NAME, sizeof(sd->name));
+	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+	sd->internal_ops = &m5mols_subdev_internal_ops;
+	info->pad.flags = MEDIA_PAD_FL_SOURCE;
+	ret = media_entity_init(&sd->entity, 1, &info->pad, 0);
+	if (ret < 0)
+		goto out_reg;
+	sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR;
+
+	init_waitqueue_head(&info->irq_waitq);
+	ret = request_irq(client->irq, m5mols_irq_handler,
+			  IRQF_TRIGGER_RISING, MODULE_NAME, sd);
+	if (ret) {
+		dev_err(&client->dev, "Interrupt request failed: %d\n", ret);
+		goto out_me;
+	}
+	info->res_type = M5MOLS_RESTYPE_MONITOR;
+	info->ffmt[0] = m5mols_default_ffmt[0];
+	info->ffmt[1] =	m5mols_default_ffmt[1];
+
+	ret = m5mols_sensor_power(info, true);
+	if (ret)
+		goto out_irq;
+
+	ret = m5mols_fw_start(sd);
+	if (!ret)
+		ret = m5mols_init_controls(sd);
+
+	ret = m5mols_sensor_power(info, false);
+	if (!ret)
+		return 0;
+out_irq:
+	free_irq(client->irq, sd);
+out_me:
+	media_entity_cleanup(&sd->entity);
+out_reg:
+	regulator_bulk_free(ARRAY_SIZE(supplies), supplies);
+out_gpio:
+	gpio_free(pdata->gpio_reset);
+out_free:
+	kfree(info);
+	return ret;
+}
+
+static int __devexit m5mols_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct m5mols_info *info = to_m5mols(sd);
+
+	v4l2_device_unregister_subdev(sd);
+	v4l2_ctrl_handler_free(sd->ctrl_handler);
+	free_irq(client->irq, sd);
+
+	regulator_bulk_free(ARRAY_SIZE(supplies), supplies);
+	gpio_free(info->pdata->gpio_reset);
+	media_entity_cleanup(&sd->entity);
+	kfree(info);
+	return 0;
+}
+
+static const struct i2c_device_id m5mols_id[] = {
+	{ MODULE_NAME, 0 },
+	{ },
+};
+MODULE_DEVICE_TABLE(i2c, m5mols_id);
+
+static struct i2c_driver m5mols_i2c_driver = {
+	.driver = {
+		.name	= MODULE_NAME,
+	},
+	.probe		= m5mols_probe,
+	.remove		= __devexit_p(m5mols_remove),
+	.id_table	= m5mols_id,
+};
+
+module_i2c_driver(m5mols_i2c_driver);
+
+MODULE_AUTHOR("HeungJun Kim <riverful.kim@samsung.com>");
+MODULE_AUTHOR("Dongsoo Kim <dongsoo45.kim@samsung.com>");
+MODULE_DESCRIPTION("Fujitsu M-5MOLS 8M Pixel camera driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/i2c/m5mols/m5mols_reg.h b/drivers/media/i2c/m5mols/m5mols_reg.h
new file mode 100644
index 0000000..14d4be7
--- /dev/null
+++ b/drivers/media/i2c/m5mols/m5mols_reg.h
@@ -0,0 +1,362 @@
+/*
+ * Register map for M-5MOLS 8M Pixel camera sensor with ISP
+ *
+ * Copyright (C) 2011 Samsung Electronics Co., Ltd.
+ * Author: HeungJun Kim <riverful.kim@samsung.com>
+ *
+ * Copyright (C) 2009 Samsung Electronics Co., Ltd.
+ * Author: Dongsoo Nathaniel Kim <dongsoo45.kim@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef M5MOLS_REG_H
+#define M5MOLS_REG_H
+
+#define M5MOLS_I2C_MAX_SIZE	4
+#define M5MOLS_BYTE_READ	0x01
+#define M5MOLS_BYTE_WRITE	0x02
+
+#define I2C_CATEGORY(__cat)		((__cat >> 16) & 0xff)
+#define I2C_COMMAND(__comm)		((__comm >> 8) & 0xff)
+#define I2C_SIZE(__reg_s)		((__reg_s) & 0xff)
+#define I2C_REG(__cat, __cmd, __reg_s)	((__cat << 16) | (__cmd << 8) | __reg_s)
+
+/*
+ * Category section register
+ *
+ * The category means set including relevant command of M-5MOLS.
+ */
+#define CAT_SYSTEM		0x00
+#define CAT_PARAM		0x01
+#define CAT_MONITOR		0x02
+#define CAT_AE			0x03
+#define CAT_WB			0x06
+#define CAT_EXIF		0x07
+#define CAT_FD			0x09
+#define CAT_LENS		0x0a
+#define CAT_CAPT_PARM		0x0b
+#define CAT_CAPT_CTRL		0x0c
+#define CAT_FLASH		0x0f	/* related to FW, revisions, booting */
+
+/*
+ * Category 0 - SYSTEM mode
+ *
+ * The SYSTEM mode in the M-5MOLS means area available to handle with the whole
+ * & all-round system of sensor. It deals with version/interrupt/setting mode &
+ * even sensor's status. Especially, the M-5MOLS sensor with ISP varies by
+ * packaging & manufacturer, even the customer and project code. And the
+ * function details may vary among them. The version information helps to
+ * determine what methods shall be used in the driver.
+ *
+ * There is many registers between customer version address and awb one. For
+ * more specific contents, see definition if file m5mols.h.
+ */
+#define SYSTEM_VER_CUSTOMER	I2C_REG(CAT_SYSTEM, 0x00, 1)
+#define SYSTEM_VER_PROJECT	I2C_REG(CAT_SYSTEM, 0x01, 1)
+#define SYSTEM_VER_FIRMWARE	I2C_REG(CAT_SYSTEM, 0x02, 2)
+#define SYSTEM_VER_HARDWARE	I2C_REG(CAT_SYSTEM, 0x04, 2)
+#define SYSTEM_VER_PARAMETER	I2C_REG(CAT_SYSTEM, 0x06, 2)
+#define SYSTEM_VER_AWB		I2C_REG(CAT_SYSTEM, 0x08, 2)
+
+#define SYSTEM_SYSMODE		I2C_REG(CAT_SYSTEM, 0x0b, 1)
+#define REG_SYSINIT		0x00	/* SYSTEM mode */
+#define REG_PARAMETER		0x01	/* PARAMETER mode */
+#define REG_MONITOR		0x02	/* MONITOR mode */
+#define REG_CAPTURE		0x03	/* CAPTURE mode */
+
+#define SYSTEM_CMD(__cmd)	I2C_REG(CAT_SYSTEM, cmd, 1)
+#define SYSTEM_VER_STRING	I2C_REG(CAT_SYSTEM, 0x0a, 1)
+#define REG_SAMSUNG_ELECTRO	"SE"	/* Samsung Electro-Mechanics */
+#define REG_SAMSUNG_OPTICS	"OP"	/* Samsung Fiber-Optics */
+#define REG_SAMSUNG_TECHWIN	"TB"	/* Samsung Techwin */
+/* SYSTEM mode status */
+#define SYSTEM_STATUS	I2C_REG(CAT_SYSTEM, 0x0c, 1)
+
+/* Interrupt pending register */
+#define SYSTEM_INT_FACTOR	I2C_REG(CAT_SYSTEM, 0x10, 1)
+/* interrupt enable register */
+#define SYSTEM_INT_ENABLE	I2C_REG(CAT_SYSTEM, 0x11, 1)
+#define REG_INT_MODE		(1 << 0)
+#define REG_INT_AF		(1 << 1)
+#define REG_INT_ZOOM		(1 << 2)
+#define REG_INT_CAPTURE		(1 << 3)
+#define REG_INT_FRAMESYNC	(1 << 4)
+#define REG_INT_FD		(1 << 5)
+#define REG_INT_LENS_INIT	(1 << 6)
+#define REG_INT_SOUND		(1 << 7)
+#define REG_INT_MASK		0x0f
+
+/*
+ * category 1 - PARAMETER mode
+ *
+ * This category supports function of camera features of M-5MOLS. It means we
+ * can handle with preview(MONITOR) resolution size/frame per second/interface
+ * between the sensor and the Application Processor/even the image effect.
+ */
+
+/* Resolution in the MONITOR mode */
+#define PARM_MON_SIZE		I2C_REG(CAT_PARAM, 0x01, 1)
+
+/* Frame rate */
+#define PARM_MON_FPS		I2C_REG(CAT_PARAM, 0x02, 1)
+#define REG_FPS_30		0x02
+
+/* Video bus between the sensor and a host processor */
+#define PARM_INTERFACE		I2C_REG(CAT_PARAM, 0x00, 1)
+#define REG_INTERFACE_MIPI	0x02
+
+/* Image effects */
+#define PARM_EFFECT		I2C_REG(CAT_PARAM, 0x0b, 1)
+#define REG_EFFECT_OFF		0x00
+#define REG_EFFECT_NEGA		0x01
+#define REG_EFFECT_EMBOSS	0x06
+#define REG_EFFECT_OUTLINE	0x07
+#define REG_EFFECT_WATERCOLOR	0x08
+
+/*
+ * Category 2 - MONITOR mode
+ *
+ * The MONITOR mode is same as preview mode as we said. The M-5MOLS has another
+ * mode named "Preview", but this preview mode is used at the case specific
+ * vider-recording mode. This mmode supports only YUYV format. On the other
+ * hand, the JPEG & RAW formats is supports by CAPTURE mode. And, there are
+ * another options like zoom/color effect(different with effect in PARAMETER
+ * mode)/anti hand shaking algorithm.
+ */
+
+/* Target digital zoom position */
+#define MON_ZOOM		I2C_REG(CAT_MONITOR, 0x01, 1)
+
+/* CR value for color effect */
+#define MON_CFIXR		I2C_REG(CAT_MONITOR, 0x0a, 1)
+/* CB value for color effect */
+#define MON_CFIXB		I2C_REG(CAT_MONITOR, 0x09, 1)
+#define REG_CFIXB_SEPIA		0xd8
+#define REG_CFIXR_SEPIA		0x18
+
+#define MON_EFFECT		I2C_REG(CAT_MONITOR, 0x0b, 1)
+#define REG_COLOR_EFFECT_OFF	0x00
+#define REG_COLOR_EFFECT_ON	0x01
+
+/* Chroma enable */
+#define MON_CHROMA_EN		I2C_REG(CAT_MONITOR, 0x10, 1)
+/* Chroma level */
+#define MON_CHROMA_LVL		I2C_REG(CAT_MONITOR, 0x0f, 1)
+#define REG_CHROMA_OFF		0x00
+#define REG_CHROMA_ON		0x01
+
+/* Sharpness on/off */
+#define MON_EDGE_EN		I2C_REG(CAT_MONITOR, 0x12, 1)
+/* Sharpness level */
+#define MON_EDGE_LVL		I2C_REG(CAT_MONITOR, 0x11, 1)
+#define REG_EDGE_OFF		0x00
+#define REG_EDGE_ON		0x01
+
+/* Set color tone (contrast) */
+#define MON_TONE_CTL		I2C_REG(CAT_MONITOR, 0x25, 1)
+
+/*
+ * Category 3 - Auto Exposure
+ *
+ * The M-5MOLS exposure capbility is detailed as which is similar to digital
+ * camera. This category supports AE locking/various AE mode(range of exposure)
+ * /ISO/flickering/EV bias/shutter/meteoring, and anything else. And the
+ * maximum/minimum exposure gain value depending on M-5MOLS firmware, may be
+ * different. So, this category also provide getting the max/min values. And,
+ * each MONITOR and CAPTURE mode has each gain/shutter/max exposure values.
+ */
+
+/* Auto Exposure locking */
+#define AE_LOCK			I2C_REG(CAT_AE, 0x00, 1)
+#define REG_AE_UNLOCK		0x00
+#define REG_AE_LOCK		0x01
+
+/* Auto Exposure algorithm mode */
+#define AE_MODE			I2C_REG(CAT_AE, 0x01, 1)
+#define REG_AE_OFF		0x00	/* AE off */
+#define REG_AE_ALL		0x01	/* calc AE in all block integral */
+#define REG_AE_CENTER		0x03	/* calc AE in center weighted */
+#define REG_AE_SPOT		0x06	/* calc AE in specific spot */
+
+#define AE_ISO			I2C_REG(CAT_AE, 0x05, 1)
+#define REG_ISO_AUTO		0x00
+#define REG_ISO_50		0x01
+#define REG_ISO_100		0x02
+#define REG_ISO_200		0x03
+#define REG_ISO_400		0x04
+#define REG_ISO_800		0x05
+
+/* EV (scenemode) preset for MONITOR */
+#define AE_EV_PRESET_MONITOR	I2C_REG(CAT_AE, 0x0a, 1)
+/* EV (scenemode) preset for CAPTURE */
+#define AE_EV_PRESET_CAPTURE	I2C_REG(CAT_AE, 0x0b, 1)
+#define REG_SCENE_NORMAL	0x00
+#define REG_SCENE_PORTRAIT	0x01
+#define REG_SCENE_LANDSCAPE	0x02
+#define REG_SCENE_SPORTS	0x03
+#define REG_SCENE_PARTY_INDOOR	0x04
+#define REG_SCENE_BEACH_SNOW	0x05
+#define REG_SCENE_SUNSET	0x06
+#define REG_SCENE_DAWN_DUSK	0x07
+#define REG_SCENE_FALL		0x08
+#define REG_SCENE_NIGHT		0x09
+#define REG_SCENE_AGAINST_LIGHT	0x0a
+#define REG_SCENE_FIRE		0x0b
+#define REG_SCENE_TEXT		0x0c
+#define REG_SCENE_CANDLE	0x0d
+
+/* Manual gain in MONITOR mode */
+#define AE_MAN_GAIN_MON		I2C_REG(CAT_AE, 0x12, 2)
+/* Maximum gain in MONITOR mode */
+#define AE_MAX_GAIN_MON		I2C_REG(CAT_AE, 0x1a, 2)
+/* Manual gain in CAPTURE mode */
+#define AE_MAN_GAIN_CAP		I2C_REG(CAT_AE, 0x26, 2)
+
+#define AE_INDEX		I2C_REG(CAT_AE, 0x38, 1)
+#define REG_AE_INDEX_20_NEG	0x00
+#define REG_AE_INDEX_15_NEG	0x01
+#define REG_AE_INDEX_10_NEG	0x02
+#define REG_AE_INDEX_05_NEG	0x03
+#define REG_AE_INDEX_00		0x04
+#define REG_AE_INDEX_05_POS	0x05
+#define REG_AE_INDEX_10_POS	0x06
+#define REG_AE_INDEX_15_POS	0x07
+#define REG_AE_INDEX_20_POS	0x08
+
+/*
+ * Category 6 - White Balance
+ */
+
+/* Auto Whitebalance locking */
+#define AWB_LOCK		I2C_REG(CAT_WB, 0x00, 1)
+#define REG_AWB_UNLOCK		0x00
+#define REG_AWB_LOCK		0x01
+
+#define AWB_MODE		I2C_REG(CAT_WB, 0x02, 1)
+#define REG_AWB_AUTO		0x01	/* AWB off */
+#define REG_AWB_PRESET		0x02	/* AWB preset */
+
+/* Manual WB (preset) */
+#define AWB_MANUAL		I2C_REG(CAT_WB, 0x03, 1)
+#define REG_AWB_INCANDESCENT	0x01
+#define REG_AWB_FLUORESCENT_1	0x02
+#define REG_AWB_FLUORESCENT_2	0x03
+#define REG_AWB_DAYLIGHT	0x04
+#define REG_AWB_CLOUDY		0x05
+#define REG_AWB_SHADE		0x06
+#define REG_AWB_HORIZON		0x07
+#define REG_AWB_LEDLIGHT	0x09
+
+/*
+ * Category 7 - EXIF information
+ */
+#define EXIF_INFO_EXPTIME_NU	I2C_REG(CAT_EXIF, 0x00, 4)
+#define EXIF_INFO_EXPTIME_DE	I2C_REG(CAT_EXIF, 0x04, 4)
+#define EXIF_INFO_TV_NU		I2C_REG(CAT_EXIF, 0x08, 4)
+#define EXIF_INFO_TV_DE		I2C_REG(CAT_EXIF, 0x0c, 4)
+#define EXIF_INFO_AV_NU		I2C_REG(CAT_EXIF, 0x10, 4)
+#define EXIF_INFO_AV_DE		I2C_REG(CAT_EXIF, 0x14, 4)
+#define EXIF_INFO_BV_NU		I2C_REG(CAT_EXIF, 0x18, 4)
+#define EXIF_INFO_BV_DE		I2C_REG(CAT_EXIF, 0x1c, 4)
+#define EXIF_INFO_EBV_NU	I2C_REG(CAT_EXIF, 0x20, 4)
+#define EXIF_INFO_EBV_DE	I2C_REG(CAT_EXIF, 0x24, 4)
+#define EXIF_INFO_ISO		I2C_REG(CAT_EXIF, 0x28, 2)
+#define EXIF_INFO_FLASH		I2C_REG(CAT_EXIF, 0x2a, 2)
+#define EXIF_INFO_SDR		I2C_REG(CAT_EXIF, 0x2c, 2)
+#define EXIF_INFO_QVAL		I2C_REG(CAT_EXIF, 0x2e, 2)
+
+/*
+ * Category 9 - Face Detection
+ */
+#define FD_CTL			I2C_REG(CAT_FD, 0x00, 1)
+#define BIT_FD_EN		0
+#define BIT_FD_DRAW_FACE_FRAME	4
+#define BIT_FD_DRAW_SMILE_LVL	6
+#define REG_FD(shift)		(1 << shift)
+#define REG_FD_OFF		0x0
+
+/*
+ * Category A - Lens Parameter
+ */
+#define AF_MODE			I2C_REG(CAT_LENS, 0x01, 1)
+#define REG_AF_NORMAL		0x00	/* Normal AF, one time */
+#define REG_AF_MACRO		0x01	/* Macro AF, one time */
+#define REG_AF_POWEROFF		0x07
+
+#define AF_EXECUTE		I2C_REG(CAT_LENS, 0x02, 1)
+#define REG_AF_STOP		0x00
+#define REG_AF_EXE_AUTO		0x01
+#define REG_AF_EXE_CAF		0x02
+
+#define AF_STATUS		I2C_REG(CAT_LENS, 0x03, 1)
+#define REG_AF_FAIL		0x00
+#define REG_AF_SUCCESS		0x02
+#define REG_AF_IDLE		0x04
+#define REG_AF_BUSY		0x05
+
+#define AF_VERSION		I2C_REG(CAT_LENS, 0x0a, 1)
+
+/*
+ * Category B - CAPTURE Parameter
+ */
+#define CAPP_YUVOUT_MAIN	I2C_REG(CAT_CAPT_PARM, 0x00, 1)
+#define REG_YUV422		0x00
+#define REG_BAYER10		0x05
+#define REG_BAYER8		0x06
+#define REG_JPEG		0x10
+
+#define CAPP_MAIN_IMAGE_SIZE	I2C_REG(CAT_CAPT_PARM, 0x01, 1)
+#define CAPP_JPEG_RATIO		I2C_REG(CAT_CAPT_PARM, 0x17, 1)
+
+#define CAPP_MCC_MODE		I2C_REG(CAT_CAPT_PARM, 0x1d, 1)
+#define REG_MCC_OFF		0x00
+#define REG_MCC_NORMAL		0x01
+
+#define CAPP_WDR_EN		I2C_REG(CAT_CAPT_PARM, 0x2c, 1)
+#define REG_WDR_OFF		0x00
+#define REG_WDR_ON		0x01
+#define REG_WDR_AUTO		0x02
+
+#define CAPP_LIGHT_CTRL		I2C_REG(CAT_CAPT_PARM, 0x40, 1)
+#define REG_LIGHT_OFF		0x00
+#define REG_LIGHT_ON		0x01
+#define REG_LIGHT_AUTO		0x02
+
+#define CAPP_FLASH_CTRL		I2C_REG(CAT_CAPT_PARM, 0x41, 1)
+#define REG_FLASH_OFF		0x00
+#define REG_FLASH_ON		0x01
+#define REG_FLASH_AUTO		0x02
+
+/*
+ * Category C - CAPTURE Control
+ */
+#define CAPC_MODE		I2C_REG(CAT_CAPT_CTRL, 0x00, 1)
+#define REG_CAP_NONE		0x00
+#define REG_CAP_ANTI_SHAKE	0x02
+
+/* Select single- or multi-shot capture */
+#define CAPC_SEL_FRAME		I2C_REG(CAT_CAPT_CTRL, 0x06, 1)
+
+#define CAPC_START		I2C_REG(CAT_CAPT_CTRL, 0x09, 1)
+#define REG_CAP_START_MAIN	0x01
+#define REG_CAP_START_THUMB	0x03
+
+#define CAPC_IMAGE_SIZE		I2C_REG(CAT_CAPT_CTRL, 0x0d, 4)
+#define CAPC_THUMB_SIZE		I2C_REG(CAT_CAPT_CTRL, 0x11, 4)
+
+/*
+ * Category F - Flash
+ *
+ * This mode provides functions about internal flash stuff and system startup.
+ */
+
+/* Starts internal ARM core booting after power-up */
+#define FLASH_CAM_START		I2C_REG(CAT_FLASH, 0x12, 1)
+#define REG_START_ARM_BOOT	0x01	/* write value */
+#define REG_IN_FLASH_MODE	0x00	/* read value */
+
+#endif	/* M5MOLS_REG_H */
diff --git a/drivers/media/i2c/msp3400-driver.c b/drivers/media/i2c/msp3400-driver.c
new file mode 100644
index 0000000..aeb22be
--- /dev/null
+++ b/drivers/media/i2c/msp3400-driver.c
@@ -0,0 +1,899 @@
+/*
+ * Programming the mspx4xx sound processor family
+ *
+ * (c) 1997-2001 Gerd Knorr <kraxel@bytesex.org>
+ *
+ * what works and what doesn't:
+ *
+ *  AM-Mono
+ *      Support for Hauppauge cards added (decoding handled by tuner) added by
+ *      Frederic Crozat <fcrozat@mail.dotcom.fr>
+ *
+ *  FM-Mono
+ *      should work. The stereo modes are backward compatible to FM-mono,
+ *      therefore FM-Mono should be allways available.
+ *
+ *  FM-Stereo (B/G, used in germany)
+ *      should work, with autodetect
+ *
+ *  FM-Stereo (satellite)
+ *      should work, no autodetect (i.e. default is mono, but you can
+ *      switch to stereo -- untested)
+ *
+ *  NICAM (B/G, L , used in UK, Scandinavia, Spain and France)
+ *      should work, with autodetect. Support for NICAM was added by
+ *      Pekka Pietikainen <pp@netppl.fi>
+ *
+ * TODO:
+ *   - better SAT support
+ *
+ * 980623  Thomas Sailer (sailer@ife.ee.ethz.ch)
+ *         using soundcore instead of OSS
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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/module.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/kthread.h>
+#include <linux/freezer.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
+#include <media/msp3400.h>
+#include <media/tvaudio.h>
+#include "msp3400-driver.h"
+
+/* ---------------------------------------------------------------------- */
+
+MODULE_DESCRIPTION("device driver for msp34xx TV sound processor");
+MODULE_AUTHOR("Gerd Knorr");
+MODULE_LICENSE("GPL");
+
+/* module parameters */
+static int opmode   = OPMODE_AUTO;
+int msp_debug;		 /* msp_debug output */
+bool msp_once;		 /* no continuous stereo monitoring */
+bool msp_amsound;	 /* hard-wire AM sound at 6.5 Hz (france),
+			    the autoscan seems work well only with FM... */
+int msp_standard = 1;    /* Override auto detect of audio msp_standard,
+			    if needed. */
+bool msp_dolby;
+
+int msp_stereo_thresh = 0x190; /* a2 threshold for stereo/bilingual
+					(msp34xxg only) 0x00a0-0x03c0 */
+
+/* read-only */
+module_param(opmode,           int, 0444);
+
+/* read-write */
+module_param_named(once, msp_once,                      bool, 0644);
+module_param_named(debug, msp_debug,                    int,  0644);
+module_param_named(stereo_threshold, msp_stereo_thresh, int,  0644);
+module_param_named(standard, msp_standard,              int,  0644);
+module_param_named(amsound, msp_amsound,                bool, 0644);
+module_param_named(dolby, msp_dolby,                    bool, 0644);
+
+MODULE_PARM_DESC(opmode, "Forces a MSP3400 opmode. 0=Manual, 1=Autodetect, 2=Autodetect and autoselect");
+MODULE_PARM_DESC(once, "No continuous stereo monitoring");
+MODULE_PARM_DESC(debug, "Enable debug messages [0-3]");
+MODULE_PARM_DESC(stereo_threshold, "Sets signal threshold to activate stereo");
+MODULE_PARM_DESC(standard, "Specify audio standard: 32 = NTSC, 64 = radio, Default: Autodetect");
+MODULE_PARM_DESC(amsound, "Hardwire AM sound at 6.5Hz (France), FM can autoscan");
+MODULE_PARM_DESC(dolby, "Activates Dolby processing");
+
+/* ---------------------------------------------------------------------- */
+
+/* control subaddress */
+#define I2C_MSP_CONTROL 0x00
+/* demodulator unit subaddress */
+#define I2C_MSP_DEM     0x10
+/* DSP unit subaddress */
+#define I2C_MSP_DSP     0x12
+
+
+/* ----------------------------------------------------------------------- */
+/* functions for talking to the MSP3400C Sound processor                   */
+
+int msp_reset(struct i2c_client *client)
+{
+	/* reset and read revision code */
+	static u8 reset_off[3] = { I2C_MSP_CONTROL, 0x80, 0x00 };
+	static u8 reset_on[3]  = { I2C_MSP_CONTROL, 0x00, 0x00 };
+	static u8 write[3]     = { I2C_MSP_DSP + 1, 0x00, 0x1e };
+	u8 read[2];
+	struct i2c_msg reset[2] = {
+		{ client->addr, I2C_M_IGNORE_NAK, 3, reset_off },
+		{ client->addr, I2C_M_IGNORE_NAK, 3, reset_on  },
+	};
+	struct i2c_msg test[2] = {
+		{ client->addr, 0,        3, write },
+		{ client->addr, I2C_M_RD, 2, read  },
+	};
+
+	v4l_dbg(3, msp_debug, client, "msp_reset\n");
+	if (i2c_transfer(client->adapter, &reset[0], 1) != 1 ||
+	    i2c_transfer(client->adapter, &reset[1], 1) != 1 ||
+	    i2c_transfer(client->adapter, test, 2) != 2) {
+		v4l_err(client, "chip reset failed\n");
+		return -1;
+	}
+	return 0;
+}
+
+static int msp_read(struct i2c_client *client, int dev, int addr)
+{
+	int err, retval;
+	u8 write[3];
+	u8 read[2];
+	struct i2c_msg msgs[2] = {
+		{ client->addr, 0,        3, write },
+		{ client->addr, I2C_M_RD, 2, read  }
+	};
+
+	write[0] = dev + 1;
+	write[1] = addr >> 8;
+	write[2] = addr & 0xff;
+
+	for (err = 0; err < 3; err++) {
+		if (i2c_transfer(client->adapter, msgs, 2) == 2)
+			break;
+		v4l_warn(client, "I/O error #%d (read 0x%02x/0x%02x)\n", err,
+		       dev, addr);
+		schedule_timeout_interruptible(msecs_to_jiffies(10));
+	}
+	if (err == 3) {
+		v4l_warn(client, "resetting chip, sound will go off.\n");
+		msp_reset(client);
+		return -1;
+	}
+	retval = read[0] << 8 | read[1];
+	v4l_dbg(3, msp_debug, client, "msp_read(0x%x, 0x%x): 0x%x\n",
+			dev, addr, retval);
+	return retval;
+}
+
+int msp_read_dem(struct i2c_client *client, int addr)
+{
+	return msp_read(client, I2C_MSP_DEM, addr);
+}
+
+int msp_read_dsp(struct i2c_client *client, int addr)
+{
+	return msp_read(client, I2C_MSP_DSP, addr);
+}
+
+static int msp_write(struct i2c_client *client, int dev, int addr, int val)
+{
+	int err;
+	u8 buffer[5];
+
+	buffer[0] = dev;
+	buffer[1] = addr >> 8;
+	buffer[2] = addr &  0xff;
+	buffer[3] = val  >> 8;
+	buffer[4] = val  &  0xff;
+
+	v4l_dbg(3, msp_debug, client, "msp_write(0x%x, 0x%x, 0x%x)\n",
+			dev, addr, val);
+	for (err = 0; err < 3; err++) {
+		if (i2c_master_send(client, buffer, 5) == 5)
+			break;
+		v4l_warn(client, "I/O error #%d (write 0x%02x/0x%02x)\n", err,
+		       dev, addr);
+		schedule_timeout_interruptible(msecs_to_jiffies(10));
+	}
+	if (err == 3) {
+		v4l_warn(client, "resetting chip, sound will go off.\n");
+		msp_reset(client);
+		return -1;
+	}
+	return 0;
+}
+
+int msp_write_dem(struct i2c_client *client, int addr, int val)
+{
+	return msp_write(client, I2C_MSP_DEM, addr, val);
+}
+
+int msp_write_dsp(struct i2c_client *client, int addr, int val)
+{
+	return msp_write(client, I2C_MSP_DSP, addr, val);
+}
+
+/* ----------------------------------------------------------------------- *
+ * bits  9  8  5 - SCART DSP input Select:
+ *       0  0  0 - SCART 1 to DSP input (reset position)
+ *       0  1  0 - MONO to DSP input
+ *       1  0  0 - SCART 2 to DSP input
+ *       1  1  1 - Mute DSP input
+ *
+ * bits 11 10  6 - SCART 1 Output Select:
+ *       0  0  0 - undefined (reset position)
+ *       0  1  0 - SCART 2 Input to SCART 1 Output (for devices with 2 SCARTS)
+ *       1  0  0 - MONO input to SCART 1 Output
+ *       1  1  0 - SCART 1 DA to SCART 1 Output
+ *       0  0  1 - SCART 2 DA to SCART 1 Output
+ *       0  1  1 - SCART 1 Input to SCART 1 Output
+ *       1  1  1 - Mute SCART 1 Output
+ *
+ * bits 13 12  7 - SCART 2 Output Select (for devices with 2 Output SCART):
+ *       0  0  0 - SCART 1 DA to SCART 2 Output (reset position)
+ *       0  1  0 - SCART 1 Input to SCART 2 Output
+ *       1  0  0 - MONO input to SCART 2 Output
+ *       0  0  1 - SCART 2 DA to SCART 2 Output
+ *       0  1  1 - SCART 2 Input to SCART 2 Output
+ *       1  1  0 - Mute SCART 2 Output
+ *
+ * Bits 4 to 0 should be zero.
+ * ----------------------------------------------------------------------- */
+
+static int scarts[3][9] = {
+	/* MASK   IN1     IN2     IN3     IN4     IN1_DA  IN2_DA  MONO    MUTE   */
+	/* SCART DSP Input select */
+	{ 0x0320, 0x0000, 0x0200, 0x0300, 0x0020, -1,     -1,     0x0100, 0x0320 },
+	/* SCART1 Output select */
+	{ 0x0c40, 0x0440, 0x0400, 0x0000, 0x0840, 0x0c00, 0x0040, 0x0800, 0x0c40 },
+	/* SCART2 Output select */
+	{ 0x3080, 0x1000, 0x1080, 0x2080, 0x3080, 0x0000, 0x0080, 0x2000, 0x3000 },
+};
+
+static char *scart_names[] = {
+	"in1", "in2", "in3", "in4", "in1 da", "in2 da", "mono", "mute"
+};
+
+void msp_set_scart(struct i2c_client *client, int in, int out)
+{
+	struct msp_state *state = to_state(i2c_get_clientdata(client));
+
+	state->in_scart = in;
+
+	if (in >= 0 && in <= 7 && out >= 0 && out <= 2) {
+		if (-1 == scarts[out][in + 1])
+			return;
+
+		state->acb &= ~scarts[out][0];
+		state->acb |=  scarts[out][in + 1];
+	} else
+		state->acb = 0xf60; /* Mute Input and SCART 1 Output */
+
+	v4l_dbg(1, msp_debug, client, "scart switch: %s => %d (ACB=0x%04x)\n",
+					scart_names[in], out, state->acb);
+	msp_write_dsp(client, 0x13, state->acb);
+
+	/* Sets I2S speed 0 = 1.024 Mbps, 1 = 2.048 Mbps */
+	if (state->has_i2s_conf)
+		msp_write_dem(client, 0x40, state->i2s_mode);
+}
+
+/* ------------------------------------------------------------------------ */
+
+static void msp_wake_thread(struct i2c_client *client)
+{
+	struct msp_state *state = to_state(i2c_get_clientdata(client));
+
+	if (NULL == state->kthread)
+		return;
+	state->watch_stereo = 0;
+	state->restart = 1;
+	wake_up_interruptible(&state->wq);
+}
+
+int msp_sleep(struct msp_state *state, int timeout)
+{
+	DECLARE_WAITQUEUE(wait, current);
+
+	add_wait_queue(&state->wq, &wait);
+	if (!kthread_should_stop()) {
+		if (timeout < 0) {
+			set_current_state(TASK_INTERRUPTIBLE);
+			schedule();
+		} else {
+			schedule_timeout_interruptible
+						(msecs_to_jiffies(timeout));
+		}
+	}
+
+	remove_wait_queue(&state->wq, &wait);
+	try_to_freeze();
+	return state->restart;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int msp_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct msp_state *state = ctrl_to_state(ctrl);
+	struct i2c_client *client = v4l2_get_subdevdata(&state->sd);
+	int val = ctrl->val;
+
+	switch (ctrl->id) {
+	case V4L2_CID_AUDIO_VOLUME: {
+		/* audio volume cluster */
+		int reallymuted = state->muted->val | state->scan_in_progress;
+
+		if (!reallymuted)
+			val = (val * 0x7f / 65535) << 8;
+
+		v4l_dbg(1, msp_debug, client, "mute=%s scanning=%s volume=%d\n",
+				state->muted->val ? "on" : "off",
+				state->scan_in_progress ? "yes" : "no",
+				state->volume->val);
+
+		msp_write_dsp(client, 0x0000, val);
+		msp_write_dsp(client, 0x0007, reallymuted ? 0x1 : (val | 0x1));
+		if (state->has_scart2_out_volume)
+			msp_write_dsp(client, 0x0040, reallymuted ? 0x1 : (val | 0x1));
+		if (state->has_headphones)
+			msp_write_dsp(client, 0x0006, val);
+		break;
+	}
+
+	case V4L2_CID_AUDIO_BASS:
+		val = ((val - 32768) * 0x60 / 65535) << 8;
+		msp_write_dsp(client, 0x0002, val);
+		if (state->has_headphones)
+			msp_write_dsp(client, 0x0031, val);
+		break;
+
+	case V4L2_CID_AUDIO_TREBLE:
+		val = ((val - 32768) * 0x60 / 65535) << 8;
+		msp_write_dsp(client, 0x0003, val);
+		if (state->has_headphones)
+			msp_write_dsp(client, 0x0032, val);
+		break;
+
+	case V4L2_CID_AUDIO_LOUDNESS:
+		val = val ? ((5 * 4) << 8) : 0;
+		msp_write_dsp(client, 0x0004, val);
+		if (state->has_headphones)
+			msp_write_dsp(client, 0x0033, val);
+		break;
+
+	case V4L2_CID_AUDIO_BALANCE:
+		val = (u8)((val / 256) - 128);
+		msp_write_dsp(client, 0x0001, val << 8);
+		if (state->has_headphones)
+			msp_write_dsp(client, 0x0030, val << 8);
+		break;
+
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+void msp_update_volume(struct msp_state *state)
+{
+	/* Force an update of the volume/mute cluster */
+	v4l2_ctrl_lock(state->volume);
+	state->volume->val = state->volume->cur.val;
+	state->muted->val = state->muted->cur.val;
+	msp_s_ctrl(state->volume);
+	v4l2_ctrl_unlock(state->volume);
+}
+
+/* --- v4l2 ioctls --- */
+static int msp_s_radio(struct v4l2_subdev *sd)
+{
+	struct msp_state *state = to_state(sd);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	if (state->radio)
+		return 0;
+	state->radio = 1;
+	v4l_dbg(1, msp_debug, client, "switching to radio mode\n");
+	state->watch_stereo = 0;
+	switch (state->opmode) {
+	case OPMODE_MANUAL:
+		/* set msp3400 to FM radio mode */
+		msp3400c_set_mode(client, MSP_MODE_FM_RADIO);
+		msp3400c_set_carrier(client, MSP_CARRIER(10.7),
+				MSP_CARRIER(10.7));
+		msp_update_volume(state);
+		break;
+	case OPMODE_AUTODETECT:
+	case OPMODE_AUTOSELECT:
+		/* the thread will do for us */
+		msp_wake_thread(client);
+		break;
+	}
+	return 0;
+}
+
+static int msp_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *freq)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	/* new channel -- kick audio carrier scan */
+	msp_wake_thread(client);
+	return 0;
+}
+
+static int msp_querystd(struct v4l2_subdev *sd, v4l2_std_id *id)
+{
+	struct msp_state *state = to_state(sd);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	*id &= state->detected_std;
+
+	v4l_dbg(2, msp_debug, client,
+		"detected standard: %s(0x%08Lx)\n",
+		msp_standard_std_name(state->std), state->detected_std);
+
+	return 0;
+}
+
+static int msp_s_std(struct v4l2_subdev *sd, v4l2_std_id id)
+{
+	struct msp_state *state = to_state(sd);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	int update = state->radio || state->v4l2_std != id;
+
+	state->v4l2_std = id;
+	state->radio = 0;
+	if (update)
+		msp_wake_thread(client);
+	return 0;
+}
+
+static int msp_s_routing(struct v4l2_subdev *sd,
+			 u32 input, u32 output, u32 config)
+{
+	struct msp_state *state = to_state(sd);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	int tuner = (input >> 3) & 1;
+	int sc_in = input & 0x7;
+	int sc1_out = output & 0xf;
+	int sc2_out = (output >> 4) & 0xf;
+	u16 val, reg;
+	int i;
+	int extern_input = 1;
+
+	if (state->route_in == input && state->route_out == output)
+		return 0;
+	state->route_in = input;
+	state->route_out = output;
+	/* check if the tuner input is used */
+	for (i = 0; i < 5; i++) {
+		if (((input >> (4 + i * 4)) & 0xf) == 0)
+			extern_input = 0;
+	}
+	state->mode = extern_input ? MSP_MODE_EXTERN : MSP_MODE_AM_DETECT;
+	state->rxsubchans = V4L2_TUNER_SUB_STEREO;
+	msp_set_scart(client, sc_in, 0);
+	msp_set_scart(client, sc1_out, 1);
+	msp_set_scart(client, sc2_out, 2);
+	msp_set_audmode(client);
+	reg = (state->opmode == OPMODE_AUTOSELECT) ? 0x30 : 0xbb;
+	val = msp_read_dem(client, reg);
+	msp_write_dem(client, reg, (val & ~0x100) | (tuner << 8));
+	/* wake thread when a new input is chosen */
+	msp_wake_thread(client);
+	return 0;
+}
+
+static int msp_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
+{
+	struct msp_state *state = to_state(sd);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	if (vt->type != V4L2_TUNER_ANALOG_TV)
+		return 0;
+	if (!state->radio) {
+		if (state->opmode == OPMODE_AUTOSELECT)
+			msp_detect_stereo(client);
+		vt->rxsubchans = state->rxsubchans;
+	}
+	vt->audmode = state->audmode;
+	vt->capability |= V4L2_TUNER_CAP_STEREO |
+		V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2;
+	return 0;
+}
+
+static int msp_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
+{
+	struct msp_state *state = to_state(sd);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	if (state->radio)  /* TODO: add mono/stereo support for radio */
+		return 0;
+	if (state->audmode == vt->audmode)
+		return 0;
+	state->audmode = vt->audmode;
+	/* only set audmode */
+	msp_set_audmode(client);
+	return 0;
+}
+
+static int msp_s_i2s_clock_freq(struct v4l2_subdev *sd, u32 freq)
+{
+	struct msp_state *state = to_state(sd);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	v4l_dbg(1, msp_debug, client, "Setting I2S speed to %d\n", freq);
+
+	switch (freq) {
+		case 1024000:
+			state->i2s_mode = 0;
+			break;
+		case 2048000:
+			state->i2s_mode = 1;
+			break;
+		default:
+			return -EINVAL;
+	}
+	return 0;
+}
+
+static int msp_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
+{
+	struct msp_state *state = to_state(sd);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	return v4l2_chip_ident_i2c_client(client, chip, state->ident,
+			(state->rev1 << 16) | state->rev2);
+}
+
+static int msp_log_status(struct v4l2_subdev *sd)
+{
+	struct msp_state *state = to_state(sd);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	const char *p;
+	char prefix[V4L2_SUBDEV_NAME_SIZE + 20];
+
+	if (state->opmode == OPMODE_AUTOSELECT)
+		msp_detect_stereo(client);
+	v4l_info(client, "%s rev1 = 0x%04x rev2 = 0x%04x\n",
+			client->name, state->rev1, state->rev2);
+	snprintf(prefix, sizeof(prefix), "%s: Audio:    ", sd->name);
+	v4l2_ctrl_handler_log_status(&state->hdl, prefix);
+	switch (state->mode) {
+		case MSP_MODE_AM_DETECT: p = "AM (for carrier detect)"; break;
+		case MSP_MODE_FM_RADIO: p = "FM Radio"; break;
+		case MSP_MODE_FM_TERRA: p = "Terrestrial FM-mono/stereo"; break;
+		case MSP_MODE_FM_SAT: p = "Satellite FM-mono"; break;
+		case MSP_MODE_FM_NICAM1: p = "NICAM/FM (B/G, D/K)"; break;
+		case MSP_MODE_FM_NICAM2: p = "NICAM/FM (I)"; break;
+		case MSP_MODE_AM_NICAM: p = "NICAM/AM (L)"; break;
+		case MSP_MODE_BTSC: p = "BTSC"; break;
+		case MSP_MODE_EXTERN: p = "External input"; break;
+		default: p = "unknown"; break;
+	}
+	if (state->mode == MSP_MODE_EXTERN) {
+		v4l_info(client, "Mode:     %s\n", p);
+	} else if (state->opmode == OPMODE_MANUAL) {
+		v4l_info(client, "Mode:     %s (%s%s)\n", p,
+				(state->rxsubchans & V4L2_TUNER_SUB_STEREO) ? "stereo" : "mono",
+				(state->rxsubchans & V4L2_TUNER_SUB_LANG2) ? ", dual" : "");
+	} else {
+		if (state->opmode == OPMODE_AUTODETECT)
+			v4l_info(client, "Mode:     %s\n", p);
+		v4l_info(client, "Standard: %s (%s%s)\n",
+				msp_standard_std_name(state->std),
+				(state->rxsubchans & V4L2_TUNER_SUB_STEREO) ? "stereo" : "mono",
+				(state->rxsubchans & V4L2_TUNER_SUB_LANG2) ? ", dual" : "");
+	}
+	v4l_info(client, "Audmode:  0x%04x\n", state->audmode);
+	v4l_info(client, "Routing:  0x%08x (input) 0x%08x (output)\n",
+			state->route_in, state->route_out);
+	v4l_info(client, "ACB:      0x%04x\n", state->acb);
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int msp_suspend(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	v4l_dbg(1, msp_debug, client, "suspend\n");
+	msp_reset(client);
+	return 0;
+}
+
+static int msp_resume(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	v4l_dbg(1, msp_debug, client, "resume\n");
+	msp_wake_thread(client);
+	return 0;
+}
+#endif
+
+/* ----------------------------------------------------------------------- */
+
+static const struct v4l2_ctrl_ops msp_ctrl_ops = {
+	.s_ctrl = msp_s_ctrl,
+};
+
+static const struct v4l2_subdev_core_ops msp_core_ops = {
+	.log_status = msp_log_status,
+	.g_chip_ident = msp_g_chip_ident,
+	.g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
+	.try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
+	.s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
+	.g_ctrl = v4l2_subdev_g_ctrl,
+	.s_ctrl = v4l2_subdev_s_ctrl,
+	.queryctrl = v4l2_subdev_queryctrl,
+	.querymenu = v4l2_subdev_querymenu,
+	.s_std = msp_s_std,
+};
+
+static const struct v4l2_subdev_video_ops msp_video_ops = {
+	.querystd = msp_querystd,
+};
+
+static const struct v4l2_subdev_tuner_ops msp_tuner_ops = {
+	.s_frequency = msp_s_frequency,
+	.g_tuner = msp_g_tuner,
+	.s_tuner = msp_s_tuner,
+	.s_radio = msp_s_radio,
+};
+
+static const struct v4l2_subdev_audio_ops msp_audio_ops = {
+	.s_routing = msp_s_routing,
+	.s_i2s_clock_freq = msp_s_i2s_clock_freq,
+};
+
+static const struct v4l2_subdev_ops msp_ops = {
+	.core = &msp_core_ops,
+	.video = &msp_video_ops,
+	.tuner = &msp_tuner_ops,
+	.audio = &msp_audio_ops,
+};
+
+/* ----------------------------------------------------------------------- */
+
+static int msp_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+	struct msp_state *state;
+	struct v4l2_subdev *sd;
+	struct v4l2_ctrl_handler *hdl;
+	int (*thread_func)(void *data) = NULL;
+	int msp_hard;
+	int msp_family;
+	int msp_revision;
+	int msp_product, msp_prod_hi, msp_prod_lo;
+	int msp_rom;
+
+	if (!id)
+		strlcpy(client->name, "msp3400", sizeof(client->name));
+
+	if (msp_reset(client) == -1) {
+		v4l_dbg(1, msp_debug, client, "msp3400 not found\n");
+		return -ENODEV;
+	}
+
+	state = kzalloc(sizeof(*state), GFP_KERNEL);
+	if (!state)
+		return -ENOMEM;
+
+	sd = &state->sd;
+	v4l2_i2c_subdev_init(sd, client, &msp_ops);
+
+	state->v4l2_std = V4L2_STD_NTSC;
+	state->detected_std = V4L2_STD_ALL;
+	state->audmode = V4L2_TUNER_MODE_STEREO;
+	state->input = -1;
+	state->i2s_mode = 0;
+	init_waitqueue_head(&state->wq);
+	/* These are the reset input/output positions */
+	state->route_in = MSP_INPUT_DEFAULT;
+	state->route_out = MSP_OUTPUT_DEFAULT;
+
+	state->rev1 = msp_read_dsp(client, 0x1e);
+	if (state->rev1 != -1)
+		state->rev2 = msp_read_dsp(client, 0x1f);
+	v4l_dbg(1, msp_debug, client, "rev1=0x%04x, rev2=0x%04x\n",
+			state->rev1, state->rev2);
+	if (state->rev1 == -1 || (state->rev1 == 0 && state->rev2 == 0)) {
+		v4l_dbg(1, msp_debug, client,
+				"not an msp3400 (cannot read chip version)\n");
+		kfree(state);
+		return -ENODEV;
+	}
+
+	msp_family = ((state->rev1 >> 4) & 0x0f) + 3;
+	msp_product = (state->rev2 >> 8) & 0xff;
+	msp_prod_hi = msp_product / 10;
+	msp_prod_lo = msp_product % 10;
+	msp_revision = (state->rev1 & 0x0f) + '@';
+	msp_hard = ((state->rev1 >> 8) & 0xff) + '@';
+	msp_rom = state->rev2 & 0x1f;
+	/* Rev B=2, C=3, D=4, G=7 */
+	state->ident = msp_family * 10000 + 4000 + msp_product * 10 +
+			msp_revision - '@';
+
+	/* Has NICAM support: all mspx41x and mspx45x products have NICAM */
+	state->has_nicam =
+		msp_prod_hi == 1 || msp_prod_hi == 5;
+	/* Has radio support: was added with revision G */
+	state->has_radio =
+		msp_revision >= 'G';
+	/* Has headphones output: not for stripped down products */
+	state->has_headphones =
+		msp_prod_lo < 5;
+	/* Has scart2 input: not in stripped down products of the '3' family */
+	state->has_scart2 =
+		msp_family >= 4 || msp_prod_lo < 7;
+	/* Has scart3 input: not in stripped down products of the '3' family */
+	state->has_scart3 =
+		msp_family >= 4 || msp_prod_lo < 5;
+	/* Has scart4 input: not in pre D revisions, not in stripped D revs */
+	state->has_scart4 =
+		msp_family >= 4 || (msp_revision >= 'D' && msp_prod_lo < 5);
+	/* Has scart2 output: not in stripped down products of
+	 * the '3' family */
+	state->has_scart2_out =
+		msp_family >= 4 || msp_prod_lo < 5;
+	/* Has scart2 a volume control? Not in pre-D revisions. */
+	state->has_scart2_out_volume =
+		msp_revision > 'C' && state->has_scart2_out;
+	/* Has a configurable i2s out? */
+	state->has_i2s_conf =
+		msp_revision >= 'G' && msp_prod_lo < 7;
+	/* Has subwoofer output: not in pre-D revs and not in stripped down
+	 * products */
+	state->has_subwoofer =
+		msp_revision >= 'D' && msp_prod_lo < 5;
+	/* Has soundprocessing (bass/treble/balance/loudness/equalizer):
+	 *  not in stripped down products */
+	state->has_sound_processing =
+		msp_prod_lo < 7;
+	/* Has Virtual Dolby Surround: only in msp34x1 */
+	state->has_virtual_dolby_surround =
+		msp_revision == 'G' && msp_prod_lo == 1;
+	/* Has Virtual Dolby Surround & Dolby Pro Logic: only in msp34x2 */
+	state->has_dolby_pro_logic =
+		msp_revision == 'G' && msp_prod_lo == 2;
+	/* The msp343xG supports BTSC only and cannot do Automatic Standard
+	 * Detection. */
+	state->force_btsc =
+		msp_family == 3 && msp_revision == 'G' && msp_prod_hi == 3;
+
+	state->opmode = opmode;
+	if (state->opmode == OPMODE_AUTO) {
+		/* MSP revision G and up have both autodetect and autoselect */
+		if (msp_revision >= 'G')
+			state->opmode = OPMODE_AUTOSELECT;
+		/* MSP revision D and up have autodetect */
+		else if (msp_revision >= 'D')
+			state->opmode = OPMODE_AUTODETECT;
+		else
+			state->opmode = OPMODE_MANUAL;
+	}
+
+	hdl = &state->hdl;
+	v4l2_ctrl_handler_init(hdl, 6);
+	if (state->has_sound_processing) {
+		v4l2_ctrl_new_std(hdl, &msp_ctrl_ops,
+			V4L2_CID_AUDIO_BASS, 0, 65535, 65535 / 100, 32768);
+		v4l2_ctrl_new_std(hdl, &msp_ctrl_ops,
+			V4L2_CID_AUDIO_TREBLE, 0, 65535, 65535 / 100, 32768);
+		v4l2_ctrl_new_std(hdl, &msp_ctrl_ops,
+			V4L2_CID_AUDIO_LOUDNESS, 0, 1, 1, 0);
+	}
+	state->volume = v4l2_ctrl_new_std(hdl, &msp_ctrl_ops,
+			V4L2_CID_AUDIO_VOLUME, 0, 65535, 65535 / 100, 58880);
+	v4l2_ctrl_new_std(hdl, &msp_ctrl_ops,
+			V4L2_CID_AUDIO_BALANCE, 0, 65535, 65535 / 100, 32768);
+	state->muted = v4l2_ctrl_new_std(hdl, &msp_ctrl_ops,
+			V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0);
+	sd->ctrl_handler = hdl;
+	if (hdl->error) {
+		int err = hdl->error;
+
+		v4l2_ctrl_handler_free(hdl);
+		kfree(state);
+		return err;
+	}
+
+	v4l2_ctrl_cluster(2, &state->volume);
+	v4l2_ctrl_handler_setup(hdl);
+
+	/* hello world :-) */
+	v4l_info(client, "MSP%d4%02d%c-%c%d found @ 0x%x (%s)\n",
+			msp_family, msp_product,
+			msp_revision, msp_hard, msp_rom,
+			client->addr << 1, client->adapter->name);
+	v4l_info(client, "%s ", client->name);
+	if (state->has_nicam && state->has_radio)
+		printk(KERN_CONT "supports nicam and radio, ");
+	else if (state->has_nicam)
+		printk(KERN_CONT "supports nicam, ");
+	else if (state->has_radio)
+		printk(KERN_CONT "supports radio, ");
+	printk(KERN_CONT "mode is ");
+
+	/* version-specific initialization */
+	switch (state->opmode) {
+	case OPMODE_MANUAL:
+		printk(KERN_CONT "manual");
+		thread_func = msp3400c_thread;
+		break;
+	case OPMODE_AUTODETECT:
+		printk(KERN_CONT "autodetect");
+		thread_func = msp3410d_thread;
+		break;
+	case OPMODE_AUTOSELECT:
+		printk(KERN_CONT "autodetect and autoselect");
+		thread_func = msp34xxg_thread;
+		break;
+	}
+	printk(KERN_CONT "\n");
+
+	/* startup control thread if needed */
+	if (thread_func) {
+		state->kthread = kthread_run(thread_func, client, "msp34xx");
+
+		if (IS_ERR(state->kthread))
+			v4l_warn(client, "kernel_thread() failed\n");
+		msp_wake_thread(client);
+	}
+	return 0;
+}
+
+static int msp_remove(struct i2c_client *client)
+{
+	struct msp_state *state = to_state(i2c_get_clientdata(client));
+
+	v4l2_device_unregister_subdev(&state->sd);
+	/* shutdown control thread */
+	if (state->kthread) {
+		state->restart = 1;
+		kthread_stop(state->kthread);
+	}
+	msp_reset(client);
+
+	v4l2_ctrl_handler_free(&state->hdl);
+	kfree(state);
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static const struct dev_pm_ops msp3400_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(msp_suspend, msp_resume)
+};
+
+static const struct i2c_device_id msp_id[] = {
+	{ "msp3400", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, msp_id);
+
+static struct i2c_driver msp_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "msp3400",
+		.pm	= &msp3400_pm_ops,
+	},
+	.probe		= msp_probe,
+	.remove		= msp_remove,
+	.id_table	= msp_id,
+};
+
+module_i2c_driver(msp_driver);
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/i2c/msp3400-driver.h b/drivers/media/i2c/msp3400-driver.h
new file mode 100644
index 0000000..fbe5e07
--- /dev/null
+++ b/drivers/media/i2c/msp3400-driver.h
@@ -0,0 +1,137 @@
+/*
+ */
+
+#ifndef MSP3400_DRIVER_H
+#define MSP3400_DRIVER_H
+
+#include <media/msp3400.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ctrls.h>
+
+/* ---------------------------------------------------------------------- */
+
+/* This macro is allowed for *constants* only, gcc must calculate it
+   at compile time.  Remember -- no floats in kernel mode */
+#define MSP_CARRIER(freq) ((int)((float)(freq / 18.432) * (1 << 24)))
+
+#define MSP_MODE_AM_DETECT   0
+#define MSP_MODE_FM_RADIO    2
+#define MSP_MODE_FM_TERRA    3
+#define MSP_MODE_FM_SAT      4
+#define MSP_MODE_FM_NICAM1   5
+#define MSP_MODE_FM_NICAM2   6
+#define MSP_MODE_AM_NICAM    7
+#define MSP_MODE_BTSC        8
+#define MSP_MODE_EXTERN      9
+
+#define SCART_IN1     0
+#define SCART_IN2     1
+#define SCART_IN3     2
+#define SCART_IN4     3
+#define SCART_IN1_DA  4
+#define SCART_IN2_DA  5
+#define SCART_MONO    6
+#define SCART_MUTE    7
+
+#define SCART_DSP_IN  0
+#define SCART1_OUT    1
+#define SCART2_OUT    2
+
+#define OPMODE_AUTO       -1
+#define OPMODE_MANUAL      0
+#define OPMODE_AUTODETECT  1   /* use autodetect (>= msp3410 only) */
+#define OPMODE_AUTOSELECT  2   /* use autodetect & autoselect (>= msp34xxG)   */
+
+/* module parameters */
+extern int msp_debug;
+extern bool msp_once;
+extern bool msp_amsound;
+extern int msp_standard;
+extern bool msp_dolby;
+extern int msp_stereo_thresh;
+
+struct msp_state {
+	struct v4l2_subdev sd;
+	struct v4l2_ctrl_handler hdl;
+	int rev1, rev2;
+	int ident;
+	u8 has_nicam;
+	u8 has_radio;
+	u8 has_headphones;
+	u8 has_ntsc_jp_d_k3;
+	u8 has_scart2;
+	u8 has_scart3;
+	u8 has_scart4;
+	u8 has_scart2_out;
+	u8 has_scart2_out_volume;
+	u8 has_i2s_conf;
+	u8 has_subwoofer;
+	u8 has_sound_processing;
+	u8 has_virtual_dolby_surround;
+	u8 has_dolby_pro_logic;
+	u8 force_btsc;
+
+	int radio;
+	int opmode;
+	int std;
+	int mode;
+	v4l2_std_id v4l2_std, detected_std;
+	int nicam_on;
+	int acb;
+	int in_scart;
+	int i2s_mode;
+	int main, second;	/* sound carrier */
+	int input;
+	u32 route_in;
+	u32 route_out;
+
+	/* v4l2 */
+	int audmode;
+	int rxsubchans;
+
+	struct {
+		/* volume cluster */
+		struct v4l2_ctrl *volume;
+		struct v4l2_ctrl *muted;
+	};
+
+	int scan_in_progress;
+
+	/* thread */
+	struct task_struct   *kthread;
+	wait_queue_head_t    wq;
+	unsigned int         restart:1;
+	unsigned int         watch_stereo:1;
+};
+
+static inline struct msp_state *to_state(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct msp_state, sd);
+}
+
+static inline struct msp_state *ctrl_to_state(struct v4l2_ctrl *ctrl)
+{
+	return container_of(ctrl->handler, struct msp_state, hdl);
+}
+
+/* msp3400-driver.c */
+int msp_write_dem(struct i2c_client *client, int addr, int val);
+int msp_write_dsp(struct i2c_client *client, int addr, int val);
+int msp_read_dem(struct i2c_client *client, int addr);
+int msp_read_dsp(struct i2c_client *client, int addr);
+int msp_reset(struct i2c_client *client);
+void msp_set_scart(struct i2c_client *client, int in, int out);
+void msp_update_volume(struct msp_state *state);
+int msp_sleep(struct msp_state *state, int timeout);
+
+/* msp3400-kthreads.c */
+const char *msp_standard_std_name(int std);
+void msp_set_audmode(struct i2c_client *client);
+int msp_detect_stereo(struct i2c_client *client);
+int msp3400c_thread(void *data);
+int msp3410d_thread(void *data);
+int msp34xxg_thread(void *data);
+void msp3400c_set_mode(struct i2c_client *client, int mode);
+void msp3400c_set_carrier(struct i2c_client *client, int cdo1, int cdo2);
+
+#endif /* MSP3400_DRIVER_H */
diff --git a/drivers/media/i2c/msp3400-kthreads.c b/drivers/media/i2c/msp3400-kthreads.c
new file mode 100644
index 0000000..f8b5171
--- /dev/null
+++ b/drivers/media/i2c/msp3400-kthreads.c
@@ -0,0 +1,1165 @@
+/*
+ * Programming the mspx4xx sound processor family
+ *
+ * (c) 1997-2001 Gerd Knorr <kraxel@bytesex.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., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/freezer.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
+#include <media/msp3400.h>
+#include <linux/kthread.h>
+#include <linux/suspend.h>
+#include "msp3400-driver.h"
+
+/* this one uses the automatic sound standard detection of newer msp34xx
+   chip versions */
+static struct {
+	int retval;
+	int main, second;
+	char *name;
+	v4l2_std_id std;
+} msp_stdlist[] = {
+	{ 0x0000, 0, 0, "could not detect sound standard", V4L2_STD_ALL },
+	{ 0x0001, 0, 0, "autodetect start", V4L2_STD_ALL },
+	{ 0x0002, MSP_CARRIER(4.5), MSP_CARRIER(4.72),
+	  "4.5/4.72  M Dual FM-Stereo", V4L2_STD_MN },
+	{ 0x0003, MSP_CARRIER(5.5), MSP_CARRIER(5.7421875),
+	  "5.5/5.74  B/G Dual FM-Stereo", V4L2_STD_BG },
+	{ 0x0004, MSP_CARRIER(6.5), MSP_CARRIER(6.2578125),
+	  "6.5/6.25  D/K1 Dual FM-Stereo", V4L2_STD_DK },
+	{ 0x0005, MSP_CARRIER(6.5), MSP_CARRIER(6.7421875),
+	  "6.5/6.74  D/K2 Dual FM-Stereo", V4L2_STD_DK },
+	{ 0x0006, MSP_CARRIER(6.5), MSP_CARRIER(6.5),
+	  "6.5  D/K FM-Mono (HDEV3)", V4L2_STD_DK },
+	{ 0x0007, MSP_CARRIER(6.5), MSP_CARRIER(5.7421875),
+	  "6.5/5.74  D/K3 Dual FM-Stereo", V4L2_STD_DK },
+	{ 0x0008, MSP_CARRIER(5.5), MSP_CARRIER(5.85),
+	  "5.5/5.85  B/G NICAM FM", V4L2_STD_BG },
+	{ 0x0009, MSP_CARRIER(6.5), MSP_CARRIER(5.85),
+	  "6.5/5.85  L NICAM AM", V4L2_STD_L },
+	{ 0x000a, MSP_CARRIER(6.0), MSP_CARRIER(6.55),
+	  "6.0/6.55  I NICAM FM", V4L2_STD_PAL_I },
+	{ 0x000b, MSP_CARRIER(6.5), MSP_CARRIER(5.85),
+	  "6.5/5.85  D/K NICAM FM", V4L2_STD_DK },
+	{ 0x000c, MSP_CARRIER(6.5), MSP_CARRIER(5.85),
+	  "6.5/5.85  D/K NICAM FM (HDEV2)", V4L2_STD_DK },
+	{ 0x000d, MSP_CARRIER(6.5), MSP_CARRIER(5.85),
+	  "6.5/5.85  D/K NICAM FM (HDEV3)", V4L2_STD_DK },
+	{ 0x0020, MSP_CARRIER(4.5), MSP_CARRIER(4.5),
+	  "4.5  M BTSC-Stereo", V4L2_STD_MTS },
+	{ 0x0021, MSP_CARRIER(4.5), MSP_CARRIER(4.5),
+	  "4.5  M BTSC-Mono + SAP", V4L2_STD_MTS },
+	{ 0x0030, MSP_CARRIER(4.5), MSP_CARRIER(4.5),
+	  "4.5  M EIA-J Japan Stereo", V4L2_STD_NTSC_M_JP },
+	{ 0x0040, MSP_CARRIER(10.7), MSP_CARRIER(10.7),
+	  "10.7  FM-Stereo Radio", V4L2_STD_ALL },
+	{ 0x0050, MSP_CARRIER(6.5), MSP_CARRIER(6.5),
+	  "6.5  SAT-Mono", V4L2_STD_ALL },
+	{ 0x0051, MSP_CARRIER(7.02), MSP_CARRIER(7.20),
+	  "7.02/7.20  SAT-Stereo", V4L2_STD_ALL },
+	{ 0x0060, MSP_CARRIER(7.2), MSP_CARRIER(7.2),
+	  "7.2  SAT ADR", V4L2_STD_ALL },
+	{     -1, 0, 0, NULL, 0 }, /* EOF */
+};
+
+static struct msp3400c_init_data_dem {
+	int fir1[6];
+	int fir2[6];
+	int cdo1;
+	int cdo2;
+	int ad_cv;
+	int mode_reg;
+	int dsp_src;
+	int dsp_matrix;
+} msp3400c_init_data[] = {
+	{	/* AM (for carrier detect / msp3400) */
+		{75, 19, 36, 35, 39, 40},
+		{75, 19, 36, 35, 39, 40},
+		MSP_CARRIER(5.5), MSP_CARRIER(5.5),
+		0x00d0, 0x0500, 0x0020, 0x3000
+	}, {	/* AM (for carrier detect / msp3410) */
+		{-1, -1, -8, 2, 59, 126},
+		{-1, -1, -8, 2, 59, 126},
+		MSP_CARRIER(5.5), MSP_CARRIER(5.5),
+		0x00d0, 0x0100, 0x0020, 0x3000
+	}, {	/* FM Radio */
+		{-8, -8, 4, 6, 78, 107},
+		{-8, -8, 4, 6, 78, 107},
+		MSP_CARRIER(10.7), MSP_CARRIER(10.7),
+		0x00d0, 0x0480, 0x0020, 0x3000
+	}, {	/* Terrestrial FM-mono + FM-stereo */
+		{3, 18, 27, 48, 66, 72},
+		{3, 18, 27, 48, 66, 72},
+		MSP_CARRIER(5.5), MSP_CARRIER(5.5),
+		0x00d0, 0x0480, 0x0030, 0x3000
+	}, {	/* Sat FM-mono */
+		{ 1, 9, 14, 24, 33, 37},
+		{ 3, 18, 27, 48, 66, 72},
+		MSP_CARRIER(6.5), MSP_CARRIER(6.5),
+		0x00c6, 0x0480, 0x0000, 0x3000
+	}, {	/* NICAM/FM --  B/G (5.5/5.85), D/K (6.5/5.85) */
+		{-2, -8, -10, 10, 50, 86},
+		{3, 18, 27, 48, 66, 72},
+		MSP_CARRIER(5.5), MSP_CARRIER(5.5),
+		0x00d0, 0x0040, 0x0120, 0x3000
+	}, {	/* NICAM/FM -- I (6.0/6.552) */
+		{2, 4, -6, -4, 40, 94},
+		{3, 18, 27, 48, 66, 72},
+		MSP_CARRIER(6.0), MSP_CARRIER(6.0),
+		0x00d0, 0x0040, 0x0120, 0x3000
+	}, {	/* NICAM/AM -- L (6.5/5.85) */
+		{-2, -8, -10, 10, 50, 86},
+		{-4, -12, -9, 23, 79, 126},
+		MSP_CARRIER(6.5), MSP_CARRIER(6.5),
+		0x00c6, 0x0140, 0x0120, 0x7c00
+	},
+};
+
+struct msp3400c_carrier_detect {
+	int   cdo;
+	char *name;
+};
+
+static struct msp3400c_carrier_detect msp3400c_carrier_detect_main[] = {
+	/* main carrier */
+	{ MSP_CARRIER(4.5),        "4.5   NTSC"                   },
+	{ MSP_CARRIER(5.5),        "5.5   PAL B/G"                },
+	{ MSP_CARRIER(6.0),        "6.0   PAL I"                  },
+	{ MSP_CARRIER(6.5),        "6.5   PAL D/K + SAT + SECAM"  }
+};
+
+static struct msp3400c_carrier_detect msp3400c_carrier_detect_55[] = {
+	/* PAL B/G */
+	{ MSP_CARRIER(5.7421875),  "5.742 PAL B/G FM-stereo"     },
+	{ MSP_CARRIER(5.85),       "5.85  PAL B/G NICAM"         }
+};
+
+static struct msp3400c_carrier_detect msp3400c_carrier_detect_65[] = {
+	/* PAL SAT / SECAM */
+	{ MSP_CARRIER(5.85),       "5.85  PAL D/K + SECAM NICAM" },
+	{ MSP_CARRIER(6.2578125),  "6.25  PAL D/K1 FM-stereo" },
+	{ MSP_CARRIER(6.7421875),  "6.74  PAL D/K2 FM-stereo" },
+	{ MSP_CARRIER(7.02),       "7.02  PAL SAT FM-stereo s/b" },
+	{ MSP_CARRIER(7.20),       "7.20  PAL SAT FM-stereo s"   },
+	{ MSP_CARRIER(7.38),       "7.38  PAL SAT FM-stereo b"   },
+};
+
+/* ------------------------------------------------------------------------ */
+
+const char *msp_standard_std_name(int std)
+{
+	int i;
+
+	for (i = 0; msp_stdlist[i].name != NULL; i++)
+		if (msp_stdlist[i].retval == std)
+			return msp_stdlist[i].name;
+	return "unknown";
+}
+
+static v4l2_std_id msp_standard_std(int std)
+{
+	int i;
+
+	for (i = 0; msp_stdlist[i].name != NULL; i++)
+		if (msp_stdlist[i].retval == std)
+			return msp_stdlist[i].std;
+	return V4L2_STD_ALL;
+}
+
+static void msp_set_source(struct i2c_client *client, u16 src)
+{
+	struct msp_state *state = to_state(i2c_get_clientdata(client));
+
+	if (msp_dolby) {
+		msp_write_dsp(client, 0x0008, 0x0520); /* I2S1 */
+		msp_write_dsp(client, 0x0009, 0x0620); /* I2S2 */
+	} else {
+		msp_write_dsp(client, 0x0008, src);
+		msp_write_dsp(client, 0x0009, src);
+	}
+	msp_write_dsp(client, 0x000a, src);
+	msp_write_dsp(client, 0x000b, src);
+	msp_write_dsp(client, 0x000c, src);
+	if (state->has_scart2_out)
+		msp_write_dsp(client, 0x0041, src);
+}
+
+void msp3400c_set_carrier(struct i2c_client *client, int cdo1, int cdo2)
+{
+	msp_write_dem(client, 0x0093, cdo1 & 0xfff);
+	msp_write_dem(client, 0x009b, cdo1 >> 12);
+	msp_write_dem(client, 0x00a3, cdo2 & 0xfff);
+	msp_write_dem(client, 0x00ab, cdo2 >> 12);
+	msp_write_dem(client, 0x0056, 0); /* LOAD_REG_1/2 */
+}
+
+void msp3400c_set_mode(struct i2c_client *client, int mode)
+{
+	struct msp_state *state = to_state(i2c_get_clientdata(client));
+	struct msp3400c_init_data_dem *data = &msp3400c_init_data[mode];
+	int tuner = (state->route_in >> 3) & 1;
+	int i;
+
+	v4l_dbg(1, msp_debug, client, "set_mode: %d\n", mode);
+	state->mode = mode;
+	state->rxsubchans = V4L2_TUNER_SUB_MONO;
+
+	msp_write_dem(client, 0x00bb, data->ad_cv | (tuner ? 0x100 : 0));
+
+	for (i = 5; i >= 0; i--)               /* fir 1 */
+		msp_write_dem(client, 0x0001, data->fir1[i]);
+
+	msp_write_dem(client, 0x0005, 0x0004); /* fir 2 */
+	msp_write_dem(client, 0x0005, 0x0040);
+	msp_write_dem(client, 0x0005, 0x0000);
+	for (i = 5; i >= 0; i--)
+		msp_write_dem(client, 0x0005, data->fir2[i]);
+
+	msp_write_dem(client, 0x0083, data->mode_reg);
+
+	msp3400c_set_carrier(client, data->cdo1, data->cdo2);
+
+	msp_set_source(client, data->dsp_src);
+	/* set prescales */
+
+	/* volume prescale for SCART (AM mono input) */
+	msp_write_dsp(client, 0x000d, 0x1900);
+	msp_write_dsp(client, 0x000e, data->dsp_matrix);
+	if (state->has_nicam) /* nicam prescale */
+		msp_write_dsp(client, 0x0010, 0x5a00);
+}
+
+/* Set audio mode. Note that the pre-'G' models do not support BTSC+SAP,
+   nor do they support stereo BTSC. */
+static void msp3400c_set_audmode(struct i2c_client *client)
+{
+	static char *strmode[] = {
+		"mono", "stereo", "lang2", "lang1", "lang1+lang2"
+	};
+	struct msp_state *state = to_state(i2c_get_clientdata(client));
+	char *modestr = (state->audmode >= 0 && state->audmode < 5) ?
+		strmode[state->audmode] : "unknown";
+	int src = 0;	/* channel source: FM/AM, nicam or SCART */
+	int audmode = state->audmode;
+
+	if (state->opmode == OPMODE_AUTOSELECT) {
+		/* this method would break everything, let's make sure
+		 * it's never called
+		 */
+		v4l_dbg(1, msp_debug, client,
+			"set_audmode called with mode=%d instead of set_source (ignored)\n",
+			state->audmode);
+		return;
+	}
+
+	/* Note: for the C and D revs no NTSC stereo + SAP is possible as
+	   the hardware does not support SAP. So the rxsubchans combination
+	   of STEREO | LANG2 does not occur. */
+
+	if (state->mode != MSP_MODE_EXTERN) {
+		/* switch to mono if only mono is available */
+		if (state->rxsubchans == V4L2_TUNER_SUB_MONO)
+			audmode = V4L2_TUNER_MODE_MONO;
+		/* if bilingual */
+		else if (state->rxsubchans & V4L2_TUNER_SUB_LANG2) {
+			/* and mono or stereo, then fallback to lang1 */
+			if (audmode == V4L2_TUNER_MODE_MONO ||
+			    audmode == V4L2_TUNER_MODE_STEREO)
+				audmode = V4L2_TUNER_MODE_LANG1;
+		}
+		/* if stereo, and audmode is not mono, then switch to stereo */
+		else if (audmode != V4L2_TUNER_MODE_MONO)
+			audmode = V4L2_TUNER_MODE_STEREO;
+	}
+
+	/* switch demodulator */
+	switch (state->mode) {
+	case MSP_MODE_FM_TERRA:
+		v4l_dbg(1, msp_debug, client, "FM set_audmode: %s\n", modestr);
+		switch (audmode) {
+		case V4L2_TUNER_MODE_STEREO:
+			msp_write_dsp(client, 0x000e, 0x3001);
+			break;
+		case V4L2_TUNER_MODE_MONO:
+		case V4L2_TUNER_MODE_LANG1:
+		case V4L2_TUNER_MODE_LANG2:
+		case V4L2_TUNER_MODE_LANG1_LANG2:
+			msp_write_dsp(client, 0x000e, 0x3000);
+			break;
+		}
+		break;
+	case MSP_MODE_FM_SAT:
+		v4l_dbg(1, msp_debug, client, "SAT set_audmode: %s\n", modestr);
+		switch (audmode) {
+		case V4L2_TUNER_MODE_MONO:
+			msp3400c_set_carrier(client, MSP_CARRIER(6.5), MSP_CARRIER(6.5));
+			break;
+		case V4L2_TUNER_MODE_STEREO:
+		case V4L2_TUNER_MODE_LANG1_LANG2:
+			msp3400c_set_carrier(client, MSP_CARRIER(7.2), MSP_CARRIER(7.02));
+			break;
+		case V4L2_TUNER_MODE_LANG1:
+			msp3400c_set_carrier(client, MSP_CARRIER(7.38), MSP_CARRIER(7.02));
+			break;
+		case V4L2_TUNER_MODE_LANG2:
+			msp3400c_set_carrier(client, MSP_CARRIER(7.38), MSP_CARRIER(7.02));
+			break;
+		}
+		break;
+	case MSP_MODE_FM_NICAM1:
+	case MSP_MODE_FM_NICAM2:
+	case MSP_MODE_AM_NICAM:
+		v4l_dbg(1, msp_debug, client,
+			"NICAM set_audmode: %s\n", modestr);
+		if (state->nicam_on)
+			src = 0x0100;  /* NICAM */
+		break;
+	case MSP_MODE_BTSC:
+		v4l_dbg(1, msp_debug, client,
+			"BTSC set_audmode: %s\n", modestr);
+		break;
+	case MSP_MODE_EXTERN:
+		v4l_dbg(1, msp_debug, client,
+			"extern set_audmode: %s\n", modestr);
+		src = 0x0200;  /* SCART */
+		break;
+	case MSP_MODE_FM_RADIO:
+		v4l_dbg(1, msp_debug, client,
+			"FM-Radio set_audmode: %s\n", modestr);
+		break;
+	default:
+		v4l_dbg(1, msp_debug, client, "mono set_audmode\n");
+		return;
+	}
+
+	/* switch audio */
+	v4l_dbg(1, msp_debug, client, "set audmode %d\n", audmode);
+	switch (audmode) {
+	case V4L2_TUNER_MODE_STEREO:
+	case V4L2_TUNER_MODE_LANG1_LANG2:
+		src |= 0x0020;
+		break;
+	case V4L2_TUNER_MODE_MONO:
+		if (state->mode == MSP_MODE_AM_NICAM) {
+			v4l_dbg(1, msp_debug, client, "switching to AM mono\n");
+			/* AM mono decoding is handled by tuner, not MSP chip */
+			/* SCART switching control register */
+			msp_set_scart(client, SCART_MONO, 0);
+			src = 0x0200;
+			break;
+		}
+		if (state->rxsubchans & V4L2_TUNER_SUB_STEREO)
+			src = 0x0030;
+		break;
+	case V4L2_TUNER_MODE_LANG1:
+		break;
+	case V4L2_TUNER_MODE_LANG2:
+		src |= 0x0010;
+		break;
+	}
+	v4l_dbg(1, msp_debug, client,
+		"set_audmode final source/matrix = 0x%x\n", src);
+
+	msp_set_source(client, src);
+}
+
+static void msp3400c_print_mode(struct i2c_client *client)
+{
+	struct msp_state *state = to_state(i2c_get_clientdata(client));
+
+	if (state->main == state->second)
+		v4l_dbg(1, msp_debug, client,
+			"mono sound carrier: %d.%03d MHz\n",
+			state->main / 910000, (state->main / 910) % 1000);
+	else
+		v4l_dbg(1, msp_debug, client,
+			"main sound carrier: %d.%03d MHz\n",
+			state->main / 910000, (state->main / 910) % 1000);
+	if (state->mode == MSP_MODE_FM_NICAM1 || state->mode == MSP_MODE_FM_NICAM2)
+		v4l_dbg(1, msp_debug, client,
+			"NICAM/FM carrier  : %d.%03d MHz\n",
+			state->second / 910000, (state->second/910) % 1000);
+	if (state->mode == MSP_MODE_AM_NICAM)
+		v4l_dbg(1, msp_debug, client,
+			"NICAM/AM carrier  : %d.%03d MHz\n",
+			state->second / 910000, (state->second / 910) % 1000);
+	if (state->mode == MSP_MODE_FM_TERRA && state->main != state->second) {
+		v4l_dbg(1, msp_debug, client,
+			"FM-stereo carrier : %d.%03d MHz\n",
+			state->second / 910000, (state->second / 910) % 1000);
+	}
+}
+
+/* ----------------------------------------------------------------------- */
+
+static int msp3400c_detect_stereo(struct i2c_client *client)
+{
+	struct msp_state *state = to_state(i2c_get_clientdata(client));
+	int val;
+	int rxsubchans = state->rxsubchans;
+	int newnicam = state->nicam_on;
+	int update = 0;
+
+	switch (state->mode) {
+	case MSP_MODE_FM_TERRA:
+		val = msp_read_dsp(client, 0x18);
+		if (val > 32767)
+			val -= 65536;
+		v4l_dbg(2, msp_debug, client,
+			"stereo detect register: %d\n", val);
+		if (val > 8192) {
+			rxsubchans = V4L2_TUNER_SUB_STEREO;
+		} else if (val < -4096) {
+			rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
+		} else {
+			rxsubchans = V4L2_TUNER_SUB_MONO;
+		}
+		newnicam = 0;
+		break;
+	case MSP_MODE_FM_NICAM1:
+	case MSP_MODE_FM_NICAM2:
+	case MSP_MODE_AM_NICAM:
+		val = msp_read_dem(client, 0x23);
+		v4l_dbg(2, msp_debug, client, "nicam sync=%d, mode=%d\n",
+			val & 1, (val & 0x1e) >> 1);
+
+		if (val & 1) {
+			/* nicam synced */
+			switch ((val & 0x1e) >> 1)  {
+			case 0:
+			case 8:
+				rxsubchans = V4L2_TUNER_SUB_STEREO;
+				break;
+			case 1:
+			case 9:
+				rxsubchans = V4L2_TUNER_SUB_MONO;
+				break;
+			case 2:
+			case 10:
+				rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
+				break;
+			default:
+				rxsubchans = V4L2_TUNER_SUB_MONO;
+				break;
+			}
+			newnicam = 1;
+		} else {
+			newnicam = 0;
+			rxsubchans = V4L2_TUNER_SUB_MONO;
+		}
+		break;
+	}
+	if (rxsubchans != state->rxsubchans) {
+		update = 1;
+		v4l_dbg(1, msp_debug, client,
+			"watch: rxsubchans %02x => %02x\n",
+			state->rxsubchans, rxsubchans);
+		state->rxsubchans = rxsubchans;
+	}
+	if (newnicam != state->nicam_on) {
+		update = 1;
+		v4l_dbg(1, msp_debug, client, "watch: nicam %d => %d\n",
+			state->nicam_on, newnicam);
+		state->nicam_on = newnicam;
+	}
+	return update;
+}
+
+/*
+ * A kernel thread for msp3400 control -- we don't want to block the
+ * in the ioctl while doing the sound carrier & stereo detect
+ */
+/* stereo/multilang monitoring */
+static void watch_stereo(struct i2c_client *client)
+{
+	struct msp_state *state = to_state(i2c_get_clientdata(client));
+
+	if (msp_detect_stereo(client))
+		msp_set_audmode(client);
+
+	if (msp_once)
+		state->watch_stereo = 0;
+}
+
+int msp3400c_thread(void *data)
+{
+	struct i2c_client *client = data;
+	struct msp_state *state = to_state(i2c_get_clientdata(client));
+	struct msp3400c_carrier_detect *cd;
+	int count, max1, max2, val1, val2, val, i;
+
+	v4l_dbg(1, msp_debug, client, "msp3400 daemon started\n");
+	state->detected_std = V4L2_STD_ALL;
+	set_freezable();
+	for (;;) {
+		v4l_dbg(2, msp_debug, client, "msp3400 thread: sleep\n");
+		msp_sleep(state, -1);
+		v4l_dbg(2, msp_debug, client, "msp3400 thread: wakeup\n");
+
+restart:
+		v4l_dbg(2, msp_debug, client, "thread: restart scan\n");
+		state->restart = 0;
+		if (kthread_should_stop())
+			break;
+
+		if (state->radio || MSP_MODE_EXTERN == state->mode) {
+			/* no carrier scan, just unmute */
+			v4l_dbg(1, msp_debug, client,
+				"thread: no carrier scan\n");
+			state->scan_in_progress = 0;
+			msp_update_volume(state);
+			continue;
+		}
+
+		/* mute audio */
+		state->scan_in_progress = 1;
+		msp_update_volume(state);
+
+		msp3400c_set_mode(client, MSP_MODE_AM_DETECT);
+		val1 = val2 = 0;
+		max1 = max2 = -1;
+		state->watch_stereo = 0;
+		state->nicam_on = 0;
+
+		/* wait for tuner to settle down after a channel change */
+		if (msp_sleep(state, 200))
+			goto restart;
+
+		/* carrier detect pass #1 -- main carrier */
+		cd = msp3400c_carrier_detect_main;
+		count = ARRAY_SIZE(msp3400c_carrier_detect_main);
+
+		if (msp_amsound && (state->v4l2_std & V4L2_STD_SECAM)) {
+			/* autodetect doesn't work well with AM ... */
+			max1 = 3;
+			count = 0;
+			v4l_dbg(1, msp_debug, client, "AM sound override\n");
+		}
+
+		for (i = 0; i < count; i++) {
+			msp3400c_set_carrier(client, cd[i].cdo, cd[i].cdo);
+			if (msp_sleep(state, 100))
+				goto restart;
+			val = msp_read_dsp(client, 0x1b);
+			if (val > 32767)
+				val -= 65536;
+			if (val1 < val)
+				val1 = val, max1 = i;
+			v4l_dbg(1, msp_debug, client,
+				"carrier1 val: %5d / %s\n", val, cd[i].name);
+		}
+
+		/* carrier detect pass #2 -- second (stereo) carrier */
+		switch (max1) {
+		case 1: /* 5.5 */
+			cd = msp3400c_carrier_detect_55;
+			count = ARRAY_SIZE(msp3400c_carrier_detect_55);
+			break;
+		case 3: /* 6.5 */
+			cd = msp3400c_carrier_detect_65;
+			count = ARRAY_SIZE(msp3400c_carrier_detect_65);
+			break;
+		case 0: /* 4.5 */
+		case 2: /* 6.0 */
+		default:
+			cd = NULL;
+			count = 0;
+			break;
+		}
+
+		if (msp_amsound && (state->v4l2_std & V4L2_STD_SECAM)) {
+			/* autodetect doesn't work well with AM ... */
+			cd = NULL;
+			count = 0;
+			max2 = 0;
+		}
+		for (i = 0; i < count; i++) {
+			msp3400c_set_carrier(client, cd[i].cdo, cd[i].cdo);
+			if (msp_sleep(state, 100))
+				goto restart;
+			val = msp_read_dsp(client, 0x1b);
+			if (val > 32767)
+				val -= 65536;
+			if (val2 < val)
+				val2 = val, max2 = i;
+			v4l_dbg(1, msp_debug, client,
+				"carrier2 val: %5d / %s\n", val, cd[i].name);
+		}
+
+		/* program the msp3400 according to the results */
+		state->main = msp3400c_carrier_detect_main[max1].cdo;
+		switch (max1) {
+		case 1: /* 5.5 */
+			state->detected_std = V4L2_STD_BG | V4L2_STD_PAL_H;
+			if (max2 == 0) {
+				/* B/G FM-stereo */
+				state->second = msp3400c_carrier_detect_55[max2].cdo;
+				msp3400c_set_mode(client, MSP_MODE_FM_TERRA);
+				state->watch_stereo = 1;
+			} else if (max2 == 1 && state->has_nicam) {
+				/* B/G NICAM */
+				state->second = msp3400c_carrier_detect_55[max2].cdo;
+				msp3400c_set_mode(client, MSP_MODE_FM_NICAM1);
+				state->nicam_on = 1;
+				state->watch_stereo = 1;
+			} else {
+				goto no_second;
+			}
+			break;
+		case 2: /* 6.0 */
+			/* PAL I NICAM */
+			state->detected_std = V4L2_STD_PAL_I;
+			state->second = MSP_CARRIER(6.552);
+			msp3400c_set_mode(client, MSP_MODE_FM_NICAM2);
+			state->nicam_on = 1;
+			state->watch_stereo = 1;
+			break;
+		case 3: /* 6.5 */
+			if (max2 == 1 || max2 == 2) {
+				/* D/K FM-stereo */
+				state->second = msp3400c_carrier_detect_65[max2].cdo;
+				msp3400c_set_mode(client, MSP_MODE_FM_TERRA);
+				state->watch_stereo = 1;
+				state->detected_std = V4L2_STD_DK;
+			} else if (max2 == 0 && (state->v4l2_std & V4L2_STD_SECAM)) {
+				/* L NICAM or AM-mono */
+				state->second = msp3400c_carrier_detect_65[max2].cdo;
+				msp3400c_set_mode(client, MSP_MODE_AM_NICAM);
+				state->watch_stereo = 1;
+				state->detected_std = V4L2_STD_L;
+			} else if (max2 == 0 && state->has_nicam) {
+				/* D/K NICAM */
+				state->second = msp3400c_carrier_detect_65[max2].cdo;
+				msp3400c_set_mode(client, MSP_MODE_FM_NICAM1);
+				state->nicam_on = 1;
+				state->watch_stereo = 1;
+				state->detected_std = V4L2_STD_DK;
+			} else {
+				goto no_second;
+			}
+			break;
+		case 0: /* 4.5 */
+			state->detected_std = V4L2_STD_MN;
+		default:
+no_second:
+			state->second = msp3400c_carrier_detect_main[max1].cdo;
+			msp3400c_set_mode(client, MSP_MODE_FM_TERRA);
+			break;
+		}
+		msp3400c_set_carrier(client, state->second, state->main);
+
+		/* unmute */
+		state->scan_in_progress = 0;
+		msp3400c_set_audmode(client);
+		msp_update_volume(state);
+
+		if (msp_debug)
+			msp3400c_print_mode(client);
+
+		/* monitor tv audio mode, the first time don't wait
+		   so long to get a quick stereo/bilingual result */
+		count = 3;
+		while (state->watch_stereo) {
+			if (msp_sleep(state, count ? 1000 : 5000))
+				goto restart;
+			if (count)
+				count--;
+			watch_stereo(client);
+		}
+	}
+	v4l_dbg(1, msp_debug, client, "thread: exit\n");
+	return 0;
+}
+
+
+int msp3410d_thread(void *data)
+{
+	struct i2c_client *client = data;
+	struct msp_state *state = to_state(i2c_get_clientdata(client));
+	int val, i, std, count;
+
+	v4l_dbg(1, msp_debug, client, "msp3410 daemon started\n");
+	state->detected_std = V4L2_STD_ALL;
+	set_freezable();
+	for (;;) {
+		v4l_dbg(2, msp_debug, client, "msp3410 thread: sleep\n");
+		msp_sleep(state, -1);
+		v4l_dbg(2, msp_debug, client, "msp3410 thread: wakeup\n");
+
+restart:
+		v4l_dbg(2, msp_debug, client, "thread: restart scan\n");
+		state->restart = 0;
+		if (kthread_should_stop())
+			break;
+
+		if (state->mode == MSP_MODE_EXTERN) {
+			/* no carrier scan needed, just unmute */
+			v4l_dbg(1, msp_debug, client,
+				"thread: no carrier scan\n");
+			state->scan_in_progress = 0;
+			msp_update_volume(state);
+			continue;
+		}
+
+		/* mute audio */
+		state->scan_in_progress = 1;
+		msp_update_volume(state);
+
+		/* start autodetect. Note: autodetect is not supported for
+		   NTSC-M and radio, hence we force the standard in those
+		   cases. */
+		if (state->radio)
+			std = 0x40;
+		else
+			std = (state->v4l2_std & V4L2_STD_NTSC) ? 0x20 : 1;
+		state->watch_stereo = 0;
+		state->nicam_on = 0;
+
+		/* wait for tuner to settle down after a channel change */
+		if (msp_sleep(state, 200))
+			goto restart;
+
+		if (msp_debug)
+			v4l_dbg(2, msp_debug, client,
+				"setting standard: %s (0x%04x)\n",
+				msp_standard_std_name(std), std);
+
+		if (std != 1) {
+			/* programmed some specific mode */
+			val = std;
+		} else {
+			/* triggered autodetect */
+			msp_write_dem(client, 0x20, std);
+			for (;;) {
+				if (msp_sleep(state, 100))
+					goto restart;
+
+				/* check results */
+				val = msp_read_dem(client, 0x7e);
+				if (val < 0x07ff)
+					break;
+				v4l_dbg(2, msp_debug, client,
+					"detection still in progress\n");
+			}
+		}
+		for (i = 0; msp_stdlist[i].name != NULL; i++)
+			if (msp_stdlist[i].retval == val)
+				break;
+		v4l_dbg(1, msp_debug, client, "current standard: %s (0x%04x)\n",
+			msp_standard_std_name(val), val);
+		state->main   = msp_stdlist[i].main;
+		state->second = msp_stdlist[i].second;
+		state->std = val;
+		state->rxsubchans = V4L2_TUNER_SUB_MONO;
+
+		if (msp_amsound && !state->radio &&
+		    (state->v4l2_std & V4L2_STD_SECAM) && (val != 0x0009)) {
+			/* autodetection has failed, let backup */
+			v4l_dbg(1, msp_debug, client, "autodetection failed,"
+				" switching to backup standard: %s (0x%04x)\n",
+				msp_stdlist[8].name ?
+					msp_stdlist[8].name : "unknown", val);
+			state->std = val = 0x0009;
+			msp_write_dem(client, 0x20, val);
+		} else {
+			state->detected_std = msp_standard_std(state->std);
+		}
+
+		/* set stereo */
+		switch (val) {
+		case 0x0008: /* B/G NICAM */
+		case 0x000a: /* I NICAM */
+		case 0x000b: /* D/K NICAM */
+			if (val == 0x000a)
+				state->mode = MSP_MODE_FM_NICAM2;
+			else
+				state->mode = MSP_MODE_FM_NICAM1;
+			/* just turn on stereo */
+			state->nicam_on = 1;
+			state->watch_stereo = 1;
+			break;
+		case 0x0009:
+			state->mode = MSP_MODE_AM_NICAM;
+			state->nicam_on = 1;
+			state->watch_stereo = 1;
+			break;
+		case 0x0020: /* BTSC */
+			/* The pre-'G' models only have BTSC-mono */
+			state->mode = MSP_MODE_BTSC;
+			break;
+		case 0x0040: /* FM radio */
+			state->mode = MSP_MODE_FM_RADIO;
+			state->rxsubchans = V4L2_TUNER_SUB_STEREO;
+			/* not needed in theory if we have radio, but
+			   short programming enables carrier mute */
+			msp3400c_set_mode(client, MSP_MODE_FM_RADIO);
+			msp3400c_set_carrier(client, MSP_CARRIER(10.7),
+					    MSP_CARRIER(10.7));
+			break;
+		case 0x0002:
+		case 0x0003:
+		case 0x0004:
+		case 0x0005:
+			state->mode = MSP_MODE_FM_TERRA;
+			state->watch_stereo = 1;
+			break;
+		}
+
+		/* set various prescales */
+		msp_write_dsp(client, 0x0d, 0x1900); /* scart */
+		msp_write_dsp(client, 0x0e, 0x3000); /* FM */
+		if (state->has_nicam)
+			msp_write_dsp(client, 0x10, 0x5a00); /* nicam */
+
+		if (state->has_i2s_conf)
+			msp_write_dem(client, 0x40, state->i2s_mode);
+
+		/* unmute */
+		msp3400c_set_audmode(client);
+		state->scan_in_progress = 0;
+		msp_update_volume(state);
+
+		/* monitor tv audio mode, the first time don't wait
+		   so long to get a quick stereo/bilingual result */
+		count = 3;
+		while (state->watch_stereo) {
+			if (msp_sleep(state, count ? 1000 : 5000))
+				goto restart;
+			if (count)
+				count--;
+			watch_stereo(client);
+		}
+	}
+	v4l_dbg(1, msp_debug, client, "thread: exit\n");
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+/* msp34xxG + (autoselect no-thread)
+ * this one uses both automatic standard detection and automatic sound
+ * select which are available in the newer G versions
+ * struct msp: only norm, acb and source are really used in this mode
+ */
+
+static int msp34xxg_modus(struct i2c_client *client)
+{
+	struct msp_state *state = to_state(i2c_get_clientdata(client));
+
+	if (state->radio) {
+		v4l_dbg(1, msp_debug, client, "selected radio modus\n");
+		return 0x0001;
+	}
+	if (state->v4l2_std == V4L2_STD_NTSC_M_JP) {
+		v4l_dbg(1, msp_debug, client, "selected M (EIA-J) modus\n");
+		return 0x4001;
+	}
+	if (state->v4l2_std == V4L2_STD_NTSC_M_KR) {
+		v4l_dbg(1, msp_debug, client, "selected M (A2) modus\n");
+		return 0x0001;
+	}
+	if (state->v4l2_std == V4L2_STD_SECAM_L) {
+		v4l_dbg(1, msp_debug, client, "selected SECAM-L modus\n");
+		return 0x6001;
+	}
+	if (state->v4l2_std & V4L2_STD_MN) {
+		v4l_dbg(1, msp_debug, client, "selected M (BTSC) modus\n");
+		return 0x2001;
+	}
+	return 0x7001;
+}
+
+static void msp34xxg_set_source(struct i2c_client *client, u16 reg, int in)
+ {
+	struct msp_state *state = to_state(i2c_get_clientdata(client));
+	int source, matrix;
+
+	switch (state->audmode) {
+	case V4L2_TUNER_MODE_MONO:
+		source = 0; /* mono only */
+		matrix = 0x30;
+		break;
+	case V4L2_TUNER_MODE_LANG2:
+		source = 4; /* stereo or B */
+		matrix = 0x10;
+		break;
+	case V4L2_TUNER_MODE_LANG1_LANG2:
+		source = 1; /* stereo or A|B */
+		matrix = 0x20;
+		break;
+	case V4L2_TUNER_MODE_LANG1:
+		source = 3; /* stereo or A */
+		matrix = 0x00;
+		break;
+	case V4L2_TUNER_MODE_STEREO:
+	default:
+		source = 3; /* stereo or A */
+		matrix = 0x20;
+		break;
+	}
+
+	if (in == MSP_DSP_IN_TUNER)
+		source = (source << 8) | 0x20;
+	/* the msp34x2g puts the MAIN_AVC, MAIN and AUX sources in 12, 13, 14
+	   instead of 11, 12, 13. So we add one for that msp version. */
+	else if (in >= MSP_DSP_IN_MAIN_AVC && state->has_dolby_pro_logic)
+		source = ((in + 1) << 8) | matrix;
+	else
+		source = (in << 8) | matrix;
+
+	v4l_dbg(1, msp_debug, client,
+		"set source to %d (0x%x) for output %02x\n", in, source, reg);
+	msp_write_dsp(client, reg, source);
+}
+
+static void msp34xxg_set_sources(struct i2c_client *client)
+{
+	struct msp_state *state = to_state(i2c_get_clientdata(client));
+	u32 in = state->route_in;
+
+	msp34xxg_set_source(client, 0x0008, (in >> 4) & 0xf);
+	/* quasi-peak detector is set to same input as the loudspeaker (MAIN) */
+	msp34xxg_set_source(client, 0x000c, (in >> 4) & 0xf);
+	msp34xxg_set_source(client, 0x0009, (in >> 8) & 0xf);
+	msp34xxg_set_source(client, 0x000a, (in >> 12) & 0xf);
+	if (state->has_scart2_out)
+		msp34xxg_set_source(client, 0x0041, (in >> 16) & 0xf);
+	msp34xxg_set_source(client, 0x000b, (in >> 20) & 0xf);
+}
+
+/* (re-)initialize the msp34xxg */
+static void msp34xxg_reset(struct i2c_client *client)
+{
+	struct msp_state *state = to_state(i2c_get_clientdata(client));
+	int tuner = (state->route_in >> 3) & 1;
+	int modus;
+
+	/* initialize std to 1 (autodetect) to signal that no standard is
+	   selected yet. */
+	state->std = 1;
+
+	msp_reset(client);
+
+	if (state->has_i2s_conf)
+		msp_write_dem(client, 0x40, state->i2s_mode);
+
+	/* step-by-step initialisation, as described in the manual */
+	modus = msp34xxg_modus(client);
+	modus |= tuner ? 0x100 : 0;
+	msp_write_dem(client, 0x30, modus);
+
+	/* write the dsps that may have an influence on
+	   standard/audio autodetection right now */
+	msp34xxg_set_sources(client);
+
+	msp_write_dsp(client, 0x0d, 0x1900); /* scart */
+	msp_write_dsp(client, 0x0e, 0x3000); /* FM */
+	if (state->has_nicam)
+		msp_write_dsp(client, 0x10, 0x5a00); /* nicam */
+
+	/* set identification threshold. Personally, I
+	 * I set it to a higher value than the default
+	 * of 0x190 to ignore noisy stereo signals.
+	 * this needs tuning. (recommended range 0x00a0-0x03c0)
+	 * 0x7f0 = forced mono mode
+	 *
+	 * a2 threshold for stereo/bilingual.
+	 * Note: this register is part of the Manual/Compatibility mode.
+	 * It is supported by all 'G'-family chips.
+	 */
+	msp_write_dem(client, 0x22, msp_stereo_thresh);
+}
+
+int msp34xxg_thread(void *data)
+{
+	struct i2c_client *client = data;
+	struct msp_state *state = to_state(i2c_get_clientdata(client));
+	int val, i;
+
+	v4l_dbg(1, msp_debug, client, "msp34xxg daemon started\n");
+	state->detected_std = V4L2_STD_ALL;
+	set_freezable();
+	for (;;) {
+		v4l_dbg(2, msp_debug, client, "msp34xxg thread: sleep\n");
+		msp_sleep(state, -1);
+		v4l_dbg(2, msp_debug, client, "msp34xxg thread: wakeup\n");
+
+restart:
+		v4l_dbg(1, msp_debug, client, "thread: restart scan\n");
+		state->restart = 0;
+		if (kthread_should_stop())
+			break;
+
+		if (state->mode == MSP_MODE_EXTERN) {
+			/* no carrier scan needed, just unmute */
+			v4l_dbg(1, msp_debug, client,
+				"thread: no carrier scan\n");
+			state->scan_in_progress = 0;
+			msp_update_volume(state);
+			continue;
+		}
+
+		/* setup the chip*/
+		msp34xxg_reset(client);
+		state->std = state->radio ? 0x40 :
+			(state->force_btsc && msp_standard == 1) ? 32 : msp_standard;
+		msp_write_dem(client, 0x20, state->std);
+		/* start autodetect */
+		if (state->std != 1)
+			goto unmute;
+
+		/* watch autodetect */
+		v4l_dbg(1, msp_debug, client,
+			"started autodetect, waiting for result\n");
+		for (i = 0; i < 10; i++) {
+			if (msp_sleep(state, 100))
+				goto restart;
+
+			/* check results */
+			val = msp_read_dem(client, 0x7e);
+			if (val < 0x07ff) {
+				state->std = val;
+				break;
+			}
+			v4l_dbg(2, msp_debug, client,
+				"detection still in progress\n");
+		}
+		if (state->std == 1) {
+			v4l_dbg(1, msp_debug, client,
+				"detection still in progress after 10 tries. giving up.\n");
+			continue;
+		}
+
+unmute:
+		v4l_dbg(1, msp_debug, client,
+			"detected standard: %s (0x%04x)\n",
+			msp_standard_std_name(state->std), state->std);
+		state->detected_std = msp_standard_std(state->std);
+
+		if (state->std == 9) {
+			/* AM NICAM mode */
+			msp_write_dsp(client, 0x0e, 0x7c00);
+		}
+
+		/* unmute: dispatch sound to scart output, set scart volume */
+		msp_update_volume(state);
+
+		/* restore ACB */
+		if (msp_write_dsp(client, 0x13, state->acb))
+			return -1;
+
+		/* the periodic stereo/SAP check is only relevant for
+		   the 0x20 standard (BTSC) */
+		if (state->std != 0x20)
+			continue;
+
+		state->watch_stereo = 1;
+
+		/* monitor tv audio mode, the first time don't wait
+		   in order to get a quick stereo/SAP update */
+		watch_stereo(client);
+		while (state->watch_stereo) {
+			watch_stereo(client);
+			if (msp_sleep(state, 5000))
+				goto restart;
+		}
+	}
+	v4l_dbg(1, msp_debug, client, "thread: exit\n");
+	return 0;
+}
+
+static int msp34xxg_detect_stereo(struct i2c_client *client)
+{
+	struct msp_state *state = to_state(i2c_get_clientdata(client));
+	int status = msp_read_dem(client, 0x0200);
+	int is_bilingual = status & 0x100;
+	int is_stereo = status & 0x40;
+	int oldrx = state->rxsubchans;
+
+	if (state->mode == MSP_MODE_EXTERN)
+		return 0;
+
+	state->rxsubchans = 0;
+	if (is_stereo)
+		state->rxsubchans = V4L2_TUNER_SUB_STEREO;
+	else
+		state->rxsubchans = V4L2_TUNER_SUB_MONO;
+	if (is_bilingual) {
+		if (state->std == 0x20)
+			state->rxsubchans |= V4L2_TUNER_SUB_SAP;
+		else
+			state->rxsubchans =
+				V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
+	}
+	v4l_dbg(1, msp_debug, client,
+		"status=0x%x, stereo=%d, bilingual=%d -> rxsubchans=%d\n",
+		status, is_stereo, is_bilingual, state->rxsubchans);
+	return (oldrx != state->rxsubchans);
+}
+
+static void msp34xxg_set_audmode(struct i2c_client *client)
+{
+	struct msp_state *state = to_state(i2c_get_clientdata(client));
+
+	if (state->std == 0x20) {
+	       if ((state->rxsubchans & V4L2_TUNER_SUB_SAP) &&
+		   (state->audmode == V4L2_TUNER_MODE_LANG1_LANG2 ||
+		    state->audmode == V4L2_TUNER_MODE_LANG2)) {
+			msp_write_dem(client, 0x20, 0x21);
+	       } else {
+			msp_write_dem(client, 0x20, 0x20);
+	       }
+	}
+
+	msp34xxg_set_sources(client);
+}
+
+void msp_set_audmode(struct i2c_client *client)
+{
+	struct msp_state *state = to_state(i2c_get_clientdata(client));
+
+	switch (state->opmode) {
+	case OPMODE_MANUAL:
+	case OPMODE_AUTODETECT:
+		msp3400c_set_audmode(client);
+		break;
+	case OPMODE_AUTOSELECT:
+		msp34xxg_set_audmode(client);
+		break;
+	}
+}
+
+int msp_detect_stereo(struct i2c_client *client)
+{
+	struct msp_state *state  = to_state(i2c_get_clientdata(client));
+
+	switch (state->opmode) {
+	case OPMODE_MANUAL:
+	case OPMODE_AUTODETECT:
+		return msp3400c_detect_stereo(client);
+	case OPMODE_AUTOSELECT:
+		return msp34xxg_detect_stereo(client);
+	}
+	return 0;
+}
+
diff --git a/drivers/media/i2c/mt9m032.c b/drivers/media/i2c/mt9m032.c
new file mode 100644
index 0000000..f80c1d7e
--- /dev/null
+++ b/drivers/media/i2c/mt9m032.c
@@ -0,0 +1,878 @@
+/*
+ * Driver for MT9M032 CMOS Image Sensor from Micron
+ *
+ * Copyright (C) 2010-2011 Lund Engineering
+ * Contact: Gil Lund <gwlund@lundeng.com>
+ * Author: Martin Hostettler <martin@neutronstar.dyndns.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.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/math64.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/v4l2-mediabus.h>
+
+#include <media/media-entity.h>
+#include <media/mt9m032.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+
+#include "aptina-pll.h"
+
+/*
+ * width and height include active boundary and black parts
+ *
+ * column    0-  15 active boundary
+ * column   16-1455 image
+ * column 1456-1471 active boundary
+ * column 1472-1599 black
+ *
+ * row       0-  51 black
+ * row      53-  59 active boundary
+ * row      60-1139 image
+ * row    1140-1147 active boundary
+ * row    1148-1151 black
+ */
+
+#define MT9M032_PIXEL_ARRAY_WIDTH			1600
+#define MT9M032_PIXEL_ARRAY_HEIGHT			1152
+
+#define MT9M032_CHIP_VERSION				0x00
+#define		MT9M032_CHIP_VERSION_VALUE		0x1402
+#define MT9M032_ROW_START				0x01
+#define		MT9M032_ROW_START_MIN			0
+#define		MT9M032_ROW_START_MAX			1152
+#define		MT9M032_ROW_START_DEF			60
+#define MT9M032_COLUMN_START				0x02
+#define		MT9M032_COLUMN_START_MIN		0
+#define		MT9M032_COLUMN_START_MAX		1600
+#define		MT9M032_COLUMN_START_DEF		16
+#define MT9M032_ROW_SIZE				0x03
+#define		MT9M032_ROW_SIZE_MIN			32
+#define		MT9M032_ROW_SIZE_MAX			1152
+#define		MT9M032_ROW_SIZE_DEF			1080
+#define MT9M032_COLUMN_SIZE				0x04
+#define		MT9M032_COLUMN_SIZE_MIN			32
+#define		MT9M032_COLUMN_SIZE_MAX			1600
+#define		MT9M032_COLUMN_SIZE_DEF			1440
+#define MT9M032_HBLANK					0x05
+#define MT9M032_VBLANK					0x06
+#define		MT9M032_VBLANK_MAX			0x7ff
+#define MT9M032_SHUTTER_WIDTH_HIGH			0x08
+#define MT9M032_SHUTTER_WIDTH_LOW			0x09
+#define		MT9M032_SHUTTER_WIDTH_MIN		1
+#define		MT9M032_SHUTTER_WIDTH_MAX		1048575
+#define		MT9M032_SHUTTER_WIDTH_DEF		1943
+#define MT9M032_PIX_CLK_CTRL				0x0a
+#define		MT9M032_PIX_CLK_CTRL_INV_PIXCLK		0x8000
+#define MT9M032_RESTART					0x0b
+#define MT9M032_RESET					0x0d
+#define MT9M032_PLL_CONFIG1				0x11
+#define		MT9M032_PLL_CONFIG1_OUTDIV_MASK		0x3f
+#define		MT9M032_PLL_CONFIG1_MUL_SHIFT		8
+#define MT9M032_READ_MODE1				0x1e
+#define MT9M032_READ_MODE2				0x20
+#define		MT9M032_READ_MODE2_VFLIP_SHIFT		15
+#define		MT9M032_READ_MODE2_HFLIP_SHIFT		14
+#define		MT9M032_READ_MODE2_ROW_BLC		0x40
+#define MT9M032_GAIN_GREEN1				0x2b
+#define MT9M032_GAIN_BLUE				0x2c
+#define MT9M032_GAIN_RED				0x2d
+#define MT9M032_GAIN_GREEN2				0x2e
+
+/* write only */
+#define MT9M032_GAIN_ALL				0x35
+#define		MT9M032_GAIN_DIGITAL_MASK		0x7f
+#define		MT9M032_GAIN_DIGITAL_SHIFT		8
+#define		MT9M032_GAIN_AMUL_SHIFT			6
+#define		MT9M032_GAIN_ANALOG_MASK		0x3f
+#define MT9M032_FORMATTER1				0x9e
+#define MT9M032_FORMATTER2				0x9f
+#define		MT9M032_FORMATTER2_DOUT_EN		0x1000
+#define		MT9M032_FORMATTER2_PIXCLK_EN		0x2000
+
+/*
+ * The available MT9M032 datasheet is missing documentation for register 0x10
+ * MT9P031 seems to be close enough, so use constants from that datasheet for
+ * now.
+ * But keep the name MT9P031 to remind us, that this isn't really confirmed
+ * for this sensor.
+ */
+#define MT9P031_PLL_CONTROL				0x10
+#define		MT9P031_PLL_CONTROL_PWROFF		0x0050
+#define		MT9P031_PLL_CONTROL_PWRON		0x0051
+#define		MT9P031_PLL_CONTROL_USEPLL		0x0052
+#define MT9P031_PLL_CONFIG2				0x11
+#define		MT9P031_PLL_CONFIG2_P1_DIV_MASK		0x1f
+
+struct mt9m032 {
+	struct v4l2_subdev subdev;
+	struct media_pad pad;
+	struct mt9m032_platform_data *pdata;
+
+	unsigned int pix_clock;
+
+	struct v4l2_ctrl_handler ctrls;
+	struct {
+		struct v4l2_ctrl *hflip;
+		struct v4l2_ctrl *vflip;
+	};
+
+	struct mutex lock; /* Protects streaming, format, interval and crop */
+
+	bool streaming;
+
+	struct v4l2_mbus_framefmt format;
+	struct v4l2_rect crop;
+	struct v4l2_fract frame_interval;
+};
+
+#define to_mt9m032(sd)	container_of(sd, struct mt9m032, subdev)
+#define to_dev(sensor) \
+	(&((struct i2c_client *)v4l2_get_subdevdata(&(sensor)->subdev))->dev)
+
+static int mt9m032_read(struct i2c_client *client, u8 reg)
+{
+	return i2c_smbus_read_word_swapped(client, reg);
+}
+
+static int mt9m032_write(struct i2c_client *client, u8 reg, const u16 data)
+{
+	return i2c_smbus_write_word_swapped(client, reg, data);
+}
+
+static u32 mt9m032_row_time(struct mt9m032 *sensor, unsigned int width)
+{
+	unsigned int effective_width;
+	u32 ns;
+
+	effective_width = width + 716; /* empirical value */
+	ns = div_u64(1000000000ULL * effective_width, sensor->pix_clock);
+	dev_dbg(to_dev(sensor),	"MT9M032 line time: %u ns\n", ns);
+	return ns;
+}
+
+static int mt9m032_update_timing(struct mt9m032 *sensor,
+				 struct v4l2_fract *interval)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev);
+	struct v4l2_rect *crop = &sensor->crop;
+	unsigned int min_vblank;
+	unsigned int vblank;
+	u32 row_time;
+
+	if (!interval)
+		interval = &sensor->frame_interval;
+
+	row_time = mt9m032_row_time(sensor, crop->width);
+
+	vblank = div_u64(1000000000ULL * interval->numerator,
+			 (u64)row_time * interval->denominator)
+	       - crop->height;
+
+	if (vblank > MT9M032_VBLANK_MAX) {
+		/* hardware limits to 11 bit values */
+		interval->denominator = 1000;
+		interval->numerator =
+			div_u64((crop->height + MT9M032_VBLANK_MAX) *
+				(u64)row_time * interval->denominator,
+				1000000000ULL);
+		vblank = div_u64(1000000000ULL * interval->numerator,
+				 (u64)row_time * interval->denominator)
+		       - crop->height;
+	}
+	/* enforce minimal 1.6ms blanking time. */
+	min_vblank = 1600000 / row_time;
+	vblank = clamp_t(unsigned int, vblank, min_vblank, MT9M032_VBLANK_MAX);
+
+	return mt9m032_write(client, MT9M032_VBLANK, vblank);
+}
+
+static int mt9m032_update_geom_timing(struct mt9m032 *sensor)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev);
+	int ret;
+
+	ret = mt9m032_write(client, MT9M032_COLUMN_SIZE,
+			    sensor->crop.width - 1);
+	if (!ret)
+		ret = mt9m032_write(client, MT9M032_ROW_SIZE,
+				    sensor->crop.height - 1);
+	if (!ret)
+		ret = mt9m032_write(client, MT9M032_COLUMN_START,
+				    sensor->crop.left);
+	if (!ret)
+		ret = mt9m032_write(client, MT9M032_ROW_START,
+				    sensor->crop.top);
+	if (!ret)
+		ret = mt9m032_update_timing(sensor, NULL);
+	return ret;
+}
+
+static int update_formatter2(struct mt9m032 *sensor, bool streaming)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev);
+	u16 reg_val =   MT9M032_FORMATTER2_DOUT_EN
+		      | 0x0070;  /* parts reserved! */
+				 /* possibly for changing to 14-bit mode */
+
+	if (streaming)
+		reg_val |= MT9M032_FORMATTER2_PIXCLK_EN;   /* pixclock enable */
+
+	return mt9m032_write(client, MT9M032_FORMATTER2, reg_val);
+}
+
+static int mt9m032_setup_pll(struct mt9m032 *sensor)
+{
+	static const struct aptina_pll_limits limits = {
+		.ext_clock_min = 8000000,
+		.ext_clock_max = 16500000,
+		.int_clock_min = 2000000,
+		.int_clock_max = 24000000,
+		.out_clock_min = 322000000,
+		.out_clock_max = 693000000,
+		.pix_clock_max = 99000000,
+		.n_min = 1,
+		.n_max = 64,
+		.m_min = 16,
+		.m_max = 255,
+		.p1_min = 1,
+		.p1_max = 128,
+	};
+
+	struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev);
+	struct mt9m032_platform_data *pdata = sensor->pdata;
+	struct aptina_pll pll;
+	int ret;
+
+	pll.ext_clock = pdata->ext_clock;
+	pll.pix_clock = pdata->pix_clock;
+
+	ret = aptina_pll_calculate(&client->dev, &limits, &pll);
+	if (ret < 0)
+		return ret;
+
+	sensor->pix_clock = pdata->pix_clock;
+
+	ret = mt9m032_write(client, MT9M032_PLL_CONFIG1,
+			    (pll.m << MT9M032_PLL_CONFIG1_MUL_SHIFT)
+			    | (pll.p1 - 1));
+	if (!ret)
+		ret = mt9m032_write(client, MT9P031_PLL_CONFIG2, pll.n - 1);
+	if (!ret)
+		ret = mt9m032_write(client, MT9P031_PLL_CONTROL,
+				    MT9P031_PLL_CONTROL_PWRON |
+				    MT9P031_PLL_CONTROL_USEPLL);
+	if (!ret)		/* more reserved, Continuous, Master Mode */
+		ret = mt9m032_write(client, MT9M032_READ_MODE1, 0x8006);
+	if (!ret)		/* Set 14-bit mode, select 7 divider */
+		ret = mt9m032_write(client, MT9M032_FORMATTER1, 0x111e);
+
+	return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ * Subdev pad operations
+ */
+
+static int mt9m032_enum_mbus_code(struct v4l2_subdev *subdev,
+				  struct v4l2_subdev_fh *fh,
+				  struct v4l2_subdev_mbus_code_enum *code)
+{
+	if (code->index != 0)
+		return -EINVAL;
+
+	code->code = V4L2_MBUS_FMT_Y8_1X8;
+	return 0;
+}
+
+static int mt9m032_enum_frame_size(struct v4l2_subdev *subdev,
+				   struct v4l2_subdev_fh *fh,
+				   struct v4l2_subdev_frame_size_enum *fse)
+{
+	if (fse->index != 0 || fse->code != V4L2_MBUS_FMT_Y8_1X8)
+		return -EINVAL;
+
+	fse->min_width = MT9M032_COLUMN_SIZE_DEF;
+	fse->max_width = MT9M032_COLUMN_SIZE_DEF;
+	fse->min_height = MT9M032_ROW_SIZE_DEF;
+	fse->max_height = MT9M032_ROW_SIZE_DEF;
+
+	return 0;
+}
+
+/**
+ * __mt9m032_get_pad_crop() - get crop rect
+ * @sensor: pointer to the sensor struct
+ * @fh: file handle for getting the try crop rect from
+ * @which: select try or active crop rect
+ *
+ * Returns a pointer the current active or fh relative try crop rect
+ */
+static struct v4l2_rect *
+__mt9m032_get_pad_crop(struct mt9m032 *sensor, struct v4l2_subdev_fh *fh,
+		       enum v4l2_subdev_format_whence which)
+{
+	switch (which) {
+	case V4L2_SUBDEV_FORMAT_TRY:
+		return v4l2_subdev_get_try_crop(fh, 0);
+	case V4L2_SUBDEV_FORMAT_ACTIVE:
+		return &sensor->crop;
+	default:
+		return NULL;
+	}
+}
+
+/**
+ * __mt9m032_get_pad_format() - get format
+ * @sensor: pointer to the sensor struct
+ * @fh: file handle for getting the try format from
+ * @which: select try or active format
+ *
+ * Returns a pointer the current active or fh relative try format
+ */
+static struct v4l2_mbus_framefmt *
+__mt9m032_get_pad_format(struct mt9m032 *sensor, struct v4l2_subdev_fh *fh,
+			 enum v4l2_subdev_format_whence which)
+{
+	switch (which) {
+	case V4L2_SUBDEV_FORMAT_TRY:
+		return v4l2_subdev_get_try_format(fh, 0);
+	case V4L2_SUBDEV_FORMAT_ACTIVE:
+		return &sensor->format;
+	default:
+		return NULL;
+	}
+}
+
+static int mt9m032_get_pad_format(struct v4l2_subdev *subdev,
+				  struct v4l2_subdev_fh *fh,
+				  struct v4l2_subdev_format *fmt)
+{
+	struct mt9m032 *sensor = to_mt9m032(subdev);
+
+	mutex_lock(&sensor->lock);
+	fmt->format = *__mt9m032_get_pad_format(sensor, fh, fmt->which);
+	mutex_unlock(&sensor->lock);
+
+	return 0;
+}
+
+static int mt9m032_set_pad_format(struct v4l2_subdev *subdev,
+				  struct v4l2_subdev_fh *fh,
+				  struct v4l2_subdev_format *fmt)
+{
+	struct mt9m032 *sensor = to_mt9m032(subdev);
+	int ret;
+
+	mutex_lock(&sensor->lock);
+
+	if (sensor->streaming && fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
+		ret = -EBUSY;
+		goto done;
+	}
+
+	/* Scaling is not supported, the format is thus fixed. */
+	fmt->format = *__mt9m032_get_pad_format(sensor, fh, fmt->which);
+	ret = 0;
+
+done:
+	mutex_unlock(&sensor->lock);
+	return ret;
+}
+
+static int mt9m032_get_pad_crop(struct v4l2_subdev *subdev,
+				struct v4l2_subdev_fh *fh,
+				struct v4l2_subdev_crop *crop)
+{
+	struct mt9m032 *sensor = to_mt9m032(subdev);
+
+	mutex_lock(&sensor->lock);
+	crop->rect = *__mt9m032_get_pad_crop(sensor, fh, crop->which);
+	mutex_unlock(&sensor->lock);
+
+	return 0;
+}
+
+static int mt9m032_set_pad_crop(struct v4l2_subdev *subdev,
+				struct v4l2_subdev_fh *fh,
+				struct v4l2_subdev_crop *crop)
+{
+	struct mt9m032 *sensor = to_mt9m032(subdev);
+	struct v4l2_mbus_framefmt *format;
+	struct v4l2_rect *__crop;
+	struct v4l2_rect rect;
+	int ret = 0;
+
+	mutex_lock(&sensor->lock);
+
+	if (sensor->streaming && crop->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
+		ret = -EBUSY;
+		goto done;
+	}
+
+	/* Clamp the crop rectangle boundaries and align them to a multiple of 2
+	 * pixels to ensure a GRBG Bayer pattern.
+	 */
+	rect.left = clamp(ALIGN(crop->rect.left, 2), MT9M032_COLUMN_START_MIN,
+			  MT9M032_COLUMN_START_MAX);
+	rect.top = clamp(ALIGN(crop->rect.top, 2), MT9M032_ROW_START_MIN,
+			 MT9M032_ROW_START_MAX);
+	rect.width = clamp(ALIGN(crop->rect.width, 2), MT9M032_COLUMN_SIZE_MIN,
+			   MT9M032_COLUMN_SIZE_MAX);
+	rect.height = clamp(ALIGN(crop->rect.height, 2), MT9M032_ROW_SIZE_MIN,
+			    MT9M032_ROW_SIZE_MAX);
+
+	rect.width = min(rect.width, MT9M032_PIXEL_ARRAY_WIDTH - rect.left);
+	rect.height = min(rect.height, MT9M032_PIXEL_ARRAY_HEIGHT - rect.top);
+
+	__crop = __mt9m032_get_pad_crop(sensor, fh, crop->which);
+
+	if (rect.width != __crop->width || rect.height != __crop->height) {
+		/* Reset the output image size if the crop rectangle size has
+		 * been modified.
+		 */
+		format = __mt9m032_get_pad_format(sensor, fh, crop->which);
+		format->width = rect.width;
+		format->height = rect.height;
+	}
+
+	*__crop = rect;
+	crop->rect = rect;
+
+	if (crop->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+		ret = mt9m032_update_geom_timing(sensor);
+
+done:
+	mutex_unlock(&sensor->lock);
+	return ret;
+}
+
+static int mt9m032_get_frame_interval(struct v4l2_subdev *subdev,
+				      struct v4l2_subdev_frame_interval *fi)
+{
+	struct mt9m032 *sensor = to_mt9m032(subdev);
+
+	mutex_lock(&sensor->lock);
+	memset(fi, 0, sizeof(*fi));
+	fi->interval = sensor->frame_interval;
+	mutex_unlock(&sensor->lock);
+
+	return 0;
+}
+
+static int mt9m032_set_frame_interval(struct v4l2_subdev *subdev,
+				      struct v4l2_subdev_frame_interval *fi)
+{
+	struct mt9m032 *sensor = to_mt9m032(subdev);
+	int ret;
+
+	mutex_lock(&sensor->lock);
+
+	if (sensor->streaming) {
+		ret = -EBUSY;
+		goto done;
+	}
+
+	/* Avoid divisions by 0. */
+	if (fi->interval.denominator == 0)
+		fi->interval.denominator = 1;
+
+	ret = mt9m032_update_timing(sensor, &fi->interval);
+	if (!ret)
+		sensor->frame_interval = fi->interval;
+
+done:
+	mutex_unlock(&sensor->lock);
+	return ret;
+}
+
+static int mt9m032_s_stream(struct v4l2_subdev *subdev, int streaming)
+{
+	struct mt9m032 *sensor = to_mt9m032(subdev);
+	int ret;
+
+	mutex_lock(&sensor->lock);
+	ret = update_formatter2(sensor, streaming);
+	if (!ret)
+		sensor->streaming = streaming;
+	mutex_unlock(&sensor->lock);
+
+	return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 subdev core operations
+ */
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int mt9m032_g_register(struct v4l2_subdev *sd,
+			      struct v4l2_dbg_register *reg)
+{
+	struct mt9m032 *sensor = to_mt9m032(sd);
+	struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev);
+	int val;
+
+	if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
+		return -EINVAL;
+	if (reg->match.addr != client->addr)
+		return -ENODEV;
+
+	val = mt9m032_read(client, reg->reg);
+	if (val < 0)
+		return -EIO;
+
+	reg->size = 2;
+	reg->val = val;
+
+	return 0;
+}
+
+static int mt9m032_s_register(struct v4l2_subdev *sd,
+			      struct v4l2_dbg_register *reg)
+{
+	struct mt9m032 *sensor = to_mt9m032(sd);
+	struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev);
+
+	if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
+		return -EINVAL;
+
+	if (reg->match.addr != client->addr)
+		return -ENODEV;
+
+	return mt9m032_write(client, reg->reg, reg->val);
+}
+#endif
+
+/* -----------------------------------------------------------------------------
+ * V4L2 subdev control operations
+ */
+
+static int update_read_mode2(struct mt9m032 *sensor, bool vflip, bool hflip)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev);
+	int reg_val = (vflip << MT9M032_READ_MODE2_VFLIP_SHIFT)
+		    | (hflip << MT9M032_READ_MODE2_HFLIP_SHIFT)
+		    | MT9M032_READ_MODE2_ROW_BLC
+		    | 0x0007;
+
+	return mt9m032_write(client, MT9M032_READ_MODE2, reg_val);
+}
+
+static int mt9m032_set_gain(struct mt9m032 *sensor, s32 val)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev);
+	int digital_gain_val;	/* in 1/8th (0..127) */
+	int analog_mul;		/* 0 or 1 */
+	int analog_gain_val;	/* in 1/16th. (0..63) */
+	u16 reg_val;
+
+	digital_gain_val = 51; /* from setup example */
+
+	if (val < 63) {
+		analog_mul = 0;
+		analog_gain_val = val;
+	} else {
+		analog_mul = 1;
+		analog_gain_val = val / 2;
+	}
+
+	/* a_gain = (1 + analog_mul) + (analog_gain_val + 1) / 16 */
+	/* overall_gain = a_gain * (1 + digital_gain_val / 8) */
+
+	reg_val = ((digital_gain_val & MT9M032_GAIN_DIGITAL_MASK)
+		   << MT9M032_GAIN_DIGITAL_SHIFT)
+		| ((analog_mul & 1) << MT9M032_GAIN_AMUL_SHIFT)
+		| (analog_gain_val & MT9M032_GAIN_ANALOG_MASK);
+
+	return mt9m032_write(client, MT9M032_GAIN_ALL, reg_val);
+}
+
+static int mt9m032_try_ctrl(struct v4l2_ctrl *ctrl)
+{
+	if (ctrl->id == V4L2_CID_GAIN && ctrl->val >= 63) {
+		/* round because of multiplier used for values >= 63 */
+		ctrl->val &= ~1;
+	}
+
+	return 0;
+}
+
+static int mt9m032_set_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct mt9m032 *sensor =
+		container_of(ctrl->handler, struct mt9m032, ctrls);
+	struct i2c_client *client = v4l2_get_subdevdata(&sensor->subdev);
+	int ret;
+
+	switch (ctrl->id) {
+	case V4L2_CID_GAIN:
+		return mt9m032_set_gain(sensor, ctrl->val);
+
+	case V4L2_CID_HFLIP:
+	/* case V4L2_CID_VFLIP: -- In the same cluster */
+		return update_read_mode2(sensor, sensor->vflip->val,
+					 sensor->hflip->val);
+
+	case V4L2_CID_EXPOSURE:
+		ret = mt9m032_write(client, MT9M032_SHUTTER_WIDTH_HIGH,
+				    (ctrl->val >> 16) & 0xffff);
+		if (ret < 0)
+			return ret;
+
+		return mt9m032_write(client, MT9M032_SHUTTER_WIDTH_LOW,
+				     ctrl->val & 0xffff);
+	}
+
+	return 0;
+}
+
+static struct v4l2_ctrl_ops mt9m032_ctrl_ops = {
+	.s_ctrl = mt9m032_set_ctrl,
+	.try_ctrl = mt9m032_try_ctrl,
+};
+
+/* -------------------------------------------------------------------------- */
+
+static const struct v4l2_subdev_core_ops mt9m032_core_ops = {
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.g_register = mt9m032_g_register,
+	.s_register = mt9m032_s_register,
+#endif
+};
+
+static const struct v4l2_subdev_video_ops mt9m032_video_ops = {
+	.s_stream = mt9m032_s_stream,
+	.g_frame_interval = mt9m032_get_frame_interval,
+	.s_frame_interval = mt9m032_set_frame_interval,
+};
+
+static const struct v4l2_subdev_pad_ops mt9m032_pad_ops = {
+	.enum_mbus_code = mt9m032_enum_mbus_code,
+	.enum_frame_size = mt9m032_enum_frame_size,
+	.get_fmt = mt9m032_get_pad_format,
+	.set_fmt = mt9m032_set_pad_format,
+	.set_crop = mt9m032_set_pad_crop,
+	.get_crop = mt9m032_get_pad_crop,
+};
+
+static const struct v4l2_subdev_ops mt9m032_ops = {
+	.core = &mt9m032_core_ops,
+	.video = &mt9m032_video_ops,
+	.pad = &mt9m032_pad_ops,
+};
+
+/* -----------------------------------------------------------------------------
+ * Driver initialization and probing
+ */
+
+static int mt9m032_probe(struct i2c_client *client,
+			 const struct i2c_device_id *devid)
+{
+	struct mt9m032_platform_data *pdata = client->dev.platform_data;
+	struct i2c_adapter *adapter = client->adapter;
+	struct mt9m032 *sensor;
+	int chip_version;
+	int ret;
+
+	if (pdata == NULL) {
+		dev_err(&client->dev, "No platform data\n");
+		return -EINVAL;
+	}
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) {
+		dev_warn(&client->dev,
+			 "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n");
+		return -EIO;
+	}
+
+	if (!client->dev.platform_data)
+		return -ENODEV;
+
+	sensor = kzalloc(sizeof(*sensor), GFP_KERNEL);
+	if (sensor == NULL)
+		return -ENOMEM;
+
+	mutex_init(&sensor->lock);
+
+	sensor->pdata = pdata;
+
+	v4l2_i2c_subdev_init(&sensor->subdev, client, &mt9m032_ops);
+	sensor->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+	chip_version = mt9m032_read(client, MT9M032_CHIP_VERSION);
+	if (chip_version != MT9M032_CHIP_VERSION_VALUE) {
+		dev_err(&client->dev, "MT9M032 not detected, wrong version "
+			"0x%04x\n", chip_version);
+		ret = -ENODEV;
+		goto error_sensor;
+	}
+
+	dev_info(&client->dev, "MT9M032 detected at address 0x%02x\n",
+		 client->addr);
+
+	sensor->frame_interval.numerator = 1;
+	sensor->frame_interval.denominator = 30;
+
+	sensor->crop.left = MT9M032_COLUMN_START_DEF;
+	sensor->crop.top = MT9M032_ROW_START_DEF;
+	sensor->crop.width = MT9M032_COLUMN_SIZE_DEF;
+	sensor->crop.height = MT9M032_ROW_SIZE_DEF;
+
+	sensor->format.width = sensor->crop.width;
+	sensor->format.height = sensor->crop.height;
+	sensor->format.code = V4L2_MBUS_FMT_Y8_1X8;
+	sensor->format.field = V4L2_FIELD_NONE;
+	sensor->format.colorspace = V4L2_COLORSPACE_SRGB;
+
+	v4l2_ctrl_handler_init(&sensor->ctrls, 5);
+
+	v4l2_ctrl_new_std(&sensor->ctrls, &mt9m032_ctrl_ops,
+			  V4L2_CID_GAIN, 0, 127, 1, 64);
+
+	sensor->hflip = v4l2_ctrl_new_std(&sensor->ctrls,
+					  &mt9m032_ctrl_ops,
+					  V4L2_CID_HFLIP, 0, 1, 1, 0);
+	sensor->vflip = v4l2_ctrl_new_std(&sensor->ctrls,
+					  &mt9m032_ctrl_ops,
+					  V4L2_CID_VFLIP, 0, 1, 1, 0);
+
+	v4l2_ctrl_new_std(&sensor->ctrls, &mt9m032_ctrl_ops,
+			  V4L2_CID_EXPOSURE, MT9M032_SHUTTER_WIDTH_MIN,
+			  MT9M032_SHUTTER_WIDTH_MAX, 1,
+			  MT9M032_SHUTTER_WIDTH_DEF);
+	v4l2_ctrl_new_std(&sensor->ctrls, &mt9m032_ctrl_ops,
+			  V4L2_CID_PIXEL_RATE, pdata->pix_clock,
+			  pdata->pix_clock, 1, pdata->pix_clock);
+
+	if (sensor->ctrls.error) {
+		ret = sensor->ctrls.error;
+		dev_err(&client->dev, "control initialization error %d\n", ret);
+		goto error_ctrl;
+	}
+
+	v4l2_ctrl_cluster(2, &sensor->hflip);
+
+	sensor->subdev.ctrl_handler = &sensor->ctrls;
+	sensor->pad.flags = MEDIA_PAD_FL_SOURCE;
+	ret = media_entity_init(&sensor->subdev.entity, 1, &sensor->pad, 0);
+	if (ret < 0)
+		goto error_ctrl;
+
+	ret = mt9m032_write(client, MT9M032_RESET, 1);	/* reset on */
+	if (ret < 0)
+		goto error_entity;
+	ret = mt9m032_write(client, MT9M032_RESET, 0);	/* reset off */
+	if (ret < 0)
+		goto error_entity;
+
+	ret = mt9m032_setup_pll(sensor);
+	if (ret < 0)
+		goto error_entity;
+	usleep_range(10000, 11000);
+
+	ret = v4l2_ctrl_handler_setup(&sensor->ctrls);
+	if (ret < 0)
+		goto error_entity;
+
+	/* SIZE */
+	ret = mt9m032_update_geom_timing(sensor);
+	if (ret < 0)
+		goto error_entity;
+
+	ret = mt9m032_write(client, 0x41, 0x0000);	/* reserved !!! */
+	if (ret < 0)
+		goto error_entity;
+	ret = mt9m032_write(client, 0x42, 0x0003);	/* reserved !!! */
+	if (ret < 0)
+		goto error_entity;
+	ret = mt9m032_write(client, 0x43, 0x0003);	/* reserved !!! */
+	if (ret < 0)
+		goto error_entity;
+	ret = mt9m032_write(client, 0x7f, 0x0000);	/* reserved !!! */
+	if (ret < 0)
+		goto error_entity;
+	if (sensor->pdata->invert_pixclock) {
+		ret = mt9m032_write(client, MT9M032_PIX_CLK_CTRL,
+				    MT9M032_PIX_CLK_CTRL_INV_PIXCLK);
+		if (ret < 0)
+			goto error_entity;
+	}
+
+	ret = mt9m032_write(client, MT9M032_RESTART, 1); /* Restart on */
+	if (ret < 0)
+		goto error_entity;
+	msleep(100);
+	ret = mt9m032_write(client, MT9M032_RESTART, 0); /* Restart off */
+	if (ret < 0)
+		goto error_entity;
+	msleep(100);
+	ret = update_formatter2(sensor, false);
+	if (ret < 0)
+		goto error_entity;
+
+	return ret;
+
+error_entity:
+	media_entity_cleanup(&sensor->subdev.entity);
+error_ctrl:
+	v4l2_ctrl_handler_free(&sensor->ctrls);
+error_sensor:
+	mutex_destroy(&sensor->lock);
+	kfree(sensor);
+	return ret;
+}
+
+static int mt9m032_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *subdev = i2c_get_clientdata(client);
+	struct mt9m032 *sensor = to_mt9m032(subdev);
+
+	v4l2_device_unregister_subdev(subdev);
+	v4l2_ctrl_handler_free(&sensor->ctrls);
+	media_entity_cleanup(&subdev->entity);
+	mutex_destroy(&sensor->lock);
+	kfree(sensor);
+	return 0;
+}
+
+static const struct i2c_device_id mt9m032_id_table[] = {
+	{ MT9M032_NAME, 0 },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(i2c, mt9m032_id_table);
+
+static struct i2c_driver mt9m032_i2c_driver = {
+	.driver = {
+		.name = MT9M032_NAME,
+	},
+	.probe = mt9m032_probe,
+	.remove = mt9m032_remove,
+	.id_table = mt9m032_id_table,
+};
+
+module_i2c_driver(mt9m032_i2c_driver);
+
+MODULE_AUTHOR("Martin Hostettler <martin@neutronstar.dyndns.org>");
+MODULE_DESCRIPTION("MT9M032 camera sensor driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/i2c/mt9p031.c b/drivers/media/i2c/mt9p031.c
new file mode 100644
index 0000000..2c0f407
--- /dev/null
+++ b/drivers/media/i2c/mt9p031.c
@@ -0,0 +1,1071 @@
+/*
+ * Driver for MT9P031 CMOS Image Sensor from Aptina
+ *
+ * Copyright (C) 2011, Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ * Copyright (C) 2011, Javier Martin <javier.martin@vista-silicon.com>
+ * Copyright (C) 2011, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+ *
+ * Based on the MT9V032 driver and Bastian Hecht's 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/delay.h>
+#include <linux/device.h>
+#include <linux/gpio.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/log2.h>
+#include <linux/pm.h>
+#include <linux/slab.h>
+#include <linux/videodev2.h>
+
+#include <media/mt9p031.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+
+#include "aptina-pll.h"
+
+#define MT9P031_PIXEL_ARRAY_WIDTH			2752
+#define MT9P031_PIXEL_ARRAY_HEIGHT			2004
+
+#define MT9P031_CHIP_VERSION				0x00
+#define		MT9P031_CHIP_VERSION_VALUE		0x1801
+#define MT9P031_ROW_START				0x01
+#define		MT9P031_ROW_START_MIN			0
+#define		MT9P031_ROW_START_MAX			2004
+#define		MT9P031_ROW_START_DEF			54
+#define MT9P031_COLUMN_START				0x02
+#define		MT9P031_COLUMN_START_MIN		0
+#define		MT9P031_COLUMN_START_MAX		2750
+#define		MT9P031_COLUMN_START_DEF		16
+#define MT9P031_WINDOW_HEIGHT				0x03
+#define		MT9P031_WINDOW_HEIGHT_MIN		2
+#define		MT9P031_WINDOW_HEIGHT_MAX		2006
+#define		MT9P031_WINDOW_HEIGHT_DEF		1944
+#define MT9P031_WINDOW_WIDTH				0x04
+#define		MT9P031_WINDOW_WIDTH_MIN		2
+#define		MT9P031_WINDOW_WIDTH_MAX		2752
+#define		MT9P031_WINDOW_WIDTH_DEF		2592
+#define MT9P031_HORIZONTAL_BLANK			0x05
+#define		MT9P031_HORIZONTAL_BLANK_MIN		0
+#define		MT9P031_HORIZONTAL_BLANK_MAX		4095
+#define MT9P031_VERTICAL_BLANK				0x06
+#define		MT9P031_VERTICAL_BLANK_MIN		1
+#define		MT9P031_VERTICAL_BLANK_MAX		4096
+#define		MT9P031_VERTICAL_BLANK_DEF		26
+#define MT9P031_OUTPUT_CONTROL				0x07
+#define		MT9P031_OUTPUT_CONTROL_CEN		2
+#define		MT9P031_OUTPUT_CONTROL_SYN		1
+#define		MT9P031_OUTPUT_CONTROL_DEF		0x1f82
+#define MT9P031_SHUTTER_WIDTH_UPPER			0x08
+#define MT9P031_SHUTTER_WIDTH_LOWER			0x09
+#define		MT9P031_SHUTTER_WIDTH_MIN		1
+#define		MT9P031_SHUTTER_WIDTH_MAX		1048575
+#define		MT9P031_SHUTTER_WIDTH_DEF		1943
+#define	MT9P031_PLL_CONTROL				0x10
+#define		MT9P031_PLL_CONTROL_PWROFF		0x0050
+#define		MT9P031_PLL_CONTROL_PWRON		0x0051
+#define		MT9P031_PLL_CONTROL_USEPLL		0x0052
+#define	MT9P031_PLL_CONFIG_1				0x11
+#define	MT9P031_PLL_CONFIG_2				0x12
+#define MT9P031_PIXEL_CLOCK_CONTROL			0x0a
+#define MT9P031_FRAME_RESTART				0x0b
+#define MT9P031_SHUTTER_DELAY				0x0c
+#define MT9P031_RST					0x0d
+#define		MT9P031_RST_ENABLE			1
+#define		MT9P031_RST_DISABLE			0
+#define MT9P031_READ_MODE_1				0x1e
+#define MT9P031_READ_MODE_2				0x20
+#define		MT9P031_READ_MODE_2_ROW_MIR		(1 << 15)
+#define		MT9P031_READ_MODE_2_COL_MIR		(1 << 14)
+#define		MT9P031_READ_MODE_2_ROW_BLC		(1 << 6)
+#define MT9P031_ROW_ADDRESS_MODE			0x22
+#define MT9P031_COLUMN_ADDRESS_MODE			0x23
+#define MT9P031_GLOBAL_GAIN				0x35
+#define		MT9P031_GLOBAL_GAIN_MIN			8
+#define		MT9P031_GLOBAL_GAIN_MAX			1024
+#define		MT9P031_GLOBAL_GAIN_DEF			8
+#define		MT9P031_GLOBAL_GAIN_MULT		(1 << 6)
+#define MT9P031_ROW_BLACK_TARGET			0x49
+#define MT9P031_ROW_BLACK_DEF_OFFSET			0x4b
+#define MT9P031_GREEN1_OFFSET				0x60
+#define MT9P031_GREEN2_OFFSET				0x61
+#define MT9P031_BLACK_LEVEL_CALIBRATION			0x62
+#define		MT9P031_BLC_MANUAL_BLC			(1 << 0)
+#define MT9P031_RED_OFFSET				0x63
+#define MT9P031_BLUE_OFFSET				0x64
+#define MT9P031_TEST_PATTERN				0xa0
+#define		MT9P031_TEST_PATTERN_SHIFT		3
+#define		MT9P031_TEST_PATTERN_ENABLE		(1 << 0)
+#define		MT9P031_TEST_PATTERN_DISABLE		(0 << 0)
+#define MT9P031_TEST_PATTERN_GREEN			0xa1
+#define MT9P031_TEST_PATTERN_RED			0xa2
+#define MT9P031_TEST_PATTERN_BLUE			0xa3
+
+enum mt9p031_model {
+	MT9P031_MODEL_COLOR,
+	MT9P031_MODEL_MONOCHROME,
+};
+
+struct mt9p031 {
+	struct v4l2_subdev subdev;
+	struct media_pad pad;
+	struct v4l2_rect crop;  /* Sensor window */
+	struct v4l2_mbus_framefmt format;
+	struct mt9p031_platform_data *pdata;
+	struct mutex power_lock; /* lock to protect power_count */
+	int power_count;
+
+	enum mt9p031_model model;
+	struct aptina_pll pll;
+	int reset;
+
+	struct v4l2_ctrl_handler ctrls;
+	struct v4l2_ctrl *blc_auto;
+	struct v4l2_ctrl *blc_offset;
+
+	/* Registers cache */
+	u16 output_control;
+	u16 mode2;
+};
+
+static struct mt9p031 *to_mt9p031(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct mt9p031, subdev);
+}
+
+static int mt9p031_read(struct i2c_client *client, u8 reg)
+{
+	return i2c_smbus_read_word_swapped(client, reg);
+}
+
+static int mt9p031_write(struct i2c_client *client, u8 reg, u16 data)
+{
+	return i2c_smbus_write_word_swapped(client, reg, data);
+}
+
+static int mt9p031_set_output_control(struct mt9p031 *mt9p031, u16 clear,
+				      u16 set)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev);
+	u16 value = (mt9p031->output_control & ~clear) | set;
+	int ret;
+
+	ret = mt9p031_write(client, MT9P031_OUTPUT_CONTROL, value);
+	if (ret < 0)
+		return ret;
+
+	mt9p031->output_control = value;
+	return 0;
+}
+
+static int mt9p031_set_mode2(struct mt9p031 *mt9p031, u16 clear, u16 set)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev);
+	u16 value = (mt9p031->mode2 & ~clear) | set;
+	int ret;
+
+	ret = mt9p031_write(client, MT9P031_READ_MODE_2, value);
+	if (ret < 0)
+		return ret;
+
+	mt9p031->mode2 = value;
+	return 0;
+}
+
+static int mt9p031_reset(struct mt9p031 *mt9p031)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev);
+	int ret;
+
+	/* Disable chip output, synchronous option update */
+	ret = mt9p031_write(client, MT9P031_RST, MT9P031_RST_ENABLE);
+	if (ret < 0)
+		return ret;
+	ret = mt9p031_write(client, MT9P031_RST, MT9P031_RST_DISABLE);
+	if (ret < 0)
+		return ret;
+
+	return mt9p031_set_output_control(mt9p031, MT9P031_OUTPUT_CONTROL_CEN,
+					  0);
+}
+
+static int mt9p031_pll_setup(struct mt9p031 *mt9p031)
+{
+	static const struct aptina_pll_limits limits = {
+		.ext_clock_min = 6000000,
+		.ext_clock_max = 27000000,
+		.int_clock_min = 2000000,
+		.int_clock_max = 13500000,
+		.out_clock_min = 180000000,
+		.out_clock_max = 360000000,
+		.pix_clock_max = 96000000,
+		.n_min = 1,
+		.n_max = 64,
+		.m_min = 16,
+		.m_max = 255,
+		.p1_min = 1,
+		.p1_max = 128,
+	};
+
+	struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev);
+	struct mt9p031_platform_data *pdata = mt9p031->pdata;
+
+	mt9p031->pll.ext_clock = pdata->ext_freq;
+	mt9p031->pll.pix_clock = pdata->target_freq;
+
+	return aptina_pll_calculate(&client->dev, &limits, &mt9p031->pll);
+}
+
+static int mt9p031_pll_enable(struct mt9p031 *mt9p031)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev);
+	int ret;
+
+	ret = mt9p031_write(client, MT9P031_PLL_CONTROL,
+			    MT9P031_PLL_CONTROL_PWRON);
+	if (ret < 0)
+		return ret;
+
+	ret = mt9p031_write(client, MT9P031_PLL_CONFIG_1,
+			    (mt9p031->pll.m << 8) | (mt9p031->pll.n - 1));
+	if (ret < 0)
+		return ret;
+
+	ret = mt9p031_write(client, MT9P031_PLL_CONFIG_2, mt9p031->pll.p1 - 1);
+	if (ret < 0)
+		return ret;
+
+	usleep_range(1000, 2000);
+	ret = mt9p031_write(client, MT9P031_PLL_CONTROL,
+			    MT9P031_PLL_CONTROL_PWRON |
+			    MT9P031_PLL_CONTROL_USEPLL);
+	return ret;
+}
+
+static inline int mt9p031_pll_disable(struct mt9p031 *mt9p031)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev);
+
+	return mt9p031_write(client, MT9P031_PLL_CONTROL,
+			     MT9P031_PLL_CONTROL_PWROFF);
+}
+
+static int mt9p031_power_on(struct mt9p031 *mt9p031)
+{
+	/* Ensure RESET_BAR is low */
+	if (mt9p031->reset != -1) {
+		gpio_set_value(mt9p031->reset, 0);
+		usleep_range(1000, 2000);
+	}
+
+	/* Emable clock */
+	if (mt9p031->pdata->set_xclk)
+		mt9p031->pdata->set_xclk(&mt9p031->subdev,
+					 mt9p031->pdata->ext_freq);
+
+	/* Now RESET_BAR must be high */
+	if (mt9p031->reset != -1) {
+		gpio_set_value(mt9p031->reset, 1);
+		usleep_range(1000, 2000);
+	}
+
+	return 0;
+}
+
+static void mt9p031_power_off(struct mt9p031 *mt9p031)
+{
+	if (mt9p031->reset != -1) {
+		gpio_set_value(mt9p031->reset, 0);
+		usleep_range(1000, 2000);
+	}
+
+	if (mt9p031->pdata->set_xclk)
+		mt9p031->pdata->set_xclk(&mt9p031->subdev, 0);
+}
+
+static int __mt9p031_set_power(struct mt9p031 *mt9p031, bool on)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev);
+	int ret;
+
+	if (!on) {
+		mt9p031_power_off(mt9p031);
+		return 0;
+	}
+
+	ret = mt9p031_power_on(mt9p031);
+	if (ret < 0)
+		return ret;
+
+	ret = mt9p031_reset(mt9p031);
+	if (ret < 0) {
+		dev_err(&client->dev, "Failed to reset the camera\n");
+		return ret;
+	}
+
+	return v4l2_ctrl_handler_setup(&mt9p031->ctrls);
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 subdev video operations
+ */
+
+static int mt9p031_set_params(struct mt9p031 *mt9p031)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev);
+	struct v4l2_mbus_framefmt *format = &mt9p031->format;
+	const struct v4l2_rect *crop = &mt9p031->crop;
+	unsigned int hblank;
+	unsigned int vblank;
+	unsigned int xskip;
+	unsigned int yskip;
+	unsigned int xbin;
+	unsigned int ybin;
+	int ret;
+
+	/* Windows position and size.
+	 *
+	 * TODO: Make sure the start coordinates and window size match the
+	 * skipping, binning and mirroring (see description of registers 2 and 4
+	 * in table 13, and Binning section on page 41).
+	 */
+	ret = mt9p031_write(client, MT9P031_COLUMN_START, crop->left);
+	if (ret < 0)
+		return ret;
+	ret = mt9p031_write(client, MT9P031_ROW_START, crop->top);
+	if (ret < 0)
+		return ret;
+	ret = mt9p031_write(client, MT9P031_WINDOW_WIDTH, crop->width - 1);
+	if (ret < 0)
+		return ret;
+	ret = mt9p031_write(client, MT9P031_WINDOW_HEIGHT, crop->height - 1);
+	if (ret < 0)
+		return ret;
+
+	/* Row and column binning and skipping. Use the maximum binning value
+	 * compatible with the skipping settings.
+	 */
+	xskip = DIV_ROUND_CLOSEST(crop->width, format->width);
+	yskip = DIV_ROUND_CLOSEST(crop->height, format->height);
+	xbin = 1 << (ffs(xskip) - 1);
+	ybin = 1 << (ffs(yskip) - 1);
+
+	ret = mt9p031_write(client, MT9P031_COLUMN_ADDRESS_MODE,
+			    ((xbin - 1) << 4) | (xskip - 1));
+	if (ret < 0)
+		return ret;
+	ret = mt9p031_write(client, MT9P031_ROW_ADDRESS_MODE,
+			    ((ybin - 1) << 4) | (yskip - 1));
+	if (ret < 0)
+		return ret;
+
+	/* Blanking - use minimum value for horizontal blanking and default
+	 * value for vertical blanking.
+	 */
+	hblank = 346 * ybin + 64 + (80 >> min_t(unsigned int, xbin, 3));
+	vblank = MT9P031_VERTICAL_BLANK_DEF;
+
+	ret = mt9p031_write(client, MT9P031_HORIZONTAL_BLANK, hblank - 1);
+	if (ret < 0)
+		return ret;
+	ret = mt9p031_write(client, MT9P031_VERTICAL_BLANK, vblank - 1);
+	if (ret < 0)
+		return ret;
+
+	return ret;
+}
+
+static int mt9p031_s_stream(struct v4l2_subdev *subdev, int enable)
+{
+	struct mt9p031 *mt9p031 = to_mt9p031(subdev);
+	int ret;
+
+	if (!enable) {
+		/* Stop sensor readout */
+		ret = mt9p031_set_output_control(mt9p031,
+						 MT9P031_OUTPUT_CONTROL_CEN, 0);
+		if (ret < 0)
+			return ret;
+
+		return mt9p031_pll_disable(mt9p031);
+	}
+
+	ret = mt9p031_set_params(mt9p031);
+	if (ret < 0)
+		return ret;
+
+	/* Switch to master "normal" mode */
+	ret = mt9p031_set_output_control(mt9p031, 0,
+					 MT9P031_OUTPUT_CONTROL_CEN);
+	if (ret < 0)
+		return ret;
+
+	return mt9p031_pll_enable(mt9p031);
+}
+
+static int mt9p031_enum_mbus_code(struct v4l2_subdev *subdev,
+				  struct v4l2_subdev_fh *fh,
+				  struct v4l2_subdev_mbus_code_enum *code)
+{
+	struct mt9p031 *mt9p031 = to_mt9p031(subdev);
+
+	if (code->pad || code->index)
+		return -EINVAL;
+
+	code->code = mt9p031->format.code;
+	return 0;
+}
+
+static int mt9p031_enum_frame_size(struct v4l2_subdev *subdev,
+				   struct v4l2_subdev_fh *fh,
+				   struct v4l2_subdev_frame_size_enum *fse)
+{
+	struct mt9p031 *mt9p031 = to_mt9p031(subdev);
+
+	if (fse->index >= 8 || fse->code != mt9p031->format.code)
+		return -EINVAL;
+
+	fse->min_width = MT9P031_WINDOW_WIDTH_DEF
+		       / min_t(unsigned int, 7, fse->index + 1);
+	fse->max_width = fse->min_width;
+	fse->min_height = MT9P031_WINDOW_HEIGHT_DEF / (fse->index + 1);
+	fse->max_height = fse->min_height;
+
+	return 0;
+}
+
+static struct v4l2_mbus_framefmt *
+__mt9p031_get_pad_format(struct mt9p031 *mt9p031, struct v4l2_subdev_fh *fh,
+			 unsigned int pad, u32 which)
+{
+	switch (which) {
+	case V4L2_SUBDEV_FORMAT_TRY:
+		return v4l2_subdev_get_try_format(fh, pad);
+	case V4L2_SUBDEV_FORMAT_ACTIVE:
+		return &mt9p031->format;
+	default:
+		return NULL;
+	}
+}
+
+static struct v4l2_rect *
+__mt9p031_get_pad_crop(struct mt9p031 *mt9p031, struct v4l2_subdev_fh *fh,
+		     unsigned int pad, u32 which)
+{
+	switch (which) {
+	case V4L2_SUBDEV_FORMAT_TRY:
+		return v4l2_subdev_get_try_crop(fh, pad);
+	case V4L2_SUBDEV_FORMAT_ACTIVE:
+		return &mt9p031->crop;
+	default:
+		return NULL;
+	}
+}
+
+static int mt9p031_get_format(struct v4l2_subdev *subdev,
+			      struct v4l2_subdev_fh *fh,
+			      struct v4l2_subdev_format *fmt)
+{
+	struct mt9p031 *mt9p031 = to_mt9p031(subdev);
+
+	fmt->format = *__mt9p031_get_pad_format(mt9p031, fh, fmt->pad,
+						fmt->which);
+	return 0;
+}
+
+static int mt9p031_set_format(struct v4l2_subdev *subdev,
+			      struct v4l2_subdev_fh *fh,
+			      struct v4l2_subdev_format *format)
+{
+	struct mt9p031 *mt9p031 = to_mt9p031(subdev);
+	struct v4l2_mbus_framefmt *__format;
+	struct v4l2_rect *__crop;
+	unsigned int width;
+	unsigned int height;
+	unsigned int hratio;
+	unsigned int vratio;
+
+	__crop = __mt9p031_get_pad_crop(mt9p031, fh, format->pad,
+					format->which);
+
+	/* Clamp the width and height to avoid dividing by zero. */
+	width = clamp_t(unsigned int, ALIGN(format->format.width, 2),
+			max(__crop->width / 7, MT9P031_WINDOW_WIDTH_MIN),
+			__crop->width);
+	height = clamp_t(unsigned int, ALIGN(format->format.height, 2),
+			max(__crop->height / 8, MT9P031_WINDOW_HEIGHT_MIN),
+			__crop->height);
+
+	hratio = DIV_ROUND_CLOSEST(__crop->width, width);
+	vratio = DIV_ROUND_CLOSEST(__crop->height, height);
+
+	__format = __mt9p031_get_pad_format(mt9p031, fh, format->pad,
+					    format->which);
+	__format->width = __crop->width / hratio;
+	__format->height = __crop->height / vratio;
+
+	format->format = *__format;
+
+	return 0;
+}
+
+static int mt9p031_get_crop(struct v4l2_subdev *subdev,
+			    struct v4l2_subdev_fh *fh,
+			    struct v4l2_subdev_crop *crop)
+{
+	struct mt9p031 *mt9p031 = to_mt9p031(subdev);
+
+	crop->rect = *__mt9p031_get_pad_crop(mt9p031, fh, crop->pad,
+					     crop->which);
+	return 0;
+}
+
+static int mt9p031_set_crop(struct v4l2_subdev *subdev,
+			    struct v4l2_subdev_fh *fh,
+			    struct v4l2_subdev_crop *crop)
+{
+	struct mt9p031 *mt9p031 = to_mt9p031(subdev);
+	struct v4l2_mbus_framefmt *__format;
+	struct v4l2_rect *__crop;
+	struct v4l2_rect rect;
+
+	/* Clamp the crop rectangle boundaries and align them to a multiple of 2
+	 * pixels to ensure a GRBG Bayer pattern.
+	 */
+	rect.left = clamp(ALIGN(crop->rect.left, 2), MT9P031_COLUMN_START_MIN,
+			  MT9P031_COLUMN_START_MAX);
+	rect.top = clamp(ALIGN(crop->rect.top, 2), MT9P031_ROW_START_MIN,
+			 MT9P031_ROW_START_MAX);
+	rect.width = clamp(ALIGN(crop->rect.width, 2),
+			   MT9P031_WINDOW_WIDTH_MIN,
+			   MT9P031_WINDOW_WIDTH_MAX);
+	rect.height = clamp(ALIGN(crop->rect.height, 2),
+			    MT9P031_WINDOW_HEIGHT_MIN,
+			    MT9P031_WINDOW_HEIGHT_MAX);
+
+	rect.width = min(rect.width, MT9P031_PIXEL_ARRAY_WIDTH - rect.left);
+	rect.height = min(rect.height, MT9P031_PIXEL_ARRAY_HEIGHT - rect.top);
+
+	__crop = __mt9p031_get_pad_crop(mt9p031, fh, crop->pad, crop->which);
+
+	if (rect.width != __crop->width || rect.height != __crop->height) {
+		/* Reset the output image size if the crop rectangle size has
+		 * been modified.
+		 */
+		__format = __mt9p031_get_pad_format(mt9p031, fh, crop->pad,
+						    crop->which);
+		__format->width = rect.width;
+		__format->height = rect.height;
+	}
+
+	*__crop = rect;
+	crop->rect = rect;
+
+	return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 subdev control operations
+ */
+
+#define V4L2_CID_TEST_PATTERN		(V4L2_CID_USER_BASE | 0x1001)
+#define V4L2_CID_BLC_AUTO		(V4L2_CID_USER_BASE | 0x1002)
+#define V4L2_CID_BLC_TARGET_LEVEL	(V4L2_CID_USER_BASE | 0x1003)
+#define V4L2_CID_BLC_ANALOG_OFFSET	(V4L2_CID_USER_BASE | 0x1004)
+#define V4L2_CID_BLC_DIGITAL_OFFSET	(V4L2_CID_USER_BASE | 0x1005)
+
+static int mt9p031_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct mt9p031 *mt9p031 =
+			container_of(ctrl->handler, struct mt9p031, ctrls);
+	struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev);
+	u16 data;
+	int ret;
+
+	switch (ctrl->id) {
+	case V4L2_CID_EXPOSURE:
+		ret = mt9p031_write(client, MT9P031_SHUTTER_WIDTH_UPPER,
+				    (ctrl->val >> 16) & 0xffff);
+		if (ret < 0)
+			return ret;
+
+		return mt9p031_write(client, MT9P031_SHUTTER_WIDTH_LOWER,
+				     ctrl->val & 0xffff);
+
+	case V4L2_CID_GAIN:
+		/* Gain is controlled by 2 analog stages and a digital stage.
+		 * Valid values for the 3 stages are
+		 *
+		 * Stage                Min     Max     Step
+		 * ------------------------------------------
+		 * First analog stage   x1      x2      1
+		 * Second analog stage  x1      x4      0.125
+		 * Digital stage        x1      x16     0.125
+		 *
+		 * To minimize noise, the gain stages should be used in the
+		 * second analog stage, first analog stage, digital stage order.
+		 * Gain from a previous stage should be pushed to its maximum
+		 * value before the next stage is used.
+		 */
+		if (ctrl->val <= 32) {
+			data = ctrl->val;
+		} else if (ctrl->val <= 64) {
+			ctrl->val &= ~1;
+			data = (1 << 6) | (ctrl->val >> 1);
+		} else {
+			ctrl->val &= ~7;
+			data = ((ctrl->val - 64) << 5) | (1 << 6) | 32;
+		}
+
+		return mt9p031_write(client, MT9P031_GLOBAL_GAIN, data);
+
+	case V4L2_CID_HFLIP:
+		if (ctrl->val)
+			return mt9p031_set_mode2(mt9p031,
+					0, MT9P031_READ_MODE_2_COL_MIR);
+		else
+			return mt9p031_set_mode2(mt9p031,
+					MT9P031_READ_MODE_2_COL_MIR, 0);
+
+	case V4L2_CID_VFLIP:
+		if (ctrl->val)
+			return mt9p031_set_mode2(mt9p031,
+					0, MT9P031_READ_MODE_2_ROW_MIR);
+		else
+			return mt9p031_set_mode2(mt9p031,
+					MT9P031_READ_MODE_2_ROW_MIR, 0);
+
+	case V4L2_CID_TEST_PATTERN:
+		if (!ctrl->val) {
+			/* Restore the black level compensation settings. */
+			if (mt9p031->blc_auto->cur.val != 0) {
+				ret = mt9p031_s_ctrl(mt9p031->blc_auto);
+				if (ret < 0)
+					return ret;
+			}
+			if (mt9p031->blc_offset->cur.val != 0) {
+				ret = mt9p031_s_ctrl(mt9p031->blc_offset);
+				if (ret < 0)
+					return ret;
+			}
+			return mt9p031_write(client, MT9P031_TEST_PATTERN,
+					     MT9P031_TEST_PATTERN_DISABLE);
+		}
+
+		ret = mt9p031_write(client, MT9P031_TEST_PATTERN_GREEN, 0x05a0);
+		if (ret < 0)
+			return ret;
+		ret = mt9p031_write(client, MT9P031_TEST_PATTERN_RED, 0x0a50);
+		if (ret < 0)
+			return ret;
+		ret = mt9p031_write(client, MT9P031_TEST_PATTERN_BLUE, 0x0aa0);
+		if (ret < 0)
+			return ret;
+
+		/* Disable digital black level compensation when using a test
+		 * pattern.
+		 */
+		ret = mt9p031_set_mode2(mt9p031, MT9P031_READ_MODE_2_ROW_BLC,
+					0);
+		if (ret < 0)
+			return ret;
+
+		ret = mt9p031_write(client, MT9P031_ROW_BLACK_DEF_OFFSET, 0);
+		if (ret < 0)
+			return ret;
+
+		return mt9p031_write(client, MT9P031_TEST_PATTERN,
+				((ctrl->val - 1) << MT9P031_TEST_PATTERN_SHIFT)
+				| MT9P031_TEST_PATTERN_ENABLE);
+
+	case V4L2_CID_BLC_AUTO:
+		ret = mt9p031_set_mode2(mt9p031,
+				ctrl->val ? 0 : MT9P031_READ_MODE_2_ROW_BLC,
+				ctrl->val ? MT9P031_READ_MODE_2_ROW_BLC : 0);
+		if (ret < 0)
+			return ret;
+
+		return mt9p031_write(client, MT9P031_BLACK_LEVEL_CALIBRATION,
+				     ctrl->val ? 0 : MT9P031_BLC_MANUAL_BLC);
+
+	case V4L2_CID_BLC_TARGET_LEVEL:
+		return mt9p031_write(client, MT9P031_ROW_BLACK_TARGET,
+				     ctrl->val);
+
+	case V4L2_CID_BLC_ANALOG_OFFSET:
+		data = ctrl->val & ((1 << 9) - 1);
+
+		ret = mt9p031_write(client, MT9P031_GREEN1_OFFSET, data);
+		if (ret < 0)
+			return ret;
+		ret = mt9p031_write(client, MT9P031_GREEN2_OFFSET, data);
+		if (ret < 0)
+			return ret;
+		ret = mt9p031_write(client, MT9P031_RED_OFFSET, data);
+		if (ret < 0)
+			return ret;
+		return mt9p031_write(client, MT9P031_BLUE_OFFSET, data);
+
+	case V4L2_CID_BLC_DIGITAL_OFFSET:
+		return mt9p031_write(client, MT9P031_ROW_BLACK_DEF_OFFSET,
+				     ctrl->val & ((1 << 12) - 1));
+	}
+
+	return 0;
+}
+
+static struct v4l2_ctrl_ops mt9p031_ctrl_ops = {
+	.s_ctrl = mt9p031_s_ctrl,
+};
+
+static const char * const mt9p031_test_pattern_menu[] = {
+	"Disabled",
+	"Color Field",
+	"Horizontal Gradient",
+	"Vertical Gradient",
+	"Diagonal Gradient",
+	"Classic Test Pattern",
+	"Walking 1s",
+	"Monochrome Horizontal Bars",
+	"Monochrome Vertical Bars",
+	"Vertical Color Bars",
+};
+
+static const struct v4l2_ctrl_config mt9p031_ctrls[] = {
+	{
+		.ops		= &mt9p031_ctrl_ops,
+		.id		= V4L2_CID_TEST_PATTERN,
+		.type		= V4L2_CTRL_TYPE_MENU,
+		.name		= "Test Pattern",
+		.min		= 0,
+		.max		= ARRAY_SIZE(mt9p031_test_pattern_menu) - 1,
+		.step		= 0,
+		.def		= 0,
+		.flags		= 0,
+		.menu_skip_mask	= 0,
+		.qmenu		= mt9p031_test_pattern_menu,
+	}, {
+		.ops		= &mt9p031_ctrl_ops,
+		.id		= V4L2_CID_BLC_AUTO,
+		.type		= V4L2_CTRL_TYPE_BOOLEAN,
+		.name		= "BLC, Auto",
+		.min		= 0,
+		.max		= 1,
+		.step		= 1,
+		.def		= 1,
+		.flags		= 0,
+	}, {
+		.ops		= &mt9p031_ctrl_ops,
+		.id		= V4L2_CID_BLC_TARGET_LEVEL,
+		.type		= V4L2_CTRL_TYPE_INTEGER,
+		.name		= "BLC Target Level",
+		.min		= 0,
+		.max		= 4095,
+		.step		= 1,
+		.def		= 168,
+		.flags		= 0,
+	}, {
+		.ops		= &mt9p031_ctrl_ops,
+		.id		= V4L2_CID_BLC_ANALOG_OFFSET,
+		.type		= V4L2_CTRL_TYPE_INTEGER,
+		.name		= "BLC Analog Offset",
+		.min		= -255,
+		.max		= 255,
+		.step		= 1,
+		.def		= 32,
+		.flags		= 0,
+	}, {
+		.ops		= &mt9p031_ctrl_ops,
+		.id		= V4L2_CID_BLC_DIGITAL_OFFSET,
+		.type		= V4L2_CTRL_TYPE_INTEGER,
+		.name		= "BLC Digital Offset",
+		.min		= -2048,
+		.max		= 2047,
+		.step		= 1,
+		.def		= 40,
+		.flags		= 0,
+	}
+};
+
+/* -----------------------------------------------------------------------------
+ * V4L2 subdev core operations
+ */
+
+static int mt9p031_set_power(struct v4l2_subdev *subdev, int on)
+{
+	struct mt9p031 *mt9p031 = to_mt9p031(subdev);
+	int ret = 0;
+
+	mutex_lock(&mt9p031->power_lock);
+
+	/* If the power count is modified from 0 to != 0 or from != 0 to 0,
+	 * update the power state.
+	 */
+	if (mt9p031->power_count == !on) {
+		ret = __mt9p031_set_power(mt9p031, !!on);
+		if (ret < 0)
+			goto out;
+	}
+
+	/* Update the power count. */
+	mt9p031->power_count += on ? 1 : -1;
+	WARN_ON(mt9p031->power_count < 0);
+
+out:
+	mutex_unlock(&mt9p031->power_lock);
+	return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 subdev internal operations
+ */
+
+static int mt9p031_registered(struct v4l2_subdev *subdev)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(subdev);
+	struct mt9p031 *mt9p031 = to_mt9p031(subdev);
+	s32 data;
+	int ret;
+
+	ret = mt9p031_power_on(mt9p031);
+	if (ret < 0) {
+		dev_err(&client->dev, "MT9P031 power up failed\n");
+		return ret;
+	}
+
+	/* Read out the chip version register */
+	data = mt9p031_read(client, MT9P031_CHIP_VERSION);
+	if (data != MT9P031_CHIP_VERSION_VALUE) {
+		dev_err(&client->dev, "MT9P031 not detected, wrong version "
+			"0x%04x\n", data);
+		return -ENODEV;
+	}
+
+	mt9p031_power_off(mt9p031);
+
+	dev_info(&client->dev, "MT9P031 detected at address 0x%02x\n",
+		 client->addr);
+
+	return ret;
+}
+
+static int mt9p031_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
+{
+	struct mt9p031 *mt9p031 = to_mt9p031(subdev);
+	struct v4l2_mbus_framefmt *format;
+	struct v4l2_rect *crop;
+
+	crop = v4l2_subdev_get_try_crop(fh, 0);
+	crop->left = MT9P031_COLUMN_START_DEF;
+	crop->top = MT9P031_ROW_START_DEF;
+	crop->width = MT9P031_WINDOW_WIDTH_DEF;
+	crop->height = MT9P031_WINDOW_HEIGHT_DEF;
+
+	format = v4l2_subdev_get_try_format(fh, 0);
+
+	if (mt9p031->model == MT9P031_MODEL_MONOCHROME)
+		format->code = V4L2_MBUS_FMT_Y12_1X12;
+	else
+		format->code = V4L2_MBUS_FMT_SGRBG12_1X12;
+
+	format->width = MT9P031_WINDOW_WIDTH_DEF;
+	format->height = MT9P031_WINDOW_HEIGHT_DEF;
+	format->field = V4L2_FIELD_NONE;
+	format->colorspace = V4L2_COLORSPACE_SRGB;
+
+	return mt9p031_set_power(subdev, 1);
+}
+
+static int mt9p031_close(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
+{
+	return mt9p031_set_power(subdev, 0);
+}
+
+static struct v4l2_subdev_core_ops mt9p031_subdev_core_ops = {
+	.s_power        = mt9p031_set_power,
+};
+
+static struct v4l2_subdev_video_ops mt9p031_subdev_video_ops = {
+	.s_stream       = mt9p031_s_stream,
+};
+
+static struct v4l2_subdev_pad_ops mt9p031_subdev_pad_ops = {
+	.enum_mbus_code = mt9p031_enum_mbus_code,
+	.enum_frame_size = mt9p031_enum_frame_size,
+	.get_fmt = mt9p031_get_format,
+	.set_fmt = mt9p031_set_format,
+	.get_crop = mt9p031_get_crop,
+	.set_crop = mt9p031_set_crop,
+};
+
+static struct v4l2_subdev_ops mt9p031_subdev_ops = {
+	.core   = &mt9p031_subdev_core_ops,
+	.video  = &mt9p031_subdev_video_ops,
+	.pad    = &mt9p031_subdev_pad_ops,
+};
+
+static const struct v4l2_subdev_internal_ops mt9p031_subdev_internal_ops = {
+	.registered = mt9p031_registered,
+	.open = mt9p031_open,
+	.close = mt9p031_close,
+};
+
+/* -----------------------------------------------------------------------------
+ * Driver initialization and probing
+ */
+
+static int mt9p031_probe(struct i2c_client *client,
+			 const struct i2c_device_id *did)
+{
+	struct mt9p031_platform_data *pdata = client->dev.platform_data;
+	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+	struct mt9p031 *mt9p031;
+	unsigned int i;
+	int ret;
+
+	if (pdata == NULL) {
+		dev_err(&client->dev, "No platform data\n");
+		return -EINVAL;
+	}
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) {
+		dev_warn(&client->dev,
+			"I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n");
+		return -EIO;
+	}
+
+	mt9p031 = kzalloc(sizeof(*mt9p031), GFP_KERNEL);
+	if (mt9p031 == NULL)
+		return -ENOMEM;
+
+	mt9p031->pdata = pdata;
+	mt9p031->output_control	= MT9P031_OUTPUT_CONTROL_DEF;
+	mt9p031->mode2 = MT9P031_READ_MODE_2_ROW_BLC;
+	mt9p031->model = did->driver_data;
+	mt9p031->reset = -1;
+
+	v4l2_ctrl_handler_init(&mt9p031->ctrls, ARRAY_SIZE(mt9p031_ctrls) + 5);
+
+	v4l2_ctrl_new_std(&mt9p031->ctrls, &mt9p031_ctrl_ops,
+			  V4L2_CID_EXPOSURE, MT9P031_SHUTTER_WIDTH_MIN,
+			  MT9P031_SHUTTER_WIDTH_MAX, 1,
+			  MT9P031_SHUTTER_WIDTH_DEF);
+	v4l2_ctrl_new_std(&mt9p031->ctrls, &mt9p031_ctrl_ops,
+			  V4L2_CID_GAIN, MT9P031_GLOBAL_GAIN_MIN,
+			  MT9P031_GLOBAL_GAIN_MAX, 1, MT9P031_GLOBAL_GAIN_DEF);
+	v4l2_ctrl_new_std(&mt9p031->ctrls, &mt9p031_ctrl_ops,
+			  V4L2_CID_HFLIP, 0, 1, 1, 0);
+	v4l2_ctrl_new_std(&mt9p031->ctrls, &mt9p031_ctrl_ops,
+			  V4L2_CID_VFLIP, 0, 1, 1, 0);
+	v4l2_ctrl_new_std(&mt9p031->ctrls, &mt9p031_ctrl_ops,
+			  V4L2_CID_PIXEL_RATE, pdata->target_freq,
+			  pdata->target_freq, 1, pdata->target_freq);
+
+	for (i = 0; i < ARRAY_SIZE(mt9p031_ctrls); ++i)
+		v4l2_ctrl_new_custom(&mt9p031->ctrls, &mt9p031_ctrls[i], NULL);
+
+	mt9p031->subdev.ctrl_handler = &mt9p031->ctrls;
+
+	if (mt9p031->ctrls.error) {
+		printk(KERN_INFO "%s: control initialization error %d\n",
+		       __func__, mt9p031->ctrls.error);
+		ret = mt9p031->ctrls.error;
+		goto done;
+	}
+
+	mt9p031->blc_auto = v4l2_ctrl_find(&mt9p031->ctrls, V4L2_CID_BLC_AUTO);
+	mt9p031->blc_offset = v4l2_ctrl_find(&mt9p031->ctrls,
+					     V4L2_CID_BLC_DIGITAL_OFFSET);
+
+	mutex_init(&mt9p031->power_lock);
+	v4l2_i2c_subdev_init(&mt9p031->subdev, client, &mt9p031_subdev_ops);
+	mt9p031->subdev.internal_ops = &mt9p031_subdev_internal_ops;
+
+	mt9p031->pad.flags = MEDIA_PAD_FL_SOURCE;
+	ret = media_entity_init(&mt9p031->subdev.entity, 1, &mt9p031->pad, 0);
+	if (ret < 0)
+		goto done;
+
+	mt9p031->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+	mt9p031->crop.width = MT9P031_WINDOW_WIDTH_DEF;
+	mt9p031->crop.height = MT9P031_WINDOW_HEIGHT_DEF;
+	mt9p031->crop.left = MT9P031_COLUMN_START_DEF;
+	mt9p031->crop.top = MT9P031_ROW_START_DEF;
+
+	if (mt9p031->model == MT9P031_MODEL_MONOCHROME)
+		mt9p031->format.code = V4L2_MBUS_FMT_Y12_1X12;
+	else
+		mt9p031->format.code = V4L2_MBUS_FMT_SGRBG12_1X12;
+
+	mt9p031->format.width = MT9P031_WINDOW_WIDTH_DEF;
+	mt9p031->format.height = MT9P031_WINDOW_HEIGHT_DEF;
+	mt9p031->format.field = V4L2_FIELD_NONE;
+	mt9p031->format.colorspace = V4L2_COLORSPACE_SRGB;
+
+	if (pdata->reset != -1) {
+		ret = gpio_request_one(pdata->reset, GPIOF_OUT_INIT_LOW,
+				       "mt9p031_rst");
+		if (ret < 0)
+			goto done;
+
+		mt9p031->reset = pdata->reset;
+	}
+
+	ret = mt9p031_pll_setup(mt9p031);
+
+done:
+	if (ret < 0) {
+		if (mt9p031->reset != -1)
+			gpio_free(mt9p031->reset);
+
+		v4l2_ctrl_handler_free(&mt9p031->ctrls);
+		media_entity_cleanup(&mt9p031->subdev.entity);
+		kfree(mt9p031);
+	}
+
+	return ret;
+}
+
+static int mt9p031_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *subdev = i2c_get_clientdata(client);
+	struct mt9p031 *mt9p031 = to_mt9p031(subdev);
+
+	v4l2_ctrl_handler_free(&mt9p031->ctrls);
+	v4l2_device_unregister_subdev(subdev);
+	media_entity_cleanup(&subdev->entity);
+	if (mt9p031->reset != -1)
+		gpio_free(mt9p031->reset);
+	kfree(mt9p031);
+
+	return 0;
+}
+
+static const struct i2c_device_id mt9p031_id[] = {
+	{ "mt9p031", MT9P031_MODEL_COLOR },
+	{ "mt9p031m", MT9P031_MODEL_MONOCHROME },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, mt9p031_id);
+
+static struct i2c_driver mt9p031_i2c_driver = {
+	.driver = {
+		.name = "mt9p031",
+	},
+	.probe          = mt9p031_probe,
+	.remove         = mt9p031_remove,
+	.id_table       = mt9p031_id,
+};
+
+module_i2c_driver(mt9p031_i2c_driver);
+
+MODULE_DESCRIPTION("Aptina MT9P031 Camera driver");
+MODULE_AUTHOR("Bastian Hecht <hechtb@gmail.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/i2c/mt9t001.c b/drivers/media/i2c/mt9t001.c
new file mode 100644
index 0000000..6d343ad
--- /dev/null
+++ b/drivers/media/i2c/mt9t001.c
@@ -0,0 +1,833 @@
+/*
+ * Driver for MT9T001 CMOS Image Sensor from Aptina (Micron)
+ *
+ * Copyright (C) 2010-2011, Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * Based on the MT9M001 driver,
+ *
+ * Copyright (C) 2008, Guennadi Liakhovetski <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 version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/log2.h>
+#include <linux/slab.h>
+#include <linux/videodev2.h>
+#include <linux/v4l2-mediabus.h>
+
+#include <media/mt9t001.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+
+#define MT9T001_PIXEL_ARRAY_HEIGHT			1568
+#define MT9T001_PIXEL_ARRAY_WIDTH			2112
+
+#define MT9T001_CHIP_VERSION				0x00
+#define		MT9T001_CHIP_ID				0x1621
+#define MT9T001_ROW_START				0x01
+#define		MT9T001_ROW_START_MIN			0
+#define		MT9T001_ROW_START_DEF			20
+#define		MT9T001_ROW_START_MAX			1534
+#define MT9T001_COLUMN_START				0x02
+#define		MT9T001_COLUMN_START_MIN		0
+#define		MT9T001_COLUMN_START_DEF		32
+#define		MT9T001_COLUMN_START_MAX		2046
+#define MT9T001_WINDOW_HEIGHT				0x03
+#define		MT9T001_WINDOW_HEIGHT_MIN		1
+#define		MT9T001_WINDOW_HEIGHT_DEF		1535
+#define		MT9T001_WINDOW_HEIGHT_MAX		1567
+#define MT9T001_WINDOW_WIDTH				0x04
+#define		MT9T001_WINDOW_WIDTH_MIN		1
+#define		MT9T001_WINDOW_WIDTH_DEF		2047
+#define		MT9T001_WINDOW_WIDTH_MAX		2111
+#define MT9T001_HORIZONTAL_BLANKING			0x05
+#define		MT9T001_HORIZONTAL_BLANKING_MIN		21
+#define		MT9T001_HORIZONTAL_BLANKING_MAX		1023
+#define MT9T001_VERTICAL_BLANKING			0x06
+#define		MT9T001_VERTICAL_BLANKING_MIN		3
+#define		MT9T001_VERTICAL_BLANKING_MAX		1023
+#define MT9T001_OUTPUT_CONTROL				0x07
+#define		MT9T001_OUTPUT_CONTROL_SYNC		(1 << 0)
+#define		MT9T001_OUTPUT_CONTROL_CHIP_ENABLE	(1 << 1)
+#define		MT9T001_OUTPUT_CONTROL_TEST_DATA	(1 << 6)
+#define MT9T001_SHUTTER_WIDTH_HIGH			0x08
+#define MT9T001_SHUTTER_WIDTH_LOW			0x09
+#define		MT9T001_SHUTTER_WIDTH_MIN		1
+#define		MT9T001_SHUTTER_WIDTH_DEF		1561
+#define		MT9T001_SHUTTER_WIDTH_MAX		(1024 * 1024)
+#define MT9T001_PIXEL_CLOCK				0x0a
+#define		MT9T001_PIXEL_CLOCK_INVERT		(1 << 15)
+#define		MT9T001_PIXEL_CLOCK_SHIFT_MASK		(7 << 8)
+#define		MT9T001_PIXEL_CLOCK_SHIFT_SHIFT		8
+#define		MT9T001_PIXEL_CLOCK_DIVIDE_MASK		(0x7f << 0)
+#define MT9T001_FRAME_RESTART				0x0b
+#define MT9T001_SHUTTER_DELAY				0x0c
+#define		MT9T001_SHUTTER_DELAY_MAX		2047
+#define MT9T001_RESET					0x0d
+#define MT9T001_READ_MODE1				0x1e
+#define		MT9T001_READ_MODE_SNAPSHOT		(1 << 8)
+#define		MT9T001_READ_MODE_STROBE_ENABLE		(1 << 9)
+#define		MT9T001_READ_MODE_STROBE_WIDTH		(1 << 10)
+#define		MT9T001_READ_MODE_STROBE_OVERRIDE	(1 << 11)
+#define MT9T001_READ_MODE2				0x20
+#define		MT9T001_READ_MODE_BAD_FRAMES		(1 << 0)
+#define		MT9T001_READ_MODE_LINE_VALID_CONTINUOUS	(1 << 9)
+#define		MT9T001_READ_MODE_LINE_VALID_FRAME	(1 << 10)
+#define MT9T001_READ_MODE3				0x21
+#define		MT9T001_READ_MODE_GLOBAL_RESET		(1 << 0)
+#define		MT9T001_READ_MODE_GHST_CTL		(1 << 1)
+#define MT9T001_ROW_ADDRESS_MODE			0x22
+#define		MT9T001_ROW_SKIP_MASK			(7 << 0)
+#define		MT9T001_ROW_BIN_MASK			(3 << 3)
+#define		MT9T001_ROW_BIN_SHIFT			3
+#define MT9T001_COLUMN_ADDRESS_MODE			0x23
+#define		MT9T001_COLUMN_SKIP_MASK		(7 << 0)
+#define		MT9T001_COLUMN_BIN_MASK			(3 << 3)
+#define		MT9T001_COLUMN_BIN_SHIFT		3
+#define MT9T001_GREEN1_GAIN				0x2b
+#define MT9T001_BLUE_GAIN				0x2c
+#define MT9T001_RED_GAIN				0x2d
+#define MT9T001_GREEN2_GAIN				0x2e
+#define MT9T001_TEST_DATA				0x32
+#define MT9T001_GLOBAL_GAIN				0x35
+#define		MT9T001_GLOBAL_GAIN_MIN			8
+#define		MT9T001_GLOBAL_GAIN_MAX			1024
+#define MT9T001_BLACK_LEVEL				0x49
+#define MT9T001_ROW_BLACK_DEFAULT_OFFSET		0x4b
+#define MT9T001_BLC_DELTA_THRESHOLDS			0x5d
+#define MT9T001_CAL_THRESHOLDS				0x5f
+#define MT9T001_GREEN1_OFFSET				0x60
+#define MT9T001_GREEN2_OFFSET				0x61
+#define MT9T001_BLACK_LEVEL_CALIBRATION			0x62
+#define		MT9T001_BLACK_LEVEL_OVERRIDE		(1 << 0)
+#define		MT9T001_BLACK_LEVEL_DISABLE_OFFSET	(1 << 1)
+#define		MT9T001_BLACK_LEVEL_RECALCULATE		(1 << 12)
+#define		MT9T001_BLACK_LEVEL_LOCK_RED_BLUE	(1 << 13)
+#define		MT9T001_BLACK_LEVEL_LOCK_GREEN		(1 << 14)
+#define MT9T001_RED_OFFSET				0x63
+#define MT9T001_BLUE_OFFSET				0x64
+
+struct mt9t001 {
+	struct v4l2_subdev subdev;
+	struct media_pad pad;
+
+	struct v4l2_mbus_framefmt format;
+	struct v4l2_rect crop;
+
+	struct v4l2_ctrl_handler ctrls;
+	struct v4l2_ctrl *gains[4];
+
+	u16 output_control;
+	u16 black_level;
+};
+
+static inline struct mt9t001 *to_mt9t001(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct mt9t001, subdev);
+}
+
+static int mt9t001_read(struct i2c_client *client, u8 reg)
+{
+	return i2c_smbus_read_word_swapped(client, reg);
+}
+
+static int mt9t001_write(struct i2c_client *client, u8 reg, u16 data)
+{
+	return i2c_smbus_write_word_swapped(client, reg, data);
+}
+
+static int mt9t001_set_output_control(struct mt9t001 *mt9t001, u16 clear,
+				      u16 set)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&mt9t001->subdev);
+	u16 value = (mt9t001->output_control & ~clear) | set;
+	int ret;
+
+	if (value == mt9t001->output_control)
+		return 0;
+
+	ret = mt9t001_write(client, MT9T001_OUTPUT_CONTROL, value);
+	if (ret < 0)
+		return ret;
+
+	mt9t001->output_control = value;
+	return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 subdev video operations
+ */
+
+static struct v4l2_mbus_framefmt *
+__mt9t001_get_pad_format(struct mt9t001 *mt9t001, struct v4l2_subdev_fh *fh,
+			 unsigned int pad, enum v4l2_subdev_format_whence which)
+{
+	switch (which) {
+	case V4L2_SUBDEV_FORMAT_TRY:
+		return v4l2_subdev_get_try_format(fh, pad);
+	case V4L2_SUBDEV_FORMAT_ACTIVE:
+		return &mt9t001->format;
+	default:
+		return NULL;
+	}
+}
+
+static struct v4l2_rect *
+__mt9t001_get_pad_crop(struct mt9t001 *mt9t001, struct v4l2_subdev_fh *fh,
+		       unsigned int pad, enum v4l2_subdev_format_whence which)
+{
+	switch (which) {
+	case V4L2_SUBDEV_FORMAT_TRY:
+		return v4l2_subdev_get_try_crop(fh, pad);
+	case V4L2_SUBDEV_FORMAT_ACTIVE:
+		return &mt9t001->crop;
+	default:
+		return NULL;
+	}
+}
+
+static int mt9t001_s_stream(struct v4l2_subdev *subdev, int enable)
+{
+	const u16 mode = MT9T001_OUTPUT_CONTROL_CHIP_ENABLE;
+	struct i2c_client *client = v4l2_get_subdevdata(subdev);
+	struct mt9t001 *mt9t001 = to_mt9t001(subdev);
+	struct v4l2_mbus_framefmt *format = &mt9t001->format;
+	struct v4l2_rect *crop = &mt9t001->crop;
+	unsigned int hratio;
+	unsigned int vratio;
+	int ret;
+
+	if (!enable)
+		return mt9t001_set_output_control(mt9t001, mode, 0);
+
+	/* Configure the window size and row/column bin */
+	hratio = DIV_ROUND_CLOSEST(crop->width, format->width);
+	vratio = DIV_ROUND_CLOSEST(crop->height, format->height);
+
+	ret = mt9t001_write(client, MT9T001_ROW_ADDRESS_MODE, hratio - 1);
+	if (ret < 0)
+		return ret;
+
+	ret = mt9t001_write(client, MT9T001_COLUMN_ADDRESS_MODE, vratio - 1);
+	if (ret < 0)
+		return ret;
+
+	ret = mt9t001_write(client, MT9T001_COLUMN_START, crop->left);
+	if (ret < 0)
+		return ret;
+
+	ret = mt9t001_write(client, MT9T001_ROW_START, crop->top);
+	if (ret < 0)
+		return ret;
+
+	ret = mt9t001_write(client, MT9T001_WINDOW_WIDTH, crop->width - 1);
+	if (ret < 0)
+		return ret;
+
+	ret = mt9t001_write(client, MT9T001_WINDOW_HEIGHT, crop->height - 1);
+	if (ret < 0)
+		return ret;
+
+	/* Switch to master "normal" mode */
+	return mt9t001_set_output_control(mt9t001, 0, mode);
+}
+
+static int mt9t001_enum_mbus_code(struct v4l2_subdev *subdev,
+				  struct v4l2_subdev_fh *fh,
+				  struct v4l2_subdev_mbus_code_enum *code)
+{
+	if (code->index > 0)
+		return -EINVAL;
+
+	code->code = V4L2_MBUS_FMT_SGRBG10_1X10;
+	return 0;
+}
+
+static int mt9t001_enum_frame_size(struct v4l2_subdev *subdev,
+				   struct v4l2_subdev_fh *fh,
+				   struct v4l2_subdev_frame_size_enum *fse)
+{
+	if (fse->index >= 8 || fse->code != V4L2_MBUS_FMT_SGRBG10_1X10)
+		return -EINVAL;
+
+	fse->min_width = (MT9T001_WINDOW_WIDTH_DEF + 1) / fse->index;
+	fse->max_width = fse->min_width;
+	fse->min_height = (MT9T001_WINDOW_HEIGHT_DEF + 1) / fse->index;
+	fse->max_height = fse->min_height;
+
+	return 0;
+}
+
+static int mt9t001_get_format(struct v4l2_subdev *subdev,
+			      struct v4l2_subdev_fh *fh,
+			      struct v4l2_subdev_format *format)
+{
+	struct mt9t001 *mt9t001 = to_mt9t001(subdev);
+
+	format->format = *__mt9t001_get_pad_format(mt9t001, fh, format->pad,
+						   format->which);
+	return 0;
+}
+
+static int mt9t001_set_format(struct v4l2_subdev *subdev,
+			      struct v4l2_subdev_fh *fh,
+			      struct v4l2_subdev_format *format)
+{
+	struct mt9t001 *mt9t001 = to_mt9t001(subdev);
+	struct v4l2_mbus_framefmt *__format;
+	struct v4l2_rect *__crop;
+	unsigned int width;
+	unsigned int height;
+	unsigned int hratio;
+	unsigned int vratio;
+
+	__crop = __mt9t001_get_pad_crop(mt9t001, fh, format->pad,
+					format->which);
+
+	/* Clamp the width and height to avoid dividing by zero. */
+	width = clamp_t(unsigned int, ALIGN(format->format.width, 2),
+			max(__crop->width / 8, MT9T001_WINDOW_HEIGHT_MIN + 1),
+			__crop->width);
+	height = clamp_t(unsigned int, ALIGN(format->format.height, 2),
+			 max(__crop->height / 8, MT9T001_WINDOW_HEIGHT_MIN + 1),
+			 __crop->height);
+
+	hratio = DIV_ROUND_CLOSEST(__crop->width, width);
+	vratio = DIV_ROUND_CLOSEST(__crop->height, height);
+
+	__format = __mt9t001_get_pad_format(mt9t001, fh, format->pad,
+					    format->which);
+	__format->width = __crop->width / hratio;
+	__format->height = __crop->height / vratio;
+
+	format->format = *__format;
+
+	return 0;
+}
+
+static int mt9t001_get_crop(struct v4l2_subdev *subdev,
+			    struct v4l2_subdev_fh *fh,
+			    struct v4l2_subdev_crop *crop)
+{
+	struct mt9t001 *mt9t001 = to_mt9t001(subdev);
+
+	crop->rect = *__mt9t001_get_pad_crop(mt9t001, fh, crop->pad,
+					     crop->which);
+	return 0;
+}
+
+static int mt9t001_set_crop(struct v4l2_subdev *subdev,
+			    struct v4l2_subdev_fh *fh,
+			    struct v4l2_subdev_crop *crop)
+{
+	struct mt9t001 *mt9t001 = to_mt9t001(subdev);
+	struct v4l2_mbus_framefmt *__format;
+	struct v4l2_rect *__crop;
+	struct v4l2_rect rect;
+
+	/* Clamp the crop rectangle boundaries and align them to a multiple of 2
+	 * pixels.
+	 */
+	rect.left = clamp(ALIGN(crop->rect.left, 2),
+			  MT9T001_COLUMN_START_MIN,
+			  MT9T001_COLUMN_START_MAX);
+	rect.top = clamp(ALIGN(crop->rect.top, 2),
+			 MT9T001_ROW_START_MIN,
+			 MT9T001_ROW_START_MAX);
+	rect.width = clamp(ALIGN(crop->rect.width, 2),
+			   MT9T001_WINDOW_WIDTH_MIN + 1,
+			   MT9T001_WINDOW_WIDTH_MAX + 1);
+	rect.height = clamp(ALIGN(crop->rect.height, 2),
+			    MT9T001_WINDOW_HEIGHT_MIN + 1,
+			    MT9T001_WINDOW_HEIGHT_MAX + 1);
+
+	rect.width = min(rect.width, MT9T001_PIXEL_ARRAY_WIDTH - rect.left);
+	rect.height = min(rect.height, MT9T001_PIXEL_ARRAY_HEIGHT - rect.top);
+
+	__crop = __mt9t001_get_pad_crop(mt9t001, fh, crop->pad, crop->which);
+
+	if (rect.width != __crop->width || rect.height != __crop->height) {
+		/* Reset the output image size if the crop rectangle size has
+		 * been modified.
+		 */
+		__format = __mt9t001_get_pad_format(mt9t001, fh, crop->pad,
+						    crop->which);
+		__format->width = rect.width;
+		__format->height = rect.height;
+	}
+
+	*__crop = rect;
+	crop->rect = rect;
+
+	return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 subdev control operations
+ */
+
+#define V4L2_CID_TEST_PATTERN		(V4L2_CID_USER_BASE | 0x1001)
+#define V4L2_CID_BLACK_LEVEL_AUTO	(V4L2_CID_USER_BASE | 0x1002)
+#define V4L2_CID_BLACK_LEVEL_OFFSET	(V4L2_CID_USER_BASE | 0x1003)
+#define V4L2_CID_BLACK_LEVEL_CALIBRATE	(V4L2_CID_USER_BASE | 0x1004)
+
+#define V4L2_CID_GAIN_RED		(V4L2_CTRL_CLASS_CAMERA | 0x1001)
+#define V4L2_CID_GAIN_GREEN_RED		(V4L2_CTRL_CLASS_CAMERA | 0x1002)
+#define V4L2_CID_GAIN_GREEN_BLUE	(V4L2_CTRL_CLASS_CAMERA | 0x1003)
+#define V4L2_CID_GAIN_BLUE		(V4L2_CTRL_CLASS_CAMERA | 0x1004)
+
+static u16 mt9t001_gain_value(s32 *gain)
+{
+	/* Gain is controlled by 2 analog stages and a digital stage. Valid
+	 * values for the 3 stages are
+	 *
+	 * Stage		Min	Max	Step
+	 * ------------------------------------------
+	 * First analog stage	x1	x2	1
+	 * Second analog stage	x1	x4	0.125
+	 * Digital stage	x1	x16	0.125
+	 *
+	 * To minimize noise, the gain stages should be used in the second
+	 * analog stage, first analog stage, digital stage order. Gain from a
+	 * previous stage should be pushed to its maximum value before the next
+	 * stage is used.
+	 */
+	if (*gain <= 32)
+		return *gain;
+
+	if (*gain <= 64) {
+		*gain &= ~1;
+		return (1 << 6) | (*gain >> 1);
+	}
+
+	*gain &= ~7;
+	return ((*gain - 64) << 5) | (1 << 6) | 32;
+}
+
+static int mt9t001_ctrl_freeze(struct mt9t001 *mt9t001, bool freeze)
+{
+	return mt9t001_set_output_control(mt9t001,
+		freeze ? 0 : MT9T001_OUTPUT_CONTROL_SYNC,
+		freeze ? MT9T001_OUTPUT_CONTROL_SYNC : 0);
+}
+
+static int mt9t001_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	static const u8 gains[4] = {
+		MT9T001_RED_GAIN, MT9T001_GREEN1_GAIN,
+		MT9T001_GREEN2_GAIN, MT9T001_BLUE_GAIN
+	};
+
+	struct mt9t001 *mt9t001 =
+			container_of(ctrl->handler, struct mt9t001, ctrls);
+	struct i2c_client *client = v4l2_get_subdevdata(&mt9t001->subdev);
+	unsigned int count;
+	unsigned int i;
+	u16 value;
+	int ret;
+
+	switch (ctrl->id) {
+	case V4L2_CID_GAIN_RED:
+	case V4L2_CID_GAIN_GREEN_RED:
+	case V4L2_CID_GAIN_GREEN_BLUE:
+	case V4L2_CID_GAIN_BLUE:
+
+		/* Disable control updates if more than one control has changed
+		 * in the cluster.
+		 */
+		for (i = 0, count = 0; i < 4; ++i) {
+			struct v4l2_ctrl *gain = mt9t001->gains[i];
+
+			if (gain->val != gain->cur.val)
+				count++;
+		}
+
+		if (count > 1) {
+			ret = mt9t001_ctrl_freeze(mt9t001, true);
+			if (ret < 0)
+				return ret;
+		}
+
+		/* Update the gain controls. */
+		for (i = 0; i < 4; ++i) {
+			struct v4l2_ctrl *gain = mt9t001->gains[i];
+
+			if (gain->val == gain->cur.val)
+				continue;
+
+			value = mt9t001_gain_value(&gain->val);
+			ret = mt9t001_write(client, gains[i], value);
+			if (ret < 0) {
+				mt9t001_ctrl_freeze(mt9t001, false);
+				return ret;
+			}
+		}
+
+		/* Enable control updates. */
+		if (count > 1) {
+			ret = mt9t001_ctrl_freeze(mt9t001, false);
+			if (ret < 0)
+				return ret;
+		}
+
+		break;
+
+	case V4L2_CID_EXPOSURE:
+		ret = mt9t001_write(client, MT9T001_SHUTTER_WIDTH_LOW,
+				    ctrl->val & 0xffff);
+		if (ret < 0)
+			return ret;
+
+		return mt9t001_write(client, MT9T001_SHUTTER_WIDTH_HIGH,
+				     ctrl->val >> 16);
+
+	case V4L2_CID_TEST_PATTERN:
+		ret = mt9t001_set_output_control(mt9t001,
+			ctrl->val ? 0 : MT9T001_OUTPUT_CONTROL_TEST_DATA,
+			ctrl->val ? MT9T001_OUTPUT_CONTROL_TEST_DATA : 0);
+		if (ret < 0)
+			return ret;
+
+		return mt9t001_write(client, MT9T001_TEST_DATA, ctrl->val << 2);
+
+	case V4L2_CID_BLACK_LEVEL_AUTO:
+		value = ctrl->val ? 0 : MT9T001_BLACK_LEVEL_OVERRIDE;
+		ret = mt9t001_write(client, MT9T001_BLACK_LEVEL_CALIBRATION,
+				    value);
+		if (ret < 0)
+			return ret;
+
+		mt9t001->black_level = value;
+		break;
+
+	case V4L2_CID_BLACK_LEVEL_OFFSET:
+		ret = mt9t001_write(client, MT9T001_GREEN1_OFFSET, ctrl->val);
+		if (ret < 0)
+			return ret;
+
+		ret = mt9t001_write(client, MT9T001_GREEN2_OFFSET, ctrl->val);
+		if (ret < 0)
+			return ret;
+
+		ret = mt9t001_write(client, MT9T001_RED_OFFSET, ctrl->val);
+		if (ret < 0)
+			return ret;
+
+		return mt9t001_write(client, MT9T001_BLUE_OFFSET, ctrl->val);
+
+	case V4L2_CID_BLACK_LEVEL_CALIBRATE:
+		return mt9t001_write(client, MT9T001_BLACK_LEVEL_CALIBRATION,
+				     MT9T001_BLACK_LEVEL_RECALCULATE |
+				     mt9t001->black_level);
+	}
+
+	return 0;
+}
+
+static struct v4l2_ctrl_ops mt9t001_ctrl_ops = {
+	.s_ctrl = mt9t001_s_ctrl,
+};
+
+static const struct v4l2_ctrl_config mt9t001_ctrls[] = {
+	{
+		.ops		= &mt9t001_ctrl_ops,
+		.id		= V4L2_CID_TEST_PATTERN,
+		.type		= V4L2_CTRL_TYPE_INTEGER,
+		.name		= "Test pattern",
+		.min		= 0,
+		.max		= 1023,
+		.step		= 1,
+		.def		= 0,
+		.flags		= 0,
+	}, {
+		.ops		= &mt9t001_ctrl_ops,
+		.id		= V4L2_CID_BLACK_LEVEL_AUTO,
+		.type		= V4L2_CTRL_TYPE_BOOLEAN,
+		.name		= "Black Level, Auto",
+		.min		= 0,
+		.max		= 1,
+		.step		= 1,
+		.def		= 1,
+		.flags		= 0,
+	}, {
+		.ops		= &mt9t001_ctrl_ops,
+		.id		= V4L2_CID_BLACK_LEVEL_OFFSET,
+		.type		= V4L2_CTRL_TYPE_INTEGER,
+		.name		= "Black Level, Offset",
+		.min		= -256,
+		.max		= 255,
+		.step		= 1,
+		.def		= 32,
+		.flags		= 0,
+	}, {
+		.ops		= &mt9t001_ctrl_ops,
+		.id		= V4L2_CID_BLACK_LEVEL_CALIBRATE,
+		.type		= V4L2_CTRL_TYPE_BUTTON,
+		.name		= "Black Level, Calibrate",
+		.min		= 0,
+		.max		= 0,
+		.step		= 0,
+		.def		= 0,
+		.flags		= V4L2_CTRL_FLAG_WRITE_ONLY,
+	},
+};
+
+static const struct v4l2_ctrl_config mt9t001_gains[] = {
+	{
+		.ops		= &mt9t001_ctrl_ops,
+		.id		= V4L2_CID_GAIN_RED,
+		.type		= V4L2_CTRL_TYPE_INTEGER,
+		.name		= "Gain, Red",
+		.min		= MT9T001_GLOBAL_GAIN_MIN,
+		.max		= MT9T001_GLOBAL_GAIN_MAX,
+		.step		= 1,
+		.def		= MT9T001_GLOBAL_GAIN_MIN,
+		.flags		= 0,
+	}, {
+		.ops		= &mt9t001_ctrl_ops,
+		.id		= V4L2_CID_GAIN_GREEN_RED,
+		.type		= V4L2_CTRL_TYPE_INTEGER,
+		.name		= "Gain, Green (R)",
+		.min		= MT9T001_GLOBAL_GAIN_MIN,
+		.max		= MT9T001_GLOBAL_GAIN_MAX,
+		.step		= 1,
+		.def		= MT9T001_GLOBAL_GAIN_MIN,
+		.flags		= 0,
+	}, {
+		.ops		= &mt9t001_ctrl_ops,
+		.id		= V4L2_CID_GAIN_GREEN_BLUE,
+		.type		= V4L2_CTRL_TYPE_INTEGER,
+		.name		= "Gain, Green (B)",
+		.min		= MT9T001_GLOBAL_GAIN_MIN,
+		.max		= MT9T001_GLOBAL_GAIN_MAX,
+		.step		= 1,
+		.def		= MT9T001_GLOBAL_GAIN_MIN,
+		.flags		= 0,
+	}, {
+		.ops		= &mt9t001_ctrl_ops,
+		.id		= V4L2_CID_GAIN_BLUE,
+		.type		= V4L2_CTRL_TYPE_INTEGER,
+		.name		= "Gain, Blue",
+		.min		= MT9T001_GLOBAL_GAIN_MIN,
+		.max		= MT9T001_GLOBAL_GAIN_MAX,
+		.step		= 1,
+		.def		= MT9T001_GLOBAL_GAIN_MIN,
+		.flags		= 0,
+	},
+};
+
+/* -----------------------------------------------------------------------------
+ * V4L2 subdev internal operations
+ */
+
+static int mt9t001_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
+{
+	struct v4l2_mbus_framefmt *format;
+	struct v4l2_rect *crop;
+
+	crop = v4l2_subdev_get_try_crop(fh, 0);
+	crop->left = MT9T001_COLUMN_START_DEF;
+	crop->top = MT9T001_ROW_START_DEF;
+	crop->width = MT9T001_WINDOW_WIDTH_DEF + 1;
+	crop->height = MT9T001_WINDOW_HEIGHT_DEF + 1;
+
+	format = v4l2_subdev_get_try_format(fh, 0);
+	format->code = V4L2_MBUS_FMT_SGRBG10_1X10;
+	format->width = MT9T001_WINDOW_WIDTH_DEF + 1;
+	format->height = MT9T001_WINDOW_HEIGHT_DEF + 1;
+	format->field = V4L2_FIELD_NONE;
+	format->colorspace = V4L2_COLORSPACE_SRGB;
+
+	return 0;
+}
+
+static struct v4l2_subdev_video_ops mt9t001_subdev_video_ops = {
+	.s_stream = mt9t001_s_stream,
+};
+
+static struct v4l2_subdev_pad_ops mt9t001_subdev_pad_ops = {
+	.enum_mbus_code = mt9t001_enum_mbus_code,
+	.enum_frame_size = mt9t001_enum_frame_size,
+	.get_fmt = mt9t001_get_format,
+	.set_fmt = mt9t001_set_format,
+	.get_crop = mt9t001_get_crop,
+	.set_crop = mt9t001_set_crop,
+};
+
+static struct v4l2_subdev_ops mt9t001_subdev_ops = {
+	.video = &mt9t001_subdev_video_ops,
+	.pad = &mt9t001_subdev_pad_ops,
+};
+
+static struct v4l2_subdev_internal_ops mt9t001_subdev_internal_ops = {
+	.open = mt9t001_open,
+};
+
+static int mt9t001_video_probe(struct i2c_client *client)
+{
+	struct mt9t001_platform_data *pdata = client->dev.platform_data;
+	s32 data;
+	int ret;
+
+	dev_info(&client->dev, "Probing MT9T001 at address 0x%02x\n",
+		 client->addr);
+
+	/* Reset the chip and stop data read out */
+	ret = mt9t001_write(client, MT9T001_RESET, 1);
+	if (ret < 0)
+		return ret;
+
+	ret = mt9t001_write(client, MT9T001_RESET, 0);
+	if (ret < 0)
+		return ret;
+
+	ret  = mt9t001_write(client, MT9T001_OUTPUT_CONTROL, 0);
+	if (ret < 0)
+		return ret;
+
+	/* Configure the pixel clock polarity */
+	if (pdata->clk_pol) {
+		ret  = mt9t001_write(client, MT9T001_PIXEL_CLOCK,
+				     MT9T001_PIXEL_CLOCK_INVERT);
+		if (ret < 0)
+			return ret;
+	}
+
+	/* Read and check the sensor version */
+	data = mt9t001_read(client, MT9T001_CHIP_VERSION);
+	if (data != MT9T001_CHIP_ID) {
+		dev_err(&client->dev, "MT9T001 not detected, wrong version "
+			"0x%04x\n", data);
+		return -ENODEV;
+	}
+
+	dev_info(&client->dev, "MT9T001 detected at address 0x%02x\n",
+		 client->addr);
+
+	return ret;
+}
+
+static int mt9t001_probe(struct i2c_client *client,
+			 const struct i2c_device_id *did)
+{
+	struct mt9t001_platform_data *pdata = client->dev.platform_data;
+	struct mt9t001 *mt9t001;
+	unsigned int i;
+	int ret;
+
+	if (pdata == NULL) {
+		dev_err(&client->dev, "No platform data\n");
+		return -EINVAL;
+	}
+
+	if (!i2c_check_functionality(client->adapter,
+				     I2C_FUNC_SMBUS_WORD_DATA)) {
+		dev_warn(&client->adapter->dev,
+			 "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n");
+		return -EIO;
+	}
+
+	ret = mt9t001_video_probe(client);
+	if (ret < 0)
+		return ret;
+
+	mt9t001 = kzalloc(sizeof(*mt9t001), GFP_KERNEL);
+	if (!mt9t001)
+		return -ENOMEM;
+
+	v4l2_ctrl_handler_init(&mt9t001->ctrls, ARRAY_SIZE(mt9t001_ctrls) +
+						ARRAY_SIZE(mt9t001_gains) + 3);
+
+	v4l2_ctrl_new_std(&mt9t001->ctrls, &mt9t001_ctrl_ops,
+			  V4L2_CID_EXPOSURE, MT9T001_SHUTTER_WIDTH_MIN,
+			  MT9T001_SHUTTER_WIDTH_MAX, 1,
+			  MT9T001_SHUTTER_WIDTH_DEF);
+	v4l2_ctrl_new_std(&mt9t001->ctrls, &mt9t001_ctrl_ops,
+			  V4L2_CID_BLACK_LEVEL, 1, 1, 1, 1);
+	v4l2_ctrl_new_std(&mt9t001->ctrls, &mt9t001_ctrl_ops,
+			  V4L2_CID_PIXEL_RATE, pdata->ext_clk, pdata->ext_clk,
+			  1, pdata->ext_clk);
+
+	for (i = 0; i < ARRAY_SIZE(mt9t001_ctrls); ++i)
+		v4l2_ctrl_new_custom(&mt9t001->ctrls, &mt9t001_ctrls[i], NULL);
+
+	for (i = 0; i < ARRAY_SIZE(mt9t001_gains); ++i)
+		mt9t001->gains[i] = v4l2_ctrl_new_custom(&mt9t001->ctrls,
+			&mt9t001_gains[i], NULL);
+
+	v4l2_ctrl_cluster(ARRAY_SIZE(mt9t001_gains), mt9t001->gains);
+
+	mt9t001->subdev.ctrl_handler = &mt9t001->ctrls;
+
+	if (mt9t001->ctrls.error) {
+		printk(KERN_INFO "%s: control initialization error %d\n",
+		       __func__, mt9t001->ctrls.error);
+		ret = -EINVAL;
+		goto done;
+	}
+
+	mt9t001->crop.left = MT9T001_COLUMN_START_DEF;
+	mt9t001->crop.top = MT9T001_ROW_START_DEF;
+	mt9t001->crop.width = MT9T001_WINDOW_WIDTH_DEF + 1;
+	mt9t001->crop.height = MT9T001_WINDOW_HEIGHT_DEF + 1;
+
+	mt9t001->format.code = V4L2_MBUS_FMT_SGRBG10_1X10;
+	mt9t001->format.width = MT9T001_WINDOW_WIDTH_DEF + 1;
+	mt9t001->format.height = MT9T001_WINDOW_HEIGHT_DEF + 1;
+	mt9t001->format.field = V4L2_FIELD_NONE;
+	mt9t001->format.colorspace = V4L2_COLORSPACE_SRGB;
+
+	v4l2_i2c_subdev_init(&mt9t001->subdev, client, &mt9t001_subdev_ops);
+	mt9t001->subdev.internal_ops = &mt9t001_subdev_internal_ops;
+	mt9t001->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+	mt9t001->pad.flags = MEDIA_PAD_FL_SOURCE;
+	ret = media_entity_init(&mt9t001->subdev.entity, 1, &mt9t001->pad, 0);
+
+done:
+	if (ret < 0) {
+		v4l2_ctrl_handler_free(&mt9t001->ctrls);
+		media_entity_cleanup(&mt9t001->subdev.entity);
+		kfree(mt9t001);
+	}
+
+	return ret;
+}
+
+static int mt9t001_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *subdev = i2c_get_clientdata(client);
+	struct mt9t001 *mt9t001 = to_mt9t001(subdev);
+
+	v4l2_ctrl_handler_free(&mt9t001->ctrls);
+	v4l2_device_unregister_subdev(subdev);
+	media_entity_cleanup(&subdev->entity);
+	kfree(mt9t001);
+	return 0;
+}
+
+static const struct i2c_device_id mt9t001_id[] = {
+	{ "mt9t001", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, mt9t001_id);
+
+static struct i2c_driver mt9t001_driver = {
+	.driver = {
+		.name = "mt9t001",
+	},
+	.probe		= mt9t001_probe,
+	.remove		= mt9t001_remove,
+	.id_table	= mt9t001_id,
+};
+
+module_i2c_driver(mt9t001_driver);
+
+MODULE_DESCRIPTION("Aptina (Micron) MT9T001 Camera driver");
+MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/i2c/mt9v011.c b/drivers/media/i2c/mt9v011.c
new file mode 100644
index 0000000..6bf01ad
--- /dev/null
+++ b/drivers/media/i2c/mt9v011.c
@@ -0,0 +1,712 @@
+/*
+ * mt9v011 -Micron 1/4-Inch VGA Digital Image Sensor
+ *
+ * Copyright (c) 2009 Mauro Carvalho Chehab (mchehab@redhat.com)
+ * This code is placed under the terms of the GNU General Public License v2
+ */
+
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/videodev2.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <asm/div64.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/mt9v011.h>
+
+MODULE_DESCRIPTION("Micron mt9v011 sensor driver");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
+MODULE_LICENSE("GPL");
+
+static int debug;
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "Debug level (0-2)");
+
+#define R00_MT9V011_CHIP_VERSION	0x00
+#define R01_MT9V011_ROWSTART		0x01
+#define R02_MT9V011_COLSTART		0x02
+#define R03_MT9V011_HEIGHT		0x03
+#define R04_MT9V011_WIDTH		0x04
+#define R05_MT9V011_HBLANK		0x05
+#define R06_MT9V011_VBLANK		0x06
+#define R07_MT9V011_OUT_CTRL		0x07
+#define R09_MT9V011_SHUTTER_WIDTH	0x09
+#define R0A_MT9V011_CLK_SPEED		0x0a
+#define R0B_MT9V011_RESTART		0x0b
+#define R0C_MT9V011_SHUTTER_DELAY	0x0c
+#define R0D_MT9V011_RESET		0x0d
+#define R1E_MT9V011_DIGITAL_ZOOM	0x1e
+#define R20_MT9V011_READ_MODE		0x20
+#define R2B_MT9V011_GREEN_1_GAIN	0x2b
+#define R2C_MT9V011_BLUE_GAIN		0x2c
+#define R2D_MT9V011_RED_GAIN		0x2d
+#define R2E_MT9V011_GREEN_2_GAIN	0x2e
+#define R35_MT9V011_GLOBAL_GAIN		0x35
+#define RF1_MT9V011_CHIP_ENABLE		0xf1
+
+#define MT9V011_VERSION			0x8232
+#define MT9V011_REV_B_VERSION		0x8243
+
+/* supported controls */
+static struct v4l2_queryctrl mt9v011_qctrl[] = {
+	{
+		.id = V4L2_CID_GAIN,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "Gain",
+		.minimum = 0,
+		.maximum = (1 << 12) - 1 - 0x0020,
+		.step = 1,
+		.default_value = 0x0020,
+		.flags = 0,
+	}, {
+		.id = V4L2_CID_EXPOSURE,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "Exposure",
+		.minimum = 0,
+		.maximum = 2047,
+		.step = 1,
+		.default_value = 0x01fc,
+		.flags = 0,
+	}, {
+		.id = V4L2_CID_RED_BALANCE,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "Red Balance",
+		.minimum = -1 << 9,
+		.maximum = (1 << 9) - 1,
+		.step = 1,
+		.default_value = 0,
+		.flags = 0,
+	}, {
+		.id = V4L2_CID_BLUE_BALANCE,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.name = "Blue Balance",
+		.minimum = -1 << 9,
+		.maximum = (1 << 9) - 1,
+		.step = 1,
+		.default_value = 0,
+		.flags = 0,
+	}, {
+		.id      = V4L2_CID_HFLIP,
+		.type    = V4L2_CTRL_TYPE_BOOLEAN,
+		.name    = "Mirror",
+		.minimum = 0,
+		.maximum = 1,
+		.step    = 1,
+		.default_value = 0,
+		.flags = 0,
+	}, {
+		.id      = V4L2_CID_VFLIP,
+		.type    = V4L2_CTRL_TYPE_BOOLEAN,
+		.name    = "Vflip",
+		.minimum = 0,
+		.maximum = 1,
+		.step    = 1,
+		.default_value = 0,
+		.flags = 0,
+	}, {
+	}
+};
+
+struct mt9v011 {
+	struct v4l2_subdev sd;
+	unsigned width, height;
+	unsigned xtal;
+	unsigned hflip:1;
+	unsigned vflip:1;
+
+	u16 global_gain, exposure;
+	s16 red_bal, blue_bal;
+};
+
+static inline struct mt9v011 *to_mt9v011(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct mt9v011, sd);
+}
+
+static int mt9v011_read(struct v4l2_subdev *sd, unsigned char addr)
+{
+	struct i2c_client *c = v4l2_get_subdevdata(sd);
+	__be16 buffer;
+	int rc, val;
+
+	rc = i2c_master_send(c, &addr, 1);
+	if (rc != 1)
+		v4l2_dbg(0, debug, sd,
+			 "i2c i/o error: rc == %d (should be 1)\n", rc);
+
+	msleep(10);
+
+	rc = i2c_master_recv(c, (char *)&buffer, 2);
+	if (rc != 2)
+		v4l2_dbg(0, debug, sd,
+			 "i2c i/o error: rc == %d (should be 2)\n", rc);
+
+	val = be16_to_cpu(buffer);
+
+	v4l2_dbg(2, debug, sd, "mt9v011: read 0x%02x = 0x%04x\n", addr, val);
+
+	return val;
+}
+
+static void mt9v011_write(struct v4l2_subdev *sd, unsigned char addr,
+				 u16 value)
+{
+	struct i2c_client *c = v4l2_get_subdevdata(sd);
+	unsigned char buffer[3];
+	int rc;
+
+	buffer[0] = addr;
+	buffer[1] = value >> 8;
+	buffer[2] = value & 0xff;
+
+	v4l2_dbg(2, debug, sd,
+		 "mt9v011: writing 0x%02x 0x%04x\n", buffer[0], value);
+	rc = i2c_master_send(c, buffer, 3);
+	if (rc != 3)
+		v4l2_dbg(0, debug, sd,
+			 "i2c i/o error: rc == %d (should be 3)\n", rc);
+}
+
+
+struct i2c_reg_value {
+	unsigned char reg;
+	u16           value;
+};
+
+/*
+ * Values used at the original driver
+ * Some values are marked as Reserved at the datasheet
+ */
+static const struct i2c_reg_value mt9v011_init_default[] = {
+		{ R0D_MT9V011_RESET, 0x0001 },
+		{ R0D_MT9V011_RESET, 0x0000 },
+
+		{ R0C_MT9V011_SHUTTER_DELAY, 0x0000 },
+		{ R09_MT9V011_SHUTTER_WIDTH, 0x1fc },
+
+		{ R0A_MT9V011_CLK_SPEED, 0x0000 },
+		{ R1E_MT9V011_DIGITAL_ZOOM,  0x0000 },
+
+		{ R07_MT9V011_OUT_CTRL, 0x0002 },	/* chip enable */
+};
+
+
+static u16 calc_mt9v011_gain(s16 lineargain)
+{
+
+	u16 digitalgain = 0;
+	u16 analogmult = 0;
+	u16 analoginit = 0;
+
+	if (lineargain < 0)
+		lineargain = 0;
+
+	/* recommended minimum */
+	lineargain += 0x0020;
+
+	if (lineargain > 2047)
+		lineargain = 2047;
+
+	if (lineargain > 1023) {
+		digitalgain = 3;
+		analogmult = 3;
+		analoginit = lineargain / 16;
+	} else if (lineargain > 511) {
+		digitalgain = 1;
+		analogmult = 3;
+		analoginit = lineargain / 8;
+	} else if (lineargain > 255) {
+		analogmult = 3;
+		analoginit = lineargain / 4;
+	} else if (lineargain > 127) {
+		analogmult = 1;
+		analoginit = lineargain / 2;
+	} else
+		analoginit = lineargain;
+
+	return analoginit + (analogmult << 7) + (digitalgain << 9);
+
+}
+
+static void set_balance(struct v4l2_subdev *sd)
+{
+	struct mt9v011 *core = to_mt9v011(sd);
+	u16 green_gain, blue_gain, red_gain;
+	u16 exposure;
+	s16 bal;
+
+	exposure = core->exposure;
+
+	green_gain = calc_mt9v011_gain(core->global_gain);
+
+	bal = core->global_gain;
+	bal += (core->blue_bal * core->global_gain / (1 << 7));
+	blue_gain = calc_mt9v011_gain(bal);
+
+	bal = core->global_gain;
+	bal += (core->red_bal * core->global_gain / (1 << 7));
+	red_gain = calc_mt9v011_gain(bal);
+
+	mt9v011_write(sd, R2B_MT9V011_GREEN_1_GAIN, green_gain);
+	mt9v011_write(sd, R2E_MT9V011_GREEN_2_GAIN, green_gain);
+	mt9v011_write(sd, R2C_MT9V011_BLUE_GAIN, blue_gain);
+	mt9v011_write(sd, R2D_MT9V011_RED_GAIN, red_gain);
+	mt9v011_write(sd, R09_MT9V011_SHUTTER_WIDTH, exposure);
+}
+
+static void calc_fps(struct v4l2_subdev *sd, u32 *numerator, u32 *denominator)
+{
+	struct mt9v011 *core = to_mt9v011(sd);
+	unsigned height, width, hblank, vblank, speed;
+	unsigned row_time, t_time;
+	u64 frames_per_ms;
+	unsigned tmp;
+
+	height = mt9v011_read(sd, R03_MT9V011_HEIGHT);
+	width = mt9v011_read(sd, R04_MT9V011_WIDTH);
+	hblank = mt9v011_read(sd, R05_MT9V011_HBLANK);
+	vblank = mt9v011_read(sd, R06_MT9V011_VBLANK);
+	speed = mt9v011_read(sd, R0A_MT9V011_CLK_SPEED);
+
+	row_time = (width + 113 + hblank) * (speed + 2);
+	t_time = row_time * (height + vblank + 1);
+
+	frames_per_ms = core->xtal * 1000l;
+	do_div(frames_per_ms, t_time);
+	tmp = frames_per_ms;
+
+	v4l2_dbg(1, debug, sd, "Programmed to %u.%03u fps (%d pixel clcks)\n",
+		tmp / 1000, tmp % 1000, t_time);
+
+	if (numerator && denominator) {
+		*numerator = 1000;
+		*denominator = (u32)frames_per_ms;
+	}
+}
+
+static u16 calc_speed(struct v4l2_subdev *sd, u32 numerator, u32 denominator)
+{
+	struct mt9v011 *core = to_mt9v011(sd);
+	unsigned height, width, hblank, vblank;
+	unsigned row_time, line_time;
+	u64 t_time, speed;
+
+	/* Avoid bogus calculus */
+	if (!numerator || !denominator)
+		return 0;
+
+	height = mt9v011_read(sd, R03_MT9V011_HEIGHT);
+	width = mt9v011_read(sd, R04_MT9V011_WIDTH);
+	hblank = mt9v011_read(sd, R05_MT9V011_HBLANK);
+	vblank = mt9v011_read(sd, R06_MT9V011_VBLANK);
+
+	row_time = width + 113 + hblank;
+	line_time = height + vblank + 1;
+
+	t_time = core->xtal * ((u64)numerator);
+	/* round to the closest value */
+	t_time += denominator / 2;
+	do_div(t_time, denominator);
+
+	speed = t_time;
+	do_div(speed, row_time * line_time);
+
+	/* Avoid having a negative value for speed */
+	if (speed < 2)
+		speed = 0;
+	else
+		speed -= 2;
+
+	/* Avoid speed overflow */
+	if (speed > 15)
+		return 15;
+
+	return (u16)speed;
+}
+
+static void set_res(struct v4l2_subdev *sd)
+{
+	struct mt9v011 *core = to_mt9v011(sd);
+	unsigned vstart, hstart;
+
+	/*
+	 * The mt9v011 doesn't have scaling. So, in order to select the desired
+	 * resolution, we're cropping at the middle of the sensor.
+	 * hblank and vblank should be adjusted, in order to warrant that
+	 * we'll preserve the line timings for 30 fps, no matter what resolution
+	 * is selected.
+	 * NOTE: datasheet says that width (and height) should be filled with
+	 * width-1. However, this doesn't work, since one pixel per line will
+	 * be missing.
+	 */
+
+	hstart = 20 + (640 - core->width) / 2;
+	mt9v011_write(sd, R02_MT9V011_COLSTART, hstart);
+	mt9v011_write(sd, R04_MT9V011_WIDTH, core->width);
+	mt9v011_write(sd, R05_MT9V011_HBLANK, 771 - core->width);
+
+	vstart = 8 + (480 - core->height) / 2;
+	mt9v011_write(sd, R01_MT9V011_ROWSTART, vstart);
+	mt9v011_write(sd, R03_MT9V011_HEIGHT, core->height);
+	mt9v011_write(sd, R06_MT9V011_VBLANK, 508 - core->height);
+
+	calc_fps(sd, NULL, NULL);
+};
+
+static void set_read_mode(struct v4l2_subdev *sd)
+{
+	struct mt9v011 *core = to_mt9v011(sd);
+	unsigned mode = 0x1000;
+
+	if (core->hflip)
+		mode |= 0x4000;
+
+	if (core->vflip)
+		mode |= 0x8000;
+
+	mt9v011_write(sd, R20_MT9V011_READ_MODE, mode);
+}
+
+static int mt9v011_reset(struct v4l2_subdev *sd, u32 val)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(mt9v011_init_default); i++)
+		mt9v011_write(sd, mt9v011_init_default[i].reg,
+			       mt9v011_init_default[i].value);
+
+	set_balance(sd);
+	set_res(sd);
+	set_read_mode(sd);
+
+	return 0;
+};
+
+static int mt9v011_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+	struct mt9v011 *core = to_mt9v011(sd);
+
+	v4l2_dbg(1, debug, sd, "g_ctrl called\n");
+
+	switch (ctrl->id) {
+	case V4L2_CID_GAIN:
+		ctrl->value = core->global_gain;
+		return 0;
+	case V4L2_CID_EXPOSURE:
+		ctrl->value = core->exposure;
+		return 0;
+	case V4L2_CID_RED_BALANCE:
+		ctrl->value = core->red_bal;
+		return 0;
+	case V4L2_CID_BLUE_BALANCE:
+		ctrl->value = core->blue_bal;
+		return 0;
+	case V4L2_CID_HFLIP:
+		ctrl->value = core->hflip ? 1 : 0;
+		return 0;
+	case V4L2_CID_VFLIP:
+		ctrl->value = core->vflip ? 1 : 0;
+		return 0;
+	}
+	return -EINVAL;
+}
+
+static int mt9v011_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
+{
+	int i;
+
+	v4l2_dbg(1, debug, sd, "queryctrl called\n");
+
+	for (i = 0; i < ARRAY_SIZE(mt9v011_qctrl); i++)
+		if (qc->id && qc->id == mt9v011_qctrl[i].id) {
+			memcpy(qc, &(mt9v011_qctrl[i]),
+			       sizeof(*qc));
+			return 0;
+		}
+
+	return -EINVAL;
+}
+
+
+static int mt9v011_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+	struct mt9v011 *core = to_mt9v011(sd);
+	u8 i, n;
+	n = ARRAY_SIZE(mt9v011_qctrl);
+
+	for (i = 0; i < n; i++) {
+		if (ctrl->id != mt9v011_qctrl[i].id)
+			continue;
+		if (ctrl->value < mt9v011_qctrl[i].minimum ||
+		    ctrl->value > mt9v011_qctrl[i].maximum)
+			return -ERANGE;
+		v4l2_dbg(1, debug, sd, "s_ctrl: id=%d, value=%d\n",
+					ctrl->id, ctrl->value);
+		break;
+	}
+
+	switch (ctrl->id) {
+	case V4L2_CID_GAIN:
+		core->global_gain = ctrl->value;
+		break;
+	case V4L2_CID_EXPOSURE:
+		core->exposure = ctrl->value;
+		break;
+	case V4L2_CID_RED_BALANCE:
+		core->red_bal = ctrl->value;
+		break;
+	case V4L2_CID_BLUE_BALANCE:
+		core->blue_bal = ctrl->value;
+		break;
+	case V4L2_CID_HFLIP:
+		core->hflip = ctrl->value;
+		set_read_mode(sd);
+		return 0;
+	case V4L2_CID_VFLIP:
+		core->vflip = ctrl->value;
+		set_read_mode(sd);
+		return 0;
+	default:
+		return -EINVAL;
+	}
+
+	set_balance(sd);
+
+	return 0;
+}
+
+static int mt9v011_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index,
+					enum v4l2_mbus_pixelcode *code)
+{
+	if (index > 0)
+		return -EINVAL;
+
+	*code = V4L2_MBUS_FMT_SGRBG8_1X8;
+	return 0;
+}
+
+static int mt9v011_try_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
+{
+	if (fmt->code != V4L2_MBUS_FMT_SGRBG8_1X8)
+		return -EINVAL;
+
+	v4l_bound_align_image(&fmt->width, 48, 639, 1,
+			      &fmt->height, 32, 480, 1, 0);
+	fmt->field = V4L2_FIELD_NONE;
+	fmt->colorspace = V4L2_COLORSPACE_SRGB;
+
+	return 0;
+}
+
+static int mt9v011_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms)
+{
+	struct v4l2_captureparm *cp = &parms->parm.capture;
+
+	if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
+	memset(cp, 0, sizeof(struct v4l2_captureparm));
+	cp->capability = V4L2_CAP_TIMEPERFRAME;
+	calc_fps(sd,
+		 &cp->timeperframe.numerator,
+		 &cp->timeperframe.denominator);
+
+	return 0;
+}
+
+static int mt9v011_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms)
+{
+	struct v4l2_captureparm *cp = &parms->parm.capture;
+	struct v4l2_fract *tpf = &cp->timeperframe;
+	u16 speed;
+
+	if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+	if (cp->extendedmode != 0)
+		return -EINVAL;
+
+	speed = calc_speed(sd, tpf->numerator, tpf->denominator);
+
+	mt9v011_write(sd, R0A_MT9V011_CLK_SPEED, speed);
+	v4l2_dbg(1, debug, sd, "Setting speed to %d\n", speed);
+
+	/* Recalculate and update fps info */
+	calc_fps(sd, &tpf->numerator, &tpf->denominator);
+
+	return 0;
+}
+
+static int mt9v011_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
+{
+	struct mt9v011 *core = to_mt9v011(sd);
+	int rc;
+
+	rc = mt9v011_try_mbus_fmt(sd, fmt);
+	if (rc < 0)
+		return -EINVAL;
+
+	core->width = fmt->width;
+	core->height = fmt->height;
+
+	set_res(sd);
+
+	return 0;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int mt9v011_g_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;
+
+	reg->val = mt9v011_read(sd, reg->reg & 0xff);
+	reg->size = 2;
+
+	return 0;
+}
+
+static int mt9v011_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;
+
+	mt9v011_write(sd, reg->reg & 0xff, reg->val & 0xffff);
+
+	return 0;
+}
+#endif
+
+static int mt9v011_g_chip_ident(struct v4l2_subdev *sd,
+				struct v4l2_dbg_chip_ident *chip)
+{
+	u16 version;
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	version = mt9v011_read(sd, R00_MT9V011_CHIP_VERSION);
+
+	return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_MT9V011,
+					  version);
+}
+
+static const struct v4l2_subdev_core_ops mt9v011_core_ops = {
+	.queryctrl = mt9v011_queryctrl,
+	.g_ctrl = mt9v011_g_ctrl,
+	.s_ctrl = mt9v011_s_ctrl,
+	.reset = mt9v011_reset,
+	.g_chip_ident = mt9v011_g_chip_ident,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.g_register = mt9v011_g_register,
+	.s_register = mt9v011_s_register,
+#endif
+};
+
+static const struct v4l2_subdev_video_ops mt9v011_video_ops = {
+	.enum_mbus_fmt = mt9v011_enum_mbus_fmt,
+	.try_mbus_fmt = mt9v011_try_mbus_fmt,
+	.s_mbus_fmt = mt9v011_s_mbus_fmt,
+	.g_parm = mt9v011_g_parm,
+	.s_parm = mt9v011_s_parm,
+};
+
+static const struct v4l2_subdev_ops mt9v011_ops = {
+	.core  = &mt9v011_core_ops,
+	.video = &mt9v011_video_ops,
+};
+
+
+/****************************************************************************
+			I2C Client & Driver
+ ****************************************************************************/
+
+static int mt9v011_probe(struct i2c_client *c,
+			 const struct i2c_device_id *id)
+{
+	u16 version;
+	struct mt9v011 *core;
+	struct v4l2_subdev *sd;
+
+	/* Check if the adapter supports the needed features */
+	if (!i2c_check_functionality(c->adapter,
+	     I2C_FUNC_SMBUS_READ_BYTE | I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
+		return -EIO;
+
+	core = kzalloc(sizeof(struct mt9v011), GFP_KERNEL);
+	if (!core)
+		return -ENOMEM;
+
+	sd = &core->sd;
+	v4l2_i2c_subdev_init(sd, c, &mt9v011_ops);
+
+	/* Check if the sensor is really a MT9V011 */
+	version = mt9v011_read(sd, R00_MT9V011_CHIP_VERSION);
+	if ((version != MT9V011_VERSION) &&
+	    (version != MT9V011_REV_B_VERSION)) {
+		v4l2_info(sd, "*** unknown micron chip detected (0x%04x).\n",
+			  version);
+		kfree(core);
+		return -EINVAL;
+	}
+
+	core->global_gain = 0x0024;
+	core->exposure = 0x01fc;
+	core->width  = 640;
+	core->height = 480;
+	core->xtal = 27000000;	/* Hz */
+
+	if (c->dev.platform_data) {
+		struct mt9v011_platform_data *pdata = c->dev.platform_data;
+
+		core->xtal = pdata->xtal;
+		v4l2_dbg(1, debug, sd, "xtal set to %d.%03d MHz\n",
+			core->xtal / 1000000, (core->xtal / 1000) % 1000);
+	}
+
+	v4l_info(c, "chip found @ 0x%02x (%s - chip version 0x%04x)\n",
+		 c->addr << 1, c->adapter->name, version);
+
+	return 0;
+}
+
+static int mt9v011_remove(struct i2c_client *c)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(c);
+
+	v4l2_dbg(1, debug, sd,
+		"mt9v011.c: removing mt9v011 adapter on address 0x%x\n",
+		c->addr << 1);
+
+	v4l2_device_unregister_subdev(sd);
+	kfree(to_mt9v011(sd));
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static const struct i2c_device_id mt9v011_id[] = {
+	{ "mt9v011", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, mt9v011_id);
+
+static struct i2c_driver mt9v011_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "mt9v011",
+	},
+	.probe		= mt9v011_probe,
+	.remove		= mt9v011_remove,
+	.id_table	= mt9v011_id,
+};
+
+module_i2c_driver(mt9v011_driver);
diff --git a/drivers/media/i2c/mt9v032.c b/drivers/media/i2c/mt9v032.c
new file mode 100644
index 0000000..e217740
--- /dev/null
+++ b/drivers/media/i2c/mt9v032.c
@@ -0,0 +1,853 @@
+/*
+ * Driver for MT9V032 CMOS Image Sensor from Micron
+ *
+ * Copyright (C) 2010, Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * Based on the MT9M001 driver,
+ *
+ * Copyright (C) 2008, Guennadi Liakhovetski <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 version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/log2.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/videodev2.h>
+#include <linux/v4l2-mediabus.h>
+#include <linux/module.h>
+
+#include <media/mt9v032.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+
+#define MT9V032_PIXEL_ARRAY_HEIGHT			492
+#define MT9V032_PIXEL_ARRAY_WIDTH			782
+
+#define MT9V032_SYSCLK_FREQ_DEF				26600000
+
+#define MT9V032_CHIP_VERSION				0x00
+#define		MT9V032_CHIP_ID_REV1			0x1311
+#define		MT9V032_CHIP_ID_REV3			0x1313
+#define MT9V032_COLUMN_START				0x01
+#define		MT9V032_COLUMN_START_MIN		1
+#define		MT9V032_COLUMN_START_DEF		1
+#define		MT9V032_COLUMN_START_MAX		752
+#define MT9V032_ROW_START				0x02
+#define		MT9V032_ROW_START_MIN			4
+#define		MT9V032_ROW_START_DEF			5
+#define		MT9V032_ROW_START_MAX			482
+#define MT9V032_WINDOW_HEIGHT				0x03
+#define		MT9V032_WINDOW_HEIGHT_MIN		1
+#define		MT9V032_WINDOW_HEIGHT_DEF		480
+#define		MT9V032_WINDOW_HEIGHT_MAX		480
+#define MT9V032_WINDOW_WIDTH				0x04
+#define		MT9V032_WINDOW_WIDTH_MIN		1
+#define		MT9V032_WINDOW_WIDTH_DEF		752
+#define		MT9V032_WINDOW_WIDTH_MAX		752
+#define MT9V032_HORIZONTAL_BLANKING			0x05
+#define		MT9V032_HORIZONTAL_BLANKING_MIN		43
+#define		MT9V032_HORIZONTAL_BLANKING_DEF		94
+#define		MT9V032_HORIZONTAL_BLANKING_MAX		1023
+#define MT9V032_VERTICAL_BLANKING			0x06
+#define		MT9V032_VERTICAL_BLANKING_MIN		4
+#define		MT9V032_VERTICAL_BLANKING_DEF		45
+#define		MT9V032_VERTICAL_BLANKING_MAX		3000
+#define MT9V032_CHIP_CONTROL				0x07
+#define		MT9V032_CHIP_CONTROL_MASTER_MODE	(1 << 3)
+#define		MT9V032_CHIP_CONTROL_DOUT_ENABLE	(1 << 7)
+#define		MT9V032_CHIP_CONTROL_SEQUENTIAL		(1 << 8)
+#define MT9V032_SHUTTER_WIDTH1				0x08
+#define MT9V032_SHUTTER_WIDTH2				0x09
+#define MT9V032_SHUTTER_WIDTH_CONTROL			0x0a
+#define MT9V032_TOTAL_SHUTTER_WIDTH			0x0b
+#define		MT9V032_TOTAL_SHUTTER_WIDTH_MIN		1
+#define		MT9V032_TOTAL_SHUTTER_WIDTH_DEF		480
+#define		MT9V032_TOTAL_SHUTTER_WIDTH_MAX		32767
+#define MT9V032_RESET					0x0c
+#define MT9V032_READ_MODE				0x0d
+#define		MT9V032_READ_MODE_ROW_BIN_MASK		(3 << 0)
+#define		MT9V032_READ_MODE_ROW_BIN_SHIFT		0
+#define		MT9V032_READ_MODE_COLUMN_BIN_MASK	(3 << 2)
+#define		MT9V032_READ_MODE_COLUMN_BIN_SHIFT	2
+#define		MT9V032_READ_MODE_ROW_FLIP		(1 << 4)
+#define		MT9V032_READ_MODE_COLUMN_FLIP		(1 << 5)
+#define		MT9V032_READ_MODE_DARK_COLUMNS		(1 << 6)
+#define		MT9V032_READ_MODE_DARK_ROWS		(1 << 7)
+#define MT9V032_PIXEL_OPERATION_MODE			0x0f
+#define		MT9V032_PIXEL_OPERATION_MODE_COLOR	(1 << 2)
+#define		MT9V032_PIXEL_OPERATION_MODE_HDR	(1 << 6)
+#define MT9V032_ANALOG_GAIN				0x35
+#define		MT9V032_ANALOG_GAIN_MIN			16
+#define		MT9V032_ANALOG_GAIN_DEF			16
+#define		MT9V032_ANALOG_GAIN_MAX			64
+#define MT9V032_MAX_ANALOG_GAIN				0x36
+#define		MT9V032_MAX_ANALOG_GAIN_MAX		127
+#define MT9V032_FRAME_DARK_AVERAGE			0x42
+#define MT9V032_DARK_AVG_THRESH				0x46
+#define		MT9V032_DARK_AVG_LOW_THRESH_MASK	(255 << 0)
+#define		MT9V032_DARK_AVG_LOW_THRESH_SHIFT	0
+#define		MT9V032_DARK_AVG_HIGH_THRESH_MASK	(255 << 8)
+#define		MT9V032_DARK_AVG_HIGH_THRESH_SHIFT	8
+#define MT9V032_ROW_NOISE_CORR_CONTROL			0x70
+#define		MT9V032_ROW_NOISE_CORR_ENABLE		(1 << 5)
+#define		MT9V032_ROW_NOISE_CORR_USE_BLK_AVG	(1 << 7)
+#define MT9V032_PIXEL_CLOCK				0x74
+#define		MT9V032_PIXEL_CLOCK_INV_LINE		(1 << 0)
+#define		MT9V032_PIXEL_CLOCK_INV_FRAME		(1 << 1)
+#define		MT9V032_PIXEL_CLOCK_XOR_LINE		(1 << 2)
+#define		MT9V032_PIXEL_CLOCK_CONT_LINE		(1 << 3)
+#define		MT9V032_PIXEL_CLOCK_INV_PXL_CLK		(1 << 4)
+#define MT9V032_TEST_PATTERN				0x7f
+#define		MT9V032_TEST_PATTERN_DATA_MASK		(1023 << 0)
+#define		MT9V032_TEST_PATTERN_DATA_SHIFT		0
+#define		MT9V032_TEST_PATTERN_USE_DATA		(1 << 10)
+#define		MT9V032_TEST_PATTERN_GRAY_MASK		(3 << 11)
+#define		MT9V032_TEST_PATTERN_GRAY_NONE		(0 << 11)
+#define		MT9V032_TEST_PATTERN_GRAY_VERTICAL	(1 << 11)
+#define		MT9V032_TEST_PATTERN_GRAY_HORIZONTAL	(2 << 11)
+#define		MT9V032_TEST_PATTERN_GRAY_DIAGONAL	(3 << 11)
+#define		MT9V032_TEST_PATTERN_ENABLE		(1 << 13)
+#define		MT9V032_TEST_PATTERN_FLIP		(1 << 14)
+#define MT9V032_AEC_AGC_ENABLE				0xaf
+#define		MT9V032_AEC_ENABLE			(1 << 0)
+#define		MT9V032_AGC_ENABLE			(1 << 1)
+#define MT9V032_THERMAL_INFO				0xc1
+
+struct mt9v032 {
+	struct v4l2_subdev subdev;
+	struct media_pad pad;
+
+	struct v4l2_mbus_framefmt format;
+	struct v4l2_rect crop;
+
+	struct v4l2_ctrl_handler ctrls;
+	struct {
+		struct v4l2_ctrl *link_freq;
+		struct v4l2_ctrl *pixel_rate;
+	};
+
+	struct mutex power_lock;
+	int power_count;
+
+	struct mt9v032_platform_data *pdata;
+
+	u32 sysclk;
+	u16 chip_control;
+	u16 aec_agc;
+	u16 hblank;
+};
+
+static struct mt9v032 *to_mt9v032(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct mt9v032, subdev);
+}
+
+static int mt9v032_read(struct i2c_client *client, const u8 reg)
+{
+	s32 data = i2c_smbus_read_word_swapped(client, reg);
+	dev_dbg(&client->dev, "%s: read 0x%04x from 0x%02x\n", __func__,
+		data, reg);
+	return data;
+}
+
+static int mt9v032_write(struct i2c_client *client, const u8 reg,
+			 const u16 data)
+{
+	dev_dbg(&client->dev, "%s: writing 0x%04x to 0x%02x\n", __func__,
+		data, reg);
+	return i2c_smbus_write_word_swapped(client, reg, data);
+}
+
+static int mt9v032_set_chip_control(struct mt9v032 *mt9v032, u16 clear, u16 set)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev);
+	u16 value = (mt9v032->chip_control & ~clear) | set;
+	int ret;
+
+	ret = mt9v032_write(client, MT9V032_CHIP_CONTROL, value);
+	if (ret < 0)
+		return ret;
+
+	mt9v032->chip_control = value;
+	return 0;
+}
+
+static int
+mt9v032_update_aec_agc(struct mt9v032 *mt9v032, u16 which, int enable)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev);
+	u16 value = mt9v032->aec_agc;
+	int ret;
+
+	if (enable)
+		value |= which;
+	else
+		value &= ~which;
+
+	ret = mt9v032_write(client, MT9V032_AEC_AGC_ENABLE, value);
+	if (ret < 0)
+		return ret;
+
+	mt9v032->aec_agc = value;
+	return 0;
+}
+
+static int
+mt9v032_update_hblank(struct mt9v032 *mt9v032)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev);
+	struct v4l2_rect *crop = &mt9v032->crop;
+
+	return mt9v032_write(client, MT9V032_HORIZONTAL_BLANKING,
+			     max_t(s32, mt9v032->hblank, 660 - crop->width));
+}
+
+#define EXT_CLK		25000000
+
+static int mt9v032_power_on(struct mt9v032 *mt9v032)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev);
+	int ret;
+
+	if (mt9v032->pdata->set_clock) {
+		mt9v032->pdata->set_clock(&mt9v032->subdev, mt9v032->sysclk);
+		udelay(1);
+	}
+
+	/* Reset the chip and stop data read out */
+	ret = mt9v032_write(client, MT9V032_RESET, 1);
+	if (ret < 0)
+		return ret;
+
+	ret = mt9v032_write(client, MT9V032_RESET, 0);
+	if (ret < 0)
+		return ret;
+
+	return mt9v032_write(client, MT9V032_CHIP_CONTROL, 0);
+}
+
+static void mt9v032_power_off(struct mt9v032 *mt9v032)
+{
+	if (mt9v032->pdata->set_clock)
+		mt9v032->pdata->set_clock(&mt9v032->subdev, 0);
+}
+
+static int __mt9v032_set_power(struct mt9v032 *mt9v032, bool on)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev);
+	int ret;
+
+	if (!on) {
+		mt9v032_power_off(mt9v032);
+		return 0;
+	}
+
+	ret = mt9v032_power_on(mt9v032);
+	if (ret < 0)
+		return ret;
+
+	/* Configure the pixel clock polarity */
+	if (mt9v032->pdata && mt9v032->pdata->clk_pol) {
+		ret = mt9v032_write(client, MT9V032_PIXEL_CLOCK,
+				MT9V032_PIXEL_CLOCK_INV_PXL_CLK);
+		if (ret < 0)
+			return ret;
+	}
+
+	/* Disable the noise correction algorithm and restore the controls. */
+	ret = mt9v032_write(client, MT9V032_ROW_NOISE_CORR_CONTROL, 0);
+	if (ret < 0)
+		return ret;
+
+	return v4l2_ctrl_handler_setup(&mt9v032->ctrls);
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 subdev video operations
+ */
+
+static struct v4l2_mbus_framefmt *
+__mt9v032_get_pad_format(struct mt9v032 *mt9v032, struct v4l2_subdev_fh *fh,
+			 unsigned int pad, enum v4l2_subdev_format_whence which)
+{
+	switch (which) {
+	case V4L2_SUBDEV_FORMAT_TRY:
+		return v4l2_subdev_get_try_format(fh, pad);
+	case V4L2_SUBDEV_FORMAT_ACTIVE:
+		return &mt9v032->format;
+	default:
+		return NULL;
+	}
+}
+
+static struct v4l2_rect *
+__mt9v032_get_pad_crop(struct mt9v032 *mt9v032, struct v4l2_subdev_fh *fh,
+		       unsigned int pad, enum v4l2_subdev_format_whence which)
+{
+	switch (which) {
+	case V4L2_SUBDEV_FORMAT_TRY:
+		return v4l2_subdev_get_try_crop(fh, pad);
+	case V4L2_SUBDEV_FORMAT_ACTIVE:
+		return &mt9v032->crop;
+	default:
+		return NULL;
+	}
+}
+
+static int mt9v032_s_stream(struct v4l2_subdev *subdev, int enable)
+{
+	const u16 mode = MT9V032_CHIP_CONTROL_MASTER_MODE
+		       | MT9V032_CHIP_CONTROL_DOUT_ENABLE
+		       | MT9V032_CHIP_CONTROL_SEQUENTIAL;
+	struct i2c_client *client = v4l2_get_subdevdata(subdev);
+	struct mt9v032 *mt9v032 = to_mt9v032(subdev);
+	struct v4l2_mbus_framefmt *format = &mt9v032->format;
+	struct v4l2_rect *crop = &mt9v032->crop;
+	unsigned int hratio;
+	unsigned int vratio;
+	int ret;
+
+	if (!enable)
+		return mt9v032_set_chip_control(mt9v032, mode, 0);
+
+	/* Configure the window size and row/column bin */
+	hratio = DIV_ROUND_CLOSEST(crop->width, format->width);
+	vratio = DIV_ROUND_CLOSEST(crop->height, format->height);
+
+	ret = mt9v032_write(client, MT9V032_READ_MODE,
+		    (hratio - 1) << MT9V032_READ_MODE_ROW_BIN_SHIFT |
+		    (vratio - 1) << MT9V032_READ_MODE_COLUMN_BIN_SHIFT);
+	if (ret < 0)
+		return ret;
+
+	ret = mt9v032_write(client, MT9V032_COLUMN_START, crop->left);
+	if (ret < 0)
+		return ret;
+
+	ret = mt9v032_write(client, MT9V032_ROW_START, crop->top);
+	if (ret < 0)
+		return ret;
+
+	ret = mt9v032_write(client, MT9V032_WINDOW_WIDTH, crop->width);
+	if (ret < 0)
+		return ret;
+
+	ret = mt9v032_write(client, MT9V032_WINDOW_HEIGHT, crop->height);
+	if (ret < 0)
+		return ret;
+
+	ret = mt9v032_update_hblank(mt9v032);
+	if (ret < 0)
+		return ret;
+
+	/* Switch to master "normal" mode */
+	return mt9v032_set_chip_control(mt9v032, 0, mode);
+}
+
+static int mt9v032_enum_mbus_code(struct v4l2_subdev *subdev,
+				  struct v4l2_subdev_fh *fh,
+				  struct v4l2_subdev_mbus_code_enum *code)
+{
+	if (code->index > 0)
+		return -EINVAL;
+
+	code->code = V4L2_MBUS_FMT_SGRBG10_1X10;
+	return 0;
+}
+
+static int mt9v032_enum_frame_size(struct v4l2_subdev *subdev,
+				   struct v4l2_subdev_fh *fh,
+				   struct v4l2_subdev_frame_size_enum *fse)
+{
+	if (fse->index >= 8 || fse->code != V4L2_MBUS_FMT_SGRBG10_1X10)
+		return -EINVAL;
+
+	fse->min_width = MT9V032_WINDOW_WIDTH_DEF / fse->index;
+	fse->max_width = fse->min_width;
+	fse->min_height = MT9V032_WINDOW_HEIGHT_DEF / fse->index;
+	fse->max_height = fse->min_height;
+
+	return 0;
+}
+
+static int mt9v032_get_format(struct v4l2_subdev *subdev,
+			      struct v4l2_subdev_fh *fh,
+			      struct v4l2_subdev_format *format)
+{
+	struct mt9v032 *mt9v032 = to_mt9v032(subdev);
+
+	format->format = *__mt9v032_get_pad_format(mt9v032, fh, format->pad,
+						   format->which);
+	return 0;
+}
+
+static void mt9v032_configure_pixel_rate(struct mt9v032 *mt9v032,
+					 unsigned int hratio)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev);
+	int ret;
+
+	ret = v4l2_ctrl_s_ctrl_int64(mt9v032->pixel_rate,
+				     mt9v032->sysclk / hratio);
+	if (ret < 0)
+		dev_warn(&client->dev, "failed to set pixel rate (%d)\n", ret);
+}
+
+static int mt9v032_set_format(struct v4l2_subdev *subdev,
+			      struct v4l2_subdev_fh *fh,
+			      struct v4l2_subdev_format *format)
+{
+	struct mt9v032 *mt9v032 = to_mt9v032(subdev);
+	struct v4l2_mbus_framefmt *__format;
+	struct v4l2_rect *__crop;
+	unsigned int width;
+	unsigned int height;
+	unsigned int hratio;
+	unsigned int vratio;
+
+	__crop = __mt9v032_get_pad_crop(mt9v032, fh, format->pad,
+					format->which);
+
+	/* Clamp the width and height to avoid dividing by zero. */
+	width = clamp_t(unsigned int, ALIGN(format->format.width, 2),
+			max(__crop->width / 8, MT9V032_WINDOW_WIDTH_MIN),
+			__crop->width);
+	height = clamp_t(unsigned int, ALIGN(format->format.height, 2),
+			 max(__crop->height / 8, MT9V032_WINDOW_HEIGHT_MIN),
+			 __crop->height);
+
+	hratio = DIV_ROUND_CLOSEST(__crop->width, width);
+	vratio = DIV_ROUND_CLOSEST(__crop->height, height);
+
+	__format = __mt9v032_get_pad_format(mt9v032, fh, format->pad,
+					    format->which);
+	__format->width = __crop->width / hratio;
+	__format->height = __crop->height / vratio;
+	if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+		mt9v032_configure_pixel_rate(mt9v032, hratio);
+
+	format->format = *__format;
+
+	return 0;
+}
+
+static int mt9v032_get_crop(struct v4l2_subdev *subdev,
+			    struct v4l2_subdev_fh *fh,
+			    struct v4l2_subdev_crop *crop)
+{
+	struct mt9v032 *mt9v032 = to_mt9v032(subdev);
+
+	crop->rect = *__mt9v032_get_pad_crop(mt9v032, fh, crop->pad,
+					     crop->which);
+	return 0;
+}
+
+static int mt9v032_set_crop(struct v4l2_subdev *subdev,
+			    struct v4l2_subdev_fh *fh,
+			    struct v4l2_subdev_crop *crop)
+{
+	struct mt9v032 *mt9v032 = to_mt9v032(subdev);
+	struct v4l2_mbus_framefmt *__format;
+	struct v4l2_rect *__crop;
+	struct v4l2_rect rect;
+
+	/* Clamp the crop rectangle boundaries and align them to a non multiple
+	 * of 2 pixels to ensure a GRBG Bayer pattern.
+	 */
+	rect.left = clamp(ALIGN(crop->rect.left + 1, 2) - 1,
+			  MT9V032_COLUMN_START_MIN,
+			  MT9V032_COLUMN_START_MAX);
+	rect.top = clamp(ALIGN(crop->rect.top + 1, 2) - 1,
+			 MT9V032_ROW_START_MIN,
+			 MT9V032_ROW_START_MAX);
+	rect.width = clamp(ALIGN(crop->rect.width, 2),
+			   MT9V032_WINDOW_WIDTH_MIN,
+			   MT9V032_WINDOW_WIDTH_MAX);
+	rect.height = clamp(ALIGN(crop->rect.height, 2),
+			    MT9V032_WINDOW_HEIGHT_MIN,
+			    MT9V032_WINDOW_HEIGHT_MAX);
+
+	rect.width = min(rect.width, MT9V032_PIXEL_ARRAY_WIDTH - rect.left);
+	rect.height = min(rect.height, MT9V032_PIXEL_ARRAY_HEIGHT - rect.top);
+
+	__crop = __mt9v032_get_pad_crop(mt9v032, fh, crop->pad, crop->which);
+
+	if (rect.width != __crop->width || rect.height != __crop->height) {
+		/* Reset the output image size if the crop rectangle size has
+		 * been modified.
+		 */
+		__format = __mt9v032_get_pad_format(mt9v032, fh, crop->pad,
+						    crop->which);
+		__format->width = rect.width;
+		__format->height = rect.height;
+		if (crop->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+			mt9v032_configure_pixel_rate(mt9v032, 1);
+	}
+
+	*__crop = rect;
+	crop->rect = rect;
+
+	return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 subdev control operations
+ */
+
+#define V4L2_CID_TEST_PATTERN		(V4L2_CID_USER_BASE | 0x1001)
+
+static int mt9v032_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct mt9v032 *mt9v032 =
+			container_of(ctrl->handler, struct mt9v032, ctrls);
+	struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev);
+	u32 freq;
+	u16 data;
+
+	switch (ctrl->id) {
+	case V4L2_CID_AUTOGAIN:
+		return mt9v032_update_aec_agc(mt9v032, MT9V032_AGC_ENABLE,
+					      ctrl->val);
+
+	case V4L2_CID_GAIN:
+		return mt9v032_write(client, MT9V032_ANALOG_GAIN, ctrl->val);
+
+	case V4L2_CID_EXPOSURE_AUTO:
+		return mt9v032_update_aec_agc(mt9v032, MT9V032_AEC_ENABLE,
+					      !ctrl->val);
+
+	case V4L2_CID_EXPOSURE:
+		return mt9v032_write(client, MT9V032_TOTAL_SHUTTER_WIDTH,
+				     ctrl->val);
+
+	case V4L2_CID_HBLANK:
+		mt9v032->hblank = ctrl->val;
+		return mt9v032_update_hblank(mt9v032);
+
+	case V4L2_CID_VBLANK:
+		return mt9v032_write(client, MT9V032_VERTICAL_BLANKING,
+				     ctrl->val);
+
+	case V4L2_CID_PIXEL_RATE:
+	case V4L2_CID_LINK_FREQ:
+		if (mt9v032->link_freq == NULL)
+			break;
+
+		freq = mt9v032->pdata->link_freqs[mt9v032->link_freq->val];
+		mt9v032->pixel_rate->val64 = freq;
+		mt9v032->sysclk = freq;
+		break;
+
+	case V4L2_CID_TEST_PATTERN:
+		switch (ctrl->val) {
+		case 0:
+			data = 0;
+			break;
+		case 1:
+			data = MT9V032_TEST_PATTERN_GRAY_VERTICAL
+			     | MT9V032_TEST_PATTERN_ENABLE;
+			break;
+		case 2:
+			data = MT9V032_TEST_PATTERN_GRAY_HORIZONTAL
+			     | MT9V032_TEST_PATTERN_ENABLE;
+			break;
+		case 3:
+			data = MT9V032_TEST_PATTERN_GRAY_DIAGONAL
+			     | MT9V032_TEST_PATTERN_ENABLE;
+			break;
+		default:
+			data = (ctrl->val << MT9V032_TEST_PATTERN_DATA_SHIFT)
+			     | MT9V032_TEST_PATTERN_USE_DATA
+			     | MT9V032_TEST_PATTERN_ENABLE
+			     | MT9V032_TEST_PATTERN_FLIP;
+			break;
+		}
+
+		return mt9v032_write(client, MT9V032_TEST_PATTERN, data);
+	}
+
+	return 0;
+}
+
+static struct v4l2_ctrl_ops mt9v032_ctrl_ops = {
+	.s_ctrl = mt9v032_s_ctrl,
+};
+
+static const struct v4l2_ctrl_config mt9v032_ctrls[] = {
+	{
+		.ops		= &mt9v032_ctrl_ops,
+		.id		= V4L2_CID_TEST_PATTERN,
+		.type		= V4L2_CTRL_TYPE_INTEGER,
+		.name		= "Test pattern",
+		.min		= 0,
+		.max		= 1023,
+		.step		= 1,
+		.def		= 0,
+		.flags		= 0,
+	}
+};
+
+/* -----------------------------------------------------------------------------
+ * V4L2 subdev core operations
+ */
+
+static int mt9v032_set_power(struct v4l2_subdev *subdev, int on)
+{
+	struct mt9v032 *mt9v032 = to_mt9v032(subdev);
+	int ret = 0;
+
+	mutex_lock(&mt9v032->power_lock);
+
+	/* If the power count is modified from 0 to != 0 or from != 0 to 0,
+	 * update the power state.
+	 */
+	if (mt9v032->power_count == !on) {
+		ret = __mt9v032_set_power(mt9v032, !!on);
+		if (ret < 0)
+			goto done;
+	}
+
+	/* Update the power count. */
+	mt9v032->power_count += on ? 1 : -1;
+	WARN_ON(mt9v032->power_count < 0);
+
+done:
+	mutex_unlock(&mt9v032->power_lock);
+	return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 subdev internal operations
+ */
+
+static int mt9v032_registered(struct v4l2_subdev *subdev)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(subdev);
+	struct mt9v032 *mt9v032 = to_mt9v032(subdev);
+	s32 data;
+	int ret;
+
+	dev_info(&client->dev, "Probing MT9V032 at address 0x%02x\n",
+			client->addr);
+
+	ret = mt9v032_power_on(mt9v032);
+	if (ret < 0) {
+		dev_err(&client->dev, "MT9V032 power up failed\n");
+		return ret;
+	}
+
+	/* Read and check the sensor version */
+	data = mt9v032_read(client, MT9V032_CHIP_VERSION);
+	if (data != MT9V032_CHIP_ID_REV1 && data != MT9V032_CHIP_ID_REV3) {
+		dev_err(&client->dev, "MT9V032 not detected, wrong version "
+				"0x%04x\n", data);
+		return -ENODEV;
+	}
+
+	mt9v032_power_off(mt9v032);
+
+	dev_info(&client->dev, "MT9V032 detected at address 0x%02x\n",
+			client->addr);
+
+	mt9v032_configure_pixel_rate(mt9v032, 1);
+
+	return ret;
+}
+
+static int mt9v032_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
+{
+	struct v4l2_mbus_framefmt *format;
+	struct v4l2_rect *crop;
+
+	crop = v4l2_subdev_get_try_crop(fh, 0);
+	crop->left = MT9V032_COLUMN_START_DEF;
+	crop->top = MT9V032_ROW_START_DEF;
+	crop->width = MT9V032_WINDOW_WIDTH_DEF;
+	crop->height = MT9V032_WINDOW_HEIGHT_DEF;
+
+	format = v4l2_subdev_get_try_format(fh, 0);
+	format->code = V4L2_MBUS_FMT_SGRBG10_1X10;
+	format->width = MT9V032_WINDOW_WIDTH_DEF;
+	format->height = MT9V032_WINDOW_HEIGHT_DEF;
+	format->field = V4L2_FIELD_NONE;
+	format->colorspace = V4L2_COLORSPACE_SRGB;
+
+	return mt9v032_set_power(subdev, 1);
+}
+
+static int mt9v032_close(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
+{
+	return mt9v032_set_power(subdev, 0);
+}
+
+static struct v4l2_subdev_core_ops mt9v032_subdev_core_ops = {
+	.s_power	= mt9v032_set_power,
+};
+
+static struct v4l2_subdev_video_ops mt9v032_subdev_video_ops = {
+	.s_stream	= mt9v032_s_stream,
+};
+
+static struct v4l2_subdev_pad_ops mt9v032_subdev_pad_ops = {
+	.enum_mbus_code = mt9v032_enum_mbus_code,
+	.enum_frame_size = mt9v032_enum_frame_size,
+	.get_fmt = mt9v032_get_format,
+	.set_fmt = mt9v032_set_format,
+	.get_crop = mt9v032_get_crop,
+	.set_crop = mt9v032_set_crop,
+};
+
+static struct v4l2_subdev_ops mt9v032_subdev_ops = {
+	.core	= &mt9v032_subdev_core_ops,
+	.video	= &mt9v032_subdev_video_ops,
+	.pad	= &mt9v032_subdev_pad_ops,
+};
+
+static const struct v4l2_subdev_internal_ops mt9v032_subdev_internal_ops = {
+	.registered = mt9v032_registered,
+	.open = mt9v032_open,
+	.close = mt9v032_close,
+};
+
+/* -----------------------------------------------------------------------------
+ * Driver initialization and probing
+ */
+
+static int mt9v032_probe(struct i2c_client *client,
+		const struct i2c_device_id *did)
+{
+	struct mt9v032_platform_data *pdata = client->dev.platform_data;
+	struct mt9v032 *mt9v032;
+	unsigned int i;
+	int ret;
+
+	if (!i2c_check_functionality(client->adapter,
+				     I2C_FUNC_SMBUS_WORD_DATA)) {
+		dev_warn(&client->adapter->dev,
+			 "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n");
+		return -EIO;
+	}
+
+	mt9v032 = kzalloc(sizeof(*mt9v032), GFP_KERNEL);
+	if (!mt9v032)
+		return -ENOMEM;
+
+	mutex_init(&mt9v032->power_lock);
+	mt9v032->pdata = pdata;
+
+	v4l2_ctrl_handler_init(&mt9v032->ctrls, ARRAY_SIZE(mt9v032_ctrls) + 8);
+
+	v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops,
+			  V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
+	v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops,
+			  V4L2_CID_GAIN, MT9V032_ANALOG_GAIN_MIN,
+			  MT9V032_ANALOG_GAIN_MAX, 1, MT9V032_ANALOG_GAIN_DEF);
+	v4l2_ctrl_new_std_menu(&mt9v032->ctrls, &mt9v032_ctrl_ops,
+			       V4L2_CID_EXPOSURE_AUTO, V4L2_EXPOSURE_MANUAL, 0,
+			       V4L2_EXPOSURE_AUTO);
+	v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops,
+			  V4L2_CID_EXPOSURE, MT9V032_TOTAL_SHUTTER_WIDTH_MIN,
+			  MT9V032_TOTAL_SHUTTER_WIDTH_MAX, 1,
+			  MT9V032_TOTAL_SHUTTER_WIDTH_DEF);
+	v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops,
+			  V4L2_CID_HBLANK, MT9V032_HORIZONTAL_BLANKING_MIN,
+			  MT9V032_HORIZONTAL_BLANKING_MAX, 1,
+			  MT9V032_HORIZONTAL_BLANKING_DEF);
+	v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops,
+			  V4L2_CID_VBLANK, MT9V032_VERTICAL_BLANKING_MIN,
+			  MT9V032_VERTICAL_BLANKING_MAX, 1,
+			  MT9V032_VERTICAL_BLANKING_DEF);
+
+	mt9v032->pixel_rate =
+		v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops,
+				  V4L2_CID_PIXEL_RATE, 0, 0, 1, 0);
+
+	if (pdata && pdata->link_freqs) {
+		unsigned int def = 0;
+
+		for (i = 0; pdata->link_freqs[i]; ++i) {
+			if (pdata->link_freqs[i] == pdata->link_def_freq)
+				def = i;
+		}
+
+		mt9v032->link_freq =
+			v4l2_ctrl_new_int_menu(&mt9v032->ctrls,
+					       &mt9v032_ctrl_ops,
+					       V4L2_CID_LINK_FREQ, i - 1, def,
+					       pdata->link_freqs);
+		v4l2_ctrl_cluster(2, &mt9v032->link_freq);
+	}
+
+	for (i = 0; i < ARRAY_SIZE(mt9v032_ctrls); ++i)
+		v4l2_ctrl_new_custom(&mt9v032->ctrls, &mt9v032_ctrls[i], NULL);
+
+	mt9v032->subdev.ctrl_handler = &mt9v032->ctrls;
+
+	if (mt9v032->ctrls.error)
+		printk(KERN_INFO "%s: control initialization error %d\n",
+		       __func__, mt9v032->ctrls.error);
+
+	mt9v032->crop.left = MT9V032_COLUMN_START_DEF;
+	mt9v032->crop.top = MT9V032_ROW_START_DEF;
+	mt9v032->crop.width = MT9V032_WINDOW_WIDTH_DEF;
+	mt9v032->crop.height = MT9V032_WINDOW_HEIGHT_DEF;
+
+	mt9v032->format.code = V4L2_MBUS_FMT_SGRBG10_1X10;
+	mt9v032->format.width = MT9V032_WINDOW_WIDTH_DEF;
+	mt9v032->format.height = MT9V032_WINDOW_HEIGHT_DEF;
+	mt9v032->format.field = V4L2_FIELD_NONE;
+	mt9v032->format.colorspace = V4L2_COLORSPACE_SRGB;
+
+	mt9v032->aec_agc = MT9V032_AEC_ENABLE | MT9V032_AGC_ENABLE;
+	mt9v032->hblank = MT9V032_HORIZONTAL_BLANKING_DEF;
+	mt9v032->sysclk = MT9V032_SYSCLK_FREQ_DEF;
+
+	v4l2_i2c_subdev_init(&mt9v032->subdev, client, &mt9v032_subdev_ops);
+	mt9v032->subdev.internal_ops = &mt9v032_subdev_internal_ops;
+	mt9v032->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+	mt9v032->pad.flags = MEDIA_PAD_FL_SOURCE;
+	ret = media_entity_init(&mt9v032->subdev.entity, 1, &mt9v032->pad, 0);
+	if (ret < 0)
+		kfree(mt9v032);
+
+	return ret;
+}
+
+static int mt9v032_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *subdev = i2c_get_clientdata(client);
+	struct mt9v032 *mt9v032 = to_mt9v032(subdev);
+
+	v4l2_device_unregister_subdev(subdev);
+	media_entity_cleanup(&subdev->entity);
+	kfree(mt9v032);
+	return 0;
+}
+
+static const struct i2c_device_id mt9v032_id[] = {
+	{ "mt9v032", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, mt9v032_id);
+
+static struct i2c_driver mt9v032_driver = {
+	.driver = {
+		.name = "mt9v032",
+	},
+	.probe		= mt9v032_probe,
+	.remove		= mt9v032_remove,
+	.id_table	= mt9v032_id,
+};
+
+module_i2c_driver(mt9v032_driver);
+
+MODULE_DESCRIPTION("Aptina MT9V032 Camera driver");
+MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/i2c/noon010pc30.c b/drivers/media/i2c/noon010pc30.c
new file mode 100644
index 0000000..440c129
--- /dev/null
+++ b/drivers/media/i2c/noon010pc30.c
@@ -0,0 +1,851 @@
+/*
+ * Driver for SiliconFile NOON010PC30 CIF (1/11") Image Sensor with ISP
+ *
+ * Copyright (C) 2010 - 2011 Samsung Electronics Co., Ltd.
+ * Contact: Sylwester Nawrocki, <s.nawrocki@samsung.com>
+ *
+ * Initial register configuration based on a driver authored by
+ * HeungJun Kim <riverful.kim@samsung.com>.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/regulator/consumer.h>
+#include <media/noon010pc30.h>
+#include <media/v4l2-chip-ident.h>
+#include <linux/videodev2.h>
+#include <linux/module.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-mediabus.h>
+#include <media/v4l2-subdev.h>
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Enable module debug trace. Set to 1 to enable.");
+
+#define MODULE_NAME		"NOON010PC30"
+
+/*
+ * Register offsets within a page
+ * b15..b8 - page id, b7..b0 - register address
+ */
+#define POWER_CTRL_REG		0x0001
+#define PAGEMODE_REG		0x03
+#define DEVICE_ID_REG		0x0004
+#define NOON010PC30_ID		0x86
+#define VDO_CTL_REG(n)		(0x0010 + (n))
+#define SYNC_CTL_REG		0x0012
+/* Window size and position */
+#define WIN_ROWH_REG		0x0013
+#define WIN_ROWL_REG		0x0014
+#define WIN_COLH_REG		0x0015
+#define WIN_COLL_REG		0x0016
+#define WIN_HEIGHTH_REG		0x0017
+#define WIN_HEIGHTL_REG		0x0018
+#define WIN_WIDTHH_REG		0x0019
+#define WIN_WIDTHL_REG		0x001A
+#define HBLANKH_REG		0x001B
+#define HBLANKL_REG		0x001C
+#define VSYNCH_REG		0x001D
+#define VSYNCL_REG		0x001E
+/* VSYNC control */
+#define VS_CTL_REG(n)		(0x00A1 + (n))
+/* page 1 */
+#define ISP_CTL_REG(n)		(0x0110 + (n))
+#define YOFS_REG		0x0119
+#define DARK_YOFS_REG		0x011A
+#define SAT_CTL_REG		0x0120
+#define BSAT_REG		0x0121
+#define RSAT_REG		0x0122
+/* Color correction */
+#define CMC_CTL_REG		0x0130
+#define CMC_OFSGH_REG		0x0133
+#define CMC_OFSGL_REG		0x0135
+#define CMC_SIGN_REG		0x0136
+#define CMC_GOFS_REG		0x0137
+#define CMC_COEF_REG(n)		(0x0138 + (n))
+#define CMC_OFS_REG(n)		(0x0141 + (n))
+/* Gamma correction */
+#define GMA_CTL_REG		0x0160
+#define GMA_COEF_REG(n)		(0x0161 + (n))
+/* Lens Shading */
+#define LENS_CTRL_REG		0x01D0
+#define LENS_XCEN_REG		0x01D1
+#define LENS_YCEN_REG		0x01D2
+#define LENS_RC_REG		0x01D3
+#define LENS_GC_REG		0x01D4
+#define LENS_BC_REG		0x01D5
+#define L_AGON_REG		0x01D6
+#define L_AGOFF_REG		0x01D7
+/* Page 3 - Auto Exposure */
+#define AE_CTL_REG(n)		(0x0310 + (n))
+#define AE_CTL9_REG		0x032C
+#define AE_CTL10_REG		0x032D
+#define AE_YLVL_REG		0x031C
+#define AE_YTH_REG(n)		(0x031D + (n))
+#define AE_WGT_REG		0x0326
+#define EXP_TIMEH_REG		0x0333
+#define EXP_TIMEM_REG		0x0334
+#define EXP_TIMEL_REG		0x0335
+#define EXP_MMINH_REG		0x0336
+#define EXP_MMINL_REG		0x0337
+#define EXP_MMAXH_REG		0x0338
+#define EXP_MMAXM_REG		0x0339
+#define EXP_MMAXL_REG		0x033A
+/* Page 4 - Auto White Balance */
+#define AWB_CTL_REG(n)		(0x0410 + (n))
+#define AWB_ENABE		0x80
+#define AWB_WGHT_REG		0x0419
+#define BGAIN_PAR_REG(n)	(0x044F + (n))
+/* Manual white balance, when AWB_CTL2[0]=1 */
+#define MWB_RGAIN_REG		0x0466
+#define MWB_BGAIN_REG		0x0467
+
+/* The token to mark an array end */
+#define REG_TERM		0xFFFF
+
+struct noon010_format {
+	enum v4l2_mbus_pixelcode code;
+	enum v4l2_colorspace colorspace;
+	u16 ispctl1_reg;
+};
+
+struct noon010_frmsize {
+	u16 width;
+	u16 height;
+	int vid_ctl1;
+};
+
+static const char * const noon010_supply_name[] = {
+	"vdd_core", "vddio", "vdda"
+};
+
+#define NOON010_NUM_SUPPLIES ARRAY_SIZE(noon010_supply_name)
+
+struct noon010_info {
+	struct v4l2_subdev sd;
+	struct media_pad pad;
+	struct v4l2_ctrl_handler hdl;
+	struct regulator_bulk_data supply[NOON010_NUM_SUPPLIES];
+	u32 gpio_nreset;
+	u32 gpio_nstby;
+
+	/* Protects the struct members below */
+	struct mutex lock;
+
+	const struct noon010_format *curr_fmt;
+	const struct noon010_frmsize *curr_win;
+	unsigned int apply_new_cfg:1;
+	unsigned int streaming:1;
+	unsigned int hflip:1;
+	unsigned int vflip:1;
+	unsigned int power:1;
+	u8 i2c_reg_page;
+};
+
+struct i2c_regval {
+	u16 addr;
+	u16 val;
+};
+
+/* Supported resolutions. */
+static const struct noon010_frmsize noon010_sizes[] = {
+	{
+		.width		= 352,
+		.height		= 288,
+		.vid_ctl1	= 0,
+	}, {
+		.width		= 176,
+		.height		= 144,
+		.vid_ctl1	= 0x10,
+	}, {
+		.width		= 88,
+		.height		= 72,
+		.vid_ctl1	= 0x20,
+	},
+};
+
+/* Supported pixel formats. */
+static const struct noon010_format noon010_formats[] = {
+	{
+		.code		= V4L2_MBUS_FMT_YUYV8_2X8,
+		.colorspace	= V4L2_COLORSPACE_JPEG,
+		.ispctl1_reg	= 0x03,
+	}, {
+		.code		= V4L2_MBUS_FMT_YVYU8_2X8,
+		.colorspace	= V4L2_COLORSPACE_JPEG,
+		.ispctl1_reg	= 0x02,
+	}, {
+		.code		= V4L2_MBUS_FMT_VYUY8_2X8,
+		.colorspace	= V4L2_COLORSPACE_JPEG,
+		.ispctl1_reg	= 0,
+	}, {
+		.code		= V4L2_MBUS_FMT_UYVY8_2X8,
+		.colorspace	= V4L2_COLORSPACE_JPEG,
+		.ispctl1_reg	= 0x01,
+	}, {
+		.code		= V4L2_MBUS_FMT_RGB565_2X8_BE,
+		.colorspace	= V4L2_COLORSPACE_JPEG,
+		.ispctl1_reg	= 0x40,
+	},
+};
+
+static const struct i2c_regval noon010_base_regs[] = {
+	{ WIN_COLL_REG,		0x06 },	{ HBLANKL_REG,		0x7C },
+	/* Color corection and saturation */
+	{ ISP_CTL_REG(0),	0x30 }, { ISP_CTL_REG(2),	0x30 },
+	{ YOFS_REG,		0x80 }, { DARK_YOFS_REG,	0x04 },
+	{ SAT_CTL_REG,		0x1F }, { BSAT_REG,		0x90 },
+	{ CMC_CTL_REG,		0x0F }, { CMC_OFSGH_REG,	0x3C },
+	{ CMC_OFSGL_REG,	0x2C }, { CMC_SIGN_REG,		0x3F },
+	{ CMC_COEF_REG(0),	0x79 }, { CMC_OFS_REG(0),	0x00 },
+	{ CMC_COEF_REG(1),	0x39 }, { CMC_OFS_REG(1),	0x00 },
+	{ CMC_COEF_REG(2),	0x00 }, { CMC_OFS_REG(2),	0x00 },
+	{ CMC_COEF_REG(3),	0x11 }, { CMC_OFS_REG(3),	0x8B },
+	{ CMC_COEF_REG(4),	0x65 }, { CMC_OFS_REG(4),	0x07 },
+	{ CMC_COEF_REG(5),	0x14 }, { CMC_OFS_REG(5),	0x04 },
+	{ CMC_COEF_REG(6),	0x01 }, { CMC_OFS_REG(6),	0x9C },
+	{ CMC_COEF_REG(7),	0x33 }, { CMC_OFS_REG(7),	0x89 },
+	{ CMC_COEF_REG(8),	0x74 }, { CMC_OFS_REG(8),	0x25 },
+	/* Automatic white balance */
+	{ AWB_CTL_REG(0),	0x78 }, { AWB_CTL_REG(1),	0x2E },
+	{ AWB_CTL_REG(2),	0x20 }, { AWB_CTL_REG(3),	0x85 },
+	/* Auto exposure */
+	{ AE_CTL_REG(0),	0xDC }, { AE_CTL_REG(1),	0x81 },
+	{ AE_CTL_REG(2),	0x30 }, { AE_CTL_REG(3),	0xA5 },
+	{ AE_CTL_REG(4),	0x40 }, { AE_CTL_REG(5),	0x51 },
+	{ AE_CTL_REG(6),	0x33 }, { AE_CTL_REG(7),	0x7E },
+	{ AE_CTL9_REG,		0x00 }, { AE_CTL10_REG,		0x02 },
+	{ AE_YLVL_REG,		0x44 },	{ AE_YTH_REG(0),	0x34 },
+	{ AE_YTH_REG(1),	0x30 },	{ AE_WGT_REG,		0xD5 },
+	/* Lens shading compensation */
+	{ LENS_CTRL_REG,	0x01 }, { LENS_XCEN_REG,	0x80 },
+	{ LENS_YCEN_REG,	0x70 }, { LENS_RC_REG,		0x53 },
+	{ LENS_GC_REG,		0x40 }, { LENS_BC_REG,		0x3E },
+	{ REG_TERM,		0 },
+};
+
+static inline struct noon010_info *to_noon010(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct noon010_info, sd);
+}
+
+static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
+{
+	return &container_of(ctrl->handler, struct noon010_info, hdl)->sd;
+}
+
+static inline int set_i2c_page(struct noon010_info *info,
+			       struct i2c_client *client, unsigned int reg)
+{
+	u32 page = reg >> 8 & 0xFF;
+	int ret = 0;
+
+	if (info->i2c_reg_page != page && (reg & 0xFF) != 0x03) {
+		ret = i2c_smbus_write_byte_data(client, PAGEMODE_REG, page);
+		if (!ret)
+			info->i2c_reg_page = page;
+	}
+	return ret;
+}
+
+static int cam_i2c_read(struct v4l2_subdev *sd, u32 reg_addr)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct noon010_info *info = to_noon010(sd);
+	int ret = set_i2c_page(info, client, reg_addr);
+
+	if (ret)
+		return ret;
+	return i2c_smbus_read_byte_data(client, reg_addr & 0xFF);
+}
+
+static int cam_i2c_write(struct v4l2_subdev *sd, u32 reg_addr, u32 val)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct noon010_info *info = to_noon010(sd);
+	int ret = set_i2c_page(info, client, reg_addr);
+
+	if (ret)
+		return ret;
+	return i2c_smbus_write_byte_data(client, reg_addr & 0xFF, val);
+}
+
+static inline int noon010_bulk_write_reg(struct v4l2_subdev *sd,
+					 const struct i2c_regval *msg)
+{
+	while (msg->addr != REG_TERM) {
+		int ret = cam_i2c_write(sd, msg->addr, msg->val);
+
+		if (ret)
+			return ret;
+		msg++;
+	}
+	return 0;
+}
+
+/* Device reset and sleep mode control */
+static int noon010_power_ctrl(struct v4l2_subdev *sd, bool reset, bool sleep)
+{
+	struct noon010_info *info = to_noon010(sd);
+	u8 reg = sleep ? 0xF1 : 0xF0;
+	int ret = 0;
+
+	if (reset) {
+		ret = cam_i2c_write(sd, POWER_CTRL_REG, reg | 0x02);
+		udelay(20);
+	}
+	if (!ret) {
+		ret = cam_i2c_write(sd, POWER_CTRL_REG, reg);
+		if (reset && !ret)
+			info->i2c_reg_page = -1;
+	}
+	return ret;
+}
+
+/* Automatic white balance control */
+static int noon010_enable_autowhitebalance(struct v4l2_subdev *sd, int on)
+{
+	int ret;
+
+	ret = cam_i2c_write(sd, AWB_CTL_REG(1), on ? 0x2E : 0x2F);
+	if (!ret)
+		ret = cam_i2c_write(sd, AWB_CTL_REG(0), on ? 0xFB : 0x7B);
+	return ret;
+}
+
+/* Called with struct noon010_info.lock mutex held */
+static int noon010_set_flip(struct v4l2_subdev *sd, int hflip, int vflip)
+{
+	struct noon010_info *info = to_noon010(sd);
+	int reg, ret;
+
+	reg = cam_i2c_read(sd, VDO_CTL_REG(1));
+	if (reg < 0)
+		return reg;
+
+	reg &= 0x7C;
+	if (hflip)
+		reg |= 0x01;
+	if (vflip)
+		reg |= 0x02;
+
+	ret = cam_i2c_write(sd, VDO_CTL_REG(1), reg | 0x80);
+	if (!ret) {
+		info->hflip = hflip;
+		info->vflip = vflip;
+	}
+	return ret;
+}
+
+/* Configure resolution and color format */
+static int noon010_set_params(struct v4l2_subdev *sd)
+{
+	struct noon010_info *info = to_noon010(sd);
+
+	int ret = cam_i2c_write(sd, VDO_CTL_REG(0),
+				info->curr_win->vid_ctl1);
+	if (ret)
+		return ret;
+	return cam_i2c_write(sd, ISP_CTL_REG(0),
+			     info->curr_fmt->ispctl1_reg);
+}
+
+/* Find nearest matching image pixel size. */
+static int noon010_try_frame_size(struct v4l2_mbus_framefmt *mf,
+				  const struct noon010_frmsize **size)
+{
+	unsigned int min_err = ~0;
+	int i = ARRAY_SIZE(noon010_sizes);
+	const struct noon010_frmsize *fsize = &noon010_sizes[0],
+		*match = NULL;
+
+	while (i--) {
+		int err = abs(fsize->width - mf->width)
+				+ abs(fsize->height - mf->height);
+
+		if (err < min_err) {
+			min_err = err;
+			match = fsize;
+		}
+		fsize++;
+	}
+	if (match) {
+		mf->width  = match->width;
+		mf->height = match->height;
+		if (size)
+			*size = match;
+		return 0;
+	}
+	return -EINVAL;
+}
+
+/* Called with info.lock mutex held */
+static int power_enable(struct noon010_info *info)
+{
+	int ret;
+
+	if (info->power) {
+		v4l2_info(&info->sd, "%s: sensor is already on\n", __func__);
+		return 0;
+	}
+
+	if (gpio_is_valid(info->gpio_nstby))
+		gpio_set_value(info->gpio_nstby, 0);
+
+	if (gpio_is_valid(info->gpio_nreset))
+		gpio_set_value(info->gpio_nreset, 0);
+
+	ret = regulator_bulk_enable(NOON010_NUM_SUPPLIES, info->supply);
+	if (ret)
+		return ret;
+
+	if (gpio_is_valid(info->gpio_nreset)) {
+		msleep(50);
+		gpio_set_value(info->gpio_nreset, 1);
+	}
+	if (gpio_is_valid(info->gpio_nstby)) {
+		udelay(1000);
+		gpio_set_value(info->gpio_nstby, 1);
+	}
+	if (gpio_is_valid(info->gpio_nreset)) {
+		udelay(1000);
+		gpio_set_value(info->gpio_nreset, 0);
+		msleep(100);
+		gpio_set_value(info->gpio_nreset, 1);
+		msleep(20);
+	}
+	info->power = 1;
+
+	v4l2_dbg(1, debug, &info->sd,  "%s: sensor is on\n", __func__);
+	return 0;
+}
+
+/* Called with info.lock mutex held */
+static int power_disable(struct noon010_info *info)
+{
+	int ret;
+
+	if (!info->power) {
+		v4l2_info(&info->sd, "%s: sensor is already off\n", __func__);
+		return 0;
+	}
+
+	ret = regulator_bulk_disable(NOON010_NUM_SUPPLIES, info->supply);
+	if (ret)
+		return ret;
+
+	if (gpio_is_valid(info->gpio_nstby))
+		gpio_set_value(info->gpio_nstby, 0);
+
+	if (gpio_is_valid(info->gpio_nreset))
+		gpio_set_value(info->gpio_nreset, 0);
+
+	info->power = 0;
+
+	v4l2_dbg(1, debug, &info->sd,  "%s: sensor is off\n", __func__);
+
+	return 0;
+}
+
+static int noon010_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct v4l2_subdev *sd = to_sd(ctrl);
+	struct noon010_info *info = to_noon010(sd);
+	int ret = 0;
+
+	v4l2_dbg(1, debug, sd, "%s: ctrl_id: %d, value: %d\n",
+		 __func__, ctrl->id, ctrl->val);
+
+	mutex_lock(&info->lock);
+	/*
+	 * If the device is not powered up by the host driver do
+	 * not apply any controls to H/W at this time. Instead
+	 * the controls will be restored right after power-up.
+	 */
+	if (!info->power)
+		goto unlock;
+
+	switch (ctrl->id) {
+	case V4L2_CID_AUTO_WHITE_BALANCE:
+		ret = noon010_enable_autowhitebalance(sd, ctrl->val);
+		break;
+	case V4L2_CID_BLUE_BALANCE:
+		ret = cam_i2c_write(sd, MWB_BGAIN_REG, ctrl->val);
+		break;
+	case V4L2_CID_RED_BALANCE:
+		ret =  cam_i2c_write(sd, MWB_RGAIN_REG, ctrl->val);
+		break;
+	default:
+		ret = -EINVAL;
+	}
+unlock:
+	mutex_unlock(&info->lock);
+	return ret;
+}
+
+static int noon010_enum_mbus_code(struct v4l2_subdev *sd,
+				  struct v4l2_subdev_fh *fh,
+				  struct v4l2_subdev_mbus_code_enum *code)
+{
+	if (code->index >= ARRAY_SIZE(noon010_formats))
+		return -EINVAL;
+
+	code->code = noon010_formats[code->index].code;
+	return 0;
+}
+
+static int noon010_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+			   struct v4l2_subdev_format *fmt)
+{
+	struct noon010_info *info = to_noon010(sd);
+	struct v4l2_mbus_framefmt *mf;
+
+	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
+		if (fh) {
+			mf = v4l2_subdev_get_try_format(fh, 0);
+			fmt->format = *mf;
+		}
+		return 0;
+	}
+	mf = &fmt->format;
+
+	mutex_lock(&info->lock);
+	mf->width = info->curr_win->width;
+	mf->height = info->curr_win->height;
+	mf->code = info->curr_fmt->code;
+	mf->colorspace = info->curr_fmt->colorspace;
+	mf->field = V4L2_FIELD_NONE;
+
+	mutex_unlock(&info->lock);
+	return 0;
+}
+
+/* Return nearest media bus frame format. */
+static const struct noon010_format *noon010_try_fmt(struct v4l2_subdev *sd,
+					    struct v4l2_mbus_framefmt *mf)
+{
+	int i = ARRAY_SIZE(noon010_formats);
+
+	while (--i)
+		if (mf->code == noon010_formats[i].code)
+			break;
+	mf->code = noon010_formats[i].code;
+
+	return &noon010_formats[i];
+}
+
+static int noon010_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+			   struct v4l2_subdev_format *fmt)
+{
+	struct noon010_info *info = to_noon010(sd);
+	const struct noon010_frmsize *size = NULL;
+	const struct noon010_format *nf;
+	struct v4l2_mbus_framefmt *mf;
+	int ret = 0;
+
+	nf = noon010_try_fmt(sd, &fmt->format);
+	noon010_try_frame_size(&fmt->format, &size);
+	fmt->format.colorspace = V4L2_COLORSPACE_JPEG;
+
+	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
+		if (fh) {
+			mf = v4l2_subdev_get_try_format(fh, 0);
+			*mf = fmt->format;
+		}
+		return 0;
+	}
+	mutex_lock(&info->lock);
+	if (!info->streaming) {
+		info->apply_new_cfg = 1;
+		info->curr_fmt = nf;
+		info->curr_win = size;
+	} else {
+		ret = -EBUSY;
+	}
+	mutex_unlock(&info->lock);
+	return ret;
+}
+
+/* Called with struct noon010_info.lock mutex held */
+static int noon010_base_config(struct v4l2_subdev *sd)
+{
+	int ret = noon010_bulk_write_reg(sd, noon010_base_regs);
+	if (!ret)
+		ret = noon010_set_params(sd);
+	if (!ret)
+		ret = noon010_set_flip(sd, 1, 0);
+
+	return ret;
+}
+
+static int noon010_s_power(struct v4l2_subdev *sd, int on)
+{
+	struct noon010_info *info = to_noon010(sd);
+	int ret;
+
+	mutex_lock(&info->lock);
+	if (on) {
+		ret = power_enable(info);
+		if (!ret)
+			ret = noon010_base_config(sd);
+	} else {
+		noon010_power_ctrl(sd, false, true);
+		ret = power_disable(info);
+	}
+	mutex_unlock(&info->lock);
+
+	/* Restore the controls state */
+	if (!ret && on)
+		ret = v4l2_ctrl_handler_setup(&info->hdl);
+
+	return ret;
+}
+
+static int noon010_s_stream(struct v4l2_subdev *sd, int on)
+{
+	struct noon010_info *info = to_noon010(sd);
+	int ret = 0;
+
+	mutex_lock(&info->lock);
+	if (!info->streaming != !on) {
+		ret = noon010_power_ctrl(sd, false, !on);
+		if (!ret)
+			info->streaming = on;
+	}
+	if (!ret && on && info->apply_new_cfg) {
+		ret = noon010_set_params(sd);
+		if (!ret)
+			info->apply_new_cfg = 0;
+	}
+	mutex_unlock(&info->lock);
+	return ret;
+}
+
+static int noon010_log_status(struct v4l2_subdev *sd)
+{
+	struct noon010_info *info = to_noon010(sd);
+
+	v4l2_ctrl_handler_log_status(&info->hdl, sd->name);
+	return 0;
+}
+
+static int noon010_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+	struct v4l2_mbus_framefmt *mf = v4l2_subdev_get_try_format(fh, 0);
+
+	mf->width = noon010_sizes[0].width;
+	mf->height = noon010_sizes[0].height;
+	mf->code = noon010_formats[0].code;
+	mf->colorspace = V4L2_COLORSPACE_JPEG;
+	mf->field = V4L2_FIELD_NONE;
+	return 0;
+}
+
+static const struct v4l2_subdev_internal_ops noon010_subdev_internal_ops = {
+	.open = noon010_open,
+};
+
+static const struct v4l2_ctrl_ops noon010_ctrl_ops = {
+	.s_ctrl = noon010_s_ctrl,
+};
+
+static const struct v4l2_subdev_core_ops noon010_core_ops = {
+	.s_power	= noon010_s_power,
+	.g_ctrl		= v4l2_subdev_g_ctrl,
+	.s_ctrl		= v4l2_subdev_s_ctrl,
+	.queryctrl	= v4l2_subdev_queryctrl,
+	.querymenu	= v4l2_subdev_querymenu,
+	.g_ext_ctrls	= v4l2_subdev_g_ext_ctrls,
+	.try_ext_ctrls	= v4l2_subdev_try_ext_ctrls,
+	.s_ext_ctrls	= v4l2_subdev_s_ext_ctrls,
+	.log_status	= noon010_log_status,
+};
+
+static struct v4l2_subdev_pad_ops noon010_pad_ops = {
+	.enum_mbus_code	= noon010_enum_mbus_code,
+	.get_fmt	= noon010_get_fmt,
+	.set_fmt	= noon010_set_fmt,
+};
+
+static struct v4l2_subdev_video_ops noon010_video_ops = {
+	.s_stream	= noon010_s_stream,
+};
+
+static const struct v4l2_subdev_ops noon010_ops = {
+	.core	= &noon010_core_ops,
+	.pad	= &noon010_pad_ops,
+	.video	= &noon010_video_ops,
+};
+
+/* Return 0 if NOON010PC30L sensor type was detected or -ENODEV otherwise. */
+static int noon010_detect(struct i2c_client *client, struct noon010_info *info)
+{
+	int ret;
+
+	ret = power_enable(info);
+	if (ret)
+		return ret;
+
+	ret = i2c_smbus_read_byte_data(client, DEVICE_ID_REG);
+	if (ret < 0)
+		dev_err(&client->dev, "I2C read failed: 0x%X\n", ret);
+
+	power_disable(info);
+
+	return ret == NOON010PC30_ID ? 0 : -ENODEV;
+}
+
+static int noon010_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
+{
+	struct noon010_info *info;
+	struct v4l2_subdev *sd;
+	const struct noon010pc30_platform_data *pdata
+		= client->dev.platform_data;
+	int ret;
+	int i;
+
+	if (!pdata) {
+		dev_err(&client->dev, "No platform data!\n");
+		return -EIO;
+	}
+
+	info = kzalloc(sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	mutex_init(&info->lock);
+	sd = &info->sd;
+	v4l2_i2c_subdev_init(sd, client, &noon010_ops);
+	strlcpy(sd->name, MODULE_NAME, sizeof(sd->name));
+
+	sd->internal_ops = &noon010_subdev_internal_ops;
+	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+	v4l2_ctrl_handler_init(&info->hdl, 3);
+
+	v4l2_ctrl_new_std(&info->hdl, &noon010_ctrl_ops,
+			  V4L2_CID_AUTO_WHITE_BALANCE, 0, 1, 1, 1);
+	v4l2_ctrl_new_std(&info->hdl, &noon010_ctrl_ops,
+			  V4L2_CID_RED_BALANCE, 0, 127, 1, 64);
+	v4l2_ctrl_new_std(&info->hdl, &noon010_ctrl_ops,
+			  V4L2_CID_BLUE_BALANCE, 0, 127, 1, 64);
+
+	sd->ctrl_handler = &info->hdl;
+
+	ret = info->hdl.error;
+	if (ret)
+		goto np_err;
+
+	info->i2c_reg_page	= -1;
+	info->gpio_nreset	= -EINVAL;
+	info->gpio_nstby	= -EINVAL;
+	info->curr_fmt		= &noon010_formats[0];
+	info->curr_win		= &noon010_sizes[0];
+
+	if (gpio_is_valid(pdata->gpio_nreset)) {
+		ret = gpio_request(pdata->gpio_nreset, "NOON010PC30 NRST");
+		if (ret) {
+			dev_err(&client->dev, "GPIO request error: %d\n", ret);
+			goto np_err;
+		}
+		info->gpio_nreset = pdata->gpio_nreset;
+		gpio_direction_output(info->gpio_nreset, 0);
+		gpio_export(info->gpio_nreset, 0);
+	}
+
+	if (gpio_is_valid(pdata->gpio_nstby)) {
+		ret = gpio_request(pdata->gpio_nstby, "NOON010PC30 NSTBY");
+		if (ret) {
+			dev_err(&client->dev, "GPIO request error: %d\n", ret);
+			goto np_gpio_err;
+		}
+		info->gpio_nstby = pdata->gpio_nstby;
+		gpio_direction_output(info->gpio_nstby, 0);
+		gpio_export(info->gpio_nstby, 0);
+	}
+
+	for (i = 0; i < NOON010_NUM_SUPPLIES; i++)
+		info->supply[i].supply = noon010_supply_name[i];
+
+	ret = regulator_bulk_get(&client->dev, NOON010_NUM_SUPPLIES,
+				 info->supply);
+	if (ret)
+		goto np_reg_err;
+
+	info->pad.flags = MEDIA_PAD_FL_SOURCE;
+	sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR;
+	ret = media_entity_init(&sd->entity, 1, &info->pad, 0);
+	if (ret < 0)
+		goto np_me_err;
+
+	ret = noon010_detect(client, info);
+	if (!ret)
+		return 0;
+
+np_me_err:
+	regulator_bulk_free(NOON010_NUM_SUPPLIES, info->supply);
+np_reg_err:
+	if (gpio_is_valid(info->gpio_nstby))
+		gpio_free(info->gpio_nstby);
+np_gpio_err:
+	if (gpio_is_valid(info->gpio_nreset))
+		gpio_free(info->gpio_nreset);
+np_err:
+	v4l2_ctrl_handler_free(&info->hdl);
+	v4l2_device_unregister_subdev(sd);
+	kfree(info);
+	return ret;
+}
+
+static int noon010_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct noon010_info *info = to_noon010(sd);
+
+	v4l2_device_unregister_subdev(sd);
+	v4l2_ctrl_handler_free(&info->hdl);
+
+	regulator_bulk_free(NOON010_NUM_SUPPLIES, info->supply);
+
+	if (gpio_is_valid(info->gpio_nreset))
+		gpio_free(info->gpio_nreset);
+
+	if (gpio_is_valid(info->gpio_nstby))
+		gpio_free(info->gpio_nstby);
+
+	media_entity_cleanup(&sd->entity);
+	kfree(info);
+	return 0;
+}
+
+static const struct i2c_device_id noon010_id[] = {
+	{ MODULE_NAME, 0 },
+	{ },
+};
+MODULE_DEVICE_TABLE(i2c, noon010_id);
+
+
+static struct i2c_driver noon010_i2c_driver = {
+	.driver = {
+		.name = MODULE_NAME
+	},
+	.probe		= noon010_probe,
+	.remove		= noon010_remove,
+	.id_table	= noon010_id,
+};
+
+module_i2c_driver(noon010_i2c_driver);
+
+MODULE_DESCRIPTION("Siliconfile NOON010PC30 camera driver");
+MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/i2c/ov7670.c b/drivers/media/i2c/ov7670.c
new file mode 100644
index 0000000..e7c82b2
--- /dev/null
+++ b/drivers/media/i2c/ov7670.c
@@ -0,0 +1,1586 @@
+/*
+ * A V4L2 driver for OmniVision OV7670 cameras.
+ *
+ * Copyright 2006 One Laptop Per Child Association, Inc.  Written
+ * by Jonathan Corbet with substantial inspiration from Mark
+ * McClelland's ovcamchip code.
+ *
+ * Copyright 2006-7 Jonathan Corbet <corbet@lwn.net>
+ *
+ * This file may be distributed under the terms of the GNU General
+ * Public License, version 2.
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.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-mediabus.h>
+#include <media/ov7670.h>
+
+MODULE_AUTHOR("Jonathan Corbet <corbet@lwn.net>");
+MODULE_DESCRIPTION("A low-level driver for OmniVision ov7670 sensors");
+MODULE_LICENSE("GPL");
+
+static bool debug;
+module_param(debug, bool, 0644);
+MODULE_PARM_DESC(debug, "Debug level (0-1)");
+
+/*
+ * Basic window sizes.  These probably belong somewhere more globally
+ * useful.
+ */
+#define VGA_WIDTH	640
+#define VGA_HEIGHT	480
+#define QVGA_WIDTH	320
+#define QVGA_HEIGHT	240
+#define CIF_WIDTH	352
+#define CIF_HEIGHT	288
+#define QCIF_WIDTH	176
+#define	QCIF_HEIGHT	144
+
+/*
+ * The 7670 sits on i2c with ID 0x42
+ */
+#define OV7670_I2C_ADDR 0x42
+
+/* Registers */
+#define REG_GAIN	0x00	/* Gain lower 8 bits (rest in vref) */
+#define REG_BLUE	0x01	/* blue gain */
+#define REG_RED		0x02	/* red gain */
+#define REG_VREF	0x03	/* Pieces of GAIN, VSTART, VSTOP */
+#define REG_COM1	0x04	/* Control 1 */
+#define  COM1_CCIR656	  0x40  /* CCIR656 enable */
+#define REG_BAVE	0x05	/* U/B Average level */
+#define REG_GbAVE	0x06	/* Y/Gb Average level */
+#define REG_AECHH	0x07	/* AEC MS 5 bits */
+#define REG_RAVE	0x08	/* V/R Average level */
+#define REG_COM2	0x09	/* Control 2 */
+#define  COM2_SSLEEP	  0x10	/* Soft sleep mode */
+#define REG_PID		0x0a	/* Product ID MSB */
+#define REG_VER		0x0b	/* Product ID LSB */
+#define REG_COM3	0x0c	/* Control 3 */
+#define  COM3_SWAP	  0x40	  /* Byte swap */
+#define  COM3_SCALEEN	  0x08	  /* Enable scaling */
+#define  COM3_DCWEN	  0x04	  /* Enable downsamp/crop/window */
+#define REG_COM4	0x0d	/* Control 4 */
+#define REG_COM5	0x0e	/* All "reserved" */
+#define REG_COM6	0x0f	/* Control 6 */
+#define REG_AECH	0x10	/* More bits of AEC value */
+#define REG_CLKRC	0x11	/* Clocl control */
+#define   CLK_EXT	  0x40	  /* Use external clock directly */
+#define   CLK_SCALE	  0x3f	  /* Mask for internal clock scale */
+#define REG_COM7	0x12	/* Control 7 */
+#define   COM7_RESET	  0x80	  /* Register reset */
+#define   COM7_FMT_MASK	  0x38
+#define   COM7_FMT_VGA	  0x00
+#define	  COM7_FMT_CIF	  0x20	  /* CIF format */
+#define   COM7_FMT_QVGA	  0x10	  /* QVGA format */
+#define   COM7_FMT_QCIF	  0x08	  /* QCIF format */
+#define	  COM7_RGB	  0x04	  /* bits 0 and 2 - RGB format */
+#define	  COM7_YUV	  0x00	  /* YUV */
+#define	  COM7_BAYER	  0x01	  /* Bayer format */
+#define	  COM7_PBAYER	  0x05	  /* "Processed bayer" */
+#define REG_COM8	0x13	/* Control 8 */
+#define   COM8_FASTAEC	  0x80	  /* Enable fast AGC/AEC */
+#define   COM8_AECSTEP	  0x40	  /* Unlimited AEC step size */
+#define   COM8_BFILT	  0x20	  /* Band filter enable */
+#define   COM8_AGC	  0x04	  /* Auto gain enable */
+#define   COM8_AWB	  0x02	  /* White balance enable */
+#define   COM8_AEC	  0x01	  /* Auto exposure enable */
+#define REG_COM9	0x14	/* Control 9  - gain ceiling */
+#define REG_COM10	0x15	/* Control 10 */
+#define   COM10_HSYNC	  0x40	  /* HSYNC instead of HREF */
+#define   COM10_PCLK_HB	  0x20	  /* Suppress PCLK on horiz blank */
+#define   COM10_HREF_REV  0x08	  /* Reverse HREF */
+#define   COM10_VS_LEAD	  0x04	  /* VSYNC on clock leading edge */
+#define   COM10_VS_NEG	  0x02	  /* VSYNC negative */
+#define   COM10_HS_NEG	  0x01	  /* HSYNC negative */
+#define REG_HSTART	0x17	/* Horiz start high bits */
+#define REG_HSTOP	0x18	/* Horiz stop high bits */
+#define REG_VSTART	0x19	/* Vert start high bits */
+#define REG_VSTOP	0x1a	/* Vert stop high bits */
+#define REG_PSHFT	0x1b	/* Pixel delay after HREF */
+#define REG_MIDH	0x1c	/* Manuf. ID high */
+#define REG_MIDL	0x1d	/* Manuf. ID low */
+#define REG_MVFP	0x1e	/* Mirror / vflip */
+#define   MVFP_MIRROR	  0x20	  /* Mirror image */
+#define   MVFP_FLIP	  0x10	  /* Vertical flip */
+
+#define REG_AEW		0x24	/* AGC upper limit */
+#define REG_AEB		0x25	/* AGC lower limit */
+#define REG_VPT		0x26	/* AGC/AEC fast mode op region */
+#define REG_HSYST	0x30	/* HSYNC rising edge delay */
+#define REG_HSYEN	0x31	/* HSYNC falling edge delay */
+#define REG_HREF	0x32	/* HREF pieces */
+#define REG_TSLB	0x3a	/* lots of stuff */
+#define   TSLB_YLAST	  0x04	  /* UYVY or VYUY - see com13 */
+#define REG_COM11	0x3b	/* Control 11 */
+#define   COM11_NIGHT	  0x80	  /* NIght mode enable */
+#define   COM11_NMFR	  0x60	  /* Two bit NM frame rate */
+#define   COM11_HZAUTO	  0x10	  /* Auto detect 50/60 Hz */
+#define	  COM11_50HZ	  0x08	  /* Manual 50Hz select */
+#define   COM11_EXP	  0x02
+#define REG_COM12	0x3c	/* Control 12 */
+#define   COM12_HREF	  0x80	  /* HREF always */
+#define REG_COM13	0x3d	/* Control 13 */
+#define   COM13_GAMMA	  0x80	  /* Gamma enable */
+#define	  COM13_UVSAT	  0x40	  /* UV saturation auto adjustment */
+#define   COM13_UVSWAP	  0x01	  /* V before U - w/TSLB */
+#define REG_COM14	0x3e	/* Control 14 */
+#define   COM14_DCWEN	  0x10	  /* DCW/PCLK-scale enable */
+#define REG_EDGE	0x3f	/* Edge enhancement factor */
+#define REG_COM15	0x40	/* Control 15 */
+#define   COM15_R10F0	  0x00	  /* Data range 10 to F0 */
+#define	  COM15_R01FE	  0x80	  /*            01 to FE */
+#define   COM15_R00FF	  0xc0	  /*            00 to FF */
+#define   COM15_RGB565	  0x10	  /* RGB565 output */
+#define   COM15_RGB555	  0x30	  /* RGB555 output */
+#define REG_COM16	0x41	/* Control 16 */
+#define   COM16_AWBGAIN   0x08	  /* AWB gain enable */
+#define REG_COM17	0x42	/* Control 17 */
+#define   COM17_AECWIN	  0xc0	  /* AEC window - must match COM4 */
+#define   COM17_CBAR	  0x08	  /* DSP Color bar */
+
+/*
+ * This matrix defines how the colors are generated, must be
+ * tweaked to adjust hue and saturation.
+ *
+ * Order: v-red, v-green, v-blue, u-red, u-green, u-blue
+ *
+ * They are nine-bit signed quantities, with the sign bit
+ * stored in 0x58.  Sign for v-red is bit 0, and up from there.
+ */
+#define	REG_CMATRIX_BASE 0x4f
+#define   CMATRIX_LEN 6
+#define REG_CMATRIX_SIGN 0x58
+
+
+#define REG_BRIGHT	0x55	/* Brightness */
+#define REG_CONTRAS	0x56	/* Contrast control */
+
+#define REG_GFIX	0x69	/* Fix gain control */
+
+#define REG_REG76	0x76	/* OV's name */
+#define   R76_BLKPCOR	  0x80	  /* Black pixel correction enable */
+#define   R76_WHTPCOR	  0x40	  /* White pixel correction enable */
+
+#define REG_RGB444	0x8c	/* RGB 444 control */
+#define   R444_ENABLE	  0x02	  /* Turn on RGB444, overrides 5x5 */
+#define   R444_RGBX	  0x01	  /* Empty nibble at end */
+
+#define REG_HAECC1	0x9f	/* Hist AEC/AGC control 1 */
+#define REG_HAECC2	0xa0	/* Hist AEC/AGC control 2 */
+
+#define REG_BD50MAX	0xa5	/* 50hz banding step limit */
+#define REG_HAECC3	0xa6	/* Hist AEC/AGC control 3 */
+#define REG_HAECC4	0xa7	/* Hist AEC/AGC control 4 */
+#define REG_HAECC5	0xa8	/* Hist AEC/AGC control 5 */
+#define REG_HAECC6	0xa9	/* Hist AEC/AGC control 6 */
+#define REG_HAECC7	0xaa	/* Hist AEC/AGC control 7 */
+#define REG_BD60MAX	0xab	/* 60hz banding step limit */
+
+
+/*
+ * Information we maintain about a known sensor.
+ */
+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 */
+	int min_width;			/* Filter out smaller sizes */
+	int min_height;			/* Filter out smaller sizes */
+	int clock_speed;		/* External clock speed (MHz) */
+	u8 clkrc;			/* Clock divider value */
+	bool use_smbus;			/* Use smbus I/O instead of I2C */
+};
+
+static inline struct ov7670_info *to_state(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct ov7670_info, sd);
+}
+
+
+
+/*
+ * The default register settings, as obtained from OmniVision.  There
+ * is really no making sense of most of these - lots of "reserved" values
+ * and such.
+ *
+ * These settings give VGA YUYV.
+ */
+
+struct regval_list {
+	unsigned char reg_num;
+	unsigned char value;
+};
+
+static struct regval_list ov7670_default_regs[] = {
+	{ REG_COM7, COM7_RESET },
+/*
+ * Clock scale: 3 = 15fps
+ *              2 = 20fps
+ *              1 = 30fps
+ */
+	{ REG_CLKRC, 0x1 },	/* OV: clock scale (30 fps) */
+	{ REG_TSLB,  0x04 },	/* OV */
+	{ REG_COM7, 0 },	/* VGA */
+	/*
+	 * Set the hardware window.  These values from OV don't entirely
+	 * make sense - hstop is less than hstart.  But they work...
+	 */
+	{ REG_HSTART, 0x13 },	{ REG_HSTOP, 0x01 },
+	{ REG_HREF, 0xb6 },	{ REG_VSTART, 0x02 },
+	{ REG_VSTOP, 0x7a },	{ REG_VREF, 0x0a },
+
+	{ REG_COM3, 0 },	{ REG_COM14, 0 },
+	/* Mystery scaling numbers */
+	{ 0x70, 0x3a },		{ 0x71, 0x35 },
+	{ 0x72, 0x11 },		{ 0x73, 0xf0 },
+	{ 0xa2, 0x02 },		{ REG_COM10, 0x0 },
+
+	/* Gamma curve values */
+	{ 0x7a, 0x20 },		{ 0x7b, 0x10 },
+	{ 0x7c, 0x1e },		{ 0x7d, 0x35 },
+	{ 0x7e, 0x5a },		{ 0x7f, 0x69 },
+	{ 0x80, 0x76 },		{ 0x81, 0x80 },
+	{ 0x82, 0x88 },		{ 0x83, 0x8f },
+	{ 0x84, 0x96 },		{ 0x85, 0xa3 },
+	{ 0x86, 0xaf },		{ 0x87, 0xc4 },
+	{ 0x88, 0xd7 },		{ 0x89, 0xe8 },
+
+	/* AGC and AEC parameters.  Note we start by disabling those features,
+	   then turn them only after tweaking the values. */
+	{ REG_COM8, COM8_FASTAEC | COM8_AECSTEP | COM8_BFILT },
+	{ REG_GAIN, 0 },	{ REG_AECH, 0 },
+	{ REG_COM4, 0x40 }, /* magic reserved bit */
+	{ REG_COM9, 0x18 }, /* 4x gain + magic rsvd bit */
+	{ REG_BD50MAX, 0x05 },	{ REG_BD60MAX, 0x07 },
+	{ REG_AEW, 0x95 },	{ REG_AEB, 0x33 },
+	{ REG_VPT, 0xe3 },	{ REG_HAECC1, 0x78 },
+	{ REG_HAECC2, 0x68 },	{ 0xa1, 0x03 }, /* magic */
+	{ REG_HAECC3, 0xd8 },	{ REG_HAECC4, 0xd8 },
+	{ REG_HAECC5, 0xf0 },	{ REG_HAECC6, 0x90 },
+	{ REG_HAECC7, 0x94 },
+	{ REG_COM8, COM8_FASTAEC|COM8_AECSTEP|COM8_BFILT|COM8_AGC|COM8_AEC },
+
+	/* Almost all of these are magic "reserved" values.  */
+	{ REG_COM5, 0x61 },	{ REG_COM6, 0x4b },
+	{ 0x16, 0x02 },		{ REG_MVFP, 0x07 },
+	{ 0x21, 0x02 },		{ 0x22, 0x91 },
+	{ 0x29, 0x07 },		{ 0x33, 0x0b },
+	{ 0x35, 0x0b },		{ 0x37, 0x1d },
+	{ 0x38, 0x71 },		{ 0x39, 0x2a },
+	{ REG_COM12, 0x78 },	{ 0x4d, 0x40 },
+	{ 0x4e, 0x20 },		{ REG_GFIX, 0 },
+	{ 0x6b, 0x4a },		{ 0x74, 0x10 },
+	{ 0x8d, 0x4f },		{ 0x8e, 0 },
+	{ 0x8f, 0 },		{ 0x90, 0 },
+	{ 0x91, 0 },		{ 0x96, 0 },
+	{ 0x9a, 0 },		{ 0xb0, 0x84 },
+	{ 0xb1, 0x0c },		{ 0xb2, 0x0e },
+	{ 0xb3, 0x82 },		{ 0xb8, 0x0a },
+
+	/* More reserved magic, some of which tweaks white balance */
+	{ 0x43, 0x0a },		{ 0x44, 0xf0 },
+	{ 0x45, 0x34 },		{ 0x46, 0x58 },
+	{ 0x47, 0x28 },		{ 0x48, 0x3a },
+	{ 0x59, 0x88 },		{ 0x5a, 0x88 },
+	{ 0x5b, 0x44 },		{ 0x5c, 0x67 },
+	{ 0x5d, 0x49 },		{ 0x5e, 0x0e },
+	{ 0x6c, 0x0a },		{ 0x6d, 0x55 },
+	{ 0x6e, 0x11 },		{ 0x6f, 0x9f }, /* "9e for advance AWB" */
+	{ 0x6a, 0x40 },		{ REG_BLUE, 0x40 },
+	{ REG_RED, 0x60 },
+	{ REG_COM8, COM8_FASTAEC|COM8_AECSTEP|COM8_BFILT|COM8_AGC|COM8_AEC|COM8_AWB },
+
+	/* Matrix coefficients */
+	{ 0x4f, 0x80 },		{ 0x50, 0x80 },
+	{ 0x51, 0 },		{ 0x52, 0x22 },
+	{ 0x53, 0x5e },		{ 0x54, 0x80 },
+	{ 0x58, 0x9e },
+
+	{ REG_COM16, COM16_AWBGAIN },	{ REG_EDGE, 0 },
+	{ 0x75, 0x05 },		{ 0x76, 0xe1 },
+	{ 0x4c, 0 },		{ 0x77, 0x01 },
+	{ REG_COM13, 0xc3 },	{ 0x4b, 0x09 },
+	{ 0xc9, 0x60 },		{ REG_COM16, 0x38 },
+	{ 0x56, 0x40 },
+
+	{ 0x34, 0x11 },		{ REG_COM11, COM11_EXP|COM11_HZAUTO },
+	{ 0xa4, 0x88 },		{ 0x96, 0 },
+	{ 0x97, 0x30 },		{ 0x98, 0x20 },
+	{ 0x99, 0x30 },		{ 0x9a, 0x84 },
+	{ 0x9b, 0x29 },		{ 0x9c, 0x03 },
+	{ 0x9d, 0x4c },		{ 0x9e, 0x3f },
+	{ 0x78, 0x04 },
+
+	/* Extra-weird stuff.  Some sort of multiplexor register */
+	{ 0x79, 0x01 },		{ 0xc8, 0xf0 },
+	{ 0x79, 0x0f },		{ 0xc8, 0x00 },
+	{ 0x79, 0x10 },		{ 0xc8, 0x7e },
+	{ 0x79, 0x0a },		{ 0xc8, 0x80 },
+	{ 0x79, 0x0b },		{ 0xc8, 0x01 },
+	{ 0x79, 0x0c },		{ 0xc8, 0x0f },
+	{ 0x79, 0x0d },		{ 0xc8, 0x20 },
+	{ 0x79, 0x09 },		{ 0xc8, 0x80 },
+	{ 0x79, 0x02 },		{ 0xc8, 0xc0 },
+	{ 0x79, 0x03 },		{ 0xc8, 0x40 },
+	{ 0x79, 0x05 },		{ 0xc8, 0x30 },
+	{ 0x79, 0x26 },
+
+	{ 0xff, 0xff },	/* END MARKER */
+};
+
+
+/*
+ * Here we'll try to encapsulate the changes for just the output
+ * video format.
+ *
+ * RGB656 and YUV422 come from OV; RGB444 is homebrewed.
+ *
+ * IMPORTANT RULE: the first entry must be for COM7, see ov7670_s_fmt for why.
+ */
+
+
+static struct regval_list ov7670_fmt_yuv422[] = {
+	{ REG_COM7, 0x0 },  /* Selects YUV mode */
+	{ REG_RGB444, 0 },	/* No RGB444 please */
+	{ REG_COM1, 0 },	/* CCIR601 */
+	{ REG_COM15, COM15_R00FF },
+	{ REG_COM9, 0x18 }, /* 4x gain ceiling; 0x8 is reserved bit */
+	{ 0x4f, 0x80 }, 	/* "matrix coefficient 1" */
+	{ 0x50, 0x80 }, 	/* "matrix coefficient 2" */
+	{ 0x51, 0    },		/* vb */
+	{ 0x52, 0x22 }, 	/* "matrix coefficient 4" */
+	{ 0x53, 0x5e }, 	/* "matrix coefficient 5" */
+	{ 0x54, 0x80 }, 	/* "matrix coefficient 6" */
+	{ REG_COM13, COM13_GAMMA|COM13_UVSAT },
+	{ 0xff, 0xff },
+};
+
+static struct regval_list ov7670_fmt_rgb565[] = {
+	{ REG_COM7, COM7_RGB },	/* Selects RGB mode */
+	{ REG_RGB444, 0 },	/* No RGB444 please */
+	{ REG_COM1, 0x0 },	/* CCIR601 */
+	{ REG_COM15, COM15_RGB565 },
+	{ REG_COM9, 0x38 }, 	/* 16x gain ceiling; 0x8 is reserved bit */
+	{ 0x4f, 0xb3 }, 	/* "matrix coefficient 1" */
+	{ 0x50, 0xb3 }, 	/* "matrix coefficient 2" */
+	{ 0x51, 0    },		/* vb */
+	{ 0x52, 0x3d }, 	/* "matrix coefficient 4" */
+	{ 0x53, 0xa7 }, 	/* "matrix coefficient 5" */
+	{ 0x54, 0xe4 }, 	/* "matrix coefficient 6" */
+	{ REG_COM13, COM13_GAMMA|COM13_UVSAT },
+	{ 0xff, 0xff },
+};
+
+static struct regval_list ov7670_fmt_rgb444[] = {
+	{ REG_COM7, COM7_RGB },	/* Selects RGB mode */
+	{ REG_RGB444, R444_ENABLE },	/* Enable xxxxrrrr ggggbbbb */
+	{ REG_COM1, 0x0 },	/* CCIR601 */
+	{ REG_COM15, COM15_R01FE|COM15_RGB565 }, /* Data range needed? */
+	{ REG_COM9, 0x38 }, 	/* 16x gain ceiling; 0x8 is reserved bit */
+	{ 0x4f, 0xb3 }, 	/* "matrix coefficient 1" */
+	{ 0x50, 0xb3 }, 	/* "matrix coefficient 2" */
+	{ 0x51, 0    },		/* vb */
+	{ 0x52, 0x3d }, 	/* "matrix coefficient 4" */
+	{ 0x53, 0xa7 }, 	/* "matrix coefficient 5" */
+	{ 0x54, 0xe4 }, 	/* "matrix coefficient 6" */
+	{ REG_COM13, COM13_GAMMA|COM13_UVSAT|0x2 },  /* Magic rsvd bit */
+	{ 0xff, 0xff },
+};
+
+static struct regval_list ov7670_fmt_raw[] = {
+	{ REG_COM7, COM7_BAYER },
+	{ REG_COM13, 0x08 }, /* No gamma, magic rsvd bit */
+	{ REG_COM16, 0x3d }, /* Edge enhancement, denoise */
+	{ REG_REG76, 0xe1 }, /* Pix correction, magic rsvd */
+	{ 0xff, 0xff },
+};
+
+
+
+/*
+ * Low-level register I/O.
+ *
+ * Note that there are two versions of these.  On the XO 1, the
+ * i2c controller only does SMBUS, so that's what we use.  The
+ * ov7670 is not really an SMBUS device, though, so the communication
+ * is not always entirely reliable.
+ */
+static int ov7670_read_smbus(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(client, reg);
+	if (ret >= 0) {
+		*value = (unsigned char)ret;
+		ret = 0;
+	}
+	return ret;
+}
+
+
+static int ov7670_write_smbus(struct v4l2_subdev *sd, unsigned char reg,
+		unsigned char 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(5);  /* Wait for reset to run */
+	return ret;
+}
+
+/*
+ * On most platforms, we'd rather do straight i2c I/O.
+ */
+static int ov7670_read_i2c(struct v4l2_subdev *sd, unsigned char reg,
+		unsigned char *value)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	u8 data = reg;
+	struct i2c_msg msg;
+	int ret;
+
+	/*
+	 * Send out the register address...
+	 */
+	msg.addr = client->addr;
+	msg.flags = 0;
+	msg.len = 1;
+	msg.buf = &data;
+	ret = i2c_transfer(client->adapter, &msg, 1);
+	if (ret < 0) {
+		printk(KERN_ERR "Error %d on register write\n", ret);
+		return ret;
+	}
+	/*
+	 * ...then read back the result.
+	 */
+	msg.flags = I2C_M_RD;
+	ret = i2c_transfer(client->adapter, &msg, 1);
+	if (ret >= 0) {
+		*value = data;
+		ret = 0;
+	}
+	return ret;
+}
+
+
+static int ov7670_write_i2c(struct v4l2_subdev *sd, unsigned char reg,
+		unsigned char value)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct i2c_msg msg;
+	unsigned char data[2] = { reg, value };
+	int ret;
+
+	msg.addr = client->addr;
+	msg.flags = 0;
+	msg.len = 2;
+	msg.buf = data;
+	ret = i2c_transfer(client->adapter, &msg, 1);
+	if (ret > 0)
+		ret = 0;
+	if (reg == REG_COM7 && (value & COM7_RESET))
+		msleep(5);  /* Wait for reset to run */
+	return ret;
+}
+
+static int ov7670_read(struct v4l2_subdev *sd, unsigned char reg,
+		unsigned char *value)
+{
+	struct ov7670_info *info = to_state(sd);
+	if (info->use_smbus)
+		return ov7670_read_smbus(sd, reg, value);
+	else
+		return ov7670_read_i2c(sd, reg, value);
+}
+
+static int ov7670_write(struct v4l2_subdev *sd, unsigned char reg,
+		unsigned char value)
+{
+	struct ov7670_info *info = to_state(sd);
+	if (info->use_smbus)
+		return ov7670_write_smbus(sd, reg, value);
+	else
+		return ov7670_write_i2c(sd, reg, value);
+}
+
+/*
+ * Write a list of register settings; ff/ff stops the process.
+ */
+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(sd, vals->reg_num, vals->value);
+		if (ret < 0)
+			return ret;
+		vals++;
+	}
+	return 0;
+}
+
+
+/*
+ * Stuff that knows about the sensor.
+ */
+static int ov7670_reset(struct v4l2_subdev *sd, u32 val)
+{
+	ov7670_write(sd, REG_COM7, COM7_RESET);
+	msleep(1);
+	return 0;
+}
+
+
+static int ov7670_init(struct v4l2_subdev *sd, u32 val)
+{
+	return ov7670_write_array(sd, ov7670_default_regs);
+}
+
+
+
+static int ov7670_detect(struct v4l2_subdev *sd)
+{
+	unsigned char v;
+	int ret;
+
+	ret = ov7670_init(sd, 0);
+	if (ret < 0)
+		return ret;
+	ret = ov7670_read(sd, REG_MIDH, &v);
+	if (ret < 0)
+		return ret;
+	if (v != 0x7f) /* OV manuf. id. */
+		return -ENODEV;
+	ret = ov7670_read(sd, REG_MIDL, &v);
+	if (ret < 0)
+		return ret;
+	if (v != 0xa2)
+		return -ENODEV;
+	/*
+	 * OK, we know we have an OmniVision chip...but which one?
+	 */
+	ret = ov7670_read(sd, REG_PID, &v);
+	if (ret < 0)
+		return ret;
+	if (v != 0x76)  /* PID + VER = 0x76 / 0x73 */
+		return -ENODEV;
+	ret = ov7670_read(sd, REG_VER, &v);
+	if (ret < 0)
+		return ret;
+	if (v != 0x73)  /* PID + VER = 0x76 / 0x73 */
+		return -ENODEV;
+	return 0;
+}
+
+
+/*
+ * Store information about the video data format.  The color matrix
+ * is deeply tied into the format, so keep the relevant values here.
+ * The magic matrix numbers come from OmniVision.
+ */
+static struct ov7670_format_struct {
+	enum v4l2_mbus_pixelcode mbus_code;
+	enum v4l2_colorspace colorspace;
+	struct regval_list *regs;
+	int cmatrix[CMATRIX_LEN];
+} ov7670_formats[] = {
+	{
+		.mbus_code	= V4L2_MBUS_FMT_YUYV8_2X8,
+		.colorspace	= V4L2_COLORSPACE_JPEG,
+		.regs 		= ov7670_fmt_yuv422,
+		.cmatrix	= { 128, -128, 0, -34, -94, 128 },
+	},
+	{
+		.mbus_code	= V4L2_MBUS_FMT_RGB444_2X8_PADHI_LE,
+		.colorspace	= V4L2_COLORSPACE_SRGB,
+		.regs		= ov7670_fmt_rgb444,
+		.cmatrix	= { 179, -179, 0, -61, -176, 228 },
+	},
+	{
+		.mbus_code	= V4L2_MBUS_FMT_RGB565_2X8_LE,
+		.colorspace	= V4L2_COLORSPACE_SRGB,
+		.regs		= ov7670_fmt_rgb565,
+		.cmatrix	= { 179, -179, 0, -61, -176, 228 },
+	},
+	{
+		.mbus_code	= V4L2_MBUS_FMT_SBGGR8_1X8,
+		.colorspace	= V4L2_COLORSPACE_SRGB,
+		.regs 		= ov7670_fmt_raw,
+		.cmatrix	= { 0, 0, 0, 0, 0, 0 },
+	},
+};
+#define N_OV7670_FMTS ARRAY_SIZE(ov7670_formats)
+
+
+/*
+ * Then there is the issue of window sizes.  Try to capture the info here.
+ */
+
+/*
+ * QCIF mode is done (by OV) in a very strange way - it actually looks like
+ * VGA with weird scaling options - they do *not* use the canned QCIF mode
+ * which is allegedly provided by the sensor.  So here's the weird register
+ * settings.
+ */
+static struct regval_list ov7670_qcif_regs[] = {
+	{ REG_COM3, COM3_SCALEEN|COM3_DCWEN },
+	{ REG_COM3, COM3_DCWEN },
+	{ REG_COM14, COM14_DCWEN | 0x01},
+	{ 0x73, 0xf1 },
+	{ 0xa2, 0x52 },
+	{ 0x7b, 0x1c },
+	{ 0x7c, 0x28 },
+	{ 0x7d, 0x3c },
+	{ 0x7f, 0x69 },
+	{ REG_COM9, 0x38 },
+	{ 0xa1, 0x0b },
+	{ 0x74, 0x19 },
+	{ 0x9a, 0x80 },
+	{ 0x43, 0x14 },
+	{ REG_COM13, 0xc0 },
+	{ 0xff, 0xff },
+};
+
+static struct ov7670_win_size {
+	int	width;
+	int	height;
+	unsigned char com7_bit;
+	int	hstart;		/* Start/stop values for the camera.  Note */
+	int	hstop;		/* that they do not always make complete */
+	int	vstart;		/* sense to humans, but evidently the sensor */
+	int	vstop;		/* will do the right thing... */
+	struct regval_list *regs; /* Regs to tweak */
+/* h/vref stuff */
+} ov7670_win_sizes[] = {
+	/* VGA */
+	{
+		.width		= VGA_WIDTH,
+		.height		= VGA_HEIGHT,
+		.com7_bit	= COM7_FMT_VGA,
+		.hstart		= 158,		/* These values from */
+		.hstop		=  14,		/* Omnivision */
+		.vstart		=  10,
+		.vstop		= 490,
+		.regs 		= NULL,
+	},
+	/* CIF */
+	{
+		.width		= CIF_WIDTH,
+		.height		= CIF_HEIGHT,
+		.com7_bit	= COM7_FMT_CIF,
+		.hstart		= 170,		/* Empirically determined */
+		.hstop		=  90,
+		.vstart		=  14,
+		.vstop		= 494,
+		.regs 		= NULL,
+	},
+	/* QVGA */
+	{
+		.width		= QVGA_WIDTH,
+		.height		= QVGA_HEIGHT,
+		.com7_bit	= COM7_FMT_QVGA,
+		.hstart		= 168,		/* Empirically determined */
+		.hstop		=  24,
+		.vstart		=  12,
+		.vstop		= 492,
+		.regs 		= NULL,
+	},
+	/* QCIF */
+	{
+		.width		= QCIF_WIDTH,
+		.height		= QCIF_HEIGHT,
+		.com7_bit	= COM7_FMT_VGA, /* see comment above */
+		.hstart		= 456,		/* Empirically determined */
+		.hstop		=  24,
+		.vstart		=  14,
+		.vstop		= 494,
+		.regs 		= ov7670_qcif_regs,
+	},
+};
+
+#define N_WIN_SIZES (ARRAY_SIZE(ov7670_win_sizes))
+
+
+/*
+ * Store a set of start/stop values into the camera.
+ */
+static int ov7670_set_hw(struct v4l2_subdev *sd, int hstart, int hstop,
+		int vstart, int vstop)
+{
+	int ret;
+	unsigned char v;
+/*
+ * Horizontal: 11 bits, top 8 live in hstart and hstop.  Bottom 3 of
+ * 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(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(sd, REG_HREF, v);
+/*
+ * Vertical: similar arrangement, but only 10 bits.
+ */
+	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(sd, REG_VREF, v);
+	return ret;
+}
+
+
+static int ov7670_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index,
+					enum v4l2_mbus_pixelcode *code)
+{
+	if (index >= N_OV7670_FMTS)
+		return -EINVAL;
+
+	*code = ov7670_formats[index].mbus_code;
+	return 0;
+}
+
+static int ov7670_try_fmt_internal(struct v4l2_subdev *sd,
+		struct v4l2_mbus_framefmt *fmt,
+		struct ov7670_format_struct **ret_fmt,
+		struct ov7670_win_size **ret_wsize)
+{
+	int index;
+	struct ov7670_win_size *wsize;
+
+	for (index = 0; index < N_OV7670_FMTS; index++)
+		if (ov7670_formats[index].mbus_code == fmt->code)
+			break;
+	if (index >= N_OV7670_FMTS) {
+		/* default to first format */
+		index = 0;
+		fmt->code = ov7670_formats[0].mbus_code;
+	}
+	if (ret_fmt != NULL)
+		*ret_fmt = ov7670_formats + index;
+	/*
+	 * Fields: the OV devices claim to be progressive.
+	 */
+	fmt->field = V4L2_FIELD_NONE;
+	/*
+	 * Round requested image size down to the nearest
+	 * we support, but not below the smallest.
+	 */
+	for (wsize = ov7670_win_sizes; wsize < ov7670_win_sizes + N_WIN_SIZES;
+	     wsize++)
+		if (fmt->width >= wsize->width && fmt->height >= wsize->height)
+			break;
+	if (wsize >= ov7670_win_sizes + N_WIN_SIZES)
+		wsize--;   /* Take the smallest one */
+	if (ret_wsize != NULL)
+		*ret_wsize = wsize;
+	/*
+	 * Note the size we'll actually handle.
+	 */
+	fmt->width = wsize->width;
+	fmt->height = wsize->height;
+	fmt->colorspace = ov7670_formats[index].colorspace;
+	return 0;
+}
+
+static int ov7670_try_mbus_fmt(struct v4l2_subdev *sd,
+			    struct v4l2_mbus_framefmt *fmt)
+{
+	return ov7670_try_fmt_internal(sd, fmt, NULL, NULL);
+}
+
+/*
+ * Set a format.
+ */
+static int ov7670_s_mbus_fmt(struct v4l2_subdev *sd,
+			  struct v4l2_mbus_framefmt *fmt)
+{
+	struct ov7670_format_struct *ovfmt;
+	struct ov7670_win_size *wsize;
+	struct ov7670_info *info = to_state(sd);
+	unsigned char com7;
+	int ret;
+
+	ret = ov7670_try_fmt_internal(sd, fmt, &ovfmt, &wsize);
+
+	if (ret)
+		return ret;
+	/*
+	 * COM7 is a pain in the ass, it doesn't like to be read then
+	 * quickly written afterward.  But we have everything we need
+	 * to set it absolutely here, as long as the format-specific
+	 * register sets list it first.
+	 */
+	com7 = ovfmt->regs[0].value;
+	com7 |= wsize->com7_bit;
+	ov7670_write(sd, REG_COM7, com7);
+	/*
+	 * Now write the rest of the array.  Also store start/stops
+	 */
+	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(sd, wsize->regs);
+	info->fmt = ovfmt;
+
+	/*
+	 * If we're running RGB565, we must rewrite clkrc after setting
+	 * the other parameters or the image looks poor.  If we're *not*
+	 * doing RGB565, we must not rewrite clkrc or the image looks
+	 * *really* poor.
+	 *
+	 * (Update) Now that we retain clkrc state, we should be able
+	 * to write it unconditionally, and that will make the frame
+	 * rate persistent too.
+	 */
+	if (ret == 0)
+		ret = ov7670_write(sd, REG_CLKRC, info->clkrc);
+	return 0;
+}
+
+/*
+ * 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 v4l2_subdev *sd, struct v4l2_streamparm *parms)
+{
+	struct v4l2_captureparm *cp = &parms->parm.capture;
+	struct ov7670_info *info = to_state(sd);
+
+	if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
+	memset(cp, 0, sizeof(struct v4l2_captureparm));
+	cp->capability = V4L2_CAP_TIMEPERFRAME;
+	cp->timeperframe.numerator = 1;
+	cp->timeperframe.denominator = info->clock_speed;
+	if ((info->clkrc & CLK_EXT) == 0 && (info->clkrc & CLK_SCALE) > 1)
+		cp->timeperframe.denominator /= (info->clkrc & CLK_SCALE);
+	return 0;
+}
+
+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;
+	struct ov7670_info *info = to_state(sd);
+	int div;
+
+	if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+	if (cp->extendedmode != 0)
+		return -EINVAL;
+
+	if (tpf->numerator == 0 || tpf->denominator == 0)
+		div = 1;  /* Reset to full rate */
+	else
+		div = (tpf->numerator * info->clock_speed) / tpf->denominator;
+	if (div == 0)
+		div = 1;
+	else if (div > CLK_SCALE)
+		div = CLK_SCALE;
+	info->clkrc = (info->clkrc & 0x80) | div;
+	tpf->numerator = 1;
+	tpf->denominator = info->clock_speed / div;
+	return ov7670_write(sd, REG_CLKRC, info->clkrc);
+}
+
+
+/*
+ * Frame intervals.  Since frame rates are controlled with the clock
+ * divider, we can only do 30/n for integer n values.  So no continuous
+ * or stepwise options.  Here we just pick a handful of logical values.
+ */
+
+static int ov7670_frame_rates[] = { 30, 15, 10, 5, 1 };
+
+static int ov7670_enum_frameintervals(struct v4l2_subdev *sd,
+		struct v4l2_frmivalenum *interval)
+{
+	if (interval->index >= ARRAY_SIZE(ov7670_frame_rates))
+		return -EINVAL;
+	interval->type = V4L2_FRMIVAL_TYPE_DISCRETE;
+	interval->discrete.numerator = 1;
+	interval->discrete.denominator = ov7670_frame_rates[interval->index];
+	return 0;
+}
+
+/*
+ * Frame size enumeration
+ */
+static int ov7670_enum_framesizes(struct v4l2_subdev *sd,
+		struct v4l2_frmsizeenum *fsize)
+{
+	struct ov7670_info *info = to_state(sd);
+	int i;
+	int num_valid = -1;
+	__u32 index = fsize->index;
+
+	/*
+	 * If a minimum width/height was requested, filter out the capture
+	 * windows that fall outside that.
+	 */
+	for (i = 0; i < N_WIN_SIZES; i++) {
+		struct ov7670_win_size *win = &ov7670_win_sizes[index];
+		if (info->min_width && win->width < info->min_width)
+			continue;
+		if (info->min_height && win->height < info->min_height)
+			continue;
+		if (index == ++num_valid) {
+			fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
+			fsize->discrete.width = win->width;
+			fsize->discrete.height = win->height;
+			return 0;
+		}
+	}
+
+	return -EINVAL;
+}
+
+/*
+ * Code for dealing with controls.
+ */
+
+static int ov7670_store_cmatrix(struct v4l2_subdev *sd,
+		int matrix[CMATRIX_LEN])
+{
+	int i, ret;
+	unsigned char signbits = 0;
+
+	/*
+	 * Weird crap seems to exist in the upper part of
+	 * the sign bits register, so let's preserve it.
+	 */
+	ret = ov7670_read(sd, REG_CMATRIX_SIGN, &signbits);
+	signbits &= 0xc0;
+
+	for (i = 0; i < CMATRIX_LEN; i++) {
+		unsigned char raw;
+
+		if (matrix[i] < 0) {
+			signbits |= (1 << i);
+			if (matrix[i] < -255)
+				raw = 0xff;
+			else
+				raw = (-1 * matrix[i]) & 0xff;
+		}
+		else {
+			if (matrix[i] > 255)
+				raw = 0xff;
+			else
+				raw = matrix[i] & 0xff;
+		}
+		ret += ov7670_write(sd, REG_CMATRIX_BASE + i, raw);
+	}
+	ret += ov7670_write(sd, REG_CMATRIX_SIGN, signbits);
+	return ret;
+}
+
+
+/*
+ * Hue also requires messing with the color matrix.  It also requires
+ * trig functions, which tend not to be well supported in the kernel.
+ * So here is a simple table of sine values, 0-90 degrees, in steps
+ * of five degrees.  Values are multiplied by 1000.
+ *
+ * The following naive approximate trig functions require an argument
+ * carefully limited to -180 <= theta <= 180.
+ */
+#define SIN_STEP 5
+static const int ov7670_sin_table[] = {
+	   0,	 87,   173,   258,   342,   422,
+	 499,	573,   642,   707,   766,   819,
+	 866,	906,   939,   965,   984,   996,
+	1000
+};
+
+static int ov7670_sine(int theta)
+{
+	int chs = 1;
+	int sine;
+
+	if (theta < 0) {
+		theta = -theta;
+		chs = -1;
+	}
+	if (theta <= 90)
+		sine = ov7670_sin_table[theta/SIN_STEP];
+	else {
+		theta -= 90;
+		sine = 1000 - ov7670_sin_table[theta/SIN_STEP];
+	}
+	return sine*chs;
+}
+
+static int ov7670_cosine(int theta)
+{
+	theta = 90 - theta;
+	if (theta > 180)
+		theta -= 360;
+	else if (theta < -180)
+		theta += 360;
+	return ov7670_sine(theta);
+}
+
+
+
+
+static void ov7670_calc_cmatrix(struct ov7670_info *info,
+		int matrix[CMATRIX_LEN])
+{
+	int i;
+	/*
+	 * Apply the current saturation setting first.
+	 */
+	for (i = 0; i < CMATRIX_LEN; i++)
+		matrix[i] = (info->fmt->cmatrix[i]*info->sat) >> 7;
+	/*
+	 * Then, if need be, rotate the hue value.
+	 */
+	if (info->hue != 0) {
+		int sinth, costh, tmpmatrix[CMATRIX_LEN];
+
+		memcpy(tmpmatrix, matrix, CMATRIX_LEN*sizeof(int));
+		sinth = ov7670_sine(info->hue);
+		costh = ov7670_cosine(info->hue);
+
+		matrix[0] = (matrix[3]*sinth + matrix[0]*costh)/1000;
+		matrix[1] = (matrix[4]*sinth + matrix[1]*costh)/1000;
+		matrix[2] = (matrix[5]*sinth + matrix[2]*costh)/1000;
+		matrix[3] = (matrix[3]*costh - matrix[0]*sinth)/1000;
+		matrix[4] = (matrix[4]*costh - matrix[1]*sinth)/1000;
+		matrix[5] = (matrix[5]*costh - matrix[2]*sinth)/1000;
+	}
+}
+
+
+
+static int ov7670_s_sat(struct v4l2_subdev *sd, int value)
+{
+	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(sd, matrix);
+	return ret;
+}
+
+static int ov7670_g_sat(struct v4l2_subdev *sd, __s32 *value)
+{
+	struct ov7670_info *info = to_state(sd);
+
+	*value = info->sat;
+	return 0;
+}
+
+static int ov7670_s_hue(struct v4l2_subdev *sd, int value)
+{
+	struct ov7670_info *info = to_state(sd);
+	int matrix[CMATRIX_LEN];
+	int ret;
+
+	if (value < -180 || value > 180)
+		return -EINVAL;
+	info->hue = value;
+	ov7670_calc_cmatrix(info, matrix);
+	ret = ov7670_store_cmatrix(sd, matrix);
+	return ret;
+}
+
+
+static int ov7670_g_hue(struct v4l2_subdev *sd, __s32 *value)
+{
+	struct ov7670_info *info = to_state(sd);
+
+	*value = info->hue;
+	return 0;
+}
+
+
+/*
+ * Some weird registers seem to store values in a sign/magnitude format!
+ */
+static unsigned char ov7670_sm_to_abs(unsigned char v)
+{
+	if ((v & 0x80) == 0)
+		return v + 128;
+	return 128 - (v & 0x7f);
+}
+
+
+static unsigned char ov7670_abs_to_sm(unsigned char v)
+{
+	if (v > 127)
+		return v & 0x7f;
+	return (128 - v) | 0x80;
+}
+
+static int ov7670_s_brightness(struct v4l2_subdev *sd, int value)
+{
+	unsigned char com8 = 0, v;
+	int ret;
+
+	ov7670_read(sd, REG_COM8, &com8);
+	com8 &= ~COM8_AEC;
+	ov7670_write(sd, REG_COM8, com8);
+	v = ov7670_abs_to_sm(value);
+	ret = ov7670_write(sd, REG_BRIGHT, v);
+	return ret;
+}
+
+static int ov7670_g_brightness(struct v4l2_subdev *sd, __s32 *value)
+{
+	unsigned char v = 0;
+	int ret = ov7670_read(sd, REG_BRIGHT, &v);
+
+	*value = ov7670_sm_to_abs(v);
+	return ret;
+}
+
+static int ov7670_s_contrast(struct v4l2_subdev *sd, int value)
+{
+	return ov7670_write(sd, REG_CONTRAS, (unsigned char) value);
+}
+
+static int ov7670_g_contrast(struct v4l2_subdev *sd, __s32 *value)
+{
+	unsigned char v = 0;
+	int ret = ov7670_read(sd, REG_CONTRAS, &v);
+
+	*value = v;
+	return ret;
+}
+
+static int ov7670_g_hflip(struct v4l2_subdev *sd, __s32 *value)
+{
+	int ret;
+	unsigned char v = 0;
+
+	ret = ov7670_read(sd, REG_MVFP, &v);
+	*value = (v & MVFP_MIRROR) == MVFP_MIRROR;
+	return ret;
+}
+
+
+static int ov7670_s_hflip(struct v4l2_subdev *sd, int value)
+{
+	unsigned char v = 0;
+	int ret;
+
+	ret = ov7670_read(sd, REG_MVFP, &v);
+	if (value)
+		v |= MVFP_MIRROR;
+	else
+		v &= ~MVFP_MIRROR;
+	msleep(10);  /* FIXME */
+	ret += ov7670_write(sd, REG_MVFP, v);
+	return ret;
+}
+
+
+
+static int ov7670_g_vflip(struct v4l2_subdev *sd, __s32 *value)
+{
+	int ret;
+	unsigned char v = 0;
+
+	ret = ov7670_read(sd, REG_MVFP, &v);
+	*value = (v & MVFP_FLIP) == MVFP_FLIP;
+	return ret;
+}
+
+
+static int ov7670_s_vflip(struct v4l2_subdev *sd, int value)
+{
+	unsigned char v = 0;
+	int ret;
+
+	ret = ov7670_read(sd, REG_MVFP, &v);
+	if (value)
+		v |= MVFP_FLIP;
+	else
+		v &= ~MVFP_FLIP;
+	msleep(10);  /* FIXME */
+	ret += ov7670_write(sd, REG_MVFP, v);
+	return ret;
+}
+
+/*
+ * GAIN is split between REG_GAIN and REG_VREF[7:6].  If one believes
+ * the data sheet, the VREF parts should be the most significant, but
+ * experience shows otherwise.  There seems to be little value in
+ * messing with the VREF bits, so we leave them alone.
+ */
+static int ov7670_g_gain(struct v4l2_subdev *sd, __s32 *value)
+{
+	int ret;
+	unsigned char gain;
+
+	ret = ov7670_read(sd, REG_GAIN, &gain);
+	*value = gain;
+	return ret;
+}
+
+static int ov7670_s_gain(struct v4l2_subdev *sd, int value)
+{
+	int ret;
+	unsigned char com8;
+
+	ret = ov7670_write(sd, REG_GAIN, value & 0xff);
+	/* Have to turn off AGC as well */
+	if (ret == 0) {
+		ret = ov7670_read(sd, REG_COM8, &com8);
+		ret = ov7670_write(sd, REG_COM8, com8 & ~COM8_AGC);
+	}
+	return ret;
+}
+
+/*
+ * Tweak autogain.
+ */
+static int ov7670_g_autogain(struct v4l2_subdev *sd, __s32 *value)
+{
+	int ret;
+	unsigned char com8;
+
+	ret = ov7670_read(sd, REG_COM8, &com8);
+	*value = (com8 & COM8_AGC) != 0;
+	return ret;
+}
+
+static int ov7670_s_autogain(struct v4l2_subdev *sd, int value)
+{
+	int ret;
+	unsigned char com8;
+
+	ret = ov7670_read(sd, REG_COM8, &com8);
+	if (ret == 0) {
+		if (value)
+			com8 |= COM8_AGC;
+		else
+			com8 &= ~COM8_AGC;
+		ret = ov7670_write(sd, REG_COM8, com8);
+	}
+	return ret;
+}
+
+/*
+ * Exposure is spread all over the place: top 6 bits in AECHH, middle
+ * 8 in AECH, and two stashed in COM1 just for the hell of it.
+ */
+static int ov7670_g_exp(struct v4l2_subdev *sd, __s32 *value)
+{
+	int ret;
+	unsigned char com1, aech, aechh;
+
+	ret = ov7670_read(sd, REG_COM1, &com1) +
+		ov7670_read(sd, REG_AECH, &aech) +
+		ov7670_read(sd, REG_AECHH, &aechh);
+	*value = ((aechh & 0x3f) << 10) | (aech << 2) | (com1 & 0x03);
+	return ret;
+}
+
+static int ov7670_s_exp(struct v4l2_subdev *sd, int value)
+{
+	int ret;
+	unsigned char com1, com8, aech, aechh;
+
+	ret = ov7670_read(sd, REG_COM1, &com1) +
+		ov7670_read(sd, REG_COM8, &com8);
+		ov7670_read(sd, REG_AECHH, &aechh);
+	if (ret)
+		return ret;
+
+	com1 = (com1 & 0xfc) | (value & 0x03);
+	aech = (value >> 2) & 0xff;
+	aechh = (aechh & 0xc0) | ((value >> 10) & 0x3f);
+	ret = ov7670_write(sd, REG_COM1, com1) +
+		ov7670_write(sd, REG_AECH, aech) +
+		ov7670_write(sd, REG_AECHH, aechh);
+	/* Have to turn off AEC as well */
+	if (ret == 0)
+		ret = ov7670_write(sd, REG_COM8, com8 & ~COM8_AEC);
+	return ret;
+}
+
+/*
+ * Tweak autoexposure.
+ */
+static int ov7670_g_autoexp(struct v4l2_subdev *sd, __s32 *value)
+{
+	int ret;
+	unsigned char com8;
+	enum v4l2_exposure_auto_type *atype = (enum v4l2_exposure_auto_type *) value;
+
+	ret = ov7670_read(sd, REG_COM8, &com8);
+	if (com8 & COM8_AEC)
+		*atype = V4L2_EXPOSURE_AUTO;
+	else
+		*atype = V4L2_EXPOSURE_MANUAL;
+	return ret;
+}
+
+static int ov7670_s_autoexp(struct v4l2_subdev *sd,
+		enum v4l2_exposure_auto_type value)
+{
+	int ret;
+	unsigned char com8;
+
+	ret = ov7670_read(sd, REG_COM8, &com8);
+	if (ret == 0) {
+		if (value == V4L2_EXPOSURE_AUTO)
+			com8 |= COM8_AEC;
+		else
+			com8 &= ~COM8_AEC;
+		ret = ov7670_write(sd, REG_COM8, com8);
+	}
+	return ret;
+}
+
+
+
+static int ov7670_queryctrl(struct v4l2_subdev *sd,
+		struct v4l2_queryctrl *qc)
+{
+	/* 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);
+	case V4L2_CID_GAIN:
+		return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128);
+	case V4L2_CID_AUTOGAIN:
+		return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1);
+	case V4L2_CID_EXPOSURE:
+		return v4l2_ctrl_query_fill(qc, 0, 65535, 1, 500);
+	case V4L2_CID_EXPOSURE_AUTO:
+		return v4l2_ctrl_query_fill(qc, 0, 1, 1, 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);
+	case V4L2_CID_GAIN:
+		return ov7670_g_gain(sd, &ctrl->value);
+	case V4L2_CID_AUTOGAIN:
+		return ov7670_g_autogain(sd, &ctrl->value);
+	case V4L2_CID_EXPOSURE:
+		return ov7670_g_exp(sd, &ctrl->value);
+	case V4L2_CID_EXPOSURE_AUTO:
+		return ov7670_g_autoexp(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);
+	case V4L2_CID_GAIN:
+		return ov7670_s_gain(sd, ctrl->value);
+	case V4L2_CID_AUTOGAIN:
+		return ov7670_s_autogain(sd, ctrl->value);
+	case V4L2_CID_EXPOSURE:
+		return ov7670_s_exp(sd, ctrl->value);
+	case V4L2_CID_EXPOSURE_AUTO:
+		return ov7670_s_autoexp(sd,
+				(enum v4l2_exposure_auto_type) ctrl->value);
+	}
+	return -EINVAL;
+}
+
+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_mbus_fmt = ov7670_enum_mbus_fmt,
+	.try_mbus_fmt = ov7670_try_mbus_fmt,
+	.s_mbus_fmt = ov7670_s_mbus_fmt,
+	.s_parm = ov7670_s_parm,
+	.g_parm = ov7670_g_parm,
+	.enum_frameintervals = ov7670_enum_frameintervals,
+	.enum_framesizes = ov7670_enum_framesizes,
+};
+
+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)
+{
+	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);
+
+	info->clock_speed = 30; /* default: a guess */
+	if (client->dev.platform_data) {
+		struct ov7670_config *config = client->dev.platform_data;
+
+		/*
+		 * Must apply configuration before initializing device, because it
+		 * selects I/O method.
+		 */
+		info->min_width = config->min_width;
+		info->min_height = config->min_height;
+		info->use_smbus = config->use_smbus;
+
+		if (config->clock_speed)
+			info->clock_speed = config->clock_speed;
+	}
+
+	/* 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 */
+	info->clkrc = info->clock_speed / 30;
+	return 0;
+}
+
+
+static int ov7670_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+
+	v4l2_device_unregister_subdev(sd);
+	kfree(to_state(sd));
+	return 0;
+}
+
+static const struct i2c_device_id ov7670_id[] = {
+	{ "ov7670", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, ov7670_id);
+
+static struct i2c_driver ov7670_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "ov7670",
+	},
+	.probe		= ov7670_probe,
+	.remove		= ov7670_remove,
+	.id_table	= ov7670_id,
+};
+
+module_i2c_driver(ov7670_driver);
diff --git a/drivers/media/i2c/s5k6aa.c b/drivers/media/i2c/s5k6aa.c
new file mode 100644
index 0000000..045ca7f
--- /dev/null
+++ b/drivers/media/i2c/s5k6aa.c
@@ -0,0 +1,1667 @@
+/*
+ * Driver for Samsung S5K6AAFX SXGA 1/6" 1.3M CMOS Image Sensor
+ * with embedded SoC ISP.
+ *
+ * Copyright (C) 2011, Samsung Electronics Co., Ltd.
+ * Sylwester Nawrocki <s.nawrocki@samsung.com>
+ *
+ * Based on a driver authored by Dongsoo Nathaniel Kim.
+ * Copyright (C) 2009, Dongsoo Nathaniel Kim <dongsoo45.kim@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/media.h>
+#include <linux/module.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+
+#include <media/media-entity.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+#include <media/v4l2-mediabus.h>
+#include <media/s5k6aa.h>
+
+static int debug;
+module_param(debug, int, 0644);
+
+#define DRIVER_NAME			"S5K6AA"
+
+/* The token to indicate array termination */
+#define S5K6AA_TERM			0xffff
+#define S5K6AA_OUT_WIDTH_DEF		640
+#define S5K6AA_OUT_HEIGHT_DEF		480
+#define S5K6AA_WIN_WIDTH_MAX		1280
+#define S5K6AA_WIN_HEIGHT_MAX		1024
+#define S5K6AA_WIN_WIDTH_MIN		8
+#define S5K6AA_WIN_HEIGHT_MIN		8
+
+/*
+ * H/W register Interface (0xD0000000 - 0xD0000FFF)
+ */
+#define AHB_MSB_ADDR_PTR		0xfcfc
+#define GEN_REG_OFFSH			0xd000
+#define REG_CMDWR_ADDRH			0x0028
+#define REG_CMDWR_ADDRL			0x002a
+#define REG_CMDRD_ADDRH			0x002c
+#define REG_CMDRD_ADDRL			0x002e
+#define REG_CMDBUF0_ADDR		0x0f12
+#define REG_CMDBUF1_ADDR		0x0f10
+
+/*
+ * Host S/W Register interface (0x70000000 - 0x70002000)
+ * The value of the two most significant address bytes is 0x7000,
+ * (HOST_SWIF_OFFS_H). The register addresses below specify 2 LSBs.
+ */
+#define HOST_SWIF_OFFSH			0x7000
+
+/* Initialization parameters */
+/* Master clock frequency in KHz */
+#define REG_I_INCLK_FREQ_L		0x01b8
+#define REG_I_INCLK_FREQ_H		0x01ba
+#define  MIN_MCLK_FREQ_KHZ		6000U
+#define  MAX_MCLK_FREQ_KHZ		27000U
+#define REG_I_USE_NPVI_CLOCKS		0x01c6
+#define REG_I_USE_NMIPI_CLOCKS		0x01c8
+
+/* Clock configurations, n = 0..2. REG_I_* frequency unit is 4 kHz. */
+#define REG_I_OPCLK_4KHZ(n)		((n) * 6 + 0x01cc)
+#define REG_I_MIN_OUTRATE_4KHZ(n)	((n) * 6 + 0x01ce)
+#define REG_I_MAX_OUTRATE_4KHZ(n)	((n) * 6 + 0x01d0)
+#define  SYS_PLL_OUT_FREQ		(48000000 / 4000)
+#define  PCLK_FREQ_MIN			(24000000 / 4000)
+#define  PCLK_FREQ_MAX			(48000000 / 4000)
+#define REG_I_INIT_PARAMS_UPDATED	0x01e0
+#define REG_I_ERROR_INFO		0x01e2
+
+/* General purpose parameters */
+#define REG_USER_BRIGHTNESS		0x01e4
+#define REG_USER_CONTRAST		0x01e6
+#define REG_USER_SATURATION		0x01e8
+#define REG_USER_SHARPBLUR		0x01ea
+
+#define REG_G_SPEC_EFFECTS		0x01ee
+#define REG_G_ENABLE_PREV		0x01f0
+#define REG_G_ENABLE_PREV_CHG		0x01f2
+#define REG_G_NEW_CFG_SYNC		0x01f8
+#define REG_G_PREVZOOM_IN_WIDTH		0x020a
+#define REG_G_PREVZOOM_IN_HEIGHT	0x020c
+#define REG_G_PREVZOOM_IN_XOFFS		0x020e
+#define REG_G_PREVZOOM_IN_YOFFS		0x0210
+#define REG_G_INPUTS_CHANGE_REQ		0x021a
+#define REG_G_ACTIVE_PREV_CFG		0x021c
+#define REG_G_PREV_CFG_CHG		0x021e
+#define REG_G_PREV_OPEN_AFTER_CH	0x0220
+#define REG_G_PREV_CFG_ERROR		0x0222
+
+/* Preview control section. n = 0...4. */
+#define PREG(n, x)			((n) * 0x26 + x)
+#define REG_P_OUT_WIDTH(n)		PREG(n, 0x0242)
+#define REG_P_OUT_HEIGHT(n)		PREG(n, 0x0244)
+#define REG_P_FMT(n)			PREG(n, 0x0246)
+#define REG_P_MAX_OUT_RATE(n)		PREG(n, 0x0248)
+#define REG_P_MIN_OUT_RATE(n)		PREG(n, 0x024a)
+#define REG_P_PVI_MASK(n)		PREG(n, 0x024c)
+#define REG_P_CLK_INDEX(n)		PREG(n, 0x024e)
+#define REG_P_FR_RATE_TYPE(n)		PREG(n, 0x0250)
+#define  FR_RATE_DYNAMIC		0
+#define  FR_RATE_FIXED			1
+#define  FR_RATE_FIXED_ACCURATE		2
+#define REG_P_FR_RATE_Q_TYPE(n)		PREG(n, 0x0252)
+#define  FR_RATE_Q_BEST_FRRATE		1 /* Binning enabled */
+#define  FR_RATE_Q_BEST_QUALITY		2 /* Binning disabled */
+/* Frame period in 0.1 ms units */
+#define REG_P_MAX_FR_TIME(n)		PREG(n, 0x0254)
+#define REG_P_MIN_FR_TIME(n)		PREG(n, 0x0256)
+/* Conversion to REG_P_[MAX/MIN]_FR_TIME value; __t: time in us */
+#define  US_TO_FR_TIME(__t)		((__t) / 100)
+#define  S5K6AA_MIN_FR_TIME		33300  /* us */
+#define  S5K6AA_MAX_FR_TIME		650000 /* us */
+#define  S5K6AA_MAX_HIGHRES_FR_TIME	666    /* x100 us */
+/* The below 5 registers are for "device correction" values */
+#define REG_P_COLORTEMP(n)		PREG(n, 0x025e)
+#define REG_P_PREV_MIRROR(n)		PREG(n, 0x0262)
+
+/* Extended image property controls */
+/* Exposure time in 10 us units */
+#define REG_SF_USR_EXPOSURE_L		0x03c6
+#define REG_SF_USR_EXPOSURE_H		0x03c8
+#define REG_SF_USR_EXPOSURE_CHG		0x03ca
+#define REG_SF_USR_TOT_GAIN		0x03cc
+#define REG_SF_USR_TOT_GAIN_CHG		0x03ce
+#define REG_SF_RGAIN			0x03d0
+#define REG_SF_RGAIN_CHG		0x03d2
+#define REG_SF_GGAIN			0x03d4
+#define REG_SF_GGAIN_CHG		0x03d6
+#define REG_SF_BGAIN			0x03d8
+#define REG_SF_BGAIN_CHG		0x03da
+#define REG_SF_FLICKER_QUANT		0x03dc
+#define REG_SF_FLICKER_QUANT_CHG	0x03de
+
+/* Output interface (parallel/MIPI) setup */
+#define REG_OIF_EN_MIPI_LANES		0x03fa
+#define REG_OIF_EN_PACKETS		0x03fc
+#define REG_OIF_CFG_CHG			0x03fe
+
+/* Auto-algorithms enable mask */
+#define REG_DBG_AUTOALG_EN		0x0400
+#define  AALG_ALL_EN_MASK		(1 << 0)
+#define  AALG_AE_EN_MASK		(1 << 1)
+#define  AALG_DIVLEI_EN_MASK		(1 << 2)
+#define  AALG_WB_EN_MASK		(1 << 3)
+#define  AALG_FLICKER_EN_MASK		(1 << 5)
+#define  AALG_FIT_EN_MASK		(1 << 6)
+#define  AALG_WRHW_EN_MASK		(1 << 7)
+
+/* Firmware revision information */
+#define REG_FW_APIVER			0x012e
+#define  S5K6AAFX_FW_APIVER		0x0001
+#define REG_FW_REVISION			0x0130
+
+/* For now we use only one user configuration register set */
+#define S5K6AA_MAX_PRESETS		1
+
+static const char * const s5k6aa_supply_names[] = {
+	"vdd_core",	/* Digital core supply 1.5V (1.4V to 1.6V) */
+	"vdda",		/* Analog power supply 2.8V (2.6V to 3.0V) */
+	"vdd_reg",	/* Regulator input power 1.8V (1.7V to 1.9V)
+			   or 2.8V (2.6V to 3.0) */
+	"vddio",	/* I/O supply 1.8V (1.65V to 1.95V)
+			   or 2.8V (2.5V to 3.1V) */
+};
+#define S5K6AA_NUM_SUPPLIES ARRAY_SIZE(s5k6aa_supply_names)
+
+enum s5k6aa_gpio_id {
+	STBY,
+	RST,
+	GPIO_NUM,
+};
+
+struct s5k6aa_regval {
+	u16 addr;
+	u16 val;
+};
+
+struct s5k6aa_pixfmt {
+	enum v4l2_mbus_pixelcode code;
+	u32 colorspace;
+	/* REG_P_FMT(x) register value */
+	u16 reg_p_fmt;
+};
+
+struct s5k6aa_preset {
+	/* output pixel format and resolution */
+	struct v4l2_mbus_framefmt mbus_fmt;
+	u8 clk_id;
+	u8 index;
+};
+
+struct s5k6aa_ctrls {
+	struct v4l2_ctrl_handler handler;
+	/* Auto / manual white balance cluster */
+	struct v4l2_ctrl *awb;
+	struct v4l2_ctrl *gain_red;
+	struct v4l2_ctrl *gain_blue;
+	struct v4l2_ctrl *gain_green;
+	/* Mirror cluster */
+	struct v4l2_ctrl *hflip;
+	struct v4l2_ctrl *vflip;
+	/* Auto exposure / manual exposure and gain cluster */
+	struct v4l2_ctrl *auto_exp;
+	struct v4l2_ctrl *exposure;
+	struct v4l2_ctrl *gain;
+};
+
+struct s5k6aa_interval {
+	u16 reg_fr_time;
+	struct v4l2_fract interval;
+	/* Maximum rectangle for the interval */
+	struct v4l2_frmsize_discrete size;
+};
+
+struct s5k6aa {
+	struct v4l2_subdev sd;
+	struct media_pad pad;
+
+	enum v4l2_mbus_type bus_type;
+	u8 mipi_lanes;
+
+	int (*s_power)(int enable);
+	struct regulator_bulk_data supplies[S5K6AA_NUM_SUPPLIES];
+	struct s5k6aa_gpio gpio[GPIO_NUM];
+
+	/* external master clock frequency */
+	unsigned long mclk_frequency;
+	/* ISP internal master clock frequency */
+	u16 clk_fop;
+	/* output pixel clock frequency range */
+	u16 pclk_fmin;
+	u16 pclk_fmax;
+
+	unsigned int inv_hflip:1;
+	unsigned int inv_vflip:1;
+
+	/* protects the struct members below */
+	struct mutex lock;
+
+	/* sensor matrix scan window */
+	struct v4l2_rect ccd_rect;
+
+	struct s5k6aa_ctrls ctrls;
+	struct s5k6aa_preset presets[S5K6AA_MAX_PRESETS];
+	struct s5k6aa_preset *preset;
+	const struct s5k6aa_interval *fiv;
+
+	unsigned int streaming:1;
+	unsigned int apply_cfg:1;
+	unsigned int apply_crop:1;
+	unsigned int power;
+};
+
+static struct s5k6aa_regval s5k6aa_analog_config[] = {
+	/* Analog settings */
+	{ 0x112a, 0x0000 }, { 0x1132, 0x0000 },
+	{ 0x113e, 0x0000 }, { 0x115c, 0x0000 },
+	{ 0x1164, 0x0000 }, { 0x1174, 0x0000 },
+	{ 0x1178, 0x0000 }, { 0x077a, 0x0000 },
+	{ 0x077c, 0x0000 }, { 0x077e, 0x0000 },
+	{ 0x0780, 0x0000 }, { 0x0782, 0x0000 },
+	{ 0x0784, 0x0000 }, { 0x0786, 0x0000 },
+	{ 0x0788, 0x0000 }, { 0x07a2, 0x0000 },
+	{ 0x07a4, 0x0000 }, { 0x07a6, 0x0000 },
+	{ 0x07a8, 0x0000 }, { 0x07b6, 0x0000 },
+	{ 0x07b8, 0x0002 }, { 0x07ba, 0x0004 },
+	{ 0x07bc, 0x0004 }, { 0x07be, 0x0005 },
+	{ 0x07c0, 0x0005 }, { S5K6AA_TERM, 0 },
+};
+
+/* TODO: Add RGB888 and Bayer format */
+static const struct s5k6aa_pixfmt s5k6aa_formats[] = {
+	{ V4L2_MBUS_FMT_YUYV8_2X8,	V4L2_COLORSPACE_JPEG,	5 },
+	/* range 16-240 */
+	{ V4L2_MBUS_FMT_YUYV8_2X8,	V4L2_COLORSPACE_REC709,	6 },
+	{ V4L2_MBUS_FMT_RGB565_2X8_BE,	V4L2_COLORSPACE_JPEG,	0 },
+};
+
+static const struct s5k6aa_interval s5k6aa_intervals[] = {
+	{ 1000, {10000, 1000000}, {1280, 1024} }, /* 10 fps */
+	{ 666,  {15000, 1000000}, {1280, 1024} }, /* 15 fps */
+	{ 500,  {20000, 1000000}, {1280, 720} },  /* 20 fps */
+	{ 400,  {25000, 1000000}, {640, 480} },   /* 25 fps */
+	{ 333,  {33300, 1000000}, {640, 480} },   /* 30 fps */
+};
+
+#define S5K6AA_INTERVAL_DEF_INDEX 1 /* 15 fps */
+
+static inline struct v4l2_subdev *ctrl_to_sd(struct v4l2_ctrl *ctrl)
+{
+	return &container_of(ctrl->handler, struct s5k6aa, ctrls.handler)->sd;
+}
+
+static inline struct s5k6aa *to_s5k6aa(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct s5k6aa, sd);
+}
+
+/* Set initial values for all preview presets */
+static void s5k6aa_presets_data_init(struct s5k6aa *s5k6aa)
+{
+	struct s5k6aa_preset *preset = &s5k6aa->presets[0];
+	int i;
+
+	for (i = 0; i < S5K6AA_MAX_PRESETS; i++) {
+		preset->mbus_fmt.width	= S5K6AA_OUT_WIDTH_DEF;
+		preset->mbus_fmt.height	= S5K6AA_OUT_HEIGHT_DEF;
+		preset->mbus_fmt.code	= s5k6aa_formats[0].code;
+		preset->index		= i;
+		preset->clk_id		= 0;
+		preset++;
+	}
+
+	s5k6aa->fiv = &s5k6aa_intervals[S5K6AA_INTERVAL_DEF_INDEX];
+	s5k6aa->preset = &s5k6aa->presets[0];
+}
+
+static int s5k6aa_i2c_read(struct i2c_client *client, u16 addr, u16 *val)
+{
+	u8 wbuf[2] = {addr >> 8, addr & 0xFF};
+	struct i2c_msg msg[2];
+	u8 rbuf[2];
+	int ret;
+
+	msg[0].addr = client->addr;
+	msg[0].flags = 0;
+	msg[0].len = 2;
+	msg[0].buf = wbuf;
+
+	msg[1].addr = client->addr;
+	msg[1].flags = I2C_M_RD;
+	msg[1].len = 2;
+	msg[1].buf = rbuf;
+
+	ret = i2c_transfer(client->adapter, msg, 2);
+	*val = be16_to_cpu(*((u16 *)rbuf));
+
+	v4l2_dbg(3, debug, client, "i2c_read: 0x%04X : 0x%04x\n", addr, *val);
+
+	return ret == 2 ? 0 : ret;
+}
+
+static int s5k6aa_i2c_write(struct i2c_client *client, u16 addr, u16 val)
+{
+	u8 buf[4] = {addr >> 8, addr & 0xFF, val >> 8, val & 0xFF};
+
+	int ret = i2c_master_send(client, buf, 4);
+	v4l2_dbg(3, debug, client, "i2c_write: 0x%04X : 0x%04x\n", addr, val);
+
+	return ret == 4 ? 0 : ret;
+}
+
+/* The command register write, assumes Command_Wr_addH = 0x7000. */
+static int s5k6aa_write(struct i2c_client *c, u16 addr, u16 val)
+{
+	int ret = s5k6aa_i2c_write(c, REG_CMDWR_ADDRL, addr);
+	if (ret)
+		return ret;
+	return s5k6aa_i2c_write(c, REG_CMDBUF0_ADDR, val);
+}
+
+/* The command register read, assumes Command_Rd_addH = 0x7000. */
+static int s5k6aa_read(struct i2c_client *client, u16 addr, u16 *val)
+{
+	int ret = s5k6aa_i2c_write(client, REG_CMDRD_ADDRL, addr);
+	if (ret)
+		return ret;
+	return s5k6aa_i2c_read(client, REG_CMDBUF0_ADDR, val);
+}
+
+static int s5k6aa_write_array(struct v4l2_subdev *sd,
+			      const struct s5k6aa_regval *msg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	u16 addr_incr = 0;
+	int ret = 0;
+
+	while (msg->addr != S5K6AA_TERM) {
+		if (addr_incr != 2)
+			ret = s5k6aa_i2c_write(client, REG_CMDWR_ADDRL,
+					       msg->addr);
+		if (ret)
+			break;
+		ret = s5k6aa_i2c_write(client, REG_CMDBUF0_ADDR, msg->val);
+		if (ret)
+			break;
+		/* Assume that msg->addr is always less than 0xfffc */
+		addr_incr = (msg + 1)->addr - msg->addr;
+		msg++;
+	}
+
+	return ret;
+}
+
+/* Configure the AHB high address bytes for GTG registers access */
+static int s5k6aa_set_ahb_address(struct i2c_client *client)
+{
+	int ret = s5k6aa_i2c_write(client, AHB_MSB_ADDR_PTR, GEN_REG_OFFSH);
+	if (ret)
+		return ret;
+	ret = s5k6aa_i2c_write(client, REG_CMDRD_ADDRH, HOST_SWIF_OFFSH);
+	if (ret)
+		return ret;
+	return s5k6aa_i2c_write(client, REG_CMDWR_ADDRH, HOST_SWIF_OFFSH);
+}
+
+/**
+ * s5k6aa_configure_pixel_clock - apply ISP main clock/PLL configuration
+ *
+ * Configure the internal ISP PLL for the required output frequency.
+ * Locking: called with s5k6aa.lock mutex held.
+ */
+static int s5k6aa_configure_pixel_clocks(struct s5k6aa *s5k6aa)
+{
+	struct i2c_client *c = v4l2_get_subdevdata(&s5k6aa->sd);
+	unsigned long fmclk = s5k6aa->mclk_frequency / 1000;
+	u16 status;
+	int ret;
+
+	if (WARN(fmclk < MIN_MCLK_FREQ_KHZ || fmclk > MAX_MCLK_FREQ_KHZ,
+		 "Invalid clock frequency: %ld\n", fmclk))
+		return -EINVAL;
+
+	s5k6aa->pclk_fmin = PCLK_FREQ_MIN;
+	s5k6aa->pclk_fmax = PCLK_FREQ_MAX;
+	s5k6aa->clk_fop = SYS_PLL_OUT_FREQ;
+
+	/* External input clock frequency in kHz */
+	ret = s5k6aa_write(c, REG_I_INCLK_FREQ_H, fmclk >> 16);
+	if (!ret)
+		ret = s5k6aa_write(c, REG_I_INCLK_FREQ_L, fmclk & 0xFFFF);
+	if (!ret)
+		ret = s5k6aa_write(c, REG_I_USE_NPVI_CLOCKS, 1);
+	/* Internal PLL frequency */
+	if (!ret)
+		ret = s5k6aa_write(c, REG_I_OPCLK_4KHZ(0), s5k6aa->clk_fop);
+	if (!ret)
+		ret = s5k6aa_write(c, REG_I_MIN_OUTRATE_4KHZ(0),
+				   s5k6aa->pclk_fmin);
+	if (!ret)
+		ret = s5k6aa_write(c, REG_I_MAX_OUTRATE_4KHZ(0),
+				   s5k6aa->pclk_fmax);
+	if (!ret)
+		ret = s5k6aa_write(c, REG_I_INIT_PARAMS_UPDATED, 1);
+	if (!ret)
+		ret = s5k6aa_read(c, REG_I_ERROR_INFO, &status);
+
+	return ret ? ret : (status ? -EINVAL : 0);
+}
+
+/* Set horizontal and vertical image flipping */
+static int s5k6aa_set_mirror(struct s5k6aa *s5k6aa, int horiz_flip)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->sd);
+	int index = s5k6aa->preset->index;
+
+	unsigned int vflip = s5k6aa->ctrls.vflip->val ^ s5k6aa->inv_vflip;
+	unsigned int flip = (horiz_flip ^ s5k6aa->inv_hflip) | (vflip << 1);
+
+	return s5k6aa_write(client, REG_P_PREV_MIRROR(index), flip);
+}
+
+/* Configure auto/manual white balance and R/G/B gains */
+static int s5k6aa_set_awb(struct s5k6aa *s5k6aa, int awb)
+{
+	struct i2c_client *c = v4l2_get_subdevdata(&s5k6aa->sd);
+	struct s5k6aa_ctrls *ctrls = &s5k6aa->ctrls;
+	u16 reg;
+
+	int ret = s5k6aa_read(c, REG_DBG_AUTOALG_EN, &reg);
+
+	if (!ret && !awb) {
+		ret = s5k6aa_write(c, REG_SF_RGAIN, ctrls->gain_red->val);
+		if (!ret)
+			ret = s5k6aa_write(c, REG_SF_RGAIN_CHG, 1);
+		if (ret)
+			return ret;
+
+		ret = s5k6aa_write(c, REG_SF_GGAIN, ctrls->gain_green->val);
+		if (!ret)
+			ret = s5k6aa_write(c, REG_SF_GGAIN_CHG, 1);
+		if (ret)
+			return ret;
+
+		ret = s5k6aa_write(c, REG_SF_BGAIN, ctrls->gain_blue->val);
+		if (!ret)
+			ret = s5k6aa_write(c, REG_SF_BGAIN_CHG, 1);
+	}
+	if (!ret) {
+		reg = awb ? reg | AALG_WB_EN_MASK : reg & ~AALG_WB_EN_MASK;
+		ret = s5k6aa_write(c, REG_DBG_AUTOALG_EN, reg);
+	}
+
+	return ret;
+}
+
+/* Program FW with exposure time, 'exposure' in us units */
+static int s5k6aa_set_user_exposure(struct i2c_client *client, int exposure)
+{
+	unsigned int time = exposure / 10;
+
+	int ret = s5k6aa_write(client, REG_SF_USR_EXPOSURE_L, time & 0xffff);
+	if (!ret)
+		ret = s5k6aa_write(client, REG_SF_USR_EXPOSURE_H, time >> 16);
+	if (ret)
+		return ret;
+	return s5k6aa_write(client, REG_SF_USR_EXPOSURE_CHG, 1);
+}
+
+static int s5k6aa_set_user_gain(struct i2c_client *client, int gain)
+{
+	int ret = s5k6aa_write(client, REG_SF_USR_TOT_GAIN, gain);
+	if (ret)
+		return ret;
+	return s5k6aa_write(client, REG_SF_USR_TOT_GAIN_CHG, 1);
+}
+
+/* Set auto/manual exposure and total gain */
+static int s5k6aa_set_auto_exposure(struct s5k6aa *s5k6aa, int value)
+{
+	struct i2c_client *c = v4l2_get_subdevdata(&s5k6aa->sd);
+	unsigned int exp_time = s5k6aa->ctrls.exposure->val;
+	u16 auto_alg;
+
+	int ret = s5k6aa_read(c, REG_DBG_AUTOALG_EN, &auto_alg);
+	if (ret)
+		return ret;
+
+	v4l2_dbg(1, debug, c, "man_exp: %d, auto_exp: %d, a_alg: 0x%x\n",
+		 exp_time, value, auto_alg);
+
+	if (value == V4L2_EXPOSURE_AUTO) {
+		auto_alg |= AALG_AE_EN_MASK | AALG_DIVLEI_EN_MASK;
+	} else {
+		ret = s5k6aa_set_user_exposure(c, exp_time);
+		if (ret)
+			return ret;
+		ret = s5k6aa_set_user_gain(c, s5k6aa->ctrls.gain->val);
+		if (ret)
+			return ret;
+		auto_alg &= ~(AALG_AE_EN_MASK | AALG_DIVLEI_EN_MASK);
+	}
+
+	return s5k6aa_write(c, REG_DBG_AUTOALG_EN, auto_alg);
+}
+
+static int s5k6aa_set_anti_flicker(struct s5k6aa *s5k6aa, int value)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->sd);
+	u16 auto_alg;
+	int ret;
+
+	ret = s5k6aa_read(client, REG_DBG_AUTOALG_EN, &auto_alg);
+	if (ret)
+		return ret;
+
+	if (value == V4L2_CID_POWER_LINE_FREQUENCY_AUTO) {
+		auto_alg |= AALG_FLICKER_EN_MASK;
+	} else {
+		auto_alg &= ~AALG_FLICKER_EN_MASK;
+		/* The V4L2_CID_LINE_FREQUENCY control values match
+		 * the register values */
+		ret = s5k6aa_write(client, REG_SF_FLICKER_QUANT, value);
+		if (ret)
+			return ret;
+		ret = s5k6aa_write(client, REG_SF_FLICKER_QUANT_CHG, 1);
+		if (ret)
+			return ret;
+	}
+
+	return s5k6aa_write(client, REG_DBG_AUTOALG_EN, auto_alg);
+}
+
+static int s5k6aa_set_colorfx(struct s5k6aa *s5k6aa, int val)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->sd);
+	static const struct v4l2_control colorfx[] = {
+		{ V4L2_COLORFX_NONE,	 0 },
+		{ V4L2_COLORFX_BW,	 1 },
+		{ V4L2_COLORFX_NEGATIVE, 2 },
+		{ V4L2_COLORFX_SEPIA,	 3 },
+		{ V4L2_COLORFX_SKY_BLUE, 4 },
+		{ V4L2_COLORFX_SKETCH,	 5 },
+	};
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(colorfx); i++) {
+		if (colorfx[i].id == val)
+			return s5k6aa_write(client, REG_G_SPEC_EFFECTS,
+					    colorfx[i].value);
+	}
+	return -EINVAL;
+}
+
+static int s5k6aa_preview_config_status(struct i2c_client *client)
+{
+	u16 error = 0;
+	int ret = s5k6aa_read(client, REG_G_PREV_CFG_ERROR, &error);
+
+	v4l2_dbg(1, debug, client, "error: 0x%x (%d)\n", error, ret);
+	return ret ? ret : (error ? -EINVAL : 0);
+}
+
+static int s5k6aa_get_pixfmt_index(struct s5k6aa *s5k6aa,
+				   struct v4l2_mbus_framefmt *mf)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(s5k6aa_formats); i++)
+		if (mf->colorspace == s5k6aa_formats[i].colorspace &&
+		    mf->code == s5k6aa_formats[i].code)
+			return i;
+	return 0;
+}
+
+static int s5k6aa_set_output_framefmt(struct s5k6aa *s5k6aa,
+				      struct s5k6aa_preset *preset)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->sd);
+	int fmt_index = s5k6aa_get_pixfmt_index(s5k6aa, &preset->mbus_fmt);
+	int ret;
+
+	ret = s5k6aa_write(client, REG_P_OUT_WIDTH(preset->index),
+			   preset->mbus_fmt.width);
+	if (!ret)
+		ret = s5k6aa_write(client, REG_P_OUT_HEIGHT(preset->index),
+				   preset->mbus_fmt.height);
+	if (!ret)
+		ret = s5k6aa_write(client, REG_P_FMT(preset->index),
+				   s5k6aa_formats[fmt_index].reg_p_fmt);
+	return ret;
+}
+
+static int s5k6aa_set_input_params(struct s5k6aa *s5k6aa)
+{
+	struct i2c_client *c = v4l2_get_subdevdata(&s5k6aa->sd);
+	struct v4l2_rect *r = &s5k6aa->ccd_rect;
+	int ret;
+
+	ret = s5k6aa_write(c, REG_G_PREVZOOM_IN_WIDTH, r->width);
+	if (!ret)
+		ret = s5k6aa_write(c, REG_G_PREVZOOM_IN_HEIGHT, r->height);
+	if (!ret)
+		ret = s5k6aa_write(c, REG_G_PREVZOOM_IN_XOFFS, r->left);
+	if (!ret)
+		ret = s5k6aa_write(c, REG_G_PREVZOOM_IN_YOFFS, r->top);
+	if (!ret)
+		ret = s5k6aa_write(c, REG_G_INPUTS_CHANGE_REQ, 1);
+	if (!ret)
+		s5k6aa->apply_crop = 0;
+
+	return ret;
+}
+
+/**
+ * s5k6aa_configure_video_bus - configure the video output interface
+ * @bus_type: video bus type: parallel or MIPI-CSI
+ * @nlanes: number of MIPI lanes to be used (MIPI-CSI only)
+ *
+ * Note: Only parallel bus operation has been tested.
+ */
+static int s5k6aa_configure_video_bus(struct s5k6aa *s5k6aa,
+				      enum v4l2_mbus_type bus_type, int nlanes)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->sd);
+	u16 cfg = 0;
+	int ret;
+
+	/*
+	 * TODO: The sensor is supposed to support BT.601 and BT.656
+	 * but there is nothing indicating how to switch between both
+	 * in the datasheet. For now default BT.601 interface is assumed.
+	 */
+	if (bus_type == V4L2_MBUS_CSI2)
+		cfg = nlanes;
+	else if (bus_type != V4L2_MBUS_PARALLEL)
+		return -EINVAL;
+
+	ret = s5k6aa_write(client, REG_OIF_EN_MIPI_LANES, cfg);
+	if (ret)
+		return ret;
+	return s5k6aa_write(client, REG_OIF_CFG_CHG, 1);
+}
+
+/* This function should be called when switching to new user configuration set*/
+static int s5k6aa_new_config_sync(struct i2c_client *client, int timeout,
+				  int cid)
+{
+	unsigned long end = jiffies + msecs_to_jiffies(timeout);
+	u16 reg = 1;
+	int ret;
+
+	ret = s5k6aa_write(client, REG_G_ACTIVE_PREV_CFG, cid);
+	if (!ret)
+		ret = s5k6aa_write(client, REG_G_PREV_CFG_CHG, 1);
+	if (!ret)
+		ret = s5k6aa_write(client, REG_G_NEW_CFG_SYNC, 1);
+	if (timeout == 0)
+		return ret;
+
+	while (ret >= 0 && time_is_after_jiffies(end)) {
+		ret = s5k6aa_read(client, REG_G_NEW_CFG_SYNC, &reg);
+		if (!reg)
+			return 0;
+		usleep_range(1000, 5000);
+	}
+	return ret ? ret : -ETIMEDOUT;
+}
+
+/**
+ * s5k6aa_set_prev_config - write user preview register set
+ *
+ * Configure output resolution and color fromat, pixel clock
+ * frequency range, device frame rate type and frame period range.
+ */
+static int s5k6aa_set_prev_config(struct s5k6aa *s5k6aa,
+				  struct s5k6aa_preset *preset)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->sd);
+	int idx = preset->index;
+	u16 frame_rate_q;
+	int ret;
+
+	if (s5k6aa->fiv->reg_fr_time >= S5K6AA_MAX_HIGHRES_FR_TIME)
+		frame_rate_q = FR_RATE_Q_BEST_FRRATE;
+	else
+		frame_rate_q = FR_RATE_Q_BEST_QUALITY;
+
+	ret = s5k6aa_set_output_framefmt(s5k6aa, preset);
+	if (!ret)
+		ret = s5k6aa_write(client, REG_P_MAX_OUT_RATE(idx),
+				   s5k6aa->pclk_fmax);
+	if (!ret)
+		ret = s5k6aa_write(client, REG_P_MIN_OUT_RATE(idx),
+				   s5k6aa->pclk_fmin);
+	if (!ret)
+		ret = s5k6aa_write(client, REG_P_CLK_INDEX(idx),
+				   preset->clk_id);
+	if (!ret)
+		ret = s5k6aa_write(client, REG_P_FR_RATE_TYPE(idx),
+				   FR_RATE_DYNAMIC);
+	if (!ret)
+		ret = s5k6aa_write(client, REG_P_FR_RATE_Q_TYPE(idx),
+				   frame_rate_q);
+	if (!ret)
+		ret = s5k6aa_write(client, REG_P_MAX_FR_TIME(idx),
+				   s5k6aa->fiv->reg_fr_time + 33);
+	if (!ret)
+		ret = s5k6aa_write(client, REG_P_MIN_FR_TIME(idx),
+				   s5k6aa->fiv->reg_fr_time - 33);
+	if (!ret)
+		ret = s5k6aa_new_config_sync(client, 250, idx);
+	if (!ret)
+		ret = s5k6aa_preview_config_status(client);
+	if (!ret)
+		s5k6aa->apply_cfg = 0;
+
+	v4l2_dbg(1, debug, client, "Frame interval: %d +/- 3.3ms. (%d)\n",
+		 s5k6aa->fiv->reg_fr_time, ret);
+	return ret;
+}
+
+/**
+ * s5k6aa_initialize_isp - basic ISP MCU initialization
+ *
+ * Configure AHB addresses for registers read/write; configure PLLs for
+ * required output pixel clock. The ISP power supply needs to be already
+ * enabled, with an optional H/W reset.
+ * Locking: called with s5k6aa.lock mutex held.
+ */
+static int s5k6aa_initialize_isp(struct v4l2_subdev *sd)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct s5k6aa *s5k6aa = to_s5k6aa(sd);
+	int ret;
+
+	s5k6aa->apply_crop = 1;
+	s5k6aa->apply_cfg = 1;
+	msleep(100);
+
+	ret = s5k6aa_set_ahb_address(client);
+	if (ret)
+		return ret;
+	ret = s5k6aa_configure_video_bus(s5k6aa, s5k6aa->bus_type,
+					 s5k6aa->mipi_lanes);
+	if (ret)
+		return ret;
+	ret = s5k6aa_write_array(sd, s5k6aa_analog_config);
+	if (ret)
+		return ret;
+	msleep(20);
+
+	return s5k6aa_configure_pixel_clocks(s5k6aa);
+}
+
+static int s5k6aa_gpio_set_value(struct s5k6aa *priv, int id, u32 val)
+{
+	if (!gpio_is_valid(priv->gpio[id].gpio))
+		return 0;
+	gpio_set_value(priv->gpio[id].gpio, !!val);
+	return 1;
+}
+
+static int s5k6aa_gpio_assert(struct s5k6aa *priv, int id)
+{
+	return s5k6aa_gpio_set_value(priv, id, priv->gpio[id].level);
+}
+
+static int s5k6aa_gpio_deassert(struct s5k6aa *priv, int id)
+{
+	return s5k6aa_gpio_set_value(priv, id, !priv->gpio[id].level);
+}
+
+static int __s5k6aa_power_on(struct s5k6aa *s5k6aa)
+{
+	int ret;
+
+	ret = regulator_bulk_enable(S5K6AA_NUM_SUPPLIES, s5k6aa->supplies);
+	if (ret)
+		return ret;
+	if (s5k6aa_gpio_deassert(s5k6aa, STBY))
+		usleep_range(150, 200);
+
+	if (s5k6aa->s_power)
+		ret = s5k6aa->s_power(1);
+	usleep_range(4000, 4000);
+
+	if (s5k6aa_gpio_deassert(s5k6aa, RST))
+		msleep(20);
+
+	return ret;
+}
+
+static int __s5k6aa_power_off(struct s5k6aa *s5k6aa)
+{
+	int ret;
+
+	if (s5k6aa_gpio_assert(s5k6aa, RST))
+		usleep_range(100, 150);
+
+	if (s5k6aa->s_power) {
+		ret = s5k6aa->s_power(0);
+		if (ret)
+			return ret;
+	}
+	if (s5k6aa_gpio_assert(s5k6aa, STBY))
+		usleep_range(50, 100);
+	s5k6aa->streaming = 0;
+
+	return regulator_bulk_disable(S5K6AA_NUM_SUPPLIES, s5k6aa->supplies);
+}
+
+/*
+ * V4L2 subdev core and video operations
+ */
+static int s5k6aa_set_power(struct v4l2_subdev *sd, int on)
+{
+	struct s5k6aa *s5k6aa = to_s5k6aa(sd);
+	int ret = 0;
+
+	mutex_lock(&s5k6aa->lock);
+
+	if (!on == s5k6aa->power) {
+		if (on) {
+			ret = __s5k6aa_power_on(s5k6aa);
+			if (!ret)
+				ret = s5k6aa_initialize_isp(sd);
+		} else {
+			ret = __s5k6aa_power_off(s5k6aa);
+		}
+
+		if (!ret)
+			s5k6aa->power += on ? 1 : -1;
+	}
+
+	mutex_unlock(&s5k6aa->lock);
+
+	if (!on || ret || s5k6aa->power != 1)
+		return ret;
+
+	return v4l2_ctrl_handler_setup(sd->ctrl_handler);
+}
+
+static int __s5k6aa_stream(struct s5k6aa *s5k6aa, int enable)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->sd);
+	int ret = 0;
+
+	ret = s5k6aa_write(client, REG_G_ENABLE_PREV, enable);
+	if (!ret)
+		ret = s5k6aa_write(client, REG_G_ENABLE_PREV_CHG, 1);
+	if (!ret)
+		s5k6aa->streaming = enable;
+
+	return ret;
+}
+
+static int s5k6aa_s_stream(struct v4l2_subdev *sd, int on)
+{
+	struct s5k6aa *s5k6aa = to_s5k6aa(sd);
+	int ret = 0;
+
+	mutex_lock(&s5k6aa->lock);
+
+	if (s5k6aa->streaming == !on) {
+		if (!ret && s5k6aa->apply_cfg)
+			ret = s5k6aa_set_prev_config(s5k6aa, s5k6aa->preset);
+		if (s5k6aa->apply_crop)
+			ret = s5k6aa_set_input_params(s5k6aa);
+		if (!ret)
+			ret = __s5k6aa_stream(s5k6aa, !!on);
+	}
+	mutex_unlock(&s5k6aa->lock);
+
+	return ret;
+}
+
+static int s5k6aa_g_frame_interval(struct v4l2_subdev *sd,
+				   struct v4l2_subdev_frame_interval *fi)
+{
+	struct s5k6aa *s5k6aa = to_s5k6aa(sd);
+
+	mutex_lock(&s5k6aa->lock);
+	fi->interval = s5k6aa->fiv->interval;
+	mutex_unlock(&s5k6aa->lock);
+
+	return 0;
+}
+
+static int __s5k6aa_set_frame_interval(struct s5k6aa *s5k6aa,
+				       struct v4l2_subdev_frame_interval *fi)
+{
+	struct v4l2_mbus_framefmt *mbus_fmt = &s5k6aa->preset->mbus_fmt;
+	const struct s5k6aa_interval *fiv = &s5k6aa_intervals[0];
+	unsigned int err, min_err = UINT_MAX;
+	unsigned int i, fr_time;
+
+	if (fi->interval.denominator == 0)
+		return -EINVAL;
+
+	fr_time = fi->interval.numerator * 10000 / fi->interval.denominator;
+
+	for (i = 0; i < ARRAY_SIZE(s5k6aa_intervals); i++) {
+		const struct s5k6aa_interval *iv = &s5k6aa_intervals[i];
+
+		if (mbus_fmt->width > iv->size.width ||
+		    mbus_fmt->height > iv->size.height)
+			continue;
+
+		err = abs(iv->reg_fr_time - fr_time);
+		if (err < min_err) {
+			fiv = iv;
+			min_err = err;
+		}
+	}
+	s5k6aa->fiv = fiv;
+
+	v4l2_dbg(1, debug, &s5k6aa->sd, "Changed frame interval to %d us\n",
+		 fiv->reg_fr_time * 100);
+	return 0;
+}
+
+static int s5k6aa_s_frame_interval(struct v4l2_subdev *sd,
+				   struct v4l2_subdev_frame_interval *fi)
+{
+	struct s5k6aa *s5k6aa = to_s5k6aa(sd);
+	int ret;
+
+	v4l2_dbg(1, debug, sd, "Setting %d/%d frame interval\n",
+		 fi->interval.numerator, fi->interval.denominator);
+
+	mutex_lock(&s5k6aa->lock);
+	ret = __s5k6aa_set_frame_interval(s5k6aa, fi);
+	s5k6aa->apply_cfg = 1;
+
+	mutex_unlock(&s5k6aa->lock);
+	return ret;
+}
+
+/*
+ * V4L2 subdev pad level and video operations
+ */
+static int s5k6aa_enum_frame_interval(struct v4l2_subdev *sd,
+			      struct v4l2_subdev_fh *fh,
+			      struct v4l2_subdev_frame_interval_enum *fie)
+{
+	struct s5k6aa *s5k6aa = to_s5k6aa(sd);
+	const struct s5k6aa_interval *fi;
+	int ret = 0;
+
+	if (fie->index > ARRAY_SIZE(s5k6aa_intervals))
+		return -EINVAL;
+
+	v4l_bound_align_image(&fie->width, S5K6AA_WIN_WIDTH_MIN,
+			      S5K6AA_WIN_WIDTH_MAX, 1,
+			      &fie->height, S5K6AA_WIN_HEIGHT_MIN,
+			      S5K6AA_WIN_HEIGHT_MAX, 1, 0);
+
+	mutex_lock(&s5k6aa->lock);
+	fi = &s5k6aa_intervals[fie->index];
+	if (fie->width > fi->size.width || fie->height > fi->size.height)
+		ret = -EINVAL;
+	else
+		fie->interval = fi->interval;
+	mutex_unlock(&s5k6aa->lock);
+
+	return ret;
+}
+
+static int s5k6aa_enum_mbus_code(struct v4l2_subdev *sd,
+				 struct v4l2_subdev_fh *fh,
+				 struct v4l2_subdev_mbus_code_enum *code)
+{
+	if (code->index >= ARRAY_SIZE(s5k6aa_formats))
+		return -EINVAL;
+
+	code->code = s5k6aa_formats[code->index].code;
+	return 0;
+}
+
+static int s5k6aa_enum_frame_size(struct v4l2_subdev *sd,
+				  struct v4l2_subdev_fh *fh,
+				  struct v4l2_subdev_frame_size_enum *fse)
+{
+	int i = ARRAY_SIZE(s5k6aa_formats);
+
+	if (fse->index > 0)
+		return -EINVAL;
+
+	while (--i)
+		if (fse->code == s5k6aa_formats[i].code)
+			break;
+
+	fse->code = s5k6aa_formats[i].code;
+	fse->min_width  = S5K6AA_WIN_WIDTH_MIN;
+	fse->max_width  = S5K6AA_WIN_WIDTH_MAX;
+	fse->max_height = S5K6AA_WIN_HEIGHT_MIN;
+	fse->min_height = S5K6AA_WIN_HEIGHT_MAX;
+
+	return 0;
+}
+
+static struct v4l2_rect *
+__s5k6aa_get_crop_rect(struct s5k6aa *s5k6aa, struct v4l2_subdev_fh *fh,
+		       enum v4l2_subdev_format_whence which)
+{
+	if (which == V4L2_SUBDEV_FORMAT_ACTIVE)
+		return &s5k6aa->ccd_rect;
+	if (which == V4L2_SUBDEV_FORMAT_TRY)
+		return v4l2_subdev_get_try_crop(fh, 0);
+
+	return NULL;
+}
+
+static void s5k6aa_try_format(struct s5k6aa *s5k6aa,
+			      struct v4l2_mbus_framefmt *mf)
+{
+	unsigned int index;
+
+	v4l_bound_align_image(&mf->width, S5K6AA_WIN_WIDTH_MIN,
+			      S5K6AA_WIN_WIDTH_MAX, 1,
+			      &mf->height, S5K6AA_WIN_HEIGHT_MIN,
+			      S5K6AA_WIN_HEIGHT_MAX, 1, 0);
+
+	if (mf->colorspace != V4L2_COLORSPACE_JPEG &&
+	    mf->colorspace != V4L2_COLORSPACE_REC709)
+		mf->colorspace = V4L2_COLORSPACE_JPEG;
+
+	index = s5k6aa_get_pixfmt_index(s5k6aa, mf);
+
+	mf->colorspace	= s5k6aa_formats[index].colorspace;
+	mf->code	= s5k6aa_formats[index].code;
+	mf->field	= V4L2_FIELD_NONE;
+}
+
+static int s5k6aa_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+			  struct v4l2_subdev_format *fmt)
+{
+	struct s5k6aa *s5k6aa = to_s5k6aa(sd);
+	struct v4l2_mbus_framefmt *mf;
+
+	memset(fmt->reserved, 0, sizeof(fmt->reserved));
+
+	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
+		mf = v4l2_subdev_get_try_format(fh, 0);
+		fmt->format = *mf;
+		return 0;
+	}
+
+	mutex_lock(&s5k6aa->lock);
+	fmt->format = s5k6aa->preset->mbus_fmt;
+	mutex_unlock(&s5k6aa->lock);
+
+	return 0;
+}
+
+static int s5k6aa_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+			  struct v4l2_subdev_format *fmt)
+{
+	struct s5k6aa *s5k6aa = to_s5k6aa(sd);
+	struct s5k6aa_preset *preset = s5k6aa->preset;
+	struct v4l2_mbus_framefmt *mf;
+	struct v4l2_rect *crop;
+	int ret = 0;
+
+	mutex_lock(&s5k6aa->lock);
+	s5k6aa_try_format(s5k6aa, &fmt->format);
+
+	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
+		mf = v4l2_subdev_get_try_format(fh, fmt->pad);
+		crop = v4l2_subdev_get_try_crop(fh, 0);
+	} else {
+		if (s5k6aa->streaming) {
+			ret = -EBUSY;
+		} else {
+			mf = &preset->mbus_fmt;
+			crop = &s5k6aa->ccd_rect;
+			s5k6aa->apply_cfg = 1;
+		}
+	}
+
+	if (ret == 0) {
+		struct v4l2_subdev_frame_interval fiv = {
+			.interval = {0, 1}
+		};
+
+		*mf = fmt->format;
+		/*
+		 * Make sure the crop window is valid, i.e. its size is
+		 * greater than the output window, as the ISP supports
+		 * only down-scaling.
+		 */
+		crop->width = clamp_t(unsigned int, crop->width, mf->width,
+				      S5K6AA_WIN_WIDTH_MAX);
+		crop->height = clamp_t(unsigned int, crop->height, mf->height,
+				       S5K6AA_WIN_HEIGHT_MAX);
+		crop->left = clamp_t(unsigned int, crop->left, 0,
+				     S5K6AA_WIN_WIDTH_MAX - crop->width);
+		crop->top  = clamp_t(unsigned int, crop->top, 0,
+				     S5K6AA_WIN_HEIGHT_MAX - crop->height);
+
+		/* Reset to minimum possible frame interval */
+		ret = __s5k6aa_set_frame_interval(s5k6aa, &fiv);
+	}
+	mutex_unlock(&s5k6aa->lock);
+
+	return ret;
+}
+
+static int s5k6aa_get_crop(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+			   struct v4l2_subdev_crop *crop)
+{
+	struct s5k6aa *s5k6aa = to_s5k6aa(sd);
+	struct v4l2_rect *rect;
+
+	memset(crop->reserved, 0, sizeof(crop->reserved));
+	mutex_lock(&s5k6aa->lock);
+
+	rect = __s5k6aa_get_crop_rect(s5k6aa, fh, crop->which);
+	if (rect)
+		crop->rect = *rect;
+
+	mutex_unlock(&s5k6aa->lock);
+
+	v4l2_dbg(1, debug, sd, "Current crop rectangle: (%d,%d)/%dx%d\n",
+		 rect->left, rect->top, rect->width, rect->height);
+
+	return 0;
+}
+
+static int s5k6aa_set_crop(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+			   struct v4l2_subdev_crop *crop)
+{
+	struct s5k6aa *s5k6aa = to_s5k6aa(sd);
+	struct v4l2_mbus_framefmt *mf;
+	unsigned int max_x, max_y;
+	struct v4l2_rect *crop_r;
+
+	mutex_lock(&s5k6aa->lock);
+	crop_r = __s5k6aa_get_crop_rect(s5k6aa, fh, crop->which);
+
+	if (crop->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
+		mf = &s5k6aa->preset->mbus_fmt;
+		s5k6aa->apply_crop = 1;
+	} else {
+		mf = v4l2_subdev_get_try_format(fh, 0);
+	}
+	v4l_bound_align_image(&crop->rect.width, mf->width,
+			      S5K6AA_WIN_WIDTH_MAX, 1,
+			      &crop->rect.height, mf->height,
+			      S5K6AA_WIN_HEIGHT_MAX, 1, 0);
+
+	max_x = (S5K6AA_WIN_WIDTH_MAX - crop->rect.width) & ~1;
+	max_y = (S5K6AA_WIN_HEIGHT_MAX - crop->rect.height) & ~1;
+
+	crop->rect.left = clamp_t(unsigned int, crop->rect.left, 0, max_x);
+	crop->rect.top  = clamp_t(unsigned int, crop->rect.top, 0, max_y);
+
+	*crop_r = crop->rect;
+
+	mutex_unlock(&s5k6aa->lock);
+
+	v4l2_dbg(1, debug, sd, "Set crop rectangle: (%d,%d)/%dx%d\n",
+		 crop_r->left, crop_r->top, crop_r->width, crop_r->height);
+
+	return 0;
+}
+
+static const struct v4l2_subdev_pad_ops s5k6aa_pad_ops = {
+	.enum_mbus_code		= s5k6aa_enum_mbus_code,
+	.enum_frame_size	= s5k6aa_enum_frame_size,
+	.enum_frame_interval	= s5k6aa_enum_frame_interval,
+	.get_fmt		= s5k6aa_get_fmt,
+	.set_fmt		= s5k6aa_set_fmt,
+	.get_crop		= s5k6aa_get_crop,
+	.set_crop		= s5k6aa_set_crop,
+};
+
+static const struct v4l2_subdev_video_ops s5k6aa_video_ops = {
+	.g_frame_interval	= s5k6aa_g_frame_interval,
+	.s_frame_interval	= s5k6aa_s_frame_interval,
+	.s_stream		= s5k6aa_s_stream,
+};
+
+/*
+ * V4L2 subdev controls
+ */
+
+static int s5k6aa_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct v4l2_subdev *sd = ctrl_to_sd(ctrl);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct s5k6aa *s5k6aa = to_s5k6aa(sd);
+	int idx, err = 0;
+
+	v4l2_dbg(1, debug, sd, "ctrl: 0x%x, value: %d\n", ctrl->id, ctrl->val);
+
+	mutex_lock(&s5k6aa->lock);
+	/*
+	 * If the device is not powered up by the host driver do
+	 * not apply any controls to H/W at this time. Instead
+	 * the controls will be restored right after power-up.
+	 */
+	if (s5k6aa->power == 0)
+		goto unlock;
+	idx = s5k6aa->preset->index;
+
+	switch (ctrl->id) {
+	case V4L2_CID_AUTO_WHITE_BALANCE:
+		err = s5k6aa_set_awb(s5k6aa, ctrl->val);
+		break;
+
+	case V4L2_CID_BRIGHTNESS:
+		err = s5k6aa_write(client, REG_USER_BRIGHTNESS, ctrl->val);
+		break;
+
+	case V4L2_CID_COLORFX:
+		err = s5k6aa_set_colorfx(s5k6aa, ctrl->val);
+		break;
+
+	case V4L2_CID_CONTRAST:
+		err = s5k6aa_write(client, REG_USER_CONTRAST, ctrl->val);
+		break;
+
+	case V4L2_CID_EXPOSURE_AUTO:
+		err = s5k6aa_set_auto_exposure(s5k6aa, ctrl->val);
+		break;
+
+	case V4L2_CID_HFLIP:
+		err = s5k6aa_set_mirror(s5k6aa, ctrl->val);
+		if (err)
+			break;
+		err = s5k6aa_write(client, REG_G_PREV_CFG_CHG, 1);
+		break;
+
+	case V4L2_CID_POWER_LINE_FREQUENCY:
+		err = s5k6aa_set_anti_flicker(s5k6aa, ctrl->val);
+		break;
+
+	case V4L2_CID_SATURATION:
+		err = s5k6aa_write(client, REG_USER_SATURATION, ctrl->val);
+		break;
+
+	case V4L2_CID_SHARPNESS:
+		err = s5k6aa_write(client, REG_USER_SHARPBLUR, ctrl->val);
+		break;
+
+	case V4L2_CID_WHITE_BALANCE_TEMPERATURE:
+		err = s5k6aa_write(client, REG_P_COLORTEMP(idx), ctrl->val);
+		if (err)
+			break;
+		err = s5k6aa_write(client, REG_G_PREV_CFG_CHG, 1);
+		break;
+	}
+unlock:
+	mutex_unlock(&s5k6aa->lock);
+	return err;
+}
+
+static const struct v4l2_ctrl_ops s5k6aa_ctrl_ops = {
+	.s_ctrl	= s5k6aa_s_ctrl,
+};
+
+static int s5k6aa_log_status(struct v4l2_subdev *sd)
+{
+	v4l2_ctrl_handler_log_status(sd->ctrl_handler, sd->name);
+	return 0;
+}
+
+#define V4L2_CID_RED_GAIN	(V4L2_CTRL_CLASS_CAMERA | 0x1001)
+#define V4L2_CID_GREEN_GAIN	(V4L2_CTRL_CLASS_CAMERA | 0x1002)
+#define V4L2_CID_BLUE_GAIN	(V4L2_CTRL_CLASS_CAMERA | 0x1003)
+
+static const struct v4l2_ctrl_config s5k6aa_ctrls[] = {
+	{
+		.ops	= &s5k6aa_ctrl_ops,
+		.id	= V4L2_CID_RED_GAIN,
+		.type	= V4L2_CTRL_TYPE_INTEGER,
+		.name	= "Gain, Red",
+		.min	= 0,
+		.max	= 256,
+		.def	= 127,
+		.step	= 1,
+	}, {
+		.ops	= &s5k6aa_ctrl_ops,
+		.id	= V4L2_CID_GREEN_GAIN,
+		.type	= V4L2_CTRL_TYPE_INTEGER,
+		.name	= "Gain, Green",
+		.min	= 0,
+		.max	= 256,
+		.def	= 127,
+		.step	= 1,
+	}, {
+		.ops	= &s5k6aa_ctrl_ops,
+		.id	= V4L2_CID_BLUE_GAIN,
+		.type	= V4L2_CTRL_TYPE_INTEGER,
+		.name	= "Gain, Blue",
+		.min	= 0,
+		.max	= 256,
+		.def	= 127,
+		.step	= 1,
+	},
+};
+
+static int s5k6aa_initialize_ctrls(struct s5k6aa *s5k6aa)
+{
+	const struct v4l2_ctrl_ops *ops = &s5k6aa_ctrl_ops;
+	struct s5k6aa_ctrls *ctrls = &s5k6aa->ctrls;
+	struct v4l2_ctrl_handler *hdl = &ctrls->handler;
+
+	int ret = v4l2_ctrl_handler_init(hdl, 16);
+	if (ret)
+		return ret;
+	/* Auto white balance cluster */
+	ctrls->awb = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_AUTO_WHITE_BALANCE,
+				       0, 1, 1, 1);
+	ctrls->gain_red = v4l2_ctrl_new_custom(hdl, &s5k6aa_ctrls[0], NULL);
+	ctrls->gain_green = v4l2_ctrl_new_custom(hdl, &s5k6aa_ctrls[1], NULL);
+	ctrls->gain_blue = v4l2_ctrl_new_custom(hdl, &s5k6aa_ctrls[2], NULL);
+	v4l2_ctrl_auto_cluster(4, &ctrls->awb, 0, false);
+
+	ctrls->hflip = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_HFLIP, 0, 1, 1, 0);
+	ctrls->vflip = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_VFLIP, 0, 1, 1, 0);
+	v4l2_ctrl_cluster(2, &ctrls->hflip);
+
+	ctrls->auto_exp = v4l2_ctrl_new_std_menu(hdl, ops,
+				V4L2_CID_EXPOSURE_AUTO,
+				V4L2_EXPOSURE_MANUAL, 0, V4L2_EXPOSURE_AUTO);
+	/* Exposure time: x 1 us */
+	ctrls->exposure = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_EXPOSURE,
+					    0, 6000000U, 1, 100000U);
+	/* Total gain: 256 <=> 1x */
+	ctrls->gain = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_GAIN,
+					0, 256, 1, 256);
+	v4l2_ctrl_auto_cluster(3, &ctrls->auto_exp, 0, false);
+
+	v4l2_ctrl_new_std_menu(hdl, ops, V4L2_CID_POWER_LINE_FREQUENCY,
+			       V4L2_CID_POWER_LINE_FREQUENCY_AUTO, 0,
+			       V4L2_CID_POWER_LINE_FREQUENCY_AUTO);
+
+	v4l2_ctrl_new_std_menu(hdl, ops, V4L2_CID_COLORFX,
+			       V4L2_COLORFX_SKY_BLUE, ~0x6f, V4L2_COLORFX_NONE);
+
+	v4l2_ctrl_new_std(hdl, ops, V4L2_CID_WHITE_BALANCE_TEMPERATURE,
+			  0, 256, 1, 0);
+
+	v4l2_ctrl_new_std(hdl, ops, V4L2_CID_SATURATION, -127, 127, 1, 0);
+	v4l2_ctrl_new_std(hdl, ops, V4L2_CID_BRIGHTNESS, -127, 127, 1, 0);
+	v4l2_ctrl_new_std(hdl, ops, V4L2_CID_CONTRAST, -127, 127, 1, 0);
+	v4l2_ctrl_new_std(hdl, ops, V4L2_CID_SHARPNESS, -127, 127, 1, 0);
+
+	if (hdl->error) {
+		ret = hdl->error;
+		v4l2_ctrl_handler_free(hdl);
+		return ret;
+	}
+
+	s5k6aa->sd.ctrl_handler = hdl;
+	return 0;
+}
+
+/*
+ * V4L2 subdev internal operations
+ */
+static int s5k6aa_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+	struct v4l2_mbus_framefmt *format = v4l2_subdev_get_try_format(fh, 0);
+	struct v4l2_rect *crop = v4l2_subdev_get_try_crop(fh, 0);
+
+	format->colorspace = s5k6aa_formats[0].colorspace;
+	format->code = s5k6aa_formats[0].code;
+	format->width = S5K6AA_OUT_WIDTH_DEF;
+	format->height = S5K6AA_OUT_HEIGHT_DEF;
+	format->field = V4L2_FIELD_NONE;
+
+	crop->width = S5K6AA_WIN_WIDTH_MAX;
+	crop->height = S5K6AA_WIN_HEIGHT_MAX;
+	crop->left = 0;
+	crop->top = 0;
+
+	return 0;
+}
+
+static int s5k6aa_check_fw_revision(struct s5k6aa *s5k6aa)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->sd);
+	u16 api_ver = 0, fw_rev = 0;
+
+	int ret = s5k6aa_set_ahb_address(client);
+
+	if (!ret)
+		ret = s5k6aa_read(client, REG_FW_APIVER, &api_ver);
+	if (!ret)
+		ret = s5k6aa_read(client, REG_FW_REVISION, &fw_rev);
+	if (ret) {
+		v4l2_err(&s5k6aa->sd, "FW revision check failed!\n");
+		return ret;
+	}
+
+	v4l2_info(&s5k6aa->sd, "FW API ver.: 0x%X, FW rev.: 0x%X\n",
+		  api_ver, fw_rev);
+
+	return api_ver == S5K6AAFX_FW_APIVER ? 0 : -ENODEV;
+}
+
+static int s5k6aa_registered(struct v4l2_subdev *sd)
+{
+	struct s5k6aa *s5k6aa = to_s5k6aa(sd);
+	int ret;
+
+	mutex_lock(&s5k6aa->lock);
+	ret = __s5k6aa_power_on(s5k6aa);
+	if (!ret) {
+		msleep(100);
+		ret = s5k6aa_check_fw_revision(s5k6aa);
+		__s5k6aa_power_off(s5k6aa);
+	}
+	mutex_unlock(&s5k6aa->lock);
+
+	return ret;
+}
+
+static const struct v4l2_subdev_internal_ops s5k6aa_subdev_internal_ops = {
+	.registered = s5k6aa_registered,
+	.open = s5k6aa_open,
+};
+
+static const struct v4l2_subdev_core_ops s5k6aa_core_ops = {
+	.s_power = s5k6aa_set_power,
+	.log_status = s5k6aa_log_status,
+};
+
+static const struct v4l2_subdev_ops s5k6aa_subdev_ops = {
+	.core = &s5k6aa_core_ops,
+	.pad = &s5k6aa_pad_ops,
+	.video = &s5k6aa_video_ops,
+};
+
+/*
+ * GPIO setup
+ */
+static int s5k6aa_configure_gpio(int nr, int val, const char *name)
+{
+	unsigned long flags = val ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW;
+	int ret;
+
+	if (!gpio_is_valid(nr))
+		return 0;
+	ret = gpio_request_one(nr, flags, name);
+	if (!ret)
+		gpio_export(nr, 0);
+	return ret;
+}
+
+static void s5k6aa_free_gpios(struct s5k6aa *s5k6aa)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(s5k6aa->gpio); i++) {
+		if (!gpio_is_valid(s5k6aa->gpio[i].gpio))
+			continue;
+		gpio_free(s5k6aa->gpio[i].gpio);
+		s5k6aa->gpio[i].gpio = -EINVAL;
+	}
+}
+
+static int s5k6aa_configure_gpios(struct s5k6aa *s5k6aa,
+				  const struct s5k6aa_platform_data *pdata)
+{
+	const struct s5k6aa_gpio *gpio = &pdata->gpio_stby;
+	int ret;
+
+	s5k6aa->gpio[STBY].gpio = -EINVAL;
+	s5k6aa->gpio[RST].gpio  = -EINVAL;
+
+	ret = s5k6aa_configure_gpio(gpio->gpio, gpio->level, "S5K6AA_STBY");
+	if (ret) {
+		s5k6aa_free_gpios(s5k6aa);
+		return ret;
+	}
+	s5k6aa->gpio[STBY] = *gpio;
+	if (gpio_is_valid(gpio->gpio))
+		gpio_set_value(gpio->gpio, 0);
+
+	gpio = &pdata->gpio_reset;
+	ret = s5k6aa_configure_gpio(gpio->gpio, gpio->level, "S5K6AA_RST");
+	if (ret) {
+		s5k6aa_free_gpios(s5k6aa);
+		return ret;
+	}
+	s5k6aa->gpio[RST] = *gpio;
+	if (gpio_is_valid(gpio->gpio))
+		gpio_set_value(gpio->gpio, 0);
+
+	return 0;
+}
+
+static int s5k6aa_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	const struct s5k6aa_platform_data *pdata = client->dev.platform_data;
+	struct v4l2_subdev *sd;
+	struct s5k6aa *s5k6aa;
+	int i, ret;
+
+	if (pdata == NULL) {
+		dev_err(&client->dev, "Platform data not specified\n");
+		return -EINVAL;
+	}
+
+	if (pdata->mclk_frequency == 0) {
+		dev_err(&client->dev, "MCLK frequency not specified\n");
+		return -EINVAL;
+	}
+
+	s5k6aa = devm_kzalloc(&client->dev, sizeof(*s5k6aa), GFP_KERNEL);
+	if (!s5k6aa)
+		return -ENOMEM;
+
+	mutex_init(&s5k6aa->lock);
+
+	s5k6aa->mclk_frequency = pdata->mclk_frequency;
+	s5k6aa->bus_type = pdata->bus_type;
+	s5k6aa->mipi_lanes = pdata->nlanes;
+	s5k6aa->s_power	= pdata->set_power;
+	s5k6aa->inv_hflip = pdata->horiz_flip;
+	s5k6aa->inv_vflip = pdata->vert_flip;
+
+	sd = &s5k6aa->sd;
+	v4l2_i2c_subdev_init(sd, client, &s5k6aa_subdev_ops);
+	strlcpy(sd->name, DRIVER_NAME, sizeof(sd->name));
+
+	sd->internal_ops = &s5k6aa_subdev_internal_ops;
+	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+	s5k6aa->pad.flags = MEDIA_PAD_FL_SOURCE;
+	sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR;
+	ret = media_entity_init(&sd->entity, 1, &s5k6aa->pad, 0);
+	if (ret)
+		return ret;
+
+	ret = s5k6aa_configure_gpios(s5k6aa, pdata);
+	if (ret)
+		goto out_err2;
+
+	for (i = 0; i < S5K6AA_NUM_SUPPLIES; i++)
+		s5k6aa->supplies[i].supply = s5k6aa_supply_names[i];
+
+	ret = regulator_bulk_get(&client->dev, S5K6AA_NUM_SUPPLIES,
+				 s5k6aa->supplies);
+	if (ret) {
+		dev_err(&client->dev, "Failed to get regulators\n");
+		goto out_err3;
+	}
+
+	ret = s5k6aa_initialize_ctrls(s5k6aa);
+	if (ret)
+		goto out_err4;
+
+	s5k6aa_presets_data_init(s5k6aa);
+
+	s5k6aa->ccd_rect.width = S5K6AA_WIN_WIDTH_MAX;
+	s5k6aa->ccd_rect.height	= S5K6AA_WIN_HEIGHT_MAX;
+	s5k6aa->ccd_rect.left = 0;
+	s5k6aa->ccd_rect.top = 0;
+
+	return 0;
+
+out_err4:
+	regulator_bulk_free(S5K6AA_NUM_SUPPLIES, s5k6aa->supplies);
+out_err3:
+	s5k6aa_free_gpios(s5k6aa);
+out_err2:
+	media_entity_cleanup(&s5k6aa->sd.entity);
+	return ret;
+}
+
+static int s5k6aa_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct s5k6aa *s5k6aa = to_s5k6aa(sd);
+
+	v4l2_device_unregister_subdev(sd);
+	v4l2_ctrl_handler_free(sd->ctrl_handler);
+	media_entity_cleanup(&sd->entity);
+	regulator_bulk_free(S5K6AA_NUM_SUPPLIES, s5k6aa->supplies);
+	s5k6aa_free_gpios(s5k6aa);
+
+	return 0;
+}
+
+static const struct i2c_device_id s5k6aa_id[] = {
+	{ DRIVER_NAME, 0 },
+	{ },
+};
+MODULE_DEVICE_TABLE(i2c, s5k6aa_id);
+
+
+static struct i2c_driver s5k6aa_i2c_driver = {
+	.driver = {
+		.name = DRIVER_NAME
+	},
+	.probe		= s5k6aa_probe,
+	.remove		= s5k6aa_remove,
+	.id_table	= s5k6aa_id,
+};
+
+module_i2c_driver(s5k6aa_i2c_driver);
+
+MODULE_DESCRIPTION("Samsung S5K6AA(FX) SXGA camera driver");
+MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/i2c/saa6588.c b/drivers/media/i2c/saa6588.c
new file mode 100644
index 0000000..0caac50
--- /dev/null
+++ b/drivers/media/i2c/saa6588.c
@@ -0,0 +1,542 @@
+/*
+    Driver for SAA6588 RDS decoder
+
+    (c) 2005 Hans J. Koch
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+#include <linux/types.h>
+#include <linux/videodev2.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/poll.h>
+#include <linux/wait.h>
+#include <asm/uaccess.h>
+
+#include <media/saa6588.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-chip-ident.h>
+
+
+/* insmod options */
+static unsigned int debug;
+static unsigned int xtal;
+static unsigned int mmbs;
+static unsigned int plvl;
+static unsigned int bufblocks = 100;
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "enable debug messages");
+module_param(xtal, int, 0);
+MODULE_PARM_DESC(xtal, "select oscillator frequency (0..3), default 0");
+module_param(mmbs, int, 0);
+MODULE_PARM_DESC(mmbs, "enable MMBS mode: 0=off (default), 1=on");
+module_param(plvl, int, 0);
+MODULE_PARM_DESC(plvl, "select pause level (0..3), default 0");
+module_param(bufblocks, int, 0);
+MODULE_PARM_DESC(bufblocks, "number of buffered blocks, default 100");
+
+MODULE_DESCRIPTION("v4l2 driver module for SAA6588 RDS decoder");
+MODULE_AUTHOR("Hans J. Koch <koch@hjk-az.de>");
+
+MODULE_LICENSE("GPL");
+
+/* ---------------------------------------------------------------------- */
+
+#define UNSET       (-1U)
+#define PREFIX      "saa6588: "
+#define dprintk     if (debug) printk
+
+struct saa6588 {
+	struct v4l2_subdev sd;
+	struct delayed_work work;
+	spinlock_t lock;
+	unsigned char *buffer;
+	unsigned int buf_size;
+	unsigned int rd_index;
+	unsigned int wr_index;
+	unsigned int block_count;
+	unsigned char last_blocknum;
+	wait_queue_head_t read_queue;
+	int data_available_for_read;
+	u8 sync;
+};
+
+static inline struct saa6588 *to_saa6588(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct saa6588, sd);
+}
+
+/* ---------------------------------------------------------------------- */
+
+/*
+ * SAA6588 defines
+ */
+
+/* Initialization and mode control byte (0w) */
+
+/* bit 0+1 (DAC0/DAC1) */
+#define cModeStandard           0x00
+#define cModeFastPI             0x01
+#define cModeReducedRequest     0x02
+#define cModeInvalid            0x03
+
+/* bit 2 (RBDS) */
+#define cProcessingModeRDS      0x00
+#define cProcessingModeRBDS     0x04
+
+/* bit 3+4 (SYM0/SYM1) */
+#define cErrCorrectionNone      0x00
+#define cErrCorrection2Bits     0x08
+#define cErrCorrection5Bits     0x10
+#define cErrCorrectionNoneRBDS  0x18
+
+/* bit 5 (NWSY) */
+#define cSyncNormal             0x00
+#define cSyncRestart            0x20
+
+/* bit 6 (TSQD) */
+#define cSigQualityDetectOFF    0x00
+#define cSigQualityDetectON     0x40
+
+/* bit 7 (SQCM) */
+#define cSigQualityTriggered    0x00
+#define cSigQualityContinous    0x80
+
+/* Pause level and flywheel control byte (1w) */
+
+/* bits 0..5 (FEB0..FEB5) */
+#define cFlywheelMaxBlocksMask  0x3F
+#define cFlywheelDefault        0x20
+
+/* bits 6+7 (PL0/PL1) */
+#define cPauseLevel_11mV	0x00
+#define cPauseLevel_17mV        0x40
+#define cPauseLevel_27mV        0x80
+#define cPauseLevel_43mV        0xC0
+
+/* Pause time/oscillator frequency/quality detector control byte (1w) */
+
+/* bits 0..4 (SQS0..SQS4) */
+#define cQualityDetectSensMask  0x1F
+#define cQualityDetectDefault   0x0F
+
+/* bit 5 (SOSC) */
+#define cSelectOscFreqOFF	0x00
+#define cSelectOscFreqON	0x20
+
+/* bit 6+7 (PTF0/PTF1) */
+#define cOscFreq_4332kHz	0x00
+#define cOscFreq_8664kHz	0x40
+#define cOscFreq_12996kHz	0x80
+#define cOscFreq_17328kHz	0xC0
+
+/* ---------------------------------------------------------------------- */
+
+static int block_to_user_buf(struct saa6588 *s, unsigned char __user *user_buf)
+{
+	int i;
+
+	if (s->rd_index == s->wr_index) {
+		if (debug > 2)
+			dprintk(PREFIX "Read: buffer empty.\n");
+		return 0;
+	}
+
+	if (debug > 2) {
+		dprintk(PREFIX "Read: ");
+		for (i = s->rd_index; i < s->rd_index + 3; i++)
+			dprintk("0x%02x ", s->buffer[i]);
+	}
+
+	if (copy_to_user(user_buf, &s->buffer[s->rd_index], 3))
+		return -EFAULT;
+
+	s->rd_index += 3;
+	if (s->rd_index >= s->buf_size)
+		s->rd_index = 0;
+	s->block_count--;
+
+	if (debug > 2)
+		dprintk("%d blocks total.\n", s->block_count);
+
+	return 1;
+}
+
+static void read_from_buf(struct saa6588 *s, struct saa6588_command *a)
+{
+	unsigned long flags;
+
+	unsigned char __user *buf_ptr = a->buffer;
+	unsigned int i;
+	unsigned int rd_blocks;
+
+	a->result = 0;
+	if (!a->buffer)
+		return;
+
+	while (!s->data_available_for_read) {
+		int ret = wait_event_interruptible(s->read_queue,
+					     s->data_available_for_read);
+		if (ret == -ERESTARTSYS) {
+			a->result = -EINTR;
+			return;
+		}
+	}
+
+	spin_lock_irqsave(&s->lock, flags);
+	rd_blocks = a->block_count;
+	if (rd_blocks > s->block_count)
+		rd_blocks = s->block_count;
+
+	if (!rd_blocks) {
+		spin_unlock_irqrestore(&s->lock, flags);
+		return;
+	}
+
+	for (i = 0; i < rd_blocks; i++) {
+		if (block_to_user_buf(s, buf_ptr)) {
+			buf_ptr += 3;
+			a->result++;
+		} else
+			break;
+	}
+	a->result *= 3;
+	s->data_available_for_read = (s->block_count > 0);
+	spin_unlock_irqrestore(&s->lock, flags);
+}
+
+static void block_to_buf(struct saa6588 *s, unsigned char *blockbuf)
+{
+	unsigned int i;
+
+	if (debug > 3)
+		dprintk(PREFIX "New block: ");
+
+	for (i = 0; i < 3; ++i) {
+		if (debug > 3)
+			dprintk("0x%02x ", blockbuf[i]);
+		s->buffer[s->wr_index] = blockbuf[i];
+		s->wr_index++;
+	}
+
+	if (s->wr_index >= s->buf_size)
+		s->wr_index = 0;
+
+	if (s->wr_index == s->rd_index) {
+		s->rd_index += 3;
+		if (s->rd_index >= s->buf_size)
+			s->rd_index = 0;
+	} else
+		s->block_count++;
+
+	if (debug > 3)
+		dprintk("%d blocks total.\n", s->block_count);
+}
+
+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;
+	unsigned char tmp;
+
+	/* Although we only need 3 bytes, we have to read at least 6.
+	   SAA6588 returns garbage otherwise. */
+	if (6 != i2c_master_recv(client, &tmpbuf[0], 6)) {
+		if (debug > 1)
+			dprintk(PREFIX "read error!\n");
+		return;
+	}
+
+	s->sync = tmpbuf[0] & 0x10;
+	if (!s->sync)
+		return;
+	blocknum = tmpbuf[0] >> 5;
+	if (blocknum == s->last_blocknum) {
+		if (debug > 3)
+			dprintk("Saw block %d again.\n", blocknum);
+		return;
+	}
+
+	s->last_blocknum = blocknum;
+
+	/*
+	   Byte order according to v4l2 specification:
+
+	   Byte 0: Least Significant Byte of RDS Block
+	   Byte 1: Most Significant Byte of RDS Block
+	   Byte 2 Bit 7: Error bit. Indicates that an uncorrectable error
+	   occurred during reception of this block.
+	   Bit 6: Corrected bit. Indicates that an error was
+	   corrected for this data block.
+	   Bits 5-3: Same as bits 0-2.
+	   Bits 2-0: Block number.
+
+	   SAA6588 byte order is Status-MSB-LSB, so we have to swap the
+	   first and the last of the 3 bytes block.
+	 */
+
+	tmp = tmpbuf[2];
+	tmpbuf[2] = tmpbuf[0];
+	tmpbuf[0] = tmp;
+
+	/* Map 'Invalid block E' to 'Invalid Block' */
+	if (blocknum == 6)
+		blocknum = V4L2_RDS_BLOCK_INVALID;
+	/* And if are not in mmbs mode, then 'Block E' is also mapped
+	   to 'Invalid Block'. As far as I can tell MMBS is discontinued,
+	   and if there is ever a need to support E blocks, then please
+	   contact the linux-media mailinglist. */
+	else if (!mmbs && blocknum == 5)
+		blocknum = V4L2_RDS_BLOCK_INVALID;
+	tmp = blocknum;
+	tmp |= blocknum << 3;	/* Received offset == Offset Name (OK ?) */
+	if ((tmpbuf[2] & 0x03) == 0x03)
+		tmp |= V4L2_RDS_BLOCK_ERROR;	 /* uncorrectable error */
+	else if ((tmpbuf[2] & 0x03) != 0x00)
+		tmp |= V4L2_RDS_BLOCK_CORRECTED; /* corrected error */
+	tmpbuf[2] = tmp;	/* Is this enough ? Should we also check other bits ? */
+
+	spin_lock_irqsave(&s->lock, flags);
+	block_to_buf(s, tmpbuf);
+	spin_unlock_irqrestore(&s->lock, flags);
+	s->data_available_for_read = 1;
+	wake_up_interruptible(&s->read_queue);
+}
+
+static void saa6588_work(struct work_struct *work)
+{
+	struct saa6588 *s = container_of(work, struct saa6588, work.work);
+
+	saa6588_i2c_poll(s);
+	schedule_delayed_work(&s->work, msecs_to_jiffies(20));
+}
+
+static void saa6588_configure(struct saa6588 *s)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&s->sd);
+	unsigned char buf[3];
+	int rc;
+
+	buf[0] = cSyncRestart;
+	if (mmbs)
+		buf[0] |= cProcessingModeRBDS;
+
+	buf[1] = cFlywheelDefault;
+	switch (plvl) {
+	case 0:
+		buf[1] |= cPauseLevel_11mV;
+		break;
+	case 1:
+		buf[1] |= cPauseLevel_17mV;
+		break;
+	case 2:
+		buf[1] |= cPauseLevel_27mV;
+		break;
+	case 3:
+		buf[1] |= cPauseLevel_43mV;
+		break;
+	default:		/* nothing */
+		break;
+	}
+
+	buf[2] = cQualityDetectDefault | cSelectOscFreqON;
+
+	switch (xtal) {
+	case 0:
+		buf[2] |= cOscFreq_4332kHz;
+		break;
+	case 1:
+		buf[2] |= cOscFreq_8664kHz;
+		break;
+	case 2:
+		buf[2] |= cOscFreq_12996kHz;
+		break;
+	case 3:
+		buf[2] |= cOscFreq_17328kHz;
+		break;
+	default:		/* nothing */
+		break;
+	}
+
+	dprintk(PREFIX "writing: 0w=0x%02x 1w=0x%02x 2w=0x%02x\n",
+		buf[0], buf[1], buf[2]);
+
+	rc = i2c_master_send(client, buf, 3);
+	if (rc != 3)
+		printk(PREFIX "i2c i/o error: rc == %d (should be 3)\n", rc);
+}
+
+/* ---------------------------------------------------------------------- */
+
+static long saa6588_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
+{
+	struct saa6588 *s = to_saa6588(sd);
+	struct saa6588_command *a = arg;
+
+	switch (cmd) {
+		/* --- open() for /dev/radio --- */
+	case SAA6588_CMD_OPEN:
+		a->result = 0;	/* return error if chip doesn't work ??? */
+		break;
+		/* --- close() for /dev/radio --- */
+	case SAA6588_CMD_CLOSE:
+		s->data_available_for_read = 1;
+		wake_up_interruptible(&s->read_queue);
+		a->result = 0;
+		break;
+		/* --- read() for /dev/radio --- */
+	case SAA6588_CMD_READ:
+		read_from_buf(s, a);
+		break;
+		/* --- poll() for /dev/radio --- */
+	case SAA6588_CMD_POLL:
+		a->result = 0;
+		if (s->data_available_for_read) {
+			a->result |= POLLIN | POLLRDNORM;
+		}
+		poll_wait(a->instance, &s->read_queue, a->event_list);
+		break;
+
+	default:
+		/* nothing */
+		return -ENOIOCTLCMD;
+	}
+	return 0;
+}
+
+static int saa6588_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
+{
+	struct saa6588 *s = to_saa6588(sd);
+
+	vt->capability |= V4L2_TUNER_CAP_RDS | V4L2_TUNER_CAP_RDS_BLOCK_IO;
+	if (s->sync)
+		vt->rxsubchans |= V4L2_TUNER_SUB_RDS;
+	return 0;
+}
+
+static int saa6588_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
+{
+	struct saa6588 *s = to_saa6588(sd);
+
+	saa6588_configure(s);
+	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_tuner_ops saa6588_tuner_ops = {
+	.g_tuner = saa6588_g_tuner,
+	.s_tuner = saa6588_s_tuner,
+};
+
+static const struct v4l2_subdev_ops saa6588_ops = {
+	.core = &saa6588_core_ops,
+	.tuner = &saa6588_tuner_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 const struct i2c_device_id saa6588_id[] = {
+	{ "saa6588", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, saa6588_id);
+
+static struct i2c_driver saa6588_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "saa6588",
+	},
+	.probe		= saa6588_probe,
+	.remove		= saa6588_remove,
+	.id_table	= saa6588_id,
+};
+
+module_i2c_driver(saa6588_driver);
diff --git a/drivers/media/i2c/saa7110.c b/drivers/media/i2c/saa7110.c
new file mode 100644
index 0000000..51cd4c8
--- /dev/null
+++ b/drivers/media/i2c/saa7110.c
@@ -0,0 +1,494 @@
+/*
+ * saa7110 - Philips SAA7110(A) video decoder driver
+ *
+ * Copyright (C) 1998 Pauline Middelink <middelin@polyware.nl>
+ *
+ * Copyright (C) 1999 Wolfgang Scherr <scherr@net4you.net>
+ * Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
+ *    - some corrections for Pinnacle Systems Inc. DC10plus card.
+ *
+ * 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/init.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/wait.h>
+#include <asm/uaccess.h>
+#include <linux/i2c.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-ctrls.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)");
+
+#define SAA7110_MAX_INPUT	9	/* 6 CVBS, 3 SVHS */
+#define SAA7110_MAX_OUTPUT	1	/* 1 YUV */
+
+#define SAA7110_NR_REG		0x35
+
+struct saa7110 {
+	struct v4l2_subdev sd;
+	struct v4l2_ctrl_handler hdl;
+	u8 reg[SAA7110_NR_REG];
+
+	v4l2_std_id norm;
+	int input;
+	int enable;
+
+	wait_queue_head_t wq;
+};
+
+static inline struct saa7110 *to_saa7110(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct saa7110, sd);
+}
+
+static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
+{
+	return &container_of(ctrl->handler, struct saa7110, hdl)->sd;
+}
+
+/* ----------------------------------------------------------------------- */
+/* I2C support functions						   */
+/* ----------------------------------------------------------------------- */
+
+static int saa7110_write(struct v4l2_subdev *sd, u8 reg, u8 value)
+{
+	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 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 */
+
+	/* Sanity check */
+	if (reg + (len - 1) > SAA7110_NR_REG)
+		return ret;
+
+	/* the saa7110 has an autoincrement function, use it if
+	 * the adapter understands raw I2C */
+	if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+		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(sd, reg++, *data++);
+			if (ret < 0)
+				break;
+		}
+	}
+
+	return ret;
+}
+
+static inline int saa7110_read(struct v4l2_subdev *sd)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	return i2c_smbus_read_byte(client);
+}
+
+/* ----------------------------------------------------------------------- */
+/* SAA7110 functions							   */
+/* ----------------------------------------------------------------------- */
+
+#define FRESP_06H_COMPST 0x03	/*0x13*/
+#define FRESP_06H_SVIDEO 0x83	/*0xC0*/
+
+
+static int saa7110_selmux(struct v4l2_subdev *sd, int chan)
+{
+	static const unsigned char modes[9][8] = {
+		/* mode 0 */
+		{FRESP_06H_COMPST, 0xD9, 0x17, 0x40, 0x03,
+			      0x44, 0x75, 0x16},
+		/* mode 1 */
+		{FRESP_06H_COMPST, 0xD8, 0x17, 0x40, 0x03,
+			      0x44, 0x75, 0x16},
+		/* mode 2 */
+		{FRESP_06H_COMPST, 0xBA, 0x07, 0x91, 0x03,
+			      0x60, 0xB5, 0x05},
+		/* mode 3 */
+		{FRESP_06H_COMPST, 0xB8, 0x07, 0x91, 0x03,
+			      0x60, 0xB5, 0x05},
+		/* mode 4 */
+		{FRESP_06H_COMPST, 0x7C, 0x07, 0xD2, 0x83,
+			      0x60, 0xB5, 0x03},
+		/* mode 5 */
+		{FRESP_06H_COMPST, 0x78, 0x07, 0xD2, 0x83,
+			      0x60, 0xB5, 0x03},
+		/* mode 6 */
+		{FRESP_06H_SVIDEO, 0x59, 0x17, 0x42, 0xA3,
+			      0x44, 0x75, 0x12},
+		/* mode 7 */
+		{FRESP_06H_SVIDEO, 0x9A, 0x17, 0xB1, 0x13,
+			      0x60, 0xB5, 0x14},
+		/* mode 8 */
+		{FRESP_06H_SVIDEO, 0x3C, 0x27, 0xC1, 0x23,
+			      0x44, 0x75, 0x21}
+	};
+	struct saa7110 *decoder = to_saa7110(sd);
+	const unsigned char *ptr = modes[chan];
+
+	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;
+}
+
+static const unsigned char initseq[1 + SAA7110_NR_REG] = {
+	0, 0x4C, 0x3C, 0x0D, 0xEF, 0xBD, 0xF2, 0x03, 0x00,
+	/* 0x08 */ 0xF8, 0xF8, 0x60, 0x60, 0x00, 0x86, 0x18, 0x90,
+	/* 0x10 */ 0x00, 0x59, 0x40, 0x46, 0x42, 0x1A, 0xFF, 0xDA,
+	/* 0x18 */ 0xF2, 0x8B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	/* 0x20 */ 0xD9, 0x16, 0x40, 0x41, 0x80, 0x41, 0x80, 0x4F,
+	/* 0x28 */ 0xFE, 0x01, 0xCF, 0x0F, 0x03, 0x01, 0x03, 0x0C,
+	/* 0x30 */ 0x44, 0x71, 0x02, 0x8C, 0x02
+};
+
+static v4l2_std_id determine_norm(struct v4l2_subdev *sd)
+{
+	DEFINE_WAIT(wait);
+	struct saa7110 *decoder = to_saa7110(sd);
+	int status;
+
+	/* mode changed, start automatic detection */
+	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(sd);
+	if (status & 0x40) {
+		v4l2_dbg(1, debug, sd, "status=0x%02x (no signal)\n", status);
+		return decoder->norm;	/* no change*/
+	}
+	if ((status & 3) == 0) {
+		saa7110_write(sd, 0x06, 0x83);
+		if (status & 0x20) {
+			v4l2_dbg(1, debug, sd, "status=0x%02x (NTSC/no color)\n", status);
+			/*saa7110_write(sd,0x2E,0x81);*/
+			return V4L2_STD_NTSC;
+		}
+		v4l2_dbg(1, debug, sd, "status=0x%02x (PAL/no color)\n", status);
+		/*saa7110_write(sd,0x2E,0x9A);*/
+		return V4L2_STD_PAL;
+	}
+	/*saa7110_write(sd,0x06,0x03);*/
+	if (status & 0x20) {	/* 60Hz */
+		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(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(sd);
+	if ((status & 0x03) == 0x01) {
+		v4l2_dbg(1, debug, sd, "status=0x%02x (SECAM)\n", status);
+		saa7110_write(sd, 0x0D, 0x87);
+		return V4L2_STD_SECAM;
+	}
+	v4l2_dbg(1, debug, sd, "status=0x%02x (PAL)\n", status);
+	return V4L2_STD_PAL;
+}
+
+static int saa7110_g_input_status(struct v4l2_subdev *sd, u32 *pstatus)
+{
+	struct saa7110 *decoder = to_saa7110(sd);
+	int res = V4L2_IN_ST_NO_SIGNAL;
+	int status = saa7110_read(sd);
+
+	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;
+
+	*pstatus = res;
+	return 0;
+}
+
+static int saa7110_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
+{
+	*(v4l2_std_id *)std = determine_norm(sd);
+	return 0;
+}
+
+static int saa7110_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
+{
+	struct saa7110 *decoder = to_saa7110(sd);
+
+	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;
+		}
+	}
+	return 0;
+}
+
+static int saa7110_s_routing(struct v4l2_subdev *sd,
+			     u32 input, u32 output, u32 config)
+{
+	struct saa7110 *decoder = to_saa7110(sd);
+
+	if (input >= SAA7110_MAX_INPUT) {
+		v4l2_dbg(1, debug, sd, "input=%d not available\n", input);
+		return -EINVAL;
+	}
+	if (decoder->input != input) {
+		saa7110_selmux(sd, input);
+		v4l2_dbg(1, debug, sd, "switched to input=%d\n", 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_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct v4l2_subdev *sd = to_sd(ctrl);
+
+	switch (ctrl->id) {
+	case V4L2_CID_BRIGHTNESS:
+		saa7110_write(sd, 0x19, ctrl->val);
+		break;
+	case V4L2_CID_CONTRAST:
+		saa7110_write(sd, 0x13, ctrl->val);
+		break;
+	case V4L2_CID_SATURATION:
+		saa7110_write(sd, 0x12, ctrl->val);
+		break;
+	case V4L2_CID_HUE:
+		saa7110_write(sd, 0x07, ctrl->val);
+		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);
+}
+
+/* ----------------------------------------------------------------------- */
+
+static const struct v4l2_ctrl_ops saa7110_ctrl_ops = {
+	.s_ctrl = saa7110_s_ctrl,
+};
+
+static const struct v4l2_subdev_core_ops saa7110_core_ops = {
+	.g_chip_ident = saa7110_g_chip_ident,
+	.g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
+	.try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
+	.s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
+	.g_ctrl = v4l2_subdev_g_ctrl,
+	.s_ctrl = v4l2_subdev_s_ctrl,
+	.queryctrl = v4l2_subdev_queryctrl,
+	.querymenu = v4l2_subdev_querymenu,
+	.s_std = saa7110_s_std,
+};
+
+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,
+	.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 */
+	if (!i2c_check_functionality(client->adapter,
+		I2C_FUNC_SMBUS_READ_BYTE | I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
+		return -ENODEV;
+
+	v4l_info(client, "chip found @ 0x%x (%s)\n",
+			client->addr << 1, client->adapter->name);
+
+	decoder = kzalloc(sizeof(struct saa7110), GFP_KERNEL);
+	if (!decoder)
+		return -ENOMEM;
+	sd = &decoder->sd;
+	v4l2_i2c_subdev_init(sd, client, &saa7110_ops);
+	decoder->norm = V4L2_STD_PAL;
+	decoder->input = 0;
+	decoder->enable = 1;
+	v4l2_ctrl_handler_init(&decoder->hdl, 2);
+	v4l2_ctrl_new_std(&decoder->hdl, &saa7110_ctrl_ops,
+		V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
+	v4l2_ctrl_new_std(&decoder->hdl, &saa7110_ctrl_ops,
+		V4L2_CID_CONTRAST, 0, 127, 1, 64);
+	v4l2_ctrl_new_std(&decoder->hdl, &saa7110_ctrl_ops,
+		V4L2_CID_SATURATION, 0, 127, 1, 64);
+	v4l2_ctrl_new_std(&decoder->hdl, &saa7110_ctrl_ops,
+		V4L2_CID_HUE, -128, 127, 1, 0);
+	sd->ctrl_handler = &decoder->hdl;
+	if (decoder->hdl.error) {
+		int err = decoder->hdl.error;
+
+		v4l2_ctrl_handler_free(&decoder->hdl);
+		kfree(decoder);
+		return err;
+	}
+	v4l2_ctrl_handler_setup(&decoder->hdl);
+
+	init_waitqueue_head(&decoder->wq);
+
+	rv = saa7110_write_block(sd, initseq, sizeof(initseq));
+	if (rv < 0) {
+		v4l2_dbg(1, debug, sd, "init status %d\n", rv);
+	} else {
+		int ver, status;
+		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(sd, 0x0D, 0x86);
+		saa7110_write(sd, 0x0F, 0x10);
+		saa7110_write(sd, 0x11, 0x59);
+		/*saa7110_write(sd, 0x2E, 0x9A);*/
+	}
+
+	/*saa7110_selmux(sd,0);*/
+	/*determine_norm(sd);*/
+	/* setup and implicit mode 0 select has been performed */
+
+	return 0;
+}
+
+static int saa7110_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct saa7110 *decoder = to_saa7110(sd);
+
+	v4l2_device_unregister_subdev(sd);
+	v4l2_ctrl_handler_free(&decoder->hdl);
+	kfree(decoder);
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static const struct i2c_device_id saa7110_id[] = {
+	{ "saa7110", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, saa7110_id);
+
+static struct i2c_driver saa7110_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "saa7110",
+	},
+	.probe		= saa7110_probe,
+	.remove		= saa7110_remove,
+	.id_table	= saa7110_id,
+};
+
+module_i2c_driver(saa7110_driver);
diff --git a/drivers/media/i2c/saa7115.c b/drivers/media/i2c/saa7115.c
new file mode 100644
index 0000000..2107336
--- /dev/null
+++ b/drivers/media/i2c/saa7115.c
@@ -0,0 +1,1727 @@
+/* saa711x - Philips SAA711x video decoder driver
+ * This driver can work with saa7111, saa7111a, saa7113, saa7114,
+ *			     saa7115 and saa7118.
+ *
+ * Based on saa7114 driver by Maxim Yevtyushkin, which is based on
+ * the saa7111 driver by Dave Perks.
+ *
+ * Copyright (C) 1998 Dave Perks <dperks@ibm.net>
+ * Copyright (C) 2002 Maxim Yevtyushkin <max@linuxmedialabs.com>
+ *
+ * Slight changes for video timing and attachment output by
+ * Wolfgang Scherr <scherr@net4you.net>
+ *
+ * Moved over to the linux >= 2.4.x i2c protocol (1/1/2003)
+ * by Ronald Bultje <rbultje@ronald.bitfreak.net>
+ *
+ * Added saa7115 support by Kevin Thayer <nufan_wfk at yahoo.com>
+ * (2/17/2003)
+ *
+ * VBI support (2004) and cleanups (2005) by Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ * Copyright (c) 2005-2006 Mauro Carvalho Chehab <mchehab@infradead.org>
+ *	SAA7111, SAA7113 and SAA7118 support
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include "saa711x_regs.h"
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/saa7115.h>
+#include <asm/div64.h>
+
+#define VRES_60HZ	(480+16)
+
+MODULE_DESCRIPTION("Philips SAA7111/SAA7113/SAA7114/SAA7115/SAA7118 video decoder driver");
+MODULE_AUTHOR(  "Maxim Yevtyushkin, Kevin Thayer, Chris Kennedy, "
+		"Hans Verkuil, Mauro Carvalho Chehab");
+MODULE_LICENSE("GPL");
+
+static bool debug;
+module_param(debug, bool, 0644);
+
+MODULE_PARM_DESC(debug, "Debug level (0-1)");
+
+
+struct saa711x_state {
+	struct v4l2_subdev sd;
+	struct v4l2_ctrl_handler hdl;
+
+	struct {
+		/* chroma gain control cluster */
+		struct v4l2_ctrl *agc;
+		struct v4l2_ctrl *gain;
+	};
+
+	v4l2_std_id std;
+	int input;
+	int output;
+	int enable;
+	int radio;
+	int width;
+	int height;
+	u32 ident;
+	u32 audclk_freq;
+	u32 crystal_freq;
+	u8 ucgc;
+	u8 cgcdiv;
+	u8 apll;
+};
+
+static inline struct saa711x_state *to_state(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct saa711x_state, sd);
+}
+
+static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
+{
+	return &container_of(ctrl->handler, struct saa711x_state, hdl)->sd;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static inline int saa711x_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);
+}
+
+/* Sanity routine to check if a register is present */
+static int saa711x_has_reg(const int id, const u8 reg)
+{
+	if (id == V4L2_IDENT_SAA7111)
+		return reg < 0x20 && reg != 0x01 && reg != 0x0f &&
+		       (reg < 0x13 || reg > 0x19) && reg != 0x1d && reg != 0x1e;
+	if (id == V4L2_IDENT_SAA7111A)
+		return reg < 0x20 && reg != 0x01 && reg != 0x0f &&
+		       reg != 0x14 && reg != 0x18 && reg != 0x19 &&
+		       reg != 0x1d && reg != 0x1e;
+
+	/* common for saa7113/4/5/8 */
+	if (unlikely((reg >= 0x3b && reg <= 0x3f) || reg == 0x5c || reg == 0x5f ||
+	    reg == 0xa3 || reg == 0xa7 || reg == 0xab || reg == 0xaf || (reg >= 0xb5 && reg <= 0xb7) ||
+	    reg == 0xd3 || reg == 0xd7 || reg == 0xdb || reg == 0xdf || (reg >= 0xe5 && reg <= 0xe7) ||
+	    reg == 0x82 || (reg >= 0x89 && reg <= 0x8e)))
+		return 0;
+
+	switch (id) {
+	case V4L2_IDENT_SAA7113:
+		return reg != 0x14 && (reg < 0x18 || reg > 0x1e) && (reg < 0x20 || reg > 0x3f) &&
+		       reg != 0x5d && reg < 0x63;
+	case V4L2_IDENT_SAA7114:
+		return (reg < 0x1a || reg > 0x1e) && (reg < 0x20 || reg > 0x2f) &&
+		       (reg < 0x63 || reg > 0x7f) && reg != 0x33 && reg != 0x37 &&
+		       reg != 0x81 && reg < 0xf0;
+	case V4L2_IDENT_SAA7115:
+		return (reg < 0x20 || reg > 0x2f) && reg != 0x65 && (reg < 0xfc || reg > 0xfe);
+	case V4L2_IDENT_SAA7118:
+		return (reg < 0x1a || reg > 0x1d) && (reg < 0x20 || reg > 0x22) &&
+		       (reg < 0x26 || reg > 0x28) && reg != 0x33 && reg != 0x37 &&
+		       (reg < 0x63 || reg > 0x7f) && reg != 0x81 && reg < 0xf0;
+	}
+	return 1;
+}
+
+static int saa711x_writeregs(struct v4l2_subdev *sd, const unsigned char *regs)
+{
+	struct saa711x_state *state = to_state(sd);
+	unsigned char reg, data;
+
+	while (*regs != 0x00) {
+		reg = *(regs++);
+		data = *(regs++);
+
+		/* According with datasheets, reserved regs should be
+		   filled with 0 - seems better not to touch on they */
+		if (saa711x_has_reg(state->ident, reg)) {
+			if (saa711x_write(sd, reg, data) < 0)
+				return -1;
+		} else {
+			v4l2_dbg(1, debug, sd, "tried to access reserved reg 0x%02x\n", reg);
+		}
+	}
+	return 0;
+}
+
+static inline int saa711x_read(struct v4l2_subdev *sd, u8 reg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	return i2c_smbus_read_byte_data(client, reg);
+}
+
+/* ----------------------------------------------------------------------- */
+
+/* SAA7111 initialization table */
+static const unsigned char saa7111_init[] = {
+	R_01_INC_DELAY, 0x00,		/* reserved */
+
+	/*front end */
+	R_02_INPUT_CNTL_1, 0xd0,	/* FUSE=3, GUDL=2, MODE=0 */
+	R_03_INPUT_CNTL_2, 0x23,	/* HLNRS=0, VBSL=1, WPOFF=0, HOLDG=0,
+					 * GAFIX=0, GAI1=256, GAI2=256 */
+	R_04_INPUT_CNTL_3, 0x00,	/* GAI1=256 */
+	R_05_INPUT_CNTL_4, 0x00,	/* GAI2=256 */
+
+	/* decoder */
+	R_06_H_SYNC_START, 0xf3,	/* HSB at  13(50Hz) /  17(60Hz)
+					 * pixels after end of last line */
+	R_07_H_SYNC_STOP, 0xe8,		/* HSS seems to be needed to
+					 * work with NTSC, too */
+	R_08_SYNC_CNTL, 0xc8,		/* AUFD=1, FSEL=1, EXFIL=0,
+					 * VTRC=1, HPLL=0, VNOI=0 */
+	R_09_LUMA_CNTL, 0x01,		/* BYPS=0, PREF=0, BPSS=0,
+					 * VBLB=0, UPTCV=0, APER=1 */
+	R_0A_LUMA_BRIGHT_CNTL, 0x80,
+	R_0B_LUMA_CONTRAST_CNTL, 0x47,	/* 0b - CONT=1.109 */
+	R_0C_CHROMA_SAT_CNTL, 0x40,
+	R_0D_CHROMA_HUE_CNTL, 0x00,
+	R_0E_CHROMA_CNTL_1, 0x01,	/* 0e - CDTO=0, CSTD=0, DCCF=0,
+					 * FCTC=0, CHBW=1 */
+	R_0F_CHROMA_GAIN_CNTL, 0x00,	/* reserved */
+	R_10_CHROMA_CNTL_2, 0x48,	/* 10 - OFTS=1, HDEL=0, VRLN=1, YDEL=0 */
+	R_11_MODE_DELAY_CNTL, 0x1c,	/* 11 - GPSW=0, CM99=0, FECO=0, COMPO=1,
+					 * OEYC=1, OEHV=1, VIPB=0, COLO=0 */
+	R_12_RT_SIGNAL_CNTL, 0x00,	/* 12 - output control 2 */
+	R_13_RT_X_PORT_OUT_CNTL, 0x00,	/* 13 - output control 3 */
+	R_14_ANAL_ADC_COMPAT_CNTL, 0x00,
+	R_15_VGATE_START_FID_CHG, 0x00,
+	R_16_VGATE_STOP, 0x00,
+	R_17_MISC_VGATE_CONF_AND_MSB, 0x00,
+
+	0x00, 0x00
+};
+
+/* SAA7113 init codes */
+static const unsigned char saa7113_init[] = {
+	R_01_INC_DELAY, 0x08,
+	R_02_INPUT_CNTL_1, 0xc2,
+	R_03_INPUT_CNTL_2, 0x30,
+	R_04_INPUT_CNTL_3, 0x00,
+	R_05_INPUT_CNTL_4, 0x00,
+	R_06_H_SYNC_START, 0x89,
+	R_07_H_SYNC_STOP, 0x0d,
+	R_08_SYNC_CNTL, 0x88,
+	R_09_LUMA_CNTL, 0x01,
+	R_0A_LUMA_BRIGHT_CNTL, 0x80,
+	R_0B_LUMA_CONTRAST_CNTL, 0x47,
+	R_0C_CHROMA_SAT_CNTL, 0x40,
+	R_0D_CHROMA_HUE_CNTL, 0x00,
+	R_0E_CHROMA_CNTL_1, 0x01,
+	R_0F_CHROMA_GAIN_CNTL, 0x2a,
+	R_10_CHROMA_CNTL_2, 0x08,
+	R_11_MODE_DELAY_CNTL, 0x0c,
+	R_12_RT_SIGNAL_CNTL, 0x07,
+	R_13_RT_X_PORT_OUT_CNTL, 0x00,
+	R_14_ANAL_ADC_COMPAT_CNTL, 0x00,
+	R_15_VGATE_START_FID_CHG, 0x00,
+	R_16_VGATE_STOP, 0x00,
+	R_17_MISC_VGATE_CONF_AND_MSB, 0x00,
+
+	0x00, 0x00
+};
+
+/* If a value differs from the Hauppauge driver values, then the comment starts with
+   'was 0xXX' to denote the Hauppauge value. Otherwise the value is identical to what the
+   Hauppauge driver sets. */
+
+/* SAA7114 and SAA7115 initialization table */
+static const unsigned char saa7115_init_auto_input[] = {
+		/* Front-End Part */
+	R_01_INC_DELAY, 0x48,			/* white peak control disabled */
+	R_03_INPUT_CNTL_2, 0x20,		/* was 0x30. 0x20: long vertical blanking */
+	R_04_INPUT_CNTL_3, 0x90,		/* analog gain set to 0 */
+	R_05_INPUT_CNTL_4, 0x90,		/* analog gain set to 0 */
+		/* Decoder Part */
+	R_06_H_SYNC_START, 0xeb,		/* horiz sync begin = -21 */
+	R_07_H_SYNC_STOP, 0xe0,			/* horiz sync stop = -17 */
+	R_09_LUMA_CNTL, 0x53,			/* 0x53, was 0x56 for 60hz. luminance control */
+	R_0A_LUMA_BRIGHT_CNTL, 0x80,		/* was 0x88. decoder brightness, 0x80 is itu standard */
+	R_0B_LUMA_CONTRAST_CNTL, 0x44,		/* was 0x48. decoder contrast, 0x44 is itu standard */
+	R_0C_CHROMA_SAT_CNTL, 0x40,		/* was 0x47. decoder saturation, 0x40 is itu standard */
+	R_0D_CHROMA_HUE_CNTL, 0x00,
+	R_0F_CHROMA_GAIN_CNTL, 0x00,		/* use automatic gain  */
+	R_10_CHROMA_CNTL_2, 0x06,		/* chroma: active adaptive combfilter */
+	R_11_MODE_DELAY_CNTL, 0x00,
+	R_12_RT_SIGNAL_CNTL, 0x9d,		/* RTS0 output control: VGATE */
+	R_13_RT_X_PORT_OUT_CNTL, 0x80,		/* ITU656 standard mode, RTCO output enable RTCE */
+	R_14_ANAL_ADC_COMPAT_CNTL, 0x00,
+	R_18_RAW_DATA_GAIN_CNTL, 0x40,		/* gain 0x00 = nominal */
+	R_19_RAW_DATA_OFF_CNTL, 0x80,
+	R_1A_COLOR_KILL_LVL_CNTL, 0x77,		/* recommended value */
+	R_1B_MISC_TVVCRDET, 0x42,		/* recommended value */
+	R_1C_ENHAN_COMB_CTRL1, 0xa9,		/* recommended value */
+	R_1D_ENHAN_COMB_CTRL2, 0x01,		/* recommended value */
+
+
+	R_80_GLOBAL_CNTL_1, 0x0,		/* No tasks enabled at init */
+
+		/* Power Device Control */
+	R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0,	/* reset device */
+	R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0,	/* set device programmed, all in operational mode */
+	0x00, 0x00
+};
+
+/* Used to reset saa7113, saa7114 and saa7115 */
+static const unsigned char saa7115_cfg_reset_scaler[] = {
+	R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x00,	/* disable I-port output */
+	R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0,		/* reset scaler */
+	R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0,		/* activate scaler */
+	R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x01,	/* enable I-port output */
+	0x00, 0x00
+};
+
+/* ============== SAA7715 VIDEO templates =============  */
+
+static const unsigned char saa7115_cfg_60hz_video[] = {
+	R_80_GLOBAL_CNTL_1, 0x00,			/* reset tasks */
+	R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0,		/* reset scaler */
+
+	R_15_VGATE_START_FID_CHG, 0x03,
+	R_16_VGATE_STOP, 0x11,
+	R_17_MISC_VGATE_CONF_AND_MSB, 0x9c,
+
+	R_08_SYNC_CNTL, 0x68,			/* 0xBO: auto detection, 0x68 = NTSC */
+	R_0E_CHROMA_CNTL_1, 0x07,		/* video autodetection is on */
+
+	R_5A_V_OFF_FOR_SLICER, 0x06,		/* standard 60hz value for ITU656 line counting */
+
+	/* Task A */
+	R_90_A_TASK_HANDLING_CNTL, 0x80,
+	R_91_A_X_PORT_FORMATS_AND_CONF, 0x48,
+	R_92_A_X_PORT_INPUT_REFERENCE_SIGNAL, 0x40,
+	R_93_A_I_PORT_OUTPUT_FORMATS_AND_CONF, 0x84,
+
+	/* hoffset low (input), 0x0002 is minimum */
+	R_94_A_HORIZ_INPUT_WINDOW_START, 0x01,
+	R_95_A_HORIZ_INPUT_WINDOW_START_MSB, 0x00,
+
+	/* hsize low (input), 0x02d0 = 720 */
+	R_96_A_HORIZ_INPUT_WINDOW_LENGTH, 0xd0,
+	R_97_A_HORIZ_INPUT_WINDOW_LENGTH_MSB, 0x02,
+
+	R_98_A_VERT_INPUT_WINDOW_START, 0x05,
+	R_99_A_VERT_INPUT_WINDOW_START_MSB, 0x00,
+
+	R_9A_A_VERT_INPUT_WINDOW_LENGTH, 0x0c,
+	R_9B_A_VERT_INPUT_WINDOW_LENGTH_MSB, 0x00,
+
+	R_9C_A_HORIZ_OUTPUT_WINDOW_LENGTH, 0xa0,
+	R_9D_A_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, 0x05,
+
+	R_9E_A_VERT_OUTPUT_WINDOW_LENGTH, 0x0c,
+	R_9F_A_VERT_OUTPUT_WINDOW_LENGTH_MSB, 0x00,
+
+	/* Task B */
+	R_C0_B_TASK_HANDLING_CNTL, 0x00,
+	R_C1_B_X_PORT_FORMATS_AND_CONF, 0x08,
+	R_C2_B_INPUT_REFERENCE_SIGNAL_DEFINITION, 0x00,
+	R_C3_B_I_PORT_FORMATS_AND_CONF, 0x80,
+
+	/* 0x0002 is minimum */
+	R_C4_B_HORIZ_INPUT_WINDOW_START, 0x02,
+	R_C5_B_HORIZ_INPUT_WINDOW_START_MSB, 0x00,
+
+	/* 0x02d0 = 720 */
+	R_C6_B_HORIZ_INPUT_WINDOW_LENGTH, 0xd0,
+	R_C7_B_HORIZ_INPUT_WINDOW_LENGTH_MSB, 0x02,
+
+	/* vwindow start 0x12 = 18 */
+	R_C8_B_VERT_INPUT_WINDOW_START, 0x12,
+	R_C9_B_VERT_INPUT_WINDOW_START_MSB, 0x00,
+
+	/* vwindow length 0xf8 = 248 */
+	R_CA_B_VERT_INPUT_WINDOW_LENGTH, VRES_60HZ>>1,
+	R_CB_B_VERT_INPUT_WINDOW_LENGTH_MSB, VRES_60HZ>>9,
+
+	/* hwindow 0x02d0 = 720 */
+	R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH, 0xd0,
+	R_CD_B_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, 0x02,
+
+	R_F0_LFCO_PER_LINE, 0xad,		/* Set PLL Register. 60hz 525 lines per frame, 27 MHz */
+	R_F1_P_I_PARAM_SELECT, 0x05,		/* low bit with 0xF0 */
+	R_F5_PULSGEN_LINE_LENGTH, 0xad,
+	R_F6_PULSE_A_POS_LSB_AND_PULSEGEN_CONFIG, 0x01,
+
+	0x00, 0x00
+};
+
+static const unsigned char saa7115_cfg_50hz_video[] = {
+	R_80_GLOBAL_CNTL_1, 0x00,
+	R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0,	/* reset scaler */
+
+	R_15_VGATE_START_FID_CHG, 0x37,		/* VGATE start */
+	R_16_VGATE_STOP, 0x16,
+	R_17_MISC_VGATE_CONF_AND_MSB, 0x99,
+
+	R_08_SYNC_CNTL, 0x28,			/* 0x28 = PAL */
+	R_0E_CHROMA_CNTL_1, 0x07,
+
+	R_5A_V_OFF_FOR_SLICER, 0x03,		/* standard 50hz value */
+
+	/* Task A */
+	R_90_A_TASK_HANDLING_CNTL, 0x81,
+	R_91_A_X_PORT_FORMATS_AND_CONF, 0x48,
+	R_92_A_X_PORT_INPUT_REFERENCE_SIGNAL, 0x40,
+	R_93_A_I_PORT_OUTPUT_FORMATS_AND_CONF, 0x84,
+
+	/* This is weird: the datasheet says that you should use 2 as the minimum value, */
+	/* but Hauppauge uses 0, and changing that to 2 causes indeed problems (for 50hz) */
+	/* hoffset low (input), 0x0002 is minimum */
+	R_94_A_HORIZ_INPUT_WINDOW_START, 0x00,
+	R_95_A_HORIZ_INPUT_WINDOW_START_MSB, 0x00,
+
+	/* hsize low (input), 0x02d0 = 720 */
+	R_96_A_HORIZ_INPUT_WINDOW_LENGTH, 0xd0,
+	R_97_A_HORIZ_INPUT_WINDOW_LENGTH_MSB, 0x02,
+
+	R_98_A_VERT_INPUT_WINDOW_START, 0x03,
+	R_99_A_VERT_INPUT_WINDOW_START_MSB, 0x00,
+
+	/* vsize 0x12 = 18 */
+	R_9A_A_VERT_INPUT_WINDOW_LENGTH, 0x12,
+	R_9B_A_VERT_INPUT_WINDOW_LENGTH_MSB, 0x00,
+
+	/* hsize 0x05a0 = 1440 */
+	R_9C_A_HORIZ_OUTPUT_WINDOW_LENGTH, 0xa0,
+	R_9D_A_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, 0x05,	/* hsize hi (output) */
+	R_9E_A_VERT_OUTPUT_WINDOW_LENGTH, 0x12,		/* vsize low (output), 0x12 = 18 */
+	R_9F_A_VERT_OUTPUT_WINDOW_LENGTH_MSB, 0x00,	/* vsize hi (output) */
+
+	/* Task B */
+	R_C0_B_TASK_HANDLING_CNTL, 0x00,
+	R_C1_B_X_PORT_FORMATS_AND_CONF, 0x08,
+	R_C2_B_INPUT_REFERENCE_SIGNAL_DEFINITION, 0x00,
+	R_C3_B_I_PORT_FORMATS_AND_CONF, 0x80,
+
+	/* This is weird: the datasheet says that you should use 2 as the minimum value, */
+	/* but Hauppauge uses 0, and changing that to 2 causes indeed problems (for 50hz) */
+	/* hoffset low (input), 0x0002 is minimum. See comment above. */
+	R_C4_B_HORIZ_INPUT_WINDOW_START, 0x00,
+	R_C5_B_HORIZ_INPUT_WINDOW_START_MSB, 0x00,
+
+	/* hsize 0x02d0 = 720 */
+	R_C6_B_HORIZ_INPUT_WINDOW_LENGTH, 0xd0,
+	R_C7_B_HORIZ_INPUT_WINDOW_LENGTH_MSB, 0x02,
+
+	/* voffset 0x16 = 22 */
+	R_C8_B_VERT_INPUT_WINDOW_START, 0x16,
+	R_C9_B_VERT_INPUT_WINDOW_START_MSB, 0x00,
+
+	/* vsize 0x0120 = 288 */
+	R_CA_B_VERT_INPUT_WINDOW_LENGTH, 0x20,
+	R_CB_B_VERT_INPUT_WINDOW_LENGTH_MSB, 0x01,
+
+	/* hsize 0x02d0 = 720 */
+	R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH, 0xd0,
+	R_CD_B_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, 0x02,
+
+	R_F0_LFCO_PER_LINE, 0xb0,		/* Set PLL Register. 50hz 625 lines per frame, 27 MHz */
+	R_F1_P_I_PARAM_SELECT, 0x05,		/* low bit with 0xF0, (was 0x05) */
+	R_F5_PULSGEN_LINE_LENGTH, 0xb0,
+	R_F6_PULSE_A_POS_LSB_AND_PULSEGEN_CONFIG, 0x01,
+
+	0x00, 0x00
+};
+
+/* ============== SAA7715 VIDEO templates (end) =======  */
+
+static const unsigned char saa7115_cfg_vbi_on[] = {
+	R_80_GLOBAL_CNTL_1, 0x00,			/* reset tasks */
+	R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0,		/* reset scaler */
+	R_80_GLOBAL_CNTL_1, 0x30,			/* Activate both tasks */
+	R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0,		/* activate scaler */
+	R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x01,	/* Enable I-port output */
+
+	0x00, 0x00
+};
+
+static const unsigned char saa7115_cfg_vbi_off[] = {
+	R_80_GLOBAL_CNTL_1, 0x00,			/* reset tasks */
+	R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0,		/* reset scaler */
+	R_80_GLOBAL_CNTL_1, 0x20,			/* Activate only task "B" */
+	R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0,		/* activate scaler */
+	R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x01,	/* Enable I-port output */
+
+	0x00, 0x00
+};
+
+
+static const unsigned char saa7115_init_misc[] = {
+	R_81_V_SYNC_FLD_ID_SRC_SEL_AND_RETIMED_V_F, 0x01,
+	R_83_X_PORT_I_O_ENA_AND_OUT_CLK, 0x01,
+	R_84_I_PORT_SIGNAL_DEF, 0x20,
+	R_85_I_PORT_SIGNAL_POLAR, 0x21,
+	R_86_I_PORT_FIFO_FLAG_CNTL_AND_ARBIT, 0xc5,
+	R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x01,
+
+	/* Task A */
+	R_A0_A_HORIZ_PRESCALING, 0x01,
+	R_A1_A_ACCUMULATION_LENGTH, 0x00,
+	R_A2_A_PRESCALER_DC_GAIN_AND_FIR_PREFILTER, 0x00,
+
+	/* Configure controls at nominal value*/
+	R_A4_A_LUMA_BRIGHTNESS_CNTL, 0x80,
+	R_A5_A_LUMA_CONTRAST_CNTL, 0x40,
+	R_A6_A_CHROMA_SATURATION_CNTL, 0x40,
+
+	/* note: 2 x zoom ensures that VBI lines have same length as video lines. */
+	R_A8_A_HORIZ_LUMA_SCALING_INC, 0x00,
+	R_A9_A_HORIZ_LUMA_SCALING_INC_MSB, 0x02,
+
+	R_AA_A_HORIZ_LUMA_PHASE_OFF, 0x00,
+
+	/* must be horiz lum scaling / 2 */
+	R_AC_A_HORIZ_CHROMA_SCALING_INC, 0x00,
+	R_AD_A_HORIZ_CHROMA_SCALING_INC_MSB, 0x01,
+
+	/* must be offset luma / 2 */
+	R_AE_A_HORIZ_CHROMA_PHASE_OFF, 0x00,
+
+	R_B0_A_VERT_LUMA_SCALING_INC, 0x00,
+	R_B1_A_VERT_LUMA_SCALING_INC_MSB, 0x04,
+
+	R_B2_A_VERT_CHROMA_SCALING_INC, 0x00,
+	R_B3_A_VERT_CHROMA_SCALING_INC_MSB, 0x04,
+
+	R_B4_A_VERT_SCALING_MODE_CNTL, 0x01,
+
+	R_B8_A_VERT_CHROMA_PHASE_OFF_00, 0x00,
+	R_B9_A_VERT_CHROMA_PHASE_OFF_01, 0x00,
+	R_BA_A_VERT_CHROMA_PHASE_OFF_10, 0x00,
+	R_BB_A_VERT_CHROMA_PHASE_OFF_11, 0x00,
+
+	R_BC_A_VERT_LUMA_PHASE_OFF_00, 0x00,
+	R_BD_A_VERT_LUMA_PHASE_OFF_01, 0x00,
+	R_BE_A_VERT_LUMA_PHASE_OFF_10, 0x00,
+	R_BF_A_VERT_LUMA_PHASE_OFF_11, 0x00,
+
+	/* Task B */
+	R_D0_B_HORIZ_PRESCALING, 0x01,
+	R_D1_B_ACCUMULATION_LENGTH, 0x00,
+	R_D2_B_PRESCALER_DC_GAIN_AND_FIR_PREFILTER, 0x00,
+
+	/* Configure controls at nominal value*/
+	R_D4_B_LUMA_BRIGHTNESS_CNTL, 0x80,
+	R_D5_B_LUMA_CONTRAST_CNTL, 0x40,
+	R_D6_B_CHROMA_SATURATION_CNTL, 0x40,
+
+	/* hor lum scaling 0x0400 = 1 */
+	R_D8_B_HORIZ_LUMA_SCALING_INC, 0x00,
+	R_D9_B_HORIZ_LUMA_SCALING_INC_MSB, 0x04,
+
+	R_DA_B_HORIZ_LUMA_PHASE_OFF, 0x00,
+
+	/* must be hor lum scaling / 2 */
+	R_DC_B_HORIZ_CHROMA_SCALING, 0x00,
+	R_DD_B_HORIZ_CHROMA_SCALING_MSB, 0x02,
+
+	/* must be offset luma / 2 */
+	R_DE_B_HORIZ_PHASE_OFFSET_CRHOMA, 0x00,
+
+	R_E0_B_VERT_LUMA_SCALING_INC, 0x00,
+	R_E1_B_VERT_LUMA_SCALING_INC_MSB, 0x04,
+
+	R_E2_B_VERT_CHROMA_SCALING_INC, 0x00,
+	R_E3_B_VERT_CHROMA_SCALING_INC_MSB, 0x04,
+
+	R_E4_B_VERT_SCALING_MODE_CNTL, 0x01,
+
+	R_E8_B_VERT_CHROMA_PHASE_OFF_00, 0x00,
+	R_E9_B_VERT_CHROMA_PHASE_OFF_01, 0x00,
+	R_EA_B_VERT_CHROMA_PHASE_OFF_10, 0x00,
+	R_EB_B_VERT_CHROMA_PHASE_OFF_11, 0x00,
+
+	R_EC_B_VERT_LUMA_PHASE_OFF_00, 0x00,
+	R_ED_B_VERT_LUMA_PHASE_OFF_01, 0x00,
+	R_EE_B_VERT_LUMA_PHASE_OFF_10, 0x00,
+	R_EF_B_VERT_LUMA_PHASE_OFF_11, 0x00,
+
+	R_F2_NOMINAL_PLL2_DTO, 0x50,		/* crystal clock = 24.576 MHz, target = 27MHz */
+	R_F3_PLL_INCREMENT, 0x46,
+	R_F4_PLL2_STATUS, 0x00,
+	R_F7_PULSE_A_POS_MSB, 0x4b,		/* not the recommended settings! */
+	R_F8_PULSE_B_POS, 0x00,
+	R_F9_PULSE_B_POS_MSB, 0x4b,
+	R_FA_PULSE_C_POS, 0x00,
+	R_FB_PULSE_C_POS_MSB, 0x4b,
+
+	/* PLL2 lock detection settings: 71 lines 50% phase error */
+	R_FF_S_PLL_MAX_PHASE_ERR_THRESH_NUM_LINES, 0x88,
+
+	/* Turn off VBI */
+	R_40_SLICER_CNTL_1, 0x20,             /* No framing code errors allowed. */
+	R_41_LCR_BASE, 0xff,
+	R_41_LCR_BASE+1, 0xff,
+	R_41_LCR_BASE+2, 0xff,
+	R_41_LCR_BASE+3, 0xff,
+	R_41_LCR_BASE+4, 0xff,
+	R_41_LCR_BASE+5, 0xff,
+	R_41_LCR_BASE+6, 0xff,
+	R_41_LCR_BASE+7, 0xff,
+	R_41_LCR_BASE+8, 0xff,
+	R_41_LCR_BASE+9, 0xff,
+	R_41_LCR_BASE+10, 0xff,
+	R_41_LCR_BASE+11, 0xff,
+	R_41_LCR_BASE+12, 0xff,
+	R_41_LCR_BASE+13, 0xff,
+	R_41_LCR_BASE+14, 0xff,
+	R_41_LCR_BASE+15, 0xff,
+	R_41_LCR_BASE+16, 0xff,
+	R_41_LCR_BASE+17, 0xff,
+	R_41_LCR_BASE+18, 0xff,
+	R_41_LCR_BASE+19, 0xff,
+	R_41_LCR_BASE+20, 0xff,
+	R_41_LCR_BASE+21, 0xff,
+	R_41_LCR_BASE+22, 0xff,
+	R_58_PROGRAM_FRAMING_CODE, 0x40,
+	R_59_H_OFF_FOR_SLICER, 0x47,
+	R_5B_FLD_OFF_AND_MSB_FOR_H_AND_V_OFF, 0x83,
+	R_5D_DID, 0xbd,
+	R_5E_SDID, 0x35,
+
+	R_02_INPUT_CNTL_1, 0xc4, /* input tuner -> input 4, amplifier active */
+
+	R_80_GLOBAL_CNTL_1, 0x20,		/* enable task B */
+	R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0,
+	R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0,
+	0x00, 0x00
+};
+
+static int saa711x_odd_parity(u8 c)
+{
+	c ^= (c >> 4);
+	c ^= (c >> 2);
+	c ^= (c >> 1);
+
+	return c & 1;
+}
+
+static int saa711x_decode_vps(u8 *dst, u8 *p)
+{
+	static const u8 biphase_tbl[] = {
+		0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
+		0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
+		0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96,
+		0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2,
+		0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94,
+		0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0,
+		0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
+		0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
+		0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5,
+		0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1,
+		0xc3, 0x4b, 0x43, 0xc3, 0x87, 0x0f, 0x07, 0x87,
+		0x83, 0x0b, 0x03, 0x83, 0xc3, 0x4b, 0x43, 0xc3,
+		0xc1, 0x49, 0x41, 0xc1, 0x85, 0x0d, 0x05, 0x85,
+		0x81, 0x09, 0x01, 0x81, 0xc1, 0x49, 0x41, 0xc1,
+		0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5,
+		0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1,
+		0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4,
+		0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0,
+		0xc2, 0x4a, 0x42, 0xc2, 0x86, 0x0e, 0x06, 0x86,
+		0x82, 0x0a, 0x02, 0x82, 0xc2, 0x4a, 0x42, 0xc2,
+		0xc0, 0x48, 0x40, 0xc0, 0x84, 0x0c, 0x04, 0x84,
+		0x80, 0x08, 0x00, 0x80, 0xc0, 0x48, 0x40, 0xc0,
+		0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4,
+		0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0,
+		0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
+		0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
+		0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96,
+		0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2,
+		0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94,
+		0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0,
+		0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
+		0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
+	};
+	int i;
+	u8 c, err = 0;
+
+	for (i = 0; i < 2 * 13; i += 2) {
+		err |= biphase_tbl[p[i]] | biphase_tbl[p[i + 1]];
+		c = (biphase_tbl[p[i + 1]] & 0xf) | ((biphase_tbl[p[i]] & 0xf) << 4);
+		dst[i / 2] = c;
+	}
+	return err & 0xf0;
+}
+
+static int saa711x_decode_wss(u8 *p)
+{
+	static const int wss_bits[8] = {
+		0, 0, 0, 1, 0, 1, 1, 1
+	};
+	unsigned char parity;
+	int wss = 0;
+	int i;
+
+	for (i = 0; i < 16; i++) {
+		int b1 = wss_bits[p[i] & 7];
+		int b2 = wss_bits[(p[i] >> 3) & 7];
+
+		if (b1 == b2)
+			return -1;
+		wss |= b2 << i;
+	}
+	parity = wss & 15;
+	parity ^= parity >> 2;
+	parity ^= parity >> 1;
+
+	if (!(parity & 1))
+		return -1;
+
+	return wss;
+}
+
+static int saa711x_s_clock_freq(struct v4l2_subdev *sd, u32 freq)
+{
+	struct saa711x_state *state = to_state(sd);
+	u32 acpf;
+	u32 acni;
+	u32 hz;
+	u64 f;
+	u8 acc = 0; 	/* reg 0x3a, audio clock control */
+
+	/* Checks for chips that don't have audio clock (saa7111, saa7113) */
+	if (!saa711x_has_reg(state->ident, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD))
+		return 0;
+
+	v4l2_dbg(1, debug, sd, "set audio clock freq: %d\n", freq);
+
+	/* sanity check */
+	if (freq < 32000 || freq > 48000)
+		return -EINVAL;
+
+	/* hz is the refresh rate times 100 */
+	hz = (state->std & V4L2_STD_525_60) ? 5994 : 5000;
+	/* acpf = (256 * freq) / field_frequency == (256 * 100 * freq) / hz */
+	acpf = (25600 * freq) / hz;
+	/* acni = (256 * freq * 2^23) / crystal_frequency =
+		  (freq * 2^(8+23)) / crystal_frequency =
+		  (freq << 31) / crystal_frequency */
+	f = freq;
+	f = f << 31;
+	do_div(f, state->crystal_freq);
+	acni = f;
+	if (state->ucgc) {
+		acpf = acpf * state->cgcdiv / 16;
+		acni = acni * state->cgcdiv / 16;
+		acc = 0x80;
+		if (state->cgcdiv == 3)
+			acc |= 0x40;
+	}
+	if (state->apll)
+		acc |= 0x08;
+
+	saa711x_write(sd, R_38_CLK_RATIO_AMXCLK_TO_ASCLK, 0x03);
+	saa711x_write(sd, R_39_CLK_RATIO_ASCLK_TO_ALRCLK, 0x10);
+	saa711x_write(sd, R_3A_AUD_CLK_GEN_BASIC_SETUP, acc);
+
+	saa711x_write(sd, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD, acpf & 0xff);
+	saa711x_write(sd, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD+1,
+							(acpf >> 8) & 0xff);
+	saa711x_write(sd, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD+2,
+							(acpf >> 16) & 0x03);
+
+	saa711x_write(sd, R_34_AUD_MAST_CLK_NOMINAL_INC, acni & 0xff);
+	saa711x_write(sd, R_34_AUD_MAST_CLK_NOMINAL_INC+1, (acni >> 8) & 0xff);
+	saa711x_write(sd, R_34_AUD_MAST_CLK_NOMINAL_INC+2, (acni >> 16) & 0x3f);
+	state->audclk_freq = freq;
+	return 0;
+}
+
+static int saa711x_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct v4l2_subdev *sd = to_sd(ctrl);
+	struct saa711x_state *state = to_state(sd);
+
+	switch (ctrl->id) {
+	case V4L2_CID_CHROMA_AGC:
+		/* chroma gain cluster */
+		if (state->agc->val)
+			state->gain->val =
+				saa711x_read(sd, R_0F_CHROMA_GAIN_CNTL) & 0x7f;
+		break;
+	}
+	return 0;
+}
+
+static int saa711x_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct v4l2_subdev *sd = to_sd(ctrl);
+	struct saa711x_state *state = to_state(sd);
+
+	switch (ctrl->id) {
+	case V4L2_CID_BRIGHTNESS:
+		saa711x_write(sd, R_0A_LUMA_BRIGHT_CNTL, ctrl->val);
+		break;
+
+	case V4L2_CID_CONTRAST:
+		saa711x_write(sd, R_0B_LUMA_CONTRAST_CNTL, ctrl->val);
+		break;
+
+	case V4L2_CID_SATURATION:
+		saa711x_write(sd, R_0C_CHROMA_SAT_CNTL, ctrl->val);
+		break;
+
+	case V4L2_CID_HUE:
+		saa711x_write(sd, R_0D_CHROMA_HUE_CNTL, ctrl->val);
+		break;
+
+	case V4L2_CID_CHROMA_AGC:
+		/* chroma gain cluster */
+		if (state->agc->val)
+			saa711x_write(sd, R_0F_CHROMA_GAIN_CNTL, state->gain->val);
+		else
+			saa711x_write(sd, R_0F_CHROMA_GAIN_CNTL, state->gain->val | 0x80);
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int saa711x_set_size(struct v4l2_subdev *sd, int width, int height)
+{
+	struct saa711x_state *state = to_state(sd);
+	int HPSC, HFSC;
+	int VSCY;
+	int res;
+	int is_50hz = state->std & V4L2_STD_625_50;
+	int Vsrc = is_50hz ? 576 : 480;
+
+	v4l2_dbg(1, debug, sd, "decoder set size to %ix%i\n", width, height);
+
+	/* FIXME need better bounds checking here */
+	if ((width < 1) || (width > 1440))
+		return -EINVAL;
+	if ((height < 1) || (height > Vsrc))
+		return -EINVAL;
+
+	if (!saa711x_has_reg(state->ident, R_D0_B_HORIZ_PRESCALING)) {
+		/* Decoder only supports 720 columns and 480 or 576 lines */
+		if (width != 720)
+			return -EINVAL;
+		if (height != Vsrc)
+			return -EINVAL;
+	}
+
+	state->width = width;
+	state->height = height;
+
+	if (!saa711x_has_reg(state->ident, R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH))
+		return 0;
+
+	/* probably have a valid size, let's set it */
+	/* Set output width/height */
+	/* width */
+
+	saa711x_write(sd, R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH,
+					(u8) (width & 0xff));
+	saa711x_write(sd, R_CD_B_HORIZ_OUTPUT_WINDOW_LENGTH_MSB,
+					(u8) ((width >> 8) & 0xff));
+
+	/* Vertical Scaling uses height/2 */
+	res = height / 2;
+
+	/* On 60Hz, it is using a higher Vertical Output Size */
+	if (!is_50hz)
+		res += (VRES_60HZ - 480) >> 1;
+
+		/* height */
+	saa711x_write(sd, R_CE_B_VERT_OUTPUT_WINDOW_LENGTH,
+					(u8) (res & 0xff));
+	saa711x_write(sd, R_CF_B_VERT_OUTPUT_WINDOW_LENGTH_MSB,
+					(u8) ((res >> 8) & 0xff));
+
+	/* Scaling settings */
+	/* Hprescaler is floor(inres/outres) */
+	HPSC = (int)(720 / width);
+	/* 0 is not allowed (div. by zero) */
+	HPSC = HPSC ? HPSC : 1;
+	HFSC = (int)((1024 * 720) / (HPSC * width));
+	/* FIXME hardcodes to "Task B"
+	 * write H prescaler integer */
+	saa711x_write(sd, R_D0_B_HORIZ_PRESCALING,
+				(u8) (HPSC & 0x3f));
+
+	v4l2_dbg(1, debug, sd, "Hpsc: 0x%05x, Hfsc: 0x%05x\n", HPSC, HFSC);
+	/* write H fine-scaling (luminance) */
+	saa711x_write(sd, R_D8_B_HORIZ_LUMA_SCALING_INC,
+				(u8) (HFSC & 0xff));
+	saa711x_write(sd, R_D9_B_HORIZ_LUMA_SCALING_INC_MSB,
+				(u8) ((HFSC >> 8) & 0xff));
+	/* write H fine-scaling (chrominance)
+	 * must be lum/2, so i'll just bitshift :) */
+	saa711x_write(sd, R_DC_B_HORIZ_CHROMA_SCALING,
+				(u8) ((HFSC >> 1) & 0xff));
+	saa711x_write(sd, R_DD_B_HORIZ_CHROMA_SCALING_MSB,
+				(u8) ((HFSC >> 9) & 0xff));
+
+	VSCY = (int)((1024 * Vsrc) / height);
+	v4l2_dbg(1, debug, sd, "Vsrc: %d, Vscy: 0x%05x\n", Vsrc, VSCY);
+
+	/* Correct Contrast and Luminance */
+	saa711x_write(sd, R_D5_B_LUMA_CONTRAST_CNTL,
+					(u8) (64 * 1024 / VSCY));
+	saa711x_write(sd, R_D6_B_CHROMA_SATURATION_CNTL,
+					(u8) (64 * 1024 / VSCY));
+
+		/* write V fine-scaling (luminance) */
+	saa711x_write(sd, R_E0_B_VERT_LUMA_SCALING_INC,
+					(u8) (VSCY & 0xff));
+	saa711x_write(sd, R_E1_B_VERT_LUMA_SCALING_INC_MSB,
+					(u8) ((VSCY >> 8) & 0xff));
+		/* write V fine-scaling (chrominance) */
+	saa711x_write(sd, R_E2_B_VERT_CHROMA_SCALING_INC,
+					(u8) (VSCY & 0xff));
+	saa711x_write(sd, R_E3_B_VERT_CHROMA_SCALING_INC_MSB,
+					(u8) ((VSCY >> 8) & 0xff));
+
+	saa711x_writeregs(sd, saa7115_cfg_reset_scaler);
+
+	/* Activates task "B" */
+	saa711x_write(sd, R_80_GLOBAL_CNTL_1,
+				saa711x_read(sd, R_80_GLOBAL_CNTL_1) | 0x20);
+
+	return 0;
+}
+
+static void saa711x_set_v4lstd(struct v4l2_subdev *sd, v4l2_std_id std)
+{
+	struct saa711x_state *state = to_state(sd);
+
+	/* 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 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)
+		return;
+
+	state->std = std;
+
+	// This works for NTSC-M, SECAM-L and the 50Hz PAL variants.
+	if (std & V4L2_STD_525_60) {
+		v4l2_dbg(1, debug, sd, "decoder set standard 60 Hz\n");
+		saa711x_writeregs(sd, saa7115_cfg_60hz_video);
+		saa711x_set_size(sd, 720, 480);
+	} else {
+		v4l2_dbg(1, debug, sd, "decoder set standard 50 Hz\n");
+		saa711x_writeregs(sd, saa7115_cfg_50hz_video);
+		saa711x_set_size(sd, 720, 576);
+	}
+
+	/* Register 0E - Bits D6-D4 on NO-AUTO mode
+		(SAA7111 and SAA7113 doesn't have auto mode)
+	    50 Hz / 625 lines           60 Hz / 525 lines
+	000 PAL BGDHI (4.43Mhz)         NTSC M (3.58MHz)
+	001 NTSC 4.43 (50 Hz)           PAL 4.43 (60 Hz)
+	010 Combination-PAL N (3.58MHz) NTSC 4.43 (60 Hz)
+	011 NTSC N (3.58MHz)            PAL M (3.58MHz)
+	100 reserved                    NTSC-Japan (3.58MHz)
+	*/
+	if (state->ident <= V4L2_IDENT_SAA7113) {
+		u8 reg = saa711x_read(sd, R_0E_CHROMA_CNTL_1) & 0x8f;
+
+		if (std == V4L2_STD_PAL_M) {
+			reg |= 0x30;
+		} else if (std == V4L2_STD_PAL_Nc) {
+			reg |= 0x20;
+		} else if (std == V4L2_STD_PAL_60) {
+			reg |= 0x10;
+		} else if (std == V4L2_STD_NTSC_M_JP) {
+			reg |= 0x40;
+		} else if (std & V4L2_STD_SECAM) {
+			reg |= 0x50;
+		}
+		saa711x_write(sd, R_0E_CHROMA_CNTL_1, reg);
+	} else {
+		/* restart task B if needed */
+		int taskb = saa711x_read(sd, R_80_GLOBAL_CNTL_1) & 0x10;
+
+		if (taskb && state->ident == V4L2_IDENT_SAA7114) {
+			saa711x_writeregs(sd, saa7115_cfg_vbi_on);
+		}
+
+		/* switch audio mode too! */
+		saa711x_s_clock_freq(sd, state->audclk_freq);
+	}
+}
+
+/* setup the sliced VBI lcr registers according to the sliced VBI format */
+static void saa711x_set_lcr(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt)
+{
+	struct saa711x_state *state = to_state(sd);
+	int is_50hz = (state->std & V4L2_STD_625_50);
+	u8 lcr[24];
+	int i, x;
+
+#if 1
+	/* saa7113/7114/7118 VBI support are experimental */
+	if (!saa711x_has_reg(state->ident, R_41_LCR_BASE))
+		return;
+
+#else
+	/* SAA7113 and SAA7118 also should support VBI - Need testing */
+	if (state->ident != V4L2_IDENT_SAA7115)
+		return;
+#endif
+
+	for (i = 0; i <= 23; i++)
+		lcr[i] = 0xff;
+
+	if (fmt == NULL) {
+		/* raw VBI */
+		if (is_50hz)
+			for (i = 6; i <= 23; i++)
+				lcr[i] = 0xdd;
+		else
+			for (i = 10; i <= 21; i++)
+				lcr[i] = 0xdd;
+	} else {
+		/* sliced VBI */
+		/* first clear lines that cannot be captured */
+		if (is_50hz) {
+			for (i = 0; i <= 5; i++)
+				fmt->service_lines[0][i] =
+					fmt->service_lines[1][i] = 0;
+		}
+		else {
+			for (i = 0; i <= 9; i++)
+				fmt->service_lines[0][i] =
+					fmt->service_lines[1][i] = 0;
+			for (i = 22; i <= 23; i++)
+				fmt->service_lines[0][i] =
+					fmt->service_lines[1][i] = 0;
+		}
+
+		/* Now set the lcr values according to the specified service */
+		for (i = 6; i <= 23; i++) {
+			lcr[i] = 0;
+			for (x = 0; x <= 1; x++) {
+				switch (fmt->service_lines[1-x][i]) {
+					case 0:
+						lcr[i] |= 0xf << (4 * x);
+						break;
+					case V4L2_SLICED_TELETEXT_B:
+						lcr[i] |= 1 << (4 * x);
+						break;
+					case V4L2_SLICED_CAPTION_525:
+						lcr[i] |= 4 << (4 * x);
+						break;
+					case V4L2_SLICED_WSS_625:
+						lcr[i] |= 5 << (4 * x);
+						break;
+					case V4L2_SLICED_VPS:
+						lcr[i] |= 7 << (4 * x);
+						break;
+				}
+			}
+		}
+	}
+
+	/* write the lcr registers */
+	for (i = 2; i <= 23; i++) {
+		saa711x_write(sd, i - 2 + R_41_LCR_BASE, lcr[i]);
+	}
+
+	/* enable/disable raw VBI capturing */
+	saa711x_writeregs(sd, fmt == NULL ?
+				saa7115_cfg_vbi_on :
+				saa7115_cfg_vbi_off);
+}
+
+static int saa711x_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *sliced)
+{
+	static u16 lcr2vbi[] = {
+		0, V4L2_SLICED_TELETEXT_B, 0,	/* 1 */
+		0, V4L2_SLICED_CAPTION_525,	/* 4 */
+		V4L2_SLICED_WSS_625, 0,		/* 5 */
+		V4L2_SLICED_VPS, 0, 0, 0, 0,	/* 7 */
+		0, 0, 0, 0
+	};
+	int i;
+
+	memset(sliced, 0, sizeof(*sliced));
+	/* done if using raw VBI */
+	if (saa711x_read(sd, R_80_GLOBAL_CNTL_1) & 0x10)
+		return 0;
+	for (i = 2; i <= 23; i++) {
+		u8 v = saa711x_read(sd, i - 2 + R_41_LCR_BASE);
+
+		sliced->service_lines[0][i] = lcr2vbi[v >> 4];
+		sliced->service_lines[1][i] = lcr2vbi[v & 0xf];
+		sliced->service_set |=
+			sliced->service_lines[0][i] | sliced->service_lines[1][i];
+	}
+	return 0;
+}
+
+static int saa711x_s_raw_fmt(struct v4l2_subdev *sd, struct v4l2_vbi_format *fmt)
+{
+	saa711x_set_lcr(sd, NULL);
+	return 0;
+}
+
+static int saa711x_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt)
+{
+	saa711x_set_lcr(sd, fmt);
+	return 0;
+}
+
+static int saa711x_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
+{
+	if (fmt->code != V4L2_MBUS_FMT_FIXED)
+		return -EINVAL;
+	fmt->field = V4L2_FIELD_INTERLACED;
+	fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
+	return saa711x_set_size(sd, fmt->width, fmt->height);
+}
+
+/* Decode the sliced VBI data stream as created by the saa7115.
+   The format is described in the saa7115 datasheet in Tables 25 and 26
+   and in Figure 33.
+   The current implementation uses SAV/EAV codes and not the ancillary data
+   headers. The vbi->p pointer points to the R_5E_SDID byte right after the SAV
+   code. */
+static int saa711x_decode_vbi_line(struct v4l2_subdev *sd, struct v4l2_decode_vbi_line *vbi)
+{
+	struct saa711x_state *state = to_state(sd);
+	static const char vbi_no_data_pattern[] = {
+		0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0
+	};
+	u8 *p = vbi->p;
+	u32 wss;
+	int id1, id2;   /* the ID1 and ID2 bytes from the internal header */
+
+	vbi->type = 0;  /* mark result as a failure */
+	id1 = p[2];
+	id2 = p[3];
+	/* Note: the field bit is inverted for 60 Hz video */
+	if (state->std & V4L2_STD_525_60)
+		id1 ^= 0x40;
+
+	/* Skip internal header, p now points to the start of the payload */
+	p += 4;
+	vbi->p = p;
+
+	/* calculate field and line number of the VBI packet (1-23) */
+	vbi->is_second_field = ((id1 & 0x40) != 0);
+	vbi->line = (id1 & 0x3f) << 3;
+	vbi->line |= (id2 & 0x70) >> 4;
+
+	/* Obtain data type */
+	id2 &= 0xf;
+
+	/* If the VBI slicer does not detect any signal it will fill up
+	   the payload buffer with 0xa0 bytes. */
+	if (!memcmp(p, vbi_no_data_pattern, sizeof(vbi_no_data_pattern)))
+		return 0;
+
+	/* decode payloads */
+	switch (id2) {
+	case 1:
+		vbi->type = V4L2_SLICED_TELETEXT_B;
+		break;
+	case 4:
+		if (!saa711x_odd_parity(p[0]) || !saa711x_odd_parity(p[1]))
+			return 0;
+		vbi->type = V4L2_SLICED_CAPTION_525;
+		break;
+	case 5:
+		wss = saa711x_decode_wss(p);
+		if (wss == -1)
+			return 0;
+		p[0] = wss & 0xff;
+		p[1] = wss >> 8;
+		vbi->type = V4L2_SLICED_WSS_625;
+		break;
+	case 7:
+		if (saa711x_decode_vps(p, p) != 0)
+			return 0;
+		vbi->type = V4L2_SLICED_VPS;
+		break;
+	default:
+		break;
+	}
+	return 0;
+}
+
+/* ============ SAA7115 AUDIO settings (end) ============= */
+
+static int saa711x_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
+{
+	struct saa711x_state *state = to_state(sd);
+	int status;
+
+	if (state->radio)
+		return 0;
+	status = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
+
+	v4l2_dbg(1, debug, sd, "status: 0x%02x\n", status);
+	vt->signal = ((status & (1 << 6)) == 0) ? 0xffff : 0x0;
+	return 0;
+}
+
+static int saa711x_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
+{
+	struct saa711x_state *state = to_state(sd);
+
+	state->radio = 0;
+	saa711x_set_v4lstd(sd, std);
+	return 0;
+}
+
+static int saa711x_s_radio(struct v4l2_subdev *sd)
+{
+	struct saa711x_state *state = to_state(sd);
+
+	state->radio = 1;
+	return 0;
+}
+
+static int saa711x_s_routing(struct v4l2_subdev *sd,
+			     u32 input, u32 output, u32 config)
+{
+	struct saa711x_state *state = to_state(sd);
+	u8 mask = (state->ident <= V4L2_IDENT_SAA7111A) ? 0xf8 : 0xf0;
+
+	v4l2_dbg(1, debug, sd, "decoder set input %d output %d\n",
+		input, output);
+
+	/* saa7111/3 does not have these inputs */
+	if (state->ident <= V4L2_IDENT_SAA7113 &&
+	    (input == SAA7115_COMPOSITE4 ||
+	     input == SAA7115_COMPOSITE5)) {
+		return -EINVAL;
+	}
+	if (input > SAA7115_SVIDEO3)
+		return -EINVAL;
+	if (state->input == input && state->output == output)
+		return 0;
+	v4l2_dbg(1, debug, sd, "now setting %s input %s output\n",
+		(input >= SAA7115_SVIDEO0) ? "S-Video" : "Composite",
+		(output == SAA7115_IPORT_ON) ? "iport on" : "iport off");
+	state->input = input;
+
+	/* saa7111 has slightly different input numbering */
+	if (state->ident <= V4L2_IDENT_SAA7111A) {
+		if (input >= SAA7115_COMPOSITE4)
+			input -= 2;
+		/* saa7111 specific */
+		saa711x_write(sd, R_10_CHROMA_CNTL_2,
+				(saa711x_read(sd, R_10_CHROMA_CNTL_2) & 0x3f) |
+				((output & 0xc0) ^ 0x40));
+		saa711x_write(sd, R_13_RT_X_PORT_OUT_CNTL,
+				(saa711x_read(sd, R_13_RT_X_PORT_OUT_CNTL) & 0xf0) |
+				((output & 2) ? 0x0a : 0));
+	}
+
+	/* select mode */
+	saa711x_write(sd, R_02_INPUT_CNTL_1,
+		      (saa711x_read(sd, R_02_INPUT_CNTL_1) & mask) |
+		       input);
+
+	/* bypass chrominance trap for S-Video modes */
+	saa711x_write(sd, R_09_LUMA_CNTL,
+			(saa711x_read(sd, R_09_LUMA_CNTL) & 0x7f) |
+			(state->input >= SAA7115_SVIDEO0 ? 0x80 : 0x0));
+
+	state->output = output;
+	if (state->ident == V4L2_IDENT_SAA7114 ||
+			state->ident == V4L2_IDENT_SAA7115) {
+		saa711x_write(sd, R_83_X_PORT_I_O_ENA_AND_OUT_CLK,
+				(saa711x_read(sd, R_83_X_PORT_I_O_ENA_AND_OUT_CLK) & 0xfe) |
+				(state->output & 0x01));
+	}
+	return 0;
+}
+
+static int saa711x_s_gpio(struct v4l2_subdev *sd, u32 val)
+{
+	struct saa711x_state *state = to_state(sd);
+
+	if (state->ident > V4L2_IDENT_SAA7111A)
+		return -EINVAL;
+	saa711x_write(sd, 0x11, (saa711x_read(sd, 0x11) & 0x7f) |
+		(val ? 0x80 : 0));
+	return 0;
+}
+
+static int saa711x_s_stream(struct v4l2_subdev *sd, int enable)
+{
+	struct saa711x_state *state = to_state(sd);
+
+	v4l2_dbg(1, debug, sd, "%s output\n",
+			enable ? "enable" : "disable");
+
+	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;
+}
+
+static int saa711x_s_crystal_freq(struct v4l2_subdev *sd, u32 freq, u32 flags)
+{
+	struct saa711x_state *state = to_state(sd);
+
+	if (freq != SAA7115_FREQ_32_11_MHZ && freq != SAA7115_FREQ_24_576_MHZ)
+		return -EINVAL;
+	state->crystal_freq = freq;
+	state->cgcdiv = (flags & SAA7115_FREQ_FL_CGCDIV) ? 3 : 4;
+	state->ucgc = (flags & SAA7115_FREQ_FL_UCGC) ? 1 : 0;
+	state->apll = (flags & SAA7115_FREQ_FL_APLL) ? 1 : 0;
+	saa711x_s_clock_freq(sd, state->audclk_freq);
+	return 0;
+}
+
+static int saa711x_reset(struct v4l2_subdev *sd, u32 val)
+{
+	v4l2_dbg(1, debug, sd, "decoder RESET\n");
+	saa711x_writeregs(sd, saa7115_cfg_reset_scaler);
+	return 0;
+}
+
+static int saa711x_g_vbi_data(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_data *data)
+{
+	/* Note: the internal field ID is inverted for NTSC,
+	   so data->field 0 maps to the saa7115 even field,
+	   whereas for PAL it maps to the saa7115 odd field. */
+	switch (data->id) {
+	case V4L2_SLICED_WSS_625:
+		if (saa711x_read(sd, 0x6b) & 0xc0)
+			return -EIO;
+		data->data[0] = saa711x_read(sd, 0x6c);
+		data->data[1] = saa711x_read(sd, 0x6d);
+		return 0;
+	case V4L2_SLICED_CAPTION_525:
+		if (data->field == 0) {
+			/* CC */
+			if (saa711x_read(sd, 0x66) & 0x30)
+				return -EIO;
+			data->data[0] = saa711x_read(sd, 0x69);
+			data->data[1] = saa711x_read(sd, 0x6a);
+			return 0;
+		}
+		/* XDS */
+		if (saa711x_read(sd, 0x66) & 0xc0)
+			return -EIO;
+		data->data[0] = saa711x_read(sd, 0x67);
+		data->data[1] = saa711x_read(sd, 0x68);
+		return 0;
+	default:
+		return -EINVAL;
+	}
+}
+
+static int saa711x_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
+{
+	struct saa711x_state *state = to_state(sd);
+	int reg1f, reg1e;
+
+	/*
+	 * The V4L2 core already initializes std with all supported
+	 * Standards. All driver needs to do is to mask it, to remove
+	 * standards that don't apply from the mask
+	 */
+
+	reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
+	v4l2_dbg(1, debug, sd, "Status byte 2 (0x1f)=0x%02x\n", reg1f);
+
+	/* horizontal/vertical not locked */
+	if (reg1f & 0x40)
+		goto ret;
+
+	if (reg1f & 0x20)
+		*std &= V4L2_STD_525_60;
+	else
+		*std &= V4L2_STD_625_50;
+
+	if (state->ident != V4L2_IDENT_SAA7115)
+		goto ret;
+
+	reg1e = saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC);
+
+	switch (reg1e & 0x03) {
+	case 1:
+		*std &= V4L2_STD_NTSC;
+		break;
+	case 2:
+		/*
+		 * V4L2_STD_PAL just cover the european PAL standards.
+		 * This is wrong, as the device could also be using an
+		 * other PAL standard.
+		 */
+		*std &= V4L2_STD_PAL   | V4L2_STD_PAL_N  | V4L2_STD_PAL_Nc |
+			V4L2_STD_PAL_M | V4L2_STD_PAL_60;
+		break;
+	case 3:
+		*std &= V4L2_STD_SECAM;
+		break;
+	default:
+		/* Can't detect anything */
+		break;
+	}
+
+	v4l2_dbg(1, debug, sd, "Status byte 1 (0x1e)=0x%02x\n", reg1e);
+
+ret:
+	v4l2_dbg(1, debug, sd, "detected std mask = %08Lx\n", *std);
+
+	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)
+{
+	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;
+	reg->val = saa711x_read(sd, reg->reg & 0xff);
+	reg->size = 1;
+	return 0;
+}
+
+static int saa711x_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;
+	saa711x_write(sd, reg->reg & 0xff, reg->val & 0xff);
+	return 0;
+}
+#endif
+
+static int saa711x_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
+{
+	struct saa711x_state *state = to_state(sd);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	return v4l2_chip_ident_i2c_client(client, chip, state->ident, 0);
+}
+
+static int saa711x_log_status(struct v4l2_subdev *sd)
+{
+	struct saa711x_state *state = to_state(sd);
+	int reg1e, reg1f;
+	int signalOk;
+	int vcr;
+
+	v4l2_info(sd, "Audio frequency: %d Hz\n", state->audclk_freq);
+	if (state->ident != V4L2_IDENT_SAA7115) {
+		/* status for the saa7114 */
+		reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
+		signalOk = (reg1f & 0xc1) == 0x81;
+		v4l2_info(sd, "Video signal:    %s\n", signalOk ? "ok" : "bad");
+		v4l2_info(sd, "Frequency:       %s\n", (reg1f & 0x20) ? "60 Hz" : "50 Hz");
+		return 0;
+	}
+
+	/* status for the saa7115 */
+	reg1e = saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC);
+	reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
+
+	signalOk = (reg1f & 0xc1) == 0x81 && (reg1e & 0xc0) == 0x80;
+	vcr = !(reg1f & 0x10);
+
+	if (state->input >= 6)
+		v4l2_info(sd, "Input:           S-Video %d\n", state->input - 6);
+	else
+		v4l2_info(sd, "Input:           Composite %d\n", state->input);
+	v4l2_info(sd, "Video signal:    %s\n", signalOk ? (vcr ? "VCR" : "broadcast/DVD") : "bad");
+	v4l2_info(sd, "Frequency:       %s\n", (reg1f & 0x20) ? "60 Hz" : "50 Hz");
+
+	switch (reg1e & 0x03) {
+	case 1:
+		v4l2_info(sd, "Detected format: NTSC\n");
+		break;
+	case 2:
+		v4l2_info(sd, "Detected format: PAL\n");
+		break;
+	case 3:
+		v4l2_info(sd, "Detected format: SECAM\n");
+		break;
+	default:
+		v4l2_info(sd, "Detected format: BW/No color\n");
+		break;
+	}
+	v4l2_info(sd, "Width, Height:   %d, %d\n", state->width, state->height);
+	v4l2_ctrl_handler_log_status(&state->hdl, sd->name);
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static const struct v4l2_ctrl_ops saa711x_ctrl_ops = {
+	.s_ctrl = saa711x_s_ctrl,
+	.g_volatile_ctrl = saa711x_g_volatile_ctrl,
+};
+
+static const struct v4l2_subdev_core_ops saa711x_core_ops = {
+	.log_status = saa711x_log_status,
+	.g_chip_ident = saa711x_g_chip_ident,
+	.g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
+	.try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
+	.s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
+	.g_ctrl = v4l2_subdev_g_ctrl,
+	.s_ctrl = v4l2_subdev_s_ctrl,
+	.queryctrl = v4l2_subdev_queryctrl,
+	.querymenu = v4l2_subdev_querymenu,
+	.s_std = saa711x_s_std,
+	.reset = saa711x_reset,
+	.s_gpio = saa711x_s_gpio,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.g_register = saa711x_g_register,
+	.s_register = saa711x_s_register,
+#endif
+};
+
+static const struct v4l2_subdev_tuner_ops saa711x_tuner_ops = {
+	.s_radio = saa711x_s_radio,
+	.g_tuner = saa711x_g_tuner,
+};
+
+static const struct v4l2_subdev_audio_ops saa711x_audio_ops = {
+	.s_clock_freq = saa711x_s_clock_freq,
+};
+
+static const struct v4l2_subdev_video_ops saa711x_video_ops = {
+	.s_routing = saa711x_s_routing,
+	.s_crystal_freq = saa711x_s_crystal_freq,
+	.s_mbus_fmt = saa711x_s_mbus_fmt,
+	.s_stream = saa711x_s_stream,
+	.querystd = saa711x_querystd,
+	.g_input_status = saa711x_g_input_status,
+};
+
+static const struct v4l2_subdev_vbi_ops saa711x_vbi_ops = {
+	.g_vbi_data = saa711x_g_vbi_data,
+	.decode_vbi_line = saa711x_decode_vbi_line,
+	.g_sliced_fmt = saa711x_g_sliced_fmt,
+	.s_sliced_fmt = saa711x_s_sliced_fmt,
+	.s_raw_fmt = saa711x_s_raw_fmt,
+};
+
+static const struct v4l2_subdev_ops saa711x_ops = {
+	.core = &saa711x_core_ops,
+	.tuner = &saa711x_tuner_ops,
+	.audio = &saa711x_audio_ops,
+	.video = &saa711x_video_ops,
+	.vbi = &saa711x_vbi_ops,
+};
+
+/* ----------------------------------------------------------------------- */
+
+static int saa711x_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
+{
+	struct saa711x_state *state;
+	struct v4l2_subdev *sd;
+	struct v4l2_ctrl_handler *hdl;
+	int i;
+	char name[17];
+	char chip_id;
+	int autodetect = !id || id->driver_data == 1;
+
+	/* Check if the adapter supports the needed features */
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		return -EIO;
+
+	for (i = 0; i < 0x0f; i++) {
+		i2c_smbus_write_byte_data(client, 0, i);
+		name[i] = (i2c_smbus_read_byte_data(client, 0) & 0x0f) + '0';
+		if (name[i] > '9')
+			name[i] += 'a' - '9' - 1;
+	}
+	name[i] = '\0';
+
+	chip_id = name[5];
+
+	/* Check whether this chip is part of the saa711x series */
+	if (memcmp(name + 1, "f711", 4)) {
+		v4l_dbg(1, debug, client, "chip found @ 0x%x (ID %s) does not match a known saa711x chip.\n",
+			client->addr << 1, name);
+		return -ENODEV;
+	}
+
+	/* Safety check */
+	if (!autodetect && id->name[6] != chip_id) {
+		v4l_warn(client, "found saa711%c while %s was expected\n",
+			 chip_id, id->name);
+	}
+	snprintf(client->name, sizeof(client->name), "saa711%c", chip_id);
+	v4l_info(client, "saa711%c found (%s) @ 0x%x (%s)\n", chip_id, name,
+		 client->addr << 1, client->adapter->name);
+
+	state = kzalloc(sizeof(struct saa711x_state), GFP_KERNEL);
+	if (state == NULL)
+		return -ENOMEM;
+	sd = &state->sd;
+	v4l2_i2c_subdev_init(sd, client, &saa711x_ops);
+
+	hdl = &state->hdl;
+	v4l2_ctrl_handler_init(hdl, 6);
+	/* add in ascending ID order */
+	v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
+			V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
+	v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
+			V4L2_CID_CONTRAST, 0, 127, 1, 64);
+	v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
+			V4L2_CID_SATURATION, 0, 127, 1, 64);
+	v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
+			V4L2_CID_HUE, -128, 127, 1, 0);
+	state->agc = v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
+			V4L2_CID_CHROMA_AGC, 0, 1, 1, 1);
+	state->gain = v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
+			V4L2_CID_CHROMA_GAIN, 0, 127, 1, 40);
+	sd->ctrl_handler = hdl;
+	if (hdl->error) {
+		int err = hdl->error;
+
+		v4l2_ctrl_handler_free(hdl);
+		kfree(state);
+		return err;
+	}
+	v4l2_ctrl_auto_cluster(2, &state->agc, 0, true);
+
+	state->input = -1;
+	state->output = SAA7115_IPORT_ON;
+	state->enable = 1;
+	state->radio = 0;
+	switch (chip_id) {
+	case '1':
+		state->ident = V4L2_IDENT_SAA7111;
+		if (saa711x_read(sd, R_00_CHIP_VERSION) & 0xf0) {
+			v4l_info(client, "saa7111a variant found\n");
+			state->ident = V4L2_IDENT_SAA7111A;
+		}
+		break;
+	case '3':
+		state->ident = V4L2_IDENT_SAA7113;
+		break;
+	case '4':
+		state->ident = V4L2_IDENT_SAA7114;
+		break;
+	case '5':
+		state->ident = V4L2_IDENT_SAA7115;
+		break;
+	case '8':
+		state->ident = V4L2_IDENT_SAA7118;
+		break;
+	default:
+		state->ident = V4L2_IDENT_SAA7111;
+		v4l2_info(sd, "WARNING: Chip is not known - Falling back to saa7111\n");
+		break;
+	}
+
+	state->audclk_freq = 48000;
+
+	v4l2_dbg(1, debug, sd, "writing init values\n");
+
+	/* init to 60hz/48khz */
+	state->crystal_freq = SAA7115_FREQ_24_576_MHZ;
+	switch (state->ident) {
+	case V4L2_IDENT_SAA7111:
+	case V4L2_IDENT_SAA7111A:
+		saa711x_writeregs(sd, saa7111_init);
+		break;
+	case V4L2_IDENT_SAA7113:
+		saa711x_writeregs(sd, saa7113_init);
+		break;
+	default:
+		state->crystal_freq = SAA7115_FREQ_32_11_MHZ;
+		saa711x_writeregs(sd, saa7115_init_auto_input);
+	}
+	if (state->ident > V4L2_IDENT_SAA7111A)
+		saa711x_writeregs(sd, saa7115_init_misc);
+	saa711x_set_v4lstd(sd, V4L2_STD_NTSC);
+	v4l2_ctrl_handler_setup(hdl);
+
+	v4l2_dbg(1, debug, sd, "status: (1E) 0x%02x, (1F) 0x%02x\n",
+		saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC),
+		saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC));
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static int saa711x_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+
+	v4l2_device_unregister_subdev(sd);
+	v4l2_ctrl_handler_free(sd->ctrl_handler);
+	kfree(to_state(sd));
+	return 0;
+}
+
+static const struct i2c_device_id saa711x_id[] = {
+	{ "saa7115_auto", 1 }, /* autodetect */
+	{ "saa7111", 0 },
+	{ "saa7113", 0 },
+	{ "saa7114", 0 },
+	{ "saa7115", 0 },
+	{ "saa7118", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, saa711x_id);
+
+static struct i2c_driver saa711x_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "saa7115",
+	},
+	.probe		= saa711x_probe,
+	.remove		= saa711x_remove,
+	.id_table	= saa711x_id,
+};
+
+module_i2c_driver(saa711x_driver);
diff --git a/drivers/media/i2c/saa711x_regs.h b/drivers/media/i2c/saa711x_regs.h
new file mode 100644
index 0000000..4e5f2eb
--- /dev/null
+++ b/drivers/media/i2c/saa711x_regs.h
@@ -0,0 +1,549 @@
+/* saa711x - Philips SAA711x video decoder register specifications
+ *
+ * Copyright (c) 2006 Mauro Carvalho Chehab <mchehab@infradead.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#define R_00_CHIP_VERSION                             0x00
+/* Video Decoder */
+	/* Video Decoder - Frontend part */
+#define R_01_INC_DELAY                                0x01
+#define R_02_INPUT_CNTL_1                             0x02
+#define R_03_INPUT_CNTL_2                             0x03
+#define R_04_INPUT_CNTL_3                             0x04
+#define R_05_INPUT_CNTL_4                             0x05
+	/* Video Decoder - Decoder part */
+#define R_06_H_SYNC_START                             0x06
+#define R_07_H_SYNC_STOP                              0x07
+#define R_08_SYNC_CNTL                                0x08
+#define R_09_LUMA_CNTL                                0x09
+#define R_0A_LUMA_BRIGHT_CNTL                         0x0a
+#define R_0B_LUMA_CONTRAST_CNTL                       0x0b
+#define R_0C_CHROMA_SAT_CNTL                          0x0c
+#define R_0D_CHROMA_HUE_CNTL                          0x0d
+#define R_0E_CHROMA_CNTL_1                            0x0e
+#define R_0F_CHROMA_GAIN_CNTL                         0x0f
+#define R_10_CHROMA_CNTL_2                            0x10
+#define R_11_MODE_DELAY_CNTL                          0x11
+#define R_12_RT_SIGNAL_CNTL                           0x12
+#define R_13_RT_X_PORT_OUT_CNTL                       0x13
+#define R_14_ANAL_ADC_COMPAT_CNTL                     0x14
+#define R_15_VGATE_START_FID_CHG                      0x15
+#define R_16_VGATE_STOP                               0x16
+#define R_17_MISC_VGATE_CONF_AND_MSB                  0x17
+#define R_18_RAW_DATA_GAIN_CNTL                       0x18
+#define R_19_RAW_DATA_OFF_CNTL                        0x19
+#define R_1A_COLOR_KILL_LVL_CNTL                      0x1a
+#define R_1B_MISC_TVVCRDET                            0x1b
+#define R_1C_ENHAN_COMB_CTRL1                         0x1c
+#define R_1D_ENHAN_COMB_CTRL2                         0x1d
+#define R_1E_STATUS_BYTE_1_VD_DEC                     0x1e
+#define R_1F_STATUS_BYTE_2_VD_DEC                     0x1f
+
+/* Component processing and interrupt masking part */
+#define R_23_INPUT_CNTL_5                             0x23
+#define R_24_INPUT_CNTL_6                             0x24
+#define R_25_INPUT_CNTL_7                             0x25
+#define R_29_COMP_DELAY                               0x29
+#define R_2A_COMP_BRIGHT_CNTL                         0x2a
+#define R_2B_COMP_CONTRAST_CNTL                       0x2b
+#define R_2C_COMP_SAT_CNTL                            0x2c
+#define R_2D_INTERRUPT_MASK_1                         0x2d
+#define R_2E_INTERRUPT_MASK_2                         0x2e
+#define R_2F_INTERRUPT_MASK_3                         0x2f
+
+/* Audio clock generator part */
+#define R_30_AUD_MAST_CLK_CYCLES_PER_FIELD            0x30
+#define R_34_AUD_MAST_CLK_NOMINAL_INC                 0x34
+#define R_38_CLK_RATIO_AMXCLK_TO_ASCLK                0x38
+#define R_39_CLK_RATIO_ASCLK_TO_ALRCLK                0x39
+#define R_3A_AUD_CLK_GEN_BASIC_SETUP                  0x3a
+
+/* General purpose VBI data slicer part */
+#define R_40_SLICER_CNTL_1                            0x40
+#define R_41_LCR_BASE                                 0x41
+#define R_58_PROGRAM_FRAMING_CODE                     0x58
+#define R_59_H_OFF_FOR_SLICER                         0x59
+#define R_5A_V_OFF_FOR_SLICER                         0x5a
+#define R_5B_FLD_OFF_AND_MSB_FOR_H_AND_V_OFF          0x5b
+#define R_5D_DID                                      0x5d
+#define R_5E_SDID                                     0x5e
+#define R_60_SLICER_STATUS_BYTE_0                     0x60
+#define R_61_SLICER_STATUS_BYTE_1                     0x61
+#define R_62_SLICER_STATUS_BYTE_2                     0x62
+
+/* X port, I port and the scaler part */
+	/* Task independent global settings */
+#define R_80_GLOBAL_CNTL_1                            0x80
+#define R_81_V_SYNC_FLD_ID_SRC_SEL_AND_RETIMED_V_F    0x81
+#define R_83_X_PORT_I_O_ENA_AND_OUT_CLK               0x83
+#define R_84_I_PORT_SIGNAL_DEF                        0x84
+#define R_85_I_PORT_SIGNAL_POLAR                      0x85
+#define R_86_I_PORT_FIFO_FLAG_CNTL_AND_ARBIT          0x86
+#define R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED         0x87
+#define R_88_POWER_SAVE_ADC_PORT_CNTL                 0x88
+#define R_8F_STATUS_INFO_SCALER                       0x8f
+	/* Task A definition */
+		/* Basic settings and acquisition window definition */
+#define R_90_A_TASK_HANDLING_CNTL                     0x90
+#define R_91_A_X_PORT_FORMATS_AND_CONF                0x91
+#define R_92_A_X_PORT_INPUT_REFERENCE_SIGNAL          0x92
+#define R_93_A_I_PORT_OUTPUT_FORMATS_AND_CONF         0x93
+#define R_94_A_HORIZ_INPUT_WINDOW_START               0x94
+#define R_95_A_HORIZ_INPUT_WINDOW_START_MSB           0x95
+#define R_96_A_HORIZ_INPUT_WINDOW_LENGTH              0x96
+#define R_97_A_HORIZ_INPUT_WINDOW_LENGTH_MSB          0x97
+#define R_98_A_VERT_INPUT_WINDOW_START                0x98
+#define R_99_A_VERT_INPUT_WINDOW_START_MSB            0x99
+#define R_9A_A_VERT_INPUT_WINDOW_LENGTH               0x9a
+#define R_9B_A_VERT_INPUT_WINDOW_LENGTH_MSB           0x9b
+#define R_9C_A_HORIZ_OUTPUT_WINDOW_LENGTH             0x9c
+#define R_9D_A_HORIZ_OUTPUT_WINDOW_LENGTH_MSB         0x9d
+#define R_9E_A_VERT_OUTPUT_WINDOW_LENGTH              0x9e
+#define R_9F_A_VERT_OUTPUT_WINDOW_LENGTH_MSB          0x9f
+		/* FIR filtering and prescaling */
+#define R_A0_A_HORIZ_PRESCALING                       0xa0
+#define R_A1_A_ACCUMULATION_LENGTH                    0xa1
+#define R_A2_A_PRESCALER_DC_GAIN_AND_FIR_PREFILTER    0xa2
+#define R_A4_A_LUMA_BRIGHTNESS_CNTL                   0xa4
+#define R_A5_A_LUMA_CONTRAST_CNTL                     0xa5
+#define R_A6_A_CHROMA_SATURATION_CNTL                 0xa6
+		/* Horizontal phase scaling */
+#define R_A8_A_HORIZ_LUMA_SCALING_INC                 0xa8
+#define R_A9_A_HORIZ_LUMA_SCALING_INC_MSB             0xa9
+#define R_AA_A_HORIZ_LUMA_PHASE_OFF                   0xaa
+#define R_AC_A_HORIZ_CHROMA_SCALING_INC               0xac
+#define R_AD_A_HORIZ_CHROMA_SCALING_INC_MSB           0xad
+#define R_AE_A_HORIZ_CHROMA_PHASE_OFF                 0xae
+#define R_AF_A_HORIZ_CHROMA_PHASE_OFF_MSB             0xaf
+		/* Vertical scaling */
+#define R_B0_A_VERT_LUMA_SCALING_INC                  0xb0
+#define R_B1_A_VERT_LUMA_SCALING_INC_MSB              0xb1
+#define R_B2_A_VERT_CHROMA_SCALING_INC                0xb2
+#define R_B3_A_VERT_CHROMA_SCALING_INC_MSB            0xb3
+#define R_B4_A_VERT_SCALING_MODE_CNTL                 0xb4
+#define R_B8_A_VERT_CHROMA_PHASE_OFF_00               0xb8
+#define R_B9_A_VERT_CHROMA_PHASE_OFF_01               0xb9
+#define R_BA_A_VERT_CHROMA_PHASE_OFF_10               0xba
+#define R_BB_A_VERT_CHROMA_PHASE_OFF_11               0xbb
+#define R_BC_A_VERT_LUMA_PHASE_OFF_00                 0xbc
+#define R_BD_A_VERT_LUMA_PHASE_OFF_01                 0xbd
+#define R_BE_A_VERT_LUMA_PHASE_OFF_10                 0xbe
+#define R_BF_A_VERT_LUMA_PHASE_OFF_11                 0xbf
+	/* Task B definition */
+		/* Basic settings and acquisition window definition */
+#define R_C0_B_TASK_HANDLING_CNTL                     0xc0
+#define R_C1_B_X_PORT_FORMATS_AND_CONF                0xc1
+#define R_C2_B_INPUT_REFERENCE_SIGNAL_DEFINITION      0xc2
+#define R_C3_B_I_PORT_FORMATS_AND_CONF                0xc3
+#define R_C4_B_HORIZ_INPUT_WINDOW_START               0xc4
+#define R_C5_B_HORIZ_INPUT_WINDOW_START_MSB           0xc5
+#define R_C6_B_HORIZ_INPUT_WINDOW_LENGTH              0xc6
+#define R_C7_B_HORIZ_INPUT_WINDOW_LENGTH_MSB          0xc7
+#define R_C8_B_VERT_INPUT_WINDOW_START                0xc8
+#define R_C9_B_VERT_INPUT_WINDOW_START_MSB            0xc9
+#define R_CA_B_VERT_INPUT_WINDOW_LENGTH               0xca
+#define R_CB_B_VERT_INPUT_WINDOW_LENGTH_MSB           0xcb
+#define R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH             0xcc
+#define R_CD_B_HORIZ_OUTPUT_WINDOW_LENGTH_MSB         0xcd
+#define R_CE_B_VERT_OUTPUT_WINDOW_LENGTH              0xce
+#define R_CF_B_VERT_OUTPUT_WINDOW_LENGTH_MSB          0xcf
+		/* FIR filtering and prescaling */
+#define R_D0_B_HORIZ_PRESCALING                       0xd0
+#define R_D1_B_ACCUMULATION_LENGTH                    0xd1
+#define R_D2_B_PRESCALER_DC_GAIN_AND_FIR_PREFILTER    0xd2
+#define R_D4_B_LUMA_BRIGHTNESS_CNTL                   0xd4
+#define R_D5_B_LUMA_CONTRAST_CNTL                     0xd5
+#define R_D6_B_CHROMA_SATURATION_CNTL                 0xd6
+		/* Horizontal phase scaling */
+#define R_D8_B_HORIZ_LUMA_SCALING_INC                 0xd8
+#define R_D9_B_HORIZ_LUMA_SCALING_INC_MSB             0xd9
+#define R_DA_B_HORIZ_LUMA_PHASE_OFF                   0xda
+#define R_DC_B_HORIZ_CHROMA_SCALING                   0xdc
+#define R_DD_B_HORIZ_CHROMA_SCALING_MSB               0xdd
+#define R_DE_B_HORIZ_PHASE_OFFSET_CRHOMA              0xde
+		/* Vertical scaling */
+#define R_E0_B_VERT_LUMA_SCALING_INC                  0xe0
+#define R_E1_B_VERT_LUMA_SCALING_INC_MSB              0xe1
+#define R_E2_B_VERT_CHROMA_SCALING_INC                0xe2
+#define R_E3_B_VERT_CHROMA_SCALING_INC_MSB            0xe3
+#define R_E4_B_VERT_SCALING_MODE_CNTL                 0xe4
+#define R_E8_B_VERT_CHROMA_PHASE_OFF_00               0xe8
+#define R_E9_B_VERT_CHROMA_PHASE_OFF_01               0xe9
+#define R_EA_B_VERT_CHROMA_PHASE_OFF_10               0xea
+#define R_EB_B_VERT_CHROMA_PHASE_OFF_11               0xeb
+#define R_EC_B_VERT_LUMA_PHASE_OFF_00                 0xec
+#define R_ED_B_VERT_LUMA_PHASE_OFF_01                 0xed
+#define R_EE_B_VERT_LUMA_PHASE_OFF_10                 0xee
+#define R_EF_B_VERT_LUMA_PHASE_OFF_11                 0xef
+
+/* second PLL (PLL2) and Pulsegenerator Programming */
+#define R_F0_LFCO_PER_LINE                            0xf0
+#define R_F1_P_I_PARAM_SELECT                         0xf1
+#define R_F2_NOMINAL_PLL2_DTO                         0xf2
+#define R_F3_PLL_INCREMENT                            0xf3
+#define R_F4_PLL2_STATUS                              0xf4
+#define R_F5_PULSGEN_LINE_LENGTH                      0xf5
+#define R_F6_PULSE_A_POS_LSB_AND_PULSEGEN_CONFIG      0xf6
+#define R_F7_PULSE_A_POS_MSB                          0xf7
+#define R_F8_PULSE_B_POS                              0xf8
+#define R_F9_PULSE_B_POS_MSB                          0xf9
+#define R_FA_PULSE_C_POS                              0xfa
+#define R_FB_PULSE_C_POS_MSB                          0xfb
+#define R_FF_S_PLL_MAX_PHASE_ERR_THRESH_NUM_LINES     0xff
+
+#if 0
+/* Those structs will be used in the future for debug purposes */
+struct saa711x_reg_descr {
+	u8 reg;
+	int count;
+	char *name;
+};
+
+struct saa711x_reg_descr saa711x_regs[] = {
+	/* REG COUNT NAME */
+	{R_00_CHIP_VERSION,1,
+	 "Chip version"},
+
+	/* Video Decoder: R_01_INC_DELAY to R_1F_STATUS_BYTE_2_VD_DEC */
+
+	/* Video Decoder - Frontend part: R_01_INC_DELAY to R_05_INPUT_CNTL_4 */
+	{R_01_INC_DELAY,1,
+	 "Increment delay"},
+	{R_02_INPUT_CNTL_1,1,
+	 "Analog input control 1"},
+	{R_03_INPUT_CNTL_2,1,
+	 "Analog input control 2"},
+	{R_04_INPUT_CNTL_3,1,
+	 "Analog input control 3"},
+	{R_05_INPUT_CNTL_4,1,
+	 "Analog input control 4"},
+
+	/* Video Decoder - Decoder part: R_06_H_SYNC_START to R_1F_STATUS_BYTE_2_VD_DEC */
+	{R_06_H_SYNC_START,1,
+	 "Horizontal sync start"},
+	{R_07_H_SYNC_STOP,1,
+	 "Horizontal sync stop"},
+	{R_08_SYNC_CNTL,1,
+	 "Sync control"},
+	{R_09_LUMA_CNTL,1,
+	 "Luminance control"},
+	{R_0A_LUMA_BRIGHT_CNTL,1,
+	 "Luminance brightness control"},
+	{R_0B_LUMA_CONTRAST_CNTL,1,
+	 "Luminance contrast control"},
+	{R_0C_CHROMA_SAT_CNTL,1,
+	 "Chrominance saturation control"},
+	{R_0D_CHROMA_HUE_CNTL,1,
+	 "Chrominance hue control"},
+	{R_0E_CHROMA_CNTL_1,1,
+	 "Chrominance control 1"},
+	{R_0F_CHROMA_GAIN_CNTL,1,
+	 "Chrominance gain control"},
+	{R_10_CHROMA_CNTL_2,1,
+	 "Chrominance control 2"},
+	{R_11_MODE_DELAY_CNTL,1,
+	 "Mode/delay control"},
+	{R_12_RT_SIGNAL_CNTL,1,
+	 "RT signal control"},
+	{R_13_RT_X_PORT_OUT_CNTL,1,
+	 "RT/X port output control"},
+	{R_14_ANAL_ADC_COMPAT_CNTL,1,
+	 "Analog/ADC/compatibility control"},
+	{R_15_VGATE_START_FID_CHG,  1,
+	 "VGATE start FID change"},
+	{R_16_VGATE_STOP,1,
+	 "VGATE stop"},
+	{R_17_MISC_VGATE_CONF_AND_MSB,  1,
+	 "Miscellaneous VGATE configuration and MSBs"},
+	{R_18_RAW_DATA_GAIN_CNTL,1,
+	 "Raw data gain control",},
+	{R_19_RAW_DATA_OFF_CNTL,1,
+	 "Raw data offset control",},
+	{R_1A_COLOR_KILL_LVL_CNTL,1,
+	 "Color Killer Level Control"},
+	{ R_1B_MISC_TVVCRDET, 1,
+	  "MISC /TVVCRDET"},
+	{ R_1C_ENHAN_COMB_CTRL1, 1,
+	 "Enhanced comb ctrl1"},
+	{ R_1D_ENHAN_COMB_CTRL2, 1,
+	 "Enhanced comb ctrl1"},
+	{R_1E_STATUS_BYTE_1_VD_DEC,1,
+	 "Status byte 1 video decoder"},
+	{R_1F_STATUS_BYTE_2_VD_DEC,1,
+	 "Status byte 2 video decoder"},
+
+	/* Component processing and interrupt masking part:  0x20h to R_2F_INTERRUPT_MASK_3 */
+	/* 0x20 to 0x22 - Reserved */
+	{R_23_INPUT_CNTL_5,1,
+	 "Analog input control 5"},
+	{R_24_INPUT_CNTL_6,1,
+	 "Analog input control 6"},
+	{R_25_INPUT_CNTL_7,1,
+	 "Analog input control 7"},
+	/* 0x26 to 0x28 - Reserved */
+	{R_29_COMP_DELAY,1,
+	 "Component delay"},
+	{R_2A_COMP_BRIGHT_CNTL,1,
+	 "Component brightness control"},
+	{R_2B_COMP_CONTRAST_CNTL,1,
+	 "Component contrast control"},
+	{R_2C_COMP_SAT_CNTL,1,
+	 "Component saturation control"},
+	{R_2D_INTERRUPT_MASK_1,1,
+	 "Interrupt mask 1"},
+	{R_2E_INTERRUPT_MASK_2,1,
+	 "Interrupt mask 2"},
+	{R_2F_INTERRUPT_MASK_3,1,
+	 "Interrupt mask 3"},
+
+	/* Audio clock generator part: R_30_AUD_MAST_CLK_CYCLES_PER_FIELD to 0x3f */
+	{R_30_AUD_MAST_CLK_CYCLES_PER_FIELD,3,
+	 "Audio master clock cycles per field"},
+	/* 0x33 - Reserved */
+	{R_34_AUD_MAST_CLK_NOMINAL_INC,3,
+	 "Audio master clock nominal increment"},
+	/* 0x37 - Reserved */
+	{R_38_CLK_RATIO_AMXCLK_TO_ASCLK,1,
+	 "Clock ratio AMXCLK to ASCLK"},
+	{R_39_CLK_RATIO_ASCLK_TO_ALRCLK,1,
+	 "Clock ratio ASCLK to ALRCLK"},
+	{R_3A_AUD_CLK_GEN_BASIC_SETUP,1,
+	 "Audio clock generator basic setup"},
+	/* 0x3b-0x3f - Reserved */
+
+	/* General purpose VBI data slicer part: R_40_SLICER_CNTL_1 to 0x7f */
+	{R_40_SLICER_CNTL_1,1,
+	 "Slicer control 1"},
+	{R_41_LCR,23,
+	 "R_41_LCR"},
+	{R_58_PROGRAM_FRAMING_CODE,1,
+	 "Programmable framing code"},
+	{R_59_H_OFF_FOR_SLICER,1,
+	 "Horizontal offset for slicer"},
+	{R_5A_V_OFF_FOR_SLICER,1,
+	 "Vertical offset for slicer"},
+	{R_5B_FLD_OFF_AND_MSB_FOR_H_AND_V_OFF,1,
+	 "Field offset and MSBs for horizontal and vertical offset"},
+	{R_5D_DID,1,
+	 "Header and data identification (R_5D_DID)"},
+	{R_5E_SDID,1,
+	 "Sliced data identification (R_5E_SDID) code"},
+	{R_60_SLICER_STATUS_BYTE_0,1,
+	 "Slicer status byte 0"},
+	{R_61_SLICER_STATUS_BYTE_1,1,
+	 "Slicer status byte 1"},
+	{R_62_SLICER_STATUS_BYTE_2,1,
+	 "Slicer status byte 2"},
+	/* 0x63-0x7f - Reserved */
+
+	/* X port, I port and the scaler part: R_80_GLOBAL_CNTL_1 to R_EF_B_VERT_LUMA_PHASE_OFF_11 */
+	/* Task independent global settings: R_80_GLOBAL_CNTL_1 to R_8F_STATUS_INFO_SCALER */
+	{R_80_GLOBAL_CNTL_1,1,
+	 "Global control 1"},
+	{R_81_V_SYNC_FLD_ID_SRC_SEL_AND_RETIMED_V_F,1,
+	 "Vertical sync and Field ID source selection, retimed V and F signals"},
+	/* 0x82 - Reserved */
+	{R_83_X_PORT_I_O_ENA_AND_OUT_CLK,1,
+	 "X port I/O enable and output clock"},
+	{R_84_I_PORT_SIGNAL_DEF,1,
+	 "I port signal definitions"},
+	{R_85_I_PORT_SIGNAL_POLAR,1,
+	 "I port signal polarities"},
+	{R_86_I_PORT_FIFO_FLAG_CNTL_AND_ARBIT,1,
+	 "I port FIFO flag control and arbitration"},
+	{R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED,  1,
+	 "I port I/O enable output clock and gated"},
+	{R_88_POWER_SAVE_ADC_PORT_CNTL,1,
+	 "Power save/ADC port control"},
+	/* 089-0x8e - Reserved */
+	{R_8F_STATUS_INFO_SCALER,1,
+	 "Status information scaler part"},
+
+	/* Task A definition: R_90_A_TASK_HANDLING_CNTL to R_BF_A_VERT_LUMA_PHASE_OFF_11 */
+	/* Task A: Basic settings and acquisition window definition */
+	{R_90_A_TASK_HANDLING_CNTL,1,
+	 "Task A: Task handling control"},
+	{R_91_A_X_PORT_FORMATS_AND_CONF,1,
+	 "Task A: X port formats and configuration"},
+	{R_92_A_X_PORT_INPUT_REFERENCE_SIGNAL,1,
+	 "Task A: X port input reference signal definition"},
+	{R_93_A_I_PORT_OUTPUT_FORMATS_AND_CONF,1,
+	 "Task A: I port output formats and configuration"},
+	{R_94_A_HORIZ_INPUT_WINDOW_START,2,
+	 "Task A: Horizontal input window start"},
+	{R_96_A_HORIZ_INPUT_WINDOW_LENGTH,2,
+	 "Task A: Horizontal input window length"},
+	{R_98_A_VERT_INPUT_WINDOW_START,2,
+	 "Task A: Vertical input window start"},
+	{R_9A_A_VERT_INPUT_WINDOW_LENGTH,2,
+	 "Task A: Vertical input window length"},
+	{R_9C_A_HORIZ_OUTPUT_WINDOW_LENGTH,2,
+	 "Task A: Horizontal output window length"},
+	{R_9E_A_VERT_OUTPUT_WINDOW_LENGTH,2,
+	 "Task A: Vertical output window length"},
+
+	/* Task A: FIR filtering and prescaling */
+	{R_A0_A_HORIZ_PRESCALING,1,
+	 "Task A: Horizontal prescaling"},
+	{R_A1_A_ACCUMULATION_LENGTH,1,
+	 "Task A: Accumulation length"},
+	{R_A2_A_PRESCALER_DC_GAIN_AND_FIR_PREFILTER,1,
+	 "Task A: Prescaler DC gain and FIR prefilter"},
+	/* 0xa3 - Reserved */
+	{R_A4_A_LUMA_BRIGHTNESS_CNTL,1,
+	 "Task A: Luminance brightness control"},
+	{R_A5_A_LUMA_CONTRAST_CNTL,1,
+	 "Task A: Luminance contrast control"},
+	{R_A6_A_CHROMA_SATURATION_CNTL,1,
+	 "Task A: Chrominance saturation control"},
+	/* 0xa7 - Reserved */
+
+	/* Task A: Horizontal phase scaling */
+	{R_A8_A_HORIZ_LUMA_SCALING_INC,2,
+	 "Task A: Horizontal luminance scaling increment"},
+	{R_AA_A_HORIZ_LUMA_PHASE_OFF,1,
+	 "Task A: Horizontal luminance phase offset"},
+	/* 0xab - Reserved */
+	{R_AC_A_HORIZ_CHROMA_SCALING_INC,2,
+	 "Task A: Horizontal chrominance scaling increment"},
+	{R_AE_A_HORIZ_CHROMA_PHASE_OFF,1,
+	 "Task A: Horizontal chrominance phase offset"},
+	/* 0xaf - Reserved */
+
+	/* Task A: Vertical scaling */
+	{R_B0_A_VERT_LUMA_SCALING_INC,2,
+	 "Task A: Vertical luminance scaling increment"},
+	{R_B2_A_VERT_CHROMA_SCALING_INC,2,
+	 "Task A: Vertical chrominance scaling increment"},
+	{R_B4_A_VERT_SCALING_MODE_CNTL,1,
+	 "Task A: Vertical scaling mode control"},
+	/* 0xb5-0xb7 - Reserved */
+	{R_B8_A_VERT_CHROMA_PHASE_OFF_00,1,
+	 "Task A: Vertical chrominance phase offset '00'"},
+	{R_B9_A_VERT_CHROMA_PHASE_OFF_01,1,
+	 "Task A: Vertical chrominance phase offset '01'"},
+	{R_BA_A_VERT_CHROMA_PHASE_OFF_10,1,
+	 "Task A: Vertical chrominance phase offset '10'"},
+	{R_BB_A_VERT_CHROMA_PHASE_OFF_11,1,
+	 "Task A: Vertical chrominance phase offset '11'"},
+	{R_BC_A_VERT_LUMA_PHASE_OFF_00,1,
+	 "Task A: Vertical luminance phase offset '00'"},
+	{R_BD_A_VERT_LUMA_PHASE_OFF_01,1,
+	 "Task A: Vertical luminance phase offset '01'"},
+	{R_BE_A_VERT_LUMA_PHASE_OFF_10,1,
+	 "Task A: Vertical luminance phase offset '10'"},
+	{R_BF_A_VERT_LUMA_PHASE_OFF_11,1,
+	 "Task A: Vertical luminance phase offset '11'"},
+
+	/* Task B definition: R_C0_B_TASK_HANDLING_CNTL to R_EF_B_VERT_LUMA_PHASE_OFF_11 */
+	/* Task B: Basic settings and acquisition window definition */
+	{R_C0_B_TASK_HANDLING_CNTL,1,
+	 "Task B: Task handling control"},
+	{R_C1_B_X_PORT_FORMATS_AND_CONF,1,
+	 "Task B: X port formats and configuration"},
+	{R_C2_B_INPUT_REFERENCE_SIGNAL_DEFINITION,1,
+	 "Task B: Input reference signal definition"},
+	{R_C3_B_I_PORT_FORMATS_AND_CONF,1,
+	 "Task B: I port formats and configuration"},
+	{R_C4_B_HORIZ_INPUT_WINDOW_START,2,
+	 "Task B: Horizontal input window start"},
+	{R_C6_B_HORIZ_INPUT_WINDOW_LENGTH,2,
+	 "Task B: Horizontal input window length"},
+	{R_C8_B_VERT_INPUT_WINDOW_START,2,
+	 "Task B: Vertical input window start"},
+	{R_CA_B_VERT_INPUT_WINDOW_LENGTH,2,
+	 "Task B: Vertical input window length"},
+	{R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH,2,
+	 "Task B: Horizontal output window length"},
+	{R_CE_B_VERT_OUTPUT_WINDOW_LENGTH,2,
+	 "Task B: Vertical output window length"},
+
+	/* Task B: FIR filtering and prescaling */
+	{R_D0_B_HORIZ_PRESCALING,1,
+	 "Task B: Horizontal prescaling"},
+	{R_D1_B_ACCUMULATION_LENGTH,1,
+	 "Task B: Accumulation length"},
+	{R_D2_B_PRESCALER_DC_GAIN_AND_FIR_PREFILTER,1,
+	 "Task B: Prescaler DC gain and FIR prefilter"},
+	/* 0xd3 - Reserved */
+	{R_D4_B_LUMA_BRIGHTNESS_CNTL,1,
+	 "Task B: Luminance brightness control"},
+	{R_D5_B_LUMA_CONTRAST_CNTL,1,
+	 "Task B: Luminance contrast control"},
+	{R_D6_B_CHROMA_SATURATION_CNTL,1,
+	 "Task B: Chrominance saturation control"},
+	/* 0xd7 - Reserved */
+
+	/* Task B: Horizontal phase scaling */
+	{R_D8_B_HORIZ_LUMA_SCALING_INC,2,
+	 "Task B: Horizontal luminance scaling increment"},
+	{R_DA_B_HORIZ_LUMA_PHASE_OFF,1,
+	 "Task B: Horizontal luminance phase offset"},
+	/* 0xdb - Reserved */
+	{R_DC_B_HORIZ_CHROMA_SCALING,2,
+	 "Task B: Horizontal chrominance scaling"},
+	{R_DE_B_HORIZ_PHASE_OFFSET_CRHOMA,1,
+	 "Task B: Horizontal Phase Offset Chroma"},
+	/* 0xdf - Reserved */
+
+	/* Task B: Vertical scaling */
+	{R_E0_B_VERT_LUMA_SCALING_INC,2,
+	 "Task B: Vertical luminance scaling increment"},
+	{R_E2_B_VERT_CHROMA_SCALING_INC,2,
+	 "Task B: Vertical chrominance scaling increment"},
+	{R_E4_B_VERT_SCALING_MODE_CNTL,1,
+	 "Task B: Vertical scaling mode control"},
+	/* 0xe5-0xe7 - Reserved */
+	{R_E8_B_VERT_CHROMA_PHASE_OFF_00,1,
+	 "Task B: Vertical chrominance phase offset '00'"},
+	{R_E9_B_VERT_CHROMA_PHASE_OFF_01,1,
+	 "Task B: Vertical chrominance phase offset '01'"},
+	{R_EA_B_VERT_CHROMA_PHASE_OFF_10,1,
+	 "Task B: Vertical chrominance phase offset '10'"},
+	{R_EB_B_VERT_CHROMA_PHASE_OFF_11,1,
+	 "Task B: Vertical chrominance phase offset '11'"},
+	{R_EC_B_VERT_LUMA_PHASE_OFF_00,1,
+	 "Task B: Vertical luminance phase offset '00'"},
+	{R_ED_B_VERT_LUMA_PHASE_OFF_01,1,
+	 "Task B: Vertical luminance phase offset '01'"},
+	{R_EE_B_VERT_LUMA_PHASE_OFF_10,1,
+	 "Task B: Vertical luminance phase offset '10'"},
+	{R_EF_B_VERT_LUMA_PHASE_OFF_11,1,
+	 "Task B: Vertical luminance phase offset '11'"},
+
+	/* second PLL (PLL2) and Pulsegenerator Programming */
+	{ R_F0_LFCO_PER_LINE, 1,
+	  "LFCO's per line"},
+	{ R_F1_P_I_PARAM_SELECT,1,
+	  "P-/I- Param. Select., PLL Mode, PLL H-Src., LFCO's per line"},
+	{ R_F2_NOMINAL_PLL2_DTO,1,
+	 "Nominal PLL2 DTO"},
+	{R_F3_PLL_INCREMENT,1,
+	 "PLL2 Increment"},
+	{R_F4_PLL2_STATUS,1,
+	 "PLL2 Status"},
+	{R_F5_PULSGEN_LINE_LENGTH,1,
+	 "Pulsgen. line length"},
+	{R_F6_PULSE_A_POS_LSB_AND_PULSEGEN_CONFIG,1,
+	 "Pulse A Position, Pulsgen Resync., Pulsgen. H-Src., Pulsgen. line length"},
+	{R_F7_PULSE_A_POS_MSB,1,
+	 "Pulse A Position"},
+	{R_F8_PULSE_B_POS,2,
+	 "Pulse B Position"},
+	{R_FA_PULSE_C_POS,2,
+	 "Pulse C Position"},
+	/* 0xfc to 0xfe - Reserved */
+	{R_FF_S_PLL_MAX_PHASE_ERR_THRESH_NUM_LINES,1,
+	 "S_PLL max. phase, error threshold, PLL2 no. of lines, threshold"},
+};
+#endif
diff --git a/drivers/media/i2c/saa7127.c b/drivers/media/i2c/saa7127.c
new file mode 100644
index 0000000..8ecb656
--- /dev/null
+++ b/drivers/media/i2c/saa7127.c
@@ -0,0 +1,852 @@
+/*
+ * saa7127 - Philips SAA7127/SAA7129 video encoder driver
+ *
+ * Copyright (C) 2003 Roy Bulter <rbulter@hetnet.nl>
+ *
+ * Based on SAA7126 video encoder driver by Gillem & Andreas Oberritter
+ *
+ * Copyright (C) 2000-2001 Gillem <htoa@gmx.net>
+ * Copyright (C) 2002 Andreas Oberritter <obi@saftware.de>
+ *
+ * Based on Stadis 4:2:2 MPEG-2 Decoder Driver by Nathan Laredo
+ *
+ * Copyright (C) 1999 Nathan Laredo <laredo@gnu.org>
+ *
+ * This driver is designed for the Hauppauge 250/350 Linux driver
+ * from the ivtv Project
+ *
+ * Copyright (C) 2003 Kevin Thayer <nufan_wfk@yahoo.com>
+ *
+ * Dual output support:
+ * Copyright (C) 2004 Eric Varsanyi
+ *
+ * NTSC Tuning and 7.5 IRE Setup
+ * Copyright (C) 2004  Chris Kennedy <c@groovy.org>
+ *
+ * VBI additions & cleanup:
+ * Copyright (C) 2004, 2005 Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ * Note: the saa7126 is identical to the saa7127, and the saa7128 is
+ * identical to the saa7129, except that the saa7126 and saa7128 have
+ * macrovision anti-taping support. This driver will almost certainly
+ * work fine for those chips, except of course for the missing anti-taping
+ * support.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/saa7127.h>
+
+static int debug;
+static int test_image;
+
+MODULE_DESCRIPTION("Philips SAA7127/9 video encoder driver");
+MODULE_AUTHOR("Kevin Thayer, Chris Kennedy, Hans Verkuil");
+MODULE_LICENSE("GPL");
+module_param(debug, int, 0644);
+module_param(test_image, int, 0644);
+MODULE_PARM_DESC(debug, "debug level (0-2)");
+MODULE_PARM_DESC(test_image, "test_image (0-1)");
+
+
+/*
+ * SAA7127 registers
+ */
+
+#define SAA7127_REG_STATUS                           0x00
+#define SAA7127_REG_WIDESCREEN_CONFIG                0x26
+#define SAA7127_REG_WIDESCREEN_ENABLE                0x27
+#define SAA7127_REG_BURST_START                      0x28
+#define SAA7127_REG_BURST_END                        0x29
+#define SAA7127_REG_COPYGEN_0                        0x2a
+#define SAA7127_REG_COPYGEN_1                        0x2b
+#define SAA7127_REG_COPYGEN_2                        0x2c
+#define SAA7127_REG_OUTPUT_PORT_CONTROL              0x2d
+#define SAA7127_REG_GAIN_LUMINANCE_RGB               0x38
+#define SAA7127_REG_GAIN_COLORDIFF_RGB               0x39
+#define SAA7127_REG_INPUT_PORT_CONTROL_1             0x3a
+#define SAA7129_REG_FADE_KEY_COL2		     0x4f
+#define SAA7127_REG_CHROMA_PHASE                     0x5a
+#define SAA7127_REG_GAINU                            0x5b
+#define SAA7127_REG_GAINV                            0x5c
+#define SAA7127_REG_BLACK_LEVEL                      0x5d
+#define SAA7127_REG_BLANKING_LEVEL                   0x5e
+#define SAA7127_REG_VBI_BLANKING                     0x5f
+#define SAA7127_REG_DAC_CONTROL                      0x61
+#define SAA7127_REG_BURST_AMP                        0x62
+#define SAA7127_REG_SUBC3                            0x63
+#define SAA7127_REG_SUBC2                            0x64
+#define SAA7127_REG_SUBC1                            0x65
+#define SAA7127_REG_SUBC0                            0x66
+#define SAA7127_REG_LINE_21_ODD_0                    0x67
+#define SAA7127_REG_LINE_21_ODD_1                    0x68
+#define SAA7127_REG_LINE_21_EVEN_0                   0x69
+#define SAA7127_REG_LINE_21_EVEN_1                   0x6a
+#define SAA7127_REG_RCV_PORT_CONTROL                 0x6b
+#define SAA7127_REG_VTRIG                            0x6c
+#define SAA7127_REG_HTRIG_HI                         0x6d
+#define SAA7127_REG_MULTI                            0x6e
+#define SAA7127_REG_CLOSED_CAPTION                   0x6f
+#define SAA7127_REG_RCV2_OUTPUT_START                0x70
+#define SAA7127_REG_RCV2_OUTPUT_END                  0x71
+#define SAA7127_REG_RCV2_OUTPUT_MSBS                 0x72
+#define SAA7127_REG_TTX_REQUEST_H_START              0x73
+#define SAA7127_REG_TTX_REQUEST_H_DELAY_LENGTH       0x74
+#define SAA7127_REG_CSYNC_ADVANCE_VSYNC_SHIFT        0x75
+#define SAA7127_REG_TTX_ODD_REQ_VERT_START           0x76
+#define SAA7127_REG_TTX_ODD_REQ_VERT_END             0x77
+#define SAA7127_REG_TTX_EVEN_REQ_VERT_START          0x78
+#define SAA7127_REG_TTX_EVEN_REQ_VERT_END            0x79
+#define SAA7127_REG_FIRST_ACTIVE                     0x7a
+#define SAA7127_REG_LAST_ACTIVE                      0x7b
+#define SAA7127_REG_MSB_VERTICAL                     0x7c
+#define SAA7127_REG_DISABLE_TTX_LINE_LO_0            0x7e
+#define SAA7127_REG_DISABLE_TTX_LINE_LO_1            0x7f
+
+/*
+ **********************************************************************
+ *
+ *  Arrays with configuration parameters for the SAA7127
+ *
+ **********************************************************************
+ */
+
+struct i2c_reg_value {
+	unsigned char reg;
+	unsigned char value;
+};
+
+static const struct i2c_reg_value saa7129_init_config_extra[] = {
+	{ SAA7127_REG_OUTPUT_PORT_CONTROL, 		0x38 },
+	{ SAA7127_REG_VTRIG, 				0xfa },
+	{ 0, 0 }
+};
+
+static const struct i2c_reg_value saa7127_init_config_common[] = {
+	{ SAA7127_REG_WIDESCREEN_CONFIG, 		0x0d },
+	{ SAA7127_REG_WIDESCREEN_ENABLE, 		0x00 },
+	{ SAA7127_REG_COPYGEN_0, 			0x77 },
+	{ SAA7127_REG_COPYGEN_1, 			0x41 },
+	{ SAA7127_REG_COPYGEN_2, 			0x00 },	/* Macrovision enable/disable */
+	{ SAA7127_REG_OUTPUT_PORT_CONTROL, 		0xbf },
+	{ SAA7127_REG_GAIN_LUMINANCE_RGB, 		0x00 },
+	{ SAA7127_REG_GAIN_COLORDIFF_RGB, 		0x00 },
+	{ SAA7127_REG_INPUT_PORT_CONTROL_1, 		0x80 },	/* for color bars */
+	{ SAA7127_REG_LINE_21_ODD_0, 			0x77 },
+	{ SAA7127_REG_LINE_21_ODD_1, 			0x41 },
+	{ SAA7127_REG_LINE_21_EVEN_0, 			0x88 },
+	{ SAA7127_REG_LINE_21_EVEN_1, 			0x41 },
+	{ SAA7127_REG_RCV_PORT_CONTROL, 		0x12 },
+	{ SAA7127_REG_VTRIG, 				0xf9 },
+	{ SAA7127_REG_HTRIG_HI, 			0x00 },
+	{ SAA7127_REG_RCV2_OUTPUT_START, 		0x41 },
+	{ SAA7127_REG_RCV2_OUTPUT_END, 			0xc3 },
+	{ SAA7127_REG_RCV2_OUTPUT_MSBS, 		0x00 },
+	{ SAA7127_REG_TTX_REQUEST_H_START, 		0x3e },
+	{ SAA7127_REG_TTX_REQUEST_H_DELAY_LENGTH, 	0xb8 },
+	{ SAA7127_REG_CSYNC_ADVANCE_VSYNC_SHIFT,  	0x03 },
+	{ SAA7127_REG_TTX_ODD_REQ_VERT_START, 		0x15 },
+	{ SAA7127_REG_TTX_ODD_REQ_VERT_END, 		0x16 },
+	{ SAA7127_REG_TTX_EVEN_REQ_VERT_START, 		0x15 },
+	{ SAA7127_REG_TTX_EVEN_REQ_VERT_END, 		0x16 },
+	{ SAA7127_REG_FIRST_ACTIVE, 			0x1a },
+	{ SAA7127_REG_LAST_ACTIVE, 			0x01 },
+	{ SAA7127_REG_MSB_VERTICAL, 			0xc0 },
+	{ SAA7127_REG_DISABLE_TTX_LINE_LO_0, 		0x00 },
+	{ SAA7127_REG_DISABLE_TTX_LINE_LO_1, 		0x00 },
+	{ 0, 0 }
+};
+
+#define SAA7127_60HZ_DAC_CONTROL 0x15
+static const struct i2c_reg_value saa7127_init_config_60hz[] = {
+	{ SAA7127_REG_BURST_START, 			0x19 },
+	/* BURST_END is also used as a chip ID in saa7127_probe */
+	{ SAA7127_REG_BURST_END, 			0x1d },
+	{ SAA7127_REG_CHROMA_PHASE, 			0xa3 },
+	{ SAA7127_REG_GAINU, 				0x98 },
+	{ SAA7127_REG_GAINV, 				0xd3 },
+	{ SAA7127_REG_BLACK_LEVEL, 			0x39 },
+	{ SAA7127_REG_BLANKING_LEVEL, 			0x2e },
+	{ SAA7127_REG_VBI_BLANKING, 			0x2e },
+	{ SAA7127_REG_DAC_CONTROL, 			0x15 },
+	{ SAA7127_REG_BURST_AMP, 			0x4d },
+	{ SAA7127_REG_SUBC3, 				0x1f },
+	{ SAA7127_REG_SUBC2, 				0x7c },
+	{ SAA7127_REG_SUBC1, 				0xf0 },
+	{ SAA7127_REG_SUBC0, 				0x21 },
+	{ SAA7127_REG_MULTI, 				0x90 },
+	{ SAA7127_REG_CLOSED_CAPTION, 			0x11 },
+	{ 0, 0 }
+};
+
+#define SAA7127_50HZ_PAL_DAC_CONTROL 0x02
+static struct i2c_reg_value saa7127_init_config_50hz_pal[] = {
+	{ SAA7127_REG_BURST_START, 			0x21 },
+	/* BURST_END is also used as a chip ID in saa7127_probe */
+	{ SAA7127_REG_BURST_END, 			0x1d },
+	{ SAA7127_REG_CHROMA_PHASE, 			0x3f },
+	{ SAA7127_REG_GAINU, 				0x7d },
+	{ SAA7127_REG_GAINV, 				0xaf },
+	{ SAA7127_REG_BLACK_LEVEL, 			0x33 },
+	{ SAA7127_REG_BLANKING_LEVEL, 			0x35 },
+	{ SAA7127_REG_VBI_BLANKING, 			0x35 },
+	{ SAA7127_REG_DAC_CONTROL, 			0x02 },
+	{ SAA7127_REG_BURST_AMP, 			0x2f },
+	{ SAA7127_REG_SUBC3, 				0xcb },
+	{ SAA7127_REG_SUBC2, 				0x8a },
+	{ SAA7127_REG_SUBC1, 				0x09 },
+	{ SAA7127_REG_SUBC0, 				0x2a },
+	{ SAA7127_REG_MULTI, 				0xa0 },
+	{ SAA7127_REG_CLOSED_CAPTION, 			0x00 },
+	{ 0, 0 }
+};
+
+#define SAA7127_50HZ_SECAM_DAC_CONTROL 0x08
+static struct i2c_reg_value saa7127_init_config_50hz_secam[] = {
+	{ SAA7127_REG_BURST_START, 			0x21 },
+	/* BURST_END is also used as a chip ID in saa7127_probe */
+	{ SAA7127_REG_BURST_END, 			0x1d },
+	{ SAA7127_REG_CHROMA_PHASE, 			0x3f },
+	{ SAA7127_REG_GAINU, 				0x6a },
+	{ SAA7127_REG_GAINV, 				0x81 },
+	{ SAA7127_REG_BLACK_LEVEL, 			0x33 },
+	{ SAA7127_REG_BLANKING_LEVEL, 			0x35 },
+	{ SAA7127_REG_VBI_BLANKING, 			0x35 },
+	{ SAA7127_REG_DAC_CONTROL, 			0x08 },
+	{ SAA7127_REG_BURST_AMP, 			0x2f },
+	{ SAA7127_REG_SUBC3, 				0xb2 },
+	{ SAA7127_REG_SUBC2, 				0x3b },
+	{ SAA7127_REG_SUBC1, 				0xa3 },
+	{ SAA7127_REG_SUBC0, 				0x28 },
+	{ SAA7127_REG_MULTI, 				0x90 },
+	{ SAA7127_REG_CLOSED_CAPTION, 			0x00 },
+	{ 0, 0 }
+};
+
+/*
+ **********************************************************************
+ *
+ *  Encoder Struct, holds the configuration state of the encoder
+ *
+ **********************************************************************
+ */
+
+struct saa7127_state {
+	struct v4l2_subdev sd;
+	v4l2_std_id std;
+	u32 ident;
+	enum saa7127_input_type input_type;
+	enum saa7127_output_type output_type;
+	int video_enable;
+	int wss_enable;
+	u16 wss_mode;
+	int cc_enable;
+	u16 cc_data;
+	int xds_enable;
+	u16 xds_data;
+	int vps_enable;
+	u8 vps_data[5];
+	u8 reg_2d;
+	u8 reg_3a;
+	u8 reg_3a_cb;   /* colorbar bit */
+	u8 reg_61;
+};
+
+static inline struct saa7127_state *to_state(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct saa7127_state, sd);
+}
+
+static const char * const output_strs[] =
+{
+	"S-Video + Composite",
+	"Composite",
+	"S-Video",
+	"RGB",
+	"YUV C",
+	"YUV V"
+};
+
+static const char * const wss_strs[] = {
+	"invalid",
+	"letterbox 14:9 center",
+	"letterbox 14:9 top",
+	"invalid",
+	"letterbox 16:9 top",
+	"invalid",
+	"invalid",
+	"16:9 full format anamorphic",
+	"4:3 full format",
+	"invalid",
+	"invalid",
+	"letterbox 16:9 center",
+	"invalid",
+	"letterbox >16:9 center",
+	"14:9 full format center",
+	"invalid",
+};
+
+/* ----------------------------------------------------------------------- */
+
+static int saa7127_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 saa7127_write(struct v4l2_subdev *sd, u8 reg, u8 val)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	int i;
+
+	for (i = 0; i < 3; i++) {
+		if (i2c_smbus_write_byte_data(client, reg, val) == 0)
+			return 0;
+	}
+	v4l2_err(sd, "I2C Write Problem\n");
+	return -1;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static int saa7127_write_inittab(struct v4l2_subdev *sd,
+				 const struct i2c_reg_value *regs)
+{
+	while (regs->reg != 0) {
+		saa7127_write(sd, regs->reg, regs->value);
+		regs++;
+	}
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static int saa7127_set_vps(struct v4l2_subdev *sd, const struct v4l2_sliced_vbi_data *data)
+{
+	struct saa7127_state *state = to_state(sd);
+	int enable = (data->line != 0);
+
+	if (enable && (data->field != 0 || data->line != 16))
+		return -EINVAL;
+	if (state->vps_enable != enable) {
+		v4l2_dbg(1, debug, sd, "Turn VPS Signal %s\n", enable ? "on" : "off");
+		saa7127_write(sd, 0x54, enable << 7);
+		state->vps_enable = enable;
+	}
+	if (!enable)
+		return 0;
+
+	state->vps_data[0] = data->data[2];
+	state->vps_data[1] = data->data[8];
+	state->vps_data[2] = data->data[9];
+	state->vps_data[3] = data->data[10];
+	state->vps_data[4] = data->data[11];
+	v4l2_dbg(1, debug, sd, "Set VPS data %*ph\n", 5, state->vps_data);
+	saa7127_write(sd, 0x55, state->vps_data[0]);
+	saa7127_write(sd, 0x56, state->vps_data[1]);
+	saa7127_write(sd, 0x57, state->vps_data[2]);
+	saa7127_write(sd, 0x58, state->vps_data[3]);
+	saa7127_write(sd, 0x59, state->vps_data[4]);
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static int saa7127_set_cc(struct v4l2_subdev *sd, const struct v4l2_sliced_vbi_data *data)
+{
+	struct saa7127_state *state = to_state(sd);
+	u16 cc = data->data[1] << 8 | data->data[0];
+	int enable = (data->line != 0);
+
+	if (enable && (data->field != 0 || data->line != 21))
+		return -EINVAL;
+	if (state->cc_enable != enable) {
+		v4l2_dbg(1, debug, sd,
+			"Turn CC %s\n", enable ? "on" : "off");
+		saa7127_write(sd, SAA7127_REG_CLOSED_CAPTION,
+			(state->xds_enable << 7) | (enable << 6) | 0x11);
+		state->cc_enable = enable;
+	}
+	if (!enable)
+		return 0;
+
+	v4l2_dbg(2, debug, sd, "CC data: %04x\n", cc);
+	saa7127_write(sd, SAA7127_REG_LINE_21_ODD_0, cc & 0xff);
+	saa7127_write(sd, SAA7127_REG_LINE_21_ODD_1, cc >> 8);
+	state->cc_data = cc;
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static int saa7127_set_xds(struct v4l2_subdev *sd, const struct v4l2_sliced_vbi_data *data)
+{
+	struct saa7127_state *state = to_state(sd);
+	u16 xds = data->data[1] << 8 | data->data[0];
+	int enable = (data->line != 0);
+
+	if (enable && (data->field != 1 || data->line != 21))
+		return -EINVAL;
+	if (state->xds_enable != enable) {
+		v4l2_dbg(1, debug, sd, "Turn XDS %s\n", enable ? "on" : "off");
+		saa7127_write(sd, SAA7127_REG_CLOSED_CAPTION,
+				(enable << 7) | (state->cc_enable << 6) | 0x11);
+		state->xds_enable = enable;
+	}
+	if (!enable)
+		return 0;
+
+	v4l2_dbg(2, debug, sd, "XDS data: %04x\n", xds);
+	saa7127_write(sd, SAA7127_REG_LINE_21_EVEN_0, xds & 0xff);
+	saa7127_write(sd, SAA7127_REG_LINE_21_EVEN_1, xds >> 8);
+	state->xds_data = xds;
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static int saa7127_set_wss(struct v4l2_subdev *sd, const struct v4l2_sliced_vbi_data *data)
+{
+	struct saa7127_state *state = to_state(sd);
+	int enable = (data->line != 0);
+
+	if (enable && (data->field != 0 || data->line != 23))
+		return -EINVAL;
+	if (state->wss_enable != enable) {
+		v4l2_dbg(1, debug, sd, "Turn WSS %s\n", enable ? "on" : "off");
+		saa7127_write(sd, 0x27, enable << 7);
+		state->wss_enable = enable;
+	}
+	if (!enable)
+		return 0;
+
+	saa7127_write(sd, 0x26, data->data[0]);
+	saa7127_write(sd, 0x27, 0x80 | (data->data[1] & 0x3f));
+	v4l2_dbg(1, debug, sd,
+		"WSS mode: %s\n", wss_strs[data->data[0] & 0xf]);
+	state->wss_mode = (data->data[1] & 0x3f) << 8 | data->data[0];
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static int saa7127_set_video_enable(struct v4l2_subdev *sd, int enable)
+{
+	struct saa7127_state *state = to_state(sd);
+
+	if (enable) {
+		v4l2_dbg(1, debug, sd, "Enable Video Output\n");
+		saa7127_write(sd, 0x2d, state->reg_2d);
+		saa7127_write(sd, 0x61, state->reg_61);
+	} else {
+		v4l2_dbg(1, debug, sd, "Disable Video Output\n");
+		saa7127_write(sd, 0x2d, (state->reg_2d & 0xf0));
+		saa7127_write(sd, 0x61, (state->reg_61 | 0xc0));
+	}
+	state->video_enable = enable;
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static int saa7127_set_std(struct v4l2_subdev *sd, v4l2_std_id std)
+{
+	struct saa7127_state *state = to_state(sd);
+	const struct i2c_reg_value *inittab;
+
+	if (std & V4L2_STD_525_60) {
+		v4l2_dbg(1, debug, sd, "Selecting 60 Hz video Standard\n");
+		inittab = saa7127_init_config_60hz;
+		state->reg_61 = SAA7127_60HZ_DAC_CONTROL;
+
+	} else if (state->ident == V4L2_IDENT_SAA7129 &&
+		   (std & V4L2_STD_SECAM) &&
+		   !(std & (V4L2_STD_625_50 & ~V4L2_STD_SECAM))) {
+
+		/* If and only if SECAM, with a SAA712[89] */
+		v4l2_dbg(1, debug, sd,
+			 "Selecting 50 Hz SECAM video Standard\n");
+		inittab = saa7127_init_config_50hz_secam;
+		state->reg_61 = SAA7127_50HZ_SECAM_DAC_CONTROL;
+
+	} else {
+		v4l2_dbg(1, debug, sd, "Selecting 50 Hz PAL video Standard\n");
+		inittab = saa7127_init_config_50hz_pal;
+		state->reg_61 = SAA7127_50HZ_PAL_DAC_CONTROL;
+	}
+
+	/* Write Table */
+	saa7127_write_inittab(sd, inittab);
+	state->std = std;
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static int saa7127_set_output_type(struct v4l2_subdev *sd, int output)
+{
+	struct saa7127_state *state = to_state(sd);
+
+	switch (output) {
+	case SAA7127_OUTPUT_TYPE_RGB:
+		state->reg_2d = 0x0f;	/* RGB + CVBS (for sync) */
+		state->reg_3a = 0x13;	/* by default switch YUV to RGB-matrix on */
+		break;
+
+	case SAA7127_OUTPUT_TYPE_COMPOSITE:
+		if (state->ident == V4L2_IDENT_SAA7129)
+			state->reg_2d = 0x20;	/* CVBS only */
+		else
+			state->reg_2d = 0x08;	/* 00001000 CVBS only, RGB DAC's off (high impedance mode) */
+		state->reg_3a = 0x13;	/* by default switch YUV to RGB-matrix on */
+		break;
+
+	case SAA7127_OUTPUT_TYPE_SVIDEO:
+		if (state->ident == V4L2_IDENT_SAA7129)
+			state->reg_2d = 0x18;	/* Y + C */
+		else
+			state->reg_2d = 0xff;   /*11111111  croma -> R, luma -> CVBS + G + B */
+		state->reg_3a = 0x13;	/* by default switch YUV to RGB-matrix on */
+		break;
+
+	case SAA7127_OUTPUT_TYPE_YUV_V:
+		state->reg_2d = 0x4f;	/* reg 2D = 01001111, all DAC's on, RGB + VBS */
+		state->reg_3a = 0x0b;	/* reg 3A = 00001011, bypass RGB-matrix */
+		break;
+
+	case SAA7127_OUTPUT_TYPE_YUV_C:
+		state->reg_2d = 0x0f;	/* reg 2D = 00001111, all DAC's on, RGB + CVBS */
+		state->reg_3a = 0x0b;	/* reg 3A = 00001011, bypass RGB-matrix */
+		break;
+
+	case SAA7127_OUTPUT_TYPE_BOTH:
+		if (state->ident == V4L2_IDENT_SAA7129)
+			state->reg_2d = 0x38;
+		else
+			state->reg_2d = 0xbf;
+		state->reg_3a = 0x13;	/* by default switch YUV to RGB-matrix on */
+		break;
+
+	default:
+		return -EINVAL;
+	}
+	v4l2_dbg(1, debug, sd,
+		"Selecting %s output type\n", output_strs[output]);
+
+	/* Configure Encoder */
+	saa7127_write(sd, 0x2d, state->reg_2d);
+	saa7127_write(sd, 0x3a, state->reg_3a | state->reg_3a_cb);
+	state->output_type = output;
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static int saa7127_set_input_type(struct v4l2_subdev *sd, int input)
+{
+	struct saa7127_state *state = to_state(sd);
+
+	switch (input) {
+	case SAA7127_INPUT_TYPE_NORMAL:	/* avia */
+		v4l2_dbg(1, debug, sd, "Selecting Normal Encoder Input\n");
+		state->reg_3a_cb = 0;
+		break;
+
+	case SAA7127_INPUT_TYPE_TEST_IMAGE:	/* color bar */
+		v4l2_dbg(1, debug, sd, "Selecting Color Bar generator\n");
+		state->reg_3a_cb = 0x80;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+	saa7127_write(sd, 0x3a, state->reg_3a | state->reg_3a_cb);
+	state->input_type = input;
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static int saa7127_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std)
+{
+	struct saa7127_state *state = to_state(sd);
+
+	if (state->std == std)
+		return 0;
+	return saa7127_set_std(sd, std);
+}
+
+static int saa7127_s_routing(struct v4l2_subdev *sd,
+			     u32 input, u32 output, u32 config)
+{
+	struct saa7127_state *state = to_state(sd);
+	int rc = 0;
+
+	if (state->input_type != input)
+		rc = saa7127_set_input_type(sd, input);
+	if (rc == 0 && state->output_type != output)
+		rc = saa7127_set_output_type(sd, output);
+	return rc;
+}
+
+static int saa7127_s_stream(struct v4l2_subdev *sd, int enable)
+{
+	struct saa7127_state *state = to_state(sd);
+
+	if (state->video_enable == enable)
+		return 0;
+	return saa7127_set_video_enable(sd, enable);
+}
+
+static int saa7127_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt)
+{
+	struct saa7127_state *state = to_state(sd);
+
+	memset(fmt, 0, sizeof(*fmt));
+	if (state->vps_enable)
+		fmt->service_lines[0][16] = V4L2_SLICED_VPS;
+	if (state->wss_enable)
+		fmt->service_lines[0][23] = V4L2_SLICED_WSS_625;
+	if (state->cc_enable) {
+		fmt->service_lines[0][21] = V4L2_SLICED_CAPTION_525;
+		fmt->service_lines[1][21] = V4L2_SLICED_CAPTION_525;
+	}
+	fmt->service_set =
+		(state->vps_enable ? V4L2_SLICED_VPS : 0) |
+		(state->wss_enable ? V4L2_SLICED_WSS_625 : 0) |
+		(state->cc_enable ? V4L2_SLICED_CAPTION_525 : 0);
+	return 0;
+}
+
+static int saa7127_s_vbi_data(struct v4l2_subdev *sd, const struct v4l2_sliced_vbi_data *data)
+{
+	switch (data->id) {
+	case V4L2_SLICED_WSS_625:
+		return saa7127_set_wss(sd, data);
+	case V4L2_SLICED_VPS:
+		return saa7127_set_vps(sd, data);
+	case V4L2_SLICED_CAPTION_525:
+		if (data->field == 0)
+			return saa7127_set_cc(sd, data);
+		return saa7127_set_xds(sd, data);
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int saa7127_g_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;
+	reg->val = saa7127_read(sd, reg->reg & 0xff);
+	reg->size = 1;
+	return 0;
+}
+
+static int saa7127_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;
+	saa7127_write(sd, reg->reg & 0xff, reg->val & 0xff);
+	return 0;
+}
+#endif
+
+static int saa7127_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
+{
+	struct saa7127_state *state = to_state(sd);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	return v4l2_chip_ident_i2c_client(client, chip, state->ident, 0);
+}
+
+static int saa7127_log_status(struct v4l2_subdev *sd)
+{
+	struct saa7127_state *state = to_state(sd);
+
+	v4l2_info(sd, "Standard: %s\n", (state->std & V4L2_STD_525_60) ? "60 Hz" : "50 Hz");
+	v4l2_info(sd, "Input:    %s\n", state->input_type ?  "color bars" : "normal");
+	v4l2_info(sd, "Output:   %s\n", state->video_enable ?
+			output_strs[state->output_type] : "disabled");
+	v4l2_info(sd, "WSS:      %s\n", state->wss_enable ?
+			wss_strs[state->wss_mode] : "disabled");
+	v4l2_info(sd, "VPS:      %s\n", state->vps_enable ? "enabled" : "disabled");
+	v4l2_info(sd, "CC:       %s\n", state->cc_enable ? "enabled" : "disabled");
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static const struct v4l2_subdev_core_ops saa7127_core_ops = {
+	.log_status = saa7127_log_status,
+	.g_chip_ident = saa7127_g_chip_ident,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.g_register = saa7127_g_register,
+	.s_register = saa7127_s_register,
+#endif
+};
+
+static const struct v4l2_subdev_video_ops saa7127_video_ops = {
+	.s_std_output = saa7127_s_std_output,
+	.s_routing = saa7127_s_routing,
+	.s_stream = saa7127_s_stream,
+};
+
+static const struct v4l2_subdev_vbi_ops saa7127_vbi_ops = {
+	.s_vbi_data = saa7127_s_vbi_data,
+	.g_sliced_fmt = saa7127_g_sliced_fmt,
+};
+
+static const struct v4l2_subdev_ops saa7127_ops = {
+	.core = &saa7127_core_ops,
+	.video = &saa7127_video_ops,
+	.vbi = &saa7127_vbi_ops,
+};
+
+/* ----------------------------------------------------------------------- */
+
+static int saa7127_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
+{
+	struct saa7127_state *state;
+	struct v4l2_subdev *sd;
+	struct v4l2_sliced_vbi_data vbi = { 0, 0, 0, 0 };  /* set to disabled */
+
+	/* Check if the adapter supports the needed features */
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		return -EIO;
+
+	v4l_dbg(1, debug, client, "detecting saa7127 client on address 0x%x\n",
+			client->addr << 1);
+
+	state = kzalloc(sizeof(struct saa7127_state), GFP_KERNEL);
+	if (state == NULL)
+		return -ENOMEM;
+
+	sd = &state->sd;
+	v4l2_i2c_subdev_init(sd, client, &saa7127_ops);
+
+	/* First test register 0: Bits 5-7 are a version ID (should be 0),
+	   and bit 2 should also be 0.
+	   This is rather general, so the second test is more specific and
+	   looks at the 'ending point of burst in clock cycles' which is
+	   0x1d after a reset and not expected to ever change. */
+	if ((saa7127_read(sd, 0) & 0xe4) != 0 ||
+			(saa7127_read(sd, 0x29) & 0x3f) != 0x1d) {
+		v4l2_dbg(1, debug, sd, "saa7127 not found\n");
+		kfree(state);
+		return -ENODEV;
+	}
+
+	if (id->driver_data) {	/* Chip type is already known */
+		state->ident = id->driver_data;
+	} else {		/* Needs detection */
+		int read_result;
+
+		/* Detect if it's an saa7129 */
+		read_result = saa7127_read(sd, SAA7129_REG_FADE_KEY_COL2);
+		saa7127_write(sd, SAA7129_REG_FADE_KEY_COL2, 0xaa);
+		if (saa7127_read(sd, SAA7129_REG_FADE_KEY_COL2) == 0xaa) {
+			saa7127_write(sd, SAA7129_REG_FADE_KEY_COL2,
+					read_result);
+			state->ident = V4L2_IDENT_SAA7129;
+			strlcpy(client->name, "saa7129", I2C_NAME_SIZE);
+		} else {
+			state->ident = V4L2_IDENT_SAA7127;
+			strlcpy(client->name, "saa7127", I2C_NAME_SIZE);
+		}
+	}
+
+	v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name,
+			client->addr << 1, client->adapter->name);
+
+	v4l2_dbg(1, debug, sd, "Configuring encoder\n");
+	saa7127_write_inittab(sd, saa7127_init_config_common);
+	saa7127_set_std(sd, V4L2_STD_NTSC);
+	saa7127_set_output_type(sd, SAA7127_OUTPUT_TYPE_BOTH);
+	saa7127_set_vps(sd, &vbi);
+	saa7127_set_wss(sd, &vbi);
+	saa7127_set_cc(sd, &vbi);
+	saa7127_set_xds(sd, &vbi);
+	if (test_image == 1)
+		/* The Encoder has an internal Colorbar generator */
+		/* This can be used for debugging */
+		saa7127_set_input_type(sd, SAA7127_INPUT_TYPE_TEST_IMAGE);
+	else
+		saa7127_set_input_type(sd, SAA7127_INPUT_TYPE_NORMAL);
+	saa7127_set_video_enable(sd, 1);
+
+	if (state->ident == V4L2_IDENT_SAA7129)
+		saa7127_write_inittab(sd, saa7129_init_config_extra);
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static int saa7127_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+
+	v4l2_device_unregister_subdev(sd);
+	/* Turn off TV output */
+	saa7127_set_video_enable(sd, 0);
+	kfree(to_state(sd));
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static struct i2c_device_id saa7127_id[] = {
+	{ "saa7127_auto", 0 },	/* auto-detection */
+	{ "saa7126", V4L2_IDENT_SAA7127 },
+	{ "saa7127", V4L2_IDENT_SAA7127 },
+	{ "saa7128", V4L2_IDENT_SAA7129 },
+	{ "saa7129", V4L2_IDENT_SAA7129 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, saa7127_id);
+
+static struct i2c_driver saa7127_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "saa7127",
+	},
+	.probe		= saa7127_probe,
+	.remove		= saa7127_remove,
+	.id_table	= saa7127_id,
+};
+
+module_i2c_driver(saa7127_driver);
diff --git a/drivers/media/i2c/saa717x.c b/drivers/media/i2c/saa717x.c
new file mode 100644
index 0000000..1e84466
--- /dev/null
+++ b/drivers/media/i2c/saa717x.c
@@ -0,0 +1,1378 @@
+/*
+ * saa717x - Philips SAA717xHL video decoder driver
+ *
+ * Based on the saa7115 driver
+ *
+ * Changes by Ohta Kyuma <alpha292@bremen.or.jp>
+ *    - Apply to SAA717x,NEC uPD64031,uPD64083. (1/31/2004)
+ *
+ * Changes by T.Adachi (tadachi@tadachi-net.com)
+ *    - support audio, video scaler etc, and checked the initialize sequence.
+ *
+ * Cleaned up by Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ * Note: this is a reversed engineered driver based on captures from
+ * the I2C bus under Windows. This chip is very similar to the saa7134,
+ * though. Unfortunately, this driver is currently only working for NTSC.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+
+#include <linux/videodev2.h>
+#include <linux/i2c.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ctrls.h>
+
+MODULE_DESCRIPTION("Philips SAA717x audio/video decoder driver");
+MODULE_AUTHOR("K. Ohta, T. Adachi, Hans Verkuil");
+MODULE_LICENSE("GPL");
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Debug level (0-1)");
+
+/*
+ * Generic i2c probe
+ * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
+ */
+
+struct saa717x_state {
+	struct v4l2_subdev sd;
+	struct v4l2_ctrl_handler hdl;
+	v4l2_std_id std;
+	int input;
+	int enable;
+	int radio;
+	int playback;
+	int audio;
+	int tuner_audio_mode;
+	int audio_main_mute;
+	int audio_main_vol_r;
+	int audio_main_vol_l;
+	u16 audio_main_bass;
+	u16 audio_main_treble;
+	u16 audio_main_volume;
+	u16 audio_main_balance;
+	int audio_input;
+};
+
+static inline struct saa717x_state *to_state(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct saa717x_state, sd);
+}
+
+static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
+{
+	return &container_of(ctrl->handler, struct saa717x_state, hdl)->sd;
+}
+
+/* ----------------------------------------------------------------------- */
+
+/* for audio mode */
+#define TUNER_AUDIO_MONO   	0  /* LL */
+#define TUNER_AUDIO_STEREO 	1  /* LR */
+#define TUNER_AUDIO_LANG1  	2  /* LL */
+#define TUNER_AUDIO_LANG2  	3  /* RR */
+
+#define SAA717X_NTSC_WIDTH   	(704)
+#define SAA717X_NTSC_HEIGHT  	(480)
+
+/* ----------------------------------------------------------------------- */
+
+static int saa717x_write(struct v4l2_subdev *sd, u32 reg, u32 value)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct i2c_adapter *adap = client->adapter;
+	int fw_addr = reg == 0x454 || (reg >= 0x464 && reg <= 0x478) || reg == 0x480 || reg == 0x488;
+	unsigned char mm1[6];
+	struct i2c_msg msg;
+
+	msg.flags = 0;
+	msg.addr = client->addr;
+	mm1[0] = (reg >> 8) & 0xff;
+	mm1[1] = reg & 0xff;
+
+	if (fw_addr) {
+		mm1[4] = (value >> 16) & 0xff;
+		mm1[3] = (value >> 8) & 0xff;
+		mm1[2] = value & 0xff;
+	} else {
+		mm1[2] = value & 0xff;
+	}
+	msg.len = fw_addr ? 5 : 3; /* Long Registers have *only* three bytes! */
+	msg.buf = mm1;
+	v4l2_dbg(2, debug, sd, "wrote:  reg 0x%03x=%08x\n", reg, value);
+	return i2c_transfer(adap, &msg, 1) == 1;
+}
+
+static void saa717x_write_regs(struct v4l2_subdev *sd, u32 *data)
+{
+	while (data[0] || data[1]) {
+		saa717x_write(sd, data[0], data[1]);
+		data += 2;
+	}
+}
+
+static u32 saa717x_read(struct v4l2_subdev *sd, u32 reg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct i2c_adapter *adap = client->adapter;
+	int fw_addr = (reg >= 0x404 && reg <= 0x4b8) || reg == 0x528;
+	unsigned char mm1[2];
+	unsigned char mm2[4] = { 0, 0, 0, 0 };
+	struct i2c_msg msgs[2];
+	u32 value;
+
+	msgs[0].flags = 0;
+	msgs[1].flags = I2C_M_RD;
+	msgs[0].addr = msgs[1].addr = client->addr;
+	mm1[0] = (reg >> 8) & 0xff;
+	mm1[1] = reg & 0xff;
+	msgs[0].len = 2;
+	msgs[0].buf = mm1;
+	msgs[1].len = fw_addr ? 3 : 1; /* Multibyte Registers contains *only* 3 bytes */
+	msgs[1].buf = mm2;
+	i2c_transfer(adap, msgs, 2);
+
+	if (fw_addr)
+		value = (mm2[2] & 0xff)  | ((mm2[1] & 0xff) >> 8) | ((mm2[0] & 0xff) >> 16);
+	else
+		value = mm2[0] & 0xff;
+
+	v4l2_dbg(2, debug, sd, "read:  reg 0x%03x=0x%08x\n", reg, value);
+	return value;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static u32 reg_init_initialize[] =
+{
+	/* from linux driver */
+	0x101, 0x008, /* Increment delay */
+
+	0x103, 0x000, /* Analog input control 2 */
+	0x104, 0x090, /* Analog input control 3 */
+	0x105, 0x090, /* Analog input control 4 */
+	0x106, 0x0eb, /* Horizontal sync start */
+	0x107, 0x0e0, /* Horizontal sync stop */
+	0x109, 0x055, /* Luminance control */
+
+	0x10f, 0x02a, /* Chroma gain control */
+	0x110, 0x000, /* Chroma control 2 */
+
+	0x114, 0x045, /* analog/ADC */
+
+	0x118, 0x040, /* RAW data gain */
+	0x119, 0x080, /* RAW data offset */
+
+	0x044, 0x000, /* VBI horizontal input window start (L) TASK A */
+	0x045, 0x000, /* VBI horizontal input window start (H) TASK A */
+	0x046, 0x0cf, /* VBI horizontal input window stop (L) TASK A */
+	0x047, 0x002, /* VBI horizontal input window stop (H) TASK A */
+
+	0x049, 0x000, /* VBI vertical input window start (H) TASK A */
+
+	0x04c, 0x0d0, /* VBI horizontal output length (L) TASK A */
+	0x04d, 0x002, /* VBI horizontal output length (H) TASK A */
+
+	0x064, 0x080, /* Lumina brightness TASK A */
+	0x065, 0x040, /* Luminance contrast TASK A */
+	0x066, 0x040, /* Chroma saturation TASK A */
+	/* 067H: Reserved */
+	0x068, 0x000, /* VBI horizontal scaling increment (L) TASK A */
+	0x069, 0x004, /* VBI horizontal scaling increment (H) TASK A */
+	0x06a, 0x000, /* VBI phase offset TASK A */
+
+	0x06e, 0x000, /* Horizontal phase offset Luma TASK A */
+	0x06f, 0x000, /* Horizontal phase offset Chroma TASK A */
+
+	0x072, 0x000, /* Vertical filter mode TASK A */
+
+	0x084, 0x000, /* VBI horizontal input window start (L) TAKS B */
+	0x085, 0x000, /* VBI horizontal input window start (H) TAKS B */
+	0x086, 0x0cf, /* VBI horizontal input window stop (L) TAKS B */
+	0x087, 0x002, /* VBI horizontal input window stop (H) TAKS B */
+
+	0x089, 0x000, /* VBI vertical input window start (H) TAKS B */
+
+	0x08c, 0x0d0, /* VBI horizontal output length (L) TASK B */
+	0x08d, 0x002, /* VBI horizontal output length (H) TASK B */
+
+	0x0a4, 0x080, /* Lumina brightness TASK B */
+	0x0a5, 0x040, /* Luminance contrast TASK B */
+	0x0a6, 0x040, /* Chroma saturation TASK B */
+	/* 0A7H reserved */
+	0x0a8, 0x000, /* VBI horizontal scaling increment (L) TASK B */
+	0x0a9, 0x004, /* VBI horizontal scaling increment (H) TASK B */
+	0x0aa, 0x000, /* VBI phase offset TASK B */
+
+	0x0ae, 0x000, /* Horizontal phase offset Luma TASK B */
+	0x0af, 0x000, /*Horizontal phase offset Chroma TASK B */
+
+	0x0b2, 0x000, /* Vertical filter mode TASK B */
+
+	0x00c, 0x000, /* Start point GREEN path */
+	0x00d, 0x000, /* Start point BLUE path */
+	0x00e, 0x000, /* Start point RED path */
+
+	0x010, 0x010, /* GREEN path gamma curve --- */
+	0x011, 0x020,
+	0x012, 0x030,
+	0x013, 0x040,
+	0x014, 0x050,
+	0x015, 0x060,
+	0x016, 0x070,
+	0x017, 0x080,
+	0x018, 0x090,
+	0x019, 0x0a0,
+	0x01a, 0x0b0,
+	0x01b, 0x0c0,
+	0x01c, 0x0d0,
+	0x01d, 0x0e0,
+	0x01e, 0x0f0,
+	0x01f, 0x0ff, /* --- GREEN path gamma curve */
+
+	0x020, 0x010, /* BLUE path gamma curve --- */
+	0x021, 0x020,
+	0x022, 0x030,
+	0x023, 0x040,
+	0x024, 0x050,
+	0x025, 0x060,
+	0x026, 0x070,
+	0x027, 0x080,
+	0x028, 0x090,
+	0x029, 0x0a0,
+	0x02a, 0x0b0,
+	0x02b, 0x0c0,
+	0x02c, 0x0d0,
+	0x02d, 0x0e0,
+	0x02e, 0x0f0,
+	0x02f, 0x0ff, /* --- BLUE path gamma curve */
+
+	0x030, 0x010, /* RED path gamma curve --- */
+	0x031, 0x020,
+	0x032, 0x030,
+	0x033, 0x040,
+	0x034, 0x050,
+	0x035, 0x060,
+	0x036, 0x070,
+	0x037, 0x080,
+	0x038, 0x090,
+	0x039, 0x0a0,
+	0x03a, 0x0b0,
+	0x03b, 0x0c0,
+	0x03c, 0x0d0,
+	0x03d, 0x0e0,
+	0x03e, 0x0f0,
+	0x03f, 0x0ff, /* --- RED path gamma curve */
+
+	0x109, 0x085, /* Luminance control  */
+
+	/**** from app start ****/
+	0x584, 0x000, /* AGC gain control */
+	0x585, 0x000, /* Program count */
+	0x586, 0x003, /* Status reset */
+	0x588, 0x0ff, /* Number of audio samples (L) */
+	0x589, 0x00f, /* Number of audio samples (M) */
+	0x58a, 0x000, /* Number of audio samples (H) */
+	0x58b, 0x000, /* Audio select */
+	0x58c, 0x010, /* Audio channel assign1 */
+	0x58d, 0x032, /* Audio channel assign2 */
+	0x58e, 0x054, /* Audio channel assign3 */
+	0x58f, 0x023, /* Audio format */
+	0x590, 0x000, /* SIF control */
+
+	0x595, 0x000, /* ?? */
+	0x596, 0x000, /* ?? */
+	0x597, 0x000, /* ?? */
+
+	0x464, 0x00, /* Digital input crossbar1 */
+
+	0x46c, 0xbbbb10, /* Digital output selection1-3 */
+	0x470, 0x101010, /* Digital output selection4-6 */
+
+	0x478, 0x00, /* Sound feature control */
+
+	0x474, 0x18, /* Softmute control */
+
+	0x454, 0x0425b9, /* Sound Easy programming(reset) */
+	0x454, 0x042539, /* Sound Easy programming(reset) */
+
+
+	/**** common setting( of DVD play, including scaler commands) ****/
+	0x042, 0x003, /* Data path configuration for VBI (TASK A) */
+
+	0x082, 0x003, /* Data path configuration for VBI (TASK B) */
+
+	0x108, 0x0f8, /* Sync control */
+	0x2a9, 0x0fd, /* ??? */
+	0x102, 0x089, /* select video input "mode 9" */
+	0x111, 0x000, /* Mode/delay control */
+
+	0x10e, 0x00a, /* Chroma control 1 */
+
+	0x594, 0x002, /* SIF, analog I/O select */
+
+	0x454, 0x0425b9, /* Sound  */
+	0x454, 0x042539,
+
+	0x111, 0x000,
+	0x10e, 0x00a,
+	0x464, 0x000,
+	0x300, 0x000,
+	0x301, 0x006,
+	0x302, 0x000,
+	0x303, 0x006,
+	0x308, 0x040,
+	0x309, 0x000,
+	0x30a, 0x000,
+	0x30b, 0x000,
+	0x000, 0x002,
+	0x001, 0x000,
+	0x002, 0x000,
+	0x003, 0x000,
+	0x004, 0x033,
+	0x040, 0x01d,
+	0x041, 0x001,
+	0x042, 0x004,
+	0x043, 0x000,
+	0x080, 0x01e,
+	0x081, 0x001,
+	0x082, 0x004,
+	0x083, 0x000,
+	0x190, 0x018,
+	0x115, 0x000,
+	0x116, 0x012,
+	0x117, 0x018,
+	0x04a, 0x011,
+	0x08a, 0x011,
+	0x04b, 0x000,
+	0x08b, 0x000,
+	0x048, 0x000,
+	0x088, 0x000,
+	0x04e, 0x012,
+	0x08e, 0x012,
+	0x058, 0x012,
+	0x098, 0x012,
+	0x059, 0x000,
+	0x099, 0x000,
+	0x05a, 0x003,
+	0x09a, 0x003,
+	0x05b, 0x001,
+	0x09b, 0x001,
+	0x054, 0x008,
+	0x094, 0x008,
+	0x055, 0x000,
+	0x095, 0x000,
+	0x056, 0x0c7,
+	0x096, 0x0c7,
+	0x057, 0x002,
+	0x097, 0x002,
+	0x0ff, 0x0ff,
+	0x060, 0x001,
+	0x0a0, 0x001,
+	0x061, 0x000,
+	0x0a1, 0x000,
+	0x062, 0x000,
+	0x0a2, 0x000,
+	0x063, 0x000,
+	0x0a3, 0x000,
+	0x070, 0x000,
+	0x0b0, 0x000,
+	0x071, 0x004,
+	0x0b1, 0x004,
+	0x06c, 0x0e9,
+	0x0ac, 0x0e9,
+	0x06d, 0x003,
+	0x0ad, 0x003,
+	0x05c, 0x0d0,
+	0x09c, 0x0d0,
+	0x05d, 0x002,
+	0x09d, 0x002,
+	0x05e, 0x0f2,
+	0x09e, 0x0f2,
+	0x05f, 0x000,
+	0x09f, 0x000,
+	0x074, 0x000,
+	0x0b4, 0x000,
+	0x075, 0x000,
+	0x0b5, 0x000,
+	0x076, 0x000,
+	0x0b6, 0x000,
+	0x077, 0x000,
+	0x0b7, 0x000,
+	0x195, 0x008,
+	0x0ff, 0x0ff,
+	0x108, 0x0f8,
+	0x111, 0x000,
+	0x10e, 0x00a,
+	0x2a9, 0x0fd,
+	0x464, 0x001,
+	0x454, 0x042135,
+	0x598, 0x0e7,
+	0x599, 0x07d,
+	0x59a, 0x018,
+	0x59c, 0x066,
+	0x59d, 0x090,
+	0x59e, 0x001,
+	0x584, 0x000,
+	0x585, 0x000,
+	0x586, 0x003,
+	0x588, 0x0ff,
+	0x589, 0x00f,
+	0x58a, 0x000,
+	0x58b, 0x000,
+	0x58c, 0x010,
+	0x58d, 0x032,
+	0x58e, 0x054,
+	0x58f, 0x023,
+	0x590, 0x000,
+	0x595, 0x000,
+	0x596, 0x000,
+	0x597, 0x000,
+	0x464, 0x000,
+	0x46c, 0xbbbb10,
+	0x470, 0x101010,
+
+
+	0x478, 0x000,
+	0x474, 0x018,
+	0x454, 0x042135,
+	0x598, 0x0e7,
+	0x599, 0x07d,
+	0x59a, 0x018,
+	0x59c, 0x066,
+	0x59d, 0x090,
+	0x59e, 0x001,
+	0x584, 0x000,
+	0x585, 0x000,
+	0x586, 0x003,
+	0x588, 0x0ff,
+	0x589, 0x00f,
+	0x58a, 0x000,
+	0x58b, 0x000,
+	0x58c, 0x010,
+	0x58d, 0x032,
+	0x58e, 0x054,
+	0x58f, 0x023,
+	0x590, 0x000,
+	0x595, 0x000,
+	0x596, 0x000,
+	0x597, 0x000,
+	0x464, 0x000,
+	0x46c, 0xbbbb10,
+	0x470, 0x101010,
+
+	0x478, 0x000,
+	0x474, 0x018,
+	0x454, 0x042135,
+	0x598, 0x0e7,
+	0x599, 0x07d,
+	0x59a, 0x018,
+	0x59c, 0x066,
+	0x59d, 0x090,
+	0x59e, 0x001,
+	0x584, 0x000,
+	0x585, 0x000,
+	0x586, 0x003,
+	0x588, 0x0ff,
+	0x589, 0x00f,
+	0x58a, 0x000,
+	0x58b, 0x000,
+	0x58c, 0x010,
+	0x58d, 0x032,
+	0x58e, 0x054,
+	0x58f, 0x023,
+	0x590, 0x000,
+	0x595, 0x000,
+	0x596, 0x000,
+	0x597, 0x000,
+	0x464, 0x000,
+	0x46c, 0xbbbb10,
+	0x470, 0x101010,
+	0x478, 0x000,
+	0x474, 0x018,
+	0x454, 0x042135,
+	0x193, 0x000,
+	0x300, 0x000,
+	0x301, 0x006,
+	0x302, 0x000,
+	0x303, 0x006,
+	0x308, 0x040,
+	0x309, 0x000,
+	0x30a, 0x000,
+	0x30b, 0x000,
+	0x000, 0x002,
+	0x001, 0x000,
+	0x002, 0x000,
+	0x003, 0x000,
+	0x004, 0x033,
+	0x040, 0x01d,
+	0x041, 0x001,
+	0x042, 0x004,
+	0x043, 0x000,
+	0x080, 0x01e,
+	0x081, 0x001,
+	0x082, 0x004,
+	0x083, 0x000,
+	0x190, 0x018,
+	0x115, 0x000,
+	0x116, 0x012,
+	0x117, 0x018,
+	0x04a, 0x011,
+	0x08a, 0x011,
+	0x04b, 0x000,
+	0x08b, 0x000,
+	0x048, 0x000,
+	0x088, 0x000,
+	0x04e, 0x012,
+	0x08e, 0x012,
+	0x058, 0x012,
+	0x098, 0x012,
+	0x059, 0x000,
+	0x099, 0x000,
+	0x05a, 0x003,
+	0x09a, 0x003,
+	0x05b, 0x001,
+	0x09b, 0x001,
+	0x054, 0x008,
+	0x094, 0x008,
+	0x055, 0x000,
+	0x095, 0x000,
+	0x056, 0x0c7,
+	0x096, 0x0c7,
+	0x057, 0x002,
+	0x097, 0x002,
+	0x060, 0x001,
+	0x0a0, 0x001,
+	0x061, 0x000,
+	0x0a1, 0x000,
+	0x062, 0x000,
+	0x0a2, 0x000,
+	0x063, 0x000,
+	0x0a3, 0x000,
+	0x070, 0x000,
+	0x0b0, 0x000,
+	0x071, 0x004,
+	0x0b1, 0x004,
+	0x06c, 0x0e9,
+	0x0ac, 0x0e9,
+	0x06d, 0x003,
+	0x0ad, 0x003,
+	0x05c, 0x0d0,
+	0x09c, 0x0d0,
+	0x05d, 0x002,
+	0x09d, 0x002,
+	0x05e, 0x0f2,
+	0x09e, 0x0f2,
+	0x05f, 0x000,
+	0x09f, 0x000,
+	0x074, 0x000,
+	0x0b4, 0x000,
+	0x075, 0x000,
+	0x0b5, 0x000,
+	0x076, 0x000,
+	0x0b6, 0x000,
+	0x077, 0x000,
+	0x0b7, 0x000,
+	0x195, 0x008,
+	0x598, 0x0e7,
+	0x599, 0x07d,
+	0x59a, 0x018,
+	0x59c, 0x066,
+	0x59d, 0x090,
+	0x59e, 0x001,
+	0x584, 0x000,
+	0x585, 0x000,
+	0x586, 0x003,
+	0x588, 0x0ff,
+	0x589, 0x00f,
+	0x58a, 0x000,
+	0x58b, 0x000,
+	0x58c, 0x010,
+	0x58d, 0x032,
+	0x58e, 0x054,
+	0x58f, 0x023,
+	0x590, 0x000,
+	0x595, 0x000,
+	0x596, 0x000,
+	0x597, 0x000,
+	0x464, 0x000,
+	0x46c, 0xbbbb10,
+	0x470, 0x101010,
+	0x478, 0x000,
+	0x474, 0x018,
+	0x454, 0x042135,
+	0x193, 0x0a6,
+	0x108, 0x0f8,
+	0x042, 0x003,
+	0x082, 0x003,
+	0x454, 0x0425b9,
+	0x454, 0x042539,
+	0x193, 0x000,
+	0x193, 0x0a6,
+	0x464, 0x000,
+
+	0, 0
+};
+
+/* Tuner */
+static u32 reg_init_tuner_input[] = {
+	0x108, 0x0f8, /* Sync control */
+	0x111, 0x000, /* Mode/delay control */
+	0x10e, 0x00a, /* Chroma control 1 */
+	0, 0
+};
+
+/* Composite */
+static u32 reg_init_composite_input[] = {
+	0x108, 0x0e8, /* Sync control */
+	0x111, 0x000, /* Mode/delay control */
+	0x10e, 0x04a, /* Chroma control 1 */
+	0, 0
+};
+
+/* S-Video */
+static u32 reg_init_svideo_input[] = {
+	0x108, 0x0e8, /* Sync control */
+	0x111, 0x000, /* Mode/delay control */
+	0x10e, 0x04a, /* Chroma control 1 */
+	0, 0
+};
+
+static u32 reg_set_audio_template[4][2] =
+{
+	{ /* for MONO
+		tadachi 6/29 DMA audio output select?
+		Register 0x46c
+		7-4: DMA2, 3-0: DMA1 ch. DMA4, DMA3 DMA2, DMA1
+		0: MAIN left,  1: MAIN right
+		2: AUX1 left,  3: AUX1 right
+		4: AUX2 left,  5: AUX2 right
+		6: DPL left,   7: DPL  right
+		8: DPL center, 9: DPL surround
+		A: monitor output, B: digital sense */
+		0xbbbb00,
+
+		/* tadachi 6/29 DAC and I2S output select?
+		   Register 0x470
+		   7-4:DAC right ch. 3-0:DAC left ch.
+		   I2S1 right,left  I2S2 right,left */
+		0x00,
+	},
+	{ /* for STEREO */
+		0xbbbb10, 0x101010,
+	},
+	{ /* for LANG1 */
+		0xbbbb00, 0x00,
+	},
+	{ /* for LANG2/SAP */
+		0xbbbb11, 0x111111,
+	}
+};
+
+
+/* Get detected audio flags (from saa7134 driver) */
+static void get_inf_dev_status(struct v4l2_subdev *sd,
+		int *dual_flag, int *stereo_flag)
+{
+	u32 reg_data3;
+
+	static char *stdres[0x20] = {
+		[0x00] = "no standard detected",
+		[0x01] = "B/G (in progress)",
+		[0x02] = "D/K (in progress)",
+		[0x03] = "M (in progress)",
+
+		[0x04] = "B/G A2",
+		[0x05] = "B/G NICAM",
+		[0x06] = "D/K A2 (1)",
+		[0x07] = "D/K A2 (2)",
+		[0x08] = "D/K A2 (3)",
+		[0x09] = "D/K NICAM",
+		[0x0a] = "L NICAM",
+		[0x0b] = "I NICAM",
+
+		[0x0c] = "M Korea",
+		[0x0d] = "M BTSC ",
+		[0x0e] = "M EIAJ",
+
+		[0x0f] = "FM radio / IF 10.7 / 50 deemp",
+		[0x10] = "FM radio / IF 10.7 / 75 deemp",
+		[0x11] = "FM radio / IF sel / 50 deemp",
+		[0x12] = "FM radio / IF sel / 75 deemp",
+
+		[0x13 ... 0x1e] = "unknown",
+		[0x1f] = "??? [in progress]",
+	};
+
+
+	*dual_flag = *stereo_flag = 0;
+
+	/* (demdec status: 0x528) */
+
+	/* read current status */
+	reg_data3 = saa717x_read(sd, 0x0528);
+
+	v4l2_dbg(1, debug, sd, "tvaudio thread status: 0x%x [%s%s%s]\n",
+		reg_data3, stdres[reg_data3 & 0x1f],
+		(reg_data3 & 0x000020) ? ",stereo" : "",
+		(reg_data3 & 0x000040) ? ",dual"   : "");
+	v4l2_dbg(1, debug, sd, "detailed status: "
+		"%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s\n",
+		(reg_data3 & 0x000080) ? " A2/EIAJ pilot tone "     : "",
+		(reg_data3 & 0x000100) ? " A2/EIAJ dual "           : "",
+		(reg_data3 & 0x000200) ? " A2/EIAJ stereo "         : "",
+		(reg_data3 & 0x000400) ? " A2/EIAJ noise mute "     : "",
+
+		(reg_data3 & 0x000800) ? " BTSC/FM radio pilot "    : "",
+		(reg_data3 & 0x001000) ? " SAP carrier "            : "",
+		(reg_data3 & 0x002000) ? " BTSC stereo noise mute " : "",
+		(reg_data3 & 0x004000) ? " SAP noise mute "         : "",
+		(reg_data3 & 0x008000) ? " VDSP "                   : "",
+
+		(reg_data3 & 0x010000) ? " NICST "                  : "",
+		(reg_data3 & 0x020000) ? " NICDU "                  : "",
+		(reg_data3 & 0x040000) ? " NICAM muted "            : "",
+		(reg_data3 & 0x080000) ? " NICAM reserve sound "    : "",
+
+		(reg_data3 & 0x100000) ? " init done "              : "");
+
+	if (reg_data3 & 0x000220) {
+		v4l2_dbg(1, debug, sd, "ST!!!\n");
+		*stereo_flag = 1;
+	}
+
+	if (reg_data3 & 0x000140) {
+		v4l2_dbg(1, debug, sd, "DUAL!!!\n");
+		*dual_flag = 1;
+	}
+}
+
+/* regs write to set audio mode */
+static void set_audio_mode(struct v4l2_subdev *sd, int audio_mode)
+{
+	v4l2_dbg(1, debug, sd, "writing registers to set audio mode by set %d\n",
+			audio_mode);
+
+	saa717x_write(sd, 0x46c, reg_set_audio_template[audio_mode][0]);
+	saa717x_write(sd, 0x470, reg_set_audio_template[audio_mode][1]);
+}
+
+/* write regs to set audio volume, bass and treble */
+static int set_audio_regs(struct v4l2_subdev *sd,
+		struct saa717x_state *decoder)
+{
+	u8 mute = 0xac; /* -84 dB */
+	u32 val;
+	unsigned int work_l, work_r;
+
+	/* set SIF analog I/O select */
+	saa717x_write(sd, 0x0594, decoder->audio_input);
+	v4l2_dbg(1, debug, sd, "set audio input %d\n",
+			decoder->audio_input);
+
+	/* normalize ( 65535 to 0 -> 24 to -40 (not -84)) */
+	work_l = (min(65536 - decoder->audio_main_balance, 32768) * decoder->audio_main_volume) / 32768;
+	work_r = (min(decoder->audio_main_balance, (u16)32768) * decoder->audio_main_volume) / 32768;
+	decoder->audio_main_vol_l = (long)work_l * (24 - (-40)) / 65535 - 40;
+	decoder->audio_main_vol_r = (long)work_r * (24 - (-40)) / 65535 - 40;
+
+	/* set main volume */
+	/* main volume L[7-0],R[7-0],0x00  24=24dB,-83dB, -84(mute) */
+	/*    def:0dB->6dB(MPG600GR) */
+	/* if mute is on, set mute */
+	if (decoder->audio_main_mute) {
+		val = mute | (mute << 8);
+	} else {
+		val = (u8)decoder->audio_main_vol_l |
+			((u8)decoder->audio_main_vol_r << 8);
+	}
+
+	saa717x_write(sd, 0x480, val);
+
+	/* set bass and treble */
+	val = decoder->audio_main_bass & 0x1f;
+	val |= (decoder->audio_main_treble & 0x1f) << 5;
+	saa717x_write(sd, 0x488, val);
+	return 0;
+}
+
+/********** scaling staff ***********/
+static void set_h_prescale(struct v4l2_subdev *sd,
+		int task, int prescale)
+{
+	static const struct {
+		int xpsc;
+		int xacl;
+		int xc2_1;
+		int xdcg;
+		int vpfy;
+	} vals[] = {
+		/* XPSC XACL XC2_1 XDCG VPFY */
+		{    1,   0,    0,    0,   0 },
+		{    2,   2,    1,    2,   2 },
+		{    3,   4,    1,    3,   2 },
+		{    4,   8,    1,    4,   2 },
+		{    5,   8,    1,    4,   2 },
+		{    6,   8,    1,    4,   3 },
+		{    7,   8,    1,    4,   3 },
+		{    8,  15,    0,    4,   3 },
+		{    9,  15,    0,    4,   3 },
+		{   10,  16,    1,    5,   3 },
+	};
+	static const int count = ARRAY_SIZE(vals);
+	int i, task_shift;
+
+	task_shift = task * 0x40;
+	for (i = 0; i < count; i++)
+		if (vals[i].xpsc == prescale)
+			break;
+	if (i == count)
+		return;
+
+	/* horizonal prescaling */
+	saa717x_write(sd, 0x60 + task_shift, vals[i].xpsc);
+	/* accumulation length */
+	saa717x_write(sd, 0x61 + task_shift, vals[i].xacl);
+	/* level control */
+	saa717x_write(sd, 0x62 + task_shift,
+			(vals[i].xc2_1 << 3) | vals[i].xdcg);
+	/*FIR prefilter control */
+	saa717x_write(sd, 0x63 + task_shift,
+			(vals[i].vpfy << 2) | vals[i].vpfy);
+}
+
+/********** scaling staff ***********/
+static void set_v_scale(struct v4l2_subdev *sd, int task, int yscale)
+{
+	int task_shift;
+
+	task_shift = task * 0x40;
+	/* Vertical scaling ratio (LOW) */
+	saa717x_write(sd, 0x70 + task_shift, yscale & 0xff);
+	/* Vertical scaling ratio (HI) */
+	saa717x_write(sd, 0x71 + task_shift, yscale >> 8);
+}
+
+static int saa717x_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct v4l2_subdev *sd = to_sd(ctrl);
+	struct saa717x_state *state = to_state(sd);
+
+	switch (ctrl->id) {
+	case V4L2_CID_BRIGHTNESS:
+		saa717x_write(sd, 0x10a, ctrl->val);
+		return 0;
+
+	case V4L2_CID_CONTRAST:
+		saa717x_write(sd, 0x10b, ctrl->val);
+		return 0;
+
+	case V4L2_CID_SATURATION:
+		saa717x_write(sd, 0x10c, ctrl->val);
+		return 0;
+
+	case V4L2_CID_HUE:
+		saa717x_write(sd, 0x10d, ctrl->val);
+		return 0;
+
+	case V4L2_CID_AUDIO_MUTE:
+		state->audio_main_mute = ctrl->val;
+		break;
+
+	case V4L2_CID_AUDIO_VOLUME:
+		state->audio_main_volume = ctrl->val;
+		break;
+
+	case V4L2_CID_AUDIO_BALANCE:
+		state->audio_main_balance = ctrl->val;
+		break;
+
+	case V4L2_CID_AUDIO_TREBLE:
+		state->audio_main_treble = ctrl->val;
+		break;
+
+	case V4L2_CID_AUDIO_BASS:
+		state->audio_main_bass = ctrl->val;
+		break;
+
+	default:
+		return 0;
+	}
+	set_audio_regs(sd, state);
+	return 0;
+}
+
+static int saa717x_s_video_routing(struct v4l2_subdev *sd,
+				   u32 input, u32 output, u32 config)
+{
+	struct saa717x_state *decoder = to_state(sd);
+	int is_tuner = input & 0x80;  /* tuner input flag */
+
+	input &= 0x7f;
+
+	v4l2_dbg(1, debug, sd, "decoder set input (%d)\n", input);
+	/* inputs from 0-9 are available*/
+	/* saa717x have mode0-mode9 but mode5 is reserved. */
+	if (input > 9 || input == 5)
+		return -EINVAL;
+
+	if (decoder->input != input) {
+		int input_line = input;
+
+		decoder->input = input_line;
+		v4l2_dbg(1, debug, sd,  "now setting %s input %d\n",
+				input_line >= 6 ? "S-Video" : "Composite",
+				input_line);
+
+		/* select mode */
+		saa717x_write(sd, 0x102,
+				(saa717x_read(sd, 0x102) & 0xf0) |
+				input_line);
+
+		/* bypass chrominance trap for modes 6..9 */
+		saa717x_write(sd, 0x109,
+				(saa717x_read(sd, 0x109) & 0x7f) |
+				(input_line < 6 ? 0x0 : 0x80));
+
+		/* change audio_mode */
+		if (is_tuner) {
+			/* tuner */
+			set_audio_mode(sd, decoder->tuner_audio_mode);
+		} else {
+			/* Force to STEREO mode if Composite or
+			 * S-Video were chosen */
+			set_audio_mode(sd, TUNER_AUDIO_STEREO);
+		}
+		/* change initialize procedure (Composite/S-Video) */
+		if (is_tuner)
+			saa717x_write_regs(sd, reg_init_tuner_input);
+		else if (input_line >= 6)
+			saa717x_write_regs(sd, reg_init_svideo_input);
+		else
+			saa717x_write_regs(sd, reg_init_composite_input);
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int saa717x_g_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;
+	reg->val = saa717x_read(sd, reg->reg);
+	reg->size = 1;
+	return 0;
+}
+
+static int saa717x_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	u16 addr = reg->reg & 0xffff;
+	u8 val = reg->val & 0xff;
+
+	if (!v4l2_chip_match_i2c_client(client, &reg->match))
+		return -EINVAL;
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+	saa717x_write(sd, addr, val);
+	return 0;
+}
+#endif
+
+static int saa717x_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
+{
+	int prescale, h_scale, v_scale;
+
+	v4l2_dbg(1, debug, sd, "decoder set size\n");
+
+	if (fmt->code != V4L2_MBUS_FMT_FIXED)
+		return -EINVAL;
+
+	/* FIXME need better bounds checking here */
+	if (fmt->width < 1 || fmt->width > 1440)
+		return -EINVAL;
+	if (fmt->height < 1 || fmt->height > 960)
+		return -EINVAL;
+
+	fmt->field = V4L2_FIELD_INTERLACED;
+	fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
+
+	/* scaling setting */
+	/* NTSC and interlace only */
+	prescale = SAA717X_NTSC_WIDTH / fmt->width;
+	if (prescale == 0)
+		prescale = 1;
+	h_scale = 1024 * SAA717X_NTSC_WIDTH / prescale / fmt->width;
+	/* interlace */
+	v_scale = 512 * 2 * SAA717X_NTSC_HEIGHT / fmt->height;
+
+	/* Horizontal prescaling etc */
+	set_h_prescale(sd, 0, prescale);
+	set_h_prescale(sd, 1, prescale);
+
+	/* Horizontal scaling increment */
+	/* TASK A */
+	saa717x_write(sd, 0x6C, (u8)(h_scale & 0xFF));
+	saa717x_write(sd, 0x6D, (u8)((h_scale >> 8) & 0xFF));
+	/* TASK B */
+	saa717x_write(sd, 0xAC, (u8)(h_scale & 0xFF));
+	saa717x_write(sd, 0xAD, (u8)((h_scale >> 8) & 0xFF));
+
+	/* Vertical prescaling etc */
+	set_v_scale(sd, 0, v_scale);
+	set_v_scale(sd, 1, v_scale);
+
+	/* set video output size */
+	/* video number of pixels at output */
+	/* TASK A */
+	saa717x_write(sd, 0x5C, (u8)(fmt->width & 0xFF));
+	saa717x_write(sd, 0x5D, (u8)((fmt->width >> 8) & 0xFF));
+	/* TASK B */
+	saa717x_write(sd, 0x9C, (u8)(fmt->width & 0xFF));
+	saa717x_write(sd, 0x9D, (u8)((fmt->width >> 8) & 0xFF));
+
+	/* video number of lines at output */
+	/* TASK A */
+	saa717x_write(sd, 0x5E, (u8)(fmt->height & 0xFF));
+	saa717x_write(sd, 0x5F, (u8)((fmt->height >> 8) & 0xFF));
+	/* TASK B */
+	saa717x_write(sd, 0x9E, (u8)(fmt->height & 0xFF));
+	saa717x_write(sd, 0x9F, (u8)((fmt->height >> 8) & 0xFF));
+	return 0;
+}
+
+static int saa717x_s_radio(struct v4l2_subdev *sd)
+{
+	struct saa717x_state *decoder = to_state(sd);
+
+	decoder->radio = 1;
+	return 0;
+}
+
+static int saa717x_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
+{
+	struct saa717x_state *decoder = to_state(sd);
+
+	v4l2_dbg(1, debug, sd, "decoder set norm ");
+	v4l2_dbg(1, debug, sd, "(not yet implementd)\n");
+
+	decoder->radio = 0;
+	decoder->std = std;
+	return 0;
+}
+
+static int saa717x_s_audio_routing(struct v4l2_subdev *sd,
+				   u32 input, u32 output, u32 config)
+{
+	struct saa717x_state *decoder = to_state(sd);
+
+	if (input < 3) { /* FIXME! --tadachi */
+		decoder->audio_input = input;
+		v4l2_dbg(1, debug, sd,
+				"set decoder audio input to %d\n",
+				decoder->audio_input);
+		set_audio_regs(sd, decoder);
+		return 0;
+	}
+	return -ERANGE;
+}
+
+static int saa717x_s_stream(struct v4l2_subdev *sd, int enable)
+{
+	struct saa717x_state *decoder = to_state(sd);
+
+	v4l2_dbg(1, debug, sd, "decoder %s output\n",
+			enable ? "enable" : "disable");
+	decoder->enable = enable;
+	saa717x_write(sd, 0x193, enable ? 0xa6 : 0x26);
+	return 0;
+}
+
+/* change audio mode */
+static int saa717x_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
+{
+	struct saa717x_state *decoder = to_state(sd);
+	int audio_mode;
+	char *mes[4] = {
+		"MONO", "STEREO", "LANG1", "LANG2/SAP"
+	};
+
+	audio_mode = TUNER_AUDIO_STEREO;
+
+	switch (vt->audmode) {
+		case V4L2_TUNER_MODE_MONO:
+			audio_mode = TUNER_AUDIO_MONO;
+			break;
+		case V4L2_TUNER_MODE_STEREO:
+			audio_mode = TUNER_AUDIO_STEREO;
+			break;
+		case V4L2_TUNER_MODE_LANG2:
+			audio_mode = TUNER_AUDIO_LANG2;
+			break;
+		case V4L2_TUNER_MODE_LANG1:
+			audio_mode = TUNER_AUDIO_LANG1;
+			break;
+	}
+
+	v4l2_dbg(1, debug, sd, "change audio mode to %s\n",
+			mes[audio_mode]);
+	decoder->tuner_audio_mode = audio_mode;
+	/* The registers are not changed here. */
+	/* See DECODER_ENABLE_OUTPUT section. */
+	set_audio_mode(sd, decoder->tuner_audio_mode);
+	return 0;
+}
+
+static int saa717x_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
+{
+	struct saa717x_state *decoder = to_state(sd);
+	int dual_f, stereo_f;
+
+	if (decoder->radio)
+		return 0;
+	get_inf_dev_status(sd, &dual_f, &stereo_f);
+
+	v4l2_dbg(1, debug, sd, "DETECT==st:%d dual:%d\n",
+			stereo_f, dual_f);
+
+	/* mono */
+	if ((dual_f == 0) && (stereo_f == 0)) {
+		vt->rxsubchans = V4L2_TUNER_SUB_MONO;
+		v4l2_dbg(1, debug, sd, "DETECT==MONO\n");
+	}
+
+	/* stereo */
+	if (stereo_f == 1) {
+		if (vt->audmode == V4L2_TUNER_MODE_STEREO ||
+				vt->audmode == V4L2_TUNER_MODE_LANG1) {
+			vt->rxsubchans = V4L2_TUNER_SUB_STEREO;
+			v4l2_dbg(1, debug, sd, "DETECT==ST(ST)\n");
+		} else {
+			vt->rxsubchans = V4L2_TUNER_SUB_MONO;
+			v4l2_dbg(1, debug, sd, "DETECT==ST(MONO)\n");
+		}
+	}
+
+	/* dual */
+	if (dual_f == 1) {
+		if (vt->audmode == V4L2_TUNER_MODE_LANG2) {
+			vt->rxsubchans = V4L2_TUNER_SUB_LANG2 | V4L2_TUNER_SUB_MONO;
+			v4l2_dbg(1, debug, sd, "DETECT==DUAL1\n");
+		} else {
+			vt->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_MONO;
+			v4l2_dbg(1, debug, sd, "DETECT==DUAL2\n");
+		}
+	}
+	return 0;
+}
+
+static int saa717x_log_status(struct v4l2_subdev *sd)
+{
+	struct saa717x_state *state = to_state(sd);
+
+	v4l2_ctrl_handler_log_status(&state->hdl, sd->name);
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static const struct v4l2_ctrl_ops saa717x_ctrl_ops = {
+	.s_ctrl = saa717x_s_ctrl,
+};
+
+static const struct v4l2_subdev_core_ops saa717x_core_ops = {
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.g_register = saa717x_g_register,
+	.s_register = saa717x_s_register,
+#endif
+	.s_std = saa717x_s_std,
+	.g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
+	.try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
+	.s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
+	.g_ctrl = v4l2_subdev_g_ctrl,
+	.s_ctrl = v4l2_subdev_s_ctrl,
+	.queryctrl = v4l2_subdev_queryctrl,
+	.querymenu = v4l2_subdev_querymenu,
+	.log_status = saa717x_log_status,
+};
+
+static const struct v4l2_subdev_tuner_ops saa717x_tuner_ops = {
+	.g_tuner = saa717x_g_tuner,
+	.s_tuner = saa717x_s_tuner,
+	.s_radio = saa717x_s_radio,
+};
+
+static const struct v4l2_subdev_video_ops saa717x_video_ops = {
+	.s_routing = saa717x_s_video_routing,
+	.s_mbus_fmt = saa717x_s_mbus_fmt,
+	.s_stream = saa717x_s_stream,
+};
+
+static const struct v4l2_subdev_audio_ops saa717x_audio_ops = {
+	.s_routing = saa717x_s_audio_routing,
+};
+
+static const struct v4l2_subdev_ops saa717x_ops = {
+	.core = &saa717x_core_ops,
+	.tuner = &saa717x_tuner_ops,
+	.audio = &saa717x_audio_ops,
+	.video = &saa717x_video_ops,
+};
+
+/* ----------------------------------------------------------------------- */
+
+
+/* i2c implementation */
+
+/* ----------------------------------------------------------------------- */
+static int saa717x_probe(struct i2c_client *client,
+			 const struct i2c_device_id *did)
+{
+	struct saa717x_state *decoder;
+	struct v4l2_ctrl_handler *hdl;
+	struct v4l2_subdev *sd;
+	u8 id = 0;
+	char *p = "";
+
+	/* Check if the adapter supports the needed features */
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		return -EIO;
+
+	decoder = kzalloc(sizeof(struct saa717x_state), GFP_KERNEL);
+	if (decoder == NULL)
+		return -ENOMEM;
+
+	sd = &decoder->sd;
+	v4l2_i2c_subdev_init(sd, client, &saa717x_ops);
+
+	if (saa717x_write(sd, 0x5a4, 0xfe) &&
+			saa717x_write(sd, 0x5a5, 0x0f) &&
+			saa717x_write(sd, 0x5a6, 0x00) &&
+			saa717x_write(sd, 0x5a7, 0x01))
+		id = saa717x_read(sd, 0x5a0);
+	if (id != 0xc2 && id != 0x32 && id != 0xf2 && id != 0x6c) {
+		v4l2_dbg(1, debug, sd, "saa717x not found (id=%02x)\n", id);
+		kfree(decoder);
+		return -ENODEV;
+	}
+	if (id == 0xc2)
+		p = "saa7173";
+	else if (id == 0x32)
+		p = "saa7174A";
+	else if (id == 0x6c)
+		p = "saa7174HL";
+	else
+		p = "saa7171";
+	v4l2_info(sd, "%s found @ 0x%x (%s)\n", p,
+			client->addr << 1, client->adapter->name);
+
+	hdl = &decoder->hdl;
+	v4l2_ctrl_handler_init(hdl, 9);
+	/* add in ascending ID order */
+	v4l2_ctrl_new_std(hdl, &saa717x_ctrl_ops,
+			V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
+	v4l2_ctrl_new_std(hdl, &saa717x_ctrl_ops,
+			V4L2_CID_CONTRAST, 0, 255, 1, 68);
+	v4l2_ctrl_new_std(hdl, &saa717x_ctrl_ops,
+			V4L2_CID_SATURATION, 0, 255, 1, 64);
+	v4l2_ctrl_new_std(hdl, &saa717x_ctrl_ops,
+			V4L2_CID_HUE, -128, 127, 1, 0);
+	v4l2_ctrl_new_std(hdl, &saa717x_ctrl_ops,
+			V4L2_CID_AUDIO_VOLUME, 0, 65535, 65535 / 100, 42000);
+	v4l2_ctrl_new_std(hdl, &saa717x_ctrl_ops,
+			V4L2_CID_AUDIO_BALANCE, 0, 65535, 65535 / 100, 32768);
+	v4l2_ctrl_new_std(hdl, &saa717x_ctrl_ops,
+			V4L2_CID_AUDIO_BASS, -16, 15, 1, 0);
+	v4l2_ctrl_new_std(hdl, &saa717x_ctrl_ops,
+			V4L2_CID_AUDIO_TREBLE, -16, 15, 1, 0);
+	v4l2_ctrl_new_std(hdl, &saa717x_ctrl_ops,
+			V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0);
+	sd->ctrl_handler = hdl;
+	if (hdl->error) {
+		int err = hdl->error;
+
+		v4l2_ctrl_handler_free(hdl);
+		kfree(decoder);
+		return err;
+	}
+
+	decoder->std = V4L2_STD_NTSC;
+	decoder->input = -1;
+	decoder->enable = 1;
+
+	/* FIXME!! */
+	decoder->playback = 0;	/* initially capture mode used */
+	decoder->audio = 1; /* DECODER_AUDIO_48_KHZ */
+
+	decoder->audio_input = 2; /* FIXME!! */
+
+	decoder->tuner_audio_mode = TUNER_AUDIO_STEREO;
+	/* set volume, bass and treble */
+	decoder->audio_main_vol_l = 6;
+	decoder->audio_main_vol_r = 6;
+
+	v4l2_dbg(1, debug, sd, "writing init values\n");
+
+	/* FIXME!! */
+	saa717x_write_regs(sd, reg_init_initialize);
+
+	v4l2_ctrl_handler_setup(hdl);
+
+	set_current_state(TASK_INTERRUPTIBLE);
+	schedule_timeout(2*HZ);
+	return 0;
+}
+
+static int saa717x_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+
+	v4l2_device_unregister_subdev(sd);
+	v4l2_ctrl_handler_free(sd->ctrl_handler);
+	kfree(to_state(sd));
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static const struct i2c_device_id saa717x_id[] = {
+	{ "saa717x", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, saa717x_id);
+
+static struct i2c_driver saa717x_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "saa717x",
+	},
+	.probe		= saa717x_probe,
+	.remove		= saa717x_remove,
+	.id_table	= saa717x_id,
+};
+
+module_i2c_driver(saa717x_driver);
diff --git a/drivers/media/i2c/saa7185.c b/drivers/media/i2c/saa7185.c
new file mode 100644
index 0000000..2c6b65c
--- /dev/null
+++ b/drivers/media/i2c/saa7185.c
@@ -0,0 +1,377 @@
+/*
+ * saa7185 - Philips SAA7185B video encoder 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)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/slab.h>
+#include <linux/ioctl.h>
+#include <asm/uaccess.h>
+#include <linux/i2c.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-chip-ident.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];
+
+	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 v4l2_subdev *sd)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	return i2c_smbus_read_byte(client);
+}
+
+static int saa7185_write(struct v4l2_subdev *sd, u8 reg, u8 value)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct saa7185 *encoder = to_saa7185(sd);
+
+	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 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;
+
+	/* the adv7175 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++] =
+				    encoder->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 = saa7185_write(sd, reg, *data++);
+			if (ret < 0)
+				break;
+			len -= 2;
+		}
+	}
+
+	return ret;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static const unsigned char init_common[] = {
+	0x3a, 0x0f,		/* CBENB=0, V656=0, VY2C=1,
+				 * YUV2C=1, MY2C=1, MUV2C=1 */
+
+	0x42, 0x6b,		/* OVLY0=107 */
+	0x43, 0x00,		/* OVLU0=0     white */
+	0x44, 0x00,		/* OVLV0=0   */
+	0x45, 0x22,		/* OVLY1=34  */
+	0x46, 0xac,		/* OVLU1=172   yellow */
+	0x47, 0x0e,		/* OVLV1=14  */
+	0x48, 0x03,		/* OVLY2=3   */
+	0x49, 0x1d,		/* OVLU2=29    cyan */
+	0x4a, 0xac,		/* OVLV2=172 */
+	0x4b, 0xf0,		/* OVLY3=240 */
+	0x4c, 0xc8,		/* OVLU3=200   green */
+	0x4d, 0xb9,		/* OVLV3=185 */
+	0x4e, 0xd4,		/* OVLY4=212 */
+	0x4f, 0x38,		/* OVLU4=56    magenta */
+	0x50, 0x47,		/* OVLV4=71  */
+	0x51, 0xc1,		/* OVLY5=193 */
+	0x52, 0xe3,		/* OVLU5=227   red */
+	0x53, 0x54,		/* OVLV5=84  */
+	0x54, 0xa3,		/* OVLY6=163 */
+	0x55, 0x54,		/* OVLU6=84    blue */
+	0x56, 0xf2,		/* OVLV6=242 */
+	0x57, 0x90,		/* OVLY7=144 */
+	0x58, 0x00,		/* OVLU7=0     black */
+	0x59, 0x00,		/* OVLV7=0   */
+
+	0x5a, 0x00,		/* CHPS=0    */
+	0x5b, 0x76,		/* GAINU=118 */
+	0x5c, 0xa5,		/* GAINV=165 */
+	0x5d, 0x3c,		/* BLCKL=60  */
+	0x5e, 0x3a,		/* BLNNL=58  */
+	0x5f, 0x3a,		/* CCRS=0, BLNVB=58 */
+	0x60, 0x00,		/* NULL      */
+
+	/* 0x61 - 0x66 set according to norm */
+
+	0x67, 0x00,		/* 0 : caption 1st byte odd  field */
+	0x68, 0x00,		/* 0 : caption 2nd byte odd  field */
+	0x69, 0x00,		/* 0 : caption 1st byte even field */
+	0x6a, 0x00,		/* 0 : caption 2nd byte even field */
+
+	0x6b, 0x91,		/* MODIN=2, PCREF=0, SCCLN=17 */
+	0x6c, 0x20,		/* SRCV1=0, TRCV2=1, ORCV1=0, PRCV1=0,
+				 * CBLF=0, ORCV2=0, PRCV2=0 */
+	0x6d, 0x00,		/* SRCM1=0, CCEN=0 */
+
+	0x6e, 0x0e,		/* HTRIG=0x005, approx. centered, at
+				 * least for PAL */
+	0x6f, 0x00,		/* HTRIG upper bits */
+	0x70, 0x20,		/* PHRES=0, SBLN=1, VTRIG=0 */
+
+	/* The following should not be needed */
+
+	0x71, 0x15,		/* BMRQ=0x115 */
+	0x72, 0x90,		/* EMRQ=0x690 */
+	0x73, 0x61,		/* EMRQ=0x690, BMRQ=0x115 */
+	0x74, 0x00,		/* NULL       */
+	0x75, 0x00,		/* NULL       */
+	0x76, 0x00,		/* NULL       */
+	0x77, 0x15,		/* BRCV=0x115 */
+	0x78, 0x90,		/* ERCV=0x690 */
+	0x79, 0x61,		/* ERCV=0x690, BRCV=0x115 */
+
+	/* Field length controls */
+
+	0x7a, 0x70,		/* FLC=0 */
+
+	/* The following should not be needed if SBLN = 1 */
+
+	0x7b, 0x16,		/* FAL=22 */
+	0x7c, 0x35,		/* LAL=244 */
+	0x7d, 0x20,		/* LAL=244, FAL=22 */
+};
+
+static const unsigned char init_pal[] = {
+	0x61, 0x1e,		/* FISE=0, PAL=1, SCBW=1, RTCE=1,
+				 * YGS=1, INPI=0, DOWN=0 */
+	0x62, 0xc8,		/* DECTYP=1, BSTA=72 */
+	0x63, 0xcb,		/* FSC0 */
+	0x64, 0x8a,		/* FSC1 */
+	0x65, 0x09,		/* FSC2 */
+	0x66, 0x2a,		/* FSC3 */
+};
+
+static const unsigned char init_ntsc[] = {
+	0x61, 0x1d,		/* FISE=1, PAL=0, SCBW=1, RTCE=1,
+				 * YGS=1, INPI=0, DOWN=0 */
+	0x62, 0xe6,		/* DECTYP=1, BSTA=102 */
+	0x63, 0x1f,		/* FSC0 */
+	0x64, 0x7c,		/* FSC1 */
+	0x65, 0xf0,		/* FSC2 */
+	0x66, 0x21,		/* FSC3 */
+};
+
+
+static int saa7185_init(struct v4l2_subdev *sd, u32 val)
+{
+	struct saa7185 *encoder = to_saa7185(sd);
+
+	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,
+			     u32 input, u32 output, u32 config)
+{
+	struct saa7185 *encoder = to_saa7185(sd);
+
+	/* RJ: input = 0: input is from SA7111
+	 input = 1: input is from ZR36060 */
+
+	switch (input) {
+	case 0:
+		/* 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 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 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;
+
+	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 const struct v4l2_subdev_core_ops saa7185_core_ops = {
+	.g_chip_ident = saa7185_g_chip_ident,
+	.init = saa7185_init,
+};
+
+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))
+		return -ENODEV;
+
+	v4l_info(client, "chip found @ 0x%x (%s)\n",
+			client->addr << 1, client->adapter->name);
+
+	encoder = kzalloc(sizeof(struct saa7185), GFP_KERNEL);
+	if (encoder == NULL)
+		return -ENOMEM;
+	encoder->norm = V4L2_STD_NTSC;
+	sd = &encoder->sd;
+	v4l2_i2c_subdev_init(sd, client, &saa7185_ops);
+
+	i = saa7185_write_block(sd, init_common, sizeof(init_common));
+	if (i >= 0)
+		i = saa7185_write_block(sd, init_ntsc, sizeof(init_ntsc));
+	if (i < 0)
+		v4l2_dbg(1, debug, sd, "init error %d\n", i);
+	else
+		v4l2_dbg(1, debug, sd, "revision 0x%x\n",
+				saa7185_read(sd) >> 5);
+	return 0;
+}
+
+static int saa7185_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct saa7185 *encoder = to_saa7185(sd);
+
+	v4l2_device_unregister_subdev(sd);
+	/* SW: output off is active */
+	saa7185_write(sd, 0x61, (encoder->reg[0x61]) | 0x40);
+	kfree(encoder);
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static const struct i2c_device_id saa7185_id[] = {
+	{ "saa7185", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, saa7185_id);
+
+static struct i2c_driver saa7185_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "saa7185",
+	},
+	.probe		= saa7185_probe,
+	.remove		= saa7185_remove,
+	.id_table	= saa7185_id,
+};
+
+module_i2c_driver(saa7185_driver);
diff --git a/drivers/media/i2c/saa7191.c b/drivers/media/i2c/saa7191.c
new file mode 100644
index 0000000..d7d1670
--- /dev/null
+++ b/drivers/media/i2c/saa7191.c
@@ -0,0 +1,659 @@
+/*
+ *  saa7191.c - Philips SAA7191 video decoder driver
+ *
+ *  Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org>
+ *  Copyright (C) 2004,2005 Mikael Nousiainen <tmnousia@cc.hut.fi>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+
+#include <linux/videodev2.h>
+#include <linux/i2c.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-chip-ident.h>
+
+#include "saa7191.h"
+
+#define SAA7191_MODULE_VERSION	"0.0.5"
+
+MODULE_DESCRIPTION("Philips SAA7191 video decoder driver");
+MODULE_VERSION(SAA7191_MODULE_VERSION);
+MODULE_AUTHOR("Mikael Nousiainen <tmnousia@cc.hut.fi>");
+MODULE_LICENSE("GPL");
+
+
+// #define SAA7191_DEBUG
+
+#ifdef SAA7191_DEBUG
+#define dprintk(x...) printk("SAA7191: " x);
+#else
+#define dprintk(x...)
+#endif
+
+#define SAA7191_SYNC_COUNT	30
+#define SAA7191_SYNC_DELAY	100	/* milliseconds */
+
+struct saa7191 {
+	struct v4l2_subdev sd;
+
+	/* the register values are stored here as the actual
+	 * I2C-registers are write-only */
+	u8 reg[25];
+
+	int input;
+	v4l2_std_id norm;
+};
+
+static inline struct saa7191 *to_saa7191(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct saa7191, sd);
+}
+
+static const u8 initseq[] = {
+	0,	/* Subaddress */
+
+	0x50,	/* (0x50) SAA7191_REG_IDEL */
+
+	/* 50 Hz signal timing */
+	0x30,	/* (0x30) SAA7191_REG_HSYB */
+	0x00,	/* (0x00) SAA7191_REG_HSYS */
+	0xe8,	/* (0xe8) SAA7191_REG_HCLB */
+	0xb6,	/* (0xb6) SAA7191_REG_HCLS */
+	0xf4,	/* (0xf4) SAA7191_REG_HPHI */
+
+	/* control */
+	SAA7191_LUMA_APER_1,	/* (0x01) SAA7191_REG_LUMA - CVBS mode */
+	0x00,	/* (0x00) SAA7191_REG_HUEC */
+	0xf8,	/* (0xf8) SAA7191_REG_CKTQ */
+	0xf8,	/* (0xf8) SAA7191_REG_CKTS */
+	0x90,	/* (0x90) SAA7191_REG_PLSE */
+	0x90,	/* (0x90) SAA7191_REG_SESE */
+	0x00,	/* (0x00) SAA7191_REG_GAIN */
+	SAA7191_STDC_NFEN | SAA7191_STDC_HRMV,	/* (0x0c) SAA7191_REG_STDC
+						 * - not SECAM,
+						 * slow time constant */
+	SAA7191_IOCK_OEDC | SAA7191_IOCK_OEHS | SAA7191_IOCK_OEVS
+	| SAA7191_IOCK_OEDY,	/* (0x78) SAA7191_REG_IOCK
+				 * - chroma from CVBS, GPSW1 & 2 off */
+	SAA7191_CTL3_AUFD | SAA7191_CTL3_SCEN | SAA7191_CTL3_OFTS
+	| SAA7191_CTL3_YDEL0,	/* (0x99) SAA7191_REG_CTL3
+				 * - automatic field detection */
+	0x00,	/* (0x00) SAA7191_REG_CTL4 */
+	0x2c,	/* (0x2c) SAA7191_REG_CHCV - PAL nominal value */
+	0x00,	/* unused */
+	0x00,	/* unused */
+
+	/* 60 Hz signal timing */
+	0x34,	/* (0x34) SAA7191_REG_HS6B */
+	0x0a,	/* (0x0a) SAA7191_REG_HS6S */
+	0xf4,	/* (0xf4) SAA7191_REG_HC6B */
+	0xce,	/* (0xce) SAA7191_REG_HC6S */
+	0xf4,	/* (0xf4) SAA7191_REG_HP6I */
+};
+
+/* SAA7191 register handling */
+
+static u8 saa7191_read_reg(struct v4l2_subdev *sd, u8 reg)
+{
+	return to_saa7191(sd)->reg[reg];
+}
+
+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);
+	if (ret < 0) {
+		printk(KERN_ERR "SAA7191: saa7191_read_status(): read failed\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+
+static int saa7191_write_reg(struct v4l2_subdev *sd, u8 reg, u8 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 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;
+
+	for (i = 0; i < (length - 1); i++) {
+		decoder->reg[data[0] + i] = data[i + 1];
+	}
+
+	ret = i2c_master_send(client, data, length);
+	if (ret < 0) {
+		printk(KERN_ERR "SAA7191: saa7191_write_block(): "
+		       "write failed\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+/* Helper functions */
+
+static int saa7191_s_routing(struct v4l2_subdev *sd,
+			     u32 input, u32 output, u32 config)
+{
+	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) {
+	case SAA7191_INPUT_COMPOSITE: /* Set Composite input */
+		iock &= ~(SAA7191_IOCK_CHRS | SAA7191_IOCK_GPSW1
+			  | SAA7191_IOCK_GPSW2);
+		/* Chrominance trap active */
+		luma &= ~SAA7191_LUMA_BYPS;
+		break;
+	case SAA7191_INPUT_SVIDEO: /* Set S-Video input */
+		iock |= SAA7191_IOCK_CHRS | SAA7191_IOCK_GPSW2;
+		/* Chrominance trap bypassed */
+		luma |= SAA7191_LUMA_BYPS;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	err = saa7191_write_reg(sd, SAA7191_REG_LUMA, luma);
+	if (err)
+		return -EIO;
+	err = saa7191_write_reg(sd, SAA7191_REG_IOCK, iock);
+	if (err)
+		return -EIO;
+
+	decoder->input = input;
+
+	return 0;
+}
+
+static int saa7191_s_std(struct v4l2_subdev *sd, v4l2_std_id norm)
+{
+	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;
+
+	if (norm & V4L2_STD_PAL) {
+		stdc &= ~SAA7191_STDC_SECS;
+		ctl3 &= ~(SAA7191_CTL3_AUFD | SAA7191_CTL3_FSEL);
+		chcv = SAA7191_CHCV_PAL;
+	} else if (norm & V4L2_STD_NTSC) {
+		stdc &= ~SAA7191_STDC_SECS;
+		ctl3 &= ~SAA7191_CTL3_AUFD;
+		ctl3 |= SAA7191_CTL3_FSEL;
+		chcv = SAA7191_CHCV_NTSC;
+	} else if (norm & V4L2_STD_SECAM) {
+		stdc |= SAA7191_STDC_SECS;
+		ctl3 &= ~(SAA7191_CTL3_AUFD | SAA7191_CTL3_FSEL);
+		chcv = SAA7191_CHCV_PAL;
+	} else {
+		return -EINVAL;
+	}
+
+	err = saa7191_write_reg(sd, SAA7191_REG_CTL3, ctl3);
+	if (err)
+		return -EIO;
+	err = saa7191_write_reg(sd, SAA7191_REG_STDC, stdc);
+	if (err)
+		return -EIO;
+	err = saa7191_write_reg(sd, SAA7191_REG_CHCV, chcv);
+	if (err)
+		return -EIO;
+
+	decoder->norm = norm;
+
+	dprintk("ctl3: %02x stdc: %02x chcv: %02x\n", ctl3,
+		stdc, chcv);
+	dprintk("norm: %llx\n", norm);
+
+	return 0;
+}
+
+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(sd, status))
+			return -EIO;
+
+		if (((*status) & SAA7191_STATUS_HLCK) == 0) {
+			dprintk("Signal found\n");
+			return 0;
+		}
+
+		msleep(SAA7191_SYNC_DELAY);
+	}
+
+	dprintk("No signal\n");
+
+	return -EBUSY;
+}
+
+static int saa7191_querystd(struct v4l2_subdev *sd, v4l2_std_id *norm)
+{
+	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(sd, SAA7191_REG_STDC, stdc);
+	if (err) {
+		err = -EIO;
+		goto out;
+	}
+	err = saa7191_write_reg(sd, SAA7191_REG_CTL3, ctl3);
+	if (err) {
+		err = -EIO;
+		goto out;
+	}
+
+	ctl3 |= SAA7191_CTL3_AUFD;
+	err = saa7191_write_reg(sd, SAA7191_REG_CTL3, ctl3);
+	if (err) {
+		err = -EIO;
+		goto out;
+	}
+
+	msleep(SAA7191_SYNC_DELAY);
+
+	err = saa7191_wait_for_signal(sd, &status);
+	if (err)
+		goto out;
+
+	if (status & SAA7191_STATUS_FIDT) {
+		/* 60Hz signal -> NTSC */
+		dprintk("60Hz signal: NTSC\n");
+		*norm = V4L2_STD_NTSC;
+		return 0;
+	}
+
+	/* 50Hz signal */
+	dprintk("50Hz signal: Trying PAL...\n");
+
+	/* try PAL first */
+	err = saa7191_s_std(sd, V4L2_STD_PAL);
+	if (err)
+		goto out;
+
+	msleep(SAA7191_SYNC_DELAY);
+
+	err = saa7191_wait_for_signal(sd, &status);
+	if (err)
+		goto out;
+
+	/* not 50Hz ? */
+	if (status & SAA7191_STATUS_FIDT) {
+		dprintk("No 50Hz signal\n");
+		saa7191_s_std(sd, old_norm);
+		return -EAGAIN;
+	}
+
+	if (status & SAA7191_STATUS_CODE) {
+		dprintk("PAL\n");
+		*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_s_std(sd, V4L2_STD_SECAM);
+	if (err)
+		goto out;
+
+	msleep(SAA7191_SYNC_DELAY);
+
+	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;
+	}
+
+	if (status & SAA7191_STATUS_CODE) {
+		/* Color detected -> SECAM */
+		dprintk("SECAM\n");
+		*norm = V4L2_STD_SECAM;
+		return saa7191_s_std(sd, old_norm);
+	}
+
+	dprintk("No color detected with SECAM - Going back to PAL.\n");
+
+out:
+	return saa7191_s_std(sd, old_norm);
+}
+
+static int saa7191_autodetect_norm(struct v4l2_subdev *sd)
+{
+	u8 status;
+
+	dprintk("SAA7191 signal auto-detection...\n");
+
+	dprintk("Reading status...\n");
+
+	if (saa7191_read_status(sd, &status))
+		return -EIO;
+
+	dprintk("Checking for signal...\n");
+
+	/* no signal ? */
+	if (status & SAA7191_STATUS_HLCK) {
+		dprintk("No signal\n");
+		return -EBUSY;
+	}
+
+	dprintk("Signal found\n");
+
+	if (status & SAA7191_STATUS_FIDT) {
+		/* 60hz signal -> NTSC */
+		dprintk("NTSC\n");
+		return saa7191_s_std(sd, V4L2_STD_NTSC);
+	} else {
+		/* 50hz signal -> PAL */
+		dprintk("PAL\n");
+		return saa7191_s_std(sd, V4L2_STD_PAL);
+	}
+}
+
+static int saa7191_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+	u8 reg;
+	int ret = 0;
+
+	switch (ctrl->id) {
+	case SAA7191_CONTROL_BANDPASS:
+	case SAA7191_CONTROL_BANDPASS_WEIGHT:
+	case SAA7191_CONTROL_CORING:
+		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;
+			break;
+		case SAA7191_CONTROL_BANDPASS_WEIGHT:
+			ctrl->value = ((s32)reg & SAA7191_LUMA_APER_MASK)
+				>> SAA7191_LUMA_APER_SHIFT;
+			break;
+		case SAA7191_CONTROL_CORING:
+			ctrl->value = ((s32)reg & SAA7191_LUMA_CORI_MASK)
+				>> SAA7191_LUMA_CORI_SHIFT;
+			break;
+		}
+		break;
+	case SAA7191_CONTROL_FORCE_COLOUR:
+	case SAA7191_CONTROL_CHROMA_GAIN:
+		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 V4L2_CID_HUE:
+		reg = saa7191_read_reg(sd, SAA7191_REG_HUEC);
+		if (reg < 0x80)
+			reg += 0x80;
+		else
+			reg -= 0x80;
+		ctrl->value = (s32)reg;
+		break;
+	case SAA7191_CONTROL_VTRC:
+		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(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(sd, SAA7191_REG_CTL4);
+		ctrl->value = ((s32)reg & SAA7191_CTL4_VNOI_MASK)
+			>> SAA7191_CTL4_VNOI_SHIFT;
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static int saa7191_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+	u8 reg;
+	int ret = 0;
+
+	switch (ctrl->id) {
+	case SAA7191_CONTROL_BANDPASS:
+	case SAA7191_CONTROL_BANDPASS_WEIGHT:
+	case SAA7191_CONTROL_CORING:
+		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)
+				& SAA7191_LUMA_BPSS_MASK;
+			break;
+		case SAA7191_CONTROL_BANDPASS_WEIGHT:
+			reg &= ~SAA7191_LUMA_APER_MASK;
+			reg |= (ctrl->value << SAA7191_LUMA_APER_SHIFT)
+				& SAA7191_LUMA_APER_MASK;
+			break;
+		case SAA7191_CONTROL_CORING:
+			reg &= ~SAA7191_LUMA_CORI_MASK;
+			reg |= (ctrl->value << SAA7191_LUMA_CORI_SHIFT)
+				& SAA7191_LUMA_CORI_MASK;
+			break;
+		}
+		ret = saa7191_write_reg(sd, SAA7191_REG_LUMA, reg);
+		break;
+	case SAA7191_CONTROL_FORCE_COLOUR:
+	case SAA7191_CONTROL_CHROMA_GAIN:
+		reg = saa7191_read_reg(sd, SAA7191_REG_GAIN);
+		if (ctrl->id == SAA7191_CONTROL_FORCE_COLOUR) {
+			if (ctrl->value)
+				reg |= SAA7191_GAIN_COLO;
+			else
+				reg &= ~SAA7191_GAIN_COLO;
+		} else {
+			reg &= ~SAA7191_GAIN_LFIS_MASK;
+			reg |= (ctrl->value << SAA7191_GAIN_LFIS_SHIFT)
+				& SAA7191_GAIN_LFIS_MASK;
+		}
+		ret = saa7191_write_reg(sd, SAA7191_REG_GAIN, reg);
+		break;
+	case V4L2_CID_HUE:
+		reg = ctrl->value & 0xff;
+		if (reg < 0x80)
+			reg += 0x80;
+		else
+			reg -= 0x80;
+		ret = saa7191_write_reg(sd, SAA7191_REG_HUEC, reg);
+		break;
+	case SAA7191_CONTROL_VTRC:
+		reg = saa7191_read_reg(sd, SAA7191_REG_STDC);
+		if (ctrl->value)
+			reg |= SAA7191_STDC_VTRC;
+		else
+			reg &= ~SAA7191_STDC_VTRC;
+		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(sd, SAA7191_REG_CTL3);
+		reg &= ~SAA7191_CTL3_YDEL_MASK;
+		reg |= (value << SAA7191_CTL3_YDEL_SHIFT)
+			& SAA7191_CTL3_YDEL_MASK;
+		ret = saa7191_write_reg(sd, SAA7191_REG_CTL3, reg);
+		break;
+	}
+	case SAA7191_CONTROL_VNR:
+		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(sd, SAA7191_REG_CTL4, reg);
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+/* I2C-interface */
+
+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,
+	.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,
+};
+
+static int saa7191_probe(struct i2c_client *client,
+			  const struct i2c_device_id *id)
+{
+	int err = 0;
+	struct saa7191 *decoder;
+	struct v4l2_subdev *sd;
+
+	v4l_info(client, "chip found @ 0x%x (%s)\n",
+			client->addr << 1, client->adapter->name);
+
+	decoder = kzalloc(sizeof(*decoder), GFP_KERNEL);
+	if (!decoder)
+		return -ENOMEM;
+
+	sd = &decoder->sd;
+	v4l2_i2c_subdev_init(sd, client, &saa7191_ops);
+
+	err = saa7191_write_block(sd, sizeof(initseq), initseq);
+	if (err) {
+		printk(KERN_ERR "SAA7191 initialization failed\n");
+		kfree(decoder);
+		return err;
+	}
+
+	printk(KERN_INFO "SAA7191 initialized\n");
+
+	decoder->input = SAA7191_INPUT_COMPOSITE;
+	decoder->norm = V4L2_STD_PAL;
+
+	err = saa7191_autodetect_norm(sd);
+	if (err && (err != -EBUSY))
+		printk(KERN_ERR "SAA7191: Signal auto-detection failed\n");
+
+	return 0;
+}
+
+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 struct i2c_driver saa7191_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "saa7191",
+	},
+	.probe		= saa7191_probe,
+	.remove		= saa7191_remove,
+	.id_table	= saa7191_id,
+};
+
+module_i2c_driver(saa7191_driver);
diff --git a/drivers/media/i2c/saa7191.h b/drivers/media/i2c/saa7191.h
new file mode 100644
index 0000000..803c74d
--- /dev/null
+++ b/drivers/media/i2c/saa7191.h
@@ -0,0 +1,245 @@
+/*
+ *  saa7191.h - Philips SAA7191 video decoder driver
+ *
+ *  Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org>
+ *  Copyright (C) 2004,2005 Mikael Nousiainen <tmnousia@cc.hut.fi>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+
+#ifndef _SAA7191_H_
+#define _SAA7191_H_
+
+/* Philips SAA7191 DMSD I2C bus address */
+#define SAA7191_ADDR		0x8a
+
+/* Register subaddresses. */
+#define SAA7191_REG_IDEL	0x00
+#define SAA7191_REG_HSYB	0x01
+#define SAA7191_REG_HSYS	0x02
+#define SAA7191_REG_HCLB	0x03
+#define SAA7191_REG_HCLS	0x04
+#define SAA7191_REG_HPHI	0x05
+#define SAA7191_REG_LUMA	0x06
+#define SAA7191_REG_HUEC	0x07
+#define SAA7191_REG_CKTQ	0x08 /* bits 3-7 */
+#define SAA7191_REG_CKTS	0x09 /* bits 3-7 */
+#define SAA7191_REG_PLSE	0x0a
+#define SAA7191_REG_SESE	0x0b
+#define SAA7191_REG_GAIN	0x0c
+#define SAA7191_REG_STDC	0x0d
+#define SAA7191_REG_IOCK	0x0e
+#define SAA7191_REG_CTL3	0x0f
+#define SAA7191_REG_CTL4	0x10
+#define SAA7191_REG_CHCV	0x11
+#define SAA7191_REG_HS6B	0x14
+#define SAA7191_REG_HS6S	0x15
+#define SAA7191_REG_HC6B	0x16
+#define SAA7191_REG_HC6S	0x17
+#define SAA7191_REG_HP6I	0x18
+#define SAA7191_REG_STATUS	0xff	/* not really a subaddress */
+
+/* Status Register definitions */
+#define SAA7191_STATUS_CODE	0x01	/* color detected flag */
+#define SAA7191_STATUS_FIDT	0x20	/* signal type 50/60 Hz */
+#define SAA7191_STATUS_HLCK	0x40	/* PLL unlocked(1)/locked(0) */
+#define SAA7191_STATUS_STTC	0x80	/* tv/vtr time constant */
+
+/* Luminance Control Register definitions */
+/* input mode select bit:
+ * 0=CVBS (chrominance trap active), 1=S-Video (trap bypassed) */
+#define SAA7191_LUMA_BYPS	0x80
+/* pre-filter (only when chrominance trap is active) */
+#define SAA7191_LUMA_PREF	0x40
+/* aperture bandpass to select different characteristics with maximums
+ * (bits 4-5) */
+#define SAA7191_LUMA_BPSS_MASK	0x30
+#define SAA7191_LUMA_BPSS_SHIFT	4
+#define SAA7191_LUMA_BPSS_3	0x30
+#define SAA7191_LUMA_BPSS_2	0x20
+#define SAA7191_LUMA_BPSS_1	0x10
+#define SAA7191_LUMA_BPSS_0	0x00
+/* coring range for high frequency components according to 8-bit luminance
+ * (bits 2-3)
+ * 0=coring off, n= (+-)n LSB */
+#define SAA7191_LUMA_CORI_MASK	0x0c
+#define SAA7191_LUMA_CORI_SHIFT	2
+#define SAA7191_LUMA_CORI_3	0x0c
+#define SAA7191_LUMA_CORI_2	0x08
+#define SAA7191_LUMA_CORI_1	0x04
+#define SAA7191_LUMA_CORI_0	0x00
+/* aperture bandpass filter weights high frequency components of luminance
+ * signal (bits 0-1)
+ * 0=factor 0, 1=0.25, 2=0.5, 3=1 */
+#define SAA7191_LUMA_APER_MASK	0x03
+#define SAA7191_LUMA_APER_SHIFT	0
+#define SAA7191_LUMA_APER_3	0x03
+#define SAA7191_LUMA_APER_2	0x02
+#define SAA7191_LUMA_APER_1	0x01
+#define SAA7191_LUMA_APER_0	0x00
+
+/* Chrominance Gain Control Settings Register definitions */
+/* colour on: 0=automatic colour-killer enabled, 1=forced colour on */
+#define SAA7191_GAIN_COLO	0x80
+/* chrominance gain control (AGC filter)
+ * 0=loop filter time constant slow, 1=medium, 2=fast, 3=actual gain */
+#define SAA7191_GAIN_LFIS_MASK	0x60
+#define SAA7191_GAIN_LFIS_SHIFT	5
+#define SAA7191_GAIN_LFIS_3	0x60
+#define SAA7191_GAIN_LFIS_2	0x40
+#define SAA7191_GAIN_LFIS_1	0x20
+#define SAA7191_GAIN_LFIS_0	0x00
+
+/* Standard/Mode Control Register definitions */
+/* tv/vtr mode bit: 0=TV mode (slow time constant),
+ * 1=VTR mode (fast time constant) */
+#define SAA7191_STDC_VTRC	0x80
+/* SAA7191B-specific functions enable (RTCO, ODD and GPSW0 outputs)
+ * 0=outputs set to high-impedance (circuit equals SAA7191), 1=enabled */
+#define SAA7191_STDC_NFEN	0x08
+/* HREF generation: 0=like SAA7191, 1=HREF is 8xLLC2 clocks earlier */
+#define SAA7191_STDC_HRMV	0x04
+/* general purpose switch 0
+ * (not used with VINO afaik) */
+#define SAA7191_STDC_GPSW0	0x02
+/* SECAM mode bit: 0=other standards, 1=SECAM */
+#define SAA7191_STDC_SECS	0x01
+
+/* I/O and Clock Control Register definitions */
+/* horizontal clock PLL: 0=PLL closed,
+ * 1=PLL circuit open and horizontal freq fixed */
+#define SAA7191_IOCK_HPLL	0x80
+/* colour-difference output enable (outputs UV0-UV7) */
+#define SAA7191_IOCK_OEDC	0x40
+/* H-sync output enable */
+#define SAA7191_IOCK_OEHS	0x20
+/* V-sync output enable */
+#define SAA7191_IOCK_OEVS	0x10
+/* luminance output enable (outputs Y0-Y7) */
+#define SAA7191_IOCK_OEDY	0x08
+/* S-VHS bit (chrominance from CVBS or from chrominance input):
+ * 0=controlled by BYPS-bit, 1=from chrominance input */
+#define SAA7191_IOCK_CHRS	0x04
+/* general purpose switch 2
+ * VINO-specific: 0=used with CVBS, 1=used with S-Video */
+#define SAA7191_IOCK_GPSW2	0x02
+/* general purpose switch 1 */
+/* VINO-specific: 0=always, 1=not used!*/
+#define SAA7191_IOCK_GPSW1	0x01
+
+/* Miscellaneous Control #1 Register definitions */
+/* automatic field detection (50/60Hz standard) */
+#define SAA7191_CTL3_AUFD	0x80
+/* field select: (if AUFD=0)
+ * 0=50Hz (625 lines), 1=60Hz (525 lines) */
+#define SAA7191_CTL3_FSEL	0x40
+/* SECAM cross-colour reduction enable */
+#define SAA7191_CTL3_SXCR	0x20
+/* sync and clamping pulse enable (HCL and HSY outputs) */
+#define SAA7191_CTL3_SCEN	0x10
+/* output format: 0=4:1:1, 1=4:2:2 (4:2:2 for VINO) */
+#define SAA7191_CTL3_OFTS	0x08
+/* luminance delay compensation
+ * 0=0*2/LLC,  1=+1*2/LLC, 2=+2*2/LLC, 3=+3*2/LLC,
+ * 4=-4*2/LLC, 5=-3*2/LLC, 6=-2*2/LLC, 7=-1*2/LLC
+ * step size = 2/LLC = 67.8ns for 50Hz, 81.5ns for 60Hz */
+#define SAA7191_CTL3_YDEL_MASK	0x07
+#define SAA7191_CTL3_YDEL_SHIFT	0
+#define SAA7191_CTL3_YDEL2	0x04
+#define SAA7191_CTL3_YDEL1	0x02
+#define SAA7191_CTL3_YDEL0	0x01
+
+/* Miscellaneous Control #2 Register definitions */
+/* select HREF position
+ * 0=normal, HREF is matched to YUV output port,
+ * 1=HREF is matched to CVBS input port */
+#define SAA7191_CTL4_HRFS	0x04
+/* vertical noise reduction
+ * 0=normal, 1=searching window, 2=auto-deflection, 3=reduction bypassed */
+#define SAA7191_CTL4_VNOI_MASK	0x03
+#define SAA7191_CTL4_VNOI_SHIFT	0
+#define SAA7191_CTL4_VNOI_3	0x03
+#define SAA7191_CTL4_VNOI_2	0x02
+#define SAA7191_CTL4_VNOI_1	0x01
+#define SAA7191_CTL4_VNOI_0	0x00
+
+/* Chrominance Gain Control Register definitions
+ * - for QAM-modulated input signals, effects output amplitude
+ * (SECAM gain fixed)
+ * (nominal values for UV CCIR level) */
+#define SAA7191_CHCV_NTSC	0x2c
+#define SAA7191_CHCV_PAL	0x59
+
+/* Driver interface definitions */
+#define SAA7191_INPUT_COMPOSITE	0
+#define SAA7191_INPUT_SVIDEO	1
+
+#define SAA7191_NORM_PAL	1
+#define SAA7191_NORM_NTSC	2
+#define SAA7191_NORM_SECAM	3
+
+struct saa7191_status {
+	/* 0=no signal, 1=signal detected */
+	int signal;
+	/* 0=50hz (pal) signal, 1=60hz (ntsc) signal */
+	int signal_60hz;
+	/* 0=no color detected, 1=color detected */
+	int color;
+
+	/* current SAA7191_INPUT_ */
+	int input;
+	/* current SAA7191_NORM_ */
+	int norm;
+};
+
+#define SAA7191_BANDPASS_MIN		0x00
+#define SAA7191_BANDPASS_MAX		0x03
+#define SAA7191_BANDPASS_DEFAULT	0x00
+
+#define SAA7191_BANDPASS_WEIGHT_MIN	0x00
+#define SAA7191_BANDPASS_WEIGHT_MAX	0x03
+#define SAA7191_BANDPASS_WEIGHT_DEFAULT	0x01
+
+#define SAA7191_CORING_MIN		0x00
+#define SAA7191_CORING_MAX		0x03
+#define SAA7191_CORING_DEFAULT		0x00
+
+#define SAA7191_HUE_MIN			0x00
+#define SAA7191_HUE_MAX			0xff
+#define SAA7191_HUE_DEFAULT		0x80
+
+#define SAA7191_VTRC_MIN		0x00
+#define SAA7191_VTRC_MAX		0x01
+#define SAA7191_VTRC_DEFAULT		0x00
+
+#define SAA7191_FORCE_COLOUR_MIN	0x00
+#define SAA7191_FORCE_COLOUR_MAX	0x01
+#define SAA7191_FORCE_COLOUR_DEFAULT	0x00
+
+#define SAA7191_CHROMA_GAIN_MIN		0x00
+#define SAA7191_CHROMA_GAIN_MAX		0x03
+#define SAA7191_CHROMA_GAIN_DEFAULT	0x00
+
+#define SAA7191_LUMA_DELAY_MIN		-0x04
+#define SAA7191_LUMA_DELAY_MAX		0x03
+#define SAA7191_LUMA_DELAY_DEFAULT	0x01
+
+#define SAA7191_VNR_MIN			0x00
+#define SAA7191_VNR_MAX			0x03
+#define SAA7191_VNR_DEFAULT		0x00
+
+#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)
+
+#endif
diff --git a/drivers/media/i2c/smiapp-pll.c b/drivers/media/i2c/smiapp-pll.c
new file mode 100644
index 0000000..a577614
--- /dev/null
+++ b/drivers/media/i2c/smiapp-pll.c
@@ -0,0 +1,418 @@
+/*
+ * drivers/media/i2c/smiapp-pll.c
+ *
+ * Generic driver for SMIA/SMIA++ compliant camera modules
+ *
+ * Copyright (C) 2011--2012 Nokia Corporation
+ * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/gcd.h>
+#include <linux/lcm.h>
+#include <linux/module.h>
+
+#include "smiapp-pll.h"
+
+/* Return an even number or one. */
+static inline uint32_t clk_div_even(uint32_t a)
+{
+	return max_t(uint32_t, 1, a & ~1);
+}
+
+/* Return an even number or one. */
+static inline uint32_t clk_div_even_up(uint32_t a)
+{
+	if (a == 1)
+		return 1;
+	return (a + 1) & ~1;
+}
+
+static inline uint32_t is_one_or_even(uint32_t a)
+{
+	if (a == 1)
+		return 1;
+	if (a & 1)
+		return 0;
+
+	return 1;
+}
+
+static int bounds_check(struct device *dev, uint32_t val,
+			uint32_t min, uint32_t max, char *str)
+{
+	if (val >= min && val <= max)
+		return 0;
+
+	dev_warn(dev, "%s out of bounds: %d (%d--%d)\n", str, val, min, max);
+
+	return -EINVAL;
+}
+
+static void print_pll(struct device *dev, struct smiapp_pll *pll)
+{
+	dev_dbg(dev, "pre_pll_clk_div\t%d\n",  pll->pre_pll_clk_div);
+	dev_dbg(dev, "pll_multiplier \t%d\n",  pll->pll_multiplier);
+	if (pll->flags != SMIAPP_PLL_FLAG_NO_OP_CLOCKS) {
+		dev_dbg(dev, "op_sys_clk_div \t%d\n", pll->op_sys_clk_div);
+		dev_dbg(dev, "op_pix_clk_div \t%d\n", pll->op_pix_clk_div);
+	}
+	dev_dbg(dev, "vt_sys_clk_div \t%d\n",  pll->vt_sys_clk_div);
+	dev_dbg(dev, "vt_pix_clk_div \t%d\n",  pll->vt_pix_clk_div);
+
+	dev_dbg(dev, "ext_clk_freq_hz \t%d\n", pll->ext_clk_freq_hz);
+	dev_dbg(dev, "pll_ip_clk_freq_hz \t%d\n", pll->pll_ip_clk_freq_hz);
+	dev_dbg(dev, "pll_op_clk_freq_hz \t%d\n", pll->pll_op_clk_freq_hz);
+	if (pll->flags & SMIAPP_PLL_FLAG_NO_OP_CLOCKS) {
+		dev_dbg(dev, "op_sys_clk_freq_hz \t%d\n",
+			pll->op_sys_clk_freq_hz);
+		dev_dbg(dev, "op_pix_clk_freq_hz \t%d\n",
+			pll->op_pix_clk_freq_hz);
+	}
+	dev_dbg(dev, "vt_sys_clk_freq_hz \t%d\n", pll->vt_sys_clk_freq_hz);
+	dev_dbg(dev, "vt_pix_clk_freq_hz \t%d\n", pll->vt_pix_clk_freq_hz);
+}
+
+int smiapp_pll_calculate(struct device *dev, struct smiapp_pll_limits *limits,
+			 struct smiapp_pll *pll)
+{
+	uint32_t sys_div;
+	uint32_t best_pix_div = INT_MAX >> 1;
+	uint32_t vt_op_binning_div;
+	uint32_t lane_op_clock_ratio;
+	uint32_t mul, div;
+	uint32_t more_mul_min, more_mul_max;
+	uint32_t more_mul_factor;
+	uint32_t min_vt_div, max_vt_div, vt_div;
+	uint32_t min_sys_div, max_sys_div;
+	unsigned int i;
+	int rval;
+
+	if (pll->flags & SMIAPP_PLL_FLAG_OP_PIX_CLOCK_PER_LANE)
+		lane_op_clock_ratio = pll->lanes;
+	else
+		lane_op_clock_ratio = 1;
+	dev_dbg(dev, "lane_op_clock_ratio: %d\n", lane_op_clock_ratio);
+
+	dev_dbg(dev, "binning: %dx%d\n", pll->binning_horizontal,
+		pll->binning_vertical);
+
+	/* CSI transfers 2 bits per clock per lane; thus times 2 */
+	pll->pll_op_clk_freq_hz = pll->link_freq * 2
+		* (pll->lanes / lane_op_clock_ratio);
+
+	/* Figure out limits for pre-pll divider based on extclk */
+	dev_dbg(dev, "min / max pre_pll_clk_div: %d / %d\n",
+		limits->min_pre_pll_clk_div, limits->max_pre_pll_clk_div);
+	limits->max_pre_pll_clk_div =
+		min_t(uint16_t, limits->max_pre_pll_clk_div,
+		      clk_div_even(pll->ext_clk_freq_hz /
+				   limits->min_pll_ip_freq_hz));
+	limits->min_pre_pll_clk_div =
+		max_t(uint16_t, limits->min_pre_pll_clk_div,
+		      clk_div_even_up(
+			      DIV_ROUND_UP(pll->ext_clk_freq_hz,
+					   limits->max_pll_ip_freq_hz)));
+	dev_dbg(dev, "pre-pll check: min / max pre_pll_clk_div: %d / %d\n",
+		limits->min_pre_pll_clk_div, limits->max_pre_pll_clk_div);
+
+	i = gcd(pll->pll_op_clk_freq_hz, pll->ext_clk_freq_hz);
+	mul = div_u64(pll->pll_op_clk_freq_hz, i);
+	div = pll->ext_clk_freq_hz / i;
+	dev_dbg(dev, "mul %d / div %d\n", mul, div);
+
+	limits->min_pre_pll_clk_div =
+		max_t(uint16_t, limits->min_pre_pll_clk_div,
+		      clk_div_even_up(
+			      DIV_ROUND_UP(mul * pll->ext_clk_freq_hz,
+					   limits->max_pll_op_freq_hz)));
+	dev_dbg(dev, "pll_op check: min / max pre_pll_clk_div: %d / %d\n",
+		limits->min_pre_pll_clk_div, limits->max_pre_pll_clk_div);
+
+	if (limits->min_pre_pll_clk_div > limits->max_pre_pll_clk_div) {
+		dev_err(dev, "unable to compute pre_pll divisor\n");
+		return -EINVAL;
+	}
+
+	pll->pre_pll_clk_div = limits->min_pre_pll_clk_div;
+
+	/*
+	 * Get pre_pll_clk_div so that our pll_op_clk_freq_hz won't be
+	 * too high.
+	 */
+	dev_dbg(dev, "pre_pll_clk_div %d\n", pll->pre_pll_clk_div);
+
+	/* Don't go above max pll multiplier. */
+	more_mul_max = limits->max_pll_multiplier / mul;
+	dev_dbg(dev, "more_mul_max: max_pll_multiplier check: %d\n",
+		more_mul_max);
+	/* Don't go above max pll op frequency. */
+	more_mul_max =
+		min_t(int,
+		      more_mul_max,
+		      limits->max_pll_op_freq_hz
+		      / (pll->ext_clk_freq_hz / pll->pre_pll_clk_div * mul));
+	dev_dbg(dev, "more_mul_max: max_pll_op_freq_hz check: %d\n",
+		more_mul_max);
+	/* Don't go above the division capability of op sys clock divider. */
+	more_mul_max = min(more_mul_max,
+			   limits->max_op_sys_clk_div * pll->pre_pll_clk_div
+			   / div);
+	dev_dbg(dev, "more_mul_max: max_op_sys_clk_div check: %d\n",
+		more_mul_max);
+	/* Ensure we won't go above min_pll_multiplier. */
+	more_mul_max = min(more_mul_max,
+			   DIV_ROUND_UP(limits->max_pll_multiplier, mul));
+	dev_dbg(dev, "more_mul_max: min_pll_multiplier check: %d\n",
+		more_mul_max);
+
+	/* Ensure we won't go below min_pll_op_freq_hz. */
+	more_mul_min = DIV_ROUND_UP(limits->min_pll_op_freq_hz,
+				    pll->ext_clk_freq_hz / pll->pre_pll_clk_div
+				    * mul);
+	dev_dbg(dev, "more_mul_min: min_pll_op_freq_hz check: %d\n",
+		more_mul_min);
+	/* Ensure we won't go below min_pll_multiplier. */
+	more_mul_min = max(more_mul_min,
+			   DIV_ROUND_UP(limits->min_pll_multiplier, mul));
+	dev_dbg(dev, "more_mul_min: min_pll_multiplier check: %d\n",
+		more_mul_min);
+
+	if (more_mul_min > more_mul_max) {
+		dev_warn(dev,
+			 "unable to compute more_mul_min and more_mul_max");
+		return -EINVAL;
+	}
+
+	more_mul_factor = lcm(div, pll->pre_pll_clk_div) / div;
+	dev_dbg(dev, "more_mul_factor: %d\n", more_mul_factor);
+	more_mul_factor = lcm(more_mul_factor, limits->min_op_sys_clk_div);
+	dev_dbg(dev, "more_mul_factor: min_op_sys_clk_div: %d\n",
+		more_mul_factor);
+	i = roundup(more_mul_min, more_mul_factor);
+	if (!is_one_or_even(i))
+		i <<= 1;
+
+	dev_dbg(dev, "final more_mul: %d\n", i);
+	if (i > more_mul_max) {
+		dev_warn(dev, "final more_mul is bad, max %d", more_mul_max);
+		return -EINVAL;
+	}
+
+	pll->pll_multiplier = mul * i;
+	pll->op_sys_clk_div = div * i / pll->pre_pll_clk_div;
+	dev_dbg(dev, "op_sys_clk_div: %d\n", pll->op_sys_clk_div);
+
+	pll->pll_ip_clk_freq_hz = pll->ext_clk_freq_hz
+		/ pll->pre_pll_clk_div;
+
+	pll->pll_op_clk_freq_hz = pll->pll_ip_clk_freq_hz
+		* pll->pll_multiplier;
+
+	/* Derive pll_op_clk_freq_hz. */
+	pll->op_sys_clk_freq_hz =
+		pll->pll_op_clk_freq_hz / pll->op_sys_clk_div;
+
+	pll->op_pix_clk_div = pll->bits_per_pixel;
+	dev_dbg(dev, "op_pix_clk_div: %d\n", pll->op_pix_clk_div);
+
+	pll->op_pix_clk_freq_hz =
+		pll->op_sys_clk_freq_hz / pll->op_pix_clk_div;
+
+	/*
+	 * Some sensors perform analogue binning and some do this
+	 * digitally. The ones doing this digitally can be roughly be
+	 * found out using this formula. The ones doing this digitally
+	 * should run at higher clock rate, so smaller divisor is used
+	 * on video timing side.
+	 */
+	if (limits->min_line_length_pck_bin > limits->min_line_length_pck
+	    / pll->binning_horizontal)
+		vt_op_binning_div = pll->binning_horizontal;
+	else
+		vt_op_binning_div = 1;
+	dev_dbg(dev, "vt_op_binning_div: %d\n", vt_op_binning_div);
+
+	/*
+	 * Profile 2 supports vt_pix_clk_div E [4, 10]
+	 *
+	 * Horizontal binning can be used as a base for difference in
+	 * divisors. One must make sure that horizontal blanking is
+	 * enough to accommodate the CSI-2 sync codes.
+	 *
+	 * Take scaling factor into account as well.
+	 *
+	 * Find absolute limits for the factor of vt divider.
+	 */
+	dev_dbg(dev, "scale_m: %d\n", pll->scale_m);
+	min_vt_div = DIV_ROUND_UP(pll->op_pix_clk_div * pll->op_sys_clk_div
+				  * pll->scale_n,
+				  lane_op_clock_ratio * vt_op_binning_div
+				  * pll->scale_m);
+
+	/* Find smallest and biggest allowed vt divisor. */
+	dev_dbg(dev, "min_vt_div: %d\n", min_vt_div);
+	min_vt_div = max(min_vt_div,
+			 DIV_ROUND_UP(pll->pll_op_clk_freq_hz,
+				      limits->max_vt_pix_clk_freq_hz));
+	dev_dbg(dev, "min_vt_div: max_vt_pix_clk_freq_hz: %d\n",
+		min_vt_div);
+	min_vt_div = max_t(uint32_t, min_vt_div,
+			   limits->min_vt_pix_clk_div
+			   * limits->min_vt_sys_clk_div);
+	dev_dbg(dev, "min_vt_div: min_vt_clk_div: %d\n", min_vt_div);
+
+	max_vt_div = limits->max_vt_sys_clk_div * limits->max_vt_pix_clk_div;
+	dev_dbg(dev, "max_vt_div: %d\n", max_vt_div);
+	max_vt_div = min(max_vt_div,
+			 DIV_ROUND_UP(pll->pll_op_clk_freq_hz,
+				      limits->min_vt_pix_clk_freq_hz));
+	dev_dbg(dev, "max_vt_div: min_vt_pix_clk_freq_hz: %d\n",
+		max_vt_div);
+
+	/*
+	 * Find limitsits for sys_clk_div. Not all values are possible
+	 * with all values of pix_clk_div.
+	 */
+	min_sys_div = limits->min_vt_sys_clk_div;
+	dev_dbg(dev, "min_sys_div: %d\n", min_sys_div);
+	min_sys_div = max(min_sys_div,
+			  DIV_ROUND_UP(min_vt_div,
+				       limits->max_vt_pix_clk_div));
+	dev_dbg(dev, "min_sys_div: max_vt_pix_clk_div: %d\n", min_sys_div);
+	min_sys_div = max(min_sys_div,
+			  pll->pll_op_clk_freq_hz
+			  / limits->max_vt_sys_clk_freq_hz);
+	dev_dbg(dev, "min_sys_div: max_pll_op_clk_freq_hz: %d\n", min_sys_div);
+	min_sys_div = clk_div_even_up(min_sys_div);
+	dev_dbg(dev, "min_sys_div: one or even: %d\n", min_sys_div);
+
+	max_sys_div = limits->max_vt_sys_clk_div;
+	dev_dbg(dev, "max_sys_div: %d\n", max_sys_div);
+	max_sys_div = min(max_sys_div,
+			  DIV_ROUND_UP(max_vt_div,
+				       limits->min_vt_pix_clk_div));
+	dev_dbg(dev, "max_sys_div: min_vt_pix_clk_div: %d\n", max_sys_div);
+	max_sys_div = min(max_sys_div,
+			  DIV_ROUND_UP(pll->pll_op_clk_freq_hz,
+				       limits->min_vt_pix_clk_freq_hz));
+	dev_dbg(dev, "max_sys_div: min_vt_pix_clk_freq_hz: %d\n", max_sys_div);
+
+	/*
+	 * Find pix_div such that a legal pix_div * sys_div results
+	 * into a value which is not smaller than div, the desired
+	 * divisor.
+	 */
+	for (vt_div = min_vt_div; vt_div <= max_vt_div;
+	     vt_div += 2 - (vt_div & 1)) {
+		for (sys_div = min_sys_div;
+		     sys_div <= max_sys_div;
+		     sys_div += 2 - (sys_div & 1)) {
+			int pix_div = DIV_ROUND_UP(vt_div, sys_div);
+
+			if (pix_div < limits->min_vt_pix_clk_div
+			    || pix_div > limits->max_vt_pix_clk_div) {
+				dev_dbg(dev,
+					"pix_div %d too small or too big (%d--%d)\n",
+					pix_div,
+					limits->min_vt_pix_clk_div,
+					limits->max_vt_pix_clk_div);
+				continue;
+			}
+
+			/* Check if this one is better. */
+			if (pix_div * sys_div
+			    <= roundup(min_vt_div, best_pix_div))
+				best_pix_div = pix_div;
+		}
+		if (best_pix_div < INT_MAX >> 1)
+			break;
+	}
+
+	pll->vt_sys_clk_div = DIV_ROUND_UP(min_vt_div, best_pix_div);
+	pll->vt_pix_clk_div = best_pix_div;
+
+	pll->vt_sys_clk_freq_hz =
+		pll->pll_op_clk_freq_hz / pll->vt_sys_clk_div;
+	pll->vt_pix_clk_freq_hz =
+		pll->vt_sys_clk_freq_hz / pll->vt_pix_clk_div;
+
+	pll->pixel_rate_csi =
+		pll->op_pix_clk_freq_hz * lane_op_clock_ratio;
+
+	print_pll(dev, pll);
+
+	rval = bounds_check(dev, pll->pre_pll_clk_div,
+			    limits->min_pre_pll_clk_div,
+			    limits->max_pre_pll_clk_div, "pre_pll_clk_div");
+	if (!rval)
+		rval = bounds_check(
+			dev, pll->pll_ip_clk_freq_hz,
+			limits->min_pll_ip_freq_hz, limits->max_pll_ip_freq_hz,
+			"pll_ip_clk_freq_hz");
+	if (!rval)
+		rval = bounds_check(
+			dev, pll->pll_multiplier,
+			limits->min_pll_multiplier, limits->max_pll_multiplier,
+			"pll_multiplier");
+	if (!rval)
+		rval = bounds_check(
+			dev, pll->pll_op_clk_freq_hz,
+			limits->min_pll_op_freq_hz, limits->max_pll_op_freq_hz,
+			"pll_op_clk_freq_hz");
+	if (!rval)
+		rval = bounds_check(
+			dev, pll->op_sys_clk_div,
+			limits->min_op_sys_clk_div, limits->max_op_sys_clk_div,
+			"op_sys_clk_div");
+	if (!rval)
+		rval = bounds_check(
+			dev, pll->op_pix_clk_div,
+			limits->min_op_pix_clk_div, limits->max_op_pix_clk_div,
+			"op_pix_clk_div");
+	if (!rval)
+		rval = bounds_check(
+			dev, pll->op_sys_clk_freq_hz,
+			limits->min_op_sys_clk_freq_hz,
+			limits->max_op_sys_clk_freq_hz,
+			"op_sys_clk_freq_hz");
+	if (!rval)
+		rval = bounds_check(
+			dev, pll->op_pix_clk_freq_hz,
+			limits->min_op_pix_clk_freq_hz,
+			limits->max_op_pix_clk_freq_hz,
+			"op_pix_clk_freq_hz");
+	if (!rval)
+		rval = bounds_check(
+			dev, pll->vt_sys_clk_freq_hz,
+			limits->min_vt_sys_clk_freq_hz,
+			limits->max_vt_sys_clk_freq_hz,
+			"vt_sys_clk_freq_hz");
+	if (!rval)
+		rval = bounds_check(
+			dev, pll->vt_pix_clk_freq_hz,
+			limits->min_vt_pix_clk_freq_hz,
+			limits->max_vt_pix_clk_freq_hz,
+			"vt_pix_clk_freq_hz");
+
+	return rval;
+}
+EXPORT_SYMBOL_GPL(smiapp_pll_calculate);
+
+MODULE_AUTHOR("Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>");
+MODULE_DESCRIPTION("Generic SMIA/SMIA++ PLL calculator");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/i2c/smiapp-pll.h b/drivers/media/i2c/smiapp-pll.h
new file mode 100644
index 0000000..cb2d2db
--- /dev/null
+++ b/drivers/media/i2c/smiapp-pll.h
@@ -0,0 +1,103 @@
+/*
+ * drivers/media/i2c/smiapp-pll.h
+ *
+ * Generic driver for SMIA/SMIA++ compliant camera modules
+ *
+ * Copyright (C) 2012 Nokia Corporation
+ * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef SMIAPP_PLL_H
+#define SMIAPP_PLL_H
+
+#include <linux/device.h>
+
+struct smiapp_pll {
+	uint8_t lanes;
+	uint8_t binning_horizontal;
+	uint8_t binning_vertical;
+	uint8_t scale_m;
+	uint8_t scale_n;
+	uint8_t bits_per_pixel;
+	uint16_t flags;
+	uint32_t link_freq;
+
+	uint16_t pre_pll_clk_div;
+	uint16_t pll_multiplier;
+	uint16_t op_sys_clk_div;
+	uint16_t op_pix_clk_div;
+	uint16_t vt_sys_clk_div;
+	uint16_t vt_pix_clk_div;
+
+	uint32_t ext_clk_freq_hz;
+	uint32_t pll_ip_clk_freq_hz;
+	uint32_t pll_op_clk_freq_hz;
+	uint32_t op_sys_clk_freq_hz;
+	uint32_t op_pix_clk_freq_hz;
+	uint32_t vt_sys_clk_freq_hz;
+	uint32_t vt_pix_clk_freq_hz;
+
+	uint32_t pixel_rate_csi;
+};
+
+struct smiapp_pll_limits {
+	/* Strict PLL limits */
+	uint32_t min_ext_clk_freq_hz;
+	uint32_t max_ext_clk_freq_hz;
+	uint16_t min_pre_pll_clk_div;
+	uint16_t max_pre_pll_clk_div;
+	uint32_t min_pll_ip_freq_hz;
+	uint32_t max_pll_ip_freq_hz;
+	uint16_t min_pll_multiplier;
+	uint16_t max_pll_multiplier;
+	uint32_t min_pll_op_freq_hz;
+	uint32_t max_pll_op_freq_hz;
+
+	uint16_t min_vt_sys_clk_div;
+	uint16_t max_vt_sys_clk_div;
+	uint32_t min_vt_sys_clk_freq_hz;
+	uint32_t max_vt_sys_clk_freq_hz;
+	uint16_t min_vt_pix_clk_div;
+	uint16_t max_vt_pix_clk_div;
+	uint32_t min_vt_pix_clk_freq_hz;
+	uint32_t max_vt_pix_clk_freq_hz;
+
+	uint16_t min_op_sys_clk_div;
+	uint16_t max_op_sys_clk_div;
+	uint32_t min_op_sys_clk_freq_hz;
+	uint32_t max_op_sys_clk_freq_hz;
+	uint16_t min_op_pix_clk_div;
+	uint16_t max_op_pix_clk_div;
+	uint32_t min_op_pix_clk_freq_hz;
+	uint32_t max_op_pix_clk_freq_hz;
+
+	/* Other relevant limits */
+	uint32_t min_line_length_pck_bin;
+	uint32_t min_line_length_pck;
+};
+
+/* op pix clock is for all lanes in total normally */
+#define SMIAPP_PLL_FLAG_OP_PIX_CLOCK_PER_LANE			(1 << 0)
+#define SMIAPP_PLL_FLAG_NO_OP_CLOCKS				(1 << 1)
+
+struct device;
+
+int smiapp_pll_calculate(struct device *dev, struct smiapp_pll_limits *limits,
+			 struct smiapp_pll *pll);
+
+#endif /* SMIAPP_PLL_H */
diff --git a/drivers/media/i2c/smiapp/Kconfig b/drivers/media/i2c/smiapp/Kconfig
new file mode 100644
index 0000000..3149cda
--- /dev/null
+++ b/drivers/media/i2c/smiapp/Kconfig
@@ -0,0 +1,7 @@
+config VIDEO_SMIAPP
+	tristate "SMIA++/SMIA sensor support"
+	depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API && HAVE_CLK
+	depends on MEDIA_CAMERA_SUPPORT
+	select VIDEO_SMIAPP_PLL
+	---help---
+	  This is a generic driver for SMIA++/SMIA camera modules.
diff --git a/drivers/media/i2c/smiapp/Makefile b/drivers/media/i2c/smiapp/Makefile
new file mode 100644
index 0000000..f45a003
--- /dev/null
+++ b/drivers/media/i2c/smiapp/Makefile
@@ -0,0 +1,5 @@
+smiapp-objs			+= smiapp-core.o smiapp-regs.o \
+				   smiapp-quirk.o smiapp-limits.o
+obj-$(CONFIG_VIDEO_SMIAPP)	+= smiapp.o
+
+ccflags-y += -Idrivers/media/i2c
diff --git a/drivers/media/i2c/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c
new file mode 100644
index 0000000..1cf914d
--- /dev/null
+++ b/drivers/media/i2c/smiapp/smiapp-core.c
@@ -0,0 +1,2895 @@
+/*
+ * drivers/media/i2c/smiapp/smiapp-core.c
+ *
+ * Generic driver for SMIA/SMIA++ compliant camera modules
+ *
+ * Copyright (C) 2010--2012 Nokia Corporation
+ * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ *
+ * Based on smiapp driver by Vimarsh Zutshi
+ * Based on jt8ev1.c by Vimarsh Zutshi
+ * Based on smia-sensor.c by Tuukka Toivonen <tuukkat76@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.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/gpio.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/regulator/consumer.h>
+#include <linux/v4l2-mediabus.h>
+#include <media/v4l2-device.h>
+
+#include "smiapp.h"
+
+#define SMIAPP_ALIGN_DIM(dim, flags)	\
+	((flags) & V4L2_SEL_FLAG_GE	\
+	 ? ALIGN((dim), 2)		\
+	 : (dim) & ~1)
+
+/*
+ * smiapp_module_idents - supported camera modules
+ */
+static const struct smiapp_module_ident smiapp_module_idents[] = {
+	SMIAPP_IDENT_L(0x01, 0x022b, -1, "vs6555"),
+	SMIAPP_IDENT_L(0x01, 0x022e, -1, "vw6558"),
+	SMIAPP_IDENT_L(0x07, 0x7698, -1, "ovm7698"),
+	SMIAPP_IDENT_L(0x0b, 0x4242, -1, "smiapp-003"),
+	SMIAPP_IDENT_L(0x0c, 0x208a, -1, "tcm8330md"),
+	SMIAPP_IDENT_LQ(0x0c, 0x2134, -1, "tcm8500md", &smiapp_tcm8500md_quirk),
+	SMIAPP_IDENT_L(0x0c, 0x213e, -1, "et8en2"),
+	SMIAPP_IDENT_L(0x0c, 0x2184, -1, "tcm8580md"),
+	SMIAPP_IDENT_LQ(0x0c, 0x560f, -1, "jt8ew9", &smiapp_jt8ew9_quirk),
+	SMIAPP_IDENT_LQ(0x10, 0x4141, -1, "jt8ev1", &smiapp_jt8ev1_quirk),
+	SMIAPP_IDENT_LQ(0x10, 0x4241, -1, "imx125es", &smiapp_imx125es_quirk),
+};
+
+/*
+ *
+ * Dynamic Capability Identification
+ *
+ */
+
+static int smiapp_read_frame_fmt(struct smiapp_sensor *sensor)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
+	u32 fmt_model_type, fmt_model_subtype, ncol_desc, nrow_desc;
+	unsigned int i;
+	int rval;
+	int line_count = 0;
+	int embedded_start = -1, embedded_end = -1;
+	int image_start = 0;
+
+	rval = smiapp_read(sensor, SMIAPP_REG_U8_FRAME_FORMAT_MODEL_TYPE,
+			   &fmt_model_type);
+	if (rval)
+		return rval;
+
+	rval = smiapp_read(sensor, SMIAPP_REG_U8_FRAME_FORMAT_MODEL_SUBTYPE,
+			   &fmt_model_subtype);
+	if (rval)
+		return rval;
+
+	ncol_desc = (fmt_model_subtype
+		     & SMIAPP_FRAME_FORMAT_MODEL_SUBTYPE_NCOLS_MASK)
+		>> SMIAPP_FRAME_FORMAT_MODEL_SUBTYPE_NCOLS_SHIFT;
+	nrow_desc = fmt_model_subtype
+		& SMIAPP_FRAME_FORMAT_MODEL_SUBTYPE_NROWS_MASK;
+
+	dev_dbg(&client->dev, "format_model_type %s\n",
+		fmt_model_type == SMIAPP_FRAME_FORMAT_MODEL_TYPE_2BYTE
+		? "2 byte" :
+		fmt_model_type == SMIAPP_FRAME_FORMAT_MODEL_TYPE_4BYTE
+		? "4 byte" : "is simply bad");
+
+	for (i = 0; i < ncol_desc + nrow_desc; i++) {
+		u32 desc;
+		u32 pixelcode;
+		u32 pixels;
+		char *which;
+		char *what;
+
+		if (fmt_model_type == SMIAPP_FRAME_FORMAT_MODEL_TYPE_2BYTE) {
+			rval = smiapp_read(
+				sensor,
+				SMIAPP_REG_U16_FRAME_FORMAT_DESCRIPTOR_2(i),
+				&desc);
+			if (rval)
+				return rval;
+
+			pixelcode =
+				(desc
+				 & SMIAPP_FRAME_FORMAT_DESC_2_PIXELCODE_MASK)
+				>> SMIAPP_FRAME_FORMAT_DESC_2_PIXELCODE_SHIFT;
+			pixels = desc & SMIAPP_FRAME_FORMAT_DESC_2_PIXELS_MASK;
+		} else if (fmt_model_type
+			   == SMIAPP_FRAME_FORMAT_MODEL_TYPE_4BYTE) {
+			rval = smiapp_read(
+				sensor,
+				SMIAPP_REG_U32_FRAME_FORMAT_DESCRIPTOR_4(i),
+				&desc);
+			if (rval)
+				return rval;
+
+			pixelcode =
+				(desc
+				 & SMIAPP_FRAME_FORMAT_DESC_4_PIXELCODE_MASK)
+				>> SMIAPP_FRAME_FORMAT_DESC_4_PIXELCODE_SHIFT;
+			pixels = desc & SMIAPP_FRAME_FORMAT_DESC_4_PIXELS_MASK;
+		} else {
+			dev_dbg(&client->dev,
+				"invalid frame format model type %d\n",
+				fmt_model_type);
+			return -EINVAL;
+		}
+
+		if (i < ncol_desc)
+			which = "columns";
+		else
+			which = "rows";
+
+		switch (pixelcode) {
+		case SMIAPP_FRAME_FORMAT_DESC_PIXELCODE_EMBEDDED:
+			what = "embedded";
+			break;
+		case SMIAPP_FRAME_FORMAT_DESC_PIXELCODE_DUMMY:
+			what = "dummy";
+			break;
+		case SMIAPP_FRAME_FORMAT_DESC_PIXELCODE_BLACK:
+			what = "black";
+			break;
+		case SMIAPP_FRAME_FORMAT_DESC_PIXELCODE_DARK:
+			what = "dark";
+			break;
+		case SMIAPP_FRAME_FORMAT_DESC_PIXELCODE_VISIBLE:
+			what = "visible";
+			break;
+		default:
+			what = "invalid";
+			dev_dbg(&client->dev, "pixelcode %d\n", pixelcode);
+			break;
+		}
+
+		dev_dbg(&client->dev, "%s pixels: %d %s\n",
+			what, pixels, which);
+
+		if (i < ncol_desc)
+			continue;
+
+		/* Handle row descriptors */
+		if (pixelcode
+		    == SMIAPP_FRAME_FORMAT_DESC_PIXELCODE_EMBEDDED) {
+			embedded_start = line_count;
+		} else {
+			if (pixelcode == SMIAPP_FRAME_FORMAT_DESC_PIXELCODE_VISIBLE
+			    || pixels >= sensor->limits[SMIAPP_LIMIT_MIN_FRAME_LENGTH_LINES] / 2)
+				image_start = line_count;
+			if (embedded_start != -1 && embedded_end == -1)
+				embedded_end = line_count;
+		}
+		line_count += pixels;
+	}
+
+	if (embedded_start == -1 || embedded_end == -1) {
+		embedded_start = 0;
+		embedded_end = 0;
+	}
+
+	dev_dbg(&client->dev, "embedded data from lines %d to %d\n",
+		embedded_start, embedded_end);
+	dev_dbg(&client->dev, "image data starts at line %d\n", image_start);
+
+	return 0;
+}
+
+static int smiapp_pll_configure(struct smiapp_sensor *sensor)
+{
+	struct smiapp_pll *pll = &sensor->pll;
+	int rval;
+
+	rval = smiapp_write(
+		sensor, SMIAPP_REG_U16_VT_PIX_CLK_DIV, pll->vt_pix_clk_div);
+	if (rval < 0)
+		return rval;
+
+	rval = smiapp_write(
+		sensor, SMIAPP_REG_U16_VT_SYS_CLK_DIV, pll->vt_sys_clk_div);
+	if (rval < 0)
+		return rval;
+
+	rval = smiapp_write(
+		sensor, SMIAPP_REG_U16_PRE_PLL_CLK_DIV, pll->pre_pll_clk_div);
+	if (rval < 0)
+		return rval;
+
+	rval = smiapp_write(
+		sensor, SMIAPP_REG_U16_PLL_MULTIPLIER, pll->pll_multiplier);
+	if (rval < 0)
+		return rval;
+
+	/* Lane op clock ratio does not apply here. */
+	rval = smiapp_write(
+		sensor, SMIAPP_REG_U32_REQUESTED_LINK_BIT_RATE_MBPS,
+		DIV_ROUND_UP(pll->op_sys_clk_freq_hz, 1000000 / 256 / 256));
+	if (rval < 0 || sensor->minfo.smiapp_profile == SMIAPP_PROFILE_0)
+		return rval;
+
+	rval = smiapp_write(
+		sensor, SMIAPP_REG_U16_OP_PIX_CLK_DIV, pll->op_pix_clk_div);
+	if (rval < 0)
+		return rval;
+
+	return smiapp_write(
+		sensor, SMIAPP_REG_U16_OP_SYS_CLK_DIV, pll->op_sys_clk_div);
+}
+
+static int smiapp_pll_update(struct smiapp_sensor *sensor)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
+	struct smiapp_pll_limits lim = {
+		.min_pre_pll_clk_div = sensor->limits[SMIAPP_LIMIT_MIN_PRE_PLL_CLK_DIV],
+		.max_pre_pll_clk_div = sensor->limits[SMIAPP_LIMIT_MAX_PRE_PLL_CLK_DIV],
+		.min_pll_ip_freq_hz = sensor->limits[SMIAPP_LIMIT_MIN_PLL_IP_FREQ_HZ],
+		.max_pll_ip_freq_hz = sensor->limits[SMIAPP_LIMIT_MAX_PLL_IP_FREQ_HZ],
+		.min_pll_multiplier = sensor->limits[SMIAPP_LIMIT_MIN_PLL_MULTIPLIER],
+		.max_pll_multiplier = sensor->limits[SMIAPP_LIMIT_MAX_PLL_MULTIPLIER],
+		.min_pll_op_freq_hz = sensor->limits[SMIAPP_LIMIT_MIN_PLL_OP_FREQ_HZ],
+		.max_pll_op_freq_hz = sensor->limits[SMIAPP_LIMIT_MAX_PLL_OP_FREQ_HZ],
+
+		.min_op_sys_clk_div = sensor->limits[SMIAPP_LIMIT_MIN_OP_SYS_CLK_DIV],
+		.max_op_sys_clk_div = sensor->limits[SMIAPP_LIMIT_MAX_OP_SYS_CLK_DIV],
+		.min_op_pix_clk_div = sensor->limits[SMIAPP_LIMIT_MIN_OP_PIX_CLK_DIV],
+		.max_op_pix_clk_div = sensor->limits[SMIAPP_LIMIT_MAX_OP_PIX_CLK_DIV],
+		.min_op_sys_clk_freq_hz = sensor->limits[SMIAPP_LIMIT_MIN_OP_SYS_CLK_FREQ_HZ],
+		.max_op_sys_clk_freq_hz = sensor->limits[SMIAPP_LIMIT_MAX_OP_SYS_CLK_FREQ_HZ],
+		.min_op_pix_clk_freq_hz = sensor->limits[SMIAPP_LIMIT_MIN_OP_PIX_CLK_FREQ_HZ],
+		.max_op_pix_clk_freq_hz = sensor->limits[SMIAPP_LIMIT_MAX_OP_PIX_CLK_FREQ_HZ],
+
+		.min_vt_sys_clk_div = sensor->limits[SMIAPP_LIMIT_MIN_VT_SYS_CLK_DIV],
+		.max_vt_sys_clk_div = sensor->limits[SMIAPP_LIMIT_MAX_VT_SYS_CLK_DIV],
+		.min_vt_pix_clk_div = sensor->limits[SMIAPP_LIMIT_MIN_VT_PIX_CLK_DIV],
+		.max_vt_pix_clk_div = sensor->limits[SMIAPP_LIMIT_MAX_VT_PIX_CLK_DIV],
+		.min_vt_sys_clk_freq_hz = sensor->limits[SMIAPP_LIMIT_MIN_VT_SYS_CLK_FREQ_HZ],
+		.max_vt_sys_clk_freq_hz = sensor->limits[SMIAPP_LIMIT_MAX_VT_SYS_CLK_FREQ_HZ],
+		.min_vt_pix_clk_freq_hz = sensor->limits[SMIAPP_LIMIT_MIN_VT_PIX_CLK_FREQ_HZ],
+		.max_vt_pix_clk_freq_hz = sensor->limits[SMIAPP_LIMIT_MAX_VT_PIX_CLK_FREQ_HZ],
+
+		.min_line_length_pck_bin = sensor->limits[SMIAPP_LIMIT_MIN_LINE_LENGTH_PCK_BIN],
+		.min_line_length_pck = sensor->limits[SMIAPP_LIMIT_MIN_LINE_LENGTH_PCK],
+	};
+	struct smiapp_pll *pll = &sensor->pll;
+	int rval;
+
+	memset(&sensor->pll, 0, sizeof(sensor->pll));
+
+	pll->lanes = sensor->platform_data->lanes;
+	pll->ext_clk_freq_hz = sensor->platform_data->ext_clk;
+
+	if (sensor->minfo.smiapp_profile == SMIAPP_PROFILE_0) {
+		/*
+		 * Fill in operational clock divisors limits from the
+		 * video timing ones. On profile 0 sensors the
+		 * requirements regarding them are essentially the
+		 * same as on VT ones.
+		 */
+		lim.min_op_sys_clk_div = lim.min_vt_sys_clk_div;
+		lim.max_op_sys_clk_div = lim.max_vt_sys_clk_div;
+		lim.min_op_pix_clk_div = lim.min_vt_pix_clk_div;
+		lim.max_op_pix_clk_div = lim.max_vt_pix_clk_div;
+		lim.min_op_sys_clk_freq_hz = lim.min_vt_sys_clk_freq_hz;
+		lim.max_op_sys_clk_freq_hz = lim.max_vt_sys_clk_freq_hz;
+		lim.min_op_pix_clk_freq_hz = lim.min_vt_pix_clk_freq_hz;
+		lim.max_op_pix_clk_freq_hz = lim.max_vt_pix_clk_freq_hz;
+		/* Profile 0 sensors have no separate OP clock branch. */
+		pll->flags |= SMIAPP_PLL_FLAG_NO_OP_CLOCKS;
+	}
+
+	if (smiapp_needs_quirk(sensor,
+			       SMIAPP_QUIRK_FLAG_OP_PIX_CLOCK_PER_LANE))
+		pll->flags |= SMIAPP_PLL_FLAG_OP_PIX_CLOCK_PER_LANE;
+
+	pll->binning_horizontal = sensor->binning_horizontal;
+	pll->binning_vertical = sensor->binning_vertical;
+	pll->link_freq =
+		sensor->link_freq->qmenu_int[sensor->link_freq->val];
+	pll->scale_m = sensor->scale_m;
+	pll->scale_n = sensor->limits[SMIAPP_LIMIT_SCALER_N_MIN];
+	pll->bits_per_pixel = sensor->csi_format->compressed;
+
+	rval = smiapp_pll_calculate(&client->dev, &lim, pll);
+	if (rval < 0)
+		return rval;
+
+	sensor->pixel_rate_parray->cur.val64 = pll->vt_pix_clk_freq_hz;
+	sensor->pixel_rate_csi->cur.val64 = pll->pixel_rate_csi;
+
+	return 0;
+}
+
+
+/*
+ *
+ * V4L2 Controls handling
+ *
+ */
+
+static void __smiapp_update_exposure_limits(struct smiapp_sensor *sensor)
+{
+	struct v4l2_ctrl *ctrl = sensor->exposure;
+	int max;
+
+	max = sensor->pixel_array->crop[SMIAPP_PA_PAD_SRC].height
+		+ sensor->vblank->val
+		- sensor->limits[SMIAPP_LIMIT_COARSE_INTEGRATION_TIME_MAX_MARGIN];
+
+	ctrl->maximum = max;
+	if (ctrl->default_value > max)
+		ctrl->default_value = max;
+	if (ctrl->val > max)
+		ctrl->val = max;
+	if (ctrl->cur.val > max)
+		ctrl->cur.val = max;
+}
+
+/*
+ * Order matters.
+ *
+ * 1. Bits-per-pixel, descending.
+ * 2. Bits-per-pixel compressed, descending.
+ * 3. Pixel order, same as in pixel_order_str. Formats for all four pixel
+ *    orders must be defined.
+ */
+static const struct smiapp_csi_data_format smiapp_csi_data_formats[] = {
+	{ V4L2_MBUS_FMT_SGRBG12_1X12, 12, 12, SMIAPP_PIXEL_ORDER_GRBG, },
+	{ V4L2_MBUS_FMT_SRGGB12_1X12, 12, 12, SMIAPP_PIXEL_ORDER_RGGB, },
+	{ V4L2_MBUS_FMT_SBGGR12_1X12, 12, 12, SMIAPP_PIXEL_ORDER_BGGR, },
+	{ V4L2_MBUS_FMT_SGBRG12_1X12, 12, 12, SMIAPP_PIXEL_ORDER_GBRG, },
+	{ V4L2_MBUS_FMT_SGRBG10_1X10, 10, 10, SMIAPP_PIXEL_ORDER_GRBG, },
+	{ V4L2_MBUS_FMT_SRGGB10_1X10, 10, 10, SMIAPP_PIXEL_ORDER_RGGB, },
+	{ V4L2_MBUS_FMT_SBGGR10_1X10, 10, 10, SMIAPP_PIXEL_ORDER_BGGR, },
+	{ V4L2_MBUS_FMT_SGBRG10_1X10, 10, 10, SMIAPP_PIXEL_ORDER_GBRG, },
+	{ V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8, 10, 8, SMIAPP_PIXEL_ORDER_GRBG, },
+	{ V4L2_MBUS_FMT_SRGGB10_DPCM8_1X8, 10, 8, SMIAPP_PIXEL_ORDER_RGGB, },
+	{ V4L2_MBUS_FMT_SBGGR10_DPCM8_1X8, 10, 8, SMIAPP_PIXEL_ORDER_BGGR, },
+	{ V4L2_MBUS_FMT_SGBRG10_DPCM8_1X8, 10, 8, SMIAPP_PIXEL_ORDER_GBRG, },
+	{ V4L2_MBUS_FMT_SGRBG8_1X8, 8, 8, SMIAPP_PIXEL_ORDER_GRBG, },
+	{ V4L2_MBUS_FMT_SRGGB8_1X8, 8, 8, SMIAPP_PIXEL_ORDER_RGGB, },
+	{ V4L2_MBUS_FMT_SBGGR8_1X8, 8, 8, SMIAPP_PIXEL_ORDER_BGGR, },
+	{ V4L2_MBUS_FMT_SGBRG8_1X8, 8, 8, SMIAPP_PIXEL_ORDER_GBRG, },
+};
+
+const char *pixel_order_str[] = { "GRBG", "RGGB", "BGGR", "GBRG" };
+
+#define to_csi_format_idx(fmt) (((unsigned long)(fmt)			\
+				 - (unsigned long)smiapp_csi_data_formats) \
+				/ sizeof(*smiapp_csi_data_formats))
+
+static u32 smiapp_pixel_order(struct smiapp_sensor *sensor)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
+	int flip = 0;
+
+	if (sensor->hflip) {
+		if (sensor->hflip->val)
+			flip |= SMIAPP_IMAGE_ORIENTATION_HFLIP;
+
+		if (sensor->vflip->val)
+			flip |= SMIAPP_IMAGE_ORIENTATION_VFLIP;
+	}
+
+	flip ^= sensor->hvflip_inv_mask;
+
+	dev_dbg(&client->dev, "flip %d\n", flip);
+	return sensor->default_pixel_order ^ flip;
+}
+
+static void smiapp_update_mbus_formats(struct smiapp_sensor *sensor)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
+	unsigned int csi_format_idx =
+		to_csi_format_idx(sensor->csi_format) & ~3;
+	unsigned int internal_csi_format_idx =
+		to_csi_format_idx(sensor->internal_csi_format) & ~3;
+	unsigned int pixel_order = smiapp_pixel_order(sensor);
+
+	sensor->mbus_frame_fmts =
+		sensor->default_mbus_frame_fmts << pixel_order;
+	sensor->csi_format =
+		&smiapp_csi_data_formats[csi_format_idx + pixel_order];
+	sensor->internal_csi_format =
+		&smiapp_csi_data_formats[internal_csi_format_idx
+					 + pixel_order];
+
+	BUG_ON(max(internal_csi_format_idx, csi_format_idx) + pixel_order
+	       >= ARRAY_SIZE(smiapp_csi_data_formats));
+	BUG_ON(min(internal_csi_format_idx, csi_format_idx) < 0);
+
+	dev_dbg(&client->dev, "new pixel order %s\n",
+		pixel_order_str[pixel_order]);
+}
+
+static int smiapp_set_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct smiapp_sensor *sensor =
+		container_of(ctrl->handler, struct smiapp_subdev, ctrl_handler)
+			->sensor;
+	u32 orient = 0;
+	int exposure;
+	int rval;
+
+	switch (ctrl->id) {
+	case V4L2_CID_ANALOGUE_GAIN:
+		return smiapp_write(
+			sensor,
+			SMIAPP_REG_U16_ANALOGUE_GAIN_CODE_GLOBAL, ctrl->val);
+
+	case V4L2_CID_EXPOSURE:
+		return smiapp_write(
+			sensor,
+			SMIAPP_REG_U16_COARSE_INTEGRATION_TIME, ctrl->val);
+
+	case V4L2_CID_HFLIP:
+	case V4L2_CID_VFLIP:
+		if (sensor->streaming)
+			return -EBUSY;
+
+		if (sensor->hflip->val)
+			orient |= SMIAPP_IMAGE_ORIENTATION_HFLIP;
+
+		if (sensor->vflip->val)
+			orient |= SMIAPP_IMAGE_ORIENTATION_VFLIP;
+
+		orient ^= sensor->hvflip_inv_mask;
+		rval = smiapp_write(sensor,
+				    SMIAPP_REG_U8_IMAGE_ORIENTATION,
+				    orient);
+		if (rval < 0)
+			return rval;
+
+		smiapp_update_mbus_formats(sensor);
+
+		return 0;
+
+	case V4L2_CID_VBLANK:
+		exposure = sensor->exposure->val;
+
+		__smiapp_update_exposure_limits(sensor);
+
+		if (exposure > sensor->exposure->maximum) {
+			sensor->exposure->val =
+				sensor->exposure->maximum;
+			rval = smiapp_set_ctrl(
+				sensor->exposure);
+			if (rval < 0)
+				return rval;
+		}
+
+		return smiapp_write(
+			sensor, SMIAPP_REG_U16_FRAME_LENGTH_LINES,
+			sensor->pixel_array->crop[SMIAPP_PA_PAD_SRC].height
+			+ ctrl->val);
+
+	case V4L2_CID_HBLANK:
+		return smiapp_write(
+			sensor, SMIAPP_REG_U16_LINE_LENGTH_PCK,
+			sensor->pixel_array->crop[SMIAPP_PA_PAD_SRC].width
+			+ ctrl->val);
+
+	case V4L2_CID_LINK_FREQ:
+		if (sensor->streaming)
+			return -EBUSY;
+
+		return smiapp_pll_update(sensor);
+
+	default:
+		return -EINVAL;
+	}
+}
+
+static const struct v4l2_ctrl_ops smiapp_ctrl_ops = {
+	.s_ctrl = smiapp_set_ctrl,
+};
+
+static int smiapp_init_controls(struct smiapp_sensor *sensor)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
+	unsigned int max;
+	int rval;
+
+	rval = v4l2_ctrl_handler_init(&sensor->pixel_array->ctrl_handler, 7);
+	if (rval)
+		return rval;
+	sensor->pixel_array->ctrl_handler.lock = &sensor->mutex;
+
+	sensor->analog_gain = v4l2_ctrl_new_std(
+		&sensor->pixel_array->ctrl_handler, &smiapp_ctrl_ops,
+		V4L2_CID_ANALOGUE_GAIN,
+		sensor->limits[SMIAPP_LIMIT_ANALOGUE_GAIN_CODE_MIN],
+		sensor->limits[SMIAPP_LIMIT_ANALOGUE_GAIN_CODE_MAX],
+		max(sensor->limits[SMIAPP_LIMIT_ANALOGUE_GAIN_CODE_STEP], 1U),
+		sensor->limits[SMIAPP_LIMIT_ANALOGUE_GAIN_CODE_MIN]);
+
+	/* Exposure limits will be updated soon, use just something here. */
+	sensor->exposure = v4l2_ctrl_new_std(
+		&sensor->pixel_array->ctrl_handler, &smiapp_ctrl_ops,
+		V4L2_CID_EXPOSURE, 0, 0, 1, 0);
+
+	sensor->hflip = v4l2_ctrl_new_std(
+		&sensor->pixel_array->ctrl_handler, &smiapp_ctrl_ops,
+		V4L2_CID_HFLIP, 0, 1, 1, 0);
+	sensor->vflip = v4l2_ctrl_new_std(
+		&sensor->pixel_array->ctrl_handler, &smiapp_ctrl_ops,
+		V4L2_CID_VFLIP, 0, 1, 1, 0);
+
+	sensor->vblank = v4l2_ctrl_new_std(
+		&sensor->pixel_array->ctrl_handler, &smiapp_ctrl_ops,
+		V4L2_CID_VBLANK, 0, 1, 1, 0);
+
+	if (sensor->vblank)
+		sensor->vblank->flags |= V4L2_CTRL_FLAG_UPDATE;
+
+	sensor->hblank = v4l2_ctrl_new_std(
+		&sensor->pixel_array->ctrl_handler, &smiapp_ctrl_ops,
+		V4L2_CID_HBLANK, 0, 1, 1, 0);
+
+	if (sensor->hblank)
+		sensor->hblank->flags |= V4L2_CTRL_FLAG_UPDATE;
+
+	sensor->pixel_rate_parray = v4l2_ctrl_new_std(
+		&sensor->pixel_array->ctrl_handler, &smiapp_ctrl_ops,
+		V4L2_CID_PIXEL_RATE, 0, 0, 1, 0);
+
+	if (sensor->pixel_array->ctrl_handler.error) {
+		dev_err(&client->dev,
+			"pixel array controls initialization failed (%d)\n",
+			sensor->pixel_array->ctrl_handler.error);
+		rval = sensor->pixel_array->ctrl_handler.error;
+		goto error;
+	}
+
+	sensor->pixel_array->sd.ctrl_handler =
+		&sensor->pixel_array->ctrl_handler;
+
+	v4l2_ctrl_cluster(2, &sensor->hflip);
+
+	rval = v4l2_ctrl_handler_init(&sensor->src->ctrl_handler, 0);
+	if (rval)
+		goto error;
+	sensor->src->ctrl_handler.lock = &sensor->mutex;
+
+	for (max = 0; sensor->platform_data->op_sys_clock[max + 1]; max++);
+
+	sensor->link_freq = v4l2_ctrl_new_int_menu(
+		&sensor->src->ctrl_handler, &smiapp_ctrl_ops,
+		V4L2_CID_LINK_FREQ, max, 0,
+		sensor->platform_data->op_sys_clock);
+
+	sensor->pixel_rate_csi = v4l2_ctrl_new_std(
+		&sensor->src->ctrl_handler, &smiapp_ctrl_ops,
+		V4L2_CID_PIXEL_RATE, 0, 0, 1, 0);
+
+	if (sensor->src->ctrl_handler.error) {
+		dev_err(&client->dev,
+			"src controls initialization failed (%d)\n",
+			sensor->src->ctrl_handler.error);
+		rval = sensor->src->ctrl_handler.error;
+		goto error;
+	}
+
+	sensor->src->sd.ctrl_handler =
+		&sensor->src->ctrl_handler;
+
+	return 0;
+
+error:
+	v4l2_ctrl_handler_free(&sensor->pixel_array->ctrl_handler);
+	v4l2_ctrl_handler_free(&sensor->src->ctrl_handler);
+
+	return rval;
+}
+
+static void smiapp_free_controls(struct smiapp_sensor *sensor)
+{
+	unsigned int i;
+
+	for (i = 0; i < sensor->ssds_used; i++)
+		v4l2_ctrl_handler_free(&sensor->ssds[i].ctrl_handler);
+}
+
+static int smiapp_get_limits(struct smiapp_sensor *sensor, int const *limit,
+			     unsigned int n)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
+	unsigned int i;
+	u32 val;
+	int rval;
+
+	for (i = 0; i < n; i++) {
+		rval = smiapp_read(
+			sensor, smiapp_reg_limits[limit[i]].addr, &val);
+		if (rval)
+			return rval;
+		sensor->limits[limit[i]] = val;
+		dev_dbg(&client->dev, "0x%8.8x \"%s\" = %d, 0x%x\n",
+			smiapp_reg_limits[limit[i]].addr,
+			smiapp_reg_limits[limit[i]].what, val, val);
+	}
+
+	return 0;
+}
+
+static int smiapp_get_all_limits(struct smiapp_sensor *sensor)
+{
+	unsigned int i;
+	int rval;
+
+	for (i = 0; i < SMIAPP_LIMIT_LAST; i++) {
+		rval = smiapp_get_limits(sensor, &i, 1);
+		if (rval < 0)
+			return rval;
+	}
+
+	if (sensor->limits[SMIAPP_LIMIT_SCALER_N_MIN] == 0)
+		smiapp_replace_limit(sensor, SMIAPP_LIMIT_SCALER_N_MIN, 16);
+
+	return 0;
+}
+
+static int smiapp_get_limits_binning(struct smiapp_sensor *sensor)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
+	static u32 const limits[] = {
+		SMIAPP_LIMIT_MIN_FRAME_LENGTH_LINES_BIN,
+		SMIAPP_LIMIT_MAX_FRAME_LENGTH_LINES_BIN,
+		SMIAPP_LIMIT_MIN_LINE_LENGTH_PCK_BIN,
+		SMIAPP_LIMIT_MAX_LINE_LENGTH_PCK_BIN,
+		SMIAPP_LIMIT_MIN_LINE_BLANKING_PCK_BIN,
+		SMIAPP_LIMIT_FINE_INTEGRATION_TIME_MIN_BIN,
+		SMIAPP_LIMIT_FINE_INTEGRATION_TIME_MAX_MARGIN_BIN,
+	};
+	static u32 const limits_replace[] = {
+		SMIAPP_LIMIT_MIN_FRAME_LENGTH_LINES,
+		SMIAPP_LIMIT_MAX_FRAME_LENGTH_LINES,
+		SMIAPP_LIMIT_MIN_LINE_LENGTH_PCK,
+		SMIAPP_LIMIT_MAX_LINE_LENGTH_PCK,
+		SMIAPP_LIMIT_MIN_LINE_BLANKING_PCK,
+		SMIAPP_LIMIT_FINE_INTEGRATION_TIME_MIN,
+		SMIAPP_LIMIT_FINE_INTEGRATION_TIME_MAX_MARGIN,
+	};
+	unsigned int i;
+	int rval;
+
+	if (sensor->limits[SMIAPP_LIMIT_BINNING_CAPABILITY] ==
+	    SMIAPP_BINNING_CAPABILITY_NO) {
+		for (i = 0; i < ARRAY_SIZE(limits); i++)
+			sensor->limits[limits[i]] =
+				sensor->limits[limits_replace[i]];
+
+		return 0;
+	}
+
+	rval = smiapp_get_limits(sensor, limits, ARRAY_SIZE(limits));
+	if (rval < 0)
+		return rval;
+
+	/*
+	 * Sanity check whether the binning limits are valid. If not,
+	 * use the non-binning ones.
+	 */
+	if (sensor->limits[SMIAPP_LIMIT_MIN_FRAME_LENGTH_LINES_BIN]
+	    && sensor->limits[SMIAPP_LIMIT_MIN_LINE_LENGTH_PCK_BIN]
+	    && sensor->limits[SMIAPP_LIMIT_MIN_LINE_BLANKING_PCK_BIN])
+		return 0;
+
+	for (i = 0; i < ARRAY_SIZE(limits); i++) {
+		dev_dbg(&client->dev,
+			"replace limit 0x%8.8x \"%s\" = %d, 0x%x\n",
+			smiapp_reg_limits[limits[i]].addr,
+			smiapp_reg_limits[limits[i]].what,
+			sensor->limits[limits_replace[i]],
+			sensor->limits[limits_replace[i]]);
+		sensor->limits[limits[i]] =
+			sensor->limits[limits_replace[i]];
+	}
+
+	return 0;
+}
+
+static int smiapp_get_mbus_formats(struct smiapp_sensor *sensor)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
+	unsigned int type, n;
+	unsigned int i, pixel_order;
+	int rval;
+
+	rval = smiapp_read(
+		sensor, SMIAPP_REG_U8_DATA_FORMAT_MODEL_TYPE, &type);
+	if (rval)
+		return rval;
+
+	dev_dbg(&client->dev, "data_format_model_type %d\n", type);
+
+	rval = smiapp_read(sensor, SMIAPP_REG_U8_PIXEL_ORDER,
+			   &pixel_order);
+	if (rval)
+		return rval;
+
+	if (pixel_order >= ARRAY_SIZE(pixel_order_str)) {
+		dev_dbg(&client->dev, "bad pixel order %d\n", pixel_order);
+		return -EINVAL;
+	}
+
+	dev_dbg(&client->dev, "pixel order %d (%s)\n", pixel_order,
+		pixel_order_str[pixel_order]);
+
+	switch (type) {
+	case SMIAPP_DATA_FORMAT_MODEL_TYPE_NORMAL:
+		n = SMIAPP_DATA_FORMAT_MODEL_TYPE_NORMAL_N;
+		break;
+	case SMIAPP_DATA_FORMAT_MODEL_TYPE_EXTENDED:
+		n = SMIAPP_DATA_FORMAT_MODEL_TYPE_EXTENDED_N;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	sensor->default_pixel_order = pixel_order;
+	sensor->mbus_frame_fmts = 0;
+
+	for (i = 0; i < n; i++) {
+		unsigned int fmt, j;
+
+		rval = smiapp_read(
+			sensor,
+			SMIAPP_REG_U16_DATA_FORMAT_DESCRIPTOR(i), &fmt);
+		if (rval)
+			return rval;
+
+		dev_dbg(&client->dev, "bpp %d, compressed %d\n",
+			fmt >> 8, (u8)fmt);
+
+		for (j = 0; j < ARRAY_SIZE(smiapp_csi_data_formats); j++) {
+			const struct smiapp_csi_data_format *f =
+				&smiapp_csi_data_formats[j];
+
+			if (f->pixel_order != SMIAPP_PIXEL_ORDER_GRBG)
+				continue;
+
+			if (f->width != fmt >> 8 || f->compressed != (u8)fmt)
+				continue;
+
+			dev_dbg(&client->dev, "jolly good! %d\n", j);
+
+			sensor->default_mbus_frame_fmts |= 1 << j;
+			if (!sensor->csi_format) {
+				sensor->csi_format = f;
+				sensor->internal_csi_format = f;
+			}
+		}
+	}
+
+	if (!sensor->csi_format) {
+		dev_err(&client->dev, "no supported mbus code found\n");
+		return -EINVAL;
+	}
+
+	smiapp_update_mbus_formats(sensor);
+
+	return 0;
+}
+
+static void smiapp_update_blanking(struct smiapp_sensor *sensor)
+{
+	struct v4l2_ctrl *vblank = sensor->vblank;
+	struct v4l2_ctrl *hblank = sensor->hblank;
+
+	vblank->minimum =
+		max_t(int,
+		      sensor->limits[SMIAPP_LIMIT_MIN_FRAME_BLANKING_LINES],
+		      sensor->limits[SMIAPP_LIMIT_MIN_FRAME_LENGTH_LINES_BIN] -
+		      sensor->pixel_array->crop[SMIAPP_PA_PAD_SRC].height);
+	vblank->maximum =
+		sensor->limits[SMIAPP_LIMIT_MAX_FRAME_LENGTH_LINES_BIN] -
+		sensor->pixel_array->crop[SMIAPP_PA_PAD_SRC].height;
+
+	vblank->val = clamp_t(int, vblank->val,
+			      vblank->minimum, vblank->maximum);
+	vblank->default_value = vblank->minimum;
+	vblank->val = vblank->val;
+	vblank->cur.val = vblank->val;
+
+	hblank->minimum =
+		max_t(int,
+		      sensor->limits[SMIAPP_LIMIT_MIN_LINE_LENGTH_PCK_BIN] -
+		      sensor->pixel_array->crop[SMIAPP_PA_PAD_SRC].width,
+		      sensor->limits[SMIAPP_LIMIT_MIN_LINE_BLANKING_PCK_BIN]);
+	hblank->maximum =
+		sensor->limits[SMIAPP_LIMIT_MAX_LINE_LENGTH_PCK_BIN] -
+		sensor->pixel_array->crop[SMIAPP_PA_PAD_SRC].width;
+
+	hblank->val = clamp_t(int, hblank->val,
+			      hblank->minimum, hblank->maximum);
+	hblank->default_value = hblank->minimum;
+	hblank->val = hblank->val;
+	hblank->cur.val = hblank->val;
+
+	__smiapp_update_exposure_limits(sensor);
+}
+
+static int smiapp_update_mode(struct smiapp_sensor *sensor)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
+	unsigned int binning_mode;
+	int rval;
+
+	dev_dbg(&client->dev, "frame size: %dx%d\n",
+		sensor->src->crop[SMIAPP_PAD_SRC].width,
+		sensor->src->crop[SMIAPP_PAD_SRC].height);
+	dev_dbg(&client->dev, "csi format width: %d\n",
+		sensor->csi_format->width);
+
+	/* Binning has to be set up here; it affects limits */
+	if (sensor->binning_horizontal == 1 &&
+	    sensor->binning_vertical == 1) {
+		binning_mode = 0;
+	} else {
+		u8 binning_type =
+			(sensor->binning_horizontal << 4)
+			| sensor->binning_vertical;
+
+		rval = smiapp_write(
+			sensor, SMIAPP_REG_U8_BINNING_TYPE, binning_type);
+		if (rval < 0)
+			return rval;
+
+		binning_mode = 1;
+	}
+	rval = smiapp_write(sensor, SMIAPP_REG_U8_BINNING_MODE, binning_mode);
+	if (rval < 0)
+		return rval;
+
+	/* Get updated limits due to binning */
+	rval = smiapp_get_limits_binning(sensor);
+	if (rval < 0)
+		return rval;
+
+	rval = smiapp_pll_update(sensor);
+	if (rval < 0)
+		return rval;
+
+	/* Output from pixel array, including blanking */
+	smiapp_update_blanking(sensor);
+
+	dev_dbg(&client->dev, "vblank\t\t%d\n", sensor->vblank->val);
+	dev_dbg(&client->dev, "hblank\t\t%d\n", sensor->hblank->val);
+
+	dev_dbg(&client->dev, "real timeperframe\t100/%d\n",
+		sensor->pll.vt_pix_clk_freq_hz /
+		((sensor->pixel_array->crop[SMIAPP_PA_PAD_SRC].width
+		  + sensor->hblank->val) *
+		 (sensor->pixel_array->crop[SMIAPP_PA_PAD_SRC].height
+		  + sensor->vblank->val) / 100));
+
+	return 0;
+}
+
+/*
+ *
+ * SMIA++ NVM handling
+ *
+ */
+static int smiapp_read_nvm(struct smiapp_sensor *sensor,
+			   unsigned char *nvm)
+{
+	u32 i, s, p, np, v;
+	int rval = 0, rval2;
+
+	np = sensor->nvm_size / SMIAPP_NVM_PAGE_SIZE;
+	for (p = 0; p < np; p++) {
+		rval = smiapp_write(
+			sensor,
+			SMIAPP_REG_U8_DATA_TRANSFER_IF_1_PAGE_SELECT, p);
+		if (rval)
+			goto out;
+
+		rval = smiapp_write(sensor,
+				    SMIAPP_REG_U8_DATA_TRANSFER_IF_1_CTRL,
+				    SMIAPP_DATA_TRANSFER_IF_1_CTRL_EN |
+				    SMIAPP_DATA_TRANSFER_IF_1_CTRL_RD_EN);
+		if (rval)
+			goto out;
+
+		for (i = 0; i < 1000; i++) {
+			rval = smiapp_read(
+				sensor,
+				SMIAPP_REG_U8_DATA_TRANSFER_IF_1_STATUS, &s);
+
+			if (rval)
+				goto out;
+
+			if (s & SMIAPP_DATA_TRANSFER_IF_1_STATUS_RD_READY)
+				break;
+
+			if (--i == 0) {
+				rval = -ETIMEDOUT;
+				goto out;
+			}
+
+		}
+
+		for (i = 0; i < SMIAPP_NVM_PAGE_SIZE; i++) {
+			rval = smiapp_read(
+				sensor,
+				SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_0 + i,
+				&v);
+			if (rval)
+				goto out;
+
+			*nvm++ = v;
+		}
+	}
+
+out:
+	rval2 = smiapp_write(sensor, SMIAPP_REG_U8_DATA_TRANSFER_IF_1_CTRL, 0);
+	if (rval < 0)
+		return rval;
+	else
+		return rval2;
+}
+
+/*
+ *
+ * SMIA++ CCI address control
+ *
+ */
+static int smiapp_change_cci_addr(struct smiapp_sensor *sensor)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
+	int rval;
+	u32 val;
+
+	client->addr = sensor->platform_data->i2c_addr_dfl;
+
+	rval = smiapp_write(sensor,
+			    SMIAPP_REG_U8_CCI_ADDRESS_CONTROL,
+			    sensor->platform_data->i2c_addr_alt << 1);
+	if (rval)
+		return rval;
+
+	client->addr = sensor->platform_data->i2c_addr_alt;
+
+	/* verify addr change went ok */
+	rval = smiapp_read(sensor, SMIAPP_REG_U8_CCI_ADDRESS_CONTROL, &val);
+	if (rval)
+		return rval;
+
+	if (val != sensor->platform_data->i2c_addr_alt << 1)
+		return -ENODEV;
+
+	return 0;
+}
+
+/*
+ *
+ * SMIA++ Mode Control
+ *
+ */
+static int smiapp_setup_flash_strobe(struct smiapp_sensor *sensor)
+{
+	struct smiapp_flash_strobe_parms *strobe_setup;
+	unsigned int ext_freq = sensor->platform_data->ext_clk;
+	u32 tmp;
+	u32 strobe_adjustment;
+	u32 strobe_width_high_rs;
+	int rval;
+
+	strobe_setup = sensor->platform_data->strobe_setup;
+
+	/*
+	 * How to calculate registers related to strobe length. Please
+	 * do not change, or if you do at least know what you're
+	 * doing. :-)
+	 *
+	 * Sakari Ailus <sakari.ailus@maxwell.research.nokia.com> 2010-10-25
+	 *
+	 * flash_strobe_length [us] / 10^6 = (tFlash_strobe_width_ctrl
+	 *	/ EXTCLK freq [Hz]) * flash_strobe_adjustment
+	 *
+	 * tFlash_strobe_width_ctrl E N, [1 - 0xffff]
+	 * flash_strobe_adjustment E N, [1 - 0xff]
+	 *
+	 * The formula above is written as below to keep it on one
+	 * line:
+	 *
+	 * l / 10^6 = w / e * a
+	 *
+	 * Let's mark w * a by x:
+	 *
+	 * x = w * a
+	 *
+	 * Thus, we get:
+	 *
+	 * x = l * e / 10^6
+	 *
+	 * The strobe width must be at least as long as requested,
+	 * thus rounding upwards is needed.
+	 *
+	 * x = (l * e + 10^6 - 1) / 10^6
+	 * -----------------------------
+	 *
+	 * Maximum possible accuracy is wanted at all times. Thus keep
+	 * a as small as possible.
+	 *
+	 * Calculate a, assuming maximum w, with rounding upwards:
+	 *
+	 * a = (x + (2^16 - 1) - 1) / (2^16 - 1)
+	 * -------------------------------------
+	 *
+	 * Thus, we also get w, with that a, with rounding upwards:
+	 *
+	 * w = (x + a - 1) / a
+	 * -------------------
+	 *
+	 * To get limits:
+	 *
+	 * x E [1, (2^16 - 1) * (2^8 - 1)]
+	 *
+	 * Substituting maximum x to the original formula (with rounding),
+	 * the maximum l is thus
+	 *
+	 * (2^16 - 1) * (2^8 - 1) * 10^6 = l * e + 10^6 - 1
+	 *
+	 * l = (10^6 * (2^16 - 1) * (2^8 - 1) - 10^6 + 1) / e
+	 * --------------------------------------------------
+	 *
+	 * flash_strobe_length must be clamped between 1 and
+	 * (10^6 * (2^16 - 1) * (2^8 - 1) - 10^6 + 1) / EXTCLK freq.
+	 *
+	 * Then,
+	 *
+	 * flash_strobe_adjustment = ((flash_strobe_length *
+	 *	EXTCLK freq + 10^6 - 1) / 10^6 + (2^16 - 1) - 1) / (2^16 - 1)
+	 *
+	 * tFlash_strobe_width_ctrl = ((flash_strobe_length *
+	 *	EXTCLK freq + 10^6 - 1) / 10^6 +
+	 *	flash_strobe_adjustment - 1) / flash_strobe_adjustment
+	 */
+	tmp = div_u64(1000000ULL * ((1 << 16) - 1) * ((1 << 8) - 1) -
+		      1000000 + 1, ext_freq);
+	strobe_setup->strobe_width_high_us =
+		clamp_t(u32, strobe_setup->strobe_width_high_us, 1, tmp);
+
+	tmp = div_u64(((u64)strobe_setup->strobe_width_high_us * (u64)ext_freq +
+			1000000 - 1), 1000000ULL);
+	strobe_adjustment = (tmp + (1 << 16) - 1 - 1) / ((1 << 16) - 1);
+	strobe_width_high_rs = (tmp + strobe_adjustment - 1) /
+				strobe_adjustment;
+
+	rval = smiapp_write(sensor, SMIAPP_REG_U8_FLASH_MODE_RS,
+			    strobe_setup->mode);
+	if (rval < 0)
+		goto out;
+
+	rval = smiapp_write(sensor, SMIAPP_REG_U8_FLASH_STROBE_ADJUSTMENT,
+			    strobe_adjustment);
+	if (rval < 0)
+		goto out;
+
+	rval = smiapp_write(
+		sensor, SMIAPP_REG_U16_TFLASH_STROBE_WIDTH_HIGH_RS_CTRL,
+		strobe_width_high_rs);
+	if (rval < 0)
+		goto out;
+
+	rval = smiapp_write(sensor, SMIAPP_REG_U16_TFLASH_STROBE_DELAY_RS_CTRL,
+			    strobe_setup->strobe_delay);
+	if (rval < 0)
+		goto out;
+
+	rval = smiapp_write(sensor, SMIAPP_REG_U16_FLASH_STROBE_START_POINT,
+			    strobe_setup->stobe_start_point);
+	if (rval < 0)
+		goto out;
+
+	rval = smiapp_write(sensor, SMIAPP_REG_U8_FLASH_TRIGGER_RS,
+			    strobe_setup->trigger);
+
+out:
+	sensor->platform_data->strobe_setup->trigger = 0;
+
+	return rval;
+}
+
+/* -----------------------------------------------------------------------------
+ * Power management
+ */
+
+static int smiapp_power_on(struct smiapp_sensor *sensor)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
+	unsigned int sleep;
+	int rval;
+
+	rval = regulator_enable(sensor->vana);
+	if (rval) {
+		dev_err(&client->dev, "failed to enable vana regulator\n");
+		return rval;
+	}
+	usleep_range(1000, 1000);
+
+	if (sensor->platform_data->set_xclk)
+		rval = sensor->platform_data->set_xclk(
+			&sensor->src->sd, sensor->platform_data->ext_clk);
+	else
+		rval = clk_enable(sensor->ext_clk);
+	if (rval < 0) {
+		dev_dbg(&client->dev, "failed to set xclk\n");
+		goto out_xclk_fail;
+	}
+	usleep_range(1000, 1000);
+
+	if (sensor->platform_data->xshutdown != SMIAPP_NO_XSHUTDOWN)
+		gpio_set_value(sensor->platform_data->xshutdown, 1);
+
+	sleep = SMIAPP_RESET_DELAY(sensor->platform_data->ext_clk);
+	usleep_range(sleep, sleep);
+
+	/*
+	 * Failures to respond to the address change command have been noticed.
+	 * Those failures seem to be caused by the sensor requiring a longer
+	 * boot time than advertised. An additional 10ms delay seems to work
+	 * around the issue, but the SMIA++ I2C write retry hack makes the delay
+	 * unnecessary. The failures need to be investigated to find a proper
+	 * fix, and a delay will likely need to be added here if the I2C write
+	 * retry hack is reverted before the root cause of the boot time issue
+	 * is found.
+	 */
+
+	if (sensor->platform_data->i2c_addr_alt) {
+		rval = smiapp_change_cci_addr(sensor);
+		if (rval) {
+			dev_err(&client->dev, "cci address change error\n");
+			goto out_cci_addr_fail;
+		}
+	}
+
+	rval = smiapp_write(sensor, SMIAPP_REG_U8_SOFTWARE_RESET,
+			    SMIAPP_SOFTWARE_RESET);
+	if (rval < 0) {
+		dev_err(&client->dev, "software reset failed\n");
+		goto out_cci_addr_fail;
+	}
+
+	if (sensor->platform_data->i2c_addr_alt) {
+		rval = smiapp_change_cci_addr(sensor);
+		if (rval) {
+			dev_err(&client->dev, "cci address change error\n");
+			goto out_cci_addr_fail;
+		}
+	}
+
+	rval = smiapp_write(sensor, SMIAPP_REG_U16_COMPRESSION_MODE,
+			    SMIAPP_COMPRESSION_MODE_SIMPLE_PREDICTOR);
+	if (rval) {
+		dev_err(&client->dev, "compression mode set failed\n");
+		goto out_cci_addr_fail;
+	}
+
+	rval = smiapp_write(
+		sensor, SMIAPP_REG_U16_EXTCLK_FREQUENCY_MHZ,
+		sensor->platform_data->ext_clk / (1000000 / (1 << 8)));
+	if (rval) {
+		dev_err(&client->dev, "extclk frequency set failed\n");
+		goto out_cci_addr_fail;
+	}
+
+	rval = smiapp_write(sensor, SMIAPP_REG_U8_CSI_LANE_MODE,
+			    sensor->platform_data->lanes - 1);
+	if (rval) {
+		dev_err(&client->dev, "csi lane mode set failed\n");
+		goto out_cci_addr_fail;
+	}
+
+	rval = smiapp_write(sensor, SMIAPP_REG_U8_FAST_STANDBY_CTRL,
+			    SMIAPP_FAST_STANDBY_CTRL_IMMEDIATE);
+	if (rval) {
+		dev_err(&client->dev, "fast standby set failed\n");
+		goto out_cci_addr_fail;
+	}
+
+	rval = smiapp_write(sensor, SMIAPP_REG_U8_CSI_SIGNALLING_MODE,
+			    sensor->platform_data->csi_signalling_mode);
+	if (rval) {
+		dev_err(&client->dev, "csi signalling mode set failed\n");
+		goto out_cci_addr_fail;
+	}
+
+	/* DPHY control done by sensor based on requested link rate */
+	rval = smiapp_write(sensor, SMIAPP_REG_U8_DPHY_CTRL,
+			    SMIAPP_DPHY_CTRL_UI);
+	if (rval < 0)
+		return rval;
+
+	rval = smiapp_call_quirk(sensor, post_poweron);
+	if (rval) {
+		dev_err(&client->dev, "post_poweron quirks failed\n");
+		goto out_cci_addr_fail;
+	}
+
+	/* Are we still initialising...? If yes, return here. */
+	if (!sensor->pixel_array)
+		return 0;
+
+	rval = v4l2_ctrl_handler_setup(
+		&sensor->pixel_array->ctrl_handler);
+	if (rval)
+		goto out_cci_addr_fail;
+
+	rval = v4l2_ctrl_handler_setup(&sensor->src->ctrl_handler);
+	if (rval)
+		goto out_cci_addr_fail;
+
+	mutex_lock(&sensor->mutex);
+	rval = smiapp_update_mode(sensor);
+	mutex_unlock(&sensor->mutex);
+	if (rval < 0)
+		goto out_cci_addr_fail;
+
+	return 0;
+
+out_cci_addr_fail:
+	if (sensor->platform_data->xshutdown != SMIAPP_NO_XSHUTDOWN)
+		gpio_set_value(sensor->platform_data->xshutdown, 0);
+	if (sensor->platform_data->set_xclk)
+		sensor->platform_data->set_xclk(&sensor->src->sd, 0);
+	else
+		clk_disable(sensor->ext_clk);
+
+out_xclk_fail:
+	regulator_disable(sensor->vana);
+	return rval;
+}
+
+static void smiapp_power_off(struct smiapp_sensor *sensor)
+{
+	/*
+	 * Currently power/clock to lens are enable/disabled separately
+	 * but they are essentially the same signals. So if the sensor is
+	 * powered off while the lens is powered on the sensor does not
+	 * really see a power off and next time the cci address change
+	 * will fail. So do a soft reset explicitly here.
+	 */
+	if (sensor->platform_data->i2c_addr_alt)
+		smiapp_write(sensor,
+			     SMIAPP_REG_U8_SOFTWARE_RESET,
+			     SMIAPP_SOFTWARE_RESET);
+
+	if (sensor->platform_data->xshutdown != SMIAPP_NO_XSHUTDOWN)
+		gpio_set_value(sensor->platform_data->xshutdown, 0);
+	if (sensor->platform_data->set_xclk)
+		sensor->platform_data->set_xclk(&sensor->src->sd, 0);
+	else
+		clk_disable(sensor->ext_clk);
+	usleep_range(5000, 5000);
+	regulator_disable(sensor->vana);
+	sensor->streaming = 0;
+}
+
+static int smiapp_set_power(struct v4l2_subdev *subdev, int on)
+{
+	struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
+	int ret = 0;
+
+	mutex_lock(&sensor->power_mutex);
+
+	/*
+	 * If the power count is modified from 0 to != 0 or from != 0
+	 * to 0, update the power state.
+	 */
+	if (!sensor->power_count == !on)
+		goto out;
+
+	if (on) {
+		/* Power on and perform initialisation. */
+		ret = smiapp_power_on(sensor);
+		if (ret < 0)
+			goto out;
+	} else {
+		smiapp_power_off(sensor);
+	}
+
+	/* Update the power count. */
+	sensor->power_count += on ? 1 : -1;
+	WARN_ON(sensor->power_count < 0);
+
+out:
+	mutex_unlock(&sensor->power_mutex);
+	return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ * Video stream management
+ */
+
+static int smiapp_start_streaming(struct smiapp_sensor *sensor)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
+	int rval;
+
+	mutex_lock(&sensor->mutex);
+
+	rval = smiapp_write(sensor, SMIAPP_REG_U16_CSI_DATA_FORMAT,
+			    (sensor->csi_format->width << 8) |
+			    sensor->csi_format->compressed);
+	if (rval)
+		goto out;
+
+	rval = smiapp_pll_configure(sensor);
+	if (rval)
+		goto out;
+
+	/* Analog crop start coordinates */
+	rval = smiapp_write(sensor, SMIAPP_REG_U16_X_ADDR_START,
+			    sensor->pixel_array->crop[SMIAPP_PA_PAD_SRC].left);
+	if (rval < 0)
+		goto out;
+
+	rval = smiapp_write(sensor, SMIAPP_REG_U16_Y_ADDR_START,
+			    sensor->pixel_array->crop[SMIAPP_PA_PAD_SRC].top);
+	if (rval < 0)
+		goto out;
+
+	/* Analog crop end coordinates */
+	rval = smiapp_write(
+		sensor, SMIAPP_REG_U16_X_ADDR_END,
+		sensor->pixel_array->crop[SMIAPP_PA_PAD_SRC].left
+		+ sensor->pixel_array->crop[SMIAPP_PA_PAD_SRC].width - 1);
+	if (rval < 0)
+		goto out;
+
+	rval = smiapp_write(
+		sensor, SMIAPP_REG_U16_Y_ADDR_END,
+		sensor->pixel_array->crop[SMIAPP_PA_PAD_SRC].top
+		+ sensor->pixel_array->crop[SMIAPP_PA_PAD_SRC].height - 1);
+	if (rval < 0)
+		goto out;
+
+	/*
+	 * Output from pixel array, including blanking, is set using
+	 * controls below. No need to set here.
+	 */
+
+	/* Digital crop */
+	if (sensor->limits[SMIAPP_LIMIT_DIGITAL_CROP_CAPABILITY]
+	    == SMIAPP_DIGITAL_CROP_CAPABILITY_INPUT_CROP) {
+		rval = smiapp_write(
+			sensor, SMIAPP_REG_U16_DIGITAL_CROP_X_OFFSET,
+			sensor->scaler->crop[SMIAPP_PAD_SINK].left);
+		if (rval < 0)
+			goto out;
+
+		rval = smiapp_write(
+			sensor, SMIAPP_REG_U16_DIGITAL_CROP_Y_OFFSET,
+			sensor->scaler->crop[SMIAPP_PAD_SINK].top);
+		if (rval < 0)
+			goto out;
+
+		rval = smiapp_write(
+			sensor, SMIAPP_REG_U16_DIGITAL_CROP_IMAGE_WIDTH,
+			sensor->scaler->crop[SMIAPP_PAD_SINK].width);
+		if (rval < 0)
+			goto out;
+
+		rval = smiapp_write(
+			sensor, SMIAPP_REG_U16_DIGITAL_CROP_IMAGE_HEIGHT,
+			sensor->scaler->crop[SMIAPP_PAD_SINK].height);
+		if (rval < 0)
+			goto out;
+	}
+
+	/* Scaling */
+	if (sensor->limits[SMIAPP_LIMIT_SCALING_CAPABILITY]
+	    != SMIAPP_SCALING_CAPABILITY_NONE) {
+		rval = smiapp_write(sensor, SMIAPP_REG_U16_SCALING_MODE,
+				    sensor->scaling_mode);
+		if (rval < 0)
+			goto out;
+
+		rval = smiapp_write(sensor, SMIAPP_REG_U16_SCALE_M,
+				    sensor->scale_m);
+		if (rval < 0)
+			goto out;
+	}
+
+	/* Output size from sensor */
+	rval = smiapp_write(sensor, SMIAPP_REG_U16_X_OUTPUT_SIZE,
+			    sensor->src->crop[SMIAPP_PAD_SRC].width);
+	if (rval < 0)
+		goto out;
+	rval = smiapp_write(sensor, SMIAPP_REG_U16_Y_OUTPUT_SIZE,
+			    sensor->src->crop[SMIAPP_PAD_SRC].height);
+	if (rval < 0)
+		goto out;
+
+	if ((sensor->flash_capability &
+	     (SMIAPP_FLASH_MODE_CAPABILITY_SINGLE_STROBE |
+	      SMIAPP_FLASH_MODE_CAPABILITY_MULTIPLE_STROBE)) &&
+	    sensor->platform_data->strobe_setup != NULL &&
+	    sensor->platform_data->strobe_setup->trigger != 0) {
+		rval = smiapp_setup_flash_strobe(sensor);
+		if (rval)
+			goto out;
+	}
+
+	rval = smiapp_call_quirk(sensor, pre_streamon);
+	if (rval) {
+		dev_err(&client->dev, "pre_streamon quirks failed\n");
+		goto out;
+	}
+
+	rval = smiapp_write(sensor, SMIAPP_REG_U8_MODE_SELECT,
+			    SMIAPP_MODE_SELECT_STREAMING);
+
+out:
+	mutex_unlock(&sensor->mutex);
+
+	return rval;
+}
+
+static int smiapp_stop_streaming(struct smiapp_sensor *sensor)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
+	int rval;
+
+	mutex_lock(&sensor->mutex);
+	rval = smiapp_write(sensor, SMIAPP_REG_U8_MODE_SELECT,
+			    SMIAPP_MODE_SELECT_SOFTWARE_STANDBY);
+	if (rval)
+		goto out;
+
+	rval = smiapp_call_quirk(sensor, post_streamoff);
+	if (rval)
+		dev_err(&client->dev, "post_streamoff quirks failed\n");
+
+out:
+	mutex_unlock(&sensor->mutex);
+	return rval;
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 subdev video operations
+ */
+
+static int smiapp_set_stream(struct v4l2_subdev *subdev, int enable)
+{
+	struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
+	int rval;
+
+	if (sensor->streaming == enable)
+		return 0;
+
+	if (enable) {
+		sensor->streaming = 1;
+		rval = smiapp_start_streaming(sensor);
+		if (rval < 0)
+			sensor->streaming = 0;
+	} else {
+		rval = smiapp_stop_streaming(sensor);
+		sensor->streaming = 0;
+	}
+
+	return rval;
+}
+
+static int smiapp_enum_mbus_code(struct v4l2_subdev *subdev,
+				 struct v4l2_subdev_fh *fh,
+				 struct v4l2_subdev_mbus_code_enum *code)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(subdev);
+	struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
+	unsigned int i;
+	int idx = -1;
+	int rval = -EINVAL;
+
+	mutex_lock(&sensor->mutex);
+
+	dev_err(&client->dev, "subdev %s, pad %d, index %d\n",
+		subdev->name, code->pad, code->index);
+
+	if (subdev != &sensor->src->sd || code->pad != SMIAPP_PAD_SRC) {
+		if (code->index)
+			goto out;
+
+		code->code = sensor->internal_csi_format->code;
+		rval = 0;
+		goto out;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(smiapp_csi_data_formats); i++) {
+		if (sensor->mbus_frame_fmts & (1 << i))
+			idx++;
+
+		if (idx == code->index) {
+			code->code = smiapp_csi_data_formats[i].code;
+			dev_err(&client->dev, "found index %d, i %d, code %x\n",
+				code->index, i, code->code);
+			rval = 0;
+			break;
+		}
+	}
+
+out:
+	mutex_unlock(&sensor->mutex);
+
+	return rval;
+}
+
+static u32 __smiapp_get_mbus_code(struct v4l2_subdev *subdev,
+				  unsigned int pad)
+{
+	struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
+
+	if (subdev == &sensor->src->sd && pad == SMIAPP_PAD_SRC)
+		return sensor->csi_format->code;
+	else
+		return sensor->internal_csi_format->code;
+}
+
+static int __smiapp_get_format(struct v4l2_subdev *subdev,
+			       struct v4l2_subdev_fh *fh,
+			       struct v4l2_subdev_format *fmt)
+{
+	struct smiapp_subdev *ssd = to_smiapp_subdev(subdev);
+
+	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
+		fmt->format = *v4l2_subdev_get_try_format(fh, fmt->pad);
+	} else {
+		struct v4l2_rect *r;
+
+		if (fmt->pad == ssd->source_pad)
+			r = &ssd->crop[ssd->source_pad];
+		else
+			r = &ssd->sink_fmt;
+
+		fmt->format.code = __smiapp_get_mbus_code(subdev, fmt->pad);
+		fmt->format.width = r->width;
+		fmt->format.height = r->height;
+	}
+
+	return 0;
+}
+
+static int smiapp_get_format(struct v4l2_subdev *subdev,
+			     struct v4l2_subdev_fh *fh,
+			     struct v4l2_subdev_format *fmt)
+{
+	struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
+	int rval;
+
+	mutex_lock(&sensor->mutex);
+	rval = __smiapp_get_format(subdev, fh, fmt);
+	mutex_unlock(&sensor->mutex);
+
+	return rval;
+}
+
+static void smiapp_get_crop_compose(struct v4l2_subdev *subdev,
+				    struct v4l2_subdev_fh *fh,
+				    struct v4l2_rect **crops,
+				    struct v4l2_rect **comps, int which)
+{
+	struct smiapp_subdev *ssd = to_smiapp_subdev(subdev);
+	unsigned int i;
+
+	if (which == V4L2_SUBDEV_FORMAT_ACTIVE) {
+		if (crops)
+			for (i = 0; i < subdev->entity.num_pads; i++)
+				crops[i] = &ssd->crop[i];
+		if (comps)
+			*comps = &ssd->compose;
+	} else {
+		if (crops) {
+			for (i = 0; i < subdev->entity.num_pads; i++) {
+				crops[i] = v4l2_subdev_get_try_crop(fh, i);
+				BUG_ON(!crops[i]);
+			}
+		}
+		if (comps) {
+			*comps = v4l2_subdev_get_try_compose(fh,
+							     SMIAPP_PAD_SINK);
+			BUG_ON(!*comps);
+		}
+	}
+}
+
+/* Changes require propagation only on sink pad. */
+static void smiapp_propagate(struct v4l2_subdev *subdev,
+			     struct v4l2_subdev_fh *fh, int which,
+			     int target)
+{
+	struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
+	struct smiapp_subdev *ssd = to_smiapp_subdev(subdev);
+	struct v4l2_rect *comp, *crops[SMIAPP_PADS];
+
+	smiapp_get_crop_compose(subdev, fh, crops, &comp, which);
+
+	switch (target) {
+	case V4L2_SEL_TGT_CROP:
+		comp->width = crops[SMIAPP_PAD_SINK]->width;
+		comp->height = crops[SMIAPP_PAD_SINK]->height;
+		if (which == V4L2_SUBDEV_FORMAT_ACTIVE) {
+			if (ssd == sensor->scaler) {
+				sensor->scale_m =
+					sensor->limits[
+						SMIAPP_LIMIT_SCALER_N_MIN];
+				sensor->scaling_mode =
+					SMIAPP_SCALING_MODE_NONE;
+			} else if (ssd == sensor->binner) {
+				sensor->binning_horizontal = 1;
+				sensor->binning_vertical = 1;
+			}
+		}
+		/* Fall through */
+	case V4L2_SEL_TGT_COMPOSE:
+		*crops[SMIAPP_PAD_SRC] = *comp;
+		break;
+	default:
+		BUG();
+	}
+}
+
+static const struct smiapp_csi_data_format
+*smiapp_validate_csi_data_format(struct smiapp_sensor *sensor, u32 code)
+{
+	const struct smiapp_csi_data_format *csi_format = sensor->csi_format;
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(smiapp_csi_data_formats); i++) {
+		if (sensor->mbus_frame_fmts & (1 << i)
+		    && smiapp_csi_data_formats[i].code == code)
+			return &smiapp_csi_data_formats[i];
+	}
+
+	return csi_format;
+}
+
+static int smiapp_set_format(struct v4l2_subdev *subdev,
+			     struct v4l2_subdev_fh *fh,
+			     struct v4l2_subdev_format *fmt)
+{
+	struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
+	struct smiapp_subdev *ssd = to_smiapp_subdev(subdev);
+	struct v4l2_rect *crops[SMIAPP_PADS];
+
+	mutex_lock(&sensor->mutex);
+
+	/*
+	 * Media bus code is changeable on src subdev's source pad. On
+	 * other source pads we just get format here.
+	 */
+	if (fmt->pad == ssd->source_pad) {
+		u32 code = fmt->format.code;
+		int rval = __smiapp_get_format(subdev, fh, fmt);
+
+		if (!rval && subdev == &sensor->src->sd) {
+			const struct smiapp_csi_data_format *csi_format =
+				smiapp_validate_csi_data_format(sensor, code);
+			if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+				sensor->csi_format = csi_format;
+			fmt->format.code = csi_format->code;
+		}
+
+		mutex_unlock(&sensor->mutex);
+		return rval;
+	}
+
+	/* Sink pad. Width and height are changeable here. */
+	fmt->format.code = __smiapp_get_mbus_code(subdev, fmt->pad);
+	fmt->format.width &= ~1;
+	fmt->format.height &= ~1;
+
+	fmt->format.width =
+		clamp(fmt->format.width,
+		      sensor->limits[SMIAPP_LIMIT_MIN_X_OUTPUT_SIZE],
+		      sensor->limits[SMIAPP_LIMIT_MAX_X_OUTPUT_SIZE]);
+	fmt->format.height =
+		clamp(fmt->format.height,
+		      sensor->limits[SMIAPP_LIMIT_MIN_Y_OUTPUT_SIZE],
+		      sensor->limits[SMIAPP_LIMIT_MAX_Y_OUTPUT_SIZE]);
+
+	smiapp_get_crop_compose(subdev, fh, crops, NULL, fmt->which);
+
+	crops[ssd->sink_pad]->left = 0;
+	crops[ssd->sink_pad]->top = 0;
+	crops[ssd->sink_pad]->width = fmt->format.width;
+	crops[ssd->sink_pad]->height = fmt->format.height;
+	if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+		ssd->sink_fmt = *crops[ssd->sink_pad];
+	smiapp_propagate(subdev, fh, fmt->which,
+			 V4L2_SEL_TGT_CROP);
+
+	mutex_unlock(&sensor->mutex);
+
+	return 0;
+}
+
+/*
+ * Calculate goodness of scaled image size compared to expected image
+ * size and flags provided.
+ */
+#define SCALING_GOODNESS		100000
+#define SCALING_GOODNESS_EXTREME	100000000
+static int scaling_goodness(struct v4l2_subdev *subdev, int w, int ask_w,
+			    int h, int ask_h, u32 flags)
+{
+	struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
+	struct i2c_client *client = v4l2_get_subdevdata(subdev);
+	int val = 0;
+
+	w &= ~1;
+	ask_w &= ~1;
+	h &= ~1;
+	ask_h &= ~1;
+
+	if (flags & V4L2_SEL_FLAG_GE) {
+		if (w < ask_w)
+			val -= SCALING_GOODNESS;
+		if (h < ask_h)
+			val -= SCALING_GOODNESS;
+	}
+
+	if (flags & V4L2_SEL_FLAG_LE) {
+		if (w > ask_w)
+			val -= SCALING_GOODNESS;
+		if (h > ask_h)
+			val -= SCALING_GOODNESS;
+	}
+
+	val -= abs(w - ask_w);
+	val -= abs(h - ask_h);
+
+	if (w < sensor->limits[SMIAPP_LIMIT_MIN_X_OUTPUT_SIZE])
+		val -= SCALING_GOODNESS_EXTREME;
+
+	dev_dbg(&client->dev, "w %d ask_w %d h %d ask_h %d goodness %d\n",
+		w, ask_h, h, ask_h, val);
+
+	return val;
+}
+
+static void smiapp_set_compose_binner(struct v4l2_subdev *subdev,
+				      struct v4l2_subdev_fh *fh,
+				      struct v4l2_subdev_selection *sel,
+				      struct v4l2_rect **crops,
+				      struct v4l2_rect *comp)
+{
+	struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
+	unsigned int i;
+	unsigned int binh = 1, binv = 1;
+	unsigned int best = scaling_goodness(
+		subdev,
+		crops[SMIAPP_PAD_SINK]->width, sel->r.width,
+		crops[SMIAPP_PAD_SINK]->height, sel->r.height, sel->flags);
+
+	for (i = 0; i < sensor->nbinning_subtypes; i++) {
+		int this = scaling_goodness(
+			subdev,
+			crops[SMIAPP_PAD_SINK]->width
+			/ sensor->binning_subtypes[i].horizontal,
+			sel->r.width,
+			crops[SMIAPP_PAD_SINK]->height
+			/ sensor->binning_subtypes[i].vertical,
+			sel->r.height, sel->flags);
+
+		if (this > best) {
+			binh = sensor->binning_subtypes[i].horizontal;
+			binv = sensor->binning_subtypes[i].vertical;
+			best = this;
+		}
+	}
+	if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
+		sensor->binning_vertical = binv;
+		sensor->binning_horizontal = binh;
+	}
+
+	sel->r.width = (crops[SMIAPP_PAD_SINK]->width / binh) & ~1;
+	sel->r.height = (crops[SMIAPP_PAD_SINK]->height / binv) & ~1;
+}
+
+/*
+ * Calculate best scaling ratio and mode for given output resolution.
+ *
+ * Try all of these: horizontal ratio, vertical ratio and smallest
+ * size possible (horizontally).
+ *
+ * Also try whether horizontal scaler or full scaler gives a better
+ * result.
+ */
+static void smiapp_set_compose_scaler(struct v4l2_subdev *subdev,
+				      struct v4l2_subdev_fh *fh,
+				      struct v4l2_subdev_selection *sel,
+				      struct v4l2_rect **crops,
+				      struct v4l2_rect *comp)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(subdev);
+	struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
+	u32 min, max, a, b, max_m;
+	u32 scale_m = sensor->limits[SMIAPP_LIMIT_SCALER_N_MIN];
+	int mode = SMIAPP_SCALING_MODE_HORIZONTAL;
+	u32 try[4];
+	u32 ntry = 0;
+	unsigned int i;
+	int best = INT_MIN;
+
+	sel->r.width = min_t(unsigned int, sel->r.width,
+			     crops[SMIAPP_PAD_SINK]->width);
+	sel->r.height = min_t(unsigned int, sel->r.height,
+			      crops[SMIAPP_PAD_SINK]->height);
+
+	a = crops[SMIAPP_PAD_SINK]->width
+		* sensor->limits[SMIAPP_LIMIT_SCALER_N_MIN] / sel->r.width;
+	b = crops[SMIAPP_PAD_SINK]->height
+		* sensor->limits[SMIAPP_LIMIT_SCALER_N_MIN] / sel->r.height;
+	max_m = crops[SMIAPP_PAD_SINK]->width
+		* sensor->limits[SMIAPP_LIMIT_SCALER_N_MIN]
+		/ sensor->limits[SMIAPP_LIMIT_MIN_X_OUTPUT_SIZE];
+
+	a = min(sensor->limits[SMIAPP_LIMIT_SCALER_M_MAX],
+		max(a, sensor->limits[SMIAPP_LIMIT_SCALER_M_MIN]));
+	b = min(sensor->limits[SMIAPP_LIMIT_SCALER_M_MAX],
+		max(b, sensor->limits[SMIAPP_LIMIT_SCALER_M_MIN]));
+	max_m = min(sensor->limits[SMIAPP_LIMIT_SCALER_M_MAX],
+		    max(max_m, sensor->limits[SMIAPP_LIMIT_SCALER_M_MIN]));
+
+	dev_dbg(&client->dev, "scaling: a %d b %d max_m %d\n", a, b, max_m);
+
+	min = min(max_m, min(a, b));
+	max = min(max_m, max(a, b));
+
+	try[ntry] = min;
+	ntry++;
+	if (min != max) {
+		try[ntry] = max;
+		ntry++;
+	}
+	if (max != max_m) {
+		try[ntry] = min + 1;
+		ntry++;
+		if (min != max) {
+			try[ntry] = max + 1;
+			ntry++;
+		}
+	}
+
+	for (i = 0; i < ntry; i++) {
+		int this = scaling_goodness(
+			subdev,
+			crops[SMIAPP_PAD_SINK]->width
+			/ try[i]
+			* sensor->limits[SMIAPP_LIMIT_SCALER_N_MIN],
+			sel->r.width,
+			crops[SMIAPP_PAD_SINK]->height,
+			sel->r.height,
+			sel->flags);
+
+		dev_dbg(&client->dev, "trying factor %d (%d)\n", try[i], i);
+
+		if (this > best) {
+			scale_m = try[i];
+			mode = SMIAPP_SCALING_MODE_HORIZONTAL;
+			best = this;
+		}
+
+		if (sensor->limits[SMIAPP_LIMIT_SCALING_CAPABILITY]
+		    == SMIAPP_SCALING_CAPABILITY_HORIZONTAL)
+			continue;
+
+		this = scaling_goodness(
+			subdev, crops[SMIAPP_PAD_SINK]->width
+			/ try[i]
+			* sensor->limits[SMIAPP_LIMIT_SCALER_N_MIN],
+			sel->r.width,
+			crops[SMIAPP_PAD_SINK]->height
+			/ try[i]
+			* sensor->limits[SMIAPP_LIMIT_SCALER_N_MIN],
+			sel->r.height,
+			sel->flags);
+
+		if (this > best) {
+			scale_m = try[i];
+			mode = SMIAPP_SCALING_MODE_BOTH;
+			best = this;
+		}
+	}
+
+	sel->r.width =
+		(crops[SMIAPP_PAD_SINK]->width
+		 / scale_m
+		 * sensor->limits[SMIAPP_LIMIT_SCALER_N_MIN]) & ~1;
+	if (mode == SMIAPP_SCALING_MODE_BOTH)
+		sel->r.height =
+			(crops[SMIAPP_PAD_SINK]->height
+			 / scale_m
+			 * sensor->limits[SMIAPP_LIMIT_SCALER_N_MIN])
+			& ~1;
+	else
+		sel->r.height = crops[SMIAPP_PAD_SINK]->height;
+
+	if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
+		sensor->scale_m = scale_m;
+		sensor->scaling_mode = mode;
+	}
+}
+/* We're only called on source pads. This function sets scaling. */
+static int smiapp_set_compose(struct v4l2_subdev *subdev,
+			      struct v4l2_subdev_fh *fh,
+			      struct v4l2_subdev_selection *sel)
+{
+	struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
+	struct smiapp_subdev *ssd = to_smiapp_subdev(subdev);
+	struct v4l2_rect *comp, *crops[SMIAPP_PADS];
+
+	smiapp_get_crop_compose(subdev, fh, crops, &comp, sel->which);
+
+	sel->r.top = 0;
+	sel->r.left = 0;
+
+	if (ssd == sensor->binner)
+		smiapp_set_compose_binner(subdev, fh, sel, crops, comp);
+	else
+		smiapp_set_compose_scaler(subdev, fh, sel, crops, comp);
+
+	*comp = sel->r;
+	smiapp_propagate(subdev, fh, sel->which,
+			 V4L2_SEL_TGT_COMPOSE);
+
+	if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+		return smiapp_update_mode(sensor);
+
+	return 0;
+}
+
+static int __smiapp_sel_supported(struct v4l2_subdev *subdev,
+				  struct v4l2_subdev_selection *sel)
+{
+	struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
+	struct smiapp_subdev *ssd = to_smiapp_subdev(subdev);
+
+	/* We only implement crop in three places. */
+	switch (sel->target) {
+	case V4L2_SEL_TGT_CROP:
+	case V4L2_SEL_TGT_CROP_BOUNDS:
+		if (ssd == sensor->pixel_array
+		    && sel->pad == SMIAPP_PA_PAD_SRC)
+			return 0;
+		if (ssd == sensor->src
+		    && sel->pad == SMIAPP_PAD_SRC)
+			return 0;
+		if (ssd == sensor->scaler
+		    && sel->pad == SMIAPP_PAD_SINK
+		    && sensor->limits[SMIAPP_LIMIT_DIGITAL_CROP_CAPABILITY]
+		    == SMIAPP_DIGITAL_CROP_CAPABILITY_INPUT_CROP)
+			return 0;
+		return -EINVAL;
+	case V4L2_SEL_TGT_COMPOSE:
+	case V4L2_SEL_TGT_COMPOSE_BOUNDS:
+		if (sel->pad == ssd->source_pad)
+			return -EINVAL;
+		if (ssd == sensor->binner)
+			return 0;
+		if (ssd == sensor->scaler
+		    && sensor->limits[SMIAPP_LIMIT_SCALING_CAPABILITY]
+		    != SMIAPP_SCALING_CAPABILITY_NONE)
+			return 0;
+		/* Fall through */
+	default:
+		return -EINVAL;
+	}
+}
+
+static int smiapp_set_crop(struct v4l2_subdev *subdev,
+			   struct v4l2_subdev_fh *fh,
+			   struct v4l2_subdev_selection *sel)
+{
+	struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
+	struct smiapp_subdev *ssd = to_smiapp_subdev(subdev);
+	struct v4l2_rect *src_size, *crops[SMIAPP_PADS];
+	struct v4l2_rect _r;
+
+	smiapp_get_crop_compose(subdev, fh, crops, NULL, sel->which);
+
+	if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
+		if (sel->pad == ssd->sink_pad)
+			src_size = &ssd->sink_fmt;
+		else
+			src_size = &ssd->compose;
+	} else {
+		if (sel->pad == ssd->sink_pad) {
+			_r.left = 0;
+			_r.top = 0;
+			_r.width = v4l2_subdev_get_try_format(fh, sel->pad)
+				->width;
+			_r.height = v4l2_subdev_get_try_format(fh, sel->pad)
+				->height;
+			src_size = &_r;
+		} else {
+			src_size =
+				v4l2_subdev_get_try_compose(
+					fh, ssd->sink_pad);
+		}
+	}
+
+	if (ssd == sensor->src && sel->pad == SMIAPP_PAD_SRC) {
+		sel->r.left = 0;
+		sel->r.top = 0;
+	}
+
+	sel->r.width = min(sel->r.width, src_size->width);
+	sel->r.height = min(sel->r.height, src_size->height);
+
+	sel->r.left = min(sel->r.left, src_size->width - sel->r.width);
+	sel->r.top = min(sel->r.top, src_size->height - sel->r.height);
+
+	*crops[sel->pad] = sel->r;
+
+	if (ssd != sensor->pixel_array && sel->pad == SMIAPP_PAD_SINK)
+		smiapp_propagate(subdev, fh, sel->which,
+				 V4L2_SEL_TGT_CROP);
+
+	return 0;
+}
+
+static int __smiapp_get_selection(struct v4l2_subdev *subdev,
+				  struct v4l2_subdev_fh *fh,
+				  struct v4l2_subdev_selection *sel)
+{
+	struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
+	struct smiapp_subdev *ssd = to_smiapp_subdev(subdev);
+	struct v4l2_rect *comp, *crops[SMIAPP_PADS];
+	struct v4l2_rect sink_fmt;
+	int ret;
+
+	ret = __smiapp_sel_supported(subdev, sel);
+	if (ret)
+		return ret;
+
+	smiapp_get_crop_compose(subdev, fh, crops, &comp, sel->which);
+
+	if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
+		sink_fmt = ssd->sink_fmt;
+	} else {
+		struct v4l2_mbus_framefmt *fmt =
+			v4l2_subdev_get_try_format(fh, ssd->sink_pad);
+
+		sink_fmt.left = 0;
+		sink_fmt.top = 0;
+		sink_fmt.width = fmt->width;
+		sink_fmt.height = fmt->height;
+	}
+
+	switch (sel->target) {
+	case V4L2_SEL_TGT_CROP_BOUNDS:
+		if (ssd == sensor->pixel_array) {
+			sel->r.width =
+				sensor->limits[SMIAPP_LIMIT_X_ADDR_MAX] + 1;
+			sel->r.height =
+				sensor->limits[SMIAPP_LIMIT_Y_ADDR_MAX] + 1;
+		} else if (sel->pad == ssd->sink_pad) {
+			sel->r = sink_fmt;
+		} else {
+			sel->r = *comp;
+		}
+		break;
+	case V4L2_SEL_TGT_CROP:
+	case V4L2_SEL_TGT_COMPOSE_BOUNDS:
+		sel->r = *crops[sel->pad];
+		break;
+	case V4L2_SEL_TGT_COMPOSE:
+		sel->r = *comp;
+		break;
+	}
+
+	return 0;
+}
+
+static int smiapp_get_selection(struct v4l2_subdev *subdev,
+				struct v4l2_subdev_fh *fh,
+				struct v4l2_subdev_selection *sel)
+{
+	struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
+	int rval;
+
+	mutex_lock(&sensor->mutex);
+	rval = __smiapp_get_selection(subdev, fh, sel);
+	mutex_unlock(&sensor->mutex);
+
+	return rval;
+}
+static int smiapp_set_selection(struct v4l2_subdev *subdev,
+				struct v4l2_subdev_fh *fh,
+				struct v4l2_subdev_selection *sel)
+{
+	struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
+	int ret;
+
+	ret = __smiapp_sel_supported(subdev, sel);
+	if (ret)
+		return ret;
+
+	mutex_lock(&sensor->mutex);
+
+	sel->r.left = max(0, sel->r.left & ~1);
+	sel->r.top = max(0, sel->r.top & ~1);
+	sel->r.width = max(0, SMIAPP_ALIGN_DIM(sel->r.width, sel->flags));
+	sel->r.height = max(0, SMIAPP_ALIGN_DIM(sel->r.height, sel->flags));
+
+	sel->r.width = max_t(unsigned int,
+			     sensor->limits[SMIAPP_LIMIT_MIN_X_OUTPUT_SIZE],
+			     sel->r.width);
+	sel->r.height = max_t(unsigned int,
+			      sensor->limits[SMIAPP_LIMIT_MIN_Y_OUTPUT_SIZE],
+			      sel->r.height);
+
+	switch (sel->target) {
+	case V4L2_SEL_TGT_CROP:
+		ret = smiapp_set_crop(subdev, fh, sel);
+		break;
+	case V4L2_SEL_TGT_COMPOSE:
+		ret = smiapp_set_compose(subdev, fh, sel);
+		break;
+	default:
+		BUG();
+	}
+
+	mutex_unlock(&sensor->mutex);
+	return ret;
+}
+
+static int smiapp_get_skip_frames(struct v4l2_subdev *subdev, u32 *frames)
+{
+	struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
+
+	*frames = sensor->frame_skip;
+	return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * sysfs attributes
+ */
+
+static ssize_t
+smiapp_sysfs_nvm_read(struct device *dev, struct device_attribute *attr,
+		      char *buf)
+{
+	struct v4l2_subdev *subdev = i2c_get_clientdata(to_i2c_client(dev));
+	struct i2c_client *client = v4l2_get_subdevdata(subdev);
+	struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
+	unsigned int nbytes;
+
+	if (!sensor->dev_init_done)
+		return -EBUSY;
+
+	if (!sensor->nvm_size) {
+		/* NVM not read yet - read it now */
+		sensor->nvm_size = sensor->platform_data->nvm_size;
+		if (smiapp_set_power(subdev, 1) < 0)
+			return -ENODEV;
+		if (smiapp_read_nvm(sensor, sensor->nvm)) {
+			dev_err(&client->dev, "nvm read failed\n");
+			return -ENODEV;
+		}
+		smiapp_set_power(subdev, 0);
+	}
+	/*
+	 * NVM is still way below a PAGE_SIZE, so we can safely
+	 * assume this for now.
+	 */
+	nbytes = min_t(unsigned int, sensor->nvm_size, PAGE_SIZE);
+	memcpy(buf, sensor->nvm, nbytes);
+
+	return nbytes;
+}
+static DEVICE_ATTR(nvm, S_IRUGO, smiapp_sysfs_nvm_read, NULL);
+
+/* -----------------------------------------------------------------------------
+ * V4L2 subdev core operations
+ */
+
+static int smiapp_identify_module(struct v4l2_subdev *subdev)
+{
+	struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
+	struct i2c_client *client = v4l2_get_subdevdata(subdev);
+	struct smiapp_module_info *minfo = &sensor->minfo;
+	unsigned int i;
+	int rval = 0;
+
+	minfo->name = SMIAPP_NAME;
+
+	/* Module info */
+	rval = smiapp_read_8only(sensor, SMIAPP_REG_U8_MANUFACTURER_ID,
+				 &minfo->manufacturer_id);
+	if (!rval)
+		rval = smiapp_read_8only(sensor, SMIAPP_REG_U16_MODEL_ID,
+					 &minfo->model_id);
+	if (!rval)
+		rval = smiapp_read_8only(sensor,
+					 SMIAPP_REG_U8_REVISION_NUMBER_MAJOR,
+					 &minfo->revision_number_major);
+	if (!rval)
+		rval = smiapp_read_8only(sensor,
+					 SMIAPP_REG_U8_REVISION_NUMBER_MINOR,
+					 &minfo->revision_number_minor);
+	if (!rval)
+		rval = smiapp_read_8only(sensor,
+					 SMIAPP_REG_U8_MODULE_DATE_YEAR,
+					 &minfo->module_year);
+	if (!rval)
+		rval = smiapp_read_8only(sensor,
+					 SMIAPP_REG_U8_MODULE_DATE_MONTH,
+					 &minfo->module_month);
+	if (!rval)
+		rval = smiapp_read_8only(sensor, SMIAPP_REG_U8_MODULE_DATE_DAY,
+					 &minfo->module_day);
+
+	/* Sensor info */
+	if (!rval)
+		rval = smiapp_read_8only(sensor,
+					 SMIAPP_REG_U8_SENSOR_MANUFACTURER_ID,
+					 &minfo->sensor_manufacturer_id);
+	if (!rval)
+		rval = smiapp_read_8only(sensor,
+					 SMIAPP_REG_U16_SENSOR_MODEL_ID,
+					 &minfo->sensor_model_id);
+	if (!rval)
+		rval = smiapp_read_8only(sensor,
+					 SMIAPP_REG_U8_SENSOR_REVISION_NUMBER,
+					 &minfo->sensor_revision_number);
+	if (!rval)
+		rval = smiapp_read_8only(sensor,
+					 SMIAPP_REG_U8_SENSOR_FIRMWARE_VERSION,
+					 &minfo->sensor_firmware_version);
+
+	/* SMIA */
+	if (!rval)
+		rval = smiapp_read_8only(sensor, SMIAPP_REG_U8_SMIA_VERSION,
+					 &minfo->smia_version);
+	if (!rval)
+		rval = smiapp_read_8only(sensor, SMIAPP_REG_U8_SMIAPP_VERSION,
+					 &minfo->smiapp_version);
+
+	if (rval) {
+		dev_err(&client->dev, "sensor detection failed\n");
+		return -ENODEV;
+	}
+
+	dev_dbg(&client->dev, "module 0x%2.2x-0x%4.4x\n",
+		minfo->manufacturer_id, minfo->model_id);
+
+	dev_dbg(&client->dev,
+		"module revision 0x%2.2x-0x%2.2x date %2.2d-%2.2d-%2.2d\n",
+		minfo->revision_number_major, minfo->revision_number_minor,
+		minfo->module_year, minfo->module_month, minfo->module_day);
+
+	dev_dbg(&client->dev, "sensor 0x%2.2x-0x%4.4x\n",
+		minfo->sensor_manufacturer_id, minfo->sensor_model_id);
+
+	dev_dbg(&client->dev,
+		"sensor revision 0x%2.2x firmware version 0x%2.2x\n",
+		minfo->sensor_revision_number, minfo->sensor_firmware_version);
+
+	dev_dbg(&client->dev, "smia version %2.2d smiapp version %2.2d\n",
+		minfo->smia_version, minfo->smiapp_version);
+
+	/*
+	 * Some modules have bad data in the lvalues below. Hope the
+	 * rvalues have better stuff. The lvalues are module
+	 * parameters whereas the rvalues are sensor parameters.
+	 */
+	if (!minfo->manufacturer_id && !minfo->model_id) {
+		minfo->manufacturer_id = minfo->sensor_manufacturer_id;
+		minfo->model_id = minfo->sensor_model_id;
+		minfo->revision_number_major = minfo->sensor_revision_number;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(smiapp_module_idents); i++) {
+		if (smiapp_module_idents[i].manufacturer_id
+		    != minfo->manufacturer_id)
+			continue;
+		if (smiapp_module_idents[i].model_id != minfo->model_id)
+			continue;
+		if (smiapp_module_idents[i].flags
+		    & SMIAPP_MODULE_IDENT_FLAG_REV_LE) {
+			if (smiapp_module_idents[i].revision_number_major
+			    < minfo->revision_number_major)
+				continue;
+		} else {
+			if (smiapp_module_idents[i].revision_number_major
+			    != minfo->revision_number_major)
+				continue;
+		}
+
+		minfo->name = smiapp_module_idents[i].name;
+		minfo->quirk = smiapp_module_idents[i].quirk;
+		break;
+	}
+
+	if (i >= ARRAY_SIZE(smiapp_module_idents))
+		dev_warn(&client->dev,
+			 "no quirks for this module; let's hope it's fully compliant\n");
+
+	dev_dbg(&client->dev, "the sensor is called %s, ident %2.2x%4.4x%2.2x\n",
+		minfo->name, minfo->manufacturer_id, minfo->model_id,
+		minfo->revision_number_major);
+
+	strlcpy(subdev->name, sensor->minfo.name, sizeof(subdev->name));
+
+	return 0;
+}
+
+static const struct v4l2_subdev_ops smiapp_ops;
+static const struct v4l2_subdev_internal_ops smiapp_internal_ops;
+static const struct media_entity_operations smiapp_entity_ops;
+
+static int smiapp_registered(struct v4l2_subdev *subdev)
+{
+	struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
+	struct i2c_client *client = v4l2_get_subdevdata(subdev);
+	struct smiapp_subdev *last = NULL;
+	u32 tmp;
+	unsigned int i;
+	int rval;
+
+	sensor->vana = regulator_get(&client->dev, "VANA");
+	if (IS_ERR(sensor->vana)) {
+		dev_err(&client->dev, "could not get regulator for vana\n");
+		return -ENODEV;
+	}
+
+	if (!sensor->platform_data->set_xclk) {
+		sensor->ext_clk = clk_get(&client->dev,
+					  sensor->platform_data->ext_clk_name);
+		if (IS_ERR(sensor->ext_clk)) {
+			dev_err(&client->dev, "could not get clock %s\n",
+				sensor->platform_data->ext_clk_name);
+			rval = -ENODEV;
+			goto out_clk_get;
+		}
+
+		rval = clk_set_rate(sensor->ext_clk,
+				    sensor->platform_data->ext_clk);
+		if (rval < 0) {
+			dev_err(&client->dev,
+				"unable to set clock %s freq to %u\n",
+				sensor->platform_data->ext_clk_name,
+				sensor->platform_data->ext_clk);
+			rval = -ENODEV;
+			goto out_clk_set_rate;
+		}
+	}
+
+	if (sensor->platform_data->xshutdown != SMIAPP_NO_XSHUTDOWN) {
+		if (gpio_request_one(sensor->platform_data->xshutdown, 0,
+				     "SMIA++ xshutdown") != 0) {
+			dev_err(&client->dev,
+				"unable to acquire reset gpio %d\n",
+				sensor->platform_data->xshutdown);
+			rval = -ENODEV;
+			goto out_clk_set_rate;
+		}
+	}
+
+	rval = smiapp_power_on(sensor);
+	if (rval) {
+		rval = -ENODEV;
+		goto out_smiapp_power_on;
+	}
+
+	rval = smiapp_identify_module(subdev);
+	if (rval) {
+		rval = -ENODEV;
+		goto out_power_off;
+	}
+
+	rval = smiapp_get_all_limits(sensor);
+	if (rval) {
+		rval = -ENODEV;
+		goto out_power_off;
+	}
+
+	/*
+	 * Handle Sensor Module orientation on the board.
+	 *
+	 * The application of H-FLIP and V-FLIP on the sensor is modified by
+	 * the sensor orientation on the board.
+	 *
+	 * For SMIAPP_BOARD_SENSOR_ORIENT_180 the default behaviour is to set
+	 * both H-FLIP and V-FLIP for normal operation which also implies
+	 * that a set/unset operation for user space HFLIP and VFLIP v4l2
+	 * controls will need to be internally inverted.
+	 *
+	 * Rotation also changes the bayer pattern.
+	 */
+	if (sensor->platform_data->module_board_orient ==
+	    SMIAPP_MODULE_BOARD_ORIENT_180)
+		sensor->hvflip_inv_mask = SMIAPP_IMAGE_ORIENTATION_HFLIP |
+					  SMIAPP_IMAGE_ORIENTATION_VFLIP;
+
+	rval = smiapp_get_mbus_formats(sensor);
+	if (rval) {
+		rval = -ENODEV;
+		goto out_power_off;
+	}
+
+	if (sensor->limits[SMIAPP_LIMIT_BINNING_CAPABILITY]) {
+		u32 val;
+
+		rval = smiapp_read(sensor,
+				   SMIAPP_REG_U8_BINNING_SUBTYPES, &val);
+		if (rval < 0) {
+			rval = -ENODEV;
+			goto out_power_off;
+		}
+		sensor->nbinning_subtypes = min_t(u8, val,
+						  SMIAPP_BINNING_SUBTYPES);
+
+		for (i = 0; i < sensor->nbinning_subtypes; i++) {
+			rval = smiapp_read(
+				sensor, SMIAPP_REG_U8_BINNING_TYPE_n(i), &val);
+			if (rval < 0) {
+				rval = -ENODEV;
+				goto out_power_off;
+			}
+			sensor->binning_subtypes[i] =
+				*(struct smiapp_binning_subtype *)&val;
+
+			dev_dbg(&client->dev, "binning %xx%x\n",
+				sensor->binning_subtypes[i].horizontal,
+				sensor->binning_subtypes[i].vertical);
+		}
+	}
+	sensor->binning_horizontal = 1;
+	sensor->binning_vertical = 1;
+
+	/* SMIA++ NVM initialization - it will be read from the sensor
+	 * when it is first requested by userspace.
+	 */
+	if (sensor->minfo.smiapp_version && sensor->platform_data->nvm_size) {
+		sensor->nvm = kzalloc(sensor->platform_data->nvm_size,
+				      GFP_KERNEL);
+		if (sensor->nvm == NULL) {
+			dev_err(&client->dev, "nvm buf allocation failed\n");
+			rval = -ENOMEM;
+			goto out_power_off;
+		}
+
+		if (device_create_file(&client->dev, &dev_attr_nvm) != 0) {
+			dev_err(&client->dev, "sysfs nvm entry failed\n");
+			rval = -EBUSY;
+			goto out_power_off;
+		}
+	}
+
+	rval = smiapp_call_quirk(sensor, limits);
+	if (rval) {
+		dev_err(&client->dev, "limits quirks failed\n");
+		goto out_nvm_release;
+	}
+
+	/* We consider this as profile 0 sensor if any of these are zero. */
+	if (!sensor->limits[SMIAPP_LIMIT_MIN_OP_SYS_CLK_DIV] ||
+	    !sensor->limits[SMIAPP_LIMIT_MAX_OP_SYS_CLK_DIV] ||
+	    !sensor->limits[SMIAPP_LIMIT_MIN_OP_PIX_CLK_DIV] ||
+	    !sensor->limits[SMIAPP_LIMIT_MAX_OP_PIX_CLK_DIV]) {
+		sensor->minfo.smiapp_profile = SMIAPP_PROFILE_0;
+	} else if (sensor->limits[SMIAPP_LIMIT_SCALING_CAPABILITY]
+		   != SMIAPP_SCALING_CAPABILITY_NONE) {
+		if (sensor->limits[SMIAPP_LIMIT_SCALING_CAPABILITY]
+		    == SMIAPP_SCALING_CAPABILITY_HORIZONTAL)
+			sensor->minfo.smiapp_profile = SMIAPP_PROFILE_1;
+		else
+			sensor->minfo.smiapp_profile = SMIAPP_PROFILE_2;
+		sensor->scaler = &sensor->ssds[sensor->ssds_used];
+		sensor->ssds_used++;
+	} else if (sensor->limits[SMIAPP_LIMIT_DIGITAL_CROP_CAPABILITY]
+		   == SMIAPP_DIGITAL_CROP_CAPABILITY_INPUT_CROP) {
+		sensor->scaler = &sensor->ssds[sensor->ssds_used];
+		sensor->ssds_used++;
+	}
+	sensor->binner = &sensor->ssds[sensor->ssds_used];
+	sensor->ssds_used++;
+	sensor->pixel_array = &sensor->ssds[sensor->ssds_used];
+	sensor->ssds_used++;
+
+	sensor->scale_m = sensor->limits[SMIAPP_LIMIT_SCALER_N_MIN];
+
+	for (i = 0; i < SMIAPP_SUBDEVS; i++) {
+		struct {
+			struct smiapp_subdev *ssd;
+			char *name;
+		} const __this[] = {
+			{ sensor->scaler, "scaler", },
+			{ sensor->binner, "binner", },
+			{ sensor->pixel_array, "pixel array", },
+		}, *_this = &__this[i];
+		struct smiapp_subdev *this = _this->ssd;
+
+		if (!this)
+			continue;
+
+		if (this != sensor->src)
+			v4l2_subdev_init(&this->sd, &smiapp_ops);
+
+		this->sensor = sensor;
+
+		if (this == sensor->pixel_array) {
+			this->npads = 1;
+		} else {
+			this->npads = 2;
+			this->source_pad = 1;
+		}
+
+		snprintf(this->sd.name,
+			 sizeof(this->sd.name), "%s %s",
+			 sensor->minfo.name, _this->name);
+
+		this->sink_fmt.width =
+			sensor->limits[SMIAPP_LIMIT_X_ADDR_MAX] + 1;
+		this->sink_fmt.height =
+			sensor->limits[SMIAPP_LIMIT_Y_ADDR_MAX] + 1;
+		this->compose.width = this->sink_fmt.width;
+		this->compose.height = this->sink_fmt.height;
+		this->crop[this->source_pad] = this->compose;
+		this->pads[this->source_pad].flags = MEDIA_PAD_FL_SOURCE;
+		if (this != sensor->pixel_array) {
+			this->crop[this->sink_pad] = this->compose;
+			this->pads[this->sink_pad].flags = MEDIA_PAD_FL_SINK;
+		}
+
+		this->sd.entity.ops = &smiapp_entity_ops;
+
+		if (last == NULL) {
+			last = this;
+			continue;
+		}
+
+		this->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+		this->sd.internal_ops = &smiapp_internal_ops;
+		this->sd.owner = NULL;
+		v4l2_set_subdevdata(&this->sd, client);
+
+		rval = media_entity_init(&this->sd.entity,
+					 this->npads, this->pads, 0);
+		if (rval) {
+			dev_err(&client->dev,
+				"media_entity_init failed\n");
+			goto out_nvm_release;
+		}
+
+		rval = media_entity_create_link(&this->sd.entity,
+						this->source_pad,
+						&last->sd.entity,
+						last->sink_pad,
+						MEDIA_LNK_FL_ENABLED |
+						MEDIA_LNK_FL_IMMUTABLE);
+		if (rval) {
+			dev_err(&client->dev,
+				"media_entity_create_link failed\n");
+			goto out_nvm_release;
+		}
+
+		rval = v4l2_device_register_subdev(sensor->src->sd.v4l2_dev,
+						   &this->sd);
+		if (rval) {
+			dev_err(&client->dev,
+				"v4l2_device_register_subdev failed\n");
+			goto out_nvm_release;
+		}
+
+		last = this;
+	}
+
+	dev_dbg(&client->dev, "profile %d\n", sensor->minfo.smiapp_profile);
+
+	sensor->pixel_array->sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR;
+
+	/* final steps */
+	smiapp_read_frame_fmt(sensor);
+	rval = smiapp_init_controls(sensor);
+	if (rval < 0)
+		goto out_nvm_release;
+
+	rval = smiapp_update_mode(sensor);
+	if (rval) {
+		dev_err(&client->dev, "update mode failed\n");
+		goto out_nvm_release;
+	}
+
+	sensor->streaming = false;
+	sensor->dev_init_done = true;
+
+	/* check flash capability */
+	rval = smiapp_read(sensor, SMIAPP_REG_U8_FLASH_MODE_CAPABILITY, &tmp);
+	sensor->flash_capability = tmp;
+	if (rval)
+		goto out_nvm_release;
+
+	smiapp_power_off(sensor);
+
+	return 0;
+
+out_nvm_release:
+	device_remove_file(&client->dev, &dev_attr_nvm);
+
+out_power_off:
+	kfree(sensor->nvm);
+	sensor->nvm = NULL;
+	smiapp_power_off(sensor);
+
+out_smiapp_power_on:
+	if (sensor->platform_data->xshutdown != SMIAPP_NO_XSHUTDOWN)
+		gpio_free(sensor->platform_data->xshutdown);
+
+out_clk_set_rate:
+	clk_put(sensor->ext_clk);
+	sensor->ext_clk = NULL;
+
+out_clk_get:
+	regulator_put(sensor->vana);
+	sensor->vana = NULL;
+	return rval;
+}
+
+static int smiapp_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+	struct smiapp_subdev *ssd = to_smiapp_subdev(sd);
+	struct smiapp_sensor *sensor = ssd->sensor;
+	u32 mbus_code =
+		smiapp_csi_data_formats[smiapp_pixel_order(sensor)].code;
+	unsigned int i;
+
+	mutex_lock(&sensor->mutex);
+
+	for (i = 0; i < ssd->npads; i++) {
+		struct v4l2_mbus_framefmt *try_fmt =
+			v4l2_subdev_get_try_format(fh, i);
+		struct v4l2_rect *try_crop = v4l2_subdev_get_try_crop(fh, i);
+		struct v4l2_rect *try_comp;
+
+		try_fmt->width = sensor->limits[SMIAPP_LIMIT_X_ADDR_MAX] + 1;
+		try_fmt->height = sensor->limits[SMIAPP_LIMIT_Y_ADDR_MAX] + 1;
+		try_fmt->code = mbus_code;
+
+		try_crop->top = 0;
+		try_crop->left = 0;
+		try_crop->width = try_fmt->width;
+		try_crop->height = try_fmt->height;
+
+		if (ssd != sensor->pixel_array)
+			continue;
+
+		try_comp = v4l2_subdev_get_try_compose(fh, i);
+		*try_comp = *try_crop;
+	}
+
+	mutex_unlock(&sensor->mutex);
+
+	return smiapp_set_power(sd, 1);
+}
+
+static int smiapp_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+	return smiapp_set_power(sd, 0);
+}
+
+static const struct v4l2_subdev_video_ops smiapp_video_ops = {
+	.s_stream = smiapp_set_stream,
+};
+
+static const struct v4l2_subdev_core_ops smiapp_core_ops = {
+	.s_power = smiapp_set_power,
+};
+
+static const struct v4l2_subdev_pad_ops smiapp_pad_ops = {
+	.enum_mbus_code = smiapp_enum_mbus_code,
+	.get_fmt = smiapp_get_format,
+	.set_fmt = smiapp_set_format,
+	.get_selection = smiapp_get_selection,
+	.set_selection = smiapp_set_selection,
+};
+
+static const struct v4l2_subdev_sensor_ops smiapp_sensor_ops = {
+	.g_skip_frames = smiapp_get_skip_frames,
+};
+
+static const struct v4l2_subdev_ops smiapp_ops = {
+	.core = &smiapp_core_ops,
+	.video = &smiapp_video_ops,
+	.pad = &smiapp_pad_ops,
+	.sensor = &smiapp_sensor_ops,
+};
+
+static const struct media_entity_operations smiapp_entity_ops = {
+	.link_validate = v4l2_subdev_link_validate,
+};
+
+static const struct v4l2_subdev_internal_ops smiapp_internal_src_ops = {
+	.registered = smiapp_registered,
+	.open = smiapp_open,
+	.close = smiapp_close,
+};
+
+static const struct v4l2_subdev_internal_ops smiapp_internal_ops = {
+	.open = smiapp_open,
+	.close = smiapp_close,
+};
+
+/* -----------------------------------------------------------------------------
+ * I2C Driver
+ */
+
+#ifdef CONFIG_PM
+
+static int smiapp_suspend(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct v4l2_subdev *subdev = i2c_get_clientdata(client);
+	struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
+	bool streaming;
+
+	BUG_ON(mutex_is_locked(&sensor->mutex));
+
+	if (sensor->power_count == 0)
+		return 0;
+
+	if (sensor->streaming)
+		smiapp_stop_streaming(sensor);
+
+	streaming = sensor->streaming;
+
+	smiapp_power_off(sensor);
+
+	/* save state for resume */
+	sensor->streaming = streaming;
+
+	return 0;
+}
+
+static int smiapp_resume(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct v4l2_subdev *subdev = i2c_get_clientdata(client);
+	struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
+	int rval;
+
+	if (sensor->power_count == 0)
+		return 0;
+
+	rval = smiapp_power_on(sensor);
+	if (rval)
+		return rval;
+
+	if (sensor->streaming)
+		rval = smiapp_start_streaming(sensor);
+
+	return rval;
+}
+
+#else
+
+#define smiapp_suspend	NULL
+#define smiapp_resume	NULL
+
+#endif /* CONFIG_PM */
+
+static int smiapp_probe(struct i2c_client *client,
+			const struct i2c_device_id *devid)
+{
+	struct smiapp_sensor *sensor;
+	int rval;
+
+	if (client->dev.platform_data == NULL)
+		return -ENODEV;
+
+	sensor = kzalloc(sizeof(*sensor), GFP_KERNEL);
+	if (sensor == NULL)
+		return -ENOMEM;
+
+	sensor->platform_data = client->dev.platform_data;
+	mutex_init(&sensor->mutex);
+	mutex_init(&sensor->power_mutex);
+	sensor->src = &sensor->ssds[sensor->ssds_used];
+
+	v4l2_i2c_subdev_init(&sensor->src->sd, client, &smiapp_ops);
+	sensor->src->sd.internal_ops = &smiapp_internal_src_ops;
+	sensor->src->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+	sensor->src->sensor = sensor;
+
+	sensor->src->pads[0].flags = MEDIA_PAD_FL_SOURCE;
+	rval = media_entity_init(&sensor->src->sd.entity, 2,
+				 sensor->src->pads, 0);
+	if (rval < 0)
+		kfree(sensor);
+
+	return rval;
+}
+
+static int __exit smiapp_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *subdev = i2c_get_clientdata(client);
+	struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
+	unsigned int i;
+
+	if (sensor->power_count) {
+		if (sensor->platform_data->xshutdown != SMIAPP_NO_XSHUTDOWN)
+			gpio_set_value(sensor->platform_data->xshutdown, 0);
+		if (sensor->platform_data->set_xclk)
+			sensor->platform_data->set_xclk(&sensor->src->sd, 0);
+		else
+			clk_disable(sensor->ext_clk);
+		sensor->power_count = 0;
+	}
+
+	if (sensor->nvm) {
+		device_remove_file(&client->dev, &dev_attr_nvm);
+		kfree(sensor->nvm);
+	}
+
+	for (i = 0; i < sensor->ssds_used; i++) {
+		media_entity_cleanup(&sensor->ssds[i].sd.entity);
+		v4l2_device_unregister_subdev(&sensor->ssds[i].sd);
+	}
+	smiapp_free_controls(sensor);
+	if (sensor->platform_data->xshutdown != SMIAPP_NO_XSHUTDOWN)
+		gpio_free(sensor->platform_data->xshutdown);
+	if (sensor->ext_clk)
+		clk_put(sensor->ext_clk);
+	if (sensor->vana)
+		regulator_put(sensor->vana);
+
+	kfree(sensor);
+
+	return 0;
+}
+
+static const struct i2c_device_id smiapp_id_table[] = {
+	{ SMIAPP_NAME, 0 },
+	{ },
+};
+MODULE_DEVICE_TABLE(i2c, smiapp_id_table);
+
+static const struct dev_pm_ops smiapp_pm_ops = {
+	.suspend	= smiapp_suspend,
+	.resume		= smiapp_resume,
+};
+
+static struct i2c_driver smiapp_i2c_driver = {
+	.driver	= {
+		.name = SMIAPP_NAME,
+		.pm = &smiapp_pm_ops,
+	},
+	.probe	= smiapp_probe,
+	.remove	= __exit_p(smiapp_remove),
+	.id_table = smiapp_id_table,
+};
+
+module_i2c_driver(smiapp_i2c_driver);
+
+MODULE_AUTHOR("Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>");
+MODULE_DESCRIPTION("Generic SMIA/SMIA++ camera module driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/i2c/smiapp/smiapp-limits.c b/drivers/media/i2c/smiapp/smiapp-limits.c
new file mode 100644
index 0000000..fb2f81a
--- /dev/null
+++ b/drivers/media/i2c/smiapp/smiapp-limits.c
@@ -0,0 +1,132 @@
+/*
+ * drivers/media/i2c/smiapp/smiapp-limits.c
+ *
+ * Generic driver for SMIA/SMIA++ compliant camera modules
+ *
+ * Copyright (C) 2011--2012 Nokia Corporation
+ * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include "smiapp.h"
+
+struct smiapp_reg_limits smiapp_reg_limits[] = {
+	{ SMIAPP_REG_U16_ANALOGUE_GAIN_CAPABILITY, "analogue_gain_capability" }, /* 0 */
+	{ SMIAPP_REG_U16_ANALOGUE_GAIN_CODE_MIN, "analogue_gain_code_min" },
+	{ SMIAPP_REG_U16_ANALOGUE_GAIN_CODE_MAX, "analogue_gain_code_max" },
+	{ SMIAPP_REG_U8_THS_ZERO_MIN, "ths_zero_min" },
+	{ SMIAPP_REG_U8_TCLK_TRAIL_MIN, "tclk_trail_min" },
+	{ SMIAPP_REG_U16_INTEGRATION_TIME_CAPABILITY, "integration_time_capability" }, /* 5 */
+	{ SMIAPP_REG_U16_COARSE_INTEGRATION_TIME_MIN, "coarse_integration_time_min" },
+	{ SMIAPP_REG_U16_COARSE_INTEGRATION_TIME_MAX_MARGIN, "coarse_integration_time_max_margin" },
+	{ SMIAPP_REG_U16_FINE_INTEGRATION_TIME_MIN, "fine_integration_time_min" },
+	{ SMIAPP_REG_U16_FINE_INTEGRATION_TIME_MAX_MARGIN, "fine_integration_time_max_margin" },
+	{ SMIAPP_REG_U16_DIGITAL_GAIN_CAPABILITY, "digital_gain_capability" }, /* 10 */
+	{ SMIAPP_REG_U16_DIGITAL_GAIN_MIN, "digital_gain_min" },
+	{ SMIAPP_REG_U16_DIGITAL_GAIN_MAX, "digital_gain_max" },
+	{ SMIAPP_REG_F32_MIN_EXT_CLK_FREQ_HZ, "min_ext_clk_freq_hz" },
+	{ SMIAPP_REG_F32_MAX_EXT_CLK_FREQ_HZ, "max_ext_clk_freq_hz" },
+	{ SMIAPP_REG_U16_MIN_PRE_PLL_CLK_DIV, "min_pre_pll_clk_div" }, /* 15 */
+	{ SMIAPP_REG_U16_MAX_PRE_PLL_CLK_DIV, "max_pre_pll_clk_div" },
+	{ SMIAPP_REG_F32_MIN_PLL_IP_FREQ_HZ, "min_pll_ip_freq_hz" },
+	{ SMIAPP_REG_F32_MAX_PLL_IP_FREQ_HZ, "max_pll_ip_freq_hz" },
+	{ SMIAPP_REG_U16_MIN_PLL_MULTIPLIER, "min_pll_multiplier" },
+	{ SMIAPP_REG_U16_MAX_PLL_MULTIPLIER, "max_pll_multiplier" }, /* 20 */
+	{ SMIAPP_REG_F32_MIN_PLL_OP_FREQ_HZ, "min_pll_op_freq_hz" },
+	{ SMIAPP_REG_F32_MAX_PLL_OP_FREQ_HZ, "max_pll_op_freq_hz" },
+	{ SMIAPP_REG_U16_MIN_VT_SYS_CLK_DIV, "min_vt_sys_clk_div" },
+	{ SMIAPP_REG_U16_MAX_VT_SYS_CLK_DIV, "max_vt_sys_clk_div" },
+	{ SMIAPP_REG_F32_MIN_VT_SYS_CLK_FREQ_HZ, "min_vt_sys_clk_freq_hz" }, /* 25 */
+	{ SMIAPP_REG_F32_MAX_VT_SYS_CLK_FREQ_HZ, "max_vt_sys_clk_freq_hz" },
+	{ SMIAPP_REG_F32_MIN_VT_PIX_CLK_FREQ_HZ, "min_vt_pix_clk_freq_hz" },
+	{ SMIAPP_REG_F32_MAX_VT_PIX_CLK_FREQ_HZ, "max_vt_pix_clk_freq_hz" },
+	{ SMIAPP_REG_U16_MIN_VT_PIX_CLK_DIV, "min_vt_pix_clk_div" },
+	{ SMIAPP_REG_U16_MAX_VT_PIX_CLK_DIV, "max_vt_pix_clk_div" }, /* 30 */
+	{ SMIAPP_REG_U16_MIN_FRAME_LENGTH_LINES, "min_frame_length_lines" },
+	{ SMIAPP_REG_U16_MAX_FRAME_LENGTH_LINES, "max_frame_length_lines" },
+	{ SMIAPP_REG_U16_MIN_LINE_LENGTH_PCK, "min_line_length_pck" },
+	{ SMIAPP_REG_U16_MAX_LINE_LENGTH_PCK, "max_line_length_pck" },
+	{ SMIAPP_REG_U16_MIN_LINE_BLANKING_PCK, "min_line_blanking_pck" }, /* 35 */
+	{ SMIAPP_REG_U16_MIN_FRAME_BLANKING_LINES, "min_frame_blanking_lines" },
+	{ SMIAPP_REG_U8_MIN_LINE_LENGTH_PCK_STEP_SIZE, "min_line_length_pck_step_size" },
+	{ SMIAPP_REG_U16_MIN_OP_SYS_CLK_DIV, "min_op_sys_clk_div" },
+	{ SMIAPP_REG_U16_MAX_OP_SYS_CLK_DIV, "max_op_sys_clk_div" },
+	{ SMIAPP_REG_F32_MIN_OP_SYS_CLK_FREQ_HZ, "min_op_sys_clk_freq_hz" }, /* 40 */
+	{ SMIAPP_REG_F32_MAX_OP_SYS_CLK_FREQ_HZ, "max_op_sys_clk_freq_hz" },
+	{ SMIAPP_REG_U16_MIN_OP_PIX_CLK_DIV, "min_op_pix_clk_div" },
+	{ SMIAPP_REG_U16_MAX_OP_PIX_CLK_DIV, "max_op_pix_clk_div" },
+	{ SMIAPP_REG_F32_MIN_OP_PIX_CLK_FREQ_HZ, "min_op_pix_clk_freq_hz" },
+	{ SMIAPP_REG_F32_MAX_OP_PIX_CLK_FREQ_HZ, "max_op_pix_clk_freq_hz" }, /* 45 */
+	{ SMIAPP_REG_U16_X_ADDR_MIN, "x_addr_min" },
+	{ SMIAPP_REG_U16_Y_ADDR_MIN, "y_addr_min" },
+	{ SMIAPP_REG_U16_X_ADDR_MAX, "x_addr_max" },
+	{ SMIAPP_REG_U16_Y_ADDR_MAX, "y_addr_max" },
+	{ SMIAPP_REG_U16_MIN_X_OUTPUT_SIZE, "min_x_output_size" }, /* 50 */
+	{ SMIAPP_REG_U16_MIN_Y_OUTPUT_SIZE, "min_y_output_size" },
+	{ SMIAPP_REG_U16_MAX_X_OUTPUT_SIZE, "max_x_output_size" },
+	{ SMIAPP_REG_U16_MAX_Y_OUTPUT_SIZE, "max_y_output_size" },
+	{ SMIAPP_REG_U16_MIN_EVEN_INC, "min_even_inc" },
+	{ SMIAPP_REG_U16_MAX_EVEN_INC, "max_even_inc" }, /* 55 */
+	{ SMIAPP_REG_U16_MIN_ODD_INC, "min_odd_inc" },
+	{ SMIAPP_REG_U16_MAX_ODD_INC, "max_odd_inc" },
+	{ SMIAPP_REG_U16_SCALING_CAPABILITY, "scaling_capability" },
+	{ SMIAPP_REG_U16_SCALER_M_MIN, "scaler_m_min" },
+	{ SMIAPP_REG_U16_SCALER_M_MAX, "scaler_m_max" }, /* 60 */
+	{ SMIAPP_REG_U16_SCALER_N_MIN, "scaler_n_min" },
+	{ SMIAPP_REG_U16_SCALER_N_MAX, "scaler_n_max" },
+	{ SMIAPP_REG_U16_SPATIAL_SAMPLING_CAPABILITY, "spatial_sampling_capability" },
+	{ SMIAPP_REG_U8_DIGITAL_CROP_CAPABILITY, "digital_crop_capability" },
+	{ SMIAPP_REG_U16_COMPRESSION_CAPABILITY, "compression_capability" }, /* 65 */
+	{ SMIAPP_REG_U8_FIFO_SUPPORT_CAPABILITY, "fifo_support_capability" },
+	{ SMIAPP_REG_U8_DPHY_CTRL_CAPABILITY, "dphy_ctrl_capability" },
+	{ SMIAPP_REG_U8_CSI_LANE_MODE_CAPABILITY, "csi_lane_mode_capability" },
+	{ SMIAPP_REG_U8_CSI_SIGNALLING_MODE_CAPABILITY, "csi_signalling_mode_capability" },
+	{ SMIAPP_REG_U8_FAST_STANDBY_CAPABILITY, "fast_standby_capability" }, /* 70 */
+	{ SMIAPP_REG_U8_CCI_ADDRESS_CONTROL_CAPABILITY, "cci_address_control_capability" },
+	{ SMIAPP_REG_U32_MAX_PER_LANE_BITRATE_1_LANE_MODE_MBPS, "max_per_lane_bitrate_1_lane_mode_mbps" },
+	{ SMIAPP_REG_U32_MAX_PER_LANE_BITRATE_2_LANE_MODE_MBPS, "max_per_lane_bitrate_2_lane_mode_mbps" },
+	{ SMIAPP_REG_U32_MAX_PER_LANE_BITRATE_3_LANE_MODE_MBPS, "max_per_lane_bitrate_3_lane_mode_mbps" },
+	{ SMIAPP_REG_U32_MAX_PER_LANE_BITRATE_4_LANE_MODE_MBPS, "max_per_lane_bitrate_4_lane_mode_mbps" }, /* 75 */
+	{ SMIAPP_REG_U8_TEMP_SENSOR_CAPABILITY, "temp_sensor_capability" },
+	{ SMIAPP_REG_U16_MIN_FRAME_LENGTH_LINES_BIN, "min_frame_length_lines_bin" },
+	{ SMIAPP_REG_U16_MAX_FRAME_LENGTH_LINES_BIN, "max_frame_length_lines_bin" },
+	{ SMIAPP_REG_U16_MIN_LINE_LENGTH_PCK_BIN, "min_line_length_pck_bin" },
+	{ SMIAPP_REG_U16_MAX_LINE_LENGTH_PCK_BIN, "max_line_length_pck_bin" }, /* 80 */
+	{ SMIAPP_REG_U16_MIN_LINE_BLANKING_PCK_BIN, "min_line_blanking_pck_bin" },
+	{ SMIAPP_REG_U16_FINE_INTEGRATION_TIME_MIN_BIN, "fine_integration_time_min_bin" },
+	{ SMIAPP_REG_U16_FINE_INTEGRATION_TIME_MAX_MARGIN_BIN, "fine_integration_time_max_margin_bin" },
+	{ SMIAPP_REG_U8_BINNING_CAPABILITY, "binning_capability" },
+	{ SMIAPP_REG_U8_BINNING_WEIGHTING_CAPABILITY, "binning_weighting_capability" }, /* 85 */
+	{ SMIAPP_REG_U8_DATA_TRANSFER_IF_CAPABILITY, "data_transfer_if_capability" },
+	{ SMIAPP_REG_U8_SHADING_CORRECTION_CAPABILITY, "shading_correction_capability" },
+	{ SMIAPP_REG_U8_GREEN_IMBALANCE_CAPABILITY, "green_imbalance_capability" },
+	{ SMIAPP_REG_U8_BLACK_LEVEL_CAPABILITY, "black_level_capability" },
+	{ SMIAPP_REG_U8_MODULE_SPECIFIC_CORRECTION_CAPABILITY, "module_specific_correction_capability" }, /* 90 */
+	{ SMIAPP_REG_U16_DEFECT_CORRECTION_CAPABILITY, "defect_correction_capability" },
+	{ SMIAPP_REG_U16_DEFECT_CORRECTION_CAPABILITY_2, "defect_correction_capability_2" },
+	{ SMIAPP_REG_U8_EDOF_CAPABILITY, "edof_capability" },
+	{ SMIAPP_REG_U8_COLOUR_FEEDBACK_CAPABILITY, "colour_feedback_capability" },
+	{ SMIAPP_REG_U8_ESTIMATION_MODE_CAPABILITY, "estimation_mode_capability" }, /* 95 */
+	{ SMIAPP_REG_U8_ESTIMATION_ZONE_CAPABILITY, "estimation_zone_capability" },
+	{ SMIAPP_REG_U16_CAPABILITY_TRDY_MIN, "capability_trdy_min" },
+	{ SMIAPP_REG_U8_FLASH_MODE_CAPABILITY, "flash_mode_capability" },
+	{ SMIAPP_REG_U8_ACTUATOR_CAPABILITY, "actuator_capability" },
+	{ SMIAPP_REG_U8_BRACKETING_LUT_CAPABILITY_1, "bracketing_lut_capability_1" }, /* 100 */
+	{ SMIAPP_REG_U8_BRACKETING_LUT_CAPABILITY_2, "bracketing_lut_capability_2" },
+	{ SMIAPP_REG_U16_ANALOGUE_GAIN_CODE_STEP, "analogue_gain_code_step" },
+	{ 0, NULL },
+};
diff --git a/drivers/media/i2c/smiapp/smiapp-limits.h b/drivers/media/i2c/smiapp/smiapp-limits.h
new file mode 100644
index 0000000..9ae765e
--- /dev/null
+++ b/drivers/media/i2c/smiapp/smiapp-limits.h
@@ -0,0 +1,128 @@
+/*
+ * drivers/media/i2c/smiapp/smiapp-limits.h
+ *
+ * Generic driver for SMIA/SMIA++ compliant camera modules
+ *
+ * Copyright (C) 2011--2012 Nokia Corporation
+ * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#define SMIAPP_LIMIT_ANALOGUE_GAIN_CAPABILITY			0
+#define SMIAPP_LIMIT_ANALOGUE_GAIN_CODE_MIN			1
+#define SMIAPP_LIMIT_ANALOGUE_GAIN_CODE_MAX			2
+#define SMIAPP_LIMIT_THS_ZERO_MIN				3
+#define SMIAPP_LIMIT_TCLK_TRAIL_MIN				4
+#define SMIAPP_LIMIT_INTEGRATION_TIME_CAPABILITY		5
+#define SMIAPP_LIMIT_COARSE_INTEGRATION_TIME_MIN		6
+#define SMIAPP_LIMIT_COARSE_INTEGRATION_TIME_MAX_MARGIN		7
+#define SMIAPP_LIMIT_FINE_INTEGRATION_TIME_MIN			8
+#define SMIAPP_LIMIT_FINE_INTEGRATION_TIME_MAX_MARGIN		9
+#define SMIAPP_LIMIT_DIGITAL_GAIN_CAPABILITY			10
+#define SMIAPP_LIMIT_DIGITAL_GAIN_MIN				11
+#define SMIAPP_LIMIT_DIGITAL_GAIN_MAX				12
+#define SMIAPP_LIMIT_MIN_EXT_CLK_FREQ_HZ			13
+#define SMIAPP_LIMIT_MAX_EXT_CLK_FREQ_HZ			14
+#define SMIAPP_LIMIT_MIN_PRE_PLL_CLK_DIV			15
+#define SMIAPP_LIMIT_MAX_PRE_PLL_CLK_DIV			16
+#define SMIAPP_LIMIT_MIN_PLL_IP_FREQ_HZ				17
+#define SMIAPP_LIMIT_MAX_PLL_IP_FREQ_HZ				18
+#define SMIAPP_LIMIT_MIN_PLL_MULTIPLIER				19
+#define SMIAPP_LIMIT_MAX_PLL_MULTIPLIER				20
+#define SMIAPP_LIMIT_MIN_PLL_OP_FREQ_HZ				21
+#define SMIAPP_LIMIT_MAX_PLL_OP_FREQ_HZ				22
+#define SMIAPP_LIMIT_MIN_VT_SYS_CLK_DIV				23
+#define SMIAPP_LIMIT_MAX_VT_SYS_CLK_DIV				24
+#define SMIAPP_LIMIT_MIN_VT_SYS_CLK_FREQ_HZ			25
+#define SMIAPP_LIMIT_MAX_VT_SYS_CLK_FREQ_HZ			26
+#define SMIAPP_LIMIT_MIN_VT_PIX_CLK_FREQ_HZ			27
+#define SMIAPP_LIMIT_MAX_VT_PIX_CLK_FREQ_HZ			28
+#define SMIAPP_LIMIT_MIN_VT_PIX_CLK_DIV				29
+#define SMIAPP_LIMIT_MAX_VT_PIX_CLK_DIV				30
+#define SMIAPP_LIMIT_MIN_FRAME_LENGTH_LINES			31
+#define SMIAPP_LIMIT_MAX_FRAME_LENGTH_LINES			32
+#define SMIAPP_LIMIT_MIN_LINE_LENGTH_PCK			33
+#define SMIAPP_LIMIT_MAX_LINE_LENGTH_PCK			34
+#define SMIAPP_LIMIT_MIN_LINE_BLANKING_PCK			35
+#define SMIAPP_LIMIT_MIN_FRAME_BLANKING_LINES			36
+#define SMIAPP_LIMIT_MIN_LINE_LENGTH_PCK_STEP_SIZE		37
+#define SMIAPP_LIMIT_MIN_OP_SYS_CLK_DIV				38
+#define SMIAPP_LIMIT_MAX_OP_SYS_CLK_DIV				39
+#define SMIAPP_LIMIT_MIN_OP_SYS_CLK_FREQ_HZ			40
+#define SMIAPP_LIMIT_MAX_OP_SYS_CLK_FREQ_HZ			41
+#define SMIAPP_LIMIT_MIN_OP_PIX_CLK_DIV				42
+#define SMIAPP_LIMIT_MAX_OP_PIX_CLK_DIV				43
+#define SMIAPP_LIMIT_MIN_OP_PIX_CLK_FREQ_HZ			44
+#define SMIAPP_LIMIT_MAX_OP_PIX_CLK_FREQ_HZ			45
+#define SMIAPP_LIMIT_X_ADDR_MIN					46
+#define SMIAPP_LIMIT_Y_ADDR_MIN					47
+#define SMIAPP_LIMIT_X_ADDR_MAX					48
+#define SMIAPP_LIMIT_Y_ADDR_MAX					49
+#define SMIAPP_LIMIT_MIN_X_OUTPUT_SIZE				50
+#define SMIAPP_LIMIT_MIN_Y_OUTPUT_SIZE				51
+#define SMIAPP_LIMIT_MAX_X_OUTPUT_SIZE				52
+#define SMIAPP_LIMIT_MAX_Y_OUTPUT_SIZE				53
+#define SMIAPP_LIMIT_MIN_EVEN_INC				54
+#define SMIAPP_LIMIT_MAX_EVEN_INC				55
+#define SMIAPP_LIMIT_MIN_ODD_INC				56
+#define SMIAPP_LIMIT_MAX_ODD_INC				57
+#define SMIAPP_LIMIT_SCALING_CAPABILITY				58
+#define SMIAPP_LIMIT_SCALER_M_MIN				59
+#define SMIAPP_LIMIT_SCALER_M_MAX				60
+#define SMIAPP_LIMIT_SCALER_N_MIN				61
+#define SMIAPP_LIMIT_SCALER_N_MAX				62
+#define SMIAPP_LIMIT_SPATIAL_SAMPLING_CAPABILITY		63
+#define SMIAPP_LIMIT_DIGITAL_CROP_CAPABILITY			64
+#define SMIAPP_LIMIT_COMPRESSION_CAPABILITY			65
+#define SMIAPP_LIMIT_FIFO_SUPPORT_CAPABILITY			66
+#define SMIAPP_LIMIT_DPHY_CTRL_CAPABILITY			67
+#define SMIAPP_LIMIT_CSI_LANE_MODE_CAPABILITY			68
+#define SMIAPP_LIMIT_CSI_SIGNALLING_MODE_CAPABILITY		69
+#define SMIAPP_LIMIT_FAST_STANDBY_CAPABILITY			70
+#define SMIAPP_LIMIT_CCI_ADDRESS_CONTROL_CAPABILITY		71
+#define SMIAPP_LIMIT_MAX_PER_LANE_BITRATE_1_LANE_MODE_MBPS	72
+#define SMIAPP_LIMIT_MAX_PER_LANE_BITRATE_2_LANE_MODE_MBPS	73
+#define SMIAPP_LIMIT_MAX_PER_LANE_BITRATE_3_LANE_MODE_MBPS	74
+#define SMIAPP_LIMIT_MAX_PER_LANE_BITRATE_4_LANE_MODE_MBPS	75
+#define SMIAPP_LIMIT_TEMP_SENSOR_CAPABILITY			76
+#define SMIAPP_LIMIT_MIN_FRAME_LENGTH_LINES_BIN			77
+#define SMIAPP_LIMIT_MAX_FRAME_LENGTH_LINES_BIN			78
+#define SMIAPP_LIMIT_MIN_LINE_LENGTH_PCK_BIN			79
+#define SMIAPP_LIMIT_MAX_LINE_LENGTH_PCK_BIN			80
+#define SMIAPP_LIMIT_MIN_LINE_BLANKING_PCK_BIN			81
+#define SMIAPP_LIMIT_FINE_INTEGRATION_TIME_MIN_BIN		82
+#define SMIAPP_LIMIT_FINE_INTEGRATION_TIME_MAX_MARGIN_BIN	83
+#define SMIAPP_LIMIT_BINNING_CAPABILITY				84
+#define SMIAPP_LIMIT_BINNING_WEIGHTING_CAPABILITY		85
+#define SMIAPP_LIMIT_DATA_TRANSFER_IF_CAPABILITY		86
+#define SMIAPP_LIMIT_SHADING_CORRECTION_CAPABILITY		87
+#define SMIAPP_LIMIT_GREEN_IMBALANCE_CAPABILITY			88
+#define SMIAPP_LIMIT_BLACK_LEVEL_CAPABILITY			89
+#define SMIAPP_LIMIT_MODULE_SPECIFIC_CORRECTION_CAPABILITY	90
+#define SMIAPP_LIMIT_DEFECT_CORRECTION_CAPABILITY		91
+#define SMIAPP_LIMIT_DEFECT_CORRECTION_CAPABILITY_2		92
+#define SMIAPP_LIMIT_EDOF_CAPABILITY				93
+#define SMIAPP_LIMIT_COLOUR_FEEDBACK_CAPABILITY			94
+#define SMIAPP_LIMIT_ESTIMATION_MODE_CAPABILITY			95
+#define SMIAPP_LIMIT_ESTIMATION_ZONE_CAPABILITY			96
+#define SMIAPP_LIMIT_CAPABILITY_TRDY_MIN			97
+#define SMIAPP_LIMIT_FLASH_MODE_CAPABILITY			98
+#define SMIAPP_LIMIT_ACTUATOR_CAPABILITY			99
+#define SMIAPP_LIMIT_BRACKETING_LUT_CAPABILITY_1		100
+#define SMIAPP_LIMIT_BRACKETING_LUT_CAPABILITY_2		101
+#define SMIAPP_LIMIT_ANALOGUE_GAIN_CODE_STEP			102
+#define SMIAPP_LIMIT_LAST					103
diff --git a/drivers/media/i2c/smiapp/smiapp-quirk.c b/drivers/media/i2c/smiapp/smiapp-quirk.c
new file mode 100644
index 0000000..cf04812
--- /dev/null
+++ b/drivers/media/i2c/smiapp/smiapp-quirk.c
@@ -0,0 +1,306 @@
+/*
+ * drivers/media/i2c/smiapp/smiapp-quirk.c
+ *
+ * Generic driver for SMIA/SMIA++ compliant camera modules
+ *
+ * Copyright (C) 2011--2012 Nokia Corporation
+ * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/delay.h>
+
+#include "smiapp.h"
+
+static int smiapp_write_8(struct smiapp_sensor *sensor, u16 reg, u8 val)
+{
+	return smiapp_write(sensor, (SMIA_REG_8BIT << 16) | reg, val);
+}
+
+static int smiapp_write_8s(struct smiapp_sensor *sensor,
+			   struct smiapp_reg_8 *regs, int len)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
+	int rval;
+
+	for (; len > 0; len--, regs++) {
+		rval = smiapp_write_8(sensor, regs->reg, regs->val);
+		if (rval < 0) {
+			dev_err(&client->dev,
+				"error %d writing reg 0x%4.4x, val 0x%2.2x",
+				rval, regs->reg, regs->val);
+			return rval;
+		}
+	}
+
+	return 0;
+}
+
+void smiapp_replace_limit(struct smiapp_sensor *sensor,
+			  u32 limit, u32 val)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
+
+	dev_dbg(&client->dev, "quirk: 0x%8.8x \"%s\" = %d, 0x%x\n",
+		smiapp_reg_limits[limit].addr,
+		smiapp_reg_limits[limit].what, val, val);
+	sensor->limits[limit] = val;
+}
+
+int smiapp_replace_limit_at(struct smiapp_sensor *sensor,
+			    u32 reg, u32 val)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
+	int i;
+
+	for (i = 0; smiapp_reg_limits[i].addr; i++) {
+		if ((smiapp_reg_limits[i].addr & 0xffff) != reg)
+			continue;
+
+		smiapp_replace_limit(sensor, i, val);
+
+		return 0;
+	}
+
+	dev_dbg(&client->dev, "quirk: bad register 0x%4.4x\n", reg);
+
+	return -EINVAL;
+}
+
+bool smiapp_quirk_reg(struct smiapp_sensor *sensor,
+		      u32 reg, u32 *val)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
+	const struct smia_reg *sreg;
+
+	if (!sensor->minfo.quirk)
+		return false;
+
+	sreg = sensor->minfo.quirk->regs;
+
+	if (!sreg)
+		return false;
+
+	while (sreg->type) {
+		u16 type = reg >> 16;
+		u16 reg16 = reg;
+
+		if (sreg->type != type || sreg->reg != reg16) {
+			sreg++;
+			continue;
+		}
+
+		switch ((u8)type) {
+		case SMIA_REG_8BIT:
+			dev_dbg(&client->dev, "quirk: 0x%8.8x: 0x%2.2x\n",
+				reg, sreg->val);
+			break;
+		case SMIA_REG_16BIT:
+			dev_dbg(&client->dev, "quirk: 0x%8.8x: 0x%4.4x\n",
+				reg, sreg->val);
+			break;
+		case SMIA_REG_32BIT:
+			dev_dbg(&client->dev, "quirk: 0x%8.8x: 0x%8.8x\n",
+				reg, sreg->val);
+			break;
+		}
+
+		*val = sreg->val;
+
+		return true;
+	}
+
+	return false;
+}
+
+static int jt8ew9_limits(struct smiapp_sensor *sensor)
+{
+	if (sensor->minfo.revision_number_major < 0x03)
+		sensor->frame_skip = 1;
+
+	/* Below 24 gain doesn't have effect at all, */
+	/* but ~59 is needed for full dynamic range */
+	smiapp_replace_limit(sensor, SMIAPP_LIMIT_ANALOGUE_GAIN_CODE_MIN, 59);
+	smiapp_replace_limit(
+		sensor, SMIAPP_LIMIT_ANALOGUE_GAIN_CODE_MAX, 6000);
+
+	return 0;
+}
+
+static int jt8ew9_post_poweron(struct smiapp_sensor *sensor)
+{
+	struct smiapp_reg_8 regs[] = {
+		{ 0x30a3, 0xd8 }, /* Output port control : LVDS ports only */
+		{ 0x30ae, 0x00 }, /* 0x0307 pll_multiplier maximum value on PLL input 9.6MHz ( 19.2MHz is divided on pre_pll_div) */
+		{ 0x30af, 0xd0 }, /* 0x0307 pll_multiplier maximum value on PLL input 9.6MHz ( 19.2MHz is divided on pre_pll_div) */
+		{ 0x322d, 0x04 }, /* Adjusting Processing Image Size to Scaler Toshiba Recommendation Setting */
+		{ 0x3255, 0x0f }, /* Horizontal Noise Reduction Control Toshiba Recommendation Setting */
+		{ 0x3256, 0x15 }, /* Horizontal Noise Reduction Control Toshiba Recommendation Setting */
+		{ 0x3258, 0x70 }, /* Analog Gain Control Toshiba Recommendation Setting */
+		{ 0x3259, 0x70 }, /* Analog Gain Control Toshiba Recommendation Setting */
+		{ 0x325f, 0x7c }, /* Analog Gain Control Toshiba Recommendation Setting */
+		{ 0x3302, 0x06 }, /* Pixel Reference Voltage Control Toshiba Recommendation Setting */
+		{ 0x3304, 0x00 }, /* Pixel Reference Voltage Control Toshiba Recommendation Setting */
+		{ 0x3307, 0x22 }, /* Pixel Reference Voltage Control Toshiba Recommendation Setting */
+		{ 0x3308, 0x8d }, /* Pixel Reference Voltage Control Toshiba Recommendation Setting */
+		{ 0x331e, 0x0f }, /* Black Hole Sun Correction Control Toshiba Recommendation Setting */
+		{ 0x3320, 0x30 }, /* Black Hole Sun Correction Control Toshiba Recommendation Setting */
+		{ 0x3321, 0x11 }, /* Black Hole Sun Correction Control Toshiba Recommendation Setting */
+		{ 0x3322, 0x98 }, /* Black Hole Sun Correction Control Toshiba Recommendation Setting */
+		{ 0x3323, 0x64 }, /* Black Hole Sun Correction Control Toshiba Recommendation Setting */
+		{ 0x3325, 0x83 }, /* Read Out Timing Control Toshiba Recommendation Setting */
+		{ 0x3330, 0x18 }, /* Read Out Timing Control Toshiba Recommendation Setting */
+		{ 0x333c, 0x01 }, /* Read Out Timing Control Toshiba Recommendation Setting */
+		{ 0x3345, 0x2f }, /* Black Hole Sun Correction Control Toshiba Recommendation Setting */
+		{ 0x33de, 0x38 }, /* Horizontal Noise Reduction Control Toshiba Recommendation Setting */
+		/* Taken from v03. No idea what the rest are. */
+		{ 0x32e0, 0x05 },
+		{ 0x32e1, 0x05 },
+		{ 0x32e2, 0x04 },
+		{ 0x32e5, 0x04 },
+		{ 0x32e6, 0x04 },
+
+	};
+
+	return smiapp_write_8s(sensor, regs, ARRAY_SIZE(regs));
+}
+
+const struct smiapp_quirk smiapp_jt8ew9_quirk = {
+	.limits = jt8ew9_limits,
+	.post_poweron = jt8ew9_post_poweron,
+};
+
+static int imx125es_post_poweron(struct smiapp_sensor *sensor)
+{
+	/* Taken from v02. No idea what the other two are. */
+	struct smiapp_reg_8 regs[] = {
+		/*
+		 * 0x3302: clk during frame blanking:
+		 * 0x00 - HS mode, 0x01 - LP11
+		 */
+		{ 0x3302, 0x01 },
+		{ 0x302d, 0x00 },
+		{ 0x3b08, 0x8c },
+	};
+
+	return smiapp_write_8s(sensor, regs, ARRAY_SIZE(regs));
+}
+
+const struct smiapp_quirk smiapp_imx125es_quirk = {
+	.post_poweron = imx125es_post_poweron,
+};
+
+static int jt8ev1_limits(struct smiapp_sensor *sensor)
+{
+	smiapp_replace_limit(sensor, SMIAPP_LIMIT_X_ADDR_MAX, 4271);
+	smiapp_replace_limit(sensor,
+			     SMIAPP_LIMIT_MIN_LINE_BLANKING_PCK_BIN, 184);
+
+	return 0;
+}
+
+static int jt8ev1_post_poweron(struct smiapp_sensor *sensor)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
+	int rval;
+
+	struct smiapp_reg_8 regs[] = {
+		{ 0x3031, 0xcd }, /* For digital binning (EQ_MONI) */
+		{ 0x30a3, 0xd0 }, /* FLASH STROBE enable */
+		{ 0x3237, 0x00 }, /* For control of pulse timing for ADC */
+		{ 0x3238, 0x43 },
+		{ 0x3301, 0x06 }, /* For analog bias for sensor */
+		{ 0x3302, 0x06 },
+		{ 0x3304, 0x00 },
+		{ 0x3305, 0x88 },
+		{ 0x332a, 0x14 },
+		{ 0x332c, 0x6b },
+		{ 0x3336, 0x01 },
+		{ 0x333f, 0x1f },
+		{ 0x3355, 0x00 },
+		{ 0x3356, 0x20 },
+		{ 0x33bf, 0x20 }, /* Adjust the FBC speed */
+		{ 0x33c9, 0x20 },
+		{ 0x33ce, 0x30 }, /* Adjust the parameter for logic function */
+		{ 0x33cf, 0xec }, /* For Black sun */
+		{ 0x3328, 0x80 }, /* Ugh. No idea what's this. */
+	};
+
+	struct smiapp_reg_8 regs_96[] = {
+		{ 0x30ae, 0x00 }, /* For control of ADC clock */
+		{ 0x30af, 0xd0 },
+		{ 0x30b0, 0x01 },
+	};
+
+	rval = smiapp_write_8s(sensor, regs, ARRAY_SIZE(regs));
+	if (rval < 0)
+		return rval;
+
+	switch (sensor->platform_data->ext_clk) {
+	case 9600000:
+		return smiapp_write_8s(sensor, regs_96,
+				       ARRAY_SIZE(regs_96));
+	default:
+		dev_warn(&client->dev, "no MSRs for %d Hz ext_clk\n",
+			 sensor->platform_data->ext_clk);
+		return 0;
+	}
+}
+
+static int jt8ev1_pre_streamon(struct smiapp_sensor *sensor)
+{
+	return smiapp_write_8(sensor, 0x3328, 0x00);
+}
+
+static int jt8ev1_post_streamoff(struct smiapp_sensor *sensor)
+{
+	int rval;
+
+	/* Workaround: allows fast standby to work properly */
+	rval = smiapp_write_8(sensor, 0x3205, 0x04);
+	if (rval < 0)
+		return rval;
+
+	/* Wait for 1 ms + one line => 2 ms is likely enough */
+	usleep_range(2000, 2000);
+
+	/* Restore it */
+	rval = smiapp_write_8(sensor, 0x3205, 0x00);
+	if (rval < 0)
+		return rval;
+
+	return smiapp_write_8(sensor, 0x3328, 0x80);
+}
+
+const struct smiapp_quirk smiapp_jt8ev1_quirk = {
+	.limits = jt8ev1_limits,
+	.post_poweron = jt8ev1_post_poweron,
+	.pre_streamon = jt8ev1_pre_streamon,
+	.post_streamoff = jt8ev1_post_streamoff,
+	.flags = SMIAPP_QUIRK_FLAG_OP_PIX_CLOCK_PER_LANE,
+};
+
+static int tcm8500md_limits(struct smiapp_sensor *sensor)
+{
+	smiapp_replace_limit(sensor, SMIAPP_LIMIT_MIN_PLL_IP_FREQ_HZ, 2700000);
+
+	return 0;
+}
+
+const struct smiapp_quirk smiapp_tcm8500md_quirk = {
+	.limits = tcm8500md_limits,
+};
diff --git a/drivers/media/i2c/smiapp/smiapp-quirk.h b/drivers/media/i2c/smiapp/smiapp-quirk.h
new file mode 100644
index 0000000..86fd3e8
--- /dev/null
+++ b/drivers/media/i2c/smiapp/smiapp-quirk.h
@@ -0,0 +1,83 @@
+/*
+ * drivers/media/i2c/smiapp/smiapp-quirk.h
+ *
+ * Generic driver for SMIA/SMIA++ compliant camera modules
+ *
+ * Copyright (C) 2011--2012 Nokia Corporation
+ * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __SMIAPP_QUIRK__
+#define __SMIAPP_QUIRK__
+
+struct smiapp_sensor;
+
+/**
+ * struct smiapp_quirk - quirks for sensors that deviate from SMIA++ standard
+ *
+ * @limits: Replace sensor->limits with values which can't be read from
+ *	    sensor registers. Called the first time the sensor is powered up.
+ * @post_poweron: Called always after the sensor has been fully powered on.
+ * @pre_streamon: Called just before streaming is enabled.
+ * @post_streamon: Called right after stopping streaming.
+ */
+struct smiapp_quirk {
+	int (*limits)(struct smiapp_sensor *sensor);
+	int (*post_poweron)(struct smiapp_sensor *sensor);
+	int (*pre_streamon)(struct smiapp_sensor *sensor);
+	int (*post_streamoff)(struct smiapp_sensor *sensor);
+	const struct smia_reg *regs;
+	unsigned long flags;
+};
+
+/* op pix clock is for all lanes in total normally */
+#define SMIAPP_QUIRK_FLAG_OP_PIX_CLOCK_PER_LANE			(1 << 0)
+#define SMIAPP_QUIRK_FLAG_8BIT_READ_ONLY			(1 << 1)
+
+struct smiapp_reg_8 {
+	u16 reg;
+	u8 val;
+};
+
+void smiapp_replace_limit(struct smiapp_sensor *sensor,
+			  u32 limit, u32 val);
+bool smiapp_quirk_reg(struct smiapp_sensor *sensor,
+		      u32 reg, u32 *val);
+
+#define SMIAPP_MK_QUIRK_REG(_reg, _val) \
+	{				\
+		.type = (_reg >> 16),	\
+		.reg = (u16)_reg,	\
+		.val = _val,		\
+	}
+
+#define smiapp_call_quirk(_sensor, _quirk, ...)				\
+	(_sensor->minfo.quirk &&					\
+	 _sensor->minfo.quirk->_quirk ?					\
+	 _sensor->minfo.quirk->_quirk(_sensor, ##__VA_ARGS__) : 0)
+
+#define smiapp_needs_quirk(_sensor, _quirk)		\
+	(_sensor->minfo.quirk ?				\
+	 _sensor->minfo.quirk->flags & _quirk : 0)
+
+extern const struct smiapp_quirk smiapp_jt8ev1_quirk;
+extern const struct smiapp_quirk smiapp_imx125es_quirk;
+extern const struct smiapp_quirk smiapp_jt8ew9_quirk;
+extern const struct smiapp_quirk smiapp_tcm8500md_quirk;
+
+#endif /* __SMIAPP_QUIRK__ */
diff --git a/drivers/media/i2c/smiapp/smiapp-reg-defs.h b/drivers/media/i2c/smiapp/smiapp-reg-defs.h
new file mode 100644
index 0000000..defa7c5
--- /dev/null
+++ b/drivers/media/i2c/smiapp/smiapp-reg-defs.h
@@ -0,0 +1,503 @@
+/*
+ * drivers/media/i2c/smiapp/smiapp-reg-defs.h
+ *
+ * Generic driver for SMIA/SMIA++ compliant camera modules
+ *
+ * Copyright (C) 2011--2012 Nokia Corporation
+ * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+#define SMIAPP_REG_MK_U8(r) ((SMIA_REG_8BIT << 16) | (r))
+#define SMIAPP_REG_MK_U16(r) ((SMIA_REG_16BIT << 16) | (r))
+#define SMIAPP_REG_MK_U32(r) ((SMIA_REG_32BIT << 16) | (r))
+
+#define SMIAPP_REG_MK_F32(r) (SMIA_REG_FLAG_FLOAT | (SMIA_REG_32BIT << 16) | (r))
+
+#define SMIAPP_REG_U16_MODEL_ID					SMIAPP_REG_MK_U16(0x0000)
+#define SMIAPP_REG_U8_REVISION_NUMBER_MAJOR			SMIAPP_REG_MK_U8(0x0002)
+#define SMIAPP_REG_U8_MANUFACTURER_ID				SMIAPP_REG_MK_U8(0x0003)
+#define SMIAPP_REG_U8_SMIA_VERSION				SMIAPP_REG_MK_U8(0x0004)
+#define SMIAPP_REG_U8_FRAME_COUNT				SMIAPP_REG_MK_U8(0x0005)
+#define SMIAPP_REG_U8_PIXEL_ORDER				SMIAPP_REG_MK_U8(0x0006)
+#define SMIAPP_REG_U16_DATA_PEDESTAL				SMIAPP_REG_MK_U16(0x0008)
+#define SMIAPP_REG_U8_PIXEL_DEPTH				SMIAPP_REG_MK_U8(0x000c)
+#define SMIAPP_REG_U8_REVISION_NUMBER_MINOR			SMIAPP_REG_MK_U8(0x0010)
+#define SMIAPP_REG_U8_SMIAPP_VERSION				SMIAPP_REG_MK_U8(0x0011)
+#define SMIAPP_REG_U8_MODULE_DATE_YEAR				SMIAPP_REG_MK_U8(0x0012)
+#define SMIAPP_REG_U8_MODULE_DATE_MONTH				SMIAPP_REG_MK_U8(0x0013)
+#define SMIAPP_REG_U8_MODULE_DATE_DAY				SMIAPP_REG_MK_U8(0x0014)
+#define SMIAPP_REG_U8_MODULE_DATE_PHASE				SMIAPP_REG_MK_U8(0x0015)
+#define SMIAPP_REG_U16_SENSOR_MODEL_ID				SMIAPP_REG_MK_U16(0x0016)
+#define SMIAPP_REG_U8_SENSOR_REVISION_NUMBER			SMIAPP_REG_MK_U8(0x0018)
+#define SMIAPP_REG_U8_SENSOR_MANUFACTURER_ID			SMIAPP_REG_MK_U8(0x0019)
+#define SMIAPP_REG_U8_SENSOR_FIRMWARE_VERSION			SMIAPP_REG_MK_U8(0x001a)
+#define SMIAPP_REG_U32_SERIAL_NUMBER				SMIAPP_REG_MK_U32(0x001c)
+#define SMIAPP_REG_U8_FRAME_FORMAT_MODEL_TYPE			SMIAPP_REG_MK_U8(0x0040)
+#define SMIAPP_REG_U8_FRAME_FORMAT_MODEL_SUBTYPE		SMIAPP_REG_MK_U8(0x0041)
+#define SMIAPP_REG_U16_FRAME_FORMAT_DESCRIPTOR_2(n)		SMIAPP_REG_MK_U16(0x0042 + ((n) << 1)) /* 0 <= n <= 14 */
+#define SMIAPP_REG_U32_FRAME_FORMAT_DESCRIPTOR_4(n)		SMIAPP_REG_MK_U32(0x0060 + ((n) << 2)) /* 0 <= n <= 7 */
+#define SMIAPP_REG_U16_ANALOGUE_GAIN_CAPABILITY			SMIAPP_REG_MK_U16(0x0080)
+#define SMIAPP_REG_U16_ANALOGUE_GAIN_CODE_MIN			SMIAPP_REG_MK_U16(0x0084)
+#define SMIAPP_REG_U16_ANALOGUE_GAIN_CODE_MAX			SMIAPP_REG_MK_U16(0x0086)
+#define SMIAPP_REG_U16_ANALOGUE_GAIN_CODE_STEP			SMIAPP_REG_MK_U16(0x0088)
+#define SMIAPP_REG_U16_ANALOGUE_GAIN_TYPE			SMIAPP_REG_MK_U16(0x008a)
+#define SMIAPP_REG_U16_ANALOGUE_GAIN_M0				SMIAPP_REG_MK_U16(0x008c)
+#define SMIAPP_REG_U16_ANALOGUE_GAIN_C0				SMIAPP_REG_MK_U16(0x008e)
+#define SMIAPP_REG_U16_ANALOGUE_GAIN_M1				SMIAPP_REG_MK_U16(0x0090)
+#define SMIAPP_REG_U16_ANALOGUE_GAIN_C1				SMIAPP_REG_MK_U16(0x0092)
+#define SMIAPP_REG_U8_DATA_FORMAT_MODEL_TYPE			SMIAPP_REG_MK_U8(0x00c0)
+#define SMIAPP_REG_U8_DATA_FORMAT_MODEL_SUBTYPE			SMIAPP_REG_MK_U8(0x00c1)
+#define SMIAPP_REG_U16_DATA_FORMAT_DESCRIPTOR(n)		SMIAPP_REG_MK_U16(0x00c2 + ((n) << 1))
+#define SMIAPP_REG_U8_MODE_SELECT				SMIAPP_REG_MK_U8(0x0100)
+#define SMIAPP_REG_U8_IMAGE_ORIENTATION				SMIAPP_REG_MK_U8(0x0101)
+#define SMIAPP_REG_U8_SOFTWARE_RESET				SMIAPP_REG_MK_U8(0x0103)
+#define SMIAPP_REG_U8_GROUPED_PARAMETER_HOLD			SMIAPP_REG_MK_U8(0x0104)
+#define SMIAPP_REG_U8_MASK_CORRUPTED_FRAMES			SMIAPP_REG_MK_U8(0x0105)
+#define SMIAPP_REG_U8_FAST_STANDBY_CTRL				SMIAPP_REG_MK_U8(0x0106)
+#define SMIAPP_REG_U8_CCI_ADDRESS_CONTROL			SMIAPP_REG_MK_U8(0x0107)
+#define SMIAPP_REG_U8_2ND_CCI_IF_CONTROL			SMIAPP_REG_MK_U8(0x0108)
+#define SMIAPP_REG_U8_2ND_CCI_ADDRESS_CONTROL			SMIAPP_REG_MK_U8(0x0109)
+#define SMIAPP_REG_U8_CSI_CHANNEL_IDENTIFIER			SMIAPP_REG_MK_U8(0x0110)
+#define SMIAPP_REG_U8_CSI_SIGNALLING_MODE			SMIAPP_REG_MK_U8(0x0111)
+#define SMIAPP_REG_U16_CSI_DATA_FORMAT				SMIAPP_REG_MK_U16(0x0112)
+#define SMIAPP_REG_U8_CSI_LANE_MODE				SMIAPP_REG_MK_U8(0x0114)
+#define SMIAPP_REG_U8_CSI2_10_TO_8_DT				SMIAPP_REG_MK_U8(0x0115)
+#define SMIAPP_REG_U8_CSI2_10_TO_7_DT				SMIAPP_REG_MK_U8(0x0116)
+#define SMIAPP_REG_U8_CSI2_10_TO_6_DT				SMIAPP_REG_MK_U8(0x0117)
+#define SMIAPP_REG_U8_CSI2_12_TO_8_DT				SMIAPP_REG_MK_U8(0x0118)
+#define SMIAPP_REG_U8_CSI2_12_TO_7_DT				SMIAPP_REG_MK_U8(0x0119)
+#define SMIAPP_REG_U8_CSI2_12_TO_6_DT				SMIAPP_REG_MK_U8(0x011a)
+#define SMIAPP_REG_U8_CSI2_14_TO_10_DT				SMIAPP_REG_MK_U8(0x011b)
+#define SMIAPP_REG_U8_CSI2_14_TO_8_DT				SMIAPP_REG_MK_U8(0x011c)
+#define SMIAPP_REG_U8_CSI2_16_TO_10_DT				SMIAPP_REG_MK_U8(0x011d)
+#define SMIAPP_REG_U8_CSI2_16_TO_8_DT				SMIAPP_REG_MK_U8(0x011e)
+#define SMIAPP_REG_U8_GAIN_MODE					SMIAPP_REG_MK_U8(0x0120)
+#define SMIAPP_REG_U16_VANA_VOLTAGE				SMIAPP_REG_MK_U16(0x0130)
+#define SMIAPP_REG_U16_VDIG_VOLTAGE				SMIAPP_REG_MK_U16(0x0132)
+#define SMIAPP_REG_U16_VIO_VOLTAGE				SMIAPP_REG_MK_U16(0x0134)
+#define SMIAPP_REG_U16_EXTCLK_FREQUENCY_MHZ			SMIAPP_REG_MK_U16(0x0136)
+#define SMIAPP_REG_U8_TEMP_SENSOR_CONTROL			SMIAPP_REG_MK_U8(0x0138)
+#define SMIAPP_REG_U8_TEMP_SENSOR_MODE				SMIAPP_REG_MK_U8(0x0139)
+#define SMIAPP_REG_U8_TEMP_SENSOR_OUTPUT			SMIAPP_REG_MK_U8(0x013a)
+#define SMIAPP_REG_U16_FINE_INTEGRATION_TIME			SMIAPP_REG_MK_U16(0x0200)
+#define SMIAPP_REG_U16_COARSE_INTEGRATION_TIME			SMIAPP_REG_MK_U16(0x0202)
+#define SMIAPP_REG_U16_ANALOGUE_GAIN_CODE_GLOBAL		SMIAPP_REG_MK_U16(0x0204)
+#define SMIAPP_REG_U16_ANALOGUE_GAIN_CODE_GREENR		SMIAPP_REG_MK_U16(0x0206)
+#define SMIAPP_REG_U16_ANALOGUE_GAIN_CODE_RED			SMIAPP_REG_MK_U16(0x0208)
+#define SMIAPP_REG_U16_ANALOGUE_GAIN_CODE_BLUE			SMIAPP_REG_MK_U16(0x020a)
+#define SMIAPP_REG_U16_ANALOGUE_GAIN_CODE_GREENB		SMIAPP_REG_MK_U16(0x020c)
+#define SMIAPP_REG_U16_DIGITAL_GAIN_GREENR			SMIAPP_REG_MK_U16(0x020e)
+#define SMIAPP_REG_U16_DIGITAL_GAIN_RED				SMIAPP_REG_MK_U16(0x0210)
+#define SMIAPP_REG_U16_DIGITAL_GAIN_BLUE			SMIAPP_REG_MK_U16(0x0212)
+#define SMIAPP_REG_U16_DIGITAL_GAIN_GREENB			SMIAPP_REG_MK_U16(0x0214)
+#define SMIAPP_REG_U16_VT_PIX_CLK_DIV				SMIAPP_REG_MK_U16(0x0300)
+#define SMIAPP_REG_U16_VT_SYS_CLK_DIV				SMIAPP_REG_MK_U16(0x0302)
+#define SMIAPP_REG_U16_PRE_PLL_CLK_DIV				SMIAPP_REG_MK_U16(0x0304)
+#define SMIAPP_REG_U16_PLL_MULTIPLIER				SMIAPP_REG_MK_U16(0x0306)
+#define SMIAPP_REG_U16_OP_PIX_CLK_DIV				SMIAPP_REG_MK_U16(0x0308)
+#define SMIAPP_REG_U16_OP_SYS_CLK_DIV				SMIAPP_REG_MK_U16(0x030a)
+#define SMIAPP_REG_U16_FRAME_LENGTH_LINES			SMIAPP_REG_MK_U16(0x0340)
+#define SMIAPP_REG_U16_LINE_LENGTH_PCK				SMIAPP_REG_MK_U16(0x0342)
+#define SMIAPP_REG_U16_X_ADDR_START				SMIAPP_REG_MK_U16(0x0344)
+#define SMIAPP_REG_U16_Y_ADDR_START				SMIAPP_REG_MK_U16(0x0346)
+#define SMIAPP_REG_U16_X_ADDR_END				SMIAPP_REG_MK_U16(0x0348)
+#define SMIAPP_REG_U16_Y_ADDR_END				SMIAPP_REG_MK_U16(0x034a)
+#define SMIAPP_REG_U16_X_OUTPUT_SIZE				SMIAPP_REG_MK_U16(0x034c)
+#define SMIAPP_REG_U16_Y_OUTPUT_SIZE				SMIAPP_REG_MK_U16(0x034e)
+#define SMIAPP_REG_U16_X_EVEN_INC				SMIAPP_REG_MK_U16(0x0380)
+#define SMIAPP_REG_U16_X_ODD_INC				SMIAPP_REG_MK_U16(0x0382)
+#define SMIAPP_REG_U16_Y_EVEN_INC				SMIAPP_REG_MK_U16(0x0384)
+#define SMIAPP_REG_U16_Y_ODD_INC				SMIAPP_REG_MK_U16(0x0386)
+#define SMIAPP_REG_U16_SCALING_MODE				SMIAPP_REG_MK_U16(0x0400)
+#define SMIAPP_REG_U16_SPATIAL_SAMPLING				SMIAPP_REG_MK_U16(0x0402)
+#define SMIAPP_REG_U16_SCALE_M					SMIAPP_REG_MK_U16(0x0404)
+#define SMIAPP_REG_U16_SCALE_N					SMIAPP_REG_MK_U16(0x0406)
+#define SMIAPP_REG_U16_DIGITAL_CROP_X_OFFSET			SMIAPP_REG_MK_U16(0x0408)
+#define SMIAPP_REG_U16_DIGITAL_CROP_Y_OFFSET			SMIAPP_REG_MK_U16(0x040a)
+#define SMIAPP_REG_U16_DIGITAL_CROP_IMAGE_WIDTH			SMIAPP_REG_MK_U16(0x040c)
+#define SMIAPP_REG_U16_DIGITAL_CROP_IMAGE_HEIGHT		SMIAPP_REG_MK_U16(0x040e)
+#define SMIAPP_REG_U16_COMPRESSION_MODE				SMIAPP_REG_MK_U16(0x0500)
+#define SMIAPP_REG_U16_TEST_PATTERN_MODE			SMIAPP_REG_MK_U16(0x0600)
+#define SMIAPP_REG_U16_TEST_DATA_RED				SMIAPP_REG_MK_U16(0x0602)
+#define SMIAPP_REG_U16_TEST_DATA_GREENR				SMIAPP_REG_MK_U16(0x0604)
+#define SMIAPP_REG_U16_TEST_DATA_BLUE				SMIAPP_REG_MK_U16(0x0606)
+#define SMIAPP_REG_U16_TEST_DATA_GREENB				SMIAPP_REG_MK_U16(0x0608)
+#define SMIAPP_REG_U16_HORIZONTAL_CURSOR_WIDTH			SMIAPP_REG_MK_U16(0x060a)
+#define SMIAPP_REG_U16_HORIZONTAL_CURSOR_POSITION		SMIAPP_REG_MK_U16(0x060c)
+#define SMIAPP_REG_U16_VERTICAL_CURSOR_WIDTH			SMIAPP_REG_MK_U16(0x060e)
+#define SMIAPP_REG_U16_VERTICAL_CURSOR_POSITION			SMIAPP_REG_MK_U16(0x0610)
+#define SMIAPP_REG_U16_FIFO_WATER_MARK_PIXELS			SMIAPP_REG_MK_U16(0x0700)
+#define SMIAPP_REG_U8_TCLK_POST					SMIAPP_REG_MK_U8(0x0800)
+#define SMIAPP_REG_U8_THS_PREPARE				SMIAPP_REG_MK_U8(0x0801)
+#define SMIAPP_REG_U8_THS_ZERO_MIN				SMIAPP_REG_MK_U8(0x0802)
+#define SMIAPP_REG_U8_THS_TRAIL					SMIAPP_REG_MK_U8(0x0803)
+#define SMIAPP_REG_U8_TCLK_TRAIL_MIN				SMIAPP_REG_MK_U8(0x0804)
+#define SMIAPP_REG_U8_TCLK_PREPARE				SMIAPP_REG_MK_U8(0x0805)
+#define SMIAPP_REG_U8_TCLK_ZERO					SMIAPP_REG_MK_U8(0x0806)
+#define SMIAPP_REG_U8_TLPX					SMIAPP_REG_MK_U8(0x0807)
+#define SMIAPP_REG_U8_DPHY_CTRL					SMIAPP_REG_MK_U8(0x0808)
+#define SMIAPP_REG_U32_REQUESTED_LINK_BIT_RATE_MBPS		SMIAPP_REG_MK_U32(0x0820)
+#define SMIAPP_REG_U8_BINNING_MODE				SMIAPP_REG_MK_U8(0x0900)
+#define SMIAPP_REG_U8_BINNING_TYPE				SMIAPP_REG_MK_U8(0x0901)
+#define SMIAPP_REG_U8_BINNING_WEIGHTING				SMIAPP_REG_MK_U8(0x0902)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_CTRL			SMIAPP_REG_MK_U8(0x0a00)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_STATUS			SMIAPP_REG_MK_U8(0x0a01)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_PAGE_SELECT		SMIAPP_REG_MK_U8(0x0a02)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_0			SMIAPP_REG_MK_U8(0x0a04)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_1			SMIAPP_REG_MK_U8(0x0a05)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_2			SMIAPP_REG_MK_U8(0x0a06)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_3			SMIAPP_REG_MK_U8(0x0a07)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_4			SMIAPP_REG_MK_U8(0x0a08)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_5			SMIAPP_REG_MK_U8(0x0a09)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_12		SMIAPP_REG_MK_U8(0x0a10)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_13		SMIAPP_REG_MK_U8(0x0a11)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_14		SMIAPP_REG_MK_U8(0x0a12)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_15		SMIAPP_REG_MK_U8(0x0a13)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_16		SMIAPP_REG_MK_U8(0x0a14)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_17		SMIAPP_REG_MK_U8(0x0a15)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_18		SMIAPP_REG_MK_U8(0x0a16)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_19		SMIAPP_REG_MK_U8(0x0a17)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_20		SMIAPP_REG_MK_U8(0x0a18)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_21		SMIAPP_REG_MK_U8(0x0a19)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_22		SMIAPP_REG_MK_U8(0x0a1a)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_23		SMIAPP_REG_MK_U8(0x0a1b)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_24		SMIAPP_REG_MK_U8(0x0a1c)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_25		SMIAPP_REG_MK_U8(0x0a1d)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_26		SMIAPP_REG_MK_U8(0x0a1e)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_27		SMIAPP_REG_MK_U8(0x0a1f)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_28		SMIAPP_REG_MK_U8(0x0a20)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_29		SMIAPP_REG_MK_U8(0x0a21)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_30		SMIAPP_REG_MK_U8(0x0a22)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_31		SMIAPP_REG_MK_U8(0x0a23)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_32		SMIAPP_REG_MK_U8(0x0a24)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_33		SMIAPP_REG_MK_U8(0x0a25)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_34		SMIAPP_REG_MK_U8(0x0a26)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_35		SMIAPP_REG_MK_U8(0x0a27)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_36		SMIAPP_REG_MK_U8(0x0a28)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_37		SMIAPP_REG_MK_U8(0x0a29)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_38		SMIAPP_REG_MK_U8(0x0a2a)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_39		SMIAPP_REG_MK_U8(0x0a2b)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_40		SMIAPP_REG_MK_U8(0x0a2c)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_41		SMIAPP_REG_MK_U8(0x0a2d)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_42		SMIAPP_REG_MK_U8(0x0a2e)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_43		SMIAPP_REG_MK_U8(0x0a2f)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_44		SMIAPP_REG_MK_U8(0x0a30)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_45		SMIAPP_REG_MK_U8(0x0a31)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_46		SMIAPP_REG_MK_U8(0x0a32)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_47		SMIAPP_REG_MK_U8(0x0a33)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_48		SMIAPP_REG_MK_U8(0x0a34)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_49		SMIAPP_REG_MK_U8(0x0a35)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_50		SMIAPP_REG_MK_U8(0x0a36)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_51		SMIAPP_REG_MK_U8(0x0a37)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_52		SMIAPP_REG_MK_U8(0x0a38)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_53		SMIAPP_REG_MK_U8(0x0a39)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_54		SMIAPP_REG_MK_U8(0x0a3a)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_55		SMIAPP_REG_MK_U8(0x0a3b)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_56		SMIAPP_REG_MK_U8(0x0a3c)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_57		SMIAPP_REG_MK_U8(0x0a3d)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_58		SMIAPP_REG_MK_U8(0x0a3e)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_59		SMIAPP_REG_MK_U8(0x0a3f)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_60		SMIAPP_REG_MK_U8(0x0a40)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_61		SMIAPP_REG_MK_U8(0x0a41)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_62		SMIAPP_REG_MK_U8(0x0a42)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_1_DATA_63		SMIAPP_REG_MK_U8(0x0a43)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_CTRL			SMIAPP_REG_MK_U8(0x0a44)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_STATUS			SMIAPP_REG_MK_U8(0x0a45)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_PAGE_SELECT		SMIAPP_REG_MK_U8(0x0a46)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_0			SMIAPP_REG_MK_U8(0x0a48)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_1			SMIAPP_REG_MK_U8(0x0a49)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_2			SMIAPP_REG_MK_U8(0x0a4a)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_3			SMIAPP_REG_MK_U8(0x0a4b)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_4			SMIAPP_REG_MK_U8(0x0a4c)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_5			SMIAPP_REG_MK_U8(0x0a4d)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_6			SMIAPP_REG_MK_U8(0x0a4e)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_7			SMIAPP_REG_MK_U8(0x0a4f)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_8			SMIAPP_REG_MK_U8(0x0a50)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_9			SMIAPP_REG_MK_U8(0x0a51)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_10		SMIAPP_REG_MK_U8(0x0a52)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_11		SMIAPP_REG_MK_U8(0x0a53)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_12		SMIAPP_REG_MK_U8(0x0a54)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_13		SMIAPP_REG_MK_U8(0x0a55)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_14		SMIAPP_REG_MK_U8(0x0a56)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_15		SMIAPP_REG_MK_U8(0x0a57)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_16		SMIAPP_REG_MK_U8(0x0a58)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_17		SMIAPP_REG_MK_U8(0x0a59)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_18		SMIAPP_REG_MK_U8(0x0a5a)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_19		SMIAPP_REG_MK_U8(0x0a5b)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_20		SMIAPP_REG_MK_U8(0x0a5c)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_21		SMIAPP_REG_MK_U8(0x0a5d)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_22		SMIAPP_REG_MK_U8(0x0a5e)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_23		SMIAPP_REG_MK_U8(0x0a5f)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_24		SMIAPP_REG_MK_U8(0x0a60)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_25		SMIAPP_REG_MK_U8(0x0a61)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_26		SMIAPP_REG_MK_U8(0x0a62)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_27		SMIAPP_REG_MK_U8(0x0a63)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_28		SMIAPP_REG_MK_U8(0x0a64)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_29		SMIAPP_REG_MK_U8(0x0a65)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_30		SMIAPP_REG_MK_U8(0x0a66)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_31		SMIAPP_REG_MK_U8(0x0a67)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_32		SMIAPP_REG_MK_U8(0x0a68)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_33		SMIAPP_REG_MK_U8(0x0a69)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_34		SMIAPP_REG_MK_U8(0x0a6a)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_35		SMIAPP_REG_MK_U8(0x0a6b)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_36		SMIAPP_REG_MK_U8(0x0a6c)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_37		SMIAPP_REG_MK_U8(0x0a6d)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_38		SMIAPP_REG_MK_U8(0x0a6e)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_39		SMIAPP_REG_MK_U8(0x0a6f)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_40		SMIAPP_REG_MK_U8(0x0a70)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_41		SMIAPP_REG_MK_U8(0x0a71)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_42		SMIAPP_REG_MK_U8(0x0a72)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_43		SMIAPP_REG_MK_U8(0x0a73)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_44		SMIAPP_REG_MK_U8(0x0a74)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_45		SMIAPP_REG_MK_U8(0x0a75)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_46		SMIAPP_REG_MK_U8(0x0a76)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_47		SMIAPP_REG_MK_U8(0x0a77)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_48		SMIAPP_REG_MK_U8(0x0a78)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_49		SMIAPP_REG_MK_U8(0x0a79)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_50		SMIAPP_REG_MK_U8(0x0a7a)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_51		SMIAPP_REG_MK_U8(0x0a7b)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_52		SMIAPP_REG_MK_U8(0x0a7c)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_53		SMIAPP_REG_MK_U8(0x0a7d)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_54		SMIAPP_REG_MK_U8(0x0a7e)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_55		SMIAPP_REG_MK_U8(0x0a7f)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_56		SMIAPP_REG_MK_U8(0x0a80)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_57		SMIAPP_REG_MK_U8(0x0a81)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_58		SMIAPP_REG_MK_U8(0x0a82)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_59		SMIAPP_REG_MK_U8(0x0a83)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_60		SMIAPP_REG_MK_U8(0x0a84)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_61		SMIAPP_REG_MK_U8(0x0a85)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_62		SMIAPP_REG_MK_U8(0x0a86)
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_2_DATA_63		SMIAPP_REG_MK_U8(0x0a87)
+#define SMIAPP_REG_U8_SHADING_CORRECTION_ENABLE			SMIAPP_REG_MK_U8(0x0b00)
+#define SMIAPP_REG_U8_LUMINANCE_CORRECTION_LEVEL		SMIAPP_REG_MK_U8(0x0b01)
+#define SMIAPP_REG_U8_GREEN_IMBALANCE_FILTER_ENABLE		SMIAPP_REG_MK_U8(0x0b02)
+#define SMIAPP_REG_U8_GREEN_IMBALANCE_FILTER_WEIGHT		SMIAPP_REG_MK_U8(0x0b03)
+#define SMIAPP_REG_U8_BLACK_LEVEL_CORRECTION_ENABLE		SMIAPP_REG_MK_U8(0x0b04)
+#define SMIAPP_REG_U8_MAPPED_COUPLET_CORRECT_ENABLE		SMIAPP_REG_MK_U8(0x0b05)
+#define SMIAPP_REG_U8_SINGLE_DEFECT_CORRECT_ENABLE		SMIAPP_REG_MK_U8(0x0b06)
+#define SMIAPP_REG_U8_SINGLE_DEFECT_CORRECT_WEIGHT		SMIAPP_REG_MK_U8(0x0b07)
+#define SMIAPP_REG_U8_DYNAMIC_COUPLET_CORRECT_ENABLE		SMIAPP_REG_MK_U8(0x0b08)
+#define SMIAPP_REG_U8_DYNAMIC_COUPLET_CORRECT_WEIGHT		SMIAPP_REG_MK_U8(0x0b09)
+#define SMIAPP_REG_U8_COMBINED_DEFECT_CORRECT_ENABLE		SMIAPP_REG_MK_U8(0x0b0a)
+#define SMIAPP_REG_U8_COMBINED_DEFECT_CORRECT_WEIGHT		SMIAPP_REG_MK_U8(0x0b0b)
+#define SMIAPP_REG_U8_MODULE_SPECIFIC_CORRECTION_ENABLE		SMIAPP_REG_MK_U8(0x0b0c)
+#define SMIAPP_REG_U8_MODULE_SPECIFIC_CORRECTION_WEIGHT		SMIAPP_REG_MK_U8(0x0b0d)
+#define SMIAPP_REG_U8_MAPPED_LINE_DEFECT_CORRECT_ENABLE		SMIAPP_REG_MK_U8(0x0b0e)
+#define SMIAPP_REG_U8_MAPPED_LINE_DEFECT_CORRECT_ADJUST		SMIAPP_REG_MK_U8(0x0b0f)
+#define SMIAPP_REG_U8_MAPPED_COUPLET_CORRECT_ADJUST		SMIAPP_REG_MK_U8(0x0b10)
+#define SMIAPP_REG_U8_MAPPED_TRIPLET_DEFECT_CORRECT_ENABLE	SMIAPP_REG_MK_U8(0x0b11)
+#define SMIAPP_REG_U8_MAPPED_TRIPLET_DEFECT_CORRECT_ADJUST	SMIAPP_REG_MK_U8(0x0b12)
+#define SMIAPP_REG_U8_DYNAMIC_TRIPLET_DEFECT_CORRECT_ENABLE	SMIAPP_REG_MK_U8(0x0b13)
+#define SMIAPP_REG_U8_DYNAMIC_TRIPLET_DEFECT_CORRECT_ADJUST	SMIAPP_REG_MK_U8(0x0b14)
+#define SMIAPP_REG_U8_DYNAMIC_LINE_DEFECT_CORRECT_ENABLE	SMIAPP_REG_MK_U8(0x0b15)
+#define SMIAPP_REG_U8_DYNAMIC_LINE_DEFECT_CORRECT_ADJUST	SMIAPP_REG_MK_U8(0x0b16)
+#define SMIAPP_REG_U8_EDOF_MODE					SMIAPP_REG_MK_U8(0x0b80)
+#define SMIAPP_REG_U8_SHARPNESS					SMIAPP_REG_MK_U8(0x0b83)
+#define SMIAPP_REG_U8_DENOISING					SMIAPP_REG_MK_U8(0x0b84)
+#define SMIAPP_REG_U8_MODULE_SPECIFIC				SMIAPP_REG_MK_U8(0x0b85)
+#define SMIAPP_REG_U16_DEPTH_OF_FIELD				SMIAPP_REG_MK_U16(0x0b86)
+#define SMIAPP_REG_U16_FOCUS_DISTANCE				SMIAPP_REG_MK_U16(0x0b88)
+#define SMIAPP_REG_U8_ESTIMATION_MODE_CTRL			SMIAPP_REG_MK_U8(0x0b8a)
+#define SMIAPP_REG_U16_COLOUR_TEMPERATURE			SMIAPP_REG_MK_U16(0x0b8c)
+#define SMIAPP_REG_U16_ABSOLUTE_GAIN_GREENR			SMIAPP_REG_MK_U16(0x0b8e)
+#define SMIAPP_REG_U16_ABSOLUTE_GAIN_RED			SMIAPP_REG_MK_U16(0x0b90)
+#define SMIAPP_REG_U16_ABSOLUTE_GAIN_BLUE			SMIAPP_REG_MK_U16(0x0b92)
+#define SMIAPP_REG_U16_ABSOLUTE_GAIN_GREENB			SMIAPP_REG_MK_U16(0x0b94)
+#define SMIAPP_REG_U8_ESTIMATION_ZONE_MODE			SMIAPP_REG_MK_U8(0x0bc0)
+#define SMIAPP_REG_U16_FIXED_ZONE_WEIGHTING			SMIAPP_REG_MK_U16(0x0bc2)
+#define SMIAPP_REG_U16_CUSTOM_ZONE_X_START			SMIAPP_REG_MK_U16(0x0bc4)
+#define SMIAPP_REG_U16_CUSTOM_ZONE_Y_START			SMIAPP_REG_MK_U16(0x0bc6)
+#define SMIAPP_REG_U16_CUSTOM_ZONE_WIDTH			SMIAPP_REG_MK_U16(0x0bc8)
+#define SMIAPP_REG_U16_CUSTOM_ZONE_HEIGHT			SMIAPP_REG_MK_U16(0x0bca)
+#define SMIAPP_REG_U8_GLOBAL_RESET_CTRL1			SMIAPP_REG_MK_U8(0x0c00)
+#define SMIAPP_REG_U8_GLOBAL_RESET_CTRL2			SMIAPP_REG_MK_U8(0x0c01)
+#define SMIAPP_REG_U8_GLOBAL_RESET_MODE_CONFIG_1		SMIAPP_REG_MK_U8(0x0c02)
+#define SMIAPP_REG_U8_GLOBAL_RESET_MODE_CONFIG_2		SMIAPP_REG_MK_U8(0x0c03)
+#define SMIAPP_REG_U16_TRDY_CTRL				SMIAPP_REG_MK_U16(0x0c04)
+#define SMIAPP_REG_U16_TRDOUT_CTRL				SMIAPP_REG_MK_U16(0x0c06)
+#define SMIAPP_REG_U16_TSHUTTER_STROBE_DELAY_CTRL		SMIAPP_REG_MK_U16(0x0c08)
+#define SMIAPP_REG_U16_TSHUTTER_STROBE_WIDTH_CTRL		SMIAPP_REG_MK_U16(0x0c0a)
+#define SMIAPP_REG_U16_TFLASH_STROBE_DELAY_CTRL			SMIAPP_REG_MK_U16(0x0c0c)
+#define SMIAPP_REG_U16_TFLASH_STROBE_WIDTH_HIGH_CTRL		SMIAPP_REG_MK_U16(0x0c0e)
+#define SMIAPP_REG_U16_TGRST_INTERVAL_CTRL			SMIAPP_REG_MK_U16(0x0c10)
+#define SMIAPP_REG_U8_FLASH_STROBE_ADJUSTMENT			SMIAPP_REG_MK_U8(0x0c12)
+#define SMIAPP_REG_U16_FLASH_STROBE_START_POINT			SMIAPP_REG_MK_U16(0x0c14)
+#define SMIAPP_REG_U16_TFLASH_STROBE_DELAY_RS_CTRL		SMIAPP_REG_MK_U16(0x0c16)
+#define SMIAPP_REG_U16_TFLASH_STROBE_WIDTH_HIGH_RS_CTRL		SMIAPP_REG_MK_U16(0x0c18)
+#define SMIAPP_REG_U8_FLASH_MODE_RS				SMIAPP_REG_MK_U8(0x0c1a)
+#define SMIAPP_REG_U8_FLASH_TRIGGER_RS				SMIAPP_REG_MK_U8(0x0c1b)
+#define SMIAPP_REG_U8_FLASH_STATUS				SMIAPP_REG_MK_U8(0x0c1c)
+#define SMIAPP_REG_U8_SA_STROBE_MODE				SMIAPP_REG_MK_U8(0x0c1d)
+#define SMIAPP_REG_U16_SA_STROBE_START_POINT			SMIAPP_REG_MK_U16(0x0c1e)
+#define SMIAPP_REG_U16_TSA_STROBE_DELAY_CTRL			SMIAPP_REG_MK_U16(0x0c20)
+#define SMIAPP_REG_U16_TSA_STROBE_WIDTH_CTRL			SMIAPP_REG_MK_U16(0x0c22)
+#define SMIAPP_REG_U8_SA_STROBE_TRIGGER				SMIAPP_REG_MK_U8(0x0c24)
+#define SMIAPP_REG_U8_SPECIAL_ACTUATOR_STATUS			SMIAPP_REG_MK_U8(0x0c25)
+#define SMIAPP_REG_U16_TFLASH_STROBE_WIDTH2_HIGH_RS_CTRL	SMIAPP_REG_MK_U16(0x0c26)
+#define SMIAPP_REG_U16_TFLASH_STROBE_WIDTH_LOW_RS_CTRL		SMIAPP_REG_MK_U16(0x0c28)
+#define SMIAPP_REG_U8_TFLASH_STROBE_COUNT_RS_CTRL		SMIAPP_REG_MK_U8(0x0c2a)
+#define SMIAPP_REG_U8_TFLASH_STROBE_COUNT_CTRL			SMIAPP_REG_MK_U8(0x0c2b)
+#define SMIAPP_REG_U16_TFLASH_STROBE_WIDTH2_HIGH_CTRL		SMIAPP_REG_MK_U16(0x0c2c)
+#define SMIAPP_REG_U16_TFLASH_STROBE_WIDTH_LOW_CTRL		SMIAPP_REG_MK_U16(0x0c2e)
+#define SMIAPP_REG_U8_LOW_LEVEL_CTRL				SMIAPP_REG_MK_U8(0x0c80)
+#define SMIAPP_REG_U16_MAIN_TRIGGER_REF_POINT			SMIAPP_REG_MK_U16(0x0c82)
+#define SMIAPP_REG_U16_MAIN_TRIGGER_T3				SMIAPP_REG_MK_U16(0x0c84)
+#define SMIAPP_REG_U8_MAIN_TRIGGER_COUNT			SMIAPP_REG_MK_U8(0x0c86)
+#define SMIAPP_REG_U16_PHASE1_TRIGGER_T3			SMIAPP_REG_MK_U16(0x0c88)
+#define SMIAPP_REG_U8_PHASE1_TRIGGER_COUNT			SMIAPP_REG_MK_U8(0x0c8a)
+#define SMIAPP_REG_U16_PHASE2_TRIGGER_T3			SMIAPP_REG_MK_U16(0x0c8c)
+#define SMIAPP_REG_U8_PHASE2_TRIGGER_COUNT			SMIAPP_REG_MK_U8(0x0c8e)
+#define SMIAPP_REG_U8_MECH_SHUTTER_CTRL				SMIAPP_REG_MK_U8(0x0d00)
+#define SMIAPP_REG_U8_OPERATION_MODE				SMIAPP_REG_MK_U8(0x0d01)
+#define SMIAPP_REG_U8_ACT_STATE1				SMIAPP_REG_MK_U8(0x0d02)
+#define SMIAPP_REG_U8_ACT_STATE2				SMIAPP_REG_MK_U8(0x0d03)
+#define SMIAPP_REG_U16_FOCUS_CHANGE				SMIAPP_REG_MK_U16(0x0d80)
+#define SMIAPP_REG_U16_FOCUS_CHANGE_CONTROL			SMIAPP_REG_MK_U16(0x0d82)
+#define SMIAPP_REG_U16_FOCUS_CHANGE_NUMBER_PHASE1		SMIAPP_REG_MK_U16(0x0d84)
+#define SMIAPP_REG_U16_FOCUS_CHANGE_NUMBER_PHASE2		SMIAPP_REG_MK_U16(0x0d86)
+#define SMIAPP_REG_U8_STROBE_COUNT_PHASE1			SMIAPP_REG_MK_U8(0x0d88)
+#define SMIAPP_REG_U8_STROBE_COUNT_PHASE2			SMIAPP_REG_MK_U8(0x0d89)
+#define SMIAPP_REG_U8_POSITION					SMIAPP_REG_MK_U8(0x0d8a)
+#define SMIAPP_REG_U8_BRACKETING_LUT_CONTROL			SMIAPP_REG_MK_U8(0x0e00)
+#define SMIAPP_REG_U8_BRACKETING_LUT_MODE			SMIAPP_REG_MK_U8(0x0e01)
+#define SMIAPP_REG_U8_BRACKETING_LUT_ENTRY_CONTROL		SMIAPP_REG_MK_U8(0x0e02)
+#define SMIAPP_REG_U8_LUT_PARAMETERS_START			SMIAPP_REG_MK_U8(0x0e10)
+#define SMIAPP_REG_U8_LUT_PARAMETERS_END			SMIAPP_REG_MK_U8(0x0eff)
+#define SMIAPP_REG_U16_INTEGRATION_TIME_CAPABILITY		SMIAPP_REG_MK_U16(0x1000)
+#define SMIAPP_REG_U16_COARSE_INTEGRATION_TIME_MIN		SMIAPP_REG_MK_U16(0x1004)
+#define SMIAPP_REG_U16_COARSE_INTEGRATION_TIME_MAX_MARGIN	SMIAPP_REG_MK_U16(0x1006)
+#define SMIAPP_REG_U16_FINE_INTEGRATION_TIME_MIN		SMIAPP_REG_MK_U16(0x1008)
+#define SMIAPP_REG_U16_FINE_INTEGRATION_TIME_MAX_MARGIN		SMIAPP_REG_MK_U16(0x100a)
+#define SMIAPP_REG_U16_DIGITAL_GAIN_CAPABILITY			SMIAPP_REG_MK_U16(0x1080)
+#define SMIAPP_REG_U16_DIGITAL_GAIN_MIN				SMIAPP_REG_MK_U16(0x1084)
+#define SMIAPP_REG_U16_DIGITAL_GAIN_MAX				SMIAPP_REG_MK_U16(0x1086)
+#define SMIAPP_REG_U16_DIGITAL_GAIN_STEP_SIZE			SMIAPP_REG_MK_U16(0x1088)
+#define SMIAPP_REG_F32_MIN_EXT_CLK_FREQ_HZ			SMIAPP_REG_MK_F32(0x1100)
+#define SMIAPP_REG_F32_MAX_EXT_CLK_FREQ_HZ			SMIAPP_REG_MK_F32(0x1104)
+#define SMIAPP_REG_U16_MIN_PRE_PLL_CLK_DIV			SMIAPP_REG_MK_U16(0x1108)
+#define SMIAPP_REG_U16_MAX_PRE_PLL_CLK_DIV			SMIAPP_REG_MK_U16(0x110a)
+#define SMIAPP_REG_F32_MIN_PLL_IP_FREQ_HZ			SMIAPP_REG_MK_F32(0x110c)
+#define SMIAPP_REG_F32_MAX_PLL_IP_FREQ_HZ			SMIAPP_REG_MK_F32(0x1110)
+#define SMIAPP_REG_U16_MIN_PLL_MULTIPLIER			SMIAPP_REG_MK_U16(0x1114)
+#define SMIAPP_REG_U16_MAX_PLL_MULTIPLIER			SMIAPP_REG_MK_U16(0x1116)
+#define SMIAPP_REG_F32_MIN_PLL_OP_FREQ_HZ			SMIAPP_REG_MK_F32(0x1118)
+#define SMIAPP_REG_F32_MAX_PLL_OP_FREQ_HZ			SMIAPP_REG_MK_F32(0x111c)
+#define SMIAPP_REG_U16_MIN_VT_SYS_CLK_DIV			SMIAPP_REG_MK_U16(0x1120)
+#define SMIAPP_REG_U16_MAX_VT_SYS_CLK_DIV			SMIAPP_REG_MK_U16(0x1122)
+#define SMIAPP_REG_F32_MIN_VT_SYS_CLK_FREQ_HZ			SMIAPP_REG_MK_F32(0x1124)
+#define SMIAPP_REG_F32_MAX_VT_SYS_CLK_FREQ_HZ			SMIAPP_REG_MK_F32(0x1128)
+#define SMIAPP_REG_F32_MIN_VT_PIX_CLK_FREQ_HZ			SMIAPP_REG_MK_F32(0x112c)
+#define SMIAPP_REG_F32_MAX_VT_PIX_CLK_FREQ_HZ			SMIAPP_REG_MK_F32(0x1130)
+#define SMIAPP_REG_U16_MIN_VT_PIX_CLK_DIV			SMIAPP_REG_MK_U16(0x1134)
+#define SMIAPP_REG_U16_MAX_VT_PIX_CLK_DIV			SMIAPP_REG_MK_U16(0x1136)
+#define SMIAPP_REG_U16_MIN_FRAME_LENGTH_LINES			SMIAPP_REG_MK_U16(0x1140)
+#define SMIAPP_REG_U16_MAX_FRAME_LENGTH_LINES			SMIAPP_REG_MK_U16(0x1142)
+#define SMIAPP_REG_U16_MIN_LINE_LENGTH_PCK			SMIAPP_REG_MK_U16(0x1144)
+#define SMIAPP_REG_U16_MAX_LINE_LENGTH_PCK			SMIAPP_REG_MK_U16(0x1146)
+#define SMIAPP_REG_U16_MIN_LINE_BLANKING_PCK			SMIAPP_REG_MK_U16(0x1148)
+#define SMIAPP_REG_U16_MIN_FRAME_BLANKING_LINES			SMIAPP_REG_MK_U16(0x114a)
+#define SMIAPP_REG_U8_MIN_LINE_LENGTH_PCK_STEP_SIZE		SMIAPP_REG_MK_U8(0x114c)
+#define SMIAPP_REG_U16_MIN_OP_SYS_CLK_DIV			SMIAPP_REG_MK_U16(0x1160)
+#define SMIAPP_REG_U16_MAX_OP_SYS_CLK_DIV			SMIAPP_REG_MK_U16(0x1162)
+#define SMIAPP_REG_F32_MIN_OP_SYS_CLK_FREQ_HZ			SMIAPP_REG_MK_F32(0x1164)
+#define SMIAPP_REG_F32_MAX_OP_SYS_CLK_FREQ_HZ			SMIAPP_REG_MK_F32(0x1168)
+#define SMIAPP_REG_U16_MIN_OP_PIX_CLK_DIV			SMIAPP_REG_MK_U16(0x116c)
+#define SMIAPP_REG_U16_MAX_OP_PIX_CLK_DIV			SMIAPP_REG_MK_U16(0x116e)
+#define SMIAPP_REG_F32_MIN_OP_PIX_CLK_FREQ_HZ			SMIAPP_REG_MK_F32(0x1170)
+#define SMIAPP_REG_F32_MAX_OP_PIX_CLK_FREQ_HZ			SMIAPP_REG_MK_F32(0x1174)
+#define SMIAPP_REG_U16_X_ADDR_MIN				SMIAPP_REG_MK_U16(0x1180)
+#define SMIAPP_REG_U16_Y_ADDR_MIN				SMIAPP_REG_MK_U16(0x1182)
+#define SMIAPP_REG_U16_X_ADDR_MAX				SMIAPP_REG_MK_U16(0x1184)
+#define SMIAPP_REG_U16_Y_ADDR_MAX				SMIAPP_REG_MK_U16(0x1186)
+#define SMIAPP_REG_U16_MIN_X_OUTPUT_SIZE			SMIAPP_REG_MK_U16(0x1188)
+#define SMIAPP_REG_U16_MIN_Y_OUTPUT_SIZE			SMIAPP_REG_MK_U16(0x118a)
+#define SMIAPP_REG_U16_MAX_X_OUTPUT_SIZE			SMIAPP_REG_MK_U16(0x118c)
+#define SMIAPP_REG_U16_MAX_Y_OUTPUT_SIZE			SMIAPP_REG_MK_U16(0x118e)
+#define SMIAPP_REG_U16_MIN_EVEN_INC				SMIAPP_REG_MK_U16(0x11c0)
+#define SMIAPP_REG_U16_MAX_EVEN_INC				SMIAPP_REG_MK_U16(0x11c2)
+#define SMIAPP_REG_U16_MIN_ODD_INC				SMIAPP_REG_MK_U16(0x11c4)
+#define SMIAPP_REG_U16_MAX_ODD_INC				SMIAPP_REG_MK_U16(0x11c6)
+#define SMIAPP_REG_U16_SCALING_CAPABILITY			SMIAPP_REG_MK_U16(0x1200)
+#define SMIAPP_REG_U16_SCALER_M_MIN				SMIAPP_REG_MK_U16(0x1204)
+#define SMIAPP_REG_U16_SCALER_M_MAX				SMIAPP_REG_MK_U16(0x1206)
+#define SMIAPP_REG_U16_SCALER_N_MIN				SMIAPP_REG_MK_U16(0x1208)
+#define SMIAPP_REG_U16_SCALER_N_MAX				SMIAPP_REG_MK_U16(0x120a)
+#define SMIAPP_REG_U16_SPATIAL_SAMPLING_CAPABILITY		SMIAPP_REG_MK_U16(0x120c)
+#define SMIAPP_REG_U8_DIGITAL_CROP_CAPABILITY			SMIAPP_REG_MK_U8(0x120e)
+#define SMIAPP_REG_U16_COMPRESSION_CAPABILITY			SMIAPP_REG_MK_U16(0x1300)
+#define SMIAPP_REG_U16_MATRIX_ELEMENT_REDINRED			SMIAPP_REG_MK_U16(0x1400)
+#define SMIAPP_REG_U16_MATRIX_ELEMENT_GREENINRED		SMIAPP_REG_MK_U16(0x1402)
+#define SMIAPP_REG_U16_MATRIX_ELEMENT_BLUEINRED			SMIAPP_REG_MK_U16(0x1404)
+#define SMIAPP_REG_U16_MATRIX_ELEMENT_REDINGREEN		SMIAPP_REG_MK_U16(0x1406)
+#define SMIAPP_REG_U16_MATRIX_ELEMENT_GREENINGREEN		SMIAPP_REG_MK_U16(0x1408)
+#define SMIAPP_REG_U16_MATRIX_ELEMENT_BLUEINGREEN		SMIAPP_REG_MK_U16(0x140a)
+#define SMIAPP_REG_U16_MATRIX_ELEMENT_REDINBLUE			SMIAPP_REG_MK_U16(0x140c)
+#define SMIAPP_REG_U16_MATRIX_ELEMENT_GREENINBLUE		SMIAPP_REG_MK_U16(0x140e)
+#define SMIAPP_REG_U16_MATRIX_ELEMENT_BLUEINBLUE		SMIAPP_REG_MK_U16(0x1410)
+#define SMIAPP_REG_U16_FIFO_SIZE_PIXELS				SMIAPP_REG_MK_U16(0x1500)
+#define SMIAPP_REG_U8_FIFO_SUPPORT_CAPABILITY			SMIAPP_REG_MK_U8(0x1502)
+#define SMIAPP_REG_U8_DPHY_CTRL_CAPABILITY			SMIAPP_REG_MK_U8(0x1600)
+#define SMIAPP_REG_U8_CSI_LANE_MODE_CAPABILITY			SMIAPP_REG_MK_U8(0x1601)
+#define SMIAPP_REG_U8_CSI_SIGNALLING_MODE_CAPABILITY		SMIAPP_REG_MK_U8(0x1602)
+#define SMIAPP_REG_U8_FAST_STANDBY_CAPABILITY			SMIAPP_REG_MK_U8(0x1603)
+#define SMIAPP_REG_U8_CCI_ADDRESS_CONTROL_CAPABILITY		SMIAPP_REG_MK_U8(0x1604)
+#define SMIAPP_REG_U32_MAX_PER_LANE_BITRATE_1_LANE_MODE_MBPS	SMIAPP_REG_MK_U32(0x1608)
+#define SMIAPP_REG_U32_MAX_PER_LANE_BITRATE_2_LANE_MODE_MBPS	SMIAPP_REG_MK_U32(0x160c)
+#define SMIAPP_REG_U32_MAX_PER_LANE_BITRATE_3_LANE_MODE_MBPS	SMIAPP_REG_MK_U32(0x1610)
+#define SMIAPP_REG_U32_MAX_PER_LANE_BITRATE_4_LANE_MODE_MBPS	SMIAPP_REG_MK_U32(0x1614)
+#define SMIAPP_REG_U8_TEMP_SENSOR_CAPABILITY			SMIAPP_REG_MK_U8(0x1618)
+#define SMIAPP_REG_U16_MIN_FRAME_LENGTH_LINES_BIN		SMIAPP_REG_MK_U16(0x1700)
+#define SMIAPP_REG_U16_MAX_FRAME_LENGTH_LINES_BIN		SMIAPP_REG_MK_U16(0x1702)
+#define SMIAPP_REG_U16_MIN_LINE_LENGTH_PCK_BIN			SMIAPP_REG_MK_U16(0x1704)
+#define SMIAPP_REG_U16_MAX_LINE_LENGTH_PCK_BIN			SMIAPP_REG_MK_U16(0x1706)
+#define SMIAPP_REG_U16_MIN_LINE_BLANKING_PCK_BIN		SMIAPP_REG_MK_U16(0x1708)
+#define SMIAPP_REG_U16_FINE_INTEGRATION_TIME_MIN_BIN		SMIAPP_REG_MK_U16(0x170a)
+#define SMIAPP_REG_U16_FINE_INTEGRATION_TIME_MAX_MARGIN_BIN	SMIAPP_REG_MK_U16(0x170c)
+#define SMIAPP_REG_U8_BINNING_CAPABILITY			SMIAPP_REG_MK_U8(0x1710)
+#define SMIAPP_REG_U8_BINNING_WEIGHTING_CAPABILITY		SMIAPP_REG_MK_U8(0x1711)
+#define SMIAPP_REG_U8_BINNING_SUBTYPES				SMIAPP_REG_MK_U8(0x1712)
+#define SMIAPP_REG_U8_BINNING_TYPE_n(n)				SMIAPP_REG_MK_U8(0x1713 + (n)) /* 1 <= n <= 237 */
+#define SMIAPP_REG_U8_DATA_TRANSFER_IF_CAPABILITY		SMIAPP_REG_MK_U8(0x1800)
+#define SMIAPP_REG_U8_SHADING_CORRECTION_CAPABILITY		SMIAPP_REG_MK_U8(0x1900)
+#define SMIAPP_REG_U8_GREEN_IMBALANCE_CAPABILITY		SMIAPP_REG_MK_U8(0x1901)
+#define SMIAPP_REG_U8_BLACK_LEVEL_CAPABILITY			SMIAPP_REG_MK_U8(0x1902)
+#define SMIAPP_REG_U8_MODULE_SPECIFIC_CORRECTION_CAPABILITY	SMIAPP_REG_MK_U8(0x1903)
+#define SMIAPP_REG_U16_DEFECT_CORRECTION_CAPABILITY		SMIAPP_REG_MK_U16(0x1904)
+#define SMIAPP_REG_U16_DEFECT_CORRECTION_CAPABILITY_2		SMIAPP_REG_MK_U16(0x1906)
+#define SMIAPP_REG_U8_EDOF_CAPABILITY				SMIAPP_REG_MK_U8(0x1980)
+#define SMIAPP_REG_U8_ESTIMATION_FRAMES				SMIAPP_REG_MK_U8(0x1981)
+#define SMIAPP_REG_U8_SUPPORTS_SHARPNESS_ADJ			SMIAPP_REG_MK_U8(0x1982)
+#define SMIAPP_REG_U8_SUPPORTS_DENOISING_ADJ			SMIAPP_REG_MK_U8(0x1983)
+#define SMIAPP_REG_U8_SUPPORTS_MODULE_SPECIFIC_ADJ		SMIAPP_REG_MK_U8(0x1984)
+#define SMIAPP_REG_U8_SUPPORTS_DEPTH_OF_FIELD_ADJ		SMIAPP_REG_MK_U8(0x1985)
+#define SMIAPP_REG_U8_SUPPORTS_FOCUS_DISTANCE_ADJ		SMIAPP_REG_MK_U8(0x1986)
+#define SMIAPP_REG_U8_COLOUR_FEEDBACK_CAPABILITY		SMIAPP_REG_MK_U8(0x1987)
+#define SMIAPP_REG_U8_EDOF_SUPPORT_AB_NXM			SMIAPP_REG_MK_U8(0x1988)
+#define SMIAPP_REG_U8_ESTIMATION_MODE_CAPABILITY		SMIAPP_REG_MK_U8(0x19c0)
+#define SMIAPP_REG_U8_ESTIMATION_ZONE_CAPABILITY		SMIAPP_REG_MK_U8(0x19c1)
+#define SMIAPP_REG_U16_EST_DEPTH_OF_FIELD			SMIAPP_REG_MK_U16(0x19c2)
+#define SMIAPP_REG_U16_EST_FOCUS_DISTANCE			SMIAPP_REG_MK_U16(0x19c4)
+#define SMIAPP_REG_U16_CAPABILITY_TRDY_MIN			SMIAPP_REG_MK_U16(0x1a00)
+#define SMIAPP_REG_U8_FLASH_MODE_CAPABILITY			SMIAPP_REG_MK_U8(0x1a02)
+#define SMIAPP_REG_U16_MECH_SHUT_AND_ACT_START_ADDR		SMIAPP_REG_MK_U16(0x1b02)
+#define SMIAPP_REG_U8_ACTUATOR_CAPABILITY			SMIAPP_REG_MK_U8(0x1b04)
+#define SMIAPP_REG_U16_ACTUATOR_TYPE				SMIAPP_REG_MK_U16(0x1b40)
+#define SMIAPP_REG_U8_AF_DEVICE_ADDRESS				SMIAPP_REG_MK_U8(0x1b42)
+#define SMIAPP_REG_U16_FOCUS_CHANGE_ADDRESS			SMIAPP_REG_MK_U16(0x1b44)
+#define SMIAPP_REG_U8_BRACKETING_LUT_CAPABILITY_1		SMIAPP_REG_MK_U8(0x1c00)
+#define SMIAPP_REG_U8_BRACKETING_LUT_CAPABILITY_2		SMIAPP_REG_MK_U8(0x1c01)
+#define SMIAPP_REG_U8_BRACKETING_LUT_SIZE			SMIAPP_REG_MK_U8(0x1c02)
diff --git a/drivers/media/i2c/smiapp/smiapp-reg.h b/drivers/media/i2c/smiapp/smiapp-reg.h
new file mode 100644
index 0000000..54568ca
--- /dev/null
+++ b/drivers/media/i2c/smiapp/smiapp-reg.h
@@ -0,0 +1,122 @@
+/*
+ * drivers/media/i2c/smiapp/smiapp-reg.h
+ *
+ * Generic driver for SMIA/SMIA++ compliant camera modules
+ *
+ * Copyright (C) 2011--2012 Nokia Corporation
+ * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __SMIAPP_REG_H_
+#define __SMIAPP_REG_H_
+
+#include "smiapp-reg-defs.h"
+
+/* Bits for above register */
+#define SMIAPP_IMAGE_ORIENTATION_HFLIP		(1 << 0)
+#define SMIAPP_IMAGE_ORIENTATION_VFLIP		(1 << 1)
+
+#define SMIAPP_DATA_TRANSFER_IF_1_CTRL_EN		(1 << 0)
+#define SMIAPP_DATA_TRANSFER_IF_1_CTRL_RD_EN		(0 << 1)
+#define SMIAPP_DATA_TRANSFER_IF_1_CTRL_WR_EN		(1 << 1)
+#define SMIAPP_DATA_TRANSFER_IF_1_CTRL_ERR_CLEAR	(1 << 2)
+#define SMIAPP_DATA_TRANSFER_IF_1_STATUS_RD_READY	(1 << 0)
+#define SMIAPP_DATA_TRANSFER_IF_1_STATUS_WR_READY	(1 << 1)
+#define SMIAPP_DATA_TRANSFER_IF_1_STATUS_EDATA		(1 << 2)
+#define SMIAPP_DATA_TRANSFER_IF_1_STATUS_EUSAGE		(1 << 3)
+
+#define SMIAPP_SOFTWARE_RESET				(1 << 0)
+
+#define SMIAPP_FLASH_MODE_CAPABILITY_SINGLE_STROBE	(1 << 0)
+#define SMIAPP_FLASH_MODE_CAPABILITY_MULTIPLE_STROBE	(1 << 1)
+
+#define SMIAPP_DPHY_CTRL_AUTOMATIC			0
+/* DPHY control based on REQUESTED_LINK_BIT_RATE_MBPS */
+#define SMIAPP_DPHY_CTRL_UI				1
+#define SMIAPP_DPHY_CTRL_REGISTER			2
+
+#define SMIAPP_COMPRESSION_MODE_SIMPLE_PREDICTOR	1
+#define SMIAPP_COMPRESSION_MODE_ADVANCED_PREDICTOR	2
+
+#define SMIAPP_MODE_SELECT_SOFTWARE_STANDBY		0
+#define SMIAPP_MODE_SELECT_STREAMING			1
+
+#define SMIAPP_SCALING_MODE_NONE			0
+#define SMIAPP_SCALING_MODE_HORIZONTAL			1
+#define SMIAPP_SCALING_MODE_BOTH			2
+
+#define SMIAPP_SCALING_CAPABILITY_NONE			0
+#define SMIAPP_SCALING_CAPABILITY_HORIZONTAL		1
+#define SMIAPP_SCALING_CAPABILITY_BOTH			2 /* horizontal/both */
+
+/* digital crop right before scaler */
+#define SMIAPP_DIGITAL_CROP_CAPABILITY_NONE		0
+#define SMIAPP_DIGITAL_CROP_CAPABILITY_INPUT_CROP	1
+
+#define SMIAPP_BINNING_CAPABILITY_NO			0
+#define SMIAPP_BINNING_CAPABILITY_YES			1
+
+/* Maximum number of binning subtypes */
+#define SMIAPP_BINNING_SUBTYPES				253
+
+#define SMIAPP_PIXEL_ORDER_GRBG				0
+#define SMIAPP_PIXEL_ORDER_RGGB				1
+#define SMIAPP_PIXEL_ORDER_BGGR				2
+#define SMIAPP_PIXEL_ORDER_GBRG				3
+
+#define SMIAPP_DATA_FORMAT_MODEL_TYPE_NORMAL		1
+#define SMIAPP_DATA_FORMAT_MODEL_TYPE_EXTENDED		2
+#define SMIAPP_DATA_FORMAT_MODEL_TYPE_NORMAL_N		8
+#define SMIAPP_DATA_FORMAT_MODEL_TYPE_EXTENDED_N	16
+
+#define SMIAPP_FRAME_FORMAT_MODEL_TYPE_2BYTE		0x01
+#define SMIAPP_FRAME_FORMAT_MODEL_TYPE_4BYTE		0x02
+#define SMIAPP_FRAME_FORMAT_MODEL_SUBTYPE_NROWS_MASK	0x0f
+#define SMIAPP_FRAME_FORMAT_MODEL_SUBTYPE_NCOLS_MASK	0xf0
+#define SMIAPP_FRAME_FORMAT_MODEL_SUBTYPE_NCOLS_SHIFT	4
+
+#define SMIAPP_FRAME_FORMAT_DESC_2_PIXELCODE_MASK	0xf000
+#define SMIAPP_FRAME_FORMAT_DESC_2_PIXELCODE_SHIFT	12
+#define SMIAPP_FRAME_FORMAT_DESC_2_PIXELS_MASK		0x0fff
+
+#define SMIAPP_FRAME_FORMAT_DESC_4_PIXELCODE_MASK	0xf0000000
+#define SMIAPP_FRAME_FORMAT_DESC_4_PIXELCODE_SHIFT	28
+#define SMIAPP_FRAME_FORMAT_DESC_4_PIXELS_MASK		0x0000ffff
+
+#define SMIAPP_FRAME_FORMAT_DESC_PIXELCODE_EMBEDDED	1
+#define SMIAPP_FRAME_FORMAT_DESC_PIXELCODE_DUMMY	2
+#define SMIAPP_FRAME_FORMAT_DESC_PIXELCODE_BLACK	3
+#define SMIAPP_FRAME_FORMAT_DESC_PIXELCODE_DARK		4
+#define SMIAPP_FRAME_FORMAT_DESC_PIXELCODE_VISIBLE	5
+
+#define SMIAPP_FAST_STANDBY_CTRL_COMPLETE_FRAMES	0
+#define SMIAPP_FAST_STANDBY_CTRL_IMMEDIATE		1
+
+/* Scaling N factor */
+#define SMIAPP_SCALE_N					16
+
+/* Image statistics registers */
+/* Registers 0x2000 to 0x2fff are reserved for future
+ * use for statistics features.
+ */
+
+/* Manufacturer Specific Registers: 0x3000 to 0x3fff
+ * The manufacturer specifies these as a black box.
+ */
+
+#endif /* __SMIAPP_REG_H_ */
diff --git a/drivers/media/i2c/smiapp/smiapp-regs.c b/drivers/media/i2c/smiapp/smiapp-regs.c
new file mode 100644
index 0000000..70e0d8d
--- /dev/null
+++ b/drivers/media/i2c/smiapp/smiapp-regs.c
@@ -0,0 +1,273 @@
+/*
+ * drivers/media/i2c/smiapp/smiapp-regs.c
+ *
+ * Generic driver for SMIA/SMIA++ compliant camera modules
+ *
+ * Copyright (C) 2011--2012 Nokia Corporation
+ * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/i2c.h>
+
+#include "smiapp.h"
+#include "smiapp-regs.h"
+
+static uint32_t float_to_u32_mul_1000000(struct i2c_client *client,
+					 uint32_t phloat)
+{
+	int32_t exp;
+	uint64_t man;
+
+	if (phloat >= 0x80000000) {
+		dev_err(&client->dev, "this is a negative number\n");
+		return 0;
+	}
+
+	if (phloat == 0x7f800000)
+		return ~0; /* Inf. */
+
+	if ((phloat & 0x7f800000) == 0x7f800000) {
+		dev_err(&client->dev, "NaN or other special number\n");
+		return 0;
+	}
+
+	/* Valid cases begin here */
+	if (phloat == 0)
+		return 0; /* Valid zero */
+
+	if (phloat > 0x4f800000)
+		return ~0; /* larger than 4294967295 */
+
+	/*
+	 * Unbias exponent (note how phloat is now guaranteed to
+	 * have 0 in the high bit)
+	 */
+	exp = ((int32_t)phloat >> 23) - 127;
+
+	/* Extract mantissa, add missing '1' bit and it's in MHz */
+	man = ((phloat & 0x7fffff) | 0x800000) * 1000000ULL;
+
+	if (exp < 0)
+		man >>= -exp;
+	else
+		man <<= exp;
+
+	man >>= 23; /* Remove mantissa bias */
+
+	return man & 0xffffffff;
+}
+
+
+/*
+ * Read a 8/16/32-bit i2c register.  The value is returned in 'val'.
+ * Returns zero if successful, or non-zero otherwise.
+ */
+static int ____smiapp_read(struct smiapp_sensor *sensor, u16 reg,
+			   u16 len, u32 *val)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
+	struct i2c_msg msg;
+	unsigned char data[4];
+	u16 offset = reg;
+	int r;
+
+	msg.addr = client->addr;
+	msg.flags = 0;
+	msg.len = 2;
+	msg.buf = data;
+
+	/* high byte goes out first */
+	data[0] = (u8) (offset >> 8);
+	data[1] = (u8) offset;
+	r = i2c_transfer(client->adapter, &msg, 1);
+	if (r != 1) {
+		if (r >= 0)
+			r = -EBUSY;
+		goto err;
+	}
+
+	msg.len = len;
+	msg.flags = I2C_M_RD;
+	r = i2c_transfer(client->adapter, &msg, 1);
+	if (r != 1) {
+		if (r >= 0)
+			r = -EBUSY;
+		goto err;
+	}
+
+	*val = 0;
+	/* high byte comes first */
+	switch (len) {
+	case SMIA_REG_32BIT:
+		*val = (data[0] << 24) + (data[1] << 16) + (data[2] << 8) +
+			data[3];
+		break;
+	case SMIA_REG_16BIT:
+		*val = (data[0] << 8) + data[1];
+		break;
+	case SMIA_REG_8BIT:
+		*val = data[0];
+		break;
+	default:
+		BUG();
+	}
+
+	return 0;
+
+err:
+	dev_err(&client->dev, "read from offset 0x%x error %d\n", offset, r);
+
+	return r;
+}
+
+/* Read a register using 8-bit access only. */
+static int ____smiapp_read_8only(struct smiapp_sensor *sensor, u16 reg,
+				 u16 len, u32 *val)
+{
+	unsigned int i;
+	int rval;
+
+	*val = 0;
+
+	for (i = 0; i < len; i++) {
+		u32 val8;
+
+		rval = ____smiapp_read(sensor, reg + i, 1, &val8);
+		if (rval < 0)
+			return rval;
+		*val |= val8 << ((len - i - 1) << 3);
+	}
+
+	return 0;
+}
+
+/*
+ * Read a 8/16/32-bit i2c register.  The value is returned in 'val'.
+ * Returns zero if successful, or non-zero otherwise.
+ */
+static int __smiapp_read(struct smiapp_sensor *sensor, u32 reg, u32 *val,
+			 bool only8)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
+	unsigned int len = (u8)(reg >> 16);
+	int rval;
+
+	if (len != SMIA_REG_8BIT && len != SMIA_REG_16BIT
+	    && len != SMIA_REG_32BIT)
+		return -EINVAL;
+
+	if (smiapp_quirk_reg(sensor, reg, val))
+		goto found_quirk;
+
+	if (len == SMIA_REG_8BIT && !only8)
+		rval = ____smiapp_read(sensor, (u16)reg, len, val);
+	else
+		rval = ____smiapp_read_8only(sensor, (u16)reg, len, val);
+	if (rval < 0)
+		return rval;
+
+found_quirk:
+	if (reg & SMIA_REG_FLAG_FLOAT)
+		*val = float_to_u32_mul_1000000(client, *val);
+
+	return 0;
+}
+
+int smiapp_read(struct smiapp_sensor *sensor, u32 reg, u32 *val)
+{
+	return __smiapp_read(
+		sensor, reg, val,
+		smiapp_needs_quirk(sensor,
+				   SMIAPP_QUIRK_FLAG_8BIT_READ_ONLY));
+}
+
+int smiapp_read_8only(struct smiapp_sensor *sensor, u32 reg, u32 *val)
+{
+	return __smiapp_read(sensor, reg, val, true);
+}
+
+/*
+ * Write to a 8/16-bit register.
+ * Returns zero if successful, or non-zero otherwise.
+ */
+int smiapp_write(struct smiapp_sensor *sensor, u32 reg, u32 val)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
+	struct i2c_msg msg;
+	unsigned char data[6];
+	unsigned int retries;
+	unsigned int flags = reg >> 24;
+	unsigned int len = (u8)(reg >> 16);
+	u16 offset = reg;
+	int r;
+
+	if ((len != SMIA_REG_8BIT && len != SMIA_REG_16BIT &&
+	     len != SMIA_REG_32BIT) || flags)
+		return -EINVAL;
+
+	msg.addr = client->addr;
+	msg.flags = 0; /* Write */
+	msg.len = 2 + len;
+	msg.buf = data;
+
+	/* high byte goes out first */
+	data[0] = (u8) (reg >> 8);
+	data[1] = (u8) (reg & 0xff);
+
+	switch (len) {
+	case SMIA_REG_8BIT:
+		data[2] = val;
+		break;
+	case SMIA_REG_16BIT:
+		data[2] = val >> 8;
+		data[3] = val;
+		break;
+	case SMIA_REG_32BIT:
+		data[2] = val >> 24;
+		data[3] = val >> 16;
+		data[4] = val >> 8;
+		data[5] = val;
+		break;
+	default:
+		BUG();
+	}
+
+	for (retries = 0; retries < 5; retries++) {
+		/*
+		 * Due to unknown reason sensor stops responding. This
+		 * loop is a temporaty solution until the root cause
+		 * is found.
+		 */
+		r = i2c_transfer(client->adapter, &msg, 1);
+		if (r == 1) {
+			if (retries)
+				dev_err(&client->dev,
+					"sensor i2c stall encountered. "
+					"retries: %d\n", retries);
+			return 0;
+		}
+
+		usleep_range(2000, 2000);
+	}
+
+	dev_err(&client->dev,
+		"wrote 0x%x to offset 0x%x error %d\n", val, offset, r);
+
+	return r;
+}
diff --git a/drivers/media/i2c/smiapp/smiapp-regs.h b/drivers/media/i2c/smiapp/smiapp-regs.h
new file mode 100644
index 0000000..7f9013b
--- /dev/null
+++ b/drivers/media/i2c/smiapp/smiapp-regs.h
@@ -0,0 +1,49 @@
+/*
+ * include/media/smiapp/smiapp-regs.h
+ *
+ * Generic driver for SMIA/SMIA++ compliant camera modules
+ *
+ * Copyright (C) 2011--2012 Nokia Corporation
+ * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef SMIAPP_REGS_H
+#define SMIAPP_REGS_H
+
+#include <linux/i2c.h>
+#include <linux/types.h>
+
+/* Use upper 8 bits of the type field for flags */
+#define SMIA_REG_FLAG_FLOAT		(1 << 24)
+
+#define SMIA_REG_8BIT			1
+#define SMIA_REG_16BIT			2
+#define SMIA_REG_32BIT			4
+struct smia_reg {
+	u16 type;
+	u16 reg;			/* 16-bit offset */
+	u32 val;			/* 8/16/32-bit value */
+};
+
+struct smiapp_sensor;
+
+int smiapp_read(struct smiapp_sensor *sensor, u32 reg, u32 *val);
+int smiapp_read_8only(struct smiapp_sensor *sensor, u32 reg, u32 *val);
+int smiapp_write(struct smiapp_sensor *sensor, u32 reg, u32 val);
+
+#endif
diff --git a/drivers/media/i2c/smiapp/smiapp.h b/drivers/media/i2c/smiapp/smiapp.h
new file mode 100644
index 0000000..4182a69
--- /dev/null
+++ b/drivers/media/i2c/smiapp/smiapp.h
@@ -0,0 +1,252 @@
+/*
+ * drivers/media/i2c/smiapp/smiapp.h
+ *
+ * Generic driver for SMIA/SMIA++ compliant camera modules
+ *
+ * Copyright (C) 2010--2012 Nokia Corporation
+ * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __SMIAPP_PRIV_H_
+#define __SMIAPP_PRIV_H_
+
+#include <linux/mutex.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-subdev.h>
+#include <media/smiapp.h>
+
+#include "smiapp-pll.h"
+#include "smiapp-reg.h"
+#include "smiapp-regs.h"
+#include "smiapp-quirk.h"
+
+/*
+ * Standard SMIA++ constants
+ */
+#define SMIA_VERSION_1			10
+#define SMIAPP_VERSION_0_8		8 /* Draft 0.8 */
+#define SMIAPP_VERSION_0_9		9 /* Draft 0.9 */
+#define SMIAPP_VERSION_1		10
+
+#define SMIAPP_PROFILE_0		0
+#define SMIAPP_PROFILE_1		1
+#define SMIAPP_PROFILE_2		2
+
+#define SMIAPP_NVM_PAGE_SIZE		64	/* bytes */
+
+#define SMIAPP_RESET_DELAY_CLOCKS	2400
+#define SMIAPP_RESET_DELAY(clk)				\
+	(1000 +	(SMIAPP_RESET_DELAY_CLOCKS * 1000	\
+		 + (clk) / 1000 - 1) / ((clk) / 1000))
+
+#include "smiapp-limits.h"
+
+struct smiapp_quirk;
+
+#define SMIAPP_MODULE_IDENT_FLAG_REV_LE		(1 << 0)
+
+struct smiapp_module_ident {
+	u8 manufacturer_id;
+	u16 model_id;
+	u8 revision_number_major;
+
+	u8 flags;
+
+	char *name;
+	const struct smiapp_quirk *quirk;
+};
+
+struct smiapp_module_info {
+	u32 manufacturer_id;
+	u32 model_id;
+	u32 revision_number_major;
+	u32 revision_number_minor;
+
+	u32 module_year;
+	u32 module_month;
+	u32 module_day;
+
+	u32 sensor_manufacturer_id;
+	u32 sensor_model_id;
+	u32 sensor_revision_number;
+	u32 sensor_firmware_version;
+
+	u32 smia_version;
+	u32 smiapp_version;
+
+	u32 smiapp_profile;
+
+	char *name;
+	const struct smiapp_quirk *quirk;
+};
+
+#define SMIAPP_IDENT_FQ(manufacturer, model, rev, fl, _name, _quirk)	\
+	{ .manufacturer_id = manufacturer,				\
+	  .model_id = model,						\
+	  .revision_number_major = rev,					\
+	  .flags = fl,							\
+	  .name = _name,						\
+	  .quirk = _quirk, }
+
+#define SMIAPP_IDENT_LQ(manufacturer, model, rev, _name, _quirk)	\
+	{ .manufacturer_id = manufacturer,				\
+	  .model_id = model,						\
+	  .revision_number_major = rev,					\
+	  .flags = SMIAPP_MODULE_IDENT_FLAG_REV_LE,			\
+	  .name = _name,						\
+	  .quirk = _quirk, }
+
+#define SMIAPP_IDENT_L(manufacturer, model, rev, _name)			\
+	{ .manufacturer_id = manufacturer,				\
+	  .model_id = model,						\
+	  .revision_number_major = rev,					\
+	  .flags = SMIAPP_MODULE_IDENT_FLAG_REV_LE,			\
+	  .name = _name, }
+
+#define SMIAPP_IDENT_Q(manufacturer, model, rev, _name, _quirk)		\
+	{ .manufacturer_id = manufacturer,				\
+	  .model_id = model,						\
+	  .revision_number_major = rev,					\
+	  .flags = 0,							\
+	  .name = _name,						\
+	  .quirk = _quirk, }
+
+#define SMIAPP_IDENT(manufacturer, model, rev, _name)			\
+	{ .manufacturer_id = manufacturer,				\
+	  .model_id = model,						\
+	  .revision_number_major = rev,					\
+	  .flags = 0,							\
+	  .name = _name, }
+
+struct smiapp_reg_limits {
+	u32 addr;
+	char *what;
+};
+
+extern struct smiapp_reg_limits smiapp_reg_limits[];
+
+struct smiapp_csi_data_format {
+	u32 code;
+	u8 width;
+	u8 compressed;
+	u8 pixel_order;
+};
+
+#define SMIAPP_SUBDEVS			3
+
+#define SMIAPP_PA_PAD_SRC		0
+#define SMIAPP_PAD_SINK			0
+#define SMIAPP_PAD_SRC			1
+#define SMIAPP_PADS			2
+
+struct smiapp_binning_subtype {
+	u8 horizontal:4;
+	u8 vertical:4;
+} __packed;
+
+struct smiapp_subdev {
+	struct v4l2_subdev sd;
+	struct media_pad pads[2];
+	struct v4l2_rect sink_fmt;
+	struct v4l2_rect crop[2];
+	struct v4l2_rect compose; /* compose on sink */
+	unsigned short sink_pad;
+	unsigned short source_pad;
+	int npads;
+	struct smiapp_sensor *sensor;
+	struct v4l2_ctrl_handler ctrl_handler;
+};
+
+/*
+ * struct smiapp_sensor - Main device structure
+ */
+struct smiapp_sensor {
+	/*
+	 * "mutex" is used to serialise access to all fields here
+	 * except v4l2_ctrls at the end of the struct. "mutex" is also
+	 * used to serialise access to file handle specific
+	 * information. The exception to this rule is the power_mutex
+	 * below.
+	 */
+	struct mutex mutex;
+	/*
+	 * power_mutex is used to serialise power management related
+	 * activities. Acquiring "mutex" at that time isn't necessary
+	 * since there are no other users anyway.
+	 */
+	struct mutex power_mutex;
+	struct smiapp_subdev ssds[SMIAPP_SUBDEVS];
+	u32 ssds_used;
+	struct smiapp_subdev *src;
+	struct smiapp_subdev *binner;
+	struct smiapp_subdev *scaler;
+	struct smiapp_subdev *pixel_array;
+	struct smiapp_platform_data *platform_data;
+	struct regulator *vana;
+	struct clk *ext_clk;
+	u32 limits[SMIAPP_LIMIT_LAST];
+	u8 nbinning_subtypes;
+	struct smiapp_binning_subtype binning_subtypes[SMIAPP_BINNING_SUBTYPES];
+	u32 mbus_frame_fmts;
+	const struct smiapp_csi_data_format *csi_format;
+	const struct smiapp_csi_data_format *internal_csi_format;
+	u32 default_mbus_frame_fmts;
+	int default_pixel_order;
+
+	u8 binning_horizontal;
+	u8 binning_vertical;
+
+	u8 scale_m;
+	u8 scaling_mode;
+
+	u8 hvflip_inv_mask; /* H/VFLIP inversion due to sensor orientation */
+	u8 flash_capability;
+	u8 frame_skip;
+
+	int power_count;
+
+	bool streaming;
+	bool dev_init_done;
+
+	u8 *nvm;		/* nvm memory buffer */
+	unsigned int nvm_size;	/* bytes */
+
+	struct smiapp_module_info minfo;
+
+	struct smiapp_pll pll;
+
+	/* Pixel array controls */
+	struct v4l2_ctrl *analog_gain;
+	struct v4l2_ctrl *exposure;
+	struct v4l2_ctrl *hflip;
+	struct v4l2_ctrl *vflip;
+	struct v4l2_ctrl *vblank;
+	struct v4l2_ctrl *hblank;
+	struct v4l2_ctrl *pixel_rate_parray;
+	/* src controls */
+	struct v4l2_ctrl *link_freq;
+	struct v4l2_ctrl *pixel_rate_csi;
+};
+
+#define to_smiapp_subdev(_sd)				\
+	container_of(_sd, struct smiapp_subdev, sd)
+
+#define to_smiapp_sensor(_sd)	\
+	(to_smiapp_subdev(_sd)->sensor)
+
+#endif /* __SMIAPP_PRIV_H_ */
diff --git a/drivers/media/i2c/soc_camera/Kconfig b/drivers/media/i2c/soc_camera/Kconfig
new file mode 100644
index 0000000..6dff2b7
--- /dev/null
+++ b/drivers/media/i2c/soc_camera/Kconfig
@@ -0,0 +1,89 @@
+comment "soc_camera sensor drivers"
+
+config SOC_CAMERA_IMX074
+	tristate "imx074 support"
+	depends on SOC_CAMERA && I2C
+	help
+	  This driver supports IMX074 cameras from Sony
+
+config SOC_CAMERA_MT9M001
+	tristate "mt9m001 support"
+	depends on SOC_CAMERA && I2C
+	select GPIO_PCA953X if MT9M001_PCA9536_SWITCH
+	help
+	  This driver supports MT9M001 cameras from Micron, monochrome
+	  and colour models.
+
+config SOC_CAMERA_MT9M111
+	tristate "mt9m111, mt9m112 and mt9m131 support"
+	depends on SOC_CAMERA && I2C
+	help
+	  This driver supports MT9M111, MT9M112 and MT9M131 cameras from
+	  Micron/Aptina
+
+config SOC_CAMERA_MT9T031
+	tristate "mt9t031 support"
+	depends on SOC_CAMERA && I2C
+	help
+	  This driver supports MT9T031 cameras from Micron.
+
+config SOC_CAMERA_MT9T112
+	tristate "mt9t112 support"
+	depends on SOC_CAMERA && I2C
+	help
+	  This driver supports MT9T112 cameras from Aptina.
+
+config SOC_CAMERA_MT9V022
+	tristate "mt9v022 and mt9v024 support"
+	depends on SOC_CAMERA && I2C
+	select GPIO_PCA953X if MT9V022_PCA9536_SWITCH
+	help
+	  This driver supports MT9V022 cameras from Micron
+
+config SOC_CAMERA_OV2640
+	tristate "ov2640 camera support"
+	depends on SOC_CAMERA && I2C
+	help
+	  This is a ov2640 camera driver
+
+config SOC_CAMERA_OV5642
+	tristate "ov5642 camera support"
+	depends on SOC_CAMERA && I2C
+	help
+	  This is a V4L2 camera driver for the OmniVision OV5642 sensor
+
+config SOC_CAMERA_OV6650
+	tristate "ov6650 sensor support"
+	depends on SOC_CAMERA && I2C
+	---help---
+	  This is a V4L2 SoC camera driver for the OmniVision OV6650 sensor
+
+config SOC_CAMERA_OV772X
+	tristate "ov772x camera support"
+	depends on SOC_CAMERA && I2C
+	help
+	  This is a ov772x camera driver
+
+config SOC_CAMERA_OV9640
+	tristate "ov9640 camera support"
+	depends on SOC_CAMERA && I2C
+	help
+	  This is a ov9640 camera driver
+
+config SOC_CAMERA_OV9740
+	tristate "ov9740 camera support"
+	depends on SOC_CAMERA && I2C
+	help
+	  This is a ov9740 camera driver
+
+config SOC_CAMERA_RJ54N1
+	tristate "rj54n1cb0c support"
+	depends on SOC_CAMERA && I2C
+	help
+	  This is a rj54n1cb0c video driver
+
+config SOC_CAMERA_TW9910
+	tristate "tw9910 support"
+	depends on SOC_CAMERA && I2C
+	help
+	  This is a tw9910 video driver
diff --git a/drivers/media/i2c/soc_camera/Makefile b/drivers/media/i2c/soc_camera/Makefile
new file mode 100644
index 0000000..d0421fe
--- /dev/null
+++ b/drivers/media/i2c/soc_camera/Makefile
@@ -0,0 +1,14 @@
+obj-$(CONFIG_SOC_CAMERA_IMX074)		+= imx074.o
+obj-$(CONFIG_SOC_CAMERA_MT9M001)	+= mt9m001.o
+obj-$(CONFIG_SOC_CAMERA_MT9M111)	+= mt9m111.o
+obj-$(CONFIG_SOC_CAMERA_MT9T031)	+= mt9t031.o
+obj-$(CONFIG_SOC_CAMERA_MT9T112)	+= mt9t112.o
+obj-$(CONFIG_SOC_CAMERA_MT9V022)	+= mt9v022.o
+obj-$(CONFIG_SOC_CAMERA_OV2640)		+= ov2640.o
+obj-$(CONFIG_SOC_CAMERA_OV5642)		+= ov5642.o
+obj-$(CONFIG_SOC_CAMERA_OV6650)		+= ov6650.o
+obj-$(CONFIG_SOC_CAMERA_OV772X)		+= ov772x.o
+obj-$(CONFIG_SOC_CAMERA_OV9640)		+= ov9640.o
+obj-$(CONFIG_SOC_CAMERA_OV9740)		+= ov9740.o
+obj-$(CONFIG_SOC_CAMERA_RJ54N1)		+= rj54n1cb0c.o
+obj-$(CONFIG_SOC_CAMERA_TW9910)		+= tw9910.o
diff --git a/drivers/media/i2c/soc_camera/imx074.c b/drivers/media/i2c/soc_camera/imx074.c
new file mode 100644
index 0000000..f8534ee
--- /dev/null
+++ b/drivers/media/i2c/soc_camera/imx074.c
@@ -0,0 +1,495 @@
+/*
+ * Driver for IMX074 CMOS Image Sensor from Sony
+ *
+ * Copyright (C) 2010, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+ *
+ * Partially inspired by the IMX074 driver from the Android / MSM tree
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/v4l2-mediabus.h>
+#include <linux/slab.h>
+#include <linux/videodev2.h>
+#include <linux/module.h>
+
+#include <media/soc_camera.h>
+#include <media/v4l2-subdev.h>
+#include <media/v4l2-chip-ident.h>
+
+/* IMX074 registers */
+
+#define MODE_SELECT			0x0100
+#define IMAGE_ORIENTATION		0x0101
+#define GROUPED_PARAMETER_HOLD		0x0104
+
+/* Integration Time */
+#define COARSE_INTEGRATION_TIME_HI	0x0202
+#define COARSE_INTEGRATION_TIME_LO	0x0203
+/* Gain */
+#define ANALOGUE_GAIN_CODE_GLOBAL_HI	0x0204
+#define ANALOGUE_GAIN_CODE_GLOBAL_LO	0x0205
+
+/* PLL registers */
+#define PRE_PLL_CLK_DIV			0x0305
+#define PLL_MULTIPLIER			0x0307
+#define PLSTATIM			0x302b
+#define VNDMY_ABLMGSHLMT		0x300a
+#define Y_OPBADDR_START_DI		0x3014
+/* mode setting */
+#define FRAME_LENGTH_LINES_HI		0x0340
+#define FRAME_LENGTH_LINES_LO		0x0341
+#define LINE_LENGTH_PCK_HI		0x0342
+#define LINE_LENGTH_PCK_LO		0x0343
+#define YADDR_START			0x0347
+#define YADDR_END			0x034b
+#define X_OUTPUT_SIZE_MSB		0x034c
+#define X_OUTPUT_SIZE_LSB		0x034d
+#define Y_OUTPUT_SIZE_MSB		0x034e
+#define Y_OUTPUT_SIZE_LSB		0x034f
+#define X_EVEN_INC			0x0381
+#define X_ODD_INC			0x0383
+#define Y_EVEN_INC			0x0385
+#define Y_ODD_INC			0x0387
+
+#define HMODEADD			0x3001
+#define VMODEADD			0x3016
+#define VAPPLINE_START			0x3069
+#define VAPPLINE_END			0x306b
+#define SHUTTER				0x3086
+#define HADDAVE				0x30e8
+#define LANESEL				0x3301
+
+/* IMX074 supported geometry */
+#define IMX074_WIDTH			1052
+#define IMX074_HEIGHT			780
+
+/* IMX074 has only one fixed colorspace per pixelcode */
+struct imx074_datafmt {
+	enum v4l2_mbus_pixelcode	code;
+	enum v4l2_colorspace		colorspace;
+};
+
+struct imx074 {
+	struct v4l2_subdev		subdev;
+	const struct imx074_datafmt	*fmt;
+};
+
+static const struct imx074_datafmt imx074_colour_fmts[] = {
+	{V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_COLORSPACE_SRGB},
+};
+
+static struct imx074 *to_imx074(const struct i2c_client *client)
+{
+	return container_of(i2c_get_clientdata(client), struct imx074, subdev);
+}
+
+/* Find a data format by a pixel code in an array */
+static const struct imx074_datafmt *imx074_find_datafmt(enum v4l2_mbus_pixelcode code)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(imx074_colour_fmts); i++)
+		if (imx074_colour_fmts[i].code == code)
+			return imx074_colour_fmts + i;
+
+	return NULL;
+}
+
+static int reg_write(struct i2c_client *client, const u16 addr, const u8 data)
+{
+	struct i2c_adapter *adap = client->adapter;
+	struct i2c_msg msg;
+	unsigned char tx[3];
+	int ret;
+
+	msg.addr = client->addr;
+	msg.buf = tx;
+	msg.len = 3;
+	msg.flags = 0;
+
+	tx[0] = addr >> 8;
+	tx[1] = addr & 0xff;
+	tx[2] = data;
+
+	ret = i2c_transfer(adap, &msg, 1);
+
+	mdelay(2);
+
+	return ret == 1 ? 0 : -EIO;
+}
+
+static int reg_read(struct i2c_client *client, const u16 addr)
+{
+	u8 buf[2] = {addr >> 8, addr & 0xff};
+	int ret;
+	struct i2c_msg msgs[] = {
+		{
+			.addr  = client->addr,
+			.flags = 0,
+			.len   = 2,
+			.buf   = buf,
+		}, {
+			.addr  = client->addr,
+			.flags = I2C_M_RD,
+			.len   = 2,
+			.buf   = buf,
+		},
+	};
+
+	ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
+	if (ret < 0) {
+		dev_warn(&client->dev, "Reading register %x from %x failed\n",
+			 addr, client->addr);
+		return ret;
+	}
+
+	return buf[0] & 0xff; /* no sign-extension */
+}
+
+static int imx074_try_fmt(struct v4l2_subdev *sd,
+			  struct v4l2_mbus_framefmt *mf)
+{
+	const struct imx074_datafmt *fmt = imx074_find_datafmt(mf->code);
+
+	dev_dbg(sd->v4l2_dev->dev, "%s(%u)\n", __func__, mf->code);
+
+	if (!fmt) {
+		mf->code	= imx074_colour_fmts[0].code;
+		mf->colorspace	= imx074_colour_fmts[0].colorspace;
+	}
+
+	mf->width	= IMX074_WIDTH;
+	mf->height	= IMX074_HEIGHT;
+	mf->field	= V4L2_FIELD_NONE;
+
+	return 0;
+}
+
+static int imx074_s_fmt(struct v4l2_subdev *sd,
+			struct v4l2_mbus_framefmt *mf)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct imx074 *priv = to_imx074(client);
+
+	dev_dbg(sd->v4l2_dev->dev, "%s(%u)\n", __func__, mf->code);
+
+	/* MIPI CSI could have changed the format, double-check */
+	if (!imx074_find_datafmt(mf->code))
+		return -EINVAL;
+
+	imx074_try_fmt(sd, mf);
+
+	priv->fmt = imx074_find_datafmt(mf->code);
+
+	return 0;
+}
+
+static int imx074_g_fmt(struct v4l2_subdev *sd,
+			struct v4l2_mbus_framefmt *mf)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct imx074 *priv = to_imx074(client);
+
+	const struct imx074_datafmt *fmt = priv->fmt;
+
+	mf->code	= fmt->code;
+	mf->colorspace	= fmt->colorspace;
+	mf->width	= IMX074_WIDTH;
+	mf->height	= IMX074_HEIGHT;
+	mf->field	= V4L2_FIELD_NONE;
+
+	return 0;
+}
+
+static int imx074_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
+{
+	struct v4l2_rect *rect = &a->c;
+
+	a->type		= V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	rect->top	= 0;
+	rect->left	= 0;
+	rect->width	= IMX074_WIDTH;
+	rect->height	= IMX074_HEIGHT;
+
+	return 0;
+}
+
+static int imx074_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
+{
+	a->bounds.left			= 0;
+	a->bounds.top			= 0;
+	a->bounds.width			= IMX074_WIDTH;
+	a->bounds.height		= IMX074_HEIGHT;
+	a->defrect			= a->bounds;
+	a->type				= V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	a->pixelaspect.numerator	= 1;
+	a->pixelaspect.denominator	= 1;
+
+	return 0;
+}
+
+static int imx074_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
+			   enum v4l2_mbus_pixelcode *code)
+{
+	if ((unsigned int)index >= ARRAY_SIZE(imx074_colour_fmts))
+		return -EINVAL;
+
+	*code = imx074_colour_fmts[index].code;
+	return 0;
+}
+
+static int imx074_s_stream(struct v4l2_subdev *sd, int enable)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	/* MODE_SELECT: stream or standby */
+	return reg_write(client, MODE_SELECT, !!enable);
+}
+
+static int imx074_g_chip_ident(struct v4l2_subdev *sd,
+			       struct v4l2_dbg_chip_ident *id)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
+		return -EINVAL;
+
+	if (id->match.addr != client->addr)
+		return -ENODEV;
+
+	id->ident	= V4L2_IDENT_IMX074;
+	id->revision	= 0;
+
+	return 0;
+}
+
+static int imx074_s_power(struct v4l2_subdev *sd, int on)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+	return soc_camera_set_power(&client->dev, icl, on);
+}
+
+static int imx074_g_mbus_config(struct v4l2_subdev *sd,
+				struct v4l2_mbus_config *cfg)
+{
+	cfg->type = V4L2_MBUS_CSI2;
+	cfg->flags = V4L2_MBUS_CSI2_2_LANE |
+		V4L2_MBUS_CSI2_CHANNEL_0 |
+		V4L2_MBUS_CSI2_CONTINUOUS_CLOCK;
+
+	return 0;
+}
+
+static struct v4l2_subdev_video_ops imx074_subdev_video_ops = {
+	.s_stream	= imx074_s_stream,
+	.s_mbus_fmt	= imx074_s_fmt,
+	.g_mbus_fmt	= imx074_g_fmt,
+	.try_mbus_fmt	= imx074_try_fmt,
+	.enum_mbus_fmt	= imx074_enum_fmt,
+	.g_crop		= imx074_g_crop,
+	.cropcap	= imx074_cropcap,
+	.g_mbus_config	= imx074_g_mbus_config,
+};
+
+static struct v4l2_subdev_core_ops imx074_subdev_core_ops = {
+	.g_chip_ident	= imx074_g_chip_ident,
+	.s_power	= imx074_s_power,
+};
+
+static struct v4l2_subdev_ops imx074_subdev_ops = {
+	.core	= &imx074_subdev_core_ops,
+	.video	= &imx074_subdev_video_ops,
+};
+
+static int imx074_video_probe(struct i2c_client *client)
+{
+	struct v4l2_subdev *subdev = i2c_get_clientdata(client);
+	int ret;
+	u16 id;
+
+	ret = imx074_s_power(subdev, 1);
+	if (ret < 0)
+		return ret;
+
+	/* Read sensor Model ID */
+	ret = reg_read(client, 0);
+	if (ret < 0)
+		goto done;
+
+	id = ret << 8;
+
+	ret = reg_read(client, 1);
+	if (ret < 0)
+		goto done;
+
+	id |= ret;
+
+	dev_info(&client->dev, "Chip ID 0x%04x detected\n", id);
+
+	if (id != 0x74) {
+		ret = -ENODEV;
+		goto done;
+	}
+
+	/* PLL Setting EXTCLK=24MHz, 22.5times */
+	reg_write(client, PLL_MULTIPLIER, 0x2D);
+	reg_write(client, PRE_PLL_CLK_DIV, 0x02);
+	reg_write(client, PLSTATIM, 0x4B);
+
+	/* 2-lane mode */
+	reg_write(client, 0x3024, 0x00);
+
+	reg_write(client, IMAGE_ORIENTATION, 0x00);
+
+	/* select RAW mode:
+	 * 0x08+0x08 = top 8 bits
+	 * 0x0a+0x08 = compressed 8-bits
+	 * 0x0a+0x0a = 10 bits
+	 */
+	reg_write(client, 0x0112, 0x08);
+	reg_write(client, 0x0113, 0x08);
+
+	/* Base setting for High frame mode */
+	reg_write(client, VNDMY_ABLMGSHLMT, 0x80);
+	reg_write(client, Y_OPBADDR_START_DI, 0x08);
+	reg_write(client, 0x3015, 0x37);
+	reg_write(client, 0x301C, 0x01);
+	reg_write(client, 0x302C, 0x05);
+	reg_write(client, 0x3031, 0x26);
+	reg_write(client, 0x3041, 0x60);
+	reg_write(client, 0x3051, 0x24);
+	reg_write(client, 0x3053, 0x34);
+	reg_write(client, 0x3057, 0xC0);
+	reg_write(client, 0x305C, 0x09);
+	reg_write(client, 0x305D, 0x07);
+	reg_write(client, 0x3060, 0x30);
+	reg_write(client, 0x3065, 0x00);
+	reg_write(client, 0x30AA, 0x08);
+	reg_write(client, 0x30AB, 0x1C);
+	reg_write(client, 0x30B0, 0x32);
+	reg_write(client, 0x30B2, 0x83);
+	reg_write(client, 0x30D3, 0x04);
+	reg_write(client, 0x3106, 0x78);
+	reg_write(client, 0x310C, 0x82);
+	reg_write(client, 0x3304, 0x05);
+	reg_write(client, 0x3305, 0x04);
+	reg_write(client, 0x3306, 0x11);
+	reg_write(client, 0x3307, 0x02);
+	reg_write(client, 0x3308, 0x0C);
+	reg_write(client, 0x3309, 0x06);
+	reg_write(client, 0x330A, 0x08);
+	reg_write(client, 0x330B, 0x04);
+	reg_write(client, 0x330C, 0x08);
+	reg_write(client, 0x330D, 0x06);
+	reg_write(client, 0x330E, 0x01);
+	reg_write(client, 0x3381, 0x00);
+
+	/* V : 1/2V-addition (1,3), H : 1/2H-averaging (1,3) -> Full HD */
+	/* 1608 = 1560 + 48 (black lines) */
+	reg_write(client, FRAME_LENGTH_LINES_HI, 0x06);
+	reg_write(client, FRAME_LENGTH_LINES_LO, 0x48);
+	reg_write(client, YADDR_START, 0x00);
+	reg_write(client, YADDR_END, 0x2F);
+	/* 0x838 == 2104 */
+	reg_write(client, X_OUTPUT_SIZE_MSB, 0x08);
+	reg_write(client, X_OUTPUT_SIZE_LSB, 0x38);
+	/* 0x618 == 1560 */
+	reg_write(client, Y_OUTPUT_SIZE_MSB, 0x06);
+	reg_write(client, Y_OUTPUT_SIZE_LSB, 0x18);
+	reg_write(client, X_EVEN_INC, 0x01);
+	reg_write(client, X_ODD_INC, 0x03);
+	reg_write(client, Y_EVEN_INC, 0x01);
+	reg_write(client, Y_ODD_INC, 0x03);
+	reg_write(client, HMODEADD, 0x00);
+	reg_write(client, VMODEADD, 0x16);
+	reg_write(client, VAPPLINE_START, 0x24);
+	reg_write(client, VAPPLINE_END, 0x53);
+	reg_write(client, SHUTTER, 0x00);
+	reg_write(client, HADDAVE, 0x80);
+
+	reg_write(client, LANESEL, 0x00);
+
+	reg_write(client, GROUPED_PARAMETER_HOLD, 0x00);	/* off */
+
+	ret = 0;
+
+done:
+	imx074_s_power(subdev, 0);
+	return ret;
+}
+
+static int imx074_probe(struct i2c_client *client,
+			const struct i2c_device_id *did)
+{
+	struct imx074 *priv;
+	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+	int ret;
+
+	if (!icl) {
+		dev_err(&client->dev, "IMX074: missing platform data!\n");
+		return -EINVAL;
+	}
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
+		dev_warn(&adapter->dev,
+			 "I2C-Adapter doesn't support I2C_FUNC_SMBUS_BYTE\n");
+		return -EIO;
+	}
+
+	priv = kzalloc(sizeof(struct imx074), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	v4l2_i2c_subdev_init(&priv->subdev, client, &imx074_subdev_ops);
+
+	priv->fmt	= &imx074_colour_fmts[0];
+
+	ret = imx074_video_probe(client);
+	if (ret < 0) {
+		kfree(priv);
+		return ret;
+	}
+
+	return ret;
+}
+
+static int imx074_remove(struct i2c_client *client)
+{
+	struct imx074 *priv = to_imx074(client);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+	if (icl->free_bus)
+		icl->free_bus(icl);
+	kfree(priv);
+
+	return 0;
+}
+
+static const struct i2c_device_id imx074_id[] = {
+	{ "imx074", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, imx074_id);
+
+static struct i2c_driver imx074_i2c_driver = {
+	.driver = {
+		.name = "imx074",
+	},
+	.probe		= imx074_probe,
+	.remove		= imx074_remove,
+	.id_table	= imx074_id,
+};
+
+module_i2c_driver(imx074_i2c_driver);
+
+MODULE_DESCRIPTION("Sony IMX074 Camera driver");
+MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/i2c/soc_camera/mt9m001.c b/drivers/media/i2c/soc_camera/mt9m001.c
new file mode 100644
index 0000000..d85be41
--- /dev/null
+++ b/drivers/media/i2c/soc_camera/mt9m001.c
@@ -0,0 +1,757 @@
+/*
+ * Driver for MT9M001 CMOS Image Sensor from Micron
+ *
+ * Copyright (C) 2008, Guennadi Liakhovetski <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 version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/videodev2.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/log2.h>
+#include <linux/module.h>
+
+#include <media/soc_camera.h>
+#include <media/soc_mediabus.h>
+#include <media/v4l2-subdev.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-ctrls.h>
+
+/*
+ * mt9m001 i2c address 0x5d
+ * The platform has to define struct i2c_board_info objects and link to them
+ * from struct soc_camera_link
+ */
+
+/* mt9m001 selected register addresses */
+#define MT9M001_CHIP_VERSION		0x00
+#define MT9M001_ROW_START		0x01
+#define MT9M001_COLUMN_START		0x02
+#define MT9M001_WINDOW_HEIGHT		0x03
+#define MT9M001_WINDOW_WIDTH		0x04
+#define MT9M001_HORIZONTAL_BLANKING	0x05
+#define MT9M001_VERTICAL_BLANKING	0x06
+#define MT9M001_OUTPUT_CONTROL		0x07
+#define MT9M001_SHUTTER_WIDTH		0x09
+#define MT9M001_FRAME_RESTART		0x0b
+#define MT9M001_SHUTTER_DELAY		0x0c
+#define MT9M001_RESET			0x0d
+#define MT9M001_READ_OPTIONS1		0x1e
+#define MT9M001_READ_OPTIONS2		0x20
+#define MT9M001_GLOBAL_GAIN		0x35
+#define MT9M001_CHIP_ENABLE		0xF1
+
+#define MT9M001_MAX_WIDTH		1280
+#define MT9M001_MAX_HEIGHT		1024
+#define MT9M001_MIN_WIDTH		48
+#define MT9M001_MIN_HEIGHT		32
+#define MT9M001_COLUMN_SKIP		20
+#define MT9M001_ROW_SKIP		12
+
+/* MT9M001 has only one fixed colorspace per pixelcode */
+struct mt9m001_datafmt {
+	enum v4l2_mbus_pixelcode	code;
+	enum v4l2_colorspace		colorspace;
+};
+
+/* Find a data format by a pixel code in an array */
+static const struct mt9m001_datafmt *mt9m001_find_datafmt(
+	enum v4l2_mbus_pixelcode code, const struct mt9m001_datafmt *fmt,
+	int n)
+{
+	int i;
+	for (i = 0; i < n; i++)
+		if (fmt[i].code == code)
+			return fmt + i;
+
+	return NULL;
+}
+
+static const struct mt9m001_datafmt mt9m001_colour_fmts[] = {
+	/*
+	 * Order important: first natively supported,
+	 * second supported with a GPIO extender
+	 */
+	{V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_COLORSPACE_SRGB},
+	{V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_COLORSPACE_SRGB},
+};
+
+static const struct mt9m001_datafmt mt9m001_monochrome_fmts[] = {
+	/* Order important - see above */
+	{V4L2_MBUS_FMT_Y10_1X10, V4L2_COLORSPACE_JPEG},
+	{V4L2_MBUS_FMT_Y8_1X8, V4L2_COLORSPACE_JPEG},
+};
+
+struct mt9m001 {
+	struct v4l2_subdev subdev;
+	struct v4l2_ctrl_handler hdl;
+	struct {
+		/* exposure/auto-exposure cluster */
+		struct v4l2_ctrl *autoexposure;
+		struct v4l2_ctrl *exposure;
+	};
+	struct v4l2_rect rect;	/* Sensor window */
+	const struct mt9m001_datafmt *fmt;
+	const struct mt9m001_datafmt *fmts;
+	int num_fmts;
+	int model;	/* V4L2_IDENT_MT9M001* codes from v4l2-chip-ident.h */
+	unsigned int total_h;
+	unsigned short y_skip_top;	/* Lines to skip at the top */
+};
+
+static struct mt9m001 *to_mt9m001(const struct i2c_client *client)
+{
+	return container_of(i2c_get_clientdata(client), struct mt9m001, subdev);
+}
+
+static int reg_read(struct i2c_client *client, const u8 reg)
+{
+	return i2c_smbus_read_word_swapped(client, reg);
+}
+
+static int reg_write(struct i2c_client *client, const u8 reg,
+		     const u16 data)
+{
+	return i2c_smbus_write_word_swapped(client, reg, data);
+}
+
+static int reg_set(struct i2c_client *client, const u8 reg,
+		   const u16 data)
+{
+	int ret;
+
+	ret = reg_read(client, reg);
+	if (ret < 0)
+		return ret;
+	return reg_write(client, reg, ret | data);
+}
+
+static int reg_clear(struct i2c_client *client, const u8 reg,
+		     const u16 data)
+{
+	int ret;
+
+	ret = reg_read(client, reg);
+	if (ret < 0)
+		return ret;
+	return reg_write(client, reg, ret & ~data);
+}
+
+static int mt9m001_init(struct i2c_client *client)
+{
+	int ret;
+
+	dev_dbg(&client->dev, "%s\n", __func__);
+
+	/*
+	 * We don't know, whether platform provides reset, issue a soft reset
+	 * too. This returns all registers to their default values.
+	 */
+	ret = reg_write(client, MT9M001_RESET, 1);
+	if (!ret)
+		ret = reg_write(client, MT9M001_RESET, 0);
+
+	/* Disable chip, synchronous option update */
+	if (!ret)
+		ret = reg_write(client, MT9M001_OUTPUT_CONTROL, 0);
+
+	return ret;
+}
+
+static int mt9m001_s_stream(struct v4l2_subdev *sd, int enable)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	/* Switch to master "normal" mode or stop sensor readout */
+	if (reg_write(client, MT9M001_OUTPUT_CONTROL, enable ? 2 : 0) < 0)
+		return -EIO;
+	return 0;
+}
+
+static int mt9m001_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct mt9m001 *mt9m001 = to_mt9m001(client);
+	struct v4l2_rect rect = a->c;
+	int ret;
+	const u16 hblank = 9, vblank = 25;
+
+	if (mt9m001->fmts == mt9m001_colour_fmts)
+		/*
+		 * Bayer format - even number of rows for simplicity,
+		 * but let the user play with the top row.
+		 */
+		rect.height = ALIGN(rect.height, 2);
+
+	/* Datasheet requirement: see register description */
+	rect.width = ALIGN(rect.width, 2);
+	rect.left = ALIGN(rect.left, 2);
+
+	soc_camera_limit_side(&rect.left, &rect.width,
+		     MT9M001_COLUMN_SKIP, MT9M001_MIN_WIDTH, MT9M001_MAX_WIDTH);
+
+	soc_camera_limit_side(&rect.top, &rect.height,
+		     MT9M001_ROW_SKIP, MT9M001_MIN_HEIGHT, MT9M001_MAX_HEIGHT);
+
+	mt9m001->total_h = rect.height + mt9m001->y_skip_top + vblank;
+
+	/* Blanking and start values - default... */
+	ret = reg_write(client, MT9M001_HORIZONTAL_BLANKING, hblank);
+	if (!ret)
+		ret = reg_write(client, MT9M001_VERTICAL_BLANKING, vblank);
+
+	/*
+	 * The caller provides a supported format, as verified per
+	 * call to .try_mbus_fmt()
+	 */
+	if (!ret)
+		ret = reg_write(client, MT9M001_COLUMN_START, rect.left);
+	if (!ret)
+		ret = reg_write(client, MT9M001_ROW_START, rect.top);
+	if (!ret)
+		ret = reg_write(client, MT9M001_WINDOW_WIDTH, rect.width - 1);
+	if (!ret)
+		ret = reg_write(client, MT9M001_WINDOW_HEIGHT,
+				rect.height + mt9m001->y_skip_top - 1);
+	if (!ret && v4l2_ctrl_g_ctrl(mt9m001->autoexposure) == V4L2_EXPOSURE_AUTO)
+		ret = reg_write(client, MT9M001_SHUTTER_WIDTH, mt9m001->total_h);
+
+	if (!ret)
+		mt9m001->rect = rect;
+
+	return ret;
+}
+
+static int mt9m001_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct mt9m001 *mt9m001 = to_mt9m001(client);
+
+	a->c	= mt9m001->rect;
+	a->type	= V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+	return 0;
+}
+
+static int mt9m001_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
+{
+	a->bounds.left			= MT9M001_COLUMN_SKIP;
+	a->bounds.top			= MT9M001_ROW_SKIP;
+	a->bounds.width			= MT9M001_MAX_WIDTH;
+	a->bounds.height		= MT9M001_MAX_HEIGHT;
+	a->defrect			= a->bounds;
+	a->type				= V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	a->pixelaspect.numerator	= 1;
+	a->pixelaspect.denominator	= 1;
+
+	return 0;
+}
+
+static int mt9m001_g_fmt(struct v4l2_subdev *sd,
+			 struct v4l2_mbus_framefmt *mf)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct mt9m001 *mt9m001 = to_mt9m001(client);
+
+	mf->width	= mt9m001->rect.width;
+	mf->height	= mt9m001->rect.height;
+	mf->code	= mt9m001->fmt->code;
+	mf->colorspace	= mt9m001->fmt->colorspace;
+	mf->field	= V4L2_FIELD_NONE;
+
+	return 0;
+}
+
+static int mt9m001_s_fmt(struct v4l2_subdev *sd,
+			 struct v4l2_mbus_framefmt *mf)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct mt9m001 *mt9m001 = to_mt9m001(client);
+	struct v4l2_crop a = {
+		.c = {
+			.left	= mt9m001->rect.left,
+			.top	= mt9m001->rect.top,
+			.width	= mf->width,
+			.height	= mf->height,
+		},
+	};
+	int ret;
+
+	/* No support for scaling so far, just crop. TODO: use skipping */
+	ret = mt9m001_s_crop(sd, &a);
+	if (!ret) {
+		mf->width	= mt9m001->rect.width;
+		mf->height	= mt9m001->rect.height;
+		mt9m001->fmt	= mt9m001_find_datafmt(mf->code,
+					mt9m001->fmts, mt9m001->num_fmts);
+		mf->colorspace	= mt9m001->fmt->colorspace;
+	}
+
+	return ret;
+}
+
+static int mt9m001_try_fmt(struct v4l2_subdev *sd,
+			   struct v4l2_mbus_framefmt *mf)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct mt9m001 *mt9m001 = to_mt9m001(client);
+	const struct mt9m001_datafmt *fmt;
+
+	v4l_bound_align_image(&mf->width, MT9M001_MIN_WIDTH,
+		MT9M001_MAX_WIDTH, 1,
+		&mf->height, MT9M001_MIN_HEIGHT + mt9m001->y_skip_top,
+		MT9M001_MAX_HEIGHT + mt9m001->y_skip_top, 0, 0);
+
+	if (mt9m001->fmts == mt9m001_colour_fmts)
+		mf->height = ALIGN(mf->height - 1, 2);
+
+	fmt = mt9m001_find_datafmt(mf->code, mt9m001->fmts,
+				   mt9m001->num_fmts);
+	if (!fmt) {
+		fmt = mt9m001->fmt;
+		mf->code = fmt->code;
+	}
+
+	mf->colorspace	= fmt->colorspace;
+
+	return 0;
+}
+
+static int mt9m001_g_chip_ident(struct v4l2_subdev *sd,
+				struct v4l2_dbg_chip_ident *id)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct mt9m001 *mt9m001 = to_mt9m001(client);
+
+	if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
+		return -EINVAL;
+
+	if (id->match.addr != client->addr)
+		return -ENODEV;
+
+	id->ident	= mt9m001->model;
+	id->revision	= 0;
+
+	return 0;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int mt9m001_g_register(struct v4l2_subdev *sd,
+			      struct v4l2_dbg_register *reg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
+		return -EINVAL;
+
+	if (reg->match.addr != client->addr)
+		return -ENODEV;
+
+	reg->size = 2;
+	reg->val = reg_read(client, reg->reg);
+
+	if (reg->val > 0xffff)
+		return -EIO;
+
+	return 0;
+}
+
+static int mt9m001_s_register(struct v4l2_subdev *sd,
+			      struct v4l2_dbg_register *reg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
+		return -EINVAL;
+
+	if (reg->match.addr != client->addr)
+		return -ENODEV;
+
+	if (reg_write(client, reg->reg, reg->val) < 0)
+		return -EIO;
+
+	return 0;
+}
+#endif
+
+static int mt9m001_s_power(struct v4l2_subdev *sd, int on)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+	return soc_camera_set_power(&client->dev, icl, on);
+}
+
+static int mt9m001_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct mt9m001 *mt9m001 = container_of(ctrl->handler,
+					       struct mt9m001, hdl);
+	s32 min, max;
+
+	switch (ctrl->id) {
+	case V4L2_CID_EXPOSURE_AUTO:
+		min = mt9m001->exposure->minimum;
+		max = mt9m001->exposure->maximum;
+		mt9m001->exposure->val =
+			(524 + (mt9m001->total_h - 1) * (max - min)) / 1048 + min;
+		break;
+	}
+	return 0;
+}
+
+static int mt9m001_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct mt9m001 *mt9m001 = container_of(ctrl->handler,
+					       struct mt9m001, hdl);
+	struct v4l2_subdev *sd = &mt9m001->subdev;
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct v4l2_ctrl *exp = mt9m001->exposure;
+	int data;
+
+	switch (ctrl->id) {
+	case V4L2_CID_VFLIP:
+		if (ctrl->val)
+			data = reg_set(client, MT9M001_READ_OPTIONS2, 0x8000);
+		else
+			data = reg_clear(client, MT9M001_READ_OPTIONS2, 0x8000);
+		if (data < 0)
+			return -EIO;
+		return 0;
+
+	case V4L2_CID_GAIN:
+		/* See Datasheet Table 7, Gain settings. */
+		if (ctrl->val <= ctrl->default_value) {
+			/* Pack it into 0..1 step 0.125, register values 0..8 */
+			unsigned long range = ctrl->default_value - ctrl->minimum;
+			data = ((ctrl->val - ctrl->minimum) * 8 + range / 2) / range;
+
+			dev_dbg(&client->dev, "Setting gain %d\n", data);
+			data = reg_write(client, MT9M001_GLOBAL_GAIN, data);
+			if (data < 0)
+				return -EIO;
+		} else {
+			/* Pack it into 1.125..15 variable step, register values 9..67 */
+			/* We assume qctrl->maximum - qctrl->default_value - 1 > 0 */
+			unsigned long range = ctrl->maximum - ctrl->default_value - 1;
+			unsigned long gain = ((ctrl->val - ctrl->default_value - 1) *
+					       111 + range / 2) / range + 9;
+
+			if (gain <= 32)
+				data = gain;
+			else if (gain <= 64)
+				data = ((gain - 32) * 16 + 16) / 32 + 80;
+			else
+				data = ((gain - 64) * 7 + 28) / 56 + 96;
+
+			dev_dbg(&client->dev, "Setting gain from %d to %d\n",
+				 reg_read(client, MT9M001_GLOBAL_GAIN), data);
+			data = reg_write(client, MT9M001_GLOBAL_GAIN, data);
+			if (data < 0)
+				return -EIO;
+		}
+		return 0;
+
+	case V4L2_CID_EXPOSURE_AUTO:
+		if (ctrl->val == V4L2_EXPOSURE_MANUAL) {
+			unsigned long range = exp->maximum - exp->minimum;
+			unsigned long shutter = ((exp->val - exp->minimum) * 1048 +
+						 range / 2) / range + 1;
+
+			dev_dbg(&client->dev,
+				"Setting shutter width from %d to %lu\n",
+				reg_read(client, MT9M001_SHUTTER_WIDTH), shutter);
+			if (reg_write(client, MT9M001_SHUTTER_WIDTH, shutter) < 0)
+				return -EIO;
+		} else {
+			const u16 vblank = 25;
+
+			mt9m001->total_h = mt9m001->rect.height +
+				mt9m001->y_skip_top + vblank;
+			if (reg_write(client, MT9M001_SHUTTER_WIDTH, mt9m001->total_h) < 0)
+				return -EIO;
+		}
+		return 0;
+	}
+	return -EINVAL;
+}
+
+/*
+ * Interface active, can use i2c. If it fails, it can indeed mean, that
+ * this wasn't our capture interface, so, we wait for the right one
+ */
+static int mt9m001_video_probe(struct soc_camera_link *icl,
+			       struct i2c_client *client)
+{
+	struct mt9m001 *mt9m001 = to_mt9m001(client);
+	s32 data;
+	unsigned long flags;
+	int ret;
+
+	ret = mt9m001_s_power(&mt9m001->subdev, 1);
+	if (ret < 0)
+		return ret;
+
+	/* Enable the chip */
+	data = reg_write(client, MT9M001_CHIP_ENABLE, 1);
+	dev_dbg(&client->dev, "write: %d\n", data);
+
+	/* Read out the chip version register */
+	data = reg_read(client, MT9M001_CHIP_VERSION);
+
+	/* must be 0x8411 or 0x8421 for colour sensor and 8431 for bw */
+	switch (data) {
+	case 0x8411:
+	case 0x8421:
+		mt9m001->model = V4L2_IDENT_MT9M001C12ST;
+		mt9m001->fmts = mt9m001_colour_fmts;
+		break;
+	case 0x8431:
+		mt9m001->model = V4L2_IDENT_MT9M001C12STM;
+		mt9m001->fmts = mt9m001_monochrome_fmts;
+		break;
+	default:
+		dev_err(&client->dev,
+			"No MT9M001 chip detected, register read %x\n", data);
+		ret = -ENODEV;
+		goto done;
+	}
+
+	mt9m001->num_fmts = 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)
+		mt9m001->num_fmts++;
+	else
+		mt9m001->fmts++;
+
+	if (flags & SOCAM_DATAWIDTH_8)
+		mt9m001->num_fmts++;
+
+	mt9m001->fmt = &mt9m001->fmts[0];
+
+	dev_info(&client->dev, "Detected a MT9M001 chip ID %x (%s)\n", data,
+		 data == 0x8431 ? "C12STM" : "C12ST");
+
+	ret = mt9m001_init(client);
+	if (ret < 0) {
+		dev_err(&client->dev, "Failed to initialise the camera\n");
+		goto done;
+	}
+
+	/* mt9m001_init() has reset the chip, returning registers to defaults */
+	ret = v4l2_ctrl_handler_setup(&mt9m001->hdl);
+
+done:
+	mt9m001_s_power(&mt9m001->subdev, 0);
+	return ret;
+}
+
+static void mt9m001_video_remove(struct soc_camera_link *icl)
+{
+	if (icl->free_bus)
+		icl->free_bus(icl);
+}
+
+static int mt9m001_g_skip_top_lines(struct v4l2_subdev *sd, u32 *lines)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct mt9m001 *mt9m001 = to_mt9m001(client);
+
+	*lines = mt9m001->y_skip_top;
+
+	return 0;
+}
+
+static const struct v4l2_ctrl_ops mt9m001_ctrl_ops = {
+	.g_volatile_ctrl = mt9m001_g_volatile_ctrl,
+	.s_ctrl = mt9m001_s_ctrl,
+};
+
+static struct v4l2_subdev_core_ops mt9m001_subdev_core_ops = {
+	.g_chip_ident	= mt9m001_g_chip_ident,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.g_register	= mt9m001_g_register,
+	.s_register	= mt9m001_s_register,
+#endif
+	.s_power	= mt9m001_s_power,
+};
+
+static int mt9m001_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
+			    enum v4l2_mbus_pixelcode *code)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct mt9m001 *mt9m001 = to_mt9m001(client);
+
+	if (index >= mt9m001->num_fmts)
+		return -EINVAL;
+
+	*code = mt9m001->fmts[index].code;
+	return 0;
+}
+
+static int mt9m001_g_mbus_config(struct v4l2_subdev *sd,
+				struct v4l2_mbus_config *cfg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+	/* MT9M001 has all capture_format parameters fixed */
+	cfg->flags = V4L2_MBUS_PCLK_SAMPLE_FALLING |
+		V4L2_MBUS_HSYNC_ACTIVE_HIGH | V4L2_MBUS_VSYNC_ACTIVE_HIGH |
+		V4L2_MBUS_DATA_ACTIVE_HIGH | V4L2_MBUS_MASTER;
+	cfg->type = V4L2_MBUS_PARALLEL;
+	cfg->flags = soc_camera_apply_board_flags(icl, cfg);
+
+	return 0;
+}
+
+static int mt9m001_s_mbus_config(struct v4l2_subdev *sd,
+				const struct v4l2_mbus_config *cfg)
+{
+	const struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+	struct mt9m001 *mt9m001 = to_mt9m001(client);
+	unsigned int bps = soc_mbus_get_fmtdesc(mt9m001->fmt->code)->bits_per_sample;
+
+	if (icl->set_bus_param)
+		return icl->set_bus_param(icl, 1 << (bps - 1));
+
+	/*
+	 * Without board specific bus width settings we only support the
+	 * sensors native bus width
+	 */
+	return bps == 10 ? 0 : -EINVAL;
+}
+
+static struct v4l2_subdev_video_ops mt9m001_subdev_video_ops = {
+	.s_stream	= mt9m001_s_stream,
+	.s_mbus_fmt	= mt9m001_s_fmt,
+	.g_mbus_fmt	= mt9m001_g_fmt,
+	.try_mbus_fmt	= mt9m001_try_fmt,
+	.s_crop		= mt9m001_s_crop,
+	.g_crop		= mt9m001_g_crop,
+	.cropcap	= mt9m001_cropcap,
+	.enum_mbus_fmt	= mt9m001_enum_fmt,
+	.g_mbus_config	= mt9m001_g_mbus_config,
+	.s_mbus_config	= mt9m001_s_mbus_config,
+};
+
+static struct v4l2_subdev_sensor_ops mt9m001_subdev_sensor_ops = {
+	.g_skip_top_lines	= mt9m001_g_skip_top_lines,
+};
+
+static struct v4l2_subdev_ops mt9m001_subdev_ops = {
+	.core	= &mt9m001_subdev_core_ops,
+	.video	= &mt9m001_subdev_video_ops,
+	.sensor	= &mt9m001_subdev_sensor_ops,
+};
+
+static int mt9m001_probe(struct i2c_client *client,
+			 const struct i2c_device_id *did)
+{
+	struct mt9m001 *mt9m001;
+	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+	int ret;
+
+	if (!icl) {
+		dev_err(&client->dev, "MT9M001 driver needs platform data\n");
+		return -EINVAL;
+	}
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) {
+		dev_warn(&adapter->dev,
+			 "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n");
+		return -EIO;
+	}
+
+	mt9m001 = kzalloc(sizeof(struct mt9m001), GFP_KERNEL);
+	if (!mt9m001)
+		return -ENOMEM;
+
+	v4l2_i2c_subdev_init(&mt9m001->subdev, client, &mt9m001_subdev_ops);
+	v4l2_ctrl_handler_init(&mt9m001->hdl, 4);
+	v4l2_ctrl_new_std(&mt9m001->hdl, &mt9m001_ctrl_ops,
+			V4L2_CID_VFLIP, 0, 1, 1, 0);
+	v4l2_ctrl_new_std(&mt9m001->hdl, &mt9m001_ctrl_ops,
+			V4L2_CID_GAIN, 0, 127, 1, 64);
+	mt9m001->exposure = v4l2_ctrl_new_std(&mt9m001->hdl, &mt9m001_ctrl_ops,
+			V4L2_CID_EXPOSURE, 1, 255, 1, 255);
+	/*
+	 * Simulated autoexposure. If enabled, we calculate shutter width
+	 * ourselves in the driver based on vertical blanking and frame width
+	 */
+	mt9m001->autoexposure = v4l2_ctrl_new_std_menu(&mt9m001->hdl,
+			&mt9m001_ctrl_ops, V4L2_CID_EXPOSURE_AUTO, 1, 0,
+			V4L2_EXPOSURE_AUTO);
+	mt9m001->subdev.ctrl_handler = &mt9m001->hdl;
+	if (mt9m001->hdl.error) {
+		int err = mt9m001->hdl.error;
+
+		kfree(mt9m001);
+		return err;
+	}
+	v4l2_ctrl_auto_cluster(2, &mt9m001->autoexposure,
+					V4L2_EXPOSURE_MANUAL, true);
+
+	/* Second stage probe - when a capture adapter is there */
+	mt9m001->y_skip_top	= 0;
+	mt9m001->rect.left	= MT9M001_COLUMN_SKIP;
+	mt9m001->rect.top	= MT9M001_ROW_SKIP;
+	mt9m001->rect.width	= MT9M001_MAX_WIDTH;
+	mt9m001->rect.height	= MT9M001_MAX_HEIGHT;
+
+	ret = mt9m001_video_probe(icl, client);
+	if (ret) {
+		v4l2_ctrl_handler_free(&mt9m001->hdl);
+		kfree(mt9m001);
+	}
+
+	return ret;
+}
+
+static int mt9m001_remove(struct i2c_client *client)
+{
+	struct mt9m001 *mt9m001 = to_mt9m001(client);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+	v4l2_device_unregister_subdev(&mt9m001->subdev);
+	v4l2_ctrl_handler_free(&mt9m001->hdl);
+	mt9m001_video_remove(icl);
+	kfree(mt9m001);
+
+	return 0;
+}
+
+static const struct i2c_device_id mt9m001_id[] = {
+	{ "mt9m001", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, mt9m001_id);
+
+static struct i2c_driver mt9m001_i2c_driver = {
+	.driver = {
+		.name = "mt9m001",
+	},
+	.probe		= mt9m001_probe,
+	.remove		= mt9m001_remove,
+	.id_table	= mt9m001_id,
+};
+
+module_i2c_driver(mt9m001_i2c_driver);
+
+MODULE_DESCRIPTION("Micron MT9M001 Camera driver");
+MODULE_AUTHOR("Guennadi Liakhovetski <kernel@pengutronix.de>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/i2c/soc_camera/mt9m111.c b/drivers/media/i2c/soc_camera/mt9m111.c
new file mode 100644
index 0000000..938c5c3
--- /dev/null
+++ b/drivers/media/i2c/soc_camera/mt9m111.c
@@ -0,0 +1,1046 @@
+/*
+ * Driver for MT9M111/MT9M112/MT9M131 CMOS Image Sensor from Micron/Aptina
+ *
+ * Copyright (C) 2008, Robert Jarzmik <robert.jarzmik@free.fr>
+ *
+ * This program is free software; you can 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/videodev2.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/log2.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/v4l2-mediabus.h>
+#include <linux/module.h>
+
+#include <media/soc_camera.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-chip-ident.h>
+
+/*
+ * MT9M111, MT9M112 and MT9M131:
+ * i2c address is 0x48 or 0x5d (depending on SADDR pin)
+ * The platform has to define i2c_board_info and call i2c_register_board_info()
+ */
+
+/*
+ * Sensor core register addresses (0x000..0x0ff)
+ */
+#define MT9M111_CHIP_VERSION		0x000
+#define MT9M111_ROW_START		0x001
+#define MT9M111_COLUMN_START		0x002
+#define MT9M111_WINDOW_HEIGHT		0x003
+#define MT9M111_WINDOW_WIDTH		0x004
+#define MT9M111_HORIZONTAL_BLANKING_B	0x005
+#define MT9M111_VERTICAL_BLANKING_B	0x006
+#define MT9M111_HORIZONTAL_BLANKING_A	0x007
+#define MT9M111_VERTICAL_BLANKING_A	0x008
+#define MT9M111_SHUTTER_WIDTH		0x009
+#define MT9M111_ROW_SPEED		0x00a
+#define MT9M111_EXTRA_DELAY		0x00b
+#define MT9M111_SHUTTER_DELAY		0x00c
+#define MT9M111_RESET			0x00d
+#define MT9M111_READ_MODE_B		0x020
+#define MT9M111_READ_MODE_A		0x021
+#define MT9M111_FLASH_CONTROL		0x023
+#define MT9M111_GREEN1_GAIN		0x02b
+#define MT9M111_BLUE_GAIN		0x02c
+#define MT9M111_RED_GAIN		0x02d
+#define MT9M111_GREEN2_GAIN		0x02e
+#define MT9M111_GLOBAL_GAIN		0x02f
+#define MT9M111_CONTEXT_CONTROL		0x0c8
+#define MT9M111_PAGE_MAP		0x0f0
+#define MT9M111_BYTE_WISE_ADDR		0x0f1
+
+#define MT9M111_RESET_SYNC_CHANGES	(1 << 15)
+#define MT9M111_RESET_RESTART_BAD_FRAME	(1 << 9)
+#define MT9M111_RESET_SHOW_BAD_FRAMES	(1 << 8)
+#define MT9M111_RESET_RESET_SOC		(1 << 5)
+#define MT9M111_RESET_OUTPUT_DISABLE	(1 << 4)
+#define MT9M111_RESET_CHIP_ENABLE	(1 << 3)
+#define MT9M111_RESET_ANALOG_STANDBY	(1 << 2)
+#define MT9M111_RESET_RESTART_FRAME	(1 << 1)
+#define MT9M111_RESET_RESET_MODE	(1 << 0)
+
+#define MT9M111_RM_FULL_POWER_RD	(0 << 10)
+#define MT9M111_RM_LOW_POWER_RD		(1 << 10)
+#define MT9M111_RM_COL_SKIP_4X		(1 << 5)
+#define MT9M111_RM_ROW_SKIP_4X		(1 << 4)
+#define MT9M111_RM_COL_SKIP_2X		(1 << 3)
+#define MT9M111_RM_ROW_SKIP_2X		(1 << 2)
+#define MT9M111_RMB_MIRROR_COLS		(1 << 1)
+#define MT9M111_RMB_MIRROR_ROWS		(1 << 0)
+#define MT9M111_CTXT_CTRL_RESTART	(1 << 15)
+#define MT9M111_CTXT_CTRL_DEFECTCOR_B	(1 << 12)
+#define MT9M111_CTXT_CTRL_RESIZE_B	(1 << 10)
+#define MT9M111_CTXT_CTRL_CTRL2_B	(1 << 9)
+#define MT9M111_CTXT_CTRL_GAMMA_B	(1 << 8)
+#define MT9M111_CTXT_CTRL_XENON_EN	(1 << 7)
+#define MT9M111_CTXT_CTRL_READ_MODE_B	(1 << 3)
+#define MT9M111_CTXT_CTRL_LED_FLASH_EN	(1 << 2)
+#define MT9M111_CTXT_CTRL_VBLANK_SEL_B	(1 << 1)
+#define MT9M111_CTXT_CTRL_HBLANK_SEL_B	(1 << 0)
+
+/*
+ * Colorpipe register addresses (0x100..0x1ff)
+ */
+#define MT9M111_OPER_MODE_CTRL		0x106
+#define MT9M111_OUTPUT_FORMAT_CTRL	0x108
+#define MT9M111_REDUCER_XZOOM_B		0x1a0
+#define MT9M111_REDUCER_XSIZE_B		0x1a1
+#define MT9M111_REDUCER_YZOOM_B		0x1a3
+#define MT9M111_REDUCER_YSIZE_B		0x1a4
+#define MT9M111_REDUCER_XZOOM_A		0x1a6
+#define MT9M111_REDUCER_XSIZE_A		0x1a7
+#define MT9M111_REDUCER_YZOOM_A		0x1a9
+#define MT9M111_REDUCER_YSIZE_A		0x1aa
+
+#define MT9M111_OUTPUT_FORMAT_CTRL2_A	0x13a
+#define MT9M111_OUTPUT_FORMAT_CTRL2_B	0x19b
+
+#define MT9M111_OPMODE_AUTOEXPO_EN	(1 << 14)
+#define MT9M111_OPMODE_AUTOWHITEBAL_EN	(1 << 1)
+#define MT9M111_OUTFMT_FLIP_BAYER_COL	(1 << 9)
+#define MT9M111_OUTFMT_FLIP_BAYER_ROW	(1 << 8)
+#define MT9M111_OUTFMT_PROCESSED_BAYER	(1 << 14)
+#define MT9M111_OUTFMT_BYPASS_IFP	(1 << 10)
+#define MT9M111_OUTFMT_INV_PIX_CLOCK	(1 << 9)
+#define MT9M111_OUTFMT_RGB		(1 << 8)
+#define MT9M111_OUTFMT_RGB565		(0 << 6)
+#define MT9M111_OUTFMT_RGB555		(1 << 6)
+#define MT9M111_OUTFMT_RGB444x		(2 << 6)
+#define MT9M111_OUTFMT_RGBx444		(3 << 6)
+#define MT9M111_OUTFMT_TST_RAMP_OFF	(0 << 4)
+#define MT9M111_OUTFMT_TST_RAMP_COL	(1 << 4)
+#define MT9M111_OUTFMT_TST_RAMP_ROW	(2 << 4)
+#define MT9M111_OUTFMT_TST_RAMP_FRAME	(3 << 4)
+#define MT9M111_OUTFMT_SHIFT_3_UP	(1 << 3)
+#define MT9M111_OUTFMT_AVG_CHROMA	(1 << 2)
+#define MT9M111_OUTFMT_SWAP_YCbCr_C_Y_RGB_EVEN	(1 << 1)
+#define MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr_RGB_R_B	(1 << 0)
+
+/*
+ * Camera control register addresses (0x200..0x2ff not implemented)
+ */
+
+#define reg_read(reg) mt9m111_reg_read(client, MT9M111_##reg)
+#define reg_write(reg, val) mt9m111_reg_write(client, MT9M111_##reg, (val))
+#define reg_set(reg, val) mt9m111_reg_set(client, MT9M111_##reg, (val))
+#define reg_clear(reg, val) mt9m111_reg_clear(client, MT9M111_##reg, (val))
+#define reg_mask(reg, val, mask) mt9m111_reg_mask(client, MT9M111_##reg, \
+		(val), (mask))
+
+#define MT9M111_MIN_DARK_ROWS	8
+#define MT9M111_MIN_DARK_COLS	26
+#define MT9M111_MAX_HEIGHT	1024
+#define MT9M111_MAX_WIDTH	1280
+
+struct mt9m111_context {
+	u16 read_mode;
+	u16 blanking_h;
+	u16 blanking_v;
+	u16 reducer_xzoom;
+	u16 reducer_yzoom;
+	u16 reducer_xsize;
+	u16 reducer_ysize;
+	u16 output_fmt_ctrl2;
+	u16 control;
+};
+
+static struct mt9m111_context context_a = {
+	.read_mode		= MT9M111_READ_MODE_A,
+	.blanking_h		= MT9M111_HORIZONTAL_BLANKING_A,
+	.blanking_v		= MT9M111_VERTICAL_BLANKING_A,
+	.reducer_xzoom		= MT9M111_REDUCER_XZOOM_A,
+	.reducer_yzoom		= MT9M111_REDUCER_YZOOM_A,
+	.reducer_xsize		= MT9M111_REDUCER_XSIZE_A,
+	.reducer_ysize		= MT9M111_REDUCER_YSIZE_A,
+	.output_fmt_ctrl2	= MT9M111_OUTPUT_FORMAT_CTRL2_A,
+	.control		= MT9M111_CTXT_CTRL_RESTART,
+};
+
+static struct mt9m111_context context_b = {
+	.read_mode		= MT9M111_READ_MODE_B,
+	.blanking_h		= MT9M111_HORIZONTAL_BLANKING_B,
+	.blanking_v		= MT9M111_VERTICAL_BLANKING_B,
+	.reducer_xzoom		= MT9M111_REDUCER_XZOOM_B,
+	.reducer_yzoom		= MT9M111_REDUCER_YZOOM_B,
+	.reducer_xsize		= MT9M111_REDUCER_XSIZE_B,
+	.reducer_ysize		= MT9M111_REDUCER_YSIZE_B,
+	.output_fmt_ctrl2	= MT9M111_OUTPUT_FORMAT_CTRL2_B,
+	.control		= MT9M111_CTXT_CTRL_RESTART |
+		MT9M111_CTXT_CTRL_DEFECTCOR_B | MT9M111_CTXT_CTRL_RESIZE_B |
+		MT9M111_CTXT_CTRL_CTRL2_B | MT9M111_CTXT_CTRL_GAMMA_B |
+		MT9M111_CTXT_CTRL_READ_MODE_B | MT9M111_CTXT_CTRL_VBLANK_SEL_B |
+		MT9M111_CTXT_CTRL_HBLANK_SEL_B,
+};
+
+/* MT9M111 has only one fixed colorspace per pixelcode */
+struct mt9m111_datafmt {
+	enum v4l2_mbus_pixelcode	code;
+	enum v4l2_colorspace		colorspace;
+};
+
+static const struct mt9m111_datafmt mt9m111_colour_fmts[] = {
+	{V4L2_MBUS_FMT_YUYV8_2X8, V4L2_COLORSPACE_JPEG},
+	{V4L2_MBUS_FMT_YVYU8_2X8, V4L2_COLORSPACE_JPEG},
+	{V4L2_MBUS_FMT_UYVY8_2X8, V4L2_COLORSPACE_JPEG},
+	{V4L2_MBUS_FMT_VYUY8_2X8, V4L2_COLORSPACE_JPEG},
+	{V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE, V4L2_COLORSPACE_SRGB},
+	{V4L2_MBUS_FMT_RGB555_2X8_PADHI_BE, V4L2_COLORSPACE_SRGB},
+	{V4L2_MBUS_FMT_RGB565_2X8_LE, V4L2_COLORSPACE_SRGB},
+	{V4L2_MBUS_FMT_RGB565_2X8_BE, V4L2_COLORSPACE_SRGB},
+	{V4L2_MBUS_FMT_BGR565_2X8_LE, V4L2_COLORSPACE_SRGB},
+	{V4L2_MBUS_FMT_BGR565_2X8_BE, V4L2_COLORSPACE_SRGB},
+	{V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_COLORSPACE_SRGB},
+	{V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE, V4L2_COLORSPACE_SRGB},
+};
+
+struct mt9m111 {
+	struct v4l2_subdev subdev;
+	struct v4l2_ctrl_handler hdl;
+	struct v4l2_ctrl *gain;
+	int model;	/* V4L2_IDENT_MT9M111 or V4L2_IDENT_MT9M112 code
+			 * from v4l2-chip-ident.h */
+	struct mt9m111_context *ctx;
+	struct v4l2_rect rect;	/* cropping rectangle */
+	int width;		/* output */
+	int height;		/* sizes */
+	struct mutex power_lock; /* lock to protect power_count */
+	int power_count;
+	const struct mt9m111_datafmt *fmt;
+	int lastpage;	/* PageMap cache value */
+};
+
+/* Find a data format by a pixel code */
+static const struct mt9m111_datafmt *mt9m111_find_datafmt(struct mt9m111 *mt9m111,
+						enum v4l2_mbus_pixelcode code)
+{
+	int i;
+	for (i = 0; i < ARRAY_SIZE(mt9m111_colour_fmts); i++)
+		if (mt9m111_colour_fmts[i].code == code)
+			return mt9m111_colour_fmts + i;
+
+	return mt9m111->fmt;
+}
+
+static struct mt9m111 *to_mt9m111(const struct i2c_client *client)
+{
+	return container_of(i2c_get_clientdata(client), struct mt9m111, subdev);
+}
+
+static int reg_page_map_set(struct i2c_client *client, const u16 reg)
+{
+	int ret;
+	u16 page;
+	struct mt9m111 *mt9m111 = to_mt9m111(client);
+
+	page = (reg >> 8);
+	if (page == mt9m111->lastpage)
+		return 0;
+	if (page > 2)
+		return -EINVAL;
+
+	ret = i2c_smbus_write_word_swapped(client, MT9M111_PAGE_MAP, page);
+	if (!ret)
+		mt9m111->lastpage = page;
+	return ret;
+}
+
+static int mt9m111_reg_read(struct i2c_client *client, const u16 reg)
+{
+	int ret;
+
+	ret = reg_page_map_set(client, reg);
+	if (!ret)
+		ret = i2c_smbus_read_word_swapped(client, reg & 0xff);
+
+	dev_dbg(&client->dev, "read  reg.%03x -> %04x\n", reg, ret);
+	return ret;
+}
+
+static int mt9m111_reg_write(struct i2c_client *client, const u16 reg,
+			     const u16 data)
+{
+	int ret;
+
+	ret = reg_page_map_set(client, reg);
+	if (!ret)
+		ret = i2c_smbus_write_word_swapped(client, reg & 0xff, data);
+	dev_dbg(&client->dev, "write reg.%03x = %04x -> %d\n", reg, data, ret);
+	return ret;
+}
+
+static int mt9m111_reg_set(struct i2c_client *client, const u16 reg,
+			   const u16 data)
+{
+	int ret;
+
+	ret = mt9m111_reg_read(client, reg);
+	if (ret >= 0)
+		ret = mt9m111_reg_write(client, reg, ret | data);
+	return ret;
+}
+
+static int mt9m111_reg_clear(struct i2c_client *client, const u16 reg,
+			     const u16 data)
+{
+	int ret;
+
+	ret = mt9m111_reg_read(client, reg);
+	if (ret >= 0)
+		ret = mt9m111_reg_write(client, reg, ret & ~data);
+	return ret;
+}
+
+static int mt9m111_reg_mask(struct i2c_client *client, const u16 reg,
+			    const u16 data, const u16 mask)
+{
+	int ret;
+
+	ret = mt9m111_reg_read(client, reg);
+	if (ret >= 0)
+		ret = mt9m111_reg_write(client, reg, (ret & ~mask) | data);
+	return ret;
+}
+
+static int mt9m111_set_context(struct mt9m111 *mt9m111,
+			       struct mt9m111_context *ctx)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
+	return reg_write(CONTEXT_CONTROL, ctx->control);
+}
+
+static int mt9m111_setup_rect_ctx(struct mt9m111 *mt9m111,
+			struct mt9m111_context *ctx, struct v4l2_rect *rect,
+			unsigned int width, unsigned int height)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
+	int ret = mt9m111_reg_write(client, ctx->reducer_xzoom, rect->width);
+	if (!ret)
+		ret = mt9m111_reg_write(client, ctx->reducer_yzoom, rect->height);
+	if (!ret)
+		ret = mt9m111_reg_write(client, ctx->reducer_xsize, width);
+	if (!ret)
+		ret = mt9m111_reg_write(client, ctx->reducer_ysize, height);
+	return ret;
+}
+
+static int mt9m111_setup_geometry(struct mt9m111 *mt9m111, struct v4l2_rect *rect,
+			int width, int height, enum v4l2_mbus_pixelcode code)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
+	int ret;
+
+	ret = reg_write(COLUMN_START, rect->left);
+	if (!ret)
+		ret = reg_write(ROW_START, rect->top);
+
+	if (!ret)
+		ret = reg_write(WINDOW_WIDTH, rect->width);
+	if (!ret)
+		ret = reg_write(WINDOW_HEIGHT, rect->height);
+
+	if (code != V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE) {
+		/* IFP in use, down-scaling possible */
+		if (!ret)
+			ret = mt9m111_setup_rect_ctx(mt9m111, &context_b,
+						     rect, width, height);
+		if (!ret)
+			ret = mt9m111_setup_rect_ctx(mt9m111, &context_a,
+						     rect, width, height);
+	}
+
+	dev_dbg(&client->dev, "%s(%x): %ux%u@%u:%u -> %ux%u = %d\n",
+		__func__, code, rect->width, rect->height, rect->left, rect->top,
+		width, height, ret);
+
+	return ret;
+}
+
+static int mt9m111_enable(struct mt9m111 *mt9m111)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
+	return reg_write(RESET, MT9M111_RESET_CHIP_ENABLE);
+}
+
+static int mt9m111_reset(struct mt9m111 *mt9m111)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
+	int ret;
+
+	ret = reg_set(RESET, MT9M111_RESET_RESET_MODE);
+	if (!ret)
+		ret = reg_set(RESET, MT9M111_RESET_RESET_SOC);
+	if (!ret)
+		ret = reg_clear(RESET, MT9M111_RESET_RESET_MODE
+				| MT9M111_RESET_RESET_SOC);
+
+	return ret;
+}
+
+static int mt9m111_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
+{
+	struct v4l2_rect rect = a->c;
+	struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev);
+	int width, height;
+	int ret;
+
+	if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
+	if (mt9m111->fmt->code == V4L2_MBUS_FMT_SBGGR8_1X8 ||
+	    mt9m111->fmt->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE) {
+		/* Bayer format - even size lengths */
+		rect.width	= ALIGN(rect.width, 2);
+		rect.height	= ALIGN(rect.height, 2);
+		/* Let the user play with the starting pixel */
+	}
+
+	/* FIXME: the datasheet doesn't specify minimum sizes */
+	soc_camera_limit_side(&rect.left, &rect.width,
+		     MT9M111_MIN_DARK_COLS, 2, MT9M111_MAX_WIDTH);
+
+	soc_camera_limit_side(&rect.top, &rect.height,
+		     MT9M111_MIN_DARK_ROWS, 2, MT9M111_MAX_HEIGHT);
+
+	width = min(mt9m111->width, rect.width);
+	height = min(mt9m111->height, rect.height);
+
+	ret = mt9m111_setup_geometry(mt9m111, &rect, width, height, mt9m111->fmt->code);
+	if (!ret) {
+		mt9m111->rect = rect;
+		mt9m111->width = width;
+		mt9m111->height = height;
+	}
+
+	return ret;
+}
+
+static int mt9m111_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
+{
+	struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev);
+
+	a->c	= mt9m111->rect;
+	a->type	= V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+	return 0;
+}
+
+static int mt9m111_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
+{
+	if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
+	a->bounds.left			= MT9M111_MIN_DARK_COLS;
+	a->bounds.top			= MT9M111_MIN_DARK_ROWS;
+	a->bounds.width			= MT9M111_MAX_WIDTH;
+	a->bounds.height		= MT9M111_MAX_HEIGHT;
+	a->defrect			= a->bounds;
+	a->pixelaspect.numerator	= 1;
+	a->pixelaspect.denominator	= 1;
+
+	return 0;
+}
+
+static int mt9m111_g_fmt(struct v4l2_subdev *sd,
+			 struct v4l2_mbus_framefmt *mf)
+{
+	struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev);
+
+	mf->width	= mt9m111->width;
+	mf->height	= mt9m111->height;
+	mf->code	= mt9m111->fmt->code;
+	mf->colorspace	= mt9m111->fmt->colorspace;
+	mf->field	= V4L2_FIELD_NONE;
+
+	return 0;
+}
+
+static int mt9m111_set_pixfmt(struct mt9m111 *mt9m111,
+			      enum v4l2_mbus_pixelcode code)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
+	u16 data_outfmt2, mask_outfmt2 = MT9M111_OUTFMT_PROCESSED_BAYER |
+		MT9M111_OUTFMT_BYPASS_IFP | MT9M111_OUTFMT_RGB |
+		MT9M111_OUTFMT_RGB565 | MT9M111_OUTFMT_RGB555 |
+		MT9M111_OUTFMT_RGB444x | MT9M111_OUTFMT_RGBx444 |
+		MT9M111_OUTFMT_SWAP_YCbCr_C_Y_RGB_EVEN |
+		MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr_RGB_R_B;
+	int ret;
+
+	switch (code) {
+	case V4L2_MBUS_FMT_SBGGR8_1X8:
+		data_outfmt2 = MT9M111_OUTFMT_PROCESSED_BAYER |
+			MT9M111_OUTFMT_RGB;
+		break;
+	case V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE:
+		data_outfmt2 = MT9M111_OUTFMT_BYPASS_IFP | MT9M111_OUTFMT_RGB;
+		break;
+	case V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE:
+		data_outfmt2 = MT9M111_OUTFMT_RGB | MT9M111_OUTFMT_RGB555 |
+			MT9M111_OUTFMT_SWAP_YCbCr_C_Y_RGB_EVEN;
+		break;
+	case V4L2_MBUS_FMT_RGB555_2X8_PADHI_BE:
+		data_outfmt2 = MT9M111_OUTFMT_RGB | MT9M111_OUTFMT_RGB555;
+		break;
+	case V4L2_MBUS_FMT_RGB565_2X8_LE:
+		data_outfmt2 = MT9M111_OUTFMT_RGB | MT9M111_OUTFMT_RGB565 |
+			MT9M111_OUTFMT_SWAP_YCbCr_C_Y_RGB_EVEN;
+		break;
+	case V4L2_MBUS_FMT_RGB565_2X8_BE:
+		data_outfmt2 = MT9M111_OUTFMT_RGB | MT9M111_OUTFMT_RGB565;
+		break;
+	case V4L2_MBUS_FMT_BGR565_2X8_BE:
+		data_outfmt2 = MT9M111_OUTFMT_RGB | MT9M111_OUTFMT_RGB565 |
+			MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr_RGB_R_B;
+		break;
+	case V4L2_MBUS_FMT_BGR565_2X8_LE:
+		data_outfmt2 = MT9M111_OUTFMT_RGB | MT9M111_OUTFMT_RGB565 |
+			MT9M111_OUTFMT_SWAP_YCbCr_C_Y_RGB_EVEN |
+			MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr_RGB_R_B;
+		break;
+	case V4L2_MBUS_FMT_UYVY8_2X8:
+		data_outfmt2 = 0;
+		break;
+	case V4L2_MBUS_FMT_VYUY8_2X8:
+		data_outfmt2 = MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr_RGB_R_B;
+		break;
+	case V4L2_MBUS_FMT_YUYV8_2X8:
+		data_outfmt2 = MT9M111_OUTFMT_SWAP_YCbCr_C_Y_RGB_EVEN;
+		break;
+	case V4L2_MBUS_FMT_YVYU8_2X8:
+		data_outfmt2 = MT9M111_OUTFMT_SWAP_YCbCr_C_Y_RGB_EVEN |
+			MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr_RGB_R_B;
+		break;
+	default:
+		dev_err(&client->dev, "Pixel format not handled: %x\n", code);
+		return -EINVAL;
+	}
+
+	ret = mt9m111_reg_mask(client, context_a.output_fmt_ctrl2,
+			       data_outfmt2, mask_outfmt2);
+	if (!ret)
+		ret = mt9m111_reg_mask(client, context_b.output_fmt_ctrl2,
+				       data_outfmt2, mask_outfmt2);
+
+	return ret;
+}
+
+static int mt9m111_try_fmt(struct v4l2_subdev *sd,
+			   struct v4l2_mbus_framefmt *mf)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev);
+	const struct mt9m111_datafmt *fmt;
+	struct v4l2_rect *rect = &mt9m111->rect;
+	bool bayer;
+
+	fmt = mt9m111_find_datafmt(mt9m111, mf->code);
+
+	bayer = fmt->code == V4L2_MBUS_FMT_SBGGR8_1X8 ||
+		fmt->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE;
+
+	/*
+	 * With Bayer format enforce even side lengths, but let the user play
+	 * with the starting pixel
+	 */
+	if (bayer) {
+		rect->width = ALIGN(rect->width, 2);
+		rect->height = ALIGN(rect->height, 2);
+	}
+
+	if (fmt->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE) {
+		/* IFP bypass mode, no scaling */
+		mf->width = rect->width;
+		mf->height = rect->height;
+	} else {
+		/* No upscaling */
+		if (mf->width > rect->width)
+			mf->width = rect->width;
+		if (mf->height > rect->height)
+			mf->height = rect->height;
+	}
+
+	dev_dbg(&client->dev, "%s(): %ux%u, code=%x\n", __func__,
+		mf->width, mf->height, fmt->code);
+
+	mf->code = fmt->code;
+	mf->colorspace = fmt->colorspace;
+
+	return 0;
+}
+
+static int mt9m111_s_fmt(struct v4l2_subdev *sd,
+			 struct v4l2_mbus_framefmt *mf)
+{
+	const struct mt9m111_datafmt *fmt;
+	struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev);
+	struct v4l2_rect *rect = &mt9m111->rect;
+	int ret;
+
+	mt9m111_try_fmt(sd, mf);
+	fmt = mt9m111_find_datafmt(mt9m111, mf->code);
+	/* try_fmt() guarantees fmt != NULL && fmt->code == mf->code */
+
+	ret = mt9m111_setup_geometry(mt9m111, rect, mf->width, mf->height, mf->code);
+	if (!ret)
+		ret = mt9m111_set_pixfmt(mt9m111, mf->code);
+	if (!ret) {
+		mt9m111->width	= mf->width;
+		mt9m111->height	= mf->height;
+		mt9m111->fmt	= fmt;
+	}
+
+	return ret;
+}
+
+static int mt9m111_g_chip_ident(struct v4l2_subdev *sd,
+				struct v4l2_dbg_chip_ident *id)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev);
+
+	if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
+		return -EINVAL;
+
+	if (id->match.addr != client->addr)
+		return -ENODEV;
+
+	id->ident	= mt9m111->model;
+	id->revision	= 0;
+
+	return 0;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int mt9m111_g_register(struct v4l2_subdev *sd,
+			      struct v4l2_dbg_register *reg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	int val;
+
+	if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff)
+		return -EINVAL;
+	if (reg->match.addr != client->addr)
+		return -ENODEV;
+
+	val = mt9m111_reg_read(client, reg->reg);
+	reg->size = 2;
+	reg->val = (u64)val;
+
+	if (reg->val > 0xffff)
+		return -EIO;
+
+	return 0;
+}
+
+static int mt9m111_s_register(struct v4l2_subdev *sd,
+			      struct v4l2_dbg_register *reg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0x2ff)
+		return -EINVAL;
+
+	if (reg->match.addr != client->addr)
+		return -ENODEV;
+
+	if (mt9m111_reg_write(client, reg->reg, reg->val) < 0)
+		return -EIO;
+
+	return 0;
+}
+#endif
+
+static int mt9m111_set_flip(struct mt9m111 *mt9m111, int flip, int mask)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
+	int ret;
+
+	if (flip)
+		ret = mt9m111_reg_set(client, mt9m111->ctx->read_mode, mask);
+	else
+		ret = mt9m111_reg_clear(client, mt9m111->ctx->read_mode, mask);
+
+	return ret;
+}
+
+static int mt9m111_get_global_gain(struct mt9m111 *mt9m111)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
+	int data;
+
+	data = reg_read(GLOBAL_GAIN);
+	if (data >= 0)
+		return (data & 0x2f) * (1 << ((data >> 10) & 1)) *
+			(1 << ((data >> 9) & 1));
+	return data;
+}
+
+static int mt9m111_set_global_gain(struct mt9m111 *mt9m111, int gain)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
+	u16 val;
+
+	if (gain > 63 * 2 * 2)
+		return -EINVAL;
+
+	if ((gain >= 64 * 2) && (gain < 63 * 2 * 2))
+		val = (1 << 10) | (1 << 9) | (gain / 4);
+	else if ((gain >= 64) && (gain < 64 * 2))
+		val = (1 << 9) | (gain / 2);
+	else
+		val = gain;
+
+	return reg_write(GLOBAL_GAIN, val);
+}
+
+static int mt9m111_set_autoexposure(struct mt9m111 *mt9m111, int on)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
+
+	if (on)
+		return reg_set(OPER_MODE_CTRL, MT9M111_OPMODE_AUTOEXPO_EN);
+	return reg_clear(OPER_MODE_CTRL, MT9M111_OPMODE_AUTOEXPO_EN);
+}
+
+static int mt9m111_set_autowhitebalance(struct mt9m111 *mt9m111, int on)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
+
+	if (on)
+		return reg_set(OPER_MODE_CTRL, MT9M111_OPMODE_AUTOWHITEBAL_EN);
+	return reg_clear(OPER_MODE_CTRL, MT9M111_OPMODE_AUTOWHITEBAL_EN);
+}
+
+static int mt9m111_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct mt9m111 *mt9m111 = container_of(ctrl->handler,
+					       struct mt9m111, hdl);
+
+	switch (ctrl->id) {
+	case V4L2_CID_VFLIP:
+		return mt9m111_set_flip(mt9m111, ctrl->val,
+					MT9M111_RMB_MIRROR_ROWS);
+	case V4L2_CID_HFLIP:
+		return mt9m111_set_flip(mt9m111, ctrl->val,
+					MT9M111_RMB_MIRROR_COLS);
+	case V4L2_CID_GAIN:
+		return mt9m111_set_global_gain(mt9m111, ctrl->val);
+	case V4L2_CID_EXPOSURE_AUTO:
+		return mt9m111_set_autoexposure(mt9m111, ctrl->val);
+	case V4L2_CID_AUTO_WHITE_BALANCE:
+		return mt9m111_set_autowhitebalance(mt9m111, ctrl->val);
+	}
+
+	return -EINVAL;
+}
+
+static int mt9m111_suspend(struct mt9m111 *mt9m111)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
+	int ret;
+
+	v4l2_ctrl_s_ctrl(mt9m111->gain, mt9m111_get_global_gain(mt9m111));
+
+	ret = reg_set(RESET, MT9M111_RESET_RESET_MODE);
+	if (!ret)
+		ret = reg_set(RESET, MT9M111_RESET_RESET_SOC |
+			      MT9M111_RESET_OUTPUT_DISABLE |
+			      MT9M111_RESET_ANALOG_STANDBY);
+	if (!ret)
+		ret = reg_clear(RESET, MT9M111_RESET_CHIP_ENABLE);
+
+	return ret;
+}
+
+static void mt9m111_restore_state(struct mt9m111 *mt9m111)
+{
+	mt9m111_set_context(mt9m111, mt9m111->ctx);
+	mt9m111_set_pixfmt(mt9m111, mt9m111->fmt->code);
+	mt9m111_setup_geometry(mt9m111, &mt9m111->rect,
+			mt9m111->width, mt9m111->height, mt9m111->fmt->code);
+	v4l2_ctrl_handler_setup(&mt9m111->hdl);
+}
+
+static int mt9m111_resume(struct mt9m111 *mt9m111)
+{
+	int ret = mt9m111_enable(mt9m111);
+	if (!ret)
+		ret = mt9m111_reset(mt9m111);
+	if (!ret)
+		mt9m111_restore_state(mt9m111);
+
+	return ret;
+}
+
+static int mt9m111_init(struct mt9m111 *mt9m111)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
+	int ret;
+
+	/* Default HIGHPOWER context */
+	mt9m111->ctx = &context_b;
+	ret = mt9m111_enable(mt9m111);
+	if (!ret)
+		ret = mt9m111_reset(mt9m111);
+	if (!ret)
+		ret = mt9m111_set_context(mt9m111, mt9m111->ctx);
+	if (ret)
+		dev_err(&client->dev, "mt9m111 init failed: %d\n", ret);
+	return ret;
+}
+
+static int mt9m111_power_on(struct mt9m111 *mt9m111)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+	int ret;
+
+	ret = soc_camera_power_on(&client->dev, icl);
+	if (ret < 0)
+		return ret;
+
+	ret = mt9m111_resume(mt9m111);
+	if (ret < 0) {
+		dev_err(&client->dev, "Failed to resume the sensor: %d\n", ret);
+		soc_camera_power_off(&client->dev, icl);
+	}
+
+	return ret;
+}
+
+static void mt9m111_power_off(struct mt9m111 *mt9m111)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+	mt9m111_suspend(mt9m111);
+	soc_camera_power_off(&client->dev, icl);
+}
+
+static int mt9m111_s_power(struct v4l2_subdev *sd, int on)
+{
+	struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev);
+	int ret = 0;
+
+	mutex_lock(&mt9m111->power_lock);
+
+	/*
+	 * If the power count is modified from 0 to != 0 or from != 0 to 0,
+	 * update the power state.
+	 */
+	if (mt9m111->power_count == !on) {
+		if (on)
+			ret = mt9m111_power_on(mt9m111);
+		else
+			mt9m111_power_off(mt9m111);
+	}
+
+	if (!ret) {
+		/* Update the power count. */
+		mt9m111->power_count += on ? 1 : -1;
+		WARN_ON(mt9m111->power_count < 0);
+	}
+
+	mutex_unlock(&mt9m111->power_lock);
+	return ret;
+}
+
+static const struct v4l2_ctrl_ops mt9m111_ctrl_ops = {
+	.s_ctrl = mt9m111_s_ctrl,
+};
+
+static struct v4l2_subdev_core_ops mt9m111_subdev_core_ops = {
+	.g_chip_ident	= mt9m111_g_chip_ident,
+	.s_power	= mt9m111_s_power,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.g_register	= mt9m111_g_register,
+	.s_register	= mt9m111_s_register,
+#endif
+};
+
+static int mt9m111_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
+			    enum v4l2_mbus_pixelcode *code)
+{
+	if (index >= ARRAY_SIZE(mt9m111_colour_fmts))
+		return -EINVAL;
+
+	*code = mt9m111_colour_fmts[index].code;
+	return 0;
+}
+
+static int mt9m111_g_mbus_config(struct v4l2_subdev *sd,
+				struct v4l2_mbus_config *cfg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+	cfg->flags = V4L2_MBUS_MASTER | V4L2_MBUS_PCLK_SAMPLE_RISING |
+		V4L2_MBUS_HSYNC_ACTIVE_HIGH | V4L2_MBUS_VSYNC_ACTIVE_HIGH |
+		V4L2_MBUS_DATA_ACTIVE_HIGH;
+	cfg->type = V4L2_MBUS_PARALLEL;
+	cfg->flags = soc_camera_apply_board_flags(icl, cfg);
+
+	return 0;
+}
+
+static struct v4l2_subdev_video_ops mt9m111_subdev_video_ops = {
+	.s_mbus_fmt	= mt9m111_s_fmt,
+	.g_mbus_fmt	= mt9m111_g_fmt,
+	.try_mbus_fmt	= mt9m111_try_fmt,
+	.s_crop		= mt9m111_s_crop,
+	.g_crop		= mt9m111_g_crop,
+	.cropcap	= mt9m111_cropcap,
+	.enum_mbus_fmt	= mt9m111_enum_fmt,
+	.g_mbus_config	= mt9m111_g_mbus_config,
+};
+
+static struct v4l2_subdev_ops mt9m111_subdev_ops = {
+	.core	= &mt9m111_subdev_core_ops,
+	.video	= &mt9m111_subdev_video_ops,
+};
+
+/*
+ * Interface active, can use i2c. If it fails, it can indeed mean, that
+ * this wasn't our capture interface, so, we wait for the right one
+ */
+static int mt9m111_video_probe(struct i2c_client *client)
+{
+	struct mt9m111 *mt9m111 = to_mt9m111(client);
+	s32 data;
+	int ret;
+
+	ret = mt9m111_s_power(&mt9m111->subdev, 1);
+	if (ret < 0)
+		return ret;
+
+	data = reg_read(CHIP_VERSION);
+
+	switch (data) {
+	case 0x143a: /* MT9M111 or MT9M131 */
+		mt9m111->model = V4L2_IDENT_MT9M111;
+		dev_info(&client->dev,
+			"Detected a MT9M111/MT9M131 chip ID %x\n", data);
+		break;
+	case 0x148c: /* MT9M112 */
+		mt9m111->model = V4L2_IDENT_MT9M112;
+		dev_info(&client->dev, "Detected a MT9M112 chip ID %x\n", data);
+		break;
+	default:
+		dev_err(&client->dev,
+			"No MT9M111/MT9M112/MT9M131 chip detected register read %x\n",
+			data);
+		ret = -ENODEV;
+		goto done;
+	}
+
+	ret = mt9m111_init(mt9m111);
+	if (ret)
+		goto done;
+
+	ret = v4l2_ctrl_handler_setup(&mt9m111->hdl);
+
+done:
+	mt9m111_s_power(&mt9m111->subdev, 0);
+	return ret;
+}
+
+static int mt9m111_probe(struct i2c_client *client,
+			 const struct i2c_device_id *did)
+{
+	struct mt9m111 *mt9m111;
+	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+	int ret;
+
+	if (!icl) {
+		dev_err(&client->dev, "mt9m111: driver needs platform data\n");
+		return -EINVAL;
+	}
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) {
+		dev_warn(&adapter->dev,
+			 "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n");
+		return -EIO;
+	}
+
+	mt9m111 = kzalloc(sizeof(struct mt9m111), GFP_KERNEL);
+	if (!mt9m111)
+		return -ENOMEM;
+
+	v4l2_i2c_subdev_init(&mt9m111->subdev, client, &mt9m111_subdev_ops);
+	v4l2_ctrl_handler_init(&mt9m111->hdl, 5);
+	v4l2_ctrl_new_std(&mt9m111->hdl, &mt9m111_ctrl_ops,
+			V4L2_CID_VFLIP, 0, 1, 1, 0);
+	v4l2_ctrl_new_std(&mt9m111->hdl, &mt9m111_ctrl_ops,
+			V4L2_CID_HFLIP, 0, 1, 1, 0);
+	v4l2_ctrl_new_std(&mt9m111->hdl, &mt9m111_ctrl_ops,
+			V4L2_CID_AUTO_WHITE_BALANCE, 0, 1, 1, 1);
+	mt9m111->gain = v4l2_ctrl_new_std(&mt9m111->hdl, &mt9m111_ctrl_ops,
+			V4L2_CID_GAIN, 0, 63 * 2 * 2, 1, 32);
+	v4l2_ctrl_new_std_menu(&mt9m111->hdl,
+			&mt9m111_ctrl_ops, V4L2_CID_EXPOSURE_AUTO, 1, 0,
+			V4L2_EXPOSURE_AUTO);
+	mt9m111->subdev.ctrl_handler = &mt9m111->hdl;
+	if (mt9m111->hdl.error) {
+		int err = mt9m111->hdl.error;
+
+		kfree(mt9m111);
+		return err;
+	}
+
+	/* Second stage probe - when a capture adapter is there */
+	mt9m111->rect.left	= MT9M111_MIN_DARK_COLS;
+	mt9m111->rect.top	= MT9M111_MIN_DARK_ROWS;
+	mt9m111->rect.width	= MT9M111_MAX_WIDTH;
+	mt9m111->rect.height	= MT9M111_MAX_HEIGHT;
+	mt9m111->fmt		= &mt9m111_colour_fmts[0];
+	mt9m111->lastpage	= -1;
+	mutex_init(&mt9m111->power_lock);
+
+	ret = mt9m111_video_probe(client);
+	if (ret) {
+		v4l2_ctrl_handler_free(&mt9m111->hdl);
+		kfree(mt9m111);
+	}
+
+	return ret;
+}
+
+static int mt9m111_remove(struct i2c_client *client)
+{
+	struct mt9m111 *mt9m111 = to_mt9m111(client);
+
+	v4l2_device_unregister_subdev(&mt9m111->subdev);
+	v4l2_ctrl_handler_free(&mt9m111->hdl);
+	kfree(mt9m111);
+
+	return 0;
+}
+
+static const struct i2c_device_id mt9m111_id[] = {
+	{ "mt9m111", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, mt9m111_id);
+
+static struct i2c_driver mt9m111_i2c_driver = {
+	.driver = {
+		.name = "mt9m111",
+	},
+	.probe		= mt9m111_probe,
+	.remove		= mt9m111_remove,
+	.id_table	= mt9m111_id,
+};
+
+module_i2c_driver(mt9m111_i2c_driver);
+
+MODULE_DESCRIPTION("Micron/Aptina MT9M111/MT9M112/MT9M131 Camera driver");
+MODULE_AUTHOR("Robert Jarzmik");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/i2c/soc_camera/mt9t031.c b/drivers/media/i2c/soc_camera/mt9t031.c
new file mode 100644
index 0000000..d74607a
--- /dev/null
+++ b/drivers/media/i2c/soc_camera/mt9t031.c
@@ -0,0 +1,857 @@
+/*
+ * Driver for MT9T031 CMOS Image Sensor from Micron
+ *
+ * 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/device.h>
+#include <linux/i2c.h>
+#include <linux/log2.h>
+#include <linux/pm.h>
+#include <linux/slab.h>
+#include <linux/v4l2-mediabus.h>
+#include <linux/videodev2.h>
+#include <linux/module.h>
+
+#include <media/soc_camera.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-subdev.h>
+#include <media/v4l2-ctrls.h>
+
+/*
+ * ATTENTION: this driver still cannot be used outside of the soc-camera
+ * framework because of its PM implementation, using the video_device node.
+ * If hardware becomes available for testing, alternative PM approaches shall
+ * be considered and tested.
+ */
+
+/*
+ * mt9t031 i2c address 0x5d
+ * The platform has to define i2c_board_info and link to it from
+ * struct soc_camera_link
+ */
+
+/* mt9t031 selected register addresses */
+#define MT9T031_CHIP_VERSION		0x00
+#define MT9T031_ROW_START		0x01
+#define MT9T031_COLUMN_START		0x02
+#define MT9T031_WINDOW_HEIGHT		0x03
+#define MT9T031_WINDOW_WIDTH		0x04
+#define MT9T031_HORIZONTAL_BLANKING	0x05
+#define MT9T031_VERTICAL_BLANKING	0x06
+#define MT9T031_OUTPUT_CONTROL		0x07
+#define MT9T031_SHUTTER_WIDTH_UPPER	0x08
+#define MT9T031_SHUTTER_WIDTH		0x09
+#define MT9T031_PIXEL_CLOCK_CONTROL	0x0a
+#define MT9T031_FRAME_RESTART		0x0b
+#define MT9T031_SHUTTER_DELAY		0x0c
+#define MT9T031_RESET			0x0d
+#define MT9T031_READ_MODE_1		0x1e
+#define MT9T031_READ_MODE_2		0x20
+#define MT9T031_READ_MODE_3		0x21
+#define MT9T031_ROW_ADDRESS_MODE	0x22
+#define MT9T031_COLUMN_ADDRESS_MODE	0x23
+#define MT9T031_GLOBAL_GAIN		0x35
+#define MT9T031_CHIP_ENABLE		0xF8
+
+#define MT9T031_MAX_HEIGHT		1536
+#define MT9T031_MAX_WIDTH		2048
+#define MT9T031_MIN_HEIGHT		2
+#define MT9T031_MIN_WIDTH		18
+#define MT9T031_HORIZONTAL_BLANK	142
+#define MT9T031_VERTICAL_BLANK		25
+#define MT9T031_COLUMN_SKIP		32
+#define MT9T031_ROW_SKIP		20
+
+struct mt9t031 {
+	struct v4l2_subdev subdev;
+	struct v4l2_ctrl_handler hdl;
+	struct {
+		/* exposure/auto-exposure cluster */
+		struct v4l2_ctrl *autoexposure;
+		struct v4l2_ctrl *exposure;
+	};
+	struct v4l2_rect rect;	/* Sensor window */
+	int model;	/* V4L2_IDENT_MT9T031* codes from v4l2-chip-ident.h */
+	u16 xskip;
+	u16 yskip;
+	unsigned int total_h;
+	unsigned short y_skip_top;	/* Lines to skip at the top */
+};
+
+static struct mt9t031 *to_mt9t031(const struct i2c_client *client)
+{
+	return container_of(i2c_get_clientdata(client), struct mt9t031, subdev);
+}
+
+static int reg_read(struct i2c_client *client, const u8 reg)
+{
+	return i2c_smbus_read_word_swapped(client, reg);
+}
+
+static int reg_write(struct i2c_client *client, const u8 reg,
+		     const u16 data)
+{
+	return i2c_smbus_write_word_swapped(client, reg, data);
+}
+
+static int reg_set(struct i2c_client *client, const u8 reg,
+		   const u16 data)
+{
+	int ret;
+
+	ret = reg_read(client, reg);
+	if (ret < 0)
+		return ret;
+	return reg_write(client, reg, ret | data);
+}
+
+static int reg_clear(struct i2c_client *client, const u8 reg,
+		     const u16 data)
+{
+	int ret;
+
+	ret = reg_read(client, reg);
+	if (ret < 0)
+		return ret;
+	return reg_write(client, reg, ret & ~data);
+}
+
+static int set_shutter(struct i2c_client *client, const u32 data)
+{
+	int ret;
+
+	ret = reg_write(client, MT9T031_SHUTTER_WIDTH_UPPER, data >> 16);
+
+	if (ret >= 0)
+		ret = reg_write(client, MT9T031_SHUTTER_WIDTH, data & 0xffff);
+
+	return ret;
+}
+
+static int get_shutter(struct i2c_client *client, u32 *data)
+{
+	int ret;
+
+	ret = reg_read(client, MT9T031_SHUTTER_WIDTH_UPPER);
+	*data = ret << 16;
+
+	if (ret >= 0)
+		ret = reg_read(client, MT9T031_SHUTTER_WIDTH);
+	*data |= ret & 0xffff;
+
+	return ret < 0 ? ret : 0;
+}
+
+static int mt9t031_idle(struct i2c_client *client)
+{
+	int ret;
+
+	/* Disable chip output, synchronous option update */
+	ret = reg_write(client, MT9T031_RESET, 1);
+	if (ret >= 0)
+		ret = reg_write(client, MT9T031_RESET, 0);
+	if (ret >= 0)
+		ret = reg_clear(client, MT9T031_OUTPUT_CONTROL, 2);
+
+	return ret >= 0 ? 0 : -EIO;
+}
+
+static int mt9t031_s_stream(struct v4l2_subdev *sd, int enable)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	int ret;
+
+	if (enable)
+		/* Switch to master "normal" mode */
+		ret = reg_set(client, MT9T031_OUTPUT_CONTROL, 2);
+	else
+		/* Stop sensor readout */
+		ret = reg_clear(client, MT9T031_OUTPUT_CONTROL, 2);
+
+	if (ret < 0)
+		return -EIO;
+
+	return 0;
+}
+
+/* target must be _even_ */
+static u16 mt9t031_skip(s32 *source, s32 target, s32 max)
+{
+	unsigned int skip;
+
+	if (*source < target + target / 2) {
+		*source = target;
+		return 1;
+	}
+
+	skip = min(max, *source + target / 2) / target;
+	if (skip > 8)
+		skip = 8;
+	*source = target * skip;
+
+	return skip;
+}
+
+/* rect is the sensor rectangle, the caller guarantees parameter validity */
+static int mt9t031_set_params(struct i2c_client *client,
+			      struct v4l2_rect *rect, u16 xskip, u16 yskip)
+{
+	struct mt9t031 *mt9t031 = to_mt9t031(client);
+	int ret;
+	u16 xbin, ybin;
+	const u16 hblank = MT9T031_HORIZONTAL_BLANK,
+		vblank = MT9T031_VERTICAL_BLANK;
+
+	xbin = min(xskip, (u16)3);
+	ybin = min(yskip, (u16)3);
+
+	/*
+	 * Could just do roundup(rect->left, [xy]bin * 2); but this is cheaper.
+	 * There is always a valid suitably aligned value. The worst case is
+	 * xbin = 3, width = 2048. Then we will start at 36, the last read out
+	 * pixel will be 2083, which is < 2085 - first black pixel.
+	 *
+	 * MT9T031 datasheet imposes window left border alignment, depending on
+	 * the selected xskip. Failing to conform to this requirement produces
+	 * dark horizontal stripes in the image. However, even obeying to this
+	 * requirement doesn't eliminate the stripes in all configurations. They
+	 * appear "locally reproducibly," but can differ between tests under
+	 * different lighting conditions.
+	 */
+	switch (xbin) {
+	case 1:
+		rect->left &= ~1;
+		break;
+	case 2:
+		rect->left &= ~3;
+		break;
+	case 3:
+		rect->left = rect->left > roundup(MT9T031_COLUMN_SKIP, 6) ?
+			(rect->left / 6) * 6 : roundup(MT9T031_COLUMN_SKIP, 6);
+	}
+
+	rect->top &= ~1;
+
+	dev_dbg(&client->dev, "skip %u:%u, rect %ux%u@%u:%u\n",
+		xskip, yskip, rect->width, rect->height, rect->left, rect->top);
+
+	/* Disable register update, reconfigure atomically */
+	ret = reg_set(client, MT9T031_OUTPUT_CONTROL, 1);
+	if (ret < 0)
+		return ret;
+
+	/* Blanking and start values - default... */
+	ret = reg_write(client, MT9T031_HORIZONTAL_BLANKING, hblank);
+	if (ret >= 0)
+		ret = reg_write(client, MT9T031_VERTICAL_BLANKING, vblank);
+
+	if (yskip != mt9t031->yskip || xskip != mt9t031->xskip) {
+		/* Binning, skipping */
+		if (ret >= 0)
+			ret = reg_write(client, MT9T031_COLUMN_ADDRESS_MODE,
+					((xbin - 1) << 4) | (xskip - 1));
+		if (ret >= 0)
+			ret = reg_write(client, MT9T031_ROW_ADDRESS_MODE,
+					((ybin - 1) << 4) | (yskip - 1));
+	}
+	dev_dbg(&client->dev, "new physical left %u, top %u\n",
+		rect->left, rect->top);
+
+	/*
+	 * The caller provides a supported format, as guaranteed by
+	 * .try_mbus_fmt(), soc_camera_s_crop() and soc_camera_cropcap()
+	 */
+	if (ret >= 0)
+		ret = reg_write(client, MT9T031_COLUMN_START, rect->left);
+	if (ret >= 0)
+		ret = reg_write(client, MT9T031_ROW_START, rect->top);
+	if (ret >= 0)
+		ret = reg_write(client, MT9T031_WINDOW_WIDTH, rect->width - 1);
+	if (ret >= 0)
+		ret = reg_write(client, MT9T031_WINDOW_HEIGHT,
+				rect->height + mt9t031->y_skip_top - 1);
+	if (ret >= 0 && v4l2_ctrl_g_ctrl(mt9t031->autoexposure) == V4L2_EXPOSURE_AUTO) {
+		mt9t031->total_h = rect->height + mt9t031->y_skip_top + vblank;
+
+		ret = set_shutter(client, mt9t031->total_h);
+	}
+
+	/* Re-enable register update, commit all changes */
+	if (ret >= 0)
+		ret = reg_clear(client, MT9T031_OUTPUT_CONTROL, 1);
+
+	if (ret >= 0) {
+		mt9t031->rect = *rect;
+		mt9t031->xskip = xskip;
+		mt9t031->yskip = yskip;
+	}
+
+	return ret < 0 ? ret : 0;
+}
+
+static int mt9t031_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
+{
+	struct v4l2_rect rect = a->c;
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct mt9t031 *mt9t031 = to_mt9t031(client);
+
+	rect.width = ALIGN(rect.width, 2);
+	rect.height = ALIGN(rect.height, 2);
+
+	soc_camera_limit_side(&rect.left, &rect.width,
+		     MT9T031_COLUMN_SKIP, MT9T031_MIN_WIDTH, MT9T031_MAX_WIDTH);
+
+	soc_camera_limit_side(&rect.top, &rect.height,
+		     MT9T031_ROW_SKIP, MT9T031_MIN_HEIGHT, MT9T031_MAX_HEIGHT);
+
+	return mt9t031_set_params(client, &rect, mt9t031->xskip, mt9t031->yskip);
+}
+
+static int mt9t031_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct mt9t031 *mt9t031 = to_mt9t031(client);
+
+	a->c	= mt9t031->rect;
+	a->type	= V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+	return 0;
+}
+
+static int mt9t031_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
+{
+	a->bounds.left			= MT9T031_COLUMN_SKIP;
+	a->bounds.top			= MT9T031_ROW_SKIP;
+	a->bounds.width			= MT9T031_MAX_WIDTH;
+	a->bounds.height		= MT9T031_MAX_HEIGHT;
+	a->defrect			= a->bounds;
+	a->type				= V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	a->pixelaspect.numerator	= 1;
+	a->pixelaspect.denominator	= 1;
+
+	return 0;
+}
+
+static int mt9t031_g_fmt(struct v4l2_subdev *sd,
+			 struct v4l2_mbus_framefmt *mf)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct mt9t031 *mt9t031 = to_mt9t031(client);
+
+	mf->width	= mt9t031->rect.width / mt9t031->xskip;
+	mf->height	= mt9t031->rect.height / mt9t031->yskip;
+	mf->code	= V4L2_MBUS_FMT_SBGGR10_1X10;
+	mf->colorspace	= V4L2_COLORSPACE_SRGB;
+	mf->field	= V4L2_FIELD_NONE;
+
+	return 0;
+}
+
+static int mt9t031_s_fmt(struct v4l2_subdev *sd,
+			 struct v4l2_mbus_framefmt *mf)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct mt9t031 *mt9t031 = to_mt9t031(client);
+	u16 xskip, yskip;
+	struct v4l2_rect rect = mt9t031->rect;
+
+	/*
+	 * try_fmt has put width and height within limits.
+	 * S_FMT: use binning and skipping for scaling
+	 */
+	xskip = mt9t031_skip(&rect.width, mf->width, MT9T031_MAX_WIDTH);
+	yskip = mt9t031_skip(&rect.height, mf->height, MT9T031_MAX_HEIGHT);
+
+	mf->code	= V4L2_MBUS_FMT_SBGGR10_1X10;
+	mf->colorspace	= V4L2_COLORSPACE_SRGB;
+
+	/* mt9t031_set_params() doesn't change width and height */
+	return mt9t031_set_params(client, &rect, xskip, yskip);
+}
+
+/*
+ * If a user window larger than sensor window is requested, we'll increase the
+ * sensor window.
+ */
+static int mt9t031_try_fmt(struct v4l2_subdev *sd,
+			   struct v4l2_mbus_framefmt *mf)
+{
+	v4l_bound_align_image(
+		&mf->width, MT9T031_MIN_WIDTH, MT9T031_MAX_WIDTH, 1,
+		&mf->height, MT9T031_MIN_HEIGHT, MT9T031_MAX_HEIGHT, 1, 0);
+
+	mf->code	= V4L2_MBUS_FMT_SBGGR10_1X10;
+	mf->colorspace	= V4L2_COLORSPACE_SRGB;
+
+	return 0;
+}
+
+static int mt9t031_g_chip_ident(struct v4l2_subdev *sd,
+				struct v4l2_dbg_chip_ident *id)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct mt9t031 *mt9t031 = to_mt9t031(client);
+
+	if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
+		return -EINVAL;
+
+	if (id->match.addr != client->addr)
+		return -ENODEV;
+
+	id->ident	= mt9t031->model;
+	id->revision	= 0;
+
+	return 0;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int mt9t031_g_register(struct v4l2_subdev *sd,
+			      struct v4l2_dbg_register *reg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
+		return -EINVAL;
+
+	if (reg->match.addr != client->addr)
+		return -ENODEV;
+
+	reg->val = reg_read(client, reg->reg);
+
+	if (reg->val > 0xffff)
+		return -EIO;
+
+	return 0;
+}
+
+static int mt9t031_s_register(struct v4l2_subdev *sd,
+			      struct v4l2_dbg_register *reg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
+		return -EINVAL;
+
+	if (reg->match.addr != client->addr)
+		return -ENODEV;
+
+	if (reg_write(client, reg->reg, reg->val) < 0)
+		return -EIO;
+
+	return 0;
+}
+#endif
+
+static int mt9t031_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct mt9t031 *mt9t031 = container_of(ctrl->handler,
+					       struct mt9t031, hdl);
+	const u32 shutter_max = MT9T031_MAX_HEIGHT + MT9T031_VERTICAL_BLANK;
+	s32 min, max;
+
+	switch (ctrl->id) {
+	case V4L2_CID_EXPOSURE_AUTO:
+		min = mt9t031->exposure->minimum;
+		max = mt9t031->exposure->maximum;
+		mt9t031->exposure->val =
+			(shutter_max / 2 + (mt9t031->total_h - 1) * (max - min))
+				/ shutter_max + min;
+		break;
+	}
+	return 0;
+}
+
+static int mt9t031_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct mt9t031 *mt9t031 = container_of(ctrl->handler,
+					       struct mt9t031, hdl);
+	struct v4l2_subdev *sd = &mt9t031->subdev;
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct v4l2_ctrl *exp = mt9t031->exposure;
+	int data;
+
+	switch (ctrl->id) {
+	case V4L2_CID_VFLIP:
+		if (ctrl->val)
+			data = reg_set(client, MT9T031_READ_MODE_2, 0x8000);
+		else
+			data = reg_clear(client, MT9T031_READ_MODE_2, 0x8000);
+		if (data < 0)
+			return -EIO;
+		return 0;
+	case V4L2_CID_HFLIP:
+		if (ctrl->val)
+			data = reg_set(client, MT9T031_READ_MODE_2, 0x4000);
+		else
+			data = reg_clear(client, MT9T031_READ_MODE_2, 0x4000);
+		if (data < 0)
+			return -EIO;
+		return 0;
+	case V4L2_CID_GAIN:
+		/* See Datasheet Table 7, Gain settings. */
+		if (ctrl->val <= ctrl->default_value) {
+			/* Pack it into 0..1 step 0.125, register values 0..8 */
+			unsigned long range = ctrl->default_value - ctrl->minimum;
+			data = ((ctrl->val - ctrl->minimum) * 8 + range / 2) / range;
+
+			dev_dbg(&client->dev, "Setting gain %d\n", data);
+			data = reg_write(client, MT9T031_GLOBAL_GAIN, data);
+			if (data < 0)
+				return -EIO;
+		} else {
+			/* Pack it into 1.125..128 variable step, register values 9..0x7860 */
+			/* We assume qctrl->maximum - qctrl->default_value - 1 > 0 */
+			unsigned long range = ctrl->maximum - ctrl->default_value - 1;
+			/* calculated gain: map 65..127 to 9..1024 step 0.125 */
+			unsigned long gain = ((ctrl->val - ctrl->default_value - 1) *
+					       1015 + range / 2) / range + 9;
+
+			if (gain <= 32)		/* calculated gain 9..32 -> 9..32 */
+				data = gain;
+			else if (gain <= 64)	/* calculated gain 33..64 -> 0x51..0x60 */
+				data = ((gain - 32) * 16 + 16) / 32 + 80;
+			else
+				/* calculated gain 65..1024 -> (1..120) << 8 + 0x60 */
+				data = (((gain - 64 + 7) * 32) & 0xff00) | 0x60;
+
+			dev_dbg(&client->dev, "Set gain from 0x%x to 0x%x\n",
+				reg_read(client, MT9T031_GLOBAL_GAIN), data);
+			data = reg_write(client, MT9T031_GLOBAL_GAIN, data);
+			if (data < 0)
+				return -EIO;
+		}
+		return 0;
+
+	case V4L2_CID_EXPOSURE_AUTO:
+		if (ctrl->val == V4L2_EXPOSURE_MANUAL) {
+			unsigned int range = exp->maximum - exp->minimum;
+			unsigned int shutter = ((exp->val - exp->minimum) * 1048 +
+						 range / 2) / range + 1;
+			u32 old;
+
+			get_shutter(client, &old);
+			dev_dbg(&client->dev, "Set shutter from %u to %u\n",
+				old, shutter);
+			if (set_shutter(client, shutter) < 0)
+				return -EIO;
+		} else {
+			const u16 vblank = MT9T031_VERTICAL_BLANK;
+			mt9t031->total_h = mt9t031->rect.height +
+				mt9t031->y_skip_top + vblank;
+
+			if (set_shutter(client, mt9t031->total_h) < 0)
+				return -EIO;
+		}
+		return 0;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+/*
+ * Power Management:
+ * This function does nothing for now but must be present for pm to work
+ */
+static int mt9t031_runtime_suspend(struct device *dev)
+{
+	return 0;
+}
+
+/*
+ * Power Management:
+ * COLUMN_ADDRESS_MODE and ROW_ADDRESS_MODE are not rewritten if unchanged
+ * they are however changed at reset if the platform hook is present
+ * thus we rewrite them with the values stored by the driver
+ */
+static int mt9t031_runtime_resume(struct device *dev)
+{
+	struct video_device *vdev = to_video_device(dev);
+	struct v4l2_subdev *sd = soc_camera_vdev_to_subdev(vdev);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct mt9t031 *mt9t031 = to_mt9t031(client);
+
+	int ret;
+	u16 xbin, ybin;
+
+	xbin = min(mt9t031->xskip, (u16)3);
+	ybin = min(mt9t031->yskip, (u16)3);
+
+	ret = reg_write(client, MT9T031_COLUMN_ADDRESS_MODE,
+		((xbin - 1) << 4) | (mt9t031->xskip - 1));
+	if (ret < 0)
+		return ret;
+
+	ret = reg_write(client, MT9T031_ROW_ADDRESS_MODE,
+		((ybin - 1) << 4) | (mt9t031->yskip - 1));
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static struct dev_pm_ops mt9t031_dev_pm_ops = {
+	.runtime_suspend	= mt9t031_runtime_suspend,
+	.runtime_resume		= mt9t031_runtime_resume,
+};
+
+static struct device_type mt9t031_dev_type = {
+	.name	= "MT9T031",
+	.pm	= &mt9t031_dev_pm_ops,
+};
+
+static int mt9t031_s_power(struct v4l2_subdev *sd, int on)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+	struct video_device *vdev = soc_camera_i2c_to_vdev(client);
+	int ret;
+
+	if (on) {
+		ret = soc_camera_power_on(&client->dev, icl);
+		if (ret < 0)
+			return ret;
+		vdev->dev.type = &mt9t031_dev_type;
+	} else {
+		vdev->dev.type = NULL;
+		soc_camera_power_off(&client->dev, icl);
+	}
+
+	return 0;
+}
+
+/*
+ * Interface active, can use i2c. If it fails, it can indeed mean, that
+ * this wasn't our capture interface, so, we wait for the right one
+ */
+static int mt9t031_video_probe(struct i2c_client *client)
+{
+	struct mt9t031 *mt9t031 = to_mt9t031(client);
+	s32 data;
+	int ret;
+
+	ret = mt9t031_s_power(&mt9t031->subdev, 1);
+	if (ret < 0)
+		return ret;
+
+	ret = mt9t031_idle(client);
+	if (ret < 0) {
+		dev_err(&client->dev, "Failed to initialise the camera\n");
+		goto done;
+	}
+
+	/* Read out the chip version register */
+	data = reg_read(client, MT9T031_CHIP_VERSION);
+
+	switch (data) {
+	case 0x1621:
+		mt9t031->model = V4L2_IDENT_MT9T031;
+		break;
+	default:
+		dev_err(&client->dev,
+			"No MT9T031 chip detected, register read %x\n", data);
+		ret = -ENODEV;
+		goto done;
+	}
+
+	dev_info(&client->dev, "Detected a MT9T031 chip ID %x\n", data);
+
+	ret = v4l2_ctrl_handler_setup(&mt9t031->hdl);
+
+done:
+	mt9t031_s_power(&mt9t031->subdev, 0);
+
+	return ret;
+}
+
+static int mt9t031_g_skip_top_lines(struct v4l2_subdev *sd, u32 *lines)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct mt9t031 *mt9t031 = to_mt9t031(client);
+
+	*lines = mt9t031->y_skip_top;
+
+	return 0;
+}
+
+static const struct v4l2_ctrl_ops mt9t031_ctrl_ops = {
+	.g_volatile_ctrl = mt9t031_g_volatile_ctrl,
+	.s_ctrl = mt9t031_s_ctrl,
+};
+
+static struct v4l2_subdev_core_ops mt9t031_subdev_core_ops = {
+	.g_chip_ident	= mt9t031_g_chip_ident,
+	.s_power	= mt9t031_s_power,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.g_register	= mt9t031_g_register,
+	.s_register	= mt9t031_s_register,
+#endif
+};
+
+static int mt9t031_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
+			    enum v4l2_mbus_pixelcode *code)
+{
+	if (index)
+		return -EINVAL;
+
+	*code = V4L2_MBUS_FMT_SBGGR10_1X10;
+	return 0;
+}
+
+static int mt9t031_g_mbus_config(struct v4l2_subdev *sd,
+				struct v4l2_mbus_config *cfg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+	cfg->flags = V4L2_MBUS_MASTER | V4L2_MBUS_PCLK_SAMPLE_RISING |
+		V4L2_MBUS_PCLK_SAMPLE_FALLING | V4L2_MBUS_HSYNC_ACTIVE_HIGH |
+		V4L2_MBUS_VSYNC_ACTIVE_HIGH | V4L2_MBUS_DATA_ACTIVE_HIGH;
+	cfg->type = V4L2_MBUS_PARALLEL;
+	cfg->flags = soc_camera_apply_board_flags(icl, cfg);
+
+	return 0;
+}
+
+static int mt9t031_s_mbus_config(struct v4l2_subdev *sd,
+				const struct v4l2_mbus_config *cfg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+	if (soc_camera_apply_board_flags(icl, cfg) &
+	    V4L2_MBUS_PCLK_SAMPLE_FALLING)
+		return reg_clear(client, MT9T031_PIXEL_CLOCK_CONTROL, 0x8000);
+	else
+		return reg_set(client, MT9T031_PIXEL_CLOCK_CONTROL, 0x8000);
+}
+
+static struct v4l2_subdev_video_ops mt9t031_subdev_video_ops = {
+	.s_stream	= mt9t031_s_stream,
+	.s_mbus_fmt	= mt9t031_s_fmt,
+	.g_mbus_fmt	= mt9t031_g_fmt,
+	.try_mbus_fmt	= mt9t031_try_fmt,
+	.s_crop		= mt9t031_s_crop,
+	.g_crop		= mt9t031_g_crop,
+	.cropcap	= mt9t031_cropcap,
+	.enum_mbus_fmt	= mt9t031_enum_fmt,
+	.g_mbus_config	= mt9t031_g_mbus_config,
+	.s_mbus_config	= mt9t031_s_mbus_config,
+};
+
+static struct v4l2_subdev_sensor_ops mt9t031_subdev_sensor_ops = {
+	.g_skip_top_lines	= mt9t031_g_skip_top_lines,
+};
+
+static struct v4l2_subdev_ops mt9t031_subdev_ops = {
+	.core	= &mt9t031_subdev_core_ops,
+	.video	= &mt9t031_subdev_video_ops,
+	.sensor	= &mt9t031_subdev_sensor_ops,
+};
+
+static int mt9t031_probe(struct i2c_client *client,
+			 const struct i2c_device_id *did)
+{
+	struct mt9t031 *mt9t031;
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+	int ret;
+
+	if (!icl) {
+		dev_err(&client->dev, "MT9T031 driver needs platform data\n");
+		return -EINVAL;
+	}
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) {
+		dev_warn(&adapter->dev,
+			 "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n");
+		return -EIO;
+	}
+
+	mt9t031 = kzalloc(sizeof(struct mt9t031), GFP_KERNEL);
+	if (!mt9t031)
+		return -ENOMEM;
+
+	v4l2_i2c_subdev_init(&mt9t031->subdev, client, &mt9t031_subdev_ops);
+	v4l2_ctrl_handler_init(&mt9t031->hdl, 5);
+	v4l2_ctrl_new_std(&mt9t031->hdl, &mt9t031_ctrl_ops,
+			V4L2_CID_VFLIP, 0, 1, 1, 0);
+	v4l2_ctrl_new_std(&mt9t031->hdl, &mt9t031_ctrl_ops,
+			V4L2_CID_HFLIP, 0, 1, 1, 0);
+	v4l2_ctrl_new_std(&mt9t031->hdl, &mt9t031_ctrl_ops,
+			V4L2_CID_GAIN, 0, 127, 1, 64);
+
+	/*
+	 * Simulated autoexposure. If enabled, we calculate shutter width
+	 * ourselves in the driver based on vertical blanking and frame width
+	 */
+	mt9t031->autoexposure = v4l2_ctrl_new_std_menu(&mt9t031->hdl,
+			&mt9t031_ctrl_ops, V4L2_CID_EXPOSURE_AUTO, 1, 0,
+			V4L2_EXPOSURE_AUTO);
+	mt9t031->exposure = v4l2_ctrl_new_std(&mt9t031->hdl, &mt9t031_ctrl_ops,
+			V4L2_CID_EXPOSURE, 1, 255, 1, 255);
+
+	mt9t031->subdev.ctrl_handler = &mt9t031->hdl;
+	if (mt9t031->hdl.error) {
+		int err = mt9t031->hdl.error;
+
+		kfree(mt9t031);
+		return err;
+	}
+	v4l2_ctrl_auto_cluster(2, &mt9t031->autoexposure,
+				V4L2_EXPOSURE_MANUAL, true);
+
+	mt9t031->y_skip_top	= 0;
+	mt9t031->rect.left	= MT9T031_COLUMN_SKIP;
+	mt9t031->rect.top	= MT9T031_ROW_SKIP;
+	mt9t031->rect.width	= MT9T031_MAX_WIDTH;
+	mt9t031->rect.height	= MT9T031_MAX_HEIGHT;
+
+	mt9t031->xskip = 1;
+	mt9t031->yskip = 1;
+
+	ret = mt9t031_video_probe(client);
+	if (ret) {
+		v4l2_ctrl_handler_free(&mt9t031->hdl);
+		kfree(mt9t031);
+	}
+
+	return ret;
+}
+
+static int mt9t031_remove(struct i2c_client *client)
+{
+	struct mt9t031 *mt9t031 = to_mt9t031(client);
+
+	v4l2_device_unregister_subdev(&mt9t031->subdev);
+	v4l2_ctrl_handler_free(&mt9t031->hdl);
+	kfree(mt9t031);
+
+	return 0;
+}
+
+static const struct i2c_device_id mt9t031_id[] = {
+	{ "mt9t031", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, mt9t031_id);
+
+static struct i2c_driver mt9t031_i2c_driver = {
+	.driver = {
+		.name = "mt9t031",
+	},
+	.probe		= mt9t031_probe,
+	.remove		= mt9t031_remove,
+	.id_table	= mt9t031_id,
+};
+
+module_i2c_driver(mt9t031_i2c_driver);
+
+MODULE_DESCRIPTION("Micron MT9T031 Camera driver");
+MODULE_AUTHOR("Guennadi Liakhovetski <lg@denx.de>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/i2c/soc_camera/mt9t112.c b/drivers/media/i2c/soc_camera/mt9t112.c
new file mode 100644
index 0000000..9ba428e
--- /dev/null
+++ b/drivers/media/i2c/soc_camera/mt9t112.c
@@ -0,0 +1,1142 @@
+/*
+ * mt9t112 Camera Driver
+ *
+ * Copyright (C) 2009 Renesas Solutions Corp.
+ * Kuninori Morimoto <morimoto.kuninori@renesas.com>
+ *
+ * Based on ov772x driver, mt9m111 driver,
+ *
+ * Copyright (C) 2008 Kuninori Morimoto <morimoto.kuninori@renesas.com>
+ * Copyright (C) 2008, Robert Jarzmik <robert.jarzmik@free.fr>
+ * Copyright 2006-7 Jonathan Corbet <corbet@lwn.net>
+ * Copyright (C) 2008 Magnus Damm
+ * Copyright (C) 2008, Guennadi Liakhovetski <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 version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/v4l2-mediabus.h>
+#include <linux/videodev2.h>
+
+#include <media/mt9t112.h>
+#include <media/soc_camera.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-common.h>
+
+/* you can check PLL/clock info */
+/* #define EXT_CLOCK 24000000 */
+
+/************************************************************************
+			macro
+************************************************************************/
+/*
+ * frame size
+ */
+#define MAX_WIDTH   2048
+#define MAX_HEIGHT  1536
+
+#define VGA_WIDTH   640
+#define VGA_HEIGHT  480
+
+/*
+ * macro of read/write
+ */
+#define ECHECKER(ret, x)		\
+	do {				\
+		(ret) = (x);		\
+		if ((ret) < 0)		\
+			return (ret);	\
+	} while (0)
+
+#define mt9t112_reg_write(ret, client, a, b) \
+	ECHECKER(ret, __mt9t112_reg_write(client, a, b))
+#define mt9t112_mcu_write(ret, client, a, b) \
+	ECHECKER(ret, __mt9t112_mcu_write(client, a, b))
+
+#define mt9t112_reg_mask_set(ret, client, a, b, c) \
+	ECHECKER(ret, __mt9t112_reg_mask_set(client, a, b, c))
+#define mt9t112_mcu_mask_set(ret, client, a, b, c) \
+	ECHECKER(ret, __mt9t112_mcu_mask_set(client, a, b, c))
+
+#define mt9t112_reg_read(ret, client, a) \
+	ECHECKER(ret, __mt9t112_reg_read(client, a))
+
+/*
+ * Logical address
+ */
+#define _VAR(id, offset, base)	(base | (id & 0x1f) << 10 | (offset & 0x3ff))
+#define VAR(id, offset)  _VAR(id, offset, 0x0000)
+#define VAR8(id, offset) _VAR(id, offset, 0x8000)
+
+/************************************************************************
+			struct
+************************************************************************/
+struct mt9t112_format {
+	enum v4l2_mbus_pixelcode code;
+	enum v4l2_colorspace colorspace;
+	u16 fmt;
+	u16 order;
+};
+
+struct mt9t112_priv {
+	struct v4l2_subdev		 subdev;
+	struct mt9t112_camera_info	*info;
+	struct i2c_client		*client;
+	struct v4l2_rect		 frame;
+	const struct mt9t112_format	*format;
+	int				 model;
+	u32				 flags;
+/* for flags */
+#define INIT_DONE	(1 << 0)
+#define PCLK_RISING	(1 << 1)
+};
+
+/************************************************************************
+			supported format
+************************************************************************/
+
+static const struct mt9t112_format mt9t112_cfmts[] = {
+	{
+		.code		= V4L2_MBUS_FMT_UYVY8_2X8,
+		.colorspace	= V4L2_COLORSPACE_JPEG,
+		.fmt		= 1,
+		.order		= 0,
+	}, {
+		.code		= V4L2_MBUS_FMT_VYUY8_2X8,
+		.colorspace	= V4L2_COLORSPACE_JPEG,
+		.fmt		= 1,
+		.order		= 1,
+	}, {
+		.code		= V4L2_MBUS_FMT_YUYV8_2X8,
+		.colorspace	= V4L2_COLORSPACE_JPEG,
+		.fmt		= 1,
+		.order		= 2,
+	}, {
+		.code		= V4L2_MBUS_FMT_YVYU8_2X8,
+		.colorspace	= V4L2_COLORSPACE_JPEG,
+		.fmt		= 1,
+		.order		= 3,
+	}, {
+		.code		= V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE,
+		.colorspace	= V4L2_COLORSPACE_SRGB,
+		.fmt		= 8,
+		.order		= 2,
+	}, {
+		.code		= V4L2_MBUS_FMT_RGB565_2X8_LE,
+		.colorspace	= V4L2_COLORSPACE_SRGB,
+		.fmt		= 4,
+		.order		= 2,
+	},
+};
+
+/************************************************************************
+			general function
+************************************************************************/
+static struct mt9t112_priv *to_mt9t112(const struct i2c_client *client)
+{
+	return container_of(i2c_get_clientdata(client),
+			    struct mt9t112_priv,
+			    subdev);
+}
+
+static int __mt9t112_reg_read(const struct i2c_client *client, u16 command)
+{
+	struct i2c_msg msg[2];
+	u8 buf[2];
+	int ret;
+
+	command = swab16(command);
+
+	msg[0].addr  = client->addr;
+	msg[0].flags = 0;
+	msg[0].len   = 2;
+	msg[0].buf   = (u8 *)&command;
+
+	msg[1].addr  = client->addr;
+	msg[1].flags = I2C_M_RD;
+	msg[1].len   = 2;
+	msg[1].buf   = buf;
+
+	/*
+	 * if return value of this function is < 0,
+	 * it mean error.
+	 * else, under 16bit is valid data.
+	 */
+	ret = i2c_transfer(client->adapter, msg, 2);
+	if (ret < 0)
+		return ret;
+
+	memcpy(&ret, buf, 2);
+	return swab16(ret);
+}
+
+static int __mt9t112_reg_write(const struct i2c_client *client,
+			       u16 command, u16 data)
+{
+	struct i2c_msg msg;
+	u8 buf[4];
+	int ret;
+
+	command = swab16(command);
+	data = swab16(data);
+
+	memcpy(buf + 0, &command, 2);
+	memcpy(buf + 2, &data,    2);
+
+	msg.addr  = client->addr;
+	msg.flags = 0;
+	msg.len   = 4;
+	msg.buf   = buf;
+
+	/*
+	 * i2c_transfer return message length,
+	 * but this function should return 0 if correct case
+	 */
+	ret = i2c_transfer(client->adapter, &msg, 1);
+	if (ret >= 0)
+		ret = 0;
+
+	return ret;
+}
+
+static int __mt9t112_reg_mask_set(const struct i2c_client *client,
+				  u16  command,
+				  u16  mask,
+				  u16  set)
+{
+	int val = __mt9t112_reg_read(client, command);
+	if (val < 0)
+		return val;
+
+	val &= ~mask;
+	val |= set & mask;
+
+	return __mt9t112_reg_write(client, command, val);
+}
+
+/* mcu access */
+static int __mt9t112_mcu_read(const struct i2c_client *client, u16 command)
+{
+	int ret;
+
+	ret = __mt9t112_reg_write(client, 0x098E, command);
+	if (ret < 0)
+		return ret;
+
+	return __mt9t112_reg_read(client, 0x0990);
+}
+
+static int __mt9t112_mcu_write(const struct i2c_client *client,
+			       u16 command, u16 data)
+{
+	int ret;
+
+	ret = __mt9t112_reg_write(client, 0x098E, command);
+	if (ret < 0)
+		return ret;
+
+	return __mt9t112_reg_write(client, 0x0990, data);
+}
+
+static int __mt9t112_mcu_mask_set(const struct i2c_client *client,
+				  u16  command,
+				  u16  mask,
+				  u16  set)
+{
+	int val = __mt9t112_mcu_read(client, command);
+	if (val < 0)
+		return val;
+
+	val &= ~mask;
+	val |= set & mask;
+
+	return __mt9t112_mcu_write(client, command, val);
+}
+
+static int mt9t112_reset(const struct i2c_client *client)
+{
+	int ret;
+
+	mt9t112_reg_mask_set(ret, client, 0x001a, 0x0001, 0x0001);
+	msleep(1);
+	mt9t112_reg_mask_set(ret, client, 0x001a, 0x0001, 0x0000);
+
+	return ret;
+}
+
+#ifndef EXT_CLOCK
+#define CLOCK_INFO(a, b)
+#else
+#define CLOCK_INFO(a, b) mt9t112_clock_info(a, b)
+static int mt9t112_clock_info(const struct i2c_client *client, u32 ext)
+{
+	int m, n, p1, p2, p3, p4, p5, p6, p7;
+	u32 vco, clk;
+	char *enable;
+
+	ext /= 1000; /* kbyte order */
+
+	mt9t112_reg_read(n, client, 0x0012);
+	p1 = n & 0x000f;
+	n = n >> 4;
+	p2 = n & 0x000f;
+	n = n >> 4;
+	p3 = n & 0x000f;
+
+	mt9t112_reg_read(n, client, 0x002a);
+	p4 = n & 0x000f;
+	n = n >> 4;
+	p5 = n & 0x000f;
+	n = n >> 4;
+	p6 = n & 0x000f;
+
+	mt9t112_reg_read(n, client, 0x002c);
+	p7 = n & 0x000f;
+
+	mt9t112_reg_read(n, client, 0x0010);
+	m = n & 0x00ff;
+	n = (n >> 8) & 0x003f;
+
+	enable = ((6000 > ext) || (54000 < ext)) ? "X" : "";
+	dev_dbg(&client->dev, "EXTCLK          : %10u K %s\n", ext, enable);
+
+	vco = 2 * m * ext / (n+1);
+	enable = ((384000 > vco) || (768000 < vco)) ? "X" : "";
+	dev_dbg(&client->dev, "VCO             : %10u K %s\n", vco, enable);
+
+	clk = vco / (p1+1) / (p2+1);
+	enable = (96000 < clk) ? "X" : "";
+	dev_dbg(&client->dev, "PIXCLK          : %10u K %s\n", clk, enable);
+
+	clk = vco / (p3+1);
+	enable = (768000 < clk) ? "X" : "";
+	dev_dbg(&client->dev, "MIPICLK         : %10u K %s\n", clk, enable);
+
+	clk = vco / (p6+1);
+	enable = (96000 < clk) ? "X" : "";
+	dev_dbg(&client->dev, "MCU CLK         : %10u K %s\n", clk, enable);
+
+	clk = vco / (p5+1);
+	enable = (54000 < clk) ? "X" : "";
+	dev_dbg(&client->dev, "SOC CLK         : %10u K %s\n", clk, enable);
+
+	clk = vco / (p4+1);
+	enable = (70000 < clk) ? "X" : "";
+	dev_dbg(&client->dev, "Sensor CLK      : %10u K %s\n", clk, enable);
+
+	clk = vco / (p7+1);
+	dev_dbg(&client->dev, "External sensor : %10u K\n", clk);
+
+	clk = ext / (n+1);
+	enable = ((2000 > clk) || (24000 < clk)) ? "X" : "";
+	dev_dbg(&client->dev, "PFD             : %10u K %s\n", clk, enable);
+
+	return 0;
+}
+#endif
+
+static void mt9t112_frame_check(u32 *width, u32 *height, u32 *left, u32 *top)
+{
+	soc_camera_limit_side(left, width, 0, 0, MAX_WIDTH);
+	soc_camera_limit_side(top, height, 0, 0, MAX_HEIGHT);
+}
+
+static int mt9t112_set_a_frame_size(const struct i2c_client *client,
+				   u16 width,
+				   u16 height)
+{
+	int ret;
+	u16 wstart = (MAX_WIDTH - width) / 2;
+	u16 hstart = (MAX_HEIGHT - height) / 2;
+
+	/* (Context A) Image Width/Height */
+	mt9t112_mcu_write(ret, client, VAR(26, 0), width);
+	mt9t112_mcu_write(ret, client, VAR(26, 2), height);
+
+	/* (Context A) Output Width/Height */
+	mt9t112_mcu_write(ret, client, VAR(18, 43), 8 + width);
+	mt9t112_mcu_write(ret, client, VAR(18, 45), 8 + height);
+
+	/* (Context A) Start Row/Column */
+	mt9t112_mcu_write(ret, client, VAR(18, 2), 4 + hstart);
+	mt9t112_mcu_write(ret, client, VAR(18, 4), 4 + wstart);
+
+	/* (Context A) End Row/Column */
+	mt9t112_mcu_write(ret, client, VAR(18, 6), 11 + height + hstart);
+	mt9t112_mcu_write(ret, client, VAR(18, 8), 11 + width  + wstart);
+
+	mt9t112_mcu_write(ret, client, VAR8(1, 0), 0x06);
+
+	return ret;
+}
+
+static int mt9t112_set_pll_dividers(const struct i2c_client *client,
+				    u8 m, u8 n,
+				    u8 p1, u8 p2, u8 p3,
+				    u8 p4, u8 p5, u8 p6,
+				    u8 p7)
+{
+	int ret;
+	u16 val;
+
+	/* N/M */
+	val = (n << 8) |
+	      (m << 0);
+	mt9t112_reg_mask_set(ret, client, 0x0010, 0x3fff, val);
+
+	/* P1/P2/P3 */
+	val = ((p3 & 0x0F) << 8) |
+	      ((p2 & 0x0F) << 4) |
+	      ((p1 & 0x0F) << 0);
+	mt9t112_reg_mask_set(ret, client, 0x0012, 0x0fff, val);
+
+	/* P4/P5/P6 */
+	val = (0x7         << 12) |
+	      ((p6 & 0x0F) <<  8) |
+	      ((p5 & 0x0F) <<  4) |
+	      ((p4 & 0x0F) <<  0);
+	mt9t112_reg_mask_set(ret, client, 0x002A, 0x7fff, val);
+
+	/* P7 */
+	val = (0x1         << 12) |
+	      ((p7 & 0x0F) <<  0);
+	mt9t112_reg_mask_set(ret, client, 0x002C, 0x100f, val);
+
+	return ret;
+}
+
+static int mt9t112_init_pll(const struct i2c_client *client)
+{
+	struct mt9t112_priv *priv = to_mt9t112(client);
+	int data, i, ret;
+
+	mt9t112_reg_mask_set(ret, client, 0x0014, 0x003, 0x0001);
+
+	/* PLL control: BYPASS PLL = 8517 */
+	mt9t112_reg_write(ret, client, 0x0014, 0x2145);
+
+	/* Replace these registers when new timing parameters are generated */
+	mt9t112_set_pll_dividers(client,
+				 priv->info->divider.m,
+				 priv->info->divider.n,
+				 priv->info->divider.p1,
+				 priv->info->divider.p2,
+				 priv->info->divider.p3,
+				 priv->info->divider.p4,
+				 priv->info->divider.p5,
+				 priv->info->divider.p6,
+				 priv->info->divider.p7);
+
+	/*
+	 * TEST_BYPASS  on
+	 * PLL_ENABLE   on
+	 * SEL_LOCK_DET on
+	 * TEST_BYPASS  off
+	 */
+	mt9t112_reg_write(ret, client, 0x0014, 0x2525);
+	mt9t112_reg_write(ret, client, 0x0014, 0x2527);
+	mt9t112_reg_write(ret, client, 0x0014, 0x3427);
+	mt9t112_reg_write(ret, client, 0x0014, 0x3027);
+
+	mdelay(10);
+
+	/*
+	 * PLL_BYPASS off
+	 * Reference clock count
+	 * I2C Master Clock Divider
+	 */
+	mt9t112_reg_write(ret, client, 0x0014, 0x3046);
+	mt9t112_reg_write(ret, client, 0x0016, 0x0400); /* JPEG initialization workaround */
+	mt9t112_reg_write(ret, client, 0x0022, 0x0190);
+	mt9t112_reg_write(ret, client, 0x3B84, 0x0212);
+
+	/* External sensor clock is PLL bypass */
+	mt9t112_reg_write(ret, client, 0x002E, 0x0500);
+
+	mt9t112_reg_mask_set(ret, client, 0x0018, 0x0002, 0x0002);
+	mt9t112_reg_mask_set(ret, client, 0x3B82, 0x0004, 0x0004);
+
+	/* MCU disabled */
+	mt9t112_reg_mask_set(ret, client, 0x0018, 0x0004, 0x0004);
+
+	/* out of standby */
+	mt9t112_reg_mask_set(ret, client, 0x0018, 0x0001, 0);
+
+	mdelay(50);
+
+	/*
+	 * Standby Workaround
+	 * Disable Secondary I2C Pads
+	 */
+	mt9t112_reg_write(ret, client, 0x0614, 0x0001);
+	mdelay(1);
+	mt9t112_reg_write(ret, client, 0x0614, 0x0001);
+	mdelay(1);
+	mt9t112_reg_write(ret, client, 0x0614, 0x0001);
+	mdelay(1);
+	mt9t112_reg_write(ret, client, 0x0614, 0x0001);
+	mdelay(1);
+	mt9t112_reg_write(ret, client, 0x0614, 0x0001);
+	mdelay(1);
+	mt9t112_reg_write(ret, client, 0x0614, 0x0001);
+	mdelay(1);
+
+	/* poll to verify out of standby. Must Poll this bit */
+	for (i = 0; i < 100; i++) {
+		mt9t112_reg_read(data, client, 0x0018);
+		if (!(0x4000 & data))
+			break;
+
+		mdelay(10);
+	}
+
+	return ret;
+}
+
+static int mt9t112_init_setting(const struct i2c_client *client)
+{
+
+	int ret;
+
+	/* Adaptive Output Clock (A) */
+	mt9t112_mcu_mask_set(ret, client, VAR(26, 160), 0x0040, 0x0000);
+
+	/* Read Mode (A) */
+	mt9t112_mcu_write(ret, client, VAR(18, 12), 0x0024);
+
+	/* Fine Correction (A) */
+	mt9t112_mcu_write(ret, client, VAR(18, 15), 0x00CC);
+
+	/* Fine IT Min (A) */
+	mt9t112_mcu_write(ret, client, VAR(18, 17), 0x01f1);
+
+	/* Fine IT Max Margin (A) */
+	mt9t112_mcu_write(ret, client, VAR(18, 19), 0x00fF);
+
+	/* Base Frame Lines (A) */
+	mt9t112_mcu_write(ret, client, VAR(18, 29), 0x032D);
+
+	/* Min Line Length (A) */
+	mt9t112_mcu_write(ret, client, VAR(18, 31), 0x073a);
+
+	/* Line Length (A) */
+	mt9t112_mcu_write(ret, client, VAR(18, 37), 0x07d0);
+
+	/* Adaptive Output Clock (B) */
+	mt9t112_mcu_mask_set(ret, client, VAR(27, 160), 0x0040, 0x0000);
+
+	/* Row Start (B) */
+	mt9t112_mcu_write(ret, client, VAR(18, 74), 0x004);
+
+	/* Column Start (B) */
+	mt9t112_mcu_write(ret, client, VAR(18, 76), 0x004);
+
+	/* Row End (B) */
+	mt9t112_mcu_write(ret, client, VAR(18, 78), 0x60B);
+
+	/* Column End (B) */
+	mt9t112_mcu_write(ret, client, VAR(18, 80), 0x80B);
+
+	/* Fine Correction (B) */
+	mt9t112_mcu_write(ret, client, VAR(18, 87), 0x008C);
+
+	/* Fine IT Min (B) */
+	mt9t112_mcu_write(ret, client, VAR(18, 89), 0x01F1);
+
+	/* Fine IT Max Margin (B) */
+	mt9t112_mcu_write(ret, client, VAR(18, 91), 0x00FF);
+
+	/* Base Frame Lines (B) */
+	mt9t112_mcu_write(ret, client, VAR(18, 101), 0x0668);
+
+	/* Min Line Length (B) */
+	mt9t112_mcu_write(ret, client, VAR(18, 103), 0x0AF0);
+
+	/* Line Length (B) */
+	mt9t112_mcu_write(ret, client, VAR(18, 109), 0x0AF0);
+
+	/*
+	 * Flicker Dectection registers
+	 * This section should be replaced whenever new Timing file is generated
+	 * All the following registers need to be replaced
+	 * Following registers are generated from Register Wizard but user can
+	 * modify them. For detail see auto flicker detection tuning
+	 */
+
+	/* FD_FDPERIOD_SELECT */
+	mt9t112_mcu_write(ret, client, VAR8(8, 5), 0x01);
+
+	/* PRI_B_CONFIG_FD_ALGO_RUN */
+	mt9t112_mcu_write(ret, client, VAR(27, 17), 0x0003);
+
+	/* PRI_A_CONFIG_FD_ALGO_RUN */
+	mt9t112_mcu_write(ret, client, VAR(26, 17), 0x0003);
+
+	/*
+	 * AFD range detection tuning registers
+	 */
+
+	/* search_f1_50 */
+	mt9t112_mcu_write(ret, client, VAR8(18, 165), 0x25);
+
+	/* search_f2_50 */
+	mt9t112_mcu_write(ret, client, VAR8(18, 166), 0x28);
+
+	/* search_f1_60 */
+	mt9t112_mcu_write(ret, client, VAR8(18, 167), 0x2C);
+
+	/* search_f2_60 */
+	mt9t112_mcu_write(ret, client, VAR8(18, 168), 0x2F);
+
+	/* period_50Hz (A) */
+	mt9t112_mcu_write(ret, client, VAR8(18, 68), 0xBA);
+
+	/* secret register by aptina */
+	/* period_50Hz (A MSB) */
+	mt9t112_mcu_write(ret, client, VAR8(18, 303), 0x00);
+
+	/* period_60Hz (A) */
+	mt9t112_mcu_write(ret, client, VAR8(18, 69), 0x9B);
+
+	/* secret register by aptina */
+	/* period_60Hz (A MSB) */
+	mt9t112_mcu_write(ret, client, VAR8(18, 301), 0x00);
+
+	/* period_50Hz (B) */
+	mt9t112_mcu_write(ret, client, VAR8(18, 140), 0x82);
+
+	/* secret register by aptina */
+	/* period_50Hz (B) MSB */
+	mt9t112_mcu_write(ret, client, VAR8(18, 304), 0x00);
+
+	/* period_60Hz (B) */
+	mt9t112_mcu_write(ret, client, VAR8(18, 141), 0x6D);
+
+	/* secret register by aptina */
+	/* period_60Hz (B) MSB */
+	mt9t112_mcu_write(ret, client, VAR8(18, 302), 0x00);
+
+	/* FD Mode */
+	mt9t112_mcu_write(ret, client, VAR8(8, 2), 0x10);
+
+	/* Stat_min */
+	mt9t112_mcu_write(ret, client, VAR8(8, 9), 0x02);
+
+	/* Stat_max */
+	mt9t112_mcu_write(ret, client, VAR8(8, 10), 0x03);
+
+	/* Min_amplitude */
+	mt9t112_mcu_write(ret, client, VAR8(8, 12), 0x0A);
+
+	/* RX FIFO Watermark (A) */
+	mt9t112_mcu_write(ret, client, VAR(18, 70), 0x0014);
+
+	/* RX FIFO Watermark (B) */
+	mt9t112_mcu_write(ret, client, VAR(18, 142), 0x0014);
+
+	/* MCLK: 16MHz
+	 * PCLK: 73MHz
+	 * CorePixCLK: 36.5 MHz
+	 */
+	mt9t112_mcu_write(ret, client, VAR8(18, 0x0044), 133);
+	mt9t112_mcu_write(ret, client, VAR8(18, 0x0045), 110);
+	mt9t112_mcu_write(ret, client, VAR8(18, 0x008c), 130);
+	mt9t112_mcu_write(ret, client, VAR8(18, 0x008d), 108);
+
+	mt9t112_mcu_write(ret, client, VAR8(18, 0x00A5), 27);
+	mt9t112_mcu_write(ret, client, VAR8(18, 0x00a6), 30);
+	mt9t112_mcu_write(ret, client, VAR8(18, 0x00a7), 32);
+	mt9t112_mcu_write(ret, client, VAR8(18, 0x00a8), 35);
+
+	return ret;
+}
+
+static int mt9t112_auto_focus_setting(const struct i2c_client *client)
+{
+	int ret;
+
+	mt9t112_mcu_write(ret, client, VAR(12, 13),	0x000F);
+	mt9t112_mcu_write(ret, client, VAR(12, 23),	0x0F0F);
+	mt9t112_mcu_write(ret, client, VAR8(1, 0),	0x06);
+
+	mt9t112_reg_write(ret, client, 0x0614, 0x0000);
+
+	mt9t112_mcu_write(ret, client, VAR8(1, 0),	0x05);
+	mt9t112_mcu_write(ret, client, VAR8(12, 2),	0x02);
+	mt9t112_mcu_write(ret, client, VAR(12, 3),	0x0002);
+	mt9t112_mcu_write(ret, client, VAR(17, 3),	0x8001);
+	mt9t112_mcu_write(ret, client, VAR(17, 11),	0x0025);
+	mt9t112_mcu_write(ret, client, VAR(17, 13),	0x0193);
+	mt9t112_mcu_write(ret, client, VAR8(17, 33),	0x18);
+	mt9t112_mcu_write(ret, client, VAR8(1, 0),	0x05);
+
+	return ret;
+}
+
+static int mt9t112_auto_focus_trigger(const struct i2c_client *client)
+{
+	int ret;
+
+	mt9t112_mcu_write(ret, client, VAR8(12, 25), 0x01);
+
+	return ret;
+}
+
+static int mt9t112_init_camera(const struct i2c_client *client)
+{
+	int ret;
+
+	ECHECKER(ret, mt9t112_reset(client));
+
+	ECHECKER(ret, mt9t112_init_pll(client));
+
+	ECHECKER(ret, mt9t112_init_setting(client));
+
+	ECHECKER(ret, mt9t112_auto_focus_setting(client));
+
+	mt9t112_reg_mask_set(ret, client, 0x0018, 0x0004, 0);
+
+	/* Analog setting B */
+	mt9t112_reg_write(ret, client, 0x3084, 0x2409);
+	mt9t112_reg_write(ret, client, 0x3092, 0x0A49);
+	mt9t112_reg_write(ret, client, 0x3094, 0x4949);
+	mt9t112_reg_write(ret, client, 0x3096, 0x4950);
+
+	/*
+	 * Disable adaptive clock
+	 * PRI_A_CONFIG_JPEG_OB_TX_CONTROL_VAR
+	 * PRI_B_CONFIG_JPEG_OB_TX_CONTROL_VAR
+	 */
+	mt9t112_mcu_write(ret, client, VAR(26, 160), 0x0A2E);
+	mt9t112_mcu_write(ret, client, VAR(27, 160), 0x0A2E);
+
+	/* Configure STatus in Status_before_length Format and enable header */
+	/* PRI_B_CONFIG_JPEG_OB_TX_CONTROL_VAR */
+	mt9t112_mcu_write(ret, client, VAR(27, 144), 0x0CB4);
+
+	/* Enable JPEG in context B */
+	/* PRI_B_CONFIG_JPEG_OB_TX_CONTROL_VAR */
+	mt9t112_mcu_write(ret, client, VAR8(27, 142), 0x01);
+
+	/* Disable Dac_TXLO */
+	mt9t112_reg_write(ret, client, 0x316C, 0x350F);
+
+	/* Set max slew rates */
+	mt9t112_reg_write(ret, client, 0x1E, 0x777);
+
+	return ret;
+}
+
+/************************************************************************
+			v4l2_subdev_core_ops
+************************************************************************/
+static int mt9t112_g_chip_ident(struct v4l2_subdev *sd,
+				struct v4l2_dbg_chip_ident *id)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct mt9t112_priv *priv = to_mt9t112(client);
+
+	id->ident    = priv->model;
+	id->revision = 0;
+
+	return 0;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int mt9t112_g_register(struct v4l2_subdev *sd,
+			      struct v4l2_dbg_register *reg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	int                ret;
+
+	reg->size = 2;
+	mt9t112_reg_read(ret, client, reg->reg);
+
+	reg->val = (__u64)ret;
+
+	return 0;
+}
+
+static int mt9t112_s_register(struct v4l2_subdev *sd,
+			      struct v4l2_dbg_register *reg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	int ret;
+
+	mt9t112_reg_write(ret, client, reg->reg, reg->val);
+
+	return ret;
+}
+#endif
+
+static int mt9t112_s_power(struct v4l2_subdev *sd, int on)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+	return soc_camera_set_power(&client->dev, icl, on);
+}
+
+static struct v4l2_subdev_core_ops mt9t112_subdev_core_ops = {
+	.g_chip_ident	= mt9t112_g_chip_ident,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.g_register	= mt9t112_g_register,
+	.s_register	= mt9t112_s_register,
+#endif
+	.s_power	= mt9t112_s_power,
+};
+
+
+/************************************************************************
+			v4l2_subdev_video_ops
+************************************************************************/
+static int mt9t112_s_stream(struct v4l2_subdev *sd, int enable)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct mt9t112_priv *priv = to_mt9t112(client);
+	int ret = 0;
+
+	if (!enable) {
+		/* FIXME
+		 *
+		 * If user selected large output size,
+		 * and used it long time,
+		 * mt9t112 camera will be very warm.
+		 *
+		 * But current driver can not stop mt9t112 camera.
+		 * So, set small size here to solve this problem.
+		 */
+		mt9t112_set_a_frame_size(client, VGA_WIDTH, VGA_HEIGHT);
+		return ret;
+	}
+
+	if (!(priv->flags & INIT_DONE)) {
+		u16 param = PCLK_RISING & priv->flags ? 0x0001 : 0x0000;
+
+		ECHECKER(ret, mt9t112_init_camera(client));
+
+		/* Invert PCLK (Data sampled on falling edge of pixclk) */
+		mt9t112_reg_write(ret, client, 0x3C20, param);
+
+		mdelay(5);
+
+		priv->flags |= INIT_DONE;
+	}
+
+	mt9t112_mcu_write(ret, client, VAR(26, 7), priv->format->fmt);
+	mt9t112_mcu_write(ret, client, VAR(26, 9), priv->format->order);
+	mt9t112_mcu_write(ret, client, VAR8(1, 0), 0x06);
+
+	mt9t112_set_a_frame_size(client,
+				 priv->frame.width,
+				 priv->frame.height);
+
+	ECHECKER(ret, mt9t112_auto_focus_trigger(client));
+
+	dev_dbg(&client->dev, "format : %d\n", priv->format->code);
+	dev_dbg(&client->dev, "size   : %d x %d\n",
+		priv->frame.width,
+		priv->frame.height);
+
+	CLOCK_INFO(client, EXT_CLOCK);
+
+	return ret;
+}
+
+static int mt9t112_set_params(struct mt9t112_priv *priv,
+			      const struct v4l2_rect *rect,
+			      enum v4l2_mbus_pixelcode code)
+{
+	int i;
+
+	/*
+	 * get color format
+	 */
+	for (i = 0; i < ARRAY_SIZE(mt9t112_cfmts); i++)
+		if (mt9t112_cfmts[i].code == code)
+			break;
+
+	if (i == ARRAY_SIZE(mt9t112_cfmts))
+		return -EINVAL;
+
+	priv->frame  = *rect;
+
+	/*
+	 * frame size check
+	 */
+	mt9t112_frame_check(&priv->frame.width, &priv->frame.height,
+			    &priv->frame.left, &priv->frame.top);
+
+	priv->format = mt9t112_cfmts + i;
+
+	return 0;
+}
+
+static int mt9t112_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
+{
+	a->bounds.left			= 0;
+	a->bounds.top			= 0;
+	a->bounds.width			= MAX_WIDTH;
+	a->bounds.height		= MAX_HEIGHT;
+	a->defrect.left			= 0;
+	a->defrect.top			= 0;
+	a->defrect.width		= VGA_WIDTH;
+	a->defrect.height		= VGA_HEIGHT;
+	a->type				= V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	a->pixelaspect.numerator	= 1;
+	a->pixelaspect.denominator	= 1;
+
+	return 0;
+}
+
+static int mt9t112_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct mt9t112_priv *priv = to_mt9t112(client);
+
+	a->c	= priv->frame;
+	a->type	= V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+	return 0;
+}
+
+static int mt9t112_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct mt9t112_priv *priv = to_mt9t112(client);
+	struct v4l2_rect *rect = &a->c;
+
+	return mt9t112_set_params(priv, rect, priv->format->code);
+}
+
+static int mt9t112_g_fmt(struct v4l2_subdev *sd,
+			 struct v4l2_mbus_framefmt *mf)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct mt9t112_priv *priv = to_mt9t112(client);
+
+	mf->width	= priv->frame.width;
+	mf->height	= priv->frame.height;
+	mf->colorspace	= priv->format->colorspace;
+	mf->code	= priv->format->code;
+	mf->field	= V4L2_FIELD_NONE;
+
+	return 0;
+}
+
+static int mt9t112_s_fmt(struct v4l2_subdev *sd,
+			 struct v4l2_mbus_framefmt *mf)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct mt9t112_priv *priv = to_mt9t112(client);
+	struct v4l2_rect rect = {
+		.width = mf->width,
+		.height = mf->height,
+		.left = priv->frame.left,
+		.top = priv->frame.top,
+	};
+	int ret;
+
+	ret = mt9t112_set_params(priv, &rect, mf->code);
+
+	if (!ret)
+		mf->colorspace = priv->format->colorspace;
+
+	return ret;
+}
+
+static int mt9t112_try_fmt(struct v4l2_subdev *sd,
+			   struct v4l2_mbus_framefmt *mf)
+{
+	unsigned int top, left;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(mt9t112_cfmts); i++)
+		if (mt9t112_cfmts[i].code == mf->code)
+			break;
+
+	if (i == ARRAY_SIZE(mt9t112_cfmts)) {
+		mf->code = V4L2_MBUS_FMT_UYVY8_2X8;
+		mf->colorspace = V4L2_COLORSPACE_JPEG;
+	} else {
+		mf->colorspace	= mt9t112_cfmts[i].colorspace;
+	}
+
+	mt9t112_frame_check(&mf->width, &mf->height, &left, &top);
+
+	mf->field = V4L2_FIELD_NONE;
+
+	return 0;
+}
+
+static int mt9t112_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
+			   enum v4l2_mbus_pixelcode *code)
+{
+	if (index >= ARRAY_SIZE(mt9t112_cfmts))
+		return -EINVAL;
+
+	*code = mt9t112_cfmts[index].code;
+
+	return 0;
+}
+
+static int mt9t112_g_mbus_config(struct v4l2_subdev *sd,
+				 struct v4l2_mbus_config *cfg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+	cfg->flags = V4L2_MBUS_MASTER | V4L2_MBUS_VSYNC_ACTIVE_HIGH |
+		V4L2_MBUS_HSYNC_ACTIVE_HIGH | V4L2_MBUS_DATA_ACTIVE_HIGH |
+		V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_PCLK_SAMPLE_FALLING;
+	cfg->type = V4L2_MBUS_PARALLEL;
+	cfg->flags = soc_camera_apply_board_flags(icl, cfg);
+
+	return 0;
+}
+
+static int mt9t112_s_mbus_config(struct v4l2_subdev *sd,
+				 const struct v4l2_mbus_config *cfg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+	struct mt9t112_priv *priv = to_mt9t112(client);
+
+	if (soc_camera_apply_board_flags(icl, cfg) & V4L2_MBUS_PCLK_SAMPLE_RISING)
+		priv->flags |= PCLK_RISING;
+
+	return 0;
+}
+
+static struct v4l2_subdev_video_ops mt9t112_subdev_video_ops = {
+	.s_stream	= mt9t112_s_stream,
+	.g_mbus_fmt	= mt9t112_g_fmt,
+	.s_mbus_fmt	= mt9t112_s_fmt,
+	.try_mbus_fmt	= mt9t112_try_fmt,
+	.cropcap	= mt9t112_cropcap,
+	.g_crop		= mt9t112_g_crop,
+	.s_crop		= mt9t112_s_crop,
+	.enum_mbus_fmt	= mt9t112_enum_fmt,
+	.g_mbus_config	= mt9t112_g_mbus_config,
+	.s_mbus_config	= mt9t112_s_mbus_config,
+};
+
+/************************************************************************
+			i2c driver
+************************************************************************/
+static struct v4l2_subdev_ops mt9t112_subdev_ops = {
+	.core	= &mt9t112_subdev_core_ops,
+	.video	= &mt9t112_subdev_video_ops,
+};
+
+static int mt9t112_camera_probe(struct i2c_client *client)
+{
+	struct mt9t112_priv *priv = to_mt9t112(client);
+	const char          *devname;
+	int                  chipid;
+	int		     ret;
+
+	ret = mt9t112_s_power(&priv->subdev, 1);
+	if (ret < 0)
+		return ret;
+
+	/*
+	 * check and show chip ID
+	 */
+	mt9t112_reg_read(chipid, client, 0x0000);
+
+	switch (chipid) {
+	case 0x2680:
+		devname = "mt9t111";
+		priv->model = V4L2_IDENT_MT9T111;
+		break;
+	case 0x2682:
+		devname = "mt9t112";
+		priv->model = V4L2_IDENT_MT9T112;
+		break;
+	default:
+		dev_err(&client->dev, "Product ID error %04x\n", chipid);
+		ret = -ENODEV;
+		goto done;
+	}
+
+	dev_info(&client->dev, "%s chip ID %04x\n", devname, chipid);
+
+done:
+	mt9t112_s_power(&priv->subdev, 0);
+	return ret;
+}
+
+static int mt9t112_probe(struct i2c_client *client,
+			 const struct i2c_device_id *did)
+{
+	struct mt9t112_priv *priv;
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+	struct v4l2_rect rect = {
+		.width = VGA_WIDTH,
+		.height = VGA_HEIGHT,
+		.left = (MAX_WIDTH - VGA_WIDTH) / 2,
+		.top = (MAX_HEIGHT - VGA_HEIGHT) / 2,
+	};
+	int ret;
+
+	if (!icl || !icl->priv) {
+		dev_err(&client->dev, "mt9t112: missing platform data!\n");
+		return -EINVAL;
+	}
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->info = icl->priv;
+
+	v4l2_i2c_subdev_init(&priv->subdev, client, &mt9t112_subdev_ops);
+
+	ret = mt9t112_camera_probe(client);
+	if (ret) {
+		kfree(priv);
+		return ret;
+	}
+
+	/* Cannot fail: using the default supported pixel code */
+	mt9t112_set_params(priv, &rect, V4L2_MBUS_FMT_UYVY8_2X8);
+
+	return ret;
+}
+
+static int mt9t112_remove(struct i2c_client *client)
+{
+	struct mt9t112_priv *priv = to_mt9t112(client);
+
+	kfree(priv);
+	return 0;
+}
+
+static const struct i2c_device_id mt9t112_id[] = {
+	{ "mt9t112", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, mt9t112_id);
+
+static struct i2c_driver mt9t112_i2c_driver = {
+	.driver = {
+		.name = "mt9t112",
+	},
+	.probe    = mt9t112_probe,
+	.remove   = mt9t112_remove,
+	.id_table = mt9t112_id,
+};
+
+module_i2c_driver(mt9t112_i2c_driver);
+
+MODULE_DESCRIPTION("SoC Camera driver for mt9t112");
+MODULE_AUTHOR("Kuninori Morimoto");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/i2c/soc_camera/mt9v022.c b/drivers/media/i2c/soc_camera/mt9v022.c
new file mode 100644
index 0000000..350d0d8
--- /dev/null
+++ b/drivers/media/i2c/soc_camera/mt9v022.c
@@ -0,0 +1,919 @@
+/*
+ * Driver for MT9V022 CMOS Image Sensor from Micron
+ *
+ * Copyright (C) 2008, Guennadi Liakhovetski <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 version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/videodev2.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/log2.h>
+#include <linux/module.h>
+
+#include <media/soc_camera.h>
+#include <media/soc_mediabus.h>
+#include <media/v4l2-subdev.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-ctrls.h>
+
+/*
+ * mt9v022 i2c address 0x48, 0x4c, 0x58, 0x5c
+ * The platform has to define struct i2c_board_info objects and link to them
+ * from struct soc_camera_link
+ */
+
+static char *sensor_type;
+module_param(sensor_type, charp, S_IRUGO);
+MODULE_PARM_DESC(sensor_type, "Sensor type: \"colour\" or \"monochrome\"");
+
+/* mt9v022 selected register addresses */
+#define MT9V022_CHIP_VERSION		0x00
+#define MT9V022_COLUMN_START		0x01
+#define MT9V022_ROW_START		0x02
+#define MT9V022_WINDOW_HEIGHT		0x03
+#define MT9V022_WINDOW_WIDTH		0x04
+#define MT9V022_HORIZONTAL_BLANKING	0x05
+#define MT9V022_VERTICAL_BLANKING	0x06
+#define MT9V022_CHIP_CONTROL		0x07
+#define MT9V022_SHUTTER_WIDTH1		0x08
+#define MT9V022_SHUTTER_WIDTH2		0x09
+#define MT9V022_SHUTTER_WIDTH_CTRL	0x0a
+#define MT9V022_TOTAL_SHUTTER_WIDTH	0x0b
+#define MT9V022_RESET			0x0c
+#define MT9V022_READ_MODE		0x0d
+#define MT9V022_MONITOR_MODE		0x0e
+#define MT9V022_PIXEL_OPERATION_MODE	0x0f
+#define MT9V022_LED_OUT_CONTROL		0x1b
+#define MT9V022_ADC_MODE_CONTROL	0x1c
+#define MT9V022_ANALOG_GAIN		0x35
+#define MT9V022_BLACK_LEVEL_CALIB_CTRL	0x47
+#define MT9V022_PIXCLK_FV_LV		0x74
+#define MT9V022_DIGITAL_TEST_PATTERN	0x7f
+#define MT9V022_AEC_AGC_ENABLE		0xAF
+#define MT9V022_MAX_TOTAL_SHUTTER_WIDTH	0xBD
+
+/* mt9v024 partial list register addresses changes with respect to mt9v022 */
+#define MT9V024_PIXCLK_FV_LV		0x72
+#define MT9V024_MAX_TOTAL_SHUTTER_WIDTH	0xAD
+
+/* Progressive scan, master, defaults */
+#define MT9V022_CHIP_CONTROL_DEFAULT	0x188
+
+#define MT9V022_MAX_WIDTH		752
+#define MT9V022_MAX_HEIGHT		480
+#define MT9V022_MIN_WIDTH		48
+#define MT9V022_MIN_HEIGHT		32
+#define MT9V022_COLUMN_SKIP		1
+#define MT9V022_ROW_SKIP		4
+
+#define is_mt9v024(id) (id == 0x1324)
+
+/* MT9V022 has only one fixed colorspace per pixelcode */
+struct mt9v022_datafmt {
+	enum v4l2_mbus_pixelcode	code;
+	enum v4l2_colorspace		colorspace;
+};
+
+/* Find a data format by a pixel code in an array */
+static const struct mt9v022_datafmt *mt9v022_find_datafmt(
+	enum v4l2_mbus_pixelcode code, const struct mt9v022_datafmt *fmt,
+	int n)
+{
+	int i;
+	for (i = 0; i < n; i++)
+		if (fmt[i].code == code)
+			return fmt + i;
+
+	return NULL;
+}
+
+static const struct mt9v022_datafmt mt9v022_colour_fmts[] = {
+	/*
+	 * Order important: first natively supported,
+	 * second supported with a GPIO extender
+	 */
+	{V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_COLORSPACE_SRGB},
+	{V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_COLORSPACE_SRGB},
+};
+
+static const struct mt9v022_datafmt mt9v022_monochrome_fmts[] = {
+	/* Order important - see above */
+	{V4L2_MBUS_FMT_Y10_1X10, V4L2_COLORSPACE_JPEG},
+	{V4L2_MBUS_FMT_Y8_1X8, V4L2_COLORSPACE_JPEG},
+};
+
+/* only registers with different addresses on different mt9v02x sensors */
+struct mt9v02x_register {
+	u8	max_total_shutter_width;
+	u8	pixclk_fv_lv;
+};
+
+static const struct mt9v02x_register mt9v022_register = {
+	.max_total_shutter_width	= MT9V022_MAX_TOTAL_SHUTTER_WIDTH,
+	.pixclk_fv_lv			= MT9V022_PIXCLK_FV_LV,
+};
+
+static const struct mt9v02x_register mt9v024_register = {
+	.max_total_shutter_width	= MT9V024_MAX_TOTAL_SHUTTER_WIDTH,
+	.pixclk_fv_lv			= MT9V024_PIXCLK_FV_LV,
+};
+
+struct mt9v022 {
+	struct v4l2_subdev subdev;
+	struct v4l2_ctrl_handler hdl;
+	struct {
+		/* exposure/auto-exposure cluster */
+		struct v4l2_ctrl *autoexposure;
+		struct v4l2_ctrl *exposure;
+	};
+	struct {
+		/* gain/auto-gain cluster */
+		struct v4l2_ctrl *autogain;
+		struct v4l2_ctrl *gain;
+	};
+	struct v4l2_rect rect;	/* Sensor window */
+	const struct mt9v022_datafmt *fmt;
+	const struct mt9v022_datafmt *fmts;
+	const struct mt9v02x_register *reg;
+	int num_fmts;
+	int model;	/* V4L2_IDENT_MT9V022* codes from v4l2-chip-ident.h */
+	u16 chip_control;
+	unsigned short y_skip_top;	/* Lines to skip at the top */
+};
+
+static struct mt9v022 *to_mt9v022(const struct i2c_client *client)
+{
+	return container_of(i2c_get_clientdata(client), struct mt9v022, subdev);
+}
+
+static int reg_read(struct i2c_client *client, const u8 reg)
+{
+	return i2c_smbus_read_word_swapped(client, reg);
+}
+
+static int reg_write(struct i2c_client *client, const u8 reg,
+		     const u16 data)
+{
+	return i2c_smbus_write_word_swapped(client, reg, data);
+}
+
+static int reg_set(struct i2c_client *client, const u8 reg,
+		   const u16 data)
+{
+	int ret;
+
+	ret = reg_read(client, reg);
+	if (ret < 0)
+		return ret;
+	return reg_write(client, reg, ret | data);
+}
+
+static int reg_clear(struct i2c_client *client, const u8 reg,
+		     const u16 data)
+{
+	int ret;
+
+	ret = reg_read(client, reg);
+	if (ret < 0)
+		return ret;
+	return reg_write(client, reg, ret & ~data);
+}
+
+static int mt9v022_init(struct i2c_client *client)
+{
+	struct mt9v022 *mt9v022 = to_mt9v022(client);
+	int ret;
+
+	/*
+	 * Almost the default mode: master, parallel, simultaneous, and an
+	 * undocumented bit 0x200, which is present in table 7, but not in 8,
+	 * plus snapshot mode to disable scan for now
+	 */
+	mt9v022->chip_control |= 0x10;
+	ret = reg_write(client, MT9V022_CHIP_CONTROL, mt9v022->chip_control);
+	if (!ret)
+		ret = reg_write(client, MT9V022_READ_MODE, 0x300);
+
+	/* All defaults */
+	if (!ret)
+		/* AEC, AGC on */
+		ret = reg_set(client, MT9V022_AEC_AGC_ENABLE, 0x3);
+	if (!ret)
+		ret = reg_write(client, MT9V022_ANALOG_GAIN, 16);
+	if (!ret)
+		ret = reg_write(client, MT9V022_TOTAL_SHUTTER_WIDTH, 480);
+	if (!ret)
+		ret = reg_write(client, mt9v022->reg->max_total_shutter_width, 480);
+	if (!ret)
+		/* default - auto */
+		ret = reg_clear(client, MT9V022_BLACK_LEVEL_CALIB_CTRL, 1);
+	if (!ret)
+		ret = reg_write(client, MT9V022_DIGITAL_TEST_PATTERN, 0);
+	if (!ret)
+		return v4l2_ctrl_handler_setup(&mt9v022->hdl);
+
+	return ret;
+}
+
+static int mt9v022_s_stream(struct v4l2_subdev *sd, int enable)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct mt9v022 *mt9v022 = to_mt9v022(client);
+
+	if (enable)
+		/* Switch to master "normal" mode */
+		mt9v022->chip_control &= ~0x10;
+	else
+		/* Switch to snapshot mode */
+		mt9v022->chip_control |= 0x10;
+
+	if (reg_write(client, MT9V022_CHIP_CONTROL, mt9v022->chip_control) < 0)
+		return -EIO;
+	return 0;
+}
+
+static int mt9v022_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct mt9v022 *mt9v022 = to_mt9v022(client);
+	struct v4l2_rect rect = a->c;
+	int ret;
+
+	/* Bayer format - even size lengths */
+	if (mt9v022->fmts == mt9v022_colour_fmts) {
+		rect.width	= ALIGN(rect.width, 2);
+		rect.height	= ALIGN(rect.height, 2);
+		/* Let the user play with the starting pixel */
+	}
+
+	soc_camera_limit_side(&rect.left, &rect.width,
+		     MT9V022_COLUMN_SKIP, MT9V022_MIN_WIDTH, MT9V022_MAX_WIDTH);
+
+	soc_camera_limit_side(&rect.top, &rect.height,
+		     MT9V022_ROW_SKIP, MT9V022_MIN_HEIGHT, MT9V022_MAX_HEIGHT);
+
+	/* Like in example app. Contradicts the datasheet though */
+	ret = reg_read(client, MT9V022_AEC_AGC_ENABLE);
+	if (ret >= 0) {
+		if (ret & 1) /* Autoexposure */
+			ret = reg_write(client, mt9v022->reg->max_total_shutter_width,
+					rect.height + mt9v022->y_skip_top + 43);
+		else
+			ret = reg_write(client, MT9V022_TOTAL_SHUTTER_WIDTH,
+					rect.height + mt9v022->y_skip_top + 43);
+	}
+	/* Setup frame format: defaults apart from width and height */
+	if (!ret)
+		ret = reg_write(client, MT9V022_COLUMN_START, rect.left);
+	if (!ret)
+		ret = reg_write(client, MT9V022_ROW_START, rect.top);
+	if (!ret)
+		/*
+		 * Default 94, Phytec driver says:
+		 * "width + horizontal blank >= 660"
+		 */
+		ret = reg_write(client, MT9V022_HORIZONTAL_BLANKING,
+				rect.width > 660 - 43 ? 43 :
+				660 - rect.width);
+	if (!ret)
+		ret = reg_write(client, MT9V022_VERTICAL_BLANKING, 45);
+	if (!ret)
+		ret = reg_write(client, MT9V022_WINDOW_WIDTH, rect.width);
+	if (!ret)
+		ret = reg_write(client, MT9V022_WINDOW_HEIGHT,
+				rect.height + mt9v022->y_skip_top);
+
+	if (ret < 0)
+		return ret;
+
+	dev_dbg(&client->dev, "Frame %dx%d pixel\n", rect.width, rect.height);
+
+	mt9v022->rect = rect;
+
+	return 0;
+}
+
+static int mt9v022_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct mt9v022 *mt9v022 = to_mt9v022(client);
+
+	a->c	= mt9v022->rect;
+	a->type	= V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+	return 0;
+}
+
+static int mt9v022_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
+{
+	a->bounds.left			= MT9V022_COLUMN_SKIP;
+	a->bounds.top			= MT9V022_ROW_SKIP;
+	a->bounds.width			= MT9V022_MAX_WIDTH;
+	a->bounds.height		= MT9V022_MAX_HEIGHT;
+	a->defrect			= a->bounds;
+	a->type				= V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	a->pixelaspect.numerator	= 1;
+	a->pixelaspect.denominator	= 1;
+
+	return 0;
+}
+
+static int mt9v022_g_fmt(struct v4l2_subdev *sd,
+			 struct v4l2_mbus_framefmt *mf)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct mt9v022 *mt9v022 = to_mt9v022(client);
+
+	mf->width	= mt9v022->rect.width;
+	mf->height	= mt9v022->rect.height;
+	mf->code	= mt9v022->fmt->code;
+	mf->colorspace	= mt9v022->fmt->colorspace;
+	mf->field	= V4L2_FIELD_NONE;
+
+	return 0;
+}
+
+static int mt9v022_s_fmt(struct v4l2_subdev *sd,
+			 struct v4l2_mbus_framefmt *mf)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct mt9v022 *mt9v022 = to_mt9v022(client);
+	struct v4l2_crop a = {
+		.c = {
+			.left	= mt9v022->rect.left,
+			.top	= mt9v022->rect.top,
+			.width	= mf->width,
+			.height	= mf->height,
+		},
+	};
+	int ret;
+
+	/*
+	 * The caller provides a supported format, as verified per call to
+	 * .try_mbus_fmt(), datawidth is from our supported format list
+	 */
+	switch (mf->code) {
+	case V4L2_MBUS_FMT_Y8_1X8:
+	case V4L2_MBUS_FMT_Y10_1X10:
+		if (mt9v022->model != V4L2_IDENT_MT9V022IX7ATM)
+			return -EINVAL;
+		break;
+	case V4L2_MBUS_FMT_SBGGR8_1X8:
+	case V4L2_MBUS_FMT_SBGGR10_1X10:
+		if (mt9v022->model != V4L2_IDENT_MT9V022IX7ATC)
+			return -EINVAL;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* No support for scaling on this camera, just crop. */
+	ret = mt9v022_s_crop(sd, &a);
+	if (!ret) {
+		mf->width	= mt9v022->rect.width;
+		mf->height	= mt9v022->rect.height;
+		mt9v022->fmt	= mt9v022_find_datafmt(mf->code,
+					mt9v022->fmts, mt9v022->num_fmts);
+		mf->colorspace	= mt9v022->fmt->colorspace;
+	}
+
+	return ret;
+}
+
+static int mt9v022_try_fmt(struct v4l2_subdev *sd,
+			   struct v4l2_mbus_framefmt *mf)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct mt9v022 *mt9v022 = to_mt9v022(client);
+	const struct mt9v022_datafmt *fmt;
+	int align = mf->code == V4L2_MBUS_FMT_SBGGR8_1X8 ||
+		mf->code == V4L2_MBUS_FMT_SBGGR10_1X10;
+
+	v4l_bound_align_image(&mf->width, MT9V022_MIN_WIDTH,
+		MT9V022_MAX_WIDTH, align,
+		&mf->height, MT9V022_MIN_HEIGHT + mt9v022->y_skip_top,
+		MT9V022_MAX_HEIGHT + mt9v022->y_skip_top, align, 0);
+
+	fmt = mt9v022_find_datafmt(mf->code, mt9v022->fmts,
+				   mt9v022->num_fmts);
+	if (!fmt) {
+		fmt = mt9v022->fmt;
+		mf->code = fmt->code;
+	}
+
+	mf->colorspace	= fmt->colorspace;
+
+	return 0;
+}
+
+static int mt9v022_g_chip_ident(struct v4l2_subdev *sd,
+				struct v4l2_dbg_chip_ident *id)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct mt9v022 *mt9v022 = to_mt9v022(client);
+
+	if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
+		return -EINVAL;
+
+	if (id->match.addr != client->addr)
+		return -ENODEV;
+
+	id->ident	= mt9v022->model;
+	id->revision	= 0;
+
+	return 0;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int mt9v022_g_register(struct v4l2_subdev *sd,
+			      struct v4l2_dbg_register *reg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
+		return -EINVAL;
+
+	if (reg->match.addr != client->addr)
+		return -ENODEV;
+
+	reg->size = 2;
+	reg->val = reg_read(client, reg->reg);
+
+	if (reg->val > 0xffff)
+		return -EIO;
+
+	return 0;
+}
+
+static int mt9v022_s_register(struct v4l2_subdev *sd,
+			      struct v4l2_dbg_register *reg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
+		return -EINVAL;
+
+	if (reg->match.addr != client->addr)
+		return -ENODEV;
+
+	if (reg_write(client, reg->reg, reg->val) < 0)
+		return -EIO;
+
+	return 0;
+}
+#endif
+
+static int mt9v022_s_power(struct v4l2_subdev *sd, int on)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+	return soc_camera_set_power(&client->dev, icl, on);
+}
+
+static int mt9v022_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct mt9v022 *mt9v022 = container_of(ctrl->handler,
+					       struct mt9v022, hdl);
+	struct v4l2_subdev *sd = &mt9v022->subdev;
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct v4l2_ctrl *gain = mt9v022->gain;
+	struct v4l2_ctrl *exp = mt9v022->exposure;
+	unsigned long range;
+	int data;
+
+	switch (ctrl->id) {
+	case V4L2_CID_AUTOGAIN:
+		data = reg_read(client, MT9V022_ANALOG_GAIN);
+		if (data < 0)
+			return -EIO;
+
+		range = gain->maximum - gain->minimum;
+		gain->val = ((data - 16) * range + 24) / 48 + gain->minimum;
+		return 0;
+	case V4L2_CID_EXPOSURE_AUTO:
+		data = reg_read(client, MT9V022_TOTAL_SHUTTER_WIDTH);
+		if (data < 0)
+			return -EIO;
+
+		range = exp->maximum - exp->minimum;
+		exp->val = ((data - 1) * range + 239) / 479 + exp->minimum;
+		return 0;
+	}
+	return -EINVAL;
+}
+
+static int mt9v022_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct mt9v022 *mt9v022 = container_of(ctrl->handler,
+					       struct mt9v022, hdl);
+	struct v4l2_subdev *sd = &mt9v022->subdev;
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	int data;
+
+	switch (ctrl->id) {
+	case V4L2_CID_VFLIP:
+		if (ctrl->val)
+			data = reg_set(client, MT9V022_READ_MODE, 0x10);
+		else
+			data = reg_clear(client, MT9V022_READ_MODE, 0x10);
+		if (data < 0)
+			return -EIO;
+		return 0;
+	case V4L2_CID_HFLIP:
+		if (ctrl->val)
+			data = reg_set(client, MT9V022_READ_MODE, 0x20);
+		else
+			data = reg_clear(client, MT9V022_READ_MODE, 0x20);
+		if (data < 0)
+			return -EIO;
+		return 0;
+	case V4L2_CID_AUTOGAIN:
+		if (ctrl->val) {
+			if (reg_set(client, MT9V022_AEC_AGC_ENABLE, 0x2) < 0)
+				return -EIO;
+		} else {
+			struct v4l2_ctrl *gain = mt9v022->gain;
+			/* mt9v022 has minimum == default */
+			unsigned long range = gain->maximum - gain->minimum;
+			/* Valid values 16 to 64, 32 to 64 must be even. */
+			unsigned long gain_val = ((gain->val - gain->minimum) *
+					      48 + range / 2) / range + 16;
+
+			if (gain_val >= 32)
+				gain_val &= ~1;
+
+			/*
+			 * The user wants to set gain manually, hope, she
+			 * knows, what she's doing... Switch AGC off.
+			 */
+			if (reg_clear(client, MT9V022_AEC_AGC_ENABLE, 0x2) < 0)
+				return -EIO;
+
+			dev_dbg(&client->dev, "Setting gain from %d to %lu\n",
+				reg_read(client, MT9V022_ANALOG_GAIN), gain_val);
+			if (reg_write(client, MT9V022_ANALOG_GAIN, gain_val) < 0)
+				return -EIO;
+		}
+		return 0;
+	case V4L2_CID_EXPOSURE_AUTO:
+		if (ctrl->val == V4L2_EXPOSURE_AUTO) {
+			data = reg_set(client, MT9V022_AEC_AGC_ENABLE, 0x1);
+		} else {
+			struct v4l2_ctrl *exp = mt9v022->exposure;
+			unsigned long range = exp->maximum - exp->minimum;
+			unsigned long shutter = ((exp->val - exp->minimum) *
+					479 + range / 2) / range + 1;
+
+			/*
+			 * The user wants to set shutter width manually, hope,
+			 * she knows, what she's doing... Switch AEC off.
+			 */
+			data = reg_clear(client, MT9V022_AEC_AGC_ENABLE, 0x1);
+			if (data < 0)
+				return -EIO;
+			dev_dbg(&client->dev, "Shutter width from %d to %lu\n",
+					reg_read(client, MT9V022_TOTAL_SHUTTER_WIDTH),
+					shutter);
+			if (reg_write(client, MT9V022_TOTAL_SHUTTER_WIDTH,
+						shutter) < 0)
+				return -EIO;
+		}
+		return 0;
+	}
+	return -EINVAL;
+}
+
+/*
+ * Interface active, can use i2c. If it fails, it can indeed mean, that
+ * this wasn't our capture interface, so, we wait for the right one
+ */
+static int mt9v022_video_probe(struct i2c_client *client)
+{
+	struct mt9v022 *mt9v022 = to_mt9v022(client);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+	s32 data;
+	int ret;
+	unsigned long flags;
+
+	ret = mt9v022_s_power(&mt9v022->subdev, 1);
+	if (ret < 0)
+		return ret;
+
+	/* Read out the chip version register */
+	data = reg_read(client, MT9V022_CHIP_VERSION);
+
+	/* must be 0x1311, 0x1313 or 0x1324 */
+	if (data != 0x1311 && data != 0x1313 && data != 0x1324) {
+		ret = -ENODEV;
+		dev_info(&client->dev, "No MT9V022 found, ID register 0x%x\n",
+			 data);
+		goto ei2c;
+	}
+
+	mt9v022->reg = is_mt9v024(data) ? &mt9v024_register :
+			&mt9v022_register;
+
+	/* Soft reset */
+	ret = reg_write(client, MT9V022_RESET, 1);
+	if (ret < 0)
+		goto ei2c;
+	/* 15 clock cycles */
+	udelay(200);
+	if (reg_read(client, MT9V022_RESET)) {
+		dev_err(&client->dev, "Resetting MT9V022 failed!\n");
+		if (ret > 0)
+			ret = -EIO;
+		goto ei2c;
+	}
+
+	/* Set monochrome or colour sensor type */
+	if (sensor_type && (!strcmp("colour", sensor_type) ||
+			    !strcmp("color", sensor_type))) {
+		ret = reg_write(client, MT9V022_PIXEL_OPERATION_MODE, 4 | 0x11);
+		mt9v022->model = V4L2_IDENT_MT9V022IX7ATC;
+		mt9v022->fmts = mt9v022_colour_fmts;
+	} else {
+		ret = reg_write(client, MT9V022_PIXEL_OPERATION_MODE, 0x11);
+		mt9v022->model = V4L2_IDENT_MT9V022IX7ATM;
+		mt9v022->fmts = mt9v022_monochrome_fmts;
+	}
+
+	if (ret < 0)
+		goto ei2c;
+
+	mt9v022->num_fmts = 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)
+		mt9v022->num_fmts++;
+	else
+		mt9v022->fmts++;
+
+	if (flags & SOCAM_DATAWIDTH_8)
+		mt9v022->num_fmts++;
+
+	mt9v022->fmt = &mt9v022->fmts[0];
+
+	dev_info(&client->dev, "Detected a MT9V022 chip ID %x, %s sensor\n",
+		 data, mt9v022->model == V4L2_IDENT_MT9V022IX7ATM ?
+		 "monochrome" : "colour");
+
+	ret = mt9v022_init(client);
+	if (ret < 0)
+		dev_err(&client->dev, "Failed to initialise the camera\n");
+
+ei2c:
+	mt9v022_s_power(&mt9v022->subdev, 0);
+	return ret;
+}
+
+static int mt9v022_g_skip_top_lines(struct v4l2_subdev *sd, u32 *lines)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct mt9v022 *mt9v022 = to_mt9v022(client);
+
+	*lines = mt9v022->y_skip_top;
+
+	return 0;
+}
+
+static const struct v4l2_ctrl_ops mt9v022_ctrl_ops = {
+	.g_volatile_ctrl = mt9v022_g_volatile_ctrl,
+	.s_ctrl = mt9v022_s_ctrl,
+};
+
+static struct v4l2_subdev_core_ops mt9v022_subdev_core_ops = {
+	.g_chip_ident	= mt9v022_g_chip_ident,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.g_register	= mt9v022_g_register,
+	.s_register	= mt9v022_s_register,
+#endif
+	.s_power	= mt9v022_s_power,
+};
+
+static int mt9v022_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
+			    enum v4l2_mbus_pixelcode *code)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct mt9v022 *mt9v022 = to_mt9v022(client);
+
+	if (index >= mt9v022->num_fmts)
+		return -EINVAL;
+
+	*code = mt9v022->fmts[index].code;
+	return 0;
+}
+
+static int mt9v022_g_mbus_config(struct v4l2_subdev *sd,
+				struct v4l2_mbus_config *cfg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+	cfg->flags = V4L2_MBUS_MASTER | V4L2_MBUS_SLAVE |
+		V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_PCLK_SAMPLE_FALLING |
+		V4L2_MBUS_HSYNC_ACTIVE_HIGH | V4L2_MBUS_HSYNC_ACTIVE_LOW |
+		V4L2_MBUS_VSYNC_ACTIVE_HIGH | V4L2_MBUS_VSYNC_ACTIVE_LOW |
+		V4L2_MBUS_DATA_ACTIVE_HIGH;
+	cfg->type = V4L2_MBUS_PARALLEL;
+	cfg->flags = soc_camera_apply_board_flags(icl, cfg);
+
+	return 0;
+}
+
+static int mt9v022_s_mbus_config(struct v4l2_subdev *sd,
+				 const struct v4l2_mbus_config *cfg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+	struct mt9v022 *mt9v022 = to_mt9v022(client);
+	unsigned long flags = soc_camera_apply_board_flags(icl, cfg);
+	unsigned int bps = soc_mbus_get_fmtdesc(mt9v022->fmt->code)->bits_per_sample;
+	int ret;
+	u16 pixclk = 0;
+
+	if (icl->set_bus_param) {
+		ret = icl->set_bus_param(icl, 1 << (bps - 1));
+		if (ret)
+			return ret;
+	} else if (bps != 10) {
+		/*
+		 * Without board specific bus width settings we only support the
+		 * sensors native bus width
+		 */
+		return -EINVAL;
+	}
+
+	if (flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)
+		pixclk |= 0x10;
+
+	if (!(flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH))
+		pixclk |= 0x1;
+
+	if (!(flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH))
+		pixclk |= 0x2;
+
+	ret = reg_write(client, mt9v022->reg->pixclk_fv_lv, pixclk);
+	if (ret < 0)
+		return ret;
+
+	if (!(flags & V4L2_MBUS_MASTER))
+		mt9v022->chip_control &= ~0x8;
+
+	ret = reg_write(client, MT9V022_CHIP_CONTROL, mt9v022->chip_control);
+	if (ret < 0)
+		return ret;
+
+	dev_dbg(&client->dev, "Calculated pixclk 0x%x, chip control 0x%x\n",
+		pixclk, mt9v022->chip_control);
+
+	return 0;
+}
+
+static struct v4l2_subdev_video_ops mt9v022_subdev_video_ops = {
+	.s_stream	= mt9v022_s_stream,
+	.s_mbus_fmt	= mt9v022_s_fmt,
+	.g_mbus_fmt	= mt9v022_g_fmt,
+	.try_mbus_fmt	= mt9v022_try_fmt,
+	.s_crop		= mt9v022_s_crop,
+	.g_crop		= mt9v022_g_crop,
+	.cropcap	= mt9v022_cropcap,
+	.enum_mbus_fmt	= mt9v022_enum_fmt,
+	.g_mbus_config	= mt9v022_g_mbus_config,
+	.s_mbus_config	= mt9v022_s_mbus_config,
+};
+
+static struct v4l2_subdev_sensor_ops mt9v022_subdev_sensor_ops = {
+	.g_skip_top_lines	= mt9v022_g_skip_top_lines,
+};
+
+static struct v4l2_subdev_ops mt9v022_subdev_ops = {
+	.core	= &mt9v022_subdev_core_ops,
+	.video	= &mt9v022_subdev_video_ops,
+	.sensor	= &mt9v022_subdev_sensor_ops,
+};
+
+static int mt9v022_probe(struct i2c_client *client,
+			 const struct i2c_device_id *did)
+{
+	struct mt9v022 *mt9v022;
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+	int ret;
+
+	if (!icl) {
+		dev_err(&client->dev, "MT9V022 driver needs platform data\n");
+		return -EINVAL;
+	}
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) {
+		dev_warn(&adapter->dev,
+			 "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n");
+		return -EIO;
+	}
+
+	mt9v022 = kzalloc(sizeof(struct mt9v022), GFP_KERNEL);
+	if (!mt9v022)
+		return -ENOMEM;
+
+	v4l2_i2c_subdev_init(&mt9v022->subdev, client, &mt9v022_subdev_ops);
+	v4l2_ctrl_handler_init(&mt9v022->hdl, 6);
+	v4l2_ctrl_new_std(&mt9v022->hdl, &mt9v022_ctrl_ops,
+			V4L2_CID_VFLIP, 0, 1, 1, 0);
+	v4l2_ctrl_new_std(&mt9v022->hdl, &mt9v022_ctrl_ops,
+			V4L2_CID_HFLIP, 0, 1, 1, 0);
+	mt9v022->autogain = v4l2_ctrl_new_std(&mt9v022->hdl, &mt9v022_ctrl_ops,
+			V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
+	mt9v022->gain = v4l2_ctrl_new_std(&mt9v022->hdl, &mt9v022_ctrl_ops,
+			V4L2_CID_GAIN, 0, 127, 1, 64);
+
+	/*
+	 * Simulated autoexposure. If enabled, we calculate shutter width
+	 * ourselves in the driver based on vertical blanking and frame width
+	 */
+	mt9v022->autoexposure = v4l2_ctrl_new_std_menu(&mt9v022->hdl,
+			&mt9v022_ctrl_ops, V4L2_CID_EXPOSURE_AUTO, 1, 0,
+			V4L2_EXPOSURE_AUTO);
+	mt9v022->exposure = v4l2_ctrl_new_std(&mt9v022->hdl, &mt9v022_ctrl_ops,
+			V4L2_CID_EXPOSURE, 1, 255, 1, 255);
+
+	mt9v022->subdev.ctrl_handler = &mt9v022->hdl;
+	if (mt9v022->hdl.error) {
+		int err = mt9v022->hdl.error;
+
+		kfree(mt9v022);
+		return err;
+	}
+	v4l2_ctrl_auto_cluster(2, &mt9v022->autoexposure,
+				V4L2_EXPOSURE_MANUAL, true);
+	v4l2_ctrl_auto_cluster(2, &mt9v022->autogain, 0, true);
+
+	mt9v022->chip_control = MT9V022_CHIP_CONTROL_DEFAULT;
+
+	/*
+	 * MT9V022 _really_ corrupts the first read out line.
+	 * TODO: verify on i.MX31
+	 */
+	mt9v022->y_skip_top	= 1;
+	mt9v022->rect.left	= MT9V022_COLUMN_SKIP;
+	mt9v022->rect.top	= MT9V022_ROW_SKIP;
+	mt9v022->rect.width	= MT9V022_MAX_WIDTH;
+	mt9v022->rect.height	= MT9V022_MAX_HEIGHT;
+
+	ret = mt9v022_video_probe(client);
+	if (ret) {
+		v4l2_ctrl_handler_free(&mt9v022->hdl);
+		kfree(mt9v022);
+	}
+
+	return ret;
+}
+
+static int mt9v022_remove(struct i2c_client *client)
+{
+	struct mt9v022 *mt9v022 = to_mt9v022(client);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+	v4l2_device_unregister_subdev(&mt9v022->subdev);
+	if (icl->free_bus)
+		icl->free_bus(icl);
+	v4l2_ctrl_handler_free(&mt9v022->hdl);
+	kfree(mt9v022);
+
+	return 0;
+}
+static const struct i2c_device_id mt9v022_id[] = {
+	{ "mt9v022", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, mt9v022_id);
+
+static struct i2c_driver mt9v022_i2c_driver = {
+	.driver = {
+		.name = "mt9v022",
+	},
+	.probe		= mt9v022_probe,
+	.remove		= mt9v022_remove,
+	.id_table	= mt9v022_id,
+};
+
+module_i2c_driver(mt9v022_i2c_driver);
+
+MODULE_DESCRIPTION("Micron MT9V022 Camera driver");
+MODULE_AUTHOR("Guennadi Liakhovetski <kernel@pengutronix.de>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/i2c/soc_camera/ov2640.c b/drivers/media/i2c/soc_camera/ov2640.c
new file mode 100644
index 0000000..78ac574
--- /dev/null
+++ b/drivers/media/i2c/soc_camera/ov2640.c
@@ -0,0 +1,1122 @@
+/*
+ * ov2640 Camera Driver
+ *
+ * Copyright (C) 2010 Alberto Panizzo <maramaopercheseimorto@gmail.com>
+ *
+ * Based on ov772x, ov9640 drivers and previous non merged implementations.
+ *
+ * Copyright 2005-2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2006, OmniVision
+ *
+ * This program is free software; you can 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/i2c.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/v4l2-mediabus.h>
+#include <linux/videodev2.h>
+
+#include <media/soc_camera.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-subdev.h>
+#include <media/v4l2-ctrls.h>
+
+#define VAL_SET(x, mask, rshift, lshift)  \
+		((((x) >> rshift) & mask) << lshift)
+/*
+ * DSP registers
+ * register offset for BANK_SEL == BANK_SEL_DSP
+ */
+#define R_BYPASS    0x05 /* Bypass DSP */
+#define   R_BYPASS_DSP_BYPAS    0x01 /* Bypass DSP, sensor out directly */
+#define   R_BYPASS_USE_DSP      0x00 /* Use the internal DSP */
+#define QS          0x44 /* Quantization Scale Factor */
+#define CTRLI       0x50
+#define   CTRLI_LP_DP           0x80
+#define   CTRLI_ROUND           0x40
+#define   CTRLI_V_DIV_SET(x)    VAL_SET(x, 0x3, 0, 3)
+#define   CTRLI_H_DIV_SET(x)    VAL_SET(x, 0x3, 0, 0)
+#define HSIZE       0x51 /* H_SIZE[7:0] (real/4) */
+#define   HSIZE_SET(x)          VAL_SET(x, 0xFF, 2, 0)
+#define VSIZE       0x52 /* V_SIZE[7:0] (real/4) */
+#define   VSIZE_SET(x)          VAL_SET(x, 0xFF, 2, 0)
+#define XOFFL       0x53 /* OFFSET_X[7:0] */
+#define   XOFFL_SET(x)          VAL_SET(x, 0xFF, 0, 0)
+#define YOFFL       0x54 /* OFFSET_Y[7:0] */
+#define   YOFFL_SET(x)          VAL_SET(x, 0xFF, 0, 0)
+#define VHYX        0x55 /* Offset and size completion */
+#define   VHYX_VSIZE_SET(x)     VAL_SET(x, 0x1, (8+2), 7)
+#define   VHYX_HSIZE_SET(x)     VAL_SET(x, 0x1, (8+2), 3)
+#define   VHYX_YOFF_SET(x)      VAL_SET(x, 0x3, 8, 4)
+#define   VHYX_XOFF_SET(x)      VAL_SET(x, 0x3, 8, 0)
+#define DPRP        0x56
+#define TEST        0x57 /* Horizontal size completion */
+#define   TEST_HSIZE_SET(x)     VAL_SET(x, 0x1, (9+2), 7)
+#define ZMOW        0x5A /* Zoom: Out Width  OUTW[7:0] (real/4) */
+#define   ZMOW_OUTW_SET(x)      VAL_SET(x, 0xFF, 2, 0)
+#define ZMOH        0x5B /* Zoom: Out Height OUTH[7:0] (real/4) */
+#define   ZMOH_OUTH_SET(x)      VAL_SET(x, 0xFF, 2, 0)
+#define ZMHH        0x5C /* Zoom: Speed and H&W completion */
+#define   ZMHH_ZSPEED_SET(x)    VAL_SET(x, 0x0F, 0, 4)
+#define   ZMHH_OUTH_SET(x)      VAL_SET(x, 0x1, (8+2), 2)
+#define   ZMHH_OUTW_SET(x)      VAL_SET(x, 0x3, (8+2), 0)
+#define BPADDR      0x7C /* SDE Indirect Register Access: Address */
+#define BPDATA      0x7D /* SDE Indirect Register Access: Data */
+#define CTRL2       0x86 /* DSP Module enable 2 */
+#define   CTRL2_DCW_EN          0x20
+#define   CTRL2_SDE_EN          0x10
+#define   CTRL2_UV_ADJ_EN       0x08
+#define   CTRL2_UV_AVG_EN       0x04
+#define   CTRL2_CMX_EN          0x01
+#define CTRL3       0x87 /* DSP Module enable 3 */
+#define   CTRL3_BPC_EN          0x80
+#define   CTRL3_WPC_EN          0x40
+#define SIZEL       0x8C /* Image Size Completion */
+#define   SIZEL_HSIZE8_11_SET(x) VAL_SET(x, 0x1, 11, 6)
+#define   SIZEL_HSIZE8_SET(x)    VAL_SET(x, 0x7, 0, 3)
+#define   SIZEL_VSIZE8_SET(x)    VAL_SET(x, 0x7, 0, 0)
+#define HSIZE8      0xC0 /* Image Horizontal Size HSIZE[10:3] */
+#define   HSIZE8_SET(x)         VAL_SET(x, 0xFF, 3, 0)
+#define VSIZE8      0xC1 /* Image Vertical Size VSIZE[10:3] */
+#define   VSIZE8_SET(x)         VAL_SET(x, 0xFF, 3, 0)
+#define CTRL0       0xC2 /* DSP Module enable 0 */
+#define   CTRL0_AEC_EN       0x80
+#define   CTRL0_AEC_SEL      0x40
+#define   CTRL0_STAT_SEL     0x20
+#define   CTRL0_VFIRST       0x10
+#define   CTRL0_YUV422       0x08
+#define   CTRL0_YUV_EN       0x04
+#define   CTRL0_RGB_EN       0x02
+#define   CTRL0_RAW_EN       0x01
+#define CTRL1       0xC3 /* DSP Module enable 1 */
+#define   CTRL1_CIP          0x80
+#define   CTRL1_DMY          0x40
+#define   CTRL1_RAW_GMA      0x20
+#define   CTRL1_DG           0x10
+#define   CTRL1_AWB          0x08
+#define   CTRL1_AWB_GAIN     0x04
+#define   CTRL1_LENC         0x02
+#define   CTRL1_PRE          0x01
+#define R_DVP_SP    0xD3 /* DVP output speed control */
+#define   R_DVP_SP_AUTO_MODE 0x80
+#define   R_DVP_SP_DVP_MASK  0x3F /* DVP PCLK = sysclk (48)/[6:0] (YUV0);
+				   *          = sysclk (48)/(2*[6:0]) (RAW);*/
+#define IMAGE_MODE  0xDA /* Image Output Format Select */
+#define   IMAGE_MODE_Y8_DVP_EN   0x40
+#define   IMAGE_MODE_JPEG_EN     0x10
+#define   IMAGE_MODE_YUV422      0x00
+#define   IMAGE_MODE_RAW10       0x04 /* (DVP) */
+#define   IMAGE_MODE_RGB565      0x08
+#define   IMAGE_MODE_HREF_VSYNC  0x02 /* HREF timing select in DVP JPEG output
+				       * mode (0 for HREF is same as sensor) */
+#define   IMAGE_MODE_LBYTE_FIRST 0x01 /* Byte swap enable for DVP
+				       *    1: Low byte first UYVY (C2[4] =0)
+				       *        VYUY (C2[4] =1)
+				       *    0: High byte first YUYV (C2[4]=0)
+				       *        YVYU (C2[4] = 1) */
+#define RESET       0xE0 /* Reset */
+#define   RESET_MICROC       0x40
+#define   RESET_SCCB         0x20
+#define   RESET_JPEG         0x10
+#define   RESET_DVP          0x04
+#define   RESET_IPU          0x02
+#define   RESET_CIF          0x01
+#define REGED       0xED /* Register ED */
+#define   REGED_CLK_OUT_DIS  0x10
+#define MS_SP       0xF0 /* SCCB Master Speed */
+#define SS_ID       0xF7 /* SCCB Slave ID */
+#define SS_CTRL     0xF8 /* SCCB Slave Control */
+#define   SS_CTRL_ADD_AUTO_INC  0x20
+#define   SS_CTRL_EN            0x08
+#define   SS_CTRL_DELAY_CLK     0x04
+#define   SS_CTRL_ACC_EN        0x02
+#define   SS_CTRL_SEN_PASS_THR  0x01
+#define MC_BIST     0xF9 /* Microcontroller misc register */
+#define   MC_BIST_RESET           0x80 /* Microcontroller Reset */
+#define   MC_BIST_BOOT_ROM_SEL    0x40
+#define   MC_BIST_12KB_SEL        0x20
+#define   MC_BIST_12KB_MASK       0x30
+#define   MC_BIST_512KB_SEL       0x08
+#define   MC_BIST_512KB_MASK      0x0C
+#define   MC_BIST_BUSY_BIT_R      0x02
+#define   MC_BIST_MC_RES_ONE_SH_W 0x02
+#define   MC_BIST_LAUNCH          0x01
+#define BANK_SEL    0xFF /* Register Bank Select */
+#define   BANK_SEL_DSP     0x00
+#define   BANK_SEL_SENS    0x01
+
+/*
+ * Sensor registers
+ * register offset for BANK_SEL == BANK_SEL_SENS
+ */
+#define GAIN        0x00 /* AGC - Gain control gain setting */
+#define COM1        0x03 /* Common control 1 */
+#define   COM1_1_DUMMY_FR          0x40
+#define   COM1_3_DUMMY_FR          0x80
+#define   COM1_7_DUMMY_FR          0xC0
+#define   COM1_VWIN_LSB_UXGA       0x0F
+#define   COM1_VWIN_LSB_SVGA       0x0A
+#define   COM1_VWIN_LSB_CIF        0x06
+#define REG04       0x04 /* Register 04 */
+#define   REG04_DEF             0x20 /* Always set */
+#define   REG04_HFLIP_IMG       0x80 /* Horizontal mirror image ON/OFF */
+#define   REG04_VFLIP_IMG       0x40 /* Vertical flip image ON/OFF */
+#define   REG04_VREF_EN         0x10
+#define   REG04_HREF_EN         0x08
+#define   REG04_AEC_SET(x)      VAL_SET(x, 0x3, 0, 0)
+#define REG08       0x08 /* Frame Exposure One-pin Control Pre-charge Row Num */
+#define COM2        0x09 /* Common control 2 */
+#define   COM2_SOFT_SLEEP_MODE  0x10 /* Soft sleep mode */
+				     /* Output drive capability */
+#define   COM2_OCAP_Nx_SET(N)   (((N) - 1) & 0x03) /* N = [1x .. 4x] */
+#define PID         0x0A /* Product ID Number MSB */
+#define VER         0x0B /* Product ID Number LSB */
+#define COM3        0x0C /* Common control 3 */
+#define   COM3_BAND_50H        0x04 /* 0 For Banding at 60H */
+#define   COM3_BAND_AUTO       0x02 /* Auto Banding */
+#define   COM3_SING_FR_SNAPSH  0x01 /* 0 For enable live video output after the
+				     * snapshot sequence*/
+#define AEC         0x10 /* AEC[9:2] Exposure Value */
+#define CLKRC       0x11 /* Internal clock */
+#define   CLKRC_EN             0x80
+#define   CLKRC_DIV_SET(x)     (((x) - 1) & 0x1F) /* CLK = XVCLK/(x) */
+#define COM7        0x12 /* Common control 7 */
+#define   COM7_SRST            0x80 /* Initiates system reset. All registers are
+				     * set to factory default values after which
+				     * the chip resumes normal operation */
+#define   COM7_RES_UXGA        0x00 /* Resolution selectors for UXGA */
+#define   COM7_RES_SVGA        0x40 /* SVGA */
+#define   COM7_RES_CIF         0x20 /* CIF */
+#define   COM7_ZOOM_EN         0x04 /* Enable Zoom mode */
+#define   COM7_COLOR_BAR_TEST  0x02 /* Enable Color Bar Test Pattern */
+#define COM8        0x13 /* Common control 8 */
+#define   COM8_DEF             0xC0 /* Banding filter ON/OFF */
+#define   COM8_BNDF_EN         0x20 /* Banding filter ON/OFF */
+#define   COM8_AGC_EN          0x04 /* AGC Auto/Manual control selection */
+#define   COM8_AEC_EN          0x01 /* Auto/Manual Exposure control */
+#define COM9        0x14 /* Common control 9
+			  * Automatic gain ceiling - maximum AGC value [7:5]*/
+#define   COM9_AGC_GAIN_2x     0x00 /* 000 :   2x */
+#define   COM9_AGC_GAIN_4x     0x20 /* 001 :   4x */
+#define   COM9_AGC_GAIN_8x     0x40 /* 010 :   8x */
+#define   COM9_AGC_GAIN_16x    0x60 /* 011 :  16x */
+#define   COM9_AGC_GAIN_32x    0x80 /* 100 :  32x */
+#define   COM9_AGC_GAIN_64x    0xA0 /* 101 :  64x */
+#define   COM9_AGC_GAIN_128x   0xC0 /* 110 : 128x */
+#define COM10       0x15 /* Common control 10 */
+#define   COM10_PCLK_HREF      0x20 /* PCLK output qualified by HREF */
+#define   COM10_PCLK_RISE      0x10 /* Data is updated at the rising edge of
+				     * PCLK (user can latch data at the next
+				     * falling edge of PCLK).
+				     * 0 otherwise. */
+#define   COM10_HREF_INV       0x08 /* Invert HREF polarity:
+				     * HREF negative for valid data*/
+#define   COM10_VSINC_INV      0x02 /* Invert VSYNC polarity */
+#define HSTART      0x17 /* Horizontal Window start MSB 8 bit */
+#define HEND        0x18 /* Horizontal Window end MSB 8 bit */
+#define VSTART      0x19 /* Vertical Window start MSB 8 bit */
+#define VEND        0x1A /* Vertical Window end MSB 8 bit */
+#define MIDH        0x1C /* Manufacturer ID byte - high */
+#define MIDL        0x1D /* Manufacturer ID byte - low  */
+#define AEW         0x24 /* AGC/AEC - Stable operating region (upper limit) */
+#define AEB         0x25 /* AGC/AEC - Stable operating region (lower limit) */
+#define VV          0x26 /* AGC/AEC Fast mode operating region */
+#define   VV_HIGH_TH_SET(x)      VAL_SET(x, 0xF, 0, 4)
+#define   VV_LOW_TH_SET(x)       VAL_SET(x, 0xF, 0, 0)
+#define REG2A       0x2A /* Dummy pixel insert MSB */
+#define FRARL       0x2B /* Dummy pixel insert LSB */
+#define ADDVFL      0x2D /* LSB of insert dummy lines in Vertical direction */
+#define ADDVFH      0x2E /* MSB of insert dummy lines in Vertical direction */
+#define YAVG        0x2F /* Y/G Channel Average value */
+#define REG32       0x32 /* Common Control 32 */
+#define   REG32_PCLK_DIV_2    0x80 /* PCLK freq divided by 2 */
+#define   REG32_PCLK_DIV_4    0xC0 /* PCLK freq divided by 4 */
+#define ARCOM2      0x34 /* Zoom: Horizontal start point */
+#define REG45       0x45 /* Register 45 */
+#define FLL         0x46 /* Frame Length Adjustment LSBs */
+#define FLH         0x47 /* Frame Length Adjustment MSBs */
+#define COM19       0x48 /* Zoom: Vertical start point */
+#define ZOOMS       0x49 /* Zoom: Vertical start point */
+#define COM22       0x4B /* Flash light control */
+#define COM25       0x4E /* For Banding operations */
+#define BD50        0x4F /* 50Hz Banding AEC 8 LSBs */
+#define BD60        0x50 /* 60Hz Banding AEC 8 LSBs */
+#define REG5D       0x5D /* AVGsel[7:0],   16-zone average weight option */
+#define REG5E       0x5E /* AVGsel[15:8],  16-zone average weight option */
+#define REG5F       0x5F /* AVGsel[23:16], 16-zone average weight option */
+#define REG60       0x60 /* AVGsel[31:24], 16-zone average weight option */
+#define HISTO_LOW   0x61 /* Histogram Algorithm Low Level */
+#define HISTO_HIGH  0x62 /* Histogram Algorithm High Level */
+
+/*
+ * ID
+ */
+#define MANUFACTURER_ID	0x7FA2
+#define PID_OV2640	0x2642
+#define VERSION(pid, ver) ((pid << 8) | (ver & 0xFF))
+
+/*
+ * Struct
+ */
+struct regval_list {
+	u8 reg_num;
+	u8 value;
+};
+
+/* Supported resolutions */
+enum ov2640_width {
+	W_QCIF	= 176,
+	W_QVGA	= 320,
+	W_CIF	= 352,
+	W_VGA	= 640,
+	W_SVGA	= 800,
+	W_XGA	= 1024,
+	W_SXGA	= 1280,
+	W_UXGA	= 1600,
+};
+
+enum ov2640_height {
+	H_QCIF	= 144,
+	H_QVGA	= 240,
+	H_CIF	= 288,
+	H_VGA	= 480,
+	H_SVGA	= 600,
+	H_XGA	= 768,
+	H_SXGA	= 1024,
+	H_UXGA	= 1200,
+};
+
+struct ov2640_win_size {
+	char				*name;
+	enum ov2640_width		width;
+	enum ov2640_height		height;
+	const struct regval_list	*regs;
+};
+
+
+struct ov2640_priv {
+	struct v4l2_subdev		subdev;
+	struct v4l2_ctrl_handler	hdl;
+	enum v4l2_mbus_pixelcode	cfmt_code;
+	const struct ov2640_win_size	*win;
+	int				model;
+};
+
+/*
+ * Registers settings
+ */
+
+#define ENDMARKER { 0xff, 0xff }
+
+static const struct regval_list ov2640_init_regs[] = {
+	{ BANK_SEL, BANK_SEL_DSP },
+	{ 0x2c,   0xff },
+	{ 0x2e,   0xdf },
+	{ BANK_SEL, BANK_SEL_SENS },
+	{ 0x3c,   0x32 },
+	{ CLKRC, CLKRC_DIV_SET(1) },
+	{ COM2, COM2_OCAP_Nx_SET(3) },
+	{ REG04, REG04_DEF | REG04_HREF_EN },
+	{ COM8,  COM8_DEF | COM8_BNDF_EN | COM8_AGC_EN | COM8_AEC_EN },
+	{ COM9, COM9_AGC_GAIN_8x | 0x08},
+	{ 0x2c,   0x0c },
+	{ 0x33,   0x78 },
+	{ 0x3a,   0x33 },
+	{ 0x3b,   0xfb },
+	{ 0x3e,   0x00 },
+	{ 0x43,   0x11 },
+	{ 0x16,   0x10 },
+	{ 0x39,   0x02 },
+	{ 0x35,   0x88 },
+	{ 0x22,   0x0a },
+	{ 0x37,   0x40 },
+	{ 0x23,   0x00 },
+	{ ARCOM2, 0xa0 },
+	{ 0x06,   0x02 },
+	{ 0x06,   0x88 },
+	{ 0x07,   0xc0 },
+	{ 0x0d,   0xb7 },
+	{ 0x0e,   0x01 },
+	{ 0x4c,   0x00 },
+	{ 0x4a,   0x81 },
+	{ 0x21,   0x99 },
+	{ AEW,    0x40 },
+	{ AEB,    0x38 },
+	{ VV,     VV_HIGH_TH_SET(0x08) | VV_LOW_TH_SET(0x02) },
+	{ 0x5c,   0x00 },
+	{ 0x63,   0x00 },
+	{ FLL,    0x22 },
+	{ COM3,   0x38 | COM3_BAND_AUTO },
+	{ REG5D,  0x55 },
+	{ REG5E,  0x7d },
+	{ REG5F,  0x7d },
+	{ REG60,  0x55 },
+	{ HISTO_LOW,   0x70 },
+	{ HISTO_HIGH,  0x80 },
+	{ 0x7c,   0x05 },
+	{ 0x20,   0x80 },
+	{ 0x28,   0x30 },
+	{ 0x6c,   0x00 },
+	{ 0x6d,   0x80 },
+	{ 0x6e,   0x00 },
+	{ 0x70,   0x02 },
+	{ 0x71,   0x94 },
+	{ 0x73,   0xc1 },
+	{ 0x3d,   0x34 },
+	{ COM7, COM7_RES_UXGA | COM7_ZOOM_EN },
+	{ 0x5a,   0x57 },
+	{ BD50,   0xbb },
+	{ BD60,   0x9c },
+	{ BANK_SEL, BANK_SEL_DSP },
+	{ 0xe5,   0x7f },
+	{ MC_BIST, MC_BIST_RESET | MC_BIST_BOOT_ROM_SEL },
+	{ 0x41,   0x24 },
+	{ RESET, RESET_JPEG | RESET_DVP },
+	{ 0x76,   0xff },
+	{ 0x33,   0xa0 },
+	{ 0x42,   0x20 },
+	{ 0x43,   0x18 },
+	{ 0x4c,   0x00 },
+	{ CTRL3, CTRL3_BPC_EN | CTRL3_WPC_EN | 0x10 },
+	{ 0x88,   0x3f },
+	{ 0xd7,   0x03 },
+	{ 0xd9,   0x10 },
+	{ R_DVP_SP , R_DVP_SP_AUTO_MODE | 0x2 },
+	{ 0xc8,   0x08 },
+	{ 0xc9,   0x80 },
+	{ BPADDR, 0x00 },
+	{ BPDATA, 0x00 },
+	{ BPADDR, 0x03 },
+	{ BPDATA, 0x48 },
+	{ BPDATA, 0x48 },
+	{ BPADDR, 0x08 },
+	{ BPDATA, 0x20 },
+	{ BPDATA, 0x10 },
+	{ BPDATA, 0x0e },
+	{ 0x90,   0x00 },
+	{ 0x91,   0x0e },
+	{ 0x91,   0x1a },
+	{ 0x91,   0x31 },
+	{ 0x91,   0x5a },
+	{ 0x91,   0x69 },
+	{ 0x91,   0x75 },
+	{ 0x91,   0x7e },
+	{ 0x91,   0x88 },
+	{ 0x91,   0x8f },
+	{ 0x91,   0x96 },
+	{ 0x91,   0xa3 },
+	{ 0x91,   0xaf },
+	{ 0x91,   0xc4 },
+	{ 0x91,   0xd7 },
+	{ 0x91,   0xe8 },
+	{ 0x91,   0x20 },
+	{ 0x92,   0x00 },
+	{ 0x93,   0x06 },
+	{ 0x93,   0xe3 },
+	{ 0x93,   0x03 },
+	{ 0x93,   0x03 },
+	{ 0x93,   0x00 },
+	{ 0x93,   0x02 },
+	{ 0x93,   0x00 },
+	{ 0x93,   0x00 },
+	{ 0x93,   0x00 },
+	{ 0x93,   0x00 },
+	{ 0x93,   0x00 },
+	{ 0x93,   0x00 },
+	{ 0x93,   0x00 },
+	{ 0x96,   0x00 },
+	{ 0x97,   0x08 },
+	{ 0x97,   0x19 },
+	{ 0x97,   0x02 },
+	{ 0x97,   0x0c },
+	{ 0x97,   0x24 },
+	{ 0x97,   0x30 },
+	{ 0x97,   0x28 },
+	{ 0x97,   0x26 },
+	{ 0x97,   0x02 },
+	{ 0x97,   0x98 },
+	{ 0x97,   0x80 },
+	{ 0x97,   0x00 },
+	{ 0x97,   0x00 },
+	{ 0xa4,   0x00 },
+	{ 0xa8,   0x00 },
+	{ 0xc5,   0x11 },
+	{ 0xc6,   0x51 },
+	{ 0xbf,   0x80 },
+	{ 0xc7,   0x10 },
+	{ 0xb6,   0x66 },
+	{ 0xb8,   0xA5 },
+	{ 0xb7,   0x64 },
+	{ 0xb9,   0x7C },
+	{ 0xb3,   0xaf },
+	{ 0xb4,   0x97 },
+	{ 0xb5,   0xFF },
+	{ 0xb0,   0xC5 },
+	{ 0xb1,   0x94 },
+	{ 0xb2,   0x0f },
+	{ 0xc4,   0x5c },
+	{ 0xa6,   0x00 },
+	{ 0xa7,   0x20 },
+	{ 0xa7,   0xd8 },
+	{ 0xa7,   0x1b },
+	{ 0xa7,   0x31 },
+	{ 0xa7,   0x00 },
+	{ 0xa7,   0x18 },
+	{ 0xa7,   0x20 },
+	{ 0xa7,   0xd8 },
+	{ 0xa7,   0x19 },
+	{ 0xa7,   0x31 },
+	{ 0xa7,   0x00 },
+	{ 0xa7,   0x18 },
+	{ 0xa7,   0x20 },
+	{ 0xa7,   0xd8 },
+	{ 0xa7,   0x19 },
+	{ 0xa7,   0x31 },
+	{ 0xa7,   0x00 },
+	{ 0xa7,   0x18 },
+	{ 0x7f,   0x00 },
+	{ 0xe5,   0x1f },
+	{ 0xe1,   0x77 },
+	{ 0xdd,   0x7f },
+	{ CTRL0,  CTRL0_YUV422 | CTRL0_YUV_EN | CTRL0_RGB_EN },
+	ENDMARKER,
+};
+
+/*
+ * Register settings for window size
+ * The preamble, setup the internal DSP to input an UXGA (1600x1200) image.
+ * Then the different zooming configurations will setup the output image size.
+ */
+static const struct regval_list ov2640_size_change_preamble_regs[] = {
+	{ BANK_SEL, BANK_SEL_DSP },
+	{ RESET, RESET_DVP },
+	{ HSIZE8, HSIZE8_SET(W_UXGA) },
+	{ VSIZE8, VSIZE8_SET(H_UXGA) },
+	{ CTRL2, CTRL2_DCW_EN | CTRL2_SDE_EN |
+		 CTRL2_UV_AVG_EN | CTRL2_CMX_EN | CTRL2_UV_ADJ_EN },
+	{ HSIZE, HSIZE_SET(W_UXGA) },
+	{ VSIZE, VSIZE_SET(H_UXGA) },
+	{ XOFFL, XOFFL_SET(0) },
+	{ YOFFL, YOFFL_SET(0) },
+	{ VHYX, VHYX_HSIZE_SET(W_UXGA) | VHYX_VSIZE_SET(H_UXGA) |
+		VHYX_XOFF_SET(0) | VHYX_YOFF_SET(0)},
+	{ TEST, TEST_HSIZE_SET(W_UXGA) },
+	ENDMARKER,
+};
+
+#define PER_SIZE_REG_SEQ(x, y, v_div, h_div, pclk_div)	\
+	{ CTRLI, CTRLI_LP_DP | CTRLI_V_DIV_SET(v_div) |	\
+		 CTRLI_H_DIV_SET(h_div)},		\
+	{ ZMOW, ZMOW_OUTW_SET(x) },			\
+	{ ZMOH, ZMOH_OUTH_SET(y) },			\
+	{ ZMHH, ZMHH_OUTW_SET(x) | ZMHH_OUTH_SET(y) },	\
+	{ R_DVP_SP, pclk_div },				\
+	{ RESET, 0x00}
+
+static const struct regval_list ov2640_qcif_regs[] = {
+	PER_SIZE_REG_SEQ(W_QCIF, H_QCIF, 3, 3, 4),
+	ENDMARKER,
+};
+
+static const struct regval_list ov2640_qvga_regs[] = {
+	PER_SIZE_REG_SEQ(W_QVGA, H_QVGA, 2, 2, 4),
+	ENDMARKER,
+};
+
+static const struct regval_list ov2640_cif_regs[] = {
+	PER_SIZE_REG_SEQ(W_CIF, H_CIF, 2, 2, 8),
+	ENDMARKER,
+};
+
+static const struct regval_list ov2640_vga_regs[] = {
+	PER_SIZE_REG_SEQ(W_VGA, H_VGA, 0, 0, 2),
+	ENDMARKER,
+};
+
+static const struct regval_list ov2640_svga_regs[] = {
+	PER_SIZE_REG_SEQ(W_SVGA, H_SVGA, 1, 1, 2),
+	ENDMARKER,
+};
+
+static const struct regval_list ov2640_xga_regs[] = {
+	PER_SIZE_REG_SEQ(W_XGA, H_XGA, 0, 0, 2),
+	{ CTRLI,    0x00},
+	ENDMARKER,
+};
+
+static const struct regval_list ov2640_sxga_regs[] = {
+	PER_SIZE_REG_SEQ(W_SXGA, H_SXGA, 0, 0, 2),
+	{ CTRLI,    0x00},
+	{ R_DVP_SP, 2 | R_DVP_SP_AUTO_MODE },
+	ENDMARKER,
+};
+
+static const struct regval_list ov2640_uxga_regs[] = {
+	PER_SIZE_REG_SEQ(W_UXGA, H_UXGA, 0, 0, 0),
+	{ CTRLI,    0x00},
+	{ R_DVP_SP, 0 | R_DVP_SP_AUTO_MODE },
+	ENDMARKER,
+};
+
+#define OV2640_SIZE(n, w, h, r) \
+	{.name = n, .width = w , .height = h, .regs = r }
+
+static const struct ov2640_win_size ov2640_supported_win_sizes[] = {
+	OV2640_SIZE("QCIF", W_QCIF, H_QCIF, ov2640_qcif_regs),
+	OV2640_SIZE("QVGA", W_QVGA, H_QVGA, ov2640_qvga_regs),
+	OV2640_SIZE("CIF", W_CIF, H_CIF, ov2640_cif_regs),
+	OV2640_SIZE("VGA", W_VGA, H_VGA, ov2640_vga_regs),
+	OV2640_SIZE("SVGA", W_SVGA, H_SVGA, ov2640_svga_regs),
+	OV2640_SIZE("XGA", W_XGA, H_XGA, ov2640_xga_regs),
+	OV2640_SIZE("SXGA", W_SXGA, H_SXGA, ov2640_sxga_regs),
+	OV2640_SIZE("UXGA", W_UXGA, H_UXGA, ov2640_uxga_regs),
+};
+
+/*
+ * Register settings for pixel formats
+ */
+static const struct regval_list ov2640_format_change_preamble_regs[] = {
+	{ BANK_SEL, BANK_SEL_DSP },
+	{ R_BYPASS, R_BYPASS_USE_DSP },
+	ENDMARKER,
+};
+
+static const struct regval_list ov2640_yuv422_regs[] = {
+	{ IMAGE_MODE, IMAGE_MODE_LBYTE_FIRST | IMAGE_MODE_YUV422 },
+	{ 0xD7, 0x01 },
+	{ 0x33, 0xa0 },
+	{ 0xe1, 0x67 },
+	{ RESET,  0x00 },
+	{ R_BYPASS, R_BYPASS_USE_DSP },
+	ENDMARKER,
+};
+
+static const struct regval_list ov2640_rgb565_regs[] = {
+	{ IMAGE_MODE, IMAGE_MODE_LBYTE_FIRST | IMAGE_MODE_RGB565 },
+	{ 0xd7, 0x03 },
+	{ RESET,  0x00 },
+	{ R_BYPASS, R_BYPASS_USE_DSP },
+	ENDMARKER,
+};
+
+static enum v4l2_mbus_pixelcode ov2640_codes[] = {
+	V4L2_MBUS_FMT_UYVY8_2X8,
+	V4L2_MBUS_FMT_RGB565_2X8_LE,
+};
+
+/*
+ * General functions
+ */
+static struct ov2640_priv *to_ov2640(const struct i2c_client *client)
+{
+	return container_of(i2c_get_clientdata(client), struct ov2640_priv,
+			    subdev);
+}
+
+static int ov2640_write_array(struct i2c_client *client,
+			      const struct regval_list *vals)
+{
+	int ret;
+
+	while ((vals->reg_num != 0xff) || (vals->value != 0xff)) {
+		ret = i2c_smbus_write_byte_data(client,
+						vals->reg_num, vals->value);
+		dev_vdbg(&client->dev, "array: 0x%02x, 0x%02x",
+			 vals->reg_num, vals->value);
+
+		if (ret < 0)
+			return ret;
+		vals++;
+	}
+	return 0;
+}
+
+static int ov2640_mask_set(struct i2c_client *client,
+			   u8  reg, u8  mask, u8  set)
+{
+	s32 val = i2c_smbus_read_byte_data(client, reg);
+	if (val < 0)
+		return val;
+
+	val &= ~mask;
+	val |= set & mask;
+
+	dev_vdbg(&client->dev, "masks: 0x%02x, 0x%02x", reg, val);
+
+	return i2c_smbus_write_byte_data(client, reg, val);
+}
+
+static int ov2640_reset(struct i2c_client *client)
+{
+	int ret;
+	const struct regval_list reset_seq[] = {
+		{BANK_SEL, BANK_SEL_SENS},
+		{COM7, COM7_SRST},
+		ENDMARKER,
+	};
+
+	ret = ov2640_write_array(client, reset_seq);
+	if (ret)
+		goto err;
+
+	msleep(5);
+err:
+	dev_dbg(&client->dev, "%s: (ret %d)", __func__, ret);
+	return ret;
+}
+
+/*
+ * soc_camera_ops functions
+ */
+static int ov2640_s_stream(struct v4l2_subdev *sd, int enable)
+{
+	return 0;
+}
+
+static int ov2640_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct v4l2_subdev *sd =
+		&container_of(ctrl->handler, struct ov2640_priv, hdl)->subdev;
+	struct i2c_client  *client = v4l2_get_subdevdata(sd);
+	u8 val;
+
+	switch (ctrl->id) {
+	case V4L2_CID_VFLIP:
+		val = ctrl->val ? REG04_VFLIP_IMG : 0x00;
+		return ov2640_mask_set(client, REG04, REG04_VFLIP_IMG, val);
+	case V4L2_CID_HFLIP:
+		val = ctrl->val ? REG04_HFLIP_IMG : 0x00;
+		return ov2640_mask_set(client, REG04, REG04_HFLIP_IMG, val);
+	}
+
+	return -EINVAL;
+}
+
+static int ov2640_g_chip_ident(struct v4l2_subdev *sd,
+			       struct v4l2_dbg_chip_ident *id)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct ov2640_priv *priv = to_ov2640(client);
+
+	id->ident    = priv->model;
+	id->revision = 0;
+
+	return 0;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int ov2640_g_register(struct v4l2_subdev *sd,
+			     struct v4l2_dbg_register *reg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	int ret;
+
+	reg->size = 1;
+	if (reg->reg > 0xff)
+		return -EINVAL;
+
+	ret = i2c_smbus_read_byte_data(client, reg->reg);
+	if (ret < 0)
+		return ret;
+
+	reg->val = ret;
+
+	return 0;
+}
+
+static int ov2640_s_register(struct v4l2_subdev *sd,
+			     struct v4l2_dbg_register *reg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	if (reg->reg > 0xff ||
+	    reg->val > 0xff)
+		return -EINVAL;
+
+	return i2c_smbus_write_byte_data(client, reg->reg, reg->val);
+}
+#endif
+
+static int ov2640_s_power(struct v4l2_subdev *sd, int on)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+	return soc_camera_set_power(&client->dev, icl, on);
+}
+
+/* Select the nearest higher resolution for capture */
+static const struct ov2640_win_size *ov2640_select_win(u32 *width, u32 *height)
+{
+	int i, default_size = ARRAY_SIZE(ov2640_supported_win_sizes) - 1;
+
+	for (i = 0; i < ARRAY_SIZE(ov2640_supported_win_sizes); i++) {
+		if (ov2640_supported_win_sizes[i].width  >= *width &&
+		    ov2640_supported_win_sizes[i].height >= *height) {
+			*width = ov2640_supported_win_sizes[i].width;
+			*height = ov2640_supported_win_sizes[i].height;
+			return &ov2640_supported_win_sizes[i];
+		}
+	}
+
+	*width = ov2640_supported_win_sizes[default_size].width;
+	*height = ov2640_supported_win_sizes[default_size].height;
+	return &ov2640_supported_win_sizes[default_size];
+}
+
+static int ov2640_set_params(struct i2c_client *client, u32 *width, u32 *height,
+			     enum v4l2_mbus_pixelcode code)
+{
+	struct ov2640_priv       *priv = to_ov2640(client);
+	const struct regval_list *selected_cfmt_regs;
+	int ret;
+
+	/* select win */
+	priv->win = ov2640_select_win(width, height);
+
+	/* select format */
+	priv->cfmt_code = 0;
+	switch (code) {
+	case V4L2_MBUS_FMT_RGB565_2X8_LE:
+		dev_dbg(&client->dev, "%s: Selected cfmt RGB565", __func__);
+		selected_cfmt_regs = ov2640_rgb565_regs;
+		break;
+	default:
+	case V4L2_MBUS_FMT_UYVY8_2X8:
+		dev_dbg(&client->dev, "%s: Selected cfmt YUV422", __func__);
+		selected_cfmt_regs = ov2640_yuv422_regs;
+	}
+
+	/* reset hardware */
+	ov2640_reset(client);
+
+	/* initialize the sensor with default data */
+	dev_dbg(&client->dev, "%s: Init default", __func__);
+	ret = ov2640_write_array(client, ov2640_init_regs);
+	if (ret < 0)
+		goto err;
+
+	/* select preamble */
+	dev_dbg(&client->dev, "%s: Set size to %s", __func__, priv->win->name);
+	ret = ov2640_write_array(client, ov2640_size_change_preamble_regs);
+	if (ret < 0)
+		goto err;
+
+	/* set size win */
+	ret = ov2640_write_array(client, priv->win->regs);
+	if (ret < 0)
+		goto err;
+
+	/* cfmt preamble */
+	dev_dbg(&client->dev, "%s: Set cfmt", __func__);
+	ret = ov2640_write_array(client, ov2640_format_change_preamble_regs);
+	if (ret < 0)
+		goto err;
+
+	/* set cfmt */
+	ret = ov2640_write_array(client, selected_cfmt_regs);
+	if (ret < 0)
+		goto err;
+
+	priv->cfmt_code = code;
+	*width = priv->win->width;
+	*height = priv->win->height;
+
+	return 0;
+
+err:
+	dev_err(&client->dev, "%s: Error %d", __func__, ret);
+	ov2640_reset(client);
+	priv->win = NULL;
+
+	return ret;
+}
+
+static int ov2640_g_fmt(struct v4l2_subdev *sd,
+			struct v4l2_mbus_framefmt *mf)
+{
+	struct i2c_client  *client = v4l2_get_subdevdata(sd);
+	struct ov2640_priv *priv = to_ov2640(client);
+
+	if (!priv->win) {
+		u32 width = W_SVGA, height = H_SVGA;
+		priv->win = ov2640_select_win(&width, &height);
+		priv->cfmt_code = V4L2_MBUS_FMT_UYVY8_2X8;
+	}
+
+	mf->width	= priv->win->width;
+	mf->height	= priv->win->height;
+	mf->code	= priv->cfmt_code;
+
+	switch (mf->code) {
+	case V4L2_MBUS_FMT_RGB565_2X8_LE:
+		mf->colorspace = V4L2_COLORSPACE_SRGB;
+		break;
+	default:
+	case V4L2_MBUS_FMT_UYVY8_2X8:
+		mf->colorspace = V4L2_COLORSPACE_JPEG;
+	}
+	mf->field	= V4L2_FIELD_NONE;
+
+	return 0;
+}
+
+static int ov2640_s_fmt(struct v4l2_subdev *sd,
+			struct v4l2_mbus_framefmt *mf)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	int ret;
+
+
+	switch (mf->code) {
+	case V4L2_MBUS_FMT_RGB565_2X8_LE:
+		mf->colorspace = V4L2_COLORSPACE_SRGB;
+		break;
+	default:
+		mf->code = V4L2_MBUS_FMT_UYVY8_2X8;
+	case V4L2_MBUS_FMT_UYVY8_2X8:
+		mf->colorspace = V4L2_COLORSPACE_JPEG;
+	}
+
+	ret = ov2640_set_params(client, &mf->width, &mf->height, mf->code);
+
+	return ret;
+}
+
+static int ov2640_try_fmt(struct v4l2_subdev *sd,
+			  struct v4l2_mbus_framefmt *mf)
+{
+	const struct ov2640_win_size *win;
+
+	/*
+	 * select suitable win
+	 */
+	win = ov2640_select_win(&mf->width, &mf->height);
+
+	mf->field	= V4L2_FIELD_NONE;
+
+	switch (mf->code) {
+	case V4L2_MBUS_FMT_RGB565_2X8_LE:
+		mf->colorspace = V4L2_COLORSPACE_SRGB;
+		break;
+	default:
+		mf->code = V4L2_MBUS_FMT_UYVY8_2X8;
+	case V4L2_MBUS_FMT_UYVY8_2X8:
+		mf->colorspace = V4L2_COLORSPACE_JPEG;
+	}
+
+	return 0;
+}
+
+static int ov2640_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
+			   enum v4l2_mbus_pixelcode *code)
+{
+	if (index >= ARRAY_SIZE(ov2640_codes))
+		return -EINVAL;
+
+	*code = ov2640_codes[index];
+	return 0;
+}
+
+static int ov2640_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
+{
+	a->c.left	= 0;
+	a->c.top	= 0;
+	a->c.width	= W_UXGA;
+	a->c.height	= H_UXGA;
+	a->type		= V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+	return 0;
+}
+
+static int ov2640_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
+{
+	a->bounds.left			= 0;
+	a->bounds.top			= 0;
+	a->bounds.width			= W_UXGA;
+	a->bounds.height		= H_UXGA;
+	a->defrect			= a->bounds;
+	a->type				= V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	a->pixelaspect.numerator	= 1;
+	a->pixelaspect.denominator	= 1;
+
+	return 0;
+}
+
+static int ov2640_video_probe(struct i2c_client *client)
+{
+	struct ov2640_priv *priv = to_ov2640(client);
+	u8 pid, ver, midh, midl;
+	const char *devname;
+	int ret;
+
+	ret = ov2640_s_power(&priv->subdev, 1);
+	if (ret < 0)
+		return ret;
+
+	/*
+	 * check and show product ID and manufacturer ID
+	 */
+	i2c_smbus_write_byte_data(client, BANK_SEL, BANK_SEL_SENS);
+	pid  = i2c_smbus_read_byte_data(client, PID);
+	ver  = i2c_smbus_read_byte_data(client, VER);
+	midh = i2c_smbus_read_byte_data(client, MIDH);
+	midl = i2c_smbus_read_byte_data(client, MIDL);
+
+	switch (VERSION(pid, ver)) {
+	case PID_OV2640:
+		devname     = "ov2640";
+		priv->model = V4L2_IDENT_OV2640;
+		break;
+	default:
+		dev_err(&client->dev,
+			"Product ID error %x:%x\n", pid, ver);
+		ret = -ENODEV;
+		goto done;
+	}
+
+	dev_info(&client->dev,
+		 "%s Product ID %0x:%0x Manufacturer ID %x:%x\n",
+		 devname, pid, ver, midh, midl);
+
+	ret = v4l2_ctrl_handler_setup(&priv->hdl);
+
+done:
+	ov2640_s_power(&priv->subdev, 0);
+	return ret;
+}
+
+static const struct v4l2_ctrl_ops ov2640_ctrl_ops = {
+	.s_ctrl = ov2640_s_ctrl,
+};
+
+static struct v4l2_subdev_core_ops ov2640_subdev_core_ops = {
+	.g_chip_ident	= ov2640_g_chip_ident,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.g_register	= ov2640_g_register,
+	.s_register	= ov2640_s_register,
+#endif
+	.s_power	= ov2640_s_power,
+};
+
+static int ov2640_g_mbus_config(struct v4l2_subdev *sd,
+				struct v4l2_mbus_config *cfg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+	cfg->flags = V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_MASTER |
+		V4L2_MBUS_VSYNC_ACTIVE_HIGH | V4L2_MBUS_HSYNC_ACTIVE_HIGH |
+		V4L2_MBUS_DATA_ACTIVE_HIGH;
+	cfg->type = V4L2_MBUS_PARALLEL;
+	cfg->flags = soc_camera_apply_board_flags(icl, cfg);
+
+	return 0;
+}
+
+static struct v4l2_subdev_video_ops ov2640_subdev_video_ops = {
+	.s_stream	= ov2640_s_stream,
+	.g_mbus_fmt	= ov2640_g_fmt,
+	.s_mbus_fmt	= ov2640_s_fmt,
+	.try_mbus_fmt	= ov2640_try_fmt,
+	.cropcap	= ov2640_cropcap,
+	.g_crop		= ov2640_g_crop,
+	.enum_mbus_fmt	= ov2640_enum_fmt,
+	.g_mbus_config	= ov2640_g_mbus_config,
+};
+
+static struct v4l2_subdev_ops ov2640_subdev_ops = {
+	.core	= &ov2640_subdev_core_ops,
+	.video	= &ov2640_subdev_video_ops,
+};
+
+/*
+ * i2c_driver functions
+ */
+static int ov2640_probe(struct i2c_client *client,
+			const struct i2c_device_id *did)
+{
+	struct ov2640_priv	*priv;
+	struct soc_camera_link	*icl = soc_camera_i2c_to_link(client);
+	struct i2c_adapter	*adapter = to_i2c_adapter(client->dev.parent);
+	int			ret;
+
+	if (!icl) {
+		dev_err(&adapter->dev,
+			"OV2640: Missing platform_data for driver\n");
+		return -EINVAL;
+	}
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
+		dev_err(&adapter->dev,
+			"OV2640: I2C-Adapter doesn't support SMBUS\n");
+		return -EIO;
+	}
+
+	priv = kzalloc(sizeof(struct ov2640_priv), GFP_KERNEL);
+	if (!priv) {
+		dev_err(&adapter->dev,
+			"Failed to allocate memory for private data!\n");
+		return -ENOMEM;
+	}
+
+	v4l2_i2c_subdev_init(&priv->subdev, client, &ov2640_subdev_ops);
+	v4l2_ctrl_handler_init(&priv->hdl, 2);
+	v4l2_ctrl_new_std(&priv->hdl, &ov2640_ctrl_ops,
+			V4L2_CID_VFLIP, 0, 1, 1, 0);
+	v4l2_ctrl_new_std(&priv->hdl, &ov2640_ctrl_ops,
+			V4L2_CID_HFLIP, 0, 1, 1, 0);
+	priv->subdev.ctrl_handler = &priv->hdl;
+	if (priv->hdl.error) {
+		int err = priv->hdl.error;
+
+		kfree(priv);
+		return err;
+	}
+
+	ret = ov2640_video_probe(client);
+	if (ret) {
+		v4l2_ctrl_handler_free(&priv->hdl);
+		kfree(priv);
+	} else {
+		dev_info(&adapter->dev, "OV2640 Probed\n");
+	}
+
+	return ret;
+}
+
+static int ov2640_remove(struct i2c_client *client)
+{
+	struct ov2640_priv       *priv = to_ov2640(client);
+
+	v4l2_device_unregister_subdev(&priv->subdev);
+	v4l2_ctrl_handler_free(&priv->hdl);
+	kfree(priv);
+	return 0;
+}
+
+static const struct i2c_device_id ov2640_id[] = {
+	{ "ov2640", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, ov2640_id);
+
+static struct i2c_driver ov2640_i2c_driver = {
+	.driver = {
+		.name = "ov2640",
+	},
+	.probe    = ov2640_probe,
+	.remove   = ov2640_remove,
+	.id_table = ov2640_id,
+};
+
+module_i2c_driver(ov2640_i2c_driver);
+
+MODULE_DESCRIPTION("SoC Camera driver for Omni Vision 2640 sensor");
+MODULE_AUTHOR("Alberto Panizzo");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/i2c/soc_camera/ov5642.c b/drivers/media/i2c/soc_camera/ov5642.c
new file mode 100644
index 0000000..d886c0b
--- /dev/null
+++ b/drivers/media/i2c/soc_camera/ov5642.c
@@ -0,0 +1,1088 @@
+/*
+ * Driver for OV5642 CMOS Image Sensor from Omnivision
+ *
+ * Copyright (C) 2011, Bastian Hecht <hechtb@gmail.com>
+ *
+ * Based on Sony IMX074 Camera Driver
+ * Copyright (C) 2010, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+ *
+ * Based on Omnivision OV7670 Camera Driver
+ * Copyright (C) 2006-7 Jonathan Corbet <corbet@lwn.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/bitops.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/videodev2.h>
+#include <linux/module.h>
+#include <linux/v4l2-mediabus.h>
+
+#include <media/soc_camera.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-subdev.h>
+
+/* OV5642 registers */
+#define REG_CHIP_ID_HIGH		0x300a
+#define REG_CHIP_ID_LOW			0x300b
+
+#define REG_WINDOW_START_X_HIGH		0x3800
+#define REG_WINDOW_START_X_LOW		0x3801
+#define REG_WINDOW_START_Y_HIGH		0x3802
+#define REG_WINDOW_START_Y_LOW		0x3803
+#define REG_WINDOW_WIDTH_HIGH		0x3804
+#define REG_WINDOW_WIDTH_LOW		0x3805
+#define REG_WINDOW_HEIGHT_HIGH		0x3806
+#define REG_WINDOW_HEIGHT_LOW		0x3807
+#define REG_OUT_WIDTH_HIGH		0x3808
+#define REG_OUT_WIDTH_LOW		0x3809
+#define REG_OUT_HEIGHT_HIGH		0x380a
+#define REG_OUT_HEIGHT_LOW		0x380b
+#define REG_OUT_TOTAL_WIDTH_HIGH	0x380c
+#define REG_OUT_TOTAL_WIDTH_LOW		0x380d
+#define REG_OUT_TOTAL_HEIGHT_HIGH	0x380e
+#define REG_OUT_TOTAL_HEIGHT_LOW	0x380f
+#define REG_OUTPUT_FORMAT		0x4300
+#define REG_ISP_CTRL_01			0x5001
+#define REG_AVG_WINDOW_END_X_HIGH	0x5682
+#define REG_AVG_WINDOW_END_X_LOW	0x5683
+#define REG_AVG_WINDOW_END_Y_HIGH	0x5686
+#define REG_AVG_WINDOW_END_Y_LOW	0x5687
+
+/* active pixel array size */
+#define OV5642_SENSOR_SIZE_X	2592
+#define OV5642_SENSOR_SIZE_Y	1944
+
+/*
+ * About OV5642 resolution, cropping and binning:
+ * This sensor supports it all, at least in the feature description.
+ * Unfortunately, no combination of appropriate registers settings could make
+ * the chip work the intended way. As it works with predefined register lists,
+ * some undocumented registers are presumably changed there to achieve their
+ * goals.
+ * This driver currently only works for resolutions up to 720 lines with a
+ * 1:1 scale. Hopefully these restrictions will be removed in the future.
+ */
+#define OV5642_MAX_WIDTH	OV5642_SENSOR_SIZE_X
+#define OV5642_MAX_HEIGHT	720
+
+/* default sizes */
+#define OV5642_DEFAULT_WIDTH	1280
+#define OV5642_DEFAULT_HEIGHT	OV5642_MAX_HEIGHT
+
+/* minimum extra blanking */
+#define BLANKING_EXTRA_WIDTH		500
+#define BLANKING_EXTRA_HEIGHT		20
+
+/*
+ * the sensor's autoexposure is buggy when setting total_height low.
+ * It tries to expose longer than 1 frame period without taking care of it
+ * and this leads to weird output. So we set 1000 lines as minimum.
+ */
+#define BLANKING_MIN_HEIGHT		1000
+
+struct regval_list {
+	u16 reg_num;
+	u8 value;
+};
+
+static struct regval_list ov5642_default_regs_init[] = {
+	{ 0x3103, 0x93 },
+	{ 0x3008, 0x82 },
+	{ 0x3017, 0x7f },
+	{ 0x3018, 0xfc },
+	{ 0x3810, 0xc2 },
+	{ 0x3615, 0xf0 },
+	{ 0x3000, 0x0  },
+	{ 0x3001, 0x0  },
+	{ 0x3002, 0x0  },
+	{ 0x3003, 0x0  },
+	{ 0x3004, 0xff },
+	{ 0x3030, 0x2b },
+	{ 0x3011, 0x8  },
+	{ 0x3010, 0x10 },
+	{ 0x3604, 0x60 },
+	{ 0x3622, 0x60 },
+	{ 0x3621, 0x9  },
+	{ 0x3709, 0x0  },
+	{ 0x4000, 0x21 },
+	{ 0x401d, 0x22 },
+	{ 0x3600, 0x54 },
+	{ 0x3605, 0x4  },
+	{ 0x3606, 0x3f },
+	{ 0x3c01, 0x80 },
+	{ 0x300d, 0x22 },
+	{ 0x3623, 0x22 },
+	{ 0x5000, 0x4f },
+	{ 0x5020, 0x4  },
+	{ 0x5181, 0x79 },
+	{ 0x5182, 0x0  },
+	{ 0x5185, 0x22 },
+	{ 0x5197, 0x1  },
+	{ 0x5500, 0xa  },
+	{ 0x5504, 0x0  },
+	{ 0x5505, 0x7f },
+	{ 0x5080, 0x8  },
+	{ 0x300e, 0x18 },
+	{ 0x4610, 0x0  },
+	{ 0x471d, 0x5  },
+	{ 0x4708, 0x6  },
+	{ 0x370c, 0xa0 },
+	{ 0x5687, 0x94 },
+	{ 0x501f, 0x0  },
+	{ 0x5000, 0x4f },
+	{ 0x5001, 0xcf },
+	{ 0x4300, 0x30 },
+	{ 0x4300, 0x30 },
+	{ 0x460b, 0x35 },
+	{ 0x471d, 0x0  },
+	{ 0x3002, 0xc  },
+	{ 0x3002, 0x0  },
+	{ 0x4713, 0x3  },
+	{ 0x471c, 0x50 },
+	{ 0x4721, 0x2  },
+	{ 0x4402, 0x90 },
+	{ 0x460c, 0x22 },
+	{ 0x3815, 0x44 },
+	{ 0x3503, 0x7  },
+	{ 0x3501, 0x73 },
+	{ 0x3502, 0x80 },
+	{ 0x350b, 0x0  },
+	{ 0x3818, 0xc8 },
+	{ 0x3824, 0x11 },
+	{ 0x3a00, 0x78 },
+	{ 0x3a1a, 0x4  },
+	{ 0x3a13, 0x30 },
+	{ 0x3a18, 0x0  },
+	{ 0x3a19, 0x7c },
+	{ 0x3a08, 0x12 },
+	{ 0x3a09, 0xc0 },
+	{ 0x3a0a, 0xf  },
+	{ 0x3a0b, 0xa0 },
+	{ 0x350c, 0x7  },
+	{ 0x350d, 0xd0 },
+	{ 0x3a0d, 0x8  },
+	{ 0x3a0e, 0x6  },
+	{ 0x3500, 0x0  },
+	{ 0x3501, 0x0  },
+	{ 0x3502, 0x0  },
+	{ 0x350a, 0x0  },
+	{ 0x350b, 0x0  },
+	{ 0x3503, 0x0  },
+	{ 0x3a0f, 0x3c },
+	{ 0x3a10, 0x32 },
+	{ 0x3a1b, 0x3c },
+	{ 0x3a1e, 0x32 },
+	{ 0x3a11, 0x80 },
+	{ 0x3a1f, 0x20 },
+	{ 0x3030, 0x2b },
+	{ 0x3a02, 0x0  },
+	{ 0x3a03, 0x7d },
+	{ 0x3a04, 0x0  },
+	{ 0x3a14, 0x0  },
+	{ 0x3a15, 0x7d },
+	{ 0x3a16, 0x0  },
+	{ 0x3a00, 0x78 },
+	{ 0x3a08, 0x9  },
+	{ 0x3a09, 0x60 },
+	{ 0x3a0a, 0x7  },
+	{ 0x3a0b, 0xd0 },
+	{ 0x3a0d, 0x10 },
+	{ 0x3a0e, 0xd  },
+	{ 0x4407, 0x4  },
+	{ 0x5193, 0x70 },
+	{ 0x589b, 0x0  },
+	{ 0x589a, 0xc0 },
+	{ 0x401e, 0x20 },
+	{ 0x4001, 0x42 },
+	{ 0x401c, 0x6  },
+	{ 0x3825, 0xac },
+	{ 0x3827, 0xc  },
+	{ 0x528a, 0x1  },
+	{ 0x528b, 0x4  },
+	{ 0x528c, 0x8  },
+	{ 0x528d, 0x10 },
+	{ 0x528e, 0x20 },
+	{ 0x528f, 0x28 },
+	{ 0x5290, 0x30 },
+	{ 0x5292, 0x0  },
+	{ 0x5293, 0x1  },
+	{ 0x5294, 0x0  },
+	{ 0x5295, 0x4  },
+	{ 0x5296, 0x0  },
+	{ 0x5297, 0x8  },
+	{ 0x5298, 0x0  },
+	{ 0x5299, 0x10 },
+	{ 0x529a, 0x0  },
+	{ 0x529b, 0x20 },
+	{ 0x529c, 0x0  },
+	{ 0x529d, 0x28 },
+	{ 0x529e, 0x0  },
+	{ 0x529f, 0x30 },
+	{ 0x5282, 0x0  },
+	{ 0x5300, 0x0  },
+	{ 0x5301, 0x20 },
+	{ 0x5302, 0x0  },
+	{ 0x5303, 0x7c },
+	{ 0x530c, 0x0  },
+	{ 0x530d, 0xc  },
+	{ 0x530e, 0x20 },
+	{ 0x530f, 0x80 },
+	{ 0x5310, 0x20 },
+	{ 0x5311, 0x80 },
+	{ 0x5308, 0x20 },
+	{ 0x5309, 0x40 },
+	{ 0x5304, 0x0  },
+	{ 0x5305, 0x30 },
+	{ 0x5306, 0x0  },
+	{ 0x5307, 0x80 },
+	{ 0x5314, 0x8  },
+	{ 0x5315, 0x20 },
+	{ 0x5319, 0x30 },
+	{ 0x5316, 0x10 },
+	{ 0x5317, 0x0  },
+	{ 0x5318, 0x2  },
+	{ 0x5380, 0x1  },
+	{ 0x5381, 0x0  },
+	{ 0x5382, 0x0  },
+	{ 0x5383, 0x4e },
+	{ 0x5384, 0x0  },
+	{ 0x5385, 0xf  },
+	{ 0x5386, 0x0  },
+	{ 0x5387, 0x0  },
+	{ 0x5388, 0x1  },
+	{ 0x5389, 0x15 },
+	{ 0x538a, 0x0  },
+	{ 0x538b, 0x31 },
+	{ 0x538c, 0x0  },
+	{ 0x538d, 0x0  },
+	{ 0x538e, 0x0  },
+	{ 0x538f, 0xf  },
+	{ 0x5390, 0x0  },
+	{ 0x5391, 0xab },
+	{ 0x5392, 0x0  },
+	{ 0x5393, 0xa2 },
+	{ 0x5394, 0x8  },
+	{ 0x5480, 0x14 },
+	{ 0x5481, 0x21 },
+	{ 0x5482, 0x36 },
+	{ 0x5483, 0x57 },
+	{ 0x5484, 0x65 },
+	{ 0x5485, 0x71 },
+	{ 0x5486, 0x7d },
+	{ 0x5487, 0x87 },
+	{ 0x5488, 0x91 },
+	{ 0x5489, 0x9a },
+	{ 0x548a, 0xaa },
+	{ 0x548b, 0xb8 },
+	{ 0x548c, 0xcd },
+	{ 0x548d, 0xdd },
+	{ 0x548e, 0xea },
+	{ 0x548f, 0x1d },
+	{ 0x5490, 0x5  },
+	{ 0x5491, 0x0  },
+	{ 0x5492, 0x4  },
+	{ 0x5493, 0x20 },
+	{ 0x5494, 0x3  },
+	{ 0x5495, 0x60 },
+	{ 0x5496, 0x2  },
+	{ 0x5497, 0xb8 },
+	{ 0x5498, 0x2  },
+	{ 0x5499, 0x86 },
+	{ 0x549a, 0x2  },
+	{ 0x549b, 0x5b },
+	{ 0x549c, 0x2  },
+	{ 0x549d, 0x3b },
+	{ 0x549e, 0x2  },
+	{ 0x549f, 0x1c },
+	{ 0x54a0, 0x2  },
+	{ 0x54a1, 0x4  },
+	{ 0x54a2, 0x1  },
+	{ 0x54a3, 0xed },
+	{ 0x54a4, 0x1  },
+	{ 0x54a5, 0xc5 },
+	{ 0x54a6, 0x1  },
+	{ 0x54a7, 0xa5 },
+	{ 0x54a8, 0x1  },
+	{ 0x54a9, 0x6c },
+	{ 0x54aa, 0x1  },
+	{ 0x54ab, 0x41 },
+	{ 0x54ac, 0x1  },
+	{ 0x54ad, 0x20 },
+	{ 0x54ae, 0x0  },
+	{ 0x54af, 0x16 },
+	{ 0x54b0, 0x1  },
+	{ 0x54b1, 0x20 },
+	{ 0x54b2, 0x0  },
+	{ 0x54b3, 0x10 },
+	{ 0x54b4, 0x0  },
+	{ 0x54b5, 0xf0 },
+	{ 0x54b6, 0x0  },
+	{ 0x54b7, 0xdf },
+	{ 0x5402, 0x3f },
+	{ 0x5403, 0x0  },
+	{ 0x3406, 0x0  },
+	{ 0x5180, 0xff },
+	{ 0x5181, 0x52 },
+	{ 0x5182, 0x11 },
+	{ 0x5183, 0x14 },
+	{ 0x5184, 0x25 },
+	{ 0x5185, 0x24 },
+	{ 0x5186, 0x6  },
+	{ 0x5187, 0x8  },
+	{ 0x5188, 0x8  },
+	{ 0x5189, 0x7c },
+	{ 0x518a, 0x60 },
+	{ 0x518b, 0xb2 },
+	{ 0x518c, 0xb2 },
+	{ 0x518d, 0x44 },
+	{ 0x518e, 0x3d },
+	{ 0x518f, 0x58 },
+	{ 0x5190, 0x46 },
+	{ 0x5191, 0xf8 },
+	{ 0x5192, 0x4  },
+	{ 0x5193, 0x70 },
+	{ 0x5194, 0xf0 },
+	{ 0x5195, 0xf0 },
+	{ 0x5196, 0x3  },
+	{ 0x5197, 0x1  },
+	{ 0x5198, 0x4  },
+	{ 0x5199, 0x12 },
+	{ 0x519a, 0x4  },
+	{ 0x519b, 0x0  },
+	{ 0x519c, 0x6  },
+	{ 0x519d, 0x82 },
+	{ 0x519e, 0x0  },
+	{ 0x5025, 0x80 },
+	{ 0x3a0f, 0x38 },
+	{ 0x3a10, 0x30 },
+	{ 0x3a1b, 0x3a },
+	{ 0x3a1e, 0x2e },
+	{ 0x3a11, 0x60 },
+	{ 0x3a1f, 0x10 },
+	{ 0x5688, 0xa6 },
+	{ 0x5689, 0x6a },
+	{ 0x568a, 0xea },
+	{ 0x568b, 0xae },
+	{ 0x568c, 0xa6 },
+	{ 0x568d, 0x6a },
+	{ 0x568e, 0x62 },
+	{ 0x568f, 0x26 },
+	{ 0x5583, 0x40 },
+	{ 0x5584, 0x40 },
+	{ 0x5580, 0x2  },
+	{ 0x5000, 0xcf },
+	{ 0x5800, 0x27 },
+	{ 0x5801, 0x19 },
+	{ 0x5802, 0x12 },
+	{ 0x5803, 0xf  },
+	{ 0x5804, 0x10 },
+	{ 0x5805, 0x15 },
+	{ 0x5806, 0x1e },
+	{ 0x5807, 0x2f },
+	{ 0x5808, 0x15 },
+	{ 0x5809, 0xd  },
+	{ 0x580a, 0xa  },
+	{ 0x580b, 0x9  },
+	{ 0x580c, 0xa  },
+	{ 0x580d, 0xc  },
+	{ 0x580e, 0x12 },
+	{ 0x580f, 0x19 },
+	{ 0x5810, 0xb  },
+	{ 0x5811, 0x7  },
+	{ 0x5812, 0x4  },
+	{ 0x5813, 0x3  },
+	{ 0x5814, 0x3  },
+	{ 0x5815, 0x6  },
+	{ 0x5816, 0xa  },
+	{ 0x5817, 0xf  },
+	{ 0x5818, 0xa  },
+	{ 0x5819, 0x5  },
+	{ 0x581a, 0x1  },
+	{ 0x581b, 0x0  },
+	{ 0x581c, 0x0  },
+	{ 0x581d, 0x3  },
+	{ 0x581e, 0x8  },
+	{ 0x581f, 0xc  },
+	{ 0x5820, 0xa  },
+	{ 0x5821, 0x5  },
+	{ 0x5822, 0x1  },
+	{ 0x5823, 0x0  },
+	{ 0x5824, 0x0  },
+	{ 0x5825, 0x3  },
+	{ 0x5826, 0x8  },
+	{ 0x5827, 0xc  },
+	{ 0x5828, 0xe  },
+	{ 0x5829, 0x8  },
+	{ 0x582a, 0x6  },
+	{ 0x582b, 0x4  },
+	{ 0x582c, 0x5  },
+	{ 0x582d, 0x7  },
+	{ 0x582e, 0xb  },
+	{ 0x582f, 0x12 },
+	{ 0x5830, 0x18 },
+	{ 0x5831, 0x10 },
+	{ 0x5832, 0xc  },
+	{ 0x5833, 0xa  },
+	{ 0x5834, 0xb  },
+	{ 0x5835, 0xe  },
+	{ 0x5836, 0x15 },
+	{ 0x5837, 0x19 },
+	{ 0x5838, 0x32 },
+	{ 0x5839, 0x1f },
+	{ 0x583a, 0x18 },
+	{ 0x583b, 0x16 },
+	{ 0x583c, 0x17 },
+	{ 0x583d, 0x1e },
+	{ 0x583e, 0x26 },
+	{ 0x583f, 0x53 },
+	{ 0x5840, 0x10 },
+	{ 0x5841, 0xf  },
+	{ 0x5842, 0xd  },
+	{ 0x5843, 0xc  },
+	{ 0x5844, 0xe  },
+	{ 0x5845, 0x9  },
+	{ 0x5846, 0x11 },
+	{ 0x5847, 0x10 },
+	{ 0x5848, 0x10 },
+	{ 0x5849, 0x10 },
+	{ 0x584a, 0x10 },
+	{ 0x584b, 0xe  },
+	{ 0x584c, 0x10 },
+	{ 0x584d, 0x10 },
+	{ 0x584e, 0x11 },
+	{ 0x584f, 0x10 },
+	{ 0x5850, 0xf  },
+	{ 0x5851, 0xc  },
+	{ 0x5852, 0xf  },
+	{ 0x5853, 0x10 },
+	{ 0x5854, 0x10 },
+	{ 0x5855, 0xf  },
+	{ 0x5856, 0xe  },
+	{ 0x5857, 0xb  },
+	{ 0x5858, 0x10 },
+	{ 0x5859, 0xd  },
+	{ 0x585a, 0xd  },
+	{ 0x585b, 0xc  },
+	{ 0x585c, 0xc  },
+	{ 0x585d, 0xc  },
+	{ 0x585e, 0xb  },
+	{ 0x585f, 0xc  },
+	{ 0x5860, 0xc  },
+	{ 0x5861, 0xc  },
+	{ 0x5862, 0xd  },
+	{ 0x5863, 0x8  },
+	{ 0x5864, 0x11 },
+	{ 0x5865, 0x18 },
+	{ 0x5866, 0x18 },
+	{ 0x5867, 0x19 },
+	{ 0x5868, 0x17 },
+	{ 0x5869, 0x19 },
+	{ 0x586a, 0x16 },
+	{ 0x586b, 0x13 },
+	{ 0x586c, 0x13 },
+	{ 0x586d, 0x12 },
+	{ 0x586e, 0x13 },
+	{ 0x586f, 0x16 },
+	{ 0x5870, 0x14 },
+	{ 0x5871, 0x12 },
+	{ 0x5872, 0x10 },
+	{ 0x5873, 0x11 },
+	{ 0x5874, 0x11 },
+	{ 0x5875, 0x16 },
+	{ 0x5876, 0x14 },
+	{ 0x5877, 0x11 },
+	{ 0x5878, 0x10 },
+	{ 0x5879, 0xf  },
+	{ 0x587a, 0x10 },
+	{ 0x587b, 0x14 },
+	{ 0x587c, 0x13 },
+	{ 0x587d, 0x12 },
+	{ 0x587e, 0x11 },
+	{ 0x587f, 0x11 },
+	{ 0x5880, 0x12 },
+	{ 0x5881, 0x15 },
+	{ 0x5882, 0x14 },
+	{ 0x5883, 0x15 },
+	{ 0x5884, 0x15 },
+	{ 0x5885, 0x15 },
+	{ 0x5886, 0x13 },
+	{ 0x5887, 0x17 },
+	{ 0x3710, 0x10 },
+	{ 0x3632, 0x51 },
+	{ 0x3702, 0x10 },
+	{ 0x3703, 0xb2 },
+	{ 0x3704, 0x18 },
+	{ 0x370b, 0x40 },
+	{ 0x370d, 0x3  },
+	{ 0x3631, 0x1  },
+	{ 0x3632, 0x52 },
+	{ 0x3606, 0x24 },
+	{ 0x3620, 0x96 },
+	{ 0x5785, 0x7  },
+	{ 0x3a13, 0x30 },
+	{ 0x3600, 0x52 },
+	{ 0x3604, 0x48 },
+	{ 0x3606, 0x1b },
+	{ 0x370d, 0xb  },
+	{ 0x370f, 0xc0 },
+	{ 0x3709, 0x1  },
+	{ 0x3823, 0x0  },
+	{ 0x5007, 0x0  },
+	{ 0x5009, 0x0  },
+	{ 0x5011, 0x0  },
+	{ 0x5013, 0x0  },
+	{ 0x519e, 0x0  },
+	{ 0x5086, 0x0  },
+	{ 0x5087, 0x0  },
+	{ 0x5088, 0x0  },
+	{ 0x5089, 0x0  },
+	{ 0x302b, 0x0  },
+	{ 0x3503, 0x7  },
+	{ 0x3011, 0x8  },
+	{ 0x350c, 0x2  },
+	{ 0x350d, 0xe4 },
+	{ 0x3621, 0xc9 },
+	{ 0x370a, 0x81 },
+	{ 0xffff, 0xff },
+};
+
+static struct regval_list ov5642_default_regs_finalise[] = {
+	{ 0x3810, 0xc2 },
+	{ 0x3818, 0xc9 },
+	{ 0x381c, 0x10 },
+	{ 0x381d, 0xa0 },
+	{ 0x381e, 0x5  },
+	{ 0x381f, 0xb0 },
+	{ 0x3820, 0x0  },
+	{ 0x3821, 0x0  },
+	{ 0x3824, 0x11 },
+	{ 0x3a08, 0x1b },
+	{ 0x3a09, 0xc0 },
+	{ 0x3a0a, 0x17 },
+	{ 0x3a0b, 0x20 },
+	{ 0x3a0d, 0x2  },
+	{ 0x3a0e, 0x1  },
+	{ 0x401c, 0x4  },
+	{ 0x5682, 0x5  },
+	{ 0x5683, 0x0  },
+	{ 0x5686, 0x2  },
+	{ 0x5687, 0xcc },
+	{ 0x5001, 0x4f },
+	{ 0x589b, 0x6  },
+	{ 0x589a, 0xc5 },
+	{ 0x3503, 0x0  },
+	{ 0x460c, 0x20 },
+	{ 0x460b, 0x37 },
+	{ 0x471c, 0xd0 },
+	{ 0x471d, 0x5  },
+	{ 0x3815, 0x1  },
+	{ 0x3818, 0xc1 },
+	{ 0x501f, 0x0  },
+	{ 0x5002, 0xe0 },
+	{ 0x4300, 0x32 }, /* UYVY */
+	{ 0x3002, 0x1c },
+	{ 0x4800, 0x14 },
+	{ 0x4801, 0xf  },
+	{ 0x3007, 0x3b },
+	{ 0x300e, 0x4  },
+	{ 0x4803, 0x50 },
+	{ 0x3815, 0x1  },
+	{ 0x4713, 0x2  },
+	{ 0x4842, 0x1  },
+	{ 0x300f, 0xe  },
+	{ 0x3003, 0x3  },
+	{ 0x3003, 0x1  },
+	{ 0xffff, 0xff },
+};
+
+struct ov5642_datafmt {
+	enum v4l2_mbus_pixelcode	code;
+	enum v4l2_colorspace		colorspace;
+};
+
+struct ov5642 {
+	struct v4l2_subdev		subdev;
+	const struct ov5642_datafmt	*fmt;
+	struct v4l2_rect                crop_rect;
+
+	/* blanking information */
+	int total_width;
+	int total_height;
+};
+
+static const struct ov5642_datafmt ov5642_colour_fmts[] = {
+	{V4L2_MBUS_FMT_UYVY8_2X8, V4L2_COLORSPACE_JPEG},
+};
+
+static struct ov5642 *to_ov5642(const struct i2c_client *client)
+{
+	return container_of(i2c_get_clientdata(client), struct ov5642, subdev);
+}
+
+/* Find a data format by a pixel code in an array */
+static const struct ov5642_datafmt
+			*ov5642_find_datafmt(enum v4l2_mbus_pixelcode code)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(ov5642_colour_fmts); i++)
+		if (ov5642_colour_fmts[i].code == code)
+			return ov5642_colour_fmts + i;
+
+	return NULL;
+}
+
+static int reg_read(struct i2c_client *client, u16 reg, u8 *val)
+{
+	int ret;
+	/* We have 16-bit i2c addresses - care for endianess */
+	unsigned char data[2] = { reg >> 8, reg & 0xff };
+
+	ret = i2c_master_send(client, data, 2);
+	if (ret < 2) {
+		dev_err(&client->dev, "%s: i2c read error, reg: %x\n",
+			__func__, reg);
+		return ret < 0 ? ret : -EIO;
+	}
+
+	ret = i2c_master_recv(client, val, 1);
+	if (ret < 1) {
+		dev_err(&client->dev, "%s: i2c read error, reg: %x\n",
+				__func__, reg);
+		return ret < 0 ? ret : -EIO;
+	}
+	return 0;
+}
+
+static int reg_write(struct i2c_client *client, u16 reg, u8 val)
+{
+	int ret;
+	unsigned char data[3] = { reg >> 8, reg & 0xff, val };
+
+	ret = i2c_master_send(client, data, 3);
+	if (ret < 3) {
+		dev_err(&client->dev, "%s: i2c write error, reg: %x\n",
+			__func__, reg);
+		return ret < 0 ? ret : -EIO;
+	}
+
+	return 0;
+}
+
+/*
+ * convenience function to write 16 bit register values that are split up
+ * into two consecutive high and low parts
+ */
+static int reg_write16(struct i2c_client *client, u16 reg, u16 val16)
+{
+	int ret;
+
+	ret = reg_write(client, reg, val16 >> 8);
+	if (ret)
+		return ret;
+	return reg_write(client, reg + 1, val16 & 0x00ff);
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int ov5642_get_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	int ret;
+	u8 val;
+
+	if (reg->reg & ~0xffff)
+		return -EINVAL;
+
+	reg->size = 1;
+
+	ret = reg_read(client, reg->reg, &val);
+	if (!ret)
+		reg->val = (__u64)val;
+
+	return ret;
+}
+
+static int ov5642_set_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	if (reg->reg & ~0xffff || reg->val & ~0xff)
+		return -EINVAL;
+
+	return reg_write(client, reg->reg, reg->val);
+}
+#endif
+
+static int ov5642_write_array(struct i2c_client *client,
+				struct regval_list *vals)
+{
+	while (vals->reg_num != 0xffff || vals->value != 0xff) {
+		int ret = reg_write(client, vals->reg_num, vals->value);
+		if (ret < 0)
+			return ret;
+		vals++;
+	}
+	dev_dbg(&client->dev, "Register list loaded\n");
+	return 0;
+}
+
+static int ov5642_set_resolution(struct v4l2_subdev *sd)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct ov5642 *priv = to_ov5642(client);
+	int width = priv->crop_rect.width;
+	int height = priv->crop_rect.height;
+	int total_width = priv->total_width;
+	int total_height = priv->total_height;
+	int start_x = (OV5642_SENSOR_SIZE_X - width) / 2;
+	int start_y = (OV5642_SENSOR_SIZE_Y - height) / 2;
+	int ret;
+
+	/*
+	 * This should set the starting point for cropping.
+	 * Doesn't work so far.
+	 */
+	ret = reg_write16(client, REG_WINDOW_START_X_HIGH, start_x);
+	if (!ret)
+		ret = reg_write16(client, REG_WINDOW_START_Y_HIGH, start_y);
+	if (!ret) {
+		priv->crop_rect.left = start_x;
+		priv->crop_rect.top = start_y;
+	}
+
+	if (!ret)
+		ret = reg_write16(client, REG_WINDOW_WIDTH_HIGH, width);
+	if (!ret)
+		ret = reg_write16(client, REG_WINDOW_HEIGHT_HIGH, height);
+	if (ret)
+		return ret;
+	priv->crop_rect.width = width;
+	priv->crop_rect.height = height;
+
+	/* Set the output window size. Only 1:1 scale is supported so far. */
+	ret = reg_write16(client, REG_OUT_WIDTH_HIGH, width);
+	if (!ret)
+		ret = reg_write16(client, REG_OUT_HEIGHT_HIGH, height);
+
+	/* Total width = output size + blanking */
+	if (!ret)
+		ret = reg_write16(client, REG_OUT_TOTAL_WIDTH_HIGH, total_width);
+	if (!ret)
+		ret = reg_write16(client, REG_OUT_TOTAL_HEIGHT_HIGH, total_height);
+
+	/* Sets the window for AWB calculations */
+	if (!ret)
+		ret = reg_write16(client, REG_AVG_WINDOW_END_X_HIGH, width);
+	if (!ret)
+		ret = reg_write16(client, REG_AVG_WINDOW_END_Y_HIGH, height);
+
+	return ret;
+}
+
+static int ov5642_try_fmt(struct v4l2_subdev *sd,
+			  struct v4l2_mbus_framefmt *mf)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct ov5642 *priv = to_ov5642(client);
+	const struct ov5642_datafmt *fmt = ov5642_find_datafmt(mf->code);
+
+	mf->width = priv->crop_rect.width;
+	mf->height = priv->crop_rect.height;
+
+	if (!fmt) {
+		mf->code	= ov5642_colour_fmts[0].code;
+		mf->colorspace	= ov5642_colour_fmts[0].colorspace;
+	}
+
+	mf->field	= V4L2_FIELD_NONE;
+
+	return 0;
+}
+
+static int ov5642_s_fmt(struct v4l2_subdev *sd,
+			struct v4l2_mbus_framefmt *mf)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct ov5642 *priv = to_ov5642(client);
+
+	/* MIPI CSI could have changed the format, double-check */
+	if (!ov5642_find_datafmt(mf->code))
+		return -EINVAL;
+
+	ov5642_try_fmt(sd, mf);
+	priv->fmt = ov5642_find_datafmt(mf->code);
+
+	return 0;
+}
+
+static int ov5642_g_fmt(struct v4l2_subdev *sd,
+			struct v4l2_mbus_framefmt *mf)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct ov5642 *priv = to_ov5642(client);
+
+	const struct ov5642_datafmt *fmt = priv->fmt;
+
+	mf->code	= fmt->code;
+	mf->colorspace	= fmt->colorspace;
+	mf->width	= priv->crop_rect.width;
+	mf->height	= priv->crop_rect.height;
+	mf->field	= V4L2_FIELD_NONE;
+
+	return 0;
+}
+
+static int ov5642_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
+			   enum v4l2_mbus_pixelcode *code)
+{
+	if (index >= ARRAY_SIZE(ov5642_colour_fmts))
+		return -EINVAL;
+
+	*code = ov5642_colour_fmts[index].code;
+	return 0;
+}
+
+static int ov5642_g_chip_ident(struct v4l2_subdev *sd,
+			       struct v4l2_dbg_chip_ident *id)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
+		return -EINVAL;
+
+	if (id->match.addr != client->addr)
+		return -ENODEV;
+
+	id->ident	= V4L2_IDENT_OV5642;
+	id->revision	= 0;
+
+	return 0;
+}
+
+static int ov5642_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct ov5642 *priv = to_ov5642(client);
+	struct v4l2_rect *rect = &a->c;
+	int ret;
+
+	v4l_bound_align_image(&rect->width, 48, OV5642_MAX_WIDTH, 1,
+			      &rect->height, 32, OV5642_MAX_HEIGHT, 1, 0);
+
+	priv->crop_rect.width	= rect->width;
+	priv->crop_rect.height	= rect->height;
+	priv->total_width	= rect->width + BLANKING_EXTRA_WIDTH;
+	priv->total_height	= max_t(int, rect->height +
+							BLANKING_EXTRA_HEIGHT,
+							BLANKING_MIN_HEIGHT);
+	priv->crop_rect.width		= rect->width;
+	priv->crop_rect.height		= rect->height;
+
+	ret = ov5642_write_array(client, ov5642_default_regs_init);
+	if (!ret)
+		ret = ov5642_set_resolution(sd);
+	if (!ret)
+		ret = ov5642_write_array(client, ov5642_default_regs_finalise);
+
+	return ret;
+}
+
+static int ov5642_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct ov5642 *priv = to_ov5642(client);
+	struct v4l2_rect *rect = &a->c;
+
+	if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
+	*rect = priv->crop_rect;
+
+	return 0;
+}
+
+static int ov5642_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
+{
+	a->bounds.left			= 0;
+	a->bounds.top			= 0;
+	a->bounds.width			= OV5642_MAX_WIDTH;
+	a->bounds.height		= OV5642_MAX_HEIGHT;
+	a->defrect			= a->bounds;
+	a->type				= V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	a->pixelaspect.numerator	= 1;
+	a->pixelaspect.denominator	= 1;
+
+	return 0;
+}
+
+static int ov5642_g_mbus_config(struct v4l2_subdev *sd,
+				struct v4l2_mbus_config *cfg)
+{
+	cfg->type = V4L2_MBUS_CSI2;
+	cfg->flags = V4L2_MBUS_CSI2_2_LANE | V4L2_MBUS_CSI2_CHANNEL_0 |
+					V4L2_MBUS_CSI2_CONTINUOUS_CLOCK;
+
+	return 0;
+}
+
+static int ov5642_s_power(struct v4l2_subdev *sd, int on)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+	int ret;
+
+	if (!on)
+		return soc_camera_power_off(&client->dev, icl);
+
+	ret = soc_camera_power_on(&client->dev, icl);
+	if (ret < 0)
+		return ret;
+
+	ret = ov5642_write_array(client, ov5642_default_regs_init);
+	if (!ret)
+		ret = ov5642_set_resolution(sd);
+	if (!ret)
+		ret = ov5642_write_array(client, ov5642_default_regs_finalise);
+
+	return ret;
+}
+
+static struct v4l2_subdev_video_ops ov5642_subdev_video_ops = {
+	.s_mbus_fmt	= ov5642_s_fmt,
+	.g_mbus_fmt	= ov5642_g_fmt,
+	.try_mbus_fmt	= ov5642_try_fmt,
+	.enum_mbus_fmt	= ov5642_enum_fmt,
+	.s_crop		= ov5642_s_crop,
+	.g_crop		= ov5642_g_crop,
+	.cropcap	= ov5642_cropcap,
+	.g_mbus_config	= ov5642_g_mbus_config,
+};
+
+static struct v4l2_subdev_core_ops ov5642_subdev_core_ops = {
+	.s_power	= ov5642_s_power,
+	.g_chip_ident	= ov5642_g_chip_ident,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.g_register	= ov5642_get_register,
+	.s_register	= ov5642_set_register,
+#endif
+};
+
+static struct v4l2_subdev_ops ov5642_subdev_ops = {
+	.core	= &ov5642_subdev_core_ops,
+	.video	= &ov5642_subdev_video_ops,
+};
+
+static int ov5642_video_probe(struct i2c_client *client)
+{
+	struct v4l2_subdev *subdev = i2c_get_clientdata(client);
+	int ret;
+	u8 id_high, id_low;
+	u16 id;
+
+	ret = ov5642_s_power(subdev, 1);
+	if (ret < 0)
+		return ret;
+
+	/* Read sensor Model ID */
+	ret = reg_read(client, REG_CHIP_ID_HIGH, &id_high);
+	if (ret < 0)
+		goto done;
+
+	id = id_high << 8;
+
+	ret = reg_read(client, REG_CHIP_ID_LOW, &id_low);
+	if (ret < 0)
+		goto done;
+
+	id |= id_low;
+
+	dev_info(&client->dev, "Chip ID 0x%04x detected\n", id);
+
+	if (id != 0x5642) {
+		ret = -ENODEV;
+		goto done;
+	}
+
+	ret = 0;
+
+done:
+	ov5642_s_power(subdev, 0);
+	return ret;
+}
+
+static int ov5642_probe(struct i2c_client *client,
+			const struct i2c_device_id *did)
+{
+	struct ov5642 *priv;
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+	int ret;
+
+	if (!icl) {
+		dev_err(&client->dev, "OV5642: missing platform data!\n");
+		return -EINVAL;
+	}
+
+	priv = kzalloc(sizeof(struct ov5642), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	v4l2_i2c_subdev_init(&priv->subdev, client, &ov5642_subdev_ops);
+
+	priv->fmt		= &ov5642_colour_fmts[0];
+
+	priv->crop_rect.width	= OV5642_DEFAULT_WIDTH;
+	priv->crop_rect.height	= OV5642_DEFAULT_HEIGHT;
+	priv->crop_rect.left	= (OV5642_MAX_WIDTH - OV5642_DEFAULT_WIDTH) / 2;
+	priv->crop_rect.top	= (OV5642_MAX_HEIGHT - OV5642_DEFAULT_HEIGHT) / 2;
+	priv->total_width = OV5642_DEFAULT_WIDTH + BLANKING_EXTRA_WIDTH;
+	priv->total_height = BLANKING_MIN_HEIGHT;
+
+	ret = ov5642_video_probe(client);
+	if (ret < 0)
+		goto error;
+
+	return 0;
+
+error:
+	kfree(priv);
+	return ret;
+}
+
+static int ov5642_remove(struct i2c_client *client)
+{
+	struct ov5642 *priv = to_ov5642(client);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+	if (icl->free_bus)
+		icl->free_bus(icl);
+	kfree(priv);
+
+	return 0;
+}
+
+static const struct i2c_device_id ov5642_id[] = {
+	{ "ov5642", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, ov5642_id);
+
+static struct i2c_driver ov5642_i2c_driver = {
+	.driver = {
+		.name = "ov5642",
+	},
+	.probe		= ov5642_probe,
+	.remove		= ov5642_remove,
+	.id_table	= ov5642_id,
+};
+
+module_i2c_driver(ov5642_i2c_driver);
+
+MODULE_DESCRIPTION("Omnivision OV5642 Camera driver");
+MODULE_AUTHOR("Bastian Hecht <hechtb@gmail.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/i2c/soc_camera/ov6650.c b/drivers/media/i2c/soc_camera/ov6650.c
new file mode 100644
index 0000000..65b031f
--- /dev/null
+++ b/drivers/media/i2c/soc_camera/ov6650.c
@@ -0,0 +1,1069 @@
+/*
+ * V4L2 SoC Camera driver for OmniVision OV6650 Camera Sensor
+ *
+ * Copyright (C) 2010 Janusz Krzysztofik <jkrzyszt@tis.icnet.pl>
+ *
+ * Based on OmniVision OV96xx Camera Driver
+ * Copyright (C) 2009 Marek Vasut <marek.vasut@gmail.com>
+ *
+ * Based on ov772x camera driver:
+ * Copyright (C) 2008 Renesas Solutions Corp.
+ * Kuninori Morimoto <morimoto.kuninori@renesas.com>
+ *
+ * Based on ov7670 and soc_camera_platform driver,
+ * Copyright 2006-7 Jonathan Corbet <corbet@lwn.net>
+ * Copyright (C) 2008 Magnus Damm
+ * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de>
+ *
+ * Hardware specific bits initialy based on former work by Matt Callow
+ * drivers/media/video/omap/sensor_ov6650.c
+ * Copyright (C) 2006 Matt Callow
+ *
+ * This program is free software; you can 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/bitops.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/v4l2-mediabus.h>
+#include <linux/module.h>
+
+#include <media/soc_camera.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-ctrls.h>
+
+/* Register definitions */
+#define REG_GAIN		0x00	/* range 00 - 3F */
+#define REG_BLUE		0x01
+#define REG_RED			0x02
+#define REG_SAT			0x03	/* [7:4] saturation [0:3] reserved */
+#define REG_HUE			0x04	/* [7:6] rsrvd [5] hue en [4:0] hue */
+
+#define REG_BRT			0x06
+
+#define REG_PIDH		0x0a
+#define REG_PIDL		0x0b
+
+#define REG_AECH		0x10
+#define REG_CLKRC		0x11	/* Data Format and Internal Clock */
+					/* [7:6] Input system clock (MHz)*/
+					/*   00=8, 01=12, 10=16, 11=24 */
+					/* [5:0]: Internal Clock Pre-Scaler */
+#define REG_COMA		0x12	/* [7] Reset */
+#define REG_COMB		0x13
+#define REG_COMC		0x14
+#define REG_COMD		0x15
+#define REG_COML		0x16
+#define REG_HSTRT		0x17
+#define REG_HSTOP		0x18
+#define REG_VSTRT		0x19
+#define REG_VSTOP		0x1a
+#define REG_PSHFT		0x1b
+#define REG_MIDH		0x1c
+#define REG_MIDL		0x1d
+#define REG_HSYNS		0x1e
+#define REG_HSYNE		0x1f
+#define REG_COME		0x20
+#define REG_YOFF		0x21
+#define REG_UOFF		0x22
+#define REG_VOFF		0x23
+#define REG_AEW			0x24
+#define REG_AEB			0x25
+#define REG_COMF		0x26
+#define REG_COMG		0x27
+#define REG_COMH		0x28
+#define REG_COMI		0x29
+
+#define REG_FRARL		0x2b
+#define REG_COMJ		0x2c
+#define REG_COMK		0x2d
+#define REG_AVGY		0x2e
+#define REG_REF0		0x2f
+#define REG_REF1		0x30
+#define REG_REF2		0x31
+#define REG_FRAJH		0x32
+#define REG_FRAJL		0x33
+#define REG_FACT		0x34
+#define REG_L1AEC		0x35
+#define REG_AVGU		0x36
+#define REG_AVGV		0x37
+
+#define REG_SPCB		0x60
+#define REG_SPCC		0x61
+#define REG_GAM1		0x62
+#define REG_GAM2		0x63
+#define REG_GAM3		0x64
+#define REG_SPCD		0x65
+
+#define REG_SPCE		0x68
+#define REG_ADCL		0x69
+
+#define REG_RMCO		0x6c
+#define REG_GMCO		0x6d
+#define REG_BMCO		0x6e
+
+
+/* Register bits, values, etc. */
+#define OV6650_PIDH		0x66	/* high byte of product ID number */
+#define OV6650_PIDL		0x50	/* low byte of product ID number */
+#define OV6650_MIDH		0x7F	/* high byte of mfg ID */
+#define OV6650_MIDL		0xA2	/* low byte of mfg ID */
+
+#define DEF_GAIN		0x00
+#define DEF_BLUE		0x80
+#define DEF_RED			0x80
+
+#define SAT_SHIFT		4
+#define SAT_MASK		(0xf << SAT_SHIFT)
+#define SET_SAT(x)		(((x) << SAT_SHIFT) & SAT_MASK)
+
+#define HUE_EN			BIT(5)
+#define HUE_MASK		0x1f
+#define DEF_HUE			0x10
+#define SET_HUE(x)		(HUE_EN | ((x) & HUE_MASK))
+
+#define DEF_AECH		0x4D
+
+#define CLKRC_6MHz		0x00
+#define CLKRC_12MHz		0x40
+#define CLKRC_16MHz		0x80
+#define CLKRC_24MHz		0xc0
+#define CLKRC_DIV_MASK		0x3f
+#define GET_CLKRC_DIV(x)	(((x) & CLKRC_DIV_MASK) + 1)
+
+#define COMA_RESET		BIT(7)
+#define COMA_QCIF		BIT(5)
+#define COMA_RAW_RGB		BIT(4)
+#define COMA_RGB		BIT(3)
+#define COMA_BW			BIT(2)
+#define COMA_WORD_SWAP		BIT(1)
+#define COMA_BYTE_SWAP		BIT(0)
+#define DEF_COMA		0x00
+
+#define COMB_FLIP_V		BIT(7)
+#define COMB_FLIP_H		BIT(5)
+#define COMB_BAND_FILTER	BIT(4)
+#define COMB_AWB		BIT(2)
+#define COMB_AGC		BIT(1)
+#define COMB_AEC		BIT(0)
+#define DEF_COMB		0x5f
+
+#define COML_ONE_CHANNEL	BIT(7)
+
+#define DEF_HSTRT		0x24
+#define DEF_HSTOP		0xd4
+#define DEF_VSTRT		0x04
+#define DEF_VSTOP		0x94
+
+#define COMF_HREF_LOW		BIT(4)
+
+#define COMJ_PCLK_RISING	BIT(4)
+#define COMJ_VSYNC_HIGH		BIT(0)
+
+/* supported resolutions */
+#define W_QCIF			(DEF_HSTOP - DEF_HSTRT)
+#define W_CIF			(W_QCIF << 1)
+#define H_QCIF			(DEF_VSTOP - DEF_VSTRT)
+#define H_CIF			(H_QCIF << 1)
+
+#define FRAME_RATE_MAX		30
+
+
+struct ov6650_reg {
+	u8	reg;
+	u8	val;
+};
+
+struct ov6650 {
+	struct v4l2_subdev	subdev;
+	struct v4l2_ctrl_handler hdl;
+	struct {
+		/* exposure/autoexposure cluster */
+		struct v4l2_ctrl *autoexposure;
+		struct v4l2_ctrl *exposure;
+	};
+	struct {
+		/* gain/autogain cluster */
+		struct v4l2_ctrl *autogain;
+		struct v4l2_ctrl *gain;
+	};
+	struct {
+		/* blue/red/autowhitebalance cluster */
+		struct v4l2_ctrl *autowb;
+		struct v4l2_ctrl *blue;
+		struct v4l2_ctrl *red;
+	};
+	bool			half_scale;	/* scale down output by 2 */
+	struct v4l2_rect	rect;		/* sensor cropping window */
+	unsigned long		pclk_limit;	/* from host */
+	unsigned long		pclk_max;	/* from resolution and format */
+	struct v4l2_fract	tpf;		/* as requested with s_parm */
+	enum v4l2_mbus_pixelcode code;
+	enum v4l2_colorspace	colorspace;
+};
+
+
+static enum v4l2_mbus_pixelcode ov6650_codes[] = {
+	V4L2_MBUS_FMT_YUYV8_2X8,
+	V4L2_MBUS_FMT_UYVY8_2X8,
+	V4L2_MBUS_FMT_YVYU8_2X8,
+	V4L2_MBUS_FMT_VYUY8_2X8,
+	V4L2_MBUS_FMT_SBGGR8_1X8,
+	V4L2_MBUS_FMT_Y8_1X8,
+};
+
+/* read a register */
+static int ov6650_reg_read(struct i2c_client *client, u8 reg, u8 *val)
+{
+	int ret;
+	u8 data = reg;
+	struct i2c_msg msg = {
+		.addr	= client->addr,
+		.flags	= 0,
+		.len	= 1,
+		.buf	= &data,
+	};
+
+	ret = i2c_transfer(client->adapter, &msg, 1);
+	if (ret < 0)
+		goto err;
+
+	msg.flags = I2C_M_RD;
+	ret = i2c_transfer(client->adapter, &msg, 1);
+	if (ret < 0)
+		goto err;
+
+	*val = data;
+	return 0;
+
+err:
+	dev_err(&client->dev, "Failed reading register 0x%02x!\n", reg);
+	return ret;
+}
+
+/* write a register */
+static int ov6650_reg_write(struct i2c_client *client, u8 reg, u8 val)
+{
+	int ret;
+	unsigned char data[2] = { reg, val };
+	struct i2c_msg msg = {
+		.addr	= client->addr,
+		.flags	= 0,
+		.len	= 2,
+		.buf	= data,
+	};
+
+	ret = i2c_transfer(client->adapter, &msg, 1);
+	udelay(100);
+
+	if (ret < 0) {
+		dev_err(&client->dev, "Failed writing register 0x%02x!\n", reg);
+		return ret;
+	}
+	return 0;
+}
+
+
+/* Read a register, alter its bits, write it back */
+static int ov6650_reg_rmw(struct i2c_client *client, u8 reg, u8 set, u8 mask)
+{
+	u8 val;
+	int ret;
+
+	ret = ov6650_reg_read(client, reg, &val);
+	if (ret) {
+		dev_err(&client->dev,
+			"[Read]-Modify-Write of register 0x%02x failed!\n",
+			reg);
+		return ret;
+	}
+
+	val &= ~mask;
+	val |= set;
+
+	ret = ov6650_reg_write(client, reg, val);
+	if (ret)
+		dev_err(&client->dev,
+			"Read-Modify-[Write] of register 0x%02x failed!\n",
+			reg);
+
+	return ret;
+}
+
+static struct ov6650 *to_ov6650(const struct i2c_client *client)
+{
+	return container_of(i2c_get_clientdata(client), struct ov6650, subdev);
+}
+
+/* Start/Stop streaming from the device */
+static int ov6650_s_stream(struct v4l2_subdev *sd, int enable)
+{
+	return 0;
+}
+
+/* Get status of additional camera capabilities */
+static int ov6550_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct ov6650 *priv = container_of(ctrl->handler, struct ov6650, hdl);
+	struct v4l2_subdev *sd = &priv->subdev;
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	uint8_t reg, reg2;
+	int ret;
+
+	switch (ctrl->id) {
+	case V4L2_CID_AUTOGAIN:
+		ret = ov6650_reg_read(client, REG_GAIN, &reg);
+		if (!ret)
+			priv->gain->val = reg;
+		return ret;
+	case V4L2_CID_AUTO_WHITE_BALANCE:
+		ret = ov6650_reg_read(client, REG_BLUE, &reg);
+		if (!ret)
+			ret = ov6650_reg_read(client, REG_RED, &reg2);
+		if (!ret) {
+			priv->blue->val = reg;
+			priv->red->val = reg2;
+		}
+		return ret;
+	case V4L2_CID_EXPOSURE_AUTO:
+		ret = ov6650_reg_read(client, REG_AECH, &reg);
+		if (!ret)
+			priv->exposure->val = reg;
+		return ret;
+	}
+	return -EINVAL;
+}
+
+/* Set status of additional camera capabilities */
+static int ov6550_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct ov6650 *priv = container_of(ctrl->handler, struct ov6650, hdl);
+	struct v4l2_subdev *sd = &priv->subdev;
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	int ret;
+
+	switch (ctrl->id) {
+	case V4L2_CID_AUTOGAIN:
+		ret = ov6650_reg_rmw(client, REG_COMB,
+				ctrl->val ? COMB_AGC : 0, COMB_AGC);
+		if (!ret && !ctrl->val)
+			ret = ov6650_reg_write(client, REG_GAIN, priv->gain->val);
+		return ret;
+	case V4L2_CID_AUTO_WHITE_BALANCE:
+		ret = ov6650_reg_rmw(client, REG_COMB,
+				ctrl->val ? COMB_AWB : 0, COMB_AWB);
+		if (!ret && !ctrl->val) {
+			ret = ov6650_reg_write(client, REG_BLUE, priv->blue->val);
+			if (!ret)
+				ret = ov6650_reg_write(client, REG_RED,
+							priv->red->val);
+		}
+		return ret;
+	case V4L2_CID_SATURATION:
+		return ov6650_reg_rmw(client, REG_SAT, SET_SAT(ctrl->val),
+				SAT_MASK);
+	case V4L2_CID_HUE:
+		return ov6650_reg_rmw(client, REG_HUE, SET_HUE(ctrl->val),
+				HUE_MASK);
+	case V4L2_CID_BRIGHTNESS:
+		return ov6650_reg_write(client, REG_BRT, ctrl->val);
+	case V4L2_CID_EXPOSURE_AUTO:
+		ret = ov6650_reg_rmw(client, REG_COMB, ctrl->val ==
+				V4L2_EXPOSURE_AUTO ? COMB_AEC : 0, COMB_AEC);
+		if (!ret && ctrl->val == V4L2_EXPOSURE_MANUAL)
+			ret = ov6650_reg_write(client, REG_AECH,
+						priv->exposure->val);
+		return ret;
+	case V4L2_CID_GAMMA:
+		return ov6650_reg_write(client, REG_GAM1, ctrl->val);
+	case V4L2_CID_VFLIP:
+		return ov6650_reg_rmw(client, REG_COMB,
+				ctrl->val ? COMB_FLIP_V : 0, COMB_FLIP_V);
+	case V4L2_CID_HFLIP:
+		return ov6650_reg_rmw(client, REG_COMB,
+				ctrl->val ? COMB_FLIP_H : 0, COMB_FLIP_H);
+	}
+
+	return -EINVAL;
+}
+
+/* Get chip identification */
+static int ov6650_g_chip_ident(struct v4l2_subdev *sd,
+				struct v4l2_dbg_chip_ident *id)
+{
+	id->ident	= V4L2_IDENT_OV6650;
+	id->revision	= 0;
+
+	return 0;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int ov6650_get_register(struct v4l2_subdev *sd,
+				struct v4l2_dbg_register *reg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	int ret;
+	u8 val;
+
+	if (reg->reg & ~0xff)
+		return -EINVAL;
+
+	reg->size = 1;
+
+	ret = ov6650_reg_read(client, reg->reg, &val);
+	if (!ret)
+		reg->val = (__u64)val;
+
+	return ret;
+}
+
+static int ov6650_set_register(struct v4l2_subdev *sd,
+				struct v4l2_dbg_register *reg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	if (reg->reg & ~0xff || reg->val & ~0xff)
+		return -EINVAL;
+
+	return ov6650_reg_write(client, reg->reg, reg->val);
+}
+#endif
+
+static int ov6650_s_power(struct v4l2_subdev *sd, int on)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+	return soc_camera_set_power(&client->dev, icl, on);
+}
+
+static int ov6650_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct ov6650 *priv = to_ov6650(client);
+
+	a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	a->c = priv->rect;
+
+	return 0;
+}
+
+static int ov6650_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct ov6650 *priv = to_ov6650(client);
+	struct v4l2_rect *rect = &a->c;
+	int ret;
+
+	if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
+	rect->left   = ALIGN(rect->left,   2);
+	rect->width  = ALIGN(rect->width,  2);
+	rect->top    = ALIGN(rect->top,    2);
+	rect->height = ALIGN(rect->height, 2);
+	soc_camera_limit_side(&rect->left, &rect->width,
+			DEF_HSTRT << 1, 2, W_CIF);
+	soc_camera_limit_side(&rect->top, &rect->height,
+			DEF_VSTRT << 1, 2, H_CIF);
+
+	ret = ov6650_reg_write(client, REG_HSTRT, rect->left >> 1);
+	if (!ret) {
+		priv->rect.left = rect->left;
+		ret = ov6650_reg_write(client, REG_HSTOP,
+				(rect->left + rect->width) >> 1);
+	}
+	if (!ret) {
+		priv->rect.width = rect->width;
+		ret = ov6650_reg_write(client, REG_VSTRT, rect->top >> 1);
+	}
+	if (!ret) {
+		priv->rect.top = rect->top;
+		ret = ov6650_reg_write(client, REG_VSTOP,
+				(rect->top + rect->height) >> 1);
+	}
+	if (!ret)
+		priv->rect.height = rect->height;
+
+	return ret;
+}
+
+static int ov6650_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
+{
+	if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
+	a->bounds.left			= DEF_HSTRT << 1;
+	a->bounds.top			= DEF_VSTRT << 1;
+	a->bounds.width			= W_CIF;
+	a->bounds.height		= H_CIF;
+	a->defrect			= a->bounds;
+	a->pixelaspect.numerator	= 1;
+	a->pixelaspect.denominator	= 1;
+
+	return 0;
+}
+
+static int ov6650_g_fmt(struct v4l2_subdev *sd,
+			 struct v4l2_mbus_framefmt *mf)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct ov6650 *priv = to_ov6650(client);
+
+	mf->width	= priv->rect.width >> priv->half_scale;
+	mf->height	= priv->rect.height >> priv->half_scale;
+	mf->code	= priv->code;
+	mf->colorspace	= priv->colorspace;
+	mf->field	= V4L2_FIELD_NONE;
+
+	return 0;
+}
+
+static bool is_unscaled_ok(int width, int height, struct v4l2_rect *rect)
+{
+	return width > rect->width >> 1 || height > rect->height >> 1;
+}
+
+static u8 to_clkrc(struct v4l2_fract *timeperframe,
+		unsigned long pclk_limit, unsigned long pclk_max)
+{
+	unsigned long pclk;
+
+	if (timeperframe->numerator && timeperframe->denominator)
+		pclk = pclk_max * timeperframe->denominator /
+				(FRAME_RATE_MAX * timeperframe->numerator);
+	else
+		pclk = pclk_max;
+
+	if (pclk_limit && pclk_limit < pclk)
+		pclk = pclk_limit;
+
+	return (pclk_max - 1) / pclk;
+}
+
+/* set the format we will capture in */
+static int ov6650_s_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct soc_camera_device *icd = v4l2_get_subdev_hostdata(sd);
+	struct soc_camera_sense *sense = icd->sense;
+	struct ov6650 *priv = to_ov6650(client);
+	bool half_scale = !is_unscaled_ok(mf->width, mf->height, &priv->rect);
+	struct v4l2_crop a = {
+		.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+		.c = {
+			.left	= priv->rect.left + (priv->rect.width >> 1) -
+					(mf->width >> (1 - half_scale)),
+			.top	= priv->rect.top + (priv->rect.height >> 1) -
+					(mf->height >> (1 - half_scale)),
+			.width	= mf->width << half_scale,
+			.height	= mf->height << half_scale,
+		},
+	};
+	enum v4l2_mbus_pixelcode code = mf->code;
+	unsigned long mclk, pclk;
+	u8 coma_set = 0, coma_mask = 0, coml_set, coml_mask, clkrc;
+	int ret;
+
+	/* select color matrix configuration for given color encoding */
+	switch (code) {
+	case V4L2_MBUS_FMT_Y8_1X8:
+		dev_dbg(&client->dev, "pixel format GREY8_1X8\n");
+		coma_mask |= COMA_RGB | COMA_WORD_SWAP | COMA_BYTE_SWAP;
+		coma_set |= COMA_BW;
+		break;
+	case V4L2_MBUS_FMT_YUYV8_2X8:
+		dev_dbg(&client->dev, "pixel format YUYV8_2X8_LE\n");
+		coma_mask |= COMA_RGB | COMA_BW | COMA_BYTE_SWAP;
+		coma_set |= COMA_WORD_SWAP;
+		break;
+	case V4L2_MBUS_FMT_YVYU8_2X8:
+		dev_dbg(&client->dev, "pixel format YVYU8_2X8_LE (untested)\n");
+		coma_mask |= COMA_RGB | COMA_BW | COMA_WORD_SWAP |
+				COMA_BYTE_SWAP;
+		break;
+	case V4L2_MBUS_FMT_UYVY8_2X8:
+		dev_dbg(&client->dev, "pixel format YUYV8_2X8_BE\n");
+		if (half_scale) {
+			coma_mask |= COMA_RGB | COMA_BW | COMA_WORD_SWAP;
+			coma_set |= COMA_BYTE_SWAP;
+		} else {
+			coma_mask |= COMA_RGB | COMA_BW;
+			coma_set |= COMA_BYTE_SWAP | COMA_WORD_SWAP;
+		}
+		break;
+	case V4L2_MBUS_FMT_VYUY8_2X8:
+		dev_dbg(&client->dev, "pixel format YVYU8_2X8_BE (untested)\n");
+		if (half_scale) {
+			coma_mask |= COMA_RGB | COMA_BW;
+			coma_set |= COMA_BYTE_SWAP | COMA_WORD_SWAP;
+		} else {
+			coma_mask |= COMA_RGB | COMA_BW | COMA_WORD_SWAP;
+			coma_set |= COMA_BYTE_SWAP;
+		}
+		break;
+	case V4L2_MBUS_FMT_SBGGR8_1X8:
+		dev_dbg(&client->dev, "pixel format SBGGR8_1X8 (untested)\n");
+		coma_mask |= COMA_BW | COMA_BYTE_SWAP | COMA_WORD_SWAP;
+		coma_set |= COMA_RAW_RGB | COMA_RGB;
+		break;
+	default:
+		dev_err(&client->dev, "Pixel format not handled: 0x%x\n", code);
+		return -EINVAL;
+	}
+	priv->code = code;
+
+	if (code == V4L2_MBUS_FMT_Y8_1X8 ||
+			code == V4L2_MBUS_FMT_SBGGR8_1X8) {
+		coml_mask = COML_ONE_CHANNEL;
+		coml_set = 0;
+		priv->pclk_max = 4000000;
+	} else {
+		coml_mask = 0;
+		coml_set = COML_ONE_CHANNEL;
+		priv->pclk_max = 8000000;
+	}
+
+	if (code == V4L2_MBUS_FMT_SBGGR8_1X8)
+		priv->colorspace = V4L2_COLORSPACE_SRGB;
+	else if (code != 0)
+		priv->colorspace = V4L2_COLORSPACE_JPEG;
+
+	if (half_scale) {
+		dev_dbg(&client->dev, "max resolution: QCIF\n");
+		coma_set |= COMA_QCIF;
+		priv->pclk_max /= 2;
+	} else {
+		dev_dbg(&client->dev, "max resolution: CIF\n");
+		coma_mask |= COMA_QCIF;
+	}
+	priv->half_scale = half_scale;
+
+	if (sense) {
+		if (sense->master_clock == 8000000) {
+			dev_dbg(&client->dev, "8MHz input clock\n");
+			clkrc = CLKRC_6MHz;
+		} else if (sense->master_clock == 12000000) {
+			dev_dbg(&client->dev, "12MHz input clock\n");
+			clkrc = CLKRC_12MHz;
+		} else if (sense->master_clock == 16000000) {
+			dev_dbg(&client->dev, "16MHz input clock\n");
+			clkrc = CLKRC_16MHz;
+		} else if (sense->master_clock == 24000000) {
+			dev_dbg(&client->dev, "24MHz input clock\n");
+			clkrc = CLKRC_24MHz;
+		} else {
+			dev_err(&client->dev,
+				"unsupported input clock, check platform data\n");
+			return -EINVAL;
+		}
+		mclk = sense->master_clock;
+		priv->pclk_limit = sense->pixel_clock_max;
+	} else {
+		clkrc = CLKRC_24MHz;
+		mclk = 24000000;
+		priv->pclk_limit = 0;
+		dev_dbg(&client->dev, "using default 24MHz input clock\n");
+	}
+
+	clkrc |= to_clkrc(&priv->tpf, priv->pclk_limit, priv->pclk_max);
+
+	pclk = priv->pclk_max / GET_CLKRC_DIV(clkrc);
+	dev_dbg(&client->dev, "pixel clock divider: %ld.%ld\n",
+			mclk / pclk, 10 * mclk % pclk / pclk);
+
+	ret = ov6650_s_crop(sd, &a);
+	if (!ret)
+		ret = ov6650_reg_rmw(client, REG_COMA, coma_set, coma_mask);
+	if (!ret)
+		ret = ov6650_reg_write(client, REG_CLKRC, clkrc);
+	if (!ret)
+		ret = ov6650_reg_rmw(client, REG_COML, coml_set, coml_mask);
+
+	if (!ret) {
+		mf->colorspace	= priv->colorspace;
+		mf->width = priv->rect.width >> half_scale;
+		mf->height = priv->rect.height >> half_scale;
+	}
+
+	return ret;
+}
+
+static int ov6650_try_fmt(struct v4l2_subdev *sd,
+			  struct v4l2_mbus_framefmt *mf)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct ov6650 *priv = to_ov6650(client);
+
+	if (is_unscaled_ok(mf->width, mf->height, &priv->rect))
+		v4l_bound_align_image(&mf->width, 2, W_CIF, 1,
+				&mf->height, 2, H_CIF, 1, 0);
+
+	mf->field = V4L2_FIELD_NONE;
+
+	switch (mf->code) {
+	case V4L2_MBUS_FMT_Y10_1X10:
+		mf->code = V4L2_MBUS_FMT_Y8_1X8;
+	case V4L2_MBUS_FMT_Y8_1X8:
+	case V4L2_MBUS_FMT_YVYU8_2X8:
+	case V4L2_MBUS_FMT_YUYV8_2X8:
+	case V4L2_MBUS_FMT_VYUY8_2X8:
+	case V4L2_MBUS_FMT_UYVY8_2X8:
+		mf->colorspace = V4L2_COLORSPACE_JPEG;
+		break;
+	default:
+		mf->code = V4L2_MBUS_FMT_SBGGR8_1X8;
+	case V4L2_MBUS_FMT_SBGGR8_1X8:
+		mf->colorspace = V4L2_COLORSPACE_SRGB;
+		break;
+	}
+
+	return 0;
+}
+
+static int ov6650_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
+			   enum v4l2_mbus_pixelcode *code)
+{
+	if (index >= ARRAY_SIZE(ov6650_codes))
+		return -EINVAL;
+
+	*code = ov6650_codes[index];
+	return 0;
+}
+
+static int ov6650_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct ov6650 *priv = to_ov6650(client);
+	struct v4l2_captureparm *cp = &parms->parm.capture;
+
+	if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
+	memset(cp, 0, sizeof(*cp));
+	cp->capability = V4L2_CAP_TIMEPERFRAME;
+	cp->timeperframe.numerator = GET_CLKRC_DIV(to_clkrc(&priv->tpf,
+			priv->pclk_limit, priv->pclk_max));
+	cp->timeperframe.denominator = FRAME_RATE_MAX;
+
+	dev_dbg(&client->dev, "Frame interval: %u/%u s\n",
+		cp->timeperframe.numerator, cp->timeperframe.denominator);
+
+	return 0;
+}
+
+static int ov6650_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct ov6650 *priv = to_ov6650(client);
+	struct v4l2_captureparm *cp = &parms->parm.capture;
+	struct v4l2_fract *tpf = &cp->timeperframe;
+	int div, ret;
+	u8 clkrc;
+
+	if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
+	if (cp->extendedmode != 0)
+		return -EINVAL;
+
+	if (tpf->numerator == 0 || tpf->denominator == 0)
+		div = 1;  /* Reset to full rate */
+	else
+		div = (tpf->numerator * FRAME_RATE_MAX) / tpf->denominator;
+
+	if (div == 0)
+		div = 1;
+	else if (div > GET_CLKRC_DIV(CLKRC_DIV_MASK))
+		div = GET_CLKRC_DIV(CLKRC_DIV_MASK);
+
+	/*
+	 * Keep result to be used as tpf limit
+	 * for subseqent clock divider calculations
+	 */
+	priv->tpf.numerator = div;
+	priv->tpf.denominator = FRAME_RATE_MAX;
+
+	clkrc = to_clkrc(&priv->tpf, priv->pclk_limit, priv->pclk_max);
+
+	ret = ov6650_reg_rmw(client, REG_CLKRC, clkrc, CLKRC_DIV_MASK);
+	if (!ret) {
+		tpf->numerator = GET_CLKRC_DIV(clkrc);
+		tpf->denominator = FRAME_RATE_MAX;
+	}
+
+	return ret;
+}
+
+/* Soft reset the camera. This has nothing to do with the RESET pin! */
+static int ov6650_reset(struct i2c_client *client)
+{
+	int ret;
+
+	dev_dbg(&client->dev, "reset\n");
+
+	ret = ov6650_reg_rmw(client, REG_COMA, COMA_RESET, 0);
+	if (ret)
+		dev_err(&client->dev,
+			"An error occurred while entering soft reset!\n");
+
+	return ret;
+}
+
+/* program default register values */
+static int ov6650_prog_dflt(struct i2c_client *client)
+{
+	int ret;
+
+	dev_dbg(&client->dev, "initializing\n");
+
+	ret = ov6650_reg_write(client, REG_COMA, 0);	/* ~COMA_RESET */
+	if (!ret)
+		ret = ov6650_reg_rmw(client, REG_COMB, 0, COMB_BAND_FILTER);
+
+	return ret;
+}
+
+static int ov6650_video_probe(struct i2c_client *client)
+{
+	struct ov6650 *priv = to_ov6650(client);
+	u8		pidh, pidl, midh, midl;
+	int		ret;
+
+	ret = ov6650_s_power(&priv->subdev, 1);
+	if (ret < 0)
+		return ret;
+
+	/*
+	 * check and show product ID and manufacturer ID
+	 */
+	ret = ov6650_reg_read(client, REG_PIDH, &pidh);
+	if (!ret)
+		ret = ov6650_reg_read(client, REG_PIDL, &pidl);
+	if (!ret)
+		ret = ov6650_reg_read(client, REG_MIDH, &midh);
+	if (!ret)
+		ret = ov6650_reg_read(client, REG_MIDL, &midl);
+
+	if (ret)
+		goto done;
+
+	if ((pidh != OV6650_PIDH) || (pidl != OV6650_PIDL)) {
+		dev_err(&client->dev, "Product ID error 0x%02x:0x%02x\n",
+				pidh, pidl);
+		ret = -ENODEV;
+		goto done;
+	}
+
+	dev_info(&client->dev,
+		"ov6650 Product ID 0x%02x:0x%02x Manufacturer ID 0x%02x:0x%02x\n",
+		pidh, pidl, midh, midl);
+
+	ret = ov6650_reset(client);
+	if (!ret)
+		ret = ov6650_prog_dflt(client);
+	if (!ret)
+		ret = v4l2_ctrl_handler_setup(&priv->hdl);
+
+done:
+	ov6650_s_power(&priv->subdev, 0);
+	return ret;
+}
+
+static const struct v4l2_ctrl_ops ov6550_ctrl_ops = {
+	.g_volatile_ctrl = ov6550_g_volatile_ctrl,
+	.s_ctrl = ov6550_s_ctrl,
+};
+
+static struct v4l2_subdev_core_ops ov6650_core_ops = {
+	.g_chip_ident		= ov6650_g_chip_ident,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.g_register		= ov6650_get_register,
+	.s_register		= ov6650_set_register,
+#endif
+	.s_power		= ov6650_s_power,
+};
+
+/* Request bus settings on camera side */
+static int ov6650_g_mbus_config(struct v4l2_subdev *sd,
+				struct v4l2_mbus_config *cfg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+	cfg->flags = V4L2_MBUS_MASTER |
+		V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_PCLK_SAMPLE_FALLING |
+		V4L2_MBUS_HSYNC_ACTIVE_HIGH | V4L2_MBUS_HSYNC_ACTIVE_LOW |
+		V4L2_MBUS_VSYNC_ACTIVE_HIGH | V4L2_MBUS_VSYNC_ACTIVE_LOW |
+		V4L2_MBUS_DATA_ACTIVE_HIGH;
+	cfg->type = V4L2_MBUS_PARALLEL;
+	cfg->flags = soc_camera_apply_board_flags(icl, cfg);
+
+	return 0;
+}
+
+/* Alter bus settings on camera side */
+static int ov6650_s_mbus_config(struct v4l2_subdev *sd,
+				const struct v4l2_mbus_config *cfg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+	unsigned long flags = soc_camera_apply_board_flags(icl, cfg);
+	int ret;
+
+	if (flags & V4L2_MBUS_PCLK_SAMPLE_RISING)
+		ret = ov6650_reg_rmw(client, REG_COMJ, COMJ_PCLK_RISING, 0);
+	else
+		ret = ov6650_reg_rmw(client, REG_COMJ, 0, COMJ_PCLK_RISING);
+	if (ret)
+		return ret;
+
+	if (flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)
+		ret = ov6650_reg_rmw(client, REG_COMF, COMF_HREF_LOW, 0);
+	else
+		ret = ov6650_reg_rmw(client, REG_COMF, 0, COMF_HREF_LOW);
+	if (ret)
+		return ret;
+
+	if (flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH)
+		ret = ov6650_reg_rmw(client, REG_COMJ, COMJ_VSYNC_HIGH, 0);
+	else
+		ret = ov6650_reg_rmw(client, REG_COMJ, 0, COMJ_VSYNC_HIGH);
+
+	return ret;
+}
+
+static struct v4l2_subdev_video_ops ov6650_video_ops = {
+	.s_stream	= ov6650_s_stream,
+	.g_mbus_fmt	= ov6650_g_fmt,
+	.s_mbus_fmt	= ov6650_s_fmt,
+	.try_mbus_fmt	= ov6650_try_fmt,
+	.enum_mbus_fmt	= ov6650_enum_fmt,
+	.cropcap	= ov6650_cropcap,
+	.g_crop		= ov6650_g_crop,
+	.s_crop		= ov6650_s_crop,
+	.g_parm		= ov6650_g_parm,
+	.s_parm		= ov6650_s_parm,
+	.g_mbus_config	= ov6650_g_mbus_config,
+	.s_mbus_config	= ov6650_s_mbus_config,
+};
+
+static struct v4l2_subdev_ops ov6650_subdev_ops = {
+	.core	= &ov6650_core_ops,
+	.video	= &ov6650_video_ops,
+};
+
+/*
+ * i2c_driver function
+ */
+static int ov6650_probe(struct i2c_client *client,
+			const struct i2c_device_id *did)
+{
+	struct ov6650 *priv;
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+	int ret;
+
+	if (!icl) {
+		dev_err(&client->dev, "Missing platform_data for driver\n");
+		return -EINVAL;
+	}
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv) {
+		dev_err(&client->dev,
+			"Failed to allocate memory for private data!\n");
+		return -ENOMEM;
+	}
+
+	v4l2_i2c_subdev_init(&priv->subdev, client, &ov6650_subdev_ops);
+	v4l2_ctrl_handler_init(&priv->hdl, 13);
+	v4l2_ctrl_new_std(&priv->hdl, &ov6550_ctrl_ops,
+			V4L2_CID_VFLIP, 0, 1, 1, 0);
+	v4l2_ctrl_new_std(&priv->hdl, &ov6550_ctrl_ops,
+			V4L2_CID_HFLIP, 0, 1, 1, 0);
+	priv->autogain = v4l2_ctrl_new_std(&priv->hdl, &ov6550_ctrl_ops,
+			V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
+	priv->gain = v4l2_ctrl_new_std(&priv->hdl, &ov6550_ctrl_ops,
+			V4L2_CID_GAIN, 0, 0x3f, 1, DEF_GAIN);
+	priv->autowb = v4l2_ctrl_new_std(&priv->hdl, &ov6550_ctrl_ops,
+			V4L2_CID_AUTO_WHITE_BALANCE, 0, 1, 1, 1);
+	priv->blue = v4l2_ctrl_new_std(&priv->hdl, &ov6550_ctrl_ops,
+			V4L2_CID_BLUE_BALANCE, 0, 0xff, 1, DEF_BLUE);
+	priv->red = v4l2_ctrl_new_std(&priv->hdl, &ov6550_ctrl_ops,
+			V4L2_CID_RED_BALANCE, 0, 0xff, 1, DEF_RED);
+	v4l2_ctrl_new_std(&priv->hdl, &ov6550_ctrl_ops,
+			V4L2_CID_SATURATION, 0, 0xf, 1, 0x8);
+	v4l2_ctrl_new_std(&priv->hdl, &ov6550_ctrl_ops,
+			V4L2_CID_HUE, 0, HUE_MASK, 1, DEF_HUE);
+	v4l2_ctrl_new_std(&priv->hdl, &ov6550_ctrl_ops,
+			V4L2_CID_BRIGHTNESS, 0, 0xff, 1, 0x80);
+	priv->autoexposure = v4l2_ctrl_new_std_menu(&priv->hdl,
+			&ov6550_ctrl_ops, V4L2_CID_EXPOSURE_AUTO,
+			V4L2_EXPOSURE_MANUAL, 0, V4L2_EXPOSURE_AUTO);
+	priv->exposure = v4l2_ctrl_new_std(&priv->hdl, &ov6550_ctrl_ops,
+			V4L2_CID_EXPOSURE, 0, 0xff, 1, DEF_AECH);
+	v4l2_ctrl_new_std(&priv->hdl, &ov6550_ctrl_ops,
+			V4L2_CID_GAMMA, 0, 0xff, 1, 0x12);
+
+	priv->subdev.ctrl_handler = &priv->hdl;
+	if (priv->hdl.error) {
+		int err = priv->hdl.error;
+
+		kfree(priv);
+		return err;
+	}
+	v4l2_ctrl_auto_cluster(2, &priv->autogain, 0, true);
+	v4l2_ctrl_auto_cluster(3, &priv->autowb, 0, true);
+	v4l2_ctrl_auto_cluster(2, &priv->autoexposure,
+				V4L2_EXPOSURE_MANUAL, true);
+
+	priv->rect.left	  = DEF_HSTRT << 1;
+	priv->rect.top	  = DEF_VSTRT << 1;
+	priv->rect.width  = W_CIF;
+	priv->rect.height = H_CIF;
+	priv->half_scale  = false;
+	priv->code	  = V4L2_MBUS_FMT_YUYV8_2X8;
+	priv->colorspace  = V4L2_COLORSPACE_JPEG;
+
+	ret = ov6650_video_probe(client);
+	if (ret) {
+		v4l2_ctrl_handler_free(&priv->hdl);
+		kfree(priv);
+	}
+
+	return ret;
+}
+
+static int ov6650_remove(struct i2c_client *client)
+{
+	struct ov6650 *priv = to_ov6650(client);
+
+	v4l2_device_unregister_subdev(&priv->subdev);
+	v4l2_ctrl_handler_free(&priv->hdl);
+	kfree(priv);
+	return 0;
+}
+
+static const struct i2c_device_id ov6650_id[] = {
+	{ "ov6650", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, ov6650_id);
+
+static struct i2c_driver ov6650_i2c_driver = {
+	.driver = {
+		.name = "ov6650",
+	},
+	.probe    = ov6650_probe,
+	.remove   = ov6650_remove,
+	.id_table = ov6650_id,
+};
+
+module_i2c_driver(ov6650_i2c_driver);
+
+MODULE_DESCRIPTION("SoC Camera driver for OmniVision OV6650");
+MODULE_AUTHOR("Janusz Krzysztofik <jkrzyszt@tis.icnet.pl>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/i2c/soc_camera/ov772x.c b/drivers/media/i2c/soc_camera/ov772x.c
new file mode 100644
index 0000000..e4a1075
--- /dev/null
+++ b/drivers/media/i2c/soc_camera/ov772x.c
@@ -0,0 +1,1137 @@
+/*
+ * ov772x Camera Driver
+ *
+ * Copyright (C) 2008 Renesas Solutions Corp.
+ * Kuninori Morimoto <morimoto.kuninori@renesas.com>
+ *
+ * Based on ov7670 and soc_camera_platform driver,
+ *
+ * Copyright 2006-7 Jonathan Corbet <corbet@lwn.net>
+ * Copyright (C) 2008 Magnus Damm
+ * Copyright (C) 2008, Guennadi Liakhovetski <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 version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/v4l2-mediabus.h>
+#include <linux/videodev2.h>
+
+#include <media/ov772x.h>
+#include <media/soc_camera.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-subdev.h>
+
+/*
+ * register offset
+ */
+#define GAIN        0x00 /* AGC - Gain control gain setting */
+#define BLUE        0x01 /* AWB - Blue channel gain setting */
+#define RED         0x02 /* AWB - Red   channel gain setting */
+#define GREEN       0x03 /* AWB - Green channel gain setting */
+#define COM1        0x04 /* Common control 1 */
+#define BAVG        0x05 /* U/B Average Level */
+#define GAVG        0x06 /* Y/Gb Average Level */
+#define RAVG        0x07 /* V/R Average Level */
+#define AECH        0x08 /* Exposure Value - AEC MSBs */
+#define COM2        0x09 /* Common control 2 */
+#define PID         0x0A /* Product ID Number MSB */
+#define VER         0x0B /* Product ID Number LSB */
+#define COM3        0x0C /* Common control 3 */
+#define COM4        0x0D /* Common control 4 */
+#define COM5        0x0E /* Common control 5 */
+#define COM6        0x0F /* Common control 6 */
+#define AEC         0x10 /* Exposure Value */
+#define CLKRC       0x11 /* Internal clock */
+#define COM7        0x12 /* Common control 7 */
+#define COM8        0x13 /* Common control 8 */
+#define COM9        0x14 /* Common control 9 */
+#define COM10       0x15 /* Common control 10 */
+#define REG16       0x16 /* Register 16 */
+#define HSTART      0x17 /* Horizontal sensor size */
+#define HSIZE       0x18 /* Horizontal frame (HREF column) end high 8-bit */
+#define VSTART      0x19 /* Vertical frame (row) start high 8-bit */
+#define VSIZE       0x1A /* Vertical sensor size */
+#define PSHFT       0x1B /* Data format - pixel delay select */
+#define MIDH        0x1C /* Manufacturer ID byte - high */
+#define MIDL        0x1D /* Manufacturer ID byte - low  */
+#define LAEC        0x1F /* Fine AEC value */
+#define COM11       0x20 /* Common control 11 */
+#define BDBASE      0x22 /* Banding filter Minimum AEC value */
+#define DBSTEP      0x23 /* Banding filter Maximum Setp */
+#define AEW         0x24 /* AGC/AEC - Stable operating region (upper limit) */
+#define AEB         0x25 /* AGC/AEC - Stable operating region (lower limit) */
+#define VPT         0x26 /* AGC/AEC Fast mode operating region */
+#define REG28       0x28 /* Register 28 */
+#define HOUTSIZE    0x29 /* Horizontal data output size MSBs */
+#define EXHCH       0x2A /* Dummy pixel insert MSB */
+#define EXHCL       0x2B /* Dummy pixel insert LSB */
+#define VOUTSIZE    0x2C /* Vertical data output size MSBs */
+#define ADVFL       0x2D /* LSB of insert dummy lines in Vertical direction */
+#define ADVFH       0x2E /* MSG of insert dummy lines in Vertical direction */
+#define YAVE        0x2F /* Y/G Channel Average value */
+#define LUMHTH      0x30 /* Histogram AEC/AGC Luminance high level threshold */
+#define LUMLTH      0x31 /* Histogram AEC/AGC Luminance low  level threshold */
+#define HREF        0x32 /* Image start and size control */
+#define DM_LNL      0x33 /* Dummy line low  8 bits */
+#define DM_LNH      0x34 /* Dummy line high 8 bits */
+#define ADOFF_B     0x35 /* AD offset compensation value for B  channel */
+#define ADOFF_R     0x36 /* AD offset compensation value for R  channel */
+#define ADOFF_GB    0x37 /* AD offset compensation value for Gb channel */
+#define ADOFF_GR    0x38 /* AD offset compensation value for Gr channel */
+#define OFF_B       0x39 /* Analog process B  channel offset value */
+#define OFF_R       0x3A /* Analog process R  channel offset value */
+#define OFF_GB      0x3B /* Analog process Gb channel offset value */
+#define OFF_GR      0x3C /* Analog process Gr channel offset value */
+#define COM12       0x3D /* Common control 12 */
+#define COM13       0x3E /* Common control 13 */
+#define COM14       0x3F /* Common control 14 */
+#define COM15       0x40 /* Common control 15*/
+#define COM16       0x41 /* Common control 16 */
+#define TGT_B       0x42 /* BLC blue channel target value */
+#define TGT_R       0x43 /* BLC red  channel target value */
+#define TGT_GB      0x44 /* BLC Gb   channel target value */
+#define TGT_GR      0x45 /* BLC Gr   channel target value */
+/* for ov7720 */
+#define LCC0        0x46 /* Lens correction control 0 */
+#define LCC1        0x47 /* Lens correction option 1 - X coordinate */
+#define LCC2        0x48 /* Lens correction option 2 - Y coordinate */
+#define LCC3        0x49 /* Lens correction option 3 */
+#define LCC4        0x4A /* Lens correction option 4 - radius of the circular */
+#define LCC5        0x4B /* Lens correction option 5 */
+#define LCC6        0x4C /* Lens correction option 6 */
+/* for ov7725 */
+#define LC_CTR      0x46 /* Lens correction control */
+#define LC_XC       0x47 /* X coordinate of lens correction center relative */
+#define LC_YC       0x48 /* Y coordinate of lens correction center relative */
+#define LC_COEF     0x49 /* Lens correction coefficient */
+#define LC_RADI     0x4A /* Lens correction radius */
+#define LC_COEFB    0x4B /* Lens B channel compensation coefficient */
+#define LC_COEFR    0x4C /* Lens R channel compensation coefficient */
+
+#define FIXGAIN     0x4D /* Analog fix gain amplifer */
+#define AREF0       0x4E /* Sensor reference control */
+#define AREF1       0x4F /* Sensor reference current control */
+#define AREF2       0x50 /* Analog reference control */
+#define AREF3       0x51 /* ADC    reference control */
+#define AREF4       0x52 /* ADC    reference control */
+#define AREF5       0x53 /* ADC    reference control */
+#define AREF6       0x54 /* Analog reference control */
+#define AREF7       0x55 /* Analog reference control */
+#define UFIX        0x60 /* U channel fixed value output */
+#define VFIX        0x61 /* V channel fixed value output */
+#define AWBB_BLK    0x62 /* AWB option for advanced AWB */
+#define AWB_CTRL0   0x63 /* AWB control byte 0 */
+#define DSP_CTRL1   0x64 /* DSP control byte 1 */
+#define DSP_CTRL2   0x65 /* DSP control byte 2 */
+#define DSP_CTRL3   0x66 /* DSP control byte 3 */
+#define DSP_CTRL4   0x67 /* DSP control byte 4 */
+#define AWB_BIAS    0x68 /* AWB BLC level clip */
+#define AWB_CTRL1   0x69 /* AWB control  1 */
+#define AWB_CTRL2   0x6A /* AWB control  2 */
+#define AWB_CTRL3   0x6B /* AWB control  3 */
+#define AWB_CTRL4   0x6C /* AWB control  4 */
+#define AWB_CTRL5   0x6D /* AWB control  5 */
+#define AWB_CTRL6   0x6E /* AWB control  6 */
+#define AWB_CTRL7   0x6F /* AWB control  7 */
+#define AWB_CTRL8   0x70 /* AWB control  8 */
+#define AWB_CTRL9   0x71 /* AWB control  9 */
+#define AWB_CTRL10  0x72 /* AWB control 10 */
+#define AWB_CTRL11  0x73 /* AWB control 11 */
+#define AWB_CTRL12  0x74 /* AWB control 12 */
+#define AWB_CTRL13  0x75 /* AWB control 13 */
+#define AWB_CTRL14  0x76 /* AWB control 14 */
+#define AWB_CTRL15  0x77 /* AWB control 15 */
+#define AWB_CTRL16  0x78 /* AWB control 16 */
+#define AWB_CTRL17  0x79 /* AWB control 17 */
+#define AWB_CTRL18  0x7A /* AWB control 18 */
+#define AWB_CTRL19  0x7B /* AWB control 19 */
+#define AWB_CTRL20  0x7C /* AWB control 20 */
+#define AWB_CTRL21  0x7D /* AWB control 21 */
+#define GAM1        0x7E /* Gamma Curve  1st segment input end point */
+#define GAM2        0x7F /* Gamma Curve  2nd segment input end point */
+#define GAM3        0x80 /* Gamma Curve  3rd segment input end point */
+#define GAM4        0x81 /* Gamma Curve  4th segment input end point */
+#define GAM5        0x82 /* Gamma Curve  5th segment input end point */
+#define GAM6        0x83 /* Gamma Curve  6th segment input end point */
+#define GAM7        0x84 /* Gamma Curve  7th segment input end point */
+#define GAM8        0x85 /* Gamma Curve  8th segment input end point */
+#define GAM9        0x86 /* Gamma Curve  9th segment input end point */
+#define GAM10       0x87 /* Gamma Curve 10th segment input end point */
+#define GAM11       0x88 /* Gamma Curve 11th segment input end point */
+#define GAM12       0x89 /* Gamma Curve 12th segment input end point */
+#define GAM13       0x8A /* Gamma Curve 13th segment input end point */
+#define GAM14       0x8B /* Gamma Curve 14th segment input end point */
+#define GAM15       0x8C /* Gamma Curve 15th segment input end point */
+#define SLOP        0x8D /* Gamma curve highest segment slope */
+#define DNSTH       0x8E /* De-noise threshold */
+#define EDGE_STRNGT 0x8F /* Edge strength  control when manual mode */
+#define EDGE_TRSHLD 0x90 /* Edge threshold control when manual mode */
+#define DNSOFF      0x91 /* Auto De-noise threshold control */
+#define EDGE_UPPER  0x92 /* Edge strength upper limit when Auto mode */
+#define EDGE_LOWER  0x93 /* Edge strength lower limit when Auto mode */
+#define MTX1        0x94 /* Matrix coefficient 1 */
+#define MTX2        0x95 /* Matrix coefficient 2 */
+#define MTX3        0x96 /* Matrix coefficient 3 */
+#define MTX4        0x97 /* Matrix coefficient 4 */
+#define MTX5        0x98 /* Matrix coefficient 5 */
+#define MTX6        0x99 /* Matrix coefficient 6 */
+#define MTX_CTRL    0x9A /* Matrix control */
+#define BRIGHT      0x9B /* Brightness control */
+#define CNTRST      0x9C /* Contrast contrast */
+#define CNTRST_CTRL 0x9D /* Contrast contrast center */
+#define UVAD_J0     0x9E /* Auto UV adjust contrast 0 */
+#define UVAD_J1     0x9F /* Auto UV adjust contrast 1 */
+#define SCAL0       0xA0 /* Scaling control 0 */
+#define SCAL1       0xA1 /* Scaling control 1 */
+#define SCAL2       0xA2 /* Scaling control 2 */
+#define FIFODLYM    0xA3 /* FIFO manual mode delay control */
+#define FIFODLYA    0xA4 /* FIFO auto   mode delay control */
+#define SDE         0xA6 /* Special digital effect control */
+#define USAT        0xA7 /* U component saturation control */
+#define VSAT        0xA8 /* V component saturation control */
+/* for ov7720 */
+#define HUE0        0xA9 /* Hue control 0 */
+#define HUE1        0xAA /* Hue control 1 */
+/* for ov7725 */
+#define HUECOS      0xA9 /* Cosine value */
+#define HUESIN      0xAA /* Sine value */
+
+#define SIGN        0xAB /* Sign bit for Hue and contrast */
+#define DSPAUTO     0xAC /* DSP auto function ON/OFF control */
+
+/*
+ * register detail
+ */
+
+/* COM2 */
+#define SOFT_SLEEP_MODE 0x10	/* Soft sleep mode */
+				/* Output drive capability */
+#define OCAP_1x         0x00	/* 1x */
+#define OCAP_2x         0x01	/* 2x */
+#define OCAP_3x         0x02	/* 3x */
+#define OCAP_4x         0x03	/* 4x */
+
+/* COM3 */
+#define SWAP_MASK       (SWAP_RGB | SWAP_YUV | SWAP_ML)
+#define IMG_MASK        (VFLIP_IMG | HFLIP_IMG)
+
+#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 */
+				/* Tri-state option for output clock */
+#define NOTRI_CLOCK     0x04	/*   0: Tri-state    at this period */
+				/*   1: No tri-state at this period */
+				/* Tri-state option for output data */
+#define NOTRI_DATA      0x02	/*   0: Tri-state    at this period */
+				/*   1: No tri-state at this period */
+#define SCOLOR_TEST     0x01	/* Sensor color bar test pattern */
+
+/* COM4 */
+				/* PLL frequency control */
+#define PLL_BYPASS      0x00	/*  00: Bypass PLL */
+#define PLL_4x          0x40	/*  01: PLL 4x */
+#define PLL_6x          0x80	/*  10: PLL 6x */
+#define PLL_8x          0xc0	/*  11: PLL 8x */
+				/* AEC evaluate window */
+#define AEC_FULL        0x00	/*  00: Full window */
+#define AEC_1p2         0x10	/*  01: 1/2  window */
+#define AEC_1p4         0x20	/*  10: 1/4  window */
+#define AEC_2p3         0x30	/*  11: Low 2/3 window */
+
+/* COM5 */
+#define AFR_ON_OFF      0x80	/* Auto frame rate control ON/OFF selection */
+#define AFR_SPPED       0x40	/* Auto frame rate control speed selection */
+				/* Auto frame rate max rate control */
+#define AFR_NO_RATE     0x00	/*     No  reduction of frame rate */
+#define AFR_1p2         0x10	/*     Max reduction to 1/2 frame rate */
+#define AFR_1p4         0x20	/*     Max reduction to 1/4 frame rate */
+#define AFR_1p8         0x30	/* Max reduction to 1/8 frame rate */
+				/* Auto frame rate active point control */
+#define AF_2x           0x00	/*     Add frame when AGC reaches  2x gain */
+#define AF_4x           0x04	/*     Add frame when AGC reaches  4x gain */
+#define AF_8x           0x08	/*     Add frame when AGC reaches  8x gain */
+#define AF_16x          0x0c	/* Add frame when AGC reaches 16x gain */
+				/* AEC max step control */
+#define AEC_NO_LIMIT    0x01	/*   0 : AEC incease step has limit */
+				/*   1 : No limit to AEC increase step */
+
+/* COM7 */
+				/* SCCB Register Reset */
+#define SCCB_RESET      0x80	/*   0 : No change */
+				/*   1 : Resets all registers to default */
+				/* Resolution selection */
+#define SLCT_MASK       0x40	/*   Mask of VGA or QVGA */
+#define SLCT_VGA        0x00	/*   0 : VGA */
+#define SLCT_QVGA       0x40	/*   1 : QVGA */
+#define ITU656_ON_OFF   0x20	/* ITU656 protocol ON/OFF selection */
+#define SENSOR_RAW	0x10	/* Sensor RAW */
+				/* 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 */
+#define OFMT_BRAW       0x03	/* 11 : Bayer RAW */
+
+/* COM8 */
+#define FAST_ALGO       0x80	/* Enable fast AGC/AEC algorithm */
+				/* AEC Setp size limit */
+#define UNLMT_STEP      0x40	/*   0 : Step size is limited */
+				/*   1 : Unlimited step size */
+#define BNDF_ON_OFF     0x20	/* Banding filter ON/OFF */
+#define AEC_BND         0x10	/* Enable AEC below banding value */
+#define AEC_ON_OFF      0x08	/* Fine AEC ON/OFF control */
+#define AGC_ON          0x04	/* AGC Enable */
+#define AWB_ON          0x02	/* AWB Enable */
+#define AEC_ON          0x01	/* AEC Enable */
+
+/* COM9 */
+#define BASE_AECAGC     0x80	/* Histogram or average based AEC/AGC */
+				/* Automatic gain ceiling - maximum AGC value */
+#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_32x        0x40	/*    100 :  32x */
+#define GAIN_64x        0x50	/* 101 :  64x */
+#define GAIN_128x       0x60	/* 110 : 128x */
+#define DROP_VSYNC      0x04	/* Drop VSYNC output of corrupt frame */
+#define DROP_HREF       0x02	/* Drop HREF  output of corrupt frame */
+
+/* COM11 */
+#define SGLF_ON_OFF     0x02	/* Single frame ON/OFF selection */
+#define SGLF_TRIG       0x01	/* Single frame transfer trigger */
+
+/* HREF */
+#define HREF_VSTART_SHIFT	6	/* VSTART LSB */
+#define HREF_HSTART_SHIFT	4	/* HSTART 2 LSBs */
+#define HREF_VSIZE_SHIFT	2	/* VSIZE LSB */
+#define HREF_HSIZE_SHIFT	0	/* HSIZE 2 LSBs */
+
+/* EXHCH */
+#define EXHCH_VSIZE_SHIFT	2	/* VOUTSIZE LSB */
+#define EXHCH_HSIZE_SHIFT	0	/* HOUTSIZE 2 LSBs */
+
+/* DSP_CTRL1 */
+#define FIFO_ON         0x80	/* FIFO enable/disable selection */
+#define UV_ON_OFF       0x40	/* UV adjust function ON/OFF selection */
+#define YUV444_2_422    0x20	/* YUV444 to 422 UV channel option selection */
+#define CLR_MTRX_ON_OFF 0x10	/* Color matrix ON/OFF selection */
+#define INTPLT_ON_OFF   0x08	/* Interpolation ON/OFF selection */
+#define GMM_ON_OFF      0x04	/* Gamma function ON/OFF selection */
+#define AUTO_BLK_ON_OFF 0x02	/* Black defect auto correction ON/OFF */
+#define AUTO_WHT_ON_OFF 0x01	/* White define auto correction ON/OFF */
+
+/* DSP_CTRL3 */
+#define UV_MASK         0x80	/* UV output sequence option */
+#define UV_ON           0x80	/*   ON */
+#define UV_OFF          0x00	/*   OFF */
+#define CBAR_MASK       0x20	/* DSP Color bar mask */
+#define CBAR_ON         0x20	/*   ON */
+#define CBAR_OFF        0x00	/*   OFF */
+
+/* DSP_CTRL4 */
+#define DSP_OFMT_YUV	0x00
+#define DSP_OFMT_RGB	0x00
+#define DSP_OFMT_RAW8	0x02
+#define DSP_OFMT_RAW10	0x03
+
+/* DSPAUTO (DSP Auto Function ON/OFF Control) */
+#define AWB_ACTRL       0x80 /* AWB auto threshold control */
+#define DENOISE_ACTRL   0x40 /* De-noise auto threshold control */
+#define EDGE_ACTRL      0x20 /* Edge enhancement auto strength control */
+#define UV_ACTRL        0x10 /* UV adjust auto slope control */
+#define SCAL0_ACTRL     0x08 /* Auto scaling factor control */
+#define SCAL1_2_ACTRL   0x04 /* Auto scaling factor control */
+
+#define VGA_WIDTH		640
+#define VGA_HEIGHT		480
+#define QVGA_WIDTH		320
+#define QVGA_HEIGHT		240
+#define OV772X_MAX_WIDTH	VGA_WIDTH
+#define OV772X_MAX_HEIGHT	VGA_HEIGHT
+
+/*
+ * ID
+ */
+#define OV7720  0x7720
+#define OV7725  0x7721
+#define VERSION(pid, ver) ((pid<<8)|(ver&0xFF))
+
+/*
+ * struct
+ */
+
+struct ov772x_color_format {
+	enum v4l2_mbus_pixelcode code;
+	enum v4l2_colorspace colorspace;
+	u8 dsp3;
+	u8 dsp4;
+	u8 com3;
+	u8 com7;
+};
+
+struct ov772x_win_size {
+	char                     *name;
+	unsigned char             com7_bit;
+	struct v4l2_rect	  rect;
+};
+
+struct ov772x_priv {
+	struct v4l2_subdev                subdev;
+	struct v4l2_ctrl_handler	  hdl;
+	struct ov772x_camera_info        *info;
+	const struct ov772x_color_format *cfmt;
+	const struct ov772x_win_size     *win;
+	int                               model;
+	unsigned short                    flag_vflip:1;
+	unsigned short                    flag_hflip:1;
+	/* band_filter = COM8[5] ? 256 - BDBASE : 0 */
+	unsigned short                    band_filter;
+};
+
+/*
+ * supported color format list
+ */
+static const struct ov772x_color_format ov772x_cfmts[] = {
+	{
+		.code		= V4L2_MBUS_FMT_YUYV8_2X8,
+		.colorspace	= V4L2_COLORSPACE_JPEG,
+		.dsp3		= 0x0,
+		.dsp4		= DSP_OFMT_YUV,
+		.com3		= SWAP_YUV,
+		.com7		= OFMT_YUV,
+	},
+	{
+		.code		= V4L2_MBUS_FMT_YVYU8_2X8,
+		.colorspace	= V4L2_COLORSPACE_JPEG,
+		.dsp3		= UV_ON,
+		.dsp4		= DSP_OFMT_YUV,
+		.com3		= SWAP_YUV,
+		.com7		= OFMT_YUV,
+	},
+	{
+		.code		= V4L2_MBUS_FMT_UYVY8_2X8,
+		.colorspace	= V4L2_COLORSPACE_JPEG,
+		.dsp3		= 0x0,
+		.dsp4		= DSP_OFMT_YUV,
+		.com3		= 0x0,
+		.com7		= OFMT_YUV,
+	},
+	{
+		.code		= V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE,
+		.colorspace	= V4L2_COLORSPACE_SRGB,
+		.dsp3		= 0x0,
+		.dsp4		= DSP_OFMT_YUV,
+		.com3		= SWAP_RGB,
+		.com7		= FMT_RGB555 | OFMT_RGB,
+	},
+	{
+		.code		= V4L2_MBUS_FMT_RGB555_2X8_PADHI_BE,
+		.colorspace	= V4L2_COLORSPACE_SRGB,
+		.dsp3		= 0x0,
+		.dsp4		= DSP_OFMT_YUV,
+		.com3		= 0x0,
+		.com7		= FMT_RGB555 | OFMT_RGB,
+	},
+	{
+		.code		= V4L2_MBUS_FMT_RGB565_2X8_LE,
+		.colorspace	= V4L2_COLORSPACE_SRGB,
+		.dsp3		= 0x0,
+		.dsp4		= DSP_OFMT_YUV,
+		.com3		= SWAP_RGB,
+		.com7		= FMT_RGB565 | OFMT_RGB,
+	},
+	{
+		.code		= V4L2_MBUS_FMT_RGB565_2X8_BE,
+		.colorspace	= V4L2_COLORSPACE_SRGB,
+		.dsp3		= 0x0,
+		.dsp4		= DSP_OFMT_YUV,
+		.com3		= 0x0,
+		.com7		= FMT_RGB565 | OFMT_RGB,
+	},
+	{
+		/* Setting DSP4 to DSP_OFMT_RAW8 still gives 10-bit output,
+		 * regardless of the COM7 value. We can thus only support 10-bit
+		 * Bayer until someone figures it out.
+		 */
+		.code		= V4L2_MBUS_FMT_SBGGR10_1X10,
+		.colorspace	= V4L2_COLORSPACE_SRGB,
+		.dsp3		= 0x0,
+		.dsp4		= DSP_OFMT_RAW10,
+		.com3		= 0x0,
+		.com7		= SENSOR_RAW | OFMT_BRAW,
+	},
+};
+
+
+/*
+ * window size list
+ */
+
+static const struct ov772x_win_size ov772x_win_sizes[] = {
+	{
+		.name     = "VGA",
+		.com7_bit = SLCT_VGA,
+		.rect = {
+			.left = 140,
+			.top = 14,
+			.width = VGA_WIDTH,
+			.height = VGA_HEIGHT,
+		},
+	}, {
+		.name     = "QVGA",
+		.com7_bit = SLCT_QVGA,
+		.rect = {
+			.left = 252,
+			.top = 6,
+			.width = QVGA_WIDTH,
+			.height = QVGA_HEIGHT,
+		},
+	},
+};
+
+/*
+ * general function
+ */
+
+static struct ov772x_priv *to_ov772x(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct ov772x_priv, subdev);
+}
+
+static inline int ov772x_read(struct i2c_client *client, u8 addr)
+{
+	return i2c_smbus_read_byte_data(client, addr);
+}
+
+static inline int ov772x_write(struct i2c_client *client, u8 addr, u8 value)
+{
+	return i2c_smbus_write_byte_data(client, addr, value);
+}
+
+static int ov772x_mask_set(struct i2c_client *client, u8  command, u8  mask,
+			   u8  set)
+{
+	s32 val = ov772x_read(client, command);
+	if (val < 0)
+		return val;
+
+	val &= ~mask;
+	val |= set & mask;
+
+	return ov772x_write(client, command, val);
+}
+
+static int ov772x_reset(struct i2c_client *client)
+{
+	int ret;
+
+	ret = ov772x_write(client, COM7, SCCB_RESET);
+	if (ret < 0)
+		return ret;
+
+	msleep(1);
+
+	return ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE, SOFT_SLEEP_MODE);
+}
+
+/*
+ * soc_camera_ops function
+ */
+
+static int ov772x_s_stream(struct v4l2_subdev *sd, int enable)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct ov772x_priv *priv = to_ov772x(sd);
+
+	if (!enable) {
+		ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE, SOFT_SLEEP_MODE);
+		return 0;
+	}
+
+	ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE, 0);
+
+	dev_dbg(&client->dev, "format %d, win %s\n",
+		priv->cfmt->code, priv->win->name);
+
+	return 0;
+}
+
+static int ov772x_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct ov772x_priv *priv = container_of(ctrl->handler,
+						struct ov772x_priv, hdl);
+	struct v4l2_subdev *sd = &priv->subdev;
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	int ret = 0;
+	u8 val;
+
+	switch (ctrl->id) {
+	case V4L2_CID_VFLIP:
+		val = ctrl->val ? VFLIP_IMG : 0x00;
+		priv->flag_vflip = ctrl->val;
+		if (priv->info->flags & OV772X_FLAG_VFLIP)
+			val ^= VFLIP_IMG;
+		return ov772x_mask_set(client, COM3, VFLIP_IMG, val);
+	case V4L2_CID_HFLIP:
+		val = ctrl->val ? HFLIP_IMG : 0x00;
+		priv->flag_hflip = ctrl->val;
+		if (priv->info->flags & OV772X_FLAG_HFLIP)
+			val ^= HFLIP_IMG;
+		return ov772x_mask_set(client, COM3, HFLIP_IMG, val);
+	case V4L2_CID_BAND_STOP_FILTER:
+		if (!ctrl->val) {
+			/* Switch the filter off, it is on now */
+			ret = ov772x_mask_set(client, BDBASE, 0xff, 0xff);
+			if (!ret)
+				ret = ov772x_mask_set(client, COM8,
+						      BNDF_ON_OFF, 0);
+		} else {
+			/* Switch the filter on, set AEC low limit */
+			val = 256 - ctrl->val;
+			ret = ov772x_mask_set(client, COM8,
+					      BNDF_ON_OFF, BNDF_ON_OFF);
+			if (!ret)
+				ret = ov772x_mask_set(client, BDBASE,
+						      0xff, val);
+		}
+		if (!ret)
+			priv->band_filter = ctrl->val;
+		return ret;
+	}
+
+	return -EINVAL;
+}
+
+static int ov772x_g_chip_ident(struct v4l2_subdev *sd,
+			       struct v4l2_dbg_chip_ident *id)
+{
+	struct ov772x_priv *priv = to_ov772x(sd);
+
+	id->ident    = priv->model;
+	id->revision = 0;
+
+	return 0;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int ov772x_g_register(struct v4l2_subdev *sd,
+			     struct v4l2_dbg_register *reg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	int ret;
+
+	reg->size = 1;
+	if (reg->reg > 0xff)
+		return -EINVAL;
+
+	ret = ov772x_read(client, reg->reg);
+	if (ret < 0)
+		return ret;
+
+	reg->val = (__u64)ret;
+
+	return 0;
+}
+
+static int ov772x_s_register(struct v4l2_subdev *sd,
+			     struct v4l2_dbg_register *reg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	if (reg->reg > 0xff ||
+	    reg->val > 0xff)
+		return -EINVAL;
+
+	return ov772x_write(client, reg->reg, reg->val);
+}
+#endif
+
+static int ov772x_s_power(struct v4l2_subdev *sd, int on)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+	return soc_camera_set_power(&client->dev, icl, on);
+}
+
+static const struct ov772x_win_size *ov772x_select_win(u32 width, u32 height)
+{
+	const struct ov772x_win_size *win = &ov772x_win_sizes[0];
+	u32 best_diff = UINT_MAX;
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(ov772x_win_sizes); ++i) {
+		u32 diff = abs(width - ov772x_win_sizes[i].rect.width)
+			 + abs(height - ov772x_win_sizes[i].rect.height);
+		if (diff < best_diff) {
+			best_diff = diff;
+			win = &ov772x_win_sizes[i];
+		}
+	}
+
+	return win;
+}
+
+static void ov772x_select_params(const struct v4l2_mbus_framefmt *mf,
+				 const struct ov772x_color_format **cfmt,
+				 const struct ov772x_win_size **win)
+{
+	unsigned int i;
+
+	/* Select a format. */
+	*cfmt = &ov772x_cfmts[0];
+
+	for (i = 0; i < ARRAY_SIZE(ov772x_cfmts); i++) {
+		if (mf->code == ov772x_cfmts[i].code) {
+			*cfmt = &ov772x_cfmts[i];
+			break;
+		}
+	}
+
+	/* Select a window size. */
+	*win = ov772x_select_win(mf->width, mf->height);
+}
+
+static int ov772x_set_params(struct ov772x_priv *priv,
+			     const struct ov772x_color_format *cfmt,
+			     const struct ov772x_win_size *win)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&priv->subdev);
+	int ret;
+	u8  val;
+
+	/*
+	 * reset hardware
+	 */
+	ov772x_reset(client);
+
+	/*
+	 * Edge Ctrl
+	 */
+	if (priv->info->edgectrl.strength & OV772X_MANUAL_EDGE_CTRL) {
+
+		/*
+		 * Manual Edge Control Mode
+		 *
+		 * Edge auto strength bit is set by default.
+		 * Remove it when manual mode.
+		 */
+
+		ret = ov772x_mask_set(client, DSPAUTO, EDGE_ACTRL, 0x00);
+		if (ret < 0)
+			goto ov772x_set_fmt_error;
+
+		ret = ov772x_mask_set(client,
+				      EDGE_TRSHLD, OV772X_EDGE_THRESHOLD_MASK,
+				      priv->info->edgectrl.threshold);
+		if (ret < 0)
+			goto ov772x_set_fmt_error;
+
+		ret = ov772x_mask_set(client,
+				      EDGE_STRNGT, OV772X_EDGE_STRENGTH_MASK,
+				      priv->info->edgectrl.strength);
+		if (ret < 0)
+			goto ov772x_set_fmt_error;
+
+	} else if (priv->info->edgectrl.upper > priv->info->edgectrl.lower) {
+		/*
+		 * Auto Edge Control Mode
+		 *
+		 * set upper and lower limit
+		 */
+		ret = ov772x_mask_set(client,
+				      EDGE_UPPER, OV772X_EDGE_UPPER_MASK,
+				      priv->info->edgectrl.upper);
+		if (ret < 0)
+			goto ov772x_set_fmt_error;
+
+		ret = ov772x_mask_set(client,
+				      EDGE_LOWER, OV772X_EDGE_LOWER_MASK,
+				      priv->info->edgectrl.lower);
+		if (ret < 0)
+			goto ov772x_set_fmt_error;
+	}
+
+	/* Format and window size */
+	ret = ov772x_write(client, HSTART, win->rect.left >> 2);
+	if (ret < 0)
+		goto ov772x_set_fmt_error;
+	ret = ov772x_write(client, HSIZE, win->rect.width >> 2);
+	if (ret < 0)
+		goto ov772x_set_fmt_error;
+	ret = ov772x_write(client, VSTART, win->rect.top >> 1);
+	if (ret < 0)
+		goto ov772x_set_fmt_error;
+	ret = ov772x_write(client, VSIZE, win->rect.height >> 1);
+	if (ret < 0)
+		goto ov772x_set_fmt_error;
+	ret = ov772x_write(client, HOUTSIZE, win->rect.width >> 2);
+	if (ret < 0)
+		goto ov772x_set_fmt_error;
+	ret = ov772x_write(client, VOUTSIZE, win->rect.height >> 1);
+	if (ret < 0)
+		goto ov772x_set_fmt_error;
+	ret = ov772x_write(client, HREF,
+			   ((win->rect.top & 1) << HREF_VSTART_SHIFT) |
+			   ((win->rect.left & 3) << HREF_HSTART_SHIFT) |
+			   ((win->rect.height & 1) << HREF_VSIZE_SHIFT) |
+			   ((win->rect.width & 3) << HREF_HSIZE_SHIFT));
+	if (ret < 0)
+		goto ov772x_set_fmt_error;
+	ret = ov772x_write(client, EXHCH,
+			   ((win->rect.height & 1) << EXHCH_VSIZE_SHIFT) |
+			   ((win->rect.width & 3) << EXHCH_HSIZE_SHIFT));
+	if (ret < 0)
+		goto ov772x_set_fmt_error;
+
+	/*
+	 * set DSP_CTRL3
+	 */
+	val = cfmt->dsp3;
+	if (val) {
+		ret = ov772x_mask_set(client,
+				      DSP_CTRL3, UV_MASK, val);
+		if (ret < 0)
+			goto ov772x_set_fmt_error;
+	}
+
+	/* DSP_CTRL4: AEC reference point and DSP output format. */
+	if (cfmt->dsp4) {
+		ret = ov772x_write(client, DSP_CTRL4, cfmt->dsp4);
+		if (ret < 0)
+			goto ov772x_set_fmt_error;
+	}
+
+	/*
+	 * set COM3
+	 */
+	val = cfmt->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(client,
+			      COM3, SWAP_MASK | IMG_MASK, val);
+	if (ret < 0)
+		goto ov772x_set_fmt_error;
+
+	/* COM7: Sensor resolution and output format control. */
+	ret = ov772x_write(client, COM7, win->com7_bit | cfmt->com7);
+	if (ret < 0)
+		goto ov772x_set_fmt_error;
+
+	/*
+	 * set COM8
+	 */
+	if (priv->band_filter) {
+		ret = ov772x_mask_set(client, COM8, BNDF_ON_OFF, 1);
+		if (!ret)
+			ret = ov772x_mask_set(client, BDBASE,
+					      0xff, 256 - priv->band_filter);
+		if (ret < 0)
+			goto ov772x_set_fmt_error;
+	}
+
+	return ret;
+
+ov772x_set_fmt_error:
+
+	ov772x_reset(client);
+
+	return ret;
+}
+
+static int ov772x_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
+{
+	a->c.left	= 0;
+	a->c.top	= 0;
+	a->c.width	= VGA_WIDTH;
+	a->c.height	= VGA_HEIGHT;
+	a->type		= V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+	return 0;
+}
+
+static int ov772x_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
+{
+	a->bounds.left			= 0;
+	a->bounds.top			= 0;
+	a->bounds.width			= OV772X_MAX_WIDTH;
+	a->bounds.height		= OV772X_MAX_HEIGHT;
+	a->defrect			= a->bounds;
+	a->type				= V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	a->pixelaspect.numerator	= 1;
+	a->pixelaspect.denominator	= 1;
+
+	return 0;
+}
+
+static int ov772x_g_fmt(struct v4l2_subdev *sd,
+			struct v4l2_mbus_framefmt *mf)
+{
+	struct ov772x_priv *priv = to_ov772x(sd);
+
+	mf->width	= priv->win->rect.width;
+	mf->height	= priv->win->rect.height;
+	mf->code	= priv->cfmt->code;
+	mf->colorspace	= priv->cfmt->colorspace;
+	mf->field	= V4L2_FIELD_NONE;
+
+	return 0;
+}
+
+static int ov772x_s_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf)
+{
+	struct ov772x_priv *priv = to_ov772x(sd);
+	const struct ov772x_color_format *cfmt;
+	const struct ov772x_win_size *win;
+	int ret;
+
+	ov772x_select_params(mf, &cfmt, &win);
+
+	ret = ov772x_set_params(priv, cfmt, win);
+	if (ret < 0)
+		return ret;
+
+	priv->win = win;
+	priv->cfmt = cfmt;
+
+	mf->code = cfmt->code;
+	mf->width = win->rect.width;
+	mf->height = win->rect.height;
+	mf->field = V4L2_FIELD_NONE;
+	mf->colorspace = cfmt->colorspace;
+
+	return 0;
+}
+
+static int ov772x_try_fmt(struct v4l2_subdev *sd,
+			  struct v4l2_mbus_framefmt *mf)
+{
+	const struct ov772x_color_format *cfmt;
+	const struct ov772x_win_size *win;
+
+	ov772x_select_params(mf, &cfmt, &win);
+
+	mf->code = cfmt->code;
+	mf->width = win->rect.width;
+	mf->height = win->rect.height;
+	mf->field = V4L2_FIELD_NONE;
+	mf->colorspace = cfmt->colorspace;
+
+	return 0;
+}
+
+static int ov772x_video_probe(struct ov772x_priv *priv)
+{
+	struct i2c_client  *client = v4l2_get_subdevdata(&priv->subdev);
+	u8                  pid, ver;
+	const char         *devname;
+	int		    ret;
+
+	ret = ov772x_s_power(&priv->subdev, 1);
+	if (ret < 0)
+		return ret;
+
+	/*
+	 * check and show product ID and manufacturer ID
+	 */
+	pid = ov772x_read(client, PID);
+	ver = ov772x_read(client, VER);
+
+	switch (VERSION(pid, ver)) {
+	case OV7720:
+		devname     = "ov7720";
+		priv->model = V4L2_IDENT_OV7720;
+		break;
+	case OV7725:
+		devname     = "ov7725";
+		priv->model = V4L2_IDENT_OV7725;
+		break;
+	default:
+		dev_err(&client->dev,
+			"Product ID error %x:%x\n", pid, ver);
+		ret = -ENODEV;
+		goto done;
+	}
+
+	dev_info(&client->dev,
+		 "%s Product ID %0x:%0x Manufacturer ID %x:%x\n",
+		 devname,
+		 pid,
+		 ver,
+		 ov772x_read(client, MIDH),
+		 ov772x_read(client, MIDL));
+	ret = v4l2_ctrl_handler_setup(&priv->hdl);
+
+done:
+	ov772x_s_power(&priv->subdev, 0);
+	return ret;
+}
+
+static const struct v4l2_ctrl_ops ov772x_ctrl_ops = {
+	.s_ctrl = ov772x_s_ctrl,
+};
+
+static struct v4l2_subdev_core_ops ov772x_subdev_core_ops = {
+	.g_chip_ident	= ov772x_g_chip_ident,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.g_register	= ov772x_g_register,
+	.s_register	= ov772x_s_register,
+#endif
+	.s_power	= ov772x_s_power,
+};
+
+static int ov772x_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
+			   enum v4l2_mbus_pixelcode *code)
+{
+	if (index >= ARRAY_SIZE(ov772x_cfmts))
+		return -EINVAL;
+
+	*code = ov772x_cfmts[index].code;
+	return 0;
+}
+
+static int ov772x_g_mbus_config(struct v4l2_subdev *sd,
+				struct v4l2_mbus_config *cfg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+	cfg->flags = V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_MASTER |
+		V4L2_MBUS_VSYNC_ACTIVE_HIGH | V4L2_MBUS_HSYNC_ACTIVE_HIGH |
+		V4L2_MBUS_DATA_ACTIVE_HIGH;
+	cfg->type = V4L2_MBUS_PARALLEL;
+	cfg->flags = soc_camera_apply_board_flags(icl, cfg);
+
+	return 0;
+}
+
+static struct v4l2_subdev_video_ops ov772x_subdev_video_ops = {
+	.s_stream	= ov772x_s_stream,
+	.g_mbus_fmt	= ov772x_g_fmt,
+	.s_mbus_fmt	= ov772x_s_fmt,
+	.try_mbus_fmt	= ov772x_try_fmt,
+	.cropcap	= ov772x_cropcap,
+	.g_crop		= ov772x_g_crop,
+	.enum_mbus_fmt	= ov772x_enum_fmt,
+	.g_mbus_config	= ov772x_g_mbus_config,
+};
+
+static struct v4l2_subdev_ops ov772x_subdev_ops = {
+	.core	= &ov772x_subdev_core_ops,
+	.video	= &ov772x_subdev_video_ops,
+};
+
+/*
+ * i2c_driver function
+ */
+
+static int ov772x_probe(struct i2c_client *client,
+			const struct i2c_device_id *did)
+{
+	struct ov772x_priv	*priv;
+	struct soc_camera_link	*icl = soc_camera_i2c_to_link(client);
+	struct i2c_adapter	*adapter = to_i2c_adapter(client->dev.parent);
+	int			ret;
+
+	if (!icl || !icl->priv) {
+		dev_err(&client->dev, "OV772X: missing platform data!\n");
+		return -EINVAL;
+	}
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
+		dev_err(&adapter->dev,
+			"I2C-Adapter doesn't support "
+			"I2C_FUNC_SMBUS_BYTE_DATA\n");
+		return -EIO;
+	}
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->info = icl->priv;
+
+	v4l2_i2c_subdev_init(&priv->subdev, client, &ov772x_subdev_ops);
+	v4l2_ctrl_handler_init(&priv->hdl, 3);
+	v4l2_ctrl_new_std(&priv->hdl, &ov772x_ctrl_ops,
+			V4L2_CID_VFLIP, 0, 1, 1, 0);
+	v4l2_ctrl_new_std(&priv->hdl, &ov772x_ctrl_ops,
+			V4L2_CID_HFLIP, 0, 1, 1, 0);
+	v4l2_ctrl_new_std(&priv->hdl, &ov772x_ctrl_ops,
+			V4L2_CID_BAND_STOP_FILTER, 0, 256, 1, 0);
+	priv->subdev.ctrl_handler = &priv->hdl;
+	if (priv->hdl.error) {
+		ret = priv->hdl.error;
+		goto done;
+	}
+
+	ret = ov772x_video_probe(priv);
+	if (ret < 0)
+		goto done;
+
+	priv->cfmt = &ov772x_cfmts[0];
+	priv->win = &ov772x_win_sizes[0];
+
+done:
+	if (ret) {
+		v4l2_ctrl_handler_free(&priv->hdl);
+		kfree(priv);
+	}
+	return ret;
+}
+
+static int ov772x_remove(struct i2c_client *client)
+{
+	struct ov772x_priv *priv = to_ov772x(i2c_get_clientdata(client));
+
+	v4l2_device_unregister_subdev(&priv->subdev);
+	v4l2_ctrl_handler_free(&priv->hdl);
+	kfree(priv);
+	return 0;
+}
+
+static const struct i2c_device_id ov772x_id[] = {
+	{ "ov772x", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, ov772x_id);
+
+static struct i2c_driver ov772x_i2c_driver = {
+	.driver = {
+		.name = "ov772x",
+	},
+	.probe    = ov772x_probe,
+	.remove   = ov772x_remove,
+	.id_table = ov772x_id,
+};
+
+module_i2c_driver(ov772x_i2c_driver);
+
+MODULE_DESCRIPTION("SoC Camera driver for ov772x");
+MODULE_AUTHOR("Kuninori Morimoto");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/i2c/soc_camera/ov9640.c b/drivers/media/i2c/soc_camera/ov9640.c
new file mode 100644
index 0000000..b323684
--- /dev/null
+++ b/drivers/media/i2c/soc_camera/ov9640.c
@@ -0,0 +1,763 @@
+/*
+ * OmniVision OV96xx Camera Driver
+ *
+ * Copyright (C) 2009 Marek Vasut <marek.vasut@gmail.com>
+ *
+ * Based on ov772x camera driver:
+ *
+ * Copyright (C) 2008 Renesas Solutions Corp.
+ * Kuninori Morimoto <morimoto.kuninori@renesas.com>
+ *
+ * Based on ov7670 and soc_camera_platform driver,
+ *
+ * Copyright 2006-7 Jonathan Corbet <corbet@lwn.net>
+ * Copyright (C) 2008 Magnus Damm
+ * Copyright (C) 2008, Guennadi Liakhovetski <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 version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/v4l2-mediabus.h>
+#include <linux/videodev2.h>
+
+#include <media/soc_camera.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ctrls.h>
+
+#include "ov9640.h"
+
+#define to_ov9640_sensor(sd)	container_of(sd, struct ov9640_priv, subdev)
+
+/* default register setup */
+static const struct ov9640_reg ov9640_regs_dflt[] = {
+	{ OV9640_COM5,	OV9640_COM5_SYSCLK | OV9640_COM5_LONGEXP },
+	{ OV9640_COM6,	OV9640_COM6_OPT_BLC | OV9640_COM6_ADBLC_BIAS |
+			OV9640_COM6_FMT_RST | OV9640_COM6_ADBLC_OPTEN },
+	{ OV9640_PSHFT,	OV9640_PSHFT_VAL(0x01) },
+	{ OV9640_ACOM,	OV9640_ACOM_2X_ANALOG | OV9640_ACOM_RSVD },
+	{ OV9640_TSLB,	OV9640_TSLB_YUYV_UYVY },
+	{ OV9640_COM16,	OV9640_COM16_RB_AVG },
+
+	/* Gamma curve P */
+	{ 0x6c, 0x40 },	{ 0x6d, 0x30 },	{ 0x6e, 0x4b },	{ 0x6f, 0x60 },
+	{ 0x70, 0x70 },	{ 0x71, 0x70 },	{ 0x72, 0x70 },	{ 0x73, 0x70 },
+	{ 0x74, 0x60 },	{ 0x75, 0x60 },	{ 0x76, 0x50 },	{ 0x77, 0x48 },
+	{ 0x78, 0x3a },	{ 0x79, 0x2e },	{ 0x7a, 0x28 },	{ 0x7b, 0x22 },
+
+	/* Gamma curve T */
+	{ 0x7c, 0x04 },	{ 0x7d, 0x07 },	{ 0x7e, 0x10 },	{ 0x7f, 0x28 },
+	{ 0x80, 0x36 },	{ 0x81, 0x44 },	{ 0x82, 0x52 },	{ 0x83, 0x60 },
+	{ 0x84, 0x6c },	{ 0x85, 0x78 },	{ 0x86, 0x8c },	{ 0x87, 0x9e },
+	{ 0x88, 0xbb },	{ 0x89, 0xd2 },	{ 0x8a, 0xe6 },
+};
+
+/* Configurations
+ * NOTE: for YUV, alter the following registers:
+ * 		COM12 |= OV9640_COM12_YUV_AVG
+ *
+ *	 for RGB, alter the following registers:
+ *		COM7  |= OV9640_COM7_RGB
+ *		COM13 |= OV9640_COM13_RGB_AVG
+ *		COM15 |= proper RGB color encoding mode
+ */
+static const struct ov9640_reg ov9640_regs_qqcif[] = {
+	{ OV9640_CLKRC,	OV9640_CLKRC_DPLL_EN | OV9640_CLKRC_DIV(0x0f) },
+	{ OV9640_COM1,	OV9640_COM1_QQFMT | OV9640_COM1_HREF_2SKIP },
+	{ OV9640_COM4,	OV9640_COM4_QQ_VP | OV9640_COM4_RSVD },
+	{ OV9640_COM7,	OV9640_COM7_QCIF },
+	{ OV9640_COM12,	OV9640_COM12_RSVD },
+	{ OV9640_COM13,	OV9640_COM13_GAMMA_RAW | OV9640_COM13_MATRIX_EN },
+	{ OV9640_COM15,	OV9640_COM15_OR_10F0 },
+};
+
+static const struct ov9640_reg ov9640_regs_qqvga[] = {
+	{ OV9640_CLKRC,	OV9640_CLKRC_DPLL_EN | OV9640_CLKRC_DIV(0x07) },
+	{ OV9640_COM1,	OV9640_COM1_QQFMT | OV9640_COM1_HREF_2SKIP },
+	{ OV9640_COM4,	OV9640_COM4_QQ_VP | OV9640_COM4_RSVD },
+	{ OV9640_COM7,	OV9640_COM7_QVGA },
+	{ OV9640_COM12,	OV9640_COM12_RSVD },
+	{ OV9640_COM13,	OV9640_COM13_GAMMA_RAW | OV9640_COM13_MATRIX_EN },
+	{ OV9640_COM15,	OV9640_COM15_OR_10F0 },
+};
+
+static const struct ov9640_reg ov9640_regs_qcif[] = {
+	{ OV9640_CLKRC,	OV9640_CLKRC_DPLL_EN | OV9640_CLKRC_DIV(0x07) },
+	{ OV9640_COM4,	OV9640_COM4_QQ_VP | OV9640_COM4_RSVD },
+	{ OV9640_COM7,	OV9640_COM7_QCIF },
+	{ OV9640_COM12,	OV9640_COM12_RSVD },
+	{ OV9640_COM13,	OV9640_COM13_GAMMA_RAW | OV9640_COM13_MATRIX_EN },
+	{ OV9640_COM15,	OV9640_COM15_OR_10F0 },
+};
+
+static const struct ov9640_reg ov9640_regs_qvga[] = {
+	{ OV9640_CLKRC,	OV9640_CLKRC_DPLL_EN | OV9640_CLKRC_DIV(0x03) },
+	{ OV9640_COM4,	OV9640_COM4_QQ_VP | OV9640_COM4_RSVD },
+	{ OV9640_COM7,	OV9640_COM7_QVGA },
+	{ OV9640_COM12,	OV9640_COM12_RSVD },
+	{ OV9640_COM13,	OV9640_COM13_GAMMA_RAW | OV9640_COM13_MATRIX_EN },
+	{ OV9640_COM15,	OV9640_COM15_OR_10F0 },
+};
+
+static const struct ov9640_reg ov9640_regs_cif[] = {
+	{ OV9640_CLKRC,	OV9640_CLKRC_DPLL_EN | OV9640_CLKRC_DIV(0x03) },
+	{ OV9640_COM3,	OV9640_COM3_VP },
+	{ OV9640_COM7,	OV9640_COM7_CIF },
+	{ OV9640_COM12,	OV9640_COM12_RSVD },
+	{ OV9640_COM13,	OV9640_COM13_GAMMA_RAW | OV9640_COM13_MATRIX_EN },
+	{ OV9640_COM15,	OV9640_COM15_OR_10F0 },
+};
+
+static const struct ov9640_reg ov9640_regs_vga[] = {
+	{ OV9640_CLKRC,	OV9640_CLKRC_DPLL_EN | OV9640_CLKRC_DIV(0x01) },
+	{ OV9640_COM3,	OV9640_COM3_VP },
+	{ OV9640_COM7,	OV9640_COM7_VGA },
+	{ OV9640_COM12,	OV9640_COM12_RSVD },
+	{ OV9640_COM13,	OV9640_COM13_GAMMA_RAW | OV9640_COM13_MATRIX_EN },
+	{ OV9640_COM15,	OV9640_COM15_OR_10F0 },
+};
+
+static const struct ov9640_reg ov9640_regs_sxga[] = {
+	{ OV9640_CLKRC,	OV9640_CLKRC_DPLL_EN | OV9640_CLKRC_DIV(0x01) },
+	{ OV9640_COM3,	OV9640_COM3_VP },
+	{ OV9640_COM7,	0 },
+	{ OV9640_COM12,	OV9640_COM12_RSVD },
+	{ OV9640_COM13,	OV9640_COM13_GAMMA_RAW | OV9640_COM13_MATRIX_EN },
+	{ OV9640_COM15,	OV9640_COM15_OR_10F0 },
+};
+
+static const struct ov9640_reg ov9640_regs_yuv[] = {
+	{ OV9640_MTX1,	0x58 },
+	{ OV9640_MTX2,	0x48 },
+	{ OV9640_MTX3,	0x10 },
+	{ OV9640_MTX4,	0x28 },
+	{ OV9640_MTX5,	0x48 },
+	{ OV9640_MTX6,	0x70 },
+	{ OV9640_MTX7,	0x40 },
+	{ OV9640_MTX8,	0x40 },
+	{ OV9640_MTX9,	0x40 },
+	{ OV9640_MTXS,	0x0f },
+};
+
+static const struct ov9640_reg ov9640_regs_rgb[] = {
+	{ OV9640_MTX1,	0x71 },
+	{ OV9640_MTX2,	0x3e },
+	{ OV9640_MTX3,	0x0c },
+	{ OV9640_MTX4,	0x33 },
+	{ OV9640_MTX5,	0x72 },
+	{ OV9640_MTX6,	0x00 },
+	{ OV9640_MTX7,	0x2b },
+	{ OV9640_MTX8,	0x66 },
+	{ OV9640_MTX9,	0xd2 },
+	{ OV9640_MTXS,	0x65 },
+};
+
+static enum v4l2_mbus_pixelcode ov9640_codes[] = {
+	V4L2_MBUS_FMT_UYVY8_2X8,
+	V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE,
+	V4L2_MBUS_FMT_RGB565_2X8_LE,
+};
+
+/* read a register */
+static int ov9640_reg_read(struct i2c_client *client, u8 reg, u8 *val)
+{
+	int ret;
+	u8 data = reg;
+	struct i2c_msg msg = {
+		.addr	= client->addr,
+		.flags	= 0,
+		.len	= 1,
+		.buf	= &data,
+	};
+
+	ret = i2c_transfer(client->adapter, &msg, 1);
+	if (ret < 0)
+		goto err;
+
+	msg.flags = I2C_M_RD;
+	ret = i2c_transfer(client->adapter, &msg, 1);
+	if (ret < 0)
+		goto err;
+
+	*val = data;
+	return 0;
+
+err:
+	dev_err(&client->dev, "Failed reading register 0x%02x!\n", reg);
+	return ret;
+}
+
+/* write a register */
+static int ov9640_reg_write(struct i2c_client *client, u8 reg, u8 val)
+{
+	int ret;
+	u8 _val;
+	unsigned char data[2] = { reg, val };
+	struct i2c_msg msg = {
+		.addr	= client->addr,
+		.flags	= 0,
+		.len	= 2,
+		.buf	= data,
+	};
+
+	ret = i2c_transfer(client->adapter, &msg, 1);
+	if (ret < 0) {
+		dev_err(&client->dev, "Failed writing register 0x%02x!\n", reg);
+		return ret;
+	}
+
+	/* we have to read the register back ... no idea why, maybe HW bug */
+	ret = ov9640_reg_read(client, reg, &_val);
+	if (ret)
+		dev_err(&client->dev,
+			"Failed reading back register 0x%02x!\n", reg);
+
+	return 0;
+}
+
+
+/* Read a register, alter its bits, write it back */
+static int ov9640_reg_rmw(struct i2c_client *client, u8 reg, u8 set, u8 unset)
+{
+	u8 val;
+	int ret;
+
+	ret = ov9640_reg_read(client, reg, &val);
+	if (ret) {
+		dev_err(&client->dev,
+			"[Read]-Modify-Write of register %02x failed!\n", reg);
+		return val;
+	}
+
+	val |= set;
+	val &= ~unset;
+
+	ret = ov9640_reg_write(client, reg, val);
+	if (ret)
+		dev_err(&client->dev,
+			"Read-Modify-[Write] of register %02x failed!\n", reg);
+
+	return ret;
+}
+
+/* Soft reset the camera. This has nothing to do with the RESET pin! */
+static int ov9640_reset(struct i2c_client *client)
+{
+	int ret;
+
+	ret = ov9640_reg_write(client, OV9640_COM7, OV9640_COM7_SCCB_RESET);
+	if (ret)
+		dev_err(&client->dev,
+			"An error occurred while entering soft reset!\n");
+
+	return ret;
+}
+
+/* Start/Stop streaming from the device */
+static int ov9640_s_stream(struct v4l2_subdev *sd, int enable)
+{
+	return 0;
+}
+
+/* Set status of additional camera capabilities */
+static int ov9640_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct ov9640_priv *priv = container_of(ctrl->handler, struct ov9640_priv, hdl);
+	struct i2c_client *client = v4l2_get_subdevdata(&priv->subdev);
+
+	switch (ctrl->id) {
+	case V4L2_CID_VFLIP:
+		if (ctrl->val)
+			return ov9640_reg_rmw(client, OV9640_MVFP,
+							OV9640_MVFP_V, 0);
+		return ov9640_reg_rmw(client, OV9640_MVFP, 0, OV9640_MVFP_V);
+	case V4L2_CID_HFLIP:
+		if (ctrl->val)
+			return ov9640_reg_rmw(client, OV9640_MVFP,
+							OV9640_MVFP_H, 0);
+		return ov9640_reg_rmw(client, OV9640_MVFP, 0, OV9640_MVFP_H);
+	}
+	return -EINVAL;
+}
+
+/* Get chip identification */
+static int ov9640_g_chip_ident(struct v4l2_subdev *sd,
+				struct v4l2_dbg_chip_ident *id)
+{
+	struct ov9640_priv *priv = to_ov9640_sensor(sd);
+
+	id->ident	= priv->model;
+	id->revision	= priv->revision;
+
+	return 0;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int ov9640_get_register(struct v4l2_subdev *sd,
+				struct v4l2_dbg_register *reg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	int ret;
+	u8 val;
+
+	if (reg->reg & ~0xff)
+		return -EINVAL;
+
+	reg->size = 1;
+
+	ret = ov9640_reg_read(client, reg->reg, &val);
+	if (ret)
+		return ret;
+
+	reg->val = (__u64)val;
+
+	return 0;
+}
+
+static int ov9640_set_register(struct v4l2_subdev *sd,
+				struct v4l2_dbg_register *reg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	if (reg->reg & ~0xff || reg->val & ~0xff)
+		return -EINVAL;
+
+	return ov9640_reg_write(client, reg->reg, reg->val);
+}
+#endif
+
+static int ov9640_s_power(struct v4l2_subdev *sd, int on)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+	return soc_camera_set_power(&client->dev, icl, on);
+}
+
+/* select nearest higher resolution for capture */
+static void ov9640_res_roundup(u32 *width, u32 *height)
+{
+	int i;
+	enum { QQCIF, QQVGA, QCIF, QVGA, CIF, VGA, SXGA };
+	int res_x[] = { 88, 160, 176, 320, 352, 640, 1280 };
+	int res_y[] = { 72, 120, 144, 240, 288, 480, 960 };
+
+	for (i = 0; i < ARRAY_SIZE(res_x); i++) {
+		if (res_x[i] >= *width && res_y[i] >= *height) {
+			*width = res_x[i];
+			*height = res_y[i];
+			return;
+		}
+	}
+
+	*width = res_x[SXGA];
+	*height = res_y[SXGA];
+}
+
+/* Prepare necessary register changes depending on color encoding */
+static void ov9640_alter_regs(enum v4l2_mbus_pixelcode code,
+			      struct ov9640_reg_alt *alt)
+{
+	switch (code) {
+	default:
+	case V4L2_MBUS_FMT_UYVY8_2X8:
+		alt->com12	= OV9640_COM12_YUV_AVG;
+		alt->com13	= OV9640_COM13_Y_DELAY_EN |
+					OV9640_COM13_YUV_DLY(0x01);
+		break;
+	case V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE:
+		alt->com7	= OV9640_COM7_RGB;
+		alt->com13	= OV9640_COM13_RGB_AVG;
+		alt->com15	= OV9640_COM15_RGB_555;
+		break;
+	case V4L2_MBUS_FMT_RGB565_2X8_LE:
+		alt->com7	= OV9640_COM7_RGB;
+		alt->com13	= OV9640_COM13_RGB_AVG;
+		alt->com15	= OV9640_COM15_RGB_565;
+		break;
+	};
+}
+
+/* Setup registers according to resolution and color encoding */
+static int ov9640_write_regs(struct i2c_client *client, u32 width,
+		enum v4l2_mbus_pixelcode code, struct ov9640_reg_alt *alts)
+{
+	const struct ov9640_reg	*ov9640_regs, *matrix_regs;
+	int			ov9640_regs_len, matrix_regs_len;
+	int			i, ret;
+	u8			val;
+
+	/* select register configuration for given resolution */
+	switch (width) {
+	case W_QQCIF:
+		ov9640_regs	= ov9640_regs_qqcif;
+		ov9640_regs_len	= ARRAY_SIZE(ov9640_regs_qqcif);
+		break;
+	case W_QQVGA:
+		ov9640_regs	= ov9640_regs_qqvga;
+		ov9640_regs_len	= ARRAY_SIZE(ov9640_regs_qqvga);
+		break;
+	case W_QCIF:
+		ov9640_regs	= ov9640_regs_qcif;
+		ov9640_regs_len	= ARRAY_SIZE(ov9640_regs_qcif);
+		break;
+	case W_QVGA:
+		ov9640_regs	= ov9640_regs_qvga;
+		ov9640_regs_len	= ARRAY_SIZE(ov9640_regs_qvga);
+		break;
+	case W_CIF:
+		ov9640_regs	= ov9640_regs_cif;
+		ov9640_regs_len	= ARRAY_SIZE(ov9640_regs_cif);
+		break;
+	case W_VGA:
+		ov9640_regs	= ov9640_regs_vga;
+		ov9640_regs_len	= ARRAY_SIZE(ov9640_regs_vga);
+		break;
+	case W_SXGA:
+		ov9640_regs	= ov9640_regs_sxga;
+		ov9640_regs_len	= ARRAY_SIZE(ov9640_regs_sxga);
+		break;
+	default:
+		dev_err(&client->dev, "Failed to select resolution!\n");
+		return -EINVAL;
+	}
+
+	/* select color matrix configuration for given color encoding */
+	if (code == V4L2_MBUS_FMT_UYVY8_2X8) {
+		matrix_regs	= ov9640_regs_yuv;
+		matrix_regs_len	= ARRAY_SIZE(ov9640_regs_yuv);
+	} else {
+		matrix_regs	= ov9640_regs_rgb;
+		matrix_regs_len	= ARRAY_SIZE(ov9640_regs_rgb);
+	}
+
+	/* write register settings into the module */
+	for (i = 0; i < ov9640_regs_len; i++) {
+		val = ov9640_regs[i].val;
+
+		switch (ov9640_regs[i].reg) {
+		case OV9640_COM7:
+			val |= alts->com7;
+			break;
+		case OV9640_COM12:
+			val |= alts->com12;
+			break;
+		case OV9640_COM13:
+			val |= alts->com13;
+			break;
+		case OV9640_COM15:
+			val |= alts->com15;
+			break;
+		}
+
+		ret = ov9640_reg_write(client, ov9640_regs[i].reg, val);
+		if (ret)
+			return ret;
+	}
+
+	/* write color matrix configuration into the module */
+	for (i = 0; i < matrix_regs_len; i++) {
+		ret = ov9640_reg_write(client, matrix_regs[i].reg,
+						matrix_regs[i].val);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+/* program default register values */
+static int ov9640_prog_dflt(struct i2c_client *client)
+{
+	int i, ret;
+
+	for (i = 0; i < ARRAY_SIZE(ov9640_regs_dflt); i++) {
+		ret = ov9640_reg_write(client, ov9640_regs_dflt[i].reg,
+						ov9640_regs_dflt[i].val);
+		if (ret)
+			return ret;
+	}
+
+	/* wait for the changes to actually happen, 140ms are not enough yet */
+	mdelay(150);
+
+	return 0;
+}
+
+/* set the format we will capture in */
+static int ov9640_s_fmt(struct v4l2_subdev *sd,
+			struct v4l2_mbus_framefmt *mf)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct ov9640_reg_alt alts = {0};
+	enum v4l2_colorspace cspace;
+	enum v4l2_mbus_pixelcode code = mf->code;
+	int ret;
+
+	ov9640_res_roundup(&mf->width, &mf->height);
+	ov9640_alter_regs(mf->code, &alts);
+
+	ov9640_reset(client);
+
+	ret = ov9640_prog_dflt(client);
+	if (ret)
+		return ret;
+
+	switch (code) {
+	case V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE:
+	case V4L2_MBUS_FMT_RGB565_2X8_LE:
+		cspace = V4L2_COLORSPACE_SRGB;
+		break;
+	default:
+		code = V4L2_MBUS_FMT_UYVY8_2X8;
+	case V4L2_MBUS_FMT_UYVY8_2X8:
+		cspace = V4L2_COLORSPACE_JPEG;
+	}
+
+	ret = ov9640_write_regs(client, mf->width, code, &alts);
+	if (!ret) {
+		mf->code	= code;
+		mf->colorspace	= cspace;
+	}
+
+	return ret;
+}
+
+static int ov9640_try_fmt(struct v4l2_subdev *sd,
+			  struct v4l2_mbus_framefmt *mf)
+{
+	ov9640_res_roundup(&mf->width, &mf->height);
+
+	mf->field = V4L2_FIELD_NONE;
+
+	switch (mf->code) {
+	case V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE:
+	case V4L2_MBUS_FMT_RGB565_2X8_LE:
+		mf->colorspace = V4L2_COLORSPACE_SRGB;
+		break;
+	default:
+		mf->code = V4L2_MBUS_FMT_UYVY8_2X8;
+	case V4L2_MBUS_FMT_UYVY8_2X8:
+		mf->colorspace = V4L2_COLORSPACE_JPEG;
+	}
+
+	return 0;
+}
+
+static int ov9640_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
+			   enum v4l2_mbus_pixelcode *code)
+{
+	if (index >= ARRAY_SIZE(ov9640_codes))
+		return -EINVAL;
+
+	*code = ov9640_codes[index];
+	return 0;
+}
+
+static int ov9640_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
+{
+	a->c.left	= 0;
+	a->c.top	= 0;
+	a->c.width	= W_SXGA;
+	a->c.height	= H_SXGA;
+	a->type		= V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+	return 0;
+}
+
+static int ov9640_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
+{
+	a->bounds.left			= 0;
+	a->bounds.top			= 0;
+	a->bounds.width			= W_SXGA;
+	a->bounds.height		= H_SXGA;
+	a->defrect			= a->bounds;
+	a->type				= V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	a->pixelaspect.numerator	= 1;
+	a->pixelaspect.denominator	= 1;
+
+	return 0;
+}
+
+static int ov9640_video_probe(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct ov9640_priv *priv = to_ov9640_sensor(sd);
+	u8		pid, ver, midh, midl;
+	const char	*devname;
+	int		ret;
+
+	ret = ov9640_s_power(&priv->subdev, 1);
+	if (ret < 0)
+		return ret;
+
+	/*
+	 * check and show product ID and manufacturer ID
+	 */
+
+	ret = ov9640_reg_read(client, OV9640_PID, &pid);
+	if (!ret)
+		ret = ov9640_reg_read(client, OV9640_VER, &ver);
+	if (!ret)
+		ret = ov9640_reg_read(client, OV9640_MIDH, &midh);
+	if (!ret)
+		ret = ov9640_reg_read(client, OV9640_MIDL, &midl);
+	if (ret)
+		goto done;
+
+	switch (VERSION(pid, ver)) {
+	case OV9640_V2:
+		devname		= "ov9640";
+		priv->model	= V4L2_IDENT_OV9640;
+		priv->revision	= 2;
+		break;
+	case OV9640_V3:
+		devname		= "ov9640";
+		priv->model	= V4L2_IDENT_OV9640;
+		priv->revision	= 3;
+		break;
+	default:
+		dev_err(&client->dev, "Product ID error %x:%x\n", pid, ver);
+		ret = -ENODEV;
+		goto done;
+	}
+
+	dev_info(&client->dev, "%s Product ID %0x:%0x Manufacturer ID %x:%x\n",
+		 devname, pid, ver, midh, midl);
+
+	ret = v4l2_ctrl_handler_setup(&priv->hdl);
+
+done:
+	ov9640_s_power(&priv->subdev, 0);
+	return ret;
+}
+
+static const struct v4l2_ctrl_ops ov9640_ctrl_ops = {
+	.s_ctrl = ov9640_s_ctrl,
+};
+
+static struct v4l2_subdev_core_ops ov9640_core_ops = {
+	.g_chip_ident		= ov9640_g_chip_ident,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.g_register		= ov9640_get_register,
+	.s_register		= ov9640_set_register,
+#endif
+	.s_power		= ov9640_s_power,
+};
+
+/* Request bus settings on camera side */
+static int ov9640_g_mbus_config(struct v4l2_subdev *sd,
+				struct v4l2_mbus_config *cfg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+	cfg->flags = V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_MASTER |
+		V4L2_MBUS_VSYNC_ACTIVE_HIGH | V4L2_MBUS_HSYNC_ACTIVE_HIGH |
+		V4L2_MBUS_DATA_ACTIVE_HIGH;
+	cfg->type = V4L2_MBUS_PARALLEL;
+	cfg->flags = soc_camera_apply_board_flags(icl, cfg);
+
+	return 0;
+}
+
+static struct v4l2_subdev_video_ops ov9640_video_ops = {
+	.s_stream	= ov9640_s_stream,
+	.s_mbus_fmt	= ov9640_s_fmt,
+	.try_mbus_fmt	= ov9640_try_fmt,
+	.enum_mbus_fmt	= ov9640_enum_fmt,
+	.cropcap	= ov9640_cropcap,
+	.g_crop		= ov9640_g_crop,
+	.g_mbus_config	= ov9640_g_mbus_config,
+};
+
+static struct v4l2_subdev_ops ov9640_subdev_ops = {
+	.core	= &ov9640_core_ops,
+	.video	= &ov9640_video_ops,
+};
+
+/*
+ * i2c_driver function
+ */
+static int ov9640_probe(struct i2c_client *client,
+			const struct i2c_device_id *did)
+{
+	struct ov9640_priv *priv;
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+	int ret;
+
+	if (!icl) {
+		dev_err(&client->dev, "Missing platform_data for driver\n");
+		return -EINVAL;
+	}
+
+	priv = kzalloc(sizeof(struct ov9640_priv), GFP_KERNEL);
+	if (!priv) {
+		dev_err(&client->dev,
+			"Failed to allocate memory for private data!\n");
+		return -ENOMEM;
+	}
+
+	v4l2_i2c_subdev_init(&priv->subdev, client, &ov9640_subdev_ops);
+
+	v4l2_ctrl_handler_init(&priv->hdl, 2);
+	v4l2_ctrl_new_std(&priv->hdl, &ov9640_ctrl_ops,
+			V4L2_CID_VFLIP, 0, 1, 1, 0);
+	v4l2_ctrl_new_std(&priv->hdl, &ov9640_ctrl_ops,
+			V4L2_CID_HFLIP, 0, 1, 1, 0);
+	priv->subdev.ctrl_handler = &priv->hdl;
+	if (priv->hdl.error) {
+		int err = priv->hdl.error;
+
+		kfree(priv);
+		return err;
+	}
+
+	ret = ov9640_video_probe(client);
+
+	if (ret) {
+		v4l2_ctrl_handler_free(&priv->hdl);
+		kfree(priv);
+	}
+
+	return ret;
+}
+
+static int ov9640_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct ov9640_priv *priv = to_ov9640_sensor(sd);
+
+	v4l2_device_unregister_subdev(&priv->subdev);
+	v4l2_ctrl_handler_free(&priv->hdl);
+	kfree(priv);
+	return 0;
+}
+
+static const struct i2c_device_id ov9640_id[] = {
+	{ "ov9640", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, ov9640_id);
+
+static struct i2c_driver ov9640_i2c_driver = {
+	.driver = {
+		.name = "ov9640",
+	},
+	.probe    = ov9640_probe,
+	.remove   = ov9640_remove,
+	.id_table = ov9640_id,
+};
+
+module_i2c_driver(ov9640_i2c_driver);
+
+MODULE_DESCRIPTION("SoC Camera driver for OmniVision OV96xx");
+MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/i2c/soc_camera/ov9640.h b/drivers/media/i2c/soc_camera/ov9640.h
new file mode 100644
index 0000000..6b33a97
--- /dev/null
+++ b/drivers/media/i2c/soc_camera/ov9640.h
@@ -0,0 +1,207 @@
+/*
+ * OmniVision OV96xx Camera Header File
+ *
+ * Copyright (C) 2009 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	__DRIVERS_MEDIA_VIDEO_OV9640_H__
+#define	__DRIVERS_MEDIA_VIDEO_OV9640_H__
+
+/* Register definitions */
+#define	OV9640_GAIN	0x00
+#define	OV9640_BLUE	0x01
+#define	OV9640_RED	0x02
+#define	OV9640_VFER	0x03
+#define	OV9640_COM1	0x04
+#define	OV9640_BAVE	0x05
+#define	OV9640_GEAVE	0x06
+#define	OV9640_RSID	0x07
+#define	OV9640_RAVE	0x08
+#define	OV9640_COM2	0x09
+#define	OV9640_PID	0x0a
+#define	OV9640_VER	0x0b
+#define	OV9640_COM3	0x0c
+#define	OV9640_COM4	0x0d
+#define	OV9640_COM5	0x0e
+#define	OV9640_COM6	0x0f
+#define	OV9640_AECH	0x10
+#define	OV9640_CLKRC	0x11
+#define	OV9640_COM7	0x12
+#define	OV9640_COM8	0x13
+#define	OV9640_COM9	0x14
+#define	OV9640_COM10	0x15
+/* 0x16 - RESERVED */
+#define	OV9640_HSTART	0x17
+#define	OV9640_HSTOP	0x18
+#define	OV9640_VSTART	0x19
+#define	OV9640_VSTOP	0x1a
+#define	OV9640_PSHFT	0x1b
+#define	OV9640_MIDH	0x1c
+#define	OV9640_MIDL	0x1d
+#define	OV9640_MVFP	0x1e
+#define	OV9640_LAEC	0x1f
+#define	OV9640_BOS	0x20
+#define	OV9640_GBOS	0x21
+#define	OV9640_GROS	0x22
+#define	OV9640_ROS	0x23
+#define	OV9640_AEW	0x24
+#define	OV9640_AEB	0x25
+#define	OV9640_VPT	0x26
+#define	OV9640_BBIAS	0x27
+#define	OV9640_GBBIAS	0x28
+/* 0x29 - RESERVED */
+#define	OV9640_EXHCH	0x2a
+#define	OV9640_EXHCL	0x2b
+#define	OV9640_RBIAS	0x2c
+#define	OV9640_ADVFL	0x2d
+#define	OV9640_ADVFH	0x2e
+#define	OV9640_YAVE	0x2f
+#define	OV9640_HSYST	0x30
+#define	OV9640_HSYEN	0x31
+#define	OV9640_HREF	0x32
+#define	OV9640_CHLF	0x33
+#define	OV9640_ARBLM	0x34
+/* 0x35..0x36 - RESERVED */
+#define	OV9640_ADC	0x37
+#define	OV9640_ACOM	0x38
+#define	OV9640_OFON	0x39
+#define	OV9640_TSLB	0x3a
+#define	OV9640_COM11	0x3b
+#define	OV9640_COM12	0x3c
+#define	OV9640_COM13	0x3d
+#define	OV9640_COM14	0x3e
+#define	OV9640_EDGE	0x3f
+#define	OV9640_COM15	0x40
+#define	OV9640_COM16	0x41
+#define	OV9640_COM17	0x42
+/* 0x43..0x4e - RESERVED */
+#define	OV9640_MTX1	0x4f
+#define	OV9640_MTX2	0x50
+#define	OV9640_MTX3	0x51
+#define	OV9640_MTX4	0x52
+#define	OV9640_MTX5	0x53
+#define	OV9640_MTX6	0x54
+#define	OV9640_MTX7	0x55
+#define	OV9640_MTX8	0x56
+#define	OV9640_MTX9	0x57
+#define	OV9640_MTXS	0x58
+/* 0x59..0x61 - RESERVED */
+#define	OV9640_LCC1	0x62
+#define	OV9640_LCC2	0x63
+#define	OV9640_LCC3	0x64
+#define	OV9640_LCC4	0x65
+#define	OV9640_LCC5	0x66
+#define	OV9640_MANU	0x67
+#define	OV9640_MANV	0x68
+#define	OV9640_HV	0x69
+#define	OV9640_MBD	0x6a
+#define	OV9640_DBLV	0x6b
+#define	OV9640_GSP	0x6c	/* ... till 0x7b */
+#define	OV9640_GST	0x7c	/* ... till 0x8a */
+
+#define	OV9640_CLKRC_DPLL_EN	0x80
+#define	OV9640_CLKRC_DIRECT	0x40
+#define	OV9640_CLKRC_DIV(x)	((x) & 0x3f)
+
+#define	OV9640_PSHFT_VAL(x)	((x) & 0xff)
+
+#define	OV9640_ACOM_2X_ANALOG	0x80
+#define	OV9640_ACOM_RSVD	0x12
+
+#define	OV9640_MVFP_V		0x10
+#define	OV9640_MVFP_H		0x20
+
+#define	OV9640_COM1_HREF_NOSKIP	0x00
+#define	OV9640_COM1_HREF_2SKIP	0x04
+#define	OV9640_COM1_HREF_3SKIP	0x08
+#define	OV9640_COM1_QQFMT	0x20
+
+#define	OV9640_COM2_SSM		0x10
+
+#define	OV9640_COM3_VP		0x04
+
+#define	OV9640_COM4_QQ_VP	0x80
+#define	OV9640_COM4_RSVD	0x40
+
+#define	OV9640_COM5_SYSCLK	0x80
+#define	OV9640_COM5_LONGEXP	0x01
+
+#define	OV9640_COM6_OPT_BLC	0x40
+#define	OV9640_COM6_ADBLC_BIAS	0x08
+#define	OV9640_COM6_FMT_RST	0x82
+#define	OV9640_COM6_ADBLC_OPTEN	0x01
+
+#define	OV9640_COM7_RAW_RGB	0x01
+#define	OV9640_COM7_RGB		0x04
+#define	OV9640_COM7_QCIF	0x08
+#define	OV9640_COM7_QVGA	0x10
+#define	OV9640_COM7_CIF		0x20
+#define	OV9640_COM7_VGA		0x40
+#define	OV9640_COM7_SCCB_RESET	0x80
+
+#define	OV9640_TSLB_YVYU_YUYV	0x04
+#define	OV9640_TSLB_YUYV_UYVY	0x08
+
+#define	OV9640_COM12_YUV_AVG	0x04
+#define	OV9640_COM12_RSVD	0x40
+
+#define	OV9640_COM13_GAMMA_NONE	0x00
+#define	OV9640_COM13_GAMMA_Y	0x40
+#define	OV9640_COM13_GAMMA_RAW	0x80
+#define	OV9640_COM13_RGB_AVG	0x20
+#define	OV9640_COM13_MATRIX_EN	0x10
+#define	OV9640_COM13_Y_DELAY_EN	0x08
+#define	OV9640_COM13_YUV_DLY(x)	((x) & 0x07)
+
+#define	OV9640_COM15_OR_00FF	0x00
+#define	OV9640_COM15_OR_01FE	0x40
+#define	OV9640_COM15_OR_10F0	0xc0
+#define	OV9640_COM15_RGB_NORM	0x00
+#define	OV9640_COM15_RGB_565	0x10
+#define	OV9640_COM15_RGB_555	0x30
+
+#define	OV9640_COM16_RB_AVG	0x01
+
+/* IDs */
+#define	OV9640_V2		0x9648
+#define	OV9640_V3		0x9649
+#define	VERSION(pid, ver)	(((pid) << 8) | ((ver) & 0xFF))
+
+/* supported resolutions */
+enum {
+	W_QQCIF	= 88,
+	W_QQVGA	= 160,
+	W_QCIF	= 176,
+	W_QVGA	= 320,
+	W_CIF	= 352,
+	W_VGA	= 640,
+	W_SXGA	= 1280
+};
+#define	H_SXGA	960
+
+/* Misc. structures */
+struct ov9640_reg_alt {
+	u8	com7;
+	u8	com12;
+	u8	com13;
+	u8	com15;
+};
+
+struct ov9640_reg {
+	u8	reg;
+	u8	val;
+};
+
+struct ov9640_priv {
+	struct v4l2_subdev		subdev;
+	struct v4l2_ctrl_handler	hdl;
+
+	int				model;
+	int				revision;
+};
+
+#endif	/* __DRIVERS_MEDIA_VIDEO_OV9640_H__ */
diff --git a/drivers/media/i2c/soc_camera/ov9740.c b/drivers/media/i2c/soc_camera/ov9740.c
new file mode 100644
index 0000000..7a55889
--- /dev/null
+++ b/drivers/media/i2c/soc_camera/ov9740.c
@@ -0,0 +1,1020 @@
+/*
+ * OmniVision OV9740 Camera Driver
+ *
+ * Copyright (C) 2011 NVIDIA Corporation
+ *
+ * Based on ov9640 camera driver.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/v4l2-mediabus.h>
+
+#include <media/soc_camera.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-ctrls.h>
+
+#define to_ov9740(sd)		container_of(sd, struct ov9740_priv, subdev)
+
+/* General Status Registers */
+#define OV9740_MODEL_ID_HI		0x0000
+#define OV9740_MODEL_ID_LO		0x0001
+#define OV9740_REVISION_NUMBER		0x0002
+#define OV9740_MANUFACTURER_ID		0x0003
+#define OV9740_SMIA_VERSION		0x0004
+
+/* General Setup Registers */
+#define OV9740_MODE_SELECT		0x0100
+#define OV9740_IMAGE_ORT		0x0101
+#define OV9740_SOFTWARE_RESET		0x0103
+#define OV9740_GRP_PARAM_HOLD		0x0104
+#define OV9740_MSK_CORRUP_FM		0x0105
+
+/* Timing Setting */
+#define OV9740_FRM_LENGTH_LN_HI		0x0340 /* VTS */
+#define OV9740_FRM_LENGTH_LN_LO		0x0341 /* VTS */
+#define OV9740_LN_LENGTH_PCK_HI		0x0342 /* HTS */
+#define OV9740_LN_LENGTH_PCK_LO		0x0343 /* HTS */
+#define OV9740_X_ADDR_START_HI		0x0344
+#define OV9740_X_ADDR_START_LO		0x0345
+#define OV9740_Y_ADDR_START_HI		0x0346
+#define OV9740_Y_ADDR_START_LO		0x0347
+#define OV9740_X_ADDR_END_HI		0x0348
+#define OV9740_X_ADDR_END_LO		0x0349
+#define OV9740_Y_ADDR_END_HI		0x034a
+#define OV9740_Y_ADDR_END_LO		0x034b
+#define OV9740_X_OUTPUT_SIZE_HI		0x034c
+#define OV9740_X_OUTPUT_SIZE_LO		0x034d
+#define OV9740_Y_OUTPUT_SIZE_HI		0x034e
+#define OV9740_Y_OUTPUT_SIZE_LO		0x034f
+
+/* IO Control Registers */
+#define OV9740_IO_CREL00		0x3002
+#define OV9740_IO_CREL01		0x3004
+#define OV9740_IO_CREL02		0x3005
+#define OV9740_IO_OUTPUT_SEL01		0x3026
+#define OV9740_IO_OUTPUT_SEL02		0x3027
+
+/* AWB Registers */
+#define OV9740_AWB_MANUAL_CTRL		0x3406
+
+/* Analog Control Registers */
+#define OV9740_ANALOG_CTRL01		0x3601
+#define OV9740_ANALOG_CTRL02		0x3602
+#define OV9740_ANALOG_CTRL03		0x3603
+#define OV9740_ANALOG_CTRL04		0x3604
+#define OV9740_ANALOG_CTRL10		0x3610
+#define OV9740_ANALOG_CTRL12		0x3612
+#define OV9740_ANALOG_CTRL15		0x3615
+#define OV9740_ANALOG_CTRL20		0x3620
+#define OV9740_ANALOG_CTRL21		0x3621
+#define OV9740_ANALOG_CTRL22		0x3622
+#define OV9740_ANALOG_CTRL30		0x3630
+#define OV9740_ANALOG_CTRL31		0x3631
+#define OV9740_ANALOG_CTRL32		0x3632
+#define OV9740_ANALOG_CTRL33		0x3633
+
+/* Sensor Control */
+#define OV9740_SENSOR_CTRL03		0x3703
+#define OV9740_SENSOR_CTRL04		0x3704
+#define OV9740_SENSOR_CTRL05		0x3705
+#define OV9740_SENSOR_CTRL07		0x3707
+
+/* Timing Control */
+#define OV9740_TIMING_CTRL17		0x3817
+#define OV9740_TIMING_CTRL19		0x3819
+#define OV9740_TIMING_CTRL33		0x3833
+#define OV9740_TIMING_CTRL35		0x3835
+
+/* Banding Filter */
+#define OV9740_AEC_MAXEXPO_60_H		0x3a02
+#define OV9740_AEC_MAXEXPO_60_L		0x3a03
+#define OV9740_AEC_B50_STEP_HI		0x3a08
+#define OV9740_AEC_B50_STEP_LO		0x3a09
+#define OV9740_AEC_B60_STEP_HI		0x3a0a
+#define OV9740_AEC_B60_STEP_LO		0x3a0b
+#define OV9740_AEC_CTRL0D		0x3a0d
+#define OV9740_AEC_CTRL0E		0x3a0e
+#define OV9740_AEC_MAXEXPO_50_H		0x3a14
+#define OV9740_AEC_MAXEXPO_50_L		0x3a15
+
+/* AEC/AGC Control */
+#define OV9740_AEC_ENABLE		0x3503
+#define OV9740_GAIN_CEILING_01		0x3a18
+#define OV9740_GAIN_CEILING_02		0x3a19
+#define OV9740_AEC_HI_THRESHOLD		0x3a11
+#define OV9740_AEC_3A1A			0x3a1a
+#define OV9740_AEC_CTRL1B_WPT2		0x3a1b
+#define OV9740_AEC_CTRL0F_WPT		0x3a0f
+#define OV9740_AEC_CTRL10_BPT		0x3a10
+#define OV9740_AEC_CTRL1E_BPT2		0x3a1e
+#define OV9740_AEC_LO_THRESHOLD		0x3a1f
+
+/* BLC Control */
+#define OV9740_BLC_AUTO_ENABLE		0x4002
+#define OV9740_BLC_MODE			0x4005
+
+/* VFIFO */
+#define OV9740_VFIFO_READ_START_HI	0x4608
+#define OV9740_VFIFO_READ_START_LO	0x4609
+
+/* DVP Control */
+#define OV9740_DVP_VSYNC_CTRL02		0x4702
+#define OV9740_DVP_VSYNC_MODE		0x4704
+#define OV9740_DVP_VSYNC_CTRL06		0x4706
+
+/* PLL Setting */
+#define OV9740_PLL_MODE_CTRL01		0x3104
+#define OV9740_PRE_PLL_CLK_DIV		0x0305
+#define OV9740_PLL_MULTIPLIER		0x0307
+#define OV9740_VT_SYS_CLK_DIV		0x0303
+#define OV9740_VT_PIX_CLK_DIV		0x0301
+#define OV9740_PLL_CTRL3010		0x3010
+#define OV9740_VFIFO_CTRL00		0x460e
+
+/* ISP Control */
+#define OV9740_ISP_CTRL00		0x5000
+#define OV9740_ISP_CTRL01		0x5001
+#define OV9740_ISP_CTRL03		0x5003
+#define OV9740_ISP_CTRL05		0x5005
+#define OV9740_ISP_CTRL12		0x5012
+#define OV9740_ISP_CTRL19		0x5019
+#define OV9740_ISP_CTRL1A		0x501a
+#define OV9740_ISP_CTRL1E		0x501e
+#define OV9740_ISP_CTRL1F		0x501f
+#define OV9740_ISP_CTRL20		0x5020
+#define OV9740_ISP_CTRL21		0x5021
+
+/* AWB */
+#define OV9740_AWB_CTRL00		0x5180
+#define OV9740_AWB_CTRL01		0x5181
+#define OV9740_AWB_CTRL02		0x5182
+#define OV9740_AWB_CTRL03		0x5183
+#define OV9740_AWB_ADV_CTRL01		0x5184
+#define OV9740_AWB_ADV_CTRL02		0x5185
+#define OV9740_AWB_ADV_CTRL03		0x5186
+#define OV9740_AWB_ADV_CTRL04		0x5187
+#define OV9740_AWB_ADV_CTRL05		0x5188
+#define OV9740_AWB_ADV_CTRL06		0x5189
+#define OV9740_AWB_ADV_CTRL07		0x518a
+#define OV9740_AWB_ADV_CTRL08		0x518b
+#define OV9740_AWB_ADV_CTRL09		0x518c
+#define OV9740_AWB_ADV_CTRL10		0x518d
+#define OV9740_AWB_ADV_CTRL11		0x518e
+#define OV9740_AWB_CTRL0F		0x518f
+#define OV9740_AWB_CTRL10		0x5190
+#define OV9740_AWB_CTRL11		0x5191
+#define OV9740_AWB_CTRL12		0x5192
+#define OV9740_AWB_CTRL13		0x5193
+#define OV9740_AWB_CTRL14		0x5194
+
+/* MIPI Control */
+#define OV9740_MIPI_CTRL00		0x4800
+#define OV9740_MIPI_3837		0x3837
+#define OV9740_MIPI_CTRL01		0x4801
+#define OV9740_MIPI_CTRL03		0x4803
+#define OV9740_MIPI_CTRL05		0x4805
+#define OV9740_VFIFO_RD_CTRL		0x4601
+#define OV9740_MIPI_CTRL_3012		0x3012
+#define OV9740_SC_CMMM_MIPI_CTR		0x3014
+
+#define OV9740_MAX_WIDTH		1280
+#define OV9740_MAX_HEIGHT		720
+
+/* Misc. structures */
+struct ov9740_reg {
+	u16				reg;
+	u8				val;
+};
+
+struct ov9740_priv {
+	struct v4l2_subdev		subdev;
+	struct v4l2_ctrl_handler	hdl;
+
+	int				ident;
+	u16				model;
+	u8				revision;
+	u8				manid;
+	u8				smiaver;
+
+	bool				flag_vflip;
+	bool				flag_hflip;
+
+	/* For suspend/resume. */
+	struct v4l2_mbus_framefmt	current_mf;
+	bool				current_enable;
+};
+
+static const struct ov9740_reg ov9740_defaults[] = {
+	/* Software Reset */
+	{ OV9740_SOFTWARE_RESET,	0x01 },
+
+	/* Banding Filter */
+	{ OV9740_AEC_B50_STEP_HI,	0x00 },
+	{ OV9740_AEC_B50_STEP_LO,	0xe8 },
+	{ OV9740_AEC_CTRL0E,		0x03 },
+	{ OV9740_AEC_MAXEXPO_50_H,	0x15 },
+	{ OV9740_AEC_MAXEXPO_50_L,	0xc6 },
+	{ OV9740_AEC_B60_STEP_HI,	0x00 },
+	{ OV9740_AEC_B60_STEP_LO,	0xc0 },
+	{ OV9740_AEC_CTRL0D,		0x04 },
+	{ OV9740_AEC_MAXEXPO_60_H,	0x18 },
+	{ OV9740_AEC_MAXEXPO_60_L,	0x20 },
+
+	/* LC */
+	{ 0x5842, 0x02 }, { 0x5843, 0x5e }, { 0x5844, 0x04 }, { 0x5845, 0x32 },
+	{ 0x5846, 0x03 }, { 0x5847, 0x29 }, { 0x5848, 0x02 }, { 0x5849, 0xcc },
+
+	/* Un-documented OV9740 registers */
+	{ 0x5800, 0x29 }, { 0x5801, 0x25 }, { 0x5802, 0x20 }, { 0x5803, 0x21 },
+	{ 0x5804, 0x26 }, { 0x5805, 0x2e }, { 0x5806, 0x11 }, { 0x5807, 0x0c },
+	{ 0x5808, 0x09 }, { 0x5809, 0x0a }, { 0x580a, 0x0e }, { 0x580b, 0x16 },
+	{ 0x580c, 0x06 }, { 0x580d, 0x02 }, { 0x580e, 0x00 }, { 0x580f, 0x00 },
+	{ 0x5810, 0x04 }, { 0x5811, 0x0a }, { 0x5812, 0x05 }, { 0x5813, 0x02 },
+	{ 0x5814, 0x00 }, { 0x5815, 0x00 }, { 0x5816, 0x03 }, { 0x5817, 0x09 },
+	{ 0x5818, 0x0f }, { 0x5819, 0x0a }, { 0x581a, 0x07 }, { 0x581b, 0x08 },
+	{ 0x581c, 0x0b }, { 0x581d, 0x14 }, { 0x581e, 0x28 }, { 0x581f, 0x23 },
+	{ 0x5820, 0x1d }, { 0x5821, 0x1e }, { 0x5822, 0x24 }, { 0x5823, 0x2a },
+	{ 0x5824, 0x4f }, { 0x5825, 0x6f }, { 0x5826, 0x5f }, { 0x5827, 0x7f },
+	{ 0x5828, 0x9f }, { 0x5829, 0x5f }, { 0x582a, 0x8f }, { 0x582b, 0x9e },
+	{ 0x582c, 0x8f }, { 0x582d, 0x9f }, { 0x582e, 0x4f }, { 0x582f, 0x87 },
+	{ 0x5830, 0x86 }, { 0x5831, 0x97 }, { 0x5832, 0xae }, { 0x5833, 0x3f },
+	{ 0x5834, 0x8e }, { 0x5835, 0x7c }, { 0x5836, 0x7e }, { 0x5837, 0xaf },
+	{ 0x5838, 0x8f }, { 0x5839, 0x8f }, { 0x583a, 0x9f }, { 0x583b, 0x7f },
+	{ 0x583c, 0x5f },
+
+	/* Y Gamma */
+	{ 0x5480, 0x07 }, { 0x5481, 0x18 }, { 0x5482, 0x2c }, { 0x5483, 0x4e },
+	{ 0x5484, 0x5e }, { 0x5485, 0x6b }, { 0x5486, 0x77 }, { 0x5487, 0x82 },
+	{ 0x5488, 0x8c }, { 0x5489, 0x95 }, { 0x548a, 0xa4 }, { 0x548b, 0xb1 },
+	{ 0x548c, 0xc6 }, { 0x548d, 0xd8 }, { 0x548e, 0xe9 },
+
+	/* UV Gamma */
+	{ 0x5490, 0x0f }, { 0x5491, 0xff }, { 0x5492, 0x0d }, { 0x5493, 0x05 },
+	{ 0x5494, 0x07 }, { 0x5495, 0x1a }, { 0x5496, 0x04 }, { 0x5497, 0x01 },
+	{ 0x5498, 0x03 }, { 0x5499, 0x53 }, { 0x549a, 0x02 }, { 0x549b, 0xeb },
+	{ 0x549c, 0x02 }, { 0x549d, 0xa0 }, { 0x549e, 0x02 }, { 0x549f, 0x67 },
+	{ 0x54a0, 0x02 }, { 0x54a1, 0x3b }, { 0x54a2, 0x02 }, { 0x54a3, 0x18 },
+	{ 0x54a4, 0x01 }, { 0x54a5, 0xe7 }, { 0x54a6, 0x01 }, { 0x54a7, 0xc3 },
+	{ 0x54a8, 0x01 }, { 0x54a9, 0x94 }, { 0x54aa, 0x01 }, { 0x54ab, 0x72 },
+	{ 0x54ac, 0x01 }, { 0x54ad, 0x57 },
+
+	/* AWB */
+	{ OV9740_AWB_CTRL00,		0xf0 },
+	{ OV9740_AWB_CTRL01,		0x00 },
+	{ OV9740_AWB_CTRL02,		0x41 },
+	{ OV9740_AWB_CTRL03,		0x42 },
+	{ OV9740_AWB_ADV_CTRL01,	0x8a },
+	{ OV9740_AWB_ADV_CTRL02,	0x61 },
+	{ OV9740_AWB_ADV_CTRL03,	0xce },
+	{ OV9740_AWB_ADV_CTRL04,	0xa8 },
+	{ OV9740_AWB_ADV_CTRL05,	0x17 },
+	{ OV9740_AWB_ADV_CTRL06,	0x1f },
+	{ OV9740_AWB_ADV_CTRL07,	0x27 },
+	{ OV9740_AWB_ADV_CTRL08,	0x41 },
+	{ OV9740_AWB_ADV_CTRL09,	0x34 },
+	{ OV9740_AWB_ADV_CTRL10,	0xf0 },
+	{ OV9740_AWB_ADV_CTRL11,	0x10 },
+	{ OV9740_AWB_CTRL0F,		0xff },
+	{ OV9740_AWB_CTRL10,		0x00 },
+	{ OV9740_AWB_CTRL11,		0xff },
+	{ OV9740_AWB_CTRL12,		0x00 },
+	{ OV9740_AWB_CTRL13,		0xff },
+	{ OV9740_AWB_CTRL14,		0x00 },
+
+	/* CIP */
+	{ 0x530d, 0x12 },
+
+	/* CMX */
+	{ 0x5380, 0x01 }, { 0x5381, 0x00 }, { 0x5382, 0x00 }, { 0x5383, 0x17 },
+	{ 0x5384, 0x00 }, { 0x5385, 0x01 }, { 0x5386, 0x00 }, { 0x5387, 0x00 },
+	{ 0x5388, 0x00 }, { 0x5389, 0xe0 }, { 0x538a, 0x00 }, { 0x538b, 0x20 },
+	{ 0x538c, 0x00 }, { 0x538d, 0x00 }, { 0x538e, 0x00 }, { 0x538f, 0x16 },
+	{ 0x5390, 0x00 }, { 0x5391, 0x9c }, { 0x5392, 0x00 }, { 0x5393, 0xa0 },
+	{ 0x5394, 0x18 },
+
+	/* 50/60 Detection */
+	{ 0x3c0a, 0x9c }, { 0x3c0b, 0x3f },
+
+	/* Output Select */
+	{ OV9740_IO_OUTPUT_SEL01,	0x00 },
+	{ OV9740_IO_OUTPUT_SEL02,	0x00 },
+	{ OV9740_IO_CREL00,		0x00 },
+	{ OV9740_IO_CREL01,		0x00 },
+	{ OV9740_IO_CREL02,		0x00 },
+
+	/* AWB Control */
+	{ OV9740_AWB_MANUAL_CTRL,	0x00 },
+
+	/* Analog Control */
+	{ OV9740_ANALOG_CTRL03,		0xaa },
+	{ OV9740_ANALOG_CTRL32,		0x2f },
+	{ OV9740_ANALOG_CTRL20,		0x66 },
+	{ OV9740_ANALOG_CTRL21,		0xc0 },
+	{ OV9740_ANALOG_CTRL31,		0x52 },
+	{ OV9740_ANALOG_CTRL33,		0x50 },
+	{ OV9740_ANALOG_CTRL30,		0xca },
+	{ OV9740_ANALOG_CTRL04,		0x0c },
+	{ OV9740_ANALOG_CTRL01,		0x40 },
+	{ OV9740_ANALOG_CTRL02,		0x16 },
+	{ OV9740_ANALOG_CTRL10,		0xa1 },
+	{ OV9740_ANALOG_CTRL12,		0x24 },
+	{ OV9740_ANALOG_CTRL22,		0x9f },
+	{ OV9740_ANALOG_CTRL15,		0xf0 },
+
+	/* Sensor Control */
+	{ OV9740_SENSOR_CTRL03,		0x42 },
+	{ OV9740_SENSOR_CTRL04,		0x10 },
+	{ OV9740_SENSOR_CTRL05,		0x45 },
+	{ OV9740_SENSOR_CTRL07,		0x14 },
+
+	/* Timing Control */
+	{ OV9740_TIMING_CTRL33,		0x04 },
+	{ OV9740_TIMING_CTRL35,		0x02 },
+	{ OV9740_TIMING_CTRL19,		0x6e },
+	{ OV9740_TIMING_CTRL17,		0x94 },
+
+	/* AEC/AGC Control */
+	{ OV9740_AEC_ENABLE,		0x10 },
+	{ OV9740_GAIN_CEILING_01,	0x00 },
+	{ OV9740_GAIN_CEILING_02,	0x7f },
+	{ OV9740_AEC_HI_THRESHOLD,	0xa0 },
+	{ OV9740_AEC_3A1A,		0x05 },
+	{ OV9740_AEC_CTRL1B_WPT2,	0x50 },
+	{ OV9740_AEC_CTRL0F_WPT,	0x50 },
+	{ OV9740_AEC_CTRL10_BPT,	0x4c },
+	{ OV9740_AEC_CTRL1E_BPT2,	0x4c },
+	{ OV9740_AEC_LO_THRESHOLD,	0x26 },
+
+	/* BLC Control */
+	{ OV9740_BLC_AUTO_ENABLE,	0x45 },
+	{ OV9740_BLC_MODE,		0x18 },
+
+	/* DVP Control */
+	{ OV9740_DVP_VSYNC_CTRL02,	0x04 },
+	{ OV9740_DVP_VSYNC_MODE,	0x00 },
+	{ OV9740_DVP_VSYNC_CTRL06,	0x08 },
+
+	/* PLL Setting */
+	{ OV9740_PLL_MODE_CTRL01,	0x20 },
+	{ OV9740_PRE_PLL_CLK_DIV,	0x03 },
+	{ OV9740_PLL_MULTIPLIER,	0x4c },
+	{ OV9740_VT_SYS_CLK_DIV,	0x01 },
+	{ OV9740_VT_PIX_CLK_DIV,	0x08 },
+	{ OV9740_PLL_CTRL3010,		0x01 },
+	{ OV9740_VFIFO_CTRL00,		0x82 },
+
+	/* Timing Setting */
+	/* VTS */
+	{ OV9740_FRM_LENGTH_LN_HI,	0x03 },
+	{ OV9740_FRM_LENGTH_LN_LO,	0x07 },
+	/* HTS */
+	{ OV9740_LN_LENGTH_PCK_HI,	0x06 },
+	{ OV9740_LN_LENGTH_PCK_LO,	0x62 },
+
+	/* MIPI Control */
+	{ OV9740_MIPI_CTRL00,		0x44 }, /* 0x64 for discontinuous clk */
+	{ OV9740_MIPI_3837,		0x01 },
+	{ OV9740_MIPI_CTRL01,		0x0f },
+	{ OV9740_MIPI_CTRL03,		0x05 },
+	{ OV9740_MIPI_CTRL05,		0x10 },
+	{ OV9740_VFIFO_RD_CTRL,		0x16 },
+	{ OV9740_MIPI_CTRL_3012,	0x70 },
+	{ OV9740_SC_CMMM_MIPI_CTR,	0x01 },
+
+	/* YUYV order */
+	{ OV9740_ISP_CTRL19,		0x02 },
+};
+
+static enum v4l2_mbus_pixelcode ov9740_codes[] = {
+	V4L2_MBUS_FMT_YUYV8_2X8,
+};
+
+/* read a register */
+static int ov9740_reg_read(struct i2c_client *client, u16 reg, u8 *val)
+{
+	int ret;
+	struct i2c_msg msg[] = {
+		{
+			.addr	= client->addr,
+			.flags	= 0,
+			.len	= 2,
+			.buf	= (u8 *)&reg,
+		},
+		{
+			.addr	= client->addr,
+			.flags	= I2C_M_RD,
+			.len	= 1,
+			.buf	= val,
+		},
+	};
+
+	reg = swab16(reg);
+
+	ret = i2c_transfer(client->adapter, msg, 2);
+	if (ret < 0) {
+		dev_err(&client->dev, "Failed reading register 0x%04x!\n", reg);
+		return ret;
+	}
+
+	return 0;
+}
+
+/* write a register */
+static int ov9740_reg_write(struct i2c_client *client, u16 reg, u8 val)
+{
+	struct i2c_msg msg;
+	struct {
+		u16 reg;
+		u8 val;
+	} __packed buf;
+	int ret;
+
+	reg = swab16(reg);
+
+	buf.reg = reg;
+	buf.val = val;
+
+	msg.addr	= client->addr;
+	msg.flags	= 0;
+	msg.len		= 3;
+	msg.buf		= (u8 *)&buf;
+
+	ret = i2c_transfer(client->adapter, &msg, 1);
+	if (ret < 0) {
+		dev_err(&client->dev, "Failed writing register 0x%04x!\n", reg);
+		return ret;
+	}
+
+	return 0;
+}
+
+
+/* Read a register, alter its bits, write it back */
+static int ov9740_reg_rmw(struct i2c_client *client, u16 reg, u8 set, u8 unset)
+{
+	u8 val;
+	int ret;
+
+	ret = ov9740_reg_read(client, reg, &val);
+	if (ret < 0) {
+		dev_err(&client->dev,
+			"[Read]-Modify-Write of register 0x%04x failed!\n",
+			reg);
+		return ret;
+	}
+
+	val |= set;
+	val &= ~unset;
+
+	ret = ov9740_reg_write(client, reg, val);
+	if (ret < 0) {
+		dev_err(&client->dev,
+			"Read-Modify-[Write] of register 0x%04x failed!\n",
+			reg);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int ov9740_reg_write_array(struct i2c_client *client,
+				  const struct ov9740_reg *regarray,
+				  int regarraylen)
+{
+	int i;
+	int ret;
+
+	for (i = 0; i < regarraylen; i++) {
+		ret = ov9740_reg_write(client,
+				       regarray[i].reg, regarray[i].val);
+		if (ret < 0)
+			return ret;
+	}
+
+	return 0;
+}
+
+/* Start/Stop streaming from the device */
+static int ov9740_s_stream(struct v4l2_subdev *sd, int enable)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct ov9740_priv *priv = to_ov9740(sd);
+	int ret;
+
+	/* Program orientation register. */
+	if (priv->flag_vflip)
+		ret = ov9740_reg_rmw(client, OV9740_IMAGE_ORT, 0x2, 0);
+	else
+		ret = ov9740_reg_rmw(client, OV9740_IMAGE_ORT, 0, 0x2);
+	if (ret < 0)
+		return ret;
+
+	if (priv->flag_hflip)
+		ret = ov9740_reg_rmw(client, OV9740_IMAGE_ORT, 0x1, 0);
+	else
+		ret = ov9740_reg_rmw(client, OV9740_IMAGE_ORT, 0, 0x1);
+	if (ret < 0)
+		return ret;
+
+	if (enable) {
+		dev_dbg(&client->dev, "Enabling Streaming\n");
+		/* Start Streaming */
+		ret = ov9740_reg_write(client, OV9740_MODE_SELECT, 0x01);
+
+	} else {
+		dev_dbg(&client->dev, "Disabling Streaming\n");
+		/* Software Reset */
+		ret = ov9740_reg_write(client, OV9740_SOFTWARE_RESET, 0x01);
+		if (!ret)
+			/* Setting Streaming to Standby */
+			ret = ov9740_reg_write(client, OV9740_MODE_SELECT,
+					       0x00);
+	}
+
+	priv->current_enable = enable;
+
+	return ret;
+}
+
+/* select nearest higher resolution for capture */
+static void ov9740_res_roundup(u32 *width, u32 *height)
+{
+	/* Width must be a multiple of 4 pixels. */
+	*width = ALIGN(*width, 4);
+
+	/* Max resolution is 1280x720 (720p). */
+	if (*width > OV9740_MAX_WIDTH)
+		*width = OV9740_MAX_WIDTH;
+
+	if (*height > OV9740_MAX_HEIGHT)
+		*height = OV9740_MAX_HEIGHT;
+}
+
+/* Setup registers according to resolution and color encoding */
+static int ov9740_set_res(struct i2c_client *client, u32 width, u32 height)
+{
+	u32 x_start;
+	u32 y_start;
+	u32 x_end;
+	u32 y_end;
+	bool scaling = 0;
+	u32 scale_input_x;
+	u32 scale_input_y;
+	int ret;
+
+	if ((width != OV9740_MAX_WIDTH) || (height != OV9740_MAX_HEIGHT))
+		scaling = 1;
+
+	/*
+	 * Try to use as much of the sensor area as possible when supporting
+	 * smaller resolutions.  Depending on the aspect ratio of the
+	 * chosen resolution, we can either use the full width of the sensor,
+	 * or the full height of the sensor (or both if the aspect ratio is
+	 * the same as 1280x720.
+	 */
+	if ((OV9740_MAX_WIDTH * height) > (OV9740_MAX_HEIGHT * width)) {
+		scale_input_x = (OV9740_MAX_HEIGHT * width) / height;
+		scale_input_y = OV9740_MAX_HEIGHT;
+	} else {
+		scale_input_x = OV9740_MAX_WIDTH;
+		scale_input_y = (OV9740_MAX_WIDTH * height) / width;
+	}
+
+	/* These describe the area of the sensor to use. */
+	x_start = (OV9740_MAX_WIDTH - scale_input_x) / 2;
+	y_start = (OV9740_MAX_HEIGHT - scale_input_y) / 2;
+	x_end = x_start + scale_input_x - 1;
+	y_end = y_start + scale_input_y - 1;
+
+	ret = ov9740_reg_write(client, OV9740_X_ADDR_START_HI, x_start >> 8);
+	if (ret)
+		goto done;
+	ret = ov9740_reg_write(client, OV9740_X_ADDR_START_LO, x_start & 0xff);
+	if (ret)
+		goto done;
+	ret = ov9740_reg_write(client, OV9740_Y_ADDR_START_HI, y_start >> 8);
+	if (ret)
+		goto done;
+	ret = ov9740_reg_write(client, OV9740_Y_ADDR_START_LO, y_start & 0xff);
+	if (ret)
+		goto done;
+
+	ret = ov9740_reg_write(client, OV9740_X_ADDR_END_HI, x_end >> 8);
+	if (ret)
+		goto done;
+	ret = ov9740_reg_write(client, OV9740_X_ADDR_END_LO, x_end & 0xff);
+	if (ret)
+		goto done;
+	ret = ov9740_reg_write(client, OV9740_Y_ADDR_END_HI, y_end >> 8);
+	if (ret)
+		goto done;
+	ret = ov9740_reg_write(client, OV9740_Y_ADDR_END_LO, y_end & 0xff);
+	if (ret)
+		goto done;
+
+	ret = ov9740_reg_write(client, OV9740_X_OUTPUT_SIZE_HI, width >> 8);
+	if (ret)
+		goto done;
+	ret = ov9740_reg_write(client, OV9740_X_OUTPUT_SIZE_LO, width & 0xff);
+	if (ret)
+		goto done;
+	ret = ov9740_reg_write(client, OV9740_Y_OUTPUT_SIZE_HI, height >> 8);
+	if (ret)
+		goto done;
+	ret = ov9740_reg_write(client, OV9740_Y_OUTPUT_SIZE_LO, height & 0xff);
+	if (ret)
+		goto done;
+
+	ret = ov9740_reg_write(client, OV9740_ISP_CTRL1E, scale_input_x >> 8);
+	if (ret)
+		goto done;
+	ret = ov9740_reg_write(client, OV9740_ISP_CTRL1F, scale_input_x & 0xff);
+	if (ret)
+		goto done;
+	ret = ov9740_reg_write(client, OV9740_ISP_CTRL20, scale_input_y >> 8);
+	if (ret)
+		goto done;
+	ret = ov9740_reg_write(client, OV9740_ISP_CTRL21, scale_input_y & 0xff);
+	if (ret)
+		goto done;
+
+	ret = ov9740_reg_write(client, OV9740_VFIFO_READ_START_HI,
+			       (scale_input_x - width) >> 8);
+	if (ret)
+		goto done;
+	ret = ov9740_reg_write(client, OV9740_VFIFO_READ_START_LO,
+			       (scale_input_x - width) & 0xff);
+	if (ret)
+		goto done;
+
+	ret = ov9740_reg_write(client, OV9740_ISP_CTRL00, 0xff);
+	if (ret)
+		goto done;
+	ret = ov9740_reg_write(client, OV9740_ISP_CTRL01, 0xef |
+							  (scaling << 4));
+	if (ret)
+		goto done;
+	ret = ov9740_reg_write(client, OV9740_ISP_CTRL03, 0xff);
+
+done:
+	return ret;
+}
+
+/* set the format we will capture in */
+static int ov9740_s_fmt(struct v4l2_subdev *sd,
+			struct v4l2_mbus_framefmt *mf)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct ov9740_priv *priv = to_ov9740(sd);
+	enum v4l2_colorspace cspace;
+	enum v4l2_mbus_pixelcode code = mf->code;
+	int ret;
+
+	ov9740_res_roundup(&mf->width, &mf->height);
+
+	switch (code) {
+	case V4L2_MBUS_FMT_YUYV8_2X8:
+		cspace = V4L2_COLORSPACE_SRGB;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	ret = ov9740_reg_write_array(client, ov9740_defaults,
+				     ARRAY_SIZE(ov9740_defaults));
+	if (ret < 0)
+		return ret;
+
+	ret = ov9740_set_res(client, mf->width, mf->height);
+	if (ret < 0)
+		return ret;
+
+	mf->code	= code;
+	mf->colorspace	= cspace;
+
+	memcpy(&priv->current_mf, mf, sizeof(struct v4l2_mbus_framefmt));
+
+	return ret;
+}
+
+static int ov9740_try_fmt(struct v4l2_subdev *sd,
+			  struct v4l2_mbus_framefmt *mf)
+{
+	ov9740_res_roundup(&mf->width, &mf->height);
+
+	mf->field = V4L2_FIELD_NONE;
+	mf->code = V4L2_MBUS_FMT_YUYV8_2X8;
+	mf->colorspace = V4L2_COLORSPACE_SRGB;
+
+	return 0;
+}
+
+static int ov9740_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
+			   enum v4l2_mbus_pixelcode *code)
+{
+	if (index >= ARRAY_SIZE(ov9740_codes))
+		return -EINVAL;
+
+	*code = ov9740_codes[index];
+
+	return 0;
+}
+
+static int ov9740_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
+{
+	a->bounds.left		= 0;
+	a->bounds.top		= 0;
+	a->bounds.width		= OV9740_MAX_WIDTH;
+	a->bounds.height	= OV9740_MAX_HEIGHT;
+	a->defrect		= a->bounds;
+	a->type			= V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	a->pixelaspect.numerator	= 1;
+	a->pixelaspect.denominator	= 1;
+
+	return 0;
+}
+
+static int ov9740_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
+{
+	a->c.left		= 0;
+	a->c.top		= 0;
+	a->c.width		= OV9740_MAX_WIDTH;
+	a->c.height		= OV9740_MAX_HEIGHT;
+	a->type			= V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+	return 0;
+}
+
+/* Set status of additional camera capabilities */
+static int ov9740_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct ov9740_priv *priv =
+		container_of(ctrl->handler, struct ov9740_priv, hdl);
+
+	switch (ctrl->id) {
+	case V4L2_CID_VFLIP:
+		priv->flag_vflip = ctrl->val;
+		break;
+	case V4L2_CID_HFLIP:
+		priv->flag_hflip = ctrl->val;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/* Get chip identification */
+static int ov9740_g_chip_ident(struct v4l2_subdev *sd,
+			       struct v4l2_dbg_chip_ident *id)
+{
+	struct ov9740_priv *priv = to_ov9740(sd);
+
+	id->ident = priv->ident;
+	id->revision = priv->revision;
+
+	return 0;
+}
+
+static int ov9740_s_power(struct v4l2_subdev *sd, int on)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+	struct ov9740_priv *priv = to_ov9740(sd);
+	int ret;
+
+	if (on) {
+		ret = soc_camera_power_on(&client->dev, icl);
+		if (ret < 0)
+			return ret;
+
+		if (priv->current_enable) {
+			ov9740_s_fmt(sd, &priv->current_mf);
+			ov9740_s_stream(sd, 1);
+		}
+	} else {
+		if (priv->current_enable) {
+			ov9740_s_stream(sd, 0);
+			priv->current_enable = true;
+		}
+
+		soc_camera_power_off(&client->dev, icl);
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int ov9740_get_register(struct v4l2_subdev *sd,
+			       struct v4l2_dbg_register *reg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	int ret;
+	u8 val;
+
+	if (reg->reg & ~0xffff)
+		return -EINVAL;
+
+	reg->size = 2;
+
+	ret = ov9740_reg_read(client, reg->reg, &val);
+	if (ret)
+		return ret;
+
+	reg->val = (__u64)val;
+
+	return ret;
+}
+
+static int ov9740_set_register(struct v4l2_subdev *sd,
+			       struct v4l2_dbg_register *reg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	if (reg->reg & ~0xffff || reg->val & ~0xff)
+		return -EINVAL;
+
+	return ov9740_reg_write(client, reg->reg, reg->val);
+}
+#endif
+
+static int ov9740_video_probe(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct ov9740_priv *priv = to_ov9740(sd);
+	u8 modelhi, modello;
+	int ret;
+
+	ret = ov9740_s_power(&priv->subdev, 1);
+	if (ret < 0)
+		return ret;
+
+	/*
+	 * check and show product ID and manufacturer ID
+	 */
+	ret = ov9740_reg_read(client, OV9740_MODEL_ID_HI, &modelhi);
+	if (ret < 0)
+		goto done;
+
+	ret = ov9740_reg_read(client, OV9740_MODEL_ID_LO, &modello);
+	if (ret < 0)
+		goto done;
+
+	priv->model = (modelhi << 8) | modello;
+
+	ret = ov9740_reg_read(client, OV9740_REVISION_NUMBER, &priv->revision);
+	if (ret < 0)
+		goto done;
+
+	ret = ov9740_reg_read(client, OV9740_MANUFACTURER_ID, &priv->manid);
+	if (ret < 0)
+		goto done;
+
+	ret = ov9740_reg_read(client, OV9740_SMIA_VERSION, &priv->smiaver);
+	if (ret < 0)
+		goto done;
+
+	if (priv->model != 0x9740) {
+		ret = -ENODEV;
+		goto done;
+	}
+
+	priv->ident = V4L2_IDENT_OV9740;
+
+	dev_info(&client->dev, "ov9740 Model ID 0x%04x, Revision 0x%02x, "
+		 "Manufacturer 0x%02x, SMIA Version 0x%02x\n",
+		 priv->model, priv->revision, priv->manid, priv->smiaver);
+
+	ret = v4l2_ctrl_handler_setup(&priv->hdl);
+
+done:
+	ov9740_s_power(&priv->subdev, 0);
+	return ret;
+}
+
+/* Request bus settings on camera side */
+static int ov9740_g_mbus_config(struct v4l2_subdev *sd,
+				struct v4l2_mbus_config *cfg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+	cfg->flags = V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_MASTER |
+		V4L2_MBUS_VSYNC_ACTIVE_HIGH | V4L2_MBUS_HSYNC_ACTIVE_HIGH |
+		V4L2_MBUS_DATA_ACTIVE_HIGH;
+	cfg->type = V4L2_MBUS_PARALLEL;
+	cfg->flags = soc_camera_apply_board_flags(icl, cfg);
+
+	return 0;
+}
+
+static struct v4l2_subdev_video_ops ov9740_video_ops = {
+	.s_stream	= ov9740_s_stream,
+	.s_mbus_fmt	= ov9740_s_fmt,
+	.try_mbus_fmt	= ov9740_try_fmt,
+	.enum_mbus_fmt	= ov9740_enum_fmt,
+	.cropcap	= ov9740_cropcap,
+	.g_crop		= ov9740_g_crop,
+	.g_mbus_config	= ov9740_g_mbus_config,
+};
+
+static struct v4l2_subdev_core_ops ov9740_core_ops = {
+	.g_chip_ident		= ov9740_g_chip_ident,
+	.s_power		= ov9740_s_power,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.g_register		= ov9740_get_register,
+	.s_register		= ov9740_set_register,
+#endif
+};
+
+static struct v4l2_subdev_ops ov9740_subdev_ops = {
+	.core			= &ov9740_core_ops,
+	.video			= &ov9740_video_ops,
+};
+
+static const struct v4l2_ctrl_ops ov9740_ctrl_ops = {
+	.s_ctrl = ov9740_s_ctrl,
+};
+
+/*
+ * i2c_driver function
+ */
+static int ov9740_probe(struct i2c_client *client,
+			const struct i2c_device_id *did)
+{
+	struct ov9740_priv *priv;
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+	int ret;
+
+	if (!icl) {
+		dev_err(&client->dev, "Missing platform_data for driver\n");
+		return -EINVAL;
+	}
+
+	priv = kzalloc(sizeof(struct ov9740_priv), GFP_KERNEL);
+	if (!priv) {
+		dev_err(&client->dev, "Failed to allocate private data!\n");
+		return -ENOMEM;
+	}
+
+	v4l2_i2c_subdev_init(&priv->subdev, client, &ov9740_subdev_ops);
+	v4l2_ctrl_handler_init(&priv->hdl, 13);
+	v4l2_ctrl_new_std(&priv->hdl, &ov9740_ctrl_ops,
+			V4L2_CID_VFLIP, 0, 1, 1, 0);
+	v4l2_ctrl_new_std(&priv->hdl, &ov9740_ctrl_ops,
+			V4L2_CID_HFLIP, 0, 1, 1, 0);
+	priv->subdev.ctrl_handler = &priv->hdl;
+	if (priv->hdl.error) {
+		int err = priv->hdl.error;
+
+		kfree(priv);
+		return err;
+	}
+
+	ret = ov9740_video_probe(client);
+	if (ret < 0) {
+		v4l2_ctrl_handler_free(&priv->hdl);
+		kfree(priv);
+	}
+
+	return ret;
+}
+
+static int ov9740_remove(struct i2c_client *client)
+{
+	struct ov9740_priv *priv = i2c_get_clientdata(client);
+
+	v4l2_device_unregister_subdev(&priv->subdev);
+	v4l2_ctrl_handler_free(&priv->hdl);
+	kfree(priv);
+	return 0;
+}
+
+static const struct i2c_device_id ov9740_id[] = {
+	{ "ov9740", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, ov9740_id);
+
+static struct i2c_driver ov9740_i2c_driver = {
+	.driver = {
+		.name = "ov9740",
+	},
+	.probe    = ov9740_probe,
+	.remove   = ov9740_remove,
+	.id_table = ov9740_id,
+};
+
+module_i2c_driver(ov9740_i2c_driver);
+
+MODULE_DESCRIPTION("SoC Camera driver for OmniVision OV9740");
+MODULE_AUTHOR("Andrew Chew <achew@nvidia.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/i2c/soc_camera/rj54n1cb0c.c b/drivers/media/i2c/soc_camera/rj54n1cb0c.c
new file mode 100644
index 0000000..32226c9
--- /dev/null
+++ b/drivers/media/i2c/soc_camera/rj54n1cb0c.c
@@ -0,0 +1,1431 @@
+/*
+ * Driver for RJ54N1CB0C CMOS Image Sensor from Sharp
+ *
+ * Copyright (C) 2009, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/v4l2-mediabus.h>
+#include <linux/videodev2.h>
+#include <linux/module.h>
+
+#include <media/rj54n1cb0c.h>
+#include <media/soc_camera.h>
+#include <media/v4l2-subdev.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-ctrls.h>
+
+#define RJ54N1_DEV_CODE			0x0400
+#define RJ54N1_DEV_CODE2		0x0401
+#define RJ54N1_OUT_SEL			0x0403
+#define RJ54N1_XY_OUTPUT_SIZE_S_H	0x0404
+#define RJ54N1_X_OUTPUT_SIZE_S_L	0x0405
+#define RJ54N1_Y_OUTPUT_SIZE_S_L	0x0406
+#define RJ54N1_XY_OUTPUT_SIZE_P_H	0x0407
+#define RJ54N1_X_OUTPUT_SIZE_P_L	0x0408
+#define RJ54N1_Y_OUTPUT_SIZE_P_L	0x0409
+#define RJ54N1_LINE_LENGTH_PCK_S_H	0x040a
+#define RJ54N1_LINE_LENGTH_PCK_S_L	0x040b
+#define RJ54N1_LINE_LENGTH_PCK_P_H	0x040c
+#define RJ54N1_LINE_LENGTH_PCK_P_L	0x040d
+#define RJ54N1_RESIZE_N			0x040e
+#define RJ54N1_RESIZE_N_STEP		0x040f
+#define RJ54N1_RESIZE_STEP		0x0410
+#define RJ54N1_RESIZE_HOLD_H		0x0411
+#define RJ54N1_RESIZE_HOLD_L		0x0412
+#define RJ54N1_H_OBEN_OFS		0x0413
+#define RJ54N1_V_OBEN_OFS		0x0414
+#define RJ54N1_RESIZE_CONTROL		0x0415
+#define RJ54N1_STILL_CONTROL		0x0417
+#define RJ54N1_INC_USE_SEL_H		0x0425
+#define RJ54N1_INC_USE_SEL_L		0x0426
+#define RJ54N1_MIRROR_STILL_MODE	0x0427
+#define RJ54N1_INIT_START		0x0428
+#define RJ54N1_SCALE_1_2_LEV		0x0429
+#define RJ54N1_SCALE_4_LEV		0x042a
+#define RJ54N1_Y_GAIN			0x04d8
+#define RJ54N1_APT_GAIN_UP		0x04fa
+#define RJ54N1_RA_SEL_UL		0x0530
+#define RJ54N1_BYTE_SWAP		0x0531
+#define RJ54N1_OUT_SIGPO		0x053b
+#define RJ54N1_WB_SEL_WEIGHT_I		0x054e
+#define RJ54N1_BIT8_WB			0x0569
+#define RJ54N1_HCAPS_WB			0x056a
+#define RJ54N1_VCAPS_WB			0x056b
+#define RJ54N1_HCAPE_WB			0x056c
+#define RJ54N1_VCAPE_WB			0x056d
+#define RJ54N1_EXPOSURE_CONTROL		0x058c
+#define RJ54N1_FRAME_LENGTH_S_H		0x0595
+#define RJ54N1_FRAME_LENGTH_S_L		0x0596
+#define RJ54N1_FRAME_LENGTH_P_H		0x0597
+#define RJ54N1_FRAME_LENGTH_P_L		0x0598
+#define RJ54N1_PEAK_H			0x05b7
+#define RJ54N1_PEAK_50			0x05b8
+#define RJ54N1_PEAK_60			0x05b9
+#define RJ54N1_PEAK_DIFF		0x05ba
+#define RJ54N1_IOC			0x05ef
+#define RJ54N1_TG_BYPASS		0x0700
+#define RJ54N1_PLL_L			0x0701
+#define RJ54N1_PLL_N			0x0702
+#define RJ54N1_PLL_EN			0x0704
+#define RJ54N1_RATIO_TG			0x0706
+#define RJ54N1_RATIO_T			0x0707
+#define RJ54N1_RATIO_R			0x0708
+#define RJ54N1_RAMP_TGCLK_EN		0x0709
+#define RJ54N1_OCLK_DSP			0x0710
+#define RJ54N1_RATIO_OP			0x0711
+#define RJ54N1_RATIO_O			0x0712
+#define RJ54N1_OCLK_SEL_EN		0x0713
+#define RJ54N1_CLK_RST			0x0717
+#define RJ54N1_RESET_STANDBY		0x0718
+#define RJ54N1_FWFLG			0x07fe
+
+#define E_EXCLK				(1 << 7)
+#define SOFT_STDBY			(1 << 4)
+#define SEN_RSTX			(1 << 2)
+#define TG_RSTX				(1 << 1)
+#define DSP_RSTX			(1 << 0)
+
+#define RESIZE_HOLD_SEL			(1 << 2)
+#define RESIZE_GO			(1 << 1)
+
+/*
+ * When cropping, the camera automatically centers the cropped region, there
+ * doesn't seem to be a way to specify an explicit location of the rectangle.
+ */
+#define RJ54N1_COLUMN_SKIP		0
+#define RJ54N1_ROW_SKIP			0
+#define RJ54N1_MAX_WIDTH		1600
+#define RJ54N1_MAX_HEIGHT		1200
+
+#define PLL_L				2
+#define PLL_N				0x31
+
+/* I2C addresses: 0x50, 0x51, 0x60, 0x61 */
+
+/* RJ54N1CB0C has only one fixed colorspace per pixelcode */
+struct rj54n1_datafmt {
+	enum v4l2_mbus_pixelcode	code;
+	enum v4l2_colorspace		colorspace;
+};
+
+/* Find a data format by a pixel code in an array */
+static const struct rj54n1_datafmt *rj54n1_find_datafmt(
+	enum v4l2_mbus_pixelcode code, const struct rj54n1_datafmt *fmt,
+	int n)
+{
+	int i;
+	for (i = 0; i < n; i++)
+		if (fmt[i].code == code)
+			return fmt + i;
+
+	return NULL;
+}
+
+static const struct rj54n1_datafmt rj54n1_colour_fmts[] = {
+	{V4L2_MBUS_FMT_YUYV8_2X8, V4L2_COLORSPACE_JPEG},
+	{V4L2_MBUS_FMT_YVYU8_2X8, V4L2_COLORSPACE_JPEG},
+	{V4L2_MBUS_FMT_RGB565_2X8_LE, V4L2_COLORSPACE_SRGB},
+	{V4L2_MBUS_FMT_RGB565_2X8_BE, V4L2_COLORSPACE_SRGB},
+	{V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE, V4L2_COLORSPACE_SRGB},
+	{V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_LE, V4L2_COLORSPACE_SRGB},
+	{V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_BE, V4L2_COLORSPACE_SRGB},
+	{V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_BE, V4L2_COLORSPACE_SRGB},
+	{V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_COLORSPACE_SRGB},
+};
+
+struct rj54n1_clock_div {
+	u8 ratio_tg;	/* can be 0 or an odd number */
+	u8 ratio_t;
+	u8 ratio_r;
+	u8 ratio_op;
+	u8 ratio_o;
+};
+
+struct rj54n1 {
+	struct v4l2_subdev subdev;
+	struct v4l2_ctrl_handler hdl;
+	struct rj54n1_clock_div clk_div;
+	const struct rj54n1_datafmt *fmt;
+	struct v4l2_rect rect;	/* Sensor window */
+	unsigned int tgclk_mhz;
+	bool auto_wb;
+	unsigned short width;	/* Output window */
+	unsigned short height;
+	unsigned short resize;	/* Sensor * 1024 / resize = Output */
+	unsigned short scale;
+	u8 bank;
+};
+
+struct rj54n1_reg_val {
+	u16 reg;
+	u8 val;
+};
+
+static const struct rj54n1_reg_val bank_4[] = {
+	{0x417, 0},
+	{0x42c, 0},
+	{0x42d, 0xf0},
+	{0x42e, 0},
+	{0x42f, 0x50},
+	{0x430, 0xf5},
+	{0x431, 0x16},
+	{0x432, 0x20},
+	{0x433, 0},
+	{0x434, 0xc8},
+	{0x43c, 8},
+	{0x43e, 0x90},
+	{0x445, 0x83},
+	{0x4ba, 0x58},
+	{0x4bb, 4},
+	{0x4bc, 0x20},
+	{0x4db, 4},
+	{0x4fe, 2},
+};
+
+static const struct rj54n1_reg_val bank_5[] = {
+	{0x514, 0},
+	{0x516, 0},
+	{0x518, 0},
+	{0x51a, 0},
+	{0x51d, 0xff},
+	{0x56f, 0x28},
+	{0x575, 0x40},
+	{0x5bc, 0x48},
+	{0x5c1, 6},
+	{0x5e5, 0x11},
+	{0x5e6, 0x43},
+	{0x5e7, 0x33},
+	{0x5e8, 0x21},
+	{0x5e9, 0x30},
+	{0x5ea, 0x0},
+	{0x5eb, 0xa5},
+	{0x5ec, 0xff},
+	{0x5fe, 2},
+};
+
+static const struct rj54n1_reg_val bank_7[] = {
+	{0x70a, 0},
+	{0x714, 0xff},
+	{0x715, 0xff},
+	{0x716, 0x1f},
+	{0x7FE, 2},
+};
+
+static const struct rj54n1_reg_val bank_8[] = {
+	{0x800, 0x00},
+	{0x801, 0x01},
+	{0x802, 0x61},
+	{0x805, 0x00},
+	{0x806, 0x00},
+	{0x807, 0x00},
+	{0x808, 0x00},
+	{0x809, 0x01},
+	{0x80A, 0x61},
+	{0x80B, 0x00},
+	{0x80C, 0x01},
+	{0x80D, 0x00},
+	{0x80E, 0x00},
+	{0x80F, 0x00},
+	{0x810, 0x00},
+	{0x811, 0x01},
+	{0x812, 0x61},
+	{0x813, 0x00},
+	{0x814, 0x11},
+	{0x815, 0x00},
+	{0x816, 0x41},
+	{0x817, 0x00},
+	{0x818, 0x51},
+	{0x819, 0x01},
+	{0x81A, 0x1F},
+	{0x81B, 0x00},
+	{0x81C, 0x01},
+	{0x81D, 0x00},
+	{0x81E, 0x11},
+	{0x81F, 0x00},
+	{0x820, 0x41},
+	{0x821, 0x00},
+	{0x822, 0x51},
+	{0x823, 0x00},
+	{0x824, 0x00},
+	{0x825, 0x00},
+	{0x826, 0x47},
+	{0x827, 0x01},
+	{0x828, 0x4F},
+	{0x829, 0x00},
+	{0x82A, 0x00},
+	{0x82B, 0x00},
+	{0x82C, 0x30},
+	{0x82D, 0x00},
+	{0x82E, 0x40},
+	{0x82F, 0x00},
+	{0x830, 0xB3},
+	{0x831, 0x00},
+	{0x832, 0xE3},
+	{0x833, 0x00},
+	{0x834, 0x00},
+	{0x835, 0x00},
+	{0x836, 0x00},
+	{0x837, 0x00},
+	{0x838, 0x00},
+	{0x839, 0x01},
+	{0x83A, 0x61},
+	{0x83B, 0x00},
+	{0x83C, 0x01},
+	{0x83D, 0x00},
+	{0x83E, 0x00},
+	{0x83F, 0x00},
+	{0x840, 0x00},
+	{0x841, 0x01},
+	{0x842, 0x61},
+	{0x843, 0x00},
+	{0x844, 0x1D},
+	{0x845, 0x00},
+	{0x846, 0x00},
+	{0x847, 0x00},
+	{0x848, 0x00},
+	{0x849, 0x01},
+	{0x84A, 0x1F},
+	{0x84B, 0x00},
+	{0x84C, 0x05},
+	{0x84D, 0x00},
+	{0x84E, 0x19},
+	{0x84F, 0x01},
+	{0x850, 0x21},
+	{0x851, 0x01},
+	{0x852, 0x5D},
+	{0x853, 0x00},
+	{0x854, 0x00},
+	{0x855, 0x00},
+	{0x856, 0x19},
+	{0x857, 0x01},
+	{0x858, 0x21},
+	{0x859, 0x00},
+	{0x85A, 0x00},
+	{0x85B, 0x00},
+	{0x85C, 0x00},
+	{0x85D, 0x00},
+	{0x85E, 0x00},
+	{0x85F, 0x00},
+	{0x860, 0xB3},
+	{0x861, 0x00},
+	{0x862, 0xE3},
+	{0x863, 0x00},
+	{0x864, 0x00},
+	{0x865, 0x00},
+	{0x866, 0x00},
+	{0x867, 0x00},
+	{0x868, 0x00},
+	{0x869, 0xE2},
+	{0x86A, 0x00},
+	{0x86B, 0x01},
+	{0x86C, 0x06},
+	{0x86D, 0x00},
+	{0x86E, 0x00},
+	{0x86F, 0x00},
+	{0x870, 0x60},
+	{0x871, 0x8C},
+	{0x872, 0x10},
+	{0x873, 0x00},
+	{0x874, 0xE0},
+	{0x875, 0x00},
+	{0x876, 0x27},
+	{0x877, 0x01},
+	{0x878, 0x00},
+	{0x879, 0x00},
+	{0x87A, 0x00},
+	{0x87B, 0x03},
+	{0x87C, 0x00},
+	{0x87D, 0x00},
+	{0x87E, 0x00},
+	{0x87F, 0x00},
+	{0x880, 0x00},
+	{0x881, 0x00},
+	{0x882, 0x00},
+	{0x883, 0x00},
+	{0x884, 0x00},
+	{0x885, 0x00},
+	{0x886, 0xF8},
+	{0x887, 0x00},
+	{0x888, 0x03},
+	{0x889, 0x00},
+	{0x88A, 0x64},
+	{0x88B, 0x00},
+	{0x88C, 0x03},
+	{0x88D, 0x00},
+	{0x88E, 0xB1},
+	{0x88F, 0x00},
+	{0x890, 0x03},
+	{0x891, 0x01},
+	{0x892, 0x1D},
+	{0x893, 0x00},
+	{0x894, 0x03},
+	{0x895, 0x01},
+	{0x896, 0x4B},
+	{0x897, 0x00},
+	{0x898, 0xE5},
+	{0x899, 0x00},
+	{0x89A, 0x01},
+	{0x89B, 0x00},
+	{0x89C, 0x01},
+	{0x89D, 0x04},
+	{0x89E, 0xC8},
+	{0x89F, 0x00},
+	{0x8A0, 0x01},
+	{0x8A1, 0x01},
+	{0x8A2, 0x61},
+	{0x8A3, 0x00},
+	{0x8A4, 0x01},
+	{0x8A5, 0x00},
+	{0x8A6, 0x00},
+	{0x8A7, 0x00},
+	{0x8A8, 0x00},
+	{0x8A9, 0x00},
+	{0x8AA, 0x7F},
+	{0x8AB, 0x03},
+	{0x8AC, 0x00},
+	{0x8AD, 0x00},
+	{0x8AE, 0x00},
+	{0x8AF, 0x00},
+	{0x8B0, 0x00},
+	{0x8B1, 0x00},
+	{0x8B6, 0x00},
+	{0x8B7, 0x01},
+	{0x8B8, 0x00},
+	{0x8B9, 0x00},
+	{0x8BA, 0x02},
+	{0x8BB, 0x00},
+	{0x8BC, 0xFF},
+	{0x8BD, 0x00},
+	{0x8FE, 2},
+};
+
+static const struct rj54n1_reg_val bank_10[] = {
+	{0x10bf, 0x69}
+};
+
+/* Clock dividers - these are default register values, divider = register + 1 */
+static const struct rj54n1_clock_div clk_div = {
+	.ratio_tg	= 3 /* default: 5 */,
+	.ratio_t	= 4 /* default: 1 */,
+	.ratio_r	= 4 /* default: 0 */,
+	.ratio_op	= 1 /* default: 5 */,
+	.ratio_o	= 9 /* default: 0 */,
+};
+
+static struct rj54n1 *to_rj54n1(const struct i2c_client *client)
+{
+	return container_of(i2c_get_clientdata(client), struct rj54n1, subdev);
+}
+
+static int reg_read(struct i2c_client *client, const u16 reg)
+{
+	struct rj54n1 *rj54n1 = to_rj54n1(client);
+	int ret;
+
+	/* set bank */
+	if (rj54n1->bank != reg >> 8) {
+		dev_dbg(&client->dev, "[0x%x] = 0x%x\n", 0xff, reg >> 8);
+		ret = i2c_smbus_write_byte_data(client, 0xff, reg >> 8);
+		if (ret < 0)
+			return ret;
+		rj54n1->bank = reg >> 8;
+	}
+	return i2c_smbus_read_byte_data(client, reg & 0xff);
+}
+
+static int reg_write(struct i2c_client *client, const u16 reg,
+		     const u8 data)
+{
+	struct rj54n1 *rj54n1 = to_rj54n1(client);
+	int ret;
+
+	/* set bank */
+	if (rj54n1->bank != reg >> 8) {
+		dev_dbg(&client->dev, "[0x%x] = 0x%x\n", 0xff, reg >> 8);
+		ret = i2c_smbus_write_byte_data(client, 0xff, reg >> 8);
+		if (ret < 0)
+			return ret;
+		rj54n1->bank = reg >> 8;
+	}
+	dev_dbg(&client->dev, "[0x%x] = 0x%x\n", reg & 0xff, data);
+	return i2c_smbus_write_byte_data(client, reg & 0xff, data);
+}
+
+static int reg_set(struct i2c_client *client, const u16 reg,
+		   const u8 data, const u8 mask)
+{
+	int ret;
+
+	ret = reg_read(client, reg);
+	if (ret < 0)
+		return ret;
+	return reg_write(client, reg, (ret & ~mask) | (data & mask));
+}
+
+static int reg_write_multiple(struct i2c_client *client,
+			      const struct rj54n1_reg_val *rv, const int n)
+{
+	int i, ret;
+
+	for (i = 0; i < n; i++) {
+		ret = reg_write(client, rv->reg, rv->val);
+		if (ret < 0)
+			return ret;
+		rv++;
+	}
+
+	return 0;
+}
+
+static int rj54n1_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
+			   enum v4l2_mbus_pixelcode *code)
+{
+	if (index >= ARRAY_SIZE(rj54n1_colour_fmts))
+		return -EINVAL;
+
+	*code = rj54n1_colour_fmts[index].code;
+	return 0;
+}
+
+static int rj54n1_s_stream(struct v4l2_subdev *sd, int enable)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	/* Switch between preview and still shot modes */
+	return reg_set(client, RJ54N1_STILL_CONTROL, (!enable) << 7, 0x80);
+}
+
+static int rj54n1_set_rect(struct i2c_client *client,
+			   u16 reg_x, u16 reg_y, u16 reg_xy,
+			   u32 width, u32 height)
+{
+	int ret;
+
+	ret = reg_write(client, reg_xy,
+			((width >> 4) & 0x70) |
+			((height >> 8) & 7));
+
+	if (!ret)
+		ret = reg_write(client, reg_x, width & 0xff);
+	if (!ret)
+		ret = reg_write(client, reg_y, height & 0xff);
+
+	return ret;
+}
+
+/*
+ * Some commands, specifically certain initialisation sequences, require
+ * a commit operation.
+ */
+static int rj54n1_commit(struct i2c_client *client)
+{
+	int ret = reg_write(client, RJ54N1_INIT_START, 1);
+	msleep(10);
+	if (!ret)
+		ret = reg_write(client, RJ54N1_INIT_START, 0);
+	return ret;
+}
+
+static int rj54n1_sensor_scale(struct v4l2_subdev *sd, s32 *in_w, s32 *in_h,
+			       s32 *out_w, s32 *out_h);
+
+static int rj54n1_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct rj54n1 *rj54n1 = to_rj54n1(client);
+	struct v4l2_rect *rect = &a->c;
+	int dummy = 0, output_w, output_h,
+		input_w = rect->width, input_h = rect->height;
+	int ret;
+
+	/* arbitrary minimum width and height, edges unimportant */
+	soc_camera_limit_side(&dummy, &input_w,
+		     RJ54N1_COLUMN_SKIP, 8, RJ54N1_MAX_WIDTH);
+
+	soc_camera_limit_side(&dummy, &input_h,
+		     RJ54N1_ROW_SKIP, 8, RJ54N1_MAX_HEIGHT);
+
+	output_w = (input_w * 1024 + rj54n1->resize / 2) / rj54n1->resize;
+	output_h = (input_h * 1024 + rj54n1->resize / 2) / rj54n1->resize;
+
+	dev_dbg(&client->dev, "Scaling for %dx%d : %u = %dx%d\n",
+		input_w, input_h, rj54n1->resize, output_w, output_h);
+
+	ret = rj54n1_sensor_scale(sd, &input_w, &input_h, &output_w, &output_h);
+	if (ret < 0)
+		return ret;
+
+	rj54n1->width		= output_w;
+	rj54n1->height		= output_h;
+	rj54n1->resize		= ret;
+	rj54n1->rect.width	= input_w;
+	rj54n1->rect.height	= input_h;
+
+	return 0;
+}
+
+static int rj54n1_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct rj54n1 *rj54n1 = to_rj54n1(client);
+
+	a->c	= rj54n1->rect;
+	a->type	= V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+	return 0;
+}
+
+static int rj54n1_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
+{
+	a->bounds.left			= RJ54N1_COLUMN_SKIP;
+	a->bounds.top			= RJ54N1_ROW_SKIP;
+	a->bounds.width			= RJ54N1_MAX_WIDTH;
+	a->bounds.height		= RJ54N1_MAX_HEIGHT;
+	a->defrect			= a->bounds;
+	a->type				= V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	a->pixelaspect.numerator	= 1;
+	a->pixelaspect.denominator	= 1;
+
+	return 0;
+}
+
+static int rj54n1_g_fmt(struct v4l2_subdev *sd,
+			struct v4l2_mbus_framefmt *mf)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct rj54n1 *rj54n1 = to_rj54n1(client);
+
+	mf->code	= rj54n1->fmt->code;
+	mf->colorspace	= rj54n1->fmt->colorspace;
+	mf->field	= V4L2_FIELD_NONE;
+	mf->width	= rj54n1->width;
+	mf->height	= rj54n1->height;
+
+	return 0;
+}
+
+/*
+ * The actual geometry configuration routine. It scales the input window into
+ * the output one, updates the window sizes and returns an error or the resize
+ * coefficient on success. Note: we only use the "Fixed Scaling" on this camera.
+ */
+static int rj54n1_sensor_scale(struct v4l2_subdev *sd, s32 *in_w, s32 *in_h,
+			       s32 *out_w, s32 *out_h)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct rj54n1 *rj54n1 = to_rj54n1(client);
+	unsigned int skip, resize, input_w = *in_w, input_h = *in_h,
+		output_w = *out_w, output_h = *out_h;
+	u16 inc_sel, wb_bit8, wb_left, wb_right, wb_top, wb_bottom;
+	unsigned int peak, peak_50, peak_60;
+	int ret;
+
+	/*
+	 * We have a problem with crops, where the window is larger than 512x384
+	 * and output window is larger than a half of the input one. In this
+	 * case we have to either reduce the input window to equal or below
+	 * 512x384 or the output window to equal or below 1/2 of the input.
+	 */
+	if (output_w > max(512U, input_w / 2)) {
+		if (2 * output_w > RJ54N1_MAX_WIDTH) {
+			input_w = RJ54N1_MAX_WIDTH;
+			output_w = RJ54N1_MAX_WIDTH / 2;
+		} else {
+			input_w = output_w * 2;
+		}
+
+		dev_dbg(&client->dev, "Adjusted output width: in %u, out %u\n",
+			input_w, output_w);
+	}
+
+	if (output_h > max(384U, input_h / 2)) {
+		if (2 * output_h > RJ54N1_MAX_HEIGHT) {
+			input_h = RJ54N1_MAX_HEIGHT;
+			output_h = RJ54N1_MAX_HEIGHT / 2;
+		} else {
+			input_h = output_h * 2;
+		}
+
+		dev_dbg(&client->dev, "Adjusted output height: in %u, out %u\n",
+			input_h, output_h);
+	}
+
+	/* Idea: use the read mode for snapshots, handle separate geometries */
+	ret = rj54n1_set_rect(client, RJ54N1_X_OUTPUT_SIZE_S_L,
+			      RJ54N1_Y_OUTPUT_SIZE_S_L,
+			      RJ54N1_XY_OUTPUT_SIZE_S_H, output_w, output_h);
+	if (!ret)
+		ret = rj54n1_set_rect(client, RJ54N1_X_OUTPUT_SIZE_P_L,
+			      RJ54N1_Y_OUTPUT_SIZE_P_L,
+			      RJ54N1_XY_OUTPUT_SIZE_P_H, output_w, output_h);
+
+	if (ret < 0)
+		return ret;
+
+	if (output_w > input_w && output_h > input_h) {
+		input_w = output_w;
+		input_h = output_h;
+
+		resize = 1024;
+	} else {
+		unsigned int resize_x, resize_y;
+		resize_x = (input_w * 1024 + output_w / 2) / output_w;
+		resize_y = (input_h * 1024 + output_h / 2) / output_h;
+
+		/* We want max(resize_x, resize_y), check if it still fits */
+		if (resize_x > resize_y &&
+		    (output_h * resize_x + 512) / 1024 > RJ54N1_MAX_HEIGHT)
+			resize = (RJ54N1_MAX_HEIGHT * 1024 + output_h / 2) /
+				output_h;
+		else if (resize_y > resize_x &&
+			 (output_w * resize_y + 512) / 1024 > RJ54N1_MAX_WIDTH)
+			resize = (RJ54N1_MAX_WIDTH * 1024 + output_w / 2) /
+				output_w;
+		else
+			resize = max(resize_x, resize_y);
+
+		/* Prohibited value ranges */
+		switch (resize) {
+		case 2040 ... 2047:
+			resize = 2039;
+			break;
+		case 4080 ... 4095:
+			resize = 4079;
+			break;
+		case 8160 ... 8191:
+			resize = 8159;
+			break;
+		case 16320 ... 16384:
+			resize = 16319;
+		}
+	}
+
+	/* Set scaling */
+	ret = reg_write(client, RJ54N1_RESIZE_HOLD_L, resize & 0xff);
+	if (!ret)
+		ret = reg_write(client, RJ54N1_RESIZE_HOLD_H, resize >> 8);
+
+	if (ret < 0)
+		return ret;
+
+	/*
+	 * Configure a skipping bitmask. The sensor will select a skipping value
+	 * among set bits automatically. This is very unclear in the datasheet
+	 * too. I was told, in this register one enables all skipping values,
+	 * that are required for a specific resize, and the camera selects
+	 * automatically, which ones to use. But it is unclear how to identify,
+	 * which cropping values are needed. Secondly, why don't we just set all
+	 * bits and let the camera choose? Would it increase processing time and
+	 * reduce the framerate? Using 0xfffc for INC_USE_SEL doesn't seem to
+	 * improve the image quality or stability for larger frames (see comment
+	 * above), but I didn't check the framerate.
+	 */
+	skip = min(resize / 1024, 15U);
+
+	inc_sel = 1 << skip;
+
+	if (inc_sel <= 2)
+		inc_sel = 0xc;
+	else if (resize & 1023 && skip < 15)
+		inc_sel |= 1 << (skip + 1);
+
+	ret = reg_write(client, RJ54N1_INC_USE_SEL_L, inc_sel & 0xfc);
+	if (!ret)
+		ret = reg_write(client, RJ54N1_INC_USE_SEL_H, inc_sel >> 8);
+
+	if (!rj54n1->auto_wb) {
+		/* Auto white balance window */
+		wb_left	  = output_w / 16;
+		wb_right  = (3 * output_w / 4 - 3) / 4;
+		wb_top	  = output_h / 16;
+		wb_bottom = (3 * output_h / 4 - 3) / 4;
+		wb_bit8	  = ((wb_left >> 2) & 0x40) | ((wb_top >> 4) & 0x10) |
+			((wb_right >> 6) & 4) | ((wb_bottom >> 8) & 1);
+
+		if (!ret)
+			ret = reg_write(client, RJ54N1_BIT8_WB, wb_bit8);
+		if (!ret)
+			ret = reg_write(client, RJ54N1_HCAPS_WB, wb_left);
+		if (!ret)
+			ret = reg_write(client, RJ54N1_VCAPS_WB, wb_top);
+		if (!ret)
+			ret = reg_write(client, RJ54N1_HCAPE_WB, wb_right);
+		if (!ret)
+			ret = reg_write(client, RJ54N1_VCAPE_WB, wb_bottom);
+	}
+
+	/* Antiflicker */
+	peak = 12 * RJ54N1_MAX_WIDTH * (1 << 14) * resize / rj54n1->tgclk_mhz /
+		10000;
+	peak_50 = peak / 6;
+	peak_60 = peak / 5;
+
+	if (!ret)
+		ret = reg_write(client, RJ54N1_PEAK_H,
+				((peak_50 >> 4) & 0xf0) | (peak_60 >> 8));
+	if (!ret)
+		ret = reg_write(client, RJ54N1_PEAK_50, peak_50);
+	if (!ret)
+		ret = reg_write(client, RJ54N1_PEAK_60, peak_60);
+	if (!ret)
+		ret = reg_write(client, RJ54N1_PEAK_DIFF, peak / 150);
+
+	/* Start resizing */
+	if (!ret)
+		ret = reg_write(client, RJ54N1_RESIZE_CONTROL,
+				RESIZE_HOLD_SEL | RESIZE_GO | 1);
+
+	if (ret < 0)
+		return ret;
+
+	/* Constant taken from manufacturer's example */
+	msleep(230);
+
+	ret = reg_write(client, RJ54N1_RESIZE_CONTROL, RESIZE_HOLD_SEL | 1);
+	if (ret < 0)
+		return ret;
+
+	*in_w = (output_w * resize + 512) / 1024;
+	*in_h = (output_h * resize + 512) / 1024;
+	*out_w = output_w;
+	*out_h = output_h;
+
+	dev_dbg(&client->dev, "Scaled for %dx%d : %u = %ux%u, skip %u\n",
+		*in_w, *in_h, resize, output_w, output_h, skip);
+
+	return resize;
+}
+
+static int rj54n1_set_clock(struct i2c_client *client)
+{
+	struct rj54n1 *rj54n1 = to_rj54n1(client);
+	int ret;
+
+	/* Enable external clock */
+	ret = reg_write(client, RJ54N1_RESET_STANDBY, E_EXCLK | SOFT_STDBY);
+	/* Leave stand-by. Note: use this when implementing suspend / resume */
+	if (!ret)
+		ret = reg_write(client, RJ54N1_RESET_STANDBY, E_EXCLK);
+
+	if (!ret)
+		ret = reg_write(client, RJ54N1_PLL_L, PLL_L);
+	if (!ret)
+		ret = reg_write(client, RJ54N1_PLL_N, PLL_N);
+
+	/* TGCLK dividers */
+	if (!ret)
+		ret = reg_write(client, RJ54N1_RATIO_TG,
+				rj54n1->clk_div.ratio_tg);
+	if (!ret)
+		ret = reg_write(client, RJ54N1_RATIO_T,
+				rj54n1->clk_div.ratio_t);
+	if (!ret)
+		ret = reg_write(client, RJ54N1_RATIO_R,
+				rj54n1->clk_div.ratio_r);
+
+	/* Enable TGCLK & RAMP */
+	if (!ret)
+		ret = reg_write(client, RJ54N1_RAMP_TGCLK_EN, 3);
+
+	/* Disable clock output */
+	if (!ret)
+		ret = reg_write(client, RJ54N1_OCLK_DSP, 0);
+
+	/* Set divisors */
+	if (!ret)
+		ret = reg_write(client, RJ54N1_RATIO_OP,
+				rj54n1->clk_div.ratio_op);
+	if (!ret)
+		ret = reg_write(client, RJ54N1_RATIO_O,
+				rj54n1->clk_div.ratio_o);
+
+	/* Enable OCLK */
+	if (!ret)
+		ret = reg_write(client, RJ54N1_OCLK_SEL_EN, 1);
+
+	/* Use PLL for Timing Generator, write 2 to reserved bits */
+	if (!ret)
+		ret = reg_write(client, RJ54N1_TG_BYPASS, 2);
+
+	/* Take sensor out of reset */
+	if (!ret)
+		ret = reg_write(client, RJ54N1_RESET_STANDBY,
+				E_EXCLK | SEN_RSTX);
+	/* Enable PLL */
+	if (!ret)
+		ret = reg_write(client, RJ54N1_PLL_EN, 1);
+
+	/* Wait for PLL to stabilise */
+	msleep(10);
+
+	/* Enable clock to frequency divider */
+	if (!ret)
+		ret = reg_write(client, RJ54N1_CLK_RST, 1);
+
+	if (!ret)
+		ret = reg_read(client, RJ54N1_CLK_RST);
+	if (ret != 1) {
+		dev_err(&client->dev,
+			"Resetting RJ54N1CB0C clock failed: %d!\n", ret);
+		return -EIO;
+	}
+
+	/* Start the PLL */
+	ret = reg_set(client, RJ54N1_OCLK_DSP, 1, 1);
+
+	/* Enable OCLK */
+	if (!ret)
+		ret = reg_write(client, RJ54N1_OCLK_SEL_EN, 1);
+
+	return ret;
+}
+
+static int rj54n1_reg_init(struct i2c_client *client)
+{
+	struct rj54n1 *rj54n1 = to_rj54n1(client);
+	int ret = rj54n1_set_clock(client);
+
+	if (!ret)
+		ret = reg_write_multiple(client, bank_7, ARRAY_SIZE(bank_7));
+	if (!ret)
+		ret = reg_write_multiple(client, bank_10, ARRAY_SIZE(bank_10));
+
+	/* Set binning divisors */
+	if (!ret)
+		ret = reg_write(client, RJ54N1_SCALE_1_2_LEV, 3 | (7 << 4));
+	if (!ret)
+		ret = reg_write(client, RJ54N1_SCALE_4_LEV, 0xf);
+
+	/* Switch to fixed resize mode */
+	if (!ret)
+		ret = reg_write(client, RJ54N1_RESIZE_CONTROL,
+				RESIZE_HOLD_SEL | 1);
+
+	/* Set gain */
+	if (!ret)
+		ret = reg_write(client, RJ54N1_Y_GAIN, 0x84);
+
+	/*
+	 * Mirror the image back: default is upside down and left-to-right...
+	 * Set manual preview / still shot switching
+	 */
+	if (!ret)
+		ret = reg_write(client, RJ54N1_MIRROR_STILL_MODE, 0x27);
+
+	if (!ret)
+		ret = reg_write_multiple(client, bank_4, ARRAY_SIZE(bank_4));
+
+	/* Auto exposure area */
+	if (!ret)
+		ret = reg_write(client, RJ54N1_EXPOSURE_CONTROL, 0x80);
+	/* Check current auto WB config */
+	if (!ret)
+		ret = reg_read(client, RJ54N1_WB_SEL_WEIGHT_I);
+	if (ret >= 0) {
+		rj54n1->auto_wb = ret & 0x80;
+		ret = reg_write_multiple(client, bank_5, ARRAY_SIZE(bank_5));
+	}
+	if (!ret)
+		ret = reg_write_multiple(client, bank_8, ARRAY_SIZE(bank_8));
+
+	if (!ret)
+		ret = reg_write(client, RJ54N1_RESET_STANDBY,
+				E_EXCLK | DSP_RSTX | SEN_RSTX);
+
+	/* Commit init */
+	if (!ret)
+		ret = rj54n1_commit(client);
+
+	/* Take DSP, TG, sensor out of reset */
+	if (!ret)
+		ret = reg_write(client, RJ54N1_RESET_STANDBY,
+				E_EXCLK | DSP_RSTX | TG_RSTX | SEN_RSTX);
+
+	/* Start register update? Same register as 0x?FE in many bank_* sets */
+	if (!ret)
+		ret = reg_write(client, RJ54N1_FWFLG, 2);
+
+	/* Constant taken from manufacturer's example */
+	msleep(700);
+
+	return ret;
+}
+
+static int rj54n1_try_fmt(struct v4l2_subdev *sd,
+			  struct v4l2_mbus_framefmt *mf)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct rj54n1 *rj54n1 = to_rj54n1(client);
+	const struct rj54n1_datafmt *fmt;
+	int align = mf->code == V4L2_MBUS_FMT_SBGGR10_1X10 ||
+		mf->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_BE ||
+		mf->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_BE ||
+		mf->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE ||
+		mf->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_LE;
+
+	dev_dbg(&client->dev, "%s: code = %d, width = %u, height = %u\n",
+		__func__, mf->code, mf->width, mf->height);
+
+	fmt = rj54n1_find_datafmt(mf->code, rj54n1_colour_fmts,
+				  ARRAY_SIZE(rj54n1_colour_fmts));
+	if (!fmt) {
+		fmt = rj54n1->fmt;
+		mf->code = fmt->code;
+	}
+
+	mf->field	= V4L2_FIELD_NONE;
+	mf->colorspace	= fmt->colorspace;
+
+	v4l_bound_align_image(&mf->width, 112, RJ54N1_MAX_WIDTH, align,
+			      &mf->height, 84, RJ54N1_MAX_HEIGHT, align, 0);
+
+	return 0;
+}
+
+static int rj54n1_s_fmt(struct v4l2_subdev *sd,
+			struct v4l2_mbus_framefmt *mf)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct rj54n1 *rj54n1 = to_rj54n1(client);
+	const struct rj54n1_datafmt *fmt;
+	int output_w, output_h, max_w, max_h,
+		input_w = rj54n1->rect.width, input_h = rj54n1->rect.height;
+	int ret;
+
+	/*
+	 * The host driver can call us without .try_fmt(), so, we have to take
+	 * care ourseleves
+	 */
+	rj54n1_try_fmt(sd, mf);
+
+	/*
+	 * Verify if the sensor has just been powered on. TODO: replace this
+	 * with proper PM, when a suitable API is available.
+	 */
+	ret = reg_read(client, RJ54N1_RESET_STANDBY);
+	if (ret < 0)
+		return ret;
+
+	if (!(ret & E_EXCLK)) {
+		ret = rj54n1_reg_init(client);
+		if (ret < 0)
+			return ret;
+	}
+
+	dev_dbg(&client->dev, "%s: code = %d, width = %u, height = %u\n",
+		__func__, mf->code, mf->width, mf->height);
+
+	/* RA_SEL_UL is only relevant for raw modes, ignored otherwise. */
+	switch (mf->code) {
+	case V4L2_MBUS_FMT_YUYV8_2X8:
+		ret = reg_write(client, RJ54N1_OUT_SEL, 0);
+		if (!ret)
+			ret = reg_set(client, RJ54N1_BYTE_SWAP, 8, 8);
+		break;
+	case V4L2_MBUS_FMT_YVYU8_2X8:
+		ret = reg_write(client, RJ54N1_OUT_SEL, 0);
+		if (!ret)
+			ret = reg_set(client, RJ54N1_BYTE_SWAP, 0, 8);
+		break;
+	case V4L2_MBUS_FMT_RGB565_2X8_LE:
+		ret = reg_write(client, RJ54N1_OUT_SEL, 0x11);
+		if (!ret)
+			ret = reg_set(client, RJ54N1_BYTE_SWAP, 8, 8);
+		break;
+	case V4L2_MBUS_FMT_RGB565_2X8_BE:
+		ret = reg_write(client, RJ54N1_OUT_SEL, 0x11);
+		if (!ret)
+			ret = reg_set(client, RJ54N1_BYTE_SWAP, 0, 8);
+		break;
+	case V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_LE:
+		ret = reg_write(client, RJ54N1_OUT_SEL, 4);
+		if (!ret)
+			ret = reg_set(client, RJ54N1_BYTE_SWAP, 8, 8);
+		if (!ret)
+			ret = reg_write(client, RJ54N1_RA_SEL_UL, 0);
+		break;
+	case V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE:
+		ret = reg_write(client, RJ54N1_OUT_SEL, 4);
+		if (!ret)
+			ret = reg_set(client, RJ54N1_BYTE_SWAP, 8, 8);
+		if (!ret)
+			ret = reg_write(client, RJ54N1_RA_SEL_UL, 8);
+		break;
+	case V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_BE:
+		ret = reg_write(client, RJ54N1_OUT_SEL, 4);
+		if (!ret)
+			ret = reg_set(client, RJ54N1_BYTE_SWAP, 0, 8);
+		if (!ret)
+			ret = reg_write(client, RJ54N1_RA_SEL_UL, 0);
+		break;
+	case V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_BE:
+		ret = reg_write(client, RJ54N1_OUT_SEL, 4);
+		if (!ret)
+			ret = reg_set(client, RJ54N1_BYTE_SWAP, 0, 8);
+		if (!ret)
+			ret = reg_write(client, RJ54N1_RA_SEL_UL, 8);
+		break;
+	case V4L2_MBUS_FMT_SBGGR10_1X10:
+		ret = reg_write(client, RJ54N1_OUT_SEL, 5);
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	/* Special case: a raw mode with 10 bits of data per clock tick */
+	if (!ret)
+		ret = reg_set(client, RJ54N1_OCLK_SEL_EN,
+			      (mf->code == V4L2_MBUS_FMT_SBGGR10_1X10) << 1, 2);
+
+	if (ret < 0)
+		return ret;
+
+	/* Supported scales 1:1 >= scale > 1:16 */
+	max_w = mf->width * (16 * 1024 - 1) / 1024;
+	if (input_w > max_w)
+		input_w = max_w;
+	max_h = mf->height * (16 * 1024 - 1) / 1024;
+	if (input_h > max_h)
+		input_h = max_h;
+
+	output_w = mf->width;
+	output_h = mf->height;
+
+	ret = rj54n1_sensor_scale(sd, &input_w, &input_h, &output_w, &output_h);
+	if (ret < 0)
+		return ret;
+
+	fmt = rj54n1_find_datafmt(mf->code, rj54n1_colour_fmts,
+				  ARRAY_SIZE(rj54n1_colour_fmts));
+
+	rj54n1->fmt		= fmt;
+	rj54n1->resize		= ret;
+	rj54n1->rect.width	= input_w;
+	rj54n1->rect.height	= input_h;
+	rj54n1->width		= output_w;
+	rj54n1->height		= output_h;
+
+	mf->width		= output_w;
+	mf->height		= output_h;
+	mf->field		= V4L2_FIELD_NONE;
+	mf->colorspace		= fmt->colorspace;
+
+	return 0;
+}
+
+static int rj54n1_g_chip_ident(struct v4l2_subdev *sd,
+			       struct v4l2_dbg_chip_ident *id)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
+		return -EINVAL;
+
+	if (id->match.addr != client->addr)
+		return -ENODEV;
+
+	id->ident	= V4L2_IDENT_RJ54N1CB0C;
+	id->revision	= 0;
+
+	return 0;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int rj54n1_g_register(struct v4l2_subdev *sd,
+			     struct v4l2_dbg_register *reg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR ||
+	    reg->reg < 0x400 || reg->reg > 0x1fff)
+		/* Registers > 0x0800 are only available from Sharp support */
+		return -EINVAL;
+
+	if (reg->match.addr != client->addr)
+		return -ENODEV;
+
+	reg->size = 1;
+	reg->val = reg_read(client, reg->reg);
+
+	if (reg->val > 0xff)
+		return -EIO;
+
+	return 0;
+}
+
+static int rj54n1_s_register(struct v4l2_subdev *sd,
+			     struct v4l2_dbg_register *reg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR ||
+	    reg->reg < 0x400 || reg->reg > 0x1fff)
+		/* Registers >= 0x0800 are only available from Sharp support */
+		return -EINVAL;
+
+	if (reg->match.addr != client->addr)
+		return -ENODEV;
+
+	if (reg_write(client, reg->reg, reg->val) < 0)
+		return -EIO;
+
+	return 0;
+}
+#endif
+
+static int rj54n1_s_power(struct v4l2_subdev *sd, int on)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+	return soc_camera_set_power(&client->dev, icl, on);
+}
+
+static int rj54n1_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct rj54n1 *rj54n1 = container_of(ctrl->handler, struct rj54n1, hdl);
+	struct v4l2_subdev *sd = &rj54n1->subdev;
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	int data;
+
+	switch (ctrl->id) {
+	case V4L2_CID_VFLIP:
+		if (ctrl->val)
+			data = reg_set(client, RJ54N1_MIRROR_STILL_MODE, 0, 1);
+		else
+			data = reg_set(client, RJ54N1_MIRROR_STILL_MODE, 1, 1);
+		if (data < 0)
+			return -EIO;
+		return 0;
+	case V4L2_CID_HFLIP:
+		if (ctrl->val)
+			data = reg_set(client, RJ54N1_MIRROR_STILL_MODE, 0, 2);
+		else
+			data = reg_set(client, RJ54N1_MIRROR_STILL_MODE, 2, 2);
+		if (data < 0)
+			return -EIO;
+		return 0;
+	case V4L2_CID_GAIN:
+		if (reg_write(client, RJ54N1_Y_GAIN, ctrl->val * 2) < 0)
+			return -EIO;
+		return 0;
+	case V4L2_CID_AUTO_WHITE_BALANCE:
+		/* Auto WB area - whole image */
+		if (reg_set(client, RJ54N1_WB_SEL_WEIGHT_I, ctrl->val << 7,
+			    0x80) < 0)
+			return -EIO;
+		rj54n1->auto_wb = ctrl->val;
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+static const struct v4l2_ctrl_ops rj54n1_ctrl_ops = {
+	.s_ctrl = rj54n1_s_ctrl,
+};
+
+static struct v4l2_subdev_core_ops rj54n1_subdev_core_ops = {
+	.g_chip_ident	= rj54n1_g_chip_ident,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.g_register	= rj54n1_g_register,
+	.s_register	= rj54n1_s_register,
+#endif
+	.s_power	= rj54n1_s_power,
+};
+
+static int rj54n1_g_mbus_config(struct v4l2_subdev *sd,
+				struct v4l2_mbus_config *cfg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+	cfg->flags =
+		V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_PCLK_SAMPLE_FALLING |
+		V4L2_MBUS_MASTER | V4L2_MBUS_DATA_ACTIVE_HIGH |
+		V4L2_MBUS_HSYNC_ACTIVE_HIGH | V4L2_MBUS_VSYNC_ACTIVE_HIGH;
+	cfg->type = V4L2_MBUS_PARALLEL;
+	cfg->flags = soc_camera_apply_board_flags(icl, cfg);
+
+	return 0;
+}
+
+static int rj54n1_s_mbus_config(struct v4l2_subdev *sd,
+				const struct v4l2_mbus_config *cfg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+	/* Figures 2.5-1 to 2.5-3 - default falling pixclk edge */
+	if (soc_camera_apply_board_flags(icl, cfg) &
+	    V4L2_MBUS_PCLK_SAMPLE_RISING)
+		return reg_write(client, RJ54N1_OUT_SIGPO, 1 << 4);
+	else
+		return reg_write(client, RJ54N1_OUT_SIGPO, 0);
+}
+
+static struct v4l2_subdev_video_ops rj54n1_subdev_video_ops = {
+	.s_stream	= rj54n1_s_stream,
+	.s_mbus_fmt	= rj54n1_s_fmt,
+	.g_mbus_fmt	= rj54n1_g_fmt,
+	.try_mbus_fmt	= rj54n1_try_fmt,
+	.enum_mbus_fmt	= rj54n1_enum_fmt,
+	.g_crop		= rj54n1_g_crop,
+	.s_crop		= rj54n1_s_crop,
+	.cropcap	= rj54n1_cropcap,
+	.g_mbus_config	= rj54n1_g_mbus_config,
+	.s_mbus_config	= rj54n1_s_mbus_config,
+};
+
+static struct v4l2_subdev_ops rj54n1_subdev_ops = {
+	.core	= &rj54n1_subdev_core_ops,
+	.video	= &rj54n1_subdev_video_ops,
+};
+
+/*
+ * Interface active, can use i2c. If it fails, it can indeed mean, that
+ * this wasn't our capture interface, so, we wait for the right one
+ */
+static int rj54n1_video_probe(struct i2c_client *client,
+			      struct rj54n1_pdata *priv)
+{
+	struct rj54n1 *rj54n1 = to_rj54n1(client);
+	int data1, data2;
+	int ret;
+
+	ret = rj54n1_s_power(&rj54n1->subdev, 1);
+	if (ret < 0)
+		return ret;
+
+	/* Read out the chip version register */
+	data1 = reg_read(client, RJ54N1_DEV_CODE);
+	data2 = reg_read(client, RJ54N1_DEV_CODE2);
+
+	if (data1 != 0x51 || data2 != 0x10) {
+		ret = -ENODEV;
+		dev_info(&client->dev, "No RJ54N1CB0C found, read 0x%x:0x%x\n",
+			 data1, data2);
+		goto done;
+	}
+
+	/* Configure IOCTL polarity from the platform data: 0 or 1 << 7. */
+	ret = reg_write(client, RJ54N1_IOC, priv->ioctl_high << 7);
+	if (ret < 0)
+		goto done;
+
+	dev_info(&client->dev, "Detected a RJ54N1CB0C chip ID 0x%x:0x%x\n",
+		 data1, data2);
+
+	ret = v4l2_ctrl_handler_setup(&rj54n1->hdl);
+
+done:
+	rj54n1_s_power(&rj54n1->subdev, 0);
+	return ret;
+}
+
+static int rj54n1_probe(struct i2c_client *client,
+			const struct i2c_device_id *did)
+{
+	struct rj54n1 *rj54n1;
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+	struct rj54n1_pdata *rj54n1_priv;
+	int ret;
+
+	if (!icl || !icl->priv) {
+		dev_err(&client->dev, "RJ54N1CB0C: missing platform data!\n");
+		return -EINVAL;
+	}
+
+	rj54n1_priv = icl->priv;
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
+		dev_warn(&adapter->dev,
+			 "I2C-Adapter doesn't support I2C_FUNC_SMBUS_BYTE\n");
+		return -EIO;
+	}
+
+	rj54n1 = kzalloc(sizeof(struct rj54n1), GFP_KERNEL);
+	if (!rj54n1)
+		return -ENOMEM;
+
+	v4l2_i2c_subdev_init(&rj54n1->subdev, client, &rj54n1_subdev_ops);
+	v4l2_ctrl_handler_init(&rj54n1->hdl, 4);
+	v4l2_ctrl_new_std(&rj54n1->hdl, &rj54n1_ctrl_ops,
+			V4L2_CID_VFLIP, 0, 1, 1, 0);
+	v4l2_ctrl_new_std(&rj54n1->hdl, &rj54n1_ctrl_ops,
+			V4L2_CID_HFLIP, 0, 1, 1, 0);
+	v4l2_ctrl_new_std(&rj54n1->hdl, &rj54n1_ctrl_ops,
+			V4L2_CID_GAIN, 0, 127, 1, 66);
+	v4l2_ctrl_new_std(&rj54n1->hdl, &rj54n1_ctrl_ops,
+			V4L2_CID_AUTO_WHITE_BALANCE, 0, 1, 1, 1);
+	rj54n1->subdev.ctrl_handler = &rj54n1->hdl;
+	if (rj54n1->hdl.error) {
+		int err = rj54n1->hdl.error;
+
+		kfree(rj54n1);
+		return err;
+	}
+
+	rj54n1->clk_div		= clk_div;
+	rj54n1->rect.left	= RJ54N1_COLUMN_SKIP;
+	rj54n1->rect.top	= RJ54N1_ROW_SKIP;
+	rj54n1->rect.width	= RJ54N1_MAX_WIDTH;
+	rj54n1->rect.height	= RJ54N1_MAX_HEIGHT;
+	rj54n1->width		= RJ54N1_MAX_WIDTH;
+	rj54n1->height		= RJ54N1_MAX_HEIGHT;
+	rj54n1->fmt		= &rj54n1_colour_fmts[0];
+	rj54n1->resize		= 1024;
+	rj54n1->tgclk_mhz	= (rj54n1_priv->mclk_freq / PLL_L * PLL_N) /
+		(clk_div.ratio_tg + 1) / (clk_div.ratio_t + 1);
+
+	ret = rj54n1_video_probe(client, rj54n1_priv);
+	if (ret < 0) {
+		v4l2_ctrl_handler_free(&rj54n1->hdl);
+		kfree(rj54n1);
+	}
+
+	return ret;
+}
+
+static int rj54n1_remove(struct i2c_client *client)
+{
+	struct rj54n1 *rj54n1 = to_rj54n1(client);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+	v4l2_device_unregister_subdev(&rj54n1->subdev);
+	if (icl->free_bus)
+		icl->free_bus(icl);
+	v4l2_ctrl_handler_free(&rj54n1->hdl);
+	kfree(rj54n1);
+
+	return 0;
+}
+
+static const struct i2c_device_id rj54n1_id[] = {
+	{ "rj54n1cb0c", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, rj54n1_id);
+
+static struct i2c_driver rj54n1_i2c_driver = {
+	.driver = {
+		.name = "rj54n1cb0c",
+	},
+	.probe		= rj54n1_probe,
+	.remove		= rj54n1_remove,
+	.id_table	= rj54n1_id,
+};
+
+module_i2c_driver(rj54n1_i2c_driver);
+
+MODULE_DESCRIPTION("Sharp RJ54N1CB0C Camera driver");
+MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/i2c/soc_camera/tw9910.c b/drivers/media/i2c/soc_camera/tw9910.c
new file mode 100644
index 0000000..140716e
--- /dev/null
+++ b/drivers/media/i2c/soc_camera/tw9910.c
@@ -0,0 +1,973 @@
+/*
+ * tw9910 Video Driver
+ *
+ * Copyright (C) 2008 Renesas Solutions Corp.
+ * Kuninori Morimoto <morimoto.kuninori@renesas.com>
+ *
+ * Based on ov772x driver,
+ *
+ * Copyright (C) 2008 Kuninori Morimoto <morimoto.kuninori@renesas.com>
+ * Copyright 2006-7 Jonathan Corbet <corbet@lwn.net>
+ * Copyright (C) 2008 Magnus Damm
+ * Copyright (C) 2008, Guennadi Liakhovetski <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 version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/v4l2-mediabus.h>
+#include <linux/videodev2.h>
+
+#include <media/soc_camera.h>
+#include <media/tw9910.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-subdev.h>
+
+#define GET_ID(val)  ((val & 0xF8) >> 3)
+#define GET_REV(val) (val & 0x07)
+
+/*
+ * register offset
+ */
+#define ID		0x00 /* Product ID Code Register */
+#define STATUS1		0x01 /* Chip Status Register I */
+#define INFORM		0x02 /* Input Format */
+#define OPFORM		0x03 /* Output Format Control Register */
+#define DLYCTR		0x04 /* Hysteresis and HSYNC Delay Control */
+#define OUTCTR1		0x05 /* Output Control I */
+#define ACNTL1		0x06 /* Analog Control Register 1 */
+#define CROP_HI		0x07 /* Cropping Register, High */
+#define VDELAY_LO	0x08 /* Vertical Delay Register, Low */
+#define VACTIVE_LO	0x09 /* Vertical Active Register, Low */
+#define HDELAY_LO	0x0A /* Horizontal Delay Register, Low */
+#define HACTIVE_LO	0x0B /* Horizontal Active Register, Low */
+#define CNTRL1		0x0C /* Control Register I */
+#define VSCALE_LO	0x0D /* Vertical Scaling Register, Low */
+#define SCALE_HI	0x0E /* Scaling Register, High */
+#define HSCALE_LO	0x0F /* Horizontal Scaling Register, Low */
+#define BRIGHT		0x10 /* BRIGHTNESS Control Register */
+#define CONTRAST	0x11 /* CONTRAST Control Register */
+#define SHARPNESS	0x12 /* SHARPNESS Control Register I */
+#define SAT_U		0x13 /* Chroma (U) Gain Register */
+#define SAT_V		0x14 /* Chroma (V) Gain Register */
+#define HUE		0x15 /* Hue Control Register */
+#define CORING1		0x17
+#define CORING2		0x18 /* Coring and IF compensation */
+#define VBICNTL		0x19 /* VBI Control Register */
+#define ACNTL2		0x1A /* Analog Control 2 */
+#define OUTCTR2		0x1B /* Output Control 2 */
+#define SDT		0x1C /* Standard Selection */
+#define SDTR		0x1D /* Standard Recognition */
+#define TEST		0x1F /* Test Control Register */
+#define CLMPG		0x20 /* Clamping Gain */
+#define IAGC		0x21 /* Individual AGC Gain */
+#define AGCGAIN		0x22 /* AGC Gain */
+#define PEAKWT		0x23 /* White Peak Threshold */
+#define CLMPL		0x24 /* Clamp level */
+#define SYNCT		0x25 /* Sync Amplitude */
+#define MISSCNT		0x26 /* Sync Miss Count Register */
+#define PCLAMP		0x27 /* Clamp Position Register */
+#define VCNTL1		0x28 /* Vertical Control I */
+#define VCNTL2		0x29 /* Vertical Control II */
+#define CKILL		0x2A /* Color Killer Level Control */
+#define COMB		0x2B /* Comb Filter Control */
+#define LDLY		0x2C /* Luma Delay and H Filter Control */
+#define MISC1		0x2D /* Miscellaneous Control I */
+#define LOOP		0x2E /* LOOP Control Register */
+#define MISC2		0x2F /* Miscellaneous Control II */
+#define MVSN		0x30 /* Macrovision Detection */
+#define STATUS2		0x31 /* Chip STATUS II */
+#define HFREF		0x32 /* H monitor */
+#define CLMD		0x33 /* CLAMP MODE */
+#define IDCNTL		0x34 /* ID Detection Control */
+#define CLCNTL1		0x35 /* Clamp Control I */
+#define ANAPLLCTL	0x4C
+#define VBIMIN		0x4D
+#define HSLOWCTL	0x4E
+#define WSS3		0x4F
+#define FILLDATA	0x50
+#define SDID		0x51
+#define DID		0x52
+#define WSS1		0x53
+#define WSS2		0x54
+#define VVBI		0x55
+#define LCTL6		0x56
+#define LCTL7		0x57
+#define LCTL8		0x58
+#define LCTL9		0x59
+#define LCTL10		0x5A
+#define LCTL11		0x5B
+#define LCTL12		0x5C
+#define LCTL13		0x5D
+#define LCTL14		0x5E
+#define LCTL15		0x5F
+#define LCTL16		0x60
+#define LCTL17		0x61
+#define LCTL18		0x62
+#define LCTL19		0x63
+#define LCTL20		0x64
+#define LCTL21		0x65
+#define LCTL22		0x66
+#define LCTL23		0x67
+#define LCTL24		0x68
+#define LCTL25		0x69
+#define LCTL26		0x6A
+#define HSBEGIN		0x6B
+#define HSEND		0x6C
+#define OVSDLY		0x6D
+#define OVSEND		0x6E
+#define VBIDELAY	0x6F
+
+/*
+ * register detail
+ */
+
+/* INFORM */
+#define FC27_ON     0x40 /* 1 : Input crystal clock frequency is 27MHz */
+#define FC27_FF     0x00 /* 0 : Square pixel mode. */
+			 /*     Must use 24.54MHz for 60Hz field rate */
+			 /*     source or 29.5MHz for 50Hz field rate */
+#define IFSEL_S     0x10 /* 01 : S-video decoding */
+#define IFSEL_C     0x00 /* 00 : Composite video decoding */
+			 /* Y input video selection */
+#define YSEL_M0     0x00 /*  00 : Mux0 selected */
+#define YSEL_M1     0x04 /*  01 : Mux1 selected */
+#define YSEL_M2     0x08 /*  10 : Mux2 selected */
+#define YSEL_M3     0x10 /*  11 : Mux3 selected */
+
+/* OPFORM */
+#define MODE        0x80 /* 0 : CCIR601 compatible YCrCb 4:2:2 format */
+			 /* 1 : ITU-R-656 compatible data sequence format */
+#define LEN         0x40 /* 0 : 8-bit YCrCb 4:2:2 output format */
+			 /* 1 : 16-bit YCrCb 4:2:2 output format.*/
+#define LLCMODE     0x20 /* 1 : LLC output mode. */
+			 /* 0 : free-run output mode */
+#define AINC        0x10 /* Serial interface auto-indexing control */
+			 /* 0 : auto-increment */
+			 /* 1 : non-auto */
+#define VSCTL       0x08 /* 1 : Vertical out ctrl by DVALID */
+			 /* 0 : Vertical out ctrl by HACTIVE and DVALID */
+#define OEN_TRI_SEL_MASK	0x07
+#define OEN_TRI_SEL_ALL_ON	0x00 /* Enable output for Rev0/Rev1 */
+#define OEN_TRI_SEL_ALL_OFF_r0	0x06 /* All tri-stated for Rev0 */
+#define OEN_TRI_SEL_ALL_OFF_r1	0x07 /* All tri-stated for Rev1 */
+
+/* OUTCTR1 */
+#define VSP_LO      0x00 /* 0 : VS pin output polarity is active low */
+#define VSP_HI      0x80 /* 1 : VS pin output polarity is active high. */
+			 /* VS pin output control */
+#define VSSL_VSYNC  0x00 /*   0 : VSYNC  */
+#define VSSL_VACT   0x10 /*   1 : VACT   */
+#define VSSL_FIELD  0x20 /*   2 : FIELD  */
+#define VSSL_VVALID 0x30 /*   3 : VVALID */
+#define VSSL_ZERO   0x70 /*   7 : 0      */
+#define HSP_LOW     0x00 /* 0 : HS pin output polarity is active low */
+#define HSP_HI      0x08 /* 1 : HS pin output polarity is active high.*/
+			 /* HS pin output control */
+#define HSSL_HACT   0x00 /*   0 : HACT   */
+#define HSSL_HSYNC  0x01 /*   1 : HSYNC  */
+#define HSSL_DVALID 0x02 /*   2 : DVALID */
+#define HSSL_HLOCK  0x03 /*   3 : HLOCK  */
+#define HSSL_ASYNCW 0x04 /*   4 : ASYNCW */
+#define HSSL_ZERO   0x07 /*   7 : 0      */
+
+/* ACNTL1 */
+#define SRESET      0x80 /* resets the device to its default state
+			  * but all register content remain unchanged.
+			  * This bit is self-resetting.
+			  */
+#define ACNTL1_PDN_MASK	0x0e
+#define CLK_PDN		0x08 /* system clock power down */
+#define Y_PDN		0x04 /* Luma ADC power down */
+#define C_PDN		0x02 /* Chroma ADC power down */
+
+/* ACNTL2 */
+#define ACNTL2_PDN_MASK	0x40
+#define PLL_PDN		0x40 /* PLL power down */
+
+/* VBICNTL */
+
+/* RTSEL : control the real time signal output from the MPOUT pin */
+#define RTSEL_MASK  0x07
+#define RTSEL_VLOSS 0x00 /* 0000 = Video loss */
+#define RTSEL_HLOCK 0x01 /* 0001 = H-lock */
+#define RTSEL_SLOCK 0x02 /* 0010 = S-lock */
+#define RTSEL_VLOCK 0x03 /* 0011 = V-lock */
+#define RTSEL_MONO  0x04 /* 0100 = MONO */
+#define RTSEL_DET50 0x05 /* 0101 = DET50 */
+#define RTSEL_FIELD 0x06 /* 0110 = FIELD */
+#define RTSEL_RTCO  0x07 /* 0111 = RTCO ( Real Time Control ) */
+
+/* HSYNC start and end are constant for now */
+#define HSYNC_START	0x0260
+#define HSYNC_END	0x0300
+
+/*
+ * structure
+ */
+
+struct regval_list {
+	unsigned char reg_num;
+	unsigned char value;
+};
+
+struct tw9910_scale_ctrl {
+	char           *name;
+	unsigned short  width;
+	unsigned short  height;
+	u16             hscale;
+	u16             vscale;
+};
+
+struct tw9910_priv {
+	struct v4l2_subdev		subdev;
+	struct tw9910_video_info	*info;
+	const struct tw9910_scale_ctrl	*scale;
+	v4l2_std_id			norm;
+	u32				revision;
+};
+
+static const struct tw9910_scale_ctrl tw9910_ntsc_scales[] = {
+	{
+		.name   = "NTSC SQ",
+		.width  = 640,
+		.height = 480,
+		.hscale = 0x0100,
+		.vscale = 0x0100,
+	},
+	{
+		.name   = "NTSC CCIR601",
+		.width  = 720,
+		.height = 480,
+		.hscale = 0x0100,
+		.vscale = 0x0100,
+	},
+	{
+		.name   = "NTSC SQ (CIF)",
+		.width  = 320,
+		.height = 240,
+		.hscale = 0x0200,
+		.vscale = 0x0200,
+	},
+	{
+		.name   = "NTSC CCIR601 (CIF)",
+		.width  = 360,
+		.height = 240,
+		.hscale = 0x0200,
+		.vscale = 0x0200,
+	},
+	{
+		.name   = "NTSC SQ (QCIF)",
+		.width  = 160,
+		.height = 120,
+		.hscale = 0x0400,
+		.vscale = 0x0400,
+	},
+	{
+		.name   = "NTSC CCIR601 (QCIF)",
+		.width  = 180,
+		.height = 120,
+		.hscale = 0x0400,
+		.vscale = 0x0400,
+	},
+};
+
+static const struct tw9910_scale_ctrl tw9910_pal_scales[] = {
+	{
+		.name   = "PAL SQ",
+		.width  = 768,
+		.height = 576,
+		.hscale = 0x0100,
+		.vscale = 0x0100,
+	},
+	{
+		.name   = "PAL CCIR601",
+		.width  = 720,
+		.height = 576,
+		.hscale = 0x0100,
+		.vscale = 0x0100,
+	},
+	{
+		.name   = "PAL SQ (CIF)",
+		.width  = 384,
+		.height = 288,
+		.hscale = 0x0200,
+		.vscale = 0x0200,
+	},
+	{
+		.name   = "PAL CCIR601 (CIF)",
+		.width  = 360,
+		.height = 288,
+		.hscale = 0x0200,
+		.vscale = 0x0200,
+	},
+	{
+		.name   = "PAL SQ (QCIF)",
+		.width  = 192,
+		.height = 144,
+		.hscale = 0x0400,
+		.vscale = 0x0400,
+	},
+	{
+		.name   = "PAL CCIR601 (QCIF)",
+		.width  = 180,
+		.height = 144,
+		.hscale = 0x0400,
+		.vscale = 0x0400,
+	},
+};
+
+/*
+ * general function
+ */
+static struct tw9910_priv *to_tw9910(const struct i2c_client *client)
+{
+	return container_of(i2c_get_clientdata(client), struct tw9910_priv,
+			    subdev);
+}
+
+static int tw9910_mask_set(struct i2c_client *client, u8 command,
+			   u8 mask, u8 set)
+{
+	s32 val = i2c_smbus_read_byte_data(client, command);
+	if (val < 0)
+		return val;
+
+	val &= ~mask;
+	val |= set & mask;
+
+	return i2c_smbus_write_byte_data(client, command, val);
+}
+
+static int tw9910_set_scale(struct i2c_client *client,
+			    const struct tw9910_scale_ctrl *scale)
+{
+	int ret;
+
+	ret = i2c_smbus_write_byte_data(client, SCALE_HI,
+					(scale->vscale & 0x0F00) >> 4 |
+					(scale->hscale & 0x0F00) >> 8);
+	if (ret < 0)
+		return ret;
+
+	ret = i2c_smbus_write_byte_data(client, HSCALE_LO,
+					scale->hscale & 0x00FF);
+	if (ret < 0)
+		return ret;
+
+	ret = i2c_smbus_write_byte_data(client, VSCALE_LO,
+					scale->vscale & 0x00FF);
+
+	return ret;
+}
+
+static int tw9910_set_hsync(struct i2c_client *client)
+{
+	struct tw9910_priv *priv = to_tw9910(client);
+	int ret;
+
+	/* bit 10 - 3 */
+	ret = i2c_smbus_write_byte_data(client, HSBEGIN,
+					(HSYNC_START & 0x07F8) >> 3);
+	if (ret < 0)
+		return ret;
+
+	/* bit 10 - 3 */
+	ret = i2c_smbus_write_byte_data(client, HSEND,
+					(HSYNC_END & 0x07F8) >> 3);
+	if (ret < 0)
+		return ret;
+
+	/* So far only revisions 0 and 1 have been seen */
+	/* bit 2 - 0 */
+	if (1 == priv->revision)
+		ret = tw9910_mask_set(client, HSLOWCTL, 0x77,
+				      (HSYNC_START & 0x0007) << 4 |
+				      (HSYNC_END   & 0x0007));
+
+	return ret;
+}
+
+static void tw9910_reset(struct i2c_client *client)
+{
+	tw9910_mask_set(client, ACNTL1, SRESET, SRESET);
+	msleep(1);
+}
+
+static int tw9910_power(struct i2c_client *client, int enable)
+{
+	int ret;
+	u8 acntl1;
+	u8 acntl2;
+
+	if (enable) {
+		acntl1 = 0;
+		acntl2 = 0;
+	} else {
+		acntl1 = CLK_PDN | Y_PDN | C_PDN;
+		acntl2 = PLL_PDN;
+	}
+
+	ret = tw9910_mask_set(client, ACNTL1, ACNTL1_PDN_MASK, acntl1);
+	if (ret < 0)
+		return ret;
+
+	return tw9910_mask_set(client, ACNTL2, ACNTL2_PDN_MASK, acntl2);
+}
+
+static const struct tw9910_scale_ctrl *tw9910_select_norm(v4l2_std_id norm,
+							  u32 width, u32 height)
+{
+	const struct tw9910_scale_ctrl *scale;
+	const struct tw9910_scale_ctrl *ret = NULL;
+	__u32 diff = 0xffffffff, tmp;
+	int size, i;
+
+	if (norm & V4L2_STD_NTSC) {
+		scale = tw9910_ntsc_scales;
+		size = ARRAY_SIZE(tw9910_ntsc_scales);
+	} else if (norm & V4L2_STD_PAL) {
+		scale = tw9910_pal_scales;
+		size = ARRAY_SIZE(tw9910_pal_scales);
+	} else {
+		return NULL;
+	}
+
+	for (i = 0; i < size; i++) {
+		tmp = abs(width - scale[i].width) +
+			abs(height - scale[i].height);
+		if (tmp < diff) {
+			diff = tmp;
+			ret = scale + i;
+		}
+	}
+
+	return ret;
+}
+
+/*
+ * subdevice operations
+ */
+static int tw9910_s_stream(struct v4l2_subdev *sd, int enable)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct tw9910_priv *priv = to_tw9910(client);
+	u8 val;
+	int ret;
+
+	if (!enable) {
+		switch (priv->revision) {
+		case 0:
+			val = OEN_TRI_SEL_ALL_OFF_r0;
+			break;
+		case 1:
+			val = OEN_TRI_SEL_ALL_OFF_r1;
+			break;
+		default:
+			dev_err(&client->dev, "un-supported revision\n");
+			return -EINVAL;
+		}
+	} else {
+		val = OEN_TRI_SEL_ALL_ON;
+
+		if (!priv->scale) {
+			dev_err(&client->dev, "norm select error\n");
+			return -EPERM;
+		}
+
+		dev_dbg(&client->dev, "%s %dx%d\n",
+			priv->scale->name,
+			priv->scale->width,
+			priv->scale->height);
+	}
+
+	ret = tw9910_mask_set(client, OPFORM, OEN_TRI_SEL_MASK, val);
+	if (ret < 0)
+		return ret;
+
+	return tw9910_power(client, enable);
+}
+
+static int tw9910_g_std(struct v4l2_subdev *sd, v4l2_std_id *norm)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct tw9910_priv *priv = to_tw9910(client);
+
+	*norm = priv->norm;
+
+	return 0;
+}
+
+static int tw9910_s_std(struct v4l2_subdev *sd, v4l2_std_id norm)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct tw9910_priv *priv = to_tw9910(client);
+
+	if (!(norm & (V4L2_STD_NTSC | V4L2_STD_PAL)))
+		return -EINVAL;
+
+	priv->norm = norm;
+
+	return 0;
+}
+
+static int tw9910_g_chip_ident(struct v4l2_subdev *sd,
+			       struct v4l2_dbg_chip_ident *id)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct tw9910_priv *priv = to_tw9910(client);
+
+	id->ident = V4L2_IDENT_TW9910;
+	id->revision = priv->revision;
+
+	return 0;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int tw9910_g_register(struct v4l2_subdev *sd,
+			     struct v4l2_dbg_register *reg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	int ret;
+
+	if (reg->reg > 0xff)
+		return -EINVAL;
+
+	ret = i2c_smbus_read_byte_data(client, reg->reg);
+	if (ret < 0)
+		return ret;
+
+	/*
+	 * ret      = int
+	 * reg->val = __u64
+	 */
+	reg->val = (__u64)ret;
+
+	return 0;
+}
+
+static int tw9910_s_register(struct v4l2_subdev *sd,
+			     struct v4l2_dbg_register *reg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	if (reg->reg > 0xff ||
+	    reg->val > 0xff)
+		return -EINVAL;
+
+	return i2c_smbus_write_byte_data(client, reg->reg, reg->val);
+}
+#endif
+
+static int tw9910_s_power(struct v4l2_subdev *sd, int on)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+	return soc_camera_set_power(&client->dev, icl, on);
+}
+
+static int tw9910_set_frame(struct v4l2_subdev *sd, u32 *width, u32 *height)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct tw9910_priv *priv = to_tw9910(client);
+	int ret = -EINVAL;
+	u8 val;
+
+	/*
+	 * select suitable norm
+	 */
+	priv->scale = tw9910_select_norm(priv->norm, *width, *height);
+	if (!priv->scale)
+		goto tw9910_set_fmt_error;
+
+	/*
+	 * reset hardware
+	 */
+	tw9910_reset(client);
+
+	/*
+	 * set bus width
+	 */
+	val = 0x00;
+	if (SOCAM_DATAWIDTH_16 == priv->info->buswidth)
+		val = LEN;
+
+	ret = tw9910_mask_set(client, OPFORM, LEN, val);
+	if (ret < 0)
+		goto tw9910_set_fmt_error;
+
+	/*
+	 * select MPOUT behavior
+	 */
+	switch (priv->info->mpout) {
+	case TW9910_MPO_VLOSS:
+		val = RTSEL_VLOSS; break;
+	case TW9910_MPO_HLOCK:
+		val = RTSEL_HLOCK; break;
+	case TW9910_MPO_SLOCK:
+		val = RTSEL_SLOCK; break;
+	case TW9910_MPO_VLOCK:
+		val = RTSEL_VLOCK; break;
+	case TW9910_MPO_MONO:
+		val = RTSEL_MONO;  break;
+	case TW9910_MPO_DET50:
+		val = RTSEL_DET50; break;
+	case TW9910_MPO_FIELD:
+		val = RTSEL_FIELD; break;
+	case TW9910_MPO_RTCO:
+		val = RTSEL_RTCO;  break;
+	default:
+		val = 0;
+	}
+
+	ret = tw9910_mask_set(client, VBICNTL, RTSEL_MASK, val);
+	if (ret < 0)
+		goto tw9910_set_fmt_error;
+
+	/*
+	 * set scale
+	 */
+	ret = tw9910_set_scale(client, priv->scale);
+	if (ret < 0)
+		goto tw9910_set_fmt_error;
+
+	/*
+	 * set hsync
+	 */
+	ret = tw9910_set_hsync(client);
+	if (ret < 0)
+		goto tw9910_set_fmt_error;
+
+	*width = priv->scale->width;
+	*height = priv->scale->height;
+
+	return ret;
+
+tw9910_set_fmt_error:
+
+	tw9910_reset(client);
+	priv->scale = NULL;
+
+	return ret;
+}
+
+static int tw9910_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct tw9910_priv *priv = to_tw9910(client);
+
+	a->c.left	= 0;
+	a->c.top	= 0;
+	if (priv->norm & V4L2_STD_NTSC) {
+		a->c.width	= 640;
+		a->c.height	= 480;
+	} else {
+		a->c.width	= 768;
+		a->c.height	= 576;
+	}
+	a->type		= V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+	return 0;
+}
+
+static int tw9910_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct tw9910_priv *priv = to_tw9910(client);
+
+	a->bounds.left			= 0;
+	a->bounds.top			= 0;
+	if (priv->norm & V4L2_STD_NTSC) {
+		a->bounds.width		= 640;
+		a->bounds.height	= 480;
+	} else {
+		a->bounds.width		= 768;
+		a->bounds.height	= 576;
+	}
+	a->defrect			= a->bounds;
+	a->type				= V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	a->pixelaspect.numerator	= 1;
+	a->pixelaspect.denominator	= 1;
+
+	return 0;
+}
+
+static int tw9910_g_fmt(struct v4l2_subdev *sd,
+			struct v4l2_mbus_framefmt *mf)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct tw9910_priv *priv = to_tw9910(client);
+
+	if (!priv->scale) {
+		priv->scale = tw9910_select_norm(priv->norm, 640, 480);
+		if (!priv->scale)
+			return -EINVAL;
+	}
+
+	mf->width	= priv->scale->width;
+	mf->height	= priv->scale->height;
+	mf->code	= V4L2_MBUS_FMT_UYVY8_2X8;
+	mf->colorspace	= V4L2_COLORSPACE_JPEG;
+	mf->field	= V4L2_FIELD_INTERLACED_BT;
+
+	return 0;
+}
+
+static int tw9910_s_fmt(struct v4l2_subdev *sd,
+			struct v4l2_mbus_framefmt *mf)
+{
+	u32 width = mf->width, height = mf->height;
+	int ret;
+
+	WARN_ON(mf->field != V4L2_FIELD_ANY &&
+		mf->field != V4L2_FIELD_INTERLACED_BT);
+
+	/*
+	 * check color format
+	 */
+	if (mf->code != V4L2_MBUS_FMT_UYVY8_2X8)
+		return -EINVAL;
+
+	mf->colorspace = V4L2_COLORSPACE_JPEG;
+
+	ret = tw9910_set_frame(sd, &width, &height);
+	if (!ret) {
+		mf->width	= width;
+		mf->height	= height;
+	}
+	return ret;
+}
+
+static int tw9910_try_fmt(struct v4l2_subdev *sd,
+			  struct v4l2_mbus_framefmt *mf)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct tw9910_priv *priv = to_tw9910(client);
+	const struct tw9910_scale_ctrl *scale;
+
+	if (V4L2_FIELD_ANY == mf->field) {
+		mf->field = V4L2_FIELD_INTERLACED_BT;
+	} else if (V4L2_FIELD_INTERLACED_BT != mf->field) {
+		dev_err(&client->dev, "Field type %d invalid.\n", mf->field);
+		return -EINVAL;
+	}
+
+	mf->code = V4L2_MBUS_FMT_UYVY8_2X8;
+	mf->colorspace = V4L2_COLORSPACE_JPEG;
+
+	/*
+	 * select suitable norm
+	 */
+	scale = tw9910_select_norm(priv->norm, mf->width, mf->height);
+	if (!scale)
+		return -EINVAL;
+
+	mf->width	= scale->width;
+	mf->height	= scale->height;
+
+	return 0;
+}
+
+static int tw9910_video_probe(struct i2c_client *client)
+{
+	struct tw9910_priv *priv = to_tw9910(client);
+	s32 id;
+	int ret;
+
+	/*
+	 * tw9910 only use 8 or 16 bit bus width
+	 */
+	if (SOCAM_DATAWIDTH_16 != priv->info->buswidth &&
+	    SOCAM_DATAWIDTH_8  != priv->info->buswidth) {
+		dev_err(&client->dev, "bus width error\n");
+		return -ENODEV;
+	}
+
+	ret = tw9910_s_power(&priv->subdev, 1);
+	if (ret < 0)
+		return ret;
+
+	/*
+	 * check and show Product ID
+	 * So far only revisions 0 and 1 have been seen
+	 */
+	id = i2c_smbus_read_byte_data(client, ID);
+	priv->revision = GET_REV(id);
+	id = GET_ID(id);
+
+	if (0x0B != id ||
+	    0x01 < priv->revision) {
+		dev_err(&client->dev,
+			"Product ID error %x:%x\n",
+			id, priv->revision);
+		ret = -ENODEV;
+		goto done;
+	}
+
+	dev_info(&client->dev,
+		 "tw9910 Product ID %0x:%0x\n", id, priv->revision);
+
+	priv->norm = V4L2_STD_NTSC;
+
+done:
+	tw9910_s_power(&priv->subdev, 0);
+	return ret;
+}
+
+static struct v4l2_subdev_core_ops tw9910_subdev_core_ops = {
+	.g_chip_ident	= tw9910_g_chip_ident,
+	.s_std		= tw9910_s_std,
+	.g_std		= tw9910_g_std,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.g_register	= tw9910_g_register,
+	.s_register	= tw9910_s_register,
+#endif
+	.s_power	= tw9910_s_power,
+};
+
+static int tw9910_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
+			   enum v4l2_mbus_pixelcode *code)
+{
+	if (index)
+		return -EINVAL;
+
+	*code = V4L2_MBUS_FMT_UYVY8_2X8;
+	return 0;
+}
+
+static int tw9910_g_mbus_config(struct v4l2_subdev *sd,
+				struct v4l2_mbus_config *cfg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+	cfg->flags = V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_MASTER |
+		V4L2_MBUS_VSYNC_ACTIVE_HIGH | V4L2_MBUS_VSYNC_ACTIVE_LOW |
+		V4L2_MBUS_HSYNC_ACTIVE_HIGH | V4L2_MBUS_HSYNC_ACTIVE_LOW |
+		V4L2_MBUS_DATA_ACTIVE_HIGH;
+	cfg->type = V4L2_MBUS_PARALLEL;
+	cfg->flags = soc_camera_apply_board_flags(icl, cfg);
+
+	return 0;
+}
+
+static int tw9910_s_mbus_config(struct v4l2_subdev *sd,
+				const struct v4l2_mbus_config *cfg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+	u8 val = VSSL_VVALID | HSSL_DVALID;
+	unsigned long flags = soc_camera_apply_board_flags(icl, cfg);
+
+	/*
+	 * set OUTCTR1
+	 *
+	 * We use VVALID and DVALID signals to control VSYNC and HSYNC
+	 * outputs, in this mode their polarity is inverted.
+	 */
+	if (flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)
+		val |= HSP_HI;
+
+	if (flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)
+		val |= VSP_HI;
+
+	return i2c_smbus_write_byte_data(client, OUTCTR1, val);
+}
+
+static struct v4l2_subdev_video_ops tw9910_subdev_video_ops = {
+	.s_stream	= tw9910_s_stream,
+	.g_mbus_fmt	= tw9910_g_fmt,
+	.s_mbus_fmt	= tw9910_s_fmt,
+	.try_mbus_fmt	= tw9910_try_fmt,
+	.cropcap	= tw9910_cropcap,
+	.g_crop		= tw9910_g_crop,
+	.enum_mbus_fmt	= tw9910_enum_fmt,
+	.g_mbus_config	= tw9910_g_mbus_config,
+	.s_mbus_config	= tw9910_s_mbus_config,
+};
+
+static struct v4l2_subdev_ops tw9910_subdev_ops = {
+	.core	= &tw9910_subdev_core_ops,
+	.video	= &tw9910_subdev_video_ops,
+};
+
+/*
+ * i2c_driver function
+ */
+
+static int tw9910_probe(struct i2c_client *client,
+			const struct i2c_device_id *did)
+
+{
+	struct tw9910_priv		*priv;
+	struct tw9910_video_info	*info;
+	struct i2c_adapter		*adapter =
+		to_i2c_adapter(client->dev.parent);
+	struct soc_camera_link		*icl = soc_camera_i2c_to_link(client);
+	int				ret;
+
+	if (!icl || !icl->priv) {
+		dev_err(&client->dev, "TW9910: missing platform data!\n");
+		return -EINVAL;
+	}
+
+	info = icl->priv;
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
+		dev_err(&client->dev,
+			"I2C-Adapter doesn't support "
+			"I2C_FUNC_SMBUS_BYTE_DATA\n");
+		return -EIO;
+	}
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->info   = info;
+
+	v4l2_i2c_subdev_init(&priv->subdev, client, &tw9910_subdev_ops);
+
+	ret = tw9910_video_probe(client);
+	if (ret)
+		kfree(priv);
+
+	return ret;
+}
+
+static int tw9910_remove(struct i2c_client *client)
+{
+	struct tw9910_priv *priv = to_tw9910(client);
+
+	kfree(priv);
+	return 0;
+}
+
+static const struct i2c_device_id tw9910_id[] = {
+	{ "tw9910", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, tw9910_id);
+
+static struct i2c_driver tw9910_i2c_driver = {
+	.driver = {
+		.name = "tw9910",
+	},
+	.probe    = tw9910_probe,
+	.remove   = tw9910_remove,
+	.id_table = tw9910_id,
+};
+
+module_i2c_driver(tw9910_i2c_driver);
+
+MODULE_DESCRIPTION("SoC Camera driver for tw9910");
+MODULE_AUTHOR("Kuninori Morimoto");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/i2c/sr030pc30.c b/drivers/media/i2c/sr030pc30.c
new file mode 100644
index 0000000..e9d95bd
--- /dev/null
+++ b/drivers/media/i2c/sr030pc30.c
@@ -0,0 +1,871 @@
+/*
+ * Driver for SiliconFile SR030PC30 VGA (1/10-Inch) Image Sensor with ISP
+ *
+ * Copyright (C) 2010 Samsung Electronics Co., Ltd
+ * Author: Sylwester Nawrocki, s.nawrocki@samsung.com
+ *
+ * Based on original driver authored by Dongsoo Nathaniel Kim
+ * and HeungJun Kim <riverful.kim@samsung.com>.
+ *
+ * Based on mt9v011 Micron Digital Image Sensor driver
+ * Copyright (c) 2009 Mauro Carvalho Chehab (mchehab@redhat.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/i2c.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+#include <media/v4l2-mediabus.h>
+#include <media/sr030pc30.h>
+
+static int debug;
+module_param(debug, int, 0644);
+
+#define MODULE_NAME	"SR030PC30"
+
+/*
+ * Register offsets within a page
+ * b15..b8 - page id, b7..b0 - register address
+ */
+#define POWER_CTRL_REG		0x0001
+#define PAGEMODE_REG		0x03
+#define DEVICE_ID_REG		0x0004
+#define NOON010PC30_ID		0x86
+#define SR030PC30_ID		0x8C
+#define VDO_CTL1_REG		0x0010
+#define SUBSAMPL_NONE_VGA	0
+#define SUBSAMPL_QVGA		0x10
+#define SUBSAMPL_QQVGA		0x20
+#define VDO_CTL2_REG		0x0011
+#define SYNC_CTL_REG		0x0012
+#define WIN_ROWH_REG		0x0020
+#define WIN_ROWL_REG		0x0021
+#define WIN_COLH_REG		0x0022
+#define WIN_COLL_REG		0x0023
+#define WIN_HEIGHTH_REG		0x0024
+#define WIN_HEIGHTL_REG		0x0025
+#define WIN_WIDTHH_REG		0x0026
+#define WIN_WIDTHL_REG		0x0027
+#define HBLANKH_REG		0x0040
+#define HBLANKL_REG		0x0041
+#define VSYNCH_REG		0x0042
+#define VSYNCL_REG		0x0043
+/* page 10 */
+#define ISP_CTL_REG(n)		(0x1010 + (n))
+#define YOFS_REG		0x1040
+#define DARK_YOFS_REG		0x1041
+#define AG_ABRTH_REG		0x1050
+#define SAT_CTL_REG		0x1060
+#define BSAT_REG		0x1061
+#define RSAT_REG		0x1062
+#define AG_SAT_TH_REG		0x1063
+/* page 11 */
+#define ZLPF_CTRL_REG		0x1110
+#define ZLPF_CTRL2_REG		0x1112
+#define ZLPF_AGH_THR_REG	0x1121
+#define ZLPF_THR_REG		0x1160
+#define ZLPF_DYN_THR_REG	0x1160
+/* page 12 */
+#define YCLPF_CTL1_REG		0x1240
+#define YCLPF_CTL2_REG		0x1241
+#define YCLPF_THR_REG		0x1250
+#define BLPF_CTL_REG		0x1270
+#define BLPF_THR1_REG		0x1274
+#define BLPF_THR2_REG		0x1275
+/* page 14 - Lens Shading Compensation */
+#define LENS_CTRL_REG		0x1410
+#define LENS_XCEN_REG		0x1420
+#define LENS_YCEN_REG		0x1421
+#define LENS_R_COMP_REG		0x1422
+#define LENS_G_COMP_REG		0x1423
+#define LENS_B_COMP_REG		0x1424
+/* page 15 - Color correction */
+#define CMC_CTL_REG		0x1510
+#define CMC_OFSGH_REG		0x1514
+#define CMC_OFSGL_REG		0x1516
+#define CMC_SIGN_REG		0x1517
+/* Color correction coefficients */
+#define CMC_COEF_REG(n)		(0x1530 + (n))
+/* Color correction offset coefficients */
+#define CMC_OFS_REG(n)		(0x1540 + (n))
+/* page 16 - Gamma correction */
+#define GMA_CTL_REG		0x1610
+/* Gamma correction coefficients 0.14 */
+#define GMA_COEF_REG(n)		(0x1630 + (n))
+/* page 20 - Auto Exposure */
+#define AE_CTL1_REG		0x2010
+#define AE_CTL2_REG		0x2011
+#define AE_FRM_CTL_REG		0x2020
+#define AE_FINE_CTL_REG(n)	(0x2028 + (n))
+#define EXP_TIMEH_REG		0x2083
+#define EXP_TIMEM_REG		0x2084
+#define EXP_TIMEL_REG		0x2085
+#define EXP_MMINH_REG		0x2086
+#define EXP_MMINL_REG		0x2087
+#define EXP_MMAXH_REG		0x2088
+#define EXP_MMAXM_REG		0x2089
+#define EXP_MMAXL_REG		0x208A
+/* page 22 - Auto White Balance */
+#define AWB_CTL1_REG		0x2210
+#define AWB_ENABLE		0x80
+#define AWB_CTL2_REG		0x2211
+#define MWB_ENABLE		0x01
+/* RGB gain control (manual WB) when AWB_CTL1[7]=0 */
+#define AWB_RGAIN_REG		0x2280
+#define AWB_GGAIN_REG		0x2281
+#define AWB_BGAIN_REG		0x2282
+#define AWB_RMAX_REG		0x2283
+#define AWB_RMIN_REG		0x2284
+#define AWB_BMAX_REG		0x2285
+#define AWB_BMIN_REG		0x2286
+/* R, B gain range in bright light conditions */
+#define AWB_RMAXB_REG		0x2287
+#define AWB_RMINB_REG		0x2288
+#define AWB_BMAXB_REG		0x2289
+#define AWB_BMINB_REG		0x228A
+/* manual white balance, when AWB_CTL2[0]=1 */
+#define MWB_RGAIN_REG		0x22B2
+#define MWB_BGAIN_REG		0x22B3
+/* the token to mark an array end */
+#define REG_TERM		0xFFFF
+
+/* Minimum and maximum exposure time in ms */
+#define EXPOS_MIN_MS		1
+#define EXPOS_MAX_MS		125
+
+struct sr030pc30_info {
+	struct v4l2_subdev sd;
+	const struct sr030pc30_platform_data *pdata;
+	const struct sr030pc30_format *curr_fmt;
+	const struct sr030pc30_frmsize *curr_win;
+	unsigned int auto_wb:1;
+	unsigned int auto_exp:1;
+	unsigned int hflip:1;
+	unsigned int vflip:1;
+	unsigned int sleep:1;
+	unsigned int exposure;
+	u8 blue_balance;
+	u8 red_balance;
+	u8 i2c_reg_page;
+};
+
+struct sr030pc30_format {
+	enum v4l2_mbus_pixelcode code;
+	enum v4l2_colorspace colorspace;
+	u16 ispctl1_reg;
+};
+
+struct sr030pc30_frmsize {
+	u16 width;
+	u16 height;
+	int vid_ctl1;
+};
+
+struct i2c_regval {
+	u16 addr;
+	u16 val;
+};
+
+static const struct v4l2_queryctrl sr030pc30_ctrl[] = {
+	{
+		.id		= V4L2_CID_AUTO_WHITE_BALANCE,
+		.type		= V4L2_CTRL_TYPE_BOOLEAN,
+		.name		= "Auto White Balance",
+		.minimum	= 0,
+		.maximum	= 1,
+		.step		= 1,
+		.default_value	= 1,
+	}, {
+		.id		= V4L2_CID_RED_BALANCE,
+		.type		= V4L2_CTRL_TYPE_INTEGER,
+		.name		= "Red Balance",
+		.minimum	= 0,
+		.maximum	= 127,
+		.step		= 1,
+		.default_value	= 64,
+		.flags		= 0,
+	}, {
+		.id		= V4L2_CID_BLUE_BALANCE,
+		.type		= V4L2_CTRL_TYPE_INTEGER,
+		.name		= "Blue Balance",
+		.minimum	= 0,
+		.maximum	= 127,
+		.step		= 1,
+		.default_value	= 64,
+	}, {
+		.id		= V4L2_CID_EXPOSURE_AUTO,
+		.type		= V4L2_CTRL_TYPE_INTEGER,
+		.name		= "Auto Exposure",
+		.minimum	= 0,
+		.maximum	= 1,
+		.step		= 1,
+		.default_value	= 1,
+	}, {
+		.id		= V4L2_CID_EXPOSURE,
+		.type		= V4L2_CTRL_TYPE_INTEGER,
+		.name		= "Exposure",
+		.minimum	= EXPOS_MIN_MS,
+		.maximum	= EXPOS_MAX_MS,
+		.step		= 1,
+		.default_value	= 1,
+	}, {
+	}
+};
+
+/* supported resolutions */
+static const struct sr030pc30_frmsize sr030pc30_sizes[] = {
+	{
+		.width		= 640,
+		.height		= 480,
+		.vid_ctl1	= SUBSAMPL_NONE_VGA,
+	}, {
+		.width		= 320,
+		.height		= 240,
+		.vid_ctl1	= SUBSAMPL_QVGA,
+	}, {
+		.width		= 160,
+		.height		= 120,
+		.vid_ctl1	= SUBSAMPL_QQVGA,
+	},
+};
+
+/* supported pixel formats */
+static const struct sr030pc30_format sr030pc30_formats[] = {
+	{
+		.code		= V4L2_MBUS_FMT_YUYV8_2X8,
+		.colorspace	= V4L2_COLORSPACE_JPEG,
+		.ispctl1_reg	= 0x03,
+	}, {
+		.code		= V4L2_MBUS_FMT_YVYU8_2X8,
+		.colorspace	= V4L2_COLORSPACE_JPEG,
+		.ispctl1_reg	= 0x02,
+	}, {
+		.code		= V4L2_MBUS_FMT_VYUY8_2X8,
+		.colorspace	= V4L2_COLORSPACE_JPEG,
+		.ispctl1_reg	= 0,
+	}, {
+		.code		= V4L2_MBUS_FMT_UYVY8_2X8,
+		.colorspace	= V4L2_COLORSPACE_JPEG,
+		.ispctl1_reg	= 0x01,
+	}, {
+		.code		= V4L2_MBUS_FMT_RGB565_2X8_BE,
+		.colorspace	= V4L2_COLORSPACE_JPEG,
+		.ispctl1_reg	= 0x40,
+	},
+};
+
+static const struct i2c_regval sr030pc30_base_regs[] = {
+	/* Window size and position within pixel matrix */
+	{ WIN_ROWH_REG,		0x00 }, { WIN_ROWL_REG,		0x06 },
+	{ WIN_COLH_REG,		0x00 },	{ WIN_COLL_REG,		0x06 },
+	{ WIN_HEIGHTH_REG,	0x01 }, { WIN_HEIGHTL_REG,	0xE0 },
+	{ WIN_WIDTHH_REG,	0x02 }, { WIN_WIDTHL_REG,	0x80 },
+	{ HBLANKH_REG,		0x01 }, { HBLANKL_REG,		0x50 },
+	{ VSYNCH_REG,		0x00 }, { VSYNCL_REG,		0x14 },
+	{ SYNC_CTL_REG,		0 },
+	/* Color corection and saturation */
+	{ ISP_CTL_REG(0),	0x30 }, { YOFS_REG,		0x80 },
+	{ DARK_YOFS_REG,	0x04 }, { AG_ABRTH_REG,		0x78 },
+	{ SAT_CTL_REG,		0x1F }, { BSAT_REG,		0x90 },
+	{ AG_SAT_TH_REG,	0xF0 }, { 0x1064,		0x80 },
+	{ CMC_CTL_REG,		0x03 }, { CMC_OFSGH_REG,	0x3C },
+	{ CMC_OFSGL_REG,	0x2C }, { CMC_SIGN_REG,		0x2F },
+	{ CMC_COEF_REG(0),	0xCB }, { CMC_OFS_REG(0),	0x87 },
+	{ CMC_COEF_REG(1),	0x61 }, { CMC_OFS_REG(1),	0x18 },
+	{ CMC_COEF_REG(2),	0x16 }, { CMC_OFS_REG(2),	0x91 },
+	{ CMC_COEF_REG(3),	0x23 }, { CMC_OFS_REG(3),	0x94 },
+	{ CMC_COEF_REG(4),	0xCE }, { CMC_OFS_REG(4),	0x9f },
+	{ CMC_COEF_REG(5),	0x2B }, { CMC_OFS_REG(5),	0x33 },
+	{ CMC_COEF_REG(6),	0x01 }, { CMC_OFS_REG(6),	0x00 },
+	{ CMC_COEF_REG(7),	0x34 }, { CMC_OFS_REG(7),	0x94 },
+	{ CMC_COEF_REG(8),	0x75 }, { CMC_OFS_REG(8),	0x14 },
+	/* Color corection coefficients */
+	{ GMA_CTL_REG,		0x03 },	{ GMA_COEF_REG(0),	0x00 },
+	{ GMA_COEF_REG(1),	0x19 },	{ GMA_COEF_REG(2),	0x26 },
+	{ GMA_COEF_REG(3),	0x3B },	{ GMA_COEF_REG(4),	0x5D },
+	{ GMA_COEF_REG(5),	0x79 }, { GMA_COEF_REG(6),	0x8E },
+	{ GMA_COEF_REG(7),	0x9F },	{ GMA_COEF_REG(8),	0xAF },
+	{ GMA_COEF_REG(9),	0xBD },	{ GMA_COEF_REG(10),	0xCA },
+	{ GMA_COEF_REG(11),	0xDD }, { GMA_COEF_REG(12),	0xEC },
+	{ GMA_COEF_REG(13),	0xF7 },	{ GMA_COEF_REG(14),	0xFF },
+	/* Noise reduction, Z-LPF, YC-LPF and BLPF filters setup */
+	{ ZLPF_CTRL_REG,	0x99 }, { ZLPF_CTRL2_REG,	0x0E },
+	{ ZLPF_AGH_THR_REG,	0x29 }, { ZLPF_THR_REG,		0x0F },
+	{ ZLPF_DYN_THR_REG,	0x63 }, { YCLPF_CTL1_REG,	0x23 },
+	{ YCLPF_CTL2_REG,	0x3B }, { YCLPF_THR_REG,	0x05 },
+	{ BLPF_CTL_REG,		0x1D }, { BLPF_THR1_REG,	0x05 },
+	{ BLPF_THR2_REG,	0x04 },
+	/* Automatic white balance */
+	{ AWB_CTL1_REG,		0xFB }, { AWB_CTL2_REG,		0x26 },
+	{ AWB_RMAX_REG,		0x54 }, { AWB_RMIN_REG,		0x2B },
+	{ AWB_BMAX_REG,		0x57 }, { AWB_BMIN_REG,		0x29 },
+	{ AWB_RMAXB_REG,	0x50 }, { AWB_RMINB_REG,	0x43 },
+	{ AWB_BMAXB_REG,	0x30 }, { AWB_BMINB_REG,	0x22 },
+	/* Auto exposure */
+	{ AE_CTL1_REG,		0x8C }, { AE_CTL2_REG,		0x04 },
+	{ AE_FRM_CTL_REG,	0x01 }, { AE_FINE_CTL_REG(0),	0x3F },
+	{ AE_FINE_CTL_REG(1),	0xA3 }, { AE_FINE_CTL_REG(3),	0x34 },
+	/* Lens shading compensation */
+	{ LENS_CTRL_REG,	0x01 }, { LENS_XCEN_REG,	0x80 },
+	{ LENS_YCEN_REG,	0x70 }, { LENS_R_COMP_REG,	0x53 },
+	{ LENS_G_COMP_REG,	0x40 }, { LENS_B_COMP_REG,	0x3e },
+	{ REG_TERM,		0 },
+};
+
+static inline struct sr030pc30_info *to_sr030pc30(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct sr030pc30_info, sd);
+}
+
+static inline int set_i2c_page(struct sr030pc30_info *info,
+			       struct i2c_client *client, unsigned int reg)
+{
+	int ret = 0;
+	u32 page = reg >> 8 & 0xFF;
+
+	if (info->i2c_reg_page != page && (reg & 0xFF) != 0x03) {
+		ret = i2c_smbus_write_byte_data(client, PAGEMODE_REG, page);
+		if (!ret)
+			info->i2c_reg_page = page;
+	}
+	return ret;
+}
+
+static int cam_i2c_read(struct v4l2_subdev *sd, u32 reg_addr)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct sr030pc30_info *info = to_sr030pc30(sd);
+
+	int ret = set_i2c_page(info, client, reg_addr);
+	if (!ret)
+		ret = i2c_smbus_read_byte_data(client, reg_addr & 0xFF);
+	return ret;
+}
+
+static int cam_i2c_write(struct v4l2_subdev *sd, u32 reg_addr, u32 val)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct sr030pc30_info *info = to_sr030pc30(sd);
+
+	int ret = set_i2c_page(info, client, reg_addr);
+	if (!ret)
+		ret = i2c_smbus_write_byte_data(
+			client, reg_addr & 0xFF, val);
+	return ret;
+}
+
+static inline int sr030pc30_bulk_write_reg(struct v4l2_subdev *sd,
+				const struct i2c_regval *msg)
+{
+	while (msg->addr != REG_TERM) {
+		int ret = cam_i2c_write(sd, msg->addr, msg->val);
+		if (ret)
+			return ret;
+		msg++;
+	}
+	return 0;
+}
+
+/* Device reset and sleep mode control */
+static int sr030pc30_pwr_ctrl(struct v4l2_subdev *sd,
+				     bool reset, bool sleep)
+{
+	struct sr030pc30_info *info = to_sr030pc30(sd);
+	u8 reg = sleep ? 0xF1 : 0xF0;
+	int ret = 0;
+
+	if (reset)
+		ret = cam_i2c_write(sd, POWER_CTRL_REG, reg | 0x02);
+	if (!ret) {
+		ret = cam_i2c_write(sd, POWER_CTRL_REG, reg);
+		if (!ret) {
+			info->sleep = sleep;
+			if (reset)
+				info->i2c_reg_page = -1;
+		}
+	}
+	return ret;
+}
+
+static inline int sr030pc30_enable_autoexposure(struct v4l2_subdev *sd, int on)
+{
+	struct sr030pc30_info *info = to_sr030pc30(sd);
+	/* auto anti-flicker is also enabled here */
+	int ret = cam_i2c_write(sd, AE_CTL1_REG, on ? 0xDC : 0x0C);
+	if (!ret)
+		info->auto_exp = on;
+	return ret;
+}
+
+static int sr030pc30_set_exposure(struct v4l2_subdev *sd, int value)
+{
+	struct sr030pc30_info *info = to_sr030pc30(sd);
+
+	unsigned long expos = value * info->pdata->clk_rate / (8 * 1000);
+
+	int ret = cam_i2c_write(sd, EXP_TIMEH_REG, expos >> 16 & 0xFF);
+	if (!ret)
+		ret = cam_i2c_write(sd, EXP_TIMEM_REG, expos >> 8 & 0xFF);
+	if (!ret)
+		ret = cam_i2c_write(sd, EXP_TIMEL_REG, expos & 0xFF);
+	if (!ret) { /* Turn off AE */
+		info->exposure = value;
+		ret = sr030pc30_enable_autoexposure(sd, 0);
+	}
+	return ret;
+}
+
+/* Automatic white balance control */
+static int sr030pc30_enable_autowhitebalance(struct v4l2_subdev *sd, int on)
+{
+	struct sr030pc30_info *info = to_sr030pc30(sd);
+
+	int ret = cam_i2c_write(sd, AWB_CTL2_REG, on ? 0x2E : 0x2F);
+	if (!ret)
+		ret = cam_i2c_write(sd, AWB_CTL1_REG, on ? 0xFB : 0x7B);
+	if (!ret)
+		info->auto_wb = on;
+
+	return ret;
+}
+
+static int sr030pc30_set_flip(struct v4l2_subdev *sd)
+{
+	struct sr030pc30_info *info = to_sr030pc30(sd);
+
+	s32 reg = cam_i2c_read(sd, VDO_CTL2_REG);
+	if (reg < 0)
+		return reg;
+
+	reg &= 0x7C;
+	if (info->hflip)
+		reg |= 0x01;
+	if (info->vflip)
+		reg |= 0x02;
+	return cam_i2c_write(sd, VDO_CTL2_REG, reg | 0x80);
+}
+
+/* Configure resolution, color format and image flip */
+static int sr030pc30_set_params(struct v4l2_subdev *sd)
+{
+	struct sr030pc30_info *info = to_sr030pc30(sd);
+	int ret;
+
+	if (!info->curr_win)
+		return -EINVAL;
+
+	/* Configure the resolution through subsampling */
+	ret = cam_i2c_write(sd, VDO_CTL1_REG,
+			    info->curr_win->vid_ctl1);
+
+	if (!ret && info->curr_fmt)
+		ret = cam_i2c_write(sd, ISP_CTL_REG(0),
+				info->curr_fmt->ispctl1_reg);
+	if (!ret)
+		ret = sr030pc30_set_flip(sd);
+
+	return ret;
+}
+
+/* Find nearest matching image pixel size. */
+static int sr030pc30_try_frame_size(struct v4l2_mbus_framefmt *mf)
+{
+	unsigned int min_err = ~0;
+	int i = ARRAY_SIZE(sr030pc30_sizes);
+	const struct sr030pc30_frmsize *fsize = &sr030pc30_sizes[0],
+					*match = NULL;
+	while (i--) {
+		int err = abs(fsize->width - mf->width)
+				+ abs(fsize->height - mf->height);
+		if (err < min_err) {
+			min_err = err;
+			match = fsize;
+		}
+		fsize++;
+	}
+	if (match) {
+		mf->width  = match->width;
+		mf->height = match->height;
+		return 0;
+	}
+	return -EINVAL;
+}
+
+static int sr030pc30_queryctrl(struct v4l2_subdev *sd,
+			       struct v4l2_queryctrl *qc)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(sr030pc30_ctrl); i++)
+		if (qc->id == sr030pc30_ctrl[i].id) {
+			*qc = sr030pc30_ctrl[i];
+			v4l2_dbg(1, debug, sd, "%s id: %d\n",
+				 __func__, qc->id);
+			return 0;
+		}
+
+	return -EINVAL;
+}
+
+static inline int sr030pc30_set_bluebalance(struct v4l2_subdev *sd, int value)
+{
+	int ret = cam_i2c_write(sd, MWB_BGAIN_REG, value);
+	if (!ret)
+		to_sr030pc30(sd)->blue_balance = value;
+	return ret;
+}
+
+static inline int sr030pc30_set_redbalance(struct v4l2_subdev *sd, int value)
+{
+	int ret = cam_i2c_write(sd, MWB_RGAIN_REG, value);
+	if (!ret)
+		to_sr030pc30(sd)->red_balance = value;
+	return ret;
+}
+
+static int sr030pc30_s_ctrl(struct v4l2_subdev *sd,
+			    struct v4l2_control *ctrl)
+{
+	int i, ret = 0;
+
+	for (i = 0; i < ARRAY_SIZE(sr030pc30_ctrl); i++)
+		if (ctrl->id == sr030pc30_ctrl[i].id)
+			break;
+
+	if (i == ARRAY_SIZE(sr030pc30_ctrl))
+		return -EINVAL;
+
+	if (ctrl->value < sr030pc30_ctrl[i].minimum ||
+		ctrl->value > sr030pc30_ctrl[i].maximum)
+			return -ERANGE;
+
+	v4l2_dbg(1, debug, sd, "%s: ctrl_id: %d, value: %d\n",
+			 __func__, ctrl->id, ctrl->value);
+
+	switch (ctrl->id) {
+	case V4L2_CID_AUTO_WHITE_BALANCE:
+		sr030pc30_enable_autowhitebalance(sd, ctrl->value);
+		break;
+	case V4L2_CID_BLUE_BALANCE:
+		ret = sr030pc30_set_bluebalance(sd, ctrl->value);
+		break;
+	case V4L2_CID_RED_BALANCE:
+		ret = sr030pc30_set_redbalance(sd, ctrl->value);
+		break;
+	case V4L2_CID_EXPOSURE_AUTO:
+		sr030pc30_enable_autoexposure(sd,
+			ctrl->value == V4L2_EXPOSURE_AUTO);
+		break;
+	case V4L2_CID_EXPOSURE:
+		ret = sr030pc30_set_exposure(sd, ctrl->value);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return ret;
+}
+
+static int sr030pc30_g_ctrl(struct v4l2_subdev *sd,
+			    struct v4l2_control *ctrl)
+{
+	struct sr030pc30_info *info = to_sr030pc30(sd);
+
+	v4l2_dbg(1, debug, sd, "%s: id: %d\n", __func__, ctrl->id);
+
+	switch (ctrl->id) {
+	case V4L2_CID_AUTO_WHITE_BALANCE:
+		ctrl->value = info->auto_wb;
+		break;
+	case V4L2_CID_BLUE_BALANCE:
+		ctrl->value = info->blue_balance;
+		break;
+	case V4L2_CID_RED_BALANCE:
+		ctrl->value = info->red_balance;
+		break;
+	case V4L2_CID_EXPOSURE_AUTO:
+		ctrl->value = info->auto_exp;
+		break;
+	case V4L2_CID_EXPOSURE:
+		ctrl->value = info->exposure;
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int sr030pc30_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
+			      enum v4l2_mbus_pixelcode *code)
+{
+	if (!code || index >= ARRAY_SIZE(sr030pc30_formats))
+		return -EINVAL;
+
+	*code = sr030pc30_formats[index].code;
+	return 0;
+}
+
+static int sr030pc30_g_fmt(struct v4l2_subdev *sd,
+			   struct v4l2_mbus_framefmt *mf)
+{
+	struct sr030pc30_info *info = to_sr030pc30(sd);
+	int ret;
+
+	if (!mf)
+		return -EINVAL;
+
+	if (!info->curr_win || !info->curr_fmt) {
+		ret = sr030pc30_set_params(sd);
+		if (ret)
+			return ret;
+	}
+
+	mf->width	= info->curr_win->width;
+	mf->height	= info->curr_win->height;
+	mf->code	= info->curr_fmt->code;
+	mf->colorspace	= info->curr_fmt->colorspace;
+	mf->field	= V4L2_FIELD_NONE;
+
+	return 0;
+}
+
+/* Return nearest media bus frame format. */
+static const struct sr030pc30_format *try_fmt(struct v4l2_subdev *sd,
+					      struct v4l2_mbus_framefmt *mf)
+{
+	int i = ARRAY_SIZE(sr030pc30_formats);
+
+	sr030pc30_try_frame_size(mf);
+
+	while (i--)
+		if (mf->code == sr030pc30_formats[i].code)
+			break;
+
+	mf->code = sr030pc30_formats[i].code;
+
+	return &sr030pc30_formats[i];
+}
+
+/* Return nearest media bus frame format. */
+static int sr030pc30_try_fmt(struct v4l2_subdev *sd,
+			     struct v4l2_mbus_framefmt *mf)
+{
+	if (!sd || !mf)
+		return -EINVAL;
+
+	try_fmt(sd, mf);
+	return 0;
+}
+
+static int sr030pc30_s_fmt(struct v4l2_subdev *sd,
+			   struct v4l2_mbus_framefmt *mf)
+{
+	struct sr030pc30_info *info = to_sr030pc30(sd);
+
+	if (!sd || !mf)
+		return -EINVAL;
+
+	info->curr_fmt = try_fmt(sd, mf);
+
+	return sr030pc30_set_params(sd);
+}
+
+static int sr030pc30_base_config(struct v4l2_subdev *sd)
+{
+	struct sr030pc30_info *info = to_sr030pc30(sd);
+	int ret;
+	unsigned long expmin, expmax;
+
+	ret = sr030pc30_bulk_write_reg(sd, sr030pc30_base_regs);
+	if (!ret) {
+		info->curr_fmt = &sr030pc30_formats[0];
+		info->curr_win = &sr030pc30_sizes[0];
+		ret = sr030pc30_set_params(sd);
+	}
+	if (!ret)
+		ret = sr030pc30_pwr_ctrl(sd, false, false);
+
+	if (!ret && !info->pdata)
+		return ret;
+
+	expmin = EXPOS_MIN_MS * info->pdata->clk_rate / (8 * 1000);
+	expmax = EXPOS_MAX_MS * info->pdata->clk_rate / (8 * 1000);
+
+	v4l2_dbg(1, debug, sd, "%s: expmin= %lx, expmax= %lx", __func__,
+		 expmin, expmax);
+
+	/* Setting up manual exposure time range */
+	ret = cam_i2c_write(sd, EXP_MMINH_REG, expmin >> 8 & 0xFF);
+	if (!ret)
+		ret = cam_i2c_write(sd, EXP_MMINL_REG, expmin & 0xFF);
+	if (!ret)
+		ret = cam_i2c_write(sd, EXP_MMAXH_REG, expmax >> 16 & 0xFF);
+	if (!ret)
+		ret = cam_i2c_write(sd, EXP_MMAXM_REG, expmax >> 8 & 0xFF);
+	if (!ret)
+		ret = cam_i2c_write(sd, EXP_MMAXL_REG, expmax & 0xFF);
+
+	return ret;
+}
+
+static int sr030pc30_s_power(struct v4l2_subdev *sd, int on)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct sr030pc30_info *info = to_sr030pc30(sd);
+	const struct sr030pc30_platform_data *pdata = info->pdata;
+	int ret;
+
+	if (pdata == NULL) {
+		WARN(1, "No platform data!\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * Put sensor into power sleep mode before switching off
+	 * power and disabling MCLK.
+	 */
+	if (!on)
+		sr030pc30_pwr_ctrl(sd, false, true);
+
+	/* set_power controls sensor's power and clock */
+	if (pdata->set_power) {
+		ret = pdata->set_power(&client->dev, on);
+		if (ret)
+			return ret;
+	}
+
+	if (on) {
+		ret = sr030pc30_base_config(sd);
+	} else {
+		ret = 0;
+		info->curr_win = NULL;
+		info->curr_fmt = NULL;
+	}
+
+	return ret;
+}
+
+static const struct v4l2_subdev_core_ops sr030pc30_core_ops = {
+	.s_power	= sr030pc30_s_power,
+	.queryctrl	= sr030pc30_queryctrl,
+	.s_ctrl		= sr030pc30_s_ctrl,
+	.g_ctrl		= sr030pc30_g_ctrl,
+};
+
+static const struct v4l2_subdev_video_ops sr030pc30_video_ops = {
+	.g_mbus_fmt	= sr030pc30_g_fmt,
+	.s_mbus_fmt	= sr030pc30_s_fmt,
+	.try_mbus_fmt	= sr030pc30_try_fmt,
+	.enum_mbus_fmt	= sr030pc30_enum_fmt,
+};
+
+static const struct v4l2_subdev_ops sr030pc30_ops = {
+	.core	= &sr030pc30_core_ops,
+	.video	= &sr030pc30_video_ops,
+};
+
+/*
+ * Detect sensor type. Return 0 if SR030PC30 was detected
+ * or -ENODEV otherwise.
+ */
+static int sr030pc30_detect(struct i2c_client *client)
+{
+	const struct sr030pc30_platform_data *pdata
+		= client->dev.platform_data;
+	int ret;
+
+	/* Enable sensor's power and clock */
+	if (pdata->set_power) {
+		ret = pdata->set_power(&client->dev, 1);
+		if (ret)
+			return ret;
+	}
+
+	ret = i2c_smbus_read_byte_data(client, DEVICE_ID_REG);
+
+	if (pdata->set_power)
+		pdata->set_power(&client->dev, 0);
+
+	if (ret < 0) {
+		dev_err(&client->dev, "%s: I2C read failed\n", __func__);
+		return ret;
+	}
+
+	return ret == SR030PC30_ID ? 0 : -ENODEV;
+}
+
+
+static int sr030pc30_probe(struct i2c_client *client,
+			   const struct i2c_device_id *id)
+{
+	struct sr030pc30_info *info;
+	struct v4l2_subdev *sd;
+	const struct sr030pc30_platform_data *pdata
+		= client->dev.platform_data;
+	int ret;
+
+	if (!pdata) {
+		dev_err(&client->dev, "No platform data!");
+		return -EIO;
+	}
+
+	ret = sr030pc30_detect(client);
+	if (ret)
+		return ret;
+
+	info = kzalloc(sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	sd = &info->sd;
+	strcpy(sd->name, MODULE_NAME);
+	info->pdata = client->dev.platform_data;
+
+	v4l2_i2c_subdev_init(sd, client, &sr030pc30_ops);
+
+	info->i2c_reg_page	= -1;
+	info->hflip		= 1;
+	info->auto_exp		= 1;
+	info->exposure		= 30;
+
+	return 0;
+}
+
+static int sr030pc30_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct sr030pc30_info *info = to_sr030pc30(sd);
+
+	v4l2_device_unregister_subdev(sd);
+	kfree(info);
+	return 0;
+}
+
+static const struct i2c_device_id sr030pc30_id[] = {
+	{ MODULE_NAME, 0 },
+	{ },
+};
+MODULE_DEVICE_TABLE(i2c, sr030pc30_id);
+
+
+static struct i2c_driver sr030pc30_i2c_driver = {
+	.driver = {
+		.name = MODULE_NAME
+	},
+	.probe		= sr030pc30_probe,
+	.remove		= sr030pc30_remove,
+	.id_table	= sr030pc30_id,
+};
+
+module_i2c_driver(sr030pc30_i2c_driver);
+
+MODULE_DESCRIPTION("Siliconfile SR030PC30 camera driver");
+MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/i2c/tcm825x.c b/drivers/media/i2c/tcm825x.c
new file mode 100644
index 0000000..9252529
--- /dev/null
+++ b/drivers/media/i2c/tcm825x.c
@@ -0,0 +1,937 @@
+/*
+ * drivers/media/i2c/tcm825x.c
+ *
+ * TCM825X camera sensor driver.
+ *
+ * Copyright (C) 2007 Nokia Corporation.
+ *
+ * Contact: Sakari Ailus <sakari.ailus@nokia.com>
+ *
+ * Based on code from David Cohen <david.cohen@indt.org.br>
+ *
+ * This driver was based on ov9640 sensor driver from MontaVista
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <media/v4l2-int-device.h>
+
+#include "tcm825x.h"
+
+/*
+ * The sensor has two fps modes: the lower one just gives half the fps
+ * at the same xclk than the high one.
+ */
+#define MAX_FPS 30
+#define MIN_FPS 8
+#define MAX_HALF_FPS (MAX_FPS / 2)
+#define HIGH_FPS_MODE_LOWER_LIMIT 14
+#define DEFAULT_FPS MAX_HALF_FPS
+
+struct tcm825x_sensor {
+	const struct tcm825x_platform_data *platform_data;
+	struct v4l2_int_device *v4l2_int_device;
+	struct i2c_client *i2c_client;
+	struct v4l2_pix_format pix;
+	struct v4l2_fract timeperframe;
+};
+
+/* list of image formats supported by TCM825X sensor */
+static const struct v4l2_fmtdesc tcm825x_formats[] = {
+	{
+		.description = "YUYV (YUV 4:2:2), packed",
+		.pixelformat = V4L2_PIX_FMT_UYVY,
+	}, {
+		/* Note:  V4L2 defines RGB565 as:
+		 *
+		 *      Byte 0                    Byte 1
+		 *      g2 g1 g0 r4 r3 r2 r1 r0   b4 b3 b2 b1 b0 g5 g4 g3
+		 *
+		 * We interpret RGB565 as:
+		 *
+		 *      Byte 0                    Byte 1
+		 *      g2 g1 g0 b4 b3 b2 b1 b0   r4 r3 r2 r1 r0 g5 g4 g3
+		 */
+		.description = "RGB565, le",
+		.pixelformat = V4L2_PIX_FMT_RGB565,
+	},
+};
+
+#define TCM825X_NUM_CAPTURE_FORMATS	ARRAY_SIZE(tcm825x_formats)
+
+/*
+ * TCM825X register configuration for all combinations of pixel format and
+ * image size
+ */
+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 };
+
+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
+#define V4L2_CID_H_EDGE_EN			V4L2_CID_PRIVATE_BASE + 1
+#define V4L2_CID_V_EDGE_EN			V4L2_CID_PRIVATE_BASE + 2
+#define V4L2_CID_LENS				V4L2_CID_PRIVATE_BASE + 3
+#define V4L2_CID_MAX_EXPOSURE_TIME		V4L2_CID_PRIVATE_BASE + 4
+#define V4L2_CID_LAST_PRIV			V4L2_CID_MAX_EXPOSURE_TIME
+
+/*  Video controls  */
+static struct vcontrol {
+	struct v4l2_queryctrl qc;
+	u16 reg;
+	u16 start_bit;
+} video_control[] = {
+	{
+		{
+			.id = V4L2_CID_GAIN,
+			.type = V4L2_CTRL_TYPE_INTEGER,
+			.name = "Gain",
+			.minimum = 0,
+			.maximum = 63,
+			.step = 1,
+		},
+		.reg = TCM825X_AG,
+		.start_bit = 0,
+	},
+	{
+		{
+			.id = V4L2_CID_RED_BALANCE,
+			.type = V4L2_CTRL_TYPE_INTEGER,
+			.name = "Red Balance",
+			.minimum = 0,
+			.maximum = 255,
+			.step = 1,
+		},
+		.reg = TCM825X_MRG,
+		.start_bit = 0,
+	},
+	{
+		{
+			.id = V4L2_CID_BLUE_BALANCE,
+			.type = V4L2_CTRL_TYPE_INTEGER,
+			.name = "Blue Balance",
+			.minimum = 0,
+			.maximum = 255,
+			.step = 1,
+		},
+		.reg = TCM825X_MBG,
+		.start_bit = 0,
+	},
+	{
+		{
+			.id = V4L2_CID_AUTO_WHITE_BALANCE,
+			.type = V4L2_CTRL_TYPE_BOOLEAN,
+			.name = "Auto White Balance",
+			.minimum = 0,
+			.maximum = 1,
+			.step = 0,
+		},
+		.reg = TCM825X_AWBSW,
+		.start_bit = 7,
+	},
+	{
+		{
+			.id = V4L2_CID_EXPOSURE,
+			.type = V4L2_CTRL_TYPE_INTEGER,
+			.name = "Exposure Time",
+			.minimum = 0,
+			.maximum = 0x1fff,
+			.step = 1,
+		},
+		.reg = TCM825X_ESRSPD_U,
+		.start_bit = 0,
+	},
+	{
+		{
+			.id = V4L2_CID_HFLIP,
+			.type = V4L2_CTRL_TYPE_BOOLEAN,
+			.name = "Mirror Image",
+			.minimum = 0,
+			.maximum = 1,
+			.step = 0,
+		},
+		.reg = TCM825X_H_INV,
+		.start_bit = 6,
+	},
+	{
+		{
+			.id = V4L2_CID_VFLIP,
+			.type = V4L2_CTRL_TYPE_BOOLEAN,
+			.name = "Vertical Flip",
+			.minimum = 0,
+			.maximum = 1,
+			.step = 0,
+		},
+		.reg = TCM825X_V_INV,
+		.start_bit = 7,
+	},
+	/* Private controls */
+	{
+		{
+			.id = V4L2_CID_ALC,
+			.type = V4L2_CTRL_TYPE_BOOLEAN,
+			.name = "Auto Luminance Control",
+			.minimum = 0,
+			.maximum = 1,
+			.step = 0,
+		},
+		.reg = TCM825X_ALCSW,
+		.start_bit = 7,
+	},
+	{
+		{
+			.id = V4L2_CID_H_EDGE_EN,
+			.type = V4L2_CTRL_TYPE_INTEGER,
+			.name = "Horizontal Edge Enhancement",
+			.minimum = 0,
+			.maximum = 0xff,
+			.step = 1,
+		},
+		.reg = TCM825X_HDTG,
+		.start_bit = 0,
+	},
+	{
+		{
+			.id = V4L2_CID_V_EDGE_EN,
+			.type = V4L2_CTRL_TYPE_INTEGER,
+			.name = "Vertical Edge Enhancement",
+			.minimum = 0,
+			.maximum = 0xff,
+			.step = 1,
+		},
+		.reg = TCM825X_VDTG,
+		.start_bit = 0,
+	},
+	{
+		{
+			.id = V4L2_CID_LENS,
+			.type = V4L2_CTRL_TYPE_INTEGER,
+			.name = "Lens Shading Compensation",
+			.minimum = 0,
+			.maximum = 0x3f,
+			.step = 1,
+		},
+		.reg = TCM825X_LENS,
+		.start_bit = 0,
+	},
+	{
+		{
+			.id = V4L2_CID_MAX_EXPOSURE_TIME,
+			.type = V4L2_CTRL_TYPE_INTEGER,
+			.name = "Maximum Exposure Time",
+			.minimum = 0,
+			.maximum = 0x3,
+			.step = 1,
+		},
+		.reg = TCM825X_ESRLIM,
+		.start_bit = 5,
+	},
+};
+
+
+static const struct tcm825x_reg *tcm825x_siz_reg[NUM_IMAGE_SIZES] =
+{ &subqcif, &qqvga, &qcif, &qvga, &cif, &vga };
+
+static const struct tcm825x_reg *tcm825x_fmt_reg[NUM_PIXEL_FORMATS] =
+{ &yuv422, &rgb565 };
+
+/*
+ * Read a value from a register in an TCM825X sensor device.  The value is
+ * returned in 'val'.
+ * Returns zero if successful, or non-zero otherwise.
+ */
+static int tcm825x_read_reg(struct i2c_client *client, int reg)
+{
+	int err;
+	struct i2c_msg msg[2];
+	u8 reg_buf, data_buf = 0;
+
+	if (!client->adapter)
+		return -ENODEV;
+
+	msg[0].addr = client->addr;
+	msg[0].flags = 0;
+	msg[0].len = 1;
+	msg[0].buf = &reg_buf;
+	msg[1].addr = client->addr;
+	msg[1].flags = I2C_M_RD;
+	msg[1].len = 1;
+	msg[1].buf = &data_buf;
+
+	reg_buf = reg;
+
+	err = i2c_transfer(client->adapter, msg, 2);
+	if (err < 0)
+		return err;
+	return data_buf;
+}
+
+/*
+ * Write a value to a register in an TCM825X sensor device.
+ * Returns zero if successful, or non-zero otherwise.
+ */
+static int tcm825x_write_reg(struct i2c_client *client, u8 reg, u8 val)
+{
+	int err;
+	struct i2c_msg msg[1];
+	unsigned char data[2];
+
+	if (!client->adapter)
+		return -ENODEV;
+
+	msg->addr = client->addr;
+	msg->flags = 0;
+	msg->len = 2;
+	msg->buf = data;
+	data[0] = reg;
+	data[1] = val;
+	err = i2c_transfer(client->adapter, msg, 1);
+	if (err >= 0)
+		return 0;
+	return err;
+}
+
+static int __tcm825x_write_reg_mask(struct i2c_client *client,
+				    u8 reg, u8 val, u8 mask)
+{
+	int rc;
+
+	/* need to do read - modify - write */
+	rc = tcm825x_read_reg(client, reg);
+	if (rc < 0)
+		return rc;
+
+	rc &= (~mask);	/* Clear the masked bits */
+	val &= mask;	/* Enforce mask on value */
+	val |= rc;
+
+	/* write the new value to the register */
+	rc = tcm825x_write_reg(client, reg, val);
+	if (rc)
+		return rc;
+
+	return 0;
+}
+
+#define tcm825x_write_reg_mask(client, regmask, val)			\
+	__tcm825x_write_reg_mask(client, TCM825X_ADDR((regmask)), val,	\
+				 TCM825X_MASK((regmask)))
+
+
+/*
+ * Initialize a list of TCM825X registers.
+ * The list of registers is terminated by the pair of values
+ * { TCM825X_REG_TERM, TCM825X_VAL_TERM }.
+ * Returns zero if successful, or non-zero otherwise.
+ */
+static int tcm825x_write_default_regs(struct i2c_client *client,
+				      const struct tcm825x_reg *reglist)
+{
+	int err;
+	const struct tcm825x_reg *next = reglist;
+
+	while (!((next->reg == TCM825X_REG_TERM)
+		 && (next->val == TCM825X_VAL_TERM))) {
+		err = tcm825x_write_reg(client, next->reg, next->val);
+		if (err) {
+			dev_err(&client->dev, "register writing failed\n");
+			return err;
+		}
+		next++;
+	}
+
+	return 0;
+}
+
+static struct vcontrol *find_vctrl(int id)
+{
+	int i;
+
+	if (id < V4L2_CID_BASE)
+		return NULL;
+
+	for (i = 0; i < ARRAY_SIZE(video_control); i++)
+		if (video_control[i].qc.id == id)
+			return &video_control[i];
+
+	return NULL;
+}
+
+/*
+ * Find the best match for a requested image capture size.  The best match
+ * is chosen as the nearest match that has the same number or fewer pixels
+ * as the requested size, or the smallest image size if the requested size
+ * has fewer pixels than the smallest image.
+ */
+static enum image_size tcm825x_find_size(struct v4l2_int_device *s,
+					 unsigned int width,
+					 unsigned int height)
+{
+	enum image_size isize;
+	unsigned long pixels = width * height;
+	struct tcm825x_sensor *sensor = s->priv;
+
+	for (isize = subQCIF; isize < VGA; isize++) {
+		if (tcm825x_sizes[isize + 1].height
+		    * tcm825x_sizes[isize + 1].width > pixels) {
+			dev_dbg(&sensor->i2c_client->dev, "size %d\n", isize);
+
+			return isize;
+		}
+	}
+
+	dev_dbg(&sensor->i2c_client->dev, "format default VGA\n");
+
+	return VGA;
+}
+
+/*
+ * Configure the TCM825X for current image size, pixel format, and
+ * frame period. fper is the frame period (in seconds) expressed as a
+ * fraction. Returns zero if successful, or non-zero otherwise. The
+ * actual frame period is returned in fper.
+ */
+static int tcm825x_configure(struct v4l2_int_device *s)
+{
+	struct tcm825x_sensor *sensor = s->priv;
+	struct v4l2_pix_format *pix = &sensor->pix;
+	enum image_size isize = tcm825x_find_size(s, pix->width, pix->height);
+	struct v4l2_fract *fper = &sensor->timeperframe;
+	enum pixel_format pfmt;
+	int err;
+	u32 tgt_fps;
+	u8 val;
+
+	/* common register initialization */
+	err = tcm825x_write_default_regs(
+		sensor->i2c_client, sensor->platform_data->default_regs());
+	if (err)
+		return err;
+
+	/* configure image size */
+	val = tcm825x_siz_reg[isize]->val;
+	dev_dbg(&sensor->i2c_client->dev,
+		"configuring image size %d\n", isize);
+	err = tcm825x_write_reg_mask(sensor->i2c_client,
+				     tcm825x_siz_reg[isize]->reg, val);
+	if (err)
+		return err;
+
+	/* configure pixel format */
+	switch (pix->pixelformat) {
+	default:
+	case V4L2_PIX_FMT_RGB565:
+		pfmt = RGB565;
+		break;
+	case V4L2_PIX_FMT_UYVY:
+		pfmt = YUV422;
+		break;
+	}
+
+	dev_dbg(&sensor->i2c_client->dev,
+		"configuring pixel format %d\n", pfmt);
+	val = tcm825x_fmt_reg[pfmt]->val;
+
+	err = tcm825x_write_reg_mask(sensor->i2c_client,
+				     tcm825x_fmt_reg[pfmt]->reg, val);
+	if (err)
+		return err;
+
+	/*
+	 * For frame rate < 15, the FPS reg (addr 0x02, bit 7) must be
+	 * set. Frame rate will be halved from the normal.
+	 */
+	tgt_fps = fper->denominator / fper->numerator;
+	if (tgt_fps <= HIGH_FPS_MODE_LOWER_LIMIT) {
+		val = tcm825x_read_reg(sensor->i2c_client, 0x02);
+		val |= 0x80;
+		tcm825x_write_reg(sensor->i2c_client, 0x02, val);
+	}
+
+	return 0;
+}
+
+static int ioctl_queryctrl(struct v4l2_int_device *s,
+				struct v4l2_queryctrl *qc)
+{
+	struct vcontrol *control;
+
+	control = find_vctrl(qc->id);
+
+	if (control == NULL)
+		return -EINVAL;
+
+	*qc = control->qc;
+
+	return 0;
+}
+
+static int ioctl_g_ctrl(struct v4l2_int_device *s,
+			     struct v4l2_control *vc)
+{
+	struct tcm825x_sensor *sensor = s->priv;
+	struct i2c_client *client = sensor->i2c_client;
+	int val, r;
+	struct vcontrol *lvc;
+
+	/* exposure time is special, spread across 2 registers */
+	if (vc->id == V4L2_CID_EXPOSURE) {
+		int val_lower, val_upper;
+
+		val_upper = tcm825x_read_reg(client,
+					     TCM825X_ADDR(TCM825X_ESRSPD_U));
+		if (val_upper < 0)
+			return val_upper;
+		val_lower = tcm825x_read_reg(client,
+					     TCM825X_ADDR(TCM825X_ESRSPD_L));
+		if (val_lower < 0)
+			return val_lower;
+
+		vc->value = ((val_upper & 0x1f) << 8) | (val_lower);
+		return 0;
+	}
+
+	lvc = find_vctrl(vc->id);
+	if (lvc == NULL)
+		return -EINVAL;
+
+	r = tcm825x_read_reg(client, TCM825X_ADDR(lvc->reg));
+	if (r < 0)
+		return r;
+	val = r & TCM825X_MASK(lvc->reg);
+	val >>= lvc->start_bit;
+
+	if (val < 0)
+		return val;
+
+	if (vc->id == V4L2_CID_HFLIP || vc->id == V4L2_CID_VFLIP)
+		val ^= sensor->platform_data->is_upside_down();
+
+	vc->value = val;
+	return 0;
+}
+
+static int ioctl_s_ctrl(struct v4l2_int_device *s,
+			     struct v4l2_control *vc)
+{
+	struct tcm825x_sensor *sensor = s->priv;
+	struct i2c_client *client = sensor->i2c_client;
+	struct vcontrol *lvc;
+	int val = vc->value;
+
+	/* exposure time is special, spread across 2 registers */
+	if (vc->id == V4L2_CID_EXPOSURE) {
+		int val_lower, val_upper;
+		val_lower = val & TCM825X_MASK(TCM825X_ESRSPD_L);
+		val_upper = (val >> 8) & TCM825X_MASK(TCM825X_ESRSPD_U);
+
+		if (tcm825x_write_reg_mask(client,
+					   TCM825X_ESRSPD_U, val_upper))
+			return -EIO;
+
+		if (tcm825x_write_reg_mask(client,
+					   TCM825X_ESRSPD_L, val_lower))
+			return -EIO;
+
+		return 0;
+	}
+
+	lvc = find_vctrl(vc->id);
+	if (lvc == NULL)
+		return -EINVAL;
+
+	if (vc->id == V4L2_CID_HFLIP || vc->id == V4L2_CID_VFLIP)
+		val ^= sensor->platform_data->is_upside_down();
+
+	val = val << lvc->start_bit;
+	if (tcm825x_write_reg_mask(client, lvc->reg, val))
+		return -EIO;
+
+	return 0;
+}
+
+static int ioctl_enum_fmt_cap(struct v4l2_int_device *s,
+				   struct v4l2_fmtdesc *fmt)
+{
+	int index = fmt->index;
+
+	switch (fmt->type) {
+	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+		if (index >= TCM825X_NUM_CAPTURE_FORMATS)
+			return -EINVAL;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	fmt->flags = tcm825x_formats[index].flags;
+	strlcpy(fmt->description, tcm825x_formats[index].description,
+		sizeof(fmt->description));
+	fmt->pixelformat = tcm825x_formats[index].pixelformat;
+
+	return 0;
+}
+
+static int ioctl_try_fmt_cap(struct v4l2_int_device *s,
+			     struct v4l2_format *f)
+{
+	struct tcm825x_sensor *sensor = s->priv;
+	enum image_size isize;
+	int ifmt;
+	struct v4l2_pix_format *pix = &f->fmt.pix;
+
+	isize = tcm825x_find_size(s, pix->width, pix->height);
+	dev_dbg(&sensor->i2c_client->dev, "isize = %d num_capture = %lu\n",
+		isize, (unsigned long)TCM825X_NUM_CAPTURE_FORMATS);
+
+	pix->width = tcm825x_sizes[isize].width;
+	pix->height = tcm825x_sizes[isize].height;
+
+	for (ifmt = 0; ifmt < TCM825X_NUM_CAPTURE_FORMATS; ifmt++)
+		if (pix->pixelformat == tcm825x_formats[ifmt].pixelformat)
+			break;
+
+	if (ifmt == TCM825X_NUM_CAPTURE_FORMATS)
+		ifmt = 0;	/* Default = YUV 4:2:2 */
+
+	pix->pixelformat = tcm825x_formats[ifmt].pixelformat;
+	pix->field = V4L2_FIELD_NONE;
+	pix->bytesperline = pix->width * TCM825X_BYTES_PER_PIXEL;
+	pix->sizeimage = pix->bytesperline * pix->height;
+	pix->priv = 0;
+	dev_dbg(&sensor->i2c_client->dev, "format = 0x%08x\n",
+		pix->pixelformat);
+
+	switch (pix->pixelformat) {
+	case V4L2_PIX_FMT_UYVY:
+	default:
+		pix->colorspace = V4L2_COLORSPACE_JPEG;
+		break;
+	case V4L2_PIX_FMT_RGB565:
+		pix->colorspace = V4L2_COLORSPACE_SRGB;
+		break;
+	}
+
+	return 0;
+}
+
+static int ioctl_s_fmt_cap(struct v4l2_int_device *s,
+				struct v4l2_format *f)
+{
+	struct tcm825x_sensor *sensor = s->priv;
+	struct v4l2_pix_format *pix = &f->fmt.pix;
+	int rval;
+
+	rval = ioctl_try_fmt_cap(s, f);
+	if (rval)
+		return rval;
+
+	rval = tcm825x_configure(s);
+
+	sensor->pix = *pix;
+
+	return rval;
+}
+
+static int ioctl_g_fmt_cap(struct v4l2_int_device *s,
+				struct v4l2_format *f)
+{
+	struct tcm825x_sensor *sensor = s->priv;
+
+	f->fmt.pix = sensor->pix;
+
+	return 0;
+}
+
+static int ioctl_g_parm(struct v4l2_int_device *s,
+			     struct v4l2_streamparm *a)
+{
+	struct tcm825x_sensor *sensor = s->priv;
+	struct v4l2_captureparm *cparm = &a->parm.capture;
+
+	if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
+	memset(a, 0, sizeof(*a));
+	a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+	cparm->capability = V4L2_CAP_TIMEPERFRAME;
+	cparm->timeperframe = sensor->timeperframe;
+
+	return 0;
+}
+
+static int ioctl_s_parm(struct v4l2_int_device *s,
+			     struct v4l2_streamparm *a)
+{
+	struct tcm825x_sensor *sensor = s->priv;
+	struct v4l2_fract *timeperframe = &a->parm.capture.timeperframe;
+	u32 tgt_fps;	/* target frames per secound */
+	int rval;
+
+	if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
+	if ((timeperframe->numerator == 0)
+	    || (timeperframe->denominator == 0)) {
+		timeperframe->denominator = DEFAULT_FPS;
+		timeperframe->numerator = 1;
+	}
+
+	tgt_fps = timeperframe->denominator / timeperframe->numerator;
+
+	if (tgt_fps > MAX_FPS) {
+		timeperframe->denominator = MAX_FPS;
+		timeperframe->numerator = 1;
+	} else if (tgt_fps < MIN_FPS) {
+		timeperframe->denominator = MIN_FPS;
+		timeperframe->numerator = 1;
+	}
+
+	sensor->timeperframe = *timeperframe;
+
+	rval = tcm825x_configure(s);
+
+	return rval;
+}
+
+static int ioctl_s_power(struct v4l2_int_device *s, int on)
+{
+	struct tcm825x_sensor *sensor = s->priv;
+
+	return sensor->platform_data->power_set(on);
+}
+
+/*
+ * Given the image capture format in pix, the nominal frame period in
+ * timeperframe, calculate the required xclk frequency.
+ *
+ * TCM825X input frequency characteristics are:
+ *     Minimum 11.9 MHz, Typical 24.57 MHz and maximum 25/27 MHz
+ */
+
+static int ioctl_g_ifparm(struct v4l2_int_device *s, struct v4l2_ifparm *p)
+{
+	struct tcm825x_sensor *sensor = s->priv;
+	struct v4l2_fract *timeperframe = &sensor->timeperframe;
+	u32 tgt_xclk;	/* target xclk */
+	u32 tgt_fps;	/* target frames per secound */
+	int rval;
+
+	rval = sensor->platform_data->ifparm(p);
+	if (rval)
+		return rval;
+
+	tgt_fps = timeperframe->denominator / timeperframe->numerator;
+
+	tgt_xclk = (tgt_fps <= HIGH_FPS_MODE_LOWER_LIMIT) ?
+		(2457 * tgt_fps) / MAX_HALF_FPS :
+		(2457 * tgt_fps) / MAX_FPS;
+	tgt_xclk *= 10000;
+
+	tgt_xclk = min(tgt_xclk, (u32)TCM825X_XCLK_MAX);
+	tgt_xclk = max(tgt_xclk, (u32)TCM825X_XCLK_MIN);
+
+	p->u.bt656.clock_curr = tgt_xclk;
+
+	return 0;
+}
+
+static int ioctl_g_needs_reset(struct v4l2_int_device *s, void *buf)
+{
+	struct tcm825x_sensor *sensor = s->priv;
+
+	return sensor->platform_data->needs_reset(s, buf, &sensor->pix);
+}
+
+static int ioctl_reset(struct v4l2_int_device *s)
+{
+	return -EBUSY;
+}
+
+static int ioctl_init(struct v4l2_int_device *s)
+{
+	return tcm825x_configure(s);
+}
+
+static int ioctl_dev_exit(struct v4l2_int_device *s)
+{
+	return 0;
+}
+
+static int ioctl_dev_init(struct v4l2_int_device *s)
+{
+	struct tcm825x_sensor *sensor = s->priv;
+	int r;
+
+	r = tcm825x_read_reg(sensor->i2c_client, 0x01);
+	if (r < 0)
+		return r;
+	if (r == 0) {
+		dev_err(&sensor->i2c_client->dev, "device not detected\n");
+		return -EIO;
+	}
+	return 0;
+}
+
+static struct v4l2_int_ioctl_desc tcm825x_ioctl_desc[] = {
+	{ vidioc_int_dev_init_num,
+	  (v4l2_int_ioctl_func *)ioctl_dev_init },
+	{ vidioc_int_dev_exit_num,
+	  (v4l2_int_ioctl_func *)ioctl_dev_exit },
+	{ vidioc_int_s_power_num,
+	  (v4l2_int_ioctl_func *)ioctl_s_power },
+	{ vidioc_int_g_ifparm_num,
+	  (v4l2_int_ioctl_func *)ioctl_g_ifparm },
+	{ vidioc_int_g_needs_reset_num,
+	  (v4l2_int_ioctl_func *)ioctl_g_needs_reset },
+	{ vidioc_int_reset_num,
+	  (v4l2_int_ioctl_func *)ioctl_reset },
+	{ vidioc_int_init_num,
+	  (v4l2_int_ioctl_func *)ioctl_init },
+	{ vidioc_int_enum_fmt_cap_num,
+	  (v4l2_int_ioctl_func *)ioctl_enum_fmt_cap },
+	{ vidioc_int_try_fmt_cap_num,
+	  (v4l2_int_ioctl_func *)ioctl_try_fmt_cap },
+	{ vidioc_int_g_fmt_cap_num,
+	  (v4l2_int_ioctl_func *)ioctl_g_fmt_cap },
+	{ vidioc_int_s_fmt_cap_num,
+	  (v4l2_int_ioctl_func *)ioctl_s_fmt_cap },
+	{ vidioc_int_g_parm_num,
+	  (v4l2_int_ioctl_func *)ioctl_g_parm },
+	{ vidioc_int_s_parm_num,
+	  (v4l2_int_ioctl_func *)ioctl_s_parm },
+	{ vidioc_int_queryctrl_num,
+	  (v4l2_int_ioctl_func *)ioctl_queryctrl },
+	{ vidioc_int_g_ctrl_num,
+	  (v4l2_int_ioctl_func *)ioctl_g_ctrl },
+	{ vidioc_int_s_ctrl_num,
+	  (v4l2_int_ioctl_func *)ioctl_s_ctrl },
+};
+
+static struct v4l2_int_slave tcm825x_slave = {
+	.ioctls = tcm825x_ioctl_desc,
+	.num_ioctls = ARRAY_SIZE(tcm825x_ioctl_desc),
+};
+
+static struct tcm825x_sensor tcm825x;
+
+static struct v4l2_int_device tcm825x_int_device = {
+	.module = THIS_MODULE,
+	.name = TCM825X_NAME,
+	.priv = &tcm825x,
+	.type = v4l2_int_type_slave,
+	.u = {
+		.slave = &tcm825x_slave,
+	},
+};
+
+static int tcm825x_probe(struct i2c_client *client,
+			 const struct i2c_device_id *did)
+{
+	struct tcm825x_sensor *sensor = &tcm825x;
+
+	if (i2c_get_clientdata(client))
+		return -EBUSY;
+
+	sensor->platform_data = client->dev.platform_data;
+
+	if (sensor->platform_data == NULL
+	    || !sensor->platform_data->is_okay())
+		return -ENODEV;
+
+	sensor->v4l2_int_device = &tcm825x_int_device;
+
+	sensor->i2c_client = client;
+	i2c_set_clientdata(client, sensor);
+
+	/* Make the default capture format QVGA RGB565 */
+	sensor->pix.width = tcm825x_sizes[QVGA].width;
+	sensor->pix.height = tcm825x_sizes[QVGA].height;
+	sensor->pix.pixelformat = V4L2_PIX_FMT_RGB565;
+
+	return v4l2_int_device_register(sensor->v4l2_int_device);
+}
+
+static int tcm825x_remove(struct i2c_client *client)
+{
+	struct tcm825x_sensor *sensor = i2c_get_clientdata(client);
+
+	if (!client->adapter)
+		return -ENODEV;	/* our client isn't attached */
+
+	v4l2_int_device_unregister(sensor->v4l2_int_device);
+
+	return 0;
+}
+
+static const struct i2c_device_id tcm825x_id[] = {
+	{ "tcm825x", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, tcm825x_id);
+
+static struct i2c_driver tcm825x_i2c_driver = {
+	.driver	= {
+		.name = TCM825X_NAME,
+	},
+	.probe	= tcm825x_probe,
+	.remove	= tcm825x_remove,
+	.id_table = tcm825x_id,
+};
+
+static struct tcm825x_sensor tcm825x = {
+	.timeperframe = {
+		.numerator   = 1,
+		.denominator = DEFAULT_FPS,
+	},
+};
+
+static int __init tcm825x_init(void)
+{
+	int rval;
+
+	rval = i2c_add_driver(&tcm825x_i2c_driver);
+	if (rval)
+		printk(KERN_INFO "%s: failed registering " TCM825X_NAME "\n",
+		       __func__);
+
+	return rval;
+}
+
+static void __exit tcm825x_exit(void)
+{
+	i2c_del_driver(&tcm825x_i2c_driver);
+}
+
+/*
+ * FIXME: Menelaus isn't ready (?) at module_init stage, so use
+ * late_initcall for now.
+ */
+late_initcall(tcm825x_init);
+module_exit(tcm825x_exit);
+
+MODULE_AUTHOR("Sakari Ailus <sakari.ailus@nokia.com>");
+MODULE_DESCRIPTION("TCM825x camera sensor driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/i2c/tcm825x.h b/drivers/media/i2c/tcm825x.h
new file mode 100644
index 0000000..8ebab95
--- /dev/null
+++ b/drivers/media/i2c/tcm825x.h
@@ -0,0 +1,200 @@
+/*
+ * drivers/media/i2c/tcm825x.h
+ *
+ * Register definitions for the TCM825X CameraChip.
+ *
+ * Author: David Cohen (david.cohen@indt.org.br)
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ *
+ * This file was based on ov9640.h from MontaVista
+ */
+
+#ifndef TCM825X_H
+#define TCM825X_H
+
+#include <linux/videodev2.h>
+
+#include <media/v4l2-int-device.h>
+
+#define TCM825X_NAME "tcm825x"
+
+#define TCM825X_MASK(x)  x & 0x00ff
+#define TCM825X_ADDR(x) (x & 0xff00) >> 8
+
+/* The TCM825X I2C sensor chip has a fixed slave address of 0x3d. */
+#define TCM825X_I2C_ADDR	0x3d
+
+/*
+ * define register offsets for the TCM825X sensor chip
+ * OFFSET(8 bits) + MASK(8 bits)
+ * MASK bit 4 and 3 are used when the register uses more than one address
+ */
+#define TCM825X_FPS		0x0280
+#define TCM825X_ACF		0x0240
+#define TCM825X_DOUTBUF		0x020C
+#define TCM825X_DCLKP		0x0202
+#define TCM825X_ACFDET		0x0201
+#define TCM825X_DOUTSW		0x0380
+#define TCM825X_DATAHZ		0x0340
+#define TCM825X_PICSIZ		0x033c
+#define TCM825X_PICFMT		0x0302
+#define TCM825X_V_INV		0x0480
+#define TCM825X_H_INV		0x0440
+#define TCM825X_ESRLSW		0x0430
+#define TCM825X_V_LENGTH	0x040F
+#define TCM825X_ALCSW		0x0580
+#define TCM825X_ESRLIM		0x0560
+#define TCM825X_ESRSPD_U        0x051F
+#define TCM825X_ESRSPD_L        0x06FF
+#define TCM825X_AG		0x07FF
+#define TCM825X_ESRSPD2         0x06FF
+#define TCM825X_ALCMODE         0x0830
+#define TCM825X_ALCH            0x080F
+#define TCM825X_ALCL            0x09FF
+#define TCM825X_AWBSW           0x0A80
+#define TCM825X_MRG             0x0BFF
+#define TCM825X_MBG             0x0CFF
+#define TCM825X_GAMSW           0x0D80
+#define TCM825X_HDTG            0x0EFF
+#define TCM825X_VDTG            0x0FFF
+#define TCM825X_HDTCORE         0x10F0
+#define TCM825X_VDTCORE         0x100F
+#define TCM825X_CONT            0x11FF
+#define TCM825X_BRIGHT          0x12FF
+#define TCM825X_VHUE            0x137F
+#define TCM825X_UHUE            0x147F
+#define TCM825X_VGAIN           0x153F
+#define TCM825X_UGAIN           0x163F
+#define TCM825X_UVCORE          0x170F
+#define TCM825X_SATU            0x187F
+#define TCM825X_MHMODE          0x1980
+#define TCM825X_MHLPFSEL        0x1940
+#define TCM825X_YMODE           0x1930
+#define TCM825X_MIXHG           0x1907
+#define TCM825X_LENS            0x1A3F
+#define TCM825X_AGLIM           0x1BE0
+#define TCM825X_LENSRPOL        0x1B10
+#define TCM825X_LENSRGAIN       0x1B0F
+#define TCM825X_ES100S          0x1CFF
+#define TCM825X_ES120S          0x1DFF
+#define TCM825X_DMASK           0x1EC0
+#define TCM825X_CODESW          0x1E20
+#define TCM825X_CODESEL         0x1E10
+#define TCM825X_TESPIC          0x1E04
+#define TCM825X_PICSEL          0x1E03
+#define TCM825X_HNUM            0x20FF
+#define TCM825X_VOUTPH          0x287F
+#define TCM825X_ESROUT          0x327F
+#define TCM825X_ESROUT2         0x33FF
+#define TCM825X_AGOUT           0x34FF
+#define TCM825X_DGOUT           0x353F
+#define TCM825X_AGSLOW1         0x39C0
+#define TCM825X_FLLSMODE        0x3930
+#define TCM825X_FLLSLIM         0x390F
+#define TCM825X_DETSEL          0x3AF0
+#define TCM825X_ACDETNC         0x3A0F
+#define TCM825X_AGSLOW2         0x3BC0
+#define TCM825X_DG              0x3B3F
+#define TCM825X_REJHLEV         0x3CFF
+#define TCM825X_ALCLOCK         0x3D80
+#define TCM825X_FPSLNKSW        0x3D40
+#define TCM825X_ALCSPD          0x3D30
+#define TCM825X_REJH            0x3D03
+#define TCM825X_SHESRSW         0x3E80
+#define TCM825X_ESLIMSEL        0x3E40
+#define TCM825X_SHESRSPD        0x3E30
+#define TCM825X_ELSTEP          0x3E0C
+#define TCM825X_ELSTART         0x3E03
+#define TCM825X_AGMIN           0x3FFF
+#define TCM825X_PREGRG          0x423F
+#define TCM825X_PREGBG          0x433F
+#define TCM825X_PRERG           0x443F
+#define TCM825X_PREBG           0x453F
+#define TCM825X_MSKBR           0x477F
+#define TCM825X_MSKGR           0x487F
+#define TCM825X_MSKRB           0x497F
+#define TCM825X_MSKGB           0x4A7F
+#define TCM825X_MSKRG           0x4B7F
+#define TCM825X_MSKBG           0x4C7F
+#define TCM825X_HDTCSW          0x4D80
+#define TCM825X_VDTCSW          0x4D40
+#define TCM825X_DTCYL           0x4D3F
+#define TCM825X_HDTPSW          0x4E80
+#define TCM825X_VDTPSW          0x4E40
+#define TCM825X_DTCGAIN         0x4E3F
+#define TCM825X_DTLLIMSW        0x4F10
+#define TCM825X_DTLYLIM         0x4F0F
+#define TCM825X_YLCUTLMSK       0x5080
+#define TCM825X_YLCUTL          0x503F
+#define TCM825X_YLCUTHMSK       0x5180
+#define TCM825X_YLCUTH          0x513F
+#define TCM825X_UVSKNC          0x527F
+#define TCM825X_UVLJ            0x537F
+#define TCM825X_WBGMIN          0x54FF
+#define TCM825X_WBGMAX          0x55FF
+#define TCM825X_WBSPDUP         0x5603
+#define TCM825X_ALLAREA         0x5820
+#define TCM825X_WBLOCK          0x5810
+#define TCM825X_WB2SP           0x580F
+#define TCM825X_KIZUSW          0x5920
+#define TCM825X_PBRSW           0x5910
+#define TCM825X_ABCSW           0x5903
+#define TCM825X_PBDLV           0x5AFF
+#define TCM825X_PBC1LV          0x5BFF
+
+#define TCM825X_NUM_REGS	(TCM825X_ADDR(TCM825X_PBC1LV) + 1)
+
+#define TCM825X_BYTES_PER_PIXEL 2
+
+#define TCM825X_REG_TERM 0xff		/* terminating list entry for reg */
+#define TCM825X_VAL_TERM 0xff		/* terminating list entry for val */
+
+/* define a structure for tcm825x register initialization values */
+struct tcm825x_reg {
+	u8 val;
+	u16 reg;
+};
+
+enum image_size { subQCIF = 0, QQVGA, QCIF, QVGA, CIF, VGA };
+enum pixel_format { YUV422 = 0, RGB565 };
+#define NUM_IMAGE_SIZES 6
+#define NUM_PIXEL_FORMATS 2
+
+#define TCM825X_XCLK_MIN	11900000
+#define TCM825X_XCLK_MAX	25000000
+
+struct capture_size {
+	unsigned long width;
+	unsigned long height;
+};
+
+struct tcm825x_platform_data {
+	/* Is the sensor usable? Doesn't yet mean it's there, but you
+	 * can try! */
+	int (*is_okay)(void);
+	/* Set power state, zero is off, non-zero is on. */
+	int (*power_set)(int power);
+	/* Default registers written after power-on or reset. */
+	const struct tcm825x_reg *(*default_regs)(void);
+	int (*needs_reset)(struct v4l2_int_device *s, void *buf,
+			   struct v4l2_pix_format *fmt);
+	int (*ifparm)(struct v4l2_ifparm *p);
+	int (*is_upside_down)(void);
+};
+
+/* Array of image sizes supported by TCM825X.  These must be ordered from
+ * smallest image size to largest.
+ */
+static const struct capture_size tcm825x_sizes[] = {
+	{ 128,  96 }, /* subQCIF */
+	{ 160, 120 }, /* QQVGA */
+	{ 176, 144 }, /* QCIF */
+	{ 320, 240 }, /* QVGA */
+	{ 352, 288 }, /* CIF */
+	{ 640, 480 }, /* VGA */
+};
+
+#endif /* ifndef TCM825X_H */
diff --git a/drivers/media/i2c/tda7432.c b/drivers/media/i2c/tda7432.c
new file mode 100644
index 0000000..f7707e6
--- /dev/null
+++ b/drivers/media/i2c/tda7432.c
@@ -0,0 +1,485 @@
+/*
+ * For the STS-Thompson TDA7432 audio processor chip
+ *
+ * Handles audio functions: volume, balance, tone, loudness
+ * This driver will not complain if used with any
+ * other i2c device with the same address.
+ *
+ * Muting and tone control by Jonathan Isom <jisom@ematic.com>
+ *
+ * Copyright (c) 2000 Eric Sandeen <eric_sandeen@bigfoot.com>
+ * Copyright (c) 2006 Mauro Carvalho Chehab <mchehab@infradead.org>
+ * This code is placed under the terms of the GNU General Public License
+ * Based on tda9855.c by Steve VanDeBogart (vandebo@uclink.berkeley.edu)
+ * Which was based on tda8425.c by Greg Alexander (c) 1998
+ *
+ * OPTIONS:
+ * debug    - set to 1 if you'd like to see debug messages
+ *            set to 2 if you'd like to be inundated with debug messages
+ *
+ * loudness - set between 0 and 15 for varying degrees of loudness effect
+ *
+ * maxvol   - set maximium volume to +20db (1), default is 0db(0)
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/videodev2.h>
+#include <linux/i2c.h>
+
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
+#include <media/i2c-addr.h>
+
+#ifndef VIDEO_AUDIO_BALANCE
+# define VIDEO_AUDIO_BALANCE 32
+#endif
+
+MODULE_AUTHOR("Eric Sandeen <eric_sandeen@bigfoot.com>");
+MODULE_DESCRIPTION("bttv driver for the tda7432 audio processor chip");
+MODULE_LICENSE("GPL");
+
+static int maxvol;
+static int loudness; /* disable loudness by default */
+static int debug;	 /* insmod parameter */
+module_param(debug, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Set debugging level from 0 to 3. Default is off(0).");
+module_param(loudness, int, S_IRUGO);
+MODULE_PARM_DESC(loudness, "Turn loudness on(1) else off(0). Default is off(0).");
+module_param(maxvol, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(maxvol, "Set maximium volume to +20dB(0) else +0dB(1). Default is +20dB(0).");
+
+
+/* Structure of address and subaddresses for the tda7432 */
+
+struct tda7432 {
+	struct v4l2_subdev sd;
+	int addr;
+	int input;
+	int volume;
+	int muted;
+	int bass, treble;
+	int lf, lr, rf, rr;
+	int loud;
+};
+
+static inline struct tda7432 *to_state(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct tda7432, sd);
+}
+
+/* The TDA7432 is made by STS-Thompson
+ * http://www.st.com
+ * http://us.st.com/stonline/books/pdf/docs/4056.pdf
+ *
+ * TDA7432: I2C-bus controlled basic audio processor
+ *
+ * The TDA7432 controls basic audio functions like volume, balance,
+ * and tone control (including loudness).  It also has four channel
+ * output (for front and rear).  Since most vidcap cards probably
+ * don't have 4 channel output, this driver will set front & rear
+ * together (no independent control).
+ */
+
+		/* Subaddresses for TDA7432 */
+
+#define TDA7432_IN	0x00 /* Input select                 */
+#define TDA7432_VL	0x01 /* Volume                       */
+#define TDA7432_TN	0x02 /* Bass, Treble (Tone)          */
+#define TDA7432_LF	0x03 /* Attenuation LF (Left Front)  */
+#define TDA7432_LR	0x04 /* Attenuation LR (Left Rear)   */
+#define TDA7432_RF	0x05 /* Attenuation RF (Right Front) */
+#define TDA7432_RR	0x06 /* Attenuation RR (Right Rear)  */
+#define TDA7432_LD	0x07 /* Loudness                     */
+
+
+		/* Masks for bits in TDA7432 subaddresses */
+
+/* Many of these not used - just for documentation */
+
+/* Subaddress 0x00 - Input selection and bass control */
+
+/* Bits 0,1,2 control input:
+ * 0x00 - Stereo input
+ * 0x02 - Mono input
+ * 0x03 - Mute  (Using Attenuators Plays better with modules)
+ * Mono probably isn't used - I'm guessing only the stereo
+ * input is connected on most cards, so we'll set it to stereo.
+ *
+ * Bit 3 controls bass cut: 0/1 is non-symmetric/symmetric bass cut
+ * Bit 4 controls bass range: 0/1 is extended/standard bass range
+ *
+ * Highest 3 bits not used
+ */
+
+#define TDA7432_STEREO_IN	0
+#define TDA7432_MONO_IN		2	/* Probably won't be used */
+#define TDA7432_BASS_SYM	1 << 3
+#define TDA7432_BASS_NORM	1 << 4
+
+/* Subaddress 0x01 - Volume */
+
+/* Lower 7 bits control volume from -79dB to +32dB in 1dB steps
+ * Recommended maximum is +20 dB
+ *
+ * +32dB: 0x00
+ * +20dB: 0x0c
+ *   0dB: 0x20
+ * -79dB: 0x6f
+ *
+ * MSB (bit 7) controls loudness: 1/0 is loudness on/off
+ */
+
+#define	TDA7432_VOL_0DB		0x20
+#define TDA7432_LD_ON		1 << 7
+
+
+/* Subaddress 0x02 - Tone control */
+
+/* Bits 0,1,2 control absolute treble gain from 0dB to 14dB
+ * 0x0 is 14dB, 0x7 is 0dB
+ *
+ * Bit 3 controls treble attenuation/gain (sign)
+ * 1 = gain (+)
+ * 0 = attenuation (-)
+ *
+ * Bits 4,5,6 control absolute bass gain from 0dB to 14dB
+ * (This is only true for normal base range, set in 0x00)
+ * 0x0 << 4 is 14dB, 0x7 is 0dB
+ *
+ * Bit 7 controls bass attenuation/gain (sign)
+ * 1 << 7 = gain (+)
+ * 0 << 7 = attenuation (-)
+ *
+ * Example:
+ * 1 1 0 1 0 1 0 1 is +4dB bass, -4dB treble
+ */
+
+#define TDA7432_TREBLE_0DB		0xf
+#define TDA7432_TREBLE			7
+#define TDA7432_TREBLE_GAIN		1 << 3
+#define TDA7432_BASS_0DB		0xf
+#define TDA7432_BASS			7 << 4
+#define TDA7432_BASS_GAIN		1 << 7
+
+
+/* Subaddress 0x03 - Left  Front attenuation */
+/* Subaddress 0x04 - Left  Rear  attenuation */
+/* Subaddress 0x05 - Right Front attenuation */
+/* Subaddress 0x06 - Right Rear  attenuation */
+
+/* Bits 0,1,2,3,4 control attenuation from 0dB to -37.5dB
+ * in 1.5dB steps.
+ *
+ * 0x00 is     0dB
+ * 0x1f is -37.5dB
+ *
+ * Bit 5 mutes that channel when set (1 = mute, 0 = unmute)
+ * We'll use the mute on the input, though (above)
+ * Bits 6,7 unused
+ */
+
+#define TDA7432_ATTEN_0DB	0x00
+#define TDA7432_MUTE        0x1 << 5
+
+
+/* Subaddress 0x07 - Loudness Control */
+
+/* Bits 0,1,2,3 control loudness from 0dB to -15dB in 1dB steps
+ * when bit 4 is NOT set
+ *
+ * 0x0 is   0dB
+ * 0xf is -15dB
+ *
+ * If bit 4 is set, then there is a flat attenuation according to
+ * the lower 4 bits, as above.
+ *
+ * Bits 5,6,7 unused
+ */
+
+
+
+/* Begin code */
+
+static int tda7432_write(struct v4l2_subdev *sd, int subaddr, int val)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	unsigned char buffer[2];
+
+	v4l2_dbg(2, debug, sd, "In tda7432_write\n");
+	v4l2_dbg(1, debug, sd, "Writing %d 0x%x\n", subaddr, val);
+	buffer[0] = subaddr;
+	buffer[1] = val;
+	if (2 != i2c_master_send(client, buffer, 2)) {
+		v4l2_err(sd, "I/O error, trying (write %d 0x%x)\n",
+		       subaddr, val);
+		return -1;
+	}
+	return 0;
+}
+
+static int tda7432_set(struct v4l2_subdev *sd)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct tda7432 *t = to_state(sd);
+	unsigned char buf[16];
+
+	v4l2_dbg(1, debug, sd,
+		"tda7432: 7432_set(0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x)\n",
+		t->input, t->volume, t->bass, t->treble, t->lf, t->lr,
+		t->rf, t->rr, t->loud);
+	buf[0]  = TDA7432_IN;
+	buf[1]  = t->input;
+	buf[2]  = t->volume;
+	buf[3]  = t->bass;
+	buf[4]	= t->treble;
+	buf[5]  = t->lf;
+	buf[6]  = t->lr;
+	buf[7]  = t->rf;
+	buf[8]  = t->rr;
+	buf[9]  = t->loud;
+	if (10 != i2c_master_send(client, buf, 10)) {
+		v4l2_err(sd, "I/O error, trying tda7432_set\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+static void do_tda7432_init(struct v4l2_subdev *sd)
+{
+	struct tda7432 *t = to_state(sd);
+
+	v4l2_dbg(2, debug, sd, "In tda7432_init\n");
+
+	t->input  = TDA7432_STEREO_IN |  /* Main (stereo) input   */
+		    TDA7432_BASS_SYM  |  /* Symmetric bass cut    */
+		    TDA7432_BASS_NORM;   /* Normal bass range     */
+	t->volume =  0x3b ;				 /* -27dB Volume            */
+	if (loudness)			 /* Turn loudness on?     */
+		t->volume |= TDA7432_LD_ON;
+	t->muted    = 1;
+	t->treble   = TDA7432_TREBLE_0DB; /* 0dB Treble            */
+	t->bass		= TDA7432_BASS_0DB; 	 /* 0dB Bass              */
+	t->lf     = TDA7432_ATTEN_0DB;	 /* 0dB attenuation       */
+	t->lr     = TDA7432_ATTEN_0DB;	 /* 0dB attenuation       */
+	t->rf     = TDA7432_ATTEN_0DB;	 /* 0dB attenuation       */
+	t->rr     = TDA7432_ATTEN_0DB;	 /* 0dB attenuation       */
+	t->loud   = loudness;		 /* insmod parameter      */
+
+	tda7432_set(sd);
+}
+
+static int tda7432_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+	struct tda7432 *t = to_state(sd);
+
+	switch (ctrl->id) {
+	case V4L2_CID_AUDIO_MUTE:
+		ctrl->value=t->muted;
+		return 0;
+	case V4L2_CID_AUDIO_VOLUME:
+		if (!maxvol){  /* max +20db */
+			ctrl->value = ( 0x6f - (t->volume & 0x7F) ) * 630;
+		} else {       /* max 0db   */
+			ctrl->value = ( 0x6f - (t->volume & 0x7F) ) * 829;
+		}
+		return 0;
+	case V4L2_CID_AUDIO_BALANCE:
+	{
+		if ( (t->lf) < (t->rf) )
+			/* right is attenuated, balance shifted left */
+			ctrl->value = (32768 - 1057*(t->rf));
+		else
+			/* left is attenuated, balance shifted right */
+			ctrl->value = (32768 + 1057*(t->lf));
+		return 0;
+	}
+	case V4L2_CID_AUDIO_BASS:
+	{
+		/* Bass/treble 4 bits each */
+		int bass=t->bass;
+		if(bass >= 0x8)
+			bass = ~(bass - 0x8) & 0xf;
+		ctrl->value = (bass << 12)+(bass << 8)+(bass << 4)+(bass);
+		return 0;
+	}
+	case V4L2_CID_AUDIO_TREBLE:
+	{
+		int treble=t->treble;
+		if(treble >= 0x8)
+			treble = ~(treble - 0x8) & 0xf;
+		ctrl->value = (treble << 12)+(treble << 8)+(treble << 4)+(treble);
+		return 0;
+	}
+	}
+	return -EINVAL;
+}
+
+static int tda7432_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+	struct tda7432 *t = to_state(sd);
+
+	switch (ctrl->id) {
+	case V4L2_CID_AUDIO_MUTE:
+		t->muted=ctrl->value;
+		break;
+	case V4L2_CID_AUDIO_VOLUME:
+		if(!maxvol){ /* max +20db */
+			t->volume = 0x6f - ((ctrl->value)/630);
+		} else {    /* max 0db   */
+			t->volume = 0x6f - ((ctrl->value)/829);
+		}
+		if (loudness)		/* Turn on the loudness bit */
+			t->volume |= TDA7432_LD_ON;
+
+		tda7432_write(sd, TDA7432_VL, t->volume);
+		return 0;
+	case V4L2_CID_AUDIO_BALANCE:
+		if (ctrl->value < 32768) {
+			/* shifted to left, attenuate right */
+			t->rr = (32768 - ctrl->value)/1057;
+			t->rf = t->rr;
+			t->lr = TDA7432_ATTEN_0DB;
+			t->lf = TDA7432_ATTEN_0DB;
+		} else if(ctrl->value > 32769) {
+			/* shifted to right, attenuate left */
+			t->lf = (ctrl->value - 32768)/1057;
+			t->lr = t->lf;
+			t->rr = TDA7432_ATTEN_0DB;
+			t->rf = TDA7432_ATTEN_0DB;
+		} else {
+			/* centered */
+			t->rr = TDA7432_ATTEN_0DB;
+			t->rf = TDA7432_ATTEN_0DB;
+			t->lf = TDA7432_ATTEN_0DB;
+			t->lr = TDA7432_ATTEN_0DB;
+		}
+		break;
+	case V4L2_CID_AUDIO_BASS:
+		t->bass = ctrl->value >> 12;
+		if(t->bass>= 0x8)
+				t->bass = (~t->bass & 0xf) + 0x8 ;
+
+		tda7432_write(sd, TDA7432_TN, 0x10 | (t->bass << 4) | t->treble);
+		return 0;
+	case V4L2_CID_AUDIO_TREBLE:
+		t->treble= ctrl->value >> 12;
+		if(t->treble>= 0x8)
+				t->treble = (~t->treble & 0xf) + 0x8 ;
+
+		tda7432_write(sd, TDA7432_TN, 0x10 | (t->bass << 4) | t->treble);
+		return 0;
+	default:
+		return -EINVAL;
+	}
+
+	/* Used for both mute and balance changes */
+	if (t->muted)
+	{
+		/* Mute & update balance*/
+		tda7432_write(sd, TDA7432_LF, t->lf | TDA7432_MUTE);
+		tda7432_write(sd, TDA7432_LR, t->lr | TDA7432_MUTE);
+		tda7432_write(sd, TDA7432_RF, t->rf | TDA7432_MUTE);
+		tda7432_write(sd, TDA7432_RR, t->rr | TDA7432_MUTE);
+	} else {
+		tda7432_write(sd, TDA7432_LF, t->lf);
+		tda7432_write(sd, TDA7432_LR, t->lr);
+		tda7432_write(sd, TDA7432_RF, t->rf);
+		tda7432_write(sd, TDA7432_RR, t->rr);
+	}
+	return 0;
+}
+
+static int tda7432_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
+{
+	switch (qc->id) {
+	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(qc, 0, 65535, 65535 / 100, 32768);
+	}
+	return -EINVAL;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static const struct v4l2_subdev_core_ops tda7432_core_ops = {
+	.queryctrl = tda7432_queryctrl,
+	.g_ctrl = tda7432_g_ctrl,
+	.s_ctrl = tda7432_s_ctrl,
+};
+
+static const struct v4l2_subdev_ops tda7432_ops = {
+	.core = &tda7432_core_ops,
+};
+
+/* ----------------------------------------------------------------------- */
+
+/* *********************** *
+ * i2c interface functions *
+ * *********************** */
+
+static int tda7432_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	struct tda7432 *t;
+	struct v4l2_subdev *sd;
+
+	v4l_info(client, "chip found @ 0x%02x (%s)\n",
+			client->addr << 1, client->adapter->name);
+
+	t = kzalloc(sizeof(*t), GFP_KERNEL);
+	if (!t)
+		return -ENOMEM;
+	sd = &t->sd;
+	v4l2_i2c_subdev_init(sd, client, &tda7432_ops);
+	if (loudness < 0 || loudness > 15) {
+		v4l2_warn(sd, "loudness parameter must be between 0 and 15\n");
+		if (loudness < 0)
+			loudness = 0;
+		if (loudness > 15)
+			loudness = 15;
+	}
+
+	do_tda7432_init(sd);
+	return 0;
+}
+
+static int tda7432_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+
+	do_tda7432_init(sd);
+	v4l2_device_unregister_subdev(sd);
+	kfree(to_state(sd));
+	return 0;
+}
+
+static const struct i2c_device_id tda7432_id[] = {
+	{ "tda7432", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, tda7432_id);
+
+static struct i2c_driver tda7432_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "tda7432",
+	},
+	.probe		= tda7432_probe,
+	.remove		= tda7432_remove,
+	.id_table	= tda7432_id,
+};
+
+module_i2c_driver(tda7432_driver);
diff --git a/drivers/media/i2c/tda9840.c b/drivers/media/i2c/tda9840.c
new file mode 100644
index 0000000..3d7ddd9
--- /dev/null
+++ b/drivers/media/i2c/tda9840.c
@@ -0,0 +1,224 @@
+ /*
+    tda9840 - i2c-driver for the tda9840 by SGS Thomson
+
+    Copyright (C) 1998-2003 Michael Hunold <michael@mihu.de>
+    Copyright (C) 2008 Hans Verkuil <hverkuil@xs4all.nl>
+
+    The tda9840 is a stereo/dual sound processor with digital
+    identification. It can be found at address 0x84 on the i2c-bus.
+
+    For detailed informations download the specifications directly
+    from SGS Thomson at http://www.st.com
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+  */
+
+
+#include <linux/module.h>
+#include <linux/ioctl.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-chip-ident.h>
+
+MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
+MODULE_DESCRIPTION("tda9840 driver");
+MODULE_LICENSE("GPL");
+
+static int debug;
+module_param(debug, int, 0644);
+
+MODULE_PARM_DESC(debug, "Debug level (0-1)");
+
+#define	SWITCH		0x00
+#define	LEVEL_ADJUST	0x02
+#define	STEREO_ADJUST	0x03
+#define	TEST		0x04
+
+#define TDA9840_SET_MUTE                0x00
+#define TDA9840_SET_MONO                0x10
+#define TDA9840_SET_STEREO              0x2a
+#define TDA9840_SET_LANG1               0x12
+#define TDA9840_SET_LANG2               0x1e
+#define TDA9840_SET_BOTH                0x1a
+#define TDA9840_SET_BOTH_R              0x16
+#define TDA9840_SET_EXTERNAL            0x7a
+
+
+static void tda9840_write(struct v4l2_subdev *sd, u8 reg, u8 val)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	if (i2c_smbus_write_byte_data(client, reg, val))
+		v4l2_dbg(1, debug, sd, "error writing %02x to %02x\n",
+				val, reg);
+}
+
+static int tda9840_status(struct v4l2_subdev *sd)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	u8 byte;
+
+	if (1 != i2c_master_recv(client, &byte, 1)) {
+		v4l2_dbg(1, debug, sd,
+			"i2c_master_recv() failed\n");
+		return -EIO;
+	}
+
+	if (byte & 0x80) {
+		v4l2_dbg(1, debug, sd,
+			"TDA9840_DETECT: register contents invalid\n");
+		return -EINVAL;
+	}
+
+	v4l2_dbg(1, debug, sd, "TDA9840_DETECT: byte: 0x%02x\n", byte);
+	return byte & 0x60;
+}
+
+static int tda9840_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *t)
+{
+	int stat = tda9840_status(sd);
+	int byte;
+
+	if (t->index)
+		return -EINVAL;
+
+	stat = stat < 0 ? 0 : stat;
+	if (stat == 0 || stat == 0x60) /* mono input */
+		byte = TDA9840_SET_MONO;
+	else if (stat == 0x40) /* stereo input */
+		byte = (t->audmode == V4L2_TUNER_MODE_MONO) ?
+			TDA9840_SET_MONO : TDA9840_SET_STEREO;
+	else { /* bilingual */
+		switch (t->audmode) {
+		case V4L2_TUNER_MODE_LANG1_LANG2:
+			byte = TDA9840_SET_BOTH;
+			break;
+		case V4L2_TUNER_MODE_LANG2:
+			byte = TDA9840_SET_LANG2;
+			break;
+		default:
+			byte = TDA9840_SET_LANG1;
+			break;
+		}
+	}
+	v4l2_dbg(1, debug, sd, "TDA9840_SWITCH: 0x%02x\n", byte);
+	tda9840_write(sd, SWITCH, byte);
+	return 0;
+}
+
+static int tda9840_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *t)
+{
+	int stat = tda9840_status(sd);
+
+	if (stat < 0)
+		return stat;
+
+	t->rxsubchans = V4L2_TUNER_SUB_MONO;
+
+	switch (stat & 0x60) {
+	case 0x00:
+		t->rxsubchans = V4L2_TUNER_SUB_MONO;
+		break;
+	case 0x20:
+		t->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
+		break;
+	case 0x40:
+		t->rxsubchans = V4L2_TUNER_SUB_STEREO | V4L2_TUNER_SUB_MONO;
+		break;
+	default: /* Incorrect detect */
+		t->rxsubchans = V4L2_TUNER_MODE_MONO;
+		break;
+	}
+	return 0;
+}
+
+static int tda9840_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_TDA9840, 0);
+}
+
+/* ----------------------------------------------------------------------- */
+
+static const struct v4l2_subdev_core_ops tda9840_core_ops = {
+	.g_chip_ident = tda9840_g_chip_ident,
+};
+
+static const struct v4l2_subdev_tuner_ops tda9840_tuner_ops = {
+	.s_tuner = tda9840_s_tuner,
+	.g_tuner = tda9840_g_tuner,
+};
+
+static const struct v4l2_subdev_ops tda9840_ops = {
+	.core = &tda9840_core_ops,
+	.tuner = &tda9840_tuner_ops,
+};
+
+/* ----------------------------------------------------------------------- */
+
+static int tda9840_probe(struct i2c_client *client,
+			  const struct i2c_device_id *id)
+{
+	struct v4l2_subdev *sd;
+
+	/* let's see whether this adapter can support what we need */
+	if (!i2c_check_functionality(client->adapter,
+			I2C_FUNC_SMBUS_READ_BYTE_DATA |
+			I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
+		return -EIO;
+
+	v4l_info(client, "chip found @ 0x%x (%s)\n",
+			client->addr << 1, client->adapter->name);
+
+	sd = kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
+	if (sd == NULL)
+		return -ENOMEM;
+	v4l2_i2c_subdev_init(sd, client, &tda9840_ops);
+
+	/* set initial values for level & stereo - adjustment, mode */
+	tda9840_write(sd, LEVEL_ADJUST, 0);
+	tda9840_write(sd, STEREO_ADJUST, 0);
+	tda9840_write(sd, SWITCH, TDA9840_SET_STEREO);
+	return 0;
+}
+
+static int tda9840_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+
+	v4l2_device_unregister_subdev(sd);
+	kfree(sd);
+	return 0;
+}
+
+static const struct i2c_device_id tda9840_id[] = {
+	{ "tda9840", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, tda9840_id);
+
+static struct i2c_driver tda9840_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "tda9840",
+	},
+	.probe		= tda9840_probe,
+	.remove		= tda9840_remove,
+	.id_table	= tda9840_id,
+};
+
+module_i2c_driver(tda9840_driver);
diff --git a/drivers/media/i2c/tea6415c.c b/drivers/media/i2c/tea6415c.c
new file mode 100644
index 0000000..3d5b06a
--- /dev/null
+++ b/drivers/media/i2c/tea6415c.c
@@ -0,0 +1,187 @@
+ /*
+    tea6415c - i2c-driver for the tea6415c by SGS Thomson
+
+    Copyright (C) 1998-2003 Michael Hunold <michael@mihu.de>
+    Copyright (C) 2008 Hans Verkuil <hverkuil@xs4all.nl>
+
+    The tea6415c is a bus controlled video-matrix-switch
+    with 8 inputs and 6 outputs.
+    It is cascadable, i.e. it can be found at the addresses
+    0x86 and 0x06 on the i2c-bus.
+
+    For detailed informations download the specifications directly
+    from SGS Thomson at http://www.st.com
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License vs 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 Mvss Ave, Cambridge, MA 02139, USA.
+  */
+
+
+#include <linux/module.h>
+#include <linux/ioctl.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-chip-ident.h>
+#include "tea6415c.h"
+
+MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
+MODULE_DESCRIPTION("tea6415c driver");
+MODULE_LICENSE("GPL");
+
+static int debug;
+module_param(debug, int, 0644);
+
+MODULE_PARM_DESC(debug, "Debug level (0-1)");
+
+
+/* makes a connection between the input-pin 'i' and the output-pin 'o' */
+static int tea6415c_s_routing(struct v4l2_subdev *sd,
+			      u32 i, u32 o, u32 config)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	u8 byte = 0;
+	int ret;
+
+	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 -EINVAL;
+
+	/* to understand this, have a look at the tea6415c-specs (p.5) */
+	switch (o) {
+	case 18:
+		byte = 0x00;
+		break;
+	case 14:
+		byte = 0x20;
+		break;
+	case 16:
+		byte = 0x10;
+		break;
+	case 17:
+		byte = 0x08;
+		break;
+	case 15:
+		byte = 0x18;
+		break;
+	case 13:
+		byte = 0x28;
+		break;
+	}
+
+	switch (i) {
+	case 5:
+		byte |= 0x00;
+		break;
+	case 8:
+		byte |= 0x04;
+		break;
+	case 3:
+		byte |= 0x02;
+		break;
+	case 20:
+		byte |= 0x06;
+		break;
+	case 6:
+		byte |= 0x01;
+		break;
+	case 10:
+		byte |= 0x05;
+		break;
+	case 1:
+		byte |= 0x03;
+		break;
+	case 11:
+		byte |= 0x07;
+		break;
+	}
+
+	ret = i2c_smbus_write_byte(client, byte);
+	if (ret) {
+		v4l2_dbg(1, debug, sd,
+			"i2c_smbus_write_byte() failed, ret:%d\n", ret);
+		return -EIO;
+	}
+	return ret;
+}
+
+static int tea6415c_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_TEA6415C, 0);
+}
+
+/* ----------------------------------------------------------------------- */
+
+static const struct v4l2_subdev_core_ops tea6415c_core_ops = {
+	.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,
+};
+
+static int tea6415c_probe(struct i2c_client *client,
+			  const struct i2c_device_id *id)
+{
+	struct v4l2_subdev *sd;
+
+	/* let's see whether this adapter can support what we need */
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WRITE_BYTE))
+		return -EIO;
+
+	v4l_info(client, "chip found @ 0x%x (%s)\n",
+			client->addr << 1, client->adapter->name);
+	sd = kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
+	if (sd == NULL)
+		return -ENOMEM;
+	v4l2_i2c_subdev_init(sd, client, &tea6415c_ops);
+	return 0;
+}
+
+static int tea6415c_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+
+	v4l2_device_unregister_subdev(sd);
+	kfree(sd);
+	return 0;
+}
+
+static const struct i2c_device_id tea6415c_id[] = {
+	{ "tea6415c", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, tea6415c_id);
+
+static struct i2c_driver tea6415c_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "tea6415c",
+	},
+	.probe		= tea6415c_probe,
+	.remove		= tea6415c_remove,
+	.id_table	= tea6415c_id,
+};
+
+module_i2c_driver(tea6415c_driver);
diff --git a/drivers/media/i2c/tea6415c.h b/drivers/media/i2c/tea6415c.h
new file mode 100644
index 0000000..3a47d69
--- /dev/null
+++ b/drivers/media/i2c/tea6415c.h
@@ -0,0 +1,27 @@
+#ifndef __INCLUDED_TEA6415C__
+#define __INCLUDED_TEA6415C__
+
+/* 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
+   a "virtual" pin-order. */
+
+/* input pins */
+#define TEA6415C_OUTPUT1 18
+#define TEA6415C_OUTPUT2 14
+#define TEA6415C_OUTPUT3 16
+#define TEA6415C_OUTPUT4 17
+#define TEA6415C_OUTPUT5 13
+#define TEA6415C_OUTPUT6 15
+
+/* output pins */
+#define TEA6415C_INPUT1 5
+#define TEA6415C_INPUT2 8
+#define TEA6415C_INPUT3 3
+#define TEA6415C_INPUT4 20
+#define TEA6415C_INPUT5 6
+#define TEA6415C_INPUT6 10
+#define TEA6415C_INPUT7 1
+#define TEA6415C_INPUT8 11
+
+#endif
diff --git a/drivers/media/i2c/tea6420.c b/drivers/media/i2c/tea6420.c
new file mode 100644
index 0000000..3875721
--- /dev/null
+++ b/drivers/media/i2c/tea6420.c
@@ -0,0 +1,169 @@
+ /*
+    tea6420 - i2c-driver for the tea6420 by SGS Thomson
+
+    Copyright (C) 1998-2003 Michael Hunold <michael@mihu.de>
+    Copyright (C) 2008 Hans Verkuil <hverkuil@xs4all.nl>
+
+    The tea6420 is a bus controlled audio-matrix with 5 stereo inputs,
+    4 stereo outputs and gain control for each output.
+    It is cascadable, i.e. it can be found at the addresses 0x98
+    and 0x9a on the i2c-bus.
+
+    For detailed informations download the specifications directly
+    from SGS Thomson at http://www.st.com
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+  */
+
+
+#include <linux/module.h>
+#include <linux/ioctl.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-chip-ident.h>
+#include "tea6420.h"
+
+MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
+MODULE_DESCRIPTION("tea6420 driver");
+MODULE_LICENSE("GPL");
+
+static int debug;
+module_param(debug, int, 0644);
+
+MODULE_PARM_DESC(debug, "Debug level (0-1)");
+
+
+/* make a connection between the input 'i' and the output 'o'
+   with gain 'g' (note: i = 6 means 'mute') */
+static int tea6420_s_routing(struct v4l2_subdev *sd,
+			     u32 i, u32 o, u32 config)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	int g = (o >> 4) & 0xf;
+	u8 byte;
+	int ret;
+
+	o &= 0xf;
+	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 -EINVAL;
+
+	byte = ((o - 1) << 5);
+	byte |= (i - 1);
+
+	/* to understand this, have a look at the tea6420-specs (p.5) */
+	switch (g) {
+	case 0:
+		byte |= (3 << 3);
+		break;
+	case 2:
+		byte |= (2 << 3);
+		break;
+	case 4:
+		byte |= (1 << 3);
+		break;
+	case 6:
+		break;
+	}
+
+	ret = i2c_smbus_write_byte(client, byte);
+	if (ret) {
+		v4l2_dbg(1, debug, sd,
+			"i2c_smbus_write_byte() failed, ret:%d\n", ret);
+		return -EIO;
+	}
+	return 0;
+}
+
+static int tea6420_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_TEA6420, 0);
+}
+
+/* ----------------------------------------------------------------------- */
+
+static const struct v4l2_subdev_core_ops tea6420_core_ops = {
+	.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,
+};
+
+static int tea6420_probe(struct i2c_client *client,
+			  const struct i2c_device_id *id)
+{
+	struct v4l2_subdev *sd;
+	int err, i;
+
+	/* let's see whether this adapter can support what we need */
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WRITE_BYTE))
+		return -EIO;
+
+	v4l_info(client, "chip found @ 0x%x (%s)\n",
+			client->addr << 1, client->adapter->name);
+
+	sd = kzalloc(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_s_routing(sd, 6, i, 0);
+	if (err) {
+		v4l_dbg(1, debug, client, "could not initialize tea6420\n");
+		return -ENODEV;
+	}
+	return 0;
+}
+
+static int tea6420_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+
+	v4l2_device_unregister_subdev(sd);
+	kfree(sd);
+	return 0;
+}
+
+static const struct i2c_device_id tea6420_id[] = {
+	{ "tea6420", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, tea6420_id);
+
+static struct i2c_driver tea6420_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "tea6420",
+	},
+	.probe		= tea6420_probe,
+	.remove		= tea6420_remove,
+	.id_table	= tea6420_id,
+};
+
+module_i2c_driver(tea6420_driver);
diff --git a/drivers/media/i2c/tea6420.h b/drivers/media/i2c/tea6420.h
new file mode 100644
index 0000000..4aa3edb
--- /dev/null
+++ b/drivers/media/i2c/tea6420.h
@@ -0,0 +1,24 @@
+#ifndef __INCLUDED_TEA6420__
+#define __INCLUDED_TEA6420__
+
+/* input pins */
+#define TEA6420_OUTPUT1 1
+#define TEA6420_OUTPUT2 2
+#define TEA6420_OUTPUT3 3
+#define TEA6420_OUTPUT4 4
+
+/* 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
+
+/* 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/i2c/ths7303.c b/drivers/media/i2c/ths7303.c
new file mode 100644
index 0000000..e5c0eed
--- /dev/null
+++ b/drivers/media/i2c/ths7303.c
@@ -0,0 +1,140 @@
+/*
+ * ths7303- THS7303 Video Amplifier driver
+ *
+ * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed .as is. WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/ctype.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/uaccess.h>
+#include <linux/videodev2.h>
+
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+#include <media/v4l2-chip-ident.h>
+
+MODULE_DESCRIPTION("TI THS7303 video amplifier driver");
+MODULE_AUTHOR("Chaithrika U S");
+MODULE_LICENSE("GPL");
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Debug level 0-1");
+
+/* following function is used to set ths7303 */
+static int ths7303_setvalue(struct v4l2_subdev *sd, v4l2_std_id std)
+{
+	int err = 0;
+	u8 val;
+	struct i2c_client *client;
+
+	client = v4l2_get_subdevdata(sd);
+
+	if (std & (V4L2_STD_ALL & ~V4L2_STD_SECAM)) {
+		val = 0x02;
+		v4l2_dbg(1, debug, sd, "setting value for SDTV format\n");
+	} else {
+		val = 0x00;
+		v4l2_dbg(1, debug, sd, "disabling all channels\n");
+	}
+
+	err |= i2c_smbus_write_byte_data(client, 0x01, val);
+	err |= i2c_smbus_write_byte_data(client, 0x02, val);
+	err |= i2c_smbus_write_byte_data(client, 0x03, val);
+
+	if (err)
+		v4l2_err(sd, "write failed\n");
+
+	return err;
+}
+
+static int ths7303_s_std_output(struct v4l2_subdev *sd, v4l2_std_id norm)
+{
+	return ths7303_setvalue(sd, norm);
+}
+
+static int ths7303_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_THS7303, 0);
+}
+
+static const struct v4l2_subdev_video_ops ths7303_video_ops = {
+	.s_std_output	= ths7303_s_std_output,
+};
+
+static const struct v4l2_subdev_core_ops ths7303_core_ops = {
+	.g_chip_ident = ths7303_g_chip_ident,
+};
+
+static const struct v4l2_subdev_ops ths7303_ops = {
+	.core	= &ths7303_core_ops,
+	.video 	= &ths7303_video_ops,
+};
+
+static int ths7303_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	struct v4l2_subdev *sd;
+	v4l2_std_id std_id = V4L2_STD_NTSC;
+
+	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);
+
+	sd = kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
+	if (sd == NULL)
+		return -ENOMEM;
+
+	v4l2_i2c_subdev_init(sd, client, &ths7303_ops);
+
+	return ths7303_setvalue(sd, std_id);
+}
+
+static int ths7303_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+
+	v4l2_device_unregister_subdev(sd);
+	kfree(sd);
+
+	return 0;
+}
+
+static const struct i2c_device_id ths7303_id[] = {
+	{"ths7303", 0},
+	{},
+};
+
+MODULE_DEVICE_TABLE(i2c, ths7303_id);
+
+static struct i2c_driver ths7303_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "ths7303",
+	},
+	.probe		= ths7303_probe,
+	.remove		= ths7303_remove,
+	.id_table	= ths7303_id,
+};
+
+module_i2c_driver(ths7303_driver);
diff --git a/drivers/media/i2c/tlv320aic23b.c b/drivers/media/i2c/tlv320aic23b.c
new file mode 100644
index 0000000..809a75a
--- /dev/null
+++ b/drivers/media/i2c/tlv320aic23b.c
@@ -0,0 +1,230 @@
+/*
+ * tlv320aic23b - driver version 0.0.1
+ *
+ * Copyright (C) 2006 Scott Alfter <salfter@ssai.us>
+ *
+ * Based on wm8775 driver
+ *
+ * Copyright (C) 2004 Ulf Eklund <ivtv at eklund.to>
+ * Copyright (C) 2005 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.
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/ioctl.h>
+#include <asm/uaccess.h>
+#include <linux/i2c.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ctrls.h>
+
+MODULE_DESCRIPTION("tlv320aic23b driver");
+MODULE_AUTHOR("Scott Alfter, Ulf Eklund, Hans Verkuil");
+MODULE_LICENSE("GPL");
+
+
+/* ----------------------------------------------------------------------- */
+
+struct tlv320aic23b_state {
+	struct v4l2_subdev sd;
+	struct v4l2_ctrl_handler hdl;
+};
+
+static inline struct tlv320aic23b_state *to_state(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct tlv320aic23b_state, sd);
+}
+
+static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
+{
+	return &container_of(ctrl->handler, struct tlv320aic23b_state, hdl)->sd;
+}
+
+static int tlv320aic23b_write(struct v4l2_subdev *sd, int reg, u16 val)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	int i;
+
+	if ((reg < 0 || reg > 9) && (reg != 15)) {
+		v4l2_err(sd, "Invalid register R%d\n", reg);
+		return -1;
+	}
+
+	for (i = 0; i < 3; i++)
+		if (i2c_smbus_write_byte_data(client,
+				(reg << 1) | (val >> 8), val & 0xff) == 0)
+			return 0;
+	v4l2_err(sd, "I2C: cannot write %03x to register R%d\n", val, reg);
+	return -1;
+}
+
+static int tlv320aic23b_s_clock_freq(struct v4l2_subdev *sd, u32 freq)
+{
+	switch (freq) {
+	case 32000: /* set sample rate to 32 kHz */
+		tlv320aic23b_write(sd, 8, 0x018);
+		break;
+	case 44100: /* set sample rate to 44.1 kHz */
+		tlv320aic23b_write(sd, 8, 0x022);
+		break;
+	case 48000: /* set sample rate to 48 kHz */
+		tlv320aic23b_write(sd, 8, 0x000);
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int tlv320aic23b_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct v4l2_subdev *sd = to_sd(ctrl);
+
+	switch (ctrl->id) {
+	case V4L2_CID_AUDIO_MUTE:
+		tlv320aic23b_write(sd, 0, 0x180); /* mute both channels */
+		/* set gain on both channels to +3.0 dB */
+		if (!ctrl->val)
+			tlv320aic23b_write(sd, 0, 0x119);
+		return 0;
+	}
+	return -EINVAL;
+}
+
+static int tlv320aic23b_log_status(struct v4l2_subdev *sd)
+{
+	struct tlv320aic23b_state *state = to_state(sd);
+
+	v4l2_ctrl_handler_log_status(&state->hdl, sd->name);
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static const struct v4l2_ctrl_ops tlv320aic23b_ctrl_ops = {
+	.s_ctrl = tlv320aic23b_s_ctrl,
+};
+
+static const struct v4l2_subdev_core_ops tlv320aic23b_core_ops = {
+	.log_status = tlv320aic23b_log_status,
+	.g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
+	.try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
+	.s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
+	.g_ctrl = v4l2_subdev_g_ctrl,
+	.s_ctrl = v4l2_subdev_s_ctrl,
+	.queryctrl = v4l2_subdev_queryctrl,
+	.querymenu = v4l2_subdev_querymenu,
+};
+
+static const struct v4l2_subdev_audio_ops tlv320aic23b_audio_ops = {
+	.s_clock_freq = tlv320aic23b_s_clock_freq,
+};
+
+static const struct v4l2_subdev_ops tlv320aic23b_ops = {
+	.core = &tlv320aic23b_core_ops,
+	.audio = &tlv320aic23b_audio_ops,
+};
+
+/* ----------------------------------------------------------------------- */
+
+/* i2c implementation */
+
+/*
+ * Generic i2c probe
+ * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
+ */
+
+static int tlv320aic23b_probe(struct i2c_client *client,
+			      const struct i2c_device_id *id)
+{
+	struct tlv320aic23b_state *state;
+	struct v4l2_subdev *sd;
+
+	/* Check if the adapter supports the needed features */
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		return -EIO;
+
+	v4l_info(client, "chip found @ 0x%x (%s)\n",
+			client->addr << 1, client->adapter->name);
+
+	state = kzalloc(sizeof(struct tlv320aic23b_state), GFP_KERNEL);
+	if (state == NULL)
+		return -ENOMEM;
+	sd = &state->sd;
+	v4l2_i2c_subdev_init(sd, client, &tlv320aic23b_ops);
+
+	/* Initialize tlv320aic23b */
+
+	/* RESET */
+	tlv320aic23b_write(sd, 15, 0x000);
+	/* turn off DAC & mic input */
+	tlv320aic23b_write(sd, 6, 0x00A);
+	/* left-justified, 24-bit, master mode */
+	tlv320aic23b_write(sd, 7, 0x049);
+	/* set gain on both channels to +3.0 dB */
+	tlv320aic23b_write(sd, 0, 0x119);
+	/* set sample rate to 48 kHz */
+	tlv320aic23b_write(sd, 8, 0x000);
+	/* activate digital interface */
+	tlv320aic23b_write(sd, 9, 0x001);
+
+	v4l2_ctrl_handler_init(&state->hdl, 1);
+	v4l2_ctrl_new_std(&state->hdl, &tlv320aic23b_ctrl_ops,
+			V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0);
+	sd->ctrl_handler = &state->hdl;
+	if (state->hdl.error) {
+		int err = state->hdl.error;
+
+		v4l2_ctrl_handler_free(&state->hdl);
+		kfree(state);
+		return err;
+	}
+	v4l2_ctrl_handler_setup(&state->hdl);
+	return 0;
+}
+
+static int tlv320aic23b_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct tlv320aic23b_state *state = to_state(sd);
+
+	v4l2_device_unregister_subdev(sd);
+	v4l2_ctrl_handler_free(&state->hdl);
+	kfree(state);
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static const struct i2c_device_id tlv320aic23b_id[] = {
+	{ "tlv320aic23b", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, tlv320aic23b_id);
+
+static struct i2c_driver tlv320aic23b_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "tlv320aic23b",
+	},
+	.probe		= tlv320aic23b_probe,
+	.remove		= tlv320aic23b_remove,
+	.id_table	= tlv320aic23b_id,
+};
+
+module_i2c_driver(tlv320aic23b_driver);
diff --git a/drivers/media/i2c/tvaudio.c b/drivers/media/i2c/tvaudio.c
new file mode 100644
index 0000000..321b315
--- /dev/null
+++ b/drivers/media/i2c/tvaudio.c
@@ -0,0 +1,2118 @@
+/*
+ * Driver for simple i2c audio chips.
+ *
+ * Copyright (c) 2000 Gerd Knorr
+ * based on code by:
+ *   Eric Sandeen (eric_sandeen@bigfoot.com)
+ *   Steve VanDeBogart (vandebo@uclink.berkeley.edu)
+ *   Greg Alexander (galexand@acm.org)
+ *
+ * Copyright(c) 2005-2008 Mauro Carvalho Chehab
+ *	- Some cleanups, code fixes, etc
+ *	- Convert it to V4L2 API
+ *
+ * This code is placed under the terms of the GNU General Public License
+ *
+ * OPTIONS:
+ *   debug - set to 1 if you'd like to see debug messages
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/videodev2.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/kthread.h>
+#include <linux/freezer.h>
+
+#include <media/tvaudio.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-chip-ident.h>
+
+#include <media/i2c-addr.h>
+
+/* ---------------------------------------------------------------------- */
+/* insmod args                                                            */
+
+static int debug;	/* insmod parameter */
+module_param(debug, int, 0644);
+
+MODULE_DESCRIPTION("device driver for various i2c TV sound decoder / audiomux chips");
+MODULE_AUTHOR("Eric Sandeen, Steve VanDeBogart, Greg Alexander, Gerd Knorr");
+MODULE_LICENSE("GPL");
+
+#define UNSET    (-1U)
+
+/* ---------------------------------------------------------------------- */
+/* our structs                                                            */
+
+#define MAXREGS 256
+
+struct CHIPSTATE;
+typedef int  (*getvalue)(int);
+typedef int  (*checkit)(struct CHIPSTATE*);
+typedef int  (*initialize)(struct CHIPSTATE*);
+typedef int  (*getrxsubchans)(struct CHIPSTATE *);
+typedef void (*setaudmode)(struct CHIPSTATE*, int mode);
+
+/* i2c command */
+typedef struct AUDIOCMD {
+	int             count;             /* # of bytes to send */
+	unsigned char   bytes[MAXREGS+1];  /* addr, data, data, ... */
+} audiocmd;
+
+/* chip description */
+struct CHIPDESC {
+	char       *name;             /* chip name         */
+	int        addr_lo, addr_hi;  /* i2c address range */
+	int        registers;         /* # of registers    */
+
+	int        *insmodopt;
+	checkit    checkit;
+	initialize initialize;
+	int        flags;
+#define CHIP_HAS_VOLUME      1
+#define CHIP_HAS_BASSTREBLE  2
+#define CHIP_HAS_INPUTSEL    4
+#define CHIP_NEED_CHECKMODE  8
+
+	/* various i2c command sequences */
+	audiocmd   init;
+
+	/* which register has which value */
+	int    leftreg,rightreg,treblereg,bassreg;
+
+	/* initialize with (defaults to 65535/65535/32768/32768 */
+	int    leftinit,rightinit,trebleinit,bassinit;
+
+	/* functions to convert the values (v4l -> chip) */
+	getvalue volfunc,treblefunc,bassfunc;
+
+	/* get/set mode */
+	getrxsubchans	getrxsubchans;
+	setaudmode	setaudmode;
+
+	/* input switch register + values for v4l inputs */
+	int  inputreg;
+	int  inputmap[4];
+	int  inputmute;
+	int  inputmask;
+};
+
+/* current state of the chip */
+struct CHIPSTATE {
+	struct v4l2_subdev sd;
+
+	/* chip-specific description - should point to
+	   an entry at CHIPDESC table */
+	struct CHIPDESC *desc;
+
+	/* shadow register set */
+	audiocmd   shadow;
+
+	/* current settings */
+	__u16 left, right, treble, bass, muted;
+	int prevmode;
+	int radio;
+	int input;
+
+	/* thread */
+	struct task_struct   *thread;
+	struct timer_list    wt;
+	int 		     audmode;
+};
+
+static inline struct CHIPSTATE *to_state(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct CHIPSTATE, sd);
+}
+
+
+/* ---------------------------------------------------------------------- */
+/* i2c I/O functions                                                      */
+
+static int chip_write(struct CHIPSTATE *chip, int subaddr, int val)
+{
+	struct v4l2_subdev *sd = &chip->sd;
+	struct i2c_client *c = v4l2_get_subdevdata(sd);
+	unsigned char buffer[2];
+
+	if (subaddr < 0) {
+		v4l2_dbg(1, debug, sd, "chip_write: 0x%x\n", val);
+		chip->shadow.bytes[1] = val;
+		buffer[0] = val;
+		if (1 != i2c_master_send(c, buffer, 1)) {
+			v4l2_warn(sd, "I/O error (write 0x%x)\n", val);
+			return -1;
+		}
+	} else {
+		if (subaddr + 1 >= ARRAY_SIZE(chip->shadow.bytes)) {
+			v4l2_info(sd,
+				"Tried to access a non-existent register: %d\n",
+				subaddr);
+			return -EINVAL;
+		}
+
+		v4l2_dbg(1, debug, sd, "chip_write: reg%d=0x%x\n",
+			subaddr, val);
+		chip->shadow.bytes[subaddr+1] = val;
+		buffer[0] = subaddr;
+		buffer[1] = val;
+		if (2 != i2c_master_send(c, buffer, 2)) {
+			v4l2_warn(sd, "I/O error (write reg%d=0x%x)\n",
+				subaddr, val);
+			return -1;
+		}
+	}
+	return 0;
+}
+
+static int chip_write_masked(struct CHIPSTATE *chip,
+			     int subaddr, int val, int mask)
+{
+	struct v4l2_subdev *sd = &chip->sd;
+
+	if (mask != 0) {
+		if (subaddr < 0) {
+			val = (chip->shadow.bytes[1] & ~mask) | (val & mask);
+		} else {
+			if (subaddr + 1 >= ARRAY_SIZE(chip->shadow.bytes)) {
+				v4l2_info(sd,
+					"Tried to access a non-existent register: %d\n",
+					subaddr);
+				return -EINVAL;
+			}
+
+			val = (chip->shadow.bytes[subaddr+1] & ~mask) | (val & mask);
+		}
+	}
+	return chip_write(chip, subaddr, val);
+}
+
+static int chip_read(struct CHIPSTATE *chip)
+{
+	struct v4l2_subdev *sd = &chip->sd;
+	struct i2c_client *c = v4l2_get_subdevdata(sd);
+	unsigned char buffer;
+
+	if (1 != i2c_master_recv(c, &buffer, 1)) {
+		v4l2_warn(sd, "I/O error (read)\n");
+		return -1;
+	}
+	v4l2_dbg(1, debug, sd, "chip_read: 0x%x\n", buffer);
+	return buffer;
+}
+
+static int chip_read2(struct CHIPSTATE *chip, int subaddr)
+{
+	struct v4l2_subdev *sd = &chip->sd;
+	struct i2c_client *c = v4l2_get_subdevdata(sd);
+	unsigned char write[1];
+	unsigned char read[1];
+	struct i2c_msg msgs[2] = {
+		{ c->addr, 0,        1, write },
+		{ c->addr, I2C_M_RD, 1, read  }
+	};
+
+	write[0] = subaddr;
+
+	if (2 != i2c_transfer(c->adapter, msgs, 2)) {
+		v4l2_warn(sd, "I/O error (read2)\n");
+		return -1;
+	}
+	v4l2_dbg(1, debug, sd, "chip_read2: reg%d=0x%x\n",
+		subaddr, read[0]);
+	return read[0];
+}
+
+static int chip_cmd(struct CHIPSTATE *chip, char *name, audiocmd *cmd)
+{
+	struct v4l2_subdev *sd = &chip->sd;
+	struct i2c_client *c = v4l2_get_subdevdata(sd);
+	int i;
+
+	if (0 == cmd->count)
+		return 0;
+
+	if (cmd->count + cmd->bytes[0] - 1 >= ARRAY_SIZE(chip->shadow.bytes)) {
+		v4l2_info(sd,
+			 "Tried to access a non-existent register range: %d to %d\n",
+			 cmd->bytes[0] + 1, cmd->bytes[0] + cmd->count - 1);
+		return -EINVAL;
+	}
+
+	/* FIXME: it seems that the shadow bytes are wrong bellow !*/
+
+	/* update our shadow register set; print bytes if (debug > 0) */
+	v4l2_dbg(1, debug, sd, "chip_cmd(%s): reg=%d, data:",
+		name, cmd->bytes[0]);
+	for (i = 1; i < cmd->count; i++) {
+		if (debug)
+			printk(KERN_CONT " 0x%x", cmd->bytes[i]);
+		chip->shadow.bytes[i+cmd->bytes[0]] = cmd->bytes[i];
+	}
+	if (debug)
+		printk(KERN_CONT "\n");
+
+	/* send data to the chip */
+	if (cmd->count != i2c_master_send(c, cmd->bytes, cmd->count)) {
+		v4l2_warn(sd, "I/O error (%s)\n", name);
+		return -1;
+	}
+	return 0;
+}
+
+/* ---------------------------------------------------------------------- */
+/* kernel thread for doing i2c stuff asyncronly
+ *   right now it is used only to check the audio mode (mono/stereo/whatever)
+ *   some time after switching to another TV channel, then turn on stereo
+ *   if available, ...
+ */
+
+static void chip_thread_wake(unsigned long data)
+{
+	struct CHIPSTATE *chip = (struct CHIPSTATE*)data;
+	wake_up_process(chip->thread);
+}
+
+static int chip_thread(void *data)
+{
+	struct CHIPSTATE *chip = data;
+	struct CHIPDESC  *desc = chip->desc;
+	struct v4l2_subdev *sd = &chip->sd;
+	int mode, selected;
+
+	v4l2_dbg(1, debug, sd, "thread started\n");
+	set_freezable();
+	for (;;) {
+		set_current_state(TASK_INTERRUPTIBLE);
+		if (!kthread_should_stop())
+			schedule();
+		set_current_state(TASK_RUNNING);
+		try_to_freeze();
+		if (kthread_should_stop())
+			break;
+		v4l2_dbg(1, debug, sd, "thread wakeup\n");
+
+		/* don't do anything for radio */
+		if (chip->radio)
+			continue;
+
+		/* have a look what's going on */
+		mode = desc->getrxsubchans(chip);
+		if (mode == chip->prevmode)
+			continue;
+
+		/* chip detected a new audio mode - set it */
+		v4l2_dbg(1, debug, sd, "thread checkmode\n");
+
+		chip->prevmode = mode;
+
+		selected = V4L2_TUNER_MODE_MONO;
+		switch (chip->audmode) {
+		case V4L2_TUNER_MODE_MONO:
+			if (mode & V4L2_TUNER_SUB_LANG1)
+				selected = V4L2_TUNER_MODE_LANG1;
+			break;
+		case V4L2_TUNER_MODE_STEREO:
+		case V4L2_TUNER_MODE_LANG1:
+			if (mode & V4L2_TUNER_SUB_LANG1)
+				selected = V4L2_TUNER_MODE_LANG1;
+			else if (mode & V4L2_TUNER_SUB_STEREO)
+				selected = V4L2_TUNER_MODE_STEREO;
+			break;
+		case V4L2_TUNER_MODE_LANG2:
+			if (mode & V4L2_TUNER_SUB_LANG2)
+				selected = V4L2_TUNER_MODE_LANG2;
+			else if (mode & V4L2_TUNER_SUB_STEREO)
+				selected = V4L2_TUNER_MODE_STEREO;
+			break;
+		case V4L2_TUNER_MODE_LANG1_LANG2:
+			if (mode & V4L2_TUNER_SUB_LANG2)
+				selected = V4L2_TUNER_MODE_LANG1_LANG2;
+			else if (mode & V4L2_TUNER_SUB_STEREO)
+				selected = V4L2_TUNER_MODE_STEREO;
+		}
+		desc->setaudmode(chip, selected);
+
+		/* schedule next check */
+		mod_timer(&chip->wt, jiffies+msecs_to_jiffies(2000));
+	}
+
+	v4l2_dbg(1, debug, sd, "thread exiting\n");
+	return 0;
+}
+
+/* ---------------------------------------------------------------------- */
+/* audio chip descriptions - defines+functions for tda9840                */
+
+#define TDA9840_SW         0x00
+#define TDA9840_LVADJ      0x02
+#define TDA9840_STADJ      0x03
+#define TDA9840_TEST       0x04
+
+#define TDA9840_MONO       0x10
+#define TDA9840_STEREO     0x2a
+#define TDA9840_DUALA      0x12
+#define TDA9840_DUALB      0x1e
+#define TDA9840_DUALAB     0x1a
+#define TDA9840_DUALBA     0x16
+#define TDA9840_EXTERNAL   0x7a
+
+#define TDA9840_DS_DUAL    0x20 /* Dual sound identified          */
+#define TDA9840_ST_STEREO  0x40 /* Stereo sound identified        */
+#define TDA9840_PONRES     0x80 /* Power-on reset detected if = 1 */
+
+#define TDA9840_TEST_INT1SN 0x1 /* Integration time 0.5s when set */
+#define TDA9840_TEST_INTFU 0x02 /* Disables integrator function */
+
+static int tda9840_getrxsubchans(struct CHIPSTATE *chip)
+{
+	struct v4l2_subdev *sd = &chip->sd;
+	int val, mode;
+
+	val = chip_read(chip);
+	mode = V4L2_TUNER_SUB_MONO;
+	if (val & TDA9840_DS_DUAL)
+		mode |= V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
+	if (val & TDA9840_ST_STEREO)
+		mode = V4L2_TUNER_SUB_STEREO;
+
+	v4l2_dbg(1, debug, sd,
+		"tda9840_getrxsubchans(): raw chip read: %d, return: %d\n",
+		val, mode);
+	return mode;
+}
+
+static void tda9840_setaudmode(struct CHIPSTATE *chip, int mode)
+{
+	int update = 1;
+	int t = chip->shadow.bytes[TDA9840_SW + 1] & ~0x7e;
+
+	switch (mode) {
+	case V4L2_TUNER_MODE_MONO:
+		t |= TDA9840_MONO;
+		break;
+	case V4L2_TUNER_MODE_STEREO:
+		t |= TDA9840_STEREO;
+		break;
+	case V4L2_TUNER_MODE_LANG1:
+		t |= TDA9840_DUALA;
+		break;
+	case V4L2_TUNER_MODE_LANG2:
+		t |= TDA9840_DUALB;
+		break;
+	case V4L2_TUNER_MODE_LANG1_LANG2:
+		t |= TDA9840_DUALAB;
+		break;
+	default:
+		update = 0;
+	}
+
+	if (update)
+		chip_write(chip, TDA9840_SW, t);
+}
+
+static int tda9840_checkit(struct CHIPSTATE *chip)
+{
+	int rc;
+	rc = chip_read(chip);
+	/* lower 5 bits should be 0 */
+	return ((rc & 0x1f) == 0) ? 1 : 0;
+}
+
+/* ---------------------------------------------------------------------- */
+/* audio chip descriptions - defines+functions for tda985x                */
+
+/* subaddresses for TDA9855 */
+#define TDA9855_VR	0x00 /* Volume, right */
+#define TDA9855_VL	0x01 /* Volume, left */
+#define TDA9855_BA	0x02 /* Bass */
+#define TDA9855_TR	0x03 /* Treble */
+#define TDA9855_SW	0x04 /* Subwoofer - not connected on DTV2000 */
+
+/* subaddresses for TDA9850 */
+#define TDA9850_C4	0x04 /* Control 1 for TDA9850 */
+
+/* subaddesses for both chips */
+#define TDA985x_C5	0x05 /* Control 2 for TDA9850, Control 1 for TDA9855 */
+#define TDA985x_C6	0x06 /* Control 3 for TDA9850, Control 2 for TDA9855 */
+#define TDA985x_C7	0x07 /* Control 4 for TDA9850, Control 3 for TDA9855 */
+#define TDA985x_A1	0x08 /* Alignment 1 for both chips */
+#define TDA985x_A2	0x09 /* Alignment 2 for both chips */
+#define TDA985x_A3	0x0a /* Alignment 3 for both chips */
+
+/* Masks for bits in TDA9855 subaddresses */
+/* 0x00 - VR in TDA9855 */
+/* 0x01 - VL in TDA9855 */
+/* lower 7 bits control gain from -71dB (0x28) to 16dB (0x7f)
+ * in 1dB steps - mute is 0x27 */
+
+
+/* 0x02 - BA in TDA9855 */
+/* lower 5 bits control bass gain from -12dB (0x06) to 16.5dB (0x19)
+ * in .5dB steps - 0 is 0x0E */
+
+
+/* 0x03 - TR in TDA9855 */
+/* 4 bits << 1 control treble gain from -12dB (0x3) to 12dB (0xb)
+ * in 3dB steps - 0 is 0x7 */
+
+/* Masks for bits in both chips' subaddresses */
+/* 0x04 - SW in TDA9855, C4/Control 1 in TDA9850 */
+/* Unique to TDA9855: */
+/* 4 bits << 2 control subwoofer/surround gain from -14db (0x1) to 14db (0xf)
+ * in 3dB steps - mute is 0x0 */
+
+/* Unique to TDA9850: */
+/* lower 4 bits control stereo noise threshold, over which stereo turns off
+ * set to values of 0x00 through 0x0f for Ster1 through Ster16 */
+
+
+/* 0x05 - C5 - Control 1 in TDA9855 , Control 2 in TDA9850*/
+/* Unique to TDA9855: */
+#define TDA9855_MUTE	1<<7 /* GMU, Mute at outputs */
+#define TDA9855_AVL	1<<6 /* AVL, Automatic Volume Level */
+#define TDA9855_LOUD	1<<5 /* Loudness, 1==off */
+#define TDA9855_SUR	1<<3 /* Surround / Subwoofer 1==.5(L-R) 0==.5(L+R) */
+			     /* Bits 0 to 3 select various combinations
+			      * of line in and line out, only the
+			      * interesting ones are defined */
+#define TDA9855_EXT	1<<2 /* Selects inputs LIR and LIL.  Pins 41 & 12 */
+#define TDA9855_INT	0    /* Selects inputs LOR and LOL.  (internal) */
+
+/* Unique to TDA9850:  */
+/* lower 4 bits contol SAP noise threshold, over which SAP turns off
+ * set to values of 0x00 through 0x0f for SAP1 through SAP16 */
+
+
+/* 0x06 - C6 - Control 2 in TDA9855, Control 3 in TDA9850 */
+/* Common to TDA9855 and TDA9850: */
+#define TDA985x_SAP	3<<6 /* Selects SAP output, mute if not received */
+#define TDA985x_MONOSAP	2<<6 /* Selects Mono on left, SAP on right */
+#define TDA985x_STEREO	1<<6 /* Selects Stereo ouput, mono if not received */
+#define TDA985x_MONO	0    /* Forces Mono output */
+#define TDA985x_LMU	1<<3 /* Mute (LOR/LOL for 9855, OUTL/OUTR for 9850) */
+
+/* Unique to TDA9855: */
+#define TDA9855_TZCM	1<<5 /* If set, don't mute till zero crossing */
+#define TDA9855_VZCM	1<<4 /* If set, don't change volume till zero crossing*/
+#define TDA9855_LINEAR	0    /* Linear Stereo */
+#define TDA9855_PSEUDO	1    /* Pseudo Stereo */
+#define TDA9855_SPAT_30	2    /* Spatial Stereo, 30% anti-phase crosstalk */
+#define TDA9855_SPAT_50	3    /* Spatial Stereo, 52% anti-phase crosstalk */
+#define TDA9855_E_MONO	7    /* Forced mono - mono select elseware, so useless*/
+
+/* 0x07 - C7 - Control 3 in TDA9855, Control 4 in TDA9850 */
+/* Common to both TDA9855 and TDA9850: */
+/* lower 4 bits control input gain from -3.5dB (0x0) to 4dB (0xF)
+ * in .5dB steps -  0dB is 0x7 */
+
+/* 0x08, 0x09 - A1 and A2 (read/write) */
+/* Common to both TDA9855 and TDA9850: */
+/* lower 5 bites are wideband and spectral expander alignment
+ * from 0x00 to 0x1f - nominal at 0x0f and 0x10 (read/write) */
+#define TDA985x_STP	1<<5 /* Stereo Pilot/detect (read-only) */
+#define TDA985x_SAPP	1<<6 /* SAP Pilot/detect (read-only) */
+#define TDA985x_STS	1<<7 /* Stereo trigger 1= <35mV 0= <30mV (write-only)*/
+
+/* 0x0a - A3 */
+/* Common to both TDA9855 and TDA9850: */
+/* lower 3 bits control timing current for alignment: -30% (0x0), -20% (0x1),
+ * -10% (0x2), nominal (0x3), +10% (0x6), +20% (0x5), +30% (0x4) */
+#define TDA985x_ADJ	1<<7 /* Stereo adjust on/off (wideband and spectral */
+
+static int tda9855_volume(int val) { return val/0x2e8+0x27; }
+static int tda9855_bass(int val)   { return val/0xccc+0x06; }
+static int tda9855_treble(int val) { return (val/0x1c71+0x3)<<1; }
+
+static int  tda985x_getrxsubchans(struct CHIPSTATE *chip)
+{
+	int mode, val;
+
+	/* Add mono mode regardless of SAP and stereo */
+	/* Allows forced mono */
+	mode = V4L2_TUNER_SUB_MONO;
+	val = chip_read(chip);
+	if (val & TDA985x_STP)
+		mode = V4L2_TUNER_SUB_STEREO;
+	if (val & TDA985x_SAPP)
+		mode |= V4L2_TUNER_SUB_SAP;
+	return mode;
+}
+
+static void tda985x_setaudmode(struct CHIPSTATE *chip, int mode)
+{
+	int update = 1;
+	int c6 = chip->shadow.bytes[TDA985x_C6+1] & 0x3f;
+
+	switch (mode) {
+	case V4L2_TUNER_MODE_MONO:
+		c6 |= TDA985x_MONO;
+		break;
+	case V4L2_TUNER_MODE_STEREO:
+	case V4L2_TUNER_MODE_LANG1:
+		c6 |= TDA985x_STEREO;
+		break;
+	case V4L2_TUNER_MODE_SAP:
+		c6 |= TDA985x_SAP;
+		break;
+	case V4L2_TUNER_MODE_LANG1_LANG2:
+		c6 |= TDA985x_MONOSAP;
+		break;
+	default:
+		update = 0;
+	}
+	if (update)
+		chip_write(chip,TDA985x_C6,c6);
+}
+
+
+/* ---------------------------------------------------------------------- */
+/* audio chip descriptions - defines+functions for tda9873h               */
+
+/* Subaddresses for TDA9873H */
+
+#define TDA9873_SW	0x00 /* Switching                    */
+#define TDA9873_AD	0x01 /* Adjust                       */
+#define TDA9873_PT	0x02 /* Port                         */
+
+/* Subaddress 0x00: Switching Data
+ * B7..B0:
+ *
+ * B1, B0: Input source selection
+ *  0,  0  internal
+ *  1,  0  external stereo
+ *  0,  1  external mono
+ */
+#define TDA9873_INP_MASK    3
+#define TDA9873_INTERNAL    0
+#define TDA9873_EXT_STEREO  2
+#define TDA9873_EXT_MONO    1
+
+/*    B3, B2: output signal select
+ * B4    : transmission mode
+ *  0, 0, 1   Mono
+ *  1, 0, 0   Stereo
+ *  1, 1, 1   Stereo (reversed channel)
+ *  0, 0, 0   Dual AB
+ *  0, 0, 1   Dual AA
+ *  0, 1, 0   Dual BB
+ *  0, 1, 1   Dual BA
+ */
+
+#define TDA9873_TR_MASK     (7 << 2)
+#define TDA9873_TR_MONO     4
+#define TDA9873_TR_STEREO   1 << 4
+#define TDA9873_TR_REVERSE  ((1 << 3) | (1 << 2))
+#define TDA9873_TR_DUALA    1 << 2
+#define TDA9873_TR_DUALB    1 << 3
+#define TDA9873_TR_DUALAB   0
+
+/* output level controls
+ * B5:  output level switch (0 = reduced gain, 1 = normal gain)
+ * B6:  mute                (1 = muted)
+ * B7:  auto-mute           (1 = auto-mute enabled)
+ */
+
+#define TDA9873_GAIN_NORMAL 1 << 5
+#define TDA9873_MUTE        1 << 6
+#define TDA9873_AUTOMUTE    1 << 7
+
+/* Subaddress 0x01:  Adjust/standard */
+
+/* Lower 4 bits (C3..C0) control stereo adjustment on R channel (-0.6 - +0.7 dB)
+ * Recommended value is +0 dB
+ */
+
+#define	TDA9873_STEREO_ADJ	0x06 /* 0dB gain */
+
+/* Bits C6..C4 control FM stantard
+ * C6, C5, C4
+ *  0,  0,  0   B/G (PAL FM)
+ *  0,  0,  1   M
+ *  0,  1,  0   D/K(1)
+ *  0,  1,  1   D/K(2)
+ *  1,  0,  0   D/K(3)
+ *  1,  0,  1   I
+ */
+#define TDA9873_BG		0
+#define TDA9873_M       1
+#define TDA9873_DK1     2
+#define TDA9873_DK2     3
+#define TDA9873_DK3     4
+#define TDA9873_I       5
+
+/* C7 controls identification response time (1=fast/0=normal)
+ */
+#define TDA9873_IDR_NORM 0
+#define TDA9873_IDR_FAST 1 << 7
+
+
+/* Subaddress 0x02: Port data */
+
+/* E1, E0   free programmable ports P1/P2
+    0,  0   both ports low
+    0,  1   P1 high
+    1,  0   P2 high
+    1,  1   both ports high
+*/
+
+#define TDA9873_PORTS    3
+
+/* E2: test port */
+#define TDA9873_TST_PORT 1 << 2
+
+/* E5..E3 control mono output channel (together with transmission mode bit B4)
+ *
+ * E5 E4 E3 B4     OUTM
+ *  0  0  0  0     mono
+ *  0  0  1  0     DUAL B
+ *  0  1  0  1     mono (from stereo decoder)
+ */
+#define TDA9873_MOUT_MONO   0
+#define TDA9873_MOUT_FMONO  0
+#define TDA9873_MOUT_DUALA  0
+#define TDA9873_MOUT_DUALB  1 << 3
+#define TDA9873_MOUT_ST     1 << 4
+#define TDA9873_MOUT_EXTM   ((1 << 4) | (1 << 3))
+#define TDA9873_MOUT_EXTL   1 << 5
+#define TDA9873_MOUT_EXTR   ((1 << 5) | (1 << 3))
+#define TDA9873_MOUT_EXTLR  ((1 << 5) | (1 << 4))
+#define TDA9873_MOUT_MUTE   ((1 << 5) | (1 << 4) | (1 << 3))
+
+/* Status bits: (chip read) */
+#define TDA9873_PONR        0 /* Power-on reset detected if = 1 */
+#define TDA9873_STEREO      2 /* Stereo sound is identified     */
+#define TDA9873_DUAL        4 /* Dual sound is identified       */
+
+static int tda9873_getrxsubchans(struct CHIPSTATE *chip)
+{
+	struct v4l2_subdev *sd = &chip->sd;
+	int val,mode;
+
+	val = chip_read(chip);
+	mode = V4L2_TUNER_SUB_MONO;
+	if (val & TDA9873_STEREO)
+		mode = V4L2_TUNER_SUB_STEREO;
+	if (val & TDA9873_DUAL)
+		mode |= V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
+	v4l2_dbg(1, debug, sd,
+		"tda9873_getrxsubchans(): raw chip read: %d, return: %d\n",
+		val, mode);
+	return mode;
+}
+
+static void tda9873_setaudmode(struct CHIPSTATE *chip, int mode)
+{
+	struct v4l2_subdev *sd = &chip->sd;
+	int sw_data  = chip->shadow.bytes[TDA9873_SW+1] & ~ TDA9873_TR_MASK;
+	/*	int adj_data = chip->shadow.bytes[TDA9873_AD+1] ; */
+
+	if ((sw_data & TDA9873_INP_MASK) != TDA9873_INTERNAL) {
+		v4l2_dbg(1, debug, sd,
+			 "tda9873_setaudmode(): external input\n");
+		return;
+	}
+
+	v4l2_dbg(1, debug, sd,
+		 "tda9873_setaudmode(): chip->shadow.bytes[%d] = %d\n",
+		 TDA9873_SW+1, chip->shadow.bytes[TDA9873_SW+1]);
+	v4l2_dbg(1, debug, sd, "tda9873_setaudmode(): sw_data  = %d\n",
+		 sw_data);
+
+	switch (mode) {
+	case V4L2_TUNER_MODE_MONO:
+		sw_data |= TDA9873_TR_MONO;
+		break;
+	case V4L2_TUNER_MODE_STEREO:
+		sw_data |= TDA9873_TR_STEREO;
+		break;
+	case V4L2_TUNER_MODE_LANG1:
+		sw_data |= TDA9873_TR_DUALA;
+		break;
+	case V4L2_TUNER_MODE_LANG2:
+		sw_data |= TDA9873_TR_DUALB;
+		break;
+	case V4L2_TUNER_MODE_LANG1_LANG2:
+		sw_data |= TDA9873_TR_DUALAB;
+		break;
+	default:
+		return;
+	}
+
+	chip_write(chip, TDA9873_SW, sw_data);
+	v4l2_dbg(1, debug, sd,
+		"tda9873_setaudmode(): req. mode %d; chip_write: %d\n",
+		mode, sw_data);
+}
+
+static int tda9873_checkit(struct CHIPSTATE *chip)
+{
+	int rc;
+
+	if (-1 == (rc = chip_read2(chip,254)))
+		return 0;
+	return (rc & ~0x1f) == 0x80;
+}
+
+
+/* ---------------------------------------------------------------------- */
+/* audio chip description - defines+functions for tda9874h and tda9874a   */
+/* Dariusz Kowalewski <darekk@automex.pl>                                 */
+
+/* Subaddresses for TDA9874H and TDA9874A (slave rx) */
+#define TDA9874A_AGCGR		0x00	/* AGC gain */
+#define TDA9874A_GCONR		0x01	/* general config */
+#define TDA9874A_MSR		0x02	/* monitor select */
+#define TDA9874A_C1FRA		0x03	/* carrier 1 freq. */
+#define TDA9874A_C1FRB		0x04	/* carrier 1 freq. */
+#define TDA9874A_C1FRC		0x05	/* carrier 1 freq. */
+#define TDA9874A_C2FRA		0x06	/* carrier 2 freq. */
+#define TDA9874A_C2FRB		0x07	/* carrier 2 freq. */
+#define TDA9874A_C2FRC		0x08	/* carrier 2 freq. */
+#define TDA9874A_DCR		0x09	/* demodulator config */
+#define TDA9874A_FMER		0x0a	/* FM de-emphasis */
+#define TDA9874A_FMMR		0x0b	/* FM dematrix */
+#define TDA9874A_C1OLAR		0x0c	/* ch.1 output level adj. */
+#define TDA9874A_C2OLAR		0x0d	/* ch.2 output level adj. */
+#define TDA9874A_NCONR		0x0e	/* NICAM config */
+#define TDA9874A_NOLAR		0x0f	/* NICAM output level adj. */
+#define TDA9874A_NLELR		0x10	/* NICAM lower error limit */
+#define TDA9874A_NUELR		0x11	/* NICAM upper error limit */
+#define TDA9874A_AMCONR		0x12	/* audio mute control */
+#define TDA9874A_SDACOSR	0x13	/* stereo DAC output select */
+#define TDA9874A_AOSR		0x14	/* analog output select */
+#define TDA9874A_DAICONR	0x15	/* digital audio interface config */
+#define TDA9874A_I2SOSR		0x16	/* I2S-bus output select */
+#define TDA9874A_I2SOLAR	0x17	/* I2S-bus output level adj. */
+#define TDA9874A_MDACOSR	0x18	/* mono DAC output select (tda9874a) */
+#define TDA9874A_ESP		0xFF	/* easy standard progr. (tda9874a) */
+
+/* Subaddresses for TDA9874H and TDA9874A (slave tx) */
+#define TDA9874A_DSR		0x00	/* device status */
+#define TDA9874A_NSR		0x01	/* NICAM status */
+#define TDA9874A_NECR		0x02	/* NICAM error count */
+#define TDA9874A_DR1		0x03	/* add. data LSB */
+#define TDA9874A_DR2		0x04	/* add. data MSB */
+#define TDA9874A_LLRA		0x05	/* monitor level read-out LSB */
+#define TDA9874A_LLRB		0x06	/* monitor level read-out MSB */
+#define TDA9874A_SIFLR		0x07	/* SIF level */
+#define TDA9874A_TR2		252	/* test reg. 2 */
+#define TDA9874A_TR1		253	/* test reg. 1 */
+#define TDA9874A_DIC		254	/* device id. code */
+#define TDA9874A_SIC		255	/* software id. code */
+
+
+static int tda9874a_mode = 1;		/* 0: A2, 1: NICAM */
+static int tda9874a_GCONR = 0xc0;	/* default config. input pin: SIFSEL=0 */
+static int tda9874a_NCONR = 0x01;	/* default NICAM config.: AMSEL=0,AMUTE=1 */
+static int tda9874a_ESP = 0x07;		/* default standard: NICAM D/K */
+static int tda9874a_dic = -1;		/* device id. code */
+
+/* insmod options for tda9874a */
+static unsigned int tda9874a_SIF   = UNSET;
+static unsigned int tda9874a_AMSEL = UNSET;
+static unsigned int tda9874a_STD   = UNSET;
+module_param(tda9874a_SIF, int, 0444);
+module_param(tda9874a_AMSEL, int, 0444);
+module_param(tda9874a_STD, int, 0444);
+
+/*
+ * initialization table for tda9874 decoder:
+ *  - carrier 1 freq. registers (3 bytes)
+ *  - carrier 2 freq. registers (3 bytes)
+ *  - demudulator config register
+ *  - FM de-emphasis register (slow identification mode)
+ * Note: frequency registers must be written in single i2c transfer.
+ */
+static struct tda9874a_MODES {
+	char *name;
+	audiocmd cmd;
+} tda9874a_modelist[9] = {
+  {	"A2, B/G", /* default */
+	{ 9, { TDA9874A_C1FRA, 0x72,0x95,0x55, 0x77,0xA0,0x00, 0x00,0x00 }} },
+  {	"A2, M (Korea)",
+	{ 9, { TDA9874A_C1FRA, 0x5D,0xC0,0x00, 0x62,0x6A,0xAA, 0x20,0x22 }} },
+  {	"A2, D/K (1)",
+	{ 9, { TDA9874A_C1FRA, 0x87,0x6A,0xAA, 0x82,0x60,0x00, 0x00,0x00 }} },
+  {	"A2, D/K (2)",
+	{ 9, { TDA9874A_C1FRA, 0x87,0x6A,0xAA, 0x8C,0x75,0x55, 0x00,0x00 }} },
+  {	"A2, D/K (3)",
+	{ 9, { TDA9874A_C1FRA, 0x87,0x6A,0xAA, 0x77,0xA0,0x00, 0x00,0x00 }} },
+  {	"NICAM, I",
+	{ 9, { TDA9874A_C1FRA, 0x7D,0x00,0x00, 0x88,0x8A,0xAA, 0x08,0x33 }} },
+  {	"NICAM, B/G",
+	{ 9, { TDA9874A_C1FRA, 0x72,0x95,0x55, 0x79,0xEA,0xAA, 0x08,0x33 }} },
+  {	"NICAM, D/K",
+	{ 9, { TDA9874A_C1FRA, 0x87,0x6A,0xAA, 0x79,0xEA,0xAA, 0x08,0x33 }} },
+  {	"NICAM, L",
+	{ 9, { TDA9874A_C1FRA, 0x87,0x6A,0xAA, 0x79,0xEA,0xAA, 0x09,0x33 }} }
+};
+
+static int tda9874a_setup(struct CHIPSTATE *chip)
+{
+	struct v4l2_subdev *sd = &chip->sd;
+
+	chip_write(chip, TDA9874A_AGCGR, 0x00); /* 0 dB */
+	chip_write(chip, TDA9874A_GCONR, tda9874a_GCONR);
+	chip_write(chip, TDA9874A_MSR, (tda9874a_mode) ? 0x03:0x02);
+	if(tda9874a_dic == 0x11) {
+		chip_write(chip, TDA9874A_FMMR, 0x80);
+	} else { /* dic == 0x07 */
+		chip_cmd(chip,"tda9874_modelist",&tda9874a_modelist[tda9874a_STD].cmd);
+		chip_write(chip, TDA9874A_FMMR, 0x00);
+	}
+	chip_write(chip, TDA9874A_C1OLAR, 0x00); /* 0 dB */
+	chip_write(chip, TDA9874A_C2OLAR, 0x00); /* 0 dB */
+	chip_write(chip, TDA9874A_NCONR, tda9874a_NCONR);
+	chip_write(chip, TDA9874A_NOLAR, 0x00); /* 0 dB */
+	/* Note: If signal quality is poor you may want to change NICAM */
+	/* error limit registers (NLELR and NUELR) to some greater values. */
+	/* Then the sound would remain stereo, but won't be so clear. */
+	chip_write(chip, TDA9874A_NLELR, 0x14); /* default */
+	chip_write(chip, TDA9874A_NUELR, 0x50); /* default */
+
+	if(tda9874a_dic == 0x11) {
+		chip_write(chip, TDA9874A_AMCONR, 0xf9);
+		chip_write(chip, TDA9874A_SDACOSR, (tda9874a_mode) ? 0x81:0x80);
+		chip_write(chip, TDA9874A_AOSR, 0x80);
+		chip_write(chip, TDA9874A_MDACOSR, (tda9874a_mode) ? 0x82:0x80);
+		chip_write(chip, TDA9874A_ESP, tda9874a_ESP);
+	} else { /* dic == 0x07 */
+		chip_write(chip, TDA9874A_AMCONR, 0xfb);
+		chip_write(chip, TDA9874A_SDACOSR, (tda9874a_mode) ? 0x81:0x80);
+		chip_write(chip, TDA9874A_AOSR, 0x00); /* or 0x10 */
+	}
+	v4l2_dbg(1, debug, sd, "tda9874a_setup(): %s [0x%02X].\n",
+		tda9874a_modelist[tda9874a_STD].name,tda9874a_STD);
+	return 1;
+}
+
+static int tda9874a_getrxsubchans(struct CHIPSTATE *chip)
+{
+	struct v4l2_subdev *sd = &chip->sd;
+	int dsr,nsr,mode;
+	int necr; /* just for debugging */
+
+	mode = V4L2_TUNER_SUB_MONO;
+
+	if(-1 == (dsr = chip_read2(chip,TDA9874A_DSR)))
+		return mode;
+	if(-1 == (nsr = chip_read2(chip,TDA9874A_NSR)))
+		return mode;
+	if(-1 == (necr = chip_read2(chip,TDA9874A_NECR)))
+		return mode;
+
+	/* need to store dsr/nsr somewhere */
+	chip->shadow.bytes[MAXREGS-2] = dsr;
+	chip->shadow.bytes[MAXREGS-1] = nsr;
+
+	if(tda9874a_mode) {
+		/* Note: DSR.RSSF and DSR.AMSTAT bits are also checked.
+		 * If NICAM auto-muting is enabled, DSR.AMSTAT=1 indicates
+		 * that sound has (temporarily) switched from NICAM to
+		 * mono FM (or AM) on 1st sound carrier due to high NICAM bit
+		 * error count. So in fact there is no stereo in this case :-(
+		 * But changing the mode to V4L2_TUNER_MODE_MONO would switch
+		 * external 4052 multiplexer in audio_hook().
+		 */
+		if(nsr & 0x02) /* NSR.S/MB=1 */
+			mode = V4L2_TUNER_SUB_STEREO;
+		if(nsr & 0x01) /* NSR.D/SB=1 */
+			mode |= V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
+	} else {
+		if(dsr & 0x02) /* DSR.IDSTE=1 */
+			mode = V4L2_TUNER_SUB_STEREO;
+		if(dsr & 0x04) /* DSR.IDDUA=1 */
+			mode |= V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
+	}
+
+	v4l2_dbg(1, debug, sd,
+		 "tda9874a_getrxsubchans(): DSR=0x%X, NSR=0x%X, NECR=0x%X, return: %d.\n",
+		 dsr, nsr, necr, mode);
+	return mode;
+}
+
+static void tda9874a_setaudmode(struct CHIPSTATE *chip, int mode)
+{
+	struct v4l2_subdev *sd = &chip->sd;
+
+	/* Disable/enable NICAM auto-muting (based on DSR.RSSF status bit). */
+	/* If auto-muting is disabled, we can hear a signal of degrading quality. */
+	if (tda9874a_mode) {
+		if(chip->shadow.bytes[MAXREGS-2] & 0x20) /* DSR.RSSF=1 */
+			tda9874a_NCONR &= 0xfe; /* enable */
+		else
+			tda9874a_NCONR |= 0x01; /* disable */
+		chip_write(chip, TDA9874A_NCONR, tda9874a_NCONR);
+	}
+
+	/* Note: TDA9874A supports automatic FM dematrixing (FMMR register)
+	 * and has auto-select function for audio output (AOSR register).
+	 * Old TDA9874H doesn't support these features.
+	 * TDA9874A also has additional mono output pin (OUTM), which
+	 * on same (all?) tv-cards is not used, anyway (as well as MONOIN).
+	 */
+	if(tda9874a_dic == 0x11) {
+		int aosr = 0x80;
+		int mdacosr = (tda9874a_mode) ? 0x82:0x80;
+
+		switch(mode) {
+		case V4L2_TUNER_MODE_MONO:
+		case V4L2_TUNER_MODE_STEREO:
+			break;
+		case V4L2_TUNER_MODE_LANG1:
+			aosr = 0x80; /* auto-select, dual A/A */
+			mdacosr = (tda9874a_mode) ? 0x82:0x80;
+			break;
+		case V4L2_TUNER_MODE_LANG2:
+			aosr = 0xa0; /* auto-select, dual B/B */
+			mdacosr = (tda9874a_mode) ? 0x83:0x81;
+			break;
+		case V4L2_TUNER_MODE_LANG1_LANG2:
+			aosr = 0x00; /* always route L to L and R to R */
+			mdacosr = (tda9874a_mode) ? 0x82:0x80;
+			break;
+		default:
+			return;
+		}
+		chip_write(chip, TDA9874A_AOSR, aosr);
+		chip_write(chip, TDA9874A_MDACOSR, mdacosr);
+
+		v4l2_dbg(1, debug, sd,
+			"tda9874a_setaudmode(): req. mode %d; AOSR=0x%X, MDACOSR=0x%X.\n",
+			mode, aosr, mdacosr);
+
+	} else { /* dic == 0x07 */
+		int fmmr,aosr;
+
+		switch(mode) {
+		case V4L2_TUNER_MODE_MONO:
+			fmmr = 0x00; /* mono */
+			aosr = 0x10; /* A/A */
+			break;
+		case V4L2_TUNER_MODE_STEREO:
+			if(tda9874a_mode) {
+				fmmr = 0x00;
+				aosr = 0x00; /* handled by NICAM auto-mute */
+			} else {
+				fmmr = (tda9874a_ESP == 1) ? 0x05 : 0x04; /* stereo */
+				aosr = 0x00;
+			}
+			break;
+		case V4L2_TUNER_MODE_LANG1:
+			fmmr = 0x02; /* dual */
+			aosr = 0x10; /* dual A/A */
+			break;
+		case V4L2_TUNER_MODE_LANG2:
+			fmmr = 0x02; /* dual */
+			aosr = 0x20; /* dual B/B */
+			break;
+		case V4L2_TUNER_MODE_LANG1_LANG2:
+			fmmr = 0x02; /* dual */
+			aosr = 0x00; /* dual A/B */
+			break;
+		default:
+			return;
+		}
+		chip_write(chip, TDA9874A_FMMR, fmmr);
+		chip_write(chip, TDA9874A_AOSR, aosr);
+
+		v4l2_dbg(1, debug, sd,
+			"tda9874a_setaudmode(): req. mode %d; FMMR=0x%X, AOSR=0x%X.\n",
+			mode, fmmr, aosr);
+	}
+}
+
+static int tda9874a_checkit(struct CHIPSTATE *chip)
+{
+	struct v4l2_subdev *sd = &chip->sd;
+	int dic,sic;	/* device id. and software id. codes */
+
+	if(-1 == (dic = chip_read2(chip,TDA9874A_DIC)))
+		return 0;
+	if(-1 == (sic = chip_read2(chip,TDA9874A_SIC)))
+		return 0;
+
+	v4l2_dbg(1, debug, sd, "tda9874a_checkit(): DIC=0x%X, SIC=0x%X.\n", dic, sic);
+
+	if((dic == 0x11)||(dic == 0x07)) {
+		v4l2_info(sd, "found tda9874%s.\n", (dic == 0x11) ? "a" : "h");
+		tda9874a_dic = dic;	/* remember device id. */
+		return 1;
+	}
+	return 0;	/* not found */
+}
+
+static int tda9874a_initialize(struct CHIPSTATE *chip)
+{
+	if (tda9874a_SIF > 2)
+		tda9874a_SIF = 1;
+	if (tda9874a_STD >= ARRAY_SIZE(tda9874a_modelist))
+		tda9874a_STD = 0;
+	if(tda9874a_AMSEL > 1)
+		tda9874a_AMSEL = 0;
+
+	if(tda9874a_SIF == 1)
+		tda9874a_GCONR = 0xc0;	/* sound IF input 1 */
+	else
+		tda9874a_GCONR = 0xc1;	/* sound IF input 2 */
+
+	tda9874a_ESP = tda9874a_STD;
+	tda9874a_mode = (tda9874a_STD < 5) ? 0 : 1;
+
+	if(tda9874a_AMSEL == 0)
+		tda9874a_NCONR = 0x01; /* auto-mute: analog mono input */
+	else
+		tda9874a_NCONR = 0x05; /* auto-mute: 1st carrier FM or AM */
+
+	tda9874a_setup(chip);
+	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  /* Auxiliary channel select (FM) 0b0000000*/
+#define TDA9875_AVL         0x20  /* Auxiliary volume gauche */
+#define TDA9875_AVR         0x21  /* Auxiliary volume droite */
+#define TDA9875_ABA         0x22  /* Auxiliary Basse */
+#define TDA9875_ATR         0x23  /* Auxiliary 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                */
+
+#define TEA6300_VL         0x00  /* volume left */
+#define TEA6300_VR         0x01  /* volume right */
+#define TEA6300_BA         0x02  /* bass */
+#define TEA6300_TR         0x03  /* treble */
+#define TEA6300_FA         0x04  /* fader control */
+#define TEA6300_S          0x05  /* switch register */
+				 /* values for those registers: */
+#define TEA6300_S_SA       0x01  /* stereo A input */
+#define TEA6300_S_SB       0x02  /* stereo B */
+#define TEA6300_S_SC       0x04  /* stereo C */
+#define TEA6300_S_GMU      0x80  /* general mute */
+
+#define TEA6320_V          0x00  /* volume (0-5)/loudness off (6)/zero crossing mute(7) */
+#define TEA6320_FFR        0x01  /* fader front right (0-5) */
+#define TEA6320_FFL        0x02  /* fader front left (0-5) */
+#define TEA6320_FRR        0x03  /* fader rear right (0-5) */
+#define TEA6320_FRL        0x04  /* fader rear left (0-5) */
+#define TEA6320_BA         0x05  /* bass (0-4) */
+#define TEA6320_TR         0x06  /* treble (0-4) */
+#define TEA6320_S          0x07  /* switch register */
+				 /* values for those registers: */
+#define TEA6320_S_SA       0x07  /* stereo A input */
+#define TEA6320_S_SB       0x06  /* stereo B */
+#define TEA6320_S_SC       0x05  /* stereo C */
+#define TEA6320_S_SD       0x04  /* stereo D */
+#define TEA6320_S_GMU      0x80  /* general mute */
+
+#define TEA6420_S_SA       0x00  /* stereo A input */
+#define TEA6420_S_SB       0x01  /* stereo B */
+#define TEA6420_S_SC       0x02  /* stereo C */
+#define TEA6420_S_SD       0x03  /* stereo D */
+#define TEA6420_S_SE       0x04  /* stereo E */
+#define TEA6420_S_GMU      0x05  /* general mute */
+
+static int tea6300_shift10(int val) { return val >> 10; }
+static int tea6300_shift12(int val) { return val >> 12; }
+
+/* Assumes 16bit input (values 0x3f to 0x0c are unique, values less than */
+/* 0x0c mirror those immediately higher) */
+static int tea6320_volume(int val) { return (val / (65535/(63-12)) + 12) & 0x3f; }
+static int tea6320_shift11(int val) { return val >> 11; }
+static int tea6320_initialize(struct CHIPSTATE * chip)
+{
+	chip_write(chip, TEA6320_FFR, 0x3f);
+	chip_write(chip, TEA6320_FFL, 0x3f);
+	chip_write(chip, TEA6320_FRR, 0x3f);
+	chip_write(chip, TEA6320_FRL, 0x3f);
+
+	return 0;
+}
+
+
+/* ---------------------------------------------------------------------- */
+/* audio chip descriptions - defines+functions for tda8425                */
+
+#define TDA8425_VL         0x00  /* volume left */
+#define TDA8425_VR         0x01  /* volume right */
+#define TDA8425_BA         0x02  /* bass */
+#define TDA8425_TR         0x03  /* treble */
+#define TDA8425_S1         0x08  /* switch functions */
+				 /* values for those registers: */
+#define TDA8425_S1_OFF     0xEE  /* audio off (mute on) */
+#define TDA8425_S1_CH1     0xCE  /* audio channel 1 (mute off) - "linear stereo" mode */
+#define TDA8425_S1_CH2     0xCF  /* audio channel 2 (mute off) - "linear stereo" mode */
+#define TDA8425_S1_MU      0x20  /* mute bit */
+#define TDA8425_S1_STEREO  0x18  /* stereo bits */
+#define TDA8425_S1_STEREO_SPATIAL 0x18 /* spatial stereo */
+#define TDA8425_S1_STEREO_LINEAR  0x08 /* linear stereo */
+#define TDA8425_S1_STEREO_PSEUDO  0x10 /* pseudo stereo */
+#define TDA8425_S1_STEREO_MONO    0x00 /* forced mono */
+#define TDA8425_S1_ML      0x06        /* language selector */
+#define TDA8425_S1_ML_SOUND_A 0x02     /* sound a */
+#define TDA8425_S1_ML_SOUND_B 0x04     /* sound b */
+#define TDA8425_S1_ML_STEREO  0x06     /* stereo */
+#define TDA8425_S1_IS      0x01        /* channel selector */
+
+
+static int tda8425_shift10(int val) { return (val >> 10) | 0xc0; }
+static int tda8425_shift12(int val) { return (val >> 12) | 0xf0; }
+
+static void tda8425_setaudmode(struct CHIPSTATE *chip, int mode)
+{
+	int s1 = chip->shadow.bytes[TDA8425_S1+1] & 0xe1;
+
+	switch (mode) {
+	case V4L2_TUNER_MODE_LANG1:
+		s1 |= TDA8425_S1_ML_SOUND_A;
+		s1 |= TDA8425_S1_STEREO_PSEUDO;
+		break;
+	case V4L2_TUNER_MODE_LANG2:
+		s1 |= TDA8425_S1_ML_SOUND_B;
+		s1 |= TDA8425_S1_STEREO_PSEUDO;
+		break;
+	case V4L2_TUNER_MODE_LANG1_LANG2:
+		s1 |= TDA8425_S1_ML_STEREO;
+		s1 |= TDA8425_S1_STEREO_LINEAR;
+		break;
+	case V4L2_TUNER_MODE_MONO:
+		s1 |= TDA8425_S1_ML_STEREO;
+		s1 |= TDA8425_S1_STEREO_MONO;
+		break;
+	case V4L2_TUNER_MODE_STEREO:
+		s1 |= TDA8425_S1_ML_STEREO;
+		s1 |= TDA8425_S1_STEREO_SPATIAL;
+		break;
+	default:
+		return;
+	}
+	chip_write(chip,TDA8425_S1,s1);
+}
+
+
+/* ---------------------------------------------------------------------- */
+/* audio chip descriptions - defines+functions for pic16c54 (PV951)       */
+
+/* the registers of 16C54, I2C sub address. */
+#define PIC16C54_REG_KEY_CODE     0x01	       /* Not use. */
+#define PIC16C54_REG_MISC         0x02
+
+/* bit definition of the RESET register, I2C data. */
+#define PIC16C54_MISC_RESET_REMOTE_CTL 0x01 /* bit 0, Reset to receive the key */
+					    /*        code of remote controller */
+#define PIC16C54_MISC_MTS_MAIN         0x02 /* bit 1 */
+#define PIC16C54_MISC_MTS_SAP          0x04 /* bit 2 */
+#define PIC16C54_MISC_MTS_BOTH         0x08 /* bit 3 */
+#define PIC16C54_MISC_SND_MUTE         0x10 /* bit 4, Mute Audio(Line-in and Tuner) */
+#define PIC16C54_MISC_SND_NOTMUTE      0x20 /* bit 5 */
+#define PIC16C54_MISC_SWITCH_TUNER     0x40 /* bit 6	, Switch to Line-in */
+#define PIC16C54_MISC_SWITCH_LINE      0x80 /* bit 7	, Switch to Tuner */
+
+/* ---------------------------------------------------------------------- */
+/* audio chip descriptions - defines+functions for TA8874Z                */
+
+/* write 1st byte */
+#define TA8874Z_LED_STE	0x80
+#define TA8874Z_LED_BIL	0x40
+#define TA8874Z_LED_EXT	0x20
+#define TA8874Z_MONO_SET	0x10
+#define TA8874Z_MUTE	0x08
+#define TA8874Z_F_MONO	0x04
+#define TA8874Z_MODE_SUB	0x02
+#define TA8874Z_MODE_MAIN	0x01
+
+/* write 2nd byte */
+/*#define TA8874Z_TI	0x80  */ /* test mode */
+#define TA8874Z_SEPARATION	0x3f
+#define TA8874Z_SEPARATION_DEFAULT	0x10
+
+/* read */
+#define TA8874Z_B1	0x80
+#define TA8874Z_B0	0x40
+#define TA8874Z_CHAG_FLAG	0x20
+
+/*
+ *        B1 B0
+ * mono    L  H
+ * stereo  L  L
+ * BIL     H  L
+ */
+static int ta8874z_getrxsubchans(struct CHIPSTATE *chip)
+{
+	int val, mode;
+
+	val = chip_read(chip);
+	mode = V4L2_TUNER_SUB_MONO;
+	if (val & TA8874Z_B1){
+		mode |= V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
+	}else if (!(val & TA8874Z_B0)){
+		mode = V4L2_TUNER_SUB_STEREO;
+	}
+	/* v4l2_dbg(1, debug, &chip->sd,
+		 "ta8874z_getrxsubchans(): raw chip read: 0x%02x, return: 0x%02x\n",
+		 val, mode); */
+	return mode;
+}
+
+static audiocmd ta8874z_stereo = { 2, {0, TA8874Z_SEPARATION_DEFAULT}};
+static audiocmd ta8874z_mono = {2, { TA8874Z_MONO_SET, TA8874Z_SEPARATION_DEFAULT}};
+static audiocmd ta8874z_main = {2, { 0, TA8874Z_SEPARATION_DEFAULT}};
+static audiocmd ta8874z_sub = {2, { TA8874Z_MODE_SUB, TA8874Z_SEPARATION_DEFAULT}};
+static audiocmd ta8874z_both = {2, { TA8874Z_MODE_MAIN | TA8874Z_MODE_SUB, TA8874Z_SEPARATION_DEFAULT}};
+
+static void ta8874z_setaudmode(struct CHIPSTATE *chip, int mode)
+{
+	struct v4l2_subdev *sd = &chip->sd;
+	int update = 1;
+	audiocmd *t = NULL;
+
+	v4l2_dbg(1, debug, sd, "ta8874z_setaudmode(): mode: 0x%02x\n", mode);
+
+	switch(mode){
+	case V4L2_TUNER_MODE_MONO:
+		t = &ta8874z_mono;
+		break;
+	case V4L2_TUNER_MODE_STEREO:
+		t = &ta8874z_stereo;
+		break;
+	case V4L2_TUNER_MODE_LANG1:
+		t = &ta8874z_main;
+		break;
+	case V4L2_TUNER_MODE_LANG2:
+		t = &ta8874z_sub;
+		break;
+	case V4L2_TUNER_MODE_LANG1_LANG2:
+		t = &ta8874z_both;
+		break;
+	default:
+		update = 0;
+	}
+
+	if(update)
+		chip_cmd(chip, "TA8874Z", t);
+}
+
+static int ta8874z_checkit(struct CHIPSTATE *chip)
+{
+	int rc;
+	rc = chip_read(chip);
+	return ((rc & 0x1f) == 0x1f) ? 1 : 0;
+}
+
+/* ---------------------------------------------------------------------- */
+/* audio chip descriptions - struct CHIPDESC                              */
+
+/* insmod options to enable/disable individual audio chips */
+static int tda8425  = 1;
+static int tda9840  = 1;
+static int tda9850  = 1;
+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;
+static int pic16c54 = 1;
+static int ta8874z;	/* default 0 - address clash with tda9840 */
+
+module_param(tda8425, int, 0444);
+module_param(tda9840, int, 0444);
+module_param(tda9850, int, 0444);
+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);
+module_param(pic16c54, int, 0444);
+module_param(ta8874z, int, 0444);
+
+static struct CHIPDESC chiplist[] = {
+	{
+		.name       = "tda9840",
+		.insmodopt  = &tda9840,
+		.addr_lo    = I2C_ADDR_TDA9840 >> 1,
+		.addr_hi    = I2C_ADDR_TDA9840 >> 1,
+		.registers  = 5,
+		.flags      = CHIP_NEED_CHECKMODE,
+
+		/* callbacks */
+		.checkit    = tda9840_checkit,
+		.getrxsubchans = tda9840_getrxsubchans,
+		.setaudmode = tda9840_setaudmode,
+
+		.init       = { 2, { TDA9840_TEST, TDA9840_TEST_INT1SN
+				/* ,TDA9840_SW, TDA9840_MONO */} }
+	},
+	{
+		.name       = "tda9873h",
+		.insmodopt  = &tda9873,
+		.addr_lo    = I2C_ADDR_TDA985x_L >> 1,
+		.addr_hi    = I2C_ADDR_TDA985x_H >> 1,
+		.registers  = 3,
+		.flags      = CHIP_HAS_INPUTSEL | CHIP_NEED_CHECKMODE,
+
+		/* callbacks */
+		.checkit    = tda9873_checkit,
+		.getrxsubchans = tda9873_getrxsubchans,
+		.setaudmode = tda9873_setaudmode,
+
+		.init       = { 4, { TDA9873_SW, 0xa4, 0x06, 0x03 } },
+		.inputreg   = TDA9873_SW,
+		.inputmute  = TDA9873_MUTE | TDA9873_AUTOMUTE,
+		.inputmap   = {0xa0, 0xa2, 0xa0, 0xa0},
+		.inputmask  = TDA9873_INP_MASK|TDA9873_MUTE|TDA9873_AUTOMUTE,
+
+	},
+	{
+		.name       = "tda9874h/a",
+		.insmodopt  = &tda9874a,
+		.addr_lo    = I2C_ADDR_TDA9874 >> 1,
+		.addr_hi    = I2C_ADDR_TDA9874 >> 1,
+		.flags      = CHIP_NEED_CHECKMODE,
+
+		/* callbacks */
+		.initialize = tda9874a_initialize,
+		.checkit    = tda9874a_checkit,
+		.getrxsubchans = tda9874a_getrxsubchans,
+		.setaudmode = tda9874a_setaudmode,
+	},
+	{
+		.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,
+		.addr_hi    = I2C_ADDR_TDA985x_H >> 1,
+		.registers  = 11,
+
+		.getrxsubchans = tda985x_getrxsubchans,
+		.setaudmode = tda985x_setaudmode,
+
+		.init       = { 8, { TDA9850_C4, 0x08, 0x08, TDA985x_STEREO, 0x07, 0x10, 0x10, 0x03 } }
+	},
+	{
+		.name       = "tda9855",
+		.insmodopt  = &tda9855,
+		.addr_lo    = I2C_ADDR_TDA985x_L >> 1,
+		.addr_hi    = I2C_ADDR_TDA985x_H >> 1,
+		.registers  = 11,
+		.flags      = CHIP_HAS_VOLUME | CHIP_HAS_BASSTREBLE,
+
+		.leftreg    = TDA9855_VL,
+		.rightreg   = TDA9855_VR,
+		.bassreg    = TDA9855_BA,
+		.treblereg  = TDA9855_TR,
+
+		/* callbacks */
+		.volfunc    = tda9855_volume,
+		.bassfunc   = tda9855_bass,
+		.treblefunc = tda9855_treble,
+		.getrxsubchans = tda985x_getrxsubchans,
+		.setaudmode = tda985x_setaudmode,
+
+		.init       = { 12, { 0, 0x6f, 0x6f, 0x0e, 0x07<<1, 0x8<<2,
+				    TDA9855_MUTE | TDA9855_AVL | TDA9855_LOUD | TDA9855_INT,
+				    TDA985x_STEREO | TDA9855_LINEAR | TDA9855_TZCM | TDA9855_VZCM,
+				    0x07, 0x10, 0x10, 0x03 }}
+	},
+	{
+		.name       = "tea6300",
+		.insmodopt  = &tea6300,
+		.addr_lo    = I2C_ADDR_TEA6300 >> 1,
+		.addr_hi    = I2C_ADDR_TEA6300 >> 1,
+		.registers  = 6,
+		.flags      = CHIP_HAS_VOLUME | CHIP_HAS_BASSTREBLE | CHIP_HAS_INPUTSEL,
+
+		.leftreg    = TEA6300_VR,
+		.rightreg   = TEA6300_VL,
+		.bassreg    = TEA6300_BA,
+		.treblereg  = TEA6300_TR,
+
+		/* callbacks */
+		.volfunc    = tea6300_shift10,
+		.bassfunc   = tea6300_shift12,
+		.treblefunc = tea6300_shift12,
+
+		.inputreg   = TEA6300_S,
+		.inputmap   = { TEA6300_S_SA, TEA6300_S_SB, TEA6300_S_SC },
+		.inputmute  = TEA6300_S_GMU,
+	},
+	{
+		.name       = "tea6320",
+		.insmodopt  = &tea6320,
+		.addr_lo    = I2C_ADDR_TEA6300 >> 1,
+		.addr_hi    = I2C_ADDR_TEA6300 >> 1,
+		.registers  = 8,
+		.flags      = CHIP_HAS_VOLUME | CHIP_HAS_BASSTREBLE | CHIP_HAS_INPUTSEL,
+
+		.leftreg    = TEA6320_V,
+		.rightreg   = TEA6320_V,
+		.bassreg    = TEA6320_BA,
+		.treblereg  = TEA6320_TR,
+
+		/* callbacks */
+		.initialize = tea6320_initialize,
+		.volfunc    = tea6320_volume,
+		.bassfunc   = tea6320_shift11,
+		.treblefunc = tea6320_shift11,
+
+		.inputreg   = TEA6320_S,
+		.inputmap   = { TEA6320_S_SA, TEA6420_S_SB, TEA6300_S_SC, TEA6320_S_SD },
+		.inputmute  = TEA6300_S_GMU,
+	},
+	{
+		.name       = "tea6420",
+		.insmodopt  = &tea6420,
+		.addr_lo    = I2C_ADDR_TEA6420 >> 1,
+		.addr_hi    = I2C_ADDR_TEA6420 >> 1,
+		.registers  = 1,
+		.flags      = CHIP_HAS_INPUTSEL,
+
+		.inputreg   = -1,
+		.inputmap   = { TEA6420_S_SA, TEA6420_S_SB, TEA6420_S_SC },
+		.inputmute  = TEA6300_S_GMU,
+	},
+	{
+		.name       = "tda8425",
+		.insmodopt  = &tda8425,
+		.addr_lo    = I2C_ADDR_TDA8425 >> 1,
+		.addr_hi    = I2C_ADDR_TDA8425 >> 1,
+		.registers  = 9,
+		.flags      = CHIP_HAS_VOLUME | CHIP_HAS_BASSTREBLE | CHIP_HAS_INPUTSEL,
+
+		.leftreg    = TDA8425_VL,
+		.rightreg   = TDA8425_VR,
+		.bassreg    = TDA8425_BA,
+		.treblereg  = TDA8425_TR,
+
+		/* callbacks */
+		.volfunc    = tda8425_shift10,
+		.bassfunc   = tda8425_shift12,
+		.treblefunc = tda8425_shift12,
+		.setaudmode = tda8425_setaudmode,
+
+		.inputreg   = TDA8425_S1,
+		.inputmap   = { TDA8425_S1_CH1, TDA8425_S1_CH1, TDA8425_S1_CH1 },
+		.inputmute  = TDA8425_S1_OFF,
+
+	},
+	{
+		.name       = "pic16c54 (PV951)",
+		.insmodopt  = &pic16c54,
+		.addr_lo    = I2C_ADDR_PIC16C54 >> 1,
+		.addr_hi    = I2C_ADDR_PIC16C54>> 1,
+		.registers  = 2,
+		.flags      = CHIP_HAS_INPUTSEL,
+
+		.inputreg   = PIC16C54_REG_MISC,
+		.inputmap   = {PIC16C54_MISC_SND_NOTMUTE|PIC16C54_MISC_SWITCH_TUNER,
+			     PIC16C54_MISC_SND_NOTMUTE|PIC16C54_MISC_SWITCH_LINE,
+			     PIC16C54_MISC_SND_NOTMUTE|PIC16C54_MISC_SWITCH_LINE,
+			     PIC16C54_MISC_SND_MUTE},
+		.inputmute  = PIC16C54_MISC_SND_MUTE,
+	},
+	{
+		.name       = "ta8874z",
+		.checkit    = ta8874z_checkit,
+		.insmodopt  = &ta8874z,
+		.addr_lo    = I2C_ADDR_TDA9840 >> 1,
+		.addr_hi    = I2C_ADDR_TDA9840 >> 1,
+		.registers  = 2,
+
+		/* callbacks */
+		.getrxsubchans = ta8874z_getrxsubchans,
+		.setaudmode = ta8874z_setaudmode,
+
+		.init       = {2, { TA8874Z_MONO_SET, TA8874Z_SEPARATION_DEFAULT}},
+	},
+	{ .name = NULL } /* EOF */
+};
+
+
+/* ---------------------------------------------------------------------- */
+
+static int tvaudio_g_ctrl(struct v4l2_subdev *sd,
+			    struct v4l2_control *ctrl)
+{
+	struct CHIPSTATE *chip = to_state(sd);
+	struct CHIPDESC *desc = chip->desc;
+
+	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:
+		if (!(desc->flags & CHIP_HAS_VOLUME))
+			break;
+		ctrl->value = max(chip->left,chip->right);
+		return 0;
+	case V4L2_CID_AUDIO_BALANCE:
+	{
+		int volume;
+		if (!(desc->flags & CHIP_HAS_VOLUME))
+			break;
+		volume = max(chip->left,chip->right);
+		if (volume)
+			ctrl->value=(32768*min(chip->left,chip->right))/volume;
+		else
+			ctrl->value=32768;
+		return 0;
+	}
+	case V4L2_CID_AUDIO_BASS:
+		if (!(desc->flags & CHIP_HAS_BASSTREBLE))
+			break;
+		ctrl->value = chip->bass;
+		return 0;
+	case V4L2_CID_AUDIO_TREBLE:
+		if (!(desc->flags & CHIP_HAS_BASSTREBLE))
+			break;
+		ctrl->value = chip->treble;
+		return 0;
+	}
+	return -EINVAL;
+}
+
+static int tvaudio_s_ctrl(struct v4l2_subdev *sd,
+			    struct v4l2_control *ctrl)
+{
+	struct CHIPSTATE *chip = to_state(sd);
+	struct CHIPDESC *desc = chip->desc;
+
+	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;
+		if (chip->muted)
+			chip_write_masked(chip,desc->inputreg,desc->inputmute,desc->inputmask);
+		else
+			chip_write_masked(chip,desc->inputreg,
+					desc->inputmap[chip->input],desc->inputmask);
+		return 0;
+	case V4L2_CID_AUDIO_VOLUME:
+	{
+		int volume,balance;
+
+		if (!(desc->flags & CHIP_HAS_VOLUME))
+			break;
+
+		volume = max(chip->left,chip->right);
+		if (volume)
+			balance=(32768*min(chip->left,chip->right))/volume;
+		else
+			balance=32768;
+
+		volume=ctrl->value;
+		chip->left = (min(65536 - balance,32768) * volume) / 32768;
+		chip->right = (min(balance,volume *(__u16)32768)) / 32768;
+
+		chip_write(chip,desc->leftreg,desc->volfunc(chip->left));
+		chip_write(chip,desc->rightreg,desc->volfunc(chip->right));
+
+		return 0;
+	}
+	case V4L2_CID_AUDIO_BALANCE:
+	{
+		int volume, balance;
+
+		if (!(desc->flags & CHIP_HAS_VOLUME))
+			break;
+
+		volume = max(chip->left, chip->right);
+		balance = ctrl->value;
+		chip->left = (min(65536 - balance, 32768) * volume) / 32768;
+		chip->right = (min(balance, volume * (__u16)32768)) / 32768;
+
+		chip_write(chip, desc->leftreg, desc->volfunc(chip->left));
+		chip_write(chip, desc->rightreg, desc->volfunc(chip->right));
+
+		return 0;
+	}
+	case V4L2_CID_AUDIO_BASS:
+		if (!(desc->flags & CHIP_HAS_BASSTREBLE))
+			break;
+		chip->bass = ctrl->value;
+		chip_write(chip,desc->bassreg,desc->bassfunc(chip->bass));
+
+		return 0;
+	case V4L2_CID_AUDIO_TREBLE:
+		if (!(desc->flags & CHIP_HAS_BASSTREBLE))
+			break;
+		chip->treble = ctrl->value;
+		chip_write(chip,desc->treblereg,desc->treblefunc(chip->treble));
+
+		return 0;
+	}
+	return -EINVAL;
+}
+
+
+/* ---------------------------------------------------------------------- */
+/* video4linux interface                                                  */
+
+static int tvaudio_s_radio(struct v4l2_subdev *sd)
+{
+	struct CHIPSTATE *chip = to_state(sd);
+
+	chip->radio = 1;
+	/* del_timer(&chip->wt); */
+	return 0;
+}
+
+static int tvaudio_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
+{
+	struct CHIPSTATE *chip = to_state(sd);
+	struct CHIPDESC *desc = chip->desc;
+
+	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 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 v4l2_ctrl_query_fill(qc, 0, 65535, 65535 / 100, 32768);
+		break;
+	default:
+		break;
+	}
+	return -EINVAL;
+}
+
+static int tvaudio_s_routing(struct v4l2_subdev *sd,
+			     u32 input, u32 output, u32 config)
+{
+	struct CHIPSTATE *chip = to_state(sd);
+	struct CHIPDESC *desc = chip->desc;
+
+	if (!(desc->flags & CHIP_HAS_INPUTSEL))
+		return 0;
+	if (input >= 4)
+		return -EINVAL;
+	/* There are four inputs: tuner, radio, extern and intern. */
+	chip->input = input;
+	if (chip->muted)
+		return 0;
+	chip_write_masked(chip, desc->inputreg,
+			desc->inputmap[chip->input], desc->inputmask);
+	return 0;
+}
+
+static int tvaudio_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
+{
+	struct CHIPSTATE *chip = to_state(sd);
+	struct CHIPDESC *desc = chip->desc;
+
+	if (!desc->setaudmode)
+		return 0;
+	if (chip->radio)
+		return 0;
+
+	switch (vt->audmode) {
+	case V4L2_TUNER_MODE_MONO:
+	case V4L2_TUNER_MODE_STEREO:
+	case V4L2_TUNER_MODE_LANG1:
+	case V4L2_TUNER_MODE_LANG2:
+	case V4L2_TUNER_MODE_LANG1_LANG2:
+		break;
+	default:
+		return -EINVAL;
+	}
+	chip->audmode = vt->audmode;
+
+	if (chip->thread)
+		wake_up_process(chip->thread);
+	else
+		desc->setaudmode(chip, vt->audmode);
+
+	return 0;
+}
+
+static int tvaudio_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
+{
+	struct CHIPSTATE *chip = to_state(sd);
+	struct CHIPDESC *desc = chip->desc;
+
+	if (!desc->getrxsubchans)
+		return 0;
+	if (chip->radio)
+		return 0;
+
+	vt->audmode = chip->audmode;
+	vt->rxsubchans = desc->getrxsubchans(chip);
+	vt->capability = V4L2_TUNER_CAP_STEREO |
+		V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2;
+
+	return 0;
+}
+
+static int tvaudio_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
+{
+	struct CHIPSTATE *chip = to_state(sd);
+
+	chip->radio = 0;
+	return 0;
+}
+
+static int tvaudio_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *freq)
+{
+	struct CHIPSTATE *chip = to_state(sd);
+	struct CHIPDESC *desc = chip->desc;
+
+	/* For chips that provide getrxsubchans and setaudmode, and doesn't
+	   automatically follows the stereo carrier, a kthread is
+	   created to set the audio standard. In this case, when then
+	   the video channel is changed, tvaudio starts on MONO mode.
+	   After waiting for 2 seconds, the kernel thread is called,
+	   to follow whatever audio standard is pointed by the
+	   audio carrier.
+	 */
+	if (chip->thread) {
+		desc->setaudmode(chip, V4L2_TUNER_MODE_MONO);
+		chip->prevmode = -1; /* reset previous mode */
+		mod_timer(&chip->wt, jiffies+msecs_to_jiffies(2000));
+	}
+	return 0;
+}
+
+static int tvaudio_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_TVAUDIO, 0);
+}
+
+/* ----------------------------------------------------------------------- */
+
+static const struct v4l2_subdev_core_ops tvaudio_core_ops = {
+	.g_chip_ident = tvaudio_g_chip_ident,
+	.queryctrl = tvaudio_queryctrl,
+	.g_ctrl = tvaudio_g_ctrl,
+	.s_ctrl = tvaudio_s_ctrl,
+	.s_std = tvaudio_s_std,
+};
+
+static const struct v4l2_subdev_tuner_ops tvaudio_tuner_ops = {
+	.s_radio = tvaudio_s_radio,
+	.s_frequency = tvaudio_s_frequency,
+	.s_tuner = tvaudio_s_tuner,
+	.g_tuner = tvaudio_g_tuner,
+};
+
+static const struct v4l2_subdev_audio_ops tvaudio_audio_ops = {
+	.s_routing = tvaudio_s_routing,
+};
+
+static const struct v4l2_subdev_ops tvaudio_ops = {
+	.core = &tvaudio_core_ops,
+	.tuner = &tvaudio_tuner_ops,
+	.audio = &tvaudio_audio_ops,
+};
+
+/* ----------------------------------------------------------------------- */
+
+
+/* i2c registration                                                       */
+
+static int tvaudio_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+	struct CHIPSTATE *chip;
+	struct CHIPDESC  *desc;
+	struct v4l2_subdev *sd;
+
+	if (debug) {
+		printk(KERN_INFO "tvaudio: TV audio decoder + audio/video mux driver\n");
+		printk(KERN_INFO "tvaudio: known chips: ");
+		for (desc = chiplist; desc->name != NULL; desc++)
+			printk("%s%s", (desc == chiplist) ? "" : ", ", desc->name);
+		printk("\n");
+	}
+
+	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+	if (!chip)
+		return -ENOMEM;
+	sd = &chip->sd;
+	v4l2_i2c_subdev_init(sd, client, &tvaudio_ops);
+
+	/* find description for the chip */
+	v4l2_dbg(1, debug, sd, "chip found @ 0x%x\n", client->addr<<1);
+	for (desc = chiplist; desc->name != NULL; desc++) {
+		if (0 == *(desc->insmodopt))
+			continue;
+		if (client->addr < desc->addr_lo ||
+		    client->addr > desc->addr_hi)
+			continue;
+		if (desc->checkit && !desc->checkit(chip))
+			continue;
+		break;
+	}
+	if (desc->name == NULL) {
+		v4l2_dbg(1, debug, sd, "no matching chip description found\n");
+		kfree(chip);
+		return -EIO;
+	}
+	v4l2_info(sd, "%s found @ 0x%x (%s)\n", desc->name, client->addr<<1, client->adapter->name);
+	if (desc->flags) {
+		v4l2_dbg(1, debug, sd, "matches:%s%s%s.\n",
+			(desc->flags & CHIP_HAS_VOLUME)     ? " volume"      : "",
+			(desc->flags & CHIP_HAS_BASSTREBLE) ? " bass/treble" : "",
+			(desc->flags & CHIP_HAS_INPUTSEL)   ? " audiomux"    : "");
+	}
+
+	/* fill required data structures */
+	if (!id)
+		strlcpy(client->name, desc->name, I2C_NAME_SIZE);
+	chip->desc = desc;
+	chip->shadow.count = desc->registers+1;
+	chip->prevmode = -1;
+	chip->audmode = V4L2_TUNER_MODE_LANG1;
+
+	/* initialization  */
+	if (desc->initialize != NULL)
+		desc->initialize(chip);
+	else
+		chip_cmd(chip, "init", &desc->init);
+
+	if (desc->flags & CHIP_HAS_VOLUME) {
+		if (!desc->volfunc) {
+			/* This shouldn't be happen. Warn user, but keep working
+			   without volume controls
+			 */
+			v4l2_info(sd, "volume callback undefined!\n");
+			desc->flags &= ~CHIP_HAS_VOLUME;
+		} else {
+			chip->left  = desc->leftinit  ? desc->leftinit  : 65535;
+			chip->right = desc->rightinit ? desc->rightinit : 65535;
+			chip_write(chip, desc->leftreg,
+				   desc->volfunc(chip->left));
+			chip_write(chip, desc->rightreg,
+				   desc->volfunc(chip->right));
+		}
+	}
+	if (desc->flags & CHIP_HAS_BASSTREBLE) {
+		if (!desc->bassfunc || !desc->treblefunc) {
+			/* This shouldn't be happen. Warn user, but keep working
+			   without bass/treble controls
+			 */
+			v4l2_info(sd, "bass/treble callbacks undefined!\n");
+			desc->flags &= ~CHIP_HAS_BASSTREBLE;
+		} else {
+			chip->treble = desc->trebleinit ?
+						desc->trebleinit : 32768;
+			chip->bass   = desc->bassinit   ?
+						desc->bassinit   : 32768;
+			chip_write(chip, desc->bassreg,
+				   desc->bassfunc(chip->bass));
+			chip_write(chip, desc->treblereg,
+				   desc->treblefunc(chip->treble));
+		}
+	}
+
+	chip->thread = NULL;
+	init_timer(&chip->wt);
+	if (desc->flags & CHIP_NEED_CHECKMODE) {
+		if (!desc->getrxsubchans || !desc->setaudmode) {
+			/* This shouldn't be happen. Warn user, but keep working
+			   without kthread
+			 */
+			v4l2_info(sd, "set/get mode callbacks undefined!\n");
+			return 0;
+		}
+		/* start async thread */
+		chip->wt.function = chip_thread_wake;
+		chip->wt.data     = (unsigned long)chip;
+		chip->thread = kthread_run(chip_thread, chip, client->name);
+		if (IS_ERR(chip->thread)) {
+			v4l2_warn(sd, "failed to create kthread\n");
+			chip->thread = NULL;
+		}
+	}
+	return 0;
+}
+
+static int tvaudio_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct CHIPSTATE *chip = to_state(sd);
+
+	del_timer_sync(&chip->wt);
+	if (chip->thread) {
+		/* shutdown async thread */
+		kthread_stop(chip->thread);
+		chip->thread = NULL;
+	}
+
+	v4l2_device_unregister_subdev(sd);
+	kfree(chip);
+	return 0;
+}
+
+/* This driver supports many devices and the idea is to let the driver
+   detect which device is present. So rather than listing all supported
+   devices here, we pretend to support a single, fake device type. */
+static const struct i2c_device_id tvaudio_id[] = {
+	{ "tvaudio", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, tvaudio_id);
+
+static struct i2c_driver tvaudio_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "tvaudio",
+	},
+	.probe		= tvaudio_probe,
+	.remove		= tvaudio_remove,
+	.id_table	= tvaudio_id,
+};
+
+module_i2c_driver(tvaudio_driver);
diff --git a/drivers/media/i2c/tveeprom.c b/drivers/media/i2c/tveeprom.c
new file mode 100644
index 0000000..3b6cf03
--- /dev/null
+++ b/drivers/media/i2c/tveeprom.c
@@ -0,0 +1,792 @@
+/*
+ * tveeprom - eeprom decoder for tvcard configuration eeproms
+ *
+ * Data and decoding routines shamelessly borrowed from bttv-cards.c
+ * eeprom access routine shamelessly borrowed from bttv-if.c
+ * which are:
+
+    Copyright (C) 1996,97,98 Ralph  Metzler (rjkm@thp.uni-koeln.de)
+			   & Marcus Metzler (mocm@thp.uni-koeln.de)
+    (c) 1999-2001 Gerd Knorr <kraxel@goldbach.in-berlin.de>
+
+ * Adjustments to fit a more general model and all bugs:
+
+	Copyright (C) 2003 John Klar <linpvr at projectplasma.com>
+
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/videodev2.h>
+#include <linux/i2c.h>
+
+#include <media/tuner.h>
+#include <media/tveeprom.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-chip-ident.h>
+
+MODULE_DESCRIPTION("i2c Hauppauge eeprom decoder driver");
+MODULE_AUTHOR("John Klar");
+MODULE_LICENSE("GPL");
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Debug level (0-1)");
+
+#define STRM(array, i) \
+	(i < sizeof(array) / sizeof(char *) ? array[i] : "unknown")
+
+#define tveeprom_info(fmt, arg...) \
+	v4l_printk(KERN_INFO, "tveeprom", c->adapter, c->addr, fmt , ## arg)
+#define tveeprom_warn(fmt, arg...) \
+	v4l_printk(KERN_WARNING, "tveeprom", c->adapter, c->addr, fmt , ## arg)
+#define tveeprom_dbg(fmt, arg...) do { \
+	if (debug) \
+		v4l_printk(KERN_DEBUG, "tveeprom", \
+				c->adapter, c->addr, fmt , ## arg); \
+	} while (0)
+
+/*
+ * The Hauppauge eeprom uses an 8bit field to determine which
+ * tuner formats the tuner supports.
+ */
+static struct HAUPPAUGE_TUNER_FMT
+{
+	int	id;
+	char *name;
+}
+hauppauge_tuner_fmt[] =
+{
+	{ V4L2_STD_UNKNOWN,                   " UNKNOWN" },
+	{ V4L2_STD_UNKNOWN,                   " FM" },
+	{ V4L2_STD_B|V4L2_STD_GH,             " PAL(B/G)" },
+	{ V4L2_STD_MN,                        " NTSC(M)" },
+	{ V4L2_STD_PAL_I,                     " PAL(I)" },
+	{ V4L2_STD_SECAM_L|V4L2_STD_SECAM_LC, " SECAM(L/L')" },
+	{ V4L2_STD_DK,                        " PAL(D/D1/K)" },
+	{ V4L2_STD_ATSC,                      " ATSC/DVB Digital" },
+};
+
+/* This is the full list of possible tuners. Many thanks to Hauppauge for
+   supplying this information. Note that many tuners where only used for
+   testing and never made it to the outside world. So you will only see
+   a subset in actual produced cards. */
+static struct HAUPPAUGE_TUNER
+{
+	int  id;
+	char *name;
+}
+hauppauge_tuner[] =
+{
+	/* 0-9 */
+	{ TUNER_ABSENT,        		"None" },
+	{ TUNER_ABSENT,        		"External" },
+	{ TUNER_ABSENT,        		"Unspecified" },
+	{ TUNER_PHILIPS_PAL,   		"Philips FI1216" },
+	{ TUNER_PHILIPS_SECAM, 		"Philips FI1216MF" },
+	{ TUNER_PHILIPS_NTSC,  		"Philips FI1236" },
+	{ TUNER_PHILIPS_PAL_I, 		"Philips FI1246" },
+	{ TUNER_PHILIPS_PAL_DK,		"Philips FI1256" },
+	{ TUNER_PHILIPS_PAL,   		"Philips FI1216 MK2" },
+	{ TUNER_PHILIPS_SECAM, 		"Philips FI1216MF MK2" },
+	/* 10-19 */
+	{ TUNER_PHILIPS_NTSC,  		"Philips FI1236 MK2" },
+	{ TUNER_PHILIPS_PAL_I, 		"Philips FI1246 MK2" },
+	{ TUNER_PHILIPS_PAL_DK,		"Philips FI1256 MK2" },
+	{ TUNER_TEMIC_NTSC,    		"Temic 4032FY5" },
+	{ TUNER_TEMIC_PAL,     		"Temic 4002FH5" },
+	{ TUNER_TEMIC_PAL_I,   		"Temic 4062FY5" },
+	{ TUNER_PHILIPS_PAL,   		"Philips FR1216 MK2" },
+	{ TUNER_PHILIPS_SECAM, 		"Philips FR1216MF MK2" },
+	{ TUNER_PHILIPS_NTSC,  		"Philips FR1236 MK2" },
+	{ TUNER_PHILIPS_PAL_I, 		"Philips FR1246 MK2" },
+	/* 20-29 */
+	{ TUNER_PHILIPS_PAL_DK,		"Philips FR1256 MK2" },
+	{ TUNER_PHILIPS_PAL,   		"Philips FM1216" },
+	{ TUNER_PHILIPS_SECAM, 		"Philips FM1216MF" },
+	{ TUNER_PHILIPS_NTSC,  		"Philips FM1236" },
+	{ TUNER_PHILIPS_PAL_I, 		"Philips FM1246" },
+	{ TUNER_PHILIPS_PAL_DK,		"Philips FM1256" },
+	{ TUNER_TEMIC_4036FY5_NTSC, 	"Temic 4036FY5" },
+	{ TUNER_ABSENT,        		"Samsung TCPN9082D" },
+	{ TUNER_ABSENT,        		"Samsung TCPM9092P" },
+	{ TUNER_TEMIC_4006FH5_PAL, 	"Temic 4006FH5" },
+	/* 30-39 */
+	{ TUNER_ABSENT,        		"Samsung TCPN9085D" },
+	{ TUNER_ABSENT,        		"Samsung TCPB9085P" },
+	{ TUNER_ABSENT,        		"Samsung TCPL9091P" },
+	{ TUNER_TEMIC_4039FR5_NTSC, 	"Temic 4039FR5" },
+	{ TUNER_PHILIPS_FQ1216ME,   	"Philips FQ1216 ME" },
+	{ TUNER_TEMIC_4066FY5_PAL_I, 	"Temic 4066FY5" },
+	{ TUNER_PHILIPS_NTSC,        	"Philips TD1536" },
+	{ TUNER_PHILIPS_NTSC,        	"Philips TD1536D" },
+	{ TUNER_PHILIPS_NTSC,  		"Philips FMR1236" }, /* mono radio */
+	{ TUNER_ABSENT,        		"Philips FI1256MP" },
+	/* 40-49 */
+	{ TUNER_ABSENT,        		"Samsung TCPQ9091P" },
+	{ TUNER_TEMIC_4006FN5_MULTI_PAL, "Temic 4006FN5" },
+	{ TUNER_TEMIC_4009FR5_PAL, 	"Temic 4009FR5" },
+	{ TUNER_TEMIC_4046FM5,     	"Temic 4046FM5" },
+	{ TUNER_TEMIC_4009FN5_MULTI_PAL_FM, "Temic 4009FN5" },
+	{ TUNER_ABSENT,        		"Philips TD1536D FH 44"},
+	{ TUNER_LG_NTSC_FM,    		"LG TP18NSR01F"},
+	{ TUNER_LG_PAL_FM,     		"LG TP18PSB01D"},
+	{ TUNER_LG_PAL,        		"LG TP18PSB11D"},
+	{ TUNER_LG_PAL_I_FM,   		"LG TAPC-I001D"},
+	/* 50-59 */
+	{ TUNER_LG_PAL_I,      		"LG TAPC-I701D"},
+	{ TUNER_ABSENT,       		"Temic 4042FI5"},
+	{ TUNER_MICROTUNE_4049FM5, 	"Microtune 4049 FM5"},
+	{ TUNER_ABSENT,        		"LG TPI8NSR11F"},
+	{ TUNER_ABSENT,        		"Microtune 4049 FM5 Alt I2C"},
+	{ TUNER_PHILIPS_FM1216ME_MK3, 	"Philips FQ1216ME MK3"},
+	{ TUNER_ABSENT,        		"Philips FI1236 MK3"},
+	{ TUNER_PHILIPS_FM1216ME_MK3, 	"Philips FM1216 ME MK3"},
+	{ TUNER_PHILIPS_FM1236_MK3, 	"Philips FM1236 MK3"},
+	{ TUNER_ABSENT,        		"Philips FM1216MP MK3"},
+	/* 60-69 */
+	{ TUNER_PHILIPS_FM1216ME_MK3, 	"LG S001D MK3"},
+	{ TUNER_ABSENT,        		"LG M001D MK3"},
+	{ TUNER_PHILIPS_FM1216ME_MK3, 	"LG S701D MK3"},
+	{ TUNER_ABSENT,        		"LG M701D MK3"},
+	{ TUNER_ABSENT,        		"Temic 4146FM5"},
+	{ TUNER_ABSENT,        		"Temic 4136FY5"},
+	{ TUNER_ABSENT,        		"Temic 4106FH5"},
+	{ TUNER_ABSENT,        		"Philips FQ1216LMP MK3"},
+	{ TUNER_LG_NTSC_TAPE,  		"LG TAPE H001F MK3"},
+	{ TUNER_LG_NTSC_TAPE,  		"LG TAPE H701F MK3"},
+	/* 70-79 */
+	{ TUNER_ABSENT,        		"LG TALN H200T"},
+	{ TUNER_ABSENT,        		"LG TALN H250T"},
+	{ TUNER_ABSENT,        		"LG TALN M200T"},
+	{ TUNER_ABSENT,        		"LG TALN Z200T"},
+	{ TUNER_ABSENT,        		"LG TALN S200T"},
+	{ TUNER_ABSENT,        		"Thompson DTT7595"},
+	{ TUNER_ABSENT,        		"Thompson DTT7592"},
+	{ TUNER_ABSENT,        		"Silicon TDA8275C1 8290"},
+	{ TUNER_ABSENT,        		"Silicon TDA8275C1 8290 FM"},
+	{ TUNER_ABSENT,        		"Thompson DTT757"},
+	/* 80-89 */
+	{ TUNER_PHILIPS_FQ1216LME_MK3, 	"Philips FQ1216LME MK3"},
+	{ TUNER_LG_PAL_NEW_TAPC, 	"LG TAPC G701D"},
+	{ TUNER_LG_NTSC_NEW_TAPC, 	"LG TAPC H791F"},
+	{ TUNER_LG_PAL_NEW_TAPC, 	"TCL 2002MB 3"},
+	{ TUNER_LG_PAL_NEW_TAPC, 	"TCL 2002MI 3"},
+	{ TUNER_TCL_2002N,     		"TCL 2002N 6A"},
+	{ TUNER_PHILIPS_FM1236_MK3, 	"Philips FQ1236 MK3"},
+	{ TUNER_SAMSUNG_TCPN_2121P30A, 	"Samsung TCPN 2121P30A"},
+	{ TUNER_ABSENT,        		"Samsung TCPE 4121P30A"},
+	{ TUNER_PHILIPS_FM1216ME_MK3, 	"TCL MFPE05 2"},
+	/* 90-99 */
+	{ TUNER_ABSENT,        		"LG TALN H202T"},
+	{ TUNER_PHILIPS_FQ1216AME_MK4, 	"Philips FQ1216AME MK4"},
+	{ TUNER_PHILIPS_FQ1236A_MK4, 	"Philips FQ1236A MK4"},
+	{ TUNER_ABSENT,       		"Philips FQ1286A MK4"},
+	{ TUNER_ABSENT,        		"Philips FQ1216ME MK5"},
+	{ TUNER_ABSENT,        		"Philips FQ1236 MK5"},
+	{ TUNER_SAMSUNG_TCPG_6121P30A, 	"Samsung TCPG 6121P30A"},
+	{ TUNER_TCL_2002MB,    		"TCL 2002MB_3H"},
+	{ TUNER_ABSENT,        		"TCL 2002MI_3H"},
+	{ TUNER_TCL_2002N,     		"TCL 2002N 5H"},
+	/* 100-109 */
+	{ TUNER_PHILIPS_FMD1216ME_MK3, 	"Philips FMD1216ME"},
+	{ TUNER_TEA5767,       		"Philips TEA5768HL FM Radio"},
+	{ TUNER_ABSENT,        		"Panasonic ENV57H12D5"},
+	{ TUNER_PHILIPS_FM1236_MK3, 	"TCL MFNM05-4"},
+	{ TUNER_PHILIPS_FM1236_MK3,	"TCL MNM05-4"},
+	{ TUNER_PHILIPS_FM1216ME_MK3, 	"TCL MPE05-2"},
+	{ TUNER_ABSENT,        		"TCL MQNM05-4"},
+	{ TUNER_ABSENT,        		"LG TAPC-W701D"},
+	{ TUNER_ABSENT,        		"TCL 9886P-WM"},
+	{ TUNER_ABSENT,        		"TCL 1676NM-WM"},
+	/* 110-119 */
+	{ TUNER_ABSENT,        		"Thompson DTT75105"},
+	{ TUNER_ABSENT,        		"Conexant_CX24109"},
+	{ TUNER_TCL_2002N,     		"TCL M2523_5N_E"},
+	{ TUNER_TCL_2002MB,    		"TCL M2523_3DB_E"},
+	{ TUNER_ABSENT,        		"Philips 8275A"},
+	{ TUNER_ABSENT,        		"Microtune MT2060"},
+	{ TUNER_PHILIPS_FM1236_MK3, 	"Philips FM1236 MK5"},
+	{ TUNER_PHILIPS_FM1216ME_MK3, 	"Philips FM1216ME MK5"},
+	{ TUNER_ABSENT,        		"TCL M2523_3DI_E"},
+	{ TUNER_ABSENT,        		"Samsung THPD5222FG30A"},
+	/* 120-129 */
+	{ TUNER_XC2028,        		"Xceive XC3028"},
+	{ TUNER_PHILIPS_FQ1216LME_MK3,	"Philips FQ1216LME MK5"},
+	{ TUNER_ABSENT,        		"Philips FQD1216LME"},
+	{ TUNER_ABSENT,        		"Conexant CX24118A"},
+	{ TUNER_ABSENT,        		"TCL DMF11WIP"},
+	{ TUNER_ABSENT,        		"TCL MFNM05_4H_E"},
+	{ TUNER_ABSENT,        		"TCL MNM05_4H_E"},
+	{ TUNER_ABSENT,        		"TCL MPE05_2H_E"},
+	{ TUNER_ABSENT,        		"TCL MQNM05_4_U"},
+	{ TUNER_ABSENT,        		"TCL M2523_5NH_E"},
+	/* 130-139 */
+	{ TUNER_ABSENT,        		"TCL M2523_3DBH_E"},
+	{ TUNER_ABSENT,        		"TCL M2523_3DIH_E"},
+	{ TUNER_ABSENT,        		"TCL MFPE05_2_U"},
+	{ TUNER_PHILIPS_FMD1216MEX_MK3,	"Philips FMD1216MEX"},
+	{ TUNER_ABSENT,        		"Philips FRH2036B"},
+	{ TUNER_ABSENT,        		"Panasonic ENGF75_01GF"},
+	{ TUNER_ABSENT,        		"MaxLinear MXL5005"},
+	{ TUNER_ABSENT,        		"MaxLinear MXL5003"},
+	{ TUNER_ABSENT,        		"Xceive XC2028"},
+	{ TUNER_ABSENT,        		"Microtune MT2131"},
+	/* 140-149 */
+	{ TUNER_ABSENT,        		"Philips 8275A_8295"},
+	{ TUNER_ABSENT,        		"TCL MF02GIP_5N_E"},
+	{ TUNER_ABSENT,        		"TCL MF02GIP_3DB_E"},
+	{ TUNER_ABSENT,        		"TCL MF02GIP_3DI_E"},
+	{ TUNER_ABSENT,        		"Microtune MT2266"},
+	{ TUNER_ABSENT,        		"TCL MF10WPP_4N_E"},
+	{ TUNER_ABSENT,        		"LG TAPQ_H702F"},
+	{ TUNER_ABSENT,        		"TCL M09WPP_4N_E"},
+	{ TUNER_ABSENT,        		"MaxLinear MXL5005_v2"},
+	{ TUNER_PHILIPS_TDA8290, 	"Philips 18271_8295"},
+	/* 150-159 */
+	{ 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"},
+	{ TUNER_ABSENT,                 "Siano SMS1010"},
+	{ TUNER_ABSENT,                 "Siano SMS1150"},
+	{ TUNER_ABSENT,                 "MaxLinear 5007"},
+	{ TUNER_ABSENT,                 "TCL M09WPP_2P_E"},
+	/* 160-169 */
+	{ TUNER_ABSENT,                 "Siano SMS1180"},
+	{ TUNER_ABSENT,                 "Maxim_MAX2165"},
+	{ TUNER_ABSENT,                 "Siano SMS1140"},
+	{ TUNER_ABSENT,                 "Siano SMS1150 B1"},
+	{ TUNER_ABSENT,                 "MaxLinear 111"},
+	{ TUNER_ABSENT,                 "Dibcom 7770"},
+	{ TUNER_ABSENT,                 "Siano SMS1180VNS"},
+	{ TUNER_ABSENT,                 "Siano SMS1184"},
+	{ TUNER_PHILIPS_FQ1236_MK5,	"TCL M30WTP-4N-E"},
+	{ TUNER_ABSENT,                 "TCL_M11WPP_2PN_E"},
+	/* 170-179 */
+	{ TUNER_ABSENT,                 "MaxLinear 301"},
+	{ TUNER_ABSENT,                 "Mirics MSi001"},
+	{ TUNER_ABSENT,                 "MaxLinear MxL241SF"},
+	{ TUNER_XC5000C,                "Xceive XC5000C"},
+	{ TUNER_ABSENT,                 "Montage M68TS2020"},
+	{ TUNER_ABSENT,                 "Siano SMS1530"},
+	{ TUNER_ABSENT,                 "Dibcom 7090"},
+	{ TUNER_ABSENT,                 "Xceive XC5200C"},
+	{ TUNER_ABSENT,                 "NXP 18273"},
+	{ TUNER_ABSENT,                 "Montage M88TS2022"},
+	/* 180-189 */
+	{ TUNER_ABSENT,                 "NXP 18272M"},
+	{ TUNER_ABSENT,                 "NXP 18272S"},
+};
+
+/* Use V4L2_IDENT_AMBIGUOUS for those audio 'chips' that are
+ * internal to a video chip, i.e. not a separate audio chip. */
+static struct HAUPPAUGE_AUDIOIC
+{
+	u32   id;
+	char *name;
+}
+audioIC[] =
+{
+	/* 0-4 */
+	{ V4L2_IDENT_NONE,      "None"      },
+	{ V4L2_IDENT_UNKNOWN,   "TEA6300"   },
+	{ V4L2_IDENT_UNKNOWN,   "TEA6320"   },
+	{ V4L2_IDENT_UNKNOWN,   "TDA9850"   },
+	{ V4L2_IDENT_MSPX4XX,   "MSP3400C"  },
+	/* 5-9 */
+	{ V4L2_IDENT_MSPX4XX,   "MSP3410D"  },
+	{ V4L2_IDENT_MSPX4XX,   "MSP3415"   },
+	{ V4L2_IDENT_MSPX4XX,   "MSP3430"   },
+	{ V4L2_IDENT_MSPX4XX,   "MSP3438"   },
+	{ V4L2_IDENT_UNKNOWN,   "CS5331"    },
+	/* 10-14 */
+	{ V4L2_IDENT_MSPX4XX,   "MSP3435"   },
+	{ V4L2_IDENT_MSPX4XX,   "MSP3440"   },
+	{ V4L2_IDENT_MSPX4XX,   "MSP3445"   },
+	{ V4L2_IDENT_MSPX4XX,   "MSP3411"   },
+	{ V4L2_IDENT_MSPX4XX,   "MSP3416"   },
+	/* 15-19 */
+	{ V4L2_IDENT_MSPX4XX,   "MSP3425"   },
+	{ V4L2_IDENT_MSPX4XX,   "MSP3451"   },
+	{ V4L2_IDENT_MSPX4XX,   "MSP3418"   },
+	{ V4L2_IDENT_UNKNOWN,   "Type 0x12" },
+	{ V4L2_IDENT_UNKNOWN,   "OKI7716"   },
+	/* 20-24 */
+	{ V4L2_IDENT_MSPX4XX,   "MSP4410"   },
+	{ V4L2_IDENT_MSPX4XX,   "MSP4420"   },
+	{ V4L2_IDENT_MSPX4XX,   "MSP4440"   },
+	{ V4L2_IDENT_MSPX4XX,   "MSP4450"   },
+	{ V4L2_IDENT_MSPX4XX,   "MSP4408"   },
+	/* 25-29 */
+	{ V4L2_IDENT_MSPX4XX,   "MSP4418"   },
+	{ V4L2_IDENT_MSPX4XX,   "MSP4428"   },
+	{ V4L2_IDENT_MSPX4XX,   "MSP4448"   },
+	{ V4L2_IDENT_MSPX4XX,   "MSP4458"   },
+	{ V4L2_IDENT_MSPX4XX,   "Type 0x1d" },
+	/* 30-34 */
+	{ V4L2_IDENT_AMBIGUOUS, "CX880"     },
+	{ V4L2_IDENT_AMBIGUOUS, "CX881"     },
+	{ V4L2_IDENT_AMBIGUOUS, "CX883"     },
+	{ V4L2_IDENT_AMBIGUOUS, "CX882"     },
+	{ V4L2_IDENT_AMBIGUOUS, "CX25840"   },
+	/* 35-39 */
+	{ V4L2_IDENT_AMBIGUOUS, "CX25841"   },
+	{ V4L2_IDENT_AMBIGUOUS, "CX25842"   },
+	{ V4L2_IDENT_AMBIGUOUS, "CX25843"   },
+	{ V4L2_IDENT_AMBIGUOUS, "CX23418"   },
+	{ V4L2_IDENT_AMBIGUOUS, "CX23885"   },
+	/* 40-44 */
+	{ V4L2_IDENT_AMBIGUOUS, "CX23888"   },
+	{ V4L2_IDENT_AMBIGUOUS, "SAA7131"   },
+	{ V4L2_IDENT_AMBIGUOUS, "CX23887"   },
+	{ V4L2_IDENT_AMBIGUOUS, "SAA7164"   },
+	{ V4L2_IDENT_AMBIGUOUS, "AU8522"    },
+};
+
+/* This list is supplied by Hauppauge. Thanks! */
+static const char *decoderIC[] = {
+	/* 0-4 */
+	"None", "BT815", "BT817", "BT819", "BT815A",
+	/* 5-9 */
+	"BT817A", "BT819A", "BT827", "BT829", "BT848",
+	/* 10-14 */
+	"BT848A", "BT849A", "BT829A", "BT827A", "BT878",
+	/* 15-19 */
+	"BT879", "BT880", "VPX3226E", "SAA7114", "SAA7115",
+	/* 20-24 */
+	"CX880", "CX881", "CX883", "SAA7111", "SAA7113",
+	/* 25-29 */
+	"CX882", "TVP5150A", "CX25840", "CX25841", "CX25842",
+	/* 30-34 */
+	"CX25843", "CX23418", "NEC61153", "CX23885", "CX23888",
+	/* 35-39 */
+	"SAA7131", "CX25837", "CX23887", "CX23885A", "CX23887A",
+	/* 40-42 */
+	"SAA7164", "CX23885B", "AU8522"
+};
+
+static int hasRadioTuner(int tunerType)
+{
+	switch (tunerType) {
+	case 18: /* PNPEnv_TUNER_FR1236_MK2 */
+	case 23: /* PNPEnv_TUNER_FM1236 */
+	case 38: /* PNPEnv_TUNER_FMR1236 */
+	case 16: /* PNPEnv_TUNER_FR1216_MK2 */
+	case 19: /* PNPEnv_TUNER_FR1246_MK2 */
+	case 21: /* PNPEnv_TUNER_FM1216 */
+	case 24: /* PNPEnv_TUNER_FM1246 */
+	case 17: /* PNPEnv_TUNER_FR1216MF_MK2 */
+	case 22: /* PNPEnv_TUNER_FM1216MF */
+	case 20: /* PNPEnv_TUNER_FR1256_MK2 */
+	case 25: /* PNPEnv_TUNER_FM1256 */
+	case 33: /* PNPEnv_TUNER_4039FR5 */
+	case 42: /* PNPEnv_TUNER_4009FR5 */
+	case 52: /* PNPEnv_TUNER_4049FM5 */
+	case 54: /* PNPEnv_TUNER_4049FM5_AltI2C */
+	case 44: /* PNPEnv_TUNER_4009FN5 */
+	case 31: /* PNPEnv_TUNER_TCPB9085P */
+	case 30: /* PNPEnv_TUNER_TCPN9085D */
+	case 46: /* PNPEnv_TUNER_TP18NSR01F */
+	case 47: /* PNPEnv_TUNER_TP18PSB01D */
+	case 49: /* PNPEnv_TUNER_TAPC_I001D */
+	case 60: /* PNPEnv_TUNER_TAPE_S001D_MK3 */
+	case 57: /* PNPEnv_TUNER_FM1216ME_MK3 */
+	case 59: /* PNPEnv_TUNER_FM1216MP_MK3 */
+	case 58: /* PNPEnv_TUNER_FM1236_MK3 */
+	case 68: /* PNPEnv_TUNER_TAPE_H001F_MK3 */
+	case 61: /* PNPEnv_TUNER_TAPE_M001D_MK3 */
+	case 78: /* PNPEnv_TUNER_TDA8275C1_8290_FM */
+	case 89: /* PNPEnv_TUNER_TCL_MFPE05_2 */
+	case 92: /* PNPEnv_TUNER_PHILIPS_FQ1236A_MK4 */
+	case 105:
+		return 1;
+	}
+	return 0;
+}
+
+void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee,
+				unsigned char *eeprom_data)
+{
+	/* ----------------------------------------------
+	** The hauppauge eeprom format is tagged
+	**
+	** if packet[0] == 0x84, then packet[0..1] == length
+	** else length = packet[0] & 3f;
+	** if packet[0] & f8 == f8, then EOD and packet[1] == checksum
+	**
+	** In our (ivtv) case we're interested in the following:
+	** tuner type:   tag [00].05 or [0a].01 (index into hauppauge_tuner)
+	** tuner fmts:   tag [00].04 or [0a].00 (bitmask index into
+	**		 hauppauge_tuner_fmt)
+	** radio:        tag [00].{last} or [0e].00  (bitmask.  bit2=FM)
+	** audio proc:   tag [02].01 or [05].00 (mask with 0x7f)
+	** decoder proc: tag [09].01)
+
+	** Fun info:
+	** model:      tag [00].07-08 or [06].00-01
+	** revision:   tag [00].09-0b or [06].04-06
+	** serial#:    tag [01].05-07 or [04].04-06
+
+	** # of inputs/outputs ???
+	*/
+
+	int i, j, len, done, beenhere, tag, start;
+
+	int tuner1 = 0, t_format1 = 0, audioic = -1;
+	char *t_name1 = NULL;
+	const char *t_fmt_name1[8] = { " none", "", "", "", "", "", "", "" };
+
+	int tuner2 = 0, t_format2 = 0;
+	char *t_name2 = NULL;
+	const char *t_fmt_name2[8] = { " none", "", "", "", "", "", "", "" };
+
+	memset(tvee, 0, sizeof(*tvee));
+	tvee->tuner_type = TUNER_ABSENT;
+	tvee->tuner2_type = TUNER_ABSENT;
+
+	done = len = beenhere = 0;
+
+	/* Different eeprom start offsets for em28xx, cx2388x and cx23418 */
+	if (eeprom_data[0] == 0x1a &&
+	    eeprom_data[1] == 0xeb &&
+	    eeprom_data[2] == 0x67 &&
+	    eeprom_data[3] == 0x95)
+		start = 0xa0; /* Generic em28xx offset */
+	else if ((eeprom_data[0] & 0xe1) == 0x01 &&
+		 eeprom_data[1] == 0x00 &&
+		 eeprom_data[2] == 0x00 &&
+		 eeprom_data[8] == 0x84)
+		start = 8; /* Generic cx2388x offset */
+	else if (eeprom_data[1] == 0x70 &&
+		 eeprom_data[2] == 0x00 &&
+		 eeprom_data[4] == 0x74 &&
+		 eeprom_data[8] == 0x84)
+		start = 8; /* Generic cx23418 offset (models 74xxx) */
+	else
+		start = 0;
+
+	for (i = start; !done && i < 256; i += len) {
+		if (eeprom_data[i] == 0x84) {
+			len = eeprom_data[i + 1] + (eeprom_data[i + 2] << 8);
+			i += 3;
+		} else if ((eeprom_data[i] & 0xf0) == 0x70) {
+			if (eeprom_data[i] & 0x08) {
+				/* verify checksum! */
+				done = 1;
+				break;
+			}
+			len = eeprom_data[i] & 0x07;
+			++i;
+		} else {
+			tveeprom_warn("Encountered bad packet header [%02x]. "
+				"Corrupt or not a Hauppauge eeprom.\n",
+				eeprom_data[i]);
+			return;
+		}
+
+		if (debug) {
+			tveeprom_info("Tag [%02x] + %d bytes:",
+					eeprom_data[i], len - 1);
+			for (j = 1; j < len; j++)
+				printk(KERN_CONT " %02x", eeprom_data[i + j]);
+			printk(KERN_CONT "\n");
+		}
+
+		/* process by tag */
+		tag = eeprom_data[i];
+		switch (tag) {
+		case 0x00:
+			/* tag: 'Comprehensive' */
+			tuner1 = eeprom_data[i+6];
+			t_format1 = eeprom_data[i+5];
+			tvee->has_radio = eeprom_data[i+len-1];
+			/* old style tag, don't know how to detect
+			IR presence, mark as unknown. */
+			tvee->has_ir = 0;
+			tvee->model =
+				eeprom_data[i+8] +
+				(eeprom_data[i+9] << 8);
+			tvee->revision = eeprom_data[i+10] +
+				(eeprom_data[i+11] << 8) +
+				(eeprom_data[i+12] << 16);
+			break;
+
+		case 0x01:
+			/* tag: 'SerialID' */
+			tvee->serial_number =
+				eeprom_data[i+6] +
+				(eeprom_data[i+7] << 8) +
+				(eeprom_data[i+8] << 16);
+			break;
+
+		case 0x02:
+			/* tag 'AudioInfo'
+			Note mask with 0x7F, high bit used on some older models
+			to indicate 4052 mux was removed in favor of using MSP
+			inputs directly. */
+			audioic = eeprom_data[i+2] & 0x7f;
+			if (audioic < ARRAY_SIZE(audioIC))
+				tvee->audio_processor = audioIC[audioic].id;
+			else
+				tvee->audio_processor = V4L2_IDENT_UNKNOWN;
+			break;
+
+		/* case 0x03: tag 'EEInfo' */
+
+		case 0x04:
+			/* tag 'SerialID2' */
+			tvee->serial_number =
+				eeprom_data[i+5] +
+				(eeprom_data[i+6] << 8) +
+				(eeprom_data[i+7] << 16);
+
+			if ((eeprom_data[i + 8] & 0xf0) &&
+					(tvee->serial_number < 0xffffff)) {
+				tvee->MAC_address[0] = 0x00;
+				tvee->MAC_address[1] = 0x0D;
+				tvee->MAC_address[2] = 0xFE;
+				tvee->MAC_address[3] = eeprom_data[i + 7];
+				tvee->MAC_address[4] = eeprom_data[i + 6];
+				tvee->MAC_address[5] = eeprom_data[i + 5];
+				tvee->has_MAC_address = 1;
+			}
+			break;
+
+		case 0x05:
+			/* tag 'Audio2'
+			Note mask with 0x7F, high bit used on some older models
+			to indicate 4052 mux was removed in favor of using MSP
+			inputs directly. */
+			audioic = eeprom_data[i+1] & 0x7f;
+			if (audioic < ARRAY_SIZE(audioIC))
+				tvee->audio_processor = audioIC[audioic].id;
+			else
+				tvee->audio_processor = V4L2_IDENT_UNKNOWN;
+
+			break;
+
+		case 0x06:
+			/* tag 'ModelRev' */
+			tvee->model =
+				eeprom_data[i + 1] +
+				(eeprom_data[i + 2] << 8) +
+				(eeprom_data[i + 3] << 16) +
+				(eeprom_data[i + 4] << 24);
+			tvee->revision =
+				eeprom_data[i + 5] +
+				(eeprom_data[i + 6] << 8) +
+				(eeprom_data[i + 7] << 16);
+			break;
+
+		case 0x07:
+			/* tag 'Details': according to Hauppauge not interesting
+			on any PCI-era or later boards. */
+			break;
+
+		/* there is no tag 0x08 defined */
+
+		case 0x09:
+			/* tag 'Video' */
+			tvee->decoder_processor = eeprom_data[i + 1];
+			break;
+
+		case 0x0a:
+			/* tag 'Tuner' */
+			if (beenhere == 0) {
+				tuner1 = eeprom_data[i + 2];
+				t_format1 = eeprom_data[i + 1];
+				beenhere = 1;
+			} else {
+				/* a second (radio) tuner may be present */
+				tuner2 = eeprom_data[i + 2];
+				t_format2 = eeprom_data[i + 1];
+				/* not a TV tuner? */
+				if (t_format2 == 0)
+					tvee->has_radio = 1; /* must be radio */
+			}
+			break;
+
+		case 0x0b:
+			/* tag 'Inputs': according to Hauppauge this is specific
+			to each driver family, so no good assumptions can be
+			made. */
+			break;
+
+		/* case 0x0c: tag 'Balun' */
+		/* case 0x0d: tag 'Teletext' */
+
+		case 0x0e:
+			/* tag: 'Radio' */
+			tvee->has_radio = eeprom_data[i+1];
+			break;
+
+		case 0x0f:
+			/* tag 'IRInfo' */
+			tvee->has_ir = 1 | (eeprom_data[i+1] << 1);
+			break;
+
+		/* case 0x10: tag 'VBIInfo' */
+		/* case 0x11: tag 'QCInfo' */
+		/* case 0x12: tag 'InfoBits' */
+
+		default:
+			tveeprom_dbg("Not sure what to do with tag [%02x]\n",
+					tag);
+			/* dump the rest of the packet? */
+		}
+	}
+
+	if (!done) {
+		tveeprom_warn("Ran out of data!\n");
+		return;
+	}
+
+	if (tvee->revision != 0) {
+		tvee->rev_str[0] = 32 + ((tvee->revision >> 18) & 0x3f);
+		tvee->rev_str[1] = 32 + ((tvee->revision >> 12) & 0x3f);
+		tvee->rev_str[2] = 32 + ((tvee->revision >>  6) & 0x3f);
+		tvee->rev_str[3] = 32 + (tvee->revision & 0x3f);
+		tvee->rev_str[4] = 0;
+	}
+
+	if (hasRadioTuner(tuner1) && !tvee->has_radio) {
+		tveeprom_info("The eeprom says no radio is present, but the tuner type\n");
+		tveeprom_info("indicates otherwise. I will assume that radio is present.\n");
+		tvee->has_radio = 1;
+	}
+
+	if (tuner1 < ARRAY_SIZE(hauppauge_tuner)) {
+		tvee->tuner_type = hauppauge_tuner[tuner1].id;
+		t_name1 = hauppauge_tuner[tuner1].name;
+	} else {
+		t_name1 = "unknown";
+	}
+
+	if (tuner2 < ARRAY_SIZE(hauppauge_tuner)) {
+		tvee->tuner2_type = hauppauge_tuner[tuner2].id;
+		t_name2 = hauppauge_tuner[tuner2].name;
+	} else {
+		t_name2 = "unknown";
+	}
+
+	tvee->tuner_hauppauge_model = tuner1;
+	tvee->tuner2_hauppauge_model = tuner2;
+	tvee->tuner_formats = 0;
+	tvee->tuner2_formats = 0;
+	for (i = j = 0; i < 8; i++) {
+		if (t_format1 & (1 << i)) {
+			tvee->tuner_formats |= hauppauge_tuner_fmt[i].id;
+			t_fmt_name1[j++] = hauppauge_tuner_fmt[i].name;
+		}
+	}
+	for (i = j = 0; i < 8; i++) {
+		if (t_format2 & (1 << i)) {
+			tvee->tuner2_formats |= hauppauge_tuner_fmt[i].id;
+			t_fmt_name2[j++] = hauppauge_tuner_fmt[i].name;
+		}
+	}
+
+	tveeprom_info("Hauppauge model %d, rev %s, serial# %d\n",
+		tvee->model, tvee->rev_str, tvee->serial_number);
+	if (tvee->has_MAC_address == 1)
+		tveeprom_info("MAC address is %pM\n", tvee->MAC_address);
+	tveeprom_info("tuner model is %s (idx %d, type %d)\n",
+		t_name1, tuner1, tvee->tuner_type);
+	tveeprom_info("TV standards%s%s%s%s%s%s%s%s (eeprom 0x%02x)\n",
+		t_fmt_name1[0], t_fmt_name1[1], t_fmt_name1[2],
+		t_fmt_name1[3],	t_fmt_name1[4], t_fmt_name1[5],
+		t_fmt_name1[6], t_fmt_name1[7],	t_format1);
+	if (tuner2)
+		tveeprom_info("second tuner model is %s (idx %d, type %d)\n",
+					t_name2, tuner2, tvee->tuner2_type);
+	if (t_format2)
+		tveeprom_info("TV standards%s%s%s%s%s%s%s%s (eeprom 0x%02x)\n",
+			t_fmt_name2[0], t_fmt_name2[1], t_fmt_name2[2],
+			t_fmt_name2[3],	t_fmt_name2[4], t_fmt_name2[5],
+			t_fmt_name2[6], t_fmt_name2[7], t_format2);
+	if (audioic < 0) {
+		tveeprom_info("audio processor is unknown (no idx)\n");
+		tvee->audio_processor = V4L2_IDENT_UNKNOWN;
+	} else {
+		if (audioic < ARRAY_SIZE(audioIC))
+			tveeprom_info("audio processor is %s (idx %d)\n",
+					audioIC[audioic].name, audioic);
+		else
+			tveeprom_info("audio processor is unknown (idx %d)\n",
+								audioic);
+	}
+	if (tvee->decoder_processor)
+		tveeprom_info("decoder processor is %s (idx %d)\n",
+			STRM(decoderIC, tvee->decoder_processor),
+			tvee->decoder_processor);
+	if (tvee->has_ir)
+		tveeprom_info("has %sradio, has %sIR receiver, has %sIR transmitter\n",
+				tvee->has_radio ? "" : "no ",
+				(tvee->has_ir & 2) ? "" : "no ",
+				(tvee->has_ir & 4) ? "" : "no ");
+	else
+		tveeprom_info("has %sradio\n",
+				tvee->has_radio ? "" : "no ");
+}
+EXPORT_SYMBOL(tveeprom_hauppauge_analog);
+
+/* ----------------------------------------------------------------------- */
+/* generic helper functions                                                */
+
+int tveeprom_read(struct i2c_client *c, unsigned char *eedata, int len)
+{
+	unsigned char buf;
+	int err;
+
+	buf = 0;
+	err = i2c_master_send(c, &buf, 1);
+	if (err != 1) {
+		tveeprom_info("Huh, no eeprom present (err=%d)?\n", err);
+		return -1;
+	}
+	err = i2c_master_recv(c, eedata, len);
+	if (err != len) {
+		tveeprom_warn("i2c eeprom read error (err=%d)\n", err);
+		return -1;
+	}
+	if (debug) {
+		int i;
+
+		tveeprom_info("full 256-byte eeprom dump:\n");
+		for (i = 0; i < len; i++) {
+			if (0 == (i % 16))
+				tveeprom_info("%02x:", i);
+			printk(KERN_CONT " %02x", eedata[i]);
+			if (15 == (i % 16))
+				printk(KERN_CONT "\n");
+		}
+	}
+	return 0;
+}
+EXPORT_SYMBOL(tveeprom_read);
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/i2c/tvp514x.c b/drivers/media/i2c/tvp514x.c
new file mode 100644
index 0000000..1f3943b
--- /dev/null
+++ b/drivers/media/i2c/tvp514x.c
@@ -0,0 +1,1166 @@
+/*
+ * drivers/media/i2c/tvp514x.c
+ *
+ * TI TVP5146/47 decoder driver
+ *
+ * Copyright (C) 2008 Texas Instruments Inc
+ * Author: Vaibhav Hiremath <hvaibhav@ti.com>
+ *
+ * Contributors:
+ *     Sivaraj R <sivaraj@ti.com>
+ *     Brijesh R Jadav <brijesh.j@ti.com>
+ *     Hardik Shah <hardik.shah@ti.com>
+ *     Manjunath Hadli <mrh@ti.com>
+ *     Karicheri Muralidharan <m-karicheri2@ti.com>
+ *
+ * This package is free software; you can 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.
+ *
+ */
+
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/videodev2.h>
+#include <linux/module.h>
+
+#include <media/v4l2-device.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-mediabus.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-ctrls.h>
+#include <media/tvp514x.h>
+
+#include "tvp514x_regs.h"
+
+/* Module Name */
+#define TVP514X_MODULE_NAME		"tvp514x"
+
+/* Private macros for TVP */
+#define I2C_RETRY_COUNT                 (5)
+#define LOCK_RETRY_COUNT                (5)
+#define LOCK_RETRY_DELAY                (200)
+
+/* Debug functions */
+static bool debug;
+module_param(debug, bool, 0644);
+MODULE_PARM_DESC(debug, "Debug level (0-1)");
+
+MODULE_AUTHOR("Texas Instruments");
+MODULE_DESCRIPTION("TVP514X linux decoder driver");
+MODULE_LICENSE("GPL");
+
+/* enum tvp514x_std - enum for supported standards */
+enum tvp514x_std {
+	STD_NTSC_MJ = 0,
+	STD_PAL_BDGHIN,
+	STD_INVALID
+};
+
+/**
+ * struct tvp514x_std_info - Structure to store standard informations
+ * @width: Line width in pixels
+ * @height:Number of active lines
+ * @video_std: Value to write in REG_VIDEO_STD register
+ * @standard: v4l2 standard structure information
+ */
+struct tvp514x_std_info {
+	unsigned long width;
+	unsigned long height;
+	u8 video_std;
+	struct v4l2_standard standard;
+};
+
+static struct tvp514x_reg tvp514x_reg_list_default[0x40];
+
+static int tvp514x_s_stream(struct v4l2_subdev *sd, int enable);
+/**
+ * struct tvp514x_decoder - TVP5146/47 decoder object
+ * @sd: Subdevice Slave handle
+ * @tvp514x_regs: copy of hw's regs with preset values.
+ * @pdata: Board specific
+ * @ver: Chip version
+ * @streaming: TVP5146/47 decoder streaming - enabled or disabled.
+ * @current_std: Current standard
+ * @num_stds: Number of standards
+ * @std_list: Standards list
+ * @input: Input routing at chip level
+ * @output: Output routing at chip level
+ */
+struct tvp514x_decoder {
+	struct v4l2_subdev sd;
+	struct v4l2_ctrl_handler hdl;
+	struct tvp514x_reg tvp514x_regs[ARRAY_SIZE(tvp514x_reg_list_default)];
+	const struct tvp514x_platform_data *pdata;
+
+	int ver;
+	int streaming;
+
+	enum tvp514x_std current_std;
+	int num_stds;
+	const struct tvp514x_std_info *std_list;
+	/* Input and Output Routing parameters */
+	u32 input;
+	u32 output;
+};
+
+/* TVP514x default register values */
+static struct tvp514x_reg tvp514x_reg_list_default[] = {
+	/* Composite selected */
+	{TOK_WRITE, REG_INPUT_SEL, 0x05},
+	{TOK_WRITE, REG_AFE_GAIN_CTRL, 0x0F},
+	/* Auto mode */
+	{TOK_WRITE, REG_VIDEO_STD, 0x00},
+	{TOK_WRITE, REG_OPERATION_MODE, 0x00},
+	{TOK_SKIP, REG_AUTOSWITCH_MASK, 0x3F},
+	{TOK_WRITE, REG_COLOR_KILLER, 0x10},
+	{TOK_WRITE, REG_LUMA_CONTROL1, 0x00},
+	{TOK_WRITE, REG_LUMA_CONTROL2, 0x00},
+	{TOK_WRITE, REG_LUMA_CONTROL3, 0x02},
+	{TOK_WRITE, REG_BRIGHTNESS, 0x80},
+	{TOK_WRITE, REG_CONTRAST, 0x80},
+	{TOK_WRITE, REG_SATURATION, 0x80},
+	{TOK_WRITE, REG_HUE, 0x00},
+	{TOK_WRITE, REG_CHROMA_CONTROL1, 0x00},
+	{TOK_WRITE, REG_CHROMA_CONTROL2, 0x0E},
+	/* Reserved */
+	{TOK_SKIP, 0x0F, 0x00},
+	{TOK_WRITE, REG_COMP_PR_SATURATION, 0x80},
+	{TOK_WRITE, REG_COMP_Y_CONTRAST, 0x80},
+	{TOK_WRITE, REG_COMP_PB_SATURATION, 0x80},
+	/* Reserved */
+	{TOK_SKIP, 0x13, 0x00},
+	{TOK_WRITE, REG_COMP_Y_BRIGHTNESS, 0x80},
+	/* Reserved */
+	{TOK_SKIP, 0x15, 0x00},
+	/* NTSC timing */
+	{TOK_SKIP, REG_AVID_START_PIXEL_LSB, 0x55},
+	{TOK_SKIP, REG_AVID_START_PIXEL_MSB, 0x00},
+	{TOK_SKIP, REG_AVID_STOP_PIXEL_LSB, 0x25},
+	{TOK_SKIP, REG_AVID_STOP_PIXEL_MSB, 0x03},
+	/* NTSC timing */
+	{TOK_SKIP, REG_HSYNC_START_PIXEL_LSB, 0x00},
+	{TOK_SKIP, REG_HSYNC_START_PIXEL_MSB, 0x00},
+	{TOK_SKIP, REG_HSYNC_STOP_PIXEL_LSB, 0x40},
+	{TOK_SKIP, REG_HSYNC_STOP_PIXEL_MSB, 0x00},
+	/* NTSC timing */
+	{TOK_SKIP, REG_VSYNC_START_LINE_LSB, 0x04},
+	{TOK_SKIP, REG_VSYNC_START_LINE_MSB, 0x00},
+	{TOK_SKIP, REG_VSYNC_STOP_LINE_LSB, 0x07},
+	{TOK_SKIP, REG_VSYNC_STOP_LINE_MSB, 0x00},
+	/* NTSC timing */
+	{TOK_SKIP, REG_VBLK_START_LINE_LSB, 0x01},
+	{TOK_SKIP, REG_VBLK_START_LINE_MSB, 0x00},
+	{TOK_SKIP, REG_VBLK_STOP_LINE_LSB, 0x15},
+	{TOK_SKIP, REG_VBLK_STOP_LINE_MSB, 0x00},
+	/* Reserved */
+	{TOK_SKIP, 0x26, 0x00},
+	/* Reserved */
+	{TOK_SKIP, 0x27, 0x00},
+	{TOK_SKIP, REG_FAST_SWTICH_CONTROL, 0xCC},
+	/* Reserved */
+	{TOK_SKIP, 0x29, 0x00},
+	{TOK_SKIP, REG_FAST_SWTICH_SCART_DELAY, 0x00},
+	/* Reserved */
+	{TOK_SKIP, 0x2B, 0x00},
+	{TOK_SKIP, REG_SCART_DELAY, 0x00},
+	{TOK_SKIP, REG_CTI_DELAY, 0x00},
+	{TOK_SKIP, REG_CTI_CONTROL, 0x00},
+	/* Reserved */
+	{TOK_SKIP, 0x2F, 0x00},
+	/* Reserved */
+	{TOK_SKIP, 0x30, 0x00},
+	/* Reserved */
+	{TOK_SKIP, 0x31, 0x00},
+	/* HS, VS active high */
+	{TOK_WRITE, REG_SYNC_CONTROL, 0x00},
+	/* 10-bit BT.656 */
+	{TOK_WRITE, REG_OUTPUT_FORMATTER1, 0x00},
+	/* Enable clk & data */
+	{TOK_WRITE, REG_OUTPUT_FORMATTER2, 0x11},
+	/* Enable AVID & FLD */
+	{TOK_WRITE, REG_OUTPUT_FORMATTER3, 0xEE},
+	/* Enable VS & HS */
+	{TOK_WRITE, REG_OUTPUT_FORMATTER4, 0xAF},
+	{TOK_WRITE, REG_OUTPUT_FORMATTER5, 0xFF},
+	{TOK_WRITE, REG_OUTPUT_FORMATTER6, 0xFF},
+	/* Clear status */
+	{TOK_WRITE, REG_CLEAR_LOST_LOCK, 0x01},
+	{TOK_TERM, 0, 0},
+};
+
+/**
+ * Supported standards -
+ *
+ * Currently supports two standards only, need to add support for rest of the
+ * modes, like SECAM, etc...
+ */
+static const struct tvp514x_std_info tvp514x_std_list[] = {
+	/* Standard: STD_NTSC_MJ */
+	[STD_NTSC_MJ] = {
+	 .width = NTSC_NUM_ACTIVE_PIXELS,
+	 .height = NTSC_NUM_ACTIVE_LINES,
+	 .video_std = VIDEO_STD_NTSC_MJ_BIT,
+	 .standard = {
+		      .index = 0,
+		      .id = V4L2_STD_NTSC,
+		      .name = "NTSC",
+		      .frameperiod = {1001, 30000},
+		      .framelines = 525
+		     },
+	/* Standard: STD_PAL_BDGHIN */
+	},
+	[STD_PAL_BDGHIN] = {
+	 .width = PAL_NUM_ACTIVE_PIXELS,
+	 .height = PAL_NUM_ACTIVE_LINES,
+	 .video_std = VIDEO_STD_PAL_BDGHIN_BIT,
+	 .standard = {
+		      .index = 1,
+		      .id = V4L2_STD_PAL,
+		      .name = "PAL",
+		      .frameperiod = {1, 25},
+		      .framelines = 625
+		     },
+	},
+	/* Standard: need to add for additional standard */
+};
+
+
+static inline struct tvp514x_decoder *to_decoder(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct tvp514x_decoder, sd);
+}
+
+static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
+{
+	return &container_of(ctrl->handler, struct tvp514x_decoder, hdl)->sd;
+}
+
+
+/**
+ * tvp514x_read_reg() - Read a value from a register in an TVP5146/47.
+ * @sd: ptr to v4l2_subdev struct
+ * @reg: TVP5146/47 register address
+ *
+ * Returns value read if successful, or non-zero (-1) otherwise.
+ */
+static int tvp514x_read_reg(struct v4l2_subdev *sd, u8 reg)
+{
+	int err, retry = 0;
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+read_again:
+
+	err = i2c_smbus_read_byte_data(client, reg);
+	if (err < 0) {
+		if (retry <= I2C_RETRY_COUNT) {
+			v4l2_warn(sd, "Read: retry ... %d\n", retry);
+			retry++;
+			msleep_interruptible(10);
+			goto read_again;
+		}
+	}
+
+	return err;
+}
+
+/**
+ * dump_reg() - dump the register content of TVP5146/47.
+ * @sd: ptr to v4l2_subdev struct
+ * @reg: TVP5146/47 register address
+ */
+static void dump_reg(struct v4l2_subdev *sd, u8 reg)
+{
+	u32 val;
+
+	val = tvp514x_read_reg(sd, reg);
+	v4l2_info(sd, "Reg(0x%.2X): 0x%.2X\n", reg, val);
+}
+
+/**
+ * tvp514x_write_reg() - Write a value to a register in TVP5146/47
+ * @sd: ptr to v4l2_subdev struct
+ * @reg: TVP5146/47 register address
+ * @val: value to be written to the register
+ *
+ * Write a value to a register in an TVP5146/47 decoder device.
+ * Returns zero if successful, or non-zero otherwise.
+ */
+static int tvp514x_write_reg(struct v4l2_subdev *sd, u8 reg, u8 val)
+{
+	int err, retry = 0;
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+write_again:
+
+	err = i2c_smbus_write_byte_data(client, reg, val);
+	if (err) {
+		if (retry <= I2C_RETRY_COUNT) {
+			v4l2_warn(sd, "Write: retry ... %d\n", retry);
+			retry++;
+			msleep_interruptible(10);
+			goto write_again;
+		}
+	}
+
+	return err;
+}
+
+/**
+ * tvp514x_write_regs() : Initializes a list of TVP5146/47 registers
+ * @sd: ptr to v4l2_subdev struct
+ * @reglist: list of TVP5146/47 registers and values
+ *
+ * Initializes a list of TVP5146/47 registers:-
+ *		if token is TOK_TERM, then entire write operation terminates
+ *		if token is TOK_DELAY, then a delay of 'val' msec is introduced
+ *		if token is TOK_SKIP, then the register write is skipped
+ *		if token is TOK_WRITE, then the register write is performed
+ * Returns zero if successful, or non-zero otherwise.
+ */
+static int tvp514x_write_regs(struct v4l2_subdev *sd,
+			      const struct tvp514x_reg reglist[])
+{
+	int err;
+	const struct tvp514x_reg *next = reglist;
+
+	for (; next->token != TOK_TERM; next++) {
+		if (next->token == TOK_DELAY) {
+			msleep(next->val);
+			continue;
+		}
+
+		if (next->token == TOK_SKIP)
+			continue;
+
+		err = tvp514x_write_reg(sd, next->reg, (u8) next->val);
+		if (err) {
+			v4l2_err(sd, "Write failed. Err[%d]\n", err);
+			return err;
+		}
+	}
+	return 0;
+}
+
+/**
+ * tvp514x_query_current_std() : Query the current standard detected by TVP5146/47
+ * @sd: ptr to v4l2_subdev struct
+ *
+ * Returns the current standard detected by TVP5146/47, STD_INVALID if there is no
+ * standard detected.
+ */
+static enum tvp514x_std tvp514x_query_current_std(struct v4l2_subdev *sd)
+{
+	u8 std, std_status;
+
+	std = tvp514x_read_reg(sd, REG_VIDEO_STD);
+	if ((std & VIDEO_STD_MASK) == VIDEO_STD_AUTO_SWITCH_BIT)
+		/* use the standard status register */
+		std_status = tvp514x_read_reg(sd, REG_VIDEO_STD_STATUS);
+	else
+		/* use the standard register itself */
+		std_status = std;
+
+	switch (std_status & VIDEO_STD_MASK) {
+	case VIDEO_STD_NTSC_MJ_BIT:
+		return STD_NTSC_MJ;
+
+	case VIDEO_STD_PAL_BDGHIN_BIT:
+		return STD_PAL_BDGHIN;
+
+	default:
+		return STD_INVALID;
+	}
+
+	return STD_INVALID;
+}
+
+/* TVP5146/47 register dump function */
+static void tvp514x_reg_dump(struct v4l2_subdev *sd)
+{
+	dump_reg(sd, REG_INPUT_SEL);
+	dump_reg(sd, REG_AFE_GAIN_CTRL);
+	dump_reg(sd, REG_VIDEO_STD);
+	dump_reg(sd, REG_OPERATION_MODE);
+	dump_reg(sd, REG_COLOR_KILLER);
+	dump_reg(sd, REG_LUMA_CONTROL1);
+	dump_reg(sd, REG_LUMA_CONTROL2);
+	dump_reg(sd, REG_LUMA_CONTROL3);
+	dump_reg(sd, REG_BRIGHTNESS);
+	dump_reg(sd, REG_CONTRAST);
+	dump_reg(sd, REG_SATURATION);
+	dump_reg(sd, REG_HUE);
+	dump_reg(sd, REG_CHROMA_CONTROL1);
+	dump_reg(sd, REG_CHROMA_CONTROL2);
+	dump_reg(sd, REG_COMP_PR_SATURATION);
+	dump_reg(sd, REG_COMP_Y_CONTRAST);
+	dump_reg(sd, REG_COMP_PB_SATURATION);
+	dump_reg(sd, REG_COMP_Y_BRIGHTNESS);
+	dump_reg(sd, REG_AVID_START_PIXEL_LSB);
+	dump_reg(sd, REG_AVID_START_PIXEL_MSB);
+	dump_reg(sd, REG_AVID_STOP_PIXEL_LSB);
+	dump_reg(sd, REG_AVID_STOP_PIXEL_MSB);
+	dump_reg(sd, REG_HSYNC_START_PIXEL_LSB);
+	dump_reg(sd, REG_HSYNC_START_PIXEL_MSB);
+	dump_reg(sd, REG_HSYNC_STOP_PIXEL_LSB);
+	dump_reg(sd, REG_HSYNC_STOP_PIXEL_MSB);
+	dump_reg(sd, REG_VSYNC_START_LINE_LSB);
+	dump_reg(sd, REG_VSYNC_START_LINE_MSB);
+	dump_reg(sd, REG_VSYNC_STOP_LINE_LSB);
+	dump_reg(sd, REG_VSYNC_STOP_LINE_MSB);
+	dump_reg(sd, REG_VBLK_START_LINE_LSB);
+	dump_reg(sd, REG_VBLK_START_LINE_MSB);
+	dump_reg(sd, REG_VBLK_STOP_LINE_LSB);
+	dump_reg(sd, REG_VBLK_STOP_LINE_MSB);
+	dump_reg(sd, REG_SYNC_CONTROL);
+	dump_reg(sd, REG_OUTPUT_FORMATTER1);
+	dump_reg(sd, REG_OUTPUT_FORMATTER2);
+	dump_reg(sd, REG_OUTPUT_FORMATTER3);
+	dump_reg(sd, REG_OUTPUT_FORMATTER4);
+	dump_reg(sd, REG_OUTPUT_FORMATTER5);
+	dump_reg(sd, REG_OUTPUT_FORMATTER6);
+	dump_reg(sd, REG_CLEAR_LOST_LOCK);
+}
+
+/**
+ * tvp514x_configure() - Configure the TVP5146/47 registers
+ * @sd: ptr to v4l2_subdev struct
+ * @decoder: ptr to tvp514x_decoder structure
+ *
+ * Returns zero if successful, or non-zero otherwise.
+ */
+static int tvp514x_configure(struct v4l2_subdev *sd,
+		struct tvp514x_decoder *decoder)
+{
+	int err;
+
+	/* common register initialization */
+	err =
+	    tvp514x_write_regs(sd, decoder->tvp514x_regs);
+	if (err)
+		return err;
+
+	if (debug)
+		tvp514x_reg_dump(sd);
+
+	return 0;
+}
+
+/**
+ * tvp514x_detect() - Detect if an tvp514x is present, and if so which revision.
+ * @sd: pointer to standard V4L2 sub-device structure
+ * @decoder: pointer to tvp514x_decoder structure
+ *
+ * A device is considered to be detected if the chip ID (LSB and MSB)
+ * registers match the expected values.
+ * Any value of the rom version register is accepted.
+ * Returns ENODEV error number if no device is detected, or zero
+ * if a device is detected.
+ */
+static int tvp514x_detect(struct v4l2_subdev *sd,
+		struct tvp514x_decoder *decoder)
+{
+	u8 chip_id_msb, chip_id_lsb, rom_ver;
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	chip_id_msb = tvp514x_read_reg(sd, REG_CHIP_ID_MSB);
+	chip_id_lsb = tvp514x_read_reg(sd, REG_CHIP_ID_LSB);
+	rom_ver = tvp514x_read_reg(sd, REG_ROM_VERSION);
+
+	v4l2_dbg(1, debug, sd,
+		 "chip id detected msb:0x%x lsb:0x%x rom version:0x%x\n",
+		 chip_id_msb, chip_id_lsb, rom_ver);
+	if ((chip_id_msb != TVP514X_CHIP_ID_MSB)
+		|| ((chip_id_lsb != TVP5146_CHIP_ID_LSB)
+		&& (chip_id_lsb != TVP5147_CHIP_ID_LSB))) {
+		/* We didn't read the values we expected, so this must not be
+		 * an TVP5146/47.
+		 */
+		v4l2_err(sd, "chip id mismatch msb:0x%x lsb:0x%x\n",
+				chip_id_msb, chip_id_lsb);
+		return -ENODEV;
+	}
+
+	decoder->ver = rom_ver;
+
+	v4l2_info(sd, "%s (Version - 0x%.2x) found at 0x%x (%s)\n",
+			client->name, decoder->ver,
+			client->addr << 1, client->adapter->name);
+	return 0;
+}
+
+/**
+ * tvp514x_querystd() - V4L2 decoder interface handler for querystd
+ * @sd: pointer to standard V4L2 sub-device structure
+ * @std_id: standard V4L2 std_id ioctl enum
+ *
+ * Returns the current standard detected by TVP5146/47. If no active input is
+ * detected then *std_id is set to 0 and the function returns 0.
+ */
+static int tvp514x_querystd(struct v4l2_subdev *sd, v4l2_std_id *std_id)
+{
+	struct tvp514x_decoder *decoder = to_decoder(sd);
+	enum tvp514x_std current_std;
+	enum tvp514x_input input_sel;
+	u8 sync_lock_status, lock_mask;
+
+	if (std_id == NULL)
+		return -EINVAL;
+
+	*std_id = V4L2_STD_UNKNOWN;
+
+	/* query the current standard */
+	current_std = tvp514x_query_current_std(sd);
+	if (current_std == STD_INVALID)
+		return 0;
+
+	input_sel = decoder->input;
+
+	switch (input_sel) {
+	case INPUT_CVBS_VI1A:
+	case INPUT_CVBS_VI1B:
+	case INPUT_CVBS_VI1C:
+	case INPUT_CVBS_VI2A:
+	case INPUT_CVBS_VI2B:
+	case INPUT_CVBS_VI2C:
+	case INPUT_CVBS_VI3A:
+	case INPUT_CVBS_VI3B:
+	case INPUT_CVBS_VI3C:
+	case INPUT_CVBS_VI4A:
+		lock_mask = STATUS_CLR_SUBCAR_LOCK_BIT |
+			STATUS_HORZ_SYNC_LOCK_BIT |
+			STATUS_VIRT_SYNC_LOCK_BIT;
+		break;
+
+	case INPUT_SVIDEO_VI2A_VI1A:
+	case INPUT_SVIDEO_VI2B_VI1B:
+	case INPUT_SVIDEO_VI2C_VI1C:
+	case INPUT_SVIDEO_VI2A_VI3A:
+	case INPUT_SVIDEO_VI2B_VI3B:
+	case INPUT_SVIDEO_VI2C_VI3C:
+	case INPUT_SVIDEO_VI4A_VI1A:
+	case INPUT_SVIDEO_VI4A_VI1B:
+	case INPUT_SVIDEO_VI4A_VI1C:
+	case INPUT_SVIDEO_VI4A_VI3A:
+	case INPUT_SVIDEO_VI4A_VI3B:
+	case INPUT_SVIDEO_VI4A_VI3C:
+		lock_mask = STATUS_HORZ_SYNC_LOCK_BIT |
+			STATUS_VIRT_SYNC_LOCK_BIT;
+		break;
+		/*Need to add other interfaces*/
+	default:
+		return -EINVAL;
+	}
+	/* check whether signal is locked */
+	sync_lock_status = tvp514x_read_reg(sd, REG_STATUS1);
+	if (lock_mask != (sync_lock_status & lock_mask))
+		return 0;	/* No input detected */
+
+	*std_id = decoder->std_list[current_std].standard.id;
+
+	v4l2_dbg(1, debug, sd, "Current STD: %s\n",
+			decoder->std_list[current_std].standard.name);
+	return 0;
+}
+
+/**
+ * tvp514x_s_std() - V4L2 decoder interface handler for s_std
+ * @sd: pointer to standard V4L2 sub-device structure
+ * @std_id: standard V4L2 v4l2_std_id ioctl enum
+ *
+ * If std_id is supported, sets the requested standard. Otherwise, returns
+ * -EINVAL
+ */
+static int tvp514x_s_std(struct v4l2_subdev *sd, v4l2_std_id std_id)
+{
+	struct tvp514x_decoder *decoder = to_decoder(sd);
+	int err, i;
+
+	for (i = 0; i < decoder->num_stds; i++)
+		if (std_id & decoder->std_list[i].standard.id)
+			break;
+
+	if ((i == decoder->num_stds) || (i == STD_INVALID))
+		return -EINVAL;
+
+	err = tvp514x_write_reg(sd, REG_VIDEO_STD,
+				decoder->std_list[i].video_std);
+	if (err)
+		return err;
+
+	decoder->current_std = i;
+	decoder->tvp514x_regs[REG_VIDEO_STD].val =
+		decoder->std_list[i].video_std;
+
+	v4l2_dbg(1, debug, sd, "Standard set to: %s\n",
+			decoder->std_list[i].standard.name);
+	return 0;
+}
+
+/**
+ * tvp514x_s_routing() - V4L2 decoder interface handler for s_routing
+ * @sd: pointer to standard V4L2 sub-device structure
+ * @input: input selector for routing the signal
+ * @output: output selector for routing the signal
+ * @config: config value. Not used
+ *
+ * If index is valid, selects the requested input. Otherwise, returns -EINVAL if
+ * the input is not supported or there is no active signal present in the
+ * selected input.
+ */
+static int tvp514x_s_routing(struct v4l2_subdev *sd,
+				u32 input, u32 output, u32 config)
+{
+	struct tvp514x_decoder *decoder = to_decoder(sd);
+	int err;
+	enum tvp514x_input input_sel;
+	enum tvp514x_output output_sel;
+	u8 sync_lock_status, lock_mask;
+	int try_count = LOCK_RETRY_COUNT;
+
+	if ((input >= INPUT_INVALID) ||
+			(output >= OUTPUT_INVALID))
+		/* Index out of bound */
+		return -EINVAL;
+
+	/*
+	 * For the sequence streamon -> streamoff and again s_input
+	 * it fails to lock the signal, since streamoff puts TVP514x
+	 * into power off state which leads to failure in sub-sequent s_input.
+	 *
+	 * So power up the TVP514x device here, since it is important to lock
+	 * the signal at this stage.
+	 */
+	if (!decoder->streaming)
+		tvp514x_s_stream(sd, 1);
+
+	input_sel = input;
+	output_sel = output;
+
+	err = tvp514x_write_reg(sd, REG_INPUT_SEL, input_sel);
+	if (err)
+		return err;
+
+	output_sel |= tvp514x_read_reg(sd,
+			REG_OUTPUT_FORMATTER1) & 0x7;
+	err = tvp514x_write_reg(sd, REG_OUTPUT_FORMATTER1,
+			output_sel);
+	if (err)
+		return err;
+
+	decoder->tvp514x_regs[REG_INPUT_SEL].val = input_sel;
+	decoder->tvp514x_regs[REG_OUTPUT_FORMATTER1].val = output_sel;
+
+	/* Clear status */
+	msleep(LOCK_RETRY_DELAY);
+	err =
+	    tvp514x_write_reg(sd, REG_CLEAR_LOST_LOCK, 0x01);
+	if (err)
+		return err;
+
+	switch (input_sel) {
+	case INPUT_CVBS_VI1A:
+	case INPUT_CVBS_VI1B:
+	case INPUT_CVBS_VI1C:
+	case INPUT_CVBS_VI2A:
+	case INPUT_CVBS_VI2B:
+	case INPUT_CVBS_VI2C:
+	case INPUT_CVBS_VI3A:
+	case INPUT_CVBS_VI3B:
+	case INPUT_CVBS_VI3C:
+	case INPUT_CVBS_VI4A:
+		lock_mask = STATUS_CLR_SUBCAR_LOCK_BIT |
+			STATUS_HORZ_SYNC_LOCK_BIT |
+			STATUS_VIRT_SYNC_LOCK_BIT;
+		break;
+
+	case INPUT_SVIDEO_VI2A_VI1A:
+	case INPUT_SVIDEO_VI2B_VI1B:
+	case INPUT_SVIDEO_VI2C_VI1C:
+	case INPUT_SVIDEO_VI2A_VI3A:
+	case INPUT_SVIDEO_VI2B_VI3B:
+	case INPUT_SVIDEO_VI2C_VI3C:
+	case INPUT_SVIDEO_VI4A_VI1A:
+	case INPUT_SVIDEO_VI4A_VI1B:
+	case INPUT_SVIDEO_VI4A_VI1C:
+	case INPUT_SVIDEO_VI4A_VI3A:
+	case INPUT_SVIDEO_VI4A_VI3B:
+	case INPUT_SVIDEO_VI4A_VI3C:
+		lock_mask = STATUS_HORZ_SYNC_LOCK_BIT |
+			STATUS_VIRT_SYNC_LOCK_BIT;
+		break;
+	/* Need to add other interfaces*/
+	default:
+		return -EINVAL;
+	}
+
+	while (try_count-- > 0) {
+		/* Allow decoder to sync up with new input */
+		msleep(LOCK_RETRY_DELAY);
+
+		sync_lock_status = tvp514x_read_reg(sd,
+				REG_STATUS1);
+		if (lock_mask == (sync_lock_status & lock_mask))
+			/* Input detected */
+			break;
+	}
+
+	if (try_count < 0)
+		return -EINVAL;
+
+	decoder->input = input;
+	decoder->output = output;
+
+	v4l2_dbg(1, debug, sd, "Input set to: %d\n", input_sel);
+
+	return 0;
+}
+
+/**
+ * tvp514x_s_ctrl() - V4L2 decoder interface handler for s_ctrl
+ * @ctrl: pointer to v4l2_ctrl structure
+ *
+ * If the requested control is supported, sets the control's current
+ * value in HW. Otherwise, returns -EINVAL if the control is not supported.
+ */
+static int tvp514x_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct v4l2_subdev *sd = to_sd(ctrl);
+	struct tvp514x_decoder *decoder = to_decoder(sd);
+	int err = -EINVAL, value;
+
+	value = ctrl->val;
+
+	switch (ctrl->id) {
+	case V4L2_CID_BRIGHTNESS:
+		err = tvp514x_write_reg(sd, REG_BRIGHTNESS, value);
+		if (!err)
+			decoder->tvp514x_regs[REG_BRIGHTNESS].val = value;
+		break;
+	case V4L2_CID_CONTRAST:
+		err = tvp514x_write_reg(sd, REG_CONTRAST, value);
+		if (!err)
+			decoder->tvp514x_regs[REG_CONTRAST].val = value;
+		break;
+	case V4L2_CID_SATURATION:
+		err = tvp514x_write_reg(sd, REG_SATURATION, value);
+		if (!err)
+			decoder->tvp514x_regs[REG_SATURATION].val = value;
+		break;
+	case V4L2_CID_HUE:
+		if (value == 180)
+			value = 0x7F;
+		else if (value == -180)
+			value = 0x80;
+		err = tvp514x_write_reg(sd, REG_HUE, value);
+		if (!err)
+			decoder->tvp514x_regs[REG_HUE].val = value;
+		break;
+	case V4L2_CID_AUTOGAIN:
+		err = tvp514x_write_reg(sd, REG_AFE_GAIN_CTRL, value ? 0x0f : 0x0c);
+		if (!err)
+			decoder->tvp514x_regs[REG_AFE_GAIN_CTRL].val = value;
+		break;
+	}
+
+	v4l2_dbg(1, debug, sd, "Set Control: ID - %d - %d\n",
+			ctrl->id, ctrl->val);
+	return err;
+}
+
+/**
+ * tvp514x_enum_mbus_fmt() - V4L2 decoder interface handler for enum_mbus_fmt
+ * @sd: pointer to standard V4L2 sub-device structure
+ * @index: index of pixelcode to retrieve
+ * @code: receives the pixelcode
+ *
+ * Enumerates supported mediabus formats
+ */
+static int
+tvp514x_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index,
+					enum v4l2_mbus_pixelcode *code)
+{
+	if (index)
+		return -EINVAL;
+
+	*code = V4L2_MBUS_FMT_YUYV10_2X10;
+	return 0;
+}
+
+/**
+ * tvp514x_mbus_fmt_cap() - V4L2 decoder interface handler for try/s/g_mbus_fmt
+ * @sd: pointer to standard V4L2 sub-device structure
+ * @f: pointer to the mediabus format structure
+ *
+ * Negotiates the image capture size and mediabus format.
+ */
+static int
+tvp514x_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *f)
+{
+	struct tvp514x_decoder *decoder = to_decoder(sd);
+	enum tvp514x_std current_std;
+
+	if (f == NULL)
+		return -EINVAL;
+
+	/* Calculate height and width based on current standard */
+	current_std = decoder->current_std;
+
+	f->code = V4L2_MBUS_FMT_YUYV10_2X10;
+	f->width = decoder->std_list[current_std].width;
+	f->height = decoder->std_list[current_std].height;
+	f->field = V4L2_FIELD_INTERLACED;
+	f->colorspace = V4L2_COLORSPACE_SMPTE170M;
+
+	v4l2_dbg(1, debug, sd, "MBUS_FMT: Width - %d, Height - %d\n",
+			f->width, f->height);
+	return 0;
+}
+
+/**
+ * tvp514x_g_parm() - V4L2 decoder interface handler for g_parm
+ * @sd: pointer to standard V4L2 sub-device structure
+ * @a: pointer to standard V4L2 VIDIOC_G_PARM ioctl structure
+ *
+ * Returns the decoder's video CAPTURE parameters.
+ */
+static int
+tvp514x_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *a)
+{
+	struct tvp514x_decoder *decoder = to_decoder(sd);
+	struct v4l2_captureparm *cparm;
+	enum tvp514x_std current_std;
+
+	if (a == NULL)
+		return -EINVAL;
+
+	if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		/* only capture is supported */
+		return -EINVAL;
+
+	/* get the current standard */
+	current_std = decoder->current_std;
+
+	cparm = &a->parm.capture;
+	cparm->capability = V4L2_CAP_TIMEPERFRAME;
+	cparm->timeperframe =
+		decoder->std_list[current_std].standard.frameperiod;
+
+	return 0;
+}
+
+/**
+ * tvp514x_s_parm() - V4L2 decoder interface handler for s_parm
+ * @sd: pointer to standard V4L2 sub-device structure
+ * @a: pointer to standard V4L2 VIDIOC_S_PARM ioctl structure
+ *
+ * Configures the decoder to use the input parameters, if possible. If
+ * not possible, returns the appropriate error code.
+ */
+static int
+tvp514x_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *a)
+{
+	struct tvp514x_decoder *decoder = to_decoder(sd);
+	struct v4l2_fract *timeperframe;
+	enum tvp514x_std current_std;
+
+	if (a == NULL)
+		return -EINVAL;
+
+	if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		/* only capture is supported */
+		return -EINVAL;
+
+	timeperframe = &a->parm.capture.timeperframe;
+
+	/* get the current standard */
+	current_std = decoder->current_std;
+
+	*timeperframe =
+	    decoder->std_list[current_std].standard.frameperiod;
+
+	return 0;
+}
+
+/**
+ * tvp514x_s_stream() - V4L2 decoder i/f handler for s_stream
+ * @sd: pointer to standard V4L2 sub-device structure
+ * @enable: streaming enable or disable
+ *
+ * Sets streaming to enable or disable, if possible.
+ */
+static int tvp514x_s_stream(struct v4l2_subdev *sd, int enable)
+{
+	int err = 0;
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct tvp514x_decoder *decoder = to_decoder(sd);
+
+	if (decoder->streaming == enable)
+		return 0;
+
+	switch (enable) {
+	case 0:
+	{
+		/* Power Down Sequence */
+		err = tvp514x_write_reg(sd, REG_OPERATION_MODE, 0x01);
+		if (err) {
+			v4l2_err(sd, "Unable to turn off decoder\n");
+			return err;
+		}
+		decoder->streaming = enable;
+		break;
+	}
+	case 1:
+	{
+		struct tvp514x_reg *int_seq = (struct tvp514x_reg *)
+				client->driver->id_table->driver_data;
+
+		/* Power Up Sequence */
+		err = tvp514x_write_regs(sd, int_seq);
+		if (err) {
+			v4l2_err(sd, "Unable to turn on decoder\n");
+			return err;
+		}
+		/* Detect if not already detected */
+		err = tvp514x_detect(sd, decoder);
+		if (err) {
+			v4l2_err(sd, "Unable to detect decoder\n");
+			return err;
+		}
+		err = tvp514x_configure(sd, decoder);
+		if (err) {
+			v4l2_err(sd, "Unable to configure decoder\n");
+			return err;
+		}
+		decoder->streaming = enable;
+		break;
+	}
+	default:
+		err = -ENODEV;
+		break;
+	}
+
+	return err;
+}
+
+static const struct v4l2_ctrl_ops tvp514x_ctrl_ops = {
+	.s_ctrl = tvp514x_s_ctrl,
+};
+
+static const struct v4l2_subdev_core_ops tvp514x_core_ops = {
+	.g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
+	.try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
+	.s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
+	.g_ctrl = v4l2_subdev_g_ctrl,
+	.s_ctrl = v4l2_subdev_s_ctrl,
+	.queryctrl = v4l2_subdev_queryctrl,
+	.querymenu = v4l2_subdev_querymenu,
+	.s_std = tvp514x_s_std,
+};
+
+static const struct v4l2_subdev_video_ops tvp514x_video_ops = {
+	.s_routing = tvp514x_s_routing,
+	.querystd = tvp514x_querystd,
+	.enum_mbus_fmt = tvp514x_enum_mbus_fmt,
+	.g_mbus_fmt = tvp514x_mbus_fmt,
+	.try_mbus_fmt = tvp514x_mbus_fmt,
+	.s_mbus_fmt = tvp514x_mbus_fmt,
+	.g_parm = tvp514x_g_parm,
+	.s_parm = tvp514x_s_parm,
+	.s_stream = tvp514x_s_stream,
+};
+
+static const struct v4l2_subdev_ops tvp514x_ops = {
+	.core = &tvp514x_core_ops,
+	.video = &tvp514x_video_ops,
+};
+
+static struct tvp514x_decoder tvp514x_dev = {
+	.streaming = 0,
+	.current_std = STD_NTSC_MJ,
+	.std_list = tvp514x_std_list,
+	.num_stds = ARRAY_SIZE(tvp514x_std_list),
+
+};
+
+/**
+ * tvp514x_probe() - decoder driver i2c probe handler
+ * @client: i2c driver client device structure
+ * @id: i2c driver id table
+ *
+ * Register decoder as an i2c client device and V4L2
+ * device.
+ */
+static int
+tvp514x_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+	struct tvp514x_decoder *decoder;
+	struct v4l2_subdev *sd;
+
+	/* Check if the adapter supports the needed features */
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		return -EIO;
+
+	if (!client->dev.platform_data) {
+		v4l2_err(client, "No platform data!!\n");
+		return -ENODEV;
+	}
+
+	decoder = kzalloc(sizeof(*decoder), GFP_KERNEL);
+	if (!decoder)
+		return -ENOMEM;
+
+	/* Initialize the tvp514x_decoder with default configuration */
+	*decoder = tvp514x_dev;
+	/* Copy default register configuration */
+	memcpy(decoder->tvp514x_regs, tvp514x_reg_list_default,
+			sizeof(tvp514x_reg_list_default));
+
+	/* Copy board specific information here */
+	decoder->pdata = client->dev.platform_data;
+
+	/**
+	 * Fetch platform specific data, and configure the
+	 * tvp514x_reg_list[] accordingly. Since this is one
+	 * time configuration, no need to preserve.
+	 */
+	decoder->tvp514x_regs[REG_OUTPUT_FORMATTER2].val |=
+		(decoder->pdata->clk_polarity << 1);
+	decoder->tvp514x_regs[REG_SYNC_CONTROL].val |=
+		((decoder->pdata->hs_polarity << 2) |
+		 (decoder->pdata->vs_polarity << 3));
+	/* Set default standard to auto */
+	decoder->tvp514x_regs[REG_VIDEO_STD].val =
+		VIDEO_STD_AUTO_SWITCH_BIT;
+
+	/* Register with V4L2 layer as slave device */
+	sd = &decoder->sd;
+	v4l2_i2c_subdev_init(sd, client, &tvp514x_ops);
+
+	v4l2_ctrl_handler_init(&decoder->hdl, 5);
+	v4l2_ctrl_new_std(&decoder->hdl, &tvp514x_ctrl_ops,
+		V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
+	v4l2_ctrl_new_std(&decoder->hdl, &tvp514x_ctrl_ops,
+		V4L2_CID_CONTRAST, 0, 255, 1, 128);
+	v4l2_ctrl_new_std(&decoder->hdl, &tvp514x_ctrl_ops,
+		V4L2_CID_SATURATION, 0, 255, 1, 128);
+	v4l2_ctrl_new_std(&decoder->hdl, &tvp514x_ctrl_ops,
+		V4L2_CID_HUE, -180, 180, 180, 0);
+	v4l2_ctrl_new_std(&decoder->hdl, &tvp514x_ctrl_ops,
+		V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
+	sd->ctrl_handler = &decoder->hdl;
+	if (decoder->hdl.error) {
+		int err = decoder->hdl.error;
+
+		v4l2_ctrl_handler_free(&decoder->hdl);
+		kfree(decoder);
+		return err;
+	}
+	v4l2_ctrl_handler_setup(&decoder->hdl);
+
+	v4l2_info(sd, "%s decoder driver registered !!\n", sd->name);
+
+	return 0;
+
+}
+
+/**
+ * tvp514x_remove() - decoder driver i2c remove handler
+ * @client: i2c driver client device structure
+ *
+ * Unregister decoder as an i2c client device and V4L2
+ * device. Complement of tvp514x_probe().
+ */
+static int tvp514x_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct tvp514x_decoder *decoder = to_decoder(sd);
+
+	v4l2_device_unregister_subdev(sd);
+	v4l2_ctrl_handler_free(&decoder->hdl);
+	kfree(decoder);
+	return 0;
+}
+/* TVP5146 Init/Power on Sequence */
+static const struct tvp514x_reg tvp5146_init_reg_seq[] = {
+	{TOK_WRITE, REG_VBUS_ADDRESS_ACCESS1, 0x02},
+	{TOK_WRITE, REG_VBUS_ADDRESS_ACCESS2, 0x00},
+	{TOK_WRITE, REG_VBUS_ADDRESS_ACCESS3, 0x80},
+	{TOK_WRITE, REG_VBUS_DATA_ACCESS_NO_VBUS_ADDR_INCR, 0x01},
+	{TOK_WRITE, REG_VBUS_ADDRESS_ACCESS1, 0x60},
+	{TOK_WRITE, REG_VBUS_ADDRESS_ACCESS2, 0x00},
+	{TOK_WRITE, REG_VBUS_ADDRESS_ACCESS3, 0xB0},
+	{TOK_WRITE, REG_VBUS_DATA_ACCESS_NO_VBUS_ADDR_INCR, 0x01},
+	{TOK_WRITE, REG_VBUS_DATA_ACCESS_NO_VBUS_ADDR_INCR, 0x00},
+	{TOK_WRITE, REG_OPERATION_MODE, 0x01},
+	{TOK_WRITE, REG_OPERATION_MODE, 0x00},
+	{TOK_TERM, 0, 0},
+};
+
+/* TVP5147 Init/Power on Sequence */
+static const struct tvp514x_reg tvp5147_init_reg_seq[] =	{
+	{TOK_WRITE, REG_VBUS_ADDRESS_ACCESS1, 0x02},
+	{TOK_WRITE, REG_VBUS_ADDRESS_ACCESS2, 0x00},
+	{TOK_WRITE, REG_VBUS_ADDRESS_ACCESS3, 0x80},
+	{TOK_WRITE, REG_VBUS_DATA_ACCESS_NO_VBUS_ADDR_INCR, 0x01},
+	{TOK_WRITE, REG_VBUS_ADDRESS_ACCESS1, 0x60},
+	{TOK_WRITE, REG_VBUS_ADDRESS_ACCESS2, 0x00},
+	{TOK_WRITE, REG_VBUS_ADDRESS_ACCESS3, 0xB0},
+	{TOK_WRITE, REG_VBUS_DATA_ACCESS_NO_VBUS_ADDR_INCR, 0x01},
+	{TOK_WRITE, REG_VBUS_ADDRESS_ACCESS1, 0x16},
+	{TOK_WRITE, REG_VBUS_ADDRESS_ACCESS2, 0x00},
+	{TOK_WRITE, REG_VBUS_ADDRESS_ACCESS3, 0xA0},
+	{TOK_WRITE, REG_VBUS_DATA_ACCESS_NO_VBUS_ADDR_INCR, 0x16},
+	{TOK_WRITE, REG_VBUS_ADDRESS_ACCESS1, 0x60},
+	{TOK_WRITE, REG_VBUS_ADDRESS_ACCESS2, 0x00},
+	{TOK_WRITE, REG_VBUS_ADDRESS_ACCESS3, 0xB0},
+	{TOK_WRITE, REG_VBUS_DATA_ACCESS_NO_VBUS_ADDR_INCR, 0x00},
+	{TOK_WRITE, REG_OPERATION_MODE, 0x01},
+	{TOK_WRITE, REG_OPERATION_MODE, 0x00},
+	{TOK_TERM, 0, 0},
+};
+
+/* TVP5146M2/TVP5147M1 Init/Power on Sequence */
+static const struct tvp514x_reg tvp514xm_init_reg_seq[] = {
+	{TOK_WRITE, REG_OPERATION_MODE, 0x01},
+	{TOK_WRITE, REG_OPERATION_MODE, 0x00},
+	{TOK_TERM, 0, 0},
+};
+
+/**
+ * I2C Device Table -
+ *
+ * name - Name of the actual device/chip.
+ * driver_data - Driver data
+ */
+static const struct i2c_device_id tvp514x_id[] = {
+	{"tvp5146", (unsigned long)tvp5146_init_reg_seq},
+	{"tvp5146m2", (unsigned long)tvp514xm_init_reg_seq},
+	{"tvp5147", (unsigned long)tvp5147_init_reg_seq},
+	{"tvp5147m1", (unsigned long)tvp514xm_init_reg_seq},
+	{},
+};
+
+MODULE_DEVICE_TABLE(i2c, tvp514x_id);
+
+static struct i2c_driver tvp514x_driver = {
+	.driver = {
+		.owner = THIS_MODULE,
+		.name = TVP514X_MODULE_NAME,
+	},
+	.probe = tvp514x_probe,
+	.remove = tvp514x_remove,
+	.id_table = tvp514x_id,
+};
+
+module_i2c_driver(tvp514x_driver);
diff --git a/drivers/media/i2c/tvp514x_regs.h b/drivers/media/i2c/tvp514x_regs.h
new file mode 100644
index 0000000..d23aa2f
--- /dev/null
+++ b/drivers/media/i2c/tvp514x_regs.h
@@ -0,0 +1,287 @@
+/*
+ * drivers/media/i2c/tvp514x_regs.h
+ *
+ * Copyright (C) 2008 Texas Instruments Inc
+ * Author: Vaibhav Hiremath <hvaibhav@ti.com>
+ *
+ * Contributors:
+ *     Sivaraj R <sivaraj@ti.com>
+ *     Brijesh R Jadav <brijesh.j@ti.com>
+ *     Hardik Shah <hardik.shah@ti.com>
+ *     Manjunath Hadli <mrh@ti.com>
+ *     Karicheri Muralidharan <m-karicheri2@ti.com>
+ *
+ * This package is free software; you can 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 _TVP514X_REGS_H
+#define _TVP514X_REGS_H
+
+/*
+ * TVP5146/47 registers
+ */
+#define REG_INPUT_SEL			(0x00)
+#define REG_AFE_GAIN_CTRL		(0x01)
+#define REG_VIDEO_STD			(0x02)
+#define REG_OPERATION_MODE		(0x03)
+#define REG_AUTOSWITCH_MASK		(0x04)
+
+#define REG_COLOR_KILLER		(0x05)
+#define REG_LUMA_CONTROL1		(0x06)
+#define REG_LUMA_CONTROL2		(0x07)
+#define REG_LUMA_CONTROL3		(0x08)
+
+#define REG_BRIGHTNESS			(0x09)
+#define REG_CONTRAST			(0x0A)
+#define REG_SATURATION			(0x0B)
+#define REG_HUE				(0x0C)
+
+#define REG_CHROMA_CONTROL1		(0x0D)
+#define REG_CHROMA_CONTROL2		(0x0E)
+
+/* 0x0F Reserved */
+
+#define REG_COMP_PR_SATURATION		(0x10)
+#define REG_COMP_Y_CONTRAST		(0x11)
+#define REG_COMP_PB_SATURATION		(0x12)
+
+/* 0x13 Reserved */
+
+#define REG_COMP_Y_BRIGHTNESS		(0x14)
+
+/* 0x15 Reserved */
+
+#define REG_AVID_START_PIXEL_LSB	(0x16)
+#define REG_AVID_START_PIXEL_MSB	(0x17)
+#define REG_AVID_STOP_PIXEL_LSB		(0x18)
+#define REG_AVID_STOP_PIXEL_MSB		(0x19)
+
+#define REG_HSYNC_START_PIXEL_LSB	(0x1A)
+#define REG_HSYNC_START_PIXEL_MSB	(0x1B)
+#define REG_HSYNC_STOP_PIXEL_LSB	(0x1C)
+#define REG_HSYNC_STOP_PIXEL_MSB	(0x1D)
+
+#define REG_VSYNC_START_LINE_LSB	(0x1E)
+#define REG_VSYNC_START_LINE_MSB	(0x1F)
+#define REG_VSYNC_STOP_LINE_LSB		(0x20)
+#define REG_VSYNC_STOP_LINE_MSB		(0x21)
+
+#define REG_VBLK_START_LINE_LSB		(0x22)
+#define REG_VBLK_START_LINE_MSB		(0x23)
+#define REG_VBLK_STOP_LINE_LSB		(0x24)
+#define REG_VBLK_STOP_LINE_MSB		(0x25)
+
+/* 0x26 - 0x27 Reserved */
+
+#define REG_FAST_SWTICH_CONTROL		(0x28)
+
+/* 0x29 Reserved */
+
+#define REG_FAST_SWTICH_SCART_DELAY	(0x2A)
+
+/* 0x2B Reserved */
+
+#define REG_SCART_DELAY			(0x2C)
+#define REG_CTI_DELAY			(0x2D)
+#define REG_CTI_CONTROL			(0x2E)
+
+/* 0x2F - 0x31 Reserved */
+
+#define REG_SYNC_CONTROL		(0x32)
+#define REG_OUTPUT_FORMATTER1		(0x33)
+#define REG_OUTPUT_FORMATTER2		(0x34)
+#define REG_OUTPUT_FORMATTER3		(0x35)
+#define REG_OUTPUT_FORMATTER4		(0x36)
+#define REG_OUTPUT_FORMATTER5		(0x37)
+#define REG_OUTPUT_FORMATTER6		(0x38)
+#define REG_CLEAR_LOST_LOCK		(0x39)
+
+#define REG_STATUS1			(0x3A)
+#define REG_STATUS2			(0x3B)
+
+#define REG_AGC_GAIN_STATUS_LSB		(0x3C)
+#define REG_AGC_GAIN_STATUS_MSB		(0x3D)
+
+/* 0x3E Reserved */
+
+#define REG_VIDEO_STD_STATUS		(0x3F)
+#define REG_GPIO_INPUT1			(0x40)
+#define REG_GPIO_INPUT2			(0x41)
+
+/* 0x42 - 0x45 Reserved */
+
+#define REG_AFE_COARSE_GAIN_CH1		(0x46)
+#define REG_AFE_COARSE_GAIN_CH2		(0x47)
+#define REG_AFE_COARSE_GAIN_CH3		(0x48)
+#define REG_AFE_COARSE_GAIN_CH4		(0x49)
+
+#define REG_AFE_FINE_GAIN_PB_B_LSB	(0x4A)
+#define REG_AFE_FINE_GAIN_PB_B_MSB	(0x4B)
+#define REG_AFE_FINE_GAIN_Y_G_CHROMA_LSB	(0x4C)
+#define REG_AFE_FINE_GAIN_Y_G_CHROMA_MSB	(0x4D)
+#define REG_AFE_FINE_GAIN_PR_R_LSB	(0x4E)
+#define REG_AFE_FINE_GAIN_PR_R_MSB	(0x4F)
+#define REG_AFE_FINE_GAIN_CVBS_LUMA_LSB	(0x50)
+#define REG_AFE_FINE_GAIN_CVBS_LUMA_MSB	(0x51)
+
+/* 0x52 - 0x68 Reserved */
+
+#define REG_FBIT_VBIT_CONTROL1		(0x69)
+
+/* 0x6A - 0x6B Reserved */
+
+#define REG_BACKEND_AGC_CONTROL		(0x6C)
+
+/* 0x6D - 0x6E Reserved */
+
+#define REG_AGC_DECREMENT_SPEED_CONTROL	(0x6F)
+#define REG_ROM_VERSION			(0x70)
+
+/* 0x71 - 0x73 Reserved */
+
+#define REG_AGC_WHITE_PEAK_PROCESSING	(0x74)
+#define REG_FBIT_VBIT_CONTROL2		(0x75)
+#define REG_VCR_TRICK_MODE_CONTROL	(0x76)
+#define REG_HORIZONTAL_SHAKE_INCREMENT	(0x77)
+#define REG_AGC_INCREMENT_SPEED		(0x78)
+#define REG_AGC_INCREMENT_DELAY		(0x79)
+
+/* 0x7A - 0x7F Reserved */
+
+#define REG_CHIP_ID_MSB			(0x80)
+#define REG_CHIP_ID_LSB			(0x81)
+
+/* 0x82 Reserved */
+
+#define REG_CPLL_SPEED_CONTROL		(0x83)
+
+/* 0x84 - 0x96 Reserved */
+
+#define REG_STATUS_REQUEST		(0x97)
+
+/* 0x98 - 0x99 Reserved */
+
+#define REG_VERTICAL_LINE_COUNT_LSB	(0x9A)
+#define REG_VERTICAL_LINE_COUNT_MSB	(0x9B)
+
+/* 0x9C - 0x9D Reserved */
+
+#define REG_AGC_DECREMENT_DELAY		(0x9E)
+
+/* 0x9F - 0xB0 Reserved */
+
+#define REG_VDP_TTX_FILTER_1_MASK1	(0xB1)
+#define REG_VDP_TTX_FILTER_1_MASK2	(0xB2)
+#define REG_VDP_TTX_FILTER_1_MASK3	(0xB3)
+#define REG_VDP_TTX_FILTER_1_MASK4	(0xB4)
+#define REG_VDP_TTX_FILTER_1_MASK5	(0xB5)
+#define REG_VDP_TTX_FILTER_2_MASK1	(0xB6)
+#define REG_VDP_TTX_FILTER_2_MASK2	(0xB7)
+#define REG_VDP_TTX_FILTER_2_MASK3	(0xB8)
+#define REG_VDP_TTX_FILTER_2_MASK4	(0xB9)
+#define REG_VDP_TTX_FILTER_2_MASK5	(0xBA)
+#define REG_VDP_TTX_FILTER_CONTROL	(0xBB)
+#define REG_VDP_FIFO_WORD_COUNT		(0xBC)
+#define REG_VDP_FIFO_INTERRUPT_THRLD	(0xBD)
+
+/* 0xBE Reserved */
+
+#define REG_VDP_FIFO_RESET		(0xBF)
+#define REG_VDP_FIFO_OUTPUT_CONTROL	(0xC0)
+#define REG_VDP_LINE_NUMBER_INTERRUPT	(0xC1)
+#define REG_VDP_PIXEL_ALIGNMENT_LSB	(0xC2)
+#define REG_VDP_PIXEL_ALIGNMENT_MSB	(0xC3)
+
+/* 0xC4 - 0xD5 Reserved */
+
+#define REG_VDP_LINE_START		(0xD6)
+#define REG_VDP_LINE_STOP		(0xD7)
+#define REG_VDP_GLOBAL_LINE_MODE	(0xD8)
+#define REG_VDP_FULL_FIELD_ENABLE	(0xD9)
+#define REG_VDP_FULL_FIELD_MODE		(0xDA)
+
+/* 0xDB - 0xDF Reserved */
+
+#define REG_VBUS_DATA_ACCESS_NO_VBUS_ADDR_INCR	(0xE0)
+#define REG_VBUS_DATA_ACCESS_VBUS_ADDR_INCR	(0xE1)
+#define REG_FIFO_READ_DATA			(0xE2)
+
+/* 0xE3 - 0xE7 Reserved */
+
+#define REG_VBUS_ADDRESS_ACCESS1	(0xE8)
+#define REG_VBUS_ADDRESS_ACCESS2	(0xE9)
+#define REG_VBUS_ADDRESS_ACCESS3	(0xEA)
+
+/* 0xEB - 0xEF Reserved */
+
+#define REG_INTERRUPT_RAW_STATUS0	(0xF0)
+#define REG_INTERRUPT_RAW_STATUS1	(0xF1)
+#define REG_INTERRUPT_STATUS0		(0xF2)
+#define REG_INTERRUPT_STATUS1		(0xF3)
+#define REG_INTERRUPT_MASK0		(0xF4)
+#define REG_INTERRUPT_MASK1		(0xF5)
+#define REG_INTERRUPT_CLEAR0		(0xF6)
+#define REG_INTERRUPT_CLEAR1		(0xF7)
+
+/* 0xF8 - 0xFF Reserved */
+
+/*
+ * Mask and bit definitions of TVP5146/47 registers
+ */
+/* The ID values we are looking for */
+#define TVP514X_CHIP_ID_MSB		(0x51)
+#define TVP5146_CHIP_ID_LSB		(0x46)
+#define TVP5147_CHIP_ID_LSB		(0x47)
+
+#define VIDEO_STD_MASK			(0x07)
+#define VIDEO_STD_AUTO_SWITCH_BIT	(0x00)
+#define VIDEO_STD_NTSC_MJ_BIT		(0x01)
+#define VIDEO_STD_PAL_BDGHIN_BIT	(0x02)
+#define VIDEO_STD_PAL_M_BIT		(0x03)
+#define VIDEO_STD_PAL_COMBINATION_N_BIT	(0x04)
+#define VIDEO_STD_NTSC_4_43_BIT		(0x05)
+#define VIDEO_STD_SECAM_BIT		(0x06)
+#define VIDEO_STD_PAL_60_BIT		(0x07)
+
+/*
+ * Status bit
+ */
+#define STATUS_TV_VCR_BIT		(1<<0)
+#define STATUS_HORZ_SYNC_LOCK_BIT	(1<<1)
+#define STATUS_VIRT_SYNC_LOCK_BIT	(1<<2)
+#define STATUS_CLR_SUBCAR_LOCK_BIT	(1<<3)
+#define STATUS_LOST_LOCK_DETECT_BIT	(1<<4)
+#define STATUS_FEILD_RATE_BIT		(1<<5)
+#define STATUS_LINE_ALTERNATING_BIT	(1<<6)
+#define STATUS_PEAK_WHITE_DETECT_BIT	(1<<7)
+
+/* Tokens for register write */
+#define TOK_WRITE                       (0)     /* token for write operation */
+#define TOK_TERM                        (1)     /* terminating token */
+#define TOK_DELAY                       (2)     /* delay token for reg list */
+#define TOK_SKIP                        (3)     /* token to skip a register */
+/**
+ * struct tvp514x_reg - Structure for TVP5146/47 register initialization values
+ * @token - Token: TOK_WRITE, TOK_TERM etc..
+ * @reg - Register offset
+ * @val - Register Value for TOK_WRITE or delay in ms for TOK_DELAY
+ */
+struct tvp514x_reg {
+	u8 token;
+	u8 reg;
+	u32 val;
+};
+
+#endif				/* ifndef _TVP514X_REGS_H */
diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
new file mode 100644
index 0000000..a751b6c
--- /dev/null
+++ b/drivers/media/i2c/tvp5150.c
@@ -0,0 +1,1274 @@
+/*
+ * tvp5150 - Texas Instruments TVP5150A/AM1 video decoder driver
+ *
+ * Copyright (c) 2005,2006 Mauro Carvalho Chehab (mchehab@infradead.org)
+ * This code is placed under the terms of the GNU General Public License v2
+ */
+
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/videodev2.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <media/v4l2-device.h>
+#include <media/tvp5150.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-ctrls.h>
+
+#include "tvp5150_reg.h"
+
+#define TVP5150_H_MAX		720
+#define TVP5150_V_MAX_525_60	480
+#define TVP5150_V_MAX_OTHERS	576
+#define TVP5150_MAX_CROP_LEFT	511
+#define TVP5150_MAX_CROP_TOP	127
+#define TVP5150_CROP_SHIFT	2
+
+MODULE_DESCRIPTION("Texas Instruments TVP5150A video decoder driver");
+MODULE_AUTHOR("Mauro Carvalho Chehab");
+MODULE_LICENSE("GPL");
+
+
+static int debug;
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "Debug level (0-2)");
+
+struct tvp5150 {
+	struct v4l2_subdev sd;
+	struct v4l2_ctrl_handler hdl;
+	struct v4l2_rect rect;
+
+	v4l2_std_id norm;	/* Current set standard */
+	u32 input;
+	u32 output;
+	int enable;
+};
+
+static inline struct tvp5150 *to_tvp5150(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct tvp5150, sd);
+}
+
+static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
+{
+	return &container_of(ctrl->handler, struct tvp5150, hdl)->sd;
+}
+
+static int tvp5150_read(struct v4l2_subdev *sd, unsigned char addr)
+{
+	struct i2c_client *c = v4l2_get_subdevdata(sd);
+	unsigned char buffer[1];
+	int rc;
+
+	buffer[0] = addr;
+
+	rc = i2c_master_send(c, buffer, 1);
+	if (rc < 0) {
+		v4l2_err(sd, "i2c i/o error: rc == %d (should be 1)\n", rc);
+		return rc;
+	}
+
+	msleep(10);
+
+	rc = i2c_master_recv(c, buffer, 1);
+	if (rc < 0) {
+		v4l2_err(sd, "i2c i/o error: rc == %d (should be 1)\n", rc);
+		return rc;
+	}
+
+	v4l2_dbg(2, debug, sd, "tvp5150: read 0x%02x = 0x%02x\n", addr, buffer[0]);
+
+	return (buffer[0]);
+}
+
+static inline void tvp5150_write(struct v4l2_subdev *sd, unsigned char addr,
+				 unsigned char value)
+{
+	struct i2c_client *c = v4l2_get_subdevdata(sd);
+	unsigned char buffer[2];
+	int rc;
+
+	buffer[0] = addr;
+	buffer[1] = value;
+	v4l2_dbg(2, debug, sd, "tvp5150: writing 0x%02x 0x%02x\n", buffer[0], buffer[1]);
+	if (2 != (rc = i2c_master_send(c, buffer, 2)))
+		v4l2_dbg(0, debug, sd, "i2c i/o error: rc == %d (should be 2)\n", rc);
+}
+
+static void dump_reg_range(struct v4l2_subdev *sd, char *s, u8 init,
+				const u8 end, int max_line)
+{
+	int i = 0;
+
+	while (init != (u8)(end + 1)) {
+		if ((i % max_line) == 0) {
+			if (i > 0)
+				printk("\n");
+			printk("tvp5150: %s reg 0x%02x = ", s, init);
+		}
+		printk("%02x ", tvp5150_read(sd, init));
+
+		init++;
+		i++;
+	}
+	printk("\n");
+}
+
+static int tvp5150_log_status(struct v4l2_subdev *sd)
+{
+	printk("tvp5150: Video input source selection #1 = 0x%02x\n",
+			tvp5150_read(sd, TVP5150_VD_IN_SRC_SEL_1));
+	printk("tvp5150: Analog channel controls = 0x%02x\n",
+			tvp5150_read(sd, TVP5150_ANAL_CHL_CTL));
+	printk("tvp5150: Operation mode controls = 0x%02x\n",
+			tvp5150_read(sd, TVP5150_OP_MODE_CTL));
+	printk("tvp5150: Miscellaneous controls = 0x%02x\n",
+			tvp5150_read(sd, TVP5150_MISC_CTL));
+	printk("tvp5150: Autoswitch mask= 0x%02x\n",
+			tvp5150_read(sd, TVP5150_AUTOSW_MSK));
+	printk("tvp5150: Color killer threshold control = 0x%02x\n",
+			tvp5150_read(sd, TVP5150_COLOR_KIL_THSH_CTL));
+	printk("tvp5150: Luminance processing controls #1 #2 and #3 = %02x %02x %02x\n",
+			tvp5150_read(sd, TVP5150_LUMA_PROC_CTL_1),
+			tvp5150_read(sd, TVP5150_LUMA_PROC_CTL_2),
+			tvp5150_read(sd, TVP5150_LUMA_PROC_CTL_3));
+	printk("tvp5150: Brightness control = 0x%02x\n",
+			tvp5150_read(sd, TVP5150_BRIGHT_CTL));
+	printk("tvp5150: Color saturation control = 0x%02x\n",
+			tvp5150_read(sd, TVP5150_SATURATION_CTL));
+	printk("tvp5150: Hue control = 0x%02x\n",
+			tvp5150_read(sd, TVP5150_HUE_CTL));
+	printk("tvp5150: Contrast control = 0x%02x\n",
+			tvp5150_read(sd, TVP5150_CONTRAST_CTL));
+	printk("tvp5150: Outputs and data rates select = 0x%02x\n",
+			tvp5150_read(sd, TVP5150_DATA_RATE_SEL));
+	printk("tvp5150: Configuration shared pins = 0x%02x\n",
+			tvp5150_read(sd, TVP5150_CONF_SHARED_PIN));
+	printk("tvp5150: Active video cropping start = 0x%02x%02x\n",
+			tvp5150_read(sd, TVP5150_ACT_VD_CROP_ST_MSB),
+			tvp5150_read(sd, TVP5150_ACT_VD_CROP_ST_LSB));
+	printk("tvp5150: Active video cropping stop  = 0x%02x%02x\n",
+			tvp5150_read(sd, TVP5150_ACT_VD_CROP_STP_MSB),
+			tvp5150_read(sd, TVP5150_ACT_VD_CROP_STP_LSB));
+	printk("tvp5150: Genlock/RTC = 0x%02x\n",
+			tvp5150_read(sd, TVP5150_GENLOCK));
+	printk("tvp5150: Horizontal sync start = 0x%02x\n",
+			tvp5150_read(sd, TVP5150_HORIZ_SYNC_START));
+	printk("tvp5150: Vertical blanking start = 0x%02x\n",
+			tvp5150_read(sd, TVP5150_VERT_BLANKING_START));
+	printk("tvp5150: Vertical blanking stop = 0x%02x\n",
+			tvp5150_read(sd, TVP5150_VERT_BLANKING_STOP));
+	printk("tvp5150: Chrominance processing control #1 and #2 = %02x %02x\n",
+			tvp5150_read(sd, TVP5150_CHROMA_PROC_CTL_1),
+			tvp5150_read(sd, TVP5150_CHROMA_PROC_CTL_2));
+	printk("tvp5150: Interrupt reset register B = 0x%02x\n",
+			tvp5150_read(sd, TVP5150_INT_RESET_REG_B));
+	printk("tvp5150: Interrupt enable register B = 0x%02x\n",
+			tvp5150_read(sd, TVP5150_INT_ENABLE_REG_B));
+	printk("tvp5150: Interrupt configuration register B = 0x%02x\n",
+			tvp5150_read(sd, TVP5150_INTT_CONFIG_REG_B));
+	printk("tvp5150: Video standard = 0x%02x\n",
+			tvp5150_read(sd, TVP5150_VIDEO_STD));
+	printk("tvp5150: Chroma gain factor: Cb=0x%02x Cr=0x%02x\n",
+			tvp5150_read(sd, TVP5150_CB_GAIN_FACT),
+			tvp5150_read(sd, TVP5150_CR_GAIN_FACTOR));
+	printk("tvp5150: Macrovision on counter = 0x%02x\n",
+			tvp5150_read(sd, TVP5150_MACROVISION_ON_CTR));
+	printk("tvp5150: Macrovision off counter = 0x%02x\n",
+			tvp5150_read(sd, TVP5150_MACROVISION_OFF_CTR));
+	printk("tvp5150: ITU-R BT.656.%d timing(TVP5150AM1 only)\n",
+			(tvp5150_read(sd, TVP5150_REV_SELECT) & 1) ? 3 : 4);
+	printk("tvp5150: Device ID = %02x%02x\n",
+			tvp5150_read(sd, TVP5150_MSB_DEV_ID),
+			tvp5150_read(sd, TVP5150_LSB_DEV_ID));
+	printk("tvp5150: ROM version = (hex) %02x.%02x\n",
+			tvp5150_read(sd, TVP5150_ROM_MAJOR_VER),
+			tvp5150_read(sd, TVP5150_ROM_MINOR_VER));
+	printk("tvp5150: Vertical line count = 0x%02x%02x\n",
+			tvp5150_read(sd, TVP5150_VERT_LN_COUNT_MSB),
+			tvp5150_read(sd, TVP5150_VERT_LN_COUNT_LSB));
+	printk("tvp5150: Interrupt status register B = 0x%02x\n",
+			tvp5150_read(sd, TVP5150_INT_STATUS_REG_B));
+	printk("tvp5150: Interrupt active register B = 0x%02x\n",
+			tvp5150_read(sd, TVP5150_INT_ACTIVE_REG_B));
+	printk("tvp5150: Status regs #1 to #5 = %02x %02x %02x %02x %02x\n",
+			tvp5150_read(sd, TVP5150_STATUS_REG_1),
+			tvp5150_read(sd, TVP5150_STATUS_REG_2),
+			tvp5150_read(sd, TVP5150_STATUS_REG_3),
+			tvp5150_read(sd, TVP5150_STATUS_REG_4),
+			tvp5150_read(sd, TVP5150_STATUS_REG_5));
+
+	dump_reg_range(sd, "Teletext filter 1",   TVP5150_TELETEXT_FIL1_INI,
+			TVP5150_TELETEXT_FIL1_END, 8);
+	dump_reg_range(sd, "Teletext filter 2",   TVP5150_TELETEXT_FIL2_INI,
+			TVP5150_TELETEXT_FIL2_END, 8);
+
+	printk("tvp5150: Teletext filter enable = 0x%02x\n",
+			tvp5150_read(sd, TVP5150_TELETEXT_FIL_ENA));
+	printk("tvp5150: Interrupt status register A = 0x%02x\n",
+			tvp5150_read(sd, TVP5150_INT_STATUS_REG_A));
+	printk("tvp5150: Interrupt enable register A = 0x%02x\n",
+			tvp5150_read(sd, TVP5150_INT_ENABLE_REG_A));
+	printk("tvp5150: Interrupt configuration = 0x%02x\n",
+			tvp5150_read(sd, TVP5150_INT_CONF));
+	printk("tvp5150: VDP status register = 0x%02x\n",
+			tvp5150_read(sd, TVP5150_VDP_STATUS_REG));
+	printk("tvp5150: FIFO word count = 0x%02x\n",
+			tvp5150_read(sd, TVP5150_FIFO_WORD_COUNT));
+	printk("tvp5150: FIFO interrupt threshold = 0x%02x\n",
+			tvp5150_read(sd, TVP5150_FIFO_INT_THRESHOLD));
+	printk("tvp5150: FIFO reset = 0x%02x\n",
+			tvp5150_read(sd, TVP5150_FIFO_RESET));
+	printk("tvp5150: Line number interrupt = 0x%02x\n",
+			tvp5150_read(sd, TVP5150_LINE_NUMBER_INT));
+	printk("tvp5150: Pixel alignment register = 0x%02x%02x\n",
+			tvp5150_read(sd, TVP5150_PIX_ALIGN_REG_HIGH),
+			tvp5150_read(sd, TVP5150_PIX_ALIGN_REG_LOW));
+	printk("tvp5150: FIFO output control = 0x%02x\n",
+			tvp5150_read(sd, TVP5150_FIFO_OUT_CTRL));
+	printk("tvp5150: Full field enable = 0x%02x\n",
+			tvp5150_read(sd, TVP5150_FULL_FIELD_ENA));
+	printk("tvp5150: Full field mode register = 0x%02x\n",
+			tvp5150_read(sd, TVP5150_FULL_FIELD_MODE_REG));
+
+	dump_reg_range(sd, "CC   data",   TVP5150_CC_DATA_INI,
+			TVP5150_CC_DATA_END, 8);
+
+	dump_reg_range(sd, "WSS  data",   TVP5150_WSS_DATA_INI,
+			TVP5150_WSS_DATA_END, 8);
+
+	dump_reg_range(sd, "VPS  data",   TVP5150_VPS_DATA_INI,
+			TVP5150_VPS_DATA_END, 8);
+
+	dump_reg_range(sd, "VITC data",   TVP5150_VITC_DATA_INI,
+			TVP5150_VITC_DATA_END, 10);
+
+	dump_reg_range(sd, "Line mode",   TVP5150_LINE_MODE_INI,
+			TVP5150_LINE_MODE_END, 8);
+	return 0;
+}
+
+/****************************************************************************
+			Basic functions
+ ****************************************************************************/
+
+static inline void tvp5150_selmux(struct v4l2_subdev *sd)
+{
+	int opmode = 0;
+	struct tvp5150 *decoder = to_tvp5150(sd);
+	int input = 0;
+	int val;
+
+	if ((decoder->output & TVP5150_BLACK_SCREEN) || !decoder->enable)
+		input = 8;
+
+	switch (decoder->input) {
+	case TVP5150_COMPOSITE1:
+		input |= 2;
+		/* fall through */
+	case TVP5150_COMPOSITE0:
+		break;
+	case TVP5150_SVIDEO:
+	default:
+		input |= 1;
+		break;
+	}
+
+	v4l2_dbg(1, debug, sd, "Selecting video route: route input=%i, output=%i "
+			"=> tvp5150 input=%i, opmode=%i\n",
+			decoder->input, decoder->output,
+			input, opmode);
+
+	tvp5150_write(sd, TVP5150_OP_MODE_CTL, opmode);
+	tvp5150_write(sd, TVP5150_VD_IN_SRC_SEL_1, input);
+
+	/* Svideo should enable YCrCb output and disable GPCL output
+	 * For Composite and TV, it should be the reverse
+	 */
+	val = tvp5150_read(sd, TVP5150_MISC_CTL);
+	if (val < 0) {
+		v4l2_err(sd, "%s: failed with error = %d\n", __func__, val);
+		return;
+	}
+
+	if (decoder->input == TVP5150_SVIDEO)
+		val = (val & ~0x40) | 0x10;
+	else
+		val = (val & ~0x10) | 0x40;
+	tvp5150_write(sd, TVP5150_MISC_CTL, val);
+};
+
+struct i2c_reg_value {
+	unsigned char reg;
+	unsigned char value;
+};
+
+/* Default values as sugested at TVP5150AM1 datasheet */
+static const struct i2c_reg_value tvp5150_init_default[] = {
+	{ /* 0x00 */
+		TVP5150_VD_IN_SRC_SEL_1,0x00
+	},
+	{ /* 0x01 */
+		TVP5150_ANAL_CHL_CTL,0x15
+	},
+	{ /* 0x02 */
+		TVP5150_OP_MODE_CTL,0x00
+	},
+	{ /* 0x03 */
+		TVP5150_MISC_CTL,0x01
+	},
+	{ /* 0x06 */
+		TVP5150_COLOR_KIL_THSH_CTL,0x10
+	},
+	{ /* 0x07 */
+		TVP5150_LUMA_PROC_CTL_1,0x60
+	},
+	{ /* 0x08 */
+		TVP5150_LUMA_PROC_CTL_2,0x00
+	},
+	{ /* 0x09 */
+		TVP5150_BRIGHT_CTL,0x80
+	},
+	{ /* 0x0a */
+		TVP5150_SATURATION_CTL,0x80
+	},
+	{ /* 0x0b */
+		TVP5150_HUE_CTL,0x00
+	},
+	{ /* 0x0c */
+		TVP5150_CONTRAST_CTL,0x80
+	},
+	{ /* 0x0d */
+		TVP5150_DATA_RATE_SEL,0x47
+	},
+	{ /* 0x0e */
+		TVP5150_LUMA_PROC_CTL_3,0x00
+	},
+	{ /* 0x0f */
+		TVP5150_CONF_SHARED_PIN,0x08
+	},
+	{ /* 0x11 */
+		TVP5150_ACT_VD_CROP_ST_MSB,0x00
+	},
+	{ /* 0x12 */
+		TVP5150_ACT_VD_CROP_ST_LSB,0x00
+	},
+	{ /* 0x13 */
+		TVP5150_ACT_VD_CROP_STP_MSB,0x00
+	},
+	{ /* 0x14 */
+		TVP5150_ACT_VD_CROP_STP_LSB,0x00
+	},
+	{ /* 0x15 */
+		TVP5150_GENLOCK,0x01
+	},
+	{ /* 0x16 */
+		TVP5150_HORIZ_SYNC_START,0x80
+	},
+	{ /* 0x18 */
+		TVP5150_VERT_BLANKING_START,0x00
+	},
+	{ /* 0x19 */
+		TVP5150_VERT_BLANKING_STOP,0x00
+	},
+	{ /* 0x1a */
+		TVP5150_CHROMA_PROC_CTL_1,0x0c
+	},
+	{ /* 0x1b */
+		TVP5150_CHROMA_PROC_CTL_2,0x14
+	},
+	{ /* 0x1c */
+		TVP5150_INT_RESET_REG_B,0x00
+	},
+	{ /* 0x1d */
+		TVP5150_INT_ENABLE_REG_B,0x00
+	},
+	{ /* 0x1e */
+		TVP5150_INTT_CONFIG_REG_B,0x00
+	},
+	{ /* 0x28 */
+		TVP5150_VIDEO_STD,0x00
+	},
+	{ /* 0x2e */
+		TVP5150_MACROVISION_ON_CTR,0x0f
+	},
+	{ /* 0x2f */
+		TVP5150_MACROVISION_OFF_CTR,0x01
+	},
+	{ /* 0xbb */
+		TVP5150_TELETEXT_FIL_ENA,0x00
+	},
+	{ /* 0xc0 */
+		TVP5150_INT_STATUS_REG_A,0x00
+	},
+	{ /* 0xc1 */
+		TVP5150_INT_ENABLE_REG_A,0x00
+	},
+	{ /* 0xc2 */
+		TVP5150_INT_CONF,0x04
+	},
+	{ /* 0xc8 */
+		TVP5150_FIFO_INT_THRESHOLD,0x80
+	},
+	{ /* 0xc9 */
+		TVP5150_FIFO_RESET,0x00
+	},
+	{ /* 0xca */
+		TVP5150_LINE_NUMBER_INT,0x00
+	},
+	{ /* 0xcb */
+		TVP5150_PIX_ALIGN_REG_LOW,0x4e
+	},
+	{ /* 0xcc */
+		TVP5150_PIX_ALIGN_REG_HIGH,0x00
+	},
+	{ /* 0xcd */
+		TVP5150_FIFO_OUT_CTRL,0x01
+	},
+	{ /* 0xcf */
+		TVP5150_FULL_FIELD_ENA,0x00
+	},
+	{ /* 0xd0 */
+		TVP5150_LINE_MODE_INI,0x00
+	},
+	{ /* 0xfc */
+		TVP5150_FULL_FIELD_MODE_REG,0x7f
+	},
+	{ /* end of data */
+		0xff,0xff
+	}
+};
+
+/* Default values as sugested at TVP5150AM1 datasheet */
+static const struct i2c_reg_value tvp5150_init_enable[] = {
+	{
+		TVP5150_CONF_SHARED_PIN, 2
+	},{	/* Automatic offset and AGC enabled */
+		TVP5150_ANAL_CHL_CTL, 0x15
+	},{	/* Activate YCrCb output 0x9 or 0xd ? */
+		TVP5150_MISC_CTL, 0x6f
+	},{	/* Activates video std autodetection for all standards */
+		TVP5150_AUTOSW_MSK, 0x0
+	},{	/* Default format: 0x47. For 4:2:2: 0x40 */
+		TVP5150_DATA_RATE_SEL, 0x47
+	},{
+		TVP5150_CHROMA_PROC_CTL_1, 0x0c
+	},{
+		TVP5150_CHROMA_PROC_CTL_2, 0x54
+	},{	/* Non documented, but initialized on WinTV USB2 */
+		0x27, 0x20
+	},{
+		0xff,0xff
+	}
+};
+
+struct tvp5150_vbi_type {
+	unsigned int vbi_type;
+	unsigned int ini_line;
+	unsigned int end_line;
+	unsigned int by_field :1;
+};
+
+struct i2c_vbi_ram_value {
+	u16 reg;
+	struct tvp5150_vbi_type type;
+	unsigned char values[16];
+};
+
+/* This struct have the values for each supported VBI Standard
+ * by
+ tvp5150_vbi_types should follow the same order as vbi_ram_default
+ * value 0 means rom position 0x10, value 1 means rom position 0x30
+ * and so on. There are 16 possible locations from 0 to 15.
+ */
+
+static struct i2c_vbi_ram_value vbi_ram_default[] =
+{
+	/* FIXME: Current api doesn't handle all VBI types, those not
+	   yet supported are placed under #if 0 */
+#if 0
+	{0x010, /* Teletext, SECAM, WST System A */
+		{V4L2_SLICED_TELETEXT_SECAM,6,23,1},
+		{ 0xaa, 0xaa, 0xff, 0xff, 0xe7, 0x2e, 0x20, 0x26,
+		  0xe6, 0xb4, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00 }
+	},
+#endif
+	{0x030, /* Teletext, PAL, WST System B */
+		{V4L2_SLICED_TELETEXT_B,6,22,1},
+		{ 0xaa, 0xaa, 0xff, 0xff, 0x27, 0x2e, 0x20, 0x2b,
+		  0xa6, 0x72, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00 }
+	},
+#if 0
+	{0x050, /* Teletext, PAL, WST System C */
+		{V4L2_SLICED_TELETEXT_PAL_C,6,22,1},
+		{ 0xaa, 0xaa, 0xff, 0xff, 0xe7, 0x2e, 0x20, 0x22,
+		  0xa6, 0x98, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x00 }
+	},
+	{0x070, /* Teletext, NTSC, WST System B */
+		{V4L2_SLICED_TELETEXT_NTSC_B,10,21,1},
+		{ 0xaa, 0xaa, 0xff, 0xff, 0x27, 0x2e, 0x20, 0x23,
+		  0x69, 0x93, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x00 }
+	},
+	{0x090, /* Tetetext, NTSC NABTS System C */
+		{V4L2_SLICED_TELETEXT_NTSC_C,10,21,1},
+		{ 0xaa, 0xaa, 0xff, 0xff, 0xe7, 0x2e, 0x20, 0x22,
+		  0x69, 0x93, 0x0d, 0x00, 0x00, 0x00, 0x15, 0x00 }
+	},
+	{0x0b0, /* Teletext, NTSC-J, NABTS System D */
+		{V4L2_SLICED_TELETEXT_NTSC_D,10,21,1},
+		{ 0xaa, 0xaa, 0xff, 0xff, 0xa7, 0x2e, 0x20, 0x23,
+		  0x69, 0x93, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x00 }
+	},
+	{0x0d0, /* Closed Caption, PAL/SECAM */
+		{V4L2_SLICED_CAPTION_625,22,22,1},
+		{ 0xaa, 0x2a, 0xff, 0x3f, 0x04, 0x51, 0x6e, 0x02,
+		  0xa6, 0x7b, 0x09, 0x00, 0x00, 0x00, 0x27, 0x00 }
+	},
+#endif
+	{0x0f0, /* Closed Caption, NTSC */
+		{V4L2_SLICED_CAPTION_525,21,21,1},
+		{ 0xaa, 0x2a, 0xff, 0x3f, 0x04, 0x51, 0x6e, 0x02,
+		  0x69, 0x8c, 0x09, 0x00, 0x00, 0x00, 0x27, 0x00 }
+	},
+	{0x110, /* Wide Screen Signal, PAL/SECAM */
+		{V4L2_SLICED_WSS_625,23,23,1},
+		{ 0x5b, 0x55, 0xc5, 0xff, 0x00, 0x71, 0x6e, 0x42,
+		  0xa6, 0xcd, 0x0f, 0x00, 0x00, 0x00, 0x3a, 0x00 }
+	},
+#if 0
+	{0x130, /* Wide Screen Signal, NTSC C */
+		{V4L2_SLICED_WSS_525,20,20,1},
+		{ 0x38, 0x00, 0x3f, 0x00, 0x00, 0x71, 0x6e, 0x43,
+		  0x69, 0x7c, 0x08, 0x00, 0x00, 0x00, 0x39, 0x00 }
+	},
+	{0x150, /* Vertical Interval Timecode (VITC), PAL/SECAM */
+		{V4l2_SLICED_VITC_625,6,22,0},
+		{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x6d, 0x49,
+		  0xa6, 0x85, 0x08, 0x00, 0x00, 0x00, 0x4c, 0x00 }
+	},
+	{0x170, /* Vertical Interval Timecode (VITC), NTSC */
+		{V4l2_SLICED_VITC_525,10,20,0},
+		{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x6d, 0x49,
+		  0x69, 0x94, 0x08, 0x00, 0x00, 0x00, 0x4c, 0x00 }
+	},
+#endif
+	{0x190, /* Video Program System (VPS), PAL */
+		{V4L2_SLICED_VPS,16,16,0},
+		{ 0xaa, 0xaa, 0xff, 0xff, 0xba, 0xce, 0x2b, 0x0d,
+		  0xa6, 0xda, 0x0b, 0x00, 0x00, 0x00, 0x60, 0x00 }
+	},
+	/* 0x1d0 User programmable */
+
+	/* End of struct */
+	{ (u16)-1 }
+};
+
+static int tvp5150_write_inittab(struct v4l2_subdev *sd,
+				const struct i2c_reg_value *regs)
+{
+	while (regs->reg != 0xff) {
+		tvp5150_write(sd, regs->reg, regs->value);
+		regs++;
+	}
+	return 0;
+}
+
+static int tvp5150_vdp_init(struct v4l2_subdev *sd,
+				const struct i2c_vbi_ram_value *regs)
+{
+	unsigned int i;
+
+	/* Disable Full Field */
+	tvp5150_write(sd, TVP5150_FULL_FIELD_ENA, 0);
+
+	/* Before programming, Line mode should be at 0xff */
+	for (i = TVP5150_LINE_MODE_INI; i <= TVP5150_LINE_MODE_END; i++)
+		tvp5150_write(sd, i, 0xff);
+
+	/* Load Ram Table */
+	while (regs->reg != (u16)-1) {
+		tvp5150_write(sd, TVP5150_CONF_RAM_ADDR_HIGH, regs->reg >> 8);
+		tvp5150_write(sd, TVP5150_CONF_RAM_ADDR_LOW, regs->reg);
+
+		for (i = 0; i < 16; i++)
+			tvp5150_write(sd, TVP5150_VDP_CONF_RAM_DATA, regs->values[i]);
+
+		regs++;
+	}
+	return 0;
+}
+
+/* Fills VBI capabilities based on i2c_vbi_ram_value struct */
+static int tvp5150_g_sliced_vbi_cap(struct v4l2_subdev *sd,
+				struct v4l2_sliced_vbi_cap *cap)
+{
+	const struct i2c_vbi_ram_value *regs = vbi_ram_default;
+	int line;
+
+	v4l2_dbg(1, debug, sd, "g_sliced_vbi_cap\n");
+	memset(cap, 0, sizeof *cap);
+
+	while (regs->reg != (u16)-1 ) {
+		for (line=regs->type.ini_line;line<=regs->type.end_line;line++) {
+			cap->service_lines[0][line] |= regs->type.vbi_type;
+		}
+		cap->service_set |= regs->type.vbi_type;
+
+		regs++;
+	}
+	return 0;
+}
+
+/* Set vbi processing
+ * type - one of tvp5150_vbi_types
+ * line - line to gather data
+ * fields: bit 0 field1, bit 1, field2
+ * flags (default=0xf0) is a bitmask, were set means:
+ *	bit 7: enable filtering null bytes on CC
+ *	bit 6: send data also to FIFO
+ *	bit 5: don't allow data with errors on FIFO
+ *	bit 4: enable ECC when possible
+ * pix_align = pix alignment:
+ *	LSB = field1
+ *	MSB = field2
+ */
+static int tvp5150_set_vbi(struct v4l2_subdev *sd,
+			const struct i2c_vbi_ram_value *regs,
+			unsigned int type,u8 flags, int line,
+			const int fields)
+{
+	struct tvp5150 *decoder = to_tvp5150(sd);
+	v4l2_std_id std = decoder->norm;
+	u8 reg;
+	int pos=0;
+
+	if (std == V4L2_STD_ALL) {
+		v4l2_err(sd, "VBI can't be configured without knowing number of lines\n");
+		return 0;
+	} else if (std & V4L2_STD_625_50) {
+		/* Don't follow NTSC Line number convension */
+		line += 3;
+	}
+
+	if (line<6||line>27)
+		return 0;
+
+	while (regs->reg != (u16)-1 ) {
+		if ((type & regs->type.vbi_type) &&
+		    (line>=regs->type.ini_line) &&
+		    (line<=regs->type.end_line)) {
+			type=regs->type.vbi_type;
+			break;
+		}
+
+		regs++;
+		pos++;
+	}
+	if (regs->reg == (u16)-1)
+		return 0;
+
+	type=pos | (flags & 0xf0);
+	reg=((line-6)<<1)+TVP5150_LINE_MODE_INI;
+
+	if (fields&1) {
+		tvp5150_write(sd, reg, type);
+	}
+
+	if (fields&2) {
+		tvp5150_write(sd, reg+1, type);
+	}
+
+	return type;
+}
+
+static int tvp5150_get_vbi(struct v4l2_subdev *sd,
+			const struct i2c_vbi_ram_value *regs, int line)
+{
+	struct tvp5150 *decoder = to_tvp5150(sd);
+	v4l2_std_id std = decoder->norm;
+	u8 reg;
+	int pos, type = 0;
+	int i, ret = 0;
+
+	if (std == V4L2_STD_ALL) {
+		v4l2_err(sd, "VBI can't be configured without knowing number of lines\n");
+		return 0;
+	} else if (std & V4L2_STD_625_50) {
+		/* Don't follow NTSC Line number convension */
+		line += 3;
+	}
+
+	if (line < 6 || line > 27)
+		return 0;
+
+	reg = ((line - 6) << 1) + TVP5150_LINE_MODE_INI;
+
+	for (i = 0; i <= 1; i++) {
+		ret = tvp5150_read(sd, reg + i);
+		if (ret < 0) {
+			v4l2_err(sd, "%s: failed with error = %d\n",
+				 __func__, ret);
+			return 0;
+		}
+		pos = ret & 0x0f;
+		if (pos < 0x0f)
+			type |= regs[pos].type.vbi_type;
+	}
+
+	return type;
+}
+
+static int tvp5150_set_std(struct v4l2_subdev *sd, v4l2_std_id std)
+{
+	struct tvp5150 *decoder = to_tvp5150(sd);
+	int fmt = 0;
+
+	decoder->norm = std;
+
+	/* First tests should be against specific std */
+
+	if (std == V4L2_STD_ALL) {
+		fmt = VIDEO_STD_AUTO_SWITCH_BIT;	/* Autodetect mode */
+	} else if (std & V4L2_STD_NTSC_443) {
+		fmt = VIDEO_STD_NTSC_4_43_BIT;
+	} else if (std & V4L2_STD_PAL_M) {
+		fmt = VIDEO_STD_PAL_M_BIT;
+	} else if (std & (V4L2_STD_PAL_N | V4L2_STD_PAL_Nc)) {
+		fmt = VIDEO_STD_PAL_COMBINATION_N_BIT;
+	} else {
+		/* Then, test against generic ones */
+		if (std & V4L2_STD_NTSC)
+			fmt = VIDEO_STD_NTSC_MJ_BIT;
+		else if (std & V4L2_STD_PAL)
+			fmt = VIDEO_STD_PAL_BDGHIN_BIT;
+		else if (std & V4L2_STD_SECAM)
+			fmt = VIDEO_STD_SECAM_BIT;
+	}
+
+	v4l2_dbg(1, debug, sd, "Set video std register to %d.\n", fmt);
+	tvp5150_write(sd, TVP5150_VIDEO_STD, fmt);
+	return 0;
+}
+
+static int tvp5150_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
+{
+	struct tvp5150 *decoder = to_tvp5150(sd);
+
+	if (decoder->norm == std)
+		return 0;
+
+	/* Change cropping height limits */
+	if (std & V4L2_STD_525_60)
+		decoder->rect.height = TVP5150_V_MAX_525_60;
+	else
+		decoder->rect.height = TVP5150_V_MAX_OTHERS;
+
+
+	return tvp5150_set_std(sd, std);
+}
+
+static int tvp5150_reset(struct v4l2_subdev *sd, u32 val)
+{
+	struct tvp5150 *decoder = to_tvp5150(sd);
+
+	/* Initializes TVP5150 to its default values */
+	tvp5150_write_inittab(sd, tvp5150_init_default);
+
+	/* Initializes VDP registers */
+	tvp5150_vdp_init(sd, vbi_ram_default);
+
+	/* Selects decoder input */
+	tvp5150_selmux(sd);
+
+	/* Initializes TVP5150 to stream enabled values */
+	tvp5150_write_inittab(sd, tvp5150_init_enable);
+
+	/* Initialize image preferences */
+	v4l2_ctrl_handler_setup(&decoder->hdl);
+
+	tvp5150_set_std(sd, decoder->norm);
+	return 0;
+};
+
+static int tvp5150_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct v4l2_subdev *sd = to_sd(ctrl);
+
+	switch (ctrl->id) {
+	case V4L2_CID_BRIGHTNESS:
+		tvp5150_write(sd, TVP5150_BRIGHT_CTL, ctrl->val);
+		return 0;
+	case V4L2_CID_CONTRAST:
+		tvp5150_write(sd, TVP5150_CONTRAST_CTL, ctrl->val);
+		return 0;
+	case V4L2_CID_SATURATION:
+		tvp5150_write(sd, TVP5150_SATURATION_CTL, ctrl->val);
+		return 0;
+	case V4L2_CID_HUE:
+		tvp5150_write(sd, TVP5150_HUE_CTL, ctrl->val);
+		return 0;
+	}
+	return -EINVAL;
+}
+
+static v4l2_std_id tvp5150_read_std(struct v4l2_subdev *sd)
+{
+	int val = tvp5150_read(sd, TVP5150_STATUS_REG_5);
+
+	switch (val & 0x0F) {
+	case 0x01:
+		return V4L2_STD_NTSC;
+	case 0x03:
+		return V4L2_STD_PAL;
+	case 0x05:
+		return V4L2_STD_PAL_M;
+	case 0x07:
+		return V4L2_STD_PAL_N | V4L2_STD_PAL_Nc;
+	case 0x09:
+		return V4L2_STD_NTSC_443;
+	case 0xb:
+		return V4L2_STD_SECAM;
+	default:
+		return V4L2_STD_UNKNOWN;
+	}
+}
+
+static int tvp5150_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index,
+						enum v4l2_mbus_pixelcode *code)
+{
+	if (index)
+		return -EINVAL;
+
+	*code = V4L2_MBUS_FMT_UYVY8_2X8;
+	return 0;
+}
+
+static int tvp5150_mbus_fmt(struct v4l2_subdev *sd,
+			    struct v4l2_mbus_framefmt *f)
+{
+	struct tvp5150 *decoder = to_tvp5150(sd);
+
+	if (f == NULL)
+		return -EINVAL;
+
+	tvp5150_reset(sd, 0);
+
+	f->width = decoder->rect.width;
+	f->height = decoder->rect.height;
+
+	f->code = V4L2_MBUS_FMT_UYVY8_2X8;
+	f->field = V4L2_FIELD_SEQ_TB;
+	f->colorspace = V4L2_COLORSPACE_SMPTE170M;
+
+	v4l2_dbg(1, debug, sd, "width = %d, height = %d\n", f->width,
+			f->height);
+	return 0;
+}
+
+static int tvp5150_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
+{
+	struct v4l2_rect rect = a->c;
+	struct tvp5150 *decoder = to_tvp5150(sd);
+	v4l2_std_id std;
+	int hmax;
+
+	v4l2_dbg(1, debug, sd, "%s left=%d, top=%d, width=%d, height=%d\n",
+		__func__, rect.left, rect.top, rect.width, rect.height);
+
+	if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
+	/* tvp5150 has some special limits */
+	rect.left = clamp(rect.left, 0, TVP5150_MAX_CROP_LEFT);
+	rect.width = clamp(rect.width,
+			   TVP5150_H_MAX - TVP5150_MAX_CROP_LEFT - rect.left,
+			   TVP5150_H_MAX - rect.left);
+	rect.top = clamp(rect.top, 0, TVP5150_MAX_CROP_TOP);
+
+	/* Calculate height based on current standard */
+	if (decoder->norm == V4L2_STD_ALL)
+		std = tvp5150_read_std(sd);
+	else
+		std = decoder->norm;
+
+	if (std & V4L2_STD_525_60)
+		hmax = TVP5150_V_MAX_525_60;
+	else
+		hmax = TVP5150_V_MAX_OTHERS;
+
+	rect.height = clamp(rect.height,
+			    hmax - TVP5150_MAX_CROP_TOP - rect.top,
+			    hmax - rect.top);
+
+	tvp5150_write(sd, TVP5150_VERT_BLANKING_START, rect.top);
+	tvp5150_write(sd, TVP5150_VERT_BLANKING_STOP,
+		      rect.top + rect.height - hmax);
+	tvp5150_write(sd, TVP5150_ACT_VD_CROP_ST_MSB,
+		      rect.left >> TVP5150_CROP_SHIFT);
+	tvp5150_write(sd, TVP5150_ACT_VD_CROP_ST_LSB,
+		      rect.left | (1 << TVP5150_CROP_SHIFT));
+	tvp5150_write(sd, TVP5150_ACT_VD_CROP_STP_MSB,
+		      (rect.left + rect.width - TVP5150_MAX_CROP_LEFT) >>
+		      TVP5150_CROP_SHIFT);
+	tvp5150_write(sd, TVP5150_ACT_VD_CROP_STP_LSB,
+		      rect.left + rect.width - TVP5150_MAX_CROP_LEFT);
+
+	decoder->rect = rect;
+
+	return 0;
+}
+
+static int tvp5150_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
+{
+	struct tvp5150 *decoder = container_of(sd, struct tvp5150, sd);
+
+	a->c	= decoder->rect;
+	a->type	= V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+	return 0;
+}
+
+static int tvp5150_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
+{
+	struct tvp5150 *decoder = container_of(sd, struct tvp5150, sd);
+	v4l2_std_id std;
+
+	if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
+	a->bounds.left			= 0;
+	a->bounds.top			= 0;
+	a->bounds.width			= TVP5150_H_MAX;
+
+	/* Calculate height based on current standard */
+	if (decoder->norm == V4L2_STD_ALL)
+		std = tvp5150_read_std(sd);
+	else
+		std = decoder->norm;
+
+	if (std & V4L2_STD_525_60)
+		a->bounds.height = TVP5150_V_MAX_525_60;
+	else
+		a->bounds.height = TVP5150_V_MAX_OTHERS;
+
+	a->defrect			= a->bounds;
+	a->pixelaspect.numerator	= 1;
+	a->pixelaspect.denominator	= 1;
+
+	return 0;
+}
+
+/****************************************************************************
+			I2C Command
+ ****************************************************************************/
+
+static int tvp5150_s_routing(struct v4l2_subdev *sd,
+			     u32 input, u32 output, u32 config)
+{
+	struct tvp5150 *decoder = to_tvp5150(sd);
+
+	decoder->input = input;
+	decoder->output = output;
+	tvp5150_selmux(sd);
+	return 0;
+}
+
+static int tvp5150_s_raw_fmt(struct v4l2_subdev *sd, struct v4l2_vbi_format *fmt)
+{
+	/* this is for capturing 36 raw vbi lines
+	   if there's a way to cut off the beginning 2 vbi lines
+	   with the tvp5150 then the vbi line count could be lowered
+	   to 17 lines/field again, although I couldn't find a register
+	   which could do that cropping */
+	if (fmt->sample_format == V4L2_PIX_FMT_GREY)
+		tvp5150_write(sd, TVP5150_LUMA_PROC_CTL_1, 0x70);
+	if (fmt->count[0] == 18 && fmt->count[1] == 18) {
+		tvp5150_write(sd, TVP5150_VERT_BLANKING_START, 0x00);
+		tvp5150_write(sd, TVP5150_VERT_BLANKING_STOP, 0x01);
+	}
+	return 0;
+}
+
+static int tvp5150_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *svbi)
+{
+	int i;
+
+	if (svbi->service_set != 0) {
+		for (i = 0; i <= 23; i++) {
+			svbi->service_lines[1][i] = 0;
+			svbi->service_lines[0][i] =
+				tvp5150_set_vbi(sd, vbi_ram_default,
+				       svbi->service_lines[0][i], 0xf0, i, 3);
+		}
+		/* Enables FIFO */
+		tvp5150_write(sd, TVP5150_FIFO_OUT_CTRL, 1);
+	} else {
+		/* Disables FIFO*/
+		tvp5150_write(sd, TVP5150_FIFO_OUT_CTRL, 0);
+
+		/* Disable Full Field */
+		tvp5150_write(sd, TVP5150_FULL_FIELD_ENA, 0);
+
+		/* Disable Line modes */
+		for (i = TVP5150_LINE_MODE_INI; i <= TVP5150_LINE_MODE_END; i++)
+			tvp5150_write(sd, i, 0xff);
+	}
+	return 0;
+}
+
+static int tvp5150_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *svbi)
+{
+	int i, mask = 0;
+
+	memset(svbi, 0, sizeof(*svbi));
+
+	for (i = 0; i <= 23; i++) {
+		svbi->service_lines[0][i] =
+			tvp5150_get_vbi(sd, vbi_ram_default, i);
+		mask |= svbi->service_lines[0][i];
+	}
+	svbi->service_set = mask;
+	return 0;
+}
+
+static int tvp5150_g_chip_ident(struct v4l2_subdev *sd,
+				struct v4l2_dbg_chip_ident *chip)
+{
+	int rev;
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	rev = tvp5150_read(sd, TVP5150_ROM_MAJOR_VER) << 8 |
+	      tvp5150_read(sd, TVP5150_ROM_MINOR_VER);
+
+	return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_TVP5150,
+					  rev);
+}
+
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int tvp5150_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
+{
+	int res;
+
+	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;
+	res = tvp5150_read(sd, reg->reg & 0xff);
+	if (res < 0) {
+		v4l2_err(sd, "%s: failed with error = %d\n", __func__, res);
+		return res;
+	}
+
+	reg->val = res;
+	reg->size = 1;
+	return 0;
+}
+
+static int tvp5150_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;
+	tvp5150_write(sd, reg->reg & 0xff, reg->val & 0xff);
+	return 0;
+}
+#endif
+
+static int tvp5150_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
+{
+	int status = tvp5150_read(sd, 0x88);
+
+	vt->signal = ((status & 0x04) && (status & 0x02)) ? 0xffff : 0x0;
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static const struct v4l2_ctrl_ops tvp5150_ctrl_ops = {
+	.s_ctrl = tvp5150_s_ctrl,
+};
+
+static const struct v4l2_subdev_core_ops tvp5150_core_ops = {
+	.log_status = tvp5150_log_status,
+	.g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
+	.try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
+	.s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
+	.g_ctrl = v4l2_subdev_g_ctrl,
+	.s_ctrl = v4l2_subdev_s_ctrl,
+	.queryctrl = v4l2_subdev_queryctrl,
+	.querymenu = v4l2_subdev_querymenu,
+	.s_std = tvp5150_s_std,
+	.reset = tvp5150_reset,
+	.g_chip_ident = tvp5150_g_chip_ident,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.g_register = tvp5150_g_register,
+	.s_register = tvp5150_s_register,
+#endif
+};
+
+static const struct v4l2_subdev_tuner_ops tvp5150_tuner_ops = {
+	.g_tuner = tvp5150_g_tuner,
+};
+
+static const struct v4l2_subdev_video_ops tvp5150_video_ops = {
+	.s_routing = tvp5150_s_routing,
+	.enum_mbus_fmt = tvp5150_enum_mbus_fmt,
+	.s_mbus_fmt = tvp5150_mbus_fmt,
+	.try_mbus_fmt = tvp5150_mbus_fmt,
+	.g_mbus_fmt = tvp5150_mbus_fmt,
+	.s_crop = tvp5150_s_crop,
+	.g_crop = tvp5150_g_crop,
+	.cropcap = tvp5150_cropcap,
+};
+
+static const struct v4l2_subdev_vbi_ops tvp5150_vbi_ops = {
+	.g_sliced_vbi_cap = tvp5150_g_sliced_vbi_cap,
+	.g_sliced_fmt = tvp5150_g_sliced_fmt,
+	.s_sliced_fmt = tvp5150_s_sliced_fmt,
+	.s_raw_fmt = tvp5150_s_raw_fmt,
+};
+
+static const struct v4l2_subdev_ops tvp5150_ops = {
+	.core = &tvp5150_core_ops,
+	.tuner = &tvp5150_tuner_ops,
+	.video = &tvp5150_video_ops,
+	.vbi = &tvp5150_vbi_ops,
+};
+
+
+/****************************************************************************
+			I2C Client & Driver
+ ****************************************************************************/
+
+static int tvp5150_probe(struct i2c_client *c,
+			 const struct i2c_device_id *id)
+{
+	struct tvp5150 *core;
+	struct v4l2_subdev *sd;
+	int tvp5150_id[4];
+	int i, res;
+
+	/* Check if the adapter supports the needed features */
+	if (!i2c_check_functionality(c->adapter,
+	     I2C_FUNC_SMBUS_READ_BYTE | I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
+		return -EIO;
+
+	core = kzalloc(sizeof(struct tvp5150), GFP_KERNEL);
+	if (!core) {
+		return -ENOMEM;
+	}
+	sd = &core->sd;
+	v4l2_i2c_subdev_init(sd, c, &tvp5150_ops);
+
+	/* 
+	 * Read consequent registers - TVP5150_MSB_DEV_ID, TVP5150_LSB_DEV_ID,
+	 * TVP5150_ROM_MAJOR_VER, TVP5150_ROM_MINOR_VER 
+	 */
+	for (i = 0; i < 4; i++) {
+		res = tvp5150_read(sd, TVP5150_MSB_DEV_ID + i);
+		if (res < 0)
+			goto free_core;
+		tvp5150_id[i] = res;
+	}
+
+	v4l_info(c, "chip found @ 0x%02x (%s)\n",
+		 c->addr << 1, c->adapter->name);
+
+	if (tvp5150_id[2] == 4 && tvp5150_id[3] == 0) { /* Is TVP5150AM1 */
+		v4l2_info(sd, "tvp%02x%02xam1 detected.\n",
+			  tvp5150_id[0], tvp5150_id[1]);
+
+		/* ITU-T BT.656.4 timing */
+		tvp5150_write(sd, TVP5150_REV_SELECT, 0);
+	} else {
+		/* Is TVP5150A */
+		if (tvp5150_id[2] == 3 || tvp5150_id[3] == 0x21) {
+			v4l2_info(sd, "tvp%02x%02xa detected.\n",
+				  tvp5150_id[2], tvp5150_id[3]);
+		} else {
+			v4l2_info(sd, "*** unknown tvp%02x%02x chip detected.\n",
+				  tvp5150_id[2], tvp5150_id[3]);
+			v4l2_info(sd, "*** Rom ver is %d.%d\n",
+				  tvp5150_id[2], tvp5150_id[3]);
+		}
+	}
+
+	core->norm = V4L2_STD_ALL;	/* Default is autodetect */
+	core->input = TVP5150_COMPOSITE1;
+	core->enable = 1;
+
+	v4l2_ctrl_handler_init(&core->hdl, 4);
+	v4l2_ctrl_new_std(&core->hdl, &tvp5150_ctrl_ops,
+			V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
+	v4l2_ctrl_new_std(&core->hdl, &tvp5150_ctrl_ops,
+			V4L2_CID_CONTRAST, 0, 255, 1, 128);
+	v4l2_ctrl_new_std(&core->hdl, &tvp5150_ctrl_ops,
+			V4L2_CID_SATURATION, 0, 255, 1, 128);
+	v4l2_ctrl_new_std(&core->hdl, &tvp5150_ctrl_ops,
+			V4L2_CID_HUE, -128, 127, 1, 0);
+	sd->ctrl_handler = &core->hdl;
+	if (core->hdl.error) {
+		res = core->hdl.error;
+		v4l2_ctrl_handler_free(&core->hdl);
+		goto free_core;
+	}
+	v4l2_ctrl_handler_setup(&core->hdl);
+
+	/* Default is no cropping */
+	core->rect.top = 0;
+	if (tvp5150_read_std(sd) & V4L2_STD_525_60)
+		core->rect.height = TVP5150_V_MAX_525_60;
+	else
+		core->rect.height = TVP5150_V_MAX_OTHERS;
+	core->rect.left = 0;
+	core->rect.width = TVP5150_H_MAX;
+
+	if (debug > 1)
+		tvp5150_log_status(sd);
+	return 0;
+
+free_core:
+	kfree(core);
+	return res;
+}
+
+static int tvp5150_remove(struct i2c_client *c)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(c);
+	struct tvp5150 *decoder = to_tvp5150(sd);
+
+	v4l2_dbg(1, debug, sd,
+		"tvp5150.c: removing tvp5150 adapter on address 0x%x\n",
+		c->addr << 1);
+
+	v4l2_device_unregister_subdev(sd);
+	v4l2_ctrl_handler_free(&decoder->hdl);
+	kfree(to_tvp5150(sd));
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static const struct i2c_device_id tvp5150_id[] = {
+	{ "tvp5150", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, tvp5150_id);
+
+static struct i2c_driver tvp5150_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "tvp5150",
+	},
+	.probe		= tvp5150_probe,
+	.remove		= tvp5150_remove,
+	.id_table	= tvp5150_id,
+};
+
+module_i2c_driver(tvp5150_driver);
diff --git a/drivers/media/i2c/tvp5150_reg.h b/drivers/media/i2c/tvp5150_reg.h
new file mode 100644
index 0000000..25a9949
--- /dev/null
+++ b/drivers/media/i2c/tvp5150_reg.h
@@ -0,0 +1,139 @@
+/*
+ * tvp5150 - Texas Instruments TVP5150A/AM1 video decoder registers
+ *
+ * Copyright (c) 2005,2006 Mauro Carvalho Chehab (mchehab@infradead.org)
+ * This code is placed under the terms of the GNU General Public License v2
+ */
+
+#define TVP5150_VD_IN_SRC_SEL_1      0x00 /* Video input source selection #1 */
+#define TVP5150_ANAL_CHL_CTL         0x01 /* Analog channel controls */
+#define TVP5150_OP_MODE_CTL          0x02 /* Operation mode controls */
+#define TVP5150_MISC_CTL             0x03 /* Miscellaneous controls */
+#define TVP5150_AUTOSW_MSK           0x04 /* Autoswitch mask: TVP5150A / TVP5150AM */
+
+/* Reserved 05h */
+
+#define TVP5150_COLOR_KIL_THSH_CTL   0x06 /* Color killer threshold control */
+#define TVP5150_LUMA_PROC_CTL_1      0x07 /* Luminance processing control #1 */
+#define TVP5150_LUMA_PROC_CTL_2      0x08 /* Luminance processing control #2 */
+#define TVP5150_BRIGHT_CTL           0x09 /* Brightness control */
+#define TVP5150_SATURATION_CTL       0x0a /* Color saturation control */
+#define TVP5150_HUE_CTL              0x0b /* Hue control */
+#define TVP5150_CONTRAST_CTL         0x0c /* Contrast control */
+#define TVP5150_DATA_RATE_SEL        0x0d /* Outputs and data rates select */
+#define TVP5150_LUMA_PROC_CTL_3      0x0e /* Luminance processing control #3 */
+#define TVP5150_CONF_SHARED_PIN      0x0f /* Configuration shared pins */
+
+/* Reserved 10h */
+
+#define TVP5150_ACT_VD_CROP_ST_MSB   0x11 /* Active video cropping start MSB */
+#define TVP5150_ACT_VD_CROP_ST_LSB   0x12 /* Active video cropping start LSB */
+#define TVP5150_ACT_VD_CROP_STP_MSB  0x13 /* Active video cropping stop MSB */
+#define TVP5150_ACT_VD_CROP_STP_LSB  0x14 /* Active video cropping stop LSB */
+#define TVP5150_GENLOCK              0x15 /* Genlock/RTC */
+#define TVP5150_HORIZ_SYNC_START     0x16 /* Horizontal sync start */
+
+/* Reserved 17h */
+
+#define TVP5150_VERT_BLANKING_START 0x18 /* Vertical blanking start */
+#define TVP5150_VERT_BLANKING_STOP  0x19 /* Vertical blanking stop */
+#define TVP5150_CHROMA_PROC_CTL_1   0x1a /* Chrominance processing control #1 */
+#define TVP5150_CHROMA_PROC_CTL_2   0x1b /* Chrominance processing control #2 */
+#define TVP5150_INT_RESET_REG_B     0x1c /* Interrupt reset register B */
+#define TVP5150_INT_ENABLE_REG_B    0x1d /* Interrupt enable register B */
+#define TVP5150_INTT_CONFIG_REG_B   0x1e /* Interrupt configuration register B */
+
+/* Reserved 1Fh-27h */
+
+#define VIDEO_STD_MASK			 (0x07 >> 1)
+#define TVP5150_VIDEO_STD                0x28 /* Video standard */
+#define VIDEO_STD_AUTO_SWITCH_BIT	 0x00
+#define VIDEO_STD_NTSC_MJ_BIT		 0x02
+#define VIDEO_STD_PAL_BDGHIN_BIT	 0x04
+#define VIDEO_STD_PAL_M_BIT		 0x06
+#define VIDEO_STD_PAL_COMBINATION_N_BIT	 0x08
+#define VIDEO_STD_NTSC_4_43_BIT		 0x0a
+#define VIDEO_STD_SECAM_BIT		 0x0c
+
+#define VIDEO_STD_NTSC_MJ_BIT_AS                 0x01
+#define VIDEO_STD_PAL_BDGHIN_BIT_AS              0x03
+#define VIDEO_STD_PAL_M_BIT_AS		         0x05
+#define VIDEO_STD_PAL_COMBINATION_N_BIT_AS	 0x07
+#define VIDEO_STD_NTSC_4_43_BIT_AS		 0x09
+#define VIDEO_STD_SECAM_BIT_AS		         0x0b
+
+/* Reserved 29h-2bh */
+
+#define TVP5150_CB_GAIN_FACT        0x2c /* Cb gain factor */
+#define TVP5150_CR_GAIN_FACTOR      0x2d /* Cr gain factor */
+#define TVP5150_MACROVISION_ON_CTR  0x2e /* Macrovision on counter */
+#define TVP5150_MACROVISION_OFF_CTR 0x2f /* Macrovision off counter */
+#define TVP5150_REV_SELECT          0x30 /* revision select (TVP5150AM1 only) */
+
+/* Reserved	31h-7Fh */
+
+#define TVP5150_MSB_DEV_ID          0x80 /* MSB of device ID */
+#define TVP5150_LSB_DEV_ID          0x81 /* LSB of device ID */
+#define TVP5150_ROM_MAJOR_VER       0x82 /* ROM major version */
+#define TVP5150_ROM_MINOR_VER       0x83 /* ROM minor version */
+#define TVP5150_VERT_LN_COUNT_MSB   0x84 /* Vertical line count MSB */
+#define TVP5150_VERT_LN_COUNT_LSB   0x85 /* Vertical line count LSB */
+#define TVP5150_INT_STATUS_REG_B    0x86 /* Interrupt status register B */
+#define TVP5150_INT_ACTIVE_REG_B    0x87 /* Interrupt active register B */
+#define TVP5150_STATUS_REG_1        0x88 /* Status register #1 */
+#define TVP5150_STATUS_REG_2        0x89 /* Status register #2 */
+#define TVP5150_STATUS_REG_3        0x8a /* Status register #3 */
+#define TVP5150_STATUS_REG_4        0x8b /* Status register #4 */
+#define TVP5150_STATUS_REG_5        0x8c /* Status register #5 */
+/* Reserved	8Dh-8Fh */
+ /* Closed caption data registers */
+#define TVP5150_CC_DATA_INI         0x90
+#define TVP5150_CC_DATA_END         0x93
+
+ /* WSS data registers */
+#define TVP5150_WSS_DATA_INI        0x94
+#define TVP5150_WSS_DATA_END        0x99
+
+/* VPS data registers */
+#define TVP5150_VPS_DATA_INI        0x9a
+#define TVP5150_VPS_DATA_END        0xa6
+
+/* VITC data registers */
+#define TVP5150_VITC_DATA_INI       0xa7
+#define TVP5150_VITC_DATA_END       0xaf
+
+#define TVP5150_VBI_FIFO_READ_DATA  0xb0 /* VBI FIFO read data */
+
+/* Teletext filter 1 */
+#define TVP5150_TELETEXT_FIL1_INI  0xb1
+#define TVP5150_TELETEXT_FIL1_END  0xb5
+
+/* Teletext filter 2 */
+#define TVP5150_TELETEXT_FIL2_INI  0xb6
+#define TVP5150_TELETEXT_FIL2_END  0xba
+
+#define TVP5150_TELETEXT_FIL_ENA    0xbb /* Teletext filter enable */
+/* Reserved	BCh-BFh */
+#define TVP5150_INT_STATUS_REG_A    0xc0 /* Interrupt status register A */
+#define TVP5150_INT_ENABLE_REG_A    0xc1 /* Interrupt enable register A */
+#define TVP5150_INT_CONF            0xc2 /* Interrupt configuration */
+#define TVP5150_VDP_CONF_RAM_DATA   0xc3 /* VDP configuration RAM data */
+#define TVP5150_CONF_RAM_ADDR_LOW   0xc4 /* Configuration RAM address low byte */
+#define TVP5150_CONF_RAM_ADDR_HIGH  0xc5 /* Configuration RAM address high byte */
+#define TVP5150_VDP_STATUS_REG      0xc6 /* VDP status register */
+#define TVP5150_FIFO_WORD_COUNT     0xc7 /* FIFO word count */
+#define TVP5150_FIFO_INT_THRESHOLD  0xc8 /* FIFO interrupt threshold */
+#define TVP5150_FIFO_RESET          0xc9 /* FIFO reset */
+#define TVP5150_LINE_NUMBER_INT     0xca /* Line number interrupt */
+#define TVP5150_PIX_ALIGN_REG_LOW   0xcb /* Pixel alignment register low byte */
+#define TVP5150_PIX_ALIGN_REG_HIGH  0xcc /* Pixel alignment register high byte */
+#define TVP5150_FIFO_OUT_CTRL       0xcd /* FIFO output control */
+/* Reserved	CEh */
+#define TVP5150_FULL_FIELD_ENA      0xcf /* Full field enable 1 */
+
+/* Line mode registers */
+#define TVP5150_LINE_MODE_INI       0xd0
+#define TVP5150_LINE_MODE_END       0xfb
+
+#define TVP5150_FULL_FIELD_MODE_REG 0xfc /* Full field mode register */
+/* Reserved	FDh-FFh */
diff --git a/drivers/media/i2c/tvp7002.c b/drivers/media/i2c/tvp7002.c
new file mode 100644
index 0000000..fb6a5b5
--- /dev/null
+++ b/drivers/media/i2c/tvp7002.c
@@ -0,0 +1,1145 @@
+/* Texas Instruments Triple 8-/10-BIT 165-/110-MSPS Video and Graphics
+ * Digitizer with Horizontal PLL registers
+ *
+ * Copyright (C) 2009 Texas Instruments Inc
+ * Author: Santiago Nunez-Corrales <santiago.nunez@ridgerun.com>
+ *
+ * This code is partially based upon the TVP5150 driver
+ * written by Mauro Carvalho Chehab (mchehab@infradead.org),
+ * the TVP514x driver written by Vaibhav Hiremath <hvaibhav@ti.com>
+ * and the TVP7002 driver in the TI LSP 2.10.00.14. Revisions by
+ * Muralidharan Karicheri and Snehaprabha Narnakaje (TI).
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/delay.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/videodev2.h>
+#include <linux/module.h>
+#include <linux/v4l2-dv-timings.h>
+#include <media/tvp7002.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ctrls.h>
+#include "tvp7002_reg.h"
+
+MODULE_DESCRIPTION("TI TVP7002 Video and Graphics Digitizer driver");
+MODULE_AUTHOR("Santiago Nunez-Corrales <santiago.nunez@ridgerun.com>");
+MODULE_LICENSE("GPL");
+
+/* Module Name */
+#define TVP7002_MODULE_NAME	"tvp7002"
+
+/* I2C retry attempts */
+#define I2C_RETRY_COUNT		(5)
+
+/* End of registers */
+#define TVP7002_EOR		0x5c
+
+/* Read write definition for registers */
+#define TVP7002_READ		0
+#define TVP7002_WRITE		1
+#define TVP7002_RESERVED	2
+
+/* Interlaced vs progressive mask and shift */
+#define TVP7002_IP_SHIFT	5
+#define TVP7002_INPR_MASK	(0x01 << TVP7002_IP_SHIFT)
+
+/* Shift for CPL and LPF registers */
+#define TVP7002_CL_SHIFT	8
+#define TVP7002_CL_MASK		0x0f
+
+/* Debug functions */
+static bool debug;
+module_param(debug, bool, 0644);
+MODULE_PARM_DESC(debug, "Debug level (0-2)");
+
+/* Structure for register values */
+struct i2c_reg_value {
+	u8 reg;
+	u8 value;
+	u8 type;
+};
+
+/*
+ * Register default values (according to tvp7002 datasheet)
+ * In the case of read-only registers, the value (0xff) is
+ * never written. R/W functionality is controlled by the
+ * writable bit in the register struct definition.
+ */
+static const struct i2c_reg_value tvp7002_init_default[] = {
+	{ TVP7002_CHIP_REV, 0xff, TVP7002_READ },
+	{ TVP7002_HPLL_FDBK_DIV_MSBS, 0x67, TVP7002_WRITE },
+	{ TVP7002_HPLL_FDBK_DIV_LSBS, 0x20, TVP7002_WRITE },
+	{ TVP7002_HPLL_CRTL, 0xa0, TVP7002_WRITE },
+	{ TVP7002_HPLL_PHASE_SEL, 0x80, TVP7002_WRITE },
+	{ TVP7002_CLAMP_START, 0x32, TVP7002_WRITE },
+	{ TVP7002_CLAMP_W, 0x20, TVP7002_WRITE },
+	{ TVP7002_HSYNC_OUT_W, 0x60, TVP7002_WRITE },
+	{ TVP7002_B_FINE_GAIN, 0x00, TVP7002_WRITE },
+	{ TVP7002_G_FINE_GAIN, 0x00, TVP7002_WRITE },
+	{ TVP7002_R_FINE_GAIN, 0x00, TVP7002_WRITE },
+	{ TVP7002_B_FINE_OFF_MSBS, 0x80, TVP7002_WRITE },
+	{ TVP7002_G_FINE_OFF_MSBS, 0x80, TVP7002_WRITE },
+	{ TVP7002_R_FINE_OFF_MSBS, 0x80, TVP7002_WRITE },
+	{ TVP7002_SYNC_CTL_1, 0x20, TVP7002_WRITE },
+	{ TVP7002_HPLL_AND_CLAMP_CTL, 0x2e, TVP7002_WRITE },
+	{ TVP7002_SYNC_ON_G_THRS, 0x5d, TVP7002_WRITE },
+	{ TVP7002_SYNC_SEPARATOR_THRS, 0x47, TVP7002_WRITE },
+	{ TVP7002_HPLL_PRE_COAST, 0x00, TVP7002_WRITE },
+	{ TVP7002_HPLL_POST_COAST, 0x00, TVP7002_WRITE },
+	{ TVP7002_SYNC_DETECT_STAT, 0xff, TVP7002_READ },
+	{ TVP7002_OUT_FORMATTER, 0x47, TVP7002_WRITE },
+	{ TVP7002_MISC_CTL_1, 0x01, TVP7002_WRITE },
+	{ TVP7002_MISC_CTL_2, 0x00, TVP7002_WRITE },
+	{ TVP7002_MISC_CTL_3, 0x01, TVP7002_WRITE },
+	{ TVP7002_IN_MUX_SEL_1, 0x00, TVP7002_WRITE },
+	{ TVP7002_IN_MUX_SEL_2, 0x67, TVP7002_WRITE },
+	{ TVP7002_B_AND_G_COARSE_GAIN, 0x77, TVP7002_WRITE },
+	{ TVP7002_R_COARSE_GAIN, 0x07, TVP7002_WRITE },
+	{ TVP7002_FINE_OFF_LSBS, 0x00, TVP7002_WRITE },
+	{ TVP7002_B_COARSE_OFF, 0x10, TVP7002_WRITE },
+	{ TVP7002_G_COARSE_OFF, 0x10, TVP7002_WRITE },
+	{ TVP7002_R_COARSE_OFF, 0x10, TVP7002_WRITE },
+	{ TVP7002_HSOUT_OUT_START, 0x08, TVP7002_WRITE },
+	{ TVP7002_MISC_CTL_4, 0x00, TVP7002_WRITE },
+	{ TVP7002_B_DGTL_ALC_OUT_LSBS, 0xff, TVP7002_READ },
+	{ TVP7002_G_DGTL_ALC_OUT_LSBS, 0xff, TVP7002_READ },
+	{ TVP7002_R_DGTL_ALC_OUT_LSBS, 0xff, TVP7002_READ },
+	{ TVP7002_AUTO_LVL_CTL_ENABLE, 0x80, TVP7002_WRITE },
+	{ TVP7002_DGTL_ALC_OUT_MSBS, 0xff, TVP7002_READ },
+	{ TVP7002_AUTO_LVL_CTL_FILTER, 0x53, TVP7002_WRITE },
+	{ 0x29, 0x08, TVP7002_RESERVED },
+	{ TVP7002_FINE_CLAMP_CTL, 0x07, TVP7002_WRITE },
+	/* PWR_CTL is controlled only by the probe and reset functions */
+	{ TVP7002_PWR_CTL, 0x00, TVP7002_RESERVED },
+	{ TVP7002_ADC_SETUP, 0x50, TVP7002_WRITE },
+	{ TVP7002_COARSE_CLAMP_CTL, 0x00, TVP7002_WRITE },
+	{ TVP7002_SOG_CLAMP, 0x80, TVP7002_WRITE },
+	{ TVP7002_RGB_COARSE_CLAMP_CTL, 0x8c, TVP7002_WRITE },
+	{ TVP7002_SOG_COARSE_CLAMP_CTL, 0x04, TVP7002_WRITE },
+	{ TVP7002_ALC_PLACEMENT, 0x5a, TVP7002_WRITE },
+	{ 0x32, 0x18, TVP7002_RESERVED },
+	{ 0x33, 0x60, TVP7002_RESERVED },
+	{ TVP7002_MVIS_STRIPPER_W, 0xff, TVP7002_RESERVED },
+	{ TVP7002_VSYNC_ALGN, 0x10, TVP7002_WRITE },
+	{ TVP7002_SYNC_BYPASS, 0x00, TVP7002_WRITE },
+	{ TVP7002_L_FRAME_STAT_LSBS, 0xff, TVP7002_READ },
+	{ TVP7002_L_FRAME_STAT_MSBS, 0xff, TVP7002_READ },
+	{ TVP7002_CLK_L_STAT_LSBS, 0xff, TVP7002_READ },
+	{ TVP7002_CLK_L_STAT_MSBS, 0xff, TVP7002_READ },
+	{ TVP7002_HSYNC_W, 0xff, TVP7002_READ },
+	{ TVP7002_VSYNC_W, 0xff, TVP7002_READ },
+	{ TVP7002_L_LENGTH_TOL, 0x03, TVP7002_WRITE },
+	{ 0x3e, 0x60, TVP7002_RESERVED },
+	{ TVP7002_VIDEO_BWTH_CTL, 0x01, TVP7002_WRITE },
+	{ TVP7002_AVID_START_PIXEL_LSBS, 0x01, TVP7002_WRITE },
+	{ TVP7002_AVID_START_PIXEL_MSBS, 0x2c, TVP7002_WRITE },
+	{ TVP7002_AVID_STOP_PIXEL_LSBS, 0x06, TVP7002_WRITE },
+	{ TVP7002_AVID_STOP_PIXEL_MSBS, 0x2c, TVP7002_WRITE },
+	{ TVP7002_VBLK_F_0_START_L_OFF, 0x05, TVP7002_WRITE },
+	{ TVP7002_VBLK_F_1_START_L_OFF, 0x00, TVP7002_WRITE },
+	{ TVP7002_VBLK_F_0_DURATION, 0x1e, TVP7002_WRITE },
+	{ TVP7002_VBLK_F_1_DURATION, 0x00, TVP7002_WRITE },
+	{ TVP7002_FBIT_F_0_START_L_OFF, 0x00, TVP7002_WRITE },
+	{ TVP7002_FBIT_F_1_START_L_OFF, 0x00, TVP7002_WRITE },
+	{ TVP7002_YUV_Y_G_COEF_LSBS, 0xe3, TVP7002_WRITE },
+	{ TVP7002_YUV_Y_G_COEF_MSBS, 0x16, TVP7002_WRITE },
+	{ TVP7002_YUV_Y_B_COEF_LSBS, 0x4f, TVP7002_WRITE },
+	{ TVP7002_YUV_Y_B_COEF_MSBS, 0x02, TVP7002_WRITE },
+	{ TVP7002_YUV_Y_R_COEF_LSBS, 0xce, TVP7002_WRITE },
+	{ TVP7002_YUV_Y_R_COEF_MSBS, 0x06, TVP7002_WRITE },
+	{ TVP7002_YUV_U_G_COEF_LSBS, 0xab, TVP7002_WRITE },
+	{ TVP7002_YUV_U_G_COEF_MSBS, 0xf3, TVP7002_WRITE },
+	{ TVP7002_YUV_U_B_COEF_LSBS, 0x00, TVP7002_WRITE },
+	{ TVP7002_YUV_U_B_COEF_MSBS, 0x10, TVP7002_WRITE },
+	{ TVP7002_YUV_U_R_COEF_LSBS, 0x55, TVP7002_WRITE },
+	{ TVP7002_YUV_U_R_COEF_MSBS, 0xfc, TVP7002_WRITE },
+	{ TVP7002_YUV_V_G_COEF_LSBS, 0x78, TVP7002_WRITE },
+	{ TVP7002_YUV_V_G_COEF_MSBS, 0xf1, TVP7002_WRITE },
+	{ TVP7002_YUV_V_B_COEF_LSBS, 0x88, TVP7002_WRITE },
+	{ TVP7002_YUV_V_B_COEF_MSBS, 0xfe, TVP7002_WRITE },
+	{ TVP7002_YUV_V_R_COEF_LSBS, 0x00, TVP7002_WRITE },
+	{ TVP7002_YUV_V_R_COEF_MSBS, 0x10, TVP7002_WRITE },
+	/* This signals end of register values */
+	{ TVP7002_EOR, 0xff, TVP7002_RESERVED }
+};
+
+/* Register parameters for 480P */
+static const struct i2c_reg_value tvp7002_parms_480P[] = {
+	{ TVP7002_HPLL_FDBK_DIV_MSBS, 0x35, TVP7002_WRITE },
+	{ TVP7002_HPLL_FDBK_DIV_LSBS, 0xa0, TVP7002_WRITE },
+	{ TVP7002_HPLL_CRTL, 0x02, TVP7002_WRITE },
+	{ TVP7002_AVID_START_PIXEL_LSBS, 0x91, TVP7002_WRITE },
+	{ TVP7002_AVID_START_PIXEL_MSBS, 0x00, TVP7002_WRITE },
+	{ TVP7002_AVID_STOP_PIXEL_LSBS, 0x0B, TVP7002_WRITE },
+	{ TVP7002_AVID_STOP_PIXEL_MSBS, 0x00, TVP7002_WRITE },
+	{ TVP7002_VBLK_F_0_START_L_OFF, 0x03, TVP7002_WRITE },
+	{ TVP7002_VBLK_F_1_START_L_OFF, 0x01, TVP7002_WRITE },
+	{ TVP7002_VBLK_F_0_DURATION, 0x13, TVP7002_WRITE },
+	{ TVP7002_VBLK_F_1_DURATION, 0x13, TVP7002_WRITE },
+	{ TVP7002_ALC_PLACEMENT, 0x18, TVP7002_WRITE },
+	{ TVP7002_CLAMP_START, 0x06, TVP7002_WRITE },
+	{ TVP7002_CLAMP_W, 0x10, TVP7002_WRITE },
+	{ TVP7002_HPLL_PRE_COAST, 0x03, TVP7002_WRITE },
+	{ TVP7002_HPLL_POST_COAST, 0x03, TVP7002_WRITE },
+	{ TVP7002_EOR, 0xff, TVP7002_RESERVED }
+};
+
+/* Register parameters for 576P */
+static const struct i2c_reg_value tvp7002_parms_576P[] = {
+	{ TVP7002_HPLL_FDBK_DIV_MSBS, 0x36, TVP7002_WRITE },
+	{ TVP7002_HPLL_FDBK_DIV_LSBS, 0x00, TVP7002_WRITE },
+	{ TVP7002_HPLL_CRTL, 0x18, TVP7002_WRITE },
+	{ TVP7002_AVID_START_PIXEL_LSBS, 0x9B, TVP7002_WRITE },
+	{ TVP7002_AVID_START_PIXEL_MSBS, 0x00, TVP7002_WRITE },
+	{ TVP7002_AVID_STOP_PIXEL_LSBS, 0x0F, TVP7002_WRITE },
+	{ TVP7002_AVID_STOP_PIXEL_MSBS, 0x00, TVP7002_WRITE },
+	{ TVP7002_VBLK_F_0_START_L_OFF, 0x00, TVP7002_WRITE },
+	{ TVP7002_VBLK_F_1_START_L_OFF, 0x00, TVP7002_WRITE },
+	{ TVP7002_VBLK_F_0_DURATION, 0x2D, TVP7002_WRITE },
+	{ TVP7002_VBLK_F_1_DURATION, 0x00, TVP7002_WRITE },
+	{ TVP7002_ALC_PLACEMENT, 0x18, TVP7002_WRITE },
+	{ TVP7002_CLAMP_START, 0x06, TVP7002_WRITE },
+	{ TVP7002_CLAMP_W, 0x10, TVP7002_WRITE },
+	{ TVP7002_HPLL_PRE_COAST, 0x03, TVP7002_WRITE },
+	{ TVP7002_HPLL_POST_COAST, 0x03, TVP7002_WRITE },
+	{ TVP7002_EOR, 0xff, TVP7002_RESERVED }
+};
+
+/* Register parameters for 1080I60 */
+static const struct i2c_reg_value tvp7002_parms_1080I60[] = {
+	{ TVP7002_HPLL_FDBK_DIV_MSBS, 0x89, TVP7002_WRITE },
+	{ TVP7002_HPLL_FDBK_DIV_LSBS, 0x80, TVP7002_WRITE },
+	{ TVP7002_HPLL_CRTL, 0x98, TVP7002_WRITE },
+	{ TVP7002_AVID_START_PIXEL_LSBS, 0x06, TVP7002_WRITE },
+	{ TVP7002_AVID_START_PIXEL_MSBS, 0x01, TVP7002_WRITE },
+	{ TVP7002_AVID_STOP_PIXEL_LSBS, 0x8a, TVP7002_WRITE },
+	{ TVP7002_AVID_STOP_PIXEL_MSBS, 0x08, TVP7002_WRITE },
+	{ TVP7002_VBLK_F_0_START_L_OFF, 0x02, TVP7002_WRITE },
+	{ TVP7002_VBLK_F_1_START_L_OFF, 0x02, TVP7002_WRITE },
+	{ TVP7002_VBLK_F_0_DURATION, 0x16, TVP7002_WRITE },
+	{ TVP7002_VBLK_F_1_DURATION, 0x17, TVP7002_WRITE },
+	{ TVP7002_ALC_PLACEMENT, 0x5a, TVP7002_WRITE },
+	{ TVP7002_CLAMP_START, 0x32, TVP7002_WRITE },
+	{ TVP7002_CLAMP_W, 0x20, TVP7002_WRITE },
+	{ TVP7002_HPLL_PRE_COAST, 0x01, TVP7002_WRITE },
+	{ TVP7002_HPLL_POST_COAST, 0x00, TVP7002_WRITE },
+	{ TVP7002_EOR, 0xff, TVP7002_RESERVED }
+};
+
+/* Register parameters for 1080P60 */
+static const struct i2c_reg_value tvp7002_parms_1080P60[] = {
+	{ TVP7002_HPLL_FDBK_DIV_MSBS, 0x89, TVP7002_WRITE },
+	{ TVP7002_HPLL_FDBK_DIV_LSBS, 0x80, TVP7002_WRITE },
+	{ TVP7002_HPLL_CRTL, 0xE0, TVP7002_WRITE },
+	{ TVP7002_AVID_START_PIXEL_LSBS, 0x06, TVP7002_WRITE },
+	{ TVP7002_AVID_START_PIXEL_MSBS, 0x01, TVP7002_WRITE },
+	{ TVP7002_AVID_STOP_PIXEL_LSBS, 0x8a, TVP7002_WRITE },
+	{ TVP7002_AVID_STOP_PIXEL_MSBS, 0x08, TVP7002_WRITE },
+	{ TVP7002_VBLK_F_0_START_L_OFF, 0x02, TVP7002_WRITE },
+	{ TVP7002_VBLK_F_1_START_L_OFF, 0x02, TVP7002_WRITE },
+	{ TVP7002_VBLK_F_0_DURATION, 0x16, TVP7002_WRITE },
+	{ TVP7002_VBLK_F_1_DURATION, 0x17, TVP7002_WRITE },
+	{ TVP7002_ALC_PLACEMENT, 0x5a, TVP7002_WRITE },
+	{ TVP7002_CLAMP_START, 0x32, TVP7002_WRITE },
+	{ TVP7002_CLAMP_W, 0x20, TVP7002_WRITE },
+	{ TVP7002_HPLL_PRE_COAST, 0x01, TVP7002_WRITE },
+	{ TVP7002_HPLL_POST_COAST, 0x00, TVP7002_WRITE },
+	{ TVP7002_EOR, 0xff, TVP7002_RESERVED }
+};
+
+/* Register parameters for 1080I50 */
+static const struct i2c_reg_value tvp7002_parms_1080I50[] = {
+	{ TVP7002_HPLL_FDBK_DIV_MSBS, 0xa5, TVP7002_WRITE },
+	{ TVP7002_HPLL_FDBK_DIV_LSBS, 0x00, TVP7002_WRITE },
+	{ TVP7002_HPLL_CRTL, 0x98, TVP7002_WRITE },
+	{ TVP7002_AVID_START_PIXEL_LSBS, 0x06, TVP7002_WRITE },
+	{ TVP7002_AVID_START_PIXEL_MSBS, 0x01, TVP7002_WRITE },
+	{ TVP7002_AVID_STOP_PIXEL_LSBS, 0x8a, TVP7002_WRITE },
+	{ TVP7002_AVID_STOP_PIXEL_MSBS, 0x08, TVP7002_WRITE },
+	{ TVP7002_VBLK_F_0_START_L_OFF, 0x02, TVP7002_WRITE },
+	{ TVP7002_VBLK_F_1_START_L_OFF, 0x02, TVP7002_WRITE },
+	{ TVP7002_VBLK_F_0_DURATION, 0x16, TVP7002_WRITE },
+	{ TVP7002_VBLK_F_1_DURATION, 0x17, TVP7002_WRITE },
+	{ TVP7002_ALC_PLACEMENT, 0x5a, TVP7002_WRITE },
+	{ TVP7002_CLAMP_START, 0x32, TVP7002_WRITE },
+	{ TVP7002_CLAMP_W, 0x20, TVP7002_WRITE },
+	{ TVP7002_HPLL_PRE_COAST, 0x01, TVP7002_WRITE },
+	{ TVP7002_HPLL_POST_COAST, 0x00, TVP7002_WRITE },
+	{ TVP7002_EOR, 0xff, TVP7002_RESERVED }
+};
+
+/* Register parameters for 720P60 */
+static const struct i2c_reg_value tvp7002_parms_720P60[] = {
+	{ TVP7002_HPLL_FDBK_DIV_MSBS, 0x67, TVP7002_WRITE },
+	{ TVP7002_HPLL_FDBK_DIV_LSBS, 0x20, TVP7002_WRITE },
+	{ TVP7002_HPLL_CRTL, 0xa0, TVP7002_WRITE },
+	{ TVP7002_AVID_START_PIXEL_LSBS, 0x47, TVP7002_WRITE },
+	{ TVP7002_AVID_START_PIXEL_MSBS, 0x01, TVP7002_WRITE },
+	{ TVP7002_AVID_STOP_PIXEL_LSBS, 0x4B, TVP7002_WRITE },
+	{ TVP7002_AVID_STOP_PIXEL_MSBS, 0x06, TVP7002_WRITE },
+	{ TVP7002_VBLK_F_0_START_L_OFF, 0x05, TVP7002_WRITE },
+	{ TVP7002_VBLK_F_1_START_L_OFF, 0x00, TVP7002_WRITE },
+	{ TVP7002_VBLK_F_0_DURATION, 0x2D, TVP7002_WRITE },
+	{ TVP7002_VBLK_F_1_DURATION, 0x00, TVP7002_WRITE },
+	{ TVP7002_ALC_PLACEMENT, 0x5a, TVP7002_WRITE },
+	{ TVP7002_CLAMP_START, 0x32, TVP7002_WRITE },
+	{ TVP7002_CLAMP_W, 0x20, TVP7002_WRITE },
+	{ TVP7002_HPLL_PRE_COAST, 0x00, TVP7002_WRITE },
+	{ TVP7002_HPLL_POST_COAST, 0x00, TVP7002_WRITE },
+	{ TVP7002_EOR, 0xff, TVP7002_RESERVED }
+};
+
+/* Register parameters for 720P50 */
+static const struct i2c_reg_value tvp7002_parms_720P50[] = {
+	{ TVP7002_HPLL_FDBK_DIV_MSBS, 0x7b, TVP7002_WRITE },
+	{ TVP7002_HPLL_FDBK_DIV_LSBS, 0xc0, TVP7002_WRITE },
+	{ TVP7002_HPLL_CRTL, 0x98, TVP7002_WRITE },
+	{ TVP7002_AVID_START_PIXEL_LSBS, 0x47, TVP7002_WRITE },
+	{ TVP7002_AVID_START_PIXEL_MSBS, 0x01, TVP7002_WRITE },
+	{ TVP7002_AVID_STOP_PIXEL_LSBS, 0x4B, TVP7002_WRITE },
+	{ TVP7002_AVID_STOP_PIXEL_MSBS, 0x06, TVP7002_WRITE },
+	{ TVP7002_VBLK_F_0_START_L_OFF, 0x05, TVP7002_WRITE },
+	{ TVP7002_VBLK_F_1_START_L_OFF, 0x00, TVP7002_WRITE },
+	{ TVP7002_VBLK_F_0_DURATION, 0x2D, TVP7002_WRITE },
+	{ TVP7002_VBLK_F_1_DURATION, 0x00, TVP7002_WRITE },
+	{ TVP7002_ALC_PLACEMENT, 0x5a, TVP7002_WRITE },
+	{ TVP7002_CLAMP_START, 0x32, TVP7002_WRITE },
+	{ TVP7002_CLAMP_W, 0x20, TVP7002_WRITE },
+	{ TVP7002_HPLL_PRE_COAST, 0x01, TVP7002_WRITE },
+	{ TVP7002_HPLL_POST_COAST, 0x00, TVP7002_WRITE },
+	{ TVP7002_EOR, 0xff, TVP7002_RESERVED }
+};
+
+/* Preset definition for handling device operation */
+struct tvp7002_preset_definition {
+	u32 preset;
+	struct v4l2_dv_timings timings;
+	const struct i2c_reg_value *p_settings;
+	enum v4l2_colorspace color_space;
+	enum v4l2_field scanmode;
+	u16 progressive;
+	u16 lines_per_frame;
+	u16 cpl_min;
+	u16 cpl_max;
+};
+
+/* Struct list for digital video presets */
+static const struct tvp7002_preset_definition tvp7002_presets[] = {
+	{
+		V4L2_DV_720P60,
+		V4L2_DV_BT_CEA_1280X720P60,
+		tvp7002_parms_720P60,
+		V4L2_COLORSPACE_REC709,
+		V4L2_FIELD_NONE,
+		1,
+		0x2EE,
+		135,
+		153
+	},
+	{
+		V4L2_DV_1080I60,
+		V4L2_DV_BT_CEA_1920X1080I60,
+		tvp7002_parms_1080I60,
+		V4L2_COLORSPACE_REC709,
+		V4L2_FIELD_INTERLACED,
+		0,
+		0x465,
+		181,
+		205
+	},
+	{
+		V4L2_DV_1080I50,
+		V4L2_DV_BT_CEA_1920X1080I50,
+		tvp7002_parms_1080I50,
+		V4L2_COLORSPACE_REC709,
+		V4L2_FIELD_INTERLACED,
+		0,
+		0x465,
+		217,
+		245
+	},
+	{
+		V4L2_DV_720P50,
+		V4L2_DV_BT_CEA_1280X720P50,
+		tvp7002_parms_720P50,
+		V4L2_COLORSPACE_REC709,
+		V4L2_FIELD_NONE,
+		1,
+		0x2EE,
+		163,
+		183
+	},
+	{
+		V4L2_DV_1080P60,
+		V4L2_DV_BT_CEA_1920X1080P60,
+		tvp7002_parms_1080P60,
+		V4L2_COLORSPACE_REC709,
+		V4L2_FIELD_NONE,
+		1,
+		0x465,
+		90,
+		102
+	},
+	{
+		V4L2_DV_480P59_94,
+		V4L2_DV_BT_CEA_720X480P59_94,
+		tvp7002_parms_480P,
+		V4L2_COLORSPACE_SMPTE170M,
+		V4L2_FIELD_NONE,
+		1,
+		0x20D,
+		0xffff,
+		0xffff
+	},
+	{
+		V4L2_DV_576P50,
+		V4L2_DV_BT_CEA_720X576P50,
+		tvp7002_parms_576P,
+		V4L2_COLORSPACE_SMPTE170M,
+		V4L2_FIELD_NONE,
+		1,
+		0x271,
+		0xffff,
+		0xffff
+	}
+};
+
+#define NUM_PRESETS	ARRAY_SIZE(tvp7002_presets)
+
+/* Device definition */
+struct tvp7002 {
+	struct v4l2_subdev sd;
+	struct v4l2_ctrl_handler hdl;
+	const struct tvp7002_config *pdata;
+
+	int ver;
+	int streaming;
+
+	const struct tvp7002_preset_definition *current_preset;
+};
+
+/*
+ * to_tvp7002 - Obtain device handler TVP7002
+ * @sd: ptr to v4l2_subdev struct
+ *
+ * Returns device handler tvp7002.
+ */
+static inline struct tvp7002 *to_tvp7002(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct tvp7002, sd);
+}
+
+static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
+{
+	return &container_of(ctrl->handler, struct tvp7002, hdl)->sd;
+}
+
+/*
+ * tvp7002_read - Read a value from a register in an TVP7002
+ * @sd: ptr to v4l2_subdev struct
+ * @addr: TVP7002 register address
+ * @dst: pointer to 8-bit destination
+ *
+ * Returns value read if successful, or non-zero (-1) otherwise.
+ */
+static int tvp7002_read(struct v4l2_subdev *sd, u8 addr, u8 *dst)
+{
+	struct i2c_client *c = v4l2_get_subdevdata(sd);
+	int retry;
+	int error;
+
+	for (retry = 0; retry < I2C_RETRY_COUNT; retry++) {
+		error = i2c_smbus_read_byte_data(c, addr);
+
+		if (error >= 0) {
+			*dst = (u8)error;
+			return 0;
+		}
+
+		msleep_interruptible(10);
+	}
+	v4l2_err(sd, "TVP7002 read error %d\n", error);
+	return error;
+}
+
+/*
+ * tvp7002_read_err() - Read a register value with error code
+ * @sd: pointer to standard V4L2 sub-device structure
+ * @reg: destination register
+ * @val: value to be read
+ * @err: pointer to error value
+ *
+ * Read a value in a register and save error value in pointer.
+ * Also update the register table if successful
+ */
+static inline void tvp7002_read_err(struct v4l2_subdev *sd, u8 reg,
+							u8 *dst, int *err)
+{
+	if (!*err)
+		*err = tvp7002_read(sd, reg, dst);
+}
+
+/*
+ * tvp7002_write() - Write a value to a register in TVP7002
+ * @sd: ptr to v4l2_subdev struct
+ * @addr: TVP7002 register address
+ * @value: value to be written to the register
+ *
+ * Write a value to a register in an TVP7002 decoder device.
+ * Returns zero if successful, or non-zero otherwise.
+ */
+static int tvp7002_write(struct v4l2_subdev *sd, u8 addr, u8 value)
+{
+	struct i2c_client *c;
+	int retry;
+	int error;
+
+	c = v4l2_get_subdevdata(sd);
+
+	for (retry = 0; retry < I2C_RETRY_COUNT; retry++) {
+		error = i2c_smbus_write_byte_data(c, addr, value);
+
+		if (error >= 0)
+			return 0;
+
+		v4l2_warn(sd, "Write: retry ... %d\n", retry);
+		msleep_interruptible(10);
+	}
+	v4l2_err(sd, "TVP7002 write error %d\n", error);
+	return error;
+}
+
+/*
+ * tvp7002_write_err() - Write a register value with error code
+ * @sd: pointer to standard V4L2 sub-device structure
+ * @reg: destination register
+ * @val: value to be written
+ * @err: pointer to error value
+ *
+ * Write a value in a register and save error value in pointer.
+ * Also update the register table if successful
+ */
+static inline void tvp7002_write_err(struct v4l2_subdev *sd, u8 reg,
+							u8 val, int *err)
+{
+	if (!*err)
+		*err = tvp7002_write(sd, reg, val);
+}
+
+/*
+ * tvp7002_g_chip_ident() - Get chip identification number
+ * @sd: ptr to v4l2_subdev struct
+ * @chip: ptr to v4l2_dbg_chip_ident struct
+ *
+ * Obtains the chip's identification number.
+ * Returns zero or -EINVAL if read operation fails.
+ */
+static int tvp7002_g_chip_ident(struct v4l2_subdev *sd,
+					struct v4l2_dbg_chip_ident *chip)
+{
+	u8 rev;
+	int error;
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	error = tvp7002_read(sd, TVP7002_CHIP_REV, &rev);
+
+	if (error < 0)
+		return error;
+
+	return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_TVP7002, rev);
+}
+
+/*
+ * tvp7002_write_inittab() - Write initialization values
+ * @sd: ptr to v4l2_subdev struct
+ * @regs: ptr to i2c_reg_value struct
+ *
+ * Write initialization values.
+ * Returns zero or -EINVAL if read operation fails.
+ */
+static int tvp7002_write_inittab(struct v4l2_subdev *sd,
+					const struct i2c_reg_value *regs)
+{
+	int error = 0;
+
+	/* Initialize the first (defined) registers */
+	while (TVP7002_EOR != regs->reg) {
+		if (TVP7002_WRITE == regs->type)
+			tvp7002_write_err(sd, regs->reg, regs->value, &error);
+		regs++;
+	}
+
+	return error;
+}
+
+/*
+ * tvp7002_s_dv_preset() - Set digital video preset
+ * @sd: ptr to v4l2_subdev struct
+ * @dv_preset: ptr to v4l2_dv_preset struct
+ *
+ * Set the digital video preset for a TVP7002 decoder device.
+ * Returns zero when successful or -EINVAL if register access fails.
+ */
+static int tvp7002_s_dv_preset(struct v4l2_subdev *sd,
+					struct v4l2_dv_preset *dv_preset)
+{
+	struct tvp7002 *device = to_tvp7002(sd);
+	u32 preset;
+	int i;
+
+	for (i = 0; i < NUM_PRESETS; i++) {
+		preset = tvp7002_presets[i].preset;
+		if (preset == dv_preset->preset) {
+			device->current_preset = &tvp7002_presets[i];
+			return tvp7002_write_inittab(sd, tvp7002_presets[i].p_settings);
+		}
+	}
+
+	return -EINVAL;
+}
+
+static int tvp7002_s_dv_timings(struct v4l2_subdev *sd,
+					struct v4l2_dv_timings *dv_timings)
+{
+	struct tvp7002 *device = to_tvp7002(sd);
+	const struct v4l2_bt_timings *bt = &dv_timings->bt;
+	int i;
+
+	if (dv_timings->type != V4L2_DV_BT_656_1120)
+		return -EINVAL;
+	for (i = 0; i < NUM_PRESETS; i++) {
+		const struct v4l2_bt_timings *t = &tvp7002_presets[i].timings.bt;
+
+		if (!memcmp(bt, t, &bt->standards - &bt->width)) {
+			device->current_preset = &tvp7002_presets[i];
+			return tvp7002_write_inittab(sd, tvp7002_presets[i].p_settings);
+		}
+	}
+	return -EINVAL;
+}
+
+static int tvp7002_g_dv_timings(struct v4l2_subdev *sd,
+					struct v4l2_dv_timings *dv_timings)
+{
+	struct tvp7002 *device = to_tvp7002(sd);
+
+	*dv_timings = device->current_preset->timings;
+	return 0;
+}
+
+/*
+ * tvp7002_s_ctrl() - Set a control
+ * @ctrl: ptr to v4l2_ctrl struct
+ *
+ * Set a control in TVP7002 decoder device.
+ * Returns zero when successful or -EINVAL if register access fails.
+ */
+static int tvp7002_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct v4l2_subdev *sd = to_sd(ctrl);
+	int error = 0;
+
+	switch (ctrl->id) {
+	case V4L2_CID_GAIN:
+		tvp7002_write_err(sd, TVP7002_R_FINE_GAIN, ctrl->val, &error);
+		tvp7002_write_err(sd, TVP7002_G_FINE_GAIN, ctrl->val, &error);
+		tvp7002_write_err(sd, TVP7002_B_FINE_GAIN, ctrl->val, &error);
+		return error;
+	}
+	return -EINVAL;
+}
+
+/*
+ * tvp7002_mbus_fmt() - V4L2 decoder interface handler for try/s/g_mbus_fmt
+ * @sd: pointer to standard V4L2 sub-device structure
+ * @f: pointer to mediabus format structure
+ *
+ * Negotiate the image capture size and mediabus format.
+ * There is only one possible format, so this single function works for
+ * get, set and try.
+ */
+static int tvp7002_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *f)
+{
+	struct tvp7002 *device = to_tvp7002(sd);
+	struct v4l2_dv_enum_preset e_preset;
+	int error;
+
+	/* Calculate height and width based on current standard */
+	error = v4l_fill_dv_preset_info(device->current_preset->preset, &e_preset);
+	if (error)
+		return error;
+
+	f->width = e_preset.width;
+	f->height = e_preset.height;
+	f->code = V4L2_MBUS_FMT_YUYV10_1X20;
+	f->field = device->current_preset->scanmode;
+	f->colorspace = device->current_preset->color_space;
+
+	v4l2_dbg(1, debug, sd, "MBUS_FMT: Width - %d, Height - %d",
+			f->width, f->height);
+	return 0;
+}
+
+/*
+ * tvp7002_query_dv_preset() - query DV preset
+ * @sd: pointer to standard V4L2 sub-device structure
+ * @qpreset: standard V4L2 v4l2_dv_preset structure
+ *
+ * Returns the current DV preset by TVP7002. If no active input is
+ * detected, returns -EINVAL
+ */
+static int tvp7002_query_dv(struct v4l2_subdev *sd, int *index)
+{
+	const struct tvp7002_preset_definition *presets = tvp7002_presets;
+	u8 progressive;
+	u32 lpfr;
+	u32 cpln;
+	int error = 0;
+	u8 lpf_lsb;
+	u8 lpf_msb;
+	u8 cpl_lsb;
+	u8 cpl_msb;
+
+	/* Return invalid index if no active input is detected */
+	*index = NUM_PRESETS;
+
+	/* Read standards from device registers */
+	tvp7002_read_err(sd, TVP7002_L_FRAME_STAT_LSBS, &lpf_lsb, &error);
+	tvp7002_read_err(sd, TVP7002_L_FRAME_STAT_MSBS, &lpf_msb, &error);
+
+	if (error < 0)
+		return error;
+
+	tvp7002_read_err(sd, TVP7002_CLK_L_STAT_LSBS, &cpl_lsb, &error);
+	tvp7002_read_err(sd, TVP7002_CLK_L_STAT_MSBS, &cpl_msb, &error);
+
+	if (error < 0)
+		return error;
+
+	/* Get lines per frame, clocks per line and interlaced/progresive */
+	lpfr = lpf_lsb | ((TVP7002_CL_MASK & lpf_msb) << TVP7002_CL_SHIFT);
+	cpln = cpl_lsb | ((TVP7002_CL_MASK & cpl_msb) << TVP7002_CL_SHIFT);
+	progressive = (lpf_msb & TVP7002_INPR_MASK) >> TVP7002_IP_SHIFT;
+
+	/* Do checking of video modes */
+	for (*index = 0; *index < NUM_PRESETS; (*index)++, presets++)
+		if (lpfr == presets->lines_per_frame &&
+			progressive == presets->progressive) {
+			if (presets->cpl_min == 0xffff)
+				break;
+			if (cpln >= presets->cpl_min && cpln <= presets->cpl_max)
+				break;
+		}
+
+	if (*index == NUM_PRESETS) {
+		v4l2_dbg(1, debug, sd, "detection failed: lpf = %x, cpl = %x\n",
+								lpfr, cpln);
+		return -ENOLINK;
+	}
+
+	/* Update lines per frame and clocks per line info */
+	v4l2_dbg(1, debug, sd, "detected preset: %d\n", *index);
+	return 0;
+}
+
+static int tvp7002_query_dv_preset(struct v4l2_subdev *sd,
+					struct v4l2_dv_preset *qpreset)
+{
+	int index;
+	int err = tvp7002_query_dv(sd, &index);
+
+	if (err || index == NUM_PRESETS) {
+		qpreset->preset = V4L2_DV_INVALID;
+		if (err == -ENOLINK)
+			err = 0;
+		return err;
+	}
+	qpreset->preset = tvp7002_presets[index].preset;
+	return 0;
+}
+
+static int tvp7002_query_dv_timings(struct v4l2_subdev *sd,
+					struct v4l2_dv_timings *timings)
+{
+	int index;
+	int err = tvp7002_query_dv(sd, &index);
+
+	if (err)
+		return err;
+	*timings = tvp7002_presets[index].timings;
+	return 0;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+/*
+ * tvp7002_g_register() - Get the value of a register
+ * @sd: ptr to v4l2_subdev struct
+ * @reg: ptr to v4l2_dbg_register struct
+ *
+ * Get the value of a TVP7002 decoder device register.
+ * Returns zero when successful, -EINVAL if register read fails or
+ * access to I2C client fails, -EPERM if the call is not allowed
+ * by disabled CAP_SYS_ADMIN.
+ */
+static int tvp7002_g_register(struct v4l2_subdev *sd,
+						struct v4l2_dbg_register *reg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	u8 val;
+	int ret;
+
+	if (!v4l2_chip_match_i2c_client(client, &reg->match))
+		return -EINVAL;
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	ret = tvp7002_read(sd, reg->reg & 0xff, &val);
+	reg->val = val;
+	return ret;
+}
+
+/*
+ * tvp7002_s_register() - set a control
+ * @sd: ptr to v4l2_subdev struct
+ * @reg: ptr to v4l2_dbg_register struct
+ *
+ * Get the value of a TVP7002 decoder device register.
+ * Returns zero when successful, -EINVAL if register read fails or
+ * -EPERM if call not allowed.
+ */
+static int tvp7002_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;
+
+	return tvp7002_write(sd, reg->reg & 0xff, reg->val & 0xff);
+}
+#endif
+
+/*
+ * tvp7002_enum_mbus_fmt() - Enum supported mediabus formats
+ * @sd: pointer to standard V4L2 sub-device structure
+ * @index: format index
+ * @code: pointer to mediabus format
+ *
+ * Enumerate supported mediabus formats.
+ */
+
+static int tvp7002_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index,
+					enum v4l2_mbus_pixelcode *code)
+{
+	/* Check requested format index is within range */
+	if (index)
+		return -EINVAL;
+	*code = V4L2_MBUS_FMT_YUYV10_1X20;
+	return 0;
+}
+
+/*
+ * tvp7002_s_stream() - V4L2 decoder i/f handler for s_stream
+ * @sd: pointer to standard V4L2 sub-device structure
+ * @enable: streaming enable or disable
+ *
+ * Sets streaming to enable or disable, if possible.
+ */
+static int tvp7002_s_stream(struct v4l2_subdev *sd, int enable)
+{
+	struct tvp7002 *device = to_tvp7002(sd);
+	int error = 0;
+
+	if (device->streaming == enable)
+		return 0;
+
+	if (enable) {
+		/* Set output state on (low impedance means stream on) */
+		error = tvp7002_write(sd, TVP7002_MISC_CTL_2, 0x00);
+		device->streaming = enable;
+	} else {
+		/* Set output state off (high impedance means stream off) */
+		error = tvp7002_write(sd, TVP7002_MISC_CTL_2, 0x03);
+		if (error)
+			v4l2_dbg(1, debug, sd, "Unable to stop streaming\n");
+
+		device->streaming = enable;
+	}
+
+	return error;
+}
+
+/*
+ * tvp7002_log_status() - Print information about register settings
+ * @sd: ptr to v4l2_subdev struct
+ *
+ * Log register values of a TVP7002 decoder device.
+ * Returns zero or -EINVAL if read operation fails.
+ */
+static int tvp7002_log_status(struct v4l2_subdev *sd)
+{
+	const struct tvp7002_preset_definition *presets = tvp7002_presets;
+	struct tvp7002 *device = to_tvp7002(sd);
+	struct v4l2_dv_enum_preset e_preset;
+	struct v4l2_dv_preset detected;
+	int i;
+
+	detected.preset = V4L2_DV_INVALID;
+	/* Find my current standard*/
+	tvp7002_query_dv_preset(sd, &detected);
+
+	/* Print standard related code values */
+	for (i = 0; i < NUM_PRESETS; i++, presets++)
+		if (presets->preset == detected.preset)
+			break;
+
+	if (v4l_fill_dv_preset_info(device->current_preset->preset, &e_preset))
+		return -EINVAL;
+
+	v4l2_info(sd, "Selected DV Preset: %s\n", e_preset.name);
+	v4l2_info(sd, "   Pixels per line: %u\n", e_preset.width);
+	v4l2_info(sd, "   Lines per frame: %u\n\n", e_preset.height);
+	if (i == NUM_PRESETS) {
+		v4l2_info(sd, "Detected DV Preset: None\n");
+	} else {
+		if (v4l_fill_dv_preset_info(presets->preset, &e_preset))
+			return -EINVAL;
+		v4l2_info(sd, "Detected DV Preset: %s\n", e_preset.name);
+		v4l2_info(sd, "  Pixels per line: %u\n", e_preset.width);
+		v4l2_info(sd, "  Lines per frame: %u\n\n", e_preset.height);
+	}
+	v4l2_info(sd, "Streaming enabled: %s\n",
+					device->streaming ? "yes" : "no");
+
+	/* Print the current value of the gain control */
+	v4l2_ctrl_handler_log_status(&device->hdl, sd->name);
+
+	return 0;
+}
+
+/*
+ * tvp7002_enum_dv_presets() - Enum supported digital video formats
+ * @sd: pointer to standard V4L2 sub-device structure
+ * @preset: pointer to format struct
+ *
+ * Enumerate supported digital video formats.
+ */
+static int tvp7002_enum_dv_presets(struct v4l2_subdev *sd,
+		struct v4l2_dv_enum_preset *preset)
+{
+	/* Check requested format index is within range */
+	if (preset->index >= NUM_PRESETS)
+		return -EINVAL;
+
+	return v4l_fill_dv_preset_info(tvp7002_presets[preset->index].preset, preset);
+}
+
+static int tvp7002_enum_dv_timings(struct v4l2_subdev *sd,
+		struct v4l2_enum_dv_timings *timings)
+{
+	/* Check requested format index is within range */
+	if (timings->index >= NUM_PRESETS)
+		return -EINVAL;
+
+	timings->timings = tvp7002_presets[timings->index].timings;
+	return 0;
+}
+
+static const struct v4l2_ctrl_ops tvp7002_ctrl_ops = {
+	.s_ctrl = tvp7002_s_ctrl,
+};
+
+/* V4L2 core operation handlers */
+static const struct v4l2_subdev_core_ops tvp7002_core_ops = {
+	.g_chip_ident = tvp7002_g_chip_ident,
+	.log_status = tvp7002_log_status,
+	.g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
+	.try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
+	.s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
+	.g_ctrl = v4l2_subdev_g_ctrl,
+	.s_ctrl = v4l2_subdev_s_ctrl,
+	.queryctrl = v4l2_subdev_queryctrl,
+	.querymenu = v4l2_subdev_querymenu,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.g_register = tvp7002_g_register,
+	.s_register = tvp7002_s_register,
+#endif
+};
+
+/* Specific video subsystem operation handlers */
+static const struct v4l2_subdev_video_ops tvp7002_video_ops = {
+	.enum_dv_presets = tvp7002_enum_dv_presets,
+	.s_dv_preset = tvp7002_s_dv_preset,
+	.query_dv_preset = tvp7002_query_dv_preset,
+	.g_dv_timings = tvp7002_g_dv_timings,
+	.s_dv_timings = tvp7002_s_dv_timings,
+	.enum_dv_timings = tvp7002_enum_dv_timings,
+	.query_dv_timings = tvp7002_query_dv_timings,
+	.s_stream = tvp7002_s_stream,
+	.g_mbus_fmt = tvp7002_mbus_fmt,
+	.try_mbus_fmt = tvp7002_mbus_fmt,
+	.s_mbus_fmt = tvp7002_mbus_fmt,
+	.enum_mbus_fmt = tvp7002_enum_mbus_fmt,
+};
+
+/* V4L2 top level operation handlers */
+static const struct v4l2_subdev_ops tvp7002_ops = {
+	.core = &tvp7002_core_ops,
+	.video = &tvp7002_video_ops,
+};
+
+/*
+ * tvp7002_probe - Probe a TVP7002 device
+ * @c: ptr to i2c_client struct
+ * @id: ptr to i2c_device_id struct
+ *
+ * Initialize the TVP7002 device
+ * Returns zero when successful, -EINVAL if register read fails or
+ * -EIO if i2c access is not available.
+ */
+static int tvp7002_probe(struct i2c_client *c, const struct i2c_device_id *id)
+{
+	struct v4l2_subdev *sd;
+	struct tvp7002 *device;
+	struct v4l2_dv_preset preset;
+	int polarity_a;
+	int polarity_b;
+	u8 revision;
+
+	int error;
+
+	/* Check if the adapter supports the needed features */
+	if (!i2c_check_functionality(c->adapter,
+		I2C_FUNC_SMBUS_READ_BYTE | I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
+		return -EIO;
+
+	if (!c->dev.platform_data) {
+		v4l_err(c, "No platform data!!\n");
+		return -ENODEV;
+	}
+
+	device = kzalloc(sizeof(struct tvp7002), GFP_KERNEL);
+
+	if (!device)
+		return -ENOMEM;
+
+	sd = &device->sd;
+	device->pdata = c->dev.platform_data;
+	device->current_preset = tvp7002_presets;
+
+	/* Tell v4l2 the device is ready */
+	v4l2_i2c_subdev_init(sd, c, &tvp7002_ops);
+	v4l_info(c, "tvp7002 found @ 0x%02x (%s)\n",
+					c->addr, c->adapter->name);
+
+	error = tvp7002_read(sd, TVP7002_CHIP_REV, &revision);
+	if (error < 0)
+		goto found_error;
+
+	/* Get revision number */
+	v4l2_info(sd, "Rev. %02x detected.\n", revision);
+	if (revision != 0x02)
+		v4l2_info(sd, "Unknown revision detected.\n");
+
+	/* Initializes TVP7002 to its default values */
+	error = tvp7002_write_inittab(sd, tvp7002_init_default);
+
+	if (error < 0)
+		goto found_error;
+
+	/* Set polarity information after registers have been set */
+	polarity_a = 0x20 | device->pdata->hs_polarity << 5
+			| device->pdata->vs_polarity << 2;
+	error = tvp7002_write(sd, TVP7002_SYNC_CTL_1, polarity_a);
+	if (error < 0)
+		goto found_error;
+
+	polarity_b = 0x01  | device->pdata->fid_polarity << 2
+			| device->pdata->sog_polarity << 1
+			| device->pdata->clk_polarity;
+	error = tvp7002_write(sd, TVP7002_MISC_CTL_3, polarity_b);
+	if (error < 0)
+		goto found_error;
+
+	/* Set registers according to default video mode */
+	preset.preset = device->current_preset->preset;
+	error = tvp7002_s_dv_preset(sd, &preset);
+
+	v4l2_ctrl_handler_init(&device->hdl, 1);
+	v4l2_ctrl_new_std(&device->hdl, &tvp7002_ctrl_ops,
+			V4L2_CID_GAIN, 0, 255, 1, 0);
+	sd->ctrl_handler = &device->hdl;
+	if (device->hdl.error) {
+		int err = device->hdl.error;
+
+		v4l2_ctrl_handler_free(&device->hdl);
+		kfree(device);
+		return err;
+	}
+	v4l2_ctrl_handler_setup(&device->hdl);
+
+found_error:
+	if (error < 0)
+		kfree(device);
+
+	return error;
+}
+
+/*
+ * tvp7002_remove - Remove TVP7002 device support
+ * @c: ptr to i2c_client struct
+ *
+ * Reset the TVP7002 device
+ * Returns zero.
+ */
+static int tvp7002_remove(struct i2c_client *c)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(c);
+	struct tvp7002 *device = to_tvp7002(sd);
+
+	v4l2_dbg(1, debug, sd, "Removing tvp7002 adapter"
+				"on address 0x%x\n", c->addr);
+
+	v4l2_device_unregister_subdev(sd);
+	v4l2_ctrl_handler_free(&device->hdl);
+	kfree(device);
+	return 0;
+}
+
+/* I2C Device ID table */
+static const struct i2c_device_id tvp7002_id[] = {
+	{ "tvp7002", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, tvp7002_id);
+
+/* I2C driver data */
+static struct i2c_driver tvp7002_driver = {
+	.driver = {
+		.owner = THIS_MODULE,
+		.name = TVP7002_MODULE_NAME,
+	},
+	.probe = tvp7002_probe,
+	.remove = tvp7002_remove,
+	.id_table = tvp7002_id,
+};
+
+module_i2c_driver(tvp7002_driver);
diff --git a/drivers/media/i2c/tvp7002_reg.h b/drivers/media/i2c/tvp7002_reg.h
new file mode 100644
index 0000000..0e34ca9
--- /dev/null
+++ b/drivers/media/i2c/tvp7002_reg.h
@@ -0,0 +1,150 @@
+/* Texas Instruments Triple 8-/10-BIT 165-/110-MSPS Video and Graphics
+ * Digitizer with Horizontal PLL registers
+ *
+ * Copyright (C) 2009 Texas Instruments Inc
+ * Author: Santiago Nunez-Corrales <santiago.nunez@ridgerun.com>
+ *
+ * This code is partially based upon the TVP5150 driver
+ * written by Mauro Carvalho Chehab (mchehab@infradead.org),
+ * the TVP514x driver written by Vaibhav Hiremath <hvaibhav@ti.com>
+ * and the TVP7002 driver in the TI LSP 2.10.00.14
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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.
+ */
+
+/* Naming conventions
+ * ------------------
+ *
+ * FDBK:  Feedback
+ * DIV:   Divider
+ * CTL:   Control
+ * SEL:   Select
+ * IN:    Input
+ * OUT:   Output
+ * R:     Red
+ * G:     Green
+ * B:     Blue
+ * OFF:   Offset
+ * THRS:  Threshold
+ * DGTL:  Digital
+ * LVL:   Level
+ * PWR:   Power
+ * MVIS:  Macrovision
+ * W:     Width
+ * H:     Height
+ * ALGN:  Alignment
+ * CLK:   Clocks
+ * TOL:   Tolerance
+ * BWTH:  Bandwidth
+ * COEF:  Coefficient
+ * STAT:  Status
+ * AUTO:  Automatic
+ * FLD:   Field
+ * L:	  Line
+ */
+
+#define TVP7002_CHIP_REV		0x00
+#define TVP7002_HPLL_FDBK_DIV_MSBS	0x01
+#define TVP7002_HPLL_FDBK_DIV_LSBS	0x02
+#define TVP7002_HPLL_CRTL		0x03
+#define TVP7002_HPLL_PHASE_SEL		0x04
+#define TVP7002_CLAMP_START		0x05
+#define TVP7002_CLAMP_W			0x06
+#define TVP7002_HSYNC_OUT_W		0x07
+#define TVP7002_B_FINE_GAIN		0x08
+#define TVP7002_G_FINE_GAIN		0x09
+#define TVP7002_R_FINE_GAIN		0x0a
+#define TVP7002_B_FINE_OFF_MSBS		0x0b
+#define TVP7002_G_FINE_OFF_MSBS         0x0c
+#define TVP7002_R_FINE_OFF_MSBS         0x0d
+#define TVP7002_SYNC_CTL_1		0x0e
+#define TVP7002_HPLL_AND_CLAMP_CTL	0x0f
+#define TVP7002_SYNC_ON_G_THRS		0x10
+#define TVP7002_SYNC_SEPARATOR_THRS	0x11
+#define TVP7002_HPLL_PRE_COAST		0x12
+#define TVP7002_HPLL_POST_COAST		0x13
+#define TVP7002_SYNC_DETECT_STAT	0x14
+#define TVP7002_OUT_FORMATTER		0x15
+#define TVP7002_MISC_CTL_1		0x16
+#define TVP7002_MISC_CTL_2              0x17
+#define TVP7002_MISC_CTL_3              0x18
+#define TVP7002_IN_MUX_SEL_1		0x19
+#define TVP7002_IN_MUX_SEL_2            0x1a
+#define TVP7002_B_AND_G_COARSE_GAIN	0x1b
+#define TVP7002_R_COARSE_GAIN		0x1c
+#define TVP7002_FINE_OFF_LSBS		0x1d
+#define TVP7002_B_COARSE_OFF		0x1e
+#define TVP7002_G_COARSE_OFF            0x1f
+#define TVP7002_R_COARSE_OFF            0x20
+#define TVP7002_HSOUT_OUT_START		0x21
+#define TVP7002_MISC_CTL_4		0x22
+#define TVP7002_B_DGTL_ALC_OUT_LSBS	0x23
+#define TVP7002_G_DGTL_ALC_OUT_LSBS     0x24
+#define TVP7002_R_DGTL_ALC_OUT_LSBS     0x25
+#define TVP7002_AUTO_LVL_CTL_ENABLE	0x26
+#define TVP7002_DGTL_ALC_OUT_MSBS	0x27
+#define TVP7002_AUTO_LVL_CTL_FILTER	0x28
+/* Reserved 0x29*/
+#define TVP7002_FINE_CLAMP_CTL		0x2a
+#define TVP7002_PWR_CTL			0x2b
+#define TVP7002_ADC_SETUP		0x2c
+#define TVP7002_COARSE_CLAMP_CTL	0x2d
+#define TVP7002_SOG_CLAMP		0x2e
+#define TVP7002_RGB_COARSE_CLAMP_CTL	0x2f
+#define TVP7002_SOG_COARSE_CLAMP_CTL	0x30
+#define TVP7002_ALC_PLACEMENT		0x31
+/* Reserved 0x32 */
+/* Reserved 0x33 */
+#define TVP7002_MVIS_STRIPPER_W		0x34
+#define TVP7002_VSYNC_ALGN		0x35
+#define TVP7002_SYNC_BYPASS		0x36
+#define TVP7002_L_FRAME_STAT_LSBS	0x37
+#define TVP7002_L_FRAME_STAT_MSBS	0x38
+#define TVP7002_CLK_L_STAT_LSBS		0x39
+#define TVP7002_CLK_L_STAT_MSBS      	0x3a
+#define TVP7002_HSYNC_W			0x3b
+#define TVP7002_VSYNC_W                 0x3c
+#define TVP7002_L_LENGTH_TOL 		0x3d
+/* Reserved 0x3e */
+#define TVP7002_VIDEO_BWTH_CTL		0x3f
+#define TVP7002_AVID_START_PIXEL_LSBS	0x40
+#define TVP7002_AVID_START_PIXEL_MSBS   0x41
+#define TVP7002_AVID_STOP_PIXEL_LSBS  	0x42
+#define TVP7002_AVID_STOP_PIXEL_MSBS    0x43
+#define TVP7002_VBLK_F_0_START_L_OFF	0x44
+#define TVP7002_VBLK_F_1_START_L_OFF    0x45
+#define TVP7002_VBLK_F_0_DURATION	0x46
+#define TVP7002_VBLK_F_1_DURATION       0x47
+#define TVP7002_FBIT_F_0_START_L_OFF	0x48
+#define TVP7002_FBIT_F_1_START_L_OFF    0x49
+#define TVP7002_YUV_Y_G_COEF_LSBS	0x4a
+#define TVP7002_YUV_Y_G_COEF_MSBS       0x4b
+#define TVP7002_YUV_Y_B_COEF_LSBS       0x4c
+#define TVP7002_YUV_Y_B_COEF_MSBS       0x4d
+#define TVP7002_YUV_Y_R_COEF_LSBS       0x4e
+#define TVP7002_YUV_Y_R_COEF_MSBS       0x4f
+#define TVP7002_YUV_U_G_COEF_LSBS       0x50
+#define TVP7002_YUV_U_G_COEF_MSBS       0x51
+#define TVP7002_YUV_U_B_COEF_LSBS       0x52
+#define TVP7002_YUV_U_B_COEF_MSBS       0x53
+#define TVP7002_YUV_U_R_COEF_LSBS       0x54
+#define TVP7002_YUV_U_R_COEF_MSBS       0x55
+#define TVP7002_YUV_V_G_COEF_LSBS       0x56
+#define TVP7002_YUV_V_G_COEF_MSBS       0x57
+#define TVP7002_YUV_V_B_COEF_LSBS       0x58
+#define TVP7002_YUV_V_B_COEF_MSBS       0x59
+#define TVP7002_YUV_V_R_COEF_LSBS       0x5a
+#define TVP7002_YUV_V_R_COEF_MSBS       0x5b
+
diff --git a/drivers/media/i2c/upd64031a.c b/drivers/media/i2c/upd64031a.c
new file mode 100644
index 0000000..1e74465
--- /dev/null
+++ b/drivers/media/i2c/upd64031a.c
@@ -0,0 +1,274 @@
+/*
+ * upd64031A - NEC Electronics Ghost Reduction for NTSC in Japan
+ *
+ * 2003 by T.Adachi <tadachi@tadachi-net.com>
+ * 2003 by Takeru KOMORIYA <komoriya@paken.org>
+ * 2006 by 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.
+ */
+
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+#include <linux/videodev2.h>
+#include <linux/slab.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/upd64031a.h>
+
+/* --------------------- read registers functions define -------------------- */
+
+/* bit masks */
+#define GR_MODE_MASK              0xc0
+#define DIRECT_3DYCS_CONNECT_MASK 0xc0
+#define SYNC_CIRCUIT_MASK         0xa0
+
+/* -------------------------------------------------------------------------- */
+
+MODULE_DESCRIPTION("uPD64031A driver");
+MODULE_AUTHOR("T. Adachi, Takeru KOMORIYA, Hans Verkuil");
+MODULE_LICENSE("GPL");
+
+static int debug;
+module_param(debug, int, 0644);
+
+MODULE_PARM_DESC(debug, "Debug level (0-1)");
+
+
+enum {
+	R00 = 0, R01, R02, R03, R04,
+	R05, R06, R07, R08, R09,
+	R0A, R0B, R0C, R0D, R0E, R0F,
+	/* unused registers
+	 R10, R11, R12, R13, R14,
+	 R15, R16, R17,
+	 */
+	TOT_REGS
+};
+
+struct upd64031a_state {
+	struct v4l2_subdev sd;
+	u8 regs[TOT_REGS];
+	u8 gr_mode;
+	u8 direct_3dycs_connect;
+	u8 ext_comp_sync;
+	u8 ext_vert_sync;
+};
+
+static inline struct upd64031a_state *to_state(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct upd64031a_state, sd);
+}
+
+static u8 upd64031a_init[] = {
+	0x00, 0xb8, 0x48, 0xd2, 0xe6,
+	0x03, 0x10, 0x0b, 0xaf, 0x7f,
+	0x00, 0x00, 0x1d, 0x5e, 0x00,
+	0xd0
+};
+
+/* ------------------------------------------------------------------------ */
+
+static u8 upd64031a_read(struct v4l2_subdev *sd, u8 reg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	u8 buf[2];
+
+	if (reg >= sizeof(buf))
+		return 0xff;
+	i2c_master_recv(client, buf, 2);
+	return buf[reg];
+}
+
+/* ------------------------------------------------------------------------ */
+
+static void upd64031a_write(struct v4l2_subdev *sd, u8 reg, u8 val)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	u8 buf[2];
+
+	buf[0] = reg;
+	buf[1] = val;
+	v4l2_dbg(1, debug, sd, "write reg: %02X val: %02X\n", reg, val);
+	if (i2c_master_send(client, buf, 2) != 2)
+		v4l2_err(sd, "I/O error write 0x%02x/0x%02x\n", reg, val);
+}
+
+/* ------------------------------------------------------------------------ */
+
+/* The input changed due to new input or channel changed */
+static int upd64031a_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *freq)
+{
+	struct upd64031a_state *state = to_state(sd);
+	u8 reg = state->regs[R00];
+
+	v4l2_dbg(1, debug, sd, "changed input or channel\n");
+	upd64031a_write(sd, R00, reg | 0x10);
+	upd64031a_write(sd, R00, reg & ~0x10);
+	return 0;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int upd64031a_s_routing(struct v4l2_subdev *sd,
+			       u32 input, u32 output, u32 config)
+{
+	struct upd64031a_state *state = to_state(sd);
+	u8 r00, r05, r08;
+
+	state->gr_mode = (input & 3) << 6;
+	state->direct_3dycs_connect = (input & 0xc) << 4;
+	state->ext_comp_sync =
+		(input & UPD64031A_COMPOSITE_EXTERNAL) << 1;
+	state->ext_vert_sync =
+		(input & UPD64031A_VERTICAL_EXTERNAL) << 2;
+	r00 = (state->regs[R00] & ~GR_MODE_MASK) | state->gr_mode;
+	r05 = (state->regs[R00] & ~SYNC_CIRCUIT_MASK) |
+		state->ext_comp_sync | state->ext_vert_sync;
+	r08 = (state->regs[R08] & ~DIRECT_3DYCS_CONNECT_MASK) |
+		state->direct_3dycs_connect;
+	upd64031a_write(sd, R00, r00);
+	upd64031a_write(sd, R05, r05);
+	upd64031a_write(sd, R08, r08);
+	return upd64031a_s_frequency(sd, NULL);
+}
+
+static int upd64031a_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_UPD64031A, 0);
+}
+
+static int upd64031a_log_status(struct v4l2_subdev *sd)
+{
+	v4l2_info(sd, "Status: SA00=0x%02x SA01=0x%02x\n",
+			upd64031a_read(sd, 0), upd64031a_read(sd, 1));
+	return 0;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int upd64031a_g_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;
+	reg->val = upd64031a_read(sd, reg->reg & 0xff);
+	reg->size = 1;
+	return 0;
+}
+
+static int upd64031a_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;
+	upd64031a_write(sd, reg->reg & 0xff, reg->val & 0xff);
+	return 0;
+}
+#endif
+
+/* ----------------------------------------------------------------------- */
+
+static const struct v4l2_subdev_core_ops upd64031a_core_ops = {
+	.log_status = upd64031a_log_status,
+	.g_chip_ident = upd64031a_g_chip_ident,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.g_register = upd64031a_g_register,
+	.s_register = upd64031a_s_register,
+#endif
+};
+
+static const struct v4l2_subdev_tuner_ops upd64031a_tuner_ops = {
+	.s_frequency = upd64031a_s_frequency,
+};
+
+static const struct v4l2_subdev_video_ops upd64031a_video_ops = {
+	.s_routing = upd64031a_s_routing,
+};
+
+static const struct v4l2_subdev_ops upd64031a_ops = {
+	.core = &upd64031a_core_ops,
+	.tuner = &upd64031a_tuner_ops,
+	.video = &upd64031a_video_ops,
+};
+
+/* ------------------------------------------------------------------------ */
+
+/* i2c implementation */
+
+static int upd64031a_probe(struct i2c_client *client,
+			   const struct i2c_device_id *id)
+{
+	struct upd64031a_state *state;
+	struct v4l2_subdev *sd;
+	int i;
+
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		return -EIO;
+
+	v4l_info(client, "chip found @ 0x%x (%s)\n",
+			client->addr << 1, client->adapter->name);
+
+	state = kzalloc(sizeof(struct upd64031a_state), GFP_KERNEL);
+	if (state == NULL)
+		return -ENOMEM;
+	sd = &state->sd;
+	v4l2_i2c_subdev_init(sd, client, &upd64031a_ops);
+	memcpy(state->regs, upd64031a_init, sizeof(state->regs));
+	state->gr_mode = UPD64031A_GR_ON << 6;
+	state->direct_3dycs_connect = UPD64031A_3DYCS_COMPOSITE << 4;
+	state->ext_comp_sync = state->ext_vert_sync = 0;
+	for (i = 0; i < TOT_REGS; i++)
+		upd64031a_write(sd, i, state->regs[i]);
+	return 0;
+}
+
+static int upd64031a_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+
+	v4l2_device_unregister_subdev(sd);
+	kfree(to_state(sd));
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static const struct i2c_device_id upd64031a_id[] = {
+	{ "upd64031a", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, upd64031a_id);
+
+static struct i2c_driver upd64031a_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "upd64031a",
+	},
+	.probe		= upd64031a_probe,
+	.remove		= upd64031a_remove,
+	.id_table	= upd64031a_id,
+};
+
+module_i2c_driver(upd64031a_driver);
diff --git a/drivers/media/i2c/upd64083.c b/drivers/media/i2c/upd64083.c
new file mode 100644
index 0000000..75d6acc
--- /dev/null
+++ b/drivers/media/i2c/upd64083.c
@@ -0,0 +1,246 @@
+/*
+ * upd6408x - NEC Electronics 3-Dimensional Y/C separation driver
+ *
+ * 2003 by T.Adachi (tadachi@tadachi-net.com)
+ * 2003 by Takeru KOMORIYA <komoriya@paken.org>
+ * 2006 by 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+#include <linux/videodev2.h>
+#include <linux/slab.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/upd64083.h>
+
+MODULE_DESCRIPTION("uPD64083 driver");
+MODULE_AUTHOR("T. Adachi, Takeru KOMORIYA, Hans Verkuil");
+MODULE_LICENSE("GPL");
+
+static bool debug;
+module_param(debug, bool, 0644);
+
+MODULE_PARM_DESC(debug, "Debug level (0-1)");
+
+
+enum {
+	R00 = 0, R01, R02, R03, R04,
+	R05, R06, R07, R08, R09,
+	R0A, R0B, R0C, R0D, R0E, R0F,
+	R10, R11, R12, R13, R14,
+	R15, R16,
+	TOT_REGS
+};
+
+struct upd64083_state {
+	struct v4l2_subdev sd;
+	u8 mode;
+	u8 ext_y_adc;
+	u8 regs[TOT_REGS];
+};
+
+static inline struct upd64083_state *to_state(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct upd64083_state, sd);
+}
+
+/* Initial values when used in combination with the
+   NEC upd64031a ghost reduction chip. */
+static u8 upd64083_init[] = {
+	0x1f, 0x01, 0xa0, 0x2d, 0x29,  /* we use EXCSS=0 */
+	0x36, 0xdd, 0x05, 0x56, 0x48,
+	0x00, 0x3a, 0xa0, 0x05, 0x08,
+	0x44, 0x60, 0x08, 0x52, 0xf8,
+	0x53, 0x60, 0x10
+};
+
+/* ------------------------------------------------------------------------ */
+
+static void upd64083_write(struct v4l2_subdev *sd, u8 reg, u8 val)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	u8 buf[2];
+
+	buf[0] = reg;
+	buf[1] = val;
+	v4l2_dbg(1, debug, sd, "write reg: %02x val: %02x\n", reg, val);
+	if (i2c_master_send(client, buf, 2) != 2)
+		v4l2_err(sd, "I/O error write 0x%02x/0x%02x\n", reg, val);
+}
+
+/* ------------------------------------------------------------------------ */
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static u8 upd64083_read(struct v4l2_subdev *sd, u8 reg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	u8 buf[7];
+
+	if (reg >= sizeof(buf))
+		return 0xff;
+	i2c_master_recv(client, buf, sizeof(buf));
+	return buf[reg];
+}
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+static int upd64083_s_routing(struct v4l2_subdev *sd,
+			      u32 input, u32 output, u32 config)
+{
+	struct upd64083_state *state = to_state(sd);
+	u8 r00, r02;
+
+	if (input > 7 || (input & 6) == 6)
+		return -EINVAL;
+	state->mode = (input & 3) << 6;
+	state->ext_y_adc = (input & UPD64083_EXT_Y_ADC) << 3;
+	r00 = (state->regs[R00] & ~(3 << 6)) | state->mode;
+	r02 = (state->regs[R02] & ~(1 << 5)) | state->ext_y_adc;
+	upd64083_write(sd, R00, r00);
+	upd64083_write(sd, R02, r02);
+	return 0;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int upd64083_g_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;
+	reg->val = upd64083_read(sd, reg->reg & 0xff);
+	reg->size = 1;
+	return 0;
+}
+
+static int upd64083_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;
+	upd64083_write(sd, reg->reg & 0xff, reg->val & 0xff);
+	return 0;
+}
+#endif
+
+static int upd64083_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_UPD64083, 0);
+}
+
+static int upd64083_log_status(struct v4l2_subdev *sd)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	u8 buf[7];
+
+	i2c_master_recv(client, buf, 7);
+	v4l2_info(sd, "Status: SA00=%02x SA01=%02x SA02=%02x SA03=%02x "
+		      "SA04=%02x SA05=%02x SA06=%02x\n",
+		buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static const struct v4l2_subdev_core_ops upd64083_core_ops = {
+	.log_status = upd64083_log_status,
+	.g_chip_ident = upd64083_g_chip_ident,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.g_register = upd64083_g_register,
+	.s_register = upd64083_s_register,
+#endif
+};
+
+static const struct v4l2_subdev_video_ops upd64083_video_ops = {
+	.s_routing = upd64083_s_routing,
+};
+
+static const struct v4l2_subdev_ops upd64083_ops = {
+	.core = &upd64083_core_ops,
+	.video = &upd64083_video_ops,
+};
+
+/* ------------------------------------------------------------------------ */
+
+/* i2c implementation */
+
+static int upd64083_probe(struct i2c_client *client,
+			  const struct i2c_device_id *id)
+{
+	struct upd64083_state *state;
+	struct v4l2_subdev *sd;
+	int i;
+
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		return -EIO;
+
+	v4l_info(client, "chip found @ 0x%x (%s)\n",
+			client->addr << 1, client->adapter->name);
+
+	state = kzalloc(sizeof(struct upd64083_state), GFP_KERNEL);
+	if (state == NULL)
+		return -ENOMEM;
+	sd = &state->sd;
+	v4l2_i2c_subdev_init(sd, client, &upd64083_ops);
+	/* Initially assume that a ghost reduction chip is present */
+	state->mode = 0;  /* YCS mode */
+	state->ext_y_adc = (1 << 5);
+	memcpy(state->regs, upd64083_init, TOT_REGS);
+	for (i = 0; i < TOT_REGS; i++)
+		upd64083_write(sd, i, state->regs[i]);
+	return 0;
+}
+
+static int upd64083_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+
+	v4l2_device_unregister_subdev(sd);
+	kfree(to_state(sd));
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static const struct i2c_device_id upd64083_id[] = {
+	{ "upd64083", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, upd64083_id);
+
+static struct i2c_driver upd64083_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "upd64083",
+	},
+	.probe		= upd64083_probe,
+	.remove		= upd64083_remove,
+	.id_table	= upd64083_id,
+};
+
+module_i2c_driver(upd64083_driver);
diff --git a/drivers/media/i2c/vp27smpx.c b/drivers/media/i2c/vp27smpx.c
new file mode 100644
index 0000000..7cfbc9d
--- /dev/null
+++ b/drivers/media/i2c/vp27smpx.c
@@ -0,0 +1,211 @@
+/*
+ * vp27smpx - driver version 0.0.1
+ *
+ * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ * Based on a tvaudio patch from Takahiro Adachi <tadachi@tadachi-net.com>
+ * and Kazuhiko Kawakami <kazz-0@mail.goo.ne.jp>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/slab.h>
+#include <linux/ioctl.h>
+#include <asm/uaccess.h>
+#include <linux/i2c.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-chip-ident.h>
+
+MODULE_DESCRIPTION("vp27smpx driver");
+MODULE_AUTHOR("Hans Verkuil");
+MODULE_LICENSE("GPL");
+
+
+/* ----------------------------------------------------------------------- */
+
+struct vp27smpx_state {
+	struct v4l2_subdev sd;
+	int radio;
+	u32 audmode;
+};
+
+static inline struct vp27smpx_state *to_state(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct vp27smpx_state, sd);
+}
+
+static void vp27smpx_set_audmode(struct v4l2_subdev *sd, u32 audmode)
+{
+	struct vp27smpx_state *state = to_state(sd);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	u8 data[3] = { 0x00, 0x00, 0x04 };
+
+	switch (audmode) {
+	case V4L2_TUNER_MODE_MONO:
+	case V4L2_TUNER_MODE_LANG1:
+		break;
+	case V4L2_TUNER_MODE_STEREO:
+	case V4L2_TUNER_MODE_LANG1_LANG2:
+		data[1] = 0x01;
+		break;
+	case V4L2_TUNER_MODE_LANG2:
+		data[1] = 0x02;
+		break;
+	}
+
+	if (i2c_master_send(client, data, sizeof(data)) != sizeof(data))
+		v4l2_err(sd, "I/O error setting audmode\n");
+	else
+		state->audmode = audmode;
+}
+
+static int vp27smpx_s_radio(struct v4l2_subdev *sd)
+{
+	struct vp27smpx_state *state = to_state(sd);
+
+	state->radio = 1;
+	return 0;
+}
+
+static int vp27smpx_s_std(struct v4l2_subdev *sd, v4l2_std_id norm)
+{
+	struct vp27smpx_state *state = to_state(sd);
+
+	state->radio = 0;
+	return 0;
+}
+
+static int vp27smpx_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
+{
+	struct vp27smpx_state *state = to_state(sd);
+
+	if (!state->radio)
+		vp27smpx_set_audmode(sd, vt->audmode);
+	return 0;
+}
+
+static int vp27smpx_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
+{
+	struct vp27smpx_state *state = to_state(sd);
+
+	if (state->radio)
+		return 0;
+	vt->audmode = state->audmode;
+	vt->capability = V4L2_TUNER_CAP_STEREO |
+		V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2;
+	vt->rxsubchans = V4L2_TUNER_SUB_MONO;
+	return 0;
+}
+
+static int vp27smpx_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_VP27SMPX, 0);
+}
+
+static int vp27smpx_log_status(struct v4l2_subdev *sd)
+{
+	struct vp27smpx_state *state = to_state(sd);
+
+	v4l2_info(sd, "Audio Mode: %u%s\n", state->audmode,
+			state->radio ? " (Radio)" : "");
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static const struct v4l2_subdev_core_ops vp27smpx_core_ops = {
+	.log_status = vp27smpx_log_status,
+	.g_chip_ident = vp27smpx_g_chip_ident,
+	.s_std = vp27smpx_s_std,
+};
+
+static const struct v4l2_subdev_tuner_ops vp27smpx_tuner_ops = {
+	.s_radio = vp27smpx_s_radio,
+	.s_tuner = vp27smpx_s_tuner,
+	.g_tuner = vp27smpx_g_tuner,
+};
+
+static const struct v4l2_subdev_ops vp27smpx_ops = {
+	.core = &vp27smpx_core_ops,
+	.tuner = &vp27smpx_tuner_ops,
+};
+
+/* ----------------------------------------------------------------------- */
+
+/* i2c implementation */
+
+/*
+ * Generic i2c probe
+ * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
+ */
+
+static int vp27smpx_probe(struct i2c_client *client,
+			  const struct i2c_device_id *id)
+{
+	struct vp27smpx_state *state;
+	struct v4l2_subdev *sd;
+
+	/* Check if the adapter supports the needed features */
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		return -EIO;
+
+	v4l_info(client, "chip found @ 0x%x (%s)\n",
+			client->addr << 1, client->adapter->name);
+
+	state = kzalloc(sizeof(struct vp27smpx_state), GFP_KERNEL);
+	if (state == NULL)
+		return -ENOMEM;
+	sd = &state->sd;
+	v4l2_i2c_subdev_init(sd, client, &vp27smpx_ops);
+	state->audmode = V4L2_TUNER_MODE_STEREO;
+
+	/* initialize vp27smpx */
+	vp27smpx_set_audmode(sd, state->audmode);
+	return 0;
+}
+
+static int vp27smpx_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+
+	v4l2_device_unregister_subdev(sd);
+	kfree(to_state(sd));
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static const struct i2c_device_id vp27smpx_id[] = {
+	{ "vp27smpx", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, vp27smpx_id);
+
+static struct i2c_driver vp27smpx_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "vp27smpx",
+	},
+	.probe		= vp27smpx_probe,
+	.remove		= vp27smpx_remove,
+	.id_table	= vp27smpx_id,
+};
+
+module_i2c_driver(vp27smpx_driver);
diff --git a/drivers/media/i2c/vpx3220.c b/drivers/media/i2c/vpx3220.c
new file mode 100644
index 0000000..2f67b4c
--- /dev/null
+++ b/drivers/media/i2c/vpx3220.c
@@ -0,0 +1,591 @@
+/*
+ * vpx3220a, vpx3216b & vpx3214c video decoder driver version 0.0.1
+ *
+ * Copyright (C) 2001 Laurent Pinchart <lpinchart@freegates.be>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/init.h>
+#include <linux/delay.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <asm/uaccess.h>
+#include <linux/i2c.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-ctrls.h>
+
+MODULE_DESCRIPTION("vpx3220a/vpx3216b/vpx3214c video decoder driver");
+MODULE_AUTHOR("Laurent Pinchart");
+MODULE_LICENSE("GPL");
+
+static int debug;
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "Debug level (0-1)");
+
+
+#define VPX_TIMEOUT_COUNT  10
+
+/* ----------------------------------------------------------------------- */
+
+struct vpx3220 {
+	struct v4l2_subdev sd;
+	struct v4l2_ctrl_handler hdl;
+	unsigned char reg[255];
+
+	v4l2_std_id norm;
+	int ident;
+	int input;
+	int enable;
+};
+
+static inline struct vpx3220 *to_vpx3220(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct vpx3220, sd);
+}
+
+static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
+{
+	return &container_of(ctrl->handler, struct vpx3220, hdl)->sd;
+}
+
+static char *inputs[] = { "internal", "composite", "svideo" };
+
+/* ----------------------------------------------------------------------- */
+
+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 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 v4l2_subdev *sd)
+{
+	unsigned char status;
+	unsigned int i;
+
+	for (i = 0; i < VPX_TIMEOUT_COUNT; i++) {
+		status = vpx3220_read(sd, 0x29);
+
+		if (!(status & 4))
+			return 0;
+
+		udelay(10);
+
+		if (need_resched())
+			cond_resched();
+	}
+
+	return -1;
+}
+
+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) {
+		v4l2_dbg(1, debug, sd, "%s: failed\n", __func__);
+		return -1;
+	}
+
+	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) {
+		v4l2_dbg(1, debug, sd, "%s: failed\n", __func__);
+		return -1;
+	}
+
+	return 0;
+}
+
+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) {
+		v4l2_dbg(1, debug, sd, "%s: failed\n", __func__);
+		return -1;
+	}
+
+	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) {
+		v4l2_dbg(1, debug, sd, "%s: failed\n", __func__);
+		return -1;
+	}
+
+	return swab16(data);
+}
+
+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(sd, reg, *data++);
+		if (ret < 0)
+			break;
+		len -= 2;
+	}
+
+	return ret;
+}
+
+static int vpx3220_write_fp_block(struct v4l2_subdev *sd,
+		const u16 *data, unsigned int len)
+{
+	u8 reg;
+	int ret = 0;
+
+	while (len > 1) {
+		reg = *data++;
+		ret |= vpx3220_fp_write(sd, reg, *data++);
+		len -= 2;
+	}
+
+	return ret;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static const unsigned short init_ntsc[] = {
+	0x1c, 0x00,		/* NTSC tint angle */
+	0x88, 17,		/* Window 1 vertical */
+	0x89, 240,		/* Vertical lines in */
+	0x8a, 240,		/* Vertical lines out */
+	0x8b, 000,		/* Horizontal begin */
+	0x8c, 640,		/* Horizontal length */
+	0x8d, 640,		/* Number of pixels */
+	0x8f, 0xc00,		/* Disable window 2 */
+	0xf0, 0x73,		/* 13.5 MHz transport, Forced
+				 * mode, latch windows */
+	0xf2, 0x13,		/* NTSC M, composite input */
+	0xe7, 0x1e1,		/* Enable vertical standard
+				 * locking @ 240 lines */
+};
+
+static const unsigned short init_pal[] = {
+	0x88, 23,		/* Window 1 vertical begin */
+	0x89, 288,		/* Vertical lines in (16 lines
+				 * skipped by the VFE) */
+	0x8a, 288,		/* Vertical lines out (16 lines
+				 * skipped by the VFE) */
+	0x8b, 16,		/* Horizontal begin */
+	0x8c, 768,		/* Horizontal length */
+	0x8d, 784, 		/* Number of pixels
+				 * Must be >= Horizontal begin + Horizontal length */
+	0x8f, 0xc00,		/* Disable window 2 */
+	0xf0, 0x77,		/* 13.5 MHz transport, Forced
+				 * mode, latch windows */
+	0xf2, 0x3d1,		/* PAL B,G,H,I, composite input */
+	0xe7, 0x241,		/* PAL/SECAM set to 288 lines */
+};
+
+static const unsigned short init_secam[] = {
+	0x88, 23,		/* Window 1 vertical begin */
+	0x89, 288,		/* Vertical lines in (16 lines
+				 * skipped by the VFE) */
+	0x8a, 288,		/* Vertical lines out (16 lines
+				 * skipped by the VFE) */
+	0x8b, 16,		/* Horizontal begin */
+	0x8c, 768,		/* Horizontal length */
+	0x8d, 784,		/* Number of pixels
+				 * Must be >= Horizontal begin + Horizontal length */
+	0x8f, 0xc00,		/* Disable window 2 */
+	0xf0, 0x77,		/* 13.5 MHz transport, Forced
+				 * mode, latch windows */
+	0xf2, 0x3d5,		/* SECAM, composite input */
+	0xe7, 0x241,		/* PAL/SECAM set to 288 lines */
+};
+
+static const unsigned char init_common[] = {
+	0xf2, 0x00,		/* Disable all outputs */
+	0x33, 0x0d,		/* Luma : VIN2, Chroma : CIN
+				 * (clamp off) */
+	0xd8, 0xa8,		/* HREF/VREF active high, VREF
+				 * pulse = 2, Odd/Even flag */
+	0x20, 0x03,		/* IF compensation 0dB/oct */
+	0xe0, 0xff,		/* Open up all comparators */
+	0xe1, 0x00,
+	0xe2, 0x7f,
+	0xe3, 0x80,
+	0xe4, 0x7f,
+	0xe5, 0x80,
+	0xe6, 0x00,		/* Brightness set to 0 */
+	0xe7, 0xe0,		/* Contrast to 1.0, noise shaping
+				 * 10 to 8 2-bit error diffusion */
+	0xe8, 0xf8,		/* YUV422, CbCr binary offset,
+				 * ... (p.32) */
+	0xea, 0x18,		/* LLC2 connected, output FIFO
+				 * reset with VACTintern */
+	0xf0, 0x8a,		/* Half full level to 10, bus
+				 * shuffler [7:0, 23:16, 15:8] */
+	0xf1, 0x18,		/* Single clock, sync mode, no
+				 * FE delay, no HLEN counter */
+	0xf8, 0x12,		/* Port A, PIXCLK, HF# & FE#
+				 * strength to 2 */
+	0xf9, 0x24,		/* Port B, HREF, VREF, PREF &
+				 * ALPHA strength to 4 */
+};
+
+static const unsigned short init_fp[] = {
+	0x59, 0,
+	0xa0, 2070,		/* ACC reference */
+	0xa3, 0,
+	0xa4, 0,
+	0xa8, 30,
+	0xb2, 768,
+	0xbe, 27,
+	0x58, 0,
+	0x26, 0,
+	0x4b, 0x298,		/* PLL gain */
+};
+
+
+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_status(struct v4l2_subdev *sd, u32 *pstatus, v4l2_std_id *pstd)
+{
+	int res = V4L2_IN_ST_NO_SIGNAL, status;
+	v4l2_std_id std = 0;
+
+	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 0x08:
+			std = V4L2_STD_SECAM;
+			break;
+
+		case 0x04:
+		case 0x0c:
+		case 0x1c:
+			std = V4L2_STD_NTSC;
+			break;
+		}
+	}
+	if (pstd)
+		*pstd = std;
+	if (pstatus)
+		*pstatus = res;
+	return 0;
+}
+
+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
+	   chosen 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;
+	}
+
+	decoder->norm = std;
+
+	/* And here we set the backed up video input again */
+	vpx3220_fp_write(sd, 0xf2, temp_input | 0x0010);
+	udelay(10);
+	return 0;
+}
+
+static int vpx3220_s_routing(struct v4l2_subdev *sd,
+			     u32 input, u32 output, u32 config)
+{
+	int data;
+
+	/* RJ:   input = 0: ST8 (PCTV) input
+		 input = 1: COMPOSITE  input
+		 input = 2: SVHS       input  */
+
+	const int input_vals[3][2] = {
+		{0x0c, 0},
+		{0x0d, 0},
+		{0x0e, 1}
+	};
+
+	if (input > 2)
+		return -EINVAL;
+
+	v4l2_dbg(1, debug, sd, "input switched to %s\n", inputs[input]);
+
+	vpx3220_write(sd, 0x33, input_vals[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_vals[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_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct v4l2_subdev *sd = to_sd(ctrl);
+
+	switch (ctrl->id) {
+	case V4L2_CID_BRIGHTNESS:
+		vpx3220_write(sd, 0xe6, ctrl->val);
+		return 0;
+	case V4L2_CID_CONTRAST:
+		/* Bit 7 and 8 is for noise shaping */
+		vpx3220_write(sd, 0xe7, ctrl->val + 192);
+		return 0;
+	case V4L2_CID_SATURATION:
+		vpx3220_fp_write(sd, 0xa0, ctrl->val);
+		return 0;
+	case V4L2_CID_HUE:
+		vpx3220_fp_write(sd, 0x1c, ctrl->val);
+		return 0;
+	}
+	return -EINVAL;
+}
+
+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_ctrl_ops vpx3220_ctrl_ops = {
+	.s_ctrl = vpx3220_s_ctrl,
+};
+
+static const struct v4l2_subdev_core_ops vpx3220_core_ops = {
+	.g_chip_ident = vpx3220_g_chip_ident,
+	.init = vpx3220_init,
+	.g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
+	.try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
+	.s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
+	.g_ctrl = v4l2_subdev_g_ctrl,
+	.s_ctrl = v4l2_subdev_s_ctrl,
+	.queryctrl = v4l2_subdev_queryctrl,
+	.querymenu = v4l2_subdev_querymenu,
+	.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,
+	.video = &vpx3220_video_ops,
+};
+
+/* -----------------------------------------------------------------------
+ * Client management code
+ */
+
+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;
+
+	/* Check if the adapter supports the needed features */
+	if (!i2c_check_functionality(client->adapter,
+		I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA))
+		return -ENODEV;
+
+	decoder = kzalloc(sizeof(struct vpx3220), GFP_KERNEL);
+	if (decoder == NULL)
+		return -ENOMEM;
+	sd = &decoder->sd;
+	v4l2_i2c_subdev_init(sd, client, &vpx3220_ops);
+	decoder->norm = V4L2_STD_PAL;
+	decoder->input = 0;
+	decoder->enable = 1;
+	v4l2_ctrl_handler_init(&decoder->hdl, 4);
+	v4l2_ctrl_new_std(&decoder->hdl, &vpx3220_ctrl_ops,
+		V4L2_CID_BRIGHTNESS, -128, 127, 1, 0);
+	v4l2_ctrl_new_std(&decoder->hdl, &vpx3220_ctrl_ops,
+		V4L2_CID_CONTRAST, 0, 63, 1, 32);
+	v4l2_ctrl_new_std(&decoder->hdl, &vpx3220_ctrl_ops,
+		V4L2_CID_SATURATION, 0, 4095, 1, 2048);
+	v4l2_ctrl_new_std(&decoder->hdl, &vpx3220_ctrl_ops,
+		V4L2_CID_HUE, -512, 511, 1, 0);
+	sd->ctrl_handler = &decoder->hdl;
+	if (decoder->hdl.error) {
+		int err = decoder->hdl.error;
+
+		v4l2_ctrl_handler_free(&decoder->hdl);
+		kfree(decoder);
+		return err;
+	}
+	v4l2_ctrl_handler_setup(&decoder->hdl);
+
+	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:
+			name = "vpx3220a";
+			break;
+		case 0x4260:
+			name = "vpx3216b";
+			decoder->ident = V4L2_IDENT_VPX3216B;
+			break;
+		case 0x4280:
+			name = "vpx3214c";
+			decoder->ident = V4L2_IDENT_VPX3214C;
+			break;
+		}
+	}
+	if (name)
+		v4l2_info(sd, "%s found @ 0x%x (%s)\n", name,
+			client->addr << 1, client->adapter->name);
+	else
+		v4l2_info(sd, "chip (%02x:%04x) found @ 0x%x (%s)\n",
+			ver, pn, client->addr << 1, client->adapter->name);
+
+	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)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct vpx3220 *decoder = to_vpx3220(sd);
+
+	v4l2_device_unregister_subdev(sd);
+	v4l2_ctrl_handler_free(&decoder->hdl);
+	kfree(decoder);
+	return 0;
+}
+
+static const struct i2c_device_id vpx3220_id[] = {
+	{ "vpx3220a", 0 },
+	{ "vpx3216b", 0 },
+	{ "vpx3214c", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, vpx3220_id);
+
+static struct i2c_driver vpx3220_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "vpx3220",
+	},
+	.probe		= vpx3220_probe,
+	.remove		= vpx3220_remove,
+	.id_table	= vpx3220_id,
+};
+
+module_i2c_driver(vpx3220_driver);
diff --git a/drivers/media/i2c/vs6624.c b/drivers/media/i2c/vs6624.c
new file mode 100644
index 0000000..42ae9dc
--- /dev/null
+++ b/drivers/media/i2c/vs6624.c
@@ -0,0 +1,928 @@
+/*
+ * vs6624.c ST VS6624 CMOS image sensor driver
+ *
+ * Copyright (c) 2011 Analog Devices Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/videodev2.h>
+
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-mediabus.h>
+
+#include "vs6624_regs.h"
+
+#define VGA_WIDTH       640
+#define VGA_HEIGHT      480
+#define QVGA_WIDTH      320
+#define QVGA_HEIGHT     240
+#define QQVGA_WIDTH     160
+#define QQVGA_HEIGHT    120
+#define CIF_WIDTH       352
+#define CIF_HEIGHT      288
+#define QCIF_WIDTH      176
+#define QCIF_HEIGHT     144
+#define QQCIF_WIDTH     88
+#define QQCIF_HEIGHT    72
+
+#define MAX_FRAME_RATE  30
+
+struct vs6624 {
+	struct v4l2_subdev sd;
+	struct v4l2_ctrl_handler hdl;
+	struct v4l2_fract frame_rate;
+	struct v4l2_mbus_framefmt fmt;
+	unsigned ce_pin;
+};
+
+static const struct vs6624_format {
+	enum v4l2_mbus_pixelcode mbus_code;
+	enum v4l2_colorspace colorspace;
+} vs6624_formats[] = {
+	{
+		.mbus_code      = V4L2_MBUS_FMT_UYVY8_2X8,
+		.colorspace     = V4L2_COLORSPACE_JPEG,
+	},
+	{
+		.mbus_code      = V4L2_MBUS_FMT_YUYV8_2X8,
+		.colorspace     = V4L2_COLORSPACE_JPEG,
+	},
+	{
+		.mbus_code      = V4L2_MBUS_FMT_RGB565_2X8_LE,
+		.colorspace     = V4L2_COLORSPACE_SRGB,
+	},
+};
+
+static struct v4l2_mbus_framefmt vs6624_default_fmt = {
+	.width = VGA_WIDTH,
+	.height = VGA_HEIGHT,
+	.code = V4L2_MBUS_FMT_UYVY8_2X8,
+	.field = V4L2_FIELD_NONE,
+	.colorspace = V4L2_COLORSPACE_JPEG,
+};
+
+static const u16 vs6624_p1[] = {
+	0x8104, 0x03,
+	0x8105, 0x01,
+	0xc900, 0x03,
+	0xc904, 0x47,
+	0xc905, 0x10,
+	0xc906, 0x80,
+	0xc907, 0x3a,
+	0x903a, 0x02,
+	0x903b, 0x47,
+	0x903c, 0x15,
+	0xc908, 0x31,
+	0xc909, 0xdc,
+	0xc90a, 0x80,
+	0xc90b, 0x44,
+	0x9044, 0x02,
+	0x9045, 0x31,
+	0x9046, 0xe2,
+	0xc90c, 0x07,
+	0xc90d, 0xe0,
+	0xc90e, 0x80,
+	0xc90f, 0x47,
+	0x9047, 0x90,
+	0x9048, 0x83,
+	0x9049, 0x81,
+	0x904a, 0xe0,
+	0x904b, 0x60,
+	0x904c, 0x08,
+	0x904d, 0x90,
+	0x904e, 0xc0,
+	0x904f, 0x43,
+	0x9050, 0x74,
+	0x9051, 0x01,
+	0x9052, 0xf0,
+	0x9053, 0x80,
+	0x9054, 0x05,
+	0x9055, 0xE4,
+	0x9056, 0x90,
+	0x9057, 0xc0,
+	0x9058, 0x43,
+	0x9059, 0xf0,
+	0x905a, 0x02,
+	0x905b, 0x07,
+	0x905c, 0xec,
+	0xc910, 0x5d,
+	0xc911, 0xca,
+	0xc912, 0x80,
+	0xc913, 0x5d,
+	0x905d, 0xa3,
+	0x905e, 0x04,
+	0x905f, 0xf0,
+	0x9060, 0xa3,
+	0x9061, 0x04,
+	0x9062, 0xf0,
+	0x9063, 0x22,
+	0xc914, 0x72,
+	0xc915, 0x92,
+	0xc916, 0x80,
+	0xc917, 0x64,
+	0x9064, 0x74,
+	0x9065, 0x01,
+	0x9066, 0x02,
+	0x9067, 0x72,
+	0x9068, 0x95,
+	0xc918, 0x47,
+	0xc919, 0xf2,
+	0xc91a, 0x81,
+	0xc91b, 0x69,
+	0x9169, 0x74,
+	0x916a, 0x02,
+	0x916b, 0xf0,
+	0x916c, 0xec,
+	0x916d, 0xb4,
+	0x916e, 0x10,
+	0x916f, 0x0a,
+	0x9170, 0x90,
+	0x9171, 0x80,
+	0x9172, 0x16,
+	0x9173, 0xe0,
+	0x9174, 0x70,
+	0x9175, 0x04,
+	0x9176, 0x90,
+	0x9177, 0xd3,
+	0x9178, 0xc4,
+	0x9179, 0xf0,
+	0x917a, 0x22,
+	0xc91c, 0x0a,
+	0xc91d, 0xbe,
+	0xc91e, 0x80,
+	0xc91f, 0x73,
+	0x9073, 0xfc,
+	0x9074, 0xa3,
+	0x9075, 0xe0,
+	0x9076, 0xf5,
+	0x9077, 0x82,
+	0x9078, 0x8c,
+	0x9079, 0x83,
+	0x907a, 0xa3,
+	0x907b, 0xa3,
+	0x907c, 0xe0,
+	0x907d, 0xfc,
+	0x907e, 0xa3,
+	0x907f, 0xe0,
+	0x9080, 0xc3,
+	0x9081, 0x9f,
+	0x9082, 0xff,
+	0x9083, 0xec,
+	0x9084, 0x9e,
+	0x9085, 0xfe,
+	0x9086, 0x02,
+	0x9087, 0x0a,
+	0x9088, 0xea,
+	0xc920, 0x47,
+	0xc921, 0x38,
+	0xc922, 0x80,
+	0xc923, 0x89,
+	0x9089, 0xec,
+	0x908a, 0xd3,
+	0x908b, 0x94,
+	0x908c, 0x20,
+	0x908d, 0x40,
+	0x908e, 0x01,
+	0x908f, 0x1c,
+	0x9090, 0x90,
+	0x9091, 0xd3,
+	0x9092, 0xd4,
+	0x9093, 0xec,
+	0x9094, 0xf0,
+	0x9095, 0x02,
+	0x9096, 0x47,
+	0x9097, 0x3d,
+	0xc924, 0x45,
+	0xc925, 0xca,
+	0xc926, 0x80,
+	0xc927, 0x98,
+	0x9098, 0x12,
+	0x9099, 0x77,
+	0x909a, 0xd6,
+	0x909b, 0x02,
+	0x909c, 0x45,
+	0x909d, 0xcd,
+	0xc928, 0x20,
+	0xc929, 0xd5,
+	0xc92a, 0x80,
+	0xc92b, 0x9e,
+	0x909e, 0x90,
+	0x909f, 0x82,
+	0x90a0, 0x18,
+	0x90a1, 0xe0,
+	0x90a2, 0xb4,
+	0x90a3, 0x03,
+	0x90a4, 0x0e,
+	0x90a5, 0x90,
+	0x90a6, 0x83,
+	0x90a7, 0xbf,
+	0x90a8, 0xe0,
+	0x90a9, 0x60,
+	0x90aa, 0x08,
+	0x90ab, 0x90,
+	0x90ac, 0x81,
+	0x90ad, 0xfc,
+	0x90ae, 0xe0,
+	0x90af, 0xff,
+	0x90b0, 0xc3,
+	0x90b1, 0x13,
+	0x90b2, 0xf0,
+	0x90b3, 0x90,
+	0x90b4, 0x81,
+	0x90b5, 0xfc,
+	0x90b6, 0xe0,
+	0x90b7, 0xff,
+	0x90b8, 0x02,
+	0x90b9, 0x20,
+	0x90ba, 0xda,
+	0xc92c, 0x70,
+	0xc92d, 0xbc,
+	0xc92e, 0x80,
+	0xc92f, 0xbb,
+	0x90bb, 0x90,
+	0x90bc, 0x82,
+	0x90bd, 0x18,
+	0x90be, 0xe0,
+	0x90bf, 0xb4,
+	0x90c0, 0x03,
+	0x90c1, 0x06,
+	0x90c2, 0x90,
+	0x90c3, 0xc1,
+	0x90c4, 0x06,
+	0x90c5, 0x74,
+	0x90c6, 0x05,
+	0x90c7, 0xf0,
+	0x90c8, 0x90,
+	0x90c9, 0xd3,
+	0x90ca, 0xa0,
+	0x90cb, 0x02,
+	0x90cc, 0x70,
+	0x90cd, 0xbf,
+	0xc930, 0x72,
+	0xc931, 0x21,
+	0xc932, 0x81,
+	0xc933, 0x3b,
+	0x913b, 0x7d,
+	0x913c, 0x02,
+	0x913d, 0x7f,
+	0x913e, 0x7b,
+	0x913f, 0x02,
+	0x9140, 0x72,
+	0x9141, 0x25,
+	0xc934, 0x28,
+	0xc935, 0xae,
+	0xc936, 0x80,
+	0xc937, 0xd2,
+	0x90d2, 0xf0,
+	0x90d3, 0x90,
+	0x90d4, 0xd2,
+	0x90d5, 0x0a,
+	0x90d6, 0x02,
+	0x90d7, 0x28,
+	0x90d8, 0xb4,
+	0xc938, 0x28,
+	0xc939, 0xb1,
+	0xc93a, 0x80,
+	0xc93b, 0xd9,
+	0x90d9, 0x90,
+	0x90da, 0x83,
+	0x90db, 0xba,
+	0x90dc, 0xe0,
+	0x90dd, 0xff,
+	0x90de, 0x90,
+	0x90df, 0xd2,
+	0x90e0, 0x08,
+	0x90e1, 0xe0,
+	0x90e2, 0xe4,
+	0x90e3, 0xef,
+	0x90e4, 0xf0,
+	0x90e5, 0xa3,
+	0x90e6, 0xe0,
+	0x90e7, 0x74,
+	0x90e8, 0xff,
+	0x90e9, 0xf0,
+	0x90ea, 0x90,
+	0x90eb, 0xd2,
+	0x90ec, 0x0a,
+	0x90ed, 0x02,
+	0x90ee, 0x28,
+	0x90ef, 0xb4,
+	0xc93c, 0x29,
+	0xc93d, 0x79,
+	0xc93e, 0x80,
+	0xc93f, 0xf0,
+	0x90f0, 0xf0,
+	0x90f1, 0x90,
+	0x90f2, 0xd2,
+	0x90f3, 0x0e,
+	0x90f4, 0x02,
+	0x90f5, 0x29,
+	0x90f6, 0x7f,
+	0xc940, 0x29,
+	0xc941, 0x7c,
+	0xc942, 0x80,
+	0xc943, 0xf7,
+	0x90f7, 0x90,
+	0x90f8, 0x83,
+	0x90f9, 0xba,
+	0x90fa, 0xe0,
+	0x90fb, 0xff,
+	0x90fc, 0x90,
+	0x90fd, 0xd2,
+	0x90fe, 0x0c,
+	0x90ff, 0xe0,
+	0x9100, 0xe4,
+	0x9101, 0xef,
+	0x9102, 0xf0,
+	0x9103, 0xa3,
+	0x9104, 0xe0,
+	0x9105, 0x74,
+	0x9106, 0xff,
+	0x9107, 0xf0,
+	0x9108, 0x90,
+	0x9109, 0xd2,
+	0x910a, 0x0e,
+	0x910b, 0x02,
+	0x910c, 0x29,
+	0x910d, 0x7f,
+	0xc944, 0x2a,
+	0xc945, 0x42,
+	0xc946, 0x81,
+	0xc947, 0x0e,
+	0x910e, 0xf0,
+	0x910f, 0x90,
+	0x9110, 0xd2,
+	0x9111, 0x12,
+	0x9112, 0x02,
+	0x9113, 0x2a,
+	0x9114, 0x48,
+	0xc948, 0x2a,
+	0xc949, 0x45,
+	0xc94a, 0x81,
+	0xc94b, 0x15,
+	0x9115, 0x90,
+	0x9116, 0x83,
+	0x9117, 0xba,
+	0x9118, 0xe0,
+	0x9119, 0xff,
+	0x911a, 0x90,
+	0x911b, 0xd2,
+	0x911c, 0x10,
+	0x911d, 0xe0,
+	0x911e, 0xe4,
+	0x911f, 0xef,
+	0x9120, 0xf0,
+	0x9121, 0xa3,
+	0x9122, 0xe0,
+	0x9123, 0x74,
+	0x9124, 0xff,
+	0x9125, 0xf0,
+	0x9126, 0x90,
+	0x9127, 0xd2,
+	0x9128, 0x12,
+	0x9129, 0x02,
+	0x912a, 0x2a,
+	0x912b, 0x48,
+	0xc900, 0x01,
+	0x0000, 0x00,
+};
+
+static const u16 vs6624_p2[] = {
+	0x806f, 0x01,
+	0x058c, 0x01,
+	0x0000, 0x00,
+};
+
+static const u16 vs6624_run_setup[] = {
+	0x1d18, 0x00,				/* Enableconstrainedwhitebalance */
+	VS6624_PEAK_MIN_OUT_G_MSB, 0x3c,	/* Damper PeakGain Output MSB */
+	VS6624_PEAK_MIN_OUT_G_LSB, 0x66,	/* Damper PeakGain Output LSB */
+	VS6624_CM_LOW_THR_MSB, 0x65,		/* Damper Low MSB */
+	VS6624_CM_LOW_THR_LSB, 0xd1,		/* Damper Low LSB */
+	VS6624_CM_HIGH_THR_MSB, 0x66,		/* Damper High MSB */
+	VS6624_CM_HIGH_THR_LSB, 0x62,		/* Damper High LSB */
+	VS6624_CM_MIN_OUT_MSB, 0x00,		/* Damper Min output MSB */
+	VS6624_CM_MIN_OUT_LSB, 0x00,		/* Damper Min output LSB */
+	VS6624_NORA_DISABLE, 0x00,		/* Nora fDisable */
+	VS6624_NORA_USAGE, 0x04,		/* Nora usage */
+	VS6624_NORA_LOW_THR_MSB, 0x63,		/* Damper Low MSB Changed 0x63 to 0x65 */
+	VS6624_NORA_LOW_THR_LSB, 0xd1,		/* Damper Low LSB */
+	VS6624_NORA_HIGH_THR_MSB, 0x68,		/* Damper High MSB */
+	VS6624_NORA_HIGH_THR_LSB, 0xdd,		/* Damper High LSB */
+	VS6624_NORA_MIN_OUT_MSB, 0x3a,		/* Damper Min output MSB */
+	VS6624_NORA_MIN_OUT_LSB, 0x00,		/* Damper Min output LSB */
+	VS6624_F2B_DISABLE, 0x00,		/* Disable */
+	0x1d8a, 0x30,				/* MAXWeightHigh */
+	0x1d91, 0x62,				/* fpDamperLowThresholdHigh MSB */
+	0x1d92, 0x4a,				/* fpDamperLowThresholdHigh LSB */
+	0x1d95, 0x65,				/* fpDamperHighThresholdHigh MSB */
+	0x1d96, 0x0e,				/* fpDamperHighThresholdHigh LSB */
+	0x1da1, 0x3a,				/* fpMinimumDamperOutputLow MSB */
+	0x1da2, 0xb8,				/* fpMinimumDamperOutputLow LSB */
+	0x1e08, 0x06,				/* MAXWeightLow */
+	0x1e0a, 0x0a,				/* MAXWeightHigh */
+	0x1601, 0x3a,				/* Red A MSB */
+	0x1602, 0x14,				/* Red A LSB */
+	0x1605, 0x3b,				/* Blue A MSB */
+	0x1606, 0x85,				/* BLue A LSB */
+	0x1609, 0x3b,				/* RED B MSB */
+	0x160a, 0x85,				/* RED B LSB */
+	0x160d, 0x3a,				/* Blue B MSB */
+	0x160e, 0x14,				/* Blue B LSB */
+	0x1611, 0x30,				/* Max Distance from Locus MSB */
+	0x1612, 0x8f,				/* Max Distance from Locus MSB */
+	0x1614, 0x01,				/* Enable constrainer */
+	0x0000, 0x00,
+};
+
+static const u16 vs6624_default[] = {
+	VS6624_CONTRAST0, 0x84,
+	VS6624_SATURATION0, 0x75,
+	VS6624_GAMMA0, 0x11,
+	VS6624_CONTRAST1, 0x84,
+	VS6624_SATURATION1, 0x75,
+	VS6624_GAMMA1, 0x11,
+	VS6624_MAN_RG, 0x80,
+	VS6624_MAN_GG, 0x80,
+	VS6624_MAN_BG, 0x80,
+	VS6624_WB_MODE, 0x1,
+	VS6624_EXPO_COMPENSATION, 0xfe,
+	VS6624_EXPO_METER, 0x0,
+	VS6624_LIGHT_FREQ, 0x64,
+	VS6624_PEAK_GAIN, 0xe,
+	VS6624_PEAK_LOW_THR, 0x28,
+	VS6624_HMIRROR0, 0x0,
+	VS6624_VFLIP0, 0x0,
+	VS6624_ZOOM_HSTEP0_MSB, 0x0,
+	VS6624_ZOOM_HSTEP0_LSB, 0x1,
+	VS6624_ZOOM_VSTEP0_MSB, 0x0,
+	VS6624_ZOOM_VSTEP0_LSB, 0x1,
+	VS6624_PAN_HSTEP0_MSB, 0x0,
+	VS6624_PAN_HSTEP0_LSB, 0xf,
+	VS6624_PAN_VSTEP0_MSB, 0x0,
+	VS6624_PAN_VSTEP0_LSB, 0xf,
+	VS6624_SENSOR_MODE, 0x1,
+	VS6624_SYNC_CODE_SETUP, 0x21,
+	VS6624_DISABLE_FR_DAMPER, 0x0,
+	VS6624_FR_DEN, 0x1,
+	VS6624_FR_NUM_LSB, 0xf,
+	VS6624_INIT_PIPE_SETUP, 0x0,
+	VS6624_IMG_FMT0, 0x0,
+	VS6624_YUV_SETUP, 0x1,
+	VS6624_IMAGE_SIZE0, 0x2,
+	0x0000, 0x00,
+};
+
+static inline struct vs6624 *to_vs6624(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct vs6624, sd);
+}
+static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
+{
+	return &container_of(ctrl->handler, struct vs6624, hdl)->sd;
+}
+
+static int vs6624_read(struct v4l2_subdev *sd, u16 index)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	u8 buf[2];
+
+	buf[0] = index >> 8;
+	buf[1] = index;
+	i2c_master_send(client, buf, 2);
+	i2c_master_recv(client, buf, 1);
+
+	return buf[0];
+}
+
+static int vs6624_write(struct v4l2_subdev *sd, u16 index,
+				u8 value)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	u8 buf[3];
+
+	buf[0] = index >> 8;
+	buf[1] = index;
+	buf[2] = value;
+
+	return i2c_master_send(client, buf, 3);
+}
+
+static int vs6624_writeregs(struct v4l2_subdev *sd, const u16 *regs)
+{
+	u16 reg;
+	u8 data;
+
+	while (*regs != 0x00) {
+		reg = *regs++;
+		data = *regs++;
+
+		vs6624_write(sd, reg, data);
+	}
+	return 0;
+}
+
+static int vs6624_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct v4l2_subdev *sd = to_sd(ctrl);
+
+	switch (ctrl->id) {
+	case V4L2_CID_CONTRAST:
+		vs6624_write(sd, VS6624_CONTRAST0, ctrl->val);
+		break;
+	case V4L2_CID_SATURATION:
+		vs6624_write(sd, VS6624_SATURATION0, ctrl->val);
+		break;
+	case V4L2_CID_HFLIP:
+		vs6624_write(sd, VS6624_HMIRROR0, ctrl->val);
+		break;
+	case V4L2_CID_VFLIP:
+		vs6624_write(sd, VS6624_VFLIP0, ctrl->val);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int vs6624_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index,
+				enum v4l2_mbus_pixelcode *code)
+{
+	if (index >= ARRAY_SIZE(vs6624_formats))
+		return -EINVAL;
+
+	*code = vs6624_formats[index].mbus_code;
+	return 0;
+}
+
+static int vs6624_try_mbus_fmt(struct v4l2_subdev *sd,
+				struct v4l2_mbus_framefmt *fmt)
+{
+	int index;
+
+	for (index = 0; index < ARRAY_SIZE(vs6624_formats); index++)
+		if (vs6624_formats[index].mbus_code == fmt->code)
+			break;
+	if (index >= ARRAY_SIZE(vs6624_formats)) {
+		/* default to first format */
+		index = 0;
+		fmt->code = vs6624_formats[0].mbus_code;
+	}
+
+	/* sensor mode is VGA */
+	if (fmt->width > VGA_WIDTH)
+		fmt->width = VGA_WIDTH;
+	if (fmt->height > VGA_HEIGHT)
+		fmt->height = VGA_HEIGHT;
+	fmt->width = fmt->width & (~3);
+	fmt->height = fmt->height & (~3);
+	fmt->field = V4L2_FIELD_NONE;
+	fmt->colorspace = vs6624_formats[index].colorspace;
+	return 0;
+}
+
+static int vs6624_s_mbus_fmt(struct v4l2_subdev *sd,
+				struct v4l2_mbus_framefmt *fmt)
+{
+	struct vs6624 *sensor = to_vs6624(sd);
+	int ret;
+
+	ret = vs6624_try_mbus_fmt(sd, fmt);
+	if (ret)
+		return ret;
+
+	/* set image format */
+	switch (fmt->code) {
+	case V4L2_MBUS_FMT_UYVY8_2X8:
+		vs6624_write(sd, VS6624_IMG_FMT0, 0x0);
+		vs6624_write(sd, VS6624_YUV_SETUP, 0x1);
+		break;
+	case V4L2_MBUS_FMT_YUYV8_2X8:
+		vs6624_write(sd, VS6624_IMG_FMT0, 0x0);
+		vs6624_write(sd, VS6624_YUV_SETUP, 0x3);
+		break;
+	case V4L2_MBUS_FMT_RGB565_2X8_LE:
+		vs6624_write(sd, VS6624_IMG_FMT0, 0x4);
+		vs6624_write(sd, VS6624_RGB_SETUP, 0x0);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* set image size */
+	if ((fmt->width == VGA_WIDTH) && (fmt->height == VGA_HEIGHT))
+		vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x2);
+	else if ((fmt->width == QVGA_WIDTH) && (fmt->height == QVGA_HEIGHT))
+		vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x4);
+	else if ((fmt->width == QQVGA_WIDTH) && (fmt->height == QQVGA_HEIGHT))
+		vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x6);
+	else if ((fmt->width == CIF_WIDTH) && (fmt->height == CIF_HEIGHT))
+		vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x3);
+	else if ((fmt->width == QCIF_WIDTH) && (fmt->height == QCIF_HEIGHT))
+		vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x5);
+	else if ((fmt->width == QQCIF_WIDTH) && (fmt->height == QQCIF_HEIGHT))
+		vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x7);
+	else {
+		vs6624_write(sd, VS6624_IMAGE_SIZE0, 0x8);
+		vs6624_write(sd, VS6624_MAN_HSIZE0_MSB, fmt->width >> 8);
+		vs6624_write(sd, VS6624_MAN_HSIZE0_LSB, fmt->width & 0xFF);
+		vs6624_write(sd, VS6624_MAN_VSIZE0_MSB, fmt->height >> 8);
+		vs6624_write(sd, VS6624_MAN_VSIZE0_LSB, fmt->height & 0xFF);
+		vs6624_write(sd, VS6624_CROP_CTRL0, 0x1);
+	}
+
+	sensor->fmt = *fmt;
+
+	return 0;
+}
+
+static int vs6624_g_mbus_fmt(struct v4l2_subdev *sd,
+				struct v4l2_mbus_framefmt *fmt)
+{
+	struct vs6624 *sensor = to_vs6624(sd);
+
+	*fmt = sensor->fmt;
+	return 0;
+}
+
+static int vs6624_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms)
+{
+	struct vs6624 *sensor = to_vs6624(sd);
+	struct v4l2_captureparm *cp = &parms->parm.capture;
+
+	if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
+	memset(cp, 0, sizeof(*cp));
+	cp->capability = V4L2_CAP_TIMEPERFRAME;
+	cp->timeperframe.numerator = sensor->frame_rate.denominator;
+	cp->timeperframe.denominator = sensor->frame_rate.numerator;
+	return 0;
+}
+
+static int vs6624_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms)
+{
+	struct vs6624 *sensor = to_vs6624(sd);
+	struct v4l2_captureparm *cp = &parms->parm.capture;
+	struct v4l2_fract *tpf = &cp->timeperframe;
+
+	if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+	if (cp->extendedmode != 0)
+		return -EINVAL;
+
+	if (tpf->numerator == 0 || tpf->denominator == 0
+		|| (tpf->denominator > tpf->numerator * MAX_FRAME_RATE)) {
+		/* reset to max frame rate */
+		tpf->numerator = 1;
+		tpf->denominator = MAX_FRAME_RATE;
+	}
+	sensor->frame_rate.numerator = tpf->denominator;
+	sensor->frame_rate.denominator = tpf->numerator;
+	vs6624_write(sd, VS6624_DISABLE_FR_DAMPER, 0x0);
+	vs6624_write(sd, VS6624_FR_NUM_MSB,
+			sensor->frame_rate.numerator >> 8);
+	vs6624_write(sd, VS6624_FR_NUM_LSB,
+			sensor->frame_rate.numerator & 0xFF);
+	vs6624_write(sd, VS6624_FR_DEN,
+			sensor->frame_rate.denominator & 0xFF);
+	return 0;
+}
+
+static int vs6624_s_stream(struct v4l2_subdev *sd, int enable)
+{
+	if (enable)
+		vs6624_write(sd, VS6624_USER_CMD, 0x2);
+	else
+		vs6624_write(sd, VS6624_USER_CMD, 0x4);
+	udelay(100);
+	return 0;
+}
+
+static int vs6624_g_chip_ident(struct v4l2_subdev *sd,
+		struct v4l2_dbg_chip_ident *chip)
+{
+	int rev;
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	rev = (vs6624_read(sd, VS6624_FW_VSN_MAJOR) << 8)
+		| vs6624_read(sd, VS6624_FW_VSN_MINOR);
+
+	return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_VS6624, rev);
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int vs6624_g_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;
+	reg->val = vs6624_read(sd, reg->reg & 0xffff);
+	reg->size = 1;
+	return 0;
+}
+
+static int vs6624_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;
+	vs6624_write(sd, reg->reg & 0xffff, reg->val & 0xff);
+	return 0;
+}
+#endif
+
+static const struct v4l2_ctrl_ops vs6624_ctrl_ops = {
+	.s_ctrl = vs6624_s_ctrl,
+};
+
+static const struct v4l2_subdev_core_ops vs6624_core_ops = {
+	.g_chip_ident = vs6624_g_chip_ident,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.g_register = vs6624_g_register,
+	.s_register = vs6624_s_register,
+#endif
+};
+
+static const struct v4l2_subdev_video_ops vs6624_video_ops = {
+	.enum_mbus_fmt = vs6624_enum_mbus_fmt,
+	.try_mbus_fmt = vs6624_try_mbus_fmt,
+	.s_mbus_fmt = vs6624_s_mbus_fmt,
+	.g_mbus_fmt = vs6624_g_mbus_fmt,
+	.s_parm = vs6624_s_parm,
+	.g_parm = vs6624_g_parm,
+	.s_stream = vs6624_s_stream,
+};
+
+static const struct v4l2_subdev_ops vs6624_ops = {
+	.core = &vs6624_core_ops,
+	.video = &vs6624_video_ops,
+};
+
+static int __devinit vs6624_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	struct vs6624 *sensor;
+	struct v4l2_subdev *sd;
+	struct v4l2_ctrl_handler *hdl;
+	const unsigned *ce;
+	int ret;
+
+	/* Check if the adapter supports the needed features */
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
+		return -EIO;
+
+	ce = client->dev.platform_data;
+	if (ce == NULL)
+		return -EINVAL;
+
+	ret = gpio_request(*ce, "VS6624 Chip Enable");
+	if (ret) {
+		v4l_err(client, "failed to request GPIO %d\n", *ce);
+		return ret;
+	}
+	gpio_direction_output(*ce, 1);
+	/* wait 100ms before any further i2c writes are performed */
+	mdelay(100);
+
+	sensor = kzalloc(sizeof(*sensor), GFP_KERNEL);
+	if (sensor == NULL) {
+		gpio_free(*ce);
+		return -ENOMEM;
+	}
+
+	sd = &sensor->sd;
+	v4l2_i2c_subdev_init(sd, client, &vs6624_ops);
+
+	vs6624_writeregs(sd, vs6624_p1);
+	vs6624_write(sd, VS6624_MICRO_EN, 0x2);
+	vs6624_write(sd, VS6624_DIO_EN, 0x1);
+	mdelay(10);
+	vs6624_writeregs(sd, vs6624_p2);
+
+	vs6624_writeregs(sd, vs6624_default);
+	vs6624_write(sd, VS6624_HSYNC_SETUP, 0xF);
+	vs6624_writeregs(sd, vs6624_run_setup);
+
+	/* set frame rate */
+	sensor->frame_rate.numerator = MAX_FRAME_RATE;
+	sensor->frame_rate.denominator = 1;
+	vs6624_write(sd, VS6624_DISABLE_FR_DAMPER, 0x0);
+	vs6624_write(sd, VS6624_FR_NUM_MSB,
+			sensor->frame_rate.numerator >> 8);
+	vs6624_write(sd, VS6624_FR_NUM_LSB,
+			sensor->frame_rate.numerator & 0xFF);
+	vs6624_write(sd, VS6624_FR_DEN,
+			sensor->frame_rate.denominator & 0xFF);
+
+	sensor->fmt = vs6624_default_fmt;
+	sensor->ce_pin = *ce;
+
+	v4l_info(client, "chip found @ 0x%02x (%s)\n",
+			client->addr << 1, client->adapter->name);
+
+	hdl = &sensor->hdl;
+	v4l2_ctrl_handler_init(hdl, 4);
+	v4l2_ctrl_new_std(hdl, &vs6624_ctrl_ops,
+			V4L2_CID_CONTRAST, 0, 0xFF, 1, 0x87);
+	v4l2_ctrl_new_std(hdl, &vs6624_ctrl_ops,
+			V4L2_CID_SATURATION, 0, 0xFF, 1, 0x78);
+	v4l2_ctrl_new_std(hdl, &vs6624_ctrl_ops,
+			V4L2_CID_HFLIP, 0, 1, 1, 0);
+	v4l2_ctrl_new_std(hdl, &vs6624_ctrl_ops,
+			V4L2_CID_VFLIP, 0, 1, 1, 0);
+	/* hook the control handler into the driver */
+	sd->ctrl_handler = hdl;
+	if (hdl->error) {
+		int err = hdl->error;
+
+		v4l2_ctrl_handler_free(hdl);
+		kfree(sensor);
+		gpio_free(*ce);
+		return err;
+	}
+
+	/* initialize the hardware to the default control values */
+	ret = v4l2_ctrl_handler_setup(hdl);
+	if (ret) {
+		v4l2_ctrl_handler_free(hdl);
+		kfree(sensor);
+		gpio_free(*ce);
+	}
+	return ret;
+}
+
+static int __devexit vs6624_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct vs6624 *sensor = to_vs6624(sd);
+
+	v4l2_device_unregister_subdev(sd);
+	v4l2_ctrl_handler_free(sd->ctrl_handler);
+	gpio_free(sensor->ce_pin);
+	kfree(sensor);
+	return 0;
+}
+
+static const struct i2c_device_id vs6624_id[] = {
+	{"vs6624", 0},
+	{},
+};
+
+MODULE_DEVICE_TABLE(i2c, vs6624_id);
+
+static struct i2c_driver vs6624_driver = {
+	.driver = {
+		.owner  = THIS_MODULE,
+		.name   = "vs6624",
+	},
+	.probe          = vs6624_probe,
+	.remove         = __devexit_p(vs6624_remove),
+	.id_table       = vs6624_id,
+};
+
+static __init int vs6624_init(void)
+{
+	return i2c_add_driver(&vs6624_driver);
+}
+
+static __exit void vs6624_exit(void)
+{
+	i2c_del_driver(&vs6624_driver);
+}
+
+module_init(vs6624_init);
+module_exit(vs6624_exit);
+
+MODULE_DESCRIPTION("VS6624 sensor driver");
+MODULE_AUTHOR("Scott Jiang <Scott.Jiang.Linux@gmail.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/i2c/vs6624_regs.h b/drivers/media/i2c/vs6624_regs.h
new file mode 100644
index 0000000..6ba2ee2
--- /dev/null
+++ b/drivers/media/i2c/vs6624_regs.h
@@ -0,0 +1,337 @@
+/*
+ * vs6624 - ST VS6624 CMOS image sensor registers
+ *
+ * Copyright (c) 2011 Analog Devices Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _VS6624_REGS_H_
+#define _VS6624_REGS_H_
+
+/* low level control registers */
+#define VS6624_MICRO_EN               0xC003 /* power enable for all MCU clock */
+#define VS6624_DIO_EN                 0xC044 /* enable digital I/O */
+/* device parameters */
+#define VS6624_DEV_ID_MSB             0x0001 /* device id MSB */
+#define VS6624_DEV_ID_LSB             0x0002 /* device id LSB */
+#define VS6624_FW_VSN_MAJOR           0x0004 /* firmware version major */
+#define VS6624_FW_VSN_MINOR           0x0006 /* firmware version minor */
+#define VS6624_PATCH_VSN_MAJOR        0x0008 /* patch version major */
+#define VS6624_PATCH_VSN_MINOR        0x000A /* patch version minor */
+/* host interface manager control */
+#define VS6624_USER_CMD               0x0180 /* user level control of operating states */
+/* host interface manager status */
+#define VS6624_STATE                  0x0202 /* current state of the mode manager */
+/* run mode control */
+#define VS6624_METER_ON               0x0280 /* if false AE and AWB are disabled */
+/* mode setup */
+#define VS6624_ACTIVE_PIPE_SETUP      0x0302 /* select the active bank for non view live mode */
+#define VS6624_SENSOR_MODE            0x0308 /* select the different sensor mode */
+/* pipe setup bank0 */
+#define VS6624_IMAGE_SIZE0            0x0380 /* required output dimension */
+#define VS6624_MAN_HSIZE0_MSB         0x0383 /* input required manual H size MSB */
+#define VS6624_MAN_HSIZE0_LSB         0x0384 /* input required manual H size LSB */
+#define VS6624_MAN_VSIZE0_MSB         0x0387 /* input required manual V size MSB */
+#define VS6624_MAN_VSIZE0_LSB         0x0388 /* input required manual V size LSB */
+#define VS6624_ZOOM_HSTEP0_MSB        0x038B /* set the zoom H step MSB */
+#define VS6624_ZOOM_HSTEP0_LSB        0x038C /* set the zoom H step LSB */
+#define VS6624_ZOOM_VSTEP0_MSB        0x038F /* set the zoom V step MSB */
+#define VS6624_ZOOM_VSTEP0_LSB        0x0390 /* set the zoom V step LSB */
+#define VS6624_ZOOM_CTRL0             0x0392 /* control zoon in, out and stop */
+#define VS6624_PAN_HSTEP0_MSB         0x0395 /* set the pan H step MSB */
+#define VS6624_PAN_HSTEP0_LSB         0x0396 /* set the pan H step LSB */
+#define VS6624_PAN_VSTEP0_MSB         0x0399 /* set the pan V step MSB */
+#define VS6624_PAN_VSTEP0_LSB         0x039A /* set the pan V step LSB */
+#define VS6624_PAN_CTRL0              0x039C /* control pan operation */
+#define VS6624_CROP_CTRL0             0x039E /* select cropping mode */
+#define VS6624_CROP_HSTART0_MSB       0x03A1 /* set the cropping H start address MSB */
+#define VS6624_CROP_HSTART0_LSB       0x03A2 /* set the cropping H start address LSB */
+#define VS6624_CROP_HSIZE0_MSB        0x03A5 /* set the cropping H size MSB */
+#define VS6624_CROP_HSIZE0_LSB        0x03A6 /* set the cropping H size LSB */
+#define VS6624_CROP_VSTART0_MSB       0x03A9 /* set the cropping V start address MSB */
+#define VS6624_CROP_VSTART0_LSB       0x03AA /* set the cropping V start address LSB */
+#define VS6624_CROP_VSIZE0_MSB        0x03AD /* set the cropping V size MSB */
+#define VS6624_CROP_VSIZE0_LSB        0x03AE /* set the cropping V size LSB */
+#define VS6624_IMG_FMT0               0x03B0 /* select required output image format */
+#define VS6624_BAYER_OUT_ALIGN0       0x03B2 /* set bayer output alignment */
+#define VS6624_CONTRAST0              0x03B4 /* contrast control for output */
+#define VS6624_SATURATION0            0x03B6 /* saturation control for output */
+#define VS6624_GAMMA0                 0x03B8 /* gamma settings */
+#define VS6624_HMIRROR0               0x03BA /* horizontal image orientation flip */
+#define VS6624_VFLIP0                 0x03BC /* vertical image orientation flip */
+#define VS6624_CHANNEL_ID0            0x03BE /* logical DMA channel number */
+/* pipe setup bank1 */
+#define VS6624_IMAGE_SIZE1            0x0400 /* required output dimension */
+#define VS6624_MAN_HSIZE1_MSB         0x0403 /* input required manual H size MSB */
+#define VS6624_MAN_HSIZE1_LSB         0x0404 /* input required manual H size LSB */
+#define VS6624_MAN_VSIZE1_MSB         0x0407 /* input required manual V size MSB */
+#define VS6624_MAN_VSIZE1_LSB         0x0408 /* input required manual V size LSB */
+#define VS6624_ZOOM_HSTEP1_MSB        0x040B /* set the zoom H step MSB */
+#define VS6624_ZOOM_HSTEP1_LSB        0x040C /* set the zoom H step LSB */
+#define VS6624_ZOOM_VSTEP1_MSB        0x040F /* set the zoom V step MSB */
+#define VS6624_ZOOM_VSTEP1_LSB        0x0410 /* set the zoom V step LSB */
+#define VS6624_ZOOM_CTRL1             0x0412 /* control zoon in, out and stop */
+#define VS6624_PAN_HSTEP1_MSB         0x0415 /* set the pan H step MSB */
+#define VS6624_PAN_HSTEP1_LSB         0x0416 /* set the pan H step LSB */
+#define VS6624_PAN_VSTEP1_MSB         0x0419 /* set the pan V step MSB */
+#define VS6624_PAN_VSTEP1_LSB         0x041A /* set the pan V step LSB */
+#define VS6624_PAN_CTRL1              0x041C /* control pan operation */
+#define VS6624_CROP_CTRL1             0x041E /* select cropping mode */
+#define VS6624_CROP_HSTART1_MSB       0x0421 /* set the cropping H start address MSB */
+#define VS6624_CROP_HSTART1_LSB       0x0422 /* set the cropping H start address LSB */
+#define VS6624_CROP_HSIZE1_MSB        0x0425 /* set the cropping H size MSB */
+#define VS6624_CROP_HSIZE1_LSB        0x0426 /* set the cropping H size LSB */
+#define VS6624_CROP_VSTART1_MSB       0x0429 /* set the cropping V start address MSB */
+#define VS6624_CROP_VSTART1_LSB       0x042A /* set the cropping V start address LSB */
+#define VS6624_CROP_VSIZE1_MSB        0x042D /* set the cropping V size MSB */
+#define VS6624_CROP_VSIZE1_LSB        0x042E /* set the cropping V size LSB */
+#define VS6624_IMG_FMT1               0x0430 /* select required output image format */
+#define VS6624_BAYER_OUT_ALIGN1       0x0432 /* set bayer output alignment */
+#define VS6624_CONTRAST1              0x0434 /* contrast control for output */
+#define VS6624_SATURATION1            0x0436 /* saturation control for output */
+#define VS6624_GAMMA1                 0x0438 /* gamma settings */
+#define VS6624_HMIRROR1               0x043A /* horizontal image orientation flip */
+#define VS6624_VFLIP1                 0x043C /* vertical image orientation flip */
+#define VS6624_CHANNEL_ID1            0x043E /* logical DMA channel number */
+/* view live control */
+#define VS6624_VIEW_LIVE_EN           0x0480 /* enable view live mode */
+#define VS6624_INIT_PIPE_SETUP        0x0482 /* select initial pipe setup bank */
+/* view live status */
+#define VS6624_CUR_PIPE_SETUP         0x0500 /* indicates most recently applied setup bank */
+/* power management */
+#define VS6624_TIME_TO_POWER_DOWN     0x0580 /* automatically transition time to stop mode */
+/* video timing parameter host inputs */
+#define VS6624_EXT_CLK_FREQ_NUM_MSB   0x0605 /* external clock frequency numerator MSB */
+#define VS6624_EXT_CLK_FREQ_NUM_LSB   0x0606 /* external clock frequency numerator LSB */
+#define VS6624_EXT_CLK_FREQ_DEN       0x0608 /* external clock frequency denominator */
+/* video timing control */
+#define VS6624_SYS_CLK_MODE           0x0880 /* decides system clock frequency */
+/* frame dimension parameter host inputs */
+#define VS6624_LIGHT_FREQ             0x0C80 /* AC frequency used for flicker free time */
+#define VS6624_FLICKER_COMPAT         0x0C82 /* flicker compatible frame length */
+/* static frame rate control */
+#define VS6624_FR_NUM_MSB             0x0D81 /* desired frame rate numerator MSB */
+#define VS6624_FR_NUM_LSB             0x0D82 /* desired frame rate numerator LSB */
+#define VS6624_FR_DEN                 0x0D84 /* desired frame rate denominator */
+/* automatic frame rate control */
+#define VS6624_DISABLE_FR_DAMPER      0x0E80 /* defines frame rate mode */
+#define VS6624_MIN_DAMPER_OUT_MSB     0x0E8C /* minimum frame rate MSB */
+#define VS6624_MIN_DAMPER_OUT_LSB     0x0E8A /* minimum frame rate LSB */
+/* exposure controls */
+#define VS6624_EXPO_MODE              0x1180 /* exposure mode */
+#define VS6624_EXPO_METER             0x1182 /* weights to be associated with the zones */
+#define VS6624_EXPO_TIME_NUM          0x1184 /* exposure time numerator */
+#define VS6624_EXPO_TIME_DEN          0x1186 /* exposure time denominator */
+#define VS6624_EXPO_TIME_MSB          0x1189 /* exposure time for the Manual Mode MSB */
+#define VS6624_EXPO_TIME_LSB          0x118A /* exposure time for the Manual Mode LSB */
+#define VS6624_EXPO_COMPENSATION      0x1190 /* exposure compensation */
+#define VS6624_DIRECT_COARSE_MSB      0x1195 /* coarse integration lines for Direct Mode MSB */
+#define VS6624_DIRECT_COARSE_LSB      0x1196 /* coarse integration lines for Direct Mode LSB */
+#define VS6624_DIRECT_FINE_MSB        0x1199 /* fine integration pixels for Direct Mode MSB */
+#define VS6624_DIRECT_FINE_LSB        0x119A /* fine integration pixels for Direct Mode LSB */
+#define VS6624_DIRECT_ANAL_GAIN_MSB   0x119D /* analog gain for Direct Mode MSB */
+#define VS6624_DIRECT_ANAL_GAIN_LSB   0x119E /* analog gain for Direct Mode LSB */
+#define VS6624_DIRECT_DIGI_GAIN_MSB   0x11A1 /* digital gain for Direct Mode MSB */
+#define VS6624_DIRECT_DIGI_GAIN_LSB   0x11A2 /* digital gain for Direct Mode LSB */
+#define VS6624_FLASH_COARSE_MSB       0x11A5 /* coarse integration lines for Flash Gun Mode MSB */
+#define VS6624_FLASH_COARSE_LSB       0x11A6 /* coarse integration lines for Flash Gun Mode LSB */
+#define VS6624_FLASH_FINE_MSB         0x11A9 /* fine integration pixels for Flash Gun Mode MSB */
+#define VS6624_FLASH_FINE_LSB         0x11AA /* fine integration pixels for Flash Gun Mode LSB */
+#define VS6624_FLASH_ANAL_GAIN_MSB    0x11AD /* analog gain for Flash Gun Mode MSB */
+#define VS6624_FLASH_ANAL_GAIN_LSB    0x11AE /* analog gain for Flash Gun Mode LSB */
+#define VS6624_FLASH_DIGI_GAIN_MSB    0x11B1 /* digital gain for Flash Gun Mode MSB */
+#define VS6624_FLASH_DIGI_GAIN_LSB    0x11B2 /* digital gain for Flash Gun Mode LSB */
+#define VS6624_FREEZE_AE              0x11B4 /* freeze auto exposure */
+#define VS6624_MAX_INT_TIME_MSB       0x11B7 /* user maximum integration time MSB */
+#define VS6624_MAX_INT_TIME_LSB       0x11B8 /* user maximum integration time LSB */
+#define VS6624_FLASH_AG_THR_MSB       0x11BB /* recommend flash gun analog gain threshold MSB */
+#define VS6624_FLASH_AG_THR_LSB       0x11BC /* recommend flash gun analog gain threshold LSB */
+#define VS6624_ANTI_FLICKER_MODE      0x11C0 /* anti flicker mode */
+/* white balance control */
+#define VS6624_WB_MODE                0x1480 /* set white balance mode */
+#define VS6624_MAN_RG                 0x1482 /* user setting for red channel gain */
+#define VS6624_MAN_GG                 0x1484 /* user setting for green channel gain */
+#define VS6624_MAN_BG                 0x1486 /* user setting for blue channel gain */
+#define VS6624_FLASH_RG_MSB           0x148B /* red gain for Flash Gun MSB */
+#define VS6624_FLASH_RG_LSB           0x148C /* red gain for Flash Gun LSB */
+#define VS6624_FLASH_GG_MSB           0x148F /* green gain for Flash Gun MSB */
+#define VS6624_FLASH_GG_LSB           0x1490 /* green gain for Flash Gun LSB */
+#define VS6624_FLASH_BG_MSB           0x1493 /* blue gain for Flash Gun MSB */
+#define VS6624_FLASH_BG_LSB           0x1494 /* blue gain for Flash Gun LSB */
+/* sensor setup */
+#define VS6624_BC_OFFSET              0x1990 /* Black Correction Offset */
+/* image stability */
+#define VS6624_STABLE_WB              0x1900 /* white balance stable */
+#define VS6624_STABLE_EXPO            0x1902 /* exposure stable */
+#define VS6624_STABLE                 0x1906 /* system stable */
+/* flash control */
+#define VS6624_FLASH_MODE             0x1A80 /* flash mode */
+#define VS6624_FLASH_OFF_LINE_MSB     0x1A83 /* off line at flash pulse mode MSB */
+#define VS6624_FLASH_OFF_LINE_LSB     0x1A84 /* off line at flash pulse mode LSB */
+/* flash status */
+#define VS6624_FLASH_RECOM            0x1B00 /* flash gun is recommended */
+#define VS6624_FLASH_GRAB_COMPLETE    0x1B02 /* flash gun image has been grabbed */
+/* scythe filter controls */
+#define VS6624_SCYTHE_FILTER          0x1D80 /* disable scythe defect correction */
+/* jack filter controls */
+#define VS6624_JACK_FILTER            0x1E00 /* disable jack defect correction */
+/* demosaic control */
+#define VS6624_ANTI_ALIAS_FILTER      0x1E80 /* anti alias filter suppress */
+/* color matrix dampers */
+#define VS6624_CM_DISABLE             0x1F00 /* disable color matrix damper */
+#define VS6624_CM_LOW_THR_MSB         0x1F03 /* low threshold for exposure MSB */
+#define VS6624_CM_LOW_THR_LSB         0x1F04 /* low threshold for exposure LSB */
+#define VS6624_CM_HIGH_THR_MSB        0x1F07 /* high threshold for exposure MSB */
+#define VS6624_CM_HIGH_THR_LSB        0x1F08 /* high threshold for exposure LSB */
+#define VS6624_CM_MIN_OUT_MSB         0x1F0B /* minimum possible damper output MSB */
+#define VS6624_CM_MIN_OUT_LSB         0x1F0C /* minimum possible damper output LSB */
+/* peaking control */
+#define VS6624_PEAK_GAIN              0x2000 /* controls peaking gain */
+#define VS6624_PEAK_G_DISABLE         0x2002 /* disable peak gain damping */
+#define VS6624_PEAK_LOW_THR_G_MSB     0x2005 /* low threshold for exposure for gain MSB */
+#define VS6624_PEAK_LOW_THR_G_LSB     0x2006 /* low threshold for exposure for gain LSB */
+#define VS6624_PEAK_HIGH_THR_G_MSB    0x2009 /* high threshold for exposure for gain MSB */
+#define VS6624_PEAK_HIGH_THR_G_LSB    0x200A /* high threshold for exposure for gain LSB */
+#define VS6624_PEAK_MIN_OUT_G_MSB     0x200D /* minimum damper output for gain MSB */
+#define VS6624_PEAK_MIN_OUT_G_LSB     0x200E /* minimum damper output for gain LSB */
+#define VS6624_PEAK_LOW_THR           0x2010 /* adjust degree of coring */
+#define VS6624_PEAK_C_DISABLE         0x2012 /* disable coring damping */
+#define VS6624_PEAK_HIGH_THR          0x2014 /* adjust maximum gain */
+#define VS6624_PEAK_LOW_THR_C_MSB     0x2017 /* low threshold for exposure for coring MSB */
+#define VS6624_PEAK_LOW_THR_C_LSB     0x2018 /* low threshold for exposure for coring LSB */
+#define VS6624_PEAK_HIGH_THR_C_MSB    0x201B /* high threshold for exposure for coring MSB */
+#define VS6624_PEAK_HIGH_THR_C_LSB    0x201C /* high threshold for exposure for coring LSB */
+#define VS6624_PEAK_MIN_OUT_C_MSB     0x201F /* minimum damper output for coring MSB */
+#define VS6624_PEAK_MIN_OUT_C_LSB     0x2020 /* minimum damper output for coring LSB */
+/* pipe 0 RGB to YUV matrix manual control */
+#define VS6624_RYM0_MAN_CTRL          0x2180 /* enable manual RGB to YUV matrix */
+#define VS6624_RYM0_W00_MSB           0x2183 /* row 0 column 0 of YUV matrix MSB */
+#define VS6624_RYM0_W00_LSB           0x2184 /* row 0 column 0 of YUV matrix LSB */
+#define VS6624_RYM0_W01_MSB           0x2187 /* row 0 column 1 of YUV matrix MSB */
+#define VS6624_RYM0_W01_LSB           0x2188 /* row 0 column 1 of YUV matrix LSB */
+#define VS6624_RYM0_W02_MSB           0x218C /* row 0 column 2 of YUV matrix MSB */
+#define VS6624_RYM0_W02_LSB           0x218D /* row 0 column 2 of YUV matrix LSB */
+#define VS6624_RYM0_W10_MSB           0x2190 /* row 1 column 0 of YUV matrix MSB */
+#define VS6624_RYM0_W10_LSB           0x218F /* row 1 column 0 of YUV matrix LSB */
+#define VS6624_RYM0_W11_MSB           0x2193 /* row 1 column 1 of YUV matrix MSB */
+#define VS6624_RYM0_W11_LSB           0x2194 /* row 1 column 1 of YUV matrix LSB */
+#define VS6624_RYM0_W12_MSB           0x2197 /* row 1 column 2 of YUV matrix MSB */
+#define VS6624_RYM0_W12_LSB           0x2198 /* row 1 column 2 of YUV matrix LSB */
+#define VS6624_RYM0_W20_MSB           0x219B /* row 2 column 0 of YUV matrix MSB */
+#define VS6624_RYM0_W20_LSB           0x219C /* row 2 column 0 of YUV matrix LSB */
+#define VS6624_RYM0_W21_MSB           0x21A0 /* row 2 column 1 of YUV matrix MSB */
+#define VS6624_RYM0_W21_LSB           0x219F /* row 2 column 1 of YUV matrix LSB */
+#define VS6624_RYM0_W22_MSB           0x21A3 /* row 2 column 2 of YUV matrix MSB */
+#define VS6624_RYM0_W22_LSB           0x21A4 /* row 2 column 2 of YUV matrix LSB */
+#define VS6624_RYM0_YINY_MSB          0x21A7 /* Y in Y MSB */
+#define VS6624_RYM0_YINY_LSB          0x21A8 /* Y in Y LSB */
+#define VS6624_RYM0_YINCB_MSB         0x21AB /* Y in Cb MSB */
+#define VS6624_RYM0_YINCB_LSB         0x21AC /* Y in Cb LSB */
+#define VS6624_RYM0_YINCR_MSB         0x21B0 /* Y in Cr MSB */
+#define VS6624_RYM0_YINCR_LSB         0x21AF /* Y in Cr LSB */
+/* pipe 1 RGB to YUV matrix manual control */
+#define VS6624_RYM1_MAN_CTRL          0x2200 /* enable manual RGB to YUV matrix */
+#define VS6624_RYM1_W00_MSB           0x2203 /* row 0 column 0 of YUV matrix MSB */
+#define VS6624_RYM1_W00_LSB           0x2204 /* row 0 column 0 of YUV matrix LSB */
+#define VS6624_RYM1_W01_MSB           0x2207 /* row 0 column 1 of YUV matrix MSB */
+#define VS6624_RYM1_W01_LSB           0x2208 /* row 0 column 1 of YUV matrix LSB */
+#define VS6624_RYM1_W02_MSB           0x220C /* row 0 column 2 of YUV matrix MSB */
+#define VS6624_RYM1_W02_LSB           0x220D /* row 0 column 2 of YUV matrix LSB */
+#define VS6624_RYM1_W10_MSB           0x2210 /* row 1 column 0 of YUV matrix MSB */
+#define VS6624_RYM1_W10_LSB           0x220F /* row 1 column 0 of YUV matrix LSB */
+#define VS6624_RYM1_W11_MSB           0x2213 /* row 1 column 1 of YUV matrix MSB */
+#define VS6624_RYM1_W11_LSB           0x2214 /* row 1 column 1 of YUV matrix LSB */
+#define VS6624_RYM1_W12_MSB           0x2217 /* row 1 column 2 of YUV matrix MSB */
+#define VS6624_RYM1_W12_LSB           0x2218 /* row 1 column 2 of YUV matrix LSB */
+#define VS6624_RYM1_W20_MSB           0x221B /* row 2 column 0 of YUV matrix MSB */
+#define VS6624_RYM1_W20_LSB           0x221C /* row 2 column 0 of YUV matrix LSB */
+#define VS6624_RYM1_W21_MSB           0x2220 /* row 2 column 1 of YUV matrix MSB */
+#define VS6624_RYM1_W21_LSB           0x221F /* row 2 column 1 of YUV matrix LSB */
+#define VS6624_RYM1_W22_MSB           0x2223 /* row 2 column 2 of YUV matrix MSB */
+#define VS6624_RYM1_W22_LSB           0x2224 /* row 2 column 2 of YUV matrix LSB */
+#define VS6624_RYM1_YINY_MSB          0x2227 /* Y in Y MSB */
+#define VS6624_RYM1_YINY_LSB          0x2228 /* Y in Y LSB */
+#define VS6624_RYM1_YINCB_MSB         0x222B /* Y in Cb MSB */
+#define VS6624_RYM1_YINCB_LSB         0x222C /* Y in Cb LSB */
+#define VS6624_RYM1_YINCR_MSB         0x2220 /* Y in Cr MSB */
+#define VS6624_RYM1_YINCR_LSB         0x222F /* Y in Cr LSB */
+/* pipe 0 gamma manual control */
+#define VS6624_GAMMA_MAN_CTRL0        0x2280 /* enable manual gamma setup */
+#define VS6624_GAMMA_PEAK_R0          0x2282 /* peaked red channel gamma value */
+#define VS6624_GAMMA_PEAK_G0          0x2284 /* peaked green channel gamma value */
+#define VS6624_GAMMA_PEAK_B0          0x2286 /* peaked blue channel gamma value */
+#define VS6624_GAMMA_UNPEAK_R0        0x2288 /* unpeaked red channel gamma value */
+#define VS6624_GAMMA_UNPEAK_G0        0x228A /* unpeaked green channel gamma value */
+#define VS6624_GAMMA_UNPEAK_B0        0x228C /* unpeaked blue channel gamma value */
+/* pipe 1 gamma manual control */
+#define VS6624_GAMMA_MAN_CTRL1        0x2300 /* enable manual gamma setup */
+#define VS6624_GAMMA_PEAK_R1          0x2302 /* peaked red channel gamma value */
+#define VS6624_GAMMA_PEAK_G1          0x2304 /* peaked green channel gamma value */
+#define VS6624_GAMMA_PEAK_B1          0x2306 /* peaked blue channel gamma value */
+#define VS6624_GAMMA_UNPEAK_R1        0x2308 /* unpeaked red channel gamma value */
+#define VS6624_GAMMA_UNPEAK_G1        0x230A /* unpeaked green channel gamma value */
+#define VS6624_GAMMA_UNPEAK_B1        0x230C /* unpeaked blue channel gamma value */
+/* fade to black */
+#define VS6624_F2B_DISABLE            0x2480 /* disable fade to black */
+#define VS6624_F2B_BLACK_VAL_MSB      0x2483 /* black value MSB */
+#define VS6624_F2B_BLACK_VAL_LSB      0x2484 /* black value LSB */
+#define VS6624_F2B_LOW_THR_MSB        0x2487 /* low threshold for exposure MSB */
+#define VS6624_F2B_LOW_THR_LSB        0x2488 /* low threshold for exposure LSB */
+#define VS6624_F2B_HIGH_THR_MSB       0x248B /* high threshold for exposure MSB */
+#define VS6624_F2B_HIGH_THR_LSB       0x248C /* high threshold for exposure LSB */
+#define VS6624_F2B_MIN_OUT_MSB        0x248F /* minimum damper output MSB */
+#define VS6624_F2B_MIN_OUT_LSB        0x2490 /* minimum damper output LSB */
+/* output formatter control */
+#define VS6624_CODE_CK_EN             0x2580 /* code check enable */
+#define VS6624_BLANK_FMT              0x2582 /* blank format */
+#define VS6624_SYNC_CODE_SETUP        0x2584 /* sync code setup */
+#define VS6624_HSYNC_SETUP            0x2586 /* H sync setup */
+#define VS6624_VSYNC_SETUP            0x2588 /* V sync setup */
+#define VS6624_PCLK_SETUP             0x258A /* PCLK setup */
+#define VS6624_PCLK_EN                0x258C /* PCLK enable */
+#define VS6624_OPF_SP_SETUP           0x258E /* output formatter sp setup */
+#define VS6624_BLANK_DATA_MSB         0x2590 /* blank data MSB */
+#define VS6624_BLANK_DATA_LSB         0x2592 /* blank data LSB */
+#define VS6624_RGB_SETUP              0x2594 /* RGB setup */
+#define VS6624_YUV_SETUP              0x2596 /* YUV setup */
+#define VS6624_VSYNC_RIS_COARSE_H     0x2598 /* V sync rising coarse high */
+#define VS6624_VSYNC_RIS_COARSE_L     0x259A /* V sync rising coarse low */
+#define VS6624_VSYNC_RIS_FINE_H       0x259C /* V sync rising fine high */
+#define VS6624_VSYNC_RIS_FINE_L       0x259E /* V sync rising fine low */
+#define VS6624_VSYNC_FALL_COARSE_H    0x25A0 /* V sync falling coarse high */
+#define VS6624_VSYNC_FALL_COARSE_L    0x25A2 /* V sync falling coarse low */
+#define VS6624_VSYNC_FALL_FINE_H      0x25A4 /* V sync falling fine high */
+#define VS6624_VSYNC_FALL_FINE_L      0x25A6 /* V sync falling fine low */
+#define VS6624_HSYNC_RIS_H            0x25A8 /* H sync rising high */
+#define VS6624_HSYNC_RIS_L            0x25AA /* H sync rising low */
+#define VS6624_HSYNC_FALL_H           0x25AC /* H sync falling high */
+#define VS6624_HSYNC_FALL_L           0x25AE /* H sync falling low */
+#define VS6624_OUT_IF                 0x25B0 /* output interface */
+#define VS6624_CCP_EXT_DATA           0x25B2 /* CCP extra data */
+/* NoRA controls */
+#define VS6624_NORA_DISABLE           0x2600 /* NoRA control mode */
+#define VS6624_NORA_USAGE             0x2602 /* usage */
+#define VS6624_NORA_SPLIT_KN          0x2604 /* split kn */
+#define VS6624_NORA_SPLIT_NI          0x2606 /* split ni */
+#define VS6624_NORA_TIGHT_G           0x2608 /* tight green */
+#define VS6624_NORA_DISABLE_NP        0x260A /* disable noro promoting */
+#define VS6624_NORA_LOW_THR_MSB       0x260D /* low threshold for exposure MSB */
+#define VS6624_NORA_LOW_THR_LSB       0x260E /* low threshold for exposure LSB */
+#define VS6624_NORA_HIGH_THR_MSB      0x2611 /* high threshold for exposure MSB */
+#define VS6624_NORA_HIGH_THR_LSB      0x2612 /* high threshold for exposure LSB */
+#define VS6624_NORA_MIN_OUT_MSB       0x2615 /* minimum damper output MSB */
+#define VS6624_NORA_MIN_OUT_LSB       0x2616 /* minimum damper output LSB */
+
+#endif
diff --git a/drivers/media/i2c/wm8739.c b/drivers/media/i2c/wm8739.c
new file mode 100644
index 0000000..3bb99e9
--- /dev/null
+++ b/drivers/media/i2c/wm8739.c
@@ -0,0 +1,294 @@
+/*
+ * wm8739
+ *
+ * Copyright (C) 2005 T. Adachi <tadachi@tadachi-net.com>
+ *
+ * Copyright (C) 2005 Hans Verkuil <hverkuil@xs4all.nl>
+ * - Cleanup
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/slab.h>
+#include <linux/ioctl.h>
+#include <asm/uaccess.h>
+#include <linux/i2c.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-ctrls.h>
+
+MODULE_DESCRIPTION("wm8739 driver");
+MODULE_AUTHOR("T. Adachi, Hans Verkuil");
+MODULE_LICENSE("GPL");
+
+static int debug;
+
+module_param(debug, int, 0644);
+
+MODULE_PARM_DESC(debug, "Debug level (0-1)");
+
+
+/* ------------------------------------------------------------------------ */
+
+enum {
+	R0 = 0, R1,
+	R5 = 5, R6, R7, R8, R9, R15 = 15,
+	TOT_REGS
+};
+
+struct wm8739_state {
+	struct v4l2_subdev sd;
+	struct v4l2_ctrl_handler hdl;
+	struct {
+		/* audio cluster */
+		struct v4l2_ctrl *volume;
+		struct v4l2_ctrl *mute;
+		struct v4l2_ctrl *balance;
+	};
+	u32 clock_freq;
+};
+
+static inline struct wm8739_state *to_state(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct wm8739_state, sd);
+}
+
+static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
+{
+	return &container_of(ctrl->handler, struct wm8739_state, hdl)->sd;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int wm8739_write(struct v4l2_subdev *sd, int reg, u16 val)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	int i;
+
+	if (reg < 0 || reg >= TOT_REGS) {
+		v4l2_err(sd, "Invalid register R%d\n", reg);
+		return -1;
+	}
+
+	v4l2_dbg(1, debug, sd, "write: %02x %02x\n", reg, val);
+
+	for (i = 0; i < 3; i++)
+		if (i2c_smbus_write_byte_data(client,
+				(reg << 1) | (val >> 8), val & 0xff) == 0)
+			return 0;
+	v4l2_err(sd, "I2C: cannot write %03x to register R%d\n", val, reg);
+	return -1;
+}
+
+static int wm8739_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct v4l2_subdev *sd = to_sd(ctrl);
+	struct wm8739_state *state = to_state(sd);
+	unsigned int work_l, work_r;
+	u8 vol_l;	/* +12dB to -34.5dB 1.5dB step (5bit) def:0dB */
+	u8 vol_r;	/* +12dB to -34.5dB 1.5dB step (5bit) def:0dB */
+	u16 mute;
+
+	switch (ctrl->id) {
+	case V4L2_CID_AUDIO_VOLUME:
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	/* normalize ( 65535 to 0 -> 31 to 0 (12dB to -34.5dB) ) */
+	work_l = (min(65536 - state->balance->val, 32768) * state->volume->val) / 32768;
+	work_r = (min(state->balance->val, 32768) * state->volume->val) / 32768;
+
+	vol_l = (long)work_l * 31 / 65535;
+	vol_r = (long)work_r * 31 / 65535;
+
+	/* set audio volume etc. */
+	mute = state->mute->val ? 0x80 : 0;
+
+	/* Volume setting: bits 0-4, 0x1f = 12 dB, 0x00 = -34.5 dB
+	 * Default setting: 0x17 = 0 dB
+	 */
+	wm8739_write(sd, R0, (vol_l & 0x1f) | mute);
+	wm8739_write(sd, R1, (vol_r & 0x1f) | mute);
+	return 0;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int wm8739_s_clock_freq(struct v4l2_subdev *sd, u32 audiofreq)
+{
+	struct wm8739_state *state = to_state(sd);
+
+	state->clock_freq = audiofreq;
+	/* de-activate */
+	wm8739_write(sd, R9, 0x000);
+	switch (audiofreq) {
+	case 44100:
+		/* 256fps, fs=44.1k */
+		wm8739_write(sd, R8, 0x020);
+		break;
+	case 48000:
+		/* 256fps, fs=48k */
+		wm8739_write(sd, R8, 0x000);
+		break;
+	case 32000:
+		/* 256fps, fs=32k */
+		wm8739_write(sd, R8, 0x018);
+		break;
+	default:
+		break;
+	}
+	/* activate */
+	wm8739_write(sd, R9, 0x001);
+	return 0;
+}
+
+static int wm8739_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_WM8739, 0);
+}
+
+static int wm8739_log_status(struct v4l2_subdev *sd)
+{
+	struct wm8739_state *state = to_state(sd);
+
+	v4l2_info(sd, "Frequency: %u Hz\n", state->clock_freq);
+	v4l2_ctrl_handler_log_status(&state->hdl, sd->name);
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static const struct v4l2_ctrl_ops wm8739_ctrl_ops = {
+	.s_ctrl = wm8739_s_ctrl,
+};
+
+static const struct v4l2_subdev_core_ops wm8739_core_ops = {
+	.log_status = wm8739_log_status,
+	.g_chip_ident = wm8739_g_chip_ident,
+	.g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
+	.try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
+	.s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
+	.g_ctrl = v4l2_subdev_g_ctrl,
+	.s_ctrl = v4l2_subdev_s_ctrl,
+	.queryctrl = v4l2_subdev_queryctrl,
+	.querymenu = v4l2_subdev_querymenu,
+};
+
+static const struct v4l2_subdev_audio_ops wm8739_audio_ops = {
+	.s_clock_freq = wm8739_s_clock_freq,
+};
+
+static const struct v4l2_subdev_ops wm8739_ops = {
+	.core = &wm8739_core_ops,
+	.audio = &wm8739_audio_ops,
+};
+
+/* ------------------------------------------------------------------------ */
+
+/* i2c implementation */
+
+static int wm8739_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	struct wm8739_state *state;
+	struct v4l2_subdev *sd;
+
+	/* Check if the adapter supports the needed features */
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		return -EIO;
+
+	v4l_info(client, "chip found @ 0x%x (%s)\n",
+			client->addr << 1, client->adapter->name);
+
+	state = kzalloc(sizeof(struct wm8739_state), GFP_KERNEL);
+	if (state == NULL)
+		return -ENOMEM;
+	sd = &state->sd;
+	v4l2_i2c_subdev_init(sd, client, &wm8739_ops);
+	v4l2_ctrl_handler_init(&state->hdl, 2);
+	state->volume = v4l2_ctrl_new_std(&state->hdl, &wm8739_ctrl_ops,
+			V4L2_CID_AUDIO_VOLUME, 0, 65535, 65535 / 100, 50736);
+	state->mute = v4l2_ctrl_new_std(&state->hdl, &wm8739_ctrl_ops,
+			V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0);
+	state->balance = v4l2_ctrl_new_std(&state->hdl, &wm8739_ctrl_ops,
+			V4L2_CID_AUDIO_BALANCE, 0, 65535, 65535 / 100, 32768);
+	sd->ctrl_handler = &state->hdl;
+	if (state->hdl.error) {
+		int err = state->hdl.error;
+
+		v4l2_ctrl_handler_free(&state->hdl);
+		kfree(state);
+		return err;
+	}
+	v4l2_ctrl_cluster(3, &state->volume);
+
+	state->clock_freq = 48000;
+
+	/* Initialize wm8739 */
+
+	/* reset */
+	wm8739_write(sd, R15, 0x00);
+	/* filter setting, high path, offet clear */
+	wm8739_write(sd, R5, 0x000);
+	/* ADC, OSC, Power Off mode Disable */
+	wm8739_write(sd, R6, 0x000);
+	/* Digital Audio interface format:
+	   Enable Master mode, 24 bit, MSB first/left justified */
+	wm8739_write(sd, R7, 0x049);
+	/* sampling control: normal, 256fs, 48KHz sampling rate */
+	wm8739_write(sd, R8, 0x000);
+	/* activate */
+	wm8739_write(sd, R9, 0x001);
+	/* set volume/mute */
+	v4l2_ctrl_handler_setup(&state->hdl);
+	return 0;
+}
+
+static int wm8739_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct wm8739_state *state = to_state(sd);
+
+	v4l2_device_unregister_subdev(sd);
+	v4l2_ctrl_handler_free(&state->hdl);
+	kfree(to_state(sd));
+	return 0;
+}
+
+static const struct i2c_device_id wm8739_id[] = {
+	{ "wm8739", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, wm8739_id);
+
+static struct i2c_driver wm8739_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "wm8739",
+	},
+	.probe		= wm8739_probe,
+	.remove		= wm8739_remove,
+	.id_table	= wm8739_id,
+};
+
+module_i2c_driver(wm8739_driver);
diff --git a/drivers/media/i2c/wm8775.c b/drivers/media/i2c/wm8775.c
new file mode 100644
index 0000000..bee77ea
--- /dev/null
+++ b/drivers/media/i2c/wm8775.c
@@ -0,0 +1,342 @@
+/*
+ * wm8775 - driver version 0.0.1
+ *
+ * Copyright (C) 2004 Ulf Eklund <ivtv at eklund.to>
+ *
+ * Based on saa7115 driver
+ *
+ * Copyright (C) 2005 Hans Verkuil <hverkuil@xs4all.nl>
+ * - Cleanup
+ * - V4L2 API update
+ * - sound fixes
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/slab.h>
+#include <linux/ioctl.h>
+#include <asm/uaccess.h>
+#include <linux/i2c.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-ctrls.h>
+#include <media/wm8775.h>
+
+MODULE_DESCRIPTION("wm8775 driver");
+MODULE_AUTHOR("Ulf Eklund, Hans Verkuil");
+MODULE_LICENSE("GPL");
+
+
+
+/* ----------------------------------------------------------------------- */
+
+enum {
+	R7 = 7, R11 = 11,
+	R12, R13, R14, R15, R16, R17, R18, R19, R20, R21, R23 = 23,
+	TOT_REGS
+};
+
+#define ALC_HOLD 0x85 /* R17: use zero cross detection, ALC hold time 42.6 ms */
+#define ALC_EN 0x100  /* R17: ALC enable */
+
+struct wm8775_state {
+	struct v4l2_subdev sd;
+	struct v4l2_ctrl_handler hdl;
+	struct v4l2_ctrl *mute;
+	struct v4l2_ctrl *vol;
+	struct v4l2_ctrl *bal;
+	struct v4l2_ctrl *loud;
+	u8 input;		/* Last selected input (0-0xf) */
+};
+
+static inline struct wm8775_state *to_state(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct wm8775_state, sd);
+}
+
+static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
+{
+	return &container_of(ctrl->handler, struct wm8775_state, hdl)->sd;
+}
+
+static int wm8775_write(struct v4l2_subdev *sd, int reg, u16 val)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	int i;
+
+	if (reg < 0 || reg >= TOT_REGS) {
+		v4l2_err(sd, "Invalid register R%d\n", reg);
+		return -1;
+	}
+
+	for (i = 0; i < 3; i++)
+		if (i2c_smbus_write_byte_data(client,
+				(reg << 1) | (val >> 8), val & 0xff) == 0)
+			return 0;
+	v4l2_err(sd, "I2C: cannot write %03x to register R%d\n", val, reg);
+	return -1;
+}
+
+static void wm8775_set_audio(struct v4l2_subdev *sd, int quietly)
+{
+	struct wm8775_state *state = to_state(sd);
+	u8 vol_l, vol_r;
+	int muted = 0 != state->mute->val;
+	u16 volume = (u16)state->vol->val;
+	u16 balance = (u16)state->bal->val;
+
+	/* normalize ( 65535 to 0 -> 255 to 0 (+24dB to -103dB) ) */
+	vol_l = (min(65536 - balance, 32768) * volume) >> 23;
+	vol_r = (min(balance, (u16)32768) * volume) >> 23;
+
+	/* Mute */
+	if (muted || quietly)
+		wm8775_write(sd, R21, 0x0c0 | state->input);
+
+	wm8775_write(sd, R14, vol_l | 0x100); /* 0x100= Left channel ADC zero cross enable */
+	wm8775_write(sd, R15, vol_r | 0x100); /* 0x100= Right channel ADC zero cross enable */
+
+	/* Un-mute */
+	if (!muted)
+		wm8775_write(sd, R21, state->input);
+}
+
+static int wm8775_s_routing(struct v4l2_subdev *sd,
+			    u32 input, u32 output, u32 config)
+{
+	struct wm8775_state *state = to_state(sd);
+
+	/* There are 4 inputs and one output. Zero or more inputs
+	   are multiplexed together to the output. Hence there are
+	   16 combinations.
+	   If only one input is active (the normal case) then the
+	   input values 1, 2, 4 or 8 should be used. */
+	if (input > 15) {
+		v4l2_err(sd, "Invalid input %d.\n", input);
+		return -EINVAL;
+	}
+	state->input = input;
+	if (!v4l2_ctrl_g_ctrl(state->mute))
+		return 0;
+	if (!v4l2_ctrl_g_ctrl(state->vol))
+		return 0;
+	if (!v4l2_ctrl_g_ctrl(state->bal))
+		return 0;
+	wm8775_set_audio(sd, 1);
+	return 0;
+}
+
+static int wm8775_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct v4l2_subdev *sd = to_sd(ctrl);
+
+	switch (ctrl->id) {
+	case V4L2_CID_AUDIO_MUTE:
+	case V4L2_CID_AUDIO_VOLUME:
+	case V4L2_CID_AUDIO_BALANCE:
+		wm8775_set_audio(sd, 0);
+		return 0;
+	case V4L2_CID_AUDIO_LOUDNESS:
+		wm8775_write(sd, R17, (ctrl->val ? ALC_EN : 0) | ALC_HOLD);
+		return 0;
+	}
+	return -EINVAL;
+}
+
+static int wm8775_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_WM8775, 0);
+}
+
+static int wm8775_log_status(struct v4l2_subdev *sd)
+{
+	struct wm8775_state *state = to_state(sd);
+
+	v4l2_info(sd, "Input: %d\n", state->input);
+	v4l2_ctrl_handler_log_status(&state->hdl, sd->name);
+	return 0;
+}
+
+static int wm8775_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *freq)
+{
+	wm8775_set_audio(sd, 0);
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static const struct v4l2_ctrl_ops wm8775_ctrl_ops = {
+	.s_ctrl = wm8775_s_ctrl,
+};
+
+static const struct v4l2_subdev_core_ops wm8775_core_ops = {
+	.log_status = wm8775_log_status,
+	.g_chip_ident = wm8775_g_chip_ident,
+	.g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
+	.try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
+	.s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
+	.g_ctrl = v4l2_subdev_g_ctrl,
+	.s_ctrl = v4l2_subdev_s_ctrl,
+	.queryctrl = v4l2_subdev_queryctrl,
+	.querymenu = v4l2_subdev_querymenu,
+};
+
+static const struct v4l2_subdev_tuner_ops wm8775_tuner_ops = {
+	.s_frequency = wm8775_s_frequency,
+};
+
+static const struct v4l2_subdev_audio_ops wm8775_audio_ops = {
+	.s_routing = wm8775_s_routing,
+};
+
+static const struct v4l2_subdev_ops wm8775_ops = {
+	.core = &wm8775_core_ops,
+	.tuner = &wm8775_tuner_ops,
+	.audio = &wm8775_audio_ops,
+};
+
+/* ----------------------------------------------------------------------- */
+
+/* i2c implementation */
+
+/*
+ * Generic i2c probe
+ * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
+ */
+
+static int wm8775_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	struct wm8775_state *state;
+	struct v4l2_subdev *sd;
+	int err;
+	bool is_nova_s = false;
+
+	if (client->dev.platform_data) {
+		struct wm8775_platform_data *data = client->dev.platform_data;
+		is_nova_s = data->is_nova_s;
+	}
+
+	/* Check if the adapter supports the needed features */
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		return -EIO;
+
+	v4l_info(client, "chip found @ 0x%02x (%s)\n",
+			client->addr << 1, client->adapter->name);
+
+	state = kzalloc(sizeof(struct wm8775_state), GFP_KERNEL);
+	if (state == NULL)
+		return -ENOMEM;
+	sd = &state->sd;
+	v4l2_i2c_subdev_init(sd, client, &wm8775_ops);
+	state->input = 2;
+
+	v4l2_ctrl_handler_init(&state->hdl, 4);
+	state->mute = v4l2_ctrl_new_std(&state->hdl, &wm8775_ctrl_ops,
+			V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0);
+	state->vol = v4l2_ctrl_new_std(&state->hdl, &wm8775_ctrl_ops,
+			V4L2_CID_AUDIO_VOLUME, 0, 65535, (65535+99)/100, 0xCF00); /* 0dB*/
+	state->bal = v4l2_ctrl_new_std(&state->hdl, &wm8775_ctrl_ops,
+			V4L2_CID_AUDIO_BALANCE, 0, 65535, (65535+99)/100, 32768);
+	state->loud = v4l2_ctrl_new_std(&state->hdl, &wm8775_ctrl_ops,
+			V4L2_CID_AUDIO_LOUDNESS, 0, 1, 1, 1);
+	sd->ctrl_handler = &state->hdl;
+	err = state->hdl.error;
+	if (err) {
+		v4l2_ctrl_handler_free(&state->hdl);
+		kfree(state);
+		return err;
+	}
+
+	/* Initialize wm8775 */
+
+	/* RESET */
+	wm8775_write(sd, R23, 0x000);
+	/* Disable zero cross detect timeout */
+	wm8775_write(sd, R7, 0x000);
+	/* HPF enable, left justified, 24-bit (Philips) mode */
+	wm8775_write(sd, R11, 0x021);
+	/* Master mode, clock ratio 256fs */
+	wm8775_write(sd, R12, 0x102);
+	/* Powered up */
+	wm8775_write(sd, R13, 0x000);
+
+	if (!is_nova_s) {
+		/* ADC gain +2.5dB, enable zero cross */
+		wm8775_write(sd, R14, 0x1d4);
+		/* ADC gain +2.5dB, enable zero cross */
+		wm8775_write(sd, R15, 0x1d4);
+		/* ALC Stereo, ALC target level -1dB FS max gain +8dB */
+		wm8775_write(sd, R16, 0x1bf);
+		/* Enable gain control, use zero cross detection,
+		   ALC hold time 42.6 ms */
+		wm8775_write(sd, R17, 0x185);
+	} else {
+		/* ALC stereo, ALC target level -5dB FS, ALC max gain +8dB */
+		wm8775_write(sd, R16, 0x1bb);
+		/* Set ALC mode and hold time */
+		wm8775_write(sd, R17, (state->loud->val ? ALC_EN : 0) | ALC_HOLD);
+	}
+	/* ALC gain ramp up delay 34 s, ALC gain ramp down delay 33 ms */
+	wm8775_write(sd, R18, 0x0a2);
+	/* Enable noise gate, threshold -72dBfs */
+	wm8775_write(sd, R19, 0x005);
+	if (!is_nova_s) {
+		/* Transient window 4ms, lower PGA gain limit -1dB */
+		wm8775_write(sd, R20, 0x07a);
+		/* LRBOTH = 1, use input 2. */
+		wm8775_write(sd, R21, 0x102);
+	} else {
+		/* Transient window 4ms, ALC min gain -5dB  */
+		wm8775_write(sd, R20, 0x0fb);
+
+		wm8775_set_audio(sd, 1);      /* set volume/mute/mux */
+	}
+	return 0;
+}
+
+static int wm8775_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct wm8775_state *state = to_state(sd);
+
+	v4l2_device_unregister_subdev(sd);
+	v4l2_ctrl_handler_free(&state->hdl);
+	kfree(state);
+	return 0;
+}
+
+static const struct i2c_device_id wm8775_id[] = {
+	{ "wm8775", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, wm8775_id);
+
+static struct i2c_driver wm8775_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "wm8775",
+	},
+	.probe		= wm8775_probe,
+	.remove		= wm8775_remove,
+	.id_table	= wm8775_id,
+};
+
+module_i2c_driver(wm8775_driver);
diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c
index 6f9eb94..d01fcb7 100644
--- a/drivers/media/media-device.c
+++ b/drivers/media/media-device.c
@@ -59,7 +59,9 @@ static int media_device_get_info(struct media_device *dev,
 	info.hw_revision = dev->hw_revision;
 	info.driver_version = dev->driver_version;
 
-	return copy_to_user(__info, &info, sizeof(*__info));
+	if (copy_to_user(__info, &info, sizeof(*__info)))
+		return -EFAULT;
+	return 0;
 }
 
 static struct media_entity *find_entity(struct media_device *mdev, u32 id)
diff --git a/drivers/media/mmc/Kconfig b/drivers/media/mmc/Kconfig
new file mode 100644
index 0000000..8c30ada
--- /dev/null
+++ b/drivers/media/mmc/Kconfig
@@ -0,0 +1,2 @@
+comment "Supported MMC/SDIO adapters"
+source "drivers/media/mmc/siano/Kconfig"
diff --git a/drivers/media/mmc/Makefile b/drivers/media/mmc/Makefile
new file mode 100644
index 0000000..31e297a
--- /dev/null
+++ b/drivers/media/mmc/Makefile
@@ -0,0 +1 @@
+obj-y += siano/
diff --git a/drivers/media/mmc/siano/Kconfig b/drivers/media/mmc/siano/Kconfig
new file mode 100644
index 0000000..fa62475
--- /dev/null
+++ b/drivers/media/mmc/siano/Kconfig
@@ -0,0 +1,10 @@
+#
+# Siano Mobile Silicon Digital TV device configuration
+#
+
+config SMS_SDIO_DRV
+	tristate "Siano SMS1xxx based MDTV via SDIO interface"
+	depends on DVB_CORE && RC_CORE && HAS_DMA
+	depends on MMC
+	---help---
+	  Choose if you would like to have Siano's support for SDIO interface
diff --git a/drivers/media/mmc/siano/Makefile b/drivers/media/mmc/siano/Makefile
new file mode 100644
index 0000000..0e01f97
--- /dev/null
+++ b/drivers/media/mmc/siano/Makefile
@@ -0,0 +1,6 @@
+obj-$(CONFIG_SMS_SDIO_DRV) += smssdio.o
+
+ccflags-y += -Idrivers/media/dvb-core
+ccflags-y += -Idrivers/media/common/siano
+ccflags-y += $(extra-cflags-y) $(extra-cflags-m)
+
diff --git a/drivers/media/mmc/siano/smssdio.c b/drivers/media/mmc/siano/smssdio.c
new file mode 100644
index 0000000..d6f3f10
--- /dev/null
+++ b/drivers/media/mmc/siano/smssdio.c
@@ -0,0 +1,365 @@
+/*
+ *  smssdio.c - Siano 1xxx SDIO interface driver
+ *
+ *  Copyright 2008 Pierre Ossman
+ *
+ * Based on code by Siano Mobile Silicon, Inc.,
+ * Copyright (C) 2006-2008, Uri Shkolnik
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 hardware is a bit odd in that all transfers should be done
+ * to/from the SMSSDIO_DATA register, yet the "increase address" bit
+ * always needs to be set.
+ *
+ * Also, buffers from the card are always aligned to 128 byte
+ * boundaries.
+ */
+
+/*
+ * General cleanup notes:
+ *
+ * - only typedefs should be name *_t
+ *
+ * - use ERR_PTR and friends for smscore_register_device()
+ *
+ * - smscore_getbuffer should zero fields
+ *
+ * Fix stop command
+ */
+
+#include <linux/moduleparam.h>
+#include <linux/slab.h>
+#include <linux/firmware.h>
+#include <linux/delay.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/sdio_func.h>
+#include <linux/mmc/sdio_ids.h>
+#include <linux/module.h>
+
+#include "smscoreapi.h"
+#include "sms-cards.h"
+
+/* Registers */
+
+#define SMSSDIO_DATA		0x00
+#define SMSSDIO_INT		0x04
+#define SMSSDIO_BLOCK_SIZE	128
+
+static const struct sdio_device_id smssdio_ids[] __devinitconst = {
+	{SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_STELLAR),
+	 .driver_data = SMS1XXX_BOARD_SIANO_STELLAR},
+	{SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_NOVA_A0),
+	 .driver_data = SMS1XXX_BOARD_SIANO_NOVA_A},
+	{SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_NOVA_B0),
+	 .driver_data = SMS1XXX_BOARD_SIANO_NOVA_B},
+	{SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_VEGA_A0),
+	 .driver_data = SMS1XXX_BOARD_SIANO_VEGA},
+	{SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_VENICE),
+	 .driver_data = SMS1XXX_BOARD_SIANO_VEGA},
+	{ /* end: all zeroes */ },
+};
+
+MODULE_DEVICE_TABLE(sdio, smssdio_ids);
+
+struct smssdio_device {
+	struct sdio_func *func;
+
+	struct smscore_device_t *coredev;
+
+	struct smscore_buffer_t *split_cb;
+};
+
+/*******************************************************************/
+/* Siano core callbacks                                            */
+/*******************************************************************/
+
+static int smssdio_sendrequest(void *context, void *buffer, size_t size)
+{
+	int ret = 0;
+	struct smssdio_device *smsdev;
+
+	smsdev = context;
+
+	sdio_claim_host(smsdev->func);
+
+	while (size >= smsdev->func->cur_blksize) {
+		ret = sdio_memcpy_toio(smsdev->func, SMSSDIO_DATA,
+					buffer, smsdev->func->cur_blksize);
+		if (ret)
+			goto out;
+
+		buffer += smsdev->func->cur_blksize;
+		size -= smsdev->func->cur_blksize;
+	}
+
+	if (size) {
+		ret = sdio_memcpy_toio(smsdev->func, SMSSDIO_DATA,
+					buffer, size);
+	}
+
+out:
+	sdio_release_host(smsdev->func);
+
+	return ret;
+}
+
+/*******************************************************************/
+/* SDIO callbacks                                                  */
+/*******************************************************************/
+
+static void smssdio_interrupt(struct sdio_func *func)
+{
+	int ret;
+
+	struct smssdio_device *smsdev;
+	struct smscore_buffer_t *cb;
+	struct SmsMsgHdr_ST *hdr;
+	size_t size;
+
+	smsdev = sdio_get_drvdata(func);
+
+	/*
+	 * The interrupt register has no defined meaning. It is just
+	 * a way of turning of the level triggered interrupt.
+	 */
+	(void)sdio_readb(func, SMSSDIO_INT, &ret);
+	if (ret) {
+		sms_err("Unable to read interrupt register!\n");
+		return;
+	}
+
+	if (smsdev->split_cb == NULL) {
+		cb = smscore_getbuffer(smsdev->coredev);
+		if (!cb) {
+			sms_err("Unable to allocate data buffer!\n");
+			return;
+		}
+
+		ret = sdio_memcpy_fromio(smsdev->func,
+					 cb->p,
+					 SMSSDIO_DATA,
+					 SMSSDIO_BLOCK_SIZE);
+		if (ret) {
+			sms_err("Error %d reading initial block!\n", ret);
+			return;
+		}
+
+		hdr = cb->p;
+
+		if (hdr->msgFlags & MSG_HDR_FLAG_SPLIT_MSG) {
+			smsdev->split_cb = cb;
+			return;
+		}
+
+		if (hdr->msgLength > smsdev->func->cur_blksize)
+			size = hdr->msgLength - smsdev->func->cur_blksize;
+		else
+			size = 0;
+	} else {
+		cb = smsdev->split_cb;
+		hdr = cb->p;
+
+		size = hdr->msgLength - sizeof(struct SmsMsgHdr_ST);
+
+		smsdev->split_cb = NULL;
+	}
+
+	if (size) {
+		void *buffer;
+
+		buffer = cb->p + (hdr->msgLength - size);
+		size = ALIGN(size, SMSSDIO_BLOCK_SIZE);
+
+		BUG_ON(smsdev->func->cur_blksize != SMSSDIO_BLOCK_SIZE);
+
+		/*
+		 * First attempt to transfer all of it in one go...
+		 */
+		ret = sdio_memcpy_fromio(smsdev->func,
+					 buffer,
+					 SMSSDIO_DATA,
+					 size);
+		if (ret && ret != -EINVAL) {
+			smscore_putbuffer(smsdev->coredev, cb);
+			sms_err("Error %d reading data from card!\n", ret);
+			return;
+		}
+
+		/*
+		 * ..then fall back to one block at a time if that is
+		 * not possible...
+		 *
+		 * (we have to do this manually because of the
+		 * problem with the "increase address" bit)
+		 */
+		if (ret == -EINVAL) {
+			while (size) {
+				ret = sdio_memcpy_fromio(smsdev->func,
+						  buffer, SMSSDIO_DATA,
+						  smsdev->func->cur_blksize);
+				if (ret) {
+					smscore_putbuffer(smsdev->coredev, cb);
+					sms_err("Error %d reading "
+						"data from card!\n", ret);
+					return;
+				}
+
+				buffer += smsdev->func->cur_blksize;
+				if (size > smsdev->func->cur_blksize)
+					size -= smsdev->func->cur_blksize;
+				else
+					size = 0;
+			}
+		}
+	}
+
+	cb->size = hdr->msgLength;
+	cb->offset = 0;
+
+	smscore_onresponse(smsdev->coredev, cb);
+}
+
+static int __devinit smssdio_probe(struct sdio_func *func,
+			 const struct sdio_device_id *id)
+{
+	int ret;
+
+	int board_id;
+	struct smssdio_device *smsdev;
+	struct smsdevice_params_t params;
+
+	board_id = id->driver_data;
+
+	smsdev = kzalloc(sizeof(struct smssdio_device), GFP_KERNEL);
+	if (!smsdev)
+		return -ENOMEM;
+
+	smsdev->func = func;
+
+	memset(&params, 0, sizeof(struct smsdevice_params_t));
+
+	params.device = &func->dev;
+	params.buffer_size = 0x5000;	/* ?? */
+	params.num_buffers = 22;	/* ?? */
+	params.context = smsdev;
+
+	snprintf(params.devpath, sizeof(params.devpath),
+		 "sdio\\%s", sdio_func_id(func));
+
+	params.sendrequest_handler = smssdio_sendrequest;
+
+	params.device_type = sms_get_board(board_id)->type;
+
+	if (params.device_type != SMS_STELLAR)
+		params.flags |= SMS_DEVICE_FAMILY2;
+	else {
+		/*
+		 * FIXME: Stellar needs special handling...
+		 */
+		ret = -ENODEV;
+		goto free;
+	}
+
+	ret = smscore_register_device(&params, &smsdev->coredev);
+	if (ret < 0)
+		goto free;
+
+	smscore_set_board_id(smsdev->coredev, board_id);
+
+	sdio_claim_host(func);
+
+	ret = sdio_enable_func(func);
+	if (ret)
+		goto release;
+
+	ret = sdio_set_block_size(func, SMSSDIO_BLOCK_SIZE);
+	if (ret)
+		goto disable;
+
+	ret = sdio_claim_irq(func, smssdio_interrupt);
+	if (ret)
+		goto disable;
+
+	sdio_set_drvdata(func, smsdev);
+
+	sdio_release_host(func);
+
+	ret = smscore_start_device(smsdev->coredev);
+	if (ret < 0)
+		goto reclaim;
+
+	return 0;
+
+reclaim:
+	sdio_claim_host(func);
+	sdio_release_irq(func);
+disable:
+	sdio_disable_func(func);
+release:
+	sdio_release_host(func);
+	smscore_unregister_device(smsdev->coredev);
+free:
+	kfree(smsdev);
+
+	return ret;
+}
+
+static void smssdio_remove(struct sdio_func *func)
+{
+	struct smssdio_device *smsdev;
+
+	smsdev = sdio_get_drvdata(func);
+
+	/* FIXME: racy! */
+	if (smsdev->split_cb)
+		smscore_putbuffer(smsdev->coredev, smsdev->split_cb);
+
+	smscore_unregister_device(smsdev->coredev);
+
+	sdio_claim_host(func);
+	sdio_release_irq(func);
+	sdio_disable_func(func);
+	sdio_release_host(func);
+
+	kfree(smsdev);
+}
+
+static struct sdio_driver smssdio_driver = {
+	.name = "smssdio",
+	.id_table = smssdio_ids,
+	.probe = smssdio_probe,
+	.remove = smssdio_remove,
+};
+
+/*******************************************************************/
+/* Module functions                                                */
+/*******************************************************************/
+
+static int __init smssdio_module_init(void)
+{
+	int ret = 0;
+
+	printk(KERN_INFO "smssdio: Siano SMS1xxx SDIO driver\n");
+	printk(KERN_INFO "smssdio: Copyright Pierre Ossman\n");
+
+	ret = sdio_register_driver(&smssdio_driver);
+
+	return ret;
+}
+
+static void __exit smssdio_module_exit(void)
+{
+	sdio_unregister_driver(&smssdio_driver);
+}
+
+module_init(smssdio_module_init);
+module_exit(smssdio_module_exit);
+
+MODULE_DESCRIPTION("Siano SMS1xxx SDIO driver");
+MODULE_AUTHOR("Pierre Ossman");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/parport/Kconfig b/drivers/media/parport/Kconfig
new file mode 100644
index 0000000..ece13dc
--- /dev/null
+++ b/drivers/media/parport/Kconfig
@@ -0,0 +1,52 @@
+menuconfig MEDIA_PARPORT_SUPPORT
+	bool "ISA and parallel port devices"
+	depends on (ISA || PARPORT) && MEDIA_CAMERA_SUPPORT
+	help
+	  Enables drivers for ISA and parallel port bus. If you
+	  need media drivers using those legacy buses, say Y.
+
+if MEDIA_PARPORT_SUPPORT
+config VIDEO_BWQCAM
+	tristate "Quickcam BW Video For Linux"
+	depends on PARPORT && VIDEO_V4L2
+	help
+	  Say Y have if you the black and white version of the QuickCam
+	  camera. See the next option for the color version.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called bw-qcam.
+
+config VIDEO_CQCAM
+	tristate "QuickCam Colour Video For Linux"
+	depends on PARPORT && VIDEO_V4L2
+	help
+	  This is the video4linux driver for the colour version of the
+	  Connectix QuickCam.  If you have one of these cameras, say Y here,
+	  otherwise say N.  This driver does not work with the original
+	  monochrome QuickCam, QuickCam VC or QuickClip.  It is also available
+	  as a module (c-qcam).
+	  Read <file:Documentation/video4linux/CQcam.txt> for more information.
+
+config VIDEO_PMS
+	tristate "Mediavision Pro Movie Studio Video For Linux"
+	depends on ISA && VIDEO_V4L2
+	help
+	  Say Y if you have the ISA Mediavision Pro Movie Studio
+	  capture card.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called pms.
+
+config VIDEO_W9966
+	tristate "W9966CF Webcam (FlyCam Supra and others) Video For Linux"
+	depends on PARPORT_1284 && PARPORT && VIDEO_V4L2
+	help
+	  Video4linux driver for Winbond's w9966 based Webcams.
+	  Currently tested with the LifeView FlyCam Supra.
+	  If you have one of these cameras, say Y here
+	  otherwise say N.
+	  This driver is also available as a module (w9966).
+
+	  Check out <file:Documentation/video4linux/w9966.txt> for more
+	  information.
+endif
diff --git a/drivers/media/parport/Makefile b/drivers/media/parport/Makefile
new file mode 100644
index 0000000..4eea06d
--- /dev/null
+++ b/drivers/media/parport/Makefile
@@ -0,0 +1,4 @@
+obj-$(CONFIG_VIDEO_CQCAM) += c-qcam.o
+obj-$(CONFIG_VIDEO_BWQCAM) += bw-qcam.o
+obj-$(CONFIG_VIDEO_W9966) += w9966.o
+obj-$(CONFIG_VIDEO_PMS) += pms.o
diff --git a/drivers/media/parport/bw-qcam.c b/drivers/media/parport/bw-qcam.c
new file mode 100644
index 0000000..5b75a64
--- /dev/null
+++ b/drivers/media/parport/bw-qcam.c
@@ -0,0 +1,1113 @@
+/*
+ *    QuickCam Driver For Video4Linux.
+ *
+ *	Video4Linux conversion work by Alan Cox.
+ *	Parport compatibility by Phil Blundell.
+ *	Busy loop avoidance by Mark Cooke.
+ *
+ *    Module parameters:
+ *
+ *	maxpoll=<1 - 5000>
+ *
+ *	  When polling the QuickCam for a response, busy-wait for a
+ *	  maximum of this many loops. The default of 250 gives little
+ *	  impact on interactive response.
+ *
+ *	  NOTE: If this parameter is set too high, the processor
+ *		will busy wait until this loop times out, and then
+ *		slowly poll for a further 5 seconds before failing
+ *		the transaction. You have been warned.
+ *
+ *	yieldlines=<1 - 250>
+ *
+ *	  When acquiring a frame from the camera, the data gathering
+ *	  loop will yield back to the scheduler after completing
+ *	  this many lines. The default of 4 provides a trade-off
+ *	  between increased frame acquisition time and impact on
+ *	  interactive response.
+ */
+
+/* qcam-lib.c -- Library for programming with the Connectix QuickCam.
+ * See the included documentation for usage instructions and details
+ * of the protocol involved. */
+
+
+/* Version 0.5, August 4, 1996 */
+/* Version 0.7, August 27, 1996 */
+/* Version 0.9, November 17, 1996 */
+
+
+/******************************************************************
+
+Copyright (C) 1996 by Scott Laird
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL SCOTT LAIRD BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/parport.h>
+#include <linux/sched.h>
+#include <linux/videodev2.h>
+#include <linux/mutex.h>
+#include <asm/uaccess.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-fh.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-event.h>
+
+/* One from column A... */
+#define QC_NOTSET 0
+#define QC_UNIDIR 1
+#define QC_BIDIR  2
+#define QC_SERIAL 3
+
+/* ... and one from column B */
+#define QC_ANY          0x00
+#define QC_FORCE_UNIDIR 0x10
+#define QC_FORCE_BIDIR  0x20
+#define QC_FORCE_SERIAL 0x30
+/* in the port_mode member */
+
+#define QC_MODE_MASK    0x07
+#define QC_FORCE_MASK   0x70
+
+#define MAX_HEIGHT 243
+#define MAX_WIDTH 336
+
+/* Bit fields for status flags */
+#define QC_PARAM_CHANGE	0x01 /* Camera status change has occurred */
+
+struct qcam {
+	struct v4l2_device v4l2_dev;
+	struct video_device vdev;
+	struct v4l2_ctrl_handler hdl;
+	struct pardevice *pdev;
+	struct parport *pport;
+	struct mutex lock;
+	int width, height;
+	int bpp;
+	int mode;
+	int contrast, brightness, whitebal;
+	int port_mode;
+	int transfer_scale;
+	int top, left;
+	int status;
+	unsigned int saved_bits;
+	unsigned long in_use;
+};
+
+static unsigned int maxpoll = 250;   /* Maximum busy-loop count for qcam I/O */
+static unsigned int yieldlines = 4;  /* Yield after this many during capture */
+static int video_nr = -1;
+static unsigned int force_init;		/* Whether to probe aggressively */
+
+module_param(maxpoll, int, 0);
+module_param(yieldlines, int, 0);
+module_param(video_nr, int, 0);
+
+/* Set force_init=1 to avoid detection by polling status register and
+ * immediately attempt to initialize qcam */
+module_param(force_init, int, 0);
+
+#define MAX_CAMS 4
+static struct qcam *qcams[MAX_CAMS];
+static unsigned int num_cams;
+
+static inline int read_lpstatus(struct qcam *q)
+{
+	return parport_read_status(q->pport);
+}
+
+static inline int read_lpdata(struct qcam *q)
+{
+	return parport_read_data(q->pport);
+}
+
+static inline void write_lpdata(struct qcam *q, int d)
+{
+	parport_write_data(q->pport, d);
+}
+
+static void write_lpcontrol(struct qcam *q, int d)
+{
+	if (d & 0x20) {
+		/* Set bidirectional mode to reverse (data in) */
+		parport_data_reverse(q->pport);
+	} else {
+		/* Set bidirectional mode to forward (data out) */
+		parport_data_forward(q->pport);
+	}
+
+	/* Now issue the regular port command, but strip out the
+	 * direction flag */
+	d &= ~0x20;
+	parport_write_control(q->pport, d);
+}
+
+
+/* qc_waithand busy-waits for a handshake signal from the QuickCam.
+ * Almost all communication with the camera requires handshaking. */
+
+static int qc_waithand(struct qcam *q, int val)
+{
+	int status;
+	int runs = 0;
+
+	if (val) {
+		while (!((status = read_lpstatus(q)) & 8)) {
+			/* 1000 is enough spins on the I/O for all normal
+			   cases, at that point we start to poll slowly
+			   until the camera wakes up. However, we are
+			   busy blocked until the camera responds, so
+			   setting it lower is much better for interactive
+			   response. */
+
+			if (runs++ > maxpoll)
+				msleep_interruptible(5);
+			if (runs > (maxpoll + 1000)) /* 5 seconds */
+				return -1;
+		}
+	} else {
+		while (((status = read_lpstatus(q)) & 8)) {
+			/* 1000 is enough spins on the I/O for all normal
+			   cases, at that point we start to poll slowly
+			   until the camera wakes up. However, we are
+			   busy blocked until the camera responds, so
+			   setting it lower is much better for interactive
+			   response. */
+
+			if (runs++ > maxpoll)
+				msleep_interruptible(5);
+			if (runs++ > (maxpoll + 1000)) /* 5 seconds */
+				return -1;
+		}
+	}
+
+	return status;
+}
+
+/* Waithand2 is used when the qcam is in bidirectional mode, and the
+ * handshaking signal is CamRdy2 (bit 0 of data reg) instead of CamRdy1
+ * (bit 3 of status register).  It also returns the last value read,
+ * since this data is useful. */
+
+static unsigned int qc_waithand2(struct qcam *q, int val)
+{
+	unsigned int status;
+	int runs = 0;
+
+	do {
+		status = read_lpdata(q);
+		/* 1000 is enough spins on the I/O for all normal
+		   cases, at that point we start to poll slowly
+		   until the camera wakes up. However, we are
+		   busy blocked until the camera responds, so
+		   setting it lower is much better for interactive
+		   response. */
+
+		if (runs++ > maxpoll)
+			msleep_interruptible(5);
+		if (runs++ > (maxpoll + 1000)) /* 5 seconds */
+			return 0;
+	} while ((status & 1) != val);
+
+	return status;
+}
+
+/* qc_command is probably a bit of a misnomer -- it's used to send
+ * bytes *to* the camera.  Generally, these bytes are either commands
+ * or arguments to commands, so the name fits, but it still bugs me a
+ * bit.  See the documentation for a list of commands. */
+
+static int qc_command(struct qcam *q, int command)
+{
+	int n1, n2;
+	int cmd;
+
+	write_lpdata(q, command);
+	write_lpcontrol(q, 6);
+
+	n1 = qc_waithand(q, 1);
+
+	write_lpcontrol(q, 0xe);
+	n2 = qc_waithand(q, 0);
+
+	cmd = (n1 & 0xf0) | ((n2 & 0xf0) >> 4);
+	return cmd;
+}
+
+static int qc_readparam(struct qcam *q)
+{
+	int n1, n2;
+	int cmd;
+
+	write_lpcontrol(q, 6);
+	n1 = qc_waithand(q, 1);
+
+	write_lpcontrol(q, 0xe);
+	n2 = qc_waithand(q, 0);
+
+	cmd = (n1 & 0xf0) | ((n2 & 0xf0) >> 4);
+	return cmd;
+}
+
+
+/* Try to detect a QuickCam.  It appears to flash the upper 4 bits of
+   the status register at 5-10 Hz.  This is only used in the autoprobe
+   code.  Be aware that this isn't the way Connectix detects the
+   camera (they send a reset and try to handshake), but this should be
+   almost completely safe, while their method screws up my printer if
+   I plug it in before the camera. */
+
+static int qc_detect(struct qcam *q)
+{
+	int reg, lastreg;
+	int count = 0;
+	int i;
+
+	if (force_init)
+		return 1;
+
+	lastreg = reg = read_lpstatus(q) & 0xf0;
+
+	for (i = 0; i < 500; i++) {
+		reg = read_lpstatus(q) & 0xf0;
+		if (reg != lastreg)
+			count++;
+		lastreg = reg;
+		mdelay(2);
+	}
+
+
+#if 0
+	/* Force camera detection during testing. Sometimes the camera
+	   won't be flashing these bits. Possibly unloading the module
+	   in the middle of a grab? Or some timeout condition?
+	   I've seen this parameter as low as 19 on my 450Mhz box - mpc */
+	printk(KERN_DEBUG "Debugging: QCam detection counter <30-200 counts as detected>: %d\n", count);
+	return 1;
+#endif
+
+	/* Be (even more) liberal in what you accept...  */
+
+	if (count > 20 && count < 400) {
+		return 1;	/* found */
+	} else {
+		printk(KERN_ERR "No Quickcam found on port %s\n",
+				q->pport->name);
+		printk(KERN_DEBUG "Quickcam detection counter: %u\n", count);
+		return 0;	/* not found */
+	}
+}
+
+/* Decide which scan mode to use.  There's no real requirement that
+ * the scanmode match the resolution in q->height and q-> width -- the
+ * camera takes the picture at the resolution specified in the
+ * "scanmode" and then returns the image at the resolution specified
+ * with the resolution commands.  If the scan is bigger than the
+ * requested resolution, the upper-left hand corner of the scan is
+ * returned.  If the scan is smaller, then the rest of the image
+ * returned contains garbage. */
+
+static int qc_setscanmode(struct qcam *q)
+{
+	int old_mode = q->mode;
+
+	switch (q->transfer_scale) {
+	case 1:
+		q->mode = 0;
+		break;
+	case 2:
+		q->mode = 4;
+		break;
+	case 4:
+		q->mode = 8;
+		break;
+	}
+
+	switch (q->bpp) {
+	case 4:
+		break;
+	case 6:
+		q->mode += 2;
+		break;
+	}
+
+	switch (q->port_mode & QC_MODE_MASK) {
+	case QC_BIDIR:
+		q->mode += 1;
+		break;
+	case QC_NOTSET:
+	case QC_UNIDIR:
+		break;
+	}
+
+	if (q->mode != old_mode)
+		q->status |= QC_PARAM_CHANGE;
+
+	return 0;
+}
+
+
+/* Reset the QuickCam.  This uses the same sequence the Windows
+ * QuickPic program uses.  Someone with a bi-directional port should
+ * check that bi-directional mode is detected right, and then
+ * implement bi-directional mode in qc_readbyte(). */
+
+static void qc_reset(struct qcam *q)
+{
+	switch (q->port_mode & QC_FORCE_MASK) {
+	case QC_FORCE_UNIDIR:
+		q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_UNIDIR;
+		break;
+
+	case QC_FORCE_BIDIR:
+		q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_BIDIR;
+		break;
+
+	case QC_ANY:
+		write_lpcontrol(q, 0x20);
+		write_lpdata(q, 0x75);
+
+		if (read_lpdata(q) != 0x75)
+			q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_BIDIR;
+		else
+			q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_UNIDIR;
+		break;
+	}
+
+	write_lpcontrol(q, 0xb);
+	udelay(250);
+	write_lpcontrol(q, 0xe);
+	qc_setscanmode(q);		/* in case port_mode changed */
+}
+
+
+
+/* Reset the QuickCam and program for brightness, contrast,
+ * white-balance, and resolution. */
+
+static void qc_set(struct qcam *q)
+{
+	int val;
+	int val2;
+
+	qc_reset(q);
+
+	/* Set the brightness.  Yes, this is repetitive, but it works.
+	 * Shorter versions seem to fail subtly.  Feel free to try :-). */
+	/* I think the problem was in qc_command, not here -- bls */
+
+	qc_command(q, 0xb);
+	qc_command(q, q->brightness);
+
+	val = q->height / q->transfer_scale;
+	qc_command(q, 0x11);
+	qc_command(q, val);
+	if ((q->port_mode & QC_MODE_MASK) == QC_UNIDIR && q->bpp == 6) {
+		/* The normal "transfers per line" calculation doesn't seem to work
+		   as expected here (and yet it works fine in qc_scan).  No idea
+		   why this case is the odd man out.  Fortunately, Laird's original
+		   working version gives me a good way to guess at working values.
+		   -- bls */
+		val = q->width;
+		val2 = q->transfer_scale * 4;
+	} else {
+		val = q->width * q->bpp;
+		val2 = (((q->port_mode & QC_MODE_MASK) == QC_BIDIR) ? 24 : 8) *
+			q->transfer_scale;
+	}
+	val = DIV_ROUND_UP(val, val2);
+	qc_command(q, 0x13);
+	qc_command(q, val);
+
+	/* Setting top and left -- bls */
+	qc_command(q, 0xd);
+	qc_command(q, q->top);
+	qc_command(q, 0xf);
+	qc_command(q, q->left / 2);
+
+	qc_command(q, 0x19);
+	qc_command(q, q->contrast);
+	qc_command(q, 0x1f);
+	qc_command(q, q->whitebal);
+
+	/* Clear flag that we must update the grabbing parameters on the camera
+	   before we grab the next frame */
+	q->status &= (~QC_PARAM_CHANGE);
+}
+
+/* Qc_readbytes reads some bytes from the QC and puts them in
+   the supplied buffer.  It returns the number of bytes read,
+   or -1 on error. */
+
+static inline int qc_readbytes(struct qcam *q, char buffer[])
+{
+	int ret = 1;
+	unsigned int hi, lo;
+	unsigned int hi2, lo2;
+	static int state;
+
+	if (buffer == NULL) {
+		state = 0;
+		return 0;
+	}
+
+	switch (q->port_mode & QC_MODE_MASK) {
+	case QC_BIDIR:		/* Bi-directional Port */
+		write_lpcontrol(q, 0x26);
+		lo = (qc_waithand2(q, 1) >> 1);
+		hi = (read_lpstatus(q) >> 3) & 0x1f;
+		write_lpcontrol(q, 0x2e);
+		lo2 = (qc_waithand2(q, 0) >> 1);
+		hi2 = (read_lpstatus(q) >> 3) & 0x1f;
+		switch (q->bpp) {
+		case 4:
+			buffer[0] = lo & 0xf;
+			buffer[1] = ((lo & 0x70) >> 4) | ((hi & 1) << 3);
+			buffer[2] = (hi & 0x1e) >> 1;
+			buffer[3] = lo2 & 0xf;
+			buffer[4] = ((lo2 & 0x70) >> 4) | ((hi2 & 1) << 3);
+			buffer[5] = (hi2 & 0x1e) >> 1;
+			ret = 6;
+			break;
+		case 6:
+			buffer[0] = lo & 0x3f;
+			buffer[1] = ((lo & 0x40) >> 6) | (hi << 1);
+			buffer[2] = lo2 & 0x3f;
+			buffer[3] = ((lo2 & 0x40) >> 6) | (hi2 << 1);
+			ret = 4;
+			break;
+		}
+		break;
+
+	case QC_UNIDIR:	/* Unidirectional Port */
+		write_lpcontrol(q, 6);
+		lo = (qc_waithand(q, 1) & 0xf0) >> 4;
+		write_lpcontrol(q, 0xe);
+		hi = (qc_waithand(q, 0) & 0xf0) >> 4;
+
+		switch (q->bpp) {
+		case 4:
+			buffer[0] = lo;
+			buffer[1] = hi;
+			ret = 2;
+			break;
+		case 6:
+			switch (state) {
+			case 0:
+				buffer[0] = (lo << 2) | ((hi & 0xc) >> 2);
+				q->saved_bits = (hi & 3) << 4;
+				state = 1;
+				ret = 1;
+				break;
+			case 1:
+				buffer[0] = lo | q->saved_bits;
+				q->saved_bits = hi << 2;
+				state = 2;
+				ret = 1;
+				break;
+			case 2:
+				buffer[0] = ((lo & 0xc) >> 2) | q->saved_bits;
+				buffer[1] = ((lo & 3) << 4) | hi;
+				state = 0;
+				ret = 2;
+				break;
+			}
+			break;
+		}
+		break;
+	}
+	return ret;
+}
+
+/* requests a scan from the camera.  It sends the correct instructions
+ * to the camera and then reads back the correct number of bytes.  In
+ * previous versions of this routine the return structure contained
+ * the raw output from the camera, and there was a 'qc_convertscan'
+ * function that converted that to a useful format.  In version 0.3 I
+ * rolled qc_convertscan into qc_scan and now I only return the
+ * converted scan.  The format is just an one-dimensional array of
+ * characters, one for each pixel, with 0=black up to n=white, where
+ * n=2^(bit depth)-1.  Ask me for more details if you don't understand
+ * this. */
+
+static long qc_capture(struct qcam *q, char __user *buf, unsigned long len)
+{
+	int i, j, k, yield;
+	int bytes;
+	int linestotrans, transperline;
+	int divisor;
+	int pixels_per_line;
+	int pixels_read = 0;
+	int got = 0;
+	char buffer[6];
+	int  shift = 8 - q->bpp;
+	char invert;
+
+	if (q->mode == -1)
+		return -ENXIO;
+
+	qc_command(q, 0x7);
+	qc_command(q, q->mode);
+
+	if ((q->port_mode & QC_MODE_MASK) == QC_BIDIR) {
+		write_lpcontrol(q, 0x2e);	/* turn port around */
+		write_lpcontrol(q, 0x26);
+		qc_waithand(q, 1);
+		write_lpcontrol(q, 0x2e);
+		qc_waithand(q, 0);
+	}
+
+	/* strange -- should be 15:63 below, but 4bpp is odd */
+	invert = (q->bpp == 4) ? 16 : 63;
+
+	linestotrans = q->height / q->transfer_scale;
+	pixels_per_line = q->width / q->transfer_scale;
+	transperline = q->width * q->bpp;
+	divisor = (((q->port_mode & QC_MODE_MASK) == QC_BIDIR) ? 24 : 8) *
+		q->transfer_scale;
+	transperline = DIV_ROUND_UP(transperline, divisor);
+
+	for (i = 0, yield = yieldlines; i < linestotrans; i++) {
+		for (pixels_read = j = 0; j < transperline; j++) {
+			bytes = qc_readbytes(q, buffer);
+			for (k = 0; k < bytes && (pixels_read + k) < pixels_per_line; k++) {
+				int o;
+				if (buffer[k] == 0 && invert == 16) {
+					/* 4bpp is odd (again) -- inverter is 16, not 15, but output
+					   must be 0-15 -- bls */
+					buffer[k] = 16;
+				}
+				o = i * pixels_per_line + pixels_read + k;
+				if (o < len) {
+					u8 ch = invert - buffer[k];
+					got++;
+					put_user(ch << shift, buf + o);
+				}
+			}
+			pixels_read += bytes;
+		}
+		qc_readbytes(q, NULL);	/* reset state machine */
+
+		/* Grabbing an entire frame from the quickcam is a lengthy
+		   process. We don't (usually) want to busy-block the
+		   processor for the entire frame. yieldlines is a module
+		   parameter. If we yield every line, the minimum frame
+		   time will be 240 / 200 = 1.2 seconds. The compile-time
+		   default is to yield every 4 lines. */
+		if (i >= yield) {
+			msleep_interruptible(5);
+			yield = i + yieldlines;
+		}
+	}
+
+	if ((q->port_mode & QC_MODE_MASK) == QC_BIDIR) {
+		write_lpcontrol(q, 2);
+		write_lpcontrol(q, 6);
+		udelay(3);
+		write_lpcontrol(q, 0xe);
+	}
+	if (got < len)
+		return got;
+	return len;
+}
+
+/*
+ *	Video4linux interfacing
+ */
+
+static int qcam_querycap(struct file *file, void  *priv,
+					struct v4l2_capability *vcap)
+{
+	struct qcam *qcam = video_drvdata(file);
+
+	strlcpy(vcap->driver, qcam->v4l2_dev.name, sizeof(vcap->driver));
+	strlcpy(vcap->card, "Connectix B&W Quickcam", sizeof(vcap->card));
+	strlcpy(vcap->bus_info, qcam->pport->name, sizeof(vcap->bus_info));
+	vcap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE;
+	vcap->capabilities = vcap->device_caps | V4L2_CAP_DEVICE_CAPS;
+	return 0;
+}
+
+static int qcam_enum_input(struct file *file, void *fh, struct v4l2_input *vin)
+{
+	if (vin->index > 0)
+		return -EINVAL;
+	strlcpy(vin->name, "Camera", sizeof(vin->name));
+	vin->type = V4L2_INPUT_TYPE_CAMERA;
+	vin->audioset = 0;
+	vin->tuner = 0;
+	vin->std = 0;
+	vin->status = 0;
+	return 0;
+}
+
+static int qcam_g_input(struct file *file, void *fh, unsigned int *inp)
+{
+	*inp = 0;
+	return 0;
+}
+
+static int qcam_s_input(struct file *file, void *fh, unsigned int inp)
+{
+	return (inp > 0) ? -EINVAL : 0;
+}
+
+static int qcam_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+	struct qcam *qcam = video_drvdata(file);
+	struct v4l2_pix_format *pix = &fmt->fmt.pix;
+
+	pix->width = qcam->width / qcam->transfer_scale;
+	pix->height = qcam->height / qcam->transfer_scale;
+	pix->pixelformat = (qcam->bpp == 4) ? V4L2_PIX_FMT_Y4 : V4L2_PIX_FMT_Y6;
+	pix->field = V4L2_FIELD_NONE;
+	pix->bytesperline = pix->width;
+	pix->sizeimage = pix->width * pix->height;
+	/* Just a guess */
+	pix->colorspace = V4L2_COLORSPACE_SRGB;
+	return 0;
+}
+
+static int qcam_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+	struct v4l2_pix_format *pix = &fmt->fmt.pix;
+
+	if (pix->height <= 60 || pix->width <= 80) {
+		pix->height = 60;
+		pix->width = 80;
+	} else if (pix->height <= 120 || pix->width <= 160) {
+		pix->height = 120;
+		pix->width = 160;
+	} else {
+		pix->height = 240;
+		pix->width = 320;
+	}
+	if (pix->pixelformat != V4L2_PIX_FMT_Y4 &&
+	    pix->pixelformat != V4L2_PIX_FMT_Y6)
+		pix->pixelformat = V4L2_PIX_FMT_Y4;
+	pix->field = V4L2_FIELD_NONE;
+	pix->bytesperline = pix->width;
+	pix->sizeimage = pix->width * pix->height;
+	/* Just a guess */
+	pix->colorspace = V4L2_COLORSPACE_SRGB;
+	return 0;
+}
+
+static int qcam_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+	struct qcam *qcam = video_drvdata(file);
+	struct v4l2_pix_format *pix = &fmt->fmt.pix;
+	int ret = qcam_try_fmt_vid_cap(file, fh, fmt);
+
+	if (ret)
+		return ret;
+	qcam->width = 320;
+	qcam->height = 240;
+	if (pix->height == 60)
+		qcam->transfer_scale = 4;
+	else if (pix->height == 120)
+		qcam->transfer_scale = 2;
+	else
+		qcam->transfer_scale = 1;
+	if (pix->pixelformat == V4L2_PIX_FMT_Y6)
+		qcam->bpp = 6;
+	else
+		qcam->bpp = 4;
+
+	mutex_lock(&qcam->lock);
+	qc_setscanmode(qcam);
+	/* We must update the camera before we grab. We could
+	   just have changed the grab size */
+	qcam->status |= QC_PARAM_CHANGE;
+	mutex_unlock(&qcam->lock);
+	return 0;
+}
+
+static int qcam_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt)
+{
+	static struct v4l2_fmtdesc formats[] = {
+		{ 0, 0, 0,
+		  "4-Bit Monochrome", V4L2_PIX_FMT_Y4,
+		  { 0, 0, 0, 0 }
+		},
+		{ 1, 0, 0,
+		  "6-Bit Monochrome", V4L2_PIX_FMT_Y6,
+		  { 0, 0, 0, 0 }
+		},
+	};
+	enum v4l2_buf_type type = fmt->type;
+
+	if (fmt->index > 1)
+		return -EINVAL;
+
+	*fmt = formats[fmt->index];
+	fmt->type = type;
+	return 0;
+}
+
+static int qcam_enum_framesizes(struct file *file, void *fh,
+					 struct v4l2_frmsizeenum *fsize)
+{
+	static const struct v4l2_frmsize_discrete sizes[] = {
+		{  80,  60 },
+		{ 160, 120 },
+		{ 320, 240 },
+	};
+
+	if (fsize->index > 2)
+		return -EINVAL;
+	if (fsize->pixel_format != V4L2_PIX_FMT_Y4 &&
+	    fsize->pixel_format != V4L2_PIX_FMT_Y6)
+		return -EINVAL;
+	fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
+	fsize->discrete = sizes[fsize->index];
+	return 0;
+}
+
+static ssize_t qcam_read(struct file *file, char __user *buf,
+		size_t count, loff_t *ppos)
+{
+	struct qcam *qcam = video_drvdata(file);
+	int len;
+	parport_claim_or_block(qcam->pdev);
+
+	mutex_lock(&qcam->lock);
+
+	qc_reset(qcam);
+
+	/* Update the camera parameters if we need to */
+	if (qcam->status & QC_PARAM_CHANGE)
+		qc_set(qcam);
+
+	len = qc_capture(qcam, buf, count);
+
+	mutex_unlock(&qcam->lock);
+
+	parport_release(qcam->pdev);
+	return len;
+}
+
+static unsigned int qcam_poll(struct file *filp, poll_table *wait)
+{
+	return v4l2_ctrl_poll(filp, wait) | POLLIN | POLLRDNORM;
+}
+
+static int qcam_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct qcam *qcam =
+		container_of(ctrl->handler, struct qcam, hdl);
+	int ret = 0;
+
+	mutex_lock(&qcam->lock);
+	switch (ctrl->id) {
+	case V4L2_CID_BRIGHTNESS:
+		qcam->brightness = ctrl->val;
+		break;
+	case V4L2_CID_CONTRAST:
+		qcam->contrast = ctrl->val;
+		break;
+	case V4L2_CID_GAMMA:
+		qcam->whitebal = ctrl->val;
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+	if (ret == 0) {
+		qc_setscanmode(qcam);
+		qcam->status |= QC_PARAM_CHANGE;
+	}
+	mutex_unlock(&qcam->lock);
+	return ret;
+}
+
+static const struct v4l2_file_operations qcam_fops = {
+	.owner		= THIS_MODULE,
+	.open		= v4l2_fh_open,
+	.release	= v4l2_fh_release,
+	.poll		= qcam_poll,
+	.unlocked_ioctl = video_ioctl2,
+	.read		= qcam_read,
+};
+
+static const struct v4l2_ioctl_ops qcam_ioctl_ops = {
+	.vidioc_querycap    		    = qcam_querycap,
+	.vidioc_g_input      		    = qcam_g_input,
+	.vidioc_s_input      		    = qcam_s_input,
+	.vidioc_enum_input   		    = qcam_enum_input,
+	.vidioc_enum_fmt_vid_cap 	    = qcam_enum_fmt_vid_cap,
+	.vidioc_enum_framesizes		    = qcam_enum_framesizes,
+	.vidioc_g_fmt_vid_cap 		    = qcam_g_fmt_vid_cap,
+	.vidioc_s_fmt_vid_cap  		    = qcam_s_fmt_vid_cap,
+	.vidioc_try_fmt_vid_cap  	    = qcam_try_fmt_vid_cap,
+	.vidioc_log_status		    = v4l2_ctrl_log_status,
+	.vidioc_subscribe_event		    = v4l2_ctrl_subscribe_event,
+	.vidioc_unsubscribe_event	    = v4l2_event_unsubscribe,
+};
+
+static const struct v4l2_ctrl_ops qcam_ctrl_ops = {
+	.s_ctrl = qcam_s_ctrl,
+};
+
+/* Initialize the QuickCam driver control structure.  This is where
+ * defaults are set for people who don't have a config file.*/
+
+static struct qcam *qcam_init(struct parport *port)
+{
+	struct qcam *qcam;
+	struct v4l2_device *v4l2_dev;
+
+	qcam = kzalloc(sizeof(struct qcam), GFP_KERNEL);
+	if (qcam == NULL)
+		return NULL;
+
+	v4l2_dev = &qcam->v4l2_dev;
+	snprintf(v4l2_dev->name, sizeof(v4l2_dev->name), "bw-qcam%d", num_cams);
+
+	if (v4l2_device_register(port->dev, v4l2_dev) < 0) {
+		v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
+		kfree(qcam);
+		return NULL;
+	}
+
+	v4l2_ctrl_handler_init(&qcam->hdl, 3);
+	v4l2_ctrl_new_std(&qcam->hdl, &qcam_ctrl_ops,
+			  V4L2_CID_BRIGHTNESS, 0, 255, 1, 180);
+	v4l2_ctrl_new_std(&qcam->hdl, &qcam_ctrl_ops,
+			  V4L2_CID_CONTRAST, 0, 255, 1, 192);
+	v4l2_ctrl_new_std(&qcam->hdl, &qcam_ctrl_ops,
+			  V4L2_CID_GAMMA, 0, 255, 1, 105);
+	if (qcam->hdl.error) {
+		v4l2_err(v4l2_dev, "couldn't register controls\n");
+		v4l2_ctrl_handler_free(&qcam->hdl);
+		kfree(qcam);
+		return NULL;
+	}
+	qcam->pport = port;
+	qcam->pdev = parport_register_device(port, v4l2_dev->name, NULL, NULL,
+			NULL, 0, NULL);
+	if (qcam->pdev == NULL) {
+		v4l2_err(v4l2_dev, "couldn't register for %s.\n", port->name);
+		v4l2_ctrl_handler_free(&qcam->hdl);
+		kfree(qcam);
+		return NULL;
+	}
+
+	strlcpy(qcam->vdev.name, "Connectix QuickCam", sizeof(qcam->vdev.name));
+	qcam->vdev.v4l2_dev = v4l2_dev;
+	qcam->vdev.ctrl_handler = &qcam->hdl;
+	qcam->vdev.fops = &qcam_fops;
+	qcam->vdev.ioctl_ops = &qcam_ioctl_ops;
+	set_bit(V4L2_FL_USE_FH_PRIO, &qcam->vdev.flags);
+	qcam->vdev.release = video_device_release_empty;
+	video_set_drvdata(&qcam->vdev, qcam);
+
+	mutex_init(&qcam->lock);
+
+	qcam->port_mode = (QC_ANY | QC_NOTSET);
+	qcam->width = 320;
+	qcam->height = 240;
+	qcam->bpp = 4;
+	qcam->transfer_scale = 2;
+	qcam->contrast = 192;
+	qcam->brightness = 180;
+	qcam->whitebal = 105;
+	qcam->top = 1;
+	qcam->left = 14;
+	qcam->mode = -1;
+	qcam->status = QC_PARAM_CHANGE;
+	return qcam;
+}
+
+static int qc_calibrate(struct qcam *q)
+{
+	/*
+	 *	Bugfix by Hanno Mueller hmueller@kabel.de, Mai 21 96
+	 *	The white balance is an individual value for each
+	 *	quickcam.
+	 */
+
+	int value;
+	int count = 0;
+
+	qc_command(q, 27);	/* AutoAdjustOffset */
+	qc_command(q, 0);	/* Dummy Parameter, ignored by the camera */
+
+	/* GetOffset (33) will read 255 until autocalibration */
+	/* is finished. After that, a value of 1-254 will be */
+	/* returned. */
+
+	do {
+		qc_command(q, 33);
+		value = qc_readparam(q);
+		mdelay(1);
+		schedule();
+		count++;
+	} while (value == 0xff && count < 2048);
+
+	q->whitebal = value;
+	return value;
+}
+
+static int init_bwqcam(struct parport *port)
+{
+	struct qcam *qcam;
+
+	if (num_cams == MAX_CAMS) {
+		printk(KERN_ERR "Too many Quickcams (max %d)\n", MAX_CAMS);
+		return -ENOSPC;
+	}
+
+	qcam = qcam_init(port);
+	if (qcam == NULL)
+		return -ENODEV;
+
+	parport_claim_or_block(qcam->pdev);
+
+	qc_reset(qcam);
+
+	if (qc_detect(qcam) == 0) {
+		parport_release(qcam->pdev);
+		parport_unregister_device(qcam->pdev);
+		kfree(qcam);
+		return -ENODEV;
+	}
+	qc_calibrate(qcam);
+	v4l2_ctrl_handler_setup(&qcam->hdl);
+
+	parport_release(qcam->pdev);
+
+	v4l2_info(&qcam->v4l2_dev, "Connectix Quickcam on %s\n", qcam->pport->name);
+
+	if (video_register_device(&qcam->vdev, VFL_TYPE_GRABBER, video_nr) < 0) {
+		parport_unregister_device(qcam->pdev);
+		kfree(qcam);
+		return -ENODEV;
+	}
+
+	qcams[num_cams++] = qcam;
+
+	return 0;
+}
+
+static void close_bwqcam(struct qcam *qcam)
+{
+	video_unregister_device(&qcam->vdev);
+	v4l2_ctrl_handler_free(&qcam->hdl);
+	parport_unregister_device(qcam->pdev);
+	kfree(qcam);
+}
+
+/* The parport parameter controls which parports will be scanned.
+ * Scanning all parports causes some printers to print a garbage page.
+ *       -- March 14, 1999  Billy Donahue <billy@escape.com> */
+#ifdef MODULE
+static char *parport[MAX_CAMS] = { NULL, };
+module_param_array(parport, charp, NULL, 0);
+#endif
+
+static int accept_bwqcam(struct parport *port)
+{
+#ifdef MODULE
+	int n;
+
+	if (parport[0] && strncmp(parport[0], "auto", 4) != 0) {
+		/* user gave parport parameters */
+		for (n = 0; n < MAX_CAMS && parport[n]; n++) {
+			char *ep;
+			unsigned long r;
+			r = simple_strtoul(parport[n], &ep, 0);
+			if (ep == parport[n]) {
+				printk(KERN_ERR
+					"bw-qcam: bad port specifier \"%s\"\n",
+					parport[n]);
+				continue;
+			}
+			if (r == port->number)
+				return 1;
+		}
+		return 0;
+	}
+#endif
+	return 1;
+}
+
+static void bwqcam_attach(struct parport *port)
+{
+	if (accept_bwqcam(port))
+		init_bwqcam(port);
+}
+
+static void bwqcam_detach(struct parport *port)
+{
+	int i;
+	for (i = 0; i < num_cams; i++) {
+		struct qcam *qcam = qcams[i];
+		if (qcam && qcam->pdev->port == port) {
+			qcams[i] = NULL;
+			close_bwqcam(qcam);
+		}
+	}
+}
+
+static struct parport_driver bwqcam_driver = {
+	.name	= "bw-qcam",
+	.attach	= bwqcam_attach,
+	.detach	= bwqcam_detach,
+};
+
+static void __exit exit_bw_qcams(void)
+{
+	parport_unregister_driver(&bwqcam_driver);
+}
+
+static int __init init_bw_qcams(void)
+{
+#ifdef MODULE
+	/* Do some sanity checks on the module parameters. */
+	if (maxpoll > 5000) {
+		printk(KERN_INFO "Connectix Quickcam max-poll was above 5000. Using 5000.\n");
+		maxpoll = 5000;
+	}
+
+	if (yieldlines < 1) {
+		printk(KERN_INFO "Connectix Quickcam yieldlines was less than 1. Using 1.\n");
+		yieldlines = 1;
+	}
+#endif
+	return parport_register_driver(&bwqcam_driver);
+}
+
+module_init(init_bw_qcams);
+module_exit(exit_bw_qcams);
+
+MODULE_LICENSE("GPL");
+MODULE_VERSION("0.0.3");
diff --git a/drivers/media/parport/c-qcam.c b/drivers/media/parport/c-qcam.c
new file mode 100644
index 0000000..ec51e1f
--- /dev/null
+++ b/drivers/media/parport/c-qcam.c
@@ -0,0 +1,883 @@
+/*
+ *	Video4Linux Colour QuickCam driver
+ *	Copyright 1997-2000 Philip Blundell <philb@gnu.org>
+ *
+ *    Module parameters:
+ *
+ *	parport=auto      -- probe all parports (default)
+ *	parport=0         -- parport0 becomes qcam1
+ *	parport=2,0,1     -- parports 2,0,1 are tried in that order
+ *
+ *	probe=0		  -- do no probing, assume camera is present
+ *	probe=1		  -- use IEEE-1284 autoprobe data only (default)
+ *	probe=2		  -- probe aggressively for cameras
+ *
+ *	force_rgb=1       -- force data format to RGB (default is BGR)
+ *
+ * The parport parameter controls which parports will be scanned.
+ * Scanning all parports causes some printers to print a garbage page.
+ *       -- March 14, 1999  Billy Donahue <billy@escape.com>
+ *
+ * Fixed data format to BGR, added force_rgb parameter. Added missing
+ * parport_unregister_driver() on module removal.
+ *       -- May 28, 2000  Claudio Matsuoka <claudio@conectiva.com>
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/parport.h>
+#include <linux/sched.h>
+#include <linux/mutex.h>
+#include <linux/jiffies.h>
+#include <linux/videodev2.h>
+#include <asm/uaccess.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-fh.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-event.h>
+
+struct qcam {
+	struct v4l2_device v4l2_dev;
+	struct video_device vdev;
+	struct v4l2_ctrl_handler hdl;
+	struct pardevice *pdev;
+	struct parport *pport;
+	int width, height;
+	int ccd_width, ccd_height;
+	int mode;
+	int contrast, brightness, whitebal;
+	int top, left;
+	unsigned int bidirectional;
+	struct mutex lock;
+};
+
+/* cameras maximum */
+#define MAX_CAMS 4
+
+/* The three possible QuickCam modes */
+#define QC_MILLIONS	0x18
+#define QC_BILLIONS	0x10
+#define QC_THOUSANDS	0x08	/* with VIDEC compression (not supported) */
+
+/* The three possible decimations */
+#define QC_DECIMATION_1		0
+#define QC_DECIMATION_2		2
+#define QC_DECIMATION_4		4
+
+#define BANNER "Colour QuickCam for Video4Linux v0.06"
+
+static int parport[MAX_CAMS] = { [1 ... MAX_CAMS-1] = -1 };
+static int probe = 2;
+static bool force_rgb;
+static int video_nr = -1;
+
+/* FIXME: parport=auto would never have worked, surely? --RR */
+MODULE_PARM_DESC(parport, "parport=<auto|n[,n]...> for port detection method\n"
+			  "probe=<0|1|2> for camera detection method\n"
+			  "force_rgb=<0|1> for RGB data format (default BGR)");
+module_param_array(parport, int, NULL, 0);
+module_param(probe, int, 0);
+module_param(force_rgb, bool, 0);
+module_param(video_nr, int, 0);
+
+static struct qcam *qcams[MAX_CAMS];
+static unsigned int num_cams;
+
+static inline void qcam_set_ack(struct qcam *qcam, unsigned int i)
+{
+	/* note: the QC specs refer to the PCAck pin by voltage, not
+	   software level.  PC ports have builtin inverters. */
+	parport_frob_control(qcam->pport, 8, i ? 8 : 0);
+}
+
+static inline unsigned int qcam_ready1(struct qcam *qcam)
+{
+	return (parport_read_status(qcam->pport) & 0x8) ? 1 : 0;
+}
+
+static inline unsigned int qcam_ready2(struct qcam *qcam)
+{
+	return (parport_read_data(qcam->pport) & 0x1) ? 1 : 0;
+}
+
+static unsigned int qcam_await_ready1(struct qcam *qcam, int value)
+{
+	struct v4l2_device *v4l2_dev = &qcam->v4l2_dev;
+	unsigned long oldjiffies = jiffies;
+	unsigned int i;
+
+	for (oldjiffies = jiffies;
+	     time_before(jiffies, oldjiffies + msecs_to_jiffies(40));)
+		if (qcam_ready1(qcam) == value)
+			return 0;
+
+	/* If the camera didn't respond within 1/25 second, poll slowly
+	   for a while. */
+	for (i = 0; i < 50; i++) {
+		if (qcam_ready1(qcam) == value)
+			return 0;
+		msleep_interruptible(100);
+	}
+
+	/* Probably somebody pulled the plug out.  Not much we can do. */
+	v4l2_err(v4l2_dev, "ready1 timeout (%d) %x %x\n", value,
+	       parport_read_status(qcam->pport),
+	       parport_read_control(qcam->pport));
+	return 1;
+}
+
+static unsigned int qcam_await_ready2(struct qcam *qcam, int value)
+{
+	struct v4l2_device *v4l2_dev = &qcam->v4l2_dev;
+	unsigned long oldjiffies = jiffies;
+	unsigned int i;
+
+	for (oldjiffies = jiffies;
+	     time_before(jiffies, oldjiffies + msecs_to_jiffies(40));)
+		if (qcam_ready2(qcam) == value)
+			return 0;
+
+	/* If the camera didn't respond within 1/25 second, poll slowly
+	   for a while. */
+	for (i = 0; i < 50; i++) {
+		if (qcam_ready2(qcam) == value)
+			return 0;
+		msleep_interruptible(100);
+	}
+
+	/* Probably somebody pulled the plug out.  Not much we can do. */
+	v4l2_err(v4l2_dev, "ready2 timeout (%d) %x %x %x\n", value,
+	       parport_read_status(qcam->pport),
+	       parport_read_control(qcam->pport),
+	       parport_read_data(qcam->pport));
+	return 1;
+}
+
+static int qcam_read_data(struct qcam *qcam)
+{
+	unsigned int idata;
+
+	qcam_set_ack(qcam, 0);
+	if (qcam_await_ready1(qcam, 1))
+		return -1;
+	idata = parport_read_status(qcam->pport) & 0xf0;
+	qcam_set_ack(qcam, 1);
+	if (qcam_await_ready1(qcam, 0))
+		return -1;
+	idata |= parport_read_status(qcam->pport) >> 4;
+	return idata;
+}
+
+static int qcam_write_data(struct qcam *qcam, unsigned int data)
+{
+	struct v4l2_device *v4l2_dev = &qcam->v4l2_dev;
+	unsigned int idata;
+
+	parport_write_data(qcam->pport, data);
+	idata = qcam_read_data(qcam);
+	if (data != idata) {
+		v4l2_warn(v4l2_dev, "sent %x but received %x\n", data,
+		       idata);
+		return 1;
+	}
+	return 0;
+}
+
+static inline int qcam_set(struct qcam *qcam, unsigned int cmd, unsigned int data)
+{
+	if (qcam_write_data(qcam, cmd))
+		return -1;
+	if (qcam_write_data(qcam, data))
+		return -1;
+	return 0;
+}
+
+static inline int qcam_get(struct qcam *qcam, unsigned int cmd)
+{
+	if (qcam_write_data(qcam, cmd))
+		return -1;
+	return qcam_read_data(qcam);
+}
+
+static int qc_detect(struct qcam *qcam)
+{
+	unsigned int stat, ostat, i, count = 0;
+
+	/* The probe routine below is not very reliable.  The IEEE-1284
+	   probe takes precedence. */
+	/* XXX Currently parport provides no way to distinguish between
+	   "the IEEE probe was not done" and "the probe was done, but
+	   no device was found".  Fix this one day. */
+	if (qcam->pport->probe_info[0].class == PARPORT_CLASS_MEDIA
+	    && qcam->pport->probe_info[0].model
+	    && !strcmp(qcam->pdev->port->probe_info[0].model,
+		       "Color QuickCam 2.0")) {
+		printk(KERN_DEBUG "QuickCam: Found by IEEE1284 probe.\n");
+		return 1;
+	}
+
+	if (probe < 2)
+		return 0;
+
+	parport_write_control(qcam->pport, 0xc);
+
+	/* look for a heartbeat */
+	ostat = stat = parport_read_status(qcam->pport);
+	for (i = 0; i < 250; i++) {
+		mdelay(1);
+		stat = parport_read_status(qcam->pport);
+		if (ostat != stat) {
+			if (++count >= 3)
+				return 1;
+			ostat = stat;
+		}
+	}
+
+	/* Reset the camera and try again */
+	parport_write_control(qcam->pport, 0xc);
+	parport_write_control(qcam->pport, 0x8);
+	mdelay(1);
+	parport_write_control(qcam->pport, 0xc);
+	mdelay(1);
+	count = 0;
+
+	ostat = stat = parport_read_status(qcam->pport);
+	for (i = 0; i < 250; i++) {
+		mdelay(1);
+		stat = parport_read_status(qcam->pport);
+		if (ostat != stat) {
+			if (++count >= 3)
+				return 1;
+			ostat = stat;
+		}
+	}
+
+	/* no (or flatline) camera, give up */
+	return 0;
+}
+
+static void qc_reset(struct qcam *qcam)
+{
+	parport_write_control(qcam->pport, 0xc);
+	parport_write_control(qcam->pport, 0x8);
+	mdelay(1);
+	parport_write_control(qcam->pport, 0xc);
+	mdelay(1);
+}
+
+/* Reset the QuickCam and program for brightness, contrast,
+ * white-balance, and resolution. */
+
+static void qc_setup(struct qcam *qcam)
+{
+	qc_reset(qcam);
+
+	/* Set the brightness. */
+	qcam_set(qcam, 11, qcam->brightness);
+
+	/* Set the height and width.  These refer to the actual
+	   CCD area *before* applying the selected decimation.  */
+	qcam_set(qcam, 17, qcam->ccd_height);
+	qcam_set(qcam, 19, qcam->ccd_width / 2);
+
+	/* Set top and left.  */
+	qcam_set(qcam, 0xd, qcam->top);
+	qcam_set(qcam, 0xf, qcam->left);
+
+	/* Set contrast and white balance.  */
+	qcam_set(qcam, 0x19, qcam->contrast);
+	qcam_set(qcam, 0x1f, qcam->whitebal);
+
+	/* Set the speed.  */
+	qcam_set(qcam, 45, 2);
+}
+
+/* Read some bytes from the camera and put them in the buffer.
+   nbytes should be a multiple of 3, because bidirectional mode gives
+   us three bytes at a time.  */
+
+static unsigned int qcam_read_bytes(struct qcam *qcam, unsigned char *buf, unsigned int nbytes)
+{
+	unsigned int bytes = 0;
+
+	qcam_set_ack(qcam, 0);
+	if (qcam->bidirectional) {
+		/* It's a bidirectional port */
+		while (bytes < nbytes) {
+			unsigned int lo1, hi1, lo2, hi2;
+			unsigned char r, g, b;
+
+			if (qcam_await_ready2(qcam, 1))
+				return bytes;
+			lo1 = parport_read_data(qcam->pport) >> 1;
+			hi1 = ((parport_read_status(qcam->pport) >> 3) & 0x1f) ^ 0x10;
+			qcam_set_ack(qcam, 1);
+			if (qcam_await_ready2(qcam, 0))
+				return bytes;
+			lo2 = parport_read_data(qcam->pport) >> 1;
+			hi2 = ((parport_read_status(qcam->pport) >> 3) & 0x1f) ^ 0x10;
+			qcam_set_ack(qcam, 0);
+			r = lo1 | ((hi1 & 1) << 7);
+			g = ((hi1 & 0x1e) << 3) | ((hi2 & 0x1e) >> 1);
+			b = lo2 | ((hi2 & 1) << 7);
+			if (force_rgb) {
+				buf[bytes++] = r;
+				buf[bytes++] = g;
+				buf[bytes++] = b;
+			} else {
+				buf[bytes++] = b;
+				buf[bytes++] = g;
+				buf[bytes++] = r;
+			}
+		}
+	} else {
+		/* It's a unidirectional port */
+		int i = 0, n = bytes;
+		unsigned char rgb[3];
+
+		while (bytes < nbytes) {
+			unsigned int hi, lo;
+
+			if (qcam_await_ready1(qcam, 1))
+				return bytes;
+			hi = (parport_read_status(qcam->pport) & 0xf0);
+			qcam_set_ack(qcam, 1);
+			if (qcam_await_ready1(qcam, 0))
+				return bytes;
+			lo = (parport_read_status(qcam->pport) & 0xf0);
+			qcam_set_ack(qcam, 0);
+			/* flip some bits */
+			rgb[(i = bytes++ % 3)] = (hi | (lo >> 4)) ^ 0x88;
+			if (i >= 2) {
+get_fragment:
+				if (force_rgb) {
+					buf[n++] = rgb[0];
+					buf[n++] = rgb[1];
+					buf[n++] = rgb[2];
+				} else {
+					buf[n++] = rgb[2];
+					buf[n++] = rgb[1];
+					buf[n++] = rgb[0];
+				}
+			}
+		}
+		if (i) {
+			i = 0;
+			goto get_fragment;
+		}
+	}
+	return bytes;
+}
+
+#define BUFSZ	150
+
+static long qc_capture(struct qcam *qcam, char __user *buf, unsigned long len)
+{
+	struct v4l2_device *v4l2_dev = &qcam->v4l2_dev;
+	unsigned lines, pixelsperline;
+	unsigned int is_bi_dir = qcam->bidirectional;
+	size_t wantlen, outptr = 0;
+	char tmpbuf[BUFSZ];
+
+	if (!access_ok(VERIFY_WRITE, buf, len))
+		return -EFAULT;
+
+	/* Wait for camera to become ready */
+	for (;;) {
+		int i = qcam_get(qcam, 41);
+
+		if (i == -1) {
+			qc_setup(qcam);
+			return -EIO;
+		}
+		if ((i & 0x80) == 0)
+			break;
+		schedule();
+	}
+
+	if (qcam_set(qcam, 7, (qcam->mode | (is_bi_dir ? 1 : 0)) + 1))
+		return -EIO;
+
+	lines = qcam->height;
+	pixelsperline = qcam->width;
+
+	if (is_bi_dir) {
+		/* Turn the port around */
+		parport_data_reverse(qcam->pport);
+		mdelay(3);
+		qcam_set_ack(qcam, 0);
+		if (qcam_await_ready1(qcam, 1)) {
+			qc_setup(qcam);
+			return -EIO;
+		}
+		qcam_set_ack(qcam, 1);
+		if (qcam_await_ready1(qcam, 0)) {
+			qc_setup(qcam);
+			return -EIO;
+		}
+	}
+
+	wantlen = lines * pixelsperline * 24 / 8;
+
+	while (wantlen) {
+		size_t t, s;
+
+		s = (wantlen > BUFSZ) ? BUFSZ : wantlen;
+		t = qcam_read_bytes(qcam, tmpbuf, s);
+		if (outptr < len) {
+			size_t sz = len - outptr;
+
+			if (sz > t)
+				sz = t;
+			if (__copy_to_user(buf + outptr, tmpbuf, sz))
+				break;
+			outptr += sz;
+		}
+		wantlen -= t;
+		if (t < s)
+			break;
+		cond_resched();
+	}
+
+	len = outptr;
+
+	if (wantlen) {
+		v4l2_err(v4l2_dev, "short read.\n");
+		if (is_bi_dir)
+			parport_data_forward(qcam->pport);
+		qc_setup(qcam);
+		return len;
+	}
+
+	if (is_bi_dir) {
+		int l;
+
+		do {
+			l = qcam_read_bytes(qcam, tmpbuf, 3);
+			cond_resched();
+		} while (l && (tmpbuf[0] == 0x7e || tmpbuf[1] == 0x7e || tmpbuf[2] == 0x7e));
+		if (force_rgb) {
+			if (tmpbuf[0] != 0xe || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xf)
+				v4l2_err(v4l2_dev, "bad EOF\n");
+		} else {
+			if (tmpbuf[0] != 0xf || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xe)
+				v4l2_err(v4l2_dev, "bad EOF\n");
+		}
+		qcam_set_ack(qcam, 0);
+		if (qcam_await_ready1(qcam, 1)) {
+			v4l2_err(v4l2_dev, "no ack after EOF\n");
+			parport_data_forward(qcam->pport);
+			qc_setup(qcam);
+			return len;
+		}
+		parport_data_forward(qcam->pport);
+		mdelay(3);
+		qcam_set_ack(qcam, 1);
+		if (qcam_await_ready1(qcam, 0)) {
+			v4l2_err(v4l2_dev, "no ack to port turnaround\n");
+			qc_setup(qcam);
+			return len;
+		}
+	} else {
+		int l;
+
+		do {
+			l = qcam_read_bytes(qcam, tmpbuf, 1);
+			cond_resched();
+		} while (l && tmpbuf[0] == 0x7e);
+		l = qcam_read_bytes(qcam, tmpbuf + 1, 2);
+		if (force_rgb) {
+			if (tmpbuf[0] != 0xe || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xf)
+				v4l2_err(v4l2_dev, "bad EOF\n");
+		} else {
+			if (tmpbuf[0] != 0xf || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xe)
+				v4l2_err(v4l2_dev, "bad EOF\n");
+		}
+	}
+
+	qcam_write_data(qcam, 0);
+	return len;
+}
+
+/*
+ *	Video4linux interfacing
+ */
+
+static int qcam_querycap(struct file *file, void  *priv,
+					struct v4l2_capability *vcap)
+{
+	struct qcam *qcam = video_drvdata(file);
+
+	strlcpy(vcap->driver, qcam->v4l2_dev.name, sizeof(vcap->driver));
+	strlcpy(vcap->card, "Color Quickcam", sizeof(vcap->card));
+	strlcpy(vcap->bus_info, "parport", sizeof(vcap->bus_info));
+	vcap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE;
+	vcap->capabilities = vcap->device_caps | V4L2_CAP_DEVICE_CAPS;
+	return 0;
+}
+
+static int qcam_enum_input(struct file *file, void *fh, struct v4l2_input *vin)
+{
+	if (vin->index > 0)
+		return -EINVAL;
+	strlcpy(vin->name, "Camera", sizeof(vin->name));
+	vin->type = V4L2_INPUT_TYPE_CAMERA;
+	vin->audioset = 0;
+	vin->tuner = 0;
+	vin->std = 0;
+	vin->status = 0;
+	return 0;
+}
+
+static int qcam_g_input(struct file *file, void *fh, unsigned int *inp)
+{
+	*inp = 0;
+	return 0;
+}
+
+static int qcam_s_input(struct file *file, void *fh, unsigned int inp)
+{
+	return (inp > 0) ? -EINVAL : 0;
+}
+
+static int qcam_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+	struct qcam *qcam = video_drvdata(file);
+	struct v4l2_pix_format *pix = &fmt->fmt.pix;
+
+	pix->width = qcam->width;
+	pix->height = qcam->height;
+	pix->pixelformat = V4L2_PIX_FMT_RGB24;
+	pix->field = V4L2_FIELD_NONE;
+	pix->bytesperline = 3 * qcam->width;
+	pix->sizeimage = 3 * qcam->width * qcam->height;
+	/* Just a guess */
+	pix->colorspace = V4L2_COLORSPACE_SRGB;
+	return 0;
+}
+
+static int qcam_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+	struct v4l2_pix_format *pix = &fmt->fmt.pix;
+
+	if (pix->height < 60 || pix->width < 80) {
+		pix->height = 60;
+		pix->width = 80;
+	} else if (pix->height < 120 || pix->width < 160) {
+		pix->height = 120;
+		pix->width = 160;
+	} else {
+		pix->height = 240;
+		pix->width = 320;
+	}
+	pix->pixelformat = V4L2_PIX_FMT_RGB24;
+	pix->field = V4L2_FIELD_NONE;
+	pix->bytesperline = 3 * pix->width;
+	pix->sizeimage = 3 * pix->width * pix->height;
+	/* Just a guess */
+	pix->colorspace = V4L2_COLORSPACE_SRGB;
+	return 0;
+}
+
+static int qcam_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+	struct qcam *qcam = video_drvdata(file);
+	struct v4l2_pix_format *pix = &fmt->fmt.pix;
+	int ret = qcam_try_fmt_vid_cap(file, fh, fmt);
+
+	if (ret)
+		return ret;
+	switch (pix->height) {
+	case 60:
+		qcam->mode = QC_DECIMATION_4;
+		break;
+	case 120:
+		qcam->mode = QC_DECIMATION_2;
+		break;
+	default:
+		qcam->mode = QC_DECIMATION_1;
+		break;
+	}
+
+	mutex_lock(&qcam->lock);
+	qcam->mode |= QC_MILLIONS;
+	qcam->height = pix->height;
+	qcam->width = pix->width;
+	parport_claim_or_block(qcam->pdev);
+	qc_setup(qcam);
+	parport_release(qcam->pdev);
+	mutex_unlock(&qcam->lock);
+	return 0;
+}
+
+static int qcam_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt)
+{
+	static struct v4l2_fmtdesc formats[] = {
+		{ 0, 0, 0,
+		  "RGB 8:8:8", V4L2_PIX_FMT_RGB24,
+		  { 0, 0, 0, 0 }
+		},
+	};
+	enum v4l2_buf_type type = fmt->type;
+
+	if (fmt->index > 0)
+		return -EINVAL;
+
+	*fmt = formats[fmt->index];
+	fmt->type = type;
+	return 0;
+}
+
+static ssize_t qcam_read(struct file *file, char __user *buf,
+			 size_t count, loff_t *ppos)
+{
+	struct qcam *qcam = video_drvdata(file);
+	int len;
+
+	mutex_lock(&qcam->lock);
+	parport_claim_or_block(qcam->pdev);
+	/* Probably should have a semaphore against multiple users */
+	len = qc_capture(qcam, buf, count);
+	parport_release(qcam->pdev);
+	mutex_unlock(&qcam->lock);
+	return len;
+}
+
+static int qcam_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct qcam *qcam =
+		container_of(ctrl->handler, struct qcam, hdl);
+	int ret = 0;
+
+	mutex_lock(&qcam->lock);
+	switch (ctrl->id) {
+	case V4L2_CID_BRIGHTNESS:
+		qcam->brightness = ctrl->val;
+		break;
+	case V4L2_CID_CONTRAST:
+		qcam->contrast = ctrl->val;
+		break;
+	case V4L2_CID_GAMMA:
+		qcam->whitebal = ctrl->val;
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+	if (ret == 0) {
+		parport_claim_or_block(qcam->pdev);
+		qc_setup(qcam);
+		parport_release(qcam->pdev);
+	}
+	mutex_unlock(&qcam->lock);
+	return ret;
+}
+
+static const struct v4l2_file_operations qcam_fops = {
+	.owner		= THIS_MODULE,
+	.open		= v4l2_fh_open,
+	.release	= v4l2_fh_release,
+	.poll		= v4l2_ctrl_poll,
+	.unlocked_ioctl	= video_ioctl2,
+	.read		= qcam_read,
+};
+
+static const struct v4l2_ioctl_ops qcam_ioctl_ops = {
+	.vidioc_querycap    		    = qcam_querycap,
+	.vidioc_g_input      		    = qcam_g_input,
+	.vidioc_s_input      		    = qcam_s_input,
+	.vidioc_enum_input   		    = qcam_enum_input,
+	.vidioc_enum_fmt_vid_cap	    = qcam_enum_fmt_vid_cap,
+	.vidioc_g_fmt_vid_cap 		    = qcam_g_fmt_vid_cap,
+	.vidioc_s_fmt_vid_cap  		    = qcam_s_fmt_vid_cap,
+	.vidioc_try_fmt_vid_cap  	    = qcam_try_fmt_vid_cap,
+	.vidioc_log_status		    = v4l2_ctrl_log_status,
+	.vidioc_subscribe_event		    = v4l2_ctrl_subscribe_event,
+	.vidioc_unsubscribe_event	    = v4l2_event_unsubscribe,
+};
+
+static const struct v4l2_ctrl_ops qcam_ctrl_ops = {
+	.s_ctrl = qcam_s_ctrl,
+};
+
+/* Initialize the QuickCam driver control structure. */
+
+static struct qcam *qcam_init(struct parport *port)
+{
+	struct qcam *qcam;
+	struct v4l2_device *v4l2_dev;
+
+	qcam = kzalloc(sizeof(*qcam), GFP_KERNEL);
+	if (qcam == NULL)
+		return NULL;
+
+	v4l2_dev = &qcam->v4l2_dev;
+	strlcpy(v4l2_dev->name, "c-qcam", sizeof(v4l2_dev->name));
+
+	if (v4l2_device_register(NULL, v4l2_dev) < 0) {
+		v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
+		kfree(qcam);
+		return NULL;
+	}
+
+	v4l2_ctrl_handler_init(&qcam->hdl, 3);
+	v4l2_ctrl_new_std(&qcam->hdl, &qcam_ctrl_ops,
+			  V4L2_CID_BRIGHTNESS, 0, 255, 1, 240);
+	v4l2_ctrl_new_std(&qcam->hdl, &qcam_ctrl_ops,
+			  V4L2_CID_CONTRAST, 0, 255, 1, 192);
+	v4l2_ctrl_new_std(&qcam->hdl, &qcam_ctrl_ops,
+			  V4L2_CID_GAMMA, 0, 255, 1, 128);
+	if (qcam->hdl.error) {
+		v4l2_err(v4l2_dev, "couldn't register controls\n");
+		v4l2_ctrl_handler_free(&qcam->hdl);
+		kfree(qcam);
+		return NULL;
+	}
+
+	qcam->pport = port;
+	qcam->pdev = parport_register_device(port, "c-qcam", NULL, NULL,
+					  NULL, 0, NULL);
+
+	qcam->bidirectional = (qcam->pport->modes & PARPORT_MODE_TRISTATE) ? 1 : 0;
+
+	if (qcam->pdev == NULL) {
+		v4l2_err(v4l2_dev, "couldn't register for %s.\n", port->name);
+		v4l2_ctrl_handler_free(&qcam->hdl);
+		kfree(qcam);
+		return NULL;
+	}
+
+	strlcpy(qcam->vdev.name, "Colour QuickCam", sizeof(qcam->vdev.name));
+	qcam->vdev.v4l2_dev = v4l2_dev;
+	qcam->vdev.fops = &qcam_fops;
+	qcam->vdev.ioctl_ops = &qcam_ioctl_ops;
+	qcam->vdev.release = video_device_release_empty;
+	qcam->vdev.ctrl_handler = &qcam->hdl;
+	set_bit(V4L2_FL_USE_FH_PRIO, &qcam->vdev.flags);
+	video_set_drvdata(&qcam->vdev, qcam);
+
+	mutex_init(&qcam->lock);
+	qcam->width = qcam->ccd_width = 320;
+	qcam->height = qcam->ccd_height = 240;
+	qcam->mode = QC_MILLIONS | QC_DECIMATION_1;
+	qcam->contrast = 192;
+	qcam->brightness = 240;
+	qcam->whitebal = 128;
+	qcam->top = 1;
+	qcam->left = 14;
+	return qcam;
+}
+
+static int init_cqcam(struct parport *port)
+{
+	struct qcam *qcam;
+	struct v4l2_device *v4l2_dev;
+
+	if (parport[0] != -1) {
+		/* The user gave specific instructions */
+		int i, found = 0;
+
+		for (i = 0; i < MAX_CAMS && parport[i] != -1; i++) {
+			if (parport[0] == port->number)
+				found = 1;
+		}
+		if (!found)
+			return -ENODEV;
+	}
+
+	if (num_cams == MAX_CAMS)
+		return -ENOSPC;
+
+	qcam = qcam_init(port);
+	if (qcam == NULL)
+		return -ENODEV;
+
+	v4l2_dev = &qcam->v4l2_dev;
+
+	parport_claim_or_block(qcam->pdev);
+
+	qc_reset(qcam);
+
+	if (probe && qc_detect(qcam) == 0) {
+		parport_release(qcam->pdev);
+		parport_unregister_device(qcam->pdev);
+		kfree(qcam);
+		return -ENODEV;
+	}
+
+	qc_setup(qcam);
+
+	parport_release(qcam->pdev);
+
+	if (video_register_device(&qcam->vdev, VFL_TYPE_GRABBER, video_nr) < 0) {
+		v4l2_err(v4l2_dev, "Unable to register Colour QuickCam on %s\n",
+		       qcam->pport->name);
+		parport_unregister_device(qcam->pdev);
+		kfree(qcam);
+		return -ENODEV;
+	}
+
+	v4l2_info(v4l2_dev, "%s: Colour QuickCam found on %s\n",
+	       video_device_node_name(&qcam->vdev), qcam->pport->name);
+
+	qcams[num_cams++] = qcam;
+
+	return 0;
+}
+
+static void close_cqcam(struct qcam *qcam)
+{
+	video_unregister_device(&qcam->vdev);
+	v4l2_ctrl_handler_free(&qcam->hdl);
+	parport_unregister_device(qcam->pdev);
+	kfree(qcam);
+}
+
+static void cq_attach(struct parport *port)
+{
+	init_cqcam(port);
+}
+
+static void cq_detach(struct parport *port)
+{
+	/* Write this some day. */
+}
+
+static struct parport_driver cqcam_driver = {
+	.name = "cqcam",
+	.attach = cq_attach,
+	.detach = cq_detach,
+};
+
+static int __init cqcam_init(void)
+{
+	printk(KERN_INFO BANNER "\n");
+
+	return parport_register_driver(&cqcam_driver);
+}
+
+static void __exit cqcam_cleanup(void)
+{
+	unsigned int i;
+
+	for (i = 0; i < num_cams; i++)
+		close_cqcam(qcams[i]);
+
+	parport_unregister_driver(&cqcam_driver);
+}
+
+MODULE_AUTHOR("Philip Blundell <philb@gnu.org>");
+MODULE_DESCRIPTION(BANNER);
+MODULE_LICENSE("GPL");
+MODULE_VERSION("0.0.4");
+
+module_init(cqcam_init);
+module_exit(cqcam_cleanup);
diff --git a/drivers/media/parport/pms.c b/drivers/media/parport/pms.c
new file mode 100644
index 0000000..77f9c92
--- /dev/null
+++ b/drivers/media/parport/pms.c
@@ -0,0 +1,1152 @@
+/*
+ *	Media Vision Pro Movie Studio
+ *			or
+ *	"all you need is an I2C bus some RAM and a prayer"
+ *
+ *	This draws heavily on code
+ *
+ *	(c) Wolfgang Koehler,  wolf@first.gmd.de, Dec. 1994
+ *	Kiefernring 15
+ *	14478 Potsdam, Germany
+ *
+ *	Most of this code is directly derived from his userspace driver.
+ *	His driver works so send any reports to alan@lxorguk.ukuu.org.uk
+ *	unless the userspace driver also doesn't work for you...
+ *
+ *      Changes:
+ *	25-11-2009 	Hans Verkuil <hverkuil@xs4all.nl>
+ * 			- converted to version 2 of the V4L API.
+ *      08/07/2003      Daniele Bellucci <bellucda@tiscali.it>
+ *                      - pms_capture: report back -EFAULT
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/mutex.h>
+#include <linux/uaccess.h>
+#include <linux/isa.h>
+#include <asm/io.h>
+
+#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-fh.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-device.h>
+
+MODULE_LICENSE("GPL");
+MODULE_VERSION("0.0.5");
+
+#define MOTOROLA	1
+#define PHILIPS2	2               /* SAA7191 */
+#define PHILIPS1	3
+#define MVVMEMORYWIDTH	0x40		/* 512 bytes */
+
+struct i2c_info {
+	u8 slave;
+	u8 sub;
+	u8 data;
+	u8 hits;
+};
+
+struct pms {
+	struct v4l2_device v4l2_dev;
+	struct video_device vdev;
+	struct v4l2_ctrl_handler hdl;
+	int height;
+	int width;
+	int depth;
+	int input;
+	struct mutex lock;
+	int i2c_count;
+	struct i2c_info i2cinfo[64];
+
+	int decoder;
+	int standard;	/* 0 - auto 1 - ntsc 2 - pal 3 - secam */
+	v4l2_std_id std;
+	int io;
+	int data;
+	void __iomem *mem;
+};
+
+/*
+ *	I/O ports and Shared Memory
+ */
+
+static int io_port = 0x250;
+module_param(io_port, int, 0);
+
+static int mem_base = 0xc8000;
+module_param(mem_base, int, 0);
+
+static int video_nr = -1;
+module_param(video_nr, int, 0);
+
+
+static inline void mvv_write(struct pms *dev, u8 index, u8 value)
+{
+	outw(index | (value << 8), dev->io);
+}
+
+static inline u8 mvv_read(struct pms *dev, u8 index)
+{
+	outb(index, dev->io);
+	return inb(dev->data);
+}
+
+static int pms_i2c_stat(struct pms *dev, u8 slave)
+{
+	int counter = 0;
+	int i;
+
+	outb(0x28, dev->io);
+
+	while ((inb(dev->data) & 0x01) == 0)
+		if (counter++ == 256)
+			break;
+
+	while ((inb(dev->data) & 0x01) != 0)
+		if (counter++ == 256)
+			break;
+
+	outb(slave, dev->io);
+
+	counter = 0;
+	while ((inb(dev->data) & 0x01) == 0)
+		if (counter++ == 256)
+			break;
+
+	while ((inb(dev->data) & 0x01) != 0)
+		if (counter++ == 256)
+			break;
+
+	for (i = 0; i < 12; i++) {
+		char st = inb(dev->data);
+
+		if ((st & 2) != 0)
+			return -1;
+		if ((st & 1) == 0)
+			break;
+	}
+	outb(0x29, dev->io);
+	return inb(dev->data);
+}
+
+static int pms_i2c_write(struct pms *dev, u16 slave, u16 sub, u16 data)
+{
+	int skip = 0;
+	int count;
+	int i;
+
+	for (i = 0; i < dev->i2c_count; i++) {
+		if ((dev->i2cinfo[i].slave == slave) &&
+		    (dev->i2cinfo[i].sub == sub)) {
+			if (dev->i2cinfo[i].data == data)
+				skip = 1;
+			dev->i2cinfo[i].data = data;
+			i = dev->i2c_count + 1;
+		}
+	}
+
+	if (i == dev->i2c_count && dev->i2c_count < 64) {
+		dev->i2cinfo[dev->i2c_count].slave = slave;
+		dev->i2cinfo[dev->i2c_count].sub = sub;
+		dev->i2cinfo[dev->i2c_count].data = data;
+		dev->i2c_count++;
+	}
+
+	if (skip)
+		return 0;
+
+	mvv_write(dev, 0x29, sub);
+	mvv_write(dev, 0x2A, data);
+	mvv_write(dev, 0x28, slave);
+
+	outb(0x28, dev->io);
+
+	count = 0;
+	while ((inb(dev->data) & 1) == 0)
+		if (count > 255)
+			break;
+	while ((inb(dev->data) & 1) != 0)
+		if (count > 255)
+			break;
+
+	count = inb(dev->data);
+
+	if (count & 2)
+		return -1;
+	return count;
+}
+
+static int pms_i2c_read(struct pms *dev, int slave, int sub)
+{
+	int i;
+
+	for (i = 0; i < dev->i2c_count; i++) {
+		if (dev->i2cinfo[i].slave == slave && dev->i2cinfo[i].sub == sub)
+			return dev->i2cinfo[i].data;
+	}
+	return 0;
+}
+
+
+static void pms_i2c_andor(struct pms *dev, int slave, int sub, int and, int or)
+{
+	u8 tmp;
+
+	tmp = pms_i2c_read(dev, slave, sub);
+	tmp = (tmp & and) | or;
+	pms_i2c_write(dev, slave, sub, tmp);
+}
+
+/*
+ *	Control functions
+ */
+
+
+static void pms_videosource(struct pms *dev, short source)
+{
+	switch (dev->decoder) {
+	case MOTOROLA:
+		break;
+	case PHILIPS2:
+		pms_i2c_andor(dev, 0x8a, 0x06, 0x7f, source ? 0x80 : 0);
+		break;
+	case PHILIPS1:
+		break;
+	}
+	mvv_write(dev, 0x2E, 0x31);
+	/* Was: mvv_write(dev, 0x2E, source ? 0x31 : 0x30);
+	   But could not make this work correctly. Only Composite input
+	   worked for me. */
+}
+
+static void pms_hue(struct pms *dev, short hue)
+{
+	switch (dev->decoder) {
+	case MOTOROLA:
+		pms_i2c_write(dev, 0x8a, 0x00, hue);
+		break;
+	case PHILIPS2:
+		pms_i2c_write(dev, 0x8a, 0x07, hue);
+		break;
+	case PHILIPS1:
+		pms_i2c_write(dev, 0x42, 0x07, hue);
+		break;
+	}
+}
+
+static void pms_saturation(struct pms *dev, short sat)
+{
+	switch (dev->decoder) {
+	case MOTOROLA:
+		pms_i2c_write(dev, 0x8a, 0x00, sat);
+		break;
+	case PHILIPS1:
+		pms_i2c_write(dev, 0x42, 0x12, sat);
+		break;
+	}
+}
+
+
+static void pms_contrast(struct pms *dev, short contrast)
+{
+	switch (dev->decoder) {
+	case MOTOROLA:
+		pms_i2c_write(dev, 0x8a, 0x00, contrast);
+		break;
+	case PHILIPS1:
+		pms_i2c_write(dev, 0x42, 0x13, contrast);
+		break;
+	}
+}
+
+static void pms_brightness(struct pms *dev, short brightness)
+{
+	switch (dev->decoder) {
+	case MOTOROLA:
+		pms_i2c_write(dev, 0x8a, 0x00, brightness);
+		pms_i2c_write(dev, 0x8a, 0x00, brightness);
+		pms_i2c_write(dev, 0x8a, 0x00, brightness);
+		break;
+	case PHILIPS1:
+		pms_i2c_write(dev, 0x42, 0x19, brightness);
+		break;
+	}
+}
+
+
+static void pms_format(struct pms *dev, short format)
+{
+	int target;
+
+	dev->standard = format;
+
+	if (dev->decoder == PHILIPS1)
+		target = 0x42;
+	else if (dev->decoder == PHILIPS2)
+		target = 0x8a;
+	else
+		return;
+
+	switch (format) {
+	case 0:	/* Auto */
+		pms_i2c_andor(dev, target, 0x0d, 0xfe, 0x00);
+		pms_i2c_andor(dev, target, 0x0f, 0x3f, 0x80);
+		break;
+	case 1: /* NTSC */
+		pms_i2c_andor(dev, target, 0x0d, 0xfe, 0x00);
+		pms_i2c_andor(dev, target, 0x0f, 0x3f, 0x40);
+		break;
+	case 2: /* PAL */
+		pms_i2c_andor(dev, target, 0x0d, 0xfe, 0x00);
+		pms_i2c_andor(dev, target, 0x0f, 0x3f, 0x00);
+		break;
+	case 3:	/* SECAM */
+		pms_i2c_andor(dev, target, 0x0d, 0xfe, 0x01);
+		pms_i2c_andor(dev, target, 0x0f, 0x3f, 0x00);
+		break;
+	}
+}
+
+#ifdef FOR_FUTURE_EXPANSION
+
+/*
+ *	These features of the PMS card are not currently exposes. They
+ *	could become a private v4l ioctl for PMSCONFIG or somesuch if
+ *	people need it. We also don't yet use the PMS interrupt.
+ */
+
+static void pms_hstart(struct pms *dev, short start)
+{
+	switch (dev->decoder) {
+	case PHILIPS1:
+		pms_i2c_write(dev, 0x8a, 0x05, start);
+		pms_i2c_write(dev, 0x8a, 0x18, start);
+		break;
+	case PHILIPS2:
+		pms_i2c_write(dev, 0x42, 0x05, start);
+		pms_i2c_write(dev, 0x42, 0x18, start);
+		break;
+	}
+}
+
+/*
+ *	Bandpass filters
+ */
+
+static void pms_bandpass(struct pms *dev, short pass)
+{
+	if (dev->decoder == PHILIPS2)
+		pms_i2c_andor(dev, 0x8a, 0x06, 0xcf, (pass & 0x03) << 4);
+	else if (dev->decoder == PHILIPS1)
+		pms_i2c_andor(dev, 0x42, 0x06, 0xcf, (pass & 0x03) << 4);
+}
+
+static void pms_antisnow(struct pms *dev, short snow)
+{
+	if (dev->decoder == PHILIPS2)
+		pms_i2c_andor(dev, 0x8a, 0x06, 0xf3, (snow & 0x03) << 2);
+	else if (dev->decoder == PHILIPS1)
+		pms_i2c_andor(dev, 0x42, 0x06, 0xf3, (snow & 0x03) << 2);
+}
+
+static void pms_sharpness(struct pms *dev, short sharp)
+{
+	if (dev->decoder == PHILIPS2)
+		pms_i2c_andor(dev, 0x8a, 0x06, 0xfc, sharp & 0x03);
+	else if (dev->decoder == PHILIPS1)
+		pms_i2c_andor(dev, 0x42, 0x06, 0xfc, sharp & 0x03);
+}
+
+static void pms_chromaagc(struct pms *dev, short agc)
+{
+	if (dev->decoder == PHILIPS2)
+		pms_i2c_andor(dev, 0x8a, 0x0c, 0x9f, (agc & 0x03) << 5);
+	else if (dev->decoder == PHILIPS1)
+		pms_i2c_andor(dev, 0x42, 0x0c, 0x9f, (agc & 0x03) << 5);
+}
+
+static void pms_vertnoise(struct pms *dev, short noise)
+{
+	if (dev->decoder == PHILIPS2)
+		pms_i2c_andor(dev, 0x8a, 0x10, 0xfc, noise & 3);
+	else if (dev->decoder == PHILIPS1)
+		pms_i2c_andor(dev, 0x42, 0x10, 0xfc, noise & 3);
+}
+
+static void pms_forcecolour(struct pms *dev, short colour)
+{
+	if (dev->decoder == PHILIPS2)
+		pms_i2c_andor(dev, 0x8a, 0x0c, 0x7f, (colour & 1) << 7);
+	else if (dev->decoder == PHILIPS1)
+		pms_i2c_andor(dev, 0x42, 0x0c, 0x7, (colour & 1) << 7);
+}
+
+static void pms_antigamma(struct pms *dev, short gamma)
+{
+	if (dev->decoder == PHILIPS2)
+		pms_i2c_andor(dev, 0xb8, 0x00, 0x7f, (gamma & 1) << 7);
+	else if (dev->decoder == PHILIPS1)
+		pms_i2c_andor(dev, 0x42, 0x20, 0x7, (gamma & 1) << 7);
+}
+
+static void pms_prefilter(struct pms *dev, short filter)
+{
+	if (dev->decoder == PHILIPS2)
+		pms_i2c_andor(dev, 0x8a, 0x06, 0xbf, (filter & 1) << 6);
+	else if (dev->decoder == PHILIPS1)
+		pms_i2c_andor(dev, 0x42, 0x06, 0xbf, (filter & 1) << 6);
+}
+
+static void pms_hfilter(struct pms *dev, short filter)
+{
+	if (dev->decoder == PHILIPS2)
+		pms_i2c_andor(dev, 0xb8, 0x04, 0x1f, (filter & 7) << 5);
+	else if (dev->decoder == PHILIPS1)
+		pms_i2c_andor(dev, 0x42, 0x24, 0x1f, (filter & 7) << 5);
+}
+
+static void pms_vfilter(struct pms *dev, short filter)
+{
+	if (dev->decoder == PHILIPS2)
+		pms_i2c_andor(dev, 0xb8, 0x08, 0x9f, (filter & 3) << 5);
+	else if (dev->decoder == PHILIPS1)
+		pms_i2c_andor(dev, 0x42, 0x28, 0x9f, (filter & 3) << 5);
+}
+
+static void pms_killcolour(struct pms *dev, short colour)
+{
+	if (dev->decoder == PHILIPS2) {
+		pms_i2c_andor(dev, 0x8a, 0x08, 0x07, (colour & 0x1f) << 3);
+		pms_i2c_andor(dev, 0x8a, 0x09, 0x07, (colour & 0x1f) << 3);
+	} else if (dev->decoder == PHILIPS1) {
+		pms_i2c_andor(dev, 0x42, 0x08, 0x07, (colour & 0x1f) << 3);
+		pms_i2c_andor(dev, 0x42, 0x09, 0x07, (colour & 0x1f) << 3);
+	}
+}
+
+static void pms_chromagain(struct pms *dev, short chroma)
+{
+	if (dev->decoder == PHILIPS2)
+		pms_i2c_write(dev, 0x8a, 0x11, chroma);
+	else if (dev->decoder == PHILIPS1)
+		pms_i2c_write(dev, 0x42, 0x11, chroma);
+}
+
+
+static void pms_spacialcompl(struct pms *dev, short data)
+{
+	mvv_write(dev, 0x3b, data);
+}
+
+static void pms_spacialcomph(struct pms *dev, short data)
+{
+	mvv_write(dev, 0x3a, data);
+}
+
+static void pms_vstart(struct pms *dev, short start)
+{
+	mvv_write(dev, 0x16, start);
+	mvv_write(dev, 0x17, (start >> 8) & 0x01);
+}
+
+#endif
+
+static void pms_secamcross(struct pms *dev, short cross)
+{
+	if (dev->decoder == PHILIPS2)
+		pms_i2c_andor(dev, 0x8a, 0x0f, 0xdf, (cross & 1) << 5);
+	else if (dev->decoder == PHILIPS1)
+		pms_i2c_andor(dev, 0x42, 0x0f, 0xdf, (cross & 1) << 5);
+}
+
+
+static void pms_swsense(struct pms *dev, short sense)
+{
+	if (dev->decoder == PHILIPS2) {
+		pms_i2c_write(dev, 0x8a, 0x0a, sense);
+		pms_i2c_write(dev, 0x8a, 0x0b, sense);
+	} else if (dev->decoder == PHILIPS1) {
+		pms_i2c_write(dev, 0x42, 0x0a, sense);
+		pms_i2c_write(dev, 0x42, 0x0b, sense);
+	}
+}
+
+
+static void pms_framerate(struct pms *dev, short frr)
+{
+	int fps = (dev->std & V4L2_STD_525_60) ? 30 : 25;
+
+	if (frr == 0)
+		return;
+	fps = fps/frr;
+	mvv_write(dev, 0x14, 0x80 | fps);
+	mvv_write(dev, 0x15, 1);
+}
+
+static void pms_vert(struct pms *dev, u8 deciden, u8 decinum)
+{
+	mvv_write(dev, 0x1c, deciden);	/* Denominator */
+	mvv_write(dev, 0x1d, decinum);	/* Numerator */
+}
+
+/*
+ *	Turn 16bit ratios into best small ratio the chipset can grok
+ */
+
+static void pms_vertdeci(struct pms *dev, unsigned short decinum, unsigned short deciden)
+{
+	/* Knock it down by / 5 once */
+	if (decinum % 5 == 0) {
+		deciden /= 5;
+		decinum /= 5;
+	}
+	/*
+	 *	3's
+	 */
+	while (decinum % 3 == 0 && deciden % 3 == 0) {
+		deciden /= 3;
+		decinum /= 3;
+	}
+	/*
+	 *	2's
+	 */
+	while (decinum % 2 == 0 && deciden % 2 == 0) {
+		decinum /= 2;
+		deciden /= 2;
+	}
+	/*
+	 *	Fudgyify
+	 */
+	while (deciden > 32) {
+		deciden /= 2;
+		decinum = (decinum + 1) / 2;
+	}
+	if (deciden == 32)
+		deciden--;
+	pms_vert(dev, deciden, decinum);
+}
+
+static void pms_horzdeci(struct pms *dev, short decinum, short deciden)
+{
+	if (decinum <= 512) {
+		if (decinum % 5 == 0) {
+			decinum /= 5;
+			deciden /= 5;
+		}
+	} else {
+		decinum = 512;
+		deciden = 640;	/* 768 would be ideal */
+	}
+
+	while (((decinum | deciden) & 1) == 0) {
+		decinum >>= 1;
+		deciden >>= 1;
+	}
+	while (deciden > 32) {
+		deciden >>= 1;
+		decinum = (decinum + 1) >> 1;
+	}
+	if (deciden == 32)
+		deciden--;
+
+	mvv_write(dev, 0x24, 0x80 | deciden);
+	mvv_write(dev, 0x25, decinum);
+}
+
+static void pms_resolution(struct pms *dev, short width, short height)
+{
+	int fg_height;
+
+	fg_height = height;
+	if (fg_height > 280)
+		fg_height = 280;
+
+	mvv_write(dev, 0x18, fg_height);
+	mvv_write(dev, 0x19, fg_height >> 8);
+
+	if (dev->std & V4L2_STD_525_60) {
+		mvv_write(dev, 0x1a, 0xfc);
+		mvv_write(dev, 0x1b, 0x00);
+		if (height > fg_height)
+			pms_vertdeci(dev, 240, 240);
+		else
+			pms_vertdeci(dev, fg_height, 240);
+	} else {
+		mvv_write(dev, 0x1a, 0x1a);
+		mvv_write(dev, 0x1b, 0x01);
+		if (fg_height > 256)
+			pms_vertdeci(dev, 270, 270);
+		else
+			pms_vertdeci(dev, fg_height, 270);
+	}
+	mvv_write(dev, 0x12, 0);
+	mvv_write(dev, 0x13, MVVMEMORYWIDTH);
+	mvv_write(dev, 0x42, 0x00);
+	mvv_write(dev, 0x43, 0x00);
+	mvv_write(dev, 0x44, MVVMEMORYWIDTH);
+
+	mvv_write(dev, 0x22, width + 8);
+	mvv_write(dev, 0x23, (width + 8) >> 8);
+
+	if (dev->std & V4L2_STD_525_60)
+		pms_horzdeci(dev, width, 640);
+	else
+		pms_horzdeci(dev, width + 8, 768);
+
+	mvv_write(dev, 0x30, mvv_read(dev, 0x30) & 0xfe);
+	mvv_write(dev, 0x08, mvv_read(dev, 0x08) | 0x01);
+	mvv_write(dev, 0x01, mvv_read(dev, 0x01) & 0xfd);
+	mvv_write(dev, 0x32, 0x00);
+	mvv_write(dev, 0x33, MVVMEMORYWIDTH);
+}
+
+
+/*
+ *	Set Input
+ */
+
+static void pms_vcrinput(struct pms *dev, short input)
+{
+	if (dev->decoder == PHILIPS2)
+		pms_i2c_andor(dev, 0x8a, 0x0d, 0x7f, (input & 1) << 7);
+	else if (dev->decoder == PHILIPS1)
+		pms_i2c_andor(dev, 0x42, 0x0d, 0x7f, (input & 1) << 7);
+}
+
+
+static int pms_capture(struct pms *dev, char __user *buf, int rgb555, int count)
+{
+	int y;
+	int dw = 2 * dev->width;
+	char tmp[dw + 32]; /* using a temp buffer is faster than direct  */
+	int cnt = 0;
+	int len = 0;
+	unsigned char r8 = 0x5;  /* value for reg8  */
+
+	if (rgb555)
+		r8 |= 0x20; /* else use untranslated rgb = 565 */
+	mvv_write(dev, 0x08, r8); /* capture rgb555/565, init DRAM, PC enable */
+
+/*	printf("%d %d %d %d %d %x %x\n",width,height,voff,nom,den,mvv_buf); */
+
+	for (y = 0; y < dev->height; y++) {
+		writeb(0, dev->mem);  /* synchronisiert neue Zeile */
+
+		/*
+		 *	This is in truth a fifo, be very careful as if you
+		 *	forgot this odd things will occur 8)
+		 */
+
+		memcpy_fromio(tmp, dev->mem, dw + 32); /* discard 16 word   */
+		cnt -= dev->height;
+		while (cnt <= 0) {
+			/*
+			 *	Don't copy too far
+			 */
+			int dt = dw;
+			if (dt + len > count)
+				dt = count - len;
+			cnt += dev->height;
+			if (copy_to_user(buf, tmp + 32, dt))
+				return len ? len : -EFAULT;
+			buf += dt;
+			len += dt;
+		}
+	}
+	return len;
+}
+
+
+/*
+ *	Video4linux interfacing
+ */
+
+static int pms_querycap(struct file *file, void  *priv,
+					struct v4l2_capability *vcap)
+{
+	struct pms *dev = video_drvdata(file);
+
+	strlcpy(vcap->driver, dev->v4l2_dev.name, sizeof(vcap->driver));
+	strlcpy(vcap->card, "Mediavision PMS", sizeof(vcap->card));
+	snprintf(vcap->bus_info, sizeof(vcap->bus_info),
+			"ISA:%s", dev->v4l2_dev.name);
+	vcap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE;
+	vcap->capabilities = vcap->device_caps | V4L2_CAP_DEVICE_CAPS;
+	return 0;
+}
+
+static int pms_enum_input(struct file *file, void *fh, struct v4l2_input *vin)
+{
+	static const char *inputs[4] = {
+		"Composite",
+		"S-Video",
+		"Composite (VCR)",
+		"S-Video (VCR)"
+	};
+
+	if (vin->index > 3)
+		return -EINVAL;
+	strlcpy(vin->name, inputs[vin->index], sizeof(vin->name));
+	vin->type = V4L2_INPUT_TYPE_CAMERA;
+	vin->audioset = 0;
+	vin->tuner = 0;
+	vin->std = V4L2_STD_ALL;
+	vin->status = 0;
+	return 0;
+}
+
+static int pms_g_input(struct file *file, void *fh, unsigned int *inp)
+{
+	struct pms *dev = video_drvdata(file);
+
+	*inp = dev->input;
+	return 0;
+}
+
+static int pms_s_input(struct file *file, void *fh, unsigned int inp)
+{
+	struct pms *dev = video_drvdata(file);
+
+	if (inp > 3)
+		return -EINVAL;
+
+	dev->input = inp;
+	pms_videosource(dev, inp & 1);
+	pms_vcrinput(dev, inp >> 1);
+	return 0;
+}
+
+static int pms_g_std(struct file *file, void *fh, v4l2_std_id *std)
+{
+	struct pms *dev = video_drvdata(file);
+
+	*std = dev->std;
+	return 0;
+}
+
+static int pms_s_std(struct file *file, void *fh, v4l2_std_id *std)
+{
+	struct pms *dev = video_drvdata(file);
+	int ret = 0;
+
+	dev->std = *std;
+	if (dev->std & V4L2_STD_NTSC) {
+		pms_framerate(dev, 30);
+		pms_secamcross(dev, 0);
+		pms_format(dev, 1);
+	} else if (dev->std & V4L2_STD_PAL) {
+		pms_framerate(dev, 25);
+		pms_secamcross(dev, 0);
+		pms_format(dev, 2);
+	} else if (dev->std & V4L2_STD_SECAM) {
+		pms_framerate(dev, 25);
+		pms_secamcross(dev, 1);
+		pms_format(dev, 2);
+	} else {
+		ret = -EINVAL;
+	}
+	/*
+	switch (v->mode) {
+	case VIDEO_MODE_AUTO:
+		pms_framerate(dev, 25);
+		pms_secamcross(dev, 0);
+		pms_format(dev, 0);
+		break;
+	}*/
+	return ret;
+}
+
+static int pms_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct pms *dev = container_of(ctrl->handler, struct pms, hdl);
+	int ret = 0;
+
+	switch (ctrl->id) {
+	case V4L2_CID_BRIGHTNESS:
+		pms_brightness(dev, ctrl->val);
+		break;
+	case V4L2_CID_CONTRAST:
+		pms_contrast(dev, ctrl->val);
+		break;
+	case V4L2_CID_SATURATION:
+		pms_saturation(dev, ctrl->val);
+		break;
+	case V4L2_CID_HUE:
+		pms_hue(dev, ctrl->val);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+	return ret;
+}
+
+static int pms_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+	struct pms *dev = video_drvdata(file);
+	struct v4l2_pix_format *pix = &fmt->fmt.pix;
+
+	pix->width = dev->width;
+	pix->height = dev->height;
+	pix->pixelformat = dev->width == 15 ?
+			    V4L2_PIX_FMT_RGB555 : V4L2_PIX_FMT_RGB565;
+	pix->field = V4L2_FIELD_NONE;
+	pix->bytesperline = 2 * dev->width;
+	pix->sizeimage = 2 * dev->width * dev->height;
+	/* Just a guess */
+	pix->colorspace = V4L2_COLORSPACE_SRGB;
+	return 0;
+}
+
+static int pms_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+	struct v4l2_pix_format *pix = &fmt->fmt.pix;
+
+	if (pix->height < 16 || pix->height > 480)
+		return -EINVAL;
+	if (pix->width < 16 || pix->width > 640)
+		return -EINVAL;
+	if (pix->pixelformat != V4L2_PIX_FMT_RGB555 &&
+	    pix->pixelformat != V4L2_PIX_FMT_RGB565)
+		return -EINVAL;
+	pix->field = V4L2_FIELD_NONE;
+	pix->bytesperline = 2 * pix->width;
+	pix->sizeimage = 2 * pix->width * pix->height;
+	/* Just a guess */
+	pix->colorspace = V4L2_COLORSPACE_SRGB;
+	return 0;
+}
+
+static int pms_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+	struct pms *dev = video_drvdata(file);
+	struct v4l2_pix_format *pix = &fmt->fmt.pix;
+	int ret = pms_try_fmt_vid_cap(file, fh, fmt);
+
+	if (ret)
+		return ret;
+	dev->width = pix->width;
+	dev->height = pix->height;
+	dev->depth = (pix->pixelformat == V4L2_PIX_FMT_RGB555) ? 15 : 16;
+	pms_resolution(dev, dev->width, dev->height);
+	/* Ok we figured out what to use from our wide choice */
+	return 0;
+}
+
+static int pms_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt)
+{
+	static struct v4l2_fmtdesc formats[] = {
+		{ 0, 0, 0,
+		  "RGB 5:5:5", V4L2_PIX_FMT_RGB555,
+		  { 0, 0, 0, 0 }
+		},
+		{ 1, 0, 0,
+		  "RGB 5:6:5", V4L2_PIX_FMT_RGB565,
+		  { 0, 0, 0, 0 }
+		},
+	};
+	enum v4l2_buf_type type = fmt->type;
+
+	if (fmt->index > 1)
+		return -EINVAL;
+
+	*fmt = formats[fmt->index];
+	fmt->type = type;
+	return 0;
+}
+
+static ssize_t pms_read(struct file *file, char __user *buf,
+		    size_t count, loff_t *ppos)
+{
+	struct pms *dev = video_drvdata(file);
+	int len;
+
+	len = pms_capture(dev, buf, (dev->depth == 15), count);
+	return len;
+}
+
+static unsigned int pms_poll(struct file *file, struct poll_table_struct *wait)
+{
+	struct v4l2_fh *fh = file->private_data;
+	unsigned int res = POLLIN | POLLRDNORM;
+
+	if (v4l2_event_pending(fh))
+		res |= POLLPRI;
+	poll_wait(file, &fh->wait, wait);
+	return res;
+}
+
+static const struct v4l2_file_operations pms_fops = {
+	.owner		= THIS_MODULE,
+	.open           = v4l2_fh_open,
+	.release        = v4l2_fh_release,
+	.poll           = pms_poll,
+	.unlocked_ioctl	= video_ioctl2,
+	.read           = pms_read,
+};
+
+static const struct v4l2_ioctl_ops pms_ioctl_ops = {
+	.vidioc_querycap	    = pms_querycap,
+	.vidioc_g_input		    = pms_g_input,
+	.vidioc_s_input		    = pms_s_input,
+	.vidioc_enum_input	    = pms_enum_input,
+	.vidioc_g_std		    = pms_g_std,
+	.vidioc_s_std		    = pms_s_std,
+	.vidioc_enum_fmt_vid_cap    = pms_enum_fmt_vid_cap,
+	.vidioc_g_fmt_vid_cap	    = pms_g_fmt_vid_cap,
+	.vidioc_s_fmt_vid_cap	    = pms_s_fmt_vid_cap,
+	.vidioc_try_fmt_vid_cap     = pms_try_fmt_vid_cap,
+	.vidioc_subscribe_event     = v4l2_ctrl_subscribe_event,
+	.vidioc_unsubscribe_event   = v4l2_event_unsubscribe,
+};
+
+/*
+ *	Probe for and initialise the Mediavision PMS
+ */
+
+static int init_mediavision(struct pms *dev)
+{
+	int idec, decst;
+	int i;
+	static const unsigned char i2c_defs[] = {
+		0x4c, 0x30, 0x00, 0xe8,
+		0xb6, 0xe2, 0x00, 0x00,
+		0xff, 0xff, 0x00, 0x00,
+		0x00, 0x00, 0x78, 0x98,
+		0x00, 0x00, 0x00, 0x00,
+		0x34, 0x0a, 0xf4, 0xce,
+		0xe4
+	};
+
+	dev->mem = ioremap(mem_base, 0x800);
+	if (!dev->mem)
+		return -ENOMEM;
+
+	if (!request_region(0x9a01, 1, "Mediavision PMS config")) {
+		printk(KERN_WARNING "mediavision: unable to detect: 0x9a01 in use.\n");
+		iounmap(dev->mem);
+		return -EBUSY;
+	}
+	if (!request_region(dev->io, 3, "Mediavision PMS")) {
+		printk(KERN_WARNING "mediavision: I/O port %d in use.\n", dev->io);
+		release_region(0x9a01, 1);
+		iounmap(dev->mem);
+		return -EBUSY;
+	}
+	outb(0xb8, 0x9a01);		/* Unlock */
+	outb(dev->io >> 4, 0x9a01);	/* Set IO port */
+
+
+	decst = pms_i2c_stat(dev, 0x43);
+
+	if (decst != -1)
+		idec = 2;
+	else if (pms_i2c_stat(dev, 0xb9) != -1)
+		idec = 3;
+	else if (pms_i2c_stat(dev, 0x8b) != -1)
+		idec = 1;
+	else
+		idec = 0;
+
+	printk(KERN_INFO "PMS type is %d\n", idec);
+	if (idec == 0) {
+		release_region(dev->io, 3);
+		release_region(0x9a01, 1);
+		iounmap(dev->mem);
+		return -ENODEV;
+	}
+
+	/*
+	 *	Ok we have a PMS of some sort
+	 */
+
+	mvv_write(dev, 0x04, mem_base >> 12);	/* Set the memory area */
+
+	/* Ok now load the defaults */
+
+	for (i = 0; i < 0x19; i++) {
+		if (i2c_defs[i] == 0xff)
+			pms_i2c_andor(dev, 0x8a, i, 0x07, 0x00);
+		else
+			pms_i2c_write(dev, 0x8a, i, i2c_defs[i]);
+	}
+
+	pms_i2c_write(dev, 0xb8, 0x00, 0x12);
+	pms_i2c_write(dev, 0xb8, 0x04, 0x00);
+	pms_i2c_write(dev, 0xb8, 0x07, 0x00);
+	pms_i2c_write(dev, 0xb8, 0x08, 0x00);
+	pms_i2c_write(dev, 0xb8, 0x09, 0xff);
+	pms_i2c_write(dev, 0xb8, 0x0a, 0x00);
+	pms_i2c_write(dev, 0xb8, 0x0b, 0x10);
+	pms_i2c_write(dev, 0xb8, 0x10, 0x03);
+
+	mvv_write(dev, 0x01, 0x00);
+	mvv_write(dev, 0x05, 0xa0);
+	mvv_write(dev, 0x08, 0x25);
+	mvv_write(dev, 0x09, 0x00);
+	mvv_write(dev, 0x0a, 0x20 | MVVMEMORYWIDTH);
+
+	mvv_write(dev, 0x10, 0x02);
+	mvv_write(dev, 0x1e, 0x0c);
+	mvv_write(dev, 0x1f, 0x03);
+	mvv_write(dev, 0x26, 0x06);
+
+	mvv_write(dev, 0x2b, 0x00);
+	mvv_write(dev, 0x2c, 0x20);
+	mvv_write(dev, 0x2d, 0x00);
+	mvv_write(dev, 0x2f, 0x70);
+	mvv_write(dev, 0x32, 0x00);
+	mvv_write(dev, 0x33, MVVMEMORYWIDTH);
+	mvv_write(dev, 0x34, 0x00);
+	mvv_write(dev, 0x35, 0x00);
+	mvv_write(dev, 0x3a, 0x80);
+	mvv_write(dev, 0x3b, 0x10);
+	mvv_write(dev, 0x20, 0x00);
+	mvv_write(dev, 0x21, 0x00);
+	mvv_write(dev, 0x30, 0x22);
+	return 0;
+}
+
+/*
+ *	Initialization and module stuff
+ */
+
+#ifndef MODULE
+static int enable;
+module_param(enable, int, 0);
+#endif
+
+static const struct v4l2_ctrl_ops pms_ctrl_ops = {
+	.s_ctrl = pms_s_ctrl,
+};
+
+static int pms_probe(struct device *pdev, unsigned int card)
+{
+	struct pms *dev;
+	struct v4l2_device *v4l2_dev;
+	struct v4l2_ctrl_handler *hdl;
+	int res;
+
+#ifndef MODULE
+	if (!enable) {
+		pr_err("PMS: not enabled, use pms.enable=1 to probe\n");
+		return -ENODEV;
+	}
+#endif
+
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (dev == NULL)
+		return -ENOMEM;
+
+	dev->decoder = PHILIPS2;
+	dev->io = io_port;
+	dev->data = io_port + 1;
+	v4l2_dev = &dev->v4l2_dev;
+	hdl = &dev->hdl;
+
+	res = v4l2_device_register(pdev, v4l2_dev);
+	if (res < 0) {
+		v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
+		goto free_dev;
+	}
+	v4l2_info(v4l2_dev, "Mediavision Pro Movie Studio driver 0.05\n");
+
+	res = init_mediavision(dev);
+	if (res) {
+		v4l2_err(v4l2_dev, "Board not found.\n");
+		goto free_io;
+	}
+
+	v4l2_ctrl_handler_init(hdl, 4);
+	v4l2_ctrl_new_std(hdl, &pms_ctrl_ops,
+			V4L2_CID_BRIGHTNESS, 0, 255, 1, 139);
+	v4l2_ctrl_new_std(hdl, &pms_ctrl_ops,
+			V4L2_CID_CONTRAST, 0, 255, 1, 70);
+	v4l2_ctrl_new_std(hdl, &pms_ctrl_ops,
+			V4L2_CID_SATURATION, 0, 255, 1, 64);
+	v4l2_ctrl_new_std(hdl, &pms_ctrl_ops,
+			V4L2_CID_HUE, 0, 255, 1, 0);
+	if (hdl->error) {
+		res = hdl->error;
+		goto free_hdl;
+	}
+
+	mutex_init(&dev->lock);
+	strlcpy(dev->vdev.name, v4l2_dev->name, sizeof(dev->vdev.name));
+	dev->vdev.v4l2_dev = v4l2_dev;
+	dev->vdev.ctrl_handler = hdl;
+	dev->vdev.fops = &pms_fops;
+	dev->vdev.ioctl_ops = &pms_ioctl_ops;
+	dev->vdev.release = video_device_release_empty;
+	dev->vdev.lock = &dev->lock;
+	dev->vdev.tvnorms = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM;
+	set_bit(V4L2_FL_USE_FH_PRIO, &dev->vdev.flags);
+	video_set_drvdata(&dev->vdev, dev);
+	dev->std = V4L2_STD_NTSC_M;
+	dev->height = 240;
+	dev->width = 320;
+	dev->depth = 16;
+	pms_swsense(dev, 75);
+	pms_resolution(dev, 320, 240);
+	pms_videosource(dev, 0);
+	pms_vcrinput(dev, 0);
+	v4l2_ctrl_handler_setup(hdl);
+	res = video_register_device(&dev->vdev, VFL_TYPE_GRABBER, video_nr);
+	if (res >= 0)
+		return 0;
+
+free_hdl:
+	v4l2_ctrl_handler_free(hdl);
+	v4l2_device_unregister(&dev->v4l2_dev);
+free_io:
+	release_region(dev->io, 3);
+	release_region(0x9a01, 1);
+	iounmap(dev->mem);
+free_dev:
+	kfree(dev);
+	return res;
+}
+
+static int pms_remove(struct device *pdev, unsigned int card)
+{
+	struct pms *dev = dev_get_drvdata(pdev);
+
+	video_unregister_device(&dev->vdev);
+	v4l2_ctrl_handler_free(&dev->hdl);
+	release_region(dev->io, 3);
+	release_region(0x9a01, 1);
+	iounmap(dev->mem);
+	return 0;
+}
+
+static struct isa_driver pms_driver = {
+	.probe		= pms_probe,
+	.remove		= pms_remove,
+	.driver		= {
+		.name	= "pms",
+	},
+};
+
+static int __init pms_init(void)
+{
+	return isa_register_driver(&pms_driver, 1);
+}
+
+static void __exit pms_exit(void)
+{
+	isa_unregister_driver(&pms_driver);
+}
+
+module_init(pms_init);
+module_exit(pms_exit);
diff --git a/drivers/media/parport/w9966.c b/drivers/media/parport/w9966.c
new file mode 100644
index 0000000..db2a600
--- /dev/null
+++ b/drivers/media/parport/w9966.c
@@ -0,0 +1,981 @@
+/*
+	Winbond w9966cf Webcam parport driver.
+
+	Version 0.33
+
+	Copyright (C) 2001 Jakob Kemi <jakob.kemi@post.utfors.se>
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the 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.
+*/
+/*
+	Supported devices:
+	*Lifeview FlyCam Supra (using the Philips saa7111a chip)
+
+	Does any other model using the w9966 interface chip exist ?
+
+	Todo:
+
+	*Add a working EPP mode, since DMA ECP read isn't implemented
+	in the parport drivers. (That's why it's so sloow)
+
+	*Add support for other ccd-control chips than the saa7111
+	please send me feedback on what kind of chips you have.
+
+	*Add proper probing. I don't know what's wrong with the IEEE1284
+	parport drivers but (IEEE1284_MODE_NIBBLE|IEEE1284_DEVICE_ID)
+	and nibble read seems to be broken for some peripherals.
+
+	*Add probing for onboard SRAM, port directions etc. (if possible)
+
+	*Add support for the hardware compressed modes (maybe using v4l2)
+
+	*Fix better support for the capture window (no skewed images, v4l
+	interface to capt. window)
+
+	*Probably some bugs that I don't know of
+
+	Please support me by sending feedback!
+
+	Changes:
+
+	Alan Cox:	Removed RGB mode for kernel merge, added THIS_MODULE
+			and owner support for newer module locks
+*/
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/videodev2.h>
+#include <linux/slab.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-fh.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-event.h>
+#include <linux/parport.h>
+
+/*#define DEBUG*/				/* Undef me for production */
+
+#ifdef DEBUG
+#define DPRINTF(x, a...) printk(KERN_DEBUG "W9966: %s(): "x, __func__ , ##a)
+#else
+#define DPRINTF(x...)
+#endif
+
+/*
+ *	Defines, simple typedefs etc.
+ */
+
+#define W9966_DRIVERNAME	"W9966CF Webcam"
+#define W9966_MAXCAMS		4	/* Maximum number of cameras */
+#define W9966_RBUFFER		2048	/* Read buffer (must be an even number) */
+#define W9966_SRAMSIZE		131072	/* 128kb */
+#define W9966_SRAMID		0x02	/* check w9966cf.pdf */
+
+/* Empirically determined window limits */
+#define W9966_WND_MIN_X		16
+#define W9966_WND_MIN_Y		14
+#define W9966_WND_MAX_X		705
+#define W9966_WND_MAX_Y		253
+#define W9966_WND_MAX_W		(W9966_WND_MAX_X - W9966_WND_MIN_X)
+#define W9966_WND_MAX_H		(W9966_WND_MAX_Y - W9966_WND_MIN_Y)
+
+/* Keep track of our current state */
+#define W9966_STATE_PDEV	0x01
+#define W9966_STATE_CLAIMED	0x02
+#define W9966_STATE_VDEV	0x04
+
+#define W9966_I2C_W_ID		0x48
+#define W9966_I2C_R_ID		0x49
+#define W9966_I2C_R_DATA	0x08
+#define W9966_I2C_R_CLOCK	0x04
+#define W9966_I2C_W_DATA	0x02
+#define W9966_I2C_W_CLOCK	0x01
+
+struct w9966 {
+	struct v4l2_device v4l2_dev;
+	struct v4l2_ctrl_handler hdl;
+	unsigned char dev_state;
+	unsigned char i2c_state;
+	unsigned short ppmode;
+	struct parport *pport;
+	struct pardevice *pdev;
+	struct video_device vdev;
+	unsigned short width;
+	unsigned short height;
+	unsigned char brightness;
+	signed char contrast;
+	signed char color;
+	signed char hue;
+	struct mutex lock;
+};
+
+/*
+ *	Module specific properties
+ */
+
+MODULE_AUTHOR("Jakob Kemi <jakob.kemi@post.utfors.se>");
+MODULE_DESCRIPTION("Winbond w9966cf WebCam driver (0.32)");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("0.33.1");
+
+#ifdef MODULE
+static char *pardev[] = {[0 ... W9966_MAXCAMS] = ""};
+#else
+static char *pardev[] = {[0 ... W9966_MAXCAMS] = "aggressive"};
+#endif
+module_param_array(pardev, charp, NULL, 0);
+MODULE_PARM_DESC(pardev, "pardev: where to search for\n"
+		"\teach camera. 'aggressive' means brute-force search.\n"
+		"\tEg: >pardev=parport3,aggressive,parport2,parport1< would assign\n"
+		"\tcam 1 to parport3 and search every parport for cam 2 etc...");
+
+static int parmode;
+module_param(parmode, int, 0);
+MODULE_PARM_DESC(parmode, "parmode: transfer mode (0=auto, 1=ecp, 2=epp");
+
+static int video_nr = -1;
+module_param(video_nr, int, 0);
+
+static struct w9966 w9966_cams[W9966_MAXCAMS];
+
+/*
+ *	Private function defines
+ */
+
+
+/* Set camera phase flags, so we know what to uninit when terminating */
+static inline void w9966_set_state(struct w9966 *cam, int mask, int val)
+{
+	cam->dev_state = (cam->dev_state & ~mask) ^ val;
+}
+
+/* Get camera phase flags */
+static inline int w9966_get_state(struct w9966 *cam, int mask, int val)
+{
+	return ((cam->dev_state & mask) == val);
+}
+
+/* Claim parport for ourself */
+static void w9966_pdev_claim(struct w9966 *cam)
+{
+	if (w9966_get_state(cam, W9966_STATE_CLAIMED, W9966_STATE_CLAIMED))
+		return;
+	parport_claim_or_block(cam->pdev);
+	w9966_set_state(cam, W9966_STATE_CLAIMED, W9966_STATE_CLAIMED);
+}
+
+/* Release parport for others to use */
+static void w9966_pdev_release(struct w9966 *cam)
+{
+	if (w9966_get_state(cam, W9966_STATE_CLAIMED, 0))
+		return;
+	parport_release(cam->pdev);
+	w9966_set_state(cam, W9966_STATE_CLAIMED, 0);
+}
+
+/* Read register from W9966 interface-chip
+   Expects a claimed pdev
+   -1 on error, else register data (byte) */
+static int w9966_read_reg(struct w9966 *cam, int reg)
+{
+	/* ECP, read, regtransfer, REG, REG, REG, REG, REG */
+	const unsigned char addr = 0x80 | (reg & 0x1f);
+	unsigned char val;
+
+	if (parport_negotiate(cam->pport, cam->ppmode | IEEE1284_ADDR) != 0)
+		return -1;
+	if (parport_write(cam->pport, &addr, 1) != 1)
+		return -1;
+	if (parport_negotiate(cam->pport, cam->ppmode | IEEE1284_DATA) != 0)
+		return -1;
+	if (parport_read(cam->pport, &val, 1) != 1)
+		return -1;
+
+	return val;
+}
+
+/* Write register to W9966 interface-chip
+   Expects a claimed pdev
+   -1 on error */
+static int w9966_write_reg(struct w9966 *cam, int reg, int data)
+{
+	/* ECP, write, regtransfer, REG, REG, REG, REG, REG */
+	const unsigned char addr = 0xc0 | (reg & 0x1f);
+	const unsigned char val = data;
+
+	if (parport_negotiate(cam->pport, cam->ppmode | IEEE1284_ADDR) != 0)
+		return -1;
+	if (parport_write(cam->pport, &addr, 1) != 1)
+		return -1;
+	if (parport_negotiate(cam->pport, cam->ppmode | IEEE1284_DATA) != 0)
+		return -1;
+	if (parport_write(cam->pport, &val, 1) != 1)
+		return -1;
+
+	return 0;
+}
+
+/*
+ *	Ugly and primitive i2c protocol functions
+ */
+
+/* Sets the data line on the i2c bus.
+   Expects a claimed pdev. */
+static void w9966_i2c_setsda(struct w9966 *cam, int state)
+{
+	if (state)
+		cam->i2c_state |= W9966_I2C_W_DATA;
+	else
+		cam->i2c_state &= ~W9966_I2C_W_DATA;
+
+	w9966_write_reg(cam, 0x18, cam->i2c_state);
+	udelay(5);
+}
+
+/* Get peripheral clock line
+   Expects a claimed pdev. */
+static int w9966_i2c_getscl(struct w9966 *cam)
+{
+	const unsigned char state = w9966_read_reg(cam, 0x18);
+	return ((state & W9966_I2C_R_CLOCK) > 0);
+}
+
+/* Sets the clock line on the i2c bus.
+   Expects a claimed pdev. -1 on error */
+static int w9966_i2c_setscl(struct w9966 *cam, int state)
+{
+	unsigned long timeout;
+
+	if (state)
+		cam->i2c_state |= W9966_I2C_W_CLOCK;
+	else
+		cam->i2c_state &= ~W9966_I2C_W_CLOCK;
+
+	w9966_write_reg(cam, 0x18, cam->i2c_state);
+	udelay(5);
+
+	/* we go to high, we also expect the peripheral to ack. */
+	if (state) {
+		timeout = jiffies + 100;
+		while (!w9966_i2c_getscl(cam)) {
+			if (time_after(jiffies, timeout))
+				return -1;
+		}
+	}
+	return 0;
+}
+
+#if 0
+/* Get peripheral data line
+   Expects a claimed pdev. */
+static int w9966_i2c_getsda(struct w9966 *cam)
+{
+	const unsigned char state = w9966_read_reg(cam, 0x18);
+	return ((state & W9966_I2C_R_DATA) > 0);
+}
+#endif
+
+/* Write a byte with ack to the i2c bus.
+   Expects a claimed pdev. -1 on error */
+static int w9966_i2c_wbyte(struct w9966 *cam, int data)
+{
+	int i;
+
+	for (i = 7; i >= 0; i--) {
+		w9966_i2c_setsda(cam, (data >> i) & 0x01);
+
+		if (w9966_i2c_setscl(cam, 1) == -1)
+			return -1;
+		w9966_i2c_setscl(cam, 0);
+	}
+
+	w9966_i2c_setsda(cam, 1);
+
+	if (w9966_i2c_setscl(cam, 1) == -1)
+		return -1;
+	w9966_i2c_setscl(cam, 0);
+
+	return 0;
+}
+
+/* Read a data byte with ack from the i2c-bus
+   Expects a claimed pdev. -1 on error */
+#if 0
+static int w9966_i2c_rbyte(struct w9966 *cam)
+{
+	unsigned char data = 0x00;
+	int i;
+
+	w9966_i2c_setsda(cam, 1);
+
+	for (i = 0; i < 8; i++) {
+		if (w9966_i2c_setscl(cam, 1) == -1)
+			return -1;
+		data = data << 1;
+		if (w9966_i2c_getsda(cam))
+			data |= 0x01;
+
+		w9966_i2c_setscl(cam, 0);
+	}
+	return data;
+}
+#endif
+
+/* Read a register from the i2c device.
+   Expects claimed pdev. -1 on error */
+#if 0
+static int w9966_read_reg_i2c(struct w9966 *cam, int reg)
+{
+	int data;
+
+	w9966_i2c_setsda(cam, 0);
+	w9966_i2c_setscl(cam, 0);
+
+	if (w9966_i2c_wbyte(cam, W9966_I2C_W_ID) == -1 ||
+	    w9966_i2c_wbyte(cam, reg) == -1)
+		return -1;
+
+	w9966_i2c_setsda(cam, 1);
+	if (w9966_i2c_setscl(cam, 1) == -1)
+		return -1;
+	w9966_i2c_setsda(cam, 0);
+	w9966_i2c_setscl(cam, 0);
+
+	if (w9966_i2c_wbyte(cam, W9966_I2C_R_ID) == -1)
+		return -1;
+	data = w9966_i2c_rbyte(cam);
+	if (data == -1)
+		return -1;
+
+	w9966_i2c_setsda(cam, 0);
+
+	if (w9966_i2c_setscl(cam, 1) == -1)
+		return -1;
+	w9966_i2c_setsda(cam, 1);
+
+	return data;
+}
+#endif
+
+/* Write a register to the i2c device.
+   Expects claimed pdev. -1 on error */
+static int w9966_write_reg_i2c(struct w9966 *cam, int reg, int data)
+{
+	w9966_i2c_setsda(cam, 0);
+	w9966_i2c_setscl(cam, 0);
+
+	if (w9966_i2c_wbyte(cam, W9966_I2C_W_ID) == -1 ||
+			w9966_i2c_wbyte(cam, reg) == -1 ||
+			w9966_i2c_wbyte(cam, data) == -1)
+		return -1;
+
+	w9966_i2c_setsda(cam, 0);
+	if (w9966_i2c_setscl(cam, 1) == -1)
+		return -1;
+
+	w9966_i2c_setsda(cam, 1);
+
+	return 0;
+}
+
+/* Find a good length for capture window (used both for W and H)
+   A bit ugly but pretty functional. The capture length
+   have to match the downscale */
+static int w9966_findlen(int near, int size, int maxlen)
+{
+	int bestlen = size;
+	int besterr = abs(near - bestlen);
+	int len;
+
+	for (len = size + 1; len < maxlen; len++) {
+		int err;
+		if (((64 * size) % len) != 0)
+			continue;
+
+		err = abs(near - len);
+
+		/* Only continue as long as we keep getting better values */
+		if (err > besterr)
+			break;
+
+		besterr = err;
+		bestlen = len;
+	}
+
+	return bestlen;
+}
+
+/* Modify capture window (if necessary)
+   and calculate downscaling
+   Return -1 on error */
+static int w9966_calcscale(int size, int min, int max, int *beg, int *end, unsigned char *factor)
+{
+	int maxlen = max - min;
+	int len = *end - *beg + 1;
+	int newlen = w9966_findlen(len, size, maxlen);
+	int err = newlen - len;
+
+	/* Check for bad format */
+	if (newlen > maxlen || newlen < size)
+		return -1;
+
+	/* Set factor (6 bit fixed) */
+	*factor = (64 * size) / newlen;
+	if (*factor == 64)
+		*factor = 0x00;	/* downscale is disabled */
+	else
+		*factor |= 0x80; /* set downscale-enable bit */
+
+	/* Modify old beginning and end */
+	*beg -= err / 2;
+	*end += err - (err / 2);
+
+	/* Move window if outside borders */
+	if (*beg < min) {
+		*end += min - *beg;
+		*beg += min - *beg;
+	}
+	if (*end > max) {
+		*beg -= *end - max;
+		*end -= *end - max;
+	}
+
+	return 0;
+}
+
+/* Setup the cameras capture window etc.
+   Expects a claimed pdev
+   return -1 on error */
+static int w9966_setup(struct w9966 *cam, int x1, int y1, int x2, int y2, int w, int h)
+{
+	unsigned int i;
+	unsigned int enh_s, enh_e;
+	unsigned char scale_x, scale_y;
+	unsigned char regs[0x1c];
+	unsigned char saa7111_regs[] = {
+		0x21, 0x00, 0xd8, 0x23, 0x00, 0x80, 0x80, 0x00,
+		0x88, 0x10, 0x80, 0x40, 0x40, 0x00, 0x01, 0x00,
+		0x48, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x71, 0xe7, 0x00, 0x00, 0xc0
+	};
+
+
+	if (w * h * 2 > W9966_SRAMSIZE) {
+		DPRINTF("capture window exceeds SRAM size!.\n");
+		w = 200; h = 160;	/* Pick default values */
+	}
+
+	w &= ~0x1;
+	if (w < 2)
+		w = 2;
+	if (h < 1)
+		h = 1;
+	if (w > W9966_WND_MAX_W)
+		w = W9966_WND_MAX_W;
+	if (h > W9966_WND_MAX_H)
+		h = W9966_WND_MAX_H;
+
+	cam->width = w;
+	cam->height = h;
+
+	enh_s = 0;
+	enh_e = w * h * 2;
+
+	/* Modify capture window if necessary and calculate downscaling */
+	if (w9966_calcscale(w, W9966_WND_MIN_X, W9966_WND_MAX_X, &x1, &x2, &scale_x) != 0 ||
+			w9966_calcscale(h, W9966_WND_MIN_Y, W9966_WND_MAX_Y, &y1, &y2, &scale_y) != 0)
+		return -1;
+
+	DPRINTF("%dx%d, x: %d<->%d, y: %d<->%d, sx: %d/64, sy: %d/64.\n",
+			w, h, x1, x2, y1, y2, scale_x & ~0x80, scale_y & ~0x80);
+
+	/* Setup registers */
+	regs[0x00] = 0x00;			/* Set normal operation */
+	regs[0x01] = 0x18;			/* Capture mode */
+	regs[0x02] = scale_y;			/* V-scaling */
+	regs[0x03] = scale_x;			/* H-scaling */
+
+	/* Capture window */
+	regs[0x04] = (x1 & 0x0ff);		/* X-start (8 low bits) */
+	regs[0x05] = (x1 & 0x300)>>8;		/* X-start (2 high bits) */
+	regs[0x06] = (y1 & 0x0ff);		/* Y-start (8 low bits) */
+	regs[0x07] = (y1 & 0x300)>>8;		/* Y-start (2 high bits) */
+	regs[0x08] = (x2 & 0x0ff);		/* X-end (8 low bits) */
+	regs[0x09] = (x2 & 0x300)>>8;		/* X-end (2 high bits) */
+	regs[0x0a] = (y2 & 0x0ff);		/* Y-end (8 low bits) */
+
+	regs[0x0c] = W9966_SRAMID;		/* SRAM-banks (1x 128kb) */
+
+	/* Enhancement layer */
+	regs[0x0d] = (enh_s & 0x000ff);		/* Enh. start (0-7) */
+	regs[0x0e] = (enh_s & 0x0ff00) >> 8;	/* Enh. start (8-15) */
+	regs[0x0f] = (enh_s & 0x70000) >> 16;	/* Enh. start (16-17/18??) */
+	regs[0x10] = (enh_e & 0x000ff);		/* Enh. end (0-7) */
+	regs[0x11] = (enh_e & 0x0ff00) >> 8;	/* Enh. end (8-15) */
+	regs[0x12] = (enh_e & 0x70000) >> 16;	/* Enh. end (16-17/18??) */
+
+	/* Misc */
+	regs[0x13] = 0x40;			/* VEE control (raw 4:2:2) */
+	regs[0x17] = 0x00;			/* ??? */
+	regs[0x18] = cam->i2c_state = 0x00;	/* Serial bus */
+	regs[0x19] = 0xff;			/* I/O port direction control */
+	regs[0x1a] = 0xff;			/* I/O port data register */
+	regs[0x1b] = 0x10;			/* ??? */
+
+	/* SAA7111 chip settings */
+	saa7111_regs[0x0a] = cam->brightness;
+	saa7111_regs[0x0b] = cam->contrast;
+	saa7111_regs[0x0c] = cam->color;
+	saa7111_regs[0x0d] = cam->hue;
+
+	/* Reset (ECP-fifo & serial-bus) */
+	if (w9966_write_reg(cam, 0x00, 0x03) == -1)
+		return -1;
+
+	/* Write regs to w9966cf chip */
+	for (i = 0; i < 0x1c; i++)
+		if (w9966_write_reg(cam, i, regs[i]) == -1)
+			return -1;
+
+	/* Write regs to saa7111 chip */
+	for (i = 0; i < 0x20; i++)
+		if (w9966_write_reg_i2c(cam, i, saa7111_regs[i]) == -1)
+			return -1;
+
+	return 0;
+}
+
+/*
+ *	Video4linux interfacing
+ */
+
+static int cam_querycap(struct file *file, void  *priv,
+					struct v4l2_capability *vcap)
+{
+	struct w9966 *cam = video_drvdata(file);
+
+	strlcpy(vcap->driver, cam->v4l2_dev.name, sizeof(vcap->driver));
+	strlcpy(vcap->card, W9966_DRIVERNAME, sizeof(vcap->card));
+	strlcpy(vcap->bus_info, "parport", sizeof(vcap->bus_info));
+	vcap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE;
+	vcap->capabilities = vcap->device_caps | V4L2_CAP_DEVICE_CAPS;
+	return 0;
+}
+
+static int cam_enum_input(struct file *file, void *fh, struct v4l2_input *vin)
+{
+	if (vin->index > 0)
+		return -EINVAL;
+	strlcpy(vin->name, "Camera", sizeof(vin->name));
+	vin->type = V4L2_INPUT_TYPE_CAMERA;
+	vin->audioset = 0;
+	vin->tuner = 0;
+	vin->std = 0;
+	vin->status = 0;
+	return 0;
+}
+
+static int cam_g_input(struct file *file, void *fh, unsigned int *inp)
+{
+	*inp = 0;
+	return 0;
+}
+
+static int cam_s_input(struct file *file, void *fh, unsigned int inp)
+{
+	return (inp > 0) ? -EINVAL : 0;
+}
+
+static int cam_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct w9966 *cam =
+		container_of(ctrl->handler, struct w9966, hdl);
+	int ret = 0;
+
+	mutex_lock(&cam->lock);
+	switch (ctrl->id) {
+	case V4L2_CID_BRIGHTNESS:
+		cam->brightness = ctrl->val;
+		break;
+	case V4L2_CID_CONTRAST:
+		cam->contrast = ctrl->val;
+		break;
+	case V4L2_CID_SATURATION:
+		cam->color = ctrl->val;
+		break;
+	case V4L2_CID_HUE:
+		cam->hue = ctrl->val;
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	if (ret == 0) {
+		w9966_pdev_claim(cam);
+
+		if (w9966_write_reg_i2c(cam, 0x0a, cam->brightness) == -1 ||
+		    w9966_write_reg_i2c(cam, 0x0b, cam->contrast) == -1 ||
+		    w9966_write_reg_i2c(cam, 0x0c, cam->color) == -1 ||
+		    w9966_write_reg_i2c(cam, 0x0d, cam->hue) == -1) {
+			ret = -EIO;
+		}
+
+		w9966_pdev_release(cam);
+	}
+	mutex_unlock(&cam->lock);
+	return ret;
+}
+
+static int cam_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+	struct w9966 *cam = video_drvdata(file);
+	struct v4l2_pix_format *pix = &fmt->fmt.pix;
+
+	pix->width = cam->width;
+	pix->height = cam->height;
+	pix->pixelformat = V4L2_PIX_FMT_YUYV;
+	pix->field = V4L2_FIELD_NONE;
+	pix->bytesperline = 2 * cam->width;
+	pix->sizeimage = 2 * cam->width * cam->height;
+	/* Just a guess */
+	pix->colorspace = V4L2_COLORSPACE_SMPTE170M;
+	return 0;
+}
+
+static int cam_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+	struct v4l2_pix_format *pix = &fmt->fmt.pix;
+
+	if (pix->width < 2)
+		pix->width = 2;
+	if (pix->height < 1)
+		pix->height = 1;
+	if (pix->width > W9966_WND_MAX_W)
+		pix->width = W9966_WND_MAX_W;
+	if (pix->height > W9966_WND_MAX_H)
+		pix->height = W9966_WND_MAX_H;
+	pix->pixelformat = V4L2_PIX_FMT_YUYV;
+	pix->field = V4L2_FIELD_NONE;
+	pix->bytesperline = 2 * pix->width;
+	pix->sizeimage = 2 * pix->width * pix->height;
+	/* Just a guess */
+	pix->colorspace = V4L2_COLORSPACE_SMPTE170M;
+	return 0;
+}
+
+static int cam_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+	struct w9966 *cam = video_drvdata(file);
+	struct v4l2_pix_format *pix = &fmt->fmt.pix;
+	int ret = cam_try_fmt_vid_cap(file, fh, fmt);
+
+	if (ret)
+		return ret;
+
+	mutex_lock(&cam->lock);
+	/* Update camera regs */
+	w9966_pdev_claim(cam);
+	ret = w9966_setup(cam, 0, 0, 1023, 1023, pix->width, pix->height);
+	w9966_pdev_release(cam);
+	mutex_unlock(&cam->lock);
+	return ret;
+}
+
+static int cam_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt)
+{
+	static struct v4l2_fmtdesc formats[] = {
+		{ 0, 0, 0,
+		  "YUV 4:2:2", V4L2_PIX_FMT_YUYV,
+		  { 0, 0, 0, 0 }
+		},
+	};
+	enum v4l2_buf_type type = fmt->type;
+
+	if (fmt->index > 0)
+		return -EINVAL;
+
+	*fmt = formats[fmt->index];
+	fmt->type = type;
+	return 0;
+}
+
+/* Capture data */
+static ssize_t w9966_v4l_read(struct file *file, char  __user *buf,
+		size_t count, loff_t *ppos)
+{
+	struct w9966 *cam = video_drvdata(file);
+	unsigned char addr = 0xa0;	/* ECP, read, CCD-transfer, 00000 */
+	unsigned char __user *dest = (unsigned char __user *)buf;
+	unsigned long dleft = count;
+	unsigned char *tbuf;
+
+	/* Why would anyone want more than this?? */
+	if (count > cam->width * cam->height * 2)
+		return -EINVAL;
+
+	mutex_lock(&cam->lock);
+	w9966_pdev_claim(cam);
+	w9966_write_reg(cam, 0x00, 0x02);	/* Reset ECP-FIFO buffer */
+	w9966_write_reg(cam, 0x00, 0x00);	/* Return to normal operation */
+	w9966_write_reg(cam, 0x01, 0x98);	/* Enable capture */
+
+	/* write special capture-addr and negotiate into data transfer */
+	if ((parport_negotiate(cam->pport, cam->ppmode|IEEE1284_ADDR) != 0) ||
+			(parport_write(cam->pport, &addr, 1) != 1) ||
+			(parport_negotiate(cam->pport, cam->ppmode|IEEE1284_DATA) != 0)) {
+		w9966_pdev_release(cam);
+		mutex_unlock(&cam->lock);
+		return -EFAULT;
+	}
+
+	tbuf = kmalloc(W9966_RBUFFER, GFP_KERNEL);
+	if (tbuf == NULL) {
+		count = -ENOMEM;
+		goto out;
+	}
+
+	while (dleft > 0) {
+		unsigned long tsize = (dleft > W9966_RBUFFER) ? W9966_RBUFFER : dleft;
+
+		if (parport_read(cam->pport, tbuf, tsize) < tsize) {
+			count = -EFAULT;
+			goto out;
+		}
+		if (copy_to_user(dest, tbuf, tsize) != 0) {
+			count = -EFAULT;
+			goto out;
+		}
+		dest += tsize;
+		dleft -= tsize;
+	}
+
+	w9966_write_reg(cam, 0x01, 0x18);	/* Disable capture */
+
+out:
+	kfree(tbuf);
+	w9966_pdev_release(cam);
+	mutex_unlock(&cam->lock);
+
+	return count;
+}
+
+static const struct v4l2_file_operations w9966_fops = {
+	.owner		= THIS_MODULE,
+	.open		= v4l2_fh_open,
+	.release	= v4l2_fh_release,
+	.poll		= v4l2_ctrl_poll,
+	.unlocked_ioctl = video_ioctl2,
+	.read           = w9966_v4l_read,
+};
+
+static const struct v4l2_ioctl_ops w9966_ioctl_ops = {
+	.vidioc_querycap    		    = cam_querycap,
+	.vidioc_g_input      		    = cam_g_input,
+	.vidioc_s_input      		    = cam_s_input,
+	.vidioc_enum_input   		    = cam_enum_input,
+	.vidioc_enum_fmt_vid_cap 	    = cam_enum_fmt_vid_cap,
+	.vidioc_g_fmt_vid_cap 		    = cam_g_fmt_vid_cap,
+	.vidioc_s_fmt_vid_cap  		    = cam_s_fmt_vid_cap,
+	.vidioc_try_fmt_vid_cap  	    = cam_try_fmt_vid_cap,
+	.vidioc_log_status		    = v4l2_ctrl_log_status,
+	.vidioc_subscribe_event		    = v4l2_ctrl_subscribe_event,
+	.vidioc_unsubscribe_event	    = v4l2_event_unsubscribe,
+};
+
+static const struct v4l2_ctrl_ops cam_ctrl_ops = {
+	.s_ctrl = cam_s_ctrl,
+};
+
+
+/* Initialize camera device. Setup all internal flags, set a
+   default video mode, setup ccd-chip, register v4l device etc..
+   Also used for 'probing' of hardware.
+   -1 on error */
+static int w9966_init(struct w9966 *cam, struct parport *port)
+{
+	struct v4l2_device *v4l2_dev = &cam->v4l2_dev;
+
+	if (cam->dev_state != 0)
+		return -1;
+
+	strlcpy(v4l2_dev->name, "w9966", sizeof(v4l2_dev->name));
+
+	if (v4l2_device_register(NULL, v4l2_dev) < 0) {
+		v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
+		return -1;
+	}
+
+	v4l2_ctrl_handler_init(&cam->hdl, 4);
+	v4l2_ctrl_new_std(&cam->hdl, &cam_ctrl_ops,
+			  V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
+	v4l2_ctrl_new_std(&cam->hdl, &cam_ctrl_ops,
+			  V4L2_CID_CONTRAST, -64, 64, 1, 64);
+	v4l2_ctrl_new_std(&cam->hdl, &cam_ctrl_ops,
+			  V4L2_CID_SATURATION, -64, 64, 1, 64);
+	v4l2_ctrl_new_std(&cam->hdl, &cam_ctrl_ops,
+			  V4L2_CID_HUE, -128, 127, 1, 0);
+	if (cam->hdl.error) {
+		v4l2_err(v4l2_dev, "couldn't register controls\n");
+		return -1;
+	}
+	cam->pport = port;
+	cam->brightness = 128;
+	cam->contrast = 64;
+	cam->color = 64;
+	cam->hue = 0;
+
+	/* Select requested transfer mode */
+	switch (parmode) {
+	default:	/* Auto-detect (priority: hw-ecp, hw-epp, sw-ecp) */
+	case 0:
+		if (port->modes & PARPORT_MODE_ECP)
+			cam->ppmode = IEEE1284_MODE_ECP;
+		else if (port->modes & PARPORT_MODE_EPP)
+			cam->ppmode = IEEE1284_MODE_EPP;
+		else
+			cam->ppmode = IEEE1284_MODE_ECP;
+		break;
+	case 1:		/* hw- or sw-ecp */
+		cam->ppmode = IEEE1284_MODE_ECP;
+		break;
+	case 2:		/* hw- or sw-epp */
+		cam->ppmode = IEEE1284_MODE_EPP;
+		break;
+	}
+
+	/* Tell the parport driver that we exists */
+	cam->pdev = parport_register_device(port, "w9966", NULL, NULL, NULL, 0, NULL);
+	if (cam->pdev == NULL) {
+		DPRINTF("parport_register_device() failed\n");
+		return -1;
+	}
+	w9966_set_state(cam, W9966_STATE_PDEV, W9966_STATE_PDEV);
+
+	w9966_pdev_claim(cam);
+
+	/* Setup a default capture mode */
+	if (w9966_setup(cam, 0, 0, 1023, 1023, 200, 160) != 0) {
+		DPRINTF("w9966_setup() failed.\n");
+		return -1;
+	}
+
+	w9966_pdev_release(cam);
+
+	/* Fill in the video_device struct and register us to v4l */
+	strlcpy(cam->vdev.name, W9966_DRIVERNAME, sizeof(cam->vdev.name));
+	cam->vdev.v4l2_dev = v4l2_dev;
+	cam->vdev.fops = &w9966_fops;
+	cam->vdev.ioctl_ops = &w9966_ioctl_ops;
+	cam->vdev.release = video_device_release_empty;
+	cam->vdev.ctrl_handler = &cam->hdl;
+	set_bit(V4L2_FL_USE_FH_PRIO, &cam->vdev.flags);
+	video_set_drvdata(&cam->vdev, cam);
+
+	mutex_init(&cam->lock);
+
+	if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, video_nr) < 0)
+		return -1;
+
+	w9966_set_state(cam, W9966_STATE_VDEV, W9966_STATE_VDEV);
+
+	/* All ok */
+	v4l2_info(v4l2_dev, "Found and initialized a webcam on %s.\n",
+			cam->pport->name);
+	return 0;
+}
+
+
+/* Terminate everything gracefully */
+static void w9966_term(struct w9966 *cam)
+{
+	/* Unregister from v4l */
+	if (w9966_get_state(cam, W9966_STATE_VDEV, W9966_STATE_VDEV)) {
+		video_unregister_device(&cam->vdev);
+		w9966_set_state(cam, W9966_STATE_VDEV, 0);
+	}
+
+	v4l2_ctrl_handler_free(&cam->hdl);
+
+	/* Terminate from IEEE1284 mode and release pdev block */
+	if (w9966_get_state(cam, W9966_STATE_PDEV, W9966_STATE_PDEV)) {
+		w9966_pdev_claim(cam);
+		parport_negotiate(cam->pport, IEEE1284_MODE_COMPAT);
+		w9966_pdev_release(cam);
+	}
+
+	/* Unregister from parport */
+	if (w9966_get_state(cam, W9966_STATE_PDEV, W9966_STATE_PDEV)) {
+		parport_unregister_device(cam->pdev);
+		w9966_set_state(cam, W9966_STATE_PDEV, 0);
+	}
+	memset(cam, 0, sizeof(*cam));
+}
+
+
+/* Called once for every parport on init */
+static void w9966_attach(struct parport *port)
+{
+	int i;
+
+	for (i = 0; i < W9966_MAXCAMS; i++) {
+		if (w9966_cams[i].dev_state != 0)	/* Cam is already assigned */
+			continue;
+		if (strcmp(pardev[i], "aggressive") == 0 || strcmp(pardev[i], port->name) == 0) {
+			if (w9966_init(&w9966_cams[i], port) != 0)
+				w9966_term(&w9966_cams[i]);
+			break;	/* return */
+		}
+	}
+}
+
+/* Called once for every parport on termination */
+static void w9966_detach(struct parport *port)
+{
+	int i;
+
+	for (i = 0; i < W9966_MAXCAMS; i++)
+		if (w9966_cams[i].dev_state != 0 && w9966_cams[i].pport == port)
+			w9966_term(&w9966_cams[i]);
+}
+
+
+static struct parport_driver w9966_ppd = {
+	.name = W9966_DRIVERNAME,
+	.attach = w9966_attach,
+	.detach = w9966_detach,
+};
+
+/* Module entry point */
+static int __init w9966_mod_init(void)
+{
+	int i;
+
+	for (i = 0; i < W9966_MAXCAMS; i++)
+		w9966_cams[i].dev_state = 0;
+
+	return parport_register_driver(&w9966_ppd);
+}
+
+/* Module cleanup */
+static void __exit w9966_mod_term(void)
+{
+	parport_unregister_driver(&w9966_ppd);
+}
+
+module_init(w9966_mod_init);
+module_exit(w9966_mod_term);
diff --git a/drivers/media/pci/Kconfig b/drivers/media/pci/Kconfig
new file mode 100644
index 0000000..d4e2ed3
--- /dev/null
+++ b/drivers/media/pci/Kconfig
@@ -0,0 +1,47 @@
+menuconfig MEDIA_PCI_SUPPORT
+	bool "Media PCI Adapters"
+	depends on PCI && MEDIA_SUPPORT
+	help
+	  Enable media drivers for PCI/PCIe bus.
+	  If you have such devices, say Y.
+
+if MEDIA_PCI_SUPPORT
+
+if MEDIA_CAMERA_SUPPORT
+	comment "Media capture support"
+source "drivers/media/pci/meye/Kconfig"
+source "drivers/media/pci/sta2x11/Kconfig"
+endif
+
+if MEDIA_ANALOG_TV_SUPPORT
+	comment "Media capture/analog TV support"
+source "drivers/media/pci/ivtv/Kconfig"
+source "drivers/media/pci/zoran/Kconfig"
+source "drivers/media/pci/saa7146/Kconfig"
+endif
+
+if MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT
+	comment "Media capture/analog/hybrid TV support"
+source "drivers/media/pci/cx18/Kconfig"
+source "drivers/media/pci/cx23885/Kconfig"
+source "drivers/media/pci/cx25821/Kconfig"
+source "drivers/media/pci/cx88/Kconfig"
+source "drivers/media/pci/bt8xx/Kconfig"
+source "drivers/media/pci/saa7134/Kconfig"
+source "drivers/media/pci/saa7164/Kconfig"
+
+endif
+
+if MEDIA_DIGITAL_TV_SUPPORT
+	comment "Media digital TV PCI Adapters"
+source "drivers/media/pci/ttpci/Kconfig"
+source "drivers/media/pci/b2c2/Kconfig"
+source "drivers/media/pci/pluto2/Kconfig"
+source "drivers/media/pci/dm1105/Kconfig"
+source "drivers/media/pci/pt1/Kconfig"
+source "drivers/media/pci/mantis/Kconfig"
+source "drivers/media/pci/ngene/Kconfig"
+source "drivers/media/pci/ddbridge/Kconfig"
+endif
+
+endif #MEDIA_PCI_SUPPORT
diff --git a/drivers/media/pci/Makefile b/drivers/media/pci/Makefile
new file mode 100644
index 0000000..35cc578
--- /dev/null
+++ b/drivers/media/pci/Makefile
@@ -0,0 +1,26 @@
+#
+# Makefile for the kernel multimedia device drivers.
+#
+
+obj-y        +=	ttpci/		\
+		b2c2/		\
+		pluto2/		\
+		dm1105/		\
+		pt1/		\
+		mantis/		\
+		ngene/		\
+		ddbridge/	\
+		b2c2/		\
+		saa7146/
+
+obj-$(CONFIG_VIDEO_IVTV) += ivtv/
+obj-$(CONFIG_VIDEO_ZORAN) += zoran/
+obj-$(CONFIG_VIDEO_CX18) += cx18/
+obj-$(CONFIG_VIDEO_CX23885) += cx23885/
+obj-$(CONFIG_VIDEO_CX25821) += cx25821/
+obj-$(CONFIG_VIDEO_CX88) += cx88/
+obj-$(CONFIG_VIDEO_BT848) += bt8xx/
+obj-$(CONFIG_VIDEO_SAA7134) += saa7134/
+obj-$(CONFIG_VIDEO_SAA7164) += saa7164/
+obj-$(CONFIG_VIDEO_MEYE) += meye/
+obj-$(CONFIG_STA2X11_VIP) += sta2x11/
diff --git a/drivers/media/pci/b2c2/Kconfig b/drivers/media/pci/b2c2/Kconfig
new file mode 100644
index 0000000..58761a2
--- /dev/null
+++ b/drivers/media/pci/b2c2/Kconfig
@@ -0,0 +1,15 @@
+config DVB_B2C2_FLEXCOP_PCI
+	tristate "Technisat/B2C2 Air/Sky/Cable2PC PCI"
+	depends on DVB_CORE && I2C
+	help
+	  Support for the Air/Sky/CableStar2 PCI card (DVB/ATSC) by Technisat/B2C2.
+
+	  Say Y if you own such a device and want to use it.
+
+config DVB_B2C2_FLEXCOP_PCI_DEBUG
+	bool "Enable debug for the B2C2 FlexCop drivers"
+	depends on DVB_B2C2_FLEXCOP_PCI
+	select DVB_B2C2_FLEXCOP_DEBUG
+	help
+	Say Y if you want to enable the module option to control debug messages
+	of all B2C2 FlexCop drivers.
diff --git a/drivers/media/pci/b2c2/Makefile b/drivers/media/pci/b2c2/Makefile
new file mode 100644
index 0000000..b894320
--- /dev/null
+++ b/drivers/media/pci/b2c2/Makefile
@@ -0,0 +1,9 @@
+ifneq ($(CONFIG_DVB_B2C2_FLEXCOP_PCI),)
+b2c2-flexcop-pci-objs += flexcop-dma.o
+endif
+
+b2c2-flexcop-pci-objs += flexcop-pci.o
+obj-$(CONFIG_DVB_B2C2_FLEXCOP_PCI) += b2c2-flexcop-pci.o
+
+ccflags-y += -Idrivers/media/dvb-core/
+ccflags-y += -Idrivers/media/common/b2c2/
diff --git a/drivers/media/pci/b2c2/flexcop-dma.c b/drivers/media/pci/b2c2/flexcop-dma.c
new file mode 100644
index 0000000..2881e0d
--- /dev/null
+++ b/drivers/media/pci/b2c2/flexcop-dma.c
@@ -0,0 +1,172 @@
+/*
+ * 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)
+{
+	u8 *tcpu;
+	dma_addr_t tdma = 0;
+
+	if (size % 2) {
+		err("dma buffersize has to be even.");
+		return -EINVAL;
+	}
+
+	if ((tcpu = pci_alloc_consistent(pdev, size, &tdma)) != NULL) {
+		dma->pdev = pdev;
+		dma->cpu_addr0 = tcpu;
+		dma->dma_addr0 = tdma;
+		dma->cpu_addr1 = tcpu + size/2;
+		dma->dma_addr1 = tdma + size/2;
+		dma->size = size/2;
+		return 0;
+	}
+	return -ENOMEM;
+}
+EXPORT_SYMBOL(flexcop_dma_allocate);
+
+void flexcop_dma_free(struct flexcop_dma *dma)
+{
+	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);
+
+int flexcop_dma_config(struct flexcop_device *fc,
+		struct flexcop_dma *dma,
+		flexcop_dma_index_t dma_idx)
+{
+	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;
+	v0x4.dma_0x4_write.dma_addr_size = dma->size / 4;
+
+	if ((dma_idx & FC_DMA_1) == dma_idx) {
+		fc->write_ibi_reg(fc,dma1_000,v0x0);
+		fc->write_ibi_reg(fc,dma1_004,v0x4);
+		fc->write_ibi_reg(fc,dma1_00c,v0xc);
+	} else if ((dma_idx & FC_DMA_2) == dma_idx) {
+		fc->write_ibi_reg(fc,dma2_010,v0x0);
+		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 within one "
+			"flexcop_dma_config call.");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(flexcop_dma_config);
+
+/* start the DMA transfers, but not the DMA IRQs */
+int flexcop_dma_xfer_control(struct flexcop_device *fc,
+		flexcop_dma_index_t dma_idx,
+		flexcop_dma_addr_index_t index,
+		int onoff)
+{
+	flexcop_ibi_value v0x0,v0xc;
+	flexcop_ibi_register r0x0,r0xc;
+
+	if ((dma_idx & FC_DMA_1) == dma_idx) {
+		r0x0 = dma1_000;
+		r0xc = dma1_00c;
+	} else if ((dma_idx & FC_DMA_2) == dma_idx) {
+		r0x0 = dma2_010;
+		r0xc = dma2_01c;
+	} else {
+		err("either transfer DMA1 or DMA2 can be started within one "
+			"flexcop_dma_xfer_control call.");
+		return -EINVAL;
+	}
+
+	v0x0 = fc->read_ibi_reg(fc,r0x0);
+	v0xc = fc->read_ibi_reg(fc,r0xc);
+
+	deb_rdump("reg: %03x: %x\n",r0x0,v0x0.raw);
+	deb_rdump("reg: %03x: %x\n",r0xc,v0xc.raw);
+
+	if (index & FC_DMA_SUBADDR_0)
+		v0x0.dma_0x0.dma_0start = onoff;
+
+	if (index & FC_DMA_SUBADDR_1)
+		v0xc.dma_0xc.dma_1start = onoff;
+
+	fc->write_ibi_reg(fc,r0x0,v0x0);
+	fc->write_ibi_reg(fc,r0xc,v0xc);
+
+	deb_rdump("reg: %03x: %x\n",r0x0,v0x0.raw);
+	deb_rdump("reg: %03x: %x\n",r0xc,v0xc.raw);
+	return 0;
+}
+EXPORT_SYMBOL(flexcop_dma_xfer_control);
+
+static int flexcop_dma_remap(struct flexcop_device *fc,
+		flexcop_dma_index_t dma_idx,
+		int onoff)
+{
+	flexcop_ibi_register r = (dma_idx & FC_DMA_1) ? dma1_00c : dma2_01c;
+	flexcop_ibi_value v = fc->read_ibi_reg(fc,r);
+	deb_info("%s\n",__func__);
+	v.dma_0xc.remap_enable = onoff;
+	fc->write_ibi_reg(fc,r,v);
+	return 0;
+}
+
+int flexcop_dma_control_size_irq(struct flexcop_device *fc,
+		flexcop_dma_index_t no,
+		int onoff)
+{
+	flexcop_ibi_value v = fc->read_ibi_reg(fc,ctrl_208);
+
+	if (no & FC_DMA_1)
+		v.ctrl_208.DMA1_IRQ_Enable_sig = onoff;
+
+	if (no & FC_DMA_2)
+		v.ctrl_208.DMA2_IRQ_Enable_sig = onoff;
+
+	fc->write_ibi_reg(fc,ctrl_208,v);
+	return 0;
+}
+EXPORT_SYMBOL(flexcop_dma_control_size_irq);
+
+int flexcop_dma_control_timer_irq(struct flexcop_device *fc,
+		flexcop_dma_index_t no,
+		int onoff)
+{
+	flexcop_ibi_value v = fc->read_ibi_reg(fc,ctrl_208);
+
+	if (no & FC_DMA_1)
+		v.ctrl_208.DMA1_Timer_Enable_sig = onoff;
+
+	if (no & FC_DMA_2)
+		v.ctrl_208.DMA2_Timer_Enable_sig = onoff;
+
+	fc->write_ibi_reg(fc,ctrl_208,v);
+	return 0;
+}
+EXPORT_SYMBOL(flexcop_dma_control_timer_irq);
+
+/* 1 cycles = 1.97 msec */
+int flexcop_dma_config_timer(struct flexcop_device *fc,
+		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);
+
+	flexcop_dma_remap(fc,dma_idx,0);
+
+	deb_info("%s\n",__func__);
+	v.dma_0x4_write.dmatimer = cycles;
+	fc->write_ibi_reg(fc,r,v);
+	return 0;
+}
+EXPORT_SYMBOL(flexcop_dma_config_timer);
+
diff --git a/drivers/media/pci/b2c2/flexcop-pci.c b/drivers/media/pci/b2c2/flexcop-pci.c
new file mode 100644
index 0000000..44f8fb5
--- /dev/null
+++ b/drivers/media/pci/b2c2/flexcop-pci.c
@@ -0,0 +1,450 @@
+/*
+ * 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"
+#include "flexcop-common.h"
+
+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");
+
+static int irq_chk_intv = 100;
+module_param(irq_chk_intv, int, 0644);
+MODULE_PARM_DESC(irq_chk_intv, "set the interval for IRQ streaming watchdog.");
+
+#ifdef CONFIG_DVB_B2C2_FLEXCOP_DEBUG
+#define dprintk(level,args...) \
+	do { if ((debug & level)) printk(args); } while (0)
+#define DEBSTATUS ""
+#else
+#define dprintk(level,args...)
+#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)
+
+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);
+
+#define DRIVER_VERSION "0.1"
+#define DRIVER_NAME "flexcop-pci"
+#define DRIVER_AUTHOR "Patrick Boettcher <patrick.boettcher@desy.de>"
+
+struct flexcop_pci {
+	struct pci_dev *pdev;
+
+#define FC_PCI_INIT     0x01
+#define FC_PCI_DMA_INIT 0x02
+	int init_state;
+
+	void __iomem *io_mem;
+	u32 irq;
+	/* 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 occurred */
+	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 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;
+	v.raw = readl(fc_pci->io_mem + r);
+
+	if (lastrreg != r || lastrval != v.raw) {
+		lastrreg = r; lastrval = 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)
+{
+	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);
+	}
+
+	writel(v.raw, fc_pci->io_mem + r);
+	return 0;
+}
+
+static void flexcop_pci_irq_check_work(struct work_struct *work)
+{
+	struct flexcop_pci *fc_pci =
+		container_of(work, struct flexcop_pci, irq_check_work.work);
+	struct flexcop_device *fc = fc_pci->fc_dev;
+
+	if (fc->feedcount) {
+
+		if (fc_pci->count == fc_pci->count_prev) {
+			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) {
+					flexcop_pid_feed_control(fc, feed, 0);
+				}
+
+				list_for_each_entry(feed, &fc->demux.feed_list,
+						list_head) {
+					flexcop_pid_feed_control(fc, feed, 1);
+				}
+				spin_unlock_irq(&fc->demux.lock);
+
+				fc_pci->stream_problem = 0;
+			}
+		} else {
+			fc_pci->stream_problem = 0;
+			fc_pci->count_prev = fc_pci->count;
+		}
+	}
+
+	schedule_delayed_work(&fc_pci->irq_check_work,
+			msecs_to_jiffies(irq_chk_intv < 100 ? 100 : irq_chk_intv));
+}
+
+/* When PID filtering is turned on, we use the timer IRQ, because small amounts
+ * of data need to be passed to the user space instantly as well. When PID
+ * filtering is turned off, we use the page-change-IRQ */
+static irqreturn_t flexcop_pci_isr(int irq, void *dev_id)
+{
+	struct flexcop_pci *fc_pci = dev_id;
+	struct flexcop_device *fc = fc_pci->fc_dev;
+	unsigned long flags;
+	flexcop_ibi_value v;
+	irqreturn_t ret = IRQ_HANDLED;
+
+	spin_lock_irqsave(&fc_pci->irq_lock, flags);
+	v = fc->read_ibi_reg(fc, irq_20c);
+
+	/* errors */
+	if (v.irq_20c.Data_receiver_error)
+		deb_chk("data receiver error\n");
+	if (v.irq_20c.Continuity_error_flag)
+		deb_chk("Contunuity error flag is set\n");
+	if (v.irq_20c.LLC_SNAP_FLAG_set)
+		deb_chk("LLC_SNAP_FLAG_set is set\n");
+	if (v.irq_20c.Transport_Error)
+		deb_chk("Transport error\n");
+
+	if ((fc_pci->count % 1000) == 0)
+		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);
+		else
+			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;
+		/* 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 ",
+				jiffies_to_usecs(jiffies - fc_pci->last_irq),
+				v.raw, (unsigned long long)cur_addr, cur_pos,
+				fc_pci->last_dma1_cur_pos);
+		fc_pci->last_irq = jiffies;
+
+		/* buffer end was reached, restarted from the beginning
+		 * 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);
+			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->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);
+			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);
+		}
+		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);
+		ret = IRQ_NONE;
+	}
+
+	spin_unlock_irqrestore(&fc_pci->irq_lock, flags);
+	return ret;
+}
+
+static int flexcop_pci_stream_control(struct flexcop_device *fc, int onoff)
+{
+	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);
+		deb_irq("DMA xfer enabled\n");
+
+		fc_pci->last_dma1_cur_pos = 0;
+		flexcop_dma_control_timer_irq(fc, FC_DMA_1, 1);
+		deb_irq("IRQ enabled\n");
+		fc_pci->count_prev = fc_pci->count;
+	} else {
+		flexcop_dma_control_timer_irq(fc, FC_DMA_1, 0);
+		deb_irq("IRQ disabled\n");
+
+		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;
+	ret = flexcop_dma_allocate(fc_pci->pdev, &fc_pci->dma[0],
+			FC_DEFAULT_DMA1_BUFSIZE);
+	if (ret != 0)
+		return ret;
+
+	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);
+	fc_pci->init_state |= FC_PCI_DMA_INIT;
+	return ret;
+}
+
+static void flexcop_pci_dma_exit(struct flexcop_pci *fc_pci)
+{
+	if (fc_pci->init_state & FC_PCI_DMA_INIT) {
+		flexcop_dma_free(&fc_pci->dma[0]);
+		flexcop_dma_free(&fc_pci->dma[1]);
+	}
+	fc_pci->init_state &= ~FC_PCI_DMA_INIT;
+}
+
+static int flexcop_pci_init(struct flexcop_pci *fc_pci)
+{
+	int ret;
+
+	info("card revision %x", fc_pci->pdev->revision);
+
+	if ((ret = pci_enable_device(fc_pci->pdev)) != 0)
+		return ret;
+	pci_set_master(fc_pci->pdev);
+
+	if ((ret = pci_request_regions(fc_pci->pdev, DRIVER_NAME)) != 0)
+		goto err_pci_disable_device;
+
+	fc_pci->io_mem = pci_iomap(fc_pci->pdev, 0, 0x800);
+
+	if (!fc_pci->io_mem) {
+		err("cannot map io memory\n");
+		ret = -EIO;
+		goto err_pci_release_regions;
+	}
+
+	pci_set_drvdata(fc_pci->pdev, fc_pci);
+	spin_lock_init(&fc_pci->irq_lock);
+	if ((ret = request_irq(fc_pci->pdev->irq, flexcop_pci_isr,
+					IRQF_SHARED, DRIVER_NAME, fc_pci)) != 0)
+		goto err_pci_iounmap;
+
+	fc_pci->init_state |= FC_PCI_INIT;
+	return ret;
+
+err_pci_iounmap:
+	pci_iounmap(fc_pci->pdev, fc_pci->io_mem);
+	pci_set_drvdata(fc_pci->pdev, NULL);
+err_pci_release_regions:
+	pci_release_regions(fc_pci->pdev);
+err_pci_disable_device:
+	pci_disable_device(fc_pci->pdev);
+	return ret;
+}
+
+static void flexcop_pci_exit(struct flexcop_pci *fc_pci)
+{
+	if (fc_pci->init_state & FC_PCI_INIT) {
+		free_irq(fc_pci->pdev->irq, fc_pci);
+		pci_iounmap(fc_pci->pdev, fc_pci->io_mem);
+		pci_set_drvdata(fc_pci->pdev, NULL);
+		pci_release_regions(fc_pci->pdev);
+		pci_disable_device(fc_pci->pdev);
+	}
+	fc_pci->init_state &= ~FC_PCI_INIT;
+}
+
+static int flexcop_pci_probe(struct pci_dev *pdev,
+		const struct pci_device_id *ent)
+{
+	struct flexcop_device *fc;
+	struct flexcop_pci *fc_pci;
+	int ret = -ENOMEM;
+
+	if ((fc = flexcop_device_kmalloc(sizeof(struct flexcop_pci))) == NULL) {
+		err("out of memory\n");
+		return -ENOMEM;
+	}
+
+	/* general flexcop init */
+	fc_pci = fc->bus_specific;
+	fc_pci->fc_dev = fc;
+
+	fc->read_ibi_reg = flexcop_pci_read_ibi_reg;
+	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)
+		info("will use the HW PID filter.");
+	else
+		info("will pass the complete TS to the demuxer.");
+
+	fc->pid_filtering = enable_pid_filtering;
+	fc->bus_type = FC_PCI;
+	fc->dev = &pdev->dev;
+	fc->owner = THIS_MODULE;
+
+	/* bus specific part */
+	fc_pci->pdev = pdev;
+	if ((ret = flexcop_pci_init(fc_pci)) != 0)
+		goto err_kfree;
+
+	/* init flexcop */
+	if ((ret = flexcop_device_initialize(fc)) != 0)
+		goto err_pci_exit;
+
+	/* 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));
+	return ret;
+
+err_fc_exit:
+	flexcop_device_exit(fc);
+err_pci_exit:
+	flexcop_pci_exit(fc_pci);
+err_kfree:
+	flexcop_device_kfree(fc);
+	return ret;
+}
+
+/* in theory every _exit function should be called exactly two times,
+ * here and in the bail-out-part of the _init-function
+ */
+static void flexcop_pci_remove(struct pci_dev *pdev)
+{
+	struct flexcop_pci *fc_pci = pci_get_drvdata(pdev);
+
+	if (irq_chk_intv > 0)
+		cancel_delayed_work(&fc_pci->irq_check_work);
+
+	flexcop_pci_dma_exit(fc_pci);
+	flexcop_device_exit(fc_pci->fc_dev);
+	flexcop_pci_exit(fc_pci);
+	flexcop_device_kfree(fc_pci->fc_dev);
+}
+
+static struct pci_device_id flexcop_pci_tbl[] = {
+	{ PCI_DEVICE(0x13d0, 0x2103) },
+	{ },
+};
+
+MODULE_DEVICE_TABLE(pci, flexcop_pci_tbl);
+
+static struct pci_driver flexcop_pci_driver = {
+	.name     = "b2c2_flexcop_pci",
+	.id_table = flexcop_pci_tbl,
+	.probe    = flexcop_pci_probe,
+	.remove   = flexcop_pci_remove,
+};
+
+static int __init flexcop_pci_module_init(void)
+{
+	return pci_register_driver(&flexcop_pci_driver);
+}
+
+static void __exit flexcop_pci_module_exit(void)
+{
+	pci_unregister_driver(&flexcop_pci_driver);
+}
+
+module_init(flexcop_pci_module_init);
+module_exit(flexcop_pci_module_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_NAME);
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/pci/bt8xx/Kconfig b/drivers/media/pci/bt8xx/Kconfig
new file mode 100644
index 0000000..61d09e0
--- /dev/null
+++ b/drivers/media/pci/bt8xx/Kconfig
@@ -0,0 +1,43 @@
+config VIDEO_BT848
+	tristate "BT848 Video For Linux"
+	depends on VIDEO_DEV && PCI && I2C && VIDEO_V4L2
+	select I2C_ALGOBIT
+	select VIDEO_BTCX
+	select VIDEOBUF_DMA_SG
+	depends on RC_CORE
+	select VIDEO_TUNER
+	select VIDEO_TVEEPROM
+	select VIDEO_MSP3400 if MEDIA_SUBDRV_AUTOSELECT
+	select VIDEO_TVAUDIO if MEDIA_SUBDRV_AUTOSELECT
+	select VIDEO_TDA7432 if MEDIA_SUBDRV_AUTOSELECT
+	select VIDEO_SAA6588 if MEDIA_SUBDRV_AUTOSELECT
+	---help---
+	  Support for BT848 based frame grabber/overlay boards. This includes
+	  the Miro, Hauppauge and STB boards. Please read the material in
+	  <file:Documentation/video4linux/bttv/> for more information.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called bttv.
+
+config DVB_BT8XX
+	tristate "DVB/ATSC Support for bt878 based TV cards"
+	depends on DVB_CORE && PCI && I2C && VIDEO_BT848
+	select DVB_MT352 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_SP887X if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_NXT6000 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_CX24110 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_OR51211 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_LGDT330X if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_ZL10353 if MEDIA_SUBDRV_AUTOSELECT
+	select MEDIA_TUNER_SIMPLE if MEDIA_SUBDRV_AUTOSELECT
+	help
+	  Support for PCI cards based on the Bt8xx PCI bridge. Examples are
+	  the Nebula cards, the Pinnacle PCTV cards, the Twinhan DST cards,
+	  the pcHDTV HD2000 cards, the DViCO FusionHDTV Lite cards, and
+	  some AVerMedia cards.
+
+	  Since these cards have no MPEG decoder onboard, they transmit
+	  only compressed MPEG data over the PCI bus, so you need
+	  an external software decoder to watch TV on your computer.
+
+	  Say Y if you own such a device and want to use it.
diff --git a/drivers/media/pci/bt8xx/Makefile b/drivers/media/pci/bt8xx/Makefile
new file mode 100644
index 0000000..5f06597
--- /dev/null
+++ b/drivers/media/pci/bt8xx/Makefile
@@ -0,0 +1,11 @@
+bttv-objs      :=      bttv-driver.o bttv-cards.o bttv-if.o \
+		       bttv-risc.o bttv-vbi.o bttv-i2c.o bttv-gpio.o \
+		       bttv-input.o bttv-audio-hook.o
+
+obj-$(CONFIG_VIDEO_BT848) += bttv.o
+obj-$(CONFIG_DVB_BT8XX) += bt878.o dvb-bt8xx.o dst.o dst_ca.o
+
+ccflags-y += -Idrivers/media/dvb-core
+ccflags-y += -Idrivers/media/dvb-frontends
+ccflags-y += -Idrivers/media/i2c
+ccflags-y += -Idrivers/media/tuners
diff --git a/drivers/media/pci/bt8xx/bt848.h b/drivers/media/pci/bt8xx/bt848.h
new file mode 100644
index 0000000..c37e6ac
--- /dev/null
+++ b/drivers/media/pci/bt8xx/bt848.h
@@ -0,0 +1,369 @@
+/*
+    bt848.h - Bt848 register offsets
+
+    Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.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 _BT848_H_
+#define _BT848_H_
+
+#ifndef PCI_VENDOR_ID_BROOKTREE
+#define PCI_VENDOR_ID_BROOKTREE 0x109e
+#endif
+#ifndef PCI_DEVICE_ID_BT848
+#define PCI_DEVICE_ID_BT848     0x350
+#endif
+#ifndef PCI_DEVICE_ID_BT849
+#define PCI_DEVICE_ID_BT849     0x351
+#endif
+#ifndef PCI_DEVICE_ID_FUSION879
+#define PCI_DEVICE_ID_FUSION879	0x36c
+#endif
+
+#ifndef PCI_DEVICE_ID_BT878
+#define PCI_DEVICE_ID_BT878     0x36e
+#endif
+#ifndef PCI_DEVICE_ID_BT879
+#define PCI_DEVICE_ID_BT879     0x36f
+#endif
+
+/* Brooktree 848 registers */
+
+#define BT848_DSTATUS          0x000
+#define BT848_DSTATUS_PRES     (1<<7)
+#define BT848_DSTATUS_HLOC     (1<<6)
+#define BT848_DSTATUS_FIELD    (1<<5)
+#define BT848_DSTATUS_NUML     (1<<4)
+#define BT848_DSTATUS_CSEL     (1<<3)
+#define BT848_DSTATUS_PLOCK    (1<<2)
+#define BT848_DSTATUS_LOF      (1<<1)
+#define BT848_DSTATUS_COF      (1<<0)
+
+#define BT848_IFORM            0x004
+#define BT848_IFORM_HACTIVE    (1<<7)
+#define BT848_IFORM_MUXSEL     (3<<5)
+#define BT848_IFORM_MUX0       (2<<5)
+#define BT848_IFORM_MUX1       (3<<5)
+#define BT848_IFORM_MUX2       (1<<5)
+#define BT848_IFORM_XTSEL      (3<<3)
+#define BT848_IFORM_XT0        (1<<3)
+#define BT848_IFORM_XT1        (2<<3)
+#define BT848_IFORM_XTAUTO     (3<<3)
+#define BT848_IFORM_XTBOTH     (3<<3)
+#define BT848_IFORM_NTSC       1
+#define BT848_IFORM_NTSC_J     2
+#define BT848_IFORM_PAL_BDGHI  3
+#define BT848_IFORM_PAL_M      4
+#define BT848_IFORM_PAL_N      5
+#define BT848_IFORM_SECAM      6
+#define BT848_IFORM_PAL_NC     7
+#define BT848_IFORM_AUTO       0
+#define BT848_IFORM_NORM       7
+
+#define BT848_TDEC             0x008
+#define BT848_TDEC_DEC_FIELD   (1<<7)
+#define BT848_TDEC_FLDALIGN    (1<<6)
+#define BT848_TDEC_DEC_RAT     (0x1f)
+
+#define BT848_E_CROP           0x00C
+#define BT848_O_CROP           0x08C
+
+#define BT848_E_VDELAY_LO      0x010
+#define BT848_O_VDELAY_LO      0x090
+
+#define BT848_E_VACTIVE_LO     0x014
+#define BT848_O_VACTIVE_LO     0x094
+
+#define BT848_E_HDELAY_LO      0x018
+#define BT848_O_HDELAY_LO      0x098
+
+#define BT848_E_HACTIVE_LO     0x01C
+#define BT848_O_HACTIVE_LO     0x09C
+
+#define BT848_E_HSCALE_HI      0x020
+#define BT848_O_HSCALE_HI      0x0A0
+
+#define BT848_E_HSCALE_LO      0x024
+#define BT848_O_HSCALE_LO      0x0A4
+
+#define BT848_BRIGHT           0x028
+
+#define BT848_E_CONTROL        0x02C
+#define BT848_O_CONTROL        0x0AC
+#define BT848_CONTROL_LNOTCH    (1<<7)
+#define BT848_CONTROL_COMP      (1<<6)
+#define BT848_CONTROL_LDEC      (1<<5)
+#define BT848_CONTROL_CBSENSE   (1<<4)
+#define BT848_CONTROL_CON_MSB   (1<<2)
+#define BT848_CONTROL_SAT_U_MSB (1<<1)
+#define BT848_CONTROL_SAT_V_MSB (1<<0)
+
+#define BT848_CONTRAST_LO      0x030
+#define BT848_SAT_U_LO         0x034
+#define BT848_SAT_V_LO         0x038
+#define BT848_HUE              0x03C
+
+#define BT848_E_SCLOOP         0x040
+#define BT848_O_SCLOOP         0x0C0
+#define BT848_SCLOOP_CAGC       (1<<6)
+#define BT848_SCLOOP_CKILL      (1<<5)
+#define BT848_SCLOOP_HFILT_AUTO (0<<3)
+#define BT848_SCLOOP_HFILT_CIF  (1<<3)
+#define BT848_SCLOOP_HFILT_QCIF (2<<3)
+#define BT848_SCLOOP_HFILT_ICON (3<<3)
+
+#define BT848_SCLOOP_PEAK       (1<<7)
+#define BT848_SCLOOP_HFILT_MINP (1<<3)
+#define BT848_SCLOOP_HFILT_MEDP (2<<3)
+#define BT848_SCLOOP_HFILT_MAXP (3<<3)
+
+
+#define BT848_OFORM            0x048
+#define BT848_OFORM_RANGE      (1<<7)
+#define BT848_OFORM_CORE0      (0<<5)
+#define BT848_OFORM_CORE8      (1<<5)
+#define BT848_OFORM_CORE16     (2<<5)
+#define BT848_OFORM_CORE32     (3<<5)
+
+#define BT848_E_VSCALE_HI      0x04C
+#define BT848_O_VSCALE_HI      0x0CC
+#define BT848_VSCALE_YCOMB     (1<<7)
+#define BT848_VSCALE_COMB      (1<<6)
+#define BT848_VSCALE_INT       (1<<5)
+#define BT848_VSCALE_HI        15
+
+#define BT848_E_VSCALE_LO      0x050
+#define BT848_O_VSCALE_LO      0x0D0
+#define BT848_TEST             0x054
+#define BT848_ADELAY           0x060
+#define BT848_BDELAY           0x064
+
+#define BT848_ADC              0x068
+#define BT848_ADC_RESERVED     (2<<6)
+#define BT848_ADC_SYNC_T       (1<<5)
+#define BT848_ADC_AGC_EN       (1<<4)
+#define BT848_ADC_CLK_SLEEP    (1<<3)
+#define BT848_ADC_Y_SLEEP      (1<<2)
+#define BT848_ADC_C_SLEEP      (1<<1)
+#define BT848_ADC_CRUSH        (1<<0)
+
+#define BT848_WC_UP            0x044
+#define BT848_WC_DOWN          0x078
+
+#define BT848_E_VTC            0x06C
+#define BT848_O_VTC            0x0EC
+#define BT848_VTC_HSFMT        (1<<7)
+#define BT848_VTC_VFILT_2TAP   0
+#define BT848_VTC_VFILT_3TAP   1
+#define BT848_VTC_VFILT_4TAP   2
+#define BT848_VTC_VFILT_5TAP   3
+
+#define BT848_SRESET           0x07C
+
+#define BT848_COLOR_FMT             0x0D4
+#define BT848_COLOR_FMT_O_RGB32     (0<<4)
+#define BT848_COLOR_FMT_O_RGB24     (1<<4)
+#define BT848_COLOR_FMT_O_RGB16     (2<<4)
+#define BT848_COLOR_FMT_O_RGB15     (3<<4)
+#define BT848_COLOR_FMT_O_YUY2      (4<<4)
+#define BT848_COLOR_FMT_O_BtYUV     (5<<4)
+#define BT848_COLOR_FMT_O_Y8        (6<<4)
+#define BT848_COLOR_FMT_O_RGB8      (7<<4)
+#define BT848_COLOR_FMT_O_YCrCb422  (8<<4)
+#define BT848_COLOR_FMT_O_YCrCb411  (9<<4)
+#define BT848_COLOR_FMT_O_RAW       (14<<4)
+#define BT848_COLOR_FMT_E_RGB32     0
+#define BT848_COLOR_FMT_E_RGB24     1
+#define BT848_COLOR_FMT_E_RGB16     2
+#define BT848_COLOR_FMT_E_RGB15     3
+#define BT848_COLOR_FMT_E_YUY2      4
+#define BT848_COLOR_FMT_E_BtYUV     5
+#define BT848_COLOR_FMT_E_Y8        6
+#define BT848_COLOR_FMT_E_RGB8      7
+#define BT848_COLOR_FMT_E_YCrCb422  8
+#define BT848_COLOR_FMT_E_YCrCb411  9
+#define BT848_COLOR_FMT_E_RAW       14
+
+#define BT848_COLOR_FMT_RGB32       0x00
+#define BT848_COLOR_FMT_RGB24       0x11
+#define BT848_COLOR_FMT_RGB16       0x22
+#define BT848_COLOR_FMT_RGB15       0x33
+#define BT848_COLOR_FMT_YUY2        0x44
+#define BT848_COLOR_FMT_BtYUV       0x55
+#define BT848_COLOR_FMT_Y8          0x66
+#define BT848_COLOR_FMT_RGB8        0x77
+#define BT848_COLOR_FMT_YCrCb422    0x88
+#define BT848_COLOR_FMT_YCrCb411    0x99
+#define BT848_COLOR_FMT_RAW         0xee
+
+#define BT848_VTOTAL_LO             0xB0
+#define BT848_VTOTAL_HI             0xB4
+
+#define BT848_COLOR_CTL                0x0D8
+#define BT848_COLOR_CTL_EXT_FRMRATE    (1<<7)
+#define BT848_COLOR_CTL_COLOR_BARS     (1<<6)
+#define BT848_COLOR_CTL_RGB_DED        (1<<5)
+#define BT848_COLOR_CTL_GAMMA          (1<<4)
+#define BT848_COLOR_CTL_WSWAP_ODD      (1<<3)
+#define BT848_COLOR_CTL_WSWAP_EVEN     (1<<2)
+#define BT848_COLOR_CTL_BSWAP_ODD      (1<<1)
+#define BT848_COLOR_CTL_BSWAP_EVEN     (1<<0)
+
+#define BT848_CAP_CTL                  0x0DC
+#define BT848_CAP_CTL_DITH_FRAME       (1<<4)
+#define BT848_CAP_CTL_CAPTURE_VBI_ODD  (1<<3)
+#define BT848_CAP_CTL_CAPTURE_VBI_EVEN (1<<2)
+#define BT848_CAP_CTL_CAPTURE_ODD      (1<<1)
+#define BT848_CAP_CTL_CAPTURE_EVEN     (1<<0)
+
+#define BT848_VBI_PACK_SIZE    0x0E0
+
+#define BT848_VBI_PACK_DEL     0x0E4
+#define BT848_VBI_PACK_DEL_VBI_HDELAY 0xfc
+#define BT848_VBI_PACK_DEL_EXT_FRAME  2
+#define BT848_VBI_PACK_DEL_VBI_PKT_HI 1
+
+
+#define BT848_INT_STAT         0x100
+#define BT848_INT_MASK         0x104
+
+#define BT848_INT_ETBF         (1<<23)
+
+#define BT848_INT_RISCS   (0xf<<28)
+#define BT848_INT_RISC_EN (1<<27)
+#define BT848_INT_RACK    (1<<25)
+#define BT848_INT_FIELD   (1<<24)
+#define BT848_INT_SCERR   (1<<19)
+#define BT848_INT_OCERR   (1<<18)
+#define BT848_INT_PABORT  (1<<17)
+#define BT848_INT_RIPERR  (1<<16)
+#define BT848_INT_PPERR   (1<<15)
+#define BT848_INT_FDSR    (1<<14)
+#define BT848_INT_FTRGT   (1<<13)
+#define BT848_INT_FBUS    (1<<12)
+#define BT848_INT_RISCI   (1<<11)
+#define BT848_INT_GPINT   (1<<9)
+#define BT848_INT_I2CDONE (1<<8)
+#define BT848_INT_VPRES   (1<<5)
+#define BT848_INT_HLOCK   (1<<4)
+#define BT848_INT_OFLOW   (1<<3)
+#define BT848_INT_HSYNC   (1<<2)
+#define BT848_INT_VSYNC   (1<<1)
+#define BT848_INT_FMTCHG  (1<<0)
+
+
+#define BT848_GPIO_DMA_CTL             0x10C
+#define BT848_GPIO_DMA_CTL_GPINTC      (1<<15)
+#define BT848_GPIO_DMA_CTL_GPINTI      (1<<14)
+#define BT848_GPIO_DMA_CTL_GPWEC       (1<<13)
+#define BT848_GPIO_DMA_CTL_GPIOMODE    (3<<11)
+#define BT848_GPIO_DMA_CTL_GPCLKMODE   (1<<10)
+#define BT848_GPIO_DMA_CTL_PLTP23_4    (0<<6)
+#define BT848_GPIO_DMA_CTL_PLTP23_8    (1<<6)
+#define BT848_GPIO_DMA_CTL_PLTP23_16   (2<<6)
+#define BT848_GPIO_DMA_CTL_PLTP23_32   (3<<6)
+#define BT848_GPIO_DMA_CTL_PLTP1_4     (0<<4)
+#define BT848_GPIO_DMA_CTL_PLTP1_8     (1<<4)
+#define BT848_GPIO_DMA_CTL_PLTP1_16    (2<<4)
+#define BT848_GPIO_DMA_CTL_PLTP1_32    (3<<4)
+#define BT848_GPIO_DMA_CTL_PKTP_4      (0<<2)
+#define BT848_GPIO_DMA_CTL_PKTP_8      (1<<2)
+#define BT848_GPIO_DMA_CTL_PKTP_16     (2<<2)
+#define BT848_GPIO_DMA_CTL_PKTP_32     (3<<2)
+#define BT848_GPIO_DMA_CTL_RISC_ENABLE (1<<1)
+#define BT848_GPIO_DMA_CTL_FIFO_ENABLE (1<<0)
+
+#define BT848_I2C              0x110
+#define BT878_I2C_MODE         (1<<7)
+#define BT878_I2C_RATE         (1<<6)
+#define BT878_I2C_NOSTOP       (1<<5)
+#define BT878_I2C_NOSTART      (1<<4)
+#define BT848_I2C_DIV          (0xf<<4)
+#define BT848_I2C_SYNC         (1<<3)
+#define BT848_I2C_W3B	       (1<<2)
+#define BT848_I2C_SCL          (1<<1)
+#define BT848_I2C_SDA          (1<<0)
+
+#define BT848_RISC_STRT_ADD    0x114
+#define BT848_GPIO_OUT_EN      0x118
+#define BT848_GPIO_REG_INP     0x11C
+#define BT848_RISC_COUNT       0x120
+#define BT848_GPIO_DATA        0x200
+
+
+/* Bt848 RISC commands */
+
+/* only for the SYNC RISC command */
+#define BT848_FIFO_STATUS_FM1  0x06
+#define BT848_FIFO_STATUS_FM3  0x0e
+#define BT848_FIFO_STATUS_SOL  0x02
+#define BT848_FIFO_STATUS_EOL4 0x01
+#define BT848_FIFO_STATUS_EOL3 0x0d
+#define BT848_FIFO_STATUS_EOL2 0x09
+#define BT848_FIFO_STATUS_EOL1 0x05
+#define BT848_FIFO_STATUS_VRE  0x04
+#define BT848_FIFO_STATUS_VRO  0x0c
+#define BT848_FIFO_STATUS_PXV  0x00
+
+#define BT848_RISC_RESYNC      (1<<15)
+
+/* WRITE and SKIP */
+/* disable which bytes of each DWORD */
+#define BT848_RISC_BYTE0       (1U<<12)
+#define BT848_RISC_BYTE1       (1U<<13)
+#define BT848_RISC_BYTE2       (1U<<14)
+#define BT848_RISC_BYTE3       (1U<<15)
+#define BT848_RISC_BYTE_ALL    (0x0fU<<12)
+#define BT848_RISC_BYTE_NONE   0
+/* cause RISCI */
+#define BT848_RISC_IRQ         (1U<<24)
+/* RISC command is last one in this line */
+#define BT848_RISC_EOL         (1U<<26)
+/* RISC command is first one in this line */
+#define BT848_RISC_SOL         (1U<<27)
+
+#define BT848_RISC_WRITE       (0x01U<<28)
+#define BT848_RISC_SKIP        (0x02U<<28)
+#define BT848_RISC_WRITEC      (0x05U<<28)
+#define BT848_RISC_JUMP        (0x07U<<28)
+#define BT848_RISC_SYNC        (0x08U<<28)
+
+#define BT848_RISC_WRITE123    (0x09U<<28)
+#define BT848_RISC_SKIP123     (0x0aU<<28)
+#define BT848_RISC_WRITE1S23   (0x0bU<<28)
+
+
+/* Bt848A and higher only !! */
+#define BT848_TGLB             0x080
+#define BT848_TGCTRL           0x084
+#define BT848_FCAP             0x0E8
+#define BT848_PLL_F_LO         0x0F0
+#define BT848_PLL_F_HI         0x0F4
+
+#define BT848_PLL_XCI          0x0F8
+#define BT848_PLL_X            (1<<7)
+#define BT848_PLL_C            (1<<6)
+
+#define BT848_DVSIF            0x0FC
+
+/* Bt878 register */
+
+#define BT878_DEVCTRL 0x40
+#define BT878_EN_TBFX 0x02
+#define BT878_EN_VSFX 0x04
+
+#endif
diff --git a/drivers/media/pci/bt8xx/bt878.c b/drivers/media/pci/bt8xx/bt878.c
new file mode 100644
index 0000000..b34fa95
--- /dev/null
+++ b/drivers/media/pci/bt8xx/bt878.c
@@ -0,0 +1,609 @@
+/*
+ * bt878.c: part of the driver for the Pinnacle PCTV Sat DVB PCI card
+ *
+ * Copyright (C) 2002 Peter Hettkamp <peter.hettkamp@htp-tel.de>
+ *
+ * large parts based on the bttv driver
+ * Copyright (C) 1996,97,98 Ralph  Metzler (rjkm@metzlerbros.de)
+ *                        & Marcus Metzler (mocm@metzlerbros.de)
+ * (c) 1999,2000 Gerd Knorr <kraxel@goldbach.in-berlin.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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+#include <linux/ioport.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/kmod.h>
+#include <linux/vmalloc.h>
+#include <linux/init.h>
+
+#include "dmxdev.h"
+#include "dvbdev.h"
+#include "bt878.h"
+#include "dst_priv.h"
+
+
+/**************************************/
+/* Miscellaneous utility  definitions */
+/**************************************/
+
+static unsigned int bt878_verbose = 1;
+static unsigned int bt878_debug;
+
+module_param_named(verbose, bt878_verbose, int, 0444);
+MODULE_PARM_DESC(verbose,
+		 "verbose startup messages, default is 1 (yes)");
+module_param_named(debug, bt878_debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off debugging, default is 0 (off).");
+
+int bt878_num;
+struct bt878 bt878[BT878_MAX];
+
+EXPORT_SYMBOL(bt878_num);
+EXPORT_SYMBOL(bt878);
+
+#define btwrite(dat,adr)    bmtwrite((dat), (bt->bt878_mem+(adr)))
+#define btread(adr)         bmtread(bt->bt878_mem+(adr))
+
+#define btand(dat,adr)      btwrite((dat) & btread(adr), adr)
+#define btor(dat,adr)       btwrite((dat) | btread(adr), adr)
+#define btaor(dat,mask,adr) btwrite((dat) | ((mask) & btread(adr)), adr)
+
+#if defined(dprintk)
+#undef dprintk
+#endif
+#define dprintk(fmt, arg...) \
+	do { \
+		if (bt878_debug) \
+			printk(KERN_DEBUG fmt, ##arg); \
+	} while (0)
+
+static void bt878_mem_free(struct bt878 *bt)
+{
+	if (bt->buf_cpu) {
+		pci_free_consistent(bt->dev, bt->buf_size, bt->buf_cpu,
+				    bt->buf_dma);
+		bt->buf_cpu = NULL;
+	}
+
+	if (bt->risc_cpu) {
+		pci_free_consistent(bt->dev, bt->risc_size, bt->risc_cpu,
+				    bt->risc_dma);
+		bt->risc_cpu = NULL;
+	}
+}
+
+static int bt878_mem_alloc(struct bt878 *bt)
+{
+	if (!bt->buf_cpu) {
+		bt->buf_size = 128 * 1024;
+
+		bt->buf_cpu =
+		    pci_alloc_consistent(bt->dev, bt->buf_size,
+					 &bt->buf_dma);
+
+		if (!bt->buf_cpu)
+			return -ENOMEM;
+
+		memset(bt->buf_cpu, 0, bt->buf_size);
+	}
+
+	if (!bt->risc_cpu) {
+		bt->risc_size = PAGE_SIZE;
+		bt->risc_cpu =
+		    pci_alloc_consistent(bt->dev, bt->risc_size,
+					 &bt->risc_dma);
+
+		if (!bt->risc_cpu) {
+			bt878_mem_free(bt);
+			return -ENOMEM;
+		}
+
+		memset(bt->risc_cpu, 0, bt->risc_size);
+	}
+
+	return 0;
+}
+
+/* RISC instructions */
+#define RISC_WRITE		(0x01 << 28)
+#define RISC_JUMP		(0x07 << 28)
+#define RISC_SYNC		(0x08 << 28)
+
+/* RISC bits */
+#define RISC_WR_SOL		(1 << 27)
+#define RISC_WR_EOL		(1 << 26)
+#define RISC_IRQ		(1 << 24)
+#define RISC_STATUS(status)	((((~status) & 0x0F) << 20) | ((status & 0x0F) << 16))
+#define RISC_SYNC_RESYNC	(1 << 15)
+#define RISC_SYNC_FM1		0x06
+#define RISC_SYNC_VRO		0x0C
+
+#define RISC_FLUSH()		bt->risc_pos = 0
+#define RISC_INSTR(instr)	bt->risc_cpu[bt->risc_pos++] = cpu_to_le32(instr)
+
+static int bt878_make_risc(struct bt878 *bt)
+{
+	bt->block_bytes = bt->buf_size >> 4;
+	bt->block_count = 1 << 4;
+	bt->line_bytes = bt->block_bytes;
+	bt->line_count = bt->block_count;
+
+	while (bt->line_bytes > 4095) {
+		bt->line_bytes >>= 1;
+		bt->line_count <<= 1;
+	}
+
+	if (bt->line_count > 255) {
+		printk(KERN_ERR "bt878: buffer size error!\n");
+		return -EINVAL;
+	}
+	return 0;
+}
+
+
+static void bt878_risc_program(struct bt878 *bt, u32 op_sync_orin)
+{
+	u32 buf_pos = 0;
+	u32 line;
+
+	RISC_FLUSH();
+	RISC_INSTR(RISC_SYNC | RISC_SYNC_FM1 | op_sync_orin);
+	RISC_INSTR(0);
+
+	dprintk("bt878: risc len lines %u, bytes per line %u\n",
+			bt->line_count, bt->line_bytes);
+	for (line = 0; line < bt->line_count; line++) {
+		// At the beginning of every block we issue an IRQ with previous (finished) block number set
+		if (!(buf_pos % bt->block_bytes))
+			RISC_INSTR(RISC_WRITE | RISC_WR_SOL | RISC_WR_EOL |
+				   RISC_IRQ |
+				   RISC_STATUS(((buf_pos /
+						 bt->block_bytes) +
+						(bt->block_count -
+						 1)) %
+					       bt->block_count) | bt->
+				   line_bytes);
+		else
+			RISC_INSTR(RISC_WRITE | RISC_WR_SOL | RISC_WR_EOL |
+				   bt->line_bytes);
+		RISC_INSTR(bt->buf_dma + buf_pos);
+		buf_pos += bt->line_bytes;
+	}
+
+	RISC_INSTR(RISC_SYNC | op_sync_orin | RISC_SYNC_VRO);
+	RISC_INSTR(0);
+
+	RISC_INSTR(RISC_JUMP);
+	RISC_INSTR(bt->risc_dma);
+
+	btwrite((bt->line_count << 16) | bt->line_bytes, BT878_APACK_LEN);
+}
+
+/*****************************/
+/* Start/Stop grabbing funcs */
+/*****************************/
+
+void bt878_start(struct bt878 *bt, u32 controlreg, u32 op_sync_orin,
+		u32 irq_err_ignore)
+{
+	u32 int_mask;
+
+	dprintk("bt878 debug: bt878_start (ctl=%8.8x)\n", controlreg);
+	/* complete the writing of the risc dma program now we have
+	 * the card specifics
+	 */
+	bt878_risc_program(bt, op_sync_orin);
+	controlreg &= ~0x1f;
+	controlreg |= 0x1b;
+
+	btwrite(bt->risc_dma, BT878_ARISC_START);
+
+	/* original int mask had :
+	 *    6    2    8    4    0
+	 * 1111 1111 1000 0000 0000
+	 * SCERR|OCERR|PABORT|RIPERR|FDSR|FTRGT|FBUS|RISCI
+	 * Hacked for DST to:
+	 * SCERR | OCERR | FDSR | FTRGT | FBUS | RISCI
+	 */
+	int_mask = BT878_ASCERR | BT878_AOCERR | BT878_APABORT |
+		BT878_ARIPERR | BT878_APPERR | BT878_AFDSR | BT878_AFTRGT |
+		BT878_AFBUS | BT878_ARISCI;
+
+
+	/* ignore pesky bits */
+	int_mask &= ~irq_err_ignore;
+
+	btwrite(int_mask, BT878_AINT_MASK);
+	btwrite(controlreg, BT878_AGPIO_DMA_CTL);
+}
+
+void bt878_stop(struct bt878 *bt)
+{
+	u32 stat;
+	int i = 0;
+
+	dprintk("bt878 debug: bt878_stop\n");
+
+	btwrite(0, BT878_AINT_MASK);
+	btand(~0x13, BT878_AGPIO_DMA_CTL);
+
+	do {
+		stat = btread(BT878_AINT_STAT);
+		if (!(stat & BT878_ARISC_EN))
+			break;
+		i++;
+	} while (i < 500);
+
+	dprintk("bt878(%d) debug: bt878_stop, i=%d, stat=0x%8.8x\n",
+		bt->nr, i, stat);
+}
+
+EXPORT_SYMBOL(bt878_start);
+EXPORT_SYMBOL(bt878_stop);
+
+/*****************************/
+/* Interrupt service routine */
+/*****************************/
+
+static irqreturn_t bt878_irq(int irq, void *dev_id)
+{
+	u32 stat, astat, mask;
+	int count;
+	struct bt878 *bt;
+
+	bt = (struct bt878 *) dev_id;
+
+	count = 0;
+	while (1) {
+		stat = btread(BT878_AINT_STAT);
+		mask = btread(BT878_AINT_MASK);
+		if (!(astat = (stat & mask)))
+			return IRQ_NONE;	/* this interrupt is not for me */
+/*		dprintk("bt878(%d) debug: irq count %d, stat 0x%8.8x, mask 0x%8.8x\n",bt->nr,count,stat,mask); */
+		btwrite(astat, BT878_AINT_STAT);	/* try to clear interrupt condition */
+
+
+		if (astat & (BT878_ASCERR | BT878_AOCERR)) {
+			if (bt878_verbose) {
+				printk(KERN_INFO
+				       "bt878(%d): irq%s%s risc_pc=%08x\n",
+				       bt->nr,
+				       (astat & BT878_ASCERR) ? " SCERR" :
+				       "",
+				       (astat & BT878_AOCERR) ? " OCERR" :
+				       "", btread(BT878_ARISC_PC));
+			}
+		}
+		if (astat & (BT878_APABORT | BT878_ARIPERR | BT878_APPERR)) {
+			if (bt878_verbose) {
+				printk(KERN_INFO
+				     "bt878(%d): irq%s%s%s risc_pc=%08x\n",
+				     bt->nr,
+				     (astat & BT878_APABORT) ? " PABORT" :
+				     "",
+				     (astat & BT878_ARIPERR) ? " RIPERR" :
+				     "",
+				     (astat & BT878_APPERR) ? " PPERR" :
+				     "", btread(BT878_ARISC_PC));
+			}
+		}
+		if (astat & (BT878_AFDSR | BT878_AFTRGT | BT878_AFBUS)) {
+			if (bt878_verbose) {
+				printk(KERN_INFO
+				     "bt878(%d): irq%s%s%s risc_pc=%08x\n",
+				     bt->nr,
+				     (astat & BT878_AFDSR) ? " FDSR" : "",
+				     (astat & BT878_AFTRGT) ? " FTRGT" :
+				     "",
+				     (astat & BT878_AFBUS) ? " FBUS" : "",
+				     btread(BT878_ARISC_PC));
+			}
+		}
+		if (astat & BT878_ARISCI) {
+			bt->finished_block = (stat & BT878_ARISCS) >> 28;
+			tasklet_schedule(&bt->tasklet);
+			break;
+		}
+		count++;
+		if (count > 20) {
+			btwrite(0, BT878_AINT_MASK);
+			printk(KERN_ERR
+			       "bt878(%d): IRQ lockup, cleared int mask\n",
+			       bt->nr);
+			break;
+		}
+	}
+	return IRQ_HANDLED;
+}
+
+int
+bt878_device_control(struct bt878 *bt, unsigned int cmd, union dst_gpio_packet *mp)
+{
+	int retval;
+
+	retval = 0;
+	if (mutex_lock_interruptible(&bt->gpio_lock))
+		return -ERESTARTSYS;
+	/* special gpio signal */
+	switch (cmd) {
+	    case DST_IG_ENABLE:
+		// dprintk("dvb_bt8xx: dst enable mask 0x%02x enb 0x%02x \n", mp->dstg.enb.mask, mp->dstg.enb.enable);
+		retval = bttv_gpio_enable(bt->bttv_nr,
+				mp->enb.mask,
+				mp->enb.enable);
+		break;
+	    case DST_IG_WRITE:
+		// dprintk("dvb_bt8xx: dst write gpio mask 0x%02x out 0x%02x\n", mp->dstg.outp.mask, mp->dstg.outp.highvals);
+		retval = bttv_write_gpio(bt->bttv_nr,
+				mp->outp.mask,
+				mp->outp.highvals);
+
+		break;
+	    case DST_IG_READ:
+		/* read */
+		retval =  bttv_read_gpio(bt->bttv_nr, &mp->rd.value);
+		// dprintk("dvb_bt8xx: dst read gpio 0x%02x\n", (unsigned)mp->dstg.rd.value);
+		break;
+	    case DST_IG_TS:
+		/* Set packet size */
+		bt->TS_Size = mp->psize;
+		break;
+
+	    default:
+		retval = -EINVAL;
+		break;
+	}
+	mutex_unlock(&bt->gpio_lock);
+	return retval;
+}
+
+EXPORT_SYMBOL(bt878_device_control);
+
+#define BROOKTREE_878_DEVICE(vend, dev, name) \
+	{ \
+		.vendor = PCI_VENDOR_ID_BROOKTREE, \
+		.device = PCI_DEVICE_ID_BROOKTREE_878, \
+		.subvendor = (vend), .subdevice = (dev), \
+		.driver_data = (unsigned long) name \
+	}
+
+static struct pci_device_id bt878_pci_tbl[] __devinitdata = {
+	BROOKTREE_878_DEVICE(0x0071, 0x0101, "Nebula Electronics DigiTV"),
+	BROOKTREE_878_DEVICE(0x1461, 0x0761, "AverMedia AverTV DVB-T 761"),
+	BROOKTREE_878_DEVICE(0x11bd, 0x001c, "Pinnacle PCTV Sat"),
+	BROOKTREE_878_DEVICE(0x11bd, 0x0026, "Pinnacle PCTV SAT CI"),
+	BROOKTREE_878_DEVICE(0x1822, 0x0001, "Twinhan VisionPlus DVB"),
+	BROOKTREE_878_DEVICE(0x270f, 0xfc00,
+				"ChainTech digitop DST-1000 DVB-S"),
+	BROOKTREE_878_DEVICE(0x1461, 0x0771, "AVermedia AverTV DVB-T 771"),
+	BROOKTREE_878_DEVICE(0x18ac, 0xdb10, "DViCO FusionHDTV DVB-T Lite"),
+	BROOKTREE_878_DEVICE(0x18ac, 0xdb11, "Ultraview DVB-T Lite"),
+	BROOKTREE_878_DEVICE(0x18ac, 0xd500, "DViCO FusionHDTV 5 Lite"),
+	BROOKTREE_878_DEVICE(0x7063, 0x2000, "pcHDTV HD-2000 TV"),
+	BROOKTREE_878_DEVICE(0x1822, 0x0026, "DNTV Live! Mini"),
+	{ }
+};
+
+MODULE_DEVICE_TABLE(pci, bt878_pci_tbl);
+
+static const char * __devinit card_name(const struct pci_device_id *id)
+{
+	return id->driver_data ? (const char *)id->driver_data : "Unknown";
+}
+
+/***********************/
+/* PCI device handling */
+/***********************/
+
+static int __devinit bt878_probe(struct pci_dev *dev,
+				 const struct pci_device_id *pci_id)
+{
+	int result = 0;
+	unsigned char lat;
+	struct bt878 *bt;
+#if defined(__powerpc__)
+	unsigned int cmd;
+#endif
+	unsigned int cardid;
+
+	printk(KERN_INFO "bt878: Bt878 AUDIO function found (%d).\n",
+	       bt878_num);
+	if (bt878_num >= BT878_MAX) {
+		printk(KERN_ERR "bt878: Too many devices inserted\n");
+		result = -ENOMEM;
+		goto fail0;
+	}
+	if (pci_enable_device(dev))
+		return -EIO;
+
+	cardid = dev->subsystem_device << 16;
+	cardid |= dev->subsystem_vendor;
+
+	printk(KERN_INFO "%s: card id=[0x%x],[ %s ] has DVB functions.\n",
+				__func__, cardid, card_name(pci_id));
+
+	bt = &bt878[bt878_num];
+	bt->dev = dev;
+	bt->nr = bt878_num;
+	bt->shutdown = 0;
+
+	bt->id = dev->device;
+	bt->irq = dev->irq;
+	bt->bt878_adr = pci_resource_start(dev, 0);
+	if (!request_mem_region(pci_resource_start(dev, 0),
+				pci_resource_len(dev, 0), "bt878")) {
+		result = -EBUSY;
+		goto fail0;
+	}
+
+	bt->revision = dev->revision;
+	pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
+
+
+	printk(KERN_INFO "bt878(%d): Bt%x (rev %d) at %02x:%02x.%x, ",
+	       bt878_num, bt->id, bt->revision, dev->bus->number,
+	       PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
+	printk("irq: %d, latency: %d, memory: 0x%lx\n",
+	       bt->irq, lat, bt->bt878_adr);
+
+
+#if defined(__powerpc__)
+	/* on OpenFirmware machines (PowerMac at least), PCI memory cycle */
+	/* response on cards with no firmware is not enabled by OF */
+	pci_read_config_dword(dev, PCI_COMMAND, &cmd);
+	cmd = (cmd | PCI_COMMAND_MEMORY);
+	pci_write_config_dword(dev, PCI_COMMAND, cmd);
+#endif
+
+#ifdef __sparc__
+	bt->bt878_mem = (unsigned char *) bt->bt878_adr;
+#else
+	bt->bt878_mem = ioremap(bt->bt878_adr, 0x1000);
+#endif
+
+	/* clear interrupt mask */
+	btwrite(0, BT848_INT_MASK);
+
+	result = request_irq(bt->irq, bt878_irq,
+			     IRQF_SHARED | IRQF_DISABLED, "bt878",
+			     (void *) bt);
+	if (result == -EINVAL) {
+		printk(KERN_ERR "bt878(%d): Bad irq number or handler\n",
+		       bt878_num);
+		goto fail1;
+	}
+	if (result == -EBUSY) {
+		printk(KERN_ERR
+		       "bt878(%d): IRQ %d busy, change your PnP config in BIOS\n",
+		       bt878_num, bt->irq);
+		goto fail1;
+	}
+	if (result < 0)
+		goto fail1;
+
+	pci_set_master(dev);
+	pci_set_drvdata(dev, bt);
+
+	if ((result = bt878_mem_alloc(bt))) {
+		printk(KERN_ERR "bt878: failed to allocate memory!\n");
+		goto fail2;
+	}
+
+	bt878_make_risc(bt);
+	btwrite(0, BT878_AINT_MASK);
+	bt878_num++;
+
+	return 0;
+
+      fail2:
+	free_irq(bt->irq, bt);
+      fail1:
+	release_mem_region(pci_resource_start(bt->dev, 0),
+			   pci_resource_len(bt->dev, 0));
+      fail0:
+	pci_disable_device(dev);
+	return result;
+}
+
+static void __devexit bt878_remove(struct pci_dev *pci_dev)
+{
+	u8 command;
+	struct bt878 *bt = pci_get_drvdata(pci_dev);
+
+	if (bt878_verbose)
+		printk(KERN_INFO "bt878(%d): unloading\n", bt->nr);
+
+	/* turn off all capturing, DMA and IRQs */
+	btand(~0x13, BT878_AGPIO_DMA_CTL);
+
+	/* first disable interrupts before unmapping the memory! */
+	btwrite(0, BT878_AINT_MASK);
+	btwrite(~0U, BT878_AINT_STAT);
+
+	/* disable PCI bus-mastering */
+	pci_read_config_byte(bt->dev, PCI_COMMAND, &command);
+	/* Should this be &=~ ?? */
+	command &= ~PCI_COMMAND_MASTER;
+	pci_write_config_byte(bt->dev, PCI_COMMAND, command);
+
+	free_irq(bt->irq, bt);
+	printk(KERN_DEBUG "bt878_mem: 0x%p.\n", bt->bt878_mem);
+	if (bt->bt878_mem)
+		iounmap(bt->bt878_mem);
+
+	release_mem_region(pci_resource_start(bt->dev, 0),
+			   pci_resource_len(bt->dev, 0));
+	/* wake up any waiting processes
+	   because shutdown flag is set, no new processes (in this queue)
+	   are expected
+	 */
+	bt->shutdown = 1;
+	bt878_mem_free(bt);
+
+	pci_set_drvdata(pci_dev, NULL);
+	pci_disable_device(pci_dev);
+	return;
+}
+
+static struct pci_driver bt878_pci_driver = {
+      .name	= "bt878",
+      .id_table = bt878_pci_tbl,
+      .probe	= bt878_probe,
+      .remove	= __devexit_p(bt878_remove),
+};
+
+/*******************************/
+/* Module management functions */
+/*******************************/
+
+static int __init bt878_init_module(void)
+{
+	bt878_num = 0;
+
+	printk(KERN_INFO "bt878: AUDIO driver version %d.%d.%d loaded\n",
+	       (BT878_VERSION_CODE >> 16) & 0xff,
+	       (BT878_VERSION_CODE >> 8) & 0xff,
+	       BT878_VERSION_CODE & 0xff);
+
+	return pci_register_driver(&bt878_pci_driver);
+}
+
+static void __exit bt878_cleanup_module(void)
+{
+	pci_unregister_driver(&bt878_pci_driver);
+}
+
+module_init(bt878_init_module);
+module_exit(bt878_cleanup_module);
+
+MODULE_LICENSE("GPL");
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/pci/bt8xx/bt878.h b/drivers/media/pci/bt8xx/bt878.h
new file mode 100644
index 0000000..d19b592
--- /dev/null
+++ b/drivers/media/pci/bt8xx/bt878.h
@@ -0,0 +1,159 @@
+/*
+    bt878.h - Bt878 audio module (register offsets)
+
+    Copyright (C) 2002 Peter Hettkamp <peter.hettkamp@htp-tel.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 _BT878_H_
+#define _BT878_H_
+
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/mutex.h>
+
+#include "bt848.h"
+#include "bttv.h"
+
+#define BT878_VERSION_CODE 0x000000
+
+#define BT878_AINT_STAT		0x100
+#define BT878_ARISCS		(0xf<<28)
+#define BT878_ARISC_EN		(1<<27)
+#define BT878_ASCERR		(1<<19)
+#define BT878_AOCERR		(1<<18)
+#define BT878_APABORT		(1<<17)
+#define BT878_ARIPERR		(1<<16)
+#define BT878_APPERR		(1<<15)
+#define BT878_AFDSR		(1<<14)
+#define BT878_AFTRGT		(1<<13)
+#define BT878_AFBUS		(1<<12)
+#define BT878_ARISCI		(1<<11)
+#define BT878_AOFLOW		(1<<3)
+
+#define BT878_AINT_MASK		0x104
+
+#define BT878_AGPIO_DMA_CTL	0x10c
+#define BT878_A_GAIN		(0xf<<28)
+#define BT878_A_G2X		(1<<27)
+#define BT878_A_PWRDN		(1<<26)
+#define BT878_A_SEL		(3<<24)
+#define BT878_DA_SCE		(1<<23)
+#define BT878_DA_LRI		(1<<22)
+#define BT878_DA_MLB		(1<<21)
+#define BT878_DA_LRD		(0x1f<<16)
+#define BT878_DA_DPM		(1<<15)
+#define BT878_DA_SBR		(1<<14)
+#define BT878_DA_ES2		(1<<13)
+#define BT878_DA_LMT		(1<<12)
+#define BT878_DA_SDR		(0xf<<8)
+#define BT878_DA_IOM		(3<<6)
+#define BT878_DA_APP		(1<<5)
+#define BT878_ACAP_EN		(1<<4)
+#define BT878_PKTP		(3<<2)
+#define BT878_RISC_EN		(1<<1)
+#define BT878_FIFO_EN		1
+
+#define BT878_APACK_LEN		0x110
+#define BT878_AFP_LEN		(0xff<<16)
+#define BT878_ALP_LEN		0xfff
+
+#define BT878_ARISC_START	0x114
+
+#define BT878_ARISC_PC		0x120
+
+/* BT878 FUNCTION 0 REGISTERS */
+#define BT878_GPIO_DMA_CTL	0x10c
+
+/* Interrupt register */
+#define BT878_INT_STAT		0x100
+#define BT878_INT_MASK		0x104
+#define BT878_I2CRACK		(1<<25)
+#define BT878_I2CDONE		(1<<8)
+
+#define BT878_MAX 4
+
+#define BT878_RISC_SYNC_MASK	(1 << 15)
+
+
+#define BTTV_BOARD_UNKNOWN                 0x00
+#define BTTV_BOARD_PINNACLESAT             0x5e
+#define BTTV_BOARD_NEBULA_DIGITV           0x68
+#define BTTV_BOARD_PC_HDTV                 0x70
+#define BTTV_BOARD_TWINHAN_DST             0x71
+#define BTTV_BOARD_AVDVBT_771              0x7b
+#define BTTV_BOARD_AVDVBT_761              0x7c
+#define BTTV_BOARD_DVICO_DVBT_LITE         0x80
+#define BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE 0x87
+
+extern int bt878_num;
+
+struct bt878 {
+	struct mutex gpio_lock;
+	unsigned int nr;
+	unsigned int bttv_nr;
+	struct i2c_adapter *adapter;
+	struct pci_dev *dev;
+	unsigned int id;
+	unsigned int TS_Size;
+	unsigned char revision;
+	unsigned int irq;
+	unsigned long bt878_adr;
+	volatile void __iomem *bt878_mem; /* function 1 */
+
+	volatile u32 finished_block;
+	volatile u32 last_block;
+	u32 block_count;
+	u32 block_bytes;
+	u32 line_bytes;
+	u32 line_count;
+
+	u32 buf_size;
+	u8 *buf_cpu;
+	dma_addr_t buf_dma;
+
+	u32 risc_size;
+	__le32 *risc_cpu;
+	dma_addr_t risc_dma;
+	u32 risc_pos;
+
+	struct tasklet_struct tasklet;
+	int shutdown;
+};
+
+extern struct bt878 bt878[BT878_MAX];
+
+void bt878_start(struct bt878 *bt, u32 controlreg, u32 op_sync_orin,
+		u32 irq_err_ignore);
+void bt878_stop(struct bt878 *bt);
+
+#if defined(__powerpc__)	/* big-endian */
+static inline void io_st_le32(volatile unsigned __iomem *addr, unsigned val)
+{
+	st_le32(addr, val);
+	eieio();
+}
+
+#define bmtwrite(dat,adr)  io_st_le32((adr),(dat))
+#define bmtread(adr)       ld_le32((adr))
+#else
+#define bmtwrite(dat,adr)  writel((dat), (adr))
+#define bmtread(adr)       readl(adr)
+#endif
+
+#endif
diff --git a/drivers/media/pci/bt8xx/bttv-audio-hook.c b/drivers/media/pci/bt8xx/bttv-audio-hook.c
new file mode 100644
index 0000000..2364d16
--- /dev/null
+++ b/drivers/media/pci/bt8xx/bttv-audio-hook.c
@@ -0,0 +1,382 @@
+/*
+ * Handlers for board audio hooks, splitted from bttv-cards
+ *
+ * Copyright (c) 2006 Mauro Carvalho Chehab (mchehab@infradead.org)
+ * This code is placed under the terms of the GNU General Public License
+ */
+
+#include "bttv-audio-hook.h"
+
+#include <linux/delay.h>
+
+/* ----------------------------------------------------------------------- */
+/* winview                                                                 */
+
+void winview_volume(struct bttv *btv, __u16 volume)
+{
+	/* PT2254A programming Jon Tombs, jon@gte.esi.us.es */
+	int bits_out, loops, vol, data;
+
+	/* 32 levels logarithmic */
+	vol = 32 - ((volume>>11));
+	/* units */
+	bits_out = (PT2254_DBS_IN_2>>(vol%5));
+	/* tens */
+	bits_out |= (PT2254_DBS_IN_10>>(vol/5));
+	bits_out |= PT2254_L_CHANNEL | PT2254_R_CHANNEL;
+	data = gpio_read();
+	data &= ~(WINVIEW_PT2254_CLK| WINVIEW_PT2254_DATA|
+		  WINVIEW_PT2254_STROBE);
+	for (loops = 17; loops >= 0 ; loops--) {
+		if (bits_out & (1<<loops))
+			data |=  WINVIEW_PT2254_DATA;
+		else
+			data &= ~WINVIEW_PT2254_DATA;
+		gpio_write(data);
+		udelay(5);
+		data |= WINVIEW_PT2254_CLK;
+		gpio_write(data);
+		udelay(5);
+		data &= ~WINVIEW_PT2254_CLK;
+		gpio_write(data);
+	}
+	data |=  WINVIEW_PT2254_STROBE;
+	data &= ~WINVIEW_PT2254_DATA;
+	gpio_write(data);
+	udelay(10);
+	data &= ~WINVIEW_PT2254_STROBE;
+	gpio_write(data);
+}
+
+/* ----------------------------------------------------------------------- */
+/* mono/stereo control for various cards (which don't use i2c chips but    */
+/* connect something to the GPIO pins                                      */
+
+void gvbctv3pci_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
+{
+	unsigned int con = 0;
+
+	if (set) {
+		gpio_inout(0x300, 0x300);
+		if (t->audmode & V4L2_TUNER_MODE_LANG1)
+			con = 0x000;
+		if (t->audmode & V4L2_TUNER_MODE_LANG2)
+			con = 0x300;
+		if (t->audmode & V4L2_TUNER_MODE_STEREO)
+			con = 0x200;
+/*		if (t->audmode & V4L2_TUNER_MODE_MONO)
+ *			con = 0x100; */
+		gpio_bits(0x300, con);
+	} else {
+		t->audmode = V4L2_TUNER_MODE_STEREO |
+			  V4L2_TUNER_MODE_LANG1  | V4L2_TUNER_MODE_LANG2;
+	}
+}
+
+void gvbctv5pci_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
+{
+	unsigned int val, con;
+
+	if (btv->radio_user)
+		return;
+
+	val = gpio_read();
+	if (set) {
+		con = 0x000;
+		if (t->audmode & V4L2_TUNER_MODE_LANG2) {
+			if (t->audmode & V4L2_TUNER_MODE_LANG1) {
+				/* LANG1 + LANG2 */
+				con = 0x100;
+			}
+			else {
+				/* LANG2 */
+				con = 0x300;
+			}
+		}
+		if (con != (val & 0x300)) {
+			gpio_bits(0x300, con);
+			if (bttv_gpio)
+				bttv_gpio_tracking(btv,"gvbctv5pci");
+		}
+	} else {
+		switch (val & 0x70) {
+		  case 0x10:
+			t->rxsubchans = V4L2_TUNER_SUB_LANG1 |  V4L2_TUNER_SUB_LANG2;
+			break;
+		  case 0x30:
+			t->rxsubchans = V4L2_TUNER_SUB_LANG2;
+			break;
+		  case 0x50:
+			t->rxsubchans = V4L2_TUNER_SUB_LANG1;
+			break;
+		  case 0x60:
+			t->rxsubchans = V4L2_TUNER_SUB_STEREO;
+			break;
+		  case 0x70:
+			t->rxsubchans = V4L2_TUNER_SUB_MONO;
+			break;
+		  default:
+			t->rxsubchans = V4L2_TUNER_SUB_MONO |
+					 V4L2_TUNER_SUB_STEREO |
+					 V4L2_TUNER_SUB_LANG1 |
+					 V4L2_TUNER_SUB_LANG2;
+		}
+		t->audmode = V4L2_TUNER_MODE_STEREO |
+			  V4L2_TUNER_MODE_LANG1  | V4L2_TUNER_MODE_LANG2;
+	}
+}
+
+/*
+ * Mario Medina Nussbaum <medisoft@alohabbs.org.mx>
+ *  I discover that on BT848_GPIO_DATA address a byte 0xcce enable stereo,
+ *  0xdde enables mono and 0xccd enables sap
+ *
+ * Petr Vandrovec <VANDROVE@vc.cvut.cz>
+ *  P.S.: At least mask in line above is wrong - GPIO pins 3,2 select
+ *  input/output sound connection, so both must be set for output mode.
+ *
+ * Looks like it's needed only for the "tvphone", the "tvphone 98"
+ * handles this with a tda9840
+ *
+ */
+
+void avermedia_tvphone_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
+{
+	int val = 0;
+
+	if (set) {
+		if (t->audmode & V4L2_TUNER_MODE_LANG2)   /* SAP */
+			val = 0x02;
+		if (t->audmode & V4L2_TUNER_MODE_STEREO)
+			val = 0x01;
+		if (val) {
+			gpio_bits(0x03,val);
+			if (bttv_gpio)
+				bttv_gpio_tracking(btv,"avermedia");
+		}
+	} else {
+		t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
+			V4L2_TUNER_MODE_LANG1;
+		return;
+	}
+}
+
+
+void avermedia_tv_stereo_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
+{
+	int val = 0;
+
+	if (set) {
+		if (t->audmode & V4L2_TUNER_MODE_LANG2)   /* SAP */
+			val = 0x01;
+		if (t->audmode & V4L2_TUNER_MODE_STEREO)  /* STEREO */
+			val = 0x02;
+		btaor(val, ~0x03, BT848_GPIO_DATA);
+		if (bttv_gpio)
+			bttv_gpio_tracking(btv,"avermedia");
+	} else {
+		t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
+			V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
+		return;
+	}
+}
+
+/* Lifetec 9415 handling */
+
+void lt9415_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
+{
+	int val = 0;
+
+	if (gpio_read() & 0x4000) {
+		t->audmode = V4L2_TUNER_MODE_MONO;
+		return;
+	}
+
+	if (set) {
+		if (t->audmode & V4L2_TUNER_MODE_LANG2)  /* A2 SAP */
+			val = 0x0080;
+		if (t->audmode & V4L2_TUNER_MODE_STEREO) /* A2 stereo */
+			val = 0x0880;
+		if ((t->audmode & V4L2_TUNER_MODE_LANG1) ||
+		    (t->audmode & V4L2_TUNER_MODE_MONO))
+			val = 0;
+		gpio_bits(0x0880, val);
+		if (bttv_gpio)
+			bttv_gpio_tracking(btv,"lt9415");
+	} else {
+		/* autodetect doesn't work with this card :-( */
+		t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
+			V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
+		return;
+	}
+}
+
+/* TDA9821 on TerraTV+ Bt848, Bt878 */
+void terratv_audio(struct bttv *btv,  struct v4l2_tuner *t, int set)
+{
+	unsigned int con = 0;
+
+	if (set) {
+		gpio_inout(0x180000,0x180000);
+		if (t->audmode & V4L2_TUNER_MODE_LANG2)
+			con = 0x080000;
+		if (t->audmode & V4L2_TUNER_MODE_STEREO)
+			con = 0x180000;
+		gpio_bits(0x180000, con);
+		if (bttv_gpio)
+			bttv_gpio_tracking(btv,"terratv");
+	} else {
+		t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
+			V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
+	}
+}
+
+
+void winfast2000_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
+{
+	unsigned long val = 0;
+
+	if (set) {
+		/*btor (0xc32000, BT848_GPIO_OUT_EN);*/
+		if (t->audmode & V4L2_TUNER_MODE_MONO)		/* Mono */
+			val = 0x420000;
+		if (t->audmode & V4L2_TUNER_MODE_LANG1)	/* Mono */
+			val = 0x420000;
+		if (t->audmode & V4L2_TUNER_MODE_LANG2)	/* SAP */
+			val = 0x410000;
+		if (t->audmode & V4L2_TUNER_MODE_STEREO)	/* Stereo */
+			val = 0x020000;
+		if (val) {
+			gpio_bits(0x430000, val);
+			if (bttv_gpio)
+				bttv_gpio_tracking(btv,"winfast2000");
+		}
+	} else {
+		t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
+			  V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
+	}
+}
+
+/*
+ * Dariusz Kowalewski <darekk@automex.pl>
+ * sound control for Prolink PV-BT878P+9B (PixelView PlayTV Pro FM+NICAM
+ * revision 9B has on-board TDA9874A sound decoder).
+ *
+ * Note: There are card variants without tda9874a. Forcing the "stereo sound route"
+ *       will mute this cards.
+ */
+void pvbt878p9b_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
+{
+	unsigned int val = 0;
+
+	if (btv->radio_user)
+		return;
+
+	if (set) {
+		if (t->audmode & V4L2_TUNER_MODE_MONO)	{
+			val = 0x01;
+		}
+		if ((t->audmode & (V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2))
+		    || (t->audmode & V4L2_TUNER_MODE_STEREO)) {
+			val = 0x02;
+		}
+		if (val) {
+			gpio_bits(0x03,val);
+			if (bttv_gpio)
+				bttv_gpio_tracking(btv,"pvbt878p9b");
+		}
+	} else {
+		t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
+			V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
+	}
+}
+
+/*
+ * Dariusz Kowalewski <darekk@automex.pl>
+ * sound control for FlyVideo 2000S (with tda9874 decoder)
+ * based on pvbt878p9b_audio() - this is not tested, please fix!!!
+ */
+void fv2000s_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
+{
+	unsigned int val = 0xffff;
+
+	if (btv->radio_user)
+		return;
+
+	if (set) {
+		if (t->audmode & V4L2_TUNER_MODE_MONO)	{
+			val = 0x0000;
+		}
+		if ((t->audmode & (V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2))
+		    || (t->audmode & V4L2_TUNER_MODE_STEREO)) {
+			val = 0x1080; /*-dk-???: 0x0880, 0x0080, 0x1800 ... */
+		}
+		if (val != 0xffff) {
+			gpio_bits(0x1800, val);
+			if (bttv_gpio)
+				bttv_gpio_tracking(btv,"fv2000s");
+		}
+	} else {
+		t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
+			V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
+	}
+}
+
+/*
+ * sound control for Canopus WinDVR PCI
+ * Masaki Suzuki <masaki@btree.org>
+ */
+void windvr_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
+{
+	unsigned long val = 0;
+
+	if (set) {
+		if (t->audmode & V4L2_TUNER_MODE_MONO)
+			val = 0x040000;
+		if (t->audmode & V4L2_TUNER_MODE_LANG1)
+			val = 0;
+		if (t->audmode & V4L2_TUNER_MODE_LANG2)
+			val = 0x100000;
+		if (t->audmode & V4L2_TUNER_MODE_STEREO)
+			val = 0;
+		if (val) {
+			gpio_bits(0x140000, val);
+			if (bttv_gpio)
+				bttv_gpio_tracking(btv,"windvr");
+		}
+	} else {
+		t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
+			  V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
+	}
+}
+
+/*
+ * sound control for AD-TVK503
+ * Hiroshi Takekawa <sian@big.or.jp>
+ */
+void adtvk503_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
+{
+	unsigned int con = 0xffffff;
+
+	/* btaor(0x1e0000, ~0x1e0000, BT848_GPIO_OUT_EN); */
+
+	if (set) {
+		/* btor(***, BT848_GPIO_OUT_EN); */
+		if (t->audmode & V4L2_TUNER_MODE_LANG1)
+			con = 0x00000000;
+		if (t->audmode & V4L2_TUNER_MODE_LANG2)
+			con = 0x00180000;
+		if (t->audmode & V4L2_TUNER_MODE_STEREO)
+			con = 0x00000000;
+		if (t->audmode & V4L2_TUNER_MODE_MONO)
+			con = 0x00060000;
+		if (con != 0xffffff) {
+			gpio_bits(0x1e0000,con);
+			if (bttv_gpio)
+				bttv_gpio_tracking(btv, "adtvk503");
+		}
+	} else {
+		t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
+			  V4L2_TUNER_MODE_LANG1  | V4L2_TUNER_MODE_LANG2;
+	}
+}
diff --git a/drivers/media/pci/bt8xx/bttv-audio-hook.h b/drivers/media/pci/bt8xx/bttv-audio-hook.h
new file mode 100644
index 0000000..159d07a
--- /dev/null
+++ b/drivers/media/pci/bt8xx/bttv-audio-hook.h
@@ -0,0 +1,23 @@
+/*
+ * Handlers for board audio hooks, splitted from bttv-cards
+ *
+ * Copyright (c) 2006 Mauro Carvalho Chehab (mchehab@infradead.org)
+ * This code is placed under the terms of the GNU General Public License
+ */
+
+#include "bttvp.h"
+
+void winview_volume (struct bttv *btv, __u16 volume);
+
+void lt9415_audio(struct bttv *btv, struct v4l2_tuner *tuner, int set);
+void avermedia_tvphone_audio(struct bttv *btv, struct v4l2_tuner *tuner, int set);
+void avermedia_tv_stereo_audio(struct bttv *btv, struct v4l2_tuner *tuner, int set);
+void terratv_audio(struct bttv *btv,  struct v4l2_tuner *tuner, int set);
+void gvbctv3pci_audio(struct bttv *btv, struct v4l2_tuner *tuner, int set);
+void gvbctv5pci_audio(struct bttv *btv, struct v4l2_tuner *tuner, int set);
+void winfast2000_audio(struct bttv *btv, struct v4l2_tuner *tuner, int set);
+void pvbt878p9b_audio(struct bttv *btv, struct v4l2_tuner *tuner, int set);
+void fv2000s_audio(struct bttv *btv, struct v4l2_tuner *tuner, int set);
+void windvr_audio(struct bttv *btv, struct v4l2_tuner *tuner, int set);
+void adtvk503_audio(struct bttv *btv, struct v4l2_tuner *tuner, int set);
+
diff --git a/drivers/media/pci/bt8xx/bttv-cards.c b/drivers/media/pci/bt8xx/bttv-cards.c
new file mode 100644
index 0000000..38952fa
--- /dev/null
+++ b/drivers/media/pci/bt8xx/bttv-cards.c
@@ -0,0 +1,4895 @@
+/*
+
+    bttv-cards.c
+
+    this file has configuration informations - card-specific stuff
+    like the big tvcards array for the most part
+
+    Copyright (C) 1996,97,98 Ralph  Metzler (rjkm@thp.uni-koeln.de)
+			   & Marcus Metzler (mocm@thp.uni-koeln.de)
+    (c) 1999-2001 Gerd Knorr <kraxel@goldbach.in-berlin.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.
+
+*/
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/kmod.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/vmalloc.h>
+#include <linux/firmware.h>
+#include <net/checksum.h>
+
+#include <asm/unaligned.h>
+#include <asm/io.h>
+
+#include "bttvp.h"
+#include <media/v4l2-common.h>
+#include <media/tvaudio.h>
+#include "bttv-audio-hook.h"
+
+/* fwd decl */
+static void boot_msp34xx(struct bttv *btv, int pin);
+static void hauppauge_eeprom(struct bttv *btv);
+static void avermedia_eeprom(struct bttv *btv);
+static void osprey_eeprom(struct bttv *btv, const u8 ee[256]);
+static void modtec_eeprom(struct bttv *btv);
+static void init_PXC200(struct bttv *btv);
+static void init_RTV24(struct bttv *btv);
+
+static void rv605_muxsel(struct bttv *btv, unsigned int input);
+static void eagle_muxsel(struct bttv *btv, unsigned int input);
+static void xguard_muxsel(struct bttv *btv, unsigned int input);
+static void ivc120_muxsel(struct bttv *btv, unsigned int input);
+static void gvc1100_muxsel(struct bttv *btv, unsigned int input);
+
+static void PXC200_muxsel(struct bttv *btv, unsigned int input);
+
+static void picolo_tetra_muxsel(struct bttv *btv, unsigned int input);
+static void picolo_tetra_init(struct bttv *btv);
+
+static void tibetCS16_muxsel(struct bttv *btv, unsigned int input);
+static void tibetCS16_init(struct bttv *btv);
+
+static void kodicom4400r_muxsel(struct bttv *btv, unsigned int input);
+static void kodicom4400r_init(struct bttv *btv);
+
+static void sigmaSLC_muxsel(struct bttv *btv, unsigned int input);
+static void sigmaSQ_muxsel(struct bttv *btv, unsigned int input);
+
+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 void td3116_muxsel(struct bttv *btv, unsigned int input);
+
+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);
+static void identify_by_eeprom(struct bttv *btv,
+			       unsigned char eeprom_data[256]);
+static int __devinit pvr_boot(struct bttv *btv);
+
+/* config variables */
+static unsigned int triton1;
+static unsigned int vsfx;
+static unsigned int latency = UNSET;
+int no_overlay=-1;
+
+static unsigned int card[BTTV_MAX]   = { [ 0 ... (BTTV_MAX-1) ] = UNSET };
+static unsigned int pll[BTTV_MAX]    = { [ 0 ... (BTTV_MAX-1) ] = UNSET };
+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 };
+static unsigned int autoload = UNSET;
+static unsigned int gpiomask = UNSET;
+static unsigned int audioall = UNSET;
+static unsigned int audiomux[5] = { [ 0 ... 4 ] = UNSET };
+
+/* insmod options */
+module_param(triton1,    int, 0444);
+module_param(vsfx,       int, 0444);
+module_param(no_overlay, int, 0444);
+module_param(latency,    int, 0444);
+module_param(gpiomask,   int, 0444);
+module_param(audioall,   int, 0444);
+module_param(autoload,   int, 0444);
+
+module_param_array(card,     int, NULL, 0444);
+module_param_array(pll,      int, NULL, 0444);
+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 "
+		 "[enable bug compatibility for triton1 + others]");
+MODULE_PARM_DESC(vsfx,"set VSFX pci config bit "
+		 "[yet another chipset flaw workaround]");
+MODULE_PARM_DESC(latency,"pci latency timer");
+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, "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]");
+
+/* ----------------------------------------------------------------------- */
+/* list of card IDs for bt878+ cards                                       */
+
+static struct CARD {
+	unsigned id;
+	int cardnr;
+	char *name;
+} cards[] __devinitdata = {
+	{ 0x13eb0070, BTTV_BOARD_HAUPPAUGE878,  "Hauppauge WinTV" },
+	{ 0x39000070, BTTV_BOARD_HAUPPAUGE878,  "Hauppauge WinTV-D" },
+	{ 0x45000070, BTTV_BOARD_HAUPPAUGEPVR,  "Hauppauge WinTV/PVR" },
+	{ 0xff000070, BTTV_BOARD_OSPREY1x0,     "Osprey-100" },
+	{ 0xff010070, BTTV_BOARD_OSPREY2x0_SVID,"Osprey-200" },
+	{ 0xff020070, BTTV_BOARD_OSPREY500,     "Osprey-500" },
+	{ 0xff030070, BTTV_BOARD_OSPREY2000,    "Osprey-2000" },
+	{ 0xff040070, BTTV_BOARD_OSPREY540,     "Osprey-540" },
+	{ 0xff070070, BTTV_BOARD_OSPREY440,     "Osprey-440" },
+
+	{ 0x00011002, BTTV_BOARD_ATI_TVWONDER,  "ATI TV Wonder" },
+	{ 0x00031002, BTTV_BOARD_ATI_TVWONDERVE,"ATI TV Wonder/VE" },
+
+	{ 0x6606107d, BTTV_BOARD_WINFAST2000,   "Leadtek WinFast TV 2000" },
+	{ 0x6607107d, BTTV_BOARD_WINFASTVC100,  "Leadtek WinFast VC 100" },
+	{ 0x6609107d, BTTV_BOARD_WINFAST2000,   "Leadtek TV 2000 XP" },
+	{ 0x263610b4, BTTV_BOARD_STB2,          "STB TV PCI FM, Gateway P/N 6000704" },
+	{ 0x264510b4, BTTV_BOARD_STB2,          "STB TV PCI FM, Gateway P/N 6000704" },
+	{ 0x402010fc, BTTV_BOARD_GVBCTV3PCI,    "I-O Data Co. GV-BCTV3/PCI" },
+	{ 0x405010fc, BTTV_BOARD_GVBCTV4PCI,    "I-O Data Co. GV-BCTV4/PCI" },
+	{ 0x407010fc, BTTV_BOARD_GVBCTV5PCI,    "I-O Data Co. GV-BCTV5/PCI" },
+	{ 0xd01810fc, BTTV_BOARD_GVBCTV5PCI,    "I-O Data Co. GV-BCTV5/PCI" },
+
+	{ 0x001211bd, BTTV_BOARD_PINNACLE,      "Pinnacle PCTV" },
+	/* some cards ship with byteswapped IDs ... */
+	{ 0x1200bd11, BTTV_BOARD_PINNACLE,      "Pinnacle PCTV [bswap]" },
+	{ 0xff00bd11, BTTV_BOARD_PINNACLE,      "Pinnacle PCTV [bswap]" },
+	/* this seems to happen as well ... */
+	{ 0xff1211bd, BTTV_BOARD_PINNACLE,      "Pinnacle PCTV" },
+
+	{ 0x3000121a, BTTV_BOARD_VOODOOTV_200,  "3Dfx VoodooTV 200" },
+	{ 0x263710b4, BTTV_BOARD_VOODOOTV_FM,   "3Dfx VoodooTV FM" },
+	{ 0x3060121a, BTTV_BOARD_STB2,	  "3Dfx VoodooTV 100/ STB OEM" },
+
+	{ 0x3000144f, BTTV_BOARD_MAGICTVIEW063, "(Askey Magic/others) TView99 CPH06x" },
+	{ 0xa005144f, BTTV_BOARD_MAGICTVIEW063, "CPH06X TView99-Card" },
+	{ 0x3002144f, BTTV_BOARD_MAGICTVIEW061, "(Askey Magic/others) TView99 CPH05x" },
+	{ 0x3005144f, BTTV_BOARD_MAGICTVIEW061, "(Askey Magic/others) TView99 CPH061/06L (T1/LC)" },
+	{ 0x5000144f, BTTV_BOARD_MAGICTVIEW061, "Askey CPH050" },
+	{ 0x300014ff, BTTV_BOARD_MAGICTVIEW061, "TView 99 (CPH061)" },
+	{ 0x300214ff, BTTV_BOARD_PHOEBE_TVMAS,  "Phoebe TV Master (CPH060)" },
+
+	{ 0x00011461, BTTV_BOARD_AVPHONE98,     "AVerMedia TVPhone98" },
+	{ 0x00021461, BTTV_BOARD_AVERMEDIA98,   "AVermedia TVCapture 98" },
+	{ 0x00031461, BTTV_BOARD_AVPHONE98,     "AVerMedia TVPhone98" },
+	{ 0x00041461, BTTV_BOARD_AVERMEDIA98,   "AVerMedia TVCapture 98" },
+	{ 0x03001461, BTTV_BOARD_AVERMEDIA98,   "VDOMATE TV TUNER CARD" },
+
+	{ 0x1117153b, BTTV_BOARD_TERRATVALUE,   "Terratec TValue (Philips PAL B/G)" },
+	{ 0x1118153b, BTTV_BOARD_TERRATVALUE,   "Terratec TValue (Temic PAL B/G)" },
+	{ 0x1119153b, BTTV_BOARD_TERRATVALUE,   "Terratec TValue (Philips PAL I)" },
+	{ 0x111a153b, BTTV_BOARD_TERRATVALUE,   "Terratec TValue (Temic PAL I)" },
+
+	{ 0x1123153b, BTTV_BOARD_TERRATVRADIO,  "Terratec TV Radio+" },
+	{ 0x1127153b, BTTV_BOARD_TERRATV,       "Terratec TV+ (V1.05)"    },
+	/* clashes with FlyVideo
+	 *{ 0x18521852, BTTV_BOARD_TERRATV,     "Terratec TV+ (V1.10)"    }, */
+	{ 0x1134153b, BTTV_BOARD_TERRATVALUE,   "Terratec TValue (LR102)" },
+	{ 0x1135153b, BTTV_BOARD_TERRATVALUER,  "Terratec TValue Radio" }, /* LR102 */
+	{ 0x5018153b, BTTV_BOARD_TERRATVALUE,   "Terratec TValue" },       /* ?? */
+	{ 0xff3b153b, BTTV_BOARD_TERRATVALUER,  "Terratec TValue Radio" }, /* ?? */
+
+	{ 0x400015b0, BTTV_BOARD_ZOLTRIX_GENIE, "Zoltrix Genie TV" },
+	{ 0x400a15b0, BTTV_BOARD_ZOLTRIX_GENIE, "Zoltrix Genie TV" },
+	{ 0x400d15b0, BTTV_BOARD_ZOLTRIX_GENIE, "Zoltrix Genie TV / Radio" },
+	{ 0x401015b0, BTTV_BOARD_ZOLTRIX_GENIE, "Zoltrix Genie TV / Radio" },
+	{ 0x401615b0, BTTV_BOARD_ZOLTRIX_GENIE, "Zoltrix Genie TV / Radio" },
+
+	{ 0x1430aa00, BTTV_BOARD_PV143,         "Provideo PV143A" },
+	{ 0x1431aa00, BTTV_BOARD_PV143,         "Provideo PV143B" },
+	{ 0x1432aa00, BTTV_BOARD_PV143,         "Provideo PV143C" },
+	{ 0x1433aa00, BTTV_BOARD_PV143,         "Provideo PV143D" },
+	{ 0x1433aa03, BTTV_BOARD_PV143,         "Security Eyes" },
+
+	{ 0x1460aa00, BTTV_BOARD_PV150,         "Provideo PV150A-1" },
+	{ 0x1461aa01, BTTV_BOARD_PV150,         "Provideo PV150A-2" },
+	{ 0x1462aa02, BTTV_BOARD_PV150,         "Provideo PV150A-3" },
+	{ 0x1463aa03, BTTV_BOARD_PV150,         "Provideo PV150A-4" },
+
+	{ 0x1464aa04, BTTV_BOARD_PV150,         "Provideo PV150B-1" },
+	{ 0x1465aa05, BTTV_BOARD_PV150,         "Provideo PV150B-2" },
+	{ 0x1466aa06, BTTV_BOARD_PV150,         "Provideo PV150B-3" },
+	{ 0x1467aa07, BTTV_BOARD_PV150,         "Provideo PV150B-4" },
+
+	{ 0xa132ff00, BTTV_BOARD_IVC100,        "IVC-100"  },
+	{ 0xa1550000, BTTV_BOARD_IVC200,        "IVC-200"  },
+	{ 0xa1550001, BTTV_BOARD_IVC200,        "IVC-200"  },
+	{ 0xa1550002, BTTV_BOARD_IVC200,        "IVC-200"  },
+	{ 0xa1550003, BTTV_BOARD_IVC200,        "IVC-200"  },
+	{ 0xa1550100, BTTV_BOARD_IVC200,        "IVC-200G" },
+	{ 0xa1550101, BTTV_BOARD_IVC200,        "IVC-200G" },
+	{ 0xa1550102, BTTV_BOARD_IVC200,        "IVC-200G" },
+	{ 0xa1550103, BTTV_BOARD_IVC200,        "IVC-200G" },
+	{ 0xa1550800, BTTV_BOARD_IVC200,        "IVC-200"  },
+	{ 0xa1550801, BTTV_BOARD_IVC200,        "IVC-200"  },
+	{ 0xa1550802, BTTV_BOARD_IVC200,        "IVC-200"  },
+	{ 0xa1550803, BTTV_BOARD_IVC200,        "IVC-200"  },
+	{ 0xa182ff00, BTTV_BOARD_IVC120,        "IVC-120G" },
+	{ 0xa182ff01, BTTV_BOARD_IVC120,        "IVC-120G" },
+	{ 0xa182ff02, BTTV_BOARD_IVC120,        "IVC-120G" },
+	{ 0xa182ff03, BTTV_BOARD_IVC120,        "IVC-120G" },
+	{ 0xa182ff04, BTTV_BOARD_IVC120,        "IVC-120G" },
+	{ 0xa182ff05, BTTV_BOARD_IVC120,        "IVC-120G" },
+	{ 0xa182ff06, BTTV_BOARD_IVC120,        "IVC-120G" },
+	{ 0xa182ff07, BTTV_BOARD_IVC120,        "IVC-120G" },
+	{ 0xa182ff08, BTTV_BOARD_IVC120,        "IVC-120G" },
+	{ 0xa182ff09, BTTV_BOARD_IVC120,        "IVC-120G" },
+	{ 0xa182ff0a, BTTV_BOARD_IVC120,        "IVC-120G" },
+	{ 0xa182ff0b, BTTV_BOARD_IVC120,        "IVC-120G" },
+	{ 0xa182ff0c, BTTV_BOARD_IVC120,        "IVC-120G" },
+	{ 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" },
+
+	{ 0x18501851, BTTV_BOARD_CHRONOS_VS2,   "FlyVideo 98 (LR50)/ Chronos Video Shuttle II" },
+	{ 0xa0501851, BTTV_BOARD_CHRONOS_VS2,   "FlyVideo 98 (LR50)/ Chronos Video Shuttle II" },
+	{ 0x18511851, BTTV_BOARD_FLYVIDEO98EZ,  "FlyVideo 98EZ (LR51)/ CyberMail AV" },
+	{ 0x18521852, BTTV_BOARD_TYPHOON_TVIEW, "FlyVideo 98FM (LR50)/ Typhoon TView TV/FM Tuner" },
+	{ 0x41a0a051, BTTV_BOARD_FLYVIDEO_98FM, "Lifeview FlyVideo 98 LR50 Rev Q" },
+	{ 0x18501f7f, BTTV_BOARD_FLYVIDEO_98,   "Lifeview Flyvideo 98" },
+
+	{ 0x010115cb, BTTV_BOARD_GMV1,          "AG GMV1" },
+	{ 0x010114c7, BTTV_BOARD_MODTEC_205,    "Modular Technology MM201/MM202/MM205/MM210/MM215 PCTV" },
+
+	{ 0x10b42636, BTTV_BOARD_HAUPPAUGE878,  "STB ???" },
+	{ 0x217d6606, BTTV_BOARD_WINFAST2000,   "Leadtek WinFast TV 2000" },
+	{ 0xfff6f6ff, BTTV_BOARD_WINFAST2000,   "Leadtek WinFast TV 2000" },
+	{ 0x03116000, BTTV_BOARD_SENSORAY311_611, "Sensoray 311" },
+	{ 0x06116000, BTTV_BOARD_SENSORAY311_611, "Sensoray 611" },
+	{ 0x00790e11, BTTV_BOARD_WINDVR,        "Canopus WinDVR PCI" },
+	{ 0xa0fca1a0, BTTV_BOARD_ZOLTRIX,       "Face to Face Tvmax" },
+	{ 0x82b2aa6a, BTTV_BOARD_SIMUS_GVC1100, "SIMUS GVC1100" },
+	{ 0x146caa0c, BTTV_BOARD_PV951,         "ituner spectra8" },
+	{ 0x200a1295, BTTV_BOARD_PXC200,        "ImageNation PXC200A" },
+
+	{ 0x40111554, BTTV_BOARD_PV_BT878P_9B,  "Prolink Pixelview PV-BT" },
+	{ 0x17de0a01, BTTV_BOARD_KWORLD,        "Mecer TV/FM/Video Tuner" },
+
+	{ 0x01051805, BTTV_BOARD_PICOLO_TETRA_CHIP, "Picolo Tetra Chip #1" },
+	{ 0x01061805, BTTV_BOARD_PICOLO_TETRA_CHIP, "Picolo Tetra Chip #2" },
+	{ 0x01071805, BTTV_BOARD_PICOLO_TETRA_CHIP, "Picolo Tetra Chip #3" },
+	{ 0x01081805, BTTV_BOARD_PICOLO_TETRA_CHIP, "Picolo Tetra Chip #4" },
+
+	{ 0x15409511, BTTV_BOARD_ACORP_Y878F, "Acorp Y878F" },
+
+	{ 0x53534149, BTTV_BOARD_SSAI_SECURITY, "SSAI Security Video Interface" },
+	{ 0x5353414a, BTTV_BOARD_SSAI_ULTRASOUND, "SSAI Ultrasound Video Interface" },
+
+	/* likely broken, vendor id doesn't match the other magic views ...
+	 * { 0xa0fca04f, BTTV_BOARD_MAGICTVIEW063, "Guillemot Maxi TV Video 3" }, */
+
+	/* 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" },
+	{ 0x20007063, BTTV_BOARD_PC_HDTV,       "pcHDTV HD-2000 TV"},
+	{ 0x002611bd, BTTV_BOARD_TWINHAN_DST,   "Pinnacle PCTV SAT CI" },
+	{ 0x00011822, BTTV_BOARD_TWINHAN_DST,   "Twinhan VisionPlus DVB" },
+	{ 0xfc00270f, BTTV_BOARD_TWINHAN_DST,   "ChainTech digitop DST-1000 DVB-S" },
+	{ 0x07711461, BTTV_BOARD_AVDVBT_771,    "AVermedia AverTV DVB-T 771" },
+	{ 0x07611461, BTTV_BOARD_AVDVBT_761,    "AverMedia AverTV DVB-T 761" },
+	{ 0xdb1018ac, BTTV_BOARD_DVICO_DVBT_LITE,    "DViCO FusionHDTV DVB-T Lite" },
+	{ 0xdb1118ac, BTTV_BOARD_DVICO_DVBT_LITE,    "Ultraview DVB-T Lite" },
+	{ 0xd50018ac, BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE,    "DViCO FusionHDTV 5 Lite" },
+	{ 0x00261822, BTTV_BOARD_TWINHAN_DST,	"DNTV Live! Mini "},
+	{ 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" },
+	{ 0x3116f200, BTTV_BOARD_TVT_TD3116,	"Tongwei Video Technology TD-3116" },
+	{ 0x02280279, BTTV_BOARD_APOSONIC_WDVR, "Aposonic W-DVR" },
+	{ 0, -1, NULL }
+};
+
+/* ----------------------------------------------------------------------- */
+/* array with description for bt848 / bt878 tv/grabber cards               */
+
+struct tvcard bttv_tvcards[] = {
+	/* ---- card 0x00 ---------------------------------- */
+	[BTTV_BOARD_UNKNOWN] = {
+		.name		= " *** UNKNOWN/GENERIC *** ",
+		.video_inputs	= 4,
+		.svhs		= 2,
+		.muxsel		= MUXSEL(2, 3, 1, 0),
+		.tuner_type	= UNSET,
+		.tuner_addr	= ADDR_UNSET,
+	},
+	[BTTV_BOARD_MIRO] = {
+		.name		= "MIRO PCTV",
+		.video_inputs	= 4,
+		/* .audio_inputs= 1, */
+		.svhs		= 2,
+		.gpiomask	= 15,
+		.muxsel		= MUXSEL(2, 3, 1, 1),
+		.gpiomux 	= { 2, 0, 0, 0 },
+		.gpiomute 	= 10,
+		.tuner_type	= UNSET,
+		.tuner_addr	= ADDR_UNSET,
+	},
+	[BTTV_BOARD_HAUPPAUGE] = {
+		.name		= "Hauppauge (bt848)",
+		.video_inputs	= 4,
+		/* .audio_inputs= 1, */
+		.svhs		= 2,
+		.gpiomask	= 7,
+		.muxsel		= MUXSEL(2, 3, 1, 1),
+		.gpiomux 	= { 0, 1, 2, 3 },
+		.gpiomute 	= 4,
+		.tuner_type	= UNSET,
+		.tuner_addr	= ADDR_UNSET,
+	},
+	[BTTV_BOARD_STB] = {
+		.name		= "STB, Gateway P/N 6000699 (bt848)",
+		.video_inputs	= 3,
+		/* .audio_inputs= 1, */
+		.svhs		= 2,
+		.gpiomask	= 7,
+		.muxsel		= MUXSEL(2, 3, 1, 1),
+		.gpiomux 	= { 4, 0, 2, 3 },
+		.gpiomute 	= 1,
+		.no_msp34xx	= 1,
+		.tuner_type     = TUNER_PHILIPS_NTSC,
+		.tuner_addr	= ADDR_UNSET,
+		.pll            = PLL_28,
+		.has_radio      = 1,
+	},
+
+	/* ---- card 0x04 ---------------------------------- */
+	[BTTV_BOARD_INTEL] = {
+		.name		= "Intel Create and Share PCI/ Smart Video Recorder III",
+		.video_inputs	= 4,
+		/* .audio_inputs= 0, */
+		.svhs		= 2,
+		.gpiomask	= 0,
+		.muxsel		= MUXSEL(2, 3, 1, 1),
+		.gpiomux 	= { 0 },
+		.tuner_type	= TUNER_ABSENT,
+		.tuner_addr	= ADDR_UNSET,
+	},
+	[BTTV_BOARD_DIAMOND] = {
+		.name		= "Diamond DTV2000",
+		.video_inputs	= 4,
+		/* .audio_inputs= 1, */
+		.svhs		= 2,
+		.gpiomask	= 3,
+		.muxsel		= MUXSEL(2, 3, 1, 0),
+		.gpiomux 	= { 0, 1, 0, 1 },
+		.gpiomute 	= 3,
+		.tuner_type	= UNSET,
+		.tuner_addr	= ADDR_UNSET,
+	},
+	[BTTV_BOARD_AVERMEDIA] = {
+		.name		= "AVerMedia TVPhone",
+		.video_inputs	= 3,
+		/* .audio_inputs= 1, */
+		.svhs		= 3,
+		.muxsel		= MUXSEL(2, 3, 1, 1),
+		.gpiomask	= 0x0f,
+		.gpiomux 	= { 0x0c, 0x04, 0x08, 0x04 },
+		/*                0x04 for some cards ?? */
+		.tuner_type	= UNSET,
+		.tuner_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, */
+		.svhs		= 3,
+		.gpiomask	= 0,
+		.muxsel		= MUXSEL(2, 3, 1, 0, 0),
+		.gpiomux 	= { 0 },
+		.tuner_type	= TUNER_ABSENT,
+		.tuner_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, */
+		.svhs		= 2,
+		.gpiomask	= 0xc00,
+		.muxsel		= MUXSEL(2, 3, 1, 1),
+		.gpiomux 	= { 0, 0xc00, 0x800, 0x400 },
+		.gpiomute 	= 0xc00,
+		.pll		= PLL_28,
+		.tuner_type	= UNSET,
+		.tuner_addr	= ADDR_UNSET,
+	},
+	[BTTV_BOARD_TURBOTV] = {
+		.name		= "IMS/IXmicro TurboTV",
+		.video_inputs	= 3,
+		/* .audio_inputs= 1, */
+		.svhs		= 2,
+		.gpiomask	= 3,
+		.muxsel		= MUXSEL(2, 3, 1, 1),
+		.gpiomux 	= { 1, 1, 2, 3 },
+		.pll		= PLL_28,
+		.tuner_type	= TUNER_TEMIC_PAL,
+		.tuner_addr	= ADDR_UNSET,
+	},
+	[BTTV_BOARD_HAUPPAUGE878] = {
+		.name		= "Hauppauge (bt878)",
+		.video_inputs	= 4,
+		/* .audio_inputs= 1, */
+		.svhs		= 2,
+		.gpiomask	= 0x0f, /* old: 7 */
+		.muxsel		= MUXSEL(2, 0, 1, 1),
+		.gpiomux 	= { 0, 1, 2, 3 },
+		.gpiomute 	= 4,
+		.pll		= PLL_28,
+		.tuner_type	= UNSET,
+		.tuner_addr	= ADDR_UNSET,
+	},
+	[BTTV_BOARD_MIROPRO] = {
+		.name		= "MIRO PCTV pro",
+		.video_inputs	= 3,
+		/* .audio_inputs= 1, */
+		.svhs		= 2,
+		.gpiomask	= 0x3014f,
+		.muxsel		= MUXSEL(2, 3, 1, 1),
+		.gpiomux 	= { 0x20001,0x10001, 0, 0 },
+		.gpiomute 	= 10,
+		.tuner_type	= UNSET,
+		.tuner_addr	= ADDR_UNSET,
+	},
+
+	/* ---- card 0x0c ---------------------------------- */
+	[BTTV_BOARD_ADSTECH_TV] = {
+		.name		= "ADS Technologies Channel Surfer TV (bt848)",
+		.video_inputs	= 3,
+		/* .audio_inputs= 1, */
+		.svhs		= 2,
+		.gpiomask	= 15,
+		.muxsel		= MUXSEL(2, 3, 1, 1),
+		.gpiomux 	= { 13, 14, 11, 7 },
+		.tuner_type	= UNSET,
+		.tuner_addr	= ADDR_UNSET,
+	},
+	[BTTV_BOARD_AVERMEDIA98] = {
+		.name		= "AVerMedia TVCapture 98",
+		.video_inputs	= 3,
+		/* .audio_inputs= 4, */
+		.svhs		= 2,
+		.gpiomask	= 15,
+		.muxsel		= MUXSEL(2, 3, 1, 1),
+		.gpiomux 	= { 13, 14, 11, 7 },
+		.msp34xx_alt    = 1,
+		.pll		= PLL_28,
+		.tuner_type	= TUNER_PHILIPS_PAL,
+		.tuner_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, */
+		.svhs		= 2,
+		.gpiomask	= 7,
+		.muxsel		= MUXSEL(2, 3, 1, 1),
+		.gpiomux 	= { 0, 2, 1, 3 }, /* old: {0, 1, 2, 3, 4} */
+		.gpiomute 	= 4,
+		.pll		= PLL_28,
+		.tuner_type	= UNSET,
+		.tuner_addr	= ADDR_UNSET,
+	},
+	[BTTV_BOARD_ZOLTRIX] = {
+		.name		= "Zoltrix TV-Max",
+		.video_inputs	= 3,
+		/* .audio_inputs= 1, */
+		.svhs		= 2,
+		.gpiomask	= 15,
+		.muxsel		= MUXSEL(2, 3, 1, 1),
+		.gpiomux 	= { 0, 0, 1, 0 },
+		.gpiomute 	= 10,
+		.tuner_type	= UNSET,
+		.tuner_addr	= ADDR_UNSET,
+	},
+
+	/* ---- card 0x10 ---------------------------------- */
+	[BTTV_BOARD_PIXVIEWPLAYTV] = {
+		.name		= "Prolink Pixelview PlayTV (bt878)",
+		.video_inputs	= 3,
+		/* .audio_inputs= 1, */
+		.svhs		= 2,
+		.gpiomask	= 0x01fe00,
+		.muxsel		= MUXSEL(2, 3, 1, 1),
+		/* 2003-10-20 by "Anton A. Arapov" <arapov@mail.ru> */
+		.gpiomux        = { 0x001e00, 0, 0x018000, 0x014000 },
+		.gpiomute 	= 0x002000,
+		.pll		= PLL_28,
+		.tuner_type	= UNSET,
+		.tuner_addr     = ADDR_UNSET,
+	},
+	[BTTV_BOARD_WINVIEW_601] = {
+		.name		= "Leadtek WinView 601",
+		.video_inputs	= 3,
+		/* .audio_inputs= 1, */
+		.svhs		= 2,
+		.gpiomask	= 0x8300f8,
+		.muxsel		= MUXSEL(2, 3, 1, 1, 0),
+		.gpiomux 	= { 0x4fa007,0xcfa007,0xcfa007,0xcfa007 },
+		.gpiomute 	= 0xcfa007,
+		.tuner_type	= UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.volume_gpio	= winview_volume,
+		.has_radio	= 1,
+	},
+	[BTTV_BOARD_AVEC_INTERCAP] = {
+		.name		= "AVEC Intercapture",
+		.video_inputs	= 3,
+		/* .audio_inputs= 2, */
+		.svhs		= 2,
+		.gpiomask	= 0,
+		.muxsel		= MUXSEL(2, 3, 1, 1),
+		.gpiomux 	= { 1, 0, 0, 0 },
+		.tuner_type	= UNSET,
+		.tuner_addr	= ADDR_UNSET,
+	},
+	[BTTV_BOARD_LIFE_FLYKIT] = {
+		.name		= "Lifeview FlyVideo II EZ /FlyKit LR38 Bt848 (capture only)",
+		.video_inputs	= 4,
+		/* .audio_inputs= 1, */
+		.svhs		= NO_SVHS,
+		.gpiomask	= 0x8dff00,
+		.muxsel		= MUXSEL(2, 3, 1, 1),
+		.gpiomux 	= { 0 },
+		.no_msp34xx	= 1,
+		.tuner_type	= TUNER_ABSENT,
+		.tuner_addr	= ADDR_UNSET,
+	},
+
+	/* ---- card 0x14 ---------------------------------- */
+	[BTTV_BOARD_CEI_RAFFLES] = {
+		.name		= "CEI Raffles Card",
+		.video_inputs	= 3,
+		/* .audio_inputs= 3, */
+		.svhs		= 2,
+		.muxsel		= MUXSEL(2, 3, 1, 1),
+		.tuner_type	= UNSET,
+		.tuner_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 */
+		.svhs		= 2,
+		.gpiomask	= 0x1800,
+		.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,
+	},
+	[BTTV_BOARD_PHOEBE_TVMAS] = {
+		.name		= "Askey CPH050/ Phoebe Tv Master + FM",
+		.video_inputs	= 3,
+		/* .audio_inputs= 1, */
+		.svhs		= 2,
+		.gpiomask	= 0xc00,
+		.muxsel		= MUXSEL(2, 3, 1, 1),
+		.gpiomux 	= { 0, 1, 0x800, 0x400 },
+		.gpiomute 	= 0xc00,
+		.pll		= PLL_28,
+		.tuner_type	= UNSET,
+		.tuner_addr	= ADDR_UNSET,
+	},
+	[BTTV_BOARD_MODTEC_205] = {
+		.name		= "Modular Technology MM201/MM202/MM205/MM210/MM215 PCTV, bt878",
+		.video_inputs	= 3,
+		/* .audio_inputs= 1, */
+		.svhs		= NO_SVHS,
+		.has_dig_in	= 1,
+		.gpiomask	= 7,
+		.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,
+	},
+
+	/* ---- card 0x18 ---------------------------------- */
+	[BTTV_BOARD_MAGICTVIEW061] = {
+		.name		= "Askey CPH05X/06X (bt878) [many vendors]",
+		.video_inputs	= 3,
+		/* .audio_inputs= 1, */
+		.svhs		= 2,
+		.gpiomask	= 0xe00,
+		.muxsel		= MUXSEL(2, 3, 1, 1),
+		.gpiomux 	= {0x400, 0x400, 0x400, 0x400 },
+		.gpiomute 	= 0xc00,
+		.pll		= PLL_28,
+		.tuner_type	= UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.has_remote     = 1,
+		.has_radio	= 1,  /* not every card has radio */
+	},
+	[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, */
+		.svhs		= 2,
+		.gpiomask       = 0x1f0fff,
+		.muxsel		= MUXSEL(2, 3, 1, 1),
+		.gpiomux        = { 0x20000, 0x30000, 0x10000, 0 },
+		.gpiomute 	= 0x40000,
+		.tuner_type	= TUNER_PHILIPS_PAL,
+		.tuner_addr	= ADDR_UNSET,
+		.audio_mode_gpio= terratv_audio,
+	},
+	[BTTV_BOARD_HAUPPAUG_WCAM] = {
+		.name		= "Hauppauge WinCam newer (bt878)",
+		.video_inputs	= 4,
+		/* .audio_inputs= 1, */
+		.svhs		= 3,
+		.gpiomask	= 7,
+		.muxsel		= MUXSEL(2, 0, 1, 1),
+		.gpiomux 	= { 0, 1, 2, 3 },
+		.gpiomute 	= 4,
+		.tuner_type	= UNSET,
+		.tuner_addr	= ADDR_UNSET,
+	},
+	[BTTV_BOARD_MAXI] = {
+		.name		= "Lifeview FlyVideo 98/ MAXI TV Video PCI2 LR50",
+		.video_inputs	= 4,
+		/* .audio_inputs= 2, */
+		.svhs		= 2,
+		.gpiomask	= 0x1800,
+		.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,
+	},
+
+	/* ---- card 0x1c ---------------------------------- */
+	[BTTV_BOARD_TERRATV] = {
+		.name           = "Terratec TerraTV+ Version 1.1 (bt878)",
+		.video_inputs	= 3,
+		/* .audio_inputs= 1, */
+		.svhs		= 2,
+		.gpiomask	= 0x1f0fff,
+		.muxsel		= MUXSEL(2, 3, 1, 1),
+		.gpiomux 	= { 0x20000, 0x30000, 0x10000, 0x00000 },
+		.gpiomute 	= 0x40000,
+		.tuner_type	= TUNER_PHILIPS_PAL,
+		.tuner_addr	= ADDR_UNSET,
+		.audio_mode_gpio= terratv_audio,
+		/* GPIO wiring:
+		External 20 pin connector (for Active Radio Upgrade board)
+		gpio00: i2c-sda
+		gpio01: i2c-scl
+		gpio02: om5610-data
+		gpio03: om5610-clk
+		gpio04: om5610-wre
+		gpio05: om5610-stereo
+		gpio06: rds6588-davn
+		gpio07: Pin 7 n.c.
+		gpio08: nIOW
+		gpio09+10: nIOR, nSEL ?? (bt878)
+			gpio09: nIOR (bt848)
+			gpio10: nSEL (bt848)
+		Sound Routing:
+		gpio16: u2-A0 (1st 4052bt)
+		gpio17: u2-A1
+		gpio18: u2-nEN
+		gpio19: u4-A0 (2nd 4052)
+		gpio20: u4-A1
+			u4-nEN - GND
+		Btspy:
+			00000 : Cdrom (internal audio input)
+			10000 : ext. Video audio input
+			20000 : TV Mono
+			a0000 : TV Mono/2
+		1a0000 : TV Stereo
+			30000 : Radio
+			40000 : Mute
+	*/
+
+	},
+	[BTTV_BOARD_PXC200] = {
+		/* Jannik Fritsch <jannik@techfak.uni-bielefeld.de> */
+		.name		= "Imagenation PXC200",
+		.video_inputs	= 5,
+		/* .audio_inputs= 1, */
+		.svhs		= 1, /* was: 4 */
+		.gpiomask	= 0,
+		.muxsel		= MUXSEL(2, 3, 1, 0, 0),
+		.gpiomux 	= { 0 },
+		.tuner_type	= TUNER_ABSENT,
+		.tuner_addr	= ADDR_UNSET,
+		.muxsel_hook    = PXC200_muxsel,
+
+	},
+	[BTTV_BOARD_FLYVIDEO_98] = {
+		.name		= "Lifeview FlyVideo 98 LR50",
+		.video_inputs	= 4,
+		/* .audio_inputs= 1, */
+		.svhs		= 2,
+		.gpiomask	= 0x1800,  /* 0x8dfe00 */
+		.muxsel		= MUXSEL(2, 3, 1, 1),
+		.gpiomux 	= { 0, 0x0800, 0x1000, 0x1000 },
+		.gpiomute 	= 0x1800,
+		.pll            = PLL_28,
+		.tuner_type	= UNSET,
+		.tuner_addr	= ADDR_UNSET,
+	},
+	[BTTV_BOARD_IPROTV] = {
+		.name		= "Formac iProTV, Formac ProTV I (bt848)",
+		.video_inputs	= 4,
+		/* .audio_inputs= 1, */
+		.svhs		= 3,
+		.gpiomask	= 1,
+		.muxsel		= MUXSEL(2, 3, 1, 1),
+		.gpiomux 	= { 1, 0, 0, 0 },
+		.pll            = PLL_28,
+		.tuner_type	= TUNER_PHILIPS_PAL,
+		.tuner_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, */
+		.svhs		= 2,
+		.gpiomask	= 0,
+		.muxsel		= MUXSEL(2, 3, 1, 1),
+		.gpiomux 	= { 0 },
+		.tuner_type	= TUNER_ABSENT,
+		.tuner_addr	= ADDR_UNSET,
+	},
+	[BTTV_BOARD_TERRATVALUE] = {
+		.name           = "Terratec TerraTValue Version Bt878",
+		.video_inputs	= 3,
+		/* .audio_inputs= 1, */
+		.svhs		= 2,
+		.gpiomask	= 0xffff00,
+		.muxsel		= MUXSEL(2, 3, 1, 1),
+		.gpiomux 	= { 0x500, 0, 0x300, 0x900 },
+		.gpiomute 	= 0x900,
+		.pll		= PLL_28,
+		.tuner_type	= TUNER_PHILIPS_PAL,
+		.tuner_addr	= ADDR_UNSET,
+	},
+	[BTTV_BOARD_WINFAST2000] = {
+		.name		= "Leadtek WinFast 2000/ WinFast 2000 XP",
+		.video_inputs	= 4,
+		/* .audio_inputs= 1, */
+		.svhs		= 2,
+		/* 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 },
+		.gpiomute 	= 0x800000,
+		/* Audio Routing for "WinFast 2000 XP" (no tv stereo !)
+			gpio23 -- hef4052:nEnable (0x800000)
+			gpio12 -- hef4052:A1
+			gpio13 -- hef4052:A0
+		0x0000: external audio
+		0x1000: FM
+		0x2000: TV
+		0x3000: n.c.
+		Note: There exists another variant "Winfast 2000" with tv stereo !?
+		Note: eeprom only contains FF and pci subsystem id 107d:6606
+		*/
+		.pll		= PLL_28,
+		.has_radio	= 1,
+		.tuner_type	= TUNER_PHILIPS_PAL, /* default for now, gpio reads BFFF06 for Pal bg+dk */
+		.tuner_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, */
+		.svhs		= 2,
+		.gpiomask	= 0x1800,
+		.muxsel		= MUXSEL(2, 3, 1, 1),
+		.gpiomux 	= { 0, 0x800, 0x1000, 0x1000 },
+		.gpiomute 	= 0x1800,
+		.pll		= PLL_28,
+		.tuner_type	= UNSET,
+		.tuner_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, */
+		.svhs		= 2,
+		.gpiomask	= 0x1800,
+		.muxsel		= MUXSEL(2, 3, 1, 1),
+		.gpiomux 	= { 0, 0x800, 0x1000, 0x1000 },
+		.gpiomute 	= 0x1800,
+		.pll		= PLL_28,
+		.tuner_type	= UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.has_radio	= 1,
+	},
+	[BTTV_BOARD_PXELVWPLTVPRO] = {
+		.name		= "Prolink PixelView PlayTV pro",
+		.video_inputs	= 3,
+		/* .audio_inputs= 1, */
+		.svhs		= 2,
+		.gpiomask	= 0xff,
+		.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,
+	},
+	[BTTV_BOARD_MAGICTVIEW063] = {
+		.name		= "Askey CPH06X TView99",
+		.video_inputs	= 4,
+		/* .audio_inputs= 1, */
+		.svhs		= 2,
+		.gpiomask	= 0x551e00,
+		.muxsel		= MUXSEL(2, 3, 1, 0),
+		.gpiomux 	= { 0x551400, 0x551200, 0, 0 },
+		.gpiomute 	= 0x551c00,
+		.pll		= PLL_28,
+		.tuner_type	= TUNER_PHILIPS_PAL_I,
+		.tuner_addr	= ADDR_UNSET,
+		.has_remote     = 1,
+	},
+	[BTTV_BOARD_PINNACLE] = {
+		.name		= "Pinnacle PCTV Studio/Rave",
+		.video_inputs	= 3,
+		/* .audio_inputs= 1, */
+		.svhs		= 2,
+		.gpiomask	= 0x03000F,
+		.muxsel		= MUXSEL(2, 3, 1, 1),
+		.gpiomux 	= { 2, 0xd0001, 0, 0 },
+		.gpiomute 	= 1,
+		.pll		= PLL_28,
+		.tuner_type	= UNSET,
+		.tuner_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, */
+		.svhs		= 2,
+		.gpiomask	= 7,
+		.muxsel		= MUXSEL(2, 3, 1, 1),
+		.gpiomux 	= { 4, 0, 2, 3 },
+		.gpiomute 	= 1,
+		.no_msp34xx	= 1,
+		.tuner_type     = TUNER_PHILIPS_NTSC,
+		.tuner_addr	= ADDR_UNSET,
+		.pll            = PLL_28,
+		.has_radio      = 1,
+	},
+	[BTTV_BOARD_AVPHONE98] = {
+		.name		= "AVerMedia TVPhone 98",
+		.video_inputs	= 3,
+		/* .audio_inputs= 4, */
+		.svhs		= 2,
+		.gpiomask	= 15,
+		.muxsel		= MUXSEL(2, 3, 1, 1),
+		.gpiomux 	= { 13, 4, 11, 7 },
+		.pll		= PLL_28,
+		.tuner_type	= UNSET,
+		.tuner_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, */
+		.svhs		= 2,
+		.gpiomask	= 0,
+		.muxsel		= MUXSEL(2, 3, 1, 1),
+		.gpiomux 	= { 0, 0, 0, 0},
+		.no_msp34xx	= 1,
+		.pll		= PLL_28,
+		.tuner_type	= TUNER_PHILIPS_PAL_I,
+		.tuner_addr	= ADDR_UNSET,
+	},
+	[BTTV_BOARD_ONAIR_TV] = {
+		.name		= "Little OnAir TV",
+		.video_inputs	= 3,
+		/* .audio_inputs= 1, */
+		.svhs		= 2,
+		.gpiomask	= 0xe00b,
+		.muxsel		= MUXSEL(2, 3, 1, 1),
+		.gpiomux 	= { 0xff9ff6, 0xff9ff6, 0xff1ff7, 0 },
+		.gpiomute 	= 0xff3ffc,
+		.no_msp34xx	= 1,
+		.tuner_type	= UNSET,
+		.tuner_addr	= ADDR_UNSET,
+	},
+
+	/* ---- card 0x2c ---------------------------------- */
+	[BTTV_BOARD_SIGMA_TVII_FM] = {
+		.name		= "Sigma TVII-FM",
+		.video_inputs	= 2,
+		/* .audio_inputs= 1, */
+		.svhs		= NO_SVHS,
+		.gpiomask	= 3,
+		.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,
+	},
+	[BTTV_BOARD_MATRIX_VISION2] = {
+		.name		= "MATRIX-Vision MV-Delta 2",
+		.video_inputs	= 5,
+		/* .audio_inputs= 1, */
+		.svhs		= 3,
+		.gpiomask	= 0,
+		.muxsel		= MUXSEL(2, 3, 1, 0, 0),
+		.gpiomux 	= { 0 },
+		.no_msp34xx	= 1,
+		.pll		= PLL_28,
+		.tuner_type	= TUNER_ABSENT,
+		.tuner_addr	= ADDR_UNSET,
+	},
+	[BTTV_BOARD_ZOLTRIX_GENIE] = {
+		.name		= "Zoltrix Genie TV/FM",
+		.video_inputs	= 3,
+		/* .audio_inputs= 1, */
+		.svhs		= 2,
+		.gpiomask	= 0xbcf03f,
+		.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,
+	},
+	[BTTV_BOARD_TERRATVRADIO] = {
+		.name		= "Terratec TV/Radio+",
+		.video_inputs	= 3,
+		/* .audio_inputs= 1, */
+		.svhs		= 2,
+		.gpiomask	= 0x70000,
+		.muxsel		= MUXSEL(2, 3, 1, 1),
+		.gpiomux 	= { 0x20000, 0x30000, 0x10000, 0 },
+		.gpiomute 	= 0x40000,
+		.no_msp34xx	= 1,
+		.pll		= PLL_35,
+		.tuner_type	= TUNER_PHILIPS_PAL_I,
+		.tuner_addr	= ADDR_UNSET,
+		.has_radio	= 1,
+	},
+
+	/* ---- card 0x30 ---------------------------------- */
+	[BTTV_BOARD_DYNALINK] = {
+		.name		= "Askey CPH03x/ Dynalink Magic TView",
+		.video_inputs	= 3,
+		/* .audio_inputs= 1, */
+		.svhs		= 2,
+		.gpiomask	= 15,
+		.muxsel		= MUXSEL(2, 3, 1, 1),
+		.gpiomux 	= {2,0,0,0 },
+		.gpiomute 	= 1,
+		.pll		= PLL_28,
+		.tuner_type	= UNSET,
+		.tuner_addr	= ADDR_UNSET,
+	},
+	[BTTV_BOARD_GVBCTV3PCI] = {
+		.name		= "IODATA GV-BCTV3/PCI",
+		.video_inputs	= 3,
+		/* .audio_inputs= 1, */
+		.svhs		= 2,
+		.gpiomask	= 0x010f00,
+		.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,
+		.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, */
+		.svhs		= 3,
+		.has_dig_in	= 1,
+		.gpiomask	= 0xAA0000,
+		.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,
+		.has_remote	= 1,
+		/* GPIO wiring: (different from Rev.4C !)
+			GPIO17: U4.A0 (first hef4052bt)
+			GPIO19: U4.A1
+			GPIO20: U5.A1 (second hef4052bt)
+			GPIO21: U4.nEN
+			GPIO22: BT832 Reset Line
+			GPIO23: A5,A0, U5,nEN
+		Note: At i2c=0x8a is a Bt832 chip, which changes to 0x88 after being reset via GPIO22
+		*/
+	},
+	[BTTV_BOARD_EAGLE] = {
+		.name           = "Eagle Wireless Capricorn2 (bt878A)",
+		.video_inputs   = 4,
+		/* .audio_inputs= 1, */
+		.svhs           = 2,
+		.gpiomask       = 7,
+		.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,
+	},
+
+	/* ---- card 0x34 ---------------------------------- */
+	[BTTV_BOARD_PINNACLEPRO] = {
+		/* David Härdeman <david@2gen.com> */
+		.name           = "Pinnacle PCTV Studio Pro",
+		.video_inputs   = 4,
+		/* .audio_inputs= 1, */
+		.svhs           = 3,
+		.gpiomask       = 0x03000F,
+		.muxsel		= MUXSEL(2, 3, 1, 1),
+		.gpiomux 	= { 1, 0xd0001, 0, 0 },
+		.gpiomute 	= 10,
+				/* sound path (5 sources):
+				MUX1 (mask 0x03), Enable Pin 0x08 (0=enable, 1=disable)
+					0= ext. Audio IN
+					1= from MUX2
+					2= Mono TV sound from Tuner
+					3= not connected
+				MUX2 (mask 0x30000):
+					0,2,3= from MSP34xx
+					1= FM stereo Radio from Tuner */
+		.pll            = PLL_28,
+		.tuner_type     = UNSET,
+		.tuner_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, */
+		.svhs		= 2,
+		.gpiomask	= 0x1c,
+		.muxsel		= MUXSEL(2, 3, 1, 1),
+		.gpiomux 	= { 0, 0, 0x10, 8 },
+		.gpiomute 	= 4,
+		.pll		= PLL_28,
+		.tuner_type	= TUNER_PHILIPS_PAL,
+		.tuner_addr	= ADDR_UNSET,
+		.has_radio	= 1,
+	},
+	[BTTV_BOARD_LIFETEC_9415] = {
+		/* Tim Röstermundt <rosterm@uni-muenster.de>
+		in de.comp.os.unix.linux.hardware:
+			options bttv card=0 pll=1 radio=1 gpiomask=0x18e0
+			gpiomux =0x44c71f,0x44d71f,0,0x44d71f,0x44dfff
+			options tuner type=5 */
+		.name		= "Lifeview FlyVideo 2000 /FlyVideo A2/ Lifetec LT 9415 TV [LR90]",
+		.video_inputs	= 4,
+		/* .audio_inputs= 1, */
+		.svhs		= 2,
+		.gpiomask	= 0x18e0,
+		.muxsel		= MUXSEL(2, 3, 1, 1),
+		.gpiomux 	= { 0x0000,0x0800,0x1000,0x1000 },
+		.gpiomute 	= 0x18e0,
+			/* For cards with tda9820/tda9821:
+				0x0000: Tuner normal stereo
+				0x0080: Tuner A2 SAP (second audio program = Zweikanalton)
+				0x0880: Tuner A2 stereo */
+		.pll		= PLL_28,
+		.tuner_type	= UNSET,
+		.tuner_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, */
+		.svhs           = 2,
+		.gpiomask       = 0xF,
+		.muxsel         = MUXSEL(2, 3, 1, 0),
+		.gpiomux        = { 2, 0, 0, 0 },
+		.gpiomute 	= 10,
+		.pll		= PLL_28,
+		.tuner_type	= TUNER_TEMIC_PAL,
+		.tuner_addr	= ADDR_UNSET,
+	},
+
+	/* ---- card 0x38 ---------------------------------- */
+	[BTTV_BOARD_FLYVIDEO_98FM] = {
+		/* Gordon Heydon <gjheydon@bigfoot.com ('98) */
+		.name           = "Lifeview FlyVideo 98FM LR50",
+		.video_inputs   = 4,
+		/* .audio_inputs= 3, */
+		.svhs           = 2,
+		.gpiomask       = 0x1800,
+		.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,
+	},
+		/* This is the ultimate cheapo capture card
+		* just a BT848A on a small PCB!
+		* Steve Hosgood <steve@equiinet.com> */
+	[BTTV_BOARD_GRANDTEC] = {
+		.name           = "GrandTec 'Grand Video Capture' (Bt848)",
+		.video_inputs   = 2,
+		/* .audio_inputs= 0, */
+		.svhs           = 1,
+		.gpiomask       = 0,
+		.muxsel         = MUXSEL(3, 1),
+		.gpiomux        = { 0 },
+		.no_msp34xx     = 1,
+		.pll            = PLL_35,
+		.tuner_type     = TUNER_ABSENT,
+		.tuner_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, */
+		.svhs           = 2,
+		.gpiomask       = 0xe00,
+		.muxsel         = MUXSEL(2, 3, 1, 1),
+		.gpiomux        = { 0x400, 0x400, 0x400, 0x400 },
+		.gpiomute 	= 0x800,
+		.pll            = PLL_28,
+		.tuner_type     = TUNER_TEMIC_4036FY5_NTSC,
+		.tuner_addr	= ADDR_UNSET,
+	},
+	[BTTV_BOARD_ASKEY_CPH03X] = {
+		/* Matti Mottus <mottus@physic.ut.ee> */
+		.name		= "Askey CPH03x TV Capturer",
+		.video_inputs	= 4,
+		/* .audio_inputs= 1, */
+		.svhs		= 2,
+		.gpiomask       = 0x03000F,
+		.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,
+		.has_remote	= 1,
+	},
+
+	/* ---- card 0x3c ---------------------------------- */
+	[BTTV_BOARD_MM100PCTV] = {
+		/* Philip Blundell <philb@gnu.org> */
+		.name           = "Modular Technology MM100PCTV",
+		.video_inputs   = 2,
+		/* .audio_inputs= 2, */
+		.svhs		= NO_SVHS,
+		.gpiomask       = 11,
+		.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,
+	},
+	[BTTV_BOARD_GMV1] = {
+		/* Adrian Cox <adrian@humboldt.co.uk */
+		.name		= "AG Electronics GMV1",
+		.video_inputs   = 2,
+		/* .audio_inputs= 0, */
+		.svhs		= 1,
+		.gpiomask       = 0xF,
+		.muxsel		= MUXSEL(2, 2),
+		.gpiomux        = { },
+		.no_msp34xx     = 1,
+		.pll		= PLL_28,
+		.tuner_type     = TUNER_ABSENT,
+		.tuner_addr	= ADDR_UNSET,
+	},
+	[BTTV_BOARD_BESTBUY_EASYTV2] = {
+		/* Miguel Angel Alvarez <maacruz@navegalia.com>
+		new Easy TV BT878 version (model CPH061)
+		special thanks to Informatica Mieres for providing the card */
+		.name           = "Askey CPH061/ BESTBUY Easy TV (bt878)",
+		.video_inputs	= 3,
+		/* .audio_inputs= 2, */
+		.svhs           = 2,
+		.gpiomask       = 0xFF,
+		.muxsel         = MUXSEL(2, 3, 1, 0),
+		.gpiomux        = { 1, 0, 4, 4 },
+		.gpiomute 	= 9,
+		.pll		= PLL_28,
+		.tuner_type	= TUNER_PHILIPS_PAL,
+		.tuner_addr	= ADDR_UNSET,
+	},
+	[BTTV_BOARD_ATI_TVWONDER] = {
+		/* Lukas Gebauer <geby@volny.cz> */
+		.name		= "ATI TV-Wonder",
+		.video_inputs	= 3,
+		/* .audio_inputs= 1, */
+		.svhs		= 2,
+		.gpiomask	= 0xf03f,
+		.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,
+	},
+
+	/* ---- card 0x40 ---------------------------------- */
+	[BTTV_BOARD_ATI_TVWONDERVE] = {
+		/* Lukas Gebauer <geby@volny.cz> */
+		.name		= "ATI TV-Wonder VE",
+		.video_inputs	= 2,
+		/* .audio_inputs= 1, */
+		.svhs		= NO_SVHS,
+		.gpiomask	= 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,
+	},
+	[BTTV_BOARD_FLYVIDEO2000] = {
+		/* DeeJay <deejay@westel900.net (2000S) */
+		.name           = "Lifeview FlyVideo 2000S LR90",
+		.video_inputs   = 3,
+		/* .audio_inputs= 3, */
+		.svhs           = 2,
+		.gpiomask	= 0x18e0,
+		.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 */
+		.gpiomux 	= { 0x0000,0x0800,0x1000,0x1000 },
+		.gpiomute 	= 0x1800,
+		.audio_mode_gpio= fv2000s_audio,
+		.no_msp34xx	= 1,
+		.pll            = PLL_28,
+		.tuner_type     = TUNER_PHILIPS_PAL,
+		.tuner_addr	= ADDR_UNSET,
+	},
+	[BTTV_BOARD_TERRATVALUER] = {
+		.name		= "Terratec TValueRadio",
+		.video_inputs	= 3,
+		/* .audio_inputs= 1, */
+		.svhs		= 2,
+		.gpiomask	= 0xffff00,
+		.muxsel		= MUXSEL(2, 3, 1, 1),
+		.gpiomux 	= { 0x500, 0x500, 0x300, 0x900 },
+		.gpiomute 	= 0x900,
+		.pll		= PLL_28,
+		.tuner_type	= TUNER_PHILIPS_PAL,
+		.tuner_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, */
+		.svhs           = 2,
+		.gpiomask       = 0x010f00,
+		.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,
+		.audio_mode_gpio= gvbctv3pci_audio,
+	},
+
+	/* ---- card 0x44 ---------------------------------- */
+	[BTTV_BOARD_VOODOOTV_FM] = {
+		.name           = "3Dfx VoodooTV FM (Euro)",
+		/* try "insmod msp3400 simple=0" if you have
+		* sound problems with this card. */
+		.video_inputs   = 4,
+		/* .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) */
+		.gpiomux        = {0x947fff, 0x987fff,0x947fff,0x947fff },
+		.gpiomute 	= 0x947fff,
+		/* tvtuner, radio,   external,internal, mute,  stereo
+		* tuner, Composit, SVid, Composit-on-Svid-adapter */
+		.muxsel         = MUXSEL(2, 3, 0, 1),
+		.tuner_type     = TUNER_MT2032,
+		.tuner_addr	= ADDR_UNSET,
+		.pll		= PLL_28,
+		.has_radio	= 1,
+	},
+	[BTTV_BOARD_VOODOOTV_200] = {
+		.name           = "VoodooTV 200 (USA)",
+		/* try "insmod msp3400 simple=0" if you have
+		* sound problems with this card. */
+		.video_inputs   = 4,
+		/* .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) */
+		.gpiomux        = {0x947fff, 0x987fff,0x947fff,0x947fff },
+		.gpiomute 	= 0x947fff,
+		/* tvtuner, radio,   external,internal, mute,  stereo
+		* tuner, Composit, SVid, Composit-on-Svid-adapter */
+		.muxsel         = MUXSEL(2, 3, 0, 1),
+		.tuner_type     = TUNER_MT2032,
+		.tuner_addr	= ADDR_UNSET,
+		.pll		= PLL_28,
+		.has_radio	= 1,
+	},
+	[BTTV_BOARD_AIMMS] = {
+		/* Philip Blundell <pb@nexus.co.uk> */
+		.name           = "Active Imaging AIMMS",
+		.video_inputs   = 1,
+		/* .audio_inputs= 0, */
+		.tuner_type     = TUNER_ABSENT,
+		.tuner_addr	= ADDR_UNSET,
+		.pll            = PLL_28,
+		.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, */
+		.svhs           = 2,
+		.gpiomask       = 15,
+		.muxsel         = MUXSEL(2, 3, 1, 1),
+		.gpiomux        = { 0, 0, 11, 7 }, /* TV and Radio with same GPIO ! */
+		.gpiomute 	= 13,
+		.pll            = PLL_28,
+		.tuner_type     = TUNER_LG_PAL_I_FM,
+		.tuner_addr	= ADDR_UNSET,
+		.has_remote     = 1,
+		/* GPIO wiring:
+			GPIO0: U4.A0 (hef4052bt)
+			GPIO1: U4.A1
+			GPIO2: U4.A1 (second hef4052bt)
+			GPIO3: U4.nEN, U5.A0, A5.nEN
+			GPIO8-15: vrd866b ?
+		*/
+	},
+	[BTTV_BOARD_FLYVIDEO98EZ] = {
+		.name		= "Lifeview FlyVideo 98EZ (capture only) LR51",
+		.video_inputs	= 4,
+		/* .audio_inputs= 0, */
+		.svhs		= 2,
+		/* AV1, AV2, SVHS, CVid adapter on SVHS */
+		.muxsel		= MUXSEL(2, 3, 1, 1),
+		.pll		= PLL_28,
+		.no_msp34xx	= 1,
+		.tuner_type	= TUNER_ABSENT,
+		.tuner_addr	= ADDR_UNSET,
+	},
+
+	/* ---- card 0x48 ---------------------------------- */
+	[BTTV_BOARD_PV_BT878P_9B] = {
+		/* Dariusz Kowalewski <darekk@automex.pl> */
+		.name		= "Prolink Pixelview PV-BT878P+9B (PlayTV Pro rev.9B FM+NICAM)",
+		.video_inputs	= 4,
+		/* .audio_inputs= 1, */
+		.svhs		= 2,
+		.gpiomask	= 0x3f,
+		.muxsel		= MUXSEL(2, 3, 1, 1),
+		.gpiomux 	= { 0x01, 0x00, 0x03, 0x03 },
+		.gpiomute 	= 0x09,
+		.no_msp34xx	= 1,
+		.pll		= PLL_28,
+		.tuner_type	= TUNER_PHILIPS_PAL,
+		.tuner_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,
+		/* GPIO wiring:
+			GPIO0: A0 hef4052
+			GPIO1: A1 hef4052
+			GPIO3: nEN hef4052
+			GPIO8-15: vrd866b
+			GPIO20,22,23: R30,R29,R28
+		*/
+	},
+	[BTTV_BOARD_SENSORAY311_611] = {
+		/* Clay Kunz <ckunz@mail.arc.nasa.gov> */
+		/* you must jumper JP5 for the 311 card (PC/104+) to work */
+		.name           = "Sensoray 311/611",
+		.video_inputs   = 5,
+		/* .audio_inputs= 0, */
+		.svhs           = 4,
+		.gpiomask       = 0,
+		.muxsel         = MUXSEL(2, 3, 1, 0, 0),
+		.gpiomux        = { 0 },
+		.tuner_type     = TUNER_ABSENT,
+		.tuner_addr	= ADDR_UNSET,
+	},
+	[BTTV_BOARD_RV605] = {
+		/* Miguel Freitas <miguel@cetuc.puc-rio.br> */
+		.name           = "RemoteVision MX (RV605)",
+		.video_inputs   = 16,
+		/* .audio_inputs= 0, */
+		.svhs           = NO_SVHS,
+		.gpiomask       = 0x00,
+		.gpiomask2      = 0x07ff,
+		.muxsel         = MUXSEL(3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3),
+		.no_msp34xx     = 1,
+		.tuner_type     = TUNER_ABSENT,
+		.tuner_addr	= ADDR_UNSET,
+		.muxsel_hook    = rv605_muxsel,
+	},
+	[BTTV_BOARD_POWERCLR_MTV878] = {
+		.name           = "Powercolor MTV878/ MTV878R/ MTV878F",
+		.video_inputs   = 3,
+		/* .audio_inputs= 2, */
+		.svhs           = 2,
+		.gpiomask       = 0x1C800F,  /* Bit0-2: Audio select, 8-12:remote control 14:remote valid 15:remote reset */
+		.muxsel         = MUXSEL(2, 1, 1),
+		.gpiomux        = { 0, 1, 2, 2 },
+		.gpiomute 	= 4,
+		.tuner_type     = TUNER_PHILIPS_PAL,
+		.tuner_addr	= ADDR_UNSET,
+		.pll		= PLL_28,
+		.has_radio	= 1,
+	},
+
+	/* ---- card 0x4c ---------------------------------- */
+	[BTTV_BOARD_WINDVR] = {
+		/* Masaki Suzuki <masaki@btree.org> */
+		.name           = "Canopus WinDVR PCI (COMPAQ Presario 3524JP, 5112JP)",
+		.video_inputs   = 3,
+		/* .audio_inputs= 1, */
+		.svhs           = 2,
+		.gpiomask       = 0x140007,
+		.muxsel         = MUXSEL(2, 3, 1, 1),
+		.gpiomux        = { 0, 1, 2, 3 },
+		.gpiomute 	= 4,
+		.tuner_type     = TUNER_PHILIPS_NTSC,
+		.tuner_addr	= ADDR_UNSET,
+		.audio_mode_gpio= windvr_audio,
+	},
+	[BTTV_BOARD_GRANDTEC_MULTI] = {
+		.name           = "GrandTec Multi Capture Card (Bt878)",
+		.video_inputs   = 4,
+		/* .audio_inputs= 0, */
+		.svhs           = NO_SVHS,
+		.gpiomask       = 0,
+		.muxsel         = MUXSEL(2, 3, 1, 0),
+		.gpiomux        = { 0 },
+		.no_msp34xx     = 1,
+		.pll            = PLL_28,
+		.tuner_type     = TUNER_ABSENT,
+		.tuner_addr	= ADDR_UNSET,
+	},
+	[BTTV_BOARD_KWORLD] = {
+		.name           = "Jetway TV/Capture JW-TV878-FBK, Kworld KW-TV878RF",
+		.video_inputs   = 4,
+		/* .audio_inputs= 3, */
+		.svhs           = 2,
+		.gpiomask       = 7,
+		/* 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.
+						* This card lacks PCI subsystem ID, sigh.
+						* gpiomux =1: lower volume, 2+3: mute
+						* btwincap uses 0x80000/0x80003
+						*/
+		.gpiomute 	= 4,
+		.no_msp34xx     = 1,
+		.pll            = PLL_28,
+		.tuner_type     = TUNER_PHILIPS_PAL,
+		.tuner_addr	= ADDR_UNSET,
+		/* Samsung TCPA9095PC27A (BG+DK), philips compatible, w/FM, stereo and
+		radio signal strength indicators work fine. */
+		.has_radio	= 1,
+		/* GPIO Info:
+			GPIO0,1:   HEF4052 A0,A1
+			GPIO2:     HEF4052 nENABLE
+			GPIO3-7:   n.c.
+			GPIO8-13:  IRDC357 data0-5 (data6 n.c. ?) [chip not present on my card]
+			GPIO14,15: ??
+			GPIO16-21: n.c.
+			GPIO22,23: ??
+			??       : mtu8b56ep microcontroller for IR (GPIO wiring unknown)*/
+	},
+	[BTTV_BOARD_DSP_TCVIDEO] = {
+		/* Arthur Tetzlaff-Deas, DSP Design Ltd <software@dspdesign.com> */
+		.name           = "DSP Design TCVIDEO",
+		.video_inputs   = 4,
+		.svhs           = NO_SVHS,
+		.muxsel         = MUXSEL(2, 3, 1, 0),
+		.pll            = PLL_28,
+		.tuner_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+	},
+
+		/* ---- card 0x50 ---------------------------------- */
+	[BTTV_BOARD_HAUPPAUGEPVR] = {
+		.name           = "Hauppauge WinTV PVR",
+		.video_inputs   = 4,
+		/* .audio_inputs= 1, */
+		.svhs           = 2,
+		.muxsel         = MUXSEL(2, 0, 1, 1),
+		.pll            = PLL_28,
+		.tuner_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+
+		.gpiomask       = 7,
+		.gpiomux        = {7},
+	},
+	[BTTV_BOARD_GVBCTV5PCI] = {
+		.name           = "IODATA GV-BCTV5/PCI",
+		.video_inputs   = 3,
+		/* .audio_inputs= 1, */
+		.svhs           = 2,
+		.gpiomask       = 0x0f0f80,
+		.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,
+		.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, */
+		.svhs           = 3,
+		.muxsel         = MUXSEL(3, 2, 0, 1),
+		.pll            = PLL_28,
+		.tuner_type     = TUNER_ABSENT,
+		.tuner_addr	= ADDR_UNSET,
+		.no_msp34xx     = 1,
+		.no_tda7432     = 1,
+	},
+	[BTTV_BOARD_OSPREY1x0_848] = {
+		.name           = "Osprey 100/150 (848)", /* 0x04-54C0-C1 & older boards */
+		.video_inputs   = 3,
+		/* .audio_inputs= 0, */
+		.svhs           = 2,
+		.muxsel         = MUXSEL(2, 3, 1),
+		.pll            = PLL_28,
+		.tuner_type     = TUNER_ABSENT,
+		.tuner_addr	= ADDR_UNSET,
+		.no_msp34xx     = 1,
+		.no_tda7432     = 1,
+	},
+
+		/* ---- card 0x54 ---------------------------------- */
+	[BTTV_BOARD_OSPREY101_848] = {
+		.name           = "Osprey 101 (848)", /* 0x05-40C0-C1 */
+		.video_inputs   = 2,
+		/* .audio_inputs= 0, */
+		.svhs           = 1,
+		.muxsel         = MUXSEL(3, 1),
+		.pll            = PLL_28,
+		.tuner_type     = TUNER_ABSENT,
+		.tuner_addr	= ADDR_UNSET,
+		.no_msp34xx     = 1,
+		.no_tda7432     = 1,
+	},
+	[BTTV_BOARD_OSPREY1x1] = {
+		.name           = "Osprey 101/151",       /* 0x1(4|5)-0004-C4 */
+		.video_inputs   = 1,
+		/* .audio_inputs= 0, */
+		.svhs           = NO_SVHS,
+		.muxsel         = MUXSEL(0),
+		.pll            = PLL_28,
+		.tuner_type     = TUNER_ABSENT,
+		.tuner_addr	= ADDR_UNSET,
+		.no_msp34xx     = 1,
+		.no_tda7432     = 1,
+	},
+	[BTTV_BOARD_OSPREY1x1_SVID] = {
+		.name           = "Osprey 101/151 w/ svid",  /* 0x(16|17|20)-00C4-C1 */
+		.video_inputs   = 2,
+		/* .audio_inputs= 0, */
+		.svhs           = 1,
+		.muxsel         = MUXSEL(0, 1),
+		.pll            = PLL_28,
+		.tuner_type     = TUNER_ABSENT,
+		.tuner_addr	= ADDR_UNSET,
+		.no_msp34xx     = 1,
+		.no_tda7432     = 1,
+	},
+	[BTTV_BOARD_OSPREY2xx] = {
+		.name           = "Osprey 200/201/250/251",  /* 0x1(8|9|E|F)-0004-C4 */
+		.video_inputs   = 1,
+		/* .audio_inputs= 1, */
+		.svhs           = NO_SVHS,
+		.muxsel         = MUXSEL(0),
+		.pll            = PLL_28,
+		.tuner_type	= TUNER_ABSENT,
+		.tuner_addr	= ADDR_UNSET,
+		.no_msp34xx     = 1,
+		.no_tda7432     = 1,
+	},
+
+		/* ---- card 0x58 ---------------------------------- */
+	[BTTV_BOARD_OSPREY2x0_SVID] = {
+		.name           = "Osprey 200/250",   /* 0x1(A|B)-00C4-C1 */
+		.video_inputs   = 2,
+		/* .audio_inputs= 1, */
+		.svhs           = 1,
+		.muxsel         = MUXSEL(0, 1),
+		.pll            = PLL_28,
+		.tuner_type	= TUNER_ABSENT,
+		.tuner_addr	= ADDR_UNSET,
+		.no_msp34xx     = 1,
+		.no_tda7432     = 1,
+	},
+	[BTTV_BOARD_OSPREY2x0] = {
+		.name           = "Osprey 210/220/230",   /* 0x1(A|B)-04C0-C1 */
+		.video_inputs   = 2,
+		/* .audio_inputs= 1, */
+		.svhs           = 1,
+		.muxsel         = MUXSEL(2, 3),
+		.pll            = PLL_28,
+		.tuner_type	= TUNER_ABSENT,
+		.tuner_addr	= ADDR_UNSET,
+		.no_msp34xx     = 1,
+		.no_tda7432     = 1,
+	},
+	[BTTV_BOARD_OSPREY500] = {
+		.name           = "Osprey 500",   /* 500 */
+		.video_inputs   = 2,
+		/* .audio_inputs= 1, */
+		.svhs           = 1,
+		.muxsel         = MUXSEL(2, 3),
+		.pll            = PLL_28,
+		.tuner_type     = TUNER_ABSENT,
+		.tuner_addr	= ADDR_UNSET,
+		.no_msp34xx     = 1,
+		.no_tda7432     = 1,
+	},
+	[BTTV_BOARD_OSPREY540] = {
+		.name           = "Osprey 540",   /* 540 */
+		.video_inputs   = 4,
+		/* .audio_inputs= 1, */
+		.pll            = PLL_28,
+		.tuner_type     = TUNER_ABSENT,
+		.tuner_addr	= ADDR_UNSET,
+		.no_msp34xx     = 1,
+		.no_tda7432     = 1,
+	},
+
+		/* ---- card 0x5C ---------------------------------- */
+	[BTTV_BOARD_OSPREY2000] = {
+		.name           = "Osprey 2000",  /* 2000 */
+		.video_inputs   = 2,
+		/* .audio_inputs= 1, */
+		.svhs           = 1,
+		.muxsel         = MUXSEL(2, 3),
+		.pll            = PLL_28,
+		.tuner_type	= TUNER_ABSENT,
+		.tuner_addr	= ADDR_UNSET,
+		.no_msp34xx     = 1,
+		.no_tda7432     = 1,      /* must avoid, conflicts with the bt860 */
+	},
+	[BTTV_BOARD_IDS_EAGLE] = {
+		/* M G Berberich <berberic@forwiss.uni-passau.de> */
+		.name           = "IDS Eagle",
+		.video_inputs   = 4,
+		/* .audio_inputs= 0, */
+		.tuner_type     = TUNER_ABSENT,
+		.tuner_addr	= ADDR_UNSET,
+		.svhs           = NO_SVHS,
+		.gpiomask       = 0,
+		.muxsel         = MUXSEL(2, 2, 2, 2),
+		.muxsel_hook    = eagle_muxsel,
+		.no_msp34xx     = 1,
+		.pll            = PLL_28,
+	},
+	[BTTV_BOARD_PINNACLESAT] = {
+		.name           = "Pinnacle PCTV Sat",
+		.video_inputs   = 2,
+		/* .audio_inputs= 0, */
+		.svhs           = 1,
+		.tuner_type     = TUNER_ABSENT,
+		.tuner_addr	= ADDR_UNSET,
+		.no_msp34xx     = 1,
+		.no_tda7432     = 1,
+		.muxsel         = MUXSEL(3, 1),
+		.pll            = PLL_28,
+		.no_gpioirq     = 1,
+		.has_dvb        = 1,
+	},
+	[BTTV_BOARD_FORMAC_PROTV] = {
+		.name           = "Formac ProTV II (bt878)",
+		.video_inputs   = 4,
+		/* .audio_inputs= 1, */
+		.svhs           = 3,
+		.gpiomask       = 2,
+		/* TV, Comp1, Composite over SVID con, SVID */
+		.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,
+	/* sound routing:
+		GPIO=0x00,0x01,0x03: mute (?)
+		0x02: both TV and radio (tuner: FM1216/I)
+		The card has onboard audio connectors labeled "cdrom" and "board",
+		not soldered here, though unknown wiring.
+		Card lacks: external audio in, pci subsystem id.
+	*/
+	},
+
+		/* ---- card 0x60 ---------------------------------- */
+	[BTTV_BOARD_MACHTV] = {
+		.name           = "MachTV",
+		.video_inputs   = 3,
+		/* .audio_inputs= 1, */
+		.svhs           = NO_SVHS,
+		.gpiomask       = 7,
+		.muxsel         = MUXSEL(2, 3, 1, 1),
+		.gpiomux        = { 0, 1, 2, 3},
+		.gpiomute 	= 4,
+		.tuner_type     = TUNER_PHILIPS_PAL,
+		.tuner_addr	= ADDR_UNSET,
+		.pll            = PLL_28,
+	},
+	[BTTV_BOARD_EURESYS_PICOLO] = {
+		.name           = "Euresys Picolo",
+		.video_inputs   = 3,
+		/* .audio_inputs= 0, */
+		.svhs           = 2,
+		.gpiomask       = 0,
+		.no_msp34xx     = 1,
+		.no_tda7432     = 1,
+		.muxsel         = MUXSEL(2, 0, 1),
+		.pll            = PLL_28,
+		.tuner_type     = TUNER_ABSENT,
+		.tuner_addr	= ADDR_UNSET,
+	},
+	[BTTV_BOARD_PV150] = {
+		/* Luc Van Hoeylandt <luc@e-magic.be> */
+		.name           = "ProVideo PV150", /* 0x4f */
+		.video_inputs   = 2,
+		/* .audio_inputs= 0, */
+		.svhs           = NO_SVHS,
+		.gpiomask       = 0,
+		.muxsel         = MUXSEL(2, 3),
+		.gpiomux        = { 0 },
+		.no_msp34xx     = 1,
+		.pll            = PLL_28,
+		.tuner_type     = TUNER_ABSENT,
+		.tuner_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, */
+		.svhs           = 2,
+		.gpiomask       = 0x001e8007,
+		.muxsel         = MUXSEL(2, 3, 1, 0),
+		/*                  Tuner, Radio, external, internal, off,  on */
+		.gpiomux        = { 0x08,  0x0f,  0x0a,     0x08 },
+		.gpiomute 	= 0x0f,
+		.no_msp34xx     = 1,
+		.pll            = PLL_28,
+		.tuner_type     = TUNER_PHILIPS_NTSC,
+		.tuner_addr	= ADDR_UNSET,
+		.audio_mode_gpio= adtvk503_audio,
+	},
+
+		/* ---- card 0x64 ---------------------------------- */
+	[BTTV_BOARD_HERCULES_SM_TV] = {
+		.name           = "Hercules Smart TV Stereo",
+		.video_inputs   = 4,
+		/* .audio_inputs= 1, */
+		.svhs           = 2,
+		.gpiomask       = 0x00,
+		.muxsel         = MUXSEL(2, 3, 1, 1),
+		.no_msp34xx     = 1,
+		.pll            = PLL_28,
+		.tuner_type     = TUNER_PHILIPS_PAL,
+		.tuner_addr	= ADDR_UNSET,
+		/* Notes:
+		- card lacks subsystem ID
+		- stereo variant w/ daughter board with tda9874a @0xb0
+		- Audio Routing:
+			always from tda9874 independent of GPIO (?)
+			external line in: unknown
+		- Other chips: em78p156elp @ 0x96 (probably IR remote control)
+			hef4053 (instead 4052) for unknown function
+		*/
+	},
+	[BTTV_BOARD_PACETV] = {
+		.name           = "Pace TV & Radio Card",
+		.video_inputs   = 4,
+		/* .audio_inputs= 1, */
+		.svhs           = 2,
+		/* Tuner, CVid, SVid, CVid over SVid connector */
+		.muxsel         = MUXSEL(2, 3, 1, 1),
+		.gpiomask       = 0,
+		.no_tda7432     = 1,
+		.tuner_type     = TUNER_PHILIPS_PAL_I,
+		.tuner_addr	= ADDR_UNSET,
+		.has_radio      = 1,
+		.pll            = PLL_28,
+		/* Bt878, Bt832, FI1246 tuner; no pci subsystem id
+		only internal line out: (4pin header) RGGL
+		Radio must be decoded by msp3410d (not routed through)*/
+		/*
+		.digital_mode   = DIGITAL_MODE_CAMERA,  todo!
+		*/
+	},
+	[BTTV_BOARD_IVC200] = {
+		/* Chris Willing <chris@vislab.usyd.edu.au> */
+		.name           = "IVC-200",
+		.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_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, */
+		.svhs           = NO_SVHS,
+		.tuner_type     = TUNER_ABSENT,
+		.tuner_addr	= ADDR_UNSET,
+		.gpiomask2      = 0xff,
+		.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_tda7432     = 1,
+		.pll            = PLL_28,
+	},
+
+		/* ---- card 0x68 ---------------------------------- */
+	[BTTV_BOARD_NEBULA_DIGITV] = {
+		.name           = "Nebula Electronics DigiTV",
+		.video_inputs   = 1,
+		.svhs           = NO_SVHS,
+		.muxsel         = MUXSEL(2, 3, 1, 0),
+		.no_msp34xx     = 1,
+		.no_tda7432     = 1,
+		.pll            = PLL_28,
+		.tuner_type     = TUNER_ABSENT,
+		.tuner_addr	= ADDR_UNSET,
+		.has_dvb        = 1,
+		.has_remote	= 1,
+		.gpiomask	= 0x1b,
+		.no_gpioirq     = 1,
+	},
+	[BTTV_BOARD_PV143] = {
+		/* Jorge Boncompte - DTI2 <jorge@dti2.net> */
+		.name           = "ProVideo PV143",
+		.video_inputs   = 4,
+		/* .audio_inputs= 0, */
+		.svhs           = NO_SVHS,
+		.gpiomask       = 0,
+		.muxsel         = MUXSEL(2, 3, 1, 0),
+		.gpiomux        = { 0 },
+		.no_msp34xx     = 1,
+		.pll            = PLL_28,
+		.tuner_type     = TUNER_ABSENT,
+		.tuner_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, */
+		.svhs           = 3,
+		.gpiomask       = 0x00,
+		.muxsel         = MUXSEL(2, 3, 1, 0),
+		.gpiomux        = { 0, 0, 0, 0 }, /* card has no audio */
+		.pll            = PLL_28,
+		.tuner_type     = TUNER_ABSENT,
+		.tuner_addr	= ADDR_UNSET,
+	},
+	[BTTV_BOARD_VD009X1_VD011_COMBI] = {
+		.name           = "PHYTEC VD-009-X1 VD-011 Combi (bt878)",
+		.video_inputs   = 4,
+		/* .audio_inputs= 0, */
+		.svhs           = 3,
+		.gpiomask       = 0x00,
+		.muxsel         = MUXSEL(2, 3, 1, 1),
+		.gpiomux        = { 0, 0, 0, 0 }, /* card has no audio */
+		.pll            = PLL_28,
+		.tuner_type     = TUNER_ABSENT,
+		.tuner_addr	= ADDR_UNSET,
+	},
+
+		/* ---- card 0x6c ---------------------------------- */
+	[BTTV_BOARD_VD009_MINIDIN] = {
+		.name           = "PHYTEC VD-009 MiniDIN (bt878)",
+		.video_inputs   = 10,
+		/* .audio_inputs= 0, */
+		.svhs           = 9,
+		.gpiomask       = 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 */
+		.pll            = PLL_28,
+		.tuner_type     = TUNER_ABSENT,
+		.tuner_addr	= ADDR_UNSET,
+	},
+	[BTTV_BOARD_VD009_COMBI] = {
+		.name           = "PHYTEC VD-009 Combi (bt878)",
+		.video_inputs   = 10,
+		/* .audio_inputs= 0, */
+		.svhs           = 9,
+		.gpiomask       = 0x00,
+		.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 */
+		.pll            = PLL_28,
+		.tuner_type     = TUNER_ABSENT,
+		.tuner_addr	= ADDR_UNSET,
+	},
+	[BTTV_BOARD_IVC100] = {
+		.name           = "IVC-100",
+		.video_inputs   = 4,
+		/* .audio_inputs= 0, */
+		.tuner_type     = TUNER_ABSENT,
+		.tuner_addr	= ADDR_UNSET,
+		.svhs           = NO_SVHS,
+		.gpiomask       = 0xdf,
+		.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, */
+		.tuner_type     = TUNER_ABSENT,
+		.tuner_addr	= ADDR_UNSET,
+		.svhs           = NO_SVHS,   /* card has no svhs */
+		.no_msp34xx     = 1,
+		.no_tda7432     = 1,
+		.gpiomask       = 0x00,
+		.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,
+	},
+
+		/* ---- card 0x70 ---------------------------------- */
+	[BTTV_BOARD_PC_HDTV] = {
+		.name           = "pcHDTV HD-2000 TV",
+		.video_inputs   = 4,
+		/* .audio_inputs= 1, */
+		.svhs           = 2,
+		.muxsel         = MUXSEL(2, 3, 1, 0),
+		.tuner_type     = TUNER_PHILIPS_FCV1236D,
+		.tuner_addr	= ADDR_UNSET,
+		.has_dvb        = 1,
+	},
+	[BTTV_BOARD_TWINHAN_DST] = {
+		.name           = "Twinhan DST + clones",
+		.no_msp34xx     = 1,
+		.no_tda7432     = 1,
+		.tuner_type     = TUNER_ABSENT,
+		.tuner_addr	= ADDR_UNSET,
+		.no_video       = 1,
+		.has_dvb        = 1,
+	},
+	[BTTV_BOARD_WINFASTVC100] = {
+		.name           = "Winfast VC100",
+		.video_inputs   = 3,
+		/* .audio_inputs= 0, */
+		.svhs           = 1,
+		/* Vid In, SVid In, Vid over SVid in connector */
+		.muxsel		= MUXSEL(3, 1, 1, 3),
+		.no_msp34xx     = 1,
+		.no_tda7432     = 1,
+		.tuner_type     = TUNER_ABSENT,
+		.tuner_addr	= ADDR_UNSET,
+		.pll            = PLL_28,
+	},
+	[BTTV_BOARD_TEV560] = {
+		.name           = "Teppro TEV-560/InterVision IV-560",
+		.video_inputs   = 3,
+		/* .audio_inputs= 1, */
+		.svhs           = 2,
+		.gpiomask       = 3,
+		.muxsel         = MUXSEL(2, 3, 1, 1),
+		.gpiomux        = { 1, 1, 1, 1 },
+		.tuner_type     = TUNER_PHILIPS_PAL,
+		.tuner_addr	= ADDR_UNSET,
+		.pll            = PLL_35,
+	},
+
+		/* ---- card 0x74 ---------------------------------- */
+	[BTTV_BOARD_SIMUS_GVC1100] = {
+		.name           = "SIMUS GVC1100",
+		.video_inputs   = 4,
+		/* .audio_inputs= 0, */
+		.svhs           = NO_SVHS,
+		.tuner_type     = TUNER_ABSENT,
+		.tuner_addr	= ADDR_UNSET,
+		.pll            = PLL_28,
+		.muxsel         = MUXSEL(2, 2, 2, 2),
+		.gpiomask       = 0x3F,
+		.muxsel_hook    = gvc1100_muxsel,
+	},
+	[BTTV_BOARD_NGSTV_PLUS] = {
+		/* Carlos Silva r3pek@r3pek.homelinux.org || card 0x75 */
+		.name           = "NGS NGSTV+",
+		.video_inputs   = 3,
+		.svhs           = 2,
+		.gpiomask       = 0x008007,
+		.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,
+		.has_remote     = 1,
+	},
+	[BTTV_BOARD_LMLBT4] = {
+		/* http://linuxmedialabs.com */
+		.name           = "LMLBT4",
+		.video_inputs   = 4, /* IN1,IN2,IN3,IN4 */
+		/* .audio_inputs= 0, */
+		.svhs           = NO_SVHS,
+		.muxsel         = MUXSEL(2, 3, 1, 0),
+		.no_msp34xx     = 1,
+		.no_tda7432     = 1,
+		.tuner_type     = TUNER_ABSENT,
+		.tuner_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_type     = TUNER_PHILIPS_PAL,
+		.tuner_addr	= ADDR_UNSET,
+		.svhs           = 2,
+		.gpiomask       = 0x68,
+		.muxsel         = MUXSEL(2, 3, 1),
+		.gpiomux        = { 0x68, 0x68, 0x61, 0x61 },
+		.pll            = PLL_28,
+	},
+
+		/* ---- card 0x78 ---------------------------------- */
+	[BTTV_BOARD_CONTVFMI] = {
+		/* Javier Cendan Ares <jcendan@lycos.es> */
+		/* bt878 TV + FM without subsystem ID */
+		.name           = "Conceptronic CONTVFMi",
+		.video_inputs   = 3,
+		/* .audio_inputs= 1, */
+		.svhs           = 2,
+		.gpiomask       = 0x008007,
+		.muxsel         = MUXSEL(2, 3, 1, 1),
+		.gpiomux        = { 0, 1, 2, 2 },
+		.gpiomute 	= 3,
+		.pll            = PLL_28,
+		.tuner_type     = TUNER_PHILIPS_PAL,
+		.tuner_addr	= ADDR_UNSET,
+		.has_remote     = 1,
+		.has_radio      = 1,
+	},
+	[BTTV_BOARD_PICOLO_TETRA_CHIP] = {
+		/*Eric DEBIEF <debief@telemsa.com>*/
+		/*EURESYS Picolo Tetra : 4 Conexant Fusion 878A, no audio, video input set with analog multiplexers GPIO controlled*/
+		/* adds picolo_tetra_muxsel(), picolo_tetra_init(), the following declaration strucure, and #define BTTV_BOARD_PICOLO_TETRA_CHIP*/
+		/*0x79 in bttv.h*/
+		.name           = "Euresys Picolo Tetra",
+		.video_inputs   = 4,
+		/* .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_tda7432     = 1,
+		/*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,
+		.muxsel_hook    = picolo_tetra_muxsel,/*Required as it doesn't follow the classic input selection policy*/
+		.tuner_type     = TUNER_ABSENT,
+		.tuner_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, */
+		.svhs           = 2,
+		.gpiomask       = 0x0000000f,
+		.muxsel         = MUXSEL(2, 1, 1),
+		.gpiomux        = { 0x02, 0x00, 0x00, 0x00 },
+		.tuner_type     = TUNER_TEMIC_PAL,
+		.tuner_addr	= ADDR_UNSET,
+		.no_msp34xx     = 1,
+	},
+	[BTTV_BOARD_AVDVBT_771] = {
+		/* Wolfram Joost <wojo@frokaschwei.de> */
+		.name           = "AVerMedia AVerTV DVB-T 771",
+		.video_inputs   = 2,
+		.svhs           = 1,
+		.tuner_type     = TUNER_ABSENT,
+		.tuner_addr	= ADDR_UNSET,
+		.muxsel         = MUXSEL(3, 3),
+		.no_msp34xx     = 1,
+		.no_tda7432     = 1,
+		.pll            = PLL_28,
+		.has_dvb        = 1,
+		.no_gpioirq     = 1,
+		.has_remote     = 1,
+	},
+		/* ---- card 0x7c ---------------------------------- */
+	[BTTV_BOARD_AVDVBT_761] = {
+		/* Matt Jesson <dvb@jesson.eclipse.co.uk> */
+		/* 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,
+		.svhs           = 1,
+		.muxsel         = MUXSEL(3, 1, 2, 0), /* Comp0, S-Video, ?, ? */
+		.no_msp34xx     = 1,
+		.no_tda7432     = 1,
+		.pll            = PLL_28,
+		.tuner_type     = TUNER_ABSENT,
+		.tuner_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, */
+		.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, */
+		.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] = {
+		/* Attila Kondoros <attila.kondoros@chello.hu> */
+		/* bt878 TV + FM 0x00000000 subsystem ID */
+		.name           = "APAC Viewcomp 878(AMAX)",
+		.video_inputs   = 2,
+		/* .audio_inputs= 1, */
+		.svhs           = NO_SVHS,
+		.gpiomask       = 0xFF,
+		.muxsel         = MUXSEL(2, 3, 1, 1),
+		.gpiomux        = { 2, 0, 0, 0 },
+		.gpiomute 	= 10,
+		.pll            = PLL_28,
+		.tuner_type     = TUNER_PHILIPS_PAL,
+		.tuner_addr	= ADDR_UNSET,
+		.has_remote     = 1,   /* miniremote works, see ir-kbd-gpio.c */
+		.has_radio      = 1,   /* not every card has radio */
+	},
+
+		/* ---- card 0x80 ---------------------------------- */
+	[BTTV_BOARD_DVICO_DVBT_LITE] = {
+		/* Chris Pascoe <c.pascoe@itee.uq.edu.au> */
+		.name           = "DViCO FusionHDTV DVB-T Lite",
+		.no_msp34xx     = 1,
+		.no_tda7432     = 1,
+		.pll            = PLL_28,
+		.no_video       = 1,
+		.has_dvb        = 1,
+		.tuner_type     = TUNER_ABSENT,
+		.tuner_addr	= ADDR_UNSET,
+	},
+	[BTTV_BOARD_VGEAR_MYVCD] = {
+		/* Steven <photon38@pchome.com.tw> */
+		.name           = "V-Gear MyVCD",
+		.video_inputs   = 3,
+		/* .audio_inputs= 1, */
+		.svhs           = 2,
+		.gpiomask       = 0x3f,
+		.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,
+		.has_radio      = 0,
+	},
+	[BTTV_BOARD_SUPER_TV] = {
+		/* Rick C <cryptdragoon@gmail.com> */
+		.name           = "Super TV Tuner",
+		.video_inputs   = 4,
+		/* .audio_inputs= 1, */
+		.svhs           = 2,
+		.muxsel         = MUXSEL(2, 3, 1, 0),
+		.tuner_type     = TUNER_PHILIPS_NTSC,
+		.tuner_addr	= ADDR_UNSET,
+		.gpiomask       = 0x008007,
+		.gpiomux        = { 0, 0x000001,0,0 },
+		.has_radio      = 1,
+	},
+	[BTTV_BOARD_TIBET_CS16] = {
+		/* Chris Fanning <video4linux@haydon.net> */
+		.name           = "Tibet Systems 'Progress DVR' CS16",
+		.video_inputs   = 16,
+		/* .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_tda7432	= 1,
+		.tuner_type     = TUNER_ABSENT,
+		.tuner_addr	= ADDR_UNSET,
+		.muxsel_hook    = tibetCS16_muxsel,
+	},
+	[BTTV_BOARD_KODICOM_4400R] = {
+		/* Bill Brack <wbrack@mmm.com.hk> */
+		/*
+		* Note that, because of the card's wiring, the "master"
+		* BT878A chip (i.e. the one which controls the analog switch
+		* and must use this card type) is the 2nd one detected.  The
+		* other 3 chips should use card type 0x85, whose description
+		* follows this one.  There is a EEPROM on the card (which is
+		* connected to the I2C of one of those other chips), but is
+		* not currently handled.  There is also a facility for a
+		* "monitor", which is also not currently implemented.
+		*/
+		.name           = "Kodicom 4400R (master)",
+		.video_inputs	= 16,
+		/* .audio_inputs= 0, */
+		.tuner_type	= TUNER_ABSENT,
+		.tuner_addr	= ADDR_UNSET,
+		.svhs		= NO_SVHS,
+		/* GPIO bits 0-9 used for analog switch:
+		*   00 - 03:	camera selector
+		*   04 - 06:	channel (controller) selector
+		*   07:	data (1->on, 0->off)
+		*   08:	strobe
+		*   09:	reset
+		* bit 16 is input from sync separator for the channel
+		*/
+		.gpiomask	= 0x0003ff,
+		.no_gpioirq     = 1,
+		.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,
+		.muxsel_hook	= kodicom4400r_muxsel,
+	},
+	[BTTV_BOARD_KODICOM_4400R_SL] = {
+		/* Bill Brack <wbrack@mmm.com.hk> */
+		/* Note that, for reasons unknown, the "master" BT878A chip (i.e. the
+		* one which controls the analog switch, and must use the card type)
+		* is the 2nd one detected.  The other 3 chips should use this card
+		* type
+		*/
+		.name		= "Kodicom 4400R (slave)",
+		.video_inputs	= 16,
+		/* .audio_inputs= 0, */
+		.tuner_type	= TUNER_ABSENT,
+		.tuner_addr	= ADDR_UNSET,
+		.svhs		= NO_SVHS,
+		.gpiomask	= 0x010000,
+		.no_gpioirq     = 1,
+		.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,
+		.muxsel_hook	= kodicom4400r_muxsel,
+	},
+		/* ---- card 0x86---------------------------------- */
+	[BTTV_BOARD_ADLINK_RTV24] = {
+		/* Michael Henson <mhenson@clarityvi.com> */
+		/* Adlink RTV24 with special unlock codes */
+		.name           = "Adlink RTV24",
+		.video_inputs   = 4,
+		/* .audio_inputs= 1, */
+		.svhs           = 2,
+		.muxsel         = MUXSEL(2, 3, 1, 0),
+		.tuner_type     = UNSET,
+		.tuner_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_type     = TUNER_LG_TDVS_H06XF, /* TDVS-H064F */
+		.tuner_addr	= ADDR_UNSET,
+		.video_inputs   = 3,
+		/* .audio_inputs= 1, */
+		.svhs           = 2,
+		.muxsel		= MUXSEL(2, 3, 1),
+		.gpiomask       = 0x00e00007,
+		.gpiomux        = { 0x00400005, 0, 0x00000001, 0 },
+		.gpiomute 	= 0x00c00007,
+		.no_msp34xx     = 1,
+		.no_tda7432     = 1,
+		.has_dvb        = 1,
+	},
+		/* ---- card 0x88---------------------------------- */
+	[BTTV_BOARD_ACORP_Y878F] = {
+		/* Mauro Carvalho Chehab <mchehab@infradead.org> */
+		.name		= "Acorp Y878F",
+		.video_inputs	= 3,
+		/* .audio_inputs= 1, */
+		.svhs		= 2,
+		.gpiomask	= 0x01fe00,
+		.muxsel		= MUXSEL(2, 3, 1, 1),
+		.gpiomux        = { 0x001e00, 0, 0x018000, 0x014000 },
+		.gpiomute 	= 0x002000,
+		.pll		= PLL_28,
+		.tuner_type	= TUNER_YMEC_TVF66T5_B_DFF,
+		.tuner_addr	= 0xc1 >>1,
+		.has_radio	= 1,
+	},
+		/* ---- card 0x89 ---------------------------------- */
+	[BTTV_BOARD_CONCEPTRONIC_CTVFMI2] = {
+		.name           = "Conceptronic CTVFMi v2",
+		.video_inputs   = 3,
+		/* .audio_inputs= 1, */
+		.svhs           = 2,
+		.gpiomask       = 0x001c0007,
+		.muxsel         = MUXSEL(2, 3, 1, 1),
+		.gpiomux        = { 0, 1, 2, 2 },
+		.gpiomute 	= 3,
+		.pll            = PLL_28,
+		.tuner_type     = TUNER_TENA_9533_DI,
+		.tuner_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, */
+		.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,
+		.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, */
+		.svhs           = 2,
+		.gpiomask       = 0x3f,
+		.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,
+		.has_radio      = 1,
+		.has_remote     = 1,
+	},
+		/* ---- card 0x8c ---------------------------------- */
+	/* Has four Bt878 chips behind a PCI bridge, each chip has:
+	     one external BNC composite input (mux 2)
+	     three internal composite inputs (unknown muxes)
+	     an 18-bit stereo A/D (CS5331A), which has:
+	       one external stereo unblanced (RCA) audio connection
+	       one (or 3?) internal stereo balanced (XLR) audio connection
+	       input is selected via gpio to a 14052B mux
+		 (mask=0x300, unbal=0x000, bal=0x100, ??=0x200,0x300)
+	       gain is controlled via an X9221A chip on the I2C bus @0x28
+	       sample rate is controlled via gpio to an MK1413S
+		 (mask=0x3, 32kHz=0x0, 44.1kHz=0x1, 48kHz=0x2, ??=0x3)
+	     There is neither a tuner nor an svideo input. */
+	[BTTV_BOARD_OSPREY440]  = {
+		.name           = "Osprey 440",
+		.video_inputs   = 4,
+		/* .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     = TUNER_ABSENT,
+		.tuner_addr     = ADDR_UNSET,
+		.no_msp34xx     = 1,
+		.no_tda7432     = 1,
+	},
+		/* ---- card 0x8d ---------------------------------- */
+	[BTTV_BOARD_ASOUND_SKYEYE] = {
+		.name		= "Asound Skyeye PCTV",
+		.video_inputs	= 3,
+		/* .audio_inputs= 1, */
+		.svhs		= 2,
+		.gpiomask	= 15,
+		.muxsel		= MUXSEL(2, 3, 1, 1),
+		.gpiomux 	= { 2, 0, 0, 0 },
+		.gpiomute 	= 1,
+		.pll		= PLL_28,
+		.tuner_type	= TUNER_PHILIPS_NTSC,
+		.tuner_addr	= ADDR_UNSET,
+	},
+		/* ---- card 0x8e ---------------------------------- */
+	[BTTV_BOARD_SABRENT_TVFM] = {
+		.name		= "Sabrent TV-FM (bttv version)",
+		.video_inputs	= 3,
+		/* .audio_inputs= 1, */
+		.svhs		= 2,
+		.gpiomask	= 0x108007,
+		.muxsel		= MUXSEL(2, 3, 1, 1),
+		.gpiomux 	= { 100000, 100002, 100002, 100000 },
+		.no_msp34xx	= 1,
+		.no_tda7432     = 1,
+		.pll		= PLL_28,
+		.tuner_type	= TUNER_TNF_5335MF,
+		.tuner_addr	= ADDR_UNSET,
+		.has_radio      = 1,
+	},
+	/* ---- card 0x8f ---------------------------------- */
+	[BTTV_BOARD_HAUPPAUGE_IMPACTVCB] = {
+		.name		= "Hauppauge ImpactVCB (bt878)",
+		.video_inputs	= 4,
+		/* .audio_inputs= 0, */
+		.svhs		= NO_SVHS,
+		.gpiomask	= 0x0f, /* old: 7 */
+		.muxsel		= MUXSEL(0, 1, 3, 2), /* Composite 0-3 */
+		.no_msp34xx	= 1,
+		.no_tda7432     = 1,
+		.tuner_type	= TUNER_ABSENT,
+		.tuner_addr	= ADDR_UNSET,
+	},
+	[BTTV_BOARD_MACHTV_MAGICTV] = {
+		/* Julian Calaby <julian.calaby@gmail.com>
+		 * Slightly different from original MachTV definition (0x60)
+
+		 * FIXME: RegSpy says gpiomask should be "0x001c800f", but it
+		 * stuffs up remote chip. Bug is a pin on the jaecs is not set
+		 * properly (methinks) causing no keyup bits being set */
+
+		.name           = "MagicTV", /* rebranded MachTV */
+		.video_inputs   = 3,
+		/* .audio_inputs= 1, */
+		.svhs           = 2,
+		.gpiomask       = 7,
+		.muxsel         = MUXSEL(2, 3, 1, 1),
+		.gpiomux        = { 0, 1, 2, 3 },
+		.gpiomute 	= 4,
+		.tuner_type     = TUNER_TEMIC_4009FR5_PAL,
+		.tuner_addr     = ADDR_UNSET,
+		.pll            = PLL_28,
+		.has_radio      = 1,
+		.has_remote     = 1,
+	},
+	[BTTV_BOARD_SSAI_SECURITY] = {
+		.name		= "SSAI Security Video Interface",
+		.video_inputs	= 4,
+		/* .audio_inputs= 0, */
+		.svhs		= NO_SVHS,
+		.muxsel		= MUXSEL(0, 1, 2, 3),
+		.tuner_type	= TUNER_ABSENT,
+		.tuner_addr	= ADDR_UNSET,
+	},
+	[BTTV_BOARD_SSAI_ULTRASOUND] = {
+		.name		= "SSAI Ultrasound Video Interface",
+		.video_inputs	= 2,
+		/* .audio_inputs= 0, */
+		.svhs		= 1,
+		.muxsel		= MUXSEL(2, 0, 1, 3),
+		.tuner_type	= TUNER_ABSENT,
+		.tuner_addr	= ADDR_UNSET,
+	},
+	/* ---- card 0x94---------------------------------- */
+	[BTTV_BOARD_DVICO_FUSIONHDTV_2] = {
+		.name           = "DViCO FusionHDTV 2",
+		.tuner_type     = TUNER_PHILIPS_FCV1236D,
+		.tuner_addr	= ADDR_UNSET,
+		.video_inputs   = 3,
+		/* .audio_inputs= 1, */
+		.svhs           = 2,
+		.muxsel		= MUXSEL(2, 3, 1),
+		.gpiomask       = 0x00e00007,
+		.gpiomux        = { 0x00400005, 0, 0x00000001, 0 },
+		.gpiomute 	= 0x00c00007,
+		.no_msp34xx     = 1,
+		.no_tda7432     = 1,
+	},
+	/* ---- card 0x95---------------------------------- */
+	[BTTV_BOARD_TYPHOON_TVTUNERPCI] = {
+		.name           = "Typhoon TV-Tuner PCI (50684)",
+		.video_inputs   = 3,
+		/* .audio_inputs= 1, */
+		.svhs           = 2,
+		.gpiomask       = 0x3014f,
+		.muxsel         = MUXSEL(2, 3, 1, 1),
+		.gpiomux        = { 0x20001,0x10001, 0, 0 },
+		.gpiomute       = 10,
+		.pll            = PLL_28,
+		.tuner_type     = TUNER_PHILIPS_PAL_I,
+		.tuner_addr     = ADDR_UNSET,
+	},
+	[BTTV_BOARD_GEOVISION_GV600] = {
+		/* emhn@usb.ve */
+		.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>
+		 * Based on MagicTV and Conceptronic CONTVFMi */
+
+		.name           = "Kozumi KTV-01C",
+		.video_inputs   = 3,
+		/* .audio_inputs= 1, */
+		.svhs           = 2,
+		.gpiomask       = 0x008007,
+		.muxsel         = MUXSEL(2, 3, 1, 1),
+		.gpiomux        = { 0, 1, 2, 2 }, /* CONTVFMi */
+		.gpiomute 	= 3, /* CONTVFMi */
+		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3, /* TCL MK3 */
+		.tuner_addr     = ADDR_UNSET,
+		.pll            = PLL_28,
+		.has_radio      = 1,
+		.has_remote     = 1,
+	},
+	[BTTV_BOARD_ENLTV_FM_2] = {
+		/* Encore TV Tuner Pro ENL TV-FM-2
+		   Mauro Carvalho Chehab <mchehab@infradead.org */
+		.name           = "Encore ENL TV-FM-2",
+		.video_inputs   = 3,
+		/* .audio_inputs= 1, */
+		.svhs           = 2,
+		/* bit 6          -> IR disabled
+		   bit 18/17 = 00 -> mute
+			       01 -> enable external audio input
+			       10 -> internal audio input (mono?)
+			       11 -> internal audio input
+		 */
+		.gpiomask       = 0x060040,
+		.muxsel         = MUXSEL(2, 3, 3),
+		.gpiomux        = { 0x60000, 0x60000, 0x20000, 0x20000 },
+		.gpiomute 	= 0,
+		.tuner_type	= TUNER_TCL_MF02GIP_5N,
+		.tuner_addr     = ADDR_UNSET,
+		.pll            = PLL_28,
+		.has_radio      = 1,
+		.has_remote     = 1,
+	},
+		[BTTV_BOARD_VD012] = {
+		/* D.Heer@Phytec.de */
+		.name           = "PHYTEC VD-012 (bt878)",
+		.video_inputs   = 4,
+		/* .audio_inputs= 0, */
+		.svhs           = NO_SVHS,
+		.gpiomask       = 0x00,
+		.muxsel         = MUXSEL(0, 2, 3, 1),
+		.gpiomux        = { 0, 0, 0, 0 }, /* card has no audio */
+		.pll            = PLL_28,
+		.tuner_type     = TUNER_ABSENT,
+		.tuner_addr	= ADDR_UNSET,
+	},
+		[BTTV_BOARD_VD012_X1] = {
+		/* D.Heer@Phytec.de */
+		.name           = "PHYTEC VD-012-X1 (bt878)",
+		.video_inputs   = 4,
+		/* .audio_inputs= 0, */
+		.svhs           = 3,
+		.gpiomask       = 0x00,
+		.muxsel         = MUXSEL(2, 3, 1),
+		.gpiomux        = { 0, 0, 0, 0 }, /* card has no audio */
+		.pll            = PLL_28,
+		.tuner_type     = TUNER_ABSENT,
+		.tuner_addr	= ADDR_UNSET,
+	},
+		[BTTV_BOARD_VD012_X2] = {
+		/* D.Heer@Phytec.de */
+		.name           = "PHYTEC VD-012-X2 (bt878)",
+		.video_inputs   = 4,
+		/* .audio_inputs= 0, */
+		.svhs           = 3,
+		.gpiomask       = 0x00,
+		.muxsel         = MUXSEL(3, 2, 1),
+		.gpiomux        = { 0, 0, 0, 0 }, /* card has no audio */
+		.pll            = PLL_28,
+		.tuner_type     = TUNER_ABSENT,
+		.tuner_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,
+		.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,
+		.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 },
+		.no_msp34xx     = 1,
+		.pll            = PLL_28,
+		.tuner_type     = TUNER_ABSENT,
+		.tuner_addr	= ADDR_UNSET,
+	},
+	[BTTV_BOARD_TVT_TD3116] = {
+		.name           = "Tongwei Video Technology TD-3116",
+		.video_inputs   = 16,
+		.gpiomask       = 0xc00ff,
+		.muxsel         = MUXSEL(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2),
+		.muxsel_hook    = td3116_muxsel,
+		.svhs           = NO_SVHS,
+		.pll		= PLL_28,
+		.tuner_type     = TUNER_ABSENT,
+	},
+	[BTTV_BOARD_APOSONIC_WDVR] = {
+		.name           = "Aposonic W-DVR",
+		.video_inputs   = 4,
+		.svhs           = NO_SVHS,
+		.muxsel         = MUXSEL(2, 3, 1, 0),
+		.tuner_type     = TUNER_ABSENT,
+	},
+
+};
+
+static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards);
+
+/* ----------------------------------------------------------------------- */
+
+static unsigned char eeprom_data[256];
+
+/*
+ * identify card
+ */
+void __devinit bttv_idcard(struct bttv *btv)
+{
+	unsigned int gpiobits;
+	int i,type;
+
+	/* read PCI subsystem ID */
+	btv->cardid  = btv->c.pci->subsystem_device << 16;
+	btv->cardid |= btv->c.pci->subsystem_vendor;
+
+	if (0 != btv->cardid && 0xffffffff != btv->cardid) {
+		/* look for the card */
+		for (type = -1, i = 0; cards[i].id != 0; i++)
+			if (cards[i].id  == btv->cardid)
+				type = i;
+
+		if (type != -1) {
+			/* found it */
+			pr_info("%d: detected: %s [card=%d], PCI subsystem ID is %04x:%04x\n",
+				btv->c.nr, cards[type].name, cards[type].cardnr,
+				btv->cardid & 0xffff,
+				(btv->cardid >> 16) & 0xffff);
+			btv->c.type = cards[type].cardnr;
+		} else {
+			/* 404 */
+			pr_info("%d: subsystem: %04x:%04x (UNKNOWN)\n",
+				btv->c.nr, btv->cardid & 0xffff,
+				(btv->cardid >> 16) & 0xffff);
+			pr_debug("please mail id, board name and the correct card= insmod option to linux-media@vger.kernel.org\n");
+		}
+	}
+
+	/* let the user override the autodetected type */
+	if (card[btv->c.nr] < bttv_num_tvcards)
+		btv->c.type=card[btv->c.nr];
+
+	/* print which card config we are using */
+	pr_info("%d: using: %s [card=%d,%s]\n",
+		btv->c.nr, bttv_tvcards[btv->c.type].name, btv->c.type,
+		card[btv->c.nr] < bttv_num_tvcards
+		? "insmod option" : "autodetected");
+
+	/* overwrite gpio stuff ?? */
+	if (UNSET == audioall && UNSET == audiomux[0])
+		return;
+
+	if (UNSET != audiomux[0]) {
+		gpiobits = 0;
+		for (i = 0; i < ARRAY_SIZE(bttv_tvcards->gpiomux); i++) {
+			bttv_tvcards[btv->c.type].gpiomux[i] = audiomux[i];
+			gpiobits |= audiomux[i];
+		}
+	} else {
+		gpiobits = audioall;
+		for (i = 0; i < ARRAY_SIZE(bttv_tvcards->gpiomux); i++) {
+			bttv_tvcards[btv->c.type].gpiomux[i] = audioall;
+		}
+	}
+	bttv_tvcards[btv->c.type].gpiomask = (UNSET != gpiomask) ? gpiomask : gpiobits;
+	pr_info("%d: gpio config override: mask=0x%x, mux=",
+		btv->c.nr, bttv_tvcards[btv->c.type].gpiomask);
+	for (i = 0; i < ARRAY_SIZE(bttv_tvcards->gpiomux); i++) {
+		pr_cont("%s0x%x",
+			i ? "," : "", bttv_tvcards[btv->c.type].gpiomux[i]);
+	}
+	pr_cont("\n");
+}
+
+/*
+ * (most) board specific initialisations goes here
+ */
+
+/* Some Modular Technology cards have an eeprom, but no subsystem ID */
+static void identify_by_eeprom(struct bttv *btv, unsigned char eeprom_data[256])
+{
+	int type = -1;
+
+	if (0 == strncmp(eeprom_data,"GET MM20xPCTV",13))
+		type = BTTV_BOARD_MODTEC_205;
+	else if (0 == strncmp(eeprom_data+20,"Picolo",7))
+		type = BTTV_BOARD_EURESYS_PICOLO;
+	else if (eeprom_data[0] == 0x84 && eeprom_data[2]== 0)
+		type = BTTV_BOARD_HAUPPAUGE; /* old bt848 */
+
+	if (-1 != type) {
+		btv->c.type = type;
+		pr_info("%d: detected by eeprom: %s [card=%d]\n",
+			btv->c.nr, bttv_tvcards[btv->c.type].name, btv->c.type);
+	}
+}
+
+static void flyvideo_gpio(struct bttv *btv)
+{
+	int gpio, has_remote, has_radio, is_capture_only;
+	int is_lr90, has_tda9820_tda9821;
+	int tuner_type = UNSET, ttype;
+
+	gpio_inout(0xffffff, 0);
+	udelay(8);  /* without this we would see the 0x1800 mask */
+	gpio = gpio_read();
+	/* FIXME: must restore OUR_EN ??? */
+
+	/* all cards provide GPIO info, some have an additional eeprom
+	 * LR50: GPIO coding can be found lower right CP1 .. CP9
+	 *       CP9=GPIO23 .. CP1=GPIO15; when OPEN, the corresponding GPIO reads 1.
+	 *       GPIO14-12: n.c.
+	 * LR90: GP9=GPIO23 .. GP1=GPIO15 (right above the bt878)
+
+	 * lowest 3 bytes are remote control codes (no handshake needed)
+	 * xxxFFF: No remote control chip soldered
+	 * xxxF00(LR26/LR50), xxxFE0(LR90): Remote control chip (LVA001 or CF45) soldered
+	 * Note: Some bits are Audio_Mask !
+	 */
+	ttype = (gpio & 0x0f0000) >> 16;
+	switch (ttype) {
+	case 0x0:
+		tuner_type = 2;  /* NTSC, e.g. TPI8NSR11P */
+		break;
+	case 0x2:
+		tuner_type = 39; /* LG NTSC (newer TAPC series) TAPC-H701P */
+		break;
+	case 0x4:
+		tuner_type = 5;  /* Philips PAL TPI8PSB02P, TPI8PSB12P, TPI8PSB12D or FI1216, FM1216 */
+		break;
+	case 0x6:
+		tuner_type = 37; /* LG PAL (newer TAPC series) TAPC-G702P */
+		break;
+	case 0xC:
+		tuner_type = 3;  /* Philips SECAM(+PAL) FQ1216ME or FI1216MF */
+		break;
+	default:
+		pr_info("%d: FlyVideo_gpio: unknown tuner type\n", btv->c.nr);
+		break;
+	}
+
+	has_remote          =   gpio & 0x800000;
+	has_radio	    =   gpio & 0x400000;
+	/*   unknown                   0x200000;
+	 *   unknown2                  0x100000; */
+	is_capture_only     = !(gpio & 0x008000); /* GPIO15 */
+	has_tda9820_tda9821 = !(gpio & 0x004000);
+	is_lr90             = !(gpio & 0x002000); /* else LR26/LR50 (LR38/LR51 f. capture only) */
+	/*
+	 * gpio & 0x001000    output bit for audio routing */
+
+	if (is_capture_only)
+		tuner_type = TUNER_ABSENT; /* No tuner present */
+
+	pr_info("%d: FlyVideo Radio=%s RemoteControl=%s Tuner=%d gpio=0x%06x\n",
+		btv->c.nr, has_radio ? "yes" : "no",
+		has_remote ? "yes" : "no", tuner_type, gpio);
+	pr_info("%d: FlyVideo  LR90=%s tda9821/tda9820=%s capture_only=%s\n",
+		btv->c.nr, is_lr90 ? "yes" : "no",
+		has_tda9820_tda9821 ? "yes" : "no",
+		is_capture_only ? "yes" : "no");
+
+	if (tuner_type != UNSET) /* only set if known tuner autodetected, else let insmod option through */
+		btv->tuner_type = tuner_type;
+	btv->has_radio = has_radio;
+
+	/* LR90 Audio Routing is done by 2 hef4052, so Audio_Mask has 4 bits: 0x001c80
+	 * LR26/LR50 only has 1 hef4052, Audio_Mask 0x000c00
+	 * Audio options: from tuner, from tda9821/tda9821(mono,stereo,sap), from tda9874, ext., mute */
+	if (has_tda9820_tda9821)
+		btv->audio_mode_gpio = lt9415_audio;
+	/* todo: if(has_tda9874) btv->audio_mode_gpio = fv2000s_audio; */
+}
+
+static int miro_tunermap[] = { 0,6,2,3,   4,5,6,0,  3,0,4,5,  5,2,16,1,
+			       14,2,17,1, 4,1,4,3,  1,2,16,1, 4,4,4,4 };
+static int miro_fmtuner[]  = { 0,0,0,0,   0,0,0,0,  0,0,0,0,  0,0,0,1,
+			       1,1,1,1,   1,1,1,0,  0,0,0,0,  0,1,0,0 };
+
+static void miro_pinnacle_gpio(struct bttv *btv)
+{
+	int id,msp,gpio;
+	char *info;
+
+	gpio_inout(0xffffff, 0);
+	gpio = gpio_read();
+	id   = ((gpio>>10) & 63) -1;
+	msp  = bttv_I2CRead(btv, I2C_ADDR_MSP3400, "MSP34xx");
+	if (id < 32) {
+		btv->tuner_type = miro_tunermap[id];
+		if (0 == (gpio & 0x20)) {
+			btv->has_radio = 1;
+			if (!miro_fmtuner[id]) {
+				btv->has_matchbox = 1;
+				btv->mbox_we    = (1<<6);
+				btv->mbox_most  = (1<<7);
+				btv->mbox_clk   = (1<<8);
+				btv->mbox_data  = (1<<9);
+				btv->mbox_mask  = (1<<6)|(1<<7)|(1<<8)|(1<<9);
+			}
+		} else {
+			btv->has_radio = 0;
+		}
+		if (-1 != msp) {
+			if (btv->c.type == BTTV_BOARD_MIRO)
+				btv->c.type = BTTV_BOARD_MIROPRO;
+			if (btv->c.type == BTTV_BOARD_PINNACLE)
+				btv->c.type = BTTV_BOARD_PINNACLEPRO;
+		}
+		pr_info("%d: miro: id=%d tuner=%d radio=%s stereo=%s\n",
+			btv->c.nr, id+1, btv->tuner_type,
+			!btv->has_radio ? "no" :
+			(btv->has_matchbox ? "matchbox" : "fmtuner"),
+			(-1 == msp) ? "no" : "yes");
+	} else {
+		/* new cards with microtune tuner */
+		id = 63 - id;
+		btv->has_radio = 0;
+		switch (id) {
+		case 1:
+			info = "PAL / mono";
+			btv->tda9887_conf = TDA9887_INTERCARRIER;
+			break;
+		case 2:
+			info = "PAL+SECAM / stereo";
+			btv->has_radio = 1;
+			btv->tda9887_conf = TDA9887_QSS;
+			break;
+		case 3:
+			info = "NTSC / stereo";
+			btv->has_radio = 1;
+			btv->tda9887_conf = TDA9887_QSS;
+			break;
+		case 4:
+			info = "PAL+SECAM / mono";
+			btv->tda9887_conf = TDA9887_QSS;
+			break;
+		case 5:
+			info = "NTSC / mono";
+			btv->tda9887_conf = TDA9887_INTERCARRIER;
+			break;
+		case 6:
+			info = "NTSC / stereo";
+			btv->tda9887_conf = TDA9887_INTERCARRIER;
+			break;
+		case 7:
+			info = "PAL / stereo";
+			btv->tda9887_conf = TDA9887_INTERCARRIER;
+			break;
+		default:
+			info = "oops: unknown card";
+			break;
+		}
+		if (-1 != msp)
+			btv->c.type = BTTV_BOARD_PINNACLEPRO;
+		pr_info("%d: pinnacle/mt: id=%d info=\"%s\" radio=%s\n",
+			btv->c.nr, id, info, btv->has_radio ? "yes" : "no");
+		btv->tuner_type = TUNER_MT2032;
+	}
+}
+
+/* GPIO21   L: Buffer aktiv, H: Buffer inaktiv */
+#define LM1882_SYNC_DRIVE     0x200000L
+
+static void init_ids_eagle(struct bttv *btv)
+{
+	gpio_inout(0xffffff,0xFFFF37);
+	gpio_write(0x200020);
+
+	/* flash strobe inverter ?! */
+	gpio_write(0x200024);
+
+	/* switch sync drive off */
+	gpio_bits(LM1882_SYNC_DRIVE,LM1882_SYNC_DRIVE);
+
+	/* set BT848 muxel to 2 */
+	btaor((2)<<5, ~(2<<5), BT848_IFORM);
+}
+
+/* Muxsel helper for the IDS Eagle.
+ * the eagles does not use the standard muxsel-bits but
+ * has its own multiplexer */
+static void eagle_muxsel(struct bttv *btv, unsigned int input)
+{
+	gpio_bits(3, input & 3);
+
+	/* composite */
+	/* set chroma ADC to sleep */
+	btor(BT848_ADC_C_SLEEP, BT848_ADC);
+	/* set to composite video */
+	btand(~BT848_CONTROL_COMP, BT848_E_CONTROL);
+	btand(~BT848_CONTROL_COMP, BT848_O_CONTROL);
+
+	/* switch sync drive off */
+	gpio_bits(LM1882_SYNC_DRIVE,LM1882_SYNC_DRIVE);
+}
+
+static void gvc1100_muxsel(struct bttv *btv, unsigned int input)
+{
+	static const int masks[] = {0x30, 0x01, 0x12, 0x23};
+	gpio_write(masks[input%4]);
+}
+
+/* LMLBT4x initialization - to allow access to GPIO bits for sensors input and
+   alarms output
+
+   GPIObit    | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+   assignment | TI | O3|INx| O2| O1|IN4|IN3|IN2|IN1|   |   |
+
+   IN - sensor inputs, INx - sensor inputs and TI XORed together
+   O1,O2,O3 - alarm outputs (relays)
+
+   OUT ENABLE   1    1   0  . 1  1   0   0 . 0   0   0    0   = 0x6C0
+
+*/
+
+static void init_lmlbt4x(struct bttv *btv)
+{
+	pr_debug("LMLBT4x init\n");
+	btwrite(0x000000, BT848_GPIO_REG_INP);
+	gpio_inout(0xffffff, 0x0006C0);
+	gpio_write(0x000000);
+}
+
+static void sigmaSQ_muxsel(struct bttv *btv, unsigned int input)
+{
+	unsigned int inmux = input % 8;
+	gpio_inout( 0xf, 0xf );
+	gpio_bits( 0xf, inmux );
+}
+
+static void sigmaSLC_muxsel(struct bttv *btv, unsigned int input)
+{
+	unsigned int inmux = input % 4;
+	gpio_inout( 3<<9, 3<<9 );
+	gpio_bits( 3<<9, inmux<<9 );
+}
+
+static void geovision_muxsel(struct bttv *btv, unsigned int input)
+{
+	unsigned int inmux = input % 16;
+	gpio_inout(0xf, 0xf);
+	gpio_bits(0xf, inmux);
+}
+
+/*
+ * The TD3116 has 2 74HC4051 muxes wired to the MUX0 input of a bt878.
+ * The first 74HC4051 has the lower 8 inputs, the second one the higher 8.
+ * The muxes are controlled via a 74HC373 latch which is connected to
+ * GPIOs 0-7. GPIO 18 is connected to the LE signal of the latch.
+ * Q0 of the latch is connected to the Enable (~E) input of the first
+ * 74HC4051. Q1 - Q3 are connected to S0 - S2 of the same 74HC4051.
+ * Q4 - Q7 are connected to the second 74HC4051 in the same way.
+ */
+
+static void td3116_latch_value(struct bttv *btv, u32 value)
+{
+	gpio_bits((1<<18) | 0xff, value);
+	gpio_bits((1<<18) | 0xff, (1<<18) | value);
+	udelay(1);
+	gpio_bits((1<<18) | 0xff, value);
+}
+
+static void td3116_muxsel(struct bttv *btv, unsigned int input)
+{
+	u32 value;
+	u32 highbit;
+
+	highbit = (input & 0x8) >> 3 ;
+
+	/* Disable outputs and set value in the mux */
+	value = 0x11; /* Disable outputs */
+	value |= ((input & 0x7) << 1)  << (4 * highbit);
+	td3116_latch_value(btv, value);
+
+	/* Enable the correct output */
+	value &= ~0x11;
+	value |= ((highbit ^ 0x1) << 4) | highbit;
+	td3116_latch_value(btv, value);
+}
+
+/* ----------------------------------------------------------------------- */
+
+static void bttv_reset_audio(struct bttv *btv)
+{
+	/*
+	 * BT878A has a audio-reset register.
+	 * 1. This register is an audio reset function but it is in
+	 *    function-0 (video capture) address space.
+	 * 2. It is enough to do this once per power-up of the card.
+	 * 3. There is a typo in the Conexant doc -- it is not at
+	 *    0x5B, but at 0x058. (B is an odd-number, obviously a typo!).
+	 * --//Shrikumar 030609
+	 */
+	if (btv->id != 878)
+		return;
+
+	if (bttv_debug)
+		pr_debug("%d: BT878A ARESET\n", btv->c.nr);
+	btwrite((1<<7), 0x058);
+	udelay(10);
+	btwrite(     0, 0x058);
+}
+
+/* initialization part one -- before registering i2c bus */
+void __devinit bttv_init_card1(struct bttv *btv)
+{
+	switch (btv->c.type) {
+	case BTTV_BOARD_HAUPPAUGE:
+	case BTTV_BOARD_HAUPPAUGE878:
+		boot_msp34xx(btv,5);
+		break;
+	case BTTV_BOARD_VOODOOTV_200:
+	case BTTV_BOARD_VOODOOTV_FM:
+		boot_msp34xx(btv,20);
+		break;
+	case BTTV_BOARD_AVERMEDIA98:
+		boot_msp34xx(btv,11);
+		break;
+	case BTTV_BOARD_HAUPPAUGEPVR:
+		pvr_boot(btv);
+		break;
+	case BTTV_BOARD_TWINHAN_DST:
+	case BTTV_BOARD_AVDVBT_771:
+	case BTTV_BOARD_PINNACLESAT:
+		btv->use_i2c_hw = 1;
+		break;
+	case BTTV_BOARD_ADLINK_RTV24:
+		init_RTV24( btv );
+		break;
+
+	}
+	if (!bttv_tvcards[btv->c.type].has_dvb)
+		bttv_reset_audio(btv);
+}
+
+/* initialization part two -- after registering i2c bus */
+void __devinit bttv_init_card2(struct bttv *btv)
+{
+	btv->tuner_type = UNSET;
+
+	if (BTTV_BOARD_UNKNOWN == btv->c.type) {
+		bttv_readee(btv,eeprom_data,0xa0);
+		identify_by_eeprom(btv,eeprom_data);
+	}
+
+	switch (btv->c.type) {
+	case BTTV_BOARD_MIRO:
+	case BTTV_BOARD_MIROPRO:
+	case BTTV_BOARD_PINNACLE:
+	case BTTV_BOARD_PINNACLEPRO:
+		/* miro/pinnacle */
+		miro_pinnacle_gpio(btv);
+		break;
+	case BTTV_BOARD_FLYVIDEO_98:
+	case BTTV_BOARD_MAXI:
+	case BTTV_BOARD_LIFE_FLYKIT:
+	case BTTV_BOARD_FLYVIDEO:
+	case BTTV_BOARD_TYPHOON_TVIEW:
+	case BTTV_BOARD_CHRONOS_VS2:
+	case BTTV_BOARD_FLYVIDEO_98FM:
+	case BTTV_BOARD_FLYVIDEO2000:
+	case BTTV_BOARD_FLYVIDEO98EZ:
+	case BTTV_BOARD_CONFERENCETV:
+	case BTTV_BOARD_LIFETEC_9415:
+		flyvideo_gpio(btv);
+		break;
+	case BTTV_BOARD_HAUPPAUGE:
+	case BTTV_BOARD_HAUPPAUGE878:
+	case BTTV_BOARD_HAUPPAUGEPVR:
+		/* pick up some config infos from the eeprom */
+		bttv_readee(btv,eeprom_data,0xa0);
+		hauppauge_eeprom(btv);
+		break;
+	case BTTV_BOARD_AVERMEDIA98:
+	case BTTV_BOARD_AVPHONE98:
+		bttv_readee(btv,eeprom_data,0xa0);
+		avermedia_eeprom(btv);
+		break;
+	case BTTV_BOARD_PXC200:
+		init_PXC200(btv);
+		break;
+	case BTTV_BOARD_PICOLO_TETRA_CHIP:
+		picolo_tetra_init(btv);
+		break;
+	case BTTV_BOARD_VHX:
+		btv->has_radio    = 1;
+		btv->has_matchbox = 1;
+		btv->mbox_we      = 0x20;
+		btv->mbox_most    = 0;
+		btv->mbox_clk     = 0x08;
+		btv->mbox_data    = 0x10;
+		btv->mbox_mask    = 0x38;
+		break;
+	case BTTV_BOARD_VOBIS_BOOSTAR:
+	case BTTV_BOARD_TERRATV:
+		terratec_active_radio_upgrade(btv);
+		break;
+	case BTTV_BOARD_MAGICTVIEW061:
+		if (btv->cardid == 0x3002144f) {
+			btv->has_radio=1;
+			pr_info("%d: radio detected by subsystem id (CPH05x)\n",
+				btv->c.nr);
+		}
+		break;
+	case BTTV_BOARD_STB2:
+		if (btv->cardid == 0x3060121a) {
+			/* Fix up entry for 3DFX VoodooTV 100,
+			   which is an OEM STB card variant. */
+			btv->has_radio=0;
+			btv->tuner_type=TUNER_TEMIC_NTSC;
+		}
+		break;
+	case BTTV_BOARD_OSPREY1x0:
+	case BTTV_BOARD_OSPREY1x0_848:
+	case BTTV_BOARD_OSPREY101_848:
+	case BTTV_BOARD_OSPREY1x1:
+	case BTTV_BOARD_OSPREY1x1_SVID:
+	case BTTV_BOARD_OSPREY2xx:
+	case BTTV_BOARD_OSPREY2x0_SVID:
+	case BTTV_BOARD_OSPREY2x0:
+	case BTTV_BOARD_OSPREY440:
+	case BTTV_BOARD_OSPREY500:
+	case BTTV_BOARD_OSPREY540:
+	case BTTV_BOARD_OSPREY2000:
+		bttv_readee(btv,eeprom_data,0xa0);
+		osprey_eeprom(btv, eeprom_data);
+		break;
+	case BTTV_BOARD_IDS_EAGLE:
+		init_ids_eagle(btv);
+		break;
+	case BTTV_BOARD_MODTEC_205:
+		bttv_readee(btv,eeprom_data,0xa0);
+		modtec_eeprom(btv);
+		break;
+	case BTTV_BOARD_LMLBT4:
+		init_lmlbt4x(btv);
+		break;
+	case BTTV_BOARD_TIBET_CS16:
+		tibetCS16_init(btv);
+		break;
+	case BTTV_BOARD_KODICOM_4400R:
+		kodicom4400r_init(btv);
+		break;
+	case BTTV_BOARD_GEOVISION_GV800S:
+		gv800s_init(btv);
+		break;
+	}
+
+	/* pll configuration */
+	if (!(btv->id==848 && btv->revision==0x11)) {
+		/* defaults from card list */
+		if (PLL_28 == bttv_tvcards[btv->c.type].pll) {
+			btv->pll.pll_ifreq=28636363;
+			btv->pll.pll_crystal=BT848_IFORM_XT0;
+		}
+		if (PLL_35 == bttv_tvcards[btv->c.type].pll) {
+			btv->pll.pll_ifreq=35468950;
+			btv->pll.pll_crystal=BT848_IFORM_XT1;
+		}
+		/* insmod options can override */
+		switch (pll[btv->c.nr]) {
+		case 0: /* none */
+			btv->pll.pll_crystal = 0;
+			btv->pll.pll_ifreq   = 0;
+			btv->pll.pll_ofreq   = 0;
+			break;
+		case 1: /* 28 MHz */
+		case 28:
+			btv->pll.pll_ifreq   = 28636363;
+			btv->pll.pll_ofreq   = 0;
+			btv->pll.pll_crystal = BT848_IFORM_XT0;
+			break;
+		case 2: /* 35 MHz */
+		case 35:
+			btv->pll.pll_ifreq   = 35468950;
+			btv->pll.pll_ofreq   = 0;
+			btv->pll.pll_crystal = BT848_IFORM_XT1;
+			break;
+		}
+	}
+	btv->pll.pll_current = -1;
+
+	/* tuner configuration (from card list / autodetect / insmod option) */
+	if (UNSET != bttv_tvcards[btv->c.type].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)
+		pr_info("%d: tuner absent\n", btv->c.nr);
+	else if (btv->tuner_type == UNSET)
+		pr_warn("%d: tuner type unset\n", btv->c.nr);
+	else
+		pr_info("%d: tuner type=%d\n", btv->c.nr, btv->tuner_type);
+
+	if (autoload != UNSET) {
+		pr_warn("%d: the autoload option is obsolete\n", btv->c.nr);
+		pr_warn("%d: use option msp3400, tda7432 or tvaudio to override which audio module should be used\n",
+			btv->c.nr);
+	}
+
+	if (UNSET == btv->tuner_type)
+		btv->tuner_type = TUNER_ABSENT;
+
+	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)
+		btv->has_remote = remote[btv->c.nr];
+
+	if (bttv_tvcards[btv->c.type].has_radio)
+		btv->has_radio = 1;
+	if (bttv_tvcards[btv->c.type].has_remote)
+		btv->has_remote = 1;
+	if (!bttv_tvcards[btv->c.type].no_gpioirq)
+		btv->gpioirq = 1;
+	if (bttv_tvcards[btv->c.type].volume_gpio)
+		btv->volume_gpio = bttv_tvcards[btv->c.type].volume_gpio;
+	if (bttv_tvcards[btv->c.type].audio_mode_gpio)
+		btv->audio_mode_gpio = bttv_tvcards[btv->c.type].audio_mode_gpio;
+
+	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_subdev(&btv->c.v4l2_dev,
+			&btv->c.i2c_adap, "saa6588", 0, addrs);
+		btv->has_saa6588 = (sd != NULL);
+	}
+
+	/* try to detect audio/fader chips */
+
+	/* First check if the user specified the audio chip via a module
+	   option. */
+
+	switch (audiodev[btv->c.nr]) {
+	case -1:
+		return;	/* do not load any audio module */
+
+	case 0: /* autodetect */
+		break;
+
+	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
+		};
+
+		btv->sd_msp34xx = v4l2_i2c_new_subdev(&btv->c.v4l2_dev,
+			&btv->c.i2c_adap, "msp3400", 0, 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_subdev(&btv->c.v4l2_dev,
+				&btv->c.i2c_adap, "tda7432", 0, addrs))
+			return;
+		goto no_audio;
+	}
+
+	case 3: {
+		/* The user specified that we should probe for tvaudio */
+		btv->sd_tvaudio = v4l2_i2c_new_subdev(&btv->c.v4l2_dev,
+			&btv->c.i2c_adap, "tvaudio", 0, tvaudio_addrs());
+		if (btv->sd_tvaudio)
+			return;
+		goto no_audio;
+	}
+
+	default:
+		pr_warn("%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) {
+		btv->sd_msp34xx = v4l2_i2c_new_subdev(&btv->c.v4l2_dev,
+			&btv->c.i2c_adap, "msp3400",
+			0, I2C_ADDRS(I2C_ADDR_MSP3400 >> 1));
+	} else if (bttv_tvcards[btv->c.type].msp34xx_alt) {
+		btv->sd_msp34xx = v4l2_i2c_new_subdev(&btv->c.v4l2_dev,
+			&btv->c.i2c_adap, "msp3400",
+			0, I2C_ADDRS(I2C_ADDR_MSP3400_ALT >> 1));
+	}
+
+	/* 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_subdev(&btv->c.v4l2_dev,
+				&btv->c.i2c_adap, "tda7432", 0, addrs))
+			return;
+	}
+
+	/* Now see if we can find one of the tvaudio devices. */
+	btv->sd_tvaudio = v4l2_i2c_new_subdev(&btv->c.v4l2_dev,
+		&btv->c.i2c_adap, "tvaudio", 0, tvaudio_addrs());
+	if (btv->sd_tvaudio)
+		return;
+
+no_audio:
+	pr_warn("%d: audio absent, no audio device found!\n", btv->c.nr);
+}
+
+
+/* initialize the tuner */
+void __devinit bttv_init_tuner(struct bttv *btv)
+{
+	int addr = ADDR_UNSET;
+
+	if (ADDR_UNSET != bttv_tvcards[btv->c.type].tuner_addr)
+		addr = bttv_tvcards[btv->c.type].tuner_addr;
+
+	if (btv->tuner_type != TUNER_ABSENT) {
+		struct tuner_setup tun_setup;
+
+		/* Load tuner module before issuing tuner config call! */
+		if (btv->has_radio)
+			v4l2_i2c_new_subdev(&btv->c.v4l2_dev,
+				&btv->c.i2c_adap, "tuner",
+				0, v4l2_i2c_tuner_addrs(ADDRS_RADIO));
+		v4l2_i2c_new_subdev(&btv->c.v4l2_dev,
+				&btv->c.i2c_adap, "tuner",
+				0, v4l2_i2c_tuner_addrs(ADDRS_DEMOD));
+		v4l2_i2c_new_subdev(&btv->c.v4l2_dev,
+				&btv->c.i2c_adap, "tuner",
+				0, v4l2_i2c_tuner_addrs(ADDRS_TV_WITH_DEMOD));
+
+		tun_setup.mode_mask = T_ANALOG_TV;
+		tun_setup.type = btv->tuner_type;
+		tun_setup.addr = addr;
+
+		if (btv->has_radio)
+			tun_setup.mode_mask |= T_RADIO;
+
+		bttv_call_all(btv, tuner, s_type_addr, &tun_setup);
+	}
+
+	if (btv->tda9887_conf) {
+		struct v4l2_priv_tun_config tda9887_cfg;
+
+		tda9887_cfg.tuner = TUNER_TDA9887;
+		tda9887_cfg.priv = &btv->tda9887_conf;
+
+		bttv_call_all(btv, tuner, s_config, &tda9887_cfg);
+	}
+}
+
+/* ----------------------------------------------------------------------- */
+
+static void modtec_eeprom(struct bttv *btv)
+{
+	if( strncmp(&(eeprom_data[0x1e]),"Temic 4066 FY5",14) ==0) {
+		btv->tuner_type=TUNER_TEMIC_4066FY5_PAL_I;
+		pr_info("%d: Modtec: Tuner autodetected by eeprom: %s\n",
+			btv->c.nr, &eeprom_data[0x1e]);
+	} else if (strncmp(&(eeprom_data[0x1e]),"Alps TSBB5",10) ==0) {
+		btv->tuner_type=TUNER_ALPS_TSBB5_PAL_I;
+		pr_info("%d: Modtec: Tuner autodetected by eeprom: %s\n",
+			btv->c.nr, &eeprom_data[0x1e]);
+	} else if (strncmp(&(eeprom_data[0x1e]),"Philips FM1246",14) ==0) {
+		btv->tuner_type=TUNER_PHILIPS_NTSC;
+		pr_info("%d: Modtec: Tuner autodetected by eeprom: %s\n",
+			btv->c.nr, &eeprom_data[0x1e]);
+	} else {
+		pr_info("%d: Modtec: Unknown TunerString: %s\n",
+			btv->c.nr, &eeprom_data[0x1e]);
+	}
+}
+
+static void __devinit hauppauge_eeprom(struct bttv *btv)
+{
+	struct tveeprom tv;
+
+	tveeprom_hauppauge_analog(&btv->i2c_client, &tv, eeprom_data);
+	btv->tuner_type = tv.tuner_type;
+	btv->has_radio  = tv.has_radio;
+
+	pr_info("%d: Hauppauge eeprom indicates model#%d\n",
+		btv->c.nr, tv.model);
+
+	/*
+	 * Some of the 878 boards have duplicate PCI IDs. Switch the board
+	 * type based on model #.
+	 */
+	if(tv.model == 64900) {
+		pr_info("%d: Switching board type from %s to %s\n",
+			btv->c.nr,
+			bttv_tvcards[btv->c.type].name,
+			bttv_tvcards[BTTV_BOARD_HAUPPAUGE_IMPACTVCB].name);
+		btv->c.type = BTTV_BOARD_HAUPPAUGE_IMPACTVCB;
+	}
+
+	/* The 61334 needs the msp3410 to do the radio demod to get sound */
+	if (tv.model == 61334)
+		btv->radio_uses_msp_demodulator = 1;
+}
+
+static int terratec_active_radio_upgrade(struct bttv *btv)
+{
+	int freq;
+
+	btv->has_radio    = 1;
+	btv->has_matchbox = 1;
+	btv->mbox_we      = 0x10;
+	btv->mbox_most    = 0x20;
+	btv->mbox_clk     = 0x08;
+	btv->mbox_data    = 0x04;
+	btv->mbox_mask    = 0x3c;
+
+	btv->mbox_iow     = 1 <<  8;
+	btv->mbox_ior     = 1 <<  9;
+	btv->mbox_csel    = 1 << 10;
+
+	freq=88000/62.5;
+	tea5757_write(btv, 5 * freq + 0x358); /* write 0x1ed8 */
+	if (0x1ed8 == tea5757_read(btv)) {
+		pr_info("%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;
+		btv->has_matchbox = 0;
+	}
+	return 0;
+}
+
+
+/* ----------------------------------------------------------------------- */
+
+/*
+ * minimal bootstrap for the WinTV/PVR -- upload altera firmware.
+ *
+ * The hcwamc.rbf firmware file is on the Hauppauge driver CD.  Have
+ * a look at Pvr/pvr45xxx.EXE (self-extracting zip archive, can be
+ * unpacked with unzip).
+ */
+#define PVR_GPIO_DELAY		10
+
+#define BTTV_ALT_DATA		0x000001
+#define BTTV_ALT_DCLK		0x100000
+#define BTTV_ALT_NCONFIG	0x800000
+
+static int __devinit pvr_altera_load(struct bttv *btv, const u8 *micro,
+				     u32 microlen)
+{
+	u32 n;
+	u8 bits;
+	int i;
+
+	gpio_inout(0xffffff,BTTV_ALT_DATA|BTTV_ALT_DCLK|BTTV_ALT_NCONFIG);
+	gpio_write(0);
+	udelay(PVR_GPIO_DELAY);
+
+	gpio_write(BTTV_ALT_NCONFIG);
+	udelay(PVR_GPIO_DELAY);
+
+	for (n = 0; n < microlen; n++) {
+		bits = micro[n];
+		for (i = 0 ; i < 8 ; i++) {
+			gpio_bits(BTTV_ALT_DCLK,0);
+			if (bits & 0x01)
+				gpio_bits(BTTV_ALT_DATA,BTTV_ALT_DATA);
+			else
+				gpio_bits(BTTV_ALT_DATA,0);
+			gpio_bits(BTTV_ALT_DCLK,BTTV_ALT_DCLK);
+			bits >>= 1;
+		}
+	}
+	gpio_bits(BTTV_ALT_DCLK,0);
+	udelay(PVR_GPIO_DELAY);
+
+	/* begin Altera init loop (Not necessary,but doesn't hurt) */
+	for (i = 0 ; i < 30 ; i++) {
+		gpio_bits(BTTV_ALT_DCLK,0);
+		gpio_bits(BTTV_ALT_DCLK,BTTV_ALT_DCLK);
+	}
+	gpio_bits(BTTV_ALT_DCLK,0);
+	return 0;
+}
+
+static int __devinit pvr_boot(struct bttv *btv)
+{
+	const struct firmware *fw_entry;
+	int rc;
+
+	rc = request_firmware(&fw_entry, "hcwamc.rbf", &btv->c.pci->dev);
+	if (rc != 0) {
+		pr_warn("%d: no altera firmware [via hotplug]\n", btv->c.nr);
+		return rc;
+	}
+	rc = pvr_altera_load(btv, fw_entry->data, fw_entry->size);
+	pr_info("%d: altera firmware upload %s\n",
+		btv->c.nr, (rc < 0) ? "failed" : "ok");
+	release_firmware(fw_entry);
+	return rc;
+}
+
+/* ----------------------------------------------------------------------- */
+/* some osprey specific stuff                                              */
+
+static void __devinit osprey_eeprom(struct bttv *btv, const u8 ee[256])
+{
+	int i;
+	u32 serial = 0;
+	int cardid = -1;
+
+	/* This code will nevery actually get called in this case.... */
+	if (btv->c.type == BTTV_BOARD_UNKNOWN) {
+		/* this might be an antique... check for MMAC label in eeprom */
+		if (!strncmp(ee, "MMAC", 4)) {
+			u8 checksum = 0;
+			for (i = 0; i < 21; i++)
+				checksum += ee[i];
+			if (checksum != ee[21])
+				return;
+			cardid = BTTV_BOARD_OSPREY1x0_848;
+			for (i = 12; i < 21; i++)
+				serial *= 10, serial += ee[i] - '0';
+		}
+	} else {
+		unsigned short type;
+
+		for (i = 4*16; i < 8*16; i += 16) {
+			u16 checksum = ip_compute_csum(ee + i, 16);
+
+			if ((checksum&0xff) + (checksum>>8) == 0xff)
+				break;
+		}
+		if (i >= 8*16)
+			return;
+		ee += i;
+
+		/* found a valid descriptor */
+		type = get_unaligned_be16((__be16 *)(ee+4));
+
+		switch(type) {
+		/* 848 based */
+		case 0x0004:
+			cardid = BTTV_BOARD_OSPREY1x0_848;
+			break;
+		case 0x0005:
+			cardid = BTTV_BOARD_OSPREY101_848;
+			break;
+
+		/* 878 based */
+		case 0x0012:
+		case 0x0013:
+			cardid = BTTV_BOARD_OSPREY1x0;
+			break;
+		case 0x0014:
+		case 0x0015:
+			cardid = BTTV_BOARD_OSPREY1x1;
+			break;
+		case 0x0016:
+		case 0x0017:
+		case 0x0020:
+			cardid = BTTV_BOARD_OSPREY1x1_SVID;
+			break;
+		case 0x0018:
+		case 0x0019:
+		case 0x001E:
+		case 0x001F:
+			cardid = BTTV_BOARD_OSPREY2xx;
+			break;
+		case 0x001A:
+		case 0x001B:
+			cardid = BTTV_BOARD_OSPREY2x0_SVID;
+			break;
+		case 0x0040:
+			cardid = BTTV_BOARD_OSPREY500;
+			break;
+		case 0x0050:
+		case 0x0056:
+			cardid = BTTV_BOARD_OSPREY540;
+			/* bttv_osprey_540_init(btv); */
+			break;
+		case 0x0060:
+		case 0x0070:
+		case 0x00A0:
+			cardid = BTTV_BOARD_OSPREY2x0;
+			/* enable output on select control lines */
+			gpio_inout(0xffffff,0x000303);
+			break;
+		case 0x00D8:
+			cardid = BTTV_BOARD_OSPREY440;
+			break;
+		default:
+			/* unknown...leave generic, but get serial # */
+			pr_info("%d: osprey eeprom: unknown card type 0x%04x\n",
+				btv->c.nr, type);
+			break;
+		}
+		serial = get_unaligned_be32((__be32 *)(ee+6));
+	}
+
+	pr_info("%d: osprey eeprom: card=%d '%s' serial=%u\n",
+		btv->c.nr, cardid,
+		cardid > 0 ? bttv_tvcards[cardid].name : "Unknown", serial);
+
+	if (cardid<0 || btv->c.type == cardid)
+		return;
+
+	/* card type isn't set correctly */
+	if (card[btv->c.nr] < bttv_num_tvcards) {
+		pr_warn("%d: osprey eeprom: Not overriding user specified card type\n",
+			btv->c.nr);
+	} else {
+		pr_info("%d: osprey eeprom: Changing card type from %d to %d\n",
+			btv->c.nr, btv->c.type, cardid);
+		btv->c.type = cardid;
+	}
+}
+
+/* ----------------------------------------------------------------------- */
+/* AVermedia specific stuff, from  bktr_card.c                             */
+
+static int tuner_0_table[] = {
+	TUNER_PHILIPS_NTSC,  TUNER_PHILIPS_PAL /* PAL-BG*/,
+	TUNER_PHILIPS_PAL,   TUNER_PHILIPS_PAL /* PAL-I*/,
+	TUNER_PHILIPS_PAL,   TUNER_PHILIPS_PAL,
+	TUNER_PHILIPS_SECAM, TUNER_PHILIPS_SECAM,
+	TUNER_PHILIPS_SECAM, TUNER_PHILIPS_PAL,
+	TUNER_PHILIPS_FM1216ME_MK3 };
+
+static int tuner_1_table[] = {
+	TUNER_TEMIC_NTSC,  TUNER_TEMIC_PAL,
+	TUNER_TEMIC_PAL,   TUNER_TEMIC_PAL,
+	TUNER_TEMIC_PAL,   TUNER_TEMIC_PAL,
+	TUNER_TEMIC_4012FY5, TUNER_TEMIC_4012FY5, /* TUNER_TEMIC_SECAM */
+	TUNER_TEMIC_4012FY5, TUNER_TEMIC_PAL};
+
+static void __devinit avermedia_eeprom(struct bttv *btv)
+{
+	int tuner_make, tuner_tv_fm, tuner_format, tuner_type = 0;
+
+	tuner_make      = (eeprom_data[0x41] & 0x7);
+	tuner_tv_fm     = (eeprom_data[0x41] & 0x18) >> 3;
+	tuner_format    = (eeprom_data[0x42] & 0xf0) >> 4;
+	btv->has_remote = (eeprom_data[0x42] & 0x01);
+
+	if (tuner_make == 0 || tuner_make == 2)
+		if (tuner_format <= 0x0a)
+			tuner_type = tuner_0_table[tuner_format];
+	if (tuner_make == 1)
+		if (tuner_format <= 9)
+			tuner_type = tuner_1_table[tuner_format];
+
+	if (tuner_make == 4)
+		if (tuner_format == 0x09)
+			tuner_type = TUNER_LG_NTSC_NEW_TAPC; /* TAPC-G702P */
+
+	pr_info("%d: Avermedia eeprom[0x%02x%02x]: tuner=",
+		btv->c.nr, eeprom_data[0x41], eeprom_data[0x42]);
+	if (tuner_type) {
+		btv->tuner_type = tuner_type;
+		pr_cont("%d", tuner_type);
+	} else
+		pr_cont("Unknown type");
+	pr_cont(" radio:%s remote control:%s\n",
+	       tuner_tv_fm     ? "yes" : "no",
+	       btv->has_remote ? "yes" : "no");
+}
+
+/*
+ * 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)
+{
+
+	if (btv->audio == TVAUDIO_INPUT_TUNER) {
+		if (bttv_tvnorms[btv->tvnorm].v4l2_id & V4L2_STD_MN)
+			gpiobits |= 0x10000;
+		else
+			gpiobits &= ~0x10000;
+	}
+
+	gpio_bits(bttv_tvcards[btv->c.type].gpiomask, gpiobits);
+	return gpiobits;
+}
+
+
+/*
+ * reset/enable the MSP on some Hauppauge cards
+ * Thanks to Kyösti Mälkki (kmalkki@cc.hut.fi)!
+ *
+ * Hauppauge:  pin  5
+ * Voodoo:     pin 20
+ */
+static void __devinit boot_msp34xx(struct bttv *btv, int pin)
+{
+	int mask = (1 << pin);
+
+	gpio_inout(mask,mask);
+	gpio_bits(mask,0);
+	mdelay(2);
+	udelay(500);
+	gpio_bits(mask,mask);
+
+	if (bttv_gpio)
+		bttv_gpio_tracking(btv,"msp34xx");
+	if (bttv_verbose)
+		pr_info("%d: Hauppauge/Voodoo msp34xx: reset line init [%d]\n",
+			btv->c.nr, pin);
+}
+
+/* ----------------------------------------------------------------------- */
+/*  Imagenation L-Model PXC200 Framegrabber */
+/*  This is basically the same procedure as
+ *  used by Alessandro Rubini in his pxc200
+ *  driver, but using BTTV functions */
+
+static void __devinit init_PXC200(struct bttv *btv)
+{
+	static int vals[] __devinitdata = { 0x08, 0x09, 0x0a, 0x0b, 0x0d, 0x0d,
+					    0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
+					    0x00 };
+	unsigned int i;
+	int tmp;
+	u32 val;
+
+	/* Initialise GPIO-connevted stuff */
+	gpio_inout(0xffffff, (1<<13));
+	gpio_write(0);
+	udelay(3);
+	gpio_write(1<<13);
+	/* GPIO inputs are pulled up, so no need to drive
+	 * reset pin any longer */
+	gpio_bits(0xffffff, 0);
+	if (bttv_gpio)
+		bttv_gpio_tracking(btv,"pxc200");
+
+	/*  we could/should try and reset/control the AD pots? but
+	    right now  we simply  turned off the crushing.  Without
+	    this the AGC drifts drifts
+	    remember the EN is reverse logic -->
+	    setting BT848_ADC_AGC_EN disable the AGC
+	    tboult@eecs.lehigh.edu
+	*/
+
+	btwrite(BT848_ADC_RESERVED|BT848_ADC_AGC_EN, BT848_ADC);
+
+	/*	Initialise MAX517 DAC */
+	pr_info("Setting DAC reference voltage level ...\n");
+	bttv_I2CWrite(btv,0x5E,0,0x80,1);
+
+	/*	Initialise 12C508 PIC */
+	/*	The I2CWrite and I2CRead commmands are actually to the
+	 *	same chips - but the R/W bit is included in the address
+	 *	argument so the numbers are different */
+
+
+	pr_info("Initialising 12C508 PIC chip ...\n");
+
+	/* First of all, enable the clock line. This is used in the PXC200-F */
+	val = btread(BT848_GPIO_DMA_CTL);
+	val |= BT848_GPIO_DMA_CTL_GPCLKMODE;
+	btwrite(val, BT848_GPIO_DMA_CTL);
+
+	/* Then, push to 0 the reset pin long enough to reset the *
+	 * device same as above for the reset line, but not the same
+	 * value sent to the GPIO-connected stuff
+	 * which one is the good one? */
+	gpio_inout(0xffffff,(1<<2));
+	gpio_write(0);
+	udelay(10);
+	gpio_write(1<<2);
+
+	for (i = 0; i < ARRAY_SIZE(vals); i++) {
+		tmp=bttv_I2CWrite(btv,0x1E,0,vals[i],1);
+		if (tmp != -1) {
+			pr_info("I2C Write(%2.2x) = %i\nI2C Read () = %2.2x\n\n",
+			       vals[i],tmp,bttv_I2CRead(btv,0x1F,NULL));
+		}
+	}
+
+	pr_info("PXC200 Initialised\n");
+}
+
+
+
+/* ----------------------------------------------------------------------- */
+/*
+ *  The Adlink RTV-24 (aka Angelo) has some special initialisation to unlock
+ *  it. This apparently involves the following procedure for each 878 chip:
+ *
+ *  1) write 0x00C3FEFF to the GPIO_OUT_EN register
+ *
+ *  2)  write to GPIO_DATA
+ *      - 0x0E
+ *      - sleep 1ms
+ *      - 0x10 + 0x0E
+ *      - sleep 10ms
+ *      - 0x0E
+ *     read from GPIO_DATA into buf (uint_32)
+ *      - if ( data>>18 & 0x01 != 0) || ( buf>>19 & 0x01 != 1 )
+ *                 error. ERROR_CPLD_Check_Failed stop.
+ *
+ *  3) write to GPIO_DATA
+ *      - write 0x4400 + 0x0E
+ *      - sleep 10ms
+ *      - write 0x4410 + 0x0E
+ *      - sleep 1ms
+ *      - write 0x0E
+ *     read from GPIO_DATA into buf (uint_32)
+ *      - if ( buf>>18 & 0x01 ) || ( buf>>19 & 0x01 != 0 )
+ *                error. ERROR_CPLD_Check_Failed.
+ */
+/* ----------------------------------------------------------------------- */
+static void
+init_RTV24 (struct bttv *btv)
+{
+	uint32_t dataRead = 0;
+	long watchdog_value = 0x0E;
+
+	pr_info("%d: Adlink RTV-24 initialisation in progress ...\n",
+		btv->c.nr);
+
+	btwrite (0x00c3feff, BT848_GPIO_OUT_EN);
+
+	btwrite (0 + watchdog_value, BT848_GPIO_DATA);
+	msleep (1);
+	btwrite (0x10 + watchdog_value, BT848_GPIO_DATA);
+	msleep (10);
+	btwrite (0 + watchdog_value, BT848_GPIO_DATA);
+
+	dataRead = btread (BT848_GPIO_DATA);
+
+	if ((((dataRead >> 18) & 0x01) != 0) || (((dataRead >> 19) & 0x01) != 1)) {
+		pr_info("%d: Adlink RTV-24 initialisation(1) ERROR_CPLD_Check_Failed (read %d)\n",
+			btv->c.nr, dataRead);
+	}
+
+	btwrite (0x4400 + watchdog_value, BT848_GPIO_DATA);
+	msleep (10);
+	btwrite (0x4410 + watchdog_value, BT848_GPIO_DATA);
+	msleep (1);
+	btwrite (watchdog_value, BT848_GPIO_DATA);
+	msleep (1);
+	dataRead = btread (BT848_GPIO_DATA);
+
+	if ((((dataRead >> 18) & 0x01) != 0) || (((dataRead >> 19) & 0x01) != 0)) {
+		pr_info("%d: Adlink RTV-24 initialisation(2) ERROR_CPLD_Check_Failed (read %d)\n",
+			btv->c.nr, dataRead);
+
+		return;
+	}
+
+	pr_info("%d: Adlink RTV-24 initialisation complete\n", btv->c.nr);
+}
+
+
+
+/* ----------------------------------------------------------------------- */
+/* Miro Pro radio stuff -- the tea5757 is connected to some GPIO ports     */
+/*
+ * Copyright (c) 1999 Csaba Halasz <qgehali@uni-miskolc.hu>
+ * This code is placed under the terms of the GNU General Public License
+ *
+ * Brutally hacked by Dan Sheridan <dan.sheridan@contact.org.uk> djs52 8/3/00
+ */
+
+static void bus_low(struct bttv *btv, int bit)
+{
+	if (btv->mbox_ior) {
+		gpio_bits(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel,
+			  btv->mbox_ior | btv->mbox_iow | btv->mbox_csel);
+		udelay(5);
+	}
+
+	gpio_bits(bit,0);
+	udelay(5);
+
+	if (btv->mbox_ior) {
+		gpio_bits(btv->mbox_iow | btv->mbox_csel, 0);
+		udelay(5);
+	}
+}
+
+static void bus_high(struct bttv *btv, int bit)
+{
+	if (btv->mbox_ior) {
+		gpio_bits(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel,
+			  btv->mbox_ior | btv->mbox_iow | btv->mbox_csel);
+		udelay(5);
+	}
+
+	gpio_bits(bit,bit);
+	udelay(5);
+
+	if (btv->mbox_ior) {
+		gpio_bits(btv->mbox_iow | btv->mbox_csel, 0);
+		udelay(5);
+	}
+}
+
+static int bus_in(struct bttv *btv, int bit)
+{
+	if (btv->mbox_ior) {
+		gpio_bits(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel,
+			  btv->mbox_ior | btv->mbox_iow | btv->mbox_csel);
+		udelay(5);
+
+		gpio_bits(btv->mbox_iow | btv->mbox_csel, 0);
+		udelay(5);
+	}
+	return gpio_read() & (bit);
+}
+
+/* TEA5757 register bits */
+#define TEA_FREQ		0:14
+#define TEA_BUFFER		15:15
+
+#define TEA_SIGNAL_STRENGTH	16:17
+
+#define TEA_PORT1		18:18
+#define TEA_PORT0		19:19
+
+#define TEA_BAND		20:21
+#define TEA_BAND_FM		0
+#define TEA_BAND_MW		1
+#define TEA_BAND_LW		2
+#define TEA_BAND_SW		3
+
+#define TEA_MONO		22:22
+#define TEA_ALLOW_STEREO	0
+#define TEA_FORCE_MONO		1
+
+#define TEA_SEARCH_DIRECTION	23:23
+#define TEA_SEARCH_DOWN		0
+#define TEA_SEARCH_UP		1
+
+#define TEA_STATUS		24:24
+#define TEA_STATUS_TUNED	0
+#define TEA_STATUS_SEARCHING	1
+
+/* Low-level stuff */
+static int tea5757_read(struct bttv *btv)
+{
+	unsigned long timeout;
+	int value = 0;
+	int i;
+
+	/* better safe than sorry */
+	gpio_inout(btv->mbox_mask, btv->mbox_clk | btv->mbox_we);
+
+	if (btv->mbox_ior) {
+		gpio_bits(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel,
+			  btv->mbox_ior | btv->mbox_iow | btv->mbox_csel);
+		udelay(5);
+	}
+
+	if (bttv_gpio)
+		bttv_gpio_tracking(btv,"tea5757 read");
+
+	bus_low(btv,btv->mbox_we);
+	bus_low(btv,btv->mbox_clk);
+
+	udelay(10);
+	timeout= jiffies + msecs_to_jiffies(1000);
+
+	/* wait for DATA line to go low; error if it doesn't */
+	while (bus_in(btv,btv->mbox_data) && time_before(jiffies, timeout))
+		schedule();
+	if (bus_in(btv,btv->mbox_data)) {
+		pr_warn("%d: tea5757: read timeout\n", btv->c.nr);
+		return -1;
+	}
+
+	dprintk("%d: tea5757:", btv->c.nr);
+	for (i = 0; i < 24; i++) {
+		udelay(5);
+		bus_high(btv,btv->mbox_clk);
+		udelay(5);
+		dprintk_cont("%c",
+			     bus_in(btv, btv->mbox_most) == 0 ? 'T' : '-');
+		bus_low(btv,btv->mbox_clk);
+		value <<= 1;
+		value |= (bus_in(btv,btv->mbox_data) == 0)?0:1;  /* MSB first */
+		dprintk_cont("%c",
+			     bus_in(btv, btv->mbox_most) == 0 ? 'S' : 'M');
+	}
+	dprintk_cont("\n");
+	dprintk("%d: tea5757: read 0x%X\n", btv->c.nr, value);
+	return value;
+}
+
+static int tea5757_write(struct bttv *btv, int value)
+{
+	int i;
+	int reg = value;
+
+	gpio_inout(btv->mbox_mask, btv->mbox_clk | btv->mbox_we | btv->mbox_data);
+
+	if (btv->mbox_ior) {
+		gpio_bits(btv->mbox_ior | btv->mbox_iow | btv->mbox_csel,
+			  btv->mbox_ior | btv->mbox_iow | btv->mbox_csel);
+		udelay(5);
+	}
+	if (bttv_gpio)
+		bttv_gpio_tracking(btv,"tea5757 write");
+
+	dprintk("%d: tea5757: write 0x%X\n", btv->c.nr, value);
+	bus_low(btv,btv->mbox_clk);
+	bus_high(btv,btv->mbox_we);
+	for (i = 0; i < 25; i++) {
+		if (reg & 0x1000000)
+			bus_high(btv,btv->mbox_data);
+		else
+			bus_low(btv,btv->mbox_data);
+		reg <<= 1;
+		bus_high(btv,btv->mbox_clk);
+		udelay(10);
+		bus_low(btv,btv->mbox_clk);
+		udelay(10);
+	}
+	bus_low(btv,btv->mbox_we);  /* unmute !!! */
+	return 0;
+}
+
+void tea5757_set_freq(struct bttv *btv, unsigned short freq)
+{
+	dprintk("tea5757_set_freq %d\n",freq);
+	tea5757_write(btv, 5 * freq + 0x358); /* add 10.7MHz (see docs) */
+}
+
+/* RemoteVision MX (rv605) muxsel helper [Miguel Freitas]
+ *
+ * This is needed because rv605 don't use a normal multiplex, but a crosspoint
+ * switch instead (CD22M3494E). This IC can have multiple active connections
+ * between Xn (input) and Yn (output) pins. We need to clear any existing
+ * connection prior to establish a new one, pulsing the STROBE pin.
+ *
+ * The board hardwire Y0 (xpoint) to MUX1 and MUXOUT to Yin.
+ * GPIO pins are wired as:
+ *  GPIO[0:3] - AX[0:3] (xpoint) - P1[0:3] (microcontroller)
+ *  GPIO[4:6] - AY[0:2] (xpoint) - P1[4:6] (microcontroller)
+ *  GPIO[7]   - DATA (xpoint)    - P1[7] (microcontroller)
+ *  GPIO[8]   -                  - P3[5] (microcontroller)
+ *  GPIO[9]   - RESET (xpoint)   - P3[6] (microcontroller)
+ *  GPIO[10]  - STROBE (xpoint)  - P3[7] (microcontroller)
+ *  GPINTR    -                  - P3[4] (microcontroller)
+ *
+ * The microcontroller is a 80C32 like. It should be possible to change xpoint
+ * configuration either directly (as we are doing) or using the microcontroller
+ * which is also wired to I2C interface. I have no further info on the
+ * microcontroller features, one would need to disassembly the firmware.
+ * note: the vendor refused to give any information on this product, all
+ *       that stuff was found using a multimeter! :)
+ */
+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);
+	gpio_bits(0x200,0x000);
+	mdelay(1);
+
+	/* create a new connection */
+	gpio_bits(0x480,0x480);
+	mdelay(1);
+	gpio_bits(0x480,0x080);
+	mdelay(1);
+}
+
+/* Tibet Systems 'Progress DVR' CS16 muxsel helper [Chris Fanning]
+ *
+ * The CS16 (available on eBay cheap) is a PCI board with four Fusion
+ * 878A chips, a PCI bridge, an Atmel microcontroller, four sync separator
+ * chips, ten eight input analog multiplexors, a not chip and a few
+ * other components.
+ *
+ * 16 inputs on a secondary bracket are provided and can be selected
+ * from each of the four capture chips.  Two of the eight input
+ * multiplexors are used to select from any of the 16 input signals.
+ *
+ * Unsupported hardware capabilities:
+ *  . A video output monitor on the secondary bracket can be selected from
+ *    one of the 878A chips.
+ *  . Another passthrough but I haven't spent any time investigating it.
+ *  . Digital I/O (logic level connected to GPIO) is available from an
+ *    onboard header.
+ *
+ * The on chip input mux should always be set to 2.
+ * GPIO[16:19] - Video input selection
+ * GPIO[0:3]   - Video output monitor select (only available from one 878A)
+ * GPIO[?:?]   - Digital I/O.
+ *
+ * There is an ATMEL microcontroller with an 8031 core on board.  I have not
+ * determined what function (if any) it provides.  With the microcontroller
+ * and sync separator chips a guess is that it might have to do with video
+ * switching and maybe some digital I/O.
+ */
+static void tibetCS16_muxsel(struct bttv *btv, unsigned int input)
+{
+	/* video mux */
+	gpio_bits(0x0f0000, input << 16);
+}
+
+static void tibetCS16_init(struct bttv *btv)
+{
+	/* enable gpio bits, mask obtained via btSpy */
+	gpio_inout(0xffffff, 0x0f7fff);
+	gpio_write(0x0f7fff);
+}
+
+/*
+ * The following routines for the Kodicom-4400r get a little mind-twisting.
+ * There is a "master" controller and three "slave" controllers, together
+ * an analog switch which connects any of 16 cameras to any of the BT87A's.
+ * The analog switch is controlled by the "master", but the detection order
+ * of the four BT878A chips is in an order which I just don't understand.
+ * The "master" is actually the second controller to be detected.  The
+ * logic on the board uses logical numbers for the 4 controllers, but
+ * those numbers are different from the detection sequence.  When working
+ * with the analog switch, we need to "map" from the detection sequence
+ * over to the board's logical controller number.  This mapping sequence
+ * is {3, 0, 2, 1}, i.e. the first controller to be detected is logical
+ * unit 3, the second (which is the master) is logical unit 0, etc.
+ * We need to maintain the status of the analog switch (which of the 16
+ * cameras is connected to which of the 4 controllers).  Rather than
+ * add to the bttv structure for this, we use the data reserved for
+ * the mbox (unused for this card type).
+ */
+
+/*
+ * First a routine to set the analog switch, which controls 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 7) of '1' enables the switch, and '0' disables
+ * the switch.  A STROBE bit (gpio bit 8) latches the data value into the
+ * specified address.  The idea is to set the address and data, then bring
+ * STROBE high, and finally bring STROBE back to low.
+ */
+static void kodicom4400r_write(struct bttv *btv,
+			       unsigned char xaddr,
+			       unsigned char yaddr,
+			       unsigned char data) {
+	unsigned int udata;
+
+	udata = (data << 7) | ((yaddr&3) << 4) | (xaddr&0xf);
+	gpio_bits(0x1ff, udata);		/* write ADDR and DAT */
+	gpio_bits(0x1ff, udata | (1 << 8));	/* strobe high */
+	gpio_bits(0x1ff, udata);		/* strobe low */
+}
+
+/*
+ * Next the mux select.  Both the "master" and "slave" 'cards' (controllers)
+ * use this routine.  The routine finds the "master" for the card, maps
+ * the controller number from the detected position over to the logical
+ * number, writes the appropriate data to the analog switch, and housekeeps
+ * the local copy of the switch information.  The parameter 'input' is the
+ * requested camera number (0 - 15).
+ */
+static void kodicom4400r_muxsel(struct bttv *btv, unsigned int input)
+{
+	char *sw_status;
+	int xaddr, yaddr;
+	struct bttv *mctlr;
+	static unsigned char map[4] = {3, 0, 2, 1};
+
+	mctlr = master[btv->c.nr];
+	if (mctlr == NULL) {	/* ignore if master not yet detected */
+		return;
+	}
+	yaddr = (btv->c.nr - mctlr->c.nr + 1) & 3; /* the '&' is for safety */
+	yaddr = map[yaddr];
+	sw_status = (char *)(&mctlr->mbox_we);
+	xaddr = input & 0xf;
+	/* Check if the controller/camera pair has changed, else ignore */
+	if (sw_status[yaddr] != xaddr)
+	{
+		/* "open" the old switch, "close" the new one, save the new */
+		kodicom4400r_write(mctlr, sw_status[yaddr], yaddr, 0);
+		sw_status[yaddr] = xaddr;
+		kodicom4400r_write(mctlr, xaddr, yaddr, 1);
+	}
+}
+
+/*
+ * During initialisation, we need to reset the analog switch.  We
+ * also preset the switch to map the 4 connectors on the card to the
+ * *user's* (see above description of kodicom4400r_muxsel) channels
+ * 0 through 3
+ */
+static void kodicom4400r_init(struct bttv *btv)
+{
+	char *sw_status = (char *)(&btv->mbox_we);
+	int ix;
+
+	gpio_inout(0x0003ff, 0x0003ff);
+	gpio_write(1 << 9);	/* reset MUX */
+	gpio_write(0);
+	/* Preset camera 0 to the 4 controllers */
+	for (ix = 0; ix < 4; ix++) {
+		sw_status[ix] = ix;
+		kodicom4400r_write(btv, ix, ix, 1);
+	}
+	/*
+	 * Since this is the "master", we need to set up the
+	 * other three controller chips' pointers to this structure
+	 * for later use in the muxsel routine.
+	 */
+	if ((btv->c.nr<1) || (btv->c.nr>BTTV_MAX-3))
+	    return;
+	master[btv->c.nr-1] = btv;
+	master[btv->c.nr]   = btv;
+	master[btv->c.nr+1] = btv;
+	master[btv->c.nr+2] = btv;
+}
+
+/* The Grandtec X-Guard framegrabber card uses two Dual 4-channel
+ * video multiplexers to provide up to 16 video inputs. These
+ * multiplexers are controlled by the lower 8 GPIO pins of the
+ * bt878. The multiplexers probably Pericom PI5V331Q or similar.
+
+ * xxx0 is pin xxx of multiplexer U5,
+ * yyy1 is pin yyy of multiplexer U2
+ */
+#define ENA0    0x01
+#define ENB0    0x02
+#define ENA1    0x04
+#define ENB1    0x08
+
+#define IN10    0x10
+#define IN00    0x20
+#define IN11    0x40
+#define IN01    0x80
+
+static void xguard_muxsel(struct bttv *btv, unsigned int input)
+{
+	static const int masks[] = {
+		ENB0, ENB0|IN00, ENB0|IN10, ENB0|IN00|IN10,
+		ENA0, ENA0|IN00, ENA0|IN10, ENA0|IN00|IN10,
+		ENB1, ENB1|IN01, ENB1|IN11, ENB1|IN01|IN11,
+		ENA1, ENA1|IN01, ENA1|IN11, ENA1|IN01|IN11,
+	};
+	gpio_write(masks[input%16]);
+}
+static void picolo_tetra_init(struct bttv *btv)
+{
+	/*This is the video input redirection fonctionality : I DID NOT USED IT. */
+	btwrite (0x08<<16,BT848_GPIO_DATA);/*GPIO[19] [==> 4053 B+C] set to 1 */
+	btwrite (0x04<<16,BT848_GPIO_DATA);/*GPIO[18] [==> 4053 A]  set to 1*/
+}
+static void picolo_tetra_muxsel (struct bttv* btv, unsigned int input)
+{
+
+	dprintk("%d : picolo_tetra_muxsel =>  input = %d\n", btv->c.nr, input);
+	/*Just set the right path in the analog multiplexers : channel 1 -> 4 ==> Analog Mux ==> MUX0*/
+	/*GPIO[20]&GPIO[21] used to choose the right input*/
+	btwrite (input<<20,BT848_GPIO_DATA);
+
+}
+
+/*
+ * ivc120_muxsel [Added by Alan Garfield <alan@fromorbit.com>]
+ *
+ * The IVC120G security card has 4 i2c controlled TDA8540 matrix
+ * swichers to provide 16 channels to MUX0. The TDA8540's have
+ * 4 independent outputs and as such the IVC120G also has the
+ * optional "Monitor Out" bus. This allows the card to be looking
+ * at one input while the monitor is looking at another.
+ *
+ * Since I've couldn't be bothered figuring out how to add an
+ * independent muxsel for the monitor bus, I've just set it to
+ * whatever the card is looking at.
+ *
+ *  OUT0 of the TDA8540's is connected to MUX0         (0x03)
+ *  OUT1 of the TDA8540's is connected to "Monitor Out"        (0x0C)
+ *
+ *  TDA8540_ALT3 IN0-3 = Channel 13 - 16       (0x03)
+ *  TDA8540_ALT4 IN0-3 = Channel 1 - 4         (0x03)
+ *  TDA8540_ALT5 IN0-3 = Channel 5 - 8         (0x03)
+ *  TDA8540_ALT6 IN0-3 = Channel 9 - 12                (0x03)
+ *
+ */
+
+/* All 7 possible sub-ids for the TDA8540 Matrix Switcher */
+#define I2C_TDA8540        0x90
+#define I2C_TDA8540_ALT1   0x92
+#define I2C_TDA8540_ALT2   0x94
+#define I2C_TDA8540_ALT3   0x96
+#define I2C_TDA8540_ALT4   0x98
+#define I2C_TDA8540_ALT5   0x9a
+#define I2C_TDA8540_ALT6   0x9c
+
+static void ivc120_muxsel(struct bttv *btv, unsigned int input)
+{
+	/* Simple maths */
+	int key = input % 4;
+	int matrix = input / 4;
+
+	dprintk("%d: ivc120_muxsel: Input - %02d | TDA - %02d | In - %02d\n",
+		btv->c.nr, input, matrix, key);
+
+	/* Handles the input selection on the TDA8540's */
+	bttv_I2CWrite(btv, I2C_TDA8540_ALT3, 0x00,
+		      ((matrix == 3) ? (key | key << 2) : 0x00), 1);
+	bttv_I2CWrite(btv, I2C_TDA8540_ALT4, 0x00,
+		      ((matrix == 0) ? (key | key << 2) : 0x00), 1);
+	bttv_I2CWrite(btv, I2C_TDA8540_ALT5, 0x00,
+		      ((matrix == 1) ? (key | key << 2) : 0x00), 1);
+	bttv_I2CWrite(btv, I2C_TDA8540_ALT6, 0x00,
+		      ((matrix == 2) ? (key | key << 2) : 0x00), 1);
+
+	/* Handles the output enables on the TDA8540's */
+	bttv_I2CWrite(btv, I2C_TDA8540_ALT3, 0x02,
+		      ((matrix == 3) ? 0x03 : 0x00), 1);  /* 13 - 16 */
+	bttv_I2CWrite(btv, I2C_TDA8540_ALT4, 0x02,
+		      ((matrix == 0) ? 0x03 : 0x00), 1);  /* 1-4 */
+	bttv_I2CWrite(btv, I2C_TDA8540_ALT5, 0x02,
+		      ((matrix == 1) ? 0x03 : 0x00), 1);  /* 5-8 */
+	bttv_I2CWrite(btv, I2C_TDA8540_ALT6, 0x02,
+		      ((matrix == 2) ? 0x03 : 0x00), 1);  /* 9-12 */
+
+	/* 878's MUX0 is already selected for input via muxsel values */
+}
+
+
+/* PXC200 muxsel helper
+ * luke@syseng.anu.edu.au
+ * another transplant
+ * from Alessandro Rubini (rubini@linux.it)
+ *
+ * There are 4 kinds of cards:
+ * PXC200L which is bt848
+ * PXC200F which is bt848 with PIC controlling mux
+ * PXC200AL which is bt878
+ * PXC200AF which is bt878 with PIC controlling mux
+ */
+#define PX_CFG_PXC200F 0x01
+#define PX_FLAG_PXC200A  0x00001000 /* a pxc200A is bt-878 based */
+#define PX_I2C_PIC       0x0f
+#define PX_PXC200A_CARDID 0x200a1295
+#define PX_I2C_CMD_CFG   0x00
+
+static void PXC200_muxsel(struct bttv *btv, unsigned int input)
+{
+	int rc;
+	long mux;
+	int bitmask;
+	unsigned char buf[2];
+
+	/* Read PIC config to determine if this is a PXC200F */
+	/* PX_I2C_CMD_CFG*/
+	buf[0]=0;
+	buf[1]=0;
+	rc=bttv_I2CWrite(btv,(PX_I2C_PIC<<1),buf[0],buf[1],1);
+	if (rc) {
+		pr_debug("%d: PXC200_muxsel: pic cfg write failed:%d\n",
+			 btv->c.nr, rc);
+	  /* not PXC ? do nothing */
+		return;
+	}
+
+	rc=bttv_I2CRead(btv,(PX_I2C_PIC<<1),NULL);
+	if (!(rc & PX_CFG_PXC200F)) {
+		pr_debug("%d: PXC200_muxsel: not PXC200F rc:%d\n",
+			 btv->c.nr, rc);
+		return;
+	}
+
+
+	/* The multiplexer in the 200F is handled by the GPIO port */
+	/* get correct mapping between inputs  */
+	/*  mux = bttv_tvcards[btv->type].muxsel[input] & 3; */
+	/* ** not needed!?   */
+	mux = input;
+
+	/* make sure output pins are enabled */
+	/* bitmask=0x30f; */
+	bitmask=0x302;
+	/* check whether we have a PXC200A */
+	if (btv->cardid == PX_PXC200A_CARDID)  {
+	   bitmask ^= 0x180; /* use 7 and 9, not 8 and 9 */
+	   bitmask |= 7<<4; /* the DAC */
+	}
+	btwrite(bitmask, BT848_GPIO_OUT_EN);
+
+	bitmask = btread(BT848_GPIO_DATA);
+	if (btv->cardid == PX_PXC200A_CARDID)
+	  bitmask = (bitmask & ~0x280) | ((mux & 2) << 8) | ((mux & 1) << 7);
+	else /* older device */
+	  bitmask = (bitmask & ~0x300) | ((mux & 3) << 8);
+	btwrite(bitmask,BT848_GPIO_DATA);
+
+	/*
+	 * Was "to be safe, set the bt848 to input 0"
+	 * Actually, since it's ok at load time, better not messing
+	 * with these bits (on PXC200AF you need to set mux 2 here)
+	 *
+	 * needed because bttv-driver sets mux before calling this function
+	 */
+	if (btv->cardid == PX_PXC200A_CARDID)
+	  btaor(2<<5, ~BT848_IFORM_MUXSEL, BT848_IFORM);
+	else /* older device */
+	  btand(~BT848_IFORM_MUXSEL,BT848_IFORM);
+
+	pr_debug("%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                                      */
+
+void __init bttv_check_chipset(void)
+{
+	int pcipci_fail = 0;
+	struct pci_dev *dev = NULL;
+
+	if (pci_pci_problems & (PCIPCI_FAIL|PCIAGP_FAIL)) 	/* should check if target is AGP */
+		pcipci_fail = 1;
+	if (pci_pci_problems & (PCIPCI_TRITON|PCIPCI_NATOMA|PCIPCI_VIAETBF))
+		triton1 = 1;
+	if (pci_pci_problems & PCIPCI_VSFX)
+		vsfx = 1;
+#ifdef PCIPCI_ALIMAGIK
+	if (pci_pci_problems & PCIPCI_ALIMAGIK)
+		latency = 0x0A;
+#endif
+
+
+	/* print warnings about any quirks found */
+	if (triton1)
+		pr_info("Host bridge needs ETBF enabled\n");
+	if (vsfx)
+		pr_info("Host bridge needs VSFX enabled\n");
+	if (pcipci_fail) {
+		pr_info("bttv and your chipset may not work together\n");
+		if (!no_overlay) {
+			pr_info("overlay will be disabled\n");
+			no_overlay = 1;
+		} else {
+			pr_info("overlay forced. Use this option at your own risk.\n");
+		}
+	}
+	if (UNSET != latency)
+		pr_info("pci latency fixup [%d]\n", latency);
+	while ((dev = pci_get_device(PCI_VENDOR_ID_INTEL,
+				      PCI_DEVICE_ID_INTEL_82441, dev))) {
+		unsigned char b;
+		pci_read_config_byte(dev, 0x53, &b);
+		if (bttv_debug)
+			pr_info("Host bridge: 82441FX Natoma, bufcon=0x%02x\n",
+				b);
+	}
+}
+
+int __devinit bttv_handle_chipset(struct bttv *btv)
+{
+	unsigned char command;
+
+	if (!triton1 && !vsfx && UNSET == latency)
+		return 0;
+
+	if (bttv_verbose) {
+		if (triton1)
+			pr_info("%d: enabling ETBF (430FX/VP3 compatibility)\n",
+				btv->c.nr);
+		if (vsfx && btv->id >= 878)
+			pr_info("%d: enabling VSFX\n", btv->c.nr);
+		if (UNSET != latency)
+			pr_info("%d: setting pci timer to %d\n",
+				btv->c.nr, latency);
+	}
+
+	if (btv->id < 878) {
+		/* bt848 (mis)uses a bit in the irq mask for etbf */
+		if (triton1)
+			btv->triton1 = BT848_INT_ETBF;
+	} else {
+		/* bt878 has a bit in the pci config space for it */
+		pci_read_config_byte(btv->c.pci, BT878_DEVCTRL, &command);
+		if (triton1)
+			command |= BT878_EN_TBFX;
+		if (vsfx)
+			command |= BT878_EN_VSFX;
+		pci_write_config_byte(btv->c.pci, BT878_DEVCTRL, command);
+	}
+	if (UNSET != latency)
+		pci_write_config_byte(btv->c.pci, PCI_LATENCY_TIMER, latency);
+	return 0;
+}
+
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c
new file mode 100644
index 0000000..2ce7179
--- /dev/null
+++ b/drivers/media/pci/bt8xx/bttv-driver.c
@@ -0,0 +1,4630 @@
+/*
+
+    bttv - Bt848 frame grabber driver
+
+    Copyright (C) 1996,97,98 Ralph  Metzler <rjkm@thp.uni-koeln.de>
+			   & Marcus Metzler <mocm@thp.uni-koeln.de>
+    (c) 1999-2002 Gerd Knorr <kraxel@bytesex.org>
+
+    some v4l2 code lines are taken from Justin's bttv2 driver which is
+    (c) 2000 Justin Schoeman <justin@suntiger.ee.up.ac.za>
+
+    V4L1 removal from:
+    (c) 2005-2006 Nickolay V. Shmyrev <nshmyrev@yandex.ru>
+
+    Fixes to be fully V4L2 compliant by
+    (c) 2006 Mauro Carvalho Chehab <mchehab@infradead.org>
+
+    Cropping and overscan support
+    Copyright (C) 2005, 2006 Michael H. Schimek <mschimek@gmx.at>
+    Sponsored by OPQ Systems AB
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/kdev_t.h>
+#include "bttvp.h"
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include <media/tvaudio.h>
+#include <media/msp3400.h>
+
+#include <linux/dma-mapping.h>
+
+#include <asm/io.h>
+#include <asm/byteorder.h>
+
+#include <media/saa6588.h>
+
+#define BTTV_VERSION "0.9.19"
+
+unsigned int bttv_num;			/* number of Bt848s in use */
+struct bttv *bttvs[BTTV_MAX];
+
+unsigned int bttv_debug;
+unsigned int bttv_verbose = 1;
+unsigned int bttv_gpio;
+
+/* config variables */
+#ifdef __BIG_ENDIAN
+static unsigned int bigendian=1;
+#else
+static unsigned int bigendian;
+#endif
+static unsigned int radio[BTTV_MAX];
+static unsigned int irq_debug;
+static unsigned int gbuffers = 8;
+static unsigned int gbufsize = 0x208000;
+static unsigned int reset_crop = 1;
+
+static int video_nr[BTTV_MAX] = { [0 ... (BTTV_MAX-1)] = -1 };
+static int radio_nr[BTTV_MAX] = { [0 ... (BTTV_MAX-1)] = -1 };
+static int vbi_nr[BTTV_MAX] = { [0 ... (BTTV_MAX-1)] = -1 };
+static int debug_latency;
+static int disable_ir;
+
+static unsigned int fdsr;
+
+/* options */
+static unsigned int combfilter;
+static unsigned int lumafilter;
+static unsigned int automute    = 1;
+static unsigned int chroma_agc;
+static unsigned int adc_crush   = 1;
+static unsigned int whitecrush_upper = 0xCF;
+static unsigned int whitecrush_lower = 0x7F;
+static unsigned int vcr_hack;
+static unsigned int irq_iswitch;
+static unsigned int uv_ratio    = 50;
+static unsigned int full_luma_range;
+static unsigned int coring;
+
+/* API features (turn on/off stuff for testing) */
+static unsigned int v4l2        = 1;
+
+/* insmod args */
+module_param(bttv_verbose,      int, 0644);
+module_param(bttv_gpio,         int, 0644);
+module_param(bttv_debug,        int, 0644);
+module_param(irq_debug,         int, 0644);
+module_param(debug_latency,     int, 0644);
+module_param(disable_ir,        int, 0444);
+
+module_param(fdsr,              int, 0444);
+module_param(gbuffers,          int, 0444);
+module_param(gbufsize,          int, 0444);
+module_param(reset_crop,        int, 0444);
+
+module_param(v4l2,              int, 0644);
+module_param(bigendian,         int, 0644);
+module_param(irq_iswitch,       int, 0644);
+module_param(combfilter,        int, 0444);
+module_param(lumafilter,        int, 0444);
+module_param(automute,          int, 0444);
+module_param(chroma_agc,        int, 0444);
+module_param(adc_crush,         int, 0444);
+module_param(whitecrush_upper,  int, 0444);
+module_param(whitecrush_lower,  int, 0444);
+module_param(vcr_hack,          int, 0444);
+module_param(uv_ratio,          int, 0444);
+module_param(full_luma_range,   int, 0444);
+module_param(coring,            int, 0444);
+
+module_param_array(radio,       int, NULL, 0444);
+module_param_array(video_nr,    int, NULL, 0444);
+module_param_array(radio_nr,    int, NULL, 0444);
+module_param_array(vbi_nr,      int, NULL, 0444);
+
+MODULE_PARM_DESC(radio,"The TV card supports radio, default is 0 (no)");
+MODULE_PARM_DESC(bigendian,"byte order of the framebuffer, default is native endian");
+MODULE_PARM_DESC(bttv_verbose,"verbose startup messages, default is 1 (yes)");
+MODULE_PARM_DESC(bttv_gpio,"log gpio changes, default is 0 (no)");
+MODULE_PARM_DESC(bttv_debug,"debug messages, default is 0 (no)");
+MODULE_PARM_DESC(irq_debug,"irq handler debug messages, default is 0 (no)");
+MODULE_PARM_DESC(disable_ir, "disable infrared remote support");
+MODULE_PARM_DESC(gbuffers,"number of capture buffers. range 2-32, default 8");
+MODULE_PARM_DESC(gbufsize,"size of the capture buffers, default is 0x208000");
+MODULE_PARM_DESC(reset_crop,"reset cropping parameters at open(), default "
+		 "is 1 (yes) for compatibility with older applications");
+MODULE_PARM_DESC(automute,"mute audio on bad/missing video signal, default is 1 (yes)");
+MODULE_PARM_DESC(chroma_agc,"enables the AGC of chroma signal, default is 0 (no)");
+MODULE_PARM_DESC(adc_crush,"enables the luminance ADC crush, default is 1 (yes)");
+MODULE_PARM_DESC(whitecrush_upper,"sets the white crush upper value, default is 207");
+MODULE_PARM_DESC(whitecrush_lower,"sets the white crush lower value, default is 127");
+MODULE_PARM_DESC(vcr_hack,"enables the VCR hack (improves synch on poor VCR tapes), default is 0 (no)");
+MODULE_PARM_DESC(irq_iswitch,"switch inputs in irq handler");
+MODULE_PARM_DESC(uv_ratio,"ratio between u and v gains, default is 50");
+MODULE_PARM_DESC(full_luma_range,"use the full luma range, default is 0 (no)");
+MODULE_PARM_DESC(coring,"set the luma coring level, default is 0 (no)");
+MODULE_PARM_DESC(video_nr, "video device numbers");
+MODULE_PARM_DESC(vbi_nr, "vbi device numbers");
+MODULE_PARM_DESC(radio_nr, "radio device numbers");
+
+MODULE_DESCRIPTION("bttv - v4l/v4l2 driver module for bt848/878 based cards");
+MODULE_AUTHOR("Ralph Metzler & Marcus Metzler & Gerd Knorr");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(BTTV_VERSION);
+
+/* ----------------------------------------------------------------------- */
+/* sysfs                                                                   */
+
+static ssize_t show_card(struct device *cd,
+			 struct device_attribute *attr, char *buf)
+{
+	struct video_device *vfd = container_of(cd, struct video_device, dev);
+	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);
+
+/* ----------------------------------------------------------------------- */
+/* dvb auto-load setup                                                     */
+#if defined(CONFIG_MODULES) && defined(MODULE)
+static void request_module_async(struct work_struct *work)
+{
+	request_module("dvb-bt8xx");
+}
+
+static void request_modules(struct bttv *dev)
+{
+	INIT_WORK(&dev->request_module_wk, request_module_async);
+	schedule_work(&dev->request_module_wk);
+}
+
+static void flush_request_modules(struct bttv *dev)
+{
+	flush_work(&dev->request_module_wk);
+}
+#else
+#define request_modules(dev)
+#define flush_request_modules(dev)
+#endif /* CONFIG_MODULES */
+
+
+/* ----------------------------------------------------------------------- */
+/* static data                                                             */
+
+/* special timing tables from conexant... */
+static u8 SRAM_Table[][60] =
+{
+	/* PAL digital input over GPIO[7:0] */
+	{
+		45, // 45 bytes following
+		0x36,0x11,0x01,0x00,0x90,0x02,0x05,0x10,0x04,0x16,
+		0x12,0x05,0x11,0x00,0x04,0x12,0xC0,0x00,0x31,0x00,
+		0x06,0x51,0x08,0x03,0x89,0x08,0x07,0xC0,0x44,0x00,
+		0x81,0x01,0x01,0xA9,0x0D,0x02,0x02,0x50,0x03,0x37,
+		0x37,0x00,0xAF,0x21,0x00
+	},
+	/* NTSC digital input over GPIO[7:0] */
+	{
+		51, // 51 bytes following
+		0x0C,0xC0,0x00,0x00,0x90,0x02,0x03,0x10,0x03,0x06,
+		0x10,0x04,0x12,0x12,0x05,0x02,0x13,0x04,0x19,0x00,
+		0x04,0x39,0x00,0x06,0x59,0x08,0x03,0x83,0x08,0x07,
+		0x03,0x50,0x00,0xC0,0x40,0x00,0x86,0x01,0x01,0xA6,
+		0x0D,0x02,0x03,0x11,0x01,0x05,0x37,0x00,0xAC,0x21,
+		0x00,
+	},
+	// TGB_NTSC392 // quartzsight
+	// This table has been modified to be used for Fusion Rev D
+	{
+		0x2A, // size of table = 42
+		0x06, 0x08, 0x04, 0x0a, 0xc0, 0x00, 0x18, 0x08, 0x03, 0x24,
+		0x08, 0x07, 0x02, 0x90, 0x02, 0x08, 0x10, 0x04, 0x0c, 0x10,
+		0x05, 0x2c, 0x11, 0x04, 0x55, 0x48, 0x00, 0x05, 0x50, 0x00,
+		0xbf, 0x0c, 0x02, 0x2f, 0x3d, 0x00, 0x2f, 0x3f, 0x00, 0xc3,
+		0x20, 0x00
+	}
+};
+
+/* minhdelayx1	first video pixel we can capture on a line and
+   hdelayx1	start of active video, both relative to rising edge of
+		/HRESET pulse (0H) in 1 / fCLKx1.
+   swidth	width of active video and
+   totalwidth	total line width, both in 1 / fCLKx1.
+   sqwidth	total line width in square pixels.
+   vdelay	start of active video in 2 * field lines relative to
+		trailing edge of /VRESET pulse (VDELAY register).
+   sheight	height of active video in 2 * field lines.
+   videostart0	ITU-R frame line number of the line corresponding
+		to vdelay in the first field. */
+#define CROPCAP(minhdelayx1, hdelayx1, swidth, totalwidth, sqwidth,	 \
+		vdelay, sheight, videostart0)				 \
+	.cropcap.bounds.left = minhdelayx1,				 \
+	/* * 2 because vertically we count field lines times two, */	 \
+	/* e.g. 23 * 2 to 23 * 2 + 576 in PAL-BGHI defrect. */		 \
+	.cropcap.bounds.top = (videostart0) * 2 - (vdelay) + MIN_VDELAY, \
+	/* 4 is a safety margin at the end of the line. */		 \
+	.cropcap.bounds.width = (totalwidth) - (minhdelayx1) - 4,	 \
+	.cropcap.bounds.height = (sheight) + (vdelay) - MIN_VDELAY,	 \
+	.cropcap.defrect.left = hdelayx1,				 \
+	.cropcap.defrect.top = (videostart0) * 2,			 \
+	.cropcap.defrect.width = swidth,				 \
+	.cropcap.defrect.height = sheight,				 \
+	.cropcap.pixelaspect.numerator = totalwidth,			 \
+	.cropcap.pixelaspect.denominator = sqwidth,
+
+const struct bttv_tvnorm bttv_tvnorms[] = {
+	/* PAL-BDGHI */
+	/* max. active video is actually 922, but 924 is divisible by 4 and 3! */
+	/* actually, max active PAL with HSCALE=0 is 948, NTSC is 768 - nil */
+	{
+		.v4l2_id        = V4L2_STD_PAL,
+		.name           = "PAL",
+		.Fsc            = 35468950,
+		.swidth         = 924,
+		.sheight        = 576,
+		.totalwidth     = 1135,
+		.adelay         = 0x7f,
+		.bdelay         = 0x72,
+		.iform          = (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1),
+		.scaledtwidth   = 1135,
+		.hdelayx1       = 186,
+		.hactivex1      = 924,
+		.vdelay         = 0x20,
+		.vbipack        = 255, /* min (2048 / 4, 0x1ff) & 0xff */
+		.sram           = 0,
+		/* ITU-R frame line number of the first VBI line
+		   we can capture, of the first and second field.
+		   The last line is determined by cropcap.bounds. */
+		.vbistart       = { 7, 320 },
+		CROPCAP(/* minhdelayx1 */ 68,
+			/* hdelayx1 */ 186,
+			/* Should be (768 * 1135 + 944 / 2) / 944.
+			   cropcap.defrect is used for image width
+			   checks, so we keep the old value 924. */
+			/* swidth */ 924,
+			/* totalwidth */ 1135,
+			/* sqwidth */ 944,
+			/* vdelay */ 0x20,
+			/* sheight */ 576,
+			/* videostart0 */ 23)
+		/* bt878 (and bt848?) can capture another
+		   line below active video. */
+		.cropcap.bounds.height = (576 + 2) + 0x20 - 2,
+	},{
+		.v4l2_id        = V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_KR,
+		.name           = "NTSC",
+		.Fsc            = 28636363,
+		.swidth         = 768,
+		.sheight        = 480,
+		.totalwidth     = 910,
+		.adelay         = 0x68,
+		.bdelay         = 0x5d,
+		.iform          = (BT848_IFORM_NTSC|BT848_IFORM_XT0),
+		.scaledtwidth   = 910,
+		.hdelayx1       = 128,
+		.hactivex1      = 910,
+		.vdelay         = 0x1a,
+		.vbipack        = 144, /* min (1600 / 4, 0x1ff) & 0xff */
+		.sram           = 1,
+		.vbistart	= { 10, 273 },
+		CROPCAP(/* minhdelayx1 */ 68,
+			/* hdelayx1 */ 128,
+			/* Should be (640 * 910 + 780 / 2) / 780? */
+			/* swidth */ 768,
+			/* totalwidth */ 910,
+			/* sqwidth */ 780,
+			/* vdelay */ 0x1a,
+			/* sheight */ 480,
+			/* videostart0 */ 23)
+	},{
+		.v4l2_id        = V4L2_STD_SECAM,
+		.name           = "SECAM",
+		.Fsc            = 35468950,
+		.swidth         = 924,
+		.sheight        = 576,
+		.totalwidth     = 1135,
+		.adelay         = 0x7f,
+		.bdelay         = 0xb0,
+		.iform          = (BT848_IFORM_SECAM|BT848_IFORM_XT1),
+		.scaledtwidth   = 1135,
+		.hdelayx1       = 186,
+		.hactivex1      = 922,
+		.vdelay         = 0x20,
+		.vbipack        = 255,
+		.sram           = 0, /* like PAL, correct? */
+		.vbistart	= { 7, 320 },
+		CROPCAP(/* minhdelayx1 */ 68,
+			/* hdelayx1 */ 186,
+			/* swidth */ 924,
+			/* totalwidth */ 1135,
+			/* sqwidth */ 944,
+			/* vdelay */ 0x20,
+			/* sheight */ 576,
+			/* videostart0 */ 23)
+	},{
+		.v4l2_id        = V4L2_STD_PAL_Nc,
+		.name           = "PAL-Nc",
+		.Fsc            = 28636363,
+		.swidth         = 640,
+		.sheight        = 576,
+		.totalwidth     = 910,
+		.adelay         = 0x68,
+		.bdelay         = 0x5d,
+		.iform          = (BT848_IFORM_PAL_NC|BT848_IFORM_XT0),
+		.scaledtwidth   = 780,
+		.hdelayx1       = 130,
+		.hactivex1      = 734,
+		.vdelay         = 0x1a,
+		.vbipack        = 144,
+		.sram           = -1,
+		.vbistart	= { 7, 320 },
+		CROPCAP(/* minhdelayx1 */ 68,
+			/* hdelayx1 */ 130,
+			/* swidth */ (640 * 910 + 780 / 2) / 780,
+			/* totalwidth */ 910,
+			/* sqwidth */ 780,
+			/* vdelay */ 0x1a,
+			/* sheight */ 576,
+			/* videostart0 */ 23)
+	},{
+		.v4l2_id        = V4L2_STD_PAL_M,
+		.name           = "PAL-M",
+		.Fsc            = 28636363,
+		.swidth         = 640,
+		.sheight        = 480,
+		.totalwidth     = 910,
+		.adelay         = 0x68,
+		.bdelay         = 0x5d,
+		.iform          = (BT848_IFORM_PAL_M|BT848_IFORM_XT0),
+		.scaledtwidth   = 780,
+		.hdelayx1       = 135,
+		.hactivex1      = 754,
+		.vdelay         = 0x1a,
+		.vbipack        = 144,
+		.sram           = -1,
+		.vbistart	= { 10, 273 },
+		CROPCAP(/* minhdelayx1 */ 68,
+			/* hdelayx1 */ 135,
+			/* swidth */ (640 * 910 + 780 / 2) / 780,
+			/* totalwidth */ 910,
+			/* sqwidth */ 780,
+			/* vdelay */ 0x1a,
+			/* sheight */ 480,
+			/* videostart0 */ 23)
+	},{
+		.v4l2_id        = V4L2_STD_PAL_N,
+		.name           = "PAL-N",
+		.Fsc            = 35468950,
+		.swidth         = 768,
+		.sheight        = 576,
+		.totalwidth     = 1135,
+		.adelay         = 0x7f,
+		.bdelay         = 0x72,
+		.iform          = (BT848_IFORM_PAL_N|BT848_IFORM_XT1),
+		.scaledtwidth   = 944,
+		.hdelayx1       = 186,
+		.hactivex1      = 922,
+		.vdelay         = 0x20,
+		.vbipack        = 144,
+		.sram           = -1,
+		.vbistart       = { 7, 320 },
+		CROPCAP(/* minhdelayx1 */ 68,
+			/* hdelayx1 */ 186,
+			/* swidth */ (768 * 1135 + 944 / 2) / 944,
+			/* totalwidth */ 1135,
+			/* sqwidth */ 944,
+			/* vdelay */ 0x20,
+			/* sheight */ 576,
+			/* videostart0 */ 23)
+	},{
+		.v4l2_id        = V4L2_STD_NTSC_M_JP,
+		.name           = "NTSC-JP",
+		.Fsc            = 28636363,
+		.swidth         = 640,
+		.sheight        = 480,
+		.totalwidth     = 910,
+		.adelay         = 0x68,
+		.bdelay         = 0x5d,
+		.iform          = (BT848_IFORM_NTSC_J|BT848_IFORM_XT0),
+		.scaledtwidth   = 780,
+		.hdelayx1       = 135,
+		.hactivex1      = 754,
+		.vdelay         = 0x16,
+		.vbipack        = 144,
+		.sram           = -1,
+		.vbistart       = { 10, 273 },
+		CROPCAP(/* minhdelayx1 */ 68,
+			/* hdelayx1 */ 135,
+			/* swidth */ (640 * 910 + 780 / 2) / 780,
+			/* totalwidth */ 910,
+			/* sqwidth */ 780,
+			/* vdelay */ 0x16,
+			/* sheight */ 480,
+			/* videostart0 */ 23)
+	},{
+		/* that one hopefully works with the strange timing
+		 * which video recorders produce when playing a NTSC
+		 * tape on a PAL TV ... */
+		.v4l2_id        = V4L2_STD_PAL_60,
+		.name           = "PAL-60",
+		.Fsc            = 35468950,
+		.swidth         = 924,
+		.sheight        = 480,
+		.totalwidth     = 1135,
+		.adelay         = 0x7f,
+		.bdelay         = 0x72,
+		.iform          = (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1),
+		.scaledtwidth   = 1135,
+		.hdelayx1       = 186,
+		.hactivex1      = 924,
+		.vdelay         = 0x1a,
+		.vbipack        = 255,
+		.vtotal         = 524,
+		.sram           = -1,
+		.vbistart	= { 10, 273 },
+		CROPCAP(/* minhdelayx1 */ 68,
+			/* hdelayx1 */ 186,
+			/* swidth */ 924,
+			/* totalwidth */ 1135,
+			/* sqwidth */ 944,
+			/* vdelay */ 0x1a,
+			/* sheight */ 480,
+			/* videostart0 */ 23)
+	}
+};
+static const unsigned int BTTV_TVNORMS = ARRAY_SIZE(bttv_tvnorms);
+
+/* ----------------------------------------------------------------------- */
+/* bttv format list
+   packed pixel formats must come first */
+static const struct bttv_format formats[] = {
+	{
+		.name     = "8 bpp, gray",
+		.fourcc   = V4L2_PIX_FMT_GREY,
+		.btformat = BT848_COLOR_FMT_Y8,
+		.depth    = 8,
+		.flags    = FORMAT_FLAGS_PACKED,
+	},{
+		.name     = "8 bpp, dithered color",
+		.fourcc   = V4L2_PIX_FMT_HI240,
+		.btformat = BT848_COLOR_FMT_RGB8,
+		.depth    = 8,
+		.flags    = FORMAT_FLAGS_PACKED | FORMAT_FLAGS_DITHER,
+	},{
+		.name     = "15 bpp RGB, le",
+		.fourcc   = V4L2_PIX_FMT_RGB555,
+		.btformat = BT848_COLOR_FMT_RGB15,
+		.depth    = 16,
+		.flags    = FORMAT_FLAGS_PACKED,
+	},{
+		.name     = "15 bpp RGB, be",
+		.fourcc   = V4L2_PIX_FMT_RGB555X,
+		.btformat = BT848_COLOR_FMT_RGB15,
+		.btswap   = 0x03, /* byteswap */
+		.depth    = 16,
+		.flags    = FORMAT_FLAGS_PACKED,
+	},{
+		.name     = "16 bpp RGB, le",
+		.fourcc   = V4L2_PIX_FMT_RGB565,
+		.btformat = BT848_COLOR_FMT_RGB16,
+		.depth    = 16,
+		.flags    = FORMAT_FLAGS_PACKED,
+	},{
+		.name     = "16 bpp RGB, be",
+		.fourcc   = V4L2_PIX_FMT_RGB565X,
+		.btformat = BT848_COLOR_FMT_RGB16,
+		.btswap   = 0x03, /* byteswap */
+		.depth    = 16,
+		.flags    = FORMAT_FLAGS_PACKED,
+	},{
+		.name     = "24 bpp RGB, le",
+		.fourcc   = V4L2_PIX_FMT_BGR24,
+		.btformat = BT848_COLOR_FMT_RGB24,
+		.depth    = 24,
+		.flags    = FORMAT_FLAGS_PACKED,
+	},{
+		.name     = "32 bpp RGB, le",
+		.fourcc   = V4L2_PIX_FMT_BGR32,
+		.btformat = BT848_COLOR_FMT_RGB32,
+		.depth    = 32,
+		.flags    = FORMAT_FLAGS_PACKED,
+	},{
+		.name     = "32 bpp RGB, be",
+		.fourcc   = V4L2_PIX_FMT_RGB32,
+		.btformat = BT848_COLOR_FMT_RGB32,
+		.btswap   = 0x0f, /* byte+word swap */
+		.depth    = 32,
+		.flags    = FORMAT_FLAGS_PACKED,
+	},{
+		.name     = "4:2:2, packed, YUYV",
+		.fourcc   = V4L2_PIX_FMT_YUYV,
+		.btformat = BT848_COLOR_FMT_YUY2,
+		.depth    = 16,
+		.flags    = FORMAT_FLAGS_PACKED,
+	},{
+		.name     = "4:2:2, packed, UYVY",
+		.fourcc   = V4L2_PIX_FMT_UYVY,
+		.btformat = BT848_COLOR_FMT_YUY2,
+		.btswap   = 0x03, /* byteswap */
+		.depth    = 16,
+		.flags    = FORMAT_FLAGS_PACKED,
+	},{
+		.name     = "4:2:2, planar, Y-Cb-Cr",
+		.fourcc   = V4L2_PIX_FMT_YUV422P,
+		.btformat = BT848_COLOR_FMT_YCrCb422,
+		.depth    = 16,
+		.flags    = FORMAT_FLAGS_PLANAR,
+		.hshift   = 1,
+		.vshift   = 0,
+	},{
+		.name     = "4:2:0, planar, Y-Cb-Cr",
+		.fourcc   = V4L2_PIX_FMT_YUV420,
+		.btformat = BT848_COLOR_FMT_YCrCb422,
+		.depth    = 12,
+		.flags    = FORMAT_FLAGS_PLANAR,
+		.hshift   = 1,
+		.vshift   = 1,
+	},{
+		.name     = "4:2:0, planar, Y-Cr-Cb",
+		.fourcc   = V4L2_PIX_FMT_YVU420,
+		.btformat = BT848_COLOR_FMT_YCrCb422,
+		.depth    = 12,
+		.flags    = FORMAT_FLAGS_PLANAR | FORMAT_FLAGS_CrCb,
+		.hshift   = 1,
+		.vshift   = 1,
+	},{
+		.name     = "4:1:1, planar, Y-Cb-Cr",
+		.fourcc   = V4L2_PIX_FMT_YUV411P,
+		.btformat = BT848_COLOR_FMT_YCrCb411,
+		.depth    = 12,
+		.flags    = FORMAT_FLAGS_PLANAR,
+		.hshift   = 2,
+		.vshift   = 0,
+	},{
+		.name     = "4:1:0, planar, Y-Cb-Cr",
+		.fourcc   = V4L2_PIX_FMT_YUV410,
+		.btformat = BT848_COLOR_FMT_YCrCb411,
+		.depth    = 9,
+		.flags    = FORMAT_FLAGS_PLANAR,
+		.hshift   = 2,
+		.vshift   = 2,
+	},{
+		.name     = "4:1:0, planar, Y-Cr-Cb",
+		.fourcc   = V4L2_PIX_FMT_YVU410,
+		.btformat = BT848_COLOR_FMT_YCrCb411,
+		.depth    = 9,
+		.flags    = FORMAT_FLAGS_PLANAR | FORMAT_FLAGS_CrCb,
+		.hshift   = 2,
+		.vshift   = 2,
+	},{
+		.name     = "raw scanlines",
+		.fourcc   = -1,
+		.btformat = BT848_COLOR_FMT_RAW,
+		.depth    = 8,
+		.flags    = FORMAT_FLAGS_RAW,
+	}
+};
+static const unsigned int FORMATS = ARRAY_SIZE(formats);
+
+/* ----------------------------------------------------------------------- */
+
+#define V4L2_CID_PRIVATE_CHROMA_AGC  (V4L2_CID_PRIVATE_BASE + 0)
+#define V4L2_CID_PRIVATE_COMBFILTER  (V4L2_CID_PRIVATE_BASE + 1)
+#define V4L2_CID_PRIVATE_AUTOMUTE    (V4L2_CID_PRIVATE_BASE + 2)
+#define V4L2_CID_PRIVATE_LUMAFILTER  (V4L2_CID_PRIVATE_BASE + 3)
+#define V4L2_CID_PRIVATE_AGC_CRUSH   (V4L2_CID_PRIVATE_BASE + 4)
+#define V4L2_CID_PRIVATE_VCR_HACK    (V4L2_CID_PRIVATE_BASE + 5)
+#define V4L2_CID_PRIVATE_WHITECRUSH_UPPER   (V4L2_CID_PRIVATE_BASE + 6)
+#define V4L2_CID_PRIVATE_WHITECRUSH_LOWER   (V4L2_CID_PRIVATE_BASE + 7)
+#define V4L2_CID_PRIVATE_UV_RATIO    (V4L2_CID_PRIVATE_BASE + 8)
+#define V4L2_CID_PRIVATE_FULL_LUMA_RANGE    (V4L2_CID_PRIVATE_BASE + 9)
+#define V4L2_CID_PRIVATE_CORING      (V4L2_CID_PRIVATE_BASE + 10)
+#define V4L2_CID_PRIVATE_LASTP1      (V4L2_CID_PRIVATE_BASE + 11)
+
+static const struct v4l2_queryctrl no_ctl = {
+	.name  = "42",
+	.flags = V4L2_CTRL_FLAG_DISABLED,
+};
+static const struct v4l2_queryctrl bttv_ctls[] = {
+	/* --- video --- */
+	{
+		.id            = V4L2_CID_BRIGHTNESS,
+		.name          = "Brightness",
+		.minimum       = 0,
+		.maximum       = 65535,
+		.step          = 256,
+		.default_value = 32768,
+		.type          = V4L2_CTRL_TYPE_INTEGER,
+	},{
+		.id            = V4L2_CID_CONTRAST,
+		.name          = "Contrast",
+		.minimum       = 0,
+		.maximum       = 65535,
+		.step          = 128,
+		.default_value = 27648,
+		.type          = V4L2_CTRL_TYPE_INTEGER,
+	},{
+		.id            = V4L2_CID_SATURATION,
+		.name          = "Saturation",
+		.minimum       = 0,
+		.maximum       = 65535,
+		.step          = 128,
+		.default_value = 32768,
+		.type          = V4L2_CTRL_TYPE_INTEGER,
+	},{
+		.id            = V4L2_CID_HUE,
+		.name          = "Hue",
+		.minimum       = 0,
+		.maximum       = 65535,
+		.step          = 256,
+		.default_value = 32768,
+		.type          = V4L2_CTRL_TYPE_INTEGER,
+	},
+	/* --- audio --- */
+	{
+		.id            = V4L2_CID_AUDIO_MUTE,
+		.name          = "Mute",
+		.minimum       = 0,
+		.maximum       = 1,
+		.type          = V4L2_CTRL_TYPE_BOOLEAN,
+	},{
+		.id            = V4L2_CID_AUDIO_VOLUME,
+		.name          = "Volume",
+		.minimum       = 0,
+		.maximum       = 65535,
+		.step          = 65535/100,
+		.default_value = 65535,
+		.type          = V4L2_CTRL_TYPE_INTEGER,
+	},{
+		.id            = V4L2_CID_AUDIO_BALANCE,
+		.name          = "Balance",
+		.minimum       = 0,
+		.maximum       = 65535,
+		.step          = 65535/100,
+		.default_value = 32768,
+		.type          = V4L2_CTRL_TYPE_INTEGER,
+	},{
+		.id            = V4L2_CID_AUDIO_BASS,
+		.name          = "Bass",
+		.minimum       = 0,
+		.maximum       = 65535,
+		.step          = 65535/100,
+		.default_value = 32768,
+		.type          = V4L2_CTRL_TYPE_INTEGER,
+	},{
+		.id            = V4L2_CID_AUDIO_TREBLE,
+		.name          = "Treble",
+		.minimum       = 0,
+		.maximum       = 65535,
+		.step          = 65535/100,
+		.default_value = 32768,
+		.type          = V4L2_CTRL_TYPE_INTEGER,
+	},
+	/* --- private --- */
+	{
+		.id            = V4L2_CID_PRIVATE_CHROMA_AGC,
+		.name          = "chroma agc",
+		.minimum       = 0,
+		.maximum       = 1,
+		.type          = V4L2_CTRL_TYPE_BOOLEAN,
+	},{
+		.id            = V4L2_CID_PRIVATE_COMBFILTER,
+		.name          = "combfilter",
+		.minimum       = 0,
+		.maximum       = 1,
+		.type          = V4L2_CTRL_TYPE_BOOLEAN,
+	},{
+		.id            = V4L2_CID_PRIVATE_AUTOMUTE,
+		.name          = "automute",
+		.minimum       = 0,
+		.maximum       = 1,
+		.type          = V4L2_CTRL_TYPE_BOOLEAN,
+	},{
+		.id            = V4L2_CID_PRIVATE_LUMAFILTER,
+		.name          = "luma decimation filter",
+		.minimum       = 0,
+		.maximum       = 1,
+		.type          = V4L2_CTRL_TYPE_BOOLEAN,
+	},{
+		.id            = V4L2_CID_PRIVATE_AGC_CRUSH,
+		.name          = "agc crush",
+		.minimum       = 0,
+		.maximum       = 1,
+		.type          = V4L2_CTRL_TYPE_BOOLEAN,
+	},{
+		.id            = V4L2_CID_PRIVATE_VCR_HACK,
+		.name          = "vcr hack",
+		.minimum       = 0,
+		.maximum       = 1,
+		.type          = V4L2_CTRL_TYPE_BOOLEAN,
+	},{
+		.id            = V4L2_CID_PRIVATE_WHITECRUSH_UPPER,
+		.name          = "whitecrush upper",
+		.minimum       = 0,
+		.maximum       = 255,
+		.step          = 1,
+		.default_value = 0xCF,
+		.type          = V4L2_CTRL_TYPE_INTEGER,
+	},{
+		.id            = V4L2_CID_PRIVATE_WHITECRUSH_LOWER,
+		.name          = "whitecrush lower",
+		.minimum       = 0,
+		.maximum       = 255,
+		.step          = 1,
+		.default_value = 0x7F,
+		.type          = V4L2_CTRL_TYPE_INTEGER,
+	},{
+		.id            = V4L2_CID_PRIVATE_UV_RATIO,
+		.name          = "uv ratio",
+		.minimum       = 0,
+		.maximum       = 100,
+		.step          = 1,
+		.default_value = 50,
+		.type          = V4L2_CTRL_TYPE_INTEGER,
+	},{
+		.id            = V4L2_CID_PRIVATE_FULL_LUMA_RANGE,
+		.name          = "full luma range",
+		.minimum       = 0,
+		.maximum       = 1,
+		.type          = V4L2_CTRL_TYPE_BOOLEAN,
+	},{
+		.id            = V4L2_CID_PRIVATE_CORING,
+		.name          = "coring",
+		.minimum       = 0,
+		.maximum       = 3,
+		.step          = 1,
+		.default_value = 0,
+		.type          = V4L2_CTRL_TYPE_INTEGER,
+	}
+
+
+
+};
+
+static const struct v4l2_queryctrl *ctrl_by_id(int id)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(bttv_ctls); i++)
+		if (bttv_ctls[i].id == id)
+			return bttv_ctls+i;
+
+	return NULL;
+}
+
+/* ----------------------------------------------------------------------- */
+/* resource management                                                     */
+
+/*
+   RESOURCE_    allocated by                freed by
+
+   VIDEO_READ   bttv_read 1)                bttv_read 2)
+
+   VIDEO_STREAM VIDIOC_STREAMON             VIDIOC_STREAMOFF
+		 VIDIOC_QBUF 1)              bttv_release
+		 VIDIOCMCAPTURE 1)
+
+   OVERLAY	 VIDIOCCAPTURE on            VIDIOCCAPTURE off
+		 VIDIOC_OVERLAY on           VIDIOC_OVERLAY off
+		 3)                          bttv_release
+
+   VBI		 VIDIOC_STREAMON             VIDIOC_STREAMOFF
+		 VIDIOC_QBUF 1)              bttv_release
+		 bttv_read, bttv_poll 1) 4)
+
+   1) The resource must be allocated when we enter buffer prepare functions
+      and remain allocated while buffers are in the DMA queue.
+   2) This is a single frame read.
+   3) VIDIOC_S_FBUF and VIDIOC_S_FMT (OVERLAY) still work when
+      RESOURCE_OVERLAY is allocated.
+   4) This is a continuous read, implies VIDIOC_STREAMON.
+
+   Note this driver permits video input and standard changes regardless if
+   resources are allocated.
+*/
+
+#define VBI_RESOURCES (RESOURCE_VBI)
+#define VIDEO_RESOURCES (RESOURCE_VIDEO_READ | \
+			 RESOURCE_VIDEO_STREAM | \
+			 RESOURCE_OVERLAY)
+
+static
+int check_alloc_btres_lock(struct bttv *btv, struct bttv_fh *fh, int bit)
+{
+	int xbits; /* mutual exclusive resources */
+
+	if (fh->resources & bit)
+		/* have it already allocated */
+		return 1;
+
+	xbits = bit;
+	if (bit & (RESOURCE_VIDEO_READ | RESOURCE_VIDEO_STREAM))
+		xbits |= RESOURCE_VIDEO_READ | RESOURCE_VIDEO_STREAM;
+
+	/* is it free? */
+	if (btv->resources & xbits) {
+		/* no, someone else uses it */
+		goto fail;
+	}
+
+	if ((bit & VIDEO_RESOURCES)
+	    && 0 == (btv->resources & VIDEO_RESOURCES)) {
+		/* Do crop - use current, don't - use default parameters. */
+		__s32 top = btv->crop[!!fh->do_crop].rect.top;
+
+		if (btv->vbi_end > top)
+			goto fail;
+
+		/* We cannot capture the same line as video and VBI data.
+		   Claim scan lines crop[].rect.top to bottom. */
+		btv->crop_start = top;
+	} else if (bit & VBI_RESOURCES) {
+		__s32 end = fh->vbi_fmt.end;
+
+		if (end > btv->crop_start)
+			goto fail;
+
+		/* Claim scan lines above fh->vbi_fmt.end. */
+		btv->vbi_end = end;
+	}
+
+	/* it's free, grab it */
+	fh->resources  |= bit;
+	btv->resources |= bit;
+	return 1;
+
+ fail:
+	return 0;
+}
+
+static
+int check_btres(struct bttv_fh *fh, int bit)
+{
+	return (fh->resources & bit);
+}
+
+static
+int locked_btres(struct bttv *btv, int bit)
+{
+	return (btv->resources & bit);
+}
+
+/* Call with btv->lock down. */
+static void
+disclaim_vbi_lines(struct bttv *btv)
+{
+	btv->vbi_end = 0;
+}
+
+/* Call with btv->lock down. */
+static void
+disclaim_video_lines(struct bttv *btv)
+{
+	const struct bttv_tvnorm *tvnorm;
+	u8 crop;
+
+	tvnorm = &bttv_tvnorms[btv->tvnorm];
+	btv->crop_start = tvnorm->cropcap.bounds.top
+		+ tvnorm->cropcap.bounds.height;
+
+	/* VBI capturing ends at VDELAY, start of video capturing, no
+	   matter how many lines the VBI RISC program expects. When video
+	   capturing is off, it shall no longer "preempt" VBI capturing,
+	   so we set VDELAY to maximum. */
+	crop = btread(BT848_E_CROP) | 0xc0;
+	btwrite(crop, BT848_E_CROP);
+	btwrite(0xfe, BT848_E_VDELAY_LO);
+	btwrite(crop, BT848_O_CROP);
+	btwrite(0xfe, BT848_O_VDELAY_LO);
+}
+
+static
+void free_btres_lock(struct bttv *btv, struct bttv_fh *fh, int bits)
+{
+	if ((fh->resources & bits) != bits) {
+		/* trying to free resources not allocated by us ... */
+		pr_err("BUG! (btres)\n");
+	}
+	fh->resources  &= ~bits;
+	btv->resources &= ~bits;
+
+	bits = btv->resources;
+
+	if (0 == (bits & VIDEO_RESOURCES))
+		disclaim_video_lines(btv);
+
+	if (0 == (bits & VBI_RESOURCES))
+		disclaim_vbi_lines(btv);
+}
+
+/* ----------------------------------------------------------------------- */
+/* If Bt848a or Bt849, use PLL for PAL/SECAM and crystal for NTSC          */
+
+/* Frequency = (F_input / PLL_X) * PLL_I.PLL_F/PLL_C
+   PLL_X = Reference pre-divider (0=1, 1=2)
+   PLL_C = Post divider (0=6, 1=4)
+   PLL_I = Integer input
+   PLL_F = Fractional input
+
+   F_input = 28.636363 MHz:
+   PAL (CLKx2 = 35.46895 MHz): PLL_X = 1, PLL_I = 0x0E, PLL_F = 0xDCF9, PLL_C = 0
+*/
+
+static void set_pll_freq(struct bttv *btv, unsigned int fin, unsigned int fout)
+{
+	unsigned char fl, fh, fi;
+
+	/* prevent overflows */
+	fin/=4;
+	fout/=4;
+
+	fout*=12;
+	fi=fout/fin;
+
+	fout=(fout%fin)*256;
+	fh=fout/fin;
+
+	fout=(fout%fin)*256;
+	fl=fout/fin;
+
+	btwrite(fl, BT848_PLL_F_LO);
+	btwrite(fh, BT848_PLL_F_HI);
+	btwrite(fi|BT848_PLL_X, BT848_PLL_XCI);
+}
+
+static void set_pll(struct bttv *btv)
+{
+	int i;
+
+	if (!btv->pll.pll_crystal)
+		return;
+
+	if (btv->pll.pll_ofreq == btv->pll.pll_current) {
+		dprintk("%d: PLL: no change required\n", btv->c.nr);
+		return;
+	}
+
+	if (btv->pll.pll_ifreq == btv->pll.pll_ofreq) {
+		/* no PLL needed */
+		if (btv->pll.pll_current == 0)
+			return;
+		if (bttv_verbose)
+			pr_info("%d: PLL can sleep, using XTAL (%d)\n",
+				btv->c.nr, btv->pll.pll_ifreq);
+		btwrite(0x00,BT848_TGCTRL);
+		btwrite(0x00,BT848_PLL_XCI);
+		btv->pll.pll_current = 0;
+		return;
+	}
+
+	if (bttv_verbose)
+		pr_info("%d: Setting PLL: %d => %d (needs up to 100ms)\n",
+			btv->c.nr,
+			btv->pll.pll_ifreq, btv->pll.pll_ofreq);
+	set_pll_freq(btv, btv->pll.pll_ifreq, btv->pll.pll_ofreq);
+
+	for (i=0; i<10; i++) {
+		/*  Let other people run while the PLL stabilizes */
+		msleep(10);
+
+		if (btread(BT848_DSTATUS) & BT848_DSTATUS_PLOCK) {
+			btwrite(0,BT848_DSTATUS);
+		} else {
+			btwrite(0x08,BT848_TGCTRL);
+			btv->pll.pll_current = btv->pll.pll_ofreq;
+			if (bttv_verbose)
+				pr_info("PLL set ok\n");
+			return;
+		}
+	}
+	btv->pll.pll_current = -1;
+	if (bttv_verbose)
+		pr_info("Setting PLL failed\n");
+	return;
+}
+
+/* used to switch between the bt848's analog/digital video capture modes */
+static void bt848A_set_timing(struct bttv *btv)
+{
+	int i, len;
+	int table_idx = bttv_tvnorms[btv->tvnorm].sram;
+	int fsc       = bttv_tvnorms[btv->tvnorm].Fsc;
+
+	if (btv->input == btv->dig) {
+		dprintk("%d: load digital timing table (table_idx=%d)\n",
+			btv->c.nr,table_idx);
+
+		/* timing change...reset timing generator address */
+		btwrite(0x00, BT848_TGCTRL);
+		btwrite(0x02, BT848_TGCTRL);
+		btwrite(0x00, BT848_TGCTRL);
+
+		len=SRAM_Table[table_idx][0];
+		for(i = 1; i <= len; i++)
+			btwrite(SRAM_Table[table_idx][i],BT848_TGLB);
+		btv->pll.pll_ofreq = 27000000;
+
+		set_pll(btv);
+		btwrite(0x11, BT848_TGCTRL);
+		btwrite(0x41, BT848_DVSIF);
+	} else {
+		btv->pll.pll_ofreq = fsc;
+		set_pll(btv);
+		btwrite(0x0, BT848_DVSIF);
+	}
+}
+
+/* ----------------------------------------------------------------------- */
+
+static void bt848_bright(struct bttv *btv, int bright)
+{
+	int value;
+
+	// printk("set bright: %d\n", bright); // DEBUG
+	btv->bright = bright;
+
+	/* We want -128 to 127 we get 0-65535 */
+	value = (bright >> 8) - 128;
+	btwrite(value & 0xff, BT848_BRIGHT);
+}
+
+static void bt848_hue(struct bttv *btv, int hue)
+{
+	int value;
+
+	btv->hue = hue;
+
+	/* -128 to 127 */
+	value = (hue >> 8) - 128;
+	btwrite(value & 0xff, BT848_HUE);
+}
+
+static void bt848_contrast(struct bttv *btv, int cont)
+{
+	int value,hibit;
+
+	btv->contrast = cont;
+
+	/* 0-511 */
+	value = (cont  >> 7);
+	hibit = (value >> 6) & 4;
+	btwrite(value & 0xff, BT848_CONTRAST_LO);
+	btaor(hibit, ~4, BT848_E_CONTROL);
+	btaor(hibit, ~4, BT848_O_CONTROL);
+}
+
+static void bt848_sat(struct bttv *btv, int color)
+{
+	int val_u,val_v,hibits;
+
+	btv->saturation = color;
+
+	/* 0-511 for the color */
+	val_u   = ((color * btv->opt_uv_ratio) / 50) >> 7;
+	val_v   = (((color * (100 - btv->opt_uv_ratio) / 50) >>7)*180L)/254;
+	hibits  = (val_u >> 7) & 2;
+	hibits |= (val_v >> 8) & 1;
+	btwrite(val_u & 0xff, BT848_SAT_U_LO);
+	btwrite(val_v & 0xff, BT848_SAT_V_LO);
+	btaor(hibits, ~3, BT848_E_CONTROL);
+	btaor(hibits, ~3, BT848_O_CONTROL);
+}
+
+/* ----------------------------------------------------------------------- */
+
+static int
+video_mux(struct bttv *btv, unsigned int input)
+{
+	int mux,mask2;
+
+	if (input >= bttv_tvcards[btv->c.type].video_inputs)
+		return -EINVAL;
+
+	/* needed by RemoteVideo MX */
+	mask2 = bttv_tvcards[btv->c.type].gpiomask2;
+	if (mask2)
+		gpio_inout(mask2,mask2);
+
+	if (input == btv->svhs)  {
+		btor(BT848_CONTROL_COMP, BT848_E_CONTROL);
+		btor(BT848_CONTROL_COMP, BT848_O_CONTROL);
+	} else {
+		btand(~BT848_CONTROL_COMP, BT848_E_CONTROL);
+		btand(~BT848_CONTROL_COMP, BT848_O_CONTROL);
+	}
+	mux = bttv_muxsel(btv, input);
+	btaor(mux<<5, ~(3<<5), BT848_IFORM);
+	dprintk("%d: video mux: input=%d mux=%d\n", btv->c.nr, input, mux);
+
+	/* card specific hook */
+	if(bttv_tvcards[btv->c.type].muxsel_hook)
+		bttv_tvcards[btv->c.type].muxsel_hook (btv, input);
+	return 0;
+}
+
+static char *audio_modes[] = {
+	"audio: tuner", "audio: radio", "audio: extern",
+	"audio: intern", "audio: mute"
+};
+
+static int
+audio_mux(struct bttv *btv, int input, int mute)
+{
+	int gpio_val, signal;
+	struct v4l2_control ctrl;
+
+	gpio_inout(bttv_tvcards[btv->c.type].gpiomask,
+		   bttv_tvcards[btv->c.type].gpiomask);
+	signal = btread(BT848_DSTATUS) & BT848_DSTATUS_HLOC;
+
+	btv->mute = mute;
+	btv->audio = input;
+
+	/* automute */
+	mute = mute || (btv->opt_automute && !signal && !btv->radio_user);
+
+	if (mute)
+		gpio_val = bttv_tvcards[btv->c.type].gpiomute;
+	else
+		gpio_val = bttv_tvcards[btv->c.type].gpiomux[input];
+
+	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())
+		return 0;
+
+	ctrl.id = V4L2_CID_AUDIO_MUTE;
+	ctrl.value = btv->mute;
+	bttv_call_all(btv, core, s_ctrl, &ctrl);
+	if (btv->sd_msp34xx) {
+		u32 in;
+
+		/* Note: the inputs tuner/radio/extern/intern are translated
+		   to msp routings. This assumes common behavior for all msp3400
+		   based TV cards. When this assumption fails, then the
+		   specific MSP routing must be added to the card table.
+		   For now this is sufficient. */
+		switch (input) {
+		case TVAUDIO_INPUT_RADIO:
+			/* Some boards need the msp do to the radio demod */
+			if (btv->radio_uses_msp_demodulator) {
+				in = MSP_INPUT_DEFAULT;
+				break;
+			}
+			in = MSP_INPUT(MSP_IN_SCART2, MSP_IN_TUNER1,
+				    MSP_DSP_IN_SCART, MSP_DSP_IN_SCART);
+			break;
+		case TVAUDIO_INPUT_EXTERN:
+			in = MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER1,
+				    MSP_DSP_IN_SCART, MSP_DSP_IN_SCART);
+			break;
+		case TVAUDIO_INPUT_INTERN:
+			/* Yes, this is the same input as for RADIO. I doubt
+			   if this is ever used. The only board with an INTERN
+			   input is the BTTV_BOARD_AVERMEDIA98. I wonder how
+			   that was tested. My guess is that the whole INTERN
+			   input does not work. */
+			in = MSP_INPUT(MSP_IN_SCART2, MSP_IN_TUNER1,
+				    MSP_DSP_IN_SCART, MSP_DSP_IN_SCART);
+			break;
+		case TVAUDIO_INPUT_TUNER:
+		default:
+			/* This is the only card that uses TUNER2, and afaik,
+			   is the only difference between the VOODOOTV_FM
+			   and VOODOOTV_200 */
+			if (btv->c.type == BTTV_BOARD_VOODOOTV_200)
+				in = MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER2, \
+					MSP_DSP_IN_TUNER, MSP_DSP_IN_TUNER);
+			else
+				in = MSP_INPUT_DEFAULT;
+			break;
+		}
+		v4l2_subdev_call(btv->sd_msp34xx, audio, s_routing,
+			       in, MSP_OUTPUT_DEFAULT, 0);
+	}
+	if (btv->sd_tvaudio) {
+		v4l2_subdev_call(btv->sd_tvaudio, audio, s_routing,
+				input, 0, 0);
+	}
+	return 0;
+}
+
+static inline int
+audio_mute(struct bttv *btv, int mute)
+{
+	return audio_mux(btv, btv->audio, mute);
+}
+
+static inline int
+audio_input(struct bttv *btv, int input)
+{
+	return audio_mux(btv, input, btv->mute);
+}
+
+static void
+bttv_crop_calc_limits(struct bttv_crop *c)
+{
+	/* Scale factor min. 1:1, max. 16:1. Min. image size
+	   48 x 32. Scaled width must be a multiple of 4. */
+
+	if (1) {
+		/* For bug compatibility with VIDIOCGCAP and image
+		   size checks in earlier driver versions. */
+		c->min_scaled_width = 48;
+		c->min_scaled_height = 32;
+	} else {
+		c->min_scaled_width =
+			(max(48, c->rect.width >> 4) + 3) & ~3;
+		c->min_scaled_height =
+			max(32, c->rect.height >> 4);
+	}
+
+	c->max_scaled_width  = c->rect.width & ~3;
+	c->max_scaled_height = c->rect.height;
+}
+
+static void
+bttv_crop_reset(struct bttv_crop *c, unsigned int norm)
+{
+	c->rect = bttv_tvnorms[norm].cropcap.defrect;
+	bttv_crop_calc_limits(c);
+}
+
+/* Call with btv->lock down. */
+static int
+set_tvnorm(struct bttv *btv, unsigned int norm)
+{
+	const struct bttv_tvnorm *tvnorm;
+	v4l2_std_id id;
+
+	BUG_ON(norm >= BTTV_TVNORMS);
+	BUG_ON(btv->tvnorm >= BTTV_TVNORMS);
+
+	tvnorm = &bttv_tvnorms[norm];
+
+	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 */
+
+		if (0 == (btv->resources & VIDEO_RESOURCES)) {
+			btv->crop_start = tvnorm->cropcap.bounds.top
+				+ tvnorm->cropcap.bounds.height;
+		}
+	}
+
+	btv->tvnorm = norm;
+
+	btwrite(tvnorm->adelay, BT848_ADELAY);
+	btwrite(tvnorm->bdelay, BT848_BDELAY);
+	btaor(tvnorm->iform,~(BT848_IFORM_NORM|BT848_IFORM_XTBOTH),
+	      BT848_IFORM);
+	btwrite(tvnorm->vbipack, BT848_VBI_PACK_SIZE);
+	btwrite(1, BT848_VBI_PACK_DEL);
+	bt848A_set_timing(btv);
+
+	switch (btv->c.type) {
+	case BTTV_BOARD_VOODOOTV_FM:
+	case BTTV_BOARD_VOODOOTV_200:
+		bttv_tda9880_setnorm(btv, gpio_read());
+		break;
+	}
+	id = tvnorm->v4l2_id;
+	bttv_call_all(btv, core, s_std, id);
+
+	return 0;
+}
+
+/* Call with btv->lock down. */
+static void
+set_input(struct bttv *btv, unsigned int input, unsigned int norm)
+{
+	unsigned long flags;
+
+	btv->input = input;
+	if (irq_iswitch) {
+		spin_lock_irqsave(&btv->s_lock,flags);
+		if (btv->curr.frame_irq) {
+			/* active capture -> delayed input switch */
+			btv->new_input = input;
+		} else {
+			video_mux(btv,input);
+		}
+		spin_unlock_irqrestore(&btv->s_lock,flags);
+	} else {
+		video_mux(btv,input);
+	}
+	audio_input(btv, (btv->tuner_type != TUNER_ABSENT && input == 0) ?
+			 TVAUDIO_INPUT_TUNER : TVAUDIO_INPUT_EXTERN);
+	set_tvnorm(btv, norm);
+}
+
+static void init_irqreg(struct bttv *btv)
+{
+	/* clear status */
+	btwrite(0xfffffUL, BT848_INT_STAT);
+
+	if (bttv_tvcards[btv->c.type].no_video) {
+		/* i2c only */
+		btwrite(BT848_INT_I2CDONE,
+			BT848_INT_MASK);
+	} else {
+		/* full video */
+		btwrite((btv->triton1)  |
+			(btv->gpioirq ? BT848_INT_GPINT : 0) |
+			BT848_INT_SCERR |
+			(fdsr ? BT848_INT_FDSR : 0) |
+			BT848_INT_RISCI | BT848_INT_OCERR |
+			BT848_INT_FMTCHG|BT848_INT_HLOCK|
+			BT848_INT_I2CDONE,
+			BT848_INT_MASK);
+	}
+}
+
+static void init_bt848(struct bttv *btv)
+{
+	int val;
+
+	if (bttv_tvcards[btv->c.type].no_video) {
+		/* very basic init only */
+		init_irqreg(btv);
+		return;
+	}
+
+	btwrite(0x00, BT848_CAP_CTL);
+	btwrite(BT848_COLOR_CTL_GAMMA, BT848_COLOR_CTL);
+	btwrite(BT848_IFORM_XTAUTO | BT848_IFORM_AUTO, BT848_IFORM);
+
+	/* set planar and packed mode trigger points and         */
+	/* set rising edge of inverted GPINTR pin as irq trigger */
+	btwrite(BT848_GPIO_DMA_CTL_PKTP_32|
+		BT848_GPIO_DMA_CTL_PLTP1_16|
+		BT848_GPIO_DMA_CTL_PLTP23_16|
+		BT848_GPIO_DMA_CTL_GPINTC|
+		BT848_GPIO_DMA_CTL_GPINTI,
+		BT848_GPIO_DMA_CTL);
+
+	val = btv->opt_chroma_agc ? BT848_SCLOOP_CAGC : 0;
+	btwrite(val, BT848_E_SCLOOP);
+	btwrite(val, BT848_O_SCLOOP);
+
+	btwrite(0x20, BT848_E_VSCALE_HI);
+	btwrite(0x20, BT848_O_VSCALE_HI);
+	btwrite(BT848_ADC_RESERVED | (btv->opt_adc_crush ? BT848_ADC_CRUSH : 0),
+		BT848_ADC);
+
+	btwrite(whitecrush_upper, BT848_WC_UP);
+	btwrite(whitecrush_lower, BT848_WC_DOWN);
+
+	if (btv->opt_lumafilter) {
+		btwrite(0, BT848_E_CONTROL);
+		btwrite(0, BT848_O_CONTROL);
+	} else {
+		btwrite(BT848_CONTROL_LDEC, BT848_E_CONTROL);
+		btwrite(BT848_CONTROL_LDEC, BT848_O_CONTROL);
+	}
+
+	bt848_bright(btv,   btv->bright);
+	bt848_hue(btv,      btv->hue);
+	bt848_contrast(btv, btv->contrast);
+	bt848_sat(btv,      btv->saturation);
+
+	/* interrupt */
+	init_irqreg(btv);
+}
+
+static void bttv_reinit_bt848(struct bttv *btv)
+{
+	unsigned long flags;
+
+	if (bttv_verbose)
+		pr_info("%d: reset, reinitialize\n", btv->c.nr);
+	spin_lock_irqsave(&btv->s_lock,flags);
+	btv->errors=0;
+	bttv_set_dma(btv,0);
+	spin_unlock_irqrestore(&btv->s_lock,flags);
+
+	init_bt848(btv);
+	btv->pll.pll_current = -1;
+	set_input(btv, btv->input, btv->tvnorm);
+}
+
+static int bttv_g_ctrl(struct file *file, void *priv,
+					struct v4l2_control *c)
+{
+	struct bttv_fh *fh = priv;
+	struct bttv *btv = fh->btv;
+
+	switch (c->id) {
+	case V4L2_CID_BRIGHTNESS:
+		c->value = btv->bright;
+		break;
+	case V4L2_CID_HUE:
+		c->value = btv->hue;
+		break;
+	case V4L2_CID_CONTRAST:
+		c->value = btv->contrast;
+		break;
+	case V4L2_CID_SATURATION:
+		c->value = btv->saturation;
+		break;
+
+	case V4L2_CID_AUDIO_MUTE:
+	case V4L2_CID_AUDIO_VOLUME:
+	case V4L2_CID_AUDIO_BALANCE:
+	case V4L2_CID_AUDIO_BASS:
+	case V4L2_CID_AUDIO_TREBLE:
+		bttv_call_all(btv, core, g_ctrl, c);
+		break;
+
+	case V4L2_CID_PRIVATE_CHROMA_AGC:
+		c->value = btv->opt_chroma_agc;
+		break;
+	case V4L2_CID_PRIVATE_COMBFILTER:
+		c->value = btv->opt_combfilter;
+		break;
+	case V4L2_CID_PRIVATE_LUMAFILTER:
+		c->value = btv->opt_lumafilter;
+		break;
+	case V4L2_CID_PRIVATE_AUTOMUTE:
+		c->value = btv->opt_automute;
+		break;
+	case V4L2_CID_PRIVATE_AGC_CRUSH:
+		c->value = btv->opt_adc_crush;
+		break;
+	case V4L2_CID_PRIVATE_VCR_HACK:
+		c->value = btv->opt_vcr_hack;
+		break;
+	case V4L2_CID_PRIVATE_WHITECRUSH_UPPER:
+		c->value = btv->opt_whitecrush_upper;
+		break;
+	case V4L2_CID_PRIVATE_WHITECRUSH_LOWER:
+		c->value = btv->opt_whitecrush_lower;
+		break;
+	case V4L2_CID_PRIVATE_UV_RATIO:
+		c->value = btv->opt_uv_ratio;
+		break;
+	case V4L2_CID_PRIVATE_FULL_LUMA_RANGE:
+		c->value = btv->opt_full_luma_range;
+		break;
+	case V4L2_CID_PRIVATE_CORING:
+		c->value = btv->opt_coring;
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int bttv_s_ctrl(struct file *file, void *f,
+					struct v4l2_control *c)
+{
+	int err;
+	int val;
+	struct bttv_fh *fh = f;
+	struct bttv *btv = fh->btv;
+
+	err = v4l2_prio_check(&btv->prio, fh->prio);
+	if (0 != err)
+		return err;
+
+	switch (c->id) {
+	case V4L2_CID_BRIGHTNESS:
+		bt848_bright(btv, c->value);
+		break;
+	case V4L2_CID_HUE:
+		bt848_hue(btv, c->value);
+		break;
+	case V4L2_CID_CONTRAST:
+		bt848_contrast(btv, c->value);
+		break;
+	case V4L2_CID_SATURATION:
+		bt848_sat(btv, c->value);
+		break;
+	case V4L2_CID_AUDIO_MUTE:
+		audio_mute(btv, c->value);
+		/* fall through */
+	case V4L2_CID_AUDIO_VOLUME:
+		if (btv->volume_gpio)
+			btv->volume_gpio(btv, c->value);
+
+		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_all(btv, core, s_ctrl, c);
+		break;
+
+	case V4L2_CID_PRIVATE_CHROMA_AGC:
+		btv->opt_chroma_agc = c->value;
+		val = btv->opt_chroma_agc ? BT848_SCLOOP_CAGC : 0;
+		btwrite(val, BT848_E_SCLOOP);
+		btwrite(val, BT848_O_SCLOOP);
+		break;
+	case V4L2_CID_PRIVATE_COMBFILTER:
+		btv->opt_combfilter = c->value;
+		break;
+	case V4L2_CID_PRIVATE_LUMAFILTER:
+		btv->opt_lumafilter = c->value;
+		if (btv->opt_lumafilter) {
+			btand(~BT848_CONTROL_LDEC, BT848_E_CONTROL);
+			btand(~BT848_CONTROL_LDEC, BT848_O_CONTROL);
+		} else {
+			btor(BT848_CONTROL_LDEC, BT848_E_CONTROL);
+			btor(BT848_CONTROL_LDEC, BT848_O_CONTROL);
+		}
+		break;
+	case V4L2_CID_PRIVATE_AUTOMUTE:
+		btv->opt_automute = c->value;
+		break;
+	case V4L2_CID_PRIVATE_AGC_CRUSH:
+		btv->opt_adc_crush = c->value;
+		btwrite(BT848_ADC_RESERVED |
+				(btv->opt_adc_crush ? BT848_ADC_CRUSH : 0),
+				BT848_ADC);
+		break;
+	case V4L2_CID_PRIVATE_VCR_HACK:
+		btv->opt_vcr_hack = c->value;
+		break;
+	case V4L2_CID_PRIVATE_WHITECRUSH_UPPER:
+		btv->opt_whitecrush_upper = c->value;
+		btwrite(c->value, BT848_WC_UP);
+		break;
+	case V4L2_CID_PRIVATE_WHITECRUSH_LOWER:
+		btv->opt_whitecrush_lower = c->value;
+		btwrite(c->value, BT848_WC_DOWN);
+		break;
+	case V4L2_CID_PRIVATE_UV_RATIO:
+		btv->opt_uv_ratio = c->value;
+		bt848_sat(btv, btv->saturation);
+		break;
+	case V4L2_CID_PRIVATE_FULL_LUMA_RANGE:
+		btv->opt_full_luma_range = c->value;
+		btaor((c->value<<7), ~BT848_OFORM_RANGE, BT848_OFORM);
+		break;
+	case V4L2_CID_PRIVATE_CORING:
+		btv->opt_coring = c->value;
+		btaor((c->value<<5), ~BT848_OFORM_CORE32, BT848_OFORM);
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+void bttv_gpio_tracking(struct bttv *btv, char *comment)
+{
+	unsigned int outbits, data;
+	outbits = btread(BT848_GPIO_OUT_EN);
+	data    = btread(BT848_GPIO_DATA);
+	pr_debug("%d: gpio: en=%08x, out=%08x in=%08x [%s]\n",
+		 btv->c.nr, outbits, data & outbits, data & ~outbits, comment);
+}
+
+static void bttv_field_count(struct bttv *btv)
+{
+	int need_count = 0;
+
+	if (btv->users)
+		need_count++;
+
+	if (need_count) {
+		/* start field counter */
+		btor(BT848_INT_VSYNC,BT848_INT_MASK);
+	} else {
+		/* stop field counter */
+		btand(~BT848_INT_VSYNC,BT848_INT_MASK);
+		btv->field_count = 0;
+	}
+}
+
+static const struct bttv_format*
+format_by_fourcc(int fourcc)
+{
+	unsigned int i;
+
+	for (i = 0; i < FORMATS; i++) {
+		if (-1 == formats[i].fourcc)
+			continue;
+		if (formats[i].fourcc == fourcc)
+			return formats+i;
+	}
+	return NULL;
+}
+
+/* ----------------------------------------------------------------------- */
+/* misc helpers                                                            */
+
+static int
+bttv_switch_overlay(struct bttv *btv, struct bttv_fh *fh,
+		    struct bttv_buffer *new)
+{
+	struct bttv_buffer *old;
+	unsigned long flags;
+	int retval = 0;
+
+	dprintk("switch_overlay: enter [new=%p]\n", new);
+	if (new)
+		new->vb.state = VIDEOBUF_DONE;
+	spin_lock_irqsave(&btv->s_lock,flags);
+	old = btv->screen;
+	btv->screen = new;
+	btv->loop_irq |= 1;
+	bttv_set_dma(btv, 0x03);
+	spin_unlock_irqrestore(&btv->s_lock,flags);
+	if (NULL != old) {
+		dprintk("switch_overlay: old=%p state is %d\n",
+			old, old->vb.state);
+		bttv_dma_free(&fh->cap,btv, old);
+		kfree(old);
+	}
+	if (NULL == new)
+		free_btres_lock(btv,fh,RESOURCE_OVERLAY);
+	dprintk("switch_overlay: done\n");
+	return retval;
+}
+
+/* ----------------------------------------------------------------------- */
+/* video4linux (1) interface                                               */
+
+static int bttv_prepare_buffer(struct videobuf_queue *q,struct bttv *btv,
+			       struct bttv_buffer *buf,
+			       const struct bttv_format *fmt,
+			       unsigned int width, unsigned int height,
+			       enum v4l2_field field)
+{
+	struct bttv_fh *fh = q->priv_data;
+	int redo_dma_risc = 0;
+	struct bttv_crop c;
+	int norm;
+	int rc;
+
+	/* check settings */
+	if (NULL == fmt)
+		return -EINVAL;
+	if (fmt->btformat == BT848_COLOR_FMT_RAW) {
+		width  = RAW_BPL;
+		height = RAW_LINES*2;
+		if (width*height > buf->vb.bsize)
+			return -EINVAL;
+		buf->vb.size = buf->vb.bsize;
+
+		/* Make sure tvnorm and vbi_end remain consistent
+		   until we're done. */
+
+		norm = btv->tvnorm;
+
+		/* In this mode capturing always starts at defrect.top
+		   (default VDELAY), ignoring cropping parameters. */
+		if (btv->vbi_end > bttv_tvnorms[norm].cropcap.defrect.top) {
+			return -EINVAL;
+		}
+
+		c.rect = bttv_tvnorms[norm].cropcap.defrect;
+	} else {
+		norm = btv->tvnorm;
+		c = btv->crop[!!fh->do_crop];
+
+		if (width < c.min_scaled_width ||
+		    width > c.max_scaled_width ||
+		    height < c.min_scaled_height)
+			return -EINVAL;
+
+		switch (field) {
+		case V4L2_FIELD_TOP:
+		case V4L2_FIELD_BOTTOM:
+		case V4L2_FIELD_ALTERNATE:
+			/* btv->crop counts frame lines. Max. scale
+			   factor is 16:1 for frames, 8:1 for fields. */
+			if (height * 2 > c.max_scaled_height)
+				return -EINVAL;
+			break;
+
+		default:
+			if (height > c.max_scaled_height)
+				return -EINVAL;
+			break;
+		}
+
+		buf->vb.size = (width * height * fmt->depth) >> 3;
+		if (0 != buf->vb.baddr  &&  buf->vb.bsize < buf->vb.size)
+			return -EINVAL;
+	}
+
+	/* alloc + fill struct bttv_buffer (if changed) */
+	if (buf->vb.width != width || buf->vb.height != height ||
+	    buf->vb.field != field ||
+	    buf->tvnorm != norm || buf->fmt != fmt ||
+	    buf->crop.top != c.rect.top ||
+	    buf->crop.left != c.rect.left ||
+	    buf->crop.width != c.rect.width ||
+	    buf->crop.height != c.rect.height) {
+		buf->vb.width  = width;
+		buf->vb.height = height;
+		buf->vb.field  = field;
+		buf->tvnorm    = norm;
+		buf->fmt       = fmt;
+		buf->crop      = c.rect;
+		redo_dma_risc = 1;
+	}
+
+	/* alloc risc memory */
+	if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
+		redo_dma_risc = 1;
+		if (0 != (rc = videobuf_iolock(q,&buf->vb,&btv->fbuf)))
+			goto fail;
+	}
+
+	if (redo_dma_risc)
+		if (0 != (rc = bttv_buffer_risc(btv,buf)))
+			goto fail;
+
+	buf->vb.state = VIDEOBUF_PREPARED;
+	return 0;
+
+ fail:
+	bttv_dma_free(q,btv,buf);
+	return rc;
+}
+
+static int
+buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
+{
+	struct bttv_fh *fh = q->priv_data;
+
+	*size = fh->fmt->depth*fh->width*fh->height >> 3;
+	if (0 == *count)
+		*count = gbuffers;
+	if (*size * *count > gbuffers * gbufsize)
+		*count = (gbuffers * gbufsize) / *size;
+	return 0;
+}
+
+static int
+buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
+	       enum v4l2_field field)
+{
+	struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
+	struct bttv_fh *fh = q->priv_data;
+
+	return bttv_prepare_buffer(q,fh->btv, buf, fh->fmt,
+				   fh->width, fh->height, field);
+}
+
+static void
+buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
+{
+	struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
+	struct bttv_fh *fh = q->priv_data;
+	struct bttv    *btv = fh->btv;
+
+	buf->vb.state = VIDEOBUF_QUEUED;
+	list_add_tail(&buf->vb.queue,&btv->capture);
+	if (!btv->curr.frame_irq) {
+		btv->loop_irq |= 1;
+		bttv_set_dma(btv, 0x03);
+	}
+}
+
+static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
+{
+	struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
+	struct bttv_fh *fh = q->priv_data;
+
+	bttv_dma_free(q,fh->btv,buf);
+}
+
+static struct videobuf_queue_ops bttv_video_qops = {
+	.buf_setup    = buffer_setup,
+	.buf_prepare  = buffer_prepare,
+	.buf_queue    = buffer_queue,
+	.buf_release  = buffer_release,
+};
+
+static int bttv_s_std(struct file *file, void *priv, v4l2_std_id *id)
+{
+	struct bttv_fh *fh  = priv;
+	struct bttv *btv = fh->btv;
+	unsigned int i;
+	int err;
+
+	err = v4l2_prio_check(&btv->prio, fh->prio);
+	if (err)
+		goto err;
+
+	for (i = 0; i < BTTV_TVNORMS; i++)
+		if (*id & bttv_tvnorms[i].v4l2_id)
+			break;
+	if (i == BTTV_TVNORMS) {
+		err = -EINVAL;
+		goto err;
+	}
+
+	set_tvnorm(btv, i);
+
+err:
+
+	return err;
+}
+
+static int bttv_querystd(struct file *file, void *f, v4l2_std_id *id)
+{
+	struct bttv_fh *fh = f;
+	struct bttv *btv = fh->btv;
+
+	if (btread(BT848_DSTATUS) & BT848_DSTATUS_NUML)
+		*id = V4L2_STD_625_50;
+	else
+		*id = V4L2_STD_525_60;
+	return 0;
+}
+
+static int bttv_enum_input(struct file *file, void *priv,
+					struct v4l2_input *i)
+{
+	struct bttv_fh *fh = priv;
+	struct bttv *btv = fh->btv;
+	int rc = 0;
+
+	if (i->index >= bttv_tvcards[btv->c.type].video_inputs) {
+		rc = -EINVAL;
+		goto err;
+	}
+
+	i->type     = V4L2_INPUT_TYPE_CAMERA;
+	i->audioset = 1;
+
+	if (btv->tuner_type != TUNER_ABSENT && i->index == 0) {
+		sprintf(i->name, "Television");
+		i->type  = V4L2_INPUT_TYPE_TUNER;
+		i->tuner = 0;
+	} else if (i->index == btv->svhs) {
+		sprintf(i->name, "S-Video");
+	} else {
+		sprintf(i->name, "Composite%d", i->index);
+	}
+
+	if (i->index == btv->input) {
+		__u32 dstatus = btread(BT848_DSTATUS);
+		if (0 == (dstatus & BT848_DSTATUS_PRES))
+			i->status |= V4L2_IN_ST_NO_SIGNAL;
+		if (0 == (dstatus & BT848_DSTATUS_HLOC))
+			i->status |= V4L2_IN_ST_NO_H_LOCK;
+	}
+
+	i->std = BTTV_NORMS;
+
+err:
+
+	return rc;
+}
+
+static int bttv_g_input(struct file *file, void *priv, unsigned int *i)
+{
+	struct bttv_fh *fh = priv;
+	struct bttv *btv = fh->btv;
+
+	*i = btv->input;
+
+	return 0;
+}
+
+static int bttv_s_input(struct file *file, void *priv, unsigned int i)
+{
+	struct bttv_fh *fh  = priv;
+	struct bttv *btv = fh->btv;
+
+	int err;
+
+	err = v4l2_prio_check(&btv->prio, fh->prio);
+	if (unlikely(err))
+		goto err;
+
+	if (i > bttv_tvcards[btv->c.type].video_inputs) {
+		err = -EINVAL;
+		goto err;
+	}
+
+	set_input(btv, i, btv->tvnorm);
+
+err:
+	return 0;
+}
+
+static int bttv_s_tuner(struct file *file, void *priv,
+					struct v4l2_tuner *t)
+{
+	struct bttv_fh *fh  = priv;
+	struct bttv *btv = fh->btv;
+	int err;
+
+	if (unlikely(0 != t->index))
+		return -EINVAL;
+
+	if (unlikely(btv->tuner_type == TUNER_ABSENT)) {
+		err = -EINVAL;
+		goto err;
+	}
+
+	err = v4l2_prio_check(&btv->prio, fh->prio);
+	if (unlikely(err))
+		goto err;
+
+	bttv_call_all(btv, tuner, s_tuner, t);
+
+	if (btv->audio_mode_gpio)
+		btv->audio_mode_gpio(btv, t, 1);
+
+err:
+
+	return 0;
+}
+
+static int bttv_g_frequency(struct file *file, void *priv,
+					struct v4l2_frequency *f)
+{
+	struct bttv_fh *fh  = priv;
+	struct bttv *btv = fh->btv;
+
+	f->type = btv->radio_user ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
+	f->frequency = btv->freq;
+
+	return 0;
+}
+
+static int bttv_s_frequency(struct file *file, void *priv,
+					struct v4l2_frequency *f)
+{
+	struct bttv_fh *fh  = priv;
+	struct bttv *btv = fh->btv;
+	int err;
+
+	if (unlikely(f->tuner != 0))
+		return -EINVAL;
+
+	err = v4l2_prio_check(&btv->prio, fh->prio);
+	if (unlikely(err))
+		goto err;
+
+	if (unlikely(f->type != (btv->radio_user
+		? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV))) {
+		err = -EINVAL;
+		goto err;
+	}
+	btv->freq = f->frequency;
+	bttv_call_all(btv, tuner, s_frequency, f);
+	if (btv->has_matchbox && btv->radio_user)
+		tea5757_set_freq(btv, btv->freq);
+err:
+
+	return 0;
+}
+
+static int bttv_log_status(struct file *file, void *f)
+{
+	struct bttv_fh *fh  = f;
+	struct bttv *btv = fh->btv;
+
+	bttv_call_all(btv, core, log_status);
+	return 0;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int bttv_g_register(struct file *file, void *f,
+					struct v4l2_dbg_register *reg)
+{
+	struct bttv_fh *fh = f;
+	struct bttv *btv = fh->btv;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	if (!v4l2_chip_match_host(&reg->match))
+		return -EINVAL;
+
+	/* bt848 has a 12-bit register space */
+	reg->reg &= 0xfff;
+	reg->val = btread(reg->reg);
+	reg->size = 1;
+
+	return 0;
+}
+
+static int bttv_s_register(struct file *file, void *f,
+					struct v4l2_dbg_register *reg)
+{
+	struct bttv_fh *fh = f;
+	struct bttv *btv = fh->btv;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	if (!v4l2_chip_match_host(&reg->match))
+		return -EINVAL;
+
+	/* bt848 has a 12-bit register space */
+	reg->reg &= 0xfff;
+	btwrite(reg->val, reg->reg);
+
+	return 0;
+}
+#endif
+
+/* Given cropping boundaries b and the scaled width and height of a
+   single field or frame, which must not exceed hardware limits, this
+   function adjusts the cropping parameters c. */
+static void
+bttv_crop_adjust	(struct bttv_crop *             c,
+			 const struct v4l2_rect *	b,
+			 __s32                          width,
+			 __s32                          height,
+			 enum v4l2_field                field)
+{
+	__s32 frame_height = height << !V4L2_FIELD_HAS_BOTH(field);
+	__s32 max_left;
+	__s32 max_top;
+
+	if (width < c->min_scaled_width) {
+		/* Max. hor. scale factor 16:1. */
+		c->rect.width = width * 16;
+	} else if (width > c->max_scaled_width) {
+		/* Min. hor. scale factor 1:1. */
+		c->rect.width = width;
+
+		max_left = b->left + b->width - width;
+		max_left = min(max_left, (__s32) MAX_HDELAY);
+		if (c->rect.left > max_left)
+			c->rect.left = max_left;
+	}
+
+	if (height < c->min_scaled_height) {
+		/* Max. vert. scale factor 16:1, single fields 8:1. */
+		c->rect.height = height * 16;
+	} else if (frame_height > c->max_scaled_height) {
+		/* Min. vert. scale factor 1:1.
+		   Top and height count field lines times two. */
+		c->rect.height = (frame_height + 1) & ~1;
+
+		max_top = b->top + b->height - c->rect.height;
+		if (c->rect.top > max_top)
+			c->rect.top = max_top;
+	}
+
+	bttv_crop_calc_limits(c);
+}
+
+/* Returns an error if scaling to a frame or single field with the given
+   width and height is not possible with the current cropping parameters
+   and width aligned according to width_mask. If adjust_size is TRUE the
+   function may adjust the width and/or height instead, rounding width
+   to (width + width_bias) & width_mask. If adjust_crop is TRUE it may
+   also adjust the current cropping parameters to get closer to the
+   desired image size. */
+static int
+limit_scaled_size_lock       (struct bttv_fh *               fh,
+			 __s32 *                        width,
+			 __s32 *                        height,
+			 enum v4l2_field                field,
+			 unsigned int			width_mask,
+			 unsigned int			width_bias,
+			 int                            adjust_size,
+			 int                            adjust_crop)
+{
+	struct bttv *btv = fh->btv;
+	const struct v4l2_rect *b;
+	struct bttv_crop *c;
+	__s32 min_width;
+	__s32 min_height;
+	__s32 max_width;
+	__s32 max_height;
+	int rc;
+
+	BUG_ON((int) width_mask >= 0 ||
+	       width_bias >= (unsigned int) -width_mask);
+
+	/* Make sure tvnorm, vbi_end and the current cropping parameters
+	   remain consistent until we're done. */
+
+	b = &bttv_tvnorms[btv->tvnorm].cropcap.bounds;
+
+	/* Do crop - use current, don't - use default parameters. */
+	c = &btv->crop[!!fh->do_crop];
+
+	if (fh->do_crop
+	    && adjust_size
+	    && adjust_crop
+	    && !locked_btres(btv, VIDEO_RESOURCES)) {
+		min_width = 48;
+		min_height = 32;
+
+		/* We cannot scale up. When the scaled image is larger
+		   than crop.rect we adjust the crop.rect as required
+		   by the V4L2 spec, hence cropcap.bounds are our limit. */
+		max_width = min(b->width, (__s32) MAX_HACTIVE);
+		max_height = b->height;
+
+		/* We cannot capture the same line as video and VBI data.
+		   Note btv->vbi_end is really a minimum, see
+		   bttv_vbi_try_fmt(). */
+		if (btv->vbi_end > b->top) {
+			max_height -= btv->vbi_end - b->top;
+			rc = -EBUSY;
+			if (min_height > max_height)
+				goto fail;
+		}
+	} else {
+		rc = -EBUSY;
+		if (btv->vbi_end > c->rect.top)
+			goto fail;
+
+		min_width  = c->min_scaled_width;
+		min_height = c->min_scaled_height;
+		max_width  = c->max_scaled_width;
+		max_height = c->max_scaled_height;
+
+		adjust_crop = 0;
+	}
+
+	min_width = (min_width - width_mask - 1) & width_mask;
+	max_width = max_width & width_mask;
+
+	/* Max. scale factor is 16:1 for frames, 8:1 for fields. */
+	min_height = min_height;
+	/* Min. scale factor is 1:1. */
+	max_height >>= !V4L2_FIELD_HAS_BOTH(field);
+
+	if (adjust_size) {
+		*width = clamp(*width, min_width, max_width);
+		*height = clamp(*height, min_height, max_height);
+
+		/* Round after clamping to avoid overflow. */
+		*width = (*width + width_bias) & width_mask;
+
+		if (adjust_crop) {
+			bttv_crop_adjust(c, b, *width, *height, field);
+
+			if (btv->vbi_end > c->rect.top) {
+				/* Move the crop window out of the way. */
+				c->rect.top = btv->vbi_end;
+			}
+		}
+	} else {
+		rc = -EINVAL;
+		if (*width  < min_width ||
+		    *height < min_height ||
+		    *width  > max_width ||
+		    *height > max_height ||
+		    0 != (*width & ~width_mask))
+			goto fail;
+	}
+
+	rc = 0; /* success */
+
+ fail:
+
+	return rc;
+}
+
+/* Returns an error if the given overlay window dimensions are not
+   possible with the current cropping parameters. If adjust_size is
+   TRUE the function may adjust the window width and/or height
+   instead, however it always rounds the horizontal position and
+   width as btcx_align() does. If adjust_crop is TRUE the function
+   may also adjust the current cropping parameters to get closer
+   to the desired window size. */
+static int
+verify_window_lock		(struct bttv_fh *               fh,
+			 struct v4l2_window *           win,
+			 int                            adjust_size,
+			 int                            adjust_crop)
+{
+	enum v4l2_field field;
+	unsigned int width_mask;
+	int rc;
+
+	if (win->w.width  < 48 || win->w.height < 32)
+		return -EINVAL;
+	if (win->clipcount > 2048)
+		return -EINVAL;
+
+	field = win->field;
+
+	if (V4L2_FIELD_ANY == field) {
+		__s32 height2;
+
+		height2 = fh->btv->crop[!!fh->do_crop].rect.height >> 1;
+		field = (win->w.height > height2)
+			? V4L2_FIELD_INTERLACED
+			: V4L2_FIELD_TOP;
+	}
+	switch (field) {
+	case V4L2_FIELD_TOP:
+	case V4L2_FIELD_BOTTOM:
+	case V4L2_FIELD_INTERLACED:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* 4-byte alignment. */
+	if (NULL == fh->ovfmt)
+		return -EINVAL;
+	width_mask = ~0;
+	switch (fh->ovfmt->depth) {
+	case 8:
+	case 24:
+		width_mask = ~3;
+		break;
+	case 16:
+		width_mask = ~1;
+		break;
+	case 32:
+		break;
+	default:
+		BUG();
+	}
+
+	win->w.width -= win->w.left & ~width_mask;
+	win->w.left = (win->w.left - width_mask - 1) & width_mask;
+
+	rc = limit_scaled_size_lock(fh, &win->w.width, &win->w.height,
+			       field, width_mask,
+			       /* width_bias: round down */ 0,
+			       adjust_size, adjust_crop);
+	if (0 != rc)
+		return rc;
+
+	win->field = field;
+	return 0;
+}
+
+static int setup_window_lock(struct bttv_fh *fh, struct bttv *btv,
+			struct v4l2_window *win, int fixup)
+{
+	struct v4l2_clip *clips = NULL;
+	int n,size,retval = 0;
+
+	if (NULL == fh->ovfmt)
+		return -EINVAL;
+	if (!(fh->ovfmt->flags & FORMAT_FLAGS_PACKED))
+		return -EINVAL;
+	retval = verify_window_lock(fh, win,
+			       /* adjust_size */ fixup,
+			       /* adjust_crop */ fixup);
+	if (0 != retval)
+		return retval;
+
+	/* copy clips  --  luckily v4l1 + v4l2 are binary
+	   compatible here ...*/
+	n = win->clipcount;
+	size = sizeof(*clips)*(n+4);
+	clips = kmalloc(size,GFP_KERNEL);
+	if (NULL == clips)
+		return -ENOMEM;
+	if (n > 0) {
+		if (copy_from_user(clips,win->clips,sizeof(struct v4l2_clip)*n)) {
+			kfree(clips);
+			return -EFAULT;
+		}
+	}
+
+	/* clip against screen */
+	if (NULL != btv->fbuf.base)
+		n = btcx_screen_clips(btv->fbuf.fmt.width, btv->fbuf.fmt.height,
+				      &win->w, clips, n);
+	btcx_sort_clips(clips,n);
+
+	/* 4-byte alignments */
+	switch (fh->ovfmt->depth) {
+	case 8:
+	case 24:
+		btcx_align(&win->w, clips, n, 3);
+		break;
+	case 16:
+		btcx_align(&win->w, clips, n, 1);
+		break;
+	case 32:
+		/* no alignment fixups needed */
+		break;
+	default:
+		BUG();
+	}
+
+	kfree(fh->ov.clips);
+	fh->ov.clips    = clips;
+	fh->ov.nclips   = n;
+
+	fh->ov.w        = win->w;
+	fh->ov.field    = win->field;
+	fh->ov.setup_ok = 1;
+
+	btv->init.ov.w.width   = win->w.width;
+	btv->init.ov.w.height  = win->w.height;
+	btv->init.ov.field     = win->field;
+
+	/* update overlay if needed */
+	retval = 0;
+	if (check_btres(fh, RESOURCE_OVERLAY)) {
+		struct bttv_buffer *new;
+
+		new = videobuf_sg_alloc(sizeof(*new));
+		new->crop = btv->crop[!!fh->do_crop].rect;
+		bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
+		retval = bttv_switch_overlay(btv,fh,new);
+	}
+	return retval;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static struct videobuf_queue* bttv_queue(struct bttv_fh *fh)
+{
+	struct videobuf_queue* q = NULL;
+
+	switch (fh->type) {
+	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+		q = &fh->cap;
+		break;
+	case V4L2_BUF_TYPE_VBI_CAPTURE:
+		q = &fh->vbi;
+		break;
+	default:
+		BUG();
+	}
+	return q;
+}
+
+static int bttv_resource(struct bttv_fh *fh)
+{
+	int res = 0;
+
+	switch (fh->type) {
+	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+		res = RESOURCE_VIDEO_STREAM;
+		break;
+	case V4L2_BUF_TYPE_VBI_CAPTURE:
+		res = RESOURCE_VBI;
+		break;
+	default:
+		BUG();
+	}
+	return res;
+}
+
+static int bttv_switch_type(struct bttv_fh *fh, enum v4l2_buf_type type)
+{
+	struct videobuf_queue *q = bttv_queue(fh);
+	int res = bttv_resource(fh);
+
+	if (check_btres(fh,res))
+		return -EBUSY;
+	if (videobuf_queue_is_busy(q))
+		return -EBUSY;
+	fh->type = type;
+	return 0;
+}
+
+static void
+pix_format_set_size     (struct v4l2_pix_format *       f,
+			 const struct bttv_format *     fmt,
+			 unsigned int                   width,
+			 unsigned int                   height)
+{
+	f->width = width;
+	f->height = height;
+
+	if (fmt->flags & FORMAT_FLAGS_PLANAR) {
+		f->bytesperline = width; /* Y plane */
+		f->sizeimage = (width * height * fmt->depth) >> 3;
+	} else {
+		f->bytesperline = (width * fmt->depth) >> 3;
+		f->sizeimage = height * f->bytesperline;
+	}
+}
+
+static int bttv_g_fmt_vid_cap(struct file *file, void *priv,
+					struct v4l2_format *f)
+{
+	struct bttv_fh *fh  = priv;
+
+	pix_format_set_size(&f->fmt.pix, fh->fmt,
+				fh->width, fh->height);
+	f->fmt.pix.field        = fh->cap.field;
+	f->fmt.pix.pixelformat  = fh->fmt->fourcc;
+
+	return 0;
+}
+
+static int bttv_g_fmt_vid_overlay(struct file *file, void *priv,
+					struct v4l2_format *f)
+{
+	struct bttv_fh *fh  = priv;
+
+	f->fmt.win.w     = fh->ov.w;
+	f->fmt.win.field = fh->ov.field;
+
+	return 0;
+}
+
+static int bttv_try_fmt_vid_cap(struct file *file, void *priv,
+						struct v4l2_format *f)
+{
+	const struct bttv_format *fmt;
+	struct bttv_fh *fh = priv;
+	struct bttv *btv = fh->btv;
+	enum v4l2_field field;
+	__s32 width, height;
+	int rc;
+
+	fmt = format_by_fourcc(f->fmt.pix.pixelformat);
+	if (NULL == fmt)
+		return -EINVAL;
+
+	field = f->fmt.pix.field;
+
+	if (V4L2_FIELD_ANY == field) {
+		__s32 height2;
+
+		height2 = btv->crop[!!fh->do_crop].rect.height >> 1;
+		field = (f->fmt.pix.height > height2)
+			? V4L2_FIELD_INTERLACED
+			: V4L2_FIELD_BOTTOM;
+	}
+
+	if (V4L2_FIELD_SEQ_BT == field)
+		field = V4L2_FIELD_SEQ_TB;
+
+	switch (field) {
+	case V4L2_FIELD_TOP:
+	case V4L2_FIELD_BOTTOM:
+	case V4L2_FIELD_ALTERNATE:
+	case V4L2_FIELD_INTERLACED:
+		break;
+	case V4L2_FIELD_SEQ_TB:
+		if (fmt->flags & FORMAT_FLAGS_PLANAR)
+			return -EINVAL;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	width = f->fmt.pix.width;
+	height = f->fmt.pix.height;
+
+	rc = limit_scaled_size_lock(fh, &width, &height, field,
+			       /* width_mask: 4 pixels */ ~3,
+			       /* width_bias: nearest */ 2,
+			       /* adjust_size */ 1,
+			       /* adjust_crop */ 0);
+	if (0 != rc)
+		return rc;
+
+	/* update data for the application */
+	f->fmt.pix.field = field;
+	pix_format_set_size(&f->fmt.pix, fmt, width, height);
+
+	return 0;
+}
+
+static int bttv_try_fmt_vid_overlay(struct file *file, void *priv,
+						struct v4l2_format *f)
+{
+	struct bttv_fh *fh = priv;
+
+	return verify_window_lock(fh, &f->fmt.win,
+			/* adjust_size */ 1,
+			/* adjust_crop */ 0);
+}
+
+static int bttv_s_fmt_vid_cap(struct file *file, void *priv,
+				struct v4l2_format *f)
+{
+	int retval;
+	const struct bttv_format *fmt;
+	struct bttv_fh *fh = priv;
+	struct bttv *btv = fh->btv;
+	__s32 width, height;
+	enum v4l2_field field;
+
+	retval = bttv_switch_type(fh, f->type);
+	if (0 != retval)
+		return retval;
+
+	retval = bttv_try_fmt_vid_cap(file, priv, f);
+	if (0 != retval)
+		return retval;
+
+	width = f->fmt.pix.width;
+	height = f->fmt.pix.height;
+	field = f->fmt.pix.field;
+
+	retval = limit_scaled_size_lock(fh, &width, &height, f->fmt.pix.field,
+			       /* width_mask: 4 pixels */ ~3,
+			       /* width_bias: nearest */ 2,
+			       /* adjust_size */ 1,
+			       /* adjust_crop */ 1);
+	if (0 != retval)
+		return retval;
+
+	f->fmt.pix.field = field;
+
+	fmt = format_by_fourcc(f->fmt.pix.pixelformat);
+
+	/* update our state informations */
+	fh->fmt              = fmt;
+	fh->cap.field        = f->fmt.pix.field;
+	fh->cap.last         = V4L2_FIELD_NONE;
+	fh->width            = f->fmt.pix.width;
+	fh->height           = f->fmt.pix.height;
+	btv->init.fmt        = fmt;
+	btv->init.width      = f->fmt.pix.width;
+	btv->init.height     = f->fmt.pix.height;
+
+	return 0;
+}
+
+static int bttv_s_fmt_vid_overlay(struct file *file, void *priv,
+				struct v4l2_format *f)
+{
+	struct bttv_fh *fh = priv;
+	struct bttv *btv = fh->btv;
+
+	if (no_overlay > 0) {
+		pr_err("V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
+		return -EINVAL;
+	}
+
+	return setup_window_lock(fh, btv, &f->fmt.win, 1);
+}
+
+static int bttv_querycap(struct file *file, void  *priv,
+				struct v4l2_capability *cap)
+{
+	struct bttv_fh *fh = priv;
+	struct bttv *btv = fh->btv;
+
+	if (0 == v4l2)
+		return -EINVAL;
+
+	strlcpy(cap->driver, "bttv", sizeof(cap->driver));
+	strlcpy(cap->card, btv->video_dev->name, sizeof(cap->card));
+	snprintf(cap->bus_info, sizeof(cap->bus_info),
+		 "PCI:%s", pci_name(btv->c.pci));
+	cap->capabilities =
+		V4L2_CAP_VIDEO_CAPTURE |
+		V4L2_CAP_VBI_CAPTURE |
+		V4L2_CAP_READWRITE |
+		V4L2_CAP_STREAMING;
+	if (no_overlay <= 0)
+		cap->capabilities |= V4L2_CAP_VIDEO_OVERLAY;
+
+	/*
+	 * No need to lock here: those vars are initialized during board
+	 * probe and remains untouched during the rest of the driver lifecycle
+	 */
+	if (btv->has_saa6588)
+		cap->capabilities |= V4L2_CAP_RDS_CAPTURE;
+	if (btv->tuner_type != TUNER_ABSENT)
+		cap->capabilities |= V4L2_CAP_TUNER;
+	return 0;
+}
+
+static int bttv_enum_fmt_cap_ovr(struct v4l2_fmtdesc *f)
+{
+	int index = -1, i;
+
+	for (i = 0; i < FORMATS; i++) {
+		if (formats[i].fourcc != -1)
+			index++;
+		if ((unsigned int)index == f->index)
+			break;
+	}
+	if (FORMATS == i)
+		return -EINVAL;
+
+	f->pixelformat = formats[i].fourcc;
+	strlcpy(f->description, formats[i].name, sizeof(f->description));
+
+	return i;
+}
+
+static int bttv_enum_fmt_vid_cap(struct file *file, void  *priv,
+				struct v4l2_fmtdesc *f)
+{
+	int rc = bttv_enum_fmt_cap_ovr(f);
+
+	if (rc < 0)
+		return rc;
+
+	return 0;
+}
+
+static int bttv_enum_fmt_vid_overlay(struct file *file, void  *priv,
+					struct v4l2_fmtdesc *f)
+{
+	int rc;
+
+	if (no_overlay > 0) {
+		pr_err("V4L2_BUF_TYPE_VIDEO_OVERLAY: no_overlay\n");
+		return -EINVAL;
+	}
+
+	rc = bttv_enum_fmt_cap_ovr(f);
+
+	if (rc < 0)
+		return rc;
+
+	if (!(formats[rc].flags & FORMAT_FLAGS_PACKED))
+		return -EINVAL;
+
+	return 0;
+}
+
+static int bttv_g_fbuf(struct file *file, void *f,
+				struct v4l2_framebuffer *fb)
+{
+	struct bttv_fh *fh = f;
+	struct bttv *btv = fh->btv;
+
+	*fb = btv->fbuf;
+	fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING;
+	if (fh->ovfmt)
+		fb->fmt.pixelformat  = fh->ovfmt->fourcc;
+	return 0;
+}
+
+static int bttv_overlay(struct file *file, void *f, unsigned int on)
+{
+	struct bttv_fh *fh = f;
+	struct bttv *btv = fh->btv;
+	struct bttv_buffer *new;
+	int retval = 0;
+
+	if (on) {
+		/* verify args */
+		if (unlikely(!btv->fbuf.base)) {
+			return -EINVAL;
+		}
+		if (unlikely(!fh->ov.setup_ok)) {
+			dprintk("%d: overlay: !setup_ok\n", btv->c.nr);
+			retval = -EINVAL;
+		}
+		if (retval)
+			return retval;
+	}
+
+	if (!check_alloc_btres_lock(btv, fh, RESOURCE_OVERLAY))
+		return -EBUSY;
+
+	if (on) {
+		fh->ov.tvnorm = btv->tvnorm;
+		new = videobuf_sg_alloc(sizeof(*new));
+		new->crop = btv->crop[!!fh->do_crop].rect;
+		bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
+	} else {
+		new = NULL;
+	}
+
+	/* switch over */
+	retval = bttv_switch_overlay(btv, fh, new);
+	return retval;
+}
+
+static int bttv_s_fbuf(struct file *file, void *f,
+				struct v4l2_framebuffer *fb)
+{
+	struct bttv_fh *fh = f;
+	struct bttv *btv = fh->btv;
+	const struct bttv_format *fmt;
+	int retval;
+
+	if (!capable(CAP_SYS_ADMIN) &&
+		!capable(CAP_SYS_RAWIO))
+		return -EPERM;
+
+	/* check args */
+	fmt = format_by_fourcc(fb->fmt.pixelformat);
+	if (NULL == fmt)
+		return -EINVAL;
+	if (0 == (fmt->flags & FORMAT_FLAGS_PACKED))
+		return -EINVAL;
+
+	retval = -EINVAL;
+	if (fb->flags & V4L2_FBUF_FLAG_OVERLAY) {
+		__s32 width = fb->fmt.width;
+		__s32 height = fb->fmt.height;
+
+		retval = limit_scaled_size_lock(fh, &width, &height,
+					   V4L2_FIELD_INTERLACED,
+					   /* width_mask */ ~3,
+					   /* width_bias */ 2,
+					   /* adjust_size */ 0,
+					   /* adjust_crop */ 0);
+		if (0 != retval)
+			return retval;
+	}
+
+	/* ok, accept it */
+	btv->fbuf.base       = fb->base;
+	btv->fbuf.fmt.width  = fb->fmt.width;
+	btv->fbuf.fmt.height = fb->fmt.height;
+	if (0 != fb->fmt.bytesperline)
+		btv->fbuf.fmt.bytesperline = fb->fmt.bytesperline;
+	else
+		btv->fbuf.fmt.bytesperline = btv->fbuf.fmt.width*fmt->depth/8;
+
+	retval = 0;
+	fh->ovfmt = fmt;
+	btv->init.ovfmt = fmt;
+	if (fb->flags & V4L2_FBUF_FLAG_OVERLAY) {
+		fh->ov.w.left   = 0;
+		fh->ov.w.top    = 0;
+		fh->ov.w.width  = fb->fmt.width;
+		fh->ov.w.height = fb->fmt.height;
+		btv->init.ov.w.width  = fb->fmt.width;
+		btv->init.ov.w.height = fb->fmt.height;
+			kfree(fh->ov.clips);
+		fh->ov.clips = NULL;
+		fh->ov.nclips = 0;
+
+		if (check_btres(fh, RESOURCE_OVERLAY)) {
+			struct bttv_buffer *new;
+
+			new = videobuf_sg_alloc(sizeof(*new));
+			new->crop = btv->crop[!!fh->do_crop].rect;
+			bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
+			retval = bttv_switch_overlay(btv, fh, new);
+		}
+	}
+	return retval;
+}
+
+static int bttv_reqbufs(struct file *file, void *priv,
+				struct v4l2_requestbuffers *p)
+{
+	struct bttv_fh *fh = priv;
+	return videobuf_reqbufs(bttv_queue(fh), p);
+}
+
+static int bttv_querybuf(struct file *file, void *priv,
+				struct v4l2_buffer *b)
+{
+	struct bttv_fh *fh = priv;
+	return videobuf_querybuf(bttv_queue(fh), b);
+}
+
+static int bttv_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
+{
+	struct bttv_fh *fh = priv;
+	struct bttv *btv = fh->btv;
+	int res = bttv_resource(fh);
+
+	if (!check_alloc_btres_lock(btv, fh, res))
+		return -EBUSY;
+
+	return videobuf_qbuf(bttv_queue(fh), b);
+}
+
+static int bttv_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
+{
+	struct bttv_fh *fh = priv;
+	return videobuf_dqbuf(bttv_queue(fh), b,
+			file->f_flags & O_NONBLOCK);
+}
+
+static int bttv_streamon(struct file *file, void *priv,
+					enum v4l2_buf_type type)
+{
+	struct bttv_fh *fh = priv;
+	struct bttv *btv = fh->btv;
+	int res = bttv_resource(fh);
+
+	if (!check_alloc_btres_lock(btv, fh, res))
+		return -EBUSY;
+	return videobuf_streamon(bttv_queue(fh));
+}
+
+
+static int bttv_streamoff(struct file *file, void *priv,
+					enum v4l2_buf_type type)
+{
+	struct bttv_fh *fh = priv;
+	struct bttv *btv = fh->btv;
+	int retval;
+	int res = bttv_resource(fh);
+
+
+	retval = videobuf_streamoff(bttv_queue(fh));
+	if (retval < 0)
+		return retval;
+	free_btres_lock(btv, fh, res);
+	return 0;
+}
+
+static int bttv_queryctrl(struct file *file, void *priv,
+					struct v4l2_queryctrl *c)
+{
+	struct bttv_fh *fh = priv;
+	struct bttv *btv = fh->btv;
+	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;
+
+	if (!btv->volume_gpio && (c->id == V4L2_CID_AUDIO_VOLUME))
+		*c = no_ctl;
+	else {
+		ctrl = ctrl_by_id(c->id);
+
+		*c = (NULL != ctrl) ? *ctrl : no_ctl;
+	}
+
+	return 0;
+}
+
+static int bttv_g_parm(struct file *file, void *f,
+				struct v4l2_streamparm *parm)
+{
+	struct bttv_fh *fh = f;
+	struct bttv *btv = fh->btv;
+
+	v4l2_video_std_frame_period(bttv_tvnorms[btv->tvnorm].v4l2_id,
+				    &parm->parm.capture.timeperframe);
+
+	return 0;
+}
+
+static int bttv_g_tuner(struct file *file, void *priv,
+				struct v4l2_tuner *t)
+{
+	struct bttv_fh *fh = priv;
+	struct bttv *btv = fh->btv;
+
+	if (btv->tuner_type == TUNER_ABSENT)
+		return -EINVAL;
+	if (0 != t->index)
+		return -EINVAL;
+
+	t->rxsubchans = V4L2_TUNER_SUB_MONO;
+	bttv_call_all(btv, tuner, g_tuner, t);
+	strcpy(t->name, "Television");
+	t->capability = V4L2_TUNER_CAP_NORM;
+	t->type       = V4L2_TUNER_ANALOG_TV;
+	if (btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC)
+		t->signal = 0xffff;
+
+	if (btv->audio_mode_gpio)
+		btv->audio_mode_gpio(btv, t, 0);
+
+	return 0;
+}
+
+static int bttv_g_priority(struct file *file, void *f, enum v4l2_priority *p)
+{
+	struct bttv_fh *fh = f;
+	struct bttv *btv = fh->btv;
+
+	*p = v4l2_prio_max(&btv->prio);
+
+	return 0;
+}
+
+static int bttv_s_priority(struct file *file, void *f,
+					enum v4l2_priority prio)
+{
+	struct bttv_fh *fh = f;
+	struct bttv *btv = fh->btv;
+	int	rc;
+
+	rc = v4l2_prio_change(&btv->prio, &fh->prio, prio);
+
+	return rc;
+}
+
+static int bttv_cropcap(struct file *file, void *priv,
+				struct v4l2_cropcap *cap)
+{
+	struct bttv_fh *fh = priv;
+	struct bttv *btv = fh->btv;
+
+	if (cap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
+	    cap->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
+		return -EINVAL;
+
+	*cap = bttv_tvnorms[btv->tvnorm].cropcap;
+
+	return 0;
+}
+
+static int bttv_g_crop(struct file *file, void *f, struct v4l2_crop *crop)
+{
+	struct bttv_fh *fh = f;
+	struct bttv *btv = fh->btv;
+
+	if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
+	    crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
+		return -EINVAL;
+
+	/* No fh->do_crop = 1; because btv->crop[1] may be
+	   inconsistent with fh->width or fh->height and apps
+	   do not expect a change here. */
+
+	crop->c = btv->crop[!!fh->do_crop].rect;
+
+	return 0;
+}
+
+static int bttv_s_crop(struct file *file, void *f, struct v4l2_crop *crop)
+{
+	struct bttv_fh *fh = f;
+	struct bttv *btv = fh->btv;
+	const struct v4l2_rect *b;
+	int retval;
+	struct bttv_crop c;
+	__s32 b_left;
+	__s32 b_top;
+	__s32 b_right;
+	__s32 b_bottom;
+
+	if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
+	    crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
+		return -EINVAL;
+
+	/* Make sure tvnorm, vbi_end and the current cropping
+	   parameters remain consistent until we're done. Note
+	   read() may change vbi_end in check_alloc_btres_lock(). */
+	retval = v4l2_prio_check(&btv->prio, fh->prio);
+	if (0 != retval) {
+		return retval;
+	}
+
+	retval = -EBUSY;
+
+	if (locked_btres(fh->btv, VIDEO_RESOURCES)) {
+		return retval;
+	}
+
+	b = &bttv_tvnorms[btv->tvnorm].cropcap.bounds;
+
+	b_left = b->left;
+	b_right = b_left + b->width;
+	b_bottom = b->top + b->height;
+
+	b_top = max(b->top, btv->vbi_end);
+	if (b_top + 32 >= b_bottom) {
+		return retval;
+	}
+
+	/* Min. scaled size 48 x 32. */
+	c.rect.left = clamp(crop->c.left, b_left, b_right - 48);
+	c.rect.left = min(c.rect.left, (__s32) MAX_HDELAY);
+
+	c.rect.width = clamp(crop->c.width,
+			     48, b_right - c.rect.left);
+
+	c.rect.top = clamp(crop->c.top, b_top, b_bottom - 32);
+	/* Top and height must be a multiple of two. */
+	c.rect.top = (c.rect.top + 1) & ~1;
+
+	c.rect.height = clamp(crop->c.height,
+			      32, b_bottom - c.rect.top);
+	c.rect.height = (c.rect.height + 1) & ~1;
+
+	bttv_crop_calc_limits(&c);
+
+	btv->crop[1] = c;
+
+	fh->do_crop = 1;
+
+	if (fh->width < c.min_scaled_width) {
+		fh->width = c.min_scaled_width;
+		btv->init.width = c.min_scaled_width;
+	} else if (fh->width > c.max_scaled_width) {
+		fh->width = c.max_scaled_width;
+		btv->init.width = c.max_scaled_width;
+	}
+
+	if (fh->height < c.min_scaled_height) {
+		fh->height = c.min_scaled_height;
+		btv->init.height = c.min_scaled_height;
+	} else if (fh->height > c.max_scaled_height) {
+		fh->height = c.max_scaled_height;
+		btv->init.height = c.max_scaled_height;
+	}
+
+	return 0;
+}
+
+static int bttv_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
+{
+	if (unlikely(a->index))
+		return -EINVAL;
+
+	strcpy(a->name, "audio");
+	return 0;
+}
+
+static int bttv_s_audio(struct file *file, void *priv, struct v4l2_audio *a)
+{
+	if (unlikely(a->index))
+		return -EINVAL;
+
+	return 0;
+}
+
+static ssize_t bttv_read(struct file *file, char __user *data,
+			 size_t count, loff_t *ppos)
+{
+	struct bttv_fh *fh = file->private_data;
+	int retval = 0;
+
+	if (fh->btv->errors)
+		bttv_reinit_bt848(fh->btv);
+	dprintk("%d: read count=%d type=%s\n",
+		fh->btv->c.nr, (int)count, v4l2_type_names[fh->type]);
+
+	switch (fh->type) {
+	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+		if (!check_alloc_btres_lock(fh->btv, fh, RESOURCE_VIDEO_READ)) {
+			/* VIDEO_READ in use by another fh,
+			   or VIDEO_STREAM by any fh. */
+			return -EBUSY;
+		}
+		retval = videobuf_read_one(&fh->cap, data, count, ppos,
+					   file->f_flags & O_NONBLOCK);
+		free_btres_lock(fh->btv, fh, RESOURCE_VIDEO_READ);
+		break;
+	case V4L2_BUF_TYPE_VBI_CAPTURE:
+		if (!check_alloc_btres_lock(fh->btv,fh,RESOURCE_VBI))
+			return -EBUSY;
+		retval = videobuf_read_stream(&fh->vbi, data, count, ppos, 1,
+					      file->f_flags & O_NONBLOCK);
+		break;
+	default:
+		BUG();
+	}
+	return retval;
+}
+
+static unsigned int bttv_poll(struct file *file, poll_table *wait)
+{
+	struct bttv_fh *fh = file->private_data;
+	struct bttv_buffer *buf;
+	enum v4l2_field field;
+	unsigned int rc = POLLERR;
+
+	if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) {
+		if (!check_alloc_btres_lock(fh->btv,fh,RESOURCE_VBI))
+			return POLLERR;
+		return videobuf_poll_stream(file, &fh->vbi, wait);
+	}
+
+	if (check_btres(fh,RESOURCE_VIDEO_STREAM)) {
+		/* streaming capture */
+		if (list_empty(&fh->cap.stream))
+			goto err;
+		buf = list_entry(fh->cap.stream.next,struct bttv_buffer,vb.stream);
+	} else {
+		/* read() capture */
+		if (NULL == fh->cap.read_buf) {
+			/* need to capture a new frame */
+			if (locked_btres(fh->btv,RESOURCE_VIDEO_STREAM))
+				goto err;
+			fh->cap.read_buf = videobuf_sg_alloc(fh->cap.msize);
+			if (NULL == fh->cap.read_buf)
+				goto err;
+			fh->cap.read_buf->memory = V4L2_MEMORY_USERPTR;
+			field = videobuf_next_field(&fh->cap);
+			if (0 != fh->cap.ops->buf_prepare(&fh->cap,fh->cap.read_buf,field)) {
+				kfree (fh->cap.read_buf);
+				fh->cap.read_buf = NULL;
+				goto err;
+			}
+			fh->cap.ops->buf_queue(&fh->cap,fh->cap.read_buf);
+			fh->cap.read_off = 0;
+		}
+		buf = (struct bttv_buffer*)fh->cap.read_buf;
+	}
+
+	poll_wait(file, &buf->vb.done, wait);
+	if (buf->vb.state == VIDEOBUF_DONE ||
+	    buf->vb.state == VIDEOBUF_ERROR)
+		rc =  POLLIN|POLLRDNORM;
+	else
+		rc = 0;
+err:
+	return rc;
+}
+
+static int bttv_open(struct file *file)
+{
+	struct video_device *vdev = video_devdata(file);
+	struct bttv *btv = video_drvdata(file);
+	struct bttv_fh *fh;
+	enum v4l2_buf_type type = 0;
+
+	dprintk("open dev=%s\n", video_device_node_name(vdev));
+
+	if (vdev->vfl_type == VFL_TYPE_GRABBER) {
+		type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	} else if (vdev->vfl_type == VFL_TYPE_VBI) {
+		type = V4L2_BUF_TYPE_VBI_CAPTURE;
+	} else {
+		WARN_ON(1);
+		return -ENODEV;
+	}
+
+	dprintk("%d: open called (type=%s)\n",
+		btv->c.nr, v4l2_type_names[type]);
+
+	/* allocate per filehandle data */
+	fh = kmalloc(sizeof(*fh), GFP_KERNEL);
+	if (unlikely(!fh))
+		return -ENOMEM;
+	file->private_data = fh;
+
+	*fh = btv->init;
+
+	fh->type = type;
+	fh->ov.setup_ok = 0;
+
+	v4l2_prio_open(&btv->prio, &fh->prio);
+
+	videobuf_queue_sg_init(&fh->cap, &bttv_video_qops,
+			    &btv->c.pci->dev, &btv->s_lock,
+			    V4L2_BUF_TYPE_VIDEO_CAPTURE,
+			    V4L2_FIELD_INTERLACED,
+			    sizeof(struct bttv_buffer),
+			    fh, &btv->lock);
+	videobuf_queue_sg_init(&fh->vbi, &bttv_vbi_qops,
+			    &btv->c.pci->dev, &btv->s_lock,
+			    V4L2_BUF_TYPE_VBI_CAPTURE,
+			    V4L2_FIELD_SEQ_TB,
+			    sizeof(struct bttv_buffer),
+			    fh, &btv->lock);
+	set_tvnorm(btv,btv->tvnorm);
+	set_input(btv, btv->input, btv->tvnorm);
+
+	btv->users++;
+
+	/* The V4L2 spec requires one global set of cropping parameters
+	   which only change on request. These are stored in btv->crop[1].
+	   However for compatibility with V4L apps and cropping unaware
+	   V4L2 apps we now reset the cropping parameters as seen through
+	   this fh, which is to say VIDIOC_G_CROP and scaling limit checks
+	   will use btv->crop[0], the default cropping parameters for the
+	   current video standard, and VIDIOC_S_FMT will not implicitely
+	   change the cropping parameters until VIDIOC_S_CROP has been
+	   called. */
+	fh->do_crop = !reset_crop; /* module parameter */
+
+	/* Likewise there should be one global set of VBI capture
+	   parameters, but for compatibility with V4L apps and earlier
+	   driver versions each fh has its own parameters. */
+	bttv_vbi_fmt_reset(&fh->vbi_fmt, btv->tvnorm);
+
+	bttv_field_count(btv);
+	return 0;
+}
+
+static int bttv_release(struct file *file)
+{
+	struct bttv_fh *fh = file->private_data;
+	struct bttv *btv = fh->btv;
+
+	/* turn off overlay */
+	if (check_btres(fh, RESOURCE_OVERLAY))
+		bttv_switch_overlay(btv,fh,NULL);
+
+	/* stop video capture */
+	if (check_btres(fh, RESOURCE_VIDEO_STREAM)) {
+		videobuf_streamoff(&fh->cap);
+		free_btres_lock(btv,fh,RESOURCE_VIDEO_STREAM);
+	}
+	if (fh->cap.read_buf) {
+		buffer_release(&fh->cap,fh->cap.read_buf);
+		kfree(fh->cap.read_buf);
+	}
+	if (check_btres(fh, RESOURCE_VIDEO_READ)) {
+		free_btres_lock(btv, fh, RESOURCE_VIDEO_READ);
+	}
+
+	/* stop vbi capture */
+	if (check_btres(fh, RESOURCE_VBI)) {
+		videobuf_stop(&fh->vbi);
+		free_btres_lock(btv,fh,RESOURCE_VBI);
+	}
+
+	/* free stuff */
+
+	videobuf_mmap_free(&fh->cap);
+	videobuf_mmap_free(&fh->vbi);
+	v4l2_prio_close(&btv->prio, fh->prio);
+	file->private_data = NULL;
+	kfree(fh);
+
+	btv->users--;
+	bttv_field_count(btv);
+
+	if (!btv->users)
+		audio_mute(btv, 1);
+
+	return 0;
+}
+
+static int
+bttv_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	struct bttv_fh *fh = file->private_data;
+
+	dprintk("%d: mmap type=%s 0x%lx+%ld\n",
+		fh->btv->c.nr, v4l2_type_names[fh->type],
+		vma->vm_start, vma->vm_end - vma->vm_start);
+	return videobuf_mmap_mapper(bttv_queue(fh),vma);
+}
+
+static const struct v4l2_file_operations bttv_fops =
+{
+	.owner		  = THIS_MODULE,
+	.open		  = bttv_open,
+	.release	  = bttv_release,
+	.unlocked_ioctl	  = video_ioctl2,
+	.read		  = bttv_read,
+	.mmap		  = bttv_mmap,
+	.poll		  = bttv_poll,
+};
+
+static const struct v4l2_ioctl_ops bttv_ioctl_ops = {
+	.vidioc_querycap                = bttv_querycap,
+	.vidioc_enum_fmt_vid_cap        = bttv_enum_fmt_vid_cap,
+	.vidioc_g_fmt_vid_cap           = bttv_g_fmt_vid_cap,
+	.vidioc_try_fmt_vid_cap         = bttv_try_fmt_vid_cap,
+	.vidioc_s_fmt_vid_cap           = bttv_s_fmt_vid_cap,
+	.vidioc_enum_fmt_vid_overlay    = bttv_enum_fmt_vid_overlay,
+	.vidioc_g_fmt_vid_overlay       = bttv_g_fmt_vid_overlay,
+	.vidioc_try_fmt_vid_overlay     = bttv_try_fmt_vid_overlay,
+	.vidioc_s_fmt_vid_overlay       = bttv_s_fmt_vid_overlay,
+	.vidioc_g_fmt_vbi_cap           = bttv_g_fmt_vbi_cap,
+	.vidioc_try_fmt_vbi_cap         = bttv_try_fmt_vbi_cap,
+	.vidioc_s_fmt_vbi_cap           = bttv_s_fmt_vbi_cap,
+	.vidioc_g_audio                 = bttv_g_audio,
+	.vidioc_s_audio                 = bttv_s_audio,
+	.vidioc_cropcap                 = bttv_cropcap,
+	.vidioc_reqbufs                 = bttv_reqbufs,
+	.vidioc_querybuf                = bttv_querybuf,
+	.vidioc_qbuf                    = bttv_qbuf,
+	.vidioc_dqbuf                   = bttv_dqbuf,
+	.vidioc_s_std                   = bttv_s_std,
+	.vidioc_enum_input              = bttv_enum_input,
+	.vidioc_g_input                 = bttv_g_input,
+	.vidioc_s_input                 = bttv_s_input,
+	.vidioc_queryctrl               = bttv_queryctrl,
+	.vidioc_g_ctrl                  = bttv_g_ctrl,
+	.vidioc_s_ctrl                  = bttv_s_ctrl,
+	.vidioc_streamon                = bttv_streamon,
+	.vidioc_streamoff               = bttv_streamoff,
+	.vidioc_g_tuner                 = bttv_g_tuner,
+	.vidioc_s_tuner                 = bttv_s_tuner,
+	.vidioc_g_crop                  = bttv_g_crop,
+	.vidioc_s_crop                  = bttv_s_crop,
+	.vidioc_g_fbuf                  = bttv_g_fbuf,
+	.vidioc_s_fbuf                  = bttv_s_fbuf,
+	.vidioc_overlay                 = bttv_overlay,
+	.vidioc_g_priority              = bttv_g_priority,
+	.vidioc_s_priority              = bttv_s_priority,
+	.vidioc_g_parm                  = bttv_g_parm,
+	.vidioc_g_frequency             = bttv_g_frequency,
+	.vidioc_s_frequency             = bttv_s_frequency,
+	.vidioc_log_status		= bttv_log_status,
+	.vidioc_querystd		= bttv_querystd,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.vidioc_g_register		= bttv_g_register,
+	.vidioc_s_register		= bttv_s_register,
+#endif
+};
+
+static struct video_device bttv_video_template = {
+	.fops         = &bttv_fops,
+	.ioctl_ops    = &bttv_ioctl_ops,
+	.tvnorms      = BTTV_NORMS,
+	.current_norm = V4L2_STD_PAL,
+};
+
+/* ----------------------------------------------------------------------- */
+/* radio interface                                                         */
+
+static int radio_open(struct file *file)
+{
+	struct video_device *vdev = video_devdata(file);
+	struct bttv *btv = video_drvdata(file);
+	struct bttv_fh *fh;
+
+	dprintk("open dev=%s\n", video_device_node_name(vdev));
+
+	dprintk("%d: open called (radio)\n", btv->c.nr);
+
+	/* allocate per filehandle data */
+	fh = kmalloc(sizeof(*fh), GFP_KERNEL);
+	if (unlikely(!fh))
+		return -ENOMEM;
+	file->private_data = fh;
+	*fh = btv->init;
+
+	v4l2_prio_open(&btv->prio, &fh->prio);
+
+	btv->radio_user++;
+
+	bttv_call_all(btv, tuner, s_radio);
+	audio_input(btv,TVAUDIO_INPUT_RADIO);
+
+	return 0;
+}
+
+static int radio_release(struct file *file)
+{
+	struct bttv_fh *fh = file->private_data;
+	struct bttv *btv = fh->btv;
+	struct saa6588_command cmd;
+
+	v4l2_prio_close(&btv->prio, fh->prio);
+	file->private_data = NULL;
+	kfree(fh);
+
+	btv->radio_user--;
+
+	bttv_call_all(btv, core, ioctl, SAA6588_CMD_CLOSE, &cmd);
+
+	return 0;
+}
+
+static int radio_querycap(struct file *file, void *priv,
+					struct v4l2_capability *cap)
+{
+	struct bttv_fh *fh = priv;
+	struct bttv *btv = fh->btv;
+
+	strcpy(cap->driver, "bttv");
+	strlcpy(cap->card, btv->radio_dev->name, sizeof(cap->card));
+	sprintf(cap->bus_info, "PCI:%s", pci_name(btv->c.pci));
+	cap->capabilities = V4L2_CAP_TUNER;
+
+	return 0;
+}
+
+static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
+{
+	struct bttv_fh *fh = priv;
+	struct bttv *btv = fh->btv;
+
+	if (btv->tuner_type == TUNER_ABSENT)
+		return -EINVAL;
+	if (0 != t->index)
+		return -EINVAL;
+	strcpy(t->name, "Radio");
+	t->type = V4L2_TUNER_RADIO;
+
+	bttv_call_all(btv, tuner, g_tuner, t);
+
+	if (btv->audio_mode_gpio)
+		btv->audio_mode_gpio(btv, t, 0);
+
+	return 0;
+}
+
+static int radio_enum_input(struct file *file, void *priv,
+				struct v4l2_input *i)
+{
+	if (i->index != 0)
+		return -EINVAL;
+
+	strcpy(i->name, "Radio");
+	i->type = V4L2_INPUT_TYPE_TUNER;
+
+	return 0;
+}
+
+static int radio_g_audio(struct file *file, void *priv,
+					struct v4l2_audio *a)
+{
+	if (unlikely(a->index))
+		return -EINVAL;
+
+	strcpy(a->name, "Radio");
+
+	return 0;
+}
+
+static int radio_s_tuner(struct file *file, void *priv,
+					struct v4l2_tuner *t)
+{
+	struct bttv_fh *fh = priv;
+	struct bttv *btv = fh->btv;
+
+	if (0 != t->index)
+		return -EINVAL;
+
+	bttv_call_all(btv, tuner, s_tuner, t);
+	return 0;
+}
+
+static int radio_s_audio(struct file *file, void *priv,
+					struct v4l2_audio *a)
+{
+	if (unlikely(a->index))
+		return -EINVAL;
+
+	return 0;
+}
+
+static int radio_s_input(struct file *filp, void *priv, unsigned int i)
+{
+	if (unlikely(i))
+		return -EINVAL;
+
+	return 0;
+}
+
+static int radio_s_std(struct file *file, void *fh, v4l2_std_id *norm)
+{
+	return 0;
+}
+
+static int radio_queryctrl(struct file *file, void *priv,
+					struct v4l2_queryctrl *c)
+{
+	const struct v4l2_queryctrl *ctrl;
+
+	if (c->id <  V4L2_CID_BASE ||
+			c->id >= V4L2_CID_LASTP1)
+		return -EINVAL;
+
+	if (c->id == V4L2_CID_AUDIO_MUTE) {
+		ctrl = ctrl_by_id(c->id);
+		*c = *ctrl;
+	} else
+		*c = no_ctl;
+
+	return 0;
+}
+
+static int radio_g_input(struct file *filp, void *priv, unsigned int *i)
+{
+	*i = 0;
+	return 0;
+}
+
+static ssize_t radio_read(struct file *file, char __user *data,
+			 size_t count, loff_t *ppos)
+{
+	struct bttv_fh *fh = file->private_data;
+	struct bttv *btv = fh->btv;
+	struct saa6588_command cmd;
+	cmd.block_count = count/3;
+	cmd.buffer = data;
+	cmd.instance = file;
+	cmd.result = -ENODEV;
+
+	bttv_call_all(btv, core, ioctl, SAA6588_CMD_READ, &cmd);
+
+	return cmd.result;
+}
+
+static unsigned int radio_poll(struct file *file, poll_table *wait)
+{
+	struct bttv_fh *fh = file->private_data;
+	struct bttv *btv = fh->btv;
+	struct saa6588_command cmd;
+	cmd.instance = file;
+	cmd.event_list = wait;
+	cmd.result = -ENODEV;
+	bttv_call_all(btv, core, ioctl, SAA6588_CMD_POLL, &cmd);
+
+	return cmd.result;
+}
+
+static const struct v4l2_file_operations radio_fops =
+{
+	.owner	  = THIS_MODULE,
+	.open	  = radio_open,
+	.read     = radio_read,
+	.release  = radio_release,
+	.unlocked_ioctl = video_ioctl2,
+	.poll     = radio_poll,
+};
+
+static const struct v4l2_ioctl_ops radio_ioctl_ops = {
+	.vidioc_querycap        = radio_querycap,
+	.vidioc_g_tuner         = radio_g_tuner,
+	.vidioc_enum_input      = radio_enum_input,
+	.vidioc_g_audio         = radio_g_audio,
+	.vidioc_s_tuner         = radio_s_tuner,
+	.vidioc_s_audio         = radio_s_audio,
+	.vidioc_s_input         = radio_s_input,
+	.vidioc_s_std           = radio_s_std,
+	.vidioc_queryctrl       = radio_queryctrl,
+	.vidioc_g_input         = radio_g_input,
+	.vidioc_g_ctrl          = bttv_g_ctrl,
+	.vidioc_s_ctrl          = bttv_s_ctrl,
+	.vidioc_g_frequency     = bttv_g_frequency,
+	.vidioc_s_frequency     = bttv_s_frequency,
+};
+
+static struct video_device radio_template = {
+	.fops      = &radio_fops,
+	.ioctl_ops = &radio_ioctl_ops,
+};
+
+/* ----------------------------------------------------------------------- */
+/* some debug code                                                         */
+
+static int bttv_risc_decode(u32 risc)
+{
+	static char *instr[16] = {
+		[ BT848_RISC_WRITE     >> 28 ] = "write",
+		[ BT848_RISC_SKIP      >> 28 ] = "skip",
+		[ BT848_RISC_WRITEC    >> 28 ] = "writec",
+		[ BT848_RISC_JUMP      >> 28 ] = "jump",
+		[ BT848_RISC_SYNC      >> 28 ] = "sync",
+		[ BT848_RISC_WRITE123  >> 28 ] = "write123",
+		[ BT848_RISC_SKIP123   >> 28 ] = "skip123",
+		[ BT848_RISC_WRITE1S23 >> 28 ] = "write1s23",
+	};
+	static int incr[16] = {
+		[ BT848_RISC_WRITE     >> 28 ] = 2,
+		[ BT848_RISC_JUMP      >> 28 ] = 2,
+		[ BT848_RISC_SYNC      >> 28 ] = 2,
+		[ BT848_RISC_WRITE123  >> 28 ] = 5,
+		[ BT848_RISC_SKIP123   >> 28 ] = 2,
+		[ BT848_RISC_WRITE1S23 >> 28 ] = 3,
+	};
+	static char *bits[] = {
+		"be0",  "be1",  "be2",  "be3/resync",
+		"set0", "set1", "set2", "set3",
+		"clr0", "clr1", "clr2", "clr3",
+		"irq",  "res",  "eol",  "sol",
+	};
+	int i;
+
+	pr_cont("0x%08x [ %s", risc,
+	       instr[risc >> 28] ? instr[risc >> 28] : "INVALID");
+	for (i = ARRAY_SIZE(bits)-1; i >= 0; i--)
+		if (risc & (1 << (i + 12)))
+			pr_cont(" %s", bits[i]);
+	pr_cont(" count=%d ]\n", risc & 0xfff);
+	return incr[risc >> 28] ? incr[risc >> 28] : 1;
+}
+
+static void bttv_risc_disasm(struct bttv *btv,
+			     struct btcx_riscmem *risc)
+{
+	unsigned int i,j,n;
+
+	pr_info("%s: risc disasm: %p [dma=0x%08lx]\n",
+		btv->c.v4l2_dev.name, risc->cpu, (unsigned long)risc->dma);
+	for (i = 0; i < (risc->size >> 2); i += n) {
+		pr_info("%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++)
+			pr_info("%s:   0x%lx: 0x%08x [ arg #%d ]\n",
+				btv->c.v4l2_dev.name,
+				(unsigned long)(risc->dma + ((i+j)<<2)),
+				risc->cpu[i+j], j);
+		if (0 == risc->cpu[i])
+			break;
+	}
+}
+
+static void bttv_print_riscaddr(struct bttv *btv)
+{
+	pr_info("  main: %08llx\n", (unsigned long long)btv->main.dma);
+	pr_info("  vbi : o=%08llx e=%08llx\n",
+		btv->cvbi ? (unsigned long long)btv->cvbi->top.dma : 0,
+		btv->cvbi ? (unsigned long long)btv->cvbi->bottom.dma : 0);
+	pr_info("  cap : o=%08llx e=%08llx\n",
+		btv->curr.top
+		? (unsigned long long)btv->curr.top->top.dma : 0,
+		btv->curr.bottom
+		? (unsigned long long)btv->curr.bottom->bottom.dma : 0);
+	pr_info("  scr : o=%08llx e=%08llx\n",
+		btv->screen ? (unsigned long long)btv->screen->top.dma : 0,
+		btv->screen ? (unsigned long long)btv->screen->bottom.dma : 0);
+	bttv_risc_disasm(btv, &btv->main);
+}
+
+/* ----------------------------------------------------------------------- */
+/* irq handler                                                             */
+
+static char *irq_name[] = {
+	"FMTCHG",  // format change detected (525 vs. 625)
+	"VSYNC",   // vertical sync (new field)
+	"HSYNC",   // horizontal sync
+	"OFLOW",   // chroma/luma AGC overflow
+	"HLOCK",   // horizontal lock changed
+	"VPRES",   // video presence changed
+	"6", "7",
+	"I2CDONE", // hw irc operation finished
+	"GPINT",   // gpio port triggered irq
+	"10",
+	"RISCI",   // risc instruction triggered irq
+	"FBUS",    // pixel data fifo dropped data (high pci bus latencies)
+	"FTRGT",   // pixel data fifo overrun
+	"FDSR",    // fifo data stream resyncronisation
+	"PPERR",   // parity error (data transfer)
+	"RIPERR",  // parity error (read risc instructions)
+	"PABORT",  // pci abort
+	"OCERR",   // risc instruction error
+	"SCERR",   // syncronisation error
+};
+
+static void bttv_print_irqbits(u32 print, u32 mark)
+{
+	unsigned int i;
+
+	pr_cont("bits:");
+	for (i = 0; i < ARRAY_SIZE(irq_name); i++) {
+		if (print & (1 << i))
+			pr_cont(" %s", irq_name[i]);
+		if (mark & (1 << i))
+			pr_cont("*");
+	}
+}
+
+static void bttv_irq_debug_low_latency(struct bttv *btv, u32 rc)
+{
+	pr_warn("%d: irq: skipped frame [main=%lx,o_vbi=%lx,o_field=%lx,rc=%lx]\n",
+		btv->c.nr,
+		(unsigned long)btv->main.dma,
+		(unsigned long)le32_to_cpu(btv->main.cpu[RISC_SLOT_O_VBI+1]),
+		(unsigned long)le32_to_cpu(btv->main.cpu[RISC_SLOT_O_FIELD+1]),
+		(unsigned long)rc);
+
+	if (0 == (btread(BT848_DSTATUS) & BT848_DSTATUS_HLOC)) {
+		pr_notice("%d: Oh, there (temporarily?) is no input signal. "
+			  "Ok, then this is harmless, don't worry ;)\n",
+			  btv->c.nr);
+		return;
+	}
+	pr_notice("%d: Uhm. Looks like we have unusual high IRQ latencies\n",
+		  btv->c.nr);
+	pr_notice("%d: Lets try to catch the culpit red-handed ...\n",
+		  btv->c.nr);
+	dump_stack();
+}
+
+static int
+bttv_irq_next_video(struct bttv *btv, struct bttv_buffer_set *set)
+{
+	struct bttv_buffer *item;
+
+	memset(set,0,sizeof(*set));
+
+	/* capture request ? */
+	if (!list_empty(&btv->capture)) {
+		set->frame_irq = 1;
+		item = list_entry(btv->capture.next, struct bttv_buffer, vb.queue);
+		if (V4L2_FIELD_HAS_TOP(item->vb.field))
+			set->top    = item;
+		if (V4L2_FIELD_HAS_BOTTOM(item->vb.field))
+			set->bottom = item;
+
+		/* capture request for other field ? */
+		if (!V4L2_FIELD_HAS_BOTH(item->vb.field) &&
+		    (item->vb.queue.next != &btv->capture)) {
+			item = list_entry(item->vb.queue.next, struct bttv_buffer, vb.queue);
+			/* Mike Isely <isely@pobox.com> - Only check
+			 * and set up the bottom field in the logic
+			 * below.  Don't ever do the top field.  This
+			 * of course means that if we set up the
+			 * bottom field in the above code that we'll
+			 * actually skip a field.  But that's OK.
+			 * Having processed only a single buffer this
+			 * time, then the next time around the first
+			 * available buffer should be for a top field.
+			 * That will then cause us here to set up a
+			 * top then a bottom field in the normal way.
+			 * The alternative to this understanding is
+			 * that we set up the second available buffer
+			 * as a top field, but that's out of order
+			 * since this driver always processes the top
+			 * field first - the effect will be the two
+			 * buffers being returned in the wrong order,
+			 * with the second buffer also being delayed
+			 * by one field time (owing to the fifo nature
+			 * of videobuf).  Worse still, we'll be stuck
+			 * doing fields out of order now every time
+			 * until something else causes a field to be
+			 * dropped.  By effectively forcing a field to
+			 * drop this way then we always get back into
+			 * sync within a single frame time.  (Out of
+			 * order fields can screw up deinterlacing
+			 * algorithms.) */
+			if (!V4L2_FIELD_HAS_BOTH(item->vb.field)) {
+				if (NULL == set->bottom &&
+				    V4L2_FIELD_BOTTOM == item->vb.field) {
+					set->bottom = item;
+				}
+				if (NULL != set->top  &&  NULL != set->bottom)
+					set->top_irq = 2;
+			}
+		}
+	}
+
+	/* screen overlay ? */
+	if (NULL != btv->screen) {
+		if (V4L2_FIELD_HAS_BOTH(btv->screen->vb.field)) {
+			if (NULL == set->top && NULL == set->bottom) {
+				set->top    = btv->screen;
+				set->bottom = btv->screen;
+			}
+		} else {
+			if (V4L2_FIELD_TOP == btv->screen->vb.field &&
+			    NULL == set->top) {
+				set->top = btv->screen;
+			}
+			if (V4L2_FIELD_BOTTOM == btv->screen->vb.field &&
+			    NULL == set->bottom) {
+				set->bottom = btv->screen;
+			}
+		}
+	}
+
+	dprintk("%d: next set: top=%p bottom=%p [screen=%p,irq=%d,%d]\n",
+		btv->c.nr, set->top, set->bottom,
+		btv->screen, set->frame_irq, set->top_irq);
+	return 0;
+}
+
+static void
+bttv_irq_wakeup_video(struct bttv *btv, struct bttv_buffer_set *wakeup,
+		      struct bttv_buffer_set *curr, unsigned int state)
+{
+	struct timeval ts;
+
+	do_gettimeofday(&ts);
+
+	if (wakeup->top == wakeup->bottom) {
+		if (NULL != wakeup->top && curr->top != wakeup->top) {
+			if (irq_debug > 1)
+				pr_debug("%d: wakeup: both=%p\n",
+					 btv->c.nr, wakeup->top);
+			wakeup->top->vb.ts = ts;
+			wakeup->top->vb.field_count = btv->field_count;
+			wakeup->top->vb.state = state;
+			wake_up(&wakeup->top->vb.done);
+		}
+	} else {
+		if (NULL != wakeup->top && curr->top != wakeup->top) {
+			if (irq_debug > 1)
+				pr_debug("%d: wakeup: top=%p\n",
+					 btv->c.nr, wakeup->top);
+			wakeup->top->vb.ts = ts;
+			wakeup->top->vb.field_count = btv->field_count;
+			wakeup->top->vb.state = state;
+			wake_up(&wakeup->top->vb.done);
+		}
+		if (NULL != wakeup->bottom && curr->bottom != wakeup->bottom) {
+			if (irq_debug > 1)
+				pr_debug("%d: wakeup: bottom=%p\n",
+					 btv->c.nr, wakeup->bottom);
+			wakeup->bottom->vb.ts = ts;
+			wakeup->bottom->vb.field_count = btv->field_count;
+			wakeup->bottom->vb.state = state;
+			wake_up(&wakeup->bottom->vb.done);
+		}
+	}
+}
+
+static void
+bttv_irq_wakeup_vbi(struct bttv *btv, struct bttv_buffer *wakeup,
+		    unsigned int state)
+{
+	struct timeval ts;
+
+	if (NULL == wakeup)
+		return;
+
+	do_gettimeofday(&ts);
+	wakeup->vb.ts = ts;
+	wakeup->vb.field_count = btv->field_count;
+	wakeup->vb.state = state;
+	wake_up(&wakeup->vb.done);
+}
+
+static void bttv_irq_timeout(unsigned long data)
+{
+	struct bttv *btv = (struct bttv *)data;
+	struct bttv_buffer_set old,new;
+	struct bttv_buffer *ovbi;
+	struct bttv_buffer *item;
+	unsigned long flags;
+
+	if (bttv_verbose) {
+		pr_info("%d: timeout: drop=%d irq=%d/%d, risc=%08x, ",
+			btv->c.nr, btv->framedrop, btv->irq_me, btv->irq_total,
+			btread(BT848_RISC_COUNT));
+		bttv_print_irqbits(btread(BT848_INT_STAT),0);
+		pr_cont("\n");
+	}
+
+	spin_lock_irqsave(&btv->s_lock,flags);
+
+	/* deactivate stuff */
+	memset(&new,0,sizeof(new));
+	old  = btv->curr;
+	ovbi = btv->cvbi;
+	btv->curr = new;
+	btv->cvbi = NULL;
+	btv->loop_irq = 0;
+	bttv_buffer_activate_video(btv, &new);
+	bttv_buffer_activate_vbi(btv,   NULL);
+	bttv_set_dma(btv, 0);
+
+	/* wake up */
+	bttv_irq_wakeup_video(btv, &old, &new, VIDEOBUF_ERROR);
+	bttv_irq_wakeup_vbi(btv, ovbi, VIDEOBUF_ERROR);
+
+	/* cancel all outstanding capture / vbi requests */
+	while (!list_empty(&btv->capture)) {
+		item = list_entry(btv->capture.next, struct bttv_buffer, vb.queue);
+		list_del(&item->vb.queue);
+		item->vb.state = VIDEOBUF_ERROR;
+		wake_up(&item->vb.done);
+	}
+	while (!list_empty(&btv->vcapture)) {
+		item = list_entry(btv->vcapture.next, struct bttv_buffer, vb.queue);
+		list_del(&item->vb.queue);
+		item->vb.state = VIDEOBUF_ERROR;
+		wake_up(&item->vb.done);
+	}
+
+	btv->errors++;
+	spin_unlock_irqrestore(&btv->s_lock,flags);
+}
+
+static void
+bttv_irq_wakeup_top(struct bttv *btv)
+{
+	struct bttv_buffer *wakeup = btv->curr.top;
+
+	if (NULL == wakeup)
+		return;
+
+	spin_lock(&btv->s_lock);
+	btv->curr.top_irq = 0;
+	btv->curr.top = NULL;
+	bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
+
+	do_gettimeofday(&wakeup->vb.ts);
+	wakeup->vb.field_count = btv->field_count;
+	wakeup->vb.state = VIDEOBUF_DONE;
+	wake_up(&wakeup->vb.done);
+	spin_unlock(&btv->s_lock);
+}
+
+static inline int is_active(struct btcx_riscmem *risc, u32 rc)
+{
+	if (rc < risc->dma)
+		return 0;
+	if (rc > risc->dma + risc->size)
+		return 0;
+	return 1;
+}
+
+static void
+bttv_irq_switch_video(struct bttv *btv)
+{
+	struct bttv_buffer_set new;
+	struct bttv_buffer_set old;
+	dma_addr_t rc;
+
+	spin_lock(&btv->s_lock);
+
+	/* new buffer set */
+	bttv_irq_next_video(btv, &new);
+	rc = btread(BT848_RISC_COUNT);
+	if ((btv->curr.top    && is_active(&btv->curr.top->top,       rc)) ||
+	    (btv->curr.bottom && is_active(&btv->curr.bottom->bottom, rc))) {
+		btv->framedrop++;
+		if (debug_latency)
+			bttv_irq_debug_low_latency(btv, rc);
+		spin_unlock(&btv->s_lock);
+		return;
+	}
+
+	/* switch over */
+	old = btv->curr;
+	btv->curr = new;
+	btv->loop_irq &= ~1;
+	bttv_buffer_activate_video(btv, &new);
+	bttv_set_dma(btv, 0);
+
+	/* switch input */
+	if (UNSET != btv->new_input) {
+		video_mux(btv,btv->new_input);
+		btv->new_input = UNSET;
+	}
+
+	/* wake up finished buffers */
+	bttv_irq_wakeup_video(btv, &old, &new, VIDEOBUF_DONE);
+	spin_unlock(&btv->s_lock);
+}
+
+static void
+bttv_irq_switch_vbi(struct bttv *btv)
+{
+	struct bttv_buffer *new = NULL;
+	struct bttv_buffer *old;
+	u32 rc;
+
+	spin_lock(&btv->s_lock);
+
+	if (!list_empty(&btv->vcapture))
+		new = list_entry(btv->vcapture.next, struct bttv_buffer, vb.queue);
+	old = btv->cvbi;
+
+	rc = btread(BT848_RISC_COUNT);
+	if (NULL != old && (is_active(&old->top,    rc) ||
+			    is_active(&old->bottom, rc))) {
+		btv->framedrop++;
+		if (debug_latency)
+			bttv_irq_debug_low_latency(btv, rc);
+		spin_unlock(&btv->s_lock);
+		return;
+	}
+
+	/* switch */
+	btv->cvbi = new;
+	btv->loop_irq &= ~4;
+	bttv_buffer_activate_vbi(btv, new);
+	bttv_set_dma(btv, 0);
+
+	bttv_irq_wakeup_vbi(btv, old, VIDEOBUF_DONE);
+	spin_unlock(&btv->s_lock);
+}
+
+static irqreturn_t bttv_irq(int irq, void *dev_id)
+{
+	u32 stat,astat;
+	u32 dstat;
+	int count;
+	struct bttv *btv;
+	int handled = 0;
+
+	btv=(struct bttv *)dev_id;
+
+	count=0;
+	while (1) {
+		/* get/clear interrupt status bits */
+		stat=btread(BT848_INT_STAT);
+		astat=stat&btread(BT848_INT_MASK);
+		if (!astat)
+			break;
+		handled = 1;
+		btwrite(stat,BT848_INT_STAT);
+
+		/* get device status bits */
+		dstat=btread(BT848_DSTATUS);
+
+		if (irq_debug) {
+			pr_debug("%d: irq loop=%d fc=%d riscs=%x, riscc=%08x, ",
+				 btv->c.nr, count, btv->field_count,
+				 stat>>28, btread(BT848_RISC_COUNT));
+			bttv_print_irqbits(stat,astat);
+			if (stat & BT848_INT_HLOCK)
+				pr_cont("   HLOC => %s",
+					dstat & BT848_DSTATUS_HLOC
+					? "yes" : "no");
+			if (stat & BT848_INT_VPRES)
+				pr_cont("   PRES => %s",
+					dstat & BT848_DSTATUS_PRES
+					? "yes" : "no");
+			if (stat & BT848_INT_FMTCHG)
+				pr_cont("   NUML => %s",
+					dstat & BT848_DSTATUS_NUML
+					? "625" : "525");
+			pr_cont("\n");
+		}
+
+		if (astat&BT848_INT_VSYNC)
+			btv->field_count++;
+
+		if ((astat & BT848_INT_GPINT) && btv->remote) {
+			bttv_input_irq(btv);
+		}
+
+		if (astat & BT848_INT_I2CDONE) {
+			btv->i2c_done = stat;
+			wake_up(&btv->i2c_queue);
+		}
+
+		if ((astat & BT848_INT_RISCI)  &&  (stat & (4<<28)))
+			bttv_irq_switch_vbi(btv);
+
+		if ((astat & BT848_INT_RISCI)  &&  (stat & (2<<28)))
+			bttv_irq_wakeup_top(btv);
+
+		if ((astat & BT848_INT_RISCI)  &&  (stat & (1<<28)))
+			bttv_irq_switch_video(btv);
+
+		if ((astat & BT848_INT_HLOCK)  &&  btv->opt_automute)
+			audio_mute(btv, btv->mute);  /* trigger automute */
+
+		if (astat & (BT848_INT_SCERR|BT848_INT_OCERR)) {
+			pr_info("%d: %s%s @ %08x,",
+				btv->c.nr,
+				(astat & BT848_INT_SCERR) ? "SCERR" : "",
+				(astat & BT848_INT_OCERR) ? "OCERR" : "",
+				btread(BT848_RISC_COUNT));
+			bttv_print_irqbits(stat,astat);
+			pr_cont("\n");
+			if (bttv_debug)
+				bttv_print_riscaddr(btv);
+		}
+		if (fdsr && astat & BT848_INT_FDSR) {
+			pr_info("%d: FDSR @ %08x\n",
+				btv->c.nr, btread(BT848_RISC_COUNT));
+			if (bttv_debug)
+				bttv_print_riscaddr(btv);
+		}
+
+		count++;
+		if (count > 4) {
+
+			if (count > 8 || !(astat & BT848_INT_GPINT)) {
+				btwrite(0, BT848_INT_MASK);
+
+				pr_err("%d: IRQ lockup, cleared int mask [",
+				       btv->c.nr);
+			} else {
+				pr_err("%d: IRQ lockup, clearing GPINT from int mask [",
+				       btv->c.nr);
+
+				btwrite(btread(BT848_INT_MASK) & (-1 ^ BT848_INT_GPINT),
+						BT848_INT_MASK);
+			};
+
+			bttv_print_irqbits(stat,astat);
+
+			pr_cont("]\n");
+		}
+	}
+	btv->irq_total++;
+	if (handled)
+		btv->irq_me++;
+	return IRQ_RETVAL(handled);
+}
+
+
+/* ----------------------------------------------------------------------- */
+/* initialitation                                                          */
+
+static struct video_device *vdev_init(struct bttv *btv,
+				      const struct video_device *template,
+				      const char *type_name)
+{
+	struct video_device *vfd;
+
+	vfd = video_device_alloc();
+	if (NULL == vfd)
+		return NULL;
+	*vfd = *template;
+	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);
+	return vfd;
+}
+
+static void bttv_unregister_video(struct bttv *btv)
+{
+	if (btv->video_dev) {
+		if (video_is_registered(btv->video_dev))
+			video_unregister_device(btv->video_dev);
+		else
+			video_device_release(btv->video_dev);
+		btv->video_dev = NULL;
+	}
+	if (btv->vbi_dev) {
+		if (video_is_registered(btv->vbi_dev))
+			video_unregister_device(btv->vbi_dev);
+		else
+			video_device_release(btv->vbi_dev);
+		btv->vbi_dev = NULL;
+	}
+	if (btv->radio_dev) {
+		if (video_is_registered(btv->radio_dev))
+			video_unregister_device(btv->radio_dev);
+		else
+			video_device_release(btv->radio_dev);
+		btv->radio_dev = NULL;
+	}
+}
+
+/* register video4linux devices */
+static int __devinit bttv_register_video(struct bttv *btv)
+{
+	if (no_overlay > 0)
+		pr_notice("Overlay support disabled\n");
+
+	/* video */
+	btv->video_dev = vdev_init(btv, &bttv_video_template, "video");
+
+	if (NULL == btv->video_dev)
+		goto err;
+	if (video_register_device(btv->video_dev, VFL_TYPE_GRABBER,
+				  video_nr[btv->c.nr]) < 0)
+		goto err;
+	pr_info("%d: registered device %s\n",
+		btv->c.nr, video_device_node_name(btv->video_dev));
+	if (device_create_file(&btv->video_dev->dev,
+				     &dev_attr_card)<0) {
+		pr_err("%d: device_create_file 'card' failed\n", btv->c.nr);
+		goto err;
+	}
+
+	/* vbi */
+	btv->vbi_dev = vdev_init(btv, &bttv_video_template, "vbi");
+
+	if (NULL == btv->vbi_dev)
+		goto err;
+	if (video_register_device(btv->vbi_dev, VFL_TYPE_VBI,
+				  vbi_nr[btv->c.nr]) < 0)
+		goto err;
+	pr_info("%d: registered device %s\n",
+		btv->c.nr, video_device_node_name(btv->vbi_dev));
+
+	if (!btv->has_radio)
+		return 0;
+	/* radio */
+	btv->radio_dev = vdev_init(btv, &radio_template, "radio");
+	if (NULL == btv->radio_dev)
+		goto err;
+	if (video_register_device(btv->radio_dev, VFL_TYPE_RADIO,
+				  radio_nr[btv->c.nr]) < 0)
+		goto err;
+	pr_info("%d: registered device %s\n",
+		btv->c.nr, video_device_node_name(btv->radio_dev));
+
+	/* all done */
+	return 0;
+
+ err:
+	bttv_unregister_video(btv);
+	return -1;
+}
+
+
+/* on OpenFirmware machines (PowerMac at least), PCI memory cycle */
+/* response on cards with no firmware is not enabled by OF */
+static void pci_set_command(struct pci_dev *dev)
+{
+#if defined(__powerpc__)
+	unsigned int cmd;
+
+	pci_read_config_dword(dev, PCI_COMMAND, &cmd);
+	cmd = (cmd | PCI_COMMAND_MEMORY );
+	pci_write_config_dword(dev, PCI_COMMAND, cmd);
+#endif
+}
+
+static int __devinit bttv_probe(struct pci_dev *dev,
+				const struct pci_device_id *pci_id)
+{
+	int result;
+	unsigned char lat;
+	struct bttv *btv;
+
+	if (bttv_num == BTTV_MAX)
+		return -ENOMEM;
+	pr_info("Bt8xx card found (%d)\n", bttv_num);
+	bttvs[bttv_num] = btv = kzalloc(sizeof(*btv), GFP_KERNEL);
+	if (btv == NULL) {
+		pr_err("out of memory\n");
+		return -ENOMEM;
+	}
+	btv->c.nr  = bttv_num;
+	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);
+	spin_lock_init(&btv->s_lock);
+	spin_lock_init(&btv->gpio_lock);
+	init_waitqueue_head(&btv->i2c_queue);
+	INIT_LIST_HEAD(&btv->c.subs);
+	INIT_LIST_HEAD(&btv->capture);
+	INIT_LIST_HEAD(&btv->vcapture);
+	v4l2_prio_init(&btv->prio);
+
+	init_timer(&btv->timeout);
+	btv->timeout.function = bttv_irq_timeout;
+	btv->timeout.data     = (unsigned long)btv;
+
+	btv->i2c_rc = -1;
+	btv->tuner_type  = UNSET;
+	btv->new_input   = UNSET;
+	btv->has_radio=radio[btv->c.nr];
+
+	/* pci stuff (init, get irq/mmio, ... */
+	btv->c.pci = dev;
+	btv->id  = dev->device;
+	if (pci_enable_device(dev)) {
+		pr_warn("%d: Can't enable device\n", btv->c.nr);
+		return -EIO;
+	}
+	if (pci_set_dma_mask(dev, DMA_BIT_MASK(32))) {
+		pr_warn("%d: No suitable DMA available\n", btv->c.nr);
+		return -EIO;
+	}
+	if (!request_mem_region(pci_resource_start(dev,0),
+				pci_resource_len(dev,0),
+				btv->c.v4l2_dev.name)) {
+		pr_warn("%d: can't request iomem (0x%llx)\n",
+			btv->c.nr,
+			(unsigned long long)pci_resource_start(dev, 0));
+		return -EBUSY;
+	}
+	pci_set_master(dev);
+	pci_set_command(dev);
+
+	result = v4l2_device_register(&dev->dev, &btv->c.v4l2_dev);
+	if (result < 0) {
+		pr_warn("%d: v4l2_device_register() failed\n", btv->c.nr);
+		goto fail0;
+	}
+
+	btv->revision = dev->revision;
+	pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
+	pr_info("%d: Bt%d (rev %d) at %s, irq: %d, latency: %d, mmio: 0x%llx\n",
+		bttv_num, btv->id, btv->revision, pci_name(dev),
+		btv->c.pci->irq, lat,
+		(unsigned long long)pci_resource_start(dev, 0));
+	schedule();
+
+	btv->bt848_mmio = ioremap(pci_resource_start(dev, 0), 0x1000);
+	if (NULL == btv->bt848_mmio) {
+		pr_err("%d: ioremap() failed\n", btv->c.nr);
+		result = -EIO;
+		goto fail1;
+	}
+
+	/* identify card */
+	bttv_idcard(btv);
+
+	/* 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.v4l2_dev.name, (void *)btv);
+	if (result < 0) {
+		pr_err("%d: can't get IRQ %d\n",
+		       bttv_num, btv->c.pci->irq);
+		goto fail1;
+	}
+
+	if (0 != bttv_handle_chipset(btv)) {
+		result = -EIO;
+		goto fail2;
+	}
+
+	/* init options from insmod args */
+	btv->opt_combfilter = combfilter;
+	btv->opt_lumafilter = lumafilter;
+	btv->opt_automute   = automute;
+	btv->opt_chroma_agc = chroma_agc;
+	btv->opt_adc_crush  = adc_crush;
+	btv->opt_vcr_hack   = vcr_hack;
+	btv->opt_whitecrush_upper  = whitecrush_upper;
+	btv->opt_whitecrush_lower  = whitecrush_lower;
+	btv->opt_uv_ratio   = uv_ratio;
+	btv->opt_full_luma_range   = full_luma_range;
+	btv->opt_coring     = coring;
+
+	/* fill struct bttv with some useful defaults */
+	btv->init.btv         = btv;
+	btv->init.ov.w.width  = 320;
+	btv->init.ov.w.height = 240;
+	btv->init.fmt         = format_by_fourcc(V4L2_PIX_FMT_BGR24);
+	btv->init.width       = 320;
+	btv->init.height      = 240;
+	btv->input = 0;
+
+	/* initialize hardware */
+	if (bttv_gpio)
+		bttv_gpio_tracking(btv,"pre-init");
+
+	bttv_risc_init_main(btv);
+	init_bt848(btv);
+
+	/* gpio */
+	btwrite(0x00, BT848_GPIO_REG_INP);
+	btwrite(0x00, BT848_GPIO_OUT_EN);
+	if (bttv_verbose)
+		bttv_gpio_tracking(btv,"init");
+
+	/* needs to be done before i2c is registered */
+	bttv_init_card1(btv);
+
+	/* register i2c + gpio */
+	init_bttv_i2c(btv);
+
+	/* some card-specific stuff (needs working i2c) */
+	bttv_init_card2(btv);
+	bttv_init_tuner(btv);
+	init_irqreg(btv);
+
+	/* register video4linux + input */
+	if (!bttv_tvcards[btv->c.type].no_video) {
+		bttv_register_video(btv);
+		bt848_bright(btv,32768);
+		bt848_contrast(btv, 27648);
+		bt848_hue(btv,32768);
+		bt848_sat(btv,32768);
+		audio_mute(btv, 1);
+		set_input(btv, 0, btv->tvnorm);
+		bttv_crop_reset(&btv->crop[0], btv->tvnorm);
+		btv->crop[1] = btv->crop[0]; /* current = default */
+		disclaim_vbi_lines(btv);
+		disclaim_video_lines(btv);
+	}
+
+	/* add subdevices and autoload dvb-bt8xx if needed */
+	if (bttv_tvcards[btv->c.type].has_dvb) {
+		bttv_sub_add_device(&btv->c, "dvb");
+		request_modules(btv);
+	}
+
+	if (!disable_ir) {
+		init_bttv_i2c_ir(btv);
+		bttv_input_init(btv);
+	}
+
+	/* everything is fine */
+	bttv_num++;
+	return 0;
+
+fail2:
+	free_irq(btv->c.pci->irq,btv);
+
+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));
+	return result;
+}
+
+static void __devexit bttv_remove(struct pci_dev *pci_dev)
+{
+	struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
+	struct bttv *btv = to_bttv(v4l2_dev);
+
+	if (bttv_verbose)
+		pr_info("%d: unloading\n", btv->c.nr);
+
+	if (bttv_tvcards[btv->c.type].has_dvb)
+		flush_request_modules(btv);
+
+	/* shutdown everything (DMA+IRQs) */
+	btand(~15, BT848_GPIO_DMA_CTL);
+	btwrite(0, BT848_INT_MASK);
+	btwrite(~0x0, BT848_INT_STAT);
+	btwrite(0x0, BT848_GPIO_OUT_EN);
+	if (bttv_gpio)
+		bttv_gpio_tracking(btv,"cleanup");
+
+	/* tell gpio modules we are leaving ... */
+	btv->shutdown=1;
+	bttv_input_fini(btv);
+	bttv_sub_del_devices(&btv->c);
+
+	/* unregister i2c_bus + input */
+	fini_bttv_i2c(btv);
+
+	/* unregister video4linux */
+	bttv_unregister_video(btv);
+
+	/* free allocated memory */
+	btcx_riscmem_free(btv->c.pci,&btv->main);
+
+	/* free ressources */
+	free_irq(btv->c.pci->irq,btv);
+	iounmap(btv->bt848_mmio);
+	release_mem_region(pci_resource_start(btv->c.pci,0),
+			   pci_resource_len(btv->c.pci,0));
+
+	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 v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
+	struct bttv *btv = to_bttv(v4l2_dev);
+	struct bttv_buffer_set idle;
+	unsigned long flags;
+
+	dprintk("%d: suspend %d\n", btv->c.nr, state.event);
+
+	/* stop dma + irqs */
+	spin_lock_irqsave(&btv->s_lock,flags);
+	memset(&idle, 0, sizeof(idle));
+	btv->state.video = btv->curr;
+	btv->state.vbi   = btv->cvbi;
+	btv->state.loop_irq = btv->loop_irq;
+	btv->curr = idle;
+	btv->loop_irq = 0;
+	bttv_buffer_activate_video(btv, &idle);
+	bttv_buffer_activate_vbi(btv, NULL);
+	bttv_set_dma(btv, 0);
+	btwrite(0, BT848_INT_MASK);
+	spin_unlock_irqrestore(&btv->s_lock,flags);
+
+	/* save bt878 state */
+	btv->state.gpio_enable = btread(BT848_GPIO_OUT_EN);
+	btv->state.gpio_data   = gpio_read();
+
+	/* save pci state */
+	pci_save_state(pci_dev);
+	if (0 != pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state))) {
+		pci_disable_device(pci_dev);
+		btv->state.disabled = 1;
+	}
+	return 0;
+}
+
+static int bttv_resume(struct pci_dev *pci_dev)
+{
+	struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
+	struct bttv *btv = to_bttv(v4l2_dev);
+	unsigned long flags;
+	int err;
+
+	dprintk("%d: resume\n", btv->c.nr);
+
+	/* restore pci state */
+	if (btv->state.disabled) {
+		err=pci_enable_device(pci_dev);
+		if (err) {
+			pr_warn("%d: Can't enable device\n", btv->c.nr);
+			return err;
+		}
+		btv->state.disabled = 0;
+	}
+	err=pci_set_power_state(pci_dev, PCI_D0);
+	if (err) {
+		pci_disable_device(pci_dev);
+		pr_warn("%d: Can't enable device\n", btv->c.nr);
+		btv->state.disabled = 1;
+		return err;
+	}
+
+	pci_restore_state(pci_dev);
+
+	/* restore bt878 state */
+	bttv_reinit_bt848(btv);
+	gpio_inout(0xffffff, btv->state.gpio_enable);
+	gpio_write(btv->state.gpio_data);
+
+	/* restart dma */
+	spin_lock_irqsave(&btv->s_lock,flags);
+	btv->curr = btv->state.video;
+	btv->cvbi = btv->state.vbi;
+	btv->loop_irq = btv->state.loop_irq;
+	bttv_buffer_activate_video(btv, &btv->curr);
+	bttv_buffer_activate_vbi(btv, btv->cvbi);
+	bttv_set_dma(btv, 0);
+	spin_unlock_irqrestore(&btv->s_lock,flags);
+	return 0;
+}
+#endif
+
+static struct pci_device_id bttv_pci_tbl[] = {
+	{PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT848), 0},
+	{PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT849), 0},
+	{PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT878), 0},
+	{PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT879), 0},
+	{PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_FUSION879), 0},
+	{0,}
+};
+
+MODULE_DEVICE_TABLE(pci, bttv_pci_tbl);
+
+static struct pci_driver bttv_pci_driver = {
+	.name     = "bttv",
+	.id_table = bttv_pci_tbl,
+	.probe    = bttv_probe,
+	.remove   = __devexit_p(bttv_remove),
+#ifdef CONFIG_PM
+	.suspend  = bttv_suspend,
+	.resume   = bttv_resume,
+#endif
+};
+
+static int __init bttv_init_module(void)
+{
+	int ret;
+
+	bttv_num = 0;
+
+	pr_info("driver version %s loaded\n", BTTV_VERSION);
+	if (gbuffers < 2 || gbuffers > VIDEO_MAX_FRAME)
+		gbuffers = 2;
+	if (gbufsize > BTTV_MAX_FBUF)
+		gbufsize = BTTV_MAX_FBUF;
+	gbufsize = (gbufsize + PAGE_SIZE - 1) & PAGE_MASK;
+	if (bttv_verbose)
+		pr_info("using %d buffers with %dk (%d pages) each for capture\n",
+			gbuffers, gbufsize >> 10, gbufsize >> PAGE_SHIFT);
+
+	bttv_check_chipset();
+
+	ret = bus_register(&bttv_sub_bus_type);
+	if (ret < 0) {
+		pr_warn("bus_register error: %d\n", ret);
+		return ret;
+	}
+	ret = pci_register_driver(&bttv_pci_driver);
+	if (ret < 0)
+		bus_unregister(&bttv_sub_bus_type);
+
+	return ret;
+}
+
+static void __exit bttv_cleanup_module(void)
+{
+	pci_unregister_driver(&bttv_pci_driver);
+	bus_unregister(&bttv_sub_bus_type);
+}
+
+module_init(bttv_init_module);
+module_exit(bttv_cleanup_module);
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/pci/bt8xx/bttv-gpio.c b/drivers/media/pci/bt8xx/bttv-gpio.c
new file mode 100644
index 0000000..922e823
--- /dev/null
+++ b/drivers/media/pci/bt8xx/bttv-gpio.c
@@ -0,0 +1,189 @@
+/*
+
+    bttv-gpio.c  --  gpio sub drivers
+
+    sysfs-based sub driver interface for bttv
+    mainly intended for gpio access
+
+
+    Copyright (C) 1996,97,98 Ralph  Metzler (rjkm@thp.uni-koeln.de)
+			   & Marcus Metzler (mocm@thp.uni-koeln.de)
+    (c) 1999-2003 Gerd Knorr <kraxel@bytesex.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.
+
+*/
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <asm/io.h>
+
+#include "bttvp.h"
+
+/* ----------------------------------------------------------------------- */
+/* internal: the bttv "bus"                                                */
+
+static int bttv_sub_bus_match(struct device *dev, struct device_driver *drv)
+{
+	struct bttv_sub_driver *sub = to_bttv_sub_drv(drv);
+	int len = strlen(sub->wanted);
+
+	if (0 == strncmp(dev_name(dev), sub->wanted, len))
+		return 1;
+	return 0;
+}
+
+static int bttv_sub_probe(struct device *dev)
+{
+	struct bttv_sub_device *sdev = to_bttv_sub_dev(dev);
+	struct bttv_sub_driver *sub = to_bttv_sub_drv(dev->driver);
+
+	return sub->probe ? sub->probe(sdev) : -ENODEV;
+}
+
+static int bttv_sub_remove(struct device *dev)
+{
+	struct bttv_sub_device *sdev = to_bttv_sub_dev(dev);
+	struct bttv_sub_driver *sub = to_bttv_sub_drv(dev->driver);
+
+	if (sub->remove)
+		sub->remove(sdev);
+	return 0;
+}
+
+struct bus_type bttv_sub_bus_type = {
+	.name   = "bttv-sub",
+	.match  = &bttv_sub_bus_match,
+	.probe  = bttv_sub_probe,
+	.remove = bttv_sub_remove,
+};
+
+static void release_sub_device(struct device *dev)
+{
+	struct bttv_sub_device *sub = to_bttv_sub_dev(dev);
+	kfree(sub);
+}
+
+int bttv_sub_add_device(struct bttv_core *core, char *name)
+{
+	struct bttv_sub_device *sub;
+	int err;
+
+	sub = kzalloc(sizeof(*sub),GFP_KERNEL);
+	if (NULL == sub)
+		return -ENOMEM;
+
+	sub->core        = core;
+	sub->dev.parent  = &core->pci->dev;
+	sub->dev.bus     = &bttv_sub_bus_type;
+	sub->dev.release = release_sub_device;
+	dev_set_name(&sub->dev, "%s%d", name, core->nr);
+
+	err = device_register(&sub->dev);
+	if (0 != err) {
+		kfree(sub);
+		return err;
+	}
+	pr_info("%d: add subdevice \"%s\"\n", core->nr, dev_name(&sub->dev));
+	list_add_tail(&sub->list,&core->subs);
+	return 0;
+}
+
+int bttv_sub_del_devices(struct bttv_core *core)
+{
+	struct bttv_sub_device *sub, *save;
+
+	list_for_each_entry_safe(sub, save, &core->subs, list) {
+		list_del(&sub->list);
+		device_unregister(&sub->dev);
+	}
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+/* external: sub-driver register/unregister                                */
+
+int bttv_sub_register(struct bttv_sub_driver *sub, char *wanted)
+{
+	sub->drv.bus = &bttv_sub_bus_type;
+	snprintf(sub->wanted,sizeof(sub->wanted),"%s",wanted);
+	return driver_register(&sub->drv);
+}
+EXPORT_SYMBOL(bttv_sub_register);
+
+int bttv_sub_unregister(struct bttv_sub_driver *sub)
+{
+	driver_unregister(&sub->drv);
+	return 0;
+}
+EXPORT_SYMBOL(bttv_sub_unregister);
+
+/* ----------------------------------------------------------------------- */
+/* external: gpio access functions                                         */
+
+void bttv_gpio_inout(struct bttv_core *core, u32 mask, u32 outbits)
+{
+	struct bttv *btv = container_of(core, struct bttv, c);
+	unsigned long flags;
+	u32 data;
+
+	spin_lock_irqsave(&btv->gpio_lock,flags);
+	data = btread(BT848_GPIO_OUT_EN);
+	data = data & ~mask;
+	data = data | (mask & outbits);
+	btwrite(data,BT848_GPIO_OUT_EN);
+	spin_unlock_irqrestore(&btv->gpio_lock,flags);
+}
+
+u32 bttv_gpio_read(struct bttv_core *core)
+{
+	struct bttv *btv = container_of(core, struct bttv, c);
+	u32 value;
+
+	value = btread(BT848_GPIO_DATA);
+	return value;
+}
+
+void bttv_gpio_write(struct bttv_core *core, u32 value)
+{
+	struct bttv *btv = container_of(core, struct bttv, c);
+
+	btwrite(value,BT848_GPIO_DATA);
+}
+
+void bttv_gpio_bits(struct bttv_core *core, u32 mask, u32 bits)
+{
+	struct bttv *btv = container_of(core, struct bttv, c);
+	unsigned long flags;
+	u32 data;
+
+	spin_lock_irqsave(&btv->gpio_lock,flags);
+	data = btread(BT848_GPIO_DATA);
+	data = data & ~mask;
+	data = data | (mask & bits);
+	btwrite(data,BT848_GPIO_DATA);
+	spin_unlock_irqrestore(&btv->gpio_lock,flags);
+}
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/pci/bt8xx/bttv-i2c.c b/drivers/media/pci/bt8xx/bttv-i2c.c
new file mode 100644
index 0000000..580c8e6
--- /dev/null
+++ b/drivers/media/pci/bt8xx/bttv-i2c.c
@@ -0,0 +1,397 @@
+/*
+
+    bttv-i2c.c  --  all the i2c code is here
+
+    bttv - Bt848 frame grabber driver
+
+    Copyright (C) 1996,97,98 Ralph  Metzler (rjkm@thp.uni-koeln.de)
+			   & Marcus Metzler (mocm@thp.uni-koeln.de)
+    (c) 1999-2003 Gerd Knorr <kraxel@bytesex.org>
+
+    (c) 2005 Mauro Carvalho Chehab <mchehab@infradead.org>
+	- Multituner support and i2c address binding
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+
+#include "bttvp.h"
+#include <media/v4l2-common.h>
+#include <linux/jiffies.h>
+#include <asm/io.h>
+
+static int i2c_debug;
+static int i2c_hw;
+static int i2c_scan;
+module_param(i2c_debug, int, 0644);
+MODULE_PARM_DESC(i2c_debug, "configure i2c debug level");
+module_param(i2c_hw,    int, 0444);
+MODULE_PARM_DESC(i2c_hw,"force use of hardware i2c support, "
+			"instead of software bitbang");
+module_param(i2c_scan,  int, 0444);
+MODULE_PARM_DESC(i2c_scan,"scan i2c bus at insmod time");
+
+static unsigned int i2c_udelay = 5;
+module_param(i2c_udelay, int, 0444);
+MODULE_PARM_DESC(i2c_udelay,"soft i2c delay at insmod time, in usecs "
+		"(should be 5 or higher). Lower value means higher bus speed.");
+
+/* ----------------------------------------------------------------------- */
+/* I2C functions - bitbanging adapter (software i2c)                       */
+
+static void bttv_bit_setscl(void *data, int state)
+{
+	struct bttv *btv = (struct bttv*)data;
+
+	if (state)
+		btv->i2c_state |= 0x02;
+	else
+		btv->i2c_state &= ~0x02;
+	btwrite(btv->i2c_state, BT848_I2C);
+	btread(BT848_I2C);
+}
+
+static void bttv_bit_setsda(void *data, int state)
+{
+	struct bttv *btv = (struct bttv*)data;
+
+	if (state)
+		btv->i2c_state |= 0x01;
+	else
+		btv->i2c_state &= ~0x01;
+	btwrite(btv->i2c_state, BT848_I2C);
+	btread(BT848_I2C);
+}
+
+static int bttv_bit_getscl(void *data)
+{
+	struct bttv *btv = (struct bttv*)data;
+	int state;
+
+	state = btread(BT848_I2C) & 0x02 ? 1 : 0;
+	return state;
+}
+
+static int bttv_bit_getsda(void *data)
+{
+	struct bttv *btv = (struct bttv*)data;
+	int state;
+
+	state = btread(BT848_I2C) & 0x01;
+	return state;
+}
+
+static struct i2c_algo_bit_data __devinitdata bttv_i2c_algo_bit_template = {
+	.setsda  = bttv_bit_setsda,
+	.setscl  = bttv_bit_setscl,
+	.getsda  = bttv_bit_getsda,
+	.getscl  = bttv_bit_getscl,
+	.udelay  = 16,
+	.timeout = 200,
+};
+
+/* ----------------------------------------------------------------------- */
+/* I2C functions - hardware i2c                                            */
+
+static u32 functionality(struct i2c_adapter *adap)
+{
+	return I2C_FUNC_SMBUS_EMUL;
+}
+
+static int
+bttv_i2c_wait_done(struct bttv *btv)
+{
+	int rc = 0;
+
+	/* timeout */
+	if (wait_event_interruptible_timeout(btv->i2c_queue,
+	    btv->i2c_done, msecs_to_jiffies(85)) == -ERESTARTSYS)
+		rc = -EIO;
+
+	if (btv->i2c_done & BT848_INT_RACK)
+		rc = 1;
+	btv->i2c_done = 0;
+	return rc;
+}
+
+#define I2C_HW (BT878_I2C_MODE  | BT848_I2C_SYNC |\
+		BT848_I2C_SCL | BT848_I2C_SDA)
+
+static int
+bttv_i2c_sendbytes(struct bttv *btv, const struct i2c_msg *msg, int last)
+{
+	u32 xmit;
+	int retval,cnt;
+
+	/* sanity checks */
+	if (0 == msg->len)
+		return -EINVAL;
+
+	/* start, address + first byte */
+	xmit = (msg->addr << 25) | (msg->buf[0] << 16) | I2C_HW;
+	if (msg->len > 1 || !last)
+		xmit |= BT878_I2C_NOSTOP;
+	btwrite(xmit, BT848_I2C);
+	retval = bttv_i2c_wait_done(btv);
+	if (retval < 0)
+		goto err;
+	if (retval == 0)
+		goto eio;
+	if (i2c_debug) {
+		pr_cont(" <W %02x %02x", msg->addr << 1, msg->buf[0]);
+	}
+
+	for (cnt = 1; cnt < msg->len; cnt++ ) {
+		/* following bytes */
+		xmit = (msg->buf[cnt] << 24) | I2C_HW | BT878_I2C_NOSTART;
+		if (cnt < msg->len-1 || !last)
+			xmit |= BT878_I2C_NOSTOP;
+		btwrite(xmit, BT848_I2C);
+		retval = bttv_i2c_wait_done(btv);
+		if (retval < 0)
+			goto err;
+		if (retval == 0)
+			goto eio;
+		if (i2c_debug)
+			pr_cont(" %02x", msg->buf[cnt]);
+	}
+	if (!(xmit & BT878_I2C_NOSTOP))
+		pr_cont(">\n");
+	return msg->len;
+
+ eio:
+	retval = -EIO;
+ err:
+	if (i2c_debug)
+		pr_cont(" ERR: %d\n",retval);
+	return retval;
+}
+
+static int
+bttv_i2c_readbytes(struct bttv *btv, const struct i2c_msg *msg, int last)
+{
+	u32 xmit;
+	u32 cnt;
+	int retval;
+
+	for (cnt = 0; cnt < msg->len; cnt++) {
+		xmit = (msg->addr << 25) | (1 << 24) | I2C_HW;
+		if (cnt < msg->len-1)
+			xmit |= BT848_I2C_W3B;
+		if (cnt < msg->len-1 || !last)
+			xmit |= BT878_I2C_NOSTOP;
+		if (cnt)
+			xmit |= BT878_I2C_NOSTART;
+
+		if (i2c_debug) {
+			if (!(xmit & BT878_I2C_NOSTART))
+				pr_cont(" <R %02x", (msg->addr << 1) +1);
+		}
+
+		btwrite(xmit, BT848_I2C);
+		retval = bttv_i2c_wait_done(btv);
+		if (retval < 0)
+			goto err;
+		if (retval == 0)
+			goto eio;
+		msg->buf[cnt] = ((u32)btread(BT848_I2C) >> 8) & 0xff;
+		if (i2c_debug) {
+			pr_cont(" =%02x", msg->buf[cnt]);
+		}
+		if (i2c_debug && !(xmit & BT878_I2C_NOSTOP))
+			pr_cont(" >\n");
+	}
+
+
+	return msg->len;
+
+ eio:
+	retval = -EIO;
+ err:
+	if (i2c_debug)
+		pr_cont(" ERR: %d\n",retval);
+	return retval;
+}
+
+static int bttv_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
+{
+	struct v4l2_device *v4l2_dev = i2c_get_adapdata(i2c_adap);
+	struct bttv *btv = to_bttv(v4l2_dev);
+	int retval = 0;
+	int i;
+
+	if (i2c_debug)
+		pr_debug("bt-i2c:");
+
+	btwrite(BT848_INT_I2CDONE|BT848_INT_RACK, BT848_INT_STAT);
+	for (i = 0 ; i < num; i++) {
+		if (msgs[i].flags & I2C_M_RD) {
+			/* read */
+			retval = bttv_i2c_readbytes(btv, &msgs[i], i+1 == num);
+			if (retval < 0)
+				goto err;
+		} else {
+			/* write */
+			retval = bttv_i2c_sendbytes(btv, &msgs[i], i+1 == num);
+			if (retval < 0)
+				goto err;
+		}
+	}
+	return num;
+
+ err:
+	return retval;
+}
+
+static const struct i2c_algorithm bttv_algo = {
+	.master_xfer   = bttv_i2c_xfer,
+	.functionality = functionality,
+};
+
+/* ----------------------------------------------------------------------- */
+/* I2C functions - common stuff                                            */
+
+/* read I2C */
+int bttv_I2CRead(struct bttv *btv, unsigned char addr, char *probe_for)
+{
+	unsigned char buffer = 0;
+
+	if (0 != btv->i2c_rc)
+		return -1;
+	if (bttv_verbose && NULL != probe_for)
+		pr_info("%d: i2c: checking for %s @ 0x%02x... ",
+			btv->c.nr, probe_for, addr);
+	btv->i2c_client.addr = addr >> 1;
+	if (1 != i2c_master_recv(&btv->i2c_client, &buffer, 1)) {
+		if (NULL != probe_for) {
+			if (bttv_verbose)
+				pr_cont("not found\n");
+		} else
+			pr_warn("%d: i2c read 0x%x: error\n",
+				btv->c.nr, addr);
+		return -1;
+	}
+	if (bttv_verbose && NULL != probe_for)
+		pr_cont("found\n");
+	return buffer;
+}
+
+/* write I2C */
+int bttv_I2CWrite(struct bttv *btv, unsigned char addr, unsigned char b1,
+		    unsigned char b2, int both)
+{
+	unsigned char buffer[2];
+	int bytes = both ? 2 : 1;
+
+	if (0 != btv->i2c_rc)
+		return -1;
+	btv->i2c_client.addr = addr >> 1;
+	buffer[0] = b1;
+	buffer[1] = b2;
+	if (bytes != i2c_master_send(&btv->i2c_client, buffer, bytes))
+		return -1;
+	return 0;
+}
+
+/* read EEPROM content */
+void __devinit bttv_readee(struct bttv *btv, unsigned char *eedata, int addr)
+{
+	memset(eedata, 0, 256);
+	if (0 != btv->i2c_rc)
+		return;
+	btv->i2c_client.addr = addr >> 1;
+	tveeprom_read(&btv->i2c_client, eedata, 256);
+}
+
+static char *i2c_devs[128] = {
+	[ 0x1c >> 1 ] = "lgdt330x",
+	[ 0x30 >> 1 ] = "IR (hauppauge)",
+	[ 0x80 >> 1 ] = "msp34xx",
+	[ 0x86 >> 1 ] = "tda9887",
+	[ 0xa0 >> 1 ] = "eeprom",
+	[ 0xc0 >> 1 ] = "tuner (analog)",
+	[ 0xc2 >> 1 ] = "tuner (analog)",
+};
+
+static void do_i2c_scan(char *name, struct i2c_client *c)
+{
+	unsigned char buf;
+	int i,rc;
+
+	for (i = 0; i < ARRAY_SIZE(i2c_devs); i++) {
+		c->addr = i;
+		rc = i2c_master_recv(c,&buf,0);
+		if (rc < 0)
+			continue;
+		pr_info("%s: i2c scan: found device @ 0x%x  [%s]\n",
+			name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???");
+	}
+}
+
+/* init + register i2c adapter */
+int __devinit init_bttv_i2c(struct bttv *btv)
+{
+	strlcpy(btv->i2c_client.name, "bttv internal", I2C_NAME_SIZE);
+
+	if (i2c_hw)
+		btv->use_i2c_hw = 1;
+	if (btv->use_i2c_hw) {
+		/* bt878 */
+		strlcpy(btv->c.i2c_adap.name, "bt878",
+			sizeof(btv->c.i2c_adap.name));
+		btv->c.i2c_adap.algo = &bttv_algo;
+	} else {
+		/* bt848 */
+	/* Prevents usage of invalid delay values */
+		if (i2c_udelay<5)
+			i2c_udelay=5;
+
+		strlcpy(btv->c.i2c_adap.name, "bttv",
+			sizeof(btv->c.i2c_adap.name));
+		memcpy(&btv->i2c_algo, &bttv_i2c_algo_bit_template,
+		       sizeof(bttv_i2c_algo_bit_template));
+		btv->i2c_algo.udelay = i2c_udelay;
+		btv->i2c_algo.data = btv;
+		btv->c.i2c_adap.algo_data = &btv->i2c_algo;
+	}
+	btv->c.i2c_adap.owner = THIS_MODULE;
+
+	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->c.v4l2_dev);
+	btv->i2c_client.adapter = &btv->c.i2c_adap;
+
+
+	if (btv->use_i2c_hw) {
+		btv->i2c_rc = i2c_add_adapter(&btv->c.i2c_adap);
+	} else {
+		bttv_bit_setscl(btv,1);
+		bttv_bit_setsda(btv,1);
+		btv->i2c_rc = i2c_bit_add_bus(&btv->c.i2c_adap);
+	}
+	if (0 == btv->i2c_rc && i2c_scan)
+		do_i2c_scan(btv->c.v4l2_dev.name, &btv->i2c_client);
+
+	return btv->i2c_rc;
+}
diff --git a/drivers/media/pci/bt8xx/bttv-if.c b/drivers/media/pci/bt8xx/bttv-if.c
new file mode 100644
index 0000000..a6a540d
--- /dev/null
+++ b/drivers/media/pci/bt8xx/bttv-if.c
@@ -0,0 +1,121 @@
+/*
+
+    bttv-if.c  --  old gpio interface to other kernel modules
+		   don't use in new code, will go away in 2.7
+		   have a look at bttv-gpio.c instead.
+
+    bttv - Bt848 frame grabber driver
+
+    Copyright (C) 1996,97,98 Ralph  Metzler (rjkm@thp.uni-koeln.de)
+			   & Marcus Metzler (mocm@thp.uni-koeln.de)
+    (c) 1999-2003 Gerd Knorr <kraxel@bytesex.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/module.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+
+#include "bttvp.h"
+
+EXPORT_SYMBOL(bttv_get_pcidev);
+EXPORT_SYMBOL(bttv_gpio_enable);
+EXPORT_SYMBOL(bttv_read_gpio);
+EXPORT_SYMBOL(bttv_write_gpio);
+
+/* ----------------------------------------------------------------------- */
+/* Exported functions - for other modules which want to access the         */
+/*                      gpio ports (IR for example)                        */
+/*                      see bttv.h for comments                            */
+
+struct pci_dev* bttv_get_pcidev(unsigned int card)
+{
+	if (card >= bttv_num)
+		return NULL;
+	if (!bttvs[card])
+		return NULL;
+
+	return bttvs[card]->c.pci;
+}
+
+
+int bttv_gpio_enable(unsigned int card, unsigned long mask, unsigned long data)
+{
+	struct bttv *btv;
+
+	if (card >= bttv_num) {
+		return -EINVAL;
+	}
+
+	btv = bttvs[card];
+	if (!btv)
+		return -ENODEV;
+
+	gpio_inout(mask,data);
+	if (bttv_gpio)
+		bttv_gpio_tracking(btv,"extern enable");
+	return 0;
+}
+
+int bttv_read_gpio(unsigned int card, unsigned long *data)
+{
+	struct bttv *btv;
+
+	if (card >= bttv_num) {
+		return -EINVAL;
+	}
+
+	btv = bttvs[card];
+	if (!btv)
+		return -ENODEV;
+
+	if(btv->shutdown) {
+		return -ENODEV;
+	}
+
+/* prior setting BT848_GPIO_REG_INP is (probably) not needed
+   because we set direct input on init */
+	*data = gpio_read();
+	return 0;
+}
+
+int bttv_write_gpio(unsigned int card, unsigned long mask, unsigned long data)
+{
+	struct bttv *btv;
+
+	if (card >= bttv_num) {
+		return -EINVAL;
+	}
+
+	btv = bttvs[card];
+	if (!btv)
+		return -ENODEV;
+
+/* prior setting BT848_GPIO_REG_INP is (probably) not needed
+   because direct input is set on init */
+	gpio_bits(mask,data);
+	if (bttv_gpio)
+		bttv_gpio_tracking(btv,"extern write");
+	return 0;
+}
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/pci/bt8xx/bttv-input.c b/drivers/media/pci/bt8xx/bttv-input.c
new file mode 100644
index 0000000..ef4c7cd
--- /dev/null
+++ b/drivers/media/pci/bt8xx/bttv-input.c
@@ -0,0 +1,589 @@
+/*
+ *
+ * Copyright (c) 2003 Gerd Knorr
+ * Copyright (c) 2003 Pavel Machek
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/input.h>
+#include <linux/slab.h>
+
+#include "bttv.h"
+#include "bttvp.h"
+
+
+static int ir_debug;
+module_param(ir_debug, int, 0644);
+
+static int ir_rc5_remote_gap = 885;
+module_param(ir_rc5_remote_gap, int, 0644);
+
+#undef dprintk
+#define dprintk(fmt, ...)			\
+do {						\
+	if (ir_debug >= 1)			\
+		pr_info(fmt, ##__VA_ARGS__);	\
+} while (0)
+
+#define DEVNAME "bttv-input"
+
+#define MODULE_NAME "bttv"
+
+/* ---------------------------------------------------------------------- */
+
+static void ir_handle_key(struct bttv *btv)
+{
+	struct bttv_ir *ir = btv->remote;
+	u32 gpio,data;
+
+	/* read gpio value */
+	gpio = bttv_gpio_read(&btv->c);
+	if (ir->polling) {
+		if (ir->last_gpio == gpio)
+			return;
+		ir->last_gpio = gpio;
+	}
+
+	/* extract data */
+	data = ir_extract_bits(gpio, ir->mask_keycode);
+	dprintk("irq gpio=0x%x code=%d | %s%s%s\n",
+		gpio, data,
+		ir->polling               ? "poll"  : "irq",
+		(gpio & ir->mask_keydown) ? " down" : "",
+		(gpio & ir->mask_keyup)   ? " up"   : "");
+
+	if ((ir->mask_keydown && (gpio & ir->mask_keydown)) ||
+	    (ir->mask_keyup   && !(gpio & ir->mask_keyup))) {
+		rc_keydown_notimeout(ir->dev, data, 0);
+	} else {
+		/* HACK: Probably, ir->mask_keydown is missing
+		   for this board */
+		if (btv->c.type == BTTV_BOARD_WINFAST2000)
+			rc_keydown_notimeout(ir->dev, data, 0);
+
+		rc_keyup(ir->dev);
+	}
+}
+
+static void ir_enltv_handle_key(struct bttv *btv)
+{
+	struct bttv_ir *ir = btv->remote;
+	u32 gpio, data, keyup;
+
+	/* read gpio value */
+	gpio = bttv_gpio_read(&btv->c);
+
+	/* extract data */
+	data = ir_extract_bits(gpio, ir->mask_keycode);
+
+	/* Check if it is keyup */
+	keyup = (gpio & ir->mask_keyup) ? 1 << 31 : 0;
+
+	if ((ir->last_gpio & 0x7f) != data) {
+		dprintk("gpio=0x%x code=%d | %s\n",
+			gpio, data,
+			(gpio & ir->mask_keyup) ? " up" : "up/down");
+
+		rc_keydown_notimeout(ir->dev, data, 0);
+		if (keyup)
+			rc_keyup(ir->dev);
+	} else {
+		if ((ir->last_gpio & 1 << 31) == keyup)
+			return;
+
+		dprintk("(cnt) gpio=0x%x code=%d | %s\n",
+			gpio, data,
+			(gpio & ir->mask_keyup) ? " up" : "down");
+
+		if (keyup)
+			rc_keyup(ir->dev);
+		else
+			rc_keydown_notimeout(ir->dev, data, 0);
+	}
+
+	ir->last_gpio = data | keyup;
+}
+
+static int bttv_rc5_irq(struct bttv *btv);
+
+void bttv_input_irq(struct bttv *btv)
+{
+	struct bttv_ir *ir = btv->remote;
+
+	if (ir->rc5_gpio)
+		bttv_rc5_irq(btv);
+	else if (!ir->polling)
+		ir_handle_key(btv);
+}
+
+static void bttv_input_timer(unsigned long data)
+{
+	struct bttv *btv = (struct bttv*)data;
+	struct bttv_ir *ir = btv->remote;
+
+	if (btv->c.type == BTTV_BOARD_ENLTV_FM_2)
+		ir_enltv_handle_key(btv);
+	else
+		ir_handle_key(btv);
+	mod_timer(&ir->timer, jiffies + msecs_to_jiffies(ir->polling));
+}
+
+/*
+ * FIXME: Nebula digi uses the legacy way to decode RC5, instead of relying
+ * on the rc-core way. As we need to be sure that both IRQ transitions are
+ * properly triggered, Better to touch it only with this hardware for
+ * testing.
+ */
+
+#define RC5_START(x)	(((x) >> 12) & 3)
+#define RC5_TOGGLE(x)	(((x) >> 11) & 1)
+#define RC5_ADDR(x)	(((x) >> 6) & 31)
+#define RC5_INSTR(x)	((x) & 63)
+
+/* decode raw bit pattern to RC5 code */
+static u32 bttv_rc5_decode(unsigned int code)
+{
+	unsigned int org_code = code;
+	unsigned int pair;
+	unsigned int rc5 = 0;
+	int i;
+
+	for (i = 0; i < 14; ++i) {
+		pair = code & 0x3;
+		code >>= 2;
+
+		rc5 <<= 1;
+		switch (pair) {
+		case 0:
+		case 2:
+			break;
+		case 1:
+			rc5 |= 1;
+		break;
+		case 3:
+			dprintk("rc5_decode(%x) bad code\n",
+				org_code);
+			return 0;
+		}
+	}
+	dprintk("code=%x, rc5=%x, start=%x, toggle=%x, address=%x, "
+		"instr=%x\n", rc5, org_code, RC5_START(rc5),
+		RC5_TOGGLE(rc5), RC5_ADDR(rc5), RC5_INSTR(rc5));
+	return rc5;
+}
+
+static void bttv_rc5_timer_end(unsigned long data)
+{
+	struct bttv_ir *ir = (struct bttv_ir *)data;
+	struct timeval tv;
+	u32 gap;
+	u32 rc5 = 0;
+
+	/* get time */
+	do_gettimeofday(&tv);
+
+	/* avoid overflow with gap >1s */
+	if (tv.tv_sec - ir->base_time.tv_sec > 1) {
+		gap = 200000;
+	} else {
+		gap = 1000000 * (tv.tv_sec - ir->base_time.tv_sec) +
+		    tv.tv_usec - ir->base_time.tv_usec;
+	}
+
+	/* signal we're ready to start a new code */
+	ir->active = false;
+
+	/* Allow some timer jitter (RC5 is ~24ms anyway so this is ok) */
+	if (gap < 28000) {
+		dprintk("spurious timer_end\n");
+		return;
+	}
+
+	if (ir->last_bit < 20) {
+		/* ignore spurious codes (caused by light/other remotes) */
+		dprintk("short code: %x\n", ir->code);
+	} else {
+		ir->code = (ir->code << ir->shift_by) | 1;
+		rc5 = bttv_rc5_decode(ir->code);
+
+		/* two start bits? */
+		if (RC5_START(rc5) != ir->start) {
+			pr_info(DEVNAME ":"
+			       " rc5 start bits invalid: %u\n", RC5_START(rc5));
+
+			/* right address? */
+		} else if (RC5_ADDR(rc5) == ir->addr) {
+			u32 toggle = RC5_TOGGLE(rc5);
+			u32 instr = RC5_INSTR(rc5);
+
+			/* Good code */
+			rc_keydown(ir->dev, instr, toggle);
+			dprintk("instruction %x, toggle %x\n",
+				instr, toggle);
+		}
+	}
+}
+
+static int bttv_rc5_irq(struct bttv *btv)
+{
+	struct bttv_ir *ir = btv->remote;
+	struct timeval tv;
+	u32 gpio;
+	u32 gap;
+	unsigned long current_jiffies;
+
+	/* read gpio port */
+	gpio = bttv_gpio_read(&btv->c);
+
+	/* get time of bit */
+	current_jiffies = jiffies;
+	do_gettimeofday(&tv);
+
+	/* avoid overflow with gap >1s */
+	if (tv.tv_sec - ir->base_time.tv_sec > 1) {
+		gap = 200000;
+	} else {
+		gap = 1000000 * (tv.tv_sec - ir->base_time.tv_sec) +
+		    tv.tv_usec - ir->base_time.tv_usec;
+	}
+
+	dprintk("RC5 IRQ: gap %d us for %s\n",
+		gap, (gpio & 0x20) ? "mark" : "space");
+
+	/* remote IRQ? */
+	if (!(gpio & 0x20))
+		return 0;
+
+	/* active code => add bit */
+	if (ir->active) {
+		/* only if in the code (otherwise spurious IRQ or timer
+		   late) */
+		if (ir->last_bit < 28) {
+			ir->last_bit = (gap - ir_rc5_remote_gap / 2) /
+			    ir_rc5_remote_gap;
+			ir->code |= 1 << ir->last_bit;
+		}
+		/* starting new code */
+	} else {
+		ir->active = true;
+		ir->code = 0;
+		ir->base_time = tv;
+		ir->last_bit = 0;
+
+		mod_timer(&ir->timer, current_jiffies + msecs_to_jiffies(30));
+	}
+
+	/* toggle GPIO pin 4 to reset the irq */
+	bttv_gpio_write(&btv->c, gpio & ~(1 << 4));
+	bttv_gpio_write(&btv->c, gpio | (1 << 4));
+	return 1;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static void bttv_ir_start(struct bttv *btv, struct bttv_ir *ir)
+{
+	if (ir->polling) {
+		setup_timer(&ir->timer, bttv_input_timer, (unsigned long)btv);
+		ir->timer.expires  = jiffies + msecs_to_jiffies(1000);
+		add_timer(&ir->timer);
+	} else if (ir->rc5_gpio) {
+		/* set timer_end for code completion */
+		setup_timer(&ir->timer, bttv_rc5_timer_end, (unsigned long)ir);
+		ir->shift_by = 1;
+		ir->start = 3;
+		ir->addr = 0x0;
+		ir->rc5_remote_gap = ir_rc5_remote_gap;
+	}
+}
+
+static void bttv_ir_stop(struct bttv *btv)
+{
+	if (btv->remote->polling)
+		del_timer_sync(&btv->remote->timer);
+
+	if (btv->remote->rc5_gpio) {
+		u32 gpio;
+
+		del_timer_sync(&btv->remote->timer);
+
+		gpio = bttv_gpio_read(&btv->c);
+		bttv_gpio_write(&btv->c, gpio & ~(1 << 4));
+	}
+}
+
+/*
+ * Get_key functions used by I2C remotes
+ */
+
+static int get_key_pv951(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+{
+	unsigned char b;
+
+	/* poll IR chip */
+	if (1 != i2c_master_recv(ir->c, &b, 1)) {
+		dprintk("read error\n");
+		return -EIO;
+	}
+
+	/* ignore 0xaa */
+	if (b==0xaa)
+		return 0;
+	dprintk("key %02x\n", b);
+
+	/*
+	 * NOTE:
+	 * lirc_i2c maps the pv951 code as:
+	 *	addr = 0x61D6
+	 * 	cmd = bit_reverse (b)
+	 * So, it seems that this device uses NEC extended
+	 * I decided to not fix the table, due to two reasons:
+	 * 	1) Without the actual device, this is only a guess;
+	 * 	2) As the addr is not reported via I2C, nor can be changed,
+	 * 	   the device is bound to the vendor-provided RC.
+	 */
+
+	*ir_key = b;
+	*ir_raw = b;
+	return 1;
+}
+
+/* Instantiate the I2C IR receiver device, if present */
+void __devinit init_bttv_i2c_ir(struct bttv *btv)
+{
+	const unsigned short addr_list[] = {
+		0x1a, 0x18, 0x64, 0x30, 0x71,
+		I2C_CLIENT_END
+	};
+	struct i2c_board_info info;
+
+	if (0 != btv->i2c_rc)
+		return;
+
+	memset(&info, 0, sizeof(struct i2c_board_info));
+	memset(&btv->init_data, 0, sizeof(btv->init_data));
+	strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
+
+	switch (btv->c.type) {
+	case BTTV_BOARD_PV951:
+		btv->init_data.name = "PV951";
+		btv->init_data.get_key = get_key_pv951;
+		btv->init_data.ir_codes = RC_MAP_PV951;
+		info.addr = 0x4b;
+		break;
+	default:
+		/*
+		 * The external IR receiver is at i2c address 0x34 (0x35 for
+		 * reads).  Future Hauppauge cards will have an internal
+		 * receiver at 0x30 (0x31 for reads).  In theory, both can be
+		 * fitted, and Hauppauge suggest an external overrides an
+		 * internal.
+		 * That's why we probe 0x1a (~0x34) first. CB
+		 */
+
+		i2c_new_probed_device(&btv->c.i2c_adap, &info, addr_list, NULL);
+		return;
+	}
+
+	if (btv->init_data.name)
+		info.platform_data = &btv->init_data;
+	i2c_new_device(&btv->c.i2c_adap, &info);
+
+	return;
+}
+
+int __devexit fini_bttv_i2c(struct bttv *btv)
+{
+	if (0 != btv->i2c_rc)
+		return 0;
+
+	return i2c_del_adapter(&btv->c.i2c_adap);
+}
+
+int bttv_input_init(struct bttv *btv)
+{
+	struct bttv_ir *ir;
+	char *ir_codes = NULL;
+	struct rc_dev *rc;
+	int err = -ENOMEM;
+
+	if (!btv->has_remote)
+		return -ENODEV;
+
+	ir = kzalloc(sizeof(*ir),GFP_KERNEL);
+	rc = rc_allocate_device();
+	if (!ir || !rc)
+		goto err_out_free;
+
+	/* detect & configure */
+	switch (btv->c.type) {
+	case BTTV_BOARD_AVERMEDIA:
+	case BTTV_BOARD_AVPHONE98:
+	case BTTV_BOARD_AVERMEDIA98:
+		ir_codes         = RC_MAP_AVERMEDIA;
+		ir->mask_keycode = 0xf88000;
+		ir->mask_keydown = 0x010000;
+		ir->polling      = 50; // ms
+		break;
+
+	case BTTV_BOARD_AVDVBT_761:
+	case BTTV_BOARD_AVDVBT_771:
+		ir_codes         = RC_MAP_AVERMEDIA_DVBT;
+		ir->mask_keycode = 0x0f00c0;
+		ir->mask_keydown = 0x000020;
+		ir->polling      = 50; // ms
+		break;
+
+	case BTTV_BOARD_PXELVWPLTVPAK:
+		ir_codes         = RC_MAP_PIXELVIEW;
+		ir->mask_keycode = 0x003e00;
+		ir->mask_keyup   = 0x010000;
+		ir->polling      = 50; // ms
+		break;
+	case BTTV_BOARD_PV_M4900:
+	case BTTV_BOARD_PV_BT878P_9B:
+	case BTTV_BOARD_PV_BT878P_PLUS:
+		ir_codes         = RC_MAP_PIXELVIEW;
+		ir->mask_keycode = 0x001f00;
+		ir->mask_keyup   = 0x008000;
+		ir->polling      = 50; // ms
+		break;
+
+	case BTTV_BOARD_WINFAST2000:
+		ir_codes         = RC_MAP_WINFAST;
+		ir->mask_keycode = 0x1f8;
+		break;
+	case BTTV_BOARD_MAGICTVIEW061:
+	case BTTV_BOARD_MAGICTVIEW063:
+		ir_codes         = RC_MAP_WINFAST;
+		ir->mask_keycode = 0x0008e000;
+		ir->mask_keydown = 0x00200000;
+		break;
+	case BTTV_BOARD_APAC_VIEWCOMP:
+		ir_codes         = RC_MAP_APAC_VIEWCOMP;
+		ir->mask_keycode = 0x001f00;
+		ir->mask_keyup   = 0x008000;
+		ir->polling      = 50; // ms
+		break;
+	case BTTV_BOARD_ASKEY_CPH03X:
+	case BTTV_BOARD_CONCEPTRONIC_CTVFMI2:
+	case BTTV_BOARD_CONTVFMI:
+		ir_codes         = RC_MAP_PIXELVIEW;
+		ir->mask_keycode = 0x001F00;
+		ir->mask_keyup   = 0x006000;
+		ir->polling      = 50; // ms
+		break;
+	case BTTV_BOARD_NEBULA_DIGITV:
+		ir_codes = RC_MAP_NEBULA;
+		ir->rc5_gpio = true;
+		break;
+	case BTTV_BOARD_MACHTV_MAGICTV:
+		ir_codes         = RC_MAP_APAC_VIEWCOMP;
+		ir->mask_keycode = 0x001F00;
+		ir->mask_keyup   = 0x004000;
+		ir->polling      = 50; /* ms */
+		break;
+	case BTTV_BOARD_KOZUMI_KTV_01C:
+		ir_codes         = RC_MAP_PCTV_SEDNA;
+		ir->mask_keycode = 0x001f00;
+		ir->mask_keyup   = 0x006000;
+		ir->polling      = 50; /* ms */
+		break;
+	case BTTV_BOARD_ENLTV_FM_2:
+		ir_codes         = RC_MAP_ENCORE_ENLTV2;
+		ir->mask_keycode = 0x00fd00;
+		ir->mask_keyup   = 0x000080;
+		ir->polling      = 1; /* ms */
+		ir->last_gpio    = ir_extract_bits(bttv_gpio_read(&btv->c),
+						   ir->mask_keycode);
+		break;
+	}
+	if (NULL == ir_codes) {
+		dprintk("Ooops: IR config error [card=%d]\n", btv->c.type);
+		err = -ENODEV;
+		goto err_out_free;
+	}
+
+	if (ir->rc5_gpio) {
+		u32 gpio;
+		/* enable remote irq */
+		bttv_gpio_inout(&btv->c, (1 << 4), 1 << 4);
+		gpio = bttv_gpio_read(&btv->c);
+		bttv_gpio_write(&btv->c, gpio & ~(1 << 4));
+		bttv_gpio_write(&btv->c, gpio | (1 << 4));
+	} else {
+		/* init hardware-specific stuff */
+		bttv_gpio_inout(&btv->c, ir->mask_keycode | ir->mask_keydown, 0);
+	}
+
+	/* init input device */
+	ir->dev = rc;
+
+	snprintf(ir->name, sizeof(ir->name), "bttv IR (card=%d)",
+		 btv->c.type);
+	snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0",
+		 pci_name(btv->c.pci));
+
+	rc->input_name = ir->name;
+	rc->input_phys = ir->phys;
+	rc->input_id.bustype = BUS_PCI;
+	rc->input_id.version = 1;
+	if (btv->c.pci->subsystem_vendor) {
+		rc->input_id.vendor  = btv->c.pci->subsystem_vendor;
+		rc->input_id.product = btv->c.pci->subsystem_device;
+	} else {
+		rc->input_id.vendor  = btv->c.pci->vendor;
+		rc->input_id.product = btv->c.pci->device;
+	}
+	rc->dev.parent = &btv->c.pci->dev;
+	rc->map_name = ir_codes;
+	rc->driver_name = MODULE_NAME;
+
+	btv->remote = ir;
+	bttv_ir_start(btv, ir);
+
+	/* all done */
+	err = rc_register_device(rc);
+	if (err)
+		goto err_out_stop;
+
+	return 0;
+
+ err_out_stop:
+	bttv_ir_stop(btv);
+	btv->remote = NULL;
+ err_out_free:
+	rc_free_device(rc);
+	kfree(ir);
+	return err;
+}
+
+void bttv_input_fini(struct bttv *btv)
+{
+	if (btv->remote == NULL)
+		return;
+
+	bttv_ir_stop(btv);
+	rc_unregister_device(btv->remote->dev);
+	kfree(btv->remote);
+	btv->remote = NULL;
+}
diff --git a/drivers/media/pci/bt8xx/bttv-risc.c b/drivers/media/pci/bt8xx/bttv-risc.c
new file mode 100644
index 0000000..82cc47d
--- /dev/null
+++ b/drivers/media/pci/bt8xx/bttv-risc.c
@@ -0,0 +1,909 @@
+/*
+
+    bttv-risc.c  --  interfaces to other kernel modules
+
+    bttv risc code handling
+	- memory management
+	- generation
+
+    (c) 2000-2003 Gerd Knorr <kraxel@bytesex.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.
+
+*/
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/vmalloc.h>
+#include <linux/interrupt.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <media/v4l2-ioctl.h>
+
+#include "bttvp.h"
+
+#define VCR_HACK_LINES 4
+
+/* ---------------------------------------------------------- */
+/* risc code generators                                       */
+
+int
+bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc,
+		 struct scatterlist *sglist,
+		 unsigned int offset, unsigned int bpl,
+		 unsigned int padding, unsigned int skip_lines,
+		 unsigned int store_lines)
+{
+	u32 instructions,line,todo;
+	struct scatterlist *sg;
+	__le32 *rp;
+	int rc;
+
+	/* estimate risc mem: worst case is one write per page border +
+	   one write per scan line + sync + jump (all 2 dwords).  padding
+	   can cause next bpl to start close to a page border.  First DMA
+	   region may be smaller than PAGE_SIZE */
+	instructions  = skip_lines * 4;
+	instructions += (1 + ((bpl + padding) * store_lines)
+			 / PAGE_SIZE + store_lines) * 8;
+	instructions += 2 * 8;
+	if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,instructions)) < 0)
+		return rc;
+
+	/* sync instruction */
+	rp = risc->cpu;
+	*(rp++) = cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1);
+	*(rp++) = cpu_to_le32(0);
+
+	while (skip_lines-- > 0) {
+		*(rp++) = cpu_to_le32(BT848_RISC_SKIP | BT848_RISC_SOL |
+				      BT848_RISC_EOL | bpl);
+	}
+
+	/* scan lines */
+	sg = sglist;
+	for (line = 0; line < store_lines; line++) {
+		if ((btv->opt_vcr_hack) &&
+		    (line >= (store_lines - VCR_HACK_LINES)))
+			continue;
+		while (offset && offset >= sg_dma_len(sg)) {
+			offset -= sg_dma_len(sg);
+			sg++;
+		}
+		if (bpl <= sg_dma_len(sg)-offset) {
+			/* fits into current chunk */
+			*(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL|
+					    BT848_RISC_EOL|bpl);
+			*(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
+			offset+=bpl;
+		} else {
+			/* scanline needs to be splitted */
+			todo = bpl;
+			*(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL|
+					    (sg_dma_len(sg)-offset));
+			*(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
+			todo -= (sg_dma_len(sg)-offset);
+			offset = 0;
+			sg++;
+			while (todo > sg_dma_len(sg)) {
+				*(rp++)=cpu_to_le32(BT848_RISC_WRITE|
+						    sg_dma_len(sg));
+				*(rp++)=cpu_to_le32(sg_dma_address(sg));
+				todo -= sg_dma_len(sg);
+				sg++;
+			}
+			*(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_EOL|
+					    todo);
+			*(rp++)=cpu_to_le32(sg_dma_address(sg));
+			offset += todo;
+		}
+		offset += padding;
+	}
+
+	/* save pointer to jmp instruction address */
+	risc->jmp = rp;
+	BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
+	return 0;
+}
+
+static int
+bttv_risc_planar(struct bttv *btv, struct btcx_riscmem *risc,
+		 struct scatterlist *sglist,
+		 unsigned int yoffset,  unsigned int ybpl,
+		 unsigned int ypadding, unsigned int ylines,
+		 unsigned int uoffset,  unsigned int voffset,
+		 unsigned int hshift,   unsigned int vshift,
+		 unsigned int cpadding)
+{
+	unsigned int instructions,line,todo,ylen,chroma;
+	__le32 *rp;
+	u32 ri;
+	struct scatterlist *ysg;
+	struct scatterlist *usg;
+	struct scatterlist *vsg;
+	int topfield = (0 == yoffset);
+	int rc;
+
+	/* estimate risc mem: worst case is one write per page border +
+	   one write per scan line (5 dwords)
+	   plus sync + jump (2 dwords) */
+	instructions  = ((3 + (ybpl + ypadding) * ylines * 2)
+			 / PAGE_SIZE) + ylines;
+	instructions += 2;
+	if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,instructions*4*5)) < 0)
+		return rc;
+
+	/* sync instruction */
+	rp = risc->cpu;
+	*(rp++) = cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM3);
+	*(rp++) = cpu_to_le32(0);
+
+	/* scan lines */
+	ysg = sglist;
+	usg = sglist;
+	vsg = sglist;
+	for (line = 0; line < ylines; line++) {
+		if ((btv->opt_vcr_hack) &&
+		    (line >= (ylines - VCR_HACK_LINES)))
+			continue;
+		switch (vshift) {
+		case 0:
+			chroma = 1;
+			break;
+		case 1:
+			if (topfield)
+				chroma = ((line & 1) == 0);
+			else
+				chroma = ((line & 1) == 1);
+			break;
+		case 2:
+			if (topfield)
+				chroma = ((line & 3) == 0);
+			else
+				chroma = ((line & 3) == 2);
+			break;
+		default:
+			chroma = 0;
+			break;
+		}
+
+		for (todo = ybpl; todo > 0; todo -= ylen) {
+			/* go to next sg entry if needed */
+			while (yoffset && yoffset >= sg_dma_len(ysg)) {
+				yoffset -= sg_dma_len(ysg);
+				ysg++;
+			}
+			while (uoffset && uoffset >= sg_dma_len(usg)) {
+				uoffset -= sg_dma_len(usg);
+				usg++;
+			}
+			while (voffset && voffset >= sg_dma_len(vsg)) {
+				voffset -= sg_dma_len(vsg);
+				vsg++;
+			}
+
+			/* calculate max number of bytes we can write */
+			ylen = todo;
+			if (yoffset + ylen > sg_dma_len(ysg))
+				ylen = sg_dma_len(ysg) - yoffset;
+			if (chroma) {
+				if (uoffset + (ylen>>hshift) > sg_dma_len(usg))
+					ylen = (sg_dma_len(usg) - uoffset) << hshift;
+				if (voffset + (ylen>>hshift) > sg_dma_len(vsg))
+					ylen = (sg_dma_len(vsg) - voffset) << hshift;
+				ri = BT848_RISC_WRITE123;
+			} else {
+				ri = BT848_RISC_WRITE1S23;
+			}
+			if (ybpl == todo)
+				ri |= BT848_RISC_SOL;
+			if (ylen == todo)
+				ri |= BT848_RISC_EOL;
+
+			/* write risc instruction */
+			*(rp++)=cpu_to_le32(ri | ylen);
+			*(rp++)=cpu_to_le32(((ylen >> hshift) << 16) |
+					    (ylen >> hshift));
+			*(rp++)=cpu_to_le32(sg_dma_address(ysg)+yoffset);
+			yoffset += ylen;
+			if (chroma) {
+				*(rp++)=cpu_to_le32(sg_dma_address(usg)+uoffset);
+				uoffset += ylen >> hshift;
+				*(rp++)=cpu_to_le32(sg_dma_address(vsg)+voffset);
+				voffset += ylen >> hshift;
+			}
+		}
+		yoffset += ypadding;
+		if (chroma) {
+			uoffset += cpadding;
+			voffset += cpadding;
+		}
+	}
+
+	/* save pointer to jmp instruction address */
+	risc->jmp = rp;
+	BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
+	return 0;
+}
+
+static int
+bttv_risc_overlay(struct bttv *btv, struct btcx_riscmem *risc,
+		  const struct bttv_format *fmt, struct bttv_overlay *ov,
+		  int skip_even, int skip_odd)
+{
+	int dwords, rc, line, maxy, start, end;
+	unsigned skip, nskips;
+	struct btcx_skiplist *skips;
+	__le32 *rp;
+	u32 ri,ra;
+	u32 addr;
+
+	/* skip list for window clipping */
+	if (NULL == (skips = kmalloc(sizeof(*skips) * ov->nclips,GFP_KERNEL)))
+		return -ENOMEM;
+
+	/* estimate risc mem: worst case is (1.5*clip+1) * lines instructions
+	   + sync + jump (all 2 dwords) */
+	dwords  = (3 * ov->nclips + 2) *
+		((skip_even || skip_odd) ? (ov->w.height+1)>>1 :  ov->w.height);
+	dwords += 4;
+	if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,dwords*4)) < 0) {
+		kfree(skips);
+		return rc;
+	}
+
+	/* sync instruction */
+	rp = risc->cpu;
+	*(rp++) = cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1);
+	*(rp++) = cpu_to_le32(0);
+
+	addr  = (unsigned long)btv->fbuf.base;
+	addr += btv->fbuf.fmt.bytesperline * ov->w.top;
+	addr += (fmt->depth >> 3)          * ov->w.left;
+
+	/* scan lines */
+	for (maxy = -1, line = 0; line < ov->w.height;
+	     line++, addr += btv->fbuf.fmt.bytesperline) {
+		if ((btv->opt_vcr_hack) &&
+		     (line >= (ov->w.height - VCR_HACK_LINES)))
+			continue;
+		if ((line%2) == 0  &&  skip_even)
+			continue;
+		if ((line%2) == 1  &&  skip_odd)
+			continue;
+
+		/* calculate clipping */
+		if (line > maxy)
+			btcx_calc_skips(line, ov->w.width, &maxy,
+					skips, &nskips, ov->clips, ov->nclips);
+
+		/* write out risc code */
+		for (start = 0, skip = 0; start < ov->w.width; start = end) {
+			if (skip >= nskips) {
+				ri  = BT848_RISC_WRITE;
+				end = ov->w.width;
+			} else if (start < skips[skip].start) {
+				ri  = BT848_RISC_WRITE;
+				end = skips[skip].start;
+			} else {
+				ri  = BT848_RISC_SKIP;
+				end = skips[skip].end;
+				skip++;
+			}
+			if (BT848_RISC_WRITE == ri)
+				ra = addr + (fmt->depth>>3)*start;
+			else
+				ra = 0;
+
+			if (0 == start)
+				ri |= BT848_RISC_SOL;
+			if (ov->w.width == end)
+				ri |= BT848_RISC_EOL;
+			ri |= (fmt->depth>>3) * (end-start);
+
+			*(rp++)=cpu_to_le32(ri);
+			if (0 != ra)
+				*(rp++)=cpu_to_le32(ra);
+		}
+	}
+
+	/* save pointer to jmp instruction address */
+	risc->jmp = rp;
+	BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
+	kfree(skips);
+	return 0;
+}
+
+/* ---------------------------------------------------------- */
+
+static void
+bttv_calc_geo_old(struct bttv *btv, struct bttv_geometry *geo,
+		  int width, int height, int interleaved,
+		  const struct bttv_tvnorm *tvnorm)
+{
+	u32 xsf, sr;
+	int vdelay;
+
+	int swidth       = tvnorm->swidth;
+	int totalwidth   = tvnorm->totalwidth;
+	int scaledtwidth = tvnorm->scaledtwidth;
+
+	if (btv->input == btv->dig) {
+		swidth       = 720;
+		totalwidth   = 858;
+		scaledtwidth = 858;
+	}
+
+	vdelay = tvnorm->vdelay;
+
+	xsf = (width*scaledtwidth)/swidth;
+	geo->hscale =  ((totalwidth*4096UL)/xsf-4096);
+	geo->hdelay =  tvnorm->hdelayx1;
+	geo->hdelay =  (geo->hdelay*width)/swidth;
+	geo->hdelay &= 0x3fe;
+	sr = ((tvnorm->sheight >> (interleaved?0:1))*512)/height - 512;
+	geo->vscale =  (0x10000UL-sr) & 0x1fff;
+	geo->crop   =  ((width>>8)&0x03) | ((geo->hdelay>>6)&0x0c) |
+		((tvnorm->sheight>>4)&0x30) | ((vdelay>>2)&0xc0);
+	geo->vscale |= interleaved ? (BT848_VSCALE_INT<<8) : 0;
+	geo->vdelay  =  vdelay;
+	geo->width   =  width;
+	geo->sheight =  tvnorm->sheight;
+	geo->vtotal  =  tvnorm->vtotal;
+
+	if (btv->opt_combfilter) {
+		geo->vtc  = (width < 193) ? 2 : ((width < 385) ? 1 : 0);
+		geo->comb = (width < 769) ? 1 : 0;
+	} else {
+		geo->vtc  = 0;
+		geo->comb = 0;
+	}
+}
+
+static void
+bttv_calc_geo		(struct bttv *                  btv,
+			 struct bttv_geometry *         geo,
+			 unsigned int                   width,
+			 unsigned int                   height,
+			 int                            both_fields,
+			 const struct bttv_tvnorm *     tvnorm,
+			 const struct v4l2_rect *       crop)
+{
+	unsigned int c_width;
+	unsigned int c_height;
+	u32 sr;
+
+	if ((crop->left == tvnorm->cropcap.defrect.left
+	     && crop->top == tvnorm->cropcap.defrect.top
+	     && crop->width == tvnorm->cropcap.defrect.width
+	     && crop->height == tvnorm->cropcap.defrect.height
+	     && width <= tvnorm->swidth /* see PAL-Nc et al */)
+	    || btv->input == btv->dig) {
+		bttv_calc_geo_old(btv, geo, width, height,
+				  both_fields, tvnorm);
+		return;
+	}
+
+	/* For bug compatibility the image size checks permit scale
+	   factors > 16. See bttv_crop_calc_limits(). */
+	c_width = min((unsigned int) crop->width, width * 16);
+	c_height = min((unsigned int) crop->height, height * 16);
+
+	geo->width = width;
+	geo->hscale = (c_width * 4096U + (width >> 1)) / width - 4096;
+	/* Even to store Cb first, odd for Cr. */
+	geo->hdelay = ((crop->left * width + c_width) / c_width) & ~1;
+
+	geo->sheight = c_height;
+	geo->vdelay = crop->top - tvnorm->cropcap.bounds.top + MIN_VDELAY;
+	sr = c_height >> !both_fields;
+	sr = (sr * 512U + (height >> 1)) / height - 512;
+	geo->vscale = (0x10000UL - sr) & 0x1fff;
+	geo->vscale |= both_fields ? (BT848_VSCALE_INT << 8) : 0;
+	geo->vtotal = tvnorm->vtotal;
+
+	geo->crop = (((geo->width   >> 8) & 0x03) |
+		     ((geo->hdelay  >> 6) & 0x0c) |
+		     ((geo->sheight >> 4) & 0x30) |
+		     ((geo->vdelay  >> 2) & 0xc0));
+
+	if (btv->opt_combfilter) {
+		geo->vtc  = (width < 193) ? 2 : ((width < 385) ? 1 : 0);
+		geo->comb = (width < 769) ? 1 : 0;
+	} else {
+		geo->vtc  = 0;
+		geo->comb = 0;
+	}
+}
+
+static void
+bttv_apply_geo(struct bttv *btv, struct bttv_geometry *geo, int odd)
+{
+	int off = odd ? 0x80 : 0x00;
+
+	if (geo->comb)
+		btor(BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off);
+	else
+		btand(~BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off);
+
+	btwrite(geo->vtc,             BT848_E_VTC+off);
+	btwrite(geo->hscale >> 8,     BT848_E_HSCALE_HI+off);
+	btwrite(geo->hscale & 0xff,   BT848_E_HSCALE_LO+off);
+	btaor((geo->vscale>>8), 0xe0, BT848_E_VSCALE_HI+off);
+	btwrite(geo->vscale & 0xff,   BT848_E_VSCALE_LO+off);
+	btwrite(geo->width & 0xff,    BT848_E_HACTIVE_LO+off);
+	btwrite(geo->hdelay & 0xff,   BT848_E_HDELAY_LO+off);
+	btwrite(geo->sheight & 0xff,  BT848_E_VACTIVE_LO+off);
+	btwrite(geo->vdelay & 0xff,   BT848_E_VDELAY_LO+off);
+	btwrite(geo->crop,            BT848_E_CROP+off);
+	btwrite(geo->vtotal>>8,       BT848_VTOTAL_HI);
+	btwrite(geo->vtotal & 0xff,   BT848_VTOTAL_LO);
+}
+
+/* ---------------------------------------------------------- */
+/* risc group / risc main loop / dma management               */
+
+void
+bttv_set_dma(struct bttv *btv, int override)
+{
+	unsigned long cmd;
+	int capctl;
+
+	btv->cap_ctl = 0;
+	if (NULL != btv->curr.top)      btv->cap_ctl |= 0x02;
+	if (NULL != btv->curr.bottom)   btv->cap_ctl |= 0x01;
+	if (NULL != btv->cvbi)          btv->cap_ctl |= 0x0c;
+
+	capctl  = 0;
+	capctl |= (btv->cap_ctl & 0x03) ? 0x03 : 0x00;  /* capture  */
+	capctl |= (btv->cap_ctl & 0x0c) ? 0x0c : 0x00;  /* vbi data */
+	capctl |= override;
+
+	d2printk("%d: capctl=%x lirq=%d top=%08llx/%08llx even=%08llx/%08llx\n",
+		 btv->c.nr,capctl,btv->loop_irq,
+		 btv->cvbi         ? (unsigned long long)btv->cvbi->top.dma            : 0,
+		 btv->curr.top     ? (unsigned long long)btv->curr.top->top.dma        : 0,
+		 btv->cvbi         ? (unsigned long long)btv->cvbi->bottom.dma         : 0,
+		 btv->curr.bottom  ? (unsigned long long)btv->curr.bottom->bottom.dma  : 0);
+
+	cmd = BT848_RISC_JUMP;
+	if (btv->loop_irq) {
+		cmd |= BT848_RISC_IRQ;
+		cmd |= (btv->loop_irq  & 0x0f) << 16;
+		cmd |= (~btv->loop_irq & 0x0f) << 20;
+	}
+	if (btv->curr.frame_irq || btv->loop_irq || btv->cvbi) {
+		mod_timer(&btv->timeout, jiffies+BTTV_TIMEOUT);
+	} else {
+		del_timer(&btv->timeout);
+	}
+	btv->main.cpu[RISC_SLOT_LOOP] = cpu_to_le32(cmd);
+
+	btaor(capctl, ~0x0f, BT848_CAP_CTL);
+	if (capctl) {
+		if (btv->dma_on)
+			return;
+		btwrite(btv->main.dma, BT848_RISC_STRT_ADD);
+		btor(3, BT848_GPIO_DMA_CTL);
+		btv->dma_on = 1;
+	} else {
+		if (!btv->dma_on)
+			return;
+		btand(~3, BT848_GPIO_DMA_CTL);
+		btv->dma_on = 0;
+	}
+	return;
+}
+
+int
+bttv_risc_init_main(struct bttv *btv)
+{
+	int rc;
+
+	if ((rc = btcx_riscmem_alloc(btv->c.pci,&btv->main,PAGE_SIZE)) < 0)
+		return rc;
+	dprintk("%d: risc main @ %08llx\n",
+		btv->c.nr, (unsigned long long)btv->main.dma);
+
+	btv->main.cpu[0] = cpu_to_le32(BT848_RISC_SYNC | BT848_RISC_RESYNC |
+				       BT848_FIFO_STATUS_VRE);
+	btv->main.cpu[1] = cpu_to_le32(0);
+	btv->main.cpu[2] = cpu_to_le32(BT848_RISC_JUMP);
+	btv->main.cpu[3] = cpu_to_le32(btv->main.dma + (4<<2));
+
+	/* top field */
+	btv->main.cpu[4] = cpu_to_le32(BT848_RISC_JUMP);
+	btv->main.cpu[5] = cpu_to_le32(btv->main.dma + (6<<2));
+	btv->main.cpu[6] = cpu_to_le32(BT848_RISC_JUMP);
+	btv->main.cpu[7] = cpu_to_le32(btv->main.dma + (8<<2));
+
+	btv->main.cpu[8] = cpu_to_le32(BT848_RISC_SYNC | BT848_RISC_RESYNC |
+				       BT848_FIFO_STATUS_VRO);
+	btv->main.cpu[9] = cpu_to_le32(0);
+
+	/* bottom field */
+	btv->main.cpu[10] = cpu_to_le32(BT848_RISC_JUMP);
+	btv->main.cpu[11] = cpu_to_le32(btv->main.dma + (12<<2));
+	btv->main.cpu[12] = cpu_to_le32(BT848_RISC_JUMP);
+	btv->main.cpu[13] = cpu_to_le32(btv->main.dma + (14<<2));
+
+	/* jump back to top field */
+	btv->main.cpu[14] = cpu_to_le32(BT848_RISC_JUMP);
+	btv->main.cpu[15] = cpu_to_le32(btv->main.dma + (0<<2));
+
+	return 0;
+}
+
+int
+bttv_risc_hook(struct bttv *btv, int slot, struct btcx_riscmem *risc,
+	       int irqflags)
+{
+	unsigned long cmd;
+	unsigned long next = btv->main.dma + ((slot+2) << 2);
+
+	if (NULL == risc) {
+		d2printk("%d: risc=%p slot[%d]=NULL\n", btv->c.nr, risc, slot);
+		btv->main.cpu[slot+1] = cpu_to_le32(next);
+	} else {
+		d2printk("%d: risc=%p slot[%d]=%08llx irq=%d\n",
+			 btv->c.nr, risc, slot,
+			 (unsigned long long)risc->dma, irqflags);
+		cmd = BT848_RISC_JUMP;
+		if (irqflags) {
+			cmd |= BT848_RISC_IRQ;
+			cmd |= (irqflags  & 0x0f) << 16;
+			cmd |= (~irqflags & 0x0f) << 20;
+		}
+		risc->jmp[0] = cpu_to_le32(cmd);
+		risc->jmp[1] = cpu_to_le32(next);
+		btv->main.cpu[slot+1] = cpu_to_le32(risc->dma);
+	}
+	return 0;
+}
+
+void
+bttv_dma_free(struct videobuf_queue *q,struct bttv *btv, struct bttv_buffer *buf)
+{
+	struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
+
+	BUG_ON(in_interrupt());
+	videobuf_waiton(q, &buf->vb, 0, 0);
+	videobuf_dma_unmap(q->dev, dma);
+	videobuf_dma_free(dma);
+	btcx_riscmem_free(btv->c.pci,&buf->bottom);
+	btcx_riscmem_free(btv->c.pci,&buf->top);
+	buf->vb.state = VIDEOBUF_NEEDS_INIT;
+}
+
+int
+bttv_buffer_activate_vbi(struct bttv *btv,
+			 struct bttv_buffer *vbi)
+{
+	struct btcx_riscmem *top;
+	struct btcx_riscmem *bottom;
+	int top_irq_flags;
+	int bottom_irq_flags;
+
+	top = NULL;
+	bottom = NULL;
+	top_irq_flags = 0;
+	bottom_irq_flags = 0;
+
+	if (vbi) {
+		unsigned int crop, vdelay;
+
+		vbi->vb.state = VIDEOBUF_ACTIVE;
+		list_del(&vbi->vb.queue);
+
+		/* VDELAY is start of video, end of VBI capturing. */
+		crop = btread(BT848_E_CROP);
+		vdelay = btread(BT848_E_VDELAY_LO) + ((crop & 0xc0) << 2);
+
+		if (vbi->geo.vdelay > vdelay) {
+			vdelay = vbi->geo.vdelay & 0xfe;
+			crop = (crop & 0x3f) | ((vbi->geo.vdelay >> 2) & 0xc0);
+
+			btwrite(vdelay, BT848_E_VDELAY_LO);
+			btwrite(crop,	BT848_E_CROP);
+			btwrite(vdelay, BT848_O_VDELAY_LO);
+			btwrite(crop,	BT848_O_CROP);
+		}
+
+		if (vbi->vbi_count[0] > 0) {
+			top = &vbi->top;
+			top_irq_flags = 4;
+		}
+
+		if (vbi->vbi_count[1] > 0) {
+			top_irq_flags = 0;
+			bottom = &vbi->bottom;
+			bottom_irq_flags = 4;
+		}
+	}
+
+	bttv_risc_hook(btv, RISC_SLOT_O_VBI, top, top_irq_flags);
+	bttv_risc_hook(btv, RISC_SLOT_E_VBI, bottom, bottom_irq_flags);
+
+	return 0;
+}
+
+int
+bttv_buffer_activate_video(struct bttv *btv,
+			   struct bttv_buffer_set *set)
+{
+	/* video capture */
+	if (NULL != set->top  &&  NULL != set->bottom) {
+		if (set->top == set->bottom) {
+			set->top->vb.state    = VIDEOBUF_ACTIVE;
+			if (set->top->vb.queue.next)
+				list_del(&set->top->vb.queue);
+		} else {
+			set->top->vb.state    = VIDEOBUF_ACTIVE;
+			set->bottom->vb.state = VIDEOBUF_ACTIVE;
+			if (set->top->vb.queue.next)
+				list_del(&set->top->vb.queue);
+			if (set->bottom->vb.queue.next)
+				list_del(&set->bottom->vb.queue);
+		}
+		bttv_apply_geo(btv, &set->top->geo, 1);
+		bttv_apply_geo(btv, &set->bottom->geo,0);
+		bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top,
+			       set->top_irq);
+		bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &set->bottom->bottom,
+			       set->frame_irq);
+		btaor((set->top->btformat & 0xf0) | (set->bottom->btformat & 0x0f),
+		      ~0xff, BT848_COLOR_FMT);
+		btaor((set->top->btswap & 0x0a) | (set->bottom->btswap & 0x05),
+		      ~0x0f, BT848_COLOR_CTL);
+	} else if (NULL != set->top) {
+		set->top->vb.state  = VIDEOBUF_ACTIVE;
+		if (set->top->vb.queue.next)
+			list_del(&set->top->vb.queue);
+		bttv_apply_geo(btv, &set->top->geo,1);
+		bttv_apply_geo(btv, &set->top->geo,0);
+		bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top,
+			       set->frame_irq);
+		bttv_risc_hook(btv, RISC_SLOT_E_FIELD, NULL,           0);
+		btaor(set->top->btformat & 0xff, ~0xff, BT848_COLOR_FMT);
+		btaor(set->top->btswap & 0x0f,   ~0x0f, BT848_COLOR_CTL);
+	} else if (NULL != set->bottom) {
+		set->bottom->vb.state = VIDEOBUF_ACTIVE;
+		if (set->bottom->vb.queue.next)
+			list_del(&set->bottom->vb.queue);
+		bttv_apply_geo(btv, &set->bottom->geo,1);
+		bttv_apply_geo(btv, &set->bottom->geo,0);
+		bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
+		bttv_risc_hook(btv, RISC_SLOT_E_FIELD, &set->bottom->bottom,
+			       set->frame_irq);
+		btaor(set->bottom->btformat & 0xff, ~0xff, BT848_COLOR_FMT);
+		btaor(set->bottom->btswap & 0x0f,   ~0x0f, BT848_COLOR_CTL);
+	} else {
+		bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
+		bttv_risc_hook(btv, RISC_SLOT_E_FIELD, NULL, 0);
+	}
+	return 0;
+}
+
+/* ---------------------------------------------------------- */
+
+/* calculate geometry, build risc code */
+int
+bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf)
+{
+	const struct bttv_tvnorm *tvnorm = bttv_tvnorms + buf->tvnorm;
+	struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
+
+	dprintk("%d: buffer field: %s  format: %s  size: %dx%d\n",
+		btv->c.nr, v4l2_field_names[buf->vb.field],
+		buf->fmt->name, buf->vb.width, buf->vb.height);
+
+	/* packed pixel modes */
+	if (buf->fmt->flags & FORMAT_FLAGS_PACKED) {
+		int bpl = (buf->fmt->depth >> 3) * buf->vb.width;
+		int bpf = bpl * (buf->vb.height >> 1);
+
+		bttv_calc_geo(btv,&buf->geo,buf->vb.width,buf->vb.height,
+			      V4L2_FIELD_HAS_BOTH(buf->vb.field),
+			      tvnorm,&buf->crop);
+
+		switch (buf->vb.field) {
+		case V4L2_FIELD_TOP:
+			bttv_risc_packed(btv,&buf->top,dma->sglist,
+					 /* offset */ 0,bpl,
+					 /* padding */ 0,/* skip_lines */ 0,
+					 buf->vb.height);
+			break;
+		case V4L2_FIELD_BOTTOM:
+			bttv_risc_packed(btv,&buf->bottom,dma->sglist,
+					 0,bpl,0,0,buf->vb.height);
+			break;
+		case V4L2_FIELD_INTERLACED:
+			bttv_risc_packed(btv,&buf->top,dma->sglist,
+					 0,bpl,bpl,0,buf->vb.height >> 1);
+			bttv_risc_packed(btv,&buf->bottom,dma->sglist,
+					 bpl,bpl,bpl,0,buf->vb.height >> 1);
+			break;
+		case V4L2_FIELD_SEQ_TB:
+			bttv_risc_packed(btv,&buf->top,dma->sglist,
+					 0,bpl,0,0,buf->vb.height >> 1);
+			bttv_risc_packed(btv,&buf->bottom,dma->sglist,
+					 bpf,bpl,0,0,buf->vb.height >> 1);
+			break;
+		default:
+			BUG();
+		}
+	}
+
+	/* planar modes */
+	if (buf->fmt->flags & FORMAT_FLAGS_PLANAR) {
+		int uoffset, voffset;
+		int ypadding, cpadding, lines;
+
+		/* calculate chroma offsets */
+		uoffset = buf->vb.width * buf->vb.height;
+		voffset = buf->vb.width * buf->vb.height;
+		if (buf->fmt->flags & FORMAT_FLAGS_CrCb) {
+			/* Y-Cr-Cb plane order */
+			uoffset >>= buf->fmt->hshift;
+			uoffset >>= buf->fmt->vshift;
+			uoffset  += voffset;
+		} else {
+			/* Y-Cb-Cr plane order */
+			voffset >>= buf->fmt->hshift;
+			voffset >>= buf->fmt->vshift;
+			voffset  += uoffset;
+		}
+
+		switch (buf->vb.field) {
+		case V4L2_FIELD_TOP:
+			bttv_calc_geo(btv,&buf->geo,buf->vb.width,
+				      buf->vb.height,/* both_fields */ 0,
+				      tvnorm,&buf->crop);
+			bttv_risc_planar(btv, &buf->top, dma->sglist,
+					 0,buf->vb.width,0,buf->vb.height,
+					 uoffset,voffset,buf->fmt->hshift,
+					 buf->fmt->vshift,0);
+			break;
+		case V4L2_FIELD_BOTTOM:
+			bttv_calc_geo(btv,&buf->geo,buf->vb.width,
+				      buf->vb.height,0,
+				      tvnorm,&buf->crop);
+			bttv_risc_planar(btv, &buf->bottom, dma->sglist,
+					 0,buf->vb.width,0,buf->vb.height,
+					 uoffset,voffset,buf->fmt->hshift,
+					 buf->fmt->vshift,0);
+			break;
+		case V4L2_FIELD_INTERLACED:
+			bttv_calc_geo(btv,&buf->geo,buf->vb.width,
+				      buf->vb.height,1,
+				      tvnorm,&buf->crop);
+			lines    = buf->vb.height >> 1;
+			ypadding = buf->vb.width;
+			cpadding = buf->vb.width >> buf->fmt->hshift;
+			bttv_risc_planar(btv,&buf->top,
+					 dma->sglist,
+					 0,buf->vb.width,ypadding,lines,
+					 uoffset,voffset,
+					 buf->fmt->hshift,
+					 buf->fmt->vshift,
+					 cpadding);
+			bttv_risc_planar(btv,&buf->bottom,
+					 dma->sglist,
+					 ypadding,buf->vb.width,ypadding,lines,
+					 uoffset+cpadding,
+					 voffset+cpadding,
+					 buf->fmt->hshift,
+					 buf->fmt->vshift,
+					 cpadding);
+			break;
+		case V4L2_FIELD_SEQ_TB:
+			bttv_calc_geo(btv,&buf->geo,buf->vb.width,
+				      buf->vb.height,1,
+				      tvnorm,&buf->crop);
+			lines    = buf->vb.height >> 1;
+			ypadding = buf->vb.width;
+			cpadding = buf->vb.width >> buf->fmt->hshift;
+			bttv_risc_planar(btv,&buf->top,
+					 dma->sglist,
+					 0,buf->vb.width,0,lines,
+					 uoffset >> 1,
+					 voffset >> 1,
+					 buf->fmt->hshift,
+					 buf->fmt->vshift,
+					 0);
+			bttv_risc_planar(btv,&buf->bottom,
+					 dma->sglist,
+					 lines * ypadding,buf->vb.width,0,lines,
+					 lines * ypadding + (uoffset >> 1),
+					 lines * ypadding + (voffset >> 1),
+					 buf->fmt->hshift,
+					 buf->fmt->vshift,
+					 0);
+			break;
+		default:
+			BUG();
+		}
+	}
+
+	/* raw data */
+	if (buf->fmt->flags & FORMAT_FLAGS_RAW) {
+		/* build risc code */
+		buf->vb.field = V4L2_FIELD_SEQ_TB;
+		bttv_calc_geo(btv,&buf->geo,tvnorm->swidth,tvnorm->sheight,
+			      1,tvnorm,&buf->crop);
+		bttv_risc_packed(btv, &buf->top,  dma->sglist,
+				 /* offset */ 0, RAW_BPL, /* padding */ 0,
+				 /* skip_lines */ 0, RAW_LINES);
+		bttv_risc_packed(btv, &buf->bottom, dma->sglist,
+				 buf->vb.size/2 , RAW_BPL, 0, 0, RAW_LINES);
+	}
+
+	/* copy format info */
+	buf->btformat = buf->fmt->btformat;
+	buf->btswap   = buf->fmt->btswap;
+	return 0;
+}
+
+/* ---------------------------------------------------------- */
+
+/* calculate geometry, build risc code */
+int
+bttv_overlay_risc(struct bttv *btv,
+		  struct bttv_overlay *ov,
+		  const struct bttv_format *fmt,
+		  struct bttv_buffer *buf)
+{
+	/* check interleave, bottom+top fields */
+	dprintk("%d: overlay fields: %s format: %s  size: %dx%d\n",
+		btv->c.nr, v4l2_field_names[buf->vb.field],
+		fmt->name, ov->w.width, ov->w.height);
+
+	/* calculate geometry */
+	bttv_calc_geo(btv,&buf->geo,ov->w.width,ov->w.height,
+		      V4L2_FIELD_HAS_BOTH(ov->field),
+		      &bttv_tvnorms[ov->tvnorm],&buf->crop);
+
+	/* build risc code */
+	switch (ov->field) {
+	case V4L2_FIELD_TOP:
+		bttv_risc_overlay(btv, &buf->top,    fmt, ov, 0, 0);
+		break;
+	case V4L2_FIELD_BOTTOM:
+		bttv_risc_overlay(btv, &buf->bottom, fmt, ov, 0, 0);
+		break;
+	case V4L2_FIELD_INTERLACED:
+		bttv_risc_overlay(btv, &buf->top,    fmt, ov, 0, 1);
+		bttv_risc_overlay(btv, &buf->bottom, fmt, ov, 1, 0);
+		break;
+	default:
+		BUG();
+	}
+
+	/* copy format info */
+	buf->btformat = fmt->btformat;
+	buf->btswap   = fmt->btswap;
+	buf->vb.field = ov->field;
+	return 0;
+}
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/pci/bt8xx/bttv-vbi.c b/drivers/media/pci/bt8xx/bttv-vbi.c
new file mode 100644
index 0000000..b433267
--- /dev/null
+++ b/drivers/media/pci/bt8xx/bttv-vbi.c
@@ -0,0 +1,459 @@
+/*
+
+    bttv - Bt848 frame grabber driver
+    vbi interface
+
+    (c) 2002 Gerd Knorr <kraxel@bytesex.org>
+
+    Copyright (C) 2005, 2006 Michael H. Schimek <mschimek@gmx.at>
+    Sponsored by OPQ Systems AB
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/kdev_t.h>
+#include <media/v4l2-ioctl.h>
+#include <asm/io.h>
+#include "bttvp.h"
+
+/* Offset from line sync pulse leading edge (0H) to start of VBI capture,
+   in fCLKx2 pixels.  According to the datasheet, VBI capture starts
+   VBI_HDELAY fCLKx1 pixels from the tailing edgeof /HRESET, and /HRESET
+   is 64 fCLKx1 pixels wide.  VBI_HDELAY is set to 0, so this should be
+   (64 + 0) * 2 = 128 fCLKx2 pixels.  But it's not!  The datasheet is
+   Just Plain Wrong.  The real value appears to be different for
+   different revisions of the bt8x8 chips, and to be affected by the
+   horizontal scaling factor.  Experimentally, the value is measured
+   to be about 244.  */
+#define VBI_OFFSET 244
+
+/* 2048 for compatibility with earlier driver versions. The driver
+   really stores 1024 + tvnorm->vbipack * 4 samples per line in the
+   buffer. Note tvnorm->vbipack is <= 0xFF (limit of VBIPACK_LO + HI
+   is 0x1FF DWORDs) and VBI read()s store a frame counter in the last
+   four bytes of the VBI image. */
+#define VBI_BPL 2048
+
+/* Compatibility. */
+#define VBI_DEFLINES 16
+
+static unsigned int vbibufs = 4;
+static unsigned int vbi_debug;
+
+module_param(vbibufs,   int, 0444);
+module_param(vbi_debug, int, 0644);
+MODULE_PARM_DESC(vbibufs,"number of vbi buffers, range 2-32, default 4");
+MODULE_PARM_DESC(vbi_debug,"vbi code debug messages, default is 0 (no)");
+
+#ifdef dprintk
+# undef dprintk
+#endif
+#define dprintk(fmt, ...)						\
+do {									\
+	if (vbi_debug)							\
+		pr_debug("%d: " fmt, btv->c.nr, ##__VA_ARGS__);		\
+} while (0)
+
+#define IMAGE_SIZE(fmt) \
+	(((fmt)->count[0] + (fmt)->count[1]) * (fmt)->samples_per_line)
+
+/* ----------------------------------------------------------------------- */
+/* vbi risc code + mm                                                      */
+
+static int vbi_buffer_setup(struct videobuf_queue *q,
+			    unsigned int *count, unsigned int *size)
+{
+	struct bttv_fh *fh = q->priv_data;
+	struct bttv *btv = fh->btv;
+
+	if (0 == *count)
+		*count = vbibufs;
+
+	*size = IMAGE_SIZE(&fh->vbi_fmt.fmt);
+
+	dprintk("setup: samples=%u start=%d,%d count=%u,%u\n",
+		fh->vbi_fmt.fmt.samples_per_line,
+		fh->vbi_fmt.fmt.start[0],
+		fh->vbi_fmt.fmt.start[1],
+		fh->vbi_fmt.fmt.count[0],
+		fh->vbi_fmt.fmt.count[1]);
+
+	return 0;
+}
+
+static int vbi_buffer_prepare(struct videobuf_queue *q,
+			      struct videobuf_buffer *vb,
+			      enum v4l2_field field)
+{
+	struct bttv_fh *fh = q->priv_data;
+	struct bttv *btv = fh->btv;
+	struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
+	const struct bttv_tvnorm *tvnorm;
+	unsigned int skip_lines0, skip_lines1, min_vdelay;
+	int redo_dma_risc;
+	int rc;
+
+	buf->vb.size = IMAGE_SIZE(&fh->vbi_fmt.fmt);
+	if (0 != buf->vb.baddr  &&  buf->vb.bsize < buf->vb.size)
+		return -EINVAL;
+
+	tvnorm = fh->vbi_fmt.tvnorm;
+
+	/* There's no VBI_VDELAY register, RISC must skip the lines
+	   we don't want. With default parameters we skip zero lines
+	   as earlier driver versions did. The driver permits video
+	   standard changes while capturing, so we use vbi_fmt.tvnorm
+	   instead of btv->tvnorm to skip zero lines after video
+	   standard changes as well. */
+
+	skip_lines0 = 0;
+	skip_lines1 = 0;
+
+	if (fh->vbi_fmt.fmt.count[0] > 0)
+		skip_lines0 = max(0, (fh->vbi_fmt.fmt.start[0]
+				      - tvnorm->vbistart[0]));
+	if (fh->vbi_fmt.fmt.count[1] > 0)
+		skip_lines1 = max(0, (fh->vbi_fmt.fmt.start[1]
+				      - tvnorm->vbistart[1]));
+
+	redo_dma_risc = 0;
+
+	if (buf->vbi_skip[0] != skip_lines0 ||
+	    buf->vbi_skip[1] != skip_lines1 ||
+	    buf->vbi_count[0] != fh->vbi_fmt.fmt.count[0] ||
+	    buf->vbi_count[1] != fh->vbi_fmt.fmt.count[1]) {
+		buf->vbi_skip[0] = skip_lines0;
+		buf->vbi_skip[1] = skip_lines1;
+		buf->vbi_count[0] = fh->vbi_fmt.fmt.count[0];
+		buf->vbi_count[1] = fh->vbi_fmt.fmt.count[1];
+		redo_dma_risc = 1;
+	}
+
+	if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
+		redo_dma_risc = 1;
+		if (0 != (rc = videobuf_iolock(q, &buf->vb, NULL)))
+			goto fail;
+	}
+
+	if (redo_dma_risc) {
+		unsigned int bpl, padding, offset;
+		struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
+
+		bpl = 2044; /* max. vbipack */
+		padding = VBI_BPL - bpl;
+
+		if (fh->vbi_fmt.fmt.count[0] > 0) {
+			rc = bttv_risc_packed(btv, &buf->top,
+					      dma->sglist,
+					      /* offset */ 0, bpl,
+					      padding, skip_lines0,
+					      fh->vbi_fmt.fmt.count[0]);
+			if (0 != rc)
+				goto fail;
+		}
+
+		if (fh->vbi_fmt.fmt.count[1] > 0) {
+			offset = fh->vbi_fmt.fmt.count[0] * VBI_BPL;
+
+			rc = bttv_risc_packed(btv, &buf->bottom,
+					      dma->sglist,
+					      offset, bpl,
+					      padding, skip_lines1,
+					      fh->vbi_fmt.fmt.count[1]);
+			if (0 != rc)
+				goto fail;
+		}
+	}
+
+	/* VBI capturing ends at VDELAY, start of video capturing,
+	   no matter where the RISC program ends. VDELAY minimum is 2,
+	   bounds.top is the corresponding first field line number
+	   times two. VDELAY counts half field lines. */
+	min_vdelay = MIN_VDELAY;
+	if (fh->vbi_fmt.end >= tvnorm->cropcap.bounds.top)
+		min_vdelay += fh->vbi_fmt.end - tvnorm->cropcap.bounds.top;
+
+	/* For bttv_buffer_activate_vbi(). */
+	buf->geo.vdelay = min_vdelay;
+
+	buf->vb.state = VIDEOBUF_PREPARED;
+	buf->vb.field = field;
+	dprintk("buf prepare %p: top=%p bottom=%p field=%s\n",
+		vb, &buf->top, &buf->bottom,
+		v4l2_field_names[buf->vb.field]);
+	return 0;
+
+ fail:
+	bttv_dma_free(q,btv,buf);
+	return rc;
+}
+
+static void
+vbi_buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
+{
+	struct bttv_fh *fh = q->priv_data;
+	struct bttv *btv = fh->btv;
+	struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
+
+	dprintk("queue %p\n",vb);
+	buf->vb.state = VIDEOBUF_QUEUED;
+	list_add_tail(&buf->vb.queue,&btv->vcapture);
+	if (NULL == btv->cvbi) {
+		fh->btv->loop_irq |= 4;
+		bttv_set_dma(btv,0x0c);
+	}
+}
+
+static void vbi_buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
+{
+	struct bttv_fh *fh = q->priv_data;
+	struct bttv *btv = fh->btv;
+	struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
+
+	dprintk("free %p\n",vb);
+	bttv_dma_free(q,fh->btv,buf);
+}
+
+struct videobuf_queue_ops bttv_vbi_qops = {
+	.buf_setup    = vbi_buffer_setup,
+	.buf_prepare  = vbi_buffer_prepare,
+	.buf_queue    = vbi_buffer_queue,
+	.buf_release  = vbi_buffer_release,
+};
+
+/* ----------------------------------------------------------------------- */
+
+static int try_fmt(struct v4l2_vbi_format *f, const struct bttv_tvnorm *tvnorm,
+			__s32 crop_start)
+{
+	__s32 min_start, max_start, max_end, f2_offset;
+	unsigned int i;
+
+	/* For compatibility with earlier driver versions we must pretend
+	   the VBI and video capture window may overlap. In reality RISC
+	   magic aborts VBI capturing at the first line of video capturing,
+	   leaving the rest of the buffer unchanged, usually all zero.
+	   VBI capturing must always start before video capturing. >> 1
+	   because cropping counts field lines times two. */
+	min_start = tvnorm->vbistart[0];
+	max_start = (crop_start >> 1) - 1;
+	max_end = (tvnorm->cropcap.bounds.top
+		   + tvnorm->cropcap.bounds.height) >> 1;
+
+	if (min_start > max_start)
+		return -EBUSY;
+
+	BUG_ON(max_start >= max_end);
+
+	f->sampling_rate    = tvnorm->Fsc;
+	f->samples_per_line = VBI_BPL;
+	f->sample_format    = V4L2_PIX_FMT_GREY;
+	f->offset           = VBI_OFFSET;
+
+	f2_offset = tvnorm->vbistart[1] - tvnorm->vbistart[0];
+
+	for (i = 0; i < 2; ++i) {
+		if (0 == f->count[i]) {
+			/* No data from this field. We leave f->start[i]
+			   alone because VIDIOCSVBIFMT is w/o and EINVALs
+			   when a driver does not support exactly the
+			   requested parameters. */
+		} else {
+			s64 start, count;
+
+			start = clamp(f->start[i], min_start, max_start);
+			/* s64 to prevent overflow. */
+			count = (s64) f->start[i] + f->count[i] - start;
+			f->start[i] = start;
+			f->count[i] = clamp(count, (s64) 1,
+					    max_end - start);
+		}
+
+		min_start += f2_offset;
+		max_start += f2_offset;
+		max_end += f2_offset;
+	}
+
+	if (0 == (f->count[0] | f->count[1])) {
+		/* As in earlier driver versions. */
+		f->start[0] = tvnorm->vbistart[0];
+		f->start[1] = tvnorm->vbistart[1];
+		f->count[0] = 1;
+		f->count[1] = 1;
+	}
+
+	f->flags = 0;
+
+	f->reserved[0] = 0;
+	f->reserved[1] = 0;
+
+	return 0;
+}
+
+int bttv_try_fmt_vbi_cap(struct file *file, void *f, struct v4l2_format *frt)
+{
+	struct bttv_fh *fh = f;
+	struct bttv *btv = fh->btv;
+	const struct bttv_tvnorm *tvnorm;
+	__s32 crop_start;
+
+	mutex_lock(&btv->lock);
+
+	tvnorm = &bttv_tvnorms[btv->tvnorm];
+	crop_start = btv->crop_start;
+
+	mutex_unlock(&btv->lock);
+
+	return try_fmt(&frt->fmt.vbi, tvnorm, crop_start);
+}
+
+
+int bttv_s_fmt_vbi_cap(struct file *file, void *f, struct v4l2_format *frt)
+{
+	struct bttv_fh *fh = f;
+	struct bttv *btv = fh->btv;
+	const struct bttv_tvnorm *tvnorm;
+	__s32 start1, end;
+	int rc;
+
+	mutex_lock(&btv->lock);
+
+	rc = -EBUSY;
+	if (fh->resources & RESOURCE_VBI)
+		goto fail;
+
+	tvnorm = &bttv_tvnorms[btv->tvnorm];
+
+	rc = try_fmt(&frt->fmt.vbi, tvnorm, btv->crop_start);
+	if (0 != rc)
+		goto fail;
+
+	start1 = frt->fmt.vbi.start[1] - tvnorm->vbistart[1] +
+		tvnorm->vbistart[0];
+
+	/* First possible line of video capturing. Should be
+	   max(f->start[0] + f->count[0], start1 + f->count[1]) * 2
+	   when capturing both fields. But for compatibility we must
+	   pretend the VBI and video capture window may overlap,
+	   so end = start + 1, the lowest possible value, times two
+	   because vbi_fmt.end counts field lines times two. */
+	end = max(frt->fmt.vbi.start[0], start1) * 2 + 2;
+
+	mutex_lock(&fh->vbi.vb_lock);
+
+	fh->vbi_fmt.fmt    = frt->fmt.vbi;
+	fh->vbi_fmt.tvnorm = tvnorm;
+	fh->vbi_fmt.end    = end;
+
+	mutex_unlock(&fh->vbi.vb_lock);
+
+	rc = 0;
+
+ fail:
+	mutex_unlock(&btv->lock);
+
+	return rc;
+}
+
+
+int bttv_g_fmt_vbi_cap(struct file *file, void *f, struct v4l2_format *frt)
+{
+	struct bttv_fh *fh = f;
+	const struct bttv_tvnorm *tvnorm;
+
+	frt->fmt.vbi = fh->vbi_fmt.fmt;
+
+	tvnorm = &bttv_tvnorms[fh->btv->tvnorm];
+
+	if (tvnorm != fh->vbi_fmt.tvnorm) {
+		__s32 max_end;
+		unsigned int i;
+
+		/* As in vbi_buffer_prepare() this imitates the
+		   behaviour of earlier driver versions after video
+		   standard changes, with default parameters anyway. */
+
+		max_end = (tvnorm->cropcap.bounds.top
+			   + tvnorm->cropcap.bounds.height) >> 1;
+
+		frt->fmt.vbi.sampling_rate = tvnorm->Fsc;
+
+		for (i = 0; i < 2; ++i) {
+			__s32 new_start;
+
+			new_start = frt->fmt.vbi.start[i]
+				+ tvnorm->vbistart[i]
+				- fh->vbi_fmt.tvnorm->vbistart[i];
+
+			frt->fmt.vbi.start[i] = min(new_start, max_end - 1);
+			frt->fmt.vbi.count[i] =
+				min((__s32) frt->fmt.vbi.count[i],
+					  max_end - frt->fmt.vbi.start[i]);
+
+			max_end += tvnorm->vbistart[1]
+				- tvnorm->vbistart[0];
+		}
+	}
+	return 0;
+}
+
+void bttv_vbi_fmt_reset(struct bttv_vbi_fmt *f, unsigned int norm)
+{
+	const struct bttv_tvnorm *tvnorm;
+	unsigned int real_samples_per_line;
+	unsigned int real_count;
+
+	tvnorm = &bttv_tvnorms[norm];
+
+	f->fmt.sampling_rate    = tvnorm->Fsc;
+	f->fmt.samples_per_line = VBI_BPL;
+	f->fmt.sample_format    = V4L2_PIX_FMT_GREY;
+	f->fmt.offset           = VBI_OFFSET;
+	f->fmt.start[0]		= tvnorm->vbistart[0];
+	f->fmt.start[1]		= tvnorm->vbistart[1];
+	f->fmt.count[0]		= VBI_DEFLINES;
+	f->fmt.count[1]		= VBI_DEFLINES;
+	f->fmt.flags            = 0;
+	f->fmt.reserved[0]      = 0;
+	f->fmt.reserved[1]      = 0;
+
+	/* For compatibility the buffer size must be 2 * VBI_DEFLINES *
+	   VBI_BPL regardless of the current video standard. */
+	real_samples_per_line   = 1024 + tvnorm->vbipack * 4;
+	real_count              = ((tvnorm->cropcap.defrect.top >> 1)
+				   - tvnorm->vbistart[0]);
+
+	BUG_ON(real_samples_per_line > VBI_BPL);
+	BUG_ON(real_count > VBI_DEFLINES);
+
+	f->tvnorm               = tvnorm;
+
+	/* See bttv_vbi_fmt_set(). */
+	f->end                  = tvnorm->vbistart[0] * 2 + 2;
+}
+
+/* ----------------------------------------------------------------------- */
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/pci/bt8xx/bttv.h b/drivers/media/pci/bt8xx/bttv.h
new file mode 100644
index 0000000..79a1124
--- /dev/null
+++ b/drivers/media/pci/bt8xx/bttv.h
@@ -0,0 +1,376 @@
+/*
+ *
+ *  bttv - Bt848 frame grabber driver
+ *
+ *  card ID's and external interfaces of the bttv driver
+ *  basically stuff needed by other drivers (i2c, lirc, ...)
+ *  and is supported not to change much over time.
+ *
+ *  Copyright (C) 1996,97 Ralph Metzler (rjkm@thp.uni-koeln.de)
+ *  (c) 1999,2000 Gerd Knorr <kraxel@goldbach.in-berlin.de>
+ *
+ */
+
+#ifndef _BTTV_H_
+#define _BTTV_H_
+
+#include <linux/videodev2.h>
+#include <linux/i2c.h>
+#include <media/v4l2-device.h>
+#include <media/i2c-addr.h>
+#include <media/tuner.h>
+
+/* ---------------------------------------------------------- */
+/* exported by bttv-cards.c                                   */
+
+#define BTTV_BOARD_UNKNOWN                 0x00
+#define BTTV_BOARD_MIRO                    0x01
+#define BTTV_BOARD_HAUPPAUGE               0x02
+#define BTTV_BOARD_STB                     0x03
+#define BTTV_BOARD_INTEL                   0x04
+#define BTTV_BOARD_DIAMOND                 0x05
+#define BTTV_BOARD_AVERMEDIA               0x06
+#define BTTV_BOARD_MATRIX_VISION           0x07
+#define BTTV_BOARD_FLYVIDEO                0x08
+#define BTTV_BOARD_TURBOTV                 0x09
+#define BTTV_BOARD_HAUPPAUGE878            0x0a
+#define BTTV_BOARD_MIROPRO                 0x0b
+#define BTTV_BOARD_ADSTECH_TV              0x0c
+#define BTTV_BOARD_AVERMEDIA98             0x0d
+#define BTTV_BOARD_VHX                     0x0e
+#define BTTV_BOARD_ZOLTRIX                 0x0f
+#define BTTV_BOARD_PIXVIEWPLAYTV           0x10
+#define BTTV_BOARD_WINVIEW_601             0x11
+#define BTTV_BOARD_AVEC_INTERCAP           0x12
+#define BTTV_BOARD_LIFE_FLYKIT             0x13
+#define BTTV_BOARD_CEI_RAFFLES             0x14
+#define BTTV_BOARD_CONFERENCETV            0x15
+#define BTTV_BOARD_PHOEBE_TVMAS            0x16
+#define BTTV_BOARD_MODTEC_205              0x17
+#define BTTV_BOARD_MAGICTVIEW061           0x18
+#define BTTV_BOARD_VOBIS_BOOSTAR           0x19
+#define BTTV_BOARD_HAUPPAUG_WCAM           0x1a
+#define BTTV_BOARD_MAXI                    0x1b
+#define BTTV_BOARD_TERRATV                 0x1c
+#define BTTV_BOARD_PXC200                  0x1d
+#define BTTV_BOARD_FLYVIDEO_98             0x1e
+#define BTTV_BOARD_IPROTV                  0x1f
+#define BTTV_BOARD_INTEL_C_S_PCI           0x20
+#define BTTV_BOARD_TERRATVALUE             0x21
+#define BTTV_BOARD_WINFAST2000             0x22
+#define BTTV_BOARD_CHRONOS_VS2             0x23
+#define BTTV_BOARD_TYPHOON_TVIEW           0x24
+#define BTTV_BOARD_PXELVWPLTVPRO           0x25
+#define BTTV_BOARD_MAGICTVIEW063           0x26
+#define BTTV_BOARD_PINNACLE                0x27
+#define BTTV_BOARD_STB2                    0x28
+#define BTTV_BOARD_AVPHONE98               0x29
+#define BTTV_BOARD_PV951                   0x2a
+#define BTTV_BOARD_ONAIR_TV                0x2b
+#define BTTV_BOARD_SIGMA_TVII_FM           0x2c
+#define BTTV_BOARD_MATRIX_VISION2          0x2d
+#define BTTV_BOARD_ZOLTRIX_GENIE           0x2e
+#define BTTV_BOARD_TERRATVRADIO            0x2f
+#define BTTV_BOARD_DYNALINK                0x30
+#define BTTV_BOARD_GVBCTV3PCI              0x31
+#define BTTV_BOARD_PXELVWPLTVPAK           0x32
+#define BTTV_BOARD_EAGLE                   0x33
+#define BTTV_BOARD_PINNACLEPRO             0x34
+#define BTTV_BOARD_TVIEW_RDS_FM            0x35
+#define BTTV_BOARD_LIFETEC_9415            0x36
+#define BTTV_BOARD_BESTBUY_EASYTV          0x37
+#define BTTV_BOARD_FLYVIDEO_98FM           0x38
+#define BTTV_BOARD_GRANDTEC                0x39
+#define BTTV_BOARD_ASKEY_CPH060            0x3a
+#define BTTV_BOARD_ASKEY_CPH03X            0x3b
+#define BTTV_BOARD_MM100PCTV               0x3c
+#define BTTV_BOARD_GMV1                    0x3d
+#define BTTV_BOARD_BESTBUY_EASYTV2         0x3e
+#define BTTV_BOARD_ATI_TVWONDER            0x3f
+#define BTTV_BOARD_ATI_TVWONDERVE          0x40
+#define BTTV_BOARD_FLYVIDEO2000            0x41
+#define BTTV_BOARD_TERRATVALUER            0x42
+#define BTTV_BOARD_GVBCTV4PCI              0x43
+#define BTTV_BOARD_VOODOOTV_FM             0x44
+#define BTTV_BOARD_AIMMS                   0x45
+#define BTTV_BOARD_PV_BT878P_PLUS          0x46
+#define BTTV_BOARD_FLYVIDEO98EZ            0x47
+#define BTTV_BOARD_PV_BT878P_9B            0x48
+#define BTTV_BOARD_SENSORAY311_611         0x49
+#define BTTV_BOARD_RV605                   0x4a
+#define BTTV_BOARD_POWERCLR_MTV878         0x4b
+#define BTTV_BOARD_WINDVR                  0x4c
+#define BTTV_BOARD_GRANDTEC_MULTI          0x4d
+#define BTTV_BOARD_KWORLD                  0x4e
+#define BTTV_BOARD_DSP_TCVIDEO             0x4f
+#define BTTV_BOARD_HAUPPAUGEPVR            0x50
+#define BTTV_BOARD_GVBCTV5PCI              0x51
+#define BTTV_BOARD_OSPREY1x0               0x52
+#define BTTV_BOARD_OSPREY1x0_848           0x53
+#define BTTV_BOARD_OSPREY101_848           0x54
+#define BTTV_BOARD_OSPREY1x1               0x55
+#define BTTV_BOARD_OSPREY1x1_SVID          0x56
+#define BTTV_BOARD_OSPREY2xx               0x57
+#define BTTV_BOARD_OSPREY2x0_SVID          0x58
+#define BTTV_BOARD_OSPREY2x0               0x59
+#define BTTV_BOARD_OSPREY500               0x5a
+#define BTTV_BOARD_OSPREY540               0x5b
+#define BTTV_BOARD_OSPREY2000              0x5c
+#define BTTV_BOARD_IDS_EAGLE               0x5d
+#define BTTV_BOARD_PINNACLESAT             0x5e
+#define BTTV_BOARD_FORMAC_PROTV            0x5f
+#define BTTV_BOARD_MACHTV                  0x60
+#define BTTV_BOARD_EURESYS_PICOLO          0x61
+#define BTTV_BOARD_PV150                   0x62
+#define BTTV_BOARD_AD_TVK503               0x63
+#define BTTV_BOARD_HERCULES_SM_TV          0x64
+#define BTTV_BOARD_PACETV                  0x65
+#define BTTV_BOARD_IVC200                  0x66
+#define BTTV_BOARD_XGUARD                  0x67
+#define BTTV_BOARD_NEBULA_DIGITV           0x68
+#define BTTV_BOARD_PV143                   0x69
+#define BTTV_BOARD_VD009X1_VD011_MINIDIN   0x6a
+#define BTTV_BOARD_VD009X1_VD011_COMBI     0x6b
+#define BTTV_BOARD_VD009_MINIDIN           0x6c
+#define BTTV_BOARD_VD009_COMBI             0x6d
+#define BTTV_BOARD_IVC100                  0x6e
+#define BTTV_BOARD_IVC120                  0x6f
+#define BTTV_BOARD_PC_HDTV                 0x70
+#define BTTV_BOARD_TWINHAN_DST             0x71
+#define BTTV_BOARD_WINFASTVC100            0x72
+#define BTTV_BOARD_TEV560                  0x73
+#define BTTV_BOARD_SIMUS_GVC1100           0x74
+#define BTTV_BOARD_NGSTV_PLUS              0x75
+#define BTTV_BOARD_LMLBT4                  0x76
+#define BTTV_BOARD_TEKRAM_M205             0x77
+#define BTTV_BOARD_CONTVFMI                0x78
+#define BTTV_BOARD_PICOLO_TETRA_CHIP       0x79
+#define BTTV_BOARD_SPIRIT_TV               0x7a
+#define BTTV_BOARD_AVDVBT_771              0x7b
+#define BTTV_BOARD_AVDVBT_761              0x7c
+#define BTTV_BOARD_MATRIX_VISIONSQ         0x7d
+#define BTTV_BOARD_MATRIX_VISIONSLC        0x7e
+#define BTTV_BOARD_APAC_VIEWCOMP           0x7f
+#define BTTV_BOARD_DVICO_DVBT_LITE         0x80
+#define BTTV_BOARD_VGEAR_MYVCD             0x81
+#define BTTV_BOARD_SUPER_TV                0x82
+#define BTTV_BOARD_TIBET_CS16              0x83
+#define BTTV_BOARD_KODICOM_4400R           0x84
+#define BTTV_BOARD_KODICOM_4400R_SL        0x85
+#define BTTV_BOARD_ADLINK_RTV24            0x86
+#define BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE 0x87
+#define BTTV_BOARD_ACORP_Y878F             0x88
+#define BTTV_BOARD_CONCEPTRONIC_CTVFMI2    0x89
+#define BTTV_BOARD_PV_BT878P_2E            0x8a
+#define BTTV_BOARD_PV_M4900                0x8b
+#define BTTV_BOARD_OSPREY440               0x8c
+#define BTTV_BOARD_ASOUND_SKYEYE	   0x8d
+#define BTTV_BOARD_SABRENT_TVFM   	   0x8e
+#define BTTV_BOARD_HAUPPAUGE_IMPACTVCB     0x8f
+#define BTTV_BOARD_MACHTV_MAGICTV          0x90
+#define BTTV_BOARD_SSAI_SECURITY	   0x91
+#define BTTV_BOARD_SSAI_ULTRASOUND	   0x92
+#define BTTV_BOARD_VOODOOTV_200		   0x93
+#define BTTV_BOARD_DVICO_FUSIONHDTV_2	   0x94
+#define BTTV_BOARD_TYPHOON_TVTUNERPCI	   0x95
+#define BTTV_BOARD_GEOVISION_GV600	   0x96
+#define BTTV_BOARD_KOZUMI_KTV_01C          0x97
+#define BTTV_BOARD_ENLTV_FM_2		   0x98
+#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
+#define BTTV_BOARD_TVT_TD3116		   0xa0
+#define BTTV_BOARD_APOSONIC_WDVR           0xa1
+
+/* more card-specific defines */
+#define PT2254_L_CHANNEL 0x10
+#define PT2254_R_CHANNEL 0x08
+#define PT2254_DBS_IN_2 0x400
+#define PT2254_DBS_IN_10 0x20000
+#define WINVIEW_PT2254_CLK  0x40
+#define WINVIEW_PT2254_DATA 0x20
+#define WINVIEW_PT2254_STROBE 0x80
+
+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 */
+
+	/* device config */
+	unsigned int         nr;       /* dev nr (for printk("bttv%d: ...");  */
+	unsigned int         type;     /* card type (pointer into tvcards[])  */
+};
+
+struct bttv;
+
+struct tvcard {
+	char *name;
+	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 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_tda7432: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. */
+
+	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;
+};
+
+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);
+extern void bttv_init_card2(struct bttv *btv);
+extern void bttv_init_tuner(struct bttv *btv);
+
+/* card-specific funtions */
+extern void tea5757_set_freq(struct bttv *btv, unsigned short freq);
+extern u32 bttv_tda9880_setnorm(struct bttv *btv, u32 gpiobits);
+
+/* extra tweaks for some chipsets */
+extern void bttv_check_chipset(void);
+extern int bttv_handle_chipset(struct bttv *btv);
+
+/* ---------------------------------------------------------- */
+/* exported by bttv-if.c                                      */
+
+/* this obsolete -- please use the sysfs-based
+   interface below for new code */
+
+extern struct pci_dev* bttv_get_pcidev(unsigned int card);
+
+/* sets GPOE register (BT848_GPIO_OUT_EN) to new value:
+   data | (current_GPOE_value & ~mask)
+   returns negative value if error occurred
+*/
+extern int bttv_gpio_enable(unsigned int card,
+			    unsigned long mask, unsigned long data);
+
+/* fills data with GPDATA register contents
+   returns negative value if error occurred
+*/
+extern int bttv_read_gpio(unsigned int card, unsigned long *data);
+
+/* sets GPDATA register to new value:
+  (data & mask) | (current_GPDATA_value & ~mask)
+  returns negative value if error occurred
+*/
+extern int bttv_write_gpio(unsigned int card,
+			   unsigned long mask, unsigned long data);
+
+
+
+
+/* ---------------------------------------------------------- */
+/* sysfs/driver-moded based gpio access interface             */
+
+struct bttv_sub_device {
+	struct device    dev;
+	struct bttv_core *core;
+	struct list_head list;
+};
+#define to_bttv_sub_dev(x) container_of((x), struct bttv_sub_device, dev)
+
+struct bttv_sub_driver {
+	struct device_driver   drv;
+	char                   wanted[20];
+	int                    (*probe)(struct bttv_sub_device *sub);
+	void                   (*remove)(struct bttv_sub_device *sub);
+};
+#define to_bttv_sub_drv(x) container_of((x), struct bttv_sub_driver, drv)
+
+int bttv_sub_register(struct bttv_sub_driver *drv, char *wanted);
+int bttv_sub_unregister(struct bttv_sub_driver *drv);
+
+/* gpio access functions */
+void bttv_gpio_inout(struct bttv_core *core, u32 mask, u32 outbits);
+u32 bttv_gpio_read(struct bttv_core *core);
+void bttv_gpio_write(struct bttv_core *core, u32 value);
+void bttv_gpio_bits(struct bttv_core *core, u32 mask, u32 bits);
+
+#define gpio_inout(mask,bits)  bttv_gpio_inout(&btv->c, mask, bits)
+#define gpio_read()            bttv_gpio_read(&btv->c)
+#define gpio_write(value)      bttv_gpio_write(&btv->c, value)
+#define gpio_bits(mask,bits)   bttv_gpio_bits(&btv->c, mask, bits)
+
+
+/* ---------------------------------------------------------- */
+/* i2c                                                        */
+
+#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);
+extern void bttv_readee(struct bttv *btv, unsigned char *eedata, int addr);
+
+extern int bttv_input_init(struct bttv *dev);
+extern void bttv_input_fini(struct bttv *dev);
+extern void bttv_input_irq(struct bttv *dev);
+
+#endif /* _BTTV_H_ */
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/pci/bt8xx/bttvp.h b/drivers/media/pci/bt8xx/bttvp.h
new file mode 100644
index 0000000..70fd4f2
--- /dev/null
+++ b/drivers/media/pci/bt8xx/bttvp.h
@@ -0,0 +1,535 @@
+/*
+
+    bttv - Bt848 frame grabber driver
+
+    bttv's *private* header file  --  nobody other than bttv itself
+    should ever include this file.
+
+    (c) 2000-2002 Gerd Knorr <kraxel@bytesex.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 _BTTVP_H_
+#define _BTTVP_H_
+
+#include <linux/types.h>
+#include <linux/wait.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+#include <linux/pci.h>
+#include <linux/input.h>
+#include <linux/mutex.h>
+#include <linux/scatterlist.h>
+#include <asm/io.h>
+#include <media/v4l2-common.h>
+#include <linux/device.h>
+#include <media/videobuf-dma-sg.h>
+#include <media/tveeprom.h>
+#include <media/rc-core.h>
+#include <media/ir-kbd-i2c.h>
+
+#include "bt848.h"
+#include "bttv.h"
+#include "btcx-risc.h"
+
+#ifdef __KERNEL__
+
+#define FORMAT_FLAGS_DITHER       0x01
+#define FORMAT_FLAGS_PACKED       0x02
+#define FORMAT_FLAGS_PLANAR       0x04
+#define FORMAT_FLAGS_RAW          0x08
+#define FORMAT_FLAGS_CrCb         0x10
+
+#define RISC_SLOT_O_VBI        4
+#define RISC_SLOT_O_FIELD      6
+#define RISC_SLOT_E_VBI       10
+#define RISC_SLOT_E_FIELD     12
+#define RISC_SLOT_LOOP        14
+
+#define RESOURCE_OVERLAY       1
+#define RESOURCE_VIDEO_STREAM  2
+#define RESOURCE_VBI           4
+#define RESOURCE_VIDEO_READ    8
+
+#define RAW_LINES            640
+#define RAW_BPL             1024
+
+#define UNSET (-1U)
+
+/* Min. value in VDELAY register. */
+#define MIN_VDELAY 2
+/* Even to get Cb first, odd for Cr. */
+#define MAX_HDELAY (0x3FF & -2)
+/* Limits scaled width, which must be a multiple of 4. */
+#define MAX_HACTIVE (0x3FF & -4)
+
+#define BTTV_NORMS    (\
+		V4L2_STD_PAL    | V4L2_STD_PAL_N | \
+		V4L2_STD_PAL_Nc | V4L2_STD_SECAM | \
+		V4L2_STD_NTSC   | V4L2_STD_PAL_M | \
+		V4L2_STD_PAL_60)
+/* ---------------------------------------------------------- */
+
+struct bttv_tvnorm {
+	int   v4l2_id;
+	char  *name;
+	u32   Fsc;
+	u16   swidth, sheight; /* scaled standard width, height */
+	u16   totalwidth;
+	u8    adelay, bdelay, iform;
+	u32   scaledtwidth;
+	u16   hdelayx1, hactivex1;
+	u16   vdelay;
+	u8    vbipack;
+	u16   vtotal;
+	int   sram;
+	/* ITU-R frame line number of the first VBI line we can
+	   capture, of the first and second field. The last possible line
+	   is determined by cropcap.bounds. */
+	u16   vbistart[2];
+	/* Horizontally this counts fCLKx1 samples following the leading
+	   edge of the horizontal sync pulse, vertically ITU-R frame line
+	   numbers of the first field times two (2, 4, 6, ... 524 or 624). */
+	struct v4l2_cropcap cropcap;
+};
+extern const struct bttv_tvnorm bttv_tvnorms[];
+
+struct bttv_format {
+	char *name;
+	int  fourcc;          /* video4linux 2      */
+	int  btformat;        /* BT848_COLOR_FMT_*  */
+	int  btswap;          /* BT848_COLOR_CTL_*  */
+	int  depth;           /* bit/pixel          */
+	int  flags;
+	int  hshift,vshift;   /* for planar modes   */
+};
+
+struct bttv_ir {
+	struct rc_dev           *dev;
+	struct timer_list       timer;
+
+	char                    name[32];
+	char                    phys[32];
+
+	/* Usual gpio signalling */
+	u32                     mask_keycode;
+	u32                     mask_keydown;
+	u32                     mask_keyup;
+	u32                     polling;
+	u32                     last_gpio;
+	int                     shift_by;
+	int                     start; // What should RC5_START() be
+	int                     addr; // What RC5_ADDR() should be.
+	int                     rc5_remote_gap;
+
+	/* RC5 gpio */
+	bool			rc5_gpio;   /* Is RC5 legacy GPIO enabled? */
+	u32                     last_bit;   /* last raw bit seen */
+	u32                     code;       /* raw code under construction */
+	struct timeval          base_time;  /* time of last seen code */
+	bool                    active;     /* building raw code */
+};
+
+
+/* ---------------------------------------------------------- */
+
+struct bttv_geometry {
+	u8  vtc,crop,comb;
+	u16 width,hscale,hdelay;
+	u16 sheight,vscale,vdelay,vtotal;
+};
+
+struct bttv_buffer {
+	/* common v4l buffer stuff -- must be first */
+	struct videobuf_buffer     vb;
+
+	/* bttv specific */
+	const struct bttv_format   *fmt;
+	unsigned int               tvnorm;
+	int                        btformat;
+	int                        btswap;
+	struct bttv_geometry       geo;
+	struct btcx_riscmem        top;
+	struct btcx_riscmem        bottom;
+	struct v4l2_rect           crop;
+	unsigned int               vbi_skip[2];
+	unsigned int               vbi_count[2];
+};
+
+struct bttv_buffer_set {
+	struct bttv_buffer     *top;       /* top field buffer    */
+	struct bttv_buffer     *bottom;    /* bottom field buffer */
+	unsigned int           top_irq;
+	unsigned int           frame_irq;
+};
+
+struct bttv_overlay {
+	unsigned int           tvnorm;
+	struct v4l2_rect       w;
+	enum v4l2_field        field;
+	struct v4l2_clip       *clips;
+	int                    nclips;
+	int                    setup_ok;
+};
+
+struct bttv_vbi_fmt {
+	struct v4l2_vbi_format fmt;
+
+	/* fmt.start[] and count[] refer to this video standard. */
+	const struct bttv_tvnorm *tvnorm;
+
+	/* Earliest possible start of video capturing with this
+	   v4l2_vbi_format, in struct bttv_crop.rect units. */
+	__s32                  end;
+};
+
+/* bttv-vbi.c */
+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. */
+	struct v4l2_rect       rect;
+
+	/* Scaled image size limits with this crop rect. Divide
+	   max_height, but not min_height, by two when capturing
+	   single fields. See also bttv_crop_reset() and
+	   bttv_crop_adjust() in bttv-driver.c. */
+	__s32                  min_scaled_width;
+	__s32                  min_scaled_height;
+	__s32                  max_scaled_width;
+	__s32                  max_scaled_height;
+};
+
+struct bttv_fh {
+	struct bttv              *btv;
+	int resources;
+#ifdef VIDIOC_G_PRIORITY
+	enum v4l2_priority       prio;
+#endif
+	enum v4l2_buf_type       type;
+
+	/* video capture */
+	struct videobuf_queue    cap;
+	const struct bttv_format *fmt;
+	int                      width;
+	int                      height;
+
+	/* video overlay */
+	const struct bttv_format *ovfmt;
+	struct bttv_overlay      ov;
+
+	/* Application called VIDIOC_S_CROP. */
+	int                      do_crop;
+
+	/* vbi capture */
+	struct videobuf_queue    vbi;
+	/* Current VBI capture window as seen through this fh (cannot
+	   be global for compatibility with earlier drivers). Protected
+	   by struct bttv.lock and struct bttv_fh.vbi.lock. */
+	struct bttv_vbi_fmt      vbi_fmt;
+};
+
+/* ---------------------------------------------------------- */
+/* bttv-risc.c                                                */
+
+/* risc code generators - capture */
+int bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc,
+		     struct scatterlist *sglist,
+		     unsigned int offset, unsigned int bpl,
+		     unsigned int pitch, unsigned int skip_lines,
+		     unsigned int store_lines);
+
+/* control dma register + risc main loop */
+void bttv_set_dma(struct bttv *btv, int override);
+int bttv_risc_init_main(struct bttv *btv);
+int bttv_risc_hook(struct bttv *btv, int slot, struct btcx_riscmem *risc,
+		   int irqflags);
+
+/* capture buffer handling */
+int bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf);
+int bttv_buffer_activate_video(struct bttv *btv,
+			       struct bttv_buffer_set *set);
+int bttv_buffer_activate_vbi(struct bttv *btv,
+			     struct bttv_buffer *vbi);
+void bttv_dma_free(struct videobuf_queue *q, struct bttv *btv,
+		   struct bttv_buffer *buf);
+
+/* overlay handling */
+int bttv_overlay_risc(struct bttv *btv, struct bttv_overlay *ov,
+		      const struct bttv_format *fmt,
+		      struct bttv_buffer *buf);
+
+
+/* ---------------------------------------------------------- */
+/* bttv-vbi.c                                                 */
+
+int bttv_try_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *f);
+int bttv_g_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *f);
+int bttv_s_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *f);
+
+extern struct videobuf_queue_ops bttv_vbi_qops;
+
+/* ---------------------------------------------------------- */
+/* bttv-gpio.c */
+
+extern struct bus_type bttv_sub_bus_type;
+int bttv_sub_add_device(struct bttv_core *core, char *name);
+int bttv_sub_del_devices(struct bttv_core *core);
+
+/* ---------------------------------------------------------- */
+/* bttv-cards.c                                               */
+
+extern int no_overlay;
+
+/* ---------------------------------------------------------- */
+/* bttv-input.c                                               */
+
+extern void init_bttv_i2c_ir(struct bttv *btv);
+extern int fini_bttv_i2c(struct bttv *btv);
+
+/* ---------------------------------------------------------- */
+/* bttv-driver.c                                              */
+
+/* insmod options */
+extern unsigned int bttv_verbose;
+extern unsigned int bttv_debug;
+extern unsigned int bttv_gpio;
+extern void bttv_gpio_tracking(struct bttv *btv, char *comment);
+extern int init_bttv_i2c(struct bttv *btv);
+
+#define dprintk(fmt, ...)			\
+do {						\
+	if (bttv_debug >= 1)			\
+		pr_debug(fmt, ##__VA_ARGS__);	\
+} while (0)
+#define dprintk_cont(fmt, ...)			\
+do {						\
+	if (bttv_debug >= 1)			\
+		pr_cont(fmt, ##__VA_ARGS__);	\
+} while (0)
+#define d2printk(fmt, ...)			\
+do {						\
+	if (bttv_debug >= 2)			\
+		printk(fmt, ##__VA_ARGS__);	\
+} while (0)
+
+#define BTTV_MAX_FBUF   0x208000
+#define BTTV_TIMEOUT    msecs_to_jiffies(500)    /* 0.5 seconds */
+#define BTTV_FREE_IDLE  msecs_to_jiffies(1000)   /* one second */
+
+
+struct bttv_pll_info {
+	unsigned int pll_ifreq;    /* PLL input frequency        */
+	unsigned int pll_ofreq;    /* PLL output frequency       */
+	unsigned int pll_crystal;  /* Crystal used for input     */
+	unsigned int pll_current;  /* Currently programmed ofreq */
+};
+
+/* for gpio-connected remote control */
+struct bttv_input {
+	struct input_dev      *dev;
+	char                  name[32];
+	char                  phys[32];
+	u32                   mask_keycode;
+	u32                   mask_keydown;
+};
+
+struct bttv_suspend_state {
+	u32  gpio_enable;
+	u32  gpio_data;
+	int  disabled;
+	int  loop_irq;
+	struct bttv_buffer_set video;
+	struct bttv_buffer     *vbi;
+};
+
+struct bttv {
+	struct bttv_core c;
+
+	/* pci device config */
+	unsigned short id;
+	unsigned char revision;
+	unsigned char __iomem *bt848_mmio;   /* pointer to mmio */
+
+	/* card configuration info */
+	unsigned int cardid;   /* pci subsystem id (bt878 based ones) */
+	unsigned int tuner_type;  /* tuner chip type */
+	unsigned int tda9887_conf;
+	unsigned int svhs, dig;
+	unsigned int has_saa6588:1;
+	struct bttv_pll_info pll;
+	int triton1;
+	int gpioirq;
+
+	int use_i2c_hw;
+
+	/* old gpio interface */
+	int shutdown;
+
+	void (*volume_gpio)(struct bttv *btv, __u16 volume);
+	void (*audio_mode_gpio)(struct bttv *btv, struct v4l2_tuner *tuner, int set);
+
+	/* new gpio interface */
+	spinlock_t gpio_lock;
+
+	/* i2c layer */
+	struct i2c_algo_bit_data   i2c_algo;
+	struct i2c_client          i2c_client;
+	int                        i2c_state, i2c_rc;
+	int                        i2c_done;
+	wait_queue_head_t          i2c_queue;
+	struct v4l2_subdev 	  *sd_msp34xx;
+	struct v4l2_subdev 	  *sd_tvaudio;
+
+	/* video4linux (1) */
+	struct video_device *video_dev;
+	struct video_device *radio_dev;
+	struct video_device *vbi_dev;
+
+	/* infrared remote */
+	int has_remote;
+	struct bttv_ir *remote;
+
+	/* I2C remote data */
+	struct IR_i2c_init_data    init_data;
+
+	/* locking */
+	spinlock_t s_lock;
+	struct mutex lock;
+	int resources;
+#ifdef VIDIOC_G_PRIORITY
+	struct v4l2_prio_state prio;
+#endif
+
+	/* video state */
+	unsigned int input;
+	unsigned int audio;
+	unsigned int mute;
+	unsigned long freq;
+	unsigned int tvnorm;
+	int hue, contrast, bright, saturation;
+	struct v4l2_framebuffer fbuf;
+	unsigned int field_count;
+
+	/* various options */
+	int opt_combfilter;
+	int opt_lumafilter;
+	int opt_automute;
+	int opt_chroma_agc;
+	int opt_adc_crush;
+	int opt_vcr_hack;
+	int opt_whitecrush_upper;
+	int opt_whitecrush_lower;
+	int opt_uv_ratio;
+	int opt_full_luma_range;
+	int opt_coring;
+
+	/* radio data/state */
+	int has_radio;
+	int radio_user;
+	int radio_uses_msp_demodulator;
+
+	/* miro/pinnacle + Aimslab VHX
+	   philips matchbox (tea5757 radio tuner) support */
+	int has_matchbox;
+	int mbox_we;
+	int mbox_data;
+	int mbox_clk;
+	int mbox_most;
+	int mbox_mask;
+
+	/* ISA stuff (Terratec Active Radio Upgrade) */
+	int mbox_ior;
+	int mbox_iow;
+	int mbox_csel;
+
+	/* risc memory management data
+	   - must acquire s_lock before changing these
+	   - only the irq handler is supported to touch top + bottom + vcurr */
+	struct btcx_riscmem     main;
+	struct bttv_buffer      *screen;    /* overlay             */
+	struct list_head        capture;    /* video capture queue */
+	struct list_head        vcapture;   /* vbi capture queue   */
+	struct bttv_buffer_set  curr;       /* active buffers      */
+	struct bttv_buffer      *cvbi;      /* active vbi buffer   */
+	int                     loop_irq;
+	int                     new_input;
+
+	unsigned long cap_ctl;
+	unsigned long dma_on;
+	struct timer_list timeout;
+	struct bttv_suspend_state state;
+
+	/* stats */
+	unsigned int errors;
+	unsigned int framedrop;
+	unsigned int irq_total;
+	unsigned int irq_me;
+
+	unsigned int users;
+	struct bttv_fh init;
+
+	/* used to make dvb-bt8xx autoloadable */
+	struct work_struct request_module_wk;
+
+	/* Default (0) and current (1) video capturing and overlay
+	   cropping parameters in bttv_tvnorm.cropcap units. Protected
+	   by bttv.lock. */
+	struct bttv_crop crop[2];
+
+	/* Earliest possible start of video capturing in
+	   bttv_tvnorm.cropcap line units. Set by check_alloc_btres()
+	   and free_btres(). Protected by bttv.lock. */
+	__s32			vbi_end;
+
+	/* Latest possible end of VBI capturing (= crop[x].rect.top when
+	   VIDEO_RESOURCES are locked). Set by check_alloc_btres()
+	   and free_btres(). Protected by bttv.lock. */
+	__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];
+
+static inline unsigned int bttv_muxsel(const struct bttv *btv,
+				       unsigned int input)
+{
+	return (bttv_tvcards[btv->c.type].muxsel >> (input * 2)) & 3;
+}
+
+#endif
+
+#define btwrite(dat,adr)    writel((dat), btv->bt848_mmio+(adr))
+#define btread(adr)         readl(btv->bt848_mmio+(adr))
+
+#define btand(dat,adr)      btwrite((dat) & btread(adr), adr)
+#define btor(dat,adr)       btwrite((dat) | btread(adr), adr)
+#define btaor(dat,mask,adr) btwrite((dat) | ((mask) & btread(adr)), adr)
+
+#endif /* _BTTVP_H_ */
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/pci/bt8xx/dst.c b/drivers/media/pci/bt8xx/dst.c
new file mode 100644
index 0000000..430b3eb
--- /dev/null
+++ b/drivers/media/pci/bt8xx/dst.c
@@ -0,0 +1,1873 @@
+/*
+	Frontend/Card driver for TwinHan DST Frontend
+	Copyright (C) 2003 Jamie Honan
+	Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.com)
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <asm/div64.h>
+#include "dvb_frontend.h"
+#include "dst_priv.h"
+#include "dst_common.h"
+
+static unsigned int verbose = 1;
+module_param(verbose, int, 0644);
+MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)");
+
+static unsigned int dst_addons;
+module_param(dst_addons, int, 0644);
+MODULE_PARM_DESC(dst_addons, "CA daughterboard, default is 0 (No addons)");
+
+static unsigned int dst_algo;
+module_param(dst_algo, int, 0644);
+MODULE_PARM_DESC(dst_algo, "tuning algo: default is 0=(SW), 1=(HW)");
+
+#define HAS_LOCK		1
+#define ATTEMPT_TUNE		2
+#define HAS_POWER		4
+
+#define DST_ERROR		0
+#define DST_NOTICE		1
+#define DST_INFO		2
+#define DST_DEBUG		3
+
+#define dprintk(x, y, z, format, arg...) do {				\
+	if (z) {							\
+		if	((x > DST_ERROR) && (x > y))			\
+			printk(KERN_ERR "dst(%d) %s: " format "\n",	\
+				state->bt->nr, __func__ , ##arg);	\
+		else if	((x > DST_NOTICE) && (x > y))			\
+			printk(KERN_NOTICE "dst(%d) %s: " format "\n",  \
+				state->bt->nr, __func__ , ##arg);	\
+		else if ((x > DST_INFO) && (x > y))			\
+			printk(KERN_INFO "dst(%d) %s: " format "\n",	\
+				state->bt->nr, __func__ , ##arg);	\
+		else if ((x > DST_DEBUG) && (x > y))			\
+			printk(KERN_DEBUG "dst(%d) %s: " format "\n",	\
+				state->bt->nr,  __func__ , ##arg);	\
+	} else {							\
+		if (x > y)						\
+			printk(format, ##arg);				\
+	}								\
+} while(0)
+
+static int dst_command(struct dst_state *state, u8 *data, u8 len);
+
+static void dst_packsize(struct dst_state *state, int psize)
+{
+	union dst_gpio_packet bits;
+
+	bits.psize = psize;
+	bt878_device_control(state->bt, DST_IG_TS, &bits);
+}
+
+static int dst_gpio_outb(struct dst_state *state, u32 mask, u32 enbb,
+			 u32 outhigh, int delay)
+{
+	union dst_gpio_packet enb;
+	union dst_gpio_packet bits;
+	int err;
+
+	enb.enb.mask = mask;
+	enb.enb.enable = enbb;
+
+	dprintk(verbose, DST_INFO, 1, "mask=[%04x], enbb=[%04x], outhigh=[%04x]", mask, enbb, outhigh);
+	if ((err = bt878_device_control(state->bt, DST_IG_ENABLE, &enb)) < 0) {
+		dprintk(verbose, DST_INFO, 1, "dst_gpio_enb error (err == %i, mask == %02x, enb == %02x)", err, mask, enbb);
+		return -EREMOTEIO;
+	}
+	udelay(1000);
+	/* because complete disabling means no output, no need to do output packet */
+	if (enbb == 0)
+		return 0;
+	if (delay)
+		msleep(10);
+	bits.outp.mask = enbb;
+	bits.outp.highvals = outhigh;
+	if ((err = bt878_device_control(state->bt, DST_IG_WRITE, &bits)) < 0) {
+		dprintk(verbose, DST_INFO, 1, "dst_gpio_outb error (err == %i, enbb == %02x, outhigh == %02x)", err, enbb, outhigh);
+		return -EREMOTEIO;
+	}
+
+	return 0;
+}
+
+static int dst_gpio_inb(struct dst_state *state, u8 *result)
+{
+	union dst_gpio_packet rd_packet;
+	int err;
+
+	*result = 0;
+	if ((err = bt878_device_control(state->bt, DST_IG_READ, &rd_packet)) < 0) {
+		dprintk(verbose, DST_ERROR, 1, "dst_gpio_inb error (err == %i)", err);
+		return -EREMOTEIO;
+	}
+	*result = (u8) rd_packet.rd.value;
+
+	return 0;
+}
+
+int rdc_reset_state(struct dst_state *state)
+{
+	dprintk(verbose, DST_INFO, 1, "Resetting state machine");
+	if (dst_gpio_outb(state, RDC_8820_INT, RDC_8820_INT, 0, NO_DELAY) < 0) {
+		dprintk(verbose, DST_ERROR, 1, "dst_gpio_outb ERROR !");
+		return -1;
+	}
+	msleep(10);
+	if (dst_gpio_outb(state, RDC_8820_INT, RDC_8820_INT, RDC_8820_INT, NO_DELAY) < 0) {
+		dprintk(verbose, DST_ERROR, 1, "dst_gpio_outb ERROR !");
+		msleep(10);
+		return -1;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(rdc_reset_state);
+
+static int rdc_8820_reset(struct dst_state *state)
+{
+	dprintk(verbose, DST_DEBUG, 1, "Resetting DST");
+	if (dst_gpio_outb(state, RDC_8820_RESET, RDC_8820_RESET, 0, NO_DELAY) < 0) {
+		dprintk(verbose, DST_ERROR, 1, "dst_gpio_outb ERROR !");
+		return -1;
+	}
+	udelay(1000);
+	if (dst_gpio_outb(state, RDC_8820_RESET, RDC_8820_RESET, RDC_8820_RESET, DELAY) < 0) {
+		dprintk(verbose, DST_ERROR, 1, "dst_gpio_outb ERROR !");
+		return -1;
+	}
+
+	return 0;
+}
+
+static int dst_pio_enable(struct dst_state *state)
+{
+	if (dst_gpio_outb(state, ~0, RDC_8820_PIO_0_ENABLE, 0, NO_DELAY) < 0) {
+		dprintk(verbose, DST_ERROR, 1, "dst_gpio_outb ERROR !");
+		return -1;
+	}
+	udelay(1000);
+
+	return 0;
+}
+
+int dst_pio_disable(struct dst_state *state)
+{
+	if (dst_gpio_outb(state, ~0, RDC_8820_PIO_0_DISABLE, RDC_8820_PIO_0_DISABLE, NO_DELAY) < 0) {
+		dprintk(verbose, DST_ERROR, 1, "dst_gpio_outb ERROR !");
+		return -1;
+	}
+	if (state->type_flags & DST_TYPE_HAS_FW_1)
+		udelay(1000);
+
+	return 0;
+}
+EXPORT_SYMBOL(dst_pio_disable);
+
+int dst_wait_dst_ready(struct dst_state *state, u8 delay_mode)
+{
+	u8 reply;
+	int i;
+
+	for (i = 0; i < 200; i++) {
+		if (dst_gpio_inb(state, &reply) < 0) {
+			dprintk(verbose, DST_ERROR, 1, "dst_gpio_inb ERROR !");
+			return -1;
+		}
+		if ((reply & RDC_8820_PIO_0_ENABLE) == 0) {
+			dprintk(verbose, DST_INFO, 1, "dst wait ready after %d", i);
+			return 1;
+		}
+		msleep(10);
+	}
+	dprintk(verbose, DST_NOTICE, 1, "dst wait NOT ready after %d", i);
+
+	return 0;
+}
+EXPORT_SYMBOL(dst_wait_dst_ready);
+
+int dst_error_recovery(struct dst_state *state)
+{
+	dprintk(verbose, DST_NOTICE, 1, "Trying to return from previous errors.");
+	dst_pio_disable(state);
+	msleep(10);
+	dst_pio_enable(state);
+	msleep(10);
+
+	return 0;
+}
+EXPORT_SYMBOL(dst_error_recovery);
+
+int dst_error_bailout(struct dst_state *state)
+{
+	dprintk(verbose, DST_INFO, 1, "Trying to bailout from previous error.");
+	rdc_8820_reset(state);
+	dst_pio_disable(state);
+	msleep(10);
+
+	return 0;
+}
+EXPORT_SYMBOL(dst_error_bailout);
+
+int dst_comm_init(struct dst_state *state)
+{
+	dprintk(verbose, DST_INFO, 1, "Initializing DST.");
+	if ((dst_pio_enable(state)) < 0) {
+		dprintk(verbose, DST_ERROR, 1, "PIO Enable Failed");
+		return -1;
+	}
+	if ((rdc_reset_state(state)) < 0) {
+		dprintk(verbose, DST_ERROR, 1, "RDC 8820 State RESET Failed.");
+		return -1;
+	}
+	if (state->type_flags & DST_TYPE_HAS_FW_1)
+		msleep(100);
+	else
+		msleep(5);
+
+	return 0;
+}
+EXPORT_SYMBOL(dst_comm_init);
+
+int write_dst(struct dst_state *state, u8 *data, u8 len)
+{
+	struct i2c_msg msg = {
+		.addr = state->config->demod_address,
+		.flags = 0,
+		.buf = data,
+		.len = len
+	};
+
+	int err;
+	u8 cnt, i;
+
+	dprintk(verbose, DST_NOTICE, 0, "writing [ ");
+	for (i = 0; i < len; i++)
+		dprintk(verbose, DST_NOTICE, 0, "%02x ", data[i]);
+	dprintk(verbose, DST_NOTICE, 0, "]\n");
+
+	for (cnt = 0; cnt < 2; cnt++) {
+		if ((err = i2c_transfer(state->i2c, &msg, 1)) < 0) {
+			dprintk(verbose, DST_INFO, 1, "_write_dst error (err == %i, len == 0x%02x, b0 == 0x%02x)", err, len, data[0]);
+			dst_error_recovery(state);
+			continue;
+		} else
+			break;
+	}
+	if (cnt >= 2) {
+		dprintk(verbose, DST_INFO, 1, "RDC 8820 RESET");
+		dst_error_bailout(state);
+
+		return -1;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(write_dst);
+
+int read_dst(struct dst_state *state, u8 *ret, u8 len)
+{
+	struct i2c_msg msg = {
+		.addr = state->config->demod_address,
+		.flags = I2C_M_RD,
+		.buf = ret,
+		.len = len
+	};
+
+	int err;
+	int cnt;
+
+	for (cnt = 0; cnt < 2; cnt++) {
+		if ((err = i2c_transfer(state->i2c, &msg, 1)) < 0) {
+			dprintk(verbose, DST_INFO, 1, "read_dst error (err == %i, len == 0x%02x, b0 == 0x%02x)", err, len, ret[0]);
+			dst_error_recovery(state);
+			continue;
+		} else
+			break;
+	}
+	if (cnt >= 2) {
+		dprintk(verbose, DST_INFO, 1, "RDC 8820 RESET");
+		dst_error_bailout(state);
+
+		return -1;
+	}
+	dprintk(verbose, DST_DEBUG, 1, "reply is 0x%x", ret[0]);
+	for (err = 1; err < len; err++)
+		dprintk(verbose, DST_DEBUG, 0, " 0x%x", ret[err]);
+	if (err > 1)
+		dprintk(verbose, DST_DEBUG, 0, "\n");
+
+	return 0;
+}
+EXPORT_SYMBOL(read_dst);
+
+static int dst_set_polarization(struct dst_state *state)
+{
+	switch (state->voltage) {
+	case SEC_VOLTAGE_13:	/*	Vertical	*/
+		dprintk(verbose, DST_INFO, 1, "Polarization=[Vertical]");
+		state->tx_tuna[8] &= ~0x40;
+		break;
+	case SEC_VOLTAGE_18:	/*	Horizontal	*/
+		dprintk(verbose, DST_INFO, 1, "Polarization=[Horizontal]");
+		state->tx_tuna[8] |= 0x40;
+		break;
+	case SEC_VOLTAGE_OFF:
+		break;
+	}
+
+	return 0;
+}
+
+static int dst_set_freq(struct dst_state *state, u32 freq)
+{
+	state->frequency = freq;
+	dprintk(verbose, DST_INFO, 1, "set Frequency %u", freq);
+
+	if (state->dst_type == DST_TYPE_IS_SAT) {
+		freq = freq / 1000;
+		if (freq < 950 || freq > 2150)
+			return -EINVAL;
+		state->tx_tuna[2] = (freq >> 8);
+		state->tx_tuna[3] = (u8) freq;
+		state->tx_tuna[4] = 0x01;
+		state->tx_tuna[8] &= ~0x04;
+		if (state->type_flags & DST_TYPE_HAS_OBS_REGS) {
+			if (freq < 1531)
+				state->tx_tuna[8] |= 0x04;
+		}
+	} else if (state->dst_type == DST_TYPE_IS_TERR) {
+		freq = freq / 1000;
+		if (freq < 137000 || freq > 858000)
+			return -EINVAL;
+		state->tx_tuna[2] = (freq >> 16) & 0xff;
+		state->tx_tuna[3] = (freq >> 8) & 0xff;
+		state->tx_tuna[4] = (u8) freq;
+	} else if (state->dst_type == DST_TYPE_IS_CABLE) {
+		freq = freq / 1000;
+		state->tx_tuna[2] = (freq >> 16) & 0xff;
+		state->tx_tuna[3] = (freq >> 8) & 0xff;
+		state->tx_tuna[4] = (u8) freq;
+	} else if (state->dst_type == DST_TYPE_IS_ATSC) {
+		freq = freq / 1000;
+		if (freq < 51000 || freq > 858000)
+			return -EINVAL;
+		state->tx_tuna[2] = (freq >> 16) & 0xff;
+		state->tx_tuna[3] = (freq >>  8) & 0xff;
+		state->tx_tuna[4] = (u8) freq;
+		state->tx_tuna[5] = 0x00;		/*	ATSC	*/
+		state->tx_tuna[6] = 0x00;
+		if (state->dst_hw_cap & DST_TYPE_HAS_ANALOG)
+			state->tx_tuna[7] = 0x00;	/*	Digital	*/
+	} else
+		return -EINVAL;
+
+	return 0;
+}
+
+static int dst_set_bandwidth(struct dst_state *state, u32 bandwidth)
+{
+	state->bandwidth = bandwidth;
+
+	if (state->dst_type != DST_TYPE_IS_TERR)
+		return -EOPNOTSUPP;
+
+	switch (bandwidth) {
+	case 6000000:
+		if (state->dst_hw_cap & DST_TYPE_HAS_CA)
+			state->tx_tuna[7] = 0x06;
+		else {
+			state->tx_tuna[6] = 0x06;
+			state->tx_tuna[7] = 0x00;
+		}
+		break;
+	case 7000000:
+		if (state->dst_hw_cap & DST_TYPE_HAS_CA)
+			state->tx_tuna[7] = 0x07;
+		else {
+			state->tx_tuna[6] = 0x07;
+			state->tx_tuna[7] = 0x00;
+		}
+		break;
+	case 8000000:
+		if (state->dst_hw_cap & DST_TYPE_HAS_CA)
+			state->tx_tuna[7] = 0x08;
+		else {
+			state->tx_tuna[6] = 0x08;
+			state->tx_tuna[7] = 0x00;
+		}
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int dst_set_inversion(struct dst_state *state, fe_spectral_inversion_t inversion)
+{
+	state->inversion = inversion;
+	switch (inversion) {
+	case INVERSION_OFF:	/*	Inversion = Normal	*/
+		state->tx_tuna[8] &= ~0x80;
+		break;
+	case INVERSION_ON:
+		state->tx_tuna[8] |= 0x80;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int dst_set_fec(struct dst_state *state, fe_code_rate_t fec)
+{
+	state->fec = fec;
+	return 0;
+}
+
+static fe_code_rate_t dst_get_fec(struct dst_state *state)
+{
+	return state->fec;
+}
+
+static int dst_set_symbolrate(struct dst_state *state, u32 srate)
+{
+	u32 symcalc;
+	u64 sval;
+
+	state->symbol_rate = srate;
+	if (state->dst_type == DST_TYPE_IS_TERR) {
+		return -EOPNOTSUPP;
+	}
+	dprintk(verbose, DST_INFO, 1, "set symrate %u", srate);
+	srate /= 1000;
+	if (state->dst_type == DST_TYPE_IS_SAT) {
+		if (state->type_flags & DST_TYPE_HAS_SYMDIV) {
+			sval = srate;
+			sval <<= 20;
+			do_div(sval, 88000);
+			symcalc = (u32) sval;
+			dprintk(verbose, DST_INFO, 1, "set symcalc %u", symcalc);
+			state->tx_tuna[5] = (u8) (symcalc >> 12);
+			state->tx_tuna[6] = (u8) (symcalc >> 4);
+			state->tx_tuna[7] = (u8) (symcalc << 4);
+		} else {
+			state->tx_tuna[5] = (u8) (srate >> 16) & 0x7f;
+			state->tx_tuna[6] = (u8) (srate >> 8);
+			state->tx_tuna[7] = (u8) srate;
+		}
+		state->tx_tuna[8] &= ~0x20;
+		if (state->type_flags & DST_TYPE_HAS_OBS_REGS) {
+			if (srate > 8000)
+				state->tx_tuna[8] |= 0x20;
+		}
+	} else if (state->dst_type == DST_TYPE_IS_CABLE) {
+		dprintk(verbose, DST_DEBUG, 1, "%s", state->fw_name);
+		if (!strncmp(state->fw_name, "DCTNEW", 6)) {
+			state->tx_tuna[5] = (u8) (srate >> 8);
+			state->tx_tuna[6] = (u8) srate;
+			state->tx_tuna[7] = 0x00;
+		} else if (!strncmp(state->fw_name, "DCT-CI", 6)) {
+			state->tx_tuna[5] = 0x00;
+			state->tx_tuna[6] = (u8) (srate >> 8);
+			state->tx_tuna[7] = (u8) srate;
+		}
+	}
+	return 0;
+}
+
+static int dst_set_modulation(struct dst_state *state, fe_modulation_t modulation)
+{
+	if (state->dst_type != DST_TYPE_IS_CABLE)
+		return -EOPNOTSUPP;
+
+	state->modulation = modulation;
+	switch (modulation) {
+	case QAM_16:
+		state->tx_tuna[8] = 0x10;
+		break;
+	case QAM_32:
+		state->tx_tuna[8] = 0x20;
+		break;
+	case QAM_64:
+		state->tx_tuna[8] = 0x40;
+		break;
+	case QAM_128:
+		state->tx_tuna[8] = 0x80;
+		break;
+	case QAM_256:
+		if (!strncmp(state->fw_name, "DCTNEW", 6))
+			state->tx_tuna[8] = 0xff;
+		else if (!strncmp(state->fw_name, "DCT-CI", 6))
+			state->tx_tuna[8] = 0x00;
+		break;
+	case QPSK:
+	case QAM_AUTO:
+	case VSB_8:
+	case VSB_16:
+	default:
+		return -EINVAL;
+
+	}
+
+	return 0;
+}
+
+static fe_modulation_t dst_get_modulation(struct dst_state *state)
+{
+	return state->modulation;
+}
+
+
+u8 dst_check_sum(u8 *buf, u32 len)
+{
+	u32 i;
+	u8 val = 0;
+	if (!len)
+		return 0;
+	for (i = 0; i < len; i++) {
+		val += buf[i];
+	}
+	return ((~val) + 1);
+}
+EXPORT_SYMBOL(dst_check_sum);
+
+static void dst_type_flags_print(struct dst_state *state)
+{
+	u32 type_flags = state->type_flags;
+
+	dprintk(verbose, DST_ERROR, 0, "DST type flags :");
+	if (type_flags & DST_TYPE_HAS_TS188)
+		dprintk(verbose, DST_ERROR, 0, " 0x%x newtuner", DST_TYPE_HAS_TS188);
+	if (type_flags & DST_TYPE_HAS_NEWTUNE_2)
+		dprintk(verbose, DST_ERROR, 0, " 0x%x newtuner 2", DST_TYPE_HAS_NEWTUNE_2);
+	if (type_flags & DST_TYPE_HAS_TS204)
+		dprintk(verbose, DST_ERROR, 0, " 0x%x ts204", DST_TYPE_HAS_TS204);
+	if (type_flags & DST_TYPE_HAS_VLF)
+		dprintk(verbose, DST_ERROR, 0, " 0x%x VLF", DST_TYPE_HAS_VLF);
+	if (type_flags & DST_TYPE_HAS_SYMDIV)
+		dprintk(verbose, DST_ERROR, 0, " 0x%x symdiv", DST_TYPE_HAS_SYMDIV);
+	if (type_flags & DST_TYPE_HAS_FW_1)
+		dprintk(verbose, DST_ERROR, 0, " 0x%x firmware version = 1", DST_TYPE_HAS_FW_1);
+	if (type_flags & DST_TYPE_HAS_FW_2)
+		dprintk(verbose, DST_ERROR, 0, " 0x%x firmware version = 2", DST_TYPE_HAS_FW_2);
+	if (type_flags & DST_TYPE_HAS_FW_3)
+		dprintk(verbose, DST_ERROR, 0, " 0x%x firmware version = 3", DST_TYPE_HAS_FW_3);
+	dprintk(verbose, DST_ERROR, 0, "\n");
+}
+
+
+static int dst_type_print(struct dst_state *state, u8 type)
+{
+	char *otype;
+	switch (type) {
+	case DST_TYPE_IS_SAT:
+		otype = "satellite";
+		break;
+
+	case DST_TYPE_IS_TERR:
+		otype = "terrestrial";
+		break;
+
+	case DST_TYPE_IS_CABLE:
+		otype = "cable";
+		break;
+
+	case DST_TYPE_IS_ATSC:
+		otype = "atsc";
+		break;
+
+	default:
+		dprintk(verbose, DST_INFO, 1, "invalid dst type %d", type);
+		return -EINVAL;
+	}
+	dprintk(verbose, DST_INFO, 1, "DST type: %s", otype);
+
+	return 0;
+}
+
+static struct tuner_types tuner_list[] = {
+	{
+		.tuner_type = TUNER_TYPE_L64724,
+		.tuner_name = "L 64724",
+		.board_name = "UNKNOWN",
+		.fw_name    = "UNKNOWN"
+	},
+
+	{
+		.tuner_type = TUNER_TYPE_STV0299,
+		.tuner_name = "STV 0299",
+		.board_name = "VP1020",
+		.fw_name    = "DST-MOT"
+	},
+
+	{
+		.tuner_type = TUNER_TYPE_STV0299,
+		.tuner_name = "STV 0299",
+		.board_name = "VP1020",
+		.fw_name    = "DST-03T"
+	},
+
+	{
+		.tuner_type = TUNER_TYPE_MB86A15,
+		.tuner_name = "MB 86A15",
+		.board_name = "VP1022",
+		.fw_name    = "DST-03T"
+	},
+
+	{
+		.tuner_type = TUNER_TYPE_MB86A15,
+		.tuner_name = "MB 86A15",
+		.board_name = "VP1025",
+		.fw_name    = "DST-03T"
+	},
+
+	{
+		.tuner_type = TUNER_TYPE_STV0299,
+		.tuner_name = "STV 0299",
+		.board_name = "VP1030",
+		.fw_name    = "DST-CI"
+	},
+
+	{
+		.tuner_type = TUNER_TYPE_STV0299,
+		.tuner_name = "STV 0299",
+		.board_name = "VP1030",
+		.fw_name    = "DSTMCI"
+	},
+
+	{
+		.tuner_type = TUNER_TYPE_UNKNOWN,
+		.tuner_name = "UNKNOWN",
+		.board_name = "VP2021",
+		.fw_name    = "DCTNEW"
+	},
+
+	{
+		.tuner_type = TUNER_TYPE_UNKNOWN,
+		.tuner_name = "UNKNOWN",
+		.board_name = "VP2030",
+		.fw_name    = "DCT-CI"
+	},
+
+	{
+		.tuner_type = TUNER_TYPE_UNKNOWN,
+		.tuner_name = "UNKNOWN",
+		.board_name = "VP2031",
+		.fw_name    = "DCT-CI"
+	},
+
+	{
+		.tuner_type = TUNER_TYPE_UNKNOWN,
+		.tuner_name = "UNKNOWN",
+		.board_name = "VP2040",
+		.fw_name    = "DCT-CI"
+	},
+
+	{
+		.tuner_type = TUNER_TYPE_UNKNOWN,
+		.tuner_name = "UNKNOWN",
+		.board_name = "VP3020",
+		.fw_name    = "DTTFTA"
+	},
+
+	{
+		.tuner_type = TUNER_TYPE_UNKNOWN,
+		.tuner_name = "UNKNOWN",
+		.board_name = "VP3021",
+		.fw_name    = "DTTFTA"
+	},
+
+	{
+		.tuner_type = TUNER_TYPE_TDA10046,
+		.tuner_name = "TDA10046",
+		.board_name = "VP3040",
+		.fw_name    = "DTT-CI"
+	},
+
+	{
+		.tuner_type = TUNER_TYPE_UNKNOWN,
+		.tuner_name = "UNKNOWN",
+		.board_name = "VP3051",
+		.fw_name    = "DTTNXT"
+	},
+
+	{
+		.tuner_type = TUNER_TYPE_NXT200x,
+		.tuner_name = "NXT200x",
+		.board_name = "VP3220",
+		.fw_name    = "ATSCDI"
+	},
+
+	{
+		.tuner_type = TUNER_TYPE_NXT200x,
+		.tuner_name = "NXT200x",
+		.board_name = "VP3250",
+		.fw_name    = "ATSCAD"
+	},
+};
+
+/*
+	Known cards list
+	Satellite
+	-------------------
+		  200103A
+	VP-1020   DST-MOT	LG(old), TS=188
+
+	VP-1020   DST-03T	LG(new), TS=204
+	VP-1022   DST-03T	LG(new), TS=204
+	VP-1025   DST-03T	LG(new), TS=204
+
+	VP-1030   DSTMCI,	LG(new), TS=188
+	VP-1032   DSTMCI,	LG(new), TS=188
+
+	Cable
+	-------------------
+	VP-2030   DCT-CI,	Samsung, TS=204
+	VP-2021   DCT-CI,	Unknown, TS=204
+	VP-2031   DCT-CI,	Philips, TS=188
+	VP-2040   DCT-CI,	Philips, TS=188, with CA daughter board
+	VP-2040   DCT-CI,	Philips, TS=204, without CA daughter board
+
+	Terrestrial
+	-------------------
+	VP-3050  DTTNXT			 TS=188
+	VP-3040  DTT-CI,	Philips, TS=188
+	VP-3040  DTT-CI,	Philips, TS=204
+
+	ATSC
+	-------------------
+	VP-3220  ATSCDI,		 TS=188
+	VP-3250  ATSCAD,		 TS=188
+
+*/
+
+static struct dst_types dst_tlist[] = {
+	{
+		.device_id = "200103A",
+		.offset = 0,
+		.dst_type =  DST_TYPE_IS_SAT,
+		.type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_FW_1 | DST_TYPE_HAS_OBS_REGS,
+		.dst_feature = 0,
+		.tuner_type = 0
+	},	/*	obsolete	*/
+
+	{
+		.device_id = "DST-020",
+		.offset = 0,
+		.dst_type =  DST_TYPE_IS_SAT,
+		.type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_FW_1,
+		.dst_feature = 0,
+		.tuner_type = 0
+	},	/*	obsolete	*/
+
+	{
+		.device_id = "DST-030",
+		.offset =  0,
+		.dst_type = DST_TYPE_IS_SAT,
+		.type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_TS188 | DST_TYPE_HAS_FW_1,
+		.dst_feature = 0,
+		.tuner_type = 0
+	},	/*	obsolete	*/
+
+	{
+		.device_id = "DST-03T",
+		.offset = 0,
+		.dst_type = DST_TYPE_IS_SAT,
+		.type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_TS204 | DST_TYPE_HAS_FW_2,
+		.dst_feature = DST_TYPE_HAS_DISEQC3 | DST_TYPE_HAS_DISEQC4 | DST_TYPE_HAS_DISEQC5
+							 | DST_TYPE_HAS_MAC | DST_TYPE_HAS_MOTO,
+		.tuner_type = TUNER_TYPE_MULTI
+	 },
+
+	{
+		.device_id = "DST-MOT",
+		.offset =  0,
+		.dst_type = DST_TYPE_IS_SAT,
+		.type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_FW_1,
+		.dst_feature = 0,
+		.tuner_type = 0
+	},	/*	obsolete	*/
+
+	{
+		.device_id = "DST-CI",
+		.offset = 1,
+		.dst_type = DST_TYPE_IS_SAT,
+		.type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_FW_1,
+		.dst_feature = DST_TYPE_HAS_CA,
+		.tuner_type = 0
+	},	/*	An OEM board	*/
+
+	{
+		.device_id = "DSTMCI",
+		.offset = 1,
+		.dst_type = DST_TYPE_IS_SAT,
+		.type_flags = DST_TYPE_HAS_TS188 | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_FW_BUILD | DST_TYPE_HAS_INC_COUNT | DST_TYPE_HAS_VLF,
+		.dst_feature = DST_TYPE_HAS_CA | DST_TYPE_HAS_DISEQC3 | DST_TYPE_HAS_DISEQC4
+							| DST_TYPE_HAS_MOTO | DST_TYPE_HAS_MAC,
+		.tuner_type = TUNER_TYPE_MULTI
+	},
+
+	{
+		.device_id = "DSTFCI",
+		.offset = 1,
+		.dst_type = DST_TYPE_IS_SAT,
+		.type_flags = DST_TYPE_HAS_TS188 | DST_TYPE_HAS_FW_1,
+		.dst_feature = 0,
+		.tuner_type = 0
+	},	/* unknown to vendor	*/
+
+	{
+		.device_id = "DCT-CI",
+		.offset = 1,
+		.dst_type = DST_TYPE_IS_CABLE,
+		.type_flags = DST_TYPE_HAS_MULTI_FE | DST_TYPE_HAS_FW_1	| DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_VLF,
+		.dst_feature = DST_TYPE_HAS_CA,
+		.tuner_type = 0
+	},
+
+	{
+		.device_id = "DCTNEW",
+		.offset = 1,
+		.dst_type = DST_TYPE_IS_CABLE,
+		.type_flags = DST_TYPE_HAS_TS188 | DST_TYPE_HAS_FW_3 | DST_TYPE_HAS_FW_BUILD | DST_TYPE_HAS_MULTI_FE,
+		.dst_feature = 0,
+		.tuner_type = 0
+	},
+
+	{
+		.device_id = "DTT-CI",
+		.offset = 1,
+		.dst_type = DST_TYPE_IS_TERR,
+		.type_flags = DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_MULTI_FE | DST_TYPE_HAS_VLF,
+		.dst_feature = DST_TYPE_HAS_CA,
+		.tuner_type = 0
+	},
+
+	{
+		.device_id = "DTTDIG",
+		.offset = 1,
+		.dst_type = DST_TYPE_IS_TERR,
+		.type_flags = DST_TYPE_HAS_FW_2,
+		.dst_feature = 0,
+		.tuner_type = 0
+	},
+
+	{
+		.device_id = "DTTNXT",
+		.offset = 1,
+		.dst_type = DST_TYPE_IS_TERR,
+		.type_flags = DST_TYPE_HAS_FW_2,
+		.dst_feature = DST_TYPE_HAS_ANALOG,
+		.tuner_type = 0
+	},
+
+	{
+		.device_id = "ATSCDI",
+		.offset = 1,
+		.dst_type = DST_TYPE_IS_ATSC,
+		.type_flags = DST_TYPE_HAS_FW_2,
+		.dst_feature = 0,
+		.tuner_type = 0
+	},
+
+	{
+		.device_id = "ATSCAD",
+		.offset = 1,
+		.dst_type = DST_TYPE_IS_ATSC,
+		.type_flags = DST_TYPE_HAS_MULTI_FE | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_FW_BUILD,
+		.dst_feature = DST_TYPE_HAS_MAC | DST_TYPE_HAS_ANALOG,
+		.tuner_type = 0
+	},
+
+	{ }
+
+};
+
+static int dst_get_mac(struct dst_state *state)
+{
+	u8 get_mac[] = { 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+	get_mac[7] = dst_check_sum(get_mac, 7);
+	if (dst_command(state, get_mac, 8) < 0) {
+		dprintk(verbose, DST_INFO, 1, "Unsupported Command");
+		return -1;
+	}
+	memset(&state->mac_address, '\0', 8);
+	memcpy(&state->mac_address, &state->rxbuffer, 6);
+	dprintk(verbose, DST_ERROR, 1, "MAC Address=[%pM]", state->mac_address);
+
+	return 0;
+}
+
+static int dst_fw_ver(struct dst_state *state)
+{
+	u8 get_ver[] = { 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+	get_ver[7] = dst_check_sum(get_ver, 7);
+	if (dst_command(state, get_ver, 8) < 0) {
+		dprintk(verbose, DST_INFO, 1, "Unsupported Command");
+		return -1;
+	}
+	memcpy(&state->fw_version, &state->rxbuffer, 8);
+	dprintk(verbose, DST_ERROR, 1, "Firmware Ver = %x.%x Build = %02x, on %x:%x, %x-%x-20%02x",
+		state->fw_version[0] >> 4, state->fw_version[0] & 0x0f,
+		state->fw_version[1],
+		state->fw_version[5], state->fw_version[6],
+		state->fw_version[4], state->fw_version[3], state->fw_version[2]);
+
+	return 0;
+}
+
+static int dst_card_type(struct dst_state *state)
+{
+	int j;
+	struct tuner_types *p_tuner_list = NULL;
+
+	u8 get_type[] = { 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+	get_type[7] = dst_check_sum(get_type, 7);
+	if (dst_command(state, get_type, 8) < 0) {
+		dprintk(verbose, DST_INFO, 1, "Unsupported Command");
+		return -1;
+	}
+	memset(&state->card_info, '\0', 8);
+	memcpy(&state->card_info, &state->rxbuffer, 7);
+	dprintk(verbose, DST_ERROR, 1, "Device Model=[%s]", &state->card_info[0]);
+
+	for (j = 0, p_tuner_list = tuner_list; j < ARRAY_SIZE(tuner_list); j++, p_tuner_list++) {
+		if (!strcmp(&state->card_info[0], p_tuner_list->board_name)) {
+			state->tuner_type = p_tuner_list->tuner_type;
+			dprintk(verbose, DST_ERROR, 1, "DST has [%s] tuner, tuner type=[%d]",
+				p_tuner_list->tuner_name, p_tuner_list->tuner_type);
+		}
+	}
+
+	return 0;
+}
+
+static int dst_get_vendor(struct dst_state *state)
+{
+	u8 get_vendor[] = { 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+	get_vendor[7] = dst_check_sum(get_vendor, 7);
+	if (dst_command(state, get_vendor, 8) < 0) {
+		dprintk(verbose, DST_INFO, 1, "Unsupported Command");
+		return -1;
+	}
+	memset(&state->vendor, '\0', 8);
+	memcpy(&state->vendor, &state->rxbuffer, 7);
+	dprintk(verbose, DST_ERROR, 1, "Vendor=[%s]", &state->vendor[0]);
+
+	return 0;
+}
+
+static void debug_dst_buffer(struct dst_state *state)
+{
+	int i;
+
+	if (verbose > 2) {
+		printk("%s: [", __func__);
+		for (i = 0; i < 8; i++)
+			printk(" %02x", state->rxbuffer[i]);
+		printk("]\n");
+	}
+}
+
+static int dst_check_stv0299(struct dst_state *state)
+{
+	u8 check_stv0299[] = { 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+	check_stv0299[7] = dst_check_sum(check_stv0299, 7);
+	if (dst_command(state, check_stv0299, 8) < 0) {
+		dprintk(verbose, DST_ERROR, 1, "Cmd=[0x04] failed");
+		return -1;
+	}
+	debug_dst_buffer(state);
+
+	if (memcmp(&check_stv0299, &state->rxbuffer, 8)) {
+		dprintk(verbose, DST_ERROR, 1, "Found a STV0299 NIM");
+		state->tuner_type = TUNER_TYPE_STV0299;
+		return 0;
+	}
+
+	return -1;
+}
+
+static int dst_check_mb86a15(struct dst_state *state)
+{
+	u8 check_mb86a15[] = { 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+	check_mb86a15[7] = dst_check_sum(check_mb86a15, 7);
+	if (dst_command(state, check_mb86a15, 8) < 0) {
+		dprintk(verbose, DST_ERROR, 1, "Cmd=[0x10], failed");
+		return -1;
+	}
+	debug_dst_buffer(state);
+
+	if (memcmp(&check_mb86a15, &state->rxbuffer, 8) < 0) {
+		dprintk(verbose, DST_ERROR, 1, "Found a MB86A15 NIM");
+		state->tuner_type = TUNER_TYPE_MB86A15;
+		return 0;
+	}
+
+	return -1;
+}
+
+static int dst_get_tuner_info(struct dst_state *state)
+{
+	u8 get_tuner_1[] = { 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+	u8 get_tuner_2[] = { 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+	get_tuner_1[7] = dst_check_sum(get_tuner_1, 7);
+	get_tuner_2[7] = dst_check_sum(get_tuner_2, 7);
+	dprintk(verbose, DST_ERROR, 1, "DST TYpe = MULTI FE");
+	if (state->type_flags & DST_TYPE_HAS_MULTI_FE) {
+		if (dst_command(state, get_tuner_1, 8) < 0) {
+			dprintk(verbose, DST_INFO, 1, "Cmd=[0x13], Unsupported");
+			goto force;
+		}
+	} else {
+		if (dst_command(state, get_tuner_2, 8) < 0) {
+			dprintk(verbose, DST_INFO, 1, "Cmd=[0xb], Unsupported");
+			goto force;
+		}
+	}
+	memcpy(&state->board_info, &state->rxbuffer, 8);
+	if (state->type_flags & DST_TYPE_HAS_MULTI_FE) {
+		dprintk(verbose, DST_ERROR, 1, "DST type has TS=188");
+	}
+	if (state->board_info[0] == 0xbc) {
+		if (state->dst_type != DST_TYPE_IS_ATSC)
+			state->type_flags |= DST_TYPE_HAS_TS188;
+		else
+			state->type_flags |= DST_TYPE_HAS_NEWTUNE_2;
+
+		if (state->board_info[1] == 0x01) {
+			state->dst_hw_cap |= DST_TYPE_HAS_DBOARD;
+			dprintk(verbose, DST_ERROR, 1, "DST has Daughterboard");
+		}
+	}
+
+	return 0;
+force:
+	if (!strncmp(state->fw_name, "DCT-CI", 6)) {
+		state->type_flags |= DST_TYPE_HAS_TS204;
+		dprintk(verbose, DST_ERROR, 1, "Forcing [%s] to TS188", state->fw_name);
+	}
+
+	return -1;
+}
+
+static int dst_get_device_id(struct dst_state *state)
+{
+	u8 reply;
+
+	int i, j;
+	struct dst_types *p_dst_type = NULL;
+	struct tuner_types *p_tuner_list = NULL;
+
+	u8 use_dst_type = 0;
+	u32 use_type_flags = 0;
+
+	static u8 device_type[8] = {0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff};
+
+	state->tuner_type = 0;
+	device_type[7] = dst_check_sum(device_type, 7);
+
+	if (write_dst(state, device_type, FIXED_COMM))
+		return -1;		/*	Write failed		*/
+	if ((dst_pio_disable(state)) < 0)
+		return -1;
+	if (read_dst(state, &reply, GET_ACK))
+		return -1;		/*	Read failure		*/
+	if (reply != ACK) {
+		dprintk(verbose, DST_INFO, 1, "Write not Acknowledged! [Reply=0x%02x]", reply);
+		return -1;		/*	Unack'd write		*/
+	}
+	if (!dst_wait_dst_ready(state, DEVICE_INIT))
+		return -1;		/*	DST not ready yet	*/
+	if (read_dst(state, state->rxbuffer, FIXED_COMM))
+		return -1;
+
+	dst_pio_disable(state);
+	if (state->rxbuffer[7] != dst_check_sum(state->rxbuffer, 7)) {
+		dprintk(verbose, DST_INFO, 1, "Checksum failure!");
+		return -1;		/*	Checksum failure	*/
+	}
+	state->rxbuffer[7] = '\0';
+
+	for (i = 0, p_dst_type = dst_tlist; i < ARRAY_SIZE(dst_tlist); i++, p_dst_type++) {
+		if (!strncmp (&state->rxbuffer[p_dst_type->offset], p_dst_type->device_id, strlen (p_dst_type->device_id))) {
+			use_type_flags = p_dst_type->type_flags;
+			use_dst_type = p_dst_type->dst_type;
+
+			/*	Card capabilities	*/
+			state->dst_hw_cap = p_dst_type->dst_feature;
+			dprintk(verbose, DST_ERROR, 1, "Recognise [%s]", p_dst_type->device_id);
+			strncpy(&state->fw_name[0], p_dst_type->device_id, 6);
+			/*	Multiple tuners		*/
+			if (p_dst_type->tuner_type & TUNER_TYPE_MULTI) {
+				switch (use_dst_type) {
+				case DST_TYPE_IS_SAT:
+					/*	STV0299 check	*/
+					if (dst_check_stv0299(state) < 0) {
+						dprintk(verbose, DST_ERROR, 1, "Unsupported");
+						state->tuner_type = TUNER_TYPE_MB86A15;
+					}
+					break;
+				default:
+					break;
+				}
+				if (dst_check_mb86a15(state) < 0)
+					dprintk(verbose, DST_ERROR, 1, "Unsupported");
+			/*	Single tuner		*/
+			} else {
+				state->tuner_type = p_dst_type->tuner_type;
+			}
+			for (j = 0, p_tuner_list = tuner_list; j < ARRAY_SIZE(tuner_list); j++, p_tuner_list++) {
+				if (!(strncmp(p_dst_type->device_id, p_tuner_list->fw_name, 7)) &&
+					p_tuner_list->tuner_type == state->tuner_type) {
+					dprintk(verbose, DST_ERROR, 1, "[%s] has a [%s]",
+						p_dst_type->device_id, p_tuner_list->tuner_name);
+				}
+			}
+			break;
+		}
+	}
+
+	if (i >= ARRAY_SIZE(dst_tlist)) {
+		dprintk(verbose, DST_ERROR, 1, "Unable to recognize %s or %s", &state->rxbuffer[0], &state->rxbuffer[1]);
+		dprintk(verbose, DST_ERROR, 1, "please email linux-dvb@linuxtv.org with this type in");
+		use_dst_type = DST_TYPE_IS_SAT;
+		use_type_flags = DST_TYPE_HAS_SYMDIV;
+	}
+	dst_type_print(state, use_dst_type);
+	state->type_flags = use_type_flags;
+	state->dst_type = use_dst_type;
+	dst_type_flags_print(state);
+
+	return 0;
+}
+
+static int dst_probe(struct dst_state *state)
+{
+	mutex_init(&state->dst_mutex);
+	if (dst_addons & DST_TYPE_HAS_CA) {
+		if ((rdc_8820_reset(state)) < 0) {
+			dprintk(verbose, DST_ERROR, 1, "RDC 8820 RESET Failed.");
+			return -1;
+		}
+		msleep(4000);
+	} else {
+		msleep(100);
+	}
+	if ((dst_comm_init(state)) < 0) {
+		dprintk(verbose, DST_ERROR, 1, "DST Initialization Failed.");
+		return -1;
+	}
+	msleep(100);
+	if (dst_get_device_id(state) < 0) {
+		dprintk(verbose, DST_ERROR, 1, "unknown device.");
+		return -1;
+	}
+	if (dst_get_mac(state) < 0) {
+		dprintk(verbose, DST_INFO, 1, "MAC: Unsupported command");
+	}
+	if ((state->type_flags & DST_TYPE_HAS_MULTI_FE) || (state->type_flags & DST_TYPE_HAS_FW_BUILD)) {
+		if (dst_get_tuner_info(state) < 0)
+			dprintk(verbose, DST_INFO, 1, "Tuner: Unsupported command");
+	}
+	if (state->type_flags & DST_TYPE_HAS_TS204) {
+		dst_packsize(state, 204);
+	}
+	if (state->type_flags & DST_TYPE_HAS_FW_BUILD) {
+		if (dst_fw_ver(state) < 0) {
+			dprintk(verbose, DST_INFO, 1, "FW: Unsupported command");
+			return 0;
+		}
+		if (dst_card_type(state) < 0) {
+			dprintk(verbose, DST_INFO, 1, "Card: Unsupported command");
+			return 0;
+		}
+		if (dst_get_vendor(state) < 0) {
+			dprintk(verbose, DST_INFO, 1, "Vendor: Unsupported command");
+			return 0;
+		}
+	}
+
+	return 0;
+}
+
+static int dst_command(struct dst_state *state, u8 *data, u8 len)
+{
+	u8 reply;
+
+	mutex_lock(&state->dst_mutex);
+	if ((dst_comm_init(state)) < 0) {
+		dprintk(verbose, DST_NOTICE, 1, "DST Communication Initialization Failed.");
+		goto error;
+	}
+	if (write_dst(state, data, len)) {
+		dprintk(verbose, DST_INFO, 1, "Trying to recover.. ");
+		if ((dst_error_recovery(state)) < 0) {
+			dprintk(verbose, DST_ERROR, 1, "Recovery Failed.");
+			goto error;
+		}
+		goto error;
+	}
+	if ((dst_pio_disable(state)) < 0) {
+		dprintk(verbose, DST_ERROR, 1, "PIO Disable Failed.");
+		goto error;
+	}
+	if (state->type_flags & DST_TYPE_HAS_FW_1)
+		mdelay(3);
+	if (read_dst(state, &reply, GET_ACK)) {
+		dprintk(verbose, DST_DEBUG, 1, "Trying to recover.. ");
+		if ((dst_error_recovery(state)) < 0) {
+			dprintk(verbose, DST_INFO, 1, "Recovery Failed.");
+			goto error;
+		}
+		goto error;
+	}
+	if (reply != ACK) {
+		dprintk(verbose, DST_INFO, 1, "write not acknowledged 0x%02x ", reply);
+		goto error;
+	}
+	if (len >= 2 && data[0] == 0 && (data[1] == 1 || data[1] == 3))
+		goto error;
+	if (state->type_flags & DST_TYPE_HAS_FW_1)
+		mdelay(3);
+	else
+		udelay(2000);
+	if (!dst_wait_dst_ready(state, NO_DELAY))
+		goto error;
+	if (read_dst(state, state->rxbuffer, FIXED_COMM)) {
+		dprintk(verbose, DST_DEBUG, 1, "Trying to recover.. ");
+		if ((dst_error_recovery(state)) < 0) {
+			dprintk(verbose, DST_INFO, 1, "Recovery failed.");
+			goto error;
+		}
+		goto error;
+	}
+	if (state->rxbuffer[7] != dst_check_sum(state->rxbuffer, 7)) {
+		dprintk(verbose, DST_INFO, 1, "checksum failure");
+		goto error;
+	}
+	mutex_unlock(&state->dst_mutex);
+	return 0;
+
+error:
+	mutex_unlock(&state->dst_mutex);
+	return -EIO;
+
+}
+
+static int dst_get_signal(struct dst_state *state)
+{
+	int retval;
+	u8 get_signal[] = { 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb };
+	//dprintk("%s: Getting Signal strength and other parameters\n", __func__);
+	if ((state->diseq_flags & ATTEMPT_TUNE) == 0) {
+		state->decode_lock = state->decode_strength = state->decode_snr = 0;
+		return 0;
+	}
+	if (0 == (state->diseq_flags & HAS_LOCK)) {
+		state->decode_lock = state->decode_strength = state->decode_snr = 0;
+		return 0;
+	}
+	if (time_after_eq(jiffies, state->cur_jiff + (HZ / 5))) {
+		retval = dst_command(state, get_signal, 8);
+		if (retval < 0)
+			return retval;
+		if (state->dst_type == DST_TYPE_IS_SAT) {
+			state->decode_lock = ((state->rxbuffer[6] & 0x10) == 0) ? 1 : 0;
+			state->decode_strength = state->rxbuffer[5] << 8;
+			state->decode_snr = state->rxbuffer[2] << 8 | state->rxbuffer[3];
+		} else if ((state->dst_type == DST_TYPE_IS_TERR) || (state->dst_type == DST_TYPE_IS_CABLE)) {
+			state->decode_lock = (state->rxbuffer[1]) ? 1 : 0;
+			state->decode_strength = state->rxbuffer[4] << 8;
+			state->decode_snr = state->rxbuffer[3] << 8;
+		} else if (state->dst_type == DST_TYPE_IS_ATSC) {
+			state->decode_lock = (state->rxbuffer[6] == 0x00) ? 1 : 0;
+			state->decode_strength = state->rxbuffer[4] << 8;
+			state->decode_snr = state->rxbuffer[2] << 8 | state->rxbuffer[3];
+		}
+		state->cur_jiff = jiffies;
+	}
+	return 0;
+}
+
+static int dst_tone_power_cmd(struct dst_state *state)
+{
+	u8 paket[8] = { 0x00, 0x09, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00 };
+
+	if (state->dst_type != DST_TYPE_IS_SAT)
+		return -EOPNOTSUPP;
+	paket[4] = state->tx_tuna[4];
+	paket[2] = state->tx_tuna[2];
+	paket[3] = state->tx_tuna[3];
+	paket[7] = dst_check_sum (paket, 7);
+	return dst_command(state, paket, 8);
+}
+
+static int dst_get_tuna(struct dst_state *state)
+{
+	int retval;
+
+	if ((state->diseq_flags & ATTEMPT_TUNE) == 0)
+		return 0;
+	state->diseq_flags &= ~(HAS_LOCK);
+	if (!dst_wait_dst_ready(state, NO_DELAY))
+		return -EIO;
+	if ((state->type_flags & DST_TYPE_HAS_VLF) &&
+		!(state->dst_type == DST_TYPE_IS_ATSC))
+
+		retval = read_dst(state, state->rx_tuna, 10);
+	else
+		retval = read_dst(state, &state->rx_tuna[2], FIXED_COMM);
+	if (retval < 0) {
+		dprintk(verbose, DST_DEBUG, 1, "read not successful");
+		return retval;
+	}
+	if ((state->type_flags & DST_TYPE_HAS_VLF) &&
+	   !(state->dst_type == DST_TYPE_IS_ATSC)) {
+
+		if (state->rx_tuna[9] != dst_check_sum(&state->rx_tuna[0], 9)) {
+			dprintk(verbose, DST_INFO, 1, "checksum failure ? ");
+			return -EIO;
+		}
+	} else {
+		if (state->rx_tuna[9] != dst_check_sum(&state->rx_tuna[2], 7)) {
+			dprintk(verbose, DST_INFO, 1, "checksum failure? ");
+			return -EIO;
+		}
+	}
+	if (state->rx_tuna[2] == 0 && state->rx_tuna[3] == 0)
+		return 0;
+	if (state->dst_type == DST_TYPE_IS_SAT) {
+		state->decode_freq = ((state->rx_tuna[2] & 0x7f) << 8) + state->rx_tuna[3];
+	} else {
+		state->decode_freq = ((state->rx_tuna[2] & 0x7f) << 16) + (state->rx_tuna[3] << 8) + state->rx_tuna[4];
+	}
+	state->decode_freq = state->decode_freq * 1000;
+	state->decode_lock = 1;
+	state->diseq_flags |= HAS_LOCK;
+
+	return 1;
+}
+
+static int dst_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage);
+
+static int dst_write_tuna(struct dvb_frontend *fe)
+{
+	struct dst_state *state = fe->demodulator_priv;
+	int retval;
+	u8 reply;
+
+	dprintk(verbose, DST_INFO, 1, "type_flags 0x%x ", state->type_flags);
+	state->decode_freq = 0;
+	state->decode_lock = state->decode_strength = state->decode_snr = 0;
+	if (state->dst_type == DST_TYPE_IS_SAT) {
+		if (!(state->diseq_flags & HAS_POWER))
+			dst_set_voltage(fe, SEC_VOLTAGE_13);
+	}
+	state->diseq_flags &= ~(HAS_LOCK | ATTEMPT_TUNE);
+	mutex_lock(&state->dst_mutex);
+	if ((dst_comm_init(state)) < 0) {
+		dprintk(verbose, DST_DEBUG, 1, "DST Communication initialization failed.");
+		goto error;
+	}
+//	if (state->type_flags & DST_TYPE_HAS_NEWTUNE) {
+	if ((state->type_flags & DST_TYPE_HAS_VLF) &&
+		(!(state->dst_type == DST_TYPE_IS_ATSC))) {
+
+		state->tx_tuna[9] = dst_check_sum(&state->tx_tuna[0], 9);
+		retval = write_dst(state, &state->tx_tuna[0], 10);
+	} else {
+		state->tx_tuna[9] = dst_check_sum(&state->tx_tuna[2], 7);
+		retval = write_dst(state, &state->tx_tuna[2], FIXED_COMM);
+	}
+	if (retval < 0) {
+		dst_pio_disable(state);
+		dprintk(verbose, DST_DEBUG, 1, "write not successful");
+		goto werr;
+	}
+	if ((dst_pio_disable(state)) < 0) {
+		dprintk(verbose, DST_DEBUG, 1, "DST PIO disable failed !");
+		goto error;
+	}
+	if ((read_dst(state, &reply, GET_ACK) < 0)) {
+		dprintk(verbose, DST_DEBUG, 1, "read verify not successful.");
+		goto error;
+	}
+	if (reply != ACK) {
+		dprintk(verbose, DST_DEBUG, 1, "write not acknowledged 0x%02x ", reply);
+		goto error;
+	}
+	state->diseq_flags |= ATTEMPT_TUNE;
+	retval = dst_get_tuna(state);
+werr:
+	mutex_unlock(&state->dst_mutex);
+	return retval;
+
+error:
+	mutex_unlock(&state->dst_mutex);
+	return -EIO;
+}
+
+/*
+ * line22k0    0x00, 0x09, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00
+ * line22k1    0x00, 0x09, 0x01, 0xff, 0x01, 0x00, 0x00, 0x00
+ * line22k2    0x00, 0x09, 0x02, 0xff, 0x01, 0x00, 0x00, 0x00
+ * tone        0x00, 0x09, 0xff, 0x00, 0x01, 0x00, 0x00, 0x00
+ * data        0x00, 0x09, 0xff, 0x01, 0x01, 0x00, 0x00, 0x00
+ * power_off   0x00, 0x09, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00
+ * power_on    0x00, 0x09, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00
+ * Diseqc 1    0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf0, 0xec
+ * Diseqc 2    0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf4, 0xe8
+ * Diseqc 3    0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf8, 0xe4
+ * Diseqc 4    0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xfc, 0xe0
+ */
+
+static int dst_set_diseqc(struct dvb_frontend *fe, struct dvb_diseqc_master_cmd *cmd)
+{
+	struct dst_state *state = fe->demodulator_priv;
+	u8 paket[8] = { 0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf0, 0xec };
+
+	if (state->dst_type != DST_TYPE_IS_SAT)
+		return -EOPNOTSUPP;
+	if (cmd->msg_len > 0 && cmd->msg_len < 5)
+		memcpy(&paket[3], cmd->msg, cmd->msg_len);
+	else if (cmd->msg_len == 5 && state->dst_hw_cap & DST_TYPE_HAS_DISEQC5)
+		memcpy(&paket[2], cmd->msg, cmd->msg_len);
+	else
+		return -EINVAL;
+	paket[7] = dst_check_sum(&paket[0], 7);
+	return dst_command(state, paket, 8);
+}
+
+static int dst_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+{
+	int need_cmd, retval = 0;
+	struct dst_state *state = fe->demodulator_priv;
+
+	state->voltage = voltage;
+	if (state->dst_type != DST_TYPE_IS_SAT)
+		return -EOPNOTSUPP;
+
+	need_cmd = 0;
+
+	switch (voltage) {
+	case SEC_VOLTAGE_13:
+	case SEC_VOLTAGE_18:
+		if ((state->diseq_flags & HAS_POWER) == 0)
+			need_cmd = 1;
+		state->diseq_flags |= HAS_POWER;
+		state->tx_tuna[4] = 0x01;
+		break;
+	case SEC_VOLTAGE_OFF:
+		need_cmd = 1;
+		state->diseq_flags &= ~(HAS_POWER | HAS_LOCK | ATTEMPT_TUNE);
+		state->tx_tuna[4] = 0x00;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (need_cmd)
+		retval = dst_tone_power_cmd(state);
+
+	return retval;
+}
+
+static int dst_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
+{
+	struct dst_state *state = fe->demodulator_priv;
+
+	state->tone = tone;
+	if (state->dst_type != DST_TYPE_IS_SAT)
+		return -EOPNOTSUPP;
+
+	switch (tone) {
+	case SEC_TONE_OFF:
+		if (state->type_flags & DST_TYPE_HAS_OBS_REGS)
+		    state->tx_tuna[2] = 0x00;
+		else
+		    state->tx_tuna[2] = 0xff;
+		break;
+
+	case SEC_TONE_ON:
+		state->tx_tuna[2] = 0x02;
+		break;
+	default:
+		return -EINVAL;
+	}
+	return dst_tone_power_cmd(state);
+}
+
+static int dst_send_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t minicmd)
+{
+	struct dst_state *state = fe->demodulator_priv;
+
+	if (state->dst_type != DST_TYPE_IS_SAT)
+		return -EOPNOTSUPP;
+	state->minicmd = minicmd;
+	switch (minicmd) {
+	case SEC_MINI_A:
+		state->tx_tuna[3] = 0x02;
+		break;
+	case SEC_MINI_B:
+		state->tx_tuna[3] = 0xff;
+		break;
+	}
+	return dst_tone_power_cmd(state);
+}
+
+
+static int dst_init(struct dvb_frontend *fe)
+{
+	struct dst_state *state = fe->demodulator_priv;
+
+	static u8 sat_tuna_188[] = { 0x09, 0x00, 0x03, 0xb6, 0x01, 0x00, 0x73, 0x21, 0x00, 0x00 };
+	static u8 sat_tuna_204[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x55, 0xbd, 0x50, 0x00, 0x00 };
+	static u8 ter_tuna_188[] = { 0x09, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
+	static u8 ter_tuna_204[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
+	static u8 cab_tuna_188[] = { 0x09, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
+	static u8 cab_tuna_204[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
+	static u8 atsc_tuner[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
+
+	state->inversion = INVERSION_OFF;
+	state->voltage = SEC_VOLTAGE_13;
+	state->tone = SEC_TONE_OFF;
+	state->diseq_flags = 0;
+	state->k22 = 0x02;
+	state->bandwidth = 7000000;
+	state->cur_jiff = jiffies;
+	if (state->dst_type == DST_TYPE_IS_SAT)
+		memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_VLF) ? sat_tuna_188 : sat_tuna_204), sizeof (sat_tuna_204));
+	else if (state->dst_type == DST_TYPE_IS_TERR)
+		memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_VLF) ? ter_tuna_188 : ter_tuna_204), sizeof (ter_tuna_204));
+	else if (state->dst_type == DST_TYPE_IS_CABLE)
+		memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_VLF) ? cab_tuna_188 : cab_tuna_204), sizeof (cab_tuna_204));
+	else if (state->dst_type == DST_TYPE_IS_ATSC)
+		memcpy(state->tx_tuna, atsc_tuner, sizeof (atsc_tuner));
+
+	return 0;
+}
+
+static int dst_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+	struct dst_state *state = fe->demodulator_priv;
+
+	*status = 0;
+	if (state->diseq_flags & HAS_LOCK) {
+//		dst_get_signal(state);	// don't require(?) to ask MCU
+		if (state->decode_lock)
+			*status |= FE_HAS_LOCK | FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_SYNC | FE_HAS_VITERBI;
+	}
+
+	return 0;
+}
+
+static int dst_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
+{
+	struct dst_state *state = fe->demodulator_priv;
+
+	int retval = dst_get_signal(state);
+	*strength = state->decode_strength;
+
+	return retval;
+}
+
+static int dst_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+	struct dst_state *state = fe->demodulator_priv;
+
+	int retval = dst_get_signal(state);
+	*snr = state->decode_snr;
+
+	return retval;
+}
+
+static int dst_set_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	int retval = -EINVAL;
+	struct dst_state *state = fe->demodulator_priv;
+
+	if (p != NULL) {
+		retval = dst_set_freq(state, p->frequency);
+		if(retval != 0)
+			return retval;
+		dprintk(verbose, DST_DEBUG, 1, "Set Frequency=[%d]", p->frequency);
+
+		if (state->dst_type == DST_TYPE_IS_SAT) {
+			if (state->type_flags & DST_TYPE_HAS_OBS_REGS)
+				dst_set_inversion(state, p->inversion);
+			dst_set_fec(state, p->fec_inner);
+			dst_set_symbolrate(state, p->symbol_rate);
+			dst_set_polarization(state);
+			dprintk(verbose, DST_DEBUG, 1, "Set Symbolrate=[%d]", p->symbol_rate);
+
+		} else if (state->dst_type == DST_TYPE_IS_TERR)
+			dst_set_bandwidth(state, p->bandwidth_hz);
+		else if (state->dst_type == DST_TYPE_IS_CABLE) {
+			dst_set_fec(state, p->fec_inner);
+			dst_set_symbolrate(state, p->symbol_rate);
+			dst_set_modulation(state, p->modulation);
+		}
+		retval = dst_write_tuna(fe);
+	}
+
+	return retval;
+}
+
+static int dst_tune_frontend(struct dvb_frontend* fe,
+			    bool re_tune,
+			    unsigned int mode_flags,
+			    unsigned int *delay,
+			    fe_status_t *status)
+{
+	struct dst_state *state = fe->demodulator_priv;
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+
+	if (re_tune) {
+		dst_set_freq(state, p->frequency);
+		dprintk(verbose, DST_DEBUG, 1, "Set Frequency=[%d]", p->frequency);
+
+		if (state->dst_type == DST_TYPE_IS_SAT) {
+			if (state->type_flags & DST_TYPE_HAS_OBS_REGS)
+				dst_set_inversion(state, p->inversion);
+			dst_set_fec(state, p->fec_inner);
+			dst_set_symbolrate(state, p->symbol_rate);
+			dst_set_polarization(state);
+			dprintk(verbose, DST_DEBUG, 1, "Set Symbolrate=[%d]", p->symbol_rate);
+
+		} else if (state->dst_type == DST_TYPE_IS_TERR)
+			dst_set_bandwidth(state, p->bandwidth_hz);
+		else if (state->dst_type == DST_TYPE_IS_CABLE) {
+			dst_set_fec(state, p->fec_inner);
+			dst_set_symbolrate(state, p->symbol_rate);
+			dst_set_modulation(state, p->modulation);
+		}
+		dst_write_tuna(fe);
+	}
+
+	if (!(mode_flags & FE_TUNE_MODE_ONESHOT))
+		dst_read_status(fe, status);
+
+	*delay = HZ/10;
+	return 0;
+}
+
+static int dst_get_tuning_algo(struct dvb_frontend *fe)
+{
+	return dst_algo ? DVBFE_ALGO_HW : DVBFE_ALGO_SW;
+}
+
+static int dst_get_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct dst_state *state = fe->demodulator_priv;
+
+	p->frequency = state->decode_freq;
+	if (state->dst_type == DST_TYPE_IS_SAT) {
+		if (state->type_flags & DST_TYPE_HAS_OBS_REGS)
+			p->inversion = state->inversion;
+		p->symbol_rate = state->symbol_rate;
+		p->fec_inner = dst_get_fec(state);
+	} else if (state->dst_type == DST_TYPE_IS_TERR) {
+		p->bandwidth_hz = state->bandwidth;
+	} else if (state->dst_type == DST_TYPE_IS_CABLE) {
+		p->symbol_rate = state->symbol_rate;
+		p->fec_inner = dst_get_fec(state);
+		p->modulation = dst_get_modulation(state);
+	}
+
+	return 0;
+}
+
+static void dst_release(struct dvb_frontend *fe)
+{
+	struct dst_state *state = fe->demodulator_priv;
+	if (state->dst_ca) {
+		dvb_unregister_device(state->dst_ca);
+#ifdef CONFIG_MEDIA_ATTACH
+		symbol_put(dst_ca_attach);
+#endif
+	}
+	kfree(state);
+}
+
+static struct dvb_frontend_ops dst_dvbt_ops;
+static struct dvb_frontend_ops dst_dvbs_ops;
+static struct dvb_frontend_ops dst_dvbc_ops;
+static struct dvb_frontend_ops dst_atsc_ops;
+
+struct dst_state *dst_attach(struct dst_state *state, struct dvb_adapter *dvb_adapter)
+{
+	/* check if the ASIC is there */
+	if (dst_probe(state) < 0) {
+		kfree(state);
+		return NULL;
+	}
+	/* determine settings based on type */
+	/* create dvb_frontend */
+	switch (state->dst_type) {
+	case DST_TYPE_IS_TERR:
+		memcpy(&state->frontend.ops, &dst_dvbt_ops, sizeof(struct dvb_frontend_ops));
+		break;
+	case DST_TYPE_IS_CABLE:
+		memcpy(&state->frontend.ops, &dst_dvbc_ops, sizeof(struct dvb_frontend_ops));
+		break;
+	case DST_TYPE_IS_SAT:
+		memcpy(&state->frontend.ops, &dst_dvbs_ops, sizeof(struct dvb_frontend_ops));
+		break;
+	case DST_TYPE_IS_ATSC:
+		memcpy(&state->frontend.ops, &dst_atsc_ops, sizeof(struct dvb_frontend_ops));
+		break;
+	default:
+		dprintk(verbose, DST_ERROR, 1, "unknown DST type. please report to the LinuxTV.org DVB mailinglist.");
+		kfree(state);
+		return NULL;
+	}
+	state->frontend.demodulator_priv = state;
+
+	return state;				/*	Manu (DST is a card not a frontend)	*/
+}
+
+EXPORT_SYMBOL(dst_attach);
+
+static struct dvb_frontend_ops dst_dvbt_ops = {
+	.delsys = { SYS_DVBT },
+	.info = {
+		.name = "DST DVB-T",
+		.frequency_min = 137000000,
+		.frequency_max = 858000000,
+		.frequency_stepsize = 166667,
+		.caps = FE_CAN_FEC_AUTO			|
+			FE_CAN_QAM_AUTO			|
+			FE_CAN_QAM_16			|
+			FE_CAN_QAM_32			|
+			FE_CAN_QAM_64			|
+			FE_CAN_QAM_128			|
+			FE_CAN_QAM_256			|
+			FE_CAN_TRANSMISSION_MODE_AUTO	|
+			FE_CAN_GUARD_INTERVAL_AUTO
+	},
+
+	.release = dst_release,
+	.init = dst_init,
+	.tune = dst_tune_frontend,
+	.set_frontend = dst_set_frontend,
+	.get_frontend = dst_get_frontend,
+	.get_frontend_algo = dst_get_tuning_algo,
+	.read_status = dst_read_status,
+	.read_signal_strength = dst_read_signal_strength,
+	.read_snr = dst_read_snr,
+};
+
+static struct dvb_frontend_ops dst_dvbs_ops = {
+	.delsys = { SYS_DVBS },
+	.info = {
+		.name = "DST DVB-S",
+		.frequency_min = 950000,
+		.frequency_max = 2150000,
+		.frequency_stepsize = 1000,	/* kHz for QPSK frontends */
+		.frequency_tolerance = 29500,
+		.symbol_rate_min = 1000000,
+		.symbol_rate_max = 45000000,
+	/*     . symbol_rate_tolerance	=	???,*/
+		.caps = FE_CAN_FEC_AUTO | FE_CAN_QPSK
+	},
+
+	.release = dst_release,
+	.init = dst_init,
+	.tune = dst_tune_frontend,
+	.set_frontend = dst_set_frontend,
+	.get_frontend = dst_get_frontend,
+	.get_frontend_algo = dst_get_tuning_algo,
+	.read_status = dst_read_status,
+	.read_signal_strength = dst_read_signal_strength,
+	.read_snr = dst_read_snr,
+	.diseqc_send_burst = dst_send_burst,
+	.diseqc_send_master_cmd = dst_set_diseqc,
+	.set_voltage = dst_set_voltage,
+	.set_tone = dst_set_tone,
+};
+
+static struct dvb_frontend_ops dst_dvbc_ops = {
+	.delsys = { SYS_DVBC_ANNEX_A },
+	.info = {
+		.name = "DST DVB-C",
+		.frequency_stepsize = 62500,
+		.frequency_min = 51000000,
+		.frequency_max = 858000000,
+		.symbol_rate_min = 1000000,
+		.symbol_rate_max = 45000000,
+		.caps = FE_CAN_FEC_AUTO |
+			FE_CAN_QAM_AUTO |
+			FE_CAN_QAM_16	|
+			FE_CAN_QAM_32	|
+			FE_CAN_QAM_64	|
+			FE_CAN_QAM_128	|
+			FE_CAN_QAM_256
+	},
+
+	.release = dst_release,
+	.init = dst_init,
+	.tune = dst_tune_frontend,
+	.set_frontend = dst_set_frontend,
+	.get_frontend = dst_get_frontend,
+	.get_frontend_algo = dst_get_tuning_algo,
+	.read_status = dst_read_status,
+	.read_signal_strength = dst_read_signal_strength,
+	.read_snr = dst_read_snr,
+};
+
+static struct dvb_frontend_ops dst_atsc_ops = {
+	.delsys = { SYS_ATSC },
+	.info = {
+		.name = "DST ATSC",
+		.frequency_stepsize = 62500,
+		.frequency_min = 510000000,
+		.frequency_max = 858000000,
+		.symbol_rate_min = 1000000,
+		.symbol_rate_max = 45000000,
+		.caps = FE_CAN_FEC_AUTO | FE_CAN_QAM_AUTO | FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
+	},
+
+	.release = dst_release,
+	.init = dst_init,
+	.tune = dst_tune_frontend,
+	.set_frontend = dst_set_frontend,
+	.get_frontend = dst_get_frontend,
+	.get_frontend_algo = dst_get_tuning_algo,
+	.read_status = dst_read_status,
+	.read_signal_strength = dst_read_signal_strength,
+	.read_snr = dst_read_snr,
+};
+
+MODULE_DESCRIPTION("DST DVB-S/T/C/ATSC Combo Frontend driver");
+MODULE_AUTHOR("Jamie Honan, Manu Abraham");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/pci/bt8xx/dst_ca.c b/drivers/media/pci/bt8xx/dst_ca.c
new file mode 100644
index 0000000..ee3884f
--- /dev/null
+++ b/drivers/media/pci/bt8xx/dst_ca.c
@@ -0,0 +1,726 @@
+/*
+	CA-driver for TwinHan DST Frontend/Card
+
+	Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.com)
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/mutex.h>
+#include <linux/string.h>
+#include <linux/dvb/ca.h>
+#include "dvbdev.h"
+#include "dvb_frontend.h"
+#include "dst_ca.h"
+#include "dst_common.h"
+
+#define DST_CA_ERROR		0
+#define DST_CA_NOTICE		1
+#define DST_CA_INFO		2
+#define DST_CA_DEBUG		3
+
+#define dprintk(x, y, z, format, arg...) do {						\
+	if (z) {									\
+		if	((x > DST_CA_ERROR) && (x > y))					\
+			printk(KERN_ERR "%s: " format "\n", __func__ , ##arg);	\
+		else if	((x > DST_CA_NOTICE) && (x > y))				\
+			printk(KERN_NOTICE "%s: " format "\n", __func__ , ##arg);	\
+		else if ((x > DST_CA_INFO) && (x > y))					\
+			printk(KERN_INFO "%s: " format "\n", __func__ , ##arg);	\
+		else if ((x > DST_CA_DEBUG) && (x > y))					\
+			printk(KERN_DEBUG "%s: " format "\n", __func__ , ##arg);	\
+	} else {									\
+		if (x > y)								\
+			printk(format, ## arg);						\
+	}										\
+} while(0)
+
+
+static DEFINE_MUTEX(dst_ca_mutex);
+static unsigned int verbose = 5;
+module_param(verbose, int, 0644);
+MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)");
+
+/*	Need some more work	*/
+static int ca_set_slot_descr(void)
+{
+	/*	We could make this more graceful ?	*/
+	return -EOPNOTSUPP;
+}
+
+/*	Need some more work	*/
+static int ca_set_pid(void)
+{
+	/*	We could make this more graceful ?	*/
+	return -EOPNOTSUPP;
+}
+
+static void put_command_and_length(u8 *data, int command, int length)
+{
+	data[0] = (command >> 16) & 0xff;
+	data[1] = (command >> 8) & 0xff;
+	data[2] = command & 0xff;
+	data[3] = length;
+}
+
+static void put_checksum(u8 *check_string, int length)
+{
+	dprintk(verbose, DST_CA_DEBUG, 1, " Computing string checksum.");
+	dprintk(verbose, DST_CA_DEBUG, 1, "  -> string length : 0x%02x", length);
+	check_string[length] = dst_check_sum (check_string, length);
+	dprintk(verbose, DST_CA_DEBUG, 1, "  -> checksum      : 0x%02x", check_string[length]);
+}
+
+static int dst_ci_command(struct dst_state* state, u8 * data, u8 *ca_string, u8 len, int read)
+{
+	u8 reply;
+
+	mutex_lock(&state->dst_mutex);
+	dst_comm_init(state);
+	msleep(65);
+
+	if (write_dst(state, data, len)) {
+		dprintk(verbose, DST_CA_INFO, 1, " Write not successful, trying to recover");
+		dst_error_recovery(state);
+		goto error;
+	}
+	if ((dst_pio_disable(state)) < 0) {
+		dprintk(verbose, DST_CA_ERROR, 1, " DST PIO disable failed.");
+		goto error;
+	}
+	if (read_dst(state, &reply, GET_ACK) < 0) {
+		dprintk(verbose, DST_CA_INFO, 1, " Read not successful, trying to recover");
+		dst_error_recovery(state);
+		goto error;
+	}
+	if (read) {
+		if (! dst_wait_dst_ready(state, LONG_DELAY)) {
+			dprintk(verbose, DST_CA_NOTICE, 1, " 8820 not ready");
+			goto error;
+		}
+		if (read_dst(state, ca_string, 128) < 0) {	/*	Try to make this dynamic	*/
+			dprintk(verbose, DST_CA_INFO, 1, " Read not successful, trying to recover");
+			dst_error_recovery(state);
+			goto error;
+		}
+	}
+	mutex_unlock(&state->dst_mutex);
+	return 0;
+
+error:
+	mutex_unlock(&state->dst_mutex);
+	return -EIO;
+}
+
+
+static int dst_put_ci(struct dst_state *state, u8 *data, int len, u8 *ca_string, int read)
+{
+	u8 dst_ca_comm_err = 0;
+
+	while (dst_ca_comm_err < RETRIES) {
+		dprintk(verbose, DST_CA_NOTICE, 1, " Put Command");
+		if (dst_ci_command(state, data, ca_string, len, read)) {	// If error
+			dst_error_recovery(state);
+			dst_ca_comm_err++; // work required here.
+		} else {
+			break;
+		}
+	}
+
+	if(dst_ca_comm_err == RETRIES)
+		return -1;
+
+	return 0;
+}
+
+
+
+static int ca_get_app_info(struct dst_state *state)
+{
+	int length, str_length;
+	static u8 command[8] = {0x07, 0x40, 0x01, 0x00, 0x01, 0x00, 0x00, 0xff};
+
+	put_checksum(&command[0], command[0]);
+	if ((dst_put_ci(state, command, sizeof(command), state->messages, GET_REPLY)) < 0) {
+		dprintk(verbose, DST_CA_ERROR, 1, " -->dst_put_ci FAILED !");
+		return -1;
+	}
+	dprintk(verbose, DST_CA_INFO, 1, " -->dst_put_ci SUCCESS !");
+	dprintk(verbose, DST_CA_INFO, 1, " ================================ CI Module Application Info ======================================");
+	dprintk(verbose, DST_CA_INFO, 1, " Application Type=[%d], Application Vendor=[%d], Vendor Code=[%d]\n%s: Application info=[%s]",
+		state->messages[7], (state->messages[8] << 8) | state->messages[9],
+		(state->messages[10] << 8) | state->messages[11], __func__, (char *)(&state->messages[12]));
+	dprintk(verbose, DST_CA_INFO, 1, " ==================================================================================================");
+
+	// Transform dst message to correct application_info message
+	length = state->messages[5];
+	str_length = length - 6;
+	if (str_length < 0) {
+		str_length = 0;
+		dprintk(verbose, DST_CA_ERROR, 1, "Invalid string length returned in ca_get_app_info(). Recovering.");
+	}
+
+	// First, the command and length fields
+	put_command_and_length(&state->messages[0], CA_APP_INFO, length);
+
+	// Copy application_type, application_manufacturer and manufacturer_code
+	memcpy(&state->messages[4], &state->messages[7], 5);
+
+	// Set string length and copy string
+	state->messages[9] = str_length;
+	memcpy(&state->messages[10], &state->messages[12], str_length);
+
+	return 0;
+}
+
+static int ca_get_ca_info(struct dst_state *state)
+{
+	int srcPtr, dstPtr, i, num_ids;
+	static u8 slot_command[8] = {0x07, 0x40, 0x00, 0x00, 0x02, 0x00, 0x00, 0xff};
+	const int in_system_id_pos = 8, out_system_id_pos = 4, in_num_ids_pos = 7;
+
+	put_checksum(&slot_command[0], slot_command[0]);
+	if ((dst_put_ci(state, slot_command, sizeof (slot_command), state->messages, GET_REPLY)) < 0) {
+		dprintk(verbose, DST_CA_ERROR, 1, " -->dst_put_ci FAILED !");
+		return -1;
+	}
+	dprintk(verbose, DST_CA_INFO, 1, " -->dst_put_ci SUCCESS !");
+
+	// Print raw data
+	dprintk(verbose, DST_CA_INFO, 0, " DST data = [");
+	for (i = 0; i < state->messages[0] + 1; i++) {
+		dprintk(verbose, DST_CA_INFO, 0, " 0x%02x", state->messages[i]);
+	}
+	dprintk(verbose, DST_CA_INFO, 0, "]\n");
+
+	// Set the command and length of the output
+	num_ids = state->messages[in_num_ids_pos];
+	if (num_ids >= 100) {
+		num_ids = 100;
+		dprintk(verbose, DST_CA_ERROR, 1, "Invalid number of ids (>100). Recovering.");
+	}
+	put_command_and_length(&state->messages[0], CA_INFO, num_ids * 2);
+
+	dprintk(verbose, DST_CA_INFO, 0, " CA_INFO = [");
+	srcPtr = in_system_id_pos;
+	dstPtr = out_system_id_pos;
+	for(i = 0; i < num_ids; i++) {
+		dprintk(verbose, DST_CA_INFO, 0, " 0x%02x%02x", state->messages[srcPtr + 0], state->messages[srcPtr + 1]);
+		// Append to output
+		state->messages[dstPtr + 0] = state->messages[srcPtr + 0];
+		state->messages[dstPtr + 1] = state->messages[srcPtr + 1];
+		srcPtr += 2;
+		dstPtr += 2;
+	}
+	dprintk(verbose, DST_CA_INFO, 0, "]\n");
+
+	return 0;
+}
+
+static int ca_get_slot_caps(struct dst_state *state, struct ca_caps *p_ca_caps, void __user *arg)
+{
+	int i;
+	u8 slot_cap[256];
+	static u8 slot_command[8] = {0x07, 0x40, 0x02, 0x00, 0x02, 0x00, 0x00, 0xff};
+
+	put_checksum(&slot_command[0], slot_command[0]);
+	if ((dst_put_ci(state, slot_command, sizeof (slot_command), slot_cap, GET_REPLY)) < 0) {
+		dprintk(verbose, DST_CA_ERROR, 1, " -->dst_put_ci FAILED !");
+		return -1;
+	}
+	dprintk(verbose, DST_CA_NOTICE, 1, " -->dst_put_ci SUCCESS !");
+
+	/*	Will implement the rest soon		*/
+
+	dprintk(verbose, DST_CA_INFO, 1, " Slot cap = [%d]", slot_cap[7]);
+	dprintk(verbose, DST_CA_INFO, 0, "===================================\n");
+	for (i = 0; i < slot_cap[0] + 1; i++)
+		dprintk(verbose, DST_CA_INFO, 0, " %d", slot_cap[i]);
+	dprintk(verbose, DST_CA_INFO, 0, "\n");
+
+	p_ca_caps->slot_num = 1;
+	p_ca_caps->slot_type = 1;
+	p_ca_caps->descr_num = slot_cap[7];
+	p_ca_caps->descr_type = 1;
+
+	if (copy_to_user(arg, p_ca_caps, sizeof (struct ca_caps)))
+		return -EFAULT;
+
+	return 0;
+}
+
+/*	Need some more work	*/
+static int ca_get_slot_descr(struct dst_state *state, struct ca_msg *p_ca_message, void __user *arg)
+{
+	return -EOPNOTSUPP;
+}
+
+
+static int ca_get_slot_info(struct dst_state *state, struct ca_slot_info *p_ca_slot_info, void __user *arg)
+{
+	int i;
+	static u8 slot_command[8] = {0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff};
+
+	u8 *slot_info = state->messages;
+
+	put_checksum(&slot_command[0], 7);
+	if ((dst_put_ci(state, slot_command, sizeof (slot_command), slot_info, GET_REPLY)) < 0) {
+		dprintk(verbose, DST_CA_ERROR, 1, " -->dst_put_ci FAILED !");
+		return -1;
+	}
+	dprintk(verbose, DST_CA_INFO, 1, " -->dst_put_ci SUCCESS !");
+
+	/*	Will implement the rest soon		*/
+
+	dprintk(verbose, DST_CA_INFO, 1, " Slot info = [%d]", slot_info[3]);
+	dprintk(verbose, DST_CA_INFO, 0, "===================================\n");
+	for (i = 0; i < 8; i++)
+		dprintk(verbose, DST_CA_INFO, 0, " %d", slot_info[i]);
+	dprintk(verbose, DST_CA_INFO, 0, "\n");
+
+	if (slot_info[4] & 0x80) {
+		p_ca_slot_info->flags = CA_CI_MODULE_PRESENT;
+		p_ca_slot_info->num = 1;
+		p_ca_slot_info->type = CA_CI;
+	} else if (slot_info[4] & 0x40) {
+		p_ca_slot_info->flags = CA_CI_MODULE_READY;
+		p_ca_slot_info->num = 1;
+		p_ca_slot_info->type = CA_CI;
+	} else
+		p_ca_slot_info->flags = 0;
+
+	if (copy_to_user(arg, p_ca_slot_info, sizeof (struct ca_slot_info)))
+		return -EFAULT;
+
+	return 0;
+}
+
+
+static int ca_get_message(struct dst_state *state, struct ca_msg *p_ca_message, void __user *arg)
+{
+	u8 i = 0;
+	u32 command = 0;
+
+	if (copy_from_user(p_ca_message, arg, sizeof (struct ca_msg)))
+		return -EFAULT;
+
+	if (p_ca_message->msg) {
+		dprintk(verbose, DST_CA_NOTICE, 1, " Message = [%*ph]",
+			3, p_ca_message->msg);
+
+		for (i = 0; i < 3; i++) {
+			command = command | p_ca_message->msg[i];
+			if (i < 2)
+				command = command << 8;
+		}
+		dprintk(verbose, DST_CA_NOTICE, 1, " Command=[0x%x]", command);
+
+		switch (command) {
+		case CA_APP_INFO:
+			memcpy(p_ca_message->msg, state->messages, 128);
+			if (copy_to_user(arg, p_ca_message, sizeof (struct ca_msg)) )
+				return -EFAULT;
+			break;
+		case CA_INFO:
+			memcpy(p_ca_message->msg, state->messages, 128);
+			if (copy_to_user(arg, p_ca_message, sizeof (struct ca_msg)) )
+				return -EFAULT;
+			break;
+		}
+	}
+
+	return 0;
+}
+
+static int handle_dst_tag(struct dst_state *state, struct ca_msg *p_ca_message, struct ca_msg *hw_buffer, u32 length)
+{
+	if (state->dst_hw_cap & DST_TYPE_HAS_SESSION) {
+		hw_buffer->msg[2] = p_ca_message->msg[1];	/*	MSB	*/
+		hw_buffer->msg[3] = p_ca_message->msg[2];	/*	LSB	*/
+	} else {
+		if (length > 247) {
+			dprintk(verbose, DST_CA_ERROR, 1, " Message too long ! *** Bailing Out *** !");
+			return -1;
+		}
+		hw_buffer->msg[0] = (length & 0xff) + 7;
+		hw_buffer->msg[1] = 0x40;
+		hw_buffer->msg[2] = 0x03;
+		hw_buffer->msg[3] = 0x00;
+		hw_buffer->msg[4] = 0x03;
+		hw_buffer->msg[5] = length & 0xff;
+		hw_buffer->msg[6] = 0x00;
+
+		/*
+		 *	Need to compute length for EN50221 section 8.3.2, for the time being
+		 *	assuming 8.3.2 is not applicable
+		 */
+		memcpy(&hw_buffer->msg[7], &p_ca_message->msg[4], length);
+	}
+
+	return 0;
+}
+
+static int write_to_8820(struct dst_state *state, struct ca_msg *hw_buffer, u8 length, u8 reply)
+{
+	if ((dst_put_ci(state, hw_buffer->msg, length, hw_buffer->msg, reply)) < 0) {
+		dprintk(verbose, DST_CA_ERROR, 1, " DST-CI Command failed.");
+		dprintk(verbose, DST_CA_NOTICE, 1, " Resetting DST.");
+		rdc_reset_state(state);
+		return -1;
+	}
+	dprintk(verbose, DST_CA_NOTICE, 1, " DST-CI Command success.");
+
+	return 0;
+}
+
+static u32 asn_1_decode(u8 *asn_1_array)
+{
+	u8 length_field = 0, word_count = 0, count = 0;
+	u32 length = 0;
+
+	length_field = asn_1_array[0];
+	dprintk(verbose, DST_CA_DEBUG, 1, " Length field=[%02x]", length_field);
+	if (length_field < 0x80) {
+		length = length_field & 0x7f;
+		dprintk(verbose, DST_CA_DEBUG, 1, " Length=[%02x]\n", length);
+	} else {
+		word_count = length_field & 0x7f;
+		for (count = 0; count < word_count; count++) {
+			length = length  << 8;
+			length += asn_1_array[count + 1];
+			dprintk(verbose, DST_CA_DEBUG, 1, " Length=[%04x]", length);
+		}
+	}
+	return length;
+}
+
+static int debug_string(u8 *msg, u32 length, u32 offset)
+{
+	u32 i;
+
+	dprintk(verbose, DST_CA_DEBUG, 0, " String=[ ");
+	for (i = offset; i < length; i++)
+		dprintk(verbose, DST_CA_DEBUG, 0, "%02x ", msg[i]);
+	dprintk(verbose, DST_CA_DEBUG, 0, "]\n");
+
+	return 0;
+}
+
+
+static int ca_set_pmt(struct dst_state *state, struct ca_msg *p_ca_message, struct ca_msg *hw_buffer, u8 reply, u8 query)
+{
+	u32 length = 0;
+	u8 tag_length = 8;
+
+	length = asn_1_decode(&p_ca_message->msg[3]);
+	dprintk(verbose, DST_CA_DEBUG, 1, " CA Message length=[%d]", length);
+	debug_string(&p_ca_message->msg[4], length, 0); /*	length is excluding tag & length	*/
+
+	memset(hw_buffer->msg, '\0', length);
+	handle_dst_tag(state, p_ca_message, hw_buffer, length);
+	put_checksum(hw_buffer->msg, hw_buffer->msg[0]);
+
+	debug_string(hw_buffer->msg, (length + tag_length), 0); /*	tags too	*/
+	write_to_8820(state, hw_buffer, (length + tag_length), reply);
+
+	return 0;
+}
+
+
+/*	Board supports CA PMT reply ?		*/
+static int dst_check_ca_pmt(struct dst_state *state, struct ca_msg *p_ca_message, struct ca_msg *hw_buffer)
+{
+	int ca_pmt_reply_test = 0;
+
+	/*	Do test board			*/
+	/*	Not there yet but soon		*/
+
+	/*	CA PMT Reply capable		*/
+	if (ca_pmt_reply_test) {
+		if ((ca_set_pmt(state, p_ca_message, hw_buffer, 1, GET_REPLY)) < 0) {
+			dprintk(verbose, DST_CA_ERROR, 1, " ca_set_pmt.. failed !");
+			return -1;
+		}
+
+	/*	Process CA PMT Reply		*/
+	/*	will implement soon		*/
+		dprintk(verbose, DST_CA_ERROR, 1, " Not there yet");
+	}
+	/*	CA PMT Reply not capable	*/
+	if (!ca_pmt_reply_test) {
+		if ((ca_set_pmt(state, p_ca_message, hw_buffer, 0, NO_REPLY)) < 0) {
+			dprintk(verbose, DST_CA_ERROR, 1, " ca_set_pmt.. failed !");
+			return -1;
+		}
+		dprintk(verbose, DST_CA_NOTICE, 1, " ca_set_pmt.. success !");
+	/*	put a dummy message		*/
+
+	}
+	return 0;
+}
+
+static int ca_send_message(struct dst_state *state, struct ca_msg *p_ca_message, void __user *arg)
+{
+	int i = 0;
+
+	u32 command = 0;
+	struct ca_msg *hw_buffer;
+	int result = 0;
+
+	if ((hw_buffer = kmalloc(sizeof (struct ca_msg), GFP_KERNEL)) == NULL) {
+		dprintk(verbose, DST_CA_ERROR, 1, " Memory allocation failure");
+		return -ENOMEM;
+	}
+	dprintk(verbose, DST_CA_DEBUG, 1, " ");
+
+	if (copy_from_user(p_ca_message, arg, sizeof (struct ca_msg))) {
+		result = -EFAULT;
+		goto free_mem_and_exit;
+	}
+
+
+	if (p_ca_message->msg) {
+		/*	EN50221 tag	*/
+		command = 0;
+
+		for (i = 0; i < 3; i++) {
+			command = command | p_ca_message->msg[i];
+			if (i < 2)
+				command = command << 8;
+		}
+		dprintk(verbose, DST_CA_DEBUG, 1, " Command=[0x%x]\n", command);
+
+		switch (command) {
+		case CA_PMT:
+			dprintk(verbose, DST_CA_DEBUG, 1, "Command = SEND_CA_PMT");
+			if ((ca_set_pmt(state, p_ca_message, hw_buffer, 0, 0)) < 0) {	// code simplification started
+				dprintk(verbose, DST_CA_ERROR, 1, " -->CA_PMT Failed !");
+				result = -1;
+				goto free_mem_and_exit;
+			}
+			dprintk(verbose, DST_CA_INFO, 1, " -->CA_PMT Success !");
+			break;
+		case CA_PMT_REPLY:
+			dprintk(verbose, DST_CA_INFO, 1, "Command = CA_PMT_REPLY");
+			/*      Have to handle the 2 basic types of cards here  */
+			if ((dst_check_ca_pmt(state, p_ca_message, hw_buffer)) < 0) {
+				dprintk(verbose, DST_CA_ERROR, 1, " -->CA_PMT_REPLY Failed !");
+				result = -1;
+				goto free_mem_and_exit;
+			}
+			dprintk(verbose, DST_CA_INFO, 1, " -->CA_PMT_REPLY Success !");
+			break;
+		case CA_APP_INFO_ENQUIRY:		// only for debugging
+			dprintk(verbose, DST_CA_INFO, 1, " Getting Cam Application information");
+
+			if ((ca_get_app_info(state)) < 0) {
+				dprintk(verbose, DST_CA_ERROR, 1, " -->CA_APP_INFO_ENQUIRY Failed !");
+				result = -1;
+				goto free_mem_and_exit;
+			}
+			dprintk(verbose, DST_CA_INFO, 1, " -->CA_APP_INFO_ENQUIRY Success !");
+			break;
+		case CA_INFO_ENQUIRY:
+			dprintk(verbose, DST_CA_INFO, 1, " Getting CA Information");
+
+			if ((ca_get_ca_info(state)) < 0) {
+				dprintk(verbose, DST_CA_ERROR, 1, " -->CA_INFO_ENQUIRY Failed !");
+				result = -1;
+				goto free_mem_and_exit;
+			}
+			dprintk(verbose, DST_CA_INFO, 1, " -->CA_INFO_ENQUIRY Success !");
+			break;
+		}
+	}
+free_mem_and_exit:
+	kfree (hw_buffer);
+
+	return result;
+}
+
+static long dst_ca_ioctl(struct file *file, unsigned int cmd, unsigned long ioctl_arg)
+{
+	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;
+
+	mutex_lock(&dst_ca_mutex);
+	dvbdev = 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);
+	if (!p_ca_message || !p_ca_slot_info || !p_ca_caps) {
+		dprintk(verbose, DST_CA_ERROR, 1, " Memory allocation failure");
+		result = -ENOMEM;
+		goto free_mem_and_exit;
+	}
+
+	/*	We have now only the standard ioctl's, the driver is upposed to handle internals.	*/
+	switch (cmd) {
+	case CA_SEND_MSG:
+		dprintk(verbose, DST_CA_INFO, 1, " Sending message");
+		if ((ca_send_message(state, p_ca_message, arg)) < 0) {
+			dprintk(verbose, DST_CA_ERROR, 1, " -->CA_SEND_MSG Failed !");
+			result = -1;
+			goto free_mem_and_exit;
+		}
+		break;
+	case CA_GET_MSG:
+		dprintk(verbose, DST_CA_INFO, 1, " Getting message");
+		if ((ca_get_message(state, p_ca_message, arg)) < 0) {
+			dprintk(verbose, DST_CA_ERROR, 1, " -->CA_GET_MSG Failed !");
+			result = -1;
+			goto free_mem_and_exit;
+		}
+		dprintk(verbose, DST_CA_INFO, 1, " -->CA_GET_MSG Success !");
+		break;
+	case CA_RESET:
+		dprintk(verbose, DST_CA_ERROR, 1, " Resetting DST");
+		dst_error_bailout(state);
+		msleep(4000);
+		break;
+	case CA_GET_SLOT_INFO:
+		dprintk(verbose, DST_CA_INFO, 1, " Getting Slot info");
+		if ((ca_get_slot_info(state, p_ca_slot_info, arg)) < 0) {
+			dprintk(verbose, DST_CA_ERROR, 1, " -->CA_GET_SLOT_INFO Failed !");
+			result = -1;
+			goto free_mem_and_exit;
+		}
+		dprintk(verbose, DST_CA_INFO, 1, " -->CA_GET_SLOT_INFO Success !");
+		break;
+	case CA_GET_CAP:
+		dprintk(verbose, DST_CA_INFO, 1, " Getting Slot capabilities");
+		if ((ca_get_slot_caps(state, p_ca_caps, arg)) < 0) {
+			dprintk(verbose, DST_CA_ERROR, 1, " -->CA_GET_CAP Failed !");
+			result = -1;
+			goto free_mem_and_exit;
+		}
+		dprintk(verbose, DST_CA_INFO, 1, " -->CA_GET_CAP Success !");
+		break;
+	case CA_GET_DESCR_INFO:
+		dprintk(verbose, DST_CA_INFO, 1, " Getting descrambler description");
+		if ((ca_get_slot_descr(state, p_ca_message, arg)) < 0) {
+			dprintk(verbose, DST_CA_ERROR, 1, " -->CA_GET_DESCR_INFO Failed !");
+			result = -1;
+			goto free_mem_and_exit;
+		}
+		dprintk(verbose, DST_CA_INFO, 1, " -->CA_GET_DESCR_INFO Success !");
+		break;
+	case CA_SET_DESCR:
+		dprintk(verbose, DST_CA_INFO, 1, " Setting descrambler");
+		if ((ca_set_slot_descr()) < 0) {
+			dprintk(verbose, DST_CA_ERROR, 1, " -->CA_SET_DESCR Failed !");
+			result = -1;
+			goto free_mem_and_exit;
+		}
+		dprintk(verbose, DST_CA_INFO, 1, " -->CA_SET_DESCR Success !");
+		break;
+	case CA_SET_PID:
+		dprintk(verbose, DST_CA_INFO, 1, " Setting PID");
+		if ((ca_set_pid()) < 0) {
+			dprintk(verbose, DST_CA_ERROR, 1, " -->CA_SET_PID Failed !");
+			result = -1;
+			goto free_mem_and_exit;
+		}
+		dprintk(verbose, DST_CA_INFO, 1, " -->CA_SET_PID Success !");
+	default:
+		result = -EOPNOTSUPP;
+	};
+ free_mem_and_exit:
+	kfree (p_ca_message);
+	kfree (p_ca_slot_info);
+	kfree (p_ca_caps);
+
+	mutex_unlock(&dst_ca_mutex);
+	return result;
+}
+
+static int dst_ca_open(struct inode *inode, struct file *file)
+{
+	dprintk(verbose, DST_CA_DEBUG, 1, " Device opened [%p] ", file);
+	try_module_get(THIS_MODULE);
+
+	return 0;
+}
+
+static int dst_ca_release(struct inode *inode, struct file *file)
+{
+	dprintk(verbose, DST_CA_DEBUG, 1, " Device closed.");
+	module_put(THIS_MODULE);
+
+	return 0;
+}
+
+static ssize_t dst_ca_read(struct file *file, char __user *buffer, size_t length, loff_t *offset)
+{
+	ssize_t bytes_read = 0;
+
+	dprintk(verbose, DST_CA_DEBUG, 1, " Device read.");
+
+	return bytes_read;
+}
+
+static ssize_t dst_ca_write(struct file *file, const char __user *buffer, size_t length, loff_t *offset)
+{
+	dprintk(verbose, DST_CA_DEBUG, 1, " Device write.");
+
+	return 0;
+}
+
+static const struct file_operations dst_ca_fops = {
+	.owner = THIS_MODULE,
+	.unlocked_ioctl = dst_ca_ioctl,
+	.open = dst_ca_open,
+	.release = dst_ca_release,
+	.read = dst_ca_read,
+	.write = dst_ca_write,
+	.llseek = noop_llseek,
+};
+
+static struct dvb_device dvbdev_ca = {
+	.priv = NULL,
+	.users = 1,
+	.readers = 1,
+	.writers = 1,
+	.fops = &dst_ca_fops
+};
+
+struct dvb_device *dst_ca_attach(struct dst_state *dst, struct dvb_adapter *dvb_adapter)
+{
+	struct dvb_device *dvbdev;
+
+	dprintk(verbose, DST_CA_ERROR, 1, "registering DST-CA device");
+	if (dvb_register_device(dvb_adapter, &dvbdev, &dvbdev_ca, dst, DVB_DEVICE_CA) == 0) {
+		dst->dst_ca = dvbdev;
+		return dst->dst_ca;
+	}
+
+	return NULL;
+}
+
+EXPORT_SYMBOL(dst_ca_attach);
+
+MODULE_DESCRIPTION("DST DVB-S/T/C Combo CA driver");
+MODULE_AUTHOR("Manu Abraham");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/pci/bt8xx/dst_ca.h b/drivers/media/pci/bt8xx/dst_ca.h
new file mode 100644
index 0000000..59cd0dd
--- /dev/null
+++ b/drivers/media/pci/bt8xx/dst_ca.h
@@ -0,0 +1,58 @@
+/*
+	CA-driver for TwinHan DST Frontend/Card
+
+	Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.com)
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef _DST_CA_H_
+#define _DST_CA_H_
+
+#define RETRIES			5
+
+
+#define	CA_APP_INFO_ENQUIRY	0x9f8020
+#define	CA_APP_INFO		0x9f8021
+#define	CA_ENTER_MENU		0x9f8022
+#define CA_INFO_ENQUIRY		0x9f8030
+#define	CA_INFO			0x9f8031
+#define CA_PMT			0x9f8032
+#define CA_PMT_REPLY		0x9f8033
+
+#define CA_CLOSE_MMI		0x9f8800
+#define CA_DISPLAY_CONTROL	0x9f8801
+#define CA_DISPLAY_REPLY	0x9f8802
+#define CA_TEXT_LAST		0x9f8803
+#define CA_TEXT_MORE		0x9f8804
+#define CA_KEYPAD_CONTROL	0x9f8805
+#define CA_KEYPRESS		0x9f8806
+
+#define CA_ENQUIRY		0x9f8807
+#define CA_ANSWER		0x9f8808
+#define CA_MENU_LAST		0x9f8809
+#define CA_MENU_MORE		0x9f880a
+#define CA_MENU_ANSWER		0x9f880b
+#define CA_LIST_LAST		0x9f880c
+#define CA_LIST_MORE		0x9f880d
+
+
+struct dst_ca_private {
+	struct dst_state *dst;
+	struct dvb_device *dvbdev;
+};
+
+
+#endif
diff --git a/drivers/media/pci/bt8xx/dst_common.h b/drivers/media/pci/bt8xx/dst_common.h
new file mode 100644
index 0000000..d70d98f
--- /dev/null
+++ b/drivers/media/pci/bt8xx/dst_common.h
@@ -0,0 +1,182 @@
+/*
+	Frontend-driver for TwinHan DST Frontend
+
+	Copyright (C) 2003 Jamie Honan
+	Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.com)
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef DST_COMMON_H
+#define DST_COMMON_H
+
+#include <linux/dvb/frontend.h>
+#include <linux/device.h>
+#include <linux/mutex.h>
+#include "bt878.h"
+
+#include "dst_ca.h"
+
+
+#define NO_DELAY		0
+#define LONG_DELAY		1
+#define DEVICE_INIT		2
+
+#define DELAY			1
+
+#define DST_TYPE_IS_SAT		0
+#define DST_TYPE_IS_TERR	1
+#define DST_TYPE_IS_CABLE	2
+#define DST_TYPE_IS_ATSC	3
+
+#define DST_TYPE_HAS_TS188	1
+#define DST_TYPE_HAS_TS204	2
+#define DST_TYPE_HAS_SYMDIV	4
+#define DST_TYPE_HAS_FW_1	8
+#define DST_TYPE_HAS_FW_2	16
+#define DST_TYPE_HAS_FW_3	32
+#define DST_TYPE_HAS_FW_BUILD	64
+#define DST_TYPE_HAS_OBS_REGS	128
+#define DST_TYPE_HAS_INC_COUNT	256
+#define DST_TYPE_HAS_MULTI_FE	512
+#define DST_TYPE_HAS_NEWTUNE_2	1024
+#define DST_TYPE_HAS_DBOARD	2048
+#define DST_TYPE_HAS_VLF	4096
+
+/*	Card capability list	*/
+
+#define DST_TYPE_HAS_MAC	1
+#define DST_TYPE_HAS_DISEQC3	2
+#define DST_TYPE_HAS_DISEQC4	4
+#define DST_TYPE_HAS_DISEQC5	8
+#define DST_TYPE_HAS_MOTO	16
+#define DST_TYPE_HAS_CA		32
+#define	DST_TYPE_HAS_ANALOG	64	/*	Analog inputs	*/
+#define DST_TYPE_HAS_SESSION	128
+
+#define TUNER_TYPE_MULTI	1
+#define TUNER_TYPE_UNKNOWN	2
+/*	DVB-S		*/
+#define TUNER_TYPE_L64724	4
+#define TUNER_TYPE_STV0299	8
+#define TUNER_TYPE_MB86A15	16
+
+/*	DVB-T		*/
+#define TUNER_TYPE_TDA10046	32
+
+/*	ATSC		*/
+#define TUNER_TYPE_NXT200x	64
+
+
+#define RDC_8820_PIO_0_DISABLE	0
+#define RDC_8820_PIO_0_ENABLE	1
+#define RDC_8820_INT		2
+#define RDC_8820_RESET		4
+
+/*	DST Communication	*/
+#define GET_REPLY		1
+#define NO_REPLY		0
+
+#define GET_ACK			1
+#define FIXED_COMM		8
+
+#define ACK			0xff
+
+struct dst_state {
+
+	struct i2c_adapter* i2c;
+
+	struct bt878* bt;
+
+	/* configuration settings */
+	const struct dst_config* config;
+
+	struct dvb_frontend frontend;
+
+	/* private ASIC data */
+	u8 tx_tuna[10];
+	u8 rx_tuna[10];
+	u8 rxbuffer[10];
+	u8 diseq_flags;
+	u8 dst_type;
+	u32 type_flags;
+	u32 frequency;		/* intermediate frequency in kHz for QPSK */
+	fe_spectral_inversion_t inversion;
+	u32 symbol_rate;	/* symbol rate in Symbols per second */
+	fe_code_rate_t fec;
+	fe_sec_voltage_t voltage;
+	fe_sec_tone_mode_t tone;
+	u32 decode_freq;
+	u8 decode_lock;
+	u16 decode_strength;
+	u16 decode_snr;
+	unsigned long cur_jiff;
+	u8 k22;
+	u32 bandwidth;
+	u32 dst_hw_cap;
+	u8 dst_fw_version;
+	fe_sec_mini_cmd_t minicmd;
+	fe_modulation_t modulation;
+	u8 messages[256];
+	u8 mac_address[8];
+	u8 fw_version[8];
+	u8 card_info[8];
+	u8 vendor[8];
+	u8 board_info[8];
+	u32 tuner_type;
+	char *tuner_name;
+	struct mutex dst_mutex;
+	u8 fw_name[8];
+	struct dvb_device *dst_ca;
+};
+
+struct tuner_types {
+	u32 tuner_type;
+	char *tuner_name;
+	char *board_name;
+	char *fw_name;
+};
+
+struct dst_types {
+	char *device_id;
+	int offset;
+	u8 dst_type;
+	u32 type_flags;
+	u32 dst_feature;
+	u32 tuner_type;
+};
+
+struct dst_config
+{
+	/* the ASIC i2c address */
+	u8 demod_address;
+};
+
+int rdc_reset_state(struct dst_state *state);
+
+int dst_wait_dst_ready(struct dst_state *state, u8 delay_mode);
+int dst_pio_disable(struct dst_state *state);
+int dst_error_recovery(struct dst_state* state);
+int dst_error_bailout(struct dst_state *state);
+int dst_comm_init(struct dst_state* state);
+
+int write_dst(struct dst_state *state, u8 * data, u8 len);
+int read_dst(struct dst_state *state, u8 * ret, u8 len);
+u8 dst_check_sum(u8 * buf, u32 len);
+struct dst_state* dst_attach(struct dst_state* state, struct dvb_adapter *dvb_adapter);
+struct dvb_device *dst_ca_attach(struct dst_state *state, struct dvb_adapter *dvb_adapter);
+
+
+#endif // DST_COMMON_H
diff --git a/drivers/media/pci/bt8xx/dst_priv.h b/drivers/media/pci/bt8xx/dst_priv.h
new file mode 100644
index 0000000..3974a4c
--- /dev/null
+++ b/drivers/media/pci/bt8xx/dst_priv.h
@@ -0,0 +1,35 @@
+/*
+ * dst-bt878.h: part of the DST driver for the TwinHan DST Frontend
+ *
+ * Copyright (C) 2003 Jamie Honan
+ */
+
+struct dst_gpio_enable {
+	u32	mask;
+	u32	enable;
+};
+
+struct dst_gpio_output {
+	u32	mask;
+	u32	highvals;
+};
+
+struct dst_gpio_read {
+	unsigned long value;
+};
+
+union dst_gpio_packet {
+	struct dst_gpio_enable enb;
+	struct dst_gpio_output outp;
+	struct dst_gpio_read rd;
+	int    psize;
+};
+
+#define DST_IG_ENABLE	0
+#define DST_IG_WRITE	1
+#define DST_IG_READ	2
+#define DST_IG_TS       3
+
+struct bt878;
+
+int bt878_device_control(struct bt878 *bt, unsigned int cmd, union dst_gpio_packet *mp);
diff --git a/drivers/media/pci/bt8xx/dvb-bt8xx.c b/drivers/media/pci/bt8xx/dvb-bt8xx.c
new file mode 100644
index 0000000..81fab9a
--- /dev/null
+++ b/drivers/media/pci/bt8xx/dvb-bt8xx.c
@@ -0,0 +1,975 @@
+/*
+ * Bt8xx based DVB adapter driver
+ *
+ * Copyright (C) 2002,2003 Florian Schirmer <jolt@tuxbox.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.
+ *
+ */
+
+#define pr_fmt(fmt) "dvb_bt8xx: " fmt
+
+#include <linux/bitops.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+
+#include "dmxdev.h"
+#include "dvbdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dvb-bt8xx.h"
+#include "bt878.h"
+
+static int debug;
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+#define dprintk( args... ) \
+	do { \
+		if (debug) printk(KERN_DEBUG args); \
+	} while (0)
+
+#define IF_FREQUENCYx6 217    /* 6 * 36.16666666667MHz */
+
+static void dvb_bt8xx_task(unsigned long data)
+{
+	struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *)data;
+
+	//printk("%d ", card->bt->finished_block);
+
+	while (card->bt->last_block != card->bt->finished_block) {
+		(card->bt->TS_Size ? dvb_dmx_swfilter_204 : dvb_dmx_swfilter)
+			(&card->demux,
+			 &card->bt->buf_cpu[card->bt->last_block *
+					    card->bt->block_bytes],
+			 card->bt->block_bytes);
+		card->bt->last_block = (card->bt->last_block + 1) %
+					card->bt->block_count;
+	}
+}
+
+static int dvb_bt8xx_start_feed(struct dvb_demux_feed *dvbdmxfeed)
+{
+	struct dvb_demux*dvbdmx = dvbdmxfeed->demux;
+	struct dvb_bt8xx_card *card = dvbdmx->priv;
+	int rc;
+
+	dprintk("dvb_bt8xx: start_feed\n");
+
+	if (!dvbdmx->dmx.frontend)
+		return -EINVAL;
+
+	mutex_lock(&card->lock);
+	card->nfeeds++;
+	rc = card->nfeeds;
+	if (card->nfeeds == 1)
+		bt878_start(card->bt, card->gpio_mode,
+			    card->op_sync_orin, card->irq_err_ignore);
+	mutex_unlock(&card->lock);
+	return rc;
+}
+
+static int dvb_bt8xx_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
+{
+	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
+	struct dvb_bt8xx_card *card = dvbdmx->priv;
+
+	dprintk("dvb_bt8xx: stop_feed\n");
+
+	if (!dvbdmx->dmx.frontend)
+		return -EINVAL;
+
+	mutex_lock(&card->lock);
+	card->nfeeds--;
+	if (card->nfeeds == 0)
+		bt878_stop(card->bt);
+	mutex_unlock(&card->lock);
+
+	return 0;
+}
+
+static int is_pci_slot_eq(struct pci_dev* adev, struct pci_dev* bdev)
+{
+	if ((adev->subsystem_vendor == bdev->subsystem_vendor) &&
+		(adev->subsystem_device == bdev->subsystem_device) &&
+		(adev->bus->number == bdev->bus->number) &&
+		(PCI_SLOT(adev->devfn) == PCI_SLOT(bdev->devfn)))
+		return 1;
+	return 0;
+}
+
+static struct bt878 __devinit *dvb_bt8xx_878_match(unsigned int bttv_nr, struct pci_dev* bttv_pci_dev)
+{
+	unsigned int card_nr;
+
+	/* Hmm, n squared. Hope n is small */
+	for (card_nr = 0; card_nr < bt878_num; card_nr++)
+		if (is_pci_slot_eq(bt878[card_nr].dev, bttv_pci_dev))
+			return &bt878[card_nr];
+	return NULL;
+}
+
+static int thomson_dtt7579_demod_init(struct dvb_frontend* fe)
+{
+	static u8 mt352_clock_config [] = { 0x89, 0x38, 0x38 };
+	static u8 mt352_reset [] = { 0x50, 0x80 };
+	static u8 mt352_adc_ctl_1_cfg [] = { 0x8E, 0x40 };
+	static u8 mt352_agc_cfg [] = { 0x67, 0x28, 0x20 };
+	static u8 mt352_gpp_ctl_cfg [] = { 0x8C, 0x33 };
+	static u8 mt352_capt_range_cfg[] = { 0x75, 0x32 };
+
+	mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config));
+	udelay(2000);
+	mt352_write(fe, mt352_reset, sizeof(mt352_reset));
+	mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg));
+
+	mt352_write(fe, mt352_agc_cfg, sizeof(mt352_agc_cfg));
+	mt352_write(fe, mt352_gpp_ctl_cfg, sizeof(mt352_gpp_ctl_cfg));
+	mt352_write(fe, mt352_capt_range_cfg, sizeof(mt352_capt_range_cfg));
+
+	return 0;
+}
+
+static int thomson_dtt7579_tuner_calc_regs(struct dvb_frontend *fe, u8* pllbuf, int buf_len)
+{
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	u32 div;
+	unsigned char bs = 0;
+	unsigned char cp = 0;
+
+	if (buf_len < 5)
+		return -EINVAL;
+
+	div = (((c->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
+
+	if (c->frequency < 542000000)
+		cp = 0xb4;
+	else if (c->frequency < 771000000)
+		cp = 0xbc;
+	else
+		cp = 0xf4;
+
+	if (c->frequency == 0)
+		bs = 0x03;
+	else if (c->frequency < 443250000)
+		bs = 0x02;
+	else
+		bs = 0x08;
+
+	pllbuf[0] = 0x60;
+	pllbuf[1] = div >> 8;
+	pllbuf[2] = div & 0xff;
+	pllbuf[3] = cp;
+	pllbuf[4] = bs;
+
+	return 5;
+}
+
+static struct mt352_config thomson_dtt7579_config = {
+	.demod_address = 0x0f,
+	.demod_init = thomson_dtt7579_demod_init,
+};
+
+static struct zl10353_config thomson_dtt7579_zl10353_config = {
+	.demod_address = 0x0f,
+};
+
+static int cx24108_tuner_set_params(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	u32 freq = c->frequency;
+	int i, a, n, pump;
+	u32 band, pll;
+	u32 osci[]={950000,1019000,1075000,1178000,1296000,1432000,
+		1576000,1718000,1856000,2036000,2150000};
+	u32 bandsel[]={0,0x00020000,0x00040000,0x00100800,0x00101000,
+		0x00102000,0x00104000,0x00108000,0x00110000,
+		0x00120000,0x00140000};
+
+	#define XTAL 1011100 /* Hz, really 1.0111 MHz and a /10 prescaler */
+	dprintk("cx24108 debug: entering SetTunerFreq, freq=%d\n", freq);
+
+	/* This is really the bit driving the tuner chip cx24108 */
+
+	if (freq<950000)
+		freq = 950000; /* kHz */
+	else if (freq>2150000)
+		freq = 2150000; /* satellite IF is 950..2150MHz */
+
+	/* decide which VCO to use for the input frequency */
+	for(i = 1; (i < ARRAY_SIZE(osci) - 1) && (osci[i] < freq); i++);
+	dprintk("cx24108 debug: select vco #%d (f=%d)\n", i, freq);
+	band=bandsel[i];
+	/* the gain values must be set by SetSymbolrate */
+	/* compute the pll divider needed, from Conexant data sheet,
+	   resolved for (n*32+a), remember f(vco) is f(receive) *2 or *4,
+	   depending on the divider bit. It is set to /4 on the 2 lowest
+	   bands  */
+	n=((i<=2?2:1)*freq*10L)/(XTAL/100);
+	a=n%32; n/=32; if(a==0) n--;
+	pump=(freq<(osci[i-1]+osci[i])/2);
+	pll=0xf8000000|
+	    ((pump?1:2)<<(14+11))|
+	    ((n&0x1ff)<<(5+11))|
+	    ((a&0x1f)<<11);
+	/* everything is shifted left 11 bits to left-align the bits in the
+	   32bit word. Output to the tuner goes MSB-aligned, after all */
+	dprintk("cx24108 debug: pump=%d, n=%d, a=%d\n", pump, n, a);
+	cx24110_pll_write(fe,band);
+	/* set vga and vca to their widest-band settings, as a precaution.
+	   SetSymbolrate might not be called to set this up */
+	cx24110_pll_write(fe,0x500c0000);
+	cx24110_pll_write(fe,0x83f1f800);
+	cx24110_pll_write(fe,pll);
+	//writereg(client,0x56,0x7f);
+
+	return 0;
+}
+
+static int pinnsat_tuner_init(struct dvb_frontend* fe)
+{
+	struct dvb_bt8xx_card *card = fe->dvb->priv;
+
+	bttv_gpio_enable(card->bttv_nr, 1, 1);  /* output */
+	bttv_write_gpio(card->bttv_nr, 1, 1);   /* relay on */
+
+	return 0;
+}
+
+static int pinnsat_tuner_sleep(struct dvb_frontend* fe)
+{
+	struct dvb_bt8xx_card *card = fe->dvb->priv;
+
+	bttv_write_gpio(card->bttv_nr, 1, 0);   /* relay off */
+
+	return 0;
+}
+
+static struct cx24110_config pctvsat_config = {
+	.demod_address = 0x55,
+};
+
+static int microtune_mt7202dtf_tuner_set_params(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *) fe->dvb->priv;
+	u8 cfg, cpump, band_select;
+	u8 data[4];
+	u32 div;
+	struct i2c_msg msg = { .addr = 0x60, .flags = 0, .buf = data, .len = sizeof(data) };
+
+	div = (36000000 + c->frequency + 83333) / 166666;
+	cfg = 0x88;
+
+	if (c->frequency < 175000000)
+		cpump = 2;
+	else if (c->frequency < 390000000)
+		cpump = 1;
+	else if (c->frequency < 470000000)
+		cpump = 2;
+	else if (c->frequency < 750000000)
+		cpump = 2;
+	else
+		cpump = 3;
+
+	if (c->frequency < 175000000)
+		band_select = 0x0e;
+	else if (c->frequency < 470000000)
+		band_select = 0x05;
+	else
+		band_select = 0x03;
+
+	data[0] = (div >> 8) & 0x7f;
+	data[1] = div & 0xff;
+	data[2] = ((div >> 10) & 0x60) | cfg;
+	data[3] = (cpump << 6) | band_select;
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+	i2c_transfer(card->i2c_adapter, &msg, 1);
+	return (div * 166666 - 36000000);
+}
+
+static int microtune_mt7202dtf_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name)
+{
+	struct dvb_bt8xx_card* bt = (struct dvb_bt8xx_card*) fe->dvb->priv;
+
+	return request_firmware(fw, name, &bt->bt->dev->dev);
+}
+
+static struct sp887x_config microtune_mt7202dtf_config = {
+	.demod_address = 0x70,
+	.request_firmware = microtune_mt7202dtf_request_firmware,
+};
+
+static int advbt771_samsung_tdtc9251dh0_demod_init(struct dvb_frontend* fe)
+{
+	static u8 mt352_clock_config [] = { 0x89, 0x38, 0x2d };
+	static u8 mt352_reset [] = { 0x50, 0x80 };
+	static u8 mt352_adc_ctl_1_cfg [] = { 0x8E, 0x40 };
+	static u8 mt352_agc_cfg [] = { 0x67, 0x10, 0x23, 0x00, 0xFF, 0xFF,
+				       0x00, 0xFF, 0x00, 0x40, 0x40 };
+	static u8 mt352_av771_extra[] = { 0xB5, 0x7A };
+	static u8 mt352_capt_range_cfg[] = { 0x75, 0x32 };
+
+	mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config));
+	udelay(2000);
+	mt352_write(fe, mt352_reset, sizeof(mt352_reset));
+	mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg));
+
+	mt352_write(fe, mt352_agc_cfg,sizeof(mt352_agc_cfg));
+	udelay(2000);
+	mt352_write(fe, mt352_av771_extra,sizeof(mt352_av771_extra));
+	mt352_write(fe, mt352_capt_range_cfg, sizeof(mt352_capt_range_cfg));
+
+	return 0;
+}
+
+static int advbt771_samsung_tdtc9251dh0_tuner_calc_regs(struct dvb_frontend *fe, u8 *pllbuf, int buf_len)
+{
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	u32 div;
+	unsigned char bs = 0;
+	unsigned char cp = 0;
+
+	if (buf_len < 5) return -EINVAL;
+
+	div = (((c->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
+
+	if (c->frequency < 150000000)
+		cp = 0xB4;
+	else if (c->frequency < 173000000)
+		cp = 0xBC;
+	else if (c->frequency < 250000000)
+		cp = 0xB4;
+	else if (c->frequency < 400000000)
+		cp = 0xBC;
+	else if (c->frequency < 420000000)
+		cp = 0xF4;
+	else if (c->frequency < 470000000)
+		cp = 0xFC;
+	else if (c->frequency < 600000000)
+		cp = 0xBC;
+	else if (c->frequency < 730000000)
+		cp = 0xF4;
+	else
+		cp = 0xFC;
+
+	if (c->frequency < 150000000)
+		bs = 0x01;
+	else if (c->frequency < 173000000)
+		bs = 0x01;
+	else if (c->frequency < 250000000)
+		bs = 0x02;
+	else if (c->frequency < 400000000)
+		bs = 0x02;
+	else if (c->frequency < 420000000)
+		bs = 0x02;
+	else if (c->frequency < 470000000)
+		bs = 0x02;
+	else if (c->frequency < 600000000)
+		bs = 0x08;
+	else if (c->frequency < 730000000)
+		bs = 0x08;
+	else
+		bs = 0x08;
+
+	pllbuf[0] = 0x61;
+	pllbuf[1] = div >> 8;
+	pllbuf[2] = div & 0xff;
+	pllbuf[3] = cp;
+	pllbuf[4] = bs;
+
+	return 5;
+}
+
+static struct mt352_config advbt771_samsung_tdtc9251dh0_config = {
+	.demod_address = 0x0f,
+	.demod_init = advbt771_samsung_tdtc9251dh0_demod_init,
+};
+
+static struct dst_config dst_config = {
+	.demod_address = 0x55,
+};
+
+static int or51211_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name)
+{
+	struct dvb_bt8xx_card* bt = (struct dvb_bt8xx_card*) fe->dvb->priv;
+
+	return request_firmware(fw, name, &bt->bt->dev->dev);
+}
+
+static void or51211_setmode(struct dvb_frontend * fe, int mode)
+{
+	struct dvb_bt8xx_card *bt = fe->dvb->priv;
+	bttv_write_gpio(bt->bttv_nr, 0x0002, mode);   /* Reset */
+	msleep(20);
+}
+
+static void or51211_reset(struct dvb_frontend * fe)
+{
+	struct dvb_bt8xx_card *bt = fe->dvb->priv;
+
+	/* RESET DEVICE
+	 * reset is controlled by GPIO-0
+	 * when set to 0 causes reset and when to 1 for normal op
+	 * must remain reset for 128 clock cycles on a 50Mhz clock
+	 * also PRM1 PRM2 & PRM4 are controlled by GPIO-1,GPIO-2 & GPIO-4
+	 * We assume that the reset has be held low long enough or we
+	 * have been reset by a power on.  When the driver is unloaded
+	 * reset set to 0 so if reloaded we have been reset.
+	 */
+	/* reset & PRM1,2&4 are outputs */
+	int ret = bttv_gpio_enable(bt->bttv_nr, 0x001F, 0x001F);
+	if (ret != 0)
+		printk(KERN_WARNING "or51211: Init Error - Can't Reset DVR (%i)\n", ret);
+	bttv_write_gpio(bt->bttv_nr, 0x001F, 0x0000);   /* Reset */
+	msleep(20);
+	/* Now set for normal operation */
+	bttv_write_gpio(bt->bttv_nr, 0x0001F, 0x0001);
+	/* wait for operation to begin */
+	msleep(500);
+}
+
+static void or51211_sleep(struct dvb_frontend * fe)
+{
+	struct dvb_bt8xx_card *bt = fe->dvb->priv;
+	bttv_write_gpio(bt->bttv_nr, 0x0001, 0x0000);
+}
+
+static struct or51211_config or51211_config = {
+	.demod_address = 0x15,
+	.request_firmware = or51211_request_firmware,
+	.setmode = or51211_setmode,
+	.reset = or51211_reset,
+	.sleep = or51211_sleep,
+};
+
+static int vp3021_alps_tded4_tuner_set_params(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *) fe->dvb->priv;
+	u8 buf[4];
+	u32 div;
+	struct i2c_msg msg = { .addr = 0x60, .flags = 0, .buf = buf, .len = sizeof(buf) };
+
+	div = (c->frequency + 36166667) / 166667;
+
+	buf[0] = (div >> 8) & 0x7F;
+	buf[1] = div & 0xFF;
+	buf[2] = 0x85;
+	if ((c->frequency >= 47000000) && (c->frequency < 153000000))
+		buf[3] = 0x01;
+	else if ((c->frequency >= 153000000) && (c->frequency < 430000000))
+		buf[3] = 0x02;
+	else if ((c->frequency >= 430000000) && (c->frequency < 824000000))
+		buf[3] = 0x0C;
+	else if ((c->frequency >= 824000000) && (c->frequency < 863000000))
+		buf[3] = 0x8C;
+	else
+		return -EINVAL;
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+	i2c_transfer(card->i2c_adapter, &msg, 1);
+	return 0;
+}
+
+static struct nxt6000_config vp3021_alps_tded4_config = {
+	.demod_address = 0x0a,
+	.clock_inversion = 1,
+};
+
+static int digitv_alps_tded4_demod_init(struct dvb_frontend* fe)
+{
+	static u8 mt352_clock_config [] = { 0x89, 0x38, 0x2d };
+	static u8 mt352_reset [] = { 0x50, 0x80 };
+	static u8 mt352_adc_ctl_1_cfg [] = { 0x8E, 0x40 };
+	static u8 mt352_agc_cfg [] = { 0x67, 0x20, 0xa0 };
+	static u8 mt352_capt_range_cfg[] = { 0x75, 0x32 };
+
+	mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config));
+	udelay(2000);
+	mt352_write(fe, mt352_reset, sizeof(mt352_reset));
+	mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg));
+	mt352_write(fe, mt352_agc_cfg,sizeof(mt352_agc_cfg));
+	mt352_write(fe, mt352_capt_range_cfg, sizeof(mt352_capt_range_cfg));
+
+	return 0;
+}
+
+static int digitv_alps_tded4_tuner_calc_regs(struct dvb_frontend *fe,  u8 *pllbuf, int buf_len)
+{
+	u32 div;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+
+	if (buf_len < 5)
+		return -EINVAL;
+
+	div = (((c->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
+
+	pllbuf[0] = 0x61;
+	pllbuf[1] = (div >> 8) & 0x7F;
+	pllbuf[2] = div & 0xFF;
+	pllbuf[3] = 0x85;
+
+	dprintk("frequency %u, div %u\n", c->frequency, div);
+
+	if (c->frequency < 470000000)
+		pllbuf[4] = 0x02;
+	else if (c->frequency > 823000000)
+		pllbuf[4] = 0x88;
+	else
+		pllbuf[4] = 0x08;
+
+	if (c->bandwidth_hz == 8000000)
+		pllbuf[4] |= 0x04;
+
+	return 5;
+}
+
+static void digitv_alps_tded4_reset(struct dvb_bt8xx_card *bt)
+{
+	/*
+	 * Reset the frontend, must be called before trying
+	 * to initialise the MT352 or mt352_attach
+	 * will fail. Same goes for the nxt6000 frontend.
+	 *
+	 */
+
+	int ret = bttv_gpio_enable(bt->bttv_nr, 0x08, 0x08);
+	if (ret != 0)
+		printk(KERN_WARNING "digitv_alps_tded4: Init Error - Can't Reset DVR (%i)\n", ret);
+
+	/* Pulse the reset line */
+	bttv_write_gpio(bt->bttv_nr, 0x08, 0x08); /* High */
+	bttv_write_gpio(bt->bttv_nr, 0x08, 0x00); /* Low  */
+	msleep(100);
+
+	bttv_write_gpio(bt->bttv_nr, 0x08, 0x08); /* High */
+}
+
+static struct mt352_config digitv_alps_tded4_config = {
+	.demod_address = 0x0a,
+	.demod_init = digitv_alps_tded4_demod_init,
+};
+
+static struct lgdt330x_config tdvs_tua6034_config = {
+	.demod_address    = 0x0e,
+	.demod_chip       = LGDT3303,
+	.serial_mpeg      = 0x40, /* TPSERIAL for 3303 in TOP_CONTROL */
+};
+
+static void lgdt330x_reset(struct dvb_bt8xx_card *bt)
+{
+	/* Set pin 27 of the lgdt3303 chip high to reset the frontend */
+
+	/* Pulse the reset line */
+	bttv_write_gpio(bt->bttv_nr, 0x00e00007, 0x00000001); /* High */
+	bttv_write_gpio(bt->bttv_nr, 0x00e00007, 0x00000000); /* Low  */
+	msleep(100);
+
+	bttv_write_gpio(bt->bttv_nr, 0x00e00007, 0x00000001); /* High */
+	msleep(100);
+}
+
+static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
+{
+	struct dst_state* state = NULL;
+
+	switch(type) {
+	case BTTV_BOARD_DVICO_DVBT_LITE:
+		card->fe = dvb_attach(mt352_attach, &thomson_dtt7579_config, card->i2c_adapter);
+
+		if (card->fe == NULL)
+			card->fe = dvb_attach(zl10353_attach, &thomson_dtt7579_zl10353_config,
+						  card->i2c_adapter);
+
+		if (card->fe != NULL) {
+			card->fe->ops.tuner_ops.calc_regs = thomson_dtt7579_tuner_calc_regs;
+			card->fe->ops.info.frequency_min = 174000000;
+			card->fe->ops.info.frequency_max = 862000000;
+		}
+		break;
+
+	case BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE:
+		lgdt330x_reset(card);
+		card->fe = dvb_attach(lgdt330x_attach, &tdvs_tua6034_config, card->i2c_adapter);
+		if (card->fe != NULL) {
+			dvb_attach(simple_tuner_attach, card->fe,
+				   card->i2c_adapter, 0x61,
+				   TUNER_LG_TDVS_H06XF);
+			dprintk ("dvb_bt8xx: lgdt330x detected\n");
+		}
+		break;
+
+	case BTTV_BOARD_NEBULA_DIGITV:
+		/*
+		 * It is possible to determine the correct frontend using the I2C bus (see the Nebula SDK);
+		 * this would be a cleaner solution than trying each frontend in turn.
+		 */
+
+		/* Old Nebula (marked (c)2003 on high profile pci card) has nxt6000 demod */
+		digitv_alps_tded4_reset(card);
+		card->fe = dvb_attach(nxt6000_attach, &vp3021_alps_tded4_config, card->i2c_adapter);
+		if (card->fe != NULL) {
+			card->fe->ops.tuner_ops.set_params = vp3021_alps_tded4_tuner_set_params;
+			dprintk ("dvb_bt8xx: an nxt6000 was detected on your digitv card\n");
+			break;
+		}
+
+		/* New Nebula (marked (c)2005 on low profile pci card) has mt352 demod */
+		digitv_alps_tded4_reset(card);
+		card->fe = dvb_attach(mt352_attach, &digitv_alps_tded4_config, card->i2c_adapter);
+
+		if (card->fe != NULL) {
+			card->fe->ops.tuner_ops.calc_regs = digitv_alps_tded4_tuner_calc_regs;
+			dprintk ("dvb_bt8xx: an mt352 was detected on your digitv card\n");
+		}
+		break;
+
+	case BTTV_BOARD_AVDVBT_761:
+		card->fe = dvb_attach(sp887x_attach, &microtune_mt7202dtf_config, card->i2c_adapter);
+		if (card->fe) {
+			card->fe->ops.tuner_ops.set_params = microtune_mt7202dtf_tuner_set_params;
+		}
+		break;
+
+	case BTTV_BOARD_AVDVBT_771:
+		card->fe = dvb_attach(mt352_attach, &advbt771_samsung_tdtc9251dh0_config, card->i2c_adapter);
+		if (card->fe != NULL) {
+			card->fe->ops.tuner_ops.calc_regs = advbt771_samsung_tdtc9251dh0_tuner_calc_regs;
+			card->fe->ops.info.frequency_min = 174000000;
+			card->fe->ops.info.frequency_max = 862000000;
+		}
+		break;
+
+	case BTTV_BOARD_TWINHAN_DST:
+		/*	DST is not a frontend driver !!!		*/
+		state = kmalloc(sizeof (struct dst_state), GFP_KERNEL);
+		if (!state) {
+			pr_err("No memory\n");
+			break;
+		}
+		/*	Setup the Card					*/
+		state->config = &dst_config;
+		state->i2c = card->i2c_adapter;
+		state->bt = card->bt;
+		state->dst_ca = NULL;
+		/*	DST is not a frontend, attaching the ASIC	*/
+		if (dvb_attach(dst_attach, state, &card->dvb_adapter) == NULL) {
+			pr_err("%s: Could not find a Twinhan DST\n", __func__);
+			break;
+		}
+		/*	Attach other DST peripherals if any		*/
+		/*	Conditional Access device			*/
+		card->fe = &state->frontend;
+		if (state->dst_hw_cap & DST_TYPE_HAS_CA)
+			dvb_attach(dst_ca_attach, state, &card->dvb_adapter);
+		break;
+
+	case BTTV_BOARD_PINNACLESAT:
+		card->fe = dvb_attach(cx24110_attach, &pctvsat_config, card->i2c_adapter);
+		if (card->fe) {
+			card->fe->ops.tuner_ops.init = pinnsat_tuner_init;
+			card->fe->ops.tuner_ops.sleep = pinnsat_tuner_sleep;
+			card->fe->ops.tuner_ops.set_params = cx24108_tuner_set_params;
+		}
+		break;
+
+	case BTTV_BOARD_PC_HDTV:
+		card->fe = dvb_attach(or51211_attach, &or51211_config, card->i2c_adapter);
+		if (card->fe != NULL)
+			dvb_attach(simple_tuner_attach, card->fe,
+				   card->i2c_adapter, 0x61,
+				   TUNER_PHILIPS_FCV1236D);
+		break;
+	}
+
+	if (card->fe == NULL)
+		pr_err("A frontend driver was not found for device [%04x:%04x] subsystem [%04x:%04x]\n",
+		       card->bt->dev->vendor,
+		       card->bt->dev->device,
+		       card->bt->dev->subsystem_vendor,
+		       card->bt->dev->subsystem_device);
+	else
+		if (dvb_register_frontend(&card->dvb_adapter, card->fe)) {
+			pr_err("Frontend registration failed!\n");
+			dvb_frontend_detach(card->fe);
+			card->fe = NULL;
+		}
+}
+
+static int __devinit dvb_bt8xx_load_card(struct dvb_bt8xx_card *card, u32 type)
+{
+	int result;
+
+	result = dvb_register_adapter(&card->dvb_adapter, card->card_name,
+				      THIS_MODULE, &card->bt->dev->dev,
+				      adapter_nr);
+	if (result < 0) {
+		pr_err("dvb_register_adapter failed (errno = %d)\n", result);
+		return result;
+	}
+	card->dvb_adapter.priv = card;
+
+	card->bt->adapter = card->i2c_adapter;
+
+	memset(&card->demux, 0, sizeof(struct dvb_demux));
+
+	card->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING | DMX_MEMORY_BASED_FILTERING;
+
+	card->demux.priv = card;
+	card->demux.filternum = 256;
+	card->demux.feednum = 256;
+	card->demux.start_feed = dvb_bt8xx_start_feed;
+	card->demux.stop_feed = dvb_bt8xx_stop_feed;
+	card->demux.write_to_decoder = NULL;
+
+	result = dvb_dmx_init(&card->demux);
+	if (result < 0) {
+		pr_err("dvb_dmx_init failed (errno = %d)\n", result);
+		goto err_unregister_adaptor;
+	}
+
+	card->dmxdev.filternum = 256;
+	card->dmxdev.demux = &card->demux.dmx;
+	card->dmxdev.capabilities = 0;
+
+	result = dvb_dmxdev_init(&card->dmxdev, &card->dvb_adapter);
+	if (result < 0) {
+		pr_err("dvb_dmxdev_init failed (errno = %d)\n", result);
+		goto err_dmx_release;
+	}
+
+	card->fe_hw.source = DMX_FRONTEND_0;
+
+	result = card->demux.dmx.add_frontend(&card->demux.dmx, &card->fe_hw);
+	if (result < 0) {
+		pr_err("dvb_dmx_init failed (errno = %d)\n", result);
+		goto err_dmxdev_release;
+	}
+
+	card->fe_mem.source = DMX_MEMORY_FE;
+
+	result = card->demux.dmx.add_frontend(&card->demux.dmx, &card->fe_mem);
+	if (result < 0) {
+		pr_err("dvb_dmx_init failed (errno = %d)\n", result);
+		goto err_remove_hw_frontend;
+	}
+
+	result = card->demux.dmx.connect_frontend(&card->demux.dmx, &card->fe_hw);
+	if (result < 0) {
+		pr_err("dvb_dmx_init failed (errno = %d)\n", result);
+		goto err_remove_mem_frontend;
+	}
+
+	result = dvb_net_init(&card->dvb_adapter, &card->dvbnet, &card->demux.dmx);
+	if (result < 0) {
+		pr_err("dvb_net_init failed (errno = %d)\n", result);
+		goto err_disconnect_frontend;
+	}
+
+	tasklet_init(&card->bt->tasklet, dvb_bt8xx_task, (unsigned long) card);
+
+	frontend_init(card, type);
+
+	return 0;
+
+err_disconnect_frontend:
+	card->demux.dmx.disconnect_frontend(&card->demux.dmx);
+err_remove_mem_frontend:
+	card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_mem);
+err_remove_hw_frontend:
+	card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_hw);
+err_dmxdev_release:
+	dvb_dmxdev_release(&card->dmxdev);
+err_dmx_release:
+	dvb_dmx_release(&card->demux);
+err_unregister_adaptor:
+	dvb_unregister_adapter(&card->dvb_adapter);
+	return result;
+}
+
+static int __devinit dvb_bt8xx_probe(struct bttv_sub_device *sub)
+{
+	struct dvb_bt8xx_card *card;
+	struct pci_dev* bttv_pci_dev;
+	int ret;
+
+	if (!(card = kzalloc(sizeof(struct dvb_bt8xx_card), GFP_KERNEL)))
+		return -ENOMEM;
+
+	mutex_init(&card->lock);
+	card->bttv_nr = sub->core->nr;
+	strlcpy(card->card_name, sub->core->v4l2_dev.name, sizeof(card->card_name));
+	card->i2c_adapter = &sub->core->i2c_adap;
+
+	switch(sub->core->type) {
+	case BTTV_BOARD_PINNACLESAT:
+		card->gpio_mode = 0x0400c060;
+		/* should be: BT878_A_GAIN=0,BT878_A_PWRDN,BT878_DA_DPM,BT878_DA_SBR,
+			      BT878_DA_IOM=1,BT878_DA_APP to enable serial highspeed mode. */
+		card->op_sync_orin = BT878_RISC_SYNC_MASK;
+		card->irq_err_ignore = BT878_AFBUS | BT878_AFDSR;
+		break;
+
+	case BTTV_BOARD_DVICO_DVBT_LITE:
+		card->gpio_mode = 0x0400C060;
+		card->op_sync_orin = BT878_RISC_SYNC_MASK;
+		card->irq_err_ignore = BT878_AFBUS | BT878_AFDSR;
+		/* 26, 15, 14, 6, 5
+		 * A_PWRDN  DA_DPM DA_SBR DA_IOM_DA
+		 * DA_APP(parallel) */
+		break;
+
+	case BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE:
+		card->gpio_mode = 0x0400c060;
+		card->op_sync_orin = BT878_RISC_SYNC_MASK;
+		card->irq_err_ignore = BT878_AFBUS | BT878_AFDSR;
+		break;
+
+	case BTTV_BOARD_NEBULA_DIGITV:
+	case BTTV_BOARD_AVDVBT_761:
+		card->gpio_mode = (1 << 26) | (1 << 14) | (1 << 5);
+		card->op_sync_orin = BT878_RISC_SYNC_MASK;
+		card->irq_err_ignore = BT878_AFBUS | BT878_AFDSR;
+		/* A_PWRDN DA_SBR DA_APP (high speed serial) */
+		break;
+
+	case BTTV_BOARD_AVDVBT_771: //case 0x07711461:
+		card->gpio_mode = 0x0400402B;
+		card->op_sync_orin = BT878_RISC_SYNC_MASK;
+		card->irq_err_ignore = BT878_AFBUS | BT878_AFDSR;
+		/* A_PWRDN DA_SBR  DA_APP[0] PKTP=10 RISC_ENABLE FIFO_ENABLE*/
+		break;
+
+	case BTTV_BOARD_TWINHAN_DST:
+		card->gpio_mode = 0x2204f2c;
+		card->op_sync_orin = BT878_RISC_SYNC_MASK;
+		card->irq_err_ignore = BT878_APABORT | BT878_ARIPERR |
+				       BT878_APPERR | BT878_AFBUS;
+		/* 25,21,14,11,10,9,8,3,2 then
+		 * 0x33 = 5,4,1,0
+		 * A_SEL=SML, DA_MLB, DA_SBR,
+		 * DA_SDR=f, fifo trigger = 32 DWORDS
+		 * IOM = 0 == audio A/D
+		 * DPM = 0 == digital audio mode
+		 * == async data parallel port
+		 * then 0x33 (13 is set by start_capture)
+		 * DA_APP = async data parallel port,
+		 * ACAP_EN = 1,
+		 * RISC+FIFO ENABLE */
+		break;
+
+	case BTTV_BOARD_PC_HDTV:
+		card->gpio_mode = 0x0100EC7B;
+		card->op_sync_orin = BT878_RISC_SYNC_MASK;
+		card->irq_err_ignore = BT878_AFBUS | BT878_AFDSR;
+		break;
+
+	default:
+		pr_err("Unknown bttv card type: %d\n", sub->core->type);
+		kfree(card);
+		return -ENODEV;
+	}
+
+	dprintk("dvb_bt8xx: identified card%d as %s\n", card->bttv_nr, card->card_name);
+
+	if (!(bttv_pci_dev = bttv_get_pcidev(card->bttv_nr))) {
+		pr_err("no pci device for card %d\n", card->bttv_nr);
+		kfree(card);
+		return -ENODEV;
+	}
+
+	if (!(card->bt = dvb_bt8xx_878_match(card->bttv_nr, bttv_pci_dev))) {
+		pr_err("unable to determine DMA core of card %d,\n", card->bttv_nr);
+		pr_err("if you have the ALSA bt87x audio driver installed, try removing it.\n");
+
+		kfree(card);
+		return -ENODEV;
+	}
+
+	mutex_init(&card->bt->gpio_lock);
+	card->bt->bttv_nr = sub->core->nr;
+
+	if ( (ret = dvb_bt8xx_load_card(card, sub->core->type)) ) {
+		kfree(card);
+		return ret;
+	}
+
+	dev_set_drvdata(&sub->dev, card);
+	return 0;
+}
+
+static void dvb_bt8xx_remove(struct bttv_sub_device *sub)
+{
+	struct dvb_bt8xx_card *card = dev_get_drvdata(&sub->dev);
+
+	dprintk("dvb_bt8xx: unloading card%d\n", card->bttv_nr);
+
+	bt878_stop(card->bt);
+	tasklet_kill(&card->bt->tasklet);
+	dvb_net_release(&card->dvbnet);
+	card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_mem);
+	card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_hw);
+	dvb_dmxdev_release(&card->dmxdev);
+	dvb_dmx_release(&card->demux);
+	if (card->fe) {
+		dvb_unregister_frontend(card->fe);
+		dvb_frontend_detach(card->fe);
+	}
+	dvb_unregister_adapter(&card->dvb_adapter);
+
+	kfree(card);
+}
+
+static struct bttv_sub_driver driver = {
+	.drv = {
+		.name		= "dvb-bt8xx",
+	},
+	.probe		= dvb_bt8xx_probe,
+	.remove		= dvb_bt8xx_remove,
+	/* FIXME:
+	 * .shutdown	= dvb_bt8xx_shutdown,
+	 * .suspend	= dvb_bt8xx_suspend,
+	 * .resume	= dvb_bt8xx_resume,
+	 */
+};
+
+static int __init dvb_bt8xx_init(void)
+{
+	return bttv_sub_register(&driver, "dvb");
+}
+
+static void __exit dvb_bt8xx_exit(void)
+{
+	bttv_sub_unregister(&driver);
+}
+
+module_init(dvb_bt8xx_init);
+module_exit(dvb_bt8xx_exit);
+
+MODULE_DESCRIPTION("Bt8xx based DVB adapter driver");
+MODULE_AUTHOR("Florian Schirmer <jolt@tuxbox.org>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/pci/bt8xx/dvb-bt8xx.h b/drivers/media/pci/bt8xx/dvb-bt8xx.h
new file mode 100644
index 0000000..4499ed2
--- /dev/null
+++ b/drivers/media/pci/bt8xx/dvb-bt8xx.h
@@ -0,0 +1,63 @@
+/*
+ * Bt8xx based DVB adapter driver
+ *
+ * Copyright (C) 2002,2003 Florian Schirmer <jolt@tuxbox.org>
+ * Copyright (C) 2002 Peter Hettkamp <peter.hettkamp@htp-tel.de>
+ * Copyright (C) 1999-2001 Ralph  Metzler & Marcus Metzler for convergence integrated media GmbH
+ * Copyright (C) 1998,1999 Christian Theiss <mistert@rz.fh-augsburg.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 DVB_BT8XX_H
+#define DVB_BT8XX_H
+
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+#include "dvbdev.h"
+#include "dvb_net.h"
+#include "bttv.h"
+#include "mt352.h"
+#include "sp887x.h"
+#include "dst_common.h"
+#include "nxt6000.h"
+#include "cx24110.h"
+#include "or51211.h"
+#include "lgdt330x.h"
+#include "zl10353.h"
+#include "tuner-simple.h"
+
+struct dvb_bt8xx_card {
+	struct mutex lock;
+	int nfeeds;
+	char card_name[32];
+	struct dvb_adapter dvb_adapter;
+	struct bt878 *bt;
+	unsigned int bttv_nr;
+	struct dvb_demux demux;
+	struct dmxdev dmxdev;
+	struct dmx_frontend fe_hw;
+	struct dmx_frontend fe_mem;
+	u32 gpio_mode;
+	u32 op_sync_orin;
+	u32 irq_err_ignore;
+	struct i2c_adapter *i2c_adapter;
+	struct dvb_net dvbnet;
+
+	struct dvb_frontend* fe;
+};
+
+#endif /* DVB_BT8XX_H */
diff --git a/drivers/media/pci/cx18/Kconfig b/drivers/media/pci/cx18/Kconfig
new file mode 100644
index 0000000..9a9f765
--- /dev/null
+++ b/drivers/media/pci/cx18/Kconfig
@@ -0,0 +1,35 @@
+config VIDEO_CX18
+	tristate "Conexant cx23418 MPEG encoder support"
+	depends on VIDEO_V4L2 && DVB_CORE && PCI && I2C && EXPERIMENTAL
+	select I2C_ALGOBIT
+	select VIDEOBUF_VMALLOC
+	depends on RC_CORE
+	select VIDEO_TUNER
+	select VIDEO_TVEEPROM
+	select VIDEO_CX2341X
+	select VIDEO_CS5345
+	select DVB_S5H1409 if MEDIA_SUBDRV_AUTOSELECT
+	select MEDIA_TUNER_MXL5005S if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_S5H1411 if MEDIA_SUBDRV_AUTOSELECT
+	select MEDIA_TUNER_TDA18271 if MEDIA_SUBDRV_AUTOSELECT
+	select MEDIA_TUNER_TDA8290 if MEDIA_SUBDRV_AUTOSELECT
+	---help---
+	  This is a video4linux driver for Conexant cx23418 based
+	  PCI combo video recorder devices.
+
+	  This is used in devices such as the Hauppauge HVR-1600
+	  cards.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called cx18.
+
+config VIDEO_CX18_ALSA
+	tristate "Conexant 23418 DMA audio support"
+	depends on VIDEO_CX18 && SND && EXPERIMENTAL
+	select SND_PCM
+	---help---
+	  This is a video4linux driver for direct (DMA) audio on
+	  Conexant 23418 based TV cards using ALSA.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called cx18-alsa.
diff --git a/drivers/media/pci/cx18/Makefile b/drivers/media/pci/cx18/Makefile
new file mode 100644
index 0000000..d3ff154
--- /dev/null
+++ b/drivers/media/pci/cx18/Makefile
@@ -0,0 +1,13 @@
+cx18-objs    := cx18-driver.o cx18-cards.o cx18-i2c.o cx18-firmware.o cx18-gpio.o \
+	cx18-queue.o cx18-streams.o cx18-fileops.o cx18-ioctl.o cx18-controls.o \
+	cx18-mailbox.o cx18-vbi.o cx18-audio.o cx18-video.o cx18-irq.o \
+	cx18-av-core.o cx18-av-audio.o cx18-av-firmware.o cx18-av-vbi.o cx18-scb.o \
+	cx18-dvb.o cx18-io.o
+cx18-alsa-objs := cx18-alsa-main.o cx18-alsa-pcm.o
+
+obj-$(CONFIG_VIDEO_CX18) += cx18.o
+obj-$(CONFIG_VIDEO_CX18_ALSA) += cx18-alsa.o
+
+ccflags-y += -Idrivers/media/dvb-core
+ccflags-y += -Idrivers/media/dvb-frontends
+ccflags-y += -Idrivers/media/tuners
diff --git a/drivers/media/pci/cx18/cx18-alsa-main.c b/drivers/media/pci/cx18/cx18-alsa-main.c
new file mode 100644
index 0000000..6d2a982
--- /dev/null
+++ b/drivers/media/pci/cx18/cx18-alsa-main.c
@@ -0,0 +1,295 @@
+/*
+ *  ALSA interface to cx18 PCM capture streams
+ *
+ *  Copyright (C) 2009  Andy Walls <awalls@md.metrocast.net>
+ *  Copyright (C) 2009  Devin Heitmueller <dheitmueller@kernellabs.com>
+ *
+ *  Portions of this work were sponsored by ONELAN Limited.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307  USA
+ */
+
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/spinlock.h>
+
+#include <media/v4l2-device.h>
+
+#include <sound/core.h>
+#include <sound/initval.h>
+
+#include "cx18-driver.h"
+#include "cx18-version.h"
+#include "cx18-alsa.h"
+#include "cx18-alsa-mixer.h"
+#include "cx18-alsa-pcm.h"
+
+int cx18_alsa_debug;
+
+#define CX18_DEBUG_ALSA_INFO(fmt, arg...) \
+	do { \
+		if (cx18_alsa_debug & 2) \
+			printk(KERN_INFO "%s: " fmt, "cx18-alsa", ## arg); \
+	} while (0);
+
+module_param_named(debug, cx18_alsa_debug, int, 0644);
+MODULE_PARM_DESC(debug,
+		 "Debug level (bitmask). Default: 0\n"
+		 "\t\t\t  1/0x0001: warning\n"
+		 "\t\t\t  2/0x0002: info\n");
+
+MODULE_AUTHOR("Andy Walls");
+MODULE_DESCRIPTION("CX23418 ALSA Interface");
+MODULE_SUPPORTED_DEVICE("CX23418 MPEG2 encoder");
+MODULE_LICENSE("GPL");
+
+MODULE_VERSION(CX18_VERSION);
+
+static inline
+struct snd_cx18_card *to_snd_cx18_card(struct v4l2_device *v4l2_dev)
+{
+	return to_cx18(v4l2_dev)->alsa;
+}
+
+static inline
+struct snd_cx18_card *p_to_snd_cx18_card(struct v4l2_device **v4l2_dev)
+{
+	return container_of(v4l2_dev, struct snd_cx18_card, v4l2_dev);
+}
+
+static void snd_cx18_card_free(struct snd_cx18_card *cxsc)
+{
+	if (cxsc == NULL)
+		return;
+
+	if (cxsc->v4l2_dev != NULL)
+		to_cx18(cxsc->v4l2_dev)->alsa = NULL;
+
+	/* FIXME - take any other stopping actions needed */
+
+	kfree(cxsc);
+}
+
+static void snd_cx18_card_private_free(struct snd_card *sc)
+{
+	if (sc == NULL)
+		return;
+	snd_cx18_card_free(sc->private_data);
+	sc->private_data = NULL;
+	sc->private_free = NULL;
+}
+
+static int snd_cx18_card_create(struct v4l2_device *v4l2_dev,
+				       struct snd_card *sc,
+				       struct snd_cx18_card **cxsc)
+{
+	*cxsc = kzalloc(sizeof(struct snd_cx18_card), GFP_KERNEL);
+	if (*cxsc == NULL)
+		return -ENOMEM;
+
+	(*cxsc)->v4l2_dev = v4l2_dev;
+	(*cxsc)->sc = sc;
+
+	sc->private_data = *cxsc;
+	sc->private_free = snd_cx18_card_private_free;
+
+	return 0;
+}
+
+static int snd_cx18_card_set_names(struct snd_cx18_card *cxsc)
+{
+	struct cx18 *cx = to_cx18(cxsc->v4l2_dev);
+	struct snd_card *sc = cxsc->sc;
+
+	/* sc->driver is used by alsa-lib's configurator: simple, unique */
+	strlcpy(sc->driver, "CX23418", sizeof(sc->driver));
+
+	/* sc->shortname is a symlink in /proc/asound: CX18-M -> cardN */
+	snprintf(sc->shortname,  sizeof(sc->shortname), "CX18-%d",
+		 cx->instance);
+
+	/* sc->longname is read from /proc/asound/cards */
+	snprintf(sc->longname, sizeof(sc->longname),
+		 "CX23418 #%d %s TV/FM Radio/Line-In Capture",
+		 cx->instance, cx->card_name);
+
+	return 0;
+}
+
+static int snd_cx18_init(struct v4l2_device *v4l2_dev)
+{
+	struct cx18 *cx = to_cx18(v4l2_dev);
+	struct snd_card *sc = NULL;
+	struct snd_cx18_card *cxsc;
+	int ret;
+
+	/* Numbrs steps from "Writing an ALSA Driver" by Takashi Iwai */
+
+	/* (1) Check and increment the device index */
+	/* This is a no-op for us.  We'll use the cx->instance */
+
+	/* (2) Create a card instance */
+	ret = snd_card_create(SNDRV_DEFAULT_IDX1, /* use first available id */
+			      SNDRV_DEFAULT_STR1, /* xid from end of shortname*/
+			      THIS_MODULE, 0, &sc);
+	if (ret) {
+		CX18_ALSA_ERR("%s: snd_card_create() failed with err %d\n",
+			      __func__, ret);
+		goto err_exit;
+	}
+
+	/* (3) Create a main component */
+	ret = snd_cx18_card_create(v4l2_dev, sc, &cxsc);
+	if (ret) {
+		CX18_ALSA_ERR("%s: snd_cx18_card_create() failed with err %d\n",
+			      __func__, ret);
+		goto err_exit_free;
+	}
+
+	/* (4) Set the driver ID and name strings */
+	snd_cx18_card_set_names(cxsc);
+
+
+	ret = snd_cx18_pcm_create(cxsc);
+	if (ret) {
+		CX18_ALSA_ERR("%s: snd_cx18_pcm_create() failed with err %d\n",
+			      __func__, ret);
+		goto err_exit_free;
+	}
+	/* FIXME - proc files */
+
+	/* (7) Set the driver data and return 0 */
+	/* We do this out of normal order for PCI drivers to avoid races */
+	cx->alsa = cxsc;
+
+	/* (6) Register the card instance */
+	ret = snd_card_register(sc);
+	if (ret) {
+		cx->alsa = NULL;
+		CX18_ALSA_ERR("%s: snd_card_register() failed with err %d\n",
+			      __func__, ret);
+		goto err_exit_free;
+	}
+
+	return 0;
+
+err_exit_free:
+	if (sc != NULL)
+		snd_card_free(sc);
+	kfree(cxsc);
+err_exit:
+	return ret;
+}
+
+int cx18_alsa_load(struct cx18 *cx)
+{
+	struct v4l2_device *v4l2_dev = &cx->v4l2_dev;
+	struct cx18_stream *s;
+
+	if (v4l2_dev == NULL) {
+		printk(KERN_ERR "cx18-alsa: %s: struct v4l2_device * is NULL\n",
+		       __func__);
+		return 0;
+	}
+
+	cx = to_cx18(v4l2_dev);
+	if (cx == NULL) {
+		printk(KERN_ERR "cx18-alsa cx is NULL\n");
+		return 0;
+	}
+
+	s = &cx->streams[CX18_ENC_STREAM_TYPE_PCM];
+	if (s->video_dev == NULL) {
+		CX18_DEBUG_ALSA_INFO("%s: PCM stream for card is disabled - "
+				     "skipping\n", __func__);
+		return 0;
+	}
+
+	if (cx->alsa != NULL) {
+		CX18_ALSA_ERR("%s: struct snd_cx18_card * already exists\n",
+			      __func__);
+		return 0;
+	}
+
+	if (snd_cx18_init(v4l2_dev)) {
+		CX18_ALSA_ERR("%s: failed to create struct snd_cx18_card\n",
+			      __func__);
+	} else {
+		CX18_DEBUG_ALSA_INFO("%s: created cx18 ALSA interface instance "
+				     "\n", __func__);
+	}
+	return 0;
+}
+
+static int __init cx18_alsa_init(void)
+{
+	printk(KERN_INFO "cx18-alsa: module loading...\n");
+	cx18_ext_init = &cx18_alsa_load;
+	return 0;
+}
+
+static void __exit snd_cx18_exit(struct snd_cx18_card *cxsc)
+{
+	struct cx18 *cx = to_cx18(cxsc->v4l2_dev);
+
+	/* FIXME - pointer checks & shutdown cxsc */
+
+	snd_card_free(cxsc->sc);
+	cx->alsa = NULL;
+}
+
+static int __exit cx18_alsa_exit_callback(struct device *dev, void *data)
+{
+	struct v4l2_device *v4l2_dev = dev_get_drvdata(dev);
+	struct snd_cx18_card *cxsc;
+
+	if (v4l2_dev == NULL) {
+		printk(KERN_ERR "cx18-alsa: %s: struct v4l2_device * is NULL\n",
+		       __func__);
+		return 0;
+	}
+
+	cxsc = to_snd_cx18_card(v4l2_dev);
+	if (cxsc == NULL) {
+		CX18_ALSA_WARN("%s: struct snd_cx18_card * is NULL\n",
+			       __func__);
+		return 0;
+	}
+
+	snd_cx18_exit(cxsc);
+	return 0;
+}
+
+static void __exit cx18_alsa_exit(void)
+{
+	struct device_driver *drv;
+	int ret;
+
+	printk(KERN_INFO "cx18-alsa: module unloading...\n");
+
+	drv = driver_find("cx18", &pci_bus_type);
+	ret = driver_for_each_device(drv, NULL, NULL, cx18_alsa_exit_callback);
+	(void)ret;	/* suppress compiler warning */
+
+	cx18_ext_init = NULL;
+	printk(KERN_INFO "cx18-alsa: module unload complete\n");
+}
+
+module_init(cx18_alsa_init);
+module_exit(cx18_alsa_exit);
diff --git a/drivers/media/pci/cx18/cx18-alsa-mixer.c b/drivers/media/pci/cx18/cx18-alsa-mixer.c
new file mode 100644
index 0000000..341bddc
--- /dev/null
+++ b/drivers/media/pci/cx18/cx18-alsa-mixer.c
@@ -0,0 +1,175 @@
+/*
+ *  ALSA mixer controls for the
+ *  ALSA interface to cx18 PCM capture streams
+ *
+ *  Copyright (C) 2009  Andy Walls <awalls@md.metrocast.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 program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307  USA
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/spinlock.h>
+#include <linux/videodev2.h>
+
+#include <media/v4l2-device.h>
+
+#include <sound/core.h>
+#include <sound/control.h>
+#include <sound/tlv.h>
+
+#include "cx18-alsa.h"
+#include "cx18-driver.h"
+
+/*
+ * Note the cx18-av-core volume scale is funny, due to the alignment of the
+ * scale with another chip's range:
+ *
+ * v4l2_control value	/512	indicated dB	actual dB	reg 0x8d4
+ * 0x0000 - 0x01ff	  0	-119		-96		228
+ * 0x0200 - 0x02ff	  1	-118		-96		228
+ * ...
+ * 0x2c00 - 0x2dff	 22	 -97		-96		228
+ * 0x2e00 - 0x2fff	 23	 -96		-96		228
+ * 0x3000 - 0x31ff	 24	 -95		-95		226
+ * ...
+ * 0xee00 - 0xefff	119	   0		  0		 36
+ * ...
+ * 0xfe00 - 0xffff	127	  +8		 +8		 20
+ */
+static inline int dB_to_cx18_av_vol(int dB)
+{
+	if (dB < -96)
+		dB = -96;
+	else if (dB > 8)
+		dB = 8;
+	return (dB + 119) << 9;
+}
+
+static inline int cx18_av_vol_to_dB(int v)
+{
+	if (v < (23 << 9))
+		v = (23 << 9);
+	else if (v > (127 << 9))
+		v = (127 << 9);
+	return (v >> 9) - 119;
+}
+
+static int snd_cx18_mixer_tv_vol_info(struct snd_kcontrol *kcontrol,
+				      struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 1;
+	/* We're already translating values, just keep this control in dB */
+	uinfo->value.integer.min  = -96;
+	uinfo->value.integer.max  =   8;
+	uinfo->value.integer.step =   1;
+	return 0;
+}
+
+static int snd_cx18_mixer_tv_vol_get(struct snd_kcontrol *kctl,
+				     struct snd_ctl_elem_value *uctl)
+{
+	struct snd_cx18_card *cxsc = snd_kcontrol_chip(kctl);
+	struct cx18 *cx = to_cx18(cxsc->v4l2_dev);
+	struct v4l2_control vctrl;
+	int ret;
+
+	vctrl.id = V4L2_CID_AUDIO_VOLUME;
+	vctrl.value = dB_to_cx18_av_vol(uctl->value.integer.value[0]);
+
+	snd_cx18_lock(cxsc);
+	ret = v4l2_subdev_call(cx->sd_av, core, g_ctrl, &vctrl);
+	snd_cx18_unlock(cxsc);
+
+	if (!ret)
+		uctl->value.integer.value[0] = cx18_av_vol_to_dB(vctrl.value);
+	return ret;
+}
+
+static int snd_cx18_mixer_tv_vol_put(struct snd_kcontrol *kctl,
+				     struct snd_ctl_elem_value *uctl)
+{
+	struct snd_cx18_card *cxsc = snd_kcontrol_chip(kctl);
+	struct cx18 *cx = to_cx18(cxsc->v4l2_dev);
+	struct v4l2_control vctrl;
+	int ret;
+
+	vctrl.id = V4L2_CID_AUDIO_VOLUME;
+	vctrl.value = dB_to_cx18_av_vol(uctl->value.integer.value[0]);
+
+	snd_cx18_lock(cxsc);
+
+	/* Fetch current state */
+	ret = v4l2_subdev_call(cx->sd_av, core, g_ctrl, &vctrl);
+
+	if (ret ||
+	    (cx18_av_vol_to_dB(vctrl.value) != uctl->value.integer.value[0])) {
+
+		/* Set, if needed */
+		vctrl.value = dB_to_cx18_av_vol(uctl->value.integer.value[0]);
+		ret = v4l2_subdev_call(cx->sd_av, core, s_ctrl, &vctrl);
+		if (!ret)
+			ret = 1; /* Indicate control was changed w/o error */
+	}
+	snd_cx18_unlock(cxsc);
+
+	return ret;
+}
+
+
+/* This is a bit of overkill, the slider is already in dB internally */
+static DECLARE_TLV_DB_SCALE(snd_cx18_mixer_tv_vol_db_scale, -9600, 100, 0);
+
+static struct snd_kcontrol_new snd_cx18_mixer_tv_vol __initdata = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "Analog TV Capture Volume",
+	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
+		  SNDRV_CTL_ELEM_ACCESS_TLV_READ,
+	.info = snd_cx18_mixer_tv_volume_info,
+	.get = snd_cx18_mixer_tv_volume_get,
+	.put = snd_cx18_mixer_tv_volume_put,
+	.tlv.p = snd_cx18_mixer_tv_vol_db_scale
+};
+
+/* FIXME - add mute switch and balance, bass, treble sliders:
+	V4L2_CID_AUDIO_MUTE
+
+	V4L2_CID_AUDIO_BALANCE
+
+	V4L2_CID_AUDIO_BASS
+	V4L2_CID_AUDIO_TREBLE
+*/
+
+/* FIXME - add stereo, lang1, lang2, mono menu */
+/* FIXME - add CS5345 I2S volume for HVR-1600 */
+
+int __init snd_cx18_mixer_create(struct snd_cx18_card *cxsc)
+{
+	struct v4l2_device *v4l2_dev = cxsc->v4l2_dev;
+	struct snd_card *sc = cxsc->sc;
+	int ret;
+
+	strlcpy(sc->mixername, "CX23418 Mixer", sizeof(sc->mixername));
+
+	ret = snd_ctl_add(sc, snd_ctl_new1(snd_cx18_mixer_tv_vol, cxsc));
+	if (ret) {
+		CX18_ALSA_WARN("%s: failed to add %s control, err %d\n",
+				__func__, snd_cx18_mixer_tv_vol.name, ret);
+	}
+	return ret;
+}
diff --git a/drivers/media/pci/cx18/cx18-alsa-mixer.h b/drivers/media/pci/cx18/cx18-alsa-mixer.h
new file mode 100644
index 0000000..ec92387
--- /dev/null
+++ b/drivers/media/pci/cx18/cx18-alsa-mixer.h
@@ -0,0 +1,23 @@
+/*
+ *  ALSA mixer controls for the
+ *  ALSA interface to cx18 PCM capture streams
+ *
+ *  Copyright (C) 2009  Andy Walls <awalls@md.metrocast.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 program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307  USA
+ */
+
+int __init snd_cx18_mixer_create(struct snd_cx18_card *cxsc);
diff --git a/drivers/media/pci/cx18/cx18-alsa-pcm.c b/drivers/media/pci/cx18/cx18-alsa-pcm.c
new file mode 100644
index 0000000..7a5b84a
--- /dev/null
+++ b/drivers/media/pci/cx18/cx18-alsa-pcm.c
@@ -0,0 +1,356 @@
+/*
+ *  ALSA PCM device for the
+ *  ALSA interface to cx18 PCM capture streams
+ *
+ *  Copyright (C) 2009  Andy Walls <awalls@md.metrocast.net>
+ *  Copyright (C) 2009  Devin Heitmueller <dheitmueller@kernellabs.com>
+ *
+ *  Portions of this work were sponsored by ONELAN Limited.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307  USA
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/vmalloc.h>
+
+#include <media/v4l2-device.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+
+#include "cx18-driver.h"
+#include "cx18-queue.h"
+#include "cx18-streams.h"
+#include "cx18-fileops.h"
+#include "cx18-alsa.h"
+
+static unsigned int pcm_debug;
+module_param(pcm_debug, int, 0644);
+MODULE_PARM_DESC(pcm_debug, "enable debug messages for pcm");
+
+#define dprintk(fmt, arg...) do {					\
+	    if (pcm_debug)						\
+		printk(KERN_INFO "cx18-alsa-pcm %s: " fmt,		\
+				  __func__, ##arg); 			\
+	} while (0)
+
+static struct snd_pcm_hardware snd_cx18_hw_capture = {
+	.info = SNDRV_PCM_INFO_BLOCK_TRANSFER |
+		SNDRV_PCM_INFO_MMAP           |
+		SNDRV_PCM_INFO_INTERLEAVED    |
+		SNDRV_PCM_INFO_MMAP_VALID,
+
+	.formats = SNDRV_PCM_FMTBIT_S16_LE,
+
+	.rates = SNDRV_PCM_RATE_48000,
+
+	.rate_min = 48000,
+	.rate_max = 48000,
+	.channels_min = 2,
+	.channels_max = 2,
+	.buffer_bytes_max = 62720 * 8,	/* just about the value in usbaudio.c */
+	.period_bytes_min = 64,		/* 12544/2, */
+	.period_bytes_max = 12544,
+	.periods_min = 2,
+	.periods_max = 98,		/* 12544, */
+};
+
+void cx18_alsa_announce_pcm_data(struct snd_cx18_card *cxsc, u8 *pcm_data,
+				 size_t num_bytes)
+{
+	struct snd_pcm_substream *substream;
+	struct snd_pcm_runtime *runtime;
+	unsigned int oldptr;
+	unsigned int stride;
+	int period_elapsed = 0;
+	int length;
+
+	dprintk("cx18 alsa announce ptr=%p data=%p num_bytes=%zd\n", cxsc,
+		pcm_data, num_bytes);
+
+	substream = cxsc->capture_pcm_substream;
+	if (substream == NULL) {
+		dprintk("substream was NULL\n");
+		return;
+	}
+
+	runtime = substream->runtime;
+	if (runtime == NULL) {
+		dprintk("runtime was NULL\n");
+		return;
+	}
+
+	stride = runtime->frame_bits >> 3;
+	if (stride == 0) {
+		dprintk("stride is zero\n");
+		return;
+	}
+
+	length = num_bytes / stride;
+	if (length == 0) {
+		dprintk("%s: length was zero\n", __func__);
+		return;
+	}
+
+	if (runtime->dma_area == NULL) {
+		dprintk("dma area was NULL - ignoring\n");
+		return;
+	}
+
+	oldptr = cxsc->hwptr_done_capture;
+	if (oldptr + length >= runtime->buffer_size) {
+		unsigned int cnt =
+			runtime->buffer_size - oldptr;
+		memcpy(runtime->dma_area + oldptr * stride, pcm_data,
+		       cnt * stride);
+		memcpy(runtime->dma_area, pcm_data + cnt * stride,
+		       length * stride - cnt * stride);
+	} else {
+		memcpy(runtime->dma_area + oldptr * stride, pcm_data,
+		       length * stride);
+	}
+	snd_pcm_stream_lock(substream);
+
+	cxsc->hwptr_done_capture += length;
+	if (cxsc->hwptr_done_capture >=
+	    runtime->buffer_size)
+		cxsc->hwptr_done_capture -=
+			runtime->buffer_size;
+
+	cxsc->capture_transfer_done += length;
+	if (cxsc->capture_transfer_done >=
+	    runtime->period_size) {
+		cxsc->capture_transfer_done -=
+			runtime->period_size;
+		period_elapsed = 1;
+	}
+
+	snd_pcm_stream_unlock(substream);
+
+	if (period_elapsed)
+		snd_pcm_period_elapsed(substream);
+}
+
+static int snd_cx18_pcm_capture_open(struct snd_pcm_substream *substream)
+{
+	struct snd_cx18_card *cxsc = snd_pcm_substream_chip(substream);
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct v4l2_device *v4l2_dev = cxsc->v4l2_dev;
+	struct cx18 *cx = to_cx18(v4l2_dev);
+	struct cx18_stream *s;
+	struct cx18_open_id item;
+	int ret;
+
+	/* Instruct the cx18 to start sending packets */
+	snd_cx18_lock(cxsc);
+	s = &cx->streams[CX18_ENC_STREAM_TYPE_PCM];
+
+	item.cx = cx;
+	item.type = s->type;
+	item.open_id = cx->open_id++;
+
+	/* See if the stream is available */
+	if (cx18_claim_stream(&item, item.type)) {
+		/* No, it's already in use */
+		snd_cx18_unlock(cxsc);
+		return -EBUSY;
+	}
+
+	if (test_bit(CX18_F_S_STREAMOFF, &s->s_flags) ||
+	    test_and_set_bit(CX18_F_S_STREAMING, &s->s_flags)) {
+		/* We're already streaming.  No additional action required */
+		snd_cx18_unlock(cxsc);
+		return 0;
+	}
+
+
+	runtime->hw = snd_cx18_hw_capture;
+	snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
+	cxsc->capture_pcm_substream = substream;
+	runtime->private_data = cx;
+
+	cx->pcm_announce_callback = cx18_alsa_announce_pcm_data;
+
+	/* Not currently streaming, so start it up */
+	set_bit(CX18_F_S_STREAMING, &s->s_flags);
+	ret = cx18_start_v4l2_encode_stream(s);
+	snd_cx18_unlock(cxsc);
+
+	return ret;
+}
+
+static int snd_cx18_pcm_capture_close(struct snd_pcm_substream *substream)
+{
+	struct snd_cx18_card *cxsc = snd_pcm_substream_chip(substream);
+	struct v4l2_device *v4l2_dev = cxsc->v4l2_dev;
+	struct cx18 *cx = to_cx18(v4l2_dev);
+	struct cx18_stream *s;
+
+	/* Instruct the cx18 to stop sending packets */
+	snd_cx18_lock(cxsc);
+	s = &cx->streams[CX18_ENC_STREAM_TYPE_PCM];
+	cx18_stop_v4l2_encode_stream(s, 0);
+	clear_bit(CX18_F_S_STREAMING, &s->s_flags);
+
+	cx18_release_stream(s);
+
+	cx->pcm_announce_callback = NULL;
+	snd_cx18_unlock(cxsc);
+
+	return 0;
+}
+
+static int snd_cx18_pcm_ioctl(struct snd_pcm_substream *substream,
+		     unsigned int cmd, void *arg)
+{
+	struct snd_cx18_card *cxsc = snd_pcm_substream_chip(substream);
+	int ret;
+
+	snd_cx18_lock(cxsc);
+	ret = snd_pcm_lib_ioctl(substream, cmd, arg);
+	snd_cx18_unlock(cxsc);
+	return ret;
+}
+
+
+static int snd_pcm_alloc_vmalloc_buffer(struct snd_pcm_substream *subs,
+					size_t size)
+{
+	struct snd_pcm_runtime *runtime = subs->runtime;
+
+	dprintk("Allocating vbuffer\n");
+	if (runtime->dma_area) {
+		if (runtime->dma_bytes > size)
+			return 0;
+
+		vfree(runtime->dma_area);
+	}
+	runtime->dma_area = vmalloc(size);
+	if (!runtime->dma_area)
+		return -ENOMEM;
+
+	runtime->dma_bytes = size;
+
+	return 0;
+}
+
+static int snd_cx18_pcm_hw_params(struct snd_pcm_substream *substream,
+			 struct snd_pcm_hw_params *params)
+{
+	dprintk("%s called\n", __func__);
+
+	return snd_pcm_alloc_vmalloc_buffer(substream,
+					   params_buffer_bytes(params));
+}
+
+static int snd_cx18_pcm_hw_free(struct snd_pcm_substream *substream)
+{
+	struct snd_cx18_card *cxsc = snd_pcm_substream_chip(substream);
+	unsigned long flags;
+
+	spin_lock_irqsave(&cxsc->slock, flags);
+	if (substream->runtime->dma_area) {
+		dprintk("freeing pcm capture region\n");
+		vfree(substream->runtime->dma_area);
+		substream->runtime->dma_area = NULL;
+	}
+	spin_unlock_irqrestore(&cxsc->slock, flags);
+
+	return 0;
+}
+
+static int snd_cx18_pcm_prepare(struct snd_pcm_substream *substream)
+{
+	struct snd_cx18_card *cxsc = snd_pcm_substream_chip(substream);
+
+	cxsc->hwptr_done_capture = 0;
+	cxsc->capture_transfer_done = 0;
+
+	return 0;
+}
+
+static int snd_cx18_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+	return 0;
+}
+
+static
+snd_pcm_uframes_t snd_cx18_pcm_pointer(struct snd_pcm_substream *substream)
+{
+	unsigned long flags;
+	snd_pcm_uframes_t hwptr_done;
+	struct snd_cx18_card *cxsc = snd_pcm_substream_chip(substream);
+
+	spin_lock_irqsave(&cxsc->slock, flags);
+	hwptr_done = cxsc->hwptr_done_capture;
+	spin_unlock_irqrestore(&cxsc->slock, flags);
+
+	return hwptr_done;
+}
+
+static struct page *snd_pcm_get_vmalloc_page(struct snd_pcm_substream *subs,
+					     unsigned long offset)
+{
+	void *pageptr = subs->runtime->dma_area + offset;
+
+	return vmalloc_to_page(pageptr);
+}
+
+static struct snd_pcm_ops snd_cx18_pcm_capture_ops = {
+	.open		= snd_cx18_pcm_capture_open,
+	.close		= snd_cx18_pcm_capture_close,
+	.ioctl		= snd_cx18_pcm_ioctl,
+	.hw_params	= snd_cx18_pcm_hw_params,
+	.hw_free	= snd_cx18_pcm_hw_free,
+	.prepare	= snd_cx18_pcm_prepare,
+	.trigger	= snd_cx18_pcm_trigger,
+	.pointer	= snd_cx18_pcm_pointer,
+	.page		= snd_pcm_get_vmalloc_page,
+};
+
+int snd_cx18_pcm_create(struct snd_cx18_card *cxsc)
+{
+	struct snd_pcm *sp;
+	struct snd_card *sc = cxsc->sc;
+	struct v4l2_device *v4l2_dev = cxsc->v4l2_dev;
+	struct cx18 *cx = to_cx18(v4l2_dev);
+	int ret;
+
+	ret = snd_pcm_new(sc, "CX23418 PCM",
+			  0, /* PCM device 0, the only one for this card */
+			  0, /* 0 playback substreams */
+			  1, /* 1 capture substream */
+			  &sp);
+	if (ret) {
+		CX18_ALSA_ERR("%s: snd_cx18_pcm_create() failed with err %d\n",
+			      __func__, ret);
+		goto err_exit;
+	}
+
+	spin_lock_init(&cxsc->slock);
+
+	snd_pcm_set_ops(sp, SNDRV_PCM_STREAM_CAPTURE,
+			&snd_cx18_pcm_capture_ops);
+	sp->info_flags = 0;
+	sp->private_data = cxsc;
+	strlcpy(sp->name, cx->card_name, sizeof(sp->name));
+
+	return 0;
+
+err_exit:
+	return ret;
+}
diff --git a/drivers/media/pci/cx18/cx18-alsa-pcm.h b/drivers/media/pci/cx18/cx18-alsa-pcm.h
new file mode 100644
index 0000000..d26e51f
--- /dev/null
+++ b/drivers/media/pci/cx18/cx18-alsa-pcm.h
@@ -0,0 +1,27 @@
+/*
+ *  ALSA PCM device for the
+ *  ALSA interface to cx18 PCM capture streams
+ *
+ *  Copyright (C) 2009  Andy Walls <awalls@md.metrocast.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 program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307  USA
+ */
+
+int __init snd_cx18_pcm_create(struct snd_cx18_card *cxsc);
+
+/* Used by cx18-mailbox to announce the PCM data to the module */
+void cx18_alsa_announce_pcm_data(struct snd_cx18_card *card, u8 *pcm_data,
+				 size_t num_bytes);
diff --git a/drivers/media/pci/cx18/cx18-alsa.h b/drivers/media/pci/cx18/cx18-alsa.h
new file mode 100644
index 0000000..447da37
--- /dev/null
+++ b/drivers/media/pci/cx18/cx18-alsa.h
@@ -0,0 +1,75 @@
+/*
+ *  ALSA interface to cx18 PCM capture streams
+ *
+ *  Copyright (C) 2009  Andy Walls <awalls@md.metrocast.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 program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307  USA
+ */
+
+struct snd_card;
+
+struct snd_cx18_card {
+	struct v4l2_device *v4l2_dev;
+	struct snd_card *sc;
+	unsigned int capture_transfer_done;
+	unsigned int hwptr_done_capture;
+	struct snd_pcm_substream *capture_pcm_substream;
+	spinlock_t slock;
+};
+
+extern int cx18_alsa_debug;
+
+/*
+ * File operations that manipulate the encoder or video or audio subdevices
+ * need to be serialized.  Use the same lock we use for v4l2 file ops.
+ */
+static inline void snd_cx18_lock(struct snd_cx18_card *cxsc)
+{
+	struct cx18 *cx = to_cx18(cxsc->v4l2_dev);
+	mutex_lock(&cx->serialize_lock);
+}
+
+static inline void snd_cx18_unlock(struct snd_cx18_card *cxsc)
+{
+	struct cx18 *cx = to_cx18(cxsc->v4l2_dev);
+	mutex_unlock(&cx->serialize_lock);
+}
+
+#define CX18_ALSA_DBGFLG_WARN  (1 << 0)
+#define CX18_ALSA_DBGFLG_WARN  (1 << 0)
+#define CX18_ALSA_DBGFLG_INFO  (1 << 1)
+
+#define CX18_ALSA_DEBUG(x, type, fmt, args...) \
+	do { \
+		if ((x) & cx18_alsa_debug) \
+			printk(KERN_INFO "%s-alsa: " type ": " fmt, \
+				v4l2_dev->name , ## args); \
+	} while (0)
+
+#define CX18_ALSA_DEBUG_WARN(fmt, args...) \
+	CX18_ALSA_DEBUG(CX18_ALSA_DBGFLG_WARN, "warning", fmt , ## args)
+
+#define CX18_ALSA_DEBUG_INFO(fmt, args...) \
+	CX18_ALSA_DEBUG(CX18_ALSA_DBGFLG_INFO, "info", fmt , ## args)
+
+#define CX18_ALSA_ERR(fmt, args...) \
+	printk(KERN_ERR "%s-alsa: " fmt, v4l2_dev->name , ## args)
+
+#define CX18_ALSA_WARN(fmt, args...) \
+	printk(KERN_WARNING "%s-alsa: " fmt, v4l2_dev->name , ## args)
+
+#define CX18_ALSA_INFO(fmt, args...) \
+	printk(KERN_INFO "%s-alsa: " fmt, v4l2_dev->name , ## args)
diff --git a/drivers/media/pci/cx18/cx18-audio.c b/drivers/media/pci/cx18/cx18-audio.c
new file mode 100644
index 0000000..3526892
--- /dev/null
+++ b/drivers/media/pci/cx18/cx18-audio.c
@@ -0,0 +1,92 @@
+/*
+ *  cx18 audio-related functions
+ *
+ *  Derived from ivtv-audio.c
+ *
+ *  Copyright (C) 2007  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., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307  USA
+ */
+
+#include "cx18-driver.h"
+#include "cx18-io.h"
+#include "cx18-cards.h"
+#include "cx18-audio.h"
+
+#define CX18_AUDIO_ENABLE    0xc72014
+#define CX18_AI1_MUX_MASK    0x30
+#define CX18_AI1_MUX_I2S1    0x00
+#define CX18_AI1_MUX_I2S2    0x10
+#define CX18_AI1_MUX_843_I2S 0x20
+
+/* Selects the audio input and output according to the current
+   settings. */
+int cx18_audio_set_io(struct cx18 *cx)
+{
+	const struct cx18_card_audio_input *in;
+	u32 u, v;
+	int err;
+
+	/* Determine which input to use */
+	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 */
+	v4l2_subdev_call(cx->sd_extmux, audio, s_routing,
+			 (u32) in->muxer_input, 0, 0);
+
+	err = cx18_call_hw_err(cx, cx->card->hw_audio_ctrl,
+			       audio, s_routing, in->audio_input, 0, 0);
+	if (err)
+		return err;
+
+	/* FIXME - this internal mux should be abstracted to a subdev */
+	u = cx18_read_reg(cx, CX18_AUDIO_ENABLE);
+	v = u & ~CX18_AI1_MUX_MASK;
+	switch (in->audio_input) {
+	case CX18_AV_AUDIO_SERIAL1:
+		v |= CX18_AI1_MUX_I2S1;
+		break;
+	case CX18_AV_AUDIO_SERIAL2:
+		v |= CX18_AI1_MUX_I2S2;
+		break;
+	default:
+		v |= CX18_AI1_MUX_843_I2S;
+		break;
+	}
+	if (v == u) {
+		/* force a toggle of some AI1 MUX control bits */
+		u &= ~CX18_AI1_MUX_MASK;
+		switch (in->audio_input) {
+		case CX18_AV_AUDIO_SERIAL1:
+			u |= CX18_AI1_MUX_843_I2S;
+			break;
+		case CX18_AV_AUDIO_SERIAL2:
+			u |= CX18_AI1_MUX_843_I2S;
+			break;
+		default:
+			u |= CX18_AI1_MUX_I2S1;
+			break;
+		}
+		cx18_write_reg_expect(cx, u | 0xb00, CX18_AUDIO_ENABLE,
+				      u, CX18_AI1_MUX_MASK);
+	}
+	cx18_write_reg_expect(cx, v | 0xb00, CX18_AUDIO_ENABLE,
+			      v, CX18_AI1_MUX_MASK);
+	return 0;
+}
diff --git a/drivers/media/pci/cx18/cx18-audio.h b/drivers/media/pci/cx18/cx18-audio.h
new file mode 100644
index 0000000..2731d29
--- /dev/null
+++ b/drivers/media/pci/cx18/cx18-audio.h
@@ -0,0 +1,24 @@
+/*
+ *  cx18 audio-related functions
+ *
+ *  Derived from ivtv-audio.c
+ *
+ *  Copyright (C) 2007  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., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307  USA
+ */
+
+int cx18_audio_set_io(struct cx18 *cx);
diff --git a/drivers/media/pci/cx18/cx18-av-audio.c b/drivers/media/pci/cx18/cx18-av-audio.c
new file mode 100644
index 0000000..4a24ffb
--- /dev/null
+++ b/drivers/media/pci/cx18/cx18-av-audio.c
@@ -0,0 +1,471 @@
+/*
+ *  cx18 ADEC audio functions
+ *
+ *  Derived from cx25840-audio.c
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.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 program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You 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 "cx18-driver.h"
+
+static int set_audclk_freq(struct cx18 *cx, u32 freq)
+{
+	struct cx18_av_state *state = &cx->av_state;
+
+	if (freq != 32000 && freq != 44100 && freq != 48000)
+		return -EINVAL;
+
+	/*
+	 * The PLL parameters are based on the external crystal frequency that
+	 * would ideally be:
+	 *
+	 * NTSC Color subcarrier freq * 8 =
+	 * 	4.5 MHz/286 * 455/2 * 8 = 28.63636363... MHz
+	 *
+	 * The accidents of history and rationale that explain from where this
+	 * combination of magic numbers originate can be found in:
+	 *
+	 * [1] Abrahams, I. C., "Choice of Chrominance Subcarrier Frequency in
+	 * the NTSC Standards", Proceedings of the I-R-E, January 1954, pp 79-80
+	 *
+	 * [2] Abrahams, I. C., "The 'Frequency Interleaving' Principle in the
+	 * NTSC Standards", Proceedings of the I-R-E, January 1954, pp 81-83
+	 *
+	 * As Mike Bradley has rightly pointed out, it's not the exact crystal
+	 * frequency that matters, only that all parts of the driver and
+	 * firmware are using the same value (close to the ideal value).
+	 *
+	 * Since I have a strong suspicion that, if the firmware ever assumes a
+	 * crystal value at all, it will assume 28.636360 MHz, the crystal
+	 * freq used in calculations in this driver will be:
+	 *
+	 *	xtal_freq = 28.636360 MHz
+	 *
+	 * an error of less than 0.13 ppm which is way, way better than any off
+	 * the shelf crystal will have for accuracy anyway.
+	 *
+	 * Below I aim to run the PLLs' VCOs near 400 MHz to minimze error.
+	 *
+	 * Many thanks to Jeff Campbell and Mike Bradley for their extensive
+	 * investigation, experimentation, testing, and suggested solutions of
+	 * of audio/video sync problems with SVideo and CVBS captures.
+	 */
+
+	if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
+		switch (freq) {
+		case 32000:
+			/*
+			 * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04
+			 * AUX_PLL Integer = 0x0d, AUX PLL Post Divider = 0x20
+			 */
+			cx18_av_write4(cx, 0x108, 0x200d040f);
+
+			/* VID_PLL Fraction = 0x2be2fe */
+			/* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz pre-postdiv*/
+			cx18_av_write4(cx, 0x10c, 0x002be2fe);
+
+			/* AUX_PLL Fraction = 0x176740c */
+			/* xtal * 0xd.bb3a060/0x20 = 32000 * 384: 393 MHz p-pd*/
+			cx18_av_write4(cx, 0x110, 0x0176740c);
+
+			/* src3/4/6_ctl */
+			/* 0x1.f77f = (4 * xtal/8*2/455) / 32000 */
+			cx18_av_write4(cx, 0x900, 0x0801f77f);
+			cx18_av_write4(cx, 0x904, 0x0801f77f);
+			cx18_av_write4(cx, 0x90c, 0x0801f77f);
+
+			/* SA_MCLK_SEL=1, SA_MCLK_DIV=0x20 */
+			cx18_av_write(cx, 0x127, 0x60);
+
+			/* AUD_COUNT = 0x2fff = 8 samples * 4 * 384 - 1 */
+			cx18_av_write4(cx, 0x12c, 0x11202fff);
+
+			/*
+			 * EN_AV_LOCK = 0
+			 * VID_COUNT = 0x0d2ef8 = 107999.000 * 8 =
+			 *  ((8 samples/32,000) * (13,500,000 * 8) * 4 - 1) * 8
+			 */
+			cx18_av_write4(cx, 0x128, 0xa00d2ef8);
+			break;
+
+		case 44100:
+			/*
+			 * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04
+			 * AUX_PLL Integer = 0x0e, AUX PLL Post Divider = 0x18
+			 */
+			cx18_av_write4(cx, 0x108, 0x180e040f);
+
+			/* VID_PLL Fraction = 0x2be2fe */
+			/* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz pre-postdiv*/
+			cx18_av_write4(cx, 0x10c, 0x002be2fe);
+
+			/* AUX_PLL Fraction = 0x062a1f2 */
+			/* xtal * 0xe.3150f90/0x18 = 44100 * 384: 406 MHz p-pd*/
+			cx18_av_write4(cx, 0x110, 0x0062a1f2);
+
+			/* src3/4/6_ctl */
+			/* 0x1.6d59 = (4 * xtal/8*2/455) / 44100 */
+			cx18_av_write4(cx, 0x900, 0x08016d59);
+			cx18_av_write4(cx, 0x904, 0x08016d59);
+			cx18_av_write4(cx, 0x90c, 0x08016d59);
+
+			/* SA_MCLK_SEL=1, SA_MCLK_DIV=0x18 */
+			cx18_av_write(cx, 0x127, 0x58);
+
+			/* AUD_COUNT = 0x92ff = 49 samples * 2 * 384 - 1 */
+			cx18_av_write4(cx, 0x12c, 0x112092ff);
+
+			/*
+			 * EN_AV_LOCK = 0
+			 * VID_COUNT = 0x1d4bf8 = 239999.000 * 8 =
+			 *  ((49 samples/44,100) * (13,500,000 * 8) * 2 - 1) * 8
+			 */
+			cx18_av_write4(cx, 0x128, 0xa01d4bf8);
+			break;
+
+		case 48000:
+			/*
+			 * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04
+			 * AUX_PLL Integer = 0x0e, AUX PLL Post Divider = 0x16
+			 */
+			cx18_av_write4(cx, 0x108, 0x160e040f);
+
+			/* VID_PLL Fraction = 0x2be2fe */
+			/* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz pre-postdiv*/
+			cx18_av_write4(cx, 0x10c, 0x002be2fe);
+
+			/* AUX_PLL Fraction = 0x05227ad */
+			/* xtal * 0xe.2913d68/0x16 = 48000 * 384: 406 MHz p-pd*/
+			cx18_av_write4(cx, 0x110, 0x005227ad);
+
+			/* src3/4/6_ctl */
+			/* 0x1.4faa = (4 * xtal/8*2/455) / 48000 */
+			cx18_av_write4(cx, 0x900, 0x08014faa);
+			cx18_av_write4(cx, 0x904, 0x08014faa);
+			cx18_av_write4(cx, 0x90c, 0x08014faa);
+
+			/* SA_MCLK_SEL=1, SA_MCLK_DIV=0x16 */
+			cx18_av_write(cx, 0x127, 0x56);
+
+			/* AUD_COUNT = 0x5fff = 4 samples * 16 * 384 - 1 */
+			cx18_av_write4(cx, 0x12c, 0x11205fff);
+
+			/*
+			 * EN_AV_LOCK = 0
+			 * VID_COUNT = 0x1193f8 = 143999.000 * 8 =
+			 *  ((4 samples/48,000) * (13,500,000 * 8) * 16 - 1) * 8
+			 */
+			cx18_av_write4(cx, 0x128, 0xa01193f8);
+			break;
+		}
+	} else {
+		switch (freq) {
+		case 32000:
+			/*
+			 * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04
+			 * AUX_PLL Integer = 0x0d, AUX PLL Post Divider = 0x30
+			 */
+			cx18_av_write4(cx, 0x108, 0x300d040f);
+
+			/* VID_PLL Fraction = 0x2be2fe */
+			/* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz pre-postdiv*/
+			cx18_av_write4(cx, 0x10c, 0x002be2fe);
+
+			/* AUX_PLL Fraction = 0x176740c */
+			/* xtal * 0xd.bb3a060/0x30 = 32000 * 256: 393 MHz p-pd*/
+			cx18_av_write4(cx, 0x110, 0x0176740c);
+
+			/* src1_ctl */
+			/* 0x1.0000 = 32000/32000 */
+			cx18_av_write4(cx, 0x8f8, 0x08010000);
+
+			/* src3/4/6_ctl */
+			/* 0x2.0000 = 2 * (32000/32000) */
+			cx18_av_write4(cx, 0x900, 0x08020000);
+			cx18_av_write4(cx, 0x904, 0x08020000);
+			cx18_av_write4(cx, 0x90c, 0x08020000);
+
+			/* SA_MCLK_SEL=1, SA_MCLK_DIV=0x30 */
+			cx18_av_write(cx, 0x127, 0x70);
+
+			/* AUD_COUNT = 0x1fff = 8 samples * 4 * 256 - 1 */
+			cx18_av_write4(cx, 0x12c, 0x11201fff);
+
+			/*
+			 * EN_AV_LOCK = 0
+			 * VID_COUNT = 0x0d2ef8 = 107999.000 * 8 =
+			 *  ((8 samples/32,000) * (13,500,000 * 8) * 4 - 1) * 8
+			 */
+			cx18_av_write4(cx, 0x128, 0xa00d2ef8);
+			break;
+
+		case 44100:
+			/*
+			 * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04
+			 * AUX_PLL Integer = 0x0e, AUX PLL Post Divider = 0x24
+			 */
+			cx18_av_write4(cx, 0x108, 0x240e040f);
+
+			/* VID_PLL Fraction = 0x2be2fe */
+			/* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz pre-postdiv*/
+			cx18_av_write4(cx, 0x10c, 0x002be2fe);
+
+			/* AUX_PLL Fraction = 0x062a1f2 */
+			/* xtal * 0xe.3150f90/0x24 = 44100 * 256: 406 MHz p-pd*/
+			cx18_av_write4(cx, 0x110, 0x0062a1f2);
+
+			/* src1_ctl */
+			/* 0x1.60cd = 44100/32000 */
+			cx18_av_write4(cx, 0x8f8, 0x080160cd);
+
+			/* src3/4/6_ctl */
+			/* 0x1.7385 = 2 * (32000/44100) */
+			cx18_av_write4(cx, 0x900, 0x08017385);
+			cx18_av_write4(cx, 0x904, 0x08017385);
+			cx18_av_write4(cx, 0x90c, 0x08017385);
+
+			/* SA_MCLK_SEL=1, SA_MCLK_DIV=0x24 */
+			cx18_av_write(cx, 0x127, 0x64);
+
+			/* AUD_COUNT = 0x61ff = 49 samples * 2 * 256 - 1 */
+			cx18_av_write4(cx, 0x12c, 0x112061ff);
+
+			/*
+			 * EN_AV_LOCK = 0
+			 * VID_COUNT = 0x1d4bf8 = 239999.000 * 8 =
+			 *  ((49 samples/44,100) * (13,500,000 * 8) * 2 - 1) * 8
+			 */
+			cx18_av_write4(cx, 0x128, 0xa01d4bf8);
+			break;
+
+		case 48000:
+			/*
+			 * VID_PLL Integer = 0x0f, VID_PLL Post Divider = 0x04
+			 * AUX_PLL Integer = 0x0d, AUX PLL Post Divider = 0x20
+			 */
+			cx18_av_write4(cx, 0x108, 0x200d040f);
+
+			/* VID_PLL Fraction = 0x2be2fe */
+			/* xtal * 0xf.15f17f0/4 = 108 MHz: 432 MHz pre-postdiv*/
+			cx18_av_write4(cx, 0x10c, 0x002be2fe);
+
+			/* AUX_PLL Fraction = 0x176740c */
+			/* xtal * 0xd.bb3a060/0x20 = 48000 * 256: 393 MHz p-pd*/
+			cx18_av_write4(cx, 0x110, 0x0176740c);
+
+			/* src1_ctl */
+			/* 0x1.8000 = 48000/32000 */
+			cx18_av_write4(cx, 0x8f8, 0x08018000);
+
+			/* src3/4/6_ctl */
+			/* 0x1.5555 = 2 * (32000/48000) */
+			cx18_av_write4(cx, 0x900, 0x08015555);
+			cx18_av_write4(cx, 0x904, 0x08015555);
+			cx18_av_write4(cx, 0x90c, 0x08015555);
+
+			/* SA_MCLK_SEL=1, SA_MCLK_DIV=0x20 */
+			cx18_av_write(cx, 0x127, 0x60);
+
+			/* AUD_COUNT = 0x3fff = 4 samples * 16 * 256 - 1 */
+			cx18_av_write4(cx, 0x12c, 0x11203fff);
+
+			/*
+			 * EN_AV_LOCK = 0
+			 * VID_COUNT = 0x1193f8 = 143999.000 * 8 =
+			 *  ((4 samples/48,000) * (13,500,000 * 8) * 16 - 1) * 8
+			 */
+			cx18_av_write4(cx, 0x128, 0xa01193f8);
+			break;
+		}
+	}
+
+	state->audclk_freq = freq;
+
+	return 0;
+}
+
+void cx18_av_audio_set_path(struct cx18 *cx)
+{
+	struct cx18_av_state *state = &cx->av_state;
+	u8 v;
+
+	/* stop microcontroller */
+	v = cx18_av_read(cx, 0x803) & ~0x10;
+	cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
+
+	/* assert soft reset */
+	v = cx18_av_read(cx, 0x810) | 0x01;
+	cx18_av_write_expect(cx, 0x810, v, v, 0x0f);
+
+	/* Mute everything to prevent the PFFT! */
+	cx18_av_write(cx, 0x8d3, 0x1f);
+
+	if (state->aud_input <= CX18_AV_AUDIO_SERIAL2) {
+		/* Set Path1 to Serial Audio Input */
+		cx18_av_write4(cx, 0x8d0, 0x01011012);
+
+		/* The microcontroller should not be started for the
+		 * non-tuner inputs: autodetection is specific for
+		 * TV audio. */
+	} else {
+		/* Set Path1 to Analog Demod Main Channel */
+		cx18_av_write4(cx, 0x8d0, 0x1f063870);
+	}
+
+	set_audclk_freq(cx, state->audclk_freq);
+
+	/* deassert soft reset */
+	v = cx18_av_read(cx, 0x810) & ~0x01;
+	cx18_av_write_expect(cx, 0x810, v, v, 0x0f);
+
+	if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
+		/* When the microcontroller detects the
+		 * audio format, it will unmute the lines */
+		v = cx18_av_read(cx, 0x803) | 0x10;
+		cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
+	}
+}
+
+static void set_volume(struct cx18 *cx, int volume)
+{
+	/* First convert the volume to msp3400 values (0-127) */
+	int vol = volume >> 9;
+	/* now scale it up to cx18_av values
+	 * -114dB to -96dB maps to 0
+	 * this should be 19, but in my testing that was 4dB too loud */
+	if (vol <= 23)
+		vol = 0;
+	else
+		vol -= 23;
+
+	/* PATH1_VOLUME */
+	cx18_av_write(cx, 0x8d4, 228 - (vol * 2));
+}
+
+static void set_bass(struct cx18 *cx, int bass)
+{
+	/* PATH1_EQ_BASS_VOL */
+	cx18_av_and_or(cx, 0x8d9, ~0x3f, 48 - (bass * 48 / 0xffff));
+}
+
+static void set_treble(struct cx18 *cx, int treble)
+{
+	/* PATH1_EQ_TREBLE_VOL */
+	cx18_av_and_or(cx, 0x8db, ~0x3f, 48 - (treble * 48 / 0xffff));
+}
+
+static void set_balance(struct cx18 *cx, int balance)
+{
+	int bal = balance >> 8;
+	if (bal > 0x80) {
+		/* PATH1_BAL_LEFT */
+		cx18_av_and_or(cx, 0x8d5, 0x7f, 0x80);
+		/* PATH1_BAL_LEVEL */
+		cx18_av_and_or(cx, 0x8d5, ~0x7f, bal & 0x7f);
+	} else {
+		/* PATH1_BAL_LEFT */
+		cx18_av_and_or(cx, 0x8d5, 0x7f, 0x00);
+		/* PATH1_BAL_LEVEL */
+		cx18_av_and_or(cx, 0x8d5, ~0x7f, 0x80 - bal);
+	}
+}
+
+static void set_mute(struct cx18 *cx, int mute)
+{
+	struct cx18_av_state *state = &cx->av_state;
+	u8 v;
+
+	if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
+		/* Must turn off microcontroller in order to mute sound.
+		 * Not sure if this is the best method, but it does work.
+		 * If the microcontroller is running, then it will undo any
+		 * changes to the mute register. */
+		v = cx18_av_read(cx, 0x803);
+		if (mute) {
+			/* disable microcontroller */
+			v &= ~0x10;
+			cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
+			cx18_av_write(cx, 0x8d3, 0x1f);
+		} else {
+			/* enable microcontroller */
+			v |= 0x10;
+			cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
+		}
+	} else {
+		/* SRC1_MUTE_EN */
+		cx18_av_and_or(cx, 0x8d3, ~0x2, mute ? 0x02 : 0x00);
+	}
+}
+
+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;
+	int retval;
+	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, 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;
+}
+
+static int cx18_av_audio_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct v4l2_subdev *sd = to_sd(ctrl);
+	struct cx18 *cx = v4l2_get_subdevdata(sd);
+
+	switch (ctrl->id) {
+	case V4L2_CID_AUDIO_VOLUME:
+		set_volume(cx, ctrl->val);
+		break;
+	case V4L2_CID_AUDIO_BASS:
+		set_bass(cx, ctrl->val);
+		break;
+	case V4L2_CID_AUDIO_TREBLE:
+		set_treble(cx, ctrl->val);
+		break;
+	case V4L2_CID_AUDIO_BALANCE:
+		set_balance(cx, ctrl->val);
+		break;
+	case V4L2_CID_AUDIO_MUTE:
+		set_mute(cx, ctrl->val);
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+const struct v4l2_ctrl_ops cx18_av_audio_ctrl_ops = {
+	.s_ctrl = cx18_av_audio_s_ctrl,
+};
diff --git a/drivers/media/pci/cx18/cx18-av-core.c b/drivers/media/pci/cx18/cx18-av-core.c
new file mode 100644
index 0000000..f164b7f
--- /dev/null
+++ b/drivers/media/pci/cx18/cx18-av-core.c
@@ -0,0 +1,1401 @@
+/*
+ *  cx18 ADEC audio functions
+ *
+ *  Derived from cx25840-core.c
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.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 program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You 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 <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)
+{
+	u32 reg = 0xc40000 + (addr & ~3);
+	u32 mask = 0xff;
+	int shift = (addr & 3) * 8;
+	u32 x = cx18_read_reg(cx, reg);
+
+	x = (x & ~(mask << shift)) | ((u32)value << shift);
+	cx18_write_reg(cx, x, reg);
+	return 0;
+}
+
+int cx18_av_write_expect(struct cx18 *cx, u16 addr, u8 value, u8 eval, u8 mask)
+{
+	u32 reg = 0xc40000 + (addr & ~3);
+	int shift = (addr & 3) * 8;
+	u32 x = cx18_read_reg(cx, reg);
+
+	x = (x & ~((u32)0xff << shift)) | ((u32)value << shift);
+	cx18_write_reg_expect(cx, x, reg,
+				((u32)eval << shift), ((u32)mask << shift));
+	return 0;
+}
+
+int cx18_av_write4(struct cx18 *cx, u16 addr, u32 value)
+{
+	cx18_write_reg(cx, value, 0xc40000 + addr);
+	return 0;
+}
+
+int
+cx18_av_write4_expect(struct cx18 *cx, u16 addr, u32 value, u32 eval, u32 mask)
+{
+	cx18_write_reg_expect(cx, value, 0xc40000 + addr, eval, mask);
+	return 0;
+}
+
+int cx18_av_write4_noretry(struct cx18 *cx, u16 addr, u32 value)
+{
+	cx18_write_reg_noretry(cx, value, 0xc40000 + addr);
+	return 0;
+}
+
+u8 cx18_av_read(struct cx18 *cx, u16 addr)
+{
+	u32 x = cx18_read_reg(cx, 0xc40000 + (addr & ~3));
+	int shift = (addr & 3) * 8;
+
+	return (x >> shift) & 0xff;
+}
+
+u32 cx18_av_read4(struct cx18 *cx, u16 addr)
+{
+	return cx18_read_reg(cx, 0xc40000 + addr);
+}
+
+int cx18_av_and_or(struct cx18 *cx, u16 addr, unsigned and_mask,
+		   u8 or_value)
+{
+	return cx18_av_write(cx, addr,
+			     (cx18_av_read(cx, addr) & and_mask) |
+			     or_value);
+}
+
+int cx18_av_and_or4(struct cx18 *cx, u16 addr, u32 and_mask,
+		   u32 or_value)
+{
+	return cx18_av_write4(cx, addr,
+			     (cx18_av_read4(cx, addr) & and_mask) |
+			     or_value);
+}
+
+static void cx18_av_init(struct cx18 *cx)
+{
+	/*
+	 * 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);
+}
+
+static void cx18_av_initialize(struct v4l2_subdev *sd)
+{
+	struct cx18_av_state *state = to_cx18_av_state(sd);
+	struct cx18 *cx = v4l2_get_subdevdata(sd);
+	int default_volume;
+	u32 v;
+
+	cx18_av_loadfw(cx);
+	/* Stop 8051 code execution */
+	cx18_av_write4_expect(cx, CXADEC_DL_CTL, 0x03000000,
+						 0x03000000, 0x13000000);
+
+	/* initallize the PLL by toggling sleep bit */
+	v = cx18_av_read4(cx, CXADEC_HOST_REG1);
+	/* enable sleep mode - register appears to be read only... */
+	cx18_av_write4_expect(cx, CXADEC_HOST_REG1, v | 1, v, 0xfffe);
+	/* disable sleep mode */
+	cx18_av_write4_expect(cx, CXADEC_HOST_REG1, v & 0xfffe,
+						    v & 0xfffe, 0xffff);
+
+	/* initialize DLLs */
+	v = cx18_av_read4(cx, CXADEC_DLL1_DIAG_CTRL) & 0xE1FFFEFF;
+	/* disable FLD */
+	cx18_av_write4(cx, CXADEC_DLL1_DIAG_CTRL, v);
+	/* enable FLD */
+	cx18_av_write4(cx, CXADEC_DLL1_DIAG_CTRL, v | 0x10000100);
+
+	v = cx18_av_read4(cx, CXADEC_DLL2_DIAG_CTRL) & 0xE1FFFEFF;
+	/* disable FLD */
+	cx18_av_write4(cx, CXADEC_DLL2_DIAG_CTRL, v);
+	/* enable FLD */
+	cx18_av_write4(cx, CXADEC_DLL2_DIAG_CTRL, v | 0x06000100);
+
+	/* set analog bias currents. Set Vreg to 1.20V. */
+	cx18_av_write4(cx, CXADEC_AFE_DIAG_CTRL1, 0x000A1802);
+
+	v = cx18_av_read4(cx, CXADEC_AFE_DIAG_CTRL3) | 1;
+	/* enable TUNE_FIL_RST */
+	cx18_av_write4_expect(cx, CXADEC_AFE_DIAG_CTRL3, v, v, 0x03009F0F);
+	/* disable TUNE_FIL_RST */
+	cx18_av_write4_expect(cx, CXADEC_AFE_DIAG_CTRL3,
+			      v & 0xFFFFFFFE, v & 0xFFFFFFFE, 0x03009F0F);
+
+	/* enable 656 output */
+	cx18_av_and_or4(cx, CXADEC_PIN_CTRL1, ~0, 0x040C00);
+
+	/* video output drive strength */
+	cx18_av_and_or4(cx, CXADEC_PIN_CTRL2, ~0, 0x2);
+
+	/* reset video */
+	cx18_av_write4(cx, CXADEC_SOFT_RST_CTRL, 0x8000);
+	cx18_av_write4(cx, CXADEC_SOFT_RST_CTRL, 0);
+
+	/*
+	 * Disable Video Auto-config of the Analog Front End and Video PLL.
+	 *
+	 * Since we only use BT.656 pixel mode, which works for both 525 and 625
+	 * line systems, it's just easier for us to set registers
+	 * 0x102 (CXADEC_CHIP_CTRL), 0x104-0x106 (CXADEC_AFE_CTRL),
+	 * 0x108-0x109 (CXADEC_PLL_CTRL1), and 0x10c-0x10f (CXADEC_VID_PLL_FRAC)
+	 * ourselves, than to run around cleaning up after the auto-config.
+	 *
+	 * (Note: my CX23418 chip doesn't seem to let the ACFG_DIS bit
+	 * get set to 1, but OTOH, it doesn't seem to do AFE and VID PLL
+	 * autoconfig either.)
+	 *
+	 * As a default, also turn off Dual mode for ADC2 and set ADC2 to CH3.
+	 */
+	cx18_av_and_or4(cx, CXADEC_CHIP_CTRL, 0xFFFBFFFF, 0x00120000);
+
+	/* Setup the Video and and Aux/Audio PLLs */
+	cx18_av_init(cx);
+
+	/* set video to auto-detect */
+	/* Clear bits 11-12 to enable slow locking mode.  Set autodetect mode */
+	/* set the comb notch = 1 */
+	cx18_av_and_or4(cx, CXADEC_MODE_CTRL, 0xFFF7E7F0, 0x02040800);
+
+	/* Enable wtw_en in CRUSH_CTRL (Set bit 22) */
+	/* Enable maj_sel in CRUSH_CTRL (Set bit 20) */
+	cx18_av_and_or4(cx, CXADEC_CRUSH_CTRL, ~0, 0x00500000);
+
+	/* Set VGA_TRACK_RANGE to 0x20 */
+	cx18_av_and_or4(cx, CXADEC_DFE_CTRL2, 0xFFFF00FF, 0x00002000);
+
+	/*
+	 * 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 */
+	/* EncSetSignalStd(dwDevNum, pEnc->dwSigStd); */
+	/* EncSetVideoInput(dwDevNum, pEnc->VidIndSelection); */
+
+	/*
+	 * Analog Front End (AFE)
+	 * Default to luma on ch1/ADC1, chroma on ch2/ADC2, SIF on ch3/ADC2
+	 *  bypass_ch[1-3]     use filter
+	 *  droop_comp_ch[1-3] disable
+	 *  clamp_en_ch[1-3]   disable
+	 *  aud_in_sel         ADC2
+	 *  luma_in_sel        ADC1
+	 *  chroma_in_sel      ADC2
+	 *  clamp_sel_ch[2-3]  midcode
+	 *  clamp_sel_ch1      video decoder
+	 *  vga_sel_ch3        audio decoder
+	 *  vga_sel_ch[1-2]    video decoder
+	 *  half_bw_ch[1-3]    disable
+	 *  +12db_ch[1-3]      disable
+	 */
+	cx18_av_and_or4(cx, CXADEC_AFE_CTRL, 0xFF000000, 0x00005D00);
+
+/* 	if(dwEnable && dw3DCombAvailable) { */
+/*      	CxDevWrReg(CXADEC_SRC_COMB_CFG, 0x7728021F); */
+/*    } else { */
+/*      	CxDevWrReg(CXADEC_SRC_COMB_CFG, 0x6628021F); */
+/*    } */
+	cx18_av_write4(cx, CXADEC_SRC_COMB_CFG, 0x6628021F);
+	default_volume = cx18_av_read(cx, 0x8d4);
+	/*
+	 * Enforce the legacy volume scale mapping limits to avoid
+	 * -ERANGE errors when initializing the volume control
+	 */
+	if (default_volume > 228) {
+		/* Bottom out at -96 dB, v4l2 vol range 0x2e00-0x2fff */
+		default_volume = 228;
+		cx18_av_write(cx, 0x8d4, 228);
+	} else if (default_volume < 20) {
+		/* Top out at + 8 dB, v4l2 vol range 0xfe00-0xffff */
+		default_volume = 20;
+		cx18_av_write(cx, 0x8d4, 20);
+	}
+	default_volume = (((228 - default_volume) >> 1) + 23) << 9;
+	state->volume->cur.val = state->volume->default_value = default_volume;
+	v4l2_ctrl_handler_setup(&state->hdl);
+}
+
+static int cx18_av_reset(struct v4l2_subdev *sd, u32 val)
+{
+	cx18_av_initialize(sd);
+	return 0;
+}
+
+static int cx18_av_load_fw(struct v4l2_subdev *sd)
+{
+	struct cx18_av_state *state = to_cx18_av_state(sd);
+
+	if (!state->is_initialized) {
+		/* initialize on first use */
+		state->is_initialized = 1;
+		cx18_av_initialize(sd);
+	}
+	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;
+
+	/*
+	 * Video ADC crystal clock to pixel clock SRC decimation ratio
+	 * 28.636360 MHz/13.5 Mpps * 256 = 0x21f.07b
+	 */
+	const int src_decimation = 0x21f;
+
+	int hblank, hactive, burst, vblank, vactive, sc;
+	int vblank656;
+	int luma_lpf, uv_lpf, comb;
+	u32 pll_int, pll_frac, pll_post;
+
+	/* datasheet startup, step 8d */
+	if (std & ~V4L2_STD_NTSC)
+		cx18_av_write(cx, 0x49f, 0x11);
+	else
+		cx18_av_write(cx, 0x49f, 0x14);
+
+	/*
+	 * Note: At the end of a field, there are 3 sets of half line duration
+	 * (double horizontal rate) pulses:
+	 *
+	 * 5 (625) or 6 (525) half-lines to blank for the vertical retrace
+	 * 5 (625) or 6 (525) vertical sync pulses of half line duration
+	 * 5 (625) or 6 (525) half-lines of equalization pulses
+	 */
+	if (std & V4L2_STD_625_50) {
+		/*
+		 * The following relationships of half line counts should hold:
+		 * 625 = vblank656 + vactive
+		 * 10 = vblank656 - vblank = vsync pulses + equalization pulses
+		 *
+		 * vblank656: half lines after line 625/mid-313 of blanked video
+		 * vblank:    half lines, after line 5/317, of blanked video
+		 * vactive:   half lines of active video +
+		 * 		5 half lines after the end of active video
+		 *
+		 * As far as I can tell:
+		 * vblank656 starts counting from the falling edge of the first
+		 * 	vsync pulse (start of line 1 or mid-313)
+		 * vblank starts counting from the after the 5 vsync pulses and
+		 * 	5 or 4 equalization pulses (start of line 6 or 318)
+		 *
+		 * For 625 line systems the driver will extract VBI information
+		 * from lines 6-23 and lines 318-335 (but the slicer can only
+		 * handle 17 lines, not the 18 in the vblank region).
+		 * In addition, we need vblank656 and vblank to be one whole
+		 * line longer, to cover line 24 and 336, so the SAV/EAV RP
+		 * codes get generated such that the encoder can actually
+		 * extract line 23 & 335 (WSS).  We'll lose 1 line in each field
+		 * at the top of the screen.
+		 *
+		 * It appears the 5 half lines that happen after active
+		 * video must be included in vactive (579 instead of 574),
+		 * otherwise the colors get badly displayed in various regions
+		 * of the screen.  I guess the chroma comb filter gets confused
+		 * without them (at least when a PVR-350 is the PAL source).
+		 */
+		vblank656 = 48; /* lines  1 -  24  &  313 - 336 */
+		vblank = 38;    /* lines  6 -  24  &  318 - 336 */
+		vactive = 579;  /* lines 24 - 313  &  337 - 626 */
+
+		/*
+		 * For a 13.5 Mpps clock and 15,625 Hz line rate, a line is
+		 * is 864 pixels = 720 active + 144 blanking.  ITU-R BT.601
+		 * specifies 12 luma clock periods or ~ 0.9 * 13.5 Mpps after
+		 * the end of active video to start a horizontal line, so that
+		 * leaves 132 pixels of hblank to ignore.
+		 */
+		hblank = 132;
+		hactive = 720;
+
+		/*
+		 * Burst gate delay (for 625 line systems)
+		 * Hsync leading edge to color burst rise = 5.6 us
+		 * Color burst width = 2.25 us
+		 * Gate width = 4 pixel clocks
+		 * (5.6 us + 2.25/2 us) * 13.5 Mpps + 4/2 clocks = 92.79 clocks
+		 */
+		burst = 93;
+		luma_lpf = 2;
+		if (std & V4L2_STD_PAL) {
+			uv_lpf = 1;
+			comb = 0x20;
+			/* sc = 4433618.75 * src_decimation/28636360 * 2^13 */
+			sc = 688700;
+		} else if (std == V4L2_STD_PAL_Nc) {
+			uv_lpf = 1;
+			comb = 0x20;
+			/* sc = 3582056.25 * src_decimation/28636360 * 2^13 */
+			sc = 556422;
+		} else { /* SECAM */
+			uv_lpf = 0;
+			comb = 0;
+			/* (fr + fb)/2 = (4406260 + 4250000)/2 = 4328130 */
+			/* sc = 4328130 * src_decimation/28636360 * 2^13 */
+			sc = 672314;
+		}
+	} else {
+		/*
+		 * The following relationships of half line counts should hold:
+		 * 525 = prevsync + vblank656 + vactive
+		 * 12 = vblank656 - vblank = vsync pulses + equalization pulses
+		 *
+		 * prevsync:  6 half-lines before the vsync pulses
+		 * vblank656: half lines, after line 3/mid-266, of blanked video
+		 * vblank:    half lines, after line 9/272, of blanked video
+		 * vactive:   half lines of active 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;
+		luma_lpf = 1;
+		uv_lpf = 1;
+
+		/*
+		 * Burst gate delay (for 525 line systems)
+		 * Hsync leading edge to color burst rise = 5.3 us
+		 * Color burst width = 2.5 us
+		 * Gate width = 4 pixel clocks
+		 * (5.3 us + 2.5/2 us) * 13.5 Mpps + 4/2 clocks = 90.425 clocks
+		 */
+		if (std == V4L2_STD_PAL_60) {
+			burst = 90;
+			luma_lpf = 2;
+			comb = 0x20;
+			/* sc = 4433618.75 * src_decimation/28636360 * 2^13 */
+			sc = 688700;
+		} else if (std == V4L2_STD_PAL_M) {
+			/* The 97 needs to be verified against PAL-M timings */
+			burst = 97;
+			comb = 0x20;
+			/* sc = 3575611.49 * src_decimation/28636360 * 2^13 */
+			sc = 555421;
+		} else {
+			burst = 90;
+			comb = 0x66;
+			/* sc = 3579545.45.. * src_decimation/28636360 * 2^13 */
+			sc = 556032;
+		}
+	}
+
+	/* DEBUG: Displays configured PLL frequency */
+	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_DEV(sd, "PLL regs = int: %u, frac: %u, post: %u\n",
+			    pll_int, pll_frac, pll_post);
+
+	if (pll_post) {
+		int fsc, pll;
+		u64 tmp;
+
+		pll = (28636360L * ((((u64)pll_int) << 25) + pll_frac)) >> 25;
+		pll /= pll_post;
+		CX18_DEBUG_INFO_DEV(sd, "Video PLL = %d.%06d MHz\n",
+				    pll / 1000000, pll % 1000000);
+		CX18_DEBUG_INFO_DEV(sd, "Pixel rate = %d.%06d Mpixel/sec\n",
+				    pll / 8000000, (pll / 8) % 1000000);
+
+		CX18_DEBUG_INFO_DEV(sd, "ADC XTAL/pixel clock decimation ratio "
+				    "= %d.%03d\n", src_decimation / 256,
+				    ((src_decimation % 256) * 1000) / 256);
+
+		tmp = 28636360 * (u64) sc;
+		do_div(tmp, src_decimation);
+		fsc = tmp >> 13;
+		CX18_DEBUG_INFO_DEV(sd,
+				    "Chroma sub-carrier initial freq = %d.%06d "
+				    "MHz\n", fsc / 1000000, fsc % 1000000);
+
+		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 */
+	cx18_av_write(cx, 0x470, hblank);
+	cx18_av_write(cx, 0x471, 0xff & (((hblank >> 8) & 0x3) |
+						(hactive << 4)));
+	cx18_av_write(cx, 0x472, hactive >> 4);
+
+	/* Sets burst gate delay */
+	cx18_av_write(cx, 0x473, burst);
+
+	/* Sets vertical blanking delay and active duration */
+	cx18_av_write(cx, 0x474, vblank);
+	cx18_av_write(cx, 0x475, 0xff & (((vblank >> 8) & 0x3) |
+						(vactive << 4)));
+	cx18_av_write(cx, 0x476, vactive >> 4);
+	cx18_av_write(cx, 0x477, vblank656);
+
+	/* Sets src decimation rate */
+	cx18_av_write(cx, 0x478, 0xff & src_decimation);
+	cx18_av_write(cx, 0x479, 0xff & (src_decimation >> 8));
+
+	/* Sets Luma and UV Low pass filters */
+	cx18_av_write(cx, 0x47a, luma_lpf << 6 | ((uv_lpf << 4) & 0x30));
+
+	/* Enables comb filters */
+	cx18_av_write(cx, 0x47b, comb);
+
+	/* Sets SC Step*/
+	cx18_av_write(cx, 0x47c, sc);
+	cx18_av_write(cx, 0x47d, 0xff & sc >> 8);
+	cx18_av_write(cx, 0x47e, 0xff & sc >> 16);
+
+	if (std & V4L2_STD_625_50) {
+		state->slicer_line_delay = 1;
+		state->slicer_line_offset = (6 + state->slicer_line_delay - 2);
+	} else {
+		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;
+	v4l2_std_id std = state->std;
+	u8 v;
+
+	/* Follow step 8c and 8d of section 3.16 in the cx18_av datasheet */
+	cx18_av_write(cx, 0x49f, (std & V4L2_STD_NTSC) ? 0x14 : 0x11);
+	cx18_av_and_or(cx, 0x401, ~0x60, 0);
+	cx18_av_and_or(cx, 0x401, ~0x60, 0x60);
+
+	if (std & V4L2_STD_525_60) {
+		if (std == V4L2_STD_NTSC_M_JP) {
+			/* Japan uses EIAJ audio standard */
+			cx18_av_write_expect(cx, 0x808, 0xf7, 0xf7, 0xff);
+			cx18_av_write_expect(cx, 0x80b, 0x02, 0x02, 0x3f);
+		} else if (std == V4L2_STD_NTSC_M_KR) {
+			/* South Korea uses A2 audio standard */
+			cx18_av_write_expect(cx, 0x808, 0xf8, 0xf8, 0xff);
+			cx18_av_write_expect(cx, 0x80b, 0x03, 0x03, 0x3f);
+		} else {
+			/* Others use the BTSC audio standard */
+			cx18_av_write_expect(cx, 0x808, 0xf6, 0xf6, 0xff);
+			cx18_av_write_expect(cx, 0x80b, 0x01, 0x01, 0x3f);
+		}
+	} else if (std & V4L2_STD_PAL) {
+		/* Follow tuner change procedure for PAL */
+		cx18_av_write_expect(cx, 0x808, 0xff, 0xff, 0xff);
+		cx18_av_write_expect(cx, 0x80b, 0x03, 0x03, 0x3f);
+	} else if (std & V4L2_STD_SECAM) {
+		/* Select autodetect for SECAM */
+		cx18_av_write_expect(cx, 0x808, 0xff, 0xff, 0xff);
+		cx18_av_write_expect(cx, 0x80b, 0x03, 0x03, 0x3f);
+	}
+
+	v = cx18_av_read(cx, 0x803);
+	if (v & 0x10) {
+		/* restart audio decoder microcontroller */
+		v &= ~0x10;
+		cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
+		v |= 0x10;
+		cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
+	}
+}
+
+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;
+
+	enum analog_signal_type {
+		NONE, CVBS, Y, C, SIF, Pb, Pr
+	} ch[3] = {NONE, NONE, NONE};
+
+	u8 afe_mux_cfg;
+	u8 adc2_cfg;
+	u8 input_mode;
+	u32 afe_cfg;
+	int i;
+
+	CX18_DEBUG_INFO_DEV(sd, "decoder set video input %d, audio input %d\n",
+			    vid_input, aud_input);
+
+	if (vid_input >= CX18_AV_COMPOSITE1 &&
+	    vid_input <= CX18_AV_COMPOSITE8) {
+		afe_mux_cfg = 0xf0 + (vid_input - CX18_AV_COMPOSITE1);
+		ch[0] = CVBS;
+		input_mode = 0x0;
+	} else if (vid_input >= CX18_AV_COMPONENT_LUMA1) {
+		int luma = vid_input & 0xf000;
+		int r_chroma = vid_input & 0xf0000;
+		int b_chroma = vid_input & 0xf00000;
+
+		if ((vid_input & ~0xfff000) ||
+		    luma < CX18_AV_COMPONENT_LUMA1 ||
+		    luma > CX18_AV_COMPONENT_LUMA8 ||
+		    r_chroma < CX18_AV_COMPONENT_R_CHROMA4 ||
+		    r_chroma > CX18_AV_COMPONENT_R_CHROMA6 ||
+		    b_chroma < CX18_AV_COMPONENT_B_CHROMA7 ||
+		    b_chroma > CX18_AV_COMPONENT_B_CHROMA8) {
+			CX18_ERR_DEV(sd, "0x%06x is not a valid video input!\n",
+				     vid_input);
+			return -EINVAL;
+		}
+		afe_mux_cfg = (luma - CX18_AV_COMPONENT_LUMA1) >> 12;
+		ch[0] = Y;
+		afe_mux_cfg |= (r_chroma - CX18_AV_COMPONENT_R_CHROMA4) >> 12;
+		ch[1] = Pr;
+		afe_mux_cfg |= (b_chroma - CX18_AV_COMPONENT_B_CHROMA7) >> 14;
+		ch[2] = Pb;
+		input_mode = 0x6;
+	} else {
+		int luma = vid_input & 0xf0;
+		int chroma = vid_input & 0xf00;
+
+		if ((vid_input & ~0xff0) ||
+		    luma < CX18_AV_SVIDEO_LUMA1 ||
+		    luma > CX18_AV_SVIDEO_LUMA8 ||
+		    chroma < CX18_AV_SVIDEO_CHROMA4 ||
+		    chroma > CX18_AV_SVIDEO_CHROMA8) {
+			CX18_ERR_DEV(sd, "0x%06x is not a valid video input!\n",
+				     vid_input);
+			return -EINVAL;
+		}
+		afe_mux_cfg = 0xf0 + ((luma - CX18_AV_SVIDEO_LUMA1) >> 4);
+		ch[0] = Y;
+		if (chroma >= CX18_AV_SVIDEO_CHROMA7) {
+			afe_mux_cfg &= 0x3f;
+			afe_mux_cfg |= (chroma - CX18_AV_SVIDEO_CHROMA7) >> 2;
+			ch[2] = C;
+		} else {
+			afe_mux_cfg &= 0xcf;
+			afe_mux_cfg |= (chroma - CX18_AV_SVIDEO_CHROMA4) >> 4;
+			ch[1] = C;
+		}
+		input_mode = 0x2;
+	}
+
+	switch (aud_input) {
+	case CX18_AV_AUDIO_SERIAL1:
+	case CX18_AV_AUDIO_SERIAL2:
+		/* do nothing, use serial audio input */
+		break;
+	case CX18_AV_AUDIO4:
+		afe_mux_cfg &= ~0x30;
+		ch[1] = SIF;
+		break;
+	case CX18_AV_AUDIO5:
+		afe_mux_cfg = (afe_mux_cfg & ~0x30) | 0x10;
+		ch[1] = SIF;
+		break;
+	case CX18_AV_AUDIO6:
+		afe_mux_cfg = (afe_mux_cfg & ~0x30) | 0x20;
+		ch[1] = SIF;
+		break;
+	case CX18_AV_AUDIO7:
+		afe_mux_cfg &= ~0xc0;
+		ch[2] = SIF;
+		break;
+	case CX18_AV_AUDIO8:
+		afe_mux_cfg = (afe_mux_cfg & ~0xc0) | 0x40;
+		ch[2] = SIF;
+		break;
+
+	default:
+		CX18_ERR_DEV(sd, "0x%04x is not a valid audio input!\n",
+			     aud_input);
+		return -EINVAL;
+	}
+
+	/* Set up analog front end multiplexers */
+	cx18_av_write_expect(cx, 0x103, afe_mux_cfg, afe_mux_cfg, 0xf7);
+	/* Set INPUT_MODE to Composite, S-Video, or Component */
+	cx18_av_and_or(cx, 0x401, ~0x6, input_mode);
+
+	/* Set CH_SEL_ADC2 to 1 if input comes from CH3 */
+	adc2_cfg = cx18_av_read(cx, 0x102);
+	if (ch[2] == NONE)
+		adc2_cfg &= ~0x2; /* No sig on CH3, set ADC2 to CH2 for input */
+	else
+		adc2_cfg |= 0x2;  /* Signal on CH3, set ADC2 to CH3 for input */
+
+	/* Set DUAL_MODE_ADC2 to 1 if input comes from both CH2 and CH3 */
+	if (ch[1] != NONE && ch[2] != NONE)
+		adc2_cfg |= 0x4; /* Set dual mode */
+	else
+		adc2_cfg &= ~0x4; /* Clear dual mode */
+	cx18_av_write_expect(cx, 0x102, adc2_cfg, adc2_cfg, 0x17);
+
+	/* Configure the analog front end */
+	afe_cfg = cx18_av_read4(cx, CXADEC_AFE_CTRL);
+	afe_cfg &= 0xff000000;
+	afe_cfg |= 0x00005000; /* CHROMA_IN, AUD_IN: ADC2; LUMA_IN: ADC1 */
+	if (ch[1] != NONE && ch[2] != NONE)
+		afe_cfg |= 0x00000030; /* half_bw_ch[2-3] since in dual mode */
+
+	for (i = 0; i < 3; i++) {
+		switch (ch[i]) {
+		default:
+		case NONE:
+			/* CLAMP_SEL = Fixed to midcode clamp level */
+			afe_cfg |= (0x00000200 << i);
+			break;
+		case CVBS:
+		case Y:
+			if (i > 0)
+				afe_cfg |= 0x00002000; /* LUMA_IN_SEL: ADC2 */
+			break;
+		case C:
+		case Pb:
+		case Pr:
+			/* CLAMP_SEL = Fixed to midcode clamp level */
+			afe_cfg |= (0x00000200 << i);
+			if (i == 0 && ch[i] == C)
+				afe_cfg &= ~0x00001000; /* CHROMA_IN_SEL ADC1 */
+			break;
+		case SIF:
+			/*
+			 * VGA_GAIN_SEL = Audio Decoder
+			 * CLAMP_SEL = Fixed to midcode clamp level
+			 */
+			afe_cfg |= (0x00000240 << i);
+			if (i == 0)
+				afe_cfg &= ~0x00004000; /* AUD_IN_SEL ADC1 */
+			break;
+		}
+	}
+
+	cx18_av_write4(cx, CXADEC_AFE_CTRL, afe_cfg);
+
+	state->vid_input = vid_input;
+	state->aud_input = aud_input;
+	cx18_av_audio_set_path(cx);
+	input_change(cx);
+	return 0;
+}
+
+static int cx18_av_s_video_routing(struct v4l2_subdev *sd,
+				   u32 input, u32 output, u32 config)
+{
+	struct cx18_av_state *state = to_cx18_av_state(sd);
+	struct cx18 *cx = v4l2_get_subdevdata(sd);
+	return set_input(cx, input, state->aud_input);
+}
+
+static int cx18_av_s_audio_routing(struct v4l2_subdev *sd,
+				   u32 input, u32 output, u32 config)
+{
+	struct cx18_av_state *state = to_cx18_av_state(sd);
+	struct cx18 *cx = v4l2_get_subdevdata(sd);
+	return set_input(cx, state->vid_input, 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;
+	} else if (state->std == V4L2_STD_NTSC_443) {
+		fmt = 0x3;
+	} else if (state->std == V4L2_STD_PAL_M) {
+		pal_m = 1;
+		fmt = 0x5;
+	} else if (state->std == V4L2_STD_PAL_N) {
+		fmt = 0x6;
+	} else if (state->std == V4L2_STD_PAL_Nc) {
+		fmt = 0x7;
+	} else if (state->std == V4L2_STD_PAL_60) {
+		fmt = 0x8;
+	} else {
+		/* Then, test against generic ones */
+		if (state->std & V4L2_STD_NTSC)
+			fmt = 0x1;
+		else if (state->std & V4L2_STD_PAL)
+			fmt = 0x4;
+		else if (state->std & V4L2_STD_SECAM)
+			fmt = 0xc;
+	}
+
+	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.
+	   This happens for example with the Yuan MPC622. */
+	if (fmt >= 4 && fmt < 8) {
+		/* Set format to NTSC-M */
+		cx18_av_and_or(cx, 0x400, ~0xf, 1);
+		/* Turn off LCOMB */
+		cx18_av_and_or(cx, 0x47b, ~6, 0);
+	}
+	cx18_av_and_or(cx, 0x400, ~0x2f, fmt | 0x20);
+	cx18_av_and_or(cx, 0x403, ~0x3, pal_m);
+	cx18_av_std_setup(cx);
+	input_change(cx);
+	return 0;
+}
+
+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_ctrl *ctrl)
+{
+	struct v4l2_subdev *sd = to_sd(ctrl);
+	struct cx18 *cx = v4l2_get_subdevdata(sd);
+
+	switch (ctrl->id) {
+	case V4L2_CID_BRIGHTNESS:
+		cx18_av_write(cx, 0x414, ctrl->val - 128);
+		break;
+
+	case V4L2_CID_CONTRAST:
+		cx18_av_write(cx, 0x415, ctrl->val << 1);
+		break;
+
+	case V4L2_CID_SATURATION:
+		cx18_av_write(cx, 0x420, ctrl->val << 1);
+		cx18_av_write(cx, 0x421, ctrl->val << 1);
+		break;
+
+	case V4L2_CID_HUE:
+		cx18_av_write(cx, 0x422, ctrl->val);
+		break;
+
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int cx18_av_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
+{
+	struct cx18_av_state *state = to_cx18_av_state(sd);
+	struct cx18 *cx = v4l2_get_subdevdata(sd);
+	int HSC, VSC, Vsrc, Hsrc, filter, Vlines;
+	int is_50Hz = !(state->std & V4L2_STD_525_60);
+
+	if (fmt->code != V4L2_MBUS_FMT_FIXED)
+		return -EINVAL;
+
+	fmt->field = V4L2_FIELD_INTERLACED;
+	fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
+
+	Vsrc = (cx18_av_read(cx, 0x476) & 0x3f) << 4;
+	Vsrc |= (cx18_av_read(cx, 0x475) & 0xf0) >> 4;
+
+	Hsrc = (cx18_av_read(cx, 0x472) & 0x3f) << 4;
+	Hsrc |= (cx18_av_read(cx, 0x471) & 0xf0) >> 4;
+
+	/*
+	 * This adjustment reflects the excess of vactive, set in
+	 * cx18_av_std_setup(), above standard values:
+	 *
+	 * 480 + 1 for 60 Hz systems
+	 * 576 + 3 for 50 Hz systems
+	 */
+	Vlines = fmt->height + (is_50Hz ? 3 : 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 ((fmt->width * 16 < Hsrc) || (Hsrc < fmt->width) ||
+	    (Vlines * 8 < Vsrc) || (Vsrc < Vlines)) {
+		CX18_ERR_DEV(sd, "%dx%d is not a valid size!\n",
+			     fmt->width, fmt->height);
+		return -ERANGE;
+	}
+
+	HSC = (Hsrc * (1 << 20)) / fmt->width - (1 << 20);
+	VSC = (1 << 16) - (Vsrc * (1 << 9) / Vlines - (1 << 9));
+	VSC &= 0x1fff;
+
+	if (fmt->width >= 385)
+		filter = 0;
+	else if (fmt->width > 192)
+		filter = 1;
+	else if (fmt->width > 96)
+		filter = 2;
+	else
+		filter = 3;
+
+	CX18_DEBUG_INFO_DEV(sd,
+			    "decoder set size %dx%d -> scale  %ux%u\n",
+			    fmt->width, fmt->height, HSC, VSC);
+
+	/* HSCALE=HSC */
+	cx18_av_write(cx, 0x418, HSC & 0xff);
+	cx18_av_write(cx, 0x419, (HSC >> 8) & 0xff);
+	cx18_av_write(cx, 0x41a, HSC >> 16);
+	/* VSCALE=VSC */
+	cx18_av_write(cx, 0x41c, VSC & 0xff);
+	cx18_av_write(cx, 0x41d, VSC >> 8);
+	/* VS_INTRLACE=1 VFILT=filter */
+	cx18_av_write(cx, 0x41e, 0x8 | filter);
+	return 0;
+}
+
+static int cx18_av_s_stream(struct v4l2_subdev *sd, int enable)
+{
+	struct cx18 *cx = v4l2_get_subdevdata(sd);
+
+	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);
+	} else {
+		cx18_av_write(cx, 0x115, 0x00);
+		cx18_av_write(cx, 0x116, 0x00);
+	}
+	return 0;
+}
+
+static void log_video_status(struct cx18 *cx)
+{
+	static const char *const fmt_strs[] = {
+		"0x0",
+		"NTSC-M", "NTSC-J", "NTSC-4.43",
+		"PAL-BDGHI", "PAL-M", "PAL-N", "PAL-Nc", "PAL-60",
+		"0x9", "0xA", "0xB",
+		"SECAM",
+		"0xD", "0xE", "0xF"
+	};
+
+	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_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_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_DEV(sd, "Specified video input:     Composite %d\n",
+			      vid_input - CX18_AV_COMPOSITE1 + 1);
+	} else {
+		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_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);
+	u8 audio_config = cx18_av_read(cx, 0x808);
+	u8 pref_mode = cx18_av_read(cx, 0x809);
+	u8 afc0 = cx18_av_read(cx, 0x80b);
+	u8 mute_ctl = cx18_av_read(cx, 0x8d3);
+	int aud_input = state->aud_input;
+	char *p;
+
+	switch (mod_det_stat0) {
+	case 0x00: p = "mono"; break;
+	case 0x01: p = "stereo"; break;
+	case 0x02: p = "dual"; break;
+	case 0x04: p = "tri"; break;
+	case 0x10: p = "mono with SAP"; break;
+	case 0x11: p = "stereo with SAP"; break;
+	case 0x12: p = "dual with SAP"; break;
+	case 0x14: p = "tri with SAP"; break;
+	case 0xfe: p = "forced mode"; break;
+	default: p = "not defined"; break;
+	}
+	CX18_INFO_DEV(sd, "Detected audio mode:       %s\n", p);
+
+	switch (mod_det_stat1) {
+	case 0x00: p = "not defined"; break;
+	case 0x01: p = "EIAJ"; break;
+	case 0x02: p = "A2-M"; break;
+	case 0x03: p = "A2-BG"; break;
+	case 0x04: p = "A2-DK1"; break;
+	case 0x05: p = "A2-DK2"; break;
+	case 0x06: p = "A2-DK3"; break;
+	case 0x07: p = "A1 (6.0 MHz FM Mono)"; break;
+	case 0x08: p = "AM-L"; break;
+	case 0x09: p = "NICAM-BG"; break;
+	case 0x0a: p = "NICAM-DK"; break;
+	case 0x0b: p = "NICAM-I"; break;
+	case 0x0c: p = "NICAM-L"; break;
+	case 0x0d: p = "BTSC/EIAJ/A2-M Mono (4.5 MHz FMMono)"; break;
+	case 0x0e: p = "IF FM Radio"; break;
+	case 0x0f: p = "BTSC"; break;
+	case 0x10: p = "detected chrominance"; break;
+	case 0xfd: p = "unknown audio standard"; break;
+	case 0xfe: p = "forced audio standard"; break;
+	case 0xff: p = "no detected audio standard"; break;
+	default: p = "not defined"; break;
+	}
+	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;
+	case 0x01: p = "BTSC"; break;
+	case 0x02: p = "EIAJ"; break;
+	case 0x03: p = "A2-M"; break;
+	case 0x04: p = "A2-BG"; break;
+	case 0x05: p = "A2-DK1"; break;
+	case 0x06: p = "A2-DK2"; break;
+	case 0x07: p = "A2-DK3"; break;
+	case 0x08: p = "A1 (6.0 MHz FM Mono)"; break;
+	case 0x09: p = "AM-L"; break;
+	case 0x0a: p = "NICAM-BG"; break;
+	case 0x0b: p = "NICAM-DK"; break;
+	case 0x0c: p = "NICAM-I"; break;
+	case 0x0d: p = "NICAM-L"; break;
+	case 0x0e: p = "FM radio"; break;
+	case 0x0f: p = "automatic detection"; break;
+	default: p = "undefined"; break;
+	}
+	CX18_INFO_DEV(sd, "Configured audio standard: %s\n", p);
+
+	if ((audio_config >> 4) < 0xF) {
+		switch (audio_config & 0xF) {
+		case 0x00: p = "MONO1 (LANGUAGE A/Mono L+R channel for BTSC, EIAJ, A2)"; break;
+		case 0x01: p = "MONO2 (LANGUAGE B)"; break;
+		case 0x02: p = "MONO3 (STEREO forced MONO)"; break;
+		case 0x03: p = "MONO4 (NICAM ANALOG-Language C/Analog Fallback)"; break;
+		case 0x04: p = "STEREO"; break;
+		case 0x05: p = "DUAL1 (AC)"; break;
+		case 0x06: p = "DUAL2 (BC)"; break;
+		case 0x07: p = "DUAL3 (AB)"; break;
+		default: p = "undefined";
+		}
+		CX18_INFO_DEV(sd, "Configured audio mode:     %s\n", p);
+	} else {
+		switch (audio_config & 0xF) {
+		case 0x00: p = "BG"; break;
+		case 0x01: p = "DK1"; break;
+		case 0x02: p = "DK2"; break;
+		case 0x03: p = "DK3"; break;
+		case 0x04: p = "I"; break;
+		case 0x05: p = "L"; break;
+		case 0x06: p = "BTSC"; break;
+		case 0x07: p = "EIAJ"; break;
+		case 0x08: p = "A2-M"; break;
+		case 0x09: p = "FM Radio (4.5 MHz)"; break;
+		case 0x0a: p = "FM Radio (5.5 MHz)"; break;
+		case 0x0b: p = "S-Video"; break;
+		case 0x0f: p = "automatic standard and mode detection"; break;
+		default: p = "undefined"; break;
+		}
+		CX18_INFO_DEV(sd, "Configured audio system:   %s\n", p);
+	}
+
+	if (aud_input)
+		CX18_INFO_DEV(sd, "Specified audio input:     Tuner (In%d)\n",
+			      aud_input);
+	else
+		CX18_INFO_DEV(sd, "Specified audio input:     External\n");
+
+	switch (pref_mode & 0xf) {
+	case 0: p = "mono/language A"; break;
+	case 1: p = "language B"; break;
+	case 2: p = "language C"; break;
+	case 3: p = "analog fallback"; break;
+	case 4: p = "stereo"; break;
+	case 5: p = "language AC"; break;
+	case 6: p = "language BC"; break;
+	case 7: p = "language AB"; break;
+	default: p = "undefined"; break;
+	}
+	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_DEV(sd, "Selected 65 MHz format:    %s\n", p);
+
+		switch (afc0 & 0x7) {
+		case 0: p = "Chroma"; break;
+		case 1: p = "BTSC"; break;
+		case 2: p = "EIAJ"; break;
+		case 3: p = "A2-M"; break;
+		case 4: p = "autodetect"; break;
+		default: p = "undefined"; break;
+		}
+		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_ctrl_ops cx18_av_ctrl_ops = {
+	.s_ctrl = cx18_av_s_ctrl,
+};
+
+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,
+	.load_fw = cx18_av_load_fw,
+	.reset = cx18_av_reset,
+	.g_ctrl = v4l2_subdev_g_ctrl,
+	.s_ctrl = v4l2_subdev_s_ctrl,
+	.s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
+	.try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
+	.g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
+	.queryctrl = v4l2_subdev_queryctrl,
+	.querymenu = v4l2_subdev_querymenu,
+	.s_std = cx18_av_s_std,
+#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,
+};
+
+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,
+	.s_stream = cx18_av_s_stream,
+	.s_mbus_fmt = cx18_av_s_mbus_fmt,
+};
+
+static const struct v4l2_subdev_vbi_ops cx18_av_vbi_ops = {
+	.decode_vbi_line = cx18_av_decode_vbi_line,
+	.g_sliced_fmt = cx18_av_g_sliced_fmt,
+	.s_sliced_fmt = cx18_av_s_sliced_fmt,
+	.s_raw_fmt = cx18_av_s_raw_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,
+	.vbi = &cx18_av_vbi_ops,
+};
+
+int cx18_av_probe(struct cx18 *cx)
+{
+	struct cx18_av_state *state = &cx->av_state;
+	struct v4l2_subdev *sd;
+	int err;
+
+	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;
+	v4l2_ctrl_handler_init(&state->hdl, 9);
+	v4l2_ctrl_new_std(&state->hdl, &cx18_av_ctrl_ops,
+			V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
+	v4l2_ctrl_new_std(&state->hdl, &cx18_av_ctrl_ops,
+			V4L2_CID_CONTRAST, 0, 127, 1, 64);
+	v4l2_ctrl_new_std(&state->hdl, &cx18_av_ctrl_ops,
+			V4L2_CID_SATURATION, 0, 127, 1, 64);
+	v4l2_ctrl_new_std(&state->hdl, &cx18_av_ctrl_ops,
+			V4L2_CID_HUE, -128, 127, 1, 0);
+
+	state->volume = v4l2_ctrl_new_std(&state->hdl,
+			&cx18_av_audio_ctrl_ops, V4L2_CID_AUDIO_VOLUME,
+			0, 65535, 65535 / 100, 0);
+	v4l2_ctrl_new_std(&state->hdl,
+			&cx18_av_audio_ctrl_ops, V4L2_CID_AUDIO_MUTE,
+			0, 1, 1, 0);
+	v4l2_ctrl_new_std(&state->hdl, &cx18_av_audio_ctrl_ops,
+			V4L2_CID_AUDIO_BALANCE,
+			0, 65535, 65535 / 100, 32768);
+	v4l2_ctrl_new_std(&state->hdl, &cx18_av_audio_ctrl_ops,
+			V4L2_CID_AUDIO_BASS,
+			0, 65535, 65535 / 100, 32768);
+	v4l2_ctrl_new_std(&state->hdl, &cx18_av_audio_ctrl_ops,
+			V4L2_CID_AUDIO_TREBLE,
+			0, 65535, 65535 / 100, 32768);
+	sd->ctrl_handler = &state->hdl;
+	if (state->hdl.error) {
+		int err = state->hdl.error;
+
+		v4l2_ctrl_handler_free(&state->hdl);
+		return err;
+	}
+	err = v4l2_device_register_subdev(&cx->v4l2_dev, sd);
+	if (err)
+		v4l2_ctrl_handler_free(&state->hdl);
+	else
+		cx18_av_init(cx);
+	return err;
+}
diff --git a/drivers/media/pci/cx18/cx18-av-core.h b/drivers/media/pci/cx18/cx18-av-core.h
new file mode 100644
index 0000000..e9c69d9
--- /dev/null
+++ b/drivers/media/pci/cx18/cx18-av-core.h
@@ -0,0 +1,391 @@
+/*
+ *  cx18 ADEC header
+ *
+ *  Derived from cx25840-core.h
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.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 program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You 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 _CX18_AV_CORE_H_
+#define _CX18_AV_CORE_H_
+
+#include <media/v4l2-device.h>
+#include <media/v4l2-ctrls.h>
+
+struct cx18;
+
+enum cx18_av_video_input {
+	/* Composite video inputs In1-In8 */
+	CX18_AV_COMPOSITE1 = 1,
+	CX18_AV_COMPOSITE2,
+	CX18_AV_COMPOSITE3,
+	CX18_AV_COMPOSITE4,
+	CX18_AV_COMPOSITE5,
+	CX18_AV_COMPOSITE6,
+	CX18_AV_COMPOSITE7,
+	CX18_AV_COMPOSITE8,
+
+	/* S-Video inputs consist of one luma input (In1-In8) ORed with one
+	   chroma input (In5-In8) */
+	CX18_AV_SVIDEO_LUMA1 = 0x10,
+	CX18_AV_SVIDEO_LUMA2 = 0x20,
+	CX18_AV_SVIDEO_LUMA3 = 0x30,
+	CX18_AV_SVIDEO_LUMA4 = 0x40,
+	CX18_AV_SVIDEO_LUMA5 = 0x50,
+	CX18_AV_SVIDEO_LUMA6 = 0x60,
+	CX18_AV_SVIDEO_LUMA7 = 0x70,
+	CX18_AV_SVIDEO_LUMA8 = 0x80,
+	CX18_AV_SVIDEO_CHROMA4 = 0x400,
+	CX18_AV_SVIDEO_CHROMA5 = 0x500,
+	CX18_AV_SVIDEO_CHROMA6 = 0x600,
+	CX18_AV_SVIDEO_CHROMA7 = 0x700,
+	CX18_AV_SVIDEO_CHROMA8 = 0x800,
+
+	/* S-Video aliases for common luma/chroma combinations */
+	CX18_AV_SVIDEO1 = 0x510,
+	CX18_AV_SVIDEO2 = 0x620,
+	CX18_AV_SVIDEO3 = 0x730,
+	CX18_AV_SVIDEO4 = 0x840,
+
+	/* Component Video inputs consist of one luma input (In1-In8) ORed
+	   with a red chroma (In4-In6) and blue chroma input (In7-In8) */
+	CX18_AV_COMPONENT_LUMA1 = 0x1000,
+	CX18_AV_COMPONENT_LUMA2 = 0x2000,
+	CX18_AV_COMPONENT_LUMA3 = 0x3000,
+	CX18_AV_COMPONENT_LUMA4 = 0x4000,
+	CX18_AV_COMPONENT_LUMA5 = 0x5000,
+	CX18_AV_COMPONENT_LUMA6 = 0x6000,
+	CX18_AV_COMPONENT_LUMA7 = 0x7000,
+	CX18_AV_COMPONENT_LUMA8 = 0x8000,
+	CX18_AV_COMPONENT_R_CHROMA4 = 0x40000,
+	CX18_AV_COMPONENT_R_CHROMA5 = 0x50000,
+	CX18_AV_COMPONENT_R_CHROMA6 = 0x60000,
+	CX18_AV_COMPONENT_B_CHROMA7 = 0x700000,
+	CX18_AV_COMPONENT_B_CHROMA8 = 0x800000,
+
+	/* Component Video aliases for common combinations */
+	CX18_AV_COMPONENT1 = 0x861000,
+};
+
+enum cx18_av_audio_input {
+	/* Audio inputs: serial or In4-In8 */
+	CX18_AV_AUDIO_SERIAL1,
+	CX18_AV_AUDIO_SERIAL2,
+	CX18_AV_AUDIO4 = 4,
+	CX18_AV_AUDIO5,
+	CX18_AV_AUDIO6,
+	CX18_AV_AUDIO7,
+	CX18_AV_AUDIO8,
+};
+
+struct cx18_av_state {
+	struct v4l2_subdev sd;
+	struct v4l2_ctrl_handler hdl;
+	struct v4l2_ctrl *volume;
+	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;
+	u32 id;
+	u32 rev;
+	int is_initialized;
+
+	/*
+	 * The VBI slicer starts operating and counting lines, beginning 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;
+};
+
+
+/* Registers */
+#define CXADEC_CHIP_TYPE_TIGER     0x837
+#define CXADEC_CHIP_TYPE_MAKO      0x843
+
+#define CXADEC_HOST_REG1           0x000
+#define CXADEC_HOST_REG2           0x001
+
+#define CXADEC_CHIP_CTRL           0x100
+#define CXADEC_AFE_CTRL            0x104
+#define CXADEC_PLL_CTRL1           0x108
+#define CXADEC_VID_PLL_FRAC        0x10C
+#define CXADEC_AUX_PLL_FRAC        0x110
+#define CXADEC_PIN_CTRL1           0x114
+#define CXADEC_PIN_CTRL2           0x118
+#define CXADEC_PIN_CFG1            0x11C
+#define CXADEC_PIN_CFG2            0x120
+
+#define CXADEC_PIN_CFG3            0x124
+#define CXADEC_I2S_MCLK            0x127
+
+#define CXADEC_AUD_LOCK1           0x128
+#define CXADEC_AUD_LOCK2           0x12C
+#define CXADEC_POWER_CTRL          0x130
+#define CXADEC_AFE_DIAG_CTRL1      0x134
+#define CXADEC_AFE_DIAG_CTRL2      0x138
+#define CXADEC_AFE_DIAG_CTRL3      0x13C
+#define CXADEC_PLL_DIAG_CTRL       0x140
+#define CXADEC_TEST_CTRL1          0x144
+#define CXADEC_TEST_CTRL2          0x148
+#define CXADEC_BIST_STAT           0x14C
+#define CXADEC_DLL1_DIAG_CTRL      0x158
+#define CXADEC_DLL2_DIAG_CTRL      0x15C
+
+/* IR registers */
+#define CXADEC_IR_CTRL_REG         0x200
+#define CXADEC_IR_TXCLK_REG        0x204
+#define CXADEC_IR_RXCLK_REG        0x208
+#define CXADEC_IR_CDUTY_REG        0x20C
+#define CXADEC_IR_STAT_REG         0x210
+#define CXADEC_IR_IRQEN_REG        0x214
+#define CXADEC_IR_FILTER_REG       0x218
+#define CXADEC_IR_FIFO_REG         0x21C
+
+/* Video Registers */
+#define CXADEC_MODE_CTRL           0x400
+#define CXADEC_OUT_CTRL1           0x404
+#define CXADEC_OUT_CTRL2           0x408
+#define CXADEC_GEN_STAT            0x40C
+#define CXADEC_INT_STAT_MASK       0x410
+#define CXADEC_LUMA_CTRL           0x414
+
+#define CXADEC_BRIGHTNESS_CTRL_BYTE 0x414
+#define CXADEC_CONTRAST_CTRL_BYTE  0x415
+#define CXADEC_LUMA_CTRL_BYTE_3    0x416
+
+#define CXADEC_HSCALE_CTRL         0x418
+#define CXADEC_VSCALE_CTRL         0x41C
+
+#define CXADEC_CHROMA_CTRL         0x420
+
+#define CXADEC_USAT_CTRL_BYTE      0x420
+#define CXADEC_VSAT_CTRL_BYTE      0x421
+#define CXADEC_HUE_CTRL_BYTE       0x422
+
+#define CXADEC_VBI_LINE_CTRL1      0x424
+#define CXADEC_VBI_LINE_CTRL2      0x428
+#define CXADEC_VBI_LINE_CTRL3      0x42C
+#define CXADEC_VBI_LINE_CTRL4      0x430
+#define CXADEC_VBI_LINE_CTRL5      0x434
+#define CXADEC_VBI_FC_CFG          0x438
+#define CXADEC_VBI_MISC_CFG1       0x43C
+#define CXADEC_VBI_MISC_CFG2       0x440
+#define CXADEC_VBI_PAY1            0x444
+#define CXADEC_VBI_PAY2            0x448
+#define CXADEC_VBI_CUST1_CFG1      0x44C
+#define CXADEC_VBI_CUST1_CFG2      0x450
+#define CXADEC_VBI_CUST1_CFG3      0x454
+#define CXADEC_VBI_CUST2_CFG1      0x458
+#define CXADEC_VBI_CUST2_CFG2      0x45C
+#define CXADEC_VBI_CUST2_CFG3      0x460
+#define CXADEC_VBI_CUST3_CFG1      0x464
+#define CXADEC_VBI_CUST3_CFG2      0x468
+#define CXADEC_VBI_CUST3_CFG3      0x46C
+#define CXADEC_HORIZ_TIM_CTRL      0x470
+#define CXADEC_VERT_TIM_CTRL       0x474
+#define CXADEC_SRC_COMB_CFG        0x478
+#define CXADEC_CHROMA_VBIOFF_CFG   0x47C
+#define CXADEC_FIELD_COUNT         0x480
+#define CXADEC_MISC_TIM_CTRL       0x484
+#define CXADEC_DFE_CTRL1           0x488
+#define CXADEC_DFE_CTRL2           0x48C
+#define CXADEC_DFE_CTRL3           0x490
+#define CXADEC_PLL_CTRL2           0x494
+#define CXADEC_HTL_CTRL            0x498
+#define CXADEC_COMB_CTRL           0x49C
+#define CXADEC_CRUSH_CTRL          0x4A0
+#define CXADEC_SOFT_RST_CTRL       0x4A4
+#define CXADEC_MV_DT_CTRL2         0x4A8
+#define CXADEC_MV_DT_CTRL3         0x4AC
+#define CXADEC_MISC_DIAG_CTRL      0x4B8
+
+#define CXADEC_DL_CTL              0x800
+#define CXADEC_DL_CTL_ADDRESS_LOW  0x800   /* Byte 1 in DL_CTL */
+#define CXADEC_DL_CTL_ADDRESS_HIGH 0x801   /* Byte 2 in DL_CTL */
+#define CXADEC_DL_CTL_DATA         0x802   /* Byte 3 in DL_CTL */
+#define CXADEC_DL_CTL_CONTROL      0x803   /* Byte 4 in DL_CTL */
+
+#define CXADEC_STD_DET_STATUS      0x804
+
+#define CXADEC_STD_DET_CTL         0x808
+#define CXADEC_STD_DET_CTL_AUD_CTL   0x808 /* Byte 1 in STD_DET_CTL */
+#define CXADEC_STD_DET_CTL_PREF_MODE 0x809 /* Byte 2 in STD_DET_CTL */
+
+#define CXADEC_DW8051_INT          0x80C
+#define CXADEC_GENERAL_CTL         0x810
+#define CXADEC_AAGC_CTL            0x814
+#define CXADEC_IF_SRC_CTL          0x818
+#define CXADEC_ANLOG_DEMOD_CTL     0x81C
+#define CXADEC_ROT_FREQ_CTL        0x820
+#define CXADEC_FM1_CTL             0x824
+#define CXADEC_PDF_CTL             0x828
+#define CXADEC_DFT1_CTL1           0x82C
+#define CXADEC_DFT1_CTL2           0x830
+#define CXADEC_DFT_STATUS          0x834
+#define CXADEC_DFT2_CTL1           0x838
+#define CXADEC_DFT2_CTL2           0x83C
+#define CXADEC_DFT2_STATUS         0x840
+#define CXADEC_DFT3_CTL1           0x844
+#define CXADEC_DFT3_CTL2           0x848
+#define CXADEC_DFT3_STATUS         0x84C
+#define CXADEC_DFT4_CTL1           0x850
+#define CXADEC_DFT4_CTL2           0x854
+#define CXADEC_DFT4_STATUS         0x858
+#define CXADEC_AM_MTS_DET          0x85C
+#define CXADEC_ANALOG_MUX_CTL      0x860
+#define CXADEC_DIG_PLL_CTL1        0x864
+#define CXADEC_DIG_PLL_CTL2        0x868
+#define CXADEC_DIG_PLL_CTL3        0x86C
+#define CXADEC_DIG_PLL_CTL4        0x870
+#define CXADEC_DIG_PLL_CTL5        0x874
+#define CXADEC_DEEMPH_GAIN_CTL     0x878
+#define CXADEC_DEEMPH_COEF1        0x87C
+#define CXADEC_DEEMPH_COEF2        0x880
+#define CXADEC_DBX1_CTL1           0x884
+#define CXADEC_DBX1_CTL2           0x888
+#define CXADEC_DBX1_STATUS         0x88C
+#define CXADEC_DBX2_CTL1           0x890
+#define CXADEC_DBX2_CTL2           0x894
+#define CXADEC_DBX2_STATUS         0x898
+#define CXADEC_AM_FM_DIFF          0x89C
+
+/* NICAM registers go here */
+#define CXADEC_NICAM_STATUS        0x8C8
+#define CXADEC_DEMATRIX_CTL        0x8CC
+
+#define CXADEC_PATH1_CTL1          0x8D0
+#define CXADEC_PATH1_VOL_CTL       0x8D4
+#define CXADEC_PATH1_EQ_CTL        0x8D8
+#define CXADEC_PATH1_SC_CTL        0x8DC
+
+#define CXADEC_PATH2_CTL1          0x8E0
+#define CXADEC_PATH2_VOL_CTL       0x8E4
+#define CXADEC_PATH2_EQ_CTL        0x8E8
+#define CXADEC_PATH2_SC_CTL        0x8EC
+
+#define CXADEC_SRC_CTL             0x8F0
+#define CXADEC_SRC_LF_COEF         0x8F4
+#define CXADEC_SRC1_CTL            0x8F8
+#define CXADEC_SRC2_CTL            0x8FC
+#define CXADEC_SRC3_CTL            0x900
+#define CXADEC_SRC4_CTL            0x904
+#define CXADEC_SRC5_CTL            0x908
+#define CXADEC_SRC6_CTL            0x90C
+
+#define CXADEC_BASEBAND_OUT_SEL    0x910
+#define CXADEC_I2S_IN_CTL          0x914
+#define CXADEC_I2S_OUT_CTL         0x918
+#define CXADEC_AC97_CTL            0x91C
+#define CXADEC_QAM_PDF             0x920
+#define CXADEC_QAM_CONST_DEC       0x924
+#define CXADEC_QAM_ROTATOR_FREQ    0x948
+
+/* Bit definitions / settings used in Mako Audio */
+#define CXADEC_PREF_MODE_MONO_LANGA        0
+#define CXADEC_PREF_MODE_MONO_LANGB        1
+#define CXADEC_PREF_MODE_MONO_LANGC        2
+#define CXADEC_PREF_MODE_FALLBACK          3
+#define CXADEC_PREF_MODE_STEREO            4
+#define CXADEC_PREF_MODE_DUAL_LANG_AC      5
+#define CXADEC_PREF_MODE_DUAL_LANG_BC      6
+#define CXADEC_PREF_MODE_DUAL_LANG_AB      7
+
+
+#define CXADEC_DETECT_STEREO               1
+#define CXADEC_DETECT_DUAL                 2
+#define CXADEC_DETECT_TRI                  4
+#define CXADEC_DETECT_SAP                  0x10
+#define CXADEC_DETECT_NO_SIGNAL            0xFF
+
+#define CXADEC_SELECT_AUDIO_STANDARD_BG    0xF0  /* NICAM BG and A2 BG */
+#define CXADEC_SELECT_AUDIO_STANDARD_DK1   0xF1  /* NICAM DK and A2 DK */
+#define CXADEC_SELECT_AUDIO_STANDARD_DK2   0xF2
+#define CXADEC_SELECT_AUDIO_STANDARD_DK3   0xF3
+#define CXADEC_SELECT_AUDIO_STANDARD_I     0xF4  /* NICAM I and A1 */
+#define CXADEC_SELECT_AUDIO_STANDARD_L     0xF5  /* NICAM L and System L AM */
+#define CXADEC_SELECT_AUDIO_STANDARD_BTSC  0xF6
+#define CXADEC_SELECT_AUDIO_STANDARD_EIAJ  0xF7
+#define CXADEC_SELECT_AUDIO_STANDARD_A2_M  0xF8  /* A2 M */
+#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);
+}
+
+static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
+{
+	return &container_of(ctrl->handler, struct cx18_av_state, hdl)->sd;
+}
+
+/* ----------------------------------------------------------------------- */
+/* cx18_av-core.c 							   */
+int cx18_av_write(struct cx18 *cx, u16 addr, u8 value);
+int cx18_av_write4(struct cx18 *cx, u16 addr, u32 value);
+int cx18_av_write4_noretry(struct cx18 *cx, u16 addr, u32 value);
+int cx18_av_write_expect(struct cx18 *cx, u16 addr, u8 value, u8 eval, u8 mask);
+int cx18_av_write4_expect(struct cx18 *cx, u16 addr, u32 value, u32 eval,
+			  u32 mask);
+u8 cx18_av_read(struct cx18 *cx, u16 addr);
+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);
+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_s_clock_freq(struct v4l2_subdev *sd, u32 freq);
+void cx18_av_audio_set_path(struct cx18 *cx);
+extern const struct v4l2_ctrl_ops cx18_av_audio_ctrl_ops;
+
+/* ----------------------------------------------------------------------- */
+/* cx18_av-vbi.c                                                           */
+int cx18_av_decode_vbi_line(struct v4l2_subdev *sd,
+			   struct v4l2_decode_vbi_line *vbi);
+int cx18_av_s_raw_fmt(struct v4l2_subdev *sd, struct v4l2_vbi_format *fmt);
+int cx18_av_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt);
+int cx18_av_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt);
+
+#endif
diff --git a/drivers/media/pci/cx18/cx18-av-firmware.c b/drivers/media/pci/cx18/cx18-av-firmware.c
new file mode 100644
index 0000000..a34fd08
--- /dev/null
+++ b/drivers/media/pci/cx18/cx18-av-firmware.c
@@ -0,0 +1,225 @@
+/*
+ *  cx18 ADEC firmware functions
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.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 program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You 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 "cx18-driver.h"
+#include "cx18-io.h"
+#include <linux/firmware.h>
+
+#define CX18_AUDIO_ENABLE    0xc72014
+#define CX18_AI1_MUX_MASK    0x30
+#define CX18_AI1_MUX_I2S1    0x00
+#define CX18_AI1_MUX_I2S2    0x10
+#define CX18_AI1_MUX_843_I2S 0x20
+#define CX18_AI1_MUX_INVALID 0x30
+
+#define FWFILE "v4l-cx23418-dig.fw"
+
+static int cx18_av_verifyfw(struct cx18 *cx, const struct firmware *fw)
+{
+	struct v4l2_subdev *sd = &cx->av_state.sd;
+	int ret = 0;
+	const u8 *data;
+	u32 size;
+	int addr;
+	u32 expected, dl_control;
+
+	/* Ensure we put the 8051 in reset and enable firmware upload mode */
+	dl_control = cx18_av_read4(cx, CXADEC_DL_CTL);
+	do {
+		dl_control &= 0x00ffffff;
+		dl_control |= 0x0f000000;
+		cx18_av_write4_noretry(cx, CXADEC_DL_CTL, dl_control);
+		dl_control = cx18_av_read4(cx, CXADEC_DL_CTL);
+	} while ((dl_control & 0xff000000) != 0x0f000000);
+
+	/* Read and auto increment until at address 0x0000 */
+	while (dl_control & 0x3fff)
+		dl_control = cx18_av_read4(cx, CXADEC_DL_CTL);
+
+	data = fw->data;
+	size = fw->size;
+	for (addr = 0; addr < size; addr++) {
+		dl_control &= 0xffff3fff; /* ignore top 2 bits of address */
+		expected = 0x0f000000 | ((u32)data[addr] << 16) | addr;
+		if (expected != dl_control) {
+			CX18_ERR_DEV(sd, "verification of %s firmware load "
+				     "failed: expected %#010x got %#010x\n",
+				     FWFILE, expected, dl_control);
+			ret = -EIO;
+			break;
+		}
+		dl_control = cx18_av_read4(cx, CXADEC_DL_CTL);
+	}
+	if (ret == 0)
+		CX18_INFO_DEV(sd, "verified load of %s firmware (%d bytes)\n",
+			      FWFILE, size);
+	return ret;
+}
+
+int cx18_av_loadfw(struct cx18 *cx)
+{
+	struct v4l2_subdev *sd = &cx->av_state.sd;
+	const struct firmware *fw = NULL;
+	u32 size;
+	u32 u, v;
+	const u8 *ptr;
+	int i;
+	int retries1 = 0;
+
+	if (request_firmware(&fw, FWFILE, &cx->pci_dev->dev) != 0) {
+		CX18_ERR_DEV(sd, "unable to open firmware %s\n", FWFILE);
+		return -EINVAL;
+	}
+
+	/* The firmware load often has byte errors, so allow for several
+	   retries, both at byte level and at the firmware load level. */
+	while (retries1 < 5) {
+		cx18_av_write4_expect(cx, CXADEC_CHIP_CTRL, 0x00010000,
+					  0x00008430, 0xffffffff); /* cx25843 */
+		cx18_av_write_expect(cx, CXADEC_STD_DET_CTL, 0xf6, 0xf6, 0xff);
+
+		/* Reset the Mako core, Register is alias of CXADEC_CHIP_CTRL */
+		cx18_av_write4_expect(cx, 0x8100, 0x00010000,
+					  0x00008430, 0xffffffff); /* cx25843 */
+
+		/* Put the 8051 in reset and enable firmware upload */
+		cx18_av_write4_noretry(cx, CXADEC_DL_CTL, 0x0F000000);
+
+		ptr = fw->data;
+		size = fw->size;
+
+		for (i = 0; i < size; i++) {
+			u32 dl_control = 0x0F000000 | i | ((u32)ptr[i] << 16);
+			u32 value = 0;
+			int retries2;
+			int unrec_err = 0;
+
+			for (retries2 = 0; retries2 < CX18_MAX_MMIO_WR_RETRIES;
+			     retries2++) {
+				cx18_av_write4_noretry(cx, CXADEC_DL_CTL,
+						       dl_control);
+				udelay(10);
+				value = cx18_av_read4(cx, CXADEC_DL_CTL);
+				if (value == dl_control)
+					break;
+				/* Check if we can correct the byte by changing
+				   the address.  We can only write the lower
+				   address byte of the address. */
+				if ((value & 0x3F00) != (dl_control & 0x3F00)) {
+					unrec_err = 1;
+					break;
+				}
+			}
+			if (unrec_err || retries2 >= CX18_MAX_MMIO_WR_RETRIES)
+				break;
+		}
+		if (i == size)
+			break;
+		retries1++;
+	}
+	if (retries1 >= 5) {
+		CX18_ERR_DEV(sd, "unable to load firmware %s\n", FWFILE);
+		release_firmware(fw);
+		return -EIO;
+	}
+
+	cx18_av_write4_expect(cx, CXADEC_DL_CTL,
+				0x03000000 | fw->size, 0x03000000, 0x13000000);
+
+	CX18_INFO_DEV(sd, "loaded %s firmware (%d bytes)\n", FWFILE, size);
+
+	if (cx18_av_verifyfw(cx, fw) == 0)
+		cx18_av_write4_expect(cx, CXADEC_DL_CTL,
+				0x13000000 | fw->size, 0x13000000, 0x13000000);
+
+	/* Output to the 416 */
+	cx18_av_and_or4(cx, CXADEC_PIN_CTRL1, ~0, 0x78000);
+
+	/* Audio input control 1 set to Sony mode */
+	/* Audio output input 2 is 0 for slave operation input */
+	/* 0xC4000914[5]: 0 = left sample on WS=0, 1 = left sample on WS=1 */
+	/* 0xC4000914[7]: 0 = Philips mode, 1 = Sony mode (1st SCK rising edge
+	   after WS transition for first bit of audio word. */
+	cx18_av_write4(cx, CXADEC_I2S_IN_CTL, 0x000000A0);
+
+	/* Audio output control 1 is set to Sony mode */
+	/* Audio output control 2 is set to 1 for master mode */
+	/* 0xC4000918[5]: 0 = left sample on WS=0, 1 = left sample on WS=1 */
+	/* 0xC4000918[7]: 0 = Philips mode, 1 = Sony mode (1st SCK rising edge
+	   after WS transition for first bit of audio word. */
+	/* 0xC4000918[8]: 0 = slave operation, 1 = master (SCK_OUT and WS_OUT
+	   are generated) */
+	cx18_av_write4(cx, CXADEC_I2S_OUT_CTL, 0x000001A0);
+
+	/* set alt I2s master clock to /0x16 and enable alt divider i2s
+	   passthrough */
+	cx18_av_write4(cx, CXADEC_PIN_CFG3, 0x5600B687);
+
+	cx18_av_write4_expect(cx, CXADEC_STD_DET_CTL, 0x000000F6, 0x000000F6,
+								  0x3F00FFFF);
+	/* CxDevWrReg(CXADEC_STD_DET_CTL, 0x000000FF); */
+
+	/* Set bit 0 in register 0x9CC to signify that this is MiniMe. */
+	/* Register 0x09CC is defined by the Merlin firmware, and doesn't
+	   have a name in the spec. */
+	cx18_av_write4(cx, 0x09CC, 1);
+
+	v = cx18_read_reg(cx, CX18_AUDIO_ENABLE);
+	/* If bit 11 is 1, clear bit 10 */
+	if (v & 0x800)
+		cx18_write_reg_expect(cx, v & 0xFFFFFBFF, CX18_AUDIO_ENABLE,
+				      0, 0x400);
+
+	/* Toggle the AI1 MUX */
+	v = cx18_read_reg(cx, CX18_AUDIO_ENABLE);
+	u = v & CX18_AI1_MUX_MASK;
+	v &= ~CX18_AI1_MUX_MASK;
+	if (u == CX18_AI1_MUX_843_I2S || u == CX18_AI1_MUX_INVALID) {
+		/* Switch to I2S1 */
+		v |= CX18_AI1_MUX_I2S1;
+		cx18_write_reg_expect(cx, v | 0xb00, CX18_AUDIO_ENABLE,
+				      v, CX18_AI1_MUX_MASK);
+		/* Switch back to the A/V decoder core I2S output */
+		v = (v & ~CX18_AI1_MUX_MASK) | CX18_AI1_MUX_843_I2S;
+	} else {
+		/* Switch to the A/V decoder core I2S output */
+		v |= CX18_AI1_MUX_843_I2S;
+		cx18_write_reg_expect(cx, v | 0xb00, CX18_AUDIO_ENABLE,
+				      v, CX18_AI1_MUX_MASK);
+		/* Switch back to I2S1 or I2S2 */
+		v = (v & ~CX18_AI1_MUX_MASK) | u;
+	}
+	cx18_write_reg_expect(cx, v | 0xb00, CX18_AUDIO_ENABLE,
+			      v, CX18_AI1_MUX_MASK);
+
+	/* Enable WW auto audio standard detection */
+	v = cx18_av_read4(cx, CXADEC_STD_DET_CTL);
+	v |= 0xFF;   /* Auto by default */
+	v |= 0x400;  /* Stereo by default */
+	v |= 0x14000000;
+	cx18_av_write4_expect(cx, CXADEC_STD_DET_CTL, v, v, 0x3F00FFFF);
+
+	release_firmware(fw);
+	return 0;
+}
+
+MODULE_FIRMWARE(FWFILE);
diff --git a/drivers/media/pci/cx18/cx18-av-vbi.c b/drivers/media/pci/cx18/cx18-av-vbi.c
new file mode 100644
index 0000000..baa36fb
--- /dev/null
+++ b/drivers/media/pci/cx18/cx18-av-vbi.c
@@ -0,0 +1,311 @@
+/*
+ *  cx18 ADEC VBI functions
+ *
+ *  Derived from cx25840-vbi.c
+ *
+ *  Copyright (C) 2007  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., 51 Franklin Street, Fifth Floor, Boston, MA
+ *  02110-1301, USA.
+ */
+
+
+#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);
+	c ^= (c >> 2);
+	c ^= (c >> 1);
+
+	return c & 1;
+}
+
+static int decode_vps(u8 *dst, u8 *p)
+{
+	static const u8 biphase_tbl[] = {
+		0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
+		0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
+		0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96,
+		0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2,
+		0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94,
+		0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0,
+		0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
+		0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
+		0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5,
+		0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1,
+		0xc3, 0x4b, 0x43, 0xc3, 0x87, 0x0f, 0x07, 0x87,
+		0x83, 0x0b, 0x03, 0x83, 0xc3, 0x4b, 0x43, 0xc3,
+		0xc1, 0x49, 0x41, 0xc1, 0x85, 0x0d, 0x05, 0x85,
+		0x81, 0x09, 0x01, 0x81, 0xc1, 0x49, 0x41, 0xc1,
+		0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5,
+		0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1,
+		0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4,
+		0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0,
+		0xc2, 0x4a, 0x42, 0xc2, 0x86, 0x0e, 0x06, 0x86,
+		0x82, 0x0a, 0x02, 0x82, 0xc2, 0x4a, 0x42, 0xc2,
+		0xc0, 0x48, 0x40, 0xc0, 0x84, 0x0c, 0x04, 0x84,
+		0x80, 0x08, 0x00, 0x80, 0xc0, 0x48, 0x40, 0xc0,
+		0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4,
+		0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0,
+		0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
+		0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
+		0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96,
+		0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2,
+		0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94,
+		0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0,
+		0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
+		0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
+	};
+
+	u8 c, err = 0;
+	int i;
+
+	for (i = 0; i < 2 * 13; i += 2) {
+		err |= biphase_tbl[p[i]] | biphase_tbl[p[i + 1]];
+		c = (biphase_tbl[p[i + 1]] & 0xf) |
+		    ((biphase_tbl[p[i]] & 0xf) << 4);
+		dst[i / 2] = c;
+	}
+
+	return err & 0xf0;
+}
+
+int cx18_av_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *svbi)
+{
+	struct cx18 *cx = v4l2_get_subdevdata(sd);
+	struct cx18_av_state *state = &cx->av_state;
+	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;
+
+	memset(svbi, 0, sizeof(*svbi));
+	/* we're done if raw VBI is active */
+	if ((cx18_av_read(cx, 0x404) & 0x10) == 0)
+		return 0;
+
+	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];
+		}
+	}
+	return 0;
+}
+
+int cx18_av_s_raw_fmt(struct v4l2_subdev *sd, struct v4l2_vbi_format *fmt)
+{
+	struct cx18 *cx = v4l2_get_subdevdata(sd);
+	struct cx18_av_state *state = &cx->av_state;
+
+	/* Setup standard */
+	cx18_av_std_setup(cx);
+
+	/* VBI Offset */
+	cx18_av_write(cx, 0x47f, state->slicer_line_delay);
+	cx18_av_write(cx, 0x404, 0x2e);
+	return 0;
+}
+
+int cx18_av_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *svbi)
+{
+	struct cx18 *cx = v4l2_get_subdevdata(sd);
+	struct cx18_av_state *state = &cx->av_state;
+	int is_pal = !(state->std & V4L2_STD_525_60);
+	int i, x;
+	u8 lcr[24];
+
+	for (x = 0; x <= 23; x++)
+		lcr[x] = 0x00;
+
+	/* 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, 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);
+	/* Should match vblank set in cx18_av_std_setup() */
+	cx18_av_write(cx, 0x474, is_pal ? 38 : 26);
+	return 0;
+}
+
+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;
+
+	/*
+	 * 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;
+	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/pci/cx18/cx18-cards.c b/drivers/media/pci/cx18/cx18-cards.c
new file mode 100644
index 0000000..c07c849
--- /dev/null
+++ b/drivers/media/pci/cx18/cx18-cards.c
@@ -0,0 +1,638 @@
+/*
+ *  cx18 functions to query card hardware
+ *
+ *  Derived from ivtv-cards.c
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.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 program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public 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 "cx18-driver.h"
+#include "cx18-cards.h"
+#include "cx18-av-core.h"
+#include "cx18-i2c.h"
+#include <media/cs5345.h>
+
+#define V4L2_STD_PAL_SECAM (V4L2_STD_PAL|V4L2_STD_SECAM)
+
+/********************** card configuration *******************************/
+
+/* usual i2c tuner addresses to probe */
+static struct cx18_card_tuner_i2c cx18_i2c_std = {
+	.radio = { I2C_CLIENT_END },
+	.demod = { 0x43, I2C_CLIENT_END },
+	.tv    = { 0x61, 0x60, I2C_CLIENT_END },
+};
+
+/*
+ * usual i2c tuner addresses to probe with additional demod address for
+ * an NXP TDA8295 at 0x42 (N.B. it can possibly be at 0x4b or 0x4c too).
+ */
+static struct cx18_card_tuner_i2c cx18_i2c_nxp = {
+	.radio = { I2C_CLIENT_END },
+	.demod = { 0x42, 0x43, I2C_CLIENT_END },
+	.tv    = { 0x61, 0x60, I2C_CLIENT_END },
+};
+
+/* Please add new PCI IDs to: http://pci-ids.ucw.cz/
+   This keeps the PCI ID database up to date. Note that the entries
+   must be added under vendor 0x4444 (Conexant) as subsystem IDs.
+   New vendor IDs should still be added to the vendor ID list. */
+
+/* Hauppauge HVR-1600 cards */
+
+/* Note: for Hauppauge cards the tveeprom information is used instead
+   of PCI IDs */
+static const struct cx18_card cx18_card_hvr1600_esmt = {
+	.type = CX18_CARD_HVR_1600_ESMT,
+	.name = "Hauppauge HVR-1600",
+	.comment = "Simultaneous Digital and Analog TV capture supported\n",
+	.v4l2_capabilities = CX18_CAP_ENCODER,
+	.hw_audio_ctrl = CX18_HW_418_AV,
+	.hw_muxer = CX18_HW_CS5345,
+	.hw_all = CX18_HW_TVEEPROM | CX18_HW_418_AV | CX18_HW_TUNER |
+		  CX18_HW_CS5345 | CX18_HW_DVB | CX18_HW_GPIO_RESET_CTRL |
+		  CX18_HW_Z8F0811_IR_HAUP,
+	.video_inputs = {
+		{ CX18_CARD_INPUT_VID_TUNER,  0, CX18_AV_COMPOSITE7 },
+		{ CX18_CARD_INPUT_SVIDEO1,    1, CX18_AV_SVIDEO1    },
+		{ CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE3 },
+		{ CX18_CARD_INPUT_SVIDEO2,    2, CX18_AV_SVIDEO2    },
+		{ CX18_CARD_INPUT_COMPOSITE2, 2, CX18_AV_COMPOSITE4 },
+	},
+	.audio_inputs = {
+		{ CX18_CARD_INPUT_AUD_TUNER,
+		  CX18_AV_AUDIO8, CS5345_IN_1 | CS5345_MCLK_1_5 },
+		{ CX18_CARD_INPUT_LINE_IN1,
+		  CX18_AV_AUDIO_SERIAL1, CS5345_IN_2 },
+		{ CX18_CARD_INPUT_LINE_IN2,
+		  CX18_AV_AUDIO_SERIAL1, CS5345_IN_3 },
+	},
+	.radio_input = { CX18_CARD_INPUT_AUD_TUNER,
+			 CX18_AV_AUDIO_SERIAL1, CS5345_IN_4 },
+	.ddr = {
+		/* ESMT M13S128324A-5B memory */
+		.chip_config = 0x003,
+		.refresh = 0x30c,
+		.timing1 = 0x44220e82,
+		.timing2 = 0x08,
+		.tune_lane = 0,
+		.initial_emrs = 0,
+	},
+	.gpio_init.initial_value = 0x3001,
+	.gpio_init.direction = 0x3001,
+	.gpio_i2c_slave_reset = {
+		.active_lo_mask = 0x3001,
+		.msecs_asserted = 10,
+		.msecs_recovery = 40,
+		.ir_reset_mask  = 0x0001,
+	},
+	.i2c = &cx18_i2c_std,
+};
+
+static const struct cx18_card cx18_card_hvr1600_s5h1411 = {
+	.type = CX18_CARD_HVR_1600_S5H1411,
+	.name = "Hauppauge HVR-1600",
+	.comment = "Simultaneous Digital and Analog TV capture supported\n",
+	.v4l2_capabilities = CX18_CAP_ENCODER,
+	.hw_audio_ctrl = CX18_HW_418_AV,
+	.hw_muxer = CX18_HW_CS5345,
+	.hw_all = CX18_HW_TVEEPROM | CX18_HW_418_AV | CX18_HW_TUNER |
+		  CX18_HW_CS5345 | CX18_HW_DVB | CX18_HW_GPIO_RESET_CTRL |
+		  CX18_HW_Z8F0811_IR_HAUP,
+	.video_inputs = {
+		{ CX18_CARD_INPUT_VID_TUNER,  0, CX18_AV_COMPOSITE7 },
+		{ CX18_CARD_INPUT_SVIDEO1,    1, CX18_AV_SVIDEO1    },
+		{ CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE3 },
+		{ CX18_CARD_INPUT_SVIDEO2,    2, CX18_AV_SVIDEO2    },
+		{ CX18_CARD_INPUT_COMPOSITE2, 2, CX18_AV_COMPOSITE4 },
+	},
+	.audio_inputs = {
+		{ CX18_CARD_INPUT_AUD_TUNER,
+		  CX18_AV_AUDIO8, CS5345_IN_1 | CS5345_MCLK_1_5 },
+		{ CX18_CARD_INPUT_LINE_IN1,
+		  CX18_AV_AUDIO_SERIAL1, CS5345_IN_2 },
+		{ CX18_CARD_INPUT_LINE_IN2,
+		  CX18_AV_AUDIO_SERIAL1, CS5345_IN_3 },
+	},
+	.radio_input = { CX18_CARD_INPUT_AUD_TUNER,
+			 CX18_AV_AUDIO_SERIAL1, CS5345_IN_4 },
+	.ddr = {
+		/* ESMT M13S128324A-5B memory */
+		.chip_config = 0x003,
+		.refresh = 0x30c,
+		.timing1 = 0x44220e82,
+		.timing2 = 0x08,
+		.tune_lane = 0,
+		.initial_emrs = 0,
+	},
+	.gpio_init.initial_value = 0x3801,
+	.gpio_init.direction = 0x3801,
+	.gpio_i2c_slave_reset = {
+		.active_lo_mask = 0x3801,
+		.msecs_asserted = 10,
+		.msecs_recovery = 40,
+		.ir_reset_mask  = 0x0001,
+	},
+	.i2c = &cx18_i2c_nxp,
+};
+
+static const struct cx18_card cx18_card_hvr1600_samsung = {
+	.type = CX18_CARD_HVR_1600_SAMSUNG,
+	.name = "Hauppauge HVR-1600 (Preproduction)",
+	.comment = "Simultaneous Digital and Analog TV capture supported\n",
+	.v4l2_capabilities = CX18_CAP_ENCODER,
+	.hw_audio_ctrl = CX18_HW_418_AV,
+	.hw_muxer = CX18_HW_CS5345,
+	.hw_all = CX18_HW_TVEEPROM | CX18_HW_418_AV | CX18_HW_TUNER |
+		  CX18_HW_CS5345 | CX18_HW_DVB | CX18_HW_GPIO_RESET_CTRL |
+		  CX18_HW_Z8F0811_IR_HAUP,
+	.video_inputs = {
+		{ CX18_CARD_INPUT_VID_TUNER,  0, CX18_AV_COMPOSITE7 },
+		{ CX18_CARD_INPUT_SVIDEO1,    1, CX18_AV_SVIDEO1    },
+		{ CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE3 },
+		{ CX18_CARD_INPUT_SVIDEO2,    2, CX18_AV_SVIDEO2    },
+		{ CX18_CARD_INPUT_COMPOSITE2, 2, CX18_AV_COMPOSITE4 },
+	},
+	.audio_inputs = {
+		{ CX18_CARD_INPUT_AUD_TUNER,
+		  CX18_AV_AUDIO8, CS5345_IN_1 | CS5345_MCLK_1_5 },
+		{ CX18_CARD_INPUT_LINE_IN1,
+		  CX18_AV_AUDIO_SERIAL1, CS5345_IN_2 },
+		{ CX18_CARD_INPUT_LINE_IN2,
+		  CX18_AV_AUDIO_SERIAL1, CS5345_IN_3 },
+	},
+	.radio_input = { CX18_CARD_INPUT_AUD_TUNER,
+			 CX18_AV_AUDIO_SERIAL1, CS5345_IN_4 },
+	.ddr = {
+		/* Samsung K4D263238G-VC33 memory */
+		.chip_config = 0x003,
+		.refresh = 0x30c,
+		.timing1 = 0x23230b73,
+		.timing2 = 0x08,
+		.tune_lane = 0,
+		.initial_emrs = 2,
+	},
+	.gpio_init.initial_value = 0x3001,
+	.gpio_init.direction = 0x3001,
+	.gpio_i2c_slave_reset = {
+		.active_lo_mask = 0x3001,
+		.msecs_asserted = 10,
+		.msecs_recovery = 40,
+		.ir_reset_mask  = 0x0001,
+	},
+	.i2c = &cx18_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* Compro VideoMate H900: note that this card is analog only! */
+
+static const struct cx18_card_pci_info cx18_pci_h900[] = {
+	{ PCI_DEVICE_ID_CX23418, CX18_PCI_ID_COMPRO, 0xe100 },
+	{ 0, 0, 0 }
+};
+
+static const struct cx18_card cx18_card_h900 = {
+	.type = CX18_CARD_COMPRO_H900,
+	.name = "Compro VideoMate H900",
+	.comment = "Analog TV capture supported\n",
+	.v4l2_capabilities = CX18_CAP_ENCODER,
+	.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,
+			CX18_AV_SVIDEO_LUMA3 | CX18_AV_SVIDEO_CHROMA4 },
+		{ CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE1 },
+	},
+	.audio_inputs = {
+		{ CX18_CARD_INPUT_AUD_TUNER,
+		  CX18_AV_AUDIO5, 0 },
+		{ CX18_CARD_INPUT_LINE_IN1,
+		  CX18_AV_AUDIO_SERIAL1, 0 },
+	},
+	.radio_input = { CX18_CARD_INPUT_AUD_TUNER,
+			 CX18_AV_AUDIO_SERIAL1, 0 },
+	.tuners = {
+		{ .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
+	},
+	.ddr = {
+		/* EtronTech EM6A9160TS-5G memory */
+		.chip_config = 0x50003,
+		.refresh = 0x753,
+		.timing1 = 0x24330e84,
+		.timing2 = 0x1f,
+		.tune_lane = 0,
+		.initial_emrs = 0,
+	},
+	.xceive_pin = 15,
+	.pci_list = cx18_pci_h900,
+	.i2c = &cx18_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* Yuan MPC718: not working at the moment! */
+
+static const struct cx18_card_pci_info cx18_pci_mpc718[] = {
+	{ PCI_DEVICE_ID_CX23418, CX18_PCI_ID_YUAN, 0x0718 },
+	{ 0, 0, 0 }
+};
+
+static const struct cx18_card cx18_card_mpc718 = {
+	.type = CX18_CARD_YUAN_MPC718,
+	.name = "Yuan MPC718 MiniPCI DVB-T/Analog",
+	.comment = "Experimenters 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_418_AV,
+	.hw_muxer = CX18_HW_GPIO_MUX,
+	.hw_all = CX18_HW_TVEEPROM | CX18_HW_418_AV | CX18_HW_TUNER |
+		  CX18_HW_GPIO_MUX | CX18_HW_DVB | CX18_HW_GPIO_RESET_CTRL,
+	.video_inputs = {
+		{ CX18_CARD_INPUT_VID_TUNER,  0, CX18_AV_COMPOSITE2 },
+		{ CX18_CARD_INPUT_SVIDEO1,    1,
+				CX18_AV_SVIDEO_LUMA3 | CX18_AV_SVIDEO_CHROMA4 },
+		{ CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE1 },
+		{ CX18_CARD_INPUT_SVIDEO2,    2,
+				CX18_AV_SVIDEO_LUMA7 | CX18_AV_SVIDEO_CHROMA8 },
+		{ CX18_CARD_INPUT_COMPOSITE2, 2, CX18_AV_COMPOSITE6 },
+	},
+	.audio_inputs = {
+		{ CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5,        0 },
+		{ CX18_CARD_INPUT_LINE_IN1,  CX18_AV_AUDIO_SERIAL1, 1 },
+		{ CX18_CARD_INPUT_LINE_IN2,  CX18_AV_AUDIO_SERIAL2, 1 },
+	},
+	.tuners = {
+		/* XC3028 tuner */
+		{ .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
+	},
+	/* FIXME - the FM radio is just a guess and driver doesn't use SIF */
+	.radio_input = { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 2 },
+	.ddr = {
+		/* Hynix HY5DU283222B DDR RAM */
+		.chip_config = 0x303,
+		.refresh = 0x3bd,
+		.timing1 = 0x36320966,
+		.timing2 = 0x1f,
+		.tune_lane = 0,
+		.initial_emrs = 2,
+	},
+	.gpio_init.initial_value = 0x1,
+	.gpio_init.direction = 0x3,
+	/* FIXME - these GPIO's are just guesses */
+	.gpio_audio_input = { .mask   = 0x3,
+			      .tuner  = 0x1,
+			      .linein = 0x3,
+			      .radio  = 0x1 },
+	.xceive_pin = 0,
+	.pci_list = cx18_pci_mpc718,
+	.i2c = &cx18_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* GoTView PCI */
+
+static const struct cx18_card_pci_info cx18_pci_gotview_dvd3[] = {
+	{ PCI_DEVICE_ID_CX23418, CX18_PCI_ID_GOTVIEW, 0x3343 },
+	{ 0, 0, 0 }
+};
+
+static const struct cx18_card cx18_card_gotview_dvd3 = {
+	.type = CX18_CARD_GOTVIEW_PCI_DVD3,
+	.name = "GoTView PCI DVD3 Hybrid",
+	.comment = "Experimenters 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_418_AV,
+	.hw_muxer = CX18_HW_GPIO_MUX,
+	.hw_all = CX18_HW_TVEEPROM | CX18_HW_418_AV | CX18_HW_TUNER |
+		  CX18_HW_GPIO_MUX | CX18_HW_DVB | CX18_HW_GPIO_RESET_CTRL,
+	.video_inputs = {
+		{ CX18_CARD_INPUT_VID_TUNER,  0, CX18_AV_COMPOSITE2 },
+		{ CX18_CARD_INPUT_SVIDEO1,    1,
+				CX18_AV_SVIDEO_LUMA3 | CX18_AV_SVIDEO_CHROMA4 },
+		{ CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE1 },
+		{ CX18_CARD_INPUT_SVIDEO2,    2,
+				CX18_AV_SVIDEO_LUMA7 | CX18_AV_SVIDEO_CHROMA8 },
+		{ CX18_CARD_INPUT_COMPOSITE2, 2, CX18_AV_COMPOSITE6 },
+	},
+	.audio_inputs = {
+		{ CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5,        0 },
+		{ CX18_CARD_INPUT_LINE_IN1,  CX18_AV_AUDIO_SERIAL1, 1 },
+		{ CX18_CARD_INPUT_LINE_IN2,  CX18_AV_AUDIO_SERIAL2, 1 },
+	},
+	.tuners = {
+		/* XC3028 tuner */
+		{ .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
+	},
+	/* FIXME - the FM radio is just a guess and driver doesn't use SIF */
+	.radio_input = { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 2 },
+	.ddr = {
+		/* Hynix HY5DU283222B DDR RAM */
+		.chip_config = 0x303,
+		.refresh = 0x3bd,
+		.timing1 = 0x36320966,
+		.timing2 = 0x1f,
+		.tune_lane = 0,
+		.initial_emrs = 2,
+	},
+	.gpio_init.initial_value = 0x1,
+	.gpio_init.direction = 0x3,
+
+	.gpio_audio_input = { .mask   = 0x3,
+			      .tuner  = 0x1,
+			      .linein = 0x2,
+			      .radio  = 0x1 },
+	.xceive_pin = 0,
+	.pci_list = cx18_pci_gotview_dvd3,
+	.i2c = &cx18_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* Conexant Raptor PAL/SECAM: note that this card is analog only! */
+
+static const struct cx18_card_pci_info cx18_pci_cnxt_raptor_pal[] = {
+	{ PCI_DEVICE_ID_CX23418, CX18_PCI_ID_CONEXANT, 0x0009 },
+	{ 0, 0, 0 }
+};
+
+static const struct cx18_card cx18_card_cnxt_raptor_pal = {
+	.type = CX18_CARD_CNXT_RAPTOR_PAL,
+	.name = "Conexant Raptor PAL/SECAM",
+	.comment = "Analog TV capture supported\n",
+	.v4l2_capabilities = CX18_CAP_ENCODER,
+	.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,
+			CX18_AV_SVIDEO_LUMA3 | CX18_AV_SVIDEO_CHROMA4 },
+		{ CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE1 },
+		{ CX18_CARD_INPUT_SVIDEO2,    2,
+			CX18_AV_SVIDEO_LUMA7 | CX18_AV_SVIDEO_CHROMA8 },
+		{ CX18_CARD_INPUT_COMPOSITE2, 2, CX18_AV_COMPOSITE6 },
+	},
+	.audio_inputs = {
+		{ CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 	    0 },
+		{ CX18_CARD_INPUT_LINE_IN1,  CX18_AV_AUDIO_SERIAL1, 1 },
+		{ CX18_CARD_INPUT_LINE_IN2,  CX18_AV_AUDIO_SERIAL2, 1 },
+	},
+	.tuners = {
+		{ .std = V4L2_STD_PAL_SECAM, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
+	},
+	.radio_input = { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO_SERIAL1, 2 },
+	.ddr = {
+		/* MT 46V16M16 memory */
+		.chip_config = 0x50306,
+		.refresh = 0x753,
+		.timing1 = 0x33220953,
+		.timing2 = 0x09,
+		.tune_lane = 0,
+		.initial_emrs = 0,
+	},
+	.gpio_init.initial_value = 0x1002,
+	.gpio_init.direction = 0xf002,
+	.gpio_audio_input = { .mask   = 0xf002,
+			      .tuner  = 0x1002,   /* LED D1  Tuner AF  */
+			      .linein = 0x2000,   /* LED D2  Line In 1 */
+			      .radio  = 0x4002 }, /* LED D3  Tuner AF  */
+	.pci_list = cx18_pci_cnxt_raptor_pal,
+	.i2c = &cx18_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* Toshiba Qosmio laptop internal DVB-T/Analog Hybrid Tuner */
+
+static const struct cx18_card_pci_info cx18_pci_toshiba_qosmio_dvbt[] = {
+	{ PCI_DEVICE_ID_CX23418, CX18_PCI_ID_TOSHIBA, 0x0110 },
+	{ 0, 0, 0 }
+};
+
+static const struct cx18_card cx18_card_toshiba_qosmio_dvbt = {
+	.type = CX18_CARD_TOSHIBA_QOSMIO_DVBT,
+	.name = "Toshiba Qosmio DVB-T/Analog",
+	.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_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,
+			CX18_AV_SVIDEO_LUMA3 | CX18_AV_SVIDEO_CHROMA4 },
+		{ CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE1 },
+	},
+	.audio_inputs = {
+		{ CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 	    0 },
+		{ CX18_CARD_INPUT_LINE_IN1,  CX18_AV_AUDIO_SERIAL1, 1 },
+	},
+	.tuners = {
+		{ .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
+	},
+	.ddr = {
+		.chip_config = 0x202,
+		.refresh = 0x3bb,
+		.timing1 = 0x33320a63,
+		.timing2 = 0x0a,
+		.tune_lane = 0,
+		.initial_emrs = 0x42,
+	},
+	.xceive_pin = 15,
+	.pci_list = cx18_pci_toshiba_qosmio_dvbt,
+	.i2c = &cx18_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* Leadtek WinFast PVR2100 */
+
+static const struct cx18_card_pci_info cx18_pci_leadtek_pvr2100[] = {
+	{ PCI_DEVICE_ID_CX23418, CX18_PCI_ID_LEADTEK, 0x6f27 }, /* PVR2100   */
+	{ 0, 0, 0 }
+};
+
+static const struct cx18_card cx18_card_leadtek_pvr2100 = {
+	.type = CX18_CARD_LEADTEK_PVR2100,
+	.name = "Leadtek WinFast PVR2100",
+	.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_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,
+			CX18_AV_SVIDEO_LUMA3 | CX18_AV_SVIDEO_CHROMA4 },
+		{ CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE7 },
+		{ CX18_CARD_INPUT_COMPONENT1, 1, CX18_AV_COMPONENT1 },
+	},
+	.audio_inputs = {
+		{ CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 	    0 },
+		{ CX18_CARD_INPUT_LINE_IN1,  CX18_AV_AUDIO_SERIAL1, 1 },
+	},
+	.tuners = {
+		/* XC2028 tuner */
+		{ .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
+	},
+	.radio_input = { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 2 },
+	.ddr = {
+		/* Pointer to proper DDR config values provided by Terry Wu */
+		.chip_config = 0x303,
+		.refresh = 0x3bb,
+		.timing1 = 0x24220e83,
+		.timing2 = 0x1f,
+		.tune_lane = 0,
+		.initial_emrs = 0x2,
+	},
+	.gpio_init.initial_value = 0x6,
+	.gpio_init.direction = 0x7,
+	.gpio_audio_input = { .mask   = 0x7,
+			      .tuner  = 0x6, .linein = 0x2, .radio  = 0x2 },
+	.xceive_pin = 1,
+	.pci_list = cx18_pci_leadtek_pvr2100,
+	.i2c = &cx18_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* Leadtek WinFast DVR3100 H */
+
+static const struct cx18_card_pci_info cx18_pci_leadtek_dvr3100h[] = {
+	{ PCI_DEVICE_ID_CX23418, CX18_PCI_ID_LEADTEK, 0x6690 }, /* DVR3100 H */
+	{ 0, 0, 0 }
+};
+
+static const struct cx18_card cx18_card_leadtek_dvr3100h = {
+	.type = CX18_CARD_LEADTEK_DVR3100H,
+	.name = "Leadtek WinFast DVR3100 H",
+	.comment = "Simultaneous DVB-T and Analog capture supported,\n"
+		  "\texcept when capturing Analog from the antenna input.\n",
+	.v4l2_capabilities = CX18_CAP_ENCODER,
+	.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_DVB | CX18_HW_GPIO_RESET_CTRL,
+	.video_inputs = {
+		{ CX18_CARD_INPUT_VID_TUNER,  0, CX18_AV_COMPOSITE2 },
+		{ CX18_CARD_INPUT_SVIDEO1,    1,
+			CX18_AV_SVIDEO_LUMA3 | CX18_AV_SVIDEO_CHROMA4 },
+		{ CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE7 },
+		{ CX18_CARD_INPUT_COMPONENT1, 1, CX18_AV_COMPONENT1 },
+	},
+	.audio_inputs = {
+		{ CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 	    0 },
+		{ CX18_CARD_INPUT_LINE_IN1,  CX18_AV_AUDIO_SERIAL1, 1 },
+	},
+	.tuners = {
+		/* XC3028 tuner */
+		{ .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
+	},
+	.radio_input = { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 2 },
+	.ddr = {
+		/* Pointer to proper DDR config values provided by Terry Wu */
+		.chip_config = 0x303,
+		.refresh = 0x3bb,
+		.timing1 = 0x24220e83,
+		.timing2 = 0x1f,
+		.tune_lane = 0,
+		.initial_emrs = 0x2,
+	},
+	.gpio_init.initial_value = 0x6,
+	.gpio_init.direction = 0x7,
+	.gpio_audio_input = { .mask   = 0x7,
+			      .tuner  = 0x6, .linein = 0x2, .radio  = 0x2 },
+	.xceive_pin = 1,
+	.pci_list = cx18_pci_leadtek_dvr3100h,
+	.i2c = &cx18_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+static const struct cx18_card *cx18_card_list[] = {
+	&cx18_card_hvr1600_esmt,
+	&cx18_card_hvr1600_samsung,
+	&cx18_card_h900,
+	&cx18_card_mpc718,
+	&cx18_card_cnxt_raptor_pal,
+	&cx18_card_toshiba_qosmio_dvbt,
+	&cx18_card_leadtek_pvr2100,
+	&cx18_card_leadtek_dvr3100h,
+	&cx18_card_gotview_dvd3,
+	&cx18_card_hvr1600_s5h1411
+};
+
+const struct cx18_card *cx18_get_card(u16 index)
+{
+	if (index >= ARRAY_SIZE(cx18_card_list))
+		return NULL;
+	return cx18_card_list[index];
+}
+
+int cx18_get_input(struct cx18 *cx, u16 index, struct v4l2_input *input)
+{
+	const struct cx18_card_video_input *card_input =
+		cx->card->video_inputs + index;
+	static const char * const input_strs[] = {
+		"Tuner 1",
+		"S-Video 1",
+		"S-Video 2",
+		"Composite 1",
+		"Composite 2",
+		"Component 1"
+	};
+
+	if (index >= cx->nof_inputs)
+		return -EINVAL;
+	input->index = index;
+	strlcpy(input->name, input_strs[card_input->video_type - 1],
+			sizeof(input->name));
+	input->type = (card_input->video_type == CX18_CARD_INPUT_VID_TUNER ?
+			V4L2_INPUT_TYPE_TUNER : V4L2_INPUT_TYPE_CAMERA);
+	input->audioset = (1 << cx->nof_audio_inputs) - 1;
+	input->std = (input->type == V4L2_INPUT_TYPE_TUNER) ?
+				cx->tuner_std : V4L2_STD_ALL;
+	return 0;
+}
+
+int cx18_get_audio_input(struct cx18 *cx, u16 index, struct v4l2_audio *audio)
+{
+	const struct cx18_card_audio_input *aud_input =
+		cx->card->audio_inputs + index;
+	static const char * const input_strs[] = {
+		"Tuner 1",
+		"Line In 1",
+		"Line In 2"
+	};
+
+	memset(audio, 0, sizeof(*audio));
+	if (index >= cx->nof_audio_inputs)
+		return -EINVAL;
+	strlcpy(audio->name, input_strs[aud_input->audio_type - 1],
+			sizeof(audio->name));
+	audio->index = index;
+	audio->capability = V4L2_AUDCAP_STEREO;
+	return 0;
+}
diff --git a/drivers/media/pci/cx18/cx18-cards.h b/drivers/media/pci/cx18/cx18-cards.h
new file mode 100644
index 0000000..add7391
--- /dev/null
+++ b/drivers/media/pci/cx18/cx18-cards.h
@@ -0,0 +1,157 @@
+/*
+ *  cx18 functions to query card hardware
+ *
+ *  Derived from ivtv-cards.c
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.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 program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/* hardware flags */
+#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)
+#define CX18_HW_Z8F0811_IR_TX_HAUP	(1 << 7)
+#define CX18_HW_Z8F0811_IR_RX_HAUP	(1 << 8)
+#define CX18_HW_Z8F0811_IR_HAUP	(CX18_HW_Z8F0811_IR_RX_HAUP | \
+				 CX18_HW_Z8F0811_IR_TX_HAUP)
+
+#define CX18_HW_IR_ANY (CX18_HW_Z8F0811_IR_RX_HAUP | \
+			CX18_HW_Z8F0811_IR_TX_HAUP)
+
+/* video inputs */
+#define	CX18_CARD_INPUT_VID_TUNER	1
+#define	CX18_CARD_INPUT_SVIDEO1 	2
+#define	CX18_CARD_INPUT_SVIDEO2 	3
+#define	CX18_CARD_INPUT_COMPOSITE1 	4
+#define	CX18_CARD_INPUT_COMPOSITE2 	5
+#define	CX18_CARD_INPUT_COMPONENT1 	6
+
+/* audio inputs */
+#define	CX18_CARD_INPUT_AUD_TUNER	1
+#define	CX18_CARD_INPUT_LINE_IN1 	2
+#define	CX18_CARD_INPUT_LINE_IN2 	3
+
+#define CX18_CARD_MAX_VIDEO_INPUTS 6
+#define CX18_CARD_MAX_AUDIO_INPUTS 3
+#define CX18_CARD_MAX_TUNERS  	   2
+
+/* 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)
+
+struct cx18_card_video_input {
+	u8  video_type; 	/* video input type */
+	u8  audio_index;	/* index in cx18_card_audio_input array */
+	u32 video_input;	/* hardware video input */
+};
+
+struct cx18_card_audio_input {
+	u8  audio_type;		/* audio input type */
+	u32 audio_input;	/* hardware audio input */
+	u16 muxer_input;	/* hardware muxer input for boards with a
+				   multiplexer chip */
+};
+
+struct cx18_card_pci_info {
+	u16 device;
+	u16 subsystem_vendor;
+	u16 subsystem_device;
+};
+
+/* GPIO definitions */
+
+/* The mask is the set of bits used by the operation */
+
+struct cx18_gpio_init { /* set initial GPIO DIR and OUT values */
+	u32 direction; 	/* DIR setting. Leave to 0 if no init is needed */
+	u32 initial_value;
+};
+
+struct cx18_gpio_i2c_slave_reset {
+	u32 active_lo_mask; /* GPIO outputs that reset i2c chips when low */
+	u32 active_hi_mask; /* GPIO outputs that reset i2c chips when high */
+	int msecs_asserted; /* time period reset must remain asserted */
+	int msecs_recovery; /* time after deassert for chips to be ready */
+	u32 ir_reset_mask;  /* GPIO to reset the Zilog Z8F0811 IR contoller */
+};
+
+struct cx18_gpio_audio_input { 	/* select tuner/line in input */
+	u32 mask; 		/* leave to 0 if not supported */
+	u32 tuner;
+	u32 linein;
+	u32 radio;
+};
+
+struct cx18_card_tuner {
+	v4l2_std_id std; 	/* standard for which the tuner is suitable */
+	int 	    tuner; 	/* tuner ID (from tuner.h) */
+};
+
+struct cx18_card_tuner_i2c {
+	unsigned short radio[2];/* radio tuner i2c address to probe */
+	unsigned short demod[3];/* demodulator i2c address to probe */
+	unsigned short tv[4];	/* tv tuner i2c addresses to probe */
+};
+
+struct cx18_ddr {		/* DDR config data */
+	u32 chip_config;
+	u32 refresh;
+	u32 timing1;
+	u32 timing2;
+	u32 tune_lane;
+	u32 initial_emrs;
+};
+
+/* for card information/parameters */
+struct cx18_card {
+	int type;
+	char *name;
+	char *comment;
+	u32 v4l2_capabilities;
+	u32 hw_audio_ctrl;	/* hardware used for the V4L2 controls (only
+				   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];
+	struct cx18_card_audio_input audio_inputs[CX18_CARD_MAX_AUDIO_INPUTS];
+	struct cx18_card_audio_input radio_input;
+
+	/* GPIO card-specific settings */
+	u8 xceive_pin; 		/* XCeive tuner GPIO reset pin */
+	struct cx18_gpio_init 		 gpio_init;
+	struct cx18_gpio_i2c_slave_reset gpio_i2c_slave_reset;
+	struct cx18_gpio_audio_input    gpio_audio_input;
+
+	struct cx18_card_tuner tuners[CX18_CARD_MAX_TUNERS];
+	struct cx18_card_tuner_i2c *i2c;
+
+	struct cx18_ddr ddr;
+
+	/* list of device and subsystem vendor/devices that
+	   correspond to this card type. */
+	const struct cx18_card_pci_info *pci_list;
+};
+
+int cx18_get_input(struct cx18 *cx, u16 index, struct v4l2_input *input);
+int cx18_get_audio_input(struct cx18 *cx, u16 index, struct v4l2_audio *input);
+const struct cx18_card *cx18_get_card(u16 index);
diff --git a/drivers/media/pci/cx18/cx18-controls.c b/drivers/media/pci/cx18/cx18-controls.c
new file mode 100644
index 0000000..282a3d2
--- /dev/null
+++ b/drivers/media/pci/cx18/cx18-controls.c
@@ -0,0 +1,131 @@
+/*
+ *  cx18 ioctl control functions
+ *
+ *  Derived from ivtv-controls.c
+ *
+ *  Copyright (C) 2007  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., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307  USA
+ */
+#include <linux/kernel.h>
+#include <linux/slab.h>
+
+#include "cx18-driver.h"
+#include "cx18-cards.h"
+#include "cx18-ioctl.h"
+#include "cx18-audio.h"
+#include "cx18-mailbox.h"
+#include "cx18-controls.h"
+
+static int cx18_s_stream_vbi_fmt(struct cx2341x_handler *cxhdl, u32 fmt)
+{
+	struct cx18 *cx = container_of(cxhdl, struct cx18, cxhdl);
+	int type = cxhdl->stream_type->val;
+
+	if (atomic_read(&cx->ana_capturing) > 0)
+		return -EBUSY;
+
+	if (fmt != V4L2_MPEG_STREAM_VBI_FMT_IVTV ||
+	    !(type == V4L2_MPEG_STREAM_TYPE_MPEG2_PS ||
+	      type == V4L2_MPEG_STREAM_TYPE_MPEG2_DVD ||
+	      type == V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD)) {
+		/* Only IVTV fmt VBI insertion & only MPEG-2 PS type streams */
+		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++) {
+			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 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;
+		else
+			cx->vbi.sliced_in->service_set = V4L2_SLICED_WSS_625;
+		cx18_expand_service_set(cx->vbi.sliced_in, cx->is_50hz);
+	}
+	return 0;
+}
+
+static int cx18_s_video_encoding(struct cx2341x_handler *cxhdl, u32 val)
+{
+	struct cx18 *cx = container_of(cxhdl, struct cx18, cxhdl);
+	int is_mpeg1 = val == V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
+	struct v4l2_mbus_framefmt fmt;
+
+	/* fix videodecoder resolution */
+	fmt.width = cxhdl->width / (is_mpeg1 ? 2 : 1);
+	fmt.height = cxhdl->height;
+	fmt.code = V4L2_MBUS_FMT_FIXED;
+	v4l2_subdev_call(cx->sd_av, video, s_mbus_fmt, &fmt);
+	return 0;
+}
+
+static int cx18_s_audio_sampling_freq(struct cx2341x_handler *cxhdl, u32 idx)
+{
+	static const u32 freqs[3] = { 44100, 48000, 32000 };
+	struct cx18 *cx = container_of(cxhdl, struct cx18, cxhdl);
+
+	/* The audio clock of the digitizer must match the codec sample
+	   rate otherwise you get some very strange effects. */
+	if (idx < ARRAY_SIZE(freqs))
+		cx18_call_all(cx, audio, s_clock_freq, freqs[idx]);
+	return 0;
+}
+
+static int cx18_s_audio_mode(struct cx2341x_handler *cxhdl, u32 val)
+{
+	struct cx18 *cx = container_of(cxhdl, struct cx18, cxhdl);
+
+	cx->dualwatch_stereo_mode = val;
+	return 0;
+}
+
+struct cx2341x_handler_ops cx18_cxhdl_ops = {
+	.s_audio_mode = cx18_s_audio_mode,
+	.s_audio_sampling_freq = cx18_s_audio_sampling_freq,
+	.s_video_encoding = cx18_s_video_encoding,
+	.s_stream_vbi_fmt = cx18_s_stream_vbi_fmt,
+};
diff --git a/drivers/media/pci/cx18/cx18-controls.h b/drivers/media/pci/cx18/cx18-controls.h
new file mode 100644
index 0000000..cb5dfc7
--- /dev/null
+++ b/drivers/media/pci/cx18/cx18-controls.h
@@ -0,0 +1,24 @@
+/*
+ *  cx18 ioctl control functions
+ *
+ *  Derived from ivtv-controls.h
+ *
+ *  Copyright (C) 2007  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., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307  USA
+ */
+
+extern struct cx2341x_handler_ops cx18_cxhdl_ops;
diff --git a/drivers/media/pci/cx18/cx18-driver.c b/drivers/media/pci/cx18/cx18-driver.c
new file mode 100644
index 0000000..039133d
--- /dev/null
+++ b/drivers/media/pci/cx18/cx18-driver.c
@@ -0,0 +1,1360 @@
+/*
+ *  cx18 driver initialization and card probing
+ *
+ *  Derived from ivtv-driver.c
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.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 program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public 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 "cx18-driver.h"
+#include "cx18-io.h"
+#include "cx18-version.h"
+#include "cx18-cards.h"
+#include "cx18-i2c.h"
+#include "cx18-irq.h"
+#include "cx18-gpio.h"
+#include "cx18-firmware.h"
+#include "cx18-queue.h"
+#include "cx18-streams.h"
+#include "cx18-av-core.h"
+#include "cx18-scb.h"
+#include "cx18-mailbox.h"
+#include "cx18-ioctl.h"
+#include "cx18-controls.h"
+#include "tuner-xc2028.h"
+#include <linux/dma-mapping.h>
+#include <media/tveeprom.h>
+
+/* 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
+   video1 device together with a radio0 device for the Compro. By
+   setting this to 1 you ensure that radio0 is now also radio1. */
+int cx18_first_minor;
+
+/* Callback for registering extensions */
+int (*cx18_ext_init)(struct cx18 *);
+EXPORT_SYMBOL(cx18_ext_init);
+
+/* add your revision and whatnot here */
+static struct pci_device_id cx18_pci_tbl[] __devinitdata = {
+	{PCI_VENDOR_ID_CX, PCI_DEVICE_ID_CX23418,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{0,}
+};
+
+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,
+				     -1, -1, -1, -1, -1, -1, -1, -1,
+				     -1, -1, -1, -1, -1, -1, -1, -1,
+				     -1, -1, -1, -1, -1, -1, -1, -1 };
+static int radio[CX18_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1,
+				     -1, -1, -1, -1, -1, -1, -1, -1,
+				     -1, -1, -1, -1, -1, -1, -1, -1,
+				     -1, -1, -1, -1, -1, -1, -1, -1 };
+static unsigned cardtype_c = 1;
+static unsigned tuner_c = 1;
+static unsigned radio_c = 1;
+static char pal[] = "--";
+static char secam[] = "--";
+static char ntsc[] = "-";
+
+/* Buffers */
+static int enc_ts_buffers = CX18_DEFAULT_ENC_TS_BUFFERS;
+static int enc_mpg_buffers = CX18_DEFAULT_ENC_MPG_BUFFERS;
+static int enc_idx_buffers = CX18_DEFAULT_ENC_IDX_BUFFERS;
+static int enc_yuv_buffers = CX18_DEFAULT_ENC_YUV_BUFFERS;
+static int enc_vbi_buffers = CX18_DEFAULT_ENC_VBI_BUFFERS;
+static int enc_pcm_buffers = CX18_DEFAULT_ENC_PCM_BUFFERS;
+
+static int enc_ts_bufsize = CX18_DEFAULT_ENC_TS_BUFSIZE;
+static int enc_mpg_bufsize = CX18_DEFAULT_ENC_MPG_BUFSIZE;
+static int enc_idx_bufsize = CX18_DEFAULT_ENC_IDX_BUFSIZE;
+static int enc_yuv_bufsize = CX18_DEFAULT_ENC_YUV_BUFSIZE;
+static int enc_pcm_bufsize = CX18_DEFAULT_ENC_PCM_BUFSIZE;
+
+static int enc_ts_bufs = -1;
+static int enc_mpg_bufs = -1;
+static int enc_idx_bufs = CX18_MAX_FW_MDLS_PER_STREAM;
+static int enc_yuv_bufs = -1;
+static int enc_vbi_bufs = -1;
+static int enc_pcm_bufs = -1;
+
+
+static int cx18_pci_latency = 1;
+
+static int mmio_ndelay;
+static int retry_mmio = 1;
+
+int cx18_debug;
+
+module_param_array(tuner, int, &tuner_c, 0644);
+module_param_array(radio, int, &radio_c, 0644);
+module_param_array(cardtype, int, &cardtype_c, 0644);
+module_param_string(pal, pal, sizeof(pal), 0644);
+module_param_string(secam, secam, sizeof(secam), 0644);
+module_param_string(ntsc, ntsc, sizeof(ntsc), 0644);
+module_param_named(debug, cx18_debug, int, 0644);
+module_param(mmio_ndelay, int, 0644);
+module_param(retry_mmio, int, 0644);
+module_param(cx18_pci_latency, int, 0644);
+module_param(cx18_first_minor, int, 0644);
+
+module_param(enc_ts_buffers, int, 0644);
+module_param(enc_mpg_buffers, int, 0644);
+module_param(enc_idx_buffers, int, 0644);
+module_param(enc_yuv_buffers, int, 0644);
+module_param(enc_vbi_buffers, int, 0644);
+module_param(enc_pcm_buffers, int, 0644);
+
+module_param(enc_ts_bufsize, int, 0644);
+module_param(enc_mpg_bufsize, int, 0644);
+module_param(enc_idx_bufsize, int, 0644);
+module_param(enc_yuv_bufsize, int, 0644);
+module_param(enc_pcm_bufsize, int, 0644);
+
+module_param(enc_ts_bufs, int, 0644);
+module_param(enc_mpg_bufs, int, 0644);
+module_param(enc_idx_bufs, int, 0644);
+module_param(enc_yuv_bufs, int, 0644);
+module_param(enc_vbi_bufs, int, 0644);
+module_param(enc_pcm_bufs, int, 0644);
+
+MODULE_PARM_DESC(tuner, "Tuner type selection,\n"
+			"\t\t\tsee tuner.h for values");
+MODULE_PARM_DESC(radio,
+		 "Enable or disable the radio. Use only if autodetection\n"
+		 "\t\t\tfails. 0 = disable, 1 = enable");
+MODULE_PARM_DESC(cardtype,
+		 "Only use this option if your card is not detected properly.\n"
+		 "\t\tSpecify card type:\n"
+		 "\t\t\t 1 = Hauppauge HVR 1600 (ESMT memory)\n"
+		 "\t\t\t 2 = Hauppauge HVR 1600 (Samsung memory)\n"
+		 "\t\t\t 3 = Compro VideoMate H900\n"
+		 "\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 8 = Leadtek WinFast DVR3100 H\n"
+		 "\t\t\t 9 = GoTView PCI DVD3 Hybrid\n"
+		 "\t\t\t 10 = Hauppauge HVR 1600 (S5H1411)\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");
+MODULE_PARM_DESC(secam, "Set SECAM standard: B, G, H, D, K, L, LC");
+MODULE_PARM_DESC(ntsc, "Set NTSC standard: M, J, K");
+MODULE_PARM_DESC(debug,
+		 "Debug level (bitmask). Default: 0\n"
+		 "\t\t\t  1/0x0001: warning\n"
+		 "\t\t\t  2/0x0002: info\n"
+		 "\t\t\t  4/0x0004: mailbox\n"
+		 "\t\t\t  8/0x0008: dma\n"
+		 "\t\t\t 16/0x0010: ioctl\n"
+		 "\t\t\t 32/0x0020: file\n"
+		 "\t\t\t 64/0x0040: i2c\n"
+		 "\t\t\t128/0x0080: irq\n"
+		 "\t\t\t256/0x0100: high volume\n");
+MODULE_PARM_DESC(cx18_pci_latency,
+		 "Change the PCI latency to 64 if lower: 0 = No, 1 = Yes,\n"
+		 "\t\t\tDefault: Yes");
+MODULE_PARM_DESC(retry_mmio,
+		 "(Deprecated) MMIO writes are now always checked and retried\n"
+		 "\t\t\tEffectively: 1 [Yes]");
+MODULE_PARM_DESC(mmio_ndelay,
+		 "(Deprecated) MMIO accesses are now never purposely delayed\n"
+		 "\t\t\tEffectively: 0 ns");
+MODULE_PARM_DESC(enc_ts_buffers,
+		 "Encoder TS buffer memory (MB). (enc_ts_bufs can override)\n"
+		 "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_TS_BUFFERS));
+MODULE_PARM_DESC(enc_ts_bufsize,
+		 "Size of an encoder TS buffer (kB)\n"
+		 "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_TS_BUFSIZE));
+MODULE_PARM_DESC(enc_ts_bufs,
+		 "Number of encoder TS buffers\n"
+		 "\t\t\tDefault is computed from other enc_ts_* parameters");
+MODULE_PARM_DESC(enc_mpg_buffers,
+		 "Encoder MPG buffer memory (MB). (enc_mpg_bufs can override)\n"
+		 "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_MPG_BUFFERS));
+MODULE_PARM_DESC(enc_mpg_bufsize,
+		 "Size of an encoder MPG buffer (kB)\n"
+		 "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_MPG_BUFSIZE));
+MODULE_PARM_DESC(enc_mpg_bufs,
+		 "Number of encoder MPG buffers\n"
+		 "\t\t\tDefault is computed from other enc_mpg_* parameters");
+MODULE_PARM_DESC(enc_idx_buffers,
+		 "(Deprecated) Encoder IDX buffer memory (MB)\n"
+		 "\t\t\tIgnored, except 0 disables IDX buffer allocations\n"
+		 "\t\t\tDefault: 1 [Enabled]");
+MODULE_PARM_DESC(enc_idx_bufsize,
+		 "Size of an encoder IDX buffer (kB)\n"
+		 "\t\t\tAllowed values are multiples of 1.5 kB rounded up\n"
+		 "\t\t\t(multiples of size required for 64 index entries)\n"
+		 "\t\t\tDefault: 2");
+MODULE_PARM_DESC(enc_idx_bufs,
+		 "Number of encoder IDX buffers\n"
+		 "\t\t\tDefault: " __stringify(CX18_MAX_FW_MDLS_PER_STREAM));
+MODULE_PARM_DESC(enc_yuv_buffers,
+		 "Encoder YUV buffer memory (MB). (enc_yuv_bufs can override)\n"
+		 "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_YUV_BUFFERS));
+MODULE_PARM_DESC(enc_yuv_bufsize,
+		 "Size of an encoder YUV buffer (kB)\n"
+		 "\t\t\tAllowed values are multiples of 33.75 kB rounded up\n"
+		 "\t\t\t(multiples of size required for 32 screen lines)\n"
+		 "\t\t\tDefault: 102");
+MODULE_PARM_DESC(enc_yuv_bufs,
+		 "Number of encoder YUV buffers\n"
+		 "\t\t\tDefault is computed from other enc_yuv_* parameters");
+MODULE_PARM_DESC(enc_vbi_buffers,
+		 "Encoder VBI buffer memory (MB). (enc_vbi_bufs can override)\n"
+		 "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_VBI_BUFFERS));
+MODULE_PARM_DESC(enc_vbi_bufs,
+		 "Number of encoder VBI buffers\n"
+		 "\t\t\tDefault is computed from enc_vbi_buffers");
+MODULE_PARM_DESC(enc_pcm_buffers,
+		 "Encoder PCM buffer memory (MB). (enc_pcm_bufs can override)\n"
+		 "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_PCM_BUFFERS));
+MODULE_PARM_DESC(enc_pcm_bufsize,
+		 "Size of an encoder PCM buffer (kB)\n"
+		 "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_PCM_BUFSIZE));
+MODULE_PARM_DESC(enc_pcm_bufs,
+		 "Number of encoder PCM buffers\n"
+		 "\t\t\tDefault is computed from other enc_pcm_* parameters");
+
+MODULE_PARM_DESC(cx18_first_minor,
+		 "Set device node number assigned to first card");
+
+MODULE_AUTHOR("Hans Verkuil");
+MODULE_DESCRIPTION("CX23418 driver");
+MODULE_SUPPORTED_DEVICE("CX23418 MPEG2 encoder");
+MODULE_LICENSE("GPL");
+
+MODULE_VERSION(CX18_VERSION);
+
+#if defined(CONFIG_MODULES) && defined(MODULE)
+static void request_module_async(struct work_struct *work)
+{
+	struct cx18 *dev = container_of(work, struct cx18, request_module_wk);
+
+	/* Make sure cx18-alsa module is loaded */
+	request_module("cx18-alsa");
+
+	/* Initialize cx18-alsa for this instance of the cx18 device */
+	if (cx18_ext_init != NULL)
+		cx18_ext_init(dev);
+}
+
+static void request_modules(struct cx18 *dev)
+{
+	INIT_WORK(&dev->request_module_wk, request_module_async);
+	schedule_work(&dev->request_module_wk);
+}
+
+static void flush_request_modules(struct cx18 *dev)
+{
+	flush_work(&dev->request_module_wk);
+}
+#else
+#define request_modules(dev)
+#define flush_request_modules(dev)
+#endif /* CONFIG_MODULES */
+
+/* Generic utility functions */
+int cx18_msleep_timeout(unsigned int msecs, int intr)
+{
+	long int timeout = msecs_to_jiffies(msecs);
+	int sig;
+
+	do {
+		set_current_state(intr ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
+		timeout = schedule_timeout(timeout);
+		sig = intr ? signal_pending(current) : 0;
+	} while (!sig && timeout);
+	return sig;
+}
+
+/* Release ioremapped memory */
+static void cx18_iounmap(struct cx18 *cx)
+{
+	if (cx == NULL)
+		return;
+
+	/* Release io memory */
+	if (cx->enc_mem != NULL) {
+		CX18_DEBUG_INFO("releasing enc_mem\n");
+		iounmap(cx->enc_mem);
+		cx->enc_mem = NULL;
+	}
+}
+
+static void cx18_eeprom_dump(struct cx18 *cx, unsigned char *eedata, int len)
+{
+	int i;
+
+	CX18_INFO("eeprom dump:\n");
+	for (i = 0; i < len; i++) {
+		if (0 == (i % 16))
+			CX18_INFO("eeprom %02x:", i);
+		printk(KERN_CONT " %02x", eedata[i]);
+		if (15 == (i % 16))
+			printk(KERN_CONT "\n");
+	}
+}
+
+/* Hauppauge card? get values from tveeprom */
+void cx18_read_eeprom(struct cx18 *cx, struct tveeprom *tv)
+{
+	struct i2c_client c;
+	u8 eedata[256];
+
+	memset(&c, 0, sizeof(c));
+	strlcpy(c.name, "cx18 tveeprom tmp", sizeof(c.name));
+	c.adapter = &cx->i2c_adap[0];
+	c.addr = 0xA0 >> 1;
+
+	memset(tv, 0, sizeof(*tv));
+	if (tveeprom_read(&c, eedata, sizeof(eedata)))
+		return;
+
+	switch (cx->card->type) {
+	case CX18_CARD_HVR_1600_ESMT:
+	case CX18_CARD_HVR_1600_SAMSUNG:
+	case CX18_CARD_HVR_1600_S5H1411:
+		tveeprom_hauppauge_analog(&c, tv, eedata);
+		break;
+	case CX18_CARD_YUAN_MPC718:
+	case CX18_CARD_GOTVIEW_PCI_DVD3:
+		tv->model = 0x718;
+		cx18_eeprom_dump(cx, eedata, sizeof(eedata));
+		CX18_INFO("eeprom PCI ID: %02x%02x:%02x%02x\n",
+			  eedata[2], eedata[1], eedata[4], eedata[3]);
+		break;
+	default:
+		tv->model = 0xffffffff;
+		cx18_eeprom_dump(cx, eedata, sizeof(eedata));
+		break;
+	}
+}
+
+static void cx18_process_eeprom(struct cx18 *cx)
+{
+	struct tveeprom tv;
+
+	cx18_read_eeprom(cx, &tv);
+
+	/* Many thanks to Steven Toth from Hauppauge for providing the
+	   model numbers */
+	/* Note: the Samsung memory models cannot be reliably determined
+	   from the model number. Use the cardtype module option if you
+	   have one of these preproduction models. */
+	switch (tv.model) {
+	case 74301: /* Retail models */
+	case 74321:
+	case 74351: /* OEM models */
+	case 74361:
+		/* Digital side is s5h1411/tda18271 */
+		cx->card = cx18_get_card(CX18_CARD_HVR_1600_S5H1411);
+		break;
+	case 74021: /* Retail models */
+	case 74031:
+	case 74041:
+	case 74141:
+	case 74541: /* OEM models */
+	case 74551:
+	case 74591:
+	case 74651:
+	case 74691:
+	case 74751:
+	case 74891:
+		/* Digital side is s5h1409/mxl5005s */
+		cx->card = cx18_get_card(CX18_CARD_HVR_1600_ESMT);
+		break;
+	case 0x718:
+		return;
+	case 0xffffffff:
+		CX18_INFO("Unknown EEPROM encoding\n");
+		return;
+	case 0:
+		CX18_ERR("Invalid EEPROM\n");
+		return;
+	default:
+		CX18_ERR("Unknown model %d, defaulting to original HVR-1600 "
+			 "(cardtype=1)\n", tv.model);
+		cx->card = cx18_get_card(CX18_CARD_HVR_1600_ESMT);
+		break;
+	}
+
+	cx->v4l2_cap = cx->card->v4l2_capabilities;
+	cx->card_name = cx->card->name;
+	cx->card_i2c = cx->card->i2c;
+
+	CX18_INFO("Autodetected %s\n", cx->card_name);
+
+	if (tv.tuner_type == TUNER_ABSENT)
+		CX18_ERR("tveeprom cannot autodetect tuner!\n");
+
+	if (cx->options.tuner == -1)
+		cx->options.tuner = tv.tuner_type;
+	if (cx->options.radio == -1)
+		cx->options.radio = (tv.has_radio != 0);
+
+	if (cx->std != 0)
+		/* user specified tuner standard */
+		return;
+
+	/* autodetect tuner standard */
+#define TVEEPROM_TUNER_FORMAT_ALL (V4L2_STD_B  | V4L2_STD_GH | \
+				   V4L2_STD_MN | \
+				   V4L2_STD_PAL_I | \
+				   V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC | \
+				   V4L2_STD_DK)
+	if ((tv.tuner_formats & TVEEPROM_TUNER_FORMAT_ALL)
+					== TVEEPROM_TUNER_FORMAT_ALL) {
+		CX18_DEBUG_INFO("Worldwide tuner detected\n");
+		cx->std = V4L2_STD_ALL;
+	} else if (tv.tuner_formats & V4L2_STD_PAL) {
+		CX18_DEBUG_INFO("PAL tuner detected\n");
+		cx->std |= V4L2_STD_PAL_BG | V4L2_STD_PAL_H;
+	} else if (tv.tuner_formats & V4L2_STD_NTSC) {
+		CX18_DEBUG_INFO("NTSC tuner detected\n");
+		cx->std |= V4L2_STD_NTSC_M;
+	} else if (tv.tuner_formats & V4L2_STD_SECAM) {
+		CX18_DEBUG_INFO("SECAM tuner detected\n");
+		cx->std |= V4L2_STD_SECAM_L;
+	} else {
+		CX18_INFO("No tuner detected, default to NTSC-M\n");
+		cx->std |= V4L2_STD_NTSC_M;
+	}
+}
+
+static v4l2_std_id cx18_parse_std(struct cx18 *cx)
+{
+	switch (pal[0]) {
+	case '6':
+		return V4L2_STD_PAL_60;
+	case 'b':
+	case 'B':
+	case 'g':
+	case 'G':
+		return V4L2_STD_PAL_BG;
+	case 'h':
+	case 'H':
+		return V4L2_STD_PAL_H;
+	case 'n':
+	case 'N':
+		if (pal[1] == 'c' || pal[1] == 'C')
+			return V4L2_STD_PAL_Nc;
+		return V4L2_STD_PAL_N;
+	case 'i':
+	case 'I':
+		return V4L2_STD_PAL_I;
+	case 'd':
+	case 'D':
+	case 'k':
+	case 'K':
+		return V4L2_STD_PAL_DK;
+	case 'M':
+	case 'm':
+		return V4L2_STD_PAL_M;
+	case '-':
+		break;
+	default:
+		CX18_WARN("pal= argument not recognised\n");
+		return 0;
+	}
+
+	switch (secam[0]) {
+	case 'b':
+	case 'B':
+	case 'g':
+	case 'G':
+	case 'h':
+	case 'H':
+		return V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H;
+	case 'd':
+	case 'D':
+	case 'k':
+	case 'K':
+		return V4L2_STD_SECAM_DK;
+	case 'l':
+	case 'L':
+		if (secam[1] == 'C' || secam[1] == 'c')
+			return V4L2_STD_SECAM_LC;
+		return V4L2_STD_SECAM_L;
+	case '-':
+		break;
+	default:
+		CX18_WARN("secam= argument not recognised\n");
+		return 0;
+	}
+
+	switch (ntsc[0]) {
+	case 'm':
+	case 'M':
+		return V4L2_STD_NTSC_M;
+	case 'j':
+	case 'J':
+		return V4L2_STD_NTSC_M_JP;
+	case 'k':
+	case 'K':
+		return V4L2_STD_NTSC_M_KR;
+	case '-':
+		break;
+	default:
+		CX18_WARN("ntsc= argument not recognised\n");
+		return 0;
+	}
+
+	/* no match found */
+	return 0;
+}
+
+static void cx18_process_options(struct cx18 *cx)
+{
+	int i, j;
+
+	cx->options.megabytes[CX18_ENC_STREAM_TYPE_TS] = enc_ts_buffers;
+	cx->options.megabytes[CX18_ENC_STREAM_TYPE_MPG] = enc_mpg_buffers;
+	cx->options.megabytes[CX18_ENC_STREAM_TYPE_IDX] = enc_idx_buffers;
+	cx->options.megabytes[CX18_ENC_STREAM_TYPE_YUV] = enc_yuv_buffers;
+	cx->options.megabytes[CX18_ENC_STREAM_TYPE_VBI] = enc_vbi_buffers;
+	cx->options.megabytes[CX18_ENC_STREAM_TYPE_PCM] = enc_pcm_buffers;
+	cx->options.megabytes[CX18_ENC_STREAM_TYPE_RAD] = 0; /* control only */
+
+	cx->stream_buffers[CX18_ENC_STREAM_TYPE_TS] = enc_ts_bufs;
+	cx->stream_buffers[CX18_ENC_STREAM_TYPE_MPG] = enc_mpg_bufs;
+	cx->stream_buffers[CX18_ENC_STREAM_TYPE_IDX] = enc_idx_bufs;
+	cx->stream_buffers[CX18_ENC_STREAM_TYPE_YUV] = enc_yuv_bufs;
+	cx->stream_buffers[CX18_ENC_STREAM_TYPE_VBI] = enc_vbi_bufs;
+	cx->stream_buffers[CX18_ENC_STREAM_TYPE_PCM] = enc_pcm_bufs;
+	cx->stream_buffers[CX18_ENC_STREAM_TYPE_RAD] = 0; /* control, no data */
+
+	cx->stream_buf_size[CX18_ENC_STREAM_TYPE_TS] = enc_ts_bufsize;
+	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] = 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 */
+
+	/* Ensure stream_buffers & stream_buf_size are valid */
+	for (i = 0; i < CX18_MAX_STREAMS; i++) {
+		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;
+		}
+		/*
+		 * YUV is a special case where the stream_buf_size needs to be
+		 * an integral multiple of 33.75 kB (storage for 32 screens
+		 * lines to maintain alignment in case of lost buffers).
+		 *
+		 * IDX is a special case where the stream_buf_size should be
+		 * an integral multiple of 1.5 kB (storage for 64 index entries
+		 * to maintain alignment in case of lost buffers).
+		 *
+		 */
+		if (i == CX18_ENC_STREAM_TYPE_YUV) {
+			cx->stream_buf_size[i] *= 1024;
+			cx->stream_buf_size[i] -=
+			   (cx->stream_buf_size[i] % CX18_UNIT_ENC_YUV_BUFSIZE);
+
+			if (cx->stream_buf_size[i] < CX18_UNIT_ENC_YUV_BUFSIZE)
+				cx->stream_buf_size[i] =
+						CX18_UNIT_ENC_YUV_BUFSIZE;
+		} else if (i == CX18_ENC_STREAM_TYPE_IDX) {
+			cx->stream_buf_size[i] *= 1024;
+			cx->stream_buf_size[i] -=
+			   (cx->stream_buf_size[i] % CX18_UNIT_ENC_IDX_BUFSIZE);
+
+			if (cx->stream_buf_size[i] < CX18_UNIT_ENC_IDX_BUFSIZE)
+				cx->stream_buf_size[i] =
+						CX18_UNIT_ENC_IDX_BUFSIZE;
+		}
+		/*
+		 * YUV and IDX are special cases where the stream_buf_size is
+		 * now in bytes.
+		 * VBI is a special case where the stream_buf_size is fixed
+		 * and already in bytes
+		 */
+		if (i == CX18_ENC_STREAM_TYPE_VBI ||
+		    i == CX18_ENC_STREAM_TYPE_YUV ||
+		    i == CX18_ENC_STREAM_TYPE_IDX) {
+			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);
+			}
+		} else {
+			/* All other streams have stream_buf_size in kB here */
+			if (cx->stream_buffers[i] < 0) {
+				cx->stream_buffers[i] =
+						cx->options.megabytes[i] * 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;
+			}
+			/* convert from kB to bytes */
+			cx->stream_buf_size[i] *= 1024;
+		}
+		CX18_DEBUG_INFO("Stream type %d options: %d MB, %d buffers, "
+				"%d bytes\n", i, cx->options.megabytes[i],
+				cx->stream_buffers[i], cx->stream_buf_size[i]);
+	}
+
+	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) {
+		CX18_INFO("Ignore card\n");
+		return;
+	}
+	cx->card = cx18_get_card(cx->options.cardtype - 1);
+	if (cx->card)
+		CX18_INFO("User specified %s card\n", cx->card->name);
+	else if (cx->options.cardtype != 0)
+		CX18_ERR("Unknown user specified type, trying to autodetect card\n");
+	if (cx->card == NULL) {
+		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");
+		}
+	}
+	if (cx->card == NULL) {
+		for (i = 0; (cx->card = cx18_get_card(i)); i++) {
+			if (cx->card->pci_list == NULL)
+				continue;
+			for (j = 0; cx->card->pci_list[j].device; j++) {
+				if (cx->pci_dev->device !=
+				    cx->card->pci_list[j].device)
+					continue;
+				if (cx->pci_dev->subsystem_vendor !=
+				    cx->card->pci_list[j].subsystem_vendor)
+					continue;
+				if (cx->pci_dev->subsystem_device !=
+				    cx->card->pci_list[j].subsystem_device)
+					continue;
+				CX18_INFO("Autodetected %s card\n", cx->card->name);
+				goto done;
+			}
+		}
+	}
+done:
+
+	if (cx->card == NULL) {
+		cx->card = cx18_get_card(CX18_CARD_HVR_1600_ESMT);
+		CX18_ERR("Unknown card: vendor/device: [%04x:%04x]\n",
+			 cx->pci_dev->vendor, cx->pci_dev->device);
+		CX18_ERR("              subsystem vendor/device: [%04x:%04x]\n",
+			 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");
+		CX18_ERR("Prefix your subject line with [UNKNOWN CX18 CARD].\n");
+	}
+	cx->v4l2_cap = cx->card->v4l2_capabilities;
+	cx->card_name = cx->card->name;
+	cx->card_i2c = cx->card->i2c;
+}
+
+static int __devinit cx18_create_in_workq(struct cx18 *cx)
+{
+	snprintf(cx->in_workq_name, sizeof(cx->in_workq_name), "%s-in",
+		 cx->v4l2_dev.name);
+	cx->in_work_queue = alloc_ordered_workqueue(cx->in_workq_name, 0);
+	if (cx->in_work_queue == NULL) {
+		CX18_ERR("Unable to create incoming mailbox handler thread\n");
+		return -ENOMEM;
+	}
+	return 0;
+}
+
+static void __devinit cx18_init_in_work_orders(struct cx18 *cx)
+{
+	int i;
+	for (i = 0; i < CX18_MAX_IN_WORK_ORDERS; i++) {
+		cx->in_work_order[i].cx = cx;
+		cx->in_work_order[i].str = cx->epu_debug_str;
+		INIT_WORK(&cx->in_work_order[i].work, cx18_in_work_handler);
+	}
+}
+
+/* Precondition: the cx18 structure has been memset to 0. Only
+   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).
+ */
+static int __devinit cx18_init_struct1(struct cx18 *cx)
+{
+	int ret;
+
+	cx->base_addr = pci_resource_start(cx->pci_dev, 0);
+
+	mutex_init(&cx->serialize_lock);
+	mutex_init(&cx->gpio_lock);
+	mutex_init(&cx->epu2apu_mb_lock);
+	mutex_init(&cx->epu2cpu_mb_lock);
+
+	ret = cx18_create_in_workq(cx);
+	if (ret)
+		return ret;
+
+	cx18_init_in_work_orders(cx);
+
+	/* start counting open_id at 1 */
+	cx->open_id = 1;
+
+	/* Initial settings */
+	cx->cxhdl.port = CX2341X_PORT_MEMORY;
+	cx->cxhdl.capabilities = CX2341X_CAP_HAS_TS | CX2341X_CAP_HAS_SLICED_VBI;
+	cx->cxhdl.ops = &cx18_cxhdl_ops;
+	cx->cxhdl.func = cx18_api_func;
+	cx->cxhdl.priv = &cx->streams[CX18_ENC_STREAM_TYPE_MPG];
+	ret = cx2341x_handler_init(&cx->cxhdl, 50);
+	if (ret)
+		return ret;
+	cx->v4l2_dev.ctrl_handler = &cx->cxhdl.hdl;
+
+	cx->temporal_strength = cx->cxhdl.video_temporal_filter->cur.val;
+	cx->spatial_strength = cx->cxhdl.video_spatial_filter->cur.val;
+	cx->filter_mode = cx->cxhdl.video_spatial_filter_mode->cur.val |
+		(cx->cxhdl.video_temporal_filter_mode->cur.val << 1) |
+		(cx->cxhdl.video_median_filter_type->cur.val << 2);
+
+	init_waitqueue_head(&cx->cap_w);
+	init_waitqueue_head(&cx->mb_apu_waitq);
+	init_waitqueue_head(&cx->mb_cpu_waitq);
+	init_waitqueue_head(&cx->dma_waitq);
+
+	/* VBI */
+	cx->vbi.in.type = V4L2_BUF_TYPE_VBI_CAPTURE;
+	cx->vbi.sliced_in = &cx->vbi.in.fmt.sliced;
+
+	/* IVTV style VBI insertion into MPEG streams */
+	INIT_LIST_HEAD(&cx->vbi.sliced_mpeg_buf.list);
+	INIT_LIST_HEAD(&cx->vbi.sliced_mpeg_mdl.list);
+	INIT_LIST_HEAD(&cx->vbi.sliced_mpeg_mdl.buf_list);
+	list_add(&cx->vbi.sliced_mpeg_buf.list,
+		 &cx->vbi.sliced_mpeg_mdl.buf_list);
+	return 0;
+}
+
+/* Second initialization part. Here the card type has been
+   autodetected. */
+static void __devinit cx18_init_struct2(struct cx18 *cx)
+{
+	int i;
+
+	for (i = 0; i < CX18_CARD_MAX_VIDEO_INPUTS; i++)
+		if (cx->card->video_inputs[i].video_type == 0)
+			break;
+	cx->nof_inputs = i;
+	for (i = 0; i < CX18_CARD_MAX_AUDIO_INPUTS; i++)
+		if (cx->card->audio_inputs[i].audio_type == 0)
+			break;
+	cx->nof_audio_inputs = i;
+
+	/* Find tuner input */
+	for (i = 0; i < cx->nof_inputs; i++) {
+		if (cx->card->video_inputs[i].video_type ==
+				CX18_CARD_INPUT_VID_TUNER)
+			break;
+	}
+	if (i == cx->nof_inputs)
+		i = 0;
+	cx->active_input = i;
+	cx->audio_input = cx->card->video_inputs[i].audio_index;
+}
+
+static int cx18_setup_pci(struct cx18 *cx, struct pci_dev *pci_dev,
+			  const struct pci_device_id *pci_id)
+{
+	u16 cmd;
+	unsigned char pci_latency;
+
+	CX18_DEBUG_INFO("Enabling pci device\n");
+
+	if (pci_enable_device(pci_dev)) {
+		CX18_ERR("Can't enable device %d!\n", cx->instance);
+		return -EIO;
+	}
+	if (pci_set_dma_mask(pci_dev, DMA_BIT_MASK(32))) {
+		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, card %d\n",
+			 cx->instance);
+		return -EIO;
+	}
+
+	/* Enable bus mastering and memory mapped IO for the CX23418 */
+	pci_read_config_word(pci_dev, PCI_COMMAND, &cmd);
+	cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
+	pci_write_config_word(pci_dev, PCI_COMMAND, cmd);
+
+	cx->card_rev = pci_dev->revision;
+	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(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%llx\n",
+		   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, (u64)cx->base_addr);
+
+	return 0;
+}
+
+static void cx18_init_subdevs(struct cx18 *cx)
+{
+	u32 hw = cx->card->hw_all;
+	u32 device;
+	int i;
+
+	for (i = 0, device = 1; i < 32; i++, device <<= 1) {
+
+		if (!(device & hw))
+			continue;
+
+		switch (device) {
+		case CX18_HW_DVB:
+		case CX18_HW_TVEEPROM:
+			/* These subordinate devices do not use probing */
+			cx->hw_flags |= device;
+			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;
+		}
+	}
+
+	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 *pci_dev,
+				const struct pci_device_id *pci_id)
+{
+	int retval = 0;
+	int i;
+	u32 devtype;
+	struct cx18 *cx;
+
+	/* 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 == NULL) {
+		printk(KERN_ERR "cx18: cannot manage card %d, out of memory\n",
+		       i);
+		return -ENOMEM;
+	}
+	cx->pci_dev = pci_dev;
+	cx->instance = i;
+
+	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) {
+		retval = -ENODEV;
+		goto err;
+	}
+
+	retval = cx18_init_struct1(cx);
+	if (retval)
+		goto err;
+
+	CX18_DEBUG_INFO("base addr: 0x%llx\n", (u64)cx->base_addr);
+
+	/* PCI Device Setup */
+	retval = cx18_setup_pci(cx, pci_dev, pci_id);
+	if (retval != 0)
+		goto free_workqueues;
+
+	/* map io memory */
+	CX18_DEBUG_INFO("attempting ioremap at 0x%llx len 0x%08x\n",
+		   (u64)cx->base_addr + CX18_MEM_OFFSET, CX18_MEM_SIZE);
+	cx->enc_mem = ioremap_nocache(cx->base_addr + CX18_MEM_OFFSET,
+				       CX18_MEM_SIZE);
+	if (!cx->enc_mem) {
+		CX18_ERR("ioremap failed. Can't get a window into CX23418 "
+			 "memory and register space\n");
+		CX18_ERR("Each capture card with a CX23418 needs 64 MB of "
+			 "vmalloc address space for the window\n");
+		CX18_ERR("Check the output of 'grep Vmalloc /proc/meminfo'\n");
+		CX18_ERR("Use the vmalloc= kernel command line option to set "
+			 "VmallocTotal to a larger value\n");
+		retval = -ENOMEM;
+		goto free_mem;
+	}
+	cx->reg_mem = cx->enc_mem + CX18_REG_OFFSET;
+	devtype = cx18_read_reg(cx, 0xC72028);
+	switch (devtype & 0xff000000) {
+	case 0xff000000:
+		CX18_INFO("cx23418 revision %08x (A)\n", devtype);
+		break;
+	case 0x01000000:
+		CX18_INFO("cx23418 revision %08x (B)\n", devtype);
+		break;
+	default:
+		CX18_INFO("cx23418 revision %08x (Unknown)\n", devtype);
+		break;
+	}
+
+	cx18_init_power(cx, 1);
+	cx18_init_memory(cx);
+
+	cx->scb = (struct cx18_scb __iomem *)(cx->enc_mem + SCB_OFFSET);
+	cx18_init_scb(cx);
+
+	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;
+	}
+
+	/* 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);
+	if (retval) {
+		CX18_ERR("Could not initialize i2c\n");
+		goto free_map;
+	}
+
+	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. */
+		const struct cx18_card *orig_card = cx->card;
+		cx18_process_eeprom(cx);
+
+		if (cx->card != orig_card) {
+			/* Changed the cardtype; re-reset the I2C chips */
+			cx18_gpio_init(cx);
+			cx18_call_hw(cx, CX18_HW_GPIO_RESET_CTRL,
+					core, reset, (u32) CX18_GPIO_RESET_I2C);
+		}
+	}
+	if (cx->card->comment)
+		CX18_INFO("%s", cx->card->comment);
+	if (cx->card->v4l2_capabilities == 0) {
+		retval = -ENODEV;
+		goto free_i2c;
+	}
+	cx18_init_memory(cx);
+	cx18_init_scb(cx);
+
+	/* Register IRQ */
+	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;
+	}
+
+	if (cx->std == 0)
+		cx->std = V4L2_STD_NTSC_M;
+
+	if (cx->options.tuner == -1) {
+		for (i = 0; i < CX18_CARD_MAX_TUNERS; i++) {
+			if ((cx->std & cx->card->tuners[i].std) == 0)
+				continue;
+			cx->options.tuner = cx->card->tuners[i].tuner;
+			break;
+		}
+	}
+	/* if no tuner was found, then pick the first tuner in the card list */
+	if (cx->options.tuner == -1 && cx->card->tuners[0].std) {
+		cx->std = cx->card->tuners[0].std;
+		if (cx->std & V4L2_STD_PAL)
+			cx->std = V4L2_STD_PAL_BG | V4L2_STD_PAL_H;
+		else if (cx->std & V4L2_STD_NTSC)
+			cx->std = V4L2_STD_NTSC_M;
+		else if (cx->std & V4L2_STD_SECAM)
+			cx->std = V4L2_STD_SECAM_L;
+		cx->options.tuner = cx->card->tuners[0].tuner;
+	}
+	if (cx->options.radio == -1)
+		cx->options.radio = (cx->card->radio_input.audio_type != 0);
+
+	/* The card is now fully identified, continue with card-specific
+	   initialization. */
+	cx18_init_struct2(cx);
+
+	cx18_init_subdevs(cx);
+
+	if (cx->std & V4L2_STD_525_60)
+		cx->is_60hz = 1;
+	else
+		cx->is_50hz = 1;
+
+	cx2341x_handler_set_50hz(&cx->cxhdl, !cx->is_60hz);
+
+	if (cx->options.radio > 0)
+		cx->v4l2_cap |= V4L2_CAP_RADIO;
+
+	if (cx->options.tuner > -1) {
+		struct tuner_setup setup;
+
+		setup.addr = ADDR_UNSET;
+		setup.type = cx->options.tuner;
+		setup.mode_mask = T_ANALOG_TV;  /* matches TV tuners */
+		if (cx->options.radio > 0)
+			setup.mode_mask |= T_RADIO;
+		setup.tuner_callback = (setup.type == TUNER_XC2028) ?
+			cx18_reset_tuner_gpio : NULL;
+		cx18_call_all(cx, tuner, s_type_addr, &setup);
+		if (setup.type == TUNER_XC2028) {
+			static struct xc2028_ctrl ctrl = {
+				.fname = XC2028_DEFAULT_FIRMWARE,
+				.max_len = 64,
+			};
+			struct v4l2_priv_tun_config cfg = {
+				.tuner = cx->options.tuner,
+				.priv = &ctrl,
+			};
+			cx18_call_all(cx, tuner, s_config, &cfg);
+		}
+	}
+
+	/* The tuner is fixed to the standard. The other inputs (e.g. S-Video)
+	   are not. */
+	cx->tuner_std = cx->std;
+	if (cx->std == V4L2_STD_ALL)
+		cx->std = V4L2_STD_NTSC_M;
+
+	retval = cx18_streams_setup(cx);
+	if (retval) {
+		CX18_ERR("Error %d setting up streams\n", retval);
+		goto free_irq;
+	}
+	retval = cx18_streams_register(cx);
+	if (retval) {
+		CX18_ERR("Error %d registering devices\n", retval);
+		goto free_streams;
+	}
+
+	CX18_INFO("Initialized card: %s\n", cx->card_name);
+
+	/* Load cx18 submodules (cx18-alsa) */
+	request_modules(cx);
+	return 0;
+
+free_streams:
+	cx18_streams_cleanup(cx, 1);
+free_irq:
+	free_irq(cx->pci_dev->irq, (void *)cx);
+free_i2c:
+	exit_cx18_i2c(cx);
+free_map:
+	cx18_iounmap(cx);
+free_mem:
+	release_mem_region(cx->base_addr, CX18_MEM_SIZE);
+free_workqueues:
+	destroy_workqueue(cx->in_work_queue);
+err:
+	if (retval == 0)
+		retval = -ENODEV;
+	CX18_ERR("Error %d on initialization\n", retval);
+
+	v4l2_device_unregister(&cx->v4l2_dev);
+	kfree(cx);
+	return retval;
+}
+
+int cx18_init_on_first_open(struct cx18 *cx)
+{
+	int video_input;
+	int fw_retry_count = 3;
+	struct v4l2_frequency vf;
+	struct cx18_open_id fh;
+	v4l2_std_id std;
+
+	fh.cx = cx;
+
+	if (test_bit(CX18_F_I_FAILED, &cx->i_flags))
+		return -ENXIO;
+
+	if (test_and_set_bit(CX18_F_I_INITED, &cx->i_flags))
+		return 0;
+
+	while (--fw_retry_count > 0) {
+		/* load firmware */
+		if (cx18_firmware_init(cx) == 0)
+			break;
+		if (fw_retry_count > 1)
+			CX18_WARN("Retry loading firmware\n");
+	}
+
+	if (fw_retry_count == 0) {
+		set_bit(CX18_F_I_FAILED, &cx->i_flags);
+		return -ENXIO;
+	}
+	set_bit(CX18_F_I_LOADED_FW, &cx->i_flags);
+
+	/*
+	 * 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) {
+		/* load firmware */
+		if (cx18_firmware_init(cx) == 0)
+			break;
+		if (fw_retry_count > 1)
+			CX18_WARN("Retry loading firmware\n");
+	}
+
+	if (fw_retry_count == 0) {
+		set_bit(CX18_F_I_FAILED, &cx->i_flags);
+		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, load_fw);
+
+	vf.tuner = 0;
+	vf.type = V4L2_TUNER_ANALOG_TV;
+	vf.frequency = 6400; /* the tuner 'baseline' frequency */
+
+	/* Set initial frequency. For PAL/SECAM broadcasts no
+	   'default' channel exists AFAIK. */
+	if (cx->std == V4L2_STD_NTSC_M_JP)
+		vf.frequency = 1460;	/* ch. 1 91250*16/1000 */
+	else if (cx->std & V4L2_STD_NTSC_M)
+		vf.frequency = 1076;	/* ch. 4 67250*16/1000 */
+
+	video_input = cx->active_input;
+	cx->active_input++;	/* Force update of input */
+	cx18_s_input(NULL, &fh, video_input);
+
+	/* Let the VIDIOC_S_STD ioctl do all the work, keeps the code
+	   in one place. */
+	cx->std++;		/* Force full standard initialization */
+	std = (cx->tuner_std == V4L2_STD_ALL) ? V4L2_STD_NTSC_M : cx->tuner_std;
+	cx18_s_std(NULL, &fh, &std);
+	cx18_s_frequency(NULL, &fh, &vf);
+	return 0;
+}
+
+static void cx18_cancel_in_work_orders(struct cx18 *cx)
+{
+	int i;
+	for (i = 0; i < CX18_MAX_IN_WORK_ORDERS; i++)
+		cancel_work_sync(&cx->in_work_order[i].work);
+}
+
+static void cx18_cancel_out_work_orders(struct cx18 *cx)
+{
+	int i;
+	for (i = 0; i < CX18_MAX_STREAMS; i++)
+		if (&cx->streams[i].video_dev != NULL)
+			cancel_work_sync(&cx->streams[i].out_work_order);
+}
+
+static void cx18_remove(struct pci_dev *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\n");
+
+	flush_request_modules(cx);
+
+	/* Stop all captures */
+	CX18_DEBUG_INFO("Stopping all streams\n");
+	if (atomic_read(&cx->tot_capturing) > 0)
+		cx18_stop_all_captures(cx);
+
+	/* Stop interrupts that cause incoming work to be queued */
+	cx18_sw1_irq_disable(cx, IRQ_CPU_TO_EPU | IRQ_APU_TO_EPU);
+
+	/* Incoming work can cause outgoing work, so clean up incoming first */
+	cx18_cancel_in_work_orders(cx);
+	cx18_cancel_out_work_orders(cx);
+
+	/* Stop ack interrupts that may have been needed for work to finish */
+	cx18_sw2_irq_disable(cx, IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK);
+
+	cx18_halt_firmware(cx);
+
+	destroy_workqueue(cx->in_work_queue);
+
+	cx18_streams_cleanup(cx, 1);
+
+	exit_cx18_i2c(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->pci_dev);
+
+	if (cx->vbi.sliced_mpeg_data[0] != NULL)
+		for (i = 0; i < CX18_VBI_FRAMES; i++)
+			kfree(cx->vbi.sliced_mpeg_data[i]);
+
+	v4l2_ctrl_handler_free(&cx->av_state.hdl);
+
+	CX18_INFO("Removed %s\n", cx->card_name);
+
+	v4l2_device_unregister(v4l2_dev);
+	kfree(cx);
+}
+
+
+/* define a pci_driver for card detection */
+static struct pci_driver cx18_pci_driver = {
+      .name =     "cx18",
+      .id_table = cx18_pci_tbl,
+      .probe =    cx18_probe,
+      .remove =   cx18_remove,
+};
+
+static int __init module_start(void)
+{
+	printk(KERN_INFO "cx18:  Start initialization, version %s\n",
+	       CX18_VERSION);
+
+	/* 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",
+		     CX18_MAX_CARDS - 1);
+		return -1;
+	}
+
+	if (cx18_debug < 0 || cx18_debug > 511) {
+		cx18_debug = 0;
+		printk(KERN_INFO "cx18:   Debug value must be >= 0 and <= 511!\n");
+	}
+
+	if (pci_register_driver(&cx18_pci_driver)) {
+		printk(KERN_ERR "cx18:   Error detecting PCI card\n");
+		return -ENODEV;
+	}
+	printk(KERN_INFO "cx18:  End initialization\n");
+	return 0;
+}
+
+static void __exit module_cleanup(void)
+{
+	pci_unregister_driver(&cx18_pci_driver);
+}
+
+module_init(module_start);
+module_exit(module_cleanup);
+MODULE_FIRMWARE(XC2028_DEFAULT_FIRMWARE);
diff --git a/drivers/media/pci/cx18/cx18-driver.h b/drivers/media/pci/cx18/cx18-driver.h
new file mode 100644
index 0000000..2767c64
--- /dev/null
+++ b/drivers/media/pci/cx18/cx18-driver.h
@@ -0,0 +1,730 @@
+/*
+ *  cx18 driver internal defines and structures
+ *
+ *  Derived from ivtv-driver.h
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.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 program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public 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 CX18_DRIVER_H
+#define CX18_DRIVER_H
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+#include <linux/list.h>
+#include <linux/unistd.h>
+#include <linux/pagemap.h>
+#include <linux/workqueue.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <asm/byteorder.h>
+
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-fh.h>
+#include <media/tuner.h>
+#include <media/ir-kbd-i2c.h>
+#include "cx18-mailbox.h"
+#include "cx18-av-core.h"
+#include "cx23418.h"
+
+/* DVB */
+#include "demux.h"
+#include "dmxdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dvb_net.h"
+#include "dvbdev.h"
+
+/* Videobuf / YUV support */
+#include <media/videobuf-core.h>
+#include <media/videobuf-vmalloc.h>
+
+#ifndef CONFIG_PCI
+#  error "This driver requires kernel PCI support."
+#endif
+
+#define CX18_MEM_OFFSET	0x00000000
+#define CX18_MEM_SIZE	0x04000000
+#define CX18_REG_OFFSET	0x02000000
+
+/* Maximum cx18 driver instances. */
+#define CX18_MAX_CARDS 32
+
+/* Supported cards */
+#define CX18_CARD_HVR_1600_ESMT	      0	/* Hauppauge HVR 1600 (ESMT memory) */
+#define CX18_CARD_HVR_1600_SAMSUNG    1	/* Hauppauge HVR 1600 (Samsung memory) */
+#define CX18_CARD_COMPRO_H900 	      2	/* Compro VideoMate H900 */
+#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_DVR3100H    7 /* Leadtek WinFast DVR3100 H */
+#define CX18_CARD_GOTVIEW_PCI_DVD3    8 /* GoTView PCI DVD3 Hybrid */
+#define CX18_CARD_HVR_1600_S5H1411    9 /* Hauppauge HVR 1600 s5h1411/tda18271*/
+#define CX18_CARD_LAST		      9
+
+#define CX18_ENC_STREAM_TYPE_MPG  0
+#define CX18_ENC_STREAM_TYPE_TS   1
+#define CX18_ENC_STREAM_TYPE_YUV  2
+#define CX18_ENC_STREAM_TYPE_VBI  3
+#define CX18_ENC_STREAM_TYPE_PCM  4
+#define CX18_ENC_STREAM_TYPE_IDX  5
+#define CX18_ENC_STREAM_TYPE_RAD  6
+#define CX18_MAX_STREAMS	  7
+
+/* system vendor and device IDs */
+#define PCI_VENDOR_ID_CX      0x14f1
+#define PCI_DEVICE_ID_CX23418 0x5b7a
+
+/* subsystem vendor ID */
+#define CX18_PCI_ID_HAUPPAUGE 		0x0070
+#define CX18_PCI_ID_COMPRO 		0x185b
+#define CX18_PCI_ID_YUAN 		0x12ab
+#define CX18_PCI_ID_CONEXANT		0x14f1
+#define CX18_PCI_ID_TOSHIBA		0x1179
+#define CX18_PCI_ID_LEADTEK		0x107D
+#define CX18_PCI_ID_GOTVIEW		0x5854
+
+/* ======================================================================== */
+/* ========================== START USER SETTABLE DMA VARIABLES =========== */
+/* ======================================================================== */
+
+/* DMA Buffers, Default size in MB allocated */
+#define CX18_DEFAULT_ENC_TS_BUFFERS  1
+#define CX18_DEFAULT_ENC_MPG_BUFFERS 2
+#define CX18_DEFAULT_ENC_IDX_BUFFERS 1
+#define CX18_DEFAULT_ENC_YUV_BUFFERS 2
+#define CX18_DEFAULT_ENC_VBI_BUFFERS 1
+#define CX18_DEFAULT_ENC_PCM_BUFFERS 1
+
+/* Maximum firmware DMA buffers per stream */
+#define CX18_MAX_FW_MDLS_PER_STREAM 63
+
+/* YUV buffer sizes in bytes to ensure integer # of frames per buffer */
+#define CX18_UNIT_ENC_YUV_BUFSIZE	(720 *  32 * 3 / 2) /* bytes */
+#define CX18_625_LINE_ENC_YUV_BUFSIZE	(CX18_UNIT_ENC_YUV_BUFSIZE * 576/32)
+#define CX18_525_LINE_ENC_YUV_BUFSIZE	(CX18_UNIT_ENC_YUV_BUFSIZE * 480/32)
+
+/* IDX buffer size should be a multiple of the index entry size from the chip */
+struct cx18_enc_idx_entry {
+	__le32 length;
+	__le32 offset_low;
+	__le32 offset_high;
+	__le32 flags;
+	__le32 pts_low;
+	__le32 pts_high;
+} __attribute__ ((packed));
+#define CX18_UNIT_ENC_IDX_BUFSIZE \
+	(sizeof(struct cx18_enc_idx_entry) * V4L2_ENC_IDX_ENTRIES)
+
+/* DMA buffer, default size in kB allocated */
+#define CX18_DEFAULT_ENC_TS_BUFSIZE   32
+#define CX18_DEFAULT_ENC_MPG_BUFSIZE  32
+#define CX18_DEFAULT_ENC_IDX_BUFSIZE  (CX18_UNIT_ENC_IDX_BUFSIZE * 1 / 1024 + 1)
+#define CX18_DEFAULT_ENC_YUV_BUFSIZE  (CX18_UNIT_ENC_YUV_BUFSIZE * 3 / 1024 + 1)
+#define CX18_DEFAULT_ENC_PCM_BUFSIZE   4
+
+/* i2c stuff */
+#define I2C_CLIENTS_MAX 16
+
+/* debugging */
+
+/* Flag to turn on high volume debugging */
+#define CX18_DBGFLG_WARN  (1 << 0)
+#define CX18_DBGFLG_INFO  (1 << 1)
+#define CX18_DBGFLG_API   (1 << 2)
+#define CX18_DBGFLG_DMA   (1 << 3)
+#define CX18_DBGFLG_IOCTL (1 << 4)
+#define CX18_DBGFLG_FILE  (1 << 5)
+#define CX18_DBGFLG_I2C   (1 << 6)
+#define CX18_DBGFLG_IRQ   (1 << 7)
+/* Flag to turn on high volume debugging */
+#define CX18_DBGFLG_HIGHVOL (1 << 8)
+
+/* 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) \
+			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)
+#define CX18_DEBUG_API(fmt, args...)   CX18_DEBUG(CX18_DBGFLG_API, "api", fmt , ## args)
+#define CX18_DEBUG_DMA(fmt, args...)   CX18_DEBUG(CX18_DBGFLG_DMA, "dma", fmt , ## args)
+#define CX18_DEBUG_IOCTL(fmt, args...) CX18_DEBUG(CX18_DBGFLG_IOCTL, "ioctl", fmt , ## args)
+#define CX18_DEBUG_FILE(fmt, args...)  CX18_DEBUG(CX18_DBGFLG_FILE, "file", fmt , ## args)
+#define CX18_DEBUG_I2C(fmt, args...)   CX18_DEBUG(CX18_DBGFLG_I2C, "i2c", fmt , ## args)
+#define CX18_DEBUG_IRQ(fmt, args...)   CX18_DEBUG(CX18_DBGFLG_IRQ, "irq", fmt , ## args)
+
+#define CX18_DEBUG_HIGH_VOL(x, type, fmt, args...) \
+	do { \
+		if (((x) & cx18_debug) && (cx18_debug & CX18_DBGFLG_HIGHVOL)) \
+			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)
+#define CX18_DEBUG_HI_API(fmt, args...)   CX18_DEBUG_HIGH_VOL(CX18_DBGFLG_API, "api", fmt , ## args)
+#define CX18_DEBUG_HI_DMA(fmt, args...)   CX18_DEBUG_HIGH_VOL(CX18_DBGFLG_DMA, "dma", fmt , ## args)
+#define CX18_DEBUG_HI_IOCTL(fmt, args...) CX18_DEBUG_HIGH_VOL(CX18_DBGFLG_IOCTL, "ioctl", fmt , ## args)
+#define CX18_DEBUG_HI_FILE(fmt, args...)  CX18_DEBUG_HIGH_VOL(CX18_DBGFLG_FILE, "file", fmt , ## args)
+#define CX18_DEBUG_HI_I2C(fmt, args...)   CX18_DEBUG_HIGH_VOL(CX18_DBGFLG_I2C, "i2c", fmt , ## args)
+#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...)      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)
+
+extern int cx18_debug;
+
+struct cx18_options {
+	int megabytes[CX18_MAX_STREAMS]; /* Size in megabytes of each stream */
+	int cardtype;		/* force card type on load */
+	int tuner;		/* set tuner on load */
+	int radio;		/* enable/disable radio */
+};
+
+/* per-mdl bit flags */
+#define CX18_F_M_NEED_SWAP  0	/* mdl buffer data must be endianess swapped */
+
+/* per-stream, s_flags */
+#define CX18_F_S_CLAIMED 	3	/* this stream is claimed */
+#define CX18_F_S_STREAMING      4	/* the fw is decoding/encoding this stream */
+#define CX18_F_S_INTERNAL_USE	5	/* this stream is used internally (sliced VBI processing) */
+#define CX18_F_S_STREAMOFF	7	/* signal end of stream EOS */
+#define CX18_F_S_APPL_IO        8	/* this stream is used read/written by an application */
+#define CX18_F_S_STOPPING	9	/* telling the fw to stop capturing */
+
+/* per-cx18, i_flags */
+#define CX18_F_I_LOADED_FW		0 	/* Loaded firmware 1st time */
+#define CX18_F_I_EOS			4 	/* End of encoder stream */
+#define CX18_F_I_RADIO_USER		5 	/* radio tuner is selected */
+#define CX18_F_I_ENC_PAUSED		13 	/* the encoder is paused */
+#define CX18_F_I_INITED			21 	/* set after first open */
+#define CX18_F_I_FAILED			22 	/* set if first open failed */
+
+/* These are the VBI types as they appear in the embedded VBI private packets. */
+#define CX18_SLICED_TYPE_TELETEXT_B     (1)
+#define CX18_SLICED_TYPE_CAPTION_525    (4)
+#define CX18_SLICED_TYPE_WSS_625        (5)
+#define CX18_SLICED_TYPE_VPS            (7)
+
+/**
+ * list_entry_is_past_end - check if a previous loop cursor is off list end
+ * @pos:	the type * previously used as a loop cursor.
+ * @head:	the head for your list.
+ * @member:	the name of the list_struct within the struct.
+ *
+ * Check if the entry's list_head is the head of the list, thus it's not a
+ * real entry but was the loop cursor that walked past the end
+ */
+#define list_entry_is_past_end(pos, head, member) \
+	(&pos->member == (head))
+
+struct cx18_buffer {
+	struct list_head list;
+	dma_addr_t dma_handle;
+	char *buf;
+
+	u32 bytesused;
+	u32 readpos;
+};
+
+struct cx18_mdl {
+	struct list_head list;
+	u32 id;		/* index into cx->scb->cpu_mdl[] of 1st cx18_mdl_ent */
+
+	unsigned int skipped;
+	unsigned long m_flags;
+
+	struct list_head buf_list;
+	struct cx18_buffer *curr_buf; /* current buffer in list for reading */
+
+	u32 bytesused;
+	u32 readpos;
+};
+
+struct cx18_queue {
+	struct list_head list;
+	atomic_t depth;
+	u32 bytesused;
+	spinlock_t lock;
+};
+
+struct cx18_stream; /* forward reference */
+
+struct cx18_dvb {
+	struct cx18_stream *stream;
+	struct dmx_frontend hw_frontend;
+	struct dmx_frontend mem_frontend;
+	struct dmxdev dmxdev;
+	struct dvb_adapter dvb_adapter;
+	struct dvb_demux demux;
+	struct dvb_frontend *fe;
+	struct dvb_net dvbnet;
+	int enabled;
+	int feeding;
+	struct mutex feedlock;
+};
+
+struct cx18;	 /* forward reference */
+struct cx18_scb; /* forward reference */
+
+
+#define CX18_MAX_MDL_ACKS 2
+#define CX18_MAX_IN_WORK_ORDERS (CX18_MAX_FW_MDLS_PER_STREAM + 7)
+/* CPU_DE_RELEASE_MDL can burst CX18_MAX_FW_MDLS_PER_STREAM orders in a group */
+
+#define CX18_F_EWO_MB_STALE_UPON_RECEIPT 0x1
+#define CX18_F_EWO_MB_STALE_WHILE_PROC   0x2
+#define CX18_F_EWO_MB_STALE \
+	     (CX18_F_EWO_MB_STALE_UPON_RECEIPT | CX18_F_EWO_MB_STALE_WHILE_PROC)
+
+struct cx18_in_work_order {
+	struct work_struct work;
+	atomic_t pending;
+	struct cx18 *cx;
+	unsigned long flags;
+	int rpu;
+	struct cx18_mailbox mb;
+	struct cx18_mdl_ack mdl_ack[CX18_MAX_MDL_ACKS];
+	char *str;
+};
+
+#define CX18_INVALID_TASK_HANDLE 0xffffffff
+
+struct cx18_stream {
+	/* These first five fields are always set, even if the stream
+	   is not actually created. */
+	struct video_device *video_dev;	/* NULL when stream not created */
+	struct cx18_dvb *dvb;		/* DVB / Digital Transport */
+	struct cx18 *cx; 		/* for ease of use */
+	const char *name;		/* name of the stream */
+	int type;			/* stream type */
+	u32 handle;			/* task handle */
+	unsigned int mdl_base_idx;
+
+	u32 id;
+	unsigned long s_flags;	/* status flags, see above */
+	int dma;		/* can be PCI_DMA_TODEVICE,
+				   PCI_DMA_FROMDEVICE or
+				   PCI_DMA_NONE */
+	wait_queue_head_t waitq;
+
+	/* Buffers */
+	struct list_head buf_pool;	/* buffers not attached to an MDL */
+	u32 buffers;			/* total buffers owned by this stream */
+	u32 buf_size;			/* size in bytes of a single buffer */
+
+	/* MDL sizes - all stream MDLs are the same size */
+	u32 bufs_per_mdl;
+	u32 mdl_size;		/* total bytes in all buffers in a mdl */
+
+	/* MDL Queues */
+	struct cx18_queue q_free;	/* free - in rotation, not committed */
+	struct cx18_queue q_busy;	/* busy - in use by firmware */
+	struct cx18_queue q_full;	/* full - data for user apps */
+	struct cx18_queue q_idle;	/* idle - not in rotation */
+
+	struct work_struct out_work_order;
+
+	/* Videobuf for YUV video */
+	u32 pixelformat;
+	u32 vb_bytes_per_frame;
+	struct list_head vb_capture;    /* video capture queue */
+	spinlock_t vb_lock;
+	struct timer_list vb_timeout;
+
+	struct videobuf_queue vbuf_q;
+	spinlock_t vbuf_q_lock; /* Protect vbuf_q */
+	enum v4l2_buf_type vb_type;
+};
+
+struct cx18_videobuf_buffer {
+	/* Common video buffer sub-system struct */
+	struct videobuf_buffer vb;
+	v4l2_std_id tvnorm; /* selected tv norm */
+	u32 bytes_used;
+};
+
+struct cx18_open_id {
+	struct v4l2_fh fh;
+	u32 open_id;
+	int type;
+	struct cx18 *cx;
+};
+
+static inline struct cx18_open_id *fh2id(struct v4l2_fh *fh)
+{
+	return container_of(fh, struct cx18_open_id, fh);
+}
+
+static inline struct cx18_open_id *file2id(struct file *file)
+{
+	return fh2id(file->private_data);
+}
+
+/* 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
+
+struct vbi_info {
+	/* Current state of v4l2 VBI settings for this device */
+	struct v4l2_format 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.
+	 * 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];
+
+	/*
+	 * 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];
+
+	/* Count of Program Pack/Program Stream 1 packets inserted into PS */
+	u32 inserted_frame;
+
+	/*
+	 * A dummy driver stream transfer mdl & 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_mdl sliced_mpeg_mdl;
+	struct cx18_buffer sliced_mpeg_buf;
+};
+
+/* Per cx23418, per I2C bus private algo callback data */
+struct cx18_i2c_algo_callback_data {
+	struct cx18 *cx;
+	int bus_index;   /* 0 or 1 for the cx23418's 1st or 2nd I2C bus */
+};
+
+#define CX18_MAX_MMIO_WR_RETRIES 10
+
+/* Struct to hold info about cx18 cards */
+struct cx18 {
+	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 nof_inputs;		/* number of video inputs */
+	u8 nof_audio_inputs;	/* number of audio inputs */
+	u32 v4l2_cap;		/* V4L2 capabilities of card */
+	u32 hw_flags; 		/* Hardware description of the board */
+	unsigned int free_mdl_idx;
+	struct cx18_scb __iomem *scb; /* pointer to SCB */
+	struct mutex epu2apu_mb_lock; /* protect driver to chip mailbox in SCB*/
+	struct mutex epu2cpu_mb_lock; /* protect driver to chip mailbox in SCB*/
+
+	struct cx18_av_state av_state;
+
+	/* codec settings */
+	struct cx2341x_handler cxhdl;
+	u32 filter_mode;
+	u32 temporal_strength;
+	u32 spatial_strength;
+
+	/* dualwatch */
+	unsigned long dualwatch_jiffies;
+	u32 dualwatch_stereo_mode;
+
+	struct mutex serialize_lock;    /* mutex used to serialize open/close/start/stop/ioctl operations */
+	struct cx18_options options; 	/* User options */
+	int stream_buffers[CX18_MAX_STREAMS]; /* # of buffers for each stream */
+	int stream_buf_size[CX18_MAX_STREAMS]; /* Stream buffer size */
+	struct cx18_stream streams[CX18_MAX_STREAMS]; 	/* Stream data */
+	struct snd_cx18_card *alsa; /* ALSA interface for PCM capture stream */
+	void (*pcm_announce_callback)(struct snd_cx18_card *card, u8 *pcm_data,
+				      size_t num_bytes);
+
+	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 */
+	int search_pack_header;
+
+	int open_id;		/* incremented each time an open occurs, used as
+				   unique ID. Starts at 1, so 0 can be used as
+				   uninitialized value in the stream->id. */
+
+	resource_size_t base_addr;
+
+	u8 card_rev;
+	void __iomem *enc_mem, *reg_mem;
+
+	struct vbi_info vbi;
+
+	u64 mpg_data_received;
+	u64 vbi_data_inserted;
+
+	wait_queue_head_t mb_apu_waitq;
+	wait_queue_head_t mb_cpu_waitq;
+	wait_queue_head_t cap_w;
+	/* when the current DMA is finished this queue is woken up */
+	wait_queue_head_t dma_waitq;
+
+	u32 sw1_irq_mask;
+	u32 sw2_irq_mask;
+	u32 hw2_irq_mask;
+
+	struct workqueue_struct *in_work_queue;
+	char in_workq_name[11]; /* "cx18-NN-in" */
+	struct cx18_in_work_order in_work_order[CX18_MAX_IN_WORK_ORDERS];
+	char epu_debug_str[256]; /* CX18_EPU_DEBUG is rare: use shared space */
+
+	/* i2c */
+	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 IR_i2c_init_data ir_i2c_init_data;
+
+	/* 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;
+	v4l2_std_id std;
+	v4l2_std_id tuner_std;	/* The norm of the tuner (fixed) */
+
+	/* Used for cx18-alsa module loading */
+	struct work_struct request_module_wk;
+};
+
+static inline struct cx18 *to_cx18(struct v4l2_device *v4l2_dev)
+{
+	return container_of(v4l2_dev, struct cx18, v4l2_dev);
+}
+
+/* cx18 extensions to be loaded */
+extern int (*cx18_ext_init)(struct cx18 *);
+
+/* Globals */
+extern int cx18_first_minor;
+
+/*==============Prototypes==================*/
+
+/* Return non-zero if a signal is pending */
+int cx18_msleep_timeout(unsigned int msecs, int intr);
+
+/* Read Hauppauge eeprom */
+struct tveeprom; /* forward reference */
+void cx18_read_eeprom(struct cx18 *cx, struct tveeprom *tv);
+
+/* First-open initialization: load firmware, etc. */
+int cx18_init_on_first_open(struct cx18 *cx);
+
+/* Test if the current VBI mode is raw (1) or sliced (0) */
+static inline int cx18_raw_vbi(const struct cx18 *cx)
+{
+	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...)				\
+	do {								\
+		struct v4l2_subdev *__sd;				\
+		__v4l2_device_call_subdevs_p(&(cx)->v4l2_dev, __sd,	\
+			!(hw) || (__sd->grp_id & (hw)), o, f , ##args);	\
+	} while (0)
+
+#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...)				\
+({									\
+	struct v4l2_subdev *__sd;					\
+	__v4l2_device_call_subdevs_until_err_p(&(cx)->v4l2_dev,		\
+			__sd, !(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/pci/cx18/cx18-dvb.c b/drivers/media/pci/cx18/cx18-dvb.c
new file mode 100644
index 0000000..3eac59c
--- /dev/null
+++ b/drivers/media/pci/cx18/cx18-dvb.c
@@ -0,0 +1,609 @@
+/*
+ *  cx18 functions for DVB support
+ *
+ *  Copyright (c) 2008 Steven Toth <stoth@linuxtv.org>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.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 program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You 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 "cx18-version.h"
+#include "cx18-dvb.h"
+#include "cx18-io.h"
+#include "cx18-queue.h"
+#include "cx18-streams.h"
+#include "cx18-cards.h"
+#include "cx18-gpio.h"
+#include "s5h1409.h"
+#include "mxl5005s.h"
+#include "s5h1411.h"
+#include "tda18271.h"
+#include "zl10353.h"
+
+#include <linux/firmware.h>
+#include "mt352.h"
+#include "mt352_priv.h"
+#include "tuner-xc2028.h"
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+#define FWFILE "dvb-cx18-mpc718-mt352.fw"
+
+#define CX18_REG_DMUX_NUM_PORT_0_CONTROL 0xd5a000
+#define CX18_CLOCK_ENABLE2		 0xc71024
+#define CX18_DMUX_CLK_MASK		 0x0080
+
+/*
+ * CX18_CARD_HVR_1600_ESMT
+ * CX18_CARD_HVR_1600_SAMSUNG
+ */
+
+static struct mxl5005s_config hauppauge_hvr1600_tuner = {
+	.i2c_address     = 0xC6 >> 1,
+	.if_freq         = IF_FREQ_5380000HZ,
+	.xtal_freq       = CRYSTAL_FREQ_16000000HZ,
+	.agc_mode        = MXL_SINGLE_AGC,
+	.tracking_filter = MXL_TF_C_H,
+	.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,
+	.qam_gain        = 0x02,
+	.AgcMasterByte   = 0x00,
+};
+
+static struct s5h1409_config hauppauge_hvr1600_config = {
+	.demod_address = 0x32 >> 1,
+	.output_mode   = S5H1409_SERIAL_OUTPUT,
+	.gpio          = S5H1409_GPIO_ON,
+	.qam_if        = 44000,
+	.inversion     = S5H1409_INVERSION_OFF,
+	.status_mode   = S5H1409_DEMODLOCKING,
+	.mpeg_timing   = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
+	.hvr1600_opt   = S5H1409_HVR1600_OPTIMIZE
+};
+
+/*
+ * CX18_CARD_HVR_1600_S5H1411
+ */
+static struct s5h1411_config hcw_s5h1411_config = {
+	.output_mode   = S5H1411_SERIAL_OUTPUT,
+	.gpio          = S5H1411_GPIO_OFF,
+	.vsb_if        = S5H1411_IF_44000,
+	.qam_if        = S5H1411_IF_4000,
+	.inversion     = S5H1411_INVERSION_ON,
+	.status_mode   = S5H1411_DEMODLOCKING,
+	.mpeg_timing   = S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
+};
+
+static struct tda18271_std_map hauppauge_tda18271_std_map = {
+	.atsc_6   = { .if_freq = 5380, .agc_mode = 3, .std = 3,
+		      .if_lvl = 6, .rfagc_top = 0x37 },
+	.qam_6    = { .if_freq = 4000, .agc_mode = 3, .std = 0,
+		      .if_lvl = 6, .rfagc_top = 0x37 },
+};
+
+static struct tda18271_config hauppauge_tda18271_config = {
+	.std_map = &hauppauge_tda18271_std_map,
+	.gate    = TDA18271_GATE_DIGITAL,
+	.output_opt = TDA18271_OUTPUT_LT_OFF,
+};
+
+/*
+ * CX18_CARD_LEADTEK_DVR3100H
+ */
+/* Information/confirmation of proper config values provided by Terry Wu */
+static struct zl10353_config leadtek_dvr3100h_demod = {
+	.demod_address         = 0x1e >> 1, /* Datasheet suggested straps */
+	.if2                   = 45600,     /* 4.560 MHz IF from the XC3028 */
+	.parallel_ts           = 1,         /* Not a serial TS */
+	.no_tuner              = 1,         /* XC3028 is not behind the gate */
+	.disable_i2c_gate_ctrl = 1,         /* Disable the I2C gate */
+};
+
+/*
+ * CX18_CARD_YUAN_MPC718
+ */
+/*
+ * Due to
+ *
+ * 1. an absence of information on how to prgram the MT352
+ * 2. the Linux mt352 module pushing MT352 initialzation off onto us here
+ *
+ * We have to use an init sequence that *you* must extract from the Windows
+ * driver (yuanrap.sys) and which we load as a firmware.
+ *
+ * If someone can provide me with a Zarlink MT352 (Intel CE6352?) Design Manual
+ * with chip programming details, then I can remove this annoyance.
+ */
+static int yuan_mpc718_mt352_reqfw(struct cx18_stream *stream,
+				   const struct firmware **fw)
+{
+	struct cx18 *cx = stream->cx;
+	const char *fn = FWFILE;
+	int ret;
+
+	ret = request_firmware(fw, fn, &cx->pci_dev->dev);
+	if (ret)
+		CX18_ERR("Unable to open firmware file %s\n", fn);
+	else {
+		size_t sz = (*fw)->size;
+		if (sz < 2 || sz > 64 || (sz % 2) != 0) {
+			CX18_ERR("Firmware %s has a bad size: %lu bytes\n",
+				 fn, (unsigned long) sz);
+			ret = -EILSEQ;
+			release_firmware(*fw);
+			*fw = NULL;
+		}
+	}
+
+	if (ret) {
+		CX18_ERR("The MPC718 board variant with the MT352 DVB-T"
+			  "demodualtor will not work without it\n");
+		CX18_ERR("Run 'linux/Documentation/dvb/get_dvb_firmware "
+			  "mpc718' if you need the firmware\n");
+	}
+	return ret;
+}
+
+static int yuan_mpc718_mt352_init(struct dvb_frontend *fe)
+{
+	struct cx18_dvb *dvb = container_of(fe->dvb,
+					    struct cx18_dvb, dvb_adapter);
+	struct cx18_stream *stream = dvb->stream;
+	const struct firmware *fw = NULL;
+	int ret;
+	int i;
+	u8 buf[3];
+
+	ret = yuan_mpc718_mt352_reqfw(stream, &fw);
+	if (ret)
+		return ret;
+
+	/* Loop through all the register-value pairs in the firmware file */
+	for (i = 0; i < fw->size; i += 2) {
+		buf[0] = fw->data[i];
+		/* Intercept a few registers we want to set ourselves */
+		switch (buf[0]) {
+		case TRL_NOMINAL_RATE_0:
+			/* Set our custom OFDM bandwidth in the case below */
+			break;
+		case TRL_NOMINAL_RATE_1:
+			/* 6 MHz: 64/7 * 6/8 / 20.48 * 2^16 = 0x55b6.db6 */
+			/* 7 MHz: 64/7 * 7/8 / 20.48 * 2^16 = 0x6400 */
+			/* 8 MHz: 64/7 * 8/8 / 20.48 * 2^16 = 0x7249.249 */
+			buf[1] = 0x72;
+			buf[2] = 0x49;
+			mt352_write(fe, buf, 3);
+			break;
+		case INPUT_FREQ_0:
+			/* Set our custom IF in the case below */
+			break;
+		case INPUT_FREQ_1:
+			/* 4.56 MHz IF: (20.48 - 4.56)/20.48 * 2^14 = 0x31c0 */
+			buf[1] = 0x31;
+			buf[2] = 0xc0;
+			mt352_write(fe, buf, 3);
+			break;
+		default:
+			/* Pass through the register-value pair from the fw */
+			buf[1] = fw->data[i+1];
+			mt352_write(fe, buf, 2);
+			break;
+		}
+	}
+
+	buf[0] = (u8) TUNER_GO;
+	buf[1] = 0x01; /* Go */
+	mt352_write(fe, buf, 2);
+	release_firmware(fw);
+	return 0;
+}
+
+static struct mt352_config yuan_mpc718_mt352_demod = {
+	.demod_address = 0x1e >> 1,
+	.adc_clock     = 20480,     /* 20.480 MHz */
+	.if2           =  4560,     /*  4.560 MHz */
+	.no_tuner      = 1,         /* XC3028 is not behind the gate */
+	.demod_init    = yuan_mpc718_mt352_init,
+};
+
+static struct zl10353_config yuan_mpc718_zl10353_demod = {
+	.demod_address         = 0x1e >> 1, /* Datasheet suggested straps */
+	.if2                   = 45600,     /* 4.560 MHz IF from the XC3028 */
+	.parallel_ts           = 1,         /* Not a serial TS */
+	.no_tuner              = 1,         /* XC3028 is not behind the gate */
+	.disable_i2c_gate_ctrl = 1,         /* Disable the I2C gate */
+};
+
+static struct zl10353_config gotview_dvd3_zl10353_demod = {
+	.demod_address         = 0x1e >> 1, /* Datasheet suggested straps */
+	.if2                   = 45600,     /* 4.560 MHz IF from the XC3028 */
+	.parallel_ts           = 1,         /* Not a serial TS */
+	.no_tuner              = 1,         /* XC3028 is not behind the gate */
+	.disable_i2c_gate_ctrl = 1,         /* Disable the I2C gate */
+};
+
+static int dvb_register(struct cx18_stream *stream);
+
+/* Kernel DVB framework calls this when the feed needs to start.
+ * The CX18 framework should enable the transport DMA handling
+ * and queue processing.
+ */
+static int cx18_dvb_start_feed(struct dvb_demux_feed *feed)
+{
+	struct dvb_demux *demux = feed->demux;
+	struct cx18_stream *stream = (struct cx18_stream *) demux->priv;
+	struct cx18 *cx;
+	int ret;
+	u32 v;
+
+	if (!stream)
+		return -EINVAL;
+
+	cx = stream->cx;
+	CX18_DEBUG_INFO("Start feed: pid = 0x%x index = %d\n",
+			feed->pid, feed->index);
+
+	mutex_lock(&cx->serialize_lock);
+	ret = cx18_init_on_first_open(cx);
+	mutex_unlock(&cx->serialize_lock);
+	if (ret) {
+		CX18_ERR("Failed to initialize firmware starting DVB feed\n");
+		return ret;
+	}
+	ret = -EINVAL;
+
+	switch (cx->card->type) {
+	case CX18_CARD_HVR_1600_ESMT:
+	case CX18_CARD_HVR_1600_SAMSUNG:
+	case CX18_CARD_HVR_1600_S5H1411:
+		v = cx18_read_reg(cx, CX18_REG_DMUX_NUM_PORT_0_CONTROL);
+		v |= 0x00400000; /* Serial Mode */
+		v |= 0x00002000; /* Data Length - Byte */
+		v |= 0x00010000; /* Error - Polarity */
+		v |= 0x00020000; /* Error - Passthru */
+		v |= 0x000c0000; /* Error - Ignore */
+		cx18_write_reg(cx, v, CX18_REG_DMUX_NUM_PORT_0_CONTROL);
+		break;
+
+	case CX18_CARD_LEADTEK_DVR3100H:
+	case CX18_CARD_YUAN_MPC718:
+	case CX18_CARD_GOTVIEW_PCI_DVD3:
+	default:
+		/* Assumption - Parallel transport - Signalling
+		 * undefined or default.
+		 */
+		break;
+	}
+
+	if (!demux->dmx.frontend)
+		return -EINVAL;
+
+	mutex_lock(&stream->dvb->feedlock);
+	if (stream->dvb->feeding++ == 0) {
+		CX18_DEBUG_INFO("Starting Transport DMA\n");
+		mutex_lock(&cx->serialize_lock);
+		set_bit(CX18_F_S_STREAMING, &stream->s_flags);
+		ret = cx18_start_v4l2_encode_stream(stream);
+		if (ret < 0) {
+			CX18_DEBUG_INFO("Failed to start Transport DMA\n");
+			stream->dvb->feeding--;
+			if (stream->dvb->feeding == 0)
+				clear_bit(CX18_F_S_STREAMING, &stream->s_flags);
+		}
+		mutex_unlock(&cx->serialize_lock);
+	} else
+		ret = 0;
+	mutex_unlock(&stream->dvb->feedlock);
+
+	return ret;
+}
+
+/* Kernel DVB framework calls this when the feed needs to stop. */
+static int cx18_dvb_stop_feed(struct dvb_demux_feed *feed)
+{
+	struct dvb_demux *demux = feed->demux;
+	struct cx18_stream *stream = (struct cx18_stream *)demux->priv;
+	struct cx18 *cx;
+	int ret = -EINVAL;
+
+	if (stream) {
+		cx = stream->cx;
+		CX18_DEBUG_INFO("Stop feed: pid = 0x%x index = %d\n",
+				feed->pid, feed->index);
+
+		mutex_lock(&stream->dvb->feedlock);
+		if (--stream->dvb->feeding == 0) {
+			CX18_DEBUG_INFO("Stopping Transport DMA\n");
+			mutex_lock(&cx->serialize_lock);
+			ret = cx18_stop_v4l2_encode_stream(stream, 0);
+			mutex_unlock(&cx->serialize_lock);
+		} else
+			ret = 0;
+		mutex_unlock(&stream->dvb->feedlock);
+	}
+
+	return ret;
+}
+
+int cx18_dvb_register(struct cx18_stream *stream)
+{
+	struct cx18 *cx = stream->cx;
+	struct cx18_dvb *dvb = stream->dvb;
+	struct dvb_adapter *dvb_adapter;
+	struct dvb_demux *dvbdemux;
+	struct dmx_demux *dmx;
+	int ret;
+
+	if (!dvb)
+		return -EINVAL;
+
+	dvb->enabled = 0;
+	dvb->stream = stream;
+
+	ret = dvb_register_adapter(&dvb->dvb_adapter,
+			CX18_DRIVER_NAME,
+			THIS_MODULE, &cx->pci_dev->dev, adapter_nr);
+	if (ret < 0)
+		goto err_out;
+
+	dvb_adapter = &dvb->dvb_adapter;
+
+	dvbdemux = &dvb->demux;
+
+	dvbdemux->priv = (void *)stream;
+
+	dvbdemux->filternum = 256;
+	dvbdemux->feednum = 256;
+	dvbdemux->start_feed = cx18_dvb_start_feed;
+	dvbdemux->stop_feed = cx18_dvb_stop_feed;
+	dvbdemux->dmx.capabilities = (DMX_TS_FILTERING |
+		DMX_SECTION_FILTERING | DMX_MEMORY_BASED_FILTERING);
+	ret = dvb_dmx_init(dvbdemux);
+	if (ret < 0)
+		goto err_dvb_unregister_adapter;
+
+	dmx = &dvbdemux->dmx;
+
+	dvb->hw_frontend.source = DMX_FRONTEND_0;
+	dvb->mem_frontend.source = DMX_MEMORY_FE;
+	dvb->dmxdev.filternum = 256;
+	dvb->dmxdev.demux = dmx;
+
+	ret = dvb_dmxdev_init(&dvb->dmxdev, dvb_adapter);
+	if (ret < 0)
+		goto err_dvb_dmx_release;
+
+	ret = dmx->add_frontend(dmx, &dvb->hw_frontend);
+	if (ret < 0)
+		goto err_dvb_dmxdev_release;
+
+	ret = dmx->add_frontend(dmx, &dvb->mem_frontend);
+	if (ret < 0)
+		goto err_remove_hw_frontend;
+
+	ret = dmx->connect_frontend(dmx, &dvb->hw_frontend);
+	if (ret < 0)
+		goto err_remove_mem_frontend;
+
+	ret = dvb_register(stream);
+	if (ret < 0)
+		goto err_disconnect_frontend;
+
+	dvb_net_init(dvb_adapter, &dvb->dvbnet, dmx);
+
+	CX18_INFO("DVB Frontend registered\n");
+	CX18_INFO("Registered DVB adapter%d for %s (%d x %d.%02d kB)\n",
+		  stream->dvb->dvb_adapter.num, stream->name,
+		  stream->buffers, stream->buf_size/1024,
+		  (stream->buf_size * 100 / 1024) % 100);
+
+	mutex_init(&dvb->feedlock);
+	dvb->enabled = 1;
+	return ret;
+
+err_disconnect_frontend:
+	dmx->disconnect_frontend(dmx);
+err_remove_mem_frontend:
+	dmx->remove_frontend(dmx, &dvb->mem_frontend);
+err_remove_hw_frontend:
+	dmx->remove_frontend(dmx, &dvb->hw_frontend);
+err_dvb_dmxdev_release:
+	dvb_dmxdev_release(&dvb->dmxdev);
+err_dvb_dmx_release:
+	dvb_dmx_release(dvbdemux);
+err_dvb_unregister_adapter:
+	dvb_unregister_adapter(dvb_adapter);
+err_out:
+	return ret;
+}
+
+void cx18_dvb_unregister(struct cx18_stream *stream)
+{
+	struct cx18 *cx = stream->cx;
+	struct cx18_dvb *dvb = stream->dvb;
+	struct dvb_adapter *dvb_adapter;
+	struct dvb_demux *dvbdemux;
+	struct dmx_demux *dmx;
+
+	CX18_INFO("unregister DVB\n");
+
+	if (dvb == NULL || !dvb->enabled)
+		return;
+
+	dvb_adapter = &dvb->dvb_adapter;
+	dvbdemux = &dvb->demux;
+	dmx = &dvbdemux->dmx;
+
+	dmx->close(dmx);
+	dvb_net_release(&dvb->dvbnet);
+	dmx->remove_frontend(dmx, &dvb->mem_frontend);
+	dmx->remove_frontend(dmx, &dvb->hw_frontend);
+	dvb_dmxdev_release(&dvb->dmxdev);
+	dvb_dmx_release(dvbdemux);
+	dvb_unregister_frontend(dvb->fe);
+	dvb_frontend_detach(dvb->fe);
+	dvb_unregister_adapter(dvb_adapter);
+}
+
+/* All the DVB attach calls go here, this function get's modified
+ * for each new card. cx18_dvb_start_feed() will also need changes.
+ */
+static int dvb_register(struct cx18_stream *stream)
+{
+	struct cx18_dvb *dvb = stream->dvb;
+	struct cx18 *cx = stream->cx;
+	int ret = 0;
+
+	switch (cx->card->type) {
+	case CX18_CARD_HVR_1600_ESMT:
+	case CX18_CARD_HVR_1600_SAMSUNG:
+		dvb->fe = dvb_attach(s5h1409_attach,
+			&hauppauge_hvr1600_config,
+			&cx->i2c_adap[0]);
+		if (dvb->fe != NULL) {
+			dvb_attach(mxl5005s_attach, dvb->fe,
+				&cx->i2c_adap[0],
+				&hauppauge_hvr1600_tuner);
+			ret = 0;
+		}
+		break;
+	case CX18_CARD_HVR_1600_S5H1411:
+		dvb->fe = dvb_attach(s5h1411_attach,
+				     &hcw_s5h1411_config,
+				     &cx->i2c_adap[0]);
+		if (dvb->fe != NULL)
+			dvb_attach(tda18271_attach, dvb->fe,
+				   0x60, &cx->i2c_adap[0],
+				   &hauppauge_tda18271_config);
+		break;
+	case CX18_CARD_LEADTEK_DVR3100H:
+		dvb->fe = dvb_attach(zl10353_attach,
+				     &leadtek_dvr3100h_demod,
+				     &cx->i2c_adap[1]);
+		if (dvb->fe != NULL) {
+			struct dvb_frontend *fe;
+			struct xc2028_config cfg = {
+				.i2c_adap = &cx->i2c_adap[1],
+				.i2c_addr = 0xc2 >> 1,
+				.ctrl = NULL,
+			};
+			static struct xc2028_ctrl ctrl = {
+				.fname   = XC2028_DEFAULT_FIRMWARE,
+				.max_len = 64,
+				.demod   = XC3028_FE_ZARLINK456,
+				.type    = XC2028_AUTO,
+			};
+
+			fe = dvb_attach(xc2028_attach, dvb->fe, &cfg);
+			if (fe != NULL && fe->ops.tuner_ops.set_config != NULL)
+				fe->ops.tuner_ops.set_config(fe, &ctrl);
+		}
+		break;
+	case CX18_CARD_YUAN_MPC718:
+		/*
+		 * TODO
+		 * Apparently, these cards also could instead have a
+		 * DiBcom demod supported by one of the db7000 drivers
+		 */
+		dvb->fe = dvb_attach(mt352_attach,
+				     &yuan_mpc718_mt352_demod,
+				     &cx->i2c_adap[1]);
+		if (dvb->fe == NULL)
+			dvb->fe = dvb_attach(zl10353_attach,
+					     &yuan_mpc718_zl10353_demod,
+					     &cx->i2c_adap[1]);
+		if (dvb->fe != NULL) {
+			struct dvb_frontend *fe;
+			struct xc2028_config cfg = {
+				.i2c_adap = &cx->i2c_adap[1],
+				.i2c_addr = 0xc2 >> 1,
+				.ctrl = NULL,
+			};
+			static struct xc2028_ctrl ctrl = {
+				.fname   = XC2028_DEFAULT_FIRMWARE,
+				.max_len = 64,
+				.demod   = XC3028_FE_ZARLINK456,
+				.type    = XC2028_AUTO,
+			};
+
+			fe = dvb_attach(xc2028_attach, dvb->fe, &cfg);
+			if (fe != NULL && fe->ops.tuner_ops.set_config != NULL)
+				fe->ops.tuner_ops.set_config(fe, &ctrl);
+		}
+		break;
+	case CX18_CARD_GOTVIEW_PCI_DVD3:
+			dvb->fe = dvb_attach(zl10353_attach,
+					     &gotview_dvd3_zl10353_demod,
+					     &cx->i2c_adap[1]);
+		if (dvb->fe != NULL) {
+			struct dvb_frontend *fe;
+			struct xc2028_config cfg = {
+				.i2c_adap = &cx->i2c_adap[1],
+				.i2c_addr = 0xc2 >> 1,
+				.ctrl = NULL,
+			};
+			static struct xc2028_ctrl ctrl = {
+				.fname   = XC2028_DEFAULT_FIRMWARE,
+				.max_len = 64,
+				.demod   = XC3028_FE_ZARLINK456,
+				.type    = XC2028_AUTO,
+			};
+
+			fe = dvb_attach(xc2028_attach, dvb->fe, &cfg);
+			if (fe != NULL && fe->ops.tuner_ops.set_config != NULL)
+				fe->ops.tuner_ops.set_config(fe, &ctrl);
+		}
+		break;
+	default:
+		/* No Digital Tv Support */
+		break;
+	}
+
+	if (dvb->fe == NULL) {
+		CX18_ERR("frontend initialization failed\n");
+		return -1;
+	}
+
+	dvb->fe->callback = cx18_reset_tuner_gpio;
+
+	ret = dvb_register_frontend(&dvb->dvb_adapter, dvb->fe);
+	if (ret < 0) {
+		if (dvb->fe->ops.release)
+			dvb->fe->ops.release(dvb->fe);
+		return ret;
+	}
+
+	/*
+	 * The firmware seems to enable the TS DMUX clock
+	 * under various circumstances.  However, since we know we
+	 * might use it, let's just turn it on ourselves here.
+	 */
+	cx18_write_reg_expect(cx,
+			      (CX18_DMUX_CLK_MASK << 16) | CX18_DMUX_CLK_MASK,
+			      CX18_CLOCK_ENABLE2,
+			      CX18_DMUX_CLK_MASK,
+			      (CX18_DMUX_CLK_MASK << 16) | CX18_DMUX_CLK_MASK);
+
+	return ret;
+}
+
+MODULE_FIRMWARE(FWFILE);
diff --git a/drivers/media/pci/cx18/cx18-dvb.h b/drivers/media/pci/cx18/cx18-dvb.h
new file mode 100644
index 0000000..bf8d8f6
--- /dev/null
+++ b/drivers/media/pci/cx18/cx18-dvb.h
@@ -0,0 +1,25 @@
+/*
+ *  cx18 functions for DVB support
+ *
+ *  Copyright (c) 2008 Steven Toth <stoth@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 "cx18-driver.h"
+
+int cx18_dvb_register(struct cx18_stream *stream);
+void cx18_dvb_unregister(struct cx18_stream *stream);
diff --git a/drivers/media/pci/cx18/cx18-fileops.c b/drivers/media/pci/cx18/cx18-fileops.c
new file mode 100644
index 0000000..4bfd865
--- /dev/null
+++ b/drivers/media/pci/cx18/cx18-fileops.c
@@ -0,0 +1,881 @@
+/*
+ *  cx18 file operation functions
+ *
+ *  Derived from ivtv-fileops.c
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.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 program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public 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 "cx18-driver.h"
+#include "cx18-fileops.h"
+#include "cx18-i2c.h"
+#include "cx18-queue.h"
+#include "cx18-vbi.h"
+#include "cx18-audio.h"
+#include "cx18-mailbox.h"
+#include "cx18-scb.h"
+#include "cx18-streams.h"
+#include "cx18-controls.h"
+#include "cx18-ioctl.h"
+#include "cx18-cards.h"
+
+/* This function tries to claim the stream for a specific file descriptor.
+   If no one else is using this stream then the stream is claimed and
+   associated VBI and IDX streams are also automatically claimed.
+   Possible error returns: -EBUSY if someone else has claimed
+   the stream or 0 on success. */
+int cx18_claim_stream(struct cx18_open_id *id, int type)
+{
+	struct cx18 *cx = id->cx;
+	struct cx18_stream *s = &cx->streams[type];
+	struct cx18_stream *s_assoc;
+
+	/* Nothing should ever try to directly claim the IDX stream */
+	if (type == CX18_ENC_STREAM_TYPE_IDX) {
+		CX18_WARN("MPEG Index stream cannot be claimed "
+			  "directly, but something tried.\n");
+		return -EINVAL;
+	}
+
+	if (test_and_set_bit(CX18_F_S_CLAIMED, &s->s_flags)) {
+		/* someone already claimed this stream */
+		if (s->id == id->open_id) {
+			/* yes, this file descriptor did. So that's OK. */
+			return 0;
+		}
+		if (s->id == -1 && type == CX18_ENC_STREAM_TYPE_VBI) {
+			/* VBI is handled already internally, now also assign
+			   the file descriptor to this stream for external
+			   reading of the stream. */
+			s->id = id->open_id;
+			CX18_DEBUG_INFO("Start Read VBI\n");
+			return 0;
+		}
+		/* someone else is using this stream already */
+		CX18_DEBUG_INFO("Stream %d is busy\n", type);
+		return -EBUSY;
+	}
+	s->id = id->open_id;
+
+	/*
+	 * CX18_ENC_STREAM_TYPE_MPG needs to claim:
+	 * CX18_ENC_STREAM_TYPE_VBI, if VBI insertion is on for sliced VBI, or
+	 * CX18_ENC_STREAM_TYPE_IDX, if VBI insertion is off for sliced VBI
+	 * (We don't yet fix up MPEG Index entries for our inserted packets).
+	 *
+	 * For all other streams we're done.
+	 */
+	if (type != CX18_ENC_STREAM_TYPE_MPG)
+		return 0;
+
+	s_assoc = &cx->streams[CX18_ENC_STREAM_TYPE_IDX];
+	if (cx->vbi.insert_mpeg && !cx18_raw_vbi(cx))
+		s_assoc = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
+	else if (!cx18_stream_enabled(s_assoc))
+		return 0;
+
+	set_bit(CX18_F_S_CLAIMED, &s_assoc->s_flags);
+
+	/* mark that it is used internally */
+	set_bit(CX18_F_S_INTERNAL_USE, &s_assoc->s_flags);
+	return 0;
+}
+EXPORT_SYMBOL(cx18_claim_stream);
+
+/* This function releases a previously claimed stream. It will take into
+   account associated VBI streams. */
+void cx18_release_stream(struct cx18_stream *s)
+{
+	struct cx18 *cx = s->cx;
+	struct cx18_stream *s_assoc;
+
+	s->id = -1;
+	if (s->type == CX18_ENC_STREAM_TYPE_IDX) {
+		/*
+		 * The IDX stream is only used internally, and can
+		 * only be indirectly unclaimed by unclaiming the MPG stream.
+		 */
+		return;
+	}
+
+	if (s->type == CX18_ENC_STREAM_TYPE_VBI &&
+		test_bit(CX18_F_S_INTERNAL_USE, &s->s_flags)) {
+		/* this stream is still in use internally */
+		return;
+	}
+	if (!test_and_clear_bit(CX18_F_S_CLAIMED, &s->s_flags)) {
+		CX18_DEBUG_WARN("Release stream %s not in use!\n", s->name);
+		return;
+	}
+
+	cx18_flush_queues(s);
+
+	/*
+	 * CX18_ENC_STREAM_TYPE_MPG needs to release the
+	 * CX18_ENC_STREAM_TYPE_VBI and/or CX18_ENC_STREAM_TYPE_IDX streams.
+	 *
+	 * For all other streams we're done.
+	 */
+	if (s->type != CX18_ENC_STREAM_TYPE_MPG)
+		return;
+
+	/* Unclaim the associated MPEG Index stream */
+	s_assoc = &cx->streams[CX18_ENC_STREAM_TYPE_IDX];
+	if (test_and_clear_bit(CX18_F_S_INTERNAL_USE, &s_assoc->s_flags)) {
+		clear_bit(CX18_F_S_CLAIMED, &s_assoc->s_flags);
+		cx18_flush_queues(s_assoc);
+	}
+
+	/* Unclaim the associated VBI stream */
+	s_assoc = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
+	if (test_and_clear_bit(CX18_F_S_INTERNAL_USE, &s_assoc->s_flags)) {
+		if (s_assoc->id == -1) {
+			/*
+			 * The VBI stream is not still claimed by a file
+			 * descriptor, so completely unclaim it.
+			 */
+			clear_bit(CX18_F_S_CLAIMED, &s_assoc->s_flags);
+			cx18_flush_queues(s_assoc);
+		}
+	}
+}
+EXPORT_SYMBOL(cx18_release_stream);
+
+static void cx18_dualwatch(struct cx18 *cx)
+{
+	struct v4l2_tuner vt;
+	u32 new_stereo_mode;
+	const u32 dual = 0x0200;
+
+	new_stereo_mode = v4l2_ctrl_g_ctrl(cx->cxhdl.audio_mode);
+	memset(&vt, 0, sizeof(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;
+
+	if (new_stereo_mode == cx->dualwatch_stereo_mode)
+		return;
+
+	CX18_DEBUG_INFO("dualwatch: change stereo flag from 0x%x to 0x%x.\n",
+			   cx->dualwatch_stereo_mode, new_stereo_mode);
+	if (v4l2_ctrl_s_ctrl(cx->cxhdl.audio_mode, new_stereo_mode))
+		CX18_DEBUG_INFO("dualwatch: changing stereo flag failed\n");
+}
+
+
+static struct cx18_mdl *cx18_get_mdl(struct cx18_stream *s, int non_block,
+				     int *err)
+{
+	struct cx18 *cx = s->cx;
+	struct cx18_stream *s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
+	struct cx18_mdl *mdl;
+	DEFINE_WAIT(wait);
+
+	*err = 0;
+	while (1) {
+		if (s->type == CX18_ENC_STREAM_TYPE_MPG) {
+			/* Process pending program updates and VBI data */
+			if (time_after(jiffies, cx->dualwatch_jiffies + msecs_to_jiffies(1000))) {
+				cx->dualwatch_jiffies = jiffies;
+				cx18_dualwatch(cx);
+			}
+			if (test_bit(CX18_F_S_INTERNAL_USE, &s_vbi->s_flags) &&
+			    !test_bit(CX18_F_S_APPL_IO, &s_vbi->s_flags)) {
+				while ((mdl = cx18_dequeue(s_vbi,
+							   &s_vbi->q_full))) {
+					/* byteswap and process VBI data */
+					cx18_process_vbi_data(cx, mdl,
+							      s_vbi->type);
+					cx18_stream_put_mdl_fw(s_vbi, mdl);
+				}
+			}
+			mdl = &cx->vbi.sliced_mpeg_mdl;
+			if (mdl->readpos != mdl->bytesused)
+				return mdl;
+		}
+
+		/* do we have new data? */
+		mdl = cx18_dequeue(s, &s->q_full);
+		if (mdl) {
+			if (!test_and_clear_bit(CX18_F_M_NEED_SWAP,
+						&mdl->m_flags))
+				return mdl;
+			if (s->type == CX18_ENC_STREAM_TYPE_MPG)
+				/* byteswap MPG data */
+				cx18_mdl_swap(mdl);
+			else {
+				/* byteswap and process VBI data */
+				cx18_process_vbi_data(cx, mdl, s->type);
+			}
+			return mdl;
+		}
+
+		/* return if end of stream */
+		if (!test_bit(CX18_F_S_STREAMING, &s->s_flags)) {
+			CX18_DEBUG_INFO("EOS %s\n", s->name);
+			return NULL;
+		}
+
+		/* return if file was opened with O_NONBLOCK */
+		if (non_block) {
+			*err = -EAGAIN;
+			return NULL;
+		}
+
+		/* wait for more data to arrive */
+		prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE);
+		/* New buffers might have become available before we were added
+		   to the waitqueue */
+		if (!atomic_read(&s->q_full.depth))
+			schedule();
+		finish_wait(&s->waitq, &wait);
+		if (signal_pending(current)) {
+			/* return if a signal was received */
+			CX18_DEBUG_INFO("User stopped %s\n", s->name);
+			*err = -EINTR;
+			return NULL;
+		}
+	}
+}
+
+static void cx18_setup_sliced_vbi_mdl(struct cx18 *cx)
+{
+	struct cx18_mdl *mdl = &cx->vbi.sliced_mpeg_mdl;
+	struct cx18_buffer *buf = &cx->vbi.sliced_mpeg_buf;
+	int idx = cx->vbi.inserted_frame % CX18_VBI_FRAMES;
+
+	buf->buf = cx->vbi.sliced_mpeg_data[idx];
+	buf->bytesused = cx->vbi.sliced_mpeg_size[idx];
+	buf->readpos = 0;
+
+	mdl->curr_buf = NULL;
+	mdl->bytesused = cx->vbi.sliced_mpeg_size[idx];
+	mdl->readpos = 0;
+}
+
+static size_t cx18_copy_buf_to_user(struct cx18_stream *s,
+	struct cx18_buffer *buf, char __user *ubuf, size_t ucount, bool *stop)
+{
+	struct cx18 *cx = s->cx;
+	size_t len = buf->bytesused - buf->readpos;
+
+	*stop = false;
+	if (len > ucount)
+		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.
+		 *
+		 * This will not work for an MPEG-2 TS and has only been
+		 * verified by analysis to work for an MPEG-2 PS.  Helen Buus
+		 * pointed out this works for the CX23416 MPEG-2 DVD compatible
+		 * stream, and research indicates both the MPEG 2 SVCD and DVD
+		 * stream types use an MPEG-2 PS container.
+		 */
+		/*
+		 * 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;
+		u8 ch = cx->search_pack_header ? 0xba : 0xe0;
+		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;
+				/* 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; /* 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 && /* 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) {
+				/* We declare we actually found a Program Pack*/
+				cx->search_pack_header = 0; /* expect vid PES */
+				len = (char *)q - start;
+				cx18_setup_sliced_vbi_mdl(cx);
+				*stop = true;
+				break;
+			}
+		}
+	}
+	if (copy_to_user(ubuf, (u8 *)buf->buf + buf->readpos, len)) {
+		CX18_DEBUG_WARN("copy %zd bytes to user failed for %s\n",
+				len, s->name);
+		return -EFAULT;
+	}
+	buf->readpos += len;
+	if (s->type == CX18_ENC_STREAM_TYPE_MPG &&
+	    buf != &cx->vbi.sliced_mpeg_buf)
+		cx->mpg_data_received += len;
+	return len;
+}
+
+static size_t cx18_copy_mdl_to_user(struct cx18_stream *s,
+		struct cx18_mdl *mdl, char __user *ubuf, size_t ucount)
+{
+	size_t tot_written = 0;
+	int rc;
+	bool stop = false;
+
+	if (mdl->curr_buf == NULL)
+		mdl->curr_buf = list_first_entry(&mdl->buf_list,
+						 struct cx18_buffer, list);
+
+	if (list_entry_is_past_end(mdl->curr_buf, &mdl->buf_list, list)) {
+		/*
+		 * For some reason we've exhausted the buffers, but the MDL
+		 * object still said some data was unread.
+		 * Fix that and bail out.
+		 */
+		mdl->readpos = mdl->bytesused;
+		return 0;
+	}
+
+	list_for_each_entry_from(mdl->curr_buf, &mdl->buf_list, list) {
+
+		if (mdl->curr_buf->readpos >= mdl->curr_buf->bytesused)
+			continue;
+
+		rc = cx18_copy_buf_to_user(s, mdl->curr_buf, ubuf + tot_written,
+					   ucount - tot_written, &stop);
+		if (rc < 0)
+			return rc;
+		mdl->readpos += rc;
+		tot_written += rc;
+
+		if (stop ||	/* Forced stopping point for VBI insertion */
+		    tot_written >= ucount ||	/* Reader request statisfied */
+		    mdl->curr_buf->readpos < mdl->curr_buf->bytesused ||
+		    mdl->readpos >= mdl->bytesused) /* MDL buffers drained */
+			break;
+	}
+	return tot_written;
+}
+
+static ssize_t cx18_read(struct cx18_stream *s, char __user *ubuf,
+		size_t tot_count, int non_block)
+{
+	struct cx18 *cx = s->cx;
+	size_t tot_written = 0;
+	int single_frame = 0;
+
+	if (atomic_read(&cx->ana_capturing) == 0 && s->id == -1) {
+		/* shouldn't happen */
+		CX18_DEBUG_WARN("Stream %s not initialized before read\n",
+				s->name);
+		return -EIO;
+	}
+
+	/* Each VBI buffer is one frame, the v4l2 API says that for VBI the
+	   frames should arrive one-by-one, so make sure we never output more
+	   than one VBI frame at a time */
+	if (s->type == CX18_ENC_STREAM_TYPE_VBI && !cx18_raw_vbi(cx))
+		single_frame = 1;
+
+	for (;;) {
+		struct cx18_mdl *mdl;
+		int rc;
+
+		mdl = cx18_get_mdl(s, non_block, &rc);
+		/* if there is no data available... */
+		if (mdl == NULL) {
+			/* if we got data, then return that regardless */
+			if (tot_written)
+				break;
+			/* EOS condition */
+			if (rc == 0) {
+				clear_bit(CX18_F_S_STREAMOFF, &s->s_flags);
+				clear_bit(CX18_F_S_APPL_IO, &s->s_flags);
+				cx18_release_stream(s);
+			}
+			/* set errno */
+			return rc;
+		}
+
+		rc = cx18_copy_mdl_to_user(s, mdl, ubuf + tot_written,
+				tot_count - tot_written);
+
+		if (mdl != &cx->vbi.sliced_mpeg_mdl) {
+			if (mdl->readpos == mdl->bytesused)
+				cx18_stream_put_mdl_fw(s, mdl);
+			else
+				cx18_push(s, mdl, &s->q_full);
+		} else if (mdl->readpos == mdl->bytesused) {
+			int idx = cx->vbi.inserted_frame % CX18_VBI_FRAMES;
+
+			cx->vbi.sliced_mpeg_size[idx] = 0;
+			cx->vbi.inserted_frame++;
+			cx->vbi_data_inserted += mdl->bytesused;
+		}
+		if (rc < 0)
+			return rc;
+		tot_written += rc;
+
+		if (tot_written == tot_count || single_frame)
+			break;
+	}
+	return tot_written;
+}
+
+static ssize_t cx18_read_pos(struct cx18_stream *s, char __user *ubuf,
+		size_t count, loff_t *pos, int non_block)
+{
+	ssize_t rc = count ? cx18_read(s, ubuf, count, non_block) : 0;
+	struct cx18 *cx = s->cx;
+
+	CX18_DEBUG_HI_FILE("read %zd from %s, got %zd\n", count, s->name, rc);
+	if (rc > 0)
+		pos += rc;
+	return rc;
+}
+
+int cx18_start_capture(struct cx18_open_id *id)
+{
+	struct cx18 *cx = id->cx;
+	struct cx18_stream *s = &cx->streams[id->type];
+	struct cx18_stream *s_vbi;
+	struct cx18_stream *s_idx;
+
+	if (s->type == CX18_ENC_STREAM_TYPE_RAD) {
+		/* you cannot read from these stream types. */
+		return -EPERM;
+	}
+
+	/* Try to claim this stream. */
+	if (cx18_claim_stream(id, s->type))
+		return -EBUSY;
+
+	/* If capture is already in progress, then we also have to
+	   do nothing extra. */
+	if (test_bit(CX18_F_S_STREAMOFF, &s->s_flags) ||
+	    test_and_set_bit(CX18_F_S_STREAMING, &s->s_flags)) {
+		set_bit(CX18_F_S_APPL_IO, &s->s_flags);
+		return 0;
+	}
+
+	/* Start associated VBI or IDX stream capture if required */
+	s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
+	s_idx = &cx->streams[CX18_ENC_STREAM_TYPE_IDX];
+	if (s->type == CX18_ENC_STREAM_TYPE_MPG) {
+		/*
+		 * The VBI and IDX streams should have been claimed
+		 * automatically, if for internal use, when the MPG stream was
+		 * claimed.  We only need to start these streams capturing.
+		 */
+		if (test_bit(CX18_F_S_INTERNAL_USE, &s_idx->s_flags) &&
+		    !test_and_set_bit(CX18_F_S_STREAMING, &s_idx->s_flags)) {
+			if (cx18_start_v4l2_encode_stream(s_idx)) {
+				CX18_DEBUG_WARN("IDX capture start failed\n");
+				clear_bit(CX18_F_S_STREAMING, &s_idx->s_flags);
+				goto start_failed;
+			}
+			CX18_DEBUG_INFO("IDX capture started\n");
+		}
+		if (test_bit(CX18_F_S_INTERNAL_USE, &s_vbi->s_flags) &&
+		    !test_and_set_bit(CX18_F_S_STREAMING, &s_vbi->s_flags)) {
+			if (cx18_start_v4l2_encode_stream(s_vbi)) {
+				CX18_DEBUG_WARN("VBI capture start failed\n");
+				clear_bit(CX18_F_S_STREAMING, &s_vbi->s_flags);
+				goto start_failed;
+			}
+			CX18_DEBUG_INFO("VBI insertion started\n");
+		}
+	}
+
+	/* Tell the card to start capturing */
+	if (!cx18_start_v4l2_encode_stream(s)) {
+		/* We're done */
+		set_bit(CX18_F_S_APPL_IO, &s->s_flags);
+		/* Resume a possibly paused encoder */
+		if (test_and_clear_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags))
+			cx18_vapi(cx, CX18_CPU_CAPTURE_PAUSE, 1, s->handle);
+		return 0;
+	}
+
+start_failed:
+	CX18_DEBUG_WARN("Failed to start capturing for stream %s\n", s->name);
+
+	/*
+	 * The associated VBI and IDX streams for internal use are released
+	 * automatically when the MPG stream is released.  We only need to stop
+	 * the associated stream.
+	 */
+	if (s->type == CX18_ENC_STREAM_TYPE_MPG) {
+		/* Stop the IDX stream which is always for internal use */
+		if (test_bit(CX18_F_S_STREAMING, &s_idx->s_flags)) {
+			cx18_stop_v4l2_encode_stream(s_idx, 0);
+			clear_bit(CX18_F_S_STREAMING, &s_idx->s_flags);
+		}
+		/* Stop the VBI stream, if only running for internal use */
+		if (test_bit(CX18_F_S_STREAMING, &s_vbi->s_flags) &&
+		    !test_bit(CX18_F_S_APPL_IO, &s_vbi->s_flags)) {
+			cx18_stop_v4l2_encode_stream(s_vbi, 0);
+			clear_bit(CX18_F_S_STREAMING, &s_vbi->s_flags);
+		}
+	}
+	clear_bit(CX18_F_S_STREAMING, &s->s_flags);
+	cx18_release_stream(s); /* Also releases associated streams */
+	return -EIO;
+}
+
+ssize_t cx18_v4l2_read(struct file *filp, char __user *buf, size_t count,
+		loff_t *pos)
+{
+	struct cx18_open_id *id = file2id(filp);
+	struct cx18 *cx = id->cx;
+	struct cx18_stream *s = &cx->streams[id->type];
+	int rc;
+
+	CX18_DEBUG_HI_FILE("read %zd bytes from %s\n", count, s->name);
+
+	mutex_lock(&cx->serialize_lock);
+	rc = cx18_start_capture(id);
+	mutex_unlock(&cx->serialize_lock);
+	if (rc)
+		return rc;
+
+	if ((s->vb_type == V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
+		(id->type == CX18_ENC_STREAM_TYPE_YUV)) {
+		return videobuf_read_stream(&s->vbuf_q, buf, count, pos, 0,
+			filp->f_flags & O_NONBLOCK);
+	}
+
+	return cx18_read_pos(s, buf, count, pos, filp->f_flags & O_NONBLOCK);
+}
+
+unsigned int cx18_v4l2_enc_poll(struct file *filp, poll_table *wait)
+{
+	struct cx18_open_id *id = file2id(filp);
+	struct cx18 *cx = id->cx;
+	struct cx18_stream *s = &cx->streams[id->type];
+	int eof = test_bit(CX18_F_S_STREAMOFF, &s->s_flags);
+
+	/* Start a capture if there is none */
+	if (!eof && !test_bit(CX18_F_S_STREAMING, &s->s_flags)) {
+		int rc;
+
+		mutex_lock(&cx->serialize_lock);
+		rc = cx18_start_capture(id);
+		mutex_unlock(&cx->serialize_lock);
+		if (rc) {
+			CX18_DEBUG_INFO("Could not start capture for %s (%d)\n",
+					s->name, rc);
+			return POLLERR;
+		}
+		CX18_DEBUG_FILE("Encoder poll started capture\n");
+	}
+
+	if ((s->vb_type == V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
+		(id->type == CX18_ENC_STREAM_TYPE_YUV)) {
+		int videobuf_poll = videobuf_poll_stream(filp, &s->vbuf_q, wait);
+                if (eof && videobuf_poll == POLLERR)
+                        return POLLHUP;
+                else
+                        return videobuf_poll;
+	}
+
+	/* add stream's waitq to the poll list */
+	CX18_DEBUG_HI_FILE("Encoder poll\n");
+	poll_wait(filp, &s->waitq, wait);
+
+	if (atomic_read(&s->q_full.depth))
+		return POLLIN | POLLRDNORM;
+	if (eof)
+		return POLLHUP;
+	return 0;
+}
+
+int cx18_v4l2_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	struct cx18_open_id *id = file->private_data;
+	struct cx18 *cx = id->cx;
+	struct cx18_stream *s = &cx->streams[id->type];
+	int eof = test_bit(CX18_F_S_STREAMOFF, &s->s_flags);
+
+	if ((s->vb_type == V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
+		(id->type == CX18_ENC_STREAM_TYPE_YUV)) {
+
+		/* Start a capture if there is none */
+		if (!eof && !test_bit(CX18_F_S_STREAMING, &s->s_flags)) {
+			int rc;
+
+			mutex_lock(&cx->serialize_lock);
+			rc = cx18_start_capture(id);
+			mutex_unlock(&cx->serialize_lock);
+			if (rc) {
+				CX18_DEBUG_INFO(
+					"Could not start capture for %s (%d)\n",
+					s->name, rc);
+				return -EINVAL;
+			}
+			CX18_DEBUG_FILE("Encoder mmap started capture\n");
+		}
+
+		return videobuf_mmap_mapper(&s->vbuf_q, vma);
+	}
+
+	return -EINVAL;
+}
+
+void cx18_vb_timeout(unsigned long data)
+{
+	struct cx18_stream *s = (struct cx18_stream *)data;
+	struct cx18_videobuf_buffer *buf;
+	unsigned long flags;
+
+	/* Return all of the buffers in error state, so the vbi/vid inode
+	 * can return from blocking.
+	 */
+	spin_lock_irqsave(&s->vb_lock, flags);
+	while (!list_empty(&s->vb_capture)) {
+		buf = list_entry(s->vb_capture.next,
+			struct cx18_videobuf_buffer, vb.queue);
+		list_del(&buf->vb.queue);
+		buf->vb.state = VIDEOBUF_ERROR;
+		wake_up(&buf->vb.done);
+	}
+	spin_unlock_irqrestore(&s->vb_lock, flags);
+}
+
+void cx18_stop_capture(struct cx18_open_id *id, int gop_end)
+{
+	struct cx18 *cx = id->cx;
+	struct cx18_stream *s = &cx->streams[id->type];
+	struct cx18_stream *s_vbi = &cx->streams[CX18_ENC_STREAM_TYPE_VBI];
+	struct cx18_stream *s_idx = &cx->streams[CX18_ENC_STREAM_TYPE_IDX];
+
+	CX18_DEBUG_IOCTL("close() of %s\n", s->name);
+
+	/* 'Unclaim' this stream */
+
+	/* Stop capturing */
+	if (test_bit(CX18_F_S_STREAMING, &s->s_flags)) {
+		CX18_DEBUG_INFO("close stopping capture\n");
+		if (id->type == CX18_ENC_STREAM_TYPE_MPG) {
+			/* Stop internal use associated VBI and IDX streams */
+			if (test_bit(CX18_F_S_STREAMING, &s_vbi->s_flags) &&
+			    !test_bit(CX18_F_S_APPL_IO, &s_vbi->s_flags)) {
+				CX18_DEBUG_INFO("close stopping embedded VBI "
+						"capture\n");
+				cx18_stop_v4l2_encode_stream(s_vbi, 0);
+			}
+			if (test_bit(CX18_F_S_STREAMING, &s_idx->s_flags)) {
+				CX18_DEBUG_INFO("close stopping IDX capture\n");
+				cx18_stop_v4l2_encode_stream(s_idx, 0);
+			}
+		}
+		if (id->type == CX18_ENC_STREAM_TYPE_VBI &&
+		    test_bit(CX18_F_S_INTERNAL_USE, &s->s_flags))
+			/* Also used internally, don't stop capturing */
+			s->id = -1;
+		else
+			cx18_stop_v4l2_encode_stream(s, gop_end);
+	}
+	if (!gop_end) {
+		clear_bit(CX18_F_S_APPL_IO, &s->s_flags);
+		clear_bit(CX18_F_S_STREAMOFF, &s->s_flags);
+		cx18_release_stream(s);
+	}
+}
+
+int cx18_v4l2_close(struct file *filp)
+{
+	struct v4l2_fh *fh = filp->private_data;
+	struct cx18_open_id *id = fh2id(fh);
+	struct cx18 *cx = id->cx;
+	struct cx18_stream *s = &cx->streams[id->type];
+
+	CX18_DEBUG_IOCTL("close() of %s\n", s->name);
+
+	mutex_lock(&cx->serialize_lock);
+	/* Stop radio */
+	if (id->type == CX18_ENC_STREAM_TYPE_RAD &&
+			v4l2_fh_is_singular_file(filp)) {
+		/* Closing radio device, return to TV mode */
+		cx18_mute(cx);
+		/* 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_all(cx, core, 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) {
+			/* Undo video mute */
+			cx18_vapi(cx, CX18_CPU_SET_VIDEO_MUTE, 2, s->handle,
+			    (v4l2_ctrl_g_ctrl(cx->cxhdl.video_mute) |
+			    (v4l2_ctrl_g_ctrl(cx->cxhdl.video_mute_yuv) << 8)));
+		}
+		/* Done! Unmute and continue. */
+		cx18_unmute(cx);
+	}
+
+	v4l2_fh_del(fh);
+	v4l2_fh_exit(fh);
+
+	/* 'Unclaim' this stream */
+	if (s->id == id->open_id)
+		cx18_stop_capture(id, 0);
+	kfree(id);
+	mutex_unlock(&cx->serialize_lock);
+	return 0;
+}
+
+static int cx18_serialized_open(struct cx18_stream *s, struct file *filp)
+{
+	struct cx18 *cx = s->cx;
+	struct cx18_open_id *item;
+
+	CX18_DEBUG_FILE("open %s\n", s->name);
+
+	/* Allocate memory */
+	item = kzalloc(sizeof(struct cx18_open_id), GFP_KERNEL);
+	if (NULL == item) {
+		CX18_DEBUG_WARN("nomem on v4l2 open\n");
+		return -ENOMEM;
+	}
+	v4l2_fh_init(&item->fh, s->video_dev);
+
+	item->cx = cx;
+	item->type = s->type;
+
+	item->open_id = cx->open_id++;
+	filp->private_data = &item->fh;
+	v4l2_fh_add(&item->fh);
+
+	if (item->type == CX18_ENC_STREAM_TYPE_RAD &&
+			v4l2_fh_is_singular_file(filp)) {
+		if (!test_bit(CX18_F_I_RADIO_USER, &cx->i_flags)) {
+			if (atomic_read(&cx->ana_capturing) > 0) {
+				/* switching to radio while capture is
+				   in progress is not polite */
+				v4l2_fh_del(&item->fh);
+				v4l2_fh_exit(&item->fh);
+				kfree(item);
+				return -EBUSY;
+			}
+		}
+
+		/* Mark that the radio is being used. */
+		set_bit(CX18_F_I_RADIO_USER, &cx->i_flags);
+		/* We have the radio */
+		cx18_mute(cx);
+		/* Switch tuner to radio */
+		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. */
+		cx18_unmute(cx);
+	}
+	return 0;
+}
+
+int cx18_v4l2_open(struct file *filp)
+{
+	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 %s\n",
+			 video_device_node_name(video_dev));
+		mutex_unlock(&cx->serialize_lock);
+		return -ENXIO;
+	}
+	res = cx18_serialized_open(s, filp);
+	mutex_unlock(&cx->serialize_lock);
+	return res;
+}
+
+void cx18_mute(struct cx18 *cx)
+{
+	u32 h;
+	if (atomic_read(&cx->ana_capturing)) {
+		h = cx18_find_handle(cx);
+		if (h != CX18_INVALID_TASK_HANDLE)
+			cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2, h, 1);
+		else
+			CX18_ERR("Can't find valid task handle for mute\n");
+	}
+	CX18_DEBUG_INFO("Mute\n");
+}
+
+void cx18_unmute(struct cx18 *cx)
+{
+	u32 h;
+	if (atomic_read(&cx->ana_capturing)) {
+		h = cx18_find_handle(cx);
+		if (h != CX18_INVALID_TASK_HANDLE) {
+			cx18_msleep_timeout(100, 0);
+			cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 2, h, 12);
+			cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2, h, 0);
+		} else
+			CX18_ERR("Can't find valid task handle for unmute\n");
+	}
+	CX18_DEBUG_INFO("Unmute\n");
+}
diff --git a/drivers/media/pci/cx18/cx18-fileops.h b/drivers/media/pci/cx18/cx18-fileops.h
new file mode 100644
index 0000000..b9e5110
--- /dev/null
+++ b/drivers/media/pci/cx18/cx18-fileops.h
@@ -0,0 +1,41 @@
+/*
+ *  cx18 file operation functions
+ *
+ *  Derived from ivtv-fileops.h
+ *
+ *  Copyright (C) 2007  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., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307  USA
+ */
+
+/* Testing/Debugging */
+int cx18_v4l2_open(struct file *filp);
+ssize_t cx18_v4l2_read(struct file *filp, char __user *buf, size_t count,
+		      loff_t *pos);
+ssize_t cx18_v4l2_write(struct file *filp, const char __user *buf, size_t count,
+		       loff_t *pos);
+int cx18_v4l2_close(struct file *filp);
+unsigned int cx18_v4l2_enc_poll(struct file *filp, poll_table *wait);
+int cx18_start_capture(struct cx18_open_id *id);
+void cx18_stop_capture(struct cx18_open_id *id, int gop_end);
+void cx18_mute(struct cx18 *cx);
+void cx18_unmute(struct cx18 *cx);
+int cx18_v4l2_mmap(struct file *file, struct vm_area_struct *vma);
+void cx18_vb_timeout(unsigned long data);
+
+/* Shared with cx18-alsa module */
+int cx18_claim_stream(struct cx18_open_id *id, int type);
+void cx18_release_stream(struct cx18_stream *s);
diff --git a/drivers/media/pci/cx18/cx18-firmware.c b/drivers/media/pci/cx18/cx18-firmware.c
new file mode 100644
index 0000000..a1c1cec
--- /dev/null
+++ b/drivers/media/pci/cx18/cx18-firmware.c
@@ -0,0 +1,459 @@
+/*
+ *  cx18 firmware functions
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.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 program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public 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 "cx18-driver.h"
+#include "cx18-io.h"
+#include "cx18-scb.h"
+#include "cx18-irq.h"
+#include "cx18-firmware.h"
+#include "cx18-cards.h"
+#include <linux/firmware.h>
+
+#define CX18_PROC_SOFT_RESET 		0xc70010
+#define CX18_DDR_SOFT_RESET          	0xc70014
+#define CX18_CLOCK_SELECT1           	0xc71000
+#define CX18_CLOCK_SELECT2           	0xc71004
+#define CX18_HALF_CLOCK_SELECT1      	0xc71008
+#define CX18_HALF_CLOCK_SELECT2      	0xc7100C
+#define CX18_CLOCK_POLARITY1         	0xc71010
+#define CX18_CLOCK_POLARITY2         	0xc71014
+#define CX18_ADD_DELAY_ENABLE1       	0xc71018
+#define CX18_ADD_DELAY_ENABLE2       	0xc7101C
+#define CX18_CLOCK_ENABLE1           	0xc71020
+#define CX18_CLOCK_ENABLE2           	0xc71024
+
+#define CX18_REG_BUS_TIMEOUT_EN      	0xc72024
+
+#define CX18_FAST_CLOCK_PLL_INT      	0xc78000
+#define CX18_FAST_CLOCK_PLL_FRAC     	0xc78004
+#define CX18_FAST_CLOCK_PLL_POST     	0xc78008
+#define CX18_FAST_CLOCK_PLL_PRESCALE 	0xc7800C
+#define CX18_FAST_CLOCK_PLL_ADJUST_BANDWIDTH 0xc78010
+
+#define CX18_SLOW_CLOCK_PLL_INT      	0xc78014
+#define CX18_SLOW_CLOCK_PLL_FRAC     	0xc78018
+#define CX18_SLOW_CLOCK_PLL_POST     	0xc7801C
+#define CX18_MPEG_CLOCK_PLL_INT		0xc78040
+#define CX18_MPEG_CLOCK_PLL_FRAC	0xc78044
+#define CX18_MPEG_CLOCK_PLL_POST	0xc78048
+#define CX18_PLL_POWER_DOWN          	0xc78088
+#define CX18_SW1_INT_STATUS             0xc73104
+#define CX18_SW1_INT_ENABLE_PCI         0xc7311C
+#define CX18_SW2_INT_SET                0xc73140
+#define CX18_SW2_INT_STATUS             0xc73144
+#define CX18_ADEC_CONTROL            	0xc78120
+
+#define CX18_DDR_REQUEST_ENABLE      	0xc80000
+#define CX18_DDR_CHIP_CONFIG         	0xc80004
+#define CX18_DDR_REFRESH            	0xc80008
+#define CX18_DDR_TIMING1             	0xc8000C
+#define CX18_DDR_TIMING2             	0xc80010
+#define CX18_DDR_POWER_REG		0xc8001C
+
+#define CX18_DDR_TUNE_LANE           	0xc80048
+#define CX18_DDR_INITIAL_EMRS        	0xc80054
+#define CX18_DDR_MB_PER_ROW_7        	0xc8009C
+#define CX18_DDR_BASE_63_ADDR        	0xc804FC
+
+#define CX18_WMB_CLIENT02            	0xc90108
+#define CX18_WMB_CLIENT05            	0xc90114
+#define CX18_WMB_CLIENT06            	0xc90118
+#define CX18_WMB_CLIENT07            	0xc9011C
+#define CX18_WMB_CLIENT08            	0xc90120
+#define CX18_WMB_CLIENT09            	0xc90124
+#define CX18_WMB_CLIENT10            	0xc90128
+#define CX18_WMB_CLIENT11            	0xc9012C
+#define CX18_WMB_CLIENT12            	0xc90130
+#define CX18_WMB_CLIENT13            	0xc90134
+#define CX18_WMB_CLIENT14            	0xc90138
+
+#define CX18_DSP0_INTERRUPT_MASK     	0xd0004C
+
+#define APU_ROM_SYNC1 0x6D676553 /* "mgeS" */
+#define APU_ROM_SYNC2 0x72646548 /* "rdeH" */
+
+struct cx18_apu_rom_seghdr {
+	u32 sync1;
+	u32 sync2;
+	u32 addr;
+	u32 size;
+};
+
+static int load_cpu_fw_direct(const char *fn, u8 __iomem *mem, struct cx18 *cx)
+{
+	const struct firmware *fw = NULL;
+	int i, j;
+	unsigned size;
+	u32 __iomem *dst = (u32 __iomem *)mem;
+	const u32 *src;
+
+	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;
+	}
+
+	src = (const u32 *)fw->data;
+
+	for (i = 0; i < fw->size; i += 4096) {
+		cx18_setup_page(cx, i);
+		for (j = i; j < fw->size && j < i + 4096; j += 4) {
+			/* no need for endianness conversion on the ppc */
+			cx18_raw_writel(cx, *src, dst);
+			if (cx18_raw_readl(cx, dst) != *src) {
+				CX18_ERR("Mismatch at offset %x\n", i);
+				release_firmware(fw);
+				cx18_setup_page(cx, 0);
+				return -EIO;
+			}
+			dst++;
+			src++;
+		}
+	}
+	if (!test_bit(CX18_F_I_LOADED_FW, &cx->i_flags))
+		CX18_INFO("loaded %s firmware (%zd bytes)\n", fn, fw->size);
+	size = fw->size;
+	release_firmware(fw);
+	cx18_setup_page(cx, SCB_OFFSET);
+	return size;
+}
+
+static int load_apu_fw_direct(const char *fn, u8 __iomem *dst, struct cx18 *cx,
+				u32 *entry_addr)
+{
+	const struct firmware *fw = NULL;
+	int i, j;
+	unsigned size;
+	const u32 *src;
+	struct cx18_apu_rom_seghdr seghdr;
+	const u8 *vers;
+	u32 offset = 0;
+	u32 apu_version = 0;
+	int sz;
+
+	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);
+		return -ENOMEM;
+	}
+
+	*entry_addr = 0;
+	src = (const u32 *)fw->data;
+	vers = fw->data + sizeof(seghdr);
+	sz = fw->size;
+
+	apu_version = (vers[0] << 24) | (vers[4] << 16) | vers[32];
+	while (offset + sizeof(seghdr) < fw->size) {
+		const u32 *shptr = src + offset / 4;
+
+		seghdr.sync1 = le32_to_cpu(shptr[0]);
+		seghdr.sync2 = le32_to_cpu(shptr[1]);
+		seghdr.addr = le32_to_cpu(shptr[2]);
+		seghdr.size = le32_to_cpu(shptr[3]);
+
+		offset += sizeof(seghdr);
+		if (seghdr.sync1 != APU_ROM_SYNC1 ||
+		    seghdr.sync2 != APU_ROM_SYNC2) {
+			offset += seghdr.size;
+			continue;
+		}
+		CX18_DEBUG_INFO("load segment %x-%x\n", seghdr.addr,
+				seghdr.addr + seghdr.size - 1);
+		if (*entry_addr == 0)
+			*entry_addr = seghdr.addr;
+		if (offset + seghdr.size > sz)
+			break;
+		for (i = 0; i < seghdr.size; i += 4096) {
+			cx18_setup_page(cx, seghdr.addr + i);
+			for (j = i; j < seghdr.size && j < i + 4096; j += 4) {
+				/* no need for endianness conversion on the ppc */
+				cx18_raw_writel(cx, src[(offset + j) / 4],
+						dst + seghdr.addr + j);
+				if (cx18_raw_readl(cx, dst + seghdr.addr + j)
+				    != src[(offset + j) / 4]) {
+					CX18_ERR("Mismatch at offset %x\n",
+						 offset + j);
+					release_firmware(fw);
+					cx18_setup_page(cx, 0);
+					return -EIO;
+				}
+			}
+		}
+		offset += seghdr.size;
+	}
+	if (!test_bit(CX18_F_I_LOADED_FW, &cx->i_flags))
+		CX18_INFO("loaded %s firmware V%08x (%zd bytes)\n",
+				fn, apu_version, fw->size);
+	size = fw->size;
+	release_firmware(fw);
+	cx18_setup_page(cx, 0);
+	return size;
+}
+
+void cx18_halt_firmware(struct cx18 *cx)
+{
+	CX18_DEBUG_INFO("Preparing for firmware halt.\n");
+	cx18_write_reg_expect(cx, 0x000F000F, CX18_PROC_SOFT_RESET,
+				  0x0000000F, 0x000F000F);
+	cx18_write_reg_expect(cx, 0x00020002, CX18_ADEC_CONTROL,
+				  0x00000002, 0x00020002);
+}
+
+void cx18_init_power(struct cx18 *cx, int lowpwr)
+{
+	/* power-down Spare and AOM PLLs */
+	/* power-up fast, slow and mpeg PLLs */
+	cx18_write_reg(cx, 0x00000008, CX18_PLL_POWER_DOWN);
+
+	/* ADEC out of sleep */
+	cx18_write_reg_expect(cx, 0x00020000, CX18_ADEC_CONTROL,
+				  0x00000000, 0x00020002);
+
+	/*
+	 * The PLL parameters are based on the external crystal frequency that
+	 * would ideally be:
+	 *
+	 * NTSC Color subcarrier freq * 8 =
+	 * 	4.5 MHz/286 * 455/2 * 8 = 28.63636363... MHz
+	 *
+	 * The accidents of history and rationale that explain from where this
+	 * combination of magic numbers originate can be found in:
+	 *
+	 * [1] Abrahams, I. C., "Choice of Chrominance Subcarrier Frequency in
+	 * the NTSC Standards", Proceedings of the I-R-E, January 1954, pp 79-80
+	 *
+	 * [2] Abrahams, I. C., "The 'Frequency Interleaving' Principle in the
+	 * NTSC Standards", Proceedings of the I-R-E, January 1954, pp 81-83
+	 *
+	 * As Mike Bradley has rightly pointed out, it's not the exact crystal
+	 * frequency that matters, only that all parts of the driver and
+	 * firmware are using the same value (close to the ideal value).
+	 *
+	 * Since I have a strong suspicion that, if the firmware ever assumes a
+	 * crystal value at all, it will assume 28.636360 MHz, the crystal
+	 * freq used in calculations in this driver will be:
+	 *
+	 *	xtal_freq = 28.636360 MHz
+	 *
+	 * an error of less than 0.13 ppm which is way, way better than any off
+	 * the shelf crystal will have for accuracy anyway.
+	 *
+	 * Below I aim to run the PLLs' VCOs near 400 MHz to minimze errors.
+	 *
+	 * Many thanks to Jeff Campbell and Mike Bradley for their extensive
+	 * investigation, experimentation, testing, and suggested solutions of
+	 * of audio/video sync problems with SVideo and CVBS captures.
+	 */
+
+	/* the fast clock is at 200/245 MHz */
+	/* 1 * xtal_freq * 0x0d.f7df9b8 / 2 = 200 MHz: 400 MHz pre post-divide*/
+	/* 1 * xtal_freq * 0x11.1c71eb8 / 2 = 245 MHz: 490 MHz pre post-divide*/
+	cx18_write_reg(cx, lowpwr ? 0xD : 0x11, CX18_FAST_CLOCK_PLL_INT);
+	cx18_write_reg(cx, lowpwr ? 0x1EFBF37 : 0x038E3D7,
+						CX18_FAST_CLOCK_PLL_FRAC);
+
+	cx18_write_reg(cx, 2, CX18_FAST_CLOCK_PLL_POST);
+	cx18_write_reg(cx, 1, CX18_FAST_CLOCK_PLL_PRESCALE);
+	cx18_write_reg(cx, 4, CX18_FAST_CLOCK_PLL_ADJUST_BANDWIDTH);
+
+	/* set slow clock to 125/120 MHz */
+	/* xtal_freq * 0x0d.1861a20 / 3 = 125 MHz: 375 MHz before post-divide */
+	/* xtal_freq * 0x0c.92493f8 / 3 = 120 MHz: 360 MHz before post-divide */
+	cx18_write_reg(cx, lowpwr ? 0xD : 0xC, CX18_SLOW_CLOCK_PLL_INT);
+	cx18_write_reg(cx, lowpwr ? 0x30C344 : 0x124927F,
+						CX18_SLOW_CLOCK_PLL_FRAC);
+	cx18_write_reg(cx, 3, CX18_SLOW_CLOCK_PLL_POST);
+
+	/* mpeg clock pll 54MHz */
+	/* xtal_freq * 0xf.15f17f0 / 8 = 54 MHz: 432 MHz before post-divide */
+	cx18_write_reg(cx, 0xF, CX18_MPEG_CLOCK_PLL_INT);
+	cx18_write_reg(cx, 0x2BE2FE, CX18_MPEG_CLOCK_PLL_FRAC);
+	cx18_write_reg(cx, 8, CX18_MPEG_CLOCK_PLL_POST);
+
+	/* Defaults */
+	/* APU = SC or SC/2 = 125/62.5 */
+	/* EPU = SC = 125 */
+	/* DDR = FC = 180 */
+	/* ENC = SC = 125 */
+	/* AI1 = SC = 125 */
+	/* VIM2 = disabled */
+	/* PCI = FC/2 = 90 */
+	/* AI2 = disabled */
+	/* DEMUX = disabled */
+	/* AO = SC/2 = 62.5 */
+	/* SER = 54MHz */
+	/* VFC = disabled */
+	/* USB = disabled */
+
+	if (lowpwr) {
+		cx18_write_reg_expect(cx, 0xFFFF0020, CX18_CLOCK_SELECT1,
+					  0x00000020, 0xFFFFFFFF);
+		cx18_write_reg_expect(cx, 0xFFFF0004, CX18_CLOCK_SELECT2,
+					  0x00000004, 0xFFFFFFFF);
+	} else {
+		/* This doesn't explicitly set every clock select */
+		cx18_write_reg_expect(cx, 0x00060004, CX18_CLOCK_SELECT1,
+					  0x00000004, 0x00060006);
+		cx18_write_reg_expect(cx, 0x00060006, CX18_CLOCK_SELECT2,
+					  0x00000006, 0x00060006);
+	}
+
+	cx18_write_reg_expect(cx, 0xFFFF0002, CX18_HALF_CLOCK_SELECT1,
+				  0x00000002, 0xFFFFFFFF);
+	cx18_write_reg_expect(cx, 0xFFFF0104, CX18_HALF_CLOCK_SELECT2,
+				  0x00000104, 0xFFFFFFFF);
+	cx18_write_reg_expect(cx, 0xFFFF9026, CX18_CLOCK_ENABLE1,
+				  0x00009026, 0xFFFFFFFF);
+	cx18_write_reg_expect(cx, 0xFFFF3105, CX18_CLOCK_ENABLE2,
+				  0x00003105, 0xFFFFFFFF);
+}
+
+void cx18_init_memory(struct cx18 *cx)
+{
+	cx18_msleep_timeout(10, 0);
+	cx18_write_reg_expect(cx, 0x00010000, CX18_DDR_SOFT_RESET,
+				  0x00000000, 0x00010001);
+	cx18_msleep_timeout(10, 0);
+
+	cx18_write_reg(cx, cx->card->ddr.chip_config, CX18_DDR_CHIP_CONFIG);
+
+	cx18_msleep_timeout(10, 0);
+
+	cx18_write_reg(cx, cx->card->ddr.refresh, CX18_DDR_REFRESH);
+	cx18_write_reg(cx, cx->card->ddr.timing1, CX18_DDR_TIMING1);
+	cx18_write_reg(cx, cx->card->ddr.timing2, CX18_DDR_TIMING2);
+
+	cx18_msleep_timeout(10, 0);
+
+	/* Initialize DQS pad time */
+	cx18_write_reg(cx, cx->card->ddr.tune_lane, CX18_DDR_TUNE_LANE);
+	cx18_write_reg(cx, cx->card->ddr.initial_emrs, CX18_DDR_INITIAL_EMRS);
+
+	cx18_msleep_timeout(10, 0);
+
+	cx18_write_reg_expect(cx, 0x00020000, CX18_DDR_SOFT_RESET,
+				  0x00000000, 0x00020002);
+	cx18_msleep_timeout(10, 0);
+
+	/* use power-down mode when idle */
+	cx18_write_reg(cx, 0x00000010, CX18_DDR_POWER_REG);
+
+	cx18_write_reg_expect(cx, 0x00010001, CX18_REG_BUS_TIMEOUT_EN,
+				  0x00000001, 0x00010001);
+
+	cx18_write_reg(cx, 0x48, CX18_DDR_MB_PER_ROW_7);
+	cx18_write_reg(cx, 0xE0000, CX18_DDR_BASE_63_ADDR);
+
+	cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT02);  /* AO */
+	cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT09);  /* AI2 */
+	cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT05);  /* VIM1 */
+	cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT06);  /* AI1 */
+	cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT07);  /* 3D comb */
+	cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT10);  /* ME */
+	cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT12);  /* ENC */
+	cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT13);  /* PK */
+	cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT11);  /* RC */
+	cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT14);  /* AVO */
+}
+
+#define CX18_CPU_FIRMWARE "v4l-cx23418-cpu.fw"
+#define CX18_APU_FIRMWARE "v4l-cx23418-apu.fw"
+
+int cx18_firmware_init(struct cx18 *cx)
+{
+	u32 fw_entry_addr;
+	int sz, retries;
+	u32 api_args[MAX_MB_ARGUMENTS];
+
+	/* Allow chip to control CLKRUN */
+	cx18_write_reg(cx, 0x5, CX18_DSP0_INTERRUPT_MASK);
+
+	/* Stop the firmware */
+	cx18_write_reg_expect(cx, 0x000F000F, CX18_PROC_SOFT_RESET,
+				  0x0000000F, 0x000F000F);
+
+	cx18_msleep_timeout(1, 0);
+
+	/* If the CPU is still running */
+	if ((cx18_read_reg(cx, CX18_PROC_SOFT_RESET) & 8) == 0) {
+		CX18_ERR("%s: couldn't stop CPU to load firmware\n", __func__);
+		return -EIO;
+	}
+
+	cx18_sw1_irq_enable(cx, IRQ_CPU_TO_EPU | IRQ_APU_TO_EPU);
+	cx18_sw2_irq_enable(cx, IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK);
+
+	sz = load_cpu_fw_direct(CX18_CPU_FIRMWARE, cx->enc_mem, cx);
+	if (sz <= 0)
+		return sz;
+
+	/* The SCB & IPC area *must* be correct before starting the firmwares */
+	cx18_init_scb(cx);
+
+	fw_entry_addr = 0;
+	sz = load_apu_fw_direct(CX18_APU_FIRMWARE, cx->enc_mem, cx,
+				&fw_entry_addr);
+	if (sz <= 0)
+		return sz;
+
+	/* Start the CPU. The CPU will take care of the APU for us. */
+	cx18_write_reg_expect(cx, 0x00080000, CX18_PROC_SOFT_RESET,
+				  0x00000000, 0x00080008);
+
+	/* Wait up to 500 ms for the APU to come out of reset */
+	for (retries = 0;
+	     retries < 50 && (cx18_read_reg(cx, CX18_PROC_SOFT_RESET) & 1) == 1;
+	     retries++)
+		cx18_msleep_timeout(10, 0);
+
+	cx18_msleep_timeout(200, 0);
+
+	if (retries == 50 &&
+	    (cx18_read_reg(cx, CX18_PROC_SOFT_RESET) & 1) == 1) {
+		CX18_ERR("Could not start the CPU\n");
+		return -EIO;
+	}
+
+	/*
+	 * The CPU had once before set up to receive an interrupt for it's
+	 * outgoing IRQ_CPU_TO_EPU_ACK to us.  If it ever does this, we get an
+	 * interrupt when it sends us an ack, but by the time we process it,
+	 * that flag in the SW2 status register has been cleared by the CPU
+	 * firmware.  We'll prevent that not so useful condition from happening
+	 * by clearing the CPU's interrupt enables for Ack IRQ's we want to
+	 * process.
+	 */
+	cx18_sw2_irq_disable_cpu(cx, IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK);
+
+	/* Try a benign command to see if the CPU is alive and well */
+	sz = cx18_vapi_result(cx, api_args, CX18_CPU_DEBUG_PEEK32, 1, 0);
+	if (sz < 0)
+		return sz;
+
+	/* initialize GPIO */
+	cx18_write_reg_expect(cx, 0x14001400, 0xc78110, 0x00001400, 0x14001400);
+	return 0;
+}
+
+MODULE_FIRMWARE(CX18_CPU_FIRMWARE);
+MODULE_FIRMWARE(CX18_APU_FIRMWARE);
diff --git a/drivers/media/pci/cx18/cx18-firmware.h b/drivers/media/pci/cx18/cx18-firmware.h
new file mode 100644
index 0000000..38d4c05
--- /dev/null
+++ b/drivers/media/pci/cx18/cx18-firmware.h
@@ -0,0 +1,25 @@
+/*
+ *  cx18 firmware functions
+ *
+ *  Copyright (C) 2007  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., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307  USA
+ */
+
+int cx18_firmware_init(struct cx18 *cx);
+void cx18_halt_firmware(struct cx18 *cx);
+void cx18_init_memory(struct cx18 *cx);
+void cx18_init_power(struct cx18 *cx, int lowpwr);
diff --git a/drivers/media/pci/cx18/cx18-gpio.c b/drivers/media/pci/cx18/cx18-gpio.c
new file mode 100644
index 0000000..5374aeb
--- /dev/null
+++ b/drivers/media/pci/cx18/cx18-gpio.c
@@ -0,0 +1,347 @@
+/*
+ *  cx18 gpio functions
+ *
+ *  Derived from ivtv-gpio.c
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.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 program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public 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 "cx18-driver.h"
+#include "cx18-io.h"
+#include "cx18-cards.h"
+#include "cx18-gpio.h"
+#include "tuner-xc2028.h"
+
+/********************* GPIO stuffs *********************/
+
+/* GPIO registers */
+#define CX18_REG_GPIO_IN     0xc72010
+#define CX18_REG_GPIO_OUT1   0xc78100
+#define CX18_REG_GPIO_DIR1   0xc78108
+#define CX18_REG_GPIO_OUT2   0xc78104
+#define CX18_REG_GPIO_DIR2   0xc7810c
+
+/*
+ * HVR-1600 GPIO pins, courtesy of Hauppauge:
+ *
+ * gpio0: zilog ir process reset pin
+ * gpio1: zilog programming pin (you should never use this)
+ * gpio12: cx24227 reset pin
+ * gpio13: cs5345 reset pin
+*/
+
+/*
+ * File scope utility functions
+ */
+static void gpio_write(struct cx18 *cx)
+{
+	u32 dir_lo = cx->gpio_dir & 0xffff;
+	u32 val_lo = cx->gpio_val & 0xffff;
+	u32 dir_hi = cx->gpio_dir >> 16;
+	u32 val_hi = cx->gpio_val >> 16;
+
+	cx18_write_reg_expect(cx, dir_lo << 16,
+					CX18_REG_GPIO_DIR1, ~dir_lo, dir_lo);
+	cx18_write_reg_expect(cx, (dir_lo << 16) | val_lo,
+					CX18_REG_GPIO_OUT1, val_lo, dir_lo);
+	cx18_write_reg_expect(cx, dir_hi << 16,
+					CX18_REG_GPIO_DIR2, ~dir_hi, dir_hi);
+	cx18_write_reg_expect(cx, (dir_hi << 16) | val_hi,
+					CX18_REG_GPIO_OUT2, val_hi, dir_hi);
+}
+
+static void gpio_update(struct cx18 *cx, u32 mask, u32 data)
+{
+	if (mask == 0)
+		return;
+
+	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 */
+	gpio_update(cx, mask, ~active_lo);
+	schedule_timeout_uninterruptible(msecs_to_jiffies(assert_msecs));
+
+	/* Deassert */
+	gpio_update(cx, mask, ~active_hi);
+	schedule_timeout_uninterruptible(msecs_to_jiffies(recovery_msecs));
+}
+
+/*
+ * GPIO Multiplexer - logical device
+ */
+static int gpiomux_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 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,
+				   u32 input, u32 output, u32 config)
+{
+	struct cx18 *cx = v4l2_get_subdevdata(sd);
+	u32 data;
+
+	switch (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,
+	.s_std = gpiomux_s_std,
+};
+
+static const struct v4l2_subdev_tuner_ops gpiomux_tuner_ops = {
+	.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;
+	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;
+}
+
+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);
+	cx->gpio_dir = cx->card->gpio_init.direction;
+	cx->gpio_val = cx->card->gpio_init.initial_value;
+
+	if (cx->card->tuners[0].tuner == TUNER_XC2028) {
+		cx->gpio_dir |= 1 << cx->card->xceive_pin;
+		cx->gpio_val |= 1 << cx->card->xceive_pin;
+	}
+
+	if (cx->gpio_dir == 0) {
+		mutex_unlock(&cx->gpio_lock);
+		return;
+	}
+
+	CX18_DEBUG_INFO("GPIO initial dir: %08x/%08x out: %08x/%08x\n",
+			cx18_read_reg(cx, CX18_REG_GPIO_DIR1),
+			cx18_read_reg(cx, CX18_REG_GPIO_DIR2),
+			cx18_read_reg(cx, CX18_REG_GPIO_OUT1),
+			cx18_read_reg(cx, CX18_REG_GPIO_OUT2));
+
+	gpio_write(cx);
+	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)
+{
+	struct i2c_algo_bit_data *algo = dev;
+	struct cx18_i2c_algo_callback_data *cb_data = algo->data;
+	struct cx18 *cx = cb_data->cx;
+
+	if (cmd != XC2028_TUNER_RESET ||
+	    cx->card->tuners[0].tuner != TUNER_XC2028)
+		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/pci/cx18/cx18-gpio.h b/drivers/media/pci/cx18/cx18-gpio.h
new file mode 100644
index 0000000..4aea2ef
--- /dev/null
+++ b/drivers/media/pci/cx18/cx18-gpio.h
@@ -0,0 +1,34 @@
+/*
+ *  cx18 gpio functions
+ *
+ *  Derived from ivtv-gpio.h
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.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 program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+void cx18_gpio_init(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);
diff --git a/drivers/media/pci/cx18/cx18-i2c.c b/drivers/media/pci/cx18/cx18-i2c.c
new file mode 100644
index 0000000..51609d5
--- /dev/null
+++ b/drivers/media/pci/cx18/cx18-i2c.c
@@ -0,0 +1,330 @@
+/*
+ *  cx18 I2C functions
+ *
+ *  Derived from ivtv-i2c.c
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.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 program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public 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 "cx18-driver.h"
+#include "cx18-io.h"
+#include "cx18-cards.h"
+#include "cx18-gpio.h"
+#include "cx18-i2c.h"
+#include "cx18-irq.h"
+
+#define CX18_REG_I2C_1_WR   0xf15000
+#define CX18_REG_I2C_1_RD   0xf15008
+#define CX18_REG_I2C_2_WR   0xf25100
+#define CX18_REG_I2C_2_RD   0xf25108
+
+#define SETSCL_BIT      0x0001
+#define SETSDL_BIT      0x0002
+#define GETSCL_BIT      0x0004
+#define GETSDL_BIT      0x0008
+
+#define CX18_CS5345_I2C_ADDR		0x4c
+#define CX18_Z8F0811_IR_TX_I2C_ADDR	0x70
+#define CX18_Z8F0811_IR_RX_I2C_ADDR	0x71
+
+/* This array should match the CX18_HW_ defines */
+static const u8 hw_addrs[] = {
+	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 */
+	CX18_Z8F0811_IR_TX_I2C_ADDR,	/* CX18_HW_Z8F0811_IR_TX_HAUP */
+	CX18_Z8F0811_IR_RX_I2C_ADDR,	/* CX18_HW_Z8F0811_IR_RX_HAUP */
+};
+
+/* This array should match the CX18_HW_ defines */
+/* This might well become a card-specific array */
+static const u8 hw_bus[] = {
+	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 */
+	0,	/* CX18_HW_Z8F0811_IR_TX_HAUP */
+	0,	/* CX18_HW_Z8F0811_IR_RX_HAUP */
+};
+
+/* This array should match the CX18_HW_ defines */
+static const char * const hw_devicenames[] = {
+	"tuner",
+	"tveeprom",
+	"cs5345",
+	"cx23418_DTV",
+	"cx23418_AV",
+	"gpio_mux",
+	"gpio_reset_ctrl",
+	"ir_tx_z8f0811_haup",
+	"ir_rx_z8f0811_haup",
+};
+
+static int cx18_i2c_new_ir(struct cx18 *cx, struct i2c_adapter *adap, u32 hw,
+			   const char *type, u8 addr)
+{
+	struct i2c_board_info info;
+	struct IR_i2c_init_data *init_data = &cx->ir_i2c_init_data;
+	unsigned short addr_list[2] = { addr, I2C_CLIENT_END };
+
+	memset(&info, 0, sizeof(struct i2c_board_info));
+	strlcpy(info.type, type, I2C_NAME_SIZE);
+
+	/* Our default information for ir-kbd-i2c.c to use */
+	switch (hw) {
+	case CX18_HW_Z8F0811_IR_RX_HAUP:
+		init_data->ir_codes = RC_MAP_HAUPPAUGE;
+		init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR;
+		init_data->type = RC_TYPE_RC5;
+		init_data->name = cx->card_name;
+		info.platform_data = init_data;
+		break;
+	}
+
+	return i2c_new_probed_device(adap, &info, addr_list, NULL) == NULL ?
+	       -1 : 0;
+}
+
+int cx18_i2c_register(struct cx18 *cx, unsigned idx)
+{
+	struct v4l2_subdev *sd;
+	int bus = hw_bus[idx];
+	struct i2c_adapter *adap = &cx->i2c_adap[bus];
+	const char *type = hw_devicenames[idx];
+	u32 hw = 1 << idx;
+
+	if (idx >= ARRAY_SIZE(hw_addrs))
+		return -1;
+
+	if (hw == CX18_HW_TUNER) {
+		/* special tuner group handling */
+		sd = v4l2_i2c_new_subdev(&cx->v4l2_dev,
+				adap, type, 0, cx->card_i2c->radio);
+		if (sd != NULL)
+			sd->grp_id = hw;
+		sd = v4l2_i2c_new_subdev(&cx->v4l2_dev,
+				adap, type, 0, cx->card_i2c->demod);
+		if (sd != NULL)
+			sd->grp_id = hw;
+		sd = v4l2_i2c_new_subdev(&cx->v4l2_dev,
+				adap, type, 0, cx->card_i2c->tv);
+		if (sd != NULL)
+			sd->grp_id = hw;
+		return sd != NULL ? 0 : -1;
+	}
+
+	if (hw & CX18_HW_IR_ANY)
+		return cx18_i2c_new_ir(cx, adap, hw, type, hw_addrs[idx]);
+
+	/* Is it not an I2C device or one we do not wish to register? */
+	if (!hw_addrs[idx])
+		return -1;
+
+	/* It's an I2C device other than an analog tuner or IR chip */
+	sd = v4l2_i2c_new_subdev(&cx->v4l2_dev, adap, type, hw_addrs[idx],
+				 NULL);
+	if (sd != NULL)
+		sd->grp_id = hw;
+	return sd != NULL ? 0 : -1;
+}
+
+/* Find the first member of the subdev group id in hw */
+struct v4l2_subdev *cx18_find_hw(struct cx18 *cx, u32 hw)
+{
+	struct v4l2_subdev *result = NULL;
+	struct v4l2_subdev *sd;
+
+	spin_lock(&cx->v4l2_dev.lock);
+	v4l2_device_for_each_subdev(sd, &cx->v4l2_dev) {
+		if (sd->grp_id == hw) {
+			result = sd;
+			break;
+		}
+	}
+	spin_unlock(&cx->v4l2_dev.lock);
+	return result;
+}
+
+static void cx18_setscl(void *data, int state)
+{
+	struct cx18 *cx = ((struct cx18_i2c_algo_callback_data *)data)->cx;
+	int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index;
+	u32 addr = bus_index ? CX18_REG_I2C_2_WR : CX18_REG_I2C_1_WR;
+	u32 r = cx18_read_reg(cx, addr);
+
+	if (state)
+		cx18_write_reg(cx, r | SETSCL_BIT, addr);
+	else
+		cx18_write_reg(cx, r & ~SETSCL_BIT, addr);
+}
+
+static void cx18_setsda(void *data, int state)
+{
+	struct cx18 *cx = ((struct cx18_i2c_algo_callback_data *)data)->cx;
+	int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index;
+	u32 addr = bus_index ? CX18_REG_I2C_2_WR : CX18_REG_I2C_1_WR;
+	u32 r = cx18_read_reg(cx, addr);
+
+	if (state)
+		cx18_write_reg(cx, r | SETSDL_BIT, addr);
+	else
+		cx18_write_reg(cx, r & ~SETSDL_BIT, addr);
+}
+
+static int cx18_getscl(void *data)
+{
+	struct cx18 *cx = ((struct cx18_i2c_algo_callback_data *)data)->cx;
+	int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index;
+	u32 addr = bus_index ? CX18_REG_I2C_2_RD : CX18_REG_I2C_1_RD;
+
+	return cx18_read_reg(cx, addr) & GETSCL_BIT;
+}
+
+static int cx18_getsda(void *data)
+{
+	struct cx18 *cx = ((struct cx18_i2c_algo_callback_data *)data)->cx;
+	int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index;
+	u32 addr = bus_index ? CX18_REG_I2C_2_RD : CX18_REG_I2C_1_RD;
+
+	return cx18_read_reg(cx, addr) & GETSDL_BIT;
+}
+
+/* template for i2c-bit-algo */
+static struct i2c_adapter cx18_i2c_adap_template = {
+	.name = "cx18 i2c driver",
+	.algo = NULL,                   /* set by i2c-algo-bit */
+	.algo_data = NULL,              /* filled from template */
+	.owner = THIS_MODULE,
+};
+
+#define CX18_SCL_PERIOD (10) /* usecs. 10 usec is period for a 100 KHz clock */
+#define CX18_ALGO_BIT_TIMEOUT (2) /* seconds */
+
+static struct i2c_algo_bit_data cx18_i2c_algo_template = {
+	.setsda		= cx18_setsda,
+	.setscl		= cx18_setscl,
+	.getsda		= cx18_getsda,
+	.getscl		= cx18_getscl,
+	.udelay		= CX18_SCL_PERIOD/2,       /* 1/2 clock period in usec*/
+	.timeout	= CX18_ALGO_BIT_TIMEOUT*HZ /* jiffies */
+};
+
+/* init + register i2c adapter */
+int init_cx18_i2c(struct cx18 *cx)
+{
+	int i, err;
+	CX18_DEBUG_I2C("i2c init\n");
+
+	for (i = 0; i < 2; i++) {
+		/* 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->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) {
+		/* Reset/Unreset I2C hardware block */
+		/* Clock select 220MHz */
+		cx18_write_reg_expect(cx, 0x10000000, 0xc71004,
+					  0x00000000, 0x10001000);
+		/* Clock Enable */
+		cx18_write_reg_expect(cx, 0x10001000, 0xc71024,
+					  0x00001000, 0x10001000);
+	}
+	/* courtesy of Steven Toth <stoth@hauppauge.com> */
+	cx18_write_reg_expect(cx, 0x00c00000, 0xc7001c, 0x00000000, 0x00c000c0);
+	mdelay(10);
+	cx18_write_reg_expect(cx, 0x00c000c0, 0xc7001c, 0x000000c0, 0x00c000c0);
+	mdelay(10);
+	cx18_write_reg_expect(cx, 0x00c00000, 0xc7001c, 0x00000000, 0x00c000c0);
+	mdelay(10);
+
+	/* Set to edge-triggered intrs. */
+	cx18_write_reg(cx, 0x00c00000, 0xc730c8);
+	/* Clear any stale intrs */
+	cx18_write_reg_expect(cx, HW2_I2C1_INT|HW2_I2C2_INT, HW2_INT_CLR_STATUS,
+		       ~(HW2_I2C1_INT|HW2_I2C2_INT), HW2_I2C1_INT|HW2_I2C2_INT);
+
+	/* Hw I2C1 Clock Freq ~100kHz */
+	cx18_write_reg(cx, 0x00021c0f & ~4, CX18_REG_I2C_1_WR);
+	cx18_setscl(&cx->i2c_algo_cb_data[0], 1);
+	cx18_setsda(&cx->i2c_algo_cb_data[0], 1);
+
+	/* Hw I2C2 Clock Freq ~100kHz */
+	cx18_write_reg(cx, 0x00021c0f & ~4, CX18_REG_I2C_2_WR);
+	cx18_setscl(&cx->i2c_algo_cb_data[1], 1);
+	cx18_setsda(&cx->i2c_algo_cb_data[1], 1);
+
+	cx18_call_hw(cx, CX18_HW_GPIO_RESET_CTRL,
+		     core, reset, (u32) CX18_GPIO_RESET_I2C);
+
+	err = i2c_bit_add_bus(&cx->i2c_adap[0]);
+	if (err)
+		goto err;
+	err = i2c_bit_add_bus(&cx->i2c_adap[1]);
+	if (err)
+		goto err_del_bus_0;
+	return 0;
+
+ err_del_bus_0:
+	i2c_del_adapter(&cx->i2c_adap[0]);
+ err:
+	return err;
+}
+
+void exit_cx18_i2c(struct cx18 *cx)
+{
+	int i;
+	CX18_DEBUG_I2C("i2c exit\n");
+	cx18_write_reg(cx, cx18_read_reg(cx, CX18_REG_I2C_1_WR) | 4,
+							CX18_REG_I2C_1_WR);
+	cx18_write_reg(cx, cx18_read_reg(cx, CX18_REG_I2C_2_WR) | 4,
+							CX18_REG_I2C_2_WR);
+
+	for (i = 0; i < 2; i++) {
+		i2c_del_adapter(&cx->i2c_adap[i]);
+	}
+}
+
+/*
+   Hauppauge HVR1600 should have:
+   32 cx24227
+   98 unknown
+   a0 eeprom
+   c2 tuner
+   e? zilog ir
+   */
diff --git a/drivers/media/pci/cx18/cx18-i2c.h b/drivers/media/pci/cx18/cx18-i2c.h
new file mode 100644
index 0000000..1180fdc
--- /dev/null
+++ b/drivers/media/pci/cx18/cx18-i2c.h
@@ -0,0 +1,29 @@
+/*
+ *  cx18 I2C functions
+ *
+ *  Derived from ivtv-i2c.h
+ *
+ *  Copyright (C) 2007  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., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307  USA
+ */
+
+int cx18_i2c_register(struct cx18 *cx, unsigned idx);
+struct v4l2_subdev *cx18_find_hw(struct cx18 *cx, u32 hw);
+
+/* init + register i2c adapter */
+int init_cx18_i2c(struct cx18 *cx);
+void exit_cx18_i2c(struct cx18 *cx);
diff --git a/drivers/media/pci/cx18/cx18-io.c b/drivers/media/pci/cx18/cx18-io.c
new file mode 100644
index 0000000..49b9dbd
--- /dev/null
+++ b/drivers/media/pci/cx18/cx18-io.c
@@ -0,0 +1,97 @@
+/*
+ *  cx18 driver PCI memory mapped IO access routines
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.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 program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public 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 "cx18-driver.h"
+#include "cx18-io.h"
+#include "cx18-irq.h"
+
+void cx18_memset_io(struct cx18 *cx, void __iomem *addr, int val, size_t count)
+{
+	u8 __iomem *dst = addr;
+	u16 val2 = val | (val << 8);
+	u32 val4 = val2 | (val2 << 16);
+
+	/* Align writes on the CX23418's addresses */
+	if ((count > 0) && ((unsigned long)dst & 1)) {
+		cx18_writeb(cx, (u8) val, dst);
+		count--;
+		dst++;
+	}
+	if ((count > 1) && ((unsigned long)dst & 2)) {
+		cx18_writew(cx, val2, dst);
+		count -= 2;
+		dst += 2;
+	}
+	while (count > 3) {
+		cx18_writel(cx, val4, dst);
+		count -= 4;
+		dst += 4;
+	}
+	if (count > 1) {
+		cx18_writew(cx, val2, dst);
+		count -= 2;
+		dst += 2;
+	}
+	if (count > 0)
+		cx18_writeb(cx, (u8) val, dst);
+}
+
+void cx18_sw1_irq_enable(struct cx18 *cx, u32 val)
+{
+	cx18_write_reg_expect(cx, val, SW1_INT_STATUS, ~val, val);
+	cx->sw1_irq_mask = cx18_read_reg(cx, SW1_INT_ENABLE_PCI) | val;
+	cx18_write_reg(cx, cx->sw1_irq_mask, SW1_INT_ENABLE_PCI);
+}
+
+void cx18_sw1_irq_disable(struct cx18 *cx, u32 val)
+{
+	cx->sw1_irq_mask = cx18_read_reg(cx, SW1_INT_ENABLE_PCI) & ~val;
+	cx18_write_reg(cx, cx->sw1_irq_mask, SW1_INT_ENABLE_PCI);
+}
+
+void cx18_sw2_irq_enable(struct cx18 *cx, u32 val)
+{
+	cx18_write_reg_expect(cx, val, SW2_INT_STATUS, ~val, val);
+	cx->sw2_irq_mask = cx18_read_reg(cx, SW2_INT_ENABLE_PCI) | val;
+	cx18_write_reg(cx, cx->sw2_irq_mask, SW2_INT_ENABLE_PCI);
+}
+
+void cx18_sw2_irq_disable(struct cx18 *cx, u32 val)
+{
+	cx->sw2_irq_mask = cx18_read_reg(cx, SW2_INT_ENABLE_PCI) & ~val;
+	cx18_write_reg(cx, cx->sw2_irq_mask, SW2_INT_ENABLE_PCI);
+}
+
+void cx18_sw2_irq_disable_cpu(struct cx18 *cx, u32 val)
+{
+	u32 r;
+	r = cx18_read_reg(cx, SW2_INT_ENABLE_CPU);
+	cx18_write_reg(cx, r & ~val, SW2_INT_ENABLE_CPU);
+}
+
+void cx18_setup_page(struct cx18 *cx, u32 addr)
+{
+	u32 val;
+	val = cx18_read_reg(cx, 0xD000F8);
+	val = (val & ~0x1f00) | ((addr >> 17) & 0x1f00);
+	cx18_write_reg(cx, val, 0xD000F8);
+}
diff --git a/drivers/media/pci/cx18/cx18-io.h b/drivers/media/pci/cx18/cx18-io.h
new file mode 100644
index 0000000..18974d8
--- /dev/null
+++ b/drivers/media/pci/cx18/cx18-io.h
@@ -0,0 +1,191 @@
+/*
+ *  cx18 driver PCI memory mapped IO access routines
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.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 program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public 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 CX18_IO_H
+#define CX18_IO_H
+
+#include "cx18-driver.h"
+
+/*
+ * Readback and retry of MMIO access for reliability:
+ * The concept was suggested by Steve Toth <stoth@linuxtv.org>.
+ * The implmentation is the fault of Andy Walls <awalls@md.metrocast.net>.
+ *
+ * *write* functions are implied to retry the mmio unless suffixed with _noretry
+ * *read* functions never retry the mmio (it never helps to do so)
+ */
+
+/* Non byteswapping memory mapped IO */
+static inline u32 cx18_raw_readl(struct cx18 *cx, const void __iomem *addr)
+{
+	return __raw_readl(addr);
+}
+
+static inline
+void cx18_raw_writel_noretry(struct cx18 *cx, u32 val, void __iomem *addr)
+{
+	__raw_writel(val, addr);
+}
+
+static inline void cx18_raw_writel(struct cx18 *cx, u32 val, void __iomem *addr)
+{
+	int i;
+	for (i = 0; i < CX18_MAX_MMIO_WR_RETRIES; i++) {
+		cx18_raw_writel_noretry(cx, val, addr);
+		if (val == cx18_raw_readl(cx, addr))
+			break;
+	}
+}
+
+/* Normal memory mapped IO */
+static inline u32 cx18_readl(struct cx18 *cx, const void __iomem *addr)
+{
+	return readl(addr);
+}
+
+static inline
+void cx18_writel_noretry(struct cx18 *cx, u32 val, void __iomem *addr)
+{
+	writel(val, addr);
+}
+
+static inline void cx18_writel(struct cx18 *cx, u32 val, void __iomem *addr)
+{
+	int i;
+	for (i = 0; i < CX18_MAX_MMIO_WR_RETRIES; i++) {
+		cx18_writel_noretry(cx, val, addr);
+		if (val == cx18_readl(cx, addr))
+			break;
+	}
+}
+
+static inline
+void cx18_writel_expect(struct cx18 *cx, u32 val, void __iomem *addr,
+			u32 eval, u32 mask)
+{
+	int i;
+	u32 r;
+	eval &= mask;
+	for (i = 0; i < CX18_MAX_MMIO_WR_RETRIES; i++) {
+		cx18_writel_noretry(cx, val, addr);
+		r = cx18_readl(cx, addr);
+		if (r == 0xffffffff && eval != 0xffffffff)
+			continue;
+		if (eval == (r & mask))
+			break;
+	}
+}
+
+static inline u16 cx18_readw(struct cx18 *cx, const void __iomem *addr)
+{
+	return readw(addr);
+}
+
+static inline
+void cx18_writew_noretry(struct cx18 *cx, u16 val, void __iomem *addr)
+{
+	writew(val, addr);
+}
+
+static inline void cx18_writew(struct cx18 *cx, u16 val, void __iomem *addr)
+{
+	int i;
+	for (i = 0; i < CX18_MAX_MMIO_WR_RETRIES; i++) {
+		cx18_writew_noretry(cx, val, addr);
+		if (val == cx18_readw(cx, addr))
+			break;
+	}
+}
+
+static inline u8 cx18_readb(struct cx18 *cx, const void __iomem *addr)
+{
+	return readb(addr);
+}
+
+static inline
+void cx18_writeb_noretry(struct cx18 *cx, u8 val, void __iomem *addr)
+{
+	writeb(val, addr);
+}
+
+static inline void cx18_writeb(struct cx18 *cx, u8 val, void __iomem *addr)
+{
+	int i;
+	for (i = 0; i < CX18_MAX_MMIO_WR_RETRIES; i++) {
+		cx18_writeb_noretry(cx, val, addr);
+		if (val == cx18_readb(cx, addr))
+			break;
+	}
+}
+
+static inline
+void cx18_memcpy_fromio(struct cx18 *cx, void *to,
+			const void __iomem *from, unsigned int len)
+{
+	memcpy_fromio(to, from, len);
+}
+
+void cx18_memset_io(struct cx18 *cx, void __iomem *addr, int val, size_t count);
+
+
+/* Access "register" region of CX23418 memory mapped I/O */
+static inline void cx18_write_reg_noretry(struct cx18 *cx, u32 val, u32 reg)
+{
+	cx18_writel_noretry(cx, val, cx->reg_mem + reg);
+}
+
+static inline void cx18_write_reg(struct cx18 *cx, u32 val, u32 reg)
+{
+	cx18_writel(cx, val, cx->reg_mem + reg);
+}
+
+static inline void cx18_write_reg_expect(struct cx18 *cx, u32 val, u32 reg,
+					 u32 eval, u32 mask)
+{
+	cx18_writel_expect(cx, val, cx->reg_mem + reg, eval, mask);
+}
+
+static inline u32 cx18_read_reg(struct cx18 *cx, u32 reg)
+{
+	return cx18_readl(cx, cx->reg_mem + reg);
+}
+
+
+/* Access "encoder memory" region of CX23418 memory mapped I/O */
+static inline void cx18_write_enc(struct cx18 *cx, u32 val, u32 addr)
+{
+	cx18_writel(cx, val, cx->enc_mem + addr);
+}
+
+static inline u32 cx18_read_enc(struct cx18 *cx, u32 addr)
+{
+	return cx18_readl(cx, cx->enc_mem + addr);
+}
+
+void cx18_sw1_irq_enable(struct cx18 *cx, u32 val);
+void cx18_sw1_irq_disable(struct cx18 *cx, u32 val);
+void cx18_sw2_irq_enable(struct cx18 *cx, u32 val);
+void cx18_sw2_irq_disable(struct cx18 *cx, u32 val);
+void cx18_sw2_irq_disable_cpu(struct cx18 *cx, u32 val);
+void cx18_setup_page(struct cx18 *cx, u32 addr);
+
+#endif /* CX18_IO_H */
diff --git a/drivers/media/pci/cx18/cx18-ioctl.c b/drivers/media/pci/cx18/cx18-ioctl.c
new file mode 100644
index 0000000..e9912db
--- /dev/null
+++ b/drivers/media/pci/cx18/cx18-ioctl.c
@@ -0,0 +1,1194 @@
+/*
+ *  cx18 ioctl system call
+ *
+ *  Derived from ivtv-ioctl.c
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.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 program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public 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 "cx18-driver.h"
+#include "cx18-io.h"
+#include "cx18-version.h"
+#include "cx18-mailbox.h"
+#include "cx18-i2c.h"
+#include "cx18-queue.h"
+#include "cx18-fileops.h"
+#include "cx18-vbi.h"
+#include "cx18-audio.h"
+#include "cx18-video.h"
+#include "cx18-streams.h"
+#include "cx18-ioctl.h"
+#include "cx18-gpio.h"
+#include "cx18-controls.h"
+#include "cx18-cards.h"
+#include "cx18-av-core.h"
+#include <media/tveeprom.h>
+#include <media/v4l2-chip-ident.h>
+
+u16 cx18_service2vbi(int type)
+{
+	switch (type) {
+	case V4L2_SLICED_TELETEXT_B:
+		return CX18_SLICED_TYPE_TELETEXT_B;
+	case V4L2_SLICED_CAPTION_525:
+		return CX18_SLICED_TYPE_CAPTION_525;
+	case V4L2_SLICED_WSS_625:
+		return CX18_SLICED_TYPE_WSS_625;
+	case V4L2_SLICED_VPS:
+		return CX18_SLICED_TYPE_VPS;
+	default:
+		return 0;
+	}
+}
+
+/* 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 &&
+		((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);
+	int i;
+
+	set = set & valid_set;
+	if (set == 0 || !valid_service_line(field, line, is_pal))
+		return 0;
+	if (!is_pal) {
+		if (line == 21 && (set & V4L2_SLICED_CAPTION_525))
+			return V4L2_SLICED_CAPTION_525;
+	} else {
+		if (line == 16 && field == 0 && (set & V4L2_SLICED_VPS))
+			return V4L2_SLICED_VPS;
+		if (line == 23 && field == 0 && (set & V4L2_SLICED_WSS_625))
+			return V4L2_SLICED_WSS_625;
+		if (line == 23)
+			return 0;
+	}
+	for (i = 0; i < 32; i++) {
+		if ((1 << i) & set)
+			return 1 << i;
+	}
+	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;
+	int f, l;
+
+	fmt->service_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, set, is_pal);
+	}
+}
+
+/*
+ * 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;
+	u16 set = 0;
+
+	for (f = 0; f < 2; f++) {
+		for (l = 0; l < 24; l++)
+			set |= fmt->service_lines[f][l];
+	}
+	return set;
+}
+
+static int cx18_g_fmt_vid_cap(struct file *file, void *fh,
+				struct v4l2_format *fmt)
+{
+	struct cx18_open_id *id = fh2id(fh);
+	struct cx18 *cx = id->cx;
+	struct cx18_stream *s = &cx->streams[id->type];
+	struct v4l2_pix_format *pixfmt = &fmt->fmt.pix;
+
+	pixfmt->width = cx->cxhdl.width;
+	pixfmt->height = cx->cxhdl.height;
+	pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
+	pixfmt->field = V4L2_FIELD_INTERLACED;
+	pixfmt->priv = 0;
+	if (id->type == CX18_ENC_STREAM_TYPE_YUV) {
+		pixfmt->pixelformat = s->pixelformat;
+		pixfmt->sizeimage = s->vb_bytes_per_frame;
+		pixfmt->bytesperline = 720;
+	} else {
+		pixfmt->pixelformat = V4L2_PIX_FMT_MPEG;
+		pixfmt->sizeimage = 128 * 1024;
+		pixfmt->bytesperline = 0;
+	}
+	return 0;
+}
+
+static int cx18_g_fmt_vbi_cap(struct file *file, void *fh,
+				struct v4l2_format *fmt)
+{
+	struct cx18 *cx = fh2id(fh)->cx;
+	struct v4l2_vbi_format *vbifmt = &fmt->fmt.vbi;
+
+	vbifmt->sampling_rate = 27000000;
+	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];
+	vbifmt->count[0] = vbifmt->count[1] = cx->vbi.count;
+	vbifmt->flags = 0;
+	vbifmt->reserved[0] = 0;
+	vbifmt->reserved[1] = 0;
+	return 0;
+}
+
+static int cx18_g_fmt_sliced_vbi_cap(struct file *file, void *fh,
+					struct v4l2_format *fmt)
+{
+	struct cx18 *cx = fh2id(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, vbi, g_sliced_fmt, &fmt->fmt.sliced))
+		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,
+				struct v4l2_format *fmt)
+{
+	struct cx18_open_id *id = fh2id(fh);
+	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, 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, min_h);
+
+	fmt->fmt.pix.width = w;
+	fmt->fmt.pix.height = h;
+	return 0;
+}
+
+static int cx18_try_fmt_vbi_cap(struct file *file, void *fh,
+				struct v4l2_format *fmt)
+{
+	return cx18_g_fmt_vbi_cap(file, fh, fmt);
+}
+
+static int cx18_try_fmt_sliced_vbi_cap(struct file *file, void *fh,
+					struct v4l2_format *fmt)
+{
+	struct cx18 *cx = fh2id(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,
+				struct v4l2_format *fmt)
+{
+	struct cx18_open_id *id = fh2id(fh);
+	struct cx18 *cx = id->cx;
+	struct v4l2_mbus_framefmt mbus_fmt;
+	struct cx18_stream *s = &cx->streams[id->type];
+	int ret;
+	int w, h;
+
+	ret = cx18_try_fmt_vid_cap(file, fh, fmt);
+	if (ret)
+		return ret;
+	w = fmt->fmt.pix.width;
+	h = fmt->fmt.pix.height;
+
+	if (cx->cxhdl.width == w && cx->cxhdl.height == h &&
+	    s->pixelformat == fmt->fmt.pix.pixelformat)
+		return 0;
+
+	if (atomic_read(&cx->ana_capturing) > 0)
+		return -EBUSY;
+
+	s->pixelformat = fmt->fmt.pix.pixelformat;
+	/* HM12 YUV size is (Y=(h*720) + UV=(h*(720/2)))
+	   UYUV YUV size is (Y=(h*720) + UV=(h*(720))) */
+	if (s->pixelformat == V4L2_PIX_FMT_HM12)
+		s->vb_bytes_per_frame = h * 720 * 3 / 2;
+	else
+		s->vb_bytes_per_frame = h * 720 * 2;
+
+	mbus_fmt.width = cx->cxhdl.width = w;
+	mbus_fmt.height = cx->cxhdl.height = h;
+	mbus_fmt.code = V4L2_MBUS_FMT_FIXED;
+	v4l2_subdev_call(cx->sd_av, video, s_mbus_fmt, &mbus_fmt);
+	return cx18_g_fmt_vid_cap(file, fh, fmt);
+}
+
+static int cx18_s_fmt_vbi_cap(struct file *file, void *fh,
+				struct v4l2_format *fmt)
+{
+	struct cx18_open_id *id = fh2id(fh);
+	struct cx18 *cx = id->cx;
+	int 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 a lot of the passed in fmt under valid
+	 * calling conditions
+	 */
+	ret = v4l2_subdev_call(cx->sd_av, vbi, s_raw_fmt, &fmt->fmt.vbi);
+	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;
+
+	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)
+{
+	struct cx18_open_id *id = fh2id(fh);
+	struct cx18 *cx = id->cx;
+	int ret;
+	struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
+
+	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, vbi, s_sliced_fmt, &fmt->fmt.sliced);
+	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 = fh2id(fh)->cx;
+	int err = 0;
+
+	chip->ident = V4L2_IDENT_NONE;
+	chip->revision = 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;
+	}
+	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;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+	if (regs->reg >= CX18_MEM_OFFSET + CX18_MEM_SIZE)
+		return -EINVAL;
+
+	regs->size = 4;
+	if (cmd == VIDIOC_DBG_S_REGISTER)
+		cx18_write_enc(cx, regs->val, regs->reg);
+	else
+		regs->val = cx18_read_enc(cx, regs->reg);
+	return 0;
+}
+
+static int cx18_g_register(struct file *file, void *fh,
+				struct v4l2_dbg_register *reg)
+{
+	struct cx18 *cx = fh2id(fh)->cx;
+
+	if (v4l2_chip_match_host(&reg->match))
+		return cx18_cxc(cx, VIDIOC_DBG_G_REGISTER, reg);
+	/* FIXME - errors shouldn't be ignored */
+	cx18_call_all(cx, core, g_register, reg);
+	return 0;
+}
+
+static int cx18_s_register(struct file *file, void *fh,
+				struct v4l2_dbg_register *reg)
+{
+	struct cx18 *cx = fh2id(fh)->cx;
+
+	if (v4l2_chip_match_host(&reg->match))
+		return cx18_cxc(cx, VIDIOC_DBG_S_REGISTER, reg);
+	/* FIXME - errors shouldn't be ignored */
+	cx18_call_all(cx, core, s_register, reg);
+	return 0;
+}
+#endif
+
+static int cx18_querycap(struct file *file, void *fh,
+				struct v4l2_capability *vcap)
+{
+	struct cx18_open_id *id = fh2id(fh);
+	struct cx18 *cx = id->cx;
+
+	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->pci_dev));
+	vcap->capabilities = cx->v4l2_cap; 	    /* capabilities */
+	if (id->type == CX18_ENC_STREAM_TYPE_YUV)
+		vcap->capabilities |= V4L2_CAP_STREAMING;
+	return 0;
+}
+
+static int cx18_enumaudio(struct file *file, void *fh, struct v4l2_audio *vin)
+{
+	struct cx18 *cx = fh2id(fh)->cx;
+
+	return cx18_get_audio_input(cx, vin->index, vin);
+}
+
+static int cx18_g_audio(struct file *file, void *fh, struct v4l2_audio *vin)
+{
+	struct cx18 *cx = fh2id(fh)->cx;
+
+	vin->index = cx->audio_input;
+	return cx18_get_audio_input(cx, vin->index, vin);
+}
+
+static int cx18_s_audio(struct file *file, void *fh, struct v4l2_audio *vout)
+{
+	struct cx18 *cx = fh2id(fh)->cx;
+
+	if (vout->index >= cx->nof_audio_inputs)
+		return -EINVAL;
+	cx->audio_input = vout->index;
+	cx18_audio_set_io(cx);
+	return 0;
+}
+
+static int cx18_enum_input(struct file *file, void *fh, struct v4l2_input *vin)
+{
+	struct cx18 *cx = fh2id(fh)->cx;
+
+	/* set it to defaults from our table */
+	return cx18_get_input(cx, vin->index, vin);
+}
+
+static int cx18_cropcap(struct file *file, void *fh,
+			struct v4l2_cropcap *cropcap)
+{
+	struct cx18 *cx = fh2id(fh)->cx;
+
+	if (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+	cropcap->bounds.top = cropcap->bounds.left = 0;
+	cropcap->bounds.width = 720;
+	cropcap->bounds.height = cx->is_50hz ? 576 : 480;
+	cropcap->pixelaspect.numerator = cx->is_50hz ? 59 : 10;
+	cropcap->pixelaspect.denominator = cx->is_50hz ? 54 : 11;
+	cropcap->defrect = cropcap->bounds;
+	return 0;
+}
+
+static int cx18_s_crop(struct file *file, void *fh, struct v4l2_crop *crop)
+{
+	struct cx18_open_id *id = fh2id(fh);
+	struct cx18 *cx = id->cx;
+
+	if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+	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)
+{
+	struct cx18 *cx = fh2id(fh)->cx;
+
+	if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+	CX18_DEBUG_WARN("VIDIOC_G_CROP not implemented\n");
+	return -EINVAL;
+}
+
+static int cx18_enum_fmt_vid_cap(struct file *file, void *fh,
+					struct v4l2_fmtdesc *fmt)
+{
+	static const struct v4l2_fmtdesc formats[] = {
+		{ 0, V4L2_BUF_TYPE_VIDEO_CAPTURE, 0,
+		  "HM12 (YUV 4:1:1)", V4L2_PIX_FMT_HM12, { 0, 0, 0, 0 }
+		},
+		{ 1, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FMT_FLAG_COMPRESSED,
+		  "MPEG", V4L2_PIX_FMT_MPEG, { 0, 0, 0, 0 }
+		},
+		{ 2, V4L2_BUF_TYPE_VIDEO_CAPTURE, 0,
+		  "UYVY 4:2:2", V4L2_PIX_FMT_UYVY, { 0, 0, 0, 0 }
+		},
+	};
+
+	if (fmt->index > ARRAY_SIZE(formats) - 1)
+		return -EINVAL;
+	*fmt = formats[fmt->index];
+	return 0;
+}
+
+static int cx18_g_input(struct file *file, void *fh, unsigned int *i)
+{
+	struct cx18 *cx = fh2id(fh)->cx;
+
+	*i = cx->active_input;
+	return 0;
+}
+
+int cx18_s_input(struct file *file, void *fh, unsigned int inp)
+{
+	struct cx18_open_id *id = fh2id(fh);
+	struct cx18 *cx = id->cx;
+
+	if (inp >= cx->nof_inputs)
+		return -EINVAL;
+
+	if (inp == cx->active_input) {
+		CX18_DEBUG_INFO("Input unchanged\n");
+		return 0;
+	}
+
+	CX18_DEBUG_INFO("Changing input from %d to %d\n",
+			cx->active_input, inp);
+
+	cx->active_input = inp;
+	/* Set the audio input to whatever is appropriate for the input type. */
+	cx->audio_input = cx->card->video_inputs[inp].audio_index;
+
+	/* prevent others from messing with the streams until
+	   we're finished changing inputs. */
+	cx18_mute(cx);
+	cx18_video_set_io(cx);
+	cx18_audio_set_io(cx);
+	cx18_unmute(cx);
+	return 0;
+}
+
+static int cx18_g_frequency(struct file *file, void *fh,
+				struct v4l2_frequency *vf)
+{
+	struct cx18 *cx = fh2id(fh)->cx;
+
+	if (vf->tuner != 0)
+		return -EINVAL;
+
+	cx18_call_all(cx, tuner, g_frequency, vf);
+	return 0;
+}
+
+int cx18_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf)
+{
+	struct cx18_open_id *id = fh2id(fh);
+	struct cx18 *cx = id->cx;
+
+	if (vf->tuner != 0)
+		return -EINVAL;
+
+	cx18_mute(cx);
+	CX18_DEBUG_INFO("v4l2 ioctl: set frequency %d\n", vf->frequency);
+	cx18_call_all(cx, tuner, s_frequency, vf);
+	cx18_unmute(cx);
+	return 0;
+}
+
+static int cx18_g_std(struct file *file, void *fh, v4l2_std_id *std)
+{
+	struct cx18 *cx = fh2id(fh)->cx;
+
+	*std = cx->std;
+	return 0;
+}
+
+int cx18_s_std(struct file *file, void *fh, v4l2_std_id *std)
+{
+	struct cx18_open_id *id = fh2id(fh);
+	struct cx18 *cx = id->cx;
+
+	if ((*std & V4L2_STD_ALL) == 0)
+		return -EINVAL;
+
+	if (*std == cx->std)
+		return 0;
+
+	if (test_bit(CX18_F_I_RADIO_USER, &cx->i_flags) ||
+	    atomic_read(&cx->ana_capturing) > 0) {
+		/* Switching standard would turn off the radio or mess
+		   with already running streams, prevent that by
+		   returning EBUSY. */
+		return -EBUSY;
+	}
+
+	cx->std = *std;
+	cx->is_60hz = (*std & V4L2_STD_525_60) ? 1 : 0;
+	cx->is_50hz = !cx->is_60hz;
+	cx2341x_handler_set_50hz(&cx->cxhdl, cx->is_50hz);
+	cx->cxhdl.width = 720;
+	cx->cxhdl.height = cx->is_50hz ? 576 : 480;
+	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;
+	CX18_DEBUG_INFO("Switching standard to %llx.\n",
+			(unsigned long long) cx->std);
+
+	/* Tuner */
+	cx18_call_all(cx, core, s_std, cx->std);
+	return 0;
+}
+
+static int cx18_s_tuner(struct file *file, void *fh, struct v4l2_tuner *vt)
+{
+	struct cx18_open_id *id = fh2id(fh);
+	struct cx18 *cx = id->cx;
+
+	if (vt->index != 0)
+		return -EINVAL;
+
+	cx18_call_all(cx, tuner, s_tuner, vt);
+	return 0;
+}
+
+static int cx18_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt)
+{
+	struct cx18 *cx = fh2id(fh)->cx;
+
+	if (vt->index != 0)
+		return -EINVAL;
+
+	cx18_call_all(cx, tuner, g_tuner, vt);
+
+	if (vt->type == V4L2_TUNER_RADIO)
+		strlcpy(vt->name, "cx18 Radio Tuner", sizeof(vt->name));
+	else
+		strlcpy(vt->name, "cx18 TV Tuner", sizeof(vt->name));
+	return 0;
+}
+
+static int cx18_g_sliced_vbi_cap(struct file *file, void *fh,
+					struct v4l2_sliced_vbi_cap *cap)
+{
+	struct cx18 *cx = fh2id(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_process_idx_data(struct cx18_buffer *buf,
+				  struct v4l2_enc_idx *idx)
+{
+	int consumed, remaining;
+	struct v4l2_enc_idx_entry *e_idx;
+	struct cx18_enc_idx_entry *e_buf;
+
+	/* Frame type lookup: 1=I, 2=P, 4=B */
+	const int mapping[8] = {
+		-1, V4L2_ENC_IDX_FRAME_I, V4L2_ENC_IDX_FRAME_P,
+		-1, V4L2_ENC_IDX_FRAME_B, -1, -1, -1
+	};
+
+	/*
+	 * Assumption here is that a buf holds an integral number of
+	 * struct cx18_enc_idx_entry objects and is properly aligned.
+	 * This is enforced by the module options on IDX buffer sizes.
+	 */
+	remaining = buf->bytesused - buf->readpos;
+	consumed = 0;
+	e_idx = &idx->entry[idx->entries];
+	e_buf = (struct cx18_enc_idx_entry *) &buf->buf[buf->readpos];
+
+	while (remaining >= sizeof(struct cx18_enc_idx_entry) &&
+	       idx->entries < V4L2_ENC_IDX_ENTRIES) {
+
+		e_idx->offset = (((u64) le32_to_cpu(e_buf->offset_high)) << 32)
+				| le32_to_cpu(e_buf->offset_low);
+
+		e_idx->pts = (((u64) (le32_to_cpu(e_buf->pts_high) & 1)) << 32)
+			     | le32_to_cpu(e_buf->pts_low);
+
+		e_idx->length = le32_to_cpu(e_buf->length);
+
+		e_idx->flags = mapping[le32_to_cpu(e_buf->flags) & 0x7];
+
+		e_idx->reserved[0] = 0;
+		e_idx->reserved[1] = 0;
+
+		idx->entries++;
+		e_idx = &idx->entry[idx->entries];
+		e_buf++;
+
+		remaining -= sizeof(struct cx18_enc_idx_entry);
+		consumed += sizeof(struct cx18_enc_idx_entry);
+	}
+
+	/* Swallow any partial entries at the end, if there are any */
+	if (remaining > 0 && remaining < sizeof(struct cx18_enc_idx_entry))
+		consumed += remaining;
+
+	buf->readpos += consumed;
+	return consumed;
+}
+
+static int cx18_process_idx_data(struct cx18_stream *s, struct cx18_mdl *mdl,
+				 struct v4l2_enc_idx *idx)
+{
+	if (s->type != CX18_ENC_STREAM_TYPE_IDX)
+		return -EINVAL;
+
+	if (mdl->curr_buf == NULL)
+		mdl->curr_buf = list_first_entry(&mdl->buf_list,
+						 struct cx18_buffer, list);
+
+	if (list_entry_is_past_end(mdl->curr_buf, &mdl->buf_list, list)) {
+		/*
+		 * For some reason we've exhausted the buffers, but the MDL
+		 * object still said some data was unread.
+		 * Fix that and bail out.
+		 */
+		mdl->readpos = mdl->bytesused;
+		return 0;
+	}
+
+	list_for_each_entry_from(mdl->curr_buf, &mdl->buf_list, list) {
+
+		/* Skip any empty buffers in the MDL */
+		if (mdl->curr_buf->readpos >= mdl->curr_buf->bytesused)
+			continue;
+
+		mdl->readpos += _cx18_process_idx_data(mdl->curr_buf, idx);
+
+		/* exit when MDL drained or request satisfied */
+		if (idx->entries >= V4L2_ENC_IDX_ENTRIES ||
+		    mdl->curr_buf->readpos < mdl->curr_buf->bytesused ||
+		    mdl->readpos >= mdl->bytesused)
+			break;
+	}
+	return 0;
+}
+
+static int cx18_g_enc_index(struct file *file, void *fh,
+				struct v4l2_enc_idx *idx)
+{
+	struct cx18 *cx = fh2id(fh)->cx;
+	struct cx18_stream *s = &cx->streams[CX18_ENC_STREAM_TYPE_IDX];
+	s32 tmp;
+	struct cx18_mdl *mdl;
+
+	if (!cx18_stream_enabled(s)) /* Module options inhibited IDX stream */
+		return -EINVAL;
+
+	/* Compute the best case number of entries we can buffer */
+	tmp = s->buffers -
+			  s->bufs_per_mdl * CX18_ENC_STREAM_TYPE_IDX_FW_MDL_MIN;
+	if (tmp <= 0)
+		tmp = 1;
+	tmp = tmp * s->buf_size / sizeof(struct cx18_enc_idx_entry);
+
+	/* Fill out the header of the return structure */
+	idx->entries = 0;
+	idx->entries_cap = tmp;
+	memset(idx->reserved, 0, sizeof(idx->reserved));
+
+	/* Pull IDX MDLs and buffers from q_full and populate the entries */
+	do {
+		mdl = cx18_dequeue(s, &s->q_full);
+		if (mdl == NULL) /* No more IDX data right now */
+			break;
+
+		/* Extract the Index entry data from the MDL and buffers */
+		cx18_process_idx_data(s, mdl, idx);
+		if (mdl->readpos < mdl->bytesused) {
+			/* We finished with data remaining, push the MDL back */
+			cx18_push(s, mdl, &s->q_full);
+			break;
+		}
+
+		/* We drained this MDL, schedule it to go to the firmware */
+		cx18_enqueue(s, mdl, &s->q_free);
+
+	} while (idx->entries < V4L2_ENC_IDX_ENTRIES);
+
+	/* Tell the work handler to send free IDX MDLs to the firmware */
+	cx18_stream_load_fw_queue(s);
+	return 0;
+}
+
+static struct videobuf_queue *cx18_vb_queue(struct cx18_open_id *id)
+{
+	struct videobuf_queue *q = NULL;
+	struct cx18 *cx = id->cx;
+	struct cx18_stream *s = &cx->streams[id->type];
+
+	switch (s->vb_type) {
+	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+		q = &s->vbuf_q;
+		break;
+	case V4L2_BUF_TYPE_VBI_CAPTURE:
+		break;
+	default:
+		break;
+	}
+	return q;
+}
+
+static int cx18_streamon(struct file *file, void *priv,
+	enum v4l2_buf_type type)
+{
+	struct cx18_open_id *id = file->private_data;
+	struct cx18 *cx = id->cx;
+	struct cx18_stream *s = &cx->streams[id->type];
+
+	/* Start the hardware only if we're the video device */
+	if ((s->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
+		(s->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE))
+		return -EINVAL;
+
+	if (id->type != CX18_ENC_STREAM_TYPE_YUV)
+		return -EINVAL;
+
+	/* Establish a buffer timeout */
+	mod_timer(&s->vb_timeout, msecs_to_jiffies(2000) + jiffies);
+
+	return videobuf_streamon(cx18_vb_queue(id));
+}
+
+static int cx18_streamoff(struct file *file, void *priv,
+	enum v4l2_buf_type type)
+{
+	struct cx18_open_id *id = file->private_data;
+	struct cx18 *cx = id->cx;
+	struct cx18_stream *s = &cx->streams[id->type];
+
+	/* Start the hardware only if we're the video device */
+	if ((s->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
+		(s->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE))
+		return -EINVAL;
+
+	if (id->type != CX18_ENC_STREAM_TYPE_YUV)
+		return -EINVAL;
+
+	return videobuf_streamoff(cx18_vb_queue(id));
+}
+
+static int cx18_reqbufs(struct file *file, void *priv,
+	struct v4l2_requestbuffers *rb)
+{
+	struct cx18_open_id *id = file->private_data;
+	struct cx18 *cx = id->cx;
+	struct cx18_stream *s = &cx->streams[id->type];
+
+	if ((s->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
+		(s->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE))
+		return -EINVAL;
+
+	return videobuf_reqbufs(cx18_vb_queue(id), rb);
+}
+
+static int cx18_querybuf(struct file *file, void *priv,
+	struct v4l2_buffer *b)
+{
+	struct cx18_open_id *id = file->private_data;
+	struct cx18 *cx = id->cx;
+	struct cx18_stream *s = &cx->streams[id->type];
+
+	if ((s->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
+		(s->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE))
+		return -EINVAL;
+
+	return videobuf_querybuf(cx18_vb_queue(id), b);
+}
+
+static int cx18_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
+{
+	struct cx18_open_id *id = file->private_data;
+	struct cx18 *cx = id->cx;
+	struct cx18_stream *s = &cx->streams[id->type];
+
+	if ((s->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
+		(s->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE))
+		return -EINVAL;
+
+	return videobuf_qbuf(cx18_vb_queue(id), b);
+}
+
+static int cx18_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
+{
+	struct cx18_open_id *id = file->private_data;
+	struct cx18 *cx = id->cx;
+	struct cx18_stream *s = &cx->streams[id->type];
+
+	if ((s->vb_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
+		(s->vb_type != V4L2_BUF_TYPE_VBI_CAPTURE))
+		return -EINVAL;
+
+	return videobuf_dqbuf(cx18_vb_queue(id), b, file->f_flags & O_NONBLOCK);
+}
+
+static int cx18_encoder_cmd(struct file *file, void *fh,
+				struct v4l2_encoder_cmd *enc)
+{
+	struct cx18_open_id *id = fh2id(fh);
+	struct cx18 *cx = id->cx;
+	u32 h;
+
+	switch (enc->cmd) {
+	case V4L2_ENC_CMD_START:
+		CX18_DEBUG_IOCTL("V4L2_ENC_CMD_START\n");
+		enc->flags = 0;
+		return cx18_start_capture(id);
+
+	case V4L2_ENC_CMD_STOP:
+		CX18_DEBUG_IOCTL("V4L2_ENC_CMD_STOP\n");
+		enc->flags &= V4L2_ENC_CMD_STOP_AT_GOP_END;
+		cx18_stop_capture(id,
+				  enc->flags & V4L2_ENC_CMD_STOP_AT_GOP_END);
+		break;
+
+	case V4L2_ENC_CMD_PAUSE:
+		CX18_DEBUG_IOCTL("V4L2_ENC_CMD_PAUSE\n");
+		enc->flags = 0;
+		if (!atomic_read(&cx->ana_capturing))
+			return -EPERM;
+		if (test_and_set_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags))
+			return 0;
+		h = cx18_find_handle(cx);
+		if (h == CX18_INVALID_TASK_HANDLE) {
+			CX18_ERR("Can't find valid task handle for "
+				 "V4L2_ENC_CMD_PAUSE\n");
+			return -EBADFD;
+		}
+		cx18_mute(cx);
+		cx18_vapi(cx, CX18_CPU_CAPTURE_PAUSE, 1, h);
+		break;
+
+	case V4L2_ENC_CMD_RESUME:
+		CX18_DEBUG_IOCTL("V4L2_ENC_CMD_RESUME\n");
+		enc->flags = 0;
+		if (!atomic_read(&cx->ana_capturing))
+			return -EPERM;
+		if (!test_and_clear_bit(CX18_F_I_ENC_PAUSED, &cx->i_flags))
+			return 0;
+		h = cx18_find_handle(cx);
+		if (h == CX18_INVALID_TASK_HANDLE) {
+			CX18_ERR("Can't find valid task handle for "
+				 "V4L2_ENC_CMD_RESUME\n");
+			return -EBADFD;
+		}
+		cx18_vapi(cx, CX18_CPU_CAPTURE_RESUME, 1, h);
+		cx18_unmute(cx);
+		break;
+
+	default:
+		CX18_DEBUG_IOCTL("Unknown cmd %d\n", enc->cmd);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int cx18_try_encoder_cmd(struct file *file, void *fh,
+				struct v4l2_encoder_cmd *enc)
+{
+	struct cx18 *cx = fh2id(fh)->cx;
+
+	switch (enc->cmd) {
+	case V4L2_ENC_CMD_START:
+		CX18_DEBUG_IOCTL("V4L2_ENC_CMD_START\n");
+		enc->flags = 0;
+		break;
+
+	case V4L2_ENC_CMD_STOP:
+		CX18_DEBUG_IOCTL("V4L2_ENC_CMD_STOP\n");
+		enc->flags &= V4L2_ENC_CMD_STOP_AT_GOP_END;
+		break;
+
+	case V4L2_ENC_CMD_PAUSE:
+		CX18_DEBUG_IOCTL("V4L2_ENC_CMD_PAUSE\n");
+		enc->flags = 0;
+		break;
+
+	case V4L2_ENC_CMD_RESUME:
+		CX18_DEBUG_IOCTL("V4L2_ENC_CMD_RESUME\n");
+		enc->flags = 0;
+		break;
+
+	default:
+		CX18_DEBUG_IOCTL("Unknown cmd %d\n", enc->cmd);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int cx18_log_status(struct file *file, void *fh)
+{
+	struct cx18 *cx = fh2id(fh)->cx;
+	struct v4l2_input vidin;
+	struct v4l2_audio audin;
+	int i;
+
+	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_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);
+	CX18_INFO("Audio Input: %s\n", audin.name);
+	mutex_lock(&cx->gpio_lock);
+	CX18_INFO("GPIO:  direction 0x%08x, value 0x%08x\n",
+		cx->gpio_dir, cx->gpio_val);
+	mutex_unlock(&cx->gpio_lock);
+	CX18_INFO("Tuner: %s\n",
+		test_bit(CX18_F_I_RADIO_USER, &cx->i_flags) ?  "Radio" : "TV");
+	v4l2_ctrl_handler_log_status(&cx->cxhdl.hdl, 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->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,
+			  atomic_read(&s->q_full.depth) * s->bufs_per_mdl * 100
+			   / s->buffers,
+			  (s->buffers * s->buf_size) / 1024, s->buffers);
+	}
+	CX18_INFO("Read MPEG/VBI: %lld/%lld bytes\n",
+			(long long)cx->mpg_data_received,
+			(long long)cx->vbi_data_inserted);
+	return 0;
+}
+
+static long cx18_default(struct file *file, void *fh, bool valid_prio,
+							int cmd, void *arg)
+{
+	struct cx18 *cx = fh2id(fh)->cx;
+
+	switch (cmd) {
+	case VIDIOC_INT_RESET: {
+		u32 val = *(u32 *)arg;
+
+		if ((val == 0) || (val & 0x01))
+			cx18_call_hw(cx, CX18_HW_GPIO_RESET_CTRL, core, reset,
+				     (u32) CX18_GPIO_RESET_Z8F0811);
+		break;
+	}
+
+	default:
+		return -ENOTTY;
+	}
+	return 0;
+}
+
+static const struct v4l2_ioctl_ops cx18_ioctl_ops = {
+	.vidioc_querycap                = cx18_querycap,
+	.vidioc_s_audio                 = cx18_s_audio,
+	.vidioc_g_audio                 = cx18_g_audio,
+	.vidioc_enumaudio               = cx18_enumaudio,
+	.vidioc_enum_input              = cx18_enum_input,
+	.vidioc_cropcap                 = cx18_cropcap,
+	.vidioc_s_crop                  = cx18_s_crop,
+	.vidioc_g_crop                  = cx18_g_crop,
+	.vidioc_g_input                 = cx18_g_input,
+	.vidioc_s_input                 = cx18_s_input,
+	.vidioc_g_frequency             = cx18_g_frequency,
+	.vidioc_s_frequency             = cx18_s_frequency,
+	.vidioc_s_tuner                 = cx18_s_tuner,
+	.vidioc_g_tuner                 = cx18_g_tuner,
+	.vidioc_g_enc_index             = cx18_g_enc_index,
+	.vidioc_g_std                   = cx18_g_std,
+	.vidioc_s_std                   = cx18_s_std,
+	.vidioc_log_status              = cx18_log_status,
+	.vidioc_enum_fmt_vid_cap        = cx18_enum_fmt_vid_cap,
+	.vidioc_encoder_cmd             = cx18_encoder_cmd,
+	.vidioc_try_encoder_cmd         = cx18_try_encoder_cmd,
+	.vidioc_g_fmt_vid_cap           = cx18_g_fmt_vid_cap,
+	.vidioc_g_fmt_vbi_cap           = cx18_g_fmt_vbi_cap,
+	.vidioc_g_fmt_sliced_vbi_cap    = cx18_g_fmt_sliced_vbi_cap,
+	.vidioc_s_fmt_vid_cap           = cx18_s_fmt_vid_cap,
+	.vidioc_s_fmt_vbi_cap           = cx18_s_fmt_vbi_cap,
+	.vidioc_s_fmt_sliced_vbi_cap    = cx18_s_fmt_sliced_vbi_cap,
+	.vidioc_try_fmt_vid_cap         = cx18_try_fmt_vid_cap,
+	.vidioc_try_fmt_vbi_cap         = cx18_try_fmt_vbi_cap,
+	.vidioc_try_fmt_sliced_vbi_cap  = cx18_try_fmt_sliced_vbi_cap,
+	.vidioc_g_sliced_vbi_cap        = cx18_g_sliced_vbi_cap,
+	.vidioc_g_chip_ident            = cx18_g_chip_ident,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.vidioc_g_register              = cx18_g_register,
+	.vidioc_s_register              = cx18_s_register,
+#endif
+	.vidioc_default                 = cx18_default,
+	.vidioc_streamon                = cx18_streamon,
+	.vidioc_streamoff               = cx18_streamoff,
+	.vidioc_reqbufs                 = cx18_reqbufs,
+	.vidioc_querybuf                = cx18_querybuf,
+	.vidioc_qbuf                    = cx18_qbuf,
+	.vidioc_dqbuf                   = cx18_dqbuf,
+};
+
+void cx18_set_funcs(struct video_device *vdev)
+{
+	vdev->ioctl_ops = &cx18_ioctl_ops;
+}
diff --git a/drivers/media/pci/cx18/cx18-ioctl.h b/drivers/media/pci/cx18/cx18-ioctl.h
new file mode 100644
index 0000000..2f9dd59
--- /dev/null
+++ b/drivers/media/pci/cx18/cx18-ioctl.h
@@ -0,0 +1,31 @@
+/*
+ *  cx18 ioctl system call
+ *
+ *  Derived from ivtv-ioctl.h
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.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 program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307  USA
+ */
+
+u16 cx18_service2vbi(int type);
+void cx18_expand_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal);
+u16 cx18_get_service_set(struct v4l2_sliced_vbi_format *fmt);
+void cx18_set_funcs(struct video_device *vdev);
+int cx18_s_std(struct file *file, void *fh, v4l2_std_id *std);
+int cx18_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf);
+int cx18_s_input(struct file *file, void *fh, unsigned int inp);
diff --git a/drivers/media/pci/cx18/cx18-irq.c b/drivers/media/pci/cx18/cx18-irq.c
new file mode 100644
index 0000000..80edfe9
--- /dev/null
+++ b/drivers/media/pci/cx18/cx18-irq.c
@@ -0,0 +1,81 @@
+/*
+ *  cx18 interrupt handling
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.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 program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public 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 "cx18-driver.h"
+#include "cx18-io.h"
+#include "cx18-irq.h"
+#include "cx18-mailbox.h"
+#include "cx18-scb.h"
+
+static void xpu_ack(struct cx18 *cx, u32 sw2)
+{
+	if (sw2 & IRQ_CPU_TO_EPU_ACK)
+		wake_up(&cx->mb_cpu_waitq);
+	if (sw2 & IRQ_APU_TO_EPU_ACK)
+		wake_up(&cx->mb_apu_waitq);
+}
+
+static void epu_cmd(struct cx18 *cx, u32 sw1)
+{
+	if (sw1 & IRQ_CPU_TO_EPU)
+		cx18_api_epu_cmd_irq(cx, CPU);
+	if (sw1 & IRQ_APU_TO_EPU)
+		cx18_api_epu_cmd_irq(cx, APU);
+}
+
+irqreturn_t cx18_irq_handler(int irq, void *dev_id)
+{
+	struct cx18 *cx = (struct cx18 *)dev_id;
+	u32 sw1, sw2, hw2;
+
+	sw1 = cx18_read_reg(cx, SW1_INT_STATUS) & cx->sw1_irq_mask;
+	sw2 = cx18_read_reg(cx, SW2_INT_STATUS) & cx->sw2_irq_mask;
+	hw2 = cx18_read_reg(cx, HW2_INT_CLR_STATUS) & cx->hw2_irq_mask;
+
+	if (sw1)
+		cx18_write_reg_expect(cx, sw1, SW1_INT_STATUS, ~sw1, sw1);
+	if (sw2)
+		cx18_write_reg_expect(cx, sw2, SW2_INT_STATUS, ~sw2, sw2);
+	if (hw2)
+		cx18_write_reg_expect(cx, hw2, HW2_INT_CLR_STATUS, ~hw2, hw2);
+
+	if (sw1 || sw2 || hw2)
+		CX18_DEBUG_HI_IRQ("received interrupts "
+				  "SW1: %x  SW2: %x  HW2: %x\n", sw1, sw2, hw2);
+
+	/*
+	 * SW1 responses have to happen first.  The sending XPU times out the
+	 * incoming mailboxes on us rather rapidly.
+	 */
+	if (sw1)
+		epu_cmd(cx, sw1);
+
+	/* To do: interrupt-based I2C handling
+	if (hw2 & (HW2_I2C1_INT|HW2_I2C2_INT)) {
+	}
+	*/
+
+	if (sw2)
+		xpu_ack(cx, sw2);
+
+	return (sw1 || sw2 || hw2) ? IRQ_HANDLED : IRQ_NONE;
+}
diff --git a/drivers/media/pci/cx18/cx18-irq.h b/drivers/media/pci/cx18/cx18-irq.h
new file mode 100644
index 0000000..30e7eaf
--- /dev/null
+++ b/drivers/media/pci/cx18/cx18-irq.h
@@ -0,0 +1,35 @@
+/*
+ *  cx18 interrupt handling
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.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 program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public 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 HW2_I2C1_INT			(1 << 22)
+#define HW2_I2C2_INT			(1 << 23)
+#define HW2_INT_CLR_STATUS		0xc730c4
+#define HW2_INT_MASK5_PCI		0xc730e4
+#define SW1_INT_SET                     0xc73100
+#define SW1_INT_STATUS                  0xc73104
+#define SW1_INT_ENABLE_PCI              0xc7311c
+#define SW2_INT_SET                     0xc73140
+#define SW2_INT_STATUS                  0xc73144
+#define SW2_INT_ENABLE_CPU              0xc73158
+#define SW2_INT_ENABLE_PCI              0xc7315c
+
+irqreturn_t cx18_irq_handler(int irq, void *dev_id);
diff --git a/drivers/media/pci/cx18/cx18-mailbox.c b/drivers/media/pci/cx18/cx18-mailbox.c
new file mode 100644
index 0000000..eabf00c
--- /dev/null
+++ b/drivers/media/pci/cx18/cx18-mailbox.c
@@ -0,0 +1,870 @@
+/*
+ *  cx18 mailbox functions
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.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 program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public 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 <stdarg.h>
+
+#include "cx18-driver.h"
+#include "cx18-io.h"
+#include "cx18-scb.h"
+#include "cx18-irq.h"
+#include "cx18-mailbox.h"
+#include "cx18-queue.h"
+#include "cx18-streams.h"
+#include "cx18-alsa-pcm.h" /* FIXME make configurable */
+
+static const char *rpu_str[] = { "APU", "CPU", "EPU", "HPU" };
+
+#define API_FAST (1 << 2) /* Short timeout */
+#define API_SLOW (1 << 3) /* Additional 300ms timeout */
+
+struct cx18_api_info {
+	u32 cmd;
+	u8 flags;		/* Flags, see above */
+	u8 rpu;			/* Processing unit */
+	const char *name; 	/* The name of the command */
+};
+
+#define API_ENTRY(rpu, x, f) { (x), (f), (rpu), #x }
+
+static const struct cx18_api_info api_info[] = {
+	/* MPEG encoder API */
+	API_ENTRY(CPU, CX18_CPU_SET_CHANNEL_TYPE,		0),
+	API_ENTRY(CPU, CX18_EPU_DEBUG, 				0),
+	API_ENTRY(CPU, CX18_CREATE_TASK, 			0),
+	API_ENTRY(CPU, CX18_DESTROY_TASK, 			0),
+	API_ENTRY(CPU, CX18_CPU_CAPTURE_START,                  API_SLOW),
+	API_ENTRY(CPU, CX18_CPU_CAPTURE_STOP,                   API_SLOW),
+	API_ENTRY(CPU, CX18_CPU_CAPTURE_PAUSE,                  0),
+	API_ENTRY(CPU, CX18_CPU_CAPTURE_RESUME,                 0),
+	API_ENTRY(CPU, CX18_CPU_SET_CHANNEL_TYPE,               0),
+	API_ENTRY(CPU, CX18_CPU_SET_STREAM_OUTPUT_TYPE,         0),
+	API_ENTRY(CPU, CX18_CPU_SET_VIDEO_IN,                   0),
+	API_ENTRY(CPU, CX18_CPU_SET_VIDEO_RATE,                 0),
+	API_ENTRY(CPU, CX18_CPU_SET_VIDEO_RESOLUTION,           0),
+	API_ENTRY(CPU, CX18_CPU_SET_FILTER_PARAM,               0),
+	API_ENTRY(CPU, CX18_CPU_SET_SPATIAL_FILTER_TYPE,        0),
+	API_ENTRY(CPU, CX18_CPU_SET_MEDIAN_CORING,              0),
+	API_ENTRY(CPU, CX18_CPU_SET_INDEXTABLE,                 0),
+	API_ENTRY(CPU, CX18_CPU_SET_AUDIO_PARAMETERS,           0),
+	API_ENTRY(CPU, CX18_CPU_SET_VIDEO_MUTE,                 0),
+	API_ENTRY(CPU, CX18_CPU_SET_AUDIO_MUTE,                 0),
+	API_ENTRY(CPU, CX18_CPU_SET_MISC_PARAMETERS,            0),
+	API_ENTRY(CPU, CX18_CPU_SET_RAW_VBI_PARAM,              API_SLOW),
+	API_ENTRY(CPU, CX18_CPU_SET_CAPTURE_LINE_NO,            0),
+	API_ENTRY(CPU, CX18_CPU_SET_COPYRIGHT,                  0),
+	API_ENTRY(CPU, CX18_CPU_SET_AUDIO_PID,                  0),
+	API_ENTRY(CPU, CX18_CPU_SET_VIDEO_PID,                  0),
+	API_ENTRY(CPU, CX18_CPU_SET_VER_CROP_LINE,              0),
+	API_ENTRY(CPU, CX18_CPU_SET_GOP_STRUCTURE,              0),
+	API_ENTRY(CPU, CX18_CPU_SET_SCENE_CHANGE_DETECTION,     0),
+	API_ENTRY(CPU, CX18_CPU_SET_ASPECT_RATIO,               0),
+	API_ENTRY(CPU, CX18_CPU_SET_SKIP_INPUT_FRAME,           0),
+	API_ENTRY(CPU, CX18_CPU_SET_SLICED_VBI_PARAM,           0),
+	API_ENTRY(CPU, CX18_CPU_SET_USERDATA_PLACE_HOLDER,      0),
+	API_ENTRY(CPU, CX18_CPU_GET_ENC_PTS,                    0),
+	API_ENTRY(CPU, CX18_CPU_SET_VFC_PARAM,                  0),
+	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),
+};
+
+static const struct cx18_api_info *find_api_info(u32 cmd)
+{
+	int i;
+
+	for (i = 0; api_info[i].cmd; i++)
+		if (api_info[i].cmd == cmd)
+			return &api_info[i];
+	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];
+
+	if (!(cx18_debug & CX18_DBGFLG_API))
+		return;
+
+	CX18_DEBUG_API("%s: req %#010x ack %#010x cmd %#010x err %#010x args%s"
+		       "\n", name, mb->request, mb->ack, mb->cmd, mb->error,
+		       u32arr2hex(mb->args, MAX_MB_ARGUMENTS, argstr));
+}
+
+
+/*
+ * Functions that run in a work_queue work handling context
+ */
+
+static void cx18_mdl_send_to_dvb(struct cx18_stream *s, struct cx18_mdl *mdl)
+{
+	struct cx18_buffer *buf;
+
+	if (s->dvb == NULL || !s->dvb->enabled || mdl->bytesused == 0)
+		return;
+
+	/* We ignore mdl and buf readpos accounting here - it doesn't matter */
+
+	/* The likely case */
+	if (list_is_singular(&mdl->buf_list)) {
+		buf = list_first_entry(&mdl->buf_list, struct cx18_buffer,
+				       list);
+		if (buf->bytesused)
+			dvb_dmx_swfilter(&s->dvb->demux,
+					 buf->buf, buf->bytesused);
+		return;
+	}
+
+	list_for_each_entry(buf, &mdl->buf_list, list) {
+		if (buf->bytesused == 0)
+			break;
+		dvb_dmx_swfilter(&s->dvb->demux, buf->buf, buf->bytesused);
+	}
+}
+
+static void cx18_mdl_send_to_videobuf(struct cx18_stream *s,
+	struct cx18_mdl *mdl)
+{
+	struct cx18_videobuf_buffer *vb_buf;
+	struct cx18_buffer *buf;
+	u8 *p;
+	u32 offset = 0;
+	int dispatch = 0;
+
+	if (mdl->bytesused == 0)
+		return;
+
+	/* Acquire a videobuf buffer, clone to and and release it */
+	spin_lock(&s->vb_lock);
+	if (list_empty(&s->vb_capture))
+		goto out;
+
+	vb_buf = list_first_entry(&s->vb_capture, struct cx18_videobuf_buffer,
+		vb.queue);
+
+	p = videobuf_to_vmalloc(&vb_buf->vb);
+	if (!p)
+		goto out;
+
+	offset = vb_buf->bytes_used;
+	list_for_each_entry(buf, &mdl->buf_list, list) {
+		if (buf->bytesused == 0)
+			break;
+
+		if ((offset + buf->bytesused) <= vb_buf->vb.bsize) {
+			memcpy(p + offset, buf->buf, buf->bytesused);
+			offset += buf->bytesused;
+			vb_buf->bytes_used += buf->bytesused;
+		}
+	}
+
+	/* If we've filled the buffer as per the callers res then dispatch it */
+	if (vb_buf->bytes_used >= s->vb_bytes_per_frame) {
+		dispatch = 1;
+		vb_buf->bytes_used = 0;
+	}
+
+	if (dispatch) {
+		vb_buf->vb.ts = ktime_to_timeval(ktime_get());
+		list_del(&vb_buf->vb.queue);
+		vb_buf->vb.state = VIDEOBUF_DONE;
+		wake_up(&vb_buf->vb.done);
+	}
+
+	mod_timer(&s->vb_timeout, msecs_to_jiffies(2000) + jiffies);
+
+out:
+	spin_unlock(&s->vb_lock);
+}
+
+static void cx18_mdl_send_to_alsa(struct cx18 *cx, struct cx18_stream *s,
+				  struct cx18_mdl *mdl)
+{
+	struct cx18_buffer *buf;
+
+	if (mdl->bytesused == 0)
+		return;
+
+	/* We ignore mdl and buf readpos accounting here - it doesn't matter */
+
+	/* The likely case */
+	if (list_is_singular(&mdl->buf_list)) {
+		buf = list_first_entry(&mdl->buf_list, struct cx18_buffer,
+				       list);
+		if (buf->bytesused)
+			cx->pcm_announce_callback(cx->alsa, buf->buf,
+						  buf->bytesused);
+		return;
+	}
+
+	list_for_each_entry(buf, &mdl->buf_list, list) {
+		if (buf->bytesused == 0)
+			break;
+		cx->pcm_announce_callback(cx->alsa, buf->buf, buf->bytesused);
+	}
+}
+
+static void epu_dma_done(struct cx18 *cx, struct cx18_in_work_order *order)
+{
+	u32 handle, mdl_ack_count, id;
+	struct cx18_mailbox *mb;
+	struct cx18_mdl_ack *mdl_ack;
+	struct cx18_stream *s;
+	struct cx18_mdl *mdl;
+	int i;
+
+	mb = &order->mb;
+	handle = mb->args[0];
+	s = cx18_handle_to_stream(cx, handle);
+
+	if (s == NULL) {
+		CX18_WARN("Got DMA done notification for unknown/inactive"
+			  " handle %d, %s mailbox seq no %d\n", handle,
+			  (order->flags & CX18_F_EWO_MB_STALE_UPON_RECEIPT) ?
+			  "stale" : "good", mb->request);
+		return;
+	}
+
+	mdl_ack_count = mb->args[2];
+	mdl_ack = order->mdl_ack;
+	for (i = 0; i < mdl_ack_count; i++, mdl_ack++) {
+		id = mdl_ack->id;
+		/*
+		 * Simple integrity check for processing a stale (and possibly
+		 * inconsistent mailbox): make sure the MDL id is in the
+		 * valid range for the stream.
+		 *
+		 * We go through the trouble of dealing with stale mailboxes
+		 * because most of the time, the mailbox data is still valid and
+		 * unchanged (and in practice the firmware ping-pongs the
+		 * two mdl_ack buffers so mdl_acks are not stale).
+		 *
+		 * There are occasions when we get a half changed mailbox,
+		 * which this check catches for a handle & id mismatch.  If the
+		 * handle and id do correspond, the worst case is that we
+		 * completely lost the old MDL, but pick up the new MDL
+		 * early (but the new mdl_ack is guaranteed to be good in this
+		 * case as the firmware wouldn't point us to a new mdl_ack until
+		 * it's filled in).
+		 *
+		 * cx18_queue_get_mdl() will detect the lost MDLs
+		 * and send them back to q_free for fw rotation eventually.
+		 */
+		if ((order->flags & CX18_F_EWO_MB_STALE_UPON_RECEIPT) &&
+		    !(id >= s->mdl_base_idx &&
+		      id < (s->mdl_base_idx + s->buffers))) {
+			CX18_WARN("Fell behind! Ignoring stale mailbox with "
+				  " inconsistent data. Lost MDL for mailbox "
+				  "seq no %d\n", mb->request);
+			break;
+		}
+		mdl = cx18_queue_get_mdl(s, id, mdl_ack->data_used);
+
+		CX18_DEBUG_HI_DMA("DMA DONE for %s (MDL %d)\n", s->name, id);
+		if (mdl == NULL) {
+			CX18_WARN("Could not find MDL %d for stream %s\n",
+				  id, s->name);
+			continue;
+		}
+
+		CX18_DEBUG_HI_DMA("%s recv bytesused = %d\n",
+				  s->name, mdl->bytesused);
+
+		if (s->type == CX18_ENC_STREAM_TYPE_TS) {
+			cx18_mdl_send_to_dvb(s, mdl);
+			cx18_enqueue(s, mdl, &s->q_free);
+		} else if (s->type == CX18_ENC_STREAM_TYPE_PCM) {
+			/* Pass the data to cx18-alsa */
+			if (cx->pcm_announce_callback != NULL) {
+				cx18_mdl_send_to_alsa(cx, s, mdl);
+				cx18_enqueue(s, mdl, &s->q_free);
+			} else {
+				cx18_enqueue(s, mdl, &s->q_full);
+			}
+		} else if (s->type == CX18_ENC_STREAM_TYPE_YUV) {
+			cx18_mdl_send_to_videobuf(s, mdl);
+			cx18_enqueue(s, mdl, &s->q_free);
+		} else {
+			cx18_enqueue(s, mdl, &s->q_full);
+			if (s->type == CX18_ENC_STREAM_TYPE_IDX)
+				cx18_stream_rotate_idx_mdls(cx);
+		}
+	}
+	/* Put as many MDLs as possible back into fw use */
+	cx18_stream_load_fw_queue(s);
+
+	wake_up(&cx->dma_waitq);
+	if (s->id != -1)
+		wake_up(&s->waitq);
+}
+
+static void epu_debug(struct cx18 *cx, struct cx18_in_work_order *order)
+{
+	char *p;
+	char *str = order->str;
+
+	CX18_DEBUG_INFO("%x %s\n", order->mb.args[0], str);
+	p = strchr(str, '.');
+	if (!test_bit(CX18_F_I_LOADED_FW, &cx->i_flags) && p && p > str)
+		CX18_INFO("FW version: %s\n", p - 1);
+}
+
+static void epu_cmd(struct cx18 *cx, struct cx18_in_work_order *order)
+{
+	switch (order->rpu) {
+	case CPU:
+	{
+		switch (order->mb.cmd) {
+		case CX18_EPU_DMA_DONE:
+			epu_dma_done(cx, order);
+			break;
+		case CX18_EPU_DEBUG:
+			epu_debug(cx, order);
+			break;
+		default:
+			CX18_WARN("Unknown CPU to EPU mailbox command %#0x\n",
+				  order->mb.cmd);
+			break;
+		}
+		break;
+	}
+	case APU:
+		CX18_WARN("Unknown APU to EPU mailbox command %#0x\n",
+			  order->mb.cmd);
+		break;
+	default:
+		break;
+	}
+}
+
+static
+void free_in_work_order(struct cx18 *cx, struct cx18_in_work_order *order)
+{
+	atomic_set(&order->pending, 0);
+}
+
+void cx18_in_work_handler(struct work_struct *work)
+{
+	struct cx18_in_work_order *order =
+			container_of(work, struct cx18_in_work_order, work);
+	struct cx18 *cx = order->cx;
+	epu_cmd(cx, order);
+	free_in_work_order(cx, order);
+}
+
+
+/*
+ * Functions that run in an interrupt handling context
+ */
+
+static void mb_ack_irq(struct cx18 *cx, struct cx18_in_work_order *order)
+{
+	struct cx18_mailbox __iomem *ack_mb;
+	u32 ack_irq, req;
+
+	switch (order->rpu) {
+	case APU:
+		ack_irq = IRQ_EPU_TO_APU_ACK;
+		ack_mb = &cx->scb->apu2epu_mb;
+		break;
+	case CPU:
+		ack_irq = IRQ_EPU_TO_CPU_ACK;
+		ack_mb = &cx->scb->cpu2epu_mb;
+		break;
+	default:
+		CX18_WARN("Unhandled RPU (%d) for command %x ack\n",
+			  order->rpu, order->mb.cmd);
+		return;
+	}
+
+	req = order->mb.request;
+	/* Don't ack if the RPU has gotten impatient and timed us out */
+	if (req != cx18_readl(cx, &ack_mb->request) ||
+	    req == cx18_readl(cx, &ack_mb->ack)) {
+		CX18_DEBUG_WARN("Possibly falling behind: %s self-ack'ed our "
+				"incoming %s to EPU mailbox (sequence no. %u) "
+				"while processing\n",
+				rpu_str[order->rpu], rpu_str[order->rpu], req);
+		order->flags |= CX18_F_EWO_MB_STALE_WHILE_PROC;
+		return;
+	}
+	cx18_writel(cx, req, &ack_mb->ack);
+	cx18_write_reg_expect(cx, ack_irq, SW2_INT_SET, ack_irq, ack_irq);
+	return;
+}
+
+static int epu_dma_done_irq(struct cx18 *cx, struct cx18_in_work_order *order)
+{
+	u32 handle, mdl_ack_offset, mdl_ack_count;
+	struct cx18_mailbox *mb;
+	int i;
+
+	mb = &order->mb;
+	handle = mb->args[0];
+	mdl_ack_offset = mb->args[1];
+	mdl_ack_count = mb->args[2];
+
+	if (handle == CX18_INVALID_TASK_HANDLE ||
+	    mdl_ack_count == 0 || mdl_ack_count > CX18_MAX_MDL_ACKS) {
+		if ((order->flags & CX18_F_EWO_MB_STALE) == 0)
+			mb_ack_irq(cx, order);
+		return -1;
+	}
+
+	for (i = 0; i < sizeof(struct cx18_mdl_ack) * mdl_ack_count; i += sizeof(u32))
+		((u32 *)order->mdl_ack)[i / sizeof(u32)] =
+			cx18_readl(cx, cx->enc_mem + mdl_ack_offset + i);
+
+	if ((order->flags & CX18_F_EWO_MB_STALE) == 0)
+		mb_ack_irq(cx, order);
+	return 1;
+}
+
+static
+int epu_debug_irq(struct cx18 *cx, struct cx18_in_work_order *order)
+{
+	u32 str_offset;
+	char *str = order->str;
+
+	str[0] = '\0';
+	str_offset = order->mb.args[1];
+	if (str_offset) {
+		cx18_setup_page(cx, str_offset);
+		cx18_memcpy_fromio(cx, str, cx->enc_mem + str_offset, 252);
+		str[252] = '\0';
+		cx18_setup_page(cx, SCB_OFFSET);
+	}
+
+	if ((order->flags & CX18_F_EWO_MB_STALE) == 0)
+		mb_ack_irq(cx, order);
+
+	return str_offset ? 1 : 0;
+}
+
+static inline
+int epu_cmd_irq(struct cx18 *cx, struct cx18_in_work_order *order)
+{
+	int ret = -1;
+
+	switch (order->rpu) {
+	case CPU:
+	{
+		switch (order->mb.cmd) {
+		case CX18_EPU_DMA_DONE:
+			ret = epu_dma_done_irq(cx, order);
+			break;
+		case CX18_EPU_DEBUG:
+			ret = epu_debug_irq(cx, order);
+			break;
+		default:
+			CX18_WARN("Unknown CPU to EPU mailbox command %#0x\n",
+				  order->mb.cmd);
+			break;
+		}
+		break;
+	}
+	case APU:
+		CX18_WARN("Unknown APU to EPU mailbox command %#0x\n",
+			  order->mb.cmd);
+		break;
+	default:
+		break;
+	}
+	return ret;
+}
+
+static inline
+struct cx18_in_work_order *alloc_in_work_order_irq(struct cx18 *cx)
+{
+	int i;
+	struct cx18_in_work_order *order = NULL;
+
+	for (i = 0; i < CX18_MAX_IN_WORK_ORDERS; i++) {
+		/*
+		 * We only need "pending" atomic to inspect its contents,
+		 * and need not do a check and set because:
+		 * 1. Any work handler thread only clears "pending" and only
+		 * on one, particular work order at a time, per handler thread.
+		 * 2. "pending" is only set here, and we're serialized because
+		 * we're called in an IRQ handler context.
+		 */
+		if (atomic_read(&cx->in_work_order[i].pending) == 0) {
+			order = &cx->in_work_order[i];
+			atomic_set(&order->pending, 1);
+			break;
+		}
+	}
+	return order;
+}
+
+void cx18_api_epu_cmd_irq(struct cx18 *cx, int rpu)
+{
+	struct cx18_mailbox __iomem *mb;
+	struct cx18_mailbox *order_mb;
+	struct cx18_in_work_order *order;
+	int submit;
+	int i;
+
+	switch (rpu) {
+	case CPU:
+		mb = &cx->scb->cpu2epu_mb;
+		break;
+	case APU:
+		mb = &cx->scb->apu2epu_mb;
+		break;
+	default:
+		return;
+	}
+
+	order = alloc_in_work_order_irq(cx);
+	if (order == NULL) {
+		CX18_WARN("Unable to find blank work order form to schedule "
+			  "incoming mailbox command processing\n");
+		return;
+	}
+
+	order->flags = 0;
+	order->rpu = rpu;
+	order_mb = &order->mb;
+
+	/* mb->cmd and mb->args[0] through mb->args[2] */
+	for (i = 0; i < 4; i++)
+		(&order_mb->cmd)[i] = cx18_readl(cx, &mb->cmd + i);
+
+	/* mb->request and mb->ack.  N.B. we want to read mb->ack last */
+	for (i = 0; i < 2; i++)
+		(&order_mb->request)[i] = cx18_readl(cx, &mb->request + i);
+
+	if (order_mb->request == order_mb->ack) {
+		CX18_DEBUG_WARN("Possibly falling behind: %s self-ack'ed our "
+				"incoming %s to EPU mailbox (sequence no. %u)"
+				"\n",
+				rpu_str[rpu], rpu_str[rpu], order_mb->request);
+		if (cx18_debug & CX18_DBGFLG_WARN)
+			dump_mb(cx, order_mb, "incoming");
+		order->flags = CX18_F_EWO_MB_STALE_UPON_RECEIPT;
+	}
+
+	/*
+	 * Individual EPU command processing is responsible for ack-ing
+	 * a non-stale mailbox as soon as possible
+	 */
+	submit = epu_cmd_irq(cx, order);
+	if (submit > 0) {
+		queue_work(cx->in_work_queue, &order->work);
+	}
+}
+
+
+/*
+ * Functions called from a non-interrupt, non work_queue context
+ */
+
+static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[])
+{
+	const struct cx18_api_info *info = find_api_info(cmd);
+	u32 irq, req, ack, err;
+	struct cx18_mailbox __iomem *mb;
+	wait_queue_head_t *waitq;
+	struct mutex *mb_lock;
+	unsigned long int t0, timeout, ret;
+	int i;
+	char argstr[MAX_MB_ARGUMENTS*11+1];
+	DEFINE_WAIT(w);
+
+	if (info == NULL) {
+		CX18_WARN("unknown cmd %x\n", cmd);
+		return -EINVAL;
+	}
+
+	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:
+		waitq = &cx->mb_apu_waitq;
+		mb_lock = &cx->epu2apu_mb_lock;
+		irq = IRQ_EPU_TO_APU;
+		mb = &cx->scb->epu2apu_mb;
+		break;
+	case CPU:
+		waitq = &cx->mb_cpu_waitq;
+		mb_lock = &cx->epu2cpu_mb_lock;
+		irq = IRQ_EPU_TO_CPU;
+		mb = &cx->scb->epu2cpu_mb;
+		break;
+	default:
+		CX18_WARN("Unknown RPU (%d) for API call\n", info->rpu);
+		return -EINVAL;
+	}
+
+	mutex_lock(mb_lock);
+	/*
+	 * Wait for an in-use mailbox to complete
+	 *
+	 * If the XPU is responding with Ack's, the mailbox shouldn't be in
+	 * a busy state, since we serialize access to it on our end.
+	 *
+	 * If the wait for ack after sending a previous command was interrupted
+	 * by a signal, we may get here and find a busy mailbox.  After waiting,
+	 * mark it "not busy" from our end, if the XPU hasn't ack'ed it still.
+	 */
+	req = cx18_readl(cx, &mb->request);
+	timeout = msecs_to_jiffies(10);
+	ret = wait_event_timeout(*waitq,
+				 (ack = cx18_readl(cx, &mb->ack)) == req,
+				 timeout);
+	if (req != ack) {
+		/* waited long enough, make the mbox "not busy" from our end */
+		cx18_writel(cx, req, &mb->ack);
+		CX18_ERR("mbox was found stuck busy when setting up for %s; "
+			 "clearing busy and trying to proceed\n", info->name);
+	} else if (ret != timeout)
+		CX18_DEBUG_API("waited %u msecs for busy mbox to be acked\n",
+			       jiffies_to_msecs(timeout-ret));
+
+	/* Build the outgoing mailbox */
+	req = ((req & 0xfffffffe) == 0xfffffffe) ? 1 : req + 1;
+
+	cx18_writel(cx, cmd, &mb->cmd);
+	for (i = 0; i < args; i++)
+		cx18_writel(cx, data[i], &mb->args[i]);
+	cx18_writel(cx, 0, &mb->error);
+	cx18_writel(cx, req, &mb->request);
+	cx18_writel(cx, req - 1, &mb->ack); /* ensure ack & req are distinct */
+
+	/*
+	 * Notify the XPU and wait for it to send an Ack back
+	 */
+	timeout = msecs_to_jiffies((info->flags & API_FAST) ? 10 : 20);
+
+	CX18_DEBUG_HI_IRQ("sending interrupt SW1: %x to send %s\n",
+			  irq, info->name);
+
+	/* So we don't miss the wakeup, prepare to wait before notifying fw */
+	prepare_to_wait(waitq, &w, TASK_UNINTERRUPTIBLE);
+	cx18_write_reg_expect(cx, irq, SW1_INT_SET, irq, irq);
+
+	t0 = jiffies;
+	ack = cx18_readl(cx, &mb->ack);
+	if (ack != req) {
+		schedule_timeout(timeout);
+		ret = jiffies - t0;
+		ack = cx18_readl(cx, &mb->ack);
+	} else {
+		ret = jiffies - t0;
+	}
+
+	finish_wait(waitq, &w);
+
+	if (req != ack) {
+		mutex_unlock(mb_lock);
+		if (ret >= timeout) {
+			/* Timed out */
+			CX18_DEBUG_WARN("sending %s timed out waiting %d msecs "
+					"for RPU acknowledgement\n",
+					info->name, jiffies_to_msecs(ret));
+		} else {
+			CX18_DEBUG_WARN("woken up before mailbox ack was ready "
+					"after submitting %s to RPU.  only "
+					"waited %d msecs on req %u but awakened"
+					" with unmatched ack %u\n",
+					info->name,
+					jiffies_to_msecs(ret),
+					req, ack);
+		}
+		return -EINVAL;
+	}
+
+	if (ret >= timeout)
+		CX18_DEBUG_WARN("failed to be awakened upon RPU acknowledgment "
+				"sending %s; timed out waiting %d msecs\n",
+				info->name, jiffies_to_msecs(ret));
+	else
+		CX18_DEBUG_HI_API("waited %u msecs for %s to be acked\n",
+				  jiffies_to_msecs(ret), info->name);
+
+	/* Collect data returned by the XPU */
+	for (i = 0; i < MAX_MB_ARGUMENTS; i++)
+		data[i] = cx18_readl(cx, &mb->args[i]);
+	err = cx18_readl(cx, &mb->error);
+	mutex_unlock(mb_lock);
+
+	/*
+	 * Wait for XPU to perform extra actions for the caller in some cases.
+	 * e.g. CX18_CPU_DE_RELEASE_MDL will cause the CPU to send all MDLs
+	 * back in a burst shortly thereafter
+	 */
+	if (info->flags & API_SLOW)
+		cx18_msleep_timeout(300, 0);
+
+	if (err)
+		CX18_DEBUG_API("mailbox error %08x for command %s\n", err,
+				info->name);
+	return err ? -EIO : 0;
+}
+
+int cx18_api(struct cx18 *cx, u32 cmd, int args, u32 data[])
+{
+	return cx18_api_call(cx, cmd, args, data);
+}
+
+static int cx18_set_filter_param(struct cx18_stream *s)
+{
+	struct cx18 *cx = s->cx;
+	u32 mode;
+	int ret;
+
+	mode = (cx->filter_mode & 1) ? 2 : (cx->spatial_strength ? 1 : 0);
+	ret = cx18_vapi(cx, CX18_CPU_SET_FILTER_PARAM, 4,
+			s->handle, 1, mode, cx->spatial_strength);
+	mode = (cx->filter_mode & 2) ? 2 : (cx->temporal_strength ? 1 : 0);
+	ret = ret ? ret : cx18_vapi(cx, CX18_CPU_SET_FILTER_PARAM, 4,
+			s->handle, 0, mode, cx->temporal_strength);
+	ret = ret ? ret : cx18_vapi(cx, CX18_CPU_SET_FILTER_PARAM, 4,
+			s->handle, 2, cx->filter_mode >> 2, 0);
+	return ret;
+}
+
+int cx18_api_func(void *priv, u32 cmd, int in, int out,
+		u32 data[CX2341X_MBOX_MAX_DATA])
+{
+	struct cx18_stream *s = priv;
+	struct cx18 *cx = s->cx;
+
+	switch (cmd) {
+	case CX2341X_ENC_SET_OUTPUT_PORT:
+		return 0;
+	case CX2341X_ENC_SET_FRAME_RATE:
+		return cx18_vapi(cx, CX18_CPU_SET_VIDEO_IN, 6,
+				s->handle, 0, 0, 0, 0, data[0]);
+	case CX2341X_ENC_SET_FRAME_SIZE:
+		return cx18_vapi(cx, CX18_CPU_SET_VIDEO_RESOLUTION, 3,
+				s->handle, data[1], data[0]);
+	case CX2341X_ENC_SET_STREAM_TYPE:
+		return cx18_vapi(cx, CX18_CPU_SET_STREAM_OUTPUT_TYPE, 2,
+				s->handle, data[0]);
+	case CX2341X_ENC_SET_ASPECT_RATIO:
+		return cx18_vapi(cx, CX18_CPU_SET_ASPECT_RATIO, 2,
+				s->handle, data[0]);
+
+	case CX2341X_ENC_SET_GOP_PROPERTIES:
+		return cx18_vapi(cx, CX18_CPU_SET_GOP_STRUCTURE, 3,
+				s->handle, data[0], data[1]);
+	case CX2341X_ENC_SET_GOP_CLOSURE:
+		return 0;
+	case CX2341X_ENC_SET_AUDIO_PROPERTIES:
+		return cx18_vapi(cx, CX18_CPU_SET_AUDIO_PARAMETERS, 2,
+				s->handle, data[0]);
+	case CX2341X_ENC_MUTE_AUDIO:
+		return cx18_vapi(cx, CX18_CPU_SET_AUDIO_MUTE, 2,
+				s->handle, data[0]);
+	case CX2341X_ENC_SET_BIT_RATE:
+		return cx18_vapi(cx, CX18_CPU_SET_VIDEO_RATE, 5,
+				s->handle, data[0], data[1], data[2], data[3]);
+	case CX2341X_ENC_MUTE_VIDEO:
+		return cx18_vapi(cx, CX18_CPU_SET_VIDEO_MUTE, 2,
+				s->handle, data[0]);
+	case CX2341X_ENC_SET_FRAME_DROP_RATE:
+		return cx18_vapi(cx, CX18_CPU_SET_SKIP_INPUT_FRAME, 2,
+				s->handle, data[0]);
+	case CX2341X_ENC_MISC:
+		return cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 4,
+				s->handle, data[0], data[1], data[2]);
+	case CX2341X_ENC_SET_DNR_FILTER_MODE:
+		cx->filter_mode = (data[0] & 3) | (data[1] << 2);
+		return cx18_set_filter_param(s);
+	case CX2341X_ENC_SET_DNR_FILTER_PROPS:
+		cx->spatial_strength = data[0];
+		cx->temporal_strength = data[1];
+		return cx18_set_filter_param(s);
+	case CX2341X_ENC_SET_SPATIAL_FILTER_TYPE:
+		return cx18_vapi(cx, CX18_CPU_SET_SPATIAL_FILTER_TYPE, 3,
+				s->handle, data[0], data[1]);
+	case CX2341X_ENC_SET_CORING_LEVELS:
+		return cx18_vapi(cx, CX18_CPU_SET_MEDIAN_CORING, 5,
+				s->handle, data[0], data[1], data[2], data[3]);
+	}
+	CX18_WARN("Unknown cmd %x\n", cmd);
+	return 0;
+}
+
+int cx18_vapi_result(struct cx18 *cx, u32 data[MAX_MB_ARGUMENTS],
+		u32 cmd, int args, ...)
+{
+	va_list ap;
+	int i;
+
+	va_start(ap, args);
+	for (i = 0; i < args; i++)
+		data[i] = va_arg(ap, u32);
+	va_end(ap);
+	return cx18_api(cx, cmd, args, data);
+}
+
+int cx18_vapi(struct cx18 *cx, u32 cmd, int args, ...)
+{
+	u32 data[MAX_MB_ARGUMENTS];
+	va_list ap;
+	int i;
+
+	if (cx == NULL) {
+		CX18_ERR("cx == NULL (cmd=%x)\n", cmd);
+		return 0;
+	}
+	if (args > MAX_MB_ARGUMENTS) {
+		CX18_ERR("args too big (cmd=%x)\n", cmd);
+		args = MAX_MB_ARGUMENTS;
+	}
+	va_start(ap, args);
+	for (i = 0; i < args; i++)
+		data[i] = va_arg(ap, u32);
+	va_end(ap);
+	return cx18_api(cx, cmd, args, data);
+}
diff --git a/drivers/media/pci/cx18/cx18-mailbox.h b/drivers/media/pci/cx18/cx18-mailbox.h
new file mode 100644
index 0000000..b63fdfa
--- /dev/null
+++ b/drivers/media/pci/cx18/cx18-mailbox.h
@@ -0,0 +1,95 @@
+/*
+ *  cx18 mailbox functions
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.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 program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public 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 _CX18_MAILBOX_H_
+#define _CX18_MAILBOX_H_
+
+/* mailbox max args */
+#define MAX_MB_ARGUMENTS 6
+/* compatibility, should be same as the define in cx2341x.h */
+#define CX2341X_MBOX_MAX_DATA 16
+
+#define MB_RESERVED_HANDLE_0 0
+#define MB_RESERVED_HANDLE_1 0xFFFFFFFF
+
+#define APU 0
+#define CPU 1
+#define EPU 2
+#define HPU 3
+
+struct cx18;
+
+/*
+ * This structure is used by CPU to provide completed MDL & buffers information.
+ * Its structure is dictated by the layout of the SCB, required by the
+ * firmware, but its definition needs to be here, instead of in cx18-scb.h,
+ * for mailbox work order scheduling
+ */
+struct cx18_mdl_ack {
+    u32 id;        /* ID of a completed MDL */
+    u32 data_used; /* Total data filled in the MDL with 'id' */
+};
+
+/* The cx18_mailbox struct is the mailbox structure which is used for passing
+   messages between processors */
+struct cx18_mailbox {
+    /* The sender sets a handle in 'request' after he fills the command. The
+       'request' should be different than 'ack'. The sender, also, generates
+       an interrupt on XPU2YPU_irq where XPU is the sender and YPU is the
+       receiver. */
+    u32       request;
+    /* The receiver detects a new command when 'req' is different than 'ack'.
+       He sets 'ack' to the same value as 'req' to clear the command. He, also,
+       generates an interrupt on YPU2XPU_irq where XPU is the sender and YPU
+       is the receiver. */
+    u32       ack;
+    u32       reserved[6];
+    /* 'cmd' identifies the command. The list of these commands are in
+       cx23418.h */
+    u32       cmd;
+    /* Each command can have up to 6 arguments */
+    u32       args[MAX_MB_ARGUMENTS];
+    /* The return code can be one of the codes in the file cx23418.h. If the
+       command is completed successfully, the error will be ERR_SYS_SUCCESS.
+       If it is pending, the code is ERR_SYS_PENDING. If it failed, the error
+       code would indicate the task from which the error originated and will
+       be one of the errors in cx23418.h. In that case, the following
+       applies ((error & 0xff) != 0).
+       If the command is pending, the return will be passed in a MB from the
+       receiver to the sender. 'req' will be returned in args[0] */
+    u32       error;
+};
+
+struct cx18_stream;
+
+int cx18_api(struct cx18 *cx, u32 cmd, int args, u32 data[]);
+int cx18_vapi_result(struct cx18 *cx, u32 data[MAX_MB_ARGUMENTS], u32 cmd,
+		int args, ...);
+int cx18_vapi(struct cx18 *cx, u32 cmd, int args, ...);
+int cx18_api_func(void *priv, u32 cmd, int in, int out,
+		u32 data[CX2341X_MBOX_MAX_DATA]);
+
+void cx18_api_epu_cmd_irq(struct cx18 *cx, int rpu);
+
+void cx18_in_work_handler(struct work_struct *work);
+
+#endif
diff --git a/drivers/media/pci/cx18/cx18-queue.c b/drivers/media/pci/cx18/cx18-queue.c
new file mode 100644
index 0000000..8884537
--- /dev/null
+++ b/drivers/media/pci/cx18/cx18-queue.c
@@ -0,0 +1,443 @@
+/*
+ *  cx18 buffer queues
+ *
+ *  Derived from ivtv-queue.c
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.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 program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public 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 "cx18-driver.h"
+#include "cx18-queue.h"
+#include "cx18-streams.h"
+#include "cx18-scb.h"
+#include "cx18-io.h"
+
+void cx18_buf_swap(struct cx18_buffer *buf)
+{
+	int i;
+
+	for (i = 0; i < buf->bytesused; i += 4)
+		swab32s((u32 *)(buf->buf + i));
+}
+
+void _cx18_mdl_swap(struct cx18_mdl *mdl)
+{
+	struct cx18_buffer *buf;
+
+	list_for_each_entry(buf, &mdl->buf_list, list) {
+		if (buf->bytesused == 0)
+			break;
+		cx18_buf_swap(buf);
+	}
+}
+
+void cx18_queue_init(struct cx18_queue *q)
+{
+	INIT_LIST_HEAD(&q->list);
+	atomic_set(&q->depth, 0);
+	q->bytesused = 0;
+}
+
+struct cx18_queue *_cx18_enqueue(struct cx18_stream *s, struct cx18_mdl *mdl,
+				 struct cx18_queue *q, int to_front)
+{
+	/* clear the mdl if it is not to be enqueued to the full queue */
+	if (q != &s->q_full) {
+		mdl->bytesused = 0;
+		mdl->readpos = 0;
+		mdl->m_flags = 0;
+		mdl->skipped = 0;
+		mdl->curr_buf = NULL;
+	}
+
+	/* q_busy is restricted to a max buffer count imposed by firmware */
+	if (q == &s->q_busy &&
+	    atomic_read(&q->depth) >= CX18_MAX_FW_MDLS_PER_STREAM)
+		q = &s->q_free;
+
+	spin_lock(&q->lock);
+
+	if (to_front)
+		list_add(&mdl->list, &q->list); /* LIFO */
+	else
+		list_add_tail(&mdl->list, &q->list); /* FIFO */
+	q->bytesused += mdl->bytesused - mdl->readpos;
+	atomic_inc(&q->depth);
+
+	spin_unlock(&q->lock);
+	return q;
+}
+
+struct cx18_mdl *cx18_dequeue(struct cx18_stream *s, struct cx18_queue *q)
+{
+	struct cx18_mdl *mdl = NULL;
+
+	spin_lock(&q->lock);
+	if (!list_empty(&q->list)) {
+		mdl = list_first_entry(&q->list, struct cx18_mdl, list);
+		list_del_init(&mdl->list);
+		q->bytesused -= mdl->bytesused - mdl->readpos;
+		mdl->skipped = 0;
+		atomic_dec(&q->depth);
+	}
+	spin_unlock(&q->lock);
+	return mdl;
+}
+
+static void _cx18_mdl_update_bufs_for_cpu(struct cx18_stream *s,
+					  struct cx18_mdl *mdl)
+{
+	struct cx18_buffer *buf;
+	u32 buf_size = s->buf_size;
+	u32 bytesused = mdl->bytesused;
+
+	list_for_each_entry(buf, &mdl->buf_list, list) {
+		buf->readpos = 0;
+		if (bytesused >= buf_size) {
+			buf->bytesused = buf_size;
+			bytesused -= buf_size;
+		} else {
+			buf->bytesused = bytesused;
+			bytesused = 0;
+		}
+		cx18_buf_sync_for_cpu(s, buf);
+	}
+}
+
+static inline void cx18_mdl_update_bufs_for_cpu(struct cx18_stream *s,
+						struct cx18_mdl *mdl)
+{
+	struct cx18_buffer *buf;
+
+	if (list_is_singular(&mdl->buf_list)) {
+		buf = list_first_entry(&mdl->buf_list, struct cx18_buffer,
+				       list);
+		buf->bytesused = mdl->bytesused;
+		buf->readpos = 0;
+		cx18_buf_sync_for_cpu(s, buf);
+	} else {
+		_cx18_mdl_update_bufs_for_cpu(s, mdl);
+	}
+}
+
+struct cx18_mdl *cx18_queue_get_mdl(struct cx18_stream *s, u32 id,
+	u32 bytesused)
+{
+	struct cx18 *cx = s->cx;
+	struct cx18_mdl *mdl;
+	struct cx18_mdl *tmp;
+	struct cx18_mdl *ret = NULL;
+	LIST_HEAD(sweep_up);
+
+	/*
+	 * We don't have to acquire multiple q locks here, because we are
+	 * serialized by the single threaded work handler.
+	 * MDLs from the firmware will thus remain in order as
+	 * they are moved from q_busy to q_full or to the dvb ring buffer.
+	 */
+	spin_lock(&s->q_busy.lock);
+	list_for_each_entry_safe(mdl, tmp, &s->q_busy.list, list) {
+		/*
+		 * We should find what the firmware told us is done,
+		 * right at the front of the queue.  If we don't, we likely have
+		 * missed an mdl done message from the firmware.
+		 * Once we skip an mdl repeatedly, relative to the size of
+		 * q_busy, we have high confidence we've missed it.
+		 */
+		if (mdl->id != id) {
+			mdl->skipped++;
+			if (mdl->skipped >= atomic_read(&s->q_busy.depth)-1) {
+				/* mdl must have fallen out of rotation */
+				CX18_WARN("Skipped %s, MDL %d, %d "
+					  "times - it must have dropped out of "
+					  "rotation\n", s->name, mdl->id,
+					  mdl->skipped);
+				/* Sweep it up to put it back into rotation */
+				list_move_tail(&mdl->list, &sweep_up);
+				atomic_dec(&s->q_busy.depth);
+			}
+			continue;
+		}
+		/*
+		 * We pull the desired mdl off of the queue here.  Something
+		 * will have to put it back on a queue later.
+		 */
+		list_del_init(&mdl->list);
+		atomic_dec(&s->q_busy.depth);
+		ret = mdl;
+		break;
+	}
+	spin_unlock(&s->q_busy.lock);
+
+	/*
+	 * We found the mdl for which we were looking.  Get it ready for
+	 * the caller to put on q_full or in the dvb ring buffer.
+	 */
+	if (ret != NULL) {
+		ret->bytesused = bytesused;
+		ret->skipped = 0;
+		/* 0'ed readpos, m_flags & curr_buf when mdl went on q_busy */
+		cx18_mdl_update_bufs_for_cpu(s, ret);
+		if (s->type != CX18_ENC_STREAM_TYPE_TS)
+			set_bit(CX18_F_M_NEED_SWAP, &ret->m_flags);
+	}
+
+	/* Put any mdls the firmware is ignoring back into normal rotation */
+	list_for_each_entry_safe(mdl, tmp, &sweep_up, list) {
+		list_del_init(&mdl->list);
+		cx18_enqueue(s, mdl, &s->q_free);
+	}
+	return ret;
+}
+
+/* Move all mdls of a queue, while flushing the mdl */
+static void cx18_queue_flush(struct cx18_stream *s,
+			     struct cx18_queue *q_src, struct cx18_queue *q_dst)
+{
+	struct cx18_mdl *mdl;
+
+	/* It only makes sense to flush to q_free or q_idle */
+	if (q_src == q_dst || q_dst == &s->q_full || q_dst == &s->q_busy)
+		return;
+
+	spin_lock(&q_src->lock);
+	spin_lock(&q_dst->lock);
+	while (!list_empty(&q_src->list)) {
+		mdl = list_first_entry(&q_src->list, struct cx18_mdl, list);
+		list_move_tail(&mdl->list, &q_dst->list);
+		mdl->bytesused = 0;
+		mdl->readpos = 0;
+		mdl->m_flags = 0;
+		mdl->skipped = 0;
+		mdl->curr_buf = NULL;
+		atomic_inc(&q_dst->depth);
+	}
+	cx18_queue_init(q_src);
+	spin_unlock(&q_src->lock);
+	spin_unlock(&q_dst->lock);
+}
+
+void cx18_flush_queues(struct cx18_stream *s)
+{
+	cx18_queue_flush(s, &s->q_busy, &s->q_free);
+	cx18_queue_flush(s, &s->q_full, &s->q_free);
+}
+
+/*
+ * Note, s->buf_pool is not protected by a lock,
+ * the stream better not have *anything* going on when calling this
+ */
+void cx18_unload_queues(struct cx18_stream *s)
+{
+	struct cx18_queue *q_idle = &s->q_idle;
+	struct cx18_mdl *mdl;
+	struct cx18_buffer *buf;
+
+	/* Move all MDLS to q_idle */
+	cx18_queue_flush(s, &s->q_busy, q_idle);
+	cx18_queue_flush(s, &s->q_full, q_idle);
+	cx18_queue_flush(s, &s->q_free, q_idle);
+
+	/* Reset MDL id's and move all buffers back to the stream's buf_pool */
+	spin_lock(&q_idle->lock);
+	list_for_each_entry(mdl, &q_idle->list, list) {
+		while (!list_empty(&mdl->buf_list)) {
+			buf = list_first_entry(&mdl->buf_list,
+					       struct cx18_buffer, list);
+			list_move_tail(&buf->list, &s->buf_pool);
+			buf->bytesused = 0;
+			buf->readpos = 0;
+		}
+		mdl->id = s->mdl_base_idx; /* reset id to a "safe" value */
+		/* all other mdl fields were cleared by cx18_queue_flush() */
+	}
+	spin_unlock(&q_idle->lock);
+}
+
+/*
+ * Note, s->buf_pool is not protected by a lock,
+ * the stream better not have *anything* going on when calling this
+ */
+void cx18_load_queues(struct cx18_stream *s)
+{
+	struct cx18 *cx = s->cx;
+	struct cx18_mdl *mdl;
+	struct cx18_buffer *buf;
+	int mdl_id;
+	int i;
+	u32 partial_buf_size;
+
+	/*
+	 * Attach buffers to MDLs, give the MDLs ids, and add MDLs to q_free
+	 * Excess MDLs are left on q_idle
+	 * Excess buffers are left in buf_pool and/or on an MDL in q_idle
+	 */
+	mdl_id = s->mdl_base_idx;
+	for (mdl = cx18_dequeue(s, &s->q_idle), i = s->bufs_per_mdl;
+	     mdl != NULL && i == s->bufs_per_mdl;
+	     mdl = cx18_dequeue(s, &s->q_idle)) {
+
+		mdl->id = mdl_id;
+
+		for (i = 0; i < s->bufs_per_mdl; i++) {
+			if (list_empty(&s->buf_pool))
+				break;
+
+			buf = list_first_entry(&s->buf_pool, struct cx18_buffer,
+					       list);
+			list_move_tail(&buf->list, &mdl->buf_list);
+
+			/* update the firmware's MDL array with this buffer */
+			cx18_writel(cx, buf->dma_handle,
+				    &cx->scb->cpu_mdl[mdl_id + i].paddr);
+			cx18_writel(cx, s->buf_size,
+				    &cx->scb->cpu_mdl[mdl_id + i].length);
+		}
+
+		if (i == s->bufs_per_mdl) {
+			/*
+			 * The encoder doesn't honor s->mdl_size.  So in the
+			 * case of a non-integral number of buffers to meet
+			 * mdl_size, we lie about the size of the last buffer
+			 * in the MDL to get the encoder to really only send
+			 * us mdl_size bytes per MDL transfer.
+			 */
+			partial_buf_size = s->mdl_size % s->buf_size;
+			if (partial_buf_size) {
+				cx18_writel(cx, partial_buf_size,
+				      &cx->scb->cpu_mdl[mdl_id + i - 1].length);
+			}
+			cx18_enqueue(s, mdl, &s->q_free);
+		} else {
+			/* Not enough buffers for this MDL; we won't use it */
+			cx18_push(s, mdl, &s->q_idle);
+		}
+		mdl_id += i;
+	}
+}
+
+void _cx18_mdl_sync_for_device(struct cx18_stream *s, struct cx18_mdl *mdl)
+{
+	int dma = s->dma;
+	u32 buf_size = s->buf_size;
+	struct pci_dev *pci_dev = s->cx->pci_dev;
+	struct cx18_buffer *buf;
+
+	list_for_each_entry(buf, &mdl->buf_list, list)
+		pci_dma_sync_single_for_device(pci_dev, buf->dma_handle,
+					       buf_size, dma);
+}
+
+int cx18_stream_alloc(struct cx18_stream *s)
+{
+	struct cx18 *cx = s->cx;
+	int i;
+
+	if (s->buffers == 0)
+		return 0;
+
+	CX18_DEBUG_INFO("Allocate %s stream: %d x %d buffers "
+			"(%d.%02d kB total)\n",
+		s->name, s->buffers, s->buf_size,
+		s->buffers * s->buf_size / 1024,
+		(s->buffers * s->buf_size * 100 / 1024) % 100);
+
+	if (((char __iomem *)&cx->scb->cpu_mdl[cx->free_mdl_idx + s->buffers] -
+				(char __iomem *)cx->scb) > SCB_RESERVED_SIZE) {
+		unsigned bufsz = (((char __iomem *)cx->scb) + SCB_RESERVED_SIZE -
+					((char __iomem *)cx->scb->cpu_mdl));
+
+		CX18_ERR("Too many buffers, cannot fit in SCB area\n");
+		CX18_ERR("Max buffers = %zd\n",
+			bufsz / sizeof(struct cx18_mdl_ent));
+		return -ENOMEM;
+	}
+
+	s->mdl_base_idx = cx->free_mdl_idx;
+
+	/* allocate stream buffers and MDLs */
+	for (i = 0; i < s->buffers; i++) {
+		struct cx18_mdl *mdl;
+		struct cx18_buffer *buf;
+
+		/* 1 MDL per buffer to handle the worst & also default case */
+		mdl = kzalloc(sizeof(struct cx18_mdl), GFP_KERNEL|__GFP_NOWARN);
+		if (mdl == NULL)
+			break;
+
+		buf = kzalloc(sizeof(struct cx18_buffer),
+				GFP_KERNEL|__GFP_NOWARN);
+		if (buf == NULL) {
+			kfree(mdl);
+			break;
+		}
+
+		buf->buf = kmalloc(s->buf_size, GFP_KERNEL|__GFP_NOWARN);
+		if (buf->buf == NULL) {
+			kfree(mdl);
+			kfree(buf);
+			break;
+		}
+
+		INIT_LIST_HEAD(&mdl->list);
+		INIT_LIST_HEAD(&mdl->buf_list);
+		mdl->id = s->mdl_base_idx; /* a somewhat safe value */
+		cx18_enqueue(s, mdl, &s->q_idle);
+
+		INIT_LIST_HEAD(&buf->list);
+		buf->dma_handle = pci_map_single(s->cx->pci_dev,
+				buf->buf, s->buf_size, s->dma);
+		cx18_buf_sync_for_cpu(s, buf);
+		list_add_tail(&buf->list, &s->buf_pool);
+	}
+	if (i == s->buffers) {
+		cx->free_mdl_idx += s->buffers;
+		return 0;
+	}
+	CX18_ERR("Couldn't allocate buffers for %s stream\n", s->name);
+	cx18_stream_free(s);
+	return -ENOMEM;
+}
+
+void cx18_stream_free(struct cx18_stream *s)
+{
+	struct cx18_mdl *mdl;
+	struct cx18_buffer *buf;
+	struct cx18 *cx = s->cx;
+
+	CX18_DEBUG_INFO("Deallocating buffers for %s stream\n", s->name);
+
+	/* move all buffers to buf_pool and all MDLs to q_idle */
+	cx18_unload_queues(s);
+
+	/* empty q_idle */
+	while ((mdl = cx18_dequeue(s, &s->q_idle)))
+		kfree(mdl);
+
+	/* empty buf_pool */
+	while (!list_empty(&s->buf_pool)) {
+		buf = list_first_entry(&s->buf_pool, struct cx18_buffer, list);
+		list_del_init(&buf->list);
+
+		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/pci/cx18/cx18-queue.h b/drivers/media/pci/cx18/cx18-queue.h
new file mode 100644
index 0000000..4201ddc
--- /dev/null
+++ b/drivers/media/pci/cx18/cx18-queue.h
@@ -0,0 +1,98 @@
+/*
+ *  cx18 buffer queues
+ *
+ *  Derived from ivtv-queue.h
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.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 program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public 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 CX18_DMA_UNMAPPED	((u32) -1)
+
+/* cx18_buffer utility functions */
+
+static inline void cx18_buf_sync_for_cpu(struct cx18_stream *s,
+	struct cx18_buffer *buf)
+{
+	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->pci_dev, buf->dma_handle,
+				s->buf_size, s->dma);
+}
+
+void _cx18_mdl_sync_for_device(struct cx18_stream *s, struct cx18_mdl *mdl);
+
+static inline void cx18_mdl_sync_for_device(struct cx18_stream *s,
+					    struct cx18_mdl *mdl)
+{
+	if (list_is_singular(&mdl->buf_list))
+		cx18_buf_sync_for_device(s, list_first_entry(&mdl->buf_list,
+							     struct cx18_buffer,
+							     list));
+	else
+		_cx18_mdl_sync_for_device(s, mdl);
+}
+
+void cx18_buf_swap(struct cx18_buffer *buf);
+void _cx18_mdl_swap(struct cx18_mdl *mdl);
+
+static inline void cx18_mdl_swap(struct cx18_mdl *mdl)
+{
+	if (list_is_singular(&mdl->buf_list))
+		cx18_buf_swap(list_first_entry(&mdl->buf_list,
+					       struct cx18_buffer, list));
+	else
+		_cx18_mdl_swap(mdl);
+}
+
+/* cx18_queue utility functions */
+struct cx18_queue *_cx18_enqueue(struct cx18_stream *s, struct cx18_mdl *mdl,
+				 struct cx18_queue *q, int to_front);
+
+static inline
+struct cx18_queue *cx18_enqueue(struct cx18_stream *s, struct cx18_mdl *mdl,
+				struct cx18_queue *q)
+{
+	return _cx18_enqueue(s, mdl, q, 0); /* FIFO */
+}
+
+static inline
+struct cx18_queue *cx18_push(struct cx18_stream *s, struct cx18_mdl *mdl,
+			     struct cx18_queue *q)
+{
+	return _cx18_enqueue(s, mdl, q, 1); /* LIFO */
+}
+
+void cx18_queue_init(struct cx18_queue *q);
+struct cx18_mdl *cx18_dequeue(struct cx18_stream *s, struct cx18_queue *q);
+struct cx18_mdl *cx18_queue_get_mdl(struct cx18_stream *s, u32 id,
+	u32 bytesused);
+void cx18_flush_queues(struct cx18_stream *s);
+
+/* queue MDL reconfiguration helpers */
+void cx18_unload_queues(struct cx18_stream *s);
+void cx18_load_queues(struct cx18_stream *s);
+
+/* cx18_stream utility functions */
+int cx18_stream_alloc(struct cx18_stream *s);
+void cx18_stream_free(struct cx18_stream *s);
diff --git a/drivers/media/pci/cx18/cx18-scb.c b/drivers/media/pci/cx18/cx18-scb.c
new file mode 100644
index 0000000..85cc596
--- /dev/null
+++ b/drivers/media/pci/cx18/cx18-scb.c
@@ -0,0 +1,122 @@
+/*
+ *  cx18 System Control Block initialization
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.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 program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public 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 "cx18-driver.h"
+#include "cx18-io.h"
+#include "cx18-scb.h"
+
+void cx18_init_scb(struct cx18 *cx)
+{
+	cx18_setup_page(cx, SCB_OFFSET);
+	cx18_memset_io(cx, cx->scb, 0, 0x10000);
+
+	cx18_writel(cx, IRQ_APU_TO_CPU,     &cx->scb->apu2cpu_irq);
+	cx18_writel(cx, IRQ_CPU_TO_APU_ACK, &cx->scb->cpu2apu_irq_ack);
+	cx18_writel(cx, IRQ_HPU_TO_CPU,     &cx->scb->hpu2cpu_irq);
+	cx18_writel(cx, IRQ_CPU_TO_HPU_ACK, &cx->scb->cpu2hpu_irq_ack);
+	cx18_writel(cx, IRQ_PPU_TO_CPU,     &cx->scb->ppu2cpu_irq);
+	cx18_writel(cx, IRQ_CPU_TO_PPU_ACK, &cx->scb->cpu2ppu_irq_ack);
+	cx18_writel(cx, IRQ_EPU_TO_CPU,     &cx->scb->epu2cpu_irq);
+	cx18_writel(cx, IRQ_CPU_TO_EPU_ACK, &cx->scb->cpu2epu_irq_ack);
+
+	cx18_writel(cx, IRQ_CPU_TO_APU,     &cx->scb->cpu2apu_irq);
+	cx18_writel(cx, IRQ_APU_TO_CPU_ACK, &cx->scb->apu2cpu_irq_ack);
+	cx18_writel(cx, IRQ_HPU_TO_APU,     &cx->scb->hpu2apu_irq);
+	cx18_writel(cx, IRQ_APU_TO_HPU_ACK, &cx->scb->apu2hpu_irq_ack);
+	cx18_writel(cx, IRQ_PPU_TO_APU,     &cx->scb->ppu2apu_irq);
+	cx18_writel(cx, IRQ_APU_TO_PPU_ACK, &cx->scb->apu2ppu_irq_ack);
+	cx18_writel(cx, IRQ_EPU_TO_APU,     &cx->scb->epu2apu_irq);
+	cx18_writel(cx, IRQ_APU_TO_EPU_ACK, &cx->scb->apu2epu_irq_ack);
+
+	cx18_writel(cx, IRQ_CPU_TO_HPU,     &cx->scb->cpu2hpu_irq);
+	cx18_writel(cx, IRQ_HPU_TO_CPU_ACK, &cx->scb->hpu2cpu_irq_ack);
+	cx18_writel(cx, IRQ_APU_TO_HPU,     &cx->scb->apu2hpu_irq);
+	cx18_writel(cx, IRQ_HPU_TO_APU_ACK, &cx->scb->hpu2apu_irq_ack);
+	cx18_writel(cx, IRQ_PPU_TO_HPU,     &cx->scb->ppu2hpu_irq);
+	cx18_writel(cx, IRQ_HPU_TO_PPU_ACK, &cx->scb->hpu2ppu_irq_ack);
+	cx18_writel(cx, IRQ_EPU_TO_HPU,     &cx->scb->epu2hpu_irq);
+	cx18_writel(cx, IRQ_HPU_TO_EPU_ACK, &cx->scb->hpu2epu_irq_ack);
+
+	cx18_writel(cx, IRQ_CPU_TO_PPU,     &cx->scb->cpu2ppu_irq);
+	cx18_writel(cx, IRQ_PPU_TO_CPU_ACK, &cx->scb->ppu2cpu_irq_ack);
+	cx18_writel(cx, IRQ_APU_TO_PPU,     &cx->scb->apu2ppu_irq);
+	cx18_writel(cx, IRQ_PPU_TO_APU_ACK, &cx->scb->ppu2apu_irq_ack);
+	cx18_writel(cx, IRQ_HPU_TO_PPU,     &cx->scb->hpu2ppu_irq);
+	cx18_writel(cx, IRQ_PPU_TO_HPU_ACK, &cx->scb->ppu2hpu_irq_ack);
+	cx18_writel(cx, IRQ_EPU_TO_PPU,     &cx->scb->epu2ppu_irq);
+	cx18_writel(cx, IRQ_PPU_TO_EPU_ACK, &cx->scb->ppu2epu_irq_ack);
+
+	cx18_writel(cx, IRQ_CPU_TO_EPU,     &cx->scb->cpu2epu_irq);
+	cx18_writel(cx, IRQ_EPU_TO_CPU_ACK, &cx->scb->epu2cpu_irq_ack);
+	cx18_writel(cx, IRQ_APU_TO_EPU,     &cx->scb->apu2epu_irq);
+	cx18_writel(cx, IRQ_EPU_TO_APU_ACK, &cx->scb->epu2apu_irq_ack);
+	cx18_writel(cx, IRQ_HPU_TO_EPU,     &cx->scb->hpu2epu_irq);
+	cx18_writel(cx, IRQ_EPU_TO_HPU_ACK, &cx->scb->epu2hpu_irq_ack);
+	cx18_writel(cx, IRQ_PPU_TO_EPU,     &cx->scb->ppu2epu_irq);
+	cx18_writel(cx, IRQ_EPU_TO_PPU_ACK, &cx->scb->epu2ppu_irq_ack);
+
+	cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, apu2cpu_mb),
+			&cx->scb->apu2cpu_mb_offset);
+	cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, hpu2cpu_mb),
+			&cx->scb->hpu2cpu_mb_offset);
+	cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, ppu2cpu_mb),
+			&cx->scb->ppu2cpu_mb_offset);
+	cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, epu2cpu_mb),
+			&cx->scb->epu2cpu_mb_offset);
+	cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, cpu2apu_mb),
+			&cx->scb->cpu2apu_mb_offset);
+	cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, hpu2apu_mb),
+			&cx->scb->hpu2apu_mb_offset);
+	cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, ppu2apu_mb),
+			&cx->scb->ppu2apu_mb_offset);
+	cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, epu2apu_mb),
+			&cx->scb->epu2apu_mb_offset);
+	cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, cpu2hpu_mb),
+			&cx->scb->cpu2hpu_mb_offset);
+	cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, apu2hpu_mb),
+			&cx->scb->apu2hpu_mb_offset);
+	cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, ppu2hpu_mb),
+			&cx->scb->ppu2hpu_mb_offset);
+	cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, epu2hpu_mb),
+			&cx->scb->epu2hpu_mb_offset);
+	cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, cpu2ppu_mb),
+			&cx->scb->cpu2ppu_mb_offset);
+	cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, apu2ppu_mb),
+			&cx->scb->apu2ppu_mb_offset);
+	cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, hpu2ppu_mb),
+			&cx->scb->hpu2ppu_mb_offset);
+	cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, epu2ppu_mb),
+			&cx->scb->epu2ppu_mb_offset);
+	cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, cpu2epu_mb),
+			&cx->scb->cpu2epu_mb_offset);
+	cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, apu2epu_mb),
+			&cx->scb->apu2epu_mb_offset);
+	cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, hpu2epu_mb),
+			&cx->scb->hpu2epu_mb_offset);
+	cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, ppu2epu_mb),
+			&cx->scb->ppu2epu_mb_offset);
+
+	cx18_writel(cx, SCB_OFFSET + offsetof(struct cx18_scb, cpu_state),
+			&cx->scb->ipc_offset);
+
+	cx18_writel(cx, 1, &cx->scb->epu_state);
+}
diff --git a/drivers/media/pci/cx18/cx18-scb.h b/drivers/media/pci/cx18/cx18-scb.h
new file mode 100644
index 0000000..0887765
--- /dev/null
+++ b/drivers/media/pci/cx18/cx18-scb.h
@@ -0,0 +1,280 @@
+/*
+ *  cx18 System Control Block initialization
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.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 program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public 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 CX18_SCB_H
+#define CX18_SCB_H
+
+#include "cx18-mailbox.h"
+
+/* NOTE: All ACK interrupts are in the SW2 register.  All non-ACK interrupts
+   are in the SW1 register. */
+
+#define IRQ_APU_TO_CPU         0x00000001
+#define IRQ_CPU_TO_APU_ACK     0x00000001
+#define IRQ_HPU_TO_CPU         0x00000002
+#define IRQ_CPU_TO_HPU_ACK     0x00000002
+#define IRQ_PPU_TO_CPU         0x00000004
+#define IRQ_CPU_TO_PPU_ACK     0x00000004
+#define IRQ_EPU_TO_CPU         0x00000008
+#define IRQ_CPU_TO_EPU_ACK     0x00000008
+
+#define IRQ_CPU_TO_APU         0x00000010
+#define IRQ_APU_TO_CPU_ACK     0x00000010
+#define IRQ_HPU_TO_APU         0x00000020
+#define IRQ_APU_TO_HPU_ACK     0x00000020
+#define IRQ_PPU_TO_APU         0x00000040
+#define IRQ_APU_TO_PPU_ACK     0x00000040
+#define IRQ_EPU_TO_APU         0x00000080
+#define IRQ_APU_TO_EPU_ACK     0x00000080
+
+#define IRQ_CPU_TO_HPU         0x00000100
+#define IRQ_HPU_TO_CPU_ACK     0x00000100
+#define IRQ_APU_TO_HPU         0x00000200
+#define IRQ_HPU_TO_APU_ACK     0x00000200
+#define IRQ_PPU_TO_HPU         0x00000400
+#define IRQ_HPU_TO_PPU_ACK     0x00000400
+#define IRQ_EPU_TO_HPU         0x00000800
+#define IRQ_HPU_TO_EPU_ACK     0x00000800
+
+#define IRQ_CPU_TO_PPU         0x00001000
+#define IRQ_PPU_TO_CPU_ACK     0x00001000
+#define IRQ_APU_TO_PPU         0x00002000
+#define IRQ_PPU_TO_APU_ACK     0x00002000
+#define IRQ_HPU_TO_PPU         0x00004000
+#define IRQ_PPU_TO_HPU_ACK     0x00004000
+#define IRQ_EPU_TO_PPU         0x00008000
+#define IRQ_PPU_TO_EPU_ACK     0x00008000
+
+#define IRQ_CPU_TO_EPU         0x00010000
+#define IRQ_EPU_TO_CPU_ACK     0x00010000
+#define IRQ_APU_TO_EPU         0x00020000
+#define IRQ_EPU_TO_APU_ACK     0x00020000
+#define IRQ_HPU_TO_EPU         0x00040000
+#define IRQ_EPU_TO_HPU_ACK     0x00040000
+#define IRQ_PPU_TO_EPU         0x00080000
+#define IRQ_EPU_TO_PPU_ACK     0x00080000
+
+#define SCB_OFFSET  0xDC0000
+
+/* If Firmware uses fixed memory map, it shall not allocate the area
+   between SCB_OFFSET and SCB_OFFSET+SCB_RESERVED_SIZE-1 inclusive */
+#define SCB_RESERVED_SIZE 0x10000
+
+
+/* This structure is used by EPU to provide memory descriptors in its memory */
+struct cx18_mdl_ent {
+    u32 paddr;  /* Physical address of a buffer segment */
+    u32 length; /* Length of the buffer segment */
+};
+
+struct cx18_scb {
+	/* These fields form the System Control Block which is used at boot time
+	   for localizing the IPC data as well as the code positions for all
+	   processors. The offsets are from the start of this struct. */
+
+	/* Offset where to find the Inter-Processor Communication data */
+	u32 ipc_offset;
+	u32 reserved01[7];
+	/* Offset where to find the start of the CPU code */
+	u32 cpu_code_offset;
+	u32 reserved02[3];
+	/* Offset where to find the start of the APU code */
+	u32 apu_code_offset;
+	u32 reserved03[3];
+	/* Offset where to find the start of the HPU code */
+	u32 hpu_code_offset;
+	u32 reserved04[3];
+	/* Offset where to find the start of the PPU code */
+	u32 ppu_code_offset;
+	u32 reserved05[3];
+
+	/* These fields form Inter-Processor Communication data which is used
+	   by all processors to locate the information needed for communicating
+	   with other processors */
+
+	/* Fields for CPU: */
+
+	/* bit 0: 1/0 processor ready/not ready. Set other bits to 0. */
+	u32 cpu_state;
+	u32 reserved1[7];
+	/* Offset to the mailbox used for sending commands from APU to CPU */
+	u32 apu2cpu_mb_offset;
+	/* Value to write to register SW1 register set (0xC7003100) after the
+	   command is ready */
+	u32 apu2cpu_irq;
+	/* Value to write to register SW2 register set (0xC7003140) after the
+	   command is cleared */
+	u32 cpu2apu_irq_ack;
+	u32 reserved2[13];
+
+	u32 hpu2cpu_mb_offset;
+	u32 hpu2cpu_irq;
+	u32 cpu2hpu_irq_ack;
+	u32 reserved3[13];
+
+	u32 ppu2cpu_mb_offset;
+	u32 ppu2cpu_irq;
+	u32 cpu2ppu_irq_ack;
+	u32 reserved4[13];
+
+	u32 epu2cpu_mb_offset;
+	u32 epu2cpu_irq;
+	u32 cpu2epu_irq_ack;
+	u32 reserved5[13];
+	u32 reserved6[8];
+
+	/* Fields for APU: */
+
+	u32 apu_state;
+	u32 reserved11[7];
+	u32 cpu2apu_mb_offset;
+	u32 cpu2apu_irq;
+	u32 apu2cpu_irq_ack;
+	u32 reserved12[13];
+
+	u32 hpu2apu_mb_offset;
+	u32 hpu2apu_irq;
+	u32 apu2hpu_irq_ack;
+	u32 reserved13[13];
+
+	u32 ppu2apu_mb_offset;
+	u32 ppu2apu_irq;
+	u32 apu2ppu_irq_ack;
+	u32 reserved14[13];
+
+	u32 epu2apu_mb_offset;
+	u32 epu2apu_irq;
+	u32 apu2epu_irq_ack;
+	u32 reserved15[13];
+	u32 reserved16[8];
+
+	/* Fields for HPU: */
+
+	u32 hpu_state;
+	u32 reserved21[7];
+	u32 cpu2hpu_mb_offset;
+	u32 cpu2hpu_irq;
+	u32 hpu2cpu_irq_ack;
+	u32 reserved22[13];
+
+	u32 apu2hpu_mb_offset;
+	u32 apu2hpu_irq;
+	u32 hpu2apu_irq_ack;
+	u32 reserved23[13];
+
+	u32 ppu2hpu_mb_offset;
+	u32 ppu2hpu_irq;
+	u32 hpu2ppu_irq_ack;
+	u32 reserved24[13];
+
+	u32 epu2hpu_mb_offset;
+	u32 epu2hpu_irq;
+	u32 hpu2epu_irq_ack;
+	u32 reserved25[13];
+	u32 reserved26[8];
+
+	/* Fields for PPU: */
+
+	u32 ppu_state;
+	u32 reserved31[7];
+	u32 cpu2ppu_mb_offset;
+	u32 cpu2ppu_irq;
+	u32 ppu2cpu_irq_ack;
+	u32 reserved32[13];
+
+	u32 apu2ppu_mb_offset;
+	u32 apu2ppu_irq;
+	u32 ppu2apu_irq_ack;
+	u32 reserved33[13];
+
+	u32 hpu2ppu_mb_offset;
+	u32 hpu2ppu_irq;
+	u32 ppu2hpu_irq_ack;
+	u32 reserved34[13];
+
+	u32 epu2ppu_mb_offset;
+	u32 epu2ppu_irq;
+	u32 ppu2epu_irq_ack;
+	u32 reserved35[13];
+	u32 reserved36[8];
+
+	/* Fields for EPU: */
+
+	u32 epu_state;
+	u32 reserved41[7];
+	u32 cpu2epu_mb_offset;
+	u32 cpu2epu_irq;
+	u32 epu2cpu_irq_ack;
+	u32 reserved42[13];
+
+	u32 apu2epu_mb_offset;
+	u32 apu2epu_irq;
+	u32 epu2apu_irq_ack;
+	u32 reserved43[13];
+
+	u32 hpu2epu_mb_offset;
+	u32 hpu2epu_irq;
+	u32 epu2hpu_irq_ack;
+	u32 reserved44[13];
+
+	u32 ppu2epu_mb_offset;
+	u32 ppu2epu_irq;
+	u32 epu2ppu_irq_ack;
+	u32 reserved45[13];
+	u32 reserved46[8];
+
+	u32 semaphores[8];  /* Semaphores */
+
+	u32 reserved50[32]; /* Reserved for future use */
+
+	struct cx18_mailbox  apu2cpu_mb;
+	struct cx18_mailbox  hpu2cpu_mb;
+	struct cx18_mailbox  ppu2cpu_mb;
+	struct cx18_mailbox  epu2cpu_mb;
+
+	struct cx18_mailbox  cpu2apu_mb;
+	struct cx18_mailbox  hpu2apu_mb;
+	struct cx18_mailbox  ppu2apu_mb;
+	struct cx18_mailbox  epu2apu_mb;
+
+	struct cx18_mailbox  cpu2hpu_mb;
+	struct cx18_mailbox  apu2hpu_mb;
+	struct cx18_mailbox  ppu2hpu_mb;
+	struct cx18_mailbox  epu2hpu_mb;
+
+	struct cx18_mailbox  cpu2ppu_mb;
+	struct cx18_mailbox  apu2ppu_mb;
+	struct cx18_mailbox  hpu2ppu_mb;
+	struct cx18_mailbox  epu2ppu_mb;
+
+	struct cx18_mailbox  cpu2epu_mb;
+	struct cx18_mailbox  apu2epu_mb;
+	struct cx18_mailbox  hpu2epu_mb;
+	struct cx18_mailbox  ppu2epu_mb;
+
+	struct cx18_mdl_ack  cpu_mdl_ack[CX18_MAX_STREAMS][CX18_MAX_MDL_ACKS];
+	struct cx18_mdl_ent  cpu_mdl[1];
+};
+
+void cx18_init_scb(struct cx18 *cx);
+
+#endif
diff --git a/drivers/media/pci/cx18/cx18-streams.c b/drivers/media/pci/cx18/cx18-streams.c
new file mode 100644
index 0000000..9d598ab
--- /dev/null
+++ b/drivers/media/pci/cx18/cx18-streams.c
@@ -0,0 +1,1060 @@
+/*
+ *  cx18 init/start/stop/exit stream functions
+ *
+ *  Derived from ivtv-streams.c
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.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 program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public 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 "cx18-driver.h"
+#include "cx18-io.h"
+#include "cx18-fileops.h"
+#include "cx18-mailbox.h"
+#include "cx18-i2c.h"
+#include "cx18-queue.h"
+#include "cx18-ioctl.h"
+#include "cx18-streams.h"
+#include "cx18-cards.h"
+#include "cx18-scb.h"
+#include "cx18-dvb.h"
+
+#define CX18_DSP0_INTERRUPT_MASK     	0xd0004C
+
+static struct v4l2_file_operations cx18_v4l2_enc_fops = {
+	.owner = THIS_MODULE,
+	.read = cx18_v4l2_read,
+	.open = cx18_v4l2_open,
+	.unlocked_ioctl = video_ioctl2,
+	.release = cx18_v4l2_close,
+	.poll = cx18_v4l2_enc_poll,
+	.mmap = cx18_v4l2_mmap,
+};
+
+/* offset from 0 to register ts v4l2 minors on */
+#define CX18_V4L2_ENC_TS_OFFSET   16
+/* offset from 0 to register pcm v4l2 minors on */
+#define CX18_V4L2_ENC_PCM_OFFSET  24
+/* offset from 0 to register yuv v4l2 minors on */
+#define CX18_V4L2_ENC_YUV_OFFSET  32
+
+static struct {
+	const char *name;
+	int vfl_type;
+	int num_offset;
+	int dma;
+	enum v4l2_buf_type buf_type;
+} cx18_stream_info[] = {
+	{	/* CX18_ENC_STREAM_TYPE_MPG */
+		"encoder MPEG",
+		VFL_TYPE_GRABBER, 0,
+		PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_VIDEO_CAPTURE,
+	},
+	{	/* CX18_ENC_STREAM_TYPE_TS */
+		"TS",
+		VFL_TYPE_GRABBER, -1,
+		PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_VIDEO_CAPTURE,
+	},
+	{	/* CX18_ENC_STREAM_TYPE_YUV */
+		"encoder YUV",
+		VFL_TYPE_GRABBER, CX18_V4L2_ENC_YUV_OFFSET,
+		PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_VIDEO_CAPTURE,
+	},
+	{	/* CX18_ENC_STREAM_TYPE_VBI */
+		"encoder VBI",
+		VFL_TYPE_VBI, 0,
+		PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_VBI_CAPTURE,
+	},
+	{	/* CX18_ENC_STREAM_TYPE_PCM */
+		"encoder PCM audio",
+		VFL_TYPE_GRABBER, CX18_V4L2_ENC_PCM_OFFSET,
+		PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_PRIVATE,
+	},
+	{	/* CX18_ENC_STREAM_TYPE_IDX */
+		"encoder IDX",
+		VFL_TYPE_GRABBER, -1,
+		PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_VIDEO_CAPTURE,
+	},
+	{	/* CX18_ENC_STREAM_TYPE_RAD */
+		"encoder radio",
+		VFL_TYPE_RADIO, 0,
+		PCI_DMA_NONE, V4L2_BUF_TYPE_PRIVATE,
+	},
+};
+
+
+void cx18_dma_free(struct videobuf_queue *q,
+	struct cx18_stream *s, struct cx18_videobuf_buffer *buf)
+{
+	videobuf_waiton(q, &buf->vb, 0, 0);
+	videobuf_vmalloc_free(&buf->vb);
+	buf->vb.state = VIDEOBUF_NEEDS_INIT;
+}
+
+static int cx18_prepare_buffer(struct videobuf_queue *q,
+	struct cx18_stream *s,
+	struct cx18_videobuf_buffer *buf,
+	u32 pixelformat,
+	unsigned int width, unsigned int height,
+	enum v4l2_field field)
+{
+        struct cx18 *cx = s->cx;
+	int rc = 0;
+
+	/* check settings */
+	buf->bytes_used = 0;
+
+	if ((width  < 48) || (height < 32))
+		return -EINVAL;
+
+	buf->vb.size = (width * height * 2);
+	if ((buf->vb.baddr != 0) && (buf->vb.bsize < buf->vb.size))
+		return -EINVAL;
+
+	/* alloc + fill struct (if changed) */
+	if (buf->vb.width != width || buf->vb.height != height ||
+	    buf->vb.field != field || s->pixelformat != pixelformat ||
+	    buf->tvnorm != cx->std) {
+
+		buf->vb.width  = width;
+		buf->vb.height = height;
+		buf->vb.field  = field;
+		buf->tvnorm    = cx->std;
+		s->pixelformat = pixelformat;
+
+		/* HM12 YUV size is (Y=(h*720) + UV=(h*(720/2)))
+		   UYUV YUV size is (Y=(h*720) + UV=(h*(720))) */
+		if (s->pixelformat == V4L2_PIX_FMT_HM12)
+			s->vb_bytes_per_frame = height * 720 * 3 / 2;
+		else
+			s->vb_bytes_per_frame = height * 720 * 2;
+		cx18_dma_free(q, s, buf);
+	}
+
+	if ((buf->vb.baddr != 0) && (buf->vb.bsize < buf->vb.size))
+		return -EINVAL;
+
+	if (buf->vb.field == 0)
+		buf->vb.field = V4L2_FIELD_INTERLACED;
+
+	if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
+		buf->vb.width  = width;
+		buf->vb.height = height;
+		buf->vb.field  = field;
+		buf->tvnorm    = cx->std;
+		s->pixelformat = pixelformat;
+
+		/* HM12 YUV size is (Y=(h*720) + UV=(h*(720/2)))
+		   UYUV YUV size is (Y=(h*720) + UV=(h*(720))) */
+		if (s->pixelformat == V4L2_PIX_FMT_HM12)
+			s->vb_bytes_per_frame = height * 720 * 3 / 2;
+		else
+			s->vb_bytes_per_frame = height * 720 * 2;
+		rc = videobuf_iolock(q, &buf->vb, NULL);
+		if (rc != 0)
+			goto fail;
+	}
+	buf->vb.state = VIDEOBUF_PREPARED;
+	return 0;
+
+fail:
+	cx18_dma_free(q, s, buf);
+	return rc;
+
+}
+
+/* VB_MIN_BUFSIZE is lcm(1440 * 480, 1440 * 576)
+   1440 is a single line of 4:2:2 YUV at 720 luma samples wide
+*/
+#define VB_MIN_BUFFERS 32
+#define VB_MIN_BUFSIZE 4147200
+
+static int buffer_setup(struct videobuf_queue *q,
+	unsigned int *count, unsigned int *size)
+{
+	struct cx18_stream *s = q->priv_data;
+	struct cx18 *cx = s->cx;
+
+	*size = 2 * cx->cxhdl.width * cx->cxhdl.height;
+	if (*count == 0)
+		*count = VB_MIN_BUFFERS;
+
+	while (*size * *count > VB_MIN_BUFFERS * VB_MIN_BUFSIZE)
+		(*count)--;
+
+	q->field = V4L2_FIELD_INTERLACED;
+	q->last = V4L2_FIELD_INTERLACED;
+
+	return 0;
+}
+
+static int buffer_prepare(struct videobuf_queue *q,
+	struct videobuf_buffer *vb,
+	enum v4l2_field field)
+{
+	struct cx18_videobuf_buffer *buf =
+		container_of(vb, struct cx18_videobuf_buffer, vb);
+	struct cx18_stream *s = q->priv_data;
+	struct cx18 *cx = s->cx;
+
+	return cx18_prepare_buffer(q, s, buf, s->pixelformat,
+		cx->cxhdl.width, cx->cxhdl.height, field);
+}
+
+static void buffer_release(struct videobuf_queue *q,
+	struct videobuf_buffer *vb)
+{
+	struct cx18_videobuf_buffer *buf =
+		container_of(vb, struct cx18_videobuf_buffer, vb);
+	struct cx18_stream *s = q->priv_data;
+
+	cx18_dma_free(q, s, buf);
+}
+
+static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
+{
+	struct cx18_videobuf_buffer *buf =
+		container_of(vb, struct cx18_videobuf_buffer, vb);
+	struct cx18_stream *s = q->priv_data;
+
+	buf->vb.state = VIDEOBUF_QUEUED;
+
+	list_add_tail(&buf->vb.queue, &s->vb_capture);
+}
+
+static struct videobuf_queue_ops cx18_videobuf_qops = {
+	.buf_setup    = buffer_setup,
+	.buf_prepare  = buffer_prepare,
+	.buf_queue    = buffer_queue,
+	.buf_release  = buffer_release,
+};
+
+static void cx18_stream_init(struct cx18 *cx, int type)
+{
+	struct cx18_stream *s = &cx->streams[type];
+	struct video_device *video_dev = s->video_dev;
+
+	/* we need to keep video_dev, so restore it afterwards */
+	memset(s, 0, sizeof(*s));
+	s->video_dev = video_dev;
+
+	/* initialize cx18_stream fields */
+	s->dvb = NULL;
+	s->cx = cx;
+	s->type = type;
+	s->name = cx18_stream_info[type].name;
+	s->handle = CX18_INVALID_TASK_HANDLE;
+
+	s->dma = cx18_stream_info[type].dma;
+	s->buffers = cx->stream_buffers[type];
+	s->buf_size = cx->stream_buf_size[type];
+	INIT_LIST_HEAD(&s->buf_pool);
+	s->bufs_per_mdl = 1;
+	s->mdl_size = s->buf_size * s->bufs_per_mdl;
+
+	init_waitqueue_head(&s->waitq);
+	s->id = -1;
+	spin_lock_init(&s->q_free.lock);
+	cx18_queue_init(&s->q_free);
+	spin_lock_init(&s->q_busy.lock);
+	cx18_queue_init(&s->q_busy);
+	spin_lock_init(&s->q_full.lock);
+	cx18_queue_init(&s->q_full);
+	spin_lock_init(&s->q_idle.lock);
+	cx18_queue_init(&s->q_idle);
+
+	INIT_WORK(&s->out_work_order, cx18_out_work_handler);
+
+	INIT_LIST_HEAD(&s->vb_capture);
+	s->vb_timeout.function = cx18_vb_timeout;
+	s->vb_timeout.data = (unsigned long)s;
+	init_timer(&s->vb_timeout);
+	spin_lock_init(&s->vb_lock);
+	if (type == CX18_ENC_STREAM_TYPE_YUV) {
+		spin_lock_init(&s->vbuf_q_lock);
+
+		s->vb_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+		videobuf_queue_vmalloc_init(&s->vbuf_q, &cx18_videobuf_qops,
+			&cx->pci_dev->dev, &s->vbuf_q_lock,
+			V4L2_BUF_TYPE_VIDEO_CAPTURE,
+			V4L2_FIELD_INTERLACED,
+			sizeof(struct cx18_videobuf_buffer),
+			s, &cx->serialize_lock);
+
+		/* Assume the previous pixel default */
+		s->pixelformat = V4L2_PIX_FMT_HM12;
+		s->vb_bytes_per_frame = cx->cxhdl.height * 720 * 3 / 2;
+	}
+}
+
+static int cx18_prep_dev(struct cx18 *cx, int type)
+{
+	struct cx18_stream *s = &cx->streams[type];
+	u32 cap = cx->v4l2_cap;
+	int num_offset = cx18_stream_info[type].num_offset;
+	int num = cx->instance + cx18_first_minor + num_offset;
+
+	/*
+	 * These five fields are always initialized.
+	 * For analog capture related streams, if video_dev == NULL then the
+	 * stream is not in use.
+	 * For the TS stream, if dvb == NULL then the stream is not in use.
+	 * In those cases no other fields but these four can be used.
+	 */
+	s->video_dev = NULL;
+	s->dvb = NULL;
+	s->cx = cx;
+	s->type = type;
+	s->name = cx18_stream_info[type].name;
+
+	/* Check whether the radio is supported */
+	if (type == CX18_ENC_STREAM_TYPE_RAD && !(cap & V4L2_CAP_RADIO))
+		return 0;
+
+	/* Check whether VBI is supported */
+	if (type == CX18_ENC_STREAM_TYPE_VBI &&
+	    !(cap & (V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_CAPTURE)))
+		return 0;
+
+	/* User explicitly selected 0 buffers for these streams, so don't
+	   create them. */
+	if (cx18_stream_info[type].dma != PCI_DMA_NONE &&
+	    cx->stream_buffers[type] == 0) {
+		CX18_INFO("Disabled %s device\n", cx18_stream_info[type].name);
+		return 0;
+	}
+
+	cx18_stream_init(cx, type);
+
+	/* Allocate the cx18_dvb struct only for the TS on cards with DTV */
+	if (type == CX18_ENC_STREAM_TYPE_TS) {
+		if (cx->card->hw_all & CX18_HW_DVB) {
+			s->dvb = kzalloc(sizeof(struct cx18_dvb), GFP_KERNEL);
+			if (s->dvb == NULL) {
+				CX18_ERR("Couldn't allocate cx18_dvb structure"
+					 " for %s\n", s->name);
+				return -ENOMEM;
+			}
+		} else {
+			/* Don't need buffers for the TS, if there is no DVB */
+			s->buffers = 0;
+		}
+	}
+
+	if (num_offset == -1)
+		return 0;
+
+	/* allocate and initialize the v4l2 video device structure */
+	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->video_dev->name, sizeof(s->video_dev->name), "%s %s",
+		 cx->v4l2_dev.name, s->name);
+
+	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;
+	s->video_dev->lock = &cx->serialize_lock;
+	set_bit(V4L2_FL_USE_FH_PRIO, &s->video_dev->flags);
+	cx18_set_funcs(s->video_dev);
+	return 0;
+}
+
+/* Initialize v4l2 variables and register v4l2 devices */
+int cx18_streams_setup(struct cx18 *cx)
+{
+	int type, ret;
+
+	/* Setup V4L2 Devices */
+	for (type = 0; type < CX18_MAX_STREAMS; type++) {
+		/* Prepare device */
+		ret = cx18_prep_dev(cx, type);
+		if (ret < 0)
+			break;
+
+		/* Allocate Stream */
+		ret = cx18_stream_alloc(&cx->streams[type]);
+		if (ret < 0)
+			break;
+	}
+	if (type == CX18_MAX_STREAMS)
+		return 0;
+
+	/* One or more streams could not be initialized. Clean 'em all up. */
+	cx18_streams_cleanup(cx, 0);
+	return ret;
+}
+
+static int cx18_reg_dev(struct cx18 *cx, int type)
+{
+	struct cx18_stream *s = &cx->streams[type];
+	int vfl_type = cx18_stream_info[type].vfl_type;
+	const char *name;
+	int num, ret;
+
+	if (type == CX18_ENC_STREAM_TYPE_TS && s->dvb != NULL) {
+		ret = cx18_dvb_register(s);
+		if (ret < 0) {
+			CX18_ERR("DVB failed to register\n");
+			return ret;
+		}
+	}
+
+	if (s->video_dev == NULL)
+		return 0;
+
+	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->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_no_warn(s->video_dev, vfl_type, num);
+	if (ret < 0) {
+		CX18_ERR("Couldn't register v4l2 device for %s (device node number %d)\n",
+			s->name, num);
+		video_device_release(s->video_dev);
+		s->video_dev = NULL;
+		return ret;
+	}
+
+	name = video_device_node_name(s->video_dev);
+
+	switch (vfl_type) {
+	case VFL_TYPE_GRABBER:
+		CX18_INFO("Registered device %s for %s (%d x %d.%02d kB)\n",
+			  name, s->name, cx->stream_buffers[type],
+			  cx->stream_buf_size[type] / 1024,
+			  (cx->stream_buf_size[type] * 100 / 1024) % 100);
+		break;
+
+	case VFL_TYPE_RADIO:
+		CX18_INFO("Registered device %s for %s\n", name, s->name);
+		break;
+
+	case VFL_TYPE_VBI:
+		if (cx->stream_buffers[type])
+			CX18_INFO("Registered device %s for %s "
+				  "(%d x %d bytes)\n",
+				  name, s->name, cx->stream_buffers[type],
+				  cx->stream_buf_size[type]);
+		else
+			CX18_INFO("Registered device %s for %s\n",
+				name, s->name);
+		break;
+	}
+
+	return 0;
+}
+
+/* Register v4l2 devices */
+int cx18_streams_register(struct cx18 *cx)
+{
+	int type;
+	int err;
+	int ret = 0;
+
+	/* Register V4L2 devices */
+	for (type = 0; type < CX18_MAX_STREAMS; type++) {
+		err = cx18_reg_dev(cx, type);
+		if (err && ret == 0)
+			ret = err;
+	}
+
+	if (ret == 0)
+		return 0;
+
+	/* One or more streams could not be initialized. Clean 'em all up. */
+	cx18_streams_cleanup(cx, 1);
+	return ret;
+}
+
+/* Unregister v4l2 devices */
+void cx18_streams_cleanup(struct cx18 *cx, int unregister)
+{
+	struct video_device *vdev;
+	int type;
+
+	/* Teardown all streams */
+	for (type = 0; type < CX18_MAX_STREAMS; type++) {
+
+		/* The TS has a cx18_dvb structure, not a video_device */
+		if (type == CX18_ENC_STREAM_TYPE_TS) {
+			if (cx->streams[type].dvb != NULL) {
+				if (unregister)
+					cx18_dvb_unregister(&cx->streams[type]);
+				kfree(cx->streams[type].dvb);
+				cx->streams[type].dvb = NULL;
+				cx18_stream_free(&cx->streams[type]);
+			}
+			continue;
+		}
+
+		/* No struct video_device, but can have buffers allocated */
+		if (type == CX18_ENC_STREAM_TYPE_IDX) {
+			/* If the module params didn't inhibit IDX ... */
+			if (cx->stream_buffers[type] != 0) {
+				cx->stream_buffers[type] = 0;
+				/*
+				 * Before calling cx18_stream_free(),
+				 * check if the IDX stream was actually set up.
+				 * Needed, since the cx18_probe() error path
+				 * exits through here as well as normal clean up
+				 */
+				if (cx->streams[type].buffers != 0)
+					cx18_stream_free(&cx->streams[type]);
+			}
+			continue;
+		}
+
+		/* If struct video_device exists, can have buffers allocated */
+		vdev = cx->streams[type].video_dev;
+
+		cx->streams[type].video_dev = NULL;
+		if (vdev == NULL)
+			continue;
+
+		if (type == CX18_ENC_STREAM_TYPE_YUV)
+			videobuf_mmap_free(&cx->streams[type].vbuf_q);
+
+		cx18_stream_free(&cx->streams[type]);
+
+		/* Unregister or release device */
+		if (unregister)
+			video_unregister_device(vdev);
+		else
+			video_device_release(vdev);
+	}
+}
+
+static void cx18_vbi_setup(struct cx18_stream *s)
+{
+	struct cx18 *cx = s->cx;
+	int raw = cx18_raw_vbi(cx);
+	u32 data[CX2341X_MBOX_MAX_DATA];
+	int lines;
+
+	if (cx->is_60hz) {
+		cx->vbi.count = 12;
+		cx->vbi.start[0] = 10;
+		cx->vbi.start[1] = 273;
+	} else {        /* PAL/SECAM */
+		cx->vbi.count = 18;
+		cx->vbi.start[0] = 6;
+		cx->vbi.start[1] = 318;
+	}
+
+	/* setup VBI registers */
+	if (raw)
+		v4l2_subdev_call(cx->sd_av, vbi, s_raw_fmt, &cx->vbi.in.fmt.vbi);
+	else
+		v4l2_subdev_call(cx->sd_av, vbi, s_sliced_fmt, &cx->vbi.in.fmt.sliced);
+
+	/*
+	 * 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 {
+		/*
+		 * 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.
+		 *
+		 * For 625/50 systems, according to the VIP 2 & BT.656 std:
+		 * The EAV RP code's Field bit toggles on line 1, a few lines
+		 * after the Vertcal Blank bit has already toggled.
+		 * (We've actually set the digitizer so that the Field bit
+		 * toggles on line 2.) Tell the encoder to capture 23-2+1=22
+		 * lines per field, since we want lines 6 through 23.
+		 */
+		lines = cx->is_60hz ? (21 - 4 + 1) * 2 : (23 - 2 + 1) * 2;
+	}
+
+	data[0] = s->handle;
+	/* Lines per field */
+	data[1] = (lines / 2) | ((lines / 2) << 16);
+	/* bytes per line */
+	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;
+	/*
+	 * 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]);
+
+	cx18_api(cx, CX18_CPU_SET_RAW_VBI_PARAM, 6, data);
+}
+
+void cx18_stream_rotate_idx_mdls(struct cx18 *cx)
+{
+	struct cx18_stream *s = &cx->streams[CX18_ENC_STREAM_TYPE_IDX];
+	struct cx18_mdl *mdl;
+
+	if (!cx18_stream_enabled(s))
+		return;
+
+	/* Return if the firmware is not running low on MDLs */
+	if ((atomic_read(&s->q_free.depth) + atomic_read(&s->q_busy.depth)) >=
+					    CX18_ENC_STREAM_TYPE_IDX_FW_MDL_MIN)
+		return;
+
+	/* Return if there are no MDLs to rotate back to the firmware */
+	if (atomic_read(&s->q_full.depth) < 2)
+		return;
+
+	/*
+	 * Take the oldest IDX MDL still holding data, and discard its index
+	 * entries by scheduling the MDL to go back to the firmware
+	 */
+	mdl = cx18_dequeue(s, &s->q_full);
+	if (mdl != NULL)
+		cx18_enqueue(s, mdl, &s->q_free);
+}
+
+static
+struct cx18_queue *_cx18_stream_put_mdl_fw(struct cx18_stream *s,
+					   struct cx18_mdl *mdl)
+{
+	struct cx18 *cx = s->cx;
+	struct cx18_queue *q;
+
+	/* Don't give it to the firmware, if we're not running a capture */
+	if (s->handle == CX18_INVALID_TASK_HANDLE ||
+	    test_bit(CX18_F_S_STOPPING, &s->s_flags) ||
+	    !test_bit(CX18_F_S_STREAMING, &s->s_flags))
+		return cx18_enqueue(s, mdl, &s->q_free);
+
+	q = cx18_enqueue(s, mdl, &s->q_busy);
+	if (q != &s->q_busy)
+		return q; /* The firmware has the max MDLs it can handle */
+
+	cx18_mdl_sync_for_device(s, mdl);
+	cx18_vapi(cx, CX18_CPU_DE_SET_MDL, 5, s->handle,
+		  (void __iomem *) &cx->scb->cpu_mdl[mdl->id] - cx->enc_mem,
+		  s->bufs_per_mdl, mdl->id, s->mdl_size);
+	return q;
+}
+
+static
+void _cx18_stream_load_fw_queue(struct cx18_stream *s)
+{
+	struct cx18_queue *q;
+	struct cx18_mdl *mdl;
+
+	if (atomic_read(&s->q_free.depth) == 0 ||
+	    atomic_read(&s->q_busy.depth) >= CX18_MAX_FW_MDLS_PER_STREAM)
+		return;
+
+	/* Move from q_free to q_busy notifying the firmware, until the limit */
+	do {
+		mdl = cx18_dequeue(s, &s->q_free);
+		if (mdl == NULL)
+			break;
+		q = _cx18_stream_put_mdl_fw(s, mdl);
+	} while (atomic_read(&s->q_busy.depth) < CX18_MAX_FW_MDLS_PER_STREAM
+		 && q == &s->q_busy);
+}
+
+void cx18_out_work_handler(struct work_struct *work)
+{
+	struct cx18_stream *s =
+			 container_of(work, struct cx18_stream, out_work_order);
+
+	_cx18_stream_load_fw_queue(s);
+}
+
+static void cx18_stream_configure_mdls(struct cx18_stream *s)
+{
+	cx18_unload_queues(s);
+
+	switch (s->type) {
+	case CX18_ENC_STREAM_TYPE_YUV:
+		/*
+		 * Height should be a multiple of 32 lines.
+		 * Set the MDL size to the exact size needed for one frame.
+		 * Use enough buffers per MDL to cover the MDL size
+		 */
+		if (s->pixelformat == V4L2_PIX_FMT_HM12)
+			s->mdl_size = 720 * s->cx->cxhdl.height * 3 / 2;
+		else
+			s->mdl_size = 720 * s->cx->cxhdl.height * 2;
+		s->bufs_per_mdl = s->mdl_size / s->buf_size;
+		if (s->mdl_size % s->buf_size)
+			s->bufs_per_mdl++;
+		break;
+	case CX18_ENC_STREAM_TYPE_VBI:
+		s->bufs_per_mdl = 1;
+		if  (cx18_raw_vbi(s->cx)) {
+			s->mdl_size = (s->cx->is_60hz ? 12 : 18)
+						       * 2 * vbi_active_samples;
+		} else {
+			/*
+			 * See comment in cx18_vbi_setup() below about the
+			 * extra lines we capture in sliced VBI mode due to
+			 * the lines on which EAV RP codes toggle.
+			*/
+			s->mdl_size = s->cx->is_60hz
+				   ? (21 - 4 + 1) * 2 * vbi_hblank_samples_60Hz
+				   : (23 - 2 + 1) * 2 * vbi_hblank_samples_50Hz;
+		}
+		break;
+	default:
+		s->bufs_per_mdl = 1;
+		s->mdl_size = s->buf_size * s->bufs_per_mdl;
+		break;
+	}
+
+	cx18_load_queues(s);
+}
+
+int cx18_start_v4l2_encode_stream(struct cx18_stream *s)
+{
+	u32 data[MAX_MB_ARGUMENTS];
+	struct cx18 *cx = s->cx;
+	int captype = 0;
+	struct cx18_stream *s_idx;
+
+	if (!cx18_stream_enabled(s))
+		return -EINVAL;
+
+	CX18_DEBUG_INFO("Start encoder stream %s\n", s->name);
+
+	switch (s->type) {
+	case CX18_ENC_STREAM_TYPE_MPG:
+		captype = CAPTURE_CHANNEL_TYPE_MPEG;
+		cx->mpg_data_received = cx->vbi_data_inserted = 0;
+		cx->dualwatch_jiffies = jiffies;
+		cx->dualwatch_stereo_mode = v4l2_ctrl_g_ctrl(cx->cxhdl.audio_mode);
+		cx->search_pack_header = 0;
+		break;
+
+	case CX18_ENC_STREAM_TYPE_IDX:
+		captype = CAPTURE_CHANNEL_TYPE_INDEX;
+		break;
+	case CX18_ENC_STREAM_TYPE_TS:
+		captype = CAPTURE_CHANNEL_TYPE_TS;
+		break;
+	case CX18_ENC_STREAM_TYPE_YUV:
+		captype = CAPTURE_CHANNEL_TYPE_YUV;
+		break;
+	case CX18_ENC_STREAM_TYPE_PCM:
+		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,
+			0, sizeof(cx->vbi.sliced_mpeg_size));
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* Clear Streamoff flags in case left from last capture */
+	clear_bit(CX18_F_S_STREAMOFF, &s->s_flags);
+
+	cx18_vapi_result(cx, data, CX18_CREATE_TASK, 1, CPU_CMD_MASK_CAPTURE);
+	s->handle = data[0];
+	cx18_vapi(cx, CX18_CPU_SET_CHANNEL_TYPE, 2, s->handle, captype);
+
+	/*
+	 * 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);
+
+		/*
+		 * 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, 312, 313);
+
+		if (cx->v4l2_cap & V4L2_CAP_VBI_CAPTURE)
+			cx18_vbi_setup(s);
+
+		/*
+		 * Select to receive I, P, and B frame index entries, if the
+		 * index stream is enabled.  Otherwise disable index entry
+		 * generation.
+		 */
+		s_idx = &cx->streams[CX18_ENC_STREAM_TYPE_IDX];
+		cx18_vapi_result(cx, data, CX18_CPU_SET_INDEXTABLE, 2,
+				 s->handle, cx18_stream_enabled(s_idx) ? 7 : 0);
+
+		/* Call out to the common CX2341x API setup for user controls */
+		cx->cxhdl.priv = s;
+		cx2341x_handler_setup(&cx->cxhdl);
+
+		/*
+		 * When starting a capture and we're set for radio,
+		 * ensure the video is muted, despite the user control.
+		 */
+		if (!cx->cxhdl.video_mute &&
+		    test_bit(CX18_F_I_RADIO_USER, &cx->i_flags))
+			cx18_vapi(cx, CX18_CPU_SET_VIDEO_MUTE, 2, s->handle,
+			  (v4l2_ctrl_g_ctrl(cx->cxhdl.video_mute_yuv) << 8) | 1);
+
+		/* Enable the Video Format Converter for UYVY 4:2:2 support,
+		 * rather than the default HM12 Macroblovk 4:2:0 support.
+		 */
+		if (captype == CAPTURE_CHANNEL_TYPE_YUV) {
+			if (s->pixelformat == V4L2_PIX_FMT_UYVY)
+				cx18_vapi(cx, CX18_CPU_SET_VFC_PARAM, 2,
+					s->handle, 1);
+			else
+				/* If in doubt, default to HM12 */
+				cx18_vapi(cx, CX18_CPU_SET_VFC_PARAM, 2,
+					s->handle, 0);
+		}
+	}
+
+	if (atomic_read(&cx->tot_capturing) == 0) {
+		cx2341x_handler_set_busy(&cx->cxhdl, 1);
+		clear_bit(CX18_F_I_EOS, &cx->i_flags);
+		cx18_write_reg(cx, 7, CX18_DSP0_INTERRUPT_MASK);
+	}
+
+	cx18_vapi(cx, CX18_CPU_DE_SET_MDL_ACK, 3, s->handle,
+		(void __iomem *)&cx->scb->cpu_mdl_ack[s->type][0] - cx->enc_mem,
+		(void __iomem *)&cx->scb->cpu_mdl_ack[s->type][1] - cx->enc_mem);
+
+	/* Init all the cpu_mdls for this stream */
+	cx18_stream_configure_mdls(s);
+	_cx18_stream_load_fw_queue(s);
+
+	/* begin_capture */
+	if (cx18_vapi(cx, CX18_CPU_CAPTURE_START, 1, s->handle)) {
+		CX18_DEBUG_WARN("Error starting capture!\n");
+		/* Ensure we're really not capturing before releasing MDLs */
+		set_bit(CX18_F_S_STOPPING, &s->s_flags);
+		if (s->type == CX18_ENC_STREAM_TYPE_MPG)
+			cx18_vapi(cx, CX18_CPU_CAPTURE_STOP, 2, s->handle, 1);
+		else
+			cx18_vapi(cx, CX18_CPU_CAPTURE_STOP, 1, s->handle);
+		clear_bit(CX18_F_S_STREAMING, &s->s_flags);
+		/* FIXME - CX18_F_S_STREAMOFF as well? */
+		cx18_vapi(cx, CX18_CPU_DE_RELEASE_MDL, 1, s->handle);
+		cx18_vapi(cx, CX18_DESTROY_TASK, 1, s->handle);
+		s->handle = CX18_INVALID_TASK_HANDLE;
+		clear_bit(CX18_F_S_STOPPING, &s->s_flags);
+		if (atomic_read(&cx->tot_capturing) == 0) {
+			set_bit(CX18_F_I_EOS, &cx->i_flags);
+			cx18_write_reg(cx, 5, CX18_DSP0_INTERRUPT_MASK);
+		}
+		return -EINVAL;
+	}
+
+	/* you're live! sit back and await interrupts :) */
+	if (captype != CAPTURE_CHANNEL_TYPE_TS)
+		atomic_inc(&cx->ana_capturing);
+	atomic_inc(&cx->tot_capturing);
+	return 0;
+}
+EXPORT_SYMBOL(cx18_start_v4l2_encode_stream);
+
+void cx18_stop_all_captures(struct cx18 *cx)
+{
+	int i;
+
+	for (i = CX18_MAX_STREAMS - 1; i >= 0; i--) {
+		struct cx18_stream *s = &cx->streams[i];
+
+		if (!cx18_stream_enabled(s))
+			continue;
+		if (test_bit(CX18_F_S_STREAMING, &s->s_flags))
+			cx18_stop_v4l2_encode_stream(s, 0);
+	}
+}
+
+int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end)
+{
+	struct cx18 *cx = s->cx;
+
+	if (!cx18_stream_enabled(s))
+		return -EINVAL;
+
+	/* This function assumes that you are allowed to stop the capture
+	   and that we are actually capturing */
+
+	CX18_DEBUG_INFO("Stop Capture\n");
+
+	if (atomic_read(&cx->tot_capturing) == 0)
+		return 0;
+
+	set_bit(CX18_F_S_STOPPING, &s->s_flags);
+	if (s->type == CX18_ENC_STREAM_TYPE_MPG)
+		cx18_vapi(cx, CX18_CPU_CAPTURE_STOP, 2, s->handle, !gop_end);
+	else
+		cx18_vapi(cx, CX18_CPU_CAPTURE_STOP, 1, s->handle);
+
+	if (s->type == CX18_ENC_STREAM_TYPE_MPG && gop_end) {
+		CX18_INFO("ignoring gop_end: not (yet?) supported by the firmware\n");
+	}
+
+	if (s->type != CX18_ENC_STREAM_TYPE_TS)
+		atomic_dec(&cx->ana_capturing);
+	atomic_dec(&cx->tot_capturing);
+
+	/* Clear capture and no-read bits */
+	clear_bit(CX18_F_S_STREAMING, &s->s_flags);
+
+	/* Tell the CX23418 it can't use our buffers anymore */
+	cx18_vapi(cx, CX18_CPU_DE_RELEASE_MDL, 1, s->handle);
+
+	cx18_vapi(cx, CX18_DESTROY_TASK, 1, s->handle);
+	s->handle = CX18_INVALID_TASK_HANDLE;
+	clear_bit(CX18_F_S_STOPPING, &s->s_flags);
+
+	if (atomic_read(&cx->tot_capturing) > 0)
+		return 0;
+
+	cx2341x_handler_set_busy(&cx->cxhdl, 0);
+	cx18_write_reg(cx, 5, CX18_DSP0_INTERRUPT_MASK);
+	wake_up(&s->waitq);
+
+	return 0;
+}
+EXPORT_SYMBOL(cx18_stop_v4l2_encode_stream);
+
+u32 cx18_find_handle(struct cx18 *cx)
+{
+	int i;
+
+	/* find first available handle to be used for global settings */
+	for (i = 0; i < CX18_MAX_STREAMS; i++) {
+		struct cx18_stream *s = &cx->streams[i];
+
+		if (s->video_dev && (s->handle != CX18_INVALID_TASK_HANDLE))
+			return s->handle;
+	}
+	return CX18_INVALID_TASK_HANDLE;
+}
+
+struct cx18_stream *cx18_handle_to_stream(struct cx18 *cx, u32 handle)
+{
+	int i;
+	struct cx18_stream *s;
+
+	if (handle == CX18_INVALID_TASK_HANDLE)
+		return NULL;
+
+	for (i = 0; i < CX18_MAX_STREAMS; i++) {
+		s = &cx->streams[i];
+		if (s->handle != handle)
+			continue;
+		if (cx18_stream_enabled(s))
+			return s;
+	}
+	return NULL;
+}
diff --git a/drivers/media/pci/cx18/cx18-streams.h b/drivers/media/pci/cx18/cx18-streams.h
new file mode 100644
index 0000000..713b0e6
--- /dev/null
+++ b/drivers/media/pci/cx18/cx18-streams.h
@@ -0,0 +1,62 @@
+/*
+ *  cx18 init/start/stop/exit stream functions
+ *
+ *  Derived from ivtv-streams.h
+ *
+ *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
+ *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.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 program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307  USA
+ */
+
+u32 cx18_find_handle(struct cx18 *cx);
+struct cx18_stream *cx18_handle_to_stream(struct cx18 *cx, u32 handle);
+int cx18_streams_setup(struct cx18 *cx);
+int cx18_streams_register(struct cx18 *cx);
+void cx18_streams_cleanup(struct cx18 *cx, int unregister);
+
+#define CX18_ENC_STREAM_TYPE_IDX_FW_MDL_MIN (3)
+void cx18_stream_rotate_idx_mdls(struct cx18 *cx);
+
+static inline bool cx18_stream_enabled(struct cx18_stream *s)
+{
+	return s->video_dev ||
+	       (s->dvb && s->dvb->enabled) ||
+	       (s->type == CX18_ENC_STREAM_TYPE_IDX &&
+		s->cx->stream_buffers[CX18_ENC_STREAM_TYPE_IDX] != 0);
+}
+
+/* Related to submission of mdls to firmware */
+static inline void cx18_stream_load_fw_queue(struct cx18_stream *s)
+{
+	schedule_work(&s->out_work_order);
+}
+
+static inline void cx18_stream_put_mdl_fw(struct cx18_stream *s,
+					  struct cx18_mdl *mdl)
+{
+	/* Put mdl on q_free; the out work handler will move mdl(s) to q_busy */
+	cx18_enqueue(s, mdl, &s->q_free);
+	cx18_stream_load_fw_queue(s);
+}
+
+void cx18_out_work_handler(struct work_struct *work);
+
+/* Capture related */
+int cx18_start_v4l2_encode_stream(struct cx18_stream *s);
+int cx18_stop_v4l2_encode_stream(struct cx18_stream *s, int gop_end);
+
+void cx18_stop_all_captures(struct cx18 *cx);
diff --git a/drivers/media/pci/cx18/cx18-vbi.c b/drivers/media/pci/cx18/cx18-vbi.c
new file mode 100644
index 0000000..6d3121f
--- /dev/null
+++ b/drivers/media/pci/cx18/cx18-vbi.c
@@ -0,0 +1,277 @@
+/*
+ *  cx18 Vertical Blank Interval support functions
+ *
+ *  Derived from ivtv-vbi.c
+ *
+ *  Copyright (C) 2007  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., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307  USA
+ */
+
+#include "cx18-driver.h"
+#include "cx18-vbi.h"
+#include "cx18-ioctl.h"
+#include "cx18-queue.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 ancillary 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)
+{
+	int line = 0;
+	int i;
+	u32 linemask[2] = { 0, 0 };
+	unsigned short size;
+	static const u8 mpeg_hdr_data[] = {
+		/* 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;
+	u8 *dst = &cx->vbi.sliced_mpeg_data[idx][0];
+
+	for (i = 0; i < lines; i++) {
+		struct v4l2_sliced_vbi_data *sdata = cx->vbi.sliced_data + i;
+		int f, l;
+
+		if (sdata->id == 0)
+			continue;
+
+		l = sdata->line - 6;
+		f = sdata->field;
+		if (f)
+			l += 18;
+		if (l < 32)
+			linemask[0] |= (1 << l);
+		else
+			linemask[1] |= (1 << (l - 32));
+		dst[sd + 12 + line * 43] = cx18_service2vbi(sdata->id);
+		memcpy(dst + sd + 12 + line * 43 + 1, sdata->data, 42);
+		line++;
+	}
+	memcpy(dst, mpeg_hdr_data, sizeof(mpeg_hdr_data));
+	if (line == 36) {
+		/* All lines are used, so there is no space for the linemask
+		   (the max size of the VBI data is 36 * 43 + 4 bytes).
+		   So in this case we use the magic number 'ITV0'. */
+		memcpy(dst + sd, "ITV0", 4);
+		memcpy(dst + sd + 4, dst + sd + 12, line * 43);
+		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);
+	}
+	dst[4+16] = (size + 10) >> 8;
+	dst[5+16] = (size + 10) & 0xff;
+	dst[9+16] = 0x21 | ((pts_stamp >> 29) & 0x6);
+	dst[10+16] = (pts_stamp >> 22) & 0xff;
+	dst[11+16] = 1 | ((pts_stamp >> 14) & 0xff);
+	dst[12+16] = (pts_stamp >> 7) & 0xff;
+	dst[13+16] = 1 | ((pts_stamp & 0x7f) << 1);
+	cx->vbi.sliced_mpeg_size[idx] = sd + size;
+}
+
+/* Compress raw VBI format, removes leading SAV codes and surplus space
+   after the frame.  Returns new compressed size. */
+/* FIXME - this function ignores the input size. */
+static u32 compress_raw_buf(struct cx18 *cx, u8 *buf, u32 size, u32 hdr_size)
+{
+	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] != raw_vbi_sav_rp[0] &&
+		     p[3] != raw_vbi_sav_rp[1]))
+			break;
+		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);
+}
+
+static u32 compress_sliced_buf(struct cx18 *cx, u8 *buf, u32 size,
+			       const u32 hdr_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 = 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;
+	}
+
+	/*
+	 * 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 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;
+		v4l2_subdev_call(cx->sd_av, vbi, 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;
+			cx->vbi.sliced_data[line].line = vbi.line;
+			memcpy(cx->vbi.sliced_data[line].data, vbi.p, 42);
+			line++;
+		}
+	}
+	return line;
+}
+
+static void _cx18_process_vbi_data(struct cx18 *cx, struct cx18_buffer *buf)
+{
+	/*
+	 * 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;
+
+	/*
+	 * 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)) {
+
+		size = buf->bytesused =
+		     compress_raw_buf(cx, p, size, sizeof(struct vbi_data_hdr));
+
+		/*
+		 * 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 */
+
+	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;
+		cx->vbi.sliced_data[0].line = 0;
+		cx->vbi.sliced_data[0].field = 0;
+		lines = 1;
+	}
+	buf->bytesused = size = lines * sizeof(cx->vbi.sliced_data[0]);
+	memcpy(p, &cx->vbi.sliced_data[0], size);
+
+	if (cx->vbi.insert_mpeg)
+		copy_vbi_data(cx, lines, pts);
+	cx->vbi.frame++;
+}
+
+void cx18_process_vbi_data(struct cx18 *cx, struct cx18_mdl *mdl,
+			   int streamtype)
+{
+	struct cx18_buffer *buf;
+	u32 orig_used;
+
+	if (streamtype != CX18_ENC_STREAM_TYPE_VBI)
+		return;
+
+	/*
+	 * Big assumption here:
+	 * Every buffer hooked to the MDL's buf_list is a complete VBI frame
+	 * that ends at the end of the buffer.
+	 *
+	 * To assume anything else would make the code in this file
+	 * more complex, or require extra memcpy()'s to make the
+	 * buffers satisfy the above assumption.  It's just simpler to set
+	 * up the encoder buffer transfers to make the assumption true.
+	 */
+	list_for_each_entry(buf, &mdl->buf_list, list) {
+		orig_used = buf->bytesused;
+		if (orig_used == 0)
+			break;
+		_cx18_process_vbi_data(cx, buf);
+		mdl->bytesused -= (orig_used - buf->bytesused);
+	}
+}
diff --git a/drivers/media/pci/cx18/cx18-vbi.h b/drivers/media/pci/cx18/cx18-vbi.h
new file mode 100644
index 0000000..b365cf4
--- /dev/null
+++ b/drivers/media/pci/cx18/cx18-vbi.h
@@ -0,0 +1,26 @@
+/*
+ *  cx18 Vertical Blank Interval support functions
+ *
+ *  Derived from ivtv-vbi.h
+ *
+ *  Copyright (C) 2007  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., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307  USA
+ */
+
+void cx18_process_vbi_data(struct cx18 *cx, struct cx18_mdl *mdl,
+			   int streamtype);
+int cx18_used_line(struct cx18 *cx, int line, int field);
diff --git a/drivers/media/pci/cx18/cx18-version.h b/drivers/media/pci/cx18/cx18-version.h
new file mode 100644
index 0000000..fed48b6
--- /dev/null
+++ b/drivers/media/pci/cx18/cx18-version.h
@@ -0,0 +1,28 @@
+/*
+ *  cx18 driver version information
+ *
+ *  Copyright (C) 2007  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., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307  USA
+ */
+
+#ifndef CX18_VERSION_H
+#define CX18_VERSION_H
+
+#define CX18_DRIVER_NAME "cx18"
+#define CX18_VERSION "1.5.1"
+
+#endif
diff --git a/drivers/media/pci/cx18/cx18-video.c b/drivers/media/pci/cx18/cx18-video.c
new file mode 100644
index 0000000..6dc84aa
--- /dev/null
+++ b/drivers/media/pci/cx18/cx18-video.c
@@ -0,0 +1,32 @@
+/*
+ *  cx18 video interface functions
+ *
+ *  Copyright (C) 2007  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., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307  USA
+ */
+
+#include "cx18-driver.h"
+#include "cx18-video.h"
+#include "cx18-cards.h"
+
+void cx18_video_set_io(struct cx18 *cx)
+{
+	int inp = cx->active_input;
+
+	v4l2_subdev_call(cx->sd_av, video, s_routing,
+			cx->card->video_inputs[inp].video_input, 0, 0);
+}
diff --git a/drivers/media/pci/cx18/cx18-video.h b/drivers/media/pci/cx18/cx18-video.h
new file mode 100644
index 0000000..529006a
--- /dev/null
+++ b/drivers/media/pci/cx18/cx18-video.h
@@ -0,0 +1,22 @@
+/*
+ *  cx18 video interface functions
+ *
+ *  Copyright (C) 2007  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., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307  USA
+ */
+
+void cx18_video_set_io(struct cx18 *cx);
diff --git a/drivers/media/pci/cx18/cx23418.h b/drivers/media/pci/cx18/cx23418.h
new file mode 100644
index 0000000..767a8d2
--- /dev/null
+++ b/drivers/media/pci/cx18/cx23418.h
@@ -0,0 +1,492 @@
+/*
+ *  cx18 header containing common defines.
+ *
+ *  Copyright (C) 2007  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., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307  USA
+ */
+
+#ifndef CX23418_H
+#define CX23418_H
+
+#include <media/cx2341x.h>
+
+#define MGR_CMD_MASK            		0x40000000
+/* The MSB of the command code indicates that this is the completion of a
+   command */
+#define MGR_CMD_MASK_ACK        		(MGR_CMD_MASK | 0x80000000)
+
+/* Description: This command creates a new instance of a certain task
+   IN[0]  - Task ID. This is one of the XPU_CMD_MASK_YYY where XPU is
+	    the processor on which the task YYY will be created
+   OUT[0] - Task handle. This handle is passed along with commands to
+	    dispatch to the right instance of the task
+   ReturnCode - One of the ERR_SYS_... */
+#define CX18_CREATE_TASK      			(MGR_CMD_MASK | 0x0001)
+
+/* Description: This command destroys an instance of a task
+   IN[0] - Task handle. Hanlde of the task to destroy
+   ReturnCode - One of the ERR_SYS_... */
+#define CX18_DESTROY_TASK     			(MGR_CMD_MASK | 0x0002)
+
+/* All commands for CPU have the following mask set */
+#define CPU_CMD_MASK                        	0x20000000
+#define CPU_CMD_MASK_DEBUG       		(CPU_CMD_MASK | 0x00000000)
+#define CPU_CMD_MASK_ACK                    	(CPU_CMD_MASK | 0x80000000)
+#define CPU_CMD_MASK_CAPTURE                	(CPU_CMD_MASK | 0x00020000)
+#define CPU_CMD_MASK_TS                     	(CPU_CMD_MASK | 0x00040000)
+
+#define EPU_CMD_MASK                        	0x02000000
+#define EPU_CMD_MASK_DEBUG       		(EPU_CMD_MASK | 0x000000)
+#define EPU_CMD_MASK_DE                     	(EPU_CMD_MASK | 0x040000)
+
+#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
+   filled with the requested channel type
+   IN[0] - Task handle. Handle of the task
+   IN[1] - Offset of the MDL_ACK from the beginning of the local DDR.
+   IN[2] - Number of CNXT_MDL_ACK structures in the array pointed to by IN[1]
+   ReturnCode - One of the ERR_DE_... */
+#define CX18_EPU_DMA_DONE              		(EPU_CMD_MASK_DE | 0x0001)
+
+/* Something interesting happened
+   IN[0] - A value to log
+   IN[1] - An offset of a string in the MiniMe memory;
+	   0/zero/NULL means "I have nothing to say" */
+#define CX18_EPU_DEBUG 				(EPU_CMD_MASK_DEBUG | 0x0003)
+
+/* Reads memory/registers (32-bit)
+   IN[0] - Address
+   OUT[1] - Value */
+#define CX18_CPU_DEBUG_PEEK32			(CPU_CMD_MASK_DEBUG | 0x0003)
+
+/* Description: This command starts streaming with the set channel type
+   IN[0] - Task handle. Handle of the task to start
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_CAPTURE_START               	(CPU_CMD_MASK_CAPTURE | 0x0002)
+
+/* Description: This command stops streaming with the set channel type
+   IN[0] - Task handle. Handle of the task to stop
+   IN[1] - 0 = stop at end of GOP, 1 = stop at end of frame (MPEG only)
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_CAPTURE_STOP                	(CPU_CMD_MASK_CAPTURE | 0x0003)
+
+/* Description: This command pauses streaming with the set channel type
+   IN[0] - Task handle. Handle of the task to pause
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_CAPTURE_PAUSE               	(CPU_CMD_MASK_CAPTURE | 0x0007)
+
+/* Description: This command resumes streaming with the set channel type
+   IN[0] - Task handle. Handle of the task to resume
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_CAPTURE_RESUME              	(CPU_CMD_MASK_CAPTURE | 0x0008)
+
+#define CAPTURE_CHANNEL_TYPE_NONE  		0
+#define CAPTURE_CHANNEL_TYPE_MPEG  		1
+#define CAPTURE_CHANNEL_TYPE_INDEX 		2
+#define CAPTURE_CHANNEL_TYPE_YUV   		3
+#define CAPTURE_CHANNEL_TYPE_PCM   		4
+#define CAPTURE_CHANNEL_TYPE_VBI   		5
+#define CAPTURE_CHANNEL_TYPE_SLICED_VBI		6
+#define CAPTURE_CHANNEL_TYPE_TS			7
+#define CAPTURE_CHANNEL_TYPE_MAX   		15
+
+/* Description: This command sets the channel type. This can only be done
+   when stopped.
+   IN[0] - Task handle. Handle of the task to start
+   IN[1] - Channel Type. See Below.
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_CHANNEL_TYPE      		(CPU_CMD_MASK_CAPTURE + 1)
+
+/* Description: Set stream output type
+   IN[0] - task handle. Handle of the task to start
+   IN[1] - type
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_STREAM_OUTPUT_TYPE		(CPU_CMD_MASK_CAPTURE | 0x0012)
+
+/* Description: Set video input resolution and frame rate
+   IN[0] - task handle
+   IN[1] - reserved
+   IN[2] - reserved
+   IN[3] - reserved
+   IN[4] - reserved
+   IN[5] - frame rate, 0 - 29.97f/s, 1 - 25f/s
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_VIDEO_IN                	(CPU_CMD_MASK_CAPTURE | 0x0004)
+
+/* Description: Set video frame rate
+   IN[0] - task handle. Handle of the task to start
+   IN[1] - video bit rate mode
+   IN[2] - video average rate
+   IN[3] - video peak rate
+   IN[4] - system mux rate
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_VIDEO_RATE              	(CPU_CMD_MASK_CAPTURE | 0x0005)
+
+/* Description: Set video output resolution
+   IN[0] - task handle
+   IN[1] - horizontal size
+   IN[2] - vertical size
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_VIDEO_RESOLUTION		(CPU_CMD_MASK_CAPTURE | 0x0006)
+
+/* Description: This command set filter parameters
+   IN[0] - Task handle. Handle of the task
+   IN[1] - type, 0 - temporal, 1 - spatial, 2 - median
+   IN[2] - mode,  temporal/spatial: 0 - disable, 1 - static, 2 - dynamic
+			median:	0 = disable, 1 = horizontal, 2 = vertical,
+				3 = horizontal/vertical, 4 = diagonal
+   IN[3] - strength, temporal 0 - 31, spatial 0 - 15
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_FILTER_PARAM            	(CPU_CMD_MASK_CAPTURE | 0x0009)
+
+/* Description: This command set spatial filter type
+   IN[0] - Task handle.
+   IN[1] - luma type: 0 = disable, 1 = 1D horizontal only, 2 = 1D vertical only,
+		      3 = 2D H/V separable, 4 = 2D symmetric non-separable
+   IN[2] - chroma type: 0 - disable, 1 = 1D horizontal
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_SPATIAL_FILTER_TYPE     	(CPU_CMD_MASK_CAPTURE | 0x000C)
+
+/* Description: This command set coring levels for median filter
+   IN[0] - Task handle.
+   IN[1] - luma_high
+   IN[2] - luma_low
+   IN[3] - chroma_high
+   IN[4] - chroma_low
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_MEDIAN_CORING           	(CPU_CMD_MASK_CAPTURE | 0x000E)
+
+/* Description: This command set the picture type mask for index file
+   IN[0] - Task handle (ignored by firmware)
+   IN[1] - 	0 = disable index file output
+			1 = output I picture
+			2 = P picture
+			4 = B picture
+			other = illegal */
+#define CX18_CPU_SET_INDEXTABLE         	(CPU_CMD_MASK_CAPTURE | 0x0010)
+
+/* Description: Set audio parameters
+   IN[0] - task handle. Handle of the task to start
+   IN[1] - audio parameter
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_AUDIO_PARAMETERS		(CPU_CMD_MASK_CAPTURE | 0x0011)
+
+/* Description: Set video mute
+   IN[0] - task handle. Handle of the task to start
+   IN[1] - bit31-24: muteYvalue
+	   bit23-16: muteUvalue
+	   bit15-8:  muteVvalue
+	   bit0:     1:mute, 0: unmute
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_VIDEO_MUTE			(CPU_CMD_MASK_CAPTURE | 0x0013)
+
+/* Description: Set audio mute
+   IN[0] - task handle. Handle of the task to start
+   IN[1] - mute/unmute
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_AUDIO_MUTE			(CPU_CMD_MASK_CAPTURE | 0x0014)
+
+/* Description: Set stream output type
+   IN[0] - task handle. Handle of the task to start
+   IN[1] - subType
+	    SET_INITIAL_SCR      		1
+	    SET_QUALITY_MODE            2
+	    SET_VIM_PROTECT_MODE        3
+	    SET_PTS_CORRECTION          4
+	    SET_USB_FLUSH_MODE          5
+	    SET_MERAQPAR_ENABLE         6
+	    SET_NAV_PACK_INSERTION      7
+	    SET_SCENE_CHANGE_ENABLE     8
+   IN[2] - parameter 1
+   IN[3] - parameter 2
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_MISC_PARAMETERS		(CPU_CMD_MASK_CAPTURE | 0x0015)
+
+/* Description: Set raw VBI parameters
+   IN[0] - Task handle
+   IN[1] - No. of input lines per field:
+				bit[15:0]: field 1,
+				bit[31:16]: field 2
+   IN[2] - No. of input bytes per line
+   IN[3] - No. of output frames per transfer
+   IN[4] - start code
+   IN[5] - stop code
+   ReturnCode */
+#define CX18_CPU_SET_RAW_VBI_PARAM		(CPU_CMD_MASK_CAPTURE | 0x0016)
+
+/* Description: Set capture line No.
+   IN[0] - task handle. Handle of the task to start
+   IN[1] - height1
+   IN[2] - height2
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_CAPTURE_LINE_NO		(CPU_CMD_MASK_CAPTURE | 0x0017)
+
+/* Description: Set copyright
+   IN[0] - task handle. Handle of the task to start
+   IN[1] - copyright
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_COPYRIGHT			(CPU_CMD_MASK_CAPTURE | 0x0018)
+
+/* Description: Set audio PID
+   IN[0] - task handle. Handle of the task to start
+   IN[1] - PID
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_AUDIO_PID			(CPU_CMD_MASK_CAPTURE | 0x0019)
+
+/* Description: Set video PID
+   IN[0] - task handle. Handle of the task to start
+   IN[1] - PID
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_VIDEO_PID			(CPU_CMD_MASK_CAPTURE | 0x001A)
+
+/* Description: Set Vertical Crop Line
+   IN[0] - task handle. Handle of the task to start
+   IN[1] - Line
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_VER_CROP_LINE		(CPU_CMD_MASK_CAPTURE | 0x001B)
+
+/* Description: Set COP structure
+   IN[0] - task handle. Handle of the task to start
+   IN[1] - M
+   IN[2] - N
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_GOP_STRUCTURE		(CPU_CMD_MASK_CAPTURE | 0x001C)
+
+/* Description: Set Scene Change Detection
+   IN[0] - task handle. Handle of the task to start
+   IN[1] - scene change
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_SCENE_CHANGE_DETECTION	(CPU_CMD_MASK_CAPTURE | 0x001D)
+
+/* Description: Set Aspect Ratio
+   IN[0] - task handle. Handle of the task to start
+   IN[1] - AspectRatio
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_ASPECT_RATIO		(CPU_CMD_MASK_CAPTURE | 0x001E)
+
+/* Description: Set Skip Input Frame
+   IN[0] - task handle. Handle of the task to start
+   IN[1] - skip input frames
+   ReturnCode - One of the ERR_CAPTURE_... */
+#define CX18_CPU_SET_SKIP_INPUT_FRAME		(CPU_CMD_MASK_CAPTURE | 0x001F)
+
+/* Description: Set sliced VBI parameters -
+   Note This API will only apply to MPEG and Sliced VBI Channels
+   IN[0] - Task handle
+   IN[1] - output type, 0 - CC, 1 - Moji, 2 - Teletext
+   IN[2] - start / stop line
+			bit[15:0] start line number
+			bit[31:16] stop line number
+   IN[3] - number of output frames per interrupt
+   IN[4] - VBI insertion mode
+			bit 0:	output user data, 1 - enable
+			bit 1:	output private stream, 1 - enable
+			bit 2:	mux option, 0 - in GOP, 1 - in picture
+			bit[7:0] 	private stream ID
+   IN[5] - insertion period while mux option is in picture
+   ReturnCode - VBI data offset */
+#define CX18_CPU_SET_SLICED_VBI_PARAM		(CPU_CMD_MASK_CAPTURE | 0x0020)
+
+/* Description: Set the user data place holder
+   IN[0] - type of data (0 for user)
+   IN[1] - Stuffing period
+   IN[2] - ID data size in word (less than 10)
+   IN[3] - Pointer to ID buffer */
+#define CX18_CPU_SET_USERDATA_PLACE_HOLDER	(CPU_CMD_MASK_CAPTURE | 0x0021)
+
+
+/* Description:
+   In[0] Task Handle
+   return parameter:
+   Out[0]  Reserved
+   Out[1]  Video PTS bit[32:2] of last output video frame.
+   Out[2]  Video PTS bit[ 1:0] of last output video frame.
+   Out[3]  Hardware Video PTS counter bit[31:0],
+	     these bits get incremented on every 90kHz clock tick.
+   Out[4]  Hardware Video PTS counter bit32,
+	     these bits get incremented on every 90kHz clock tick.
+   ReturnCode */
+#define CX18_CPU_GET_ENC_PTS			(CPU_CMD_MASK_CAPTURE | 0x0022)
+
+/* Description: Set VFC parameters
+   IN[0] - task handle
+   IN[1] - VFC enable flag, 1 - enable, 0 - disable
+*/
+#define CX18_CPU_SET_VFC_PARAM                  (CPU_CMD_MASK_CAPTURE | 0x0023)
+
+/* Below is the list of commands related to the data exchange */
+#define CPU_CMD_MASK_DE 			(CPU_CMD_MASK | 0x040000)
+
+/* Description: This command provides the physical base address of the local
+   DDR as viewed by EPU
+   IN[0] - Physical offset where EPU has the local DDR mapped
+   ReturnCode - One of the ERR_DE_... */
+#define CPU_CMD_DE_SetBase 			(CPU_CMD_MASK_DE | 0x0001)
+
+/* Description: This command provides the offsets in the device memory where
+   the 2 cx18_mdl_ack blocks reside
+   IN[0] - Task handle. Handle of the task to start
+   IN[1] - Offset of the first cx18_mdl_ack from the beginning of the
+	   local DDR.
+   IN[2] - Offset of the second cx18_mdl_ack from the beginning of the
+	   local DDR.
+   ReturnCode - One of the ERR_DE_... */
+#define CX18_CPU_DE_SET_MDL_ACK                	(CPU_CMD_MASK_DE | 0x0002)
+
+/* Description: This command provides the offset to a Memory Descriptor List
+   IN[0] - Task handle. Handle of the task to start
+   IN[1] - Offset of the MDL from the beginning of the local DDR.
+   IN[2] - Number of cx18_mdl_ent structures in the array pointed to by IN[1]
+   IN[3] - Buffer ID
+   IN[4] - Total buffer length
+   ReturnCode - One of the ERR_DE_... */
+#define CX18_CPU_DE_SET_MDL                   	(CPU_CMD_MASK_DE | 0x0005)
+
+/* Description: This command requests return of all current Memory
+   Descriptor Lists to the driver
+   IN[0] - Task handle. Handle of the task to start
+   ReturnCode - One of the ERR_DE_... */
+#define CX18_CPU_DE_RELEASE_MDL               	(CPU_CMD_MASK_DE | 0x0006)
+
+/* Description: This command signals the cpu that the dat buffer has been
+   consumed and ready for re-use.
+   IN[0] - Task handle. Handle of the task
+   IN[1] - Offset of the data block from the beginning of the local DDR.
+   IN[2] - Number of bytes in the data block
+   ReturnCode - One of the ERR_DE_... */
+/* #define CX18_CPU_DE_RELEASE_BUFFER           (CPU_CMD_MASK_DE | 0x0007) */
+
+/* No Error / Success */
+#define CNXT_OK                 0x000000
+
+/* Received unknown command */
+#define CXERR_UNK_CMD           0x000001
+
+/* First parameter in the command is invalid */
+#define CXERR_INVALID_PARAM1    0x000002
+
+/* Second parameter in the command is invalid */
+#define CXERR_INVALID_PARAM2    0x000003
+
+/* Device interface is not open/found */
+#define CXERR_DEV_NOT_FOUND     0x000004
+
+/* Requested function is not implemented/available */
+#define CXERR_NOTSUPPORTED      0x000005
+
+/* Invalid pointer is provided */
+#define CXERR_BADPTR            0x000006
+
+/* Unable to allocate memory */
+#define CXERR_NOMEM             0x000007
+
+/* Object/Link not found */
+#define CXERR_LINK              0x000008
+
+/* Device busy, command cannot be executed */
+#define CXERR_BUSY              0x000009
+
+/* File/device/handle is not open. */
+#define CXERR_NOT_OPEN          0x00000A
+
+/* Value is out of range */
+#define CXERR_OUTOFRANGE        0x00000B
+
+/* Buffer overflow */
+#define CXERR_OVERFLOW          0x00000C
+
+/* Version mismatch */
+#define CXERR_BADVER            0x00000D
+
+/* Operation timed out */
+#define CXERR_TIMEOUT           0x00000E
+
+/* Operation aborted */
+#define CXERR_ABORT             0x00000F
+
+/* Specified I2C device not found for read/write */
+#define CXERR_I2CDEV_NOTFOUND   0x000010
+
+/* Error in I2C data xfer (but I2C device is present) */
+#define CXERR_I2CDEV_XFERERR    0x000011
+
+/* Chanel changing component not ready */
+#define CXERR_CHANNELNOTREADY   0x000012
+
+/* PPU (Presensation/Decoder) mail box is corrupted */
+#define CXERR_PPU_MB_CORRUPT    0x000013
+
+/* CPU (Capture/Encoder) mail box is corrupted */
+#define CXERR_CPU_MB_CORRUPT    0x000014
+
+/* APU (Audio) mail box is corrupted */
+#define CXERR_APU_MB_CORRUPT    0x000015
+
+/* Unable to open file for reading */
+#define CXERR_FILE_OPEN_READ    0x000016
+
+/* Unable to open file for writing */
+#define CXERR_FILE_OPEN_WRITE   0x000017
+
+/* Unable to find the I2C section specified */
+#define CXERR_I2C_BADSECTION    0x000018
+
+/* Error in I2C data xfer (but I2C device is present) */
+#define CXERR_I2CDEV_DATALOW    0x000019
+
+/* Error in I2C data xfer (but I2C device is present) */
+#define CXERR_I2CDEV_CLOCKLOW   0x00001A
+
+/* No Interrupt received from HW (for I2C access) */
+#define CXERR_NO_HW_I2C_INTR    0x00001B
+
+/* RPU is not ready to accept commands! */
+#define CXERR_RPU_NOT_READY     0x00001C
+
+/* RPU is not ready to accept commands! */
+#define CXERR_RPU_NO_ACK        0x00001D
+
+/* The are no buffers ready. Try again soon! */
+#define CXERR_NODATA_AGAIN      0x00001E
+
+/* The stream is stopping. Function not allowed now! */
+#define CXERR_STOPPING_STATUS   0x00001F
+
+/* Trying to access hardware when the power is turned OFF */
+#define CXERR_DEVPOWER_OFF      0x000020
+
+#endif /* CX23418_H */
diff --git a/drivers/media/pci/cx23885/Kconfig b/drivers/media/pci/cx23885/Kconfig
new file mode 100644
index 0000000..4b99a26
--- /dev/null
+++ b/drivers/media/pci/cx23885/Kconfig
@@ -0,0 +1,48 @@
+config VIDEO_CX23885
+	tristate "Conexant cx23885 (2388x successor) support"
+	depends on DVB_CORE && VIDEO_DEV && PCI && I2C && INPUT && SND
+	select SND_PCM
+	select I2C_ALGOBIT
+	select VIDEO_BTCX
+	select VIDEO_TUNER
+	select VIDEO_TVEEPROM
+	depends on RC_CORE
+	select VIDEOBUF_DVB
+	select VIDEOBUF_DMA_SG
+	select VIDEO_CX25840
+	select VIDEO_CX2341X
+	select DVB_DIB7000P if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_S5H1409 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_S5H1411 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_LGDT330X if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_ZL10353 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_TDA10048 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_LNBP21 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_STV090x if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_STB6100 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_STV6110 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_CX24116 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_STV0900 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_DS3000 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_STV0367 if MEDIA_SUBDRV_AUTOSELECT
+	select MEDIA_TUNER_MT2131 if MEDIA_SUBDRV_AUTOSELECT
+	select MEDIA_TUNER_XC2028 if MEDIA_SUBDRV_AUTOSELECT
+	select MEDIA_TUNER_TDA8290 if MEDIA_SUBDRV_AUTOSELECT
+	select MEDIA_TUNER_TDA18271 if MEDIA_SUBDRV_AUTOSELECT
+	select MEDIA_TUNER_XC5000 if MEDIA_SUBDRV_AUTOSELECT
+	---help---
+	  This is a video4linux driver for Conexant 23885 based
+	  TV cards.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called cx23885
+
+config MEDIA_ALTERA_CI
+	tristate "Altera FPGA based CI module"
+	depends on VIDEO_CX23885 && DVB_CORE
+	select ALTERA_STAPL
+	---help---
+	  An Altera FPGA CI module for NetUP Dual DVB-T/C RF CI card.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called altera-ci
diff --git a/drivers/media/pci/cx23885/Makefile b/drivers/media/pci/cx23885/Makefile
new file mode 100644
index 0000000..a2cbdcf
--- /dev/null
+++ b/drivers/media/pci/cx23885/Makefile
@@ -0,0 +1,15 @@
+cx23885-objs	:= cx23885-cards.o cx23885-video.o cx23885-vbi.o \
+		    cx23885-core.o cx23885-i2c.o cx23885-dvb.o cx23885-417.o \
+		    cx23885-ioctl.o cx23885-ir.o cx23885-av.o cx23885-input.o \
+		    cx23888-ir.o netup-init.o cimax2.o netup-eeprom.o \
+		    cx23885-f300.o cx23885-alsa.o
+
+obj-$(CONFIG_VIDEO_CX23885) += cx23885.o
+obj-$(CONFIG_MEDIA_ALTERA_CI) += altera-ci.o
+
+ccflags-y += -Idrivers/media/i2c
+ccflags-y += -Idrivers/media/tuners
+ccflags-y += -Idrivers/media/dvb-core
+ccflags-y += -Idrivers/media/dvb-frontends
+
+ccflags-y += $(extra-cflags-y) $(extra-cflags-m)
diff --git a/drivers/media/pci/cx23885/altera-ci.c b/drivers/media/pci/cx23885/altera-ci.c
new file mode 100644
index 0000000..aee7f0d
--- /dev/null
+++ b/drivers/media/pci/cx23885/altera-ci.c
@@ -0,0 +1,839 @@
+/*
+ * altera-ci.c
+ *
+ *  CI driver in conjunction with NetUp Dual DVB-T/C RF CI card
+ *
+ * Copyright (C) 2010,2011 NetUP Inc.
+ * Copyright (C) 2010,2011 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.
+ */
+
+/*
+ * currently cx23885 GPIO's used.
+ * GPIO-0 ~INT in
+ * GPIO-1 TMS out
+ * GPIO-2 ~reset chips out
+ * GPIO-3 to GPIO-10 data/addr for CA in/out
+ * GPIO-11 ~CS out
+ * GPIO-12 AD_RG out
+ * GPIO-13 ~WR out
+ * GPIO-14 ~RD out
+ * GPIO-15 ~RDY in
+ * GPIO-16 TCK out
+ * GPIO-17 TDO in
+ * GPIO-18 TDI out
+ */
+/*
+ *  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
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * |  TDI  |  TDO  |  TCK  |  RDY# |  #RD  |  #WR  | AD_RG |  #CS  |
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ *  bit 7   bit 6   bit 5   bit 4   bit 3   bit 2   bit 1   bit 0
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * |  DATA7|  DATA6|  DATA5|  DATA4|  DATA3|  DATA2|  DATA1|  DATA0|
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ */
+#include <media/videobuf-dma-sg.h>
+#include <media/videobuf-dvb.h>
+#include "altera-ci.h"
+#include "dvb_ca_en50221.h"
+
+/* FPGA regs */
+#define NETUP_CI_INT_CTRL	0x00
+#define NETUP_CI_BUSCTRL2	0x01
+#define NETUP_CI_ADDR0		0x04
+#define NETUP_CI_ADDR1		0x05
+#define NETUP_CI_DATA		0x06
+#define NETUP_CI_BUSCTRL	0x07
+#define NETUP_CI_PID_ADDR0	0x08
+#define NETUP_CI_PID_ADDR1	0x09
+#define NETUP_CI_PID_DATA	0x0a
+#define NETUP_CI_TSA_DIV	0x0c
+#define NETUP_CI_TSB_DIV	0x0d
+#define NETUP_CI_REVISION	0x0f
+
+/* const for ci op */
+#define NETUP_CI_FLG_CTL	1
+#define NETUP_CI_FLG_RD		1
+#define NETUP_CI_FLG_AD		1
+
+static unsigned int ci_dbg;
+module_param(ci_dbg, int, 0644);
+MODULE_PARM_DESC(ci_dbg, "Enable CI debugging");
+
+static unsigned int pid_dbg;
+module_param(pid_dbg, int, 0644);
+MODULE_PARM_DESC(pid_dbg, "Enable PID filtering debugging");
+
+MODULE_DESCRIPTION("altera FPGA CI module");
+MODULE_AUTHOR("Igor M. Liplianin  <liplianin@netup.ru>");
+MODULE_LICENSE("GPL");
+
+#define ci_dbg_print(args...) \
+	do { \
+		if (ci_dbg) \
+			printk(KERN_DEBUG args); \
+	} while (0)
+
+#define pid_dbg_print(args...) \
+	do { \
+		if (pid_dbg) \
+			printk(KERN_DEBUG args); \
+	} while (0)
+
+struct altera_ci_state;
+struct netup_hw_pid_filter;
+
+struct fpga_internal {
+	void *dev;
+	struct mutex fpga_mutex;/* two CI's on the same fpga */
+	struct netup_hw_pid_filter *pid_filt[2];
+	struct altera_ci_state *state[2];
+	struct work_struct work;
+	int (*fpga_rw) (void *dev, int flag, int data, int rw);
+	int cis_used;
+	int filts_used;
+	int strt_wrk;
+};
+
+/* stores all private variables for communication with CI */
+struct altera_ci_state {
+	struct fpga_internal *internal;
+	struct dvb_ca_en50221 ca;
+	int status;
+	int nr;
+};
+
+/* stores all private variables for hardware pid filtering */
+struct netup_hw_pid_filter {
+	struct fpga_internal *internal;
+	struct dvb_demux *demux;
+	/* save old functions */
+	int (*start_feed)(struct dvb_demux_feed *feed);
+	int (*stop_feed)(struct dvb_demux_feed *feed);
+
+	int status;
+	int nr;
+};
+
+/* internal params node */
+struct fpga_inode {
+	/* pointer for internal params, one for each pair of CI's */
+	struct fpga_internal		*internal;
+	struct fpga_inode		*next_inode;
+};
+
+/* first internal params */
+static struct fpga_inode *fpga_first_inode;
+
+/* find chip by dev */
+static struct fpga_inode *find_inode(void *dev)
+{
+	struct fpga_inode *temp_chip = fpga_first_inode;
+
+	if (temp_chip == NULL)
+		return temp_chip;
+
+	/*
+	 Search for the last fpga CI chip or
+	 find it by dev */
+	while ((temp_chip != NULL) &&
+				(temp_chip->internal->dev != dev))
+		temp_chip = temp_chip->next_inode;
+
+	return temp_chip;
+}
+/* check demux */
+static struct fpga_internal *check_filter(struct fpga_internal *temp_int,
+						void *demux_dev, int filt_nr)
+{
+	if (temp_int == NULL)
+		return NULL;
+
+	if ((temp_int->pid_filt[filt_nr]) == NULL)
+		return NULL;
+
+	if (temp_int->pid_filt[filt_nr]->demux == demux_dev)
+		return temp_int;
+
+	return NULL;
+}
+
+/* find chip by demux */
+static struct fpga_inode *find_dinode(void *demux_dev)
+{
+	struct fpga_inode *temp_chip = fpga_first_inode;
+	struct fpga_internal *temp_int;
+
+	/*
+	 * Search of the last fpga CI chip or
+	 * find it by demux
+	 */
+	while (temp_chip != NULL) {
+		if (temp_chip->internal != NULL) {
+			temp_int = temp_chip->internal;
+			if (check_filter(temp_int, demux_dev, 0))
+				break;
+			if (check_filter(temp_int, demux_dev, 1))
+				break;
+		}
+
+		temp_chip = temp_chip->next_inode;
+	}
+
+	return temp_chip;
+}
+
+/* deallocating chip */
+static void remove_inode(struct fpga_internal *internal)
+{
+	struct fpga_inode *prev_node = fpga_first_inode;
+	struct fpga_inode *del_node = find_inode(internal->dev);
+
+	if (del_node != NULL) {
+		if (del_node == fpga_first_inode) {
+			fpga_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 fpga_inode *append_internal(struct fpga_internal *internal)
+{
+	struct fpga_inode *new_node = fpga_first_inode;
+
+	if (new_node == NULL) {
+		new_node = kmalloc(sizeof(struct fpga_inode), GFP_KERNEL);
+		fpga_first_inode = new_node;
+	} else {
+		while (new_node->next_inode != NULL)
+			new_node = new_node->next_inode;
+
+		new_node->next_inode =
+				kmalloc(sizeof(struct fpga_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;
+}
+
+static int netup_fpga_op_rw(struct fpga_internal *inter, int addr,
+							u8 val, u8 read)
+{
+	inter->fpga_rw(inter->dev, NETUP_CI_FLG_AD, addr, 0);
+	return inter->fpga_rw(inter->dev, 0, val, read);
+}
+
+/* flag - mem/io, read - read/write */
+int altera_ci_op_cam(struct dvb_ca_en50221 *en50221, int slot,
+				u8 flag, u8 read, int addr, u8 val)
+{
+
+	struct altera_ci_state *state = en50221->data;
+	struct fpga_internal *inter = state->internal;
+
+	u8 store;
+	int mem = 0;
+
+	if (0 != slot)
+		return -EINVAL;
+
+	mutex_lock(&inter->fpga_mutex);
+
+	netup_fpga_op_rw(inter, NETUP_CI_ADDR0, ((addr << 1) & 0xfe), 0);
+	netup_fpga_op_rw(inter, NETUP_CI_ADDR1, ((addr >> 7) & 0x7f), 0);
+	store = netup_fpga_op_rw(inter, NETUP_CI_BUSCTRL, 0, NETUP_CI_FLG_RD);
+
+	store &= 0x0f;
+	store |= ((state->nr << 7) | (flag << 6));
+
+	netup_fpga_op_rw(inter, NETUP_CI_BUSCTRL, store, 0);
+	mem = netup_fpga_op_rw(inter, NETUP_CI_DATA, val, read);
+
+	mutex_unlock(&inter->fpga_mutex);
+
+	ci_dbg_print("%s: %s: addr=[0x%02x], %s=%x\n", __func__,
+			(read) ? "read" : "write", addr,
+			(flag == NETUP_CI_FLG_CTL) ? "ctl" : "mem",
+			(read) ? mem : val);
+
+	return mem;
+}
+
+int altera_ci_read_attribute_mem(struct dvb_ca_en50221 *en50221,
+						int slot, int addr)
+{
+	return altera_ci_op_cam(en50221, slot, 0, NETUP_CI_FLG_RD, addr, 0);
+}
+
+int altera_ci_write_attribute_mem(struct dvb_ca_en50221 *en50221,
+						int slot, int addr, u8 data)
+{
+	return altera_ci_op_cam(en50221, slot, 0, 0, addr, data);
+}
+
+int altera_ci_read_cam_ctl(struct dvb_ca_en50221 *en50221, int slot, u8 addr)
+{
+	return altera_ci_op_cam(en50221, slot, NETUP_CI_FLG_CTL,
+						NETUP_CI_FLG_RD, addr, 0);
+}
+
+int altera_ci_write_cam_ctl(struct dvb_ca_en50221 *en50221, int slot,
+						u8 addr, u8 data)
+{
+	return altera_ci_op_cam(en50221, slot, NETUP_CI_FLG_CTL, 0, addr, data);
+}
+
+int altera_ci_slot_reset(struct dvb_ca_en50221 *en50221, int slot)
+{
+	struct altera_ci_state *state = en50221->data;
+	struct fpga_internal *inter = state->internal;
+	/* reasonable timeout for CI reset is 10 seconds */
+	unsigned long t_out = jiffies + msecs_to_jiffies(9999);
+	int ret;
+
+	ci_dbg_print("%s\n", __func__);
+
+	if (0 != slot)
+		return -EINVAL;
+
+	mutex_lock(&inter->fpga_mutex);
+
+	ret = netup_fpga_op_rw(inter, NETUP_CI_BUSCTRL, 0, NETUP_CI_FLG_RD);
+	netup_fpga_op_rw(inter, NETUP_CI_BUSCTRL,
+				(ret & 0xcf) | (1 << (5 - state->nr)), 0);
+
+	mutex_unlock(&inter->fpga_mutex);
+
+	for (;;) {
+		mdelay(50);
+
+		mutex_lock(&inter->fpga_mutex);
+
+		ret = netup_fpga_op_rw(inter, NETUP_CI_BUSCTRL,
+						0, NETUP_CI_FLG_RD);
+		mutex_unlock(&inter->fpga_mutex);
+
+		if ((ret & (1 << (5 - state->nr))) == 0)
+			break;
+		if (time_after(jiffies, t_out))
+			break;
+	}
+
+
+	ci_dbg_print("%s: %d msecs\n", __func__,
+		jiffies_to_msecs(jiffies + msecs_to_jiffies(9999) - t_out));
+
+	return 0;
+}
+
+int altera_ci_slot_shutdown(struct dvb_ca_en50221 *en50221, int slot)
+{
+	/* not implemented */
+	return 0;
+}
+
+int altera_ci_slot_ts_ctl(struct dvb_ca_en50221 *en50221, int slot)
+{
+	struct altera_ci_state *state = en50221->data;
+	struct fpga_internal *inter = state->internal;
+	int ret;
+
+	ci_dbg_print("%s\n", __func__);
+
+	if (0 != slot)
+		return -EINVAL;
+
+	mutex_lock(&inter->fpga_mutex);
+
+	ret = netup_fpga_op_rw(inter, NETUP_CI_BUSCTRL, 0, NETUP_CI_FLG_RD);
+	netup_fpga_op_rw(inter, NETUP_CI_BUSCTRL,
+				(ret & 0x0f) | (1 << (3 - state->nr)), 0);
+
+	mutex_unlock(&inter->fpga_mutex);
+
+	return 0;
+}
+
+/* work handler */
+static void netup_read_ci_status(struct work_struct *work)
+{
+	struct fpga_internal *inter =
+			container_of(work, struct fpga_internal, work);
+	int ret;
+
+	ci_dbg_print("%s\n", __func__);
+
+	mutex_lock(&inter->fpga_mutex);
+	/* ack' irq */
+	ret = netup_fpga_op_rw(inter, NETUP_CI_INT_CTRL, 0, NETUP_CI_FLG_RD);
+	ret = netup_fpga_op_rw(inter, NETUP_CI_BUSCTRL, 0, NETUP_CI_FLG_RD);
+
+	mutex_unlock(&inter->fpga_mutex);
+
+	if (inter->state[1] != NULL) {
+		inter->state[1]->status =
+				((ret & 1) == 0 ?
+				DVB_CA_EN50221_POLL_CAM_PRESENT |
+				DVB_CA_EN50221_POLL_CAM_READY : 0);
+		ci_dbg_print("%s: setting CI[1] status = 0x%x\n",
+				__func__, inter->state[1]->status);
+	};
+
+	if (inter->state[0] != NULL) {
+		inter->state[0]->status =
+				((ret & 2) == 0 ?
+				DVB_CA_EN50221_POLL_CAM_PRESENT |
+				DVB_CA_EN50221_POLL_CAM_READY : 0);
+		ci_dbg_print("%s: setting CI[0] status = 0x%x\n",
+				__func__, inter->state[0]->status);
+	};
+}
+
+/* CI irq handler */
+int altera_ci_irq(void *dev)
+{
+	struct fpga_inode *temp_int = NULL;
+	struct fpga_internal *inter = NULL;
+
+	ci_dbg_print("%s\n", __func__);
+
+	if (dev != NULL) {
+		temp_int = find_inode(dev);
+		if (temp_int != NULL) {
+			inter = temp_int->internal;
+			schedule_work(&inter->work);
+		}
+	}
+
+	return 1;
+}
+EXPORT_SYMBOL(altera_ci_irq);
+
+int altera_poll_ci_slot_status(struct dvb_ca_en50221 *en50221, int slot,
+								int open)
+{
+	struct altera_ci_state *state = en50221->data;
+
+	if (0 != slot)
+		return -EINVAL;
+
+	return state->status;
+}
+
+void altera_hw_filt_release(void *main_dev, int filt_nr)
+{
+	struct fpga_inode *temp_int = find_inode(main_dev);
+	struct netup_hw_pid_filter *pid_filt = NULL;
+
+	ci_dbg_print("%s\n", __func__);
+
+	if (temp_int != NULL) {
+		pid_filt = temp_int->internal->pid_filt[filt_nr - 1];
+		/* stored old feed controls */
+		pid_filt->demux->start_feed = pid_filt->start_feed;
+		pid_filt->demux->stop_feed = pid_filt->stop_feed;
+
+		if (((--(temp_int->internal->filts_used)) <= 0) &&
+			 ((temp_int->internal->cis_used) <= 0)) {
+
+			ci_dbg_print("%s: Actually removing\n", __func__);
+
+			remove_inode(temp_int->internal);
+			kfree(pid_filt->internal);
+		}
+
+		kfree(pid_filt);
+
+	}
+
+}
+EXPORT_SYMBOL(altera_hw_filt_release);
+
+void altera_ci_release(void *dev, int ci_nr)
+{
+	struct fpga_inode *temp_int = find_inode(dev);
+	struct altera_ci_state *state = NULL;
+
+	ci_dbg_print("%s\n", __func__);
+
+	if (temp_int != NULL) {
+		state = temp_int->internal->state[ci_nr - 1];
+		altera_hw_filt_release(dev, ci_nr);
+
+
+		if (((temp_int->internal->filts_used) <= 0) &&
+				((--(temp_int->internal->cis_used)) <= 0)) {
+
+			ci_dbg_print("%s: Actually removing\n", __func__);
+
+			remove_inode(temp_int->internal);
+			kfree(state->internal);
+		}
+
+		if (state != NULL) {
+			if (state->ca.data != NULL)
+				dvb_ca_en50221_release(&state->ca);
+
+			kfree(state);
+		}
+	}
+
+}
+EXPORT_SYMBOL(altera_ci_release);
+
+static void altera_pid_control(struct netup_hw_pid_filter *pid_filt,
+		u16 pid, int onoff)
+{
+	struct fpga_internal *inter = pid_filt->internal;
+	u8 store = 0;
+
+	/* pid 0-0x1f always enabled, don't touch them */
+	if ((pid == 0x2000) || (pid < 0x20))
+		return;
+
+	mutex_lock(&inter->fpga_mutex);
+
+	netup_fpga_op_rw(inter, NETUP_CI_PID_ADDR0, (pid >> 3) & 0xff, 0);
+	netup_fpga_op_rw(inter, NETUP_CI_PID_ADDR1,
+			((pid >> 11) & 0x03) | (pid_filt->nr << 2), 0);
+
+	store = netup_fpga_op_rw(inter, NETUP_CI_PID_DATA, 0, NETUP_CI_FLG_RD);
+
+	if (onoff)/* 0 - on, 1 - off */
+		store |= (1 << (pid & 7));
+	else
+		store &= ~(1 << (pid & 7));
+
+	netup_fpga_op_rw(inter, NETUP_CI_PID_DATA, store, 0);
+
+	mutex_unlock(&inter->fpga_mutex);
+
+	pid_dbg_print("%s: (%d) set pid: %5d 0x%04x '%s'\n", __func__,
+		pid_filt->nr, pid, pid, onoff ? "off" : "on");
+}
+
+static void altera_toggle_fullts_streaming(struct netup_hw_pid_filter *pid_filt,
+					int filt_nr, int onoff)
+{
+	struct fpga_internal *inter = pid_filt->internal;
+	u8 store = 0;
+	int i;
+
+	pid_dbg_print("%s: pid_filt->nr[%d]  now %s\n", __func__, pid_filt->nr,
+			onoff ? "off" : "on");
+
+	if (onoff)/* 0 - on, 1 - off */
+		store = 0xff;/* ignore pid */
+	else
+		store = 0;/* enable pid */
+
+	mutex_lock(&inter->fpga_mutex);
+
+	for (i = 0; i < 1024; i++) {
+		netup_fpga_op_rw(inter, NETUP_CI_PID_ADDR0, i & 0xff, 0);
+
+		netup_fpga_op_rw(inter, NETUP_CI_PID_ADDR1,
+				((i >> 8) & 0x03) | (pid_filt->nr << 2), 0);
+		/* pid 0-0x1f always enabled */
+		netup_fpga_op_rw(inter, NETUP_CI_PID_DATA,
+				(i > 3 ? store : 0), 0);
+	}
+
+	mutex_unlock(&inter->fpga_mutex);
+}
+
+int altera_pid_feed_control(void *demux_dev, int filt_nr,
+		struct dvb_demux_feed *feed, int onoff)
+{
+	struct fpga_inode *temp_int = find_dinode(demux_dev);
+	struct fpga_internal *inter = temp_int->internal;
+	struct netup_hw_pid_filter *pid_filt = inter->pid_filt[filt_nr - 1];
+
+	altera_pid_control(pid_filt, feed->pid, onoff ? 0 : 1);
+	/* call old feed proc's */
+	if (onoff)
+		pid_filt->start_feed(feed);
+	else
+		pid_filt->stop_feed(feed);
+
+	if (feed->pid == 0x2000)
+		altera_toggle_fullts_streaming(pid_filt, filt_nr,
+						onoff ? 0 : 1);
+
+	return 0;
+}
+EXPORT_SYMBOL(altera_pid_feed_control);
+
+int altera_ci_start_feed(struct dvb_demux_feed *feed, int num)
+{
+	altera_pid_feed_control(feed->demux, num, feed, 1);
+
+	return 0;
+}
+
+int altera_ci_stop_feed(struct dvb_demux_feed *feed, int num)
+{
+	altera_pid_feed_control(feed->demux, num, feed, 0);
+
+	return 0;
+}
+
+int altera_ci_start_feed_1(struct dvb_demux_feed *feed)
+{
+	return altera_ci_start_feed(feed, 1);
+}
+
+int altera_ci_stop_feed_1(struct dvb_demux_feed *feed)
+{
+	return altera_ci_stop_feed(feed, 1);
+}
+
+int altera_ci_start_feed_2(struct dvb_demux_feed *feed)
+{
+	return altera_ci_start_feed(feed, 2);
+}
+
+int altera_ci_stop_feed_2(struct dvb_demux_feed *feed)
+{
+	return altera_ci_stop_feed(feed, 2);
+}
+
+int altera_hw_filt_init(struct altera_ci_config *config, int hw_filt_nr)
+{
+	struct netup_hw_pid_filter *pid_filt = NULL;
+	struct fpga_inode *temp_int = find_inode(config->dev);
+	struct fpga_internal *inter = NULL;
+	int ret = 0;
+
+	pid_filt = kzalloc(sizeof(struct netup_hw_pid_filter), GFP_KERNEL);
+
+	ci_dbg_print("%s\n", __func__);
+
+	if (!pid_filt) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	if (temp_int != NULL) {
+		inter = temp_int->internal;
+		(inter->filts_used)++;
+		ci_dbg_print("%s: Find Internal Structure!\n", __func__);
+	} else {
+		inter = kzalloc(sizeof(struct fpga_internal), GFP_KERNEL);
+		if (!inter) {
+			ret = -ENOMEM;
+			goto err;
+		}
+
+		temp_int = append_internal(inter);
+		inter->filts_used = 1;
+		inter->dev = config->dev;
+		inter->fpga_rw = config->fpga_rw;
+		mutex_init(&inter->fpga_mutex);
+		inter->strt_wrk = 1;
+		ci_dbg_print("%s: Create New Internal Structure!\n", __func__);
+	}
+
+	ci_dbg_print("%s: setting hw pid filter = %p for ci = %d\n", __func__,
+						pid_filt, hw_filt_nr - 1);
+	inter->pid_filt[hw_filt_nr - 1] = pid_filt;
+	pid_filt->demux = config->demux;
+	pid_filt->internal = inter;
+	pid_filt->nr = hw_filt_nr - 1;
+	/* store old feed controls */
+	pid_filt->start_feed = config->demux->start_feed;
+	pid_filt->stop_feed = config->demux->stop_feed;
+	/* replace with new feed controls */
+	if (hw_filt_nr == 1) {
+		pid_filt->demux->start_feed = altera_ci_start_feed_1;
+		pid_filt->demux->stop_feed = altera_ci_stop_feed_1;
+	} else if (hw_filt_nr == 2) {
+		pid_filt->demux->start_feed = altera_ci_start_feed_2;
+		pid_filt->demux->stop_feed = altera_ci_stop_feed_2;
+	}
+
+	altera_toggle_fullts_streaming(pid_filt, 0, 1);
+
+	return 0;
+err:
+	ci_dbg_print("%s: Can't init hardware filter: Error %d\n",
+		     __func__, ret);
+
+	kfree(pid_filt);
+
+	return ret;
+}
+EXPORT_SYMBOL(altera_hw_filt_init);
+
+int altera_ci_init(struct altera_ci_config *config, int ci_nr)
+{
+	struct altera_ci_state *state;
+	struct fpga_inode *temp_int = find_inode(config->dev);
+	struct fpga_internal *inter = NULL;
+	int ret = 0;
+	u8 store = 0;
+
+	state = kzalloc(sizeof(struct altera_ci_state), GFP_KERNEL);
+
+	ci_dbg_print("%s\n", __func__);
+
+	if (!state) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	if (temp_int != NULL) {
+		inter = temp_int->internal;
+		(inter->cis_used)++;
+                inter->fpga_rw = config->fpga_rw;
+		ci_dbg_print("%s: Find Internal Structure!\n", __func__);
+	} else {
+		inter = kzalloc(sizeof(struct fpga_internal), GFP_KERNEL);
+		if (!inter) {
+			ret = -ENOMEM;
+			goto err;
+		}
+
+		temp_int = append_internal(inter);
+		inter->cis_used = 1;
+		inter->dev = config->dev;
+		inter->fpga_rw = config->fpga_rw;
+		mutex_init(&inter->fpga_mutex);
+		inter->strt_wrk = 1;
+		ci_dbg_print("%s: Create New Internal Structure!\n", __func__);
+	}
+
+	ci_dbg_print("%s: setting state = %p for ci = %d\n", __func__,
+						state, ci_nr - 1);
+	state->internal = inter;
+	state->nr = ci_nr - 1;
+
+	state->ca.owner = THIS_MODULE;
+	state->ca.read_attribute_mem = altera_ci_read_attribute_mem;
+	state->ca.write_attribute_mem = altera_ci_write_attribute_mem;
+	state->ca.read_cam_control = altera_ci_read_cam_ctl;
+	state->ca.write_cam_control = altera_ci_write_cam_ctl;
+	state->ca.slot_reset = altera_ci_slot_reset;
+	state->ca.slot_shutdown = altera_ci_slot_shutdown;
+	state->ca.slot_ts_enable = altera_ci_slot_ts_ctl;
+	state->ca.poll_slot_status = altera_poll_ci_slot_status;
+	state->ca.data = state;
+
+	ret = dvb_ca_en50221_init(config->adapter,
+				   &state->ca,
+				   /* flags */ 0,
+				   /* n_slots */ 1);
+	if (0 != ret)
+		goto err;
+
+       inter->state[ci_nr - 1] = state;
+
+	altera_hw_filt_init(config, ci_nr);
+
+	if (inter->strt_wrk) {
+		INIT_WORK(&inter->work, netup_read_ci_status);
+		inter->strt_wrk = 0;
+	}
+
+	ci_dbg_print("%s: CI initialized!\n", __func__);
+
+	mutex_lock(&inter->fpga_mutex);
+
+	/* Enable div */
+	netup_fpga_op_rw(inter, NETUP_CI_TSA_DIV, 0x0, 0);
+	netup_fpga_op_rw(inter, NETUP_CI_TSB_DIV, 0x0, 0);
+
+	/* enable TS out */
+	store = netup_fpga_op_rw(inter, NETUP_CI_BUSCTRL2, 0, NETUP_CI_FLG_RD);
+	store |= (3 << 4);
+	netup_fpga_op_rw(inter, NETUP_CI_BUSCTRL2, store, 0);
+
+	ret = netup_fpga_op_rw(inter, NETUP_CI_REVISION, 0, NETUP_CI_FLG_RD);
+	/* enable irq */
+	netup_fpga_op_rw(inter, NETUP_CI_INT_CTRL, 0x44, 0);
+
+	mutex_unlock(&inter->fpga_mutex);
+
+	ci_dbg_print("%s: NetUP CI Revision = 0x%x\n", __func__, ret);
+
+	schedule_work(&inter->work);
+
+	return 0;
+err:
+	ci_dbg_print("%s: Cannot initialize CI: Error %d.\n", __func__, ret);
+
+	kfree(state);
+
+	return ret;
+}
+EXPORT_SYMBOL(altera_ci_init);
+
+int altera_ci_tuner_reset(void *dev, int ci_nr)
+{
+	struct fpga_inode *temp_int = find_inode(dev);
+	struct fpga_internal *inter = NULL;
+	u8 store;
+
+	ci_dbg_print("%s\n", __func__);
+
+	if (temp_int == NULL)
+		return -1;
+
+	if (temp_int->internal == NULL)
+		return -1;
+
+	inter = temp_int->internal;
+
+	mutex_lock(&inter->fpga_mutex);
+
+	store = netup_fpga_op_rw(inter, NETUP_CI_BUSCTRL2, 0, NETUP_CI_FLG_RD);
+	store &= ~(4 << (2 - ci_nr));
+	netup_fpga_op_rw(inter, NETUP_CI_BUSCTRL2, store, 0);
+	msleep(100);
+	store |= (4 << (2 - ci_nr));
+	netup_fpga_op_rw(inter, NETUP_CI_BUSCTRL2, store, 0);
+
+	mutex_unlock(&inter->fpga_mutex);
+
+	return 0;
+}
+EXPORT_SYMBOL(altera_ci_tuner_reset);
diff --git a/drivers/media/pci/cx23885/altera-ci.h b/drivers/media/pci/cx23885/altera-ci.h
new file mode 100644
index 0000000..70e4fd6
--- /dev/null
+++ b/drivers/media/pci/cx23885/altera-ci.h
@@ -0,0 +1,100 @@
+/*
+ * altera-ci.c
+ *
+ *  CI driver in conjunction with NetUp Dual DVB-T/C RF CI card
+ *
+ * Copyright (C) 2010 NetUP Inc.
+ * Copyright (C) 2010 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 __ALTERA_CI_H
+#define __ALTERA_CI_H
+
+#define ALT_DATA	0x000000ff
+#define ALT_TDI		0x00008000
+#define ALT_TDO		0x00004000
+#define ALT_TCK		0x00002000
+#define ALT_RDY		0x00001000
+#define ALT_RD		0x00000800
+#define ALT_WR		0x00000400
+#define ALT_AD_RG	0x00000200
+#define ALT_CS		0x00000100
+
+struct altera_ci_config {
+	void *dev;/* main dev, for example cx23885_dev */
+	void *adapter;/* for CI to connect to */
+	struct dvb_demux *demux;/* for hardware PID filter to connect to */
+	int (*fpga_rw) (void *dev, int ad_rg, int val, int rw);
+};
+
+#if defined(CONFIG_MEDIA_ALTERA_CI) || (defined(CONFIG_MEDIA_ALTERA_CI_MODULE) \
+							&& defined(MODULE))
+
+extern int altera_ci_init(struct altera_ci_config *config, int ci_nr);
+extern void altera_ci_release(void *dev, int ci_nr);
+extern int altera_ci_irq(void *dev);
+extern int altera_ci_tuner_reset(void *dev, int ci_nr);
+
+#else
+
+static inline int altera_ci_init(struct altera_ci_config *config, int ci_nr)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return 0;
+}
+
+static inline void altera_ci_release(void *dev, int ci_nr)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+}
+
+static inline int altera_ci_irq(void *dev)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return 0;
+}
+
+static inline int altera_ci_tuner_reset(void *dev, int ci_nr)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return 0;
+}
+
+#endif
+#if 0
+static inline int altera_hw_filt_init(struct altera_ci_config *config,
+							int hw_filt_nr)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return 0;
+}
+
+static inline void altera_hw_filt_release(void *dev, int filt_nr)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+}
+
+static inline int altera_pid_feed_control(void *dev, int filt_nr,
+		struct dvb_demux_feed *dvbdmxfeed, int onoff)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return 0;
+}
+
+#endif /* CONFIG_MEDIA_ALTERA_CI */
+
+#endif /* __ALTERA_CI_H */
diff --git a/drivers/media/pci/cx23885/cimax2.c b/drivers/media/pci/cx23885/cimax2.c
new file mode 100644
index 0000000..c9f15d6
--- /dev/null
+++ b/drivers/media/pci/cx23885/cimax2.c
@@ -0,0 +1,536 @@
+/*
+ * 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
+
+#define NETUP_IRQ_DETAM 	0x1
+#define NETUP_IRQ_IRQAM		0x4
+
+static unsigned int ci_dbg;
+module_param(ci_dbg, int, 0644);
+MODULE_PARM_DESC(ci_dbg, "Enable CI debugging");
+
+static unsigned int ci_irq_enable;
+module_param(ci_irq_enable, int, 0644);
+MODULE_PARM_DESC(ci_irq_enable, "Enable IRQ from CAM");
+
+#define ci_dbg_print(args...) \
+	do { \
+		if (ci_dbg) \
+			printk(KERN_DEBUG args); \
+	} while (0)
+
+#define ci_irq_flags() (ci_irq_enable ? NETUP_IRQ_IRQAM : 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;
+	u8 current_irq_mode;
+	int current_ci_flag;
+	unsigned long next_status_checked_time;
+};
+
+
+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;
+
+	if (state->current_ci_flag != flag) {
+		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;
+	};
+	state->current_ci_flag = flag;
+
+	mutex_lock(&dev->gpio_lock);
+
+	/* 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(&dev->gpio_lock);
+
+	if (!read)
+		if (mem < 0)
+			return -EREMOTEIO;
+
+	ci_dbg_print("%s: %s: chipaddr=[0x%x] addr=[0x%02x], %s=%x\n", __func__,
+			(read) ? "read" : "write", state->ci_i2c_addr, 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_set_irq(struct dvb_ca_en50221 *en50221, u8 irq_mode)
+{
+	struct netup_ci_state *state = en50221->data;
+	int ret;
+
+	if (irq_mode == state->current_irq_mode)
+		return 0;
+
+	ci_dbg_print("%s: chipaddr=[0x%x] setting ci IRQ to [0x%x] \n",
+			__func__, state->ci_i2c_addr, irq_mode);
+	ret = netup_write_i2c(state->i2c_adap, state->ci_i2c_addr,
+							0x1b, &irq_mode, 1);
+
+	if (ret != 0)
+		return ret;
+
+	state->current_irq_mode = irq_mode;
+
+	return 0;
+}
+
+int netup_ci_slot_ts_ctl(struct dvb_ca_en50221 *en50221, int slot)
+{
+	struct netup_ci_state *state = en50221->data;
+	u8 buf;
+
+	if (0 != slot)
+		return -EINVAL;
+
+	netup_read_i2c(state->i2c_adap, state->ci_i2c_addr,
+			0, &buf, 1);
+	buf |= 0x60;
+
+	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;
+
+	/* CAM module IRQ processing. fast operation */
+	dvb_ca_en50221_frda_irq(&state->ca, 0);
+
+	/* CAM module INSERT/REMOVE processing. slow operation because of i2c
+	 * transfers */
+	if (time_after(jiffies, state->next_status_checked_time)
+			|| !state->status) {
+		ret = netup_read_i2c(state->i2c_adap, state->ci_i2c_addr,
+				0, &buf[0], 33);
+
+		state->next_status_checked_time = jiffies
+			+ msecs_to_jiffies(1000);
+
+		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[0]);
+
+
+		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;
+
+	ci_dbg_print("%s:\n", __func__);
+
+	if (0 == (pci_status & (PCI_MSK_GPIO0 | PCI_MSK_GPIO1)))
+		return 0;
+
+	if (pci_status & PCI_MSK_GPIO0) {
+		port = &dev->ts1;
+		state = port->port_priv;
+		schedule_work(&state->work);
+		ci_dbg_print("%s: Wakeup CI0\n", __func__);
+	}
+
+	if (pci_status & PCI_MSK_GPIO1) {
+		port = &dev->ts2;
+		state = port->port_priv;
+		schedule_work(&state->work);
+		ci_dbg_print("%s: Wakeup CI1\n", __func__);
+	}
+
+	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;
+
+	netup_ci_set_irq(en50221, open ? (NETUP_IRQ_DETAM | ci_irq_flags())
+			: NETUP_IRQ_DETAM);
+
+	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 */
+		ci_irq_flags() | NETUP_IRQ_DETAM, /* DETAM, IRQAM unmasked */
+		0x05, /* EXTINT=active-high, INT=push-pull */
+		0x00, /* USCG1 */
+		0x04, /* ack active low */
+		0x00, /* LOCK = 0 */
+		0x33, /* serial mode, rising in, rising out, MSB first*/
+		0x31, /* synchronization */
+	};
+	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;
+		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;
+	state->current_irq_mode = ci_irq_flags() | NETUP_IRQ_DETAM;
+
+	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);
+	schedule_work(&state->work);
+
+	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/pci/cx23885/cimax2.h b/drivers/media/pci/cx23885/cimax2.h
new file mode 100644
index 0000000..518744a
--- /dev/null
+++ b/drivers/media/pci/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/pci/cx23885/cx23885-417.c b/drivers/media/pci/cx23885/cx23885-417.c
new file mode 100644
index 0000000..5d5052d
--- /dev/null
+++ b/drivers/media/pci/cx23885/cx23885-417.c
@@ -0,0 +1,1790 @@
+/*
+ *
+ *  Support for a cx23417 mpeg encoder via cx23885 host port.
+ *
+ *    (c) 2004 Jelle Foks <jelle@foks.us>
+ *    (c) 2004 Gerd Knorr <kraxel@bytesex.org>
+ *    (c) 2008 Steven Toth <stoth@linuxtv.org>
+ *      - CX23885/7/8 support
+ *
+ *  Includes parts from the ivtv driver <http://sourceforge.net/projects/ivtv/>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the 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/moduleparam.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/firmware.h>
+#include <linux/slab.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include <media/cx2341x.h>
+
+#include "cx23885.h"
+#include "cx23885-ioctl.h"
+
+#define CX23885_FIRM_IMAGE_SIZE 376836
+#define CX23885_FIRM_IMAGE_NAME "v4l-cx23885-enc.fw"
+
+static unsigned int mpegbufs = 32;
+module_param(mpegbufs, int, 0644);
+MODULE_PARM_DESC(mpegbufs, "number of mpeg buffers, range 2-32");
+static unsigned int mpeglines = 32;
+module_param(mpeglines, int, 0644);
+MODULE_PARM_DESC(mpeglines, "number of lines in an MPEG buffer, range 2-32");
+static unsigned int mpeglinesize = 512;
+module_param(mpeglinesize, int, 0644);
+MODULE_PARM_DESC(mpeglinesize,
+	"number of bytes in each line of an MPEG buffer, range 512-1024");
+
+static unsigned int v4l_debug;
+module_param(v4l_debug, int, 0644);
+MODULE_PARM_DESC(v4l_debug, "enable V4L debug messages");
+
+#define dprintk(level, fmt, arg...)\
+	do { if (v4l_debug >= level) \
+		printk(KERN_DEBUG "%s: " fmt, \
+		(dev) ? dev->name : "cx23885[?]", ## arg); \
+	} while (0)
+
+static struct cx23885_tvnorm cx23885_tvnorms[] = {
+	{
+		.name      = "NTSC-M",
+		.id        = V4L2_STD_NTSC_M,
+	}, {
+		.name      = "NTSC-JP",
+		.id        = V4L2_STD_NTSC_M_JP,
+	}, {
+		.name      = "PAL-BG",
+		.id        = V4L2_STD_PAL_BG,
+	}, {
+		.name      = "PAL-DK",
+		.id        = V4L2_STD_PAL_DK,
+	}, {
+		.name      = "PAL-I",
+		.id        = V4L2_STD_PAL_I,
+	}, {
+		.name      = "PAL-M",
+		.id        = V4L2_STD_PAL_M,
+	}, {
+		.name      = "PAL-N",
+		.id        = V4L2_STD_PAL_N,
+	}, {
+		.name      = "PAL-Nc",
+		.id        = V4L2_STD_PAL_Nc,
+	}, {
+		.name      = "PAL-60",
+		.id        = V4L2_STD_PAL_60,
+	}, {
+		.name      = "SECAM-L",
+		.id        = V4L2_STD_SECAM_L,
+	}, {
+		.name      = "SECAM-DK",
+		.id        = V4L2_STD_SECAM_DK,
+	}
+};
+
+/* ------------------------------------------------------------------ */
+enum cx23885_capture_type {
+	CX23885_MPEG_CAPTURE,
+	CX23885_RAW_CAPTURE,
+	CX23885_RAW_PASSTHRU_CAPTURE
+};
+enum cx23885_capture_bits {
+	CX23885_RAW_BITS_NONE             = 0x00,
+	CX23885_RAW_BITS_YUV_CAPTURE      = 0x01,
+	CX23885_RAW_BITS_PCM_CAPTURE      = 0x02,
+	CX23885_RAW_BITS_VBI_CAPTURE      = 0x04,
+	CX23885_RAW_BITS_PASSTHRU_CAPTURE = 0x08,
+	CX23885_RAW_BITS_TO_HOST_CAPTURE  = 0x10
+};
+enum cx23885_capture_end {
+	CX23885_END_AT_GOP, /* stop at the end of gop, generate irq */
+	CX23885_END_NOW, /* stop immediately, no irq */
+};
+enum cx23885_framerate {
+	CX23885_FRAMERATE_NTSC_30, /* NTSC: 30fps */
+	CX23885_FRAMERATE_PAL_25   /* PAL: 25fps */
+};
+enum cx23885_stream_port {
+	CX23885_OUTPUT_PORT_MEMORY,
+	CX23885_OUTPUT_PORT_STREAMING,
+	CX23885_OUTPUT_PORT_SERIAL
+};
+enum cx23885_data_xfer_status {
+	CX23885_MORE_BUFFERS_FOLLOW,
+	CX23885_LAST_BUFFER,
+};
+enum cx23885_picture_mask {
+	CX23885_PICTURE_MASK_NONE,
+	CX23885_PICTURE_MASK_I_FRAMES,
+	CX23885_PICTURE_MASK_I_P_FRAMES = 0x3,
+	CX23885_PICTURE_MASK_ALL_FRAMES = 0x7,
+};
+enum cx23885_vbi_mode_bits {
+	CX23885_VBI_BITS_SLICED,
+	CX23885_VBI_BITS_RAW,
+};
+enum cx23885_vbi_insertion_bits {
+	CX23885_VBI_BITS_INSERT_IN_XTENSION_USR_DATA,
+	CX23885_VBI_BITS_INSERT_IN_PRIVATE_PACKETS = 0x1 << 1,
+	CX23885_VBI_BITS_SEPARATE_STREAM = 0x2 << 1,
+	CX23885_VBI_BITS_SEPARATE_STREAM_USR_DATA = 0x4 << 1,
+	CX23885_VBI_BITS_SEPARATE_STREAM_PRV_DATA = 0x5 << 1,
+};
+enum cx23885_dma_unit {
+	CX23885_DMA_BYTES,
+	CX23885_DMA_FRAMES,
+};
+enum cx23885_dma_transfer_status_bits {
+	CX23885_DMA_TRANSFER_BITS_DONE = 0x01,
+	CX23885_DMA_TRANSFER_BITS_ERROR = 0x04,
+	CX23885_DMA_TRANSFER_BITS_LL_ERROR = 0x10,
+};
+enum cx23885_pause {
+	CX23885_PAUSE_ENCODING,
+	CX23885_RESUME_ENCODING,
+};
+enum cx23885_copyright {
+	CX23885_COPYRIGHT_OFF,
+	CX23885_COPYRIGHT_ON,
+};
+enum cx23885_notification_type {
+	CX23885_NOTIFICATION_REFRESH,
+};
+enum cx23885_notification_status {
+	CX23885_NOTIFICATION_OFF,
+	CX23885_NOTIFICATION_ON,
+};
+enum cx23885_notification_mailbox {
+	CX23885_NOTIFICATION_NO_MAILBOX = -1,
+};
+enum cx23885_field1_lines {
+	CX23885_FIELD1_SAA7114 = 0x00EF, /* 239 */
+	CX23885_FIELD1_SAA7115 = 0x00F0, /* 240 */
+	CX23885_FIELD1_MICRONAS = 0x0105, /* 261 */
+};
+enum cx23885_field2_lines {
+	CX23885_FIELD2_SAA7114 = 0x00EF, /* 239 */
+	CX23885_FIELD2_SAA7115 = 0x00F0, /* 240 */
+	CX23885_FIELD2_MICRONAS = 0x0106, /* 262 */
+};
+enum cx23885_custom_data_type {
+	CX23885_CUSTOM_EXTENSION_USR_DATA,
+	CX23885_CUSTOM_PRIVATE_PACKET,
+};
+enum cx23885_mute {
+	CX23885_UNMUTE,
+	CX23885_MUTE,
+};
+enum cx23885_mute_video_mask {
+	CX23885_MUTE_VIDEO_V_MASK = 0x0000FF00,
+	CX23885_MUTE_VIDEO_U_MASK = 0x00FF0000,
+	CX23885_MUTE_VIDEO_Y_MASK = 0xFF000000,
+};
+enum cx23885_mute_video_shift {
+	CX23885_MUTE_VIDEO_V_SHIFT = 8,
+	CX23885_MUTE_VIDEO_U_SHIFT = 16,
+	CX23885_MUTE_VIDEO_Y_SHIFT = 24,
+};
+
+/* defines below are from ivtv-driver.h */
+#define IVTV_CMD_HW_BLOCKS_RST 0xFFFFFFFF
+
+/* Firmware API commands */
+#define IVTV_API_STD_TIMEOUT 500
+
+/* Registers */
+/* IVTV_REG_OFFSET */
+#define IVTV_REG_ENC_SDRAM_REFRESH (0x07F8)
+#define IVTV_REG_ENC_SDRAM_PRECHARGE (0x07FC)
+#define IVTV_REG_SPU (0x9050)
+#define IVTV_REG_HW_BLOCKS (0x9054)
+#define IVTV_REG_VPU (0x9058)
+#define IVTV_REG_APU (0xA064)
+
+/**** 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
++-------+-------+-------+-------+-------+-------+-------+-------+
+| MIWR# | MIRD# | MICS# |MIRDY# |MIADDR3|MIADDR2|MIADDR1|MIADDR0|
++-------+-------+-------+-------+-------+-------+-------+-------+
+ bit 7   bit 6   bit 5   bit 4   bit 3   bit 2   bit 1   bit 0
++-------+-------+-------+-------+-------+-------+-------+-------+
+|MIDATA7|MIDATA6|MIDATA5|MIDATA4|MIDATA3|MIDATA2|MIDATA1|MIDATA0|
++-------+-------+-------+-------+-------+-------+-------+-------+
+***/
+#define MC417_MIWR	0x8000
+#define MC417_MIRD	0x4000
+#define MC417_MICS	0x2000
+#define MC417_MIRDY	0x1000
+#define MC417_MIADDR	0x0F00
+#define MC417_MIDATA	0x00FF
+
+/* MIADDR* nibble definitions */
+#define  MCI_MEMORY_DATA_BYTE0          0x000
+#define  MCI_MEMORY_DATA_BYTE1          0x100
+#define  MCI_MEMORY_DATA_BYTE2          0x200
+#define  MCI_MEMORY_DATA_BYTE3          0x300
+#define  MCI_MEMORY_ADDRESS_BYTE2       0x400
+#define  MCI_MEMORY_ADDRESS_BYTE1       0x500
+#define  MCI_MEMORY_ADDRESS_BYTE0       0x600
+#define  MCI_REGISTER_DATA_BYTE0        0x800
+#define  MCI_REGISTER_DATA_BYTE1        0x900
+#define  MCI_REGISTER_DATA_BYTE2        0xA00
+#define  MCI_REGISTER_DATA_BYTE3        0xB00
+#define  MCI_REGISTER_ADDRESS_BYTE0     0xC00
+#define  MCI_REGISTER_ADDRESS_BYTE1     0xD00
+#define  MCI_REGISTER_MODE              0xE00
+
+/* Read and write modes */
+#define  MCI_MODE_REGISTER_READ         0
+#define  MCI_MODE_REGISTER_WRITE        1
+#define  MCI_MODE_MEMORY_READ           0
+#define  MCI_MODE_MEMORY_WRITE          0x40
+
+/*** Bit definitions for MC417_CTL register ****
+ bits 31-6   bits 5-4   bit 3    bits 2-1       Bit 0
++--------+-------------+--------+--------------+------------+
+|Reserved|MC417_SPD_CTL|Reserved|MC417_GPIO_SEL|UART_GPIO_EN|
++--------+-------------+--------+--------------+------------+
+***/
+#define MC417_SPD_CTL(x)	(((x) << 4) & 0x00000030)
+#define MC417_GPIO_SEL(x)	(((x) << 1) & 0x00000006)
+#define MC417_UART_GPIO_EN	0x00000001
+
+/* Values for speed control */
+#define MC417_SPD_CTL_SLOW	0x1
+#define MC417_SPD_CTL_MEDIUM	0x0
+#define MC417_SPD_CTL_FAST	0x3     /* b'1x, but we use b'11 */
+
+/* Values for GPIO select */
+#define MC417_GPIO_SEL_GPIO3	0x3
+#define MC417_GPIO_SEL_GPIO2	0x2
+#define MC417_GPIO_SEL_GPIO1	0x1
+#define MC417_GPIO_SEL_GPIO0	0x0
+
+void cx23885_mc417_init(struct cx23885_dev *dev)
+{
+	u32 regval;
+
+	dprintk(2, "%s()\n", __func__);
+
+	/* Configure MC417_CTL register to defaults. */
+	regval = MC417_SPD_CTL(MC417_SPD_CTL_FAST)	|
+		 MC417_GPIO_SEL(MC417_GPIO_SEL_GPIO3)	|
+		 MC417_UART_GPIO_EN;
+	cx_write(MC417_CTL, regval);
+
+	/* Configure MC417_OEN to defaults. */
+	regval = MC417_MIRDY;
+	cx_write(MC417_OEN, regval);
+
+	/* Configure MC417_RWD to defaults. */
+	regval = MC417_MIWR | MC417_MIRD | MC417_MICS;
+	cx_write(MC417_RWD, regval);
+}
+
+static int mc417_wait_ready(struct cx23885_dev *dev)
+{
+	u32 mi_ready;
+	unsigned long timeout = jiffies + msecs_to_jiffies(1);
+
+	for (;;) {
+		mi_ready = cx_read(MC417_RWD) & MC417_MIRDY;
+		if (mi_ready != 0)
+			return 0;
+		if (time_after(jiffies, timeout))
+			return -1;
+		udelay(1);
+	}
+}
+
+int mc417_register_write(struct cx23885_dev *dev, u16 address, u32 value)
+{
+	u32 regval;
+
+	/* Enable MC417 GPIO outputs except for MC417_MIRDY,
+	 * which is an input.
+	 */
+	cx_write(MC417_OEN, MC417_MIRDY);
+
+	/* Write data byte 0 */
+	regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE0 |
+		(value & 0x000000FF);
+	cx_write(MC417_RWD, regval);
+
+	/* Transition CS/WR to effect write transaction across bus. */
+	regval |= MC417_MICS | MC417_MIWR;
+	cx_write(MC417_RWD, regval);
+
+	/* Write data byte 1 */
+	regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE1 |
+		((value >> 8) & 0x000000FF);
+	cx_write(MC417_RWD, regval);
+	regval |= MC417_MICS | MC417_MIWR;
+	cx_write(MC417_RWD, regval);
+
+	/* Write data byte 2 */
+	regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE2 |
+		((value >> 16) & 0x000000FF);
+	cx_write(MC417_RWD, regval);
+	regval |= MC417_MICS | MC417_MIWR;
+	cx_write(MC417_RWD, regval);
+
+	/* Write data byte 3 */
+	regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE3 |
+		((value >> 24) & 0x000000FF);
+	cx_write(MC417_RWD, regval);
+	regval |= MC417_MICS | MC417_MIWR;
+	cx_write(MC417_RWD, regval);
+
+	/* Write address byte 0 */
+	regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_ADDRESS_BYTE0 |
+		(address & 0xFF);
+	cx_write(MC417_RWD, regval);
+	regval |= MC417_MICS | MC417_MIWR;
+	cx_write(MC417_RWD, regval);
+
+	/* Write address byte 1 */
+	regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_ADDRESS_BYTE1 |
+		((address >> 8) & 0xFF);
+	cx_write(MC417_RWD, regval);
+	regval |= MC417_MICS | MC417_MIWR;
+	cx_write(MC417_RWD, regval);
+
+	/* Indicate that this is a write. */
+	regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_MODE |
+		MCI_MODE_REGISTER_WRITE;
+	cx_write(MC417_RWD, regval);
+	regval |= MC417_MICS | MC417_MIWR;
+	cx_write(MC417_RWD, regval);
+
+	/* Wait for the trans to complete (MC417_MIRDY asserted). */
+	return mc417_wait_ready(dev);
+}
+
+int mc417_register_read(struct cx23885_dev *dev, u16 address, u32 *value)
+{
+	int retval;
+	u32 regval;
+	u32 tempval;
+	u32 dataval;
+
+	/* Enable MC417 GPIO outputs except for MC417_MIRDY,
+	 * which is an input.
+	 */
+	cx_write(MC417_OEN, MC417_MIRDY);
+
+	/* Write address byte 0 */
+	regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_ADDRESS_BYTE0 |
+		((address & 0x00FF));
+	cx_write(MC417_RWD, regval);
+	regval |= MC417_MICS | MC417_MIWR;
+	cx_write(MC417_RWD, regval);
+
+	/* Write address byte 1 */
+	regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_ADDRESS_BYTE1 |
+		((address >> 8) & 0xFF);
+	cx_write(MC417_RWD, regval);
+	regval |= MC417_MICS | MC417_MIWR;
+	cx_write(MC417_RWD, regval);
+
+	/* Indicate that this is a register read. */
+	regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_MODE |
+		MCI_MODE_REGISTER_READ;
+	cx_write(MC417_RWD, regval);
+	regval |= MC417_MICS | MC417_MIWR;
+	cx_write(MC417_RWD, regval);
+
+	/* Wait for the trans to complete (MC417_MIRDY asserted). */
+	retval = mc417_wait_ready(dev);
+
+	/* switch the DAT0-7 GPIO[10:3] to input mode */
+	cx_write(MC417_OEN, MC417_MIRDY | MC417_MIDATA);
+
+	/* Read data byte 0 */
+	regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE0;
+	cx_write(MC417_RWD, regval);
+
+	/* Transition RD to effect read transaction across bus.
+	 * Transtion 0x5000 -> 0x9000 correct (RD/RDY -> WR/RDY)?
+	 * Should it be 0x9000 -> 0xF000 (also why is RDY being set, its
+	 * input only...)
+	 */
+	regval = MC417_MIWR | MC417_MIRDY | MCI_REGISTER_DATA_BYTE0;
+	cx_write(MC417_RWD, regval);
+
+	/* Collect byte */
+	tempval = cx_read(MC417_RWD);
+	dataval = tempval & 0x000000FF;
+
+	/* Bring CS and RD high. */
+	regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY;
+	cx_write(MC417_RWD, regval);
+
+	/* Read data byte 1 */
+	regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE1;
+	cx_write(MC417_RWD, regval);
+	regval = MC417_MIWR | MC417_MIRDY | MCI_REGISTER_DATA_BYTE1;
+	cx_write(MC417_RWD, regval);
+	tempval = cx_read(MC417_RWD);
+	dataval |= ((tempval & 0x000000FF) << 8);
+	regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY;
+	cx_write(MC417_RWD, regval);
+
+	/* Read data byte 2 */
+	regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE2;
+	cx_write(MC417_RWD, regval);
+	regval = MC417_MIWR | MC417_MIRDY | MCI_REGISTER_DATA_BYTE2;
+	cx_write(MC417_RWD, regval);
+	tempval = cx_read(MC417_RWD);
+	dataval |= ((tempval & 0x000000FF) << 16);
+	regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY;
+	cx_write(MC417_RWD, regval);
+
+	/* Read data byte 3 */
+	regval = MC417_MIRD | MC417_MIRDY | MCI_REGISTER_DATA_BYTE3;
+	cx_write(MC417_RWD, regval);
+	regval = MC417_MIWR | MC417_MIRDY | MCI_REGISTER_DATA_BYTE3;
+	cx_write(MC417_RWD, regval);
+	tempval = cx_read(MC417_RWD);
+	dataval |= ((tempval & 0x000000FF) << 24);
+	regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY;
+	cx_write(MC417_RWD, regval);
+
+	*value  = dataval;
+
+	return retval;
+}
+
+int mc417_memory_write(struct cx23885_dev *dev, u32 address, u32 value)
+{
+	u32 regval;
+
+	/* Enable MC417 GPIO outputs except for MC417_MIRDY,
+	 * which is an input.
+	 */
+	cx_write(MC417_OEN, MC417_MIRDY);
+
+	/* Write data byte 0 */
+	regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE0 |
+		(value & 0x000000FF);
+	cx_write(MC417_RWD, regval);
+
+	/* Transition CS/WR to effect write transaction across bus. */
+	regval |= MC417_MICS | MC417_MIWR;
+	cx_write(MC417_RWD, regval);
+
+	/* Write data byte 1 */
+	regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE1 |
+		((value >> 8) & 0x000000FF);
+	cx_write(MC417_RWD, regval);
+	regval |= MC417_MICS | MC417_MIWR;
+	cx_write(MC417_RWD, regval);
+
+	/* Write data byte 2 */
+	regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE2 |
+		((value >> 16) & 0x000000FF);
+	cx_write(MC417_RWD, regval);
+	regval |= MC417_MICS | MC417_MIWR;
+	cx_write(MC417_RWD, regval);
+
+	/* Write data byte 3 */
+	regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE3 |
+		((value >> 24) & 0x000000FF);
+	cx_write(MC417_RWD, regval);
+	regval |= MC417_MICS | MC417_MIWR;
+	cx_write(MC417_RWD, regval);
+
+	/* Write address byte 2 */
+	regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_ADDRESS_BYTE2 |
+		MCI_MODE_MEMORY_WRITE | ((address >> 16) & 0x3F);
+	cx_write(MC417_RWD, regval);
+	regval |= MC417_MICS | MC417_MIWR;
+	cx_write(MC417_RWD, regval);
+
+	/* Write address byte 1 */
+	regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_ADDRESS_BYTE1 |
+		((address >> 8) & 0xFF);
+	cx_write(MC417_RWD, regval);
+	regval |= MC417_MICS | MC417_MIWR;
+	cx_write(MC417_RWD, regval);
+
+	/* Write address byte 0 */
+	regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_ADDRESS_BYTE0 |
+		(address & 0xFF);
+	cx_write(MC417_RWD, regval);
+	regval |= MC417_MICS | MC417_MIWR;
+	cx_write(MC417_RWD, regval);
+
+	/* Wait for the trans to complete (MC417_MIRDY asserted). */
+	return mc417_wait_ready(dev);
+}
+
+int mc417_memory_read(struct cx23885_dev *dev, u32 address, u32 *value)
+{
+	int retval;
+	u32 regval;
+	u32 tempval;
+	u32 dataval;
+
+	/* Enable MC417 GPIO outputs except for MC417_MIRDY,
+	 * which is an input.
+	 */
+	cx_write(MC417_OEN, MC417_MIRDY);
+
+	/* Write address byte 2 */
+	regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_ADDRESS_BYTE2 |
+		MCI_MODE_MEMORY_READ | ((address >> 16) & 0x3F);
+	cx_write(MC417_RWD, regval);
+	regval |= MC417_MICS | MC417_MIWR;
+	cx_write(MC417_RWD, regval);
+
+	/* Write address byte 1 */
+	regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_ADDRESS_BYTE1 |
+		((address >> 8) & 0xFF);
+	cx_write(MC417_RWD, regval);
+	regval |= MC417_MICS | MC417_MIWR;
+	cx_write(MC417_RWD, regval);
+
+	/* Write address byte 0 */
+	regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_ADDRESS_BYTE0 |
+		(address & 0xFF);
+	cx_write(MC417_RWD, regval);
+	regval |= MC417_MICS | MC417_MIWR;
+	cx_write(MC417_RWD, regval);
+
+	/* Wait for the trans to complete (MC417_MIRDY asserted). */
+	retval = mc417_wait_ready(dev);
+
+	/* switch the DAT0-7 GPIO[10:3] to input mode */
+	cx_write(MC417_OEN, MC417_MIRDY | MC417_MIDATA);
+
+	/* Read data byte 3 */
+	regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE3;
+	cx_write(MC417_RWD, regval);
+
+	/* Transition RD to effect read transaction across bus. */
+	regval = MC417_MIWR | MC417_MIRDY | MCI_MEMORY_DATA_BYTE3;
+	cx_write(MC417_RWD, regval);
+
+	/* Collect byte */
+	tempval = cx_read(MC417_RWD);
+	dataval = ((tempval & 0x000000FF) << 24);
+
+	/* Bring CS and RD high. */
+	regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY;
+	cx_write(MC417_RWD, regval);
+
+	/* Read data byte 2 */
+	regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE2;
+	cx_write(MC417_RWD, regval);
+	regval = MC417_MIWR | MC417_MIRDY | MCI_MEMORY_DATA_BYTE2;
+	cx_write(MC417_RWD, regval);
+	tempval = cx_read(MC417_RWD);
+	dataval |= ((tempval & 0x000000FF) << 16);
+	regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY;
+	cx_write(MC417_RWD, regval);
+
+	/* Read data byte 1 */
+	regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE1;
+	cx_write(MC417_RWD, regval);
+	regval = MC417_MIWR | MC417_MIRDY | MCI_MEMORY_DATA_BYTE1;
+	cx_write(MC417_RWD, regval);
+	tempval = cx_read(MC417_RWD);
+	dataval |= ((tempval & 0x000000FF) << 8);
+	regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY;
+	cx_write(MC417_RWD, regval);
+
+	/* Read data byte 0 */
+	regval = MC417_MIRD | MC417_MIRDY | MCI_MEMORY_DATA_BYTE0;
+	cx_write(MC417_RWD, regval);
+	regval = MC417_MIWR | MC417_MIRDY | MCI_MEMORY_DATA_BYTE0;
+	cx_write(MC417_RWD, regval);
+	tempval = cx_read(MC417_RWD);
+	dataval |= (tempval & 0x000000FF);
+	regval = MC417_MIWR | MC417_MIRD | MC417_MICS | MC417_MIRDY;
+	cx_write(MC417_RWD, regval);
+
+	*value  = dataval;
+
+	return retval;
+}
+
+void mc417_gpio_set(struct cx23885_dev *dev, u32 mask)
+{
+	u32 val;
+
+	/* Set the gpio value */
+	mc417_register_read(dev, 0x900C, &val);
+	val |= (mask & 0x000ffff);
+	mc417_register_write(dev, 0x900C, val);
+}
+
+void mc417_gpio_clear(struct cx23885_dev *dev, u32 mask)
+{
+	u32 val;
+
+	/* Clear the gpio value */
+	mc417_register_read(dev, 0x900C, &val);
+	val &= ~(mask & 0x0000ffff);
+	mc417_register_write(dev, 0x900C, val);
+}
+
+void mc417_gpio_enable(struct cx23885_dev *dev, u32 mask, int asoutput)
+{
+	u32 val;
+
+	/* Enable GPIO direction bits */
+	mc417_register_read(dev, 0x9020, &val);
+	if (asoutput)
+		val |= (mask & 0x0000ffff);
+	else
+		val &= ~(mask & 0x0000ffff);
+
+	mc417_register_write(dev, 0x9020, val);
+}
+/* ------------------------------------------------------------------ */
+
+/* MPEG encoder API */
+static char *cmd_to_str(int cmd)
+{
+	switch (cmd) {
+	case CX2341X_ENC_PING_FW:
+		return  "PING_FW";
+	case CX2341X_ENC_START_CAPTURE:
+		return  "START_CAPTURE";
+	case CX2341X_ENC_STOP_CAPTURE:
+		return  "STOP_CAPTURE";
+	case CX2341X_ENC_SET_AUDIO_ID:
+		return  "SET_AUDIO_ID";
+	case CX2341X_ENC_SET_VIDEO_ID:
+		return  "SET_VIDEO_ID";
+	case CX2341X_ENC_SET_PCR_ID:
+		return  "SET_PCR_ID";
+	case CX2341X_ENC_SET_FRAME_RATE:
+		return  "SET_FRAME_RATE";
+	case CX2341X_ENC_SET_FRAME_SIZE:
+		return  "SET_FRAME_SIZE";
+	case CX2341X_ENC_SET_BIT_RATE:
+		return  "SET_BIT_RATE";
+	case CX2341X_ENC_SET_GOP_PROPERTIES:
+		return  "SET_GOP_PROPERTIES";
+	case CX2341X_ENC_SET_ASPECT_RATIO:
+		return  "SET_ASPECT_RATIO";
+	case CX2341X_ENC_SET_DNR_FILTER_MODE:
+		return  "SET_DNR_FILTER_MODE";
+	case CX2341X_ENC_SET_DNR_FILTER_PROPS:
+		return  "SET_DNR_FILTER_PROPS";
+	case CX2341X_ENC_SET_CORING_LEVELS:
+		return  "SET_CORING_LEVELS";
+	case CX2341X_ENC_SET_SPATIAL_FILTER_TYPE:
+		return  "SET_SPATIAL_FILTER_TYPE";
+	case CX2341X_ENC_SET_VBI_LINE:
+		return  "SET_VBI_LINE";
+	case CX2341X_ENC_SET_STREAM_TYPE:
+		return  "SET_STREAM_TYPE";
+	case CX2341X_ENC_SET_OUTPUT_PORT:
+		return  "SET_OUTPUT_PORT";
+	case CX2341X_ENC_SET_AUDIO_PROPERTIES:
+		return  "SET_AUDIO_PROPERTIES";
+	case CX2341X_ENC_HALT_FW:
+		return  "HALT_FW";
+	case CX2341X_ENC_GET_VERSION:
+		return  "GET_VERSION";
+	case CX2341X_ENC_SET_GOP_CLOSURE:
+		return  "SET_GOP_CLOSURE";
+	case CX2341X_ENC_GET_SEQ_END:
+		return  "GET_SEQ_END";
+	case CX2341X_ENC_SET_PGM_INDEX_INFO:
+		return  "SET_PGM_INDEX_INFO";
+	case CX2341X_ENC_SET_VBI_CONFIG:
+		return  "SET_VBI_CONFIG";
+	case CX2341X_ENC_SET_DMA_BLOCK_SIZE:
+		return  "SET_DMA_BLOCK_SIZE";
+	case CX2341X_ENC_GET_PREV_DMA_INFO_MB_10:
+		return  "GET_PREV_DMA_INFO_MB_10";
+	case CX2341X_ENC_GET_PREV_DMA_INFO_MB_9:
+		return  "GET_PREV_DMA_INFO_MB_9";
+	case CX2341X_ENC_SCHED_DMA_TO_HOST:
+		return  "SCHED_DMA_TO_HOST";
+	case CX2341X_ENC_INITIALIZE_INPUT:
+		return  "INITIALIZE_INPUT";
+	case CX2341X_ENC_SET_FRAME_DROP_RATE:
+		return  "SET_FRAME_DROP_RATE";
+	case CX2341X_ENC_PAUSE_ENCODER:
+		return  "PAUSE_ENCODER";
+	case CX2341X_ENC_REFRESH_INPUT:
+		return  "REFRESH_INPUT";
+	case CX2341X_ENC_SET_COPYRIGHT:
+		return  "SET_COPYRIGHT";
+	case CX2341X_ENC_SET_EVENT_NOTIFICATION:
+		return  "SET_EVENT_NOTIFICATION";
+	case CX2341X_ENC_SET_NUM_VSYNC_LINES:
+		return  "SET_NUM_VSYNC_LINES";
+	case CX2341X_ENC_SET_PLACEHOLDER:
+		return  "SET_PLACEHOLDER";
+	case CX2341X_ENC_MUTE_VIDEO:
+		return  "MUTE_VIDEO";
+	case CX2341X_ENC_MUTE_AUDIO:
+		return  "MUTE_AUDIO";
+	case CX2341X_ENC_MISC:
+		return  "MISC";
+	default:
+		return "UNKNOWN";
+	}
+}
+
+static int cx23885_mbox_func(void *priv,
+			     u32 command,
+			     int in,
+			     int out,
+			     u32 data[CX2341X_MBOX_MAX_DATA])
+{
+	struct cx23885_dev *dev = priv;
+	unsigned long timeout;
+	u32 value, flag, retval = 0;
+	int i;
+
+	dprintk(3, "%s: command(0x%X) = %s\n", __func__, command,
+		cmd_to_str(command));
+
+	/* this may not be 100% safe if we can't read any memory location
+	   without side effects */
+	mc417_memory_read(dev, dev->cx23417_mailbox - 4, &value);
+	if (value != 0x12345678) {
+		printk(KERN_ERR
+			"Firmware and/or mailbox pointer not initialized "
+			"or corrupted, signature = 0x%x, cmd = %s\n", value,
+			cmd_to_str(command));
+		return -1;
+	}
+
+	/* This read looks at 32 bits, but flag is only 8 bits.
+	 * Seems we also bail if CMD or TIMEOUT bytes are set???
+	 */
+	mc417_memory_read(dev, dev->cx23417_mailbox, &flag);
+	if (flag) {
+		printk(KERN_ERR "ERROR: Mailbox appears to be in use "
+			"(%x), cmd = %s\n", flag, cmd_to_str(command));
+		return -1;
+	}
+
+	flag |= 1; /* tell 'em we're working on it */
+	mc417_memory_write(dev, dev->cx23417_mailbox, flag);
+
+	/* write command + args + fill remaining with zeros */
+	/* command code */
+	mc417_memory_write(dev, dev->cx23417_mailbox + 1, command);
+	mc417_memory_write(dev, dev->cx23417_mailbox + 3,
+		IVTV_API_STD_TIMEOUT); /* timeout */
+	for (i = 0; i < in; i++) {
+		mc417_memory_write(dev, dev->cx23417_mailbox + 4 + i, data[i]);
+		dprintk(3, "API Input %d = %d\n", i, data[i]);
+	}
+	for (; i < CX2341X_MBOX_MAX_DATA; i++)
+		mc417_memory_write(dev, dev->cx23417_mailbox + 4 + i, 0);
+
+	flag |= 3; /* tell 'em we're done writing */
+	mc417_memory_write(dev, dev->cx23417_mailbox, flag);
+
+	/* wait for firmware to handle the API command */
+	timeout = jiffies + msecs_to_jiffies(10);
+	for (;;) {
+		mc417_memory_read(dev, dev->cx23417_mailbox, &flag);
+		if (0 != (flag & 4))
+			break;
+		if (time_after(jiffies, timeout)) {
+			printk(KERN_ERR "ERROR: API Mailbox timeout\n");
+			return -1;
+		}
+		udelay(10);
+	}
+
+	/* read output values */
+	for (i = 0; i < out; i++) {
+		mc417_memory_read(dev, dev->cx23417_mailbox + 4 + i, data + i);
+		dprintk(3, "API Output %d = %d\n", i, data[i]);
+	}
+
+	mc417_memory_read(dev, dev->cx23417_mailbox + 2, &retval);
+	dprintk(3, "API result = %d\n", retval);
+
+	flag = 0;
+	mc417_memory_write(dev, dev->cx23417_mailbox, flag);
+
+	return retval;
+}
+
+/* We don't need to call the API often, so using just one
+ * mailbox will probably suffice
+ */
+static int cx23885_api_cmd(struct cx23885_dev *dev,
+			   u32 command,
+			   u32 inputcnt,
+			   u32 outputcnt,
+			   ...)
+{
+	u32 data[CX2341X_MBOX_MAX_DATA];
+	va_list vargs;
+	int i, err;
+
+	dprintk(3, "%s() cmds = 0x%08x\n", __func__, command);
+
+	va_start(vargs, outputcnt);
+	for (i = 0; i < inputcnt; i++)
+		data[i] = va_arg(vargs, int);
+
+	err = cx23885_mbox_func(dev, command, inputcnt, outputcnt, data);
+	for (i = 0; i < outputcnt; i++) {
+		int *vptr = va_arg(vargs, int *);
+		*vptr = data[i];
+	}
+	va_end(vargs);
+
+	return err;
+}
+
+static int cx23885_find_mailbox(struct cx23885_dev *dev)
+{
+	u32 signature[4] = {
+		0x12345678, 0x34567812, 0x56781234, 0x78123456
+	};
+	int signaturecnt = 0;
+	u32 value;
+	int i;
+
+	dprintk(2, "%s()\n", __func__);
+
+	for (i = 0; i < CX23885_FIRM_IMAGE_SIZE; i++) {
+		mc417_memory_read(dev, i, &value);
+		if (value == signature[signaturecnt])
+			signaturecnt++;
+		else
+			signaturecnt = 0;
+		if (4 == signaturecnt) {
+			dprintk(1, "Mailbox signature found at 0x%x\n", i+1);
+			return i+1;
+		}
+	}
+	printk(KERN_ERR "Mailbox signature values not found!\n");
+	return -1;
+}
+
+static int cx23885_load_firmware(struct cx23885_dev *dev)
+{
+	static const unsigned char magic[8] = {
+		0xa7, 0x0d, 0x00, 0x00, 0x66, 0xbb, 0x55, 0xaa
+	};
+	const struct firmware *firmware;
+	int i, retval = 0;
+	u32 value = 0;
+	u32 gpio_output = 0;
+	u32 gpio_value;
+	u32 checksum = 0;
+	u32 *dataptr;
+
+	dprintk(2, "%s()\n", __func__);
+
+	/* Save GPIO settings before reset of APU */
+	retval |= mc417_memory_read(dev, 0x9020, &gpio_output);
+	retval |= mc417_memory_read(dev, 0x900C, &gpio_value);
+
+	retval  = mc417_register_write(dev,
+		IVTV_REG_VPU, 0xFFFFFFED);
+	retval |= mc417_register_write(dev,
+		IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST);
+	retval |= mc417_register_write(dev,
+		IVTV_REG_ENC_SDRAM_REFRESH, 0x80000800);
+	retval |= mc417_register_write(dev,
+		IVTV_REG_ENC_SDRAM_PRECHARGE, 0x1A);
+	retval |= mc417_register_write(dev,
+		IVTV_REG_APU, 0);
+
+	if (retval != 0) {
+		printk(KERN_ERR "%s: Error with mc417_register_write\n",
+			__func__);
+		return -1;
+	}
+
+	retval = request_firmware(&firmware, CX23885_FIRM_IMAGE_NAME,
+				  &dev->pci->dev);
+
+	if (retval != 0) {
+		printk(KERN_ERR
+			"ERROR: Hotplug firmware request failed (%s).\n",
+			CX23885_FIRM_IMAGE_NAME);
+		printk(KERN_ERR "Please fix your hotplug setup, the board will "
+			"not work without firmware loaded!\n");
+		return -1;
+	}
+
+	if (firmware->size != CX23885_FIRM_IMAGE_SIZE) {
+		printk(KERN_ERR "ERROR: Firmware size mismatch "
+			"(have %zd, expected %d)\n",
+			firmware->size, CX23885_FIRM_IMAGE_SIZE);
+		release_firmware(firmware);
+		return -1;
+	}
+
+	if (0 != memcmp(firmware->data, magic, 8)) {
+		printk(KERN_ERR
+			"ERROR: Firmware magic mismatch, wrong file?\n");
+		release_firmware(firmware);
+		return -1;
+	}
+
+	/* transfer to the chip */
+	dprintk(2, "Loading firmware ...\n");
+	dataptr = (u32 *)firmware->data;
+	for (i = 0; i < (firmware->size >> 2); i++) {
+		value = *dataptr;
+		checksum += ~value;
+		if (mc417_memory_write(dev, i, value) != 0) {
+			printk(KERN_ERR "ERROR: Loading firmware failed!\n");
+			release_firmware(firmware);
+			return -1;
+		}
+		dataptr++;
+	}
+
+	/* read back to verify with the checksum */
+	dprintk(1, "Verifying firmware ...\n");
+	for (i--; i >= 0; i--) {
+		if (mc417_memory_read(dev, i, &value) != 0) {
+			printk(KERN_ERR "ERROR: Reading firmware failed!\n");
+			release_firmware(firmware);
+			return -1;
+		}
+		checksum -= ~value;
+	}
+	if (checksum) {
+		printk(KERN_ERR
+			"ERROR: Firmware load failed (checksum mismatch).\n");
+		release_firmware(firmware);
+		return -1;
+	}
+	release_firmware(firmware);
+	dprintk(1, "Firmware upload successful.\n");
+
+	retval |= mc417_register_write(dev, IVTV_REG_HW_BLOCKS,
+		IVTV_CMD_HW_BLOCKS_RST);
+
+	/* F/W power up disturbs the GPIOs, restore state */
+	retval |= mc417_register_write(dev, 0x9020, gpio_output);
+	retval |= mc417_register_write(dev, 0x900C, gpio_value);
+
+	retval |= mc417_register_read(dev, IVTV_REG_VPU, &value);
+	retval |= mc417_register_write(dev, IVTV_REG_VPU, value & 0xFFFFFFE8);
+
+	/* Hardcoded GPIO's here */
+	retval |= mc417_register_write(dev, 0x9020, 0x4000);
+	retval |= mc417_register_write(dev, 0x900C, 0x4000);
+
+	mc417_register_read(dev, 0x9020, &gpio_output);
+	mc417_register_read(dev, 0x900C, &gpio_value);
+
+	if (retval < 0)
+		printk(KERN_ERR "%s: Error with mc417_register_write\n",
+			__func__);
+	return 0;
+}
+
+void cx23885_417_check_encoder(struct cx23885_dev *dev)
+{
+	u32 status, seq;
+
+	status = seq = 0;
+	cx23885_api_cmd(dev, CX2341X_ENC_GET_SEQ_END, 0, 2, &status, &seq);
+	dprintk(1, "%s() status = %d, seq = %d\n", __func__, status, seq);
+}
+
+static void cx23885_codec_settings(struct cx23885_dev *dev)
+{
+	dprintk(1, "%s()\n", __func__);
+
+	/* Dynamically change the height based on video standard */
+	if (dev->encodernorm.id & V4L2_STD_525_60)
+		dev->ts1.height = 480;
+	else
+		dev->ts1.height = 576;
+
+	/* assign frame size */
+	cx23885_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0,
+				dev->ts1.height, dev->ts1.width);
+
+	dev->mpeg_params.width = dev->ts1.width;
+	dev->mpeg_params.height = dev->ts1.height;
+	dev->mpeg_params.is_50hz =
+		(dev->encodernorm.id & V4L2_STD_625_50) != 0;
+
+	cx2341x_update(dev, cx23885_mbox_func, NULL, &dev->mpeg_params);
+
+	cx23885_api_cmd(dev, CX2341X_ENC_MISC, 2, 0, 3, 1);
+	cx23885_api_cmd(dev, CX2341X_ENC_MISC, 2, 0, 4, 1);
+}
+
+static int cx23885_initialize_codec(struct cx23885_dev *dev, int startencoder)
+{
+	int version;
+	int retval;
+	u32 i, data[7];
+
+	dprintk(1, "%s()\n", __func__);
+
+	retval = cx23885_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); /* ping */
+	if (retval < 0) {
+		dprintk(2, "%s() PING OK\n", __func__);
+		retval = cx23885_load_firmware(dev);
+		if (retval < 0) {
+			printk(KERN_ERR "%s() f/w load failed\n", __func__);
+			return retval;
+		}
+		retval = cx23885_find_mailbox(dev);
+		if (retval < 0) {
+			printk(KERN_ERR "%s() mailbox < 0, error\n",
+				__func__);
+			return -1;
+		}
+		dev->cx23417_mailbox = retval;
+		retval = cx23885_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0);
+		if (retval < 0) {
+			printk(KERN_ERR
+				"ERROR: cx23417 firmware ping failed!\n");
+			return -1;
+		}
+		retval = cx23885_api_cmd(dev, CX2341X_ENC_GET_VERSION, 0, 1,
+			&version);
+		if (retval < 0) {
+			printk(KERN_ERR "ERROR: cx23417 firmware get encoder :"
+				"version failed!\n");
+			return -1;
+		}
+		dprintk(1, "cx23417 firmware version is 0x%08x\n", version);
+		msleep(200);
+	}
+
+	cx23885_codec_settings(dev);
+	msleep(60);
+
+	cx23885_api_cmd(dev, CX2341X_ENC_SET_NUM_VSYNC_LINES, 2, 0,
+		CX23885_FIELD1_SAA7115, CX23885_FIELD2_SAA7115);
+	cx23885_api_cmd(dev, CX2341X_ENC_SET_PLACEHOLDER, 12, 0,
+		CX23885_CUSTOM_EXTENSION_USR_DATA, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+		0, 0);
+
+	/* Setup to capture VBI */
+	data[0] = 0x0001BD00;
+	data[1] = 1;          /* frames per interrupt */
+	data[2] = 4;          /* total bufs */
+	data[3] = 0x91559155; /* start codes */
+	data[4] = 0x206080C0; /* stop codes */
+	data[5] = 6;          /* lines */
+	data[6] = 64;         /* BPL */
+
+	cx23885_api_cmd(dev, CX2341X_ENC_SET_VBI_CONFIG, 7, 0, data[0], data[1],
+		data[2], data[3], data[4], data[5], data[6]);
+
+	for (i = 2; i <= 24; i++) {
+		int valid;
+
+		valid = ((i >= 19) && (i <= 21));
+		cx23885_api_cmd(dev, CX2341X_ENC_SET_VBI_LINE, 5, 0, i,
+				valid, 0 , 0, 0);
+		cx23885_api_cmd(dev, CX2341X_ENC_SET_VBI_LINE, 5, 0,
+				i | 0x80000000, valid, 0, 0, 0);
+	}
+
+	cx23885_api_cmd(dev, CX2341X_ENC_MUTE_AUDIO, 1, 0, CX23885_UNMUTE);
+	msleep(60);
+
+	/* initialize the video input */
+	cx23885_api_cmd(dev, CX2341X_ENC_INITIALIZE_INPUT, 0, 0);
+	msleep(60);
+
+	/* Enable VIP style pixel invalidation so we work with scaled mode */
+	mc417_memory_write(dev, 2120, 0x00000080);
+
+	/* start capturing to the host interface */
+	if (startencoder) {
+		cx23885_api_cmd(dev, CX2341X_ENC_START_CAPTURE, 2, 0,
+			CX23885_MPEG_CAPTURE, CX23885_RAW_BITS_NONE);
+		msleep(10);
+	}
+
+	return 0;
+}
+
+/* ------------------------------------------------------------------ */
+
+static int bb_buf_setup(struct videobuf_queue *q,
+	unsigned int *count, unsigned int *size)
+{
+	struct cx23885_fh *fh = q->priv_data;
+
+	fh->dev->ts1.ts_packet_size  = mpeglinesize;
+	fh->dev->ts1.ts_packet_count = mpeglines;
+
+	*size = fh->dev->ts1.ts_packet_size * fh->dev->ts1.ts_packet_count;
+	*count = mpegbufs;
+
+	return 0;
+}
+
+static int bb_buf_prepare(struct videobuf_queue *q,
+	struct videobuf_buffer *vb, enum v4l2_field field)
+{
+	struct cx23885_fh *fh = q->priv_data;
+	return cx23885_buf_prepare(q, &fh->dev->ts1,
+		(struct cx23885_buffer *)vb,
+		field);
+}
+
+static void bb_buf_queue(struct videobuf_queue *q,
+	struct videobuf_buffer *vb)
+{
+	struct cx23885_fh *fh = q->priv_data;
+	cx23885_buf_queue(&fh->dev->ts1, (struct cx23885_buffer *)vb);
+}
+
+static void bb_buf_release(struct videobuf_queue *q,
+	struct videobuf_buffer *vb)
+{
+	cx23885_free_buffer(q, (struct cx23885_buffer *)vb);
+}
+
+static struct videobuf_queue_ops cx23885_qops = {
+	.buf_setup    = bb_buf_setup,
+	.buf_prepare  = bb_buf_prepare,
+	.buf_queue    = bb_buf_queue,
+	.buf_release  = bb_buf_release,
+};
+
+/* ------------------------------------------------------------------ */
+
+static const u32 *ctrl_classes[] = {
+	cx2341x_mpeg_ctrls,
+	NULL
+};
+
+static int cx23885_queryctrl(struct cx23885_dev *dev,
+	struct v4l2_queryctrl *qctrl)
+{
+	qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id);
+	if (qctrl->id == 0)
+		return -EINVAL;
+
+	/* MPEG V4L2 controls */
+	if (cx2341x_ctrl_query(&dev->mpeg_params, qctrl))
+		qctrl->flags |= V4L2_CTRL_FLAG_DISABLED;
+
+	return 0;
+}
+
+static int cx23885_querymenu(struct cx23885_dev *dev,
+	struct v4l2_querymenu *qmenu)
+{
+	struct v4l2_queryctrl qctrl;
+
+	qctrl.id = qmenu->id;
+	cx23885_queryctrl(dev, &qctrl);
+	return v4l2_ctrl_query_menu(qmenu, &qctrl,
+		cx2341x_ctrl_get_menu(&dev->mpeg_params, qmenu->id));
+}
+
+static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id)
+{
+	struct cx23885_fh  *fh  = file->private_data;
+	struct cx23885_dev *dev = fh->dev;
+
+	call_all(dev, core, g_std, id);
+
+	return 0;
+}
+
+static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *id)
+{
+	struct cx23885_fh  *fh  = file->private_data;
+	struct cx23885_dev *dev = fh->dev;
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(cx23885_tvnorms); i++)
+		if (*id & cx23885_tvnorms[i].id)
+			break;
+	if (i == ARRAY_SIZE(cx23885_tvnorms))
+		return -EINVAL;
+	dev->encodernorm = cx23885_tvnorms[i];
+
+	/* Have the drier core notify the subdevices */
+	mutex_lock(&dev->lock);
+	cx23885_set_tvnorm(dev, *id);
+	mutex_unlock(&dev->lock);
+
+	return 0;
+}
+
+static int vidioc_enum_input(struct file *file, void *priv,
+	struct v4l2_input *i)
+{
+	struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
+	dprintk(1, "%s()\n", __func__);
+	return cx23885_enum_input(dev, i);
+}
+
+static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
+{
+	return cx23885_get_input(file, priv, i);
+}
+
+static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
+{
+	return cx23885_set_input(file, priv, i);
+}
+
+static int vidioc_g_tuner(struct file *file, void *priv,
+				struct v4l2_tuner *t)
+{
+	struct cx23885_fh  *fh  = file->private_data;
+	struct cx23885_dev *dev = fh->dev;
+
+	if (UNSET == dev->tuner_type)
+		return -EINVAL;
+	if (0 != t->index)
+		return -EINVAL;
+	strcpy(t->name, "Television");
+	call_all(dev, tuner, g_tuner, t);
+
+	dprintk(1, "VIDIOC_G_TUNER: tuner type %d\n", t->type);
+
+	return 0;
+}
+
+static int vidioc_s_tuner(struct file *file, void *priv,
+				struct v4l2_tuner *t)
+{
+	struct cx23885_fh  *fh  = file->private_data;
+	struct cx23885_dev *dev = fh->dev;
+
+	if (UNSET == dev->tuner_type)
+		return -EINVAL;
+
+	/* Update the A/V core */
+	call_all(dev, tuner, s_tuner, t);
+
+	return 0;
+}
+
+static int vidioc_g_frequency(struct file *file, void *priv,
+				struct v4l2_frequency *f)
+{
+	struct cx23885_fh  *fh  = file->private_data;
+	struct cx23885_dev *dev = fh->dev;
+
+	if (UNSET == dev->tuner_type)
+		return -EINVAL;
+	f->type = V4L2_TUNER_ANALOG_TV;
+	f->frequency = dev->freq;
+
+	call_all(dev, tuner, g_frequency, f);
+
+	return 0;
+}
+
+static int vidioc_s_frequency(struct file *file, void *priv,
+	struct v4l2_frequency *f)
+{
+	return cx23885_set_frequency(file, priv, f);
+}
+
+static int vidioc_g_ctrl(struct file *file, void *priv,
+	struct v4l2_control *ctl)
+{
+	struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
+
+	return cx23885_get_control(dev, ctl);
+}
+
+static int vidioc_s_ctrl(struct file *file, void *priv,
+	struct v4l2_control *ctl)
+{
+	struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
+
+	return cx23885_set_control(dev, ctl);
+}
+
+static int vidioc_querycap(struct file *file, void  *priv,
+				struct v4l2_capability *cap)
+{
+	struct cx23885_fh  *fh  = file->private_data;
+	struct cx23885_dev *dev = fh->dev;
+	struct cx23885_tsport  *tsport = &dev->ts1;
+
+	strlcpy(cap->driver, dev->name, sizeof(cap->driver));
+	strlcpy(cap->card, cx23885_boards[tsport->dev->board].name,
+		sizeof(cap->card));
+	sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
+	cap->capabilities =
+		V4L2_CAP_VIDEO_CAPTURE |
+		V4L2_CAP_READWRITE     |
+		V4L2_CAP_STREAMING     |
+		0;
+	if (UNSET != dev->tuner_type)
+		cap->capabilities |= V4L2_CAP_TUNER;
+
+	return 0;
+}
+
+static int vidioc_enum_fmt_vid_cap(struct file *file, void  *priv,
+					struct v4l2_fmtdesc *f)
+{
+	if (f->index != 0)
+		return -EINVAL;
+
+	strlcpy(f->description, "MPEG", sizeof(f->description));
+	f->pixelformat = V4L2_PIX_FMT_MPEG;
+
+	return 0;
+}
+
+static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
+				struct v4l2_format *f)
+{
+	struct cx23885_fh  *fh  = file->private_data;
+	struct cx23885_dev *dev = fh->dev;
+
+	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.colorspace   = 0;
+	f->fmt.pix.width        = dev->ts1.width;
+	f->fmt.pix.height       = dev->ts1.height;
+	f->fmt.pix.field        = fh->mpegq.field;
+	dprintk(1, "VIDIOC_G_FMT: w: %d, h: %d, f: %d\n",
+		dev->ts1.width, dev->ts1.height, fh->mpegq.field);
+	return 0;
+}
+
+static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
+				struct v4l2_format *f)
+{
+	struct cx23885_fh  *fh  = file->private_data;
+	struct cx23885_dev *dev = fh->dev;
+
+	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.colorspace   = 0;
+	dprintk(1, "VIDIOC_TRY_FMT: w: %d, h: %d, f: %d\n",
+		dev->ts1.width, dev->ts1.height, fh->mpegq.field);
+	return 0;
+}
+
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
+				struct v4l2_format *f)
+{
+	struct cx23885_fh  *fh  = file->private_data;
+	struct cx23885_dev *dev = fh->dev;
+
+	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.colorspace   = 0;
+	dprintk(1, "VIDIOC_S_FMT: w: %d, h: %d, f: %d\n",
+		f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field);
+	return 0;
+}
+
+static int vidioc_reqbufs(struct file *file, void *priv,
+				struct v4l2_requestbuffers *p)
+{
+	struct cx23885_fh  *fh  = file->private_data;
+
+	return videobuf_reqbufs(&fh->mpegq, p);
+}
+
+static int vidioc_querybuf(struct file *file, void *priv,
+				struct v4l2_buffer *p)
+{
+	struct cx23885_fh  *fh  = file->private_data;
+
+	return videobuf_querybuf(&fh->mpegq, p);
+}
+
+static int vidioc_qbuf(struct file *file, void *priv,
+				struct v4l2_buffer *p)
+{
+	struct cx23885_fh  *fh  = file->private_data;
+
+	return videobuf_qbuf(&fh->mpegq, p);
+}
+
+static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
+{
+	struct cx23885_fh  *fh  = priv;
+
+	return videobuf_dqbuf(&fh->mpegq, b, file->f_flags & O_NONBLOCK);
+}
+
+
+static int vidioc_streamon(struct file *file, void *priv,
+				enum v4l2_buf_type i)
+{
+	struct cx23885_fh  *fh  = file->private_data;
+
+	return videobuf_streamon(&fh->mpegq);
+}
+
+static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+	struct cx23885_fh  *fh  = file->private_data;
+
+	return videobuf_streamoff(&fh->mpegq);
+}
+
+static int vidioc_g_ext_ctrls(struct file *file, void *priv,
+				struct v4l2_ext_controls *f)
+{
+	struct cx23885_fh  *fh  = priv;
+	struct cx23885_dev *dev = fh->dev;
+
+	if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
+		return -EINVAL;
+	return cx2341x_ext_ctrls(&dev->mpeg_params, 0, f, VIDIOC_G_EXT_CTRLS);
+}
+
+static int vidioc_s_ext_ctrls(struct file *file, void *priv,
+				struct v4l2_ext_controls *f)
+{
+	struct cx23885_fh  *fh  = priv;
+	struct cx23885_dev *dev = fh->dev;
+	struct cx2341x_mpeg_params p;
+	int err;
+
+	if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
+		return -EINVAL;
+
+	p = dev->mpeg_params;
+	err = cx2341x_ext_ctrls(&p, 0, f, VIDIOC_S_EXT_CTRLS);
+
+	if (err == 0) {
+		err = cx2341x_update(dev, cx23885_mbox_func,
+			&dev->mpeg_params, &p);
+		dev->mpeg_params = p;
+	}
+	return err;
+}
+
+static int vidioc_try_ext_ctrls(struct file *file, void *priv,
+				struct v4l2_ext_controls *f)
+{
+	struct cx23885_fh  *fh  = priv;
+	struct cx23885_dev *dev = fh->dev;
+	struct cx2341x_mpeg_params p;
+	int err;
+
+	if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
+		return -EINVAL;
+
+	p = dev->mpeg_params;
+	err = cx2341x_ext_ctrls(&p, 0, f, VIDIOC_TRY_EXT_CTRLS);
+	return err;
+}
+
+static int vidioc_log_status(struct file *file, void *priv)
+{
+	struct cx23885_fh  *fh  = priv;
+	struct cx23885_dev *dev = fh->dev;
+	char name[32 + 2];
+
+	snprintf(name, sizeof(name), "%s/2", dev->name);
+	printk(KERN_INFO
+		"%s/2: ============  START LOG STATUS  ============\n",
+	       dev->name);
+	call_all(dev, core, log_status);
+	cx2341x_log_status(&dev->mpeg_params, name);
+	printk(KERN_INFO
+		"%s/2: =============  END LOG STATUS  =============\n",
+	       dev->name);
+	return 0;
+}
+
+static int vidioc_querymenu(struct file *file, void *priv,
+				struct v4l2_querymenu *a)
+{
+	struct cx23885_fh  *fh  = priv;
+	struct cx23885_dev *dev = fh->dev;
+
+	return cx23885_querymenu(dev, a);
+}
+
+static int vidioc_queryctrl(struct file *file, void *priv,
+				struct v4l2_queryctrl *c)
+{
+	struct cx23885_fh  *fh  = priv;
+	struct cx23885_dev *dev = fh->dev;
+
+	return cx23885_queryctrl(dev, c);
+}
+
+static int mpeg_open(struct file *file)
+{
+	struct cx23885_dev *dev = video_drvdata(file);
+	struct cx23885_fh *fh;
+
+	dprintk(2, "%s()\n", __func__);
+
+	/* allocate + initialize per filehandle data */
+	fh = kzalloc(sizeof(*fh), GFP_KERNEL);
+	if (!fh)
+		return -ENOMEM;
+
+	file->private_data = fh;
+	fh->dev      = dev;
+
+	videobuf_queue_sg_init(&fh->mpegq, &cx23885_qops,
+			    &dev->pci->dev, &dev->ts1.slock,
+			    V4L2_BUF_TYPE_VIDEO_CAPTURE,
+			    V4L2_FIELD_INTERLACED,
+			    sizeof(struct cx23885_buffer),
+			    fh, NULL);
+	return 0;
+}
+
+static int mpeg_release(struct file *file)
+{
+	struct cx23885_fh  *fh  = file->private_data;
+	struct cx23885_dev *dev = fh->dev;
+
+	dprintk(2, "%s()\n", __func__);
+
+	/* FIXME: Review this crap */
+	/* Shut device down on last close */
+	if (atomic_cmpxchg(&fh->v4l_reading, 1, 0) == 1) {
+		if (atomic_dec_return(&dev->v4l_reader_count) == 0) {
+			/* stop mpeg capture */
+			cx23885_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0,
+				CX23885_END_NOW, CX23885_MPEG_CAPTURE,
+				CX23885_RAW_BITS_NONE);
+
+			msleep(500);
+			cx23885_417_check_encoder(dev);
+
+			cx23885_cancel_buffers(&fh->dev->ts1);
+		}
+	}
+
+	if (fh->mpegq.streaming)
+		videobuf_streamoff(&fh->mpegq);
+	if (fh->mpegq.reading)
+		videobuf_read_stop(&fh->mpegq);
+
+	videobuf_mmap_free(&fh->mpegq);
+	file->private_data = NULL;
+	kfree(fh);
+
+	return 0;
+}
+
+static ssize_t mpeg_read(struct file *file, char __user *data,
+	size_t count, loff_t *ppos)
+{
+	struct cx23885_fh *fh = file->private_data;
+	struct cx23885_dev *dev = fh->dev;
+
+	dprintk(2, "%s()\n", __func__);
+
+	/* Deal w/ A/V decoder * and mpeg encoder sync issues. */
+	/* Start mpeg encoder on first read. */
+	if (atomic_cmpxchg(&fh->v4l_reading, 0, 1) == 0) {
+		if (atomic_inc_return(&dev->v4l_reader_count) == 1) {
+			if (cx23885_initialize_codec(dev, 1) < 0)
+				return -EINVAL;
+		}
+	}
+
+	return videobuf_read_stream(&fh->mpegq, data, count, ppos, 0,
+				    file->f_flags & O_NONBLOCK);
+}
+
+static unsigned int mpeg_poll(struct file *file,
+	struct poll_table_struct *wait)
+{
+	struct cx23885_fh *fh = file->private_data;
+	struct cx23885_dev *dev = fh->dev;
+
+	dprintk(2, "%s\n", __func__);
+
+	return videobuf_poll_stream(file, &fh->mpegq, wait);
+}
+
+static int mpeg_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	struct cx23885_fh *fh = file->private_data;
+	struct cx23885_dev *dev = fh->dev;
+
+	dprintk(2, "%s()\n", __func__);
+
+	return videobuf_mmap_mapper(&fh->mpegq, vma);
+}
+
+static struct v4l2_file_operations mpeg_fops = {
+	.owner	       = THIS_MODULE,
+	.open	       = mpeg_open,
+	.release       = mpeg_release,
+	.read	       = mpeg_read,
+	.poll          = mpeg_poll,
+	.mmap	       = mpeg_mmap,
+	.ioctl	       = video_ioctl2,
+};
+
+static const struct v4l2_ioctl_ops mpeg_ioctl_ops = {
+	.vidioc_querystd	 = vidioc_g_std,
+	.vidioc_g_std		 = vidioc_g_std,
+	.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_g_tuner		 = vidioc_g_tuner,
+	.vidioc_s_tuner		 = vidioc_s_tuner,
+	.vidioc_g_frequency	 = vidioc_g_frequency,
+	.vidioc_s_frequency	 = vidioc_s_frequency,
+	.vidioc_s_ctrl		 = vidioc_s_ctrl,
+	.vidioc_g_ctrl		 = vidioc_g_ctrl,
+	.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,
+	.vidioc_reqbufs		 = vidioc_reqbufs,
+	.vidioc_querybuf	 = vidioc_querybuf,
+	.vidioc_qbuf		 = vidioc_qbuf,
+	.vidioc_dqbuf		 = vidioc_dqbuf,
+	.vidioc_streamon	 = vidioc_streamon,
+	.vidioc_streamoff	 = vidioc_streamoff,
+	.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_log_status	 = vidioc_log_status,
+	.vidioc_querymenu	 = vidioc_querymenu,
+	.vidioc_queryctrl	 = vidioc_queryctrl,
+	.vidioc_g_chip_ident	 = cx23885_g_chip_ident,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.vidioc_g_register	 = cx23885_g_register,
+	.vidioc_s_register	 = cx23885_s_register,
+#endif
+};
+
+static struct video_device cx23885_mpeg_template = {
+	.name          = "cx23885",
+	.fops          = &mpeg_fops,
+	.ioctl_ops     = &mpeg_ioctl_ops,
+	.tvnorms       = CX23885_NORMS,
+	.current_norm  = V4L2_STD_NTSC_M,
+};
+
+void cx23885_417_unregister(struct cx23885_dev *dev)
+{
+	dprintk(1, "%s()\n", __func__);
+
+	if (dev->v4l_device) {
+		if (video_is_registered(dev->v4l_device))
+			video_unregister_device(dev->v4l_device);
+		else
+			video_device_release(dev->v4l_device);
+		dev->v4l_device = NULL;
+	}
+}
+
+static struct video_device *cx23885_video_dev_alloc(
+	struct cx23885_tsport *tsport,
+	struct pci_dev *pci,
+	struct video_device *template,
+	char *type)
+{
+	struct video_device *vfd;
+	struct cx23885_dev *dev = tsport->dev;
+
+	dprintk(1, "%s()\n", __func__);
+
+	vfd = video_device_alloc();
+	if (NULL == vfd)
+		return NULL;
+	*vfd = *template;
+	snprintf(vfd->name, sizeof(vfd->name), "%s (%s)",
+		cx23885_boards[tsport->dev->board].name, type);
+	vfd->parent  = &pci->dev;
+	vfd->release = video_device_release;
+	return vfd;
+}
+
+int cx23885_417_register(struct cx23885_dev *dev)
+{
+	/* FIXME: Port1 hardcoded here */
+	int err = -ENODEV;
+	struct cx23885_tsport *tsport = &dev->ts1;
+
+	dprintk(1, "%s()\n", __func__);
+
+	if (cx23885_boards[dev->board].portb != CX23885_MPEG_ENCODER)
+		return err;
+
+	/* Set default TV standard */
+	dev->encodernorm = cx23885_tvnorms[0];
+
+	if (dev->encodernorm.id & V4L2_STD_525_60)
+		tsport->height = 480;
+	else
+		tsport->height = 576;
+
+	tsport->width = 720;
+	cx2341x_fill_defaults(&dev->mpeg_params);
+
+	dev->mpeg_params.port = CX2341X_PORT_SERIAL;
+
+	/* Allocate and initialize V4L video device */
+	dev->v4l_device = cx23885_video_dev_alloc(tsport,
+		dev->pci, &cx23885_mpeg_template, "mpeg");
+	video_set_drvdata(dev->v4l_device, dev);
+	err = video_register_device(dev->v4l_device,
+		VFL_TYPE_GRABBER, -1);
+	if (err < 0) {
+		printk(KERN_INFO "%s: can't register mpeg device\n", dev->name);
+		return err;
+	}
+
+	printk(KERN_INFO "%s: registered device %s [mpeg]\n",
+	       dev->name, video_device_node_name(dev->v4l_device));
+
+	/* ST: Configure the encoder paramaters, but don't begin
+	 * encoding, this resolves an issue where the first time the
+	 * encoder is started video can be choppy.
+	 */
+	cx23885_initialize_codec(dev, 0);
+
+	return 0;
+}
+
+MODULE_FIRMWARE(CX23885_FIRM_IMAGE_NAME);
diff --git a/drivers/media/pci/cx23885/cx23885-alsa.c b/drivers/media/pci/cx23885/cx23885-alsa.c
new file mode 100644
index 0000000..7951692
--- /dev/null
+++ b/drivers/media/pci/cx23885/cx23885-alsa.c
@@ -0,0 +1,535 @@
+/*
+ *
+ *  Support for CX23885 analog audio capture
+ *
+ *    (c) 2008 Mijhail Moreyra <mijhail.moreyra@gmail.com>
+ *    Adapted from cx88-alsa.c
+ *    (c) 2009 Steven Toth <stoth@kernellabs.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/vmalloc.h>
+#include <linux/dma-mapping.h>
+#include <linux/pci.h>
+
+#include <asm/delay.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/control.h>
+#include <sound/initval.h>
+
+#include <sound/tlv.h>
+
+
+#include "cx23885.h"
+#include "cx23885-reg.h"
+
+#define AUDIO_SRAM_CHANNEL	SRAM_CH07
+
+#define dprintk(level, fmt, arg...)	if (audio_debug >= level) \
+	printk(KERN_INFO "%s: " fmt, chip->dev->name , ## arg)
+
+#define dprintk_core(level, fmt, arg...)	if (audio_debug >= level) \
+	printk(KERN_DEBUG "%s: " fmt, chip->dev->name , ## arg)
+
+/****************************************************************************
+			Module global static vars
+ ****************************************************************************/
+
+static unsigned int disable_analog_audio;
+module_param(disable_analog_audio, int, 0644);
+MODULE_PARM_DESC(disable_analog_audio, "disable analog audio ALSA driver");
+
+static unsigned int audio_debug;
+module_param(audio_debug, int, 0644);
+MODULE_PARM_DESC(audio_debug, "enable debug messages [analog audio]");
+
+/****************************************************************************
+			Board specific funtions
+ ****************************************************************************/
+
+/* Constants taken from cx88-reg.h */
+#define AUD_INT_DN_RISCI1       (1 <<  0)
+#define AUD_INT_UP_RISCI1       (1 <<  1)
+#define AUD_INT_RDS_DN_RISCI1   (1 <<  2)
+#define AUD_INT_DN_RISCI2       (1 <<  4) /* yes, 3 is skipped */
+#define AUD_INT_UP_RISCI2       (1 <<  5)
+#define AUD_INT_RDS_DN_RISCI2   (1 <<  6)
+#define AUD_INT_DN_SYNC         (1 << 12)
+#define AUD_INT_UP_SYNC         (1 << 13)
+#define AUD_INT_RDS_DN_SYNC     (1 << 14)
+#define AUD_INT_OPC_ERR         (1 << 16)
+#define AUD_INT_BER_IRQ         (1 << 20)
+#define AUD_INT_MCHG_IRQ        (1 << 21)
+#define GP_COUNT_CONTROL_RESET	0x3
+
+/*
+ * BOARD Specific: Sets audio DMA
+ */
+
+static int cx23885_start_audio_dma(struct cx23885_audio_dev *chip)
+{
+	struct cx23885_audio_buffer *buf = chip->buf;
+	struct cx23885_dev *dev  = chip->dev;
+	struct sram_channel *audio_ch =
+		&dev->sram_channels[AUDIO_SRAM_CHANNEL];
+
+	dprintk(1, "%s()\n", __func__);
+
+	/* Make sure RISC/FIFO are off before changing FIFO/RISC settings */
+	cx_clear(AUD_INT_DMA_CTL, 0x11);
+
+	/* setup fifo + format - out channel */
+	cx23885_sram_channel_setup(chip->dev, audio_ch, buf->bpl,
+		buf->risc.dma);
+
+	/* sets bpl size */
+	cx_write(AUD_INT_A_LNGTH, buf->bpl);
+
+	/* This is required to get good audio (1 seems to be ok) */
+	cx_write(AUD_INT_A_MODE, 1);
+
+	/* reset counter */
+	cx_write(AUD_INT_A_GPCNT_CTL, GP_COUNT_CONTROL_RESET);
+	atomic_set(&chip->count, 0);
+
+	dprintk(1, "Start audio DMA, %d B/line, %d lines/FIFO, %d periods, %d "
+		"byte buffer\n", buf->bpl, cx_read(audio_ch->cmds_start+12)>>1,
+		chip->num_periods, buf->bpl * chip->num_periods);
+
+	/* Enables corresponding bits at AUD_INT_STAT */
+	cx_write(AUDIO_INT_INT_MSK, AUD_INT_OPC_ERR | AUD_INT_DN_SYNC |
+				    AUD_INT_DN_RISCI1);
+
+	/* Clean any pending interrupt bits already set */
+	cx_write(AUDIO_INT_INT_STAT, ~0);
+
+	/* enable audio irqs */
+	cx_set(PCI_INT_MSK, chip->dev->pci_irqmask | PCI_MSK_AUD_INT);
+
+	/* start dma */
+	cx_set(DEV_CNTRL2, (1<<5)); /* Enables Risc Processor */
+	cx_set(AUD_INT_DMA_CTL, 0x11); /* audio downstream FIFO and
+					  RISC enable */
+	if (audio_debug)
+		cx23885_sram_channel_dump(chip->dev, audio_ch);
+
+	return 0;
+}
+
+/*
+ * BOARD Specific: Resets audio DMA
+ */
+static int cx23885_stop_audio_dma(struct cx23885_audio_dev *chip)
+{
+	struct cx23885_dev *dev = chip->dev;
+	dprintk(1, "Stopping audio DMA\n");
+
+	/* stop dma */
+	cx_clear(AUD_INT_DMA_CTL, 0x11);
+
+	/* disable irqs */
+	cx_clear(PCI_INT_MSK, PCI_MSK_AUD_INT);
+	cx_clear(AUDIO_INT_INT_MSK, AUD_INT_OPC_ERR | AUD_INT_DN_SYNC |
+				    AUD_INT_DN_RISCI1);
+
+	if (audio_debug)
+		cx23885_sram_channel_dump(chip->dev,
+			&dev->sram_channels[AUDIO_SRAM_CHANNEL]);
+
+	return 0;
+}
+
+/*
+ * BOARD Specific: Handles audio IRQ
+ */
+int cx23885_audio_irq(struct cx23885_dev *dev, u32 status, u32 mask)
+{
+	struct cx23885_audio_dev *chip = dev->audio_dev;
+
+	if (0 == (status & mask))
+		return 0;
+
+	cx_write(AUDIO_INT_INT_STAT, status);
+
+	/* risc op code error */
+	if (status & AUD_INT_OPC_ERR) {
+		printk(KERN_WARNING "%s/1: Audio risc op code error\n",
+			dev->name);
+		cx_clear(AUD_INT_DMA_CTL, 0x11);
+		cx23885_sram_channel_dump(dev,
+			&dev->sram_channels[AUDIO_SRAM_CHANNEL]);
+	}
+	if (status & AUD_INT_DN_SYNC) {
+		dprintk(1, "Downstream sync error\n");
+		cx_write(AUD_INT_A_GPCNT_CTL, GP_COUNT_CONTROL_RESET);
+		return 1;
+	}
+	/* risc1 downstream */
+	if (status & AUD_INT_DN_RISCI1) {
+		atomic_set(&chip->count, cx_read(AUD_INT_A_GPCNT));
+		snd_pcm_period_elapsed(chip->substream);
+	}
+	/* FIXME: Any other status should deserve a special handling? */
+
+	return 1;
+}
+
+static int dsp_buffer_free(struct cx23885_audio_dev *chip)
+{
+	BUG_ON(!chip->dma_size);
+
+	dprintk(2, "Freeing buffer\n");
+	videobuf_dma_unmap(&chip->pci->dev, chip->dma_risc);
+	videobuf_dma_free(chip->dma_risc);
+	btcx_riscmem_free(chip->pci, &chip->buf->risc);
+	kfree(chip->buf);
+
+	chip->dma_risc = NULL;
+	chip->dma_size = 0;
+
+	return 0;
+}
+
+/****************************************************************************
+				ALSA PCM Interface
+ ****************************************************************************/
+
+/*
+ * Digital hardware definition
+ */
+#define DEFAULT_FIFO_SIZE	4096
+
+static struct snd_pcm_hardware snd_cx23885_digital_hw = {
+	.info = SNDRV_PCM_INFO_MMAP |
+		SNDRV_PCM_INFO_INTERLEAVED |
+		SNDRV_PCM_INFO_BLOCK_TRANSFER |
+		SNDRV_PCM_INFO_MMAP_VALID,
+	.formats = SNDRV_PCM_FMTBIT_S16_LE,
+
+	.rates =		SNDRV_PCM_RATE_48000,
+	.rate_min =		48000,
+	.rate_max =		48000,
+	.channels_min = 2,
+	.channels_max = 2,
+	/* Analog audio output will be full of clicks and pops if there
+	   are not exactly four lines in the SRAM FIFO buffer.  */
+	.period_bytes_min = DEFAULT_FIFO_SIZE/4,
+	.period_bytes_max = DEFAULT_FIFO_SIZE/4,
+	.periods_min = 1,
+	.periods_max = 1024,
+	.buffer_bytes_max = (1024*1024),
+};
+
+/*
+ * audio pcm capture open callback
+ */
+static int snd_cx23885_pcm_open(struct snd_pcm_substream *substream)
+{
+	struct cx23885_audio_dev *chip = snd_pcm_substream_chip(substream);
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	int err;
+
+	if (!chip) {
+		printk(KERN_ERR "BUG: cx23885 can't find device struct."
+				" Can't proceed with open\n");
+		return -ENODEV;
+	}
+
+	err = snd_pcm_hw_constraint_pow2(runtime, 0,
+		SNDRV_PCM_HW_PARAM_PERIODS);
+	if (err < 0)
+		goto _error;
+
+	chip->substream = substream;
+
+	runtime->hw = snd_cx23885_digital_hw;
+
+	if (chip->dev->sram_channels[AUDIO_SRAM_CHANNEL].fifo_size !=
+		DEFAULT_FIFO_SIZE) {
+		unsigned int bpl = chip->dev->
+			sram_channels[AUDIO_SRAM_CHANNEL].fifo_size / 4;
+		bpl &= ~7; /* must be multiple of 8 */
+		runtime->hw.period_bytes_min = bpl;
+		runtime->hw.period_bytes_max = bpl;
+	}
+
+	return 0;
+_error:
+	dprintk(1, "Error opening PCM!\n");
+	return err;
+}
+
+/*
+ * audio close callback
+ */
+static int snd_cx23885_close(struct snd_pcm_substream *substream)
+{
+	return 0;
+}
+
+/*
+ * hw_params callback
+ */
+static int snd_cx23885_hw_params(struct snd_pcm_substream *substream,
+			      struct snd_pcm_hw_params *hw_params)
+{
+	struct cx23885_audio_dev *chip = snd_pcm_substream_chip(substream);
+	struct videobuf_dmabuf *dma;
+
+	struct cx23885_audio_buffer *buf;
+	int ret;
+
+	if (substream->runtime->dma_area) {
+		dsp_buffer_free(chip);
+		substream->runtime->dma_area = NULL;
+	}
+
+	chip->period_size = params_period_bytes(hw_params);
+	chip->num_periods = params_periods(hw_params);
+	chip->dma_size = chip->period_size * params_periods(hw_params);
+
+	BUG_ON(!chip->dma_size);
+	BUG_ON(chip->num_periods & (chip->num_periods-1));
+
+	buf = kzalloc(sizeof(*buf), GFP_KERNEL);
+	if (NULL == buf)
+		return -ENOMEM;
+
+	buf->bpl = chip->period_size;
+
+	dma = &buf->dma;
+	videobuf_dma_init(dma);
+	ret = videobuf_dma_init_kernel(dma, PCI_DMA_FROMDEVICE,
+			(PAGE_ALIGN(chip->dma_size) >> PAGE_SHIFT));
+	if (ret < 0)
+		goto error;
+
+	ret = videobuf_dma_map(&chip->pci->dev, dma);
+	if (ret < 0)
+		goto error;
+
+	ret = cx23885_risc_databuffer(chip->pci, &buf->risc, dma->sglist,
+				   chip->period_size, chip->num_periods, 1);
+	if (ret < 0)
+		goto error;
+
+	/* Loop back to start of program */
+	buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP|RISC_IRQ1|RISC_CNT_INC);
+	buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+	buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */
+
+	chip->buf = buf;
+	chip->dma_risc = dma;
+
+	substream->runtime->dma_area = chip->dma_risc->vaddr;
+	substream->runtime->dma_bytes = chip->dma_size;
+	substream->runtime->dma_addr = 0;
+
+	return 0;
+
+error:
+	kfree(buf);
+	return ret;
+}
+
+/*
+ * hw free callback
+ */
+static int snd_cx23885_hw_free(struct snd_pcm_substream *substream)
+{
+
+	struct cx23885_audio_dev *chip = snd_pcm_substream_chip(substream);
+
+	if (substream->runtime->dma_area) {
+		dsp_buffer_free(chip);
+		substream->runtime->dma_area = NULL;
+	}
+
+	return 0;
+}
+
+/*
+ * prepare callback
+ */
+static int snd_cx23885_prepare(struct snd_pcm_substream *substream)
+{
+	return 0;
+}
+
+/*
+ * trigger callback
+ */
+static int snd_cx23885_card_trigger(struct snd_pcm_substream *substream,
+	int cmd)
+{
+	struct cx23885_audio_dev *chip = snd_pcm_substream_chip(substream);
+	int err;
+
+	/* Local interrupts are already disabled by ALSA */
+	spin_lock(&chip->lock);
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+		err = cx23885_start_audio_dma(chip);
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+		err = cx23885_stop_audio_dma(chip);
+		break;
+	default:
+		err = -EINVAL;
+		break;
+	}
+
+	spin_unlock(&chip->lock);
+
+	return err;
+}
+
+/*
+ * pointer callback
+ */
+static snd_pcm_uframes_t snd_cx23885_pointer(
+	struct snd_pcm_substream *substream)
+{
+	struct cx23885_audio_dev *chip = snd_pcm_substream_chip(substream);
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	u16 count;
+
+	count = atomic_read(&chip->count);
+
+	return runtime->period_size * (count & (runtime->periods-1));
+}
+
+/*
+ * page callback (needed for mmap)
+ */
+static struct page *snd_cx23885_page(struct snd_pcm_substream *substream,
+				unsigned long offset)
+{
+	void *pageptr = substream->runtime->dma_area + offset;
+	return vmalloc_to_page(pageptr);
+}
+
+/*
+ * operators
+ */
+static struct snd_pcm_ops snd_cx23885_pcm_ops = {
+	.open = snd_cx23885_pcm_open,
+	.close = snd_cx23885_close,
+	.ioctl = snd_pcm_lib_ioctl,
+	.hw_params = snd_cx23885_hw_params,
+	.hw_free = snd_cx23885_hw_free,
+	.prepare = snd_cx23885_prepare,
+	.trigger = snd_cx23885_card_trigger,
+	.pointer = snd_cx23885_pointer,
+	.page = snd_cx23885_page,
+};
+
+/*
+ * create a PCM device
+ */
+static int snd_cx23885_pcm(struct cx23885_audio_dev *chip, int device,
+	char *name)
+{
+	int err;
+	struct snd_pcm *pcm;
+
+	err = snd_pcm_new(chip->card, name, device, 0, 1, &pcm);
+	if (err < 0)
+		return err;
+	pcm->private_data = chip;
+	strcpy(pcm->name, name);
+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cx23885_pcm_ops);
+
+	return 0;
+}
+
+/****************************************************************************
+			Basic Flow for Sound Devices
+ ****************************************************************************/
+
+/*
+ * Alsa Constructor - Component probe
+ */
+
+struct cx23885_audio_dev *cx23885_audio_register(struct cx23885_dev *dev)
+{
+	struct snd_card *card;
+	struct cx23885_audio_dev *chip;
+	int err;
+
+	if (disable_analog_audio)
+		return NULL;
+
+	if (dev->sram_channels[AUDIO_SRAM_CHANNEL].cmds_start == 0) {
+		printk(KERN_WARNING "%s(): Missing SRAM channel configuration "
+			"for analog TV Audio\n", __func__);
+		return NULL;
+	}
+
+	err = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
+			THIS_MODULE, sizeof(struct cx23885_audio_dev), &card);
+	if (err < 0)
+		goto error;
+
+	chip = (struct cx23885_audio_dev *) card->private_data;
+	chip->dev = dev;
+	chip->pci = dev->pci;
+	chip->card = card;
+	spin_lock_init(&chip->lock);
+
+	snd_card_set_dev(card, &dev->pci->dev);
+
+	err = snd_cx23885_pcm(chip, 0, "CX23885 Digital");
+	if (err < 0)
+		goto error;
+
+	strcpy(card->driver, "CX23885");
+	sprintf(card->shortname, "Conexant CX23885");
+	sprintf(card->longname, "%s at %s", card->shortname, dev->name);
+
+	err = snd_card_register(card);
+	if (err < 0)
+		goto error;
+
+	dprintk(0, "registered ALSA audio device\n");
+
+	return chip;
+
+error:
+	snd_card_free(card);
+	printk(KERN_ERR "%s(): Failed to register analog "
+			"audio adapter\n", __func__);
+
+	return NULL;
+}
+
+/*
+ * ALSA destructor
+ */
+void cx23885_audio_unregister(struct cx23885_dev *dev)
+{
+	struct cx23885_audio_dev *chip = dev->audio_dev;
+
+	snd_card_free(chip->card);
+}
diff --git a/drivers/media/pci/cx23885/cx23885-av.c b/drivers/media/pci/cx23885/cx23885-av.c
new file mode 100644
index 0000000..134ebdd
--- /dev/null
+++ b/drivers/media/pci/cx23885/cx23885-av.c
@@ -0,0 +1,35 @@
+/*
+ *  Driver for the Conexant CX23885/7/8 PCIe bridge
+ *
+ *  AV device support routines - non-input, non-vl42_subdev routines
+ *
+ *  Copyright (C) 2010  Andy Walls <awalls@md.metrocast.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 program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You 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 "cx23885.h"
+
+void cx23885_av_work_handler(struct work_struct *work)
+{
+	struct cx23885_dev *dev =
+			   container_of(work, struct cx23885_dev, cx25840_work);
+	bool handled;
+
+	v4l2_subdev_call(dev->sd_cx25840, core, interrupt_service_routine,
+			 PCI_MSK_AV_CORE, &handled);
+	cx23885_irq_enable(dev, PCI_MSK_AV_CORE);
+}
diff --git a/drivers/media/pci/cx23885/cx23885-av.h b/drivers/media/pci/cx23885/cx23885-av.h
new file mode 100644
index 0000000..d2915c3
--- /dev/null
+++ b/drivers/media/pci/cx23885/cx23885-av.h
@@ -0,0 +1,27 @@
+/*
+ *  Driver for the Conexant CX23885/7/8 PCIe bridge
+ *
+ *  AV device support routines - non-input, non-vl42_subdev routines
+ *
+ *  Copyright (C) 2010  Andy Walls <awalls@md.metrocast.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 program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You 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 _CX23885_AV_H_
+#define _CX23885_AV_H_
+void cx23885_av_work_handler(struct work_struct *work);
+#endif
diff --git a/drivers/media/pci/cx23885/cx23885-cards.c b/drivers/media/pci/cx23885/cx23885-cards.c
new file mode 100644
index 0000000..39a4a4b
--- /dev/null
+++ b/drivers/media/pci/cx23885/cx23885-cards.c
@@ -0,0 +1,1694 @@
+/*
+ *  Driver for the Conexant CX23885 PCIe bridge
+ *
+ *  Copyright (c) 2006 Steven Toth <stoth@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/init.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <media/cx25840.h>
+#include <linux/firmware.h>
+#include <misc/altera.h>
+
+#include "cx23885.h"
+#include "tuner-xc2028.h"
+#include "netup-eeprom.h"
+#include "netup-init.h"
+#include "altera-ci.h"
+#include "xc4000.h"
+#include "xc5000.h"
+#include "cx23888-ir.h"
+
+static unsigned int netup_card_rev = 4;
+module_param(netup_card_rev, int, 0644);
+MODULE_PARM_DESC(netup_card_rev,
+		"NetUP Dual DVB-T/C CI card revision");
+static unsigned int enable_885_ir;
+module_param(enable_885_ir, int, 0644);
+MODULE_PARM_DESC(enable_885_ir,
+		 "Enable integrated IR controller for supported\n"
+		 "\t\t    CX2388[57] boards that are wired for it:\n"
+		 "\t\t\tHVR-1250 (reported safe)\n"
+		 "\t\t\tTerraTec Cinergy T PCIe Dual (not well tested, appears to be safe)\n"
+		 "\t\t\tTeVii S470 (reported unsafe)\n"
+		 "\t\t    This can cause an interrupt storm with some cards.\n"
+		 "\t\t    Default: 0 [Disabled]");
+
+/* ------------------------------------------------------------------ */
+/* board config info                                                  */
+
+struct cx23885_board cx23885_boards[] = {
+	[CX23885_BOARD_UNKNOWN] = {
+		.name		= "UNKNOWN/GENERIC",
+		/* Ensure safe default for unknown boards */
+		.clk_freq       = 0,
+		.input          = {{
+			.type   = CX23885_VMUX_COMPOSITE1,
+			.vmux   = 0,
+		}, {
+			.type   = CX23885_VMUX_COMPOSITE2,
+			.vmux   = 1,
+		}, {
+			.type   = CX23885_VMUX_COMPOSITE3,
+			.vmux   = 2,
+		}, {
+			.type   = CX23885_VMUX_COMPOSITE4,
+			.vmux   = 3,
+		} },
+	},
+	[CX23885_BOARD_HAUPPAUGE_HVR1800lp] = {
+		.name		= "Hauppauge WinTV-HVR1800lp",
+		.portc		= CX23885_MPEG_DVB,
+		.input          = {{
+			.type   = CX23885_VMUX_TELEVISION,
+			.vmux   = 0,
+			.gpio0  = 0xff00,
+		}, {
+			.type   = CX23885_VMUX_DEBUG,
+			.vmux   = 0,
+			.gpio0  = 0xff01,
+		}, {
+			.type   = CX23885_VMUX_COMPOSITE1,
+			.vmux   = 1,
+			.gpio0  = 0xff02,
+		}, {
+			.type   = CX23885_VMUX_SVIDEO,
+			.vmux   = 2,
+			.gpio0  = 0xff02,
+		} },
+	},
+	[CX23885_BOARD_HAUPPAUGE_HVR1800] = {
+		.name		= "Hauppauge WinTV-HVR1800",
+		.porta		= CX23885_ANALOG_VIDEO,
+		.portb		= CX23885_MPEG_ENCODER,
+		.portc		= CX23885_MPEG_DVB,
+		.tuner_type	= TUNER_PHILIPS_TDA8290,
+		.tuner_addr	= 0x42, /* 0x84 >> 1 */
+		.tuner_bus	= 1,
+		.input          = {{
+			.type   = CX23885_VMUX_TELEVISION,
+			.vmux   =	CX25840_VIN7_CH3 |
+					CX25840_VIN5_CH2 |
+					CX25840_VIN2_CH1,
+			.amux   = CX25840_AUDIO8,
+			.gpio0  = 0,
+		}, {
+			.type   = CX23885_VMUX_COMPOSITE1,
+			.vmux   =	CX25840_VIN7_CH3 |
+					CX25840_VIN4_CH2 |
+					CX25840_VIN6_CH1,
+			.amux   = CX25840_AUDIO7,
+			.gpio0  = 0,
+		}, {
+			.type   = CX23885_VMUX_SVIDEO,
+			.vmux   =	CX25840_VIN7_CH3 |
+					CX25840_VIN4_CH2 |
+					CX25840_VIN8_CH1 |
+					CX25840_SVIDEO_ON,
+			.amux   = CX25840_AUDIO7,
+			.gpio0  = 0,
+		} },
+	},
+	[CX23885_BOARD_HAUPPAUGE_HVR1250] = {
+		.name		= "Hauppauge WinTV-HVR1250",
+		.porta		= CX23885_ANALOG_VIDEO,
+		.portc		= CX23885_MPEG_DVB,
+#ifdef MT2131_NO_ANALOG_SUPPORT_YET
+		.tuner_type	= TUNER_PHILIPS_TDA8290,
+		.tuner_addr	= 0x42, /* 0x84 >> 1 */
+		.tuner_bus	= 1,
+#endif
+		.force_bff	= 1,
+		.input          = {{
+#ifdef MT2131_NO_ANALOG_SUPPORT_YET
+			.type   = CX23885_VMUX_TELEVISION,
+			.vmux   =	CX25840_VIN7_CH3 |
+					CX25840_VIN5_CH2 |
+					CX25840_VIN2_CH1,
+			.amux   = CX25840_AUDIO8,
+			.gpio0  = 0xff00,
+		}, {
+#endif
+			.type   = CX23885_VMUX_COMPOSITE1,
+			.vmux   =	CX25840_VIN7_CH3 |
+					CX25840_VIN4_CH2 |
+					CX25840_VIN6_CH1,
+			.amux   = CX25840_AUDIO7,
+			.gpio0  = 0xff02,
+		}, {
+			.type   = CX23885_VMUX_SVIDEO,
+			.vmux   =	CX25840_VIN7_CH3 |
+					CX25840_VIN4_CH2 |
+					CX25840_VIN8_CH1 |
+					CX25840_SVIDEO_ON,
+			.amux   = CX25840_AUDIO7,
+			.gpio0  = 0xff02,
+		} },
+	},
+	[CX23885_BOARD_DVICO_FUSIONHDTV_5_EXP] = {
+		.name		= "DViCO FusionHDTV5 Express",
+		.portb		= CX23885_MPEG_DVB,
+	},
+	[CX23885_BOARD_HAUPPAUGE_HVR1500Q] = {
+		.name		= "Hauppauge WinTV-HVR1500Q",
+		.portc		= CX23885_MPEG_DVB,
+	},
+	[CX23885_BOARD_HAUPPAUGE_HVR1500] = {
+		.name		= "Hauppauge WinTV-HVR1500",
+		.porta		= CX23885_ANALOG_VIDEO,
+		.portc		= CX23885_MPEG_DVB,
+		.tuner_type	= TUNER_XC2028,
+		.tuner_addr	= 0x61, /* 0xc2 >> 1 */
+		.input          = {{
+			.type   = CX23885_VMUX_TELEVISION,
+			.vmux   =	CX25840_VIN7_CH3 |
+					CX25840_VIN5_CH2 |
+					CX25840_VIN2_CH1,
+			.gpio0  = 0,
+		}, {
+			.type   = CX23885_VMUX_COMPOSITE1,
+			.vmux   =	CX25840_VIN7_CH3 |
+					CX25840_VIN4_CH2 |
+					CX25840_VIN6_CH1,
+			.gpio0  = 0,
+		}, {
+			.type   = CX23885_VMUX_SVIDEO,
+			.vmux   =	CX25840_VIN7_CH3 |
+					CX25840_VIN4_CH2 |
+					CX25840_VIN8_CH1 |
+					CX25840_SVIDEO_ON,
+			.gpio0  = 0,
+		} },
+	},
+	[CX23885_BOARD_HAUPPAUGE_HVR1200] = {
+		.name		= "Hauppauge WinTV-HVR1200",
+		.portc		= CX23885_MPEG_DVB,
+	},
+	[CX23885_BOARD_HAUPPAUGE_HVR1700] = {
+		.name		= "Hauppauge WinTV-HVR1700",
+		.portc		= CX23885_MPEG_DVB,
+	},
+	[CX23885_BOARD_HAUPPAUGE_HVR1400] = {
+		.name		= "Hauppauge WinTV-HVR1400",
+		.portc		= CX23885_MPEG_DVB,
+	},
+	[CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP] = {
+		.name		= "DViCO FusionHDTV7 Dual Express",
+		.portb		= CX23885_MPEG_DVB,
+		.portc		= CX23885_MPEG_DVB,
+	},
+	[CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP] = {
+		.name		= "DViCO FusionHDTV DVB-T Dual Express",
+		.portb		= CX23885_MPEG_DVB,
+		.portc		= CX23885_MPEG_DVB,
+	},
+	[CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H] = {
+		.name		= "Leadtek Winfast PxDVR3200 H",
+		.portc		= CX23885_MPEG_DVB,
+	},
+	[CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H_XC4000] = {
+		.name		= "Leadtek Winfast PxDVR3200 H XC4000",
+		.porta		= CX23885_ANALOG_VIDEO,
+		.portc		= CX23885_MPEG_DVB,
+		.tuner_type	= TUNER_XC4000,
+		.tuner_addr	= 0x61,
+		.radio_type	= UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.input		= {{
+			.type	= CX23885_VMUX_TELEVISION,
+			.vmux	= CX25840_VIN2_CH1 |
+				  CX25840_VIN5_CH2 |
+				  CX25840_NONE0_CH3,
+		}, {
+			.type	= CX23885_VMUX_COMPOSITE1,
+			.vmux	= CX25840_COMPOSITE1,
+		}, {
+			.type	= CX23885_VMUX_SVIDEO,
+			.vmux	= CX25840_SVIDEO_LUMA3 |
+				  CX25840_SVIDEO_CHROMA4,
+		}, {
+			.type	= CX23885_VMUX_COMPONENT,
+			.vmux	= CX25840_VIN7_CH1 |
+				  CX25840_VIN6_CH2 |
+				  CX25840_VIN8_CH3 |
+				  CX25840_COMPONENT_ON,
+		} },
+	},
+	[CX23885_BOARD_COMPRO_VIDEOMATE_E650F] = {
+		.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] = {
+		.ci_type	= 1,
+		.name		= "NetUP Dual DVB-S2 CI",
+		.portb		= CX23885_MPEG_DVB,
+		.portc		= CX23885_MPEG_DVB,
+	},
+	[CX23885_BOARD_HAUPPAUGE_HVR1270] = {
+		.name		= "Hauppauge WinTV-HVR1270",
+		.portc		= CX23885_MPEG_DVB,
+	},
+	[CX23885_BOARD_HAUPPAUGE_HVR1275] = {
+		.name		= "Hauppauge WinTV-HVR1275",
+		.portc		= CX23885_MPEG_DVB,
+	},
+	[CX23885_BOARD_HAUPPAUGE_HVR1255] = {
+		.name		= "Hauppauge WinTV-HVR1255",
+		.porta		= CX23885_ANALOG_VIDEO,
+		.portc		= CX23885_MPEG_DVB,
+		.tuner_type	= TUNER_ABSENT,
+		.tuner_addr	= 0x42, /* 0x84 >> 1 */
+		.force_bff	= 1,
+		.input          = {{
+			.type   = CX23885_VMUX_TELEVISION,
+			.vmux   =	CX25840_VIN7_CH3 |
+					CX25840_VIN5_CH2 |
+					CX25840_VIN2_CH1 |
+					CX25840_DIF_ON,
+			.amux   = CX25840_AUDIO8,
+		}, {
+			.type   = CX23885_VMUX_COMPOSITE1,
+			.vmux   =	CX25840_VIN7_CH3 |
+					CX25840_VIN4_CH2 |
+					CX25840_VIN6_CH1,
+			.amux   = CX25840_AUDIO7,
+		}, {
+			.type   = CX23885_VMUX_SVIDEO,
+			.vmux   =	CX25840_VIN7_CH3 |
+					CX25840_VIN4_CH2 |
+					CX25840_VIN8_CH1 |
+					CX25840_SVIDEO_ON,
+			.amux   = CX25840_AUDIO7,
+		} },
+	},
+	[CX23885_BOARD_HAUPPAUGE_HVR1255_22111] = {
+		.name		= "Hauppauge WinTV-HVR1255",
+		.porta		= CX23885_ANALOG_VIDEO,
+		.portc		= CX23885_MPEG_DVB,
+		.tuner_type	= TUNER_ABSENT,
+		.tuner_addr	= 0x42, /* 0x84 >> 1 */
+		.force_bff	= 1,
+		.input          = {{
+			.type   = CX23885_VMUX_TELEVISION,
+			.vmux   =	CX25840_VIN7_CH3 |
+					CX25840_VIN5_CH2 |
+					CX25840_VIN2_CH1 |
+					CX25840_DIF_ON,
+			.amux   = CX25840_AUDIO8,
+		}, {
+			.type   = CX23885_VMUX_SVIDEO,
+			.vmux   =	CX25840_VIN7_CH3 |
+					CX25840_VIN4_CH2 |
+					CX25840_VIN8_CH1 |
+					CX25840_SVIDEO_ON,
+			.amux   = CX25840_AUDIO7,
+		} },
+	},
+	[CX23885_BOARD_HAUPPAUGE_HVR1210] = {
+		.name		= "Hauppauge WinTV-HVR1210",
+		.portc		= CX23885_MPEG_DVB,
+	},
+	[CX23885_BOARD_MYGICA_X8506] = {
+		.name		= "Mygica X8506 DMB-TH",
+		.tuner_type = TUNER_XC5000,
+		.tuner_addr = 0x61,
+		.tuner_bus	= 1,
+		.porta		= CX23885_ANALOG_VIDEO,
+		.portb		= CX23885_MPEG_DVB,
+		.input		= {
+			{
+				.type   = CX23885_VMUX_TELEVISION,
+				.vmux   = CX25840_COMPOSITE2,
+			},
+			{
+				.type   = CX23885_VMUX_COMPOSITE1,
+				.vmux   = CX25840_COMPOSITE8,
+			},
+			{
+				.type   = CX23885_VMUX_SVIDEO,
+				.vmux   = CX25840_SVIDEO_LUMA3 |
+						CX25840_SVIDEO_CHROMA4,
+			},
+			{
+				.type   = CX23885_VMUX_COMPONENT,
+				.vmux   = CX25840_COMPONENT_ON |
+					CX25840_VIN1_CH1 |
+					CX25840_VIN6_CH2 |
+					CX25840_VIN7_CH3,
+			},
+		},
+	},
+	[CX23885_BOARD_MAGICPRO_PROHDTVE2] = {
+		.name		= "Magic-Pro ProHDTV Extreme 2",
+		.tuner_type = TUNER_XC5000,
+		.tuner_addr = 0x61,
+		.tuner_bus	= 1,
+		.porta		= CX23885_ANALOG_VIDEO,
+		.portb		= CX23885_MPEG_DVB,
+		.input		= {
+			{
+				.type   = CX23885_VMUX_TELEVISION,
+				.vmux   = CX25840_COMPOSITE2,
+			},
+			{
+				.type   = CX23885_VMUX_COMPOSITE1,
+				.vmux   = CX25840_COMPOSITE8,
+			},
+			{
+				.type   = CX23885_VMUX_SVIDEO,
+				.vmux   = CX25840_SVIDEO_LUMA3 |
+						CX25840_SVIDEO_CHROMA4,
+			},
+			{
+				.type   = CX23885_VMUX_COMPONENT,
+				.vmux   = CX25840_COMPONENT_ON |
+					CX25840_VIN1_CH1 |
+					CX25840_VIN6_CH2 |
+					CX25840_VIN7_CH3,
+			},
+		},
+	},
+	[CX23885_BOARD_HAUPPAUGE_HVR1850] = {
+		.name		= "Hauppauge WinTV-HVR1850",
+		.porta		= CX23885_ANALOG_VIDEO,
+		.portb		= CX23885_MPEG_ENCODER,
+		.portc		= CX23885_MPEG_DVB,
+		.tuner_type	= TUNER_ABSENT,
+		.tuner_addr	= 0x42, /* 0x84 >> 1 */
+		.force_bff	= 1,
+		.input          = {{
+			.type   = CX23885_VMUX_TELEVISION,
+			.vmux   =	CX25840_VIN7_CH3 |
+					CX25840_VIN5_CH2 |
+					CX25840_VIN2_CH1 |
+					CX25840_DIF_ON,
+			.amux   = CX25840_AUDIO8,
+		}, {
+			.type   = CX23885_VMUX_COMPOSITE1,
+			.vmux   =	CX25840_VIN7_CH3 |
+					CX25840_VIN4_CH2 |
+					CX25840_VIN6_CH1,
+			.amux   = CX25840_AUDIO7,
+		}, {
+			.type   = CX23885_VMUX_SVIDEO,
+			.vmux   =	CX25840_VIN7_CH3 |
+					CX25840_VIN4_CH2 |
+					CX25840_VIN8_CH1 |
+					CX25840_SVIDEO_ON,
+			.amux   = CX25840_AUDIO7,
+		} },
+	},
+	[CX23885_BOARD_COMPRO_VIDEOMATE_E800] = {
+		.name		= "Compro VideoMate E800",
+		.portc		= CX23885_MPEG_DVB,
+	},
+	[CX23885_BOARD_HAUPPAUGE_HVR1290] = {
+		.name		= "Hauppauge WinTV-HVR1290",
+		.portc		= CX23885_MPEG_DVB,
+	},
+	[CX23885_BOARD_MYGICA_X8558PRO] = {
+		.name		= "Mygica X8558 PRO DMB-TH",
+		.portb		= CX23885_MPEG_DVB,
+		.portc		= CX23885_MPEG_DVB,
+	},
+	[CX23885_BOARD_LEADTEK_WINFAST_PXTV1200] = {
+		.name           = "LEADTEK WinFast PxTV1200",
+		.porta          = CX23885_ANALOG_VIDEO,
+		.tuner_type     = TUNER_XC2028,
+		.tuner_addr     = 0x61,
+		.tuner_bus	= 1,
+		.input          = {{
+			.type   = CX23885_VMUX_TELEVISION,
+			.vmux   = CX25840_VIN2_CH1 |
+				  CX25840_VIN5_CH2 |
+				  CX25840_NONE0_CH3,
+		}, {
+			.type   = CX23885_VMUX_COMPOSITE1,
+			.vmux   = CX25840_COMPOSITE1,
+		}, {
+			.type   = CX23885_VMUX_SVIDEO,
+			.vmux   = CX25840_SVIDEO_LUMA3 |
+				  CX25840_SVIDEO_CHROMA4,
+		}, {
+			.type   = CX23885_VMUX_COMPONENT,
+			.vmux   = CX25840_VIN7_CH1 |
+				  CX25840_VIN6_CH2 |
+				  CX25840_VIN8_CH3 |
+				  CX25840_COMPONENT_ON,
+		} },
+	},
+	[CX23885_BOARD_GOTVIEW_X5_3D_HYBRID] = {
+		.name		= "GoTView X5 3D Hybrid",
+		.tuner_type	= TUNER_XC5000,
+		.tuner_addr	= 0x64,
+		.tuner_bus	= 1,
+		.porta		= CX23885_ANALOG_VIDEO,
+		.portb		= CX23885_MPEG_DVB,
+		.input          = {{
+			.type   = CX23885_VMUX_TELEVISION,
+			.vmux   = CX25840_VIN2_CH1 |
+				  CX25840_VIN5_CH2,
+			.gpio0	= 0x02,
+		}, {
+			.type   = CX23885_VMUX_COMPOSITE1,
+			.vmux   = CX23885_VMUX_COMPOSITE1,
+		}, {
+			.type   = CX23885_VMUX_SVIDEO,
+			.vmux   = CX25840_SVIDEO_LUMA3 |
+				  CX25840_SVIDEO_CHROMA4,
+		} },
+	},
+	[CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF] = {
+		.ci_type	= 2,
+		.name		= "NetUP Dual DVB-T/C-CI RF",
+		.porta		= CX23885_ANALOG_VIDEO,
+		.portb		= CX23885_MPEG_DVB,
+		.portc		= CX23885_MPEG_DVB,
+		.num_fds_portb	= 2,
+		.num_fds_portc	= 2,
+		.tuner_type	= TUNER_XC5000,
+		.tuner_addr	= 0x64,
+		.input          = { {
+				.type   = CX23885_VMUX_TELEVISION,
+				.vmux   = CX25840_COMPOSITE1,
+		} },
+	},
+	[CX23885_BOARD_MPX885] = {
+		.name		= "MPX-885",
+		.porta		= CX23885_ANALOG_VIDEO,
+		.input          = {{
+			.type   = CX23885_VMUX_COMPOSITE1,
+			.vmux   = CX25840_COMPOSITE1,
+			.amux   = CX25840_AUDIO6,
+			.gpio0  = 0,
+		}, {
+			.type   = CX23885_VMUX_COMPOSITE2,
+			.vmux   = CX25840_COMPOSITE2,
+			.amux   = CX25840_AUDIO6,
+			.gpio0  = 0,
+		}, {
+			.type   = CX23885_VMUX_COMPOSITE3,
+			.vmux   = CX25840_COMPOSITE3,
+			.amux   = CX25840_AUDIO7,
+			.gpio0  = 0,
+		}, {
+			.type   = CX23885_VMUX_COMPOSITE4,
+			.vmux   = CX25840_COMPOSITE4,
+			.amux   = CX25840_AUDIO7,
+			.gpio0  = 0,
+		} },
+	},
+	[CX23885_BOARD_MYGICA_X8507] = {
+		.name		= "Mygica X8507",
+		.tuner_type = TUNER_XC5000,
+		.tuner_addr = 0x61,
+		.tuner_bus	= 1,
+		.porta		= CX23885_ANALOG_VIDEO,
+		.input		= {
+			{
+				.type   = CX23885_VMUX_TELEVISION,
+				.vmux   = CX25840_COMPOSITE2,
+				.amux   = CX25840_AUDIO8,
+			},
+			{
+				.type   = CX23885_VMUX_COMPOSITE1,
+				.vmux   = CX25840_COMPOSITE8,
+			},
+			{
+				.type   = CX23885_VMUX_SVIDEO,
+				.vmux   = CX25840_SVIDEO_LUMA3 |
+						CX25840_SVIDEO_CHROMA4,
+			},
+			{
+				.type   = CX23885_VMUX_COMPONENT,
+				.vmux   = CX25840_COMPONENT_ON |
+					CX25840_VIN1_CH1 |
+					CX25840_VIN6_CH2 |
+					CX25840_VIN7_CH3,
+			},
+		},
+	},
+	[CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL] = {
+		.name		= "TerraTec Cinergy T PCIe Dual",
+		.portb		= CX23885_MPEG_DVB,
+		.portc		= CX23885_MPEG_DVB,
+	},
+	[CX23885_BOARD_TEVII_S471] = {
+		.name		= "TeVii S471",
+		.portb		= CX23885_MPEG_DVB,
+	},
+	[CX23885_BOARD_PROF_8000] = {
+		.name		= "Prof Revolution DVB-S2 8000",
+		.portb		= CX23885_MPEG_DVB,
+	}
+};
+const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards);
+
+/* ------------------------------------------------------------------ */
+/* PCI subsystem IDs                                                  */
+
+struct cx23885_subid cx23885_subids[] = {
+	{
+		.subvendor = 0x0070,
+		.subdevice = 0x3400,
+		.card      = CX23885_BOARD_UNKNOWN,
+	}, {
+		.subvendor = 0x0070,
+		.subdevice = 0x7600,
+		.card      = CX23885_BOARD_HAUPPAUGE_HVR1800lp,
+	}, {
+		.subvendor = 0x0070,
+		.subdevice = 0x7800,
+		.card      = CX23885_BOARD_HAUPPAUGE_HVR1800,
+	}, {
+		.subvendor = 0x0070,
+		.subdevice = 0x7801,
+		.card      = CX23885_BOARD_HAUPPAUGE_HVR1800,
+	}, {
+		.subvendor = 0x0070,
+		.subdevice = 0x7809,
+		.card      = CX23885_BOARD_HAUPPAUGE_HVR1800,
+	}, {
+		.subvendor = 0x0070,
+		.subdevice = 0x7911,
+		.card      = CX23885_BOARD_HAUPPAUGE_HVR1250,
+	}, {
+		.subvendor = 0x18ac,
+		.subdevice = 0xd500,
+		.card      = CX23885_BOARD_DVICO_FUSIONHDTV_5_EXP,
+	}, {
+		.subvendor = 0x0070,
+		.subdevice = 0x7790,
+		.card      = CX23885_BOARD_HAUPPAUGE_HVR1500Q,
+	}, {
+		.subvendor = 0x0070,
+		.subdevice = 0x7797,
+		.card      = CX23885_BOARD_HAUPPAUGE_HVR1500Q,
+	}, {
+		.subvendor = 0x0070,
+		.subdevice = 0x7710,
+		.card      = CX23885_BOARD_HAUPPAUGE_HVR1500,
+	}, {
+		.subvendor = 0x0070,
+		.subdevice = 0x7717,
+		.card      = CX23885_BOARD_HAUPPAUGE_HVR1500,
+	}, {
+		.subvendor = 0x0070,
+		.subdevice = 0x71d1,
+		.card      = CX23885_BOARD_HAUPPAUGE_HVR1200,
+	}, {
+		.subvendor = 0x0070,
+		.subdevice = 0x71d3,
+		.card      = CX23885_BOARD_HAUPPAUGE_HVR1200,
+	}, {
+		.subvendor = 0x0070,
+		.subdevice = 0x8101,
+		.card      = CX23885_BOARD_HAUPPAUGE_HVR1700,
+	}, {
+		.subvendor = 0x0070,
+		.subdevice = 0x8010,
+		.card      = CX23885_BOARD_HAUPPAUGE_HVR1400,
+	}, {
+		.subvendor = 0x18ac,
+		.subdevice = 0xd618,
+		.card      = CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP,
+	}, {
+		.subvendor = 0x18ac,
+		.subdevice = 0xdb78,
+		.card      = CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP,
+	}, {
+		.subvendor = 0x107d,
+		.subdevice = 0x6681,
+		.card      = CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H,
+	}, {
+		.subvendor = 0x107d,
+		.subdevice = 0x6f39,
+		.card	   = CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H_XC4000,
+	}, {
+		.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,
+	}, {
+		.subvendor = 0x0070,
+		.subdevice = 0x2211,
+		.card      = CX23885_BOARD_HAUPPAUGE_HVR1270,
+	}, {
+		.subvendor = 0x0070,
+		.subdevice = 0x2215,
+		.card      = CX23885_BOARD_HAUPPAUGE_HVR1275,
+	}, {
+		.subvendor = 0x0070,
+		.subdevice = 0x221d,
+		.card      = CX23885_BOARD_HAUPPAUGE_HVR1275,
+	}, {
+		.subvendor = 0x0070,
+		.subdevice = 0x2251,
+		.card      = CX23885_BOARD_HAUPPAUGE_HVR1255,
+	}, {
+		.subvendor = 0x0070,
+		.subdevice = 0x2259,
+		.card      = CX23885_BOARD_HAUPPAUGE_HVR1255_22111,
+	}, {
+		.subvendor = 0x0070,
+		.subdevice = 0x2291,
+		.card      = CX23885_BOARD_HAUPPAUGE_HVR1210,
+	}, {
+		.subvendor = 0x0070,
+		.subdevice = 0x2295,
+		.card      = CX23885_BOARD_HAUPPAUGE_HVR1210,
+	}, {
+		.subvendor = 0x0070,
+		.subdevice = 0x2299,
+		.card      = CX23885_BOARD_HAUPPAUGE_HVR1210,
+	}, {
+		.subvendor = 0x0070,
+		.subdevice = 0x229d,
+		.card      = CX23885_BOARD_HAUPPAUGE_HVR1210, /* HVR1215 */
+	}, {
+		.subvendor = 0x0070,
+		.subdevice = 0x22f0,
+		.card      = CX23885_BOARD_HAUPPAUGE_HVR1210,
+	}, {
+		.subvendor = 0x0070,
+		.subdevice = 0x22f1,
+		.card      = CX23885_BOARD_HAUPPAUGE_HVR1255,
+	}, {
+		.subvendor = 0x0070,
+		.subdevice = 0x22f2,
+		.card      = CX23885_BOARD_HAUPPAUGE_HVR1275,
+	}, {
+		.subvendor = 0x0070,
+		.subdevice = 0x22f3,
+		.card      = CX23885_BOARD_HAUPPAUGE_HVR1210, /* HVR1215 */
+	}, {
+		.subvendor = 0x0070,
+		.subdevice = 0x22f4,
+		.card      = CX23885_BOARD_HAUPPAUGE_HVR1210,
+	}, {
+		.subvendor = 0x0070,
+		.subdevice = 0x22f5,
+		.card      = CX23885_BOARD_HAUPPAUGE_HVR1210, /* HVR1215 */
+	}, {
+		.subvendor = 0x14f1,
+		.subdevice = 0x8651,
+		.card      = CX23885_BOARD_MYGICA_X8506,
+	}, {
+		.subvendor = 0x14f1,
+		.subdevice = 0x8657,
+		.card      = CX23885_BOARD_MAGICPRO_PROHDTVE2,
+	}, {
+		.subvendor = 0x0070,
+		.subdevice = 0x8541,
+		.card      = CX23885_BOARD_HAUPPAUGE_HVR1850,
+	}, {
+		.subvendor = 0x1858,
+		.subdevice = 0xe800,
+		.card      = CX23885_BOARD_COMPRO_VIDEOMATE_E800,
+	}, {
+		.subvendor = 0x0070,
+		.subdevice = 0x8551,
+		.card      = CX23885_BOARD_HAUPPAUGE_HVR1290,
+	}, {
+		.subvendor = 0x14f1,
+		.subdevice = 0x8578,
+		.card      = CX23885_BOARD_MYGICA_X8558PRO,
+	}, {
+		.subvendor = 0x107d,
+		.subdevice = 0x6f22,
+		.card      = CX23885_BOARD_LEADTEK_WINFAST_PXTV1200,
+	}, {
+		.subvendor = 0x5654,
+		.subdevice = 0x2390,
+		.card      = CX23885_BOARD_GOTVIEW_X5_3D_HYBRID,
+	}, {
+		.subvendor = 0x1b55,
+		.subdevice = 0xe2e4,
+		.card      = CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF,
+	}, {
+		.subvendor = 0x14f1,
+		.subdevice = 0x8502,
+		.card      = CX23885_BOARD_MYGICA_X8507,
+	}, {
+		.subvendor = 0x153b,
+		.subdevice = 0x117e,
+		.card      = CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL,
+	}, {
+		.subvendor = 0xd471,
+		.subdevice = 0x9022,
+		.card      = CX23885_BOARD_TEVII_S471,
+	}, {
+		.subvendor = 0x8000,
+		.subdevice = 0x3034,
+		.card      = CX23885_BOARD_PROF_8000,
+	},
+};
+const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids);
+
+void cx23885_card_list(struct cx23885_dev *dev)
+{
+	int i;
+
+	if (0 == dev->pci->subsystem_vendor &&
+	    0 == dev->pci->subsystem_device) {
+		printk(KERN_INFO
+			"%s: Board has no valid PCIe Subsystem ID and can't\n"
+		       "%s: be autodetected. Pass card=<n> insmod option\n"
+		       "%s: to workaround that. Redirect complaints to the\n"
+		       "%s: vendor of the TV card.  Best regards,\n"
+		       "%s:         -- tux\n",
+		       dev->name, dev->name, dev->name, dev->name, dev->name);
+	} else {
+		printk(KERN_INFO
+			"%s: Your board isn't known (yet) to the driver.\n"
+		       "%s: Try to pick one of the existing card configs via\n"
+		       "%s: card=<n> insmod option.  Updating to the latest\n"
+		       "%s: version might help as well.\n",
+		       dev->name, dev->name, dev->name, dev->name);
+	}
+	printk(KERN_INFO "%s: Here is a list of valid choices for the card=<n> insmod option:\n",
+	       dev->name);
+	for (i = 0; i < cx23885_bcount; i++)
+		printk(KERN_INFO "%s:    card=%d -> %s\n",
+		       dev->name, i, cx23885_boards[i].name);
+}
+
+static void hauppauge_eeprom(struct cx23885_dev *dev, u8 *eeprom_data)
+{
+	struct tveeprom tv;
+
+	tveeprom_hauppauge_analog(&dev->i2c_bus[0].i2c_client, &tv,
+		eeprom_data);
+
+	/* Make sure we support the board model */
+	switch (tv.model) {
+	case 22001:
+		/* WinTV-HVR1270 (PCIe, Retail, half height)
+		 * ATSC/QAM and basic analog, IR Blast */
+	case 22009:
+		/* WinTV-HVR1210 (PCIe, Retail, half height)
+		 * DVB-T and basic analog, IR Blast */
+	case 22011:
+		/* WinTV-HVR1270 (PCIe, Retail, half height)
+		 * ATSC/QAM and basic analog, IR Recv */
+	case 22019:
+		/* WinTV-HVR1210 (PCIe, Retail, half height)
+		 * DVB-T and basic analog, IR Recv */
+	case 22021:
+		/* WinTV-HVR1275 (PCIe, Retail, half height)
+		 * ATSC/QAM and basic analog, IR Recv */
+	case 22029:
+		/* WinTV-HVR1210 (PCIe, Retail, half height)
+		 * DVB-T and basic analog, IR Recv */
+	case 22101:
+		/* WinTV-HVR1270 (PCIe, Retail, full height)
+		 * ATSC/QAM and basic analog, IR Blast */
+	case 22109:
+		/* WinTV-HVR1210 (PCIe, Retail, full height)
+		 * DVB-T and basic analog, IR Blast */
+	case 22111:
+		/* WinTV-HVR1270 (PCIe, Retail, full height)
+		 * ATSC/QAM and basic analog, IR Recv */
+	case 22119:
+		/* WinTV-HVR1210 (PCIe, Retail, full height)
+		 * DVB-T and basic analog, IR Recv */
+	case 22121:
+		/* WinTV-HVR1275 (PCIe, Retail, full height)
+		 * ATSC/QAM and basic analog, IR Recv */
+	case 22129:
+		/* WinTV-HVR1210 (PCIe, Retail, full height)
+		 * DVB-T and basic analog, IR Recv */
+	case 71009:
+		/* WinTV-HVR1200 (PCIe, Retail, full height)
+		 * DVB-T and basic analog */
+	case 71359:
+		/* WinTV-HVR1200 (PCIe, OEM, half height)
+		 * DVB-T and basic analog */
+	case 71439:
+		/* WinTV-HVR1200 (PCIe, OEM, half height)
+		 * DVB-T and basic analog */
+	case 71449:
+		/* WinTV-HVR1200 (PCIe, OEM, full height)
+		 * DVB-T and basic analog */
+	case 71939:
+		/* WinTV-HVR1200 (PCIe, OEM, half height)
+		 * DVB-T and basic analog */
+	case 71949:
+		/* WinTV-HVR1200 (PCIe, OEM, full height)
+		 * DVB-T and basic analog */
+	case 71959:
+		/* WinTV-HVR1200 (PCIe, OEM, full height)
+		 * DVB-T and basic analog */
+	case 71979:
+		/* WinTV-HVR1200 (PCIe, OEM, half height)
+		 * DVB-T and basic analog */
+	case 71999:
+		/* WinTV-HVR1200 (PCIe, OEM, full height)
+		 * DVB-T and basic analog */
+	case 76601:
+		/* WinTV-HVR1800lp (PCIe, Retail, No IR, Dual
+			channel ATSC and MPEG2 HW Encoder */
+	case 77001:
+		/* WinTV-HVR1500 (Express Card, OEM, No IR, ATSC
+			and Basic analog */
+	case 77011:
+		/* WinTV-HVR1500 (Express Card, Retail, No IR, ATSC
+			and Basic analog */
+	case 77041:
+		/* WinTV-HVR1500Q (Express Card, OEM, No IR, ATSC/QAM
+			and Basic analog */
+	case 77051:
+		/* WinTV-HVR1500Q (Express Card, Retail, No IR, ATSC/QAM
+			and Basic analog */
+	case 78011:
+		/* WinTV-HVR1800 (PCIe, Retail, 3.5mm in, IR, No FM,
+			Dual channel ATSC and MPEG2 HW Encoder */
+	case 78501:
+		/* WinTV-HVR1800 (PCIe, OEM, RCA in, No IR, FM,
+			Dual channel ATSC and MPEG2 HW Encoder */
+	case 78521:
+		/* WinTV-HVR1800 (PCIe, OEM, RCA in, No IR, FM,
+			Dual channel ATSC and MPEG2 HW Encoder */
+	case 78531:
+		/* WinTV-HVR1800 (PCIe, OEM, RCA in, No IR, No FM,
+			Dual channel ATSC and MPEG2 HW Encoder */
+	case 78631:
+		/* WinTV-HVR1800 (PCIe, OEM, No IR, No FM,
+			Dual channel ATSC and MPEG2 HW Encoder */
+	case 79001:
+		/* WinTV-HVR1250 (PCIe, Retail, IR, full height,
+			ATSC and Basic analog */
+	case 79101:
+		/* WinTV-HVR1250 (PCIe, Retail, IR, half height,
+			ATSC and Basic analog */
+	case 79501:
+		/* WinTV-HVR1250 (PCIe, No IR, half height,
+			ATSC [at least] and Basic analog) */
+	case 79561:
+		/* WinTV-HVR1250 (PCIe, OEM, No IR, half height,
+			ATSC and Basic analog */
+	case 79571:
+		/* WinTV-HVR1250 (PCIe, OEM, No IR, full height,
+		 ATSC and Basic analog */
+	case 79671:
+		/* WinTV-HVR1250 (PCIe, OEM, No IR, half height,
+			ATSC and Basic analog */
+	case 80019:
+		/* WinTV-HVR1400 (Express Card, Retail, IR,
+		 * DVB-T and Basic analog */
+	case 81509:
+		/* WinTV-HVR1700 (PCIe, OEM, No IR, half height)
+		 * DVB-T and MPEG2 HW Encoder */
+	case 81519:
+		/* WinTV-HVR1700 (PCIe, OEM, No IR, full height)
+		 * DVB-T and MPEG2 HW Encoder */
+		break;
+	case 85021:
+		/* WinTV-HVR1850 (PCIe, Retail, 3.5mm in, IR, FM,
+			Dual channel ATSC and MPEG2 HW Encoder */
+		break;
+	case 85721:
+		/* WinTV-HVR1290 (PCIe, OEM, RCA in, IR,
+			Dual channel ATSC and Basic analog */
+		break;
+	default:
+		printk(KERN_WARNING "%s: warning: "
+			"unknown hauppauge model #%d\n",
+			dev->name, tv.model);
+		break;
+	}
+
+	printk(KERN_INFO "%s: hauppauge eeprom: model=%d\n",
+			dev->name, tv.model);
+}
+
+int cx23885_tuner_callback(void *priv, int component, int command, int arg)
+{
+	struct cx23885_tsport *port = priv;
+	struct cx23885_dev *dev = port->dev;
+	u32 bitmask = 0;
+
+	if ((command == XC2028_RESET_CLK) || (command == XC2028_I2C_FLUSH))
+		return 0;
+
+	if (command != 0) {
+		printk(KERN_ERR "%s(): Unknown command 0x%x.\n",
+			__func__, command);
+		return -EINVAL;
+	}
+
+	switch (dev->board) {
+	case CX23885_BOARD_HAUPPAUGE_HVR1400:
+	case CX23885_BOARD_HAUPPAUGE_HVR1500:
+	case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
+	case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H:
+	case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H_XC4000:
+	case CX23885_BOARD_COMPRO_VIDEOMATE_E650F:
+	case CX23885_BOARD_COMPRO_VIDEOMATE_E800:
+	case CX23885_BOARD_LEADTEK_WINFAST_PXTV1200:
+		/* Tuner Reset Command */
+		bitmask = 0x04;
+		break;
+	case CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP:
+	case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP:
+		/* Two identical tuners on two different i2c buses,
+		 * we need to reset the correct gpio. */
+		if (port->nr == 1)
+			bitmask = 0x01;
+		else if (port->nr == 2)
+			bitmask = 0x04;
+		break;
+	case CX23885_BOARD_GOTVIEW_X5_3D_HYBRID:
+		/* Tuner Reset Command */
+		bitmask = 0x02;
+		break;
+	case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF:
+		altera_ci_tuner_reset(dev, port->nr);
+		break;
+	}
+
+	if (bitmask) {
+		/* Drive the tuner into reset and back out */
+		cx_clear(GP0_IO, bitmask);
+		mdelay(200);
+		cx_set(GP0_IO, bitmask);
+	}
+
+	return 0;
+}
+
+void cx23885_gpio_setup(struct cx23885_dev *dev)
+{
+	switch (dev->board) {
+	case CX23885_BOARD_HAUPPAUGE_HVR1250:
+		/* GPIO-0 cx24227 demodulator reset */
+		cx_set(GP0_IO, 0x00010001); /* Bring the part out of reset */
+		break;
+	case CX23885_BOARD_HAUPPAUGE_HVR1500:
+		/* GPIO-0 cx24227 demodulator */
+		/* GPIO-2 xc3028 tuner */
+
+		/* Put the parts into reset */
+		cx_set(GP0_IO, 0x00050000);
+		cx_clear(GP0_IO, 0x00000005);
+		msleep(5);
+
+		/* Bring the parts out of reset */
+		cx_set(GP0_IO, 0x00050005);
+		break;
+	case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
+		/* GPIO-0 cx24227 demodulator reset */
+		/* GPIO-2 xc5000 tuner reset */
+		cx_set(GP0_IO, 0x00050005); /* Bring the part out of reset */
+		break;
+	case CX23885_BOARD_HAUPPAUGE_HVR1800:
+		/* GPIO-0 656_CLK */
+		/* GPIO-1 656_D0 */
+		/* GPIO-2 8295A Reset */
+		/* GPIO-3-10 cx23417 data0-7 */
+		/* GPIO-11-14 cx23417 addr0-3 */
+		/* GPIO-15-18 cx23417 READY, CS, RD, WR */
+		/* GPIO-19 IR_RX */
+
+		/* CX23417 GPIO's */
+		/* EIO15 Zilog Reset */
+		/* EIO14 S5H1409/CX24227 Reset */
+		mc417_gpio_enable(dev, GPIO_15 | GPIO_14, 1);
+
+		/* Put the demod into reset and protect the eeprom */
+		mc417_gpio_clear(dev, GPIO_15 | GPIO_14);
+		mdelay(100);
+
+		/* Bring the demod and blaster out of reset */
+		mc417_gpio_set(dev, GPIO_15 | GPIO_14);
+		mdelay(100);
+
+		/* Force the TDA8295A into reset and back */
+		cx23885_gpio_enable(dev, GPIO_2, 1);
+		cx23885_gpio_set(dev, GPIO_2);
+		mdelay(20);
+		cx23885_gpio_clear(dev, GPIO_2);
+		mdelay(20);
+		cx23885_gpio_set(dev, GPIO_2);
+		mdelay(20);
+		break;
+	case CX23885_BOARD_HAUPPAUGE_HVR1200:
+		/* GPIO-0 tda10048 demodulator reset */
+		/* GPIO-2 tda18271 tuner reset */
+
+		/* Put the parts into reset and back */
+		cx_set(GP0_IO, 0x00050000);
+		mdelay(20);
+		cx_clear(GP0_IO, 0x00000005);
+		mdelay(20);
+		cx_set(GP0_IO, 0x00050005);
+		break;
+	case CX23885_BOARD_HAUPPAUGE_HVR1700:
+		/* GPIO-0 TDA10048 demodulator reset */
+		/* GPIO-2 TDA8295A Reset */
+		/* GPIO-3-10 cx23417 data0-7 */
+		/* GPIO-11-14 cx23417 addr0-3 */
+		/* GPIO-15-18 cx23417 READY, CS, RD, WR */
+
+		/* The following GPIO's are on the interna AVCore (cx25840) */
+		/* GPIO-19 IR_RX */
+		/* GPIO-20 IR_TX 416/DVBT Select */
+		/* GPIO-21 IIS DAT */
+		/* GPIO-22 IIS WCLK */
+		/* GPIO-23 IIS BCLK */
+
+		/* Put the parts into reset and back */
+		cx_set(GP0_IO, 0x00050000);
+		mdelay(20);
+		cx_clear(GP0_IO, 0x00000005);
+		mdelay(20);
+		cx_set(GP0_IO, 0x00050005);
+		break;
+	case CX23885_BOARD_HAUPPAUGE_HVR1400:
+		/* GPIO-0  Dibcom7000p demodulator reset */
+		/* GPIO-2  xc3028L tuner reset */
+		/* GPIO-13 LED */
+
+		/* Put the parts into reset and back */
+		cx_set(GP0_IO, 0x00050000);
+		mdelay(20);
+		cx_clear(GP0_IO, 0x00000005);
+		mdelay(20);
+		cx_set(GP0_IO, 0x00050005);
+		break;
+	case CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP:
+		/* GPIO-0 xc5000 tuner reset i2c bus 0 */
+		/* GPIO-1 s5h1409 demod reset i2c bus 0 */
+		/* GPIO-2 xc5000 tuner reset i2c bus 1 */
+		/* GPIO-3 s5h1409 demod reset i2c bus 0 */
+
+		/* Put the parts into reset and back */
+		cx_set(GP0_IO, 0x000f0000);
+		mdelay(20);
+		cx_clear(GP0_IO, 0x0000000f);
+		mdelay(20);
+		cx_set(GP0_IO, 0x000f000f);
+		break;
+	case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP:
+		/* GPIO-0 portb xc3028 reset */
+		/* GPIO-1 portb zl10353 reset */
+		/* GPIO-2 portc xc3028 reset */
+		/* GPIO-3 portc zl10353 reset */
+
+		/* Put the parts into reset and back */
+		cx_set(GP0_IO, 0x000f0000);
+		mdelay(20);
+		cx_clear(GP0_IO, 0x0000000f);
+		mdelay(20);
+		cx_set(GP0_IO, 0x000f000f);
+		break;
+	case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H:
+	case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H_XC4000:
+	case CX23885_BOARD_COMPRO_VIDEOMATE_E650F:
+	case CX23885_BOARD_COMPRO_VIDEOMATE_E800:
+	case CX23885_BOARD_LEADTEK_WINFAST_PXTV1200:
+		/* GPIO-2  xc3028 tuner reset */
+
+		/* The following GPIO's are on the internal AVCore (cx25840) */
+		/* GPIO-?  zl10353 demod reset */
+
+		/* Put the parts into reset and back */
+		cx_set(GP0_IO, 0x00040000);
+		mdelay(20);
+		cx_clear(GP0_IO, 0x00000004);
+		mdelay(20);
+		cx_set(GP0_IO, 0x00040004);
+		break;
+	case CX23885_BOARD_TBS_6920:
+	case CX23885_BOARD_PROF_8000:
+		cx_write(MC417_CTL, 0x00000036);
+		cx_write(MC417_OEN, 0x00001000);
+		cx_set(MC417_RWD, 0x00000002);
+		mdelay(200);
+		cx_clear(MC417_RWD, 0x00000800);
+		mdelay(200);
+		cx_set(MC417_RWD, 0x00000800);
+		mdelay(200);
+		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;
+	case CX23885_BOARD_HAUPPAUGE_HVR1270:
+	case CX23885_BOARD_HAUPPAUGE_HVR1275:
+	case CX23885_BOARD_HAUPPAUGE_HVR1255:
+	case CX23885_BOARD_HAUPPAUGE_HVR1255_22111:
+	case CX23885_BOARD_HAUPPAUGE_HVR1210:
+		/* GPIO-5 RF Control: 0 = RF1 Terrestrial, 1 = RF2 Cable */
+		/* GPIO-6 I2C Gate which can isolate the demod from the bus */
+		/* GPIO-9 Demod reset */
+
+		/* Put the parts into reset and back */
+		cx23885_gpio_enable(dev, GPIO_9 | GPIO_6 | GPIO_5, 1);
+		cx23885_gpio_set(dev, GPIO_9 | GPIO_6 | GPIO_5);
+		cx23885_gpio_clear(dev, GPIO_9);
+		mdelay(20);
+		cx23885_gpio_set(dev, GPIO_9);
+		break;
+	case CX23885_BOARD_MYGICA_X8506:
+	case CX23885_BOARD_MAGICPRO_PROHDTVE2:
+	case CX23885_BOARD_MYGICA_X8507:
+		/* GPIO-0 (0)Analog / (1)Digital TV */
+		/* GPIO-1 reset XC5000 */
+		/* GPIO-2 reset LGS8GL5 / LGS8G75 */
+		cx23885_gpio_enable(dev, GPIO_0 | GPIO_1 | GPIO_2, 1);
+		cx23885_gpio_clear(dev, GPIO_1 | GPIO_2);
+		mdelay(100);
+		cx23885_gpio_set(dev, GPIO_0 | GPIO_1 | GPIO_2);
+		mdelay(100);
+		break;
+	case CX23885_BOARD_MYGICA_X8558PRO:
+		/* GPIO-0 reset first ATBM8830 */
+		/* GPIO-1 reset second ATBM8830 */
+		cx23885_gpio_enable(dev, GPIO_0 | GPIO_1, 1);
+		cx23885_gpio_clear(dev, GPIO_0 | GPIO_1);
+		mdelay(100);
+		cx23885_gpio_set(dev, GPIO_0 | GPIO_1);
+		mdelay(100);
+		break;
+	case CX23885_BOARD_HAUPPAUGE_HVR1850:
+	case CX23885_BOARD_HAUPPAUGE_HVR1290:
+		/* GPIO-0 656_CLK */
+		/* GPIO-1 656_D0 */
+		/* GPIO-2 Wake# */
+		/* GPIO-3-10 cx23417 data0-7 */
+		/* GPIO-11-14 cx23417 addr0-3 */
+		/* GPIO-15-18 cx23417 READY, CS, RD, WR */
+		/* GPIO-19 IR_RX */
+		/* GPIO-20 C_IR_TX */
+		/* GPIO-21 I2S DAT */
+		/* GPIO-22 I2S WCLK */
+		/* GPIO-23 I2S BCLK */
+		/* ALT GPIO: EXP GPIO LATCH */
+
+		/* CX23417 GPIO's */
+		/* GPIO-14 S5H1411/CX24228 Reset */
+		/* GPIO-13 EEPROM write protect */
+		mc417_gpio_enable(dev, GPIO_14 | GPIO_13, 1);
+
+		/* Put the demod into reset and protect the eeprom */
+		mc417_gpio_clear(dev, GPIO_14 | GPIO_13);
+		mdelay(100);
+
+		/* Bring the demod out of reset */
+		mc417_gpio_set(dev, GPIO_14);
+		mdelay(100);
+
+		/* CX24228 GPIO */
+		/* Connected to IF / Mux */
+		break;
+	case CX23885_BOARD_GOTVIEW_X5_3D_HYBRID:
+		cx_set(GP0_IO, 0x00010001); /* Bring the part out of reset */
+		break;
+	case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF:
+		/* GPIO-0 ~INT in
+		   GPIO-1 TMS out
+		   GPIO-2 ~reset chips out
+		   GPIO-3 to GPIO-10 data/addr for CA in/out
+		   GPIO-11 ~CS out
+		   GPIO-12 ADDR out
+		   GPIO-13 ~WR out
+		   GPIO-14 ~RD out
+		   GPIO-15 ~RDY in
+		   GPIO-16 TCK out
+		   GPIO-17 TDO in
+		   GPIO-18 TDI out
+		 */
+		cx_set(GP0_IO, 0x00060000); /* GPIO-1,2 as out */
+		/* GPIO-0 as INT, reset & TMS low */
+		cx_clear(GP0_IO, 0x00010006);
+		mdelay(100);/* reset delay */
+		cx_set(GP0_IO, 0x00000004); /* reset high */
+		cx_write(MC417_CTL, 0x00000037);/* enable GPIO-3..18 pins */
+		/* GPIO-17 is TDO in, GPIO-15 is ~RDY in, rest is out */
+		cx_write(MC417_OEN, 0x00005000);
+		/* ~RD, ~WR high; ADDR low; ~CS high */
+		cx_write(MC417_RWD, 0x00000d00);
+		/* enable irq */
+		cx_write(GPIO_ISM, 0x00000000);/* INTERRUPTS active low*/
+		break;
+	}
+}
+
+int cx23885_ir_init(struct cx23885_dev *dev)
+{
+	static struct v4l2_subdev_io_pin_config ir_rxtx_pin_cfg[] = {
+		{
+			.flags	  = V4L2_SUBDEV_IO_PIN_INPUT,
+			.pin	  = CX23885_PIN_IR_RX_GPIO19,
+			.function = CX23885_PAD_IR_RX,
+			.value	  = 0,
+			.strength = CX25840_PIN_DRIVE_MEDIUM,
+		}, {
+			.flags	  = V4L2_SUBDEV_IO_PIN_OUTPUT,
+			.pin	  = CX23885_PIN_IR_TX_GPIO20,
+			.function = CX23885_PAD_IR_TX,
+			.value	  = 0,
+			.strength = CX25840_PIN_DRIVE_MEDIUM,
+		}
+	};
+	const size_t ir_rxtx_pin_cfg_count = ARRAY_SIZE(ir_rxtx_pin_cfg);
+
+	static struct v4l2_subdev_io_pin_config ir_rx_pin_cfg[] = {
+		{
+			.flags	  = V4L2_SUBDEV_IO_PIN_INPUT,
+			.pin	  = CX23885_PIN_IR_RX_GPIO19,
+			.function = CX23885_PAD_IR_RX,
+			.value	  = 0,
+			.strength = CX25840_PIN_DRIVE_MEDIUM,
+		}
+	};
+	const size_t ir_rx_pin_cfg_count = ARRAY_SIZE(ir_rx_pin_cfg);
+
+	struct v4l2_subdev_ir_parameters params;
+	int ret = 0;
+	switch (dev->board) {
+	case CX23885_BOARD_HAUPPAUGE_HVR1500:
+	case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
+	case CX23885_BOARD_HAUPPAUGE_HVR1800:
+	case CX23885_BOARD_HAUPPAUGE_HVR1200:
+	case CX23885_BOARD_HAUPPAUGE_HVR1400:
+	case CX23885_BOARD_HAUPPAUGE_HVR1275:
+	case CX23885_BOARD_HAUPPAUGE_HVR1255:
+	case CX23885_BOARD_HAUPPAUGE_HVR1255_22111:
+	case CX23885_BOARD_HAUPPAUGE_HVR1210:
+		/* FIXME: Implement me */
+		break;
+	case CX23885_BOARD_HAUPPAUGE_HVR1270:
+		ret = cx23888_ir_probe(dev);
+		if (ret)
+			break;
+		dev->sd_ir = cx23885_find_hw(dev, CX23885_HW_888_IR);
+		v4l2_subdev_call(dev->sd_cx25840, core, s_io_pin_config,
+				 ir_rx_pin_cfg_count, ir_rx_pin_cfg);
+		break;
+	case CX23885_BOARD_HAUPPAUGE_HVR1850:
+	case CX23885_BOARD_HAUPPAUGE_HVR1290:
+		ret = cx23888_ir_probe(dev);
+		if (ret)
+			break;
+		dev->sd_ir = cx23885_find_hw(dev, CX23885_HW_888_IR);
+		v4l2_subdev_call(dev->sd_cx25840, core, s_io_pin_config,
+				 ir_rxtx_pin_cfg_count, ir_rxtx_pin_cfg);
+		/*
+		 * For these boards we need to invert the Tx output via the
+		 * IR controller to have the LED off while idle
+		 */
+		v4l2_subdev_call(dev->sd_ir, ir, tx_g_parameters, &params);
+		params.enable = false;
+		params.shutdown = false;
+		params.invert_level = true;
+		v4l2_subdev_call(dev->sd_ir, ir, tx_s_parameters, &params);
+		params.shutdown = true;
+		v4l2_subdev_call(dev->sd_ir, ir, tx_s_parameters, &params);
+		break;
+	case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL:
+	case CX23885_BOARD_TEVII_S470:
+		if (!enable_885_ir)
+			break;
+		dev->sd_ir = cx23885_find_hw(dev, CX23885_HW_AV_CORE);
+		if (dev->sd_ir == NULL) {
+			ret = -ENODEV;
+			break;
+		}
+		v4l2_subdev_call(dev->sd_cx25840, core, s_io_pin_config,
+				 ir_rx_pin_cfg_count, ir_rx_pin_cfg);
+		break;
+	case CX23885_BOARD_HAUPPAUGE_HVR1250:
+		if (!enable_885_ir)
+			break;
+		dev->sd_ir = cx23885_find_hw(dev, CX23885_HW_AV_CORE);
+		if (dev->sd_ir == NULL) {
+			ret = -ENODEV;
+			break;
+		}
+		v4l2_subdev_call(dev->sd_cx25840, core, s_io_pin_config,
+				 ir_rxtx_pin_cfg_count, ir_rxtx_pin_cfg);
+		break;
+	case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP:
+		request_module("ir-kbd-i2c");
+		break;
+	}
+
+	return ret;
+}
+
+void cx23885_ir_fini(struct cx23885_dev *dev)
+{
+	switch (dev->board) {
+	case CX23885_BOARD_HAUPPAUGE_HVR1270:
+	case CX23885_BOARD_HAUPPAUGE_HVR1850:
+	case CX23885_BOARD_HAUPPAUGE_HVR1290:
+		cx23885_irq_remove(dev, PCI_MSK_IR);
+		cx23888_ir_remove(dev);
+		dev->sd_ir = NULL;
+		break;
+	case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL:
+	case CX23885_BOARD_TEVII_S470:
+	case CX23885_BOARD_HAUPPAUGE_HVR1250:
+		cx23885_irq_remove(dev, PCI_MSK_AV_CORE);
+		/* sd_ir is a duplicate pointer to the AV Core, just clear it */
+		dev->sd_ir = NULL;
+		break;
+	}
+}
+
+int netup_jtag_io(void *device, int tms, int tdi, int read_tdo)
+{
+	int data;
+	int tdo = 0;
+	struct cx23885_dev *dev = (struct cx23885_dev *)device;
+	/*TMS*/
+	data = ((cx_read(GP0_IO)) & (~0x00000002));
+	data |= (tms ? 0x00020002 : 0x00020000);
+	cx_write(GP0_IO, data);
+
+	/*TDI*/
+	data = ((cx_read(MC417_RWD)) & (~0x0000a000));
+	data |= (tdi ? 0x00008000 : 0);
+	cx_write(MC417_RWD, data);
+	if (read_tdo)
+		tdo = (data & 0x00004000) ? 1 : 0; /*TDO*/
+
+	cx_write(MC417_RWD, data | 0x00002000);
+	udelay(1);
+	/*TCK*/
+	cx_write(MC417_RWD, data);
+
+	return tdo;
+}
+
+void cx23885_ir_pci_int_enable(struct cx23885_dev *dev)
+{
+	switch (dev->board) {
+	case CX23885_BOARD_HAUPPAUGE_HVR1270:
+	case CX23885_BOARD_HAUPPAUGE_HVR1850:
+	case CX23885_BOARD_HAUPPAUGE_HVR1290:
+		if (dev->sd_ir)
+			cx23885_irq_add_enable(dev, PCI_MSK_IR);
+		break;
+	case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL:
+	case CX23885_BOARD_TEVII_S470:
+	case CX23885_BOARD_HAUPPAUGE_HVR1250:
+		if (dev->sd_ir)
+			cx23885_irq_add_enable(dev, PCI_MSK_AV_CORE);
+		break;
+	}
+}
+
+void cx23885_card_setup(struct cx23885_dev *dev)
+{
+	struct cx23885_tsport *ts1 = &dev->ts1;
+	struct cx23885_tsport *ts2 = &dev->ts2;
+
+	static u8 eeprom[256];
+
+	if (dev->i2c_bus[0].i2c_rc == 0) {
+		dev->i2c_bus[0].i2c_client.addr = 0xa0 >> 1;
+		tveeprom_read(&dev->i2c_bus[0].i2c_client,
+			      eeprom, sizeof(eeprom));
+	}
+
+	switch (dev->board) {
+	case CX23885_BOARD_HAUPPAUGE_HVR1250:
+		if (dev->i2c_bus[0].i2c_rc == 0) {
+			if (eeprom[0x80] != 0x84)
+				hauppauge_eeprom(dev, eeprom+0xc0);
+			else
+				hauppauge_eeprom(dev, eeprom+0x80);
+		}
+		break;
+	case CX23885_BOARD_HAUPPAUGE_HVR1500:
+	case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
+	case CX23885_BOARD_HAUPPAUGE_HVR1400:
+		if (dev->i2c_bus[0].i2c_rc == 0)
+			hauppauge_eeprom(dev, eeprom+0x80);
+		break;
+	case CX23885_BOARD_HAUPPAUGE_HVR1800:
+	case CX23885_BOARD_HAUPPAUGE_HVR1800lp:
+	case CX23885_BOARD_HAUPPAUGE_HVR1200:
+	case CX23885_BOARD_HAUPPAUGE_HVR1700:
+	case CX23885_BOARD_HAUPPAUGE_HVR1270:
+	case CX23885_BOARD_HAUPPAUGE_HVR1275:
+	case CX23885_BOARD_HAUPPAUGE_HVR1255:
+	case CX23885_BOARD_HAUPPAUGE_HVR1255_22111:
+	case CX23885_BOARD_HAUPPAUGE_HVR1210:
+	case CX23885_BOARD_HAUPPAUGE_HVR1850:
+	case CX23885_BOARD_HAUPPAUGE_HVR1290:
+		if (dev->i2c_bus[0].i2c_rc == 0)
+			hauppauge_eeprom(dev, eeprom+0xc0);
+		break;
+	}
+
+	switch (dev->board) {
+	case CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP:
+	case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP:
+		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 omitted intentionally */
+	case CX23885_BOARD_DVICO_FUSIONHDTV_5_EXP:
+		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;
+		break;
+	case CX23885_BOARD_HAUPPAUGE_HVR1850:
+	case CX23885_BOARD_HAUPPAUGE_HVR1800:
+		/* Defaults for VID B - Analog encoder */
+		/* DREQ_POL, SMODE, PUNC_CLK, MCLK_POL Serial bus + punc clk */
+		ts1->gen_ctrl_val    = 0x10e;
+		ts1->ts_clk_en_val   = 0x1; /* Enable TS_CLK */
+		ts1->src_sel_val     = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
+
+		/* APB_TSVALERR_POL (active low)*/
+		ts1->vld_misc_val    = 0x2000;
+		ts1->hw_sop_ctrl_val = (0x47 << 16 | 188 << 4 | 0xc);
+		cx_write(0x130184, 0xc);
+
+		/* Defaults for VID C */
+		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_TBS_6920:
+		ts1->gen_ctrl_val  = 0x4; /* Parallel */
+		ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */
+		ts1->src_sel_val   = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
+		break;
+	case CX23885_BOARD_TEVII_S470:
+	case CX23885_BOARD_TEVII_S471:
+	case CX23885_BOARD_DVBWORLD_2005:
+	case CX23885_BOARD_PROF_8000:
+		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:
+	case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF:
+	case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL:
+		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_MYGICA_X8506:
+	case CX23885_BOARD_MAGICPRO_PROHDTVE2:
+		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_MYGICA_X8558PRO:
+		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;
+		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:
+	case CX23885_BOARD_HAUPPAUGE_HVR1800lp:
+	case CX23885_BOARD_HAUPPAUGE_HVR1200:
+	case CX23885_BOARD_HAUPPAUGE_HVR1700:
+	case CX23885_BOARD_HAUPPAUGE_HVR1400:
+	case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H:
+	case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H_XC4000:
+	case CX23885_BOARD_COMPRO_VIDEOMATE_E650F:
+	case CX23885_BOARD_HAUPPAUGE_HVR1270:
+	case CX23885_BOARD_HAUPPAUGE_HVR1275:
+	case CX23885_BOARD_HAUPPAUGE_HVR1255:
+	case CX23885_BOARD_HAUPPAUGE_HVR1255_22111:
+	case CX23885_BOARD_HAUPPAUGE_HVR1210:
+	case CX23885_BOARD_COMPRO_VIDEOMATE_E800:
+	case CX23885_BOARD_HAUPPAUGE_HVR1290:
+	case CX23885_BOARD_GOTVIEW_X5_3D_HYBRID:
+	default:
+		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;
+	}
+
+	/* Certain boards support analog, or require the avcore to be
+	 * loaded, ensure this happens.
+	 */
+	switch (dev->board) {
+	case CX23885_BOARD_TEVII_S470:
+		/* Currently only enabled for the integrated IR controller */
+		if (!enable_885_ir)
+			break;
+	case CX23885_BOARD_HAUPPAUGE_HVR1250:
+	case CX23885_BOARD_HAUPPAUGE_HVR1800:
+	case CX23885_BOARD_HAUPPAUGE_HVR1800lp:
+	case CX23885_BOARD_HAUPPAUGE_HVR1700:
+	case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H:
+	case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H_XC4000:
+	case CX23885_BOARD_COMPRO_VIDEOMATE_E650F:
+	case CX23885_BOARD_NETUP_DUAL_DVBS2_CI:
+	case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF:
+	case CX23885_BOARD_COMPRO_VIDEOMATE_E800:
+	case CX23885_BOARD_HAUPPAUGE_HVR1255:
+	case CX23885_BOARD_HAUPPAUGE_HVR1255_22111:
+	case CX23885_BOARD_HAUPPAUGE_HVR1270:
+	case CX23885_BOARD_HAUPPAUGE_HVR1850:
+	case CX23885_BOARD_MYGICA_X8506:
+	case CX23885_BOARD_MAGICPRO_PROHDTVE2:
+	case CX23885_BOARD_HAUPPAUGE_HVR1290:
+	case CX23885_BOARD_LEADTEK_WINFAST_PXTV1200:
+	case CX23885_BOARD_GOTVIEW_X5_3D_HYBRID:
+	case CX23885_BOARD_HAUPPAUGE_HVR1500:
+	case CX23885_BOARD_MPX885:
+	case CX23885_BOARD_MYGICA_X8507:
+	case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL:
+		dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev,
+				&dev->i2c_bus[2].i2c_adap,
+				"cx25840", 0x88 >> 1, NULL);
+		if (dev->sd_cx25840) {
+			dev->sd_cx25840->grp_id = CX23885_HW_AV_CORE;
+			v4l2_subdev_call(dev->sd_cx25840, core, load_fw);
+		}
+		break;
+	}
+
+	/* AUX-PLL 27MHz CLK */
+	switch (dev->board) {
+	case CX23885_BOARD_NETUP_DUAL_DVBS2_CI:
+		netup_initialize(dev);
+		break;
+	case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF: {
+		int ret;
+		const struct firmware *fw;
+		const char *filename = "dvb-netup-altera-01.fw";
+		char *action = "configure";
+		static struct netup_card_info cinfo;
+		struct altera_config netup_config = {
+			.dev = dev,
+			.action = action,
+			.jtag_io = netup_jtag_io,
+		};
+
+		netup_initialize(dev);
+
+		netup_get_card_info(&dev->i2c_bus[0].i2c_adap, &cinfo);
+		if (netup_card_rev)
+			cinfo.rev = netup_card_rev;
+
+		switch (cinfo.rev) {
+		case 0x4:
+			filename = "dvb-netup-altera-04.fw";
+			break;
+		default:
+			filename = "dvb-netup-altera-01.fw";
+			break;
+		}
+		printk(KERN_INFO "NetUP card rev=0x%x fw_filename=%s\n",
+				cinfo.rev, filename);
+
+		ret = request_firmware(&fw, filename, &dev->pci->dev);
+		if (ret != 0)
+			printk(KERN_ERR "did not find the firmware file. (%s) "
+			"Please see linux/Documentation/dvb/ for more details "
+			"on firmware-problems.", filename);
+		else
+			altera_init(&netup_config, fw);
+
+		release_firmware(fw);
+		break;
+	}
+	}
+}
+
+/* ------------------------------------------------------------------ */
diff --git a/drivers/media/pci/cx23885/cx23885-core.c b/drivers/media/pci/cx23885/cx23885-core.c
new file mode 100644
index 0000000..697728f
--- /dev/null
+++ b/drivers/media/pci/cx23885/cx23885-core.c
@@ -0,0 +1,2234 @@
+/*
+ *  Driver for the Conexant CX23885 PCIe bridge
+ *
+ *  Copyright (c) 2006 Steven Toth <stoth@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/init.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kmod.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <asm/div64.h>
+#include <linux/firmware.h>
+
+#include "cx23885.h"
+#include "cimax2.h"
+#include "altera-ci.h"
+#include "cx23888-ir.h"
+#include "cx23885-ir.h"
+#include "cx23885-av.h"
+#include "cx23885-input.h"
+
+MODULE_DESCRIPTION("Driver for cx23885 based TV cards");
+MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(CX23885_VERSION);
+
+static unsigned int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "enable debug messages");
+
+static unsigned int card[]  = {[0 ... (CX23885_MAXBOARDS - 1)] = UNSET };
+module_param_array(card,  int, NULL, 0444);
+MODULE_PARM_DESC(card, "card type");
+
+#define dprintk(level, fmt, arg...)\
+	do { if (debug >= level)\
+		printk(KERN_DEBUG "%s: " fmt, dev->name, ## arg);\
+	} while (0)
+
+static unsigned int cx23885_devcount;
+
+#define NO_SYNC_LINE (-1U)
+
+/* FIXME, these allocations will change when
+ * analog arrives. The be reviewed.
+ * CX23887 Assumptions
+ * 1 line = 16 bytes of CDT
+ * cmds size = 80
+ * cdt size = 16 * linesize
+ * iqsize = 64
+ * maxlines = 6
+ *
+ * Address Space:
+ * 0x00000000 0x00008fff FIFO clusters
+ * 0x00010000 0x000104af Channel Management Data Structures
+ * 0x000104b0 0x000104ff Free
+ * 0x00010500 0x000108bf 15 channels * iqsize
+ * 0x000108c0 0x000108ff Free
+ * 0x00010900 0x00010e9f IQ's + Cluster Descriptor Tables
+ *                       15 channels * (iqsize + (maxlines * linesize))
+ * 0x00010ea0 0x00010xxx Free
+ */
+
+static struct sram_channel cx23885_sram_channels[] = {
+	[SRAM_CH01] = {
+		.name		= "VID A",
+		.cmds_start	= 0x10000,
+		.ctrl_start	= 0x10380,
+		.cdt		= 0x104c0,
+		.fifo_start	= 0x40,
+		.fifo_size	= 0x2800,
+		.ptr1_reg	= DMA1_PTR1,
+		.ptr2_reg	= DMA1_PTR2,
+		.cnt1_reg	= DMA1_CNT1,
+		.cnt2_reg	= DMA1_CNT2,
+	},
+	[SRAM_CH02] = {
+		.name		= "ch2",
+		.cmds_start	= 0x0,
+		.ctrl_start	= 0x0,
+		.cdt		= 0x0,
+		.fifo_start	= 0x0,
+		.fifo_size	= 0x0,
+		.ptr1_reg	= DMA2_PTR1,
+		.ptr2_reg	= DMA2_PTR2,
+		.cnt1_reg	= DMA2_CNT1,
+		.cnt2_reg	= DMA2_CNT2,
+	},
+	[SRAM_CH03] = {
+		.name		= "TS1 B",
+		.cmds_start	= 0x100A0,
+		.ctrl_start	= 0x10400,
+		.cdt		= 0x10580,
+		.fifo_start	= 0x5000,
+		.fifo_size	= 0x1000,
+		.ptr1_reg	= DMA3_PTR1,
+		.ptr2_reg	= DMA3_PTR2,
+		.cnt1_reg	= DMA3_CNT1,
+		.cnt2_reg	= DMA3_CNT2,
+	},
+	[SRAM_CH04] = {
+		.name		= "ch4",
+		.cmds_start	= 0x0,
+		.ctrl_start	= 0x0,
+		.cdt		= 0x0,
+		.fifo_start	= 0x0,
+		.fifo_size	= 0x0,
+		.ptr1_reg	= DMA4_PTR1,
+		.ptr2_reg	= DMA4_PTR2,
+		.cnt1_reg	= DMA4_CNT1,
+		.cnt2_reg	= DMA4_CNT2,
+	},
+	[SRAM_CH05] = {
+		.name		= "ch5",
+		.cmds_start	= 0x0,
+		.ctrl_start	= 0x0,
+		.cdt		= 0x0,
+		.fifo_start	= 0x0,
+		.fifo_size	= 0x0,
+		.ptr1_reg	= DMA5_PTR1,
+		.ptr2_reg	= DMA5_PTR2,
+		.cnt1_reg	= DMA5_CNT1,
+		.cnt2_reg	= DMA5_CNT2,
+	},
+	[SRAM_CH06] = {
+		.name		= "TS2 C",
+		.cmds_start	= 0x10140,
+		.ctrl_start	= 0x10440,
+		.cdt		= 0x105e0,
+		.fifo_start	= 0x6000,
+		.fifo_size	= 0x1000,
+		.ptr1_reg	= DMA5_PTR1,
+		.ptr2_reg	= DMA5_PTR2,
+		.cnt1_reg	= DMA5_CNT1,
+		.cnt2_reg	= DMA5_CNT2,
+	},
+	[SRAM_CH07] = {
+		.name		= "TV Audio",
+		.cmds_start	= 0x10190,
+		.ctrl_start	= 0x10480,
+		.cdt		= 0x10a00,
+		.fifo_start	= 0x7000,
+		.fifo_size	= 0x1000,
+		.ptr1_reg	= DMA6_PTR1,
+		.ptr2_reg	= DMA6_PTR2,
+		.cnt1_reg	= DMA6_CNT1,
+		.cnt2_reg	= DMA6_CNT2,
+	},
+	[SRAM_CH08] = {
+		.name		= "ch8",
+		.cmds_start	= 0x0,
+		.ctrl_start	= 0x0,
+		.cdt		= 0x0,
+		.fifo_start	= 0x0,
+		.fifo_size	= 0x0,
+		.ptr1_reg	= DMA7_PTR1,
+		.ptr2_reg	= DMA7_PTR2,
+		.cnt1_reg	= DMA7_CNT1,
+		.cnt2_reg	= DMA7_CNT2,
+	},
+	[SRAM_CH09] = {
+		.name		= "ch9",
+		.cmds_start	= 0x0,
+		.ctrl_start	= 0x0,
+		.cdt		= 0x0,
+		.fifo_start	= 0x0,
+		.fifo_size	= 0x0,
+		.ptr1_reg	= DMA8_PTR1,
+		.ptr2_reg	= DMA8_PTR2,
+		.cnt1_reg	= DMA8_CNT1,
+		.cnt2_reg	= DMA8_CNT2,
+	},
+};
+
+static struct sram_channel cx23887_sram_channels[] = {
+	[SRAM_CH01] = {
+		.name		= "VID A",
+		.cmds_start	= 0x10000,
+		.ctrl_start	= 0x105b0,
+		.cdt		= 0x107b0,
+		.fifo_start	= 0x40,
+		.fifo_size	= 0x2800,
+		.ptr1_reg	= DMA1_PTR1,
+		.ptr2_reg	= DMA1_PTR2,
+		.cnt1_reg	= DMA1_CNT1,
+		.cnt2_reg	= DMA1_CNT2,
+	},
+	[SRAM_CH02] = {
+		.name		= "VID A (VBI)",
+		.cmds_start	= 0x10050,
+		.ctrl_start	= 0x105F0,
+		.cdt		= 0x10810,
+		.fifo_start	= 0x3000,
+		.fifo_size	= 0x1000,
+		.ptr1_reg	= DMA2_PTR1,
+		.ptr2_reg	= DMA2_PTR2,
+		.cnt1_reg	= DMA2_CNT1,
+		.cnt2_reg	= DMA2_CNT2,
+	},
+	[SRAM_CH03] = {
+		.name		= "TS1 B",
+		.cmds_start	= 0x100A0,
+		.ctrl_start	= 0x10630,
+		.cdt		= 0x10870,
+		.fifo_start	= 0x5000,
+		.fifo_size	= 0x1000,
+		.ptr1_reg	= DMA3_PTR1,
+		.ptr2_reg	= DMA3_PTR2,
+		.cnt1_reg	= DMA3_CNT1,
+		.cnt2_reg	= DMA3_CNT2,
+	},
+	[SRAM_CH04] = {
+		.name		= "ch4",
+		.cmds_start	= 0x0,
+		.ctrl_start	= 0x0,
+		.cdt		= 0x0,
+		.fifo_start	= 0x0,
+		.fifo_size	= 0x0,
+		.ptr1_reg	= DMA4_PTR1,
+		.ptr2_reg	= DMA4_PTR2,
+		.cnt1_reg	= DMA4_CNT1,
+		.cnt2_reg	= DMA4_CNT2,
+	},
+	[SRAM_CH05] = {
+		.name		= "ch5",
+		.cmds_start	= 0x0,
+		.ctrl_start	= 0x0,
+		.cdt		= 0x0,
+		.fifo_start	= 0x0,
+		.fifo_size	= 0x0,
+		.ptr1_reg	= DMA5_PTR1,
+		.ptr2_reg	= DMA5_PTR2,
+		.cnt1_reg	= DMA5_CNT1,
+		.cnt2_reg	= DMA5_CNT2,
+	},
+	[SRAM_CH06] = {
+		.name		= "TS2 C",
+		.cmds_start	= 0x10140,
+		.ctrl_start	= 0x10670,
+		.cdt		= 0x108d0,
+		.fifo_start	= 0x6000,
+		.fifo_size	= 0x1000,
+		.ptr1_reg	= DMA5_PTR1,
+		.ptr2_reg	= DMA5_PTR2,
+		.cnt1_reg	= DMA5_CNT1,
+		.cnt2_reg	= DMA5_CNT2,
+	},
+	[SRAM_CH07] = {
+		.name		= "TV Audio",
+		.cmds_start	= 0x10190,
+		.ctrl_start	= 0x106B0,
+		.cdt		= 0x10930,
+		.fifo_start	= 0x7000,
+		.fifo_size	= 0x1000,
+		.ptr1_reg	= DMA6_PTR1,
+		.ptr2_reg	= DMA6_PTR2,
+		.cnt1_reg	= DMA6_CNT1,
+		.cnt2_reg	= DMA6_CNT2,
+	},
+	[SRAM_CH08] = {
+		.name		= "ch8",
+		.cmds_start	= 0x0,
+		.ctrl_start	= 0x0,
+		.cdt		= 0x0,
+		.fifo_start	= 0x0,
+		.fifo_size	= 0x0,
+		.ptr1_reg	= DMA7_PTR1,
+		.ptr2_reg	= DMA7_PTR2,
+		.cnt1_reg	= DMA7_CNT1,
+		.cnt2_reg	= DMA7_CNT2,
+	},
+	[SRAM_CH09] = {
+		.name		= "ch9",
+		.cmds_start	= 0x0,
+		.ctrl_start	= 0x0,
+		.cdt		= 0x0,
+		.fifo_start	= 0x0,
+		.fifo_size	= 0x0,
+		.ptr1_reg	= DMA8_PTR1,
+		.ptr2_reg	= DMA8_PTR2,
+		.cnt1_reg	= DMA8_CNT1,
+		.cnt2_reg	= DMA8_CNT2,
+	},
+};
+
+void cx23885_irq_add(struct cx23885_dev *dev, u32 mask)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&dev->pci_irqmask_lock, flags);
+
+	dev->pci_irqmask |= mask;
+
+	spin_unlock_irqrestore(&dev->pci_irqmask_lock, flags);
+}
+
+void cx23885_irq_add_enable(struct cx23885_dev *dev, u32 mask)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&dev->pci_irqmask_lock, flags);
+
+	dev->pci_irqmask |= mask;
+	cx_set(PCI_INT_MSK, mask);
+
+	spin_unlock_irqrestore(&dev->pci_irqmask_lock, flags);
+}
+
+void cx23885_irq_enable(struct cx23885_dev *dev, u32 mask)
+{
+	u32 v;
+	unsigned long flags;
+	spin_lock_irqsave(&dev->pci_irqmask_lock, flags);
+
+	v = mask & dev->pci_irqmask;
+	if (v)
+		cx_set(PCI_INT_MSK, v);
+
+	spin_unlock_irqrestore(&dev->pci_irqmask_lock, flags);
+}
+
+static inline void cx23885_irq_enable_all(struct cx23885_dev *dev)
+{
+	cx23885_irq_enable(dev, 0xffffffff);
+}
+
+void cx23885_irq_disable(struct cx23885_dev *dev, u32 mask)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&dev->pci_irqmask_lock, flags);
+
+	cx_clear(PCI_INT_MSK, mask);
+
+	spin_unlock_irqrestore(&dev->pci_irqmask_lock, flags);
+}
+
+static inline void cx23885_irq_disable_all(struct cx23885_dev *dev)
+{
+	cx23885_irq_disable(dev, 0xffffffff);
+}
+
+void cx23885_irq_remove(struct cx23885_dev *dev, u32 mask)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&dev->pci_irqmask_lock, flags);
+
+	dev->pci_irqmask &= ~mask;
+	cx_clear(PCI_INT_MSK, mask);
+
+	spin_unlock_irqrestore(&dev->pci_irqmask_lock, flags);
+}
+
+static u32 cx23885_irq_get_mask(struct cx23885_dev *dev)
+{
+	u32 v;
+	unsigned long flags;
+	spin_lock_irqsave(&dev->pci_irqmask_lock, flags);
+
+	v = cx_read(PCI_INT_MSK);
+
+	spin_unlock_irqrestore(&dev->pci_irqmask_lock, flags);
+	return v;
+}
+
+static int cx23885_risc_decode(u32 risc)
+{
+	static char *instr[16] = {
+		[RISC_SYNC    >> 28] = "sync",
+		[RISC_WRITE   >> 28] = "write",
+		[RISC_WRITEC  >> 28] = "writec",
+		[RISC_READ    >> 28] = "read",
+		[RISC_READC   >> 28] = "readc",
+		[RISC_JUMP    >> 28] = "jump",
+		[RISC_SKIP    >> 28] = "skip",
+		[RISC_WRITERM >> 28] = "writerm",
+		[RISC_WRITECM >> 28] = "writecm",
+		[RISC_WRITECR >> 28] = "writecr",
+	};
+	static int incr[16] = {
+		[RISC_WRITE   >> 28] = 3,
+		[RISC_JUMP    >> 28] = 3,
+		[RISC_SKIP    >> 28] = 1,
+		[RISC_SYNC    >> 28] = 1,
+		[RISC_WRITERM >> 28] = 3,
+		[RISC_WRITECM >> 28] = 3,
+		[RISC_WRITECR >> 28] = 4,
+	};
+	static char *bits[] = {
+		"12",   "13",   "14",   "resync",
+		"cnt0", "cnt1", "18",   "19",
+		"20",   "21",   "22",   "23",
+		"irq1", "irq2", "eol",  "sol",
+	};
+	int i;
+
+	printk("0x%08x [ %s", risc,
+	       instr[risc >> 28] ? instr[risc >> 28] : "INVALID");
+	for (i = ARRAY_SIZE(bits) - 1; i >= 0; i--)
+		if (risc & (1 << (i + 12)))
+			printk(" %s", bits[i]);
+	printk(" count=%d ]\n", risc & 0xfff);
+	return incr[risc >> 28] ? incr[risc >> 28] : 1;
+}
+
+void cx23885_wakeup(struct cx23885_tsport *port,
+			   struct cx23885_dmaqueue *q, u32 count)
+{
+	struct cx23885_dev *dev = port->dev;
+	struct cx23885_buffer *buf;
+	int bc;
+
+	for (bc = 0;; bc++) {
+		if (list_empty(&q->active))
+			break;
+		buf = list_entry(q->active.next,
+				 struct cx23885_buffer, vb.queue);
+
+		/* count comes from the hw and is is 16bit wide --
+		 * this trick handles wrap-arounds correctly for
+		 * up to 32767 buffers in flight... */
+		if ((s16) (count - buf->count) < 0)
+			break;
+
+		do_gettimeofday(&buf->vb.ts);
+		dprintk(2, "[%p/%d] wakeup reg=%d buf=%d\n", buf, buf->vb.i,
+			count, buf->count);
+		buf->vb.state = VIDEOBUF_DONE;
+		list_del(&buf->vb.queue);
+		wake_up(&buf->vb.done);
+	}
+	if (list_empty(&q->active))
+		del_timer(&q->timeout);
+	else
+		mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT);
+	if (bc != 1)
+		printk(KERN_WARNING "%s: %d buffers handled (should be 1)\n",
+		       __func__, bc);
+}
+
+int cx23885_sram_channel_setup(struct cx23885_dev *dev,
+				      struct sram_channel *ch,
+				      unsigned int bpl, u32 risc)
+{
+	unsigned int i, lines;
+	u32 cdt;
+
+	if (ch->cmds_start == 0) {
+		dprintk(1, "%s() Erasing channel [%s]\n", __func__,
+			ch->name);
+		cx_write(ch->ptr1_reg, 0);
+		cx_write(ch->ptr2_reg, 0);
+		cx_write(ch->cnt2_reg, 0);
+		cx_write(ch->cnt1_reg, 0);
+		return 0;
+	} else {
+		dprintk(1, "%s() Configuring channel [%s]\n", __func__,
+			ch->name);
+	}
+
+	bpl   = (bpl + 7) & ~7; /* alignment */
+	cdt   = ch->cdt;
+	lines = ch->fifo_size / bpl;
+	if (lines > 6)
+		lines = 6;
+	BUG_ON(lines < 2);
+
+	cx_write(8 + 0, RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+	cx_write(8 + 4, 8);
+	cx_write(8 + 8, 0);
+
+	/* write CDT */
+	for (i = 0; i < lines; i++) {
+		dprintk(2, "%s() 0x%08x <- 0x%08x\n", __func__, cdt + 16*i,
+			ch->fifo_start + bpl*i);
+		cx_write(cdt + 16*i, ch->fifo_start + bpl*i);
+		cx_write(cdt + 16*i +  4, 0);
+		cx_write(cdt + 16*i +  8, 0);
+		cx_write(cdt + 16*i + 12, 0);
+	}
+
+	/* write CMDS */
+	if (ch->jumponly)
+		cx_write(ch->cmds_start + 0, 8);
+	else
+		cx_write(ch->cmds_start + 0, risc);
+	cx_write(ch->cmds_start +  4, 0); /* 64 bits 63-32 */
+	cx_write(ch->cmds_start +  8, cdt);
+	cx_write(ch->cmds_start + 12, (lines*16) >> 3);
+	cx_write(ch->cmds_start + 16, ch->ctrl_start);
+	if (ch->jumponly)
+		cx_write(ch->cmds_start + 20, 0x80000000 | (64 >> 2));
+	else
+		cx_write(ch->cmds_start + 20, 64 >> 2);
+	for (i = 24; i < 80; i += 4)
+		cx_write(ch->cmds_start + i, 0);
+
+	/* fill registers */
+	cx_write(ch->ptr1_reg, ch->fifo_start);
+	cx_write(ch->ptr2_reg, cdt);
+	cx_write(ch->cnt2_reg, (lines*16) >> 3);
+	cx_write(ch->cnt1_reg, (bpl >> 3) - 1);
+
+	dprintk(2, "[bridge %d] sram setup %s: bpl=%d lines=%d\n",
+		dev->bridge,
+		ch->name,
+		bpl,
+		lines);
+
+	return 0;
+}
+
+void cx23885_sram_channel_dump(struct cx23885_dev *dev,
+				      struct sram_channel *ch)
+{
+	static char *name[] = {
+		"init risc lo",
+		"init risc hi",
+		"cdt base",
+		"cdt size",
+		"iq base",
+		"iq size",
+		"risc pc lo",
+		"risc pc hi",
+		"iq wr ptr",
+		"iq rd ptr",
+		"cdt current",
+		"pci target lo",
+		"pci target hi",
+		"line / byte",
+	};
+	u32 risc;
+	unsigned int i, j, n;
+
+	printk(KERN_WARNING "%s: %s - dma channel status dump\n",
+	       dev->name, ch->name);
+	for (i = 0; i < ARRAY_SIZE(name); i++)
+		printk(KERN_WARNING "%s:   cmds: %-15s: 0x%08x\n",
+		       dev->name, name[i],
+		       cx_read(ch->cmds_start + 4*i));
+
+	for (i = 0; i < 4; i++) {
+		risc = cx_read(ch->cmds_start + 4 * (i + 14));
+		printk(KERN_WARNING "%s:   risc%d: ", dev->name, i);
+		cx23885_risc_decode(risc);
+	}
+	for (i = 0; i < (64 >> 2); i += n) {
+		risc = cx_read(ch->ctrl_start + 4 * i);
+		/* No consideration for bits 63-32 */
+
+		printk(KERN_WARNING "%s:   (0x%08x) iq %x: ", dev->name,
+		       ch->ctrl_start + 4 * i, i);
+		n = cx23885_risc_decode(risc);
+		for (j = 1; j < n; j++) {
+			risc = cx_read(ch->ctrl_start + 4 * (i + j));
+			printk(KERN_WARNING "%s:   iq %x: 0x%08x [ arg #%d ]\n",
+			       dev->name, i+j, risc, j);
+		}
+	}
+
+	printk(KERN_WARNING "%s: fifo: 0x%08x -> 0x%x\n",
+	       dev->name, ch->fifo_start, ch->fifo_start+ch->fifo_size);
+	printk(KERN_WARNING "%s: ctrl: 0x%08x -> 0x%x\n",
+	       dev->name, ch->ctrl_start, ch->ctrl_start + 6*16);
+	printk(KERN_WARNING "%s:   ptr1_reg: 0x%08x\n",
+	       dev->name, cx_read(ch->ptr1_reg));
+	printk(KERN_WARNING "%s:   ptr2_reg: 0x%08x\n",
+	       dev->name, cx_read(ch->ptr2_reg));
+	printk(KERN_WARNING "%s:   cnt1_reg: 0x%08x\n",
+	       dev->name, cx_read(ch->cnt1_reg));
+	printk(KERN_WARNING "%s:   cnt2_reg: 0x%08x\n",
+	       dev->name, cx_read(ch->cnt2_reg));
+}
+
+static void cx23885_risc_disasm(struct cx23885_tsport *port,
+				struct btcx_riscmem *risc)
+{
+	struct cx23885_dev *dev = port->dev;
+	unsigned int i, j, n;
+
+	printk(KERN_INFO "%s: risc disasm: %p [dma=0x%08lx]\n",
+	       dev->name, risc->cpu, (unsigned long)risc->dma);
+	for (i = 0; i < (risc->size >> 2); i += n) {
+		printk(KERN_INFO "%s:   %04d: ", dev->name, i);
+		n = cx23885_risc_decode(le32_to_cpu(risc->cpu[i]));
+		for (j = 1; j < n; j++)
+			printk(KERN_INFO "%s:   %04d: 0x%08x [ arg #%d ]\n",
+			       dev->name, i + j, risc->cpu[i + j], j);
+		if (risc->cpu[i] == cpu_to_le32(RISC_JUMP))
+			break;
+	}
+}
+
+static void cx23885_shutdown(struct cx23885_dev *dev)
+{
+	/* disable RISC controller */
+	cx_write(DEV_CNTRL2, 0);
+
+	/* Disable all IR activity */
+	cx_write(IR_CNTRL_REG, 0);
+
+	/* Disable Video A/B activity */
+	cx_write(VID_A_DMA_CTL, 0);
+	cx_write(VID_B_DMA_CTL, 0);
+	cx_write(VID_C_DMA_CTL, 0);
+
+	/* Disable Audio activity */
+	cx_write(AUD_INT_DMA_CTL, 0);
+	cx_write(AUD_EXT_DMA_CTL, 0);
+
+	/* Disable Serial port */
+	cx_write(UART_CTL, 0);
+
+	/* Disable Interrupts */
+	cx23885_irq_disable_all(dev);
+	cx_write(VID_A_INT_MSK, 0);
+	cx_write(VID_B_INT_MSK, 0);
+	cx_write(VID_C_INT_MSK, 0);
+	cx_write(AUDIO_INT_INT_MSK, 0);
+	cx_write(AUDIO_EXT_INT_MSK, 0);
+
+}
+
+static void cx23885_reset(struct cx23885_dev *dev)
+{
+	dprintk(1, "%s()\n", __func__);
+
+	cx23885_shutdown(dev);
+
+	cx_write(PCI_INT_STAT, 0xffffffff);
+	cx_write(VID_A_INT_STAT, 0xffffffff);
+	cx_write(VID_B_INT_STAT, 0xffffffff);
+	cx_write(VID_C_INT_STAT, 0xffffffff);
+	cx_write(AUDIO_INT_INT_STAT, 0xffffffff);
+	cx_write(AUDIO_EXT_INT_STAT, 0xffffffff);
+	cx_write(CLK_DELAY, cx_read(CLK_DELAY) & 0x80000000);
+	cx_write(PAD_CTRL, 0x00500300);
+
+	mdelay(100);
+
+	cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH01],
+		720*4, 0);
+	cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH02], 128, 0);
+	cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH03],
+		188*4, 0);
+	cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH04], 128, 0);
+	cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH05], 128, 0);
+	cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH06],
+		188*4, 0);
+	cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH07], 128, 0);
+	cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH08], 128, 0);
+	cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH09], 128, 0);
+
+	cx23885_gpio_setup(dev);
+}
+
+
+static int cx23885_pci_quirks(struct cx23885_dev *dev)
+{
+	dprintk(1, "%s()\n", __func__);
+
+	/* The cx23885 bridge has a weird bug which causes NMI to be asserted
+	 * when DMA begins if RDR_TLCTL0 bit4 is not cleared. It does not
+	 * occur on the cx23887 bridge.
+	 */
+	if (dev->bridge == CX23885_BRIDGE_885)
+		cx_clear(RDR_TLCTL0, 1 << 4);
+
+	return 0;
+}
+
+static int get_resources(struct cx23885_dev *dev)
+{
+	if (request_mem_region(pci_resource_start(dev->pci, 0),
+			       pci_resource_len(dev->pci, 0),
+			       dev->name))
+		return 0;
+
+	printk(KERN_ERR "%s: can't get MMIO memory @ 0x%llx\n",
+		dev->name, (unsigned long long)pci_resource_start(dev->pci, 0));
+
+	return -EBUSY;
+}
+
+static void cx23885_timeout(unsigned long data);
+int cx23885_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
+				u32 reg, u32 mask, u32 value);
+
+static int cx23885_init_tsport(struct cx23885_dev *dev,
+	struct cx23885_tsport *port, int portno)
+{
+	dprintk(1, "%s(portno=%d)\n", __func__, portno);
+
+	/* Transport bus init dma queue  - Common settings */
+	port->dma_ctl_val        = 0x11; /* Enable RISC controller and Fifo */
+	port->ts_int_msk_val     = 0x1111; /* TS port bits for RISC */
+	port->vld_misc_val       = 0x0;
+	port->hw_sop_ctrl_val    = (0x47 << 16 | 188 << 4);
+
+	spin_lock_init(&port->slock);
+	port->dev = dev;
+	port->nr = portno;
+
+	INIT_LIST_HEAD(&port->mpegq.active);
+	INIT_LIST_HEAD(&port->mpegq.queued);
+	port->mpegq.timeout.function = cx23885_timeout;
+	port->mpegq.timeout.data = (unsigned long)port;
+	init_timer(&port->mpegq.timeout);
+
+	mutex_init(&port->frontends.lock);
+	INIT_LIST_HEAD(&port->frontends.felist);
+	port->frontends.active_fe_id = 0;
+
+	/* This should be hardcoded allow a single frontend
+	 * attachment to this tsport, keeping the -dvb.c
+	 * code clean and safe.
+	 */
+	if (!port->num_frontends)
+		port->num_frontends = 1;
+
+	switch (portno) {
+	case 1:
+		port->reg_gpcnt          = VID_B_GPCNT;
+		port->reg_gpcnt_ctl      = VID_B_GPCNT_CTL;
+		port->reg_dma_ctl        = VID_B_DMA_CTL;
+		port->reg_lngth          = VID_B_LNGTH;
+		port->reg_hw_sop_ctrl    = VID_B_HW_SOP_CTL;
+		port->reg_gen_ctrl       = VID_B_GEN_CTL;
+		port->reg_bd_pkt_status  = VID_B_BD_PKT_STATUS;
+		port->reg_sop_status     = VID_B_SOP_STATUS;
+		port->reg_fifo_ovfl_stat = VID_B_FIFO_OVFL_STAT;
+		port->reg_vld_misc       = VID_B_VLD_MISC;
+		port->reg_ts_clk_en      = VID_B_TS_CLK_EN;
+		port->reg_src_sel        = VID_B_SRC_SEL;
+		port->reg_ts_int_msk     = VID_B_INT_MSK;
+		port->reg_ts_int_stat    = VID_B_INT_STAT;
+		port->sram_chno          = SRAM_CH03; /* VID_B */
+		port->pci_irqmask        = 0x02; /* VID_B bit1 */
+		break;
+	case 2:
+		port->reg_gpcnt          = VID_C_GPCNT;
+		port->reg_gpcnt_ctl      = VID_C_GPCNT_CTL;
+		port->reg_dma_ctl        = VID_C_DMA_CTL;
+		port->reg_lngth          = VID_C_LNGTH;
+		port->reg_hw_sop_ctrl    = VID_C_HW_SOP_CTL;
+		port->reg_gen_ctrl       = VID_C_GEN_CTL;
+		port->reg_bd_pkt_status  = VID_C_BD_PKT_STATUS;
+		port->reg_sop_status     = VID_C_SOP_STATUS;
+		port->reg_fifo_ovfl_stat = VID_C_FIFO_OVFL_STAT;
+		port->reg_vld_misc       = VID_C_VLD_MISC;
+		port->reg_ts_clk_en      = VID_C_TS_CLK_EN;
+		port->reg_src_sel        = 0;
+		port->reg_ts_int_msk     = VID_C_INT_MSK;
+		port->reg_ts_int_stat    = VID_C_INT_STAT;
+		port->sram_chno          = SRAM_CH06; /* VID_C */
+		port->pci_irqmask        = 0x04; /* VID_C bit2 */
+		break;
+	default:
+		BUG();
+	}
+
+	cx23885_risc_stopper(dev->pci, &port->mpegq.stopper,
+		     port->reg_dma_ctl, port->dma_ctl_val, 0x00);
+
+	return 0;
+}
+
+static void cx23885_dev_checkrevision(struct cx23885_dev *dev)
+{
+	switch (cx_read(RDR_CFG2) & 0xff) {
+	case 0x00:
+		/* cx23885 */
+		dev->hwrevision = 0xa0;
+		break;
+	case 0x01:
+		/* CX23885-12Z */
+		dev->hwrevision = 0xa1;
+		break;
+	case 0x02:
+		/* CX23885-13Z/14Z */
+		dev->hwrevision = 0xb0;
+		break;
+	case 0x03:
+		if (dev->pci->device == 0x8880) {
+			/* CX23888-21Z/22Z */
+			dev->hwrevision = 0xc0;
+		} else {
+			/* CX23885-14Z */
+			dev->hwrevision = 0xa4;
+		}
+		break;
+	case 0x04:
+		if (dev->pci->device == 0x8880) {
+			/* CX23888-31Z */
+			dev->hwrevision = 0xd0;
+		} else {
+			/* CX23885-15Z, CX23888-31Z */
+			dev->hwrevision = 0xa5;
+		}
+		break;
+	case 0x0e:
+		/* CX23887-15Z */
+		dev->hwrevision = 0xc0;
+		break;
+	case 0x0f:
+		/* CX23887-14Z */
+		dev->hwrevision = 0xb1;
+		break;
+	default:
+		printk(KERN_ERR "%s() New hardware revision found 0x%x\n",
+			__func__, dev->hwrevision);
+	}
+	if (dev->hwrevision)
+		printk(KERN_INFO "%s() Hardware revision = 0x%02x\n",
+			__func__, dev->hwrevision);
+	else
+		printk(KERN_ERR "%s() Hardware revision unknown 0x%x\n",
+			__func__, dev->hwrevision);
+}
+
+/* Find the first v4l2_subdev member of the group id in hw */
+struct v4l2_subdev *cx23885_find_hw(struct cx23885_dev *dev, u32 hw)
+{
+	struct v4l2_subdev *result = NULL;
+	struct v4l2_subdev *sd;
+
+	spin_lock(&dev->v4l2_dev.lock);
+	v4l2_device_for_each_subdev(sd, &dev->v4l2_dev) {
+		if (sd->grp_id == hw) {
+			result = sd;
+			break;
+		}
+	}
+	spin_unlock(&dev->v4l2_dev.lock);
+	return result;
+}
+
+static int cx23885_dev_setup(struct cx23885_dev *dev)
+{
+	int i;
+
+	spin_lock_init(&dev->pci_irqmask_lock);
+
+	mutex_init(&dev->lock);
+	mutex_init(&dev->gpio_lock);
+
+	atomic_inc(&dev->refcount);
+
+	dev->nr = cx23885_devcount++;
+	sprintf(dev->name, "cx23885[%d]", dev->nr);
+
+	/* Configure the internal memory */
+	if (dev->pci->device == 0x8880) {
+		/* Could be 887 or 888, assume a default */
+		dev->bridge = CX23885_BRIDGE_887;
+		/* Apply a sensible clock frequency for the PCIe bridge */
+		dev->clk_freq = 25000000;
+		dev->sram_channels = cx23887_sram_channels;
+	} else
+	if (dev->pci->device == 0x8852) {
+		dev->bridge = CX23885_BRIDGE_885;
+		/* Apply a sensible clock frequency for the PCIe bridge */
+		dev->clk_freq = 28000000;
+		dev->sram_channels = cx23885_sram_channels;
+	} else
+		BUG();
+
+	dprintk(1, "%s() Memory configured for PCIe bridge type %d\n",
+		__func__, dev->bridge);
+
+	/* board config */
+	dev->board = UNSET;
+	if (card[dev->nr] < cx23885_bcount)
+		dev->board = card[dev->nr];
+	for (i = 0; UNSET == dev->board  &&  i < cx23885_idcount; i++)
+		if (dev->pci->subsystem_vendor == cx23885_subids[i].subvendor &&
+		    dev->pci->subsystem_device == cx23885_subids[i].subdevice)
+			dev->board = cx23885_subids[i].card;
+	if (UNSET == dev->board) {
+		dev->board = CX23885_BOARD_UNKNOWN;
+		cx23885_card_list(dev);
+	}
+
+	/* If the user specific a clk freq override, apply it */
+	if (cx23885_boards[dev->board].clk_freq > 0)
+		dev->clk_freq = cx23885_boards[dev->board].clk_freq;
+
+	dev->pci_bus  = dev->pci->bus->number;
+	dev->pci_slot = PCI_SLOT(dev->pci->devfn);
+	cx23885_irq_add(dev, 0x001f00);
+
+	/* External Master 1 Bus */
+	dev->i2c_bus[0].nr = 0;
+	dev->i2c_bus[0].dev = dev;
+	dev->i2c_bus[0].reg_stat  = I2C1_STAT;
+	dev->i2c_bus[0].reg_ctrl  = I2C1_CTRL;
+	dev->i2c_bus[0].reg_addr  = I2C1_ADDR;
+	dev->i2c_bus[0].reg_rdata = I2C1_RDATA;
+	dev->i2c_bus[0].reg_wdata = I2C1_WDATA;
+	dev->i2c_bus[0].i2c_period = (0x9d << 24); /* 100kHz */
+
+	/* External Master 2 Bus */
+	dev->i2c_bus[1].nr = 1;
+	dev->i2c_bus[1].dev = dev;
+	dev->i2c_bus[1].reg_stat  = I2C2_STAT;
+	dev->i2c_bus[1].reg_ctrl  = I2C2_CTRL;
+	dev->i2c_bus[1].reg_addr  = I2C2_ADDR;
+	dev->i2c_bus[1].reg_rdata = I2C2_RDATA;
+	dev->i2c_bus[1].reg_wdata = I2C2_WDATA;
+	dev->i2c_bus[1].i2c_period = (0x9d << 24); /* 100kHz */
+
+	/* Internal Master 3 Bus */
+	dev->i2c_bus[2].nr = 2;
+	dev->i2c_bus[2].dev = dev;
+	dev->i2c_bus[2].reg_stat  = I2C3_STAT;
+	dev->i2c_bus[2].reg_ctrl  = I2C3_CTRL;
+	dev->i2c_bus[2].reg_addr  = I2C3_ADDR;
+	dev->i2c_bus[2].reg_rdata = I2C3_RDATA;
+	dev->i2c_bus[2].reg_wdata = I2C3_WDATA;
+	dev->i2c_bus[2].i2c_period = (0x07 << 24); /* 1.95MHz */
+
+	if ((cx23885_boards[dev->board].portb == CX23885_MPEG_DVB) ||
+		(cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER))
+		cx23885_init_tsport(dev, &dev->ts1, 1);
+
+	if ((cx23885_boards[dev->board].portc == CX23885_MPEG_DVB) ||
+		(cx23885_boards[dev->board].portc == CX23885_MPEG_ENCODER))
+		cx23885_init_tsport(dev, &dev->ts2, 2);
+
+	if (get_resources(dev) < 0) {
+		printk(KERN_ERR "CORE %s No more PCIe resources for "
+		       "subsystem: %04x:%04x\n",
+		       dev->name, dev->pci->subsystem_vendor,
+		       dev->pci->subsystem_device);
+
+		cx23885_devcount--;
+		return -ENODEV;
+	}
+
+	/* PCIe stuff */
+	dev->lmmio = ioremap(pci_resource_start(dev->pci, 0),
+			     pci_resource_len(dev->pci, 0));
+
+	dev->bmmio = (u8 __iomem *)dev->lmmio;
+
+	printk(KERN_INFO "CORE %s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
+	       dev->name, dev->pci->subsystem_vendor,
+	       dev->pci->subsystem_device, cx23885_boards[dev->board].name,
+	       dev->board, card[dev->nr] == dev->board ?
+	       "insmod option" : "autodetected");
+
+	cx23885_pci_quirks(dev);
+
+	/* Assume some sensible defaults */
+	dev->tuner_type = cx23885_boards[dev->board].tuner_type;
+	dev->tuner_addr = cx23885_boards[dev->board].tuner_addr;
+	dev->tuner_bus = cx23885_boards[dev->board].tuner_bus;
+	dev->radio_type = cx23885_boards[dev->board].radio_type;
+	dev->radio_addr = cx23885_boards[dev->board].radio_addr;
+
+	dprintk(1, "%s() tuner_type = 0x%x tuner_addr = 0x%x tuner_bus = %d\n",
+		__func__, dev->tuner_type, dev->tuner_addr, dev->tuner_bus);
+	dprintk(1, "%s() radio_type = 0x%x radio_addr = 0x%x\n",
+		__func__, dev->radio_type, dev->radio_addr);
+
+	/* The cx23417 encoder has GPIO's that need to be initialised
+	 * before DVB, so that demodulators and tuners are out of
+	 * reset before DVB uses them.
+	 */
+	if ((cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER) ||
+		(cx23885_boards[dev->board].portc == CX23885_MPEG_ENCODER))
+			cx23885_mc417_init(dev);
+
+	/* init hardware */
+	cx23885_reset(dev);
+
+	cx23885_i2c_register(&dev->i2c_bus[0]);
+	cx23885_i2c_register(&dev->i2c_bus[1]);
+	cx23885_i2c_register(&dev->i2c_bus[2]);
+	cx23885_card_setup(dev);
+	call_all(dev, core, s_power, 0);
+	cx23885_ir_init(dev);
+
+	if (cx23885_boards[dev->board].porta == CX23885_ANALOG_VIDEO) {
+		if (cx23885_video_register(dev) < 0) {
+			printk(KERN_ERR "%s() Failed to register analog "
+				"video adapters on VID_A\n", __func__);
+		}
+	}
+
+	if (cx23885_boards[dev->board].portb == CX23885_MPEG_DVB) {
+		if (cx23885_boards[dev->board].num_fds_portb)
+			dev->ts1.num_frontends =
+				cx23885_boards[dev->board].num_fds_portb;
+		if (cx23885_dvb_register(&dev->ts1) < 0) {
+			printk(KERN_ERR "%s() Failed to register dvb adapters on VID_B\n",
+			       __func__);
+		}
+	} else
+	if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER) {
+		if (cx23885_417_register(dev) < 0) {
+			printk(KERN_ERR
+				"%s() Failed to register 417 on VID_B\n",
+			       __func__);
+		}
+	}
+
+	if (cx23885_boards[dev->board].portc == CX23885_MPEG_DVB) {
+		if (cx23885_boards[dev->board].num_fds_portc)
+			dev->ts2.num_frontends =
+				cx23885_boards[dev->board].num_fds_portc;
+		if (cx23885_dvb_register(&dev->ts2) < 0) {
+			printk(KERN_ERR
+				"%s() Failed to register dvb on VID_C\n",
+			       __func__);
+		}
+	} else
+	if (cx23885_boards[dev->board].portc == CX23885_MPEG_ENCODER) {
+		if (cx23885_417_register(dev) < 0) {
+			printk(KERN_ERR
+				"%s() Failed to register 417 on VID_C\n",
+			       __func__);
+		}
+	}
+
+	cx23885_dev_checkrevision(dev);
+
+	/* disable MSI for NetUP cards, otherwise CI is not working */
+	if (cx23885_boards[dev->board].ci_type > 0)
+		cx_clear(RDR_RDRCTL1, 1 << 8);
+
+	switch (dev->board) {
+	case CX23885_BOARD_TEVII_S470:
+	case CX23885_BOARD_TEVII_S471:
+		cx_clear(RDR_RDRCTL1, 1 << 8);
+		break;
+	}
+
+	return 0;
+}
+
+static void cx23885_dev_unregister(struct cx23885_dev *dev)
+{
+	release_mem_region(pci_resource_start(dev->pci, 0),
+			   pci_resource_len(dev->pci, 0));
+
+	if (!atomic_dec_and_test(&dev->refcount))
+		return;
+
+	if (cx23885_boards[dev->board].porta == CX23885_ANALOG_VIDEO)
+		cx23885_video_unregister(dev);
+
+	if (cx23885_boards[dev->board].portb == CX23885_MPEG_DVB)
+		cx23885_dvb_unregister(&dev->ts1);
+
+	if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER)
+		cx23885_417_unregister(dev);
+
+	if (cx23885_boards[dev->board].portc == CX23885_MPEG_DVB)
+		cx23885_dvb_unregister(&dev->ts2);
+
+	if (cx23885_boards[dev->board].portc == CX23885_MPEG_ENCODER)
+		cx23885_417_unregister(dev);
+
+	cx23885_i2c_unregister(&dev->i2c_bus[2]);
+	cx23885_i2c_unregister(&dev->i2c_bus[1]);
+	cx23885_i2c_unregister(&dev->i2c_bus[0]);
+
+	iounmap(dev->lmmio);
+}
+
+static __le32 *cx23885_risc_field(__le32 *rp, struct scatterlist *sglist,
+			       unsigned int offset, u32 sync_line,
+			       unsigned int bpl, unsigned int padding,
+			       unsigned int lines,  unsigned int lpi)
+{
+	struct scatterlist *sg;
+	unsigned int line, todo, sol;
+
+	/* sync instruction */
+	if (sync_line != NO_SYNC_LINE)
+		*(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
+
+	/* scan lines */
+	sg = sglist;
+	for (line = 0; line < lines; line++) {
+		while (offset && offset >= sg_dma_len(sg)) {
+			offset -= sg_dma_len(sg);
+			sg++;
+		}
+
+		if (lpi && line > 0 && !(line % lpi))
+			sol = RISC_SOL | RISC_IRQ1 | RISC_CNT_INC;
+		else
+			sol = RISC_SOL;
+
+		if (bpl <= sg_dma_len(sg)-offset) {
+			/* fits into current chunk */
+			*(rp++) = cpu_to_le32(RISC_WRITE|sol|RISC_EOL|bpl);
+			*(rp++) = cpu_to_le32(sg_dma_address(sg)+offset);
+			*(rp++) = cpu_to_le32(0); /* bits 63-32 */
+			offset += bpl;
+		} else {
+			/* scanline needs to be split */
+			todo = bpl;
+			*(rp++) = cpu_to_le32(RISC_WRITE|sol|
+					    (sg_dma_len(sg)-offset));
+			*(rp++) = cpu_to_le32(sg_dma_address(sg)+offset);
+			*(rp++) = cpu_to_le32(0); /* bits 63-32 */
+			todo -= (sg_dma_len(sg)-offset);
+			offset = 0;
+			sg++;
+			while (todo > sg_dma_len(sg)) {
+				*(rp++) = cpu_to_le32(RISC_WRITE|
+						    sg_dma_len(sg));
+				*(rp++) = cpu_to_le32(sg_dma_address(sg));
+				*(rp++) = cpu_to_le32(0); /* bits 63-32 */
+				todo -= sg_dma_len(sg);
+				sg++;
+			}
+			*(rp++) = cpu_to_le32(RISC_WRITE|RISC_EOL|todo);
+			*(rp++) = cpu_to_le32(sg_dma_address(sg));
+			*(rp++) = cpu_to_le32(0); /* bits 63-32 */
+			offset += todo;
+		}
+		offset += padding;
+	}
+
+	return rp;
+}
+
+int cx23885_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
+			struct scatterlist *sglist, unsigned int top_offset,
+			unsigned int bottom_offset, unsigned int bpl,
+			unsigned int padding, unsigned int lines)
+{
+	u32 instructions, fields;
+	__le32 *rp;
+	int rc;
+
+	fields = 0;
+	if (UNSET != top_offset)
+		fields++;
+	if (UNSET != bottom_offset)
+		fields++;
+
+	/* estimate risc mem: worst case is one write per page border +
+	   one write per scan line + syncs + jump (all 2 dwords).  Padding
+	   can cause next bpl to start close to a page border.  First DMA
+	   region may be smaller than PAGE_SIZE */
+	/* write and jump need and extra dword */
+	instructions  = fields * (1 + ((bpl + padding) * lines)
+		/ PAGE_SIZE + lines);
+	instructions += 2;
+	rc = btcx_riscmem_alloc(pci, risc, instructions*12);
+	if (rc < 0)
+		return rc;
+
+	/* write risc instructions */
+	rp = risc->cpu;
+	if (UNSET != top_offset)
+		rp = cx23885_risc_field(rp, sglist, top_offset, 0,
+					bpl, padding, lines, 0);
+	if (UNSET != bottom_offset)
+		rp = cx23885_risc_field(rp, sglist, bottom_offset, 0x200,
+					bpl, padding, lines, 0);
+
+	/* save pointer to jmp instruction address */
+	risc->jmp = rp;
+	BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
+	return 0;
+}
+
+int cx23885_risc_databuffer(struct pci_dev *pci,
+				   struct btcx_riscmem *risc,
+				   struct scatterlist *sglist,
+				   unsigned int bpl,
+				   unsigned int lines, unsigned int lpi)
+{
+	u32 instructions;
+	__le32 *rp;
+	int rc;
+
+	/* estimate risc mem: worst case is one write per page border +
+	   one write per scan line + syncs + jump (all 2 dwords).  Here
+	   there is no padding and no sync.  First DMA region may be smaller
+	   than PAGE_SIZE */
+	/* Jump and write need an extra dword */
+	instructions  = 1 + (bpl * lines) / PAGE_SIZE + lines;
+	instructions += 1;
+
+	rc = btcx_riscmem_alloc(pci, risc, instructions*12);
+	if (rc < 0)
+		return rc;
+
+	/* write risc instructions */
+	rp = risc->cpu;
+	rp = cx23885_risc_field(rp, sglist, 0, NO_SYNC_LINE,
+				bpl, 0, lines, lpi);
+
+	/* save pointer to jmp instruction address */
+	risc->jmp = rp;
+	BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
+	return 0;
+}
+
+int cx23885_risc_vbibuffer(struct pci_dev *pci, struct btcx_riscmem *risc,
+			struct scatterlist *sglist, unsigned int top_offset,
+			unsigned int bottom_offset, unsigned int bpl,
+			unsigned int padding, unsigned int lines)
+{
+	u32 instructions, fields;
+	__le32 *rp;
+	int rc;
+
+	fields = 0;
+	if (UNSET != top_offset)
+		fields++;
+	if (UNSET != bottom_offset)
+		fields++;
+
+	/* estimate risc mem: worst case is one write per page border +
+	   one write per scan line + syncs + jump (all 2 dwords).  Padding
+	   can cause next bpl to start close to a page border.  First DMA
+	   region may be smaller than PAGE_SIZE */
+	/* write and jump need and extra dword */
+	instructions  = fields * (1 + ((bpl + padding) * lines)
+		/ PAGE_SIZE + lines);
+	instructions += 2;
+	rc = btcx_riscmem_alloc(pci, risc, instructions*12);
+	if (rc < 0)
+		return rc;
+	/* write risc instructions */
+	rp = risc->cpu;
+
+	/* Sync to line 6, so US CC line 21 will appear in line '12'
+	 * in the userland vbi payload */
+	if (UNSET != top_offset)
+		rp = cx23885_risc_field(rp, sglist, top_offset, 6,
+					bpl, padding, lines, 0);
+
+	if (UNSET != bottom_offset)
+		rp = cx23885_risc_field(rp, sglist, bottom_offset, 0x207,
+					bpl, padding, lines, 0);
+
+
+
+	/* save pointer to jmp instruction address */
+	risc->jmp = rp;
+	BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
+	return 0;
+}
+
+
+int cx23885_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
+				u32 reg, u32 mask, u32 value)
+{
+	__le32 *rp;
+	int rc;
+
+	rc = btcx_riscmem_alloc(pci, risc, 4*16);
+	if (rc < 0)
+		return rc;
+
+	/* write risc instructions */
+	rp = risc->cpu;
+	*(rp++) = cpu_to_le32(RISC_WRITECR  | RISC_IRQ2);
+	*(rp++) = cpu_to_le32(reg);
+	*(rp++) = cpu_to_le32(value);
+	*(rp++) = cpu_to_le32(mask);
+	*(rp++) = cpu_to_le32(RISC_JUMP);
+	*(rp++) = cpu_to_le32(risc->dma);
+	*(rp++) = cpu_to_le32(0); /* bits 63-32 */
+	return 0;
+}
+
+void cx23885_free_buffer(struct videobuf_queue *q, struct cx23885_buffer *buf)
+{
+	struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb);
+
+	BUG_ON(in_interrupt());
+	videobuf_waiton(q, &buf->vb, 0, 0);
+	videobuf_dma_unmap(q->dev, dma);
+	videobuf_dma_free(dma);
+	btcx_riscmem_free(to_pci_dev(q->dev), &buf->risc);
+	buf->vb.state = VIDEOBUF_NEEDS_INIT;
+}
+
+static void cx23885_tsport_reg_dump(struct cx23885_tsport *port)
+{
+	struct cx23885_dev *dev = port->dev;
+
+	dprintk(1, "%s() Register Dump\n", __func__);
+	dprintk(1, "%s() DEV_CNTRL2               0x%08X\n", __func__,
+		cx_read(DEV_CNTRL2));
+	dprintk(1, "%s() PCI_INT_MSK              0x%08X\n", __func__,
+		cx23885_irq_get_mask(dev));
+	dprintk(1, "%s() AUD_INT_INT_MSK          0x%08X\n", __func__,
+		cx_read(AUDIO_INT_INT_MSK));
+	dprintk(1, "%s() AUD_INT_DMA_CTL          0x%08X\n", __func__,
+		cx_read(AUD_INT_DMA_CTL));
+	dprintk(1, "%s() AUD_EXT_INT_MSK          0x%08X\n", __func__,
+		cx_read(AUDIO_EXT_INT_MSK));
+	dprintk(1, "%s() AUD_EXT_DMA_CTL          0x%08X\n", __func__,
+		cx_read(AUD_EXT_DMA_CTL));
+	dprintk(1, "%s() PAD_CTRL                 0x%08X\n", __func__,
+		cx_read(PAD_CTRL));
+	dprintk(1, "%s() ALT_PIN_OUT_SEL          0x%08X\n", __func__,
+		cx_read(ALT_PIN_OUT_SEL));
+	dprintk(1, "%s() GPIO2                    0x%08X\n", __func__,
+		cx_read(GPIO2));
+	dprintk(1, "%s() gpcnt(0x%08X)          0x%08X\n", __func__,
+		port->reg_gpcnt, cx_read(port->reg_gpcnt));
+	dprintk(1, "%s() gpcnt_ctl(0x%08X)      0x%08x\n", __func__,
+		port->reg_gpcnt_ctl, cx_read(port->reg_gpcnt_ctl));
+	dprintk(1, "%s() dma_ctl(0x%08X)        0x%08x\n", __func__,
+		port->reg_dma_ctl, cx_read(port->reg_dma_ctl));
+	if (port->reg_src_sel)
+		dprintk(1, "%s() src_sel(0x%08X)        0x%08x\n", __func__,
+			port->reg_src_sel, cx_read(port->reg_src_sel));
+	dprintk(1, "%s() lngth(0x%08X)          0x%08x\n", __func__,
+		port->reg_lngth, cx_read(port->reg_lngth));
+	dprintk(1, "%s() hw_sop_ctrl(0x%08X)    0x%08x\n", __func__,
+		port->reg_hw_sop_ctrl, cx_read(port->reg_hw_sop_ctrl));
+	dprintk(1, "%s() gen_ctrl(0x%08X)       0x%08x\n", __func__,
+		port->reg_gen_ctrl, cx_read(port->reg_gen_ctrl));
+	dprintk(1, "%s() bd_pkt_status(0x%08X)  0x%08x\n", __func__,
+		port->reg_bd_pkt_status, cx_read(port->reg_bd_pkt_status));
+	dprintk(1, "%s() sop_status(0x%08X)     0x%08x\n", __func__,
+		port->reg_sop_status, cx_read(port->reg_sop_status));
+	dprintk(1, "%s() fifo_ovfl_stat(0x%08X) 0x%08x\n", __func__,
+		port->reg_fifo_ovfl_stat, cx_read(port->reg_fifo_ovfl_stat));
+	dprintk(1, "%s() vld_misc(0x%08X)       0x%08x\n", __func__,
+		port->reg_vld_misc, cx_read(port->reg_vld_misc));
+	dprintk(1, "%s() ts_clk_en(0x%08X)      0x%08x\n", __func__,
+		port->reg_ts_clk_en, cx_read(port->reg_ts_clk_en));
+	dprintk(1, "%s() ts_int_msk(0x%08X)     0x%08x\n", __func__,
+		port->reg_ts_int_msk, cx_read(port->reg_ts_int_msk));
+}
+
+static int cx23885_start_dma(struct cx23885_tsport *port,
+			     struct cx23885_dmaqueue *q,
+			     struct cx23885_buffer   *buf)
+{
+	struct cx23885_dev *dev = port->dev;
+	u32 reg;
+
+	dprintk(1, "%s() w: %d, h: %d, f: %d\n", __func__,
+		buf->vb.width, buf->vb.height, buf->vb.field);
+
+	/* Stop the fifo and risc engine for this port */
+	cx_clear(port->reg_dma_ctl, port->dma_ctl_val);
+
+	/* setup fifo + format */
+	cx23885_sram_channel_setup(dev,
+				   &dev->sram_channels[port->sram_chno],
+				   port->ts_packet_size, buf->risc.dma);
+	if (debug > 5) {
+		cx23885_sram_channel_dump(dev,
+			&dev->sram_channels[port->sram_chno]);
+		cx23885_risc_disasm(port, &buf->risc);
+	}
+
+	/* write TS length to chip */
+	cx_write(port->reg_lngth, buf->vb.width);
+
+	if ((!(cx23885_boards[dev->board].portb & CX23885_MPEG_DVB)) &&
+		(!(cx23885_boards[dev->board].portc & CX23885_MPEG_DVB))) {
+		printk("%s() Unsupported .portb/c (0x%08x)/(0x%08x)\n",
+			__func__,
+			cx23885_boards[dev->board].portb,
+			cx23885_boards[dev->board].portc);
+		return -EINVAL;
+	}
+
+	if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER)
+		cx23885_av_clk(dev, 0);
+
+	udelay(100);
+
+	/* If the port supports SRC SELECT, configure it */
+	if (port->reg_src_sel)
+		cx_write(port->reg_src_sel, port->src_sel_val);
+
+	cx_write(port->reg_hw_sop_ctrl, port->hw_sop_ctrl_val);
+	cx_write(port->reg_ts_clk_en, port->ts_clk_en_val);
+	cx_write(port->reg_vld_misc, port->vld_misc_val);
+	cx_write(port->reg_gen_ctrl, port->gen_ctrl_val);
+	udelay(100);
+
+	/* NOTE: this is 2 (reserved) for portb, does it matter? */
+	/* reset counter to zero */
+	cx_write(port->reg_gpcnt_ctl, 3);
+	q->count = 1;
+
+	/* Set VIDB pins to input */
+	if (cx23885_boards[dev->board].portb == CX23885_MPEG_DVB) {
+		reg = cx_read(PAD_CTRL);
+		reg &= ~0x3; /* Clear TS1_OE & TS1_SOP_OE */
+		cx_write(PAD_CTRL, reg);
+	}
+
+	/* Set VIDC pins to input */
+	if (cx23885_boards[dev->board].portc == CX23885_MPEG_DVB) {
+		reg = cx_read(PAD_CTRL);
+		reg &= ~0x4; /* Clear TS2_SOP_OE */
+		cx_write(PAD_CTRL, reg);
+	}
+
+	if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER) {
+
+		reg = cx_read(PAD_CTRL);
+		reg = reg & ~0x1;    /* Clear TS1_OE */
+
+		/* FIXME, bit 2 writing here is questionable */
+		/* set TS1_SOP_OE and TS1_OE_HI */
+		reg = reg | 0xa;
+		cx_write(PAD_CTRL, reg);
+
+		/* FIXME and these two registers should be documented. */
+		cx_write(CLK_DELAY, cx_read(CLK_DELAY) | 0x80000011);
+		cx_write(ALT_PIN_OUT_SEL, 0x10100045);
+	}
+
+	switch (dev->bridge) {
+	case CX23885_BRIDGE_885:
+	case CX23885_BRIDGE_887:
+	case CX23885_BRIDGE_888:
+		/* enable irqs */
+		dprintk(1, "%s() enabling TS int's and DMA\n", __func__);
+		cx_set(port->reg_ts_int_msk,  port->ts_int_msk_val);
+		cx_set(port->reg_dma_ctl, port->dma_ctl_val);
+		cx23885_irq_add(dev, port->pci_irqmask);
+		cx23885_irq_enable_all(dev);
+		break;
+	default:
+		BUG();
+	}
+
+	cx_set(DEV_CNTRL2, (1<<5)); /* Enable RISC controller */
+
+	if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER)
+		cx23885_av_clk(dev, 1);
+
+	if (debug > 4)
+		cx23885_tsport_reg_dump(port);
+
+	return 0;
+}
+
+static int cx23885_stop_dma(struct cx23885_tsport *port)
+{
+	struct cx23885_dev *dev = port->dev;
+	u32 reg;
+
+	dprintk(1, "%s()\n", __func__);
+
+	/* Stop interrupts and DMA */
+	cx_clear(port->reg_ts_int_msk, port->ts_int_msk_val);
+	cx_clear(port->reg_dma_ctl, port->dma_ctl_val);
+
+	if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER) {
+
+		reg = cx_read(PAD_CTRL);
+
+		/* Set TS1_OE */
+		reg = reg | 0x1;
+
+		/* clear TS1_SOP_OE and TS1_OE_HI */
+		reg = reg & ~0xa;
+		cx_write(PAD_CTRL, reg);
+		cx_write(port->reg_src_sel, 0);
+		cx_write(port->reg_gen_ctrl, 8);
+
+	}
+
+	if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER)
+		cx23885_av_clk(dev, 0);
+
+	return 0;
+}
+
+int cx23885_restart_queue(struct cx23885_tsport *port,
+				struct cx23885_dmaqueue *q)
+{
+	struct cx23885_dev *dev = port->dev;
+	struct cx23885_buffer *buf;
+
+	dprintk(5, "%s()\n", __func__);
+	if (list_empty(&q->active)) {
+		struct cx23885_buffer *prev;
+		prev = NULL;
+
+		dprintk(5, "%s() queue is empty\n", __func__);
+
+		for (;;) {
+			if (list_empty(&q->queued))
+				return 0;
+			buf = list_entry(q->queued.next, struct cx23885_buffer,
+					 vb.queue);
+			if (NULL == prev) {
+				list_del(&buf->vb.queue);
+				list_add_tail(&buf->vb.queue, &q->active);
+				cx23885_start_dma(port, q, buf);
+				buf->vb.state = VIDEOBUF_ACTIVE;
+				buf->count    = q->count++;
+				mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
+				dprintk(5, "[%p/%d] restart_queue - f/active\n",
+					buf, buf->vb.i);
+
+			} else if (prev->vb.width  == buf->vb.width  &&
+				   prev->vb.height == buf->vb.height &&
+				   prev->fmt       == buf->fmt) {
+				list_del(&buf->vb.queue);
+				list_add_tail(&buf->vb.queue, &q->active);
+				buf->vb.state = VIDEOBUF_ACTIVE;
+				buf->count    = q->count++;
+				prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+				/* 64 bit bits 63-32 */
+				prev->risc.jmp[2] = cpu_to_le32(0);
+				dprintk(5, "[%p/%d] restart_queue - m/active\n",
+					buf, buf->vb.i);
+			} else {
+				return 0;
+			}
+			prev = buf;
+		}
+		return 0;
+	}
+
+	buf = list_entry(q->active.next, struct cx23885_buffer, vb.queue);
+	dprintk(2, "restart_queue [%p/%d]: restart dma\n",
+		buf, buf->vb.i);
+	cx23885_start_dma(port, q, buf);
+	list_for_each_entry(buf, &q->active, vb.queue)
+		buf->count = q->count++;
+	mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT);
+	return 0;
+}
+
+/* ------------------------------------------------------------------ */
+
+int cx23885_buf_prepare(struct videobuf_queue *q, struct cx23885_tsport *port,
+			struct cx23885_buffer *buf, enum v4l2_field field)
+{
+	struct cx23885_dev *dev = port->dev;
+	int size = port->ts_packet_size * port->ts_packet_count;
+	int rc;
+
+	dprintk(1, "%s: %p\n", __func__, buf);
+	if (0 != buf->vb.baddr  &&  buf->vb.bsize < size)
+		return -EINVAL;
+
+	if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
+		buf->vb.width  = port->ts_packet_size;
+		buf->vb.height = port->ts_packet_count;
+		buf->vb.size   = size;
+		buf->vb.field  = field /*V4L2_FIELD_TOP*/;
+
+		rc = videobuf_iolock(q, &buf->vb, NULL);
+		if (0 != rc)
+			goto fail;
+		cx23885_risc_databuffer(dev->pci, &buf->risc,
+					videobuf_to_dma(&buf->vb)->sglist,
+					buf->vb.width, buf->vb.height, 0);
+	}
+	buf->vb.state = VIDEOBUF_PREPARED;
+	return 0;
+
+ fail:
+	cx23885_free_buffer(q, buf);
+	return rc;
+}
+
+void cx23885_buf_queue(struct cx23885_tsport *port, struct cx23885_buffer *buf)
+{
+	struct cx23885_buffer    *prev;
+	struct cx23885_dev *dev = port->dev;
+	struct cx23885_dmaqueue  *cx88q = &port->mpegq;
+
+	/* add jump to stopper */
+	buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+	buf->risc.jmp[1] = cpu_to_le32(cx88q->stopper.dma);
+	buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */
+
+	if (list_empty(&cx88q->active)) {
+		dprintk(1, "queue is empty - first active\n");
+		list_add_tail(&buf->vb.queue, &cx88q->active);
+		cx23885_start_dma(port, cx88q, buf);
+		buf->vb.state = VIDEOBUF_ACTIVE;
+		buf->count    = cx88q->count++;
+		mod_timer(&cx88q->timeout, jiffies + BUFFER_TIMEOUT);
+		dprintk(1, "[%p/%d] %s - first active\n",
+			buf, buf->vb.i, __func__);
+	} else {
+		dprintk(1, "queue is not empty - append to active\n");
+		prev = list_entry(cx88q->active.prev, struct cx23885_buffer,
+				  vb.queue);
+		list_add_tail(&buf->vb.queue, &cx88q->active);
+		buf->vb.state = VIDEOBUF_ACTIVE;
+		buf->count    = cx88q->count++;
+		prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+		prev->risc.jmp[2] = cpu_to_le32(0); /* 64 bit bits 63-32 */
+		dprintk(1, "[%p/%d] %s - append to active\n",
+			 buf, buf->vb.i, __func__);
+	}
+}
+
+/* ----------------------------------------------------------- */
+
+static void do_cancel_buffers(struct cx23885_tsport *port, char *reason,
+			      int restart)
+{
+	struct cx23885_dev *dev = port->dev;
+	struct cx23885_dmaqueue *q = &port->mpegq;
+	struct cx23885_buffer *buf;
+	unsigned long flags;
+
+	spin_lock_irqsave(&port->slock, flags);
+	while (!list_empty(&q->active)) {
+		buf = list_entry(q->active.next, struct cx23885_buffer,
+				 vb.queue);
+		list_del(&buf->vb.queue);
+		buf->vb.state = VIDEOBUF_ERROR;
+		wake_up(&buf->vb.done);
+		dprintk(1, "[%p/%d] %s - dma=0x%08lx\n",
+			buf, buf->vb.i, reason, (unsigned long)buf->risc.dma);
+	}
+	if (restart) {
+		dprintk(1, "restarting queue\n");
+		cx23885_restart_queue(port, q);
+	}
+	spin_unlock_irqrestore(&port->slock, flags);
+}
+
+void cx23885_cancel_buffers(struct cx23885_tsport *port)
+{
+	struct cx23885_dev *dev = port->dev;
+	struct cx23885_dmaqueue *q = &port->mpegq;
+
+	dprintk(1, "%s()\n", __func__);
+	del_timer_sync(&q->timeout);
+	cx23885_stop_dma(port);
+	do_cancel_buffers(port, "cancel", 0);
+}
+
+static void cx23885_timeout(unsigned long data)
+{
+	struct cx23885_tsport *port = (struct cx23885_tsport *)data;
+	struct cx23885_dev *dev = port->dev;
+
+	dprintk(1, "%s()\n", __func__);
+
+	if (debug > 5)
+		cx23885_sram_channel_dump(dev,
+			&dev->sram_channels[port->sram_chno]);
+
+	cx23885_stop_dma(port);
+	do_cancel_buffers(port, "timeout", 1);
+}
+
+int cx23885_irq_417(struct cx23885_dev *dev, u32 status)
+{
+	/* FIXME: port1 assumption here. */
+	struct cx23885_tsport *port = &dev->ts1;
+	int count = 0;
+	int handled = 0;
+
+	if (status == 0)
+		return handled;
+
+	count = cx_read(port->reg_gpcnt);
+	dprintk(7, "status: 0x%08x  mask: 0x%08x count: 0x%x\n",
+		status, cx_read(port->reg_ts_int_msk), count);
+
+	if ((status & VID_B_MSK_BAD_PKT)         ||
+		(status & VID_B_MSK_OPC_ERR)     ||
+		(status & VID_B_MSK_VBI_OPC_ERR) ||
+		(status & VID_B_MSK_SYNC)        ||
+		(status & VID_B_MSK_VBI_SYNC)    ||
+		(status & VID_B_MSK_OF)          ||
+		(status & VID_B_MSK_VBI_OF)) {
+		printk(KERN_ERR "%s: V4L mpeg risc op code error, status "
+			"= 0x%x\n", dev->name, status);
+		if (status & VID_B_MSK_BAD_PKT)
+			dprintk(1, "        VID_B_MSK_BAD_PKT\n");
+		if (status & VID_B_MSK_OPC_ERR)
+			dprintk(1, "        VID_B_MSK_OPC_ERR\n");
+		if (status & VID_B_MSK_VBI_OPC_ERR)
+			dprintk(1, "        VID_B_MSK_VBI_OPC_ERR\n");
+		if (status & VID_B_MSK_SYNC)
+			dprintk(1, "        VID_B_MSK_SYNC\n");
+		if (status & VID_B_MSK_VBI_SYNC)
+			dprintk(1, "        VID_B_MSK_VBI_SYNC\n");
+		if (status & VID_B_MSK_OF)
+			dprintk(1, "        VID_B_MSK_OF\n");
+		if (status & VID_B_MSK_VBI_OF)
+			dprintk(1, "        VID_B_MSK_VBI_OF\n");
+
+		cx_clear(port->reg_dma_ctl, port->dma_ctl_val);
+		cx23885_sram_channel_dump(dev,
+			&dev->sram_channels[port->sram_chno]);
+		cx23885_417_check_encoder(dev);
+	} else if (status & VID_B_MSK_RISCI1) {
+		dprintk(7, "        VID_B_MSK_RISCI1\n");
+		spin_lock(&port->slock);
+		cx23885_wakeup(port, &port->mpegq, count);
+		spin_unlock(&port->slock);
+	} else if (status & VID_B_MSK_RISCI2) {
+		dprintk(7, "        VID_B_MSK_RISCI2\n");
+		spin_lock(&port->slock);
+		cx23885_restart_queue(port, &port->mpegq);
+		spin_unlock(&port->slock);
+	}
+	if (status) {
+		cx_write(port->reg_ts_int_stat, status);
+		handled = 1;
+	}
+
+	return handled;
+}
+
+static int cx23885_irq_ts(struct cx23885_tsport *port, u32 status)
+{
+	struct cx23885_dev *dev = port->dev;
+	int handled = 0;
+	u32 count;
+
+	if ((status & VID_BC_MSK_OPC_ERR) ||
+		(status & VID_BC_MSK_BAD_PKT) ||
+		(status & VID_BC_MSK_SYNC) ||
+		(status & VID_BC_MSK_OF)) {
+
+		if (status & VID_BC_MSK_OPC_ERR)
+			dprintk(7, " (VID_BC_MSK_OPC_ERR 0x%08x)\n",
+				VID_BC_MSK_OPC_ERR);
+
+		if (status & VID_BC_MSK_BAD_PKT)
+			dprintk(7, " (VID_BC_MSK_BAD_PKT 0x%08x)\n",
+				VID_BC_MSK_BAD_PKT);
+
+		if (status & VID_BC_MSK_SYNC)
+			dprintk(7, " (VID_BC_MSK_SYNC    0x%08x)\n",
+				VID_BC_MSK_SYNC);
+
+		if (status & VID_BC_MSK_OF)
+			dprintk(7, " (VID_BC_MSK_OF      0x%08x)\n",
+				VID_BC_MSK_OF);
+
+		printk(KERN_ERR "%s: mpeg risc op code error\n", dev->name);
+
+		cx_clear(port->reg_dma_ctl, port->dma_ctl_val);
+		cx23885_sram_channel_dump(dev,
+			&dev->sram_channels[port->sram_chno]);
+
+	} else if (status & VID_BC_MSK_RISCI1) {
+
+		dprintk(7, " (RISCI1            0x%08x)\n", VID_BC_MSK_RISCI1);
+
+		spin_lock(&port->slock);
+		count = cx_read(port->reg_gpcnt);
+		cx23885_wakeup(port, &port->mpegq, count);
+		spin_unlock(&port->slock);
+
+	} else if (status & VID_BC_MSK_RISCI2) {
+
+		dprintk(7, " (RISCI2            0x%08x)\n", VID_BC_MSK_RISCI2);
+
+		spin_lock(&port->slock);
+		cx23885_restart_queue(port, &port->mpegq);
+		spin_unlock(&port->slock);
+
+	}
+	if (status) {
+		cx_write(port->reg_ts_int_stat, status);
+		handled = 1;
+	}
+
+	return handled;
+}
+
+static irqreturn_t cx23885_irq(int irq, void *dev_id)
+{
+	struct cx23885_dev *dev = dev_id;
+	struct cx23885_tsport *ts1 = &dev->ts1;
+	struct cx23885_tsport *ts2 = &dev->ts2;
+	u32 pci_status, pci_mask;
+	u32 vida_status, vida_mask;
+	u32 audint_status, audint_mask;
+	u32 ts1_status, ts1_mask;
+	u32 ts2_status, ts2_mask;
+	int vida_count = 0, ts1_count = 0, ts2_count = 0, handled = 0;
+	int audint_count = 0;
+	bool subdev_handled;
+
+	pci_status = cx_read(PCI_INT_STAT);
+	pci_mask = cx23885_irq_get_mask(dev);
+	vida_status = cx_read(VID_A_INT_STAT);
+	vida_mask = cx_read(VID_A_INT_MSK);
+	audint_status = cx_read(AUDIO_INT_INT_STAT);
+	audint_mask = cx_read(AUDIO_INT_INT_MSK);
+	ts1_status = cx_read(VID_B_INT_STAT);
+	ts1_mask = cx_read(VID_B_INT_MSK);
+	ts2_status = cx_read(VID_C_INT_STAT);
+	ts2_mask = cx_read(VID_C_INT_MSK);
+
+	if ((pci_status == 0) && (ts2_status == 0) && (ts1_status == 0))
+		goto out;
+
+	vida_count = cx_read(VID_A_GPCNT);
+	audint_count = cx_read(AUD_INT_A_GPCNT);
+	ts1_count = cx_read(ts1->reg_gpcnt);
+	ts2_count = cx_read(ts2->reg_gpcnt);
+	dprintk(7, "pci_status: 0x%08x  pci_mask: 0x%08x\n",
+		pci_status, pci_mask);
+	dprintk(7, "vida_status: 0x%08x vida_mask: 0x%08x count: 0x%x\n",
+		vida_status, vida_mask, vida_count);
+	dprintk(7, "audint_status: 0x%08x audint_mask: 0x%08x count: 0x%x\n",
+		audint_status, audint_mask, audint_count);
+	dprintk(7, "ts1_status: 0x%08x  ts1_mask: 0x%08x count: 0x%x\n",
+		ts1_status, ts1_mask, ts1_count);
+	dprintk(7, "ts2_status: 0x%08x  ts2_mask: 0x%08x count: 0x%x\n",
+		ts2_status, ts2_mask, ts2_count);
+
+	if (pci_status & (PCI_MSK_RISC_RD | PCI_MSK_RISC_WR |
+			  PCI_MSK_AL_RD   | PCI_MSK_AL_WR   | PCI_MSK_APB_DMA |
+			  PCI_MSK_VID_C   | PCI_MSK_VID_B   | PCI_MSK_VID_A   |
+			  PCI_MSK_AUD_INT | PCI_MSK_AUD_EXT |
+			  PCI_MSK_GPIO0   | PCI_MSK_GPIO1   |
+			  PCI_MSK_AV_CORE | PCI_MSK_IR)) {
+
+		if (pci_status & PCI_MSK_RISC_RD)
+			dprintk(7, " (PCI_MSK_RISC_RD   0x%08x)\n",
+				PCI_MSK_RISC_RD);
+
+		if (pci_status & PCI_MSK_RISC_WR)
+			dprintk(7, " (PCI_MSK_RISC_WR   0x%08x)\n",
+				PCI_MSK_RISC_WR);
+
+		if (pci_status & PCI_MSK_AL_RD)
+			dprintk(7, " (PCI_MSK_AL_RD     0x%08x)\n",
+				PCI_MSK_AL_RD);
+
+		if (pci_status & PCI_MSK_AL_WR)
+			dprintk(7, " (PCI_MSK_AL_WR     0x%08x)\n",
+				PCI_MSK_AL_WR);
+
+		if (pci_status & PCI_MSK_APB_DMA)
+			dprintk(7, " (PCI_MSK_APB_DMA   0x%08x)\n",
+				PCI_MSK_APB_DMA);
+
+		if (pci_status & PCI_MSK_VID_C)
+			dprintk(7, " (PCI_MSK_VID_C     0x%08x)\n",
+				PCI_MSK_VID_C);
+
+		if (pci_status & PCI_MSK_VID_B)
+			dprintk(7, " (PCI_MSK_VID_B     0x%08x)\n",
+				PCI_MSK_VID_B);
+
+		if (pci_status & PCI_MSK_VID_A)
+			dprintk(7, " (PCI_MSK_VID_A     0x%08x)\n",
+				PCI_MSK_VID_A);
+
+		if (pci_status & PCI_MSK_AUD_INT)
+			dprintk(7, " (PCI_MSK_AUD_INT   0x%08x)\n",
+				PCI_MSK_AUD_INT);
+
+		if (pci_status & PCI_MSK_AUD_EXT)
+			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 (pci_status & PCI_MSK_AV_CORE)
+			dprintk(7, " (PCI_MSK_AV_CORE   0x%08x)\n",
+				PCI_MSK_AV_CORE);
+
+		if (pci_status & PCI_MSK_IR)
+			dprintk(7, " (PCI_MSK_IR        0x%08x)\n",
+				PCI_MSK_IR);
+	}
+
+	if (cx23885_boards[dev->board].ci_type == 1 &&
+			(pci_status & (PCI_MSK_GPIO1 | PCI_MSK_GPIO0)))
+		handled += netup_ci_slot_status(dev, pci_status);
+
+	if (cx23885_boards[dev->board].ci_type == 2 &&
+			(pci_status & PCI_MSK_GPIO0))
+		handled += altera_ci_irq(dev);
+
+	if (ts1_status) {
+		if (cx23885_boards[dev->board].portb == CX23885_MPEG_DVB)
+			handled += cx23885_irq_ts(ts1, ts1_status);
+		else
+		if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER)
+			handled += cx23885_irq_417(dev, ts1_status);
+	}
+
+	if (ts2_status) {
+		if (cx23885_boards[dev->board].portc == CX23885_MPEG_DVB)
+			handled += cx23885_irq_ts(ts2, ts2_status);
+		else
+		if (cx23885_boards[dev->board].portc == CX23885_MPEG_ENCODER)
+			handled += cx23885_irq_417(dev, ts2_status);
+	}
+
+	if (vida_status)
+		handled += cx23885_video_irq(dev, vida_status);
+
+	if (audint_status)
+		handled += cx23885_audio_irq(dev, audint_status, audint_mask);
+
+	if (pci_status & PCI_MSK_IR) {
+		subdev_handled = false;
+		v4l2_subdev_call(dev->sd_ir, core, interrupt_service_routine,
+				 pci_status, &subdev_handled);
+		if (subdev_handled)
+			handled++;
+	}
+
+	if ((pci_status & pci_mask) & PCI_MSK_AV_CORE) {
+		cx23885_irq_disable(dev, PCI_MSK_AV_CORE);
+		if (!schedule_work(&dev->cx25840_work))
+			printk(KERN_ERR "%s: failed to set up deferred work for"
+			       " AV Core/IR interrupt. Interrupt is disabled"
+			       " and won't be re-enabled\n", dev->name);
+		handled++;
+	}
+
+	if (handled)
+		cx_write(PCI_INT_STAT, pci_status);
+out:
+	return IRQ_RETVAL(handled);
+}
+
+static void cx23885_v4l2_dev_notify(struct v4l2_subdev *sd,
+				    unsigned int notification, void *arg)
+{
+	struct cx23885_dev *dev;
+
+	if (sd == NULL)
+		return;
+
+	dev = to_cx23885(sd->v4l2_dev);
+
+	switch (notification) {
+	case V4L2_SUBDEV_IR_RX_NOTIFY: /* Possibly called in an IRQ context */
+		if (sd == dev->sd_ir)
+			cx23885_ir_rx_v4l2_dev_notify(sd, *(u32 *)arg);
+		break;
+	case V4L2_SUBDEV_IR_TX_NOTIFY: /* Possibly called in an IRQ context */
+		if (sd == dev->sd_ir)
+			cx23885_ir_tx_v4l2_dev_notify(sd, *(u32 *)arg);
+		break;
+	}
+}
+
+static void cx23885_v4l2_dev_notify_init(struct cx23885_dev *dev)
+{
+	INIT_WORK(&dev->cx25840_work, cx23885_av_work_handler);
+	INIT_WORK(&dev->ir_rx_work, cx23885_ir_rx_work_handler);
+	INIT_WORK(&dev->ir_tx_work, cx23885_ir_tx_work_handler);
+	dev->v4l2_dev.notify = cx23885_v4l2_dev_notify;
+}
+
+static inline int encoder_on_portb(struct cx23885_dev *dev)
+{
+	return cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER;
+}
+
+static inline int encoder_on_portc(struct cx23885_dev *dev)
+{
+	return cx23885_boards[dev->board].portc == CX23885_MPEG_ENCODER;
+}
+
+/* Mask represents 32 different GPIOs, GPIO's are split into multiple
+ * registers depending on the board configuration (and whether the
+ * 417 encoder (wi it's own GPIO's) are present. Each GPIO bit will
+ * be pushed into the correct hardware register, regardless of the
+ * physical location. Certain registers are shared so we sanity check
+ * and report errors if we think we're tampering with a GPIo that might
+ * be assigned to the encoder (and used for the host bus).
+ *
+ * GPIO  2 thru  0 - On the cx23885 bridge
+ * GPIO 18 thru  3 - On the cx23417 host bus interface
+ * GPIO 23 thru 19 - On the cx25840 a/v core
+ */
+void cx23885_gpio_set(struct cx23885_dev *dev, u32 mask)
+{
+	if (mask & 0x7)
+		cx_set(GP0_IO, mask & 0x7);
+
+	if (mask & 0x0007fff8) {
+		if (encoder_on_portb(dev) || encoder_on_portc(dev))
+			printk(KERN_ERR
+				"%s: Setting GPIO on encoder ports\n",
+				dev->name);
+		cx_set(MC417_RWD, (mask & 0x0007fff8) >> 3);
+	}
+
+	/* TODO: 23-19 */
+	if (mask & 0x00f80000)
+		printk(KERN_INFO "%s: Unsupported\n", dev->name);
+}
+
+void cx23885_gpio_clear(struct cx23885_dev *dev, u32 mask)
+{
+	if (mask & 0x00000007)
+		cx_clear(GP0_IO, mask & 0x7);
+
+	if (mask & 0x0007fff8) {
+		if (encoder_on_portb(dev) || encoder_on_portc(dev))
+			printk(KERN_ERR
+				"%s: Clearing GPIO moving on encoder ports\n",
+				dev->name);
+		cx_clear(MC417_RWD, (mask & 0x7fff8) >> 3);
+	}
+
+	/* TODO: 23-19 */
+	if (mask & 0x00f80000)
+		printk(KERN_INFO "%s: Unsupported\n", dev->name);
+}
+
+u32 cx23885_gpio_get(struct cx23885_dev *dev, u32 mask)
+{
+	if (mask & 0x00000007)
+		return (cx_read(GP0_IO) >> 8) & mask & 0x7;
+
+	if (mask & 0x0007fff8) {
+		if (encoder_on_portb(dev) || encoder_on_portc(dev))
+			printk(KERN_ERR
+				"%s: Reading GPIO moving on encoder ports\n",
+				dev->name);
+		return (cx_read(MC417_RWD) & ((mask & 0x7fff8) >> 3)) << 3;
+	}
+
+	/* TODO: 23-19 */
+	if (mask & 0x00f80000)
+		printk(KERN_INFO "%s: Unsupported\n", dev->name);
+
+	return 0;
+}
+
+void cx23885_gpio_enable(struct cx23885_dev *dev, u32 mask, int asoutput)
+{
+	if ((mask & 0x00000007) && asoutput)
+		cx_set(GP0_IO, (mask & 0x7) << 16);
+	else if ((mask & 0x00000007) && !asoutput)
+		cx_clear(GP0_IO, (mask & 0x7) << 16);
+
+	if (mask & 0x0007fff8) {
+		if (encoder_on_portb(dev) || encoder_on_portc(dev))
+			printk(KERN_ERR
+				"%s: Enabling GPIO on encoder ports\n",
+				dev->name);
+	}
+
+	/* MC417_OEN is active low for output, write 1 for an input */
+	if ((mask & 0x0007fff8) && asoutput)
+		cx_clear(MC417_OEN, (mask & 0x7fff8) >> 3);
+
+	else if ((mask & 0x0007fff8) && !asoutput)
+		cx_set(MC417_OEN, (mask & 0x7fff8) >> 3);
+
+	/* TODO: 23-19 */
+}
+
+static int __devinit cx23885_initdev(struct pci_dev *pci_dev,
+				     const struct pci_device_id *pci_id)
+{
+	struct cx23885_dev *dev;
+	int err;
+
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (NULL == dev)
+		return -ENOMEM;
+
+	err = v4l2_device_register(&pci_dev->dev, &dev->v4l2_dev);
+	if (err < 0)
+		goto fail_free;
+
+	/* Prepare to handle notifications from subdevices */
+	cx23885_v4l2_dev_notify_init(dev);
+
+	/* pci init */
+	dev->pci = pci_dev;
+	if (pci_enable_device(pci_dev)) {
+		err = -EIO;
+		goto fail_unreg;
+	}
+
+	if (cx23885_dev_setup(dev) < 0) {
+		err = -EINVAL;
+		goto fail_unreg;
+	}
+
+	/* print pci info */
+	dev->pci_rev = pci_dev->revision;
+	pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER,  &dev->pci_lat);
+	printk(KERN_INFO "%s/0: found at %s, rev: %d, irq: %d, "
+	       "latency: %d, mmio: 0x%llx\n", dev->name,
+	       pci_name(pci_dev), dev->pci_rev, pci_dev->irq,
+	       dev->pci_lat,
+		(unsigned long long)pci_resource_start(pci_dev, 0));
+
+	pci_set_master(pci_dev);
+	if (!pci_dma_supported(pci_dev, 0xffffffff)) {
+		printk("%s/0: Oops: no 32bit PCI DMA ???\n", dev->name);
+		err = -EIO;
+		goto fail_irq;
+	}
+
+	err = request_irq(pci_dev->irq, cx23885_irq,
+			  IRQF_SHARED | IRQF_DISABLED, dev->name, dev);
+	if (err < 0) {
+		printk(KERN_ERR "%s: can't get IRQ %d\n",
+		       dev->name, pci_dev->irq);
+		goto fail_irq;
+	}
+
+	switch (dev->board) {
+	case CX23885_BOARD_NETUP_DUAL_DVBS2_CI:
+		cx23885_irq_add_enable(dev, PCI_MSK_GPIO1 | PCI_MSK_GPIO0);
+		break;
+	case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF:
+		cx23885_irq_add_enable(dev, PCI_MSK_GPIO0);
+		break;
+	}
+
+	/*
+	 * The CX2388[58] IR controller can start firing interrupts when
+	 * enabled, so these have to take place after the cx23885_irq() handler
+	 * is hooked up by the call to request_irq() above.
+	 */
+	cx23885_ir_pci_int_enable(dev);
+	cx23885_input_init(dev);
+
+	return 0;
+
+fail_irq:
+	cx23885_dev_unregister(dev);
+fail_unreg:
+	v4l2_device_unregister(&dev->v4l2_dev);
+fail_free:
+	kfree(dev);
+	return err;
+}
+
+static void __devexit cx23885_finidev(struct pci_dev *pci_dev)
+{
+	struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
+	struct cx23885_dev *dev = to_cx23885(v4l2_dev);
+
+	cx23885_input_fini(dev);
+	cx23885_ir_fini(dev);
+
+	cx23885_shutdown(dev);
+
+	pci_disable_device(pci_dev);
+
+	/* unregister stuff */
+	free_irq(pci_dev->irq, dev);
+
+	cx23885_dev_unregister(dev);
+	v4l2_device_unregister(v4l2_dev);
+	kfree(dev);
+}
+
+static struct pci_device_id cx23885_pci_tbl[] = {
+	{
+		/* CX23885 */
+		.vendor       = 0x14f1,
+		.device       = 0x8852,
+		.subvendor    = PCI_ANY_ID,
+		.subdevice    = PCI_ANY_ID,
+	}, {
+		/* CX23887 Rev 2 */
+		.vendor       = 0x14f1,
+		.device       = 0x8880,
+		.subvendor    = PCI_ANY_ID,
+		.subdevice    = PCI_ANY_ID,
+	}, {
+		/* --- end of list --- */
+	}
+};
+MODULE_DEVICE_TABLE(pci, cx23885_pci_tbl);
+
+static struct pci_driver cx23885_pci_driver = {
+	.name     = "cx23885",
+	.id_table = cx23885_pci_tbl,
+	.probe    = cx23885_initdev,
+	.remove   = __devexit_p(cx23885_finidev),
+	/* TODO */
+	.suspend  = NULL,
+	.resume   = NULL,
+};
+
+static int __init cx23885_init(void)
+{
+	printk(KERN_INFO "cx23885 driver version %s loaded\n",
+		CX23885_VERSION);
+	return pci_register_driver(&cx23885_pci_driver);
+}
+
+static void __exit cx23885_fini(void)
+{
+	pci_unregister_driver(&cx23885_pci_driver);
+}
+
+module_init(cx23885_init);
+module_exit(cx23885_fini);
diff --git a/drivers/media/pci/cx23885/cx23885-dvb.c b/drivers/media/pci/cx23885/cx23885-dvb.c
new file mode 100644
index 0000000..4379d8a
--- /dev/null
+++ b/drivers/media/pci/cx23885/cx23885-dvb.c
@@ -0,0 +1,1412 @@
+/*
+ *  Driver for the Conexant CX23885 PCIe bridge
+ *
+ *  Copyright (c) 2006 Steven Toth <stoth@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/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/fs.h>
+#include <linux/kthread.h>
+#include <linux/file.h>
+#include <linux/suspend.h>
+
+#include "cx23885.h"
+#include <media/v4l2-common.h>
+
+#include "dvb_ca_en50221.h"
+#include "s5h1409.h"
+#include "s5h1411.h"
+#include "mt2131.h"
+#include "tda8290.h"
+#include "tda18271.h"
+#include "lgdt330x.h"
+#include "xc4000.h"
+#include "xc5000.h"
+#include "max2165.h"
+#include "tda10048.h"
+#include "tuner-xc2028.h"
+#include "tuner-simple.h"
+#include "dib7000p.h"
+#include "dibx000_common.h"
+#include "zl10353.h"
+#include "stv0900.h"
+#include "stv0900_reg.h"
+#include "stv6110.h"
+#include "lnbh24.h"
+#include "cx24116.h"
+#include "cimax2.h"
+#include "lgs8gxx.h"
+#include "netup-eeprom.h"
+#include "netup-init.h"
+#include "lgdt3305.h"
+#include "atbm8830.h"
+#include "ds3000.h"
+#include "cx23885-f300.h"
+#include "altera-ci.h"
+#include "stv0367.h"
+#include "drxk.h"
+#include "mt2063.h"
+#include "stv090x.h"
+#include "stb6100.h"
+#include "stb6100_cfg.h"
+
+static unsigned int debug;
+
+#define dprintk(level, fmt, arg...)\
+	do { if (debug >= level)\
+		printk(KERN_DEBUG "%s/0: " fmt, dev->name, ## arg);\
+	} while (0)
+
+/* ------------------------------------------------------------------ */
+
+static unsigned int alt_tuner;
+module_param(alt_tuner, int, 0644);
+MODULE_PARM_DESC(alt_tuner, "Enable alternate tuner configuration");
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+/* ------------------------------------------------------------------ */
+
+static int dvb_buf_setup(struct videobuf_queue *q,
+			 unsigned int *count, unsigned int *size)
+{
+	struct cx23885_tsport *port = q->priv_data;
+
+	port->ts_packet_size  = 188 * 4;
+	port->ts_packet_count = 32;
+
+	*size  = port->ts_packet_size * port->ts_packet_count;
+	*count = 32;
+	return 0;
+}
+
+static int dvb_buf_prepare(struct videobuf_queue *q,
+			   struct videobuf_buffer *vb, enum v4l2_field field)
+{
+	struct cx23885_tsport *port = q->priv_data;
+	return cx23885_buf_prepare(q, port, (struct cx23885_buffer *)vb, field);
+}
+
+static void dvb_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
+{
+	struct cx23885_tsport *port = q->priv_data;
+	cx23885_buf_queue(port, (struct cx23885_buffer *)vb);
+}
+
+static void dvb_buf_release(struct videobuf_queue *q,
+			    struct videobuf_buffer *vb)
+{
+	cx23885_free_buffer(q, (struct cx23885_buffer *)vb);
+}
+
+static int cx23885_dvb_set_frontend(struct dvb_frontend *fe);
+
+static void cx23885_dvb_gate_ctrl(struct cx23885_tsport  *port, int open)
+{
+	struct videobuf_dvb_frontends *f;
+	struct videobuf_dvb_frontend *fe;
+
+	f = &port->frontends;
+
+	if (f->gate <= 1) /* undefined or fe0 */
+		fe = videobuf_dvb_get_frontend(f, 1);
+	else
+		fe = videobuf_dvb_get_frontend(f, f->gate);
+
+	if (fe && fe->dvb.frontend && fe->dvb.frontend->ops.i2c_gate_ctrl)
+		fe->dvb.frontend->ops.i2c_gate_ctrl(fe->dvb.frontend, open);
+
+	/*
+	 * FIXME: Improve this path to avoid calling the
+	 * cx23885_dvb_set_frontend() every time it passes here.
+	 */
+	cx23885_dvb_set_frontend(fe->dvb.frontend);
+}
+
+static struct videobuf_queue_ops dvb_qops = {
+	.buf_setup    = dvb_buf_setup,
+	.buf_prepare  = dvb_buf_prepare,
+	.buf_queue    = dvb_buf_queue,
+	.buf_release  = dvb_buf_release,
+};
+
+static struct s5h1409_config hauppauge_generic_config = {
+	.demod_address = 0x32 >> 1,
+	.output_mode   = S5H1409_SERIAL_OUTPUT,
+	.gpio          = S5H1409_GPIO_ON,
+	.qam_if        = 44000,
+	.inversion     = S5H1409_INVERSION_OFF,
+	.status_mode   = S5H1409_DEMODLOCKING,
+	.mpeg_timing   = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
+};
+
+static struct tda10048_config hauppauge_hvr1200_config = {
+	.demod_address    = 0x10 >> 1,
+	.output_mode      = TDA10048_SERIAL_OUTPUT,
+	.fwbulkwritelen   = TDA10048_BULKWRITE_200,
+	.inversion        = TDA10048_INVERSION_ON,
+	.dtv6_if_freq_khz = TDA10048_IF_3300,
+	.dtv7_if_freq_khz = TDA10048_IF_3800,
+	.dtv8_if_freq_khz = TDA10048_IF_4300,
+	.clk_freq_khz     = TDA10048_CLK_16000,
+};
+
+static struct tda10048_config hauppauge_hvr1210_config = {
+	.demod_address    = 0x10 >> 1,
+	.output_mode      = TDA10048_SERIAL_OUTPUT,
+	.fwbulkwritelen   = TDA10048_BULKWRITE_200,
+	.inversion        = TDA10048_INVERSION_ON,
+	.dtv6_if_freq_khz = TDA10048_IF_3300,
+	.dtv7_if_freq_khz = TDA10048_IF_3500,
+	.dtv8_if_freq_khz = TDA10048_IF_4000,
+	.clk_freq_khz     = TDA10048_CLK_16000,
+};
+
+static struct s5h1409_config hauppauge_ezqam_config = {
+	.demod_address = 0x32 >> 1,
+	.output_mode   = S5H1409_SERIAL_OUTPUT,
+	.gpio          = S5H1409_GPIO_OFF,
+	.qam_if        = 4000,
+	.inversion     = S5H1409_INVERSION_ON,
+	.status_mode   = S5H1409_DEMODLOCKING,
+	.mpeg_timing   = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
+};
+
+static struct s5h1409_config hauppauge_hvr1800lp_config = {
+	.demod_address = 0x32 >> 1,
+	.output_mode   = S5H1409_SERIAL_OUTPUT,
+	.gpio          = S5H1409_GPIO_OFF,
+	.qam_if        = 44000,
+	.inversion     = S5H1409_INVERSION_OFF,
+	.status_mode   = S5H1409_DEMODLOCKING,
+	.mpeg_timing   = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
+};
+
+static struct s5h1409_config hauppauge_hvr1500_config = {
+	.demod_address = 0x32 >> 1,
+	.output_mode   = S5H1409_SERIAL_OUTPUT,
+	.gpio          = S5H1409_GPIO_OFF,
+	.inversion     = S5H1409_INVERSION_OFF,
+	.status_mode   = S5H1409_DEMODLOCKING,
+	.mpeg_timing   = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
+};
+
+static struct mt2131_config hauppauge_generic_tunerconfig = {
+	0x61
+};
+
+static struct lgdt330x_config fusionhdtv_5_express = {
+	.demod_address = 0x0e,
+	.demod_chip = LGDT3303,
+	.serial_mpeg = 0x40,
+};
+
+static struct s5h1409_config hauppauge_hvr1500q_config = {
+	.demod_address = 0x32 >> 1,
+	.output_mode   = S5H1409_SERIAL_OUTPUT,
+	.gpio          = S5H1409_GPIO_ON,
+	.qam_if        = 44000,
+	.inversion     = S5H1409_INVERSION_OFF,
+	.status_mode   = S5H1409_DEMODLOCKING,
+	.mpeg_timing   = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
+};
+
+static struct s5h1409_config dvico_s5h1409_config = {
+	.demod_address = 0x32 >> 1,
+	.output_mode   = S5H1409_SERIAL_OUTPUT,
+	.gpio          = S5H1409_GPIO_ON,
+	.qam_if        = 44000,
+	.inversion     = S5H1409_INVERSION_OFF,
+	.status_mode   = S5H1409_DEMODLOCKING,
+	.mpeg_timing   = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
+};
+
+static struct s5h1411_config dvico_s5h1411_config = {
+	.output_mode   = S5H1411_SERIAL_OUTPUT,
+	.gpio          = S5H1411_GPIO_ON,
+	.qam_if        = S5H1411_IF_44000,
+	.vsb_if        = S5H1411_IF_44000,
+	.inversion     = S5H1411_INVERSION_OFF,
+	.status_mode   = S5H1411_DEMODLOCKING,
+	.mpeg_timing   = S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
+};
+
+static struct s5h1411_config hcw_s5h1411_config = {
+	.output_mode   = S5H1411_SERIAL_OUTPUT,
+	.gpio          = S5H1411_GPIO_OFF,
+	.vsb_if        = S5H1411_IF_44000,
+	.qam_if        = S5H1411_IF_4000,
+	.inversion     = S5H1411_INVERSION_ON,
+	.status_mode   = S5H1411_DEMODLOCKING,
+	.mpeg_timing   = S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
+};
+
+static struct xc5000_config hauppauge_hvr1500q_tunerconfig = {
+	.i2c_address      = 0x61,
+	.if_khz           = 5380,
+};
+
+static struct xc5000_config dvico_xc5000_tunerconfig = {
+	.i2c_address      = 0x64,
+	.if_khz           = 5380,
+};
+
+static struct tda829x_config tda829x_no_probe = {
+	.probe_tuner = TDA829X_DONT_PROBE,
+};
+
+static struct tda18271_std_map hauppauge_tda18271_std_map = {
+	.atsc_6   = { .if_freq = 5380, .agc_mode = 3, .std = 3,
+		      .if_lvl = 6, .rfagc_top = 0x37 },
+	.qam_6    = { .if_freq = 4000, .agc_mode = 3, .std = 0,
+		      .if_lvl = 6, .rfagc_top = 0x37 },
+};
+
+static struct tda18271_std_map hauppauge_hvr1200_tda18271_std_map = {
+	.dvbt_6   = { .if_freq = 3300, .agc_mode = 3, .std = 4,
+		      .if_lvl = 1, .rfagc_top = 0x37, },
+	.dvbt_7   = { .if_freq = 3800, .agc_mode = 3, .std = 5,
+		      .if_lvl = 1, .rfagc_top = 0x37, },
+	.dvbt_8   = { .if_freq = 4300, .agc_mode = 3, .std = 6,
+		      .if_lvl = 1, .rfagc_top = 0x37, },
+};
+
+static struct tda18271_config hauppauge_tda18271_config = {
+	.std_map = &hauppauge_tda18271_std_map,
+	.gate    = TDA18271_GATE_ANALOG,
+	.output_opt = TDA18271_OUTPUT_LT_OFF,
+};
+
+static struct tda18271_config hauppauge_hvr1200_tuner_config = {
+	.std_map = &hauppauge_hvr1200_tda18271_std_map,
+	.gate    = TDA18271_GATE_ANALOG,
+	.output_opt = TDA18271_OUTPUT_LT_OFF,
+};
+
+static struct tda18271_config hauppauge_hvr1210_tuner_config = {
+	.gate    = TDA18271_GATE_DIGITAL,
+	.output_opt = TDA18271_OUTPUT_LT_OFF,
+};
+
+static struct tda18271_std_map hauppauge_hvr127x_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 hauppauge_hvr127x_config = {
+	.std_map = &hauppauge_hvr127x_std_map,
+	.output_opt = TDA18271_OUTPUT_LT_OFF,
+};
+
+static struct lgdt3305_config hauppauge_lgdt3305_config = {
+	.i2c_addr           = 0x0e,
+	.mpeg_mode          = LGDT3305_MPEG_SERIAL,
+	.tpclk_edge         = LGDT3305_TPCLK_FALLING_EDGE,
+	.tpvalid_polarity   = LGDT3305_TP_VALID_HIGH,
+	.deny_i2c_rptr      = 1,
+	.spectral_inversion = 1,
+	.qam_if_khz         = 4000,
+	.vsb_if_khz         = 3250,
+};
+
+static struct dibx000_agc_config xc3028_agc_config = {
+	BAND_VHF | BAND_UHF,	/* band_caps */
+
+	/* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=0,
+	 * P_agc_inv_pwm1=0, P_agc_inv_pwm2=0,
+	 * P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0,
+	 * P_agc_nb_est=2, P_agc_write=0
+	 */
+	(0 << 15) | (0 << 14) | (0 << 11) | (0 << 10) | (0 << 9) | (0 << 8) |
+		(3 << 5) | (0 << 4) | (2 << 1) | (0 << 0), /* setup */
+
+	712,	/* inv_gain */
+	21,	/* time_stabiliz */
+
+	0,	/* alpha_level */
+	118,	/* thlock */
+
+	0,	/* wbd_inv */
+	2867,	/* wbd_ref */
+	0,	/* wbd_sel */
+	2,	/* wbd_alpha */
+
+	0,	/* agc1_max */
+	0,	/* agc1_min */
+	39718,	/* agc2_max */
+	9930,	/* agc2_min */
+	0,	/* agc1_pt1 */
+	0,	/* agc1_pt2 */
+	0,	/* agc1_pt3 */
+	0,	/* agc1_slope1 */
+	0,	/* agc1_slope2 */
+	0,	/* agc2_pt1 */
+	128,	/* agc2_pt2 */
+	29,	/* agc2_slope1 */
+	29,	/* agc2_slope2 */
+
+	17,	/* alpha_mant */
+	27,	/* alpha_exp */
+	23,	/* beta_mant */
+	51,	/* beta_exp */
+
+	1,	/* perform_agc_softsplit */
+};
+
+/* PLL Configuration for COFDM BW_MHz = 8.000000
+ * With external clock = 30.000000 */
+static struct dibx000_bandwidth_config xc3028_bw_config = {
+	60000,	/* internal */
+	30000,	/* sampling */
+	1,	/* pll_cfg: prediv */
+	8,	/* pll_cfg: ratio */
+	3,	/* pll_cfg: range */
+	1,	/* pll_cfg: reset */
+	0,	/* pll_cfg: bypass */
+	0,	/* misc: refdiv */
+	0,	/* misc: bypclk_div */
+	1,	/* misc: IO_CLK_en_core */
+	1,	/* misc: ADClkSrc */
+	0,	/* misc: modulo */
+	(3 << 14) | (1 << 12) | (524 << 0), /* sad_cfg: refsel, sel, freq_15k */
+	(1 << 25) | 5816102, /* ifreq = 5.200000 MHz */
+	20452225, /* timf */
+	30000000  /* xtal_hz */
+};
+
+static struct dib7000p_config hauppauge_hvr1400_dib7000_config = {
+	.output_mpeg2_in_188_bytes = 1,
+	.hostbus_diversity = 1,
+	.tuner_is_baseband = 0,
+	.update_lna  = NULL,
+
+	.agc_config_count = 1,
+	.agc = &xc3028_agc_config,
+	.bw  = &xc3028_bw_config,
+
+	.gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS,
+	.gpio_val = DIB7000P_GPIO_DEFAULT_VALUES,
+	.gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS,
+
+	.pwm_freq_div = 0,
+	.agc_control  = NULL,
+	.spur_protect = 0,
+
+	.output_mode = OUTMODE_MPEG2_SERIAL,
+};
+
+static struct zl10353_config dvico_fusionhdtv_xc3028 = {
+	.demod_address = 0x0f,
+	.if2           = 45600,
+	.no_tuner      = 1,
+	.disable_i2c_gate_ctrl = 1,
+};
+
+static struct stv0900_reg stv0900_ts_regs[] = {
+	{ R0900_TSGENERAL, 0x00 },
+	{ R0900_P1_TSSPEED, 0x40 },
+	{ R0900_P2_TSSPEED, 0x40 },
+	{ R0900_P1_TSCFGM, 0xc0 },
+	{ R0900_P2_TSCFGM, 0xc0 },
+	{ R0900_P1_TSCFGH, 0xe0 },
+	{ R0900_P2_TSCFGH, 0xe0 },
+	{ R0900_P1_TSCFGL, 0x20 },
+	{ R0900_P2_TSCFGL, 0x20 },
+	{ 0xffff, 0xff }, /* terminate */
+};
+
+static struct stv0900_config netup_stv0900_config = {
+	.demod_address = 0x68,
+	.demod_mode = 1, /* dual */
+	.xtal = 8000000,
+	.clkmode = 3,/* 0-CLKI, 2-XTALI, else AUTO */
+	.diseqc_mode = 2,/* 2/3 PWM */
+	.ts_config_regs = stv0900_ts_regs,
+	.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 = 16000000,
+	.clk_div = 1,
+	.gain = 8, /* +16 dB  - maximum gain */
+};
+
+static struct stv6110_config netup_stv6110_tunerconfig_b = {
+	.i2c_address = 0x63,
+	.mclk = 16000000,
+	.clk_div = 1,
+	.gain = 8, /* +16 dB  - maximum gain */
+};
+
+static struct cx24116_config tbs_cx24116_config = {
+	.demod_address = 0x55,
+};
+
+static struct ds3000_config tevii_ds3000_config = {
+	.demod_address = 0x68,
+};
+
+static struct cx24116_config dvbworld_cx24116_config = {
+	.demod_address = 0x05,
+};
+
+static struct lgs8gxx_config mygica_x8506_lgs8gl5_config = {
+	.prod = LGS8GXX_PROD_LGS8GL5,
+	.demod_address = 0x19,
+	.serial_ts = 0,
+	.ts_clk_pol = 1,
+	.ts_clk_gated = 1,
+	.if_clk_freq = 30400, /* 30.4 MHz */
+	.if_freq = 5380, /* 5.38 MHz */
+	.if_neg_center = 1,
+	.ext_adc = 0,
+	.adc_signed = 0,
+	.if_neg_edge = 0,
+};
+
+static struct xc5000_config mygica_x8506_xc5000_config = {
+	.i2c_address = 0x61,
+	.if_khz = 5380,
+};
+
+static struct stv090x_config prof_8000_stv090x_config = {
+        .device                 = STV0903,
+        .demod_mode             = STV090x_SINGLE,
+        .clk_mode               = STV090x_CLK_EXT,
+        .xtal                   = 27000000,
+        .address                = 0x6A,
+        .ts1_mode               = STV090x_TSMODE_PARALLEL_PUNCTURED,
+        .repeater_level         = STV090x_RPTLEVEL_64,
+        .adc1_range             = STV090x_ADC_2Vpp,
+        .diseqc_envelope_mode   = false,
+
+        .tuner_get_frequency    = stb6100_get_frequency,
+        .tuner_set_frequency    = stb6100_set_frequency,
+        .tuner_set_bandwidth    = stb6100_set_bandwidth,
+        .tuner_get_bandwidth    = stb6100_get_bandwidth,
+};
+
+static struct stb6100_config prof_8000_stb6100_config = {
+	.tuner_address = 0x60,
+	.refclock = 27000000,
+};
+
+static int p8000_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);
+	else if (voltage == SEC_VOLTAGE_13)
+		cx_write(MC417_RWD, 0x00001a00);
+	else
+		cx_write(MC417_RWD, 0x00001800);
+	return 0;
+}
+
+static int cx23885_dvb_set_frontend(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct cx23885_tsport *port = fe->dvb->priv;
+	struct cx23885_dev *dev = port->dev;
+
+	switch (dev->board) {
+	case CX23885_BOARD_HAUPPAUGE_HVR1275:
+		switch (p->modulation) {
+		case VSB_8:
+			cx23885_gpio_clear(dev, GPIO_5);
+			break;
+		case QAM_64:
+		case QAM_256:
+		default:
+			cx23885_gpio_set(dev, GPIO_5);
+			break;
+		}
+		break;
+	case CX23885_BOARD_MYGICA_X8506:
+	case CX23885_BOARD_MAGICPRO_PROHDTVE2:
+		/* Select Digital TV */
+		cx23885_gpio_set(dev, GPIO_0);
+		break;
+	}
+	return 0;
+}
+
+static struct lgs8gxx_config magicpro_prohdtve2_lgs8g75_config = {
+	.prod = LGS8GXX_PROD_LGS8G75,
+	.demod_address = 0x19,
+	.serial_ts = 0,
+	.ts_clk_pol = 1,
+	.ts_clk_gated = 1,
+	.if_clk_freq = 30400, /* 30.4 MHz */
+	.if_freq = 6500, /* 6.50 MHz */
+	.if_neg_center = 1,
+	.ext_adc = 0,
+	.adc_signed = 1,
+	.adc_vpp = 2, /* 1.6 Vpp */
+	.if_neg_edge = 1,
+};
+
+static struct xc5000_config magicpro_prohdtve2_xc5000_config = {
+	.i2c_address = 0x61,
+	.if_khz = 6500,
+};
+
+static struct atbm8830_config mygica_x8558pro_atbm8830_cfg1 = {
+	.prod = ATBM8830_PROD_8830,
+	.demod_address = 0x44,
+	.serial_ts = 0,
+	.ts_sampling_edge = 1,
+	.ts_clk_gated = 0,
+	.osc_clk_freq = 30400, /* in kHz */
+	.if_freq = 0, /* zero IF */
+	.zif_swap_iq = 1,
+	.agc_min = 0x2E,
+	.agc_max = 0xFF,
+	.agc_hold_loop = 0,
+};
+
+static struct max2165_config mygic_x8558pro_max2165_cfg1 = {
+	.i2c_address = 0x60,
+	.osc_clk = 20
+};
+
+static struct atbm8830_config mygica_x8558pro_atbm8830_cfg2 = {
+	.prod = ATBM8830_PROD_8830,
+	.demod_address = 0x44,
+	.serial_ts = 1,
+	.ts_sampling_edge = 1,
+	.ts_clk_gated = 0,
+	.osc_clk_freq = 30400, /* in kHz */
+	.if_freq = 0, /* zero IF */
+	.zif_swap_iq = 1,
+	.agc_min = 0x2E,
+	.agc_max = 0xFF,
+	.agc_hold_loop = 0,
+};
+
+static struct max2165_config mygic_x8558pro_max2165_cfg2 = {
+	.i2c_address = 0x60,
+	.osc_clk = 20
+};
+static struct stv0367_config netup_stv0367_config[] = {
+	{
+		.demod_address = 0x1c,
+		.xtal = 27000000,
+		.if_khz = 4500,
+		.if_iq_mode = 0,
+		.ts_mode = 1,
+		.clk_pol = 0,
+	}, {
+		.demod_address = 0x1d,
+		.xtal = 27000000,
+		.if_khz = 4500,
+		.if_iq_mode = 0,
+		.ts_mode = 1,
+		.clk_pol = 0,
+	},
+};
+
+static struct xc5000_config netup_xc5000_config[] = {
+	{
+		.i2c_address = 0x61,
+		.if_khz = 4500,
+	}, {
+		.i2c_address = 0x64,
+		.if_khz = 4500,
+	},
+};
+
+static struct drxk_config terratec_drxk_config[] = {
+	{
+		.adr = 0x29,
+		.no_i2c_bridge = 1,
+	}, {
+		.adr = 0x2a,
+		.no_i2c_bridge = 1,
+	},
+};
+
+static struct mt2063_config terratec_mt2063_config[] = {
+	{
+		.tuner_address = 0x60,
+	}, {
+		.tuner_address = 0x67,
+	},
+};
+
+int netup_altera_fpga_rw(void *device, int flag, int data, int read)
+{
+	struct cx23885_dev *dev = (struct cx23885_dev *)device;
+	unsigned long timeout = jiffies + msecs_to_jiffies(1);
+	uint32_t mem = 0;
+
+	mem = cx_read(MC417_RWD);
+	if (read)
+		cx_set(MC417_OEN, ALT_DATA);
+	else {
+		cx_clear(MC417_OEN, ALT_DATA);/* D0-D7 out */
+		mem &= ~ALT_DATA;
+		mem |= (data & ALT_DATA);
+	}
+
+	if (flag)
+		mem |= ALT_AD_RG;
+	else
+		mem &= ~ALT_AD_RG;
+
+	mem &= ~ALT_CS;
+	if (read)
+		mem = (mem & ~ALT_RD) | ALT_WR;
+	else
+		mem = (mem & ~ALT_WR) | ALT_RD;
+
+	cx_write(MC417_RWD, mem);  /* start RW cycle */
+
+	for (;;) {
+		mem = cx_read(MC417_RWD);
+		if ((mem & ALT_RDY) == 0)
+			break;
+		if (time_after(jiffies, timeout))
+			break;
+		udelay(1);
+	}
+
+	cx_set(MC417_RWD, ALT_RD | ALT_WR | ALT_CS);
+	if (read)
+		return mem & ALT_DATA;
+
+	return 0;
+};
+
+static int dvb_register(struct cx23885_tsport *port)
+{
+	struct cx23885_dev *dev = port->dev;
+	struct cx23885_i2c *i2c_bus = NULL, *i2c_bus2 = NULL;
+	struct videobuf_dvb_frontend *fe0, *fe1 = NULL;
+	int mfe_shared = 0; /* bus not shared by default */
+	int ret;
+
+	/* Get the first frontend */
+	fe0 = videobuf_dvb_get_frontend(&port->frontends, 1);
+	if (!fe0)
+		return -EINVAL;
+
+	/* init struct videobuf_dvb */
+	fe0->dvb.name = dev->name;
+
+	/* multi-frontend gate control is undefined or defaults to fe0 */
+	port->frontends.gate = 0;
+
+	/* Sets the gate control callback to be used by i2c command calls */
+	port->gate_ctrl = cx23885_dvb_gate_ctrl;
+
+	/* init frontend */
+	switch (dev->board) {
+	case CX23885_BOARD_HAUPPAUGE_HVR1250:
+		i2c_bus = &dev->i2c_bus[0];
+		fe0->dvb.frontend = dvb_attach(s5h1409_attach,
+						&hauppauge_generic_config,
+						&i2c_bus->i2c_adap);
+		if (fe0->dvb.frontend != NULL) {
+			dvb_attach(mt2131_attach, fe0->dvb.frontend,
+				   &i2c_bus->i2c_adap,
+				   &hauppauge_generic_tunerconfig, 0);
+		}
+		break;
+	case CX23885_BOARD_HAUPPAUGE_HVR1270:
+	case CX23885_BOARD_HAUPPAUGE_HVR1275:
+		i2c_bus = &dev->i2c_bus[0];
+		fe0->dvb.frontend = dvb_attach(lgdt3305_attach,
+					       &hauppauge_lgdt3305_config,
+					       &i2c_bus->i2c_adap);
+		if (fe0->dvb.frontend != NULL) {
+			dvb_attach(tda18271_attach, fe0->dvb.frontend,
+				   0x60, &dev->i2c_bus[1].i2c_adap,
+				   &hauppauge_hvr127x_config);
+		}
+		break;
+	case CX23885_BOARD_HAUPPAUGE_HVR1255:
+	case CX23885_BOARD_HAUPPAUGE_HVR1255_22111:
+		i2c_bus = &dev->i2c_bus[0];
+		fe0->dvb.frontend = dvb_attach(s5h1411_attach,
+					       &hcw_s5h1411_config,
+					       &i2c_bus->i2c_adap);
+		if (fe0->dvb.frontend != NULL) {
+			dvb_attach(tda18271_attach, fe0->dvb.frontend,
+				   0x60, &dev->i2c_bus[1].i2c_adap,
+				   &hauppauge_tda18271_config);
+		}
+
+		tda18271_attach(&dev->ts1.analog_fe,
+			0x60, &dev->i2c_bus[1].i2c_adap,
+			&hauppauge_tda18271_config);
+
+		break;
+	case CX23885_BOARD_HAUPPAUGE_HVR1800:
+		i2c_bus = &dev->i2c_bus[0];
+		switch (alt_tuner) {
+		case 1:
+			fe0->dvb.frontend =
+				dvb_attach(s5h1409_attach,
+					   &hauppauge_ezqam_config,
+					   &i2c_bus->i2c_adap);
+			if (fe0->dvb.frontend != NULL) {
+				dvb_attach(tda829x_attach, fe0->dvb.frontend,
+					   &dev->i2c_bus[1].i2c_adap, 0x42,
+					   &tda829x_no_probe);
+				dvb_attach(tda18271_attach, fe0->dvb.frontend,
+					   0x60, &dev->i2c_bus[1].i2c_adap,
+					   &hauppauge_tda18271_config);
+			}
+			break;
+		case 0:
+		default:
+			fe0->dvb.frontend =
+				dvb_attach(s5h1409_attach,
+					   &hauppauge_generic_config,
+					   &i2c_bus->i2c_adap);
+			if (fe0->dvb.frontend != NULL)
+				dvb_attach(mt2131_attach, fe0->dvb.frontend,
+					   &i2c_bus->i2c_adap,
+					   &hauppauge_generic_tunerconfig, 0);
+			break;
+		}
+		break;
+	case CX23885_BOARD_HAUPPAUGE_HVR1800lp:
+		i2c_bus = &dev->i2c_bus[0];
+		fe0->dvb.frontend = dvb_attach(s5h1409_attach,
+						&hauppauge_hvr1800lp_config,
+						&i2c_bus->i2c_adap);
+		if (fe0->dvb.frontend != NULL) {
+			dvb_attach(mt2131_attach, fe0->dvb.frontend,
+				   &i2c_bus->i2c_adap,
+				   &hauppauge_generic_tunerconfig, 0);
+		}
+		break;
+	case CX23885_BOARD_DVICO_FUSIONHDTV_5_EXP:
+		i2c_bus = &dev->i2c_bus[0];
+		fe0->dvb.frontend = dvb_attach(lgdt330x_attach,
+						&fusionhdtv_5_express,
+						&i2c_bus->i2c_adap);
+		if (fe0->dvb.frontend != NULL) {
+			dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
+				   &i2c_bus->i2c_adap, 0x61,
+				   TUNER_LG_TDVS_H06XF);
+		}
+		break;
+	case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
+		i2c_bus = &dev->i2c_bus[1];
+		fe0->dvb.frontend = dvb_attach(s5h1409_attach,
+						&hauppauge_hvr1500q_config,
+						&dev->i2c_bus[0].i2c_adap);
+		if (fe0->dvb.frontend != NULL)
+			dvb_attach(xc5000_attach, fe0->dvb.frontend,
+				   &i2c_bus->i2c_adap,
+				   &hauppauge_hvr1500q_tunerconfig);
+		break;
+	case CX23885_BOARD_HAUPPAUGE_HVR1500:
+		i2c_bus = &dev->i2c_bus[1];
+		fe0->dvb.frontend = dvb_attach(s5h1409_attach,
+						&hauppauge_hvr1500_config,
+						&dev->i2c_bus[0].i2c_adap);
+		if (fe0->dvb.frontend != NULL) {
+			struct dvb_frontend *fe;
+			struct xc2028_config cfg = {
+				.i2c_adap  = &i2c_bus->i2c_adap,
+				.i2c_addr  = 0x61,
+			};
+			static struct xc2028_ctrl ctl = {
+				.fname       = XC2028_DEFAULT_FIRMWARE,
+				.max_len     = 64,
+				.demod       = XC3028_FE_OREN538,
+			};
+
+			fe = dvb_attach(xc2028_attach,
+					fe0->dvb.frontend, &cfg);
+			if (fe != NULL && fe->ops.tuner_ops.set_config != NULL)
+				fe->ops.tuner_ops.set_config(fe, &ctl);
+		}
+		break;
+	case CX23885_BOARD_HAUPPAUGE_HVR1200:
+	case CX23885_BOARD_HAUPPAUGE_HVR1700:
+		i2c_bus = &dev->i2c_bus[0];
+		fe0->dvb.frontend = dvb_attach(tda10048_attach,
+			&hauppauge_hvr1200_config,
+			&i2c_bus->i2c_adap);
+		if (fe0->dvb.frontend != NULL) {
+			dvb_attach(tda829x_attach, fe0->dvb.frontend,
+				&dev->i2c_bus[1].i2c_adap, 0x42,
+				&tda829x_no_probe);
+			dvb_attach(tda18271_attach, fe0->dvb.frontend,
+				0x60, &dev->i2c_bus[1].i2c_adap,
+				&hauppauge_hvr1200_tuner_config);
+		}
+		break;
+	case CX23885_BOARD_HAUPPAUGE_HVR1210:
+		i2c_bus = &dev->i2c_bus[0];
+		fe0->dvb.frontend = dvb_attach(tda10048_attach,
+			&hauppauge_hvr1210_config,
+			&i2c_bus->i2c_adap);
+		if (fe0->dvb.frontend != NULL) {
+			dvb_attach(tda18271_attach, fe0->dvb.frontend,
+				0x60, &dev->i2c_bus[1].i2c_adap,
+				&hauppauge_hvr1210_tuner_config);
+		}
+		break;
+	case CX23885_BOARD_HAUPPAUGE_HVR1400:
+		i2c_bus = &dev->i2c_bus[0];
+		fe0->dvb.frontend = dvb_attach(dib7000p_attach,
+			&i2c_bus->i2c_adap,
+			0x12, &hauppauge_hvr1400_dib7000_config);
+		if (fe0->dvb.frontend != NULL) {
+			struct dvb_frontend *fe;
+			struct xc2028_config cfg = {
+				.i2c_adap  = &dev->i2c_bus[1].i2c_adap,
+				.i2c_addr  = 0x64,
+			};
+			static struct xc2028_ctrl ctl = {
+				.fname   = XC3028L_DEFAULT_FIRMWARE,
+				.max_len = 64,
+				.demod   = XC3028_FE_DIBCOM52,
+				/* This is true for all demods with
+					v36 firmware? */
+				.type    = XC2028_D2633,
+			};
+
+			fe = dvb_attach(xc2028_attach,
+					fe0->dvb.frontend, &cfg);
+			if (fe != NULL && fe->ops.tuner_ops.set_config != NULL)
+				fe->ops.tuner_ops.set_config(fe, &ctl);
+		}
+		break;
+	case CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP:
+		i2c_bus = &dev->i2c_bus[port->nr - 1];
+
+		fe0->dvb.frontend = dvb_attach(s5h1409_attach,
+						&dvico_s5h1409_config,
+						&i2c_bus->i2c_adap);
+		if (fe0->dvb.frontend == NULL)
+			fe0->dvb.frontend = dvb_attach(s5h1411_attach,
+							&dvico_s5h1411_config,
+							&i2c_bus->i2c_adap);
+		if (fe0->dvb.frontend != NULL)
+			dvb_attach(xc5000_attach, fe0->dvb.frontend,
+				   &i2c_bus->i2c_adap,
+				   &dvico_xc5000_tunerconfig);
+		break;
+	case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP: {
+		i2c_bus = &dev->i2c_bus[port->nr - 1];
+
+		fe0->dvb.frontend = dvb_attach(zl10353_attach,
+					       &dvico_fusionhdtv_xc3028,
+					       &i2c_bus->i2c_adap);
+		if (fe0->dvb.frontend != NULL) {
+			struct dvb_frontend      *fe;
+			struct xc2028_config	  cfg = {
+				.i2c_adap  = &i2c_bus->i2c_adap,
+				.i2c_addr  = 0x61,
+			};
+			static struct xc2028_ctrl ctl = {
+				.fname       = XC2028_DEFAULT_FIRMWARE,
+				.max_len     = 64,
+				.demod       = XC3028_FE_ZARLINK456,
+			};
+
+			fe = dvb_attach(xc2028_attach, fe0->dvb.frontend,
+					&cfg);
+			if (fe != NULL && fe->ops.tuner_ops.set_config != NULL)
+				fe->ops.tuner_ops.set_config(fe, &ctl);
+		}
+		break;
+	}
+	case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H:
+	case CX23885_BOARD_COMPRO_VIDEOMATE_E650F:
+	case CX23885_BOARD_COMPRO_VIDEOMATE_E800:
+		i2c_bus = &dev->i2c_bus[0];
+
+		fe0->dvb.frontend = dvb_attach(zl10353_attach,
+			&dvico_fusionhdtv_xc3028,
+			&i2c_bus->i2c_adap);
+		if (fe0->dvb.frontend != NULL) {
+			struct dvb_frontend      *fe;
+			struct xc2028_config	  cfg = {
+				.i2c_adap  = &dev->i2c_bus[1].i2c_adap,
+				.i2c_addr  = 0x61,
+			};
+			static struct xc2028_ctrl ctl = {
+				.fname       = XC2028_DEFAULT_FIRMWARE,
+				.max_len     = 64,
+				.demod       = XC3028_FE_ZARLINK456,
+			};
+
+			fe = dvb_attach(xc2028_attach, fe0->dvb.frontend,
+				&cfg);
+			if (fe != NULL && fe->ops.tuner_ops.set_config != NULL)
+				fe->ops.tuner_ops.set_config(fe, &ctl);
+		}
+		break;
+	case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H_XC4000:
+		i2c_bus = &dev->i2c_bus[0];
+
+		fe0->dvb.frontend = dvb_attach(zl10353_attach,
+					       &dvico_fusionhdtv_xc3028,
+					       &i2c_bus->i2c_adap);
+		if (fe0->dvb.frontend != NULL) {
+			struct dvb_frontend	*fe;
+			struct xc4000_config	cfg = {
+				.i2c_address	  = 0x61,
+				.default_pm	  = 0,
+				.dvb_amplitude	  = 134,
+				.set_smoothedcvbs = 1,
+				.if_khz		  = 4560
+			};
+
+			fe = dvb_attach(xc4000_attach, fe0->dvb.frontend,
+					&dev->i2c_bus[1].i2c_adap, &cfg);
+			if (!fe) {
+				printk(KERN_ERR "%s/2: xc4000 attach failed\n",
+				       dev->name);
+				goto frontend_detach;
+			}
+		}
+		break;
+	case CX23885_BOARD_TBS_6920:
+		i2c_bus = &dev->i2c_bus[1];
+
+		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 = f300_set_voltage;
+
+		break;
+	case CX23885_BOARD_TEVII_S470:
+		i2c_bus = &dev->i2c_bus[1];
+
+		fe0->dvb.frontend = dvb_attach(ds3000_attach,
+					&tevii_ds3000_config,
+					&i2c_bus->i2c_adap);
+		if (fe0->dvb.frontend != NULL)
+			fe0->dvb.frontend->ops.set_voltage = f300_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 | LNBH24_TTX,
+							LNBH24_TEN, 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 | LNBH24_TTX,
+							LNBH24_TEN, 0x0a))
+						printk(KERN_ERR
+							"No LNBH24 found!\n");
+
+				}
+			}
+			break;
+		}
+		break;
+	case CX23885_BOARD_MYGICA_X8506:
+		i2c_bus = &dev->i2c_bus[0];
+		i2c_bus2 = &dev->i2c_bus[1];
+		fe0->dvb.frontend = dvb_attach(lgs8gxx_attach,
+			&mygica_x8506_lgs8gl5_config,
+			&i2c_bus->i2c_adap);
+		if (fe0->dvb.frontend != NULL) {
+			dvb_attach(xc5000_attach,
+				fe0->dvb.frontend,
+				&i2c_bus2->i2c_adap,
+				&mygica_x8506_xc5000_config);
+		}
+		break;
+	case CX23885_BOARD_MAGICPRO_PROHDTVE2:
+		i2c_bus = &dev->i2c_bus[0];
+		i2c_bus2 = &dev->i2c_bus[1];
+		fe0->dvb.frontend = dvb_attach(lgs8gxx_attach,
+			&magicpro_prohdtve2_lgs8g75_config,
+			&i2c_bus->i2c_adap);
+		if (fe0->dvb.frontend != NULL) {
+			dvb_attach(xc5000_attach,
+				fe0->dvb.frontend,
+				&i2c_bus2->i2c_adap,
+				&magicpro_prohdtve2_xc5000_config);
+		}
+		break;
+	case CX23885_BOARD_HAUPPAUGE_HVR1850:
+		i2c_bus = &dev->i2c_bus[0];
+		fe0->dvb.frontend = dvb_attach(s5h1411_attach,
+			&hcw_s5h1411_config,
+			&i2c_bus->i2c_adap);
+		if (fe0->dvb.frontend != NULL)
+			dvb_attach(tda18271_attach, fe0->dvb.frontend,
+				0x60, &dev->i2c_bus[0].i2c_adap,
+				&hauppauge_tda18271_config);
+
+		tda18271_attach(&dev->ts1.analog_fe,
+			0x60, &dev->i2c_bus[1].i2c_adap,
+			&hauppauge_tda18271_config);
+
+		break;
+	case CX23885_BOARD_HAUPPAUGE_HVR1290:
+		i2c_bus = &dev->i2c_bus[0];
+		fe0->dvb.frontend = dvb_attach(s5h1411_attach,
+			&hcw_s5h1411_config,
+			&i2c_bus->i2c_adap);
+		if (fe0->dvb.frontend != NULL)
+			dvb_attach(tda18271_attach, fe0->dvb.frontend,
+				0x60, &dev->i2c_bus[0].i2c_adap,
+				&hauppauge_tda18271_config);
+		break;
+	case CX23885_BOARD_MYGICA_X8558PRO:
+		switch (port->nr) {
+		/* port B */
+		case 1:
+			i2c_bus = &dev->i2c_bus[0];
+			fe0->dvb.frontend = dvb_attach(atbm8830_attach,
+				&mygica_x8558pro_atbm8830_cfg1,
+				&i2c_bus->i2c_adap);
+			if (fe0->dvb.frontend != NULL) {
+				dvb_attach(max2165_attach,
+					fe0->dvb.frontend,
+					&i2c_bus->i2c_adap,
+					&mygic_x8558pro_max2165_cfg1);
+			}
+			break;
+		/* port C */
+		case 2:
+			i2c_bus = &dev->i2c_bus[1];
+			fe0->dvb.frontend = dvb_attach(atbm8830_attach,
+				&mygica_x8558pro_atbm8830_cfg2,
+				&i2c_bus->i2c_adap);
+			if (fe0->dvb.frontend != NULL) {
+				dvb_attach(max2165_attach,
+					fe0->dvb.frontend,
+					&i2c_bus->i2c_adap,
+					&mygic_x8558pro_max2165_cfg2);
+			}
+			break;
+		}
+		break;
+	case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF:
+		i2c_bus = &dev->i2c_bus[0];
+		mfe_shared = 1;/* MFE */
+		port->frontends.gate = 0;/* not clear for me yet */
+		/* ports B, C */
+		/* MFE frontend 1 DVB-T */
+		fe0->dvb.frontend = dvb_attach(stv0367ter_attach,
+					&netup_stv0367_config[port->nr - 1],
+					&i2c_bus->i2c_adap);
+		if (fe0->dvb.frontend != NULL) {
+			if (NULL == dvb_attach(xc5000_attach,
+					fe0->dvb.frontend,
+					&i2c_bus->i2c_adap,
+					&netup_xc5000_config[port->nr - 1]))
+				goto frontend_detach;
+			/* load xc5000 firmware */
+			fe0->dvb.frontend->ops.tuner_ops.init(fe0->dvb.frontend);
+		}
+		/* MFE frontend 2 */
+		fe1 = videobuf_dvb_get_frontend(&port->frontends, 2);
+		if (fe1 == NULL)
+			goto frontend_detach;
+		/* DVB-C init */
+		fe1->dvb.frontend = dvb_attach(stv0367cab_attach,
+					&netup_stv0367_config[port->nr - 1],
+					&i2c_bus->i2c_adap);
+		if (fe1->dvb.frontend != NULL) {
+			fe1->dvb.frontend->id = 1;
+			if (NULL == dvb_attach(xc5000_attach,
+					fe1->dvb.frontend,
+					&i2c_bus->i2c_adap,
+					&netup_xc5000_config[port->nr - 1]))
+				goto frontend_detach;
+		}
+		break;
+	case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL:
+		i2c_bus = &dev->i2c_bus[0];
+		i2c_bus2 = &dev->i2c_bus[1];
+
+		switch (port->nr) {
+		/* port b */
+		case 1:
+			fe0->dvb.frontend = dvb_attach(drxk_attach,
+					&terratec_drxk_config[0],
+					&i2c_bus->i2c_adap);
+			if (fe0->dvb.frontend != NULL) {
+				if (!dvb_attach(mt2063_attach,
+						fe0->dvb.frontend,
+						&terratec_mt2063_config[0],
+						&i2c_bus2->i2c_adap))
+					goto frontend_detach;
+			}
+			break;
+		/* port c */
+		case 2:
+			fe0->dvb.frontend = dvb_attach(drxk_attach,
+					&terratec_drxk_config[1],
+					&i2c_bus->i2c_adap);
+			if (fe0->dvb.frontend != NULL) {
+				if (!dvb_attach(mt2063_attach,
+						fe0->dvb.frontend,
+						&terratec_mt2063_config[1],
+						&i2c_bus2->i2c_adap))
+					goto frontend_detach;
+			}
+			break;
+		}
+		break;
+	case CX23885_BOARD_TEVII_S471:
+		i2c_bus = &dev->i2c_bus[1];
+
+		fe0->dvb.frontend = dvb_attach(ds3000_attach,
+					&tevii_ds3000_config,
+					&i2c_bus->i2c_adap);
+		break;
+	case CX23885_BOARD_PROF_8000:
+		i2c_bus = &dev->i2c_bus[0];
+
+		fe0->dvb.frontend = dvb_attach(stv090x_attach,
+						&prof_8000_stv090x_config,
+						&i2c_bus->i2c_adap,
+						STV090x_DEMODULATOR_0);
+		if (fe0->dvb.frontend != NULL) {
+			if (!dvb_attach(stb6100_attach,
+					fe0->dvb.frontend,
+					&prof_8000_stb6100_config,
+					&i2c_bus->i2c_adap))
+				goto frontend_detach;
+
+			fe0->dvb.frontend->ops.set_voltage = p8000_set_voltage;
+		}
+		break;
+	default:
+		printk(KERN_INFO "%s: The frontend of your DVB/ATSC card "
+			" isn't supported yet\n",
+		       dev->name);
+		break;
+	}
+
+	if ((NULL == fe0->dvb.frontend) || (fe1 && NULL == fe1->dvb.frontend)) {
+		printk(KERN_ERR "%s: frontend initialization failed\n",
+		       dev->name);
+		goto frontend_detach;
+	}
+
+	/* define general-purpose callback pointer */
+	fe0->dvb.frontend->callback = cx23885_tuner_callback;
+	if (fe1)
+		fe1->dvb.frontend->callback = cx23885_tuner_callback;
+#if 0
+	/* Ensure all frontends negotiate bus access */
+	fe0->dvb.frontend->ops.ts_bus_ctrl = cx23885_dvb_bus_ctrl;
+	if (fe1)
+		fe1->dvb.frontend->ops.ts_bus_ctrl = cx23885_dvb_bus_ctrl;
+#endif
+
+	/* Put the analog decoder in standby to keep it quiet */
+	call_all(dev, core, s_power, 0);
+
+	if (fe0->dvb.frontend->ops.analog_ops.standby)
+		fe0->dvb.frontend->ops.analog_ops.standby(fe0->dvb.frontend);
+
+	/* register everything */
+	ret = videobuf_dvb_register_bus(&port->frontends, THIS_MODULE, port,
+					&dev->pci->dev, adapter_nr, mfe_shared);
+	if (ret)
+		goto frontend_detach;
+
+	/* 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=%pM\n",
+			port->nr, port->frontends.adapter.proposed_mac);
+
+		netup_ci_init(port);
+		break;
+		}
+	case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF: {
+		struct altera_ci_config netup_ci_cfg = {
+			.dev = dev,/* magic number to identify*/
+			.adapter = &port->frontends.adapter,/* for CI */
+			.demux = &fe0->dvb.demux,/* for hw pid filter */
+			.fpga_rw = netup_altera_fpga_rw,
+		};
+
+		altera_ci_init(&netup_ci_cfg, port->nr);
+		break;
+		}
+	case CX23885_BOARD_TEVII_S470: {
+		u8 eeprom[256]; /* 24C02 i2c eeprom */
+
+		if (port->nr != 1)
+			break;
+
+		/* Read entire EEPROM */
+		dev->i2c_bus[0].i2c_client.addr = 0xa0 >> 1;
+		tveeprom_read(&dev->i2c_bus[0].i2c_client, eeprom, sizeof(eeprom));
+		printk(KERN_INFO "TeVii S470 MAC= %pM\n", eeprom + 0xa0);
+		memcpy(port->frontends.adapter.proposed_mac, eeprom + 0xa0, 6);
+		break;
+		}
+	}
+
+	return ret;
+
+frontend_detach:
+	port->gate_ctrl = NULL;
+	videobuf_dvb_dealloc_frontends(&port->frontends);
+	return -EINVAL;
+}
+
+int cx23885_dvb_register(struct cx23885_tsport *port)
+{
+
+	struct videobuf_dvb_frontend *fe0;
+	struct cx23885_dev *dev = port->dev;
+	int err, i;
+
+	/* Here we need to allocate the correct number of frontends,
+	 * as reflected in the cards struct. The reality is that currently
+	 * no cx23885 boards support this - yet. But, if we don't modify this
+	 * code then the second frontend would never be allocated (later)
+	 * and fail with error before the attach in dvb_register().
+	 * Without these changes we risk an OOPS later. The changes here
+	 * are for safety, and should provide a good foundation for the
+	 * future addition of any multi-frontend cx23885 based boards.
+	 */
+	printk(KERN_INFO "%s() allocating %d frontend(s)\n", __func__,
+		port->num_frontends);
+
+	for (i = 1; i <= port->num_frontends; i++) {
+		if (videobuf_dvb_alloc_frontend(
+			&port->frontends, i) == NULL) {
+			printk(KERN_ERR "%s() failed to alloc\n", __func__);
+			return -ENOMEM;
+		}
+
+		fe0 = videobuf_dvb_get_frontend(&port->frontends, i);
+		if (!fe0)
+			err = -EINVAL;
+
+		dprintk(1, "%s\n", __func__);
+		dprintk(1, " ->probed by Card=%d Name=%s, PCI %02x:%02x\n",
+			dev->board,
+			dev->name,
+			dev->pci_bus,
+			dev->pci_slot);
+
+		err = -ENODEV;
+
+		/* dvb stuff */
+		/* We have to init the queue for each frontend on a port. */
+		printk(KERN_INFO "%s: cx23885 based dvb card\n", dev->name);
+		videobuf_queue_sg_init(&fe0->dvb.dvbq, &dvb_qops,
+			    &dev->pci->dev, &port->slock,
+			    V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_TOP,
+			    sizeof(struct cx23885_buffer), port, NULL);
+	}
+	err = dvb_register(port);
+	if (err != 0)
+		printk(KERN_ERR "%s() dvb_register failed err = %d\n",
+			__func__, err);
+
+	return err;
+}
+
+int cx23885_dvb_unregister(struct cx23885_tsport *port)
+{
+	struct videobuf_dvb_frontend *fe0;
+
+	/* FIXME: in an error condition where the we have
+	 * an expected number of frontends (attach problem)
+	 * then this might not clean up correctly, if 1
+	 * is invalid.
+	 * This comment only applies to future boards IF they
+	 * implement MFE support.
+	 */
+	fe0 = videobuf_dvb_get_frontend(&port->frontends, 1);
+	if (fe0 && 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;
+	case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF:
+		altera_ci_release(port->dev, port->nr);
+		break;
+	}
+
+	port->gate_ctrl = NULL;
+
+	return 0;
+}
+
diff --git a/drivers/media/pci/cx23885/cx23885-f300.c b/drivers/media/pci/cx23885/cx23885-f300.c
new file mode 100644
index 0000000..93998f2
--- /dev/null
+++ b/drivers/media/pci/cx23885/cx23885-f300.c
@@ -0,0 +1,177 @@
+/*
+ * Driver for Silicon Labs C8051F300 microcontroller.
+ *
+ * It is used for LNB power control in TeVii S470,
+ * TBS 6920 PCIe DVB-S2 cards.
+ *
+ * Microcontroller connected to cx23885 GPIO pins:
+ * GPIO0 - data		- P0.3 F300
+ * GPIO1 - reset	- P0.2 F300
+ * GPIO2 - clk		- P0.1 F300
+ * GPIO3 - busy		- P0.0 F300
+ *
+ * Copyright (C) 2009 Igor M. Liplianin <liplianin@me.by>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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"
+
+#define F300_DATA	GPIO_0
+#define F300_RESET	GPIO_1
+#define F300_CLK	GPIO_2
+#define F300_BUSY	GPIO_3
+
+static void f300_set_line(struct cx23885_dev *dev, u32 line, u8 lvl)
+{
+	cx23885_gpio_enable(dev, line, 1);
+	if (lvl == 1)
+		cx23885_gpio_set(dev, line);
+	else
+		cx23885_gpio_clear(dev, line);
+}
+
+static u8 f300_get_line(struct cx23885_dev *dev, u32 line)
+{
+	cx23885_gpio_enable(dev, line, 0);
+
+	return cx23885_gpio_get(dev, line);
+}
+
+static void f300_send_byte(struct cx23885_dev *dev, u8 dta)
+{
+	u8 i;
+
+	for (i = 0; i < 8; i++) {
+		f300_set_line(dev, F300_CLK, 0);
+		udelay(30);
+		f300_set_line(dev, F300_DATA, (dta & 0x80) >> 7);/* msb first */
+		udelay(30);
+		dta <<= 1;
+		f300_set_line(dev, F300_CLK, 1);
+		udelay(30);
+	}
+}
+
+static u8 f300_get_byte(struct cx23885_dev *dev)
+{
+	u8 i, dta = 0;
+
+	for (i = 0; i < 8; i++) {
+		f300_set_line(dev, F300_CLK, 0);
+		udelay(30);
+		dta <<= 1;
+		f300_set_line(dev, F300_CLK, 1);
+		udelay(30);
+		dta |= f300_get_line(dev, F300_DATA);/* msb first */
+
+	}
+
+	return dta;
+}
+
+static u8 f300_xfer(struct dvb_frontend *fe, u8 *buf)
+{
+	struct cx23885_tsport *port = fe->dvb->priv;
+	struct cx23885_dev *dev = port->dev;
+	u8 i, temp, ret = 0;
+
+	temp = buf[0];
+	for (i = 0; i < buf[0]; i++)
+		temp += buf[i + 1];
+	temp = (~temp + 1);/* get check sum */
+	buf[1 + buf[0]] = temp;
+
+	f300_set_line(dev, F300_RESET, 1);
+	f300_set_line(dev, F300_CLK, 1);
+	udelay(30);
+	f300_set_line(dev, F300_DATA, 1);
+	msleep(1);
+
+	/* question: */
+	f300_set_line(dev, F300_RESET, 0);/* begin to send data */
+	msleep(1);
+
+	f300_send_byte(dev, 0xe0);/* the slave address is 0xe0, write */
+	msleep(1);
+
+	temp = buf[0];
+	temp += 2;
+	for (i = 0; i < temp; i++)
+		f300_send_byte(dev, buf[i]);
+
+	f300_set_line(dev, F300_RESET, 1);/* sent data over */
+	f300_set_line(dev, F300_DATA, 1);
+
+	/* answer: */
+	temp = 0;
+	for (i = 0; ((i < 8) & (temp == 0)); i++) {
+		msleep(1);
+		if (f300_get_line(dev, F300_BUSY) == 0)
+			temp = 1;
+	}
+
+	if (i > 7) {
+		printk(KERN_ERR "%s: timeout, the slave no response\n",
+								__func__);
+		ret = 1; /* timeout, the slave no response */
+	} else { /* the slave not busy, prepare for getting data */
+		f300_set_line(dev, F300_RESET, 0);/*ready...*/
+		msleep(1);
+		f300_send_byte(dev, 0xe1);/* 0xe1 is Read */
+		msleep(1);
+		temp = f300_get_byte(dev);/*get the data length */
+		if (temp > 14)
+			temp = 14;
+
+		for (i = 0; i < (temp + 1); i++)
+			f300_get_byte(dev);/* get data to empty buffer */
+
+		f300_set_line(dev, F300_RESET, 1);/* received data over */
+		f300_set_line(dev, F300_DATA, 1);
+	}
+
+	return ret;
+}
+
+int f300_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+{
+	u8 buf[16];
+
+	buf[0] = 0x05;
+	buf[1] = 0x38;/* write port */
+	buf[2] = 0x01;/* A port, lnb power */
+
+	switch (voltage) {
+	case SEC_VOLTAGE_13:
+		buf[3] = 0x01;/* power on */
+		buf[4] = 0x02;/* B port, H/V */
+		buf[5] = 0x00;/*13V v*/
+		break;
+	case SEC_VOLTAGE_18:
+		buf[3] = 0x01;
+		buf[4] = 0x02;
+		buf[5] = 0x01;/* 18V h*/
+		break;
+	case SEC_VOLTAGE_OFF:
+		buf[3] = 0x00;/* power off */
+		buf[4] = 0x00;
+		buf[5] = 0x00;
+		break;
+	}
+
+	return f300_xfer(fe, buf);
+}
diff --git a/drivers/media/pci/cx23885/cx23885-f300.h b/drivers/media/pci/cx23885/cx23885-f300.h
new file mode 100644
index 0000000..e73344c
--- /dev/null
+++ b/drivers/media/pci/cx23885/cx23885-f300.h
@@ -0,0 +1,2 @@
+extern int f300_set_voltage(struct dvb_frontend *fe,
+				fe_sec_voltage_t voltage);
diff --git a/drivers/media/pci/cx23885/cx23885-i2c.c b/drivers/media/pci/cx23885/cx23885-i2c.c
new file mode 100644
index 0000000..4887314
--- /dev/null
+++ b/drivers/media/pci/cx23885/cx23885-i2c.c
@@ -0,0 +1,396 @@
+/*
+ *  Driver for the Conexant CX23885 PCIe bridge
+ *
+ *  Copyright (c) 2006 Steven Toth <stoth@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/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+
+#include "cx23885.h"
+
+#include <media/v4l2-common.h>
+
+static unsigned int i2c_debug;
+module_param(i2c_debug, int, 0644);
+MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
+
+static unsigned int i2c_scan;
+module_param(i2c_scan, int, 0444);
+MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time");
+
+#define dprintk(level, fmt, arg...)\
+	do { if (i2c_debug >= level)\
+		printk(KERN_DEBUG "%s/0: " fmt, dev->name, ## arg);\
+	} while (0)
+
+#define I2C_WAIT_DELAY 32
+#define I2C_WAIT_RETRY 64
+
+#define I2C_EXTEND  (1 << 3)
+#define I2C_NOSTOP  (1 << 4)
+
+static inline int i2c_slave_did_ack(struct i2c_adapter *i2c_adap)
+{
+	struct cx23885_i2c *bus = i2c_adap->algo_data;
+	struct cx23885_dev *dev = bus->dev;
+	return cx_read(bus->reg_stat) & 0x01;
+}
+
+static inline int i2c_is_busy(struct i2c_adapter *i2c_adap)
+{
+	struct cx23885_i2c *bus = i2c_adap->algo_data;
+	struct cx23885_dev *dev = bus->dev;
+	return cx_read(bus->reg_stat) & 0x02 ? 1 : 0;
+}
+
+static int i2c_wait_done(struct i2c_adapter *i2c_adap)
+{
+	int count;
+
+	for (count = 0; count < I2C_WAIT_RETRY; count++) {
+		if (!i2c_is_busy(i2c_adap))
+			break;
+		udelay(I2C_WAIT_DELAY);
+	}
+
+	if (I2C_WAIT_RETRY == count)
+		return 0;
+
+	return 1;
+}
+
+static int i2c_sendbytes(struct i2c_adapter *i2c_adap,
+			 const struct i2c_msg *msg, int joined_rlen)
+{
+	struct cx23885_i2c *bus = i2c_adap->algo_data;
+	struct cx23885_dev *dev = bus->dev;
+	u32 wdata, addr, ctrl;
+	int retval, cnt;
+
+	if (joined_rlen)
+		dprintk(1, "%s(msg->wlen=%d, nextmsg->rlen=%d)\n", __func__,
+			msg->len, joined_rlen);
+	else
+		dprintk(1, "%s(msg->len=%d)\n", __func__, msg->len);
+
+	/* Deal with i2c probe functions with zero payload */
+	if (msg->len == 0) {
+		cx_write(bus->reg_addr, msg->addr << 25);
+		cx_write(bus->reg_ctrl, bus->i2c_period | (1 << 2));
+		if (!i2c_wait_done(i2c_adap))
+			return -EIO;
+		if (!i2c_slave_did_ack(i2c_adap))
+			return -ENXIO;
+
+		dprintk(1, "%s() returns 0\n", __func__);
+		return 0;
+	}
+
+
+	/* dev, reg + first byte */
+	addr = (msg->addr << 25) | msg->buf[0];
+	wdata = msg->buf[0];
+	ctrl = bus->i2c_period | (1 << 12) | (1 << 2);
+
+	if (msg->len > 1)
+		ctrl |= I2C_NOSTOP | I2C_EXTEND;
+	else if (joined_rlen)
+		ctrl |= I2C_NOSTOP;
+
+	cx_write(bus->reg_addr, addr);
+	cx_write(bus->reg_wdata, wdata);
+	cx_write(bus->reg_ctrl, ctrl);
+
+	if (!i2c_wait_done(i2c_adap))
+		goto eio;
+	if (i2c_debug) {
+		printk(" <W %02x %02x", msg->addr << 1, msg->buf[0]);
+		if (!(ctrl & I2C_NOSTOP))
+			printk(" >\n");
+	}
+
+	for (cnt = 1; cnt < msg->len; cnt++) {
+		/* following bytes */
+		wdata = msg->buf[cnt];
+		ctrl = bus->i2c_period | (1 << 12) | (1 << 2);
+
+		if (cnt < msg->len - 1)
+			ctrl |= I2C_NOSTOP | I2C_EXTEND;
+		else if (joined_rlen)
+			ctrl |= I2C_NOSTOP;
+
+		cx_write(bus->reg_addr, addr);
+		cx_write(bus->reg_wdata, wdata);
+		cx_write(bus->reg_ctrl, ctrl);
+
+		if (!i2c_wait_done(i2c_adap))
+			goto eio;
+		if (i2c_debug) {
+			dprintk(1, " %02x", msg->buf[cnt]);
+			if (!(ctrl & I2C_NOSTOP))
+				dprintk(1, " >\n");
+		}
+	}
+	return msg->len;
+
+ eio:
+	retval = -EIO;
+	if (i2c_debug)
+		printk(KERN_ERR " ERR: %d\n", retval);
+	return retval;
+}
+
+static int i2c_readbytes(struct i2c_adapter *i2c_adap,
+			 const struct i2c_msg *msg, int joined)
+{
+	struct cx23885_i2c *bus = i2c_adap->algo_data;
+	struct cx23885_dev *dev = bus->dev;
+	u32 ctrl, cnt;
+	int retval;
+
+
+	if (i2c_debug && !joined)
+		dprintk(1, "%s(msg->len=%d)\n", __func__, msg->len);
+
+	/* Deal with i2c probe functions with zero payload */
+	if (msg->len == 0) {
+		cx_write(bus->reg_addr, msg->addr << 25);
+		cx_write(bus->reg_ctrl, bus->i2c_period | (1 << 2) | 1);
+		if (!i2c_wait_done(i2c_adap))
+			return -EIO;
+		if (!i2c_slave_did_ack(i2c_adap))
+			return -ENXIO;
+
+
+		dprintk(1, "%s() returns 0\n", __func__);
+		return 0;
+	}
+
+	if (i2c_debug) {
+		if (joined)
+			dprintk(1, " R");
+		else
+			dprintk(1, " <R %02x", (msg->addr << 1) + 1);
+	}
+
+	for (cnt = 0; cnt < msg->len; cnt++) {
+
+		ctrl = bus->i2c_period | (1 << 12) | (1 << 2) | 1;
+
+		if (cnt < msg->len - 1)
+			ctrl |= I2C_NOSTOP | I2C_EXTEND;
+
+		cx_write(bus->reg_addr, msg->addr << 25);
+		cx_write(bus->reg_ctrl, ctrl);
+
+		if (!i2c_wait_done(i2c_adap))
+			goto eio;
+		msg->buf[cnt] = cx_read(bus->reg_rdata) & 0xff;
+		if (i2c_debug) {
+			dprintk(1, " %02x", msg->buf[cnt]);
+			if (!(ctrl & I2C_NOSTOP))
+				dprintk(1, " >\n");
+		}
+	}
+	return msg->len;
+
+ eio:
+	retval = -EIO;
+	if (i2c_debug)
+		printk(KERN_ERR " ERR: %d\n", retval);
+	return retval;
+}
+
+static int i2c_xfer(struct i2c_adapter *i2c_adap,
+		    struct i2c_msg *msgs, int num)
+{
+	struct cx23885_i2c *bus = i2c_adap->algo_data;
+	struct cx23885_dev *dev = bus->dev;
+	int i, retval = 0;
+
+	dprintk(1, "%s(num = %d)\n", __func__, num);
+
+	for (i = 0 ; i < num; i++) {
+		dprintk(1, "%s(num = %d) addr = 0x%02x  len = 0x%x\n",
+			__func__, num, msgs[i].addr, msgs[i].len);
+		if (msgs[i].flags & I2C_M_RD) {
+			/* read */
+			retval = i2c_readbytes(i2c_adap, &msgs[i], 0);
+		} else if (i + 1 < num && (msgs[i + 1].flags & I2C_M_RD) &&
+			   msgs[i].addr == msgs[i + 1].addr) {
+			/* write then read from same address */
+			retval = i2c_sendbytes(i2c_adap, &msgs[i],
+					       msgs[i + 1].len);
+			if (retval < 0)
+				goto err;
+			i++;
+			retval = i2c_readbytes(i2c_adap, &msgs[i], 1);
+		} else {
+			/* write */
+			retval = i2c_sendbytes(i2c_adap, &msgs[i], 0);
+		}
+		if (retval < 0)
+			goto err;
+	}
+	return num;
+
+ err:
+	return retval;
+}
+
+static u32 cx23885_functionality(struct i2c_adapter *adap)
+{
+	return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm cx23885_i2c_algo_template = {
+	.master_xfer	= i2c_xfer,
+	.functionality	= cx23885_functionality,
+};
+
+/* ----------------------------------------------------------------------- */
+
+static struct i2c_adapter cx23885_i2c_adap_template = {
+	.name              = "cx23885",
+	.owner             = THIS_MODULE,
+	.algo              = &cx23885_i2c_algo_template,
+};
+
+static struct i2c_client cx23885_i2c_client_template = {
+	.name	= "cx23885 internal",
+};
+
+static char *i2c_devs[128] = {
+	[0x10 >> 1] = "tda10048",
+	[0x12 >> 1] = "dib7000pc",
+	[0x1c >> 1] = "lgdt3303",
+	[0x86 >> 1] = "tda9887",
+	[0x32 >> 1] = "cx24227",
+	[0x88 >> 1] = "cx25837",
+	[0x84 >> 1] = "tda8295",
+	[0x98 >> 1] = "flatiron",
+	[0xa0 >> 1] = "eeprom",
+	[0xc0 >> 1] = "tuner/mt2131/tda8275",
+	[0xc2 >> 1] = "tuner/mt2131/tda8275/xc5000/xc3028",
+	[0xc8 >> 1] = "tuner/xc3028L",
+};
+
+static void do_i2c_scan(char *name, struct i2c_client *c)
+{
+	unsigned char buf;
+	int i, rc;
+
+	for (i = 0; i < 128; i++) {
+		c->addr = i;
+		rc = i2c_master_recv(c, &buf, 0);
+		if (rc < 0)
+			continue;
+		printk(KERN_INFO "%s: i2c scan: found device @ 0x%x  [%s]\n",
+		       name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???");
+	}
+}
+
+/* init + register i2c adapter */
+int cx23885_i2c_register(struct cx23885_i2c *bus)
+{
+	struct cx23885_dev *dev = bus->dev;
+
+	dprintk(1, "%s(bus = %d)\n", __func__, bus->nr);
+
+	bus->i2c_adap = cx23885_i2c_adap_template;
+	bus->i2c_client = cx23885_i2c_client_template;
+	bus->i2c_adap.dev.parent = &dev->pci->dev;
+
+	strlcpy(bus->i2c_adap.name, bus->dev->name,
+		sizeof(bus->i2c_adap.name));
+
+	bus->i2c_adap.algo_data = 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) {
+			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);
+
+	/* Instantiate the IR receiver device, if present */
+	if (0 == bus->i2c_rc) {
+		struct i2c_board_info info;
+		const unsigned short addr_list[] = {
+			0x6b, I2C_CLIENT_END
+		};
+
+		memset(&info, 0, sizeof(struct i2c_board_info));
+		strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
+		/* Use quick read command for probe, some IR chips don't
+		 * support writes */
+		i2c_new_probed_device(&bus->i2c_adap, &info, addr_list,
+				      i2c_probe_func_quick_read);
+	}
+
+	return bus->i2c_rc;
+}
+
+int cx23885_i2c_unregister(struct cx23885_i2c *bus)
+{
+	i2c_del_adapter(&bus->i2c_adap);
+	return 0;
+}
+
+void cx23885_av_clk(struct cx23885_dev *dev, int enable)
+{
+	/* write 0 to bus 2 addr 0x144 via i2x_xfer() */
+	char buffer[3];
+	struct i2c_msg msg;
+	dprintk(1, "%s(enabled = %d)\n", __func__, enable);
+
+	/* Register 0x144 */
+	buffer[0] = 0x01;
+	buffer[1] = 0x44;
+	if (enable == 1)
+		buffer[2] = 0x05;
+	else
+		buffer[2] = 0x00;
+
+	msg.addr = 0x44;
+	msg.flags = I2C_M_TEN;
+	msg.len = 3;
+	msg.buf = buffer;
+
+	i2c_xfer(&dev->i2c_bus[2].i2c_adap, &msg, 1);
+}
+
+/* ----------------------------------------------------------------------- */
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/pci/cx23885/cx23885-input.c b/drivers/media/pci/cx23885/cx23885-input.c
new file mode 100644
index 0000000..2c925f7
--- /dev/null
+++ b/drivers/media/pci/cx23885/cx23885-input.c
@@ -0,0 +1,365 @@
+/*
+ *  Driver for the Conexant CX23885/7/8 PCIe bridge
+ *
+ *  Infrared remote control input device
+ *
+ *  Most of this file is
+ *
+ *  Copyright (C) 2009  Andy Walls <awalls@md.metrocast.net>
+ *
+ *  However, the cx23885_input_{init,fini} functions contained herein are
+ *  derived from Linux kernel files linux/media/video/.../...-input.c marked as:
+ *
+ *  Copyright (C) 2008 <srinivasa.deevi at conexant dot com>
+ *  Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it>
+ *		       Markus Rechberger <mrechberger@gmail.com>
+ *		       Mauro Carvalho Chehab <mchehab@infradead.org>
+ *		       Sascha Sommer <saschasommer@freenet.de>
+ *  Copyright (C) 2004, 2005 Chris Pascoe
+ *  Copyright (C) 2003, 2004 Gerd Knorr
+ *  Copyright (C) 2003 Pavel Machek
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the 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/slab.h>
+#include <media/rc-core.h>
+#include <media/v4l2-subdev.h>
+
+#include "cx23885.h"
+
+#define MODULE_NAME "cx23885"
+
+static void cx23885_input_process_measurements(struct cx23885_dev *dev,
+					       bool overrun)
+{
+	struct cx23885_kernel_ir *kernel_ir = dev->kernel_ir;
+
+	ssize_t num;
+	int count, i;
+	bool handle = false;
+	struct ir_raw_event ir_core_event[64];
+
+	do {
+		num = 0;
+		v4l2_subdev_call(dev->sd_ir, ir, rx_read, (u8 *) ir_core_event,
+				 sizeof(ir_core_event), &num);
+
+		count = num / sizeof(struct ir_raw_event);
+
+		for (i = 0; i < count; i++) {
+			ir_raw_event_store(kernel_ir->rc,
+					   &ir_core_event[i]);
+			handle = true;
+		}
+	} while (num != 0);
+
+	if (overrun)
+		ir_raw_event_reset(kernel_ir->rc);
+	else if (handle)
+		ir_raw_event_handle(kernel_ir->rc);
+}
+
+void cx23885_input_rx_work_handler(struct cx23885_dev *dev, u32 events)
+{
+	struct v4l2_subdev_ir_parameters params;
+	int overrun, data_available;
+
+	if (dev->sd_ir == NULL || events == 0)
+		return;
+
+	switch (dev->board) {
+	case CX23885_BOARD_HAUPPAUGE_HVR1270:
+	case CX23885_BOARD_HAUPPAUGE_HVR1850:
+	case CX23885_BOARD_HAUPPAUGE_HVR1290:
+	case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL:
+	case CX23885_BOARD_TEVII_S470:
+	case CX23885_BOARD_HAUPPAUGE_HVR1250:
+		/*
+		 * The only boards we handle right now.  However other boards
+		 * using the CX2388x integrated IR controller should be similar
+		 */
+		break;
+	default:
+		return;
+	}
+
+	overrun = events & (V4L2_SUBDEV_IR_RX_SW_FIFO_OVERRUN |
+			    V4L2_SUBDEV_IR_RX_HW_FIFO_OVERRUN);
+
+	data_available = events & (V4L2_SUBDEV_IR_RX_END_OF_RX_DETECTED |
+				   V4L2_SUBDEV_IR_RX_FIFO_SERVICE_REQ);
+
+	if (overrun) {
+		/* If there was a FIFO overrun, stop the device */
+		v4l2_subdev_call(dev->sd_ir, ir, rx_g_parameters, &params);
+		params.enable = false;
+		/* Mitigate race with cx23885_input_ir_stop() */
+		params.shutdown = atomic_read(&dev->ir_input_stopping);
+		v4l2_subdev_call(dev->sd_ir, ir, rx_s_parameters, &params);
+	}
+
+	if (data_available)
+		cx23885_input_process_measurements(dev, overrun);
+
+	if (overrun) {
+		/* If there was a FIFO overrun, clear & restart the device */
+		params.enable = true;
+		/* Mitigate race with cx23885_input_ir_stop() */
+		params.shutdown = atomic_read(&dev->ir_input_stopping);
+		v4l2_subdev_call(dev->sd_ir, ir, rx_s_parameters, &params);
+	}
+}
+
+static int cx23885_input_ir_start(struct cx23885_dev *dev)
+{
+	struct v4l2_subdev_ir_parameters params;
+
+	if (dev->sd_ir == NULL)
+		return -ENODEV;
+
+	atomic_set(&dev->ir_input_stopping, 0);
+
+	v4l2_subdev_call(dev->sd_ir, ir, rx_g_parameters, &params);
+	switch (dev->board) {
+	case CX23885_BOARD_HAUPPAUGE_HVR1270:
+	case CX23885_BOARD_HAUPPAUGE_HVR1850:
+	case CX23885_BOARD_HAUPPAUGE_HVR1290:
+	case CX23885_BOARD_HAUPPAUGE_HVR1250:
+		/*
+		 * The IR controller on this board only returns pulse widths.
+		 * Any other mode setting will fail to set up the device.
+		*/
+		params.mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH;
+		params.enable = true;
+		params.interrupt_enable = true;
+		params.shutdown = false;
+
+		/* Setup for baseband compatible with both RC-5 and RC-6A */
+		params.modulation = false;
+		/* RC-5:  2,222,222 ns = 1/36 kHz * 32 cycles * 2 marks * 1.25*/
+		/* RC-6A: 3,333,333 ns = 1/36 kHz * 16 cycles * 6 marks * 1.25*/
+		params.max_pulse_width = 3333333; /* ns */
+		/* RC-5:    666,667 ns = 1/36 kHz * 32 cycles * 1 mark * 0.75 */
+		/* RC-6A:   333,333 ns = 1/36 kHz * 16 cycles * 1 mark * 0.75 */
+		params.noise_filter_min_width = 333333; /* ns */
+		/*
+		 * This board has inverted receive sense:
+		 * mark is received as low logic level;
+		 * falling edges are detected as rising edges; etc.
+		 */
+		params.invert_level = true;
+		break;
+	case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL:
+	case CX23885_BOARD_TEVII_S470:
+		/*
+		 * The IR controller on this board only returns pulse widths.
+		 * Any other mode setting will fail to set up the device.
+		 */
+		params.mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH;
+		params.enable = true;
+		params.interrupt_enable = true;
+		params.shutdown = false;
+
+		/* Setup for a standard NEC protocol */
+		params.carrier_freq = 37917; /* Hz, 455 kHz/12 for NEC */
+		params.carrier_range_lower = 33000; /* Hz */
+		params.carrier_range_upper = 43000; /* Hz */
+		params.duty_cycle = 33; /* percent, 33 percent for NEC */
+
+		/*
+		 * NEC max pulse width: (64/3)/(455 kHz/12) * 16 nec_units
+		 * (64/3)/(455 kHz/12) * 16 nec_units * 1.375 = 12378022 ns
+		 */
+		params.max_pulse_width = 12378022; /* ns */
+
+		/*
+		 * NEC noise filter min width: (64/3)/(455 kHz/12) * 1 nec_unit
+		 * (64/3)/(455 kHz/12) * 1 nec_units * 0.625 = 351648 ns
+		 */
+		params.noise_filter_min_width = 351648; /* ns */
+
+		params.modulation = false;
+		params.invert_level = true;
+		break;
+	}
+	v4l2_subdev_call(dev->sd_ir, ir, rx_s_parameters, &params);
+	return 0;
+}
+
+static int cx23885_input_ir_open(struct rc_dev *rc)
+{
+	struct cx23885_kernel_ir *kernel_ir = rc->priv;
+
+	if (kernel_ir->cx == NULL)
+		return -ENODEV;
+
+	return cx23885_input_ir_start(kernel_ir->cx);
+}
+
+static void cx23885_input_ir_stop(struct cx23885_dev *dev)
+{
+	struct v4l2_subdev_ir_parameters params;
+
+	if (dev->sd_ir == NULL)
+		return;
+
+	/*
+	 * Stop the sd_ir subdevice from generating notifications and
+	 * scheduling work.
+	 * It is shutdown this way in order to mitigate a race with
+	 * cx23885_input_rx_work_handler() in the overrun case, which could
+	 * re-enable the subdevice.
+	 */
+	atomic_set(&dev->ir_input_stopping, 1);
+	v4l2_subdev_call(dev->sd_ir, ir, rx_g_parameters, &params);
+	while (params.shutdown == false) {
+		params.enable = false;
+		params.interrupt_enable = false;
+		params.shutdown = true;
+		v4l2_subdev_call(dev->sd_ir, ir, rx_s_parameters, &params);
+		v4l2_subdev_call(dev->sd_ir, ir, rx_g_parameters, &params);
+	}
+	flush_work(&dev->cx25840_work);
+	flush_work(&dev->ir_rx_work);
+	flush_work(&dev->ir_tx_work);
+}
+
+static void cx23885_input_ir_close(struct rc_dev *rc)
+{
+	struct cx23885_kernel_ir *kernel_ir = rc->priv;
+
+	if (kernel_ir->cx != NULL)
+		cx23885_input_ir_stop(kernel_ir->cx);
+}
+
+int cx23885_input_init(struct cx23885_dev *dev)
+{
+	struct cx23885_kernel_ir *kernel_ir;
+	struct rc_dev *rc;
+	char *rc_map;
+	enum rc_driver_type driver_type;
+	unsigned long allowed_protos;
+
+	int ret;
+
+	/*
+	 * If the IR device (hardware registers, chip, GPIO lines, etc.) isn't
+	 * encapsulated in a v4l2_subdev, then I'm not going to deal with it.
+	 */
+	if (dev->sd_ir == NULL)
+		return -ENODEV;
+
+	switch (dev->board) {
+	case CX23885_BOARD_HAUPPAUGE_HVR1270:
+	case CX23885_BOARD_HAUPPAUGE_HVR1850:
+	case CX23885_BOARD_HAUPPAUGE_HVR1290:
+	case CX23885_BOARD_HAUPPAUGE_HVR1250:
+		/* Integrated CX2388[58] IR controller */
+		driver_type = RC_DRIVER_IR_RAW;
+		allowed_protos = RC_TYPE_ALL;
+		/* The grey Hauppauge RC-5 remote */
+		rc_map = RC_MAP_HAUPPAUGE;
+		break;
+	case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL:
+		/* Integrated CX23885 IR controller */
+		driver_type = RC_DRIVER_IR_RAW;
+		allowed_protos = RC_TYPE_NEC;
+		/* The grey Terratec remote with orange buttons */
+		rc_map = RC_MAP_NEC_TERRATEC_CINERGY_XS;
+		break;
+	case CX23885_BOARD_TEVII_S470:
+		/* Integrated CX23885 IR controller */
+		driver_type = RC_DRIVER_IR_RAW;
+		allowed_protos = RC_TYPE_ALL;
+		/* A guess at the remote */
+		rc_map = RC_MAP_TEVII_NEC;
+		break;
+	default:
+		return -ENODEV;
+	}
+
+	/* cx23885 board instance kernel IR state */
+	kernel_ir = kzalloc(sizeof(struct cx23885_kernel_ir), GFP_KERNEL);
+	if (kernel_ir == NULL)
+		return -ENOMEM;
+
+	kernel_ir->cx = dev;
+	kernel_ir->name = kasprintf(GFP_KERNEL, "cx23885 IR (%s)",
+				    cx23885_boards[dev->board].name);
+	kernel_ir->phys = kasprintf(GFP_KERNEL, "pci-%s/ir0",
+				    pci_name(dev->pci));
+
+	/* input device */
+	rc = rc_allocate_device();
+	if (!rc) {
+		ret = -ENOMEM;
+		goto err_out_free;
+	}
+
+	kernel_ir->rc = rc;
+	rc->input_name = kernel_ir->name;
+	rc->input_phys = kernel_ir->phys;
+	rc->input_id.bustype = BUS_PCI;
+	rc->input_id.version = 1;
+	if (dev->pci->subsystem_vendor) {
+		rc->input_id.vendor  = dev->pci->subsystem_vendor;
+		rc->input_id.product = dev->pci->subsystem_device;
+	} else {
+		rc->input_id.vendor  = dev->pci->vendor;
+		rc->input_id.product = dev->pci->device;
+	}
+	rc->dev.parent = &dev->pci->dev;
+	rc->driver_type = driver_type;
+	rc->allowed_protos = allowed_protos;
+	rc->priv = kernel_ir;
+	rc->open = cx23885_input_ir_open;
+	rc->close = cx23885_input_ir_close;
+	rc->map_name = rc_map;
+	rc->driver_name = MODULE_NAME;
+
+	/* Go */
+	dev->kernel_ir = kernel_ir;
+	ret = rc_register_device(rc);
+	if (ret)
+		goto err_out_stop;
+
+	return 0;
+
+err_out_stop:
+	cx23885_input_ir_stop(dev);
+	dev->kernel_ir = NULL;
+	rc_free_device(rc);
+err_out_free:
+	kfree(kernel_ir->phys);
+	kfree(kernel_ir->name);
+	kfree(kernel_ir);
+	return ret;
+}
+
+void cx23885_input_fini(struct cx23885_dev *dev)
+{
+	/* Always stop the IR hardware from generating interrupts */
+	cx23885_input_ir_stop(dev);
+
+	if (dev->kernel_ir == NULL)
+		return;
+	rc_unregister_device(dev->kernel_ir->rc);
+	kfree(dev->kernel_ir->phys);
+	kfree(dev->kernel_ir->name);
+	kfree(dev->kernel_ir);
+	dev->kernel_ir = NULL;
+}
diff --git a/drivers/media/pci/cx23885/cx23885-input.h b/drivers/media/pci/cx23885/cx23885-input.h
new file mode 100644
index 0000000..75ef15d
--- /dev/null
+++ b/drivers/media/pci/cx23885/cx23885-input.h
@@ -0,0 +1,30 @@
+/*
+ *  Driver for the Conexant CX23885/7/8 PCIe bridge
+ *
+ *  Infrared remote control input device
+ *
+ *  Copyright (C) 2009  Andy Walls <awalls@md.metrocast.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 program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You 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 _CX23885_INPUT_H_
+#define _CX23885_INPUT_H_
+int cx23885_input_rx_work_handler(struct cx23885_dev *dev, u32 events);
+
+int cx23885_input_init(struct cx23885_dev *dev);
+void cx23885_input_fini(struct cx23885_dev *dev);
+#endif
diff --git a/drivers/media/pci/cx23885/cx23885-ioctl.c b/drivers/media/pci/cx23885/cx23885-ioctl.c
new file mode 100644
index 0000000..44812ca
--- /dev/null
+++ b/drivers/media/pci/cx23885/cx23885-ioctl.c
@@ -0,0 +1,208 @@
+/*
+ *  Driver for the Conexant CX23885/7/8 PCIe bridge
+ *
+ *  Various common ioctl() support functions
+ *
+ *  Copyright (c) 2009 Andy Walls <awalls@md.metrocast.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 program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You 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 <media/v4l2-chip-ident.h>
+
+int cx23885_g_chip_ident(struct file *file, void *fh,
+			 struct v4l2_dbg_chip_ident *chip)
+{
+	struct cx23885_dev *dev = ((struct cx23885_fh *)fh)->dev;
+	int err = 0;
+	u8 rev;
+
+	chip->ident = V4L2_IDENT_NONE;
+	chip->revision = 0;
+	switch (chip->match.type) {
+	case V4L2_CHIP_MATCH_HOST:
+		switch (chip->match.addr) {
+		case 0:
+			rev = cx_read(RDR_CFG2) & 0xff;
+			switch (dev->pci->device) {
+			case 0x8852:
+				/* rev 0x04 could be '885 or '888. Pick '888. */
+				if (rev == 0x04)
+					chip->ident = V4L2_IDENT_CX23888;
+				else
+					chip->ident = V4L2_IDENT_CX23885;
+				break;
+			case 0x8880:
+				if (rev == 0x0e || rev == 0x0f)
+					chip->ident = V4L2_IDENT_CX23887;
+				else
+					chip->ident = V4L2_IDENT_CX23888;
+				break;
+			default:
+				chip->ident = V4L2_IDENT_UNKNOWN;
+				break;
+			}
+			chip->revision = (dev->pci->device << 16) | (rev << 8) |
+					 (dev->hwrevision & 0xff);
+			break;
+		case 1:
+			if (dev->v4l_device != NULL) {
+				chip->ident = V4L2_IDENT_CX23417;
+				chip->revision = 0;
+			}
+			break;
+		case 2:
+			/*
+			 * The integrated IR controller on the CX23888 is
+			 * host chip 2.  It may not be used/initialized or sd_ir
+			 * may be pointing at the cx25840 subdevice for the
+			 * IR controller on the CX23885.  Thus we find it
+			 * without using the dev->sd_ir pointer.
+			 */
+			call_hw(dev, CX23885_HW_888_IR, core, g_chip_ident,
+				chip);
+			break;
+		default:
+			err = -EINVAL; /* per V4L2 spec */
+			break;
+		}
+		break;
+	case V4L2_CHIP_MATCH_I2C_DRIVER:
+		/* If needed, returns V4L2_IDENT_AMBIGUOUS without extra work */
+		call_all(dev, 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.
+		 */
+		call_all(dev, core, g_chip_ident, chip);
+		break;
+	default:
+		err = -EINVAL;
+		break;
+	}
+	return err;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int cx23885_g_host_register(struct cx23885_dev *dev,
+				   struct v4l2_dbg_register *reg)
+{
+	if ((reg->reg & 0x3) != 0 || reg->reg >= pci_resource_len(dev->pci, 0))
+		return -EINVAL;
+
+	reg->size = 4;
+	reg->val = cx_read(reg->reg);
+	return 0;
+}
+
+static int cx23417_g_register(struct cx23885_dev *dev,
+			      struct v4l2_dbg_register *reg)
+{
+	u32 value;
+
+	if (dev->v4l_device == NULL)
+		return -EINVAL;
+
+	if ((reg->reg & 0x3) != 0 || reg->reg >= 0x10000)
+		return -EINVAL;
+
+	if (mc417_register_read(dev, (u16) reg->reg, &value))
+		return -EINVAL; /* V4L2 spec, but -EREMOTEIO really */
+
+	reg->size = 4;
+	reg->val = value;
+	return 0;
+}
+
+int cx23885_g_register(struct file *file, void *fh,
+		       struct v4l2_dbg_register *reg)
+{
+	struct cx23885_dev *dev = ((struct cx23885_fh *)fh)->dev;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	if (reg->match.type == V4L2_CHIP_MATCH_HOST) {
+		switch (reg->match.addr) {
+		case 0:
+			return cx23885_g_host_register(dev, reg);
+		case 1:
+			return cx23417_g_register(dev, reg);
+		default:
+			break;
+		}
+	}
+
+	/* FIXME - any error returns should not be ignored */
+	call_all(dev, core, g_register, reg);
+	return 0;
+}
+
+static int cx23885_s_host_register(struct cx23885_dev *dev,
+				   struct v4l2_dbg_register *reg)
+{
+	if ((reg->reg & 0x3) != 0 || reg->reg >= pci_resource_len(dev->pci, 0))
+		return -EINVAL;
+
+	reg->size = 4;
+	cx_write(reg->reg, reg->val);
+	return 0;
+}
+
+static int cx23417_s_register(struct cx23885_dev *dev,
+			      struct v4l2_dbg_register *reg)
+{
+	if (dev->v4l_device == NULL)
+		return -EINVAL;
+
+	if ((reg->reg & 0x3) != 0 || reg->reg >= 0x10000)
+		return -EINVAL;
+
+	if (mc417_register_write(dev, (u16) reg->reg, (u32) reg->val))
+		return -EINVAL; /* V4L2 spec, but -EREMOTEIO really */
+
+	reg->size = 4;
+	return 0;
+}
+
+int cx23885_s_register(struct file *file, void *fh,
+		       struct v4l2_dbg_register *reg)
+{
+	struct cx23885_dev *dev = ((struct cx23885_fh *)fh)->dev;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	if (reg->match.type == V4L2_CHIP_MATCH_HOST) {
+		switch (reg->match.addr) {
+		case 0:
+			return cx23885_s_host_register(dev, reg);
+		case 1:
+			return cx23417_s_register(dev, reg);
+		default:
+			break;
+		}
+	}
+
+	/* FIXME - any error returns should not be ignored */
+	call_all(dev, core, s_register, reg);
+	return 0;
+}
+#endif
diff --git a/drivers/media/pci/cx23885/cx23885-ioctl.h b/drivers/media/pci/cx23885/cx23885-ioctl.h
new file mode 100644
index 0000000..315be0c
--- /dev/null
+++ b/drivers/media/pci/cx23885/cx23885-ioctl.h
@@ -0,0 +1,39 @@
+/*
+ *  Driver for the Conexant CX23885/7/8 PCIe bridge
+ *
+ *  Various common ioctl() support functions
+ *
+ *  Copyright (c) 2009 Andy Walls <awalls@md.metrocast.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 program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You 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 _CX23885_IOCTL_H_
+#define _CX23885_IOCTL_H_
+
+int cx23885_g_chip_ident(struct file *file, void *fh,
+			 struct v4l2_dbg_chip_ident *chip);
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+int cx23885_g_register(struct file *file, void *fh,
+		       struct v4l2_dbg_register *reg);
+
+
+int cx23885_s_register(struct file *file, void *fh,
+		       struct v4l2_dbg_register *reg);
+
+#endif
+#endif
diff --git a/drivers/media/pci/cx23885/cx23885-ir.c b/drivers/media/pci/cx23885/cx23885-ir.c
new file mode 100644
index 0000000..7125247
--- /dev/null
+++ b/drivers/media/pci/cx23885/cx23885-ir.c
@@ -0,0 +1,117 @@
+/*
+ *  Driver for the Conexant CX23885/7/8 PCIe bridge
+ *
+ *  Infrared device support routines - non-input, non-vl42_subdev routines
+ *
+ *  Copyright (C) 2009  Andy Walls <awalls@md.metrocast.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 program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You 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 <media/v4l2-device.h>
+
+#include "cx23885.h"
+#include "cx23885-input.h"
+
+#define CX23885_IR_RX_FIFO_SERVICE_REQ		0
+#define CX23885_IR_RX_END_OF_RX_DETECTED	1
+#define CX23885_IR_RX_HW_FIFO_OVERRUN		2
+#define CX23885_IR_RX_SW_FIFO_OVERRUN		3
+
+#define CX23885_IR_TX_FIFO_SERVICE_REQ		0
+
+
+void cx23885_ir_rx_work_handler(struct work_struct *work)
+{
+	struct cx23885_dev *dev =
+			     container_of(work, struct cx23885_dev, ir_rx_work);
+	u32 events = 0;
+	unsigned long *notifications = &dev->ir_rx_notifications;
+
+	if (test_and_clear_bit(CX23885_IR_RX_SW_FIFO_OVERRUN, notifications))
+		events |= V4L2_SUBDEV_IR_RX_SW_FIFO_OVERRUN;
+	if (test_and_clear_bit(CX23885_IR_RX_HW_FIFO_OVERRUN, notifications))
+		events |= V4L2_SUBDEV_IR_RX_HW_FIFO_OVERRUN;
+	if (test_and_clear_bit(CX23885_IR_RX_END_OF_RX_DETECTED, notifications))
+		events |= V4L2_SUBDEV_IR_RX_END_OF_RX_DETECTED;
+	if (test_and_clear_bit(CX23885_IR_RX_FIFO_SERVICE_REQ, notifications))
+		events |= V4L2_SUBDEV_IR_RX_FIFO_SERVICE_REQ;
+
+	if (events == 0)
+		return;
+
+	if (dev->kernel_ir)
+		cx23885_input_rx_work_handler(dev, events);
+}
+
+void cx23885_ir_tx_work_handler(struct work_struct *work)
+{
+	struct cx23885_dev *dev =
+			     container_of(work, struct cx23885_dev, ir_tx_work);
+	u32 events = 0;
+	unsigned long *notifications = &dev->ir_tx_notifications;
+
+	if (test_and_clear_bit(CX23885_IR_TX_FIFO_SERVICE_REQ, notifications))
+		events |= V4L2_SUBDEV_IR_TX_FIFO_SERVICE_REQ;
+
+	if (events == 0)
+		return;
+
+}
+
+/* Possibly called in an IRQ context */
+void cx23885_ir_rx_v4l2_dev_notify(struct v4l2_subdev *sd, u32 events)
+{
+	struct cx23885_dev *dev = to_cx23885(sd->v4l2_dev);
+	unsigned long *notifications = &dev->ir_rx_notifications;
+
+	if (events & V4L2_SUBDEV_IR_RX_FIFO_SERVICE_REQ)
+		set_bit(CX23885_IR_RX_FIFO_SERVICE_REQ, notifications);
+	if (events & V4L2_SUBDEV_IR_RX_END_OF_RX_DETECTED)
+		set_bit(CX23885_IR_RX_END_OF_RX_DETECTED, notifications);
+	if (events & V4L2_SUBDEV_IR_RX_HW_FIFO_OVERRUN)
+		set_bit(CX23885_IR_RX_HW_FIFO_OVERRUN, notifications);
+	if (events & V4L2_SUBDEV_IR_RX_SW_FIFO_OVERRUN)
+		set_bit(CX23885_IR_RX_SW_FIFO_OVERRUN, notifications);
+
+	/*
+	 * For the integrated AV core, we are already in a workqueue context.
+	 * For the CX23888 integrated IR, we are in an interrupt context.
+	 */
+	if (sd == dev->sd_cx25840)
+		cx23885_ir_rx_work_handler(&dev->ir_rx_work);
+	else
+		schedule_work(&dev->ir_rx_work);
+}
+
+/* Possibly called in an IRQ context */
+void cx23885_ir_tx_v4l2_dev_notify(struct v4l2_subdev *sd, u32 events)
+{
+	struct cx23885_dev *dev = to_cx23885(sd->v4l2_dev);
+	unsigned long *notifications = &dev->ir_tx_notifications;
+
+	if (events & V4L2_SUBDEV_IR_TX_FIFO_SERVICE_REQ)
+		set_bit(CX23885_IR_TX_FIFO_SERVICE_REQ, notifications);
+
+	/*
+	 * For the integrated AV core, we are already in a workqueue context.
+	 * For the CX23888 integrated IR, we are in an interrupt context.
+	 */
+	if (sd == dev->sd_cx25840)
+		cx23885_ir_tx_work_handler(&dev->ir_tx_work);
+	else
+		schedule_work(&dev->ir_tx_work);
+}
diff --git a/drivers/media/pci/cx23885/cx23885-ir.h b/drivers/media/pci/cx23885/cx23885-ir.h
new file mode 100644
index 0000000..0c9d8bd
--- /dev/null
+++ b/drivers/media/pci/cx23885/cx23885-ir.h
@@ -0,0 +1,31 @@
+/*
+ *  Driver for the Conexant CX23885/7/8 PCIe bridge
+ *
+ *  Infrared device support routines - non-input, non-vl42_subdev routines
+ *
+ *  Copyright (C) 2009  Andy Walls <awalls@md.metrocast.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 program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You 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 _CX23885_IR_H_
+#define _CX23885_IR_H_
+void cx23885_ir_rx_v4l2_dev_notify(struct v4l2_subdev *sd, u32 events);
+void cx23885_ir_tx_v4l2_dev_notify(struct v4l2_subdev *sd, u32 events);
+
+void cx23885_ir_rx_work_handler(struct work_struct *work);
+void cx23885_ir_tx_work_handler(struct work_struct *work);
+#endif
diff --git a/drivers/media/pci/cx23885/cx23885-reg.h b/drivers/media/pci/cx23885/cx23885-reg.h
new file mode 100644
index 0000000..a99936e
--- /dev/null
+++ b/drivers/media/pci/cx23885/cx23885-reg.h
@@ -0,0 +1,452 @@
+/*
+ *  Driver for the Conexant CX23885 PCIe bridge
+ *
+ *  Copyright (c) 2006 Steven Toth <stoth@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 _CX23885_REG_H_
+#define _CX23885_REG_H_
+
+/*
+Address Map
+0x00000000 -> 0x00009000   TX SRAM  (Fifos)
+0x00010000 -> 0x00013c00   RX SRAM  CMDS + CDT
+
+EACH CMDS struct is 0x80 bytes long
+
+DMAx_PTR1 = 0x03040 address of first cluster
+DMAx_PTR2 = 0x10600 address of the CDT
+DMAx_CNT1 = cluster size in (bytes >> 4) -1
+DMAx_CNT2 = total cdt size for all entries >> 3
+
+Cluster Descriptor entry = 4 DWORDS
+ DWORD 0 -> ptr to cluster
+ DWORD 1 Reserved
+ DWORD 2 Reserved
+ DWORD 3 Reserved
+
+Channel manager Data Structure entry = 20 DWORD
+  0  IntialProgramCounterLow
+  1  IntialProgramCounterHigh
+  2  ClusterDescriptorTableBase
+  3  ClusterDescriptorTableSize
+  4  InstructionQueueBase
+  5  InstructionQueueSize
+...  Reserved
+ 19  Reserved
+*/
+
+/* Risc Instructions */
+#define RISC_CNT_INC		 0x00010000
+#define RISC_CNT_RESET		 0x00030000
+#define RISC_IRQ1		 0x01000000
+#define RISC_IRQ2		 0x02000000
+#define RISC_EOL		 0x04000000
+#define RISC_SOL		 0x08000000
+#define RISC_WRITE		 0x10000000
+#define RISC_SKIP		 0x20000000
+#define RISC_JUMP		 0x70000000
+#define RISC_SYNC		 0x80000000
+#define RISC_RESYNC		 0x80008000
+#define RISC_READ		 0x90000000
+#define RISC_WRITERM		 0xB0000000
+#define RISC_WRITECM		 0xC0000000
+#define RISC_WRITECR		 0xD0000000
+#define RISC_WRITEC		 0x50000000
+#define RISC_READC		 0xA0000000
+
+
+/* Audio and Video Core */
+#define HOST_REG1		0x00000000
+#define HOST_REG2		0x00000001
+#define HOST_REG3		0x00000002
+
+/* Chip Configuration Registers */
+#define CHIP_CTRL		0x00000100
+#define AFE_CTRL		0x00000104
+#define VID_PLL_INT_POST	0x00000108
+#define VID_PLL_FRAC		0x0000010C
+#define AUX_PLL_INT_POST	0x00000110
+#define AUX_PLL_FRAC		0x00000114
+#define SYS_PLL_INT_POST	0x00000118
+#define SYS_PLL_FRAC		0x0000011C
+#define PIN_CTRL		0x00000120
+#define AUD_IO_CTRL		0x00000124
+#define AUD_LOCK1		0x00000128
+#define AUD_LOCK2		0x0000012C
+#define POWER_CTRL		0x00000130
+#define AFE_DIAG_CTRL1		0x00000134
+#define AFE_DIAG_CTRL3		0x0000013C
+#define PLL_DIAG_CTRL		0x00000140
+#define AFE_CLK_OUT_CTRL	0x00000144
+#define DLL1_DIAG_CTRL		0x0000015C
+
+/* GPIO[23:19] Output Enable */
+#define GPIO2_OUT_EN_REG	0x00000160
+/* GPIO[23:19] Data Registers */
+#define GPIO2			0x00000164
+
+#define IFADC_CTRL		0x00000180
+
+/* Infrared Remote Registers */
+#define IR_CNTRL_REG	0x00000200
+#define IR_TXCLK_REG	0x00000204
+#define IR_RXCLK_REG	0x00000208
+#define IR_CDUTY_REG	0x0000020C
+#define IR_STAT_REG	0x00000210
+#define IR_IRQEN_REG	0x00000214
+#define IR_FILTR_REG	0x00000218
+#define IR_FIFO_REG	0x0000023C
+
+/* Video Decoder Registers */
+#define MODE_CTRL		0x00000400
+#define OUT_CTRL1		0x00000404
+#define OUT_CTRL2		0x00000408
+#define GEN_STAT		0x0000040C
+#define INT_STAT_MASK		0x00000410
+#define LUMA_CTRL		0x00000414
+#define HSCALE_CTRL		0x00000418
+#define VSCALE_CTRL		0x0000041C
+#define CHROMA_CTRL		0x00000420
+#define VBI_LINE_CTRL1		0x00000424
+#define VBI_LINE_CTRL2		0x00000428
+#define VBI_LINE_CTRL3		0x0000042C
+#define VBI_LINE_CTRL4		0x00000430
+#define VBI_LINE_CTRL5		0x00000434
+#define VBI_FC_CFG		0x00000438
+#define VBI_MISC_CFG1		0x0000043C
+#define VBI_MISC_CFG2		0x00000440
+#define VBI_PAY1		0x00000444
+#define VBI_PAY2		0x00000448
+#define VBI_CUST1_CFG1		0x0000044C
+#define VBI_CUST1_CFG2		0x00000450
+#define VBI_CUST1_CFG3		0x00000454
+#define VBI_CUST2_CFG1		0x00000458
+#define VBI_CUST2_CFG2		0x0000045C
+#define VBI_CUST2_CFG3		0x00000460
+#define VBI_CUST3_CFG1		0x00000464
+#define VBI_CUST3_CFG2		0x00000468
+#define VBI_CUST3_CFG3		0x0000046C
+#define HORIZ_TIM_CTRL		0x00000470
+#define VERT_TIM_CTRL		0x00000474
+#define SRC_COMB_CFG		0x00000478
+#define CHROMA_VBIOFF_CFG	0x0000047C
+#define FIELD_COUNT		0x00000480
+#define MISC_TIM_CTRL		0x00000484
+#define DFE_CTRL1		0x00000488
+#define DFE_CTRL2		0x0000048C
+#define DFE_CTRL3		0x00000490
+#define PLL_CTRL		0x00000494
+#define HTL_CTRL		0x00000498
+#define COMB_CTRL		0x0000049C
+#define CRUSH_CTRL		0x000004A0
+#define SOFT_RST_CTRL		0x000004A4
+#define CX885_VERSION		0x000004B4
+#define VBI_PASS_CTRL		0x000004BC
+
+/* Audio Decoder Registers */
+/* 8051 Configuration */
+#define DL_CTL		0x00000800
+#define STD_DET_STATUS	0x00000804
+#define STD_DET_CTL	0x00000808
+#define DW8051_INT	0x0000080C
+#define GENERAL_CTL	0x00000810
+#define AAGC_CTL	0x00000814
+#define DEMATRIX_CTL	0x000008CC
+#define PATH1_CTL1	0x000008D0
+#define PATH1_VOL_CTL	0x000008D4
+#define PATH1_EQ_CTL	0x000008D8
+#define PATH1_SC_CTL	0x000008DC
+#define PATH2_CTL1	0x000008E0
+#define PATH2_VOL_CTL	0x000008E4
+#define PATH2_EQ_CTL	0x000008E8
+#define PATH2_SC_CTL	0x000008EC
+
+/* Sample Rate Converter */
+#define SRC_CTL		0x000008F0
+#define SRC_LF_COEF	0x000008F4
+#define SRC1_CTL	0x000008F8
+#define SRC2_CTL	0x000008FC
+#define SRC3_CTL	0x00000900
+#define SRC4_CTL	0x00000904
+#define SRC5_CTL	0x00000908
+#define SRC6_CTL	0x0000090C
+#define BAND_OUT_SEL	0x00000910
+#define I2S_N_CTL	0x00000914
+#define I2S_OUT_CTL	0x00000918
+#define AUTOCONFIG_REG	0x000009C4
+
+/* Audio ADC Registers */
+#define DSM_CTRL1	0x00000000
+#define DSM_CTRL2	0x00000001
+#define CHP_EN_CTRL	0x00000002
+#define CHP_CLK_CTRL1	0x00000004
+#define CHP_CLK_CTRL2	0x00000005
+#define BG_REF_CTRL	0x00000006
+#define SD2_SW_CTRL1	0x00000008
+#define SD2_SW_CTRL2	0x00000009
+#define SD2_BIAS_CTRL	0x0000000A
+#define AMP_BIAS_CTRL	0x0000000C
+#define CH_PWR_CTRL1	0x0000000E
+#define FLD_CH_SEL      (1 << 3)
+#define CH_PWR_CTRL2	0x0000000F
+#define DSM_STATUS1	0x00000010
+#define DSM_STATUS2	0x00000011
+#define DIG_CTL1	0x00000012
+#define DIG_CTL2	0x00000013
+#define I2S_TX_CFG	0x0000001A
+
+#define DEV_CNTRL2	0x00040000
+
+#define PCI_MSK_IR        (1 << 28)
+#define PCI_MSK_AV_CORE   (1 << 27)
+#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)
+#define PCI_MSK_RISC_WR   (1 <<  9)
+#define PCI_MSK_RISC_RD   (1 <<  8)
+#define PCI_MSK_AUD_EXT   (1 <<  4)
+#define PCI_MSK_AUD_INT   (1 <<  3)
+#define PCI_MSK_VID_C     (1 <<  2)
+#define PCI_MSK_VID_B     (1 <<  1)
+#define PCI_MSK_VID_A      1
+#define PCI_INT_MSK	0x00040010
+
+#define PCI_INT_STAT	0x00040014
+#define PCI_INT_MSTAT	0x00040018
+
+#define VID_A_INT_MSK	0x00040020
+#define VID_A_INT_STAT	0x00040024
+#define VID_A_INT_MSTAT	0x00040028
+#define VID_A_INT_SSTAT	0x0004002C
+
+#define VID_B_INT_MSK	0x00040030
+#define VID_B_MSK_BAD_PKT     (1 << 20)
+#define VID_B_MSK_VBI_OPC_ERR (1 << 17)
+#define VID_B_MSK_OPC_ERR     (1 << 16)
+#define VID_B_MSK_VBI_SYNC    (1 << 13)
+#define VID_B_MSK_SYNC        (1 << 12)
+#define VID_B_MSK_VBI_OF      (1 <<  9)
+#define VID_B_MSK_OF          (1 <<  8)
+#define VID_B_MSK_VBI_RISCI2  (1 <<  5)
+#define VID_B_MSK_RISCI2      (1 <<  4)
+#define VID_B_MSK_VBI_RISCI1  (1 <<  1)
+#define VID_B_MSK_RISCI1       1
+#define VID_B_INT_STAT	0x00040034
+#define VID_B_INT_MSTAT	0x00040038
+#define VID_B_INT_SSTAT	0x0004003C
+
+#define VID_B_MSK_BAD_PKT (1 << 20)
+#define VID_B_MSK_OPC_ERR (1 << 16)
+#define VID_B_MSK_SYNC    (1 << 12)
+#define VID_B_MSK_OF      (1 <<  8)
+#define VID_B_MSK_RISCI2  (1 <<  4)
+#define VID_B_MSK_RISCI1   1
+
+#define VID_C_MSK_BAD_PKT (1 << 20)
+#define VID_C_MSK_OPC_ERR (1 << 16)
+#define VID_C_MSK_SYNC    (1 << 12)
+#define VID_C_MSK_OF      (1 <<  8)
+#define VID_C_MSK_RISCI2  (1 <<  4)
+#define VID_C_MSK_RISCI1   1
+
+/* A superset for testing purposes */
+#define VID_BC_MSK_BAD_PKT (1 << 20)
+#define VID_BC_MSK_OPC_ERR (1 << 16)
+#define VID_BC_MSK_SYNC    (1 << 12)
+#define VID_BC_MSK_OF      (1 <<  8)
+#define VID_BC_MSK_VBI_RISCI2 (1 <<  5)
+#define VID_BC_MSK_RISCI2  (1 <<  4)
+#define VID_BC_MSK_VBI_RISCI1 (1 <<  1)
+#define VID_BC_MSK_RISCI1   1
+
+#define VID_C_INT_MSK	0x00040040
+#define VID_C_INT_STAT	0x00040044
+#define VID_C_INT_MSTAT	0x00040048
+#define VID_C_INT_SSTAT	0x0004004C
+
+#define AUDIO_INT_INT_MSK	0x00040050
+#define AUDIO_INT_INT_STAT	0x00040054
+#define AUDIO_INT_INT_MSTAT	0x00040058
+#define AUDIO_INT_INT_SSTAT	0x0004005C
+
+#define AUDIO_EXT_INT_MSK	0x00040060
+#define AUDIO_EXT_INT_STAT	0x00040064
+#define AUDIO_EXT_INT_MSTAT	0x00040068
+#define AUDIO_EXT_INT_SSTAT	0x0004006C
+
+#define RDR_CFG0	0x00050000
+#define RDR_CFG1	0x00050004
+#define RDR_CFG2	0x00050008
+#define RDR_RDRCTL1	0x0005030c
+#define RDR_TLCTL0	0x00050318
+
+/* APB DMAC Current Buffer Pointer */
+#define DMA1_PTR1	0x00100000
+#define DMA2_PTR1	0x00100004
+#define DMA3_PTR1	0x00100008
+#define DMA4_PTR1	0x0010000C
+#define DMA5_PTR1	0x00100010
+#define DMA6_PTR1	0x00100014
+#define DMA7_PTR1	0x00100018
+#define DMA8_PTR1	0x0010001C
+
+/* APB DMAC Current Table Pointer */
+#define DMA1_PTR2	0x00100040
+#define DMA2_PTR2	0x00100044
+#define DMA3_PTR2	0x00100048
+#define DMA4_PTR2	0x0010004C
+#define DMA5_PTR2	0x00100050
+#define DMA6_PTR2	0x00100054
+#define DMA7_PTR2	0x00100058
+#define DMA8_PTR2	0x0010005C
+
+/* APB DMAC Buffer Limit */
+#define DMA1_CNT1	0x00100080
+#define DMA2_CNT1	0x00100084
+#define DMA3_CNT1	0x00100088
+#define DMA4_CNT1	0x0010008C
+#define DMA5_CNT1	0x00100090
+#define DMA6_CNT1	0x00100094
+#define DMA7_CNT1	0x00100098
+#define DMA8_CNT1	0x0010009C
+
+/* APB DMAC Table Size */
+#define DMA1_CNT2	0x001000C0
+#define DMA2_CNT2	0x001000C4
+#define DMA3_CNT2	0x001000C8
+#define DMA4_CNT2	0x001000CC
+#define DMA5_CNT2	0x001000D0
+#define DMA6_CNT2	0x001000D4
+#define DMA7_CNT2	0x001000D8
+#define DMA8_CNT2	0x001000DC
+
+/* Timer Counters */
+#define TM_CNT_LDW	0x00110000
+#define TM_CNT_UW	0x00110004
+#define TM_LMT_LDW	0x00110008
+#define TM_LMT_UW	0x0011000C
+
+/* GPIO */
+#define GP0_IO		0x00110010
+#define GPIO_ISM	0x00110014
+#define SOFT_RESET	0x0011001C
+
+/* GPIO (417 Microsoftcontroller) RW Data */
+#define MC417_RWD	0x00110020
+
+/* GPIO (417 Microsoftcontroller) Output Enable, Low Active */
+#define MC417_OEN	0x00110024
+#define MC417_CTL	0x00110028
+#define ALT_PIN_OUT_SEL 0x0011002C
+#define CLK_DELAY	0x00110048
+#define PAD_CTRL	0x0011004C
+
+/* Video A Interface */
+#define VID_A_GPCNT		0x00130020
+#define VBI_A_GPCNT		0x00130024
+#define VID_A_GPCNT_CTL		0x00130030
+#define VBI_A_GPCNT_CTL		0x00130034
+#define VID_A_DMA_CTL		0x00130040
+#define VID_A_VIP_CTRL		0x00130080
+#define VID_A_PIXEL_FRMT	0x00130084
+#define VID_A_VBI_CTRL		0x00130088
+
+/* Video B Interface */
+#define VID_B_DMA		0x00130100
+#define VBI_B_DMA		0x00130108
+#define VID_B_GPCNT		0x00130120
+#define VBI_B_GPCNT		0x00130124
+#define VID_B_GPCNT_CTL		0x00130134
+#define VBI_B_GPCNT_CTL		0x00130138
+#define VID_B_DMA_CTL		0x00130140
+#define VID_B_SRC_SEL		0x00130144
+#define VID_B_LNGTH		0x00130150
+#define VID_B_HW_SOP_CTL	0x00130154
+#define VID_B_GEN_CTL		0x00130158
+#define VID_B_BD_PKT_STATUS	0x0013015C
+#define VID_B_SOP_STATUS	0x00130160
+#define VID_B_FIFO_OVFL_STAT	0x00130164
+#define VID_B_VLD_MISC		0x00130168
+#define VID_B_TS_CLK_EN		0x0013016C
+#define VID_B_VIP_CTRL		0x00130180
+#define VID_B_PIXEL_FRMT	0x00130184
+
+/* Video C Interface */
+#define VID_C_GPCNT		0x00130220
+#define VID_C_GPCNT_CTL		0x00130230
+#define VBI_C_GPCNT_CTL		0x00130234
+#define VID_C_DMA_CTL		0x00130240
+#define VID_C_LNGTH		0x00130250
+#define VID_C_HW_SOP_CTL	0x00130254
+#define VID_C_GEN_CTL		0x00130258
+#define VID_C_BD_PKT_STATUS	0x0013025C
+#define VID_C_SOP_STATUS	0x00130260
+#define VID_C_FIFO_OVFL_STAT	0x00130264
+#define VID_C_VLD_MISC		0x00130268
+#define VID_C_TS_CLK_EN		0x0013026C
+
+/* Internal Audio Interface */
+#define AUD_INT_A_GPCNT		0x00140020
+#define AUD_INT_B_GPCNT		0x00140024
+#define AUD_INT_A_GPCNT_CTL	0x00140030
+#define AUD_INT_B_GPCNT_CTL	0x00140034
+#define AUD_INT_DMA_CTL		0x00140040
+#define AUD_INT_A_LNGTH		0x00140050
+#define AUD_INT_B_LNGTH		0x00140054
+#define AUD_INT_A_MODE		0x00140058
+#define AUD_INT_B_MODE		0x0014005C
+
+/* External Audio Interface */
+#define AUD_EXT_DMA		0x00140100
+#define AUD_EXT_GPCNT		0x00140120
+#define AUD_EXT_GPCNT_CTL	0x00140130
+#define AUD_EXT_DMA_CTL		0x00140140
+#define AUD_EXT_LNGTH		0x00140150
+#define AUD_EXT_A_MODE		0x00140158
+
+/* I2C Bus 1 */
+#define I2C1_ADDR	0x00180000
+#define I2C1_WDATA	0x00180004
+#define I2C1_CTRL	0x00180008
+#define I2C1_RDATA	0x0018000C
+#define I2C1_STAT	0x00180010
+
+/* I2C Bus 2 */
+#define I2C2_ADDR	0x00190000
+#define I2C2_WDATA	0x00190004
+#define I2C2_CTRL	0x00190008
+#define I2C2_RDATA	0x0019000C
+#define I2C2_STAT	0x00190010
+
+/* I2C Bus 3 */
+#define I2C3_ADDR	0x001A0000
+#define I2C3_WDATA	0x001A0004
+#define I2C3_CTRL	0x001A0008
+#define I2C3_RDATA	0x001A000C
+#define I2C3_STAT	0x001A0010
+
+/* UART */
+#define UART_CTL	0x001B0000
+#define UART_BRD	0x001B0004
+#define UART_ISR	0x001B000C
+#define UART_CNT	0x001B0010
+
+#endif /* _CX23885_REG_H_ */
diff --git a/drivers/media/pci/cx23885/cx23885-vbi.c b/drivers/media/pci/cx23885/cx23885-vbi.c
new file mode 100644
index 0000000..a1154f0
--- /dev/null
+++ b/drivers/media/pci/cx23885/cx23885-vbi.c
@@ -0,0 +1,295 @@
+/*
+ *  Driver for the Conexant CX23885 PCIe bridge
+ *
+ *  Copyright (c) 2007 Steven Toth <stoth@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/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+
+#include "cx23885.h"
+
+static unsigned int vbibufs = 4;
+module_param(vbibufs, int, 0644);
+MODULE_PARM_DESC(vbibufs, "number of vbi buffers, range 2-32");
+
+static unsigned int vbi_debug;
+module_param(vbi_debug, int, 0644);
+MODULE_PARM_DESC(vbi_debug, "enable debug messages [vbi]");
+
+#define dprintk(level, fmt, arg...)\
+	do { if (vbi_debug >= level)\
+		printk(KERN_DEBUG "%s/0: " fmt, dev->name, ## arg);\
+	} while (0)
+
+/* ------------------------------------------------------------------ */
+
+#define VBI_LINE_LENGTH 1440
+#define NTSC_VBI_START_LINE 10        /* line 10 - 21 */
+#define NTSC_VBI_END_LINE   21
+#define NTSC_VBI_LINES      (NTSC_VBI_END_LINE - NTSC_VBI_START_LINE + 1)
+
+
+int cx23885_vbi_fmt(struct file *file, void *priv,
+	struct v4l2_format *f)
+{
+	struct cx23885_fh *fh = priv;
+	struct cx23885_dev *dev = fh->dev;
+
+	if (dev->tvnorm & V4L2_STD_525_60) {
+		/* ntsc */
+		f->fmt.vbi.samples_per_line = VBI_LINE_LENGTH;
+		f->fmt.vbi.sampling_rate = 27000000;
+		f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
+		f->fmt.vbi.offset = 0;
+		f->fmt.vbi.flags = 0;
+		f->fmt.vbi.start[0] = 10;
+		f->fmt.vbi.count[0] = 17;
+		f->fmt.vbi.start[1] = 263 + 10 + 1;
+		f->fmt.vbi.count[1] = 17;
+	} else if (dev->tvnorm & V4L2_STD_625_50) {
+		/* pal */
+		f->fmt.vbi.sampling_rate = 35468950;
+		f->fmt.vbi.start[0] = 7 - 1;
+		f->fmt.vbi.start[1] = 319 - 1;
+	}
+
+	return 0;
+}
+
+/* We're given the Video Interrupt status register.
+ * The cx23885_video_irq() func has already validated
+ * the potential error bits, we just need to
+ * deal with vbi payload and return indication if
+ * we actually processed any payload.
+ */
+int cx23885_vbi_irq(struct cx23885_dev *dev, u32 status)
+{
+	u32 count;
+	int handled = 0;
+
+	if (status & VID_BC_MSK_VBI_RISCI1) {
+		dprintk(1, "%s() VID_BC_MSK_VBI_RISCI1\n", __func__);
+		spin_lock(&dev->slock);
+		count = cx_read(VID_A_GPCNT);
+		cx23885_video_wakeup(dev, &dev->vbiq, count);
+		spin_unlock(&dev->slock);
+		handled++;
+	}
+
+	if (status & VID_BC_MSK_VBI_RISCI2) {
+		dprintk(1, "%s() VID_BC_MSK_VBI_RISCI2\n", __func__);
+		dprintk(2, "stopper vbi\n");
+		spin_lock(&dev->slock);
+		cx23885_restart_vbi_queue(dev, &dev->vbiq);
+		spin_unlock(&dev->slock);
+		handled++;
+	}
+
+	return handled;
+}
+
+static int cx23885_start_vbi_dma(struct cx23885_dev    *dev,
+			 struct cx23885_dmaqueue *q,
+			 struct cx23885_buffer   *buf)
+{
+	dprintk(1, "%s()\n", __func__);
+
+	/* setup fifo + format */
+	cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH02],
+				buf->vb.width, buf->risc.dma);
+
+	/* reset counter */
+	cx_write(VID_A_GPCNT_CTL, 3);
+	cx_write(VID_A_VBI_CTRL, 3);
+	cx_write(VBI_A_GPCNT_CTL, 3);
+	q->count = 1;
+
+	/* enable irq */
+	cx23885_irq_add_enable(dev, 0x01);
+	cx_set(VID_A_INT_MSK, 0x000022);
+
+	/* start dma */
+	cx_set(DEV_CNTRL2, (1<<5));
+	cx_set(VID_A_DMA_CTL, 0x22); /* FIFO and RISC enable */
+
+	return 0;
+}
+
+
+int cx23885_restart_vbi_queue(struct cx23885_dev    *dev,
+			     struct cx23885_dmaqueue *q)
+{
+	struct cx23885_buffer *buf;
+	struct list_head *item;
+
+	if (list_empty(&q->active))
+		return 0;
+
+	buf = list_entry(q->active.next, struct cx23885_buffer, vb.queue);
+	dprintk(2, "restart_queue [%p/%d]: restart dma\n",
+		buf, buf->vb.i);
+	cx23885_start_vbi_dma(dev, q, buf);
+	list_for_each(item, &q->active) {
+		buf = list_entry(item, struct cx23885_buffer, vb.queue);
+		buf->count = q->count++;
+	}
+	mod_timer(&q->timeout, jiffies + (BUFFER_TIMEOUT / 30));
+	return 0;
+}
+
+void cx23885_vbi_timeout(unsigned long data)
+{
+	struct cx23885_dev *dev = (struct cx23885_dev *)data;
+	struct cx23885_dmaqueue *q = &dev->vbiq;
+	struct cx23885_buffer *buf;
+	unsigned long flags;
+
+	/* Stop the VBI engine */
+	cx_clear(VID_A_DMA_CTL, 0x22);
+
+	spin_lock_irqsave(&dev->slock, flags);
+	while (!list_empty(&q->active)) {
+		buf = list_entry(q->active.next, struct cx23885_buffer,
+			vb.queue);
+		list_del(&buf->vb.queue);
+		buf->vb.state = VIDEOBUF_ERROR;
+		wake_up(&buf->vb.done);
+		printk("%s/0: [%p/%d] timeout - dma=0x%08lx\n", dev->name,
+		       buf, buf->vb.i, (unsigned long)buf->risc.dma);
+	}
+	cx23885_restart_vbi_queue(dev, q);
+	spin_unlock_irqrestore(&dev->slock, flags);
+}
+
+/* ------------------------------------------------------------------ */
+#define VBI_LINE_LENGTH 1440
+#define VBI_LINE_COUNT 17
+
+static int
+vbi_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
+{
+	*size = VBI_LINE_COUNT * VBI_LINE_LENGTH * 2;
+	if (0 == *count)
+		*count = vbibufs;
+	if (*count < 2)
+		*count = 2;
+	if (*count > 32)
+		*count = 32;
+	return 0;
+}
+
+static int
+vbi_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
+	    enum v4l2_field field)
+{
+	struct cx23885_fh *fh  = q->priv_data;
+	struct cx23885_dev *dev = fh->dev;
+	struct cx23885_buffer *buf = container_of(vb,
+		struct cx23885_buffer, vb);
+	struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb);
+	unsigned int size;
+	int rc;
+
+	size = VBI_LINE_COUNT * VBI_LINE_LENGTH * 2;
+	if (0 != buf->vb.baddr  &&  buf->vb.bsize < size)
+		return -EINVAL;
+
+	if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
+		buf->vb.width  = VBI_LINE_LENGTH;
+		buf->vb.height = VBI_LINE_COUNT;
+		buf->vb.size   = size;
+		buf->vb.field  = V4L2_FIELD_SEQ_TB;
+
+		rc = videobuf_iolock(q, &buf->vb, NULL);
+		if (0 != rc)
+			goto fail;
+		cx23885_risc_vbibuffer(dev->pci, &buf->risc,
+				 dma->sglist,
+				 0, buf->vb.width * buf->vb.height,
+				 buf->vb.width, 0,
+				 buf->vb.height);
+	}
+	buf->vb.state = VIDEOBUF_PREPARED;
+	return 0;
+
+ fail:
+	cx23885_free_buffer(q, buf);
+	return rc;
+}
+
+static void
+vbi_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+{
+	struct cx23885_buffer   *buf =
+		container_of(vb, struct cx23885_buffer, vb);
+	struct cx23885_buffer   *prev;
+	struct cx23885_fh       *fh   = vq->priv_data;
+	struct cx23885_dev      *dev  = fh->dev;
+	struct cx23885_dmaqueue *q    = &dev->vbiq;
+
+	/* add jump to stopper */
+	buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+	buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma);
+	buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */
+
+	if (list_empty(&q->active)) {
+		list_add_tail(&buf->vb.queue, &q->active);
+		cx23885_start_vbi_dma(dev, q, buf);
+		buf->vb.state = VIDEOBUF_ACTIVE;
+		buf->count    = q->count++;
+		mod_timer(&q->timeout, jiffies + (BUFFER_TIMEOUT / 30));
+		dprintk(2, "[%p/%d] vbi_queue - first active\n",
+			buf, buf->vb.i);
+
+	} else {
+		prev = list_entry(q->active.prev, struct cx23885_buffer,
+			vb.queue);
+		list_add_tail(&buf->vb.queue, &q->active);
+		buf->vb.state = VIDEOBUF_ACTIVE;
+		buf->count    = q->count++;
+		prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+		prev->risc.jmp[2] = cpu_to_le32(0); /* Bits 63-32 */
+		dprintk(2, "[%p/%d] buffer_queue - append to active\n",
+			buf, buf->vb.i);
+	}
+}
+
+static void vbi_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
+{
+	struct cx23885_buffer *buf =
+		container_of(vb, struct cx23885_buffer, vb);
+
+	cx23885_free_buffer(q, buf);
+}
+
+struct videobuf_queue_ops cx23885_vbi_qops = {
+	.buf_setup    = vbi_setup,
+	.buf_prepare  = vbi_prepare,
+	.buf_queue    = vbi_queue,
+	.buf_release  = vbi_release,
+};
+
+/* ------------------------------------------------------------------ */
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/pci/cx23885/cx23885-video.c b/drivers/media/pci/cx23885/cx23885-video.c
new file mode 100644
index 0000000..22f8e7f
--- /dev/null
+++ b/drivers/media/pci/cx23885/cx23885-video.c
@@ -0,0 +1,1926 @@
+/*
+ *  Driver for the Conexant CX23885 PCIe bridge
+ *
+ *  Copyright (c) 2007 Steven Toth <stoth@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/init.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kmod.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/kthread.h>
+#include <asm/div64.h>
+
+#include "cx23885.h"
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include "cx23885-ioctl.h"
+#include "tuner-xc2028.h"
+
+#include <media/cx25840.h>
+
+MODULE_DESCRIPTION("v4l2 driver module for cx23885 based TV cards");
+MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>");
+MODULE_LICENSE("GPL");
+
+/* ------------------------------------------------------------------ */
+
+static unsigned int video_nr[] = {[0 ... (CX23885_MAXBOARDS - 1)] = UNSET };
+static unsigned int vbi_nr[]   = {[0 ... (CX23885_MAXBOARDS - 1)] = UNSET };
+static unsigned int radio_nr[] = {[0 ... (CX23885_MAXBOARDS - 1)] = UNSET };
+
+module_param_array(video_nr, int, NULL, 0444);
+module_param_array(vbi_nr,   int, NULL, 0444);
+module_param_array(radio_nr, int, NULL, 0444);
+
+MODULE_PARM_DESC(video_nr, "video device numbers");
+MODULE_PARM_DESC(vbi_nr, "vbi device numbers");
+MODULE_PARM_DESC(radio_nr, "radio device numbers");
+
+static unsigned int video_debug;
+module_param(video_debug, int, 0644);
+MODULE_PARM_DESC(video_debug, "enable debug messages [video]");
+
+static unsigned int irq_debug;
+module_param(irq_debug, int, 0644);
+MODULE_PARM_DESC(irq_debug, "enable debug messages [IRQ handler]");
+
+static unsigned int vid_limit = 16;
+module_param(vid_limit, int, 0644);
+MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes");
+
+#define dprintk(level, fmt, arg...)\
+	do { if (video_debug >= level)\
+		printk(KERN_DEBUG "%s: " fmt, dev->name, ## arg);\
+	} while (0)
+
+/* ------------------------------------------------------------------- */
+/* static data                                                         */
+
+#define FORMAT_FLAGS_PACKED       0x01
+#if 0
+static struct cx23885_fmt formats[] = {
+	{
+		.name     = "8 bpp, gray",
+		.fourcc   = V4L2_PIX_FMT_GREY,
+		.depth    = 8,
+		.flags    = FORMAT_FLAGS_PACKED,
+	}, {
+		.name     = "15 bpp RGB, le",
+		.fourcc   = V4L2_PIX_FMT_RGB555,
+		.depth    = 16,
+		.flags    = FORMAT_FLAGS_PACKED,
+	}, {
+		.name     = "15 bpp RGB, be",
+		.fourcc   = V4L2_PIX_FMT_RGB555X,
+		.depth    = 16,
+		.flags    = FORMAT_FLAGS_PACKED,
+	}, {
+		.name     = "16 bpp RGB, le",
+		.fourcc   = V4L2_PIX_FMT_RGB565,
+		.depth    = 16,
+		.flags    = FORMAT_FLAGS_PACKED,
+	}, {
+		.name     = "16 bpp RGB, be",
+		.fourcc   = V4L2_PIX_FMT_RGB565X,
+		.depth    = 16,
+		.flags    = FORMAT_FLAGS_PACKED,
+	}, {
+		.name     = "24 bpp RGB, le",
+		.fourcc   = V4L2_PIX_FMT_BGR24,
+		.depth    = 24,
+		.flags    = FORMAT_FLAGS_PACKED,
+	}, {
+		.name     = "32 bpp RGB, le",
+		.fourcc   = V4L2_PIX_FMT_BGR32,
+		.depth    = 32,
+		.flags    = FORMAT_FLAGS_PACKED,
+	}, {
+		.name     = "32 bpp RGB, be",
+		.fourcc   = V4L2_PIX_FMT_RGB32,
+		.depth    = 32,
+		.flags    = FORMAT_FLAGS_PACKED,
+	}, {
+		.name     = "4:2:2, packed, YUYV",
+		.fourcc   = V4L2_PIX_FMT_YUYV,
+		.depth    = 16,
+		.flags    = FORMAT_FLAGS_PACKED,
+	}, {
+		.name     = "4:2:2, packed, UYVY",
+		.fourcc   = V4L2_PIX_FMT_UYVY,
+		.depth    = 16,
+		.flags    = FORMAT_FLAGS_PACKED,
+	},
+};
+#else
+static struct cx23885_fmt formats[] = {
+	{
+#if 0
+		.name     = "4:2:2, packed, UYVY",
+		.fourcc   = V4L2_PIX_FMT_UYVY,
+		.depth    = 16,
+		.flags    = FORMAT_FLAGS_PACKED,
+	}, {
+#endif
+		.name     = "4:2:2, packed, YUYV",
+		.fourcc   = V4L2_PIX_FMT_YUYV,
+		.depth    = 16,
+		.flags    = FORMAT_FLAGS_PACKED,
+	}
+};
+#endif
+
+static struct cx23885_fmt *format_by_fourcc(unsigned int fourcc)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(formats); i++)
+		if (formats[i].fourcc == fourcc)
+			return formats+i;
+
+	printk(KERN_ERR "%s(%c%c%c%c) NOT FOUND\n", __func__,
+		(fourcc & 0xff),
+		((fourcc >> 8) & 0xff),
+		((fourcc >> 16) & 0xff),
+		((fourcc >> 24) & 0xff)
+		);
+	return NULL;
+}
+
+/* ------------------------------------------------------------------- */
+
+static const struct v4l2_queryctrl no_ctl = {
+	.name  = "42",
+	.flags = V4L2_CTRL_FLAG_DISABLED,
+};
+
+static struct cx23885_ctrl cx23885_ctls[] = {
+	/* --- video --- */
+	{
+		.v = {
+			.id            = V4L2_CID_BRIGHTNESS,
+			.name          = "Brightness",
+			.minimum       = 0x00,
+			.maximum       = 0xff,
+			.step          = 1,
+			.default_value = 0x7f,
+			.type          = V4L2_CTRL_TYPE_INTEGER,
+		},
+		.off                   = 128,
+		.reg                   = LUMA_CTRL,
+		.mask                  = 0x00ff,
+		.shift                 = 0,
+	}, {
+		.v = {
+			.id            = V4L2_CID_CONTRAST,
+			.name          = "Contrast",
+			.minimum       = 0,
+			.maximum       = 0x7f,
+			.step          = 1,
+			.default_value = 0x3f,
+			.type          = V4L2_CTRL_TYPE_INTEGER,
+		},
+		.off                   = 0,
+		.reg                   = LUMA_CTRL,
+		.mask                  = 0xff00,
+		.shift                 = 8,
+	}, {
+		.v = {
+			.id            = V4L2_CID_HUE,
+			.name          = "Hue",
+			.minimum       = -127,
+			.maximum       = 128,
+			.step          = 1,
+			.default_value = 0x0,
+			.type          = V4L2_CTRL_TYPE_INTEGER,
+		},
+		.off                   = 128,
+		.reg                   = CHROMA_CTRL,
+		.mask                  = 0xff0000,
+		.shift                 = 16,
+	}, {
+		/* strictly, this only describes only U saturation.
+		 * V saturation is handled specially through code.
+		 */
+		.v = {
+			.id            = V4L2_CID_SATURATION,
+			.name          = "Saturation",
+			.minimum       = 0,
+			.maximum       = 0x7f,
+			.step          = 1,
+			.default_value = 0x3f,
+			.type          = V4L2_CTRL_TYPE_INTEGER,
+		},
+		.off                   = 0,
+		.reg                   = CHROMA_CTRL,
+		.mask                  = 0x00ff,
+		.shift                 = 0,
+	}, {
+	/* --- audio --- */
+		.v = {
+			.id            = V4L2_CID_AUDIO_MUTE,
+			.name          = "Mute",
+			.minimum       = 0,
+			.maximum       = 1,
+			.default_value = 1,
+			.type          = V4L2_CTRL_TYPE_BOOLEAN,
+		},
+		.reg                   = PATH1_CTL1,
+		.mask                  = (0x1f << 24),
+		.shift                 = 24,
+	}, {
+		.v = {
+			.id            = V4L2_CID_AUDIO_VOLUME,
+			.name          = "Volume",
+			.minimum       = 0,
+			.maximum       = 65535,
+			.step          = 65535 / 100,
+			.default_value = 65535,
+			.type          = V4L2_CTRL_TYPE_INTEGER,
+		},
+		.reg                   = PATH1_VOL_CTL,
+		.mask                  = 0xff,
+		.shift                 = 0,
+	}
+};
+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,
+	V4L2_CID_CONTRAST,
+	V4L2_CID_SATURATION,
+	V4L2_CID_HUE,
+	V4L2_CID_AUDIO_VOLUME,
+	V4L2_CID_AUDIO_MUTE,
+	0
+};
+
+static const u32 *ctrl_classes[] = {
+	cx23885_user_ctrls,
+	NULL
+};
+
+void cx23885_video_wakeup(struct cx23885_dev *dev,
+	struct cx23885_dmaqueue *q, u32 count)
+{
+	struct cx23885_buffer *buf;
+	int bc;
+
+	for (bc = 0;; bc++) {
+		if (list_empty(&q->active))
+			break;
+		buf = list_entry(q->active.next,
+				 struct cx23885_buffer, vb.queue);
+
+		/* count comes from the hw and is is 16bit wide --
+		 * this trick handles wrap-arounds correctly for
+		 * up to 32767 buffers in flight... */
+		if ((s16) (count - buf->count) < 0)
+			break;
+
+		do_gettimeofday(&buf->vb.ts);
+		dprintk(2, "[%p/%d] wakeup reg=%d buf=%d\n", buf, buf->vb.i,
+			count, buf->count);
+		buf->vb.state = VIDEOBUF_DONE;
+		list_del(&buf->vb.queue);
+		wake_up(&buf->vb.done);
+	}
+	if (list_empty(&q->active))
+		del_timer(&q->timeout);
+	else
+		mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
+	if (bc != 1)
+		printk(KERN_ERR "%s: %d buffers handled (should be 1)\n",
+			__func__, bc);
+}
+
+int cx23885_set_tvnorm(struct cx23885_dev *dev, v4l2_std_id norm)
+{
+	dprintk(1, "%s(norm = 0x%08x) name: [%s]\n",
+		__func__,
+		(unsigned int)norm,
+		v4l2_norm_to_name(norm));
+
+	dev->tvnorm = norm;
+
+	call_all(dev, core, s_std, norm);
+
+	return 0;
+}
+
+static struct video_device *cx23885_vdev_init(struct cx23885_dev *dev,
+				    struct pci_dev *pci,
+				    struct video_device *template,
+				    char *type)
+{
+	struct video_device *vfd;
+	dprintk(1, "%s()\n", __func__);
+
+	vfd = video_device_alloc();
+	if (NULL == vfd)
+		return NULL;
+	*vfd = *template;
+	vfd->v4l2_dev = &dev->v4l2_dev;
+	vfd->release = video_device_release;
+	snprintf(vfd->name, sizeof(vfd->name), "%s (%s)",
+		 cx23885_boards[dev->board].name, type);
+	video_set_drvdata(vfd, dev);
+	return vfd;
+}
+
+static int cx23885_ctrl_query(struct v4l2_queryctrl *qctrl)
+{
+	int i;
+
+	if (qctrl->id < V4L2_CID_BASE ||
+	    qctrl->id >= V4L2_CID_LASTP1)
+		return -EINVAL;
+	for (i = 0; i < CX23885_CTLS; i++)
+		if (cx23885_ctls[i].v.id == qctrl->id)
+			break;
+	if (i == CX23885_CTLS) {
+		*qctrl = no_ctl;
+		return 0;
+	}
+	*qctrl = cx23885_ctls[i].v;
+	return 0;
+}
+
+/* ------------------------------------------------------------------- */
+/* resource management                                                 */
+
+static int res_get(struct cx23885_dev *dev, struct cx23885_fh *fh,
+	unsigned int bit)
+{
+	dprintk(1, "%s()\n", __func__);
+	if (fh->resources & bit)
+		/* have it already allocated */
+		return 1;
+
+	/* is it free? */
+	mutex_lock(&dev->lock);
+	if (dev->resources & bit) {
+		/* no, someone else uses it */
+		mutex_unlock(&dev->lock);
+		return 0;
+	}
+	/* it's free, grab it */
+	fh->resources  |= bit;
+	dev->resources |= bit;
+	dprintk(1, "res: get %d\n", bit);
+	mutex_unlock(&dev->lock);
+	return 1;
+}
+
+static int res_check(struct cx23885_fh *fh, unsigned int bit)
+{
+	return fh->resources & bit;
+}
+
+static int res_locked(struct cx23885_dev *dev, unsigned int bit)
+{
+	return dev->resources & bit;
+}
+
+static void res_free(struct cx23885_dev *dev, struct cx23885_fh *fh,
+	unsigned int bits)
+{
+	BUG_ON((fh->resources & bits) != bits);
+	dprintk(1, "%s()\n", __func__);
+
+	mutex_lock(&dev->lock);
+	fh->resources  &= ~bits;
+	dev->resources &= ~bits;
+	dprintk(1, "res: put %d\n", bits);
+	mutex_unlock(&dev->lock);
+}
+
+static int cx23885_flatiron_write(struct cx23885_dev *dev, u8 reg, u8 data)
+{
+	/* 8 bit registers, 8 bit values */
+	u8 buf[] = { reg, data };
+
+	struct i2c_msg msg = { .addr = 0x98 >> 1,
+		.flags = 0, .buf = buf, .len = 2 };
+
+	return i2c_transfer(&dev->i2c_bus[2].i2c_adap, &msg, 1);
+}
+
+static u8 cx23885_flatiron_read(struct cx23885_dev *dev, u8 reg)
+{
+	/* 8 bit registers, 8 bit values */
+	int ret;
+	u8 b0[] = { reg };
+	u8 b1[] = { 0 };
+
+	struct i2c_msg msg[] = {
+		{ .addr = 0x98 >> 1, .flags = 0, .buf = b0, .len = 1 },
+		{ .addr = 0x98 >> 1, .flags = I2C_M_RD, .buf = b1, .len = 1 }
+	};
+
+	ret = i2c_transfer(&dev->i2c_bus[2].i2c_adap, &msg[0], 2);
+	if (ret != 2)
+		printk(KERN_ERR "%s() error\n", __func__);
+
+	return b1[0];
+}
+
+static void cx23885_flatiron_dump(struct cx23885_dev *dev)
+{
+	int i;
+	dprintk(1, "Flatiron dump\n");
+	for (i = 0; i < 0x24; i++) {
+		dprintk(1, "FI[%02x] = %02x\n", i,
+			cx23885_flatiron_read(dev, i));
+	}
+}
+
+static int cx23885_flatiron_mux(struct cx23885_dev *dev, int input)
+{
+	u8 val;
+	dprintk(1, "%s(input = %d)\n", __func__, input);
+
+	if (input == 1)
+		val = cx23885_flatiron_read(dev, CH_PWR_CTRL1) & ~FLD_CH_SEL;
+	else if (input == 2)
+		val = cx23885_flatiron_read(dev, CH_PWR_CTRL1) | FLD_CH_SEL;
+	else
+		return -EINVAL;
+
+	val |= 0x20; /* Enable clock to delta-sigma and dec filter */
+
+	cx23885_flatiron_write(dev, CH_PWR_CTRL1, val);
+
+	/* Wake up */
+	cx23885_flatiron_write(dev, CH_PWR_CTRL2, 0);
+
+	if (video_debug)
+		cx23885_flatiron_dump(dev);
+
+	return 0;
+}
+
+static int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input)
+{
+	dprintk(1, "%s() video_mux: %d [vmux=%d, gpio=0x%x,0x%x,0x%x,0x%x]\n",
+		__func__,
+		input, INPUT(input)->vmux,
+		INPUT(input)->gpio0, INPUT(input)->gpio1,
+		INPUT(input)->gpio2, INPUT(input)->gpio3);
+	dev->input = input;
+
+	if (dev->board == CX23885_BOARD_MYGICA_X8506 ||
+		dev->board == CX23885_BOARD_MAGICPRO_PROHDTVE2 ||
+		dev->board == CX23885_BOARD_MYGICA_X8507) {
+		/* Select Analog TV */
+		if (INPUT(input)->type == CX23885_VMUX_TELEVISION)
+			cx23885_gpio_clear(dev, GPIO_0);
+	}
+
+	/* Tell the internal A/V decoder */
+	v4l2_subdev_call(dev->sd_cx25840, video, s_routing,
+			INPUT(input)->vmux, 0, 0);
+
+	if ((dev->board == CX23885_BOARD_HAUPPAUGE_HVR1800) ||
+		(dev->board == CX23885_BOARD_MPX885) ||
+		(dev->board == CX23885_BOARD_HAUPPAUGE_HVR1250) ||
+		(dev->board == CX23885_BOARD_HAUPPAUGE_HVR1255) ||
+		(dev->board == CX23885_BOARD_HAUPPAUGE_HVR1255_22111) ||
+		(dev->board == CX23885_BOARD_HAUPPAUGE_HVR1850)) {
+		/* Configure audio routing */
+		v4l2_subdev_call(dev->sd_cx25840, audio, s_routing,
+			INPUT(input)->amux, 0, 0);
+
+		if (INPUT(input)->amux == CX25840_AUDIO7)
+			cx23885_flatiron_mux(dev, 1);
+		else if (INPUT(input)->amux == CX25840_AUDIO6)
+			cx23885_flatiron_mux(dev, 2);
+	}
+
+	return 0;
+}
+
+static int cx23885_audio_mux(struct cx23885_dev *dev, unsigned int input)
+{
+	dprintk(1, "%s(input=%d)\n", __func__, input);
+
+	/* The baseband video core of the cx23885 has two audio inputs.
+	 * LR1 and LR2. In almost every single case so far only HVR1xxx
+	 * cards we've only ever supported LR1. Time to support LR2,
+	 * which is available via the optional white breakout header on
+	 * the board.
+	 * We'll use a could of existing enums in the card struct to allow
+	 * devs to specify which baseband input they need, or just default
+	 * to what we've always used.
+	 */
+	if (INPUT(input)->amux == CX25840_AUDIO7)
+		cx23885_flatiron_mux(dev, 1);
+	else if (INPUT(input)->amux == CX25840_AUDIO6)
+		cx23885_flatiron_mux(dev, 2);
+	else {
+		/* Not specifically defined, assume the default. */
+		cx23885_flatiron_mux(dev, 1);
+	}
+
+	return 0;
+}
+
+/* ------------------------------------------------------------------ */
+static int cx23885_start_video_dma(struct cx23885_dev *dev,
+			   struct cx23885_dmaqueue *q,
+			   struct cx23885_buffer *buf)
+{
+	dprintk(1, "%s()\n", __func__);
+
+	/* Stop the dma/fifo before we tamper with it's risc programs */
+	cx_clear(VID_A_DMA_CTL, 0x11);
+
+	/* setup fifo + format */
+	cx23885_sram_channel_setup(dev, &dev->sram_channels[SRAM_CH01],
+				buf->bpl, buf->risc.dma);
+
+	/* reset counter */
+	cx_write(VID_A_GPCNT_CTL, 3);
+	q->count = 1;
+
+	/* enable irq */
+	cx23885_irq_add_enable(dev, 0x01);
+	cx_set(VID_A_INT_MSK, 0x000011);
+
+	/* start dma */
+	cx_set(DEV_CNTRL2, (1<<5));
+	cx_set(VID_A_DMA_CTL, 0x11); /* FIFO and RISC enable */
+
+	return 0;
+}
+
+
+static int cx23885_restart_video_queue(struct cx23885_dev *dev,
+			       struct cx23885_dmaqueue *q)
+{
+	struct cx23885_buffer *buf, *prev;
+	struct list_head *item;
+	dprintk(1, "%s()\n", __func__);
+
+	if (!list_empty(&q->active)) {
+		buf = list_entry(q->active.next, struct cx23885_buffer,
+			vb.queue);
+		dprintk(2, "restart_queue [%p/%d]: restart dma\n",
+			buf, buf->vb.i);
+		cx23885_start_video_dma(dev, q, buf);
+		list_for_each(item, &q->active) {
+			buf = list_entry(item, struct cx23885_buffer,
+				vb.queue);
+			buf->count    = q->count++;
+		}
+		mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
+		return 0;
+	}
+
+	prev = NULL;
+	for (;;) {
+		if (list_empty(&q->queued))
+			return 0;
+		buf = list_entry(q->queued.next, struct cx23885_buffer,
+			vb.queue);
+		if (NULL == prev) {
+			list_move_tail(&buf->vb.queue, &q->active);
+			cx23885_start_video_dma(dev, q, buf);
+			buf->vb.state = VIDEOBUF_ACTIVE;
+			buf->count    = q->count++;
+			mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
+			dprintk(2, "[%p/%d] restart_queue - first active\n",
+				buf, buf->vb.i);
+
+		} else if (prev->vb.width  == buf->vb.width  &&
+			   prev->vb.height == buf->vb.height &&
+			   prev->fmt       == buf->fmt) {
+			list_move_tail(&buf->vb.queue, &q->active);
+			buf->vb.state = VIDEOBUF_ACTIVE;
+			buf->count    = q->count++;
+			prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+			prev->risc.jmp[2] = cpu_to_le32(0); /* Bits 63 - 32 */
+			dprintk(2, "[%p/%d] restart_queue - move to active\n",
+				buf, buf->vb.i);
+		} else {
+			return 0;
+		}
+		prev = buf;
+	}
+}
+
+static int buffer_setup(struct videobuf_queue *q, unsigned int *count,
+	unsigned int *size)
+{
+	struct cx23885_fh *fh = q->priv_data;
+
+	*size = fh->fmt->depth*fh->width*fh->height >> 3;
+	if (0 == *count)
+		*count = 32;
+	if (*size * *count > vid_limit * 1024 * 1024)
+		*count = (vid_limit * 1024 * 1024) / *size;
+	return 0;
+}
+
+static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
+	       enum v4l2_field field)
+{
+	struct cx23885_fh *fh  = q->priv_data;
+	struct cx23885_dev *dev = fh->dev;
+	struct cx23885_buffer *buf =
+		container_of(vb, struct cx23885_buffer, vb);
+	int rc, init_buffer = 0;
+	u32 line0_offset, line1_offset;
+	struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb);
+	int field_tff;
+
+	BUG_ON(NULL == fh->fmt);
+	if (fh->width  < 48 || fh->width  > norm_maxw(dev->tvnorm) ||
+	    fh->height < 32 || fh->height > norm_maxh(dev->tvnorm))
+		return -EINVAL;
+	buf->vb.size = (fh->width * fh->height * fh->fmt->depth) >> 3;
+	if (0 != buf->vb.baddr  &&  buf->vb.bsize < buf->vb.size)
+		return -EINVAL;
+
+	if (buf->fmt       != fh->fmt    ||
+	    buf->vb.width  != fh->width  ||
+	    buf->vb.height != fh->height ||
+	    buf->vb.field  != field) {
+		buf->fmt       = fh->fmt;
+		buf->vb.width  = fh->width;
+		buf->vb.height = fh->height;
+		buf->vb.field  = field;
+		init_buffer = 1;
+	}
+
+	if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
+		init_buffer = 1;
+		rc = videobuf_iolock(q, &buf->vb, NULL);
+		if (0 != rc)
+			goto fail;
+	}
+
+	if (init_buffer) {
+		buf->bpl = buf->vb.width * buf->fmt->depth >> 3;
+		switch (buf->vb.field) {
+		case V4L2_FIELD_TOP:
+			cx23885_risc_buffer(dev->pci, &buf->risc,
+					 dma->sglist, 0, UNSET,
+					 buf->bpl, 0, buf->vb.height);
+			break;
+		case V4L2_FIELD_BOTTOM:
+			cx23885_risc_buffer(dev->pci, &buf->risc,
+					 dma->sglist, UNSET, 0,
+					 buf->bpl, 0, buf->vb.height);
+			break;
+		case V4L2_FIELD_INTERLACED:
+			if (dev->tvnorm & V4L2_STD_NTSC)
+				/* NTSC or  */
+				field_tff = 1;
+			else
+				field_tff = 0;
+
+			if (cx23885_boards[dev->board].force_bff)
+				/* PAL / SECAM OR 888 in NTSC MODE */
+				field_tff = 0;
+
+			if (field_tff) {
+				/* cx25840 transmits NTSC bottom field first */
+				dprintk(1, "%s() Creating TFF/NTSC risc\n",
+					__func__);
+				line0_offset = buf->bpl;
+				line1_offset = 0;
+			} else {
+				/* All other formats are top field first */
+				dprintk(1, "%s() Creating BFF/PAL/SECAM risc\n",
+					__func__);
+				line0_offset = 0;
+				line1_offset = buf->bpl;
+			}
+			cx23885_risc_buffer(dev->pci, &buf->risc,
+					dma->sglist, line0_offset,
+					line1_offset,
+					buf->bpl, buf->bpl,
+					buf->vb.height >> 1);
+			break;
+		case V4L2_FIELD_SEQ_TB:
+			cx23885_risc_buffer(dev->pci, &buf->risc,
+					 dma->sglist,
+					 0, buf->bpl * (buf->vb.height >> 1),
+					 buf->bpl, 0,
+					 buf->vb.height >> 1);
+			break;
+		case V4L2_FIELD_SEQ_BT:
+			cx23885_risc_buffer(dev->pci, &buf->risc,
+					 dma->sglist,
+					 buf->bpl * (buf->vb.height >> 1), 0,
+					 buf->bpl, 0,
+					 buf->vb.height >> 1);
+			break;
+		default:
+			BUG();
+		}
+	}
+	dprintk(2, "[%p/%d] buffer_prep - %dx%d %dbpp \"%s\" - dma=0x%08lx\n",
+		buf, buf->vb.i,
+		fh->width, fh->height, fh->fmt->depth, fh->fmt->name,
+		(unsigned long)buf->risc.dma);
+
+	buf->vb.state = VIDEOBUF_PREPARED;
+	return 0;
+
+ fail:
+	cx23885_free_buffer(q, buf);
+	return rc;
+}
+
+static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+{
+	struct cx23885_buffer   *buf = container_of(vb,
+		struct cx23885_buffer, vb);
+	struct cx23885_buffer   *prev;
+	struct cx23885_fh       *fh   = vq->priv_data;
+	struct cx23885_dev      *dev  = fh->dev;
+	struct cx23885_dmaqueue *q    = &dev->vidq;
+
+	/* add jump to stopper */
+	buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+	buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma);
+	buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */
+
+	if (!list_empty(&q->queued)) {
+		list_add_tail(&buf->vb.queue, &q->queued);
+		buf->vb.state = VIDEOBUF_QUEUED;
+		dprintk(2, "[%p/%d] buffer_queue - append to queued\n",
+			buf, buf->vb.i);
+
+	} else if (list_empty(&q->active)) {
+		list_add_tail(&buf->vb.queue, &q->active);
+		cx23885_start_video_dma(dev, q, buf);
+		buf->vb.state = VIDEOBUF_ACTIVE;
+		buf->count    = q->count++;
+		mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
+		dprintk(2, "[%p/%d] buffer_queue - first active\n",
+			buf, buf->vb.i);
+
+	} else {
+		prev = list_entry(q->active.prev, struct cx23885_buffer,
+			vb.queue);
+		if (prev->vb.width  == buf->vb.width  &&
+		    prev->vb.height == buf->vb.height &&
+		    prev->fmt       == buf->fmt) {
+			list_add_tail(&buf->vb.queue, &q->active);
+			buf->vb.state = VIDEOBUF_ACTIVE;
+			buf->count    = q->count++;
+			prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+			/* 64 bit bits 63-32 */
+			prev->risc.jmp[2] = cpu_to_le32(0);
+			dprintk(2, "[%p/%d] buffer_queue - append to active\n",
+				buf, buf->vb.i);
+
+		} else {
+			list_add_tail(&buf->vb.queue, &q->queued);
+			buf->vb.state = VIDEOBUF_QUEUED;
+			dprintk(2, "[%p/%d] buffer_queue - first queued\n",
+				buf, buf->vb.i);
+		}
+	}
+}
+
+static void buffer_release(struct videobuf_queue *q,
+	struct videobuf_buffer *vb)
+{
+	struct cx23885_buffer *buf = container_of(vb,
+		struct cx23885_buffer, vb);
+
+	cx23885_free_buffer(q, buf);
+}
+
+static struct videobuf_queue_ops cx23885_video_qops = {
+	.buf_setup    = buffer_setup,
+	.buf_prepare  = buffer_prepare,
+	.buf_queue    = buffer_queue,
+	.buf_release  = buffer_release,
+};
+
+static struct videobuf_queue *get_queue(struct cx23885_fh *fh)
+{
+	switch (fh->type) {
+	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+		return &fh->vidq;
+	case V4L2_BUF_TYPE_VBI_CAPTURE:
+		return &fh->vbiq;
+	default:
+		BUG();
+		return NULL;
+	}
+}
+
+static int get_resource(struct cx23885_fh *fh)
+{
+	switch (fh->type) {
+	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+		return RESOURCE_VIDEO;
+	case V4L2_BUF_TYPE_VBI_CAPTURE:
+		return RESOURCE_VBI;
+	default:
+		BUG();
+		return 0;
+	}
+}
+
+static int video_open(struct file *file)
+{
+	struct video_device *vdev = video_devdata(file);
+	struct cx23885_dev *dev = video_drvdata(file);
+	struct cx23885_fh *fh;
+	enum v4l2_buf_type type = 0;
+	int radio = 0;
+
+	switch (vdev->vfl_type) {
+	case VFL_TYPE_GRABBER:
+		type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+		break;
+	case VFL_TYPE_VBI:
+		type = V4L2_BUF_TYPE_VBI_CAPTURE;
+		break;
+	case VFL_TYPE_RADIO:
+		radio = 1;
+		break;
+	}
+
+	dprintk(1, "open dev=%s radio=%d type=%s\n",
+		video_device_node_name(vdev), radio, v4l2_type_names[type]);
+
+	/* allocate + initialize per filehandle data */
+	fh = kzalloc(sizeof(*fh), GFP_KERNEL);
+	if (NULL == fh)
+		return -ENOMEM;
+
+	file->private_data = fh;
+	fh->dev      = dev;
+	fh->radio    = radio;
+	fh->type     = type;
+	fh->width    = 320;
+	fh->height   = 240;
+	fh->fmt      = format_by_fourcc(V4L2_PIX_FMT_YUYV);
+
+	videobuf_queue_sg_init(&fh->vidq, &cx23885_video_qops,
+			    &dev->pci->dev, &dev->slock,
+			    V4L2_BUF_TYPE_VIDEO_CAPTURE,
+			    V4L2_FIELD_INTERLACED,
+			    sizeof(struct cx23885_buffer),
+			    fh, NULL);
+
+	videobuf_queue_sg_init(&fh->vbiq, &cx23885_vbi_qops,
+		&dev->pci->dev, &dev->slock,
+		V4L2_BUF_TYPE_VBI_CAPTURE,
+		V4L2_FIELD_SEQ_TB,
+		sizeof(struct cx23885_buffer),
+		fh, NULL);
+
+
+	dprintk(1, "post videobuf_queue_init()\n");
+
+	return 0;
+}
+
+static ssize_t video_read(struct file *file, char __user *data,
+	size_t count, loff_t *ppos)
+{
+	struct cx23885_fh *fh = file->private_data;
+
+	switch (fh->type) {
+	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+		if (res_locked(fh->dev, RESOURCE_VIDEO))
+			return -EBUSY;
+		return videobuf_read_one(&fh->vidq, data, count, ppos,
+					 file->f_flags & O_NONBLOCK);
+	case V4L2_BUF_TYPE_VBI_CAPTURE:
+		if (!res_get(fh->dev, fh, RESOURCE_VBI))
+			return -EBUSY;
+		return videobuf_read_stream(&fh->vbiq, data, count, ppos, 1,
+					    file->f_flags & O_NONBLOCK);
+	default:
+		BUG();
+		return 0;
+	}
+}
+
+static unsigned int video_poll(struct file *file,
+	struct poll_table_struct *wait)
+{
+	struct cx23885_fh *fh = file->private_data;
+	struct cx23885_buffer *buf;
+	unsigned int rc = POLLERR;
+
+	if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) {
+		if (!res_get(fh->dev, fh, RESOURCE_VBI))
+			return POLLERR;
+		return videobuf_poll_stream(file, &fh->vbiq, wait);
+	}
+
+	mutex_lock(&fh->vidq.vb_lock);
+	if (res_check(fh, RESOURCE_VIDEO)) {
+		/* streaming capture */
+		if (list_empty(&fh->vidq.stream))
+			goto done;
+		buf = list_entry(fh->vidq.stream.next,
+			struct cx23885_buffer, vb.stream);
+	} else {
+		/* read() capture */
+		buf = (struct cx23885_buffer *)fh->vidq.read_buf;
+		if (NULL == buf)
+			goto done;
+	}
+	poll_wait(file, &buf->vb.done, wait);
+	if (buf->vb.state == VIDEOBUF_DONE ||
+	    buf->vb.state == VIDEOBUF_ERROR)
+		rc =  POLLIN|POLLRDNORM;
+	else
+		rc = 0;
+done:
+	mutex_unlock(&fh->vidq.vb_lock);
+	return rc;
+}
+
+static int video_release(struct file *file)
+{
+	struct cx23885_fh *fh = file->private_data;
+	struct cx23885_dev *dev = fh->dev;
+
+	/* turn off overlay */
+	if (res_check(fh, RESOURCE_OVERLAY)) {
+		/* FIXME */
+		res_free(dev, fh, RESOURCE_OVERLAY);
+	}
+
+	/* stop video capture */
+	if (res_check(fh, RESOURCE_VIDEO)) {
+		videobuf_queue_cancel(&fh->vidq);
+		res_free(dev, fh, RESOURCE_VIDEO);
+	}
+	if (fh->vidq.read_buf) {
+		buffer_release(&fh->vidq, fh->vidq.read_buf);
+		kfree(fh->vidq.read_buf);
+	}
+
+	/* stop vbi capture */
+	if (res_check(fh, RESOURCE_VBI)) {
+		if (fh->vbiq.streaming)
+			videobuf_streamoff(&fh->vbiq);
+		if (fh->vbiq.reading)
+			videobuf_read_stop(&fh->vbiq);
+		res_free(dev, fh, RESOURCE_VBI);
+	}
+
+	videobuf_mmap_free(&fh->vidq);
+	videobuf_mmap_free(&fh->vbiq);
+
+	file->private_data = NULL;
+	kfree(fh);
+
+	/* We are not putting the tuner to sleep here on exit, because
+	 * we want to use the mpeg encoder in another session to capture
+	 * tuner video. Closing this will result in no video to the encoder.
+	 */
+
+	return 0;
+}
+
+static int video_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	struct cx23885_fh *fh = file->private_data;
+
+	return videobuf_mmap_mapper(get_queue(fh), vma);
+}
+
+/* ------------------------------------------------------------------ */
+/* VIDEO CTRL IOCTLS                                                  */
+
+int cx23885_get_control(struct cx23885_dev *dev,
+	struct v4l2_control *ctl)
+{
+	dprintk(1, "%s() calling cx25840(VIDIOC_G_CTRL)\n", __func__);
+	call_all(dev, core, g_ctrl, ctl);
+	return 0;
+}
+
+int cx23885_set_control(struct cx23885_dev *dev,
+	struct v4l2_control *ctl)
+{
+	dprintk(1, "%s() calling cx25840(VIDIOC_S_CTRL)\n", __func__);
+	call_all(dev, core, s_ctrl, ctl);
+
+	return 0;
+}
+
+static void init_controls(struct cx23885_dev *dev)
+{
+	struct v4l2_control ctrl;
+	int i;
+
+	for (i = 0; i < CX23885_CTLS; i++) {
+		ctrl.id = cx23885_ctls[i].v.id;
+		ctrl.value = cx23885_ctls[i].v.default_value;
+
+		cx23885_set_control(dev, &ctrl);
+	}
+}
+
+/* ------------------------------------------------------------------ */
+/* VIDEO IOCTLS                                                       */
+
+static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
+	struct v4l2_format *f)
+{
+	struct cx23885_fh *fh   = priv;
+
+	f->fmt.pix.width        = fh->width;
+	f->fmt.pix.height       = fh->height;
+	f->fmt.pix.field        = fh->vidq.field;
+	f->fmt.pix.pixelformat  = fh->fmt->fourcc;
+	f->fmt.pix.bytesperline =
+		(f->fmt.pix.width * fh->fmt->depth) >> 3;
+	f->fmt.pix.sizeimage =
+		f->fmt.pix.height * f->fmt.pix.bytesperline;
+
+	return 0;
+}
+
+static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
+	struct v4l2_format *f)
+{
+	struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
+	struct cx23885_fmt *fmt;
+	enum v4l2_field   field;
+	unsigned int      maxw, maxh;
+
+	fmt = format_by_fourcc(f->fmt.pix.pixelformat);
+	if (NULL == fmt)
+		return -EINVAL;
+
+	field = f->fmt.pix.field;
+	maxw  = norm_maxw(dev->tvnorm);
+	maxh  = norm_maxh(dev->tvnorm);
+
+	if (V4L2_FIELD_ANY == field) {
+		field = (f->fmt.pix.height > maxh/2)
+			? V4L2_FIELD_INTERLACED
+			: V4L2_FIELD_BOTTOM;
+	}
+
+	switch (field) {
+	case V4L2_FIELD_TOP:
+	case V4L2_FIELD_BOTTOM:
+		maxh = maxh / 2;
+		break;
+	case V4L2_FIELD_INTERLACED:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	f->fmt.pix.field = field;
+	v4l_bound_align_image(&f->fmt.pix.width, 48, maxw, 2,
+			      &f->fmt.pix.height, 32, maxh, 0, 0);
+	f->fmt.pix.bytesperline =
+		(f->fmt.pix.width * fmt->depth) >> 3;
+	f->fmt.pix.sizeimage =
+		f->fmt.pix.height * f->fmt.pix.bytesperline;
+
+	return 0;
+}
+
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
+	struct v4l2_format *f)
+{
+	struct cx23885_fh *fh = priv;
+	struct cx23885_dev *dev  = ((struct cx23885_fh *)priv)->dev;
+	struct v4l2_mbus_framefmt mbus_fmt;
+	int err;
+
+	dprintk(2, "%s()\n", __func__);
+	err = vidioc_try_fmt_vid_cap(file, priv, f);
+
+	if (0 != err)
+		return err;
+	fh->fmt        = format_by_fourcc(f->fmt.pix.pixelformat);
+	fh->width      = f->fmt.pix.width;
+	fh->height     = f->fmt.pix.height;
+	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);
+	v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, V4L2_MBUS_FMT_FIXED);
+	call_all(dev, video, s_mbus_fmt, &mbus_fmt);
+	v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt);
+	return 0;
+}
+
+static int vidioc_querycap(struct file *file, void  *priv,
+	struct v4l2_capability *cap)
+{
+	struct cx23885_dev *dev  = ((struct cx23885_fh *)priv)->dev;
+
+	strcpy(cap->driver, "cx23885");
+	strlcpy(cap->card, cx23885_boards[dev->board].name,
+		sizeof(cap->card));
+	sprintf(cap->bus_info, "PCIe:%s", pci_name(dev->pci));
+	cap->capabilities =
+		V4L2_CAP_VIDEO_CAPTURE |
+		V4L2_CAP_READWRITE     |
+		V4L2_CAP_STREAMING     |
+		V4L2_CAP_VBI_CAPTURE;
+	if (UNSET != dev->tuner_type)
+		cap->capabilities |= V4L2_CAP_TUNER;
+	return 0;
+}
+
+static int vidioc_enum_fmt_vid_cap(struct file *file, void  *priv,
+	struct v4l2_fmtdesc *f)
+{
+	if (unlikely(f->index >= ARRAY_SIZE(formats)))
+		return -EINVAL;
+
+	strlcpy(f->description, formats[f->index].name,
+		sizeof(f->description));
+	f->pixelformat = formats[f->index].fourcc;
+
+	return 0;
+}
+
+static int vidioc_reqbufs(struct file *file, void *priv,
+	struct v4l2_requestbuffers *p)
+{
+	struct cx23885_fh *fh = priv;
+	return videobuf_reqbufs(get_queue(fh), p);
+}
+
+static int vidioc_querybuf(struct file *file, void *priv,
+	struct v4l2_buffer *p)
+{
+	struct cx23885_fh *fh = priv;
+	return videobuf_querybuf(get_queue(fh), p);
+}
+
+static int vidioc_qbuf(struct file *file, void *priv,
+	struct v4l2_buffer *p)
+{
+	struct cx23885_fh *fh = priv;
+	return videobuf_qbuf(get_queue(fh), p);
+}
+
+static int vidioc_dqbuf(struct file *file, void *priv,
+	struct v4l2_buffer *p)
+{
+	struct cx23885_fh *fh = priv;
+	return videobuf_dqbuf(get_queue(fh), p,
+				file->f_flags & O_NONBLOCK);
+}
+
+static int vidioc_streamon(struct file *file, void *priv,
+	enum v4l2_buf_type i)
+{
+	struct cx23885_fh *fh = priv;
+	struct cx23885_dev *dev = fh->dev;
+	dprintk(1, "%s()\n", __func__);
+
+	if ((fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
+		(fh->type != V4L2_BUF_TYPE_VBI_CAPTURE))
+		return -EINVAL;
+	if (unlikely(i != fh->type))
+		return -EINVAL;
+
+	if (unlikely(!res_get(dev, fh, get_resource(fh))))
+		return -EBUSY;
+
+	/* Don't start VBI streaming unless vida streaming
+	 * has already started.
+	 */
+	if ((fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) &&
+		((cx_read(VID_A_DMA_CTL) & 0x11) == 0))
+		return -EINVAL;
+
+	return videobuf_streamon(get_queue(fh));
+}
+
+static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+	struct cx23885_fh *fh = priv;
+	struct cx23885_dev *dev = fh->dev;
+	int err, res;
+	dprintk(1, "%s()\n", __func__);
+
+	if ((fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
+		(fh->type != V4L2_BUF_TYPE_VBI_CAPTURE))
+		return -EINVAL;
+	if (i != fh->type)
+		return -EINVAL;
+
+	res = get_resource(fh);
+	err = videobuf_streamoff(get_queue(fh));
+	if (err < 0)
+		return err;
+	res_free(dev, fh, res);
+	return 0;
+}
+
+static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id)
+{
+	struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
+	dprintk(1, "%s()\n", __func__);
+
+	call_all(dev, core, g_std, id);
+
+	return 0;
+}
+
+static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *tvnorms)
+{
+	struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
+	dprintk(1, "%s()\n", __func__);
+
+	mutex_lock(&dev->lock);
+	cx23885_set_tvnorm(dev, *tvnorms);
+	mutex_unlock(&dev->lock);
+
+	return 0;
+}
+
+int cx23885_enum_input(struct cx23885_dev *dev, struct v4l2_input *i)
+{
+	static const char *iname[] = {
+		[CX23885_VMUX_COMPOSITE1] = "Composite1",
+		[CX23885_VMUX_COMPOSITE2] = "Composite2",
+		[CX23885_VMUX_COMPOSITE3] = "Composite3",
+		[CX23885_VMUX_COMPOSITE4] = "Composite4",
+		[CX23885_VMUX_SVIDEO]     = "S-Video",
+		[CX23885_VMUX_COMPONENT]  = "Component",
+		[CX23885_VMUX_TELEVISION] = "Television",
+		[CX23885_VMUX_CABLE]      = "Cable TV",
+		[CX23885_VMUX_DVB]        = "DVB",
+		[CX23885_VMUX_DEBUG]      = "for debug only",
+	};
+	unsigned int n;
+	dprintk(1, "%s()\n", __func__);
+
+	n = i->index;
+	if (n >= MAX_CX23885_INPUT)
+		return -EINVAL;
+
+	if (0 == INPUT(n)->type)
+		return -EINVAL;
+
+	i->index = n;
+	i->type  = V4L2_INPUT_TYPE_CAMERA;
+	strcpy(i->name, iname[INPUT(n)->type]);
+	if ((CX23885_VMUX_TELEVISION == INPUT(n)->type) ||
+		(CX23885_VMUX_CABLE == INPUT(n)->type)) {
+		i->type = V4L2_INPUT_TYPE_TUNER;
+		i->std = CX23885_NORMS;
+	}
+
+	/* Two selectable audio inputs for non-tv inputs */
+	if (INPUT(n)->type != CX23885_VMUX_TELEVISION)
+		i->audioset = 0x3;
+
+	if (dev->input == n) {
+		/* enum'd input matches our configured input.
+		 * Ask the video decoder to process the call
+		 * and give it an oppertunity to update the
+		 * status field.
+		 */
+		call_all(dev, video, g_input_status, &i->status);
+	}
+
+	return 0;
+}
+
+static int vidioc_enum_input(struct file *file, void *priv,
+				struct v4l2_input *i)
+{
+	struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
+	dprintk(1, "%s()\n", __func__);
+	return cx23885_enum_input(dev, i);
+}
+
+int cx23885_get_input(struct file *file, void *priv, unsigned int *i)
+{
+	struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
+
+	*i = dev->input;
+	dprintk(1, "%s() returns %d\n", __func__, *i);
+	return 0;
+}
+
+static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
+{
+	return cx23885_get_input(file, priv, i);
+}
+
+int cx23885_set_input(struct file *file, void *priv, unsigned int i)
+{
+	struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
+
+	dprintk(1, "%s(%d)\n", __func__, i);
+
+	if (i >= MAX_CX23885_INPUT) {
+		dprintk(1, "%s() -EINVAL\n", __func__);
+		return -EINVAL;
+	}
+
+	if (INPUT(i)->type == 0)
+		return -EINVAL;
+
+	mutex_lock(&dev->lock);
+	cx23885_video_mux(dev, i);
+
+	/* By default establish the default audio input for the card also */
+	/* Caller is free to use VIDIOC_S_AUDIO to override afterwards */
+	cx23885_audio_mux(dev, i);
+	mutex_unlock(&dev->lock);
+	return 0;
+}
+
+static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
+{
+	return cx23885_set_input(file, priv, i);
+}
+
+static int vidioc_log_status(struct file *file, void *priv)
+{
+	struct cx23885_fh  *fh  = priv;
+	struct cx23885_dev *dev = fh->dev;
+
+	printk(KERN_INFO
+		"%s/0: ============  START LOG STATUS  ============\n",
+		dev->name);
+	call_all(dev, core, log_status);
+	printk(KERN_INFO
+		"%s/0: =============  END LOG STATUS  =============\n",
+		dev->name);
+	return 0;
+}
+
+static int cx23885_query_audinput(struct file *file, void *priv,
+	struct v4l2_audio *i)
+{
+	struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
+	static const char *iname[] = {
+		[0] = "Baseband L/R 1",
+		[1] = "Baseband L/R 2",
+	};
+	unsigned int n;
+	dprintk(1, "%s()\n", __func__);
+
+	n = i->index;
+	if (n >= 2)
+		return -EINVAL;
+
+	memset(i, 0, sizeof(*i));
+	i->index = n;
+	strcpy(i->name, iname[n]);
+	i->capability  = V4L2_AUDCAP_STEREO;
+	i->mode  = V4L2_AUDMODE_AVL;
+	return 0;
+
+}
+
+static int vidioc_enum_audinput(struct file *file, void *priv,
+				struct v4l2_audio *i)
+{
+	return cx23885_query_audinput(file, priv, i);
+}
+
+static int vidioc_g_audinput(struct file *file, void *priv,
+	struct v4l2_audio *i)
+{
+	struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
+
+	i->index = dev->audinput;
+	dprintk(1, "%s(input=%d)\n", __func__, i->index);
+
+	return cx23885_query_audinput(file, priv, i);
+}
+
+static int vidioc_s_audinput(struct file *file, void *priv,
+	struct v4l2_audio *i)
+{
+	struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
+	if (i->index >= 2)
+		return -EINVAL;
+
+	dprintk(1, "%s(%d)\n", __func__, i->index);
+
+	dev->audinput = i->index;
+
+	/* Skip the audio defaults from the cards struct, caller wants
+	 * directly touch the audio mux hardware. */
+	cx23885_flatiron_mux(dev, dev->audinput + 1);
+	return 0;
+}
+
+static int vidioc_queryctrl(struct file *file, void *priv,
+				struct v4l2_queryctrl *qctrl)
+{
+	qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id);
+	if (unlikely(qctrl->id == 0))
+		return -EINVAL;
+	return cx23885_ctrl_query(qctrl);
+}
+
+static int vidioc_g_ctrl(struct file *file, void *priv,
+				struct v4l2_control *ctl)
+{
+	struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
+
+	return cx23885_get_control(dev, ctl);
+}
+
+static int vidioc_s_ctrl(struct file *file, void *priv,
+				struct v4l2_control *ctl)
+{
+	struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
+
+	return cx23885_set_control(dev, ctl);
+}
+
+static int vidioc_g_tuner(struct file *file, void *priv,
+				struct v4l2_tuner *t)
+{
+	struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
+
+	if (unlikely(UNSET == dev->tuner_type))
+		return -EINVAL;
+	if (0 != t->index)
+		return -EINVAL;
+
+	strcpy(t->name, "Television");
+
+	call_all(dev, tuner, g_tuner, t);
+	return 0;
+}
+
+static int vidioc_s_tuner(struct file *file, void *priv,
+				struct v4l2_tuner *t)
+{
+	struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
+
+	if (UNSET == dev->tuner_type)
+		return -EINVAL;
+	if (0 != t->index)
+		return -EINVAL;
+	/* Update the A/V core */
+	call_all(dev, tuner, s_tuner, t);
+
+	return 0;
+}
+
+static int vidioc_g_frequency(struct file *file, void *priv,
+				struct v4l2_frequency *f)
+{
+	struct cx23885_fh *fh = priv;
+	struct cx23885_dev *dev = fh->dev;
+
+	if (unlikely(UNSET == dev->tuner_type))
+		return -EINVAL;
+
+	/* f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; */
+	f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
+	f->frequency = dev->freq;
+
+	call_all(dev, tuner, g_frequency, f);
+
+	return 0;
+}
+
+static int cx23885_set_freq(struct cx23885_dev *dev, struct v4l2_frequency *f)
+{
+	struct v4l2_control ctrl;
+
+	if (unlikely(UNSET == dev->tuner_type))
+		return -EINVAL;
+	if (unlikely(f->tuner != 0))
+		return -EINVAL;
+
+	mutex_lock(&dev->lock);
+	dev->freq = f->frequency;
+
+	/* I need to mute audio here */
+	ctrl.id = V4L2_CID_AUDIO_MUTE;
+	ctrl.value = 1;
+	cx23885_set_control(dev, &ctrl);
+
+	call_all(dev, tuner, s_frequency, f);
+
+	/* When changing channels it is required to reset TVAUDIO */
+	msleep(100);
+
+	/* I need to unmute audio here */
+	ctrl.value = 0;
+	cx23885_set_control(dev, &ctrl);
+
+	mutex_unlock(&dev->lock);
+
+	return 0;
+}
+
+static int cx23885_set_freq_via_ops(struct cx23885_dev *dev,
+	struct v4l2_frequency *f)
+{
+	struct v4l2_control ctrl;
+	struct videobuf_dvb_frontend *vfe;
+	struct dvb_frontend *fe;
+
+	struct analog_parameters params = {
+		.mode      = V4L2_TUNER_ANALOG_TV,
+		.audmode   = V4L2_TUNER_MODE_STEREO,
+		.std       = dev->tvnorm,
+		.frequency = f->frequency
+	};
+
+	mutex_lock(&dev->lock);
+	dev->freq = f->frequency;
+
+	/* I need to mute audio here */
+	ctrl.id = V4L2_CID_AUDIO_MUTE;
+	ctrl.value = 1;
+	cx23885_set_control(dev, &ctrl);
+
+	/* If HVR1850 */
+	dprintk(1, "%s() frequency=%d tuner=%d std=0x%llx\n", __func__,
+		params.frequency, f->tuner, params.std);
+
+	vfe = videobuf_dvb_get_frontend(&dev->ts2.frontends, 1);
+	if (!vfe) {
+		mutex_unlock(&dev->lock);
+		return -EINVAL;
+	}
+
+	fe = vfe->dvb.frontend;
+
+	if ((dev->board == CX23885_BOARD_HAUPPAUGE_HVR1850) ||
+	    (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1255) ||
+	    (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1255_22111))
+		fe = &dev->ts1.analog_fe;
+
+	if (fe && fe->ops.tuner_ops.set_analog_params) {
+		call_all(dev, core, s_std, dev->tvnorm);
+		fe->ops.tuner_ops.set_analog_params(fe, &params);
+	}
+	else
+		printk(KERN_ERR "%s() No analog tuner, aborting\n", __func__);
+
+	/* When changing channels it is required to reset TVAUDIO */
+	msleep(100);
+
+	/* I need to unmute audio here */
+	ctrl.value = 0;
+	cx23885_set_control(dev, &ctrl);
+
+	mutex_unlock(&dev->lock);
+
+	return 0;
+}
+
+int cx23885_set_frequency(struct file *file, void *priv,
+	struct v4l2_frequency *f)
+{
+	struct cx23885_fh *fh = priv;
+	struct cx23885_dev *dev = fh->dev;
+	int ret;
+
+	switch (dev->board) {
+	case CX23885_BOARD_HAUPPAUGE_HVR1255:
+	case CX23885_BOARD_HAUPPAUGE_HVR1255_22111:
+	case CX23885_BOARD_HAUPPAUGE_HVR1850:
+		ret = cx23885_set_freq_via_ops(dev, f);
+		break;
+	default:
+		ret = cx23885_set_freq(dev, f);
+	}
+
+	return ret;
+}
+
+static int vidioc_s_frequency(struct file *file, void *priv,
+	struct v4l2_frequency *f)
+{
+	return cx23885_set_frequency(file, priv, f);
+}
+
+/* ----------------------------------------------------------- */
+
+static void cx23885_vid_timeout(unsigned long data)
+{
+	struct cx23885_dev *dev = (struct cx23885_dev *)data;
+	struct cx23885_dmaqueue *q = &dev->vidq;
+	struct cx23885_buffer *buf;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->slock, flags);
+	while (!list_empty(&q->active)) {
+		buf = list_entry(q->active.next,
+			struct cx23885_buffer, vb.queue);
+		list_del(&buf->vb.queue);
+		buf->vb.state = VIDEOBUF_ERROR;
+		wake_up(&buf->vb.done);
+		printk(KERN_ERR "%s: [%p/%d] timeout - dma=0x%08lx\n",
+			dev->name, buf, buf->vb.i,
+			(unsigned long)buf->risc.dma);
+	}
+	cx23885_restart_video_queue(dev, q);
+	spin_unlock_irqrestore(&dev->slock, flags);
+}
+
+int cx23885_video_irq(struct cx23885_dev *dev, u32 status)
+{
+	u32 mask, count;
+	int handled = 0;
+
+	mask   = cx_read(VID_A_INT_MSK);
+	if (0 == (status & mask))
+		return handled;
+
+	cx_write(VID_A_INT_STAT, status);
+
+	/* risc op code error, fifo overflow or line sync detection error */
+	if ((status & VID_BC_MSK_OPC_ERR) ||
+		(status & VID_BC_MSK_SYNC) ||
+		(status & VID_BC_MSK_OF)) {
+
+		if (status & VID_BC_MSK_OPC_ERR) {
+			dprintk(7, " (VID_BC_MSK_OPC_ERR 0x%08x)\n",
+				VID_BC_MSK_OPC_ERR);
+			printk(KERN_WARNING "%s: video risc op code error\n",
+				dev->name);
+			cx23885_sram_channel_dump(dev,
+				&dev->sram_channels[SRAM_CH01]);
+		}
+
+		if (status & VID_BC_MSK_SYNC)
+			dprintk(7, " (VID_BC_MSK_SYNC 0x%08x) "
+				"video lines miss-match\n",
+				VID_BC_MSK_SYNC);
+
+		if (status & VID_BC_MSK_OF)
+			dprintk(7, " (VID_BC_MSK_OF 0x%08x) fifo overflow\n",
+				VID_BC_MSK_OF);
+
+	}
+
+	/* Video */
+	if (status & VID_BC_MSK_RISCI1) {
+		spin_lock(&dev->slock);
+		count = cx_read(VID_A_GPCNT);
+		cx23885_video_wakeup(dev, &dev->vidq, count);
+		spin_unlock(&dev->slock);
+		handled++;
+	}
+	if (status & VID_BC_MSK_RISCI2) {
+		dprintk(2, "stopper video\n");
+		spin_lock(&dev->slock);
+		cx23885_restart_video_queue(dev, &dev->vidq);
+		spin_unlock(&dev->slock);
+		handled++;
+	}
+
+	/* Allow the VBI framework to process it's payload */
+	handled += cx23885_vbi_irq(dev, status);
+
+	return handled;
+}
+
+/* ----------------------------------------------------------- */
+/* exported stuff                                              */
+
+static const struct v4l2_file_operations video_fops = {
+	.owner	       = THIS_MODULE,
+	.open	       = video_open,
+	.release       = video_release,
+	.read	       = video_read,
+	.poll          = video_poll,
+	.mmap	       = video_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,
+	.vidioc_g_fmt_vbi_cap     = cx23885_vbi_fmt,
+	.vidioc_try_fmt_vbi_cap   = cx23885_vbi_fmt,
+	.vidioc_s_fmt_vbi_cap     = cx23885_vbi_fmt,
+	.vidioc_reqbufs       = vidioc_reqbufs,
+	.vidioc_querybuf      = vidioc_querybuf,
+	.vidioc_qbuf          = vidioc_qbuf,
+	.vidioc_dqbuf         = vidioc_dqbuf,
+	.vidioc_s_std         = vidioc_s_std,
+	.vidioc_g_std         = vidioc_g_std,
+	.vidioc_querystd      = vidioc_g_std,
+	.vidioc_enum_input    = vidioc_enum_input,
+	.vidioc_g_input       = vidioc_g_input,
+	.vidioc_s_input       = vidioc_s_input,
+	.vidioc_log_status    = vidioc_log_status,
+	.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,
+	.vidioc_g_chip_ident  = cx23885_g_chip_ident,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.vidioc_g_register    = cx23885_g_register,
+	.vidioc_s_register    = cx23885_s_register,
+#endif
+	.vidioc_enumaudio     = vidioc_enum_audinput,
+	.vidioc_g_audio       = vidioc_g_audinput,
+	.vidioc_s_audio       = vidioc_s_audinput,
+};
+
+static struct video_device cx23885_vbi_template;
+static struct video_device cx23885_video_template = {
+	.name                 = "cx23885-video",
+	.fops                 = &video_fops,
+	.ioctl_ops 	      = &video_ioctl_ops,
+	.tvnorms              = CX23885_NORMS,
+	.current_norm         = V4L2_STD_NTSC_M,
+};
+
+static const struct v4l2_file_operations radio_fops = {
+	.owner         = THIS_MODULE,
+	.open          = video_open,
+	.release       = video_release,
+	.ioctl         = video_ioctl2,
+};
+
+
+void cx23885_video_unregister(struct cx23885_dev *dev)
+{
+	dprintk(1, "%s()\n", __func__);
+	cx23885_irq_remove(dev, 0x01);
+
+	if (dev->vbi_dev) {
+		if (video_is_registered(dev->vbi_dev))
+			video_unregister_device(dev->vbi_dev);
+		else
+			video_device_release(dev->vbi_dev);
+		dev->vbi_dev = NULL;
+		btcx_riscmem_free(dev->pci, &dev->vbiq.stopper);
+	}
+	if (dev->video_dev) {
+		if (video_is_registered(dev->video_dev))
+			video_unregister_device(dev->video_dev);
+		else
+			video_device_release(dev->video_dev);
+		dev->video_dev = NULL;
+
+		btcx_riscmem_free(dev->pci, &dev->vidq.stopper);
+	}
+
+	if (dev->audio_dev)
+		cx23885_audio_unregister(dev);
+}
+
+int cx23885_video_register(struct cx23885_dev *dev)
+{
+	int err;
+
+	dprintk(1, "%s()\n", __func__);
+	spin_lock_init(&dev->slock);
+
+	/* Initialize VBI template */
+	memcpy(&cx23885_vbi_template, &cx23885_video_template,
+		sizeof(cx23885_vbi_template));
+	strcpy(cx23885_vbi_template.name, "cx23885-vbi");
+
+	dev->tvnorm = cx23885_video_template.current_norm;
+
+	/* init video dma queues */
+	INIT_LIST_HEAD(&dev->vidq.active);
+	INIT_LIST_HEAD(&dev->vidq.queued);
+	dev->vidq.timeout.function = cx23885_vid_timeout;
+	dev->vidq.timeout.data = (unsigned long)dev;
+	init_timer(&dev->vidq.timeout);
+	cx23885_risc_stopper(dev->pci, &dev->vidq.stopper,
+		VID_A_DMA_CTL, 0x11, 0x00);
+
+	/* init vbi dma queues */
+	INIT_LIST_HEAD(&dev->vbiq.active);
+	INIT_LIST_HEAD(&dev->vbiq.queued);
+	dev->vbiq.timeout.function = cx23885_vbi_timeout;
+	dev->vbiq.timeout.data = (unsigned long)dev;
+	init_timer(&dev->vbiq.timeout);
+	cx23885_risc_stopper(dev->pci, &dev->vbiq.stopper,
+		VID_A_DMA_CTL, 0x22, 0x00);
+
+	cx23885_irq_add_enable(dev, 0x01);
+
+	if ((TUNER_ABSENT != dev->tuner_type) &&
+			((dev->tuner_bus == 0) || (dev->tuner_bus == 1))) {
+		struct v4l2_subdev *sd = NULL;
+
+		if (dev->tuner_addr)
+			sd = v4l2_i2c_new_subdev(&dev->v4l2_dev,
+				&dev->i2c_bus[dev->tuner_bus].i2c_adap,
+				"tuner", dev->tuner_addr, NULL);
+		else
+			sd = v4l2_i2c_new_subdev(&dev->v4l2_dev,
+				&dev->i2c_bus[dev->tuner_bus].i2c_adap,
+				"tuner", 0, v4l2_i2c_tuner_addrs(ADDRS_TV));
+		if (sd) {
+			struct tuner_setup tun_setup;
+
+			memset(&tun_setup, 0, sizeof(tun_setup));
+			tun_setup.mode_mask = T_ANALOG_TV;
+			tun_setup.type = dev->tuner_type;
+			tun_setup.addr = v4l2_i2c_subdev_addr(sd);
+			tun_setup.tuner_callback = cx23885_tuner_callback;
+
+			v4l2_subdev_call(sd, tuner, s_type_addr, &tun_setup);
+
+			if (dev->board == CX23885_BOARD_LEADTEK_WINFAST_PXTV1200) {
+				struct xc2028_ctrl ctrl = {
+					.fname = XC2028_DEFAULT_FIRMWARE,
+					.max_len = 64
+				};
+				struct v4l2_priv_tun_config cfg = {
+					.tuner = dev->tuner_type,
+					.priv = &ctrl
+				};
+				v4l2_subdev_call(sd, tuner, s_config, &cfg);
+			}
+		}
+	}
+
+	/* register Video device */
+	dev->video_dev = cx23885_vdev_init(dev, dev->pci,
+		&cx23885_video_template, "video");
+	err = video_register_device(dev->video_dev, VFL_TYPE_GRABBER,
+				    video_nr[dev->nr]);
+	if (err < 0) {
+		printk(KERN_INFO "%s: can't register video device\n",
+			dev->name);
+		goto fail_unreg;
+	}
+	printk(KERN_INFO "%s: registered device %s [v4l2]\n",
+	       dev->name, video_device_node_name(dev->video_dev));
+
+	/* register VBI device */
+	dev->vbi_dev = cx23885_vdev_init(dev, dev->pci,
+		&cx23885_vbi_template, "vbi");
+	err = video_register_device(dev->vbi_dev, VFL_TYPE_VBI,
+				    vbi_nr[dev->nr]);
+	if (err < 0) {
+		printk(KERN_INFO "%s: can't register vbi device\n",
+			dev->name);
+		goto fail_unreg;
+	}
+	printk(KERN_INFO "%s: registered device %s\n",
+	       dev->name, video_device_node_name(dev->vbi_dev));
+
+	/* Register ALSA audio device */
+	dev->audio_dev = cx23885_audio_register(dev);
+
+	/* initial device configuration */
+	mutex_lock(&dev->lock);
+	cx23885_set_tvnorm(dev, dev->tvnorm);
+	init_controls(dev);
+	cx23885_video_mux(dev, 0);
+	cx23885_audio_mux(dev, 0);
+	mutex_unlock(&dev->lock);
+
+	return 0;
+
+fail_unreg:
+	cx23885_video_unregister(dev);
+	return err;
+}
+
diff --git a/drivers/media/pci/cx23885/cx23885.h b/drivers/media/pci/cx23885/cx23885.h
new file mode 100644
index 0000000..67f40d3
--- /dev/null
+++ b/drivers/media/pci/cx23885/cx23885.h
@@ -0,0 +1,654 @@
+/*
+ *  Driver for the Conexant CX23885 PCIe bridge
+ *
+ *  Copyright (c) 2006 Steven Toth <stoth@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/pci.h>
+#include <linux/i2c.h>
+#include <linux/kdev_t.h>
+#include <linux/slab.h>
+
+#include <media/v4l2-device.h>
+#include <media/tuner.h>
+#include <media/tveeprom.h>
+#include <media/videobuf-dma-sg.h>
+#include <media/videobuf-dvb.h>
+#include <media/rc-core.h>
+
+#include "btcx-risc.h"
+#include "cx23885-reg.h"
+#include "media/cx2341x.h"
+
+#include <linux/mutex.h>
+
+#define CX23885_VERSION "0.0.3"
+
+#define UNSET (-1U)
+
+#define CX23885_MAXBOARDS 8
+
+/* Max number of inputs by card */
+#define MAX_CX23885_INPUT 8
+#define INPUT(nr) (&cx23885_boards[dev->board].input[nr])
+#define RESOURCE_OVERLAY       1
+#define RESOURCE_VIDEO         2
+#define RESOURCE_VBI           4
+
+#define BUFFER_TIMEOUT     (HZ)  /* 0.5 seconds */
+
+#define CX23885_BOARD_NOAUTO               UNSET
+#define CX23885_BOARD_UNKNOWN                  0
+#define CX23885_BOARD_HAUPPAUGE_HVR1800lp      1
+#define CX23885_BOARD_HAUPPAUGE_HVR1800        2
+#define CX23885_BOARD_HAUPPAUGE_HVR1250        3
+#define CX23885_BOARD_DVICO_FUSIONHDTV_5_EXP   4
+#define CX23885_BOARD_HAUPPAUGE_HVR1500Q       5
+#define CX23885_BOARD_HAUPPAUGE_HVR1500        6
+#define CX23885_BOARD_HAUPPAUGE_HVR1200        7
+#define CX23885_BOARD_HAUPPAUGE_HVR1700        8
+#define CX23885_BOARD_HAUPPAUGE_HVR1400        9
+#define CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP 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
+#define CX23885_BOARD_HAUPPAUGE_HVR1270        18
+#define CX23885_BOARD_HAUPPAUGE_HVR1275        19
+#define CX23885_BOARD_HAUPPAUGE_HVR1255        20
+#define CX23885_BOARD_HAUPPAUGE_HVR1210        21
+#define CX23885_BOARD_MYGICA_X8506             22
+#define CX23885_BOARD_MAGICPRO_PROHDTVE2       23
+#define CX23885_BOARD_HAUPPAUGE_HVR1850        24
+#define CX23885_BOARD_COMPRO_VIDEOMATE_E800    25
+#define CX23885_BOARD_HAUPPAUGE_HVR1290        26
+#define CX23885_BOARD_MYGICA_X8558PRO          27
+#define CX23885_BOARD_LEADTEK_WINFAST_PXTV1200 28
+#define CX23885_BOARD_GOTVIEW_X5_3D_HYBRID     29
+#define CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF 30
+#define CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H_XC4000 31
+#define CX23885_BOARD_MPX885                   32
+#define CX23885_BOARD_MYGICA_X8507             33
+#define CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL 34
+#define CX23885_BOARD_TEVII_S471               35
+#define CX23885_BOARD_HAUPPAUGE_HVR1255_22111  36
+#define CX23885_BOARD_PROF_8000                37
+
+#define GPIO_0 0x00000001
+#define GPIO_1 0x00000002
+#define GPIO_2 0x00000004
+#define GPIO_3 0x00000008
+#define GPIO_4 0x00000010
+#define GPIO_5 0x00000020
+#define GPIO_6 0x00000040
+#define GPIO_7 0x00000080
+#define GPIO_8 0x00000100
+#define GPIO_9 0x00000200
+#define GPIO_10 0x00000400
+#define GPIO_11 0x00000800
+#define GPIO_12 0x00001000
+#define GPIO_13 0x00002000
+#define GPIO_14 0x00004000
+#define GPIO_15 0x00008000
+
+/* Currently unsupported by the driver: PAL/H, NTSC/Kr, SECAM B/G/H/LC */
+#define CX23885_NORMS (\
+	V4L2_STD_NTSC_M |  V4L2_STD_NTSC_M_JP |  V4L2_STD_NTSC_443 | \
+	V4L2_STD_PAL_BG |  V4L2_STD_PAL_DK    |  V4L2_STD_PAL_I    | \
+	V4L2_STD_PAL_M  |  V4L2_STD_PAL_N     |  V4L2_STD_PAL_Nc   | \
+	V4L2_STD_PAL_60 |  V4L2_STD_SECAM_L   |  V4L2_STD_SECAM_DK)
+
+struct cx23885_fmt {
+	char  *name;
+	u32   fourcc;          /* v4l2 format id */
+	int   depth;
+	int   flags;
+	u32   cxformat;
+};
+
+struct cx23885_ctrl {
+	struct v4l2_queryctrl v;
+	u32                   off;
+	u32                   reg;
+	u32                   mask;
+	u32                   shift;
+};
+
+struct cx23885_tvnorm {
+	char		*name;
+	v4l2_std_id	id;
+	u32		cxiformat;
+	u32		cxoformat;
+};
+
+struct cx23885_fh {
+	struct cx23885_dev         *dev;
+	enum v4l2_buf_type         type;
+	int                        radio;
+	u32                        resources;
+
+	/* video overlay */
+	struct v4l2_window         win;
+	struct v4l2_clip           *clips;
+	unsigned int               nclips;
+
+	/* video capture */
+	struct cx23885_fmt         *fmt;
+	unsigned int               width, height;
+
+	/* vbi capture */
+	struct videobuf_queue      vidq;
+	struct videobuf_queue      vbiq;
+
+	/* MPEG Encoder specifics ONLY */
+	struct videobuf_queue      mpegq;
+	atomic_t                   v4l_reading;
+};
+
+enum cx23885_itype {
+	CX23885_VMUX_COMPOSITE1 = 1,
+	CX23885_VMUX_COMPOSITE2,
+	CX23885_VMUX_COMPOSITE3,
+	CX23885_VMUX_COMPOSITE4,
+	CX23885_VMUX_SVIDEO,
+	CX23885_VMUX_COMPONENT,
+	CX23885_VMUX_TELEVISION,
+	CX23885_VMUX_CABLE,
+	CX23885_VMUX_DVB,
+	CX23885_VMUX_DEBUG,
+	CX23885_RADIO,
+};
+
+enum cx23885_src_sel_type {
+	CX23885_SRC_SEL_EXT_656_VIDEO = 0,
+	CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO
+};
+
+/* buffer for one video frame */
+struct cx23885_buffer {
+	/* common v4l buffer stuff -- must be first */
+	struct videobuf_buffer vb;
+
+	/* cx23885 specific */
+	unsigned int           bpl;
+	struct btcx_riscmem    risc;
+	struct cx23885_fmt     *fmt;
+	u32                    count;
+};
+
+struct cx23885_input {
+	enum cx23885_itype type;
+	unsigned int    vmux;
+	unsigned int    amux;
+	u32             gpio0, gpio1, gpio2, gpio3;
+};
+
+typedef enum {
+	CX23885_MPEG_UNDEFINED = 0,
+	CX23885_MPEG_DVB,
+	CX23885_ANALOG_VIDEO,
+	CX23885_MPEG_ENCODER,
+} port_t;
+
+struct cx23885_board {
+	char                    *name;
+	port_t			porta, portb, portc;
+	int		num_fds_portb, num_fds_portc;
+	unsigned int		tuner_type;
+	unsigned int		radio_type;
+	unsigned char		tuner_addr;
+	unsigned char		radio_addr;
+	unsigned int		tuner_bus;
+
+	/* Vendors can and do run the PCIe bridge at different
+	 * clock rates, driven physically by crystals on the PCBs.
+	 * The core has to accommodate this. This allows the user
+	 * to add new boards with new frequencys. The value is
+	 * expressed in Hz.
+	 *
+	 * The core framework will default this value based on
+	 * current designs, but it can vary.
+	 */
+	u32			clk_freq;
+	struct cx23885_input    input[MAX_CX23885_INPUT];
+	int			ci_type; /* for NetUP */
+	/* Force bottom field first during DMA (888 workaround) */
+	u32                     force_bff;
+};
+
+struct cx23885_subid {
+	u16     subvendor;
+	u16     subdevice;
+	u32     card;
+};
+
+struct cx23885_i2c {
+	struct cx23885_dev *dev;
+
+	int                        nr;
+
+	/* i2c i/o */
+	struct i2c_adapter         i2c_adap;
+	struct i2c_client          i2c_client;
+	u32                        i2c_rc;
+
+	/* 885 registers used for raw addess */
+	u32                        i2c_period;
+	u32                        reg_ctrl;
+	u32                        reg_stat;
+	u32                        reg_addr;
+	u32                        reg_rdata;
+	u32                        reg_wdata;
+};
+
+struct cx23885_dmaqueue {
+	struct list_head       active;
+	struct list_head       queued;
+	struct timer_list      timeout;
+	struct btcx_riscmem    stopper;
+	u32                    count;
+};
+
+struct cx23885_tsport {
+	struct cx23885_dev *dev;
+
+	int                        nr;
+	int                        sram_chno;
+
+	struct videobuf_dvb_frontends frontends;
+
+	/* dma queues */
+	struct cx23885_dmaqueue    mpegq;
+	u32                        ts_packet_size;
+	u32                        ts_packet_count;
+
+	int                        width;
+	int                        height;
+
+	spinlock_t                 slock;
+
+	/* registers */
+	u32                        reg_gpcnt;
+	u32                        reg_gpcnt_ctl;
+	u32                        reg_dma_ctl;
+	u32                        reg_lngth;
+	u32                        reg_hw_sop_ctrl;
+	u32                        reg_gen_ctrl;
+	u32                        reg_bd_pkt_status;
+	u32                        reg_sop_status;
+	u32                        reg_fifo_ovfl_stat;
+	u32                        reg_vld_misc;
+	u32                        reg_ts_clk_en;
+	u32                        reg_ts_int_msk;
+	u32                        reg_ts_int_stat;
+	u32                        reg_src_sel;
+
+	/* Default register vals */
+	int                        pci_irqmask;
+	u32                        dma_ctl_val;
+	u32                        ts_int_msk_val;
+	u32                        gen_ctrl_val;
+	u32                        ts_clk_en_val;
+	u32                        src_sel_val;
+	u32                        vld_misc_val;
+	u32                        hw_sop_ctrl_val;
+
+	/* Allow a single tsport to have multiple frontends */
+	u32                        num_frontends;
+	void                (*gate_ctrl)(struct cx23885_tsport *port, int open);
+	void                       *port_priv;
+
+	/* Workaround for a temp dvb_frontend that the tuner can attached to */
+	struct dvb_frontend analog_fe;
+};
+
+struct cx23885_kernel_ir {
+	struct cx23885_dev	*cx;
+	char			*name;
+	char			*phys;
+
+	struct rc_dev		*rc;
+};
+
+struct cx23885_audio_buffer {
+	unsigned int		bpl;
+	struct btcx_riscmem	risc;
+	struct videobuf_dmabuf	dma;
+};
+
+struct cx23885_audio_dev {
+	struct cx23885_dev	*dev;
+
+	struct pci_dev		*pci;
+
+	struct snd_card		*card;
+
+	spinlock_t		lock;
+
+	atomic_t		count;
+
+	unsigned int		dma_size;
+	unsigned int		period_size;
+	unsigned int		num_periods;
+
+	struct videobuf_dmabuf	*dma_risc;
+
+	struct cx23885_audio_buffer   *buf;
+
+	struct snd_pcm_substream *substream;
+};
+
+struct cx23885_dev {
+	atomic_t                   refcount;
+	struct v4l2_device 	   v4l2_dev;
+
+	/* pci stuff */
+	struct pci_dev             *pci;
+	unsigned char              pci_rev, pci_lat;
+	int                        pci_bus, pci_slot;
+	u32                        __iomem *lmmio;
+	u8                         __iomem *bmmio;
+	int                        pci_irqmask;
+	spinlock_t		   pci_irqmask_lock; /* protects mask reg too */
+	int                        hwrevision;
+
+	/* This valud is board specific and is used to configure the
+	 * AV core so we see nice clean and stable video and audio. */
+	u32                        clk_freq;
+
+	/* I2C adapters: Master 1 & 2 (External) & Master 3 (Internal only) */
+	struct cx23885_i2c         i2c_bus[3];
+
+	int                        nr;
+	struct mutex               lock;
+	struct mutex               gpio_lock;
+
+	/* board details */
+	unsigned int               board;
+	char                       name[32];
+
+	struct cx23885_tsport      ts1, ts2;
+
+	/* sram configuration */
+	struct sram_channel        *sram_channels;
+
+	enum {
+		CX23885_BRIDGE_UNDEFINED = 0,
+		CX23885_BRIDGE_885 = 885,
+		CX23885_BRIDGE_887 = 887,
+		CX23885_BRIDGE_888 = 888,
+	} bridge;
+
+	/* Analog video */
+	u32                        resources;
+	unsigned int               input;
+	unsigned int               audinput; /* Selectable audio input */
+	u32                        tvaudio;
+	v4l2_std_id                tvnorm;
+	unsigned int               tuner_type;
+	unsigned char              tuner_addr;
+	unsigned int               tuner_bus;
+	unsigned int               radio_type;
+	unsigned char              radio_addr;
+	unsigned int               has_radio;
+	struct v4l2_subdev 	   *sd_cx25840;
+	struct work_struct	   cx25840_work;
+
+	/* Infrared */
+	struct v4l2_subdev         *sd_ir;
+	struct work_struct	   ir_rx_work;
+	unsigned long		   ir_rx_notifications;
+	struct work_struct	   ir_tx_work;
+	unsigned long		   ir_tx_notifications;
+
+	struct cx23885_kernel_ir   *kernel_ir;
+	atomic_t		   ir_input_stopping;
+
+	/* V4l */
+	u32                        freq;
+	struct video_device        *video_dev;
+	struct video_device        *vbi_dev;
+	struct video_device        *radio_dev;
+
+	struct cx23885_dmaqueue    vidq;
+	struct cx23885_dmaqueue    vbiq;
+	spinlock_t                 slock;
+
+	/* MPEG Encoder ONLY settings */
+	u32                        cx23417_mailbox;
+	struct cx2341x_mpeg_params mpeg_params;
+	struct video_device        *v4l_device;
+	atomic_t                   v4l_reader_count;
+	struct cx23885_tvnorm      encodernorm;
+
+	/* Analog raw audio */
+	struct cx23885_audio_dev   *audio_dev;
+
+};
+
+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)
+
+#define CX23885_HW_888_IR  (1 << 0)
+#define CX23885_HW_AV_CORE (1 << 1)
+
+#define call_hw(dev, grpid, o, f, args...) \
+	v4l2_device_call_all(&dev->v4l2_dev, grpid, o, f, ##args)
+
+extern struct v4l2_subdev *cx23885_find_hw(struct cx23885_dev *dev, u32 hw);
+
+#define SRAM_CH01  0 /* Video A */
+#define SRAM_CH02  1 /* VBI A */
+#define SRAM_CH03  2 /* Video B */
+#define SRAM_CH04  3 /* Transport via B */
+#define SRAM_CH05  4 /* VBI B */
+#define SRAM_CH06  5 /* Video C */
+#define SRAM_CH07  6 /* Transport via C */
+#define SRAM_CH08  7 /* Audio Internal A */
+#define SRAM_CH09  8 /* Audio Internal B */
+#define SRAM_CH10  9 /* Audio External */
+#define SRAM_CH11 10 /* COMB_3D_N */
+#define SRAM_CH12 11 /* Comb 3D N1 */
+#define SRAM_CH13 12 /* Comb 3D N2 */
+#define SRAM_CH14 13 /* MOE Vid */
+#define SRAM_CH15 14 /* MOE RSLT */
+
+struct sram_channel {
+	char *name;
+	u32  cmds_start;
+	u32  ctrl_start;
+	u32  cdt;
+	u32  fifo_start;
+	u32  fifo_size;
+	u32  ptr1_reg;
+	u32  ptr2_reg;
+	u32  cnt1_reg;
+	u32  cnt2_reg;
+	u32  jumponly;
+};
+
+/* ----------------------------------------------------------- */
+
+#define cx_read(reg)             readl(dev->lmmio + ((reg)>>2))
+#define cx_write(reg, value)     writel((value), dev->lmmio + ((reg)>>2))
+
+#define cx_andor(reg, mask, value) \
+  writel((readl(dev->lmmio+((reg)>>2)) & ~(mask)) |\
+  ((value) & (mask)), dev->lmmio+((reg)>>2))
+
+#define cx_set(reg, bit)          cx_andor((reg), (bit), (bit))
+#define cx_clear(reg, bit)        cx_andor((reg), (bit), 0)
+
+/* ----------------------------------------------------------- */
+/* cx23885-core.c                                              */
+
+extern int cx23885_sram_channel_setup(struct cx23885_dev *dev,
+	struct sram_channel *ch,
+	unsigned int bpl, u32 risc);
+
+extern void cx23885_sram_channel_dump(struct cx23885_dev *dev,
+	struct sram_channel *ch);
+
+extern int cx23885_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
+	u32 reg, u32 mask, u32 value);
+
+extern int cx23885_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
+	struct scatterlist *sglist,
+	unsigned int top_offset, unsigned int bottom_offset,
+	unsigned int bpl, unsigned int padding, unsigned int lines);
+
+extern int cx23885_risc_vbibuffer(struct pci_dev *pci,
+	struct btcx_riscmem *risc, struct scatterlist *sglist,
+	unsigned int top_offset, unsigned int bottom_offset,
+	unsigned int bpl, unsigned int padding, unsigned int lines);
+
+void cx23885_cancel_buffers(struct cx23885_tsport *port);
+
+extern int cx23885_restart_queue(struct cx23885_tsport *port,
+				struct cx23885_dmaqueue *q);
+
+extern void cx23885_wakeup(struct cx23885_tsport *port,
+			   struct cx23885_dmaqueue *q, u32 count);
+
+extern void cx23885_gpio_set(struct cx23885_dev *dev, u32 mask);
+extern void cx23885_gpio_clear(struct cx23885_dev *dev, u32 mask);
+extern u32 cx23885_gpio_get(struct cx23885_dev *dev, u32 mask);
+extern void cx23885_gpio_enable(struct cx23885_dev *dev, u32 mask,
+	int asoutput);
+
+extern void cx23885_irq_add_enable(struct cx23885_dev *dev, u32 mask);
+extern void cx23885_irq_enable(struct cx23885_dev *dev, u32 mask);
+extern void cx23885_irq_disable(struct cx23885_dev *dev, u32 mask);
+extern void cx23885_irq_remove(struct cx23885_dev *dev, u32 mask);
+
+/* ----------------------------------------------------------- */
+/* cx23885-cards.c                                             */
+extern struct cx23885_board cx23885_boards[];
+extern const unsigned int cx23885_bcount;
+
+extern struct cx23885_subid cx23885_subids[];
+extern const unsigned int cx23885_idcount;
+
+extern int cx23885_tuner_callback(void *priv, int component,
+	int command, int arg);
+extern void cx23885_card_list(struct cx23885_dev *dev);
+extern int  cx23885_ir_init(struct cx23885_dev *dev);
+extern void cx23885_ir_pci_int_enable(struct cx23885_dev *dev);
+extern void cx23885_ir_fini(struct cx23885_dev *dev);
+extern void cx23885_gpio_setup(struct cx23885_dev *dev);
+extern void cx23885_card_setup(struct cx23885_dev *dev);
+extern void cx23885_card_setup_pre_i2c(struct cx23885_dev *dev);
+
+extern int cx23885_dvb_register(struct cx23885_tsport *port);
+extern int cx23885_dvb_unregister(struct cx23885_tsport *port);
+
+extern int cx23885_buf_prepare(struct videobuf_queue *q,
+			       struct cx23885_tsport *port,
+			       struct cx23885_buffer *buf,
+			       enum v4l2_field field);
+extern void cx23885_buf_queue(struct cx23885_tsport *port,
+			      struct cx23885_buffer *buf);
+extern void cx23885_free_buffer(struct videobuf_queue *q,
+				struct cx23885_buffer *buf);
+
+/* ----------------------------------------------------------- */
+/* cx23885-video.c                                             */
+/* Video */
+extern int cx23885_video_register(struct cx23885_dev *dev);
+extern void cx23885_video_unregister(struct cx23885_dev *dev);
+extern int cx23885_video_irq(struct cx23885_dev *dev, u32 status);
+extern void cx23885_video_wakeup(struct cx23885_dev *dev,
+	struct cx23885_dmaqueue *q, u32 count);
+int cx23885_enum_input(struct cx23885_dev *dev, struct v4l2_input *i);
+int cx23885_set_input(struct file *file, void *priv, unsigned int i);
+int cx23885_get_input(struct file *file, void *priv, unsigned int *i);
+int cx23885_set_frequency(struct file *file, void *priv, struct v4l2_frequency *f);
+int cx23885_set_control(struct cx23885_dev *dev, struct v4l2_control *ctl);
+int cx23885_get_control(struct cx23885_dev *dev, struct v4l2_control *ctl);
+int cx23885_set_tvnorm(struct cx23885_dev *dev, v4l2_std_id norm);
+
+/* ----------------------------------------------------------- */
+/* cx23885-vbi.c                                               */
+extern int cx23885_vbi_fmt(struct file *file, void *priv,
+	struct v4l2_format *f);
+extern void cx23885_vbi_timeout(unsigned long data);
+extern struct videobuf_queue_ops cx23885_vbi_qops;
+extern int cx23885_restart_vbi_queue(struct cx23885_dev *dev,
+	struct cx23885_dmaqueue *q);
+extern int cx23885_vbi_irq(struct cx23885_dev *dev, u32 status);
+
+/* cx23885-i2c.c                                                */
+extern int cx23885_i2c_register(struct cx23885_i2c *bus);
+extern int cx23885_i2c_unregister(struct cx23885_i2c *bus);
+extern void cx23885_av_clk(struct cx23885_dev *dev, int enable);
+
+/* ----------------------------------------------------------- */
+/* cx23885-417.c                                               */
+extern int cx23885_417_register(struct cx23885_dev *dev);
+extern void cx23885_417_unregister(struct cx23885_dev *dev);
+extern int cx23885_irq_417(struct cx23885_dev *dev, u32 status);
+extern void cx23885_417_check_encoder(struct cx23885_dev *dev);
+extern void cx23885_mc417_init(struct cx23885_dev *dev);
+extern int mc417_memory_read(struct cx23885_dev *dev, u32 address, u32 *value);
+extern int mc417_memory_write(struct cx23885_dev *dev, u32 address, u32 value);
+extern int mc417_register_read(struct cx23885_dev *dev,
+				u16 address, u32 *value);
+extern int mc417_register_write(struct cx23885_dev *dev,
+				u16 address, u32 value);
+extern void mc417_gpio_set(struct cx23885_dev *dev, u32 mask);
+extern void mc417_gpio_clear(struct cx23885_dev *dev, u32 mask);
+extern void mc417_gpio_enable(struct cx23885_dev *dev, u32 mask, int asoutput);
+
+/* ----------------------------------------------------------- */
+/* cx23885-alsa.c                                             */
+extern struct cx23885_audio_dev *cx23885_audio_register(
+					struct cx23885_dev *dev);
+extern void cx23885_audio_unregister(struct cx23885_dev *dev);
+extern int cx23885_audio_irq(struct cx23885_dev *dev, u32 status, u32 mask);
+extern int cx23885_risc_databuffer(struct pci_dev *pci,
+				   struct btcx_riscmem *risc,
+				   struct scatterlist *sglist,
+				   unsigned int bpl,
+				   unsigned int lines,
+				   unsigned int lpi);
+
+/* ----------------------------------------------------------- */
+/* tv norms                                                    */
+
+static inline unsigned int norm_maxw(v4l2_std_id norm)
+{
+	return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 720 : 768;
+}
+
+static inline unsigned int norm_maxh(v4l2_std_id norm)
+{
+	return (norm & V4L2_STD_625_50) ? 576 : 480;
+}
+
+static inline unsigned int norm_swidth(v4l2_std_id norm)
+{
+	return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 754 : 922;
+}
diff --git a/drivers/media/pci/cx23885/cx23888-ir.c b/drivers/media/pci/cx23885/cx23888-ir.c
new file mode 100644
index 0000000..c2bc39c
--- /dev/null
+++ b/drivers/media/pci/cx23885/cx23888-ir.c
@@ -0,0 +1,1271 @@
+/*
+ *  Driver for the Conexant CX23885/7/8 PCIe bridge
+ *
+ *  CX23888 Integrated Consumer Infrared Controller
+ *
+ *  Copyright (C) 2009  Andy Walls <awalls@md.metrocast.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 program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You 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/kfifo.h>
+#include <linux/slab.h>
+
+#include <media/v4l2-device.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/rc-core.h>
+
+#include "cx23885.h"
+
+static unsigned int ir_888_debug;
+module_param(ir_888_debug, int, 0644);
+MODULE_PARM_DESC(ir_888_debug, "enable debug messages [CX23888 IR controller]");
+
+#define CX23888_IR_REG_BASE 	0x170000
+/*
+ * These CX23888 register offsets have a straightforward one to one mapping
+ * to the CX23885 register offsets of 0x200 through 0x218
+ */
+#define CX23888_IR_CNTRL_REG	0x170000
+#define CNTRL_WIN_3_3	0x00000000
+#define CNTRL_WIN_4_3	0x00000001
+#define CNTRL_WIN_3_4	0x00000002
+#define CNTRL_WIN_4_4	0x00000003
+#define CNTRL_WIN	0x00000003
+#define CNTRL_EDG_NONE	0x00000000
+#define CNTRL_EDG_FALL	0x00000004
+#define CNTRL_EDG_RISE	0x00000008
+#define CNTRL_EDG_BOTH	0x0000000C
+#define CNTRL_EDG	0x0000000C
+#define CNTRL_DMD	0x00000010
+#define CNTRL_MOD	0x00000020
+#define CNTRL_RFE	0x00000040
+#define CNTRL_TFE	0x00000080
+#define CNTRL_RXE	0x00000100
+#define CNTRL_TXE	0x00000200
+#define CNTRL_RIC	0x00000400
+#define CNTRL_TIC	0x00000800
+#define CNTRL_CPL	0x00001000
+#define CNTRL_LBM	0x00002000
+#define CNTRL_R		0x00004000
+/* CX23888 specific control flag */
+#define CNTRL_IVO	0x00008000
+
+#define CX23888_IR_TXCLK_REG	0x170004
+#define TXCLK_TCD	0x0000FFFF
+
+#define CX23888_IR_RXCLK_REG	0x170008
+#define RXCLK_RCD	0x0000FFFF
+
+#define CX23888_IR_CDUTY_REG	0x17000C
+#define CDUTY_CDC	0x0000000F
+
+#define CX23888_IR_STATS_REG	0x170010
+#define STATS_RTO	0x00000001
+#define STATS_ROR	0x00000002
+#define STATS_RBY	0x00000004
+#define STATS_TBY	0x00000008
+#define STATS_RSR	0x00000010
+#define STATS_TSR	0x00000020
+
+#define CX23888_IR_IRQEN_REG	0x170014
+#define IRQEN_RTE	0x00000001
+#define IRQEN_ROE	0x00000002
+#define IRQEN_RSE	0x00000010
+#define IRQEN_TSE	0x00000020
+
+#define CX23888_IR_FILTR_REG	0x170018
+#define FILTR_LPF	0x0000FFFF
+
+/* This register doesn't follow the pattern; it's 0x23C on a CX23885 */
+#define CX23888_IR_FIFO_REG	0x170040
+#define FIFO_RXTX	0x0000FFFF
+#define FIFO_RXTX_LVL	0x00010000
+#define FIFO_RXTX_RTO	0x0001FFFF
+#define FIFO_RX_NDV	0x00020000
+#define FIFO_RX_DEPTH	8
+#define FIFO_TX_DEPTH	8
+
+/* CX23888 unique registers */
+#define CX23888_IR_SEEDP_REG	0x17001C
+#define CX23888_IR_TIMOL_REG	0x170020
+#define CX23888_IR_WAKE0_REG	0x170024
+#define CX23888_IR_WAKE1_REG	0x170028
+#define CX23888_IR_WAKE2_REG	0x17002C
+#define CX23888_IR_MASK0_REG	0x170030
+#define CX23888_IR_MASK1_REG	0x170034
+#define CX23888_IR_MAKS2_REG	0x170038
+#define CX23888_IR_DPIPG_REG	0x17003C
+#define CX23888_IR_LEARN_REG	0x170044
+
+#define CX23888_VIDCLK_FREQ	108000000 /* 108 MHz, BT.656 */
+#define CX23888_IR_REFCLK_FREQ	(CX23888_VIDCLK_FREQ / 2)
+
+/*
+ * We use this union internally for convenience, but callers to tx_write
+ * and rx_read will be expecting records of type struct ir_raw_event.
+ * Always ensure the size of this union is dictated by struct ir_raw_event.
+ */
+union cx23888_ir_fifo_rec {
+	u32 hw_fifo_data;
+	struct ir_raw_event ir_core_data;
+};
+
+#define CX23888_IR_RX_KFIFO_SIZE    (256 * sizeof(union cx23888_ir_fifo_rec))
+#define CX23888_IR_TX_KFIFO_SIZE    (256 * sizeof(union cx23888_ir_fifo_rec))
+
+struct cx23888_ir_state {
+	struct v4l2_subdev sd;
+	struct cx23885_dev *dev;
+	u32 id;
+	u32 rev;
+
+	struct v4l2_subdev_ir_parameters rx_params;
+	struct mutex rx_params_lock;
+	atomic_t rxclk_divider;
+	atomic_t rx_invert;
+
+	struct kfifo rx_kfifo;
+	spinlock_t rx_kfifo_lock;
+
+	struct v4l2_subdev_ir_parameters tx_params;
+	struct mutex tx_params_lock;
+	atomic_t txclk_divider;
+};
+
+static inline struct cx23888_ir_state *to_state(struct v4l2_subdev *sd)
+{
+	return v4l2_get_subdevdata(sd);
+}
+
+/*
+ * IR register block read and write functions
+ */
+static
+inline int cx23888_ir_write4(struct cx23885_dev *dev, u32 addr, u32 value)
+{
+	cx_write(addr, value);
+	return 0;
+}
+
+static inline u32 cx23888_ir_read4(struct cx23885_dev *dev, u32 addr)
+{
+	return cx_read(addr);
+}
+
+static inline int cx23888_ir_and_or4(struct cx23885_dev *dev, u32 addr,
+				     u32 and_mask, u32 or_value)
+{
+	cx_andor(addr, ~and_mask, or_value);
+	return 0;
+}
+
+/*
+ * Rx and Tx Clock Divider register computations
+ *
+ * Note the largest clock divider value of 0xffff corresponds to:
+ * 	(0xffff + 1) * 1000 / 108/2 MHz = 1,213,629.629... ns
+ * which fits in 21 bits, so we'll use unsigned int for time arguments.
+ */
+static inline u16 count_to_clock_divider(unsigned int d)
+{
+	if (d > RXCLK_RCD + 1)
+		d = RXCLK_RCD;
+	else if (d < 2)
+		d = 1;
+	else
+		d--;
+	return (u16) d;
+}
+
+static inline u16 ns_to_clock_divider(unsigned int ns)
+{
+	return count_to_clock_divider(
+		DIV_ROUND_CLOSEST(CX23888_IR_REFCLK_FREQ / 1000000 * ns, 1000));
+}
+
+static inline unsigned int clock_divider_to_ns(unsigned int divider)
+{
+	/* Period of the Rx or Tx clock in ns */
+	return DIV_ROUND_CLOSEST((divider + 1) * 1000,
+				 CX23888_IR_REFCLK_FREQ / 1000000);
+}
+
+static inline u16 carrier_freq_to_clock_divider(unsigned int freq)
+{
+	return count_to_clock_divider(
+			  DIV_ROUND_CLOSEST(CX23888_IR_REFCLK_FREQ, freq * 16));
+}
+
+static inline unsigned int clock_divider_to_carrier_freq(unsigned int divider)
+{
+	return DIV_ROUND_CLOSEST(CX23888_IR_REFCLK_FREQ, (divider + 1) * 16);
+}
+
+static inline u16 freq_to_clock_divider(unsigned int freq,
+					unsigned int rollovers)
+{
+	return count_to_clock_divider(
+		   DIV_ROUND_CLOSEST(CX23888_IR_REFCLK_FREQ, freq * rollovers));
+}
+
+static inline unsigned int clock_divider_to_freq(unsigned int divider,
+						 unsigned int rollovers)
+{
+	return DIV_ROUND_CLOSEST(CX23888_IR_REFCLK_FREQ,
+				 (divider + 1) * rollovers);
+}
+
+/*
+ * Low Pass Filter register calculations
+ *
+ * Note the largest count value of 0xffff corresponds to:
+ * 	0xffff * 1000 / 108/2 MHz = 1,213,611.11... ns
+ * which fits in 21 bits, so we'll use unsigned int for time arguments.
+ */
+static inline u16 count_to_lpf_count(unsigned int d)
+{
+	if (d > FILTR_LPF)
+		d = FILTR_LPF;
+	else if (d < 4)
+		d = 0;
+	return (u16) d;
+}
+
+static inline u16 ns_to_lpf_count(unsigned int ns)
+{
+	return count_to_lpf_count(
+		DIV_ROUND_CLOSEST(CX23888_IR_REFCLK_FREQ / 1000000 * ns, 1000));
+}
+
+static inline unsigned int lpf_count_to_ns(unsigned int count)
+{
+	/* Duration of the Low Pass Filter rejection window in ns */
+	return DIV_ROUND_CLOSEST(count * 1000,
+				 CX23888_IR_REFCLK_FREQ / 1000000);
+}
+
+static inline unsigned int lpf_count_to_us(unsigned int count)
+{
+	/* Duration of the Low Pass Filter rejection window in us */
+	return DIV_ROUND_CLOSEST(count, CX23888_IR_REFCLK_FREQ / 1000000);
+}
+
+/*
+ * FIFO register pulse width count compuations
+ */
+static u32 clock_divider_to_resolution(u16 divider)
+{
+	/*
+	 * Resolution is the duration of 1 tick of the readable portion of
+	 * of the pulse width counter as read from the FIFO.  The two lsb's are
+	 * not readable, hence the << 2.  This function returns ns.
+	 */
+	return DIV_ROUND_CLOSEST((1 << 2)  * ((u32) divider + 1) * 1000,
+				 CX23888_IR_REFCLK_FREQ / 1000000);
+}
+
+static u64 pulse_width_count_to_ns(u16 count, u16 divider)
+{
+	u64 n;
+	u32 rem;
+
+	/*
+	 * The 2 lsb's of the pulse width timer count are not readable, hence
+	 * the (count << 2) | 0x3
+	 */
+	n = (((u64) count << 2) | 0x3) * (divider + 1) * 1000; /* millicycles */
+	rem = do_div(n, CX23888_IR_REFCLK_FREQ / 1000000);     /* / MHz => ns */
+	if (rem >= CX23888_IR_REFCLK_FREQ / 1000000 / 2)
+		n++;
+	return n;
+}
+
+static unsigned int pulse_width_count_to_us(u16 count, u16 divider)
+{
+	u64 n;
+	u32 rem;
+
+	/*
+	 * The 2 lsb's of the pulse width timer count are not readable, hence
+	 * the (count << 2) | 0x3
+	 */
+	n = (((u64) count << 2) | 0x3) * (divider + 1);    /* cycles      */
+	rem = do_div(n, CX23888_IR_REFCLK_FREQ / 1000000); /* / MHz => us */
+	if (rem >= CX23888_IR_REFCLK_FREQ / 1000000 / 2)
+		n++;
+	return (unsigned int) n;
+}
+
+/*
+ * Pulse Clocks computations: Combined Pulse Width Count & Rx Clock Counts
+ *
+ * The total pulse clock count is an 18 bit pulse width timer count as the most
+ * significant part and (up to) 16 bit clock divider count as a modulus.
+ * When the Rx clock divider ticks down to 0, it increments the 18 bit pulse
+ * width timer count's least significant bit.
+ */
+static u64 ns_to_pulse_clocks(u32 ns)
+{
+	u64 clocks;
+	u32 rem;
+	clocks = CX23888_IR_REFCLK_FREQ / 1000000 * (u64) ns; /* millicycles  */
+	rem = do_div(clocks, 1000);                         /* /1000 = cycles */
+	if (rem >= 1000 / 2)
+		clocks++;
+	return clocks;
+}
+
+static u16 pulse_clocks_to_clock_divider(u64 count)
+{
+	do_div(count, (FIFO_RXTX << 2) | 0x3);
+
+	/* net result needs to be rounded down and decremented by 1 */
+	if (count > RXCLK_RCD + 1)
+		count = RXCLK_RCD;
+	else if (count < 2)
+		count = 1;
+	else
+		count--;
+	return (u16) count;
+}
+
+/*
+ * IR Control Register helpers
+ */
+enum tx_fifo_watermark {
+	TX_FIFO_HALF_EMPTY = 0,
+	TX_FIFO_EMPTY      = CNTRL_TIC,
+};
+
+enum rx_fifo_watermark {
+	RX_FIFO_HALF_FULL = 0,
+	RX_FIFO_NOT_EMPTY = CNTRL_RIC,
+};
+
+static inline void control_tx_irq_watermark(struct cx23885_dev *dev,
+					    enum tx_fifo_watermark level)
+{
+	cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~CNTRL_TIC, level);
+}
+
+static inline void control_rx_irq_watermark(struct cx23885_dev *dev,
+					    enum rx_fifo_watermark level)
+{
+	cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~CNTRL_RIC, level);
+}
+
+static inline void control_tx_enable(struct cx23885_dev *dev, bool enable)
+{
+	cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~(CNTRL_TXE | CNTRL_TFE),
+			   enable ? (CNTRL_TXE | CNTRL_TFE) : 0);
+}
+
+static inline void control_rx_enable(struct cx23885_dev *dev, bool enable)
+{
+	cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~(CNTRL_RXE | CNTRL_RFE),
+			   enable ? (CNTRL_RXE | CNTRL_RFE) : 0);
+}
+
+static inline void control_tx_modulation_enable(struct cx23885_dev *dev,
+						bool enable)
+{
+	cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~CNTRL_MOD,
+			   enable ? CNTRL_MOD : 0);
+}
+
+static inline void control_rx_demodulation_enable(struct cx23885_dev *dev,
+						  bool enable)
+{
+	cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~CNTRL_DMD,
+			   enable ? CNTRL_DMD : 0);
+}
+
+static inline void control_rx_s_edge_detection(struct cx23885_dev *dev,
+					       u32 edge_types)
+{
+	cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~CNTRL_EDG_BOTH,
+			   edge_types & CNTRL_EDG_BOTH);
+}
+
+static void control_rx_s_carrier_window(struct cx23885_dev *dev,
+					unsigned int carrier,
+					unsigned int *carrier_range_low,
+					unsigned int *carrier_range_high)
+{
+	u32 v;
+	unsigned int c16 = carrier * 16;
+
+	if (*carrier_range_low < DIV_ROUND_CLOSEST(c16, 16 + 3)) {
+		v = CNTRL_WIN_3_4;
+		*carrier_range_low = DIV_ROUND_CLOSEST(c16, 16 + 4);
+	} else {
+		v = CNTRL_WIN_3_3;
+		*carrier_range_low = DIV_ROUND_CLOSEST(c16, 16 + 3);
+	}
+
+	if (*carrier_range_high > DIV_ROUND_CLOSEST(c16, 16 - 3)) {
+		v |= CNTRL_WIN_4_3;
+		*carrier_range_high = DIV_ROUND_CLOSEST(c16, 16 - 4);
+	} else {
+		v |= CNTRL_WIN_3_3;
+		*carrier_range_high = DIV_ROUND_CLOSEST(c16, 16 - 3);
+	}
+	cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~CNTRL_WIN, v);
+}
+
+static inline void control_tx_polarity_invert(struct cx23885_dev *dev,
+					      bool invert)
+{
+	cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~CNTRL_CPL,
+			   invert ? CNTRL_CPL : 0);
+}
+
+static inline void control_tx_level_invert(struct cx23885_dev *dev,
+					  bool invert)
+{
+	cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~CNTRL_IVO,
+			   invert ? CNTRL_IVO : 0);
+}
+
+/*
+ * IR Rx & Tx Clock Register helpers
+ */
+static unsigned int txclk_tx_s_carrier(struct cx23885_dev *dev,
+				       unsigned int freq,
+				       u16 *divider)
+{
+	*divider = carrier_freq_to_clock_divider(freq);
+	cx23888_ir_write4(dev, CX23888_IR_TXCLK_REG, *divider);
+	return clock_divider_to_carrier_freq(*divider);
+}
+
+static unsigned int rxclk_rx_s_carrier(struct cx23885_dev *dev,
+				       unsigned int freq,
+				       u16 *divider)
+{
+	*divider = carrier_freq_to_clock_divider(freq);
+	cx23888_ir_write4(dev, CX23888_IR_RXCLK_REG, *divider);
+	return clock_divider_to_carrier_freq(*divider);
+}
+
+static u32 txclk_tx_s_max_pulse_width(struct cx23885_dev *dev, u32 ns,
+				      u16 *divider)
+{
+	u64 pulse_clocks;
+
+	if (ns > IR_MAX_DURATION)
+		ns = IR_MAX_DURATION;
+	pulse_clocks = ns_to_pulse_clocks(ns);
+	*divider = pulse_clocks_to_clock_divider(pulse_clocks);
+	cx23888_ir_write4(dev, CX23888_IR_TXCLK_REG, *divider);
+	return (u32) pulse_width_count_to_ns(FIFO_RXTX, *divider);
+}
+
+static u32 rxclk_rx_s_max_pulse_width(struct cx23885_dev *dev, u32 ns,
+				      u16 *divider)
+{
+	u64 pulse_clocks;
+
+	if (ns > IR_MAX_DURATION)
+		ns = IR_MAX_DURATION;
+	pulse_clocks = ns_to_pulse_clocks(ns);
+	*divider = pulse_clocks_to_clock_divider(pulse_clocks);
+	cx23888_ir_write4(dev, CX23888_IR_RXCLK_REG, *divider);
+	return (u32) pulse_width_count_to_ns(FIFO_RXTX, *divider);
+}
+
+/*
+ * IR Tx Carrier Duty Cycle register helpers
+ */
+static unsigned int cduty_tx_s_duty_cycle(struct cx23885_dev *dev,
+					  unsigned int duty_cycle)
+{
+	u32 n;
+	n = DIV_ROUND_CLOSEST(duty_cycle * 100, 625); /* 16ths of 100% */
+	if (n != 0)
+		n--;
+	if (n > 15)
+		n = 15;
+	cx23888_ir_write4(dev, CX23888_IR_CDUTY_REG, n);
+	return DIV_ROUND_CLOSEST((n + 1) * 100, 16);
+}
+
+/*
+ * IR Filter Register helpers
+ */
+static u32 filter_rx_s_min_width(struct cx23885_dev *dev, u32 min_width_ns)
+{
+	u32 count = ns_to_lpf_count(min_width_ns);
+	cx23888_ir_write4(dev, CX23888_IR_FILTR_REG, count);
+	return lpf_count_to_ns(count);
+}
+
+/*
+ * IR IRQ Enable Register helpers
+ */
+static inline void irqenable_rx(struct cx23885_dev *dev, u32 mask)
+{
+	mask &= (IRQEN_RTE | IRQEN_ROE | IRQEN_RSE);
+	cx23888_ir_and_or4(dev, CX23888_IR_IRQEN_REG,
+			   ~(IRQEN_RTE | IRQEN_ROE | IRQEN_RSE), mask);
+}
+
+static inline void irqenable_tx(struct cx23885_dev *dev, u32 mask)
+{
+	mask &= IRQEN_TSE;
+	cx23888_ir_and_or4(dev, CX23888_IR_IRQEN_REG, ~IRQEN_TSE, mask);
+}
+
+/*
+ * V4L2 Subdevice IR Ops
+ */
+static int cx23888_ir_irq_handler(struct v4l2_subdev *sd, u32 status,
+				  bool *handled)
+{
+	struct cx23888_ir_state *state = to_state(sd);
+	struct cx23885_dev *dev = state->dev;
+	unsigned long flags;
+
+	u32 cntrl = cx23888_ir_read4(dev, CX23888_IR_CNTRL_REG);
+	u32 irqen = cx23888_ir_read4(dev, CX23888_IR_IRQEN_REG);
+	u32 stats = cx23888_ir_read4(dev, CX23888_IR_STATS_REG);
+
+	union cx23888_ir_fifo_rec rx_data[FIFO_RX_DEPTH];
+	unsigned int i, j, k;
+	u32 events, v;
+	int tsr, rsr, rto, ror, tse, rse, rte, roe, kror;
+
+	tsr = stats & STATS_TSR; /* Tx FIFO Service Request */
+	rsr = stats & STATS_RSR; /* Rx FIFO Service Request */
+	rto = stats & STATS_RTO; /* Rx Pulse Width Timer Time Out */
+	ror = stats & STATS_ROR; /* Rx FIFO Over Run */
+
+	tse = irqen & IRQEN_TSE; /* Tx FIFO Service Request IRQ Enable */
+	rse = irqen & IRQEN_RSE; /* Rx FIFO Service Reuqest IRQ Enable */
+	rte = irqen & IRQEN_RTE; /* Rx Pulse Width Timer Time Out IRQ Enable */
+	roe = irqen & IRQEN_ROE; /* Rx FIFO Over Run IRQ Enable */
+
+	*handled = false;
+	v4l2_dbg(2, ir_888_debug, sd, "IRQ Status:  %s %s %s %s %s %s\n",
+		 tsr ? "tsr" : "   ", rsr ? "rsr" : "   ",
+		 rto ? "rto" : "   ", ror ? "ror" : "   ",
+		 stats & STATS_TBY ? "tby" : "   ",
+		 stats & STATS_RBY ? "rby" : "   ");
+
+	v4l2_dbg(2, ir_888_debug, sd, "IRQ Enables: %s %s %s %s\n",
+		 tse ? "tse" : "   ", rse ? "rse" : "   ",
+		 rte ? "rte" : "   ", roe ? "roe" : "   ");
+
+	/*
+	 * Transmitter interrupt service
+	 */
+	if (tse && tsr) {
+		/*
+		 * TODO:
+		 * Check the watermark threshold setting
+		 * Pull FIFO_TX_DEPTH or FIFO_TX_DEPTH/2 entries from tx_kfifo
+		 * Push the data to the hardware FIFO.
+		 * If there was nothing more to send in the tx_kfifo, disable
+		 *	the TSR IRQ and notify the v4l2_device.
+		 * If there was something in the tx_kfifo, check the tx_kfifo
+		 *      level and notify the v4l2_device, if it is low.
+		 */
+		/* For now, inhibit TSR interrupt until Tx is implemented */
+		irqenable_tx(dev, 0);
+		events = V4L2_SUBDEV_IR_TX_FIFO_SERVICE_REQ;
+		v4l2_subdev_notify(sd, V4L2_SUBDEV_IR_TX_NOTIFY, &events);
+		*handled = true;
+	}
+
+	/*
+	 * Receiver interrupt service
+	 */
+	kror = 0;
+	if ((rse && rsr) || (rte && rto)) {
+		/*
+		 * Receive data on RSR to clear the STATS_RSR.
+		 * Receive data on RTO, since we may not have yet hit the RSR
+		 * watermark when we receive the RTO.
+		 */
+		for (i = 0, v = FIFO_RX_NDV;
+		     (v & FIFO_RX_NDV) && !kror; i = 0) {
+			for (j = 0;
+			     (v & FIFO_RX_NDV) && j < FIFO_RX_DEPTH; j++) {
+				v = cx23888_ir_read4(dev, CX23888_IR_FIFO_REG);
+				rx_data[i].hw_fifo_data = v & ~FIFO_RX_NDV;
+				i++;
+			}
+			if (i == 0)
+				break;
+			j = i * sizeof(union cx23888_ir_fifo_rec);
+			k = kfifo_in_locked(&state->rx_kfifo,
+				      (unsigned char *) rx_data, j,
+				      &state->rx_kfifo_lock);
+			if (k != j)
+				kror++; /* rx_kfifo over run */
+		}
+		*handled = true;
+	}
+
+	events = 0;
+	v = 0;
+	if (kror) {
+		events |= V4L2_SUBDEV_IR_RX_SW_FIFO_OVERRUN;
+		v4l2_err(sd, "IR receiver software FIFO overrun\n");
+	}
+	if (roe && ror) {
+		/*
+		 * The RX FIFO Enable (CNTRL_RFE) must be toggled to clear
+		 * the Rx FIFO Over Run status (STATS_ROR)
+		 */
+		v |= CNTRL_RFE;
+		events |= V4L2_SUBDEV_IR_RX_HW_FIFO_OVERRUN;
+		v4l2_err(sd, "IR receiver hardware FIFO overrun\n");
+	}
+	if (rte && rto) {
+		/*
+		 * The IR Receiver Enable (CNTRL_RXE) must be toggled to clear
+		 * the Rx Pulse Width Timer Time Out (STATS_RTO)
+		 */
+		v |= CNTRL_RXE;
+		events |= V4L2_SUBDEV_IR_RX_END_OF_RX_DETECTED;
+	}
+	if (v) {
+		/* Clear STATS_ROR & STATS_RTO as needed by reseting hardware */
+		cx23888_ir_write4(dev, CX23888_IR_CNTRL_REG, cntrl & ~v);
+		cx23888_ir_write4(dev, CX23888_IR_CNTRL_REG, cntrl);
+		*handled = true;
+	}
+
+	spin_lock_irqsave(&state->rx_kfifo_lock, flags);
+	if (kfifo_len(&state->rx_kfifo) >= CX23888_IR_RX_KFIFO_SIZE / 2)
+		events |= V4L2_SUBDEV_IR_RX_FIFO_SERVICE_REQ;
+	spin_unlock_irqrestore(&state->rx_kfifo_lock, flags);
+
+	if (events)
+		v4l2_subdev_notify(sd, V4L2_SUBDEV_IR_RX_NOTIFY, &events);
+	return 0;
+}
+
+/* Receiver */
+static int cx23888_ir_rx_read(struct v4l2_subdev *sd, u8 *buf, size_t count,
+			      ssize_t *num)
+{
+	struct cx23888_ir_state *state = to_state(sd);
+	bool invert = (bool) atomic_read(&state->rx_invert);
+	u16 divider = (u16) atomic_read(&state->rxclk_divider);
+
+	unsigned int i, n;
+	union cx23888_ir_fifo_rec *p;
+	unsigned u, v, w;
+
+	n = count / sizeof(union cx23888_ir_fifo_rec)
+		* sizeof(union cx23888_ir_fifo_rec);
+	if (n == 0) {
+		*num = 0;
+		return 0;
+	}
+
+	n = kfifo_out_locked(&state->rx_kfifo, buf, n, &state->rx_kfifo_lock);
+
+	n /= sizeof(union cx23888_ir_fifo_rec);
+	*num = n * sizeof(union cx23888_ir_fifo_rec);
+
+	for (p = (union cx23888_ir_fifo_rec *) buf, i = 0; i < n; p++, i++) {
+
+		if ((p->hw_fifo_data & FIFO_RXTX_RTO) == FIFO_RXTX_RTO) {
+			/* Assume RTO was because of no IR light input */
+			u = 0;
+			w = 1;
+		} else {
+			u = (p->hw_fifo_data & FIFO_RXTX_LVL) ? 1 : 0;
+			if (invert)
+				u = u ? 0 : 1;
+			w = 0;
+		}
+
+		v = (unsigned) pulse_width_count_to_ns(
+				  (u16) (p->hw_fifo_data & FIFO_RXTX), divider);
+		if (v > IR_MAX_DURATION)
+			v = IR_MAX_DURATION;
+
+		init_ir_raw_event(&p->ir_core_data);
+		p->ir_core_data.pulse = u;
+		p->ir_core_data.duration = v;
+		p->ir_core_data.timeout = w;
+
+		v4l2_dbg(2, ir_888_debug, sd, "rx read: %10u ns  %s  %s\n",
+			 v, u ? "mark" : "space", w ? "(timed out)" : "");
+		if (w)
+			v4l2_dbg(2, ir_888_debug, sd, "rx read: end of rx\n");
+	}
+	return 0;
+}
+
+static int cx23888_ir_rx_g_parameters(struct v4l2_subdev *sd,
+				      struct v4l2_subdev_ir_parameters *p)
+{
+	struct cx23888_ir_state *state = to_state(sd);
+	mutex_lock(&state->rx_params_lock);
+	memcpy(p, &state->rx_params, sizeof(struct v4l2_subdev_ir_parameters));
+	mutex_unlock(&state->rx_params_lock);
+	return 0;
+}
+
+static int cx23888_ir_rx_shutdown(struct v4l2_subdev *sd)
+{
+	struct cx23888_ir_state *state = to_state(sd);
+	struct cx23885_dev *dev = state->dev;
+
+	mutex_lock(&state->rx_params_lock);
+
+	/* Disable or slow down all IR Rx circuits and counters */
+	irqenable_rx(dev, 0);
+	control_rx_enable(dev, false);
+	control_rx_demodulation_enable(dev, false);
+	control_rx_s_edge_detection(dev, CNTRL_EDG_NONE);
+	filter_rx_s_min_width(dev, 0);
+	cx23888_ir_write4(dev, CX23888_IR_RXCLK_REG, RXCLK_RCD);
+
+	state->rx_params.shutdown = true;
+
+	mutex_unlock(&state->rx_params_lock);
+	return 0;
+}
+
+static int cx23888_ir_rx_s_parameters(struct v4l2_subdev *sd,
+				      struct v4l2_subdev_ir_parameters *p)
+{
+	struct cx23888_ir_state *state = to_state(sd);
+	struct cx23885_dev *dev = state->dev;
+	struct v4l2_subdev_ir_parameters *o = &state->rx_params;
+	u16 rxclk_divider;
+
+	if (p->shutdown)
+		return cx23888_ir_rx_shutdown(sd);
+
+	if (p->mode != V4L2_SUBDEV_IR_MODE_PULSE_WIDTH)
+		return -ENOSYS;
+
+	mutex_lock(&state->rx_params_lock);
+
+	o->shutdown = p->shutdown;
+
+	o->mode = p->mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH;
+
+	o->bytes_per_data_element = p->bytes_per_data_element
+				  = sizeof(union cx23888_ir_fifo_rec);
+
+	/* Before we tweak the hardware, we have to disable the receiver */
+	irqenable_rx(dev, 0);
+	control_rx_enable(dev, false);
+
+	control_rx_demodulation_enable(dev, p->modulation);
+	o->modulation = p->modulation;
+
+	if (p->modulation) {
+		p->carrier_freq = rxclk_rx_s_carrier(dev, p->carrier_freq,
+						     &rxclk_divider);
+
+		o->carrier_freq = p->carrier_freq;
+
+		o->duty_cycle = p->duty_cycle = 50;
+
+		control_rx_s_carrier_window(dev, p->carrier_freq,
+					    &p->carrier_range_lower,
+					    &p->carrier_range_upper);
+		o->carrier_range_lower = p->carrier_range_lower;
+		o->carrier_range_upper = p->carrier_range_upper;
+
+		p->max_pulse_width =
+			(u32) pulse_width_count_to_ns(FIFO_RXTX, rxclk_divider);
+	} else {
+		p->max_pulse_width =
+			    rxclk_rx_s_max_pulse_width(dev, p->max_pulse_width,
+						       &rxclk_divider);
+	}
+	o->max_pulse_width = p->max_pulse_width;
+	atomic_set(&state->rxclk_divider, rxclk_divider);
+
+	p->noise_filter_min_width =
+			  filter_rx_s_min_width(dev, p->noise_filter_min_width);
+	o->noise_filter_min_width = p->noise_filter_min_width;
+
+	p->resolution = clock_divider_to_resolution(rxclk_divider);
+	o->resolution = p->resolution;
+
+	/* FIXME - make this dependent on resolution for better performance */
+	control_rx_irq_watermark(dev, RX_FIFO_HALF_FULL);
+
+	control_rx_s_edge_detection(dev, CNTRL_EDG_BOTH);
+
+	o->invert_level = p->invert_level;
+	atomic_set(&state->rx_invert, p->invert_level);
+
+	o->interrupt_enable = p->interrupt_enable;
+	o->enable = p->enable;
+	if (p->enable) {
+		unsigned long flags;
+
+		spin_lock_irqsave(&state->rx_kfifo_lock, flags);
+		kfifo_reset(&state->rx_kfifo);
+		/* reset tx_fifo too if there is one... */
+		spin_unlock_irqrestore(&state->rx_kfifo_lock, flags);
+		if (p->interrupt_enable)
+			irqenable_rx(dev, IRQEN_RSE | IRQEN_RTE | IRQEN_ROE);
+		control_rx_enable(dev, p->enable);
+	}
+
+	mutex_unlock(&state->rx_params_lock);
+	return 0;
+}
+
+/* Transmitter */
+static int cx23888_ir_tx_write(struct v4l2_subdev *sd, u8 *buf, size_t count,
+			       ssize_t *num)
+{
+	struct cx23888_ir_state *state = to_state(sd);
+	struct cx23885_dev *dev = state->dev;
+	/* For now enable the Tx FIFO Service interrupt & pretend we did work */
+	irqenable_tx(dev, IRQEN_TSE);
+	*num = count;
+	return 0;
+}
+
+static int cx23888_ir_tx_g_parameters(struct v4l2_subdev *sd,
+				      struct v4l2_subdev_ir_parameters *p)
+{
+	struct cx23888_ir_state *state = to_state(sd);
+	mutex_lock(&state->tx_params_lock);
+	memcpy(p, &state->tx_params, sizeof(struct v4l2_subdev_ir_parameters));
+	mutex_unlock(&state->tx_params_lock);
+	return 0;
+}
+
+static int cx23888_ir_tx_shutdown(struct v4l2_subdev *sd)
+{
+	struct cx23888_ir_state *state = to_state(sd);
+	struct cx23885_dev *dev = state->dev;
+
+	mutex_lock(&state->tx_params_lock);
+
+	/* Disable or slow down all IR Tx circuits and counters */
+	irqenable_tx(dev, 0);
+	control_tx_enable(dev, false);
+	control_tx_modulation_enable(dev, false);
+	cx23888_ir_write4(dev, CX23888_IR_TXCLK_REG, TXCLK_TCD);
+
+	state->tx_params.shutdown = true;
+
+	mutex_unlock(&state->tx_params_lock);
+	return 0;
+}
+
+static int cx23888_ir_tx_s_parameters(struct v4l2_subdev *sd,
+				      struct v4l2_subdev_ir_parameters *p)
+{
+	struct cx23888_ir_state *state = to_state(sd);
+	struct cx23885_dev *dev = state->dev;
+	struct v4l2_subdev_ir_parameters *o = &state->tx_params;
+	u16 txclk_divider;
+
+	if (p->shutdown)
+		return cx23888_ir_tx_shutdown(sd);
+
+	if (p->mode != V4L2_SUBDEV_IR_MODE_PULSE_WIDTH)
+		return -ENOSYS;
+
+	mutex_lock(&state->tx_params_lock);
+
+	o->shutdown = p->shutdown;
+
+	o->mode = p->mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH;
+
+	o->bytes_per_data_element = p->bytes_per_data_element
+				  = sizeof(union cx23888_ir_fifo_rec);
+
+	/* Before we tweak the hardware, we have to disable the transmitter */
+	irqenable_tx(dev, 0);
+	control_tx_enable(dev, false);
+
+	control_tx_modulation_enable(dev, p->modulation);
+	o->modulation = p->modulation;
+
+	if (p->modulation) {
+		p->carrier_freq = txclk_tx_s_carrier(dev, p->carrier_freq,
+						     &txclk_divider);
+		o->carrier_freq = p->carrier_freq;
+
+		p->duty_cycle = cduty_tx_s_duty_cycle(dev, p->duty_cycle);
+		o->duty_cycle = p->duty_cycle;
+
+		p->max_pulse_width =
+			(u32) pulse_width_count_to_ns(FIFO_RXTX, txclk_divider);
+	} else {
+		p->max_pulse_width =
+			    txclk_tx_s_max_pulse_width(dev, p->max_pulse_width,
+						       &txclk_divider);
+	}
+	o->max_pulse_width = p->max_pulse_width;
+	atomic_set(&state->txclk_divider, txclk_divider);
+
+	p->resolution = clock_divider_to_resolution(txclk_divider);
+	o->resolution = p->resolution;
+
+	/* FIXME - make this dependent on resolution for better performance */
+	control_tx_irq_watermark(dev, TX_FIFO_HALF_EMPTY);
+
+	control_tx_polarity_invert(dev, p->invert_carrier_sense);
+	o->invert_carrier_sense = p->invert_carrier_sense;
+
+	control_tx_level_invert(dev, p->invert_level);
+	o->invert_level = p->invert_level;
+
+	o->interrupt_enable = p->interrupt_enable;
+	o->enable = p->enable;
+	if (p->enable) {
+		if (p->interrupt_enable)
+			irqenable_tx(dev, IRQEN_TSE);
+		control_tx_enable(dev, p->enable);
+	}
+
+	mutex_unlock(&state->tx_params_lock);
+	return 0;
+}
+
+
+/*
+ * V4L2 Subdevice Core Ops
+ */
+static int cx23888_ir_log_status(struct v4l2_subdev *sd)
+{
+	struct cx23888_ir_state *state = to_state(sd);
+	struct cx23885_dev *dev = state->dev;
+	char *s;
+	int i, j;
+
+	u32 cntrl = cx23888_ir_read4(dev, CX23888_IR_CNTRL_REG);
+	u32 txclk = cx23888_ir_read4(dev, CX23888_IR_TXCLK_REG) & TXCLK_TCD;
+	u32 rxclk = cx23888_ir_read4(dev, CX23888_IR_RXCLK_REG) & RXCLK_RCD;
+	u32 cduty = cx23888_ir_read4(dev, CX23888_IR_CDUTY_REG) & CDUTY_CDC;
+	u32 stats = cx23888_ir_read4(dev, CX23888_IR_STATS_REG);
+	u32 irqen = cx23888_ir_read4(dev, CX23888_IR_IRQEN_REG);
+	u32 filtr = cx23888_ir_read4(dev, CX23888_IR_FILTR_REG) & FILTR_LPF;
+
+	v4l2_info(sd, "IR Receiver:\n");
+	v4l2_info(sd, "\tEnabled:                           %s\n",
+		  cntrl & CNTRL_RXE ? "yes" : "no");
+	v4l2_info(sd, "\tDemodulation from a carrier:       %s\n",
+		  cntrl & CNTRL_DMD ? "enabled" : "disabled");
+	v4l2_info(sd, "\tFIFO:                              %s\n",
+		  cntrl & CNTRL_RFE ? "enabled" : "disabled");
+	switch (cntrl & CNTRL_EDG) {
+	case CNTRL_EDG_NONE:
+		s = "disabled";
+		break;
+	case CNTRL_EDG_FALL:
+		s = "falling edge";
+		break;
+	case CNTRL_EDG_RISE:
+		s = "rising edge";
+		break;
+	case CNTRL_EDG_BOTH:
+		s = "rising & falling edges";
+		break;
+	default:
+		s = "??? edge";
+		break;
+	}
+	v4l2_info(sd, "\tPulse timers' start/stop trigger:  %s\n", s);
+	v4l2_info(sd, "\tFIFO data on pulse timer overflow: %s\n",
+		  cntrl & CNTRL_R ? "not loaded" : "overflow marker");
+	v4l2_info(sd, "\tFIFO interrupt watermark:          %s\n",
+		  cntrl & CNTRL_RIC ? "not empty" : "half full or greater");
+	v4l2_info(sd, "\tLoopback mode:                     %s\n",
+		  cntrl & CNTRL_LBM ? "loopback active" : "normal receive");
+	if (cntrl & CNTRL_DMD) {
+		v4l2_info(sd, "\tExpected carrier (16 clocks):      %u Hz\n",
+			  clock_divider_to_carrier_freq(rxclk));
+		switch (cntrl & CNTRL_WIN) {
+		case CNTRL_WIN_3_3:
+			i = 3;
+			j = 3;
+			break;
+		case CNTRL_WIN_4_3:
+			i = 4;
+			j = 3;
+			break;
+		case CNTRL_WIN_3_4:
+			i = 3;
+			j = 4;
+			break;
+		case CNTRL_WIN_4_4:
+			i = 4;
+			j = 4;
+			break;
+		default:
+			i = 0;
+			j = 0;
+			break;
+		}
+		v4l2_info(sd, "\tNext carrier edge window:          16 clocks "
+			  "-%1d/+%1d, %u to %u Hz\n", i, j,
+			  clock_divider_to_freq(rxclk, 16 + j),
+			  clock_divider_to_freq(rxclk, 16 - i));
+	}
+	v4l2_info(sd, "\tMax measurable pulse width:        %u us, %llu ns\n",
+		  pulse_width_count_to_us(FIFO_RXTX, rxclk),
+		  pulse_width_count_to_ns(FIFO_RXTX, rxclk));
+	v4l2_info(sd, "\tLow pass filter:                   %s\n",
+		  filtr ? "enabled" : "disabled");
+	if (filtr)
+		v4l2_info(sd, "\tMin acceptable pulse width (LPF):  %u us, "
+			  "%u ns\n",
+			  lpf_count_to_us(filtr),
+			  lpf_count_to_ns(filtr));
+	v4l2_info(sd, "\tPulse width timer timed-out:       %s\n",
+		  stats & STATS_RTO ? "yes" : "no");
+	v4l2_info(sd, "\tPulse width timer time-out intr:   %s\n",
+		  irqen & IRQEN_RTE ? "enabled" : "disabled");
+	v4l2_info(sd, "\tFIFO overrun:                      %s\n",
+		  stats & STATS_ROR ? "yes" : "no");
+	v4l2_info(sd, "\tFIFO overrun interrupt:            %s\n",
+		  irqen & IRQEN_ROE ? "enabled" : "disabled");
+	v4l2_info(sd, "\tBusy:                              %s\n",
+		  stats & STATS_RBY ? "yes" : "no");
+	v4l2_info(sd, "\tFIFO service requested:            %s\n",
+		  stats & STATS_RSR ? "yes" : "no");
+	v4l2_info(sd, "\tFIFO service request interrupt:    %s\n",
+		  irqen & IRQEN_RSE ? "enabled" : "disabled");
+
+	v4l2_info(sd, "IR Transmitter:\n");
+	v4l2_info(sd, "\tEnabled:                           %s\n",
+		  cntrl & CNTRL_TXE ? "yes" : "no");
+	v4l2_info(sd, "\tModulation onto a carrier:         %s\n",
+		  cntrl & CNTRL_MOD ? "enabled" : "disabled");
+	v4l2_info(sd, "\tFIFO:                              %s\n",
+		  cntrl & CNTRL_TFE ? "enabled" : "disabled");
+	v4l2_info(sd, "\tFIFO interrupt watermark:          %s\n",
+		  cntrl & CNTRL_TIC ? "not empty" : "half full or less");
+	v4l2_info(sd, "\tOutput pin level inversion         %s\n",
+		  cntrl & CNTRL_IVO ? "yes" : "no");
+	v4l2_info(sd, "\tCarrier polarity:                  %s\n",
+		  cntrl & CNTRL_CPL ? "space:burst mark:noburst"
+				    : "space:noburst mark:burst");
+	if (cntrl & CNTRL_MOD) {
+		v4l2_info(sd, "\tCarrier (16 clocks):               %u Hz\n",
+			  clock_divider_to_carrier_freq(txclk));
+		v4l2_info(sd, "\tCarrier duty cycle:                %2u/16\n",
+			  cduty + 1);
+	}
+	v4l2_info(sd, "\tMax pulse width:                   %u us, %llu ns\n",
+		  pulse_width_count_to_us(FIFO_RXTX, txclk),
+		  pulse_width_count_to_ns(FIFO_RXTX, txclk));
+	v4l2_info(sd, "\tBusy:                              %s\n",
+		  stats & STATS_TBY ? "yes" : "no");
+	v4l2_info(sd, "\tFIFO service requested:            %s\n",
+		  stats & STATS_TSR ? "yes" : "no");
+	v4l2_info(sd, "\tFIFO service request interrupt:    %s\n",
+		  irqen & IRQEN_TSE ? "enabled" : "disabled");
+
+	return 0;
+}
+
+static inline int cx23888_ir_dbg_match(const struct v4l2_dbg_match *match)
+{
+	return match->type == V4L2_CHIP_MATCH_HOST && match->addr == 2;
+}
+
+static int cx23888_ir_g_chip_ident(struct v4l2_subdev *sd,
+				   struct v4l2_dbg_chip_ident *chip)
+{
+	struct cx23888_ir_state *state = to_state(sd);
+
+	if (cx23888_ir_dbg_match(&chip->match)) {
+		chip->ident = state->id;
+		chip->revision = state->rev;
+	}
+	return 0;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int cx23888_ir_g_register(struct v4l2_subdev *sd,
+				 struct v4l2_dbg_register *reg)
+{
+	struct cx23888_ir_state *state = to_state(sd);
+	u32 addr = CX23888_IR_REG_BASE + (u32) reg->reg;
+
+	if (!cx23888_ir_dbg_match(&reg->match))
+		return -EINVAL;
+	if ((addr & 0x3) != 0)
+		return -EINVAL;
+	if (addr < CX23888_IR_CNTRL_REG || addr > CX23888_IR_LEARN_REG)
+		return -EINVAL;
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+	reg->size = 4;
+	reg->val = cx23888_ir_read4(state->dev, addr);
+	return 0;
+}
+
+static int cx23888_ir_s_register(struct v4l2_subdev *sd,
+				 struct v4l2_dbg_register *reg)
+{
+	struct cx23888_ir_state *state = to_state(sd);
+	u32 addr = CX23888_IR_REG_BASE + (u32) reg->reg;
+
+	if (!cx23888_ir_dbg_match(&reg->match))
+		return -EINVAL;
+	if ((addr & 0x3) != 0)
+		return -EINVAL;
+	if (addr < CX23888_IR_CNTRL_REG || addr > CX23888_IR_LEARN_REG)
+		return -EINVAL;
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+	cx23888_ir_write4(state->dev, addr, reg->val);
+	return 0;
+}
+#endif
+
+static const struct v4l2_subdev_core_ops cx23888_ir_core_ops = {
+	.g_chip_ident = cx23888_ir_g_chip_ident,
+	.log_status = cx23888_ir_log_status,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.g_register = cx23888_ir_g_register,
+	.s_register = cx23888_ir_s_register,
+#endif
+	.interrupt_service_routine = cx23888_ir_irq_handler,
+};
+
+static const struct v4l2_subdev_ir_ops cx23888_ir_ir_ops = {
+	.rx_read = cx23888_ir_rx_read,
+	.rx_g_parameters = cx23888_ir_rx_g_parameters,
+	.rx_s_parameters = cx23888_ir_rx_s_parameters,
+
+	.tx_write = cx23888_ir_tx_write,
+	.tx_g_parameters = cx23888_ir_tx_g_parameters,
+	.tx_s_parameters = cx23888_ir_tx_s_parameters,
+};
+
+static const struct v4l2_subdev_ops cx23888_ir_controller_ops = {
+	.core = &cx23888_ir_core_ops,
+	.ir = &cx23888_ir_ir_ops,
+};
+
+static const struct v4l2_subdev_ir_parameters default_rx_params = {
+	.bytes_per_data_element = sizeof(union cx23888_ir_fifo_rec),
+	.mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH,
+
+	.enable = false,
+	.interrupt_enable = false,
+	.shutdown = true,
+
+	.modulation = true,
+	.carrier_freq = 36000, /* 36 kHz - RC-5, RC-6, and RC-6A carrier */
+
+	/* RC-5:    666,667 ns = 1/36 kHz * 32 cycles * 1 mark * 0.75 */
+	/* RC-6A:   333,333 ns = 1/36 kHz * 16 cycles * 1 mark * 0.75 */
+	.noise_filter_min_width = 333333, /* ns */
+	.carrier_range_lower = 35000,
+	.carrier_range_upper = 37000,
+	.invert_level = false,
+};
+
+static const struct v4l2_subdev_ir_parameters default_tx_params = {
+	.bytes_per_data_element = sizeof(union cx23888_ir_fifo_rec),
+	.mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH,
+
+	.enable = false,
+	.interrupt_enable = false,
+	.shutdown = true,
+
+	.modulation = true,
+	.carrier_freq = 36000, /* 36 kHz - RC-5 carrier */
+	.duty_cycle = 25,      /* 25 %   - RC-5 carrier */
+	.invert_level = false,
+	.invert_carrier_sense = false,
+};
+
+int cx23888_ir_probe(struct cx23885_dev *dev)
+{
+	struct cx23888_ir_state *state;
+	struct v4l2_subdev *sd;
+	struct v4l2_subdev_ir_parameters default_params;
+	int ret;
+
+	state = kzalloc(sizeof(struct cx23888_ir_state), GFP_KERNEL);
+	if (state == NULL)
+		return -ENOMEM;
+
+	spin_lock_init(&state->rx_kfifo_lock);
+	if (kfifo_alloc(&state->rx_kfifo, CX23888_IR_RX_KFIFO_SIZE, GFP_KERNEL))
+		return -ENOMEM;
+
+	state->dev = dev;
+	state->id = V4L2_IDENT_CX23888_IR;
+	state->rev = 0;
+	sd = &state->sd;
+
+	v4l2_subdev_init(sd, &cx23888_ir_controller_ops);
+	v4l2_set_subdevdata(sd, state);
+	/* FIXME - fix the formatting of dev->v4l2_dev.name and use it */
+	snprintf(sd->name, sizeof(sd->name), "%s/888-ir", dev->name);
+	sd->grp_id = CX23885_HW_888_IR;
+
+	ret = v4l2_device_register_subdev(&dev->v4l2_dev, sd);
+	if (ret == 0) {
+		/*
+		 * Ensure no interrupts arrive from '888 specific conditions,
+		 * since we ignore them in this driver to have commonality with
+		 * similar IR controller cores.
+		 */
+		cx23888_ir_write4(dev, CX23888_IR_IRQEN_REG, 0);
+
+		mutex_init(&state->rx_params_lock);
+		memcpy(&default_params, &default_rx_params,
+		       sizeof(struct v4l2_subdev_ir_parameters));
+		v4l2_subdev_call(sd, ir, rx_s_parameters, &default_params);
+
+		mutex_init(&state->tx_params_lock);
+		memcpy(&default_params, &default_tx_params,
+		       sizeof(struct v4l2_subdev_ir_parameters));
+		v4l2_subdev_call(sd, ir, tx_s_parameters, &default_params);
+	} else {
+		kfifo_free(&state->rx_kfifo);
+	}
+	return ret;
+}
+
+int cx23888_ir_remove(struct cx23885_dev *dev)
+{
+	struct v4l2_subdev *sd;
+	struct cx23888_ir_state *state;
+
+	sd = cx23885_find_hw(dev, CX23885_HW_888_IR);
+	if (sd == NULL)
+		return -ENODEV;
+
+	cx23888_ir_rx_shutdown(sd);
+	cx23888_ir_tx_shutdown(sd);
+
+	state = to_state(sd);
+	v4l2_device_unregister_subdev(sd);
+	kfifo_free(&state->rx_kfifo);
+	kfree(state);
+	/* Nothing more to free() as state held the actual v4l2_subdev object */
+	return 0;
+}
diff --git a/drivers/media/pci/cx23885/cx23888-ir.h b/drivers/media/pci/cx23885/cx23888-ir.h
new file mode 100644
index 0000000..d2de41c
--- /dev/null
+++ b/drivers/media/pci/cx23885/cx23888-ir.h
@@ -0,0 +1,28 @@
+/*
+ *  Driver for the Conexant CX23885/7/8 PCIe bridge
+ *
+ *  CX23888 Integrated Consumer Infrared Controller
+ *
+ *  Copyright (C) 2009  Andy Walls <awalls@md.metrocast.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 program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You 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 _CX23888_IR_H_
+#define _CX23888_IR_H_
+int cx23888_ir_probe(struct cx23885_dev *dev);
+int cx23888_ir_remove(struct cx23885_dev *dev);
+#endif
diff --git a/drivers/media/pci/cx23885/netup-eeprom.c b/drivers/media/pci/cx23885/netup-eeprom.c
new file mode 100644
index 0000000..98a48f5
--- /dev/null
+++ b/drivers/media/pci/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, 63);
+
+	for (i = 64, j = 0; i < 70; i++, j++)
+		cinfo->port[0].mac[j] =  netup_eeprom_read(i2c_adap, i);
+
+	for (i = 70, j = 0; i < 76; i++, j++)
+		cinfo->port[1].mac[j] =  netup_eeprom_read(i2c_adap, i);
+};
diff --git a/drivers/media/pci/cx23885/netup-eeprom.h b/drivers/media/pci/cx23885/netup-eeprom.h
new file mode 100644
index 0000000..13926e1
--- /dev/null
+++ b/drivers/media/pci/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/pci/cx23885/netup-init.c b/drivers/media/pci/cx23885/netup-init.c
new file mode 100644
index 0000000..f4893e6
--- /dev/null
+++ b/drivers/media/pci/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/pci/cx23885/netup-init.h b/drivers/media/pci/cx23885/netup-init.h
new file mode 100644
index 0000000..d26ae4b
--- /dev/null
+++ b/drivers/media/pci/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/pci/cx25821/Kconfig b/drivers/media/pci/cx25821/Kconfig
new file mode 100644
index 0000000..5f6b542
--- /dev/null
+++ b/drivers/media/pci/cx25821/Kconfig
@@ -0,0 +1,34 @@
+config VIDEO_CX25821
+	tristate "Conexant cx25821 support"
+	depends on DVB_CORE && VIDEO_DEV && PCI && I2C
+	select I2C_ALGOBIT
+	select VIDEO_BTCX
+	select VIDEO_TVEEPROM
+	depends on RC_CORE
+	select VIDEOBUF_DVB
+	select VIDEOBUF_DMA_SG
+	select VIDEO_CX25840
+	select VIDEO_CX2341X
+	---help---
+	  This is a video4linux driver for Conexant 25821 based
+	  TV cards.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called cx25821
+
+config VIDEO_CX25821_ALSA
+	tristate "Conexant 25821 DMA audio support"
+	depends on VIDEO_CX25821 && SND && EXPERIMENTAL
+	select SND_PCM
+	---help---
+	  This is a video4linux driver for direct (DMA) audio on
+	  Conexant 25821 based capture cards using ALSA.
+
+	  It only works with boards with function 01 enabled.
+	  To check if your board supports, use lspci -n.
+	  If supported, you should see 14f1:8801 or 14f1:8811
+	  PCI device.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called cx25821-alsa.
+
diff --git a/drivers/media/pci/cx25821/Makefile b/drivers/media/pci/cx25821/Makefile
new file mode 100644
index 0000000..5bf3ea4
--- /dev/null
+++ b/drivers/media/pci/cx25821/Makefile
@@ -0,0 +1,13 @@
+cx25821-y   := cx25821-core.o cx25821-cards.o cx25821-i2c.o \
+		       cx25821-gpio.o cx25821-medusa-video.o \
+		       cx25821-video.o cx25821-video-upstream.o \
+		       cx25821-video-upstream-ch2.o \
+		       cx25821-audio-upstream.o
+
+obj-$(CONFIG_VIDEO_CX25821) += cx25821.o
+obj-$(CONFIG_VIDEO_CX25821_ALSA) += cx25821-alsa.o
+
+ccflags-y += -Idrivers/media/i2c
+ccflags-y += -Idrivers/media/tuners
+ccflags-y += -Idrivers/media/dvb-core
+ccflags-y += -Idrivers/media/dvb-frontends
diff --git a/drivers/media/pci/cx25821/cx25821-alsa.c b/drivers/media/pci/cx25821/cx25821-alsa.c
new file mode 100644
index 0000000..1858a45
--- /dev/null
+++ b/drivers/media/pci/cx25821/cx25821-alsa.c
@@ -0,0 +1,784 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ *	Based on SAA713x ALSA driver and CX88 driver
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, version 2
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/vmalloc.h>
+#include <linux/dma-mapping.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+
+#include <linux/delay.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/control.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+
+#include "cx25821.h"
+#include "cx25821-reg.h"
+
+#define AUDIO_SRAM_CHANNEL	SRAM_CH08
+
+#define dprintk(level, fmt, arg...)				\
+do {								\
+	if (debug >= level)					\
+		pr_info("%s/1: " fmt, chip->dev->name, ##arg);	\
+} while (0)
+#define dprintk_core(level, fmt, arg...)				\
+do {									\
+	if (debug >= level)						\
+		printk(KERN_DEBUG "%s/1: " fmt, chip->dev->name, ##arg); \
+} while (0)
+
+/****************************************************************************
+	Data type declarations - Can be moded to a header file later
+ ****************************************************************************/
+
+static struct snd_card *snd_cx25821_cards[SNDRV_CARDS];
+static int devno;
+
+struct cx25821_audio_buffer {
+	unsigned int bpl;
+	struct btcx_riscmem risc;
+	struct videobuf_dmabuf dma;
+};
+
+struct cx25821_audio_dev {
+	struct cx25821_dev *dev;
+	struct cx25821_dmaqueue q;
+
+	/* pci i/o */
+	struct pci_dev *pci;
+
+	/* audio controls */
+	int irq;
+
+	struct snd_card *card;
+
+	unsigned long iobase;
+	spinlock_t reg_lock;
+	atomic_t count;
+
+	unsigned int dma_size;
+	unsigned int period_size;
+	unsigned int num_periods;
+
+	struct videobuf_dmabuf *dma_risc;
+
+	struct cx25821_audio_buffer *buf;
+
+	struct snd_pcm_substream *substream;
+};
+
+
+/****************************************************************************
+			Module global static vars
+ ****************************************************************************/
+
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
+static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
+static bool enable[SNDRV_CARDS] = { 1, [1 ... (SNDRV_CARDS - 1)] = 1 };
+
+module_param_array(enable, bool, NULL, 0444);
+MODULE_PARM_DESC(enable, "Enable cx25821 soundcard. default enabled.");
+
+module_param_array(index, int, NULL, 0444);
+MODULE_PARM_DESC(index, "Index value for cx25821 capture interface(s).");
+
+/****************************************************************************
+				Module macros
+ ****************************************************************************/
+
+MODULE_DESCRIPTION("ALSA driver module for cx25821 based capture cards");
+MODULE_AUTHOR("Hiep Huynh");
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("{{Conexant,25821}");	/* "{{Conexant,23881}," */
+
+static unsigned int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "enable debug messages");
+
+/****************************************************************************
+			Module specific funtions
+ ****************************************************************************/
+/* Constants taken from cx88-reg.h */
+#define AUD_INT_DN_RISCI1       (1 <<  0)
+#define AUD_INT_UP_RISCI1       (1 <<  1)
+#define AUD_INT_RDS_DN_RISCI1   (1 <<  2)
+#define AUD_INT_DN_RISCI2       (1 <<  4)	/* yes, 3 is skipped */
+#define AUD_INT_UP_RISCI2       (1 <<  5)
+#define AUD_INT_RDS_DN_RISCI2   (1 <<  6)
+#define AUD_INT_DN_SYNC         (1 << 12)
+#define AUD_INT_UP_SYNC         (1 << 13)
+#define AUD_INT_RDS_DN_SYNC     (1 << 14)
+#define AUD_INT_OPC_ERR         (1 << 16)
+#define AUD_INT_BER_IRQ         (1 << 20)
+#define AUD_INT_MCHG_IRQ        (1 << 21)
+#define GP_COUNT_CONTROL_RESET	0x3
+
+#define PCI_MSK_AUD_EXT   (1 <<  4)
+#define PCI_MSK_AUD_INT   (1 <<  3)
+/*
+ * BOARD Specific: Sets audio DMA
+ */
+
+static int _cx25821_start_audio_dma(struct cx25821_audio_dev *chip)
+{
+	struct cx25821_audio_buffer *buf = chip->buf;
+	struct cx25821_dev *dev = chip->dev;
+	struct sram_channel *audio_ch =
+	    &cx25821_sram_channels[AUDIO_SRAM_CHANNEL];
+	u32 tmp = 0;
+
+	/* enable output on the GPIO 0 for the MCLK ADC (Audio) */
+	cx25821_set_gpiopin_direction(chip->dev, 0, 0);
+
+	/* Make sure RISC/FIFO are off before changing FIFO/RISC settings */
+	cx_clear(AUD_INT_DMA_CTL,
+		 FLD_AUD_DST_A_RISC_EN | FLD_AUD_DST_A_FIFO_EN);
+
+	/* setup fifo + format - out channel */
+	cx25821_sram_channel_setup_audio(chip->dev, audio_ch, buf->bpl,
+					 buf->risc.dma);
+
+	/* sets bpl size */
+	cx_write(AUD_A_LNGTH, buf->bpl);
+
+	/* reset counter */
+	/* GP_COUNT_CONTROL_RESET = 0x3 */
+	cx_write(AUD_A_GPCNT_CTL, GP_COUNT_CONTROL_RESET);
+	atomic_set(&chip->count, 0);
+
+	/* Set the input mode to 16-bit */
+	tmp = cx_read(AUD_A_CFG);
+	cx_write(AUD_A_CFG, tmp | FLD_AUD_DST_PK_MODE | FLD_AUD_DST_ENABLE |
+		 FLD_AUD_CLK_ENABLE);
+
+	/*
+	pr_info("DEBUG: Start audio DMA, %d B/line, cmds_start(0x%x)= %d lines/FIFO, %d periods, %d byte buffer\n",
+		buf->bpl, audio_ch->cmds_start,
+		cx_read(audio_ch->cmds_start + 12)>>1,
+		chip->num_periods, buf->bpl * chip->num_periods);
+	*/
+
+	/* Enables corresponding bits at AUD_INT_STAT */
+	cx_write(AUD_A_INT_MSK, FLD_AUD_DST_RISCI1 | FLD_AUD_DST_OF |
+		 FLD_AUD_DST_SYNC | FLD_AUD_DST_OPC_ERR);
+
+	/* Clean any pending interrupt bits already set */
+	cx_write(AUD_A_INT_STAT, ~0);
+
+	/* enable audio irqs */
+	cx_set(PCI_INT_MSK, chip->dev->pci_irqmask | PCI_MSK_AUD_INT);
+
+	/* Turn on audio downstream fifo and risc enable 0x101 */
+	tmp = cx_read(AUD_INT_DMA_CTL);
+	cx_set(AUD_INT_DMA_CTL, tmp |
+	       (FLD_AUD_DST_A_RISC_EN | FLD_AUD_DST_A_FIFO_EN));
+
+	mdelay(100);
+	return 0;
+}
+
+/*
+ * BOARD Specific: Resets audio DMA
+ */
+static int _cx25821_stop_audio_dma(struct cx25821_audio_dev *chip)
+{
+	struct cx25821_dev *dev = chip->dev;
+
+	/* stop dma */
+	cx_clear(AUD_INT_DMA_CTL,
+		 FLD_AUD_DST_A_RISC_EN | FLD_AUD_DST_A_FIFO_EN);
+
+	/* disable irqs */
+	cx_clear(PCI_INT_MSK, PCI_MSK_AUD_INT);
+	cx_clear(AUD_A_INT_MSK, AUD_INT_OPC_ERR | AUD_INT_DN_SYNC |
+		 AUD_INT_DN_RISCI2 | AUD_INT_DN_RISCI1);
+
+	return 0;
+}
+
+#define MAX_IRQ_LOOP 50
+
+/*
+ * BOARD Specific: IRQ dma bits
+ */
+static char *cx25821_aud_irqs[32] = {
+	"dn_risci1", "up_risci1", "rds_dn_risc1",	/* 0-2 */
+	NULL,						/* reserved */
+	"dn_risci2", "up_risci2", "rds_dn_risc2",	/* 4-6 */
+	NULL,						/* reserved */
+	"dnf_of", "upf_uf", "rds_dnf_uf",		/* 8-10 */
+	NULL,						/* reserved */
+	"dn_sync", "up_sync", "rds_dn_sync",		/* 12-14 */
+	NULL,						/* reserved */
+	"opc_err", "par_err", "rip_err",		/* 16-18 */
+	"pci_abort", "ber_irq", "mchg_irq"		/* 19-21 */
+};
+
+/*
+ * BOARD Specific: Threats IRQ audio specific calls
+ */
+static void cx25821_aud_irq(struct cx25821_audio_dev *chip, u32 status,
+			    u32 mask)
+{
+	struct cx25821_dev *dev = chip->dev;
+
+	if (0 == (status & mask))
+		return;
+
+	cx_write(AUD_A_INT_STAT, status);
+	if (debug > 1 || (status & mask & ~0xff))
+		cx25821_print_irqbits(dev->name, "irq aud", cx25821_aud_irqs,
+				ARRAY_SIZE(cx25821_aud_irqs), status, mask);
+
+	/* risc op code error */
+	if (status & AUD_INT_OPC_ERR) {
+		pr_warn("WARNING %s/1: Audio risc op code error\n", dev->name);
+
+		cx_clear(AUD_INT_DMA_CTL,
+			 FLD_AUD_DST_A_RISC_EN | FLD_AUD_DST_A_FIFO_EN);
+		cx25821_sram_channel_dump_audio(dev,
+				&cx25821_sram_channels[AUDIO_SRAM_CHANNEL]);
+	}
+	if (status & AUD_INT_DN_SYNC) {
+		pr_warn("WARNING %s: Downstream sync error!\n", dev->name);
+		cx_write(AUD_A_GPCNT_CTL, GP_COUNT_CONTROL_RESET);
+		return;
+	}
+
+	/* risc1 downstream */
+	if (status & AUD_INT_DN_RISCI1) {
+		atomic_set(&chip->count, cx_read(AUD_A_GPCNT));
+		snd_pcm_period_elapsed(chip->substream);
+	}
+}
+
+/*
+ * BOARD Specific: Handles IRQ calls
+ */
+static irqreturn_t cx25821_irq(int irq, void *dev_id)
+{
+	struct cx25821_audio_dev *chip = dev_id;
+	struct cx25821_dev *dev = chip->dev;
+	u32 status, pci_status;
+	u32 audint_status, audint_mask;
+	int loop, handled = 0;
+
+	audint_status = cx_read(AUD_A_INT_STAT);
+	audint_mask = cx_read(AUD_A_INT_MSK);
+	status = cx_read(PCI_INT_STAT);
+
+	for (loop = 0; loop < 1; loop++) {
+		status = cx_read(PCI_INT_STAT);
+		if (0 == status) {
+			status = cx_read(PCI_INT_STAT);
+			audint_status = cx_read(AUD_A_INT_STAT);
+			audint_mask = cx_read(AUD_A_INT_MSK);
+
+			if (status) {
+				handled = 1;
+				cx_write(PCI_INT_STAT, status);
+
+				cx25821_aud_irq(chip, audint_status,
+						audint_mask);
+				break;
+			} else {
+				goto out;
+			}
+		}
+
+		handled = 1;
+		cx_write(PCI_INT_STAT, status);
+
+		cx25821_aud_irq(chip, audint_status, audint_mask);
+	}
+
+	pci_status = cx_read(PCI_INT_STAT);
+
+	if (handled)
+		cx_write(PCI_INT_STAT, pci_status);
+
+out:
+	return IRQ_RETVAL(handled);
+}
+
+static int dsp_buffer_free(struct cx25821_audio_dev *chip)
+{
+	BUG_ON(!chip->dma_size);
+
+	dprintk(2, "Freeing buffer\n");
+	videobuf_dma_unmap(&chip->pci->dev, chip->dma_risc);
+	videobuf_dma_free(chip->dma_risc);
+	btcx_riscmem_free(chip->pci, &chip->buf->risc);
+	kfree(chip->buf);
+
+	chip->dma_risc = NULL;
+	chip->dma_size = 0;
+
+	return 0;
+}
+
+/****************************************************************************
+				ALSA PCM Interface
+ ****************************************************************************/
+
+/*
+ * Digital hardware definition
+ */
+#define DEFAULT_FIFO_SIZE	384
+static struct snd_pcm_hardware snd_cx25821_digital_hw = {
+	.info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
+		SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID,
+	.formats = SNDRV_PCM_FMTBIT_S16_LE,
+
+	.rates = SNDRV_PCM_RATE_48000,
+	.rate_min = 48000,
+	.rate_max = 48000,
+	.channels_min = 2,
+	.channels_max = 2,
+	/* Analog audio output will be full of clicks and pops if there
+	   are not exactly four lines in the SRAM FIFO buffer.  */
+	.period_bytes_min = DEFAULT_FIFO_SIZE / 3,
+	.period_bytes_max = DEFAULT_FIFO_SIZE / 3,
+	.periods_min = 1,
+	.periods_max = AUDIO_LINE_SIZE,
+	/* 128 * 128 = 16384 = 1024 * 16 */
+	.buffer_bytes_max = (AUDIO_LINE_SIZE * AUDIO_LINE_SIZE),
+};
+
+/*
+ * audio pcm capture open callback
+ */
+static int snd_cx25821_pcm_open(struct snd_pcm_substream *substream)
+{
+	struct cx25821_audio_dev *chip = snd_pcm_substream_chip(substream);
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	int err;
+	unsigned int bpl = 0;
+
+	if (!chip) {
+		pr_err("DEBUG: cx25821 can't find device struct. Can't proceed with open\n");
+		return -ENODEV;
+	}
+
+	err = snd_pcm_hw_constraint_pow2(runtime, 0,
+					 SNDRV_PCM_HW_PARAM_PERIODS);
+	if (err < 0)
+		goto _error;
+
+	chip->substream = substream;
+
+	runtime->hw = snd_cx25821_digital_hw;
+
+	if (cx25821_sram_channels[AUDIO_SRAM_CHANNEL].fifo_size !=
+	    DEFAULT_FIFO_SIZE) {
+		/* since there are 3 audio Clusters */
+		bpl = cx25821_sram_channels[AUDIO_SRAM_CHANNEL].fifo_size / 3;
+		bpl &= ~7;	/* must be multiple of 8 */
+
+		if (bpl > AUDIO_LINE_SIZE)
+			bpl = AUDIO_LINE_SIZE;
+
+		runtime->hw.period_bytes_min = bpl;
+		runtime->hw.period_bytes_max = bpl;
+	}
+
+	return 0;
+_error:
+	dprintk(1, "Error opening PCM!\n");
+	return err;
+}
+
+/*
+ * audio close callback
+ */
+static int snd_cx25821_close(struct snd_pcm_substream *substream)
+{
+	return 0;
+}
+
+/*
+ * hw_params callback
+ */
+static int snd_cx25821_hw_params(struct snd_pcm_substream *substream,
+				 struct snd_pcm_hw_params *hw_params)
+{
+	struct cx25821_audio_dev *chip = snd_pcm_substream_chip(substream);
+	struct videobuf_dmabuf *dma;
+
+	struct cx25821_audio_buffer *buf;
+	int ret;
+
+	if (substream->runtime->dma_area) {
+		dsp_buffer_free(chip);
+		substream->runtime->dma_area = NULL;
+	}
+
+	chip->period_size = params_period_bytes(hw_params);
+	chip->num_periods = params_periods(hw_params);
+	chip->dma_size = chip->period_size * params_periods(hw_params);
+
+	BUG_ON(!chip->dma_size);
+	BUG_ON(chip->num_periods & (chip->num_periods - 1));
+
+	buf = kzalloc(sizeof(*buf), GFP_KERNEL);
+	if (NULL == buf)
+		return -ENOMEM;
+
+	if (chip->period_size > AUDIO_LINE_SIZE)
+		chip->period_size = AUDIO_LINE_SIZE;
+
+	buf->bpl = chip->period_size;
+
+	dma = &buf->dma;
+	videobuf_dma_init(dma);
+	ret = videobuf_dma_init_kernel(dma, PCI_DMA_FROMDEVICE,
+			(PAGE_ALIGN(chip->dma_size) >> PAGE_SHIFT));
+	if (ret < 0)
+		goto error;
+
+	ret = videobuf_dma_map(&chip->pci->dev, dma);
+	if (ret < 0)
+		goto error;
+
+	ret = cx25821_risc_databuffer_audio(chip->pci, &buf->risc, dma->sglist,
+			chip->period_size, chip->num_periods, 1);
+	if (ret < 0) {
+		pr_info("DEBUG: ERROR after cx25821_risc_databuffer_audio()\n");
+		goto error;
+	}
+
+	/* Loop back to start of program */
+	buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+	buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+	buf->risc.jmp[2] = cpu_to_le32(0);	/* bits 63-32 */
+
+	chip->buf = buf;
+	chip->dma_risc = dma;
+
+	substream->runtime->dma_area = chip->dma_risc->vaddr;
+	substream->runtime->dma_bytes = chip->dma_size;
+	substream->runtime->dma_addr = 0;
+
+	return 0;
+
+error:
+	kfree(buf);
+	return ret;
+}
+
+/*
+ * hw free callback
+ */
+static int snd_cx25821_hw_free(struct snd_pcm_substream *substream)
+{
+	struct cx25821_audio_dev *chip = snd_pcm_substream_chip(substream);
+
+	if (substream->runtime->dma_area) {
+		dsp_buffer_free(chip);
+		substream->runtime->dma_area = NULL;
+	}
+
+	return 0;
+}
+
+/*
+ * prepare callback
+ */
+static int snd_cx25821_prepare(struct snd_pcm_substream *substream)
+{
+	return 0;
+}
+
+/*
+ * trigger callback
+ */
+static int snd_cx25821_card_trigger(struct snd_pcm_substream *substream,
+				    int cmd)
+{
+	struct cx25821_audio_dev *chip = snd_pcm_substream_chip(substream);
+	int err = 0;
+
+	/* Local interrupts are already disabled by ALSA */
+	spin_lock(&chip->reg_lock);
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+		err = _cx25821_start_audio_dma(chip);
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+		err = _cx25821_stop_audio_dma(chip);
+		break;
+	default:
+		err = -EINVAL;
+		break;
+	}
+
+	spin_unlock(&chip->reg_lock);
+
+	return err;
+}
+
+/*
+ * pointer callback
+ */
+static snd_pcm_uframes_t snd_cx25821_pointer(struct snd_pcm_substream
+					     *substream)
+{
+	struct cx25821_audio_dev *chip = snd_pcm_substream_chip(substream);
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	u16 count;
+
+	count = atomic_read(&chip->count);
+
+	return runtime->period_size * (count & (runtime->periods - 1));
+}
+
+/*
+ * page callback (needed for mmap)
+ */
+static struct page *snd_cx25821_page(struct snd_pcm_substream *substream,
+				     unsigned long offset)
+{
+	void *pageptr = substream->runtime->dma_area + offset;
+
+	return vmalloc_to_page(pageptr);
+}
+
+/*
+ * operators
+ */
+static struct snd_pcm_ops snd_cx25821_pcm_ops = {
+	.open = snd_cx25821_pcm_open,
+	.close = snd_cx25821_close,
+	.ioctl = snd_pcm_lib_ioctl,
+	.hw_params = snd_cx25821_hw_params,
+	.hw_free = snd_cx25821_hw_free,
+	.prepare = snd_cx25821_prepare,
+	.trigger = snd_cx25821_card_trigger,
+	.pointer = snd_cx25821_pointer,
+	.page = snd_cx25821_page,
+};
+
+/*
+ * ALSA create a PCM device:  Called when initializing the board.
+ * Sets up the name and hooks up the callbacks
+ */
+static int snd_cx25821_pcm(struct cx25821_audio_dev *chip, int device,
+			   char *name)
+{
+	struct snd_pcm *pcm;
+	int err;
+
+	err = snd_pcm_new(chip->card, name, device, 0, 1, &pcm);
+	if (err < 0) {
+		pr_info("ERROR: FAILED snd_pcm_new() in %s\n", __func__);
+		return err;
+	}
+	pcm->private_data = chip;
+	pcm->info_flags = 0;
+	strcpy(pcm->name, name);
+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cx25821_pcm_ops);
+
+	return 0;
+}
+
+/****************************************************************************
+			Basic Flow for Sound Devices
+ ****************************************************************************/
+
+/*
+ * PCI ID Table - 14f1:8801 and 14f1:8811 means function 1: Audio
+ * Only boards with eeprom and byte 1 at eeprom=1 have it
+ */
+
+static DEFINE_PCI_DEVICE_TABLE(cx25821_audio_pci_tbl) = {
+	{0x14f1, 0x0920, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{0,}
+};
+
+MODULE_DEVICE_TABLE(pci, cx25821_audio_pci_tbl);
+
+/*
+ * Not used in the function snd_cx25821_dev_free so removing
+ * from the file.
+ */
+/*
+static int snd_cx25821_free(struct cx25821_audio_dev *chip)
+{
+	if (chip->irq >= 0)
+		free_irq(chip->irq, chip);
+
+	cx25821_dev_unregister(chip->dev);
+	pci_disable_device(chip->pci);
+
+	return 0;
+}
+*/
+
+/*
+ * Component Destructor
+ */
+static void snd_cx25821_dev_free(struct snd_card *card)
+{
+	struct cx25821_audio_dev *chip = card->private_data;
+
+	/* snd_cx25821_free(chip); */
+	snd_card_free(chip->card);
+}
+
+/*
+ * Alsa Constructor - Component probe
+ */
+static int cx25821_audio_initdev(struct cx25821_dev *dev)
+{
+	struct snd_card *card;
+	struct cx25821_audio_dev *chip;
+	int err;
+
+	if (devno >= SNDRV_CARDS) {
+		pr_info("DEBUG ERROR: devno >= SNDRV_CARDS %s\n", __func__);
+		return -ENODEV;
+	}
+
+	if (!enable[devno]) {
+		++devno;
+		pr_info("DEBUG ERROR: !enable[devno] %s\n", __func__);
+		return -ENOENT;
+	}
+
+	err = snd_card_create(index[devno], id[devno], THIS_MODULE,
+			sizeof(struct cx25821_audio_dev), &card);
+	if (err < 0) {
+		pr_info("DEBUG ERROR: cannot create snd_card_new in %s\n",
+			__func__);
+		return err;
+	}
+
+	strcpy(card->driver, "cx25821");
+
+	/* Card "creation" */
+	card->private_free = snd_cx25821_dev_free;
+	chip = card->private_data;
+	spin_lock_init(&chip->reg_lock);
+
+	chip->dev = dev;
+	chip->card = card;
+	chip->pci = dev->pci;
+	chip->iobase = pci_resource_start(dev->pci, 0);
+
+	chip->irq = dev->pci->irq;
+
+	err = request_irq(dev->pci->irq, cx25821_irq,
+			  IRQF_SHARED, chip->dev->name, chip);
+
+	if (err < 0) {
+		pr_err("ERROR %s: can't get IRQ %d for ALSA\n", chip->dev->name,
+			dev->pci->irq);
+		goto error;
+	}
+
+	err = snd_cx25821_pcm(chip, 0, "cx25821 Digital");
+	if (err < 0) {
+		pr_info("DEBUG ERROR: cannot create snd_cx25821_pcm %s\n",
+			__func__);
+		goto error;
+	}
+
+	snd_card_set_dev(card, &chip->pci->dev);
+
+	strcpy(card->shortname, "cx25821");
+	sprintf(card->longname, "%s at 0x%lx irq %d", chip->dev->name,
+		chip->iobase, chip->irq);
+	strcpy(card->mixername, "CX25821");
+
+	pr_info("%s/%i: ALSA support for cx25821 boards\n", card->driver,
+		devno);
+
+	err = snd_card_register(card);
+	if (err < 0) {
+		pr_info("DEBUG ERROR: cannot register sound card %s\n",
+			__func__);
+		goto error;
+	}
+
+	snd_cx25821_cards[devno] = card;
+
+	devno++;
+	return 0;
+
+error:
+	snd_card_free(card);
+	return err;
+}
+
+/****************************************************************************
+				LINUX MODULE INIT
+ ****************************************************************************/
+static void cx25821_audio_fini(void)
+{
+	snd_card_free(snd_cx25821_cards[0]);
+}
+
+/*
+ * Module initializer
+ *
+ * Loops through present saa7134 cards, and assigns an ALSA device
+ * to each one
+ *
+ */
+static int cx25821_alsa_init(void)
+{
+	struct cx25821_dev *dev = NULL;
+	struct list_head *list;
+
+	mutex_lock(&cx25821_devlist_mutex);
+	list_for_each(list, &cx25821_devlist) {
+		dev = list_entry(list, struct cx25821_dev, devlist);
+		cx25821_audio_initdev(dev);
+	}
+	mutex_unlock(&cx25821_devlist_mutex);
+
+	if (dev == NULL)
+		pr_info("ERROR ALSA: no cx25821 cards found\n");
+
+	return 0;
+
+}
+
+late_initcall(cx25821_alsa_init);
+module_exit(cx25821_audio_fini);
+
+/* ----------------------------------------------------------- */
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/pci/cx25821/cx25821-audio-upstream.c b/drivers/media/pci/cx25821/cx25821-audio-upstream.c
new file mode 100644
index 0000000..8b2a999
--- /dev/null
+++ b/drivers/media/pci/cx25821/cx25821-audio-upstream.c
@@ -0,0 +1,778 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <hiep.huynh@conexant.com>, <shu.lin@conexant.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include "cx25821-video.h"
+#include "cx25821-audio-upstream.h"
+
+#include <linux/fs.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/syscalls.h>
+#include <linux/file.h>
+#include <linux/fcntl.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+
+MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards");
+MODULE_AUTHOR("Hiep Huynh <hiep.huynh@conexant.com>");
+MODULE_LICENSE("GPL");
+
+static int _intr_msk = FLD_AUD_SRC_RISCI1 | FLD_AUD_SRC_OF |
+			FLD_AUD_SRC_SYNC | FLD_AUD_SRC_OPC_ERR;
+
+int cx25821_sram_channel_setup_upstream_audio(struct cx25821_dev *dev,
+					      struct sram_channel *ch,
+					      unsigned int bpl, u32 risc)
+{
+	unsigned int i, lines;
+	u32 cdt;
+
+	if (ch->cmds_start == 0) {
+		cx_write(ch->ptr1_reg, 0);
+		cx_write(ch->ptr2_reg, 0);
+		cx_write(ch->cnt2_reg, 0);
+		cx_write(ch->cnt1_reg, 0);
+		return 0;
+	}
+
+	bpl = (bpl + 7) & ~7;	/* alignment */
+	cdt = ch->cdt;
+	lines = ch->fifo_size / bpl;
+
+	if (lines > 3)
+		lines = 3;
+
+	BUG_ON(lines < 2);
+
+	/* write CDT */
+	for (i = 0; i < lines; i++) {
+		cx_write(cdt + 16 * i, ch->fifo_start + bpl * i);
+		cx_write(cdt + 16 * i + 4, 0);
+		cx_write(cdt + 16 * i + 8, 0);
+		cx_write(cdt + 16 * i + 12, 0);
+	}
+
+	/* write CMDS */
+	cx_write(ch->cmds_start + 0, risc);
+
+	cx_write(ch->cmds_start + 4, 0);
+	cx_write(ch->cmds_start + 8, cdt);
+	cx_write(ch->cmds_start + 12, AUDIO_CDT_SIZE_QW);
+	cx_write(ch->cmds_start + 16, ch->ctrl_start);
+
+	/* IQ size */
+	cx_write(ch->cmds_start + 20, AUDIO_IQ_SIZE_DW);
+
+	for (i = 24; i < 80; i += 4)
+		cx_write(ch->cmds_start + i, 0);
+
+	/* fill registers */
+	cx_write(ch->ptr1_reg, ch->fifo_start);
+	cx_write(ch->ptr2_reg, cdt);
+	cx_write(ch->cnt2_reg, AUDIO_CDT_SIZE_QW);
+	cx_write(ch->cnt1_reg, AUDIO_CLUSTER_SIZE_QW - 1);
+
+	return 0;
+}
+
+static __le32 *cx25821_risc_field_upstream_audio(struct cx25821_dev *dev,
+						 __le32 *rp,
+						 dma_addr_t databuf_phys_addr,
+						 unsigned int bpl,
+						 int fifo_enable)
+{
+	unsigned int line;
+	struct sram_channel *sram_ch =
+		dev->channels[dev->_audio_upstream_channel].sram_channels;
+	int offset = 0;
+
+	/* scan lines */
+	for (line = 0; line < LINES_PER_AUDIO_BUFFER; line++) {
+		*(rp++) = cpu_to_le32(RISC_READ | RISC_SOL | RISC_EOL | bpl);
+		*(rp++) = cpu_to_le32(databuf_phys_addr + offset);
+		*(rp++) = cpu_to_le32(0);	/* bits 63-32 */
+
+		/* Check if we need to enable the FIFO
+		 * after the first 3 lines.
+		 * For the upstream audio channel,
+		 * the risc engine will enable the FIFO */
+		if (fifo_enable && line == 2) {
+			*(rp++) = RISC_WRITECR;
+			*(rp++) = sram_ch->dma_ctl;
+			*(rp++) = sram_ch->fld_aud_fifo_en;
+			*(rp++) = 0x00000020;
+		}
+
+		offset += AUDIO_LINE_SIZE;
+	}
+
+	return rp;
+}
+
+int cx25821_risc_buffer_upstream_audio(struct cx25821_dev *dev,
+				       struct pci_dev *pci,
+				       unsigned int bpl, unsigned int lines)
+{
+	__le32 *rp;
+	int fifo_enable = 0;
+	int frame = 0, i = 0;
+	int frame_size = AUDIO_DATA_BUF_SZ;
+	int databuf_offset = 0;
+	int risc_flag = RISC_CNT_INC;
+	dma_addr_t risc_phys_jump_addr;
+
+	/* Virtual address of Risc buffer program */
+	rp = dev->_risc_virt_addr;
+
+	/* sync instruction */
+	*(rp++) = cpu_to_le32(RISC_RESYNC | AUDIO_SYNC_LINE);
+
+	for (frame = 0; frame < NUM_AUDIO_FRAMES; frame++) {
+		databuf_offset = frame_size * frame;
+
+		if (frame == 0) {
+			fifo_enable = 1;
+			risc_flag = RISC_CNT_RESET;
+		} else {
+			fifo_enable = 0;
+			risc_flag = RISC_CNT_INC;
+		}
+
+		/* Calculate physical jump address */
+		if ((frame + 1) == NUM_AUDIO_FRAMES) {
+			risc_phys_jump_addr =
+			    dev->_risc_phys_start_addr +
+			    RISC_SYNC_INSTRUCTION_SIZE;
+		} else {
+			risc_phys_jump_addr =
+			    dev->_risc_phys_start_addr +
+			    RISC_SYNC_INSTRUCTION_SIZE +
+			    AUDIO_RISC_DMA_BUF_SIZE * (frame + 1);
+		}
+
+		rp = cx25821_risc_field_upstream_audio(dev, rp,
+				dev->_audiodata_buf_phys_addr + databuf_offset,
+				bpl, fifo_enable);
+
+		if (USE_RISC_NOOP_AUDIO) {
+			for (i = 0; i < NUM_NO_OPS; i++)
+				*(rp++) = cpu_to_le32(RISC_NOOP);
+		}
+
+		/* Loop to (Nth)FrameRISC or to Start of Risc program &
+		 * generate IRQ */
+		*(rp++) = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | risc_flag);
+		*(rp++) = cpu_to_le32(risc_phys_jump_addr);
+		*(rp++) = cpu_to_le32(0);
+
+		/* Recalculate virtual address based on frame index */
+		rp = dev->_risc_virt_addr + RISC_SYNC_INSTRUCTION_SIZE / 4 +
+			(AUDIO_RISC_DMA_BUF_SIZE * (frame + 1) / 4);
+	}
+
+	return 0;
+}
+
+void cx25821_free_memory_audio(struct cx25821_dev *dev)
+{
+	if (dev->_risc_virt_addr) {
+		pci_free_consistent(dev->pci, dev->_audiorisc_size,
+				    dev->_risc_virt_addr, dev->_risc_phys_addr);
+		dev->_risc_virt_addr = NULL;
+	}
+
+	if (dev->_audiodata_buf_virt_addr) {
+		pci_free_consistent(dev->pci, dev->_audiodata_buf_size,
+				    dev->_audiodata_buf_virt_addr,
+				    dev->_audiodata_buf_phys_addr);
+		dev->_audiodata_buf_virt_addr = NULL;
+	}
+}
+
+void cx25821_stop_upstream_audio(struct cx25821_dev *dev)
+{
+	struct sram_channel *sram_ch =
+		dev->channels[AUDIO_UPSTREAM_SRAM_CHANNEL_B].sram_channels;
+	u32 tmp = 0;
+
+	if (!dev->_audio_is_running) {
+		printk(KERN_DEBUG
+		       pr_fmt("No audio file is currently running so return!\n"));
+		return;
+	}
+	/* Disable RISC interrupts */
+	cx_write(sram_ch->int_msk, 0);
+
+	/* Turn OFF risc and fifo enable in AUD_DMA_CNTRL */
+	tmp = cx_read(sram_ch->dma_ctl);
+	cx_write(sram_ch->dma_ctl,
+		 tmp & ~(sram_ch->fld_aud_fifo_en | sram_ch->fld_aud_risc_en));
+
+	/* Clear data buffer memory */
+	if (dev->_audiodata_buf_virt_addr)
+		memset(dev->_audiodata_buf_virt_addr, 0,
+		       dev->_audiodata_buf_size);
+
+	dev->_audio_is_running = 0;
+	dev->_is_first_audio_frame = 0;
+	dev->_audioframe_count = 0;
+	dev->_audiofile_status = END_OF_FILE;
+
+	kfree(dev->_irq_audio_queues);
+	dev->_irq_audio_queues = NULL;
+
+	kfree(dev->_audiofilename);
+}
+
+void cx25821_free_mem_upstream_audio(struct cx25821_dev *dev)
+{
+	if (dev->_audio_is_running)
+		cx25821_stop_upstream_audio(dev);
+
+	cx25821_free_memory_audio(dev);
+}
+
+int cx25821_get_audio_data(struct cx25821_dev *dev,
+			   struct sram_channel *sram_ch)
+{
+	struct file *myfile;
+	int frame_index_temp = dev->_audioframe_index;
+	int i = 0;
+	int line_size = AUDIO_LINE_SIZE;
+	int frame_size = AUDIO_DATA_BUF_SZ;
+	int frame_offset = frame_size * frame_index_temp;
+	ssize_t vfs_read_retval = 0;
+	char mybuf[line_size];
+	loff_t file_offset = dev->_audioframe_count * frame_size;
+	loff_t pos;
+	mm_segment_t old_fs;
+
+	if (dev->_audiofile_status == END_OF_FILE)
+		return 0;
+
+	myfile = filp_open(dev->_audiofilename, O_RDONLY | O_LARGEFILE, 0);
+
+	if (IS_ERR(myfile)) {
+		const int open_errno = -PTR_ERR(myfile);
+		pr_err("%s(): ERROR opening file(%s) with errno = %d!\n",
+		       __func__, dev->_audiofilename, open_errno);
+		return PTR_ERR(myfile);
+	} else {
+		if (!(myfile->f_op)) {
+			pr_err("%s(): File has no file operations registered!\n",
+				__func__);
+			filp_close(myfile, NULL);
+			return -EIO;
+		}
+
+		if (!myfile->f_op->read) {
+			pr_err("%s(): File has no READ operations registered!\n",
+				__func__);
+			filp_close(myfile, NULL);
+			return -EIO;
+		}
+
+		pos = myfile->f_pos;
+		old_fs = get_fs();
+		set_fs(KERNEL_DS);
+
+		for (i = 0; i < dev->_audio_lines_count; i++) {
+			pos = file_offset;
+
+			vfs_read_retval = vfs_read(myfile, mybuf, line_size,
+									&pos);
+
+			if (vfs_read_retval > 0 && vfs_read_retval == line_size
+			    && dev->_audiodata_buf_virt_addr != NULL) {
+				memcpy((void *)(dev->_audiodata_buf_virt_addr +
+						frame_offset / 4), mybuf,
+					vfs_read_retval);
+			}
+
+			file_offset += vfs_read_retval;
+			frame_offset += vfs_read_retval;
+
+			if (vfs_read_retval < line_size) {
+				pr_info("Done: exit %s() since no more bytes to read from Audio file\n",
+					__func__);
+				break;
+			}
+		}
+
+		if (i > 0)
+			dev->_audioframe_count++;
+
+		dev->_audiofile_status = (vfs_read_retval == line_size) ?
+						IN_PROGRESS : END_OF_FILE;
+
+		set_fs(old_fs);
+		filp_close(myfile, NULL);
+	}
+
+	return 0;
+}
+
+static void cx25821_audioups_handler(struct work_struct *work)
+{
+	struct cx25821_dev *dev = container_of(work, struct cx25821_dev,
+			_audio_work_entry);
+
+	if (!dev) {
+		pr_err("ERROR %s(): since container_of(work_struct) FAILED!\n",
+			__func__);
+		return;
+	}
+
+	cx25821_get_audio_data(dev, dev->channels[dev->_audio_upstream_channel].
+			sram_channels);
+}
+
+int cx25821_openfile_audio(struct cx25821_dev *dev,
+			   struct sram_channel *sram_ch)
+{
+	struct file *myfile;
+	int i = 0, j = 0;
+	int line_size = AUDIO_LINE_SIZE;
+	ssize_t vfs_read_retval = 0;
+	char mybuf[line_size];
+	loff_t pos;
+	loff_t offset = (unsigned long)0;
+	mm_segment_t old_fs;
+
+	myfile = filp_open(dev->_audiofilename, O_RDONLY | O_LARGEFILE, 0);
+
+	if (IS_ERR(myfile)) {
+		const int open_errno = -PTR_ERR(myfile);
+		pr_err("%s(): ERROR opening file(%s) with errno = %d!\n",
+			__func__, dev->_audiofilename, open_errno);
+		return PTR_ERR(myfile);
+	} else {
+		if (!(myfile->f_op)) {
+			pr_err("%s(): File has no file operations registered!\n",
+				__func__);
+			filp_close(myfile, NULL);
+			return -EIO;
+		}
+
+		if (!myfile->f_op->read) {
+			pr_err("%s(): File has no READ operations registered!\n",
+				__func__);
+			filp_close(myfile, NULL);
+			return -EIO;
+		}
+
+		pos = myfile->f_pos;
+		old_fs = get_fs();
+		set_fs(KERNEL_DS);
+
+		for (j = 0; j < NUM_AUDIO_FRAMES; j++) {
+			for (i = 0; i < dev->_audio_lines_count; i++) {
+				pos = offset;
+
+				vfs_read_retval = vfs_read(myfile, mybuf,
+						line_size, &pos);
+
+				if (vfs_read_retval > 0 &&
+				    vfs_read_retval == line_size &&
+				    dev->_audiodata_buf_virt_addr != NULL) {
+					memcpy((void *)(dev->
+							_audiodata_buf_virt_addr
+							+ offset / 4), mybuf,
+					       vfs_read_retval);
+				}
+
+				offset += vfs_read_retval;
+
+				if (vfs_read_retval < line_size) {
+					pr_info("Done: exit %s() since no more bytes to read from Audio file\n",
+						__func__);
+					break;
+				}
+			}
+
+			if (i > 0)
+				dev->_audioframe_count++;
+
+			if (vfs_read_retval < line_size)
+				break;
+		}
+
+		dev->_audiofile_status = (vfs_read_retval == line_size) ?
+						IN_PROGRESS : END_OF_FILE;
+
+		set_fs(old_fs);
+		myfile->f_pos = 0;
+		filp_close(myfile, NULL);
+	}
+
+	return 0;
+}
+
+static int cx25821_audio_upstream_buffer_prepare(struct cx25821_dev *dev,
+						 struct sram_channel *sram_ch,
+						 int bpl)
+{
+	int ret = 0;
+	dma_addr_t dma_addr;
+	dma_addr_t data_dma_addr;
+
+	cx25821_free_memory_audio(dev);
+
+	dev->_risc_virt_addr = pci_alloc_consistent(dev->pci,
+			dev->audio_upstream_riscbuf_size, &dma_addr);
+	dev->_risc_virt_start_addr = dev->_risc_virt_addr;
+	dev->_risc_phys_start_addr = dma_addr;
+	dev->_risc_phys_addr = dma_addr;
+	dev->_audiorisc_size = dev->audio_upstream_riscbuf_size;
+
+	if (!dev->_risc_virt_addr) {
+		printk(KERN_DEBUG
+			pr_fmt("ERROR: pci_alloc_consistent() FAILED to allocate memory for RISC program! Returning\n"));
+		return -ENOMEM;
+	}
+	/* Clear out memory at address */
+	memset(dev->_risc_virt_addr, 0, dev->_audiorisc_size);
+
+	/* For Audio Data buffer allocation */
+	dev->_audiodata_buf_virt_addr = pci_alloc_consistent(dev->pci,
+			dev->audio_upstream_databuf_size, &data_dma_addr);
+	dev->_audiodata_buf_phys_addr = data_dma_addr;
+	dev->_audiodata_buf_size = dev->audio_upstream_databuf_size;
+
+	if (!dev->_audiodata_buf_virt_addr) {
+		printk(KERN_DEBUG
+			pr_fmt("ERROR: pci_alloc_consistent() FAILED to allocate memory for data buffer! Returning\n"));
+		return -ENOMEM;
+	}
+	/* Clear out memory at address */
+	memset(dev->_audiodata_buf_virt_addr, 0, dev->_audiodata_buf_size);
+
+	ret = cx25821_openfile_audio(dev, sram_ch);
+	if (ret < 0)
+		return ret;
+
+	/* Creating RISC programs */
+	ret = cx25821_risc_buffer_upstream_audio(dev, dev->pci, bpl,
+						dev->_audio_lines_count);
+	if (ret < 0) {
+		printk(KERN_DEBUG
+			pr_fmt("ERROR creating audio upstream RISC programs!\n"));
+		goto error;
+	}
+
+	return 0;
+
+error:
+	return ret;
+}
+
+int cx25821_audio_upstream_irq(struct cx25821_dev *dev, int chan_num,
+			       u32 status)
+{
+	int i = 0;
+	u32 int_msk_tmp;
+	struct sram_channel *channel = dev->channels[chan_num].sram_channels;
+	dma_addr_t risc_phys_jump_addr;
+	__le32 *rp;
+
+	if (status & FLD_AUD_SRC_RISCI1) {
+		/* Get interrupt_index of the program that interrupted */
+		u32 prog_cnt = cx_read(channel->gpcnt);
+
+		/* Since we've identified our IRQ, clear our bits from the
+		 * interrupt mask and interrupt status registers */
+		cx_write(channel->int_msk, 0);
+		cx_write(channel->int_stat, cx_read(channel->int_stat));
+
+		spin_lock(&dev->slock);
+
+		while (prog_cnt != dev->_last_index_irq) {
+			/* Update _last_index_irq */
+			if (dev->_last_index_irq < (NUMBER_OF_PROGRAMS - 1))
+				dev->_last_index_irq++;
+			else
+				dev->_last_index_irq = 0;
+
+			dev->_audioframe_index = dev->_last_index_irq;
+
+			queue_work(dev->_irq_audio_queues,
+				   &dev->_audio_work_entry);
+		}
+
+		if (dev->_is_first_audio_frame) {
+			dev->_is_first_audio_frame = 0;
+
+			if (dev->_risc_virt_start_addr != NULL) {
+				risc_phys_jump_addr =
+					dev->_risc_phys_start_addr +
+					RISC_SYNC_INSTRUCTION_SIZE +
+					AUDIO_RISC_DMA_BUF_SIZE;
+
+				rp = cx25821_risc_field_upstream_audio(dev,
+						dev->_risc_virt_start_addr + 1,
+						dev->_audiodata_buf_phys_addr,
+						AUDIO_LINE_SIZE, FIFO_DISABLE);
+
+				if (USE_RISC_NOOP_AUDIO) {
+					for (i = 0; i < NUM_NO_OPS; i++) {
+						*(rp++) =
+						    cpu_to_le32(RISC_NOOP);
+					}
+				}
+				/* Jump to 2nd Audio Frame */
+				*(rp++) = cpu_to_le32(RISC_JUMP | RISC_IRQ1 |
+						RISC_CNT_RESET);
+				*(rp++) = cpu_to_le32(risc_phys_jump_addr);
+				*(rp++) = cpu_to_le32(0);
+			}
+		}
+
+		spin_unlock(&dev->slock);
+	} else {
+		if (status & FLD_AUD_SRC_OF)
+			pr_warn("%s(): Audio Received Overflow Error Interrupt!\n",
+				__func__);
+
+		if (status & FLD_AUD_SRC_SYNC)
+			pr_warn("%s(): Audio Received Sync Error Interrupt!\n",
+				__func__);
+
+		if (status & FLD_AUD_SRC_OPC_ERR)
+			pr_warn("%s(): Audio Received OpCode Error Interrupt!\n",
+				__func__);
+
+		/* Read and write back the interrupt status register to clear
+		 * our bits */
+		cx_write(channel->int_stat, cx_read(channel->int_stat));
+	}
+
+	if (dev->_audiofile_status == END_OF_FILE) {
+		pr_warn("EOF Channel Audio Framecount = %d\n",
+			dev->_audioframe_count);
+		return -1;
+	}
+	/* ElSE, set the interrupt mask register, re-enable irq. */
+	int_msk_tmp = cx_read(channel->int_msk);
+	cx_write(channel->int_msk, int_msk_tmp |= _intr_msk);
+
+	return 0;
+}
+
+static irqreturn_t cx25821_upstream_irq_audio(int irq, void *dev_id)
+{
+	struct cx25821_dev *dev = dev_id;
+	u32 audio_status;
+	int handled = 0;
+	struct sram_channel *sram_ch;
+
+	if (!dev)
+		return -1;
+
+	sram_ch = dev->channels[dev->_audio_upstream_channel].sram_channels;
+
+	audio_status = cx_read(sram_ch->int_stat);
+
+	/* Only deal with our interrupt */
+	if (audio_status) {
+		handled = cx25821_audio_upstream_irq(dev,
+				dev->_audio_upstream_channel, audio_status);
+	}
+
+	if (handled < 0)
+		cx25821_stop_upstream_audio(dev);
+	else
+		handled += handled;
+
+	return IRQ_RETVAL(handled);
+}
+
+static void cx25821_wait_fifo_enable(struct cx25821_dev *dev,
+				     struct sram_channel *sram_ch)
+{
+	int count = 0;
+	u32 tmp;
+
+	do {
+		/* Wait 10 microsecond before checking to see if the FIFO is
+		 * turned ON. */
+		udelay(10);
+
+		tmp = cx_read(sram_ch->dma_ctl);
+
+		/* 10 millisecond timeout */
+		if (count++ > 1000) {
+			pr_err("ERROR: %s() fifo is NOT turned on. Timeout!\n",
+				__func__);
+			return;
+		}
+
+	} while (!(tmp & sram_ch->fld_aud_fifo_en));
+
+}
+
+int cx25821_start_audio_dma_upstream(struct cx25821_dev *dev,
+				     struct sram_channel *sram_ch)
+{
+	u32 tmp = 0;
+	int err = 0;
+
+	/* Set the physical start address of the RISC program in the initial
+	 * program counter(IPC) member of the CMDS. */
+	cx_write(sram_ch->cmds_start + 0, dev->_risc_phys_addr);
+	/* Risc IPC High 64 bits 63-32 */
+	cx_write(sram_ch->cmds_start + 4, 0);
+
+	/* reset counter */
+	cx_write(sram_ch->gpcnt_ctl, 3);
+
+	/* Set the line length       (It looks like we do not need to set the
+	 * line length) */
+	cx_write(sram_ch->aud_length, AUDIO_LINE_SIZE & FLD_AUD_DST_LN_LNGTH);
+
+	/* Set the input mode to 16-bit */
+	tmp = cx_read(sram_ch->aud_cfg);
+	tmp |= FLD_AUD_SRC_ENABLE | FLD_AUD_DST_PK_MODE | FLD_AUD_CLK_ENABLE |
+		FLD_AUD_MASTER_MODE | FLD_AUD_CLK_SELECT_PLL_D |
+		FLD_AUD_SONY_MODE;
+	cx_write(sram_ch->aud_cfg, tmp);
+
+	/* Read and write back the interrupt status register to clear it */
+	tmp = cx_read(sram_ch->int_stat);
+	cx_write(sram_ch->int_stat, tmp);
+
+	/* Clear our bits from the interrupt status register. */
+	cx_write(sram_ch->int_stat, _intr_msk);
+
+	/* Set the interrupt mask register, enable irq. */
+	cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | (1 << sram_ch->irq_bit));
+	tmp = cx_read(sram_ch->int_msk);
+	cx_write(sram_ch->int_msk, tmp |= _intr_msk);
+
+	err = request_irq(dev->pci->irq, cx25821_upstream_irq_audio,
+			IRQF_SHARED, dev->name, dev);
+	if (err < 0) {
+		pr_err("%s: can't get upstream IRQ %d\n", dev->name,
+				dev->pci->irq);
+		goto fail_irq;
+	}
+
+	/* Start the DMA  engine */
+	tmp = cx_read(sram_ch->dma_ctl);
+	cx_set(sram_ch->dma_ctl, tmp | sram_ch->fld_aud_risc_en);
+
+	dev->_audio_is_running = 1;
+	dev->_is_first_audio_frame = 1;
+
+	/* The fifo_en bit turns on by the first Risc program */
+	cx25821_wait_fifo_enable(dev, sram_ch);
+
+	return 0;
+
+fail_irq:
+	cx25821_dev_unregister(dev);
+	return err;
+}
+
+int cx25821_audio_upstream_init(struct cx25821_dev *dev, int channel_select)
+{
+	struct sram_channel *sram_ch;
+	int retval = 0;
+	int err = 0;
+	int str_length = 0;
+
+	if (dev->_audio_is_running) {
+		pr_warn("Audio Channel is still running so return!\n");
+		return 0;
+	}
+
+	dev->_audio_upstream_channel = channel_select;
+	sram_ch = dev->channels[channel_select].sram_channels;
+
+	/* Work queue */
+	INIT_WORK(&dev->_audio_work_entry, cx25821_audioups_handler);
+	dev->_irq_audio_queues =
+	    create_singlethread_workqueue("cx25821_audioworkqueue");
+
+	if (!dev->_irq_audio_queues) {
+		printk(KERN_DEBUG
+			pr_fmt("ERROR: create_singlethread_workqueue() for Audio FAILED!\n"));
+		return -ENOMEM;
+	}
+
+	dev->_last_index_irq = 0;
+	dev->_audio_is_running = 0;
+	dev->_audioframe_count = 0;
+	dev->_audiofile_status = RESET_STATUS;
+	dev->_audio_lines_count = LINES_PER_AUDIO_BUFFER;
+	_line_size = AUDIO_LINE_SIZE;
+
+	if (dev->input_audiofilename) {
+		str_length = strlen(dev->input_audiofilename);
+		dev->_audiofilename = kmemdup(dev->input_audiofilename,
+					      str_length + 1, GFP_KERNEL);
+
+		if (!dev->_audiofilename)
+			goto error;
+
+		/* Default if filename is empty string */
+		if (strcmp(dev->input_audiofilename, "") == 0)
+			dev->_audiofilename = "/root/audioGOOD.wav";
+	} else {
+		str_length = strlen(_defaultAudioName);
+		dev->_audiofilename = kmemdup(_defaultAudioName,
+					      str_length + 1, GFP_KERNEL);
+
+		if (!dev->_audiofilename)
+			goto error;
+	}
+
+	retval = cx25821_sram_channel_setup_upstream_audio(dev, sram_ch,
+							_line_size, 0);
+
+	dev->audio_upstream_riscbuf_size =
+		AUDIO_RISC_DMA_BUF_SIZE * NUM_AUDIO_PROGS +
+		RISC_SYNC_INSTRUCTION_SIZE;
+	dev->audio_upstream_databuf_size = AUDIO_DATA_BUF_SZ * NUM_AUDIO_PROGS;
+
+	/* Allocating buffers and prepare RISC program */
+	retval = cx25821_audio_upstream_buffer_prepare(dev, sram_ch,
+							_line_size);
+	if (retval < 0) {
+		pr_err("%s: Failed to set up Audio upstream buffers!\n",
+			dev->name);
+		goto error;
+	}
+	/* Start RISC engine */
+	cx25821_start_audio_dma_upstream(dev, sram_ch);
+
+	return 0;
+
+error:
+	cx25821_dev_unregister(dev);
+
+	return err;
+}
diff --git a/drivers/media/pci/cx25821/cx25821-audio-upstream.h b/drivers/media/pci/cx25821/cx25821-audio-upstream.h
new file mode 100644
index 0000000..af2ae7c
--- /dev/null
+++ b/drivers/media/pci/cx25821/cx25821-audio-upstream.h
@@ -0,0 +1,62 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <hiep.huynh@conexant.com>, <shu.lin@conexant.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/mutex.h>
+#include <linux/workqueue.h>
+
+#define NUM_AUDIO_PROGS       8
+#define NUM_AUDIO_FRAMES      8
+#define END_OF_FILE           0
+#define IN_PROGRESS           1
+#define RESET_STATUS          -1
+#define FIFO_DISABLE          0
+#define FIFO_ENABLE           1
+#define NUM_NO_OPS            4
+
+#define RISC_READ_INSTRUCTION_SIZE      12
+#define RISC_JUMP_INSTRUCTION_SIZE      12
+#define RISC_WRITECR_INSTRUCTION_SIZE   16
+#define RISC_SYNC_INSTRUCTION_SIZE      4
+#define DWORD_SIZE                      4
+#define AUDIO_SYNC_LINE                 4
+
+#define LINES_PER_AUDIO_BUFFER      15
+#define AUDIO_LINE_SIZE             128
+#define AUDIO_DATA_BUF_SZ           (AUDIO_LINE_SIZE * LINES_PER_AUDIO_BUFFER)
+
+#define USE_RISC_NOOP_AUDIO   1
+
+#ifdef USE_RISC_NOOP_AUDIO
+#define AUDIO_RISC_DMA_BUF_SIZE						\
+	(LINES_PER_AUDIO_BUFFER * RISC_READ_INSTRUCTION_SIZE +		\
+	 RISC_WRITECR_INSTRUCTION_SIZE + NUM_NO_OPS * DWORD_SIZE +	\
+	 RISC_JUMP_INSTRUCTION_SIZE)
+#endif
+
+#ifndef USE_RISC_NOOP_AUDIO
+#define AUDIO_RISC_DMA_BUF_SIZE						\
+	(LINES_PER_AUDIO_BUFFER * RISC_READ_INSTRUCTION_SIZE +		\
+	 RISC_WRITECR_INSTRUCTION_SIZE + RISC_JUMP_INSTRUCTION_SIZE)
+#endif
+
+static int _line_size;
+char *_defaultAudioName = "/root/audioGOOD.wav";
diff --git a/drivers/media/pci/cx25821/cx25821-audio.h b/drivers/media/pci/cx25821/cx25821-audio.h
new file mode 100644
index 0000000..1fc2d24
--- /dev/null
+++ b/drivers/media/pci/cx25821/cx25821-audio.h
@@ -0,0 +1,62 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __CX25821_AUDIO_H__
+#define __CX25821_AUDIO_H__
+
+#define USE_RISC_NOOP		1
+#define LINES_PER_BUFFER	15
+#define AUDIO_LINE_SIZE		128
+
+/* Number of buffer programs to use at once. */
+#define NUMBER_OF_PROGRAMS	8
+
+/*
+ * Max size of the RISC program for a buffer. - worst case is 2 writes per line
+ * Space is also added for the 4 no-op instructions added on the end.
+ */
+#ifndef USE_RISC_NOOP
+#define MAX_BUFFER_PROGRAM_SIZE						\
+	(2 * LINES_PER_BUFFER * RISC_WRITE_INSTRUCTION_SIZE +		\
+	 RISC_WRITECR_INSTRUCTION_SIZE * 4)
+#endif
+
+/* MAE 12 July 2005 Try to use NOOP RISC instruction instead */
+#ifdef USE_RISC_NOOP
+#define MAX_BUFFER_PROGRAM_SIZE						\
+	(2 * LINES_PER_BUFFER * RISC_WRITE_INSTRUCTION_SIZE +		\
+	 RISC_NOOP_INSTRUCTION_SIZE * 4)
+#endif
+
+/* Sizes of various instructions in bytes.  Used when adding instructions. */
+#define RISC_WRITE_INSTRUCTION_SIZE	12
+#define RISC_JUMP_INSTRUCTION_SIZE	12
+#define RISC_SKIP_INSTRUCTION_SIZE	4
+#define RISC_SYNC_INSTRUCTION_SIZE	4
+#define RISC_WRITECR_INSTRUCTION_SIZE	16
+#define RISC_NOOP_INSTRUCTION_SIZE	4
+
+#define MAX_AUDIO_DMA_BUFFER_SIZE					\
+	(MAX_BUFFER_PROGRAM_SIZE * NUMBER_OF_PROGRAMS +			\
+	 RISC_SYNC_INSTRUCTION_SIZE)
+
+#endif
diff --git a/drivers/media/pci/cx25821/cx25821-biffuncs.h b/drivers/media/pci/cx25821/cx25821-biffuncs.h
new file mode 100644
index 0000000..9326a7c
--- /dev/null
+++ b/drivers/media/pci/cx25821/cx25821-biffuncs.h
@@ -0,0 +1,45 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _BITFUNCS_H
+#define _BITFUNCS_H
+
+#define SetBit(Bit)  (1 << Bit)
+
+inline u8 getBit(u32 sample, u8 index)
+{
+	return (u8) ((sample >> index) & 1);
+}
+
+inline u32 clearBitAtPos(u32 value, u8 bit)
+{
+	return value & ~(1 << bit);
+}
+
+inline u32 setBitAtPos(u32 sample, u8 bit)
+{
+	sample |= (1 << bit);
+	return sample;
+
+}
+
+#endif
diff --git a/drivers/media/pci/cx25821/cx25821-cards.c b/drivers/media/pci/cx25821/cx25821-cards.c
new file mode 100644
index 0000000..99988c9
--- /dev/null
+++ b/drivers/media/pci/cx25821/cx25821-cards.c
@@ -0,0 +1,72 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ *	Based on Steven Toth <stoth@linuxtv.org> cx23885 driver
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <media/cx25840.h>
+
+#include "cx25821.h"
+#include "tuner-xc2028.h"
+
+/* board config info */
+
+struct cx25821_board cx25821_boards[] = {
+	[UNKNOWN_BOARD] = {
+		.name = "UNKNOWN/GENERIC",
+		/* Ensure safe default for unknown boards */
+		.clk_freq = 0,
+	},
+
+	[CX25821_BOARD] = {
+		.name = "CX25821",
+		.portb = CX25821_RAW,
+		.portc = CX25821_264,
+		.input[0].type = CX25821_VMUX_COMPOSITE,
+	},
+
+};
+
+const unsigned int cx25821_bcount = ARRAY_SIZE(cx25821_boards);
+
+struct cx25821_subid cx25821_subids[] = {
+	{
+		.subvendor = 0x14f1,
+		.subdevice = 0x0920,
+		.card = CX25821_BOARD,
+	},
+};
+
+void cx25821_card_setup(struct cx25821_dev *dev)
+{
+	static u8 eeprom[256];
+
+	if (dev->i2c_bus[0].i2c_rc == 0) {
+		dev->i2c_bus[0].i2c_client.addr = 0xa0 >> 1;
+		tveeprom_read(&dev->i2c_bus[0].i2c_client, eeprom,
+				sizeof(eeprom));
+	}
+}
diff --git a/drivers/media/pci/cx25821/cx25821-core.c b/drivers/media/pci/cx25821/cx25821-core.c
new file mode 100644
index 0000000..f11f6f0
--- /dev/null
+++ b/drivers/media/pci/cx25821/cx25821-core.c
@@ -0,0 +1,1502 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ *  Based on Steven Toth <stoth@linuxtv.org> cx23885 driver
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include "cx25821.h"
+#include "cx25821-sram.h"
+#include "cx25821-video.h"
+
+MODULE_DESCRIPTION("Driver for Athena cards");
+MODULE_AUTHOR("Shu Lin - Hiep Huynh");
+MODULE_LICENSE("GPL");
+
+static unsigned int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "enable debug messages");
+
+static unsigned int card[] = {[0 ... (CX25821_MAXBOARDS - 1)] = UNSET };
+module_param_array(card, int, NULL, 0444);
+MODULE_PARM_DESC(card, "card type");
+
+static unsigned int cx25821_devcount;
+
+DEFINE_MUTEX(cx25821_devlist_mutex);
+EXPORT_SYMBOL(cx25821_devlist_mutex);
+LIST_HEAD(cx25821_devlist);
+EXPORT_SYMBOL(cx25821_devlist);
+
+struct sram_channel cx25821_sram_channels[] = {
+	[SRAM_CH00] = {
+		.i = SRAM_CH00,
+		.name = "VID A",
+		.cmds_start = VID_A_DOWN_CMDS,
+		.ctrl_start = VID_A_IQ,
+		.cdt = VID_A_CDT,
+		.fifo_start = VID_A_DOWN_CLUSTER_1,
+		.fifo_size = (VID_CLUSTER_SIZE << 2),
+		.ptr1_reg = DMA1_PTR1,
+		.ptr2_reg = DMA1_PTR2,
+		.cnt1_reg = DMA1_CNT1,
+		.cnt2_reg = DMA1_CNT2,
+		.int_msk = VID_A_INT_MSK,
+		.int_stat = VID_A_INT_STAT,
+		.int_mstat = VID_A_INT_MSTAT,
+		.dma_ctl = VID_DST_A_DMA_CTL,
+		.gpcnt_ctl = VID_DST_A_GPCNT_CTL,
+		.gpcnt = VID_DST_A_GPCNT,
+		.vip_ctl = VID_DST_A_VIP_CTL,
+		.pix_frmt = VID_DST_A_PIX_FRMT,
+	},
+
+	[SRAM_CH01] = {
+		.i = SRAM_CH01,
+		.name = "VID B",
+		.cmds_start = VID_B_DOWN_CMDS,
+		.ctrl_start = VID_B_IQ,
+		.cdt = VID_B_CDT,
+		.fifo_start = VID_B_DOWN_CLUSTER_1,
+		.fifo_size = (VID_CLUSTER_SIZE << 2),
+		.ptr1_reg = DMA2_PTR1,
+		.ptr2_reg = DMA2_PTR2,
+		.cnt1_reg = DMA2_CNT1,
+		.cnt2_reg = DMA2_CNT2,
+		.int_msk = VID_B_INT_MSK,
+		.int_stat = VID_B_INT_STAT,
+		.int_mstat = VID_B_INT_MSTAT,
+		.dma_ctl = VID_DST_B_DMA_CTL,
+		.gpcnt_ctl = VID_DST_B_GPCNT_CTL,
+		.gpcnt = VID_DST_B_GPCNT,
+		.vip_ctl = VID_DST_B_VIP_CTL,
+		.pix_frmt = VID_DST_B_PIX_FRMT,
+	},
+
+	[SRAM_CH02] = {
+		.i = SRAM_CH02,
+		.name = "VID C",
+		.cmds_start = VID_C_DOWN_CMDS,
+		.ctrl_start = VID_C_IQ,
+		.cdt = VID_C_CDT,
+		.fifo_start = VID_C_DOWN_CLUSTER_1,
+		.fifo_size = (VID_CLUSTER_SIZE << 2),
+		.ptr1_reg = DMA3_PTR1,
+		.ptr2_reg = DMA3_PTR2,
+		.cnt1_reg = DMA3_CNT1,
+		.cnt2_reg = DMA3_CNT2,
+		.int_msk = VID_C_INT_MSK,
+		.int_stat = VID_C_INT_STAT,
+		.int_mstat = VID_C_INT_MSTAT,
+		.dma_ctl = VID_DST_C_DMA_CTL,
+		.gpcnt_ctl = VID_DST_C_GPCNT_CTL,
+		.gpcnt = VID_DST_C_GPCNT,
+		.vip_ctl = VID_DST_C_VIP_CTL,
+		.pix_frmt = VID_DST_C_PIX_FRMT,
+	},
+
+	[SRAM_CH03] = {
+		.i = SRAM_CH03,
+		.name = "VID D",
+		.cmds_start = VID_D_DOWN_CMDS,
+		.ctrl_start = VID_D_IQ,
+		.cdt = VID_D_CDT,
+		.fifo_start = VID_D_DOWN_CLUSTER_1,
+		.fifo_size = (VID_CLUSTER_SIZE << 2),
+		.ptr1_reg = DMA4_PTR1,
+		.ptr2_reg = DMA4_PTR2,
+		.cnt1_reg = DMA4_CNT1,
+		.cnt2_reg = DMA4_CNT2,
+		.int_msk = VID_D_INT_MSK,
+		.int_stat = VID_D_INT_STAT,
+		.int_mstat = VID_D_INT_MSTAT,
+		.dma_ctl = VID_DST_D_DMA_CTL,
+		.gpcnt_ctl = VID_DST_D_GPCNT_CTL,
+		.gpcnt = VID_DST_D_GPCNT,
+		.vip_ctl = VID_DST_D_VIP_CTL,
+		.pix_frmt = VID_DST_D_PIX_FRMT,
+	},
+
+	[SRAM_CH04] = {
+		.i = SRAM_CH04,
+		.name = "VID E",
+		.cmds_start = VID_E_DOWN_CMDS,
+		.ctrl_start = VID_E_IQ,
+		.cdt = VID_E_CDT,
+		.fifo_start = VID_E_DOWN_CLUSTER_1,
+		.fifo_size = (VID_CLUSTER_SIZE << 2),
+		.ptr1_reg = DMA5_PTR1,
+		.ptr2_reg = DMA5_PTR2,
+		.cnt1_reg = DMA5_CNT1,
+		.cnt2_reg = DMA5_CNT2,
+		.int_msk = VID_E_INT_MSK,
+		.int_stat = VID_E_INT_STAT,
+		.int_mstat = VID_E_INT_MSTAT,
+		.dma_ctl = VID_DST_E_DMA_CTL,
+		.gpcnt_ctl = VID_DST_E_GPCNT_CTL,
+		.gpcnt = VID_DST_E_GPCNT,
+		.vip_ctl = VID_DST_E_VIP_CTL,
+		.pix_frmt = VID_DST_E_PIX_FRMT,
+	},
+
+	[SRAM_CH05] = {
+		.i = SRAM_CH05,
+		.name = "VID F",
+		.cmds_start = VID_F_DOWN_CMDS,
+		.ctrl_start = VID_F_IQ,
+		.cdt = VID_F_CDT,
+		.fifo_start = VID_F_DOWN_CLUSTER_1,
+		.fifo_size = (VID_CLUSTER_SIZE << 2),
+		.ptr1_reg = DMA6_PTR1,
+		.ptr2_reg = DMA6_PTR2,
+		.cnt1_reg = DMA6_CNT1,
+		.cnt2_reg = DMA6_CNT2,
+		.int_msk = VID_F_INT_MSK,
+		.int_stat = VID_F_INT_STAT,
+		.int_mstat = VID_F_INT_MSTAT,
+		.dma_ctl = VID_DST_F_DMA_CTL,
+		.gpcnt_ctl = VID_DST_F_GPCNT_CTL,
+		.gpcnt = VID_DST_F_GPCNT,
+		.vip_ctl = VID_DST_F_VIP_CTL,
+		.pix_frmt = VID_DST_F_PIX_FRMT,
+	},
+
+	[SRAM_CH06] = {
+		.i = SRAM_CH06,
+		.name = "VID G",
+		.cmds_start = VID_G_DOWN_CMDS,
+		.ctrl_start = VID_G_IQ,
+		.cdt = VID_G_CDT,
+		.fifo_start = VID_G_DOWN_CLUSTER_1,
+		.fifo_size = (VID_CLUSTER_SIZE << 2),
+		.ptr1_reg = DMA7_PTR1,
+		.ptr2_reg = DMA7_PTR2,
+		.cnt1_reg = DMA7_CNT1,
+		.cnt2_reg = DMA7_CNT2,
+		.int_msk = VID_G_INT_MSK,
+		.int_stat = VID_G_INT_STAT,
+		.int_mstat = VID_G_INT_MSTAT,
+		.dma_ctl = VID_DST_G_DMA_CTL,
+		.gpcnt_ctl = VID_DST_G_GPCNT_CTL,
+		.gpcnt = VID_DST_G_GPCNT,
+		.vip_ctl = VID_DST_G_VIP_CTL,
+		.pix_frmt = VID_DST_G_PIX_FRMT,
+	},
+
+	[SRAM_CH07] = {
+		.i = SRAM_CH07,
+		.name = "VID H",
+		.cmds_start = VID_H_DOWN_CMDS,
+		.ctrl_start = VID_H_IQ,
+		.cdt = VID_H_CDT,
+		.fifo_start = VID_H_DOWN_CLUSTER_1,
+		.fifo_size = (VID_CLUSTER_SIZE << 2),
+		.ptr1_reg = DMA8_PTR1,
+		.ptr2_reg = DMA8_PTR2,
+		.cnt1_reg = DMA8_CNT1,
+		.cnt2_reg = DMA8_CNT2,
+		.int_msk = VID_H_INT_MSK,
+		.int_stat = VID_H_INT_STAT,
+		.int_mstat = VID_H_INT_MSTAT,
+		.dma_ctl = VID_DST_H_DMA_CTL,
+		.gpcnt_ctl = VID_DST_H_GPCNT_CTL,
+		.gpcnt = VID_DST_H_GPCNT,
+		.vip_ctl = VID_DST_H_VIP_CTL,
+		.pix_frmt = VID_DST_H_PIX_FRMT,
+	},
+
+	[SRAM_CH08] = {
+		.name = "audio from",
+		.cmds_start = AUD_A_DOWN_CMDS,
+		.ctrl_start = AUD_A_IQ,
+		.cdt = AUD_A_CDT,
+		.fifo_start = AUD_A_DOWN_CLUSTER_1,
+		.fifo_size = AUDIO_CLUSTER_SIZE * 3,
+		.ptr1_reg = DMA17_PTR1,
+		.ptr2_reg = DMA17_PTR2,
+		.cnt1_reg = DMA17_CNT1,
+		.cnt2_reg = DMA17_CNT2,
+	},
+
+	[SRAM_CH09] = {
+		.i = SRAM_CH09,
+		.name = "VID Upstream I",
+		.cmds_start = VID_I_UP_CMDS,
+		.ctrl_start = VID_I_IQ,
+		.cdt = VID_I_CDT,
+		.fifo_start = VID_I_UP_CLUSTER_1,
+		.fifo_size = (VID_CLUSTER_SIZE << 2),
+		.ptr1_reg = DMA15_PTR1,
+		.ptr2_reg = DMA15_PTR2,
+		.cnt1_reg = DMA15_CNT1,
+		.cnt2_reg = DMA15_CNT2,
+		.int_msk = VID_I_INT_MSK,
+		.int_stat = VID_I_INT_STAT,
+		.int_mstat = VID_I_INT_MSTAT,
+		.dma_ctl = VID_SRC_I_DMA_CTL,
+		.gpcnt_ctl = VID_SRC_I_GPCNT_CTL,
+		.gpcnt = VID_SRC_I_GPCNT,
+
+		.vid_fmt_ctl = VID_SRC_I_FMT_CTL,
+		.vid_active_ctl1 = VID_SRC_I_ACTIVE_CTL1,
+		.vid_active_ctl2 = VID_SRC_I_ACTIVE_CTL2,
+		.vid_cdt_size = VID_SRC_I_CDT_SZ,
+		.irq_bit = 8,
+	},
+
+	[SRAM_CH10] = {
+		.i = SRAM_CH10,
+		.name = "VID Upstream J",
+		.cmds_start = VID_J_UP_CMDS,
+		.ctrl_start = VID_J_IQ,
+		.cdt = VID_J_CDT,
+		.fifo_start = VID_J_UP_CLUSTER_1,
+		.fifo_size = (VID_CLUSTER_SIZE << 2),
+		.ptr1_reg = DMA16_PTR1,
+		.ptr2_reg = DMA16_PTR2,
+		.cnt1_reg = DMA16_CNT1,
+		.cnt2_reg = DMA16_CNT2,
+		.int_msk = VID_J_INT_MSK,
+		.int_stat = VID_J_INT_STAT,
+		.int_mstat = VID_J_INT_MSTAT,
+		.dma_ctl = VID_SRC_J_DMA_CTL,
+		.gpcnt_ctl = VID_SRC_J_GPCNT_CTL,
+		.gpcnt = VID_SRC_J_GPCNT,
+
+		.vid_fmt_ctl = VID_SRC_J_FMT_CTL,
+		.vid_active_ctl1 = VID_SRC_J_ACTIVE_CTL1,
+		.vid_active_ctl2 = VID_SRC_J_ACTIVE_CTL2,
+		.vid_cdt_size = VID_SRC_J_CDT_SZ,
+		.irq_bit = 9,
+	},
+
+	[SRAM_CH11] = {
+		.i = SRAM_CH11,
+		.name = "Audio Upstream Channel B",
+		.cmds_start = AUD_B_UP_CMDS,
+		.ctrl_start = AUD_B_IQ,
+		.cdt = AUD_B_CDT,
+		.fifo_start = AUD_B_UP_CLUSTER_1,
+		.fifo_size = (AUDIO_CLUSTER_SIZE * 3),
+		.ptr1_reg = DMA22_PTR1,
+		.ptr2_reg = DMA22_PTR2,
+		.cnt1_reg = DMA22_CNT1,
+		.cnt2_reg = DMA22_CNT2,
+		.int_msk = AUD_B_INT_MSK,
+		.int_stat = AUD_B_INT_STAT,
+		.int_mstat = AUD_B_INT_MSTAT,
+		.dma_ctl = AUD_INT_DMA_CTL,
+		.gpcnt_ctl = AUD_B_GPCNT_CTL,
+		.gpcnt = AUD_B_GPCNT,
+		.aud_length = AUD_B_LNGTH,
+		.aud_cfg = AUD_B_CFG,
+		.fld_aud_fifo_en = FLD_AUD_SRC_B_FIFO_EN,
+		.fld_aud_risc_en = FLD_AUD_SRC_B_RISC_EN,
+		.irq_bit = 11,
+	},
+};
+EXPORT_SYMBOL(cx25821_sram_channels);
+
+struct sram_channel *channel0 = &cx25821_sram_channels[SRAM_CH00];
+struct sram_channel *channel1 = &cx25821_sram_channels[SRAM_CH01];
+struct sram_channel *channel2 = &cx25821_sram_channels[SRAM_CH02];
+struct sram_channel *channel3 = &cx25821_sram_channels[SRAM_CH03];
+struct sram_channel *channel4 = &cx25821_sram_channels[SRAM_CH04];
+struct sram_channel *channel5 = &cx25821_sram_channels[SRAM_CH05];
+struct sram_channel *channel6 = &cx25821_sram_channels[SRAM_CH06];
+struct sram_channel *channel7 = &cx25821_sram_channels[SRAM_CH07];
+struct sram_channel *channel9 = &cx25821_sram_channels[SRAM_CH09];
+struct sram_channel *channel10 = &cx25821_sram_channels[SRAM_CH10];
+struct sram_channel *channel11 = &cx25821_sram_channels[SRAM_CH11];
+
+struct cx25821_dmaqueue mpegq;
+
+static int cx25821_risc_decode(u32 risc)
+{
+	static const char * const instr[16] = {
+		[RISC_SYNC >> 28] = "sync",
+		[RISC_WRITE >> 28] = "write",
+		[RISC_WRITEC >> 28] = "writec",
+		[RISC_READ >> 28] = "read",
+		[RISC_READC >> 28] = "readc",
+		[RISC_JUMP >> 28] = "jump",
+		[RISC_SKIP >> 28] = "skip",
+		[RISC_WRITERM >> 28] = "writerm",
+		[RISC_WRITECM >> 28] = "writecm",
+		[RISC_WRITECR >> 28] = "writecr",
+	};
+	static const int incr[16] = {
+		[RISC_WRITE >> 28] = 3,
+		[RISC_JUMP >> 28] = 3,
+		[RISC_SKIP >> 28] = 1,
+		[RISC_SYNC >> 28] = 1,
+		[RISC_WRITERM >> 28] = 3,
+		[RISC_WRITECM >> 28] = 3,
+		[RISC_WRITECR >> 28] = 4,
+	};
+	static const char * const bits[] = {
+		"12", "13", "14", "resync",
+		"cnt0", "cnt1", "18", "19",
+		"20", "21", "22", "23",
+		"irq1", "irq2", "eol", "sol",
+	};
+	int i;
+
+	pr_cont("0x%08x [ %s",
+		risc, instr[risc >> 28] ? instr[risc >> 28] : "INVALID");
+	for (i = ARRAY_SIZE(bits) - 1; i >= 0; i--) {
+		if (risc & (1 << (i + 12)))
+			pr_cont(" %s", bits[i]);
+	}
+	pr_cont(" count=%d ]\n", risc & 0xfff);
+	return incr[risc >> 28] ? incr[risc >> 28] : 1;
+}
+
+static inline int i2c_slave_did_ack(struct i2c_adapter *i2c_adap)
+{
+	struct cx25821_i2c *bus = i2c_adap->algo_data;
+	struct cx25821_dev *dev = bus->dev;
+	return cx_read(bus->reg_stat) & 0x01;
+}
+
+static void cx25821_registers_init(struct cx25821_dev *dev)
+{
+	u32 tmp;
+
+	/* enable RUN_RISC in Pecos */
+	cx_write(DEV_CNTRL2, 0x20);
+
+	/* Set the master PCI interrupt masks to enable video, audio, MBIF,
+	 * and GPIO interrupts
+	 * I2C interrupt masking is handled by the I2C objects themselves. */
+	cx_write(PCI_INT_MSK, 0x2001FFFF);
+
+	tmp = cx_read(RDR_TLCTL0);
+	tmp &= ~FLD_CFG_RCB_CK_EN;	/* Clear the RCB_CK_EN bit */
+	cx_write(RDR_TLCTL0, tmp);
+
+	/* PLL-A setting for the Audio Master Clock */
+	cx_write(PLL_A_INT_FRAC, 0x9807A58B);
+
+	/* PLL_A_POST = 0x1C, PLL_A_OUT_TO_PIN = 0x1 */
+	cx_write(PLL_A_POST_STAT_BIST, 0x8000019C);
+
+	/* clear reset bit [31] */
+	tmp = cx_read(PLL_A_INT_FRAC);
+	cx_write(PLL_A_INT_FRAC, tmp & 0x7FFFFFFF);
+
+	/* PLL-B setting for Mobilygen Host Bus Interface */
+	cx_write(PLL_B_INT_FRAC, 0x9883A86F);
+
+	/* PLL_B_POST = 0xD, PLL_B_OUT_TO_PIN = 0x0 */
+	cx_write(PLL_B_POST_STAT_BIST, 0x8000018D);
+
+	/* clear reset bit [31] */
+	tmp = cx_read(PLL_B_INT_FRAC);
+	cx_write(PLL_B_INT_FRAC, tmp & 0x7FFFFFFF);
+
+	/* PLL-C setting for video upstream channel */
+	cx_write(PLL_C_INT_FRAC, 0x96A0EA3F);
+
+	/* PLL_C_POST = 0x3, PLL_C_OUT_TO_PIN = 0x0 */
+	cx_write(PLL_C_POST_STAT_BIST, 0x80000103);
+
+	/* clear reset bit [31] */
+	tmp = cx_read(PLL_C_INT_FRAC);
+	cx_write(PLL_C_INT_FRAC, tmp & 0x7FFFFFFF);
+
+	/* PLL-D setting for audio upstream channel */
+	cx_write(PLL_D_INT_FRAC, 0x98757F5B);
+
+	/* PLL_D_POST = 0x13, PLL_D_OUT_TO_PIN = 0x0 */
+	cx_write(PLL_D_POST_STAT_BIST, 0x80000113);
+
+	/* clear reset bit [31] */
+	tmp = cx_read(PLL_D_INT_FRAC);
+	cx_write(PLL_D_INT_FRAC, tmp & 0x7FFFFFFF);
+
+	/* This selects the PLL C clock source for the video upstream channel
+	 * I and J */
+	tmp = cx_read(VID_CH_CLK_SEL);
+	cx_write(VID_CH_CLK_SEL, (tmp & 0x00FFFFFF) | 0x24000000);
+
+	/* 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for
+	 * channel A-C
+	 * select 656/VIP DST for downstream Channel A - C */
+	tmp = cx_read(VID_CH_MODE_SEL);
+	/* cx_write( VID_CH_MODE_SEL, tmp | 0x1B0001FF); */
+	cx_write(VID_CH_MODE_SEL, tmp & 0xFFFFFE00);
+
+	/* enables 656 port I and J as output */
+	tmp = cx_read(CLK_RST);
+	/* use external ALT_PLL_REF pin as its reference clock instead */
+	tmp |= FLD_USE_ALT_PLL_REF;
+	cx_write(CLK_RST, tmp & ~(FLD_VID_I_CLK_NOE | FLD_VID_J_CLK_NOE));
+
+	mdelay(100);
+}
+
+int cx25821_sram_channel_setup(struct cx25821_dev *dev,
+			       struct sram_channel *ch,
+			       unsigned int bpl, u32 risc)
+{
+	unsigned int i, lines;
+	u32 cdt;
+
+	if (ch->cmds_start == 0) {
+		cx_write(ch->ptr1_reg, 0);
+		cx_write(ch->ptr2_reg, 0);
+		cx_write(ch->cnt2_reg, 0);
+		cx_write(ch->cnt1_reg, 0);
+		return 0;
+	}
+
+	bpl = (bpl + 7) & ~7;	/* alignment */
+	cdt = ch->cdt;
+	lines = ch->fifo_size / bpl;
+
+	if (lines > 4)
+		lines = 4;
+
+	BUG_ON(lines < 2);
+
+	cx_write(8 + 0, RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+	cx_write(8 + 4, 8);
+	cx_write(8 + 8, 0);
+
+	/* write CDT */
+	for (i = 0; i < lines; i++) {
+		cx_write(cdt + 16 * i, ch->fifo_start + bpl * i);
+		cx_write(cdt + 16 * i + 4, 0);
+		cx_write(cdt + 16 * i + 8, 0);
+		cx_write(cdt + 16 * i + 12, 0);
+	}
+
+	/* init the first cdt buffer */
+	for (i = 0; i < 128; i++)
+		cx_write(ch->fifo_start + 4 * i, i);
+
+	/* write CMDS */
+	if (ch->jumponly)
+		cx_write(ch->cmds_start + 0, 8);
+	else
+		cx_write(ch->cmds_start + 0, risc);
+
+	cx_write(ch->cmds_start + 4, 0);	/* 64 bits 63-32 */
+	cx_write(ch->cmds_start + 8, cdt);
+	cx_write(ch->cmds_start + 12, (lines * 16) >> 3);
+	cx_write(ch->cmds_start + 16, ch->ctrl_start);
+
+	if (ch->jumponly)
+		cx_write(ch->cmds_start + 20, 0x80000000 | (64 >> 2));
+	else
+		cx_write(ch->cmds_start + 20, 64 >> 2);
+
+	for (i = 24; i < 80; i += 4)
+		cx_write(ch->cmds_start + i, 0);
+
+	/* fill registers */
+	cx_write(ch->ptr1_reg, ch->fifo_start);
+	cx_write(ch->ptr2_reg, cdt);
+	cx_write(ch->cnt2_reg, (lines * 16) >> 3);
+	cx_write(ch->cnt1_reg, (bpl >> 3) - 1);
+
+	return 0;
+}
+EXPORT_SYMBOL(cx25821_sram_channel_setup);
+
+int cx25821_sram_channel_setup_audio(struct cx25821_dev *dev,
+				     struct sram_channel *ch,
+				     unsigned int bpl, u32 risc)
+{
+	unsigned int i, lines;
+	u32 cdt;
+
+	if (ch->cmds_start == 0) {
+		cx_write(ch->ptr1_reg, 0);
+		cx_write(ch->ptr2_reg, 0);
+		cx_write(ch->cnt2_reg, 0);
+		cx_write(ch->cnt1_reg, 0);
+		return 0;
+	}
+
+	bpl = (bpl + 7) & ~7;	/* alignment */
+	cdt = ch->cdt;
+	lines = ch->fifo_size / bpl;
+
+	if (lines > 3)
+		lines = 3;	/* for AUDIO */
+
+	BUG_ON(lines < 2);
+
+	cx_write(8 + 0, RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+	cx_write(8 + 4, 8);
+	cx_write(8 + 8, 0);
+
+	/* write CDT */
+	for (i = 0; i < lines; i++) {
+		cx_write(cdt + 16 * i, ch->fifo_start + bpl * i);
+		cx_write(cdt + 16 * i + 4, 0);
+		cx_write(cdt + 16 * i + 8, 0);
+		cx_write(cdt + 16 * i + 12, 0);
+	}
+
+	/* write CMDS */
+	if (ch->jumponly)
+		cx_write(ch->cmds_start + 0, 8);
+	else
+		cx_write(ch->cmds_start + 0, risc);
+
+	cx_write(ch->cmds_start + 4, 0);	/* 64 bits 63-32 */
+	cx_write(ch->cmds_start + 8, cdt);
+	cx_write(ch->cmds_start + 12, (lines * 16) >> 3);
+	cx_write(ch->cmds_start + 16, ch->ctrl_start);
+
+	/* IQ size */
+	if (ch->jumponly)
+		cx_write(ch->cmds_start + 20, 0x80000000 | (64 >> 2));
+	else
+		cx_write(ch->cmds_start + 20, 64 >> 2);
+
+	/* zero out */
+	for (i = 24; i < 80; i += 4)
+		cx_write(ch->cmds_start + i, 0);
+
+	/* fill registers */
+	cx_write(ch->ptr1_reg, ch->fifo_start);
+	cx_write(ch->ptr2_reg, cdt);
+	cx_write(ch->cnt2_reg, (lines * 16) >> 3);
+	cx_write(ch->cnt1_reg, (bpl >> 3) - 1);
+
+	return 0;
+}
+EXPORT_SYMBOL(cx25821_sram_channel_setup_audio);
+
+void cx25821_sram_channel_dump(struct cx25821_dev *dev, struct sram_channel *ch)
+{
+	static char *name[] = {
+		"init risc lo",
+		"init risc hi",
+		"cdt base",
+		"cdt size",
+		"iq base",
+		"iq size",
+		"risc pc lo",
+		"risc pc hi",
+		"iq wr ptr",
+		"iq rd ptr",
+		"cdt current",
+		"pci target lo",
+		"pci target hi",
+		"line / byte",
+	};
+	u32 risc;
+	unsigned int i, j, n;
+
+	pr_warn("%s: %s - dma channel status dump\n", dev->name, ch->name);
+	for (i = 0; i < ARRAY_SIZE(name); i++)
+		pr_warn("cmds + 0x%2x:   %-15s: 0x%08x\n",
+			i * 4, name[i], cx_read(ch->cmds_start + 4 * i));
+
+	j = i * 4;
+	for (i = 0; i < 4;) {
+		risc = cx_read(ch->cmds_start + 4 * (i + 14));
+		pr_warn("cmds + 0x%2x:   risc%d: ", j + i * 4, i);
+		i += cx25821_risc_decode(risc);
+	}
+
+	for (i = 0; i < (64 >> 2); i += n) {
+		risc = cx_read(ch->ctrl_start + 4 * i);
+		/* No consideration for bits 63-32 */
+
+		pr_warn("ctrl + 0x%2x (0x%08x): iq %x: ",
+			i * 4, ch->ctrl_start + 4 * i, i);
+		n = cx25821_risc_decode(risc);
+		for (j = 1; j < n; j++) {
+			risc = cx_read(ch->ctrl_start + 4 * (i + j));
+			pr_warn("ctrl + 0x%2x :   iq %x: 0x%08x [ arg #%d ]\n",
+				4 * (i + j), i + j, risc, j);
+		}
+	}
+
+	pr_warn("        :   fifo: 0x%08x -> 0x%x\n",
+		ch->fifo_start, ch->fifo_start + ch->fifo_size);
+	pr_warn("        :   ctrl: 0x%08x -> 0x%x\n",
+		ch->ctrl_start, ch->ctrl_start + 6 * 16);
+	pr_warn("        :   ptr1_reg: 0x%08x\n",
+		cx_read(ch->ptr1_reg));
+	pr_warn("        :   ptr2_reg: 0x%08x\n",
+		cx_read(ch->ptr2_reg));
+	pr_warn("        :   cnt1_reg: 0x%08x\n",
+		cx_read(ch->cnt1_reg));
+	pr_warn("        :   cnt2_reg: 0x%08x\n",
+		cx_read(ch->cnt2_reg));
+}
+EXPORT_SYMBOL(cx25821_sram_channel_dump);
+
+void cx25821_sram_channel_dump_audio(struct cx25821_dev *dev,
+				     struct sram_channel *ch)
+{
+	static const char * const name[] = {
+		"init risc lo",
+		"init risc hi",
+		"cdt base",
+		"cdt size",
+		"iq base",
+		"iq size",
+		"risc pc lo",
+		"risc pc hi",
+		"iq wr ptr",
+		"iq rd ptr",
+		"cdt current",
+		"pci target lo",
+		"pci target hi",
+		"line / byte",
+	};
+
+	u32 risc, value, tmp;
+	unsigned int i, j, n;
+
+	pr_info("\n%s: %s - dma Audio channel status dump\n",
+		dev->name, ch->name);
+
+	for (i = 0; i < ARRAY_SIZE(name); i++)
+		pr_info("%s: cmds + 0x%2x:   %-15s: 0x%08x\n",
+			dev->name, i * 4, name[i],
+			cx_read(ch->cmds_start + 4 * i));
+
+	j = i * 4;
+	for (i = 0; i < 4;) {
+		risc = cx_read(ch->cmds_start + 4 * (i + 14));
+		pr_warn("cmds + 0x%2x:   risc%d: ", j + i * 4, i);
+		i += cx25821_risc_decode(risc);
+	}
+
+	for (i = 0; i < (64 >> 2); i += n) {
+		risc = cx_read(ch->ctrl_start + 4 * i);
+		/* No consideration for bits 63-32 */
+
+		pr_warn("ctrl + 0x%2x (0x%08x): iq %x: ",
+			i * 4, ch->ctrl_start + 4 * i, i);
+		n = cx25821_risc_decode(risc);
+
+		for (j = 1; j < n; j++) {
+			risc = cx_read(ch->ctrl_start + 4 * (i + j));
+			pr_warn("ctrl + 0x%2x :   iq %x: 0x%08x [ arg #%d ]\n",
+				4 * (i + j), i + j, risc, j);
+		}
+	}
+
+	pr_warn("        :   fifo: 0x%08x -> 0x%x\n",
+		ch->fifo_start, ch->fifo_start + ch->fifo_size);
+	pr_warn("        :   ctrl: 0x%08x -> 0x%x\n",
+		ch->ctrl_start, ch->ctrl_start + 6 * 16);
+	pr_warn("        :   ptr1_reg: 0x%08x\n",
+		cx_read(ch->ptr1_reg));
+	pr_warn("        :   ptr2_reg: 0x%08x\n",
+		cx_read(ch->ptr2_reg));
+	pr_warn("        :   cnt1_reg: 0x%08x\n",
+		cx_read(ch->cnt1_reg));
+	pr_warn("        :   cnt2_reg: 0x%08x\n",
+		cx_read(ch->cnt2_reg));
+
+	for (i = 0; i < 4; i++) {
+		risc = cx_read(ch->cmds_start + 56 + (i * 4));
+		pr_warn("instruction %d = 0x%x\n", i, risc);
+	}
+
+	/* read data from the first cdt buffer */
+	risc = cx_read(AUD_A_CDT);
+	pr_warn("\nread cdt loc=0x%x\n", risc);
+	for (i = 0; i < 8; i++) {
+		n = cx_read(risc + i * 4);
+		pr_cont("0x%x ", n);
+	}
+	pr_cont("\n\n");
+
+	value = cx_read(CLK_RST);
+	CX25821_INFO(" CLK_RST = 0x%x\n\n", value);
+
+	value = cx_read(PLL_A_POST_STAT_BIST);
+	CX25821_INFO(" PLL_A_POST_STAT_BIST = 0x%x\n\n", value);
+	value = cx_read(PLL_A_INT_FRAC);
+	CX25821_INFO(" PLL_A_INT_FRAC = 0x%x\n\n", value);
+
+	value = cx_read(PLL_B_POST_STAT_BIST);
+	CX25821_INFO(" PLL_B_POST_STAT_BIST = 0x%x\n\n", value);
+	value = cx_read(PLL_B_INT_FRAC);
+	CX25821_INFO(" PLL_B_INT_FRAC = 0x%x\n\n", value);
+
+	value = cx_read(PLL_C_POST_STAT_BIST);
+	CX25821_INFO(" PLL_C_POST_STAT_BIST = 0x%x\n\n", value);
+	value = cx_read(PLL_C_INT_FRAC);
+	CX25821_INFO(" PLL_C_INT_FRAC = 0x%x\n\n", value);
+
+	value = cx_read(PLL_D_POST_STAT_BIST);
+	CX25821_INFO(" PLL_D_POST_STAT_BIST = 0x%x\n\n", value);
+	value = cx_read(PLL_D_INT_FRAC);
+	CX25821_INFO(" PLL_D_INT_FRAC = 0x%x\n\n", value);
+
+	value = cx25821_i2c_read(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL, &tmp);
+	CX25821_INFO(" AFE_AB_DIAG_CTRL (0x10900090) = 0x%x\n\n", value);
+}
+EXPORT_SYMBOL(cx25821_sram_channel_dump_audio);
+
+static void cx25821_shutdown(struct cx25821_dev *dev)
+{
+	int i;
+
+	/* disable RISC controller */
+	cx_write(DEV_CNTRL2, 0);
+
+	/* Disable Video A/B activity */
+	for (i = 0; i < VID_CHANNEL_NUM; i++) {
+		cx_write(dev->channels[i].sram_channels->dma_ctl, 0);
+		cx_write(dev->channels[i].sram_channels->int_msk, 0);
+	}
+
+	for (i = VID_UPSTREAM_SRAM_CHANNEL_I;
+		i <= VID_UPSTREAM_SRAM_CHANNEL_J; i++) {
+		cx_write(dev->channels[i].sram_channels->dma_ctl, 0);
+		cx_write(dev->channels[i].sram_channels->int_msk, 0);
+	}
+
+	/* Disable Audio activity */
+	cx_write(AUD_INT_DMA_CTL, 0);
+
+	/* Disable Serial port */
+	cx_write(UART_CTL, 0);
+
+	/* Disable Interrupts */
+	cx_write(PCI_INT_MSK, 0);
+	cx_write(AUD_A_INT_MSK, 0);
+}
+
+void cx25821_set_pixel_format(struct cx25821_dev *dev, int channel_select,
+			      u32 format)
+{
+	if (channel_select <= 7 && channel_select >= 0) {
+		cx_write(dev->channels[channel_select].sram_channels->pix_frmt,
+				format);
+		dev->channels[channel_select].pixel_formats = format;
+	}
+}
+
+static void cx25821_set_vip_mode(struct cx25821_dev *dev,
+				 struct sram_channel *ch)
+{
+	cx_write(ch->pix_frmt, PIXEL_FRMT_422);
+	cx_write(ch->vip_ctl, PIXEL_ENGINE_VIP1);
+}
+
+static void cx25821_initialize(struct cx25821_dev *dev)
+{
+	int i;
+
+	dprintk(1, "%s()\n", __func__);
+
+	cx25821_shutdown(dev);
+	cx_write(PCI_INT_STAT, 0xffffffff);
+
+	for (i = 0; i < VID_CHANNEL_NUM; i++)
+		cx_write(dev->channels[i].sram_channels->int_stat, 0xffffffff);
+
+	cx_write(AUD_A_INT_STAT, 0xffffffff);
+	cx_write(AUD_B_INT_STAT, 0xffffffff);
+	cx_write(AUD_C_INT_STAT, 0xffffffff);
+	cx_write(AUD_D_INT_STAT, 0xffffffff);
+	cx_write(AUD_E_INT_STAT, 0xffffffff);
+
+	cx_write(CLK_DELAY, cx_read(CLK_DELAY) & 0x80000000);
+	cx_write(PAD_CTRL, 0x12);	/* for I2C */
+	cx25821_registers_init(dev);	/* init Pecos registers */
+	mdelay(100);
+
+	for (i = 0; i < VID_CHANNEL_NUM; i++) {
+		cx25821_set_vip_mode(dev, dev->channels[i].sram_channels);
+		cx25821_sram_channel_setup(dev, dev->channels[i].sram_channels,
+						1440, 0);
+		dev->channels[i].pixel_formats = PIXEL_FRMT_422;
+		dev->channels[i].use_cif_resolution = FALSE;
+	}
+
+	/* Probably only affect Downstream */
+	for (i = VID_UPSTREAM_SRAM_CHANNEL_I;
+		i <= VID_UPSTREAM_SRAM_CHANNEL_J; i++) {
+		cx25821_set_vip_mode(dev, dev->channels[i].sram_channels);
+	}
+
+	cx25821_sram_channel_setup_audio(dev,
+			dev->channels[SRAM_CH08].sram_channels, 128, 0);
+
+	cx25821_gpio_init(dev);
+}
+
+static int cx25821_get_resources(struct cx25821_dev *dev)
+{
+	if (request_mem_region(pci_resource_start(dev->pci, 0),
+				pci_resource_len(dev->pci, 0), dev->name))
+		return 0;
+
+	pr_err("%s: can't get MMIO memory @ 0x%llx\n",
+		dev->name, (unsigned long long)pci_resource_start(dev->pci, 0));
+
+	return -EBUSY;
+}
+
+static void cx25821_dev_checkrevision(struct cx25821_dev *dev)
+{
+	dev->hwrevision = cx_read(RDR_CFG2) & 0xff;
+
+	pr_info("%s(): Hardware revision = 0x%02x\n",
+		__func__, dev->hwrevision);
+}
+
+static void cx25821_iounmap(struct cx25821_dev *dev)
+{
+	if (dev == NULL)
+		return;
+
+	/* Releasing IO memory */
+	if (dev->lmmio != NULL) {
+		CX25821_INFO("Releasing lmmio.\n");
+		iounmap(dev->lmmio);
+		dev->lmmio = NULL;
+	}
+}
+
+static int cx25821_dev_setup(struct cx25821_dev *dev)
+{
+	int i;
+
+	pr_info("\n***********************************\n");
+	pr_info("cx25821 set up\n");
+	pr_info("***********************************\n\n");
+
+	mutex_init(&dev->lock);
+
+	atomic_inc(&dev->refcount);
+
+	dev->nr = ++cx25821_devcount;
+	sprintf(dev->name, "cx25821[%d]", dev->nr);
+
+	mutex_lock(&cx25821_devlist_mutex);
+	list_add_tail(&dev->devlist, &cx25821_devlist);
+	mutex_unlock(&cx25821_devlist_mutex);
+
+	if (dev->pci->device != 0x8210) {
+		pr_info("%s(): Exiting. Incorrect Hardware device = 0x%02x\n",
+			__func__, dev->pci->device);
+		return -1;
+	} else {
+		pr_info("Athena Hardware device = 0x%02x\n", dev->pci->device);
+	}
+
+	/* Apply a sensible clock frequency for the PCIe bridge */
+	dev->clk_freq = 28000000;
+	for (i = 0; i < MAX_VID_CHANNEL_NUM; i++)
+		dev->channels[i].sram_channels = &cx25821_sram_channels[i];
+
+	if (dev->nr > 1)
+		CX25821_INFO("dev->nr > 1!");
+
+	/* board config */
+	dev->board = 1;		/* card[dev->nr]; */
+	dev->_max_num_decoders = MAX_DECODERS;
+
+	dev->pci_bus = dev->pci->bus->number;
+	dev->pci_slot = PCI_SLOT(dev->pci->devfn);
+	dev->pci_irqmask = 0x001f00;
+
+	/* External Master 1 Bus */
+	dev->i2c_bus[0].nr = 0;
+	dev->i2c_bus[0].dev = dev;
+	dev->i2c_bus[0].reg_stat = I2C1_STAT;
+	dev->i2c_bus[0].reg_ctrl = I2C1_CTRL;
+	dev->i2c_bus[0].reg_addr = I2C1_ADDR;
+	dev->i2c_bus[0].reg_rdata = I2C1_RDATA;
+	dev->i2c_bus[0].reg_wdata = I2C1_WDATA;
+	dev->i2c_bus[0].i2c_period = (0x07 << 24);	/* 1.95MHz */
+
+	if (cx25821_get_resources(dev) < 0) {
+		pr_err("%s: No more PCIe resources for subsystem: %04x:%04x\n",
+		       dev->name, dev->pci->subsystem_vendor,
+		       dev->pci->subsystem_device);
+
+		cx25821_devcount--;
+		return -EBUSY;
+	}
+
+	/* PCIe stuff */
+	dev->base_io_addr = pci_resource_start(dev->pci, 0);
+
+	if (!dev->base_io_addr) {
+		CX25821_ERR("No PCI Memory resources, exiting!\n");
+		return -ENODEV;
+	}
+
+	dev->lmmio = ioremap(dev->base_io_addr, pci_resource_len(dev->pci, 0));
+
+	if (!dev->lmmio) {
+		CX25821_ERR("ioremap failed, maybe increasing __VMALLOC_RESERVE in page.h\n");
+		cx25821_iounmap(dev);
+		return -ENOMEM;
+	}
+
+	dev->bmmio = (u8 __iomem *) dev->lmmio;
+
+	pr_info("%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
+		dev->name, dev->pci->subsystem_vendor,
+		dev->pci->subsystem_device, cx25821_boards[dev->board].name,
+		dev->board, card[dev->nr] == dev->board ?
+		"insmod option" : "autodetected");
+
+	/* init hardware */
+	cx25821_initialize(dev);
+
+	cx25821_i2c_register(&dev->i2c_bus[0]);
+/*  cx25821_i2c_register(&dev->i2c_bus[1]);
+ *  cx25821_i2c_register(&dev->i2c_bus[2]); */
+
+	CX25821_INFO("i2c register! bus->i2c_rc = %d\n",
+			dev->i2c_bus[0].i2c_rc);
+
+	cx25821_card_setup(dev);
+
+	if (medusa_video_init(dev) < 0)
+		CX25821_ERR("%s(): Failed to initialize medusa!\n", __func__);
+
+	cx25821_video_register(dev);
+
+	/* register IOCTL device */
+	dev->ioctl_dev = cx25821_vdev_init(dev, dev->pci,
+			&cx25821_videoioctl_template, "video");
+
+	if (video_register_device
+	    (dev->ioctl_dev, VFL_TYPE_GRABBER, VIDEO_IOCTL_CH) < 0) {
+		cx25821_videoioctl_unregister(dev);
+		pr_err("%s(): Failed to register video adapter for IOCTL, so unregistering videoioctl device\n",
+		       __func__);
+	}
+
+	cx25821_dev_checkrevision(dev);
+	CX25821_INFO("setup done!\n");
+
+	return 0;
+}
+
+void cx25821_start_upstream_video_ch1(struct cx25821_dev *dev,
+				      struct upstream_user_struct *up_data)
+{
+	dev->_isNTSC = !strcmp(dev->vid_stdname, "NTSC") ? 1 : 0;
+
+	dev->tvnorm = !dev->_isNTSC ? V4L2_STD_PAL_BG : V4L2_STD_NTSC_M;
+	medusa_set_videostandard(dev);
+
+	cx25821_vidupstream_init_ch1(dev, dev->channel_select,
+				     dev->pixel_format);
+}
+
+void cx25821_start_upstream_video_ch2(struct cx25821_dev *dev,
+				      struct upstream_user_struct *up_data)
+{
+	dev->_isNTSC_ch2 = !strcmp(dev->vid_stdname_ch2, "NTSC") ? 1 : 0;
+
+	dev->tvnorm = !dev->_isNTSC_ch2 ? V4L2_STD_PAL_BG : V4L2_STD_NTSC_M;
+	medusa_set_videostandard(dev);
+
+	cx25821_vidupstream_init_ch2(dev, dev->channel_select_ch2,
+				     dev->pixel_format_ch2);
+}
+
+void cx25821_start_upstream_audio(struct cx25821_dev *dev,
+				  struct upstream_user_struct *up_data)
+{
+	cx25821_audio_upstream_init(dev, AUDIO_UPSTREAM_SRAM_CHANNEL_B);
+}
+
+void cx25821_dev_unregister(struct cx25821_dev *dev)
+{
+	int i;
+
+	if (!dev->base_io_addr)
+		return;
+
+	cx25821_free_mem_upstream_ch1(dev);
+	cx25821_free_mem_upstream_ch2(dev);
+	cx25821_free_mem_upstream_audio(dev);
+
+	release_mem_region(dev->base_io_addr, pci_resource_len(dev->pci, 0));
+
+	if (!atomic_dec_and_test(&dev->refcount))
+		return;
+
+	for (i = 0; i < VID_CHANNEL_NUM; i++)
+		cx25821_video_unregister(dev, i);
+
+	for (i = VID_UPSTREAM_SRAM_CHANNEL_I;
+	     i <= AUDIO_UPSTREAM_SRAM_CHANNEL_B; i++) {
+		cx25821_video_unregister(dev, i);
+	}
+
+	cx25821_videoioctl_unregister(dev);
+
+	cx25821_i2c_unregister(&dev->i2c_bus[0]);
+	cx25821_iounmap(dev);
+}
+EXPORT_SYMBOL(cx25821_dev_unregister);
+
+static __le32 *cx25821_risc_field(__le32 * rp, struct scatterlist *sglist,
+				  unsigned int offset, u32 sync_line,
+				  unsigned int bpl, unsigned int padding,
+				  unsigned int lines)
+{
+	struct scatterlist *sg;
+	unsigned int line, todo;
+
+	/* sync instruction */
+	if (sync_line != NO_SYNC_LINE)
+		*(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
+
+	/* scan lines */
+	sg = sglist;
+	for (line = 0; line < lines; line++) {
+		while (offset && offset >= sg_dma_len(sg)) {
+			offset -= sg_dma_len(sg);
+			sg++;
+		}
+		if (bpl <= sg_dma_len(sg) - offset) {
+			/* fits into current chunk */
+			*(rp++) = cpu_to_le32(RISC_WRITE | RISC_SOL | RISC_EOL |
+					bpl);
+			*(rp++) = cpu_to_le32(sg_dma_address(sg) + offset);
+			*(rp++) = cpu_to_le32(0);	/* bits 63-32 */
+			offset += bpl;
+		} else {
+			/* scanline needs to be split */
+			todo = bpl;
+			*(rp++) = cpu_to_le32(RISC_WRITE | RISC_SOL |
+					(sg_dma_len(sg) - offset));
+			*(rp++) = cpu_to_le32(sg_dma_address(sg) + offset);
+			*(rp++) = cpu_to_le32(0);	/* bits 63-32 */
+			todo -= (sg_dma_len(sg) - offset);
+			offset = 0;
+			sg++;
+			while (todo > sg_dma_len(sg)) {
+				*(rp++) = cpu_to_le32(RISC_WRITE |
+						sg_dma_len(sg));
+				*(rp++) = cpu_to_le32(sg_dma_address(sg));
+				*(rp++) = cpu_to_le32(0);	/* bits 63-32 */
+				todo -= sg_dma_len(sg);
+				sg++;
+			}
+			*(rp++) = cpu_to_le32(RISC_WRITE | RISC_EOL | todo);
+			*(rp++) = cpu_to_le32(sg_dma_address(sg));
+			*(rp++) = cpu_to_le32(0);	/* bits 63-32 */
+			offset += todo;
+		}
+
+		offset += padding;
+	}
+
+	return rp;
+}
+
+int cx25821_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
+			struct scatterlist *sglist, unsigned int top_offset,
+			unsigned int bottom_offset, unsigned int bpl,
+			unsigned int padding, unsigned int lines)
+{
+	u32 instructions;
+	u32 fields;
+	__le32 *rp;
+	int rc;
+
+	fields = 0;
+	if (UNSET != top_offset)
+		fields++;
+	if (UNSET != bottom_offset)
+		fields++;
+
+	/* estimate risc mem: worst case is one write per page border +
+	   one write per scan line + syncs + jump (all 2 dwords).  Padding
+	   can cause next bpl to start close to a page border.  First DMA
+	   region may be smaller than PAGE_SIZE */
+	/* write and jump need and extra dword */
+	instructions = fields * (1 + ((bpl + padding) * lines) / PAGE_SIZE +
+			lines);
+	instructions += 2;
+	rc = btcx_riscmem_alloc(pci, risc, instructions * 12);
+
+	if (rc < 0)
+		return rc;
+
+	/* write risc instructions */
+	rp = risc->cpu;
+
+	if (UNSET != top_offset) {
+		rp = cx25821_risc_field(rp, sglist, top_offset, 0, bpl, padding,
+					lines);
+	}
+
+	if (UNSET != bottom_offset) {
+		rp = cx25821_risc_field(rp, sglist, bottom_offset, 0x200, bpl,
+					padding, lines);
+	}
+
+	/* save pointer to jmp instruction address */
+	risc->jmp = rp;
+	BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
+
+	return 0;
+}
+
+static __le32 *cx25821_risc_field_audio(__le32 * rp, struct scatterlist *sglist,
+					unsigned int offset, u32 sync_line,
+					unsigned int bpl, unsigned int padding,
+					unsigned int lines, unsigned int lpi)
+{
+	struct scatterlist *sg;
+	unsigned int line, todo, sol;
+
+	/* sync instruction */
+	if (sync_line != NO_SYNC_LINE)
+		*(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
+
+	/* scan lines */
+	sg = sglist;
+	for (line = 0; line < lines; line++) {
+		while (offset && offset >= sg_dma_len(sg)) {
+			offset -= sg_dma_len(sg);
+			sg++;
+		}
+
+		if (lpi && line > 0 && !(line % lpi))
+			sol = RISC_SOL | RISC_IRQ1 | RISC_CNT_INC;
+		else
+			sol = RISC_SOL;
+
+		if (bpl <= sg_dma_len(sg) - offset) {
+			/* fits into current chunk */
+			*(rp++) = cpu_to_le32(RISC_WRITE | sol | RISC_EOL |
+					bpl);
+			*(rp++) = cpu_to_le32(sg_dma_address(sg) + offset);
+			*(rp++) = cpu_to_le32(0);	/* bits 63-32 */
+			offset += bpl;
+		} else {
+			/* scanline needs to be split */
+			todo = bpl;
+			*(rp++) = cpu_to_le32(RISC_WRITE | sol |
+					(sg_dma_len(sg) - offset));
+			*(rp++) = cpu_to_le32(sg_dma_address(sg) + offset);
+			*(rp++) = cpu_to_le32(0);	/* bits 63-32 */
+			todo -= (sg_dma_len(sg) - offset);
+			offset = 0;
+			sg++;
+			while (todo > sg_dma_len(sg)) {
+				*(rp++) = cpu_to_le32(RISC_WRITE |
+						sg_dma_len(sg));
+				*(rp++) = cpu_to_le32(sg_dma_address(sg));
+				*(rp++) = cpu_to_le32(0);	/* bits 63-32 */
+				todo -= sg_dma_len(sg);
+				sg++;
+			}
+			*(rp++) = cpu_to_le32(RISC_WRITE | RISC_EOL | todo);
+			*(rp++) = cpu_to_le32(sg_dma_address(sg));
+			*(rp++) = cpu_to_le32(0);	/* bits 63-32 */
+			offset += todo;
+		}
+		offset += padding;
+	}
+
+	return rp;
+}
+
+int cx25821_risc_databuffer_audio(struct pci_dev *pci,
+				  struct btcx_riscmem *risc,
+				  struct scatterlist *sglist,
+				  unsigned int bpl,
+				  unsigned int lines, unsigned int lpi)
+{
+	u32 instructions;
+	__le32 *rp;
+	int rc;
+
+	/* estimate risc mem: worst case is one write per page border +
+	   one write per scan line + syncs + jump (all 2 dwords).  Here
+	   there is no padding and no sync.  First DMA region may be smaller
+	   than PAGE_SIZE */
+	/* Jump and write need an extra dword */
+	instructions = 1 + (bpl * lines) / PAGE_SIZE + lines;
+	instructions += 1;
+
+	rc = btcx_riscmem_alloc(pci, risc, instructions * 12);
+	if (rc < 0)
+		return rc;
+
+	/* write risc instructions */
+	rp = risc->cpu;
+	rp = cx25821_risc_field_audio(rp, sglist, 0, NO_SYNC_LINE, bpl, 0,
+				      lines, lpi);
+
+	/* save pointer to jmp instruction address */
+	risc->jmp = rp;
+	BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
+	return 0;
+}
+EXPORT_SYMBOL(cx25821_risc_databuffer_audio);
+
+int cx25821_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
+			 u32 reg, u32 mask, u32 value)
+{
+	__le32 *rp;
+	int rc;
+
+	rc = btcx_riscmem_alloc(pci, risc, 4 * 16);
+
+	if (rc < 0)
+		return rc;
+
+	/* write risc instructions */
+	rp = risc->cpu;
+
+	*(rp++) = cpu_to_le32(RISC_WRITECR | RISC_IRQ1);
+	*(rp++) = cpu_to_le32(reg);
+	*(rp++) = cpu_to_le32(value);
+	*(rp++) = cpu_to_le32(mask);
+	*(rp++) = cpu_to_le32(RISC_JUMP);
+	*(rp++) = cpu_to_le32(risc->dma);
+	*(rp++) = cpu_to_le32(0);	/* bits 63-32 */
+	return 0;
+}
+
+void cx25821_free_buffer(struct videobuf_queue *q, struct cx25821_buffer *buf)
+{
+	struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb);
+
+	BUG_ON(in_interrupt());
+	videobuf_waiton(q, &buf->vb, 0, 0);
+	videobuf_dma_unmap(q->dev, dma);
+	videobuf_dma_free(dma);
+	btcx_riscmem_free(to_pci_dev(q->dev), &buf->risc);
+	buf->vb.state = VIDEOBUF_NEEDS_INIT;
+}
+
+static irqreturn_t cx25821_irq(int irq, void *dev_id)
+{
+	struct cx25821_dev *dev = dev_id;
+	u32 pci_status;
+	u32 vid_status;
+	int i, handled = 0;
+	u32 mask[8] = { 1, 2, 4, 8, 16, 32, 64, 128 };
+
+	pci_status = cx_read(PCI_INT_STAT);
+
+	if (pci_status == 0)
+		goto out;
+
+	for (i = 0; i < VID_CHANNEL_NUM; i++) {
+		if (pci_status & mask[i]) {
+			vid_status = cx_read(dev->channels[i].
+				sram_channels->int_stat);
+
+			if (vid_status)
+				handled += cx25821_video_irq(dev, i,
+						vid_status);
+
+			cx_write(PCI_INT_STAT, mask[i]);
+		}
+	}
+
+out:
+	return IRQ_RETVAL(handled);
+}
+
+void cx25821_print_irqbits(char *name, char *tag, char **strings,
+			   int len, u32 bits, u32 mask)
+{
+	unsigned int i;
+
+	printk(KERN_DEBUG pr_fmt("%s: %s [0x%x]"), name, tag, bits);
+
+	for (i = 0; i < len; i++) {
+		if (!(bits & (1 << i)))
+			continue;
+		if (strings[i])
+			pr_cont(" %s", strings[i]);
+		else
+			pr_cont(" %d", i);
+		if (!(mask & (1 << i)))
+			continue;
+		pr_cont("*");
+	}
+	pr_cont("\n");
+}
+EXPORT_SYMBOL(cx25821_print_irqbits);
+
+struct cx25821_dev *cx25821_dev_get(struct pci_dev *pci)
+{
+	struct cx25821_dev *dev = pci_get_drvdata(pci);
+	return dev;
+}
+EXPORT_SYMBOL(cx25821_dev_get);
+
+static int __devinit cx25821_initdev(struct pci_dev *pci_dev,
+				     const struct pci_device_id *pci_id)
+{
+	struct cx25821_dev *dev;
+	int err = 0;
+
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	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;
+
+		pr_info("pci enable failed!\n");
+
+		goto fail_unregister_device;
+	}
+
+	pr_info("Athena pci enable !\n");
+
+	err = cx25821_dev_setup(dev);
+	if (err) {
+		if (err == -EBUSY)
+			goto fail_unregister_device;
+		else
+			goto fail_unregister_pci;
+	}
+
+	/* print pci info */
+	pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &dev->pci_rev);
+	pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &dev->pci_lat);
+	pr_info("%s/0: found at %s, rev: %d, irq: %d, latency: %d, mmio: 0x%llx\n",
+		dev->name, pci_name(pci_dev), dev->pci_rev, pci_dev->irq,
+		dev->pci_lat, (unsigned long long)dev->base_io_addr);
+
+	pci_set_master(pci_dev);
+	if (!pci_dma_supported(pci_dev, 0xffffffff)) {
+		pr_err("%s/0: Oops: no 32bit PCI DMA ???\n", dev->name);
+		err = -EIO;
+		goto fail_irq;
+	}
+
+	err = request_irq(pci_dev->irq, cx25821_irq,
+			IRQF_SHARED, dev->name, dev);
+
+	if (err < 0) {
+		pr_err("%s: can't get IRQ %d\n", dev->name, pci_dev->irq);
+		goto fail_irq;
+	}
+
+	return 0;
+
+fail_irq:
+	pr_info("cx25821_initdev() can't get IRQ !\n");
+	cx25821_dev_unregister(dev);
+
+fail_unregister_pci:
+	pci_disable_device(pci_dev);
+fail_unregister_device:
+	v4l2_device_unregister(&dev->v4l2_dev);
+
+fail_free:
+	kfree(dev);
+	return err;
+}
+
+static void __devexit cx25821_finidev(struct pci_dev *pci_dev)
+{
+	struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
+	struct cx25821_dev *dev = get_cx25821(v4l2_dev);
+
+	cx25821_shutdown(dev);
+	pci_disable_device(pci_dev);
+
+	/* unregister stuff */
+	if (pci_dev->irq)
+		free_irq(pci_dev->irq, dev);
+
+	mutex_lock(&cx25821_devlist_mutex);
+	list_del(&dev->devlist);
+	mutex_unlock(&cx25821_devlist_mutex);
+
+	cx25821_dev_unregister(dev);
+	v4l2_device_unregister(v4l2_dev);
+	kfree(dev);
+}
+
+static DEFINE_PCI_DEVICE_TABLE(cx25821_pci_tbl) = {
+	{
+		/* CX25821 Athena */
+		.vendor = 0x14f1,
+		.device = 0x8210,
+		.subvendor = 0x14f1,
+		.subdevice = 0x0920,
+	}, {
+		/* CX25821 No Brand */
+		.vendor = 0x14f1,
+		.device = 0x8210,
+		.subvendor = 0x0000,
+		.subdevice = 0x0000,
+	}, {
+		/* --- end of list --- */
+	}
+};
+
+MODULE_DEVICE_TABLE(pci, cx25821_pci_tbl);
+
+static struct pci_driver cx25821_pci_driver = {
+	.name = "cx25821",
+	.id_table = cx25821_pci_tbl,
+	.probe = cx25821_initdev,
+	.remove = __devexit_p(cx25821_finidev),
+	/* TODO */
+	.suspend = NULL,
+	.resume = NULL,
+};
+
+static int __init cx25821_init(void)
+{
+	pr_info("driver version %d.%d.%d loaded\n",
+		(CX25821_VERSION_CODE >> 16) & 0xff,
+		(CX25821_VERSION_CODE >> 8) & 0xff,
+		CX25821_VERSION_CODE & 0xff);
+	return pci_register_driver(&cx25821_pci_driver);
+}
+
+static void __exit cx25821_fini(void)
+{
+	pci_unregister_driver(&cx25821_pci_driver);
+}
+
+module_init(cx25821_init);
+module_exit(cx25821_fini);
diff --git a/drivers/media/pci/cx25821/cx25821-gpio.c b/drivers/media/pci/cx25821/cx25821-gpio.c
new file mode 100644
index 0000000..29e43b0
--- /dev/null
+++ b/drivers/media/pci/cx25821/cx25821-gpio.c
@@ -0,0 +1,98 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "cx25821.h"
+
+/********************* GPIO stuffs *********************/
+void cx25821_set_gpiopin_direction(struct cx25821_dev *dev,
+				   int pin_number, int pin_logic_value)
+{
+	int bit = pin_number;
+	u32 gpio_oe_reg = GPIO_LO_OE;
+	u32 gpio_register = 0;
+	u32 value = 0;
+
+	/* Check for valid pinNumber */
+	if (pin_number >= 47)
+		return;
+
+	if (pin_number > 31) {
+		bit = pin_number - 31;
+		gpio_oe_reg = GPIO_HI_OE;
+	}
+	/* Here we will make sure that the GPIOs 0 and 1 are output. keep the
+	 * rest as is */
+	gpio_register = cx_read(gpio_oe_reg);
+
+	if (pin_logic_value == 1)
+		value = gpio_register | Set_GPIO_Bit(bit);
+	else
+		value = gpio_register & Clear_GPIO_Bit(bit);
+
+	cx_write(gpio_oe_reg, value);
+}
+EXPORT_SYMBOL(cx25821_set_gpiopin_direction);
+
+static void cx25821_set_gpiopin_logicvalue(struct cx25821_dev *dev,
+					   int pin_number, int pin_logic_value)
+{
+	int bit = pin_number;
+	u32 gpio_reg = GPIO_LO;
+	u32 value = 0;
+
+	/* Check for valid pinNumber */
+	if (pin_number >= 47)
+		return;
+
+	/* change to output direction */
+	cx25821_set_gpiopin_direction(dev, pin_number, 0);
+
+	if (pin_number > 31) {
+		bit = pin_number - 31;
+		gpio_reg = GPIO_HI;
+	}
+
+	value = cx_read(gpio_reg);
+
+	if (pin_logic_value == 0)
+		value &= Clear_GPIO_Bit(bit);
+	else
+		value |= Set_GPIO_Bit(bit);
+
+	cx_write(gpio_reg, value);
+}
+
+void cx25821_gpio_init(struct cx25821_dev *dev)
+{
+	if (dev == NULL)
+		return;
+
+	switch (dev->board) {
+	case CX25821_BOARD_CONEXANT_ATHENA10:
+	default:
+		/* set GPIO 5 to select the path for Medusa/Athena */
+		cx25821_set_gpiopin_logicvalue(dev, 5, 1);
+		mdelay(20);
+		break;
+	}
+
+}
diff --git a/drivers/media/pci/cx25821/cx25821-i2c.c b/drivers/media/pci/cx25821/cx25821-i2c.c
new file mode 100644
index 0000000..9844549
--- /dev/null
+++ b/drivers/media/pci/cx25821/cx25821-i2c.c
@@ -0,0 +1,416 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ *	Based on Steven Toth <stoth@linuxtv.org> cx23885 driver
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include "cx25821.h"
+#include <linux/i2c.h>
+
+static unsigned int i2c_debug;
+module_param(i2c_debug, int, 0644);
+MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
+
+static unsigned int i2c_scan;
+module_param(i2c_scan, int, 0444);
+MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time");
+
+#define dprintk(level, fmt, arg...)					\
+do {									\
+	if (i2c_debug >= level)						\
+		printk(KERN_DEBUG "%s/0: " fmt, dev->name, ##arg);	\
+} while (0)
+
+#define I2C_WAIT_DELAY 32
+#define I2C_WAIT_RETRY 64
+
+#define I2C_EXTEND  (1 << 3)
+#define I2C_NOSTOP  (1 << 4)
+
+static inline int i2c_slave_did_ack(struct i2c_adapter *i2c_adap)
+{
+	struct cx25821_i2c *bus = i2c_adap->algo_data;
+	struct cx25821_dev *dev = bus->dev;
+	return cx_read(bus->reg_stat) & 0x01;
+}
+
+static inline int i2c_is_busy(struct i2c_adapter *i2c_adap)
+{
+	struct cx25821_i2c *bus = i2c_adap->algo_data;
+	struct cx25821_dev *dev = bus->dev;
+	return cx_read(bus->reg_stat) & 0x02 ? 1 : 0;
+}
+
+static int i2c_wait_done(struct i2c_adapter *i2c_adap)
+{
+	int count;
+
+	for (count = 0; count < I2C_WAIT_RETRY; count++) {
+		if (!i2c_is_busy(i2c_adap))
+			break;
+		udelay(I2C_WAIT_DELAY);
+	}
+
+	if (I2C_WAIT_RETRY == count)
+		return 0;
+
+	return 1;
+}
+
+static int i2c_sendbytes(struct i2c_adapter *i2c_adap,
+			 const struct i2c_msg *msg, int joined_rlen)
+{
+	struct cx25821_i2c *bus = i2c_adap->algo_data;
+	struct cx25821_dev *dev = bus->dev;
+	u32 wdata, addr, ctrl;
+	int retval, cnt;
+
+	if (joined_rlen)
+		dprintk(1, "%s(msg->wlen=%d, nextmsg->rlen=%d)\n", __func__,
+			msg->len, joined_rlen);
+	else
+		dprintk(1, "%s(msg->len=%d)\n", __func__, msg->len);
+
+	/* Deal with i2c probe functions with zero payload */
+	if (msg->len == 0) {
+		cx_write(bus->reg_addr, msg->addr << 25);
+		cx_write(bus->reg_ctrl, bus->i2c_period | (1 << 2));
+
+		if (!i2c_wait_done(i2c_adap))
+			return -EIO;
+
+		if (!i2c_slave_did_ack(i2c_adap))
+			return -EIO;
+
+		dprintk(1, "%s(): returns 0\n", __func__);
+		return 0;
+	}
+
+	/* dev, reg + first byte */
+	addr = (msg->addr << 25) | msg->buf[0];
+	wdata = msg->buf[0];
+
+	ctrl = bus->i2c_period | (1 << 12) | (1 << 2);
+
+	if (msg->len > 1)
+		ctrl |= I2C_NOSTOP | I2C_EXTEND;
+	else if (joined_rlen)
+		ctrl |= I2C_NOSTOP;
+
+	cx_write(bus->reg_addr, addr);
+	cx_write(bus->reg_wdata, wdata);
+	cx_write(bus->reg_ctrl, ctrl);
+
+	retval = i2c_wait_done(i2c_adap);
+	if (retval < 0)
+		goto err;
+
+	if (retval == 0)
+		goto eio;
+
+	if (i2c_debug) {
+		if (!(ctrl & I2C_NOSTOP))
+			printk(" >\n");
+	}
+
+	for (cnt = 1; cnt < msg->len; cnt++) {
+		/* following bytes */
+		wdata = msg->buf[cnt];
+		ctrl = bus->i2c_period | (1 << 12) | (1 << 2);
+
+		if (cnt < msg->len - 1)
+			ctrl |= I2C_NOSTOP | I2C_EXTEND;
+		else if (joined_rlen)
+			ctrl |= I2C_NOSTOP;
+
+		cx_write(bus->reg_addr, addr);
+		cx_write(bus->reg_wdata, wdata);
+		cx_write(bus->reg_ctrl, ctrl);
+
+		retval = i2c_wait_done(i2c_adap);
+		if (retval < 0)
+			goto err;
+
+		if (retval == 0)
+			goto eio;
+
+		if (i2c_debug) {
+			dprintk(1, " %02x", msg->buf[cnt]);
+			if (!(ctrl & I2C_NOSTOP))
+				dprintk(1, " >\n");
+		}
+	}
+
+	return msg->len;
+
+eio:
+	retval = -EIO;
+err:
+	if (i2c_debug)
+		pr_err(" ERR: %d\n", retval);
+	return retval;
+}
+
+static int i2c_readbytes(struct i2c_adapter *i2c_adap,
+			 const struct i2c_msg *msg, int joined)
+{
+	struct cx25821_i2c *bus = i2c_adap->algo_data;
+	struct cx25821_dev *dev = bus->dev;
+	u32 ctrl, cnt;
+	int retval;
+
+	if (i2c_debug && !joined)
+		dprintk(1, "6-%s(msg->len=%d)\n", __func__, msg->len);
+
+	/* Deal with i2c probe functions with zero payload */
+	if (msg->len == 0) {
+		cx_write(bus->reg_addr, msg->addr << 25);
+		cx_write(bus->reg_ctrl, bus->i2c_period | (1 << 2) | 1);
+		if (!i2c_wait_done(i2c_adap))
+			return -EIO;
+		if (!i2c_slave_did_ack(i2c_adap))
+			return -EIO;
+
+		dprintk(1, "%s(): returns 0\n", __func__);
+		return 0;
+	}
+
+	if (i2c_debug) {
+		if (joined)
+			dprintk(1, " R");
+		else
+			dprintk(1, " <R %02x", (msg->addr << 1) + 1);
+	}
+
+	for (cnt = 0; cnt < msg->len; cnt++) {
+
+		ctrl = bus->i2c_period | (1 << 12) | (1 << 2) | 1;
+
+		if (cnt < msg->len - 1)
+			ctrl |= I2C_NOSTOP | I2C_EXTEND;
+
+		cx_write(bus->reg_addr, msg->addr << 25);
+		cx_write(bus->reg_ctrl, ctrl);
+
+		retval = i2c_wait_done(i2c_adap);
+		if (retval < 0)
+			goto err;
+		if (retval == 0)
+			goto eio;
+		msg->buf[cnt] = cx_read(bus->reg_rdata) & 0xff;
+
+		if (i2c_debug) {
+			dprintk(1, " %02x", msg->buf[cnt]);
+			if (!(ctrl & I2C_NOSTOP))
+				dprintk(1, " >\n");
+		}
+	}
+
+	return msg->len;
+eio:
+	retval = -EIO;
+err:
+	if (i2c_debug)
+		pr_err(" ERR: %d\n", retval);
+	return retval;
+}
+
+static int i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
+{
+	struct cx25821_i2c *bus = i2c_adap->algo_data;
+	struct cx25821_dev *dev = bus->dev;
+	int i, retval = 0;
+
+	dprintk(1, "%s(num = %d)\n", __func__, num);
+
+	for (i = 0; i < num; i++) {
+		dprintk(1, "%s(num = %d) addr = 0x%02x  len = 0x%x\n",
+			__func__, num, msgs[i].addr, msgs[i].len);
+
+		if (msgs[i].flags & I2C_M_RD) {
+			/* read */
+			retval = i2c_readbytes(i2c_adap, &msgs[i], 0);
+		} else if (i + 1 < num && (msgs[i + 1].flags & I2C_M_RD) &&
+			   msgs[i].addr == msgs[i + 1].addr) {
+			/* write then read from same address */
+			retval = i2c_sendbytes(i2c_adap, &msgs[i],
+					msgs[i + 1].len);
+
+			if (retval < 0)
+				goto err;
+			i++;
+			retval = i2c_readbytes(i2c_adap, &msgs[i], 1);
+		} else {
+			/* write */
+			retval = i2c_sendbytes(i2c_adap, &msgs[i], 0);
+		}
+
+		if (retval < 0)
+			goto err;
+	}
+	return num;
+
+err:
+	return retval;
+}
+
+
+static u32 cx25821_functionality(struct i2c_adapter *adap)
+{
+	return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C | I2C_FUNC_SMBUS_WORD_DATA |
+		I2C_FUNC_SMBUS_READ_WORD_DATA | I2C_FUNC_SMBUS_WRITE_WORD_DATA;
+}
+
+static struct i2c_algorithm cx25821_i2c_algo_template = {
+	.master_xfer = i2c_xfer,
+	.functionality = cx25821_functionality,
+#ifdef NEED_ALGO_CONTROL
+	.algo_control = dummy_algo_control,
+#endif
+};
+
+static struct i2c_adapter cx25821_i2c_adap_template = {
+	.name = "cx25821",
+	.owner = THIS_MODULE,
+	.algo = &cx25821_i2c_algo_template,
+};
+
+static struct i2c_client cx25821_i2c_client_template = {
+	.name = "cx25821 internal",
+};
+
+/* init + register i2c adapter */
+int cx25821_i2c_register(struct cx25821_i2c *bus)
+{
+	struct cx25821_dev *dev = bus->dev;
+
+	dprintk(1, "%s(bus = %d)\n", __func__, bus->nr);
+
+	bus->i2c_adap = cx25821_i2c_adap_template;
+	bus->i2c_client = cx25821_i2c_client_template;
+	bus->i2c_adap.dev.parent = &dev->pci->dev;
+
+	strlcpy(bus->i2c_adap.name, bus->dev->name, sizeof(bus->i2c_adap.name));
+
+	bus->i2c_adap.algo_data = bus;
+	i2c_set_adapdata(&bus->i2c_adap, &dev->v4l2_dev);
+	i2c_add_adapter(&bus->i2c_adap);
+
+	bus->i2c_client.adapter = &bus->i2c_adap;
+
+	/* set up the I2c */
+	bus->i2c_client.addr = (0x88 >> 1);
+
+	return bus->i2c_rc;
+}
+
+int cx25821_i2c_unregister(struct cx25821_i2c *bus)
+{
+	i2c_del_adapter(&bus->i2c_adap);
+	return 0;
+}
+
+void cx25821_av_clk(struct cx25821_dev *dev, int enable)
+{
+	/* write 0 to bus 2 addr 0x144 via i2x_xfer() */
+	char buffer[3];
+	struct i2c_msg msg;
+	dprintk(1, "%s(enabled = %d)\n", __func__, enable);
+
+	/* Register 0x144 */
+	buffer[0] = 0x01;
+	buffer[1] = 0x44;
+	if (enable == 1)
+		buffer[2] = 0x05;
+	else
+		buffer[2] = 0x00;
+
+	msg.addr = 0x44;
+	msg.flags = I2C_M_TEN;
+	msg.len = 3;
+	msg.buf = buffer;
+
+	i2c_xfer(&dev->i2c_bus[0].i2c_adap, &msg, 1);
+}
+
+int cx25821_i2c_read(struct cx25821_i2c *bus, u16 reg_addr, int *value)
+{
+	struct i2c_client *client = &bus->i2c_client;
+	int v = 0;
+	u8 addr[2] = { 0, 0 };
+	u8 buf[4] = { 0, 0, 0, 0 };
+
+	struct i2c_msg msgs[2] = {
+		{
+			.addr = client->addr,
+			.flags = 0,
+			.len = 2,
+			.buf = addr,
+		}, {
+			.addr = client->addr,
+			.flags = I2C_M_RD,
+			.len = 4,
+			.buf = buf,
+		}
+	};
+
+	addr[0] = (reg_addr >> 8);
+	addr[1] = (reg_addr & 0xff);
+	msgs[0].addr = 0x44;
+	msgs[1].addr = 0x44;
+
+	i2c_xfer(client->adapter, msgs, 2);
+
+	v = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
+	*value = v;
+
+	return v;
+}
+
+int cx25821_i2c_write(struct cx25821_i2c *bus, u16 reg_addr, int value)
+{
+	struct i2c_client *client = &bus->i2c_client;
+	int retval = 0;
+	u8 buf[6] = { 0, 0, 0, 0, 0, 0 };
+
+	struct i2c_msg msgs[1] = {
+		{
+			.addr = client->addr,
+			.flags = 0,
+			.len = 6,
+			.buf = buf,
+		}
+	};
+
+	buf[0] = reg_addr >> 8;
+	buf[1] = reg_addr & 0xff;
+	buf[5] = (value >> 24) & 0xff;
+	buf[4] = (value >> 16) & 0xff;
+	buf[3] = (value >> 8) & 0xff;
+	buf[2] = value & 0xff;
+	client->flags = 0;
+	msgs[0].addr = 0x44;
+
+	retval = i2c_xfer(client->adapter, msgs, 1);
+
+	return retval;
+}
diff --git a/drivers/media/pci/cx25821/cx25821-medusa-defines.h b/drivers/media/pci/cx25821/cx25821-medusa-defines.h
new file mode 100644
index 0000000..7a9e647
--- /dev/null
+++ b/drivers/media/pci/cx25821/cx25821-medusa-defines.h
@@ -0,0 +1,42 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _MEDUSA_DEF_H_
+#define _MEDUSA_DEF_H_
+
+/* Video decoder that we supported */
+#define VDEC_A		0
+#define VDEC_B		1
+#define VDEC_C		2
+#define VDEC_D		3
+#define VDEC_E		4
+#define VDEC_F		5
+#define VDEC_G		6
+#define VDEC_H		7
+
+/* end of display sequence */
+#define END_OF_SEQ	0xF;
+
+/* registry string size */
+#define MAX_REGISTRY_SZ	40;
+
+#endif
diff --git a/drivers/media/pci/cx25821/cx25821-medusa-reg.h b/drivers/media/pci/cx25821/cx25821-medusa-reg.h
new file mode 100644
index 0000000..c98ac94
--- /dev/null
+++ b/drivers/media/pci/cx25821/cx25821-medusa-reg.h
@@ -0,0 +1,455 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __MEDUSA_REGISTERS__
+#define __MEDUSA_REGISTERS__
+
+/* Serial Slave Registers */
+#define	HOST_REGISTER1				0x0000
+#define	HOST_REGISTER2				0x0001
+
+/* Chip Configuration Registers */
+#define	CHIP_CTRL				0x0100
+#define	AFE_AB_CTRL				0x0104
+#define	AFE_CD_CTRL				0x0108
+#define	AFE_EF_CTRL				0x010C
+#define	AFE_GH_CTRL				0x0110
+#define	DENC_AB_CTRL				0x0114
+#define	BYP_AB_CTRL				0x0118
+#define	MON_A_CTRL				0x011C
+#define	DISP_SEQ_A				0x0120
+#define	DISP_SEQ_B				0x0124
+#define	DISP_AB_CNT				0x0128
+#define	DISP_CD_CNT				0x012C
+#define	DISP_EF_CNT				0x0130
+#define	DISP_GH_CNT				0x0134
+#define	DISP_IJ_CNT				0x0138
+#define	PIN_OE_CTRL				0x013C
+#define	PIN_SPD_CTRL				0x0140
+#define	PIN_SPD_CTRL2				0x0144
+#define	IRQ_STAT_CTRL				0x0148
+#define	POWER_CTRL_AB				0x014C
+#define	POWER_CTRL_CD				0x0150
+#define	POWER_CTRL_EF				0x0154
+#define	POWER_CTRL_GH				0x0158
+#define	TUNE_CTRL				0x015C
+#define	BIAS_CTRL				0x0160
+#define	AFE_AB_DIAG_CTRL			0x0164
+#define	AFE_CD_DIAG_CTRL			0x0168
+#define	AFE_EF_DIAG_CTRL			0x016C
+#define	AFE_GH_DIAG_CTRL			0x0170
+#define	PLL_AB_DIAG_CTRL			0x0174
+#define	PLL_CD_DIAG_CTRL			0x0178
+#define	PLL_EF_DIAG_CTRL			0x017C
+#define	PLL_GH_DIAG_CTRL			0x0180
+#define	TEST_CTRL				0x0184
+#define	BIST_STAT				0x0188
+#define	BIST_STAT2				0x018C
+#define	BIST_VID_PLL_AB_STAT			0x0190
+#define	BIST_VID_PLL_CD_STAT			0x0194
+#define	BIST_VID_PLL_EF_STAT			0x0198
+#define	BIST_VID_PLL_GH_STAT			0x019C
+#define	DLL_DIAG_CTRL				0x01A0
+#define	DEV_CH_ID_CTRL				0x01A4
+#define	ABIST_CTRL_STATUS			0x01A8
+#define	ABIST_FREQ				0x01AC
+#define	ABIST_GOERT_SHIFT			0x01B0
+#define	ABIST_COEF12				0x01B4
+#define	ABIST_COEF34				0x01B8
+#define	ABIST_COEF56				0x01BC
+#define	ABIST_COEF7_SNR				0x01C0
+#define	ABIST_ADC_CAL				0x01C4
+#define	ABIST_BIN1_VGA0				0x01C8
+#define	ABIST_BIN2_VGA1				0x01CC
+#define	ABIST_BIN3_VGA2				0x01D0
+#define	ABIST_BIN4_VGA3				0x01D4
+#define	ABIST_BIN5_VGA4				0x01D8
+#define	ABIST_BIN6_VGA5				0x01DC
+#define	ABIST_BIN7_VGA6				0x0x1E0
+#define	ABIST_CLAMP_A				0x0x1E4
+#define	ABIST_CLAMP_B				0x0x1E8
+#define	ABIST_CLAMP_C				0x01EC
+#define	ABIST_CLAMP_D				0x01F0
+#define	ABIST_CLAMP_E				0x01F4
+#define	ABIST_CLAMP_F				0x01F8
+
+/* Digital Video Encoder A Registers */
+#define	DENC_A_REG_1				0x0200
+#define	DENC_A_REG_2				0x0204
+#define	DENC_A_REG_3				0x0208
+#define	DENC_A_REG_4				0x020C
+#define	DENC_A_REG_5				0x0210
+#define	DENC_A_REG_6				0x0214
+#define	DENC_A_REG_7				0x0218
+#define	DENC_A_REG_8				0x021C
+
+/* Digital Video Encoder B Registers */
+#define	DENC_B_REG_1				0x0300
+#define	DENC_B_REG_2				0x0304
+#define	DENC_B_REG_3				0x0308
+#define	DENC_B_REG_4				0x030C
+#define	DENC_B_REG_5				0x0310
+#define	DENC_B_REG_6				0x0314
+#define	DENC_B_REG_7				0x0318
+#define	DENC_B_REG_8				0x031C
+
+/* Video Decoder A Registers */
+#define	MODE_CTRL				0x1000
+#define	OUT_CTRL1				0x1004
+#define	OUT_CTRL_NS				0x1008
+#define	GEN_STAT				0x100C
+#define	INT_STAT_MASK				0x1010
+#define	LUMA_CTRL				0x1014
+#define	CHROMA_CTRL				0x1018
+#define	CRUSH_CTRL				0x101C
+#define	HORIZ_TIM_CTRL				0x1020
+#define	VERT_TIM_CTRL				0x1024
+#define	MISC_TIM_CTRL				0x1028
+#define	FIELD_COUNT				0x102C
+#define	HSCALE_CTRL				0x1030
+#define	VSCALE_CTRL				0x1034
+#define	MAN_VGA_CTRL				0x1038
+#define	MAN_AGC_CTRL				0x103C
+#define	DFE_CTRL1				0x1040
+#define	DFE_CTRL2				0x1044
+#define	DFE_CTRL3				0x1048
+#define	PLL_CTRL				0x104C
+#define	PLL_CTRL_FAST				0x1050
+#define	HTL_CTRL				0x1054
+#define	SRC_CFG					0x1058
+#define	SC_STEP_SIZE				0x105C
+#define	SC_CONVERGE_CTRL			0x1060
+#define	SC_LOOP_CTRL				0x1064
+#define	COMB_2D_HFS_CFG				0x1068
+#define	COMB_2D_HFD_CFG				0x106C
+#define	COMB_2D_LF_CFG				0x1070
+#define	COMB_2D_BLEND				0x1074
+#define	COMB_MISC_CTRL				0x1078
+#define	COMB_FLAT_THRESH_CTRL			0x107C
+#define	COMB_TEST				0x1080
+#define	BP_MISC_CTRL				0x1084
+#define	VCR_DET_CTRL				0x1088
+#define	NOISE_DET_CTRL				0x108C
+#define	COMB_FLAT_NOISE_CTRL			0x1090
+#define	VERSION					0x11F8
+#define	SOFT_RST_CTRL				0x11FC
+
+/* Video Decoder B Registers */
+#define	VDEC_B_MODE_CTRL			0x1200
+#define	VDEC_B_OUT_CTRL1			0x1204
+#define	VDEC_B_OUT_CTRL_NS			0x1208
+#define	VDEC_B_GEN_STAT				0x120C
+#define	VDEC_B_INT_STAT_MASK			0x1210
+#define	VDEC_B_LUMA_CTRL			0x1214
+#define	VDEC_B_CHROMA_CTRL			0x1218
+#define	VDEC_B_CRUSH_CTRL			0x121C
+#define	VDEC_B_HORIZ_TIM_CTRL			0x1220
+#define	VDEC_B_VERT_TIM_CTRL			0x1224
+#define	VDEC_B_MISC_TIM_CTRL			0x1228
+#define	VDEC_B_FIELD_COUNT			0x122C
+#define	VDEC_B_HSCALE_CTRL			0x1230
+#define	VDEC_B_VSCALE_CTRL			0x1234
+#define	VDEC_B_MAN_VGA_CTRL			0x1238
+#define	VDEC_B_MAN_AGC_CTRL			0x123C
+#define	VDEC_B_DFE_CTRL1			0x1240
+#define	VDEC_B_DFE_CTRL2			0x1244
+#define	VDEC_B_DFE_CTRL3			0x1248
+#define	VDEC_B_PLL_CTRL				0x124C
+#define	VDEC_B_PLL_CTRL_FAST			0x1250
+#define	VDEC_B_HTL_CTRL				0x1254
+#define	VDEC_B_SRC_CFG				0x1258
+#define	VDEC_B_SC_STEP_SIZE			0x125C
+#define	VDEC_B_SC_CONVERGE_CTRL			0x1260
+#define	VDEC_B_SC_LOOP_CTRL			0x1264
+#define	VDEC_B_COMB_2D_HFS_CFG			0x1268
+#define	VDEC_B_COMB_2D_HFD_CFG			0x126C
+#define	VDEC_B_COMB_2D_LF_CFG			0x1270
+#define	VDEC_B_COMB_2D_BLEND			0x1274
+#define	VDEC_B_COMB_MISC_CTRL			0x1278
+#define	VDEC_B_COMB_FLAT_THRESH_CTRL		0x127C
+#define	VDEC_B_COMB_TEST			0x1280
+#define	VDEC_B_BP_MISC_CTRL			0x1284
+#define	VDEC_B_VCR_DET_CTRL			0x1288
+#define	VDEC_B_NOISE_DET_CTRL			0x128C
+#define	VDEC_B_COMB_FLAT_NOISE_CTRL		0x1290
+#define	VDEC_B_VERSION				0x13F8
+#define	VDEC_B_SOFT_RST_CTRL			0x13FC
+
+/* Video Decoder C Registers */
+#define	VDEC_C_MODE_CTRL			0x1400
+#define	VDEC_C_OUT_CTRL1			0x1404
+#define	VDEC_C_OUT_CTRL_NS			0x1408
+#define	VDEC_C_GEN_STAT				0x140C
+#define	VDEC_C_INT_STAT_MASK			0x1410
+#define VDEC_C_LUMA_CTRL			0x1414
+#define VDEC_C_CHROMA_CTRL			0x1418
+#define	VDEC_C_CRUSH_CTRL			0x141C
+#define	VDEC_C_HORIZ_TIM_CTRL			0x1420
+#define	VDEC_C_VERT_TIM_CTRL			0x1424
+#define	VDEC_C_MISC_TIM_CTRL			0x1428
+#define	VDEC_C_FIELD_COUNT			0x142C
+#define	VDEC_C_HSCALE_CTRL			0x1430
+#define	VDEC_C_VSCALE_CTRL			0x1434
+#define	VDEC_C_MAN_VGA_CTRL			0x1438
+#define	VDEC_C_MAN_AGC_CTRL			0x143C
+#define	VDEC_C_DFE_CTRL1			0x1440
+#define	VDEC_C_DFE_CTRL2			0x1444
+#define	VDEC_C_DFE_CTRL3			0x1448
+#define	VDEC_C_PLL_CTRL				0x144C
+#define	VDEC_C_PLL_CTRL_FAST			0x1450
+#define	VDEC_C_HTL_CTRL				0x1454
+#define	VDEC_C_SRC_CFG				0x1458
+#define	VDEC_C_SC_STEP_SIZE			0x145C
+#define	VDEC_C_SC_CONVERGE_CTRL			0x1460
+#define	VDEC_C_SC_LOOP_CTRL			0x1464
+#define	VDEC_C_COMB_2D_HFS_CFG			0x1468
+#define	VDEC_C_COMB_2D_HFD_CFG			0x146C
+#define	VDEC_C_COMB_2D_LF_CFG			0x1470
+#define	VDEC_C_COMB_2D_BLEND			0x1474
+#define	VDEC_C_COMB_MISC_CTRL			0x1478
+#define	VDEC_C_COMB_FLAT_THRESH_CTRL		0x147C
+#define	VDEC_C_COMB_TEST			0x1480
+#define	VDEC_C_BP_MISC_CTRL			0x1484
+#define	VDEC_C_VCR_DET_CTRL			0x1488
+#define	VDEC_C_NOISE_DET_CTRL			0x148C
+#define	VDEC_C_COMB_FLAT_NOISE_CTRL		0x1490
+#define	VDEC_C_VERSION				0x15F8
+#define	VDEC_C_SOFT_RST_CTRL			0x15FC
+
+/* Video Decoder D Registers */
+#define VDEC_D_MODE_CTRL			0x1600
+#define VDEC_D_OUT_CTRL1			0x1604
+#define VDEC_D_OUT_CTRL_NS			0x1608
+#define VDEC_D_GEN_STAT				0x160C
+#define VDEC_D_INT_STAT_MASK			0x1610
+#define VDEC_D_LUMA_CTRL			0x1614
+#define VDEC_D_CHROMA_CTRL			0x1618
+#define VDEC_D_CRUSH_CTRL			0x161C
+#define VDEC_D_HORIZ_TIM_CTRL			0x1620
+#define VDEC_D_VERT_TIM_CTRL			0x1624
+#define VDEC_D_MISC_TIM_CTRL			0x1628
+#define VDEC_D_FIELD_COUNT			0x162C
+#define VDEC_D_HSCALE_CTRL			0x1630
+#define VDEC_D_VSCALE_CTRL			0x1634
+#define VDEC_D_MAN_VGA_CTRL			0x1638
+#define VDEC_D_MAN_AGC_CTRL			0x163C
+#define VDEC_D_DFE_CTRL1			0x1640
+#define VDEC_D_DFE_CTRL2			0x1644
+#define VDEC_D_DFE_CTRL3			0x1648
+#define VDEC_D_PLL_CTRL				0x164C
+#define VDEC_D_PLL_CTRL_FAST			0x1650
+#define VDEC_D_HTL_CTRL				0x1654
+#define VDEC_D_SRC_CFG				0x1658
+#define VDEC_D_SC_STEP_SIZE			0x165C
+#define VDEC_D_SC_CONVERGE_CTRL			0x1660
+#define VDEC_D_SC_LOOP_CTRL			0x1664
+#define VDEC_D_COMB_2D_HFS_CFG			0x1668
+#define VDEC_D_COMB_2D_HFD_CFG			0x166C
+#define VDEC_D_COMB_2D_LF_CFG			0x1670
+#define VDEC_D_COMB_2D_BLEND			0x1674
+#define VDEC_D_COMB_MISC_CTRL			0x1678
+#define VDEC_D_COMB_FLAT_THRESH_CTRL		0x167C
+#define VDEC_D_COMB_TEST			0x1680
+#define VDEC_D_BP_MISC_CTRL			0x1684
+#define VDEC_D_VCR_DET_CTRL			0x1688
+#define VDEC_D_NOISE_DET_CTRL			0x168C
+#define VDEC_D_COMB_FLAT_NOISE_CTRL		0x1690
+#define VDEC_D_VERSION				0x17F8
+#define VDEC_D_SOFT_RST_CTRL			0x17FC
+
+/* Video Decoder E Registers */
+#define	VDEC_E_MODE_CTRL			0x1800
+#define	VDEC_E_OUT_CTRL1			0x1804
+#define	VDEC_E_OUT_CTRL_NS			0x1808
+#define	VDEC_E_GEN_STAT				0x180C
+#define	VDEC_E_INT_STAT_MASK			0x1810
+#define	VDEC_E_LUMA_CTRL			0x1814
+#define	VDEC_E_CHROMA_CTRL			0x1818
+#define	VDEC_E_CRUSH_CTRL			0x181C
+#define	VDEC_E_HORIZ_TIM_CTRL			0x1820
+#define	VDEC_E_VERT_TIM_CTRL			0x1824
+#define	VDEC_E_MISC_TIM_CTRL			0x1828
+#define	VDEC_E_FIELD_COUNT			0x182C
+#define	VDEC_E_HSCALE_CTRL			0x1830
+#define	VDEC_E_VSCALE_CTRL			0x1834
+#define	VDEC_E_MAN_VGA_CTRL			0x1838
+#define	VDEC_E_MAN_AGC_CTRL			0x183C
+#define	VDEC_E_DFE_CTRL1			0x1840
+#define	VDEC_E_DFE_CTRL2			0x1844
+#define	VDEC_E_DFE_CTRL3			0x1848
+#define	VDEC_E_PLL_CTRL				0x184C
+#define	VDEC_E_PLL_CTRL_FAST			0x1850
+#define	VDEC_E_HTL_CTRL				0x1854
+#define	VDEC_E_SRC_CFG				0x1858
+#define	VDEC_E_SC_STEP_SIZE			0x185C
+#define	VDEC_E_SC_CONVERGE_CTRL			0x1860
+#define	VDEC_E_SC_LOOP_CTRL			0x1864
+#define	VDEC_E_COMB_2D_HFS_CFG			0x1868
+#define	VDEC_E_COMB_2D_HFD_CFG			0x186C
+#define	VDEC_E_COMB_2D_LF_CFG			0x1870
+#define	VDEC_E_COMB_2D_BLEND			0x1874
+#define	VDEC_E_COMB_MISC_CTRL			0x1878
+#define	VDEC_E_COMB_FLAT_THRESH_CTRL		0x187C
+#define	VDEC_E_COMB_TEST			0x1880
+#define	VDEC_E_BP_MISC_CTRL			0x1884
+#define	VDEC_E_VCR_DET_CTRL			0x1888
+#define	VDEC_E_NOISE_DET_CTRL			0x188C
+#define	VDEC_E_COMB_FLAT_NOISE_CTRL		0x1890
+#define	VDEC_E_VERSION				0x19F8
+#define	VDEC_E_SOFT_RST_CTRL			0x19FC
+
+/* Video Decoder F Registers */
+#define	VDEC_F_MODE_CTRL			0x1A00
+#define	VDEC_F_OUT_CTRL1			0x1A04
+#define	VDEC_F_OUT_CTRL_NS			0x1A08
+#define	VDEC_F_GEN_STAT				0x1A0C
+#define	VDEC_F_INT_STAT_MASK			0x1A10
+#define	VDEC_F_LUMA_CTRL			0x1A14
+#define	VDEC_F_CHROMA_CTRL			0x1A18
+#define	VDEC_F_CRUSH_CTRL			0x1A1C
+#define	VDEC_F_HORIZ_TIM_CTRL			0x1A20
+#define	VDEC_F_VERT_TIM_CTRL			0x1A24
+#define	VDEC_F_MISC_TIM_CTRL			0x1A28
+#define	VDEC_F_FIELD_COUNT			0x1A2C
+#define	VDEC_F_HSCALE_CTRL			0x1A30
+#define	VDEC_F_VSCALE_CTRL			0x1A34
+#define	VDEC_F_MAN_VGA_CTRL			0x1A38
+#define	VDEC_F_MAN_AGC_CTRL			0x1A3C
+#define	VDEC_F_DFE_CTRL1			0x1A40
+#define	VDEC_F_DFE_CTRL2			0x1A44
+#define	VDEC_F_DFE_CTRL3			0x1A48
+#define	VDEC_F_PLL_CTRL				0x1A4C
+#define	VDEC_F_PLL_CTRL_FAST			0x1A50
+#define	VDEC_F_HTL_CTRL				0x1A54
+#define	VDEC_F_SRC_CFG				0x1A58
+#define	VDEC_F_SC_STEP_SIZE			0x1A5C
+#define	VDEC_F_SC_CONVERGE_CTRL			0x1A60
+#define	VDEC_F_SC_LOOP_CTRL			0x1A64
+#define	VDEC_F_COMB_2D_HFS_CFG			0x1A68
+#define	VDEC_F_COMB_2D_HFD_CFG			0x1A6C
+#define	VDEC_F_COMB_2D_LF_CFG			0x1A70
+#define	VDEC_F_COMB_2D_BLEND			0x1A74
+#define	VDEC_F_COMB_MISC_CTRL			0x1A78
+#define	VDEC_F_COMB_FLAT_THRESH_CTRL		0x1A7C
+#define	VDEC_F_COMB_TEST			0x1A80
+#define	VDEC_F_BP_MISC_CTRL			0x1A84
+#define	VDEC_F_VCR_DET_CTRL			0x1A88
+#define	VDEC_F_NOISE_DET_CTRL			0x1A8C
+#define	VDEC_F_COMB_FLAT_NOISE_CTRL		0x1A90
+#define	VDEC_F_VERSION				0x1BF8
+#define	VDEC_F_SOFT_RST_CTRL			0x1BFC
+
+/* Video Decoder G Registers */
+#define	VDEC_G_MODE_CTRL			0x1C00
+#define	VDEC_G_OUT_CTRL1			0x1C04
+#define	VDEC_G_OUT_CTRL_NS			0x1C08
+#define	VDEC_G_GEN_STAT				0x1C0C
+#define	VDEC_G_INT_STAT_MASK			0x1C10
+#define	VDEC_G_LUMA_CTRL			0x1C14
+#define	VDEC_G_CHROMA_CTRL			0x1C18
+#define	VDEC_G_CRUSH_CTRL			0x1C1C
+#define	VDEC_G_HORIZ_TIM_CTRL			0x1C20
+#define	VDEC_G_VERT_TIM_CTRL			0x1C24
+#define	VDEC_G_MISC_TIM_CTRL			0x1C28
+#define	VDEC_G_FIELD_COUNT			0x1C2C
+#define	VDEC_G_HSCALE_CTRL			0x1C30
+#define	VDEC_G_VSCALE_CTRL			0x1C34
+#define	VDEC_G_MAN_VGA_CTRL			0x1C38
+#define	VDEC_G_MAN_AGC_CTRL			0x1C3C
+#define	VDEC_G_DFE_CTRL1			0x1C40
+#define	VDEC_G_DFE_CTRL2			0x1C44
+#define	VDEC_G_DFE_CTRL3			0x1C48
+#define	VDEC_G_PLL_CTRL				0x1C4C
+#define	VDEC_G_PLL_CTRL_FAST			0x1C50
+#define	VDEC_G_HTL_CTRL				0x1C54
+#define	VDEC_G_SRC_CFG				0x1C58
+#define	VDEC_G_SC_STEP_SIZE			0x1C5C
+#define	VDEC_G_SC_CONVERGE_CTRL			0x1C60
+#define	VDEC_G_SC_LOOP_CTRL			0x1C64
+#define	VDEC_G_COMB_2D_HFS_CFG			0x1C68
+#define	VDEC_G_COMB_2D_HFD_CFG			0x1C6C
+#define	VDEC_G_COMB_2D_LF_CFG			0x1C70
+#define	VDEC_G_COMB_2D_BLEND			0x1C74
+#define	VDEC_G_COMB_MISC_CTRL			0x1C78
+#define	VDEC_G_COMB_FLAT_THRESH_CTRL		0x1C7C
+#define	VDEC_G_COMB_TEST			0x1C80
+#define	VDEC_G_BP_MISC_CTRL			0x1C84
+#define	VDEC_G_VCR_DET_CTRL			0x1C88
+#define	VDEC_G_NOISE_DET_CTRL			0x1C8C
+#define	VDEC_G_COMB_FLAT_NOISE_CTRL		0x1C90
+#define	VDEC_G_VERSION				0x1DF8
+#define	VDEC_G_SOFT_RST_CTRL			0x1DFC
+
+/* Video Decoder H Registers  */
+#define	VDEC_H_MODE_CTRL			0x1E00
+#define	VDEC_H_OUT_CTRL1			0x1E04
+#define	VDEC_H_OUT_CTRL_NS			0x1E08
+#define	VDEC_H_GEN_STAT				0x1E0C
+#define	VDEC_H_INT_STAT_MASK			0x1E1E
+#define	VDEC_H_LUMA_CTRL			0x1E14
+#define	VDEC_H_CHROMA_CTRL			0x1E18
+#define	VDEC_H_CRUSH_CTRL			0x1E1C
+#define	VDEC_H_HORIZ_TIM_CTRL			0x1E20
+#define	VDEC_H_VERT_TIM_CTRL			0x1E24
+#define	VDEC_H_MISC_TIM_CTRL			0x1E28
+#define	VDEC_H_FIELD_COUNT			0x1E2C
+#define	VDEC_H_HSCALE_CTRL			0x1E30
+#define	VDEC_H_VSCALE_CTRL			0x1E34
+#define	VDEC_H_MAN_VGA_CTRL			0x1E38
+#define	VDEC_H_MAN_AGC_CTRL			0x1E3C
+#define	VDEC_H_DFE_CTRL1			0x1E40
+#define	VDEC_H_DFE_CTRL2			0x1E44
+#define	VDEC_H_DFE_CTRL3			0x1E48
+#define	VDEC_H_PLL_CTRL				0x1E4C
+#define	VDEC_H_PLL_CTRL_FAST			0x1E50
+#define	VDEC_H_HTL_CTRL				0x1E54
+#define	VDEC_H_SRC_CFG				0x1E58
+#define	VDEC_H_SC_STEP_SIZE			0x1E5C
+#define	VDEC_H_SC_CONVERGE_CTRL			0x1E60
+#define	VDEC_H_SC_LOOP_CTRL			0x1E64
+#define	VDEC_H_COMB_2D_HFS_CFG			0x1E68
+#define	VDEC_H_COMB_2D_HFD_CFG			0x1E6C
+#define	VDEC_H_COMB_2D_LF_CFG			0x1E70
+#define	VDEC_H_COMB_2D_BLEND			0x1E74
+#define	VDEC_H_COMB_MISC_CTRL			0x1E78
+#define	VDEC_H_COMB_FLAT_THRESH_CTRL		0x1E7C
+#define	VDEC_H_COMB_TEST			0x1E80
+#define	VDEC_H_BP_MISC_CTRL			0x1E84
+#define	VDEC_H_VCR_DET_CTRL			0x1E88
+#define	VDEC_H_NOISE_DET_CTRL			0x1E8C
+#define	VDEC_H_COMB_FLAT_NOISE_CTRL		0x1E90
+#define	VDEC_H_VERSION				0x1FF8
+#define	VDEC_H_SOFT_RST_CTRL			0x1FFC
+
+/*****************************************************************************/
+/* LUMA_CTRL register fields */
+#define VDEC_A_BRITE_CTRL			0x1014
+#define VDEC_A_CNTRST_CTRL			0x1015
+#define VDEC_A_PEAK_SEL				0x1016
+
+/*****************************************************************************/
+/* CHROMA_CTRL register fields */
+#define VDEC_A_USAT_CTRL			0x1018
+#define VDEC_A_VSAT_CTRL			0x1019
+#define VDEC_A_HUE_CTRL				0x101A
+
+#endif
diff --git a/drivers/media/pci/cx25821/cx25821-medusa-video.c b/drivers/media/pci/cx25821/cx25821-medusa-video.c
new file mode 100644
index 0000000..6a92e5c
--- /dev/null
+++ b/drivers/media/pci/cx25821/cx25821-medusa-video.c
@@ -0,0 +1,787 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include "cx25821.h"
+#include "cx25821-medusa-video.h"
+#include "cx25821-biffuncs.h"
+
+/*
+ * medusa_enable_bluefield_output()
+ *
+ * Enable the generation of blue filed output if no video
+ *
+ */
+static void medusa_enable_bluefield_output(struct cx25821_dev *dev, int channel,
+					   int enable)
+{
+	u32 value = 0;
+	u32 tmp = 0;
+	int out_ctrl = OUT_CTRL1;
+	int out_ctrl_ns = OUT_CTRL_NS;
+
+	switch (channel) {
+	default:
+	case VDEC_A:
+		break;
+	case VDEC_B:
+		out_ctrl = VDEC_B_OUT_CTRL1;
+		out_ctrl_ns = VDEC_B_OUT_CTRL_NS;
+		break;
+	case VDEC_C:
+		out_ctrl = VDEC_C_OUT_CTRL1;
+		out_ctrl_ns = VDEC_C_OUT_CTRL_NS;
+		break;
+	case VDEC_D:
+		out_ctrl = VDEC_D_OUT_CTRL1;
+		out_ctrl_ns = VDEC_D_OUT_CTRL_NS;
+		break;
+	case VDEC_E:
+		out_ctrl = VDEC_E_OUT_CTRL1;
+		out_ctrl_ns = VDEC_E_OUT_CTRL_NS;
+		return;
+	case VDEC_F:
+		out_ctrl = VDEC_F_OUT_CTRL1;
+		out_ctrl_ns = VDEC_F_OUT_CTRL_NS;
+		return;
+	case VDEC_G:
+		out_ctrl = VDEC_G_OUT_CTRL1;
+		out_ctrl_ns = VDEC_G_OUT_CTRL_NS;
+		return;
+	case VDEC_H:
+		out_ctrl = VDEC_H_OUT_CTRL1;
+		out_ctrl_ns = VDEC_H_OUT_CTRL_NS;
+		return;
+	}
+
+	value = cx25821_i2c_read(&dev->i2c_bus[0], out_ctrl, &tmp);
+	value &= 0xFFFFFF7F;	/* clear BLUE_FIELD_EN */
+	if (enable)
+		value |= 0x00000080;	/* set BLUE_FIELD_EN */
+	cx25821_i2c_write(&dev->i2c_bus[0], out_ctrl, value);
+
+	value = cx25821_i2c_read(&dev->i2c_bus[0], out_ctrl_ns, &tmp);
+	value &= 0xFFFFFF7F;
+	if (enable)
+		value |= 0x00000080;	/* set BLUE_FIELD_EN */
+	cx25821_i2c_write(&dev->i2c_bus[0], out_ctrl_ns, value);
+}
+
+static int medusa_initialize_ntsc(struct cx25821_dev *dev)
+{
+	int ret_val = 0;
+	int i = 0;
+	u32 value = 0;
+	u32 tmp = 0;
+
+	mutex_lock(&dev->lock);
+
+	for (i = 0; i < MAX_DECODERS; i++) {
+		/* set video format NTSC-M */
+		value = cx25821_i2c_read(&dev->i2c_bus[0],
+				MODE_CTRL + (0x200 * i), &tmp);
+		value &= 0xFFFFFFF0;
+		/* enable the fast locking mode bit[16] */
+		value |= 0x10001;
+		ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+				MODE_CTRL + (0x200 * i), value);
+
+		/* resolution NTSC 720x480 */
+		value = cx25821_i2c_read(&dev->i2c_bus[0],
+				HORIZ_TIM_CTRL + (0x200 * i), &tmp);
+		value &= 0x00C00C00;
+		value |= 0x612D0074;
+		ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+				HORIZ_TIM_CTRL + (0x200 * i), value);
+
+		value = cx25821_i2c_read(&dev->i2c_bus[0],
+				VERT_TIM_CTRL + (0x200 * i), &tmp);
+		value &= 0x00C00C00;
+		value |= 0x1C1E001A;	/* vblank_cnt + 2 to get camera ID */
+		ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+				VERT_TIM_CTRL + (0x200 * i), value);
+
+		/* chroma subcarrier step size */
+		ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+				SC_STEP_SIZE + (0x200 * i), 0x43E00000);
+
+		/* enable VIP optional active */
+		value = cx25821_i2c_read(&dev->i2c_bus[0],
+				OUT_CTRL_NS + (0x200 * i), &tmp);
+		value &= 0xFFFBFFFF;
+		value |= 0x00040000;
+		ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+				OUT_CTRL_NS + (0x200 * i), value);
+
+		/* enable VIP optional active (VIP_OPT_AL) for direct output. */
+		value = cx25821_i2c_read(&dev->i2c_bus[0],
+				OUT_CTRL1 + (0x200 * i), &tmp);
+		value &= 0xFFFBFFFF;
+		value |= 0x00040000;
+		ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+				OUT_CTRL1 + (0x200 * i), value);
+
+		/*
+		 * clear VPRES_VERT_EN bit, fixes the chroma run away problem
+		 * when the input switching rate < 16 fields
+		*/
+		value = cx25821_i2c_read(&dev->i2c_bus[0],
+				MISC_TIM_CTRL + (0x200 * i), &tmp);
+		/* disable special play detection */
+		value = setBitAtPos(value, 14);
+		value = clearBitAtPos(value, 15);
+		ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+				MISC_TIM_CTRL + (0x200 * i), value);
+
+		/* set vbi_gate_en to 0 */
+		value = cx25821_i2c_read(&dev->i2c_bus[0],
+				DFE_CTRL1 + (0x200 * i), &tmp);
+		value = clearBitAtPos(value, 29);
+		ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+				DFE_CTRL1 + (0x200 * i), value);
+
+		/* Enable the generation of blue field output if no video */
+		medusa_enable_bluefield_output(dev, i, 1);
+	}
+
+	for (i = 0; i < MAX_ENCODERS; i++) {
+		/* NTSC hclock */
+		value = cx25821_i2c_read(&dev->i2c_bus[0],
+				DENC_A_REG_1 + (0x100 * i), &tmp);
+		value &= 0xF000FC00;
+		value |= 0x06B402D0;
+		ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+				DENC_A_REG_1 + (0x100 * i), value);
+
+		/* burst begin and burst end */
+		value = cx25821_i2c_read(&dev->i2c_bus[0],
+				DENC_A_REG_2 + (0x100 * i), &tmp);
+		value &= 0xFF000000;
+		value |= 0x007E9054;
+		ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+				DENC_A_REG_2 + (0x100 * i), value);
+
+		value = cx25821_i2c_read(&dev->i2c_bus[0],
+				DENC_A_REG_3 + (0x100 * i), &tmp);
+		value &= 0xFC00FE00;
+		value |= 0x00EC00F0;
+		ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+				DENC_A_REG_3 + (0x100 * i), value);
+
+		/* set NTSC vblank, no phase alternation, 7.5 IRE pedestal */
+		value = cx25821_i2c_read(&dev->i2c_bus[0],
+				DENC_A_REG_4 + (0x100 * i), &tmp);
+		value &= 0x00FCFFFF;
+		value |= 0x13020000;
+		ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+				DENC_A_REG_4 + (0x100 * i), value);
+
+		value = cx25821_i2c_read(&dev->i2c_bus[0],
+				DENC_A_REG_5 + (0x100 * i), &tmp);
+		value &= 0xFFFF0000;
+		value |= 0x0000E575;
+		ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+				DENC_A_REG_5 + (0x100 * i), value);
+
+		ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+				DENC_A_REG_6 + (0x100 * i), 0x009A89C1);
+
+		/* Subcarrier Increment */
+		ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+				DENC_A_REG_7 + (0x100 * i), 0x21F07C1F);
+	}
+
+	/* set picture resolutions */
+	/* 0 - 720 */
+	ret_val = cx25821_i2c_write(&dev->i2c_bus[0], HSCALE_CTRL, 0x0);
+	/* 0 - 480 */
+	ret_val = cx25821_i2c_write(&dev->i2c_bus[0], VSCALE_CTRL, 0x0);
+
+	/* set Bypass input format to NTSC 525 lines */
+	value = cx25821_i2c_read(&dev->i2c_bus[0], BYP_AB_CTRL, &tmp);
+	value |= 0x00080200;
+	ret_val = cx25821_i2c_write(&dev->i2c_bus[0], BYP_AB_CTRL, value);
+
+	mutex_unlock(&dev->lock);
+
+	return ret_val;
+}
+
+static int medusa_PALCombInit(struct cx25821_dev *dev, int dec)
+{
+	int ret_val = -1;
+	u32 value = 0, tmp = 0;
+
+	/* Setup for 2D threshold */
+	ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+			COMB_2D_HFS_CFG + (0x200 * dec), 0x20002861);
+	ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+			COMB_2D_HFD_CFG + (0x200 * dec), 0x20002861);
+	ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+			COMB_2D_LF_CFG + (0x200 * dec), 0x200A1023);
+
+	/* Setup flat chroma and luma thresholds */
+	value = cx25821_i2c_read(&dev->i2c_bus[0],
+			COMB_FLAT_THRESH_CTRL + (0x200 * dec), &tmp);
+	value &= 0x06230000;
+	ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+			COMB_FLAT_THRESH_CTRL + (0x200 * dec), value);
+
+	/* set comb 2D blend */
+	ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+			COMB_2D_BLEND + (0x200 * dec), 0x210F0F0F);
+
+	/* COMB MISC CONTROL */
+	ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+			COMB_MISC_CTRL + (0x200 * dec), 0x41120A7F);
+
+	return ret_val;
+}
+
+static int medusa_initialize_pal(struct cx25821_dev *dev)
+{
+	int ret_val = 0;
+	int i = 0;
+	u32 value = 0;
+	u32 tmp = 0;
+
+	mutex_lock(&dev->lock);
+
+	for (i = 0; i < MAX_DECODERS; i++) {
+		/* set video format PAL-BDGHI */
+		value = cx25821_i2c_read(&dev->i2c_bus[0],
+				MODE_CTRL + (0x200 * i), &tmp);
+		value &= 0xFFFFFFF0;
+		/* enable the fast locking mode bit[16] */
+		value |= 0x10004;
+		ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+				MODE_CTRL + (0x200 * i), value);
+
+		/* resolution PAL 720x576 */
+		value = cx25821_i2c_read(&dev->i2c_bus[0],
+				HORIZ_TIM_CTRL + (0x200 * i), &tmp);
+		value &= 0x00C00C00;
+		value |= 0x632D007D;
+		ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+				HORIZ_TIM_CTRL + (0x200 * i), value);
+
+		/* vblank656_cnt=x26, vactive_cnt=240h, vblank_cnt=x24 */
+		value = cx25821_i2c_read(&dev->i2c_bus[0],
+				VERT_TIM_CTRL + (0x200 * i), &tmp);
+		value &= 0x00C00C00;
+		value |= 0x28240026;	/* vblank_cnt + 2 to get camera ID */
+		ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+				VERT_TIM_CTRL + (0x200 * i), value);
+
+		/* chroma subcarrier step size */
+		ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+				SC_STEP_SIZE + (0x200 * i), 0x5411E2D0);
+
+		/* enable VIP optional active */
+		value = cx25821_i2c_read(&dev->i2c_bus[0],
+				OUT_CTRL_NS + (0x200 * i), &tmp);
+		value &= 0xFFFBFFFF;
+		value |= 0x00040000;
+		ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+				OUT_CTRL_NS + (0x200 * i), value);
+
+		/* enable VIP optional active (VIP_OPT_AL) for direct output. */
+		value = cx25821_i2c_read(&dev->i2c_bus[0],
+				OUT_CTRL1 + (0x200 * i), &tmp);
+		value &= 0xFFFBFFFF;
+		value |= 0x00040000;
+		ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+				OUT_CTRL1 + (0x200 * i), value);
+
+		/*
+		 * clear VPRES_VERT_EN bit, fixes the chroma run away problem
+		 * when the input switching rate < 16 fields
+		 */
+		value = cx25821_i2c_read(&dev->i2c_bus[0],
+				MISC_TIM_CTRL + (0x200 * i), &tmp);
+		/* disable special play detection */
+		value = setBitAtPos(value, 14);
+		value = clearBitAtPos(value, 15);
+		ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+				MISC_TIM_CTRL + (0x200 * i), value);
+
+		/* set vbi_gate_en to 0 */
+		value = cx25821_i2c_read(&dev->i2c_bus[0],
+				DFE_CTRL1 + (0x200 * i), &tmp);
+		value = clearBitAtPos(value, 29);
+		ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+				DFE_CTRL1 + (0x200 * i), value);
+
+		medusa_PALCombInit(dev, i);
+
+		/* Enable the generation of blue field output if no video */
+		medusa_enable_bluefield_output(dev, i, 1);
+	}
+
+	for (i = 0; i < MAX_ENCODERS; i++) {
+		/* PAL hclock */
+		value = cx25821_i2c_read(&dev->i2c_bus[0],
+				DENC_A_REG_1 + (0x100 * i), &tmp);
+		value &= 0xF000FC00;
+		value |= 0x06C002D0;
+		ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+				DENC_A_REG_1 + (0x100 * i), value);
+
+		/* burst begin and burst end */
+		value = cx25821_i2c_read(&dev->i2c_bus[0],
+				DENC_A_REG_2 + (0x100 * i), &tmp);
+		value &= 0xFF000000;
+		value |= 0x007E9754;
+		ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+				DENC_A_REG_2 + (0x100 * i), value);
+
+		/* hblank and vactive */
+		value = cx25821_i2c_read(&dev->i2c_bus[0],
+				DENC_A_REG_3 + (0x100 * i), &tmp);
+		value &= 0xFC00FE00;
+		value |= 0x00FC0120;
+		ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+				DENC_A_REG_3 + (0x100 * i), value);
+
+		/* set PAL vblank, phase alternation, 0 IRE pedestal */
+		value = cx25821_i2c_read(&dev->i2c_bus[0],
+				DENC_A_REG_4 + (0x100 * i), &tmp);
+		value &= 0x00FCFFFF;
+		value |= 0x14010000;
+		ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+				DENC_A_REG_4 + (0x100 * i), value);
+
+		value = cx25821_i2c_read(&dev->i2c_bus[0],
+				DENC_A_REG_5 + (0x100 * i), &tmp);
+		value &= 0xFFFF0000;
+		value |= 0x0000F078;
+		ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+				DENC_A_REG_5 + (0x100 * i), value);
+
+		ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+				DENC_A_REG_6 + (0x100 * i), 0x00A493CF);
+
+		/* Subcarrier Increment */
+		ret_val = cx25821_i2c_write(&dev->i2c_bus[0],
+				DENC_A_REG_7 + (0x100 * i), 0x2A098ACB);
+	}
+
+	/* set picture resolutions */
+	/* 0 - 720 */
+	ret_val = cx25821_i2c_write(&dev->i2c_bus[0], HSCALE_CTRL, 0x0);
+	/* 0 - 576 */
+	ret_val = cx25821_i2c_write(&dev->i2c_bus[0], VSCALE_CTRL, 0x0);
+
+	/* set Bypass input format to PAL 625 lines */
+	value = cx25821_i2c_read(&dev->i2c_bus[0], BYP_AB_CTRL, &tmp);
+	value &= 0xFFF7FDFF;
+	ret_val = cx25821_i2c_write(&dev->i2c_bus[0], BYP_AB_CTRL, value);
+
+	mutex_unlock(&dev->lock);
+
+	return ret_val;
+}
+
+int medusa_set_videostandard(struct cx25821_dev *dev)
+{
+	int status = STATUS_SUCCESS;
+	u32 value = 0, tmp = 0;
+
+	if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK)
+		status = medusa_initialize_pal(dev);
+	else
+		status = medusa_initialize_ntsc(dev);
+
+	/* Enable DENC_A output */
+	value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_4, &tmp);
+	value = setBitAtPos(value, 4);
+	status = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_4, value);
+
+	/* Enable DENC_B output */
+	value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_B_REG_4, &tmp);
+	value = setBitAtPos(value, 4);
+	status = cx25821_i2c_write(&dev->i2c_bus[0], DENC_B_REG_4, value);
+
+	return status;
+}
+
+void medusa_set_resolution(struct cx25821_dev *dev, int width,
+			   int decoder_select)
+{
+	int decoder = 0;
+	int decoder_count = 0;
+	u32 hscale = 0x0;
+	u32 vscale = 0x0;
+	const int MAX_WIDTH = 720;
+
+	mutex_lock(&dev->lock);
+
+	/* validate the width */
+	if (width > MAX_WIDTH) {
+		pr_info("%s(): width %d > MAX_WIDTH %d ! resetting to MAX_WIDTH\n",
+			__func__, width, MAX_WIDTH);
+		width = MAX_WIDTH;
+	}
+
+	if (decoder_select <= 7 && decoder_select >= 0) {
+		decoder = decoder_select;
+		decoder_count = decoder_select + 1;
+	} else {
+		decoder = 0;
+		decoder_count = _num_decoders;
+	}
+
+	switch (width) {
+	case 320:
+		hscale = 0x13E34B;
+		vscale = 0x0;
+		break;
+
+	case 352:
+		hscale = 0x10A273;
+		vscale = 0x0;
+		break;
+
+	case 176:
+		hscale = 0x3115B2;
+		vscale = 0x1E00;
+		break;
+
+	case 160:
+		hscale = 0x378D84;
+		vscale = 0x1E00;
+		break;
+
+	default:		/* 720 */
+		hscale = 0x0;
+		vscale = 0x0;
+		break;
+	}
+
+	for (; decoder < decoder_count; decoder++) {
+		/* write scaling values for each decoder */
+		cx25821_i2c_write(&dev->i2c_bus[0],
+				HSCALE_CTRL + (0x200 * decoder), hscale);
+		cx25821_i2c_write(&dev->i2c_bus[0],
+				VSCALE_CTRL + (0x200 * decoder), vscale);
+	}
+
+	mutex_unlock(&dev->lock);
+}
+
+static void medusa_set_decoderduration(struct cx25821_dev *dev, int decoder,
+				       int duration)
+{
+	u32 fld_cnt = 0;
+	u32 tmp = 0;
+	u32 disp_cnt_reg = DISP_AB_CNT;
+
+	mutex_lock(&dev->lock);
+
+	/* no support */
+	if (decoder < VDEC_A || decoder > VDEC_H) {
+		mutex_unlock(&dev->lock);
+		return;
+	}
+
+	switch (decoder) {
+	default:
+		break;
+	case VDEC_C:
+	case VDEC_D:
+		disp_cnt_reg = DISP_CD_CNT;
+		break;
+	case VDEC_E:
+	case VDEC_F:
+		disp_cnt_reg = DISP_EF_CNT;
+		break;
+	case VDEC_G:
+	case VDEC_H:
+		disp_cnt_reg = DISP_GH_CNT;
+		break;
+	}
+
+	_display_field_cnt[decoder] = duration;
+
+	/* update hardware */
+	fld_cnt = cx25821_i2c_read(&dev->i2c_bus[0], disp_cnt_reg, &tmp);
+
+	if (!(decoder % 2)) {	/* EVEN decoder */
+		fld_cnt &= 0xFFFF0000;
+		fld_cnt |= duration;
+	} else {
+		fld_cnt &= 0x0000FFFF;
+		fld_cnt |= ((u32) duration) << 16;
+	}
+
+	cx25821_i2c_write(&dev->i2c_bus[0], disp_cnt_reg, fld_cnt);
+
+	mutex_unlock(&dev->lock);
+}
+
+/* Map to Medusa register setting */
+static int mapM(int srcMin, int srcMax, int srcVal, int dstMin, int dstMax,
+		int *dstVal)
+{
+	int numerator;
+	int denominator;
+	int quotient;
+
+	if ((srcMin == srcMax) || (srcVal < srcMin) || (srcVal > srcMax))
+		return -1;
+	/*
+	 * This is the overall expression used:
+	 * *dstVal =
+	 *   (srcVal - srcMin)*(dstMax - dstMin) / (srcMax - srcMin) + dstMin;
+	 * but we need to account for rounding so below we use the modulus
+	 * operator to find the remainder and increment if necessary.
+	 */
+	numerator = (srcVal - srcMin) * (dstMax - dstMin);
+	denominator = srcMax - srcMin;
+	quotient = numerator / denominator;
+
+	if (2 * (numerator % denominator) >= denominator)
+		quotient++;
+
+	*dstVal = quotient + dstMin;
+
+	return 0;
+}
+
+static unsigned long convert_to_twos(long numeric, unsigned long bits_len)
+{
+	unsigned char temp;
+
+	if (numeric >= 0)
+		return numeric;
+	else {
+		temp = ~(abs(numeric) & 0xFF);
+		temp += 1;
+		return temp;
+	}
+}
+
+int medusa_set_brightness(struct cx25821_dev *dev, int brightness, int decoder)
+{
+	int ret_val = 0;
+	int value = 0;
+	u32 val = 0, tmp = 0;
+
+	mutex_lock(&dev->lock);
+	if ((brightness > VIDEO_PROCAMP_MAX) ||
+	    (brightness < VIDEO_PROCAMP_MIN)) {
+		mutex_unlock(&dev->lock);
+		return -1;
+	}
+	ret_val = mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, brightness,
+			SIGNED_BYTE_MIN, SIGNED_BYTE_MAX, &value);
+	value = convert_to_twos(value, 8);
+	val = cx25821_i2c_read(&dev->i2c_bus[0],
+			VDEC_A_BRITE_CTRL + (0x200 * decoder), &tmp);
+	val &= 0xFFFFFF00;
+	ret_val |= cx25821_i2c_write(&dev->i2c_bus[0],
+			VDEC_A_BRITE_CTRL + (0x200 * decoder), val | value);
+	mutex_unlock(&dev->lock);
+	return ret_val;
+}
+
+int medusa_set_contrast(struct cx25821_dev *dev, int contrast, int decoder)
+{
+	int ret_val = 0;
+	int value = 0;
+	u32 val = 0, tmp = 0;
+
+	mutex_lock(&dev->lock);
+
+	if ((contrast > VIDEO_PROCAMP_MAX) || (contrast < VIDEO_PROCAMP_MIN)) {
+		mutex_unlock(&dev->lock);
+		return -1;
+	}
+
+	ret_val = mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, contrast,
+			UNSIGNED_BYTE_MIN, UNSIGNED_BYTE_MAX, &value);
+	val = cx25821_i2c_read(&dev->i2c_bus[0],
+			VDEC_A_CNTRST_CTRL + (0x200 * decoder), &tmp);
+	val &= 0xFFFFFF00;
+	ret_val |= cx25821_i2c_write(&dev->i2c_bus[0],
+			VDEC_A_CNTRST_CTRL + (0x200 * decoder), val | value);
+
+	mutex_unlock(&dev->lock);
+	return ret_val;
+}
+
+int medusa_set_hue(struct cx25821_dev *dev, int hue, int decoder)
+{
+	int ret_val = 0;
+	int value = 0;
+	u32 val = 0, tmp = 0;
+
+	mutex_lock(&dev->lock);
+
+	if ((hue > VIDEO_PROCAMP_MAX) || (hue < VIDEO_PROCAMP_MIN)) {
+		mutex_unlock(&dev->lock);
+		return -1;
+	}
+
+	ret_val = mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, hue,
+			SIGNED_BYTE_MIN, SIGNED_BYTE_MAX, &value);
+
+	value = convert_to_twos(value, 8);
+	val = cx25821_i2c_read(&dev->i2c_bus[0],
+			VDEC_A_HUE_CTRL + (0x200 * decoder), &tmp);
+	val &= 0xFFFFFF00;
+
+	ret_val |= cx25821_i2c_write(&dev->i2c_bus[0],
+			VDEC_A_HUE_CTRL + (0x200 * decoder), val | value);
+
+	mutex_unlock(&dev->lock);
+	return ret_val;
+}
+
+int medusa_set_saturation(struct cx25821_dev *dev, int saturation, int decoder)
+{
+	int ret_val = 0;
+	int value = 0;
+	u32 val = 0, tmp = 0;
+
+	mutex_lock(&dev->lock);
+
+	if ((saturation > VIDEO_PROCAMP_MAX) ||
+	    (saturation < VIDEO_PROCAMP_MIN)) {
+		mutex_unlock(&dev->lock);
+		return -1;
+	}
+
+	ret_val = mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, saturation,
+			UNSIGNED_BYTE_MIN, UNSIGNED_BYTE_MAX, &value);
+
+	val = cx25821_i2c_read(&dev->i2c_bus[0],
+			VDEC_A_USAT_CTRL + (0x200 * decoder), &tmp);
+	val &= 0xFFFFFF00;
+	ret_val |= cx25821_i2c_write(&dev->i2c_bus[0],
+			VDEC_A_USAT_CTRL + (0x200 * decoder), val | value);
+
+	val = cx25821_i2c_read(&dev->i2c_bus[0],
+			VDEC_A_VSAT_CTRL + (0x200 * decoder), &tmp);
+	val &= 0xFFFFFF00;
+	ret_val |= cx25821_i2c_write(&dev->i2c_bus[0],
+			VDEC_A_VSAT_CTRL + (0x200 * decoder), val | value);
+
+	mutex_unlock(&dev->lock);
+	return ret_val;
+}
+
+/* Program the display sequence and monitor output. */
+
+int medusa_video_init(struct cx25821_dev *dev)
+{
+	u32 value = 0, tmp = 0;
+	int ret_val = 0;
+	int i = 0;
+
+	mutex_lock(&dev->lock);
+
+	_num_decoders = dev->_max_num_decoders;
+
+	/* disable Auto source selection on all video decoders */
+	value = cx25821_i2c_read(&dev->i2c_bus[0], MON_A_CTRL, &tmp);
+	value &= 0xFFFFF0FF;
+	ret_val = cx25821_i2c_write(&dev->i2c_bus[0], MON_A_CTRL, value);
+
+	if (ret_val < 0)
+		goto error;
+
+	/* Turn off Master source switch enable */
+	value = cx25821_i2c_read(&dev->i2c_bus[0], MON_A_CTRL, &tmp);
+	value &= 0xFFFFFFDF;
+	ret_val = cx25821_i2c_write(&dev->i2c_bus[0], MON_A_CTRL, value);
+
+	if (ret_val < 0)
+		goto error;
+
+	mutex_unlock(&dev->lock);
+
+	for (i = 0; i < _num_decoders; i++)
+		medusa_set_decoderduration(dev, i, _display_field_cnt[i]);
+
+	mutex_lock(&dev->lock);
+
+	/* Select monitor as DENC A input, power up the DAC */
+	value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_AB_CTRL, &tmp);
+	value &= 0xFF70FF70;
+	value |= 0x00090008;	/* set en_active */
+	ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_AB_CTRL, value);
+
+	if (ret_val < 0)
+		goto error;
+
+	/* enable input is VIP/656 */
+	value = cx25821_i2c_read(&dev->i2c_bus[0], BYP_AB_CTRL, &tmp);
+	value |= 0x00040100;	/* enable VIP */
+	ret_val = cx25821_i2c_write(&dev->i2c_bus[0], BYP_AB_CTRL, value);
+
+	if (ret_val < 0)
+		goto error;
+
+	/* select AFE clock to output mode */
+	value = cx25821_i2c_read(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL, &tmp);
+	value &= 0x83FFFFFF;
+	ret_val = cx25821_i2c_write(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL,
+			value | 0x10000000);
+
+	if (ret_val < 0)
+		goto error;
+
+	/* Turn on all of the data out and control output pins. */
+	value = cx25821_i2c_read(&dev->i2c_bus[0], PIN_OE_CTRL, &tmp);
+	value &= 0xFEF0FE00;
+	if (_num_decoders == MAX_DECODERS) {
+		/*
+		 * Note: The octal board does not support control pins(bit16-19)
+		 * These bits are ignored in the octal board.
+		 *
+		 * disable VDEC A-C port, default to Mobilygen Interface
+		 */
+		value |= 0x010001F8;
+	} else {
+		/* disable VDEC A-C port, default to Mobilygen Interface */
+		value |= 0x010F0108;
+	}
+
+	value |= 7;
+	ret_val = cx25821_i2c_write(&dev->i2c_bus[0], PIN_OE_CTRL, value);
+
+	if (ret_val < 0)
+		goto error;
+
+
+	mutex_unlock(&dev->lock);
+
+	ret_val = medusa_set_videostandard(dev);
+
+	return ret_val;
+
+error:
+	mutex_unlock(&dev->lock);
+	return ret_val;
+}
diff --git a/drivers/media/pci/cx25821/cx25821-medusa-video.h b/drivers/media/pci/cx25821/cx25821-medusa-video.h
new file mode 100644
index 0000000..6175e09
--- /dev/null
+++ b/drivers/media/pci/cx25821/cx25821-medusa-video.h
@@ -0,0 +1,49 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _MEDUSA_VIDEO_H
+#define _MEDUSA_VIDEO_H
+
+#include "cx25821-medusa-defines.h"
+
+/* Color control constants */
+#define VIDEO_PROCAMP_MIN                 0
+#define VIDEO_PROCAMP_MAX                 10000
+#define UNSIGNED_BYTE_MIN                 0
+#define UNSIGNED_BYTE_MAX                 0xFF
+#define SIGNED_BYTE_MIN                   -128
+#define SIGNED_BYTE_MAX                   127
+
+/* Default video color settings */
+#define SHARPNESS_DEFAULT                 50
+#define SATURATION_DEFAULT              5000
+#define BRIGHTNESS_DEFAULT              6200
+#define CONTRAST_DEFAULT                5000
+#define HUE_DEFAULT                     5000
+
+unsigned short _num_decoders;
+unsigned short _num_cameras;
+
+unsigned int _video_standard;
+int _display_field_cnt[MAX_DECODERS];
+
+#endif
diff --git a/drivers/media/pci/cx25821/cx25821-reg.h b/drivers/media/pci/cx25821/cx25821-reg.h
new file mode 100644
index 0000000..a3fc25a
--- /dev/null
+++ b/drivers/media/pci/cx25821/cx25821-reg.h
@@ -0,0 +1,1592 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __CX25821_REGISTERS__
+#define __CX25821_REGISTERS__
+
+/* Risc Instructions */
+#define RISC_CNT_INC	 0x00010000
+#define RISC_CNT_RESET	 0x00030000
+#define RISC_IRQ1		 0x01000000
+#define RISC_IRQ2		 0x02000000
+#define RISC_EOL		 0x04000000
+#define RISC_SOL		 0x08000000
+#define RISC_WRITE		 0x10000000
+#define RISC_SKIP		 0x20000000
+#define RISC_JUMP		 0x70000000
+#define RISC_SYNC		 0x80000000
+#define RISC_RESYNC		 0x80008000
+#define RISC_READ		 0x90000000
+#define RISC_WRITERM	 0xB0000000
+#define RISC_WRITECM	 0xC0000000
+#define RISC_WRITECR	 0xD0000000
+#define RISC_WRITEC		 0x50000000
+#define RISC_READC		 0xA0000000
+
+#define RISC_SYNC_ODD		 0x00000000
+#define RISC_SYNC_EVEN		 0x00000200
+#define RISC_SYNC_ODD_VBI	 0x00000006
+#define RISC_SYNC_EVEN_VBI	 0x00000207
+#define RISC_NOOP			 0xF0000000
+
+/*****************************************************************************
+* ASB SRAM
+ *****************************************************************************/
+#define  TX_SRAM                   0x000000	/* Transmit SRAM */
+
+/*****************************************************************************/
+#define  RX_RAM                    0x010000	/* Receive SRAM */
+
+/*****************************************************************************
+* Application Layer (AL)
+ *****************************************************************************/
+#define  DEV_CNTRL2                0x040000	/* Device control */
+#define  FLD_RUN_RISC              0x00000020
+
+/* ***************************************************************************** */
+#define  PCI_INT_MSK               0x040010	/* PCI interrupt mask */
+#define  PCI_INT_STAT              0x040014	/* PCI interrupt status */
+#define  PCI_INT_MSTAT             0x040018	/* PCI interrupt masked status */
+#define  FLD_HAMMERHEAD_INT        (1 << 27)
+#define  FLD_UART_INT              (1 << 26)
+#define  FLD_IRQN_INT              (1 << 25)
+#define  FLD_TM_INT                (1 << 28)
+#define  FLD_I2C_3_RACK            (1 << 27)
+#define  FLD_I2C_3_INT             (1 << 26)
+#define  FLD_I2C_2_RACK            (1 << 25)
+#define  FLD_I2C_2_INT             (1 << 24)
+#define  FLD_I2C_1_RACK            (1 << 23)
+#define  FLD_I2C_1_INT             (1 << 22)
+
+#define  FLD_APB_DMA_BERR_INT      (1 << 21)
+#define  FLD_AL_WR_BERR_INT        (1 << 20)
+#define  FLD_AL_RD_BERR_INT        (1 << 19)
+#define  FLD_RISC_WR_BERR_INT      (1 << 18)
+#define  FLD_RISC_RD_BERR_INT      (1 << 17)
+
+#define  FLD_VID_I_INT             (1 << 8)
+#define  FLD_VID_H_INT             (1 << 7)
+#define  FLD_VID_G_INT             (1 << 6)
+#define  FLD_VID_F_INT             (1 << 5)
+#define  FLD_VID_E_INT             (1 << 4)
+#define  FLD_VID_D_INT             (1 << 3)
+#define  FLD_VID_C_INT             (1 << 2)
+#define  FLD_VID_B_INT             (1 << 1)
+#define  FLD_VID_A_INT             (1 << 0)
+
+/* ***************************************************************************** */
+#define  VID_A_INT_MSK             0x040020	/* Video A interrupt mask */
+#define  VID_A_INT_STAT            0x040024	/* Video A interrupt status */
+#define  VID_A_INT_MSTAT           0x040028	/* Video A interrupt masked status */
+#define  VID_A_INT_SSTAT           0x04002C	/* Video A interrupt set status */
+
+/* ***************************************************************************** */
+#define  VID_B_INT_MSK             0x040030	/* Video B interrupt mask */
+#define  VID_B_INT_STAT            0x040034	/* Video B interrupt status */
+#define  VID_B_INT_MSTAT           0x040038	/* Video B interrupt masked status */
+#define  VID_B_INT_SSTAT           0x04003C	/* Video B interrupt set status */
+
+/* ***************************************************************************** */
+#define  VID_C_INT_MSK             0x040040	/* Video C interrupt mask */
+#define  VID_C_INT_STAT            0x040044	/* Video C interrupt status */
+#define  VID_C_INT_MSTAT           0x040048	/* Video C interrupt masked status */
+#define  VID_C_INT_SSTAT           0x04004C	/* Video C interrupt set status */
+
+/* ***************************************************************************** */
+#define  VID_D_INT_MSK             0x040050	/* Video D interrupt mask */
+#define  VID_D_INT_STAT            0x040054	/* Video D interrupt status */
+#define  VID_D_INT_MSTAT           0x040058	/* Video D interrupt masked status */
+#define  VID_D_INT_SSTAT           0x04005C	/* Video D interrupt set status */
+
+/* ***************************************************************************** */
+#define  VID_E_INT_MSK             0x040060	/* Video E interrupt mask */
+#define  VID_E_INT_STAT            0x040064	/* Video E interrupt status */
+#define  VID_E_INT_MSTAT           0x040068	/* Video E interrupt masked status */
+#define  VID_E_INT_SSTAT           0x04006C	/* Video E interrupt set status */
+
+/* ***************************************************************************** */
+#define  VID_F_INT_MSK             0x040070	/* Video F interrupt mask */
+#define  VID_F_INT_STAT            0x040074	/* Video F interrupt status */
+#define  VID_F_INT_MSTAT           0x040078	/* Video F interrupt masked status */
+#define  VID_F_INT_SSTAT           0x04007C	/* Video F interrupt set status */
+
+/* ***************************************************************************** */
+#define  VID_G_INT_MSK             0x040080	/* Video G interrupt mask */
+#define  VID_G_INT_STAT            0x040084	/* Video G interrupt status */
+#define  VID_G_INT_MSTAT           0x040088	/* Video G interrupt masked status */
+#define  VID_G_INT_SSTAT           0x04008C	/* Video G interrupt set status */
+
+/* ***************************************************************************** */
+#define  VID_H_INT_MSK             0x040090	/* Video H interrupt mask */
+#define  VID_H_INT_STAT            0x040094	/* Video H interrupt status */
+#define  VID_H_INT_MSTAT           0x040098	/* Video H interrupt masked status */
+#define  VID_H_INT_SSTAT           0x04009C	/* Video H interrupt set status */
+
+/* ***************************************************************************** */
+#define  VID_I_INT_MSK             0x0400A0	/* Video I interrupt mask */
+#define  VID_I_INT_STAT            0x0400A4	/* Video I interrupt status */
+#define  VID_I_INT_MSTAT           0x0400A8	/* Video I interrupt masked status */
+#define  VID_I_INT_SSTAT           0x0400AC	/* Video I interrupt set status */
+
+/* ***************************************************************************** */
+#define  VID_J_INT_MSK             0x0400B0	/* Video J interrupt mask */
+#define  VID_J_INT_STAT            0x0400B4	/* Video J interrupt status */
+#define  VID_J_INT_MSTAT           0x0400B8	/* Video J interrupt masked status */
+#define  VID_J_INT_SSTAT           0x0400BC	/* Video J interrupt set status */
+
+#define  FLD_VID_SRC_OPC_ERR       0x00020000
+#define  FLD_VID_DST_OPC_ERR       0x00010000
+#define  FLD_VID_SRC_SYNC          0x00002000
+#define  FLD_VID_DST_SYNC          0x00001000
+#define  FLD_VID_SRC_UF            0x00000200
+#define  FLD_VID_DST_OF            0x00000100
+#define  FLD_VID_SRC_RISC2         0x00000020
+#define  FLD_VID_DST_RISC2         0x00000010
+#define  FLD_VID_SRC_RISC1         0x00000002
+#define  FLD_VID_DST_RISC1         0x00000001
+#define  FLD_VID_SRC_ERRORS		(FLD_VID_SRC_OPC_ERR | FLD_VID_SRC_SYNC | FLD_VID_SRC_UF)
+#define  FLD_VID_DST_ERRORS		(FLD_VID_DST_OPC_ERR | FLD_VID_DST_SYNC | FLD_VID_DST_OF)
+
+/* ***************************************************************************** */
+#define  AUD_A_INT_MSK             0x0400C0	/* Audio Int interrupt mask */
+#define  AUD_A_INT_STAT            0x0400C4	/* Audio Int interrupt status */
+#define  AUD_A_INT_MSTAT           0x0400C8	/* Audio Int interrupt masked status */
+#define  AUD_A_INT_SSTAT           0x0400CC	/* Audio Int interrupt set status */
+
+/* ***************************************************************************** */
+#define  AUD_B_INT_MSK             0x0400D0	/* Audio Int interrupt mask */
+#define  AUD_B_INT_STAT            0x0400D4	/* Audio Int interrupt status */
+#define  AUD_B_INT_MSTAT           0x0400D8	/* Audio Int interrupt masked status */
+#define  AUD_B_INT_SSTAT           0x0400DC	/* Audio Int interrupt set status */
+
+/* ***************************************************************************** */
+#define  AUD_C_INT_MSK             0x0400E0	/* Audio Int interrupt mask */
+#define  AUD_C_INT_STAT            0x0400E4	/* Audio Int interrupt status */
+#define  AUD_C_INT_MSTAT           0x0400E8	/* Audio Int interrupt masked status */
+#define  AUD_C_INT_SSTAT           0x0400EC	/* Audio Int interrupt set status */
+
+/* ***************************************************************************** */
+#define  AUD_D_INT_MSK             0x0400F0	/* Audio Int interrupt mask */
+#define  AUD_D_INT_STAT            0x0400F4	/* Audio Int interrupt status */
+#define  AUD_D_INT_MSTAT           0x0400F8	/* Audio Int interrupt masked status */
+#define  AUD_D_INT_SSTAT           0x0400FC	/* Audio Int interrupt set status */
+
+/* ***************************************************************************** */
+#define  AUD_E_INT_MSK             0x040100	/* Audio Int interrupt mask */
+#define  AUD_E_INT_STAT            0x040104	/* Audio Int interrupt status */
+#define  AUD_E_INT_MSTAT           0x040108	/* Audio Int interrupt masked status */
+#define  AUD_E_INT_SSTAT           0x04010C	/* Audio Int interrupt set status */
+
+#define  FLD_AUD_SRC_OPC_ERR       0x00020000
+#define  FLD_AUD_DST_OPC_ERR       0x00010000
+#define  FLD_AUD_SRC_SYNC          0x00002000
+#define  FLD_AUD_DST_SYNC          0x00001000
+#define  FLD_AUD_SRC_OF            0x00000200
+#define  FLD_AUD_DST_OF            0x00000100
+#define  FLD_AUD_SRC_RISCI2        0x00000020
+#define  FLD_AUD_DST_RISCI2        0x00000010
+#define  FLD_AUD_SRC_RISCI1        0x00000002
+#define  FLD_AUD_DST_RISCI1        0x00000001
+
+/* ***************************************************************************** */
+#define  MBIF_A_INT_MSK             0x040110	/* MBIF Int interrupt mask */
+#define  MBIF_A_INT_STAT            0x040114	/* MBIF Int interrupt status */
+#define  MBIF_A_INT_MSTAT           0x040118	/* MBIF Int interrupt masked status */
+#define  MBIF_A_INT_SSTAT           0x04011C	/* MBIF Int interrupt set status */
+
+/* ***************************************************************************** */
+#define  MBIF_B_INT_MSK             0x040120	/* MBIF Int interrupt mask */
+#define  MBIF_B_INT_STAT            0x040124	/* MBIF Int interrupt status */
+#define  MBIF_B_INT_MSTAT           0x040128	/* MBIF Int interrupt masked status */
+#define  MBIF_B_INT_SSTAT           0x04012C	/* MBIF Int interrupt set status */
+
+#define  FLD_MBIF_DST_OPC_ERR       0x00010000
+#define  FLD_MBIF_DST_SYNC          0x00001000
+#define  FLD_MBIF_DST_OF            0x00000100
+#define  FLD_MBIF_DST_RISCI2        0x00000010
+#define  FLD_MBIF_DST_RISCI1        0x00000001
+
+/* ***************************************************************************** */
+#define  AUD_EXT_INT_MSK           0x040060	/* Audio Ext interrupt mask */
+#define  AUD_EXT_INT_STAT          0x040064	/* Audio Ext interrupt status */
+#define  AUD_EXT_INT_MSTAT         0x040068	/* Audio Ext interrupt masked status */
+#define  AUD_EXT_INT_SSTAT         0x04006C	/* Audio Ext interrupt set status */
+#define  FLD_AUD_EXT_OPC_ERR       0x00010000
+#define  FLD_AUD_EXT_SYNC          0x00001000
+#define  FLD_AUD_EXT_OF            0x00000100
+#define  FLD_AUD_EXT_RISCI2        0x00000010
+#define  FLD_AUD_EXT_RISCI1        0x00000001
+
+/* ***************************************************************************** */
+#define  GPIO_LO                   0x110010	/* Lower  of GPIO pins [31:0] */
+#define  GPIO_HI                   0x110014	/* Upper WORD  of GPIO pins [47:31] */
+
+#define  GPIO_LO_OE                0x110018	/* Lower  of GPIO output enable [31:0] */
+#define  GPIO_HI_OE                0x11001C	/* Upper word  of GPIO output enable [47:32] */
+
+#define  GPIO_LO_INT_MSK           0x11003C	/* GPIO interrupt mask */
+#define  GPIO_LO_INT_STAT          0x110044	/* GPIO interrupt status */
+#define  GPIO_LO_INT_MSTAT         0x11004C	/* GPIO interrupt masked status */
+#define  GPIO_LO_ISM_SNS           0x110054	/* GPIO interrupt sensitivity */
+#define  GPIO_LO_ISM_POL           0x11005C	/* GPIO interrupt polarity */
+
+#define  GPIO_HI_INT_MSK           0x110040	/* GPIO interrupt mask */
+#define  GPIO_HI_INT_STAT          0x110048	/* GPIO interrupt status */
+#define  GPIO_HI_INT_MSTAT         0x110050	/* GPIO interrupt masked status */
+#define  GPIO_HI_ISM_SNS           0x110058	/* GPIO interrupt sensitivity */
+#define  GPIO_HI_ISM_POL           0x110060	/* GPIO interrupt polarity */
+
+#define  FLD_GPIO43_INT            (1 << 11)
+#define  FLD_GPIO42_INT            (1 << 10)
+#define  FLD_GPIO41_INT            (1 << 9)
+#define  FLD_GPIO40_INT            (1 << 8)
+
+#define  FLD_GPIO9_INT             (1 << 9)
+#define  FLD_GPIO8_INT             (1 << 8)
+#define  FLD_GPIO7_INT             (1 << 7)
+#define  FLD_GPIO6_INT             (1 << 6)
+#define  FLD_GPIO5_INT             (1 << 5)
+#define  FLD_GPIO4_INT             (1 << 4)
+#define  FLD_GPIO3_INT             (1 << 3)
+#define  FLD_GPIO2_INT             (1 << 2)
+#define  FLD_GPIO1_INT             (1 << 1)
+#define  FLD_GPIO0_INT             (1 << 0)
+
+/* ***************************************************************************** */
+#define  TC_REQ                    0x040090	/* Rider PCI Express traFFic class request */
+
+/* ***************************************************************************** */
+#define  TC_REQ_SET                0x040094	/* Rider PCI Express traFFic class request set */
+
+/* ***************************************************************************** */
+/* Rider */
+/* ***************************************************************************** */
+
+/* PCI Compatible Header */
+/* ***************************************************************************** */
+#define  RDR_CFG0                  0x050000
+#define  RDR_VENDOR_DEVICE_ID_CFG  0x050000
+
+/* ***************************************************************************** */
+#define  RDR_CFG1                  0x050004
+
+/* ***************************************************************************** */
+#define  RDR_CFG2                  0x050008
+
+/* ***************************************************************************** */
+#define  RDR_CFG3                  0x05000C
+
+/* ***************************************************************************** */
+#define  RDR_CFG4                  0x050010
+
+/* ***************************************************************************** */
+#define  RDR_CFG5                  0x050014
+
+/* ***************************************************************************** */
+#define  RDR_CFG6                  0x050018
+
+/* ***************************************************************************** */
+#define  RDR_CFG7                  0x05001C
+
+/* ***************************************************************************** */
+#define  RDR_CFG8                  0x050020
+
+/* ***************************************************************************** */
+#define  RDR_CFG9                  0x050024
+
+/* ***************************************************************************** */
+#define  RDR_CFGA                  0x050028
+
+/* ***************************************************************************** */
+#define  RDR_CFGB                  0x05002C
+#define  RDR_SUSSYSTEM_ID_CFG      0x05002C
+
+/* ***************************************************************************** */
+#define  RDR_CFGC                  0x050030
+
+/* ***************************************************************************** */
+#define  RDR_CFGD                  0x050034
+
+/* ***************************************************************************** */
+#define  RDR_CFGE                  0x050038
+
+/* ***************************************************************************** */
+#define  RDR_CFGF                  0x05003C
+
+/* ***************************************************************************** */
+/* PCI-Express Capabilities */
+/* ***************************************************************************** */
+#define  RDR_PECAP                 0x050040
+
+/* ***************************************************************************** */
+#define  RDR_PEDEVCAP              0x050044
+
+/* ***************************************************************************** */
+#define  RDR_PEDEVSC               0x050048
+
+/* ***************************************************************************** */
+#define  RDR_PELINKCAP             0x05004C
+
+/* ***************************************************************************** */
+#define  RDR_PELINKSC              0x050050
+
+/* ***************************************************************************** */
+#define  RDR_PMICAP                0x050080
+
+/* ***************************************************************************** */
+#define  RDR_PMCSR                 0x050084
+
+/* ***************************************************************************** */
+#define  RDR_VPDCAP                0x050090
+
+/* ***************************************************************************** */
+#define  RDR_VPDDATA               0x050094
+
+/* ***************************************************************************** */
+#define  RDR_MSICAP                0x0500A0
+
+/* ***************************************************************************** */
+#define  RDR_MSIARL                0x0500A4
+
+/* ***************************************************************************** */
+#define  RDR_MSIARU                0x0500A8
+
+/* ***************************************************************************** */
+#define  RDR_MSIDATA               0x0500AC
+
+/* ***************************************************************************** */
+/* PCI Express Extended Capabilities */
+/* ***************************************************************************** */
+#define  RDR_AERXCAP               0x050100
+
+/* ***************************************************************************** */
+#define  RDR_AERUESTA              0x050104
+
+/* ***************************************************************************** */
+#define  RDR_AERUEMSK              0x050108
+
+/* ***************************************************************************** */
+#define  RDR_AERUESEV              0x05010C
+
+/* ***************************************************************************** */
+#define  RDR_AERCESTA              0x050110
+
+/* ***************************************************************************** */
+#define  RDR_AERCEMSK              0x050114
+
+/* ***************************************************************************** */
+#define  RDR_AERCC                 0x050118
+
+/* ***************************************************************************** */
+#define  RDR_AERHL0                0x05011C
+
+/* ***************************************************************************** */
+#define  RDR_AERHL1                0x050120
+
+/* ***************************************************************************** */
+#define  RDR_AERHL2                0x050124
+
+/* ***************************************************************************** */
+#define  RDR_AERHL3                0x050128
+
+/* ***************************************************************************** */
+#define  RDR_VCXCAP                0x050200
+
+/* ***************************************************************************** */
+#define  RDR_VCCAP1                0x050204
+
+/* ***************************************************************************** */
+#define  RDR_VCCAP2                0x050208
+
+/* ***************************************************************************** */
+#define  RDR_VCSC                  0x05020C
+
+/* ***************************************************************************** */
+#define  RDR_VCR0_CAP              0x050210
+
+/* ***************************************************************************** */
+#define  RDR_VCR0_CTRL             0x050214
+
+/* ***************************************************************************** */
+#define  RDR_VCR0_STAT             0x050218
+
+/* ***************************************************************************** */
+#define  RDR_VCR1_CAP              0x05021C
+
+/* ***************************************************************************** */
+#define  RDR_VCR1_CTRL             0x050220
+
+/* ***************************************************************************** */
+#define  RDR_VCR1_STAT             0x050224
+
+/* ***************************************************************************** */
+#define  RDR_VCR2_CAP              0x050228
+
+/* ***************************************************************************** */
+#define  RDR_VCR2_CTRL             0x05022C
+
+/* ***************************************************************************** */
+#define  RDR_VCR2_STAT             0x050230
+
+/* ***************************************************************************** */
+#define  RDR_VCR3_CAP              0x050234
+
+/* ***************************************************************************** */
+#define  RDR_VCR3_CTRL             0x050238
+
+/* ***************************************************************************** */
+#define  RDR_VCR3_STAT             0x05023C
+
+/* ***************************************************************************** */
+#define  RDR_VCARB0                0x050240
+
+/* ***************************************************************************** */
+#define  RDR_VCARB1                0x050244
+
+/* ***************************************************************************** */
+#define  RDR_VCARB2                0x050248
+
+/* ***************************************************************************** */
+#define  RDR_VCARB3                0x05024C
+
+/* ***************************************************************************** */
+#define  RDR_VCARB4                0x050250
+
+/* ***************************************************************************** */
+#define  RDR_VCARB5                0x050254
+
+/* ***************************************************************************** */
+#define  RDR_VCARB6                0x050258
+
+/* ***************************************************************************** */
+#define  RDR_VCARB7                0x05025C
+
+/* ***************************************************************************** */
+#define  RDR_RDRSTAT0              0x050300
+
+/* ***************************************************************************** */
+#define  RDR_RDRSTAT1              0x050304
+
+/* ***************************************************************************** */
+#define  RDR_RDRCTL0               0x050308
+
+/* ***************************************************************************** */
+#define  RDR_RDRCTL1               0x05030C
+
+/* ***************************************************************************** */
+/* Transaction Layer Registers */
+/* ***************************************************************************** */
+#define  RDR_TLSTAT0               0x050310
+
+/* ***************************************************************************** */
+#define  RDR_TLSTAT1               0x050314
+
+/* ***************************************************************************** */
+#define  RDR_TLCTL0                0x050318
+#define  FLD_CFG_UR_CPL_MODE       0x00000040
+#define  FLD_CFG_CORR_ERR_QUITE    0x00000020
+#define  FLD_CFG_RCB_CK_EN         0x00000010
+#define  FLD_CFG_BNDRY_CK_EN       0x00000008
+#define  FLD_CFG_BYTE_EN_CK_EN     0x00000004
+#define  FLD_CFG_RELAX_ORDER_MSK   0x00000002
+#define  FLD_CFG_TAG_ORDER_EN      0x00000001
+
+/* ***************************************************************************** */
+#define  RDR_TLCTL1                0x05031C
+
+/* ***************************************************************************** */
+#define  RDR_REQRCAL               0x050320
+
+/* ***************************************************************************** */
+#define  RDR_REQRCAU               0x050324
+
+/* ***************************************************************************** */
+#define  RDR_REQEPA                0x050328
+
+/* ***************************************************************************** */
+#define  RDR_REQCTRL               0x05032C
+
+/* ***************************************************************************** */
+#define  RDR_REQSTAT               0x050330
+
+/* ***************************************************************************** */
+#define  RDR_TL_TEST               0x050334
+
+/* ***************************************************************************** */
+#define  RDR_VCR01_CTL             0x050348
+
+/* ***************************************************************************** */
+#define  RDR_VCR23_CTL             0x05034C
+
+/* ***************************************************************************** */
+#define  RDR_RX_VCR0_FC            0x050350
+
+/* ***************************************************************************** */
+#define  RDR_RX_VCR1_FC            0x050354
+
+/* ***************************************************************************** */
+#define  RDR_RX_VCR2_FC            0x050358
+
+/* ***************************************************************************** */
+#define  RDR_RX_VCR3_FC            0x05035C
+
+/* ***************************************************************************** */
+/* Data Link Layer Registers */
+/* ***************************************************************************** */
+#define  RDR_DLLSTAT               0x050360
+
+/* ***************************************************************************** */
+#define  RDR_DLLCTRL               0x050364
+
+/* ***************************************************************************** */
+#define  RDR_REPLAYTO              0x050368
+
+/* ***************************************************************************** */
+#define  RDR_ACKLATTO              0x05036C
+
+/* ***************************************************************************** */
+/* MAC Layer Registers */
+/* ***************************************************************************** */
+#define  RDR_MACSTAT0              0x050380
+
+/* ***************************************************************************** */
+#define  RDR_MACSTAT1              0x050384
+
+/* ***************************************************************************** */
+#define  RDR_MACCTRL0              0x050388
+
+/* ***************************************************************************** */
+#define  RDR_MACCTRL1              0x05038C
+
+/* ***************************************************************************** */
+#define  RDR_MACCTRL2              0x050390
+
+/* ***************************************************************************** */
+#define  RDR_MAC_LB_DATA           0x050394
+
+/* ***************************************************************************** */
+#define  RDR_L0S_EXIT_LAT          0x050398
+
+/* ***************************************************************************** */
+/* DMAC */
+/* ***************************************************************************** */
+#define  DMA1_PTR1                 0x100000	/* DMA Current Ptr : Ch#1 */
+
+/* ***************************************************************************** */
+#define  DMA2_PTR1                 0x100004	/* DMA Current Ptr : Ch#2 */
+
+/* ***************************************************************************** */
+#define  DMA3_PTR1                 0x100008	/* DMA Current Ptr : Ch#3 */
+
+/* ***************************************************************************** */
+#define  DMA4_PTR1                 0x10000C	/* DMA Current Ptr : Ch#4 */
+
+/* ***************************************************************************** */
+#define  DMA5_PTR1                 0x100010	/* DMA Current Ptr : Ch#5 */
+
+/* ***************************************************************************** */
+#define  DMA6_PTR1                 0x100014	/* DMA Current Ptr : Ch#6 */
+
+/* ***************************************************************************** */
+#define  DMA7_PTR1                 0x100018	/* DMA Current Ptr : Ch#7 */
+
+/* ***************************************************************************** */
+#define  DMA8_PTR1                 0x10001C	/* DMA Current Ptr : Ch#8 */
+
+/* ***************************************************************************** */
+#define  DMA9_PTR1                 0x100020	/* DMA Current Ptr : Ch#9 */
+
+/* ***************************************************************************** */
+#define  DMA10_PTR1                0x100024	/* DMA Current Ptr : Ch#10 */
+
+/* ***************************************************************************** */
+#define  DMA11_PTR1                0x100028	/* DMA Current Ptr : Ch#11 */
+
+/* ***************************************************************************** */
+#define  DMA12_PTR1                0x10002C	/* DMA Current Ptr : Ch#12 */
+
+/* ***************************************************************************** */
+#define  DMA13_PTR1                0x100030	/* DMA Current Ptr : Ch#13 */
+
+/* ***************************************************************************** */
+#define  DMA14_PTR1                0x100034	/* DMA Current Ptr : Ch#14 */
+
+/* ***************************************************************************** */
+#define  DMA15_PTR1                0x100038	/* DMA Current Ptr : Ch#15 */
+
+/* ***************************************************************************** */
+#define  DMA16_PTR1                0x10003C	/* DMA Current Ptr : Ch#16 */
+
+/* ***************************************************************************** */
+#define  DMA17_PTR1                0x100040	/* DMA Current Ptr : Ch#17 */
+
+/* ***************************************************************************** */
+#define  DMA18_PTR1                0x100044	/* DMA Current Ptr : Ch#18 */
+
+/* ***************************************************************************** */
+#define  DMA19_PTR1                0x100048	/* DMA Current Ptr : Ch#19 */
+
+/* ***************************************************************************** */
+#define  DMA20_PTR1                0x10004C	/* DMA Current Ptr : Ch#20 */
+
+/* ***************************************************************************** */
+#define  DMA21_PTR1                0x100050	/* DMA Current Ptr : Ch#21 */
+
+/* ***************************************************************************** */
+#define  DMA22_PTR1                0x100054	/* DMA Current Ptr : Ch#22 */
+
+/* ***************************************************************************** */
+#define  DMA23_PTR1                0x100058	/* DMA Current Ptr : Ch#23 */
+
+/* ***************************************************************************** */
+#define  DMA24_PTR1                0x10005C	/* DMA Current Ptr : Ch#24 */
+
+/* ***************************************************************************** */
+#define  DMA25_PTR1                0x100060	/* DMA Current Ptr : Ch#25 */
+
+/* ***************************************************************************** */
+#define  DMA26_PTR1                0x100064	/* DMA Current Ptr : Ch#26 */
+
+/* ***************************************************************************** */
+#define  DMA1_PTR2                 0x100080	/* DMA Tab Ptr : Ch#1 */
+
+/* ***************************************************************************** */
+#define  DMA2_PTR2                 0x100084	/* DMA Tab Ptr : Ch#2 */
+
+/* ***************************************************************************** */
+#define  DMA3_PTR2                 0x100088	/* DMA Tab Ptr : Ch#3 */
+
+/* ***************************************************************************** */
+#define  DMA4_PTR2                 0x10008C	/* DMA Tab Ptr : Ch#4 */
+
+/* ***************************************************************************** */
+#define  DMA5_PTR2                 0x100090	/* DMA Tab Ptr : Ch#5 */
+
+/* ***************************************************************************** */
+#define  DMA6_PTR2                 0x100094	/* DMA Tab Ptr : Ch#6 */
+
+/* ***************************************************************************** */
+#define  DMA7_PTR2                 0x100098	/* DMA Tab Ptr : Ch#7 */
+
+/* ***************************************************************************** */
+#define  DMA8_PTR2                 0x10009C	/* DMA Tab Ptr : Ch#8 */
+
+/* ***************************************************************************** */
+#define  DMA9_PTR2                 0x1000A0	/* DMA Tab Ptr : Ch#9 */
+
+/* ***************************************************************************** */
+#define  DMA10_PTR2                0x1000A4	/* DMA Tab Ptr : Ch#10 */
+
+/* ***************************************************************************** */
+#define  DMA11_PTR2                0x1000A8	/* DMA Tab Ptr : Ch#11 */
+
+/* ***************************************************************************** */
+#define  DMA12_PTR2                0x1000AC	/* DMA Tab Ptr : Ch#12 */
+
+/* ***************************************************************************** */
+#define  DMA13_PTR2                0x1000B0	/* DMA Tab Ptr : Ch#13 */
+
+/* ***************************************************************************** */
+#define  DMA14_PTR2                0x1000B4	/* DMA Tab Ptr : Ch#14 */
+
+/* ***************************************************************************** */
+#define  DMA15_PTR2                0x1000B8	/* DMA Tab Ptr : Ch#15 */
+
+/* ***************************************************************************** */
+#define  DMA16_PTR2                0x1000BC	/* DMA Tab Ptr : Ch#16 */
+
+/* ***************************************************************************** */
+#define  DMA17_PTR2                0x1000C0	/* DMA Tab Ptr : Ch#17 */
+
+/* ***************************************************************************** */
+#define  DMA18_PTR2                0x1000C4	/* DMA Tab Ptr : Ch#18 */
+
+/* ***************************************************************************** */
+#define  DMA19_PTR2                0x1000C8	/* DMA Tab Ptr : Ch#19 */
+
+/* ***************************************************************************** */
+#define  DMA20_PTR2                0x1000CC	/* DMA Tab Ptr : Ch#20 */
+
+/* ***************************************************************************** */
+#define  DMA21_PTR2                0x1000D0	/* DMA Tab Ptr : Ch#21 */
+
+/* ***************************************************************************** */
+#define  DMA22_PTR2                0x1000D4	/* DMA Tab Ptr : Ch#22 */
+
+/* ***************************************************************************** */
+#define  DMA23_PTR2                0x1000D8	/* DMA Tab Ptr : Ch#23 */
+
+/* ***************************************************************************** */
+#define  DMA24_PTR2                0x1000DC	/* DMA Tab Ptr : Ch#24 */
+
+/* ***************************************************************************** */
+#define  DMA25_PTR2                0x1000E0	/* DMA Tab Ptr : Ch#25 */
+
+/* ***************************************************************************** */
+#define  DMA26_PTR2                0x1000E4	/* DMA Tab Ptr : Ch#26 */
+
+/* ***************************************************************************** */
+#define  DMA1_CNT1                 0x100100	/* DMA BuFFer Size : Ch#1 */
+
+/* ***************************************************************************** */
+#define  DMA2_CNT1                 0x100104	/* DMA BuFFer Size : Ch#2 */
+
+/* ***************************************************************************** */
+#define  DMA3_CNT1                 0x100108	/* DMA BuFFer Size : Ch#3 */
+
+/* ***************************************************************************** */
+#define  DMA4_CNT1                 0x10010C	/* DMA BuFFer Size : Ch#4 */
+
+/* ***************************************************************************** */
+#define  DMA5_CNT1                 0x100110	/* DMA BuFFer Size : Ch#5 */
+
+/* ***************************************************************************** */
+#define  DMA6_CNT1                 0x100114	/* DMA BuFFer Size : Ch#6 */
+
+/* ***************************************************************************** */
+#define  DMA7_CNT1                 0x100118	/* DMA BuFFer Size : Ch#7 */
+
+/* ***************************************************************************** */
+#define  DMA8_CNT1                 0x10011C	/* DMA BuFFer Size : Ch#8 */
+
+/* ***************************************************************************** */
+#define  DMA9_CNT1                 0x100120	/* DMA BuFFer Size : Ch#9 */
+
+/* ***************************************************************************** */
+#define  DMA10_CNT1                0x100124	/* DMA BuFFer Size : Ch#10 */
+
+/* ***************************************************************************** */
+#define  DMA11_CNT1                0x100128	/* DMA BuFFer Size : Ch#11 */
+
+/* ***************************************************************************** */
+#define  DMA12_CNT1                0x10012C	/* DMA BuFFer Size : Ch#12 */
+
+/* ***************************************************************************** */
+#define  DMA13_CNT1                0x100130	/* DMA BuFFer Size : Ch#13 */
+
+/* ***************************************************************************** */
+#define  DMA14_CNT1                0x100134	/* DMA BuFFer Size : Ch#14 */
+
+/* ***************************************************************************** */
+#define  DMA15_CNT1                0x100138	/* DMA BuFFer Size : Ch#15 */
+
+/* ***************************************************************************** */
+#define  DMA16_CNT1                0x10013C	/* DMA BuFFer Size : Ch#16 */
+
+/* ***************************************************************************** */
+#define  DMA17_CNT1                0x100140	/* DMA BuFFer Size : Ch#17 */
+
+/* ***************************************************************************** */
+#define  DMA18_CNT1                0x100144	/* DMA BuFFer Size : Ch#18 */
+
+/* ***************************************************************************** */
+#define  DMA19_CNT1                0x100148	/* DMA BuFFer Size : Ch#19 */
+
+/* ***************************************************************************** */
+#define  DMA20_CNT1                0x10014C	/* DMA BuFFer Size : Ch#20 */
+
+/* ***************************************************************************** */
+#define  DMA21_CNT1                0x100150	/* DMA BuFFer Size : Ch#21 */
+
+/* ***************************************************************************** */
+#define  DMA22_CNT1                0x100154	/* DMA BuFFer Size : Ch#22 */
+
+/* ***************************************************************************** */
+#define  DMA23_CNT1                0x100158	/* DMA BuFFer Size : Ch#23 */
+
+/* ***************************************************************************** */
+#define  DMA24_CNT1                0x10015C	/* DMA BuFFer Size : Ch#24 */
+
+/* ***************************************************************************** */
+#define  DMA25_CNT1                0x100160	/* DMA BuFFer Size : Ch#25 */
+
+/* ***************************************************************************** */
+#define  DMA26_CNT1                0x100164	/* DMA BuFFer Size : Ch#26 */
+
+/* ***************************************************************************** */
+#define  DMA1_CNT2                 0x100180	/* DMA Table Size : Ch#1 */
+
+/* ***************************************************************************** */
+#define  DMA2_CNT2                 0x100184	/* DMA Table Size : Ch#2 */
+
+/* ***************************************************************************** */
+#define  DMA3_CNT2                 0x100188	/* DMA Table Size : Ch#3 */
+
+/* ***************************************************************************** */
+#define  DMA4_CNT2                 0x10018C	/* DMA Table Size : Ch#4 */
+
+/* ***************************************************************************** */
+#define  DMA5_CNT2                 0x100190	/* DMA Table Size : Ch#5 */
+
+/* ***************************************************************************** */
+#define  DMA6_CNT2                 0x100194	/* DMA Table Size : Ch#6 */
+
+/* ***************************************************************************** */
+#define  DMA7_CNT2                 0x100198	/* DMA Table Size : Ch#7 */
+
+/* ***************************************************************************** */
+#define  DMA8_CNT2                 0x10019C	/* DMA Table Size : Ch#8 */
+
+/* ***************************************************************************** */
+#define  DMA9_CNT2                 0x1001A0	/* DMA Table Size : Ch#9 */
+
+/* ***************************************************************************** */
+#define  DMA10_CNT2                0x1001A4	/* DMA Table Size : Ch#10 */
+
+/* ***************************************************************************** */
+#define  DMA11_CNT2                0x1001A8	/* DMA Table Size : Ch#11 */
+
+/* ***************************************************************************** */
+#define  DMA12_CNT2                0x1001AC	/* DMA Table Size : Ch#12 */
+
+/* ***************************************************************************** */
+#define  DMA13_CNT2                0x1001B0	/* DMA Table Size : Ch#13 */
+
+/* ***************************************************************************** */
+#define  DMA14_CNT2                0x1001B4	/* DMA Table Size : Ch#14 */
+
+/* ***************************************************************************** */
+#define  DMA15_CNT2                0x1001B8	/* DMA Table Size : Ch#15 */
+
+/* ***************************************************************************** */
+#define  DMA16_CNT2                0x1001BC	/* DMA Table Size : Ch#16 */
+
+/* ***************************************************************************** */
+#define  DMA17_CNT2                0x1001C0	/* DMA Table Size : Ch#17 */
+
+/* ***************************************************************************** */
+#define  DMA18_CNT2                0x1001C4	/* DMA Table Size : Ch#18 */
+
+/* ***************************************************************************** */
+#define  DMA19_CNT2                0x1001C8	/* DMA Table Size : Ch#19 */
+
+/* ***************************************************************************** */
+#define  DMA20_CNT2                0x1001CC	/* DMA Table Size : Ch#20 */
+
+/* ***************************************************************************** */
+#define  DMA21_CNT2                0x1001D0	/* DMA Table Size : Ch#21 */
+
+/* ***************************************************************************** */
+#define  DMA22_CNT2                0x1001D4	/* DMA Table Size : Ch#22 */
+
+/* ***************************************************************************** */
+#define  DMA23_CNT2                0x1001D8	/* DMA Table Size : Ch#23 */
+
+/* ***************************************************************************** */
+#define  DMA24_CNT2                0x1001DC	/* DMA Table Size : Ch#24 */
+
+/* ***************************************************************************** */
+#define  DMA25_CNT2                0x1001E0	/* DMA Table Size : Ch#25 */
+
+/* ***************************************************************************** */
+#define  DMA26_CNT2                0x1001E4	/* DMA Table Size : Ch#26 */
+
+/* ***************************************************************************** */
+ /* ITG */
+/* ***************************************************************************** */
+#define  TM_CNT_LDW                0x110000	/* Timer : Counter low */
+
+/* ***************************************************************************** */
+#define  TM_CNT_UW                 0x110004	/* Timer : Counter high word */
+
+/* ***************************************************************************** */
+#define  TM_LMT_LDW                0x110008	/* Timer : Limit low */
+
+/* ***************************************************************************** */
+#define  TM_LMT_UW                 0x11000C	/* Timer : Limit high word */
+
+/* ***************************************************************************** */
+#define  GP0_IO                    0x110010	/* GPIO output enables data I/O */
+#define  FLD_GP_OE                 0x00FF0000	/* GPIO: GP_OE output enable */
+#define  FLD_GP_IN                 0x0000FF00	/* GPIO: GP_IN status */
+#define  FLD_GP_OUT                0x000000FF	/* GPIO: GP_OUT control */
+
+/* ***************************************************************************** */
+#define  GPIO_ISM                  0x110014	/* GPIO interrupt sensitivity mode */
+#define  FLD_GP_ISM_SNS            0x00000070
+#define  FLD_GP_ISM_POL            0x00000007
+
+/* ***************************************************************************** */
+#define  SOFT_RESET                0x11001C	/* Output system reset reg */
+#define  FLD_PECOS_SOFT_RESET      0x00000001
+
+/* ***************************************************************************** */
+#define  MC416_RWD                 0x110020	/* MC416 GPIO[18:3] pin */
+#define  MC416_OEN                 0x110024	/* Output enable of GPIO[18:3] */
+#define  MC416_CTL                 0x110028
+
+/* ***************************************************************************** */
+#define  ALT_PIN_OUT_SEL           0x11002C	/* Alternate GPIO output select */
+
+#define  FLD_ALT_GPIO_OUT_SEL      0xF0000000
+/* 0          Disabled <-- default */
+/* 1          GPIO[0] */
+/* 2          GPIO[10] */
+/* 3          VIP_656_DATA_VAL */
+/* 4          VIP_656_DATA[0] */
+/* 5          VIP_656_CLK */
+/* 6          VIP_656_DATA_EXT[1] */
+/* 7          VIP_656_DATA_EXT[0] */
+/* 8          ATT_IF */
+
+#define  FLD_AUX_PLL_CLK_ALT_SEL   0x0F000000
+/* 0          AUX_PLL_CLK<-- default */
+/* 1          GPIO[2] */
+/* 2          GPIO[10] */
+/* 3          VIP_656_DATA_VAL */
+/* 4          VIP_656_DATA[0] */
+/* 5          VIP_656_CLK */
+/* 6          VIP_656_DATA_EXT[1] */
+/* 7          VIP_656_DATA_EXT[0] */
+
+#define  FLD_IR_TX_ALT_SEL         0x00F00000
+/* 0          IR_TX <-- default */
+/* 1          GPIO[1] */
+/* 2          GPIO[10] */
+/* 3          VIP_656_DATA_VAL */
+/* 4          VIP_656_DATA[0] */
+/* 5          VIP_656_CLK */
+/* 6          VIP_656_DATA_EXT[1] */
+/* 7          VIP_656_DATA_EXT[0] */
+
+#define  FLD_IR_RX_ALT_SEL         0x000F0000
+/* 0          IR_RX <-- default */
+/* 1          GPIO[0] */
+/* 2          GPIO[10] */
+/* 3          VIP_656_DATA_VAL */
+/* 4          VIP_656_DATA[0] */
+/* 5          VIP_656_CLK */
+/* 6          VIP_656_DATA_EXT[1] */
+/* 7          VIP_656_DATA_EXT[0] */
+
+#define  FLD_GPIO10_ALT_SEL        0x0000F000
+/* 0          GPIO[10] <-- default */
+/* 1          GPIO[0] */
+/* 2          GPIO[10] */
+/* 3          VIP_656_DATA_VAL */
+/* 4          VIP_656_DATA[0] */
+/* 5          VIP_656_CLK */
+/* 6          VIP_656_DATA_EXT[1] */
+/* 7          VIP_656_DATA_EXT[0] */
+
+#define  FLD_GPIO2_ALT_SEL         0x00000F00
+/* 0          GPIO[2] <-- default */
+/* 1          GPIO[1] */
+/* 2          GPIO[10] */
+/* 3          VIP_656_DATA_VAL */
+/* 4          VIP_656_DATA[0] */
+/* 5          VIP_656_CLK */
+/* 6          VIP_656_DATA_EXT[1] */
+/* 7          VIP_656_DATA_EXT[0] */
+
+#define  FLD_GPIO1_ALT_SEL         0x000000F0
+/* 0          GPIO[1] <-- default */
+/* 1          GPIO[0] */
+/* 2          GPIO[10] */
+/* 3          VIP_656_DATA_VAL */
+/* 4          VIP_656_DATA[0] */
+/* 5          VIP_656_CLK */
+/* 6          VIP_656_DATA_EXT[1] */
+/* 7          VIP_656_DATA_EXT[0] */
+
+#define  FLD_GPIO0_ALT_SEL         0x0000000F
+/* 0          GPIO[0] <-- default */
+/* 1          GPIO[1] */
+/* 2          GPIO[10] */
+/* 3          VIP_656_DATA_VAL */
+/* 4          VIP_656_DATA[0] */
+/* 5          VIP_656_CLK */
+/* 6          VIP_656_DATA_EXT[1] */
+/* 7          VIP_656_DATA_EXT[0] */
+
+#define  ALT_PIN_IN_SEL            0x110030	/* Alternate GPIO input select */
+
+#define  FLD_GPIO10_ALT_IN_SEL     0x0000F000
+/* 0          GPIO[10] <-- default */
+/* 1          IR_RX */
+/* 2          IR_TX */
+/* 3          AUX_PLL_CLK */
+/* 4          IF_ATT_SEL */
+/* 5          GPIO[0] */
+/* 6          GPIO[1] */
+/* 7          GPIO[2] */
+
+#define  FLD_GPIO2_ALT_IN_SEL      0x00000F00
+/* 0          GPIO[2] <-- default */
+/* 1          IR_RX */
+/* 2          IR_TX */
+/* 3          AUX_PLL_CLK */
+/* 4          IF_ATT_SEL */
+
+#define  FLD_GPIO1_ALT_IN_SEL      0x000000F0
+/* 0          GPIO[1] <-- default */
+/* 1          IR_RX */
+/* 2          IR_TX */
+/* 3          AUX_PLL_CLK */
+/* 4          IF_ATT_SEL */
+
+#define  FLD_GPIO0_ALT_IN_SEL      0x0000000F
+/* 0          GPIO[0] <-- default */
+/* 1          IR_RX */
+/* 2          IR_TX */
+/* 3          AUX_PLL_CLK */
+/* 4          IF_ATT_SEL */
+
+/* ***************************************************************************** */
+#define  TEST_BUS_CTL1             0x110040	/* Test bus control register #1 */
+
+/* ***************************************************************************** */
+#define  TEST_BUS_CTL2             0x110044	/* Test bus control register #2 */
+
+/* ***************************************************************************** */
+#define  CLK_DELAY                 0x110048	/* Clock delay */
+#define  FLD_MOE_CLK_DIS           0x80000000	/* Disable MoE clock */
+
+/* ***************************************************************************** */
+#define  PAD_CTRL                  0x110068	/* Pad drive strength control */
+
+/* ***************************************************************************** */
+#define  MBIST_CTRL                0x110050	/* SRAM memory built-in self test control */
+
+/* ***************************************************************************** */
+#define  MBIST_STAT                0x110054	/* SRAM memory built-in self test status */
+
+/* ***************************************************************************** */
+/* PLL registers */
+/* ***************************************************************************** */
+#define  PLL_A_INT_FRAC            0x110088
+#define  PLL_A_POST_STAT_BIST      0x11008C
+#define  PLL_B_INT_FRAC            0x110090
+#define  PLL_B_POST_STAT_BIST      0x110094
+#define  PLL_C_INT_FRAC            0x110098
+#define  PLL_C_POST_STAT_BIST      0x11009C
+#define  PLL_D_INT_FRAC            0x1100A0
+#define  PLL_D_POST_STAT_BIST      0x1100A4
+
+#define  CLK_RST                   0x11002C
+#define  FLD_VID_I_CLK_NOE         0x00001000
+#define  FLD_VID_J_CLK_NOE         0x00002000
+#define  FLD_USE_ALT_PLL_REF       0x00004000
+
+#define  VID_CH_MODE_SEL           0x110078
+#define  VID_CH_CLK_SEL            0x11007C
+
+/* ***************************************************************************** */
+#define  VBI_A_DMA                 0x130008	/* VBI A DMA data port */
+
+/* ***************************************************************************** */
+#define  VID_A_VIP_CTL             0x130080	/* Video A VIP format control */
+#define  FLD_VIP_MODE              0x00000001
+
+/* ***************************************************************************** */
+#define  VID_A_PIXEL_FRMT          0x130084	/* Video A pixel format */
+#define  FLD_VID_A_GAMMA_DIS       0x00000008
+#define  FLD_VID_A_FORMAT          0x00000007
+#define  FLD_VID_A_GAMMA_FACTOR    0x00000010
+
+/* ***************************************************************************** */
+#define  VID_A_VBI_CTL             0x130088	/* Video A VBI miscellaneous control */
+#define  FLD_VID_A_VIP_EXT         0x00000003
+
+/* ***************************************************************************** */
+#define  VID_B_DMA                 0x130100	/* Video B DMA data port */
+
+/* ***************************************************************************** */
+#define  VBI_B_DMA                 0x130108	/* VBI B DMA data port */
+
+/* ***************************************************************************** */
+#define  VID_B_SRC_SEL             0x130144	/* Video B source select */
+#define  FLD_VID_B_SRC_SEL         0x00000000
+
+/* ***************************************************************************** */
+#define  VID_B_LNGTH               0x130150	/* Video B line length */
+#define  FLD_VID_B_LN_LNGTH        0x00000FFF
+
+/* ***************************************************************************** */
+#define  VID_B_VIP_CTL             0x130180	/* Video B VIP format control */
+
+/* ***************************************************************************** */
+#define  VID_B_PIXEL_FRMT          0x130184	/* Video B pixel format */
+#define  FLD_VID_B_GAMMA_DIS       0x00000008
+#define  FLD_VID_B_FORMAT          0x00000007
+#define  FLD_VID_B_GAMMA_FACTOR    0x00000010
+
+/* ***************************************************************************** */
+#define  VID_C_DMA                 0x130200	/* Video C DMA data port */
+
+/* ***************************************************************************** */
+#define  VID_C_LNGTH               0x130250	/* Video C line length */
+#define  FLD_VID_C_LN_LNGTH        0x00000FFF
+
+/* ***************************************************************************** */
+/* Video Destination Channels */
+/* ***************************************************************************** */
+
+#define  VID_DST_A_GPCNT           0x130020	/* Video A general purpose counter */
+#define  VID_DST_B_GPCNT           0x130120	/* Video B general purpose counter */
+#define  VID_DST_C_GPCNT           0x130220	/* Video C general purpose counter */
+#define  VID_DST_D_GPCNT           0x130320	/* Video D general purpose counter */
+#define  VID_DST_E_GPCNT           0x130420	/* Video E general purpose counter */
+#define  VID_DST_F_GPCNT           0x130520	/* Video F general purpose counter */
+#define  VID_DST_G_GPCNT           0x130620	/* Video G general purpose counter */
+#define  VID_DST_H_GPCNT           0x130720	/* Video H general purpose counter */
+
+/* ***************************************************************************** */
+
+#define  VID_DST_A_GPCNT_CTL       0x130030	/* Video A general purpose control */
+#define  VID_DST_B_GPCNT_CTL       0x130130	/* Video B general purpose control */
+#define  VID_DST_C_GPCNT_CTL       0x130230	/* Video C general purpose control */
+#define  VID_DST_D_GPCNT_CTL       0x130330	/* Video D general purpose control */
+#define  VID_DST_E_GPCNT_CTL       0x130430	/* Video E general purpose control */
+#define  VID_DST_F_GPCNT_CTL       0x130530	/* Video F general purpose control */
+#define  VID_DST_G_GPCNT_CTL       0x130630	/* Video G general purpose control */
+#define  VID_DST_H_GPCNT_CTL       0x130730	/* Video H general purpose control */
+
+/* ***************************************************************************** */
+
+#define  VID_DST_A_DMA_CTL         0x130040	/* Video A DMA control */
+#define  VID_DST_B_DMA_CTL         0x130140	/* Video B DMA control */
+#define  VID_DST_C_DMA_CTL         0x130240	/* Video C DMA control */
+#define  VID_DST_D_DMA_CTL         0x130340	/* Video D DMA control */
+#define  VID_DST_E_DMA_CTL         0x130440	/* Video E DMA control */
+#define  VID_DST_F_DMA_CTL         0x130540	/* Video F DMA control */
+#define  VID_DST_G_DMA_CTL         0x130640	/* Video G DMA control */
+#define  VID_DST_H_DMA_CTL         0x130740	/* Video H DMA control */
+
+#define  FLD_VID_RISC_EN           0x00000010
+#define  FLD_VID_FIFO_EN           0x00000001
+
+/* ***************************************************************************** */
+
+#define  VID_DST_A_VIP_CTL         0x130080	/* Video A VIP control */
+#define  VID_DST_B_VIP_CTL         0x130180	/* Video B VIP control */
+#define  VID_DST_C_VIP_CTL         0x130280	/* Video C VIP control */
+#define  VID_DST_D_VIP_CTL         0x130380	/* Video D VIP control */
+#define  VID_DST_E_VIP_CTL         0x130480	/* Video E VIP control */
+#define  VID_DST_F_VIP_CTL         0x130580	/* Video F VIP control */
+#define  VID_DST_G_VIP_CTL         0x130680	/* Video G VIP control */
+#define  VID_DST_H_VIP_CTL         0x130780	/* Video H VIP control */
+
+/* ***************************************************************************** */
+
+#define  VID_DST_A_PIX_FRMT        0x130084	/* Video A Pixel format */
+#define  VID_DST_B_PIX_FRMT        0x130184	/* Video B Pixel format */
+#define  VID_DST_C_PIX_FRMT        0x130284	/* Video C Pixel format */
+#define  VID_DST_D_PIX_FRMT        0x130384	/* Video D Pixel format */
+#define  VID_DST_E_PIX_FRMT        0x130484	/* Video E Pixel format */
+#define  VID_DST_F_PIX_FRMT        0x130584	/* Video F Pixel format */
+#define  VID_DST_G_PIX_FRMT        0x130684	/* Video G Pixel format */
+#define  VID_DST_H_PIX_FRMT        0x130784	/* Video H Pixel format */
+
+/* ***************************************************************************** */
+/* Video Source Channels */
+/* ***************************************************************************** */
+
+#define  VID_SRC_A_GPCNT_CTL       0x130804	/* Video A general purpose control */
+#define  VID_SRC_B_GPCNT_CTL       0x130904	/* Video B general purpose control */
+#define  VID_SRC_C_GPCNT_CTL       0x130A04	/* Video C general purpose control */
+#define  VID_SRC_D_GPCNT_CTL       0x130B04	/* Video D general purpose control */
+#define  VID_SRC_E_GPCNT_CTL       0x130C04	/* Video E general purpose control */
+#define  VID_SRC_F_GPCNT_CTL       0x130D04	/* Video F general purpose control */
+#define  VID_SRC_I_GPCNT_CTL       0x130E04	/* Video I general purpose control */
+#define  VID_SRC_J_GPCNT_CTL       0x130F04	/* Video J general purpose control */
+
+/* ***************************************************************************** */
+
+#define  VID_SRC_A_GPCNT           0x130808	/* Video A general purpose counter */
+#define  VID_SRC_B_GPCNT           0x130908	/* Video B general purpose counter */
+#define  VID_SRC_C_GPCNT           0x130A08	/* Video C general purpose counter */
+#define  VID_SRC_D_GPCNT           0x130B08	/* Video D general purpose counter */
+#define  VID_SRC_E_GPCNT           0x130C08	/* Video E general purpose counter */
+#define  VID_SRC_F_GPCNT           0x130D08	/* Video F general purpose counter */
+#define  VID_SRC_I_GPCNT           0x130E08	/* Video I general purpose counter */
+#define  VID_SRC_J_GPCNT           0x130F08	/* Video J general purpose counter */
+
+/* ***************************************************************************** */
+
+#define  VID_SRC_A_DMA_CTL         0x13080C	/* Video A DMA control */
+#define  VID_SRC_B_DMA_CTL         0x13090C	/* Video B DMA control */
+#define  VID_SRC_C_DMA_CTL         0x130A0C	/* Video C DMA control */
+#define  VID_SRC_D_DMA_CTL         0x130B0C	/* Video D DMA control */
+#define  VID_SRC_E_DMA_CTL         0x130C0C	/* Video E DMA control */
+#define  VID_SRC_F_DMA_CTL         0x130D0C	/* Video F DMA control */
+#define  VID_SRC_I_DMA_CTL         0x130E0C	/* Video I DMA control */
+#define  VID_SRC_J_DMA_CTL         0x130F0C	/* Video J DMA control */
+
+#define  FLD_APB_RISC_EN           0x00000010
+#define  FLD_APB_FIFO_EN           0x00000001
+
+/* ***************************************************************************** */
+
+#define  VID_SRC_A_FMT_CTL         0x130810	/* Video A format control */
+#define  VID_SRC_B_FMT_CTL         0x130910	/* Video B format control */
+#define  VID_SRC_C_FMT_CTL         0x130A10	/* Video C format control */
+#define  VID_SRC_D_FMT_CTL         0x130B10	/* Video D format control */
+#define  VID_SRC_E_FMT_CTL         0x130C10	/* Video E format control */
+#define  VID_SRC_F_FMT_CTL         0x130D10	/* Video F format control */
+#define  VID_SRC_I_FMT_CTL         0x130E10	/* Video I format control */
+#define  VID_SRC_J_FMT_CTL         0x130F10	/* Video J format control */
+
+/* ***************************************************************************** */
+
+#define  VID_SRC_A_ACTIVE_CTL1     0x130814	/* Video A active control      1 */
+#define  VID_SRC_B_ACTIVE_CTL1     0x130914	/* Video B active control      1 */
+#define  VID_SRC_C_ACTIVE_CTL1     0x130A14	/* Video C active control      1 */
+#define  VID_SRC_D_ACTIVE_CTL1     0x130B14	/* Video D active control      1 */
+#define  VID_SRC_E_ACTIVE_CTL1     0x130C14	/* Video E active control      1 */
+#define  VID_SRC_F_ACTIVE_CTL1     0x130D14	/* Video F active control      1 */
+#define  VID_SRC_I_ACTIVE_CTL1     0x130E14	/* Video I active control      1 */
+#define  VID_SRC_J_ACTIVE_CTL1     0x130F14	/* Video J active control      1 */
+
+/* ***************************************************************************** */
+
+#define  VID_SRC_A_ACTIVE_CTL2     0x130818	/* Video A active control      2 */
+#define  VID_SRC_B_ACTIVE_CTL2     0x130918	/* Video B active control      2 */
+#define  VID_SRC_C_ACTIVE_CTL2     0x130A18	/* Video C active control      2 */
+#define  VID_SRC_D_ACTIVE_CTL2     0x130B18	/* Video D active control      2 */
+#define  VID_SRC_E_ACTIVE_CTL2     0x130C18	/* Video E active control      2 */
+#define  VID_SRC_F_ACTIVE_CTL2     0x130D18	/* Video F active control      2 */
+#define  VID_SRC_I_ACTIVE_CTL2     0x130E18	/* Video I active control      2 */
+#define  VID_SRC_J_ACTIVE_CTL2     0x130F18	/* Video J active control      2 */
+
+/* ***************************************************************************** */
+
+#define  VID_SRC_A_CDT_SZ          0x13081C	/* Video A CDT size */
+#define  VID_SRC_B_CDT_SZ          0x13091C	/* Video B CDT size */
+#define  VID_SRC_C_CDT_SZ          0x130A1C	/* Video C CDT size */
+#define  VID_SRC_D_CDT_SZ          0x130B1C	/* Video D CDT size */
+#define  VID_SRC_E_CDT_SZ          0x130C1C	/* Video E CDT size */
+#define  VID_SRC_F_CDT_SZ          0x130D1C	/* Video F CDT size */
+#define  VID_SRC_I_CDT_SZ          0x130E1C	/* Video I CDT size */
+#define  VID_SRC_J_CDT_SZ          0x130F1C	/* Video J CDT size */
+
+/* ***************************************************************************** */
+/* Audio I/F */
+/* ***************************************************************************** */
+#define  AUD_DST_A_DMA             0x140000	/* Audio Int A DMA data port */
+#define  AUD_SRC_A_DMA             0x140008	/* Audio Int A DMA data port */
+
+#define  AUD_A_GPCNT               0x140010	/* Audio Int A gp counter */
+#define  FLD_AUD_A_GP_CNT          0x0000FFFF
+
+#define  AUD_A_GPCNT_CTL           0x140014	/* Audio Int A gp control */
+
+#define  AUD_A_LNGTH               0x140018	/* Audio Int A line length */
+
+#define  AUD_A_CFG                 0x14001C	/* Audio Int A configuration */
+
+/* ***************************************************************************** */
+#define  AUD_DST_B_DMA             0x140100	/* Audio Int B DMA data port */
+#define  AUD_SRC_B_DMA             0x140108	/* Audio Int B DMA data port */
+
+#define  AUD_B_GPCNT               0x140110	/* Audio Int B gp counter */
+#define  FLD_AUD_B_GP_CNT          0x0000FFFF
+
+#define  AUD_B_GPCNT_CTL           0x140114	/* Audio Int B gp control */
+
+#define  AUD_B_LNGTH               0x140118	/* Audio Int B line length */
+
+#define  AUD_B_CFG                 0x14011C	/* Audio Int B configuration */
+
+/* ***************************************************************************** */
+#define  AUD_DST_C_DMA             0x140200	/* Audio Int C DMA data port */
+#define  AUD_SRC_C_DMA             0x140208	/* Audio Int C DMA data port */
+
+#define  AUD_C_GPCNT               0x140210	/* Audio Int C gp counter */
+#define  FLD_AUD_C_GP_CNT          0x0000FFFF
+
+#define  AUD_C_GPCNT_CTL           0x140214	/* Audio Int C gp control */
+
+#define  AUD_C_LNGTH               0x140218	/* Audio Int C line length */
+
+#define  AUD_C_CFG                 0x14021C	/* Audio Int C configuration */
+
+/* ***************************************************************************** */
+#define  AUD_DST_D_DMA             0x140300	/* Audio Int D DMA data port */
+#define  AUD_SRC_D_DMA             0x140308	/* Audio Int D DMA data port */
+
+#define  AUD_D_GPCNT               0x140310	/* Audio Int D gp counter */
+#define  FLD_AUD_D_GP_CNT          0x0000FFFF
+
+#define  AUD_D_GPCNT_CTL           0x140314	/* Audio Int D gp control */
+
+#define  AUD_D_LNGTH               0x140318	/* Audio Int D line length */
+
+#define  AUD_D_CFG                 0x14031C	/* Audio Int D configuration */
+
+/* ***************************************************************************** */
+#define  AUD_SRC_E_DMA             0x140400	/* Audio Int E DMA data port */
+
+#define  AUD_E_GPCNT               0x140410	/* Audio Int E gp counter */
+#define  FLD_AUD_E_GP_CNT          0x0000FFFF
+
+#define  AUD_E_GPCNT_CTL           0x140414	/* Audio Int E gp control */
+
+#define  AUD_E_CFG                 0x14041C	/* Audio Int E configuration */
+
+/* ***************************************************************************** */
+
+#define  FLD_AUD_DST_LN_LNGTH      0x00000FFF
+
+#define  FLD_AUD_DST_PK_MODE       0x00004000
+
+#define  FLD_AUD_CLK_ENABLE        0x00000200
+
+#define  FLD_AUD_MASTER_MODE       0x00000002
+
+#define  FLD_AUD_SONY_MODE         0x00000001
+
+#define  FLD_AUD_CLK_SELECT_PLL_D  0x00001800
+
+#define  FLD_AUD_DST_ENABLE        0x00020000
+
+#define  FLD_AUD_SRC_ENABLE        0x00010000
+
+/* ***************************************************************************** */
+#define  AUD_INT_DMA_CTL           0x140500	/* Audio Int DMA control */
+
+#define  FLD_AUD_SRC_E_RISC_EN     0x00008000
+#define  FLD_AUD_SRC_C_RISC_EN     0x00004000
+#define  FLD_AUD_SRC_B_RISC_EN     0x00002000
+#define  FLD_AUD_SRC_A_RISC_EN     0x00001000
+
+#define  FLD_AUD_DST_D_RISC_EN     0x00000800
+#define  FLD_AUD_DST_C_RISC_EN     0x00000400
+#define  FLD_AUD_DST_B_RISC_EN     0x00000200
+#define  FLD_AUD_DST_A_RISC_EN     0x00000100
+
+#define  FLD_AUD_SRC_E_FIFO_EN     0x00000080
+#define  FLD_AUD_SRC_C_FIFO_EN     0x00000040
+#define  FLD_AUD_SRC_B_FIFO_EN     0x00000020
+#define  FLD_AUD_SRC_A_FIFO_EN     0x00000010
+
+#define  FLD_AUD_DST_D_FIFO_EN     0x00000008
+#define  FLD_AUD_DST_C_FIFO_EN     0x00000004
+#define  FLD_AUD_DST_B_FIFO_EN     0x00000002
+#define  FLD_AUD_DST_A_FIFO_EN     0x00000001
+
+/* ***************************************************************************** */
+/*  */
+/* Mobilygen Interface Registers */
+/*  */
+/* ***************************************************************************** */
+/* Mobilygen Interface A */
+/* ***************************************************************************** */
+#define  MB_IF_A_DMA               0x150000	/* MBIF A DMA data port */
+#define  MB_IF_A_GPCN              0x150008	/* MBIF A GP counter */
+#define  MB_IF_A_GPCN_CTRL         0x15000C
+#define  MB_IF_A_DMA_CTRL          0x150010
+#define  MB_IF_A_LENGTH            0x150014
+#define  MB_IF_A_HDMA_XFER_SZ      0x150018
+#define  MB_IF_A_HCMD              0x15001C
+#define  MB_IF_A_HCONFIG           0x150020
+#define  MB_IF_A_DATA_STRUCT_0     0x150024
+#define  MB_IF_A_DATA_STRUCT_1     0x150028
+#define  MB_IF_A_DATA_STRUCT_2     0x15002C
+#define  MB_IF_A_DATA_STRUCT_3     0x150030
+#define  MB_IF_A_DATA_STRUCT_4     0x150034
+#define  MB_IF_A_DATA_STRUCT_5     0x150038
+#define  MB_IF_A_DATA_STRUCT_6     0x15003C
+#define  MB_IF_A_DATA_STRUCT_7     0x150040
+#define  MB_IF_A_DATA_STRUCT_8     0x150044
+#define  MB_IF_A_DATA_STRUCT_9     0x150048
+#define  MB_IF_A_DATA_STRUCT_A     0x15004C
+#define  MB_IF_A_DATA_STRUCT_B     0x150050
+#define  MB_IF_A_DATA_STRUCT_C     0x150054
+#define  MB_IF_A_DATA_STRUCT_D     0x150058
+#define  MB_IF_A_DATA_STRUCT_E     0x15005C
+#define  MB_IF_A_DATA_STRUCT_F     0x150060
+/* ***************************************************************************** */
+/* Mobilygen Interface B */
+/* ***************************************************************************** */
+#define  MB_IF_B_DMA               0x160000	/* MBIF A DMA data port */
+#define  MB_IF_B_GPCN              0x160008	/* MBIF A GP counter */
+#define  MB_IF_B_GPCN_CTRL         0x16000C
+#define  MB_IF_B_DMA_CTRL          0x160010
+#define  MB_IF_B_LENGTH            0x160014
+#define  MB_IF_B_HDMA_XFER_SZ      0x160018
+#define  MB_IF_B_HCMD              0x16001C
+#define  MB_IF_B_HCONFIG           0x160020
+#define  MB_IF_B_DATA_STRUCT_0     0x160024
+#define  MB_IF_B_DATA_STRUCT_1     0x160028
+#define  MB_IF_B_DATA_STRUCT_2     0x16002C
+#define  MB_IF_B_DATA_STRUCT_3     0x160030
+#define  MB_IF_B_DATA_STRUCT_4     0x160034
+#define  MB_IF_B_DATA_STRUCT_5     0x160038
+#define  MB_IF_B_DATA_STRUCT_6     0x16003C
+#define  MB_IF_B_DATA_STRUCT_7     0x160040
+#define  MB_IF_B_DATA_STRUCT_8     0x160044
+#define  MB_IF_B_DATA_STRUCT_9     0x160048
+#define  MB_IF_B_DATA_STRUCT_A     0x16004C
+#define  MB_IF_B_DATA_STRUCT_B     0x160050
+#define  MB_IF_B_DATA_STRUCT_C     0x160054
+#define  MB_IF_B_DATA_STRUCT_D     0x160058
+#define  MB_IF_B_DATA_STRUCT_E     0x16005C
+#define  MB_IF_B_DATA_STRUCT_F     0x160060
+
+/* MB_DMA_CTRL */
+#define  FLD_MB_IF_RISC_EN         0x00000010
+#define  FLD_MB_IF_FIFO_EN         0x00000001
+
+/* MB_LENGTH */
+#define  FLD_MB_IF_LN_LNGTH        0x00000FFF
+
+/* MB_HCMD register */
+#define  FLD_MB_HCMD_H_GO          0x80000000
+#define  FLD_MB_HCMD_H_BUSY        0x40000000
+#define  FLD_MB_HCMD_H_DMA_HOLD    0x10000000
+#define  FLD_MB_HCMD_H_DMA_BUSY    0x08000000
+#define  FLD_MB_HCMD_H_DMA_TYPE    0x04000000
+#define  FLD_MB_HCMD_H_DMA_XACT    0x02000000
+#define  FLD_MB_HCMD_H_RW_N        0x01000000
+#define  FLD_MB_HCMD_H_ADDR        0x00FF0000
+#define  FLD_MB_HCMD_H_DATA        0x0000FFFF
+
+/* ***************************************************************************** */
+/* I2C #1 */
+/* ***************************************************************************** */
+#define  I2C1_ADDR                 0x180000	/* I2C #1 address */
+#define  FLD_I2C_DADDR             0xfe000000	/* RW [31:25] I2C Device Address */
+						 /* RO [24] reserved */
+/* ***************************************************************************** */
+#define  FLD_I2C_SADDR             0x00FFFFFF	/* RW [23:0]  I2C Sub-address */
+
+/* ***************************************************************************** */
+#define  I2C1_WDATA                0x180004	/* I2C #1 write data */
+#define  FLD_I2C_WDATA             0xFFFFFFFF	/* RW [31:0] */
+
+/* ***************************************************************************** */
+#define  I2C1_CTRL                 0x180008	/* I2C #1 control */
+#define  FLD_I2C_PERIOD            0xFF000000	/* RW [31:24] */
+#define  FLD_I2C_SCL_IN            0x00200000	/* RW [21] */
+#define  FLD_I2C_SDA_IN            0x00100000	/* RW [20] */
+						 /* RO [19:18] reserved */
+#define  FLD_I2C_SCL_OUT           0x00020000	/* RW [17] */
+#define  FLD_I2C_SDA_OUT           0x00010000	/* RW [16] */
+						 /* RO [15] reserved */
+#define  FLD_I2C_DATA_LEN          0x00007000	/* RW [14:12] */
+#define  FLD_I2C_SADDR_INC         0x00000800	/* RW [11] */
+						 /* RO [10:9] reserved */
+#define  FLD_I2C_SADDR_LEN         0x00000300	/* RW [9:8] */
+						 /* RO [7:6] reserved */
+#define  FLD_I2C_SOFT              0x00000020	/* RW [5] */
+#define  FLD_I2C_NOSTOP            0x00000010	/* RW [4] */
+#define  FLD_I2C_EXTEND            0x00000008	/* RW [3] */
+#define  FLD_I2C_SYNC              0x00000004	/* RW [2] */
+#define  FLD_I2C_READ_SA           0x00000002	/* RW [1] */
+#define  FLD_I2C_READ_WRN          0x00000001	/* RW [0] */
+
+/* ***************************************************************************** */
+#define  I2C1_RDATA                0x18000C	/* I2C #1 read data */
+#define  FLD_I2C_RDATA             0xFFFFFFFF	/* RO [31:0] */
+
+/* ***************************************************************************** */
+#define  I2C1_STAT                 0x180010	/* I2C #1 status */
+#define  FLD_I2C_XFER_IN_PROG      0x00000002	/* RO [1] */
+#define  FLD_I2C_RACK              0x00000001	/* RO [0] */
+
+/* ***************************************************************************** */
+/* I2C #2 */
+/* ***************************************************************************** */
+#define  I2C2_ADDR                 0x190000	/* I2C #2 address */
+
+/* ***************************************************************************** */
+#define  I2C2_WDATA                0x190004	/* I2C #2 write data */
+
+/* ***************************************************************************** */
+#define  I2C2_CTRL                 0x190008	/* I2C #2 control */
+
+/* ***************************************************************************** */
+#define  I2C2_RDATA                0x19000C	/* I2C #2 read data */
+
+/* ***************************************************************************** */
+#define  I2C2_STAT                 0x190010	/* I2C #2 status */
+
+/* ***************************************************************************** */
+/* I2C #3 */
+/* ***************************************************************************** */
+#define  I2C3_ADDR                 0x1A0000	/* I2C #3 address */
+
+/* ***************************************************************************** */
+#define  I2C3_WDATA                0x1A0004	/* I2C #3 write data */
+
+/* ***************************************************************************** */
+#define  I2C3_CTRL                 0x1A0008	/* I2C #3 control */
+
+/* ***************************************************************************** */
+#define  I2C3_RDATA                0x1A000C	/* I2C #3 read data */
+
+/* ***************************************************************************** */
+#define  I2C3_STAT                 0x1A0010	/* I2C #3 status */
+
+/* ***************************************************************************** */
+/* UART */
+/* ***************************************************************************** */
+#define  UART_CTL                  0x1B0000	/* UART Control Register */
+#define  FLD_LOOP_BACK_EN          (1 << 7)	/* RW field - default 0 */
+#define  FLD_RX_TRG_SZ             (3 << 2)	/* RW field - default 0 */
+#define  FLD_RX_EN                 (1 << 1)	/* RW field - default 0 */
+#define  FLD_TX_EN                 (1 << 0)	/* RW field - default 0 */
+
+/* ***************************************************************************** */
+#define  UART_BRD                  0x1B0004	/* UART Baud Rate Divisor */
+#define  FLD_BRD                   0x0000FFFF	/* RW field - default 0x197 */
+
+/* ***************************************************************************** */
+#define  UART_DBUF                 0x1B0008	/* UART Tx/Rx Data BuFFer */
+#define  FLD_DB                    0xFFFFFFFF	/* RW field - default 0 */
+
+/* ***************************************************************************** */
+#define  UART_ISR                  0x1B000C	/* UART Interrupt Status */
+#define  FLD_RXD_TIMEOUT_EN        (1 << 7)	/* RW field - default 0 */
+#define  FLD_FRM_ERR_EN            (1 << 6)	/* RW field - default 0 */
+#define  FLD_RXD_RDY_EN            (1 << 5)	/* RW field - default 0 */
+#define  FLD_TXD_EMPTY_EN          (1 << 4)	/* RW field - default 0 */
+#define  FLD_RXD_OVERFLOW          (1 << 3)	/* RW field - default 0 */
+#define  FLD_FRM_ERR               (1 << 2)	/* RW field - default 0 */
+#define  FLD_RXD_RDY               (1 << 1)	/* RW field - default 0 */
+#define  FLD_TXD_EMPTY             (1 << 0)	/* RW field - default 0 */
+
+/* ***************************************************************************** */
+#define  UART_CNT                  0x1B0010	/* UART Tx/Rx FIFO Byte Count */
+#define  FLD_TXD_CNT               (0x1F << 8)	/* RW field - default 0 */
+#define  FLD_RXD_CNT               (0x1F << 0)	/* RW field - default 0 */
+
+/* ***************************************************************************** */
+/* Motion Detection */
+#define  MD_CH0_GRID_BLOCK_YCNT    0x170014
+#define  MD_CH1_GRID_BLOCK_YCNT    0x170094
+#define  MD_CH2_GRID_BLOCK_YCNT    0x170114
+#define  MD_CH3_GRID_BLOCK_YCNT    0x170194
+#define  MD_CH4_GRID_BLOCK_YCNT    0x170214
+#define  MD_CH5_GRID_BLOCK_YCNT    0x170294
+#define  MD_CH6_GRID_BLOCK_YCNT    0x170314
+#define  MD_CH7_GRID_BLOCK_YCNT    0x170394
+
+#define PIXEL_FRMT_422    4
+#define PIXEL_FRMT_411    5
+#define PIXEL_FRMT_Y8     6
+
+#define PIXEL_ENGINE_VIP1 0
+#define PIXEL_ENGINE_VIP2 1
+
+#endif /* Athena_REGISTERS */
diff --git a/drivers/media/pci/cx25821/cx25821-sram.h b/drivers/media/pci/cx25821/cx25821-sram.h
new file mode 100644
index 0000000..5f05d15
--- /dev/null
+++ b/drivers/media/pci/cx25821/cx25821-sram.h
@@ -0,0 +1,261 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __ATHENA_SRAM_H__
+#define __ATHENA_SRAM_H__
+
+/* #define RX_SRAM_START_SIZE        = 0;  //  Start of reserved SRAM */
+#define VID_CMDS_SIZE             80	/* Video CMDS size in bytes */
+#define AUDIO_CMDS_SIZE           80	/* AUDIO CMDS size in bytes */
+#define MBIF_CMDS_SIZE            80	/* MBIF  CMDS size in bytes */
+
+/* #define RX_SRAM_POOL_START_SIZE   = 0;  //  Start of useable RX SRAM for buffers */
+#define VID_IQ_SIZE               64	/* VID instruction queue size in bytes */
+#define MBIF_IQ_SIZE              64
+#define AUDIO_IQ_SIZE             64	/* AUD instruction queue size in bytes */
+
+#define VID_CDT_SIZE              64	/* VID cluster descriptor table size in bytes */
+#define MBIF_CDT_SIZE             64	/* MBIF/HBI cluster descriptor table size in bytes */
+#define AUDIO_CDT_SIZE            48	/* AUD cluster descriptor table size in bytes */
+
+/* #define RX_SRAM_POOL_FREE_SIZE    = 16; //  Start of available RX SRAM */
+/* #define RX_SRAM_END_SIZE          = 0;  //  End of RX SRAM */
+
+/* #define TX_SRAM_POOL_START_SIZE   = 0;  //  Start of transmit pool SRAM */
+/* #define MSI_DATA_SIZE             = 64; //  Reserved (MSI Data, RISC working stora */
+
+#define VID_CLUSTER_SIZE          1440	/* VID cluster data line */
+#define AUDIO_CLUSTER_SIZE        128	/* AUDIO cluster data line */
+#define MBIF_CLUSTER_SIZE         1440	/* MBIF/HBI cluster data line */
+
+/* #define TX_SRAM_POOL_FREE_SIZE    = 704;    //  Start of available TX SRAM */
+/* #define TX_SRAM_END_SIZE          = 0;      //  End of TX SRAM */
+
+/* Receive SRAM */
+#define RX_SRAM_START             0x10000
+#define VID_A_DOWN_CMDS           0x10000
+#define VID_B_DOWN_CMDS           0x10050
+#define VID_C_DOWN_CMDS           0x100A0
+#define VID_D_DOWN_CMDS           0x100F0
+#define VID_E_DOWN_CMDS           0x10140
+#define VID_F_DOWN_CMDS           0x10190
+#define VID_G_DOWN_CMDS           0x101E0
+#define VID_H_DOWN_CMDS           0x10230
+#define VID_A_UP_CMDS             0x10280
+#define VID_B_UP_CMDS             0x102D0
+#define VID_C_UP_CMDS             0x10320
+#define VID_D_UP_CMDS             0x10370
+#define VID_E_UP_CMDS             0x103C0
+#define VID_F_UP_CMDS             0x10410
+#define VID_I_UP_CMDS             0x10460
+#define VID_J_UP_CMDS             0x104B0
+#define AUD_A_DOWN_CMDS           0x10500
+#define AUD_B_DOWN_CMDS           0x10550
+#define AUD_C_DOWN_CMDS           0x105A0
+#define AUD_D_DOWN_CMDS           0x105F0
+#define AUD_A_UP_CMDS             0x10640
+#define AUD_B_UP_CMDS             0x10690
+#define AUD_C_UP_CMDS             0x106E0
+#define AUD_E_UP_CMDS             0x10730
+#define MBIF_A_DOWN_CMDS          0x10780
+#define MBIF_B_DOWN_CMDS          0x107D0
+#define DMA_SCRATCH_PAD           0x10820	/* Scratch pad area from 0x10820 to 0x10B40 */
+
+/* #define RX_SRAM_POOL_START        = 0x105B0; */
+
+#define VID_A_IQ                  0x11000
+#define VID_B_IQ                  0x11040
+#define VID_C_IQ                  0x11080
+#define VID_D_IQ                  0x110C0
+#define VID_E_IQ                  0x11100
+#define VID_F_IQ                  0x11140
+#define VID_G_IQ                  0x11180
+#define VID_H_IQ                  0x111C0
+#define VID_I_IQ                  0x11200
+#define VID_J_IQ                  0x11240
+#define AUD_A_IQ                  0x11280
+#define AUD_B_IQ                  0x112C0
+#define AUD_C_IQ                  0x11300
+#define AUD_D_IQ                  0x11340
+#define AUD_E_IQ                  0x11380
+#define MBIF_A_IQ                 0x11000
+#define MBIF_B_IQ                 0x110C0
+
+#define VID_A_CDT                 0x10C00
+#define VID_B_CDT                 0x10C40
+#define VID_C_CDT                 0x10C80
+#define VID_D_CDT                 0x10CC0
+#define VID_E_CDT                 0x10D00
+#define VID_F_CDT                 0x10D40
+#define VID_G_CDT                 0x10D80
+#define VID_H_CDT                 0x10DC0
+#define VID_I_CDT                 0x10E00
+#define VID_J_CDT                 0x10E40
+#define AUD_A_CDT                 0x10E80
+#define AUD_B_CDT                 0x10EB0
+#define AUD_C_CDT                 0x10EE0
+#define AUD_D_CDT                 0x10F10
+#define AUD_E_CDT                 0x10F40
+#define MBIF_A_CDT                0x10C00
+#define MBIF_B_CDT                0x10CC0
+
+/* Cluster Buffer for RX */
+#define VID_A_UP_CLUSTER_1        0x11400
+#define VID_A_UP_CLUSTER_2        0x119A0
+#define VID_A_UP_CLUSTER_3        0x11F40
+#define VID_A_UP_CLUSTER_4        0x124E0
+
+#define VID_B_UP_CLUSTER_1        0x12A80
+#define VID_B_UP_CLUSTER_2        0x13020
+#define VID_B_UP_CLUSTER_3        0x135C0
+#define VID_B_UP_CLUSTER_4        0x13B60
+
+#define VID_C_UP_CLUSTER_1        0x14100
+#define VID_C_UP_CLUSTER_2        0x146A0
+#define VID_C_UP_CLUSTER_3        0x14C40
+#define VID_C_UP_CLUSTER_4        0x151E0
+
+#define VID_D_UP_CLUSTER_1        0x15780
+#define VID_D_UP_CLUSTER_2        0x15D20
+#define VID_D_UP_CLUSTER_3        0x162C0
+#define VID_D_UP_CLUSTER_4        0x16860
+
+#define VID_E_UP_CLUSTER_1        0x16E00
+#define VID_E_UP_CLUSTER_2        0x173A0
+#define VID_E_UP_CLUSTER_3        0x17940
+#define VID_E_UP_CLUSTER_4        0x17EE0
+
+#define VID_F_UP_CLUSTER_1        0x18480
+#define VID_F_UP_CLUSTER_2        0x18A20
+#define VID_F_UP_CLUSTER_3        0x18FC0
+#define VID_F_UP_CLUSTER_4        0x19560
+
+#define VID_I_UP_CLUSTER_1        0x19B00
+#define VID_I_UP_CLUSTER_2        0x1A0A0
+#define VID_I_UP_CLUSTER_3        0x1A640
+#define VID_I_UP_CLUSTER_4        0x1ABE0
+
+#define VID_J_UP_CLUSTER_1        0x1B180
+#define VID_J_UP_CLUSTER_2        0x1B720
+#define VID_J_UP_CLUSTER_3        0x1BCC0
+#define VID_J_UP_CLUSTER_4        0x1C260
+
+#define AUD_A_UP_CLUSTER_1        0x1C800
+#define AUD_A_UP_CLUSTER_2        0x1C880
+#define AUD_A_UP_CLUSTER_3        0x1C900
+
+#define AUD_B_UP_CLUSTER_1        0x1C980
+#define AUD_B_UP_CLUSTER_2        0x1CA00
+#define AUD_B_UP_CLUSTER_3        0x1CA80
+
+#define AUD_C_UP_CLUSTER_1        0x1CB00
+#define AUD_C_UP_CLUSTER_2        0x1CB80
+#define AUD_C_UP_CLUSTER_3        0x1CC00
+
+#define AUD_E_UP_CLUSTER_1        0x1CC80
+#define AUD_E_UP_CLUSTER_2        0x1CD00
+#define AUD_E_UP_CLUSTER_3        0x1CD80
+
+#define RX_SRAM_POOL_FREE         0x1CE00
+#define RX_SRAM_END               0x1D000
+
+/* Free Receive SRAM    144 Bytes */
+
+/* Transmit SRAM */
+#define TX_SRAM_POOL_START        0x00000
+
+#define VID_A_DOWN_CLUSTER_1      0x00040
+#define VID_A_DOWN_CLUSTER_2      0x005E0
+#define VID_A_DOWN_CLUSTER_3      0x00B80
+#define VID_A_DOWN_CLUSTER_4      0x01120
+
+#define VID_B_DOWN_CLUSTER_1      0x016C0
+#define VID_B_DOWN_CLUSTER_2      0x01C60
+#define VID_B_DOWN_CLUSTER_3      0x02200
+#define VID_B_DOWN_CLUSTER_4      0x027A0
+
+#define VID_C_DOWN_CLUSTER_1      0x02D40
+#define VID_C_DOWN_CLUSTER_2      0x032E0
+#define VID_C_DOWN_CLUSTER_3      0x03880
+#define VID_C_DOWN_CLUSTER_4      0x03E20
+
+#define VID_D_DOWN_CLUSTER_1      0x043C0
+#define VID_D_DOWN_CLUSTER_2      0x04960
+#define VID_D_DOWN_CLUSTER_3      0x04F00
+#define VID_D_DOWN_CLUSTER_4      0x054A0
+
+#define VID_E_DOWN_CLUSTER_1      0x05a40
+#define VID_E_DOWN_CLUSTER_2      0x05FE0
+#define VID_E_DOWN_CLUSTER_3      0x06580
+#define VID_E_DOWN_CLUSTER_4      0x06B20
+
+#define VID_F_DOWN_CLUSTER_1      0x070C0
+#define VID_F_DOWN_CLUSTER_2      0x07660
+#define VID_F_DOWN_CLUSTER_3      0x07C00
+#define VID_F_DOWN_CLUSTER_4      0x081A0
+
+#define VID_G_DOWN_CLUSTER_1      0x08740
+#define VID_G_DOWN_CLUSTER_2      0x08CE0
+#define VID_G_DOWN_CLUSTER_3      0x09280
+#define VID_G_DOWN_CLUSTER_4      0x09820
+
+#define VID_H_DOWN_CLUSTER_1      0x09DC0
+#define VID_H_DOWN_CLUSTER_2      0x0A360
+#define VID_H_DOWN_CLUSTER_3      0x0A900
+#define VID_H_DOWN_CLUSTER_4      0x0AEA0
+
+#define AUD_A_DOWN_CLUSTER_1      0x0B500
+#define AUD_A_DOWN_CLUSTER_2      0x0B580
+#define AUD_A_DOWN_CLUSTER_3      0x0B600
+
+#define AUD_B_DOWN_CLUSTER_1      0x0B680
+#define AUD_B_DOWN_CLUSTER_2      0x0B700
+#define AUD_B_DOWN_CLUSTER_3      0x0B780
+
+#define AUD_C_DOWN_CLUSTER_1      0x0B800
+#define AUD_C_DOWN_CLUSTER_2      0x0B880
+#define AUD_C_DOWN_CLUSTER_3      0x0B900
+
+#define AUD_D_DOWN_CLUSTER_1      0x0B980
+#define AUD_D_DOWN_CLUSTER_2      0x0BA00
+#define AUD_D_DOWN_CLUSTER_3      0x0BA80
+
+#define TX_SRAM_POOL_FREE         0x0BB00
+#define TX_SRAM_END               0x0C000
+
+#define BYTES_TO_DWORDS(bcount) ((bcount) >> 2)
+#define BYTES_TO_QWORDS(bcount) ((bcount) >> 3)
+#define BYTES_TO_OWORDS(bcount) ((bcount) >> 4)
+
+#define VID_IQ_SIZE_DW             BYTES_TO_DWORDS(VID_IQ_SIZE)
+#define VID_CDT_SIZE_QW            BYTES_TO_QWORDS(VID_CDT_SIZE)
+#define VID_CLUSTER_SIZE_OW        BYTES_TO_OWORDS(VID_CLUSTER_SIZE)
+
+#define AUDIO_IQ_SIZE_DW           BYTES_TO_DWORDS(AUDIO_IQ_SIZE)
+#define AUDIO_CDT_SIZE_QW          BYTES_TO_QWORDS(AUDIO_CDT_SIZE)
+#define AUDIO_CLUSTER_SIZE_QW      BYTES_TO_QWORDS(AUDIO_CLUSTER_SIZE)
+
+#define MBIF_IQ_SIZE_DW            BYTES_TO_DWORDS(MBIF_IQ_SIZE)
+#define MBIF_CDT_SIZE_QW           BYTES_TO_QWORDS(MBIF_CDT_SIZE)
+#define MBIF_CLUSTER_SIZE_OW       BYTES_TO_OWORDS(MBIF_CLUSTER_SIZE)
+
+#endif
diff --git a/drivers/media/pci/cx25821/cx25821-video-upstream-ch2.c b/drivers/media/pci/cx25821/cx25821-video-upstream-ch2.c
new file mode 100644
index 0000000..c8c94fb
--- /dev/null
+++ b/drivers/media/pci/cx25821/cx25821-video-upstream-ch2.c
@@ -0,0 +1,802 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <hiep.huynh@conexant.com>, <shu.lin@conexant.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include "cx25821-video.h"
+#include "cx25821-video-upstream-ch2.h"
+
+#include <linux/fs.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/syscalls.h>
+#include <linux/file.h>
+#include <linux/fcntl.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+
+MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards");
+MODULE_AUTHOR("Hiep Huynh <hiep.huynh@conexant.com>");
+MODULE_LICENSE("GPL");
+
+static int _intr_msk = FLD_VID_SRC_RISC1 | FLD_VID_SRC_UF | FLD_VID_SRC_SYNC |
+			FLD_VID_SRC_OPC_ERR;
+
+static __le32 *cx25821_update_riscprogram_ch2(struct cx25821_dev *dev,
+					      __le32 *rp, unsigned int offset,
+					      unsigned int bpl, u32 sync_line,
+					      unsigned int lines,
+					      int fifo_enable, int field_type)
+{
+	unsigned int line, i;
+	int dist_betwn_starts = bpl * 2;
+
+	*(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
+
+	if (USE_RISC_NOOP_VIDEO) {
+		for (i = 0; i < NUM_NO_OPS; i++)
+			*(rp++) = cpu_to_le32(RISC_NOOP);
+	}
+
+	/* scan lines */
+	for (line = 0; line < lines; line++) {
+		*(rp++) = cpu_to_le32(RISC_READ | RISC_SOL | RISC_EOL | bpl);
+		*(rp++) = cpu_to_le32(dev->_data_buf_phys_addr_ch2 + offset);
+		*(rp++) = cpu_to_le32(0);	/* bits 63-32 */
+
+		if ((lines <= NTSC_FIELD_HEIGHT) ||
+		    (line < (NTSC_FIELD_HEIGHT - 1)) || !(dev->_isNTSC_ch2)) {
+			offset += dist_betwn_starts;
+		}
+	}
+
+	return rp;
+}
+
+static __le32 *cx25821_risc_field_upstream_ch2(struct cx25821_dev *dev,
+					       __le32 *rp,
+					       dma_addr_t databuf_phys_addr,
+					       unsigned int offset,
+					       u32 sync_line, unsigned int bpl,
+					       unsigned int lines,
+					       int fifo_enable, int field_type)
+{
+	unsigned int line, i;
+	struct sram_channel *sram_ch =
+		dev->channels[dev->_channel2_upstream_select].sram_channels;
+	int dist_betwn_starts = bpl * 2;
+
+	/* sync instruction */
+	if (sync_line != NO_SYNC_LINE)
+		*(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
+
+	if (USE_RISC_NOOP_VIDEO) {
+		for (i = 0; i < NUM_NO_OPS; i++)
+			*(rp++) = cpu_to_le32(RISC_NOOP);
+	}
+
+	/* scan lines */
+	for (line = 0; line < lines; line++) {
+		*(rp++) = cpu_to_le32(RISC_READ | RISC_SOL | RISC_EOL | bpl);
+		*(rp++) = cpu_to_le32(databuf_phys_addr + offset);
+		*(rp++) = cpu_to_le32(0);	/* bits 63-32 */
+
+		if ((lines <= NTSC_FIELD_HEIGHT) ||
+		    (line < (NTSC_FIELD_HEIGHT - 1)) || !(dev->_isNTSC_ch2)) {
+			offset += dist_betwn_starts;
+		}
+
+	       /*
+		 check if we need to enable the FIFO after the first 4 lines
+		  For the upstream video channel, the risc engine will enable
+		  the FIFO.
+	       */
+		if (fifo_enable && line == 3) {
+			*(rp++) = RISC_WRITECR;
+			*(rp++) = sram_ch->dma_ctl;
+			*(rp++) = FLD_VID_FIFO_EN;
+			*(rp++) = 0x00000001;
+		}
+	}
+
+	return rp;
+}
+
+int cx25821_risc_buffer_upstream_ch2(struct cx25821_dev *dev,
+				     struct pci_dev *pci,
+				     unsigned int top_offset, unsigned int bpl,
+				     unsigned int lines)
+{
+	__le32 *rp;
+	int fifo_enable = 0;
+	int singlefield_lines = lines >> 1; /*get line count for single field */
+	int odd_num_lines = singlefield_lines;
+	int frame = 0;
+	int frame_size = 0;
+	int databuf_offset = 0;
+	int risc_program_size = 0;
+	int risc_flag = RISC_CNT_RESET;
+	unsigned int bottom_offset = bpl;
+	dma_addr_t risc_phys_jump_addr;
+
+	if (dev->_isNTSC_ch2) {
+		odd_num_lines = singlefield_lines + 1;
+		risc_program_size = FRAME1_VID_PROG_SIZE;
+		if (bpl == Y411_LINE_SZ)
+			frame_size = FRAME_SIZE_NTSC_Y411;
+		else
+			frame_size = FRAME_SIZE_NTSC_Y422;
+	} else {
+		risc_program_size = PAL_VID_PROG_SIZE;
+		if (bpl == Y411_LINE_SZ)
+			frame_size = FRAME_SIZE_PAL_Y411;
+		else
+			frame_size = FRAME_SIZE_PAL_Y422;
+	}
+
+	/* Virtual address of Risc buffer program */
+	rp = dev->_dma_virt_addr_ch2;
+
+	for (frame = 0; frame < NUM_FRAMES; frame++) {
+		databuf_offset = frame_size * frame;
+
+		if (UNSET != top_offset) {
+			fifo_enable = (frame == 0) ? FIFO_ENABLE : FIFO_DISABLE;
+			rp = cx25821_risc_field_upstream_ch2(dev, rp,
+				dev->_data_buf_phys_addr_ch2 + databuf_offset,
+				top_offset, 0, bpl, odd_num_lines, fifo_enable,
+				ODD_FIELD);
+		}
+
+		fifo_enable = FIFO_DISABLE;
+
+		/* Even field */
+		rp = cx25821_risc_field_upstream_ch2(dev, rp,
+				dev->_data_buf_phys_addr_ch2 + databuf_offset,
+				bottom_offset, 0x200, bpl, singlefield_lines,
+				fifo_enable, EVEN_FIELD);
+
+		if (frame == 0) {
+			risc_flag = RISC_CNT_RESET;
+			risc_phys_jump_addr = dev->_dma_phys_start_addr_ch2 +
+					risc_program_size;
+		} else {
+			risc_flag = RISC_CNT_INC;
+			risc_phys_jump_addr = dev->_dma_phys_start_addr_ch2;
+		}
+
+	       /*
+		* Loop to 2ndFrameRISC or to Start of
+		* Risc program & generate IRQ
+		*/
+		*(rp++) = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | risc_flag);
+		*(rp++) = cpu_to_le32(risc_phys_jump_addr);
+		*(rp++) = cpu_to_le32(0);
+	}
+
+	return 0;
+}
+
+void cx25821_stop_upstream_video_ch2(struct cx25821_dev *dev)
+{
+	struct sram_channel *sram_ch =
+		dev->channels[VID_UPSTREAM_SRAM_CHANNEL_J].sram_channels;
+	u32 tmp = 0;
+
+	if (!dev->_is_running_ch2) {
+		pr_info("No video file is currently running so return!\n");
+		return;
+	}
+	/* Disable RISC interrupts */
+	tmp = cx_read(sram_ch->int_msk);
+	cx_write(sram_ch->int_msk, tmp & ~_intr_msk);
+
+	/* Turn OFF risc and fifo */
+	tmp = cx_read(sram_ch->dma_ctl);
+	cx_write(sram_ch->dma_ctl, tmp & ~(FLD_VID_FIFO_EN | FLD_VID_RISC_EN));
+
+	/* Clear data buffer memory */
+	if (dev->_data_buf_virt_addr_ch2)
+		memset(dev->_data_buf_virt_addr_ch2, 0,
+		       dev->_data_buf_size_ch2);
+
+	dev->_is_running_ch2 = 0;
+	dev->_is_first_frame_ch2 = 0;
+	dev->_frame_count_ch2 = 0;
+	dev->_file_status_ch2 = END_OF_FILE;
+
+	kfree(dev->_irq_queues_ch2);
+	dev->_irq_queues_ch2 = NULL;
+
+	kfree(dev->_filename_ch2);
+
+	tmp = cx_read(VID_CH_MODE_SEL);
+	cx_write(VID_CH_MODE_SEL, tmp & 0xFFFFFE00);
+}
+
+void cx25821_free_mem_upstream_ch2(struct cx25821_dev *dev)
+{
+	if (dev->_is_running_ch2)
+		cx25821_stop_upstream_video_ch2(dev);
+
+	if (dev->_dma_virt_addr_ch2) {
+		pci_free_consistent(dev->pci, dev->_risc_size_ch2,
+				    dev->_dma_virt_addr_ch2,
+				    dev->_dma_phys_addr_ch2);
+		dev->_dma_virt_addr_ch2 = NULL;
+	}
+
+	if (dev->_data_buf_virt_addr_ch2) {
+		pci_free_consistent(dev->pci, dev->_data_buf_size_ch2,
+				    dev->_data_buf_virt_addr_ch2,
+				    dev->_data_buf_phys_addr_ch2);
+		dev->_data_buf_virt_addr_ch2 = NULL;
+	}
+}
+
+int cx25821_get_frame_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch)
+{
+	struct file *myfile;
+	int frame_index_temp = dev->_frame_index_ch2;
+	int i = 0;
+	int line_size = (dev->_pixel_format_ch2 == PIXEL_FRMT_411) ?
+		Y411_LINE_SZ : Y422_LINE_SZ;
+	int frame_size = 0;
+	int frame_offset = 0;
+	ssize_t vfs_read_retval = 0;
+	char mybuf[line_size];
+	loff_t file_offset;
+	loff_t pos;
+	mm_segment_t old_fs;
+
+	if (dev->_file_status_ch2 == END_OF_FILE)
+		return 0;
+
+	if (dev->_isNTSC_ch2) {
+		frame_size = (line_size == Y411_LINE_SZ) ?
+			FRAME_SIZE_NTSC_Y411 : FRAME_SIZE_NTSC_Y422;
+	} else {
+		frame_size = (line_size == Y411_LINE_SZ) ?
+			FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422;
+	}
+
+	frame_offset = (frame_index_temp > 0) ? frame_size : 0;
+	file_offset = dev->_frame_count_ch2 * frame_size;
+
+	myfile = filp_open(dev->_filename_ch2, O_RDONLY | O_LARGEFILE, 0);
+	if (IS_ERR(myfile)) {
+		const int open_errno = -PTR_ERR(myfile);
+		pr_err("%s(): ERROR opening file(%s) with errno = %d!\n",
+		       __func__, dev->_filename_ch2, open_errno);
+		return PTR_ERR(myfile);
+	} else {
+		if (!(myfile->f_op)) {
+			pr_err("%s(): File has no file operations registered!\n",
+			       __func__);
+			filp_close(myfile, NULL);
+			return -EIO;
+		}
+
+		if (!myfile->f_op->read) {
+			pr_err("%s(): File has no READ operations registered!\n",
+			       __func__);
+			filp_close(myfile, NULL);
+			return -EIO;
+		}
+
+		pos = myfile->f_pos;
+		old_fs = get_fs();
+		set_fs(KERNEL_DS);
+
+		for (i = 0; i < dev->_lines_count_ch2; i++) {
+			pos = file_offset;
+
+			vfs_read_retval = vfs_read(myfile, mybuf, line_size,
+					&pos);
+
+			if (vfs_read_retval > 0 && vfs_read_retval == line_size
+			    && dev->_data_buf_virt_addr_ch2 != NULL) {
+				memcpy((void *)(dev->_data_buf_virt_addr_ch2 +
+						frame_offset / 4), mybuf,
+						vfs_read_retval);
+			}
+
+			file_offset += vfs_read_retval;
+			frame_offset += vfs_read_retval;
+
+			if (vfs_read_retval < line_size) {
+				pr_info("Done: exit %s() since no more bytes to read from Video file\n",
+					__func__);
+				break;
+			}
+		}
+
+		if (i > 0)
+			dev->_frame_count_ch2++;
+
+		dev->_file_status_ch2 = (vfs_read_retval == line_size) ?
+			IN_PROGRESS : END_OF_FILE;
+
+		set_fs(old_fs);
+		filp_close(myfile, NULL);
+	}
+
+	return 0;
+}
+
+static void cx25821_vidups_handler_ch2(struct work_struct *work)
+{
+	struct cx25821_dev *dev = container_of(work, struct cx25821_dev,
+			_irq_work_entry_ch2);
+
+	if (!dev) {
+		pr_err("ERROR %s(): since container_of(work_struct) FAILED!\n",
+		       __func__);
+		return;
+	}
+
+	cx25821_get_frame_ch2(dev, dev->channels[dev->
+			_channel2_upstream_select].sram_channels);
+}
+
+int cx25821_openfile_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch)
+{
+	struct file *myfile;
+	int i = 0, j = 0;
+	int line_size = (dev->_pixel_format_ch2 == PIXEL_FRMT_411) ?
+		Y411_LINE_SZ : Y422_LINE_SZ;
+	ssize_t vfs_read_retval = 0;
+	char mybuf[line_size];
+	loff_t pos;
+	loff_t offset = (unsigned long)0;
+	mm_segment_t old_fs;
+
+	myfile = filp_open(dev->_filename_ch2, O_RDONLY | O_LARGEFILE, 0);
+
+	if (IS_ERR(myfile)) {
+		const int open_errno = -PTR_ERR(myfile);
+		pr_err("%s(): ERROR opening file(%s) with errno = %d!\n",
+		       __func__, dev->_filename_ch2, open_errno);
+		return PTR_ERR(myfile);
+	} else {
+		if (!(myfile->f_op)) {
+			pr_err("%s(): File has no file operations registered!\n",
+			       __func__);
+			filp_close(myfile, NULL);
+			return -EIO;
+		}
+
+		if (!myfile->f_op->read) {
+			pr_err("%s(): File has no READ operations registered!  Returning\n",
+			       __func__);
+			filp_close(myfile, NULL);
+			return -EIO;
+		}
+
+		pos = myfile->f_pos;
+		old_fs = get_fs();
+		set_fs(KERNEL_DS);
+
+		for (j = 0; j < NUM_FRAMES; j++) {
+			for (i = 0; i < dev->_lines_count_ch2; i++) {
+				pos = offset;
+
+				vfs_read_retval = vfs_read(myfile, mybuf,
+						line_size, &pos);
+
+				if (vfs_read_retval > 0 &&
+				    vfs_read_retval == line_size &&
+				    dev->_data_buf_virt_addr_ch2 != NULL) {
+					memcpy((void *)(dev->
+							_data_buf_virt_addr_ch2
+							+ offset / 4), mybuf,
+							vfs_read_retval);
+				}
+
+				offset += vfs_read_retval;
+
+				if (vfs_read_retval < line_size) {
+					pr_info("Done: exit %s() since no more bytes to read from Video file\n",
+						__func__);
+					break;
+				}
+			}
+
+			if (i > 0)
+				dev->_frame_count_ch2++;
+
+			if (vfs_read_retval < line_size)
+				break;
+		}
+
+		dev->_file_status_ch2 = (vfs_read_retval == line_size) ?
+			IN_PROGRESS : END_OF_FILE;
+
+		set_fs(old_fs);
+		myfile->f_pos = 0;
+		filp_close(myfile, NULL);
+	}
+
+	return 0;
+}
+
+static int cx25821_upstream_buffer_prepare_ch2(struct cx25821_dev *dev,
+					       struct sram_channel *sram_ch,
+					       int bpl)
+{
+	int ret = 0;
+	dma_addr_t dma_addr;
+	dma_addr_t data_dma_addr;
+
+	if (dev->_dma_virt_addr_ch2 != NULL) {
+		pci_free_consistent(dev->pci, dev->upstream_riscbuf_size_ch2,
+				    dev->_dma_virt_addr_ch2,
+				    dev->_dma_phys_addr_ch2);
+	}
+
+	dev->_dma_virt_addr_ch2 = pci_alloc_consistent(dev->pci,
+			dev->upstream_riscbuf_size_ch2, &dma_addr);
+	dev->_dma_virt_start_addr_ch2 = dev->_dma_virt_addr_ch2;
+	dev->_dma_phys_start_addr_ch2 = dma_addr;
+	dev->_dma_phys_addr_ch2 = dma_addr;
+	dev->_risc_size_ch2 = dev->upstream_riscbuf_size_ch2;
+
+	if (!dev->_dma_virt_addr_ch2) {
+		pr_err("FAILED to allocate memory for Risc buffer! Returning\n");
+		return -ENOMEM;
+	}
+
+	/* Iniitize at this address until n bytes to 0 */
+	memset(dev->_dma_virt_addr_ch2, 0, dev->_risc_size_ch2);
+
+	if (dev->_data_buf_virt_addr_ch2 != NULL) {
+		pci_free_consistent(dev->pci, dev->upstream_databuf_size_ch2,
+				    dev->_data_buf_virt_addr_ch2,
+				    dev->_data_buf_phys_addr_ch2);
+	}
+	/* For Video Data buffer allocation */
+	dev->_data_buf_virt_addr_ch2 = pci_alloc_consistent(dev->pci,
+			dev->upstream_databuf_size_ch2, &data_dma_addr);
+	dev->_data_buf_phys_addr_ch2 = data_dma_addr;
+	dev->_data_buf_size_ch2 = dev->upstream_databuf_size_ch2;
+
+	if (!dev->_data_buf_virt_addr_ch2) {
+		pr_err("FAILED to allocate memory for data buffer! Returning\n");
+		return -ENOMEM;
+	}
+
+	/* Initialize at this address until n bytes to 0 */
+	memset(dev->_data_buf_virt_addr_ch2, 0, dev->_data_buf_size_ch2);
+
+	ret = cx25821_openfile_ch2(dev, sram_ch);
+	if (ret < 0)
+		return ret;
+
+	/* Creating RISC programs */
+	ret = cx25821_risc_buffer_upstream_ch2(dev, dev->pci, 0, bpl,
+						dev->_lines_count_ch2);
+	if (ret < 0) {
+		pr_info("Failed creating Video Upstream Risc programs!\n");
+		goto error;
+	}
+
+	return 0;
+
+error:
+	return ret;
+}
+
+int cx25821_video_upstream_irq_ch2(struct cx25821_dev *dev, int chan_num,
+				   u32 status)
+{
+	u32 int_msk_tmp;
+	struct sram_channel *channel = dev->channels[chan_num].sram_channels;
+	int singlefield_lines = NTSC_FIELD_HEIGHT;
+	int line_size_in_bytes = Y422_LINE_SZ;
+	int odd_risc_prog_size = 0;
+	dma_addr_t risc_phys_jump_addr;
+	__le32 *rp;
+
+	if (status & FLD_VID_SRC_RISC1) {
+		/* We should only process one program per call */
+		u32 prog_cnt = cx_read(channel->gpcnt);
+
+		/*
+		 *  Since we've identified our IRQ, clear our bits from the
+		 *  interrupt mask and interrupt status registers
+		 */
+		int_msk_tmp = cx_read(channel->int_msk);
+		cx_write(channel->int_msk, int_msk_tmp & ~_intr_msk);
+		cx_write(channel->int_stat, _intr_msk);
+
+		spin_lock(&dev->slock);
+
+		dev->_frame_index_ch2 = prog_cnt;
+
+		queue_work(dev->_irq_queues_ch2, &dev->_irq_work_entry_ch2);
+
+		if (dev->_is_first_frame_ch2) {
+			dev->_is_first_frame_ch2 = 0;
+
+			if (dev->_isNTSC_ch2) {
+				singlefield_lines += 1;
+				odd_risc_prog_size = ODD_FLD_NTSC_PROG_SIZE;
+			} else {
+				singlefield_lines = PAL_FIELD_HEIGHT;
+				odd_risc_prog_size = ODD_FLD_PAL_PROG_SIZE;
+			}
+
+			if (dev->_dma_virt_start_addr_ch2 != NULL) {
+				if (dev->_pixel_format_ch2 == PIXEL_FRMT_411)
+					line_size_in_bytes = Y411_LINE_SZ;
+				else
+					line_size_in_bytes = Y422_LINE_SZ;
+				risc_phys_jump_addr =
+					dev->_dma_phys_start_addr_ch2 +
+					odd_risc_prog_size;
+
+				rp = cx25821_update_riscprogram_ch2(dev,
+						dev->_dma_virt_start_addr_ch2,
+						TOP_OFFSET, line_size_in_bytes,
+						0x0, singlefield_lines,
+						FIFO_DISABLE, ODD_FIELD);
+
+			       /* Jump to Even Risc program of 1st Frame */
+				*(rp++) = cpu_to_le32(RISC_JUMP);
+				*(rp++) = cpu_to_le32(risc_phys_jump_addr);
+				*(rp++) = cpu_to_le32(0);
+			}
+		}
+
+		spin_unlock(&dev->slock);
+	}
+
+	if (dev->_file_status_ch2 == END_OF_FILE) {
+		pr_info("EOF Channel 2 Framecount = %d\n",
+			dev->_frame_count_ch2);
+		return -1;
+	}
+	/* ElSE, set the interrupt mask register, re-enable irq. */
+	int_msk_tmp = cx_read(channel->int_msk);
+	cx_write(channel->int_msk, int_msk_tmp |= _intr_msk);
+
+	return 0;
+}
+
+static irqreturn_t cx25821_upstream_irq_ch2(int irq, void *dev_id)
+{
+	struct cx25821_dev *dev = dev_id;
+	u32 vid_status;
+	int handled = 0;
+	int channel_num = 0;
+	struct sram_channel *sram_ch;
+
+	if (!dev)
+		return -1;
+
+	channel_num = VID_UPSTREAM_SRAM_CHANNEL_J;
+	sram_ch = dev->channels[channel_num].sram_channels;
+
+	vid_status = cx_read(sram_ch->int_stat);
+
+	/* Only deal with our interrupt */
+	if (vid_status)
+		handled = cx25821_video_upstream_irq_ch2(dev, channel_num,
+				vid_status);
+
+	if (handled < 0)
+		cx25821_stop_upstream_video_ch2(dev);
+	else
+		handled += handled;
+
+	return IRQ_RETVAL(handled);
+}
+
+static void cx25821_set_pixelengine_ch2(struct cx25821_dev *dev,
+					struct sram_channel *ch, int pix_format)
+{
+	int width = WIDTH_D1;
+	int height = dev->_lines_count_ch2;
+	int num_lines, odd_num_lines;
+	u32 value;
+	int vip_mode = PIXEL_ENGINE_VIP1;
+
+	value = ((pix_format & 0x3) << 12) | (vip_mode & 0x7);
+	value &= 0xFFFFFFEF;
+	value |= dev->_isNTSC_ch2 ? 0 : 0x10;
+	cx_write(ch->vid_fmt_ctl, value);
+
+	/*
+	 *  set number of active pixels in each line. Default is 720
+	 * pixels in both NTSC and PAL format
+	 */
+	cx_write(ch->vid_active_ctl1, width);
+
+	num_lines = (height / 2) & 0x3FF;
+	odd_num_lines = num_lines;
+
+	if (dev->_isNTSC_ch2)
+		odd_num_lines += 1;
+
+	value = (num_lines << 16) | odd_num_lines;
+
+	/* set number of active lines in field 0 (top) and field 1 (bottom) */
+	cx_write(ch->vid_active_ctl2, value);
+
+	cx_write(ch->vid_cdt_size, VID_CDT_SIZE >> 3);
+}
+
+int cx25821_start_video_dma_upstream_ch2(struct cx25821_dev *dev,
+					 struct sram_channel *sram_ch)
+{
+	u32 tmp = 0;
+	int err = 0;
+
+	/*
+	 *  656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface
+	 * for channel A-C
+	 */
+	tmp = cx_read(VID_CH_MODE_SEL);
+	cx_write(VID_CH_MODE_SEL, tmp | 0x1B0001FF);
+
+	/*
+	 *  Set the physical start address of the RISC program in the initial
+	 *  program counter(IPC) member of the cmds.
+	 */
+	cx_write(sram_ch->cmds_start + 0, dev->_dma_phys_addr_ch2);
+	cx_write(sram_ch->cmds_start + 4, 0); /* Risc IPC High 64 bits 63-32 */
+
+	/* reset counter */
+	cx_write(sram_ch->gpcnt_ctl, 3);
+
+	/* Clear our bits from the interrupt status register. */
+	cx_write(sram_ch->int_stat, _intr_msk);
+
+	/* Set the interrupt mask register, enable irq. */
+	cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | (1 << sram_ch->irq_bit));
+	tmp = cx_read(sram_ch->int_msk);
+	cx_write(sram_ch->int_msk, tmp |= _intr_msk);
+
+	err = request_irq(dev->pci->irq, cx25821_upstream_irq_ch2,
+			IRQF_SHARED, dev->name, dev);
+	if (err < 0) {
+		pr_err("%s: can't get upstream IRQ %d\n",
+		       dev->name, dev->pci->irq);
+		goto fail_irq;
+	}
+	/* Start the DMA  engine */
+	tmp = cx_read(sram_ch->dma_ctl);
+	cx_set(sram_ch->dma_ctl, tmp | FLD_VID_RISC_EN);
+
+	dev->_is_running_ch2 = 1;
+	dev->_is_first_frame_ch2 = 1;
+
+	return 0;
+
+fail_irq:
+	cx25821_dev_unregister(dev);
+	return err;
+}
+
+int cx25821_vidupstream_init_ch2(struct cx25821_dev *dev, int channel_select,
+				 int pixel_format)
+{
+	struct sram_channel *sram_ch;
+	u32 tmp;
+	int retval = 0;
+	int err = 0;
+	int data_frame_size = 0;
+	int risc_buffer_size = 0;
+	int str_length = 0;
+
+	if (dev->_is_running_ch2) {
+		pr_info("Video Channel is still running so return!\n");
+		return 0;
+	}
+
+	dev->_channel2_upstream_select = channel_select;
+	sram_ch = dev->channels[channel_select].sram_channels;
+
+	INIT_WORK(&dev->_irq_work_entry_ch2, cx25821_vidups_handler_ch2);
+	dev->_irq_queues_ch2 =
+	    create_singlethread_workqueue("cx25821_workqueue2");
+
+	if (!dev->_irq_queues_ch2) {
+		pr_err("create_singlethread_workqueue() for Video FAILED!\n");
+		return -ENOMEM;
+	}
+	/*
+	 * 656/VIP SRC Upstream Channel I & J and 7 -
+	 * Host Bus Interface for channel A-C
+	 */
+	tmp = cx_read(VID_CH_MODE_SEL);
+	cx_write(VID_CH_MODE_SEL, tmp | 0x1B0001FF);
+
+	dev->_is_running_ch2 = 0;
+	dev->_frame_count_ch2 = 0;
+	dev->_file_status_ch2 = RESET_STATUS;
+	dev->_lines_count_ch2 = dev->_isNTSC_ch2 ? 480 : 576;
+	dev->_pixel_format_ch2 = pixel_format;
+	dev->_line_size_ch2 = (dev->_pixel_format_ch2 == PIXEL_FRMT_422) ?
+		(WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2;
+	data_frame_size = dev->_isNTSC_ch2 ? NTSC_DATA_BUF_SZ : PAL_DATA_BUF_SZ;
+	risc_buffer_size = dev->_isNTSC_ch2 ?
+		NTSC_RISC_BUF_SIZE : PAL_RISC_BUF_SIZE;
+
+	if (dev->input_filename_ch2) {
+		str_length = strlen(dev->input_filename_ch2);
+		dev->_filename_ch2 = kmemdup(dev->input_filename_ch2,
+					     str_length + 1, GFP_KERNEL);
+
+		if (!dev->_filename_ch2)
+			goto error;
+	} else {
+		str_length = strlen(dev->_defaultname_ch2);
+		dev->_filename_ch2 = kmemdup(dev->_defaultname_ch2,
+					     str_length + 1, GFP_KERNEL);
+
+		if (!dev->_filename_ch2)
+			goto error;
+	}
+
+	/* Default if filename is empty string */
+	if (strcmp(dev->input_filename_ch2, "") == 0) {
+		if (dev->_isNTSC_ch2) {
+			dev->_filename_ch2 = (dev->_pixel_format_ch2 ==
+				PIXEL_FRMT_411) ? "/root/vid411.yuv" :
+				"/root/vidtest.yuv";
+		} else {
+			dev->_filename_ch2 = (dev->_pixel_format_ch2 ==
+				PIXEL_FRMT_411) ? "/root/pal411.yuv" :
+				"/root/pal422.yuv";
+		}
+	}
+
+	retval = cx25821_sram_channel_setup_upstream(dev, sram_ch,
+						dev->_line_size_ch2, 0);
+
+	/* setup fifo + format */
+	cx25821_set_pixelengine_ch2(dev, sram_ch, dev->_pixel_format_ch2);
+
+	dev->upstream_riscbuf_size_ch2 = risc_buffer_size * 2;
+	dev->upstream_databuf_size_ch2 = data_frame_size * 2;
+
+	/* Allocating buffers and prepare RISC program */
+	retval = cx25821_upstream_buffer_prepare_ch2(dev, sram_ch,
+						dev->_line_size_ch2);
+	if (retval < 0) {
+		pr_err("%s: Failed to set up Video upstream buffers!\n",
+		       dev->name);
+		goto error;
+	}
+
+	cx25821_start_video_dma_upstream_ch2(dev, sram_ch);
+
+	return 0;
+
+error:
+	cx25821_dev_unregister(dev);
+
+	return err;
+}
diff --git a/drivers/media/pci/cx25821/cx25821-video-upstream-ch2.h b/drivers/media/pci/cx25821/cx25821-video-upstream-ch2.h
new file mode 100644
index 0000000..d42dab5
--- /dev/null
+++ b/drivers/media/pci/cx25821/cx25821-video-upstream-ch2.h
@@ -0,0 +1,138 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <hiep.huynh@conexant.com>, <shu.lin@conexant.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/mutex.h>
+#include <linux/workqueue.h>
+
+#define OPEN_FILE_1           0
+#define NUM_PROGS             8
+#define NUM_FRAMES            2
+#define ODD_FIELD             0
+#define EVEN_FIELD            1
+#define TOP_OFFSET            0
+#define FIFO_DISABLE          0
+#define FIFO_ENABLE           1
+#define TEST_FRAMES           5
+#define END_OF_FILE           0
+#define IN_PROGRESS           1
+#define RESET_STATUS          -1
+#define NUM_NO_OPS            5
+
+/* PAL and NTSC line sizes and number of lines. */
+#define WIDTH_D1              720
+#define NTSC_LINES_PER_FRAME  480
+#define PAL_LINES_PER_FRAME   576
+#define PAL_LINE_SZ           1440
+#define Y422_LINE_SZ          1440
+#define Y411_LINE_SZ          1080
+#define NTSC_FIELD_HEIGHT     240
+#define NTSC_ODD_FLD_LINES    241
+#define PAL_FIELD_HEIGHT      288
+
+#define FRAME_SIZE_NTSC_Y422    (NTSC_LINES_PER_FRAME * Y422_LINE_SZ)
+#define FRAME_SIZE_NTSC_Y411    (NTSC_LINES_PER_FRAME * Y411_LINE_SZ)
+#define FRAME_SIZE_PAL_Y422     (PAL_LINES_PER_FRAME * Y422_LINE_SZ)
+#define FRAME_SIZE_PAL_Y411     (PAL_LINES_PER_FRAME * Y411_LINE_SZ)
+
+#define NTSC_DATA_BUF_SZ        (Y422_LINE_SZ * NTSC_LINES_PER_FRAME)
+#define PAL_DATA_BUF_SZ         (Y422_LINE_SZ * PAL_LINES_PER_FRAME)
+
+#define RISC_WRITECR_INSTRUCTION_SIZE   16
+#define RISC_SYNC_INSTRUCTION_SIZE      4
+#define JUMP_INSTRUCTION_SIZE           12
+#define MAXSIZE_NO_OPS                  36
+#define DWORD_SIZE                      4
+
+#define USE_RISC_NOOP_VIDEO   1
+
+#ifdef USE_RISC_NOOP_VIDEO
+#define PAL_US_VID_PROG_SIZE						\
+	(PAL_FIELD_HEIGHT * 3 * DWORD_SIZE +				\
+	 RISC_WRITECR_INSTRUCTION_SIZE + RISC_SYNC_INSTRUCTION_SIZE +	\
+	 NUM_NO_OPS * DWORD_SIZE)
+
+#define PAL_RISC_BUF_SIZE         (2 * PAL_US_VID_PROG_SIZE)
+
+#define PAL_VID_PROG_SIZE						\
+	((PAL_FIELD_HEIGHT * 2) * 3 * DWORD_SIZE +			\
+	 2 * RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \
+	 JUMP_INSTRUCTION_SIZE + 2 * NUM_NO_OPS * DWORD_SIZE)
+
+#define ODD_FLD_PAL_PROG_SIZE						\
+	(PAL_FIELD_HEIGHT * 3 * DWORD_SIZE +				\
+	 RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE +	\
+	 NUM_NO_OPS * DWORD_SIZE)
+
+#define NTSC_US_VID_PROG_SIZE						\
+	((NTSC_ODD_FLD_LINES + 1) * 3 * DWORD_SIZE +			\
+	 RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE +	\
+	 NUM_NO_OPS * DWORD_SIZE)
+
+#define NTSC_RISC_BUF_SIZE						\
+	(2 * (RISC_SYNC_INSTRUCTION_SIZE + NTSC_US_VID_PROG_SIZE))
+
+#define FRAME1_VID_PROG_SIZE						\
+	((NTSC_ODD_FLD_LINES + NTSC_FIELD_HEIGHT) *			\
+	 3 * DWORD_SIZE + 2 * RISC_SYNC_INSTRUCTION_SIZE +		\
+	 RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE +	\
+	 2 * NUM_NO_OPS * DWORD_SIZE)
+
+#define ODD_FLD_NTSC_PROG_SIZE						\
+	(NTSC_ODD_FLD_LINES * 3 * DWORD_SIZE +				\
+	 RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE +	\
+	 NUM_NO_OPS * DWORD_SIZE)
+#endif
+
+#ifndef USE_RISC_NOOP_VIDEO
+#define PAL_US_VID_PROG_SIZE						\
+	((PAL_FIELD_HEIGHT + 1) * 3 * DWORD_SIZE +			\
+	 RISC_WRITECR_INSTRUCTION_SIZE)
+
+#define PAL_RISC_BUF_SIZE						\
+	(2 * (RISC_SYNC_INSTRUCTION_SIZE + PAL_US_VID_PROG_SIZE))
+
+#define PAL_VID_PROG_SIZE						\
+	((PAL_FIELD_HEIGHT * 2) * 3 * DWORD_SIZE +			\
+	 2 * RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \
+	 JUMP_INSTRUCTION_SIZE)
+
+#define ODD_FLD_PAL_PROG_SIZE						\
+	(PAL_FIELD_HEIGHT * 3 * DWORD_SIZE +				\
+	 RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE)
+
+#define ODD_FLD_NTSC_PROG_SIZE						\
+	(NTSC_ODD_FLD_LINES * 3 * DWORD_SIZE +				\
+	 RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE)
+
+#define NTSC_US_VID_PROG_SIZE						\
+	((NTSC_ODD_FLD_LINES + 1) * 3 * DWORD_SIZE +			\
+	 RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE)
+
+#define NTSC_RISC_BUF_SIZE						\
+	(2 * (RISC_SYNC_INSTRUCTION_SIZE + NTSC_US_VID_PROG_SIZE))
+
+#define FRAME1_VID_PROG_SIZE						\
+	((NTSC_ODD_FLD_LINES + NTSC_FIELD_HEIGHT) *			\
+	 3 * DWORD_SIZE + 2 * RISC_SYNC_INSTRUCTION_SIZE +		\
+	 RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE)
+
+#endif
diff --git a/drivers/media/pci/cx25821/cx25821-video-upstream.c b/drivers/media/pci/cx25821/cx25821-video-upstream.c
new file mode 100644
index 0000000..52c13e0
--- /dev/null
+++ b/drivers/media/pci/cx25821/cx25821-video-upstream.c
@@ -0,0 +1,856 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <hiep.huynh@conexant.com>, <shu.lin@conexant.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include "cx25821-video.h"
+#include "cx25821-video-upstream.h"
+
+#include <linux/fs.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/syscalls.h>
+#include <linux/file.h>
+#include <linux/fcntl.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+
+MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards");
+MODULE_AUTHOR("Hiep Huynh <hiep.huynh@conexant.com>");
+MODULE_LICENSE("GPL");
+
+static int _intr_msk = FLD_VID_SRC_RISC1 | FLD_VID_SRC_UF | FLD_VID_SRC_SYNC |
+			FLD_VID_SRC_OPC_ERR;
+
+int cx25821_sram_channel_setup_upstream(struct cx25821_dev *dev,
+					struct sram_channel *ch,
+					unsigned int bpl, u32 risc)
+{
+	unsigned int i, lines;
+	u32 cdt;
+
+	if (ch->cmds_start == 0) {
+		cx_write(ch->ptr1_reg, 0);
+		cx_write(ch->ptr2_reg, 0);
+		cx_write(ch->cnt2_reg, 0);
+		cx_write(ch->cnt1_reg, 0);
+		return 0;
+	}
+
+	bpl = (bpl + 7) & ~7;	/* alignment */
+	cdt = ch->cdt;
+	lines = ch->fifo_size / bpl;
+
+	if (lines > 4)
+		lines = 4;
+
+	BUG_ON(lines < 2);
+
+	/* write CDT */
+	for (i = 0; i < lines; i++) {
+		cx_write(cdt + 16 * i, ch->fifo_start + bpl * i);
+		cx_write(cdt + 16 * i + 4, 0);
+		cx_write(cdt + 16 * i + 8, 0);
+		cx_write(cdt + 16 * i + 12, 0);
+	}
+
+	/* write CMDS */
+	cx_write(ch->cmds_start + 0, risc);
+
+	cx_write(ch->cmds_start + 4, 0);
+	cx_write(ch->cmds_start + 8, cdt);
+	cx_write(ch->cmds_start + 12, (lines * 16) >> 3);
+	cx_write(ch->cmds_start + 16, ch->ctrl_start);
+
+	cx_write(ch->cmds_start + 20, VID_IQ_SIZE_DW);
+
+	for (i = 24; i < 80; i += 4)
+		cx_write(ch->cmds_start + i, 0);
+
+	/* fill registers */
+	cx_write(ch->ptr1_reg, ch->fifo_start);
+	cx_write(ch->ptr2_reg, cdt);
+	cx_write(ch->cnt2_reg, (lines * 16) >> 3);
+	cx_write(ch->cnt1_reg, (bpl >> 3) - 1);
+
+	return 0;
+}
+
+static __le32 *cx25821_update_riscprogram(struct cx25821_dev *dev,
+					  __le32 *rp, unsigned int offset,
+					  unsigned int bpl, u32 sync_line,
+					  unsigned int lines, int fifo_enable,
+					  int field_type)
+{
+	unsigned int line, i;
+	int dist_betwn_starts = bpl * 2;
+
+	*(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
+
+	if (USE_RISC_NOOP_VIDEO) {
+		for (i = 0; i < NUM_NO_OPS; i++)
+			*(rp++) = cpu_to_le32(RISC_NOOP);
+	}
+
+	/* scan lines */
+	for (line = 0; line < lines; line++) {
+		*(rp++) = cpu_to_le32(RISC_READ | RISC_SOL | RISC_EOL | bpl);
+		*(rp++) = cpu_to_le32(dev->_data_buf_phys_addr + offset);
+		*(rp++) = cpu_to_le32(0);	/* bits 63-32 */
+
+		if ((lines <= NTSC_FIELD_HEIGHT)
+		    || (line < (NTSC_FIELD_HEIGHT - 1)) || !(dev->_isNTSC)) {
+			offset += dist_betwn_starts;
+		}
+	}
+
+	return rp;
+}
+
+static __le32 *cx25821_risc_field_upstream(struct cx25821_dev *dev, __le32 * rp,
+					   dma_addr_t databuf_phys_addr,
+					   unsigned int offset, u32 sync_line,
+					   unsigned int bpl, unsigned int lines,
+					   int fifo_enable, int field_type)
+{
+	unsigned int line, i;
+	struct sram_channel *sram_ch =
+		dev->channels[dev->_channel_upstream_select].sram_channels;
+	int dist_betwn_starts = bpl * 2;
+
+	/* sync instruction */
+	if (sync_line != NO_SYNC_LINE)
+		*(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
+
+	if (USE_RISC_NOOP_VIDEO) {
+		for (i = 0; i < NUM_NO_OPS; i++)
+			*(rp++) = cpu_to_le32(RISC_NOOP);
+	}
+
+	/* scan lines */
+	for (line = 0; line < lines; line++) {
+		*(rp++) = cpu_to_le32(RISC_READ | RISC_SOL | RISC_EOL | bpl);
+		*(rp++) = cpu_to_le32(databuf_phys_addr + offset);
+		*(rp++) = cpu_to_le32(0);	/* bits 63-32 */
+
+		if ((lines <= NTSC_FIELD_HEIGHT)
+		    || (line < (NTSC_FIELD_HEIGHT - 1)) || !(dev->_isNTSC))
+			/* to skip the other field line */
+			offset += dist_betwn_starts;
+
+		/* check if we need to enable the FIFO after the first 4 lines
+		 * For the upstream video channel, the risc engine will enable
+		 * the FIFO. */
+		if (fifo_enable && line == 3) {
+			*(rp++) = RISC_WRITECR;
+			*(rp++) = sram_ch->dma_ctl;
+			*(rp++) = FLD_VID_FIFO_EN;
+			*(rp++) = 0x00000001;
+		}
+	}
+
+	return rp;
+}
+
+int cx25821_risc_buffer_upstream(struct cx25821_dev *dev,
+				 struct pci_dev *pci,
+				 unsigned int top_offset,
+				 unsigned int bpl, unsigned int lines)
+{
+	__le32 *rp;
+	int fifo_enable = 0;
+	/* get line count for single field */
+	int singlefield_lines = lines >> 1;
+	int odd_num_lines = singlefield_lines;
+	int frame = 0;
+	int frame_size = 0;
+	int databuf_offset = 0;
+	int risc_program_size = 0;
+	int risc_flag = RISC_CNT_RESET;
+	unsigned int bottom_offset = bpl;
+	dma_addr_t risc_phys_jump_addr;
+
+	if (dev->_isNTSC) {
+		odd_num_lines = singlefield_lines + 1;
+		risc_program_size = FRAME1_VID_PROG_SIZE;
+		frame_size = (bpl == Y411_LINE_SZ) ?
+			FRAME_SIZE_NTSC_Y411 : FRAME_SIZE_NTSC_Y422;
+	} else {
+		risc_program_size = PAL_VID_PROG_SIZE;
+		frame_size = (bpl == Y411_LINE_SZ) ?
+			FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422;
+	}
+
+	/* Virtual address of Risc buffer program */
+	rp = dev->_dma_virt_addr;
+
+	for (frame = 0; frame < NUM_FRAMES; frame++) {
+		databuf_offset = frame_size * frame;
+
+		if (UNSET != top_offset) {
+			fifo_enable = (frame == 0) ? FIFO_ENABLE : FIFO_DISABLE;
+			rp = cx25821_risc_field_upstream(dev, rp,
+					dev->_data_buf_phys_addr +
+					databuf_offset, top_offset, 0, bpl,
+					odd_num_lines, fifo_enable, ODD_FIELD);
+		}
+
+		fifo_enable = FIFO_DISABLE;
+
+		/* Even Field */
+		rp = cx25821_risc_field_upstream(dev, rp,
+						 dev->_data_buf_phys_addr +
+						 databuf_offset, bottom_offset,
+						 0x200, bpl, singlefield_lines,
+						 fifo_enable, EVEN_FIELD);
+
+		if (frame == 0) {
+			risc_flag = RISC_CNT_RESET;
+			risc_phys_jump_addr = dev->_dma_phys_start_addr +
+				risc_program_size;
+		} else {
+			risc_phys_jump_addr = dev->_dma_phys_start_addr;
+			risc_flag = RISC_CNT_INC;
+		}
+
+		/* Loop to 2ndFrameRISC or to Start of Risc
+		 * program & generate IRQ
+		 */
+		*(rp++) = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | risc_flag);
+		*(rp++) = cpu_to_le32(risc_phys_jump_addr);
+		*(rp++) = cpu_to_le32(0);
+	}
+
+	return 0;
+}
+
+void cx25821_stop_upstream_video_ch1(struct cx25821_dev *dev)
+{
+	struct sram_channel *sram_ch =
+		dev->channels[VID_UPSTREAM_SRAM_CHANNEL_I].sram_channels;
+	u32 tmp = 0;
+
+	if (!dev->_is_running) {
+		pr_info("No video file is currently running so return!\n");
+		return;
+	}
+	/* Disable RISC interrupts */
+	tmp = cx_read(sram_ch->int_msk);
+	cx_write(sram_ch->int_msk, tmp & ~_intr_msk);
+
+	/* Turn OFF risc and fifo enable */
+	tmp = cx_read(sram_ch->dma_ctl);
+	cx_write(sram_ch->dma_ctl, tmp & ~(FLD_VID_FIFO_EN | FLD_VID_RISC_EN));
+
+	/* Clear data buffer memory */
+	if (dev->_data_buf_virt_addr)
+		memset(dev->_data_buf_virt_addr, 0, dev->_data_buf_size);
+
+	dev->_is_running = 0;
+	dev->_is_first_frame = 0;
+	dev->_frame_count = 0;
+	dev->_file_status = END_OF_FILE;
+
+	kfree(dev->_irq_queues);
+	dev->_irq_queues = NULL;
+
+	kfree(dev->_filename);
+
+	tmp = cx_read(VID_CH_MODE_SEL);
+	cx_write(VID_CH_MODE_SEL, tmp & 0xFFFFFE00);
+}
+
+void cx25821_free_mem_upstream_ch1(struct cx25821_dev *dev)
+{
+	if (dev->_is_running)
+		cx25821_stop_upstream_video_ch1(dev);
+
+	if (dev->_dma_virt_addr) {
+		pci_free_consistent(dev->pci, dev->_risc_size,
+				    dev->_dma_virt_addr, dev->_dma_phys_addr);
+		dev->_dma_virt_addr = NULL;
+	}
+
+	if (dev->_data_buf_virt_addr) {
+		pci_free_consistent(dev->pci, dev->_data_buf_size,
+				    dev->_data_buf_virt_addr,
+				    dev->_data_buf_phys_addr);
+		dev->_data_buf_virt_addr = NULL;
+	}
+}
+
+int cx25821_get_frame(struct cx25821_dev *dev, struct sram_channel *sram_ch)
+{
+	struct file *myfile;
+	int frame_index_temp = dev->_frame_index;
+	int i = 0;
+	int line_size = (dev->_pixel_format == PIXEL_FRMT_411) ?
+		Y411_LINE_SZ : Y422_LINE_SZ;
+	int frame_size = 0;
+	int frame_offset = 0;
+	ssize_t vfs_read_retval = 0;
+	char mybuf[line_size];
+	loff_t file_offset;
+	loff_t pos;
+	mm_segment_t old_fs;
+
+	if (dev->_file_status == END_OF_FILE)
+		return 0;
+
+	if (dev->_isNTSC)
+		frame_size = (line_size == Y411_LINE_SZ) ?
+			FRAME_SIZE_NTSC_Y411 : FRAME_SIZE_NTSC_Y422;
+	else
+		frame_size = (line_size == Y411_LINE_SZ) ?
+			FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422;
+
+	frame_offset = (frame_index_temp > 0) ? frame_size : 0;
+	file_offset = dev->_frame_count * frame_size;
+
+	myfile = filp_open(dev->_filename, O_RDONLY | O_LARGEFILE, 0);
+
+	if (IS_ERR(myfile)) {
+		const int open_errno = -PTR_ERR(myfile);
+		pr_err("%s(): ERROR opening file(%s) with errno = %d!\n",
+		       __func__, dev->_filename, open_errno);
+		return PTR_ERR(myfile);
+	} else {
+		if (!(myfile->f_op)) {
+			pr_err("%s(): File has no file operations registered!\n",
+			       __func__);
+			filp_close(myfile, NULL);
+			return -EIO;
+		}
+
+		if (!myfile->f_op->read) {
+			pr_err("%s(): File has no READ operations registered!\n",
+			       __func__);
+			filp_close(myfile, NULL);
+			return -EIO;
+		}
+
+		pos = myfile->f_pos;
+		old_fs = get_fs();
+		set_fs(KERNEL_DS);
+
+		for (i = 0; i < dev->_lines_count; i++) {
+			pos = file_offset;
+
+			vfs_read_retval = vfs_read(myfile, mybuf, line_size,
+					&pos);
+
+			if (vfs_read_retval > 0 && vfs_read_retval == line_size
+			    && dev->_data_buf_virt_addr != NULL) {
+				memcpy((void *)(dev->_data_buf_virt_addr +
+						frame_offset / 4), mybuf,
+				       vfs_read_retval);
+			}
+
+			file_offset += vfs_read_retval;
+			frame_offset += vfs_read_retval;
+
+			if (vfs_read_retval < line_size) {
+				pr_info("Done: exit %s() since no more bytes to read from Video file\n",
+					__func__);
+				break;
+			}
+		}
+
+		if (i > 0)
+			dev->_frame_count++;
+
+		dev->_file_status = (vfs_read_retval == line_size) ?
+			IN_PROGRESS : END_OF_FILE;
+
+		set_fs(old_fs);
+		filp_close(myfile, NULL);
+	}
+
+	return 0;
+}
+
+static void cx25821_vidups_handler(struct work_struct *work)
+{
+	struct cx25821_dev *dev = container_of(work, struct cx25821_dev,
+			_irq_work_entry);
+
+	if (!dev) {
+		pr_err("ERROR %s(): since container_of(work_struct) FAILED!\n",
+		       __func__);
+		return;
+	}
+
+	cx25821_get_frame(dev, dev->channels[dev->_channel_upstream_select].
+			sram_channels);
+}
+
+int cx25821_openfile(struct cx25821_dev *dev, struct sram_channel *sram_ch)
+{
+	struct file *myfile;
+	int i = 0, j = 0;
+	int line_size = (dev->_pixel_format == PIXEL_FRMT_411) ?
+		Y411_LINE_SZ : Y422_LINE_SZ;
+	ssize_t vfs_read_retval = 0;
+	char mybuf[line_size];
+	loff_t pos;
+	loff_t offset = (unsigned long)0;
+	mm_segment_t old_fs;
+
+	myfile = filp_open(dev->_filename, O_RDONLY | O_LARGEFILE, 0);
+
+	if (IS_ERR(myfile)) {
+		const int open_errno = -PTR_ERR(myfile);
+		pr_err("%s(): ERROR opening file(%s) with errno = %d!\n",
+		       __func__, dev->_filename, open_errno);
+		return PTR_ERR(myfile);
+	} else {
+		if (!(myfile->f_op)) {
+			pr_err("%s(): File has no file operations registered!\n",
+			       __func__);
+			filp_close(myfile, NULL);
+			return -EIO;
+		}
+
+		if (!myfile->f_op->read) {
+			pr_err("%s(): File has no READ operations registered!  Returning\n",
+			       __func__);
+			filp_close(myfile, NULL);
+			return -EIO;
+		}
+
+		pos = myfile->f_pos;
+		old_fs = get_fs();
+		set_fs(KERNEL_DS);
+
+		for (j = 0; j < NUM_FRAMES; j++) {
+			for (i = 0; i < dev->_lines_count; i++) {
+				pos = offset;
+
+				vfs_read_retval = vfs_read(myfile, mybuf,
+						line_size, &pos);
+
+				if (vfs_read_retval > 0
+				    && vfs_read_retval == line_size
+				    && dev->_data_buf_virt_addr != NULL) {
+					memcpy((void *)(dev->
+							_data_buf_virt_addr +
+							offset / 4), mybuf,
+					       vfs_read_retval);
+				}
+
+				offset += vfs_read_retval;
+
+				if (vfs_read_retval < line_size) {
+					pr_info("Done: exit %s() since no more bytes to read from Video file\n",
+						__func__);
+					break;
+				}
+			}
+
+			if (i > 0)
+				dev->_frame_count++;
+
+			if (vfs_read_retval < line_size)
+				break;
+		}
+
+		dev->_file_status = (vfs_read_retval == line_size) ?
+			IN_PROGRESS : END_OF_FILE;
+
+		set_fs(old_fs);
+		myfile->f_pos = 0;
+		filp_close(myfile, NULL);
+	}
+
+	return 0;
+}
+
+int cx25821_upstream_buffer_prepare(struct cx25821_dev *dev,
+				    struct sram_channel *sram_ch, int bpl)
+{
+	int ret = 0;
+	dma_addr_t dma_addr;
+	dma_addr_t data_dma_addr;
+
+	if (dev->_dma_virt_addr != NULL)
+		pci_free_consistent(dev->pci, dev->upstream_riscbuf_size,
+				dev->_dma_virt_addr, dev->_dma_phys_addr);
+
+	dev->_dma_virt_addr = pci_alloc_consistent(dev->pci,
+			dev->upstream_riscbuf_size, &dma_addr);
+	dev->_dma_virt_start_addr = dev->_dma_virt_addr;
+	dev->_dma_phys_start_addr = dma_addr;
+	dev->_dma_phys_addr = dma_addr;
+	dev->_risc_size = dev->upstream_riscbuf_size;
+
+	if (!dev->_dma_virt_addr) {
+		pr_err("FAILED to allocate memory for Risc buffer! Returning\n");
+		return -ENOMEM;
+	}
+
+	/* Clear memory at address */
+	memset(dev->_dma_virt_addr, 0, dev->_risc_size);
+
+	if (dev->_data_buf_virt_addr != NULL)
+		pci_free_consistent(dev->pci, dev->upstream_databuf_size,
+				dev->_data_buf_virt_addr,
+				dev->_data_buf_phys_addr);
+	/* For Video Data buffer allocation */
+	dev->_data_buf_virt_addr = pci_alloc_consistent(dev->pci,
+			dev->upstream_databuf_size, &data_dma_addr);
+	dev->_data_buf_phys_addr = data_dma_addr;
+	dev->_data_buf_size = dev->upstream_databuf_size;
+
+	if (!dev->_data_buf_virt_addr) {
+		pr_err("FAILED to allocate memory for data buffer! Returning\n");
+		return -ENOMEM;
+	}
+
+	/* Clear memory at address */
+	memset(dev->_data_buf_virt_addr, 0, dev->_data_buf_size);
+
+	ret = cx25821_openfile(dev, sram_ch);
+	if (ret < 0)
+		return ret;
+
+	/* Create RISC programs */
+	ret = cx25821_risc_buffer_upstream(dev, dev->pci, 0, bpl,
+			dev->_lines_count);
+	if (ret < 0) {
+		pr_info("Failed creating Video Upstream Risc programs!\n");
+		goto error;
+	}
+
+	return 0;
+
+error:
+	return ret;
+}
+
+int cx25821_video_upstream_irq(struct cx25821_dev *dev, int chan_num,
+			       u32 status)
+{
+	u32 int_msk_tmp;
+	struct sram_channel *channel = dev->channels[chan_num].sram_channels;
+	int singlefield_lines = NTSC_FIELD_HEIGHT;
+	int line_size_in_bytes = Y422_LINE_SZ;
+	int odd_risc_prog_size = 0;
+	dma_addr_t risc_phys_jump_addr;
+	__le32 *rp;
+
+	if (status & FLD_VID_SRC_RISC1) {
+		/* We should only process one program per call */
+		u32 prog_cnt = cx_read(channel->gpcnt);
+
+		/* Since we've identified our IRQ, clear our bits from the
+		 * interrupt mask and interrupt status registers */
+		int_msk_tmp = cx_read(channel->int_msk);
+		cx_write(channel->int_msk, int_msk_tmp & ~_intr_msk);
+		cx_write(channel->int_stat, _intr_msk);
+
+		spin_lock(&dev->slock);
+
+		dev->_frame_index = prog_cnt;
+
+		queue_work(dev->_irq_queues, &dev->_irq_work_entry);
+
+		if (dev->_is_first_frame) {
+			dev->_is_first_frame = 0;
+
+			if (dev->_isNTSC) {
+				singlefield_lines += 1;
+				odd_risc_prog_size = ODD_FLD_NTSC_PROG_SIZE;
+			} else {
+				singlefield_lines = PAL_FIELD_HEIGHT;
+				odd_risc_prog_size = ODD_FLD_PAL_PROG_SIZE;
+			}
+
+			if (dev->_dma_virt_start_addr != NULL) {
+				line_size_in_bytes =
+				    (dev->_pixel_format ==
+				     PIXEL_FRMT_411) ? Y411_LINE_SZ :
+				    Y422_LINE_SZ;
+				risc_phys_jump_addr =
+				    dev->_dma_phys_start_addr +
+				    odd_risc_prog_size;
+
+				rp = cx25821_update_riscprogram(dev,
+					dev->_dma_virt_start_addr, TOP_OFFSET,
+					line_size_in_bytes, 0x0,
+					singlefield_lines, FIFO_DISABLE,
+					ODD_FIELD);
+
+				/* Jump to Even Risc program of 1st Frame */
+				*(rp++) = cpu_to_le32(RISC_JUMP);
+				*(rp++) = cpu_to_le32(risc_phys_jump_addr);
+				*(rp++) = cpu_to_le32(0);
+			}
+		}
+
+		spin_unlock(&dev->slock);
+	} else {
+		if (status & FLD_VID_SRC_UF)
+			pr_err("%s(): Video Received Underflow Error Interrupt!\n",
+			       __func__);
+
+		if (status & FLD_VID_SRC_SYNC)
+			pr_err("%s(): Video Received Sync Error Interrupt!\n",
+			       __func__);
+
+		if (status & FLD_VID_SRC_OPC_ERR)
+			pr_err("%s(): Video Received OpCode Error Interrupt!\n",
+			       __func__);
+	}
+
+	if (dev->_file_status == END_OF_FILE) {
+		pr_err("EOF Channel 1 Framecount = %d\n", dev->_frame_count);
+		return -1;
+	}
+	/* ElSE, set the interrupt mask register, re-enable irq. */
+	int_msk_tmp = cx_read(channel->int_msk);
+	cx_write(channel->int_msk, int_msk_tmp |= _intr_msk);
+
+	return 0;
+}
+
+static irqreturn_t cx25821_upstream_irq(int irq, void *dev_id)
+{
+	struct cx25821_dev *dev = dev_id;
+	u32 vid_status;
+	int handled = 0;
+	int channel_num = 0;
+	struct sram_channel *sram_ch;
+
+	if (!dev)
+		return -1;
+
+	channel_num = VID_UPSTREAM_SRAM_CHANNEL_I;
+
+	sram_ch = dev->channels[channel_num].sram_channels;
+
+	vid_status = cx_read(sram_ch->int_stat);
+
+	/* Only deal with our interrupt */
+	if (vid_status)
+		handled = cx25821_video_upstream_irq(dev, channel_num,
+				vid_status);
+
+	if (handled < 0)
+		cx25821_stop_upstream_video_ch1(dev);
+	else
+		handled += handled;
+
+	return IRQ_RETVAL(handled);
+}
+
+void cx25821_set_pixelengine(struct cx25821_dev *dev, struct sram_channel *ch,
+			     int pix_format)
+{
+	int width = WIDTH_D1;
+	int height = dev->_lines_count;
+	int num_lines, odd_num_lines;
+	u32 value;
+	int vip_mode = OUTPUT_FRMT_656;
+
+	value = ((pix_format & 0x3) << 12) | (vip_mode & 0x7);
+	value &= 0xFFFFFFEF;
+	value |= dev->_isNTSC ? 0 : 0x10;
+	cx_write(ch->vid_fmt_ctl, value);
+
+	/* set number of active pixels in each line.
+	 * Default is 720 pixels in both NTSC and PAL format */
+	cx_write(ch->vid_active_ctl1, width);
+
+	num_lines = (height / 2) & 0x3FF;
+	odd_num_lines = num_lines;
+
+	if (dev->_isNTSC)
+		odd_num_lines += 1;
+
+	value = (num_lines << 16) | odd_num_lines;
+
+	/* set number of active lines in field 0 (top) and field 1 (bottom) */
+	cx_write(ch->vid_active_ctl2, value);
+
+	cx_write(ch->vid_cdt_size, VID_CDT_SIZE >> 3);
+}
+
+int cx25821_start_video_dma_upstream(struct cx25821_dev *dev,
+				     struct sram_channel *sram_ch)
+{
+	u32 tmp = 0;
+	int err = 0;
+
+	/* 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for
+	 * channel A-C
+	 */
+	tmp = cx_read(VID_CH_MODE_SEL);
+	cx_write(VID_CH_MODE_SEL, tmp | 0x1B0001FF);
+
+	/* Set the physical start address of the RISC program in the initial
+	 * program counter(IPC) member of the cmds.
+	 */
+	cx_write(sram_ch->cmds_start + 0, dev->_dma_phys_addr);
+	/* Risc IPC High 64 bits 63-32 */
+	cx_write(sram_ch->cmds_start + 4, 0);
+
+	/* reset counter */
+	cx_write(sram_ch->gpcnt_ctl, 3);
+
+	/* Clear our bits from the interrupt status register. */
+	cx_write(sram_ch->int_stat, _intr_msk);
+
+	/* Set the interrupt mask register, enable irq. */
+	cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | (1 << sram_ch->irq_bit));
+	tmp = cx_read(sram_ch->int_msk);
+	cx_write(sram_ch->int_msk, tmp |= _intr_msk);
+
+	err = request_irq(dev->pci->irq, cx25821_upstream_irq,
+			IRQF_SHARED, dev->name, dev);
+	if (err < 0) {
+		pr_err("%s: can't get upstream IRQ %d\n",
+		       dev->name, dev->pci->irq);
+		goto fail_irq;
+	}
+
+	/* Start the DMA  engine */
+	tmp = cx_read(sram_ch->dma_ctl);
+	cx_set(sram_ch->dma_ctl, tmp | FLD_VID_RISC_EN);
+
+	dev->_is_running = 1;
+	dev->_is_first_frame = 1;
+
+	return 0;
+
+fail_irq:
+	cx25821_dev_unregister(dev);
+	return err;
+}
+
+int cx25821_vidupstream_init_ch1(struct cx25821_dev *dev, int channel_select,
+				 int pixel_format)
+{
+	struct sram_channel *sram_ch;
+	u32 tmp;
+	int retval = 0;
+	int err = 0;
+	int data_frame_size = 0;
+	int risc_buffer_size = 0;
+	int str_length = 0;
+
+	if (dev->_is_running) {
+		pr_info("Video Channel is still running so return!\n");
+		return 0;
+	}
+
+	dev->_channel_upstream_select = channel_select;
+	sram_ch = dev->channels[channel_select].sram_channels;
+
+	INIT_WORK(&dev->_irq_work_entry, cx25821_vidups_handler);
+	dev->_irq_queues = create_singlethread_workqueue("cx25821_workqueue");
+
+	if (!dev->_irq_queues) {
+		pr_err("create_singlethread_workqueue() for Video FAILED!\n");
+		return -ENOMEM;
+	}
+	/* 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface for
+	 * channel A-C
+	 */
+	tmp = cx_read(VID_CH_MODE_SEL);
+	cx_write(VID_CH_MODE_SEL, tmp | 0x1B0001FF);
+
+	dev->_is_running = 0;
+	dev->_frame_count = 0;
+	dev->_file_status = RESET_STATUS;
+	dev->_lines_count = dev->_isNTSC ? 480 : 576;
+	dev->_pixel_format = pixel_format;
+	dev->_line_size = (dev->_pixel_format == PIXEL_FRMT_422) ?
+		(WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2;
+	data_frame_size = dev->_isNTSC ? NTSC_DATA_BUF_SZ : PAL_DATA_BUF_SZ;
+	risc_buffer_size = dev->_isNTSC ?
+		NTSC_RISC_BUF_SIZE : PAL_RISC_BUF_SIZE;
+
+	if (dev->input_filename) {
+		str_length = strlen(dev->input_filename);
+		dev->_filename = kmemdup(dev->input_filename, str_length + 1,
+					 GFP_KERNEL);
+
+		if (!dev->_filename)
+			goto error;
+	} else {
+		str_length = strlen(dev->_defaultname);
+		dev->_filename = kmemdup(dev->_defaultname, str_length + 1,
+					 GFP_KERNEL);
+
+		if (!dev->_filename)
+			goto error;
+	}
+
+	/* Default if filename is empty string */
+	if (strcmp(dev->input_filename, "") == 0) {
+		if (dev->_isNTSC) {
+			dev->_filename =
+				(dev->_pixel_format == PIXEL_FRMT_411) ?
+				"/root/vid411.yuv" : "/root/vidtest.yuv";
+		} else {
+			dev->_filename =
+				(dev->_pixel_format == PIXEL_FRMT_411) ?
+				"/root/pal411.yuv" : "/root/pal422.yuv";
+		}
+	}
+
+	dev->_is_running = 0;
+	dev->_frame_count = 0;
+	dev->_file_status = RESET_STATUS;
+	dev->_lines_count = dev->_isNTSC ? 480 : 576;
+	dev->_pixel_format = pixel_format;
+	dev->_line_size = (dev->_pixel_format == PIXEL_FRMT_422) ?
+		(WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2;
+
+	retval = cx25821_sram_channel_setup_upstream(dev, sram_ch,
+			dev->_line_size, 0);
+
+	/* setup fifo + format */
+	cx25821_set_pixelengine(dev, sram_ch, dev->_pixel_format);
+
+	dev->upstream_riscbuf_size = risc_buffer_size * 2;
+	dev->upstream_databuf_size = data_frame_size * 2;
+
+	/* Allocating buffers and prepare RISC program */
+	retval = cx25821_upstream_buffer_prepare(dev, sram_ch, dev->_line_size);
+	if (retval < 0) {
+		pr_err("%s: Failed to set up Video upstream buffers!\n",
+		       dev->name);
+		goto error;
+	}
+
+	cx25821_start_video_dma_upstream(dev, sram_ch);
+
+	return 0;
+
+error:
+	cx25821_dev_unregister(dev);
+
+	return err;
+}
diff --git a/drivers/media/pci/cx25821/cx25821-video-upstream.h b/drivers/media/pci/cx25821/cx25821-video-upstream.h
new file mode 100644
index 0000000..268ec8a
--- /dev/null
+++ b/drivers/media/pci/cx25821/cx25821-video-upstream.h
@@ -0,0 +1,139 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <hiep.huynh@conexant.com>, <shu.lin@conexant.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/mutex.h>
+#include <linux/workqueue.h>
+
+#define OUTPUT_FRMT_656       0
+#define OPEN_FILE_1           0
+#define NUM_PROGS             8
+#define NUM_FRAMES            2
+#define ODD_FIELD             0
+#define EVEN_FIELD            1
+#define TOP_OFFSET            0
+#define FIFO_DISABLE          0
+#define FIFO_ENABLE           1
+#define TEST_FRAMES           5
+#define END_OF_FILE           0
+#define IN_PROGRESS           1
+#define RESET_STATUS          -1
+#define NUM_NO_OPS            5
+
+/* PAL and NTSC line sizes and number of lines. */
+#define WIDTH_D1              720
+#define NTSC_LINES_PER_FRAME  480
+#define PAL_LINES_PER_FRAME   576
+#define PAL_LINE_SZ           1440
+#define Y422_LINE_SZ          1440
+#define Y411_LINE_SZ          1080
+#define NTSC_FIELD_HEIGHT     240
+#define NTSC_ODD_FLD_LINES    241
+#define PAL_FIELD_HEIGHT      288
+
+#define FRAME_SIZE_NTSC_Y422    (NTSC_LINES_PER_FRAME * Y422_LINE_SZ)
+#define FRAME_SIZE_NTSC_Y411    (NTSC_LINES_PER_FRAME * Y411_LINE_SZ)
+#define FRAME_SIZE_PAL_Y422     (PAL_LINES_PER_FRAME * Y422_LINE_SZ)
+#define FRAME_SIZE_PAL_Y411     (PAL_LINES_PER_FRAME * Y411_LINE_SZ)
+
+#define NTSC_DATA_BUF_SZ        (Y422_LINE_SZ * NTSC_LINES_PER_FRAME)
+#define PAL_DATA_BUF_SZ         (Y422_LINE_SZ * PAL_LINES_PER_FRAME)
+
+#define RISC_WRITECR_INSTRUCTION_SIZE   16
+#define RISC_SYNC_INSTRUCTION_SIZE      4
+#define JUMP_INSTRUCTION_SIZE           12
+#define MAXSIZE_NO_OPS                  36
+#define DWORD_SIZE                      4
+
+#define USE_RISC_NOOP_VIDEO   1
+
+#ifdef USE_RISC_NOOP_VIDEO
+#define PAL_US_VID_PROG_SIZE						\
+	(PAL_FIELD_HEIGHT * 3 * DWORD_SIZE +				\
+	 RISC_WRITECR_INSTRUCTION_SIZE + RISC_SYNC_INSTRUCTION_SIZE +	\
+	 NUM_NO_OPS * DWORD_SIZE)
+
+#define PAL_RISC_BUF_SIZE           (2 * PAL_US_VID_PROG_SIZE)
+
+#define PAL_VID_PROG_SIZE						\
+	((PAL_FIELD_HEIGHT * 2) * 3 * DWORD_SIZE +			\
+	 2 * RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \
+	 JUMP_INSTRUCTION_SIZE + 2 * NUM_NO_OPS * DWORD_SIZE)
+
+#define ODD_FLD_PAL_PROG_SIZE						\
+	(PAL_FIELD_HEIGHT * 3 * DWORD_SIZE +				\
+	 RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE +	\
+	 NUM_NO_OPS * DWORD_SIZE)
+
+#define ODD_FLD_NTSC_PROG_SIZE						\
+	(NTSC_ODD_FLD_LINES * 3 * DWORD_SIZE +				\
+	 RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE +	\
+	 NUM_NO_OPS * DWORD_SIZE)
+
+#define NTSC_US_VID_PROG_SIZE						\
+	((NTSC_ODD_FLD_LINES + 1) * 3 * DWORD_SIZE +			\
+	 RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE +	\
+	 NUM_NO_OPS * DWORD_SIZE)
+
+#define NTSC_RISC_BUF_SIZE						\
+	(2 * (RISC_SYNC_INSTRUCTION_SIZE + NTSC_US_VID_PROG_SIZE))
+
+#define FRAME1_VID_PROG_SIZE						\
+	((NTSC_ODD_FLD_LINES + NTSC_FIELD_HEIGHT) * 3 * DWORD_SIZE +	\
+	 2 * RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \
+	 JUMP_INSTRUCTION_SIZE + 2 * NUM_NO_OPS * DWORD_SIZE)
+
+#endif
+
+#ifndef USE_RISC_NOOP_VIDEO
+#define PAL_US_VID_PROG_SIZE						\
+	(PAL_FIELD_HEIGHT * 3 * DWORD_SIZE +				\
+	 RISC_WRITECR_INSTRUCTION_SIZE + RISC_SYNC_INSTRUCTION_SIZE +	\
+	 JUMP_INSTRUCTION_SIZE)
+
+#define PAL_RISC_BUF_SIZE		(2 * PAL_US_VID_PROG_SIZE)
+
+#define PAL_VID_PROG_SIZE						\
+	((PAL_FIELD_HEIGHT * 2) * 3 * DWORD_SIZE +			\
+	 2 * RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \
+	 JUMP_INSTRUCTION_SIZE)
+
+#define ODD_FLD_PAL_PROG_SIZE						\
+	(PAL_FIELD_HEIGHT * 3 * DWORD_SIZE +				\
+	 RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE)
+
+#define ODD_FLD_NTSC_PROG_SIZE						\
+	(NTSC_ODD_FLD_LINES * 3 * DWORD_SIZE +				\
+	 RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE)
+
+#define NTSC_US_VID_PROG_SIZE						\
+	((NTSC_ODD_FLD_LINES + 1) * 3 * DWORD_SIZE +			\
+	 RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE)
+
+#define NTSC_RISC_BUF_SIZE						\
+	(2 * (RISC_SYNC_INSTRUCTION_SIZE + NTSC_US_VID_PROG_SIZE))
+
+#define FRAME1_VID_PROG_SIZE						\
+	((NTSC_ODD_FLD_LINES + NTSC_FIELD_HEIGHT) * 3 * DWORD_SIZE +	\
+	 2 * RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + \
+	 JUMP_INSTRUCTION_SIZE)
+
+#endif
diff --git a/drivers/media/pci/cx25821/cx25821-video.c b/drivers/media/pci/cx25821/cx25821-video.c
new file mode 100644
index 0000000..b38d437
--- /dev/null
+++ b/drivers/media/pci/cx25821/cx25821-video.c
@@ -0,0 +1,1990 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ *  Based on Steven Toth <stoth@linuxtv.org> cx23885 driver
+ *  Parts adapted/taken from Eduardo Moscoso Rubino
+ *  Copyright (C) 2009 Eduardo Moscoso Rubino <moscoso@TopoLogica.com>
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include "cx25821-video.h"
+
+MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards");
+MODULE_AUTHOR("Hiep Huynh <hiep.huynh@conexant.com>");
+MODULE_LICENSE("GPL");
+
+static unsigned int video_nr[] = {[0 ... (CX25821_MAXBOARDS - 1)] = UNSET };
+static unsigned int radio_nr[] = {[0 ... (CX25821_MAXBOARDS - 1)] = UNSET };
+
+module_param_array(video_nr, int, NULL, 0444);
+module_param_array(radio_nr, int, NULL, 0444);
+
+MODULE_PARM_DESC(video_nr, "video device numbers");
+MODULE_PARM_DESC(radio_nr, "radio device numbers");
+
+static unsigned int video_debug = VIDEO_DEBUG;
+module_param(video_debug, int, 0644);
+MODULE_PARM_DESC(video_debug, "enable debug messages [video]");
+
+static unsigned int irq_debug;
+module_param(irq_debug, int, 0644);
+MODULE_PARM_DESC(irq_debug, "enable debug messages [IRQ handler]");
+
+unsigned int vid_limit = 16;
+module_param(vid_limit, int, 0644);
+MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes");
+
+static void cx25821_init_controls(struct cx25821_dev *dev, int chan_num);
+
+static const struct v4l2_file_operations video_fops;
+static const struct v4l2_ioctl_ops video_ioctl_ops;
+
+#define FORMAT_FLAGS_PACKED       0x01
+
+struct cx25821_fmt formats[] = {
+	{
+		.name = "8 bpp, gray",
+		.fourcc = V4L2_PIX_FMT_GREY,
+		.depth = 8,
+		.flags = FORMAT_FLAGS_PACKED,
+	 }, {
+		.name = "4:1:1, packed, Y41P",
+		.fourcc = V4L2_PIX_FMT_Y41P,
+		.depth = 12,
+		.flags = FORMAT_FLAGS_PACKED,
+	}, {
+		.name = "4:2:2, packed, YUYV",
+		.fourcc = V4L2_PIX_FMT_YUYV,
+		.depth = 16,
+		.flags = FORMAT_FLAGS_PACKED,
+	}, {
+		.name = "4:2:2, packed, UYVY",
+		.fourcc = V4L2_PIX_FMT_UYVY,
+		.depth = 16,
+		.flags = FORMAT_FLAGS_PACKED,
+	}, {
+		.name = "4:2:0, YUV",
+		.fourcc = V4L2_PIX_FMT_YUV420,
+		.depth = 12,
+		.flags = FORMAT_FLAGS_PACKED,
+	},
+};
+
+int cx25821_get_format_size(void)
+{
+	return ARRAY_SIZE(formats);
+}
+
+struct cx25821_fmt *cx25821_format_by_fourcc(unsigned int fourcc)
+{
+	unsigned int i;
+
+	if (fourcc == V4L2_PIX_FMT_Y41P || fourcc == V4L2_PIX_FMT_YUV411P)
+		return formats + 1;
+
+	for (i = 0; i < ARRAY_SIZE(formats); i++)
+		if (formats[i].fourcc == fourcc)
+			return formats + i;
+
+	pr_err("%s(0x%08x) NOT FOUND\n", __func__, fourcc);
+	return NULL;
+}
+
+void cx25821_video_wakeup(struct cx25821_dev *dev, struct cx25821_dmaqueue *q,
+			  u32 count)
+{
+	struct cx25821_buffer *buf;
+	int bc;
+
+	for (bc = 0;; bc++) {
+		if (list_empty(&q->active)) {
+			dprintk(1, "bc=%d (=0: active empty)\n", bc);
+			break;
+		}
+
+		buf = list_entry(q->active.next, struct cx25821_buffer,
+				vb.queue);
+
+		/* count comes from the hw and it is 16bit wide --
+		 * this trick handles wrap-arounds correctly for
+		 * up to 32767 buffers in flight... */
+		if ((s16) (count - buf->count) < 0)
+			break;
+
+		do_gettimeofday(&buf->vb.ts);
+		buf->vb.state = VIDEOBUF_DONE;
+		list_del(&buf->vb.queue);
+		wake_up(&buf->vb.done);
+	}
+
+	if (list_empty(&q->active))
+		del_timer(&q->timeout);
+	else
+		mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT);
+	if (bc != 1)
+		pr_err("%s: %d buffers handled (should be 1)\n", __func__, bc);
+}
+
+#ifdef TUNER_FLAG
+int cx25821_set_tvnorm(struct cx25821_dev *dev, v4l2_std_id norm)
+{
+	dprintk(1, "%s(norm = 0x%08x) name: [%s]\n",
+		__func__, (unsigned int)norm, v4l2_norm_to_name(norm));
+
+	dev->tvnorm = norm;
+
+	/* Tell the internal A/V decoder */
+	cx25821_call_all(dev, core, s_std, norm);
+
+	return 0;
+}
+#endif
+
+struct video_device *cx25821_vdev_init(struct cx25821_dev *dev,
+				       struct pci_dev *pci,
+				       struct video_device *template,
+				       char *type)
+{
+	struct video_device *vfd;
+	dprintk(1, "%s()\n", __func__);
+
+	vfd = video_device_alloc();
+	if (NULL == vfd)
+		return NULL;
+	*vfd = *template;
+	vfd->v4l2_dev = &dev->v4l2_dev;
+	vfd->release = video_device_release;
+	snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name, type,
+		 cx25821_boards[dev->board].name);
+	video_set_drvdata(vfd, dev);
+	return vfd;
+}
+
+/*
+static int cx25821_ctrl_query(struct v4l2_queryctrl *qctrl)
+{
+	int i;
+
+	if (qctrl->id < V4L2_CID_BASE || qctrl->id >= V4L2_CID_LASTP1)
+		return -EINVAL;
+	for (i = 0; i < CX25821_CTLS; i++)
+		if (cx25821_ctls[i].v.id == qctrl->id)
+			break;
+	if (i == CX25821_CTLS) {
+		*qctrl = no_ctl;
+		return 0;
+	}
+	*qctrl = cx25821_ctls[i].v;
+	return 0;
+}
+*/
+
+/* resource management */
+int cx25821_res_get(struct cx25821_dev *dev, struct cx25821_fh *fh,
+		    unsigned int bit)
+{
+	dprintk(1, "%s()\n", __func__);
+	if (fh->resources & bit)
+		/* have it already allocated */
+		return 1;
+
+	/* is it free? */
+	mutex_lock(&dev->lock);
+	if (dev->channels[fh->channel_id].resources & bit) {
+		/* no, someone else uses it */
+		mutex_unlock(&dev->lock);
+		return 0;
+	}
+	/* it's free, grab it */
+	fh->resources |= bit;
+	dev->channels[fh->channel_id].resources |= bit;
+	dprintk(1, "res: get %d\n", bit);
+	mutex_unlock(&dev->lock);
+	return 1;
+}
+
+int cx25821_res_check(struct cx25821_fh *fh, unsigned int bit)
+{
+	return fh->resources & bit;
+}
+
+int cx25821_res_locked(struct cx25821_fh *fh, unsigned int bit)
+{
+	return fh->dev->channels[fh->channel_id].resources & bit;
+}
+
+void cx25821_res_free(struct cx25821_dev *dev, struct cx25821_fh *fh,
+		      unsigned int bits)
+{
+	BUG_ON((fh->resources & bits) != bits);
+	dprintk(1, "%s()\n", __func__);
+
+	mutex_lock(&dev->lock);
+	fh->resources &= ~bits;
+	dev->channels[fh->channel_id].resources &= ~bits;
+	dprintk(1, "res: put %d\n", bits);
+	mutex_unlock(&dev->lock);
+}
+
+int cx25821_video_mux(struct cx25821_dev *dev, unsigned int input)
+{
+	struct v4l2_routing route;
+	memset(&route, 0, sizeof(route));
+
+	dprintk(1, "%s(): video_mux: %d [vmux=%d, gpio=0x%x,0x%x,0x%x,0x%x]\n",
+		__func__, input, INPUT(input)->vmux, INPUT(input)->gpio0,
+		INPUT(input)->gpio1, INPUT(input)->gpio2, INPUT(input)->gpio3);
+	dev->input = input;
+
+	route.input = INPUT(input)->vmux;
+
+	/* Tell the internal A/V decoder */
+	cx25821_call_all(dev, video, s_routing, INPUT(input)->vmux, 0, 0);
+
+	return 0;
+}
+
+int cx25821_start_video_dma(struct cx25821_dev *dev,
+			    struct cx25821_dmaqueue *q,
+			    struct cx25821_buffer *buf,
+			    struct sram_channel *channel)
+{
+	int tmp = 0;
+
+	/* setup fifo + format */
+	cx25821_sram_channel_setup(dev, channel, buf->bpl, buf->risc.dma);
+
+	/* reset counter */
+	cx_write(channel->gpcnt_ctl, 3);
+	q->count = 1;
+
+	/* enable irq */
+	cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | (1 << channel->i));
+	cx_set(channel->int_msk, 0x11);
+
+	/* start dma */
+	cx_write(channel->dma_ctl, 0x11);	/* FIFO and RISC enable */
+
+	/* make sure upstream setting if any is reversed */
+	tmp = cx_read(VID_CH_MODE_SEL);
+	cx_write(VID_CH_MODE_SEL, tmp & 0xFFFFFE00);
+
+	return 0;
+}
+
+int cx25821_restart_video_queue(struct cx25821_dev *dev,
+				struct cx25821_dmaqueue *q,
+				struct sram_channel *channel)
+{
+	struct cx25821_buffer *buf, *prev;
+	struct list_head *item;
+
+	if (!list_empty(&q->active)) {
+		buf = list_entry(q->active.next, struct cx25821_buffer,
+				vb.queue);
+
+		cx25821_start_video_dma(dev, q, buf, channel);
+
+		list_for_each(item, &q->active) {
+			buf = list_entry(item, struct cx25821_buffer, vb.queue);
+			buf->count = q->count++;
+		}
+
+		mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT);
+		return 0;
+	}
+
+	prev = NULL;
+	for (;;) {
+		if (list_empty(&q->queued))
+			return 0;
+
+		buf = list_entry(q->queued.next, struct cx25821_buffer,
+				vb.queue);
+
+		if (NULL == prev) {
+			list_move_tail(&buf->vb.queue, &q->active);
+			cx25821_start_video_dma(dev, q, buf, channel);
+			buf->vb.state = VIDEOBUF_ACTIVE;
+			buf->count = q->count++;
+			mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT);
+		} else if (prev->vb.width == buf->vb.width &&
+			   prev->vb.height == buf->vb.height &&
+			   prev->fmt == buf->fmt) {
+			list_move_tail(&buf->vb.queue, &q->active);
+			buf->vb.state = VIDEOBUF_ACTIVE;
+			buf->count = q->count++;
+			prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+			prev->risc.jmp[2] = cpu_to_le32(0); /* Bits 63 - 32 */
+		} else {
+			return 0;
+		}
+		prev = buf;
+	}
+}
+
+void cx25821_vid_timeout(unsigned long data)
+{
+	struct cx25821_data *timeout_data = (struct cx25821_data *)data;
+	struct cx25821_dev *dev = timeout_data->dev;
+	struct sram_channel *channel = timeout_data->channel;
+	struct cx25821_dmaqueue *q = &dev->channels[channel->i].vidq;
+	struct cx25821_buffer *buf;
+	unsigned long flags;
+
+	/* cx25821_sram_channel_dump(dev, channel); */
+	cx_clear(channel->dma_ctl, 0x11);
+
+	spin_lock_irqsave(&dev->slock, flags);
+	while (!list_empty(&q->active)) {
+		buf = list_entry(q->active.next, struct cx25821_buffer,
+				vb.queue);
+		list_del(&buf->vb.queue);
+
+		buf->vb.state = VIDEOBUF_ERROR;
+		wake_up(&buf->vb.done);
+	}
+
+	cx25821_restart_video_queue(dev, q, channel);
+	spin_unlock_irqrestore(&dev->slock, flags);
+}
+
+int cx25821_video_irq(struct cx25821_dev *dev, int chan_num, u32 status)
+{
+	u32 count = 0;
+	int handled = 0;
+	u32 mask;
+	struct sram_channel *channel = dev->channels[chan_num].sram_channels;
+
+	mask = cx_read(channel->int_msk);
+	if (0 == (status & mask))
+		return handled;
+
+	cx_write(channel->int_stat, status);
+
+	/* risc op code error */
+	if (status & (1 << 16)) {
+		pr_warn("%s, %s: video risc op code error\n",
+			dev->name, channel->name);
+		cx_clear(channel->dma_ctl, 0x11);
+		cx25821_sram_channel_dump(dev, channel);
+	}
+
+	/* risc1 y */
+	if (status & FLD_VID_DST_RISC1) {
+		spin_lock(&dev->slock);
+		count = cx_read(channel->gpcnt);
+		cx25821_video_wakeup(dev, &dev->channels[channel->i].vidq,
+				count);
+		spin_unlock(&dev->slock);
+		handled++;
+	}
+
+	/* risc2 y */
+	if (status & 0x10) {
+		dprintk(2, "stopper video\n");
+		spin_lock(&dev->slock);
+		cx25821_restart_video_queue(dev,
+				&dev->channels[channel->i].vidq, channel);
+		spin_unlock(&dev->slock);
+		handled++;
+	}
+	return handled;
+}
+
+void cx25821_videoioctl_unregister(struct cx25821_dev *dev)
+{
+	if (dev->ioctl_dev) {
+		if (video_is_registered(dev->ioctl_dev))
+			video_unregister_device(dev->ioctl_dev);
+		else
+			video_device_release(dev->ioctl_dev);
+
+		dev->ioctl_dev = NULL;
+	}
+}
+
+void cx25821_video_unregister(struct cx25821_dev *dev, int chan_num)
+{
+	cx_clear(PCI_INT_MSK, 1);
+
+	if (dev->channels[chan_num].video_dev) {
+		if (video_is_registered(dev->channels[chan_num].video_dev))
+			video_unregister_device(
+					dev->channels[chan_num].video_dev);
+		else
+			video_device_release(
+					dev->channels[chan_num].video_dev);
+
+		dev->channels[chan_num].video_dev = NULL;
+
+		btcx_riscmem_free(dev->pci,
+				&dev->channels[chan_num].vidq.stopper);
+
+		pr_warn("device %d released!\n", chan_num);
+	}
+
+}
+
+int cx25821_video_register(struct cx25821_dev *dev)
+{
+	int err;
+	int i;
+
+	struct video_device cx25821_video_device = {
+		.name = "cx25821-video",
+		.fops = &video_fops,
+		.minor = -1,
+		.ioctl_ops = &video_ioctl_ops,
+		.tvnorms = CX25821_NORMS,
+		.current_norm = V4L2_STD_NTSC_M,
+	};
+
+	spin_lock_init(&dev->slock);
+
+	for (i = 0; i < MAX_VID_CHANNEL_NUM - 1; ++i) {
+		cx25821_init_controls(dev, i);
+
+		cx25821_risc_stopper(dev->pci, &dev->channels[i].vidq.stopper,
+			dev->channels[i].sram_channels->dma_ctl, 0x11, 0);
+
+		dev->channels[i].sram_channels = &cx25821_sram_channels[i];
+		dev->channels[i].video_dev = NULL;
+		dev->channels[i].resources = 0;
+
+		cx_write(dev->channels[i].sram_channels->int_stat, 0xffffffff);
+
+		INIT_LIST_HEAD(&dev->channels[i].vidq.active);
+		INIT_LIST_HEAD(&dev->channels[i].vidq.queued);
+
+		dev->channels[i].timeout_data.dev = dev;
+		dev->channels[i].timeout_data.channel =
+			&cx25821_sram_channels[i];
+		dev->channels[i].vidq.timeout.function = cx25821_vid_timeout;
+		dev->channels[i].vidq.timeout.data =
+			(unsigned long)&dev->channels[i].timeout_data;
+		init_timer(&dev->channels[i].vidq.timeout);
+
+		/* register v4l devices */
+		dev->channels[i].video_dev = cx25821_vdev_init(dev, dev->pci,
+				&cx25821_video_device, "video");
+
+		err = video_register_device(dev->channels[i].video_dev,
+				VFL_TYPE_GRABBER, video_nr[dev->nr]);
+
+		if (err < 0)
+			goto fail_unreg;
+
+	}
+
+	/* set PCI interrupt */
+	cx_set(PCI_INT_MSK, 0xff);
+
+	/* initial device configuration */
+	mutex_lock(&dev->lock);
+#ifdef TUNER_FLAG
+	dev->tvnorm = cx25821_video_device.current_norm;
+	cx25821_set_tvnorm(dev, dev->tvnorm);
+#endif
+	mutex_unlock(&dev->lock);
+
+	return 0;
+
+fail_unreg:
+	cx25821_video_unregister(dev, i);
+	return err;
+}
+
+int cx25821_buffer_setup(struct videobuf_queue *q, unsigned int *count,
+		 unsigned int *size)
+{
+	struct cx25821_fh *fh = q->priv_data;
+
+	*size = fh->fmt->depth * fh->width * fh->height >> 3;
+
+	if (0 == *count)
+		*count = 32;
+
+	if (*size * *count > vid_limit * 1024 * 1024)
+		*count = (vid_limit * 1024 * 1024) / *size;
+
+	return 0;
+}
+
+int cx25821_buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
+		   enum v4l2_field field)
+{
+	struct cx25821_fh *fh = q->priv_data;
+	struct cx25821_dev *dev = fh->dev;
+	struct cx25821_buffer *buf =
+		container_of(vb, struct cx25821_buffer, vb);
+	int rc, init_buffer = 0;
+	u32 line0_offset;
+	struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb);
+	int bpl_local = LINE_SIZE_D1;
+	int channel_opened = fh->channel_id;
+
+	BUG_ON(NULL == fh->fmt);
+	if (fh->width < 48 || fh->width > 720 ||
+	    fh->height < 32 || fh->height > 576)
+		return -EINVAL;
+
+	buf->vb.size = (fh->width * fh->height * fh->fmt->depth) >> 3;
+
+	if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
+		return -EINVAL;
+
+	if (buf->fmt != fh->fmt ||
+	    buf->vb.width != fh->width ||
+	    buf->vb.height != fh->height || buf->vb.field != field) {
+		buf->fmt = fh->fmt;
+		buf->vb.width = fh->width;
+		buf->vb.height = fh->height;
+		buf->vb.field = field;
+		init_buffer = 1;
+	}
+
+	if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
+		init_buffer = 1;
+		rc = videobuf_iolock(q, &buf->vb, NULL);
+		if (0 != rc) {
+			printk(KERN_DEBUG pr_fmt("videobuf_iolock failed!\n"));
+			goto fail;
+		}
+	}
+
+	dprintk(1, "init_buffer=%d\n", init_buffer);
+
+	if (init_buffer) {
+
+		channel_opened = dev->channel_opened;
+		if (channel_opened < 0 || channel_opened > 7)
+			channel_opened = 7;
+
+		if (dev->channels[channel_opened].pixel_formats ==
+				PIXEL_FRMT_411)
+			buf->bpl = (buf->fmt->depth * buf->vb.width) >> 3;
+		else
+			buf->bpl = (buf->fmt->depth >> 3) * (buf->vb.width);
+
+		if (dev->channels[channel_opened].pixel_formats ==
+				PIXEL_FRMT_411) {
+			bpl_local = buf->bpl;
+		} else {
+			bpl_local = buf->bpl;   /* Default */
+
+			if (channel_opened >= 0 && channel_opened <= 7) {
+				if (dev->channels[channel_opened]
+						.use_cif_resolution) {
+					if (dev->tvnorm & V4L2_STD_PAL_BG ||
+					    dev->tvnorm & V4L2_STD_PAL_DK)
+						bpl_local = 352 << 1;
+					else
+						bpl_local = dev->channels[
+							channel_opened].
+							cif_width << 1;
+				}
+			}
+		}
+
+		switch (buf->vb.field) {
+		case V4L2_FIELD_TOP:
+			cx25821_risc_buffer(dev->pci, &buf->risc,
+					    dma->sglist, 0, UNSET,
+					    buf->bpl, 0, buf->vb.height);
+			break;
+		case V4L2_FIELD_BOTTOM:
+			cx25821_risc_buffer(dev->pci, &buf->risc,
+					    dma->sglist, UNSET, 0,
+					    buf->bpl, 0, buf->vb.height);
+			break;
+		case V4L2_FIELD_INTERLACED:
+			/* All other formats are top field first */
+			line0_offset = 0;
+			dprintk(1, "top field first\n");
+
+			cx25821_risc_buffer(dev->pci, &buf->risc,
+					    dma->sglist, line0_offset,
+					    bpl_local, bpl_local, bpl_local,
+					    buf->vb.height >> 1);
+			break;
+		case V4L2_FIELD_SEQ_TB:
+			cx25821_risc_buffer(dev->pci, &buf->risc,
+					    dma->sglist,
+					    0, buf->bpl * (buf->vb.height >> 1),
+					    buf->bpl, 0, buf->vb.height >> 1);
+			break;
+		case V4L2_FIELD_SEQ_BT:
+			cx25821_risc_buffer(dev->pci, &buf->risc,
+					    dma->sglist,
+					    buf->bpl * (buf->vb.height >> 1), 0,
+					    buf->bpl, 0, buf->vb.height >> 1);
+			break;
+		default:
+			BUG();
+		}
+	}
+
+	dprintk(2, "[%p/%d] buffer_prep - %dx%d %dbpp \"%s\" - dma=0x%08lx\n",
+		buf, buf->vb.i, fh->width, fh->height, fh->fmt->depth,
+		fh->fmt->name, (unsigned long)buf->risc.dma);
+
+	buf->vb.state = VIDEOBUF_PREPARED;
+
+	return 0;
+
+fail:
+	cx25821_free_buffer(q, buf);
+	return rc;
+}
+
+void cx25821_buffer_release(struct videobuf_queue *q,
+			    struct videobuf_buffer *vb)
+{
+	struct cx25821_buffer *buf =
+		container_of(vb, struct cx25821_buffer, vb);
+
+	cx25821_free_buffer(q, buf);
+}
+
+struct videobuf_queue *get_queue(struct cx25821_fh *fh)
+{
+	switch (fh->type) {
+	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+		return &fh->vidq;
+	default:
+		BUG();
+		return NULL;
+	}
+}
+
+int cx25821_get_resource(struct cx25821_fh *fh, int resource)
+{
+	switch (fh->type) {
+	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+		return resource;
+	default:
+		BUG();
+		return 0;
+	}
+}
+
+int cx25821_video_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	struct cx25821_fh *fh = file->private_data;
+
+	return videobuf_mmap_mapper(get_queue(fh), vma);
+}
+
+
+static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+{
+	struct cx25821_buffer *buf =
+		container_of(vb, struct cx25821_buffer, vb);
+	struct cx25821_buffer *prev;
+	struct cx25821_fh *fh = vq->priv_data;
+	struct cx25821_dev *dev = fh->dev;
+	struct cx25821_dmaqueue *q = &dev->channels[fh->channel_id].vidq;
+
+	/* add jump to stopper */
+	buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+	buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma);
+	buf->risc.jmp[2] = cpu_to_le32(0);      /* bits 63-32 */
+
+	dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]);
+
+	if (!list_empty(&q->queued)) {
+		list_add_tail(&buf->vb.queue, &q->queued);
+		buf->vb.state = VIDEOBUF_QUEUED;
+		dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf,
+				buf->vb.i);
+
+	} else if (list_empty(&q->active)) {
+		list_add_tail(&buf->vb.queue, &q->active);
+		cx25821_start_video_dma(dev, q, buf,
+				dev->channels[fh->channel_id].sram_channels);
+		buf->vb.state = VIDEOBUF_ACTIVE;
+		buf->count = q->count++;
+		mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT);
+		dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n",
+				buf, buf->vb.i, buf->count, q->count);
+	} else {
+		prev = list_entry(q->active.prev, struct cx25821_buffer,
+				vb.queue);
+		if (prev->vb.width == buf->vb.width
+		   && prev->vb.height == buf->vb.height
+		   && prev->fmt == buf->fmt) {
+			list_add_tail(&buf->vb.queue, &q->active);
+			buf->vb.state = VIDEOBUF_ACTIVE;
+			buf->count = q->count++;
+			prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+
+			/* 64 bit bits 63-32 */
+			prev->risc.jmp[2] = cpu_to_le32(0);
+			dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n",
+					buf, buf->vb.i, buf->count);
+
+		} else {
+			list_add_tail(&buf->vb.queue, &q->queued);
+			buf->vb.state = VIDEOBUF_QUEUED;
+			dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf,
+					buf->vb.i);
+		}
+	}
+
+	if (list_empty(&q->active))
+		dprintk(2, "active queue empty!\n");
+}
+
+static struct videobuf_queue_ops cx25821_video_qops = {
+	.buf_setup = cx25821_buffer_setup,
+	.buf_prepare = cx25821_buffer_prepare,
+	.buf_queue = buffer_queue,
+	.buf_release = cx25821_buffer_release,
+};
+
+static int video_open(struct file *file)
+{
+	struct video_device *vdev = video_devdata(file);
+	struct cx25821_dev *h, *dev = video_drvdata(file);
+	struct cx25821_fh *fh;
+	struct list_head *list;
+	int minor = video_devdata(file)->minor;
+	enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	u32 pix_format;
+	int ch_id = 0;
+	int i;
+
+	dprintk(1, "open dev=%s type=%s\n", video_device_node_name(vdev),
+			v4l2_type_names[type]);
+
+	/* allocate + initialize per filehandle data */
+	fh = kzalloc(sizeof(*fh), GFP_KERNEL);
+	if (NULL == fh)
+		return -ENOMEM;
+
+	mutex_lock(&cx25821_devlist_mutex);
+
+	list_for_each(list, &cx25821_devlist)
+	{
+		h = list_entry(list, struct cx25821_dev, devlist);
+
+		for (i = 0; i < MAX_VID_CHANNEL_NUM; i++) {
+			if (h->channels[i].video_dev &&
+			    h->channels[i].video_dev->minor == minor) {
+				dev = h;
+				ch_id = i;
+				type  = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+			}
+		}
+	}
+
+	if (NULL == dev) {
+		mutex_unlock(&cx25821_devlist_mutex);
+		kfree(fh);
+		return -ENODEV;
+	}
+
+	file->private_data = fh;
+	fh->dev = dev;
+	fh->type = type;
+	fh->width = 720;
+	fh->channel_id = ch_id;
+
+	if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK)
+		fh->height = 576;
+	else
+		fh->height = 480;
+
+	dev->channel_opened = fh->channel_id;
+	if (dev->channels[ch_id].pixel_formats == PIXEL_FRMT_411)
+		pix_format = V4L2_PIX_FMT_Y41P;
+	else
+		pix_format = V4L2_PIX_FMT_YUYV;
+	fh->fmt = cx25821_format_by_fourcc(pix_format);
+
+	v4l2_prio_open(&dev->channels[ch_id].prio, &fh->prio);
+
+	videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, &dev->pci->dev,
+			&dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE,
+			V4L2_FIELD_INTERLACED, sizeof(struct cx25821_buffer),
+			fh, NULL);
+
+	dprintk(1, "post videobuf_queue_init()\n");
+	mutex_unlock(&cx25821_devlist_mutex);
+
+	return 0;
+}
+
+static ssize_t video_read(struct file *file, char __user * data, size_t count,
+			 loff_t *ppos)
+{
+	struct cx25821_fh *fh = file->private_data;
+
+	switch (fh->type) {
+	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+		if (cx25821_res_locked(fh, RESOURCE_VIDEO0))
+			return -EBUSY;
+
+		return videobuf_read_one(&fh->vidq, data, count, ppos,
+					file->f_flags & O_NONBLOCK);
+
+	default:
+		BUG();
+		return 0;
+	}
+}
+
+static unsigned int video_poll(struct file *file,
+			      struct poll_table_struct *wait)
+{
+	struct cx25821_fh *fh = file->private_data;
+	struct cx25821_buffer *buf;
+
+	if (cx25821_res_check(fh, RESOURCE_VIDEO0)) {
+		/* streaming capture */
+		if (list_empty(&fh->vidq.stream))
+			return POLLERR;
+		buf = list_entry(fh->vidq.stream.next,
+				struct cx25821_buffer, vb.stream);
+	} else {
+		/* read() capture */
+		buf = (struct cx25821_buffer *)fh->vidq.read_buf;
+		if (NULL == buf)
+			return POLLERR;
+	}
+
+	poll_wait(file, &buf->vb.done, wait);
+	if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) {
+		if (buf->vb.state == VIDEOBUF_DONE) {
+			struct cx25821_dev *dev = fh->dev;
+
+			if (dev && dev->channels[fh->channel_id]
+					.use_cif_resolution) {
+				u8 cam_id = *((char *)buf->vb.baddr + 3);
+				memcpy((char *)buf->vb.baddr,
+				      (char *)buf->vb.baddr + (fh->width * 2),
+				      (fh->width * 2));
+				*((char *)buf->vb.baddr + 3) = cam_id;
+			}
+		}
+
+		return POLLIN | POLLRDNORM;
+	}
+
+	return 0;
+}
+
+static int video_release(struct file *file)
+{
+	struct cx25821_fh *fh = file->private_data;
+	struct cx25821_dev *dev = fh->dev;
+
+	/* stop the risc engine and fifo */
+	cx_write(channel0->dma_ctl, 0); /* FIFO and RISC disable */
+
+	/* stop video capture */
+	if (cx25821_res_check(fh, RESOURCE_VIDEO0)) {
+		videobuf_queue_cancel(&fh->vidq);
+		cx25821_res_free(dev, fh, RESOURCE_VIDEO0);
+	}
+
+	if (fh->vidq.read_buf) {
+		cx25821_buffer_release(&fh->vidq, fh->vidq.read_buf);
+		kfree(fh->vidq.read_buf);
+	}
+
+	videobuf_mmap_free(&fh->vidq);
+
+	v4l2_prio_close(&dev->channels[fh->channel_id].prio, fh->prio);
+	file->private_data = NULL;
+	kfree(fh);
+
+	return 0;
+}
+
+static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+	struct cx25821_fh *fh = priv;
+	struct cx25821_dev *dev = fh->dev;
+
+	if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE))
+		return -EINVAL;
+
+	if (unlikely(i != fh->type))
+		return -EINVAL;
+
+	if (unlikely(!cx25821_res_get(dev, fh, cx25821_get_resource(fh,
+						RESOURCE_VIDEO0))))
+		return -EBUSY;
+
+	return videobuf_streamon(get_queue(fh));
+}
+
+static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+	struct cx25821_fh *fh = priv;
+	struct cx25821_dev *dev = fh->dev;
+	int err, res;
+
+	if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+	if (i != fh->type)
+		return -EINVAL;
+
+	res = cx25821_get_resource(fh, RESOURCE_VIDEO0);
+	err = videobuf_streamoff(get_queue(fh));
+	if (err < 0)
+		return err;
+	cx25821_res_free(dev, fh, res);
+	return 0;
+}
+
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
+				struct v4l2_format *f)
+{
+	struct cx25821_fh *fh = priv;
+	struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+	struct v4l2_mbus_framefmt mbus_fmt;
+	int err;
+	int pix_format = PIXEL_FRMT_422;
+
+	if (fh) {
+		err = v4l2_prio_check(&dev->channels[fh->channel_id].prio,
+				      fh->prio);
+		if (0 != err)
+			return err;
+	}
+
+	dprintk(2, "%s()\n", __func__);
+	err = cx25821_vidioc_try_fmt_vid_cap(file, priv, f);
+
+	if (0 != err)
+		return err;
+
+	fh->fmt = cx25821_format_by_fourcc(f->fmt.pix.pixelformat);
+	fh->vidq.field = f->fmt.pix.field;
+
+	/* check if width and height is valid based on set standard */
+	if (cx25821_is_valid_width(f->fmt.pix.width, dev->tvnorm))
+		fh->width = f->fmt.pix.width;
+
+	if (cx25821_is_valid_height(f->fmt.pix.height, dev->tvnorm))
+		fh->height = f->fmt.pix.height;
+
+	if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P)
+		pix_format = PIXEL_FRMT_411;
+	else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV)
+		pix_format = PIXEL_FRMT_422;
+	else
+		return -EINVAL;
+
+	cx25821_set_pixel_format(dev, SRAM_CH00, pix_format);
+
+	/* check if cif resolution */
+	if (fh->width == 320 || fh->width == 352)
+		dev->channels[fh->channel_id].use_cif_resolution = 1;
+	else
+		dev->channels[fh->channel_id].use_cif_resolution = 0;
+
+	dev->channels[fh->channel_id].cif_width = fh->width;
+	medusa_set_resolution(dev, fh->width, SRAM_CH00);
+
+	dprintk(2, "%s(): width=%d height=%d field=%d\n", __func__, fh->width,
+		fh->height, fh->vidq.field);
+	v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, V4L2_MBUS_FMT_FIXED);
+	cx25821_call_all(dev, video, s_mbus_fmt, &mbus_fmt);
+
+	return 0;
+}
+
+static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+	int ret_val = 0;
+	struct cx25821_fh *fh = priv;
+	struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+
+	ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK);
+
+	p->sequence = dev->channels[fh->channel_id].vidq.count;
+
+	return ret_val;
+}
+
+static int vidioc_log_status(struct file *file, void *priv)
+{
+	struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+	struct cx25821_fh *fh = priv;
+	char name[32 + 2];
+
+	struct sram_channel *sram_ch = dev->channels[fh->channel_id]
+								.sram_channels;
+	u32 tmp = 0;
+
+	snprintf(name, sizeof(name), "%s/2", dev->name);
+	pr_info("%s/2: ============  START LOG STATUS  ============\n",
+		dev->name);
+	cx25821_call_all(dev, core, log_status);
+	tmp = cx_read(sram_ch->dma_ctl);
+	pr_info("Video input 0 is %s\n",
+		(tmp & 0x11) ? "streaming" : "stopped");
+	pr_info("%s/2: =============  END LOG STATUS  =============\n",
+		dev->name);
+	return 0;
+}
+
+static int vidioc_s_ctrl(struct file *file, void *priv,
+			struct v4l2_control *ctl)
+{
+	struct cx25821_fh *fh = priv;
+	struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+	int err;
+
+	if (fh) {
+		err = v4l2_prio_check(&dev->channels[fh->channel_id].prio,
+				      fh->prio);
+		if (0 != err)
+			return err;
+	}
+
+	return cx25821_set_control(dev, ctl, fh->channel_id);
+}
+
+/* VIDEO IOCTLS */
+int cx25821_vidioc_g_fmt_vid_cap(struct file *file, void *priv,
+				 struct v4l2_format *f)
+{
+	struct cx25821_fh *fh = priv;
+
+	f->fmt.pix.width = fh->width;
+	f->fmt.pix.height = fh->height;
+	f->fmt.pix.field = fh->vidq.field;
+	f->fmt.pix.pixelformat = fh->fmt->fourcc;
+	f->fmt.pix.bytesperline = (f->fmt.pix.width * fh->fmt->depth) >> 3;
+	f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
+
+	return 0;
+}
+
+int cx25821_vidioc_try_fmt_vid_cap(struct file *file, void *priv,
+				   struct v4l2_format *f)
+{
+	struct cx25821_fmt *fmt;
+	enum v4l2_field field;
+	unsigned int maxw, maxh;
+
+	fmt = cx25821_format_by_fourcc(f->fmt.pix.pixelformat);
+	if (NULL == fmt)
+		return -EINVAL;
+
+	field = f->fmt.pix.field;
+	maxw = 720;
+	maxh = 576;
+
+	if (V4L2_FIELD_ANY == field) {
+		if (f->fmt.pix.height > maxh / 2)
+			field = V4L2_FIELD_INTERLACED;
+		else
+			field = V4L2_FIELD_TOP;
+	}
+
+	switch (field) {
+	case V4L2_FIELD_TOP:
+	case V4L2_FIELD_BOTTOM:
+		maxh = maxh / 2;
+		break;
+	case V4L2_FIELD_INTERLACED:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	f->fmt.pix.field = field;
+	if (f->fmt.pix.height < 32)
+		f->fmt.pix.height = 32;
+	if (f->fmt.pix.height > maxh)
+		f->fmt.pix.height = maxh;
+	if (f->fmt.pix.width < 48)
+		f->fmt.pix.width = 48;
+	if (f->fmt.pix.width > maxw)
+		f->fmt.pix.width = maxw;
+	f->fmt.pix.width &= ~0x03;
+	f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3;
+	f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
+
+	return 0;
+}
+
+int cx25821_vidioc_querycap(struct file *file, void *priv,
+			    struct v4l2_capability *cap)
+{
+	struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+
+	strcpy(cap->driver, "cx25821");
+	strlcpy(cap->card, cx25821_boards[dev->board].name, sizeof(cap->card));
+	sprintf(cap->bus_info, "PCIe:%s", pci_name(dev->pci));
+	cap->version = CX25821_VERSION_CODE;
+	cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
+		V4L2_CAP_STREAMING;
+	if (UNSET != dev->tuner_type)
+		cap->capabilities |= V4L2_CAP_TUNER;
+	return 0;
+}
+
+int cx25821_vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
+			    struct v4l2_fmtdesc *f)
+{
+	if (unlikely(f->index >= ARRAY_SIZE(formats)))
+		return -EINVAL;
+
+	strlcpy(f->description, formats[f->index].name, sizeof(f->description));
+	f->pixelformat = formats[f->index].fourcc;
+
+	return 0;
+}
+
+int cx25821_vidioc_reqbufs(struct file *file, void *priv,
+			   struct v4l2_requestbuffers *p)
+{
+	struct cx25821_fh *fh = priv;
+	return videobuf_reqbufs(get_queue(fh), p);
+}
+
+int cx25821_vidioc_querybuf(struct file *file, void *priv,
+			    struct v4l2_buffer *p)
+{
+	struct cx25821_fh *fh = priv;
+	return videobuf_querybuf(get_queue(fh), p);
+}
+
+int cx25821_vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+	struct cx25821_fh *fh = priv;
+	return videobuf_qbuf(get_queue(fh), p);
+}
+
+int cx25821_vidioc_g_priority(struct file *file, void *f, enum v4l2_priority *p)
+{
+	struct cx25821_dev *dev = ((struct cx25821_fh *)f)->dev;
+	struct cx25821_fh *fh = f;
+
+	*p = v4l2_prio_max(&dev->channels[fh->channel_id].prio);
+
+	return 0;
+}
+
+int cx25821_vidioc_s_priority(struct file *file, void *f,
+			      enum v4l2_priority prio)
+{
+	struct cx25821_fh *fh = f;
+	struct cx25821_dev *dev = ((struct cx25821_fh *)f)->dev;
+
+	return v4l2_prio_change(&dev->channels[fh->channel_id].prio, &fh->prio,
+			prio);
+}
+
+#ifdef TUNER_FLAG
+int cx25821_vidioc_s_std(struct file *file, void *priv, v4l2_std_id * tvnorms)
+{
+	struct cx25821_fh *fh = priv;
+	struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+	int err;
+
+	dprintk(1, "%s()\n", __func__);
+
+	if (fh) {
+		err = v4l2_prio_check(&dev->channels[fh->channel_id].prio,
+				      fh->prio);
+		if (0 != err)
+			return err;
+	}
+
+	if (dev->tvnorm == *tvnorms)
+		return 0;
+
+	mutex_lock(&dev->lock);
+	cx25821_set_tvnorm(dev, *tvnorms);
+	mutex_unlock(&dev->lock);
+
+	medusa_set_videostandard(dev);
+
+	return 0;
+}
+#endif
+
+int cx25821_enum_input(struct cx25821_dev *dev, struct v4l2_input *i)
+{
+	static const char * const iname[] = {
+		[CX25821_VMUX_COMPOSITE] = "Composite",
+		[CX25821_VMUX_SVIDEO] = "S-Video",
+		[CX25821_VMUX_DEBUG] = "for debug only",
+	};
+	unsigned int n;
+	dprintk(1, "%s()\n", __func__);
+
+	n = i->index;
+	if (n >= 2)
+		return -EINVAL;
+
+	if (0 == INPUT(n)->type)
+		return -EINVAL;
+
+	i->type = V4L2_INPUT_TYPE_CAMERA;
+	strcpy(i->name, iname[INPUT(n)->type]);
+
+	i->std = CX25821_NORMS;
+	return 0;
+}
+
+int cx25821_vidioc_enum_input(struct file *file, void *priv,
+			      struct v4l2_input *i)
+{
+	struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+	dprintk(1, "%s()\n", __func__);
+	return cx25821_enum_input(dev, i);
+}
+
+int cx25821_vidioc_g_input(struct file *file, void *priv, unsigned int *i)
+{
+	struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+
+	*i = dev->input;
+	dprintk(1, "%s(): returns %d\n", __func__, *i);
+	return 0;
+}
+
+int cx25821_vidioc_s_input(struct file *file, void *priv, unsigned int i)
+{
+	struct cx25821_fh *fh = priv;
+	struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+	int err;
+
+	dprintk(1, "%s(%d)\n", __func__, i);
+
+	if (fh) {
+		err = v4l2_prio_check(&dev->channels[fh->channel_id].prio,
+				      fh->prio);
+		if (0 != err)
+			return err;
+	}
+
+	if (i >= CX25821_NR_INPUT) {
+		dprintk(1, "%s(): -EINVAL\n", __func__);
+		return -EINVAL;
+	}
+
+	mutex_lock(&dev->lock);
+	cx25821_video_mux(dev, i);
+	mutex_unlock(&dev->lock);
+	return 0;
+}
+
+#ifdef TUNER_FLAG
+int cx25821_vidioc_g_frequency(struct file *file, void *priv,
+			       struct v4l2_frequency *f)
+{
+	struct cx25821_fh *fh = priv;
+	struct cx25821_dev *dev = fh->dev;
+
+	f->frequency = dev->freq;
+
+	cx25821_call_all(dev, tuner, g_frequency, f);
+
+	return 0;
+}
+
+int cx25821_set_freq(struct cx25821_dev *dev, struct v4l2_frequency *f)
+{
+	mutex_lock(&dev->lock);
+	dev->freq = f->frequency;
+
+	cx25821_call_all(dev, tuner, s_frequency, f);
+
+	/* When changing channels it is required to reset TVAUDIO */
+	msleep(10);
+
+	mutex_unlock(&dev->lock);
+
+	return 0;
+}
+
+int cx25821_vidioc_s_frequency(struct file *file, void *priv,
+			       struct v4l2_frequency *f)
+{
+	struct cx25821_fh *fh = priv;
+	struct cx25821_dev *dev;
+	int err;
+
+	if (fh) {
+		dev = fh->dev;
+		err = v4l2_prio_check(&dev->channels[fh->channel_id].prio,
+				      fh->prio);
+		if (0 != err)
+			return err;
+	} else {
+		pr_err("Invalid fh pointer!\n");
+		return -EINVAL;
+	}
+
+	return cx25821_set_freq(dev, f);
+}
+#endif
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+int cx25821_vidioc_g_register(struct file *file, void *fh,
+		      struct v4l2_dbg_register *reg)
+{
+	struct cx25821_dev *dev = ((struct cx25821_fh *)fh)->dev;
+
+	if (!v4l2_chip_match_host(&reg->match))
+		return -EINVAL;
+
+	cx25821_call_all(dev, core, g_register, reg);
+
+	return 0;
+}
+
+int cx25821_vidioc_s_register(struct file *file, void *fh,
+		      struct v4l2_dbg_register *reg)
+{
+	struct cx25821_dev *dev = ((struct cx25821_fh *)fh)->dev;
+
+	if (!v4l2_chip_match_host(&reg->match))
+		return -EINVAL;
+
+	cx25821_call_all(dev, core, s_register, reg);
+
+	return 0;
+}
+
+#endif
+
+#ifdef TUNER_FLAG
+int cx25821_vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
+{
+	struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+
+	if (unlikely(UNSET == dev->tuner_type))
+		return -EINVAL;
+	if (0 != t->index)
+		return -EINVAL;
+
+	strcpy(t->name, "Television");
+	t->type = V4L2_TUNER_ANALOG_TV;
+	t->capability = V4L2_TUNER_CAP_NORM;
+	t->rangehigh = 0xffffffffUL;
+
+	t->signal = 0xffff;	/* LOCKED */
+	return 0;
+}
+
+int cx25821_vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
+{
+	struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+	struct cx25821_fh *fh = priv;
+	int err;
+
+	if (fh) {
+		err = v4l2_prio_check(&dev->channels[fh->channel_id].prio,
+				      fh->prio);
+		if (0 != err)
+			return err;
+	}
+
+	dprintk(1, "%s()\n", __func__);
+	if (UNSET == dev->tuner_type)
+		return -EINVAL;
+	if (0 != t->index)
+		return -EINVAL;
+
+	return 0;
+}
+
+#endif
+/*****************************************************************************/
+static const struct v4l2_queryctrl no_ctl = {
+	.name = "42",
+	.flags = V4L2_CTRL_FLAG_DISABLED,
+};
+
+static struct v4l2_queryctrl cx25821_ctls[] = {
+	/* --- video --- */
+	{
+		.id = V4L2_CID_BRIGHTNESS,
+		.name = "Brightness",
+		.minimum = 0,
+		.maximum = 10000,
+		.step = 1,
+		.default_value = 6200,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+	}, {
+		.id = V4L2_CID_CONTRAST,
+		.name = "Contrast",
+		.minimum = 0,
+		.maximum = 10000,
+		.step = 1,
+		.default_value = 5000,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+	}, {
+		.id = V4L2_CID_SATURATION,
+		.name = "Saturation",
+		.minimum = 0,
+		.maximum = 10000,
+		.step = 1,
+		.default_value = 5000,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+	}, {
+		.id = V4L2_CID_HUE,
+		.name = "Hue",
+		.minimum = 0,
+		.maximum = 10000,
+		.step = 1,
+		.default_value = 5000,
+		.type = V4L2_CTRL_TYPE_INTEGER,
+	}
+};
+static const int CX25821_CTLS = ARRAY_SIZE(cx25821_ctls);
+
+static int cx25821_ctrl_query(struct v4l2_queryctrl *qctrl)
+{
+	int i;
+
+	if (qctrl->id < V4L2_CID_BASE || qctrl->id >= V4L2_CID_LASTP1)
+		return -EINVAL;
+	for (i = 0; i < CX25821_CTLS; i++)
+		if (cx25821_ctls[i].id == qctrl->id)
+			break;
+	if (i == CX25821_CTLS) {
+		*qctrl = no_ctl;
+		return 0;
+	}
+	*qctrl = cx25821_ctls[i];
+	return 0;
+}
+
+int cx25821_vidioc_queryctrl(struct file *file, void *priv,
+		     struct v4l2_queryctrl *qctrl)
+{
+	return cx25821_ctrl_query(qctrl);
+}
+
+/* ------------------------------------------------------------------ */
+/* VIDEO CTRL IOCTLS                                                  */
+
+static const struct v4l2_queryctrl *ctrl_by_id(unsigned int id)
+{
+	unsigned int i;
+
+	for (i = 0; i < CX25821_CTLS; i++)
+		if (cx25821_ctls[i].id == id)
+			return cx25821_ctls + i;
+	return NULL;
+}
+
+int cx25821_vidioc_g_ctrl(struct file *file, void *priv,
+			  struct v4l2_control *ctl)
+{
+	struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+	struct cx25821_fh *fh = priv;
+
+	const struct v4l2_queryctrl *ctrl;
+
+	ctrl = ctrl_by_id(ctl->id);
+
+	if (NULL == ctrl)
+		return -EINVAL;
+	switch (ctl->id) {
+	case V4L2_CID_BRIGHTNESS:
+		ctl->value = dev->channels[fh->channel_id].ctl_bright;
+		break;
+	case V4L2_CID_HUE:
+		ctl->value = dev->channels[fh->channel_id].ctl_hue;
+		break;
+	case V4L2_CID_CONTRAST:
+		ctl->value = dev->channels[fh->channel_id].ctl_contrast;
+		break;
+	case V4L2_CID_SATURATION:
+		ctl->value = dev->channels[fh->channel_id].ctl_saturation;
+		break;
+	}
+	return 0;
+}
+
+int cx25821_set_control(struct cx25821_dev *dev,
+			struct v4l2_control *ctl, int chan_num)
+{
+	int err;
+	const struct v4l2_queryctrl *ctrl;
+
+	err = -EINVAL;
+
+	ctrl = ctrl_by_id(ctl->id);
+
+	if (NULL == ctrl)
+		return err;
+
+	switch (ctrl->type) {
+	case V4L2_CTRL_TYPE_BOOLEAN:
+	case V4L2_CTRL_TYPE_MENU:
+	case V4L2_CTRL_TYPE_INTEGER:
+		if (ctl->value < ctrl->minimum)
+			ctl->value = ctrl->minimum;
+		if (ctl->value > ctrl->maximum)
+			ctl->value = ctrl->maximum;
+		break;
+	default:
+		/* nothing */ ;
+	}
+
+	switch (ctl->id) {
+	case V4L2_CID_BRIGHTNESS:
+		dev->channels[chan_num].ctl_bright = ctl->value;
+		medusa_set_brightness(dev, ctl->value, chan_num);
+		break;
+	case V4L2_CID_HUE:
+		dev->channels[chan_num].ctl_hue = ctl->value;
+		medusa_set_hue(dev, ctl->value, chan_num);
+		break;
+	case V4L2_CID_CONTRAST:
+		dev->channels[chan_num].ctl_contrast = ctl->value;
+		medusa_set_contrast(dev, ctl->value, chan_num);
+		break;
+	case V4L2_CID_SATURATION:
+		dev->channels[chan_num].ctl_saturation = ctl->value;
+		medusa_set_saturation(dev, ctl->value, chan_num);
+		break;
+	}
+
+	err = 0;
+
+	return err;
+}
+
+static void cx25821_init_controls(struct cx25821_dev *dev, int chan_num)
+{
+	struct v4l2_control ctrl;
+	int i;
+	for (i = 0; i < CX25821_CTLS; i++) {
+		ctrl.id = cx25821_ctls[i].id;
+		ctrl.value = cx25821_ctls[i].default_value;
+
+		cx25821_set_control(dev, &ctrl, chan_num);
+	}
+}
+
+int cx25821_vidioc_cropcap(struct file *file, void *priv,
+			   struct v4l2_cropcap *cropcap)
+{
+	struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+
+	if (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+	cropcap->bounds.top = 0;
+	cropcap->bounds.left = 0;
+	cropcap->bounds.width = 720;
+	cropcap->bounds.height = dev->tvnorm == V4L2_STD_PAL_BG ? 576 : 480;
+	cropcap->pixelaspect.numerator =
+		dev->tvnorm == V4L2_STD_PAL_BG ? 59 : 10;
+	cropcap->pixelaspect.denominator =
+		dev->tvnorm == V4L2_STD_PAL_BG ? 54 : 11;
+	cropcap->defrect = cropcap->bounds;
+	return 0;
+}
+
+int cx25821_vidioc_s_crop(struct file *file, void *priv, struct v4l2_crop *crop)
+{
+	struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
+	struct cx25821_fh *fh = priv;
+	int err;
+
+	if (fh) {
+		err = v4l2_prio_check(&dev->channels[fh->channel_id].prio,
+				      fh->prio);
+		if (0 != err)
+			return err;
+	}
+	/* cx25821_vidioc_s_crop not supported */
+	return -EINVAL;
+}
+
+int cx25821_vidioc_g_crop(struct file *file, void *priv, struct v4l2_crop *crop)
+{
+	/* cx25821_vidioc_g_crop not supported */
+	return -EINVAL;
+}
+
+int cx25821_vidioc_querystd(struct file *file, void *priv, v4l2_std_id * norm)
+{
+	/* medusa does not support video standard sensing of current input */
+	*norm = CX25821_NORMS;
+
+	return 0;
+}
+
+int cx25821_is_valid_width(u32 width, v4l2_std_id tvnorm)
+{
+	if (tvnorm == V4L2_STD_PAL_BG) {
+		if (width == 352 || width == 720)
+			return 1;
+		else
+			return 0;
+	}
+
+	if (tvnorm == V4L2_STD_NTSC_M) {
+		if (width == 320 || width == 352 || width == 720)
+			return 1;
+		else
+			return 0;
+	}
+	return 0;
+}
+
+int cx25821_is_valid_height(u32 height, v4l2_std_id tvnorm)
+{
+	if (tvnorm == V4L2_STD_PAL_BG) {
+		if (height == 576 || height == 288)
+			return 1;
+		else
+			return 0;
+	}
+
+	if (tvnorm == V4L2_STD_NTSC_M) {
+		if (height == 480 || height == 240)
+			return 1;
+		else
+			return 0;
+	}
+
+	return 0;
+}
+
+static long video_ioctl_upstream9(struct file *file, unsigned int cmd,
+				 unsigned long arg)
+{
+	struct cx25821_fh *fh = file->private_data;
+	struct cx25821_dev *dev = fh->dev;
+	int command = 0;
+	struct upstream_user_struct *data_from_user;
+
+	data_from_user = (struct upstream_user_struct *)arg;
+
+	if (!data_from_user) {
+		pr_err("%s(): Upstream data is INVALID. Returning\n", __func__);
+		return 0;
+	}
+
+	command = data_from_user->command;
+
+	if (command != UPSTREAM_START_VIDEO && command != UPSTREAM_STOP_VIDEO)
+		return 0;
+
+	dev->input_filename = data_from_user->input_filename;
+	dev->input_audiofilename = data_from_user->input_filename;
+	dev->vid_stdname = data_from_user->vid_stdname;
+	dev->pixel_format = data_from_user->pixel_format;
+	dev->channel_select = data_from_user->channel_select;
+	dev->command = data_from_user->command;
+
+	switch (command) {
+	case UPSTREAM_START_VIDEO:
+		cx25821_start_upstream_video_ch1(dev, data_from_user);
+		break;
+
+	case UPSTREAM_STOP_VIDEO:
+		cx25821_stop_upstream_video_ch1(dev);
+		break;
+	}
+
+	return 0;
+}
+
+static long video_ioctl_upstream10(struct file *file, unsigned int cmd,
+				  unsigned long arg)
+{
+	struct cx25821_fh *fh = file->private_data;
+	struct cx25821_dev *dev = fh->dev;
+	int command = 0;
+	struct upstream_user_struct *data_from_user;
+
+	data_from_user = (struct upstream_user_struct *)arg;
+
+	if (!data_from_user) {
+		pr_err("%s(): Upstream data is INVALID. Returning\n", __func__);
+		return 0;
+	}
+
+	command = data_from_user->command;
+
+	if (command != UPSTREAM_START_VIDEO && command != UPSTREAM_STOP_VIDEO)
+		return 0;
+
+	dev->input_filename_ch2 = data_from_user->input_filename;
+	dev->input_audiofilename = data_from_user->input_filename;
+	dev->vid_stdname_ch2 = data_from_user->vid_stdname;
+	dev->pixel_format_ch2 = data_from_user->pixel_format;
+	dev->channel_select_ch2 = data_from_user->channel_select;
+	dev->command_ch2 = data_from_user->command;
+
+	switch (command) {
+	case UPSTREAM_START_VIDEO:
+		cx25821_start_upstream_video_ch2(dev, data_from_user);
+		break;
+
+	case UPSTREAM_STOP_VIDEO:
+		cx25821_stop_upstream_video_ch2(dev);
+		break;
+	}
+
+	return 0;
+}
+
+static long video_ioctl_upstream11(struct file *file, unsigned int cmd,
+				  unsigned long arg)
+{
+	struct cx25821_fh *fh = file->private_data;
+	struct cx25821_dev *dev = fh->dev;
+	int command = 0;
+	struct upstream_user_struct *data_from_user;
+
+	data_from_user = (struct upstream_user_struct *)arg;
+
+	if (!data_from_user) {
+		pr_err("%s(): Upstream data is INVALID. Returning\n", __func__);
+		return 0;
+	}
+
+	command = data_from_user->command;
+
+	if (command != UPSTREAM_START_AUDIO && command != UPSTREAM_STOP_AUDIO)
+		return 0;
+
+	dev->input_filename = data_from_user->input_filename;
+	dev->input_audiofilename = data_from_user->input_filename;
+	dev->vid_stdname = data_from_user->vid_stdname;
+	dev->pixel_format = data_from_user->pixel_format;
+	dev->channel_select = data_from_user->channel_select;
+	dev->command = data_from_user->command;
+
+	switch (command) {
+	case UPSTREAM_START_AUDIO:
+		cx25821_start_upstream_audio(dev, data_from_user);
+		break;
+
+	case UPSTREAM_STOP_AUDIO:
+		cx25821_stop_upstream_audio(dev);
+		break;
+	}
+
+	return 0;
+}
+
+static long video_ioctl_set(struct file *file, unsigned int cmd,
+			   unsigned long arg)
+{
+	struct cx25821_fh *fh = file->private_data;
+	struct cx25821_dev *dev = fh->dev;
+	struct downstream_user_struct *data_from_user;
+	int command;
+	int width = 720;
+	int selected_channel = 0;
+	int pix_format = 0;
+	int i = 0;
+	int cif_enable = 0;
+	int cif_width = 0;
+
+	data_from_user = (struct downstream_user_struct *)arg;
+
+	if (!data_from_user) {
+		pr_err("%s(): User data is INVALID. Returning\n", __func__);
+		return 0;
+	}
+
+	command = data_from_user->command;
+
+	if (command != SET_VIDEO_STD && command != SET_PIXEL_FORMAT
+	   && command != ENABLE_CIF_RESOLUTION && command != REG_READ
+	   && command != REG_WRITE && command != MEDUSA_READ
+	   && command != MEDUSA_WRITE) {
+		return 0;
+	}
+
+	switch (command) {
+	case SET_VIDEO_STD:
+		if (!strcmp(data_from_user->vid_stdname, "PAL"))
+			dev->tvnorm = V4L2_STD_PAL_BG;
+		else
+			dev->tvnorm = V4L2_STD_NTSC_M;
+		medusa_set_videostandard(dev);
+		break;
+
+	case SET_PIXEL_FORMAT:
+		selected_channel = data_from_user->decoder_select;
+		pix_format = data_from_user->pixel_format;
+
+		if (!(selected_channel <= 7 && selected_channel >= 0)) {
+			selected_channel -= 4;
+			selected_channel = selected_channel % 8;
+		}
+
+		if (selected_channel >= 0)
+			cx25821_set_pixel_format(dev, selected_channel,
+						pix_format);
+
+		break;
+
+	case ENABLE_CIF_RESOLUTION:
+		selected_channel = data_from_user->decoder_select;
+		cif_enable = data_from_user->cif_resolution_enable;
+		cif_width = data_from_user->cif_width;
+
+		if (cif_enable) {
+			if (dev->tvnorm & V4L2_STD_PAL_BG
+			    || dev->tvnorm & V4L2_STD_PAL_DK) {
+				width = 352;
+			} else {
+				width = cif_width;
+				if (cif_width != 320 && cif_width != 352)
+					width = 320;
+			}
+		}
+
+		if (!(selected_channel <= 7 && selected_channel >= 0)) {
+			selected_channel -= 4;
+			selected_channel = selected_channel % 8;
+		}
+
+		if (selected_channel <= 7 && selected_channel >= 0) {
+			dev->channels[selected_channel].use_cif_resolution =
+				cif_enable;
+			dev->channels[selected_channel].cif_width = width;
+		} else {
+			for (i = 0; i < VID_CHANNEL_NUM; i++) {
+				dev->channels[i].use_cif_resolution =
+					cif_enable;
+				dev->channels[i].cif_width = width;
+			}
+		}
+
+		medusa_set_resolution(dev, width, selected_channel);
+		break;
+	case REG_READ:
+		data_from_user->reg_data = cx_read(data_from_user->reg_address);
+		break;
+	case REG_WRITE:
+		cx_write(data_from_user->reg_address, data_from_user->reg_data);
+		break;
+	case MEDUSA_READ:
+		cx25821_i2c_read(&dev->i2c_bus[0],
+					 (u16) data_from_user->reg_address,
+					 &data_from_user->reg_data);
+		break;
+	case MEDUSA_WRITE:
+		cx25821_i2c_write(&dev->i2c_bus[0],
+				  (u16) data_from_user->reg_address,
+				  data_from_user->reg_data);
+		break;
+	}
+
+	return 0;
+}
+
+static long cx25821_video_ioctl(struct file *file,
+				unsigned int cmd, unsigned long arg)
+{
+	int ret = 0;
+
+	struct cx25821_fh *fh = file->private_data;
+
+	/* check to see if it's the video upstream */
+	if (fh->channel_id == SRAM_CH09) {
+		ret = video_ioctl_upstream9(file, cmd, arg);
+		return ret;
+	} else if (fh->channel_id == SRAM_CH10) {
+		ret = video_ioctl_upstream10(file, cmd, arg);
+		return ret;
+	} else if (fh->channel_id == SRAM_CH11) {
+		ret = video_ioctl_upstream11(file, cmd, arg);
+		ret = video_ioctl_set(file, cmd, arg);
+		return ret;
+	}
+
+	return video_ioctl2(file, cmd, arg);
+}
+
+/* exported stuff */
+static const struct v4l2_file_operations video_fops = {
+	.owner = THIS_MODULE,
+	.open = video_open,
+	.release = video_release,
+	.read = video_read,
+	.poll = video_poll,
+	.mmap = cx25821_video_mmap,
+	.ioctl = cx25821_video_ioctl,
+};
+
+static const struct v4l2_ioctl_ops video_ioctl_ops = {
+	.vidioc_querycap = cx25821_vidioc_querycap,
+	.vidioc_enum_fmt_vid_cap = cx25821_vidioc_enum_fmt_vid_cap,
+	.vidioc_g_fmt_vid_cap = cx25821_vidioc_g_fmt_vid_cap,
+	.vidioc_try_fmt_vid_cap = cx25821_vidioc_try_fmt_vid_cap,
+	.vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
+	.vidioc_reqbufs = cx25821_vidioc_reqbufs,
+	.vidioc_querybuf = cx25821_vidioc_querybuf,
+	.vidioc_qbuf = cx25821_vidioc_qbuf,
+	.vidioc_dqbuf = vidioc_dqbuf,
+#ifdef TUNER_FLAG
+	.vidioc_s_std = cx25821_vidioc_s_std,
+	.vidioc_querystd = cx25821_vidioc_querystd,
+#endif
+	.vidioc_cropcap = cx25821_vidioc_cropcap,
+	.vidioc_s_crop = cx25821_vidioc_s_crop,
+	.vidioc_g_crop = cx25821_vidioc_g_crop,
+	.vidioc_enum_input = cx25821_vidioc_enum_input,
+	.vidioc_g_input = cx25821_vidioc_g_input,
+	.vidioc_s_input = cx25821_vidioc_s_input,
+	.vidioc_g_ctrl = cx25821_vidioc_g_ctrl,
+	.vidioc_s_ctrl = vidioc_s_ctrl,
+	.vidioc_queryctrl = cx25821_vidioc_queryctrl,
+	.vidioc_streamon = vidioc_streamon,
+	.vidioc_streamoff = vidioc_streamoff,
+	.vidioc_log_status = vidioc_log_status,
+	.vidioc_g_priority = cx25821_vidioc_g_priority,
+	.vidioc_s_priority = cx25821_vidioc_s_priority,
+#ifdef TUNER_FLAG
+	.vidioc_g_tuner = cx25821_vidioc_g_tuner,
+	.vidioc_s_tuner = cx25821_vidioc_s_tuner,
+	.vidioc_g_frequency = cx25821_vidioc_g_frequency,
+	.vidioc_s_frequency = cx25821_vidioc_s_frequency,
+#endif
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.vidioc_g_register = cx25821_vidioc_g_register,
+	.vidioc_s_register = cx25821_vidioc_s_register,
+#endif
+};
+
+struct video_device cx25821_videoioctl_template = {
+	.name = "cx25821-videoioctl",
+	.fops = &video_fops,
+	.ioctl_ops = &video_ioctl_ops,
+	.tvnorms = CX25821_NORMS,
+	.current_norm = V4L2_STD_NTSC_M,
+};
diff --git a/drivers/media/pci/cx25821/cx25821-video.h b/drivers/media/pci/cx25821/cx25821-video.h
new file mode 100644
index 0000000..9652a5e
--- /dev/null
+++ b/drivers/media/pci/cx25821/cx25821-video.h
@@ -0,0 +1,186 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ *  Based on Steven Toth <stoth@linuxtv.org> cx23885 driver
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You 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 CX25821_VIDEO_H_
+#define CX25821_VIDEO_H_
+
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kmod.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/kthread.h>
+#include <asm/div64.h>
+
+#include "cx25821.h"
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+
+#define TUNER_FLAG
+
+#define VIDEO_DEBUG 0
+
+#define dprintk(level, fmt, arg...)					\
+do {									\
+	if (VIDEO_DEBUG >= level)					\
+		printk(KERN_DEBUG "%s/0: " fmt, dev->name, ##arg);	\
+} while (0)
+
+/* For IOCTL to identify running upstream */
+#define UPSTREAM_START_VIDEO        700
+#define UPSTREAM_STOP_VIDEO         701
+#define UPSTREAM_START_AUDIO        702
+#define UPSTREAM_STOP_AUDIO         703
+#define UPSTREAM_DUMP_REGISTERS     702
+#define SET_VIDEO_STD               800
+#define SET_PIXEL_FORMAT            1000
+#define ENABLE_CIF_RESOLUTION       1001
+
+#define REG_READ		    900
+#define REG_WRITE		    901
+#define MEDUSA_READ		    910
+#define MEDUSA_WRITE		    911
+
+extern struct sram_channel *channel0;
+extern struct sram_channel *channel1;
+extern struct sram_channel *channel2;
+extern struct sram_channel *channel3;
+extern struct sram_channel *channel4;
+extern struct sram_channel *channel5;
+extern struct sram_channel *channel6;
+extern struct sram_channel *channel7;
+extern struct sram_channel *channel9;
+extern struct sram_channel *channel10;
+extern struct sram_channel *channel11;
+extern struct video_device cx25821_videoioctl_template;
+/* extern const u32 *ctrl_classes[]; */
+
+extern unsigned int vid_limit;
+
+#define FORMAT_FLAGS_PACKED       0x01
+extern struct cx25821_fmt formats[];
+extern struct cx25821_fmt *cx25821_format_by_fourcc(unsigned int fourcc);
+extern struct cx25821_data timeout_data[MAX_VID_CHANNEL_NUM];
+
+extern void cx25821_video_wakeup(struct cx25821_dev *dev,
+				 struct cx25821_dmaqueue *q, u32 count);
+
+#ifdef TUNER_FLAG
+extern int cx25821_set_tvnorm(struct cx25821_dev *dev, v4l2_std_id norm);
+#endif
+
+extern int cx25821_res_get(struct cx25821_dev *dev, struct cx25821_fh *fh,
+			   unsigned int bit);
+extern int cx25821_res_check(struct cx25821_fh *fh, unsigned int bit);
+extern int cx25821_res_locked(struct cx25821_fh *fh, unsigned int bit);
+extern void cx25821_res_free(struct cx25821_dev *dev, struct cx25821_fh *fh,
+			     unsigned int bits);
+extern int cx25821_video_mux(struct cx25821_dev *dev, unsigned int input);
+extern int cx25821_start_video_dma(struct cx25821_dev *dev,
+				   struct cx25821_dmaqueue *q,
+				   struct cx25821_buffer *buf,
+				   struct sram_channel *channel);
+
+extern int cx25821_set_scale(struct cx25821_dev *dev, unsigned int width,
+			     unsigned int height, enum v4l2_field field);
+extern int cx25821_video_irq(struct cx25821_dev *dev, int chan_num, u32 status);
+extern void cx25821_video_unregister(struct cx25821_dev *dev, int chan_num);
+extern int cx25821_video_register(struct cx25821_dev *dev);
+extern int cx25821_get_format_size(void);
+
+extern int cx25821_buffer_setup(struct videobuf_queue *q, unsigned int *count,
+				unsigned int *size);
+extern int cx25821_buffer_prepare(struct videobuf_queue *q,
+				  struct videobuf_buffer *vb,
+				  enum v4l2_field field);
+extern void cx25821_buffer_release(struct videobuf_queue *q,
+				   struct videobuf_buffer *vb);
+extern struct videobuf_queue *get_queue(struct cx25821_fh *fh);
+extern int cx25821_get_resource(struct cx25821_fh *fh, int resource);
+extern int cx25821_video_mmap(struct file *file, struct vm_area_struct *vma);
+extern int cx25821_vidioc_try_fmt_vid_cap(struct file *file, void *priv,
+					  struct v4l2_format *f);
+extern int cx25821_vidioc_querycap(struct file *file, void *priv,
+				   struct v4l2_capability *cap);
+extern int cx25821_vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
+					   struct v4l2_fmtdesc *f);
+extern int cx25821_vidioc_reqbufs(struct file *file, void *priv,
+				  struct v4l2_requestbuffers *p);
+extern int cx25821_vidioc_querybuf(struct file *file, void *priv,
+				   struct v4l2_buffer *p);
+extern int cx25821_vidioc_qbuf(struct file *file, void *priv,
+			       struct v4l2_buffer *p);
+extern int cx25821_vidioc_s_std(struct file *file, void *priv,
+				v4l2_std_id *tvnorms);
+extern int cx25821_enum_input(struct cx25821_dev *dev, struct v4l2_input *i);
+extern int cx25821_vidioc_enum_input(struct file *file, void *priv,
+				     struct v4l2_input *i);
+extern int cx25821_vidioc_g_input(struct file *file, void *priv,
+				  unsigned int *i);
+extern int cx25821_vidioc_s_input(struct file *file, void *priv,
+				  unsigned int i);
+extern int cx25821_vidioc_g_ctrl(struct file *file, void *priv,
+				 struct v4l2_control *ctl);
+extern int cx25821_vidioc_g_fmt_vid_cap(struct file *file, void *priv,
+					struct v4l2_format *f);
+extern int cx25821_vidioc_g_frequency(struct file *file, void *priv,
+				      struct v4l2_frequency *f);
+extern int cx25821_set_freq(struct cx25821_dev *dev, struct v4l2_frequency *f);
+extern int cx25821_vidioc_s_frequency(struct file *file, void *priv,
+				      struct v4l2_frequency *f);
+extern int cx25821_vidioc_g_register(struct file *file, void *fh,
+				     struct v4l2_dbg_register *reg);
+extern int cx25821_vidioc_s_register(struct file *file, void *fh,
+				     struct v4l2_dbg_register *reg);
+extern int cx25821_vidioc_g_tuner(struct file *file, void *priv,
+				  struct v4l2_tuner *t);
+extern int cx25821_vidioc_s_tuner(struct file *file, void *priv,
+				  struct v4l2_tuner *t);
+
+extern int cx25821_is_valid_width(u32 width, v4l2_std_id tvnorm);
+extern int cx25821_is_valid_height(u32 height, v4l2_std_id tvnorm);
+
+extern int cx25821_vidioc_g_priority(struct file *file, void *f,
+				     enum v4l2_priority *p);
+extern int cx25821_vidioc_s_priority(struct file *file, void *f,
+				     enum v4l2_priority prio);
+
+extern int cx25821_vidioc_queryctrl(struct file *file, void *priv,
+				    struct v4l2_queryctrl *qctrl);
+extern int cx25821_set_control(struct cx25821_dev *dev,
+			       struct v4l2_control *ctrl, int chan_num);
+
+extern int cx25821_vidioc_cropcap(struct file *file, void *fh,
+				  struct v4l2_cropcap *cropcap);
+extern int cx25821_vidioc_s_crop(struct file *file, void *priv,
+				 struct v4l2_crop *crop);
+extern int cx25821_vidioc_g_crop(struct file *file, void *priv,
+				 struct v4l2_crop *crop);
+
+extern int cx25821_vidioc_querystd(struct file *file, void *priv,
+				   v4l2_std_id *norm);
+#endif
diff --git a/drivers/media/pci/cx25821/cx25821.h b/drivers/media/pci/cx25821/cx25821.h
new file mode 100644
index 0000000..8a9c0c8
--- /dev/null
+++ b/drivers/media/pci/cx25821/cx25821.h
@@ -0,0 +1,615 @@
+/*
+ *  Driver for the Conexant CX25821 PCIe bridge
+ *
+ *  Copyright (C) 2009 Conexant Systems Inc.
+ *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
+ *  Based on Steven Toth <stoth@linuxtv.org> cx23885 driver
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *
+ *  GNU General Public License for more details.
+ *
+ *  You 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 CX25821_H_
+#define CX25821_H_
+
+#include <linux/pci.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/sched.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>
+#include <media/videobuf-dvb.h>
+
+#include "btcx-risc.h"
+#include "cx25821-reg.h"
+#include "cx25821-medusa-reg.h"
+#include "cx25821-sram.h"
+#include "cx25821-audio.h"
+#include "media/cx2341x.h"
+
+#include <linux/version.h>
+#include <linux/mutex.h>
+
+#define CX25821_VERSION_CODE KERNEL_VERSION(0, 0, 106)
+
+#define UNSET (-1U)
+#define NO_SYNC_LINE (-1U)
+
+#define CX25821_MAXBOARDS 2
+
+#define TRUE    1
+#define FALSE   0
+#define LINE_SIZE_D1    1440
+
+/* Number of decoders and encoders */
+#define MAX_DECODERS            8
+#define MAX_ENCODERS            2
+#define QUAD_DECODERS           4
+#define MAX_CAMERAS             16
+
+/* Max number of inputs by card */
+#define MAX_CX25821_INPUT     8
+#define INPUT(nr) (&cx25821_boards[dev->board].input[nr])
+#define RESOURCE_VIDEO0       1
+#define RESOURCE_VIDEO1       2
+#define RESOURCE_VIDEO2       4
+#define RESOURCE_VIDEO3       8
+#define RESOURCE_VIDEO4       16
+#define RESOURCE_VIDEO5       32
+#define RESOURCE_VIDEO6       64
+#define RESOURCE_VIDEO7       128
+#define RESOURCE_VIDEO8       256
+#define RESOURCE_VIDEO9       512
+#define RESOURCE_VIDEO10      1024
+#define RESOURCE_VIDEO11      2048
+#define RESOURCE_VIDEO_IOCTL  4096
+
+#define BUFFER_TIMEOUT     (HZ)	/* 0.5 seconds */
+
+#define UNKNOWN_BOARD        0
+#define CX25821_BOARD        1
+
+/* Currently supported by the driver */
+#define CX25821_NORMS (\
+	V4L2_STD_NTSC_M |  V4L2_STD_NTSC_M_JP | V4L2_STD_NTSC_M_KR | \
+	V4L2_STD_PAL_BG |  V4L2_STD_PAL_DK    |  V4L2_STD_PAL_I    | \
+	V4L2_STD_PAL_M  |  V4L2_STD_PAL_N     |  V4L2_STD_PAL_H    | \
+	V4L2_STD_PAL_Nc)
+
+#define CX25821_BOARD_CONEXANT_ATHENA10 1
+#define MAX_VID_CHANNEL_NUM     12
+#define VID_CHANNEL_NUM 8
+#define CX25821_NR_INPUT 2
+
+struct cx25821_fmt {
+	char *name;
+	u32 fourcc;		/* v4l2 format id */
+	int depth;
+	int flags;
+	u32 cxformat;
+};
+
+struct cx25821_ctrl {
+	struct v4l2_queryctrl v;
+	u32 off;
+	u32 reg;
+	u32 mask;
+	u32 shift;
+};
+
+struct cx25821_tvnorm {
+	char *name;
+	v4l2_std_id id;
+	u32 cxiformat;
+	u32 cxoformat;
+};
+
+struct cx25821_fh {
+	struct cx25821_dev *dev;
+	enum v4l2_buf_type type;
+	int radio;
+	u32 resources;
+
+	enum v4l2_priority prio;
+
+	/* video overlay */
+	struct v4l2_window win;
+	struct v4l2_clip *clips;
+	unsigned int nclips;
+
+	/* video capture */
+	struct cx25821_fmt *fmt;
+	unsigned int width, height;
+	int channel_id;
+
+	/* vbi capture */
+	struct videobuf_queue vidq;
+	struct videobuf_queue vbiq;
+
+	/* H264 Encoder specifics ONLY */
+	struct videobuf_queue mpegq;
+	atomic_t v4l_reading;
+};
+
+enum cx25821_itype {
+	CX25821_VMUX_COMPOSITE = 1,
+	CX25821_VMUX_SVIDEO,
+	CX25821_VMUX_DEBUG,
+	CX25821_RADIO,
+};
+
+enum cx25821_src_sel_type {
+	CX25821_SRC_SEL_EXT_656_VIDEO = 0,
+	CX25821_SRC_SEL_PARALLEL_MPEG_VIDEO
+};
+
+/* buffer for one video frame */
+struct cx25821_buffer {
+	/* common v4l buffer stuff -- must be first */
+	struct videobuf_buffer vb;
+
+	/* cx25821 specific */
+	unsigned int bpl;
+	struct btcx_riscmem risc;
+	struct cx25821_fmt *fmt;
+	u32 count;
+};
+
+struct cx25821_input {
+	enum cx25821_itype type;
+	unsigned int vmux;
+	u32 gpio0, gpio1, gpio2, gpio3;
+};
+
+enum port {
+	CX25821_UNDEFINED = 0,
+	CX25821_RAW,
+	CX25821_264
+};
+
+struct cx25821_board {
+	const char *name;
+	enum port porta;
+	enum port portb;
+	enum port portc;
+	unsigned int tuner_type;
+	unsigned int radio_type;
+	unsigned char tuner_addr;
+	unsigned char radio_addr;
+
+	u32 clk_freq;
+	struct cx25821_input input[CX25821_NR_INPUT];
+};
+
+struct cx25821_subid {
+	u16 subvendor;
+	u16 subdevice;
+	u32 card;
+};
+
+struct cx25821_i2c {
+	struct cx25821_dev *dev;
+
+	int nr;
+
+	/* i2c i/o */
+	struct i2c_adapter i2c_adap;
+	struct i2c_client i2c_client;
+	u32 i2c_rc;
+
+	/* cx25821 registers used for raw addess */
+	u32 i2c_period;
+	u32 reg_ctrl;
+	u32 reg_stat;
+	u32 reg_addr;
+	u32 reg_rdata;
+	u32 reg_wdata;
+};
+
+struct cx25821_dmaqueue {
+	struct list_head active;
+	struct list_head queued;
+	struct timer_list timeout;
+	struct btcx_riscmem stopper;
+	u32 count;
+};
+
+struct cx25821_data {
+	struct cx25821_dev *dev;
+	struct sram_channel *channel;
+};
+
+struct cx25821_channel {
+	struct v4l2_prio_state prio;
+
+	int ctl_bright;
+	int ctl_contrast;
+	int ctl_hue;
+	int ctl_saturation;
+	struct cx25821_data timeout_data;
+
+	struct video_device *video_dev;
+	struct cx25821_dmaqueue vidq;
+
+	struct sram_channel *sram_channels;
+
+	struct mutex lock;
+	int resources;
+
+	int pixel_formats;
+	int use_cif_resolution;
+	int cif_width;
+};
+
+struct cx25821_dev {
+	struct list_head devlist;
+	atomic_t refcount;
+	struct v4l2_device v4l2_dev;
+
+	/* pci stuff */
+	struct pci_dev *pci;
+	unsigned char pci_rev, pci_lat;
+	int pci_bus, pci_slot;
+	u32 base_io_addr;
+	u32 __iomem *lmmio;
+	u8 __iomem *bmmio;
+	int pci_irqmask;
+	int hwrevision;
+
+	u32 clk_freq;
+
+	/* I2C adapters: Master 1 & 2 (External) & Master 3 (Internal only) */
+	struct cx25821_i2c i2c_bus[3];
+
+	int nr;
+	struct mutex lock;
+
+	struct cx25821_channel channels[MAX_VID_CHANNEL_NUM];
+
+	/* board details */
+	unsigned int board;
+	char name[32];
+
+	/* Analog video */
+	u32 resources;
+	unsigned int input;
+	u32 tvaudio;
+	v4l2_std_id tvnorm;
+	unsigned int tuner_type;
+	unsigned char tuner_addr;
+	unsigned int radio_type;
+	unsigned char radio_addr;
+	unsigned int has_radio;
+	unsigned int videc_type;
+	unsigned char videc_addr;
+	unsigned short _max_num_decoders;
+
+	/* Analog Audio Upstream */
+	int _audio_is_running;
+	int _audiopixel_format;
+	int _is_first_audio_frame;
+	int _audiofile_status;
+	int _audio_lines_count;
+	int _audioframe_count;
+	int _audio_upstream_channel;
+	int _last_index_irq;    /* The last interrupt index processed. */
+
+	__le32 *_risc_audio_jmp_addr;
+	__le32 *_risc_virt_start_addr;
+	__le32 *_risc_virt_addr;
+	dma_addr_t _risc_phys_addr;
+	dma_addr_t _risc_phys_start_addr;
+
+	unsigned int _audiorisc_size;
+	unsigned int _audiodata_buf_size;
+	__le32 *_audiodata_buf_virt_addr;
+	dma_addr_t _audiodata_buf_phys_addr;
+	char *_audiofilename;
+
+	/* V4l */
+	u32 freq;
+	struct video_device *vbi_dev;
+	struct video_device *radio_dev;
+	struct video_device *ioctl_dev;
+
+	spinlock_t slock;
+
+	/* Video Upstream */
+	int _line_size;
+	int _prog_cnt;
+	int _pixel_format;
+	int _is_first_frame;
+	int _is_running;
+	int _file_status;
+	int _lines_count;
+	int _frame_count;
+	int _channel_upstream_select;
+	unsigned int _risc_size;
+
+	__le32 *_dma_virt_start_addr;
+	__le32 *_dma_virt_addr;
+	dma_addr_t _dma_phys_addr;
+	dma_addr_t _dma_phys_start_addr;
+
+	unsigned int _data_buf_size;
+	__le32 *_data_buf_virt_addr;
+	dma_addr_t _data_buf_phys_addr;
+	char *_filename;
+	char *_defaultname;
+
+	int _line_size_ch2;
+	int _prog_cnt_ch2;
+	int _pixel_format_ch2;
+	int _is_first_frame_ch2;
+	int _is_running_ch2;
+	int _file_status_ch2;
+	int _lines_count_ch2;
+	int _frame_count_ch2;
+	int _channel2_upstream_select;
+	unsigned int _risc_size_ch2;
+
+	__le32 *_dma_virt_start_addr_ch2;
+	__le32 *_dma_virt_addr_ch2;
+	dma_addr_t _dma_phys_addr_ch2;
+	dma_addr_t _dma_phys_start_addr_ch2;
+
+	unsigned int _data_buf_size_ch2;
+	__le32 *_data_buf_virt_addr_ch2;
+	dma_addr_t _data_buf_phys_addr_ch2;
+	char *_filename_ch2;
+	char *_defaultname_ch2;
+
+	/* MPEG Encoder ONLY settings */
+	u32 cx23417_mailbox;
+	struct cx2341x_mpeg_params mpeg_params;
+	struct video_device *v4l_device;
+	atomic_t v4l_reader_count;
+	struct cx25821_tvnorm encodernorm;
+
+	u32 upstream_riscbuf_size;
+	u32 upstream_databuf_size;
+	u32 upstream_riscbuf_size_ch2;
+	u32 upstream_databuf_size_ch2;
+	u32 audio_upstream_riscbuf_size;
+	u32 audio_upstream_databuf_size;
+	int _isNTSC;
+	int _frame_index;
+	int _audioframe_index;
+	struct workqueue_struct *_irq_queues;
+	struct work_struct _irq_work_entry;
+	struct workqueue_struct *_irq_queues_ch2;
+	struct work_struct _irq_work_entry_ch2;
+	struct workqueue_struct *_irq_audio_queues;
+	struct work_struct _audio_work_entry;
+	char *input_filename;
+	char *input_filename_ch2;
+	int _frame_index_ch2;
+	int _isNTSC_ch2;
+	char *vid_stdname_ch2;
+	int pixel_format_ch2;
+	int channel_select_ch2;
+	int command_ch2;
+	char *input_audiofilename;
+	char *vid_stdname;
+	int pixel_format;
+	int channel_select;
+	int command;
+	int channel_opened;
+};
+
+struct upstream_user_struct {
+	char *input_filename;
+	char *vid_stdname;
+	int pixel_format;
+	int channel_select;
+	int command;
+};
+
+struct downstream_user_struct {
+	char *vid_stdname;
+	int pixel_format;
+	int cif_resolution_enable;
+	int cif_width;
+	int decoder_select;
+	int command;
+	int reg_address;
+	int reg_data;
+};
+
+extern struct upstream_user_struct *up_data;
+
+static inline struct cx25821_dev *get_cx25821(struct v4l2_device *v4l2_dev)
+{
+	return container_of(v4l2_dev, struct cx25821_dev, v4l2_dev);
+}
+
+#define cx25821_call_all(dev, o, f, args...) \
+	v4l2_device_call_all(&dev->v4l2_dev, 0, o, f, ##args)
+
+extern struct list_head cx25821_devlist;
+extern struct mutex cx25821_devlist_mutex;
+
+extern struct cx25821_board cx25821_boards[];
+extern struct cx25821_subid cx25821_subids[];
+
+#define SRAM_CH00  0		/* Video A */
+#define SRAM_CH01  1		/* Video B */
+#define SRAM_CH02  2		/* Video C */
+#define SRAM_CH03  3		/* Video D */
+#define SRAM_CH04  4		/* Video E */
+#define SRAM_CH05  5		/* Video F */
+#define SRAM_CH06  6		/* Video G */
+#define SRAM_CH07  7		/* Video H */
+
+#define SRAM_CH08  8		/* Audio A */
+#define SRAM_CH09  9		/* Video Upstream I */
+#define SRAM_CH10  10		/* Video Upstream J */
+#define SRAM_CH11  11		/* Audio Upstream AUD_CHANNEL_B */
+
+#define VID_UPSTREAM_SRAM_CHANNEL_I     SRAM_CH09
+#define VID_UPSTREAM_SRAM_CHANNEL_J     SRAM_CH10
+#define AUDIO_UPSTREAM_SRAM_CHANNEL_B   SRAM_CH11
+#define VIDEO_IOCTL_CH  11
+
+struct sram_channel {
+	char *name;
+	u32 i;
+	u32 cmds_start;
+	u32 ctrl_start;
+	u32 cdt;
+	u32 fifo_start;
+	u32 fifo_size;
+	u32 ptr1_reg;
+	u32 ptr2_reg;
+	u32 cnt1_reg;
+	u32 cnt2_reg;
+	u32 int_msk;
+	u32 int_stat;
+	u32 int_mstat;
+	u32 dma_ctl;
+	u32 gpcnt_ctl;
+	u32 gpcnt;
+	u32 aud_length;
+	u32 aud_cfg;
+	u32 fld_aud_fifo_en;
+	u32 fld_aud_risc_en;
+
+	/* For Upstream Video */
+	u32 vid_fmt_ctl;
+	u32 vid_active_ctl1;
+	u32 vid_active_ctl2;
+	u32 vid_cdt_size;
+
+	u32 vip_ctl;
+	u32 pix_frmt;
+	u32 jumponly;
+	u32 irq_bit;
+};
+extern struct sram_channel cx25821_sram_channels[];
+
+#define STATUS_SUCCESS         0
+#define STATUS_UNSUCCESSFUL    -1
+
+#define cx_read(reg)             readl(dev->lmmio + ((reg)>>2))
+#define cx_write(reg, value)     writel((value), dev->lmmio + ((reg)>>2))
+
+#define cx_andor(reg, mask, value) \
+	writel((readl(dev->lmmio+((reg)>>2)) & ~(mask)) |\
+	((value) & (mask)), dev->lmmio+((reg)>>2))
+
+#define cx_set(reg, bit)          cx_andor((reg), (bit), (bit))
+#define cx_clear(reg, bit)        cx_andor((reg), (bit), 0)
+
+#define Set_GPIO_Bit(Bit)                       (1 << Bit)
+#define Clear_GPIO_Bit(Bit)                     (~(1 << Bit))
+
+#define CX25821_ERR(fmt, args...)			\
+	pr_err("(%d): " fmt, dev->board, ##args)
+#define CX25821_WARN(fmt, args...)			\
+	pr_warn("(%d): " fmt, dev->board, ##args)
+#define CX25821_INFO(fmt, args...)			\
+	pr_info("(%d): " fmt, dev->board, ##args)
+
+extern int cx25821_i2c_register(struct cx25821_i2c *bus);
+extern void cx25821_card_setup(struct cx25821_dev *dev);
+extern int cx25821_ir_init(struct cx25821_dev *dev);
+extern int cx25821_i2c_read(struct cx25821_i2c *bus, u16 reg_addr, int *value);
+extern int cx25821_i2c_write(struct cx25821_i2c *bus, u16 reg_addr, int value);
+extern int cx25821_i2c_unregister(struct cx25821_i2c *bus);
+extern void cx25821_gpio_init(struct cx25821_dev *dev);
+extern void cx25821_set_gpiopin_direction(struct cx25821_dev *dev,
+					  int pin_number, int pin_logic_value);
+
+extern int medusa_video_init(struct cx25821_dev *dev);
+extern int medusa_set_videostandard(struct cx25821_dev *dev);
+extern void medusa_set_resolution(struct cx25821_dev *dev, int width,
+				  int decoder_select);
+extern int medusa_set_brightness(struct cx25821_dev *dev, int brightness,
+				 int decoder);
+extern int medusa_set_contrast(struct cx25821_dev *dev, int contrast,
+			       int decoder);
+extern int medusa_set_hue(struct cx25821_dev *dev, int hue, int decoder);
+extern int medusa_set_saturation(struct cx25821_dev *dev, int saturation,
+				 int decoder);
+
+extern int cx25821_sram_channel_setup(struct cx25821_dev *dev,
+				      struct sram_channel *ch, unsigned int bpl,
+				      u32 risc);
+
+extern int cx25821_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
+			       struct scatterlist *sglist,
+			       unsigned int top_offset,
+			       unsigned int bottom_offset,
+			       unsigned int bpl,
+			       unsigned int padding, unsigned int lines);
+extern int cx25821_risc_databuffer_audio(struct pci_dev *pci,
+					 struct btcx_riscmem *risc,
+					 struct scatterlist *sglist,
+					 unsigned int bpl,
+					 unsigned int lines, unsigned int lpi);
+extern void cx25821_free_buffer(struct videobuf_queue *q,
+				struct cx25821_buffer *buf);
+extern int cx25821_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
+				u32 reg, u32 mask, u32 value);
+extern void cx25821_sram_channel_dump(struct cx25821_dev *dev,
+				      struct sram_channel *ch);
+extern void cx25821_sram_channel_dump_audio(struct cx25821_dev *dev,
+					    struct sram_channel *ch);
+
+extern struct cx25821_dev *cx25821_dev_get(struct pci_dev *pci);
+extern void cx25821_print_irqbits(char *name, char *tag, char **strings,
+				  int len, u32 bits, u32 mask);
+extern void cx25821_dev_unregister(struct cx25821_dev *dev);
+extern int cx25821_sram_channel_setup_audio(struct cx25821_dev *dev,
+					    struct sram_channel *ch,
+					    unsigned int bpl, u32 risc);
+
+extern int cx25821_vidupstream_init_ch1(struct cx25821_dev *dev,
+					int channel_select, int pixel_format);
+extern int cx25821_vidupstream_init_ch2(struct cx25821_dev *dev,
+					int channel_select, int pixel_format);
+extern int cx25821_audio_upstream_init(struct cx25821_dev *dev,
+				       int channel_select);
+extern void cx25821_free_mem_upstream_ch1(struct cx25821_dev *dev);
+extern void cx25821_free_mem_upstream_ch2(struct cx25821_dev *dev);
+extern void cx25821_free_mem_upstream_audio(struct cx25821_dev *dev);
+extern void cx25821_start_upstream_video_ch1(struct cx25821_dev *dev,
+					     struct upstream_user_struct
+					     *up_data);
+extern void cx25821_start_upstream_video_ch2(struct cx25821_dev *dev,
+					     struct upstream_user_struct
+					     *up_data);
+extern void cx25821_start_upstream_audio(struct cx25821_dev *dev,
+					 struct upstream_user_struct *up_data);
+extern void cx25821_stop_upstream_video_ch1(struct cx25821_dev *dev);
+extern void cx25821_stop_upstream_video_ch2(struct cx25821_dev *dev);
+extern void cx25821_stop_upstream_audio(struct cx25821_dev *dev);
+extern int cx25821_sram_channel_setup_upstream(struct cx25821_dev *dev,
+					       struct sram_channel *ch,
+					       unsigned int bpl, u32 risc);
+extern void cx25821_set_pixel_format(struct cx25821_dev *dev, int channel,
+				     u32 format);
+extern void cx25821_videoioctl_unregister(struct cx25821_dev *dev);
+extern struct video_device *cx25821_vdev_init(struct cx25821_dev *dev,
+					      struct pci_dev *pci,
+					      struct video_device *template,
+					      char *type);
+#endif
diff --git a/drivers/media/pci/cx88/Kconfig b/drivers/media/pci/cx88/Kconfig
new file mode 100644
index 0000000..d27fccb
--- /dev/null
+++ b/drivers/media/pci/cx88/Kconfig
@@ -0,0 +1,86 @@
+config VIDEO_CX88
+	tristate "Conexant 2388x (bt878 successor) support"
+	depends on VIDEO_DEV && PCI && I2C && RC_CORE
+	select I2C_ALGOBIT
+	select VIDEO_BTCX
+	select VIDEOBUF_DMA_SG
+	select VIDEO_TUNER
+	select VIDEO_TVEEPROM
+	select VIDEO_WM8775 if MEDIA_SUBDRV_AUTOSELECT
+	---help---
+	  This is a video4linux driver for Conexant 2388x based
+	  TV cards.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called cx8800
+
+config VIDEO_CX88_ALSA
+	tristate "Conexant 2388x DMA audio support"
+	depends on VIDEO_CX88 && SND
+	select SND_PCM
+	---help---
+	  This is a video4linux driver for direct (DMA) audio on
+	  Conexant 2388x based TV cards using ALSA.
+
+	  It only works with boards with function 01 enabled.
+	  To check if your board supports, use lspci -n.
+	  If supported, you should see 14f1:8801 or 14f1:8811
+	  PCI device.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called cx88-alsa.
+
+config VIDEO_CX88_BLACKBIRD
+	tristate "Blackbird MPEG encoder support (cx2388x + cx23416)"
+	depends on VIDEO_CX88
+	select VIDEO_CX2341X
+	---help---
+	  This adds support for MPEG encoder cards based on the
+	  Blackbird reference design, using the Conexant 2388x
+	  and 23416 chips.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called cx88-blackbird.
+
+config VIDEO_CX88_DVB
+	tristate "DVB/ATSC Support for cx2388x based TV cards"
+	depends on VIDEO_CX88 && DVB_CORE
+	select VIDEOBUF_DVB
+	select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_MT352 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_ZL10353 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_OR51132 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_CX22702 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_LGDT330X if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_NXT200X if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_CX24123 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_ISL6421 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_S5H1411 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_CX24116 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_STV0299 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_STV0288 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_STB6000 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_STV0900 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_STB6100 if MEDIA_SUBDRV_AUTOSELECT
+	select MEDIA_TUNER_SIMPLE if MEDIA_SUBDRV_AUTOSELECT
+	---help---
+	  This adds support for DVB/ATSC cards based on the
+	  Conexant 2388x chip.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called cx88-dvb.
+
+config VIDEO_CX88_VP3054
+	tristate "VP-3054 Secondary I2C Bus Support"
+	default m
+	depends on VIDEO_CX88_DVB && DVB_MT352
+	---help---
+	  This adds DVB-T support for cards based on the
+	  Conexant 2388x chip and the MT352 demodulator,
+	  which also require support for the VP-3054
+	  Secondary I2C bus, such at DNTV Live! DVB-T Pro.
+
+config VIDEO_CX88_MPEG
+	tristate
+	depends on VIDEO_CX88_DVB || VIDEO_CX88_BLACKBIRD
+	default y
diff --git a/drivers/media/pci/cx88/Makefile b/drivers/media/pci/cx88/Makefile
new file mode 100644
index 0000000..d3679c3
--- /dev/null
+++ b/drivers/media/pci/cx88/Makefile
@@ -0,0 +1,16 @@
+cx88xx-objs	:= cx88-cards.o cx88-core.o cx88-i2c.o cx88-tvaudio.o \
+		   cx88-dsp.o cx88-input.o
+cx8800-objs	:= cx88-video.o cx88-vbi.o
+cx8802-objs	:= cx88-mpeg.o
+
+obj-$(CONFIG_VIDEO_CX88) += cx88xx.o cx8800.o
+obj-$(CONFIG_VIDEO_CX88_MPEG) += cx8802.o
+obj-$(CONFIG_VIDEO_CX88_ALSA) += cx88-alsa.o
+obj-$(CONFIG_VIDEO_CX88_BLACKBIRD) += cx88-blackbird.o
+obj-$(CONFIG_VIDEO_CX88_DVB) += cx88-dvb.o
+obj-$(CONFIG_VIDEO_CX88_VP3054) += cx88-vp3054-i2c.o
+
+ccflags-y += -Idrivers/media/i2c
+ccflags-y += -Idrivers/media/tuners
+ccflags-y += -Idrivers/media/dvb-core
+ccflags-y += -Idrivers/media/dvb-frontends
diff --git a/drivers/media/pci/cx88/cx88-alsa.c b/drivers/media/pci/cx88/cx88-alsa.c
new file mode 100644
index 0000000..3aa6856
--- /dev/null
+++ b/drivers/media/pci/cx88/cx88-alsa.c
@@ -0,0 +1,975 @@
+/*
+ *
+ *  Support for audio capture
+ *  PCI function #1 of the cx2388x.
+ *
+ *    (c) 2007 Trent Piepho <xyzzy@speakeasy.org>
+ *    (c) 2005,2006 Ricardo Cerqueira <v4l@cerqueira.org>
+ *    (c) 2005 Mauro Carvalho Chehab <mchehab@infradead.org>
+ *    Based on a dummy cx88 module by Gerd Knorr <kraxel@bytesex.org>
+ *    Based on dummy.c by Jaroslav Kysela <perex@perex.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
+ *  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/init.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/vmalloc.h>
+#include <linux/dma-mapping.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+
+#include <asm/delay.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/control.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+#include <media/wm8775.h>
+
+#include "cx88.h"
+#include "cx88-reg.h"
+
+#define dprintk(level,fmt, arg...)	if (debug >= level) \
+	printk(KERN_INFO "%s/1: " fmt, chip->core->name , ## arg)
+
+#define dprintk_core(level,fmt, arg...)	if (debug >= level) \
+	printk(KERN_DEBUG "%s/1: " fmt, chip->core->name , ## arg)
+
+/****************************************************************************
+	Data type declarations - Can be moded to a header file later
+ ****************************************************************************/
+
+struct cx88_audio_buffer {
+	unsigned int               bpl;
+	struct btcx_riscmem        risc;
+	struct videobuf_dmabuf     dma;
+};
+
+struct cx88_audio_dev {
+	struct cx88_core           *core;
+	struct cx88_dmaqueue       q;
+
+	/* pci i/o */
+	struct pci_dev             *pci;
+
+	/* audio controls */
+	int                        irq;
+
+	struct snd_card            *card;
+
+	spinlock_t                 reg_lock;
+	atomic_t		   count;
+
+	unsigned int               dma_size;
+	unsigned int               period_size;
+	unsigned int               num_periods;
+
+	struct videobuf_dmabuf     *dma_risc;
+
+	struct cx88_audio_buffer   *buf;
+
+	struct snd_pcm_substream   *substream;
+};
+typedef struct cx88_audio_dev snd_cx88_card_t;
+
+
+
+/****************************************************************************
+			Module global static vars
+ ****************************************************************************/
+
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
+static const char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
+static bool enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 1};
+
+module_param_array(enable, bool, NULL, 0444);
+MODULE_PARM_DESC(enable, "Enable cx88x soundcard. default enabled.");
+
+module_param_array(index, int, NULL, 0444);
+MODULE_PARM_DESC(index, "Index value for cx88x capture interface(s).");
+
+
+/****************************************************************************
+				Module macros
+ ****************************************************************************/
+
+MODULE_DESCRIPTION("ALSA driver module for cx2388x based TV cards");
+MODULE_AUTHOR("Ricardo Cerqueira");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(CX88_VERSION);
+
+MODULE_SUPPORTED_DEVICE("{{Conexant,23881},"
+			"{{Conexant,23882},"
+			"{{Conexant,23883}");
+static unsigned int debug;
+module_param(debug,int,0644);
+MODULE_PARM_DESC(debug,"enable debug messages");
+
+/****************************************************************************
+			Module specific funtions
+ ****************************************************************************/
+
+/*
+ * BOARD Specific: Sets audio DMA
+ */
+
+static int _cx88_start_audio_dma(snd_cx88_card_t *chip)
+{
+	struct cx88_audio_buffer *buf = chip->buf;
+	struct cx88_core *core=chip->core;
+	const struct sram_channel *audio_ch = &cx88_sram_channels[SRAM_CH25];
+
+	/* Make sure RISC/FIFO are off before changing FIFO/RISC settings */
+	cx_clear(MO_AUD_DMACNTRL, 0x11);
+
+	/* setup fifo + format - out channel */
+	cx88_sram_channel_setup(chip->core, audio_ch, buf->bpl, buf->risc.dma);
+
+	/* sets bpl size */
+	cx_write(MO_AUDD_LNGTH, buf->bpl);
+
+	/* reset counter */
+	cx_write(MO_AUDD_GPCNTRL, GP_COUNT_CONTROL_RESET);
+	atomic_set(&chip->count, 0);
+
+	dprintk(1, "Start audio DMA, %d B/line, %d lines/FIFO, %d periods, %d "
+		"byte buffer\n", buf->bpl, cx_read(audio_ch->cmds_start + 8)>>1,
+		chip->num_periods, buf->bpl * chip->num_periods);
+
+	/* Enables corresponding bits at AUD_INT_STAT */
+	cx_write(MO_AUD_INTMSK, AUD_INT_OPC_ERR | AUD_INT_DN_SYNC |
+				AUD_INT_DN_RISCI2 | AUD_INT_DN_RISCI1);
+
+	/* Clean any pending interrupt bits already set */
+	cx_write(MO_AUD_INTSTAT, ~0);
+
+	/* enable audio irqs */
+	cx_set(MO_PCI_INTMSK, chip->core->pci_irqmask | PCI_INT_AUDINT);
+
+	/* start dma */
+	cx_set(MO_DEV_CNTRL2, (1<<5)); /* Enables Risc Processor */
+	cx_set(MO_AUD_DMACNTRL, 0x11); /* audio downstream FIFO and RISC enable */
+
+	if (debug)
+		cx88_sram_channel_dump(chip->core, audio_ch);
+
+	return 0;
+}
+
+/*
+ * BOARD Specific: Resets audio DMA
+ */
+static int _cx88_stop_audio_dma(snd_cx88_card_t *chip)
+{
+	struct cx88_core *core=chip->core;
+	dprintk(1, "Stopping audio DMA\n");
+
+	/* stop dma */
+	cx_clear(MO_AUD_DMACNTRL, 0x11);
+
+	/* disable irqs */
+	cx_clear(MO_PCI_INTMSK, PCI_INT_AUDINT);
+	cx_clear(MO_AUD_INTMSK, AUD_INT_OPC_ERR | AUD_INT_DN_SYNC |
+				AUD_INT_DN_RISCI2 | AUD_INT_DN_RISCI1);
+
+	if (debug)
+		cx88_sram_channel_dump(chip->core, &cx88_sram_channels[SRAM_CH25]);
+
+	return 0;
+}
+
+#define MAX_IRQ_LOOP 50
+
+/*
+ * BOARD Specific: IRQ dma bits
+ */
+static const char *cx88_aud_irqs[32] = {
+	"dn_risci1", "up_risci1", "rds_dn_risc1", /* 0-2 */
+	NULL,					  /* reserved */
+	"dn_risci2", "up_risci2", "rds_dn_risc2", /* 4-6 */
+	NULL,					  /* reserved */
+	"dnf_of", "upf_uf", "rds_dnf_uf",	  /* 8-10 */
+	NULL,					  /* reserved */
+	"dn_sync", "up_sync", "rds_dn_sync",	  /* 12-14 */
+	NULL,					  /* reserved */
+	"opc_err", "par_err", "rip_err",	  /* 16-18 */
+	"pci_abort", "ber_irq", "mchg_irq"	  /* 19-21 */
+};
+
+/*
+ * BOARD Specific: Threats IRQ audio specific calls
+ */
+static void cx8801_aud_irq(snd_cx88_card_t *chip)
+{
+	struct cx88_core *core = chip->core;
+	u32 status, mask;
+
+	status = cx_read(MO_AUD_INTSTAT);
+	mask   = cx_read(MO_AUD_INTMSK);
+	if (0 == (status & mask))
+		return;
+	cx_write(MO_AUD_INTSTAT, status);
+	if (debug > 1  ||  (status & mask & ~0xff))
+		cx88_print_irqbits(core->name, "irq aud",
+				   cx88_aud_irqs, ARRAY_SIZE(cx88_aud_irqs),
+				   status, mask);
+	/* risc op code error */
+	if (status & AUD_INT_OPC_ERR) {
+		printk(KERN_WARNING "%s/1: Audio risc op code error\n",core->name);
+		cx_clear(MO_AUD_DMACNTRL, 0x11);
+		cx88_sram_channel_dump(core, &cx88_sram_channels[SRAM_CH25]);
+	}
+	if (status & AUD_INT_DN_SYNC) {
+		dprintk(1, "Downstream sync error\n");
+		cx_write(MO_AUDD_GPCNTRL, GP_COUNT_CONTROL_RESET);
+		return;
+	}
+	/* risc1 downstream */
+	if (status & AUD_INT_DN_RISCI1) {
+		atomic_set(&chip->count, cx_read(MO_AUDD_GPCNT));
+		snd_pcm_period_elapsed(chip->substream);
+	}
+	/* FIXME: Any other status should deserve a special handling? */
+}
+
+/*
+ * BOARD Specific: Handles IRQ calls
+ */
+static irqreturn_t cx8801_irq(int irq, void *dev_id)
+{
+	snd_cx88_card_t *chip = dev_id;
+	struct cx88_core *core = chip->core;
+	u32 status;
+	int loop, handled = 0;
+
+	for (loop = 0; loop < MAX_IRQ_LOOP; loop++) {
+		status = cx_read(MO_PCI_INTSTAT) &
+			(core->pci_irqmask | PCI_INT_AUDINT);
+		if (0 == status)
+			goto out;
+		dprintk(3, "cx8801_irq loop %d/%d, status %x\n",
+			loop, MAX_IRQ_LOOP, status);
+		handled = 1;
+		cx_write(MO_PCI_INTSTAT, status);
+
+		if (status & core->pci_irqmask)
+			cx88_core_irq(core, status);
+		if (status & PCI_INT_AUDINT)
+			cx8801_aud_irq(chip);
+	}
+
+	if (MAX_IRQ_LOOP == loop) {
+		printk(KERN_ERR
+		       "%s/1: IRQ loop detected, disabling interrupts\n",
+		       core->name);
+		cx_clear(MO_PCI_INTMSK, PCI_INT_AUDINT);
+	}
+
+ out:
+	return IRQ_RETVAL(handled);
+}
+
+
+static int dsp_buffer_free(snd_cx88_card_t *chip)
+{
+	BUG_ON(!chip->dma_size);
+
+	dprintk(2,"Freeing buffer\n");
+	videobuf_dma_unmap(&chip->pci->dev, chip->dma_risc);
+	videobuf_dma_free(chip->dma_risc);
+	btcx_riscmem_free(chip->pci,&chip->buf->risc);
+	kfree(chip->buf);
+
+	chip->dma_risc = NULL;
+	chip->dma_size = 0;
+
+	return 0;
+}
+
+/****************************************************************************
+				ALSA PCM Interface
+ ****************************************************************************/
+
+/*
+ * Digital hardware definition
+ */
+#define DEFAULT_FIFO_SIZE	4096
+static const struct snd_pcm_hardware snd_cx88_digital_hw = {
+	.info = SNDRV_PCM_INFO_MMAP |
+		SNDRV_PCM_INFO_INTERLEAVED |
+		SNDRV_PCM_INFO_BLOCK_TRANSFER |
+		SNDRV_PCM_INFO_MMAP_VALID,
+	.formats = SNDRV_PCM_FMTBIT_S16_LE,
+
+	.rates =		SNDRV_PCM_RATE_48000,
+	.rate_min =		48000,
+	.rate_max =		48000,
+	.channels_min = 2,
+	.channels_max = 2,
+	/* Analog audio output will be full of clicks and pops if there
+	   are not exactly four lines in the SRAM FIFO buffer.  */
+	.period_bytes_min = DEFAULT_FIFO_SIZE/4,
+	.period_bytes_max = DEFAULT_FIFO_SIZE/4,
+	.periods_min = 1,
+	.periods_max = 1024,
+	.buffer_bytes_max = (1024*1024),
+};
+
+/*
+ * audio pcm capture open callback
+ */
+static int snd_cx88_pcm_open(struct snd_pcm_substream *substream)
+{
+	snd_cx88_card_t *chip = snd_pcm_substream_chip(substream);
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	int err;
+
+	if (!chip) {
+		printk(KERN_ERR "BUG: cx88 can't find device struct."
+				" Can't proceed with open\n");
+		return -ENODEV;
+	}
+
+	err = snd_pcm_hw_constraint_pow2(runtime, 0, SNDRV_PCM_HW_PARAM_PERIODS);
+	if (err < 0)
+		goto _error;
+
+	chip->substream = substream;
+
+	runtime->hw = snd_cx88_digital_hw;
+
+	if (cx88_sram_channels[SRAM_CH25].fifo_size != DEFAULT_FIFO_SIZE) {
+		unsigned int bpl = cx88_sram_channels[SRAM_CH25].fifo_size / 4;
+		bpl &= ~7; /* must be multiple of 8 */
+		runtime->hw.period_bytes_min = bpl;
+		runtime->hw.period_bytes_max = bpl;
+	}
+
+	return 0;
+_error:
+	dprintk(1,"Error opening PCM!\n");
+	return err;
+}
+
+/*
+ * audio close callback
+ */
+static int snd_cx88_close(struct snd_pcm_substream *substream)
+{
+	return 0;
+}
+
+/*
+ * hw_params callback
+ */
+static int snd_cx88_hw_params(struct snd_pcm_substream * substream,
+			      struct snd_pcm_hw_params * hw_params)
+{
+	snd_cx88_card_t *chip = snd_pcm_substream_chip(substream);
+	struct videobuf_dmabuf *dma;
+
+	struct cx88_audio_buffer *buf;
+	int ret;
+
+	if (substream->runtime->dma_area) {
+		dsp_buffer_free(chip);
+		substream->runtime->dma_area = NULL;
+	}
+
+	chip->period_size = params_period_bytes(hw_params);
+	chip->num_periods = params_periods(hw_params);
+	chip->dma_size = chip->period_size * params_periods(hw_params);
+
+	BUG_ON(!chip->dma_size);
+	BUG_ON(chip->num_periods & (chip->num_periods-1));
+
+	buf = kzalloc(sizeof(*buf), GFP_KERNEL);
+	if (NULL == buf)
+		return -ENOMEM;
+
+	buf->bpl = chip->period_size;
+
+	dma = &buf->dma;
+	videobuf_dma_init(dma);
+	ret = videobuf_dma_init_kernel(dma, PCI_DMA_FROMDEVICE,
+			(PAGE_ALIGN(chip->dma_size) >> PAGE_SHIFT));
+	if (ret < 0)
+		goto error;
+
+	ret = videobuf_dma_map(&chip->pci->dev, dma);
+	if (ret < 0)
+		goto error;
+
+	ret = cx88_risc_databuffer(chip->pci, &buf->risc, dma->sglist,
+				   chip->period_size, chip->num_periods, 1);
+	if (ret < 0)
+		goto error;
+
+	/* Loop back to start of program */
+	buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP|RISC_IRQ1|RISC_CNT_INC);
+	buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+
+	chip->buf = buf;
+	chip->dma_risc = dma;
+
+	substream->runtime->dma_area = chip->dma_risc->vaddr;
+	substream->runtime->dma_bytes = chip->dma_size;
+	substream->runtime->dma_addr = 0;
+	return 0;
+
+error:
+	kfree(buf);
+	return ret;
+}
+
+/*
+ * hw free callback
+ */
+static int snd_cx88_hw_free(struct snd_pcm_substream * substream)
+{
+
+	snd_cx88_card_t *chip = snd_pcm_substream_chip(substream);
+
+	if (substream->runtime->dma_area) {
+		dsp_buffer_free(chip);
+		substream->runtime->dma_area = NULL;
+	}
+
+	return 0;
+}
+
+/*
+ * prepare callback
+ */
+static int snd_cx88_prepare(struct snd_pcm_substream *substream)
+{
+	return 0;
+}
+
+/*
+ * trigger callback
+ */
+static int snd_cx88_card_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+	snd_cx88_card_t *chip = snd_pcm_substream_chip(substream);
+	int err;
+
+	/* Local interrupts are already disabled by ALSA */
+	spin_lock(&chip->reg_lock);
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+		err=_cx88_start_audio_dma(chip);
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+		err=_cx88_stop_audio_dma(chip);
+		break;
+	default:
+		err=-EINVAL;
+		break;
+	}
+
+	spin_unlock(&chip->reg_lock);
+
+	return err;
+}
+
+/*
+ * pointer callback
+ */
+static snd_pcm_uframes_t snd_cx88_pointer(struct snd_pcm_substream *substream)
+{
+	snd_cx88_card_t *chip = snd_pcm_substream_chip(substream);
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	u16 count;
+
+	count = atomic_read(&chip->count);
+
+//	dprintk(2, "%s - count %d (+%u), period %d, frame %lu\n", __func__,
+//		count, new, count & (runtime->periods-1),
+//		runtime->period_size * (count & (runtime->periods-1)));
+	return runtime->period_size * (count & (runtime->periods-1));
+}
+
+/*
+ * page callback (needed for mmap)
+ */
+static struct page *snd_cx88_page(struct snd_pcm_substream *substream,
+				unsigned long offset)
+{
+	void *pageptr = substream->runtime->dma_area + offset;
+	return vmalloc_to_page(pageptr);
+}
+
+/*
+ * operators
+ */
+static struct snd_pcm_ops snd_cx88_pcm_ops = {
+	.open = snd_cx88_pcm_open,
+	.close = snd_cx88_close,
+	.ioctl = snd_pcm_lib_ioctl,
+	.hw_params = snd_cx88_hw_params,
+	.hw_free = snd_cx88_hw_free,
+	.prepare = snd_cx88_prepare,
+	.trigger = snd_cx88_card_trigger,
+	.pointer = snd_cx88_pointer,
+	.page = snd_cx88_page,
+};
+
+/*
+ * create a PCM device
+ */
+static int __devinit snd_cx88_pcm(snd_cx88_card_t *chip, int device, const char *name)
+{
+	int err;
+	struct snd_pcm *pcm;
+
+	err = snd_pcm_new(chip->card, name, device, 0, 1, &pcm);
+	if (err < 0)
+		return err;
+	pcm->private_data = chip;
+	strcpy(pcm->name, name);
+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cx88_pcm_ops);
+
+	return 0;
+}
+
+/****************************************************************************
+				CONTROL INTERFACE
+ ****************************************************************************/
+static int snd_cx88_volume_info(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_info *info)
+{
+	info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	info->count = 2;
+	info->value.integer.min = 0;
+	info->value.integer.max = 0x3f;
+
+	return 0;
+}
+
+static int snd_cx88_volume_get(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *value)
+{
+	snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
+	struct cx88_core *core=chip->core;
+	int vol = 0x3f - (cx_read(AUD_VOL_CTL) & 0x3f),
+	    bal = cx_read(AUD_BAL_CTL);
+
+	value->value.integer.value[(bal & 0x40) ? 0 : 1] = vol;
+	vol -= (bal & 0x3f);
+	value->value.integer.value[(bal & 0x40) ? 1 : 0] = vol < 0 ? 0 : vol;
+
+	return 0;
+}
+
+static void snd_cx88_wm8775_volume_put(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *value)
+{
+	snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
+	struct cx88_core *core = chip->core;
+	int left = value->value.integer.value[0];
+	int right = value->value.integer.value[1];
+	int v, b;
+
+	/* Pass volume & balance onto any WM8775 */
+	if (left >= right) {
+		v = left << 10;
+		b = left ? (0x8000 * right) / left : 0x8000;
+	} else {
+		v = right << 10;
+		b = right ? 0xffff - (0x8000 * left) / right : 0x8000;
+	}
+	wm8775_s_ctrl(core, V4L2_CID_AUDIO_VOLUME, v);
+	wm8775_s_ctrl(core, V4L2_CID_AUDIO_BALANCE, b);
+}
+
+/* OK - TODO: test it */
+static int snd_cx88_volume_put(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *value)
+{
+	snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
+	struct cx88_core *core=chip->core;
+	int left, right, v, b;
+	int changed = 0;
+	u32 old;
+
+	if (core->board.audio_chip == V4L2_IDENT_WM8775)
+		snd_cx88_wm8775_volume_put(kcontrol, value);
+
+	left = value->value.integer.value[0] & 0x3f;
+	right = value->value.integer.value[1] & 0x3f;
+	b = right - left;
+	if (b < 0) {
+		v = 0x3f - left;
+		b = (-b) | 0x40;
+	} else {
+		v = 0x3f - right;
+	}
+	/* Do we really know this will always be called with IRQs on? */
+	spin_lock_irq(&chip->reg_lock);
+	old = cx_read(AUD_VOL_CTL);
+	if (v != (old & 0x3f)) {
+		cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, (old & ~0x3f) | v);
+		changed = 1;
+	}
+	if ((cx_read(AUD_BAL_CTL) & 0x7f) != b) {
+		cx_write(AUD_BAL_CTL, b);
+		changed = 1;
+	}
+	spin_unlock_irq(&chip->reg_lock);
+
+	return changed;
+}
+
+static const DECLARE_TLV_DB_SCALE(snd_cx88_db_scale, -6300, 100, 0);
+
+static const struct snd_kcontrol_new snd_cx88_volume = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
+		  SNDRV_CTL_ELEM_ACCESS_TLV_READ,
+	.name = "Analog-TV Volume",
+	.info = snd_cx88_volume_info,
+	.get = snd_cx88_volume_get,
+	.put = snd_cx88_volume_put,
+	.tlv.p = snd_cx88_db_scale,
+};
+
+static int snd_cx88_switch_get(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *value)
+{
+	snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
+	struct cx88_core *core = chip->core;
+	u32 bit = kcontrol->private_value;
+
+	value->value.integer.value[0] = !(cx_read(AUD_VOL_CTL) & bit);
+	return 0;
+}
+
+static int snd_cx88_switch_put(struct snd_kcontrol *kcontrol,
+				       struct snd_ctl_elem_value *value)
+{
+	snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
+	struct cx88_core *core = chip->core;
+	u32 bit = kcontrol->private_value;
+	int ret = 0;
+	u32 vol;
+
+	spin_lock_irq(&chip->reg_lock);
+	vol = cx_read(AUD_VOL_CTL);
+	if (value->value.integer.value[0] != !(vol & bit)) {
+		vol ^= bit;
+		cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, vol);
+		/* Pass mute onto any WM8775 */
+		if ((core->board.audio_chip == V4L2_IDENT_WM8775) &&
+		    ((1<<6) == bit))
+			wm8775_s_ctrl(core, V4L2_CID_AUDIO_MUTE, 0 != (vol & bit));
+		ret = 1;
+	}
+	spin_unlock_irq(&chip->reg_lock);
+	return ret;
+}
+
+static const struct snd_kcontrol_new snd_cx88_dac_switch = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "Audio-Out Switch",
+	.info = snd_ctl_boolean_mono_info,
+	.get = snd_cx88_switch_get,
+	.put = snd_cx88_switch_put,
+	.private_value = (1<<8),
+};
+
+static const struct snd_kcontrol_new snd_cx88_source_switch = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "Analog-TV Switch",
+	.info = snd_ctl_boolean_mono_info,
+	.get = snd_cx88_switch_get,
+	.put = snd_cx88_switch_put,
+	.private_value = (1<<6),
+};
+
+static int snd_cx88_alc_get(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *value)
+{
+	snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
+	struct cx88_core *core = chip->core;
+	s32 val;
+
+	val = wm8775_g_ctrl(core, V4L2_CID_AUDIO_LOUDNESS);
+	value->value.integer.value[0] = val ? 1 : 0;
+	return 0;
+}
+
+static int snd_cx88_alc_put(struct snd_kcontrol *kcontrol,
+				       struct snd_ctl_elem_value *value)
+{
+	snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
+	struct cx88_core *core = chip->core;
+	struct v4l2_control client_ctl;
+
+	memset(&client_ctl, 0, sizeof(client_ctl));
+	client_ctl.value = 0 != value->value.integer.value[0];
+	client_ctl.id = V4L2_CID_AUDIO_LOUDNESS;
+	call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl);
+
+	return 0;
+}
+
+static struct snd_kcontrol_new snd_cx88_alc_switch = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "Line-In ALC Switch",
+	.info = snd_ctl_boolean_mono_info,
+	.get = snd_cx88_alc_get,
+	.put = snd_cx88_alc_put,
+};
+
+/****************************************************************************
+			Basic Flow for Sound Devices
+ ****************************************************************************/
+
+/*
+ * PCI ID Table - 14f1:8801 and 14f1:8811 means function 1: Audio
+ * Only boards with eeprom and byte 1 at eeprom=1 have it
+ */
+
+static const struct pci_device_id cx88_audio_pci_tbl[] __devinitdata = {
+	{0x14f1,0x8801,PCI_ANY_ID,PCI_ANY_ID,0,0,0},
+	{0x14f1,0x8811,PCI_ANY_ID,PCI_ANY_ID,0,0,0},
+	{0, }
+};
+MODULE_DEVICE_TABLE(pci, cx88_audio_pci_tbl);
+
+/*
+ * Chip-specific destructor
+ */
+
+static int snd_cx88_free(snd_cx88_card_t *chip)
+{
+
+	if (chip->irq >= 0)
+		free_irq(chip->irq, chip);
+
+	cx88_core_put(chip->core,chip->pci);
+
+	pci_disable_device(chip->pci);
+	return 0;
+}
+
+/*
+ * Component Destructor
+ */
+static void snd_cx88_dev_free(struct snd_card * card)
+{
+	snd_cx88_card_t *chip = card->private_data;
+
+	snd_cx88_free(chip);
+}
+
+
+/*
+ * Alsa Constructor - Component probe
+ */
+
+static int devno;
+static int __devinit snd_cx88_create(struct snd_card *card,
+				     struct pci_dev *pci,
+				     snd_cx88_card_t **rchip,
+				     struct cx88_core **core_ptr)
+{
+	snd_cx88_card_t   *chip;
+	struct cx88_core  *core;
+	int               err;
+	unsigned char     pci_lat;
+
+	*rchip = NULL;
+
+	err = pci_enable_device(pci);
+	if (err < 0)
+		return err;
+
+	pci_set_master(pci);
+
+	chip = card->private_data;
+
+	core = cx88_core_get(pci);
+	if (NULL == core) {
+		err = -EINVAL;
+		return err;
+	}
+
+	if (!pci_dma_supported(pci,DMA_BIT_MASK(32))) {
+		dprintk(0, "%s/1: Oops: no 32bit PCI DMA ???\n",core->name);
+		err = -EIO;
+		cx88_core_put(core, pci);
+		return err;
+	}
+
+
+	/* pci init */
+	chip->card = card;
+	chip->pci = pci;
+	chip->irq = -1;
+	spin_lock_init(&chip->reg_lock);
+
+	chip->core = core;
+
+	/* get irq */
+	err = request_irq(chip->pci->irq, cx8801_irq,
+			  IRQF_SHARED | IRQF_DISABLED, chip->core->name, chip);
+	if (err < 0) {
+		dprintk(0, "%s: can't get IRQ %d\n",
+		       chip->core->name, chip->pci->irq);
+		return err;
+	}
+
+	/* print pci info */
+	pci_read_config_byte(pci, PCI_LATENCY_TIMER, &pci_lat);
+
+	dprintk(1,"ALSA %s/%i: found at %s, rev: %d, irq: %d, "
+	       "latency: %d, mmio: 0x%llx\n", core->name, devno,
+	       pci_name(pci), pci->revision, pci->irq,
+	       pci_lat, (unsigned long long)pci_resource_start(pci,0));
+
+	chip->irq = pci->irq;
+	synchronize_irq(chip->irq);
+
+	snd_card_set_dev(card, &pci->dev);
+
+	*rchip = chip;
+	*core_ptr = core;
+
+	return 0;
+}
+
+static int __devinit cx88_audio_initdev(struct pci_dev *pci,
+				    const struct pci_device_id *pci_id)
+{
+	struct snd_card  *card;
+	snd_cx88_card_t  *chip;
+	struct cx88_core *core = NULL;
+	int              err;
+
+	if (devno >= SNDRV_CARDS)
+		return (-ENODEV);
+
+	if (!enable[devno]) {
+		++devno;
+		return (-ENOENT);
+	}
+
+	err = snd_card_create(index[devno], id[devno], THIS_MODULE,
+			      sizeof(snd_cx88_card_t), &card);
+	if (err < 0)
+		return err;
+
+	card->private_free = snd_cx88_dev_free;
+
+	err = snd_cx88_create(card, pci, &chip, &core);
+	if (err < 0)
+		goto error;
+
+	err = snd_cx88_pcm(chip, 0, "CX88 Digital");
+	if (err < 0)
+		goto error;
+
+	err = snd_ctl_add(card, snd_ctl_new1(&snd_cx88_volume, chip));
+	if (err < 0)
+		goto error;
+	err = snd_ctl_add(card, snd_ctl_new1(&snd_cx88_dac_switch, chip));
+	if (err < 0)
+		goto error;
+	err = snd_ctl_add(card, snd_ctl_new1(&snd_cx88_source_switch, chip));
+	if (err < 0)
+		goto error;
+
+	/* If there's a wm8775 then add a Line-In ALC switch */
+	if (core->board.audio_chip == V4L2_IDENT_WM8775)
+		snd_ctl_add(card, snd_ctl_new1(&snd_cx88_alc_switch, chip));
+
+	strcpy (card->driver, "CX88x");
+	sprintf(card->shortname, "Conexant CX%x", pci->device);
+	sprintf(card->longname, "%s at %#llx",
+		card->shortname,(unsigned long long)pci_resource_start(pci, 0));
+	strcpy (card->mixername, "CX88");
+
+	dprintk (0, "%s/%i: ALSA support for cx2388x boards\n",
+	       card->driver,devno);
+
+	err = snd_card_register(card);
+	if (err < 0)
+		goto error;
+	pci_set_drvdata(pci,card);
+
+	devno++;
+	return 0;
+
+error:
+	snd_card_free(card);
+	return err;
+}
+/*
+ * ALSA destructor
+ */
+static void __devexit cx88_audio_finidev(struct pci_dev *pci)
+{
+	struct cx88_audio_dev *card = pci_get_drvdata(pci);
+
+	snd_card_free((void *)card);
+
+	pci_set_drvdata(pci, NULL);
+
+	devno--;
+}
+
+/*
+ * PCI driver definition
+ */
+
+static struct pci_driver cx88_audio_pci_driver = {
+	.name     = "cx88_audio",
+	.id_table = cx88_audio_pci_tbl,
+	.probe    = cx88_audio_initdev,
+	.remove   = __devexit_p(cx88_audio_finidev),
+};
+
+/****************************************************************************
+				LINUX MODULE INIT
+ ****************************************************************************/
+
+/*
+ * module init
+ */
+static int __init cx88_audio_init(void)
+{
+	printk(KERN_INFO "cx2388x alsa driver version %s loaded\n",
+	       CX88_VERSION);
+	return pci_register_driver(&cx88_audio_pci_driver);
+}
+
+/*
+ * module remove
+ */
+static void __exit cx88_audio_fini(void)
+{
+	pci_unregister_driver(&cx88_audio_pci_driver);
+}
+
+module_init(cx88_audio_init);
+module_exit(cx88_audio_fini);
diff --git a/drivers/media/pci/cx88/cx88-blackbird.c b/drivers/media/pci/cx88/cx88-blackbird.c
new file mode 100644
index 0000000..843ffd9
--- /dev/null
+++ b/drivers/media/pci/cx88/cx88-blackbird.c
@@ -0,0 +1,1299 @@
+/*
+ *
+ *  Support for a cx23416 mpeg encoder via cx2388x host port.
+ *  "blackbird" reference design.
+ *
+ *    (c) 2004 Jelle Foks <jelle@foks.us>
+ *    (c) 2004 Gerd Knorr <kraxel@bytesex.org>
+ *
+ *    (c) 2005-2006 Mauro Carvalho Chehab <mchehab@infradead.org>
+ *        - video_ioctl2 conversion
+ *
+ *  Includes parts from the ivtv driver <http://sourceforge.net/projects/ivtv/>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the 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/init.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/firmware.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-event.h>
+#include <media/cx2341x.h>
+
+#include "cx88.h"
+
+MODULE_DESCRIPTION("driver for cx2388x/cx23416 based mpeg encoder cards");
+MODULE_AUTHOR("Jelle Foks <jelle@foks.us>, Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(CX88_VERSION);
+
+static unsigned int mpegbufs = 32;
+module_param(mpegbufs,int,0644);
+MODULE_PARM_DESC(mpegbufs,"number of mpeg buffers, range 2-32");
+
+static unsigned int debug;
+module_param(debug,int,0644);
+MODULE_PARM_DESC(debug,"enable debug messages [blackbird]");
+
+#define dprintk(level,fmt, arg...)	if (debug >= level) \
+	printk(KERN_DEBUG "%s/2-bb: " fmt, dev->core->name , ## arg)
+
+
+/* ------------------------------------------------------------------ */
+
+#define BLACKBIRD_FIRM_IMAGE_SIZE 376836
+
+/* defines below are from ivtv-driver.h */
+
+#define IVTV_CMD_HW_BLOCKS_RST 0xFFFFFFFF
+
+/* Firmware API commands */
+#define IVTV_API_STD_TIMEOUT 500
+
+enum blackbird_capture_type {
+	BLACKBIRD_MPEG_CAPTURE,
+	BLACKBIRD_RAW_CAPTURE,
+	BLACKBIRD_RAW_PASSTHRU_CAPTURE
+};
+enum blackbird_capture_bits {
+	BLACKBIRD_RAW_BITS_NONE             = 0x00,
+	BLACKBIRD_RAW_BITS_YUV_CAPTURE      = 0x01,
+	BLACKBIRD_RAW_BITS_PCM_CAPTURE      = 0x02,
+	BLACKBIRD_RAW_BITS_VBI_CAPTURE      = 0x04,
+	BLACKBIRD_RAW_BITS_PASSTHRU_CAPTURE = 0x08,
+	BLACKBIRD_RAW_BITS_TO_HOST_CAPTURE  = 0x10
+};
+enum blackbird_capture_end {
+	BLACKBIRD_END_AT_GOP, /* stop at the end of gop, generate irq */
+	BLACKBIRD_END_NOW, /* stop immediately, no irq */
+};
+enum blackbird_framerate {
+	BLACKBIRD_FRAMERATE_NTSC_30, /* NTSC: 30fps */
+	BLACKBIRD_FRAMERATE_PAL_25   /* PAL: 25fps */
+};
+enum blackbird_stream_port {
+	BLACKBIRD_OUTPUT_PORT_MEMORY,
+	BLACKBIRD_OUTPUT_PORT_STREAMING,
+	BLACKBIRD_OUTPUT_PORT_SERIAL
+};
+enum blackbird_data_xfer_status {
+	BLACKBIRD_MORE_BUFFERS_FOLLOW,
+	BLACKBIRD_LAST_BUFFER,
+};
+enum blackbird_picture_mask {
+	BLACKBIRD_PICTURE_MASK_NONE,
+	BLACKBIRD_PICTURE_MASK_I_FRAMES,
+	BLACKBIRD_PICTURE_MASK_I_P_FRAMES = 0x3,
+	BLACKBIRD_PICTURE_MASK_ALL_FRAMES = 0x7,
+};
+enum blackbird_vbi_mode_bits {
+	BLACKBIRD_VBI_BITS_SLICED,
+	BLACKBIRD_VBI_BITS_RAW,
+};
+enum blackbird_vbi_insertion_bits {
+	BLACKBIRD_VBI_BITS_INSERT_IN_XTENSION_USR_DATA,
+	BLACKBIRD_VBI_BITS_INSERT_IN_PRIVATE_PACKETS = 0x1 << 1,
+	BLACKBIRD_VBI_BITS_SEPARATE_STREAM = 0x2 << 1,
+	BLACKBIRD_VBI_BITS_SEPARATE_STREAM_USR_DATA = 0x4 << 1,
+	BLACKBIRD_VBI_BITS_SEPARATE_STREAM_PRV_DATA = 0x5 << 1,
+};
+enum blackbird_dma_unit {
+	BLACKBIRD_DMA_BYTES,
+	BLACKBIRD_DMA_FRAMES,
+};
+enum blackbird_dma_transfer_status_bits {
+	BLACKBIRD_DMA_TRANSFER_BITS_DONE = 0x01,
+	BLACKBIRD_DMA_TRANSFER_BITS_ERROR = 0x04,
+	BLACKBIRD_DMA_TRANSFER_BITS_LL_ERROR = 0x10,
+};
+enum blackbird_pause {
+	BLACKBIRD_PAUSE_ENCODING,
+	BLACKBIRD_RESUME_ENCODING,
+};
+enum blackbird_copyright {
+	BLACKBIRD_COPYRIGHT_OFF,
+	BLACKBIRD_COPYRIGHT_ON,
+};
+enum blackbird_notification_type {
+	BLACKBIRD_NOTIFICATION_REFRESH,
+};
+enum blackbird_notification_status {
+	BLACKBIRD_NOTIFICATION_OFF,
+	BLACKBIRD_NOTIFICATION_ON,
+};
+enum blackbird_notification_mailbox {
+	BLACKBIRD_NOTIFICATION_NO_MAILBOX = -1,
+};
+enum blackbird_field1_lines {
+	BLACKBIRD_FIELD1_SAA7114 = 0x00EF, /* 239 */
+	BLACKBIRD_FIELD1_SAA7115 = 0x00F0, /* 240 */
+	BLACKBIRD_FIELD1_MICRONAS = 0x0105, /* 261 */
+};
+enum blackbird_field2_lines {
+	BLACKBIRD_FIELD2_SAA7114 = 0x00EF, /* 239 */
+	BLACKBIRD_FIELD2_SAA7115 = 0x00F0, /* 240 */
+	BLACKBIRD_FIELD2_MICRONAS = 0x0106, /* 262 */
+};
+enum blackbird_custom_data_type {
+	BLACKBIRD_CUSTOM_EXTENSION_USR_DATA,
+	BLACKBIRD_CUSTOM_PRIVATE_PACKET,
+};
+enum blackbird_mute {
+	BLACKBIRD_UNMUTE,
+	BLACKBIRD_MUTE,
+};
+enum blackbird_mute_video_mask {
+	BLACKBIRD_MUTE_VIDEO_V_MASK = 0x0000FF00,
+	BLACKBIRD_MUTE_VIDEO_U_MASK = 0x00FF0000,
+	BLACKBIRD_MUTE_VIDEO_Y_MASK = 0xFF000000,
+};
+enum blackbird_mute_video_shift {
+	BLACKBIRD_MUTE_VIDEO_V_SHIFT = 8,
+	BLACKBIRD_MUTE_VIDEO_U_SHIFT = 16,
+	BLACKBIRD_MUTE_VIDEO_Y_SHIFT = 24,
+};
+
+/* Registers */
+#define IVTV_REG_ENC_SDRAM_REFRESH (0x07F8 /*| IVTV_REG_OFFSET*/)
+#define IVTV_REG_ENC_SDRAM_PRECHARGE (0x07FC /*| IVTV_REG_OFFSET*/)
+#define IVTV_REG_SPU (0x9050 /*| IVTV_REG_OFFSET*/)
+#define IVTV_REG_HW_BLOCKS (0x9054 /*| IVTV_REG_OFFSET*/)
+#define IVTV_REG_VPU (0x9058 /*| IVTV_REG_OFFSET*/)
+#define IVTV_REG_APU (0xA064 /*| IVTV_REG_OFFSET*/)
+
+/* ------------------------------------------------------------------ */
+
+static void host_setup(struct cx88_core *core)
+{
+	/* toggle reset of the host */
+	cx_write(MO_GPHST_SOFT_RST, 1);
+	udelay(100);
+	cx_write(MO_GPHST_SOFT_RST, 0);
+	udelay(100);
+
+	/* host port setup */
+	cx_write(MO_GPHST_WSC, 0x44444444U);
+	cx_write(MO_GPHST_XFR, 0);
+	cx_write(MO_GPHST_WDTH, 15);
+	cx_write(MO_GPHST_HDSHK, 0);
+	cx_write(MO_GPHST_MUX16, 0x44448888U);
+	cx_write(MO_GPHST_MODE, 0);
+}
+
+/* ------------------------------------------------------------------ */
+
+#define P1_MDATA0 0x390000
+#define P1_MDATA1 0x390001
+#define P1_MDATA2 0x390002
+#define P1_MDATA3 0x390003
+#define P1_MADDR2 0x390004
+#define P1_MADDR1 0x390005
+#define P1_MADDR0 0x390006
+#define P1_RDATA0 0x390008
+#define P1_RDATA1 0x390009
+#define P1_RDATA2 0x39000A
+#define P1_RDATA3 0x39000B
+#define P1_RADDR0 0x39000C
+#define P1_RADDR1 0x39000D
+#define P1_RRDWR  0x39000E
+
+static int wait_ready_gpio0_bit1(struct cx88_core *core, u32 state)
+{
+	unsigned long timeout = jiffies + msecs_to_jiffies(1);
+	u32 gpio0,need;
+
+	need = state ? 2 : 0;
+	for (;;) {
+		gpio0 = cx_read(MO_GP0_IO) & 2;
+		if (need == gpio0)
+			return 0;
+		if (time_after(jiffies,timeout))
+			return -1;
+		udelay(1);
+	}
+}
+
+static int memory_write(struct cx88_core *core, u32 address, u32 value)
+{
+	/* Warning: address is dword address (4 bytes) */
+	cx_writeb(P1_MDATA0, (unsigned int)value);
+	cx_writeb(P1_MDATA1, (unsigned int)(value >> 8));
+	cx_writeb(P1_MDATA2, (unsigned int)(value >> 16));
+	cx_writeb(P1_MDATA3, (unsigned int)(value >> 24));
+	cx_writeb(P1_MADDR2, (unsigned int)(address >> 16) | 0x40);
+	cx_writeb(P1_MADDR1, (unsigned int)(address >> 8));
+	cx_writeb(P1_MADDR0, (unsigned int)address);
+	cx_read(P1_MDATA0);
+	cx_read(P1_MADDR0);
+
+	return wait_ready_gpio0_bit1(core,1);
+}
+
+static int memory_read(struct cx88_core *core, u32 address, u32 *value)
+{
+	int retval;
+	u32 val;
+
+	/* Warning: address is dword address (4 bytes) */
+	cx_writeb(P1_MADDR2, (unsigned int)(address >> 16) & ~0xC0);
+	cx_writeb(P1_MADDR1, (unsigned int)(address >> 8));
+	cx_writeb(P1_MADDR0, (unsigned int)address);
+	cx_read(P1_MADDR0);
+
+	retval = wait_ready_gpio0_bit1(core,1);
+
+	cx_writeb(P1_MDATA3, 0);
+	val     = (unsigned char)cx_read(P1_MDATA3) << 24;
+	cx_writeb(P1_MDATA2, 0);
+	val    |= (unsigned char)cx_read(P1_MDATA2) << 16;
+	cx_writeb(P1_MDATA1, 0);
+	val    |= (unsigned char)cx_read(P1_MDATA1) << 8;
+	cx_writeb(P1_MDATA0, 0);
+	val    |= (unsigned char)cx_read(P1_MDATA0);
+
+	*value  = val;
+	return retval;
+}
+
+static int register_write(struct cx88_core *core, u32 address, u32 value)
+{
+	cx_writeb(P1_RDATA0, (unsigned int)value);
+	cx_writeb(P1_RDATA1, (unsigned int)(value >> 8));
+	cx_writeb(P1_RDATA2, (unsigned int)(value >> 16));
+	cx_writeb(P1_RDATA3, (unsigned int)(value >> 24));
+	cx_writeb(P1_RADDR0, (unsigned int)address);
+	cx_writeb(P1_RADDR1, (unsigned int)(address >> 8));
+	cx_writeb(P1_RRDWR, 1);
+	cx_read(P1_RDATA0);
+	cx_read(P1_RADDR0);
+
+	return wait_ready_gpio0_bit1(core,1);
+}
+
+
+static int register_read(struct cx88_core *core, u32 address, u32 *value)
+{
+	int retval;
+	u32 val;
+
+	cx_writeb(P1_RADDR0, (unsigned int)address);
+	cx_writeb(P1_RADDR1, (unsigned int)(address >> 8));
+	cx_writeb(P1_RRDWR, 0);
+	cx_read(P1_RADDR0);
+
+	retval  = wait_ready_gpio0_bit1(core,1);
+	val     = (unsigned char)cx_read(P1_RDATA0);
+	val    |= (unsigned char)cx_read(P1_RDATA1) << 8;
+	val    |= (unsigned char)cx_read(P1_RDATA2) << 16;
+	val    |= (unsigned char)cx_read(P1_RDATA3) << 24;
+
+	*value  = val;
+	return retval;
+}
+
+/* ------------------------------------------------------------------ */
+
+static int blackbird_mbox_func(void *priv, u32 command, int in, int out, u32 data[CX2341X_MBOX_MAX_DATA])
+{
+	struct cx8802_dev *dev = priv;
+	unsigned long timeout;
+	u32 value, flag, retval;
+	int i;
+
+	dprintk(1,"%s: 0x%X\n", __func__, command);
+
+	/* this may not be 100% safe if we can't read any memory location
+	   without side effects */
+	memory_read(dev->core, dev->mailbox - 4, &value);
+	if (value != 0x12345678) {
+		dprintk(0, "Firmware and/or mailbox pointer not initialized or corrupted\n");
+		return -1;
+	}
+
+	memory_read(dev->core, dev->mailbox, &flag);
+	if (flag) {
+		dprintk(0, "ERROR: Mailbox appears to be in use (%x)\n", flag);
+		return -1;
+	}
+
+	flag |= 1; /* tell 'em we're working on it */
+	memory_write(dev->core, dev->mailbox, flag);
+
+	/* write command + args + fill remaining with zeros */
+	memory_write(dev->core, dev->mailbox + 1, command); /* command code */
+	memory_write(dev->core, dev->mailbox + 3, IVTV_API_STD_TIMEOUT); /* timeout */
+	for (i = 0; i < in; i++) {
+		memory_write(dev->core, dev->mailbox + 4 + i, data[i]);
+		dprintk(1, "API Input %d = %d\n", i, data[i]);
+	}
+	for (; i < CX2341X_MBOX_MAX_DATA; i++)
+		memory_write(dev->core, dev->mailbox + 4 + i, 0);
+
+	flag |= 3; /* tell 'em we're done writing */
+	memory_write(dev->core, dev->mailbox, flag);
+
+	/* wait for firmware to handle the API command */
+	timeout = jiffies + msecs_to_jiffies(10);
+	for (;;) {
+		memory_read(dev->core, dev->mailbox, &flag);
+		if (0 != (flag & 4))
+			break;
+		if (time_after(jiffies,timeout)) {
+			dprintk(0, "ERROR: API Mailbox timeout\n");
+			return -1;
+		}
+		udelay(10);
+	}
+
+	/* read output values */
+	for (i = 0; i < out; i++) {
+		memory_read(dev->core, dev->mailbox + 4 + i, data + i);
+		dprintk(1, "API Output %d = %d\n", i, data[i]);
+	}
+
+	memory_read(dev->core, dev->mailbox + 2, &retval);
+	dprintk(1, "API result = %d\n",retval);
+
+	flag = 0;
+	memory_write(dev->core, dev->mailbox, flag);
+	return retval;
+}
+/* ------------------------------------------------------------------ */
+
+/* We don't need to call the API often, so using just one mailbox will probably suffice */
+static int blackbird_api_cmd(struct cx8802_dev *dev, u32 command,
+			     u32 inputcnt, u32 outputcnt, ...)
+{
+	u32 data[CX2341X_MBOX_MAX_DATA];
+	va_list vargs;
+	int i, err;
+
+	va_start(vargs, outputcnt);
+
+	for (i = 0; i < inputcnt; i++) {
+		data[i] = va_arg(vargs, int);
+	}
+	err = blackbird_mbox_func(dev, command, inputcnt, outputcnt, data);
+	for (i = 0; i < outputcnt; i++) {
+		int *vptr = va_arg(vargs, int *);
+		*vptr = data[i];
+	}
+	va_end(vargs);
+	return err;
+}
+
+static int blackbird_find_mailbox(struct cx8802_dev *dev)
+{
+	u32 signature[4]={0x12345678, 0x34567812, 0x56781234, 0x78123456};
+	int signaturecnt=0;
+	u32 value;
+	int i;
+
+	for (i = 0; i < BLACKBIRD_FIRM_IMAGE_SIZE; i++) {
+		memory_read(dev->core, i, &value);
+		if (value == signature[signaturecnt])
+			signaturecnt++;
+		else
+			signaturecnt = 0;
+		if (4 == signaturecnt) {
+			dprintk(1, "Mailbox signature found\n");
+			return i+1;
+		}
+	}
+	dprintk(0, "Mailbox signature values not found!\n");
+	return -1;
+}
+
+static int blackbird_load_firmware(struct cx8802_dev *dev)
+{
+	static const unsigned char magic[8] = {
+		0xa7, 0x0d, 0x00, 0x00, 0x66, 0xbb, 0x55, 0xaa
+	};
+	const struct firmware *firmware;
+	int i, retval = 0;
+	u32 value = 0;
+	u32 checksum = 0;
+	u32 *dataptr;
+
+	retval  = register_write(dev->core, IVTV_REG_VPU, 0xFFFFFFED);
+	retval |= register_write(dev->core, IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST);
+	retval |= register_write(dev->core, IVTV_REG_ENC_SDRAM_REFRESH, 0x80000640);
+	retval |= register_write(dev->core, IVTV_REG_ENC_SDRAM_PRECHARGE, 0x1A);
+	msleep(1);
+	retval |= register_write(dev->core, IVTV_REG_APU, 0);
+
+	if (retval < 0)
+		dprintk(0, "Error with register_write\n");
+
+	retval = request_firmware(&firmware, CX2341X_FIRM_ENC_FILENAME,
+				  &dev->pci->dev);
+
+
+	if (retval != 0) {
+		dprintk(0, "ERROR: Hotplug firmware request failed (%s).\n",
+			CX2341X_FIRM_ENC_FILENAME);
+		dprintk(0, "Please fix your hotplug setup, the board will "
+			"not work without firmware loaded!\n");
+		return -1;
+	}
+
+	if (firmware->size != BLACKBIRD_FIRM_IMAGE_SIZE) {
+		dprintk(0, "ERROR: Firmware size mismatch (have %zd, expected %d)\n",
+			firmware->size, BLACKBIRD_FIRM_IMAGE_SIZE);
+		release_firmware(firmware);
+		return -1;
+	}
+
+	if (0 != memcmp(firmware->data, magic, 8)) {
+		dprintk(0, "ERROR: Firmware magic mismatch, wrong file?\n");
+		release_firmware(firmware);
+		return -1;
+	}
+
+	/* transfer to the chip */
+	dprintk(1,"Loading firmware ...\n");
+	dataptr = (u32*)firmware->data;
+	for (i = 0; i < (firmware->size >> 2); i++) {
+		value = le32_to_cpu(*dataptr);
+		checksum += ~value;
+		memory_write(dev->core, i, value);
+		dataptr++;
+	}
+
+	/* read back to verify with the checksum */
+	for (i--; i >= 0; i--) {
+		memory_read(dev->core, i, &value);
+		checksum -= ~value;
+	}
+	if (checksum) {
+		dprintk(0, "ERROR: Firmware load failed (checksum mismatch).\n");
+		release_firmware(firmware);
+		return -1;
+	}
+	release_firmware(firmware);
+	dprintk(0, "Firmware upload successful.\n");
+
+	retval |= register_write(dev->core, IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST);
+	retval |= register_read(dev->core, IVTV_REG_SPU, &value);
+	retval |= register_write(dev->core, IVTV_REG_SPU, value & 0xFFFFFFFE);
+	msleep(1);
+
+	retval |= register_read(dev->core, IVTV_REG_VPU, &value);
+	retval |= register_write(dev->core, IVTV_REG_VPU, value & 0xFFFFFFE8);
+
+	if (retval < 0)
+		dprintk(0, "Error with register_write\n");
+	return 0;
+}
+
+/**
+ Settings used by the windows tv app for PVR2000:
+=================================================================================================================
+Profile | Codec | Resolution | CBR/VBR | Video Qlty   | V. Bitrate | Frmrate | Audio Codec | A. Bitrate | A. Mode
+-----------------------------------------------------------------------------------------------------------------
+MPEG-1  | MPEG1 | 352x288PAL | (CBR)   | 1000:Optimal | 2000 Kbps  | 25fps   | MPG1 Layer2 | 224kbps    | Stereo
+MPEG-2  | MPEG2 | 720x576PAL | VBR     | 600 :Good    | 4000 Kbps  | 25fps   | MPG1 Layer2 | 224kbps    | Stereo
+VCD     | MPEG1 | 352x288PAL | (CBR)   | 1000:Optimal | 1150 Kbps  | 25fps   | MPG1 Layer2 | 224kbps    | Stereo
+DVD     | MPEG2 | 720x576PAL | VBR     | 600 :Good    | 6000 Kbps  | 25fps   | MPG1 Layer2 | 224kbps    | Stereo
+DB* DVD | MPEG2 | 720x576PAL | CBR     | 600 :Good    | 6000 Kbps  | 25fps   | MPG1 Layer2 | 224kbps    | Stereo
+=================================================================================================================
+*DB: "DirectBurn"
+*/
+
+static void blackbird_codec_settings(struct cx8802_dev *dev)
+{
+	/* assign frame size */
+	blackbird_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0,
+				dev->height, dev->width);
+
+	dev->cxhdl.width = dev->width;
+	dev->cxhdl.height = dev->height;
+	cx2341x_handler_set_50hz(&dev->cxhdl, dev->core->tvnorm & V4L2_STD_625_50);
+	cx2341x_handler_setup(&dev->cxhdl);
+}
+
+static int blackbird_initialize_codec(struct cx8802_dev *dev)
+{
+	struct cx88_core *core = dev->core;
+	int version;
+	int retval;
+
+	dprintk(1,"Initialize codec\n");
+	retval = blackbird_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); /* ping */
+	if (retval < 0) {
+
+		dev->mpeg_active = 0;
+
+		/* ping was not successful, reset and upload firmware */
+		cx_write(MO_SRST_IO, 0); /* SYS_RSTO=0 */
+		cx_write(MO_SRST_IO, 1); /* SYS_RSTO=1 */
+		retval = blackbird_load_firmware(dev);
+		if (retval < 0)
+			return retval;
+
+		retval = blackbird_find_mailbox(dev);
+		if (retval < 0)
+			return -1;
+
+		dev->mailbox = retval;
+
+		retval = blackbird_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); /* ping */
+		if (retval < 0) {
+			dprintk(0, "ERROR: Firmware ping failed!\n");
+			return -1;
+		}
+
+		retval = blackbird_api_cmd(dev, CX2341X_ENC_GET_VERSION, 0, 1, &version);
+		if (retval < 0) {
+			dprintk(0, "ERROR: Firmware get encoder version failed!\n");
+			return -1;
+		}
+		dprintk(0, "Firmware version is 0x%08x\n", version);
+	}
+
+	cx_write(MO_PINMUX_IO, 0x88); /* 656-8bit IO and enable MPEG parallel IO */
+	cx_clear(MO_INPUT_FORMAT, 0x100); /* chroma subcarrier lock to normal? */
+	cx_write(MO_VBOS_CONTROL, 0x84A00); /* no 656 mode, 8-bit pixels, disable VBI */
+	cx_clear(MO_OUTPUT_FORMAT, 0x0008); /* Normal Y-limits to let the mpeg encoder sync */
+
+	blackbird_codec_settings(dev);
+
+	blackbird_api_cmd(dev, CX2341X_ENC_SET_NUM_VSYNC_LINES, 2, 0,
+			BLACKBIRD_FIELD1_SAA7115,
+			BLACKBIRD_FIELD2_SAA7115
+		);
+
+	blackbird_api_cmd(dev, CX2341X_ENC_SET_PLACEHOLDER, 12, 0,
+			BLACKBIRD_CUSTOM_EXTENSION_USR_DATA,
+			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+
+	return 0;
+}
+
+static int blackbird_start_codec(struct file *file, void *priv)
+{
+	struct cx8802_dev *dev  = ((struct cx8802_fh *)priv)->dev;
+	struct cx88_core *core = dev->core;
+	/* start capturing to the host interface */
+	u32 reg;
+
+	int i;
+	int lastchange = -1;
+	int lastval = 0;
+
+	for (i = 0; (i < 10) && (i < (lastchange + 4)); i++) {
+		reg = cx_read(AUD_STATUS);
+
+		dprintk(1, "AUD_STATUS:%dL: 0x%x\n", i, reg);
+		if ((reg & 0x0F) != lastval) {
+			lastval = reg & 0x0F;
+			lastchange = i;
+		}
+		msleep(100);
+	}
+
+	/* unmute audio source */
+	cx_clear(AUD_VOL_CTL, (1 << 6));
+
+	blackbird_api_cmd(dev, CX2341X_ENC_REFRESH_INPUT, 0, 0);
+
+	/* initialize the video input */
+	blackbird_api_cmd(dev, CX2341X_ENC_INITIALIZE_INPUT, 0, 0);
+
+	cx2341x_handler_set_busy(&dev->cxhdl, 1);
+
+	/* start capturing to the host interface */
+	blackbird_api_cmd(dev, CX2341X_ENC_START_CAPTURE, 2, 0,
+			BLACKBIRD_MPEG_CAPTURE,
+			BLACKBIRD_RAW_BITS_NONE
+		);
+
+	dev->mpeg_active = 1;
+	return 0;
+}
+
+static int blackbird_stop_codec(struct cx8802_dev *dev)
+{
+	blackbird_api_cmd(dev, CX2341X_ENC_STOP_CAPTURE, 3, 0,
+			BLACKBIRD_END_NOW,
+			BLACKBIRD_MPEG_CAPTURE,
+			BLACKBIRD_RAW_BITS_NONE
+		);
+
+	cx2341x_handler_set_busy(&dev->cxhdl, 0);
+
+	dev->mpeg_active = 0;
+	return 0;
+}
+
+/* ------------------------------------------------------------------ */
+
+static int bb_buf_setup(struct videobuf_queue *q,
+			unsigned int *count, unsigned int *size)
+{
+	struct cx8802_fh *fh = q->priv_data;
+
+	fh->dev->ts_packet_size  = 188 * 4; /* was: 512 */
+	fh->dev->ts_packet_count = mpegbufs; /* was: 100 */
+
+	*size = fh->dev->ts_packet_size * fh->dev->ts_packet_count;
+	*count = fh->dev->ts_packet_count;
+	return 0;
+}
+
+static int
+bb_buf_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
+	       enum v4l2_field field)
+{
+	struct cx8802_fh *fh = q->priv_data;
+	return cx8802_buf_prepare(q, fh->dev, (struct cx88_buffer*)vb, field);
+}
+
+static void
+bb_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
+{
+	struct cx8802_fh *fh = q->priv_data;
+	cx8802_buf_queue(fh->dev, (struct cx88_buffer*)vb);
+}
+
+static void
+bb_buf_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
+{
+	cx88_free_buffer(q, (struct cx88_buffer*)vb);
+}
+
+static struct videobuf_queue_ops blackbird_qops = {
+	.buf_setup    = bb_buf_setup,
+	.buf_prepare  = bb_buf_prepare,
+	.buf_queue    = bb_buf_queue,
+	.buf_release  = bb_buf_release,
+};
+
+/* ------------------------------------------------------------------ */
+
+static int vidioc_querycap(struct file *file, void  *priv,
+					struct v4l2_capability *cap)
+{
+	struct cx8802_dev *dev  = ((struct cx8802_fh *)priv)->dev;
+	struct cx88_core  *core = dev->core;
+
+	strcpy(cap->driver, "cx88_blackbird");
+	sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
+	cx88_querycap(file, core, cap);
+	return 0;
+}
+
+static int vidioc_enum_fmt_vid_cap (struct file *file, void  *priv,
+					struct v4l2_fmtdesc *f)
+{
+	if (f->index != 0)
+		return -EINVAL;
+
+	strlcpy(f->description, "MPEG", sizeof(f->description));
+	f->pixelformat = V4L2_PIX_FMT_MPEG;
+	f->flags = V4L2_FMT_FLAG_COMPRESSED;
+	return 0;
+}
+
+static int vidioc_g_fmt_vid_cap (struct file *file, void *priv,
+					struct v4l2_format *f)
+{
+	struct cx8802_fh  *fh   = priv;
+	struct cx8802_dev *dev  = fh->dev;
+
+	f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
+	f->fmt.pix.bytesperline = 0;
+	f->fmt.pix.sizeimage    = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */;
+	f->fmt.pix.colorspace   = V4L2_COLORSPACE_SMPTE170M;
+	f->fmt.pix.width        = dev->width;
+	f->fmt.pix.height       = dev->height;
+	f->fmt.pix.field        = fh->mpegq.field;
+	dprintk(1, "VIDIOC_G_FMT: w: %d, h: %d, f: %d\n",
+		dev->width, dev->height, fh->mpegq.field );
+	return 0;
+}
+
+static int vidioc_try_fmt_vid_cap (struct file *file, void *priv,
+			struct v4l2_format *f)
+{
+	struct cx8802_fh  *fh   = priv;
+	struct cx8802_dev *dev  = fh->dev;
+
+	f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
+	f->fmt.pix.bytesperline = 0;
+	f->fmt.pix.sizeimage    = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */;
+	f->fmt.pix.colorspace   = V4L2_COLORSPACE_SMPTE170M;
+	dprintk(1, "VIDIOC_TRY_FMT: w: %d, h: %d, f: %d\n",
+		dev->width, dev->height, fh->mpegq.field );
+	return 0;
+}
+
+static int vidioc_s_fmt_vid_cap (struct file *file, void *priv,
+					struct v4l2_format *f)
+{
+	struct cx8802_fh  *fh   = priv;
+	struct cx8802_dev *dev  = fh->dev;
+	struct cx88_core  *core = dev->core;
+
+	f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
+	f->fmt.pix.bytesperline = 0;
+	f->fmt.pix.sizeimage    = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */;
+	f->fmt.pix.colorspace   = V4L2_COLORSPACE_SMPTE170M;
+	dev->width              = f->fmt.pix.width;
+	dev->height             = f->fmt.pix.height;
+	fh->mpegq.field         = f->fmt.pix.field;
+	cx88_set_scale(core, f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field);
+	blackbird_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0,
+				f->fmt.pix.height, f->fmt.pix.width);
+	dprintk(1, "VIDIOC_S_FMT: w: %d, h: %d, f: %d\n",
+		f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field );
+	return 0;
+}
+
+static int vidioc_reqbufs (struct file *file, void *priv, struct v4l2_requestbuffers *p)
+{
+	struct cx8802_fh  *fh   = priv;
+	return (videobuf_reqbufs(&fh->mpegq, p));
+}
+
+static int vidioc_querybuf (struct file *file, void *priv, struct v4l2_buffer *p)
+{
+	struct cx8802_fh  *fh   = priv;
+	return (videobuf_querybuf(&fh->mpegq, p));
+}
+
+static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *p)
+{
+	struct cx8802_fh  *fh   = priv;
+	return (videobuf_qbuf(&fh->mpegq, p));
+}
+
+static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *p)
+{
+	struct cx8802_fh  *fh   = priv;
+	return (videobuf_dqbuf(&fh->mpegq, p,
+				file->f_flags & O_NONBLOCK));
+}
+
+static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+	struct cx8802_fh  *fh   = priv;
+	struct cx8802_dev *dev  = fh->dev;
+
+	if (!dev->mpeg_active)
+		blackbird_start_codec(file, fh);
+	return videobuf_streamon(&fh->mpegq);
+}
+
+static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+	struct cx8802_fh  *fh   = priv;
+	struct cx8802_dev *dev  = fh->dev;
+
+	if (dev->mpeg_active)
+		blackbird_stop_codec(dev);
+	return videobuf_streamoff(&fh->mpegq);
+}
+
+static int vidioc_s_frequency (struct file *file, void *priv,
+				struct v4l2_frequency *f)
+{
+	struct cx8802_fh  *fh   = priv;
+	struct cx8802_dev *dev  = fh->dev;
+	struct cx88_core  *core = dev->core;
+
+	if (unlikely(UNSET == core->board.tuner_type))
+		return -EINVAL;
+	if (unlikely(f->tuner != 0))
+		return -EINVAL;
+	if (dev->mpeg_active)
+		blackbird_stop_codec(dev);
+
+	cx88_set_freq (core,f);
+	blackbird_initialize_codec(dev);
+	cx88_set_scale(dev->core, dev->width, dev->height,
+			fh->mpegq.field);
+	return 0;
+}
+
+static int vidioc_log_status (struct file *file, void *priv)
+{
+	struct cx8802_dev *dev  = ((struct cx8802_fh *)priv)->dev;
+	struct cx88_core  *core = dev->core;
+	char name[32 + 2];
+
+	snprintf(name, sizeof(name), "%s/2", core->name);
+	call_all(core, core, log_status);
+	v4l2_ctrl_handler_log_status(&dev->cxhdl.hdl, name);
+	return 0;
+}
+
+static int vidioc_enum_input (struct file *file, void *priv,
+				struct v4l2_input *i)
+{
+	struct cx88_core  *core = ((struct cx8802_fh *)priv)->dev->core;
+	return cx88_enum_input (core,i);
+}
+
+static int vidioc_g_frequency (struct file *file, void *priv,
+				struct v4l2_frequency *f)
+{
+	struct cx8802_fh  *fh   = priv;
+	struct cx88_core  *core = fh->dev->core;
+
+	if (unlikely(UNSET == core->board.tuner_type))
+		return -EINVAL;
+	if (unlikely(f->tuner != 0))
+		return -EINVAL;
+
+	f->frequency = core->freq;
+	call_all(core, tuner, g_frequency, f);
+
+	return 0;
+}
+
+static int vidioc_g_input (struct file *file, void *priv, unsigned int *i)
+{
+	struct cx88_core  *core = ((struct cx8802_fh *)priv)->dev->core;
+
+	*i = core->input;
+	return 0;
+}
+
+static int vidioc_s_input (struct file *file, void *priv, unsigned int i)
+{
+	struct cx88_core  *core = ((struct cx8802_fh *)priv)->dev->core;
+
+	if (i >= 4)
+		return -EINVAL;
+	if (0 == INPUT(i).type)
+		return -EINVAL;
+
+	mutex_lock(&core->lock);
+	cx88_newstation(core);
+	cx88_video_mux(core,i);
+	mutex_unlock(&core->lock);
+	return 0;
+}
+
+static int vidioc_g_tuner (struct file *file, void *priv,
+				struct v4l2_tuner *t)
+{
+	struct cx88_core  *core = ((struct cx8802_fh *)priv)->dev->core;
+	u32 reg;
+
+	if (unlikely(UNSET == core->board.tuner_type))
+		return -EINVAL;
+	if (0 != t->index)
+		return -EINVAL;
+
+	strcpy(t->name, "Television");
+	t->capability = V4L2_TUNER_CAP_NORM;
+	t->rangehigh  = 0xffffffffUL;
+	call_all(core, tuner, g_tuner, t);
+
+	cx88_get_stereo(core ,t);
+	reg = cx_read(MO_DEVICE_STATUS);
+	t->signal = (reg & (1<<5)) ? 0xffff : 0x0000;
+	return 0;
+}
+
+static int vidioc_s_tuner (struct file *file, void *priv,
+				struct v4l2_tuner *t)
+{
+	struct cx88_core  *core = ((struct cx8802_fh *)priv)->dev->core;
+
+	if (UNSET == core->board.tuner_type)
+		return -EINVAL;
+	if (0 != t->index)
+		return -EINVAL;
+
+	cx88_set_stereo(core, t->audmode, 1);
+	return 0;
+}
+
+static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *tvnorm)
+{
+	struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core;
+
+	*tvnorm = core->tvnorm;
+	return 0;
+}
+
+static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *id)
+{
+	struct cx88_core  *core = ((struct cx8802_fh *)priv)->dev->core;
+
+	mutex_lock(&core->lock);
+	cx88_set_tvnorm(core,*id);
+	mutex_unlock(&core->lock);
+	return 0;
+}
+
+/* FIXME: cx88_ioctl_hook not implemented */
+
+static int mpeg_open(struct file *file)
+{
+	struct video_device *vdev = video_devdata(file);
+	struct cx8802_dev *dev = video_drvdata(file);
+	struct cx8802_fh *fh;
+	struct cx8802_driver *drv = NULL;
+	int err;
+
+	dprintk( 1, "%s\n", __func__);
+
+	mutex_lock(&dev->core->lock);
+
+	/* Make sure we can acquire the hardware */
+	drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD);
+	if (!drv) {
+		dprintk(1, "%s: blackbird driver is not loaded\n", __func__);
+		mutex_unlock(&dev->core->lock);
+		return -ENODEV;
+	}
+
+	err = drv->request_acquire(drv);
+	if (err != 0) {
+		dprintk(1,"%s: Unable to acquire hardware, %d\n", __func__, err);
+		mutex_unlock(&dev->core->lock);
+		return err;
+	}
+
+	if (!dev->core->mpeg_users && blackbird_initialize_codec(dev) < 0) {
+		drv->request_release(drv);
+		mutex_unlock(&dev->core->lock);
+		return -EINVAL;
+	}
+	dprintk(1, "open dev=%s\n", video_device_node_name(vdev));
+
+	/* allocate + initialize per filehandle data */
+	fh = kzalloc(sizeof(*fh),GFP_KERNEL);
+	if (NULL == fh) {
+		drv->request_release(drv);
+		mutex_unlock(&dev->core->lock);
+		return -ENOMEM;
+	}
+	v4l2_fh_init(&fh->fh, vdev);
+	file->private_data = fh;
+	fh->dev      = dev;
+
+	videobuf_queue_sg_init(&fh->mpegq, &blackbird_qops,
+			    &dev->pci->dev, &dev->slock,
+			    V4L2_BUF_TYPE_VIDEO_CAPTURE,
+			    V4L2_FIELD_INTERLACED,
+			    sizeof(struct cx88_buffer),
+			    fh, NULL);
+
+	/* FIXME: locking against other video device */
+	cx88_set_scale(dev->core, dev->width, dev->height,
+			fh->mpegq.field);
+
+	dev->core->mpeg_users++;
+	mutex_unlock(&dev->core->lock);
+	v4l2_fh_add(&fh->fh);
+	return 0;
+}
+
+static int mpeg_release(struct file *file)
+{
+	struct cx8802_fh  *fh  = file->private_data;
+	struct cx8802_dev *dev = fh->dev;
+	struct cx8802_driver *drv = NULL;
+
+	mutex_lock(&dev->core->lock);
+
+	if (dev->mpeg_active && dev->core->mpeg_users == 1)
+		blackbird_stop_codec(dev);
+
+	cx8802_cancel_buffers(fh->dev);
+	/* stop mpeg capture */
+	videobuf_stop(&fh->mpegq);
+
+	videobuf_mmap_free(&fh->mpegq);
+
+	v4l2_fh_del(&fh->fh);
+	v4l2_fh_exit(&fh->fh);
+	file->private_data = NULL;
+	kfree(fh);
+
+	/* Make sure we release the hardware */
+	drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD);
+	WARN_ON(!drv);
+	if (drv)
+		drv->request_release(drv);
+
+	dev->core->mpeg_users--;
+
+	mutex_unlock(&dev->core->lock);
+
+	return 0;
+}
+
+static ssize_t
+mpeg_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
+{
+	struct cx8802_fh *fh = file->private_data;
+	struct cx8802_dev *dev = fh->dev;
+
+	if (!dev->mpeg_active)
+		blackbird_start_codec(file, fh);
+
+	return videobuf_read_stream(&fh->mpegq, data, count, ppos, 0,
+				    file->f_flags & O_NONBLOCK);
+}
+
+static unsigned int
+mpeg_poll(struct file *file, struct poll_table_struct *wait)
+{
+	unsigned long req_events = poll_requested_events(wait);
+	struct cx8802_fh *fh = file->private_data;
+	struct cx8802_dev *dev = fh->dev;
+
+	if (!dev->mpeg_active && (req_events & (POLLIN | POLLRDNORM)))
+		blackbird_start_codec(file, fh);
+
+	return v4l2_ctrl_poll(file, wait) | videobuf_poll_stream(file, &fh->mpegq, wait);
+}
+
+static int
+mpeg_mmap(struct file *file, struct vm_area_struct * vma)
+{
+	struct cx8802_fh *fh = file->private_data;
+
+	return videobuf_mmap_mapper(&fh->mpegq, vma);
+}
+
+static const struct v4l2_file_operations mpeg_fops =
+{
+	.owner	       = THIS_MODULE,
+	.open	       = mpeg_open,
+	.release       = mpeg_release,
+	.read	       = mpeg_read,
+	.poll          = mpeg_poll,
+	.mmap	       = mpeg_mmap,
+	.unlocked_ioctl = video_ioctl2,
+};
+
+static const struct v4l2_ioctl_ops mpeg_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,
+	.vidioc_reqbufs       = vidioc_reqbufs,
+	.vidioc_querybuf      = vidioc_querybuf,
+	.vidioc_qbuf          = vidioc_qbuf,
+	.vidioc_dqbuf         = vidioc_dqbuf,
+	.vidioc_streamon      = vidioc_streamon,
+	.vidioc_streamoff     = vidioc_streamoff,
+	.vidioc_s_frequency   = vidioc_s_frequency,
+	.vidioc_log_status    = vidioc_log_status,
+	.vidioc_enum_input    = vidioc_enum_input,
+	.vidioc_g_frequency   = vidioc_g_frequency,
+	.vidioc_g_input       = vidioc_g_input,
+	.vidioc_s_input       = vidioc_s_input,
+	.vidioc_g_tuner       = vidioc_g_tuner,
+	.vidioc_s_tuner       = vidioc_s_tuner,
+	.vidioc_g_std         = vidioc_g_std,
+	.vidioc_s_std         = vidioc_s_std,
+	.vidioc_subscribe_event      = v4l2_ctrl_subscribe_event,
+	.vidioc_unsubscribe_event    = v4l2_event_unsubscribe,
+};
+
+static struct video_device cx8802_mpeg_template = {
+	.name                 = "cx8802",
+	.fops                 = &mpeg_fops,
+	.ioctl_ops 	      = &mpeg_ioctl_ops,
+	.tvnorms              = CX88_NORMS,
+};
+
+/* ------------------------------------------------------------------ */
+
+/* The CX8802 MPEG API will call this when we can use the hardware */
+static int cx8802_blackbird_advise_acquire(struct cx8802_driver *drv)
+{
+	struct cx88_core *core = drv->core;
+	int err = 0;
+
+	switch (core->boardnr) {
+	case CX88_BOARD_HAUPPAUGE_HVR1300:
+		/* By default, core setup will leave the cx22702 out of reset, on the bus.
+		 * We left the hardware on power up with the cx22702 active.
+		 * We're being given access to re-arrange the GPIOs.
+		 * Take the bus off the cx22702 and put the cx23416 on it.
+		 */
+		/* Toggle reset on cx22702 leaving i2c active */
+		cx_set(MO_GP0_IO, 0x00000080);
+		udelay(1000);
+		cx_clear(MO_GP0_IO, 0x00000080);
+		udelay(50);
+		cx_set(MO_GP0_IO, 0x00000080);
+		udelay(1000);
+		/* tri-state the cx22702 pins */
+		cx_set(MO_GP0_IO, 0x00000004);
+		udelay(1000);
+		break;
+	default:
+		err = -ENODEV;
+	}
+	return err;
+}
+
+/* The CX8802 MPEG API will call this when we need to release the hardware */
+static int cx8802_blackbird_advise_release(struct cx8802_driver *drv)
+{
+	struct cx88_core *core = drv->core;
+	int err = 0;
+
+	switch (core->boardnr) {
+	case CX88_BOARD_HAUPPAUGE_HVR1300:
+		/* Exit leaving the cx23416 on the bus */
+		break;
+	default:
+		err = -ENODEV;
+	}
+	return err;
+}
+
+static void blackbird_unregister_video(struct cx8802_dev *dev)
+{
+	if (dev->mpeg_dev) {
+		if (video_is_registered(dev->mpeg_dev))
+			video_unregister_device(dev->mpeg_dev);
+		else
+			video_device_release(dev->mpeg_dev);
+		dev->mpeg_dev = NULL;
+	}
+}
+
+static int blackbird_register_video(struct cx8802_dev *dev)
+{
+	int err;
+
+	dev->mpeg_dev = cx88_vdev_init(dev->core,dev->pci,
+				       &cx8802_mpeg_template,"mpeg");
+	dev->mpeg_dev->ctrl_handler = &dev->cxhdl.hdl;
+	video_set_drvdata(dev->mpeg_dev, dev);
+	err = video_register_device(dev->mpeg_dev,VFL_TYPE_GRABBER, -1);
+	if (err < 0) {
+		printk(KERN_INFO "%s/2: can't register mpeg device\n",
+		       dev->core->name);
+		return err;
+	}
+	printk(KERN_INFO "%s/2: registered device %s [mpeg]\n",
+	       dev->core->name, video_device_node_name(dev->mpeg_dev));
+	return 0;
+}
+
+/* ----------------------------------------------------------- */
+
+static int cx8802_blackbird_probe(struct cx8802_driver *drv)
+{
+	struct cx88_core *core = drv->core;
+	struct cx8802_dev *dev = core->dvbdev;
+	int err;
+
+	dprintk( 1, "%s\n", __func__);
+	dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n",
+		core->boardnr,
+		core->name,
+		core->pci_bus,
+		core->pci_slot);
+
+	err = -ENODEV;
+	if (!(core->board.mpeg & CX88_MPEG_BLACKBIRD))
+		goto fail_core;
+
+	dev->width = 720;
+	if (core->tvnorm & V4L2_STD_525_60) {
+		dev->height = 480;
+	} else {
+		dev->height = 576;
+	}
+	dev->cxhdl.port = CX2341X_PORT_STREAMING;
+	dev->cxhdl.width = dev->width;
+	dev->cxhdl.height = dev->height;
+	dev->cxhdl.func = blackbird_mbox_func;
+	dev->cxhdl.priv = dev;
+	err = cx2341x_handler_init(&dev->cxhdl, 36);
+	if (err)
+		goto fail_core;
+	v4l2_ctrl_add_handler(&dev->cxhdl.hdl, &core->video_hdl);
+
+	/* blackbird stuff */
+	printk("%s/2: cx23416 based mpeg encoder (blackbird reference design)\n",
+	       core->name);
+	host_setup(dev->core);
+
+	blackbird_initialize_codec(dev);
+
+	/* initial device configuration: needed ? */
+//	init_controls(core);
+	cx88_set_tvnorm(core,core->tvnorm);
+	cx88_video_mux(core,0);
+	cx2341x_handler_set_50hz(&dev->cxhdl, dev->height == 576);
+	cx2341x_handler_setup(&dev->cxhdl);
+	blackbird_register_video(dev);
+
+	return 0;
+
+ fail_core:
+	return err;
+}
+
+static int cx8802_blackbird_remove(struct cx8802_driver *drv)
+{
+	struct cx88_core *core = drv->core;
+	struct cx8802_dev *dev = core->dvbdev;
+
+	/* blackbird */
+	blackbird_unregister_video(drv->core->dvbdev);
+	v4l2_ctrl_handler_free(&dev->cxhdl.hdl);
+
+	return 0;
+}
+
+static struct cx8802_driver cx8802_blackbird_driver = {
+	.type_id	= CX88_MPEG_BLACKBIRD,
+	.hw_access	= CX8802_DRVCTL_SHARED,
+	.probe		= cx8802_blackbird_probe,
+	.remove		= cx8802_blackbird_remove,
+	.advise_acquire	= cx8802_blackbird_advise_acquire,
+	.advise_release	= cx8802_blackbird_advise_release,
+};
+
+static int __init blackbird_init(void)
+{
+	printk(KERN_INFO "cx2388x blackbird driver version %s loaded\n",
+	       CX88_VERSION);
+	return cx8802_register_driver(&cx8802_blackbird_driver);
+}
+
+static void __exit blackbird_fini(void)
+{
+	cx8802_unregister_driver(&cx8802_blackbird_driver);
+}
+
+module_init(blackbird_init);
+module_exit(blackbird_fini);
+
+module_param_named(video_debug,cx8802_mpeg_template.debug, int, 0644);
+MODULE_PARM_DESC(debug,"enable debug messages [video]");
diff --git a/drivers/media/pci/cx88/cx88-cards.c b/drivers/media/pci/cx88/cx88-cards.c
new file mode 100644
index 0000000..0c25524
--- /dev/null
+++ b/drivers/media/pci/cx88/cx88-cards.c
@@ -0,0 +1,3811 @@
+/*
+ *
+ * device driver for Conexant 2388x based TV cards
+ * card-specific stuff.
+ *
+ * (c) 2003 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the 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/init.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+
+#include "cx88.h"
+#include "tea5767.h"
+#include "xc4000.h"
+
+static unsigned int tuner[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
+static unsigned int radio[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
+static unsigned int card[]  = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
+
+module_param_array(tuner, int, NULL, 0444);
+module_param_array(radio, int, NULL, 0444);
+module_param_array(card,  int, NULL, 0444);
+
+MODULE_PARM_DESC(tuner,"tuner type");
+MODULE_PARM_DESC(radio,"radio tuner type");
+MODULE_PARM_DESC(card,"card type");
+
+static unsigned int latency = UNSET;
+module_param(latency,int,0444);
+MODULE_PARM_DESC(latency,"pci latency timer");
+
+static int disable_ir;
+module_param(disable_ir, int, 0444);
+MODULE_PARM_DESC(disable_ir, "Disable IR support");
+
+#define info_printk(core, fmt, arg...) \
+	printk(KERN_INFO "%s: " fmt, core->name , ## arg)
+
+#define warn_printk(core, fmt, arg...) \
+	printk(KERN_WARNING "%s: " fmt, core->name , ## arg)
+
+#define err_printk(core, fmt, arg...) \
+	printk(KERN_ERR "%s: " fmt, core->name , ## arg)
+
+
+/* ------------------------------------------------------------------ */
+/* board config info                                                  */
+
+/* If radio_type !=UNSET, radio_addr should be specified
+ */
+
+static const struct cx88_board cx88_boards[] = {
+	[CX88_BOARD_UNKNOWN] = {
+		.name		= "UNKNOWN/GENERIC",
+		.tuner_type     = UNSET,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.input          = {{
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 0,
+		},{
+			.type   = CX88_VMUX_COMPOSITE2,
+			.vmux   = 1,
+		},{
+			.type   = CX88_VMUX_COMPOSITE3,
+			.vmux   = 2,
+		},{
+			.type   = CX88_VMUX_COMPOSITE4,
+			.vmux   = 3,
+		}},
+	},
+	[CX88_BOARD_HAUPPAUGE] = {
+		.name		= "Hauppauge WinTV 34xxx models",
+		.tuner_type     = UNSET,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.input          = {{
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 0,
+			.gpio0  = 0xff00,  // internal decoder
+		},{
+			.type   = CX88_VMUX_DEBUG,
+			.vmux   = 0,
+			.gpio0  = 0xff01,  // mono from tuner chip
+		},{
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 1,
+			.gpio0  = 0xff02,
+		},{
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+			.gpio0  = 0xff02,
+		}},
+		.radio = {
+			.type   = CX88_RADIO,
+			.gpio0  = 0xff01,
+		},
+	},
+	[CX88_BOARD_GDI] = {
+		.name		= "GDI Black Gold",
+		.tuner_type     = UNSET,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.input          = {{
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 0,
+		},{
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+		}},
+	},
+	[CX88_BOARD_PIXELVIEW] = {
+		.name           = "PixelView",
+		.tuner_type     = TUNER_PHILIPS_PAL,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.input          = {{
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 0,
+			.gpio0  = 0xff00,  // internal decoder
+		},{
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 1,
+		},{
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+		}},
+		.radio = {
+			 .type  = CX88_RADIO,
+			 .gpio0 = 0xff10,
+		},
+	},
+	[CX88_BOARD_ATI_WONDER_PRO] = {
+		.name           = "ATI TV Wonder Pro",
+		.tuner_type     = TUNER_PHILIPS_4IN1,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT | TDA9887_INTERCARRIER,
+		.input          = {{
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 0,
+			.gpio0  = 0x03ff,
+		},{
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 1,
+			.gpio0  = 0x03fe,
+		},{
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+			.gpio0  = 0x03fe,
+		}},
+	},
+	[CX88_BOARD_WINFAST2000XP_EXPERT] = {
+		.name           = "Leadtek Winfast 2000XP Expert",
+		.tuner_type     = TUNER_PHILIPS_4IN1,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.input          = {{
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 0,
+			.gpio0	= 0x00F5e700,
+			.gpio1  = 0x00003004,
+			.gpio2  = 0x00F5e700,
+			.gpio3  = 0x02000000,
+		},{
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 1,
+			.gpio0	= 0x00F5c700,
+			.gpio1  = 0x00003004,
+			.gpio2  = 0x00F5c700,
+			.gpio3  = 0x02000000,
+		},{
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+			.gpio0	= 0x00F5c700,
+			.gpio1  = 0x00003004,
+			.gpio2  = 0x00F5c700,
+			.gpio3  = 0x02000000,
+		}},
+		.radio = {
+			.type   = CX88_RADIO,
+			.gpio0	= 0x00F5d700,
+			.gpio1  = 0x00003004,
+			.gpio2  = 0x00F5d700,
+			.gpio3  = 0x02000000,
+		},
+	},
+	[CX88_BOARD_AVERTV_STUDIO_303] = {
+		.name           = "AverTV Studio 303 (M126)",
+		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.input          = {{
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 0,
+			.gpio1  = 0xe09f,
+		},{
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 1,
+			.gpio1  = 0xe05f,
+		},{
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+			.gpio1  = 0xe05f,
+		}},
+		.radio = {
+			.gpio1  = 0xe0df,
+			.type   = CX88_RADIO,
+		},
+	},
+	[CX88_BOARD_MSI_TVANYWHERE_MASTER] = {
+		// added gpio values thanks to Michal
+		// values for PAL from DScaler
+		.name           = "MSI TV-@nywhere Master",
+		.tuner_type     = TUNER_MT2032,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.tda9887_conf	= TDA9887_PRESENT | TDA9887_INTERCARRIER_NTSC,
+		.input          = {{
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 0,
+			.gpio0  = 0x000040bf,
+			.gpio1  = 0x000080c0,
+			.gpio2  = 0x0000ff40,
+		},{
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 1,
+			.gpio0  = 0x000040bf,
+			.gpio1  = 0x000080c0,
+			.gpio2  = 0x0000ff40,
+		},{
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+			.gpio0  = 0x000040bf,
+			.gpio1  = 0x000080c0,
+			.gpio2  = 0x0000ff40,
+		}},
+		.radio = {
+			 .type   = CX88_RADIO,
+			 .vmux   = 3,
+			 .gpio0  = 0x000040bf,
+			 .gpio1  = 0x000080c0,
+			 .gpio2  = 0x0000ff20,
+		},
+	},
+	[CX88_BOARD_WINFAST_DV2000] = {
+		.name           = "Leadtek Winfast DV2000",
+		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.input          = {{
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 0,
+			.gpio0  = 0x0035e700,
+			.gpio1  = 0x00003004,
+			.gpio2  = 0x0035e700,
+			.gpio3  = 0x02000000,
+		},{
+
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 1,
+			.gpio0  = 0x0035c700,
+			.gpio1  = 0x00003004,
+			.gpio2  = 0x0035c700,
+			.gpio3  = 0x02000000,
+		},{
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+			.gpio0  = 0x0035c700,
+			.gpio1  = 0x0035c700,
+			.gpio2  = 0x02000000,
+			.gpio3  = 0x02000000,
+		}},
+		.radio = {
+			.type   = CX88_RADIO,
+			.gpio0  = 0x0035d700,
+			.gpio1  = 0x00007004,
+			.gpio2  = 0x0035d700,
+			.gpio3  = 0x02000000,
+		},
+	},
+	[CX88_BOARD_LEADTEK_PVR2000] = {
+		// gpio values for PAL version from regspy by DScaler
+		.name           = "Leadtek PVR 2000",
+		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.input          = {{
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 0,
+			.gpio0  = 0x0000bde2,
+			.audioroute = 1,
+		},{
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 1,
+			.gpio0  = 0x0000bde6,
+			.audioroute = 1,
+		},{
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+			.gpio0  = 0x0000bde6,
+			.audioroute = 1,
+		}},
+		.radio = {
+			.type   = CX88_RADIO,
+			.gpio0  = 0x0000bd62,
+			.audioroute = 1,
+		},
+		.mpeg           = CX88_MPEG_BLACKBIRD,
+	},
+	[CX88_BOARD_IODATA_GVVCP3PCI] = {
+		.name		= "IODATA GV-VCP3/PCI",
+		.tuner_type     = TUNER_ABSENT,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.input          = {{
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 0,
+		},{
+			.type   = CX88_VMUX_COMPOSITE2,
+			.vmux   = 1,
+		},{
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+		}},
+	},
+	[CX88_BOARD_PROLINK_PLAYTVPVR] = {
+		.name           = "Prolink PlayTV PVR",
+		.tuner_type     = TUNER_PHILIPS_FM1236_MK3,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.tda9887_conf	= TDA9887_PRESENT,
+		.input          = {{
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 0,
+			.gpio0  = 0xbff0,
+		},{
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 1,
+			.gpio0  = 0xbff3,
+		},{
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+			.gpio0  = 0xbff3,
+		}},
+		.radio = {
+			.type   = CX88_RADIO,
+			.gpio0  = 0xbff0,
+		},
+	},
+	[CX88_BOARD_ASUS_PVR_416] = {
+		.name		= "ASUS PVR-416",
+		.tuner_type     = TUNER_PHILIPS_FM1236_MK3,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.input          = {{
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 0,
+			.gpio0  = 0x0000fde6,
+		},{
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+			.gpio0  = 0x0000fde6, // 0x0000fda6 L,R RCA audio in?
+			.audioroute = 1,
+		}},
+		.radio = {
+			.type   = CX88_RADIO,
+			.gpio0  = 0x0000fde2,
+		},
+		.mpeg           = CX88_MPEG_BLACKBIRD,
+	},
+	[CX88_BOARD_MSI_TVANYWHERE] = {
+		.name           = "MSI TV-@nywhere",
+		.tuner_type     = TUNER_MT2032,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.input          = {{
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 0,
+			.gpio0  = 0x00000fbf,
+			.gpio2  = 0x0000fc08,
+		},{
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 1,
+			.gpio0  = 0x00000fbf,
+			.gpio2  = 0x0000fc68,
+		},{
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+			.gpio0  = 0x00000fbf,
+			.gpio2  = 0x0000fc68,
+		}},
+	},
+	[CX88_BOARD_KWORLD_DVB_T] = {
+		.name           = "KWorld/VStream XPert DVB-T",
+		.tuner_type     = TUNER_ABSENT,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.input          = {{
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 1,
+			.gpio0  = 0x0700,
+			.gpio2  = 0x0101,
+		},{
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+			.gpio0  = 0x0700,
+			.gpio2  = 0x0101,
+		}},
+		.mpeg           = CX88_MPEG_DVB,
+	},
+	[CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1] = {
+		.name           = "DViCO FusionHDTV DVB-T1",
+		.tuner_type     = TUNER_ABSENT, /* No analog tuner */
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.input          = {{
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 1,
+			.gpio0  = 0x000027df,
+		},{
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+			.gpio0  = 0x000027df,
+		}},
+		.mpeg           = CX88_MPEG_DVB,
+	},
+	[CX88_BOARD_KWORLD_LTV883] = {
+		.name           = "KWorld LTV883RF",
+		.tuner_type     = TUNER_TNF_8831BGFF,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.input          = {{
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 0,
+			.gpio0  = 0x07f8,
+		},{
+			.type   = CX88_VMUX_DEBUG,
+			.vmux   = 0,
+			.gpio0  = 0x07f9,  // mono from tuner chip
+		},{
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 1,
+			.gpio0  = 0x000007fa,
+		},{
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+			.gpio0  = 0x000007fa,
+		}},
+		.radio = {
+			.type   = CX88_RADIO,
+			.gpio0  = 0x000007f8,
+		},
+	},
+	[CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q] = {
+		.name		= "DViCO FusionHDTV 3 Gold-Q",
+		.tuner_type     = TUNER_MICROTUNE_4042FI5,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		/*
+		   GPIO[0] resets DT3302 DTV receiver
+		    0 - reset asserted
+		    1 - normal operation
+		   GPIO[1] mutes analog audio output connector
+		    0 - enable selected source
+		    1 - mute
+		   GPIO[2] selects source for analog audio output connector
+		    0 - analog audio input connector on tab
+		    1 - analog DAC output from CX23881 chip
+		   GPIO[3] selects RF input connector on tuner module
+		    0 - RF connector labeled CABLE
+		    1 - RF connector labeled ANT
+		   GPIO[4] selects high RF for QAM256 mode
+		    0 - normal RF
+		    1 - high RF
+		*/
+		.input          = {{
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 0,
+			.gpio0	= 0x0f0d,
+		},{
+			.type   = CX88_VMUX_CABLE,
+			.vmux   = 0,
+			.gpio0	= 0x0f05,
+		},{
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 1,
+			.gpio0	= 0x0f00,
+		},{
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+			.gpio0	= 0x0f00,
+		}},
+		.mpeg           = CX88_MPEG_DVB,
+	},
+	[CX88_BOARD_HAUPPAUGE_DVB_T1] = {
+		.name           = "Hauppauge Nova-T DVB-T",
+		.tuner_type     = TUNER_ABSENT,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.input          = {{
+			.type   = CX88_VMUX_DVB,
+			.vmux   = 0,
+		}},
+		.mpeg           = CX88_MPEG_DVB,
+	},
+	[CX88_BOARD_CONEXANT_DVB_T1] = {
+		.name           = "Conexant DVB-T reference design",
+		.tuner_type     = TUNER_ABSENT,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.input          = {{
+			.type   = CX88_VMUX_DVB,
+			.vmux   = 0,
+		}},
+		.mpeg           = CX88_MPEG_DVB,
+	},
+	[CX88_BOARD_PROVIDEO_PV259] = {
+		.name		= "Provideo PV259",
+		.tuner_type     = TUNER_PHILIPS_FQ1216ME,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.input          = {{
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 0,
+			.audioroute = 1,
+		}},
+		.mpeg           = CX88_MPEG_BLACKBIRD,
+	},
+	[CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS] = {
+		.name           = "DViCO FusionHDTV DVB-T Plus",
+		.tuner_type     = TUNER_ABSENT, /* No analog tuner */
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.input          = {{
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 1,
+			.gpio0  = 0x000027df,
+		},{
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+			.gpio0  = 0x000027df,
+		}},
+		.mpeg           = CX88_MPEG_DVB,
+	},
+	[CX88_BOARD_DNTV_LIVE_DVB_T] = {
+		.name		= "digitalnow DNTV Live! DVB-T",
+		.tuner_type     = TUNER_ABSENT,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.input		= {{
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 1,
+			.gpio0  = 0x00000700,
+			.gpio2  = 0x00000101,
+		},{
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+			.gpio0  = 0x00000700,
+			.gpio2  = 0x00000101,
+		}},
+		.mpeg           = CX88_MPEG_DVB,
+	},
+	[CX88_BOARD_PCHDTV_HD3000] = {
+		.name           = "pcHDTV HD3000 HDTV",
+		.tuner_type     = TUNER_THOMSON_DTT761X,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		/* GPIO[2] = audio source for analog audio out connector
+		 *  0 = analog audio input connector
+		 *  1 = CX88 audio DACs
+		 *
+		 * GPIO[7] = input to CX88's audio/chroma ADC
+		 *  0 = FM 10.7 MHz IF
+		 *  1 = Sound 4.5 MHz IF
+		 *
+		 * GPIO[1,5,6] = Oren 51132 pins 27,35,28 respectively
+		 *
+		 * GPIO[16] = Remote control input
+		 */
+		.input          = {{
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 0,
+			.gpio0  = 0x00008484,
+		},{
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 1,
+			.gpio0  = 0x00008400,
+		},{
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+			.gpio0  = 0x00008400,
+		}},
+		.radio = {
+			.type   = CX88_RADIO,
+			.gpio0  = 0x00008404,
+		},
+		.mpeg           = CX88_MPEG_DVB,
+	},
+	[CX88_BOARD_HAUPPAUGE_ROSLYN] = {
+		// entry added by Kaustubh D. Bhalerao <bhalerao.1@osu.edu>
+		// GPIO values obtained from regspy, courtesy Sean Covel
+		.name           = "Hauppauge WinTV 28xxx (Roslyn) models",
+		.tuner_type     = UNSET,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.input          = {{
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 0,
+			.gpio0  = 0xed1a,
+			.gpio2  = 0x00ff,
+		},{
+			.type   = CX88_VMUX_DEBUG,
+			.vmux   = 0,
+			.gpio0  = 0xff01,
+		},{
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 1,
+			.gpio0  = 0xff02,
+		},{
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+			.gpio0  = 0xed92,
+			.gpio2  = 0x00ff,
+		}},
+		.radio = {
+			 .type   = CX88_RADIO,
+			 .gpio0  = 0xed96,
+			 .gpio2  = 0x00ff,
+		 },
+		.mpeg           = CX88_MPEG_BLACKBIRD,
+	},
+	[CX88_BOARD_DIGITALLOGIC_MEC] = {
+		.name           = "Digital-Logic MICROSPACE Entertainment Center (MEC)",
+		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.input          = {{
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 0,
+			.gpio0  = 0x00009d80,
+			.audioroute = 1,
+		},{
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 1,
+			.gpio0  = 0x00009d76,
+			.audioroute = 1,
+		},{
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+			.gpio0  = 0x00009d76,
+			.audioroute = 1,
+		}},
+		.radio = {
+			.type   = CX88_RADIO,
+			.gpio0  = 0x00009d00,
+			.audioroute = 1,
+		},
+		.mpeg           = CX88_MPEG_BLACKBIRD,
+	},
+	[CX88_BOARD_IODATA_GVBCTV7E] = {
+		.name           = "IODATA GV/BCTV7E",
+		.tuner_type     = TUNER_PHILIPS_FQ1286,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.input          = {{
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 1,
+			.gpio1  = 0x0000e03f,
+		},{
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 2,
+			.gpio1  = 0x0000e07f,
+		},{
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 3,
+			.gpio1  = 0x0000e07f,
+		}}
+	},
+	[CX88_BOARD_PIXELVIEW_PLAYTV_ULTRA_PRO] = {
+		.name           = "PixelView PlayTV Ultra Pro (Stereo)",
+		/* May be also TUNER_YMEC_TVF_5533MF for NTSC/M or PAL/M */
+		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+		.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,
+			.gpio0  = 0xbf61,  /* internal decoder */
+		},{
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 1,
+			.gpio0	= 0xbf63,
+		},{
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+			.gpio0	= 0xbf63,
+		}},
+		.radio = {
+			 .type  = CX88_RADIO,
+			 .gpio0 = 0xbf60,
+		 },
+	},
+	[CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T] = {
+		.name           = "DViCO FusionHDTV 3 Gold-T",
+		.tuner_type     = TUNER_THOMSON_DTT761X,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.input          = {{
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 0,
+			.gpio0  = 0x97ed,
+		},{
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 1,
+			.gpio0  = 0x97e9,
+		},{
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+			.gpio0  = 0x97e9,
+		}},
+		.mpeg           = CX88_MPEG_DVB,
+	},
+	[CX88_BOARD_ADSTECH_DVB_T_PCI] = {
+		.name           = "ADS Tech Instant TV DVB-T PCI",
+		.tuner_type     = TUNER_ABSENT,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.input          = {{
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 1,
+			.gpio0  = 0x0700,
+			.gpio2  = 0x0101,
+		},{
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+			.gpio0  = 0x0700,
+			.gpio2  = 0x0101,
+		}},
+		.mpeg           = CX88_MPEG_DVB,
+	},
+	[CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1] = {
+		.name           = "TerraTec Cinergy 1400 DVB-T",
+		.tuner_type     = TUNER_ABSENT,
+		.input          = {{
+			.type   = CX88_VMUX_DVB,
+			.vmux   = 0,
+		},{
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 2,
+		},{
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+		}},
+		.mpeg           = CX88_MPEG_DVB,
+	},
+	[CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD] = {
+		.name           = "DViCO FusionHDTV 5 Gold",
+		.tuner_type     = TUNER_LG_TDVS_H06XF, /* TDVS-H062F */
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.input          = {{
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 0,
+			.gpio0  = 0x87fd,
+		},{
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 1,
+			.gpio0  = 0x87f9,
+		},{
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+			.gpio0  = 0x87f9,
+		}},
+		.mpeg           = CX88_MPEG_DVB,
+	},
+	[CX88_BOARD_AVERMEDIA_ULTRATV_MC_550] = {
+		.name           = "AverMedia UltraTV Media Center PCI 550",
+		.tuner_type     = TUNER_PHILIPS_FM1236_MK3,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.input          = {{
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 0,
+			.gpio0  = 0x0000cd73,
+			.audioroute = 1,
+		},{
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 1,
+			.gpio0  = 0x0000cd73,
+			.audioroute = 1,
+		},{
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 3,
+			.gpio0  = 0x0000cdb3,
+			.audioroute = 1,
+		}},
+		.radio = {
+			.type   = CX88_RADIO,
+			.vmux   = 2,
+			.gpio0  = 0x0000cdf3,
+			.audioroute = 1,
+		},
+		.mpeg           = CX88_MPEG_BLACKBIRD,
+	},
+	[CX88_BOARD_KWORLD_VSTREAM_EXPERT_DVD] = {
+		 /* Alexander Wold <awold@bigfoot.com> */
+		 .name           = "Kworld V-Stream Xpert DVD",
+		 .tuner_type     = UNSET,
+		 .input          = {{
+			 .type   = CX88_VMUX_COMPOSITE1,
+			 .vmux   = 1,
+			 .gpio0  = 0x03000000,
+			 .gpio1  = 0x01000000,
+			 .gpio2  = 0x02000000,
+			 .gpio3  = 0x00100000,
+		 },{
+			 .type   = CX88_VMUX_SVIDEO,
+			 .vmux   = 2,
+			 .gpio0  = 0x03000000,
+			 .gpio1  = 0x01000000,
+			 .gpio2  = 0x02000000,
+			 .gpio3  = 0x00100000,
+		 }},
+	},
+	[CX88_BOARD_ATI_HDTVWONDER] = {
+		.name           = "ATI HDTV Wonder",
+		.tuner_type     = TUNER_PHILIPS_TUV1236D,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.input          = {{
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 0,
+			.gpio0  = 0x00000ff7,
+			.gpio1  = 0x000000ff,
+			.gpio2  = 0x00000001,
+			.gpio3  = 0x00000000,
+		},{
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 1,
+			.gpio0  = 0x00000ffe,
+			.gpio1  = 0x000000ff,
+			.gpio2  = 0x00000001,
+			.gpio3  = 0x00000000,
+		},{
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+			.gpio0  = 0x00000ffe,
+			.gpio1  = 0x000000ff,
+			.gpio2  = 0x00000001,
+			.gpio3  = 0x00000000,
+		}},
+		.mpeg           = CX88_MPEG_DVB,
+	},
+	[CX88_BOARD_WINFAST_DTV1000] = {
+		.name           = "WinFast DTV1000-T",
+		.tuner_type     = TUNER_ABSENT,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.input          = {{
+			.type   = CX88_VMUX_DVB,
+			.vmux   = 0,
+		},{
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 1,
+		},{
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+		}},
+		.mpeg           = CX88_MPEG_DVB,
+	},
+	[CX88_BOARD_AVERTV_303] = {
+		.name           = "AVerTV 303 (M126)",
+		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.input          = {{
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 0,
+			.gpio0  = 0x00ff,
+			.gpio1  = 0xe09f,
+			.gpio2  = 0x0010,
+			.gpio3  = 0x0000,
+		},{
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 1,
+			.gpio0  = 0x00ff,
+			.gpio1  = 0xe05f,
+			.gpio2  = 0x0010,
+			.gpio3  = 0x0000,
+		},{
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+			.gpio0  = 0x00ff,
+			.gpio1  = 0xe05f,
+			.gpio2  = 0x0010,
+			.gpio3  = 0x0000,
+		}},
+	},
+	[CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1] = {
+		.name		= "Hauppauge Nova-S-Plus DVB-S",
+		.tuner_type	= TUNER_ABSENT,
+		.radio_type	= UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.audio_chip	= V4L2_IDENT_WM8775,
+		.i2sinputcntl   = 2,
+		.input		= {{
+			.type	= CX88_VMUX_DVB,
+			.vmux	= 0,
+			/* 2: Line-In */
+			.audioroute = 2,
+		},{
+			.type	= CX88_VMUX_COMPOSITE1,
+			.vmux	= 1,
+			/* 2: Line-In */
+			.audioroute = 2,
+		},{
+			.type	= CX88_VMUX_SVIDEO,
+			.vmux	= 2,
+			/* 2: Line-In */
+			.audioroute = 2,
+		}},
+		.mpeg           = CX88_MPEG_DVB,
+	},
+	[CX88_BOARD_HAUPPAUGE_NOVASE2_S1] = {
+		.name		= "Hauppauge Nova-SE2 DVB-S",
+		.tuner_type	= TUNER_ABSENT,
+		.radio_type	= UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.input		= {{
+			.type	= CX88_VMUX_DVB,
+			.vmux	= 0,
+		}},
+		.mpeg           = CX88_MPEG_DVB,
+	},
+	[CX88_BOARD_KWORLD_DVBS_100] = {
+		.name		= "KWorld DVB-S 100",
+		.tuner_type	= TUNER_ABSENT,
+		.radio_type	= UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.audio_chip = V4L2_IDENT_WM8775,
+		.input		= {{
+			.type	= CX88_VMUX_DVB,
+			.vmux	= 0,
+			/* 2: Line-In */
+			.audioroute = 2,
+		},{
+			.type	= CX88_VMUX_COMPOSITE1,
+			.vmux	= 1,
+			/* 2: Line-In */
+			.audioroute = 2,
+		},{
+			.type	= CX88_VMUX_SVIDEO,
+			.vmux	= 2,
+			/* 2: Line-In */
+			.audioroute = 2,
+		}},
+		.mpeg           = CX88_MPEG_DVB,
+	},
+	[CX88_BOARD_HAUPPAUGE_HVR1100] = {
+		.name		= "Hauppauge WinTV-HVR1100 DVB-T/Hybrid",
+		.tuner_type     = TUNER_PHILIPS_FMD1216ME_MK3,
+		.radio_type	= UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.input		= {{
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 0,
+		},{
+			.type	= CX88_VMUX_COMPOSITE1,
+			.vmux	= 1,
+		},{
+			.type	= CX88_VMUX_SVIDEO,
+			.vmux	= 2,
+		}},
+		/* fixme: Add radio support */
+		.mpeg           = CX88_MPEG_DVB,
+	},
+	[CX88_BOARD_HAUPPAUGE_HVR1100LP] = {
+		.name		= "Hauppauge WinTV-HVR1100 DVB-T/Hybrid (Low Profile)",
+		.tuner_type     = TUNER_PHILIPS_FMD1216ME_MK3,
+		.radio_type	= UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.input		= {{
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 0,
+		},{
+			.type	= CX88_VMUX_COMPOSITE1,
+			.vmux	= 1,
+		}},
+		/* fixme: Add radio support */
+		.mpeg           = CX88_MPEG_DVB,
+	},
+	[CX88_BOARD_DNTV_LIVE_DVB_T_PRO] = {
+		.name           = "digitalnow DNTV Live! DVB-T Pro",
+		.tuner_type     = TUNER_PHILIPS_FMD1216ME_MK3,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE |
+				  TDA9887_PORT2_ACTIVE,
+		.input          = {{
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 0,
+			.gpio0  = 0xf80808,
+		},{
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 1,
+			.gpio0	= 0xf80808,
+		},{
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+			.gpio0	= 0xf80808,
+		}},
+		.radio = {
+			 .type  = CX88_RADIO,
+			 .gpio0 = 0xf80808,
+		},
+		.mpeg           = CX88_MPEG_DVB,
+	},
+	[CX88_BOARD_KWORLD_DVB_T_CX22702] = {
+		/* Kworld V-stream Xpert DVB-T with Thomson tuner */
+		/* DTT 7579 Conexant CX22702-19 Conexant CX2388x  */
+		/* Manenti Marco <marco_manenti@colman.it> */
+		.name           = "KWorld/VStream XPert DVB-T with cx22702",
+		.tuner_type     = TUNER_ABSENT,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.input          = {{
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 1,
+			.gpio0  = 0x0700,
+			.gpio2  = 0x0101,
+		},{
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+			.gpio0  = 0x0700,
+			.gpio2  = 0x0101,
+		}},
+		.mpeg           = CX88_MPEG_DVB,
+	},
+	[CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL] = {
+		.name           = "DViCO FusionHDTV DVB-T Dual Digital",
+		.tuner_type     = TUNER_ABSENT, /* No analog tuner */
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.input          = {{
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 1,
+			.gpio0  = 0x000067df,
+		 },{
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+			.gpio0  = 0x000067df,
+		}},
+		.mpeg           = CX88_MPEG_DVB,
+	},
+	[CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT] = {
+		.name           = "KWorld HardwareMpegTV XPert",
+		.tuner_type     = TUNER_PHILIPS_TDA8290,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.input          = {{
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 0,
+			.gpio0  = 0x3de2,
+			.gpio2  = 0x00ff,
+		},{
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 1,
+			.gpio0  = 0x3de6,
+			.audioroute = 1,
+		},{
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+			.gpio0  = 0x3de6,
+			.audioroute = 1,
+		}},
+		.radio = {
+			.type   = CX88_RADIO,
+			.gpio0  = 0x3de6,
+			.gpio2  = 0x00ff,
+		},
+		.mpeg           = CX88_MPEG_BLACKBIRD,
+	},
+	[CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID] = {
+		.name           = "DViCO FusionHDTV DVB-T Hybrid",
+		.tuner_type     = TUNER_THOMSON_FE6600,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.input          = {{
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 0,
+			.gpio0  = 0x0000a75f,
+		},{
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 1,
+			.gpio0  = 0x0000a75b,
+		},{
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+			.gpio0  = 0x0000a75b,
+		}},
+		.mpeg           = CX88_MPEG_DVB,
+	},
+	[CX88_BOARD_PCHDTV_HD5500] = {
+		.name           = "pcHDTV HD5500 HDTV",
+		.tuner_type     = TUNER_LG_TDVS_H06XF, /* TDVS-H064F */
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.input          = {{
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 0,
+			.gpio0  = 0x87fd,
+		},{
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 1,
+			.gpio0  = 0x87f9,
+		},{
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+			.gpio0  = 0x87f9,
+		}},
+		.mpeg           = CX88_MPEG_DVB,
+	},
+	[CX88_BOARD_KWORLD_MCE200_DELUXE] = {
+		/* FIXME: tested TV input only, disabled composite,
+		   svideo and radio until they can be tested also. */
+		.name           = "Kworld MCE 200 Deluxe",
+		.tuner_type     = TUNER_TENA_9533_DI,
+		.radio_type     = UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.input          = {{
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 0,
+			.gpio0  = 0x0000BDE6
+		}},
+		.mpeg           = CX88_MPEG_BLACKBIRD,
+	},
+	[CX88_BOARD_PIXELVIEW_PLAYTV_P7000] = {
+		/* FIXME: SVideo, Composite and FM inputs are untested */
+		.name           = "PixelView PlayTV P7000",
+		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE |
+				  TDA9887_PORT2_ACTIVE,
+		.input          = {{
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 0,
+			.gpio0  = 0x5da6,
+		}},
+		.mpeg           = CX88_MPEG_BLACKBIRD,
+	},
+	[CX88_BOARD_NPGTECH_REALTV_TOP10FM] = {
+		.name           = "NPG Tech Real TV FM Top 10",
+		.tuner_type     = TUNER_TNF_5335MF, /* Actually a TNF9535 */
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.input          = {{
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 0,
+			.gpio0	= 0x0788,
+		},{
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 1,
+			.gpio0	= 0x078b,
+		},{
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+			.gpio0	= 0x078b,
+		}},
+		.radio = {
+			 .type  = CX88_RADIO,
+			 .gpio0 = 0x074a,
+		},
+	},
+	[CX88_BOARD_WINFAST_DTV2000H] = {
+		.name           = "WinFast DTV2000 H",
+		.tuner_type     = TUNER_PHILIPS_FMD1216ME_MK3,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.input          = {{
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 0,
+			.gpio0  = 0x00017304,
+			.gpio1  = 0x00008203,
+			.gpio2  = 0x00017304,
+			.gpio3  = 0x02000000,
+		}, {
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 1,
+			.gpio0  = 0x0001d701,
+			.gpio1  = 0x0000b207,
+			.gpio2  = 0x0001d701,
+			.gpio3  = 0x02000000,
+		}, {
+			.type   = CX88_VMUX_COMPOSITE2,
+			.vmux   = 2,
+			.gpio0  = 0x0001d503,
+			.gpio1  = 0x0000b207,
+			.gpio2  = 0x0001d503,
+			.gpio3  = 0x02000000,
+		}, {
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 3,
+			.gpio0  = 0x0001d701,
+			.gpio1  = 0x0000b207,
+			.gpio2  = 0x0001d701,
+			.gpio3  = 0x02000000,
+		}},
+		.radio = {
+			 .type  = CX88_RADIO,
+			 .gpio0 = 0x00015702,
+			 .gpio1 = 0x0000f207,
+			 .gpio2 = 0x00015702,
+			 .gpio3 = 0x02000000,
+		},
+		.mpeg           = CX88_MPEG_DVB,
+	},
+	[CX88_BOARD_WINFAST_DTV2000H_J] = {
+		.name           = "WinFast DTV2000 H rev. J",
+		.tuner_type     = TUNER_PHILIPS_FMD1216MEX_MK3,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.input          = {{
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 0,
+			.gpio0  = 0x00017300,
+			.gpio1  = 0x00008207,
+			.gpio2	= 0x00000000,
+			.gpio3  = 0x02000000,
+		},{
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 0,
+			.gpio0  = 0x00018300,
+			.gpio1  = 0x0000f207,
+			.gpio2	= 0x00017304,
+			.gpio3  = 0x02000000,
+		},{
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 1,
+			.gpio0  = 0x00018301,
+			.gpio1  = 0x0000f207,
+			.gpio2	= 0x00017304,
+			.gpio3  = 0x02000000,
+		},{
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+			.gpio0  = 0x00018301,
+			.gpio1  = 0x0000f207,
+			.gpio2	= 0x00017304,
+			.gpio3  = 0x02000000,
+		}},
+		.radio = {
+			 .type  = CX88_RADIO,
+			 .gpio0 = 0x00015702,
+			 .gpio1 = 0x0000f207,
+			 .gpio2 = 0x00015702,
+			 .gpio3 = 0x02000000,
+		},
+		.mpeg           = CX88_MPEG_DVB,
+	},
+	[CX88_BOARD_GENIATECH_DVBS] = {
+		.name          = "Geniatech DVB-S",
+		.tuner_type    = TUNER_ABSENT,
+		.radio_type    = UNSET,
+		.tuner_addr    = ADDR_UNSET,
+		.radio_addr    = ADDR_UNSET,
+		.input  = {{
+			.type  = CX88_VMUX_DVB,
+			.vmux  = 0,
+		},{
+			.type  = CX88_VMUX_COMPOSITE1,
+			.vmux  = 1,
+		}},
+		.mpeg           = CX88_MPEG_DVB,
+	},
+	[CX88_BOARD_HAUPPAUGE_HVR3000] = {
+		.name           = "Hauppauge WinTV-HVR3000 TriMode Analog/DVB-S/DVB-T",
+		.tuner_type     = TUNER_PHILIPS_FMD1216ME_MK3,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.audio_chip     = V4L2_IDENT_WM8775,
+		.input          = {{
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 0,
+			.gpio0  = 0x84bf,
+			/* 1: TV Audio / FM Mono */
+			.audioroute = 1,
+		},{
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 1,
+			.gpio0  = 0x84bf,
+			/* 2: Line-In */
+			.audioroute = 2,
+		},{
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+			.gpio0  = 0x84bf,
+			/* 2: Line-In */
+			.audioroute = 2,
+		}},
+		.radio = {
+			.type   = CX88_RADIO,
+			.gpio0	= 0x84bf,
+			/* 4: FM Stereo (untested) */
+			.audioroute = 8,
+		},
+		.mpeg           = CX88_MPEG_DVB,
+		.num_frontends	= 2,
+	},
+	[CX88_BOARD_NORWOOD_MICRO] = {
+		.name           = "Norwood Micro TV Tuner",
+		.tuner_type     = TUNER_TNF_5335MF,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.input          = {{
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 0,
+			.gpio0  = 0x0709,
+		},{
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 1,
+			.gpio0  = 0x070b,
+		},{
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+			.gpio0  = 0x070b,
+		}},
+	},
+	[CX88_BOARD_TE_DTV_250_OEM_SWANN] = {
+		.name           = "Shenzhen Tungsten Ages Tech TE-DTV-250 / Swann OEM",
+		.tuner_type     = TUNER_LG_PAL_NEW_TAPC,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.input          = {{
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 0,
+			.gpio0  = 0x003fffff,
+			.gpio1  = 0x00e00000,
+			.gpio2  = 0x003fffff,
+			.gpio3  = 0x02000000,
+		},{
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 1,
+			.gpio0  = 0x003fffff,
+			.gpio1  = 0x00e00000,
+			.gpio2  = 0x003fffff,
+			.gpio3  = 0x02000000,
+		},{
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+			.gpio0  = 0x003fffff,
+			.gpio1  = 0x00e00000,
+			.gpio2  = 0x003fffff,
+			.gpio3  = 0x02000000,
+		}},
+	},
+	[CX88_BOARD_HAUPPAUGE_HVR1300] = {
+		.name		= "Hauppauge WinTV-HVR1300 DVB-T/Hybrid MPEG Encoder",
+		.tuner_type     = TUNER_PHILIPS_FMD1216ME_MK3,
+		.radio_type	= UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.audio_chip     = V4L2_IDENT_WM8775,
+		/*
+		 * gpio0 as reported by Mike Crash <mike AT mikecrash.com>
+		 */
+		.input		= {{
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 0,
+			.gpio0	= 0xef88,
+			/* 1: TV Audio / FM Mono */
+			.audioroute = 1,
+		},{
+			.type	= CX88_VMUX_COMPOSITE1,
+			.vmux	= 1,
+			.gpio0	= 0xef88,
+			/* 2: Line-In */
+			.audioroute = 2,
+		},{
+			.type	= CX88_VMUX_SVIDEO,
+			.vmux	= 2,
+			.gpio0	= 0xef88,
+			/* 2: Line-In */
+			.audioroute = 2,
+		}},
+		.mpeg           = CX88_MPEG_DVB | CX88_MPEG_BLACKBIRD,
+		.radio = {
+			.type   = CX88_RADIO,
+			.gpio0	= 0xef88,
+			/* 4: FM Stereo (untested) */
+			.audioroute = 8,
+		},
+	},
+	[CX88_BOARD_SAMSUNG_SMT_7020] = {
+		.name		= "Samsung SMT 7020 DVB-S",
+		.tuner_type	= TUNER_ABSENT,
+		.radio_type	= UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.input		= { {
+			.type	= CX88_VMUX_DVB,
+			.vmux	= 0,
+		} },
+		.mpeg           = CX88_MPEG_DVB,
+	},
+	[CX88_BOARD_ADSTECH_PTV_390] = {
+		.name           = "ADS Tech Instant Video PCI",
+		.tuner_type     = TUNER_ABSENT,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.input          = {{
+			.type   = CX88_VMUX_DEBUG,
+			.vmux   = 3,
+			.gpio0  = 0x04ff,
+		},{
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 1,
+			.gpio0  = 0x07fa,
+		},{
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+			.gpio0  = 0x07fa,
+		}},
+	},
+	[CX88_BOARD_PINNACLE_PCTV_HD_800i] = {
+		.name           = "Pinnacle PCTV HD 800i",
+		.tuner_type     = TUNER_XC5000,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.input          = {{
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 0,
+			.gpio0  = 0x04fb,
+			.gpio1  = 0x10ff,
+		},{
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 1,
+			.gpio0  = 0x04fb,
+			.gpio1  = 0x10ef,
+			.audioroute = 1,
+		},{
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+			.gpio0  = 0x04fb,
+			.gpio1  = 0x10ef,
+			.audioroute = 1,
+		}},
+		.mpeg           = CX88_MPEG_DVB,
+	},
+	[CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO] = {
+		.name           = "DViCO FusionHDTV 5 PCI nano",
+		/* xc3008 tuner, digital only for now */
+		.tuner_type     = TUNER_ABSENT,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.input          = {{
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 0,
+			.gpio0  = 0x000027df, /* Unconfirmed */
+		}, {
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 1,
+			.gpio0  = 0x000027df, /* Unconfirmed */
+			.audioroute = 1,
+		}, {
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+			.gpio0  = 0x000027df, /* Unconfirmed */
+			.audioroute = 1,
+		} },
+		.mpeg           = CX88_MPEG_DVB,
+	},
+	[CX88_BOARD_PINNACLE_HYBRID_PCTV] = {
+		.name           = "Pinnacle Hybrid PCTV",
+		.tuner_type     = TUNER_XC2028,
+		.tuner_addr     = 0x61,
+		.radio_type     = UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.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,
+	},
+	/* Terry Wu <terrywu2009@gmail.com> */
+	/* TV Audio :      set GPIO 2, 18, 19 value to 0, 1, 0 */
+	/* FM Audio :      set GPIO 2, 18, 19 value to 0, 0, 0 */
+	/* Line-in Audio : set GPIO 2, 18, 19 value to 0, 1, 1 */
+	/* Mute Audio :    set GPIO 2 value to 1               */
+	[CX88_BOARD_WINFAST_TV2000_XP_GLOBAL] = {
+		.name           = "Leadtek TV2000 XP Global",
+		.tuner_type     = TUNER_XC2028,
+		.tuner_addr     = 0x61,
+		.radio_type     = UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.input          = { {
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 0,
+			.gpio0  = 0x0400,       /* pin 2 = 0 */
+			.gpio1  = 0x0000,
+			.gpio2  = 0x0C04,       /* pin 18 = 1, pin 19 = 0 */
+			.gpio3  = 0x0000,
+		}, {
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 1,
+			.gpio0  = 0x0400,       /* pin 2 = 0 */
+			.gpio1  = 0x0000,
+			.gpio2  = 0x0C0C,       /* pin 18 = 1, pin 19 = 1 */
+			.gpio3  = 0x0000,
+		}, {
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+			.gpio0  = 0x0400,       /* pin 2 = 0 */
+			.gpio1  = 0x0000,
+			.gpio2  = 0x0C0C,       /* pin 18 = 1, pin 19 = 1 */
+			.gpio3  = 0x0000,
+		} },
+		.radio = {
+			.type   = CX88_RADIO,
+			.gpio0  = 0x0400,        /* pin 2 = 0 */
+			.gpio1  = 0x0000,
+			.gpio2  = 0x0C00,       /* pin 18 = 0, pin 19 = 0 */
+			.gpio3  = 0x0000,
+		},
+	},
+	[CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F36] = {
+		.name           = "Leadtek TV2000 XP Global (SC4100)",
+		.tuner_type     = TUNER_XC4000,
+		.tuner_addr     = 0x61,
+		.radio_type     = UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.input          = { {
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 0,
+			.gpio0  = 0x0400,       /* pin 2 = 0 */
+			.gpio1  = 0x0000,
+			.gpio2  = 0x0C04,       /* pin 18 = 1, pin 19 = 0 */
+			.gpio3  = 0x0000,
+		}, {
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 1,
+			.gpio0  = 0x0400,       /* pin 2 = 0 */
+			.gpio1  = 0x0000,
+			.gpio2  = 0x0C0C,       /* pin 18 = 1, pin 19 = 1 */
+			.gpio3  = 0x0000,
+		}, {
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+			.gpio0  = 0x0400,       /* pin 2 = 0 */
+			.gpio1  = 0x0000,
+			.gpio2  = 0x0C0C,       /* pin 18 = 1, pin 19 = 1 */
+			.gpio3  = 0x0000,
+		} },
+		.radio = {
+			.type   = CX88_RADIO,
+			.gpio0  = 0x0400,        /* pin 2 = 0 */
+			.gpio1  = 0x0000,
+			.gpio2  = 0x0C00,       /* pin 18 = 0, pin 19 = 0 */
+			.gpio3  = 0x0000,
+		},
+	},
+	[CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F43] = {
+		.name           = "Leadtek TV2000 XP Global (XC4100)",
+		.tuner_type     = TUNER_XC4000,
+		.tuner_addr     = 0x61,
+		.radio_type     = UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.input          = { {
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 0,
+			.gpio0  = 0x0400,       /* pin 2 = 0 */
+			.gpio1  = 0x6040,       /* pin 14 = 1, pin 13 = 0 */
+			.gpio2  = 0x0000,
+			.gpio3  = 0x0000,
+		}, {
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 1,
+			.gpio0  = 0x0400,       /* pin 2 = 0 */
+			.gpio1  = 0x6060,       /* pin 14 = 1, pin 13 = 1 */
+			.gpio2  = 0x0000,
+			.gpio3  = 0x0000,
+		}, {
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+			.gpio0  = 0x0400,       /* pin 2 = 0 */
+			.gpio1  = 0x6060,       /* pin 14 = 1, pin 13 = 1 */
+			.gpio2  = 0x0000,
+			.gpio3  = 0x0000,
+		} },
+		.radio = {
+			.type   = CX88_RADIO,
+			.gpio0  = 0x0400,        /* pin 2 = 0 */
+			.gpio1  = 0x6000,        /* pin 14 = 1, pin 13 = 0 */
+			.gpio2  = 0x0000,
+			.gpio3  = 0x0000,
+		},
+	},
+	[CX88_BOARD_POWERCOLOR_REAL_ANGEL] = {
+		.name           = "PowerColor RA330",	/* Long names may confuse LIRC. */
+		.tuner_type     = TUNER_XC2028,
+		.tuner_addr     = 0x61,
+		.input          = { {
+			.type   = CX88_VMUX_DEBUG,
+			.vmux   = 3,		/* Due to the way the cx88 driver is written,	*/
+			.gpio0 = 0x00ff,	/* there is no way to deactivate audio pass-	*/
+			.gpio1 = 0xf39d,	/* through without this entry. Furthermore, if	*/
+			.gpio3 = 0x0000,	/* the TV mux entry is first, you get audio	*/
+		}, {				/* from the tuner on boot for a little while.	*/
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 0,
+			.gpio0 = 0x00ff,
+			.gpio1 = 0xf35d,
+			.gpio3 = 0x0000,
+		}, {
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 1,
+			.gpio0 = 0x00ff,
+			.gpio1 = 0xf37d,
+			.gpio3 = 0x0000,
+		}, {
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+			.gpio0  = 0x000ff,
+			.gpio1  = 0x0f37d,
+			.gpio3  = 0x00000,
+		} },
+		.radio = {
+			.type   = CX88_RADIO,
+			.gpio0  = 0x000ff,
+			.gpio1  = 0x0f35d,
+			.gpio3  = 0x00000,
+		},
+	},
+	[CX88_BOARD_GENIATECH_X8000_MT] = {
+		/* Also PowerColor Real Angel 330 and Geniatech X800 OEM */
+		.name           = "Geniatech X8000-MT DVBT",
+		.tuner_type     = TUNER_XC2028,
+		.tuner_addr     = 0x61,
+		.input          = { {
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 0,
+			.gpio0  = 0x00000000,
+			.gpio1  = 0x00e3e341,
+			.gpio2  = 0x00000000,
+			.gpio3  = 0x00000000,
+		}, {
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 1,
+			.gpio0  = 0x00000000,
+			.gpio1  = 0x00e3e361,
+			.gpio2  = 0x00000000,
+			.gpio3  = 0x00000000,
+		}, {
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+			.gpio0  = 0x00000000,
+			.gpio1  = 0x00e3e361,
+			.gpio2  = 0x00000000,
+			.gpio3  = 0x00000000,
+		} },
+		.radio = {
+			.type   = CX88_RADIO,
+			.gpio0  = 0x00000000,
+			.gpio1  = 0x00e3e341,
+			.gpio2  = 0x00000000,
+			.gpio3  = 0x00000000,
+		},
+		.mpeg           = CX88_MPEG_DVB,
+	},
+	[CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO] = {
+		.name           = "DViCO FusionHDTV DVB-T PRO",
+		.tuner_type     = TUNER_XC2028,
+		.tuner_addr     = 0x61,
+		.radio_type     = UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.input          = { {
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 1,
+			.gpio0  = 0x000067df,
+		}, {
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+			.gpio0  = 0x000067df,
+		} },
+		.mpeg           = CX88_MPEG_DVB,
+	},
+	[CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD] = {
+		.name           = "DViCO FusionHDTV 7 Gold",
+		.tuner_type     = TUNER_XC5000,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.input          = {{
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 0,
+			.gpio0  = 0x10df,
+		},{
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 1,
+			.gpio0  = 0x16d9,
+		},{
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+			.gpio0  = 0x16d9,
+		}},
+		.mpeg           = CX88_MPEG_DVB,
+	},
+	[CX88_BOARD_PROLINK_PV_8000GT] = {
+		.name           = "Prolink Pixelview MPEG 8000GT",
+		.tuner_type     = TUNER_XC2028,
+		.tuner_addr     = 0x61,
+		.input          = { {
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 0,
+			.gpio0 = 0x0ff,
+			.gpio2 = 0x0cfb,
+		}, {
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 1,
+			.gpio2 = 0x0cfb,
+		}, {
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+			.gpio2 = 0x0cfb,
+		} },
+		.radio = {
+			.type   = CX88_RADIO,
+			.gpio2 = 0x0cfb,
+		},
+	},
+	[CX88_BOARD_PROLINK_PV_GLOBAL_XTREME] = {
+		.name           = "Prolink Pixelview Global Extreme",
+		.tuner_type     = TUNER_XC2028,
+		.tuner_addr     = 0x61,
+		.input          = { {
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 0,
+			.gpio0 = 0x04fb,
+			.gpio1 = 0x04080,
+			.gpio2 = 0x0cf7,
+		}, {
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 1,
+			.gpio0 = 0x04fb,
+			.gpio1 = 0x04080,
+			.gpio2 = 0x0cfb,
+		}, {
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+			.gpio0 = 0x04fb,
+			.gpio1 = 0x04080,
+			.gpio2 = 0x0cfb,
+		} },
+		.radio = {
+			.type   = CX88_RADIO,
+			.gpio0 = 0x04ff,
+			.gpio1 = 0x04080,
+			.gpio2 = 0x0cf7,
+		},
+	},
+	/* Both radio, analog and ATSC work with this board.
+	   However, for analog to work, s5h1409 gate should be open,
+	   otherwise, tuner-xc3028 won't be detected.
+	   A proper fix require using the newer i2c methods to add
+	   tuner-xc3028 without doing an i2c probe.
+	 */
+	[CX88_BOARD_KWORLD_ATSC_120] = {
+		.name           = "Kworld PlusTV HD PCI 120 (ATSC 120)",
+		.tuner_type     = TUNER_XC2028,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.input          = { {
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 0,
+			.gpio0  = 0x000000ff,
+			.gpio1  = 0x0000f35d,
+			.gpio2  = 0x00000000,
+		}, {
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 1,
+			.gpio0  = 0x000000ff,
+			.gpio1  = 0x0000f37e,
+			.gpio2  = 0x00000000,
+		}, {
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+			.gpio0  = 0x000000ff,
+			.gpio1  = 0x0000f37e,
+			.gpio2  = 0x00000000,
+		} },
+		.radio = {
+			.type   = CX88_RADIO,
+			.gpio0  = 0x000000ff,
+			.gpio1  = 0x0000f35d,
+			.gpio2  = 0x00000000,
+		},
+		.mpeg           = CX88_MPEG_DVB,
+	},
+	[CX88_BOARD_HAUPPAUGE_HVR4000] = {
+		.name           = "Hauppauge WinTV-HVR4000 DVB-S/S2/T/Hybrid",
+		.tuner_type     = TUNER_PHILIPS_FMD1216ME_MK3,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.audio_chip     = V4L2_IDENT_WM8775,
+		/*
+		 * GPIO0 (WINTV2000)
+		 *
+		 * Analogue     SAT     DVB-T
+		 * Antenna      0xc4bf  0xc4bb
+		 * Composite    0xc4bf  0xc4bb
+		 * S-Video      0xc4bf  0xc4bb
+		 * Composite1   0xc4ff  0xc4fb
+		 * S-Video1     0xc4ff  0xc4fb
+		 *
+		 * BIT  VALUE   FUNCTION GP{x}_IO
+		 * 0    1       I:?
+		 * 1    1       I:?
+		 * 2    1       O:MPEG PORT 0=DVB-T 1=DVB-S
+		 * 3    1       I:?
+		 * 4    1       I:?
+		 * 5    1       I:?
+		 * 6    0       O:INPUT SELECTOR 0=INTERNAL 1=EXPANSION
+		 * 7    1       O:DVB-T DEMOD RESET LOW
+		 *
+		 * BIT  VALUE   FUNCTION GP{x}_OE
+		 * 8    0       I
+		 * 9    0       I
+		 * a    1       O
+		 * b    0       I
+		 * c    0       I
+		 * d    0       I
+		 * e    1       O
+		 * f    1       O
+		 *
+		 * WM8775 ADC
+		 *
+		 * 1: TV Audio / FM Mono
+		 * 2: Line-In
+		 * 3: Line-In Expansion
+		 * 4: FM Stereo
+		 */
+		.input          = {{
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 0,
+			.gpio0  = 0xc4bf,
+			/* 1: TV Audio / FM Mono */
+			.audioroute = 1,
+		}, {
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 1,
+			.gpio0  = 0xc4bf,
+			/* 2: Line-In */
+			.audioroute = 2,
+		}, {
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+			.gpio0  = 0xc4bf,
+			/* 2: Line-In */
+			.audioroute = 2,
+		} },
+		.radio = {
+			.type   = CX88_RADIO,
+			.gpio0	= 0xc4bf,
+			/* 4: FM Stereo */
+			.audioroute = 8,
+		},
+		.mpeg           = CX88_MPEG_DVB,
+		.num_frontends	= 2,
+	},
+	[CX88_BOARD_HAUPPAUGE_HVR4000LITE] = {
+		.name           = "Hauppauge WinTV-HVR4000(Lite) DVB-S/S2",
+		.tuner_type     = UNSET,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.input          = {{
+			.type   = CX88_VMUX_DVB,
+			.vmux   = 0,
+		} },
+		.mpeg           = CX88_MPEG_DVB,
+	},
+	[CX88_BOARD_TEVII_S420] = {
+		.name           = "TeVii S420 DVB-S",
+		.tuner_type     = UNSET,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.input          = {{
+			.type   = CX88_VMUX_DVB,
+			.vmux   = 0,
+		} },
+		.mpeg           = CX88_MPEG_DVB,
+	},
+	[CX88_BOARD_TEVII_S460] = {
+		.name           = "TeVii S460 DVB-S/S2",
+		.tuner_type     = UNSET,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.input          = {{
+			.type   = CX88_VMUX_DVB,
+			.vmux   = 0,
+		} },
+		.mpeg           = CX88_MPEG_DVB,
+	},
+	[CX88_BOARD_TEVII_S464] = {
+		.name           = "TeVii S464 DVB-S/S2",
+		.tuner_type     = UNSET,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.input          = {{
+			.type   = CX88_VMUX_DVB,
+			.vmux   = 0,
+		} },
+		.mpeg           = CX88_MPEG_DVB,
+	},
+	[CX88_BOARD_OMICOM_SS4_PCI] = {
+		.name           = "Omicom SS4 DVB-S/S2 PCI",
+		.tuner_type     = UNSET,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.input          = {{
+			.type   = CX88_VMUX_DVB,
+			.vmux   = 0,
+		} },
+		.mpeg           = CX88_MPEG_DVB,
+	},
+	[CX88_BOARD_TBS_8910] = {
+		.name           = "TBS 8910 DVB-S",
+		.tuner_type     = UNSET,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.input          = {{
+			.type   = CX88_VMUX_DVB,
+			.vmux   = 0,
+		} },
+		.mpeg           = CX88_MPEG_DVB,
+	},
+	[CX88_BOARD_TBS_8920] = {
+		.name           = "TBS 8920 DVB-S/S2",
+		.tuner_type     = TUNER_ABSENT,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.input          = {{
+			.type   = CX88_VMUX_DVB,
+			.vmux   = 0,
+			.gpio0  = 0x8080,
+		} },
+		.mpeg           = CX88_MPEG_DVB,
+	},
+	[CX88_BOARD_PROF_6200] = {
+		.name           = "Prof 6200 DVB-S",
+		.tuner_type     = UNSET,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.input          = {{
+			.type   = CX88_VMUX_DVB,
+			.vmux   = 0,
+		} },
+		.mpeg           = CX88_MPEG_DVB,
+	},
+	[CX88_BOARD_PROF_7300] = {
+		.name           = "PROF 7300 DVB-S/S2",
+		.tuner_type     = UNSET,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.input          = {{
+			.type   = CX88_VMUX_DVB,
+			.vmux   = 0,
+		} },
+		.mpeg           = CX88_MPEG_DVB,
+	},
+	[CX88_BOARD_SATTRADE_ST4200] = {
+		.name           = "SATTRADE ST4200 DVB-S/S2",
+		.tuner_type     = UNSET,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.input          = {{
+			.type   = CX88_VMUX_DVB,
+			.vmux   = 0,
+		} },
+		.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     = UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.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,
+	},
+	[CX88_BOARD_HAUPPAUGE_IRONLY] = {
+		.name           = "Hauppauge WinTV-IR Only",
+		.tuner_type     = UNSET,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+	},
+	[CX88_BOARD_WINFAST_DTV1800H] = {
+		.name           = "Leadtek WinFast DTV1800 Hybrid",
+		.tuner_type     = TUNER_XC2028,
+		.radio_type     = UNSET,
+		.tuner_addr     = 0x61,
+		.radio_addr     = ADDR_UNSET,
+		/*
+		 * GPIO setting
+		 *
+		 *  2: mute (0=off,1=on)
+		 * 12: tuner reset pin
+		 * 13: audio source (0=tuner audio,1=line in)
+		 * 14: FM (0=on,1=off ???)
+		 */
+		.input          = {{
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 0,
+			.gpio0  = 0x0400,       /* pin 2 = 0 */
+			.gpio1  = 0x6040,       /* pin 13 = 0, pin 14 = 1 */
+			.gpio2  = 0x0000,
+		}, {
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 1,
+			.gpio0  = 0x0400,       /* pin 2 = 0 */
+			.gpio1  = 0x6060,       /* pin 13 = 1, pin 14 = 1 */
+			.gpio2  = 0x0000,
+		}, {
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+			.gpio0  = 0x0400,       /* pin 2 = 0 */
+			.gpio1  = 0x6060,       /* pin 13 = 1, pin 14 = 1 */
+			.gpio2  = 0x0000,
+		} },
+		.radio = {
+			.type   = CX88_RADIO,
+			.gpio0  = 0x0400,       /* pin 2 = 0 */
+			.gpio1  = 0x6000,       /* pin 13 = 0, pin 14 = 0 */
+			.gpio2  = 0x0000,
+		},
+		.mpeg           = CX88_MPEG_DVB,
+	},
+	[CX88_BOARD_WINFAST_DTV1800H_XC4000] = {
+		.name		= "Leadtek WinFast DTV1800 H (XC4000)",
+		.tuner_type	= TUNER_XC4000,
+		.radio_type	= UNSET,
+		.tuner_addr	= 0x61,
+		.radio_addr	= ADDR_UNSET,
+		/*
+		 * GPIO setting
+		 *
+		 *  2: mute (0=off,1=on)
+		 * 12: tuner reset pin
+		 * 13: audio source (0=tuner audio,1=line in)
+		 * 14: FM (0=on,1=off ???)
+		 */
+		.input		= {{
+			.type	= CX88_VMUX_TELEVISION,
+			.vmux	= 0,
+			.gpio0	= 0x0400,	/* pin 2 = 0 */
+			.gpio1	= 0x6040,	/* pin 13 = 0, pin 14 = 1 */
+			.gpio2	= 0x0000,
+		}, {
+			.type	= CX88_VMUX_COMPOSITE1,
+			.vmux	= 1,
+			.gpio0	= 0x0400,	/* pin 2 = 0 */
+			.gpio1	= 0x6060,	/* pin 13 = 1, pin 14 = 1 */
+			.gpio2	= 0x0000,
+		}, {
+			.type	= CX88_VMUX_SVIDEO,
+			.vmux	= 2,
+			.gpio0	= 0x0400,	/* pin 2 = 0 */
+			.gpio1	= 0x6060,	/* pin 13 = 1, pin 14 = 1 */
+			.gpio2	= 0x0000,
+		}},
+		.radio = {
+			.type	= CX88_RADIO,
+			.gpio0	= 0x0400,	/* pin 2 = 0 */
+			.gpio1	= 0x6000,	/* pin 13 = 0, pin 14 = 0 */
+			.gpio2	= 0x0000,
+		},
+		.mpeg		= CX88_MPEG_DVB,
+	},
+	[CX88_BOARD_WINFAST_DTV2000H_PLUS] = {
+		.name		= "Leadtek WinFast DTV2000 H PLUS",
+		.tuner_type	= TUNER_XC4000,
+		.radio_type	= UNSET,
+		.tuner_addr	= 0x61,
+		.radio_addr	= ADDR_UNSET,
+		/*
+		 * GPIO
+		 *   2: 1: mute audio
+		 *  12: 0: reset XC4000
+		 *  13: 1: audio input is line in (0: tuner)
+		 *  14: 0: FM radio
+		 *  16: 0: RF input is cable
+		 */
+		.input		= {{
+			.type	= CX88_VMUX_TELEVISION,
+			.vmux	= 0,
+			.gpio0	= 0x0403,
+			.gpio1	= 0xF0D7,
+			.gpio2	= 0x0101,
+			.gpio3	= 0x0000,
+		}, {
+			.type	= CX88_VMUX_CABLE,
+			.vmux	= 0,
+			.gpio0	= 0x0403,
+			.gpio1	= 0xF0D7,
+			.gpio2	= 0x0100,
+			.gpio3	= 0x0000,
+		}, {
+			.type	= CX88_VMUX_COMPOSITE1,
+			.vmux	= 1,
+			.gpio0	= 0x0403,	/* was 0x0407 */
+			.gpio1	= 0xF0F7,
+			.gpio2	= 0x0101,
+			.gpio3	= 0x0000,
+		}, {
+			.type	= CX88_VMUX_SVIDEO,
+			.vmux	= 2,
+			.gpio0	= 0x0403,	/* was 0x0407 */
+			.gpio1	= 0xF0F7,
+			.gpio2	= 0x0101,
+			.gpio3	= 0x0000,
+		}},
+		.radio = {
+			.type	= CX88_RADIO,
+			.gpio0	= 0x0403,
+			.gpio1	= 0xF097,
+			.gpio2	= 0x0100,
+			.gpio3	= 0x0000,
+		},
+		.mpeg		= CX88_MPEG_DVB,
+	},
+	[CX88_BOARD_PROF_7301] = {
+		.name           = "Prof 7301 DVB-S/S2",
+		.tuner_type     = UNSET,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.input          = { {
+			.type   = CX88_VMUX_DVB,
+			.vmux   = 0,
+		} },
+		.mpeg           = CX88_MPEG_DVB,
+	},
+	[CX88_BOARD_TWINHAN_VP1027_DVBS] = {
+		.name		= "Twinhan VP-1027 DVB-S",
+		.tuner_type     = TUNER_ABSENT,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.input          = {{
+		       .type   = CX88_VMUX_DVB,
+		       .vmux   = 0,
+		} },
+		.mpeg           = CX88_MPEG_DVB,
+	},
+};
+
+/* ------------------------------------------------------------------ */
+/* PCI subsystem IDs                                                  */
+
+static const struct cx88_subid cx88_subids[] = {
+	{
+		.subvendor = 0x0070,
+		.subdevice = 0x3400,
+		.card      = CX88_BOARD_HAUPPAUGE,
+	},{
+		.subvendor = 0x0070,
+		.subdevice = 0x3401,
+		.card      = CX88_BOARD_HAUPPAUGE,
+	},{
+		.subvendor = 0x14c7,
+		.subdevice = 0x0106,
+		.card      = CX88_BOARD_GDI,
+	},{
+		.subvendor = 0x14c7,
+		.subdevice = 0x0107, /* with mpeg encoder */
+		.card      = CX88_BOARD_GDI,
+	},{
+		.subvendor = PCI_VENDOR_ID_ATI,
+		.subdevice = 0x00f8,
+		.card      = CX88_BOARD_ATI_WONDER_PRO,
+	}, {
+		.subvendor = PCI_VENDOR_ID_ATI,
+		.subdevice = 0x00f9,
+		.card      = CX88_BOARD_ATI_WONDER_PRO,
+	}, {
+		.subvendor = 0x107d,
+		.subdevice = 0x6611,
+		.card      = CX88_BOARD_WINFAST2000XP_EXPERT,
+	},{
+		.subvendor = 0x107d,
+		.subdevice = 0x6613,	/* NTSC */
+		.card      = CX88_BOARD_WINFAST2000XP_EXPERT,
+	},{
+		.subvendor = 0x107d,
+		.subdevice = 0x6620,
+		.card      = CX88_BOARD_WINFAST_DV2000,
+	},{
+		.subvendor = 0x107d,
+		.subdevice = 0x663b,
+		.card      = CX88_BOARD_LEADTEK_PVR2000,
+	},{
+		.subvendor = 0x107d,
+		.subdevice = 0x663c,
+		.card      = CX88_BOARD_LEADTEK_PVR2000,
+	},{
+		.subvendor = 0x1461,
+		.subdevice = 0x000b,
+		.card      = CX88_BOARD_AVERTV_STUDIO_303,
+	},{
+		.subvendor = 0x1462,
+		.subdevice = 0x8606,
+		.card      = CX88_BOARD_MSI_TVANYWHERE_MASTER,
+	},{
+		.subvendor = 0x10fc,
+		.subdevice = 0xd003,
+		.card      = CX88_BOARD_IODATA_GVVCP3PCI,
+	},{
+		.subvendor = 0x1043,
+		.subdevice = 0x4823,  /* with mpeg encoder */
+		.card      = CX88_BOARD_ASUS_PVR_416,
+	},{
+		.subvendor = 0x17de,
+		.subdevice = 0x08a6,
+		.card      = CX88_BOARD_KWORLD_DVB_T,
+	},{
+		.subvendor = 0x18ac,
+		.subdevice = 0xd810,
+		.card      = CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q,
+	},{
+		.subvendor = 0x18ac,
+		.subdevice = 0xd820,
+		.card      = CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T,
+	},{
+		.subvendor = 0x18ac,
+		.subdevice = 0xdb00,
+		.card      = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1,
+	},{
+		.subvendor = 0x0070,
+		.subdevice = 0x9002,
+		.card      = CX88_BOARD_HAUPPAUGE_DVB_T1,
+	},{
+		.subvendor = 0x14f1,
+		.subdevice = 0x0187,
+		.card      = CX88_BOARD_CONEXANT_DVB_T1,
+	},{
+		.subvendor = 0x1540,
+		.subdevice = 0x2580,
+		.card      = CX88_BOARD_PROVIDEO_PV259,
+	},{
+		.subvendor = 0x18ac,
+		.subdevice = 0xdb10,
+		.card      = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS,
+	},{
+		.subvendor = 0x1554,
+		.subdevice = 0x4811,
+		.card      = CX88_BOARD_PIXELVIEW,
+	},{
+		.subvendor = 0x7063,
+		.subdevice = 0x3000, /* HD-3000 card */
+		.card      = CX88_BOARD_PCHDTV_HD3000,
+	},{
+		.subvendor = 0x17de,
+		.subdevice = 0xa8a6,
+		.card      = CX88_BOARD_DNTV_LIVE_DVB_T,
+	},{
+		.subvendor = 0x0070,
+		.subdevice = 0x2801,
+		.card      = CX88_BOARD_HAUPPAUGE_ROSLYN,
+	},{
+		.subvendor = 0x14f1,
+		.subdevice = 0x0342,
+		.card      = CX88_BOARD_DIGITALLOGIC_MEC,
+	},{
+		.subvendor = 0x10fc,
+		.subdevice = 0xd035,
+		.card      = CX88_BOARD_IODATA_GVBCTV7E,
+	},{
+		.subvendor = 0x1421,
+		.subdevice = 0x0334,
+		.card      = CX88_BOARD_ADSTECH_DVB_T_PCI,
+	},{
+		.subvendor = 0x153b,
+		.subdevice = 0x1166,
+		.card      = CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1,
+	},{
+		.subvendor = 0x18ac,
+		.subdevice = 0xd500,
+		.card      = CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD,
+	},{
+		.subvendor = 0x1461,
+		.subdevice = 0x8011,
+		.card      = CX88_BOARD_AVERMEDIA_ULTRATV_MC_550,
+	},{
+		.subvendor = PCI_VENDOR_ID_ATI,
+		.subdevice = 0xa101,
+		.card      = CX88_BOARD_ATI_HDTVWONDER,
+	},{
+		.subvendor = 0x107d,
+		.subdevice = 0x665f,
+		.card      = CX88_BOARD_WINFAST_DTV1000,
+	},{
+		.subvendor = 0x1461,
+		.subdevice = 0x000a,
+		.card      = CX88_BOARD_AVERTV_303,
+	},{
+		.subvendor = 0x0070,
+		.subdevice = 0x9200,
+		.card      = CX88_BOARD_HAUPPAUGE_NOVASE2_S1,
+	},{
+		.subvendor = 0x0070,
+		.subdevice = 0x9201,
+		.card      = CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1,
+	},{
+		.subvendor = 0x0070,
+		.subdevice = 0x9202,
+		.card      = CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1,
+	},{
+		.subvendor = 0x17de,
+		.subdevice = 0x08b2,
+		.card      = CX88_BOARD_KWORLD_DVBS_100,
+	},{
+		.subvendor = 0x0070,
+		.subdevice = 0x9400,
+		.card      = CX88_BOARD_HAUPPAUGE_HVR1100,
+	},{
+		.subvendor = 0x0070,
+		.subdevice = 0x9402,
+		.card      = CX88_BOARD_HAUPPAUGE_HVR1100,
+	},{
+		.subvendor = 0x0070,
+		.subdevice = 0x9800,
+		.card      = CX88_BOARD_HAUPPAUGE_HVR1100LP,
+	},{
+		.subvendor = 0x0070,
+		.subdevice = 0x9802,
+		.card      = CX88_BOARD_HAUPPAUGE_HVR1100LP,
+	},{
+		.subvendor = 0x0070,
+		.subdevice = 0x9001,
+		.card      = CX88_BOARD_HAUPPAUGE_DVB_T1,
+	},{
+		.subvendor = 0x1822,
+		.subdevice = 0x0025,
+		.card      = CX88_BOARD_DNTV_LIVE_DVB_T_PRO,
+	},{
+		.subvendor = 0x17de,
+		.subdevice = 0x08a1,
+		.card      = CX88_BOARD_KWORLD_DVB_T_CX22702,
+	},{
+		.subvendor = 0x18ac,
+		.subdevice = 0xdb50,
+		.card      = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL,
+	},{
+		.subvendor = 0x18ac,
+		.subdevice = 0xdb54,
+		.card      = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL,
+		/* Re-branded DViCO: DigitalNow DVB-T Dual */
+	},{
+		.subvendor = 0x18ac,
+		.subdevice = 0xdb11,
+		.card      = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS,
+		/* Re-branded DViCO: UltraView DVB-T Plus */
+	}, {
+		.subvendor = 0x18ac,
+		.subdevice = 0xdb30,
+		.card      = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO,
+	}, {
+		.subvendor = 0x17de,
+		.subdevice = 0x0840,
+		.card      = CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT,
+	},{
+		.subvendor = 0x1421,
+		.subdevice = 0x0305,
+		.card      = CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT,
+	},{
+		.subvendor = 0x18ac,
+		.subdevice = 0xdb40,
+		.card      = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID,
+	},{
+		.subvendor = 0x18ac,
+		.subdevice = 0xdb44,
+		.card      = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID,
+	},{
+		.subvendor = 0x7063,
+		.subdevice = 0x5500,
+		.card      = CX88_BOARD_PCHDTV_HD5500,
+	},{
+		.subvendor = 0x17de,
+		.subdevice = 0x0841,
+		.card      = CX88_BOARD_KWORLD_MCE200_DELUXE,
+	},{
+		.subvendor = 0x1822,
+		.subdevice = 0x0019,
+		.card      = CX88_BOARD_DNTV_LIVE_DVB_T_PRO,
+	},{
+		.subvendor = 0x1554,
+		.subdevice = 0x4813,
+		.card      = CX88_BOARD_PIXELVIEW_PLAYTV_P7000,
+	},{
+		.subvendor = 0x14f1,
+		.subdevice = 0x0842,
+		.card      = CX88_BOARD_NPGTECH_REALTV_TOP10FM,
+	},{
+		.subvendor = 0x107d,
+		.subdevice = 0x665e,
+		.card      = CX88_BOARD_WINFAST_DTV2000H,
+	},{
+		.subvendor = 0x107d,
+		.subdevice = 0x6f2b,
+		.card      = CX88_BOARD_WINFAST_DTV2000H_J,
+	},{
+		.subvendor = 0x18ac,
+		.subdevice = 0xd800, /* FusionHDTV 3 Gold (original revision) */
+		.card      = CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q,
+	},{
+		.subvendor = 0x14f1,
+		.subdevice = 0x0084,
+		.card      = CX88_BOARD_GENIATECH_DVBS,
+	},{
+		.subvendor = 0x0070,
+		.subdevice = 0x1404,
+		.card      = CX88_BOARD_HAUPPAUGE_HVR3000,
+	}, {
+		.subvendor = 0x18ac,
+		.subdevice = 0xdc00,
+		.card      = CX88_BOARD_SAMSUNG_SMT_7020,
+	}, {
+		.subvendor = 0x18ac,
+		.subdevice = 0xdccd,
+		.card      = CX88_BOARD_SAMSUNG_SMT_7020,
+	},{
+		.subvendor = 0x1461,
+		.subdevice = 0xc111, /* AverMedia M150-D */
+		/* This board is known to work with the ASUS PVR416 config */
+		.card      = CX88_BOARD_ASUS_PVR_416,
+	},{
+		.subvendor = 0xc180,
+		.subdevice = 0xc980,
+		.card      = CX88_BOARD_TE_DTV_250_OEM_SWANN,
+	},{
+		.subvendor = 0x0070,
+		.subdevice = 0x9600,
+		.card      = CX88_BOARD_HAUPPAUGE_HVR1300,
+	},{
+		.subvendor = 0x0070,
+		.subdevice = 0x9601,
+		.card      = CX88_BOARD_HAUPPAUGE_HVR1300,
+	},{
+		.subvendor = 0x0070,
+		.subdevice = 0x9602,
+		.card      = CX88_BOARD_HAUPPAUGE_HVR1300,
+	},{
+		.subvendor = 0x107d,
+		.subdevice = 0x6632,
+		.card      = CX88_BOARD_LEADTEK_PVR2000,
+	},{
+		.subvendor = 0x12ab,
+		.subdevice = 0x2300, /* Club3D Zap TV2100 */
+		.card      = CX88_BOARD_KWORLD_DVB_T_CX22702,
+	},{
+		.subvendor = 0x0070,
+		.subdevice = 0x9000,
+		.card      = CX88_BOARD_HAUPPAUGE_DVB_T1,
+	},{
+		.subvendor = 0x0070,
+		.subdevice = 0x1400,
+		.card      = CX88_BOARD_HAUPPAUGE_HVR3000,
+	},{
+		.subvendor = 0x0070,
+		.subdevice = 0x1401,
+		.card      = CX88_BOARD_HAUPPAUGE_HVR3000,
+	},{
+		.subvendor = 0x0070,
+		.subdevice = 0x1402,
+		.card      = CX88_BOARD_HAUPPAUGE_HVR3000,
+	},{
+		.subvendor = 0x1421,
+		.subdevice = 0x0341, /* ADS Tech InstantTV DVB-S */
+		.card      = CX88_BOARD_KWORLD_DVBS_100,
+	},{
+		.subvendor = 0x1421,
+		.subdevice = 0x0390,
+		.card      = CX88_BOARD_ADSTECH_PTV_390,
+	},{
+		.subvendor = 0x11bd,
+		.subdevice = 0x0051,
+		.card      = CX88_BOARD_PINNACLE_PCTV_HD_800i,
+	}, {
+		.subvendor = 0x18ac,
+		.subdevice = 0xd530,
+		.card      = CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO,
+	}, {
+		.subvendor = 0x12ab,
+		.subdevice = 0x1788,
+		.card      = CX88_BOARD_PINNACLE_HYBRID_PCTV,
+	}, {
+		.subvendor = 0x14f1,
+		.subdevice = 0xea3d,
+		.card      = CX88_BOARD_POWERCOLOR_REAL_ANGEL,
+	}, {
+		.subvendor = 0x107d,
+		.subdevice = 0x6f18,
+		.card      = CX88_BOARD_WINFAST_TV2000_XP_GLOBAL,
+	}, {
+		.subvendor = 0x14f1,
+		.subdevice = 0x8852,
+		.card      = CX88_BOARD_GENIATECH_X8000_MT,
+	}, {
+		.subvendor = 0x18ac,
+		.subdevice = 0xd610,
+		.card      = CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD,
+	}, {
+		.subvendor = 0x1554,
+		.subdevice = 0x4935,
+		.card      = CX88_BOARD_PROLINK_PV_8000GT,
+	}, {
+		.subvendor = 0x1554,
+		.subdevice = 0x4976,
+		.card      = CX88_BOARD_PROLINK_PV_GLOBAL_XTREME,
+	}, {
+		.subvendor = 0x17de,
+		.subdevice = 0x08c1,
+		.card      = CX88_BOARD_KWORLD_ATSC_120,
+	}, {
+		.subvendor = 0x0070,
+		.subdevice = 0x6900,
+		.card      = CX88_BOARD_HAUPPAUGE_HVR4000,
+	}, {
+		.subvendor = 0x0070,
+		.subdevice = 0x6904,
+		.card      = CX88_BOARD_HAUPPAUGE_HVR4000,
+	}, {
+		.subvendor = 0x0070,
+		.subdevice = 0x6902,
+		.card      = CX88_BOARD_HAUPPAUGE_HVR4000,
+	}, {
+		.subvendor = 0x0070,
+		.subdevice = 0x6905,
+		.card      = CX88_BOARD_HAUPPAUGE_HVR4000LITE,
+	}, {
+		.subvendor = 0x0070,
+		.subdevice = 0x6906,
+		.card      = CX88_BOARD_HAUPPAUGE_HVR4000LITE,
+	}, {
+		.subvendor = 0xd420,
+		.subdevice = 0x9022,
+		.card      = CX88_BOARD_TEVII_S420,
+	}, {
+		.subvendor = 0xd460,
+		.subdevice = 0x9022,
+		.card      = CX88_BOARD_TEVII_S460,
+	}, {
+		.subvendor = 0xd464,
+		.subdevice = 0x9022,
+		.card      = CX88_BOARD_TEVII_S464,
+	}, {
+		.subvendor = 0xA044,
+		.subdevice = 0x2011,
+		.card      = CX88_BOARD_OMICOM_SS4_PCI,
+	}, {
+		.subvendor = 0x8910,
+		.subdevice = 0x8888,
+		.card      = CX88_BOARD_TBS_8910,
+	}, {
+		.subvendor = 0x8920,
+		.subdevice = 0x8888,
+		.card      = CX88_BOARD_TBS_8920,
+	}, {
+		.subvendor = 0xb022,
+		.subdevice = 0x3022,
+		.card      = CX88_BOARD_PROF_6200,
+	}, {
+		.subvendor = 0xB033,
+		.subdevice = 0x3033,
+		.card      = CX88_BOARD_PROF_7300,
+	}, {
+		.subvendor = 0xb200,
+		.subdevice = 0x4200,
+		.card      = CX88_BOARD_SATTRADE_ST4200,
+	}, {
+		.subvendor = 0x153b,
+		.subdevice = 0x1177,
+		.card      = CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII,
+	}, {
+		.subvendor = 0x0070,
+		.subdevice = 0x9290,
+		.card      = CX88_BOARD_HAUPPAUGE_IRONLY,
+	}, {
+		.subvendor = 0x107d,
+		.subdevice = 0x6654,
+		.card      = CX88_BOARD_WINFAST_DTV1800H,
+	}, {
+		/* WinFast DTV1800 H with XC4000 tuner */
+		.subvendor = 0x107d,
+		.subdevice = 0x6f38,
+		.card      = CX88_BOARD_WINFAST_DTV1800H_XC4000,
+	}, {
+		.subvendor = 0x107d,
+		.subdevice = 0x6f42,
+		.card      = CX88_BOARD_WINFAST_DTV2000H_PLUS,
+	}, {
+		/* PVR2000 PAL Model [107d:6630] */
+		.subvendor = 0x107d,
+		.subdevice = 0x6630,
+		.card      = CX88_BOARD_LEADTEK_PVR2000,
+	}, {
+		/* PVR2000 PAL Model [107d:6638] */
+		.subvendor = 0x107d,
+		.subdevice = 0x6638,
+		.card      = CX88_BOARD_LEADTEK_PVR2000,
+	}, {
+		/* PVR2000 NTSC Model [107d:6631] */
+		.subvendor = 0x107d,
+		.subdevice = 0x6631,
+		.card      = CX88_BOARD_LEADTEK_PVR2000,
+	}, {
+		/* PVR2000 NTSC Model [107d:6637] */
+		.subvendor = 0x107d,
+		.subdevice = 0x6637,
+		.card      = CX88_BOARD_LEADTEK_PVR2000,
+	}, {
+		/* PVR2000 NTSC Model [107d:663d] */
+		.subvendor = 0x107d,
+		.subdevice = 0x663d,
+		.card      = CX88_BOARD_LEADTEK_PVR2000,
+	}, {
+		/* DV2000 NTSC Model [107d:6621] */
+		.subvendor = 0x107d,
+		.subdevice = 0x6621,
+		.card      = CX88_BOARD_WINFAST_DV2000,
+	}, {
+		/* TV2000 XP Global [107d:6618]  */
+		.subvendor = 0x107d,
+		.subdevice = 0x6618,
+		.card      = CX88_BOARD_WINFAST_TV2000_XP_GLOBAL,
+	}, {
+		/* TV2000 XP Global [107d:6618] */
+		.subvendor = 0x107d,
+		.subdevice = 0x6619,
+		.card      = CX88_BOARD_WINFAST_TV2000_XP_GLOBAL,
+	}, {
+		/* WinFast TV2000 XP Global with XC4000 tuner */
+		.subvendor = 0x107d,
+		.subdevice = 0x6f36,
+		.card      = CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F36,
+	}, {
+		/* WinFast TV2000 XP Global with XC4000 tuner and different GPIOs */
+		.subvendor = 0x107d,
+		.subdevice = 0x6f43,
+		.card      = CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F43,
+	}, {
+		.subvendor = 0xb034,
+		.subdevice = 0x3034,
+		.card      = CX88_BOARD_PROF_7301,
+	}, {
+		.subvendor = 0x1822,
+		.subdevice = 0x0023,
+		.card      = CX88_BOARD_TWINHAN_VP1027_DVBS,
+	},
+};
+
+/* ----------------------------------------------------------------------- */
+/* some leadtek specific stuff                                             */
+
+static void leadtek_eeprom(struct cx88_core *core, u8 *eeprom_data)
+{
+	if (eeprom_data[4] != 0x7d ||
+	    eeprom_data[5] != 0x10 ||
+	    eeprom_data[7] != 0x66) {
+		warn_printk(core, "Leadtek eeprom invalid.\n");
+		return;
+	}
+
+	/* Terry Wu <terrywu2009@gmail.com> */
+	switch (eeprom_data[6]) {
+	case 0x13: /* SSID 6613 for TV2000 XP Expert NTSC Model */
+	case 0x21: /* SSID 6621 for DV2000 NTSC Model */
+	case 0x31: /* SSID 6631 for PVR2000 NTSC Model */
+	case 0x37: /* SSID 6637 for PVR2000 NTSC Model */
+	case 0x3d: /* SSID 6637 for PVR2000 NTSC Model */
+		core->board.tuner_type = TUNER_PHILIPS_FM1236_MK3;
+		break;
+	default:
+		core->board.tuner_type = TUNER_PHILIPS_FM1216ME_MK3;
+		break;
+	}
+
+	info_printk(core, "Leadtek Winfast 2000XP Expert config: "
+		    "tuner=%d, eeprom[0]=0x%02x\n",
+		    core->board.tuner_type, eeprom_data[0]);
+}
+
+static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data)
+{
+	struct tveeprom tv;
+
+	tveeprom_hauppauge_analog(&core->i2c_client, &tv, eeprom_data);
+	core->board.tuner_type = tv.tuner_type;
+	core->tuner_formats = tv.tuner_formats;
+	core->board.radio.type = tv.has_radio ? CX88_RADIO : 0;
+
+	/* Make sure we support the board model */
+	switch (tv.model)
+	{
+	case 14009: /* WinTV-HVR3000 (Retail, IR, b/panel video, 3.5mm audio in) */
+	case 14019: /* WinTV-HVR3000 (Retail, IR Blaster, b/panel video, 3.5mm audio in) */
+	case 14029: /* WinTV-HVR3000 (Retail, IR, b/panel video, 3.5mm audio in - 880 bridge) */
+	case 14109: /* WinTV-HVR3000 (Retail, IR, b/panel video, 3.5mm audio in - low profile) */
+	case 14129: /* WinTV-HVR3000 (Retail, IR, b/panel video, 3.5mm audio in - 880 bridge - LP) */
+	case 14559: /* WinTV-HVR3000 (OEM, no IR, b/panel video, 3.5mm audio in) */
+	case 14569: /* WinTV-HVR3000 (OEM, no IR, no back panel video) */
+	case 14659: /* WinTV-HVR3000 (OEM, no IR, b/panel video, RCA audio in - Low profile) */
+	case 14669: /* WinTV-HVR3000 (OEM, no IR, no b/panel video - Low profile) */
+	case 28552: /* WinTV-PVR 'Roslyn' (No IR) */
+	case 34519: /* WinTV-PCI-FM */
+	case 69009:
+		/* WinTV-HVR4000 (DVBS/S2/T, Video and IR, back panel inputs) */
+	case 69100: /* WinTV-HVR4000LITE (DVBS/S2, IR) */
+	case 69500: /* WinTV-HVR4000LITE (DVBS/S2, No IR) */
+	case 69559:
+		/* WinTV-HVR4000 (DVBS/S2/T, Video no IR, back panel inputs) */
+	case 69569: /* WinTV-HVR4000 (DVBS/S2/T, Video no IR) */
+	case 90002: /* Nova-T-PCI (9002) */
+	case 92001: /* Nova-S-Plus (Video and IR) */
+	case 92002: /* Nova-S-Plus (Video and IR) */
+	case 90003: /* Nova-T-PCI (9002 No RF out) */
+	case 90500: /* Nova-T-PCI (oem) */
+	case 90501: /* Nova-T-PCI (oem/IR) */
+	case 92000: /* Nova-SE2 (OEM, No Video or IR) */
+	case 92900: /* WinTV-IROnly (No analog or digital Video inputs) */
+	case 94009: /* WinTV-HVR1100 (Video and IR Retail) */
+	case 94501: /* WinTV-HVR1100 (Video and IR OEM) */
+	case 96009: /* WinTV-HVR1300 (PAL Video, MPEG Video and IR RX) */
+	case 96019: /* WinTV-HVR1300 (PAL Video, MPEG Video and IR RX/TX) */
+	case 96559: /* WinTV-HVR1300 (PAL Video, MPEG Video no IR) */
+	case 96569: /* WinTV-HVR1300 () */
+	case 96659: /* WinTV-HVR1300 () */
+	case 98559: /* WinTV-HVR1100LP (Video no IR, Retail - Low Profile) */
+		/* known */
+		break;
+	case CX88_BOARD_SAMSUNG_SMT_7020:
+		cx_set(MO_GP0_IO, 0x008989FF);
+		break;
+	default:
+		warn_printk(core, "warning: unknown hauppauge model #%d\n",
+			    tv.model);
+		break;
+	}
+
+	info_printk(core, "hauppauge eeprom: model=%d\n", tv.model);
+}
+
+/* ----------------------------------------------------------------------- */
+/* some GDI (was: Modular Technology) specific stuff                       */
+
+static const struct {
+	int  id;
+	int  fm;
+	const char *name;
+} gdi_tuner[] = {
+	[ 0x01 ] = { .id   = TUNER_ABSENT,
+		     .name = "NTSC_M" },
+	[ 0x02 ] = { .id   = TUNER_ABSENT,
+		     .name = "PAL_B" },
+	[ 0x03 ] = { .id   = TUNER_ABSENT,
+		     .name = "PAL_I" },
+	[ 0x04 ] = { .id   = TUNER_ABSENT,
+		     .name = "PAL_D" },
+	[ 0x05 ] = { .id   = TUNER_ABSENT,
+		     .name = "SECAM" },
+
+	[ 0x10 ] = { .id   = TUNER_ABSENT,
+		     .fm   = 1,
+		     .name = "TEMIC_4049" },
+	[ 0x11 ] = { .id   = TUNER_TEMIC_4136FY5,
+		     .name = "TEMIC_4136" },
+	[ 0x12 ] = { .id   = TUNER_ABSENT,
+		     .name = "TEMIC_4146" },
+
+	[ 0x20 ] = { .id   = TUNER_PHILIPS_FQ1216ME,
+		     .fm   = 1,
+		     .name = "PHILIPS_FQ1216_MK3" },
+	[ 0x21 ] = { .id   = TUNER_ABSENT, .fm = 1,
+		     .name = "PHILIPS_FQ1236_MK3" },
+	[ 0x22 ] = { .id   = TUNER_ABSENT,
+		     .name = "PHILIPS_FI1236_MK3" },
+	[ 0x23 ] = { .id   = TUNER_ABSENT,
+		     .name = "PHILIPS_FI1216_MK3" },
+};
+
+static void gdi_eeprom(struct cx88_core *core, u8 *eeprom_data)
+{
+	const char *name = (eeprom_data[0x0d] < ARRAY_SIZE(gdi_tuner))
+		? gdi_tuner[eeprom_data[0x0d]].name : NULL;
+
+	info_printk(core, "GDI: tuner=%s\n", name ? name : "unknown");
+	if (NULL == name)
+		return;
+	core->board.tuner_type = gdi_tuner[eeprom_data[0x0d]].id;
+	core->board.radio.type = gdi_tuner[eeprom_data[0x0d]].fm ?
+		CX88_RADIO : 0;
+}
+
+/* ------------------------------------------------------------------- */
+/* some Divco specific stuff                                           */
+static int cx88_dvico_xc2028_callback(struct cx88_core *core,
+				      int command, int arg)
+{
+	switch (command) {
+	case XC2028_TUNER_RESET:
+		switch (core->boardnr) {
+		case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
+			/* GPIO-4 xc3028 tuner */
+
+			cx_set(MO_GP0_IO, 0x00001000);
+			cx_clear(MO_GP0_IO, 0x00000010);
+			msleep(100);
+			cx_set(MO_GP0_IO, 0x00000010);
+			msleep(100);
+			break;
+		default:
+			cx_write(MO_GP0_IO, 0x101000);
+			mdelay(5);
+			cx_set(MO_GP0_IO, 0x101010);
+		}
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+
+/* ----------------------------------------------------------------------- */
+/* some Geniatech specific stuff                                           */
+
+static int cx88_xc3028_geniatech_tuner_callback(struct cx88_core *core,
+						int command, int mode)
+{
+	switch (command) {
+	case XC2028_TUNER_RESET:
+		switch (INPUT(core->input).type) {
+		case CX88_RADIO:
+			break;
+		case CX88_VMUX_DVB:
+			cx_write(MO_GP1_IO, 0x030302);
+			mdelay(50);
+			break;
+		default:
+			cx_write(MO_GP1_IO, 0x030301);
+			mdelay(50);
+		}
+		cx_write(MO_GP1_IO, 0x101010);
+		mdelay(50);
+		cx_write(MO_GP1_IO, 0x101000);
+		mdelay(50);
+		cx_write(MO_GP1_IO, 0x101010);
+		mdelay(50);
+		return 0;
+	}
+	return -EINVAL;
+}
+
+static int cx88_xc3028_winfast1800h_callback(struct cx88_core *core,
+					     int command, int arg)
+{
+	switch (command) {
+	case XC2028_TUNER_RESET:
+		/* GPIO 12 (xc3028 tuner reset) */
+		cx_set(MO_GP1_IO, 0x1010);
+		mdelay(50);
+		cx_clear(MO_GP1_IO, 0x10);
+		mdelay(75);
+		cx_set(MO_GP1_IO, 0x10);
+		mdelay(75);
+		return 0;
+	}
+	return -EINVAL;
+}
+
+static int cx88_xc4000_winfast2000h_plus_callback(struct cx88_core *core,
+						  int command, int arg)
+{
+	switch (command) {
+	case XC4000_TUNER_RESET:
+		/* GPIO 12 (xc4000 tuner reset) */
+		cx_set(MO_GP1_IO, 0x1010);
+		mdelay(50);
+		cx_clear(MO_GP1_IO, 0x10);
+		mdelay(75);
+		cx_set(MO_GP1_IO, 0x10);
+		mdelay(75);
+		return 0;
+	}
+	return -EINVAL;
+}
+
+/* ------------------------------------------------------------------- */
+/* some Divco specific stuff                                           */
+static int cx88_pv_8000gt_callback(struct cx88_core *core,
+				   int command, int arg)
+{
+	switch (command) {
+	case XC2028_TUNER_RESET:
+		cx_write(MO_GP2_IO, 0xcf7);
+		mdelay(50);
+		cx_write(MO_GP2_IO, 0xef5);
+		mdelay(50);
+		cx_write(MO_GP2_IO, 0xcf7);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+/* some DViCO specific stuff                                               */
+
+static void dvico_fusionhdtv_hybrid_init(struct cx88_core *core)
+{
+	struct i2c_msg msg = { .addr = 0x45, .flags = 0 };
+	int i, err;
+	static u8 init_bufs[13][5] = {
+		{ 0x10, 0x00, 0x20, 0x01, 0x03 },
+		{ 0x10, 0x10, 0x01, 0x00, 0x21 },
+		{ 0x10, 0x10, 0x10, 0x00, 0xCA },
+		{ 0x10, 0x10, 0x12, 0x00, 0x08 },
+		{ 0x10, 0x10, 0x13, 0x00, 0x0A },
+		{ 0x10, 0x10, 0x16, 0x01, 0xC0 },
+		{ 0x10, 0x10, 0x22, 0x01, 0x3D },
+		{ 0x10, 0x10, 0x73, 0x01, 0x2E },
+		{ 0x10, 0x10, 0x72, 0x00, 0xC5 },
+		{ 0x10, 0x10, 0x71, 0x01, 0x97 },
+		{ 0x10, 0x10, 0x70, 0x00, 0x0F },
+		{ 0x10, 0x10, 0xB0, 0x00, 0x01 },
+		{ 0x03, 0x0C },
+	};
+
+	for (i = 0; i < ARRAY_SIZE(init_bufs); i++) {
+		msg.buf = init_bufs[i];
+		msg.len = (i != 12 ? 5 : 2);
+		err = i2c_transfer(&core->i2c_adap, &msg, 1);
+		if (err != 1) {
+			warn_printk(core, "dvico_fusionhdtv_hybrid_init buf %d "
+					  "failed (err = %d)!\n", i, err);
+			return;
+		}
+	}
+}
+
+static int cx88_xc2028_tuner_callback(struct cx88_core *core,
+				      int command, int arg)
+{
+	/* Board-specific callbacks */
+	switch (core->boardnr) {
+	case CX88_BOARD_POWERCOLOR_REAL_ANGEL:
+	case CX88_BOARD_GENIATECH_X8000_MT:
+	case CX88_BOARD_KWORLD_ATSC_120:
+		return cx88_xc3028_geniatech_tuner_callback(core,
+							command, arg);
+	case CX88_BOARD_PROLINK_PV_8000GT:
+	case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME:
+		return cx88_pv_8000gt_callback(core, command, arg);
+	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO:
+	case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
+		return cx88_dvico_xc2028_callback(core, command, arg);
+	case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL:
+	case CX88_BOARD_WINFAST_DTV1800H:
+		return cx88_xc3028_winfast1800h_callback(core, command, arg);
+	}
+
+	switch (command) {
+	case XC2028_TUNER_RESET:
+		switch (INPUT(core->input).type) {
+		case CX88_RADIO:
+			info_printk(core, "setting GPIO to radio!\n");
+			cx_write(MO_GP0_IO, 0x4ff);
+			mdelay(250);
+			cx_write(MO_GP2_IO, 0xff);
+			mdelay(250);
+			break;
+		case CX88_VMUX_DVB:	/* Digital TV*/
+		default:		/* Analog TV */
+			info_printk(core, "setting GPIO to TV!\n");
+			break;
+		}
+		cx_write(MO_GP1_IO, 0x101010);
+		mdelay(250);
+		cx_write(MO_GP1_IO, 0x101000);
+		mdelay(250);
+		cx_write(MO_GP1_IO, 0x101010);
+		mdelay(250);
+		return 0;
+	}
+	return -EINVAL;
+}
+
+static int cx88_xc4000_tuner_callback(struct cx88_core *core,
+				      int command, int arg)
+{
+	/* Board-specific callbacks */
+	switch (core->boardnr) {
+	case CX88_BOARD_WINFAST_DTV1800H_XC4000:
+	case CX88_BOARD_WINFAST_DTV2000H_PLUS:
+	case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F36:
+	case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F43:
+		return cx88_xc4000_winfast2000h_plus_callback(core,
+							      command, arg);
+	}
+	return -EINVAL;
+}
+
+/* ----------------------------------------------------------------------- */
+/* Tuner callback function. Currently only needed for the Pinnacle 	   *
+ * PCTV HD 800i with an xc5000 sillicon tuner. This is used for both	   *
+ * analog tuner attach (tuner-core.c) and dvb tuner attach (cx88-dvb.c)    */
+
+static int cx88_xc5000_tuner_callback(struct cx88_core *core,
+				      int command, int arg)
+{
+	switch (core->boardnr) {
+	case CX88_BOARD_PINNACLE_PCTV_HD_800i:
+		if (command == 0) { /* This is the reset command from xc5000 */
+
+			/* djh - According to the engineer at PCTV Systems,
+			   the xc5000 reset pin is supposed to be on GPIO12.
+			   However, despite three nights of effort, pulling
+			   that GPIO low didn't reset the xc5000.  While
+			   pulling MO_SRST_IO low does reset the xc5000, this
+			   also resets in the s5h1409 being reset as well.
+			   This causes tuning to always fail since the internal
+			   state of the s5h1409 does not match the driver's
+			   state.  Given that the only two conditions in which
+			   the driver performs a reset is during firmware load
+			   and powering down the chip, I am taking out the
+			   reset.  We know that the chip is being reset
+			   when the cx88 comes online, and not being able to
+			   do power management for this board is worse than
+			   not having any tuning at all. */
+			return 0;
+		} else {
+			err_printk(core, "xc5000: unknown tuner "
+				   "callback command.\n");
+			return -EINVAL;
+		}
+		break;
+	case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD:
+		if (command == 0) { /* This is the reset command from xc5000 */
+			cx_clear(MO_GP0_IO, 0x00000010);
+			msleep(10);
+			cx_set(MO_GP0_IO, 0x00000010);
+			return 0;
+		} else {
+			printk(KERN_ERR
+				"xc5000: unknown tuner callback command.\n");
+			return -EINVAL;
+		}
+		break;
+	}
+	return 0; /* Should never be here */
+}
+
+int cx88_tuner_callback(void *priv, int component, int command, int arg)
+{
+	struct i2c_algo_bit_data *i2c_algo = priv;
+	struct cx88_core *core;
+
+	if (!i2c_algo) {
+		printk(KERN_ERR "cx88: Error - i2c private data undefined.\n");
+		return -EINVAL;
+	}
+
+	core = i2c_algo->data;
+
+	if (!core) {
+		printk(KERN_ERR "cx88: Error - device struct undefined.\n");
+		return -EINVAL;
+	}
+
+	if (component != DVB_FRONTEND_COMPONENT_TUNER)
+		return -EINVAL;
+
+	switch (core->board.tuner_type) {
+		case TUNER_XC2028:
+			info_printk(core, "Calling XC2028/3028 callback\n");
+			return cx88_xc2028_tuner_callback(core, command, arg);
+		case TUNER_XC4000:
+			info_printk(core, "Calling XC4000 callback\n");
+			return cx88_xc4000_tuner_callback(core, command, arg);
+		case TUNER_XC5000:
+			info_printk(core, "Calling XC5000 callback\n");
+			return cx88_xc5000_tuner_callback(core, command, arg);
+	}
+	err_printk(core, "Error: Calling callback for tuner %d\n",
+		   core->board.tuner_type);
+	return -EINVAL;
+}
+EXPORT_SYMBOL(cx88_tuner_callback);
+
+/* ----------------------------------------------------------------------- */
+
+static void cx88_card_list(struct cx88_core *core, struct pci_dev *pci)
+{
+	int i;
+
+	if (0 == pci->subsystem_vendor &&
+	    0 == pci->subsystem_device) {
+		printk(KERN_ERR
+		       "%s: Your board has no valid PCI Subsystem ID and thus can't\n"
+		       "%s: be autodetected.  Please pass card=<n> insmod option to\n"
+		       "%s: workaround that.  Redirect complaints to the vendor of\n"
+		       "%s: the TV card.  Best regards,\n"
+		       "%s:         -- tux\n",
+		       core->name,core->name,core->name,core->name,core->name);
+	} else {
+		printk(KERN_ERR
+		       "%s: Your board isn't known (yet) to the driver.  You can\n"
+		       "%s: try to pick one of the existing card configs via\n"
+		       "%s: card=<n> insmod option.  Updating to the latest\n"
+		       "%s: version might help as well.\n",
+		       core->name,core->name,core->name,core->name);
+	}
+	err_printk(core, "Here is a list of valid choices for the card=<n> "
+		   "insmod option:\n");
+	for (i = 0; i < ARRAY_SIZE(cx88_boards); i++)
+		printk(KERN_ERR "%s:    card=%d -> %s\n",
+		       core->name, i, cx88_boards[i].name);
+}
+
+static void cx88_card_setup_pre_i2c(struct cx88_core *core)
+{
+	switch (core->boardnr) {
+	case CX88_BOARD_HAUPPAUGE_HVR1300:
+		/*
+		 * Bring the 702 demod up before i2c scanning/attach or devices are hidden
+		 * We leave here with the 702 on the bus
+		 *
+		 * "reset the IR receiver on GPIO[3]"
+		 * Reported by Mike Crash <mike AT mikecrash.com>
+		 */
+		cx_write(MO_GP0_IO, 0x0000ef88);
+		udelay(1000);
+		cx_clear(MO_GP0_IO, 0x00000088);
+		udelay(50);
+		cx_set(MO_GP0_IO, 0x00000088); /* 702 out of reset */
+		udelay(1000);
+		break;
+
+	case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME:
+	case CX88_BOARD_PROLINK_PV_8000GT:
+		cx_write(MO_GP2_IO, 0xcf7);
+		mdelay(50);
+		cx_write(MO_GP2_IO, 0xef5);
+		mdelay(50);
+		cx_write(MO_GP2_IO, 0xcf7);
+		msleep(10);
+		break;
+
+	case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD:
+		/* Enable the xc5000 tuner */
+		cx_set(MO_GP0_IO, 0x00001010);
+		break;
+
+	case CX88_BOARD_WINFAST_DTV2000H_J:
+	case CX88_BOARD_HAUPPAUGE_HVR3000:
+	case CX88_BOARD_HAUPPAUGE_HVR4000:
+		/* Init GPIO */
+		cx_write(MO_GP0_IO, core->board.input[0].gpio0);
+		udelay(1000);
+		cx_clear(MO_GP0_IO, 0x00000080);
+		udelay(50);
+		cx_set(MO_GP0_IO, 0x00000080); /* 702 out of reset */
+		udelay(1000);
+		break;
+
+	case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL:
+	case CX88_BOARD_WINFAST_DTV1800H:
+		cx88_xc3028_winfast1800h_callback(core, XC2028_TUNER_RESET, 0);
+		break;
+
+	case CX88_BOARD_WINFAST_DTV1800H_XC4000:
+	case CX88_BOARD_WINFAST_DTV2000H_PLUS:
+	case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F36:
+	case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F43:
+		cx88_xc4000_winfast2000h_plus_callback(core,
+						       XC4000_TUNER_RESET, 0);
+		break;
+
+	case CX88_BOARD_TWINHAN_VP1027_DVBS:
+		cx_write(MO_GP0_IO, 0x00003230);
+		cx_write(MO_GP0_IO, 0x00003210);
+		msleep(1);
+		cx_write(MO_GP0_IO, 0x00001230);
+		break;
+	}
+}
+
+/*
+ * Sets board-dependent xc3028 configuration
+ */
+void cx88_setup_xc3028(struct cx88_core *core, struct xc2028_ctrl *ctl)
+{
+	memset(ctl, 0, sizeof(*ctl));
+
+	ctl->fname   = XC2028_DEFAULT_FIRMWARE;
+	ctl->max_len = 64;
+
+	switch (core->boardnr) {
+	case CX88_BOARD_POWERCOLOR_REAL_ANGEL:
+		/* Now works with firmware version 2.7 */
+		if (core->i2c_algo.udelay < 16)
+			core->i2c_algo.udelay = 16;
+		break;
+	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO:
+	case CX88_BOARD_WINFAST_DTV1800H:
+		ctl->demod = XC3028_FE_ZARLINK456;
+		break;
+	case CX88_BOARD_KWORLD_ATSC_120:
+	case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
+		ctl->demod = XC3028_FE_OREN538;
+		break;
+	case CX88_BOARD_GENIATECH_X8000_MT:
+		/* FIXME: For this board, the xc3028 never recovers after being
+		   powered down (the reset GPIO probably is not set properly).
+		   We don't have access to the hardware so we cannot determine
+		   which GPIO is used for xc3028, so just disable power xc3028
+		   power management for now */
+		ctl->disable_power_mgmt = 1;
+		break;
+	case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL:
+	case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME:
+	case CX88_BOARD_PROLINK_PV_8000GT:
+		/*
+		 * Those boards uses non-MTS firmware
+		 */
+		break;
+	case CX88_BOARD_PINNACLE_HYBRID_PCTV:
+	case CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII:
+		ctl->demod = XC3028_FE_ZARLINK456;
+		ctl->mts = 1;
+		break;
+	default:
+		ctl->demod = XC3028_FE_OREN538;
+		ctl->mts = 1;
+	}
+}
+EXPORT_SYMBOL_GPL(cx88_setup_xc3028);
+
+static void cx88_card_setup(struct cx88_core *core)
+{
+	static u8 eeprom[256];
+	struct tuner_setup tun_setup;
+	unsigned int mode_mask = T_RADIO | T_ANALOG_TV;
+
+	memset(&tun_setup, 0, sizeof(tun_setup));
+
+	if (0 == core->i2c_rc) {
+		core->i2c_client.addr = 0xa0 >> 1;
+		tveeprom_read(&core->i2c_client, eeprom, sizeof(eeprom));
+	}
+
+	switch (core->boardnr) {
+	case CX88_BOARD_HAUPPAUGE:
+	case CX88_BOARD_HAUPPAUGE_ROSLYN:
+		if (0 == core->i2c_rc)
+			hauppauge_eeprom(core, eeprom+8);
+		break;
+	case CX88_BOARD_GDI:
+		if (0 == core->i2c_rc)
+			gdi_eeprom(core, eeprom);
+		break;
+	case CX88_BOARD_LEADTEK_PVR2000:
+	case CX88_BOARD_WINFAST_DV2000:
+	case CX88_BOARD_WINFAST2000XP_EXPERT:
+		if (0 == core->i2c_rc)
+			leadtek_eeprom(core, eeprom);
+		break;
+	case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
+	case CX88_BOARD_HAUPPAUGE_NOVASE2_S1:
+	case CX88_BOARD_HAUPPAUGE_DVB_T1:
+	case CX88_BOARD_HAUPPAUGE_HVR1100:
+	case CX88_BOARD_HAUPPAUGE_HVR1100LP:
+	case CX88_BOARD_HAUPPAUGE_HVR3000:
+	case CX88_BOARD_HAUPPAUGE_HVR1300:
+	case CX88_BOARD_HAUPPAUGE_HVR4000:
+	case CX88_BOARD_HAUPPAUGE_HVR4000LITE:
+	case CX88_BOARD_HAUPPAUGE_IRONLY:
+		if (0 == core->i2c_rc)
+			hauppauge_eeprom(core, eeprom);
+		break;
+	case CX88_BOARD_KWORLD_DVBS_100:
+		cx_write(MO_GP0_IO, 0x000007f8);
+		cx_write(MO_GP1_IO, 0x00000001);
+		break;
+	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO:
+		/* GPIO0:0 is hooked to demod reset */
+		/* GPIO0:4 is hooked to xc3028 reset */
+		cx_write(MO_GP0_IO, 0x00111100);
+		msleep(1);
+		cx_write(MO_GP0_IO, 0x00111111);
+		break;
+	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL:
+		/* GPIO0:6 is hooked to FX2 reset pin */
+		cx_set(MO_GP0_IO, 0x00004040);
+		cx_clear(MO_GP0_IO, 0x00000040);
+		msleep(1000);
+		cx_set(MO_GP0_IO, 0x00004040);
+		/* FALLTHROUGH */
+	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1:
+	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS:
+	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID:
+		/* GPIO0:0 is hooked to mt352 reset pin */
+		cx_set(MO_GP0_IO, 0x00000101);
+		cx_clear(MO_GP0_IO, 0x00000001);
+		msleep(1);
+		cx_set(MO_GP0_IO, 0x00000101);
+		if (0 == core->i2c_rc &&
+		    core->boardnr == CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID)
+			dvico_fusionhdtv_hybrid_init(core);
+		break;
+	case CX88_BOARD_KWORLD_DVB_T:
+	case CX88_BOARD_DNTV_LIVE_DVB_T:
+		cx_set(MO_GP0_IO, 0x00000707);
+		cx_set(MO_GP2_IO, 0x00000101);
+		cx_clear(MO_GP2_IO, 0x00000001);
+		msleep(1);
+		cx_clear(MO_GP0_IO, 0x00000007);
+		cx_set(MO_GP2_IO, 0x00000101);
+		break;
+	case CX88_BOARD_DNTV_LIVE_DVB_T_PRO:
+		cx_write(MO_GP0_IO, 0x00080808);
+		break;
+	case CX88_BOARD_ATI_HDTVWONDER:
+		if (0 == core->i2c_rc) {
+			/* enable tuner */
+			int i;
+			static const u8 buffer [][2] = {
+				{0x10,0x12},
+				{0x13,0x04},
+				{0x16,0x00},
+				{0x14,0x04},
+				{0x17,0x00}
+			};
+			core->i2c_client.addr = 0x0a;
+
+			for (i = 0; i < ARRAY_SIZE(buffer); i++)
+				if (2 != i2c_master_send(&core->i2c_client,
+							buffer[i],2))
+					warn_printk(core, "Unable to enable "
+						    "tuner(%i).\n", i);
+		}
+		break;
+	case CX88_BOARD_MSI_TVANYWHERE_MASTER:
+	{
+		struct v4l2_priv_tun_config tea5767_cfg;
+		struct tea5767_ctrl ctl;
+
+		memset(&ctl, 0, sizeof(ctl));
+
+		ctl.high_cut  = 1;
+		ctl.st_noise  = 1;
+		ctl.deemph_75 = 1;
+		ctl.xtal_freq = TEA5767_HIGH_LO_13MHz;
+
+		tea5767_cfg.tuner = TUNER_TEA5767;
+		tea5767_cfg.priv  = &ctl;
+
+		call_all(core, tuner, s_config, &tea5767_cfg);
+		break;
+	}
+	case  CX88_BOARD_TEVII_S420:
+	case  CX88_BOARD_TEVII_S460:
+	case  CX88_BOARD_TEVII_S464:
+	case  CX88_BOARD_OMICOM_SS4_PCI:
+	case  CX88_BOARD_TBS_8910:
+	case  CX88_BOARD_TBS_8920:
+	case  CX88_BOARD_PROF_6200:
+	case  CX88_BOARD_PROF_7300:
+	case  CX88_BOARD_PROF_7301:
+	case  CX88_BOARD_SATTRADE_ST4200:
+		cx_write(MO_GP0_IO, 0x8000);
+		msleep(100);
+		cx_write(MO_SRST_IO, 0);
+		msleep(10);
+		cx_write(MO_GP0_IO, 0x8080);
+		msleep(100);
+		cx_write(MO_SRST_IO, 1);
+		msleep(100);
+		break;
+	} /*end switch() */
+
+
+	/* Setup tuners */
+	if ((core->board.radio_type != UNSET)) {
+		tun_setup.mode_mask      = T_RADIO;
+		tun_setup.type           = core->board.radio_type;
+		tun_setup.addr           = core->board.radio_addr;
+		tun_setup.tuner_callback = cx88_tuner_callback;
+		call_all(core, tuner, s_type_addr, &tun_setup);
+		mode_mask &= ~T_RADIO;
+	}
+
+	if (core->board.tuner_type != TUNER_ABSENT) {
+		tun_setup.mode_mask      = mode_mask;
+		tun_setup.type           = core->board.tuner_type;
+		tun_setup.addr           = core->board.tuner_addr;
+		tun_setup.tuner_callback = cx88_tuner_callback;
+
+		call_all(core, tuner, s_type_addr, &tun_setup);
+	}
+
+	if (core->board.tda9887_conf) {
+		struct v4l2_priv_tun_config tda9887_cfg;
+
+		tda9887_cfg.tuner = TUNER_TDA9887;
+		tda9887_cfg.priv  = &core->board.tda9887_conf;
+
+		call_all(core, tuner, s_config, &tda9887_cfg);
+	}
+
+	if (core->board.tuner_type == TUNER_XC2028) {
+		struct v4l2_priv_tun_config  xc2028_cfg;
+		struct xc2028_ctrl           ctl;
+
+		/* Fills device-dependent initialization parameters */
+		cx88_setup_xc3028(core, &ctl);
+
+		/* Sends parameters to xc2028/3028 tuner */
+		memset(&xc2028_cfg, 0, sizeof(xc2028_cfg));
+		xc2028_cfg.tuner = TUNER_XC2028;
+		xc2028_cfg.priv  = &ctl;
+		info_printk(core, "Asking xc2028/3028 to load firmware %s\n",
+			    ctl.fname);
+		call_all(core, tuner, s_config, &xc2028_cfg);
+	}
+	call_all(core, core, s_power, 0);
+}
+
+/* ------------------------------------------------------------------ */
+
+static int cx88_pci_quirks(const char *name, struct pci_dev *pci)
+{
+	unsigned int lat = UNSET;
+	u8 ctrl = 0;
+	u8 value;
+
+	/* check pci quirks */
+	if (pci_pci_problems & PCIPCI_TRITON) {
+		printk(KERN_INFO "%s: quirk: PCIPCI_TRITON -- set TBFX\n",
+		       name);
+		ctrl |= CX88X_EN_TBFX;
+	}
+	if (pci_pci_problems & PCIPCI_NATOMA) {
+		printk(KERN_INFO "%s: quirk: PCIPCI_NATOMA -- set TBFX\n",
+		       name);
+		ctrl |= CX88X_EN_TBFX;
+	}
+	if (pci_pci_problems & PCIPCI_VIAETBF) {
+		printk(KERN_INFO "%s: quirk: PCIPCI_VIAETBF -- set TBFX\n",
+		       name);
+		ctrl |= CX88X_EN_TBFX;
+	}
+	if (pci_pci_problems & PCIPCI_VSFX) {
+		printk(KERN_INFO "%s: quirk: PCIPCI_VSFX -- set VSFX\n",
+		       name);
+		ctrl |= CX88X_EN_VSFX;
+	}
+#ifdef PCIPCI_ALIMAGIK
+	if (pci_pci_problems & PCIPCI_ALIMAGIK) {
+		printk(KERN_INFO "%s: quirk: PCIPCI_ALIMAGIK -- latency fixup\n",
+		       name);
+		lat = 0x0A;
+	}
+#endif
+
+	/* check insmod options */
+	if (UNSET != latency)
+		lat = latency;
+
+	/* apply stuff */
+	if (ctrl) {
+		pci_read_config_byte(pci, CX88X_DEVCTRL, &value);
+		value |= ctrl;
+		pci_write_config_byte(pci, CX88X_DEVCTRL, value);
+	}
+	if (UNSET != lat) {
+		printk(KERN_INFO "%s: setting pci latency timer to %d\n",
+		       name, latency);
+		pci_write_config_byte(pci, PCI_LATENCY_TIMER, latency);
+	}
+	return 0;
+}
+
+int cx88_get_resources(const struct cx88_core *core, struct pci_dev *pci)
+{
+	if (request_mem_region(pci_resource_start(pci,0),
+			       pci_resource_len(pci,0),
+			       core->name))
+		return 0;
+	printk(KERN_ERR
+	       "%s/%d: Can't get MMIO memory @ 0x%llx, subsystem: %04x:%04x\n",
+	       core->name, PCI_FUNC(pci->devfn),
+	       (unsigned long long)pci_resource_start(pci, 0),
+	       pci->subsystem_vendor, pci->subsystem_device);
+	return -EBUSY;
+}
+
+/* Allocate and initialize the cx88 core struct.  One should hold the
+ * devlist mutex before calling this.  */
+struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr)
+{
+	struct cx88_core *core;
+	int i;
+
+	core = kzalloc(sizeof(*core), GFP_KERNEL);
+	if (core == NULL)
+		return NULL;
+
+	atomic_inc(&core->refcount);
+	core->pci_bus  = pci->bus->number;
+	core->pci_slot = PCI_SLOT(pci->devfn);
+	core->pci_irqmask = PCI_INT_RISC_RD_BERRINT | PCI_INT_RISC_WR_BERRINT |
+			    PCI_INT_BRDG_BERRINT | PCI_INT_SRC_DMA_BERRINT |
+			    PCI_INT_DST_DMA_BERRINT | PCI_INT_IPB_DMA_BERRINT;
+	mutex_init(&core->lock);
+
+	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 (v4l2_ctrl_handler_init(&core->video_hdl, 13)) {
+		v4l2_device_unregister(&core->v4l2_dev);
+		kfree(core);
+		return NULL;
+	}
+
+	if (v4l2_ctrl_handler_init(&core->audio_hdl, 13)) {
+		v4l2_ctrl_handler_free(&core->video_hdl);
+		v4l2_device_unregister(&core->v4l2_dev);
+		kfree(core);
+		return NULL;
+	}
+
+	if (0 != cx88_get_resources(core, pci)) {
+		v4l2_ctrl_handler_free(&core->video_hdl);
+		v4l2_ctrl_handler_free(&core->audio_hdl);
+		v4l2_device_unregister(&core->v4l2_dev);
+		kfree(core);
+		return NULL;
+	}
+
+	/* PCI stuff */
+	cx88_pci_quirks(core->name, pci);
+	core->lmmio = ioremap(pci_resource_start(pci, 0),
+			      pci_resource_len(pci, 0));
+	core->bmmio = (u8 __iomem *)core->lmmio;
+
+	if (core->lmmio == NULL) {
+		release_mem_region(pci_resource_start(pci, 0),
+			   pci_resource_len(pci, 0));
+		v4l2_ctrl_handler_free(&core->video_hdl);
+		v4l2_ctrl_handler_free(&core->audio_hdl);
+		v4l2_device_unregister(&core->v4l2_dev);
+		kfree(core);
+		return NULL;
+	}
+
+	/* board config */
+	core->boardnr = UNSET;
+	if (card[core->nr] < ARRAY_SIZE(cx88_boards))
+		core->boardnr = card[core->nr];
+	for (i = 0; UNSET == core->boardnr && i < ARRAY_SIZE(cx88_subids); i++)
+		if (pci->subsystem_vendor == cx88_subids[i].subvendor &&
+		    pci->subsystem_device == cx88_subids[i].subdevice)
+			core->boardnr = cx88_subids[i].card;
+	if (UNSET == core->boardnr) {
+		core->boardnr = CX88_BOARD_UNKNOWN;
+		cx88_card_list(core, pci);
+	}
+
+	memcpy(&core->board, &cx88_boards[core->boardnr], sizeof(core->board));
+
+	if (!core->board.num_frontends && (core->board.mpeg & CX88_MPEG_DVB))
+		core->board.num_frontends = 1;
+
+	info_printk(core, "subsystem: %04x:%04x, board: %s [card=%d,%s], frontend(s): %d\n",
+		pci->subsystem_vendor, pci->subsystem_device, core->board.name,
+		core->boardnr, card[core->nr] == core->boardnr ?
+		"insmod option" : "autodetected",
+		core->board.num_frontends);
+
+	if (tuner[core->nr] != UNSET)
+		core->board.tuner_type = tuner[core->nr];
+	if (radio[core->nr] != UNSET)
+		core->board.radio_type = radio[core->nr];
+
+	info_printk(core, "TV tuner type %d, Radio tuner type %d\n",
+		    core->board.tuner_type, core->board.radio_type);
+
+	/* init hardware */
+	cx88_reset(core);
+	cx88_card_setup_pre_i2c(core);
+	cx88_i2c_init(core, pci);
+
+	/* load tuner module, if needed */
+	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_subdev(&core->v4l2_dev, &core->i2c_adap,
+				"tuner", 0, v4l2_i2c_tuner_addrs(ADDRS_RADIO));
+		if (has_demod)
+			v4l2_i2c_new_subdev(&core->v4l2_dev,
+				&core->i2c_adap, "tuner",
+				0, v4l2_i2c_tuner_addrs(ADDRS_DEMOD));
+		if (core->board.tuner_addr == ADDR_UNSET) {
+			v4l2_i2c_new_subdev(&core->v4l2_dev,
+				&core->i2c_adap, "tuner",
+				0, has_demod ? tv_addrs + 4 : tv_addrs);
+		} else {
+			v4l2_i2c_new_subdev(&core->v4l2_dev, &core->i2c_adap,
+				"tuner", core->board.tuner_addr, NULL);
+		}
+	}
+
+	cx88_card_setup(core);
+	if (!disable_ir) {
+		cx88_i2c_init_ir(core);
+		cx88_ir_init(core, pci);
+	}
+
+	return core;
+}
diff --git a/drivers/media/pci/cx88/cx88-core.c b/drivers/media/pci/cx88/cx88-core.c
new file mode 100644
index 0000000..c97b174
--- /dev/null
+++ b/drivers/media/pci/cx88/cx88-core.c
@@ -0,0 +1,1131 @@
+/*
+ *
+ * device driver for Conexant 2388x based TV cards
+ * driver core
+ *
+ * (c) 2003 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
+ *
+ * (c) 2005-2006 Mauro Carvalho Chehab <mchehab@infradead.org>
+ *     - Multituner support
+ *     - video_ioctl2 conversion
+ *     - PAL/M fixes
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the 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/init.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/kmod.h>
+#include <linux/sound.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/videodev2.h>
+#include <linux/mutex.h>
+
+#include "cx88.h"
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+
+MODULE_DESCRIPTION("v4l2 driver module for cx2388x based TV cards");
+MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
+MODULE_LICENSE("GPL");
+
+/* ------------------------------------------------------------------ */
+
+static unsigned int core_debug;
+module_param(core_debug,int,0644);
+MODULE_PARM_DESC(core_debug,"enable debug messages [core]");
+
+static unsigned int nicam;
+module_param(nicam,int,0644);
+MODULE_PARM_DESC(nicam,"tv audio is nicam");
+
+static unsigned int nocomb;
+module_param(nocomb,int,0644);
+MODULE_PARM_DESC(nocomb,"disable comb filter");
+
+#define dprintk(level,fmt, arg...)	if (core_debug >= level)	\
+	printk(KERN_DEBUG "%s: " fmt, core->name , ## arg)
+
+static unsigned int cx88_devcount;
+static LIST_HEAD(cx88_devlist);
+static DEFINE_MUTEX(devlist);
+
+#define NO_SYNC_LINE (-1U)
+
+/* @lpi: lines per IRQ, or 0 to not generate irqs. Note: IRQ to be
+	 generated _after_ lpi lines are transferred. */
+static __le32* cx88_risc_field(__le32 *rp, struct scatterlist *sglist,
+			    unsigned int offset, u32 sync_line,
+			    unsigned int bpl, unsigned int padding,
+			    unsigned int lines, unsigned int lpi)
+{
+	struct scatterlist *sg;
+	unsigned int line,todo,sol;
+
+	/* sync instruction */
+	if (sync_line != NO_SYNC_LINE)
+		*(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
+
+	/* scan lines */
+	sg = sglist;
+	for (line = 0; line < lines; line++) {
+		while (offset && offset >= sg_dma_len(sg)) {
+			offset -= sg_dma_len(sg);
+			sg++;
+		}
+		if (lpi && line>0 && !(line % lpi))
+			sol = RISC_SOL | RISC_IRQ1 | RISC_CNT_INC;
+		else
+			sol = RISC_SOL;
+		if (bpl <= sg_dma_len(sg)-offset) {
+			/* fits into current chunk */
+			*(rp++)=cpu_to_le32(RISC_WRITE|sol|RISC_EOL|bpl);
+			*(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
+			offset+=bpl;
+		} else {
+			/* scanline needs to be split */
+			todo = bpl;
+			*(rp++)=cpu_to_le32(RISC_WRITE|sol|
+					    (sg_dma_len(sg)-offset));
+			*(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
+			todo -= (sg_dma_len(sg)-offset);
+			offset = 0;
+			sg++;
+			while (todo > sg_dma_len(sg)) {
+				*(rp++)=cpu_to_le32(RISC_WRITE|
+						    sg_dma_len(sg));
+				*(rp++)=cpu_to_le32(sg_dma_address(sg));
+				todo -= sg_dma_len(sg);
+				sg++;
+			}
+			*(rp++)=cpu_to_le32(RISC_WRITE|RISC_EOL|todo);
+			*(rp++)=cpu_to_le32(sg_dma_address(sg));
+			offset += todo;
+		}
+		offset += padding;
+	}
+
+	return rp;
+}
+
+int cx88_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
+		     struct scatterlist *sglist,
+		     unsigned int top_offset, unsigned int bottom_offset,
+		     unsigned int bpl, unsigned int padding, unsigned int lines)
+{
+	u32 instructions,fields;
+	__le32 *rp;
+	int rc;
+
+	fields = 0;
+	if (UNSET != top_offset)
+		fields++;
+	if (UNSET != bottom_offset)
+		fields++;
+
+	/* estimate risc mem: worst case is one write per page border +
+	   one write per scan line + syncs + jump (all 2 dwords).  Padding
+	   can cause next bpl to start close to a page border.  First DMA
+	   region may be smaller than PAGE_SIZE */
+	instructions  = fields * (1 + ((bpl + padding) * lines) / PAGE_SIZE + lines);
+	instructions += 2;
+	if ((rc = btcx_riscmem_alloc(pci,risc,instructions*8)) < 0)
+		return rc;
+
+	/* write risc instructions */
+	rp = risc->cpu;
+	if (UNSET != top_offset)
+		rp = cx88_risc_field(rp, sglist, top_offset, 0,
+				     bpl, padding, lines, 0);
+	if (UNSET != bottom_offset)
+		rp = cx88_risc_field(rp, sglist, bottom_offset, 0x200,
+				     bpl, padding, lines, 0);
+
+	/* save pointer to jmp instruction address */
+	risc->jmp = rp;
+	BUG_ON((risc->jmp - risc->cpu + 2) * sizeof (*risc->cpu) > risc->size);
+	return 0;
+}
+
+int cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc,
+			 struct scatterlist *sglist, unsigned int bpl,
+			 unsigned int lines, unsigned int lpi)
+{
+	u32 instructions;
+	__le32 *rp;
+	int rc;
+
+	/* estimate risc mem: worst case is one write per page border +
+	   one write per scan line + syncs + jump (all 2 dwords).  Here
+	   there is no padding and no sync.  First DMA region may be smaller
+	   than PAGE_SIZE */
+	instructions  = 1 + (bpl * lines) / PAGE_SIZE + lines;
+	instructions += 1;
+	if ((rc = btcx_riscmem_alloc(pci,risc,instructions*8)) < 0)
+		return rc;
+
+	/* write risc instructions */
+	rp = risc->cpu;
+	rp = cx88_risc_field(rp, sglist, 0, NO_SYNC_LINE, bpl, 0, lines, lpi);
+
+	/* save pointer to jmp instruction address */
+	risc->jmp = rp;
+	BUG_ON((risc->jmp - risc->cpu + 2) * sizeof (*risc->cpu) > risc->size);
+	return 0;
+}
+
+int cx88_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
+		      u32 reg, u32 mask, u32 value)
+{
+	__le32 *rp;
+	int rc;
+
+	if ((rc = btcx_riscmem_alloc(pci, risc, 4*16)) < 0)
+		return rc;
+
+	/* write risc instructions */
+	rp = risc->cpu;
+	*(rp++) = cpu_to_le32(RISC_WRITECR  | RISC_IRQ2 | RISC_IMM);
+	*(rp++) = cpu_to_le32(reg);
+	*(rp++) = cpu_to_le32(value);
+	*(rp++) = cpu_to_le32(mask);
+	*(rp++) = cpu_to_le32(RISC_JUMP);
+	*(rp++) = cpu_to_le32(risc->dma);
+	return 0;
+}
+
+void
+cx88_free_buffer(struct videobuf_queue *q, struct cx88_buffer *buf)
+{
+	struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
+
+	BUG_ON(in_interrupt());
+	videobuf_waiton(q, &buf->vb, 0, 0);
+	videobuf_dma_unmap(q->dev, dma);
+	videobuf_dma_free(dma);
+	btcx_riscmem_free(to_pci_dev(q->dev), &buf->risc);
+	buf->vb.state = VIDEOBUF_NEEDS_INIT;
+}
+
+/* ------------------------------------------------------------------ */
+/* our SRAM memory layout                                             */
+
+/* we are going to put all thr risc programs into host memory, so we
+ * can use the whole SDRAM for the DMA fifos.  To simplify things, we
+ * use a static memory layout.  That surely will waste memory in case
+ * we don't use all DMA channels at the same time (which will be the
+ * case most of the time).  But that still gives us enough FIFO space
+ * to be able to deal with insane long pci latencies ...
+ *
+ * FIFO space allocations:
+ *    channel  21    (y video)  - 10.0k
+ *    channel  22    (u video)  -  2.0k
+ *    channel  23    (v video)  -  2.0k
+ *    channel  24    (vbi)      -  4.0k
+ *    channels 25+26 (audio)    -  4.0k
+ *    channel  28    (mpeg)     -  4.0k
+ *    channel  27    (audio rds)-  3.0k
+ *    TOTAL                     = 29.0k
+ *
+ * Every channel has 160 bytes control data (64 bytes instruction
+ * queue and 6 CDT entries), which is close to 2k total.
+ *
+ * Address layout:
+ *    0x0000 - 0x03ff    CMDs / reserved
+ *    0x0400 - 0x0bff    instruction queues + CDs
+ *    0x0c00 -           FIFOs
+ */
+
+const struct sram_channel cx88_sram_channels[] = {
+	[SRAM_CH21] = {
+		.name       = "video y / packed",
+		.cmds_start = 0x180040,
+		.ctrl_start = 0x180400,
+		.cdt        = 0x180400 + 64,
+		.fifo_start = 0x180c00,
+		.fifo_size  = 0x002800,
+		.ptr1_reg   = MO_DMA21_PTR1,
+		.ptr2_reg   = MO_DMA21_PTR2,
+		.cnt1_reg   = MO_DMA21_CNT1,
+		.cnt2_reg   = MO_DMA21_CNT2,
+	},
+	[SRAM_CH22] = {
+		.name       = "video u",
+		.cmds_start = 0x180080,
+		.ctrl_start = 0x1804a0,
+		.cdt        = 0x1804a0 + 64,
+		.fifo_start = 0x183400,
+		.fifo_size  = 0x000800,
+		.ptr1_reg   = MO_DMA22_PTR1,
+		.ptr2_reg   = MO_DMA22_PTR2,
+		.cnt1_reg   = MO_DMA22_CNT1,
+		.cnt2_reg   = MO_DMA22_CNT2,
+	},
+	[SRAM_CH23] = {
+		.name       = "video v",
+		.cmds_start = 0x1800c0,
+		.ctrl_start = 0x180540,
+		.cdt        = 0x180540 + 64,
+		.fifo_start = 0x183c00,
+		.fifo_size  = 0x000800,
+		.ptr1_reg   = MO_DMA23_PTR1,
+		.ptr2_reg   = MO_DMA23_PTR2,
+		.cnt1_reg   = MO_DMA23_CNT1,
+		.cnt2_reg   = MO_DMA23_CNT2,
+	},
+	[SRAM_CH24] = {
+		.name       = "vbi",
+		.cmds_start = 0x180100,
+		.ctrl_start = 0x1805e0,
+		.cdt        = 0x1805e0 + 64,
+		.fifo_start = 0x184400,
+		.fifo_size  = 0x001000,
+		.ptr1_reg   = MO_DMA24_PTR1,
+		.ptr2_reg   = MO_DMA24_PTR2,
+		.cnt1_reg   = MO_DMA24_CNT1,
+		.cnt2_reg   = MO_DMA24_CNT2,
+	},
+	[SRAM_CH25] = {
+		.name       = "audio from",
+		.cmds_start = 0x180140,
+		.ctrl_start = 0x180680,
+		.cdt        = 0x180680 + 64,
+		.fifo_start = 0x185400,
+		.fifo_size  = 0x001000,
+		.ptr1_reg   = MO_DMA25_PTR1,
+		.ptr2_reg   = MO_DMA25_PTR2,
+		.cnt1_reg   = MO_DMA25_CNT1,
+		.cnt2_reg   = MO_DMA25_CNT2,
+	},
+	[SRAM_CH26] = {
+		.name       = "audio to",
+		.cmds_start = 0x180180,
+		.ctrl_start = 0x180720,
+		.cdt        = 0x180680 + 64,  /* same as audio IN */
+		.fifo_start = 0x185400,       /* same as audio IN */
+		.fifo_size  = 0x001000,       /* same as audio IN */
+		.ptr1_reg   = MO_DMA26_PTR1,
+		.ptr2_reg   = MO_DMA26_PTR2,
+		.cnt1_reg   = MO_DMA26_CNT1,
+		.cnt2_reg   = MO_DMA26_CNT2,
+	},
+	[SRAM_CH28] = {
+		.name       = "mpeg",
+		.cmds_start = 0x180200,
+		.ctrl_start = 0x1807C0,
+		.cdt        = 0x1807C0 + 64,
+		.fifo_start = 0x186400,
+		.fifo_size  = 0x001000,
+		.ptr1_reg   = MO_DMA28_PTR1,
+		.ptr2_reg   = MO_DMA28_PTR2,
+		.cnt1_reg   = MO_DMA28_CNT1,
+		.cnt2_reg   = MO_DMA28_CNT2,
+	},
+	[SRAM_CH27] = {
+		.name       = "audio rds",
+		.cmds_start = 0x1801C0,
+		.ctrl_start = 0x180860,
+		.cdt        = 0x180860 + 64,
+		.fifo_start = 0x187400,
+		.fifo_size  = 0x000C00,
+		.ptr1_reg   = MO_DMA27_PTR1,
+		.ptr2_reg   = MO_DMA27_PTR2,
+		.cnt1_reg   = MO_DMA27_CNT1,
+		.cnt2_reg   = MO_DMA27_CNT2,
+	},
+};
+
+int cx88_sram_channel_setup(struct cx88_core *core,
+			    const struct sram_channel *ch,
+			    unsigned int bpl, u32 risc)
+{
+	unsigned int i,lines;
+	u32 cdt;
+
+	bpl   = (bpl + 7) & ~7; /* alignment */
+	cdt   = ch->cdt;
+	lines = ch->fifo_size / bpl;
+	if (lines > 6)
+		lines = 6;
+	BUG_ON(lines < 2);
+
+	/* write CDT */
+	for (i = 0; i < lines; i++)
+		cx_write(cdt + 16*i, ch->fifo_start + bpl*i);
+
+	/* write CMDS */
+	cx_write(ch->cmds_start +  0, risc);
+	cx_write(ch->cmds_start +  4, cdt);
+	cx_write(ch->cmds_start +  8, (lines*16) >> 3);
+	cx_write(ch->cmds_start + 12, ch->ctrl_start);
+	cx_write(ch->cmds_start + 16, 64 >> 2);
+	for (i = 20; i < 64; i += 4)
+		cx_write(ch->cmds_start + i, 0);
+
+	/* fill registers */
+	cx_write(ch->ptr1_reg, ch->fifo_start);
+	cx_write(ch->ptr2_reg, cdt);
+	cx_write(ch->cnt1_reg, (bpl >> 3) -1);
+	cx_write(ch->cnt2_reg, (lines*16) >> 3);
+
+	dprintk(2,"sram setup %s: bpl=%d lines=%d\n", ch->name, bpl, lines);
+	return 0;
+}
+
+/* ------------------------------------------------------------------ */
+/* debug helper code                                                  */
+
+static int cx88_risc_decode(u32 risc)
+{
+	static const char * const instr[16] = {
+		[ RISC_SYNC    >> 28 ] = "sync",
+		[ RISC_WRITE   >> 28 ] = "write",
+		[ RISC_WRITEC  >> 28 ] = "writec",
+		[ RISC_READ    >> 28 ] = "read",
+		[ RISC_READC   >> 28 ] = "readc",
+		[ RISC_JUMP    >> 28 ] = "jump",
+		[ RISC_SKIP    >> 28 ] = "skip",
+		[ RISC_WRITERM >> 28 ] = "writerm",
+		[ RISC_WRITECM >> 28 ] = "writecm",
+		[ RISC_WRITECR >> 28 ] = "writecr",
+	};
+	static int const incr[16] = {
+		[ RISC_WRITE   >> 28 ] = 2,
+		[ RISC_JUMP    >> 28 ] = 2,
+		[ RISC_WRITERM >> 28 ] = 3,
+		[ RISC_WRITECM >> 28 ] = 3,
+		[ RISC_WRITECR >> 28 ] = 4,
+	};
+	static const char * const bits[] = {
+		"12",   "13",   "14",   "resync",
+		"cnt0", "cnt1", "18",   "19",
+		"20",   "21",   "22",   "23",
+		"irq1", "irq2", "eol",  "sol",
+	};
+	int i;
+
+	printk("0x%08x [ %s", risc,
+	       instr[risc >> 28] ? instr[risc >> 28] : "INVALID");
+	for (i = ARRAY_SIZE(bits)-1; i >= 0; i--)
+		if (risc & (1 << (i + 12)))
+			printk(" %s",bits[i]);
+	printk(" count=%d ]\n", risc & 0xfff);
+	return incr[risc >> 28] ? incr[risc >> 28] : 1;
+}
+
+
+void cx88_sram_channel_dump(struct cx88_core *core,
+			    const struct sram_channel *ch)
+{
+	static const char * const name[] = {
+		"initial risc",
+		"cdt base",
+		"cdt size",
+		"iq base",
+		"iq size",
+		"risc pc",
+		"iq wr ptr",
+		"iq rd ptr",
+		"cdt current",
+		"pci target",
+		"line / byte",
+	};
+	u32 risc;
+	unsigned int i,j,n;
+
+	printk("%s: %s - dma channel status dump\n",
+	       core->name,ch->name);
+	for (i = 0; i < ARRAY_SIZE(name); i++)
+		printk("%s:   cmds: %-12s: 0x%08x\n",
+		       core->name,name[i],
+		       cx_read(ch->cmds_start + 4*i));
+	for (n = 1, i = 0; i < 4; i++) {
+		risc = cx_read(ch->cmds_start + 4 * (i+11));
+		printk("%s:   risc%d: ", core->name, i);
+		if (--n)
+			printk("0x%08x [ arg #%d ]\n", risc, n);
+		else
+			n = cx88_risc_decode(risc);
+	}
+	for (i = 0; i < 16; i += n) {
+		risc = cx_read(ch->ctrl_start + 4 * i);
+		printk("%s:   iq %x: ", core->name, i);
+		n = cx88_risc_decode(risc);
+		for (j = 1; j < n; j++) {
+			risc = cx_read(ch->ctrl_start + 4 * (i+j));
+			printk("%s:   iq %x: 0x%08x [ arg #%d ]\n",
+			       core->name, i+j, risc, j);
+		}
+	}
+
+	printk("%s: fifo: 0x%08x -> 0x%x\n",
+	       core->name, ch->fifo_start, ch->fifo_start+ch->fifo_size);
+	printk("%s: ctrl: 0x%08x -> 0x%x\n",
+	       core->name, ch->ctrl_start, ch->ctrl_start+6*16);
+	printk("%s:   ptr1_reg: 0x%08x\n",
+	       core->name,cx_read(ch->ptr1_reg));
+	printk("%s:   ptr2_reg: 0x%08x\n",
+	       core->name,cx_read(ch->ptr2_reg));
+	printk("%s:   cnt1_reg: 0x%08x\n",
+	       core->name,cx_read(ch->cnt1_reg));
+	printk("%s:   cnt2_reg: 0x%08x\n",
+	       core->name,cx_read(ch->cnt2_reg));
+}
+
+static const char *cx88_pci_irqs[32] = {
+	"vid", "aud", "ts", "vip", "hst", "5", "6", "tm1",
+	"src_dma", "dst_dma", "risc_rd_err", "risc_wr_err",
+	"brdg_err", "src_dma_err", "dst_dma_err", "ipb_dma_err",
+	"i2c", "i2c_rack", "ir_smp", "gpio0", "gpio1"
+};
+
+void cx88_print_irqbits(const char *name, const char *tag, const char *strings[],
+			int len, u32 bits, u32 mask)
+{
+	unsigned int i;
+
+	printk(KERN_DEBUG "%s: %s [0x%x]", name, tag, bits);
+	for (i = 0; i < len; i++) {
+		if (!(bits & (1 << i)))
+			continue;
+		if (strings[i])
+			printk(" %s", strings[i]);
+		else
+			printk(" %d", i);
+		if (!(mask & (1 << i)))
+			continue;
+		printk("*");
+	}
+	printk("\n");
+}
+
+/* ------------------------------------------------------------------ */
+
+int cx88_core_irq(struct cx88_core *core, u32 status)
+{
+	int handled = 0;
+
+	if (status & PCI_INT_IR_SMPINT) {
+		cx88_ir_irq(core);
+		handled++;
+	}
+	if (!handled)
+		cx88_print_irqbits(core->name, "irq pci",
+				   cx88_pci_irqs, ARRAY_SIZE(cx88_pci_irqs),
+				   status, core->pci_irqmask);
+	return handled;
+}
+
+void cx88_wakeup(struct cx88_core *core,
+		 struct cx88_dmaqueue *q, u32 count)
+{
+	struct cx88_buffer *buf;
+	int bc;
+
+	for (bc = 0;; bc++) {
+		if (list_empty(&q->active))
+			break;
+		buf = list_entry(q->active.next,
+				 struct cx88_buffer, vb.queue);
+		/* count comes from the hw and is is 16bit wide --
+		 * this trick handles wrap-arounds correctly for
+		 * up to 32767 buffers in flight... */
+		if ((s16) (count - buf->count) < 0)
+			break;
+		do_gettimeofday(&buf->vb.ts);
+		dprintk(2,"[%p/%d] wakeup reg=%d buf=%d\n",buf,buf->vb.i,
+			count, buf->count);
+		buf->vb.state = VIDEOBUF_DONE;
+		list_del(&buf->vb.queue);
+		wake_up(&buf->vb.done);
+	}
+	if (list_empty(&q->active)) {
+		del_timer(&q->timeout);
+	} else {
+		mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
+	}
+	if (bc != 1)
+		dprintk(2, "%s: %d buffers handled (should be 1)\n",
+			__func__, bc);
+}
+
+void cx88_shutdown(struct cx88_core *core)
+{
+	/* disable RISC controller + IRQs */
+	cx_write(MO_DEV_CNTRL2, 0);
+
+	/* stop dma transfers */
+	cx_write(MO_VID_DMACNTRL, 0x0);
+	cx_write(MO_AUD_DMACNTRL, 0x0);
+	cx_write(MO_TS_DMACNTRL, 0x0);
+	cx_write(MO_VIP_DMACNTRL, 0x0);
+	cx_write(MO_GPHST_DMACNTRL, 0x0);
+
+	/* stop interrupts */
+	cx_write(MO_PCI_INTMSK, 0x0);
+	cx_write(MO_VID_INTMSK, 0x0);
+	cx_write(MO_AUD_INTMSK, 0x0);
+	cx_write(MO_TS_INTMSK, 0x0);
+	cx_write(MO_VIP_INTMSK, 0x0);
+	cx_write(MO_GPHST_INTMSK, 0x0);
+
+	/* stop capturing */
+	cx_write(VID_CAPTURE_CONTROL, 0);
+}
+
+int cx88_reset(struct cx88_core *core)
+{
+	dprintk(1,"%s\n",__func__);
+	cx88_shutdown(core);
+
+	/* clear irq status */
+	cx_write(MO_VID_INTSTAT, 0xFFFFFFFF); // Clear PIV int
+	cx_write(MO_PCI_INTSTAT, 0xFFFFFFFF); // Clear PCI int
+	cx_write(MO_INT1_STAT,   0xFFFFFFFF); // Clear RISC int
+
+	/* wait a bit */
+	msleep(100);
+
+	/* init sram */
+	cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH21], 720*4, 0);
+	cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH22], 128, 0);
+	cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH23], 128, 0);
+	cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH24], 128, 0);
+	cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH25], 128, 0);
+	cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH26], 128, 0);
+	cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH28], 188*4, 0);
+	cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH27], 128, 0);
+
+	/* misc init ... */
+	cx_write(MO_INPUT_FORMAT, ((1 << 13) |   // agc enable
+				   (1 << 12) |   // agc gain
+				   (1 << 11) |   // adaptibe agc
+				   (0 << 10) |   // chroma agc
+				   (0 <<  9) |   // ckillen
+				   (7)));
+
+	/* setup image format */
+	cx_andor(MO_COLOR_CTRL, 0x4000, 0x4000);
+
+	/* setup FIFO Thresholds */
+	cx_write(MO_PDMA_STHRSH,   0x0807);
+	cx_write(MO_PDMA_DTHRSH,   0x0807);
+
+	/* fixes flashing of image */
+	cx_write(MO_AGC_SYNC_TIP1, 0x0380000F);
+	cx_write(MO_AGC_BACK_VBI,  0x00E00555);
+
+	cx_write(MO_VID_INTSTAT,   0xFFFFFFFF); // Clear PIV int
+	cx_write(MO_PCI_INTSTAT,   0xFFFFFFFF); // Clear PCI int
+	cx_write(MO_INT1_STAT,     0xFFFFFFFF); // Clear RISC int
+
+	/* Reset on-board parts */
+	cx_write(MO_SRST_IO, 0);
+	msleep(10);
+	cx_write(MO_SRST_IO, 1);
+
+	return 0;
+}
+
+/* ------------------------------------------------------------------ */
+
+static unsigned int inline norm_swidth(v4l2_std_id norm)
+{
+	return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 754 : 922;
+}
+
+static unsigned int inline norm_hdelay(v4l2_std_id norm)
+{
+	return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 135 : 186;
+}
+
+static unsigned int inline norm_vdelay(v4l2_std_id norm)
+{
+	return (norm & V4L2_STD_625_50) ? 0x24 : 0x18;
+}
+
+static unsigned int inline norm_fsc8(v4l2_std_id norm)
+{
+	if (norm & V4L2_STD_PAL_M)
+		return 28604892;      // 3.575611 MHz
+
+	if (norm & (V4L2_STD_PAL_Nc))
+		return 28656448;      // 3.582056 MHz
+
+	if (norm & V4L2_STD_NTSC) // All NTSC/M and variants
+		return 28636360;      // 3.57954545 MHz +/- 10 Hz
+
+	/* SECAM have also different sub carrier for chroma,
+	   but step_db and step_dr, at cx88_set_tvnorm already handles that.
+
+	   The same FSC applies to PAL/BGDKIH, PAL/60, NTSC/4.43 and PAL/N
+	 */
+
+	return 35468950;      // 4.43361875 MHz +/- 5 Hz
+}
+
+static unsigned int inline norm_htotal(v4l2_std_id norm)
+{
+
+	unsigned int fsc4=norm_fsc8(norm)/2;
+
+	/* returns 4*FSC / vtotal / frames per seconds */
+	return (norm & V4L2_STD_625_50) ?
+				((fsc4+312)/625+12)/25 :
+				((fsc4+262)/525*1001+15000)/30000;
+}
+
+static unsigned int inline norm_vbipack(v4l2_std_id norm)
+{
+	return (norm & V4L2_STD_625_50) ? 511 : 400;
+}
+
+int cx88_set_scale(struct cx88_core *core, unsigned int width, unsigned int height,
+		   enum v4l2_field field)
+{
+	unsigned int swidth  = norm_swidth(core->tvnorm);
+	unsigned int sheight = norm_maxh(core->tvnorm);
+	u32 value;
+
+	dprintk(1,"set_scale: %dx%d [%s%s,%s]\n", width, height,
+		V4L2_FIELD_HAS_TOP(field)    ? "T" : "",
+		V4L2_FIELD_HAS_BOTTOM(field) ? "B" : "",
+		v4l2_norm_to_name(core->tvnorm));
+	if (!V4L2_FIELD_HAS_BOTH(field))
+		height *= 2;
+
+	// recalc H delay and scale registers
+	value = (width * norm_hdelay(core->tvnorm)) / swidth;
+	value &= 0x3fe;
+	cx_write(MO_HDELAY_EVEN,  value);
+	cx_write(MO_HDELAY_ODD,   value);
+	dprintk(1,"set_scale: hdelay  0x%04x (width %d)\n", value,swidth);
+
+	value = (swidth * 4096 / width) - 4096;
+	cx_write(MO_HSCALE_EVEN,  value);
+	cx_write(MO_HSCALE_ODD,   value);
+	dprintk(1,"set_scale: hscale  0x%04x\n", value);
+
+	cx_write(MO_HACTIVE_EVEN, width);
+	cx_write(MO_HACTIVE_ODD,  width);
+	dprintk(1,"set_scale: hactive 0x%04x\n", width);
+
+	// recalc V scale Register (delay is constant)
+	cx_write(MO_VDELAY_EVEN, norm_vdelay(core->tvnorm));
+	cx_write(MO_VDELAY_ODD,  norm_vdelay(core->tvnorm));
+	dprintk(1,"set_scale: vdelay  0x%04x\n", norm_vdelay(core->tvnorm));
+
+	value = (0x10000 - (sheight * 512 / height - 512)) & 0x1fff;
+	cx_write(MO_VSCALE_EVEN,  value);
+	cx_write(MO_VSCALE_ODD,   value);
+	dprintk(1,"set_scale: vscale  0x%04x\n", value);
+
+	cx_write(MO_VACTIVE_EVEN, sheight);
+	cx_write(MO_VACTIVE_ODD,  sheight);
+	dprintk(1,"set_scale: vactive 0x%04x\n", sheight);
+
+	// setup filters
+	value = 0;
+	value |= (1 << 19);        // CFILT (default)
+	if (core->tvnorm & V4L2_STD_SECAM) {
+		value |= (1 << 15);
+		value |= (1 << 16);
+	}
+	if (INPUT(core->input).type == CX88_VMUX_SVIDEO)
+		value |= (1 << 13) | (1 << 5);
+	if (V4L2_FIELD_INTERLACED == field)
+		value |= (1 << 3); // VINT (interlaced vertical scaling)
+	if (width < 385)
+		value |= (1 << 0); // 3-tap interpolation
+	if (width < 193)
+		value |= (1 << 1); // 5-tap interpolation
+	if (nocomb)
+		value |= (3 << 5); // disable comb filter
+
+	cx_andor(MO_FILTER_EVEN,  0x7ffc7f, value); /* preserve PEAKEN, PSEL */
+	cx_andor(MO_FILTER_ODD,   0x7ffc7f, value);
+	dprintk(1,"set_scale: filter  0x%04x\n", value);
+
+	return 0;
+}
+
+static const u32 xtal = 28636363;
+
+static int set_pll(struct cx88_core *core, int prescale, u32 ofreq)
+{
+	static const u32 pre[] = { 0, 0, 0, 3, 2, 1 };
+	u64 pll;
+	u32 reg;
+	int i;
+
+	if (prescale < 2)
+		prescale = 2;
+	if (prescale > 5)
+		prescale = 5;
+
+	pll = ofreq * 8 * prescale * (u64)(1 << 20);
+	do_div(pll,xtal);
+	reg = (pll & 0x3ffffff) | (pre[prescale] << 26);
+	if (((reg >> 20) & 0x3f) < 14) {
+		printk("%s/0: pll out of range\n",core->name);
+		return -1;
+	}
+
+	dprintk(1,"set_pll:    MO_PLL_REG       0x%08x [old=0x%08x,freq=%d]\n",
+		reg, cx_read(MO_PLL_REG), ofreq);
+	cx_write(MO_PLL_REG, reg);
+	for (i = 0; i < 100; i++) {
+		reg = cx_read(MO_DEVICE_STATUS);
+		if (reg & (1<<2)) {
+			dprintk(1,"pll locked [pre=%d,ofreq=%d]\n",
+				prescale,ofreq);
+			return 0;
+		}
+		dprintk(1,"pll not locked yet, waiting ...\n");
+		msleep(10);
+	}
+	dprintk(1,"pll NOT locked [pre=%d,ofreq=%d]\n",prescale,ofreq);
+	return -1;
+}
+
+int cx88_start_audio_dma(struct cx88_core *core)
+{
+	/* constant 128 made buzz in analog Nicam-stereo for bigger fifo_size */
+	int bpl = cx88_sram_channels[SRAM_CH25].fifo_size/4;
+
+	int rds_bpl = cx88_sram_channels[SRAM_CH27].fifo_size/AUD_RDS_LINES;
+
+	/* If downstream RISC is enabled, bail out; ALSA is managing DMA */
+	if (cx_read(MO_AUD_DMACNTRL) & 0x10)
+		return 0;
+
+	/* setup fifo + format */
+	cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH25], bpl, 0);
+	cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH26], bpl, 0);
+	cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH27],
+				rds_bpl, 0);
+
+	cx_write(MO_AUDD_LNGTH, bpl); /* fifo bpl size */
+	cx_write(MO_AUDR_LNGTH, rds_bpl); /* fifo bpl size */
+
+	/* enable Up, Down and Audio RDS fifo */
+	cx_write(MO_AUD_DMACNTRL, 0x0007);
+
+	return 0;
+}
+
+int cx88_stop_audio_dma(struct cx88_core *core)
+{
+	/* If downstream RISC is enabled, bail out; ALSA is managing DMA */
+	if (cx_read(MO_AUD_DMACNTRL) & 0x10)
+		return 0;
+
+	/* stop dma */
+	cx_write(MO_AUD_DMACNTRL, 0x0000);
+
+	return 0;
+}
+
+static int set_tvaudio(struct cx88_core *core)
+{
+	v4l2_std_id norm = core->tvnorm;
+
+	if (CX88_VMUX_TELEVISION != INPUT(core->input).type &&
+	    CX88_VMUX_CABLE != INPUT(core->input).type)
+		return 0;
+
+	if (V4L2_STD_PAL_BG & norm) {
+		core->tvaudio = WW_BG;
+
+	} else if (V4L2_STD_PAL_DK & norm) {
+		core->tvaudio = WW_DK;
+
+	} else if (V4L2_STD_PAL_I & norm) {
+		core->tvaudio = WW_I;
+
+	} else if (V4L2_STD_SECAM_L & norm) {
+		core->tvaudio = WW_L;
+
+	} else if ((V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H) & norm) {
+		core->tvaudio = WW_BG;
+
+	} else if (V4L2_STD_SECAM_DK & norm) {
+		core->tvaudio = WW_DK;
+
+	} else if ((V4L2_STD_NTSC_M & norm) ||
+		   (V4L2_STD_PAL_M  & norm)) {
+		core->tvaudio = WW_BTSC;
+
+	} else if (V4L2_STD_NTSC_M_JP & norm) {
+		core->tvaudio = WW_EIAJ;
+
+	} else {
+		printk("%s/0: tvaudio support needs work for this tv norm [%s], sorry\n",
+		       core->name, v4l2_norm_to_name(core->tvnorm));
+		core->tvaudio = WW_NONE;
+		return 0;
+	}
+
+	cx_andor(MO_AFECFG_IO, 0x1f, 0x0);
+	cx88_set_tvaudio(core);
+	/* cx88_set_stereo(dev,V4L2_TUNER_MODE_STEREO); */
+
+/*
+   This should be needed only on cx88-alsa. It seems that some cx88 chips have
+   bugs and does require DMA enabled for it to work.
+ */
+	cx88_start_audio_dma(core);
+	return 0;
+}
+
+
+
+int cx88_set_tvnorm(struct cx88_core *core, v4l2_std_id norm)
+{
+	u32 fsc8;
+	u32 adc_clock;
+	u32 vdec_clock;
+	u32 step_db,step_dr;
+	u64 tmp64;
+	u32 bdelay,agcdelay,htotal;
+	u32 cxiformat, cxoformat;
+
+	core->tvnorm = norm;
+	fsc8       = norm_fsc8(norm);
+	adc_clock  = xtal;
+	vdec_clock = fsc8;
+	step_db    = fsc8;
+	step_dr    = fsc8;
+
+	if (norm & V4L2_STD_NTSC_M_JP) {
+		cxiformat = VideoFormatNTSCJapan;
+		cxoformat = 0x181f0008;
+	} else if (norm & V4L2_STD_NTSC_443) {
+		cxiformat = VideoFormatNTSC443;
+		cxoformat = 0x181f0008;
+	} else if (norm & V4L2_STD_PAL_M) {
+		cxiformat = VideoFormatPALM;
+		cxoformat = 0x1c1f0008;
+	} else if (norm & V4L2_STD_PAL_N) {
+		cxiformat = VideoFormatPALN;
+		cxoformat = 0x1c1f0008;
+	} else if (norm & V4L2_STD_PAL_Nc) {
+		cxiformat = VideoFormatPALNC;
+		cxoformat = 0x1c1f0008;
+	} else if (norm & V4L2_STD_PAL_60) {
+		cxiformat = VideoFormatPAL60;
+		cxoformat = 0x181f0008;
+	} else if (norm & V4L2_STD_NTSC) {
+		cxiformat = VideoFormatNTSC;
+		cxoformat = 0x181f0008;
+	} else if (norm & V4L2_STD_SECAM) {
+		step_db = 4250000 * 8;
+		step_dr = 4406250 * 8;
+
+		cxiformat = VideoFormatSECAM;
+		cxoformat = 0x181f0008;
+	} else { /* PAL */
+		cxiformat = VideoFormatPAL;
+		cxoformat = 0x181f0008;
+	}
+
+	dprintk(1,"set_tvnorm: \"%s\" fsc8=%d adc=%d vdec=%d db/dr=%d/%d\n",
+		v4l2_norm_to_name(core->tvnorm), fsc8, adc_clock, vdec_clock,
+		step_db, step_dr);
+	set_pll(core,2,vdec_clock);
+
+	dprintk(1,"set_tvnorm: MO_INPUT_FORMAT  0x%08x [old=0x%08x]\n",
+		cxiformat, cx_read(MO_INPUT_FORMAT) & 0x0f);
+	/* Chroma AGC must be disabled if SECAM is used, we enable it
+	   by default on PAL and NTSC */
+	cx_andor(MO_INPUT_FORMAT, 0x40f,
+		 norm & V4L2_STD_SECAM ? cxiformat : cxiformat | 0x400);
+
+	// FIXME: as-is from DScaler
+	dprintk(1,"set_tvnorm: MO_OUTPUT_FORMAT 0x%08x [old=0x%08x]\n",
+		cxoformat, cx_read(MO_OUTPUT_FORMAT));
+	cx_write(MO_OUTPUT_FORMAT, cxoformat);
+
+	// MO_SCONV_REG = adc clock / video dec clock * 2^17
+	tmp64  = adc_clock * (u64)(1 << 17);
+	do_div(tmp64, vdec_clock);
+	dprintk(1,"set_tvnorm: MO_SCONV_REG     0x%08x [old=0x%08x]\n",
+		(u32)tmp64, cx_read(MO_SCONV_REG));
+	cx_write(MO_SCONV_REG, (u32)tmp64);
+
+	// MO_SUB_STEP = 8 * fsc / video dec clock * 2^22
+	tmp64  = step_db * (u64)(1 << 22);
+	do_div(tmp64, vdec_clock);
+	dprintk(1,"set_tvnorm: MO_SUB_STEP      0x%08x [old=0x%08x]\n",
+		(u32)tmp64, cx_read(MO_SUB_STEP));
+	cx_write(MO_SUB_STEP, (u32)tmp64);
+
+	// MO_SUB_STEP_DR = 8 * 4406250 / video dec clock * 2^22
+	tmp64  = step_dr * (u64)(1 << 22);
+	do_div(tmp64, vdec_clock);
+	dprintk(1,"set_tvnorm: MO_SUB_STEP_DR   0x%08x [old=0x%08x]\n",
+		(u32)tmp64, cx_read(MO_SUB_STEP_DR));
+	cx_write(MO_SUB_STEP_DR, (u32)tmp64);
+
+	// bdelay + agcdelay
+	bdelay   = vdec_clock * 65 / 20000000 + 21;
+	agcdelay = vdec_clock * 68 / 20000000 + 15;
+	dprintk(1,"set_tvnorm: MO_AGC_BURST     0x%08x [old=0x%08x,bdelay=%d,agcdelay=%d]\n",
+		(bdelay << 8) | agcdelay, cx_read(MO_AGC_BURST), bdelay, agcdelay);
+	cx_write(MO_AGC_BURST, (bdelay << 8) | agcdelay);
+
+	// htotal
+	tmp64 = norm_htotal(norm) * (u64)vdec_clock;
+	do_div(tmp64, fsc8);
+	htotal = (u32)tmp64;
+	dprintk(1,"set_tvnorm: MO_HTOTAL        0x%08x [old=0x%08x,htotal=%d]\n",
+		htotal, cx_read(MO_HTOTAL), (u32)tmp64);
+	cx_andor(MO_HTOTAL, 0x07ff, htotal);
+
+	// vbi stuff, set vbi offset to 10 (for 20 Clk*2 pixels), this makes
+	// the effective vbi offset ~244 samples, the same as the Bt8x8
+	cx_write(MO_VBI_PACKET, (10<<11) | norm_vbipack(norm));
+
+	// this is needed as well to set all tvnorm parameter
+	cx88_set_scale(core, 320, 240, V4L2_FIELD_INTERLACED);
+
+	// audio
+	set_tvaudio(core);
+
+	// tell i2c chips
+	call_all(core, core, s_std, norm);
+
+	/* The chroma_agc control should be inaccessible if the video format is SECAM */
+	v4l2_ctrl_grab(core->chroma_agc, cxiformat == VideoFormatSECAM);
+
+	// done
+	return 0;
+}
+
+/* ------------------------------------------------------------------ */
+
+struct video_device *cx88_vdev_init(struct cx88_core *core,
+				    struct pci_dev *pci,
+				    const struct video_device *template_,
+				    const char *type)
+{
+	struct video_device *vfd;
+
+	vfd = video_device_alloc();
+	if (NULL == vfd)
+		return NULL;
+	*vfd = *template_;
+	vfd->v4l2_dev = &core->v4l2_dev;
+	vfd->release = video_device_release;
+	snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)",
+		 core->name, type, core->board.name);
+	set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
+	return vfd;
+}
+
+struct cx88_core* cx88_core_get(struct pci_dev *pci)
+{
+	struct cx88_core *core;
+
+	mutex_lock(&devlist);
+	list_for_each_entry(core, &cx88_devlist, devlist) {
+		if (pci->bus->number != core->pci_bus)
+			continue;
+		if (PCI_SLOT(pci->devfn) != core->pci_slot)
+			continue;
+
+		if (0 != cx88_get_resources(core, pci)) {
+			mutex_unlock(&devlist);
+			return NULL;
+		}
+		atomic_inc(&core->refcount);
+		mutex_unlock(&devlist);
+		return core;
+	}
+
+	core = cx88_core_create(pci, cx88_devcount);
+	if (NULL != core) {
+		cx88_devcount++;
+		list_add_tail(&core->devlist, &cx88_devlist);
+	}
+
+	mutex_unlock(&devlist);
+	return core;
+}
+
+void cx88_core_put(struct cx88_core *core, struct pci_dev *pci)
+{
+	release_mem_region(pci_resource_start(pci,0),
+			   pci_resource_len(pci,0));
+
+	if (!atomic_dec_and_test(&core->refcount))
+		return;
+
+	mutex_lock(&devlist);
+	cx88_ir_fini(core);
+	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_ctrl_handler_free(&core->video_hdl);
+	v4l2_ctrl_handler_free(&core->audio_hdl);
+	v4l2_device_unregister(&core->v4l2_dev);
+	kfree(core);
+}
+
+/* ------------------------------------------------------------------ */
+
+EXPORT_SYMBOL(cx88_print_irqbits);
+
+EXPORT_SYMBOL(cx88_core_irq);
+EXPORT_SYMBOL(cx88_wakeup);
+EXPORT_SYMBOL(cx88_reset);
+EXPORT_SYMBOL(cx88_shutdown);
+
+EXPORT_SYMBOL(cx88_risc_buffer);
+EXPORT_SYMBOL(cx88_risc_databuffer);
+EXPORT_SYMBOL(cx88_risc_stopper);
+EXPORT_SYMBOL(cx88_free_buffer);
+
+EXPORT_SYMBOL(cx88_sram_channels);
+EXPORT_SYMBOL(cx88_sram_channel_setup);
+EXPORT_SYMBOL(cx88_sram_channel_dump);
+
+EXPORT_SYMBOL(cx88_set_tvnorm);
+EXPORT_SYMBOL(cx88_set_scale);
+
+EXPORT_SYMBOL(cx88_vdev_init);
+EXPORT_SYMBOL(cx88_core_get);
+EXPORT_SYMBOL(cx88_core_put);
+
+EXPORT_SYMBOL(cx88_ir_start);
+EXPORT_SYMBOL(cx88_ir_stop);
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off
+ */
diff --git a/drivers/media/pci/cx88/cx88-dsp.c b/drivers/media/pci/cx88/cx88-dsp.c
new file mode 100644
index 0000000..a990726
--- /dev/null
+++ b/drivers/media/pci/cx88/cx88-dsp.c
@@ -0,0 +1,322 @@
+/*
+ *
+ *  Stereo and SAP detection for cx88
+ *
+ *  Copyright (c) 2009 Marton Balint <cus@fazekas.hu>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the 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/slab.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/jiffies.h>
+#include <asm/div64.h>
+
+#include "cx88.h"
+#include "cx88-reg.h"
+
+#define INT_PI			((s32)(3.141592653589 * 32768.0))
+
+#define compat_remainder(a, b) \
+	 ((float)(((s32)((a)*100))%((s32)((b)*100)))/100.0)
+
+#define baseband_freq(carrier, srate, tone) ((s32)( \
+	 (compat_remainder(carrier + tone, srate)) / srate * 2 * INT_PI))
+
+/* We calculate the baseband frequencies of the carrier and the pilot tones
+ * based on the the sampling rate of the audio rds fifo. */
+
+#define FREQ_A2_CARRIER         baseband_freq(54687.5, 2689.36, 0.0)
+#define FREQ_A2_DUAL            baseband_freq(54687.5, 2689.36, 274.1)
+#define FREQ_A2_STEREO          baseband_freq(54687.5, 2689.36, 117.5)
+
+/* The frequencies below are from the reference driver. They probably need
+ * further adjustments, because they are not tested at all. You may even need
+ * to play a bit with the registers of the chip to select the proper signal
+ * for the input of the audio rds fifo, and measure it's sampling rate to
+ * calculate the proper baseband frequencies... */
+
+#define FREQ_A2M_CARRIER	((s32)(2.114516 * 32768.0))
+#define FREQ_A2M_DUAL		((s32)(2.754916 * 32768.0))
+#define FREQ_A2M_STEREO		((s32)(2.462326 * 32768.0))
+
+#define FREQ_EIAJ_CARRIER	((s32)(1.963495 * 32768.0)) /* 5pi/8  */
+#define FREQ_EIAJ_DUAL		((s32)(2.562118 * 32768.0))
+#define FREQ_EIAJ_STEREO	((s32)(2.601053 * 32768.0))
+
+#define FREQ_BTSC_DUAL		((s32)(1.963495 * 32768.0)) /* 5pi/8  */
+#define FREQ_BTSC_DUAL_REF	((s32)(1.374446 * 32768.0)) /* 7pi/16 */
+
+#define FREQ_BTSC_SAP		((s32)(2.471532 * 32768.0))
+#define FREQ_BTSC_SAP_REF	((s32)(1.730072 * 32768.0))
+
+/* The spectrum of the signal should be empty between these frequencies. */
+#define FREQ_NOISE_START	((s32)(0.100000 * 32768.0))
+#define FREQ_NOISE_END		((s32)(1.200000 * 32768.0))
+
+static unsigned int dsp_debug;
+module_param(dsp_debug, int, 0644);
+MODULE_PARM_DESC(dsp_debug, "enable audio dsp debug messages");
+
+#define dprintk(level, fmt, arg...)	if (dsp_debug >= level) \
+	printk(KERN_DEBUG "%s/0: " fmt, core->name , ## arg)
+
+static s32 int_cos(u32 x)
+{
+	u32 t2, t4, t6, t8;
+	s32 ret;
+	u16 period = x / INT_PI;
+	if (period % 2)
+		return -int_cos(x - INT_PI);
+	x = x % INT_PI;
+	if (x > INT_PI/2)
+		return -int_cos(INT_PI/2 - (x % (INT_PI/2)));
+	/* Now x is between 0 and INT_PI/2.
+	 * To calculate cos(x) we use it's Taylor polinom. */
+	t2 = x*x/32768/2;
+	t4 = t2*x/32768*x/32768/3/4;
+	t6 = t4*x/32768*x/32768/5/6;
+	t8 = t6*x/32768*x/32768/7/8;
+	ret = 32768-t2+t4-t6+t8;
+	return ret;
+}
+
+static u32 int_goertzel(s16 x[], u32 N, u32 freq)
+{
+	/* We use the Goertzel algorithm to determine the power of the
+	 * given frequency in the signal */
+	s32 s_prev = 0;
+	s32 s_prev2 = 0;
+	s32 coeff = 2*int_cos(freq);
+	u32 i;
+
+	u64 tmp;
+	u32 divisor;
+
+	for (i = 0; i < N; i++) {
+		s32 s = x[i] + ((s64)coeff*s_prev/32768) - s_prev2;
+		s_prev2 = s_prev;
+		s_prev = s;
+	}
+
+	tmp = (s64)s_prev2 * s_prev2 + (s64)s_prev * s_prev -
+		      (s64)coeff * s_prev2 * s_prev / 32768;
+
+	/* XXX: N must be low enough so that N*N fits in s32.
+	 * Else we need two divisions. */
+	divisor = N * N;
+	do_div(tmp, divisor);
+
+	return (u32) tmp;
+}
+
+static u32 freq_magnitude(s16 x[], u32 N, u32 freq)
+{
+	u32 sum = int_goertzel(x, N, freq);
+	return (u32)int_sqrt(sum);
+}
+
+static u32 noise_magnitude(s16 x[], u32 N, u32 freq_start, u32 freq_end)
+{
+	int i;
+	u32 sum = 0;
+	u32 freq_step;
+	int samples = 5;
+
+	if (N > 192) {
+		/* The last 192 samples are enough for noise detection */
+		x += (N-192);
+		N = 192;
+	}
+
+	freq_step = (freq_end - freq_start) / (samples - 1);
+
+	for (i = 0; i < samples; i++) {
+		sum += int_goertzel(x, N, freq_start);
+		freq_start += freq_step;
+	}
+
+	return (u32)int_sqrt(sum / samples);
+}
+
+static s32 detect_a2_a2m_eiaj(struct cx88_core *core, s16 x[], u32 N)
+{
+	s32 carrier, stereo, dual, noise;
+	s32 carrier_freq, stereo_freq, dual_freq;
+	s32 ret;
+
+	switch (core->tvaudio) {
+	case WW_BG:
+	case WW_DK:
+		carrier_freq = FREQ_A2_CARRIER;
+		stereo_freq = FREQ_A2_STEREO;
+		dual_freq = FREQ_A2_DUAL;
+		break;
+	case WW_M:
+		carrier_freq = FREQ_A2M_CARRIER;
+		stereo_freq = FREQ_A2M_STEREO;
+		dual_freq = FREQ_A2M_DUAL;
+		break;
+	case WW_EIAJ:
+		carrier_freq = FREQ_EIAJ_CARRIER;
+		stereo_freq = FREQ_EIAJ_STEREO;
+		dual_freq = FREQ_EIAJ_DUAL;
+		break;
+	default:
+		printk(KERN_WARNING "%s/0: unsupported audio mode %d for %s\n",
+		       core->name, core->tvaudio, __func__);
+		return UNSET;
+	}
+
+	carrier = freq_magnitude(x, N, carrier_freq);
+	stereo  = freq_magnitude(x, N, stereo_freq);
+	dual    = freq_magnitude(x, N, dual_freq);
+	noise   = noise_magnitude(x, N, FREQ_NOISE_START, FREQ_NOISE_END);
+
+	dprintk(1, "detect a2/a2m/eiaj: carrier=%d, stereo=%d, dual=%d, "
+		   "noise=%d\n", carrier, stereo, dual, noise);
+
+	if (stereo > dual)
+		ret = V4L2_TUNER_SUB_STEREO;
+	else
+		ret = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
+
+	if (core->tvaudio == WW_EIAJ) {
+		/* EIAJ checks may need adjustments */
+		if ((carrier > max(stereo, dual)*2) &&
+		    (carrier < max(stereo, dual)*6) &&
+		    (carrier > 20 && carrier < 200) &&
+		    (max(stereo, dual) > min(stereo, dual))) {
+			/* For EIAJ the carrier is always present,
+			   so we probably don't need noise detection */
+			return ret;
+		}
+	} else {
+		if ((carrier > max(stereo, dual)*2) &&
+		    (carrier < max(stereo, dual)*8) &&
+		    (carrier > 20 && carrier < 200) &&
+		    (noise < 10) &&
+		    (max(stereo, dual) > min(stereo, dual)*2)) {
+			return ret;
+		}
+	}
+	return V4L2_TUNER_SUB_MONO;
+}
+
+static s32 detect_btsc(struct cx88_core *core, s16 x[], u32 N)
+{
+	s32 sap_ref = freq_magnitude(x, N, FREQ_BTSC_SAP_REF);
+	s32 sap = freq_magnitude(x, N, FREQ_BTSC_SAP);
+	s32 dual_ref = freq_magnitude(x, N, FREQ_BTSC_DUAL_REF);
+	s32 dual = freq_magnitude(x, N, FREQ_BTSC_DUAL);
+	dprintk(1, "detect btsc: dual_ref=%d, dual=%d, sap_ref=%d, sap=%d"
+		   "\n", dual_ref, dual, sap_ref, sap);
+	/* FIXME: Currently not supported */
+	return UNSET;
+}
+
+static s16 *read_rds_samples(struct cx88_core *core, u32 *N)
+{
+	const struct sram_channel *srch = &cx88_sram_channels[SRAM_CH27];
+	s16 *samples;
+
+	unsigned int i;
+	unsigned int bpl = srch->fifo_size/AUD_RDS_LINES;
+	unsigned int spl = bpl/4;
+	unsigned int sample_count = spl*(AUD_RDS_LINES-1);
+
+	u32 current_address = cx_read(srch->ptr1_reg);
+	u32 offset = (current_address - srch->fifo_start + bpl);
+
+	dprintk(1, "read RDS samples: current_address=%08x (offset=%08x), "
+		"sample_count=%d, aud_intstat=%08x\n", current_address,
+		current_address - srch->fifo_start, sample_count,
+		cx_read(MO_AUD_INTSTAT));
+
+	samples = kmalloc(sizeof(s16)*sample_count, GFP_KERNEL);
+	if (!samples)
+		return NULL;
+
+	*N = sample_count;
+
+	for (i = 0; i < sample_count; i++)  {
+		offset = offset % (AUD_RDS_LINES*bpl);
+		samples[i] = cx_read(srch->fifo_start + offset);
+		offset += 4;
+	}
+
+	if (dsp_debug >= 2) {
+		dprintk(2, "RDS samples dump: ");
+		for (i = 0; i < sample_count; i++)
+			printk("%hd ", samples[i]);
+		printk(".\n");
+	}
+
+	return samples;
+}
+
+s32 cx88_dsp_detect_stereo_sap(struct cx88_core *core)
+{
+	s16 *samples;
+	u32 N = 0;
+	s32 ret = UNSET;
+
+	/* If audio RDS fifo is disabled, we can't read the samples */
+	if (!(cx_read(MO_AUD_DMACNTRL) & 0x04))
+		return ret;
+	if (!(cx_read(AUD_CTL) & EN_FMRADIO_EN_RDS))
+		return ret;
+
+	/* Wait at least 500 ms after an audio standard change */
+	if (time_before(jiffies, core->last_change + msecs_to_jiffies(500)))
+		return ret;
+
+	samples = read_rds_samples(core, &N);
+
+	if (!samples)
+		return ret;
+
+	switch (core->tvaudio) {
+	case WW_BG:
+	case WW_DK:
+	case WW_EIAJ:
+	case WW_M:
+		ret = detect_a2_a2m_eiaj(core, samples, N);
+		break;
+	case WW_BTSC:
+		ret = detect_btsc(core, samples, N);
+		break;
+	case WW_NONE:
+	case WW_I:
+	case WW_L:
+	case WW_I2SPT:
+	case WW_FM:
+	case WW_I2SADC:
+		break;
+	}
+
+	kfree(samples);
+
+	if (UNSET != ret)
+		dprintk(1, "stereo/sap detection result:%s%s%s\n",
+			   (ret & V4L2_TUNER_SUB_MONO) ? " mono" : "",
+			   (ret & V4L2_TUNER_SUB_STEREO) ? " stereo" : "",
+			   (ret & V4L2_TUNER_SUB_LANG2) ? " dual" : "");
+
+	return ret;
+}
+EXPORT_SYMBOL(cx88_dsp_detect_stereo_sap);
+
diff --git a/drivers/media/pci/cx88/cx88-dvb.c b/drivers/media/pci/cx88/cx88-dvb.c
new file mode 100644
index 0000000..d803bba
--- /dev/null
+++ b/drivers/media/pci/cx88/cx88-dvb.c
@@ -0,0 +1,1778 @@
+/*
+ *
+ * device driver for Conexant 2388x based TV cards
+ * MPEG Transport Stream (DVB) routines
+ *
+ * (c) 2004, 2005 Chris Pascoe <c.pascoe@itee.uq.edu.au>
+ * (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the 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/init.h>
+#include <linux/device.h>
+#include <linux/fs.h>
+#include <linux/kthread.h>
+#include <linux/file.h>
+#include <linux/suspend.h>
+
+#include "cx88.h"
+#include "dvb-pll.h"
+#include <media/v4l2-common.h>
+
+#include "mt352.h"
+#include "mt352_priv.h"
+#include "cx88-vp3054-i2c.h"
+#include "zl10353.h"
+#include "cx22702.h"
+#include "or51132.h"
+#include "lgdt330x.h"
+#include "s5h1409.h"
+#include "xc4000.h"
+#include "xc5000.h"
+#include "nxt200x.h"
+#include "cx24123.h"
+#include "isl6421.h"
+#include "tuner-simple.h"
+#include "tda9887.h"
+#include "s5h1411.h"
+#include "stv0299.h"
+#include "z0194a.h"
+#include "stv0288.h"
+#include "stb6000.h"
+#include "cx24116.h"
+#include "stv0900.h"
+#include "stb6100.h"
+#include "stb6100_proc.h"
+#include "mb86a16.h"
+#include "ds3000.h"
+
+MODULE_DESCRIPTION("driver for cx2388x based DVB cards");
+MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>");
+MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(CX88_VERSION);
+
+static unsigned int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug,"enable debug messages [dvb]");
+
+static unsigned int dvb_buf_tscnt = 32;
+module_param(dvb_buf_tscnt, int, 0644);
+MODULE_PARM_DESC(dvb_buf_tscnt, "DVB Buffer TS count [dvb]");
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+#define dprintk(level,fmt, arg...)	if (debug >= level) \
+	printk(KERN_DEBUG "%s/2-dvb: " fmt, core->name, ## arg)
+
+/* ------------------------------------------------------------------ */
+
+static int dvb_buf_setup(struct videobuf_queue *q,
+			 unsigned int *count, unsigned int *size)
+{
+	struct cx8802_dev *dev = q->priv_data;
+
+	dev->ts_packet_size  = 188 * 4;
+	dev->ts_packet_count = dvb_buf_tscnt;
+
+	*size  = dev->ts_packet_size * dev->ts_packet_count;
+	*count = dvb_buf_tscnt;
+	return 0;
+}
+
+static int dvb_buf_prepare(struct videobuf_queue *q,
+			   struct videobuf_buffer *vb, enum v4l2_field field)
+{
+	struct cx8802_dev *dev = q->priv_data;
+	return cx8802_buf_prepare(q, dev, (struct cx88_buffer*)vb,field);
+}
+
+static void dvb_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
+{
+	struct cx8802_dev *dev = q->priv_data;
+	cx8802_buf_queue(dev, (struct cx88_buffer*)vb);
+}
+
+static void dvb_buf_release(struct videobuf_queue *q,
+			    struct videobuf_buffer *vb)
+{
+	cx88_free_buffer(q, (struct cx88_buffer*)vb);
+}
+
+static const struct videobuf_queue_ops dvb_qops = {
+	.buf_setup    = dvb_buf_setup,
+	.buf_prepare  = dvb_buf_prepare,
+	.buf_queue    = dvb_buf_queue,
+	.buf_release  = dvb_buf_release,
+};
+
+/* ------------------------------------------------------------------ */
+
+static int cx88_dvb_bus_ctrl(struct dvb_frontend* fe, int acquire)
+{
+	struct cx8802_dev *dev= fe->dvb->priv;
+	struct cx8802_driver *drv = NULL;
+	int ret = 0;
+	int fe_id;
+
+	fe_id = videobuf_dvb_find_frontend(&dev->frontends, fe);
+	if (!fe_id) {
+		printk(KERN_ERR "%s() No frontend found\n", __func__);
+		return -EINVAL;
+	}
+
+	mutex_lock(&dev->core->lock);
+	drv = cx8802_get_driver(dev, CX88_MPEG_DVB);
+	if (drv) {
+		if (acquire){
+			dev->frontends.active_fe_id = fe_id;
+			ret = drv->request_acquire(drv);
+		} else {
+			ret = drv->request_release(drv);
+			dev->frontends.active_fe_id = 0;
+		}
+	}
+	mutex_unlock(&dev->core->lock);
+
+	return ret;
+}
+
+static void cx88_dvb_gate_ctrl(struct cx88_core  *core, int open)
+{
+	struct videobuf_dvb_frontends *f;
+	struct videobuf_dvb_frontend *fe;
+
+	if (!core->dvbdev)
+		return;
+
+	f = &core->dvbdev->frontends;
+
+	if (!f)
+		return;
+
+	if (f->gate <= 1) /* undefined or fe0 */
+		fe = videobuf_dvb_get_frontend(f, 1);
+	else
+		fe = videobuf_dvb_get_frontend(f, f->gate);
+
+	if (fe && fe->dvb.frontend && fe->dvb.frontend->ops.i2c_gate_ctrl)
+		fe->dvb.frontend->ops.i2c_gate_ctrl(fe->dvb.frontend, open);
+}
+
+/* ------------------------------------------------------------------ */
+
+static int dvico_fusionhdtv_demod_init(struct dvb_frontend* fe)
+{
+	static const u8 clock_config []  = { CLOCK_CTL,  0x38, 0x39 };
+	static const u8 reset []         = { RESET,      0x80 };
+	static const u8 adc_ctl_1_cfg [] = { ADC_CTL_1,  0x40 };
+	static const u8 agc_cfg []       = { AGC_TARGET, 0x24, 0x20 };
+	static const u8 gpp_ctl_cfg []   = { GPP_CTL,    0x33 };
+	static const u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 };
+
+	mt352_write(fe, clock_config,   sizeof(clock_config));
+	udelay(200);
+	mt352_write(fe, reset,          sizeof(reset));
+	mt352_write(fe, adc_ctl_1_cfg,  sizeof(adc_ctl_1_cfg));
+
+	mt352_write(fe, agc_cfg,        sizeof(agc_cfg));
+	mt352_write(fe, gpp_ctl_cfg,    sizeof(gpp_ctl_cfg));
+	mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
+	return 0;
+}
+
+static int dvico_dual_demod_init(struct dvb_frontend *fe)
+{
+	static const u8 clock_config []  = { CLOCK_CTL,  0x38, 0x38 };
+	static const u8 reset []         = { RESET,      0x80 };
+	static const u8 adc_ctl_1_cfg [] = { ADC_CTL_1,  0x40 };
+	static const u8 agc_cfg []       = { AGC_TARGET, 0x28, 0x20 };
+	static const u8 gpp_ctl_cfg []   = { GPP_CTL,    0x33 };
+	static const u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 };
+
+	mt352_write(fe, clock_config,   sizeof(clock_config));
+	udelay(200);
+	mt352_write(fe, reset,          sizeof(reset));
+	mt352_write(fe, adc_ctl_1_cfg,  sizeof(adc_ctl_1_cfg));
+
+	mt352_write(fe, agc_cfg,        sizeof(agc_cfg));
+	mt352_write(fe, gpp_ctl_cfg,    sizeof(gpp_ctl_cfg));
+	mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
+
+	return 0;
+}
+
+static int dntv_live_dvbt_demod_init(struct dvb_frontend* fe)
+{
+	static const u8 clock_config []  = { 0x89, 0x38, 0x39 };
+	static const u8 reset []         = { 0x50, 0x80 };
+	static const u8 adc_ctl_1_cfg [] = { 0x8E, 0x40 };
+	static const u8 agc_cfg []       = { 0x67, 0x10, 0x23, 0x00, 0xFF, 0xFF,
+				       0x00, 0xFF, 0x00, 0x40, 0x40 };
+	static const u8 dntv_extra[]     = { 0xB5, 0x7A };
+	static const u8 capt_range_cfg[] = { 0x75, 0x32 };
+
+	mt352_write(fe, clock_config,   sizeof(clock_config));
+	udelay(2000);
+	mt352_write(fe, reset,          sizeof(reset));
+	mt352_write(fe, adc_ctl_1_cfg,  sizeof(adc_ctl_1_cfg));
+
+	mt352_write(fe, agc_cfg,        sizeof(agc_cfg));
+	udelay(2000);
+	mt352_write(fe, dntv_extra,     sizeof(dntv_extra));
+	mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
+
+	return 0;
+}
+
+static const struct mt352_config dvico_fusionhdtv = {
+	.demod_address = 0x0f,
+	.demod_init    = dvico_fusionhdtv_demod_init,
+};
+
+static const struct mt352_config dntv_live_dvbt_config = {
+	.demod_address = 0x0f,
+	.demod_init    = dntv_live_dvbt_demod_init,
+};
+
+static const struct mt352_config dvico_fusionhdtv_dual = {
+	.demod_address = 0x0f,
+	.demod_init    = dvico_dual_demod_init,
+};
+
+static const struct zl10353_config cx88_terratec_cinergy_ht_pci_mkii_config = {
+	.demod_address = (0x1e >> 1),
+	.no_tuner      = 1,
+	.if2           = 45600,
+};
+
+static struct mb86a16_config twinhan_vp1027 = {
+	.demod_address  = 0x08,
+};
+
+#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)
+{
+	static const u8 clock_config []  = { 0x89, 0x38, 0x38 };
+	static const u8 reset []         = { 0x50, 0x80 };
+	static const u8 adc_ctl_1_cfg [] = { 0x8E, 0x40 };
+	static const u8 agc_cfg []       = { 0x67, 0x10, 0x20, 0x00, 0xFF, 0xFF,
+				       0x00, 0xFF, 0x00, 0x40, 0x40 };
+	static const u8 dntv_extra[]     = { 0xB5, 0x7A };
+	static const u8 capt_range_cfg[] = { 0x75, 0x32 };
+
+	mt352_write(fe, clock_config,   sizeof(clock_config));
+	udelay(2000);
+	mt352_write(fe, reset,          sizeof(reset));
+	mt352_write(fe, adc_ctl_1_cfg,  sizeof(adc_ctl_1_cfg));
+
+	mt352_write(fe, agc_cfg,        sizeof(agc_cfg));
+	udelay(2000);
+	mt352_write(fe, dntv_extra,     sizeof(dntv_extra));
+	mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
+
+	return 0;
+}
+
+static const struct mt352_config dntv_live_dvbt_pro_config = {
+	.demod_address = 0x0f,
+	.no_tuner      = 1,
+	.demod_init    = dntv_live_dvbt_pro_demod_init,
+};
+#endif
+
+static const struct zl10353_config dvico_fusionhdtv_hybrid = {
+	.demod_address = 0x0f,
+	.no_tuner      = 1,
+};
+
+static const struct zl10353_config dvico_fusionhdtv_xc3028 = {
+	.demod_address = 0x0f,
+	.if2           = 45600,
+	.no_tuner      = 1,
+};
+
+static const struct mt352_config dvico_fusionhdtv_mt352_xc3028 = {
+	.demod_address = 0x0f,
+	.if2 = 4560,
+	.no_tuner = 1,
+	.demod_init = dvico_fusionhdtv_demod_init,
+};
+
+static const struct zl10353_config dvico_fusionhdtv_plus_v1_1 = {
+	.demod_address = 0x0f,
+};
+
+static const struct cx22702_config connexant_refboard_config = {
+	.demod_address = 0x43,
+	.output_mode   = CX22702_SERIAL_OUTPUT,
+};
+
+static const struct cx22702_config hauppauge_hvr_config = {
+	.demod_address = 0x63,
+	.output_mode   = CX22702_SERIAL_OUTPUT,
+};
+
+static int or51132_set_ts_param(struct dvb_frontend* fe, int is_punctured)
+{
+	struct cx8802_dev *dev= fe->dvb->priv;
+	dev->ts_gen_cntrl = is_punctured ? 0x04 : 0x00;
+	return 0;
+}
+
+static const struct or51132_config pchdtv_hd3000 = {
+	.demod_address = 0x15,
+	.set_ts_params = or51132_set_ts_param,
+};
+
+static int lgdt330x_pll_rf_set(struct dvb_frontend* fe, int index)
+{
+	struct cx8802_dev *dev= fe->dvb->priv;
+	struct cx88_core *core = dev->core;
+
+	dprintk(1, "%s: index = %d\n", __func__, index);
+	if (index == 0)
+		cx_clear(MO_GP0_IO, 8);
+	else
+		cx_set(MO_GP0_IO, 8);
+	return 0;
+}
+
+static int lgdt330x_set_ts_param(struct dvb_frontend* fe, int is_punctured)
+{
+	struct cx8802_dev *dev= fe->dvb->priv;
+	if (is_punctured)
+		dev->ts_gen_cntrl |= 0x04;
+	else
+		dev->ts_gen_cntrl &= ~0x04;
+	return 0;
+}
+
+static struct lgdt330x_config fusionhdtv_3_gold = {
+	.demod_address = 0x0e,
+	.demod_chip    = LGDT3302,
+	.serial_mpeg   = 0x04, /* TPSERIAL for 3302 in TOP_CONTROL */
+	.set_ts_params = lgdt330x_set_ts_param,
+};
+
+static const struct lgdt330x_config fusionhdtv_5_gold = {
+	.demod_address = 0x0e,
+	.demod_chip    = LGDT3303,
+	.serial_mpeg   = 0x40, /* TPSERIAL for 3303 in TOP_CONTROL */
+	.set_ts_params = lgdt330x_set_ts_param,
+};
+
+static const struct lgdt330x_config pchdtv_hd5500 = {
+	.demod_address = 0x59,
+	.demod_chip    = LGDT3303,
+	.serial_mpeg   = 0x40, /* TPSERIAL for 3303 in TOP_CONTROL */
+	.set_ts_params = lgdt330x_set_ts_param,
+};
+
+static int nxt200x_set_ts_param(struct dvb_frontend* fe, int is_punctured)
+{
+	struct cx8802_dev *dev= fe->dvb->priv;
+	dev->ts_gen_cntrl = is_punctured ? 0x04 : 0x00;
+	return 0;
+}
+
+static const struct nxt200x_config ati_hdtvwonder = {
+	.demod_address = 0x0a,
+	.set_ts_params = nxt200x_set_ts_param,
+};
+
+static int cx24123_set_ts_param(struct dvb_frontend* fe,
+	int is_punctured)
+{
+	struct cx8802_dev *dev= fe->dvb->priv;
+	dev->ts_gen_cntrl = 0x02;
+	return 0;
+}
+
+static int kworld_dvbs_100_set_voltage(struct dvb_frontend* fe,
+				       fe_sec_voltage_t voltage)
+{
+	struct cx8802_dev *dev= fe->dvb->priv;
+	struct cx88_core *core = dev->core;
+
+	if (voltage == SEC_VOLTAGE_OFF)
+		cx_write(MO_GP0_IO, 0x000006fb);
+	else
+		cx_write(MO_GP0_IO, 0x000006f9);
+
+	if (core->prev_set_voltage)
+		return core->prev_set_voltage(fe, voltage);
+	return 0;
+}
+
+static int geniatech_dvbs_set_voltage(struct dvb_frontend *fe,
+				      fe_sec_voltage_t voltage)
+{
+	struct cx8802_dev *dev= fe->dvb->priv;
+	struct cx88_core *core = dev->core;
+
+	if (voltage == SEC_VOLTAGE_OFF) {
+		dprintk(1,"LNB Voltage OFF\n");
+		cx_write(MO_GP0_IO, 0x0000efff);
+	}
+
+	if (core->prev_set_voltage)
+		return core->prev_set_voltage(fe, voltage);
+	return 0;
+}
+
+static int tevii_dvbs_set_voltage(struct dvb_frontend *fe,
+				      fe_sec_voltage_t voltage)
+{
+	struct cx8802_dev *dev= fe->dvb->priv;
+	struct cx88_core *core = dev->core;
+
+	cx_set(MO_GP0_IO, 0x6040);
+	switch (voltage) {
+	case SEC_VOLTAGE_13:
+		cx_clear(MO_GP0_IO, 0x20);
+		break;
+	case SEC_VOLTAGE_18:
+		cx_set(MO_GP0_IO, 0x20);
+		break;
+	case SEC_VOLTAGE_OFF:
+		cx_clear(MO_GP0_IO, 0x20);
+		break;
+	}
+
+	if (core->prev_set_voltage)
+		return core->prev_set_voltage(fe, voltage);
+	return 0;
+}
+
+static int vp1027_set_voltage(struct dvb_frontend *fe,
+				    fe_sec_voltage_t voltage)
+{
+	struct cx8802_dev *dev = fe->dvb->priv;
+	struct cx88_core *core = dev->core;
+
+	switch (voltage) {
+	case SEC_VOLTAGE_13:
+		dprintk(1, "LNB SEC Voltage=13\n");
+		cx_write(MO_GP0_IO, 0x00001220);
+		break;
+	case SEC_VOLTAGE_18:
+		dprintk(1, "LNB SEC Voltage=18\n");
+		cx_write(MO_GP0_IO, 0x00001222);
+		break;
+	case SEC_VOLTAGE_OFF:
+		dprintk(1, "LNB Voltage OFF\n");
+		cx_write(MO_GP0_IO, 0x00001230);
+		break;
+	}
+
+	if (core->prev_set_voltage)
+		return core->prev_set_voltage(fe, voltage);
+	return 0;
+}
+
+static const struct cx24123_config geniatech_dvbs_config = {
+	.demod_address = 0x55,
+	.set_ts_params = cx24123_set_ts_param,
+};
+
+static const struct cx24123_config hauppauge_novas_config = {
+	.demod_address = 0x55,
+	.set_ts_params = cx24123_set_ts_param,
+};
+
+static const struct cx24123_config kworld_dvbs_100_config = {
+	.demod_address = 0x15,
+	.set_ts_params = cx24123_set_ts_param,
+	.lnb_polarity  = 1,
+};
+
+static const struct s5h1409_config pinnacle_pctv_hd_800i_config = {
+	.demod_address = 0x32 >> 1,
+	.output_mode   = S5H1409_PARALLEL_OUTPUT,
+	.gpio	       = S5H1409_GPIO_ON,
+	.qam_if	       = 44000,
+	.inversion     = S5H1409_INVERSION_OFF,
+	.status_mode   = S5H1409_DEMODLOCKING,
+	.mpeg_timing   = S5H1409_MPEGTIMING_NONCONTINOUS_NONINVERTING_CLOCK,
+};
+
+static const struct s5h1409_config dvico_hdtv5_pci_nano_config = {
+	.demod_address = 0x32 >> 1,
+	.output_mode   = S5H1409_SERIAL_OUTPUT,
+	.gpio          = S5H1409_GPIO_OFF,
+	.inversion     = S5H1409_INVERSION_OFF,
+	.status_mode   = S5H1409_DEMODLOCKING,
+	.mpeg_timing   = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
+};
+
+static const struct s5h1409_config kworld_atsc_120_config = {
+	.demod_address = 0x32 >> 1,
+	.output_mode   = S5H1409_SERIAL_OUTPUT,
+	.gpio	       = S5H1409_GPIO_OFF,
+	.inversion     = S5H1409_INVERSION_OFF,
+	.status_mode   = S5H1409_DEMODLOCKING,
+	.mpeg_timing   = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
+};
+
+static const struct xc5000_config pinnacle_pctv_hd_800i_tuner_config = {
+	.i2c_address	= 0x64,
+	.if_khz		= 5380,
+};
+
+static const struct zl10353_config cx88_pinnacle_hybrid_pctv = {
+	.demod_address = (0x1e >> 1),
+	.no_tuner      = 1,
+	.if2           = 45600,
+};
+
+static const struct zl10353_config cx88_geniatech_x8000_mt = {
+	.demod_address = (0x1e >> 1),
+	.no_tuner = 1,
+	.disable_i2c_gate_ctrl = 1,
+};
+
+static const struct s5h1411_config dvico_fusionhdtv7_config = {
+	.output_mode   = S5H1411_SERIAL_OUTPUT,
+	.gpio          = S5H1411_GPIO_ON,
+	.mpeg_timing   = S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
+	.qam_if        = S5H1411_IF_44000,
+	.vsb_if        = S5H1411_IF_44000,
+	.inversion     = S5H1411_INVERSION_OFF,
+	.status_mode   = S5H1411_DEMODLOCKING
+};
+
+static const struct xc5000_config dvico_fusionhdtv7_tuner_config = {
+	.i2c_address    = 0xc2 >> 1,
+	.if_khz         = 5380,
+};
+
+static int attach_xc3028(u8 addr, struct cx8802_dev *dev)
+{
+	struct dvb_frontend *fe;
+	struct videobuf_dvb_frontend *fe0 = NULL;
+	struct xc2028_ctrl ctl;
+	struct xc2028_config cfg = {
+		.i2c_adap  = &dev->core->i2c_adap,
+		.i2c_addr  = addr,
+		.ctrl      = &ctl,
+	};
+
+	/* Get the first frontend */
+	fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1);
+	if (!fe0)
+		return -EINVAL;
+
+	if (!fe0->dvb.frontend) {
+		printk(KERN_ERR "%s/2: dvb frontend not attached. "
+				"Can't attach xc3028\n",
+		       dev->core->name);
+		return -EINVAL;
+	}
+
+	/*
+	 * Some xc3028 devices may be hidden by an I2C gate. This is known
+	 * to happen with some s5h1409-based devices.
+	 * Now that I2C gate is open, sets up xc3028 configuration
+	 */
+	cx88_setup_xc3028(dev->core, &ctl);
+
+	fe = dvb_attach(xc2028_attach, fe0->dvb.frontend, &cfg);
+	if (!fe) {
+		printk(KERN_ERR "%s/2: xc3028 attach failed\n",
+		       dev->core->name);
+		dvb_frontend_detach(fe0->dvb.frontend);
+		dvb_unregister_frontend(fe0->dvb.frontend);
+		fe0->dvb.frontend = NULL;
+		return -EINVAL;
+	}
+
+	printk(KERN_INFO "%s/2: xc3028 attached\n",
+	       dev->core->name);
+
+	return 0;
+}
+
+static int attach_xc4000(struct cx8802_dev *dev, struct xc4000_config *cfg)
+{
+	struct dvb_frontend *fe;
+	struct videobuf_dvb_frontend *fe0 = NULL;
+
+	/* Get the first frontend */
+	fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1);
+	if (!fe0)
+		return -EINVAL;
+
+	if (!fe0->dvb.frontend) {
+		printk(KERN_ERR "%s/2: dvb frontend not attached. "
+				"Can't attach xc4000\n",
+		       dev->core->name);
+		return -EINVAL;
+	}
+
+	fe = dvb_attach(xc4000_attach, fe0->dvb.frontend, &dev->core->i2c_adap,
+			cfg);
+	if (!fe) {
+		printk(KERN_ERR "%s/2: xc4000 attach failed\n",
+		       dev->core->name);
+		dvb_frontend_detach(fe0->dvb.frontend);
+		dvb_unregister_frontend(fe0->dvb.frontend);
+		fe0->dvb.frontend = NULL;
+		return -EINVAL;
+	}
+
+	printk(KERN_INFO "%s/2: xc4000 attached\n", dev->core->name);
+
+	return 0;
+}
+
+static int cx24116_set_ts_param(struct dvb_frontend *fe,
+	int is_punctured)
+{
+	struct cx8802_dev *dev = fe->dvb->priv;
+	dev->ts_gen_cntrl = 0x2;
+
+	return 0;
+}
+
+static int stv0900_set_ts_param(struct dvb_frontend *fe,
+	int is_punctured)
+{
+	struct cx8802_dev *dev = fe->dvb->priv;
+	dev->ts_gen_cntrl = 0;
+
+	return 0;
+}
+
+static int cx24116_reset_device(struct dvb_frontend *fe)
+{
+	struct cx8802_dev *dev = fe->dvb->priv;
+	struct cx88_core *core = dev->core;
+
+	/* Reset the part */
+	/* Put the cx24116 into reset */
+	cx_write(MO_SRST_IO, 0);
+	msleep(10);
+	/* Take the cx24116 out of reset */
+	cx_write(MO_SRST_IO, 1);
+	msleep(10);
+
+	return 0;
+}
+
+static const struct cx24116_config hauppauge_hvr4000_config = {
+	.demod_address          = 0x05,
+	.set_ts_params          = cx24116_set_ts_param,
+	.reset_device           = cx24116_reset_device,
+};
+
+static const struct cx24116_config tevii_s460_config = {
+	.demod_address = 0x55,
+	.set_ts_params = cx24116_set_ts_param,
+	.reset_device  = cx24116_reset_device,
+};
+
+static int ds3000_set_ts_param(struct dvb_frontend *fe,
+	int is_punctured)
+{
+	struct cx8802_dev *dev = fe->dvb->priv;
+	dev->ts_gen_cntrl = 4;
+
+	return 0;
+}
+
+static struct ds3000_config tevii_ds3000_config = {
+	.demod_address = 0x68,
+	.set_ts_params = ds3000_set_ts_param,
+};
+
+static const struct stv0900_config prof_7301_stv0900_config = {
+	.demod_address = 0x6a,
+/*	demod_mode = 0,*/
+	.xtal = 27000000,
+	.clkmode = 3,/* 0-CLKI, 2-XTALI, else AUTO */
+	.diseqc_mode = 2,/* 2/3 PWM */
+	.tun1_maddress = 0,/* 0x60 */
+	.tun1_adc = 0,/* 2 Vpp */
+	.path1_mode = 3,
+	.set_ts_params = stv0900_set_ts_param,
+};
+
+static const struct stb6100_config prof_7301_stb6100_config = {
+	.tuner_address = 0x60,
+	.refclock = 27000000,
+};
+
+static const struct stv0299_config tevii_tuner_sharp_config = {
+	.demod_address = 0x68,
+	.inittab = sharp_z0194a_inittab,
+	.mclk = 88000000UL,
+	.invert = 1,
+	.skip_reinit = 0,
+	.lock_output = 1,
+	.volt13_op0_op1 = STV0299_VOLT13_OP1,
+	.min_delay_ms = 100,
+	.set_symbol_rate = sharp_z0194a_set_symbol_rate,
+	.set_ts_params = cx24116_set_ts_param,
+};
+
+static const struct stv0288_config tevii_tuner_earda_config = {
+	.demod_address = 0x68,
+	.min_delay_ms = 100,
+	.set_ts_params = cx24116_set_ts_param,
+};
+
+static int cx8802_alloc_frontends(struct cx8802_dev *dev)
+{
+	struct cx88_core *core = dev->core;
+	struct videobuf_dvb_frontend *fe = NULL;
+	int i;
+
+	mutex_init(&dev->frontends.lock);
+	INIT_LIST_HEAD(&dev->frontends.felist);
+
+	if (!core->board.num_frontends)
+		return -ENODEV;
+
+	printk(KERN_INFO "%s() allocating %d frontend(s)\n", __func__,
+			 core->board.num_frontends);
+	for (i = 1; i <= core->board.num_frontends; i++) {
+		fe = videobuf_dvb_alloc_frontend(&dev->frontends, i);
+		if (!fe) {
+			printk(KERN_ERR "%s() failed to alloc\n", __func__);
+			videobuf_dvb_dealloc_frontends(&dev->frontends);
+			return -ENOMEM;
+		}
+	}
+	return 0;
+}
+
+
+
+static const u8 samsung_smt_7020_inittab[] = {
+	     0x01, 0x15,
+	     0x02, 0x00,
+	     0x03, 0x00,
+	     0x04, 0x7D,
+	     0x05, 0x0F,
+	     0x06, 0x02,
+	     0x07, 0x00,
+	     0x08, 0x60,
+
+	     0x0A, 0xC2,
+	     0x0B, 0x00,
+	     0x0C, 0x01,
+	     0x0D, 0x81,
+	     0x0E, 0x44,
+	     0x0F, 0x09,
+	     0x10, 0x3C,
+	     0x11, 0x84,
+	     0x12, 0xDA,
+	     0x13, 0x99,
+	     0x14, 0x8D,
+	     0x15, 0xCE,
+	     0x16, 0xE8,
+	     0x17, 0x43,
+	     0x18, 0x1C,
+	     0x19, 0x1B,
+	     0x1A, 0x1D,
+
+	     0x1C, 0x12,
+	     0x1D, 0x00,
+	     0x1E, 0x00,
+	     0x1F, 0x00,
+	     0x20, 0x00,
+	     0x21, 0x00,
+	     0x22, 0x00,
+	     0x23, 0x00,
+
+	     0x28, 0x02,
+	     0x29, 0x28,
+	     0x2A, 0x14,
+	     0x2B, 0x0F,
+	     0x2C, 0x09,
+	     0x2D, 0x05,
+
+	     0x31, 0x1F,
+	     0x32, 0x19,
+	     0x33, 0xFC,
+	     0x34, 0x13,
+	     0xff, 0xff,
+};
+
+
+static int samsung_smt_7020_tuner_set_params(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+	struct cx8802_dev *dev = fe->dvb->priv;
+	u8 buf[4];
+	u32 div;
+	struct i2c_msg msg = {
+		.addr = 0x61,
+		.flags = 0,
+		.buf = buf,
+		.len = sizeof(buf) };
+
+	div = c->frequency / 125;
+
+	buf[0] = (div >> 8) & 0x7f;
+	buf[1] = div & 0xff;
+	buf[2] = 0x84;  /* 0xC4 */
+	buf[3] = 0x00;
+
+	if (c->frequency < 1500000)
+		buf[3] |= 0x10;
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+
+	if (i2c_transfer(&dev->core->i2c_adap, &msg, 1) != 1)
+		return -EIO;
+
+	return 0;
+}
+
+static int samsung_smt_7020_set_tone(struct dvb_frontend *fe,
+	fe_sec_tone_mode_t tone)
+{
+	struct cx8802_dev *dev = fe->dvb->priv;
+	struct cx88_core *core = dev->core;
+
+	cx_set(MO_GP0_IO, 0x0800);
+
+	switch (tone) {
+	case SEC_TONE_ON:
+		cx_set(MO_GP0_IO, 0x08);
+		break;
+	case SEC_TONE_OFF:
+		cx_clear(MO_GP0_IO, 0x08);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int samsung_smt_7020_set_voltage(struct dvb_frontend *fe,
+	fe_sec_voltage_t voltage)
+{
+	struct cx8802_dev *dev = fe->dvb->priv;
+	struct cx88_core *core = dev->core;
+
+	u8 data;
+	struct i2c_msg msg = {
+		.addr = 8,
+		.flags = 0,
+		.buf = &data,
+		.len = sizeof(data) };
+
+	cx_set(MO_GP0_IO, 0x8000);
+
+	switch (voltage) {
+	case SEC_VOLTAGE_OFF:
+		break;
+	case SEC_VOLTAGE_13:
+		data = ISL6421_EN1 | ISL6421_LLC1;
+		cx_clear(MO_GP0_IO, 0x80);
+		break;
+	case SEC_VOLTAGE_18:
+		data = ISL6421_EN1 | ISL6421_LLC1 | ISL6421_VSEL1;
+		cx_clear(MO_GP0_IO, 0x80);
+		break;
+	default:
+		return -EINVAL;
+	};
+
+	return (i2c_transfer(&dev->core->i2c_adap, &msg, 1) == 1) ? 0 : -EIO;
+}
+
+static int samsung_smt_7020_stv0299_set_symbol_rate(struct dvb_frontend *fe,
+	u32 srate, u32 ratio)
+{
+	u8 aclk = 0;
+	u8 bclk = 0;
+
+	if (srate < 1500000) {
+		aclk = 0xb7;
+		bclk = 0x47;
+	} else if (srate < 3000000) {
+		aclk = 0xb7;
+		bclk = 0x4b;
+	} else if (srate < 7000000) {
+		aclk = 0xb7;
+		bclk = 0x4f;
+	} else if (srate < 14000000) {
+		aclk = 0xb7;
+		bclk = 0x53;
+	} else if (srate < 30000000) {
+		aclk = 0xb6;
+		bclk = 0x53;
+	} else if (srate < 45000000) {
+		aclk = 0xb4;
+		bclk = 0x51;
+	}
+
+	stv0299_writereg(fe, 0x13, aclk);
+	stv0299_writereg(fe, 0x14, bclk);
+	stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
+	stv0299_writereg(fe, 0x20, (ratio >>  8) & 0xff);
+	stv0299_writereg(fe, 0x21, ratio & 0xf0);
+
+	return 0;
+}
+
+
+static const struct stv0299_config samsung_stv0299_config = {
+	.demod_address = 0x68,
+	.inittab = samsung_smt_7020_inittab,
+	.mclk = 88000000UL,
+	.invert = 0,
+	.skip_reinit = 0,
+	.lock_output = STV0299_LOCKOUTPUT_LK,
+	.volt13_op0_op1 = STV0299_VOLT13_OP1,
+	.min_delay_ms = 100,
+	.set_symbol_rate = samsung_smt_7020_stv0299_set_symbol_rate,
+};
+
+static int dvb_register(struct cx8802_dev *dev)
+{
+	struct cx88_core *core = dev->core;
+	struct videobuf_dvb_frontend *fe0, *fe1 = NULL;
+	int mfe_shared = 0; /* bus not shared by default */
+	int res = -EINVAL;
+
+	if (0 != core->i2c_rc) {
+		printk(KERN_ERR "%s/2: no i2c-bus available, cannot attach dvb drivers\n", core->name);
+		goto frontend_detach;
+	}
+
+	/* Get the first frontend */
+	fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1);
+	if (!fe0)
+		goto frontend_detach;
+
+	/* multi-frontend gate control is undefined or defaults to fe0 */
+	dev->frontends.gate = 0;
+
+	/* Sets the gate control callback to be used by i2c command calls */
+	core->gate_ctrl = cx88_dvb_gate_ctrl;
+
+	/* init frontend(s) */
+	switch (core->boardnr) {
+	case CX88_BOARD_HAUPPAUGE_DVB_T1:
+		fe0->dvb.frontend = dvb_attach(cx22702_attach,
+					       &connexant_refboard_config,
+					       &core->i2c_adap);
+		if (fe0->dvb.frontend != NULL) {
+			if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
+					0x61, &core->i2c_adap,
+					DVB_PLL_THOMSON_DTT759X))
+				goto frontend_detach;
+		}
+		break;
+	case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1:
+	case CX88_BOARD_CONEXANT_DVB_T1:
+	case CX88_BOARD_KWORLD_DVB_T_CX22702:
+	case CX88_BOARD_WINFAST_DTV1000:
+		fe0->dvb.frontend = dvb_attach(cx22702_attach,
+					       &connexant_refboard_config,
+					       &core->i2c_adap);
+		if (fe0->dvb.frontend != NULL) {
+			if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
+					0x60, &core->i2c_adap,
+					DVB_PLL_THOMSON_DTT7579))
+				goto frontend_detach;
+		}
+		break;
+	case CX88_BOARD_WINFAST_DTV2000H:
+	case CX88_BOARD_HAUPPAUGE_HVR1100:
+	case CX88_BOARD_HAUPPAUGE_HVR1100LP:
+	case CX88_BOARD_HAUPPAUGE_HVR1300:
+		fe0->dvb.frontend = dvb_attach(cx22702_attach,
+					       &hauppauge_hvr_config,
+					       &core->i2c_adap);
+		if (fe0->dvb.frontend != NULL) {
+			if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
+				   &core->i2c_adap, 0x61,
+				   TUNER_PHILIPS_FMD1216ME_MK3))
+				goto frontend_detach;
+		}
+		break;
+	case CX88_BOARD_WINFAST_DTV2000H_J:
+		fe0->dvb.frontend = dvb_attach(cx22702_attach,
+					       &hauppauge_hvr_config,
+					       &core->i2c_adap);
+		if (fe0->dvb.frontend != NULL) {
+			if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
+				   &core->i2c_adap, 0x61,
+				   TUNER_PHILIPS_FMD1216MEX_MK3))
+				goto frontend_detach;
+		}
+		break;
+	case CX88_BOARD_HAUPPAUGE_HVR3000:
+		/* MFE frontend 1 */
+		mfe_shared = 1;
+		dev->frontends.gate = 2;
+		/* DVB-S init */
+		fe0->dvb.frontend = dvb_attach(cx24123_attach,
+					&hauppauge_novas_config,
+					&dev->core->i2c_adap);
+		if (fe0->dvb.frontend) {
+			if (!dvb_attach(isl6421_attach,
+					fe0->dvb.frontend,
+					&dev->core->i2c_adap,
+					0x08, ISL6421_DCL, 0x00))
+				goto frontend_detach;
+		}
+		/* MFE frontend 2 */
+		fe1 = videobuf_dvb_get_frontend(&dev->frontends, 2);
+		if (!fe1)
+			goto frontend_detach;
+		/* DVB-T init */
+		fe1->dvb.frontend = dvb_attach(cx22702_attach,
+					&hauppauge_hvr_config,
+					&dev->core->i2c_adap);
+		if (fe1->dvb.frontend) {
+			fe1->dvb.frontend->id = 1;
+			if (!dvb_attach(simple_tuner_attach,
+					fe1->dvb.frontend,
+					&dev->core->i2c_adap,
+					0x61, TUNER_PHILIPS_FMD1216ME_MK3))
+				goto frontend_detach;
+		}
+		break;
+	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS:
+		fe0->dvb.frontend = dvb_attach(mt352_attach,
+					       &dvico_fusionhdtv,
+					       &core->i2c_adap);
+		if (fe0->dvb.frontend != NULL) {
+			if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
+					0x60, NULL, DVB_PLL_THOMSON_DTT7579))
+				goto frontend_detach;
+			break;
+		}
+		/* ZL10353 replaces MT352 on later cards */
+		fe0->dvb.frontend = dvb_attach(zl10353_attach,
+					       &dvico_fusionhdtv_plus_v1_1,
+					       &core->i2c_adap);
+		if (fe0->dvb.frontend != NULL) {
+			if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
+					0x60, NULL, DVB_PLL_THOMSON_DTT7579))
+				goto frontend_detach;
+		}
+		break;
+	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL:
+		/* The tin box says DEE1601, but it seems to be DTT7579
+		 * compatible, with a slightly different MT352 AGC gain. */
+		fe0->dvb.frontend = dvb_attach(mt352_attach,
+					       &dvico_fusionhdtv_dual,
+					       &core->i2c_adap);
+		if (fe0->dvb.frontend != NULL) {
+			if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
+					0x61, NULL, DVB_PLL_THOMSON_DTT7579))
+				goto frontend_detach;
+			break;
+		}
+		/* ZL10353 replaces MT352 on later cards */
+		fe0->dvb.frontend = dvb_attach(zl10353_attach,
+					       &dvico_fusionhdtv_plus_v1_1,
+					       &core->i2c_adap);
+		if (fe0->dvb.frontend != NULL) {
+			if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
+					0x61, NULL, DVB_PLL_THOMSON_DTT7579))
+				goto frontend_detach;
+		}
+		break;
+	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1:
+		fe0->dvb.frontend = dvb_attach(mt352_attach,
+					       &dvico_fusionhdtv,
+					       &core->i2c_adap);
+		if (fe0->dvb.frontend != NULL) {
+			if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
+					0x61, NULL, DVB_PLL_LG_Z201))
+				goto frontend_detach;
+		}
+		break;
+	case CX88_BOARD_KWORLD_DVB_T:
+	case CX88_BOARD_DNTV_LIVE_DVB_T:
+	case CX88_BOARD_ADSTECH_DVB_T_PCI:
+		fe0->dvb.frontend = dvb_attach(mt352_attach,
+					       &dntv_live_dvbt_config,
+					       &core->i2c_adap);
+		if (fe0->dvb.frontend != NULL) {
+			if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
+					0x61, NULL, DVB_PLL_UNKNOWN_1))
+				goto frontend_detach;
+		}
+		break;
+	case CX88_BOARD_DNTV_LIVE_DVB_T_PRO:
+#if defined(CONFIG_VIDEO_CX88_VP3054) || (defined(CONFIG_VIDEO_CX88_VP3054_MODULE) && defined(MODULE))
+		/* MT352 is on a secondary I2C bus made from some GPIO lines */
+		fe0->dvb.frontend = dvb_attach(mt352_attach, &dntv_live_dvbt_pro_config,
+					       &dev->vp3054->adap);
+		if (fe0->dvb.frontend != NULL) {
+			if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
+					&core->i2c_adap, 0x61,
+					TUNER_PHILIPS_FMD1216ME_MK3))
+				goto frontend_detach;
+		}
+#else
+		printk(KERN_ERR "%s/2: built without vp3054 support\n",
+				core->name);
+#endif
+		break;
+	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID:
+		fe0->dvb.frontend = dvb_attach(zl10353_attach,
+					       &dvico_fusionhdtv_hybrid,
+					       &core->i2c_adap);
+		if (fe0->dvb.frontend != NULL) {
+			if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
+				   &core->i2c_adap, 0x61,
+				   TUNER_THOMSON_FE6600))
+				goto frontend_detach;
+		}
+		break;
+	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO:
+		fe0->dvb.frontend = dvb_attach(zl10353_attach,
+					       &dvico_fusionhdtv_xc3028,
+					       &core->i2c_adap);
+		if (fe0->dvb.frontend == NULL)
+			fe0->dvb.frontend = dvb_attach(mt352_attach,
+						&dvico_fusionhdtv_mt352_xc3028,
+						&core->i2c_adap);
+		/*
+		 * On this board, the demod provides the I2C bus pullup.
+		 * We must not permit gate_ctrl to be performed, or
+		 * the xc3028 cannot communicate on the bus.
+		 */
+		if (fe0->dvb.frontend)
+			fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL;
+		if (attach_xc3028(0x61, dev) < 0)
+			goto frontend_detach;
+		break;
+	case CX88_BOARD_PCHDTV_HD3000:
+		fe0->dvb.frontend = dvb_attach(or51132_attach, &pchdtv_hd3000,
+					       &core->i2c_adap);
+		if (fe0->dvb.frontend != NULL) {
+			if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
+					&core->i2c_adap, 0x61,
+					TUNER_THOMSON_DTT761X))
+				goto frontend_detach;
+		}
+		break;
+	case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q:
+		dev->ts_gen_cntrl = 0x08;
+
+		/* Do a hardware reset of chip before using it. */
+		cx_clear(MO_GP0_IO, 1);
+		mdelay(100);
+		cx_set(MO_GP0_IO, 1);
+		mdelay(200);
+
+		/* Select RF connector callback */
+		fusionhdtv_3_gold.pll_rf_set = lgdt330x_pll_rf_set;
+		fe0->dvb.frontend = dvb_attach(lgdt330x_attach,
+					       &fusionhdtv_3_gold,
+					       &core->i2c_adap);
+		if (fe0->dvb.frontend != NULL) {
+			if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
+					&core->i2c_adap, 0x61,
+					TUNER_MICROTUNE_4042FI5))
+				goto frontend_detach;
+		}
+		break;
+	case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T:
+		dev->ts_gen_cntrl = 0x08;
+
+		/* Do a hardware reset of chip before using it. */
+		cx_clear(MO_GP0_IO, 1);
+		mdelay(100);
+		cx_set(MO_GP0_IO, 9);
+		mdelay(200);
+		fe0->dvb.frontend = dvb_attach(lgdt330x_attach,
+					       &fusionhdtv_3_gold,
+					       &core->i2c_adap);
+		if (fe0->dvb.frontend != NULL) {
+			if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
+					&core->i2c_adap, 0x61,
+					TUNER_THOMSON_DTT761X))
+				goto frontend_detach;
+		}
+		break;
+	case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD:
+		dev->ts_gen_cntrl = 0x08;
+
+		/* Do a hardware reset of chip before using it. */
+		cx_clear(MO_GP0_IO, 1);
+		mdelay(100);
+		cx_set(MO_GP0_IO, 1);
+		mdelay(200);
+		fe0->dvb.frontend = dvb_attach(lgdt330x_attach,
+					       &fusionhdtv_5_gold,
+					       &core->i2c_adap);
+		if (fe0->dvb.frontend != NULL) {
+			if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
+					&core->i2c_adap, 0x61,
+					TUNER_LG_TDVS_H06XF))
+				goto frontend_detach;
+			if (!dvb_attach(tda9887_attach, fe0->dvb.frontend,
+				   &core->i2c_adap, 0x43))
+				goto frontend_detach;
+		}
+		break;
+	case CX88_BOARD_PCHDTV_HD5500:
+		dev->ts_gen_cntrl = 0x08;
+
+		/* Do a hardware reset of chip before using it. */
+		cx_clear(MO_GP0_IO, 1);
+		mdelay(100);
+		cx_set(MO_GP0_IO, 1);
+		mdelay(200);
+		fe0->dvb.frontend = dvb_attach(lgdt330x_attach,
+					       &pchdtv_hd5500,
+					       &core->i2c_adap);
+		if (fe0->dvb.frontend != NULL) {
+			if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
+					&core->i2c_adap, 0x61,
+					TUNER_LG_TDVS_H06XF))
+				goto frontend_detach;
+			if (!dvb_attach(tda9887_attach, fe0->dvb.frontend,
+				   &core->i2c_adap, 0x43))
+				goto frontend_detach;
+		}
+		break;
+	case CX88_BOARD_ATI_HDTVWONDER:
+		fe0->dvb.frontend = dvb_attach(nxt200x_attach,
+					       &ati_hdtvwonder,
+					       &core->i2c_adap);
+		if (fe0->dvb.frontend != NULL) {
+			if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
+					&core->i2c_adap, 0x61,
+					TUNER_PHILIPS_TUV1236D))
+				goto frontend_detach;
+		}
+		break;
+	case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
+	case CX88_BOARD_HAUPPAUGE_NOVASE2_S1:
+		fe0->dvb.frontend = dvb_attach(cx24123_attach,
+					       &hauppauge_novas_config,
+					       &core->i2c_adap);
+		if (fe0->dvb.frontend) {
+			if (!dvb_attach(isl6421_attach, fe0->dvb.frontend,
+					&core->i2c_adap, 0x08, ISL6421_DCL, 0x00))
+				goto frontend_detach;
+		}
+		break;
+	case CX88_BOARD_KWORLD_DVBS_100:
+		fe0->dvb.frontend = dvb_attach(cx24123_attach,
+					       &kworld_dvbs_100_config,
+					       &core->i2c_adap);
+		if (fe0->dvb.frontend) {
+			core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage;
+			fe0->dvb.frontend->ops.set_voltage = kworld_dvbs_100_set_voltage;
+		}
+		break;
+	case CX88_BOARD_GENIATECH_DVBS:
+		fe0->dvb.frontend = dvb_attach(cx24123_attach,
+					       &geniatech_dvbs_config,
+					       &core->i2c_adap);
+		if (fe0->dvb.frontend) {
+			core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage;
+			fe0->dvb.frontend->ops.set_voltage = geniatech_dvbs_set_voltage;
+		}
+		break;
+	case CX88_BOARD_PINNACLE_PCTV_HD_800i:
+		fe0->dvb.frontend = dvb_attach(s5h1409_attach,
+					       &pinnacle_pctv_hd_800i_config,
+					       &core->i2c_adap);
+		if (fe0->dvb.frontend != NULL) {
+			if (!dvb_attach(xc5000_attach, fe0->dvb.frontend,
+					&core->i2c_adap,
+					&pinnacle_pctv_hd_800i_tuner_config))
+				goto frontend_detach;
+		}
+		break;
+	case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
+		fe0->dvb.frontend = dvb_attach(s5h1409_attach,
+						&dvico_hdtv5_pci_nano_config,
+						&core->i2c_adap);
+		if (fe0->dvb.frontend != NULL) {
+			struct dvb_frontend *fe;
+			struct xc2028_config cfg = {
+				.i2c_adap  = &core->i2c_adap,
+				.i2c_addr  = 0x61,
+			};
+			static struct xc2028_ctrl ctl = {
+				.fname       = XC2028_DEFAULT_FIRMWARE,
+				.max_len     = 64,
+				.scode_table = XC3028_FE_OREN538,
+			};
+
+			fe = dvb_attach(xc2028_attach,
+					fe0->dvb.frontend, &cfg);
+			if (fe != NULL && fe->ops.tuner_ops.set_config != NULL)
+				fe->ops.tuner_ops.set_config(fe, &ctl);
+		}
+		break;
+	case CX88_BOARD_PINNACLE_HYBRID_PCTV:
+	case CX88_BOARD_WINFAST_DTV1800H:
+		fe0->dvb.frontend = dvb_attach(zl10353_attach,
+					       &cx88_pinnacle_hybrid_pctv,
+					       &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;
+	case CX88_BOARD_WINFAST_DTV1800H_XC4000:
+	case CX88_BOARD_WINFAST_DTV2000H_PLUS:
+		fe0->dvb.frontend = dvb_attach(zl10353_attach,
+					       &cx88_pinnacle_hybrid_pctv,
+					       &core->i2c_adap);
+		if (fe0->dvb.frontend) {
+			struct xc4000_config cfg = {
+				.i2c_address	  = 0x61,
+				.default_pm	  = 0,
+				.dvb_amplitude	  = 134,
+				.set_smoothedcvbs = 1,
+				.if_khz		  = 4560
+			};
+			fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL;
+			if (attach_xc4000(dev, &cfg) < 0)
+				goto frontend_detach;
+		}
+		break;
+	case CX88_BOARD_GENIATECH_X8000_MT:
+		dev->ts_gen_cntrl = 0x00;
+
+		fe0->dvb.frontend = dvb_attach(zl10353_attach,
+					       &cx88_geniatech_x8000_mt,
+					       &core->i2c_adap);
+		if (attach_xc3028(0x61, dev) < 0)
+			goto frontend_detach;
+		break;
+	 case CX88_BOARD_KWORLD_ATSC_120:
+		fe0->dvb.frontend = dvb_attach(s5h1409_attach,
+					       &kworld_atsc_120_config,
+					       &core->i2c_adap);
+		if (attach_xc3028(0x61, dev) < 0)
+			goto frontend_detach;
+		break;
+	case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD:
+		fe0->dvb.frontend = dvb_attach(s5h1411_attach,
+					       &dvico_fusionhdtv7_config,
+					       &core->i2c_adap);
+		if (fe0->dvb.frontend != NULL) {
+			if (!dvb_attach(xc5000_attach, fe0->dvb.frontend,
+					&core->i2c_adap,
+					&dvico_fusionhdtv7_tuner_config))
+				goto frontend_detach;
+		}
+		break;
+	case CX88_BOARD_HAUPPAUGE_HVR4000:
+		/* MFE frontend 1 */
+		mfe_shared = 1;
+		dev->frontends.gate = 2;
+		/* DVB-S/S2 Init */
+		fe0->dvb.frontend = dvb_attach(cx24116_attach,
+					&hauppauge_hvr4000_config,
+					&dev->core->i2c_adap);
+		if (fe0->dvb.frontend) {
+			if (!dvb_attach(isl6421_attach,
+					fe0->dvb.frontend,
+					&dev->core->i2c_adap,
+					0x08, ISL6421_DCL, 0x00))
+				goto frontend_detach;
+		}
+		/* MFE frontend 2 */
+		fe1 = videobuf_dvb_get_frontend(&dev->frontends, 2);
+		if (!fe1)
+			goto frontend_detach;
+		/* DVB-T Init */
+		fe1->dvb.frontend = dvb_attach(cx22702_attach,
+					&hauppauge_hvr_config,
+					&dev->core->i2c_adap);
+		if (fe1->dvb.frontend) {
+			fe1->dvb.frontend->id = 1;
+			if (!dvb_attach(simple_tuner_attach,
+					fe1->dvb.frontend,
+					&dev->core->i2c_adap,
+					0x61, TUNER_PHILIPS_FMD1216ME_MK3))
+				goto frontend_detach;
+		}
+		break;
+	case CX88_BOARD_HAUPPAUGE_HVR4000LITE:
+		fe0->dvb.frontend = dvb_attach(cx24116_attach,
+					&hauppauge_hvr4000_config,
+					&dev->core->i2c_adap);
+		if (fe0->dvb.frontend) {
+			if (!dvb_attach(isl6421_attach,
+					fe0->dvb.frontend,
+					&dev->core->i2c_adap,
+					0x08, ISL6421_DCL, 0x00))
+				goto frontend_detach;
+		}
+		break;
+	case CX88_BOARD_PROF_6200:
+	case CX88_BOARD_TBS_8910:
+	case CX88_BOARD_TEVII_S420:
+		fe0->dvb.frontend = dvb_attach(stv0299_attach,
+						&tevii_tuner_sharp_config,
+						&core->i2c_adap);
+		if (fe0->dvb.frontend != NULL) {
+			if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 0x60,
+					&core->i2c_adap, DVB_PLL_OPERA1))
+				goto frontend_detach;
+			core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage;
+			fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage;
+
+		} else {
+			fe0->dvb.frontend = dvb_attach(stv0288_attach,
+							    &tevii_tuner_earda_config,
+							    &core->i2c_adap);
+				if (fe0->dvb.frontend != NULL) {
+					if (!dvb_attach(stb6000_attach, fe0->dvb.frontend, 0x61,
+						&core->i2c_adap))
+					goto frontend_detach;
+				core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage;
+				fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage;
+			}
+		}
+		break;
+	case CX88_BOARD_TEVII_S460:
+		fe0->dvb.frontend = dvb_attach(cx24116_attach,
+					       &tevii_s460_config,
+					       &core->i2c_adap);
+		if (fe0->dvb.frontend != NULL)
+			fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage;
+		break;
+	case CX88_BOARD_TEVII_S464:
+		fe0->dvb.frontend = dvb_attach(ds3000_attach,
+						&tevii_ds3000_config,
+						&core->i2c_adap);
+		if (fe0->dvb.frontend != NULL)
+			fe0->dvb.frontend->ops.set_voltage =
+							tevii_dvbs_set_voltage;
+		break;
+	case CX88_BOARD_OMICOM_SS4_PCI:
+	case CX88_BOARD_TBS_8920:
+	case CX88_BOARD_PROF_7300:
+	case CX88_BOARD_SATTRADE_ST4200:
+		fe0->dvb.frontend = dvb_attach(cx24116_attach,
+					       &hauppauge_hvr4000_config,
+					       &core->i2c_adap);
+		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;
+	case CX88_BOARD_PROF_7301:{
+		struct dvb_tuner_ops *tuner_ops = NULL;
+
+		fe0->dvb.frontend = dvb_attach(stv0900_attach,
+						&prof_7301_stv0900_config,
+						&core->i2c_adap, 0);
+		if (fe0->dvb.frontend != NULL) {
+			if (!dvb_attach(stb6100_attach, fe0->dvb.frontend,
+					&prof_7301_stb6100_config,
+					&core->i2c_adap))
+				goto frontend_detach;
+
+			tuner_ops = &fe0->dvb.frontend->ops.tuner_ops;
+			tuner_ops->set_frequency = stb6100_set_freq;
+			tuner_ops->get_frequency = stb6100_get_freq;
+			tuner_ops->set_bandwidth = stb6100_set_bandw;
+			tuner_ops->get_bandwidth = stb6100_get_bandw;
+
+			core->prev_set_voltage =
+					fe0->dvb.frontend->ops.set_voltage;
+			fe0->dvb.frontend->ops.set_voltage =
+					tevii_dvbs_set_voltage;
+		}
+		break;
+		}
+	case CX88_BOARD_SAMSUNG_SMT_7020:
+		dev->ts_gen_cntrl = 0x08;
+
+		cx_set(MO_GP0_IO, 0x0101);
+
+		cx_clear(MO_GP0_IO, 0x01);
+		mdelay(100);
+		cx_set(MO_GP0_IO, 0x01);
+		mdelay(200);
+
+		fe0->dvb.frontend = dvb_attach(stv0299_attach,
+					&samsung_stv0299_config,
+					&dev->core->i2c_adap);
+		if (fe0->dvb.frontend) {
+			fe0->dvb.frontend->ops.tuner_ops.set_params =
+				samsung_smt_7020_tuner_set_params;
+			fe0->dvb.frontend->tuner_priv =
+				&dev->core->i2c_adap;
+			fe0->dvb.frontend->ops.set_voltage =
+				samsung_smt_7020_set_voltage;
+			fe0->dvb.frontend->ops.set_tone =
+				samsung_smt_7020_set_tone;
+		}
+
+		break;
+	case CX88_BOARD_TWINHAN_VP1027_DVBS:
+		dev->ts_gen_cntrl = 0x00;
+		fe0->dvb.frontend = dvb_attach(mb86a16_attach,
+						&twinhan_vp1027,
+						&core->i2c_adap);
+		if (fe0->dvb.frontend) {
+			core->prev_set_voltage =
+					fe0->dvb.frontend->ops.set_voltage;
+			fe0->dvb.frontend->ops.set_voltage =
+					vp1027_set_voltage;
+		}
+		break;
+
+	default:
+		printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n",
+		       core->name);
+		break;
+	}
+
+	if ( (NULL == fe0->dvb.frontend) || (fe1 && NULL == fe1->dvb.frontend) ) {
+		printk(KERN_ERR
+		       "%s/2: frontend initialization failed\n",
+		       core->name);
+		goto frontend_detach;
+	}
+	/* define general-purpose callback pointer */
+	fe0->dvb.frontend->callback = cx88_tuner_callback;
+
+	/* Ensure all frontends negotiate bus access */
+	fe0->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl;
+	if (fe1)
+		fe1->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl;
+
+	/* Put the analog decoder in standby to keep it quiet */
+	call_all(core, core, s_power, 0);
+
+	/* register everything */
+	res = videobuf_dvb_register_bus(&dev->frontends, THIS_MODULE, dev,
+		&dev->pci->dev, adapter_nr, mfe_shared);
+	if (res)
+		goto frontend_detach;
+	return res;
+
+frontend_detach:
+	core->gate_ctrl = NULL;
+	videobuf_dvb_dealloc_frontends(&dev->frontends);
+	return res;
+}
+
+/* ----------------------------------------------------------- */
+
+/* CX8802 MPEG -> mini driver - We have been given the hardware */
+static int cx8802_dvb_advise_acquire(struct cx8802_driver *drv)
+{
+	struct cx88_core *core = drv->core;
+	int err = 0;
+	dprintk( 1, "%s\n", __func__);
+
+	switch (core->boardnr) {
+	case CX88_BOARD_HAUPPAUGE_HVR1300:
+		/* We arrive here with either the cx23416 or the cx22702
+		 * on the bus. Take the bus from the cx23416 and enable the
+		 * cx22702 demod
+		 */
+		/* Toggle reset on cx22702 leaving i2c active */
+		cx_set(MO_GP0_IO, 0x00000080);
+		udelay(1000);
+		cx_clear(MO_GP0_IO, 0x00000080);
+		udelay(50);
+		cx_set(MO_GP0_IO, 0x00000080);
+		udelay(1000);
+		/* enable the cx22702 pins */
+		cx_clear(MO_GP0_IO, 0x00000004);
+		udelay(1000);
+		break;
+
+	case CX88_BOARD_HAUPPAUGE_HVR3000:
+	case CX88_BOARD_HAUPPAUGE_HVR4000:
+		/* Toggle reset on cx22702 leaving i2c active */
+		cx_set(MO_GP0_IO, 0x00000080);
+		udelay(1000);
+		cx_clear(MO_GP0_IO, 0x00000080);
+		udelay(50);
+		cx_set(MO_GP0_IO, 0x00000080);
+		udelay(1000);
+		switch (core->dvbdev->frontends.active_fe_id) {
+		case 1: /* DVB-S/S2 Enabled */
+			/* tri-state the cx22702 pins */
+			cx_set(MO_GP0_IO, 0x00000004);
+			/* Take the cx24116/cx24123 out of reset */
+			cx_write(MO_SRST_IO, 1);
+			core->dvbdev->ts_gen_cntrl = 0x02; /* Parallel IO */
+			break;
+		case 2: /* DVB-T Enabled */
+			/* Put the cx24116/cx24123 into reset */
+			cx_write(MO_SRST_IO, 0);
+			/* enable the cx22702 pins */
+			cx_clear(MO_GP0_IO, 0x00000004);
+			core->dvbdev->ts_gen_cntrl = 0x0c; /* Serial IO */
+			break;
+		}
+		udelay(1000);
+		break;
+
+	case CX88_BOARD_WINFAST_DTV2000H_PLUS:
+		/* set RF input to AIR for DVB-T (GPIO 16) */
+		cx_write(MO_GP2_IO, 0x0101);
+		break;
+
+	default:
+		err = -ENODEV;
+	}
+	return err;
+}
+
+/* CX8802 MPEG -> mini driver - We no longer have the hardware */
+static int cx8802_dvb_advise_release(struct cx8802_driver *drv)
+{
+	struct cx88_core *core = drv->core;
+	int err = 0;
+	dprintk( 1, "%s\n", __func__);
+
+	switch (core->boardnr) {
+	case CX88_BOARD_HAUPPAUGE_HVR1300:
+		/* Do Nothing, leave the cx22702 on the bus. */
+		break;
+	case CX88_BOARD_HAUPPAUGE_HVR3000:
+	case CX88_BOARD_HAUPPAUGE_HVR4000:
+		break;
+	default:
+		err = -ENODEV;
+	}
+	return err;
+}
+
+static int cx8802_dvb_probe(struct cx8802_driver *drv)
+{
+	struct cx88_core *core = drv->core;
+	struct cx8802_dev *dev = drv->core->dvbdev;
+	int err;
+	struct videobuf_dvb_frontend *fe;
+	int i;
+
+	dprintk( 1, "%s\n", __func__);
+	dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n",
+		core->boardnr,
+		core->name,
+		core->pci_bus,
+		core->pci_slot);
+
+	err = -ENODEV;
+	if (!(core->board.mpeg & CX88_MPEG_DVB))
+		goto fail_core;
+
+	/* If vp3054 isn't enabled, a stub will just return 0 */
+	err = vp3054_i2c_probe(dev);
+	if (0 != err)
+		goto fail_core;
+
+	/* dvb stuff */
+	printk(KERN_INFO "%s/2: cx2388x based DVB/ATSC card\n", core->name);
+	dev->ts_gen_cntrl = 0x0c;
+
+	err = cx8802_alloc_frontends(dev);
+	if (err)
+		goto fail_core;
+
+	err = -ENODEV;
+	for (i = 1; i <= core->board.num_frontends; i++) {
+		fe = videobuf_dvb_get_frontend(&core->dvbdev->frontends, i);
+		if (fe == NULL) {
+			printk(KERN_ERR "%s() failed to get frontend(%d)\n",
+					__func__, i);
+			goto fail_probe;
+		}
+		videobuf_queue_sg_init(&fe->dvb.dvbq, &dvb_qops,
+				    &dev->pci->dev, &dev->slock,
+				    V4L2_BUF_TYPE_VIDEO_CAPTURE,
+				    V4L2_FIELD_TOP,
+				    sizeof(struct cx88_buffer),
+				    dev, NULL);
+		/* init struct videobuf_dvb */
+		fe->dvb.name = dev->core->name;
+	}
+
+	err = dvb_register(dev);
+	if (err)
+		/* frontends/adapter de-allocated in dvb_register */
+		printk(KERN_ERR "%s/2: dvb_register failed (err = %d)\n",
+		       core->name, err);
+	return err;
+fail_probe:
+	videobuf_dvb_dealloc_frontends(&core->dvbdev->frontends);
+fail_core:
+	return err;
+}
+
+static int cx8802_dvb_remove(struct cx8802_driver *drv)
+{
+	struct cx88_core *core = drv->core;
+	struct cx8802_dev *dev = drv->core->dvbdev;
+
+	dprintk( 1, "%s\n", __func__);
+
+	videobuf_dvb_unregister_bus(&dev->frontends);
+
+	vp3054_i2c_remove(dev);
+
+	core->gate_ctrl = NULL;
+
+	return 0;
+}
+
+static struct cx8802_driver cx8802_dvb_driver = {
+	.type_id        = CX88_MPEG_DVB,
+	.hw_access      = CX8802_DRVCTL_SHARED,
+	.probe          = cx8802_dvb_probe,
+	.remove         = cx8802_dvb_remove,
+	.advise_acquire = cx8802_dvb_advise_acquire,
+	.advise_release = cx8802_dvb_advise_release,
+};
+
+static int __init dvb_init(void)
+{
+	printk(KERN_INFO "cx88/2: cx2388x dvb driver version %s loaded\n",
+	       CX88_VERSION);
+	return cx8802_register_driver(&cx8802_dvb_driver);
+}
+
+static void __exit dvb_fini(void)
+{
+	cx8802_unregister_driver(&cx8802_dvb_driver);
+}
+
+module_init(dvb_init);
+module_exit(dvb_fini);
diff --git a/drivers/media/pci/cx88/cx88-i2c.c b/drivers/media/pci/cx88/cx88-i2c.c
new file mode 100644
index 0000000..de0f1af
--- /dev/null
+++ b/drivers/media/pci/cx88/cx88-i2c.c
@@ -0,0 +1,184 @@
+
+/*
+
+    cx88-i2c.c  --  all the i2c code is here
+
+    Copyright (C) 1996,97,98 Ralph  Metzler (rjkm@thp.uni-koeln.de)
+			   & Marcus Metzler (mocm@thp.uni-koeln.de)
+    (c) 2002 Yurij Sysoev <yurij@naturesoft.net>
+    (c) 1999-2003 Gerd Knorr <kraxel@bytesex.org>
+
+    (c) 2005 Mauro Carvalho Chehab <mchehab@infradead.org>
+	- Multituner support and i2c address binding
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the 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/init.h>
+
+#include <asm/io.h>
+
+#include "cx88.h"
+#include <media/v4l2-common.h>
+
+static unsigned int i2c_debug;
+module_param(i2c_debug, int, 0644);
+MODULE_PARM_DESC(i2c_debug,"enable debug messages [i2c]");
+
+static unsigned int i2c_scan;
+module_param(i2c_scan, int, 0444);
+MODULE_PARM_DESC(i2c_scan,"scan i2c bus at insmod time");
+
+static unsigned int i2c_udelay = 5;
+module_param(i2c_udelay, int, 0644);
+MODULE_PARM_DESC(i2c_udelay,"i2c delay at insmod time, in usecs "
+		"(should be 5 or higher). Lower value means higher bus speed.");
+
+#define dprintk(level,fmt, arg...)	if (i2c_debug >= level) \
+	printk(KERN_DEBUG "%s: " fmt, core->name , ## arg)
+
+/* ----------------------------------------------------------------------- */
+
+static void cx8800_bit_setscl(void *data, int state)
+{
+	struct cx88_core *core = data;
+
+	if (state)
+		core->i2c_state |= 0x02;
+	else
+		core->i2c_state &= ~0x02;
+	cx_write(MO_I2C, core->i2c_state);
+	cx_read(MO_I2C);
+}
+
+static void cx8800_bit_setsda(void *data, int state)
+{
+	struct cx88_core *core = data;
+
+	if (state)
+		core->i2c_state |= 0x01;
+	else
+		core->i2c_state &= ~0x01;
+	cx_write(MO_I2C, core->i2c_state);
+	cx_read(MO_I2C);
+}
+
+static int cx8800_bit_getscl(void *data)
+{
+	struct cx88_core *core = data;
+	u32 state;
+
+	state = cx_read(MO_I2C);
+	return state & 0x02 ? 1 : 0;
+}
+
+static int cx8800_bit_getsda(void *data)
+{
+	struct cx88_core *core = data;
+	u32 state;
+
+	state = cx_read(MO_I2C);
+	return state & 0x01;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static const struct i2c_algo_bit_data cx8800_i2c_algo_template = {
+	.setsda  = cx8800_bit_setsda,
+	.setscl  = cx8800_bit_setscl,
+	.getsda  = cx8800_bit_getsda,
+	.getscl  = cx8800_bit_getscl,
+	.udelay  = 16,
+	.timeout = 200,
+};
+
+/* ----------------------------------------------------------------------- */
+
+static const char * const i2c_devs[128] = {
+	[ 0x1c >> 1 ] = "lgdt330x",
+	[ 0x86 >> 1 ] = "tda9887/cx22702",
+	[ 0xa0 >> 1 ] = "eeprom",
+	[ 0xc0 >> 1 ] = "tuner (analog)",
+	[ 0xc2 >> 1 ] = "tuner (analog/dvb)",
+	[ 0xc8 >> 1 ] = "xc5000",
+};
+
+static void do_i2c_scan(const char *name, struct i2c_client *c)
+{
+	unsigned char buf;
+	int i,rc;
+
+	for (i = 0; i < ARRAY_SIZE(i2c_devs); i++) {
+		c->addr = i;
+		rc = i2c_master_recv(c,&buf,0);
+		if (rc < 0)
+			continue;
+		printk("%s: i2c scan: found device @ 0x%x  [%s]\n",
+		       name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???");
+	}
+}
+
+/* init + register i2c adapter */
+int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci)
+{
+	/* Prevents usage of invalid delay values */
+	if (i2c_udelay<5)
+		i2c_udelay=5;
+
+	memcpy(&core->i2c_algo, &cx8800_i2c_algo_template,
+	       sizeof(core->i2c_algo));
+
+
+	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_algo.udelay = i2c_udelay;
+	core->i2c_algo.data = 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);
+
+	cx8800_bit_setscl(core,1);
+	cx8800_bit_setsda(core,1);
+
+	core->i2c_rc = i2c_bit_add_bus(&core->i2c_adap);
+	if (0 == core->i2c_rc) {
+		static u8 tuner_data[] =
+			{ 0x0b, 0xdc, 0x86, 0x52 };
+		static struct i2c_msg tuner_msg =
+			{ .flags = 0, .addr = 0xc2 >> 1, .buf = tuner_data, .len = 4 };
+
+		dprintk(1, "i2c register ok\n");
+		switch( core->boardnr ) {
+			case CX88_BOARD_HAUPPAUGE_HVR1300:
+			case CX88_BOARD_HAUPPAUGE_HVR3000:
+			case CX88_BOARD_HAUPPAUGE_HVR4000:
+				printk("%s: i2c init: enabling analog demod on HVR1300/3000/4000 tuner\n",
+					core->name);
+				i2c_transfer(core->i2c_client.adapter, &tuner_msg, 1);
+				break;
+			default:
+				break;
+		}
+		if (i2c_scan)
+			do_i2c_scan(core->name,&core->i2c_client);
+	} else
+		printk("%s: i2c register FAILED\n", core->name);
+
+	return core->i2c_rc;
+}
diff --git a/drivers/media/pci/cx88/cx88-input.c b/drivers/media/pci/cx88/cx88-input.c
new file mode 100644
index 0000000..ebf448c
--- /dev/null
+++ b/drivers/media/pci/cx88/cx88-input.c
@@ -0,0 +1,635 @@
+/*
+ *
+ * Device driver for GPIO attached remote control interfaces
+ * on Conexant 2388x based TV/DVB cards.
+ *
+ * Copyright (c) 2003 Pavel Machek
+ * Copyright (c) 2004 Gerd Knorr
+ * Copyright (c) 2004, 2005 Chris Pascoe
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/init.h>
+#include <linux/hrtimer.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+
+#include "cx88.h"
+#include <media/rc-core.h>
+
+#define MODULE_NAME "cx88xx"
+
+/* ---------------------------------------------------------------------- */
+
+struct cx88_IR {
+	struct cx88_core *core;
+	struct rc_dev *dev;
+
+	int users;
+
+	char name[32];
+	char phys[32];
+
+	/* sample from gpio pin 16 */
+	u32 sampling;
+
+	/* poll external decoder */
+	int polling;
+	struct hrtimer timer;
+	u32 gpio_addr;
+	u32 last_gpio;
+	u32 mask_keycode;
+	u32 mask_keydown;
+	u32 mask_keyup;
+};
+
+static unsigned ir_samplerate = 4;
+module_param(ir_samplerate, uint, 0444);
+MODULE_PARM_DESC(ir_samplerate, "IR samplerate in kHz, 1 - 20, default 4");
+
+static int ir_debug;
+module_param(ir_debug, int, 0644);	/* debug level [IR] */
+MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]");
+
+#define ir_dprintk(fmt, arg...)	if (ir_debug) \
+	printk(KERN_DEBUG "%s IR: " fmt , ir->core->name , ##arg)
+
+#define dprintk(fmt, arg...)	if (ir_debug) \
+	printk(KERN_DEBUG "cx88 IR: " fmt , ##arg)
+
+/* ---------------------------------------------------------------------- */
+
+static void cx88_ir_handle_key(struct cx88_IR *ir)
+{
+	struct cx88_core *core = ir->core;
+	u32 gpio, data, auxgpio;
+
+	/* read gpio value */
+	gpio = cx_read(ir->gpio_addr);
+	switch (core->boardnr) {
+	case CX88_BOARD_NPGTECH_REALTV_TOP10FM:
+		/* This board apparently uses a combination of 2 GPIO
+		   to represent the keys. Additionally, the second GPIO
+		   can be used for parity.
+
+		   Example:
+
+		   for key "5"
+			gpio = 0x758, auxgpio = 0xe5 or 0xf5
+		   for key "Power"
+			gpio = 0x758, auxgpio = 0xed or 0xfd
+		 */
+
+		auxgpio = cx_read(MO_GP1_IO);
+		/* Take out the parity part */
+		gpio=(gpio & 0x7fd) + (auxgpio & 0xef);
+		break;
+	case CX88_BOARD_WINFAST_DTV1000:
+	case CX88_BOARD_WINFAST_DTV1800H:
+	case CX88_BOARD_WINFAST_DTV1800H_XC4000:
+	case CX88_BOARD_WINFAST_DTV2000H_PLUS:
+	case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL:
+	case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F36:
+	case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F43:
+		gpio = (gpio & 0x6ff) | ((cx_read(MO_GP1_IO) << 8) & 0x900);
+		auxgpio = gpio;
+		break;
+	default:
+		auxgpio = gpio;
+	}
+	if (ir->polling) {
+		if (ir->last_gpio == auxgpio)
+			return;
+		ir->last_gpio = auxgpio;
+	}
+
+	/* extract data */
+	data = ir_extract_bits(gpio, ir->mask_keycode);
+	ir_dprintk("irq gpio=0x%x code=%d | %s%s%s\n",
+		   gpio, data,
+		   ir->polling ? "poll" : "irq",
+		   (gpio & ir->mask_keydown) ? " down" : "",
+		   (gpio & ir->mask_keyup) ? " up" : "");
+
+	if (ir->core->boardnr == CX88_BOARD_NORWOOD_MICRO) {
+		u32 gpio_key = cx_read(MO_GP0_IO);
+
+		data = (data << 4) | ((gpio_key & 0xf0) >> 4);
+
+		rc_keydown(ir->dev, data, 0);
+
+	} else if (ir->mask_keydown) {
+		/* bit set on keydown */
+		if (gpio & ir->mask_keydown)
+			rc_keydown_notimeout(ir->dev, data, 0);
+		else
+			rc_keyup(ir->dev);
+
+	} else if (ir->mask_keyup) {
+		/* bit cleared on keydown */
+		if (0 == (gpio & ir->mask_keyup))
+			rc_keydown_notimeout(ir->dev, data, 0);
+		else
+			rc_keyup(ir->dev);
+
+	} else {
+		/* can't distinguish keydown/up :-/ */
+		rc_keydown_notimeout(ir->dev, data, 0);
+		rc_keyup(ir->dev);
+	}
+}
+
+static enum hrtimer_restart cx88_ir_work(struct hrtimer *timer)
+{
+	unsigned long missed;
+	struct cx88_IR *ir = container_of(timer, struct cx88_IR, timer);
+
+	cx88_ir_handle_key(ir);
+	missed = hrtimer_forward_now(&ir->timer,
+				     ktime_set(0, ir->polling * 1000000));
+	if (missed > 1)
+		ir_dprintk("Missed ticks %ld\n", missed - 1);
+
+	return HRTIMER_RESTART;
+}
+
+static int __cx88_ir_start(void *priv)
+{
+	struct cx88_core *core = priv;
+	struct cx88_IR *ir;
+
+	if (!core || !core->ir)
+		return -EINVAL;
+
+	ir = core->ir;
+
+	if (ir->polling) {
+		hrtimer_init(&ir->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+		ir->timer.function = cx88_ir_work;
+		hrtimer_start(&ir->timer,
+			      ktime_set(0, ir->polling * 1000000),
+			      HRTIMER_MODE_REL);
+	}
+	if (ir->sampling) {
+		core->pci_irqmask |= PCI_INT_IR_SMPINT;
+		cx_write(MO_DDS_IO, 0x33F286 * ir_samplerate); /* samplerate */
+		cx_write(MO_DDSCFG_IO, 0x5); /* enable */
+	}
+	return 0;
+}
+
+static void __cx88_ir_stop(void *priv)
+{
+	struct cx88_core *core = priv;
+	struct cx88_IR *ir;
+
+	if (!core || !core->ir)
+		return;
+
+	ir = core->ir;
+	if (ir->sampling) {
+		cx_write(MO_DDSCFG_IO, 0x0);
+		core->pci_irqmask &= ~PCI_INT_IR_SMPINT;
+	}
+
+	if (ir->polling)
+		hrtimer_cancel(&ir->timer);
+}
+
+int cx88_ir_start(struct cx88_core *core)
+{
+	if (core->ir->users)
+		return __cx88_ir_start(core);
+
+	return 0;
+}
+
+void cx88_ir_stop(struct cx88_core *core)
+{
+	if (core->ir->users)
+		__cx88_ir_stop(core);
+}
+
+static int cx88_ir_open(struct rc_dev *rc)
+{
+	struct cx88_core *core = rc->priv;
+
+	core->ir->users++;
+	return __cx88_ir_start(core);
+}
+
+static void cx88_ir_close(struct rc_dev *rc)
+{
+	struct cx88_core *core = rc->priv;
+
+	core->ir->users--;
+	if (!core->ir->users)
+		__cx88_ir_stop(core);
+}
+
+/* ---------------------------------------------------------------------- */
+
+int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
+{
+	struct cx88_IR *ir;
+	struct rc_dev *dev;
+	char *ir_codes = NULL;
+	u64 rc_type = RC_TYPE_OTHER;
+	int err = -ENOMEM;
+	u32 hardware_mask = 0;	/* For devices with a hardware mask, when
+				 * used with a full-code IR table
+				 */
+
+	ir = kzalloc(sizeof(*ir), GFP_KERNEL);
+	dev = rc_allocate_device();
+	if (!ir || !dev)
+		goto err_out_free;
+
+	ir->dev = dev;
+
+	/* detect & configure */
+	switch (core->boardnr) {
+	case CX88_BOARD_DNTV_LIVE_DVB_T:
+	case CX88_BOARD_KWORLD_DVB_T:
+	case CX88_BOARD_KWORLD_DVB_T_CX22702:
+		ir_codes = RC_MAP_DNTV_LIVE_DVB_T;
+		ir->gpio_addr = MO_GP1_IO;
+		ir->mask_keycode = 0x1f;
+		ir->mask_keyup = 0x60;
+		ir->polling = 50; /* ms */
+		break;
+	case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1:
+		ir_codes = RC_MAP_CINERGY_1400;
+		ir->sampling = 0xeb04; /* address */
+		break;
+	case CX88_BOARD_HAUPPAUGE:
+	case CX88_BOARD_HAUPPAUGE_DVB_T1:
+	case CX88_BOARD_HAUPPAUGE_NOVASE2_S1:
+	case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
+	case CX88_BOARD_HAUPPAUGE_HVR1100:
+	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:
+	case CX88_BOARD_HAUPPAUGE_IRONLY:
+		ir_codes = RC_MAP_HAUPPAUGE;
+		ir->sampling = 1;
+		break;
+	case CX88_BOARD_WINFAST_DTV2000H:
+	case CX88_BOARD_WINFAST_DTV2000H_J:
+	case CX88_BOARD_WINFAST_DTV1800H:
+	case CX88_BOARD_WINFAST_DTV1800H_XC4000:
+	case CX88_BOARD_WINFAST_DTV2000H_PLUS:
+		ir_codes = RC_MAP_WINFAST;
+		ir->gpio_addr = MO_GP0_IO;
+		ir->mask_keycode = 0x8f8;
+		ir->mask_keyup = 0x100;
+		ir->polling = 50; /* ms */
+		break;
+	case CX88_BOARD_WINFAST2000XP_EXPERT:
+	case CX88_BOARD_WINFAST_DTV1000:
+	case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL:
+	case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F36:
+	case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F43:
+		ir_codes = RC_MAP_WINFAST;
+		ir->gpio_addr = MO_GP0_IO;
+		ir->mask_keycode = 0x8f8;
+		ir->mask_keyup = 0x100;
+		ir->polling = 1; /* ms */
+		break;
+	case CX88_BOARD_IODATA_GVBCTV7E:
+		ir_codes = RC_MAP_IODATA_BCTV7E;
+		ir->gpio_addr = MO_GP0_IO;
+		ir->mask_keycode = 0xfd;
+		ir->mask_keydown = 0x02;
+		ir->polling = 5; /* ms */
+		break;
+	case CX88_BOARD_PROLINK_PLAYTVPVR:
+	case CX88_BOARD_PIXELVIEW_PLAYTV_ULTRA_PRO:
+		/*
+		 * It seems that this hardware is paired with NEC extended
+		 * address 0x866b. So, unfortunately, its usage with other
+		 * IR's with different address won't work. Still, there are
+		 * other IR's from the same manufacturer that works, like the
+		 * 002-T mini RC, provided with newer PV hardware
+		 */
+		ir_codes = RC_MAP_PIXELVIEW_MK12;
+		ir->gpio_addr = MO_GP1_IO;
+		ir->mask_keyup = 0x80;
+		ir->polling = 10; /* ms */
+		hardware_mask = 0x3f;	/* Hardware returns only 6 bits from command part */
+		break;
+	case CX88_BOARD_PROLINK_PV_8000GT:
+	case CX88_BOARD_PROLINK_PV_GLOBAL_XTREME:
+		ir_codes = RC_MAP_PIXELVIEW_NEW;
+		ir->gpio_addr = MO_GP1_IO;
+		ir->mask_keycode = 0x3f;
+		ir->mask_keyup = 0x80;
+		ir->polling = 1; /* ms */
+		break;
+	case CX88_BOARD_KWORLD_LTV883:
+		ir_codes = RC_MAP_PIXELVIEW;
+		ir->gpio_addr = MO_GP1_IO;
+		ir->mask_keycode = 0x1f;
+		ir->mask_keyup = 0x60;
+		ir->polling = 1; /* ms */
+		break;
+	case CX88_BOARD_ADSTECH_DVB_T_PCI:
+		ir_codes = RC_MAP_ADSTECH_DVB_T_PCI;
+		ir->gpio_addr = MO_GP1_IO;
+		ir->mask_keycode = 0xbf;
+		ir->mask_keyup = 0x40;
+		ir->polling = 50; /* ms */
+		break;
+	case CX88_BOARD_MSI_TVANYWHERE_MASTER:
+		ir_codes = RC_MAP_MSI_TVANYWHERE;
+		ir->gpio_addr = MO_GP1_IO;
+		ir->mask_keycode = 0x1f;
+		ir->mask_keyup = 0x40;
+		ir->polling = 1; /* ms */
+		break;
+	case CX88_BOARD_AVERTV_303:
+	case CX88_BOARD_AVERTV_STUDIO_303:
+		ir_codes         = RC_MAP_AVERTV_303;
+		ir->gpio_addr    = MO_GP2_IO;
+		ir->mask_keycode = 0xfb;
+		ir->mask_keydown = 0x02;
+		ir->polling      = 50; /* ms */
+		break;
+	case CX88_BOARD_OMICOM_SS4_PCI:
+	case CX88_BOARD_SATTRADE_ST4200:
+	case CX88_BOARD_TBS_8920:
+	case CX88_BOARD_TBS_8910:
+	case CX88_BOARD_PROF_7300:
+	case CX88_BOARD_PROF_7301:
+	case CX88_BOARD_PROF_6200:
+		ir_codes = RC_MAP_TBS_NEC;
+		ir->sampling = 0xff00; /* address */
+		break;
+	case CX88_BOARD_TEVII_S464:
+	case CX88_BOARD_TEVII_S460:
+	case CX88_BOARD_TEVII_S420:
+		ir_codes = RC_MAP_TEVII_NEC;
+		ir->sampling = 0xff00; /* address */
+		break;
+	case CX88_BOARD_DNTV_LIVE_DVB_T_PRO:
+		ir_codes         = RC_MAP_DNTV_LIVE_DVBT_PRO;
+		ir->sampling     = 0xff00; /* address */
+		break;
+	case CX88_BOARD_NORWOOD_MICRO:
+		ir_codes         = RC_MAP_NORWOOD;
+		ir->gpio_addr    = MO_GP1_IO;
+		ir->mask_keycode = 0x0e;
+		ir->mask_keyup   = 0x80;
+		ir->polling      = 50; /* ms */
+		break;
+	case CX88_BOARD_NPGTECH_REALTV_TOP10FM:
+		ir_codes         = RC_MAP_NPGTECH;
+		ir->gpio_addr    = MO_GP0_IO;
+		ir->mask_keycode = 0xfa;
+		ir->polling      = 50; /* ms */
+		break;
+	case CX88_BOARD_PINNACLE_PCTV_HD_800i:
+		ir_codes         = RC_MAP_PINNACLE_PCTV_HD;
+		ir->sampling     = 1;
+		break;
+	case CX88_BOARD_POWERCOLOR_REAL_ANGEL:
+		ir_codes         = RC_MAP_POWERCOLOR_REAL_ANGEL;
+		ir->gpio_addr    = MO_GP2_IO;
+		ir->mask_keycode = 0x7e;
+		ir->polling      = 100; /* ms */
+		break;
+	case CX88_BOARD_TWINHAN_VP1027_DVBS:
+		ir_codes         = RC_MAP_TWINHAN_VP1027_DVBS;
+		rc_type          = RC_TYPE_NEC;
+		ir->sampling     = 0xff00; /* address */
+		break;
+	}
+
+	if (!ir_codes) {
+		err = -ENODEV;
+		goto err_out_free;
+	}
+
+	/*
+	 * The usage of mask_keycode were very convenient, due to several
+	 * reasons. Among others, the scancode tables were using the scancode
+	 * as the index elements. So, the less bits it was used, the smaller
+	 * the table were stored. After the input changes, the better is to use
+	 * the full scancodes, since it allows replacing the IR remote by
+	 * another one. Unfortunately, there are still some hardware, like
+	 * Pixelview Ultra Pro, where only part of the scancode is sent via
+	 * GPIO. So, there's no way to get the full scancode. Due to that,
+	 * hardware_mask were introduced here: it represents those hardware
+	 * that has such limits.
+	 */
+	if (hardware_mask && !ir->mask_keycode)
+		ir->mask_keycode = hardware_mask;
+
+	/* init input device */
+	snprintf(ir->name, sizeof(ir->name), "cx88 IR (%s)", core->board.name);
+	snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", pci_name(pci));
+
+	dev->input_name = ir->name;
+	dev->input_phys = ir->phys;
+	dev->input_id.bustype = BUS_PCI;
+	dev->input_id.version = 1;
+	if (pci->subsystem_vendor) {
+		dev->input_id.vendor = pci->subsystem_vendor;
+		dev->input_id.product = pci->subsystem_device;
+	} else {
+		dev->input_id.vendor = pci->vendor;
+		dev->input_id.product = pci->device;
+	}
+	dev->dev.parent = &pci->dev;
+	dev->map_name = ir_codes;
+	dev->driver_name = MODULE_NAME;
+	dev->priv = core;
+	dev->open = cx88_ir_open;
+	dev->close = cx88_ir_close;
+	dev->scanmask = hardware_mask;
+
+	if (ir->sampling) {
+		dev->driver_type = RC_DRIVER_IR_RAW;
+		dev->timeout = 10 * 1000 * 1000; /* 10 ms */
+	} else {
+		dev->driver_type = RC_DRIVER_SCANCODE;
+		dev->allowed_protos = rc_type;
+	}
+
+	ir->core = core;
+	core->ir = ir;
+
+	/* all done */
+	err = rc_register_device(dev);
+	if (err)
+		goto err_out_free;
+
+	return 0;
+
+err_out_free:
+	rc_free_device(dev);
+	core->ir = NULL;
+	kfree(ir);
+	return err;
+}
+
+int cx88_ir_fini(struct cx88_core *core)
+{
+	struct cx88_IR *ir = core->ir;
+
+	/* skip detach on non attached boards */
+	if (NULL == ir)
+		return 0;
+
+	cx88_ir_stop(core);
+	rc_unregister_device(ir->dev);
+	kfree(ir);
+
+	/* done */
+	core->ir = NULL;
+	return 0;
+}
+
+/* ---------------------------------------------------------------------- */
+
+void cx88_ir_irq(struct cx88_core *core)
+{
+	struct cx88_IR *ir = core->ir;
+	u32 samples;
+	unsigned todo, bits;
+	struct ir_raw_event ev;
+
+	if (!ir || !ir->sampling)
+		return;
+
+	/*
+	 * Samples are stored in a 32 bit register, oldest sample in
+	 * the msb. A set bit represents space and an unset bit
+	 * represents a pulse.
+	 */
+	samples = cx_read(MO_SAMPLE_IO);
+
+	if (samples == 0xff && ir->dev->idle)
+		return;
+
+	init_ir_raw_event(&ev);
+	for (todo = 32; todo > 0; todo -= bits) {
+		ev.pulse = samples & 0x80000000 ? false : true;
+		bits = min(todo, 32U - fls(ev.pulse ? samples : ~samples));
+		ev.duration = (bits * (NSEC_PER_SEC / 1000)) / ir_samplerate;
+		ir_raw_event_store_with_filter(ir->dev, &ev);
+		samples <<= bits;
+	}
+	ir_raw_event_handle(ir->dev);
+}
+
+static int get_key_pvr2000(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+{
+	int flags, code;
+
+	/* poll IR chip */
+	flags = i2c_smbus_read_byte_data(ir->c, 0x10);
+	if (flags < 0) {
+		dprintk("read error\n");
+		return 0;
+	}
+	/* key pressed ? */
+	if (0 == (flags & 0x80))
+		return 0;
+
+	/* read actual key code */
+	code = i2c_smbus_read_byte_data(ir->c, 0x00);
+	if (code < 0) {
+		dprintk("read error\n");
+		return 0;
+	}
+
+	dprintk("IR Key/Flags: (0x%02x/0x%02x)\n",
+		   code & 0xff, flags & 0xff);
+
+	*ir_key = code & 0xff;
+	*ir_raw = code;
+	return 1;
+}
+
+void cx88_i2c_init_ir(struct cx88_core *core)
+{
+	struct i2c_board_info info;
+	const unsigned short default_addr_list[] = {
+		0x18, 0x6b, 0x71,
+		I2C_CLIENT_END
+	};
+	const unsigned short pvr2000_addr_list[] = {
+		0x18, 0x1a,
+		I2C_CLIENT_END
+	};
+	const unsigned short *addr_list = default_addr_list;
+	const unsigned short *addrp;
+	/* Instantiate the IR receiver device, if present */
+	if (0 != core->i2c_rc)
+		return;
+
+	memset(&info, 0, sizeof(struct i2c_board_info));
+	strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
+
+	switch (core->boardnr) {
+	case CX88_BOARD_LEADTEK_PVR2000:
+		addr_list = pvr2000_addr_list;
+		core->init_data.name = "cx88 Leadtek PVR 2000 remote";
+		core->init_data.type = RC_TYPE_UNKNOWN;
+		core->init_data.get_key = get_key_pvr2000;
+		core->init_data.ir_codes = RC_MAP_EMPTY;
+		break;
+	}
+
+	/*
+	 * We can't call i2c_new_probed_device() because it uses
+	 * quick writes for probing and at least some RC receiver
+	 * devices only reply to reads.
+	 * Also, Hauppauge XVR needs to be specified, as address 0x71
+	 * conflicts with another remote type used with saa7134
+	 */
+	for (addrp = addr_list; *addrp != I2C_CLIENT_END; addrp++) {
+		info.platform_data = NULL;
+		memset(&core->init_data, 0, sizeof(core->init_data));
+
+		if (*addrp == 0x71) {
+			/* Hauppauge XVR */
+			core->init_data.name = "cx88 Hauppauge XVR remote";
+			core->init_data.ir_codes = RC_MAP_HAUPPAUGE;
+			core->init_data.type = RC_TYPE_RC5;
+			core->init_data.internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR;
+
+			info.platform_data = &core->init_data;
+		}
+		if (i2c_smbus_xfer(&core->i2c_adap, *addrp, 0,
+					I2C_SMBUS_READ, 0,
+					I2C_SMBUS_QUICK, NULL) >= 0) {
+			info.addr = *addrp;
+			i2c_new_device(&core->i2c_adap, &info);
+			break;
+		}
+	}
+}
+
+/* ---------------------------------------------------------------------- */
+
+MODULE_AUTHOR("Gerd Knorr, Pavel Machek, Chris Pascoe");
+MODULE_DESCRIPTION("input driver for cx88 GPIO-based IR remote controls");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/pci/cx88/cx88-mpeg.c b/drivers/media/pci/cx88/cx88-mpeg.c
new file mode 100644
index 0000000..c04fb61
--- /dev/null
+++ b/drivers/media/pci/cx88/cx88-mpeg.c
@@ -0,0 +1,929 @@
+/*
+ *
+ *  Support for the mpeg transport stream transfers
+ *  PCI function #2 of the cx2388x.
+ *
+ *    (c) 2004 Jelle Foks <jelle@foks.us>
+ *    (c) 2004 Chris Pascoe <c.pascoe@itee.uq.edu.au>
+ *    (c) 2004 Gerd Knorr <kraxel@bytesex.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/module.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include <asm/delay.h>
+
+#include "cx88.h"
+
+/* ------------------------------------------------------------------ */
+
+MODULE_DESCRIPTION("mpeg driver for cx2388x based TV cards");
+MODULE_AUTHOR("Jelle Foks <jelle@foks.us>");
+MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>");
+MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(CX88_VERSION);
+
+static unsigned int debug;
+module_param(debug,int,0644);
+MODULE_PARM_DESC(debug,"enable debug messages [mpeg]");
+
+#define dprintk(level,fmt, arg...)	if (debug >= level) \
+	printk(KERN_DEBUG "%s/2-mpeg: " fmt, dev->core->name, ## arg)
+
+#define mpeg_dbg(level,fmt, arg...)	if (debug >= level) \
+	printk(KERN_DEBUG "%s/2-mpeg: " fmt, core->name, ## arg)
+
+#if defined(CONFIG_MODULES) && defined(MODULE)
+static void request_module_async(struct work_struct *work)
+{
+	struct cx8802_dev *dev=container_of(work, struct cx8802_dev, request_module_wk);
+
+	if (dev->core->board.mpeg & CX88_MPEG_DVB)
+		request_module("cx88-dvb");
+	if (dev->core->board.mpeg & CX88_MPEG_BLACKBIRD)
+		request_module("cx88-blackbird");
+}
+
+static void request_modules(struct cx8802_dev *dev)
+{
+	INIT_WORK(&dev->request_module_wk, request_module_async);
+	schedule_work(&dev->request_module_wk);
+}
+
+static void flush_request_modules(struct cx8802_dev *dev)
+{
+	flush_work(&dev->request_module_wk);
+}
+#else
+#define request_modules(dev)
+#define flush_request_modules(dev)
+#endif /* CONFIG_MODULES */
+
+
+static LIST_HEAD(cx8802_devlist);
+static DEFINE_MUTEX(cx8802_mutex);
+/* ------------------------------------------------------------------ */
+
+static int cx8802_start_dma(struct cx8802_dev    *dev,
+			    struct cx88_dmaqueue *q,
+			    struct cx88_buffer   *buf)
+{
+	struct cx88_core *core = dev->core;
+
+	dprintk(1, "cx8802_start_dma w: %d, h: %d, f: %d\n",
+		buf->vb.width, buf->vb.height, buf->vb.field);
+
+	/* setup fifo + format */
+	cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH28],
+				dev->ts_packet_size, buf->risc.dma);
+
+	/* write TS length to chip */
+	cx_write(MO_TS_LNGTH, buf->vb.width);
+
+	/* FIXME: this needs a review.
+	 * also: move to cx88-blackbird + cx88-dvb source files? */
+
+	dprintk( 1, "core->active_type_id = 0x%08x\n", core->active_type_id);
+
+	if ( (core->active_type_id == CX88_MPEG_DVB) &&
+		(core->board.mpeg & CX88_MPEG_DVB) ) {
+
+		dprintk( 1, "cx8802_start_dma doing .dvb\n");
+		/* negedge driven & software reset */
+		cx_write(TS_GEN_CNTRL, 0x0040 | dev->ts_gen_cntrl);
+		udelay(100);
+		cx_write(MO_PINMUX_IO, 0x00);
+		cx_write(TS_HW_SOP_CNTRL, 0x47<<16|188<<4|0x01);
+		switch (core->boardnr) {
+		case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q:
+		case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T:
+		case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD:
+		case CX88_BOARD_PCHDTV_HD5500:
+			cx_write(TS_SOP_STAT, 1<<13);
+			break;
+		case CX88_BOARD_SAMSUNG_SMT_7020:
+			cx_write(TS_SOP_STAT, 0x00);
+			break;
+		case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
+		case CX88_BOARD_HAUPPAUGE_NOVASE2_S1:
+			cx_write(MO_PINMUX_IO, 0x88); /* Enable MPEG parallel IO and video signal pins */
+			udelay(100);
+			break;
+		case CX88_BOARD_HAUPPAUGE_HVR1300:
+			/* Enable MPEG parallel IO and video signal pins */
+			cx_write(MO_PINMUX_IO, 0x88);
+			cx_write(TS_SOP_STAT, 0);
+			cx_write(TS_VALERR_CNTRL, 0);
+			break;
+		case CX88_BOARD_PINNACLE_PCTV_HD_800i:
+			/* Enable MPEG parallel IO and video signal pins */
+			cx_write(MO_PINMUX_IO, 0x88);
+			cx_write(TS_HW_SOP_CNTRL, (0x47 << 16) | (188 << 4));
+			dev->ts_gen_cntrl = 5;
+			cx_write(TS_SOP_STAT, 0);
+			cx_write(TS_VALERR_CNTRL, 0);
+			udelay(100);
+			break;
+		default:
+			cx_write(TS_SOP_STAT, 0x00);
+			break;
+		}
+		cx_write(TS_GEN_CNTRL, dev->ts_gen_cntrl);
+		udelay(100);
+	} else if ( (core->active_type_id == CX88_MPEG_BLACKBIRD) &&
+		(core->board.mpeg & CX88_MPEG_BLACKBIRD) ) {
+		dprintk( 1, "cx8802_start_dma doing .blackbird\n");
+		cx_write(MO_PINMUX_IO, 0x88); /* enable MPEG parallel IO */
+
+		cx_write(TS_GEN_CNTRL, 0x46); /* punctured clock TS & posedge driven & software reset */
+		udelay(100);
+
+		cx_write(TS_HW_SOP_CNTRL, 0x408); /* mpeg start byte */
+		cx_write(TS_VALERR_CNTRL, 0x2000);
+
+		cx_write(TS_GEN_CNTRL, 0x06); /* punctured clock TS & posedge driven */
+		udelay(100);
+	} else {
+		printk( "%s() Failed. Unsupported value in .mpeg (0x%08x)\n", __func__,
+			core->board.mpeg );
+		return -EINVAL;
+	}
+
+	/* reset counter */
+	cx_write(MO_TS_GPCNTRL, GP_COUNT_CONTROL_RESET);
+	q->count = 1;
+
+	/* enable irqs */
+	dprintk( 1, "setting the interrupt mask\n" );
+	cx_set(MO_PCI_INTMSK, core->pci_irqmask | PCI_INT_TSINT);
+	cx_set(MO_TS_INTMSK,  0x1f0011);
+
+	/* start dma */
+	cx_set(MO_DEV_CNTRL2, (1<<5));
+	cx_set(MO_TS_DMACNTRL, 0x11);
+	return 0;
+}
+
+static int cx8802_stop_dma(struct cx8802_dev *dev)
+{
+	struct cx88_core *core = dev->core;
+	dprintk( 1, "cx8802_stop_dma\n" );
+
+	/* stop dma */
+	cx_clear(MO_TS_DMACNTRL, 0x11);
+
+	/* disable irqs */
+	cx_clear(MO_PCI_INTMSK, PCI_INT_TSINT);
+	cx_clear(MO_TS_INTMSK, 0x1f0011);
+
+	/* Reset the controller */
+	cx_write(TS_GEN_CNTRL, 0xcd);
+	return 0;
+}
+
+static int cx8802_restart_queue(struct cx8802_dev    *dev,
+				struct cx88_dmaqueue *q)
+{
+	struct cx88_buffer *buf;
+
+	dprintk( 1, "cx8802_restart_queue\n" );
+	if (list_empty(&q->active))
+	{
+		struct cx88_buffer *prev;
+		prev = NULL;
+
+		dprintk(1, "cx8802_restart_queue: queue is empty\n" );
+
+		for (;;) {
+			if (list_empty(&q->queued))
+				return 0;
+			buf = list_entry(q->queued.next, struct cx88_buffer, vb.queue);
+			if (NULL == prev) {
+				list_del(&buf->vb.queue);
+				list_add_tail(&buf->vb.queue,&q->active);
+				cx8802_start_dma(dev, q, buf);
+				buf->vb.state = VIDEOBUF_ACTIVE;
+				buf->count    = q->count++;
+				mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
+				dprintk(1,"[%p/%d] restart_queue - first active\n",
+					buf,buf->vb.i);
+
+			} else if (prev->vb.width  == buf->vb.width  &&
+				   prev->vb.height == buf->vb.height &&
+				   prev->fmt       == buf->fmt) {
+				list_del(&buf->vb.queue);
+				list_add_tail(&buf->vb.queue,&q->active);
+				buf->vb.state = VIDEOBUF_ACTIVE;
+				buf->count    = q->count++;
+				prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+				dprintk(1,"[%p/%d] restart_queue - move to active\n",
+					buf,buf->vb.i);
+			} else {
+				return 0;
+			}
+			prev = buf;
+		}
+		return 0;
+	}
+
+	buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
+	dprintk(2,"restart_queue [%p/%d]: restart dma\n",
+		buf, buf->vb.i);
+	cx8802_start_dma(dev, q, buf);
+	list_for_each_entry(buf, &q->active, vb.queue)
+		buf->count = q->count++;
+	mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
+	return 0;
+}
+
+/* ------------------------------------------------------------------ */
+
+int cx8802_buf_prepare(struct videobuf_queue *q, struct cx8802_dev *dev,
+			struct cx88_buffer *buf, enum v4l2_field field)
+{
+	int size = dev->ts_packet_size * dev->ts_packet_count;
+	struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
+	int rc;
+
+	dprintk(1, "%s: %p\n", __func__, buf);
+	if (0 != buf->vb.baddr  &&  buf->vb.bsize < size)
+		return -EINVAL;
+
+	if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
+		buf->vb.width  = dev->ts_packet_size;
+		buf->vb.height = dev->ts_packet_count;
+		buf->vb.size   = size;
+		buf->vb.field  = field /*V4L2_FIELD_TOP*/;
+
+		if (0 != (rc = videobuf_iolock(q,&buf->vb,NULL)))
+			goto fail;
+		cx88_risc_databuffer(dev->pci, &buf->risc,
+				     dma->sglist,
+				     buf->vb.width, buf->vb.height, 0);
+	}
+	buf->vb.state = VIDEOBUF_PREPARED;
+	return 0;
+
+ fail:
+	cx88_free_buffer(q,buf);
+	return rc;
+}
+
+void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf)
+{
+	struct cx88_buffer    *prev;
+	struct cx88_dmaqueue  *cx88q = &dev->mpegq;
+
+	dprintk( 1, "cx8802_buf_queue\n" );
+	/* add jump to stopper */
+	buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+	buf->risc.jmp[1] = cpu_to_le32(cx88q->stopper.dma);
+
+	if (list_empty(&cx88q->active)) {
+		dprintk( 1, "queue is empty - first active\n" );
+		list_add_tail(&buf->vb.queue,&cx88q->active);
+		cx8802_start_dma(dev, cx88q, buf);
+		buf->vb.state = VIDEOBUF_ACTIVE;
+		buf->count    = cx88q->count++;
+		mod_timer(&cx88q->timeout, jiffies+BUFFER_TIMEOUT);
+		dprintk(1,"[%p/%d] %s - first active\n",
+			buf, buf->vb.i, __func__);
+
+	} else {
+		dprintk( 1, "queue is not empty - append to active\n" );
+		prev = list_entry(cx88q->active.prev, struct cx88_buffer, vb.queue);
+		list_add_tail(&buf->vb.queue,&cx88q->active);
+		buf->vb.state = VIDEOBUF_ACTIVE;
+		buf->count    = cx88q->count++;
+		prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+		dprintk( 1, "[%p/%d] %s - append to active\n",
+			buf, buf->vb.i, __func__);
+	}
+}
+
+/* ----------------------------------------------------------- */
+
+static void do_cancel_buffers(struct cx8802_dev *dev, const char *reason, int restart)
+{
+	struct cx88_dmaqueue *q = &dev->mpegq;
+	struct cx88_buffer *buf;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->slock,flags);
+	while (!list_empty(&q->active)) {
+		buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
+		list_del(&buf->vb.queue);
+		buf->vb.state = VIDEOBUF_ERROR;
+		wake_up(&buf->vb.done);
+		dprintk(1,"[%p/%d] %s - dma=0x%08lx\n",
+			buf, buf->vb.i, reason, (unsigned long)buf->risc.dma);
+	}
+	if (restart)
+	{
+		dprintk(1, "restarting queue\n" );
+		cx8802_restart_queue(dev,q);
+	}
+	spin_unlock_irqrestore(&dev->slock,flags);
+}
+
+void cx8802_cancel_buffers(struct cx8802_dev *dev)
+{
+	struct cx88_dmaqueue *q = &dev->mpegq;
+
+	dprintk( 1, "cx8802_cancel_buffers" );
+	del_timer_sync(&q->timeout);
+	cx8802_stop_dma(dev);
+	do_cancel_buffers(dev,"cancel",0);
+}
+
+static void cx8802_timeout(unsigned long data)
+{
+	struct cx8802_dev *dev = (struct cx8802_dev*)data;
+
+	dprintk(1, "%s\n",__func__);
+
+	if (debug)
+		cx88_sram_channel_dump(dev->core, &cx88_sram_channels[SRAM_CH28]);
+	cx8802_stop_dma(dev);
+	do_cancel_buffers(dev,"timeout",1);
+}
+
+static const char * cx88_mpeg_irqs[32] = {
+	"ts_risci1", NULL, NULL, NULL,
+	"ts_risci2", NULL, NULL, NULL,
+	"ts_oflow",  NULL, NULL, NULL,
+	"ts_sync",   NULL, NULL, NULL,
+	"opc_err", "par_err", "rip_err", "pci_abort",
+	"ts_err?",
+};
+
+static void cx8802_mpeg_irq(struct cx8802_dev *dev)
+{
+	struct cx88_core *core = dev->core;
+	u32 status, mask, count;
+
+	dprintk( 1, "cx8802_mpeg_irq\n" );
+	status = cx_read(MO_TS_INTSTAT);
+	mask   = cx_read(MO_TS_INTMSK);
+	if (0 == (status & mask))
+		return;
+
+	cx_write(MO_TS_INTSTAT, status);
+
+	if (debug || (status & mask & ~0xff))
+		cx88_print_irqbits(core->name, "irq mpeg ",
+				   cx88_mpeg_irqs, ARRAY_SIZE(cx88_mpeg_irqs),
+				   status, mask);
+
+	/* risc op code error */
+	if (status & (1 << 16)) {
+		printk(KERN_WARNING "%s: mpeg risc op code error\n",core->name);
+		cx_clear(MO_TS_DMACNTRL, 0x11);
+		cx88_sram_channel_dump(dev->core, &cx88_sram_channels[SRAM_CH28]);
+	}
+
+	/* risc1 y */
+	if (status & 0x01) {
+		dprintk( 1, "wake up\n" );
+		spin_lock(&dev->slock);
+		count = cx_read(MO_TS_GPCNT);
+		cx88_wakeup(dev->core, &dev->mpegq, count);
+		spin_unlock(&dev->slock);
+	}
+
+	/* risc2 y */
+	if (status & 0x10) {
+		spin_lock(&dev->slock);
+		cx8802_restart_queue(dev,&dev->mpegq);
+		spin_unlock(&dev->slock);
+	}
+
+	/* other general errors */
+	if (status & 0x1f0100) {
+		dprintk( 0, "general errors: 0x%08x\n", status & 0x1f0100 );
+		spin_lock(&dev->slock);
+		cx8802_stop_dma(dev);
+		cx8802_restart_queue(dev,&dev->mpegq);
+		spin_unlock(&dev->slock);
+	}
+}
+
+#define MAX_IRQ_LOOP 10
+
+static irqreturn_t cx8802_irq(int irq, void *dev_id)
+{
+	struct cx8802_dev *dev = dev_id;
+	struct cx88_core *core = dev->core;
+	u32 status;
+	int loop, handled = 0;
+
+	for (loop = 0; loop < MAX_IRQ_LOOP; loop++) {
+		status = cx_read(MO_PCI_INTSTAT) &
+			(core->pci_irqmask | PCI_INT_TSINT);
+		if (0 == status)
+			goto out;
+		dprintk( 1, "cx8802_irq\n" );
+		dprintk( 1, "    loop: %d/%d\n", loop, MAX_IRQ_LOOP );
+		dprintk( 1, "    status: %d\n", status );
+		handled = 1;
+		cx_write(MO_PCI_INTSTAT, status);
+
+		if (status & core->pci_irqmask)
+			cx88_core_irq(core,status);
+		if (status & PCI_INT_TSINT)
+			cx8802_mpeg_irq(dev);
+	};
+	if (MAX_IRQ_LOOP == loop) {
+		dprintk( 0, "clearing mask\n" );
+		printk(KERN_WARNING "%s/0: irq loop -- clearing mask\n",
+		       core->name);
+		cx_write(MO_PCI_INTMSK,0);
+	}
+
+ out:
+	return IRQ_RETVAL(handled);
+}
+
+static int cx8802_init_common(struct cx8802_dev *dev)
+{
+	struct cx88_core *core = dev->core;
+	int err;
+
+	/* pci init */
+	if (pci_enable_device(dev->pci))
+		return -EIO;
+	pci_set_master(dev->pci);
+	if (!pci_dma_supported(dev->pci,DMA_BIT_MASK(32))) {
+		printk("%s/2: Oops: no 32bit PCI DMA ???\n",dev->core->name);
+		return -EIO;
+	}
+
+	dev->pci_rev = dev->pci->revision;
+	pci_read_config_byte(dev->pci, PCI_LATENCY_TIMER,  &dev->pci_lat);
+	printk(KERN_INFO "%s/2: found at %s, rev: %d, irq: %d, "
+	       "latency: %d, mmio: 0x%llx\n", dev->core->name,
+	       pci_name(dev->pci), dev->pci_rev, dev->pci->irq,
+	       dev->pci_lat,(unsigned long long)pci_resource_start(dev->pci,0));
+
+	/* initialize driver struct */
+	spin_lock_init(&dev->slock);
+
+	/* init dma queue */
+	INIT_LIST_HEAD(&dev->mpegq.active);
+	INIT_LIST_HEAD(&dev->mpegq.queued);
+	dev->mpegq.timeout.function = cx8802_timeout;
+	dev->mpegq.timeout.data     = (unsigned long)dev;
+	init_timer(&dev->mpegq.timeout);
+	cx88_risc_stopper(dev->pci,&dev->mpegq.stopper,
+			  MO_TS_DMACNTRL,0x11,0x00);
+
+	/* get irq */
+	err = request_irq(dev->pci->irq, cx8802_irq,
+			  IRQF_SHARED | IRQF_DISABLED, dev->core->name, dev);
+	if (err < 0) {
+		printk(KERN_ERR "%s: can't get IRQ %d\n",
+		       dev->core->name, dev->pci->irq);
+		return err;
+	}
+	cx_set(MO_PCI_INTMSK, core->pci_irqmask);
+
+	/* everything worked */
+	pci_set_drvdata(dev->pci,dev);
+	return 0;
+}
+
+static void cx8802_fini_common(struct cx8802_dev *dev)
+{
+	dprintk( 2, "cx8802_fini_common\n" );
+	cx8802_stop_dma(dev);
+	pci_disable_device(dev->pci);
+
+	/* unregister stuff */
+	free_irq(dev->pci->irq, dev);
+	pci_set_drvdata(dev->pci, NULL);
+
+	/* free memory */
+	btcx_riscmem_free(dev->pci,&dev->mpegq.stopper);
+}
+
+/* ----------------------------------------------------------- */
+
+static int cx8802_suspend_common(struct pci_dev *pci_dev, pm_message_t state)
+{
+	struct cx8802_dev *dev = pci_get_drvdata(pci_dev);
+	struct cx88_core *core = dev->core;
+
+	/* stop mpeg dma */
+	spin_lock(&dev->slock);
+	if (!list_empty(&dev->mpegq.active)) {
+		dprintk( 2, "suspend\n" );
+		printk("%s: suspend mpeg\n", core->name);
+		cx8802_stop_dma(dev);
+		del_timer(&dev->mpegq.timeout);
+	}
+	spin_unlock(&dev->slock);
+
+	/* FIXME -- shutdown device */
+	cx88_shutdown(dev->core);
+
+	pci_save_state(pci_dev);
+	if (0 != pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state))) {
+		pci_disable_device(pci_dev);
+		dev->state.disabled = 1;
+	}
+	return 0;
+}
+
+static int cx8802_resume_common(struct pci_dev *pci_dev)
+{
+	struct cx8802_dev *dev = pci_get_drvdata(pci_dev);
+	struct cx88_core *core = dev->core;
+	int err;
+
+	if (dev->state.disabled) {
+		err=pci_enable_device(pci_dev);
+		if (err) {
+			printk(KERN_ERR "%s: can't enable device\n",
+					       dev->core->name);
+			return err;
+		}
+		dev->state.disabled = 0;
+	}
+	err=pci_set_power_state(pci_dev, PCI_D0);
+	if (err) {
+		printk(KERN_ERR "%s: can't enable device\n",
+					       dev->core->name);
+		pci_disable_device(pci_dev);
+		dev->state.disabled = 1;
+
+		return err;
+	}
+	pci_restore_state(pci_dev);
+
+	/* FIXME: re-initialize hardware */
+	cx88_reset(dev->core);
+
+	/* restart video+vbi capture */
+	spin_lock(&dev->slock);
+	if (!list_empty(&dev->mpegq.active)) {
+		printk("%s: resume mpeg\n", core->name);
+		cx8802_restart_queue(dev,&dev->mpegq);
+	}
+	spin_unlock(&dev->slock);
+
+	return 0;
+}
+
+struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board_type btype)
+{
+	struct cx8802_driver *d;
+
+	list_for_each_entry(d, &dev->drvlist, drvlist)
+		if (d->type_id == btype)
+			return d;
+
+	return NULL;
+}
+
+/* Driver asked for hardware access. */
+static int cx8802_request_acquire(struct cx8802_driver *drv)
+{
+	struct cx88_core *core = drv->core;
+	unsigned int	i;
+
+	/* Fail a request for hardware if the device is busy. */
+	if (core->active_type_id != CX88_BOARD_NONE &&
+	    core->active_type_id != drv->type_id)
+		return -EBUSY;
+
+	if (drv->type_id == CX88_MPEG_DVB) {
+		/* When switching to DVB, always set the input to the tuner */
+		core->last_analog_input = core->input;
+		core->input = 0;
+		for (i = 0;
+		     i < (sizeof(core->board.input) / sizeof(struct cx88_input));
+		     i++) {
+			if (core->board.input[i].type == CX88_VMUX_DVB) {
+				core->input = i;
+				break;
+			}
+		}
+	}
+
+	if (drv->advise_acquire)
+	{
+		core->active_ref++;
+		if (core->active_type_id == CX88_BOARD_NONE) {
+			core->active_type_id = drv->type_id;
+			drv->advise_acquire(drv);
+		}
+
+		mpeg_dbg(1,"%s() Post acquire GPIO=%x\n", __func__, cx_read(MO_GP0_IO));
+	}
+
+	return 0;
+}
+
+/* Driver asked to release hardware. */
+static int cx8802_request_release(struct cx8802_driver *drv)
+{
+	struct cx88_core *core = drv->core;
+
+	if (drv->advise_release && --core->active_ref == 0)
+	{
+		if (drv->type_id == CX88_MPEG_DVB) {
+			/* If the DVB driver is releasing, reset the input
+			   state to the last configured analog input */
+			core->input = core->last_analog_input;
+		}
+
+		drv->advise_release(drv);
+		core->active_type_id = CX88_BOARD_NONE;
+		mpeg_dbg(1,"%s() Post release GPIO=%x\n", __func__, cx_read(MO_GP0_IO));
+	}
+
+	return 0;
+}
+
+static int cx8802_check_driver(struct cx8802_driver *drv)
+{
+	if (drv == NULL)
+		return -ENODEV;
+
+	if ((drv->type_id != CX88_MPEG_DVB) &&
+		(drv->type_id != CX88_MPEG_BLACKBIRD))
+		return -EINVAL;
+
+	if ((drv->hw_access != CX8802_DRVCTL_SHARED) &&
+		(drv->hw_access != CX8802_DRVCTL_EXCLUSIVE))
+		return -EINVAL;
+
+	if ((drv->probe == NULL) ||
+		(drv->remove == NULL) ||
+		(drv->advise_acquire == NULL) ||
+		(drv->advise_release == NULL))
+		return -EINVAL;
+
+	return 0;
+}
+
+int cx8802_register_driver(struct cx8802_driver *drv)
+{
+	struct cx8802_dev *dev;
+	struct cx8802_driver *driver;
+	int err, i = 0;
+
+	printk(KERN_INFO
+	       "cx88/2: registering cx8802 driver, type: %s access: %s\n",
+	       drv->type_id == CX88_MPEG_DVB ? "dvb" : "blackbird",
+	       drv->hw_access == CX8802_DRVCTL_SHARED ? "shared" : "exclusive");
+
+	if ((err = cx8802_check_driver(drv)) != 0) {
+		printk(KERN_ERR "cx88/2: cx8802_driver is invalid\n");
+		return err;
+	}
+
+	mutex_lock(&cx8802_mutex);
+
+	list_for_each_entry(dev, &cx8802_devlist, devlist) {
+		printk(KERN_INFO
+		       "%s/2: subsystem: %04x:%04x, board: %s [card=%d]\n",
+		       dev->core->name, dev->pci->subsystem_vendor,
+		       dev->pci->subsystem_device, dev->core->board.name,
+		       dev->core->boardnr);
+
+		/* Bring up a new struct for each driver instance */
+		driver = kzalloc(sizeof(*drv),GFP_KERNEL);
+		if (driver == NULL) {
+			err = -ENOMEM;
+			goto out;
+		}
+
+		/* Snapshot of the driver registration data */
+		drv->core = dev->core;
+		drv->suspend = cx8802_suspend_common;
+		drv->resume = cx8802_resume_common;
+		drv->request_acquire = cx8802_request_acquire;
+		drv->request_release = cx8802_request_release;
+		memcpy(driver, drv, sizeof(*driver));
+
+		mutex_lock(&drv->core->lock);
+		err = drv->probe(driver);
+		if (err == 0) {
+			i++;
+			list_add_tail(&driver->drvlist, &dev->drvlist);
+		} else {
+			printk(KERN_ERR
+			       "%s/2: cx8802 probe failed, err = %d\n",
+			       dev->core->name, err);
+		}
+		mutex_unlock(&drv->core->lock);
+	}
+
+	err = i ? 0 : -ENODEV;
+out:
+	mutex_unlock(&cx8802_mutex);
+	return err;
+}
+
+int cx8802_unregister_driver(struct cx8802_driver *drv)
+{
+	struct cx8802_dev *dev;
+	struct cx8802_driver *d, *dtmp;
+	int err = 0;
+
+	printk(KERN_INFO
+	       "cx88/2: unregistering cx8802 driver, type: %s access: %s\n",
+	       drv->type_id == CX88_MPEG_DVB ? "dvb" : "blackbird",
+	       drv->hw_access == CX8802_DRVCTL_SHARED ? "shared" : "exclusive");
+
+	mutex_lock(&cx8802_mutex);
+
+	list_for_each_entry(dev, &cx8802_devlist, devlist) {
+		printk(KERN_INFO
+		       "%s/2: subsystem: %04x:%04x, board: %s [card=%d]\n",
+		       dev->core->name, dev->pci->subsystem_vendor,
+		       dev->pci->subsystem_device, dev->core->board.name,
+		       dev->core->boardnr);
+
+		mutex_lock(&dev->core->lock);
+
+		list_for_each_entry_safe(d, dtmp, &dev->drvlist, drvlist) {
+			/* only unregister the correct driver type */
+			if (d->type_id != drv->type_id)
+				continue;
+
+			err = d->remove(d);
+			if (err == 0) {
+				list_del(&d->drvlist);
+				kfree(d);
+			} else
+				printk(KERN_ERR "%s/2: cx8802 driver remove "
+				       "failed (%d)\n", dev->core->name, err);
+		}
+
+		mutex_unlock(&dev->core->lock);
+	}
+
+	mutex_unlock(&cx8802_mutex);
+
+	return err;
+}
+
+/* ----------------------------------------------------------- */
+static int __devinit cx8802_probe(struct pci_dev *pci_dev,
+			       const struct pci_device_id *pci_id)
+{
+	struct cx8802_dev *dev;
+	struct cx88_core  *core;
+	int err;
+
+	/* general setup */
+	core = cx88_core_get(pci_dev);
+	if (NULL == core)
+		return -EINVAL;
+
+	printk("%s/2: cx2388x 8802 Driver Manager\n", core->name);
+
+	err = -ENODEV;
+	if (!core->board.mpeg)
+		goto fail_core;
+
+	err = -ENOMEM;
+	dev = kzalloc(sizeof(*dev),GFP_KERNEL);
+	if (NULL == dev)
+		goto fail_core;
+	dev->pci = pci_dev;
+	dev->core = core;
+
+	/* Maintain a reference so cx88-video can query the 8802 device. */
+	core->dvbdev = dev;
+
+	err = cx8802_init_common(dev);
+	if (err != 0)
+		goto fail_free;
+
+	INIT_LIST_HEAD(&dev->drvlist);
+	mutex_lock(&cx8802_mutex);
+	list_add_tail(&dev->devlist,&cx8802_devlist);
+	mutex_unlock(&cx8802_mutex);
+
+	/* now autoload cx88-dvb or cx88-blackbird */
+	request_modules(dev);
+	return 0;
+
+ fail_free:
+	kfree(dev);
+ fail_core:
+	core->dvbdev = NULL;
+	cx88_core_put(core,pci_dev);
+	return err;
+}
+
+static void __devexit cx8802_remove(struct pci_dev *pci_dev)
+{
+	struct cx8802_dev *dev;
+
+	dev = pci_get_drvdata(pci_dev);
+
+	dprintk( 1, "%s\n", __func__);
+
+	flush_request_modules(dev);
+
+	mutex_lock(&dev->core->lock);
+
+	if (!list_empty(&dev->drvlist)) {
+		struct cx8802_driver *drv, *tmp;
+		int err;
+
+		printk(KERN_WARNING "%s/2: Trying to remove cx8802 driver "
+		       "while cx8802 sub-drivers still loaded?!\n",
+		       dev->core->name);
+
+		list_for_each_entry_safe(drv, tmp, &dev->drvlist, drvlist) {
+			err = drv->remove(drv);
+			if (err == 0) {
+				list_del(&drv->drvlist);
+			} else
+				printk(KERN_ERR "%s/2: cx8802 driver remove "
+				       "failed (%d)\n", dev->core->name, err);
+			kfree(drv);
+		}
+	}
+
+	mutex_unlock(&dev->core->lock);
+
+	/* Destroy any 8802 reference. */
+	dev->core->dvbdev = NULL;
+
+	/* common */
+	cx8802_fini_common(dev);
+	cx88_core_put(dev->core,dev->pci);
+	kfree(dev);
+}
+
+static const struct pci_device_id cx8802_pci_tbl[] = {
+	{
+		.vendor       = 0x14f1,
+		.device       = 0x8802,
+		.subvendor    = PCI_ANY_ID,
+		.subdevice    = PCI_ANY_ID,
+	},{
+		/* --- end of list --- */
+	}
+};
+MODULE_DEVICE_TABLE(pci, cx8802_pci_tbl);
+
+static struct pci_driver cx8802_pci_driver = {
+	.name     = "cx88-mpeg driver manager",
+	.id_table = cx8802_pci_tbl,
+	.probe    = cx8802_probe,
+	.remove   = __devexit_p(cx8802_remove),
+};
+
+static int __init cx8802_init(void)
+{
+	printk(KERN_INFO "cx88/2: cx2388x MPEG-TS Driver Manager version %s loaded\n",
+	       CX88_VERSION);
+	return pci_register_driver(&cx8802_pci_driver);
+}
+
+static void __exit cx8802_fini(void)
+{
+	pci_unregister_driver(&cx8802_pci_driver);
+}
+
+module_init(cx8802_init);
+module_exit(cx8802_fini);
+EXPORT_SYMBOL(cx8802_buf_prepare);
+EXPORT_SYMBOL(cx8802_buf_queue);
+EXPORT_SYMBOL(cx8802_cancel_buffers);
+
+EXPORT_SYMBOL(cx8802_register_driver);
+EXPORT_SYMBOL(cx8802_unregister_driver);
+EXPORT_SYMBOL(cx8802_get_driver);
+/* ----------------------------------------------------------- */
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off
+ */
diff --git a/drivers/media/pci/cx88/cx88-reg.h b/drivers/media/pci/cx88/cx88-reg.h
new file mode 100644
index 0000000..2ec52d1
--- /dev/null
+++ b/drivers/media/pci/cx88/cx88-reg.h
@@ -0,0 +1,836 @@
+/*
+
+    cx88x-hw.h - CX2388x register offsets
+
+    Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de)
+		  2001 Michael Eskin
+		  2002 Yurij Sysoev <yurij@naturesoft.net>
+		  2003 Gerd Knorr <kraxel@bytesex.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 _CX88_REG_H_
+#define _CX88_REG_H_
+
+/* ---------------------------------------------------------------------- */
+/* PCI IDs and config space                                               */
+
+#ifndef PCI_VENDOR_ID_CONEXANT
+# define PCI_VENDOR_ID_CONEXANT		0x14F1
+#endif
+#ifndef PCI_DEVICE_ID_CX2300_VID
+# define PCI_DEVICE_ID_CX2300_VID	0x8800
+#endif
+
+#define CX88X_DEVCTRL 0x40
+#define CX88X_EN_TBFX 0x02
+#define CX88X_EN_VSFX 0x04
+
+/* ---------------------------------------------------------------------- */
+/* PCI controller registers                                               */
+
+/* Command and Status Register */
+#define F0_CMD_STAT_MM      0x2f0004
+#define F1_CMD_STAT_MM      0x2f0104
+#define F2_CMD_STAT_MM      0x2f0204
+#define F3_CMD_STAT_MM      0x2f0304
+#define F4_CMD_STAT_MM      0x2f0404
+
+/* Device Control #1 */
+#define F0_DEV_CNTRL1_MM    0x2f0040
+#define F1_DEV_CNTRL1_MM    0x2f0140
+#define F2_DEV_CNTRL1_MM    0x2f0240
+#define F3_DEV_CNTRL1_MM    0x2f0340
+#define F4_DEV_CNTRL1_MM    0x2f0440
+
+/* Device Control #1 */
+#define F0_BAR0_MM          0x2f0010
+#define F1_BAR0_MM          0x2f0110
+#define F2_BAR0_MM          0x2f0210
+#define F3_BAR0_MM          0x2f0310
+#define F4_BAR0_MM          0x2f0410
+
+/* ---------------------------------------------------------------------- */
+/* DMA Controller registers                                               */
+
+#define MO_PDMA_STHRSH      0x200000 // Source threshold
+#define MO_PDMA_STADRS      0x200004 // Source target address
+#define MO_PDMA_SIADRS      0x200008 // Source internal address
+#define MO_PDMA_SCNTRL      0x20000C // Source control
+#define MO_PDMA_DTHRSH      0x200010 // Destination threshold
+#define MO_PDMA_DTADRS      0x200014 // Destination target address
+#define MO_PDMA_DIADRS      0x200018 // Destination internal address
+#define MO_PDMA_DCNTRL      0x20001C // Destination control
+#define MO_LD_SSID          0x200030 // Load subsystem ID
+#define MO_DEV_CNTRL2       0x200034 // Device control
+#define MO_PCI_INTMSK       0x200040 // PCI interrupt mask
+#define MO_PCI_INTSTAT      0x200044 // PCI interrupt status
+#define MO_PCI_INTMSTAT     0x200048 // PCI interrupt masked status
+#define MO_VID_INTMSK       0x200050 // Video interrupt mask
+#define MO_VID_INTSTAT      0x200054 // Video interrupt status
+#define MO_VID_INTMSTAT     0x200058 // Video interrupt masked status
+#define MO_VID_INTSSTAT     0x20005C // Video interrupt set status
+#define MO_AUD_INTMSK       0x200060 // Audio interrupt mask
+#define MO_AUD_INTSTAT      0x200064 // Audio interrupt status
+#define MO_AUD_INTMSTAT     0x200068 // Audio interrupt masked status
+#define MO_AUD_INTSSTAT     0x20006C // Audio interrupt set status
+#define MO_TS_INTMSK        0x200070 // Transport stream interrupt mask
+#define MO_TS_INTSTAT       0x200074 // Transport stream interrupt status
+#define MO_TS_INTMSTAT      0x200078 // Transport stream interrupt mask status
+#define MO_TS_INTSSTAT      0x20007C // Transport stream interrupt set status
+#define MO_VIP_INTMSK       0x200080 // VIP interrupt mask
+#define MO_VIP_INTSTAT      0x200084 // VIP interrupt status
+#define MO_VIP_INTMSTAT     0x200088 // VIP interrupt masked status
+#define MO_VIP_INTSSTAT     0x20008C // VIP interrupt set status
+#define MO_GPHST_INTMSK     0x200090 // Host interrupt mask
+#define MO_GPHST_INTSTAT    0x200094 // Host interrupt status
+#define MO_GPHST_INTMSTAT   0x200098 // Host interrupt masked status
+#define MO_GPHST_INTSSTAT   0x20009C // Host interrupt set status
+
+// DMA Channels 1-6 belong to SPIPE
+#define MO_DMA7_PTR1        0x300018 // {24}RW* DMA Current Ptr : Ch#7
+#define MO_DMA8_PTR1        0x30001C // {24}RW* DMA Current Ptr : Ch#8
+
+// DMA Channels 9-20 belong to SPIPE
+#define MO_DMA21_PTR1       0x300080 // {24}R0* DMA Current Ptr : Ch#21
+#define MO_DMA22_PTR1       0x300084 // {24}R0* DMA Current Ptr : Ch#22
+#define MO_DMA23_PTR1       0x300088 // {24}R0* DMA Current Ptr : Ch#23
+#define MO_DMA24_PTR1       0x30008C // {24}R0* DMA Current Ptr : Ch#24
+#define MO_DMA25_PTR1       0x300090 // {24}R0* DMA Current Ptr : Ch#25
+#define MO_DMA26_PTR1       0x300094 // {24}R0* DMA Current Ptr : Ch#26
+#define MO_DMA27_PTR1       0x300098 // {24}R0* DMA Current Ptr : Ch#27
+#define MO_DMA28_PTR1       0x30009C // {24}R0* DMA Current Ptr : Ch#28
+#define MO_DMA29_PTR1       0x3000A0 // {24}R0* DMA Current Ptr : Ch#29
+#define MO_DMA30_PTR1       0x3000A4 // {24}R0* DMA Current Ptr : Ch#30
+#define MO_DMA31_PTR1       0x3000A8 // {24}R0* DMA Current Ptr : Ch#31
+#define MO_DMA32_PTR1       0x3000AC // {24}R0* DMA Current Ptr : Ch#32
+
+#define MO_DMA21_PTR2       0x3000C0 // {24}RW* DMA Tab Ptr : Ch#21
+#define MO_DMA22_PTR2       0x3000C4 // {24}RW* DMA Tab Ptr : Ch#22
+#define MO_DMA23_PTR2       0x3000C8 // {24}RW* DMA Tab Ptr : Ch#23
+#define MO_DMA24_PTR2       0x3000CC // {24}RW* DMA Tab Ptr : Ch#24
+#define MO_DMA25_PTR2       0x3000D0 // {24}RW* DMA Tab Ptr : Ch#25
+#define MO_DMA26_PTR2       0x3000D4 // {24}RW* DMA Tab Ptr : Ch#26
+#define MO_DMA27_PTR2       0x3000D8 // {24}RW* DMA Tab Ptr : Ch#27
+#define MO_DMA28_PTR2       0x3000DC // {24}RW* DMA Tab Ptr : Ch#28
+#define MO_DMA29_PTR2       0x3000E0 // {24}RW* DMA Tab Ptr : Ch#29
+#define MO_DMA30_PTR2       0x3000E4 // {24}RW* DMA Tab Ptr : Ch#30
+#define MO_DMA31_PTR2       0x3000E8 // {24}RW* DMA Tab Ptr : Ch#31
+#define MO_DMA32_PTR2       0x3000EC // {24}RW* DMA Tab Ptr : Ch#32
+
+#define MO_DMA21_CNT1       0x300100 // {11}RW* DMA Buffer Size : Ch#21
+#define MO_DMA22_CNT1       0x300104 // {11}RW* DMA Buffer Size : Ch#22
+#define MO_DMA23_CNT1       0x300108 // {11}RW* DMA Buffer Size : Ch#23
+#define MO_DMA24_CNT1       0x30010C // {11}RW* DMA Buffer Size : Ch#24
+#define MO_DMA25_CNT1       0x300110 // {11}RW* DMA Buffer Size : Ch#25
+#define MO_DMA26_CNT1       0x300114 // {11}RW* DMA Buffer Size : Ch#26
+#define MO_DMA27_CNT1       0x300118 // {11}RW* DMA Buffer Size : Ch#27
+#define MO_DMA28_CNT1       0x30011C // {11}RW* DMA Buffer Size : Ch#28
+#define MO_DMA29_CNT1       0x300120 // {11}RW* DMA Buffer Size : Ch#29
+#define MO_DMA30_CNT1       0x300124 // {11}RW* DMA Buffer Size : Ch#30
+#define MO_DMA31_CNT1       0x300128 // {11}RW* DMA Buffer Size : Ch#31
+#define MO_DMA32_CNT1       0x30012C // {11}RW* DMA Buffer Size : Ch#32
+
+#define MO_DMA21_CNT2       0x300140 // {11}RW* DMA Table Size : Ch#21
+#define MO_DMA22_CNT2       0x300144 // {11}RW* DMA Table Size : Ch#22
+#define MO_DMA23_CNT2       0x300148 // {11}RW* DMA Table Size : Ch#23
+#define MO_DMA24_CNT2       0x30014C // {11}RW* DMA Table Size : Ch#24
+#define MO_DMA25_CNT2       0x300150 // {11}RW* DMA Table Size : Ch#25
+#define MO_DMA26_CNT2       0x300154 // {11}RW* DMA Table Size : Ch#26
+#define MO_DMA27_CNT2       0x300158 // {11}RW* DMA Table Size : Ch#27
+#define MO_DMA28_CNT2       0x30015C // {11}RW* DMA Table Size : Ch#28
+#define MO_DMA29_CNT2       0x300160 // {11}RW* DMA Table Size : Ch#29
+#define MO_DMA30_CNT2       0x300164 // {11}RW* DMA Table Size : Ch#30
+#define MO_DMA31_CNT2       0x300168 // {11}RW* DMA Table Size : Ch#31
+#define MO_DMA32_CNT2       0x30016C // {11}RW* DMA Table Size : Ch#32
+
+
+/* ---------------------------------------------------------------------- */
+/* Video registers                                                        */
+
+#define MO_VIDY_DMA         0x310000 // {64}RWp Video Y
+#define MO_VIDU_DMA         0x310008 // {64}RWp Video U
+#define MO_VIDV_DMA         0x310010 // {64}RWp Video V
+#define MO_VBI_DMA          0x310018 // {64}RWp VBI (Vertical blanking interval)
+
+#define MO_DEVICE_STATUS    0x310100
+#define MO_INPUT_FORMAT     0x310104
+#define MO_AGC_BURST        0x31010c
+#define MO_CONTR_BRIGHT     0x310110
+#define MO_UV_SATURATION    0x310114
+#define MO_HUE              0x310118
+#define MO_HTOTAL           0x310120
+#define MO_HDELAY_EVEN      0x310124
+#define MO_HDELAY_ODD       0x310128
+#define MO_VDELAY_ODD       0x31012c
+#define MO_VDELAY_EVEN      0x310130
+#define MO_HACTIVE_EVEN     0x31013c
+#define MO_HACTIVE_ODD      0x310140
+#define MO_VACTIVE_EVEN     0x310144
+#define MO_VACTIVE_ODD      0x310148
+#define MO_HSCALE_EVEN      0x31014c
+#define MO_HSCALE_ODD       0x310150
+#define MO_VSCALE_EVEN      0x310154
+#define MO_FILTER_EVEN      0x31015c
+#define MO_VSCALE_ODD       0x310158
+#define MO_FILTER_ODD       0x310160
+#define MO_OUTPUT_FORMAT    0x310164
+
+#define MO_PLL_REG          0x310168 // PLL register
+#define MO_PLL_ADJ_CTRL     0x31016c // PLL adjust control register
+#define MO_SCONV_REG        0x310170 // sample rate conversion register
+#define MO_SCONV_FIFO       0x310174 // sample rate conversion fifo
+#define MO_SUB_STEP         0x310178 // subcarrier step size
+#define MO_SUB_STEP_DR      0x31017c // subcarrier step size for DR line
+
+#define MO_CAPTURE_CTRL     0x310180 // capture control
+#define MO_COLOR_CTRL       0x310184
+#define MO_VBI_PACKET       0x310188 // vbi packet size / delay
+#define MO_FIELD_COUNT      0x310190 // field counter
+#define MO_VIP_CONFIG       0x310194
+#define MO_VBOS_CONTROL	    0x3101a8
+
+#define MO_AGC_BACK_VBI     0x310200
+#define MO_AGC_SYNC_TIP1    0x310208
+
+#define MO_VIDY_GPCNT       0x31C020 // {16}RO Video Y general purpose counter
+#define MO_VIDU_GPCNT       0x31C024 // {16}RO Video U general purpose counter
+#define MO_VIDV_GPCNT       0x31C028 // {16}RO Video V general purpose counter
+#define MO_VBI_GPCNT        0x31C02C // {16}RO VBI general purpose counter
+#define MO_VIDY_GPCNTRL     0x31C030 // {2}WO Video Y general purpose control
+#define MO_VIDU_GPCNTRL     0x31C034 // {2}WO Video U general purpose control
+#define MO_VIDV_GPCNTRL     0x31C038 // {2}WO Video V general purpose control
+#define MO_VBI_GPCNTRL      0x31C03C // {2}WO VBI general purpose counter
+#define MO_VID_DMACNTRL     0x31C040 // {8}RW Video DMA control
+#define MO_VID_XFR_STAT     0x31C044 // {1}RO Video transfer status
+
+
+/* ---------------------------------------------------------------------- */
+/* audio registers                                                        */
+
+#define MO_AUDD_DMA         0x320000 // {64}RWp Audio downstream
+#define MO_AUDU_DMA         0x320008 // {64}RWp Audio upstream
+#define MO_AUDR_DMA         0x320010 // {64}RWp Audio RDS (downstream)
+#define MO_AUDD_GPCNT       0x32C020 // {16}RO Audio down general purpose counter
+#define MO_AUDU_GPCNT       0x32C024 // {16}RO Audio up general purpose counter
+#define MO_AUDR_GPCNT       0x32C028 // {16}RO Audio RDS general purpose counter
+#define MO_AUDD_GPCNTRL     0x32C030 // {2}WO Audio down general purpose control
+#define MO_AUDU_GPCNTRL     0x32C034 // {2}WO Audio up general purpose control
+#define MO_AUDR_GPCNTRL     0x32C038 // {2}WO Audio RDS general purpose control
+#define MO_AUD_DMACNTRL     0x32C040 // {6}RW Audio DMA control
+#define MO_AUD_XFR_STAT     0x32C044 // {1}RO Audio transfer status
+#define MO_AUDD_LNGTH       0x32C048 // {12}RW Audio down line length
+#define MO_AUDR_LNGTH       0x32C04C // {12}RW Audio RDS line length
+
+#define AUD_INIT                 0x320100
+#define AUD_INIT_LD              0x320104
+#define AUD_SOFT_RESET           0x320108
+#define AUD_I2SINPUTCNTL         0x320120
+#define AUD_BAUDRATE             0x320124
+#define AUD_I2SOUTPUTCNTL        0x320128
+#define AAGC_HYST                0x320134
+#define AAGC_GAIN                0x320138
+#define AAGC_DEF                 0x32013c
+#define AUD_IIR1_0_SEL           0x320150
+#define AUD_IIR1_0_SHIFT         0x320154
+#define AUD_IIR1_1_SEL           0x320158
+#define AUD_IIR1_1_SHIFT         0x32015c
+#define AUD_IIR1_2_SEL           0x320160
+#define AUD_IIR1_2_SHIFT         0x320164
+#define AUD_IIR1_3_SEL           0x320168
+#define AUD_IIR1_3_SHIFT         0x32016c
+#define AUD_IIR1_4_SEL           0x320170
+#define AUD_IIR1_4_SHIFT         0x32017c
+#define AUD_IIR1_5_SEL           0x320180
+#define AUD_IIR1_5_SHIFT         0x320184
+#define AUD_IIR2_0_SEL           0x320190
+#define AUD_IIR2_0_SHIFT         0x320194
+#define AUD_IIR2_1_SEL           0x320198
+#define AUD_IIR2_1_SHIFT         0x32019c
+#define AUD_IIR2_2_SEL           0x3201a0
+#define AUD_IIR2_2_SHIFT         0x3201a4
+#define AUD_IIR2_3_SEL           0x3201a8
+#define AUD_IIR2_3_SHIFT         0x3201ac
+#define AUD_IIR3_0_SEL           0x3201c0
+#define AUD_IIR3_0_SHIFT         0x3201c4
+#define AUD_IIR3_1_SEL           0x3201c8
+#define AUD_IIR3_1_SHIFT         0x3201cc
+#define AUD_IIR3_2_SEL           0x3201d0
+#define AUD_IIR3_2_SHIFT         0x3201d4
+#define AUD_IIR4_0_SEL           0x3201e0
+#define AUD_IIR4_0_SHIFT         0x3201e4
+#define AUD_IIR4_1_SEL           0x3201e8
+#define AUD_IIR4_1_SHIFT         0x3201ec
+#define AUD_IIR4_2_SEL           0x3201f0
+#define AUD_IIR4_2_SHIFT         0x3201f4
+#define AUD_IIR4_0_CA0           0x320200
+#define AUD_IIR4_0_CA1           0x320204
+#define AUD_IIR4_0_CA2           0x320208
+#define AUD_IIR4_0_CB0           0x32020c
+#define AUD_IIR4_0_CB1           0x320210
+#define AUD_IIR4_1_CA0           0x320214
+#define AUD_IIR4_1_CA1           0x320218
+#define AUD_IIR4_1_CA2           0x32021c
+#define AUD_IIR4_1_CB0           0x320220
+#define AUD_IIR4_1_CB1           0x320224
+#define AUD_IIR4_2_CA0           0x320228
+#define AUD_IIR4_2_CA1           0x32022c
+#define AUD_IIR4_2_CA2           0x320230
+#define AUD_IIR4_2_CB0           0x320234
+#define AUD_IIR4_2_CB1           0x320238
+#define AUD_HP_MD_IIR4_1         0x320250
+#define AUD_HP_PROG_IIR4_1       0x320254
+#define AUD_FM_MODE_ENABLE       0x320258
+#define AUD_POLY0_DDS_CONSTANT   0x320270
+#define AUD_DN0_FREQ             0x320274
+#define AUD_DN1_FREQ             0x320278
+#define AUD_DN1_FREQ_SHIFT       0x32027c
+#define AUD_DN1_AFC              0x320280
+#define AUD_DN1_SRC_SEL          0x320284
+#define AUD_DN1_SHFT             0x320288
+#define AUD_DN2_FREQ             0x32028c
+#define AUD_DN2_FREQ_SHIFT       0x320290
+#define AUD_DN2_AFC              0x320294
+#define AUD_DN2_SRC_SEL          0x320298
+#define AUD_DN2_SHFT             0x32029c
+#define AUD_CRDC0_SRC_SEL        0x320300
+#define AUD_CRDC0_SHIFT          0x320304
+#define AUD_CORDIC_SHIFT_0       0x320308
+#define AUD_CRDC1_SRC_SEL        0x32030c
+#define AUD_CRDC1_SHIFT          0x320310
+#define AUD_CORDIC_SHIFT_1       0x320314
+#define AUD_DCOC_0_SRC           0x320320
+#define AUD_DCOC0_SHIFT          0x320324
+#define AUD_DCOC_0_SHIFT_IN0     0x320328
+#define AUD_DCOC_0_SHIFT_IN1     0x32032c
+#define AUD_DCOC_1_SRC           0x320330
+#define AUD_DCOC1_SHIFT          0x320334
+#define AUD_DCOC_1_SHIFT_IN0     0x320338
+#define AUD_DCOC_1_SHIFT_IN1     0x32033c
+#define AUD_DCOC_2_SRC           0x320340
+#define AUD_DCOC2_SHIFT          0x320344
+#define AUD_DCOC_2_SHIFT_IN0     0x320348
+#define AUD_DCOC_2_SHIFT_IN1     0x32034c
+#define AUD_DCOC_PASS_IN         0x320350
+#define AUD_PDET_SRC             0x320370
+#define AUD_PDET_SHIFT           0x320374
+#define AUD_PILOT_BQD_1_K0       0x320380
+#define AUD_PILOT_BQD_1_K1       0x320384
+#define AUD_PILOT_BQD_1_K2       0x320388
+#define AUD_PILOT_BQD_1_K3       0x32038c
+#define AUD_PILOT_BQD_1_K4       0x320390
+#define AUD_PILOT_BQD_2_K0       0x320394
+#define AUD_PILOT_BQD_2_K1       0x320398
+#define AUD_PILOT_BQD_2_K2       0x32039c
+#define AUD_PILOT_BQD_2_K3       0x3203a0
+#define AUD_PILOT_BQD_2_K4       0x3203a4
+#define AUD_THR_FR               0x3203c0
+#define AUD_X_PROG               0x3203c4
+#define AUD_Y_PROG               0x3203c8
+#define AUD_HARMONIC_MULT        0x3203cc
+#define AUD_C1_UP_THR            0x3203d0
+#define AUD_C1_LO_THR            0x3203d4
+#define AUD_C2_UP_THR            0x3203d8
+#define AUD_C2_LO_THR            0x3203dc
+#define AUD_PLL_EN               0x320400
+#define AUD_PLL_SRC              0x320404
+#define AUD_PLL_SHIFT            0x320408
+#define AUD_PLL_IF_SEL           0x32040c
+#define AUD_PLL_IF_SHIFT         0x320410
+#define AUD_BIQUAD_PLL_K0        0x320414
+#define AUD_BIQUAD_PLL_K1        0x320418
+#define AUD_BIQUAD_PLL_K2        0x32041c
+#define AUD_BIQUAD_PLL_K3        0x320420
+#define AUD_BIQUAD_PLL_K4        0x320424
+#define AUD_DEEMPH0_SRC_SEL      0x320440
+#define AUD_DEEMPH0_SHIFT        0x320444
+#define AUD_DEEMPH0_G0           0x320448
+#define AUD_DEEMPH0_A0           0x32044c
+#define AUD_DEEMPH0_B0           0x320450
+#define AUD_DEEMPH0_A1           0x320454
+#define AUD_DEEMPH0_B1           0x320458
+#define AUD_DEEMPH1_SRC_SEL      0x32045c
+#define AUD_DEEMPH1_SHIFT        0x320460
+#define AUD_DEEMPH1_G0           0x320464
+#define AUD_DEEMPH1_A0           0x320468
+#define AUD_DEEMPH1_B0           0x32046c
+#define AUD_DEEMPH1_A1           0x320470
+#define AUD_DEEMPH1_B1           0x320474
+#define AUD_OUT0_SEL             0x320490
+#define AUD_OUT0_SHIFT           0x320494
+#define AUD_OUT1_SEL             0x320498
+#define AUD_OUT1_SHIFT           0x32049c
+#define AUD_RDSI_SEL             0x3204a0
+#define AUD_RDSI_SHIFT           0x3204a4
+#define AUD_RDSQ_SEL             0x3204a8
+#define AUD_RDSQ_SHIFT           0x3204ac
+#define AUD_DBX_IN_GAIN          0x320500
+#define AUD_DBX_WBE_GAIN         0x320504
+#define AUD_DBX_SE_GAIN          0x320508
+#define AUD_DBX_RMS_WBE          0x32050c
+#define AUD_DBX_RMS_SE           0x320510
+#define AUD_DBX_SE_BYPASS        0x320514
+#define AUD_FAWDETCTL            0x320530
+#define AUD_FAWDETWINCTL         0x320534
+#define AUD_DEEMPHGAIN_R         0x320538
+#define AUD_DEEMPHNUMER1_R       0x32053c
+#define AUD_DEEMPHNUMER2_R       0x320540
+#define AUD_DEEMPHDENOM1_R       0x320544
+#define AUD_DEEMPHDENOM2_R       0x320548
+#define AUD_ERRLOGPERIOD_R       0x32054c
+#define AUD_ERRINTRPTTHSHLD1_R   0x320550
+#define AUD_ERRINTRPTTHSHLD2_R   0x320554
+#define AUD_ERRINTRPTTHSHLD3_R   0x320558
+#define AUD_NICAM_STATUS1        0x32055c
+#define AUD_NICAM_STATUS2        0x320560
+#define AUD_ERRLOG1              0x320564
+#define AUD_ERRLOG2              0x320568
+#define AUD_ERRLOG3              0x32056c
+#define AUD_DAC_BYPASS_L         0x320580
+#define AUD_DAC_BYPASS_R         0x320584
+#define AUD_DAC_BYPASS_CTL       0x320588
+#define AUD_CTL                  0x32058c
+#define AUD_STATUS               0x320590
+#define AUD_VOL_CTL              0x320594
+#define AUD_BAL_CTL              0x320598
+#define AUD_START_TIMER          0x3205b0
+#define AUD_MODE_CHG_TIMER       0x3205b4
+#define AUD_POLYPH80SCALEFAC     0x3205b8
+#define AUD_DMD_RA_DDS           0x3205bc
+#define AUD_I2S_RA_DDS           0x3205c0
+#define AUD_RATE_THRES_DMD       0x3205d0
+#define AUD_RATE_THRES_I2S       0x3205d4
+#define AUD_RATE_ADJ1            0x3205d8
+#define AUD_RATE_ADJ2            0x3205dc
+#define AUD_RATE_ADJ3            0x3205e0
+#define AUD_RATE_ADJ4            0x3205e4
+#define AUD_RATE_ADJ5            0x3205e8
+#define AUD_APB_IN_RATE_ADJ      0x3205ec
+#define AUD_I2SCNTL              0x3205ec
+#define AUD_PHASE_FIX_CTL        0x3205f0
+#define AUD_PLL_PRESCALE         0x320600
+#define AUD_PLL_DDS              0x320604
+#define AUD_PLL_INT              0x320608
+#define AUD_PLL_FRAC             0x32060c
+#define AUD_PLL_JTAG             0x320620
+#define AUD_PLL_SPMP             0x320624
+#define AUD_AFE_12DB_EN          0x320628
+
+// Audio QAM Register Addresses
+#define AUD_PDF_DDS_CNST_BYTE2   0x320d01
+#define AUD_PDF_DDS_CNST_BYTE1   0x320d02
+#define AUD_PDF_DDS_CNST_BYTE0   0x320d03
+#define AUD_PHACC_FREQ_8MSB      0x320d2a
+#define AUD_PHACC_FREQ_8LSB      0x320d2b
+#define AUD_QAM_MODE             0x320d04
+
+
+/* ---------------------------------------------------------------------- */
+/* transport stream registers                                             */
+
+#define MO_TS_DMA           0x330000 // {64}RWp Transport stream downstream
+#define MO_TS_GPCNT         0x33C020 // {16}RO TS general purpose counter
+#define MO_TS_GPCNTRL       0x33C030 // {2}WO TS general purpose control
+#define MO_TS_DMACNTRL      0x33C040 // {6}RW TS DMA control
+#define MO_TS_XFR_STAT      0x33C044 // {1}RO TS transfer status
+#define MO_TS_LNGTH         0x33C048 // {12}RW TS line length
+
+#define TS_HW_SOP_CNTRL     0x33C04C
+#define TS_GEN_CNTRL        0x33C050
+#define TS_BD_PKT_STAT      0x33C054
+#define TS_SOP_STAT         0x33C058
+#define TS_FIFO_OVFL_STAT   0x33C05C
+#define TS_VALERR_CNTRL     0x33C060
+
+
+/* ---------------------------------------------------------------------- */
+/* VIP registers                                                          */
+
+#define MO_VIPD_DMA         0x340000 // {64}RWp VIP downstream
+#define MO_VIPU_DMA         0x340008 // {64}RWp VIP upstream
+#define MO_VIPD_GPCNT       0x34C020 // {16}RO VIP down general purpose counter
+#define MO_VIPU_GPCNT       0x34C024 // {16}RO VIP up general purpose counter
+#define MO_VIPD_GPCNTRL     0x34C030 // {2}WO VIP down general purpose control
+#define MO_VIPU_GPCNTRL     0x34C034 // {2}WO VIP up general purpose control
+#define MO_VIP_DMACNTRL     0x34C040 // {6}RW VIP DMA control
+#define MO_VIP_XFR_STAT     0x34C044 // {1}RO VIP transfer status
+#define MO_VIP_CFG          0x340048 // VIP configuration
+#define MO_VIPU_CNTRL       0x34004C // VIP upstream control #1
+#define MO_VIPD_CNTRL       0x340050 // VIP downstream control #2
+#define MO_VIPD_LNGTH       0x340054 // VIP downstream line length
+#define MO_VIP_BRSTLN       0x340058 // VIP burst length
+#define MO_VIP_INTCNTRL     0x34C05C // VIP Interrupt Control
+#define MO_VIP_XFTERM       0x340060 // VIP transfer terminate
+
+
+/* ---------------------------------------------------------------------- */
+/* misc registers                                                         */
+
+#define MO_M2M_DMA          0x350000 // {64}RWp Mem2Mem DMA Bfr
+#define MO_GP0_IO           0x350010 // {32}RW* GPIOoutput enablesdata I/O
+#define MO_GP1_IO           0x350014 // {32}RW* GPIOoutput enablesdata I/O
+#define MO_GP2_IO           0x350018 // {32}RW* GPIOoutput enablesdata I/O
+#define MO_GP3_IO           0x35001C // {32}RW* GPIO Mode/Ctrloutput enables
+#define MO_GPIO             0x350020 // {32}RW* GPIO I2C Ctrldata I/O
+#define MO_GPOE             0x350024 // {32}RW  GPIO I2C Ctrloutput enables
+#define MO_GP_ISM           0x350028 // {16}WO  GPIO Intr Sens/Pol
+
+#define MO_PLL_B            0x35C008 // {32}RW* PLL Control for ASB bus clks
+#define MO_M2M_CNT          0x35C024 // {32}RW  Mem2Mem DMA Cnt
+#define MO_M2M_XSUM         0x35C028 // {32}RO  M2M XOR-Checksum
+#define MO_CRC              0x35C02C // {16}RW  CRC16 init/result
+#define MO_CRC_D            0x35C030 // {32}WO  CRC16 new data in
+#define MO_TM_CNT_LDW       0x35C034 // {32}RO  Timer : Counter low dword
+#define MO_TM_CNT_UW        0x35C038 // {16}RO  Timer : Counter high word
+#define MO_TM_LMT_LDW       0x35C03C // {32}RW  Timer : Limit low dword
+#define MO_TM_LMT_UW        0x35C040 // {32}RW  Timer : Limit high word
+#define MO_PINMUX_IO        0x35C044 // {8}RW  Pin Mux Control
+#define MO_TSTSEL_IO        0x35C048 // {2}RW  Pin Mux Control
+#define MO_AFECFG_IO        0x35C04C // AFE configuration reg
+#define MO_DDS_IO           0x35C050 // DDS Increment reg
+#define MO_DDSCFG_IO        0x35C054 // DDS Configuration reg
+#define MO_SAMPLE_IO        0x35C058 // IRIn sample reg
+#define MO_SRST_IO          0x35C05C // Output system reset reg
+
+#define MO_INT1_MSK         0x35C060 // DMA RISC interrupt mask
+#define MO_INT1_STAT        0x35C064 // DMA RISC interrupt status
+#define MO_INT1_MSTAT       0x35C068 // DMA RISC interrupt masked status
+
+
+/* ---------------------------------------------------------------------- */
+/* i2c bus registers                                                      */
+
+#define MO_I2C              0x368000 // I2C data/control
+#define MO_I2C_DIV          (0xf<<4)
+#define MO_I2C_SYNC         (1<<3)
+#define MO_I2C_W3B          (1<<2)
+#define MO_I2C_SCL          (1<<1)
+#define MO_I2C_SDA          (1<<0)
+
+
+/* ---------------------------------------------------------------------- */
+/* general purpose host registers                                         */
+/* FIXME: tyops?  s/0x35/0x38/ ??                                         */
+
+#define MO_GPHSTD_DMA       0x350000 // {64}RWp Host downstream
+#define MO_GPHSTU_DMA       0x350008 // {64}RWp Host upstream
+#define MO_GPHSTU_CNTRL     0x380048 // Host upstream control #1
+#define MO_GPHSTD_CNTRL     0x38004C // Host downstream control #2
+#define MO_GPHSTD_LNGTH     0x380050 // Host downstream line length
+#define MO_GPHST_WSC        0x380054 // Host wait state control
+#define MO_GPHST_XFR        0x380058 // Host transfer control
+#define MO_GPHST_WDTH       0x38005C // Host interface width
+#define MO_GPHST_HDSHK      0x380060 // Host peripheral handshake
+#define MO_GPHST_MUX16      0x380064 // Host muxed 16-bit transfer parameters
+#define MO_GPHST_MODE       0x380068 // Host mode select
+
+#define MO_GPHSTD_GPCNT     0x35C020 // Host down general purpose counter
+#define MO_GPHSTU_GPCNT     0x35C024 // Host up general purpose counter
+#define MO_GPHSTD_GPCNTRL   0x38C030 // Host down general purpose control
+#define MO_GPHSTU_GPCNTRL   0x38C034 // Host up general purpose control
+#define MO_GPHST_DMACNTRL   0x38C040 // Host DMA control
+#define MO_GPHST_XFR_STAT   0x38C044 // Host transfer status
+#define MO_GPHST_SOFT_RST   0x38C06C // Host software reset
+
+
+/* ---------------------------------------------------------------------- */
+/* RISC instructions                                                      */
+
+#define RISC_SYNC		 0x80000000
+#define RISC_SYNC_ODD		 0x80000000
+#define RISC_SYNC_EVEN		 0x80000200
+#define RISC_RESYNC		 0x80008000
+#define RISC_RESYNC_ODD		 0x80008000
+#define RISC_RESYNC_EVEN	 0x80008200
+#define RISC_WRITE		 0x10000000
+#define RISC_WRITEC		 0x50000000
+#define RISC_READ		 0x90000000
+#define RISC_READC		 0xA0000000
+#define RISC_JUMP		 0x70000000
+#define RISC_SKIP		 0x20000000
+#define RISC_WRITERM		 0xB0000000
+#define RISC_WRITECM		 0xC0000000
+#define RISC_WRITECR		 0xD0000000
+#define RISC_IMM		 0x00000001
+
+#define RISC_SOL		 0x08000000
+#define RISC_EOL		 0x04000000
+
+#define RISC_IRQ2		 0x02000000
+#define RISC_IRQ1		 0x01000000
+
+#define RISC_CNT_NONE		 0x00000000
+#define RISC_CNT_INC		 0x00010000
+#define RISC_CNT_RSVR		 0x00020000
+#define RISC_CNT_RESET		 0x00030000
+#define RISC_JMP_SRP         	 0x01
+
+
+/* ---------------------------------------------------------------------- */
+/* various constants                                                      */
+
+// DMA
+/* Interrupt mask/status */
+#define PCI_INT_VIDINT		(1 <<  0)
+#define PCI_INT_AUDINT		(1 <<  1)
+#define PCI_INT_TSINT		(1 <<  2)
+#define PCI_INT_VIPINT		(1 <<  3)
+#define PCI_INT_HSTINT		(1 <<  4)
+#define PCI_INT_TM1INT		(1 <<  5)
+#define PCI_INT_SRCDMAINT	(1 <<  6)
+#define PCI_INT_DSTDMAINT	(1 <<  7)
+#define PCI_INT_RISC_RD_BERRINT	(1 << 10)
+#define PCI_INT_RISC_WR_BERRINT	(1 << 11)
+#define PCI_INT_BRDG_BERRINT	(1 << 12)
+#define PCI_INT_SRC_DMA_BERRINT	(1 << 13)
+#define PCI_INT_DST_DMA_BERRINT	(1 << 14)
+#define PCI_INT_IPB_DMA_BERRINT	(1 << 15)
+#define PCI_INT_I2CDONE		(1 << 16)
+#define PCI_INT_I2CRACK		(1 << 17)
+#define PCI_INT_IR_SMPINT	(1 << 18)
+#define PCI_INT_GPIO_INT0	(1 << 19)
+#define PCI_INT_GPIO_INT1	(1 << 20)
+
+#define SEL_BTSC     0x01
+#define SEL_EIAJ     0x02
+#define SEL_A2       0x04
+#define SEL_SAP      0x08
+#define SEL_NICAM    0x10
+#define SEL_FMRADIO  0x20
+
+// AUD_CTL
+#define AUD_INT_DN_RISCI1	(1 <<  0)
+#define AUD_INT_UP_RISCI1	(1 <<  1)
+#define AUD_INT_RDS_DN_RISCI1	(1 <<  2)
+#define AUD_INT_DN_RISCI2	(1 <<  4) /* yes, 3 is skipped */
+#define AUD_INT_UP_RISCI2	(1 <<  5)
+#define AUD_INT_RDS_DN_RISCI2	(1 <<  6)
+#define AUD_INT_DN_SYNC		(1 << 12)
+#define AUD_INT_UP_SYNC		(1 << 13)
+#define AUD_INT_RDS_DN_SYNC	(1 << 14)
+#define AUD_INT_OPC_ERR		(1 << 16)
+#define AUD_INT_BER_IRQ		(1 << 20)
+#define AUD_INT_MCHG_IRQ	(1 << 21)
+
+#define EN_BTSC_FORCE_MONO      0
+#define EN_BTSC_FORCE_STEREO    1
+#define EN_BTSC_FORCE_SAP       2
+#define EN_BTSC_AUTO_STEREO     3
+#define EN_BTSC_AUTO_SAP        4
+
+#define EN_A2_FORCE_MONO1       8
+#define EN_A2_FORCE_MONO2       9
+#define EN_A2_FORCE_STEREO      10
+#define EN_A2_AUTO_MONO2        11
+#define EN_A2_AUTO_STEREO       12
+
+#define EN_EIAJ_FORCE_MONO1     16
+#define EN_EIAJ_FORCE_MONO2     17
+#define EN_EIAJ_FORCE_STEREO    18
+#define EN_EIAJ_AUTO_MONO2      19
+#define EN_EIAJ_AUTO_STEREO     20
+
+#define EN_NICAM_FORCE_MONO1    32
+#define EN_NICAM_FORCE_MONO2    33
+#define EN_NICAM_FORCE_STEREO   34
+#define EN_NICAM_AUTO_MONO2     35
+#define EN_NICAM_AUTO_STEREO    36
+
+#define EN_FMRADIO_FORCE_MONO   24
+#define EN_FMRADIO_FORCE_STEREO 25
+#define EN_FMRADIO_AUTO_STEREO  26
+
+#define EN_NICAM_AUTO_FALLBACK  0x00000040
+#define EN_FMRADIO_EN_RDS       0x00000200
+#define EN_NICAM_TRY_AGAIN_BIT  0x00000400
+#define EN_DAC_ENABLE           0x00001000
+#define EN_I2SOUT_ENABLE        0x00002000
+#define EN_I2SIN_STR2DAC        0x00004000
+#define EN_I2SIN_ENABLE         0x00008000
+
+#define EN_DMTRX_SUMDIFF        (0 << 7)
+#define EN_DMTRX_SUMR           (1 << 7)
+#define EN_DMTRX_LR             (2 << 7)
+#define EN_DMTRX_MONO           (3 << 7)
+#define EN_DMTRX_BYPASS         (1 << 11)
+
+// Video
+#define VID_CAPTURE_CONTROL		0x310180
+
+#define CX23880_CAP_CTL_CAPTURE_VBI_ODD  (1<<3)
+#define CX23880_CAP_CTL_CAPTURE_VBI_EVEN (1<<2)
+#define CX23880_CAP_CTL_CAPTURE_ODD      (1<<1)
+#define CX23880_CAP_CTL_CAPTURE_EVEN     (1<<0)
+
+#define VideoInputMux0		 0x0
+#define VideoInputMux1		 0x1
+#define VideoInputMux2		 0x2
+#define VideoInputMux3		 0x3
+#define VideoInputTuner		 0x0
+#define VideoInputComposite	 0x1
+#define VideoInputSVideo	 0x2
+#define VideoInputOther		 0x3
+
+#define Xtal0		 0x1
+#define Xtal1		 0x2
+#define XtalAuto	 0x3
+
+#define VideoFormatAuto		 0x0
+#define VideoFormatNTSC		 0x1
+#define VideoFormatNTSCJapan	 0x2
+#define VideoFormatNTSC443	 0x3
+#define VideoFormatPAL		 0x4
+#define VideoFormatPALB		 0x4
+#define VideoFormatPALD		 0x4
+#define VideoFormatPALG		 0x4
+#define VideoFormatPALH		 0x4
+#define VideoFormatPALI		 0x4
+#define VideoFormatPALBDGHI	 0x4
+#define VideoFormatPALM		 0x5
+#define VideoFormatPALN		 0x6
+#define VideoFormatPALNC	 0x7
+#define VideoFormatPAL60	 0x8
+#define VideoFormatSECAM	 0x9
+
+#define VideoFormatAuto27MHz		 0x10
+#define VideoFormatNTSC27MHz		 0x11
+#define VideoFormatNTSCJapan27MHz	 0x12
+#define VideoFormatNTSC44327MHz		 0x13
+#define VideoFormatPAL27MHz		 0x14
+#define VideoFormatPALB27MHz		 0x14
+#define VideoFormatPALD27MHz		 0x14
+#define VideoFormatPALG27MHz		 0x14
+#define VideoFormatPALH27MHz		 0x14
+#define VideoFormatPALI27MHz		 0x14
+#define VideoFormatPALBDGHI27MHz	 0x14
+#define VideoFormatPALM27MHz		 0x15
+#define VideoFormatPALN27MHz		 0x16
+#define VideoFormatPALNC27MHz		 0x17
+#define VideoFormatPAL6027MHz		 0x18
+#define VideoFormatSECAM27MHz		 0x19
+
+#define NominalUSECAM	 0x87
+#define NominalVSECAM	 0x85
+#define NominalUNTSC	 0xFE
+#define NominalVNTSC	 0xB4
+
+#define NominalContrast  0xD8
+
+#define HFilterAutoFormat	 0x0
+#define HFilterCIF		 0x1
+#define HFilterQCIF		 0x2
+#define HFilterICON		 0x3
+
+#define VFilter2TapInterpolate  0
+#define VFilter3TapInterpolate  1
+#define VFilter4TapInterpolate  2
+#define VFilter5TapInterpolate  3
+#define VFilter2TapNoInterpolate  4
+#define VFilter3TapNoInterpolate  5
+#define VFilter4TapNoInterpolate  6
+#define VFilter5TapNoInterpolate  7
+
+#define ColorFormatRGB32	 0x0000
+#define ColorFormatRGB24	 0x0011
+#define ColorFormatRGB16	 0x0022
+#define ColorFormatRGB15	 0x0033
+#define ColorFormatYUY2		 0x0044
+#define ColorFormatBTYUV	 0x0055
+#define ColorFormatY8		 0x0066
+#define ColorFormatRGB8		 0x0077
+#define ColorFormatPL422	 0x0088
+#define ColorFormatPL411	 0x0099
+#define ColorFormatYUV12	 0x00AA
+#define ColorFormatYUV9		 0x00BB
+#define ColorFormatRAW		 0x00EE
+#define ColorFormatBSWAP         0x0300
+#define ColorFormatWSWAP         0x0c00
+#define ColorFormatEvenMask      0x050f
+#define ColorFormatOddMask       0x0af0
+#define ColorFormatGamma         0x1000
+
+#define Interlaced		 0x1
+#define NonInterlaced		 0x0
+
+#define FieldEven		 0x1
+#define FieldOdd		 0x0
+
+#define TGReadWriteMode		 0x0
+#define TGEnableMode		 0x1
+
+#define DV_CbAlign		 0x0
+#define DV_Y0Align		 0x1
+#define DV_CrAlign		 0x2
+#define DV_Y1Align		 0x3
+
+#define DVF_Analog		 0x0
+#define DVF_CCIR656		 0x1
+#define DVF_ByteStream		 0x2
+#define DVF_ExtVSYNC		 0x4
+#define DVF_ExtField		 0x5
+
+#define CHANNEL_VID_Y		 0x1
+#define CHANNEL_VID_U		 0x2
+#define CHANNEL_VID_V		 0x3
+#define CHANNEL_VID_VBI		 0x4
+#define CHANNEL_AUD_DN		 0x5
+#define CHANNEL_AUD_UP		 0x6
+#define CHANNEL_AUD_RDS_DN	 0x7
+#define CHANNEL_MPEG_DN		 0x8
+#define CHANNEL_VIP_DN		 0x9
+#define CHANNEL_VIP_UP		 0xA
+#define CHANNEL_HOST_DN		 0xB
+#define CHANNEL_HOST_UP		 0xC
+#define CHANNEL_FIRST		 0x1
+#define CHANNEL_LAST		 0xC
+
+#define GP_COUNT_CONTROL_NONE		 0x0
+#define GP_COUNT_CONTROL_INC		 0x1
+#define GP_COUNT_CONTROL_RESERVED	 0x2
+#define GP_COUNT_CONTROL_RESET		 0x3
+
+#define PLL_PRESCALE_BY_2  2
+#define PLL_PRESCALE_BY_3  3
+#define PLL_PRESCALE_BY_4  4
+#define PLL_PRESCALE_BY_5  5
+
+#define HLNotchFilter4xFsc	 0
+#define HLNotchFilterSquare	 1
+#define HLNotchFilter135NTSC	 2
+#define HLNotchFilter135PAL	 3
+
+#define NTSC_8x_SUB_CARRIER  28.63636E6
+#define PAL_8x_SUB_CARRIER  35.46895E6
+
+// Default analog settings
+#define DEFAULT_HUE_NTSC			0x00
+#define DEFAULT_BRIGHTNESS_NTSC			0x00
+#define DEFAULT_CONTRAST_NTSC			0x39
+#define DEFAULT_SAT_U_NTSC			0x7F
+#define DEFAULT_SAT_V_NTSC			0x5A
+
+typedef enum
+{
+	SOURCE_TUNER = 0,
+	SOURCE_COMPOSITE,
+	SOURCE_SVIDEO,
+	SOURCE_OTHER1,
+	SOURCE_OTHER2,
+	SOURCE_COMPVIASVIDEO,
+	SOURCE_CCIR656
+} VIDEOSOURCETYPE;
+
+#endif /* _CX88_REG_H_ */
diff --git a/drivers/media/pci/cx88/cx88-tvaudio.c b/drivers/media/pci/cx88/cx88-tvaudio.c
new file mode 100644
index 0000000..770ec05
--- /dev/null
+++ b/drivers/media/pci/cx88/cx88-tvaudio.c
@@ -0,0 +1,1059 @@
+/*
+
+    cx88x-audio.c - Conexant CX23880/23881 audio downstream driver driver
+
+     (c) 2001 Michael Eskin, Tom Zakrajsek [Windows version]
+     (c) 2002 Yurij Sysoev <yurij@naturesoft.net>
+     (c) 2003 Gerd Knorr <kraxel@bytesex.org>
+
+    -----------------------------------------------------------------------
+
+    Lot of voodoo here.  Even the data sheet doesn't help to
+    understand what is going on here, the documentation for the audio
+    part of the cx2388x chip is *very* bad.
+
+    Some of this comes from party done linux driver sources I got from
+    [undocumented].
+
+    Some comes from the dscaler sources, one of the dscaler driver guy works
+    for Conexant ...
+
+    -----------------------------------------------------------------------
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the 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/errno.h>
+#include <linux/freezer.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/poll.h>
+#include <linux/signal.h>
+#include <linux/ioport.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/vmalloc.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/kthread.h>
+
+#include "cx88.h"
+
+static unsigned int audio_debug;
+module_param(audio_debug, int, 0644);
+MODULE_PARM_DESC(audio_debug, "enable debug messages [audio]");
+
+static unsigned int always_analog;
+module_param(always_analog,int,0644);
+MODULE_PARM_DESC(always_analog,"force analog audio out");
+
+static unsigned int radio_deemphasis;
+module_param(radio_deemphasis,int,0644);
+MODULE_PARM_DESC(radio_deemphasis, "Radio deemphasis time constant, "
+		 "0=None, 1=50us (elsewhere), 2=75us (USA)");
+
+#define dprintk(fmt, arg...)	if (audio_debug) \
+	printk(KERN_DEBUG "%s/0: " fmt, core->name , ## arg)
+
+/* ----------------------------------------------------------- */
+
+static const char * const aud_ctl_names[64] = {
+	[EN_BTSC_FORCE_MONO] = "BTSC_FORCE_MONO",
+	[EN_BTSC_FORCE_STEREO] = "BTSC_FORCE_STEREO",
+	[EN_BTSC_FORCE_SAP] = "BTSC_FORCE_SAP",
+	[EN_BTSC_AUTO_STEREO] = "BTSC_AUTO_STEREO",
+	[EN_BTSC_AUTO_SAP] = "BTSC_AUTO_SAP",
+	[EN_A2_FORCE_MONO1] = "A2_FORCE_MONO1",
+	[EN_A2_FORCE_MONO2] = "A2_FORCE_MONO2",
+	[EN_A2_FORCE_STEREO] = "A2_FORCE_STEREO",
+	[EN_A2_AUTO_MONO2] = "A2_AUTO_MONO2",
+	[EN_A2_AUTO_STEREO] = "A2_AUTO_STEREO",
+	[EN_EIAJ_FORCE_MONO1] = "EIAJ_FORCE_MONO1",
+	[EN_EIAJ_FORCE_MONO2] = "EIAJ_FORCE_MONO2",
+	[EN_EIAJ_FORCE_STEREO] = "EIAJ_FORCE_STEREO",
+	[EN_EIAJ_AUTO_MONO2] = "EIAJ_AUTO_MONO2",
+	[EN_EIAJ_AUTO_STEREO] = "EIAJ_AUTO_STEREO",
+	[EN_NICAM_FORCE_MONO1] = "NICAM_FORCE_MONO1",
+	[EN_NICAM_FORCE_MONO2] = "NICAM_FORCE_MONO2",
+	[EN_NICAM_FORCE_STEREO] = "NICAM_FORCE_STEREO",
+	[EN_NICAM_AUTO_MONO2] = "NICAM_AUTO_MONO2",
+	[EN_NICAM_AUTO_STEREO] = "NICAM_AUTO_STEREO",
+	[EN_FMRADIO_FORCE_MONO] = "FMRADIO_FORCE_MONO",
+	[EN_FMRADIO_FORCE_STEREO] = "FMRADIO_FORCE_STEREO",
+	[EN_FMRADIO_AUTO_STEREO] = "FMRADIO_AUTO_STEREO",
+};
+
+struct rlist {
+	u32 reg;
+	u32 val;
+};
+
+static void set_audio_registers(struct cx88_core *core, const struct rlist *l)
+{
+	int i;
+
+	for (i = 0; l[i].reg; i++) {
+		switch (l[i].reg) {
+		case AUD_PDF_DDS_CNST_BYTE2:
+		case AUD_PDF_DDS_CNST_BYTE1:
+		case AUD_PDF_DDS_CNST_BYTE0:
+		case AUD_QAM_MODE:
+		case AUD_PHACC_FREQ_8MSB:
+		case AUD_PHACC_FREQ_8LSB:
+			cx_writeb(l[i].reg, l[i].val);
+			break;
+		default:
+			cx_write(l[i].reg, l[i].val);
+			break;
+		}
+	}
+}
+
+static void set_audio_start(struct cx88_core *core, u32 mode)
+{
+	/* mute */
+	cx_write(AUD_VOL_CTL, (1 << 6));
+
+	/* start programming */
+	cx_write(AUD_INIT, mode);
+	cx_write(AUD_INIT_LD, 0x0001);
+	cx_write(AUD_SOFT_RESET, 0x0001);
+}
+
+static void set_audio_finish(struct cx88_core *core, u32 ctl)
+{
+	u32 volume;
+
+	/* restart dma; This avoids buzz in NICAM and is good in others  */
+	cx88_stop_audio_dma(core);
+	cx_write(AUD_RATE_THRES_DMD, 0x000000C0);
+	cx88_start_audio_dma(core);
+
+	if (core->board.mpeg & CX88_MPEG_BLACKBIRD) {
+		cx_write(AUD_I2SINPUTCNTL, 4);
+		cx_write(AUD_BAUDRATE, 1);
+		/* 'pass-thru mode': this enables the i2s output to the mpeg encoder */
+		cx_set(AUD_CTL, EN_I2SOUT_ENABLE);
+		cx_write(AUD_I2SOUTPUTCNTL, 1);
+		cx_write(AUD_I2SCNTL, 0);
+		/* cx_write(AUD_APB_IN_RATE_ADJ, 0); */
+	}
+	if ((always_analog) || (!(core->board.mpeg & CX88_MPEG_BLACKBIRD))) {
+		ctl |= EN_DAC_ENABLE;
+		cx_write(AUD_CTL, ctl);
+	}
+
+	/* finish programming */
+	cx_write(AUD_SOFT_RESET, 0x0000);
+
+	/* unmute */
+	volume = cx_sread(SHADOW_AUD_VOL_CTL);
+	cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, volume);
+
+	core->last_change = jiffies;
+}
+
+/* ----------------------------------------------------------- */
+
+static void set_audio_standard_BTSC(struct cx88_core *core, unsigned int sap,
+				    u32 mode)
+{
+	static const struct rlist btsc[] = {
+		{AUD_AFE_12DB_EN, 0x00000001},
+		{AUD_OUT1_SEL, 0x00000013},
+		{AUD_OUT1_SHIFT, 0x00000000},
+		{AUD_POLY0_DDS_CONSTANT, 0x0012010c},
+		{AUD_DMD_RA_DDS, 0x00c3e7aa},
+		{AUD_DBX_IN_GAIN, 0x00004734},
+		{AUD_DBX_WBE_GAIN, 0x00004640},
+		{AUD_DBX_SE_GAIN, 0x00008d31},
+		{AUD_DCOC_0_SRC, 0x0000001a},
+		{AUD_IIR1_4_SEL, 0x00000021},
+		{AUD_DCOC_PASS_IN, 0x00000003},
+		{AUD_DCOC_0_SHIFT_IN0, 0x0000000a},
+		{AUD_DCOC_0_SHIFT_IN1, 0x00000008},
+		{AUD_DCOC_1_SHIFT_IN0, 0x0000000a},
+		{AUD_DCOC_1_SHIFT_IN1, 0x00000008},
+		{AUD_DN0_FREQ, 0x0000283b},
+		{AUD_DN2_SRC_SEL, 0x00000008},
+		{AUD_DN2_FREQ, 0x00003000},
+		{AUD_DN2_AFC, 0x00000002},
+		{AUD_DN2_SHFT, 0x00000000},
+		{AUD_IIR2_2_SEL, 0x00000020},
+		{AUD_IIR2_2_SHIFT, 0x00000000},
+		{AUD_IIR2_3_SEL, 0x0000001f},
+		{AUD_IIR2_3_SHIFT, 0x00000000},
+		{AUD_CRDC1_SRC_SEL, 0x000003ce},
+		{AUD_CRDC1_SHIFT, 0x00000000},
+		{AUD_CORDIC_SHIFT_1, 0x00000007},
+		{AUD_DCOC_1_SRC, 0x0000001b},
+		{AUD_DCOC1_SHIFT, 0x00000000},
+		{AUD_RDSI_SEL, 0x00000008},
+		{AUD_RDSQ_SEL, 0x00000008},
+		{AUD_RDSI_SHIFT, 0x00000000},
+		{AUD_RDSQ_SHIFT, 0x00000000},
+		{AUD_POLYPH80SCALEFAC, 0x00000003},
+		{ /* end of list */ },
+	};
+	static const struct rlist btsc_sap[] = {
+		{AUD_AFE_12DB_EN, 0x00000001},
+		{AUD_DBX_IN_GAIN, 0x00007200},
+		{AUD_DBX_WBE_GAIN, 0x00006200},
+		{AUD_DBX_SE_GAIN, 0x00006200},
+		{AUD_IIR1_1_SEL, 0x00000000},
+		{AUD_IIR1_3_SEL, 0x00000001},
+		{AUD_DN1_SRC_SEL, 0x00000007},
+		{AUD_IIR1_4_SHIFT, 0x00000006},
+		{AUD_IIR2_1_SHIFT, 0x00000000},
+		{AUD_IIR2_2_SHIFT, 0x00000000},
+		{AUD_IIR3_0_SHIFT, 0x00000000},
+		{AUD_IIR3_1_SHIFT, 0x00000000},
+		{AUD_IIR3_0_SEL, 0x0000000d},
+		{AUD_IIR3_1_SEL, 0x0000000e},
+		{AUD_DEEMPH1_SRC_SEL, 0x00000014},
+		{AUD_DEEMPH1_SHIFT, 0x00000000},
+		{AUD_DEEMPH1_G0, 0x00004000},
+		{AUD_DEEMPH1_A0, 0x00000000},
+		{AUD_DEEMPH1_B0, 0x00000000},
+		{AUD_DEEMPH1_A1, 0x00000000},
+		{AUD_DEEMPH1_B1, 0x00000000},
+		{AUD_OUT0_SEL, 0x0000003f},
+		{AUD_OUT1_SEL, 0x0000003f},
+		{AUD_DN1_AFC, 0x00000002},
+		{AUD_DCOC_0_SHIFT_IN0, 0x0000000a},
+		{AUD_DCOC_0_SHIFT_IN1, 0x00000008},
+		{AUD_DCOC_1_SHIFT_IN0, 0x0000000a},
+		{AUD_DCOC_1_SHIFT_IN1, 0x00000008},
+		{AUD_IIR1_0_SEL, 0x0000001d},
+		{AUD_IIR1_2_SEL, 0x0000001e},
+		{AUD_IIR2_1_SEL, 0x00000002},
+		{AUD_IIR2_2_SEL, 0x00000004},
+		{AUD_IIR3_2_SEL, 0x0000000f},
+		{AUD_DCOC2_SHIFT, 0x00000001},
+		{AUD_IIR3_2_SHIFT, 0x00000001},
+		{AUD_DEEMPH0_SRC_SEL, 0x00000014},
+		{AUD_CORDIC_SHIFT_1, 0x00000006},
+		{AUD_POLY0_DDS_CONSTANT, 0x000e4db2},
+		{AUD_DMD_RA_DDS, 0x00f696e6},
+		{AUD_IIR2_3_SEL, 0x00000025},
+		{AUD_IIR1_4_SEL, 0x00000021},
+		{AUD_DN1_FREQ, 0x0000c965},
+		{AUD_DCOC_PASS_IN, 0x00000003},
+		{AUD_DCOC_0_SRC, 0x0000001a},
+		{AUD_DCOC_1_SRC, 0x0000001b},
+		{AUD_DCOC1_SHIFT, 0x00000000},
+		{AUD_RDSI_SEL, 0x00000009},
+		{AUD_RDSQ_SEL, 0x00000009},
+		{AUD_RDSI_SHIFT, 0x00000000},
+		{AUD_RDSQ_SHIFT, 0x00000000},
+		{AUD_POLYPH80SCALEFAC, 0x00000003},
+		{ /* end of list */ },
+	};
+
+	mode |= EN_FMRADIO_EN_RDS;
+
+	if (sap) {
+		dprintk("%s SAP (status: unknown)\n", __func__);
+		set_audio_start(core, SEL_SAP);
+		set_audio_registers(core, btsc_sap);
+		set_audio_finish(core, mode);
+	} else {
+		dprintk("%s (status: known-good)\n", __func__);
+		set_audio_start(core, SEL_BTSC);
+		set_audio_registers(core, btsc);
+		set_audio_finish(core, mode);
+	}
+}
+
+static void set_audio_standard_NICAM(struct cx88_core *core, u32 mode)
+{
+	static const struct rlist nicam_l[] = {
+		{AUD_AFE_12DB_EN, 0x00000001},
+		{AUD_RATE_ADJ1, 0x00000060},
+		{AUD_RATE_ADJ2, 0x000000F9},
+		{AUD_RATE_ADJ3, 0x000001CC},
+		{AUD_RATE_ADJ4, 0x000002B3},
+		{AUD_RATE_ADJ5, 0x00000726},
+		{AUD_DEEMPHDENOM1_R, 0x0000F3D0},
+		{AUD_DEEMPHDENOM2_R, 0x00000000},
+		{AUD_ERRLOGPERIOD_R, 0x00000064},
+		{AUD_ERRINTRPTTHSHLD1_R, 0x00000FFF},
+		{AUD_ERRINTRPTTHSHLD2_R, 0x0000001F},
+		{AUD_ERRINTRPTTHSHLD3_R, 0x0000000F},
+		{AUD_POLYPH80SCALEFAC, 0x00000003},
+		{AUD_DMD_RA_DDS, 0x00C00000},
+		{AUD_PLL_INT, 0x0000001E},
+		{AUD_PLL_DDS, 0x00000000},
+		{AUD_PLL_FRAC, 0x0000E542},
+		{AUD_START_TIMER, 0x00000000},
+		{AUD_DEEMPHNUMER1_R, 0x000353DE},
+		{AUD_DEEMPHNUMER2_R, 0x000001B1},
+		{AUD_PDF_DDS_CNST_BYTE2, 0x06},
+		{AUD_PDF_DDS_CNST_BYTE1, 0x82},
+		{AUD_PDF_DDS_CNST_BYTE0, 0x12},
+		{AUD_QAM_MODE, 0x05},
+		{AUD_PHACC_FREQ_8MSB, 0x34},
+		{AUD_PHACC_FREQ_8LSB, 0x4C},
+		{AUD_DEEMPHGAIN_R, 0x00006680},
+		{AUD_RATE_THRES_DMD, 0x000000C0},
+		{ /* end of list */ },
+	};
+
+	static const struct rlist nicam_bgdki_common[] = {
+		{AUD_AFE_12DB_EN, 0x00000001},
+		{AUD_RATE_ADJ1, 0x00000010},
+		{AUD_RATE_ADJ2, 0x00000040},
+		{AUD_RATE_ADJ3, 0x00000100},
+		{AUD_RATE_ADJ4, 0x00000400},
+		{AUD_RATE_ADJ5, 0x00001000},
+		{AUD_ERRLOGPERIOD_R, 0x00000fff},
+		{AUD_ERRINTRPTTHSHLD1_R, 0x000003ff},
+		{AUD_ERRINTRPTTHSHLD2_R, 0x000000ff},
+		{AUD_ERRINTRPTTHSHLD3_R, 0x0000003f},
+		{AUD_POLYPH80SCALEFAC, 0x00000003},
+		{AUD_DEEMPHGAIN_R, 0x000023c2},
+		{AUD_DEEMPHNUMER1_R, 0x0002a7bc},
+		{AUD_DEEMPHNUMER2_R, 0x0003023e},
+		{AUD_DEEMPHDENOM1_R, 0x0000f3d0},
+		{AUD_DEEMPHDENOM2_R, 0x00000000},
+		{AUD_PDF_DDS_CNST_BYTE2, 0x06},
+		{AUD_PDF_DDS_CNST_BYTE1, 0x82},
+		{AUD_QAM_MODE, 0x05},
+		{ /* end of list */ },
+	};
+
+	static const struct rlist nicam_i[] = {
+		{AUD_PDF_DDS_CNST_BYTE0, 0x12},
+		{AUD_PHACC_FREQ_8MSB, 0x3a},
+		{AUD_PHACC_FREQ_8LSB, 0x93},
+		{ /* end of list */ },
+	};
+
+	static const struct rlist nicam_default[] = {
+		{AUD_PDF_DDS_CNST_BYTE0, 0x16},
+		{AUD_PHACC_FREQ_8MSB, 0x34},
+		{AUD_PHACC_FREQ_8LSB, 0x4c},
+		{ /* end of list */ },
+	};
+
+	set_audio_start(core,SEL_NICAM);
+	switch (core->tvaudio) {
+	case WW_L:
+		dprintk("%s SECAM-L NICAM (status: devel)\n", __func__);
+		set_audio_registers(core, nicam_l);
+		break;
+	case WW_I:
+		dprintk("%s PAL-I NICAM (status: known-good)\n", __func__);
+		set_audio_registers(core, nicam_bgdki_common);
+		set_audio_registers(core, nicam_i);
+		break;
+	case WW_NONE:
+	case WW_BTSC:
+	case WW_BG:
+	case WW_DK:
+	case WW_EIAJ:
+	case WW_I2SPT:
+	case WW_FM:
+	case WW_I2SADC:
+	case WW_M:
+		dprintk("%s PAL-BGDK NICAM (status: known-good)\n", __func__);
+		set_audio_registers(core, nicam_bgdki_common);
+		set_audio_registers(core, nicam_default);
+		break;
+	};
+
+	mode |= EN_DMTRX_LR | EN_DMTRX_BYPASS;
+	set_audio_finish(core, mode);
+}
+
+static void set_audio_standard_A2(struct cx88_core *core, u32 mode)
+{
+	static const struct rlist a2_bgdk_common[] = {
+		{AUD_ERRLOGPERIOD_R, 0x00000064},
+		{AUD_ERRINTRPTTHSHLD1_R, 0x00000fff},
+		{AUD_ERRINTRPTTHSHLD2_R, 0x0000001f},
+		{AUD_ERRINTRPTTHSHLD3_R, 0x0000000f},
+		{AUD_PDF_DDS_CNST_BYTE2, 0x06},
+		{AUD_PDF_DDS_CNST_BYTE1, 0x82},
+		{AUD_PDF_DDS_CNST_BYTE0, 0x12},
+		{AUD_QAM_MODE, 0x05},
+		{AUD_PHACC_FREQ_8MSB, 0x34},
+		{AUD_PHACC_FREQ_8LSB, 0x4c},
+		{AUD_RATE_ADJ1, 0x00000100},
+		{AUD_RATE_ADJ2, 0x00000200},
+		{AUD_RATE_ADJ3, 0x00000300},
+		{AUD_RATE_ADJ4, 0x00000400},
+		{AUD_RATE_ADJ5, 0x00000500},
+		{AUD_THR_FR, 0x00000000},
+		{AAGC_HYST, 0x0000001a},
+		{AUD_PILOT_BQD_1_K0, 0x0000755b},
+		{AUD_PILOT_BQD_1_K1, 0x00551340},
+		{AUD_PILOT_BQD_1_K2, 0x006d30be},
+		{AUD_PILOT_BQD_1_K3, 0xffd394af},
+		{AUD_PILOT_BQD_1_K4, 0x00400000},
+		{AUD_PILOT_BQD_2_K0, 0x00040000},
+		{AUD_PILOT_BQD_2_K1, 0x002a4841},
+		{AUD_PILOT_BQD_2_K2, 0x00400000},
+		{AUD_PILOT_BQD_2_K3, 0x00000000},
+		{AUD_PILOT_BQD_2_K4, 0x00000000},
+		{AUD_MODE_CHG_TIMER, 0x00000040},
+		{AUD_AFE_12DB_EN, 0x00000001},
+		{AUD_CORDIC_SHIFT_0, 0x00000007},
+		{AUD_CORDIC_SHIFT_1, 0x00000007},
+		{AUD_DEEMPH0_G0, 0x00000380},
+		{AUD_DEEMPH1_G0, 0x00000380},
+		{AUD_DCOC_0_SRC, 0x0000001a},
+		{AUD_DCOC0_SHIFT, 0x00000000},
+		{AUD_DCOC_0_SHIFT_IN0, 0x0000000a},
+		{AUD_DCOC_0_SHIFT_IN1, 0x00000008},
+		{AUD_DCOC_PASS_IN, 0x00000003},
+		{AUD_IIR3_0_SEL, 0x00000021},
+		{AUD_DN2_AFC, 0x00000002},
+		{AUD_DCOC_1_SRC, 0x0000001b},
+		{AUD_DCOC1_SHIFT, 0x00000000},
+		{AUD_DCOC_1_SHIFT_IN0, 0x0000000a},
+		{AUD_DCOC_1_SHIFT_IN1, 0x00000008},
+		{AUD_IIR3_1_SEL, 0x00000023},
+		{AUD_RDSI_SEL, 0x00000017},
+		{AUD_RDSI_SHIFT, 0x00000000},
+		{AUD_RDSQ_SEL, 0x00000017},
+		{AUD_RDSQ_SHIFT, 0x00000000},
+		{AUD_PLL_INT, 0x0000001e},
+		{AUD_PLL_DDS, 0x00000000},
+		{AUD_PLL_FRAC, 0x0000e542},
+		{AUD_POLYPH80SCALEFAC, 0x00000001},
+		{AUD_START_TIMER, 0x00000000},
+		{ /* end of list */ },
+	};
+
+	static const struct rlist a2_bg[] = {
+		{AUD_DMD_RA_DDS, 0x002a4f2f},
+		{AUD_C1_UP_THR, 0x00007000},
+		{AUD_C1_LO_THR, 0x00005400},
+		{AUD_C2_UP_THR, 0x00005400},
+		{AUD_C2_LO_THR, 0x00003000},
+		{ /* end of list */ },
+	};
+
+	static const struct rlist a2_dk[] = {
+		{AUD_DMD_RA_DDS, 0x002a4f2f},
+		{AUD_C1_UP_THR, 0x00007000},
+		{AUD_C1_LO_THR, 0x00005400},
+		{AUD_C2_UP_THR, 0x00005400},
+		{AUD_C2_LO_THR, 0x00003000},
+		{AUD_DN0_FREQ, 0x00003a1c},
+		{AUD_DN2_FREQ, 0x0000d2e0},
+		{ /* end of list */ },
+	};
+
+	static const struct rlist a1_i[] = {
+		{AUD_ERRLOGPERIOD_R, 0x00000064},
+		{AUD_ERRINTRPTTHSHLD1_R, 0x00000fff},
+		{AUD_ERRINTRPTTHSHLD2_R, 0x0000001f},
+		{AUD_ERRINTRPTTHSHLD3_R, 0x0000000f},
+		{AUD_PDF_DDS_CNST_BYTE2, 0x06},
+		{AUD_PDF_DDS_CNST_BYTE1, 0x82},
+		{AUD_PDF_DDS_CNST_BYTE0, 0x12},
+		{AUD_QAM_MODE, 0x05},
+		{AUD_PHACC_FREQ_8MSB, 0x3a},
+		{AUD_PHACC_FREQ_8LSB, 0x93},
+		{AUD_DMD_RA_DDS, 0x002a4f2f},
+		{AUD_PLL_INT, 0x0000001e},
+		{AUD_PLL_DDS, 0x00000004},
+		{AUD_PLL_FRAC, 0x0000e542},
+		{AUD_RATE_ADJ1, 0x00000100},
+		{AUD_RATE_ADJ2, 0x00000200},
+		{AUD_RATE_ADJ3, 0x00000300},
+		{AUD_RATE_ADJ4, 0x00000400},
+		{AUD_RATE_ADJ5, 0x00000500},
+		{AUD_THR_FR, 0x00000000},
+		{AUD_PILOT_BQD_1_K0, 0x0000755b},
+		{AUD_PILOT_BQD_1_K1, 0x00551340},
+		{AUD_PILOT_BQD_1_K2, 0x006d30be},
+		{AUD_PILOT_BQD_1_K3, 0xffd394af},
+		{AUD_PILOT_BQD_1_K4, 0x00400000},
+		{AUD_PILOT_BQD_2_K0, 0x00040000},
+		{AUD_PILOT_BQD_2_K1, 0x002a4841},
+		{AUD_PILOT_BQD_2_K2, 0x00400000},
+		{AUD_PILOT_BQD_2_K3, 0x00000000},
+		{AUD_PILOT_BQD_2_K4, 0x00000000},
+		{AUD_MODE_CHG_TIMER, 0x00000060},
+		{AUD_AFE_12DB_EN, 0x00000001},
+		{AAGC_HYST, 0x0000000a},
+		{AUD_CORDIC_SHIFT_0, 0x00000007},
+		{AUD_CORDIC_SHIFT_1, 0x00000007},
+		{AUD_C1_UP_THR, 0x00007000},
+		{AUD_C1_LO_THR, 0x00005400},
+		{AUD_C2_UP_THR, 0x00005400},
+		{AUD_C2_LO_THR, 0x00003000},
+		{AUD_DCOC_0_SRC, 0x0000001a},
+		{AUD_DCOC0_SHIFT, 0x00000000},
+		{AUD_DCOC_0_SHIFT_IN0, 0x0000000a},
+		{AUD_DCOC_0_SHIFT_IN1, 0x00000008},
+		{AUD_DCOC_PASS_IN, 0x00000003},
+		{AUD_IIR3_0_SEL, 0x00000021},
+		{AUD_DN2_AFC, 0x00000002},
+		{AUD_DCOC_1_SRC, 0x0000001b},
+		{AUD_DCOC1_SHIFT, 0x00000000},
+		{AUD_DCOC_1_SHIFT_IN0, 0x0000000a},
+		{AUD_DCOC_1_SHIFT_IN1, 0x00000008},
+		{AUD_IIR3_1_SEL, 0x00000023},
+		{AUD_DN0_FREQ, 0x000035a3},
+		{AUD_DN2_FREQ, 0x000029c7},
+		{AUD_CRDC0_SRC_SEL, 0x00000511},
+		{AUD_IIR1_0_SEL, 0x00000001},
+		{AUD_IIR1_1_SEL, 0x00000000},
+		{AUD_IIR3_2_SEL, 0x00000003},
+		{AUD_IIR3_2_SHIFT, 0x00000000},
+		{AUD_IIR3_0_SEL, 0x00000002},
+		{AUD_IIR2_0_SEL, 0x00000021},
+		{AUD_IIR2_0_SHIFT, 0x00000002},
+		{AUD_DEEMPH0_SRC_SEL, 0x0000000b},
+		{AUD_DEEMPH1_SRC_SEL, 0x0000000b},
+		{AUD_POLYPH80SCALEFAC, 0x00000001},
+		{AUD_START_TIMER, 0x00000000},
+		{ /* end of list */ },
+	};
+
+	static const struct rlist am_l[] = {
+		{AUD_ERRLOGPERIOD_R, 0x00000064},
+		{AUD_ERRINTRPTTHSHLD1_R, 0x00000FFF},
+		{AUD_ERRINTRPTTHSHLD2_R, 0x0000001F},
+		{AUD_ERRINTRPTTHSHLD3_R, 0x0000000F},
+		{AUD_PDF_DDS_CNST_BYTE2, 0x48},
+		{AUD_PDF_DDS_CNST_BYTE1, 0x3D},
+		{AUD_QAM_MODE, 0x00},
+		{AUD_PDF_DDS_CNST_BYTE0, 0xf5},
+		{AUD_PHACC_FREQ_8MSB, 0x3a},
+		{AUD_PHACC_FREQ_8LSB, 0x4a},
+		{AUD_DEEMPHGAIN_R, 0x00006680},
+		{AUD_DEEMPHNUMER1_R, 0x000353DE},
+		{AUD_DEEMPHNUMER2_R, 0x000001B1},
+		{AUD_DEEMPHDENOM1_R, 0x0000F3D0},
+		{AUD_DEEMPHDENOM2_R, 0x00000000},
+		{AUD_FM_MODE_ENABLE, 0x00000007},
+		{AUD_POLYPH80SCALEFAC, 0x00000003},
+		{AUD_AFE_12DB_EN, 0x00000001},
+		{AAGC_GAIN, 0x00000000},
+		{AAGC_HYST, 0x00000018},
+		{AAGC_DEF, 0x00000020},
+		{AUD_DN0_FREQ, 0x00000000},
+		{AUD_POLY0_DDS_CONSTANT, 0x000E4DB2},
+		{AUD_DCOC_0_SRC, 0x00000021},
+		{AUD_IIR1_0_SEL, 0x00000000},
+		{AUD_IIR1_0_SHIFT, 0x00000007},
+		{AUD_IIR1_1_SEL, 0x00000002},
+		{AUD_IIR1_1_SHIFT, 0x00000000},
+		{AUD_DCOC_1_SRC, 0x00000003},
+		{AUD_DCOC1_SHIFT, 0x00000000},
+		{AUD_DCOC_PASS_IN, 0x00000000},
+		{AUD_IIR1_2_SEL, 0x00000023},
+		{AUD_IIR1_2_SHIFT, 0x00000000},
+		{AUD_IIR1_3_SEL, 0x00000004},
+		{AUD_IIR1_3_SHIFT, 0x00000007},
+		{AUD_IIR1_4_SEL, 0x00000005},
+		{AUD_IIR1_4_SHIFT, 0x00000007},
+		{AUD_IIR3_0_SEL, 0x00000007},
+		{AUD_IIR3_0_SHIFT, 0x00000000},
+		{AUD_DEEMPH0_SRC_SEL, 0x00000011},
+		{AUD_DEEMPH0_SHIFT, 0x00000000},
+		{AUD_DEEMPH0_G0, 0x00007000},
+		{AUD_DEEMPH0_A0, 0x00000000},
+		{AUD_DEEMPH0_B0, 0x00000000},
+		{AUD_DEEMPH0_A1, 0x00000000},
+		{AUD_DEEMPH0_B1, 0x00000000},
+		{AUD_DEEMPH1_SRC_SEL, 0x00000011},
+		{AUD_DEEMPH1_SHIFT, 0x00000000},
+		{AUD_DEEMPH1_G0, 0x00007000},
+		{AUD_DEEMPH1_A0, 0x00000000},
+		{AUD_DEEMPH1_B0, 0x00000000},
+		{AUD_DEEMPH1_A1, 0x00000000},
+		{AUD_DEEMPH1_B1, 0x00000000},
+		{AUD_OUT0_SEL, 0x0000003F},
+		{AUD_OUT1_SEL, 0x0000003F},
+		{AUD_DMD_RA_DDS, 0x00F5C285},
+		{AUD_PLL_INT, 0x0000001E},
+		{AUD_PLL_DDS, 0x00000000},
+		{AUD_PLL_FRAC, 0x0000E542},
+		{AUD_RATE_ADJ1, 0x00000100},
+		{AUD_RATE_ADJ2, 0x00000200},
+		{AUD_RATE_ADJ3, 0x00000300},
+		{AUD_RATE_ADJ4, 0x00000400},
+		{AUD_RATE_ADJ5, 0x00000500},
+		{AUD_RATE_THRES_DMD, 0x000000C0},
+		{ /* end of list */ },
+	};
+
+	static const struct rlist a2_deemph50[] = {
+		{AUD_DEEMPH0_G0, 0x00000380},
+		{AUD_DEEMPH1_G0, 0x00000380},
+		{AUD_DEEMPHGAIN_R, 0x000011e1},
+		{AUD_DEEMPHNUMER1_R, 0x0002a7bc},
+		{AUD_DEEMPHNUMER2_R, 0x0003023c},
+		{ /* end of list */ },
+	};
+
+	set_audio_start(core, SEL_A2);
+	switch (core->tvaudio) {
+	case WW_BG:
+		dprintk("%s PAL-BG A1/2 (status: known-good)\n", __func__);
+		set_audio_registers(core, a2_bgdk_common);
+		set_audio_registers(core, a2_bg);
+		set_audio_registers(core, a2_deemph50);
+		break;
+	case WW_DK:
+		dprintk("%s PAL-DK A1/2 (status: known-good)\n", __func__);
+		set_audio_registers(core, a2_bgdk_common);
+		set_audio_registers(core, a2_dk);
+		set_audio_registers(core, a2_deemph50);
+		break;
+	case WW_I:
+		dprintk("%s PAL-I A1 (status: known-good)\n", __func__);
+		set_audio_registers(core, a1_i);
+		set_audio_registers(core, a2_deemph50);
+		break;
+	case WW_L:
+		dprintk("%s AM-L (status: devel)\n", __func__);
+		set_audio_registers(core, am_l);
+		break;
+	case WW_NONE:
+	case WW_BTSC:
+	case WW_EIAJ:
+	case WW_I2SPT:
+	case WW_FM:
+	case WW_I2SADC:
+	case WW_M:
+		dprintk("%s Warning: wrong value\n", __func__);
+		return;
+		break;
+	};
+
+	mode |= EN_FMRADIO_EN_RDS | EN_DMTRX_SUMDIFF;
+	set_audio_finish(core, mode);
+}
+
+static void set_audio_standard_EIAJ(struct cx88_core *core)
+{
+	static const struct rlist eiaj[] = {
+		/* TODO: eiaj register settings are not there yet ... */
+
+		{ /* end of list */ },
+	};
+	dprintk("%s (status: unknown)\n", __func__);
+
+	set_audio_start(core, SEL_EIAJ);
+	set_audio_registers(core, eiaj);
+	set_audio_finish(core, EN_EIAJ_AUTO_STEREO);
+}
+
+static void set_audio_standard_FM(struct cx88_core *core,
+				  enum cx88_deemph_type deemph)
+{
+	static const struct rlist fm_deemph_50[] = {
+		{AUD_DEEMPH0_G0, 0x0C45},
+		{AUD_DEEMPH0_A0, 0x6262},
+		{AUD_DEEMPH0_B0, 0x1C29},
+		{AUD_DEEMPH0_A1, 0x3FC66},
+		{AUD_DEEMPH0_B1, 0x399A},
+
+		{AUD_DEEMPH1_G0, 0x0D80},
+		{AUD_DEEMPH1_A0, 0x6262},
+		{AUD_DEEMPH1_B0, 0x1C29},
+		{AUD_DEEMPH1_A1, 0x3FC66},
+		{AUD_DEEMPH1_B1, 0x399A},
+
+		{AUD_POLYPH80SCALEFAC, 0x0003},
+		{ /* end of list */ },
+	};
+	static const struct rlist fm_deemph_75[] = {
+		{AUD_DEEMPH0_G0, 0x091B},
+		{AUD_DEEMPH0_A0, 0x6B68},
+		{AUD_DEEMPH0_B0, 0x11EC},
+		{AUD_DEEMPH0_A1, 0x3FC66},
+		{AUD_DEEMPH0_B1, 0x399A},
+
+		{AUD_DEEMPH1_G0, 0x0AA0},
+		{AUD_DEEMPH1_A0, 0x6B68},
+		{AUD_DEEMPH1_B0, 0x11EC},
+		{AUD_DEEMPH1_A1, 0x3FC66},
+		{AUD_DEEMPH1_B1, 0x399A},
+
+		{AUD_POLYPH80SCALEFAC, 0x0003},
+		{ /* end of list */ },
+	};
+
+	/* It is enough to leave default values? */
+	/* No, it's not!  The deemphasis registers are reset to the 75us
+	 * values by default.  Analyzing the spectrum of the decoded audio
+	 * reveals that "no deemphasis" is the same as 75 us, while the 50 us
+	 * setting results in less deemphasis.  */
+	static const struct rlist fm_no_deemph[] = {
+
+		{AUD_POLYPH80SCALEFAC, 0x0003},
+		{ /* end of list */ },
+	};
+
+	dprintk("%s (status: unknown)\n", __func__);
+	set_audio_start(core, SEL_FMRADIO);
+
+	switch (deemph) {
+	default:
+	case FM_NO_DEEMPH:
+		set_audio_registers(core, fm_no_deemph);
+		break;
+
+	case FM_DEEMPH_50:
+		set_audio_registers(core, fm_deemph_50);
+		break;
+
+	case FM_DEEMPH_75:
+		set_audio_registers(core, fm_deemph_75);
+		break;
+	}
+
+	set_audio_finish(core, EN_FMRADIO_AUTO_STEREO);
+}
+
+/* ----------------------------------------------------------- */
+
+static int cx88_detect_nicam(struct cx88_core *core)
+{
+	int i, j = 0;
+
+	dprintk("start nicam autodetect.\n");
+
+	for (i = 0; i < 6; i++) {
+		/* if bit1=1 then nicam is detected */
+		j += ((cx_read(AUD_NICAM_STATUS2) & 0x02) >> 1);
+
+		if (j == 1) {
+			dprintk("nicam is detected.\n");
+			return 1;
+		}
+
+		/* wait a little bit for next reading status */
+		msleep(10);
+	}
+
+	dprintk("nicam is not detected.\n");
+	return 0;
+}
+
+void cx88_set_tvaudio(struct cx88_core *core)
+{
+	switch (core->tvaudio) {
+	case WW_BTSC:
+		set_audio_standard_BTSC(core, 0, EN_BTSC_AUTO_STEREO);
+		break;
+	case WW_BG:
+	case WW_DK:
+	case WW_M:
+	case WW_I:
+	case WW_L:
+		/* prepare all dsp registers */
+		set_audio_standard_A2(core, EN_A2_FORCE_MONO1);
+
+		/* set nicam mode - otherwise
+		   AUD_NICAM_STATUS2 contains wrong values */
+		set_audio_standard_NICAM(core, EN_NICAM_AUTO_STEREO);
+		if (0 == cx88_detect_nicam(core)) {
+			/* fall back to fm / am mono */
+			set_audio_standard_A2(core, EN_A2_FORCE_MONO1);
+			core->audiomode_current = V4L2_TUNER_MODE_MONO;
+			core->use_nicam = 0;
+		} else {
+			core->use_nicam = 1;
+		}
+		break;
+	case WW_EIAJ:
+		set_audio_standard_EIAJ(core);
+		break;
+	case WW_FM:
+		set_audio_standard_FM(core, radio_deemphasis);
+		break;
+	case WW_I2SADC:
+		set_audio_start(core, 0x01);
+		/*
+		 * Slave/Philips/Autobaud
+		 * NB on Nova-S bit1 NPhilipsSony appears to be inverted:
+		 *	0= Sony, 1=Philips
+		 */
+		cx_write(AUD_I2SINPUTCNTL, core->board.i2sinputcntl);
+		/* Switch to "I2S ADC mode" */
+		cx_write(AUD_I2SCNTL, 0x1);
+		set_audio_finish(core, EN_I2SIN_ENABLE);
+		break;
+	case WW_NONE:
+	case WW_I2SPT:
+		printk("%s/0: unknown tv audio mode [%d]\n",
+		       core->name, core->tvaudio);
+		break;
+	}
+	return;
+}
+
+void cx88_newstation(struct cx88_core *core)
+{
+	core->audiomode_manual = UNSET;
+	core->last_change = jiffies;
+}
+
+void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t)
+{
+	static const char * const m[] = { "stereo", "dual mono", "mono", "sap" };
+	static const char * const p[] = { "no pilot", "pilot c1", "pilot c2", "?" };
+	u32 reg, mode, pilot;
+
+	reg = cx_read(AUD_STATUS);
+	mode = reg & 0x03;
+	pilot = (reg >> 2) & 0x03;
+
+	if (core->astat != reg)
+		dprintk("AUD_STATUS: 0x%x [%s/%s] ctl=%s\n",
+			reg, m[mode], p[pilot],
+			aud_ctl_names[cx_read(AUD_CTL) & 63]);
+	core->astat = reg;
+
+	t->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_SAP |
+	    V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2;
+	t->rxsubchans = UNSET;
+	t->audmode = V4L2_TUNER_MODE_MONO;
+
+	switch (mode) {
+	case 0:
+		t->audmode = V4L2_TUNER_MODE_STEREO;
+		break;
+	case 1:
+		t->audmode = V4L2_TUNER_MODE_LANG2;
+		break;
+	case 2:
+		t->audmode = V4L2_TUNER_MODE_MONO;
+		break;
+	case 3:
+		t->audmode = V4L2_TUNER_MODE_SAP;
+		break;
+	}
+
+	switch (core->tvaudio) {
+	case WW_BTSC:
+	case WW_BG:
+	case WW_DK:
+	case WW_M:
+	case WW_EIAJ:
+		if (!core->use_nicam) {
+			t->rxsubchans = cx88_dsp_detect_stereo_sap(core);
+			break;
+		}
+		break;
+	case WW_NONE:
+	case WW_I:
+	case WW_L:
+	case WW_I2SPT:
+	case WW_FM:
+	case WW_I2SADC:
+		/* nothing */
+		break;
+	}
+
+	/* If software stereo detection is not supported... */
+	if (UNSET == t->rxsubchans) {
+		t->rxsubchans = V4L2_TUNER_SUB_MONO;
+		/* If the hardware itself detected stereo, also return
+		   stereo as an available subchannel */
+		if (V4L2_TUNER_MODE_STEREO == t->audmode)
+			t->rxsubchans |= V4L2_TUNER_SUB_STEREO;
+	}
+	return;
+}
+
+void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual)
+{
+	u32 ctl = UNSET;
+	u32 mask = UNSET;
+
+	if (manual) {
+		core->audiomode_manual = mode;
+	} else {
+		if (UNSET != core->audiomode_manual)
+			return;
+	}
+	core->audiomode_current = mode;
+
+	switch (core->tvaudio) {
+	case WW_BTSC:
+		switch (mode) {
+		case V4L2_TUNER_MODE_MONO:
+			set_audio_standard_BTSC(core, 0, EN_BTSC_FORCE_MONO);
+			break;
+		case V4L2_TUNER_MODE_LANG1:
+			set_audio_standard_BTSC(core, 0, EN_BTSC_AUTO_STEREO);
+			break;
+		case V4L2_TUNER_MODE_LANG2:
+			set_audio_standard_BTSC(core, 1, EN_BTSC_FORCE_SAP);
+			break;
+		case V4L2_TUNER_MODE_STEREO:
+		case V4L2_TUNER_MODE_LANG1_LANG2:
+			set_audio_standard_BTSC(core, 0, EN_BTSC_FORCE_STEREO);
+			break;
+		}
+		break;
+	case WW_BG:
+	case WW_DK:
+	case WW_M:
+	case WW_I:
+	case WW_L:
+		if (1 == core->use_nicam) {
+			switch (mode) {
+			case V4L2_TUNER_MODE_MONO:
+			case V4L2_TUNER_MODE_LANG1:
+				set_audio_standard_NICAM(core,
+							 EN_NICAM_FORCE_MONO1);
+				break;
+			case V4L2_TUNER_MODE_LANG2:
+				set_audio_standard_NICAM(core,
+							 EN_NICAM_FORCE_MONO2);
+				break;
+			case V4L2_TUNER_MODE_STEREO:
+			case V4L2_TUNER_MODE_LANG1_LANG2:
+				set_audio_standard_NICAM(core,
+							 EN_NICAM_FORCE_STEREO);
+				break;
+			}
+		} else {
+			if ((core->tvaudio == WW_I) || (core->tvaudio == WW_L)) {
+				/* fall back to fm / am mono */
+				set_audio_standard_A2(core, EN_A2_FORCE_MONO1);
+			} else {
+				/* TODO: Add A2 autodection */
+				mask = 0x3f;
+				switch (mode) {
+				case V4L2_TUNER_MODE_MONO:
+				case V4L2_TUNER_MODE_LANG1:
+					ctl = EN_A2_FORCE_MONO1;
+					break;
+				case V4L2_TUNER_MODE_LANG2:
+					ctl = EN_A2_FORCE_MONO2;
+					break;
+				case V4L2_TUNER_MODE_STEREO:
+				case V4L2_TUNER_MODE_LANG1_LANG2:
+					ctl = EN_A2_FORCE_STEREO;
+					break;
+				}
+			}
+		}
+		break;
+	case WW_FM:
+		switch (mode) {
+		case V4L2_TUNER_MODE_MONO:
+			ctl = EN_FMRADIO_FORCE_MONO;
+			mask = 0x3f;
+			break;
+		case V4L2_TUNER_MODE_STEREO:
+			ctl = EN_FMRADIO_AUTO_STEREO;
+			mask = 0x3f;
+			break;
+		}
+		break;
+	case WW_I2SADC:
+	case WW_NONE:
+	case WW_EIAJ:
+	case WW_I2SPT:
+		/* DO NOTHING */
+		break;
+	}
+
+	if (UNSET != ctl) {
+		dprintk("cx88_set_stereo: mask 0x%x, ctl 0x%x "
+			"[status=0x%x,ctl=0x%x,vol=0x%x]\n",
+			mask, ctl, cx_read(AUD_STATUS),
+			cx_read(AUD_CTL), cx_sread(SHADOW_AUD_VOL_CTL));
+		cx_andor(AUD_CTL, mask, ctl);
+	}
+	return;
+}
+
+int cx88_audio_thread(void *data)
+{
+	struct cx88_core *core = data;
+	struct v4l2_tuner t;
+	u32 mode = 0;
+
+	dprintk("cx88: tvaudio thread started\n");
+	set_freezable();
+	for (;;) {
+		msleep_interruptible(1000);
+		if (kthread_should_stop())
+			break;
+		try_to_freeze();
+
+		switch (core->tvaudio) {
+		case WW_BG:
+		case WW_DK:
+		case WW_M:
+		case WW_I:
+		case WW_L:
+			if (core->use_nicam)
+				goto hw_autodetect;
+
+			/* just monitor the audio status for now ... */
+			memset(&t, 0, sizeof(t));
+			cx88_get_stereo(core, &t);
+
+			if (UNSET != core->audiomode_manual)
+				/* manually set, don't do anything. */
+				continue;
+
+			/* monitor signal and set stereo if available */
+			if (t.rxsubchans & V4L2_TUNER_SUB_STEREO)
+				mode = V4L2_TUNER_MODE_STEREO;
+			else
+				mode = V4L2_TUNER_MODE_MONO;
+			if (mode == core->audiomode_current)
+				continue;
+			/* automatically switch to best available mode */
+			cx88_set_stereo(core, mode, 0);
+			break;
+		case WW_NONE:
+		case WW_BTSC:
+		case WW_EIAJ:
+		case WW_I2SPT:
+		case WW_FM:
+		case WW_I2SADC:
+hw_autodetect:
+			/* stereo autodetection is supported by hardware so
+			   we don't need to do it manually. Do nothing. */
+			break;
+		}
+	}
+
+	dprintk("cx88: tvaudio thread exiting\n");
+	return 0;
+}
+
+/* ----------------------------------------------------------- */
+
+EXPORT_SYMBOL(cx88_set_tvaudio);
+EXPORT_SYMBOL(cx88_newstation);
+EXPORT_SYMBOL(cx88_set_stereo);
+EXPORT_SYMBOL(cx88_get_stereo);
+EXPORT_SYMBOL(cx88_audio_thread);
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off
+ */
diff --git a/drivers/media/pci/cx88/cx88-vbi.c b/drivers/media/pci/cx88/cx88-vbi.c
new file mode 100644
index 0000000..f8f8389
--- /dev/null
+++ b/drivers/media/pci/cx88/cx88-vbi.c
@@ -0,0 +1,245 @@
+/*
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include "cx88.h"
+
+static unsigned int vbibufs = 4;
+module_param(vbibufs,int,0644);
+MODULE_PARM_DESC(vbibufs,"number of vbi buffers, range 2-32");
+
+static unsigned int vbi_debug;
+module_param(vbi_debug,int,0644);
+MODULE_PARM_DESC(vbi_debug,"enable debug messages [vbi]");
+
+#define dprintk(level,fmt, arg...)	if (vbi_debug >= level) \
+	printk(KERN_DEBUG "%s: " fmt, dev->core->name , ## arg)
+
+/* ------------------------------------------------------------------ */
+
+int cx8800_vbi_fmt (struct file *file, void *priv,
+					struct v4l2_format *f)
+{
+	struct cx8800_fh  *fh   = priv;
+	struct cx8800_dev *dev  = fh->dev;
+
+	f->fmt.vbi.samples_per_line = VBI_LINE_LENGTH;
+	f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
+	f->fmt.vbi.offset = 244;
+	f->fmt.vbi.count[0] = VBI_LINE_COUNT;
+	f->fmt.vbi.count[1] = VBI_LINE_COUNT;
+
+	if (dev->core->tvnorm & V4L2_STD_525_60) {
+		/* ntsc */
+		f->fmt.vbi.sampling_rate = 28636363;
+		f->fmt.vbi.start[0] = 10;
+		f->fmt.vbi.start[1] = 273;
+
+	} else if (dev->core->tvnorm & V4L2_STD_625_50) {
+		/* pal */
+		f->fmt.vbi.sampling_rate = 35468950;
+		f->fmt.vbi.start[0] = 7 -1;
+		f->fmt.vbi.start[1] = 319 -1;
+	}
+	return 0;
+}
+
+static int cx8800_start_vbi_dma(struct cx8800_dev    *dev,
+			 struct cx88_dmaqueue *q,
+			 struct cx88_buffer   *buf)
+{
+	struct cx88_core *core = dev->core;
+
+	/* setup fifo + format */
+	cx88_sram_channel_setup(dev->core, &cx88_sram_channels[SRAM_CH24],
+				buf->vb.width, buf->risc.dma);
+
+	cx_write(MO_VBOS_CONTROL, ( (1 << 18) |  // comb filter delay fixup
+				    (1 << 15) |  // enable vbi capture
+				    (1 << 11) ));
+
+	/* reset counter */
+	cx_write(MO_VBI_GPCNTRL, GP_COUNT_CONTROL_RESET);
+	q->count = 1;
+
+	/* enable irqs */
+	cx_set(MO_PCI_INTMSK, core->pci_irqmask | PCI_INT_VIDINT);
+	cx_set(MO_VID_INTMSK, 0x0f0088);
+
+	/* enable capture */
+	cx_set(VID_CAPTURE_CONTROL,0x18);
+
+	/* start dma */
+	cx_set(MO_DEV_CNTRL2, (1<<5));
+	cx_set(MO_VID_DMACNTRL, 0x88);
+
+	return 0;
+}
+
+int cx8800_stop_vbi_dma(struct cx8800_dev *dev)
+{
+	struct cx88_core *core = dev->core;
+
+	/* stop dma */
+	cx_clear(MO_VID_DMACNTRL, 0x88);
+
+	/* disable capture */
+	cx_clear(VID_CAPTURE_CONTROL,0x18);
+
+	/* disable irqs */
+	cx_clear(MO_PCI_INTMSK, PCI_INT_VIDINT);
+	cx_clear(MO_VID_INTMSK, 0x0f0088);
+	return 0;
+}
+
+int cx8800_restart_vbi_queue(struct cx8800_dev    *dev,
+			     struct cx88_dmaqueue *q)
+{
+	struct cx88_buffer *buf;
+
+	if (list_empty(&q->active))
+		return 0;
+
+	buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
+	dprintk(2,"restart_queue [%p/%d]: restart dma\n",
+		buf, buf->vb.i);
+	cx8800_start_vbi_dma(dev, q, buf);
+	list_for_each_entry(buf, &q->active, vb.queue)
+		buf->count = q->count++;
+	mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
+	return 0;
+}
+
+void cx8800_vbi_timeout(unsigned long data)
+{
+	struct cx8800_dev *dev = (struct cx8800_dev*)data;
+	struct cx88_core *core = dev->core;
+	struct cx88_dmaqueue *q = &dev->vbiq;
+	struct cx88_buffer *buf;
+	unsigned long flags;
+
+	cx88_sram_channel_dump(dev->core, &cx88_sram_channels[SRAM_CH24]);
+
+	cx_clear(MO_VID_DMACNTRL, 0x88);
+	cx_clear(VID_CAPTURE_CONTROL, 0x18);
+
+	spin_lock_irqsave(&dev->slock,flags);
+	while (!list_empty(&q->active)) {
+		buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
+		list_del(&buf->vb.queue);
+		buf->vb.state = VIDEOBUF_ERROR;
+		wake_up(&buf->vb.done);
+		printk("%s/0: [%p/%d] timeout - dma=0x%08lx\n", dev->core->name,
+		       buf, buf->vb.i, (unsigned long)buf->risc.dma);
+	}
+	cx8800_restart_vbi_queue(dev,q);
+	spin_unlock_irqrestore(&dev->slock,flags);
+}
+
+/* ------------------------------------------------------------------ */
+
+static int
+vbi_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
+{
+	*size = VBI_LINE_COUNT * VBI_LINE_LENGTH * 2;
+	if (0 == *count)
+		*count = vbibufs;
+	if (*count < 2)
+		*count = 2;
+	if (*count > 32)
+		*count = 32;
+	return 0;
+}
+
+static int
+vbi_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
+	    enum v4l2_field field)
+{
+	struct cx8800_fh   *fh  = q->priv_data;
+	struct cx8800_dev  *dev = fh->dev;
+	struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb);
+	unsigned int size;
+	int rc;
+
+	size = VBI_LINE_COUNT * VBI_LINE_LENGTH * 2;
+	if (0 != buf->vb.baddr  &&  buf->vb.bsize < size)
+		return -EINVAL;
+
+	if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
+		struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
+		buf->vb.width  = VBI_LINE_LENGTH;
+		buf->vb.height = VBI_LINE_COUNT;
+		buf->vb.size   = size;
+		buf->vb.field  = V4L2_FIELD_SEQ_TB;
+
+		if (0 != (rc = videobuf_iolock(q,&buf->vb,NULL)))
+			goto fail;
+		cx88_risc_buffer(dev->pci, &buf->risc,
+				 dma->sglist,
+				 0, buf->vb.width * buf->vb.height,
+				 buf->vb.width, 0,
+				 buf->vb.height);
+	}
+	buf->vb.state = VIDEOBUF_PREPARED;
+	return 0;
+
+ fail:
+	cx88_free_buffer(q,buf);
+	return rc;
+}
+
+static void
+vbi_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+{
+	struct cx88_buffer    *buf = container_of(vb,struct cx88_buffer,vb);
+	struct cx88_buffer    *prev;
+	struct cx8800_fh      *fh   = vq->priv_data;
+	struct cx8800_dev     *dev  = fh->dev;
+	struct cx88_dmaqueue  *q    = &dev->vbiq;
+
+	/* add jump to stopper */
+	buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+	buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma);
+
+	if (list_empty(&q->active)) {
+		list_add_tail(&buf->vb.queue,&q->active);
+		cx8800_start_vbi_dma(dev, q, buf);
+		buf->vb.state = VIDEOBUF_ACTIVE;
+		buf->count    = q->count++;
+		mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
+		dprintk(2,"[%p/%d] vbi_queue - first active\n",
+			buf, buf->vb.i);
+
+	} else {
+		prev = list_entry(q->active.prev, struct cx88_buffer, vb.queue);
+		list_add_tail(&buf->vb.queue,&q->active);
+		buf->vb.state = VIDEOBUF_ACTIVE;
+		buf->count    = q->count++;
+		prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+		dprintk(2,"[%p/%d] buffer_queue - append to active\n",
+			buf, buf->vb.i);
+	}
+}
+
+static void vbi_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
+{
+	struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb);
+
+	cx88_free_buffer(q,buf);
+}
+
+const struct videobuf_queue_ops cx8800_vbi_qops = {
+	.buf_setup    = vbi_setup,
+	.buf_prepare  = vbi_prepare,
+	.buf_queue    = vbi_queue,
+	.buf_release  = vbi_release,
+};
+
+/* ------------------------------------------------------------------ */
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/pci/cx88/cx88-video.c b/drivers/media/pci/cx88/cx88-video.c
new file mode 100644
index 0000000..f6fcc7e
--- /dev/null
+++ b/drivers/media/pci/cx88/cx88-video.c
@@ -0,0 +1,2075 @@
+/*
+ *
+ * device driver for Conexant 2388x based TV cards
+ * video4linux video interface
+ *
+ * (c) 2003-04 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
+ *
+ * (c) 2005-2006 Mauro Carvalho Chehab <mchehab@infradead.org>
+ *	- Multituner support
+ *	- video_ioctl2 conversion
+ *	- PAL/M fixes
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the 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/init.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/kmod.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/kthread.h>
+#include <asm/div64.h>
+
+#include "cx88.h"
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-event.h>
+#include <media/wm8775.h>
+
+MODULE_DESCRIPTION("v4l2 driver module for cx2388x based TV cards");
+MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(CX88_VERSION);
+
+/* ------------------------------------------------------------------ */
+
+static unsigned int video_nr[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
+static unsigned int vbi_nr[]   = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
+static unsigned int radio_nr[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
+
+module_param_array(video_nr, int, NULL, 0444);
+module_param_array(vbi_nr,   int, NULL, 0444);
+module_param_array(radio_nr, int, NULL, 0444);
+
+MODULE_PARM_DESC(video_nr,"video device numbers");
+MODULE_PARM_DESC(vbi_nr,"vbi device numbers");
+MODULE_PARM_DESC(radio_nr,"radio device numbers");
+
+static unsigned int video_debug;
+module_param(video_debug,int,0644);
+MODULE_PARM_DESC(video_debug,"enable debug messages [video]");
+
+static unsigned int irq_debug;
+module_param(irq_debug,int,0644);
+MODULE_PARM_DESC(irq_debug,"enable debug messages [IRQ handler]");
+
+static unsigned int vid_limit = 16;
+module_param(vid_limit,int,0644);
+MODULE_PARM_DESC(vid_limit,"capture memory limit in megabytes");
+
+#define dprintk(level,fmt, arg...)	if (video_debug >= level) \
+	printk(KERN_DEBUG "%s/0: " fmt, core->name , ## arg)
+
+/* ------------------------------------------------------------------- */
+/* static data                                                         */
+
+static const struct cx8800_fmt formats[] = {
+	{
+		.name     = "8 bpp, gray",
+		.fourcc   = V4L2_PIX_FMT_GREY,
+		.cxformat = ColorFormatY8,
+		.depth    = 8,
+		.flags    = FORMAT_FLAGS_PACKED,
+	},{
+		.name     = "15 bpp RGB, le",
+		.fourcc   = V4L2_PIX_FMT_RGB555,
+		.cxformat = ColorFormatRGB15,
+		.depth    = 16,
+		.flags    = FORMAT_FLAGS_PACKED,
+	},{
+		.name     = "15 bpp RGB, be",
+		.fourcc   = V4L2_PIX_FMT_RGB555X,
+		.cxformat = ColorFormatRGB15 | ColorFormatBSWAP,
+		.depth    = 16,
+		.flags    = FORMAT_FLAGS_PACKED,
+	},{
+		.name     = "16 bpp RGB, le",
+		.fourcc   = V4L2_PIX_FMT_RGB565,
+		.cxformat = ColorFormatRGB16,
+		.depth    = 16,
+		.flags    = FORMAT_FLAGS_PACKED,
+	},{
+		.name     = "16 bpp RGB, be",
+		.fourcc   = V4L2_PIX_FMT_RGB565X,
+		.cxformat = ColorFormatRGB16 | ColorFormatBSWAP,
+		.depth    = 16,
+		.flags    = FORMAT_FLAGS_PACKED,
+	},{
+		.name     = "24 bpp RGB, le",
+		.fourcc   = V4L2_PIX_FMT_BGR24,
+		.cxformat = ColorFormatRGB24,
+		.depth    = 24,
+		.flags    = FORMAT_FLAGS_PACKED,
+	},{
+		.name     = "32 bpp RGB, le",
+		.fourcc   = V4L2_PIX_FMT_BGR32,
+		.cxformat = ColorFormatRGB32,
+		.depth    = 32,
+		.flags    = FORMAT_FLAGS_PACKED,
+	},{
+		.name     = "32 bpp RGB, be",
+		.fourcc   = V4L2_PIX_FMT_RGB32,
+		.cxformat = ColorFormatRGB32 | ColorFormatBSWAP | ColorFormatWSWAP,
+		.depth    = 32,
+		.flags    = FORMAT_FLAGS_PACKED,
+	},{
+		.name     = "4:2:2, packed, YUYV",
+		.fourcc   = V4L2_PIX_FMT_YUYV,
+		.cxformat = ColorFormatYUY2,
+		.depth    = 16,
+		.flags    = FORMAT_FLAGS_PACKED,
+	},{
+		.name     = "4:2:2, packed, UYVY",
+		.fourcc   = V4L2_PIX_FMT_UYVY,
+		.cxformat = ColorFormatYUY2 | ColorFormatBSWAP,
+		.depth    = 16,
+		.flags    = FORMAT_FLAGS_PACKED,
+	},
+};
+
+static const struct cx8800_fmt* format_by_fourcc(unsigned int fourcc)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(formats); i++)
+		if (formats[i].fourcc == fourcc)
+			return formats+i;
+	return NULL;
+}
+
+/* ------------------------------------------------------------------- */
+
+struct cx88_ctrl {
+	/* control information */
+	u32 id;
+	s32 minimum;
+	s32 maximum;
+	u32 step;
+	s32 default_value;
+
+	/* control register information */
+	u32 off;
+	u32 reg;
+	u32 sreg;
+	u32 mask;
+	u32 shift;
+};
+
+static const struct cx88_ctrl cx8800_vid_ctls[] = {
+	/* --- video --- */
+	{
+		.id            = V4L2_CID_BRIGHTNESS,
+		.minimum       = 0x00,
+		.maximum       = 0xff,
+		.step          = 1,
+		.default_value = 0x7f,
+		.off           = 128,
+		.reg           = MO_CONTR_BRIGHT,
+		.mask          = 0x00ff,
+		.shift         = 0,
+	},{
+		.id            = V4L2_CID_CONTRAST,
+		.minimum       = 0,
+		.maximum       = 0xff,
+		.step          = 1,
+		.default_value = 0x3f,
+		.off           = 0,
+		.reg           = MO_CONTR_BRIGHT,
+		.mask          = 0xff00,
+		.shift         = 8,
+	},{
+		.id            = V4L2_CID_HUE,
+		.minimum       = 0,
+		.maximum       = 0xff,
+		.step          = 1,
+		.default_value = 0x7f,
+		.off           = 128,
+		.reg           = MO_HUE,
+		.mask          = 0x00ff,
+		.shift         = 0,
+	},{
+		/* strictly, this only describes only U saturation.
+		 * V saturation is handled specially through code.
+		 */
+		.id            = V4L2_CID_SATURATION,
+		.minimum       = 0,
+		.maximum       = 0xff,
+		.step          = 1,
+		.default_value = 0x7f,
+		.off           = 0,
+		.reg           = MO_UV_SATURATION,
+		.mask          = 0x00ff,
+		.shift         = 0,
+	}, {
+		.id            = V4L2_CID_SHARPNESS,
+		.minimum       = 0,
+		.maximum       = 4,
+		.step          = 1,
+		.default_value = 0x0,
+		.off           = 0,
+		/* NOTE: the value is converted and written to both even
+		   and odd registers in the code */
+		.reg           = MO_FILTER_ODD,
+		.mask          = 7 << 7,
+		.shift         = 7,
+	}, {
+		.id            = V4L2_CID_CHROMA_AGC,
+		.minimum       = 0,
+		.maximum       = 1,
+		.default_value = 0x1,
+		.reg           = MO_INPUT_FORMAT,
+		.mask          = 1 << 10,
+		.shift         = 10,
+	}, {
+		.id            = V4L2_CID_COLOR_KILLER,
+		.minimum       = 0,
+		.maximum       = 1,
+		.default_value = 0x1,
+		.reg           = MO_INPUT_FORMAT,
+		.mask          = 1 << 9,
+		.shift         = 9,
+	}, {
+		.id            = V4L2_CID_BAND_STOP_FILTER,
+		.minimum       = 0,
+		.maximum       = 1,
+		.step          = 1,
+		.default_value = 0x0,
+		.off           = 0,
+		.reg           = MO_HTOTAL,
+		.mask          = 3 << 11,
+		.shift         = 11,
+	}
+};
+
+static const struct cx88_ctrl cx8800_aud_ctls[] = {
+	{
+		/* --- audio --- */
+		.id            = V4L2_CID_AUDIO_MUTE,
+		.minimum       = 0,
+		.maximum       = 1,
+		.default_value = 1,
+		.reg           = AUD_VOL_CTL,
+		.sreg          = SHADOW_AUD_VOL_CTL,
+		.mask          = (1 << 6),
+		.shift         = 6,
+	},{
+		.id            = V4L2_CID_AUDIO_VOLUME,
+		.minimum       = 0,
+		.maximum       = 0x3f,
+		.step          = 1,
+		.default_value = 0x3f,
+		.reg           = AUD_VOL_CTL,
+		.sreg          = SHADOW_AUD_VOL_CTL,
+		.mask          = 0x3f,
+		.shift         = 0,
+	},{
+		.id            = V4L2_CID_AUDIO_BALANCE,
+		.minimum       = 0,
+		.maximum       = 0x7f,
+		.step          = 1,
+		.default_value = 0x40,
+		.reg           = AUD_BAL_CTL,
+		.sreg          = SHADOW_AUD_BAL_CTL,
+		.mask          = 0x7f,
+		.shift         = 0,
+	}
+};
+
+enum {
+	CX8800_VID_CTLS = ARRAY_SIZE(cx8800_vid_ctls),
+	CX8800_AUD_CTLS = ARRAY_SIZE(cx8800_aud_ctls),
+};
+
+/* ------------------------------------------------------------------- */
+/* resource management                                                 */
+
+static int res_get(struct cx8800_dev *dev, struct cx8800_fh *fh, unsigned int bit)
+{
+	struct cx88_core *core = dev->core;
+	if (fh->resources & bit)
+		/* have it already allocated */
+		return 1;
+
+	/* is it free? */
+	mutex_lock(&core->lock);
+	if (dev->resources & bit) {
+		/* no, someone else uses it */
+		mutex_unlock(&core->lock);
+		return 0;
+	}
+	/* it's free, grab it */
+	fh->resources  |= bit;
+	dev->resources |= bit;
+	dprintk(1,"res: get %d\n",bit);
+	mutex_unlock(&core->lock);
+	return 1;
+}
+
+static
+int res_check(struct cx8800_fh *fh, unsigned int bit)
+{
+	return (fh->resources & bit);
+}
+
+static
+int res_locked(struct cx8800_dev *dev, unsigned int bit)
+{
+	return (dev->resources & bit);
+}
+
+static
+void res_free(struct cx8800_dev *dev, struct cx8800_fh *fh, unsigned int bits)
+{
+	struct cx88_core *core = dev->core;
+	BUG_ON((fh->resources & bits) != bits);
+
+	mutex_lock(&core->lock);
+	fh->resources  &= ~bits;
+	dev->resources &= ~bits;
+	dprintk(1,"res: put %d\n",bits);
+	mutex_unlock(&core->lock);
+}
+
+/* ------------------------------------------------------------------ */
+
+int cx88_video_mux(struct cx88_core *core, unsigned int input)
+{
+	/* struct cx88_core *core = dev->core; */
+
+	dprintk(1,"video_mux: %d [vmux=%d,gpio=0x%x,0x%x,0x%x,0x%x]\n",
+		input, INPUT(input).vmux,
+		INPUT(input).gpio0,INPUT(input).gpio1,
+		INPUT(input).gpio2,INPUT(input).gpio3);
+	core->input = input;
+	cx_andor(MO_INPUT_FORMAT, 0x03 << 14, INPUT(input).vmux << 14);
+	cx_write(MO_GP3_IO, INPUT(input).gpio3);
+	cx_write(MO_GP0_IO, INPUT(input).gpio0);
+	cx_write(MO_GP1_IO, INPUT(input).gpio1);
+	cx_write(MO_GP2_IO, INPUT(input).gpio2);
+
+	switch (INPUT(input).type) {
+	case CX88_VMUX_SVIDEO:
+		cx_set(MO_AFECFG_IO,    0x00000001);
+		cx_set(MO_INPUT_FORMAT, 0x00010010);
+		cx_set(MO_FILTER_EVEN,  0x00002020);
+		cx_set(MO_FILTER_ODD,   0x00002020);
+		break;
+	default:
+		cx_clear(MO_AFECFG_IO,    0x00000001);
+		cx_clear(MO_INPUT_FORMAT, 0x00010010);
+		cx_clear(MO_FILTER_EVEN,  0x00002020);
+		cx_clear(MO_FILTER_ODD,   0x00002020);
+		break;
+	}
+
+	/* if there are audioroutes defined, we have an external
+	   ADC to deal with audio */
+	if (INPUT(input).audioroute) {
+		/* The wm8775 module has the "2" route hardwired into
+		   the initialization. Some boards may use different
+		   routes for different inputs. HVR-1300 surely does */
+		if (core->board.audio_chip &&
+		    core->board.audio_chip == V4L2_IDENT_WM8775) {
+			call_all(core, audio, s_routing,
+				 INPUT(input).audioroute, 0, 0);
+		}
+		/* cx2388's C-ADC is connected to the tuner only.
+		   When used with S-Video, that ADC is busy dealing with
+		   chroma, so an external must be used for baseband audio */
+		if (INPUT(input).type != CX88_VMUX_TELEVISION &&
+		    INPUT(input).type != CX88_VMUX_CABLE) {
+			/* "I2S ADC mode" */
+			core->tvaudio = WW_I2SADC;
+			cx88_set_tvaudio(core);
+		} else {
+			/* Normal mode */
+			cx_write(AUD_I2SCNTL, 0x0);
+			cx_clear(AUD_CTL, EN_I2SIN_ENABLE);
+		}
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(cx88_video_mux);
+
+/* ------------------------------------------------------------------ */
+
+static int start_video_dma(struct cx8800_dev    *dev,
+			   struct cx88_dmaqueue *q,
+			   struct cx88_buffer   *buf)
+{
+	struct cx88_core *core = dev->core;
+
+	/* setup fifo + format */
+	cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH21],
+				buf->bpl, buf->risc.dma);
+	cx88_set_scale(core, buf->vb.width, buf->vb.height, buf->vb.field);
+	cx_write(MO_COLOR_CTRL, buf->fmt->cxformat | ColorFormatGamma);
+
+	/* reset counter */
+	cx_write(MO_VIDY_GPCNTRL,GP_COUNT_CONTROL_RESET);
+	q->count = 1;
+
+	/* enable irqs */
+	cx_set(MO_PCI_INTMSK, core->pci_irqmask | PCI_INT_VIDINT);
+
+	/* Enables corresponding bits at PCI_INT_STAT:
+		bits 0 to 4: video, audio, transport stream, VIP, Host
+		bit 7: timer
+		bits 8 and 9: DMA complete for: SRC, DST
+		bits 10 and 11: BERR signal asserted for RISC: RD, WR
+		bits 12 to 15: BERR signal asserted for: BRDG, SRC, DST, IPB
+	 */
+	cx_set(MO_VID_INTMSK, 0x0f0011);
+
+	/* enable capture */
+	cx_set(VID_CAPTURE_CONTROL,0x06);
+
+	/* start dma */
+	cx_set(MO_DEV_CNTRL2, (1<<5));
+	cx_set(MO_VID_DMACNTRL, 0x11); /* Planar Y and packed FIFO and RISC enable */
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int stop_video_dma(struct cx8800_dev    *dev)
+{
+	struct cx88_core *core = dev->core;
+
+	/* stop dma */
+	cx_clear(MO_VID_DMACNTRL, 0x11);
+
+	/* disable capture */
+	cx_clear(VID_CAPTURE_CONTROL,0x06);
+
+	/* disable irqs */
+	cx_clear(MO_PCI_INTMSK, PCI_INT_VIDINT);
+	cx_clear(MO_VID_INTMSK, 0x0f0011);
+	return 0;
+}
+#endif
+
+static int restart_video_queue(struct cx8800_dev    *dev,
+			       struct cx88_dmaqueue *q)
+{
+	struct cx88_core *core = dev->core;
+	struct cx88_buffer *buf, *prev;
+
+	if (!list_empty(&q->active)) {
+		buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
+		dprintk(2,"restart_queue [%p/%d]: restart dma\n",
+			buf, buf->vb.i);
+		start_video_dma(dev, q, buf);
+		list_for_each_entry(buf, &q->active, vb.queue)
+			buf->count = q->count++;
+		mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
+		return 0;
+	}
+
+	prev = NULL;
+	for (;;) {
+		if (list_empty(&q->queued))
+			return 0;
+		buf = list_entry(q->queued.next, struct cx88_buffer, vb.queue);
+		if (NULL == prev) {
+			list_move_tail(&buf->vb.queue, &q->active);
+			start_video_dma(dev, q, buf);
+			buf->vb.state = VIDEOBUF_ACTIVE;
+			buf->count    = q->count++;
+			mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
+			dprintk(2,"[%p/%d] restart_queue - first active\n",
+				buf,buf->vb.i);
+
+		} else if (prev->vb.width  == buf->vb.width  &&
+			   prev->vb.height == buf->vb.height &&
+			   prev->fmt       == buf->fmt) {
+			list_move_tail(&buf->vb.queue, &q->active);
+			buf->vb.state = VIDEOBUF_ACTIVE;
+			buf->count    = q->count++;
+			prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+			dprintk(2,"[%p/%d] restart_queue - move to active\n",
+				buf,buf->vb.i);
+		} else {
+			return 0;
+		}
+		prev = buf;
+	}
+}
+
+/* ------------------------------------------------------------------ */
+
+static int
+buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
+{
+	struct cx8800_fh *fh = q->priv_data;
+	struct cx8800_dev  *dev = fh->dev;
+
+	*size = dev->fmt->depth * dev->width * dev->height >> 3;
+	if (0 == *count)
+		*count = 32;
+	if (*size * *count > vid_limit * 1024 * 1024)
+		*count = (vid_limit * 1024 * 1024) / *size;
+	return 0;
+}
+
+static int
+buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
+	       enum v4l2_field field)
+{
+	struct cx8800_fh   *fh  = q->priv_data;
+	struct cx8800_dev  *dev = fh->dev;
+	struct cx88_core *core = dev->core;
+	struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb);
+	struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
+	int rc, init_buffer = 0;
+
+	BUG_ON(NULL == dev->fmt);
+	if (dev->width  < 48 || dev->width  > norm_maxw(core->tvnorm) ||
+	    dev->height < 32 || dev->height > norm_maxh(core->tvnorm))
+		return -EINVAL;
+	buf->vb.size = (dev->width * dev->height * dev->fmt->depth) >> 3;
+	if (0 != buf->vb.baddr  &&  buf->vb.bsize < buf->vb.size)
+		return -EINVAL;
+
+	if (buf->fmt       != dev->fmt    ||
+	    buf->vb.width  != dev->width  ||
+	    buf->vb.height != dev->height ||
+	    buf->vb.field  != field) {
+		buf->fmt       = dev->fmt;
+		buf->vb.width  = dev->width;
+		buf->vb.height = dev->height;
+		buf->vb.field  = field;
+		init_buffer = 1;
+	}
+
+	if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
+		init_buffer = 1;
+		if (0 != (rc = videobuf_iolock(q,&buf->vb,NULL)))
+			goto fail;
+	}
+
+	if (init_buffer) {
+		buf->bpl = buf->vb.width * buf->fmt->depth >> 3;
+		switch (buf->vb.field) {
+		case V4L2_FIELD_TOP:
+			cx88_risc_buffer(dev->pci, &buf->risc,
+					 dma->sglist, 0, UNSET,
+					 buf->bpl, 0, buf->vb.height);
+			break;
+		case V4L2_FIELD_BOTTOM:
+			cx88_risc_buffer(dev->pci, &buf->risc,
+					 dma->sglist, UNSET, 0,
+					 buf->bpl, 0, buf->vb.height);
+			break;
+		case V4L2_FIELD_INTERLACED:
+			cx88_risc_buffer(dev->pci, &buf->risc,
+					 dma->sglist, 0, buf->bpl,
+					 buf->bpl, buf->bpl,
+					 buf->vb.height >> 1);
+			break;
+		case V4L2_FIELD_SEQ_TB:
+			cx88_risc_buffer(dev->pci, &buf->risc,
+					 dma->sglist,
+					 0, buf->bpl * (buf->vb.height >> 1),
+					 buf->bpl, 0,
+					 buf->vb.height >> 1);
+			break;
+		case V4L2_FIELD_SEQ_BT:
+			cx88_risc_buffer(dev->pci, &buf->risc,
+					 dma->sglist,
+					 buf->bpl * (buf->vb.height >> 1), 0,
+					 buf->bpl, 0,
+					 buf->vb.height >> 1);
+			break;
+		default:
+			BUG();
+		}
+	}
+	dprintk(2,"[%p/%d] buffer_prepare - %dx%d %dbpp \"%s\" - dma=0x%08lx\n",
+		buf, buf->vb.i,
+		dev->width, dev->height, dev->fmt->depth, dev->fmt->name,
+		(unsigned long)buf->risc.dma);
+
+	buf->vb.state = VIDEOBUF_PREPARED;
+	return 0;
+
+ fail:
+	cx88_free_buffer(q,buf);
+	return rc;
+}
+
+static void
+buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+{
+	struct cx88_buffer    *buf = container_of(vb,struct cx88_buffer,vb);
+	struct cx88_buffer    *prev;
+	struct cx8800_fh      *fh   = vq->priv_data;
+	struct cx8800_dev     *dev  = fh->dev;
+	struct cx88_core      *core = dev->core;
+	struct cx88_dmaqueue  *q    = &dev->vidq;
+
+	/* add jump to stopper */
+	buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+	buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma);
+
+	if (!list_empty(&q->queued)) {
+		list_add_tail(&buf->vb.queue,&q->queued);
+		buf->vb.state = VIDEOBUF_QUEUED;
+		dprintk(2,"[%p/%d] buffer_queue - append to queued\n",
+			buf, buf->vb.i);
+
+	} else if (list_empty(&q->active)) {
+		list_add_tail(&buf->vb.queue,&q->active);
+		start_video_dma(dev, q, buf);
+		buf->vb.state = VIDEOBUF_ACTIVE;
+		buf->count    = q->count++;
+		mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
+		dprintk(2,"[%p/%d] buffer_queue - first active\n",
+			buf, buf->vb.i);
+
+	} else {
+		prev = list_entry(q->active.prev, struct cx88_buffer, vb.queue);
+		if (prev->vb.width  == buf->vb.width  &&
+		    prev->vb.height == buf->vb.height &&
+		    prev->fmt       == buf->fmt) {
+			list_add_tail(&buf->vb.queue,&q->active);
+			buf->vb.state = VIDEOBUF_ACTIVE;
+			buf->count    = q->count++;
+			prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+			dprintk(2,"[%p/%d] buffer_queue - append to active\n",
+				buf, buf->vb.i);
+
+		} else {
+			list_add_tail(&buf->vb.queue,&q->queued);
+			buf->vb.state = VIDEOBUF_QUEUED;
+			dprintk(2,"[%p/%d] buffer_queue - first queued\n",
+				buf, buf->vb.i);
+		}
+	}
+}
+
+static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
+{
+	struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb);
+
+	cx88_free_buffer(q,buf);
+}
+
+static const struct videobuf_queue_ops cx8800_video_qops = {
+	.buf_setup    = buffer_setup,
+	.buf_prepare  = buffer_prepare,
+	.buf_queue    = buffer_queue,
+	.buf_release  = buffer_release,
+};
+
+/* ------------------------------------------------------------------ */
+
+
+/* ------------------------------------------------------------------ */
+
+static struct videobuf_queue *get_queue(struct file *file)
+{
+	struct video_device *vdev = video_devdata(file);
+	struct cx8800_fh *fh = file->private_data;
+
+	switch (vdev->vfl_type) {
+	case VFL_TYPE_GRABBER:
+		return &fh->vidq;
+	case VFL_TYPE_VBI:
+		return &fh->vbiq;
+	default:
+		BUG();
+		return NULL;
+	}
+}
+
+static int get_resource(struct file *file)
+{
+	struct video_device *vdev = video_devdata(file);
+
+	switch (vdev->vfl_type) {
+	case VFL_TYPE_GRABBER:
+		return RESOURCE_VIDEO;
+	case VFL_TYPE_VBI:
+		return RESOURCE_VBI;
+	default:
+		BUG();
+		return 0;
+	}
+}
+
+static int video_open(struct file *file)
+{
+	struct video_device *vdev = video_devdata(file);
+	struct cx8800_dev *dev = video_drvdata(file);
+	struct cx88_core *core = dev->core;
+	struct cx8800_fh *fh;
+	enum v4l2_buf_type type = 0;
+	int radio = 0;
+
+	switch (vdev->vfl_type) {
+	case VFL_TYPE_GRABBER:
+		type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+		break;
+	case VFL_TYPE_VBI:
+		type = V4L2_BUF_TYPE_VBI_CAPTURE;
+		break;
+	case VFL_TYPE_RADIO:
+		radio = 1;
+		break;
+	}
+
+	dprintk(1, "open dev=%s radio=%d type=%s\n",
+		video_device_node_name(vdev), radio, v4l2_type_names[type]);
+
+	/* allocate + initialize per filehandle data */
+	fh = kzalloc(sizeof(*fh),GFP_KERNEL);
+	if (unlikely(!fh))
+		return -ENOMEM;
+
+	v4l2_fh_init(&fh->fh, vdev);
+	file->private_data = fh;
+	fh->dev      = dev;
+
+	mutex_lock(&core->lock);
+
+	videobuf_queue_sg_init(&fh->vidq, &cx8800_video_qops,
+			    &dev->pci->dev, &dev->slock,
+			    V4L2_BUF_TYPE_VIDEO_CAPTURE,
+			    V4L2_FIELD_INTERLACED,
+			    sizeof(struct cx88_buffer),
+			    fh, NULL);
+	videobuf_queue_sg_init(&fh->vbiq, &cx8800_vbi_qops,
+			    &dev->pci->dev, &dev->slock,
+			    V4L2_BUF_TYPE_VBI_CAPTURE,
+			    V4L2_FIELD_SEQ_TB,
+			    sizeof(struct cx88_buffer),
+			    fh, NULL);
+
+	if (vdev->vfl_type == VFL_TYPE_RADIO) {
+		dprintk(1,"video_open: setting radio device\n");
+		cx_write(MO_GP3_IO, core->board.radio.gpio3);
+		cx_write(MO_GP0_IO, core->board.radio.gpio0);
+		cx_write(MO_GP1_IO, core->board.radio.gpio1);
+		cx_write(MO_GP2_IO, core->board.radio.gpio2);
+		if (core->board.radio.audioroute) {
+			if(core->board.audio_chip &&
+				core->board.audio_chip == V4L2_IDENT_WM8775) {
+				call_all(core, audio, s_routing,
+					core->board.radio.audioroute, 0, 0);
+			}
+			/* "I2S ADC mode" */
+			core->tvaudio = WW_I2SADC;
+			cx88_set_tvaudio(core);
+		} else {
+			/* FM Mode */
+			core->tvaudio = WW_FM;
+			cx88_set_tvaudio(core);
+			cx88_set_stereo(core,V4L2_TUNER_MODE_STEREO,1);
+		}
+		call_all(core, tuner, s_radio);
+	}
+
+	core->users++;
+	mutex_unlock(&core->lock);
+	v4l2_fh_add(&fh->fh);
+
+	return 0;
+}
+
+static ssize_t
+video_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
+{
+	struct video_device *vdev = video_devdata(file);
+	struct cx8800_fh *fh = file->private_data;
+
+	switch (vdev->vfl_type) {
+	case VFL_TYPE_GRABBER:
+		if (res_locked(fh->dev,RESOURCE_VIDEO))
+			return -EBUSY;
+		return videobuf_read_one(&fh->vidq, data, count, ppos,
+					 file->f_flags & O_NONBLOCK);
+	case VFL_TYPE_VBI:
+		if (!res_get(fh->dev,fh,RESOURCE_VBI))
+			return -EBUSY;
+		return videobuf_read_stream(&fh->vbiq, data, count, ppos, 1,
+					    file->f_flags & O_NONBLOCK);
+	default:
+		BUG();
+		return 0;
+	}
+}
+
+static unsigned int
+video_poll(struct file *file, struct poll_table_struct *wait)
+{
+	struct video_device *vdev = video_devdata(file);
+	struct cx8800_fh *fh = file->private_data;
+	struct cx88_buffer *buf;
+	unsigned int rc = v4l2_ctrl_poll(file, wait);
+
+	if (vdev->vfl_type == VFL_TYPE_VBI) {
+		if (!res_get(fh->dev,fh,RESOURCE_VBI))
+			return rc | POLLERR;
+		return rc | videobuf_poll_stream(file, &fh->vbiq, wait);
+	}
+	mutex_lock(&fh->vidq.vb_lock);
+	if (res_check(fh,RESOURCE_VIDEO)) {
+		/* streaming capture */
+		if (list_empty(&fh->vidq.stream))
+			goto done;
+		buf = list_entry(fh->vidq.stream.next,struct cx88_buffer,vb.stream);
+	} else {
+		/* read() capture */
+		buf = (struct cx88_buffer*)fh->vidq.read_buf;
+		if (NULL == buf)
+			goto done;
+	}
+	poll_wait(file, &buf->vb.done, wait);
+	if (buf->vb.state == VIDEOBUF_DONE ||
+	    buf->vb.state == VIDEOBUF_ERROR)
+		rc |= POLLIN|POLLRDNORM;
+done:
+	mutex_unlock(&fh->vidq.vb_lock);
+	return rc;
+}
+
+static int video_release(struct file *file)
+{
+	struct cx8800_fh  *fh  = file->private_data;
+	struct cx8800_dev *dev = fh->dev;
+
+	/* turn off overlay */
+	if (res_check(fh, RESOURCE_OVERLAY)) {
+		/* FIXME */
+		res_free(dev,fh,RESOURCE_OVERLAY);
+	}
+
+	/* stop video capture */
+	if (res_check(fh, RESOURCE_VIDEO)) {
+		videobuf_queue_cancel(&fh->vidq);
+		res_free(dev,fh,RESOURCE_VIDEO);
+	}
+	if (fh->vidq.read_buf) {
+		buffer_release(&fh->vidq,fh->vidq.read_buf);
+		kfree(fh->vidq.read_buf);
+	}
+
+	/* stop vbi capture */
+	if (res_check(fh, RESOURCE_VBI)) {
+		videobuf_stop(&fh->vbiq);
+		res_free(dev,fh,RESOURCE_VBI);
+	}
+
+	videobuf_mmap_free(&fh->vidq);
+	videobuf_mmap_free(&fh->vbiq);
+
+	mutex_lock(&dev->core->lock);
+	v4l2_fh_del(&fh->fh);
+	v4l2_fh_exit(&fh->fh);
+	file->private_data = NULL;
+	kfree(fh);
+
+	dev->core->users--;
+	if (!dev->core->users)
+		call_all(dev->core, core, s_power, 0);
+	mutex_unlock(&dev->core->lock);
+
+	return 0;
+}
+
+static int
+video_mmap(struct file *file, struct vm_area_struct * vma)
+{
+	return videobuf_mmap_mapper(get_queue(file), vma);
+}
+
+/* ------------------------------------------------------------------ */
+/* VIDEO CTRL IOCTLS                                                  */
+
+static int cx8800_s_vid_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct cx88_core *core =
+		container_of(ctrl->handler, struct cx88_core, video_hdl);
+	const struct cx88_ctrl *cc = ctrl->priv;
+	u32 value, mask;
+
+	mask = cc->mask;
+	switch (ctrl->id) {
+	case V4L2_CID_SATURATION:
+		/* special v_sat handling */
+
+		value = ((ctrl->val - cc->off) << cc->shift) & cc->mask;
+
+		if (core->tvnorm & V4L2_STD_SECAM) {
+			/* For SECAM, both U and V sat should be equal */
+			value = value << 8 | value;
+		} else {
+			/* Keeps U Saturation proportional to V Sat */
+			value = (value * 0x5a) / 0x7f << 8 | value;
+		}
+		mask = 0xffff;
+		break;
+	case V4L2_CID_SHARPNESS:
+		/* 0b000, 0b100, 0b101, 0b110, or 0b111 */
+		value = (ctrl->val < 1 ? 0 : ((ctrl->val + 3) << 7));
+		/* needs to be set for both fields */
+		cx_andor(MO_FILTER_EVEN, mask, value);
+		break;
+	case V4L2_CID_CHROMA_AGC:
+		value = ((ctrl->val - cc->off) << cc->shift) & cc->mask;
+		break;
+	default:
+		value = ((ctrl->val - cc->off) << cc->shift) & cc->mask;
+		break;
+	}
+	dprintk(1, "set_control id=0x%X(%s) ctrl=0x%02x, reg=0x%02x val=0x%02x (mask 0x%02x)%s\n",
+				ctrl->id, ctrl->name, ctrl->val, cc->reg, value,
+				mask, cc->sreg ? " [shadowed]" : "");
+	if (cc->sreg)
+		cx_sandor(cc->sreg, cc->reg, mask, value);
+	else
+		cx_andor(cc->reg, mask, value);
+	return 0;
+}
+
+static int cx8800_s_aud_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct cx88_core *core =
+		container_of(ctrl->handler, struct cx88_core, audio_hdl);
+	const struct cx88_ctrl *cc = ctrl->priv;
+	u32 value,mask;
+
+	/* Pass changes onto any WM8775 */
+	if (core->board.audio_chip == V4L2_IDENT_WM8775) {
+		switch (ctrl->id) {
+		case V4L2_CID_AUDIO_MUTE:
+			wm8775_s_ctrl(core, ctrl->id, ctrl->val);
+			break;
+		case V4L2_CID_AUDIO_VOLUME:
+			wm8775_s_ctrl(core, ctrl->id, (ctrl->val) ?
+						(0x90 + ctrl->val) << 8 : 0);
+			break;
+		case V4L2_CID_AUDIO_BALANCE:
+			wm8775_s_ctrl(core, ctrl->id, ctrl->val << 9);
+			break;
+		default:
+			break;
+		}
+	}
+
+	mask = cc->mask;
+	switch (ctrl->id) {
+	case V4L2_CID_AUDIO_BALANCE:
+		value = (ctrl->val < 0x40) ? (0x7f - ctrl->val) : (ctrl->val - 0x40);
+		break;
+	case V4L2_CID_AUDIO_VOLUME:
+		value = 0x3f - (ctrl->val & 0x3f);
+		break;
+	default:
+		value = ((ctrl->val - cc->off) << cc->shift) & cc->mask;
+		break;
+	}
+	dprintk(1,"set_control id=0x%X(%s) ctrl=0x%02x, reg=0x%02x val=0x%02x (mask 0x%02x)%s\n",
+				ctrl->id, ctrl->name, ctrl->val, cc->reg, value,
+				mask, cc->sreg ? " [shadowed]" : "");
+	if (cc->sreg)
+		cx_sandor(cc->sreg, cc->reg, mask, value);
+	else
+		cx_andor(cc->reg, mask, value);
+	return 0;
+}
+
+/* ------------------------------------------------------------------ */
+/* VIDEO IOCTLS                                                       */
+
+static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
+					struct v4l2_format *f)
+{
+	struct cx8800_fh  *fh   = priv;
+	struct cx8800_dev *dev = fh->dev;
+
+	f->fmt.pix.width        = dev->width;
+	f->fmt.pix.height       = dev->height;
+	f->fmt.pix.field        = fh->vidq.field;
+	f->fmt.pix.pixelformat  = dev->fmt->fourcc;
+	f->fmt.pix.bytesperline =
+		(f->fmt.pix.width * dev->fmt->depth) >> 3;
+	f->fmt.pix.sizeimage =
+		f->fmt.pix.height * f->fmt.pix.bytesperline;
+	f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+	return 0;
+}
+
+static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
+			struct v4l2_format *f)
+{
+	struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;
+	const struct cx8800_fmt *fmt;
+	enum v4l2_field   field;
+	unsigned int      maxw, maxh;
+
+	fmt = format_by_fourcc(f->fmt.pix.pixelformat);
+	if (NULL == fmt)
+		return -EINVAL;
+
+	field = f->fmt.pix.field;
+	maxw  = norm_maxw(core->tvnorm);
+	maxh  = norm_maxh(core->tvnorm);
+
+	if (V4L2_FIELD_ANY == field) {
+		field = (f->fmt.pix.height > maxh/2)
+			? V4L2_FIELD_INTERLACED
+			: V4L2_FIELD_BOTTOM;
+	}
+
+	switch (field) {
+	case V4L2_FIELD_TOP:
+	case V4L2_FIELD_BOTTOM:
+		maxh = maxh / 2;
+		break;
+	case V4L2_FIELD_INTERLACED:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	f->fmt.pix.field = field;
+	v4l_bound_align_image(&f->fmt.pix.width, 48, maxw, 2,
+			      &f->fmt.pix.height, 32, maxh, 0, 0);
+	f->fmt.pix.bytesperline =
+		(f->fmt.pix.width * fmt->depth) >> 3;
+	f->fmt.pix.sizeimage =
+		f->fmt.pix.height * f->fmt.pix.bytesperline;
+
+	return 0;
+}
+
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
+					struct v4l2_format *f)
+{
+	struct cx8800_fh  *fh   = priv;
+	struct cx8800_dev *dev = fh->dev;
+	int err = vidioc_try_fmt_vid_cap (file,priv,f);
+
+	if (0 != err)
+		return err;
+	dev->fmt        = format_by_fourcc(f->fmt.pix.pixelformat);
+	dev->width      = f->fmt.pix.width;
+	dev->height     = f->fmt.pix.height;
+	fh->vidq.field = f->fmt.pix.field;
+	return 0;
+}
+
+void cx88_querycap(struct file *file, struct cx88_core *core,
+		struct v4l2_capability *cap)
+{
+	struct video_device *vdev = video_devdata(file);
+
+	strlcpy(cap->card, core->board.name, sizeof(cap->card));
+	cap->device_caps = V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
+	if (UNSET != core->board.tuner_type)
+		cap->device_caps |= V4L2_CAP_TUNER;
+	switch (vdev->vfl_type) {
+	case VFL_TYPE_RADIO:
+		cap->device_caps = V4L2_CAP_RADIO | V4L2_CAP_TUNER;
+		break;
+	case VFL_TYPE_GRABBER:
+		cap->device_caps |= V4L2_CAP_VIDEO_CAPTURE;
+		break;
+	case VFL_TYPE_VBI:
+		cap->device_caps |= V4L2_CAP_VBI_CAPTURE;
+		break;
+	}
+	cap->capabilities = cap->device_caps | V4L2_CAP_VIDEO_CAPTURE |
+		V4L2_CAP_VBI_CAPTURE | V4L2_CAP_DEVICE_CAPS;
+	if (core->board.radio.type == CX88_RADIO)
+		cap->capabilities |= V4L2_CAP_RADIO;
+}
+EXPORT_SYMBOL(cx88_querycap);
+
+static int vidioc_querycap(struct file *file, void  *priv,
+					struct v4l2_capability *cap)
+{
+	struct cx8800_dev *dev  = ((struct cx8800_fh *)priv)->dev;
+	struct cx88_core  *core = dev->core;
+
+	strcpy(cap->driver, "cx8800");
+	sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
+	cx88_querycap(file, core, cap);
+	return 0;
+}
+
+static int vidioc_enum_fmt_vid_cap (struct file *file, void  *priv,
+					struct v4l2_fmtdesc *f)
+{
+	if (unlikely(f->index >= ARRAY_SIZE(formats)))
+		return -EINVAL;
+
+	strlcpy(f->description,formats[f->index].name,sizeof(f->description));
+	f->pixelformat = formats[f->index].fourcc;
+
+	return 0;
+}
+
+static int vidioc_reqbufs (struct file *file, void *priv, struct v4l2_requestbuffers *p)
+{
+	return videobuf_reqbufs(get_queue(file), p);
+}
+
+static int vidioc_querybuf (struct file *file, void *priv, struct v4l2_buffer *p)
+{
+	return videobuf_querybuf(get_queue(file), p);
+}
+
+static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *p)
+{
+	return videobuf_qbuf(get_queue(file), p);
+}
+
+static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *p)
+{
+	return videobuf_dqbuf(get_queue(file), p,
+				file->f_flags & O_NONBLOCK);
+}
+
+static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+	struct video_device *vdev = video_devdata(file);
+	struct cx8800_fh  *fh   = priv;
+	struct cx8800_dev *dev  = fh->dev;
+
+	if ((vdev->vfl_type == VFL_TYPE_GRABBER && i != V4L2_BUF_TYPE_VIDEO_CAPTURE) ||
+	    (vdev->vfl_type == VFL_TYPE_VBI && i != V4L2_BUF_TYPE_VBI_CAPTURE))
+		return -EINVAL;
+
+	if (unlikely(!res_get(dev, fh, get_resource(file))))
+		return -EBUSY;
+	return videobuf_streamon(get_queue(file));
+}
+
+static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+	struct video_device *vdev = video_devdata(file);
+	struct cx8800_fh  *fh   = priv;
+	struct cx8800_dev *dev  = fh->dev;
+	int               err, res;
+
+	if ((vdev->vfl_type == VFL_TYPE_GRABBER && i != V4L2_BUF_TYPE_VIDEO_CAPTURE) ||
+	    (vdev->vfl_type == VFL_TYPE_VBI && i != V4L2_BUF_TYPE_VBI_CAPTURE))
+		return -EINVAL;
+
+	res = get_resource(file);
+	err = videobuf_streamoff(get_queue(file));
+	if (err < 0)
+		return err;
+	res_free(dev,fh,res);
+	return 0;
+}
+
+static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *tvnorm)
+{
+	struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
+
+	*tvnorm = core->tvnorm;
+	return 0;
+}
+
+static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id *tvnorms)
+{
+	struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;
+
+	mutex_lock(&core->lock);
+	cx88_set_tvnorm(core,*tvnorms);
+	mutex_unlock(&core->lock);
+
+	return 0;
+}
+
+/* only one input in this sample driver */
+int cx88_enum_input (struct cx88_core  *core,struct v4l2_input *i)
+{
+	static const char * const iname[] = {
+		[ CX88_VMUX_COMPOSITE1 ] = "Composite1",
+		[ CX88_VMUX_COMPOSITE2 ] = "Composite2",
+		[ CX88_VMUX_COMPOSITE3 ] = "Composite3",
+		[ CX88_VMUX_COMPOSITE4 ] = "Composite4",
+		[ CX88_VMUX_SVIDEO     ] = "S-Video",
+		[ CX88_VMUX_TELEVISION ] = "Television",
+		[ CX88_VMUX_CABLE      ] = "Cable TV",
+		[ CX88_VMUX_DVB        ] = "DVB",
+		[ CX88_VMUX_DEBUG      ] = "for debug only",
+	};
+	unsigned int n = i->index;
+
+	if (n >= 4)
+		return -EINVAL;
+	if (0 == INPUT(n).type)
+		return -EINVAL;
+	i->type  = V4L2_INPUT_TYPE_CAMERA;
+	strcpy(i->name,iname[INPUT(n).type]);
+	if ((CX88_VMUX_TELEVISION == INPUT(n).type) ||
+	    (CX88_VMUX_CABLE      == INPUT(n).type)) {
+		i->type = V4L2_INPUT_TYPE_TUNER;
+	}
+	i->std = CX88_NORMS;
+	return 0;
+}
+EXPORT_SYMBOL(cx88_enum_input);
+
+static int vidioc_enum_input (struct file *file, void *priv,
+				struct v4l2_input *i)
+{
+	struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;
+	return cx88_enum_input (core,i);
+}
+
+static int vidioc_g_input (struct file *file, void *priv, unsigned int *i)
+{
+	struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;
+
+	*i = core->input;
+	return 0;
+}
+
+static int vidioc_s_input (struct file *file, void *priv, unsigned int i)
+{
+	struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;
+
+	if (i >= 4)
+		return -EINVAL;
+	if (0 == INPUT(i).type)
+		return -EINVAL;
+
+	mutex_lock(&core->lock);
+	cx88_newstation(core);
+	cx88_video_mux(core,i);
+	mutex_unlock(&core->lock);
+	return 0;
+}
+
+static int vidioc_g_tuner (struct file *file, void *priv,
+				struct v4l2_tuner *t)
+{
+	struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;
+	u32 reg;
+
+	if (unlikely(UNSET == core->board.tuner_type))
+		return -EINVAL;
+	if (0 != t->index)
+		return -EINVAL;
+
+	strcpy(t->name, "Television");
+	t->capability = V4L2_TUNER_CAP_NORM;
+	t->rangehigh  = 0xffffffffUL;
+	call_all(core, tuner, g_tuner, t);
+
+	cx88_get_stereo(core ,t);
+	reg = cx_read(MO_DEVICE_STATUS);
+	t->signal = (reg & (1<<5)) ? 0xffff : 0x0000;
+	return 0;
+}
+
+static int vidioc_s_tuner (struct file *file, void *priv,
+				struct v4l2_tuner *t)
+{
+	struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;
+
+	if (UNSET == core->board.tuner_type)
+		return -EINVAL;
+	if (0 != t->index)
+		return -EINVAL;
+
+	cx88_set_stereo(core, t->audmode, 1);
+	return 0;
+}
+
+static int vidioc_g_frequency (struct file *file, void *priv,
+				struct v4l2_frequency *f)
+{
+	struct cx8800_fh  *fh   = priv;
+	struct cx88_core  *core = fh->dev->core;
+
+	if (unlikely(UNSET == core->board.tuner_type))
+		return -EINVAL;
+	if (f->tuner)
+		return -EINVAL;
+
+	f->frequency = core->freq;
+
+	call_all(core, tuner, g_frequency, f);
+
+	return 0;
+}
+
+int cx88_set_freq (struct cx88_core  *core,
+				struct v4l2_frequency *f)
+{
+	if (unlikely(UNSET == core->board.tuner_type))
+		return -EINVAL;
+	if (unlikely(f->tuner != 0))
+		return -EINVAL;
+
+	mutex_lock(&core->lock);
+	cx88_newstation(core);
+	call_all(core, tuner, s_frequency, f);
+	call_all(core, tuner, g_frequency, f);
+	core->freq = f->frequency;
+
+	/* When changing channels it is required to reset TVAUDIO */
+	msleep (10);
+	cx88_set_tvaudio(core);
+
+	mutex_unlock(&core->lock);
+
+	return 0;
+}
+EXPORT_SYMBOL(cx88_set_freq);
+
+static int vidioc_s_frequency (struct file *file, void *priv,
+				struct v4l2_frequency *f)
+{
+	struct cx8800_fh  *fh   = priv;
+	struct cx88_core  *core = fh->dev->core;
+
+	return cx88_set_freq(core, f);
+}
+
+static int vidioc_g_chip_ident(struct file *file, void *priv,
+				struct v4l2_dbg_chip_ident *chip)
+{
+	if (!v4l2_chip_match_host(&chip->match))
+		return -EINVAL;
+	chip->revision = 0;
+	chip->ident = V4L2_IDENT_UNKNOWN;
+	return 0;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int vidioc_g_register (struct file *file, void *fh,
+				struct v4l2_dbg_register *reg)
+{
+	struct cx88_core *core = ((struct cx8800_fh*)fh)->dev->core;
+
+	if (!v4l2_chip_match_host(&reg->match))
+		return -EINVAL;
+	/* cx2388x has a 24-bit register space */
+	reg->val = cx_read(reg->reg & 0xffffff);
+	reg->size = 4;
+	return 0;
+}
+
+static int vidioc_s_register (struct file *file, void *fh,
+				struct v4l2_dbg_register *reg)
+{
+	struct cx88_core *core = ((struct cx8800_fh*)fh)->dev->core;
+
+	if (!v4l2_chip_match_host(&reg->match))
+		return -EINVAL;
+	cx_write(reg->reg & 0xffffff, reg->val);
+	return 0;
+}
+#endif
+
+/* ----------------------------------------------------------- */
+/* RADIO ESPECIFIC IOCTLS                                      */
+/* ----------------------------------------------------------- */
+
+static int radio_g_tuner (struct file *file, void *priv,
+				struct v4l2_tuner *t)
+{
+	struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;
+
+	if (unlikely(t->index > 0))
+		return -EINVAL;
+
+	strcpy(t->name, "Radio");
+
+	call_all(core, tuner, g_tuner, t);
+	return 0;
+}
+
+/* FIXME: Should add a standard for radio */
+
+static int radio_s_tuner (struct file *file, void *priv,
+				struct v4l2_tuner *t)
+{
+	struct cx88_core  *core = ((struct cx8800_fh *)priv)->dev->core;
+
+	if (0 != t->index)
+		return -EINVAL;
+	if (t->audmode > V4L2_TUNER_MODE_STEREO)
+		t->audmode = V4L2_TUNER_MODE_STEREO;
+
+	call_all(core, tuner, s_tuner, t);
+
+	return 0;
+}
+
+/* ----------------------------------------------------------- */
+
+static void cx8800_vid_timeout(unsigned long data)
+{
+	struct cx8800_dev *dev = (struct cx8800_dev*)data;
+	struct cx88_core *core = dev->core;
+	struct cx88_dmaqueue *q = &dev->vidq;
+	struct cx88_buffer *buf;
+	unsigned long flags;
+
+	cx88_sram_channel_dump(core, &cx88_sram_channels[SRAM_CH21]);
+
+	cx_clear(MO_VID_DMACNTRL, 0x11);
+	cx_clear(VID_CAPTURE_CONTROL, 0x06);
+
+	spin_lock_irqsave(&dev->slock,flags);
+	while (!list_empty(&q->active)) {
+		buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
+		list_del(&buf->vb.queue);
+		buf->vb.state = VIDEOBUF_ERROR;
+		wake_up(&buf->vb.done);
+		printk("%s/0: [%p/%d] timeout - dma=0x%08lx\n", core->name,
+		       buf, buf->vb.i, (unsigned long)buf->risc.dma);
+	}
+	restart_video_queue(dev,q);
+	spin_unlock_irqrestore(&dev->slock,flags);
+}
+
+static const char *cx88_vid_irqs[32] = {
+	"y_risci1", "u_risci1", "v_risci1", "vbi_risc1",
+	"y_risci2", "u_risci2", "v_risci2", "vbi_risc2",
+	"y_oflow",  "u_oflow",  "v_oflow",  "vbi_oflow",
+	"y_sync",   "u_sync",   "v_sync",   "vbi_sync",
+	"opc_err",  "par_err",  "rip_err",  "pci_abort",
+};
+
+static void cx8800_vid_irq(struct cx8800_dev *dev)
+{
+	struct cx88_core *core = dev->core;
+	u32 status, mask, count;
+
+	status = cx_read(MO_VID_INTSTAT);
+	mask   = cx_read(MO_VID_INTMSK);
+	if (0 == (status & mask))
+		return;
+	cx_write(MO_VID_INTSTAT, status);
+	if (irq_debug  ||  (status & mask & ~0xff))
+		cx88_print_irqbits(core->name, "irq vid",
+				   cx88_vid_irqs, ARRAY_SIZE(cx88_vid_irqs),
+				   status, mask);
+
+	/* risc op code error */
+	if (status & (1 << 16)) {
+		printk(KERN_WARNING "%s/0: video risc op code error\n",core->name);
+		cx_clear(MO_VID_DMACNTRL, 0x11);
+		cx_clear(VID_CAPTURE_CONTROL, 0x06);
+		cx88_sram_channel_dump(core, &cx88_sram_channels[SRAM_CH21]);
+	}
+
+	/* risc1 y */
+	if (status & 0x01) {
+		spin_lock(&dev->slock);
+		count = cx_read(MO_VIDY_GPCNT);
+		cx88_wakeup(core, &dev->vidq, count);
+		spin_unlock(&dev->slock);
+	}
+
+	/* risc1 vbi */
+	if (status & 0x08) {
+		spin_lock(&dev->slock);
+		count = cx_read(MO_VBI_GPCNT);
+		cx88_wakeup(core, &dev->vbiq, count);
+		spin_unlock(&dev->slock);
+	}
+
+	/* risc2 y */
+	if (status & 0x10) {
+		dprintk(2,"stopper video\n");
+		spin_lock(&dev->slock);
+		restart_video_queue(dev,&dev->vidq);
+		spin_unlock(&dev->slock);
+	}
+
+	/* risc2 vbi */
+	if (status & 0x80) {
+		dprintk(2,"stopper vbi\n");
+		spin_lock(&dev->slock);
+		cx8800_restart_vbi_queue(dev,&dev->vbiq);
+		spin_unlock(&dev->slock);
+	}
+}
+
+static irqreturn_t cx8800_irq(int irq, void *dev_id)
+{
+	struct cx8800_dev *dev = dev_id;
+	struct cx88_core *core = dev->core;
+	u32 status;
+	int loop, handled = 0;
+
+	for (loop = 0; loop < 10; loop++) {
+		status = cx_read(MO_PCI_INTSTAT) &
+			(core->pci_irqmask | PCI_INT_VIDINT);
+		if (0 == status)
+			goto out;
+		cx_write(MO_PCI_INTSTAT, status);
+		handled = 1;
+
+		if (status & core->pci_irqmask)
+			cx88_core_irq(core,status);
+		if (status & PCI_INT_VIDINT)
+			cx8800_vid_irq(dev);
+	};
+	if (10 == loop) {
+		printk(KERN_WARNING "%s/0: irq loop -- clearing mask\n",
+		       core->name);
+		cx_write(MO_PCI_INTMSK,0);
+	}
+
+ out:
+	return IRQ_RETVAL(handled);
+}
+
+/* ----------------------------------------------------------- */
+/* exported stuff                                              */
+
+static const struct v4l2_file_operations video_fops =
+{
+	.owner	       = THIS_MODULE,
+	.open	       = video_open,
+	.release       = video_release,
+	.read	       = video_read,
+	.poll          = video_poll,
+	.mmap	       = video_mmap,
+	.unlocked_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,
+	.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_enum_input    = vidioc_enum_input,
+	.vidioc_g_input       = vidioc_g_input,
+	.vidioc_s_input       = vidioc_s_input,
+	.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,
+	.vidioc_subscribe_event      = v4l2_ctrl_subscribe_event,
+	.vidioc_unsubscribe_event    = v4l2_event_unsubscribe,
+	.vidioc_g_chip_ident  = vidioc_g_chip_ident,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.vidioc_g_register    = vidioc_g_register,
+	.vidioc_s_register    = vidioc_s_register,
+#endif
+};
+
+static const struct video_device cx8800_video_template = {
+	.name                 = "cx8800-video",
+	.fops                 = &video_fops,
+	.ioctl_ops 	      = &video_ioctl_ops,
+	.tvnorms              = CX88_NORMS,
+};
+
+static const struct v4l2_ioctl_ops vbi_ioctl_ops = {
+	.vidioc_querycap      = vidioc_querycap,
+	.vidioc_g_fmt_vbi_cap     = cx8800_vbi_fmt,
+	.vidioc_try_fmt_vbi_cap   = cx8800_vbi_fmt,
+	.vidioc_s_fmt_vbi_cap     = cx8800_vbi_fmt,
+	.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_enum_input    = vidioc_enum_input,
+	.vidioc_g_input       = vidioc_g_input,
+	.vidioc_s_input       = vidioc_s_input,
+	.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,
+	.vidioc_g_chip_ident  = vidioc_g_chip_ident,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.vidioc_g_register    = vidioc_g_register,
+	.vidioc_s_register    = vidioc_s_register,
+#endif
+};
+
+static const struct video_device cx8800_vbi_template = {
+	.name                 = "cx8800-vbi",
+	.fops                 = &video_fops,
+	.ioctl_ops	      = &vbi_ioctl_ops,
+	.tvnorms              = CX88_NORMS,
+};
+
+static const struct v4l2_file_operations radio_fops =
+{
+	.owner         = THIS_MODULE,
+	.open          = video_open,
+	.poll          = v4l2_ctrl_poll,
+	.release       = video_release,
+	.unlocked_ioctl = video_ioctl2,
+};
+
+static const struct v4l2_ioctl_ops radio_ioctl_ops = {
+	.vidioc_querycap      = vidioc_querycap,
+	.vidioc_g_tuner       = radio_g_tuner,
+	.vidioc_s_tuner       = radio_s_tuner,
+	.vidioc_g_frequency   = vidioc_g_frequency,
+	.vidioc_s_frequency   = vidioc_s_frequency,
+	.vidioc_subscribe_event      = v4l2_ctrl_subscribe_event,
+	.vidioc_unsubscribe_event    = v4l2_event_unsubscribe,
+	.vidioc_g_chip_ident  = vidioc_g_chip_ident,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.vidioc_g_register    = vidioc_g_register,
+	.vidioc_s_register    = vidioc_s_register,
+#endif
+};
+
+static const struct video_device cx8800_radio_template = {
+	.name                 = "cx8800-radio",
+	.fops                 = &radio_fops,
+	.ioctl_ops 	      = &radio_ioctl_ops,
+};
+
+static const struct v4l2_ctrl_ops cx8800_ctrl_vid_ops = {
+	.s_ctrl = cx8800_s_vid_ctrl,
+};
+
+static const struct v4l2_ctrl_ops cx8800_ctrl_aud_ops = {
+	.s_ctrl = cx8800_s_aud_ctrl,
+};
+
+/* ----------------------------------------------------------- */
+
+static void cx8800_unregister_video(struct cx8800_dev *dev)
+{
+	if (dev->radio_dev) {
+		if (video_is_registered(dev->radio_dev))
+			video_unregister_device(dev->radio_dev);
+		else
+			video_device_release(dev->radio_dev);
+		dev->radio_dev = NULL;
+	}
+	if (dev->vbi_dev) {
+		if (video_is_registered(dev->vbi_dev))
+			video_unregister_device(dev->vbi_dev);
+		else
+			video_device_release(dev->vbi_dev);
+		dev->vbi_dev = NULL;
+	}
+	if (dev->video_dev) {
+		if (video_is_registered(dev->video_dev))
+			video_unregister_device(dev->video_dev);
+		else
+			video_device_release(dev->video_dev);
+		dev->video_dev = NULL;
+	}
+}
+
+static int __devinit cx8800_initdev(struct pci_dev *pci_dev,
+				    const struct pci_device_id *pci_id)
+{
+	struct cx8800_dev *dev;
+	struct cx88_core *core;
+	int err;
+	int i;
+
+	dev = kzalloc(sizeof(*dev),GFP_KERNEL);
+	if (NULL == dev)
+		return -ENOMEM;
+
+	/* pci init */
+	dev->pci = pci_dev;
+	if (pci_enable_device(pci_dev)) {
+		err = -EIO;
+		goto fail_free;
+	}
+	core = cx88_core_get(dev->pci);
+	if (NULL == core) {
+		err = -EINVAL;
+		goto fail_free;
+	}
+	dev->core = core;
+
+	/* print pci info */
+	dev->pci_rev = pci_dev->revision;
+	pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER,  &dev->pci_lat);
+	printk(KERN_INFO "%s/0: found at %s, rev: %d, irq: %d, "
+	       "latency: %d, mmio: 0x%llx\n", core->name,
+	       pci_name(pci_dev), dev->pci_rev, pci_dev->irq,
+	       dev->pci_lat,(unsigned long long)pci_resource_start(pci_dev,0));
+
+	pci_set_master(pci_dev);
+	if (!pci_dma_supported(pci_dev,DMA_BIT_MASK(32))) {
+		printk("%s/0: Oops: no 32bit PCI DMA ???\n",core->name);
+		err = -EIO;
+		goto fail_core;
+	}
+
+	/* initialize driver struct */
+	spin_lock_init(&dev->slock);
+	core->tvnorm = V4L2_STD_NTSC_M;
+
+	/* init video dma queues */
+	INIT_LIST_HEAD(&dev->vidq.active);
+	INIT_LIST_HEAD(&dev->vidq.queued);
+	dev->vidq.timeout.function = cx8800_vid_timeout;
+	dev->vidq.timeout.data     = (unsigned long)dev;
+	init_timer(&dev->vidq.timeout);
+	cx88_risc_stopper(dev->pci,&dev->vidq.stopper,
+			  MO_VID_DMACNTRL,0x11,0x00);
+
+	/* init vbi dma queues */
+	INIT_LIST_HEAD(&dev->vbiq.active);
+	INIT_LIST_HEAD(&dev->vbiq.queued);
+	dev->vbiq.timeout.function = cx8800_vbi_timeout;
+	dev->vbiq.timeout.data     = (unsigned long)dev;
+	init_timer(&dev->vbiq.timeout);
+	cx88_risc_stopper(dev->pci,&dev->vbiq.stopper,
+			  MO_VID_DMACNTRL,0x88,0x00);
+
+	/* get irq */
+	err = request_irq(pci_dev->irq, cx8800_irq,
+			  IRQF_SHARED | IRQF_DISABLED, core->name, dev);
+	if (err < 0) {
+		printk(KERN_ERR "%s/0: can't get IRQ %d\n",
+		       core->name,pci_dev->irq);
+		goto fail_core;
+	}
+	cx_set(MO_PCI_INTMSK, core->pci_irqmask);
+
+	for (i = 0; i < CX8800_AUD_CTLS; i++) {
+		const struct cx88_ctrl *cc = &cx8800_aud_ctls[i];
+		struct v4l2_ctrl *vc;
+
+		vc = v4l2_ctrl_new_std(&core->audio_hdl, &cx8800_ctrl_aud_ops,
+			cc->id, cc->minimum, cc->maximum, cc->step, cc->default_value);
+		if (vc == NULL) {
+			err = core->audio_hdl.error;
+			goto fail_core;
+		}
+		vc->priv = (void *)cc;
+	}
+
+	for (i = 0; i < CX8800_VID_CTLS; i++) {
+		const struct cx88_ctrl *cc = &cx8800_vid_ctls[i];
+		struct v4l2_ctrl *vc;
+
+		vc = v4l2_ctrl_new_std(&core->video_hdl, &cx8800_ctrl_vid_ops,
+			cc->id, cc->minimum, cc->maximum, cc->step, cc->default_value);
+		if (vc == NULL) {
+			err = core->video_hdl.error;
+			goto fail_core;
+		}
+		vc->priv = (void *)cc;
+		if (vc->id == V4L2_CID_CHROMA_AGC)
+			core->chroma_agc = vc;
+	}
+	v4l2_ctrl_add_handler(&core->video_hdl, &core->audio_hdl);
+
+	/* load and configure helper modules */
+
+	if (core->board.audio_chip == V4L2_IDENT_WM8775) {
+		struct i2c_board_info wm8775_info = {
+			.type = "wm8775",
+			.addr = 0x36 >> 1,
+			.platform_data = &core->wm8775_data,
+		};
+		struct v4l2_subdev *sd;
+
+		if (core->boardnr == CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1)
+			core->wm8775_data.is_nova_s = true;
+		else
+			core->wm8775_data.is_nova_s = false;
+
+		sd = v4l2_i2c_new_subdev_board(&core->v4l2_dev, &core->i2c_adap,
+				&wm8775_info, NULL);
+		if (sd != NULL) {
+			core->sd_wm8775 = sd;
+			sd->grp_id = WM8775_GID;
+		}
+	}
+
+	if (core->board.audio_chip == V4L2_IDENT_TVAUDIO) {
+		/* This probes for a tda9874 as is used on some
+		   Pixelview Ultra boards. */
+		v4l2_i2c_new_subdev(&core->v4l2_dev, &core->i2c_adap,
+				"tvaudio", 0, I2C_ADDRS(0xb0 >> 1));
+	}
+
+	switch (core->boardnr) {
+	case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD:
+	case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD: {
+		static const 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");
+	}
+
+	/* Sets device info at pci_dev */
+	pci_set_drvdata(pci_dev, dev);
+
+	dev->width   = 320;
+	dev->height  = 240;
+	dev->fmt     = format_by_fourcc(V4L2_PIX_FMT_BGR24);
+
+	/* initial device configuration */
+	mutex_lock(&core->lock);
+	cx88_set_tvnorm(core, core->tvnorm);
+	v4l2_ctrl_handler_setup(&core->video_hdl);
+	v4l2_ctrl_handler_setup(&core->audio_hdl);
+	cx88_video_mux(core, 0);
+
+	/* register v4l devices */
+	dev->video_dev = cx88_vdev_init(core,dev->pci,
+					&cx8800_video_template,"video");
+	video_set_drvdata(dev->video_dev, dev);
+	dev->video_dev->ctrl_handler = &core->video_hdl;
+	err = video_register_device(dev->video_dev,VFL_TYPE_GRABBER,
+				    video_nr[core->nr]);
+	if (err < 0) {
+		printk(KERN_ERR "%s/0: can't register video device\n",
+		       core->name);
+		goto fail_unreg;
+	}
+	printk(KERN_INFO "%s/0: registered device %s [v4l2]\n",
+	       core->name, video_device_node_name(dev->video_dev));
+
+	dev->vbi_dev = cx88_vdev_init(core,dev->pci,&cx8800_vbi_template,"vbi");
+	video_set_drvdata(dev->vbi_dev, dev);
+	err = video_register_device(dev->vbi_dev,VFL_TYPE_VBI,
+				    vbi_nr[core->nr]);
+	if (err < 0) {
+		printk(KERN_ERR "%s/0: can't register vbi device\n",
+		       core->name);
+		goto fail_unreg;
+	}
+	printk(KERN_INFO "%s/0: registered device %s\n",
+	       core->name, video_device_node_name(dev->vbi_dev));
+
+	if (core->board.radio.type == CX88_RADIO) {
+		dev->radio_dev = cx88_vdev_init(core,dev->pci,
+						&cx8800_radio_template,"radio");
+		video_set_drvdata(dev->radio_dev, dev);
+		dev->radio_dev->ctrl_handler = &core->audio_hdl;
+		err = video_register_device(dev->radio_dev,VFL_TYPE_RADIO,
+					    radio_nr[core->nr]);
+		if (err < 0) {
+			printk(KERN_ERR "%s/0: can't register radio device\n",
+			       core->name);
+			goto fail_unreg;
+		}
+		printk(KERN_INFO "%s/0: registered device %s\n",
+		       core->name, video_device_node_name(dev->radio_dev));
+	}
+
+	/* start tvaudio thread */
+	if (core->board.tuner_type != TUNER_ABSENT) {
+		core->kthread = kthread_run(cx88_audio_thread, core, "cx88 tvaudio");
+		if (IS_ERR(core->kthread)) {
+			err = PTR_ERR(core->kthread);
+			printk(KERN_ERR "%s/0: failed to create cx88 audio thread, err=%d\n",
+			       core->name, err);
+		}
+	}
+	mutex_unlock(&core->lock);
+
+	return 0;
+
+fail_unreg:
+	cx8800_unregister_video(dev);
+	free_irq(pci_dev->irq, dev);
+	mutex_unlock(&core->lock);
+fail_core:
+	cx88_core_put(core,dev->pci);
+fail_free:
+	kfree(dev);
+	return err;
+}
+
+static void __devexit cx8800_finidev(struct pci_dev *pci_dev)
+{
+	struct cx8800_dev *dev = pci_get_drvdata(pci_dev);
+	struct cx88_core *core = dev->core;
+
+	/* stop thread */
+	if (core->kthread) {
+		kthread_stop(core->kthread);
+		core->kthread = NULL;
+	}
+
+	if (core->ir)
+		cx88_ir_stop(core);
+
+	cx88_shutdown(core); /* FIXME */
+	pci_disable_device(pci_dev);
+
+	/* unregister stuff */
+
+	free_irq(pci_dev->irq, dev);
+	cx8800_unregister_video(dev);
+	pci_set_drvdata(pci_dev, NULL);
+
+	/* free memory */
+	btcx_riscmem_free(dev->pci,&dev->vidq.stopper);
+	cx88_core_put(core,dev->pci);
+	kfree(dev);
+}
+
+#ifdef CONFIG_PM
+static int cx8800_suspend(struct pci_dev *pci_dev, pm_message_t state)
+{
+	struct cx8800_dev *dev = pci_get_drvdata(pci_dev);
+	struct cx88_core *core = dev->core;
+
+	/* stop video+vbi capture */
+	spin_lock(&dev->slock);
+	if (!list_empty(&dev->vidq.active)) {
+		printk("%s/0: suspend video\n", core->name);
+		stop_video_dma(dev);
+		del_timer(&dev->vidq.timeout);
+	}
+	if (!list_empty(&dev->vbiq.active)) {
+		printk("%s/0: suspend vbi\n", core->name);
+		cx8800_stop_vbi_dma(dev);
+		del_timer(&dev->vbiq.timeout);
+	}
+	spin_unlock(&dev->slock);
+
+	if (core->ir)
+		cx88_ir_stop(core);
+	/* FIXME -- shutdown device */
+	cx88_shutdown(core);
+
+	pci_save_state(pci_dev);
+	if (0 != pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state))) {
+		pci_disable_device(pci_dev);
+		dev->state.disabled = 1;
+	}
+	return 0;
+}
+
+static int cx8800_resume(struct pci_dev *pci_dev)
+{
+	struct cx8800_dev *dev = pci_get_drvdata(pci_dev);
+	struct cx88_core *core = dev->core;
+	int err;
+
+	if (dev->state.disabled) {
+		err=pci_enable_device(pci_dev);
+		if (err) {
+			printk(KERN_ERR "%s/0: can't enable device\n",
+			       core->name);
+			return err;
+		}
+
+		dev->state.disabled = 0;
+	}
+	err= pci_set_power_state(pci_dev, PCI_D0);
+	if (err) {
+		printk(KERN_ERR "%s/0: can't set power state\n", core->name);
+		pci_disable_device(pci_dev);
+		dev->state.disabled = 1;
+
+		return err;
+	}
+	pci_restore_state(pci_dev);
+
+	/* FIXME: re-initialize hardware */
+	cx88_reset(core);
+	if (core->ir)
+		cx88_ir_start(core);
+
+	cx_set(MO_PCI_INTMSK, core->pci_irqmask);
+
+	/* restart video+vbi capture */
+	spin_lock(&dev->slock);
+	if (!list_empty(&dev->vidq.active)) {
+		printk("%s/0: resume video\n", core->name);
+		restart_video_queue(dev,&dev->vidq);
+	}
+	if (!list_empty(&dev->vbiq.active)) {
+		printk("%s/0: resume vbi\n", core->name);
+		cx8800_restart_vbi_queue(dev,&dev->vbiq);
+	}
+	spin_unlock(&dev->slock);
+
+	return 0;
+}
+#endif
+
+/* ----------------------------------------------------------- */
+
+static const struct pci_device_id cx8800_pci_tbl[] = {
+	{
+		.vendor       = 0x14f1,
+		.device       = 0x8800,
+		.subvendor    = PCI_ANY_ID,
+		.subdevice    = PCI_ANY_ID,
+	},{
+		/* --- end of list --- */
+	}
+};
+MODULE_DEVICE_TABLE(pci, cx8800_pci_tbl);
+
+static struct pci_driver cx8800_pci_driver = {
+	.name     = "cx8800",
+	.id_table = cx8800_pci_tbl,
+	.probe    = cx8800_initdev,
+	.remove   = __devexit_p(cx8800_finidev),
+#ifdef CONFIG_PM
+	.suspend  = cx8800_suspend,
+	.resume   = cx8800_resume,
+#endif
+};
+
+static int __init cx8800_init(void)
+{
+	printk(KERN_INFO "cx88/0: cx2388x v4l2 driver version %s loaded\n",
+	       CX88_VERSION);
+	return pci_register_driver(&cx8800_pci_driver);
+}
+
+static void __exit cx8800_fini(void)
+{
+	pci_unregister_driver(&cx8800_pci_driver);
+}
+
+module_init(cx8800_init);
+module_exit(cx8800_fini);
diff --git a/drivers/media/pci/cx88/cx88-vp3054-i2c.c b/drivers/media/pci/cx88/cx88-vp3054-i2c.c
new file mode 100644
index 0000000..d77f8ec
--- /dev/null
+++ b/drivers/media/pci/cx88/cx88-vp3054-i2c.c
@@ -0,0 +1,159 @@
+/*
+
+    cx88-vp3054-i2c.c  --  support for the secondary I2C bus of the
+			   DNTV Live! DVB-T Pro (VP-3054), wired as:
+			   GPIO[0] -> SCL, GPIO[1] -> SDA
+
+    (c) 2005 Chris Pascoe <c.pascoe@itee.uq.edu.au>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You 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/slab.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+
+#include "cx88.h"
+#include "cx88-vp3054-i2c.h"
+
+MODULE_DESCRIPTION("driver for cx2388x VP3054 design");
+MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>");
+MODULE_LICENSE("GPL");
+
+/* ----------------------------------------------------------------------- */
+
+static void vp3054_bit_setscl(void *data, int state)
+{
+	struct cx8802_dev *dev = data;
+	struct cx88_core *core = dev->core;
+	struct vp3054_i2c_state *vp3054_i2c = dev->vp3054;
+
+	if (state) {
+		vp3054_i2c->state |=  0x0001;	/* SCL high */
+		vp3054_i2c->state &= ~0x0100;	/* external pullup */
+	} else {
+		vp3054_i2c->state &= ~0x0001;	/* SCL low */
+		vp3054_i2c->state |=  0x0100;	/* drive pin */
+	}
+	cx_write(MO_GP0_IO, 0x010000 | vp3054_i2c->state);
+	cx_read(MO_GP0_IO);
+}
+
+static void vp3054_bit_setsda(void *data, int state)
+{
+	struct cx8802_dev *dev = data;
+	struct cx88_core *core = dev->core;
+	struct vp3054_i2c_state *vp3054_i2c = dev->vp3054;
+
+	if (state) {
+		vp3054_i2c->state |=  0x0002;	/* SDA high */
+		vp3054_i2c->state &= ~0x0200;	/* tristate pin */
+	} else {
+		vp3054_i2c->state &= ~0x0002;	/* SDA low */
+		vp3054_i2c->state |=  0x0200;	/* drive pin */
+	}
+	cx_write(MO_GP0_IO, 0x020000 | vp3054_i2c->state);
+	cx_read(MO_GP0_IO);
+}
+
+static int vp3054_bit_getscl(void *data)
+{
+	struct cx8802_dev *dev = data;
+	struct cx88_core *core = dev->core;
+	u32 state;
+
+	state = cx_read(MO_GP0_IO);
+	return (state & 0x01) ? 1 : 0;
+}
+
+static int vp3054_bit_getsda(void *data)
+{
+	struct cx8802_dev *dev = data;
+	struct cx88_core *core = dev->core;
+	u32 state;
+
+	state = cx_read(MO_GP0_IO);
+	return (state & 0x02) ? 1 : 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static const struct i2c_algo_bit_data vp3054_i2c_algo_template = {
+	.setsda  = vp3054_bit_setsda,
+	.setscl  = vp3054_bit_setscl,
+	.getsda  = vp3054_bit_getsda,
+	.getscl  = vp3054_bit_getscl,
+	.udelay  = 16,
+	.timeout = 200,
+};
+
+/* ----------------------------------------------------------------------- */
+
+int vp3054_i2c_probe(struct cx8802_dev *dev)
+{
+	struct cx88_core *core = dev->core;
+	struct vp3054_i2c_state *vp3054_i2c;
+	int rc;
+
+	if (core->boardnr != CX88_BOARD_DNTV_LIVE_DVB_T_PRO)
+		return 0;
+
+	vp3054_i2c = kzalloc(sizeof(*vp3054_i2c), GFP_KERNEL);
+	if (vp3054_i2c == NULL)
+		return -ENOMEM;
+	dev->vp3054 = vp3054_i2c;
+
+	memcpy(&vp3054_i2c->algo, &vp3054_i2c_algo_template,
+	       sizeof(vp3054_i2c->algo));
+
+	vp3054_i2c->adap.dev.parent = &dev->pci->dev;
+	strlcpy(vp3054_i2c->adap.name, core->name,
+		sizeof(vp3054_i2c->adap.name));
+	vp3054_i2c->adap.owner = THIS_MODULE;
+	vp3054_i2c->algo.data = dev;
+	i2c_set_adapdata(&vp3054_i2c->adap, dev);
+	vp3054_i2c->adap.algo_data = &vp3054_i2c->algo;
+
+	vp3054_bit_setscl(dev,1);
+	vp3054_bit_setsda(dev,1);
+
+	rc = i2c_bit_add_bus(&vp3054_i2c->adap);
+	if (0 != rc) {
+		printk("%s: vp3054_i2c register FAILED\n", core->name);
+
+		kfree(dev->vp3054);
+		dev->vp3054 = NULL;
+	}
+
+	return rc;
+}
+
+void vp3054_i2c_remove(struct cx8802_dev *dev)
+{
+	struct vp3054_i2c_state *vp3054_i2c = dev->vp3054;
+
+	if (vp3054_i2c == NULL ||
+	    dev->core->boardnr != CX88_BOARD_DNTV_LIVE_DVB_T_PRO)
+		return;
+
+	i2c_del_adapter(&vp3054_i2c->adap);
+	kfree(vp3054_i2c);
+}
+
+EXPORT_SYMBOL(vp3054_i2c_probe);
+EXPORT_SYMBOL(vp3054_i2c_remove);
diff --git a/drivers/media/pci/cx88/cx88-vp3054-i2c.h b/drivers/media/pci/cx88/cx88-vp3054-i2c.h
new file mode 100644
index 0000000..be99c93
--- /dev/null
+++ b/drivers/media/pci/cx88/cx88-vp3054-i2c.h
@@ -0,0 +1,41 @@
+/*
+
+    cx88-vp3054-i2c.h  --  support for the secondary I2C bus of the
+			   DNTV Live! DVB-T Pro (VP-3054), wired as:
+			   GPIO[0] -> SCL, GPIO[1] -> SDA
+
+    (c) 2005 Chris Pascoe <c.pascoe@itee.uq.edu.au>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You 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.
+
+*/
+
+/* ----------------------------------------------------------------------- */
+struct vp3054_i2c_state {
+	struct i2c_adapter         adap;
+	struct i2c_algo_bit_data   algo;
+	u32                        state;
+};
+
+/* ----------------------------------------------------------------------- */
+#if defined(CONFIG_VIDEO_CX88_VP3054) || (defined(CONFIG_VIDEO_CX88_VP3054_MODULE) && defined(MODULE))
+int  vp3054_i2c_probe(struct cx8802_dev *dev);
+void vp3054_i2c_remove(struct cx8802_dev *dev);
+#else
+static inline int  vp3054_i2c_probe(struct cx8802_dev *dev)
+{ return 0; }
+static inline void vp3054_i2c_remove(struct cx8802_dev *dev)
+{ }
+#endif
diff --git a/drivers/media/pci/cx88/cx88.h b/drivers/media/pci/cx88/cx88.h
new file mode 100644
index 0000000..44ffc8b
--- /dev/null
+++ b/drivers/media/pci/cx88/cx88.h
@@ -0,0 +1,748 @@
+/*
+ *
+ * v4l2 device driver for cx2388x based TV cards
+ *
+ * (c) 2003,04 Gerd Knorr <kraxel@bytesex.org> [SUSE Labs]
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the 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/pci.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+#include <linux/videodev2.h>
+#include <linux/kdev_t.h>
+
+#include <media/v4l2-device.h>
+#include <media/v4l2-fh.h>
+#include <media/tuner.h>
+#include <media/tveeprom.h>
+#include <media/videobuf-dma-sg.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/cx2341x.h>
+#include <media/videobuf-dvb.h>
+#include <media/ir-kbd-i2c.h>
+#include <media/wm8775.h>
+
+#include "btcx-risc.h"
+#include "cx88-reg.h"
+#include "tuner-xc2028.h"
+
+#include <linux/mutex.h>
+
+#define CX88_VERSION "0.0.9"
+
+#define UNSET (-1U)
+
+#define CX88_MAXBOARDS 8
+
+/* Max number of inputs by card */
+#define MAX_CX88_INPUT 8
+
+/* ----------------------------------------------------------- */
+/* defines and enums                                           */
+
+/* Currently unsupported by the driver: PAL/H, NTSC/Kr, SECAM/LC */
+#define CX88_NORMS (V4L2_STD_ALL 		\
+		    & ~V4L2_STD_PAL_H		\
+		    & ~V4L2_STD_NTSC_M_KR	\
+		    & ~V4L2_STD_SECAM_LC)
+
+#define FORMAT_FLAGS_PACKED       0x01
+#define FORMAT_FLAGS_PLANAR       0x02
+
+#define VBI_LINE_COUNT              17
+#define VBI_LINE_LENGTH           2048
+
+#define AUD_RDS_LINES		     4
+
+/* need "shadow" registers for some write-only ones ... */
+#define SHADOW_AUD_VOL_CTL           1
+#define SHADOW_AUD_BAL_CTL           2
+#define SHADOW_MAX                   3
+
+/* FM Radio deemphasis type */
+enum cx88_deemph_type {
+	FM_NO_DEEMPH = 0,
+	FM_DEEMPH_50,
+	FM_DEEMPH_75
+};
+
+enum cx88_board_type {
+	CX88_BOARD_NONE = 0,
+	CX88_MPEG_DVB,
+	CX88_MPEG_BLACKBIRD
+};
+
+enum cx8802_board_access {
+	CX8802_DRVCTL_SHARED    = 1,
+	CX8802_DRVCTL_EXCLUSIVE = 2,
+};
+
+/* ----------------------------------------------------------- */
+/* tv norms                                                    */
+
+static unsigned int inline norm_maxw(v4l2_std_id norm)
+{
+	return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 720 : 768;
+}
+
+
+static unsigned int inline norm_maxh(v4l2_std_id norm)
+{
+	return (norm & V4L2_STD_625_50) ? 576 : 480;
+}
+
+/* ----------------------------------------------------------- */
+/* static data                                                 */
+
+struct cx8800_fmt {
+	const char  *name;
+	u32   fourcc;          /* v4l2 format id */
+	int   depth;
+	int   flags;
+	u32   cxformat;
+};
+
+/* ----------------------------------------------------------- */
+/* SRAM memory management data (see cx88-core.c)               */
+
+#define SRAM_CH21 0   /* video */
+#define SRAM_CH22 1
+#define SRAM_CH23 2
+#define SRAM_CH24 3   /* vbi   */
+#define SRAM_CH25 4   /* audio */
+#define SRAM_CH26 5
+#define SRAM_CH28 6   /* mpeg */
+#define SRAM_CH27 7   /* audio rds */
+/* more */
+
+struct sram_channel {
+	const char *name;
+	u32  cmds_start;
+	u32  ctrl_start;
+	u32  cdt;
+	u32  fifo_start;
+	u32  fifo_size;
+	u32  ptr1_reg;
+	u32  ptr2_reg;
+	u32  cnt1_reg;
+	u32  cnt2_reg;
+};
+extern const struct sram_channel cx88_sram_channels[];
+
+/* ----------------------------------------------------------- */
+/* card configuration                                          */
+
+#define CX88_BOARD_NOAUTO               UNSET
+#define CX88_BOARD_UNKNOWN                  0
+#define CX88_BOARD_HAUPPAUGE                1
+#define CX88_BOARD_GDI                      2
+#define CX88_BOARD_PIXELVIEW                3
+#define CX88_BOARD_ATI_WONDER_PRO           4
+#define CX88_BOARD_WINFAST2000XP_EXPERT     5
+#define CX88_BOARD_AVERTV_STUDIO_303        6
+#define CX88_BOARD_MSI_TVANYWHERE_MASTER    7
+#define CX88_BOARD_WINFAST_DV2000           8
+#define CX88_BOARD_LEADTEK_PVR2000          9
+#define CX88_BOARD_IODATA_GVVCP3PCI        10
+#define CX88_BOARD_PROLINK_PLAYTVPVR       11
+#define CX88_BOARD_ASUS_PVR_416            12
+#define CX88_BOARD_MSI_TVANYWHERE          13
+#define CX88_BOARD_KWORLD_DVB_T            14
+#define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1 15
+#define CX88_BOARD_KWORLD_LTV883           16
+#define CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q  17
+#define CX88_BOARD_HAUPPAUGE_DVB_T1        18
+#define CX88_BOARD_CONEXANT_DVB_T1         19
+#define CX88_BOARD_PROVIDEO_PV259          20
+#define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS 21
+#define CX88_BOARD_PCHDTV_HD3000           22
+#define CX88_BOARD_DNTV_LIVE_DVB_T         23
+#define CX88_BOARD_HAUPPAUGE_ROSLYN        24
+#define CX88_BOARD_DIGITALLOGIC_MEC        25
+#define CX88_BOARD_IODATA_GVBCTV7E         26
+#define CX88_BOARD_PIXELVIEW_PLAYTV_ULTRA_PRO 27
+#define CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T  28
+#define CX88_BOARD_ADSTECH_DVB_T_PCI          29
+#define CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1  30
+#define CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD 31
+#define CX88_BOARD_AVERMEDIA_ULTRATV_MC_550 32
+#define CX88_BOARD_KWORLD_VSTREAM_EXPERT_DVD 33
+#define CX88_BOARD_ATI_HDTVWONDER          34
+#define CX88_BOARD_WINFAST_DTV1000         35
+#define CX88_BOARD_AVERTV_303              36
+#define CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1  37
+#define CX88_BOARD_HAUPPAUGE_NOVASE2_S1    38
+#define CX88_BOARD_KWORLD_DVBS_100         39
+#define CX88_BOARD_HAUPPAUGE_HVR1100       40
+#define CX88_BOARD_HAUPPAUGE_HVR1100LP     41
+#define CX88_BOARD_DNTV_LIVE_DVB_T_PRO     42
+#define CX88_BOARD_KWORLD_DVB_T_CX22702    43
+#define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL 44
+#define CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT 45
+#define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID 46
+#define CX88_BOARD_PCHDTV_HD5500           47
+#define CX88_BOARD_KWORLD_MCE200_DELUXE    48
+#define CX88_BOARD_PIXELVIEW_PLAYTV_P7000  49
+#define CX88_BOARD_NPGTECH_REALTV_TOP10FM  50
+#define CX88_BOARD_WINFAST_DTV2000H        51
+#define CX88_BOARD_GENIATECH_DVBS          52
+#define CX88_BOARD_HAUPPAUGE_HVR3000       53
+#define CX88_BOARD_NORWOOD_MICRO           54
+#define CX88_BOARD_TE_DTV_250_OEM_SWANN    55
+#define CX88_BOARD_HAUPPAUGE_HVR1300       56
+#define CX88_BOARD_ADSTECH_PTV_390         57
+#define CX88_BOARD_PINNACLE_PCTV_HD_800i   58
+#define CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO 59
+#define CX88_BOARD_PINNACLE_HYBRID_PCTV    60
+#define CX88_BOARD_WINFAST_TV2000_XP_GLOBAL 61
+#define CX88_BOARD_POWERCOLOR_REAL_ANGEL   62
+#define CX88_BOARD_GENIATECH_X8000_MT      63
+#define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO 64
+#define CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD 65
+#define CX88_BOARD_PROLINK_PV_8000GT       66
+#define CX88_BOARD_KWORLD_ATSC_120         67
+#define CX88_BOARD_HAUPPAUGE_HVR4000       68
+#define CX88_BOARD_HAUPPAUGE_HVR4000LITE   69
+#define CX88_BOARD_TEVII_S460              70
+#define CX88_BOARD_OMICOM_SS4_PCI          71
+#define CX88_BOARD_TBS_8920                72
+#define CX88_BOARD_TEVII_S420              73
+#define CX88_BOARD_PROLINK_PV_GLOBAL_XTREME 74
+#define CX88_BOARD_PROF_7300               75
+#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
+#define CX88_BOARD_HAUPPAUGE_IRONLY        80
+#define CX88_BOARD_WINFAST_DTV1800H        81
+#define CX88_BOARD_WINFAST_DTV2000H_J      82
+#define CX88_BOARD_PROF_7301               83
+#define CX88_BOARD_SAMSUNG_SMT_7020        84
+#define CX88_BOARD_TWINHAN_VP1027_DVBS     85
+#define CX88_BOARD_TEVII_S464              86
+#define CX88_BOARD_WINFAST_DTV2000H_PLUS   87
+#define CX88_BOARD_WINFAST_DTV1800H_XC4000 88
+#define CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F36 89
+#define CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F43 90
+
+enum cx88_itype {
+	CX88_VMUX_COMPOSITE1 = 1,
+	CX88_VMUX_COMPOSITE2,
+	CX88_VMUX_COMPOSITE3,
+	CX88_VMUX_COMPOSITE4,
+	CX88_VMUX_SVIDEO,
+	CX88_VMUX_TELEVISION,
+	CX88_VMUX_CABLE,
+	CX88_VMUX_DVB,
+	CX88_VMUX_DEBUG,
+	CX88_RADIO,
+};
+
+struct cx88_input {
+	enum cx88_itype type;
+	u32             gpio0, gpio1, gpio2, gpio3;
+	unsigned int    vmux:2;
+	unsigned int    audioroute:4;
+};
+
+struct cx88_board {
+	const char              *name;
+	unsigned int            tuner_type;
+	unsigned int		radio_type;
+	unsigned char		tuner_addr;
+	unsigned char		radio_addr;
+	int                     tda9887_conf;
+	struct cx88_input       input[MAX_CX88_INPUT];
+	struct cx88_input       radio;
+	enum cx88_board_type    mpeg;
+	unsigned int            audio_chip;
+	int			num_frontends;
+
+	/* Used for I2S devices */
+	int			i2sinputcntl;
+};
+
+struct cx88_subid {
+	u16     subvendor;
+	u16     subdevice;
+	u32     card;
+};
+
+enum cx88_tvaudio {
+	WW_NONE = 1,
+	WW_BTSC,
+	WW_BG,
+	WW_DK,
+	WW_I,
+	WW_L,
+	WW_EIAJ,
+	WW_I2SPT,
+	WW_FM,
+	WW_I2SADC,
+	WW_M
+};
+
+#define INPUT(nr) (core->board.input[nr])
+
+/* ----------------------------------------------------------- */
+/* device / file handle status                                 */
+
+#define RESOURCE_OVERLAY       1
+#define RESOURCE_VIDEO         2
+#define RESOURCE_VBI           4
+
+#define BUFFER_TIMEOUT     msecs_to_jiffies(2000)
+
+/* buffer for one video frame */
+struct cx88_buffer {
+	/* common v4l buffer stuff -- must be first */
+	struct videobuf_buffer vb;
+
+	/* cx88 specific */
+	unsigned int           bpl;
+	struct btcx_riscmem    risc;
+	const struct cx8800_fmt *fmt;
+	u32                    count;
+};
+
+struct cx88_dmaqueue {
+	struct list_head       active;
+	struct list_head       queued;
+	struct timer_list      timeout;
+	struct btcx_riscmem    stopper;
+	u32                    count;
+};
+
+struct cx88_core {
+	struct list_head           devlist;
+	atomic_t                   refcount;
+
+	/* board name */
+	int                        nr;
+	char                       name[32];
+
+	/* pci stuff */
+	int                        pci_bus;
+	int                        pci_slot;
+	u32                        __iomem *lmmio;
+	u8                         __iomem *bmmio;
+	u32                        shadow[SHADOW_MAX];
+	int                        pci_irqmask;
+
+	/* i2c i/o */
+	struct i2c_adapter         i2c_adap;
+	struct i2c_algo_bit_data   i2c_algo;
+	struct i2c_client          i2c_client;
+	u32                        i2c_state, i2c_rc;
+
+	/* config info -- analog */
+	struct v4l2_device 	   v4l2_dev;
+	struct v4l2_ctrl_handler   video_hdl;
+	struct v4l2_ctrl	   *chroma_agc;
+	struct v4l2_ctrl_handler   audio_hdl;
+	struct v4l2_subdev	   *sd_wm8775;
+	struct i2c_client 	   *i2c_rtc;
+	unsigned int               boardnr;
+	struct cx88_board	   board;
+
+	/* Supported V4L _STD_ tuner formats */
+	unsigned int               tuner_formats;
+
+	/* config info -- dvb */
+#if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE)
+	int 			   (*prev_set_voltage)(struct dvb_frontend *fe, fe_sec_voltage_t voltage);
+#endif
+	void			   (*gate_ctrl)(struct cx88_core  *core, int open);
+
+	/* state info */
+	struct task_struct         *kthread;
+	v4l2_std_id                tvnorm;
+	enum cx88_tvaudio          tvaudio;
+	u32                        audiomode_manual;
+	u32                        audiomode_current;
+	u32                        input;
+	u32                        last_analog_input;
+	u32                        astat;
+	u32			   use_nicam;
+	unsigned long		   last_change;
+
+	/* IR remote control state */
+	struct cx88_IR             *ir;
+
+	/* I2C remote data */
+	struct IR_i2c_init_data    init_data;
+	struct wm8775_platform_data wm8775_data;
+
+	struct mutex               lock;
+	/* various v4l controls */
+	u32                        freq;
+	int                        users;
+	int                        mpeg_users;
+
+	/* cx88-video needs to access cx8802 for hybrid tuner pll access. */
+	struct cx8802_dev          *dvbdev;
+	enum cx88_board_type       active_type_id;
+	int			   active_ref;
+	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_hw(core, grpid, o, f, args...) \
+	do {							\
+		if (!core->i2c_rc) {				\
+			if (core->gate_ctrl)			\
+				core->gate_ctrl(core, 1);	\
+			v4l2_device_call_all(&core->v4l2_dev, grpid, o, f, ##args); \
+			if (core->gate_ctrl)			\
+				core->gate_ctrl(core, 0);	\
+		}						\
+	} while (0)
+
+#define call_all(core, o, f, args...) call_hw(core, 0, o, f, ##args)
+
+#define WM8775_GID      (1 << 0)
+
+#define wm8775_s_ctrl(core, id, val) \
+	do {									\
+		struct v4l2_ctrl *ctrl_ =					\
+			v4l2_ctrl_find(core->sd_wm8775->ctrl_handler, id);	\
+		if (ctrl_ && !core->i2c_rc) {					\
+			if (core->gate_ctrl)					\
+				core->gate_ctrl(core, 1);			\
+			v4l2_ctrl_s_ctrl(ctrl_, val);				\
+			if (core->gate_ctrl)					\
+				core->gate_ctrl(core, 0);			\
+		}								\
+	} while (0)
+
+#define wm8775_g_ctrl(core, id) \
+	({									\
+		struct v4l2_ctrl *ctrl_ =					\
+			v4l2_ctrl_find(core->sd_wm8775->ctrl_handler, id);	\
+		s32 val = 0;							\
+		if (ctrl_ && !core->i2c_rc) {					\
+			if (core->gate_ctrl)					\
+				core->gate_ctrl(core, 1);			\
+			val = v4l2_ctrl_g_ctrl(ctrl_);				\
+			if (core->gate_ctrl)					\
+				core->gate_ctrl(core, 0);			\
+		}								\
+		val;								\
+	})
+
+struct cx8800_dev;
+struct cx8802_dev;
+
+/* ----------------------------------------------------------- */
+/* function 0: video stuff                                     */
+
+struct cx8800_fh {
+	struct v4l2_fh		   fh;
+	struct cx8800_dev          *dev;
+	unsigned int               resources;
+
+	/* video capture */
+	struct videobuf_queue      vidq;
+
+	/* vbi capture */
+	struct videobuf_queue      vbiq;
+};
+
+struct cx8800_suspend_state {
+	int                        disabled;
+};
+
+struct cx8800_dev {
+	struct cx88_core           *core;
+	spinlock_t                 slock;
+
+	/* various device info */
+	unsigned int               resources;
+	struct video_device        *video_dev;
+	struct video_device        *vbi_dev;
+	struct video_device        *radio_dev;
+
+	/* pci i/o */
+	struct pci_dev             *pci;
+	unsigned char              pci_rev,pci_lat;
+
+	const struct cx8800_fmt    *fmt;
+	unsigned int               width, height;
+
+	/* capture queues */
+	struct cx88_dmaqueue       vidq;
+	struct cx88_dmaqueue       vbiq;
+
+	/* various v4l controls */
+
+	/* other global state info */
+	struct cx8800_suspend_state state;
+};
+
+/* ----------------------------------------------------------- */
+/* function 1: audio/alsa stuff                                */
+/* =============> moved to cx88-alsa.c <====================== */
+
+
+/* ----------------------------------------------------------- */
+/* function 2: mpeg stuff                                      */
+
+struct cx8802_fh {
+	struct v4l2_fh		   fh;
+	struct cx8802_dev          *dev;
+	struct videobuf_queue      mpegq;
+};
+
+struct cx8802_suspend_state {
+	int                        disabled;
+};
+
+struct cx8802_driver {
+	struct cx88_core *core;
+
+	/* List of drivers attached to device */
+	struct list_head drvlist;
+
+	/* Type of driver and access required */
+	enum cx88_board_type type_id;
+	enum cx8802_board_access hw_access;
+
+	/* MPEG 8802 internal only */
+	int (*suspend)(struct pci_dev *pci_dev, pm_message_t state);
+	int (*resume)(struct pci_dev *pci_dev);
+
+	/* Callers to the following functions must hold core->lock */
+
+	/* MPEG 8802 -> mini driver - Driver probe and configuration */
+	int (*probe)(struct cx8802_driver *drv);
+	int (*remove)(struct cx8802_driver *drv);
+
+	/* MPEG 8802 -> mini driver - Access for hardware control */
+	int (*advise_acquire)(struct cx8802_driver *drv);
+	int (*advise_release)(struct cx8802_driver *drv);
+
+	/* MPEG 8802 <- mini driver - Access for hardware control */
+	int (*request_acquire)(struct cx8802_driver *drv);
+	int (*request_release)(struct cx8802_driver *drv);
+};
+
+struct cx8802_dev {
+	struct cx88_core           *core;
+	spinlock_t                 slock;
+
+	/* pci i/o */
+	struct pci_dev             *pci;
+	unsigned char              pci_rev,pci_lat;
+
+	/* dma queues */
+	struct cx88_dmaqueue       mpegq;
+	u32                        ts_packet_size;
+	u32                        ts_packet_count;
+
+	/* other global state info */
+	struct cx8802_suspend_state state;
+
+	/* for blackbird only */
+	struct list_head           devlist;
+#if defined(CONFIG_VIDEO_CX88_BLACKBIRD) || \
+    defined(CONFIG_VIDEO_CX88_BLACKBIRD_MODULE)
+	struct video_device        *mpeg_dev;
+	u32                        mailbox;
+	int                        width;
+	int                        height;
+	unsigned char              mpeg_active; /* nonzero if mpeg encoder is active */
+
+	/* mpeg params */
+	struct cx2341x_handler     cxhdl;
+#endif
+
+#if defined(CONFIG_VIDEO_CX88_DVB) || defined(CONFIG_VIDEO_CX88_DVB_MODULE)
+	/* for dvb only */
+	struct videobuf_dvb_frontends frontends;
+#endif
+
+#if defined(CONFIG_VIDEO_CX88_VP3054) || \
+    defined(CONFIG_VIDEO_CX88_VP3054_MODULE)
+	/* For VP3045 secondary I2C bus support */
+	struct vp3054_i2c_state	   *vp3054;
+#endif
+	/* for switching modulation types */
+	unsigned char              ts_gen_cntrl;
+
+	/* List of attached drivers; must hold core->lock to access */
+	struct list_head	   drvlist;
+
+	struct work_struct	   request_module_wk;
+};
+
+/* ----------------------------------------------------------- */
+
+#define cx_read(reg)             readl(core->lmmio + ((reg)>>2))
+#define cx_write(reg,value)      writel((value), core->lmmio + ((reg)>>2))
+#define cx_writeb(reg,value)     writeb((value), core->bmmio + (reg))
+
+#define cx_andor(reg,mask,value) \
+  writel((readl(core->lmmio+((reg)>>2)) & ~(mask)) |\
+  ((value) & (mask)), core->lmmio+((reg)>>2))
+#define cx_set(reg,bit)          cx_andor((reg),(bit),(bit))
+#define cx_clear(reg,bit)        cx_andor((reg),(bit),0)
+
+#define cx_wait(d) { if (need_resched()) schedule(); else udelay(d); }
+
+/* shadow registers */
+#define cx_sread(sreg)		    (core->shadow[sreg])
+#define cx_swrite(sreg,reg,value) \
+  (core->shadow[sreg] = value, \
+   writel(core->shadow[sreg], core->lmmio + ((reg)>>2)))
+#define cx_sandor(sreg,reg,mask,value) \
+  (core->shadow[sreg] = (core->shadow[sreg] & ~(mask)) | ((value) & (mask)), \
+   writel(core->shadow[sreg], core->lmmio + ((reg)>>2)))
+
+/* ----------------------------------------------------------- */
+/* cx88-core.c                                                 */
+
+extern void cx88_print_irqbits(const char *name, const char *tag, const char *strings[],
+			       int len, u32 bits, u32 mask);
+
+extern int cx88_core_irq(struct cx88_core *core, u32 status);
+extern void cx88_wakeup(struct cx88_core *core,
+			struct cx88_dmaqueue *q, u32 count);
+extern void cx88_shutdown(struct cx88_core *core);
+extern int cx88_reset(struct cx88_core *core);
+
+extern int
+cx88_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
+		 struct scatterlist *sglist,
+		 unsigned int top_offset, unsigned int bottom_offset,
+		 unsigned int bpl, unsigned int padding, unsigned int lines);
+extern int
+cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc,
+		     struct scatterlist *sglist, unsigned int bpl,
+		     unsigned int lines, unsigned int lpi);
+extern int
+cx88_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
+		  u32 reg, u32 mask, u32 value);
+extern void
+cx88_free_buffer(struct videobuf_queue *q, struct cx88_buffer *buf);
+
+extern void cx88_risc_disasm(struct cx88_core *core,
+			     struct btcx_riscmem *risc);
+extern int cx88_sram_channel_setup(struct cx88_core *core,
+				   const struct sram_channel *ch,
+				   unsigned int bpl, u32 risc);
+extern void cx88_sram_channel_dump(struct cx88_core *core,
+				   const struct sram_channel *ch);
+
+extern int cx88_set_scale(struct cx88_core *core, unsigned int width,
+			  unsigned int height, enum v4l2_field field);
+extern int cx88_set_tvnorm(struct cx88_core *core, v4l2_std_id norm);
+
+extern struct video_device *cx88_vdev_init(struct cx88_core *core,
+					   struct pci_dev *pci,
+					   const struct video_device *template_,
+					   const char *type);
+extern struct cx88_core* cx88_core_get(struct pci_dev *pci);
+extern void cx88_core_put(struct cx88_core *core,
+			  struct pci_dev *pci);
+
+extern int cx88_start_audio_dma(struct cx88_core *core);
+extern int cx88_stop_audio_dma(struct cx88_core *core);
+
+
+/* ----------------------------------------------------------- */
+/* cx88-vbi.c                                                  */
+
+/* Can be used as g_vbi_fmt, try_vbi_fmt and s_vbi_fmt */
+int cx8800_vbi_fmt (struct file *file, void *priv,
+					struct v4l2_format *f);
+
+/*
+int cx8800_start_vbi_dma(struct cx8800_dev    *dev,
+			 struct cx88_dmaqueue *q,
+			 struct cx88_buffer   *buf);
+*/
+int cx8800_stop_vbi_dma(struct cx8800_dev *dev);
+int cx8800_restart_vbi_queue(struct cx8800_dev    *dev,
+			     struct cx88_dmaqueue *q);
+void cx8800_vbi_timeout(unsigned long data);
+
+extern const struct videobuf_queue_ops cx8800_vbi_qops;
+
+/* ----------------------------------------------------------- */
+/* cx88-i2c.c                                                  */
+
+extern int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci);
+
+
+/* ----------------------------------------------------------- */
+/* cx88-cards.c                                                */
+
+extern int cx88_tuner_callback(void *dev, int component, int command, int arg);
+extern int cx88_get_resources(const struct cx88_core *core,
+			      struct pci_dev *pci);
+extern struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr);
+extern void cx88_setup_xc3028(struct cx88_core *core, struct xc2028_ctrl *ctl);
+
+/* ----------------------------------------------------------- */
+/* cx88-tvaudio.c                                              */
+
+void cx88_set_tvaudio(struct cx88_core *core);
+void cx88_newstation(struct cx88_core *core);
+void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t);
+void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual);
+int cx88_audio_thread(void *data);
+
+int cx8802_register_driver(struct cx8802_driver *drv);
+int cx8802_unregister_driver(struct cx8802_driver *drv);
+
+/* Caller must hold core->lock */
+struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board_type btype);
+
+/* ----------------------------------------------------------- */
+/* cx88-dsp.c                                                  */
+
+s32 cx88_dsp_detect_stereo_sap(struct cx88_core *core);
+
+/* ----------------------------------------------------------- */
+/* cx88-input.c                                                */
+
+int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci);
+int cx88_ir_fini(struct cx88_core *core);
+void cx88_ir_irq(struct cx88_core *core);
+int cx88_ir_start(struct cx88_core *core);
+void cx88_ir_stop(struct cx88_core *core);
+extern void cx88_i2c_init_ir(struct cx88_core *core);
+
+/* ----------------------------------------------------------- */
+/* cx88-mpeg.c                                                 */
+
+int cx8802_buf_prepare(struct videobuf_queue *q,struct cx8802_dev *dev,
+			struct cx88_buffer *buf, enum v4l2_field field);
+void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf);
+void cx8802_cancel_buffers(struct cx8802_dev *dev);
+
+/* ----------------------------------------------------------- */
+/* cx88-video.c*/
+int cx88_enum_input (struct cx88_core  *core,struct v4l2_input *i);
+int cx88_set_freq (struct cx88_core  *core,struct v4l2_frequency *f);
+int cx88_video_mux(struct cx88_core *core, unsigned int input);
+void cx88_querycap(struct file *file, struct cx88_core *core,
+		struct v4l2_capability *cap);
diff --git a/drivers/media/pci/ddbridge/Kconfig b/drivers/media/pci/ddbridge/Kconfig
new file mode 100644
index 0000000..44e5dc1
--- /dev/null
+++ b/drivers/media/pci/ddbridge/Kconfig
@@ -0,0 +1,18 @@
+config DVB_DDBRIDGE
+	tristate "Digital Devices bridge support"
+	depends on DVB_CORE && PCI && I2C
+	select DVB_LNBP21 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_STV6110x if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_STV090x if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_DRXK if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_TDA18271C2DD if MEDIA_SUBDRV_AUTOSELECT
+	---help---
+	  Support for cards with the Digital Devices PCI express bridge:
+	  - Octopus PCIe Bridge
+	  - Octopus mini PCIe Bridge
+	  - Octopus LE
+	  - DuoFlex S2 Octopus
+	  - DuoFlex CT Octopus
+	  - cineS2(v6)
+
+	  Say Y if you own such a card and want to use it.
diff --git a/drivers/media/pci/ddbridge/Makefile b/drivers/media/pci/ddbridge/Makefile
new file mode 100644
index 0000000..7446c8b
--- /dev/null
+++ b/drivers/media/pci/ddbridge/Makefile
@@ -0,0 +1,14 @@
+#
+# Makefile for the ddbridge device driver
+#
+
+ddbridge-objs := ddbridge-core.o
+
+obj-$(CONFIG_DVB_DDBRIDGE) += ddbridge.o
+
+ccflags-y += -Idrivers/media/dvb-core/
+ccflags-y += -Idrivers/media/dvb-frontends/
+ccflags-y += -Idrivers/media/tuners/
+
+# For the staging CI driver cxd2099
+ccflags-y += -Idrivers/staging/media/cxd2099/
diff --git a/drivers/media/pci/ddbridge/ddbridge-core.c b/drivers/media/pci/ddbridge/ddbridge-core.c
new file mode 100644
index 0000000..feff57e
--- /dev/null
+++ b/drivers/media/pci/ddbridge/ddbridge-core.c
@@ -0,0 +1,1730 @@
+/*
+ * ddbridge.c: Digital Devices PCIe bridge driver
+ *
+ * Copyright (C) 2010-2011 Digital Devices GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 only, as published by the Free Software Foundation.
+ *
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/poll.h>
+#include <linux/io.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/timer.h>
+#include <linux/i2c.h>
+#include <linux/swab.h>
+#include <linux/vmalloc.h>
+#include "ddbridge.h"
+
+#include "ddbridge-regs.h"
+
+#include "tda18271c2dd.h"
+#include "stv6110x.h"
+#include "stv090x.h"
+#include "lnbh24.h"
+#include "drxk.h"
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+/* MSI had problems with lost interrupts, fixed but needs testing */
+#undef CONFIG_PCI_MSI
+
+/******************************************************************************/
+
+static int i2c_read(struct i2c_adapter *adapter, u8 adr, u8 *val)
+{
+	struct i2c_msg msgs[1] = {{.addr = adr,  .flags = I2C_M_RD,
+				   .buf  = val,  .len   = 1 } };
+	return (i2c_transfer(adapter, msgs, 1) == 1) ? 0 : -1;
+}
+
+static int i2c_read_reg(struct i2c_adapter *adapter, u8 adr, u8 reg, u8 *val)
+{
+	struct i2c_msg msgs[2] = {{.addr = adr,  .flags = 0,
+				   .buf  = &reg, .len   = 1 },
+				  {.addr = adr,  .flags = I2C_M_RD,
+				   .buf  = val,  .len   = 1 } };
+	return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1;
+}
+
+static int i2c_read_reg16(struct i2c_adapter *adapter, u8 adr,
+			  u16 reg, u8 *val)
+{
+	u8 msg[2] = {reg>>8, reg&0xff};
+	struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0,
+				   .buf  = msg, .len   = 2},
+				  {.addr = adr, .flags = I2C_M_RD,
+				   .buf  = val, .len   = 1} };
+	return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1;
+}
+
+static int ddb_i2c_cmd(struct ddb_i2c *i2c, u32 adr, u32 cmd)
+{
+	struct ddb *dev = i2c->dev;
+	int stat;
+	u32 val;
+
+	i2c->done = 0;
+	ddbwritel((adr << 9) | cmd, i2c->regs + I2C_COMMAND);
+	stat = wait_event_timeout(i2c->wq, i2c->done == 1, HZ);
+	if (stat <= 0) {
+		printk(KERN_ERR "I2C timeout\n");
+		{ /* MSI debugging*/
+			u32 istat = ddbreadl(INTERRUPT_STATUS);
+			printk(KERN_ERR "IRS %08x\n", istat);
+			ddbwritel(istat, INTERRUPT_ACK);
+		}
+		return -EIO;
+	}
+	val = ddbreadl(i2c->regs+I2C_COMMAND);
+	if (val & 0x70000)
+		return -EIO;
+	return 0;
+}
+
+static int ddb_i2c_master_xfer(struct i2c_adapter *adapter,
+			       struct i2c_msg msg[], int num)
+{
+	struct ddb_i2c *i2c = (struct ddb_i2c *)i2c_get_adapdata(adapter);
+	struct ddb *dev = i2c->dev;
+	u8 addr = 0;
+
+	if (num)
+		addr = msg[0].addr;
+
+	if (num == 2 && msg[1].flags & I2C_M_RD &&
+	    !(msg[0].flags & I2C_M_RD)) {
+		memcpy_toio(dev->regs + I2C_TASKMEM_BASE + i2c->wbuf,
+			    msg[0].buf, msg[0].len);
+		ddbwritel(msg[0].len|(msg[1].len << 16),
+			  i2c->regs+I2C_TASKLENGTH);
+		if (!ddb_i2c_cmd(i2c, addr, 1)) {
+			memcpy_fromio(msg[1].buf,
+				      dev->regs + I2C_TASKMEM_BASE + i2c->rbuf,
+				      msg[1].len);
+			return num;
+		}
+	}
+
+	if (num == 1 && !(msg[0].flags & I2C_M_RD)) {
+		ddbcpyto(I2C_TASKMEM_BASE + i2c->wbuf, msg[0].buf, msg[0].len);
+		ddbwritel(msg[0].len, i2c->regs + I2C_TASKLENGTH);
+		if (!ddb_i2c_cmd(i2c, addr, 2))
+			return num;
+	}
+	if (num == 1 && (msg[0].flags & I2C_M_RD)) {
+		ddbwritel(msg[0].len << 16, i2c->regs + I2C_TASKLENGTH);
+		if (!ddb_i2c_cmd(i2c, addr, 3)) {
+			ddbcpyfrom(msg[0].buf,
+				   I2C_TASKMEM_BASE + i2c->rbuf, msg[0].len);
+			return num;
+		}
+	}
+	return -EIO;
+}
+
+
+static u32 ddb_i2c_functionality(struct i2c_adapter *adap)
+{
+	return I2C_FUNC_SMBUS_EMUL;
+}
+
+struct i2c_algorithm ddb_i2c_algo = {
+	.master_xfer   = ddb_i2c_master_xfer,
+	.functionality = ddb_i2c_functionality,
+};
+
+static void ddb_i2c_release(struct ddb *dev)
+{
+	int i;
+	struct ddb_i2c *i2c;
+	struct i2c_adapter *adap;
+
+	for (i = 0; i < dev->info->port_num; i++) {
+		i2c = &dev->i2c[i];
+		adap = &i2c->adap;
+		i2c_del_adapter(adap);
+	}
+}
+
+static int ddb_i2c_init(struct ddb *dev)
+{
+	int i, j, stat = 0;
+	struct ddb_i2c *i2c;
+	struct i2c_adapter *adap;
+
+	for (i = 0; i < dev->info->port_num; i++) {
+		i2c = &dev->i2c[i];
+		i2c->dev = dev;
+		i2c->nr = i;
+		i2c->wbuf = i * (I2C_TASKMEM_SIZE / 4);
+		i2c->rbuf = i2c->wbuf + (I2C_TASKMEM_SIZE / 8);
+		i2c->regs = 0x80 + i * 0x20;
+		ddbwritel(I2C_SPEED_100, i2c->regs + I2C_TIMING);
+		ddbwritel((i2c->rbuf << 16) | i2c->wbuf,
+			  i2c->regs + I2C_TASKADDRESS);
+		init_waitqueue_head(&i2c->wq);
+
+		adap = &i2c->adap;
+		i2c_set_adapdata(adap, i2c);
+#ifdef I2C_ADAP_CLASS_TV_DIGITAL
+		adap->class = I2C_ADAP_CLASS_TV_DIGITAL|I2C_CLASS_TV_ANALOG;
+#else
+#ifdef I2C_CLASS_TV_ANALOG
+		adap->class = I2C_CLASS_TV_ANALOG;
+#endif
+#endif
+		strcpy(adap->name, "ddbridge");
+		adap->algo = &ddb_i2c_algo;
+		adap->algo_data = (void *)i2c;
+		adap->dev.parent = &dev->pdev->dev;
+		stat = i2c_add_adapter(adap);
+		if (stat)
+			break;
+	}
+	if (stat)
+		for (j = 0; j < i; j++) {
+			i2c = &dev->i2c[j];
+			adap = &i2c->adap;
+			i2c_del_adapter(adap);
+		}
+	return stat;
+}
+
+
+/******************************************************************************/
+/******************************************************************************/
+/******************************************************************************/
+
+#if 0
+static void set_table(struct ddb *dev, u32 off,
+		      dma_addr_t *pbuf, u32 num)
+{
+	u32 i, base;
+	u64 mem;
+
+	base = DMA_BASE_ADDRESS_TABLE + off;
+	for (i = 0; i < num; i++) {
+		mem = pbuf[i];
+		ddbwritel(mem & 0xffffffff, base + i * 8);
+		ddbwritel(mem >> 32, base + i * 8 + 4);
+	}
+}
+#endif
+
+static void ddb_address_table(struct ddb *dev)
+{
+	u32 i, j, base;
+	u64 mem;
+	dma_addr_t *pbuf;
+
+	for (i = 0; i < dev->info->port_num * 2; i++) {
+		base = DMA_BASE_ADDRESS_TABLE + i * 0x100;
+		pbuf = dev->input[i].pbuf;
+		for (j = 0; j < dev->input[i].dma_buf_num; j++) {
+			mem = pbuf[j];
+			ddbwritel(mem & 0xffffffff, base + j * 8);
+			ddbwritel(mem >> 32, base + j * 8 + 4);
+		}
+	}
+	for (i = 0; i < dev->info->port_num; i++) {
+		base = DMA_BASE_ADDRESS_TABLE + 0x800 + i * 0x100;
+		pbuf = dev->output[i].pbuf;
+		for (j = 0; j < dev->output[i].dma_buf_num; j++) {
+			mem = pbuf[j];
+			ddbwritel(mem & 0xffffffff, base + j * 8);
+			ddbwritel(mem >> 32, base + j * 8 + 4);
+		}
+	}
+}
+
+static void io_free(struct pci_dev *pdev, u8 **vbuf,
+		    dma_addr_t *pbuf, u32 size, int num)
+{
+	int i;
+
+	for (i = 0; i < num; i++) {
+		if (vbuf[i]) {
+			pci_free_consistent(pdev, size, vbuf[i], pbuf[i]);
+			vbuf[i] = 0;
+		}
+	}
+}
+
+static int io_alloc(struct pci_dev *pdev, u8 **vbuf,
+		    dma_addr_t *pbuf, u32 size, int num)
+{
+	int i;
+
+	for (i = 0; i < num; i++) {
+		vbuf[i] = pci_alloc_consistent(pdev, size, &pbuf[i]);
+		if (!vbuf[i])
+			return -ENOMEM;
+	}
+	return 0;
+}
+
+static int ddb_buffers_alloc(struct ddb *dev)
+{
+	int i;
+	struct ddb_port *port;
+
+	for (i = 0; i < dev->info->port_num; i++) {
+		port = &dev->port[i];
+		switch (port->class) {
+		case DDB_PORT_TUNER:
+			if (io_alloc(dev->pdev, port->input[0]->vbuf,
+				     port->input[0]->pbuf,
+				     port->input[0]->dma_buf_size,
+				     port->input[0]->dma_buf_num) < 0)
+				return -1;
+			if (io_alloc(dev->pdev, port->input[1]->vbuf,
+				     port->input[1]->pbuf,
+				     port->input[1]->dma_buf_size,
+				     port->input[1]->dma_buf_num) < 0)
+				return -1;
+			break;
+		case DDB_PORT_CI:
+			if (io_alloc(dev->pdev, port->input[0]->vbuf,
+				     port->input[0]->pbuf,
+				     port->input[0]->dma_buf_size,
+				     port->input[0]->dma_buf_num) < 0)
+				return -1;
+			if (io_alloc(dev->pdev, port->output->vbuf,
+				     port->output->pbuf,
+				     port->output->dma_buf_size,
+				     port->output->dma_buf_num) < 0)
+				return -1;
+			break;
+		default:
+			break;
+		}
+	}
+	ddb_address_table(dev);
+	return 0;
+}
+
+static void ddb_buffers_free(struct ddb *dev)
+{
+	int i;
+	struct ddb_port *port;
+
+	for (i = 0; i < dev->info->port_num; i++) {
+		port = &dev->port[i];
+		io_free(dev->pdev, port->input[0]->vbuf,
+			port->input[0]->pbuf,
+			port->input[0]->dma_buf_size,
+			port->input[0]->dma_buf_num);
+		io_free(dev->pdev, port->input[1]->vbuf,
+			port->input[1]->pbuf,
+			port->input[1]->dma_buf_size,
+			port->input[1]->dma_buf_num);
+		io_free(dev->pdev, port->output->vbuf,
+			port->output->pbuf,
+			port->output->dma_buf_size,
+			port->output->dma_buf_num);
+	}
+}
+
+static void ddb_input_start(struct ddb_input *input)
+{
+	struct ddb *dev = input->port->dev;
+
+	spin_lock_irq(&input->lock);
+	input->cbuf = 0;
+	input->coff = 0;
+
+	/* reset */
+	ddbwritel(0, TS_INPUT_CONTROL(input->nr));
+	ddbwritel(2, TS_INPUT_CONTROL(input->nr));
+	ddbwritel(0, TS_INPUT_CONTROL(input->nr));
+
+	ddbwritel((1 << 16) |
+		  (input->dma_buf_num << 11) |
+		  (input->dma_buf_size >> 7),
+		  DMA_BUFFER_SIZE(input->nr));
+	ddbwritel(0, DMA_BUFFER_ACK(input->nr));
+
+	ddbwritel(1, DMA_BASE_WRITE);
+	ddbwritel(3, DMA_BUFFER_CONTROL(input->nr));
+	ddbwritel(9, TS_INPUT_CONTROL(input->nr));
+	input->running = 1;
+	spin_unlock_irq(&input->lock);
+}
+
+static void ddb_input_stop(struct ddb_input *input)
+{
+	struct ddb *dev = input->port->dev;
+
+	spin_lock_irq(&input->lock);
+	ddbwritel(0, TS_INPUT_CONTROL(input->nr));
+	ddbwritel(0, DMA_BUFFER_CONTROL(input->nr));
+	input->running = 0;
+	spin_unlock_irq(&input->lock);
+}
+
+static void ddb_output_start(struct ddb_output *output)
+{
+	struct ddb *dev = output->port->dev;
+
+	spin_lock_irq(&output->lock);
+	output->cbuf = 0;
+	output->coff = 0;
+	ddbwritel(0, TS_OUTPUT_CONTROL(output->nr));
+	ddbwritel(2, TS_OUTPUT_CONTROL(output->nr));
+	ddbwritel(0, TS_OUTPUT_CONTROL(output->nr));
+	ddbwritel(0x3c, TS_OUTPUT_CONTROL(output->nr));
+	ddbwritel((1 << 16) |
+		  (output->dma_buf_num << 11) |
+		  (output->dma_buf_size >> 7),
+		  DMA_BUFFER_SIZE(output->nr + 8));
+	ddbwritel(0, DMA_BUFFER_ACK(output->nr + 8));
+
+	ddbwritel(1, DMA_BASE_READ);
+	ddbwritel(3, DMA_BUFFER_CONTROL(output->nr + 8));
+	/* ddbwritel(0xbd, TS_OUTPUT_CONTROL(output->nr)); */
+	ddbwritel(0x1d, TS_OUTPUT_CONTROL(output->nr));
+	output->running = 1;
+	spin_unlock_irq(&output->lock);
+}
+
+static void ddb_output_stop(struct ddb_output *output)
+{
+	struct ddb *dev = output->port->dev;
+
+	spin_lock_irq(&output->lock);
+	ddbwritel(0, TS_OUTPUT_CONTROL(output->nr));
+	ddbwritel(0, DMA_BUFFER_CONTROL(output->nr + 8));
+	output->running = 0;
+	spin_unlock_irq(&output->lock);
+}
+
+static u32 ddb_output_free(struct ddb_output *output)
+{
+	u32 idx, off, stat = output->stat;
+	s32 diff;
+
+	idx = (stat >> 11) & 0x1f;
+	off = (stat & 0x7ff) << 7;
+
+	if (output->cbuf != idx) {
+		if ((((output->cbuf + 1) % output->dma_buf_num) == idx) &&
+		    (output->dma_buf_size - output->coff <= 188))
+			return 0;
+		return 188;
+	}
+	diff = off - output->coff;
+	if (diff <= 0 || diff > 188)
+		return 188;
+	return 0;
+}
+
+static ssize_t ddb_output_write(struct ddb_output *output,
+				const u8 *buf, size_t count)
+{
+	struct ddb *dev = output->port->dev;
+	u32 idx, off, stat = output->stat;
+	u32 left = count, len;
+
+	idx = (stat >> 11) & 0x1f;
+	off = (stat & 0x7ff) << 7;
+
+	while (left) {
+		len = output->dma_buf_size - output->coff;
+		if ((((output->cbuf + 1) % output->dma_buf_num) == idx) &&
+		    (off == 0)) {
+			if (len <= 188)
+				break;
+			len -= 188;
+		}
+		if (output->cbuf == idx) {
+			if (off > output->coff) {
+#if 1
+				len = off - output->coff;
+				len -= (len % 188);
+				if (len <= 188)
+
+#endif
+					break;
+				len -= 188;
+			}
+		}
+		if (len > left)
+			len = left;
+		if (copy_from_user(output->vbuf[output->cbuf] + output->coff,
+				   buf, len))
+			return -EIO;
+		left -= len;
+		buf += len;
+		output->coff += len;
+		if (output->coff == output->dma_buf_size) {
+			output->coff = 0;
+			output->cbuf = ((output->cbuf + 1) % output->dma_buf_num);
+		}
+		ddbwritel((output->cbuf << 11) | (output->coff >> 7),
+			  DMA_BUFFER_ACK(output->nr + 8));
+	}
+	return count - left;
+}
+
+static u32 ddb_input_avail(struct ddb_input *input)
+{
+	struct ddb *dev = input->port->dev;
+	u32 idx, off, stat = input->stat;
+	u32 ctrl = ddbreadl(DMA_BUFFER_CONTROL(input->nr));
+
+	idx = (stat >> 11) & 0x1f;
+	off = (stat & 0x7ff) << 7;
+
+	if (ctrl & 4) {
+		printk(KERN_ERR "IA %d %d %08x\n", idx, off, ctrl);
+		ddbwritel(input->stat, DMA_BUFFER_ACK(input->nr));
+		return 0;
+	}
+	if (input->cbuf != idx)
+		return 188;
+	return 0;
+}
+
+static ssize_t ddb_input_read(struct ddb_input *input, u8 *buf, size_t count)
+{
+	struct ddb *dev = input->port->dev;
+	u32 left = count;
+	u32 idx, free, stat = input->stat;
+	int ret;
+
+	idx = (stat >> 11) & 0x1f;
+
+	while (left) {
+		if (input->cbuf == idx)
+			return count - left;
+		free = input->dma_buf_size - input->coff;
+		if (free > left)
+			free = left;
+		ret = copy_to_user(buf, input->vbuf[input->cbuf] +
+				   input->coff, free);
+		if (ret)
+			return -EFAULT;
+		input->coff += free;
+		if (input->coff == input->dma_buf_size) {
+			input->coff = 0;
+			input->cbuf = (input->cbuf+1) % input->dma_buf_num;
+		}
+		left -= free;
+		ddbwritel((input->cbuf << 11) | (input->coff >> 7),
+			  DMA_BUFFER_ACK(input->nr));
+	}
+	return count;
+}
+
+/******************************************************************************/
+/******************************************************************************/
+/******************************************************************************/
+
+#if 0
+static struct ddb_input *fe2input(struct ddb *dev, struct dvb_frontend *fe)
+{
+	int i;
+
+	for (i = 0; i < dev->info->port_num * 2; i++) {
+		if (dev->input[i].fe == fe)
+			return &dev->input[i];
+	}
+	return NULL;
+}
+#endif
+
+static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+	struct ddb_input *input = fe->sec_priv;
+	struct ddb_port *port = input->port;
+	int status;
+
+	if (enable) {
+		mutex_lock(&port->i2c_gate_lock);
+		status = input->gate_ctrl(fe, 1);
+	} else {
+		status = input->gate_ctrl(fe, 0);
+		mutex_unlock(&port->i2c_gate_lock);
+	}
+	return status;
+}
+
+static int demod_attach_drxk(struct ddb_input *input)
+{
+	struct i2c_adapter *i2c = &input->port->i2c->adap;
+	struct dvb_frontend *fe;
+	struct drxk_config config;
+
+	memset(&config, 0, sizeof(config));
+	config.microcode_name = "drxk_a3.mc";
+	config.qam_demod_parameter_count = 4;
+	config.adr = 0x29 + (input->nr & 1);
+
+	fe = input->fe = dvb_attach(drxk_attach, &config, i2c);
+	if (!input->fe) {
+		printk(KERN_ERR "No DRXK found!\n");
+		return -ENODEV;
+	}
+	fe->sec_priv = input;
+	input->gate_ctrl = fe->ops.i2c_gate_ctrl;
+	fe->ops.i2c_gate_ctrl = drxk_gate_ctrl;
+	return 0;
+}
+
+static int tuner_attach_tda18271(struct ddb_input *input)
+{
+	struct i2c_adapter *i2c = &input->port->i2c->adap;
+	struct dvb_frontend *fe;
+
+	if (input->fe->ops.i2c_gate_ctrl)
+		input->fe->ops.i2c_gate_ctrl(input->fe, 1);
+	fe = dvb_attach(tda18271c2dd_attach, input->fe, i2c, 0x60);
+	if (!fe) {
+		printk(KERN_ERR "No TDA18271 found!\n");
+		return -ENODEV;
+	}
+	if (input->fe->ops.i2c_gate_ctrl)
+		input->fe->ops.i2c_gate_ctrl(input->fe, 0);
+	return 0;
+}
+
+/******************************************************************************/
+/******************************************************************************/
+/******************************************************************************/
+
+static struct stv090x_config stv0900 = {
+	.device         = STV0900,
+	.demod_mode     = STV090x_DUAL,
+	.clk_mode       = STV090x_CLK_EXT,
+
+	.xtal           = 27000000,
+	.address        = 0x69,
+
+	.ts1_mode       = STV090x_TSMODE_SERIAL_PUNCTURED,
+	.ts2_mode       = STV090x_TSMODE_SERIAL_PUNCTURED,
+
+	.repeater_level = STV090x_RPTLEVEL_16,
+
+	.adc1_range	= STV090x_ADC_1Vpp,
+	.adc2_range	= STV090x_ADC_1Vpp,
+
+	.diseqc_envelope_mode = true,
+};
+
+static struct stv090x_config stv0900_aa = {
+	.device         = STV0900,
+	.demod_mode     = STV090x_DUAL,
+	.clk_mode       = STV090x_CLK_EXT,
+
+	.xtal           = 27000000,
+	.address        = 0x68,
+
+	.ts1_mode       = STV090x_TSMODE_SERIAL_PUNCTURED,
+	.ts2_mode       = STV090x_TSMODE_SERIAL_PUNCTURED,
+
+	.repeater_level = STV090x_RPTLEVEL_16,
+
+	.adc1_range	= STV090x_ADC_1Vpp,
+	.adc2_range	= STV090x_ADC_1Vpp,
+
+	.diseqc_envelope_mode = true,
+};
+
+static struct stv6110x_config stv6110a = {
+	.addr    = 0x60,
+	.refclk	 = 27000000,
+	.clk_div = 1,
+};
+
+static struct stv6110x_config stv6110b = {
+	.addr    = 0x63,
+	.refclk	 = 27000000,
+	.clk_div = 1,
+};
+
+static int demod_attach_stv0900(struct ddb_input *input, int type)
+{
+	struct i2c_adapter *i2c = &input->port->i2c->adap;
+	struct stv090x_config *feconf = type ? &stv0900_aa : &stv0900;
+
+	input->fe = dvb_attach(stv090x_attach, feconf, i2c,
+			       (input->nr & 1) ? STV090x_DEMODULATOR_1
+			       : STV090x_DEMODULATOR_0);
+	if (!input->fe) {
+		printk(KERN_ERR "No STV0900 found!\n");
+		return -ENODEV;
+	}
+	if (!dvb_attach(lnbh24_attach, input->fe, i2c, 0,
+			0, (input->nr & 1) ?
+			(0x09 - type) : (0x0b - type))) {
+		printk(KERN_ERR "No LNBH24 found!\n");
+		return -ENODEV;
+	}
+	return 0;
+}
+
+static int tuner_attach_stv6110(struct ddb_input *input, int type)
+{
+	struct i2c_adapter *i2c = &input->port->i2c->adap;
+	struct stv090x_config *feconf = type ? &stv0900_aa : &stv0900;
+	struct stv6110x_config *tunerconf = (input->nr & 1) ?
+		&stv6110b : &stv6110a;
+	struct stv6110x_devctl *ctl;
+
+	ctl = dvb_attach(stv6110x_attach, input->fe, tunerconf, i2c);
+	if (!ctl) {
+		printk(KERN_ERR "No STV6110X found!\n");
+		return -ENODEV;
+	}
+	printk(KERN_INFO "attach tuner input %d adr %02x\n",
+			 input->nr, tunerconf->addr);
+
+	feconf->tuner_init          = ctl->tuner_init;
+	feconf->tuner_sleep         = ctl->tuner_sleep;
+	feconf->tuner_set_mode      = ctl->tuner_set_mode;
+	feconf->tuner_set_frequency = ctl->tuner_set_frequency;
+	feconf->tuner_get_frequency = ctl->tuner_get_frequency;
+	feconf->tuner_set_bandwidth = ctl->tuner_set_bandwidth;
+	feconf->tuner_get_bandwidth = ctl->tuner_get_bandwidth;
+	feconf->tuner_set_bbgain    = ctl->tuner_set_bbgain;
+	feconf->tuner_get_bbgain    = ctl->tuner_get_bbgain;
+	feconf->tuner_set_refclk    = ctl->tuner_set_refclk;
+	feconf->tuner_get_status    = ctl->tuner_get_status;
+
+	return 0;
+}
+
+static int my_dvb_dmx_ts_card_init(struct dvb_demux *dvbdemux, char *id,
+			    int (*start_feed)(struct dvb_demux_feed *),
+			    int (*stop_feed)(struct dvb_demux_feed *),
+			    void *priv)
+{
+	dvbdemux->priv = priv;
+
+	dvbdemux->filternum = 256;
+	dvbdemux->feednum = 256;
+	dvbdemux->start_feed = start_feed;
+	dvbdemux->stop_feed = stop_feed;
+	dvbdemux->write_to_decoder = NULL;
+	dvbdemux->dmx.capabilities = (DMX_TS_FILTERING |
+				      DMX_SECTION_FILTERING |
+				      DMX_MEMORY_BASED_FILTERING);
+	return dvb_dmx_init(dvbdemux);
+}
+
+static int my_dvb_dmxdev_ts_card_init(struct dmxdev *dmxdev,
+			       struct dvb_demux *dvbdemux,
+			       struct dmx_frontend *hw_frontend,
+			       struct dmx_frontend *mem_frontend,
+			       struct dvb_adapter *dvb_adapter)
+{
+	int ret;
+
+	dmxdev->filternum = 256;
+	dmxdev->demux = &dvbdemux->dmx;
+	dmxdev->capabilities = 0;
+	ret = dvb_dmxdev_init(dmxdev, dvb_adapter);
+	if (ret < 0)
+		return ret;
+
+	hw_frontend->source = DMX_FRONTEND_0;
+	dvbdemux->dmx.add_frontend(&dvbdemux->dmx, hw_frontend);
+	mem_frontend->source = DMX_MEMORY_FE;
+	dvbdemux->dmx.add_frontend(&dvbdemux->dmx, mem_frontend);
+	return dvbdemux->dmx.connect_frontend(&dvbdemux->dmx, hw_frontend);
+}
+
+static int start_feed(struct dvb_demux_feed *dvbdmxfeed)
+{
+	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
+	struct ddb_input *input = dvbdmx->priv;
+
+	if (!input->users)
+		ddb_input_start(input);
+
+	return ++input->users;
+}
+
+static int stop_feed(struct dvb_demux_feed *dvbdmxfeed)
+{
+	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
+	struct ddb_input *input = dvbdmx->priv;
+
+	if (--input->users)
+		return input->users;
+
+	ddb_input_stop(input);
+	return 0;
+}
+
+
+static void dvb_input_detach(struct ddb_input *input)
+{
+	struct dvb_adapter *adap = &input->adap;
+	struct dvb_demux *dvbdemux = &input->demux;
+
+	switch (input->attached) {
+	case 5:
+		if (input->fe2)
+			dvb_unregister_frontend(input->fe2);
+		if (input->fe) {
+			dvb_unregister_frontend(input->fe);
+			dvb_frontend_detach(input->fe);
+			input->fe = NULL;
+		}
+	case 4:
+		dvb_net_release(&input->dvbnet);
+
+	case 3:
+		dvbdemux->dmx.close(&dvbdemux->dmx);
+		dvbdemux->dmx.remove_frontend(&dvbdemux->dmx,
+					      &input->hw_frontend);
+		dvbdemux->dmx.remove_frontend(&dvbdemux->dmx,
+					      &input->mem_frontend);
+		dvb_dmxdev_release(&input->dmxdev);
+
+	case 2:
+		dvb_dmx_release(&input->demux);
+
+	case 1:
+		dvb_unregister_adapter(adap);
+	}
+	input->attached = 0;
+}
+
+static int dvb_input_attach(struct ddb_input *input)
+{
+	int ret;
+	struct ddb_port *port = input->port;
+	struct dvb_adapter *adap = &input->adap;
+	struct dvb_demux *dvbdemux = &input->demux;
+
+	ret = dvb_register_adapter(adap, "DDBridge", THIS_MODULE,
+				   &input->port->dev->pdev->dev,
+				   adapter_nr);
+	if (ret < 0) {
+		printk(KERN_ERR "ddbridge: Could not register adapter."
+		       "Check if you enabled enough adapters in dvb-core!\n");
+		return ret;
+	}
+	input->attached = 1;
+
+	ret = my_dvb_dmx_ts_card_init(dvbdemux, "SW demux",
+				      start_feed,
+				      stop_feed, input);
+	if (ret < 0)
+		return ret;
+	input->attached = 2;
+
+	ret = my_dvb_dmxdev_ts_card_init(&input->dmxdev, &input->demux,
+					 &input->hw_frontend,
+					 &input->mem_frontend, adap);
+	if (ret < 0)
+		return ret;
+	input->attached = 3;
+
+	ret = dvb_net_init(adap, &input->dvbnet, input->dmxdev.demux);
+	if (ret < 0)
+		return ret;
+	input->attached = 4;
+
+	input->fe = 0;
+	switch (port->type) {
+	case DDB_TUNER_DVBS_ST:
+		if (demod_attach_stv0900(input, 0) < 0)
+			return -ENODEV;
+		if (tuner_attach_stv6110(input, 0) < 0)
+			return -ENODEV;
+		if (input->fe) {
+			if (dvb_register_frontend(adap, input->fe) < 0)
+				return -ENODEV;
+		}
+		break;
+	case DDB_TUNER_DVBS_ST_AA:
+		if (demod_attach_stv0900(input, 1) < 0)
+			return -ENODEV;
+		if (tuner_attach_stv6110(input, 1) < 0)
+			return -ENODEV;
+		if (input->fe) {
+			if (dvb_register_frontend(adap, input->fe) < 0)
+				return -ENODEV;
+		}
+		break;
+	case DDB_TUNER_DVBCT_TR:
+		if (demod_attach_drxk(input) < 0)
+			return -ENODEV;
+		if (tuner_attach_tda18271(input) < 0)
+			return -ENODEV;
+		if (input->fe) {
+			if (dvb_register_frontend(adap, input->fe) < 0)
+				return -ENODEV;
+		}
+		if (input->fe2) {
+			if (dvb_register_frontend(adap, input->fe2) < 0)
+				return -ENODEV;
+			input->fe2->tuner_priv = input->fe->tuner_priv;
+			memcpy(&input->fe2->ops.tuner_ops,
+			       &input->fe->ops.tuner_ops,
+			       sizeof(struct dvb_tuner_ops));
+		}
+		break;
+	}
+	input->attached = 5;
+	return 0;
+}
+
+/****************************************************************************/
+/****************************************************************************/
+
+static ssize_t ts_write(struct file *file, const char *buf,
+			size_t count, loff_t *ppos)
+{
+	struct dvb_device *dvbdev = file->private_data;
+	struct ddb_output *output = dvbdev->priv;
+	size_t left = count;
+	int stat;
+
+	while (left) {
+		if (ddb_output_free(output) < 188) {
+			if (file->f_flags & O_NONBLOCK)
+				break;
+			if (wait_event_interruptible(
+				    output->wq, ddb_output_free(output) >= 188) < 0)
+				break;
+		}
+		stat = ddb_output_write(output, buf, left);
+		if (stat < 0)
+			break;
+		buf += stat;
+		left -= stat;
+	}
+	return (left == count) ? -EAGAIN : (count - left);
+}
+
+static ssize_t ts_read(struct file *file, char *buf,
+		       size_t count, loff_t *ppos)
+{
+	struct dvb_device *dvbdev = file->private_data;
+	struct ddb_output *output = dvbdev->priv;
+	struct ddb_input *input = output->port->input[0];
+	int left, read;
+
+	count -= count % 188;
+	left = count;
+	while (left) {
+		if (ddb_input_avail(input) < 188) {
+			if (file->f_flags & O_NONBLOCK)
+				break;
+			if (wait_event_interruptible(
+				    input->wq, ddb_input_avail(input) >= 188) < 0)
+				break;
+		}
+		read = ddb_input_read(input, buf, left);
+		if (read < 0)
+			return read;
+		left -= read;
+		buf += read;
+	}
+	return (left == count) ? -EAGAIN : (count - left);
+}
+
+static unsigned int ts_poll(struct file *file, poll_table *wait)
+{
+	/*
+	struct dvb_device *dvbdev = file->private_data;
+	struct ddb_output *output = dvbdev->priv;
+	struct ddb_input *input = output->port->input[0];
+	*/
+	unsigned int mask = 0;
+
+#if 0
+	if (data_avail_to_read)
+		mask |= POLLIN | POLLRDNORM;
+	if (data_avail_to_write)
+		mask |= POLLOUT | POLLWRNORM;
+
+	poll_wait(file, &read_queue, wait);
+	poll_wait(file, &write_queue, wait);
+#endif
+	return mask;
+}
+
+static const struct file_operations ci_fops = {
+	.owner   = THIS_MODULE,
+	.read    = ts_read,
+	.write   = ts_write,
+	.open    = dvb_generic_open,
+	.release = dvb_generic_release,
+	.poll    = ts_poll,
+	.mmap    = 0,
+};
+
+static struct dvb_device dvbdev_ci = {
+	.priv    = 0,
+	.readers = -1,
+	.writers = -1,
+	.users   = -1,
+	.fops    = &ci_fops,
+};
+
+/****************************************************************************/
+/****************************************************************************/
+/****************************************************************************/
+
+static void input_tasklet(unsigned long data)
+{
+	struct ddb_input *input = (struct ddb_input *) data;
+	struct ddb *dev = input->port->dev;
+
+	spin_lock(&input->lock);
+	if (!input->running) {
+		spin_unlock(&input->lock);
+		return;
+	}
+	input->stat = ddbreadl(DMA_BUFFER_CURRENT(input->nr));
+
+	if (input->port->class == DDB_PORT_TUNER) {
+		if (4&ddbreadl(DMA_BUFFER_CONTROL(input->nr)))
+			printk(KERN_ERR "Overflow input %d\n", input->nr);
+		while (input->cbuf != ((input->stat >> 11) & 0x1f)
+		       || (4&ddbreadl(DMA_BUFFER_CONTROL(input->nr)))) {
+			dvb_dmx_swfilter_packets(&input->demux,
+						 input->vbuf[input->cbuf],
+						 input->dma_buf_size / 188);
+
+			input->cbuf = (input->cbuf + 1) % input->dma_buf_num;
+			ddbwritel((input->cbuf << 11),
+				  DMA_BUFFER_ACK(input->nr));
+			input->stat = ddbreadl(DMA_BUFFER_CURRENT(input->nr));
+		       }
+	}
+	if (input->port->class == DDB_PORT_CI)
+		wake_up(&input->wq);
+	spin_unlock(&input->lock);
+}
+
+static void output_tasklet(unsigned long data)
+{
+	struct ddb_output *output = (struct ddb_output *) data;
+	struct ddb *dev = output->port->dev;
+
+	spin_lock(&output->lock);
+	if (!output->running) {
+		spin_unlock(&output->lock);
+		return;
+	}
+	output->stat = ddbreadl(DMA_BUFFER_CURRENT(output->nr + 8));
+	wake_up(&output->wq);
+	spin_unlock(&output->lock);
+}
+
+
+struct cxd2099_cfg cxd_cfg = {
+	.bitrate =  62000,
+	.adr     =  0x40,
+	.polarity = 1,
+	.clock_mode = 1,
+};
+
+static int ddb_ci_attach(struct ddb_port *port)
+{
+	int ret;
+
+	ret = dvb_register_adapter(&port->output->adap,
+				   "DDBridge",
+				   THIS_MODULE,
+				   &port->dev->pdev->dev,
+				   adapter_nr);
+	if (ret < 0)
+		return ret;
+	port->en = cxd2099_attach(&cxd_cfg, port, &port->i2c->adap);
+	if (!port->en) {
+		dvb_unregister_adapter(&port->output->adap);
+		return -ENODEV;
+	}
+	ddb_input_start(port->input[0]);
+	ddb_output_start(port->output);
+	dvb_ca_en50221_init(&port->output->adap,
+			    port->en, 0, 1);
+	ret = dvb_register_device(&port->output->adap, &port->output->dev,
+				  &dvbdev_ci, (void *) port->output,
+				  DVB_DEVICE_SEC);
+	return ret;
+}
+
+static int ddb_port_attach(struct ddb_port *port)
+{
+	int ret = 0;
+
+	switch (port->class) {
+	case DDB_PORT_TUNER:
+		ret = dvb_input_attach(port->input[0]);
+		if (ret < 0)
+			break;
+		ret = dvb_input_attach(port->input[1]);
+		break;
+	case DDB_PORT_CI:
+		ret = ddb_ci_attach(port);
+		break;
+	default:
+		break;
+	}
+	if (ret < 0)
+		printk(KERN_ERR "port_attach on port %d failed\n", port->nr);
+	return ret;
+}
+
+static int ddb_ports_attach(struct ddb *dev)
+{
+	int i, ret = 0;
+	struct ddb_port *port;
+
+	for (i = 0; i < dev->info->port_num; i++) {
+		port = &dev->port[i];
+		ret = ddb_port_attach(port);
+		if (ret < 0)
+			break;
+	}
+	return ret;
+}
+
+static void ddb_ports_detach(struct ddb *dev)
+{
+	int i;
+	struct ddb_port *port;
+
+	for (i = 0; i < dev->info->port_num; i++) {
+		port = &dev->port[i];
+		switch (port->class) {
+		case DDB_PORT_TUNER:
+			dvb_input_detach(port->input[0]);
+			dvb_input_detach(port->input[1]);
+			break;
+		case DDB_PORT_CI:
+			if (port->output->dev)
+				dvb_unregister_device(port->output->dev);
+			if (port->en) {
+				ddb_input_stop(port->input[0]);
+				ddb_output_stop(port->output);
+				dvb_ca_en50221_release(port->en);
+				kfree(port->en);
+				port->en = 0;
+				dvb_unregister_adapter(&port->output->adap);
+			}
+			break;
+		}
+	}
+}
+
+/****************************************************************************/
+/****************************************************************************/
+
+static int port_has_ci(struct ddb_port *port)
+{
+	u8 val;
+	return i2c_read_reg(&port->i2c->adap, 0x40, 0, &val) ? 0 : 1;
+}
+
+static int port_has_stv0900(struct ddb_port *port)
+{
+	u8 val;
+	if (i2c_read_reg16(&port->i2c->adap, 0x69, 0xf100, &val) < 0)
+		return 0;
+	return 1;
+}
+
+static int port_has_stv0900_aa(struct ddb_port *port)
+{
+	u8 val;
+	if (i2c_read_reg16(&port->i2c->adap, 0x68, 0xf100, &val) < 0)
+		return 0;
+	return 1;
+}
+
+static int port_has_drxks(struct ddb_port *port)
+{
+	u8 val;
+	if (i2c_read(&port->i2c->adap, 0x29, &val) < 0)
+		return 0;
+	if (i2c_read(&port->i2c->adap, 0x2a, &val) < 0)
+		return 0;
+	return 1;
+}
+
+static void ddb_port_probe(struct ddb_port *port)
+{
+	struct ddb *dev = port->dev;
+	char *modname = "NO MODULE";
+
+	port->class = DDB_PORT_NONE;
+
+	if (port_has_ci(port)) {
+		modname = "CI";
+		port->class = DDB_PORT_CI;
+		ddbwritel(I2C_SPEED_400, port->i2c->regs + I2C_TIMING);
+	} else if (port_has_stv0900(port)) {
+		modname = "DUAL DVB-S2";
+		port->class = DDB_PORT_TUNER;
+		port->type = DDB_TUNER_DVBS_ST;
+		ddbwritel(I2C_SPEED_100, port->i2c->regs + I2C_TIMING);
+	} else if (port_has_stv0900_aa(port)) {
+		modname = "DUAL DVB-S2";
+		port->class = DDB_PORT_TUNER;
+		port->type = DDB_TUNER_DVBS_ST_AA;
+		ddbwritel(I2C_SPEED_100, port->i2c->regs + I2C_TIMING);
+	} else if (port_has_drxks(port)) {
+		modname = "DUAL DVB-C/T";
+		port->class = DDB_PORT_TUNER;
+		port->type = DDB_TUNER_DVBCT_TR;
+		ddbwritel(I2C_SPEED_400, port->i2c->regs + I2C_TIMING);
+	}
+	printk(KERN_INFO "Port %d (TAB %d): %s\n",
+			 port->nr, port->nr+1, modname);
+}
+
+static void ddb_input_init(struct ddb_port *port, int nr)
+{
+	struct ddb *dev = port->dev;
+	struct ddb_input *input = &dev->input[nr];
+
+	input->nr = nr;
+	input->port = port;
+	input->dma_buf_num = INPUT_DMA_BUFS;
+	input->dma_buf_size = INPUT_DMA_SIZE;
+	ddbwritel(0, TS_INPUT_CONTROL(nr));
+	ddbwritel(2, TS_INPUT_CONTROL(nr));
+	ddbwritel(0, TS_INPUT_CONTROL(nr));
+	ddbwritel(0, DMA_BUFFER_ACK(nr));
+	tasklet_init(&input->tasklet, input_tasklet, (unsigned long) input);
+	spin_lock_init(&input->lock);
+	init_waitqueue_head(&input->wq);
+}
+
+static void ddb_output_init(struct ddb_port *port, int nr)
+{
+	struct ddb *dev = port->dev;
+	struct ddb_output *output = &dev->output[nr];
+	output->nr = nr;
+	output->port = port;
+	output->dma_buf_num = OUTPUT_DMA_BUFS;
+	output->dma_buf_size = OUTPUT_DMA_SIZE;
+
+	ddbwritel(0, TS_OUTPUT_CONTROL(nr));
+	ddbwritel(2, TS_OUTPUT_CONTROL(nr));
+	ddbwritel(0, TS_OUTPUT_CONTROL(nr));
+	tasklet_init(&output->tasklet, output_tasklet, (unsigned long) output);
+	init_waitqueue_head(&output->wq);
+}
+
+static void ddb_ports_init(struct ddb *dev)
+{
+	int i;
+	struct ddb_port *port;
+
+	for (i = 0; i < dev->info->port_num; i++) {
+		port = &dev->port[i];
+		port->dev = dev;
+		port->nr = i;
+		port->i2c = &dev->i2c[i];
+		port->input[0] = &dev->input[2 * i];
+		port->input[1] = &dev->input[2 * i + 1];
+		port->output = &dev->output[i];
+
+		mutex_init(&port->i2c_gate_lock);
+		ddb_port_probe(port);
+		ddb_input_init(port, 2 * i);
+		ddb_input_init(port, 2 * i + 1);
+		ddb_output_init(port, i);
+	}
+}
+
+static void ddb_ports_release(struct ddb *dev)
+{
+	int i;
+	struct ddb_port *port;
+
+	for (i = 0; i < dev->info->port_num; i++) {
+		port = &dev->port[i];
+		port->dev = dev;
+		tasklet_kill(&port->input[0]->tasklet);
+		tasklet_kill(&port->input[1]->tasklet);
+		tasklet_kill(&port->output->tasklet);
+	}
+}
+
+/****************************************************************************/
+/****************************************************************************/
+/****************************************************************************/
+
+static void irq_handle_i2c(struct ddb *dev, int n)
+{
+	struct ddb_i2c *i2c = &dev->i2c[n];
+
+	i2c->done = 1;
+	wake_up(&i2c->wq);
+}
+
+static irqreturn_t irq_handler(int irq, void *dev_id)
+{
+	struct ddb *dev = (struct ddb *) dev_id;
+	u32 s = ddbreadl(INTERRUPT_STATUS);
+
+	if (!s)
+		return IRQ_NONE;
+
+	do {
+		ddbwritel(s, INTERRUPT_ACK);
+
+		if (s & 0x00000001)
+			irq_handle_i2c(dev, 0);
+		if (s & 0x00000002)
+			irq_handle_i2c(dev, 1);
+		if (s & 0x00000004)
+			irq_handle_i2c(dev, 2);
+		if (s & 0x00000008)
+			irq_handle_i2c(dev, 3);
+
+		if (s & 0x00000100)
+			tasklet_schedule(&dev->input[0].tasklet);
+		if (s & 0x00000200)
+			tasklet_schedule(&dev->input[1].tasklet);
+		if (s & 0x00000400)
+			tasklet_schedule(&dev->input[2].tasklet);
+		if (s & 0x00000800)
+			tasklet_schedule(&dev->input[3].tasklet);
+		if (s & 0x00001000)
+			tasklet_schedule(&dev->input[4].tasklet);
+		if (s & 0x00002000)
+			tasklet_schedule(&dev->input[5].tasklet);
+		if (s & 0x00004000)
+			tasklet_schedule(&dev->input[6].tasklet);
+		if (s & 0x00008000)
+			tasklet_schedule(&dev->input[7].tasklet);
+
+		if (s & 0x00010000)
+			tasklet_schedule(&dev->output[0].tasklet);
+		if (s & 0x00020000)
+			tasklet_schedule(&dev->output[1].tasklet);
+		if (s & 0x00040000)
+			tasklet_schedule(&dev->output[2].tasklet);
+		if (s & 0x00080000)
+			tasklet_schedule(&dev->output[3].tasklet);
+
+		/* if (s & 0x000f0000)	printk(KERN_DEBUG "%08x\n", istat); */
+	} while ((s = ddbreadl(INTERRUPT_STATUS)));
+
+	return IRQ_HANDLED;
+}
+
+/******************************************************************************/
+/******************************************************************************/
+/******************************************************************************/
+
+static int flashio(struct ddb *dev, u8 *wbuf, u32 wlen, u8 *rbuf, u32 rlen)
+{
+	u32 data, shift;
+
+	if (wlen > 4)
+		ddbwritel(1, SPI_CONTROL);
+	while (wlen > 4) {
+		/* FIXME: check for big-endian */
+		data = swab32(*(u32 *)wbuf);
+		wbuf += 4;
+		wlen -= 4;
+		ddbwritel(data, SPI_DATA);
+		while (ddbreadl(SPI_CONTROL) & 0x0004)
+			;
+	}
+
+	if (rlen)
+		ddbwritel(0x0001 | ((wlen << (8 + 3)) & 0x1f00), SPI_CONTROL);
+	else
+		ddbwritel(0x0003 | ((wlen << (8 + 3)) & 0x1f00), SPI_CONTROL);
+
+	data = 0;
+	shift = ((4 - wlen) * 8);
+	while (wlen) {
+		data <<= 8;
+		data |= *wbuf;
+		wlen--;
+		wbuf++;
+	}
+	if (shift)
+		data <<= shift;
+	ddbwritel(data, SPI_DATA);
+	while (ddbreadl(SPI_CONTROL) & 0x0004)
+		;
+
+	if (!rlen) {
+		ddbwritel(0, SPI_CONTROL);
+		return 0;
+	}
+	if (rlen > 4)
+		ddbwritel(1, SPI_CONTROL);
+
+	while (rlen > 4) {
+		ddbwritel(0xffffffff, SPI_DATA);
+		while (ddbreadl(SPI_CONTROL) & 0x0004)
+			;
+		data = ddbreadl(SPI_DATA);
+		*(u32 *) rbuf = swab32(data);
+		rbuf += 4;
+		rlen -= 4;
+	}
+	ddbwritel(0x0003 | ((rlen << (8 + 3)) & 0x1F00), SPI_CONTROL);
+	ddbwritel(0xffffffff, SPI_DATA);
+	while (ddbreadl(SPI_CONTROL) & 0x0004)
+		;
+
+	data = ddbreadl(SPI_DATA);
+	ddbwritel(0, SPI_CONTROL);
+
+	if (rlen < 4)
+		data <<= ((4 - rlen) * 8);
+
+	while (rlen > 0) {
+		*rbuf = ((data >> 24) & 0xff);
+		data <<= 8;
+		rbuf++;
+		rlen--;
+	}
+	return 0;
+}
+
+#define DDB_MAGIC 'd'
+
+struct ddb_flashio {
+	__u8 *write_buf;
+	__u32 write_len;
+	__u8 *read_buf;
+	__u32 read_len;
+};
+
+#define IOCTL_DDB_FLASHIO  _IOWR(DDB_MAGIC, 0x00, struct ddb_flashio)
+
+#define DDB_NAME "ddbridge"
+
+static u32 ddb_num;
+static struct ddb *ddbs[32];
+static struct class *ddb_class;
+static int ddb_major;
+
+static int ddb_open(struct inode *inode, struct file *file)
+{
+	struct ddb *dev = ddbs[iminor(inode)];
+
+	file->private_data = dev;
+	return 0;
+}
+
+static long ddb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct ddb *dev = file->private_data;
+	void *parg = (void *)arg;
+	int res;
+
+	switch (cmd) {
+	case IOCTL_DDB_FLASHIO:
+	{
+		struct ddb_flashio fio;
+		u8 *rbuf, *wbuf;
+
+		if (copy_from_user(&fio, parg, sizeof(fio)))
+			return -EFAULT;
+
+		if (fio.write_len > 1028 || fio.read_len > 1028)
+			return -EINVAL;
+		if (fio.write_len + fio.read_len > 1028)
+			return -EINVAL;
+
+		wbuf = &dev->iobuf[0];
+		rbuf = wbuf + fio.write_len;
+
+		if (copy_from_user(wbuf, fio.write_buf, fio.write_len))
+			return -EFAULT;
+		res = flashio(dev, wbuf, fio.write_len, rbuf, fio.read_len);
+		if (res)
+			return res;
+		if (copy_to_user(fio.read_buf, rbuf, fio.read_len))
+			return -EFAULT;
+		break;
+	}
+	default:
+		return -ENOTTY;
+	}
+	return 0;
+}
+
+static const struct file_operations ddb_fops = {
+	.unlocked_ioctl = ddb_ioctl,
+	.open           = ddb_open,
+};
+
+static char *ddb_devnode(struct device *device, umode_t *mode)
+{
+	struct ddb *dev = dev_get_drvdata(device);
+
+	return kasprintf(GFP_KERNEL, "ddbridge/card%d", dev->nr);
+}
+
+static int ddb_class_create(void)
+{
+	ddb_major = register_chrdev(0, DDB_NAME, &ddb_fops);
+	if (ddb_major < 0)
+		return ddb_major;
+
+	ddb_class = class_create(THIS_MODULE, DDB_NAME);
+	if (IS_ERR(ddb_class)) {
+		unregister_chrdev(ddb_major, DDB_NAME);
+		return PTR_ERR(ddb_class);
+	}
+	ddb_class->devnode = ddb_devnode;
+	return 0;
+}
+
+static void ddb_class_destroy(void)
+{
+	class_destroy(ddb_class);
+	unregister_chrdev(ddb_major, DDB_NAME);
+}
+
+static int ddb_device_create(struct ddb *dev)
+{
+	dev->nr = ddb_num++;
+	dev->ddb_dev = device_create(ddb_class, NULL,
+				     MKDEV(ddb_major, dev->nr),
+				     dev, "ddbridge%d", dev->nr);
+	ddbs[dev->nr] = dev;
+	if (IS_ERR(dev->ddb_dev))
+		return -1;
+	return 0;
+}
+
+static void ddb_device_destroy(struct ddb *dev)
+{
+	ddb_num--;
+	if (IS_ERR(dev->ddb_dev))
+		return;
+	device_destroy(ddb_class, MKDEV(ddb_major, 0));
+}
+
+
+/****************************************************************************/
+/****************************************************************************/
+/****************************************************************************/
+
+static void ddb_unmap(struct ddb *dev)
+{
+	if (dev->regs)
+		iounmap(dev->regs);
+	vfree(dev);
+}
+
+
+static void __devexit ddb_remove(struct pci_dev *pdev)
+{
+	struct ddb *dev = (struct ddb *) pci_get_drvdata(pdev);
+
+	ddb_ports_detach(dev);
+	ddb_i2c_release(dev);
+
+	ddbwritel(0, INTERRUPT_ENABLE);
+	free_irq(dev->pdev->irq, dev);
+#ifdef CONFIG_PCI_MSI
+	if (dev->msi)
+		pci_disable_msi(dev->pdev);
+#endif
+	ddb_ports_release(dev);
+	ddb_buffers_free(dev);
+	ddb_device_destroy(dev);
+
+	ddb_unmap(dev);
+	pci_set_drvdata(pdev, 0);
+	pci_disable_device(pdev);
+}
+
+
+static int __devinit ddb_probe(struct pci_dev *pdev,
+			       const struct pci_device_id *id)
+{
+	struct ddb *dev;
+	int stat = 0;
+	int irq_flag = IRQF_SHARED;
+
+	if (pci_enable_device(pdev) < 0)
+		return -ENODEV;
+
+	dev = vmalloc(sizeof(struct ddb));
+	if (dev == NULL)
+		return -ENOMEM;
+	memset(dev, 0, sizeof(struct ddb));
+
+	dev->pdev = pdev;
+	pci_set_drvdata(pdev, dev);
+	dev->info = (struct ddb_info *) id->driver_data;
+	printk(KERN_INFO "DDBridge driver detected: %s\n", dev->info->name);
+
+	dev->regs = ioremap(pci_resource_start(dev->pdev, 0),
+			    pci_resource_len(dev->pdev, 0));
+	if (!dev->regs) {
+		stat = -ENOMEM;
+		goto fail;
+	}
+	printk(KERN_INFO "HW %08x FW %08x\n", ddbreadl(0), ddbreadl(4));
+
+#ifdef CONFIG_PCI_MSI
+	if (pci_msi_enabled())
+		stat = pci_enable_msi(dev->pdev);
+	if (stat) {
+		printk(KERN_INFO ": MSI not available.\n");
+	} else {
+		irq_flag = 0;
+		dev->msi = 1;
+	}
+#endif
+	stat = request_irq(dev->pdev->irq, irq_handler,
+			   irq_flag, "DDBridge", (void *) dev);
+	if (stat < 0)
+		goto fail1;
+	ddbwritel(0, DMA_BASE_WRITE);
+	ddbwritel(0, DMA_BASE_READ);
+	ddbwritel(0xffffffff, INTERRUPT_ACK);
+	ddbwritel(0xfff0f, INTERRUPT_ENABLE);
+	ddbwritel(0, MSI1_ENABLE);
+
+	if (ddb_i2c_init(dev) < 0)
+		goto fail1;
+	ddb_ports_init(dev);
+	if (ddb_buffers_alloc(dev) < 0) {
+		printk(KERN_INFO ": Could not allocate buffer memory\n");
+		goto fail2;
+	}
+	if (ddb_ports_attach(dev) < 0)
+		goto fail3;
+	ddb_device_create(dev);
+	return 0;
+
+fail3:
+	ddb_ports_detach(dev);
+	printk(KERN_ERR "fail3\n");
+	ddb_ports_release(dev);
+fail2:
+	printk(KERN_ERR "fail2\n");
+	ddb_buffers_free(dev);
+fail1:
+	printk(KERN_ERR "fail1\n");
+	if (dev->msi)
+		pci_disable_msi(dev->pdev);
+	free_irq(dev->pdev->irq, dev);
+fail:
+	printk(KERN_ERR "fail\n");
+	ddb_unmap(dev);
+	pci_set_drvdata(pdev, 0);
+	pci_disable_device(pdev);
+	return -1;
+}
+
+/******************************************************************************/
+/******************************************************************************/
+/******************************************************************************/
+
+static struct ddb_info ddb_none = {
+	.type     = DDB_NONE,
+	.name     = "Digital Devices PCIe bridge",
+};
+
+static struct ddb_info ddb_octopus = {
+	.type     = DDB_OCTOPUS,
+	.name     = "Digital Devices Octopus DVB adapter",
+	.port_num = 4,
+};
+
+static struct ddb_info ddb_octopus_le = {
+	.type     = DDB_OCTOPUS,
+	.name     = "Digital Devices Octopus LE DVB adapter",
+	.port_num = 2,
+};
+
+static struct ddb_info ddb_v6 = {
+	.type     = DDB_OCTOPUS,
+	.name     = "Digital Devices Cine S2 V6 DVB adapter",
+	.port_num = 3,
+};
+
+#define DDVID 0xdd01 /* Digital Devices Vendor ID */
+
+#define DDB_ID(_vend, _dev, _subvend, _subdev, _driverdata) {	\
+	.vendor      = _vend,    .device    = _dev, \
+	.subvendor   = _subvend, .subdevice = _subdev, \
+	.driver_data = (unsigned long)&_driverdata }
+
+static const struct pci_device_id ddb_id_tbl[] __devinitdata = {
+	DDB_ID(DDVID, 0x0002, DDVID, 0x0001, ddb_octopus),
+	DDB_ID(DDVID, 0x0003, DDVID, 0x0001, ddb_octopus),
+	DDB_ID(DDVID, 0x0003, DDVID, 0x0002, ddb_octopus_le),
+	DDB_ID(DDVID, 0x0003, DDVID, 0x0010, ddb_octopus),
+	DDB_ID(DDVID, 0x0003, DDVID, 0x0020, ddb_v6),
+	/* in case sub-ids got deleted in flash */
+	DDB_ID(DDVID, 0x0003, PCI_ANY_ID, PCI_ANY_ID, ddb_none),
+	{0}
+};
+MODULE_DEVICE_TABLE(pci, ddb_id_tbl);
+
+
+static struct pci_driver ddb_pci_driver = {
+	.name        = "DDBridge",
+	.id_table    = ddb_id_tbl,
+	.probe       = ddb_probe,
+	.remove      = __devexit_p(ddb_remove),
+};
+
+static __init int module_init_ddbridge(void)
+{
+	int ret;
+
+	printk(KERN_INFO "Digital Devices PCIE bridge driver, "
+	       "Copyright (C) 2010-11 Digital Devices GmbH\n");
+
+	ret = ddb_class_create();
+	if (ret < 0)
+		return ret;
+	ret = pci_register_driver(&ddb_pci_driver);
+	if (ret < 0)
+		ddb_class_destroy();
+	return ret;
+}
+
+static __exit void module_exit_ddbridge(void)
+{
+	pci_unregister_driver(&ddb_pci_driver);
+	ddb_class_destroy();
+}
+
+module_init(module_init_ddbridge);
+module_exit(module_exit_ddbridge);
+
+MODULE_DESCRIPTION("Digital Devices PCIe Bridge");
+MODULE_AUTHOR("Ralph Metzler");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("0.5");
diff --git a/drivers/media/pci/ddbridge/ddbridge-regs.h b/drivers/media/pci/ddbridge/ddbridge-regs.h
new file mode 100644
index 0000000..a3ccb31
--- /dev/null
+++ b/drivers/media/pci/ddbridge/ddbridge-regs.h
@@ -0,0 +1,151 @@
+/*
+ * ddbridge-regs.h: Digital Devices PCIe bridge driver
+ *
+ * Copyright (C) 2010-2011 Digital Devices GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 only, as published by the Free Software Foundation.
+ *
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ */
+
+/* DD-DVBBridgeV1.h 273 2010-09-17 05:03:16Z manfred */
+
+/* Register Definitions */
+
+#define CUR_REGISTERMAP_VERSION 0x10000
+
+#define HARDWARE_VERSION       0x00
+#define REGISTERMAP_VERSION    0x04
+
+/* ------------------------------------------------------------------------- */
+/* SPI Controller */
+
+#define SPI_CONTROL     0x10
+#define SPI_DATA        0x14
+
+/* ------------------------------------------------------------------------- */
+
+/* Interrupt controller                                     */
+/* How many MSI's are available depends on HW (Min 2 max 8) */
+/* How many are usable also depends on Host platform        */
+
+#define INTERRUPT_BASE   (0x40)
+
+#define INTERRUPT_ENABLE (INTERRUPT_BASE + 0x00)
+#define MSI0_ENABLE      (INTERRUPT_BASE + 0x00)
+#define MSI1_ENABLE      (INTERRUPT_BASE + 0x04)
+#define MSI2_ENABLE      (INTERRUPT_BASE + 0x08)
+#define MSI3_ENABLE      (INTERRUPT_BASE + 0x0C)
+#define MSI4_ENABLE      (INTERRUPT_BASE + 0x10)
+#define MSI5_ENABLE      (INTERRUPT_BASE + 0x14)
+#define MSI6_ENABLE      (INTERRUPT_BASE + 0x18)
+#define MSI7_ENABLE      (INTERRUPT_BASE + 0x1C)
+
+#define INTERRUPT_STATUS (INTERRUPT_BASE + 0x20)
+#define INTERRUPT_ACK    (INTERRUPT_BASE + 0x20)
+
+#define INTMASK_I2C1        (0x00000001)
+#define INTMASK_I2C2        (0x00000002)
+#define INTMASK_I2C3        (0x00000004)
+#define INTMASK_I2C4        (0x00000008)
+
+#define INTMASK_CIRQ1       (0x00000010)
+#define INTMASK_CIRQ2       (0x00000020)
+#define INTMASK_CIRQ3       (0x00000040)
+#define INTMASK_CIRQ4       (0x00000080)
+
+#define INTMASK_TSINPUT1    (0x00000100)
+#define INTMASK_TSINPUT2    (0x00000200)
+#define INTMASK_TSINPUT3    (0x00000400)
+#define INTMASK_TSINPUT4    (0x00000800)
+#define INTMASK_TSINPUT5    (0x00001000)
+#define INTMASK_TSINPUT6    (0x00002000)
+#define INTMASK_TSINPUT7    (0x00004000)
+#define INTMASK_TSINPUT8    (0x00008000)
+
+#define INTMASK_TSOUTPUT1   (0x00010000)
+#define INTMASK_TSOUTPUT2   (0x00020000)
+#define INTMASK_TSOUTPUT3   (0x00040000)
+#define INTMASK_TSOUTPUT4   (0x00080000)
+
+/* ------------------------------------------------------------------------- */
+/* I2C Master Controller */
+
+#define I2C_BASE        (0x80)  /* Byte offset */
+
+#define I2C_COMMAND     (0x00)
+#define I2C_TIMING      (0x04)
+#define I2C_TASKLENGTH  (0x08)     /* High read, low write */
+#define I2C_TASKADDRESS (0x0C)     /* High read, low write */
+
+#define I2C_MONITOR     (0x1C)
+
+#define I2C_BASE_1      (I2C_BASE + 0x00)
+#define I2C_BASE_2      (I2C_BASE + 0x20)
+#define I2C_BASE_3      (I2C_BASE + 0x40)
+#define I2C_BASE_4      (I2C_BASE + 0x60)
+
+#define I2C_BASE_N(i)   (I2C_BASE + (i) * 0x20)
+
+#define I2C_TASKMEM_BASE    (0x1000)    /* Byte offset */
+#define I2C_TASKMEM_SIZE    (0x1000)
+
+#define I2C_SPEED_400   (0x04030404)
+#define I2C_SPEED_200   (0x09080909)
+#define I2C_SPEED_154   (0x0C0B0C0C)
+#define I2C_SPEED_100   (0x13121313)
+#define I2C_SPEED_77    (0x19181919)
+#define I2C_SPEED_50    (0x27262727)
+
+
+/* ------------------------------------------------------------------------- */
+/* DMA  Controller */
+
+#define DMA_BASE_WRITE        (0x100)
+#define DMA_BASE_READ         (0x140)
+
+#define DMA_CONTROL     (0x00)                  /* 64 */
+#define DMA_ERROR       (0x04)                  /* 65 ( only read instance ) */
+
+#define DMA_DIAG_CONTROL                (0x1C)  /* 71 */
+#define DMA_DIAG_PACKETCOUNTER_LOW      (0x20)  /* 72 */
+#define DMA_DIAG_PACKETCOUNTER_HIGH     (0x24)  /* 73 */
+#define DMA_DIAG_TIMECOUNTER_LOW        (0x28)  /* 74 */
+#define DMA_DIAG_TIMECOUNTER_HIGH       (0x2C)  /* 75 */
+#define DMA_DIAG_RECHECKCOUNTER         (0x30)  /* 76  ( Split completions on read ) */
+#define DMA_DIAG_WAITTIMEOUTINIT        (0x34)  /* 77 */
+#define DMA_DIAG_WAITOVERFLOWCOUNTER    (0x38)  /* 78 */
+#define DMA_DIAG_WAITCOUNTER            (0x3C)  /* 79 */
+
+/* ------------------------------------------------------------------------- */
+/* DMA  Buffer */
+
+#define TS_INPUT_BASE       (0x200)
+#define TS_INPUT_CONTROL(i)         (TS_INPUT_BASE + (i) * 16 + 0x00)
+
+#define TS_OUTPUT_BASE       (0x280)
+#define TS_OUTPUT_CONTROL(i)         (TS_OUTPUT_BASE + (i) * 16 + 0x00)
+
+#define DMA_BUFFER_BASE     (0x300)
+
+#define DMA_BUFFER_CONTROL(i)       (DMA_BUFFER_BASE + (i) * 16 + 0x00)
+#define DMA_BUFFER_ACK(i)           (DMA_BUFFER_BASE + (i) * 16 + 0x04)
+#define DMA_BUFFER_CURRENT(i)       (DMA_BUFFER_BASE + (i) * 16 + 0x08)
+#define DMA_BUFFER_SIZE(i)          (DMA_BUFFER_BASE + (i) * 16 + 0x0c)
+
+#define DMA_BASE_ADDRESS_TABLE  (0x2000)
+#define DMA_BASE_ADDRESS_TABLE_ENTRIES (512)
+
diff --git a/drivers/media/pci/ddbridge/ddbridge.h b/drivers/media/pci/ddbridge/ddbridge.h
new file mode 100644
index 0000000..8b1b41d
--- /dev/null
+++ b/drivers/media/pci/ddbridge/ddbridge.h
@@ -0,0 +1,185 @@
+/*
+ * ddbridge.h: Digital Devices PCIe bridge driver
+ *
+ * Copyright (C) 2010-2011 Digital Devices GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 only, as published by the Free Software Foundation.
+ *
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ */
+
+#ifndef _DDBRIDGE_H_
+#define _DDBRIDGE_H_
+
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+#include <asm/dma.h>
+#include <linux/dvb/frontend.h>
+#include <linux/dvb/ca.h>
+#include <linux/socket.h>
+
+#include "dmxdev.h"
+#include "dvbdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dvb_ringbuffer.h"
+#include "dvb_ca_en50221.h"
+#include "dvb_net.h"
+#include "cxd2099.h"
+
+#define DDB_MAX_I2C     4
+#define DDB_MAX_PORT    4
+#define DDB_MAX_INPUT   8
+#define DDB_MAX_OUTPUT  4
+
+struct ddb_info {
+	int   type;
+#define DDB_NONE         0
+#define DDB_OCTOPUS      1
+	char *name;
+	int   port_num;
+	u32   port_type[DDB_MAX_PORT];
+};
+
+/* DMA_SIZE MUST be divisible by 188 and 128 !!! */
+
+#define INPUT_DMA_MAX_BUFS 32      /* hardware table limit */
+#define INPUT_DMA_BUFS 8
+#define INPUT_DMA_SIZE (128*47*21)
+
+#define OUTPUT_DMA_MAX_BUFS 32
+#define OUTPUT_DMA_BUFS 8
+#define OUTPUT_DMA_SIZE (128*47*21)
+
+struct ddb;
+struct ddb_port;
+
+struct ddb_input {
+	struct ddb_port       *port;
+	u32                    nr;
+	int                    attached;
+
+	dma_addr_t             pbuf[INPUT_DMA_MAX_BUFS];
+	u8                    *vbuf[INPUT_DMA_MAX_BUFS];
+	u32                    dma_buf_num;
+	u32                    dma_buf_size;
+
+	struct tasklet_struct  tasklet;
+	spinlock_t             lock;
+	wait_queue_head_t      wq;
+	int                    running;
+	u32                    stat;
+	u32                    cbuf;
+	u32                    coff;
+
+	struct dvb_adapter     adap;
+	struct dvb_device     *dev;
+	struct dvb_frontend   *fe;
+	struct dvb_frontend   *fe2;
+	struct dmxdev          dmxdev;
+	struct dvb_demux       demux;
+	struct dvb_net         dvbnet;
+	struct dmx_frontend    hw_frontend;
+	struct dmx_frontend    mem_frontend;
+	int                    users;
+	int (*gate_ctrl)(struct dvb_frontend *, int);
+};
+
+struct ddb_output {
+	struct ddb_port       *port;
+	u32                    nr;
+	dma_addr_t             pbuf[OUTPUT_DMA_MAX_BUFS];
+	u8                    *vbuf[OUTPUT_DMA_MAX_BUFS];
+	u32                    dma_buf_num;
+	u32                    dma_buf_size;
+	struct tasklet_struct  tasklet;
+	spinlock_t             lock;
+	wait_queue_head_t      wq;
+	int                    running;
+	u32                    stat;
+	u32                    cbuf;
+	u32                    coff;
+
+	struct dvb_adapter     adap;
+	struct dvb_device     *dev;
+};
+
+struct ddb_i2c {
+	struct ddb            *dev;
+	u32                    nr;
+	struct i2c_adapter     adap;
+	struct i2c_adapter     adap2;
+	u32                    regs;
+	u32                    rbuf;
+	u32                    wbuf;
+	int                    done;
+	wait_queue_head_t      wq;
+};
+
+struct ddb_port {
+	struct ddb            *dev;
+	u32                    nr;
+	struct ddb_i2c        *i2c;
+	struct mutex           i2c_gate_lock;
+	u32                    class;
+#define DDB_PORT_NONE           0
+#define DDB_PORT_CI             1
+#define DDB_PORT_TUNER          2
+	u32                    type;
+#define DDB_TUNER_NONE          0
+#define DDB_TUNER_DVBS_ST       1
+#define DDB_TUNER_DVBS_ST_AA    2
+#define DDB_TUNER_DVBCT_TR     16
+#define DDB_TUNER_DVBCT_ST     17
+	u32                    adr;
+
+	struct ddb_input      *input[2];
+	struct ddb_output     *output;
+	struct dvb_ca_en50221 *en;
+};
+
+struct ddb {
+	struct pci_dev        *pdev;
+	unsigned char         *regs;
+	struct ddb_port        port[DDB_MAX_PORT];
+	struct ddb_i2c         i2c[DDB_MAX_I2C];
+	struct ddb_input       input[DDB_MAX_INPUT];
+	struct ddb_output      output[DDB_MAX_OUTPUT];
+
+	struct device         *ddb_dev;
+	int                    nr;
+	u8                     iobuf[1028];
+
+	struct ddb_info       *info;
+	int                    msi;
+};
+
+/****************************************************************************/
+
+#define ddbwritel(_val, _adr)        writel((_val), \
+				     (char *) (dev->regs+(_adr)))
+#define ddbreadl(_adr)               readl((char *) (dev->regs+(_adr)))
+#define ddbcpyto(_adr, _src, _count) memcpy_toio((char *)	\
+				     (dev->regs+(_adr)), (_src), (_count))
+#define ddbcpyfrom(_dst, _adr, _count) memcpy_fromio((_dst), (char *) \
+				       (dev->regs+(_adr)), (_count))
+
+/****************************************************************************/
+
+#endif
diff --git a/drivers/media/pci/dm1105/Kconfig b/drivers/media/pci/dm1105/Kconfig
new file mode 100644
index 0000000..013df4e
--- /dev/null
+++ b/drivers/media/pci/dm1105/Kconfig
@@ -0,0 +1,20 @@
+config DVB_DM1105
+	tristate "SDMC DM1105 based PCI cards"
+	depends on DVB_CORE && PCI && I2C
+	select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_STV0299 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_STV0288 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_STB6000 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_CX24116 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_SI21XX if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_DS3000 if MEDIA_SUBDRV_AUTOSELECT
+	depends on RC_CORE
+	help
+	  Support for cards based on the SDMC DM1105 PCI chip like
+	  DvbWorld 2002
+
+	  Since these cards have no MPEG decoder onboard, they transmit
+	  only compressed MPEG data over the PCI bus, so you need
+	  an external software decoder to watch TV on your computer.
+
+	  Say Y or M if you own such a device and want to use it.
diff --git a/drivers/media/pci/dm1105/Makefile b/drivers/media/pci/dm1105/Makefile
new file mode 100644
index 0000000..3275851
--- /dev/null
+++ b/drivers/media/pci/dm1105/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_DVB_DM1105) += dm1105.o
+
+ccflags-y += -Idrivers/media/dvb-core/ -Idrivers/media/dvb-frontends
diff --git a/drivers/media/pci/dm1105/dm1105.c b/drivers/media/pci/dm1105/dm1105.c
new file mode 100644
index 0000000..a609b3a
--- /dev/null
+++ b/drivers/media/pci/dm1105/dm1105.c
@@ -0,0 +1,1248 @@
+/*
+ * dm1105.c - driver for DVB cards based on SDMC DM1105 PCI chip
+ *
+ * Copyright (C) 2008 Igor M. Liplianin <liplianin@me.by>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/i2c.h>
+#include <linux/i2c-algo-bit.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/proc_fs.h>
+#include <linux/pci.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <media/rc-core.h>
+
+#include "demux.h"
+#include "dmxdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dvb_net.h"
+#include "dvbdev.h"
+#include "dvb-pll.h"
+
+#include "stv0299.h"
+#include "stv0288.h"
+#include "stb6000.h"
+#include "si21xx.h"
+#include "cx24116.h"
+#include "z0194a.h"
+#include "ds3000.h"
+
+#define MODULE_NAME "dm1105"
+
+#define UNSET (-1U)
+
+#define DM1105_BOARD_NOAUTO			UNSET
+#define DM1105_BOARD_UNKNOWN			0
+#define DM1105_BOARD_DVBWORLD_2002		1
+#define DM1105_BOARD_DVBWORLD_2004		2
+#define DM1105_BOARD_AXESS_DM05			3
+#define DM1105_BOARD_UNBRANDED_I2C_ON_GPIO	4
+
+/* ----------------------------------------------- */
+/*
+ * PCI ID's
+ */
+#ifndef PCI_VENDOR_ID_TRIGEM
+#define PCI_VENDOR_ID_TRIGEM	0x109f
+#endif
+#ifndef PCI_VENDOR_ID_AXESS
+#define PCI_VENDOR_ID_AXESS	0x195d
+#endif
+#ifndef PCI_DEVICE_ID_DM1105
+#define PCI_DEVICE_ID_DM1105	0x036f
+#endif
+#ifndef PCI_DEVICE_ID_DW2002
+#define PCI_DEVICE_ID_DW2002	0x2002
+#endif
+#ifndef PCI_DEVICE_ID_DW2004
+#define PCI_DEVICE_ID_DW2004	0x2004
+#endif
+#ifndef PCI_DEVICE_ID_DM05
+#define PCI_DEVICE_ID_DM05	0x1105
+#endif
+/* ----------------------------------------------- */
+/* sdmc dm1105 registers */
+
+/* TS Control */
+#define DM1105_TSCTR				0x00
+#define DM1105_DTALENTH				0x04
+
+/* GPIO Interface */
+#define DM1105_GPIOVAL				0x08
+#define DM1105_GPIOCTR				0x0c
+
+/* PID serial number */
+#define DM1105_PIDN				0x10
+
+/* Odd-even secret key select */
+#define DM1105_CWSEL				0x14
+
+/* Host Command Interface */
+#define DM1105_HOST_CTR				0x18
+#define DM1105_HOST_AD				0x1c
+
+/* PCI Interface */
+#define DM1105_CR				0x30
+#define DM1105_RST				0x34
+#define DM1105_STADR				0x38
+#define DM1105_RLEN				0x3c
+#define DM1105_WRP				0x40
+#define DM1105_INTCNT				0x44
+#define DM1105_INTMAK				0x48
+#define DM1105_INTSTS				0x4c
+
+/* CW Value */
+#define DM1105_ODD				0x50
+#define DM1105_EVEN				0x58
+
+/* PID Value */
+#define DM1105_PID				0x60
+
+/* IR Control */
+#define DM1105_IRCTR				0x64
+#define DM1105_IRMODE				0x68
+#define DM1105_SYSTEMCODE			0x6c
+#define DM1105_IRCODE				0x70
+
+/* Unknown Values */
+#define DM1105_ENCRYPT				0x74
+#define DM1105_VER				0x7c
+
+/* I2C Interface */
+#define DM1105_I2CCTR				0x80
+#define DM1105_I2CSTS				0x81
+#define DM1105_I2CDAT				0x82
+#define DM1105_I2C_RA				0x83
+/* ----------------------------------------------- */
+/* Interrupt Mask Bits */
+
+#define INTMAK_TSIRQM				0x01
+#define INTMAK_HIRQM				0x04
+#define INTMAK_IRM				0x08
+#define INTMAK_ALLMASK				(INTMAK_TSIRQM | \
+						INTMAK_HIRQM | \
+						INTMAK_IRM)
+#define INTMAK_NONEMASK				0x00
+
+/* Interrupt Status Bits */
+#define INTSTS_TSIRQ				0x01
+#define INTSTS_HIRQ				0x04
+#define INTSTS_IR				0x08
+
+/* IR Control Bits */
+#define DM1105_IR_EN				0x01
+#define DM1105_SYS_CHK				0x02
+#define DM1105_REP_FLG				0x08
+
+/* EEPROM addr */
+#define IIC_24C01_addr				0xa0
+/* Max board count */
+#define DM1105_MAX				0x04
+
+#define DRIVER_NAME				"dm1105"
+#define DM1105_I2C_GPIO_NAME			"dm1105-gpio"
+
+#define DM1105_DMA_PACKETS			47
+#define DM1105_DMA_PACKET_LENGTH		(128*4)
+#define DM1105_DMA_BYTES			(128 * 4 * DM1105_DMA_PACKETS)
+
+/*  */
+#define GPIO08					(1 << 8)
+#define GPIO13					(1 << 13)
+#define GPIO14					(1 << 14)
+#define GPIO15					(1 << 15)
+#define GPIO16					(1 << 16)
+#define GPIO17					(1 << 17)
+#define GPIO_ALL				0x03ffff
+
+/* GPIO's for LNB power control */
+#define DM1105_LNB_MASK				(GPIO_ALL & ~(GPIO14 | GPIO13))
+#define DM1105_LNB_OFF				GPIO17
+#define DM1105_LNB_13V				(GPIO16 | GPIO08)
+#define DM1105_LNB_18V				GPIO08
+
+/* GPIO's for LNB power control for Axess DM05 */
+#define DM05_LNB_MASK				(GPIO_ALL & ~(GPIO14 | GPIO13))
+#define DM05_LNB_OFF				GPIO17/* actually 13v */
+#define DM05_LNB_13V				GPIO17
+#define DM05_LNB_18V				(GPIO17 | GPIO16)
+
+/* GPIO's for LNB power control for unbranded with I2C on GPIO */
+#define UNBR_LNB_MASK				(GPIO17 | GPIO16)
+#define UNBR_LNB_OFF				0
+#define UNBR_LNB_13V				GPIO17
+#define UNBR_LNB_18V				(GPIO17 | GPIO16)
+
+static unsigned int card[]  = {[0 ... 3] = UNSET };
+module_param_array(card,  int, NULL, 0444);
+MODULE_PARM_DESC(card, "card type");
+
+static int ir_debug;
+module_param(ir_debug, int, 0644);
+MODULE_PARM_DESC(ir_debug, "enable debugging information for IR decoding");
+
+static unsigned int dm1105_devcount;
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+struct dm1105_board {
+	char	*name;
+	struct	{
+		u32	mask, off, v13, v18;
+	} lnb;
+	u32	gpio_scl, gpio_sda;
+};
+
+struct dm1105_subid {
+	u16     subvendor;
+	u16     subdevice;
+	u32     card;
+};
+
+static const struct dm1105_board dm1105_boards[] = {
+	[DM1105_BOARD_UNKNOWN] = {
+		.name		= "UNKNOWN/GENERIC",
+		.lnb = {
+			.mask = DM1105_LNB_MASK,
+			.off = DM1105_LNB_OFF,
+			.v13 = DM1105_LNB_13V,
+			.v18 = DM1105_LNB_18V,
+		},
+	},
+	[DM1105_BOARD_DVBWORLD_2002] = {
+		.name		= "DVBWorld PCI 2002",
+		.lnb = {
+			.mask = DM1105_LNB_MASK,
+			.off = DM1105_LNB_OFF,
+			.v13 = DM1105_LNB_13V,
+			.v18 = DM1105_LNB_18V,
+		},
+	},
+	[DM1105_BOARD_DVBWORLD_2004] = {
+		.name		= "DVBWorld PCI 2004",
+		.lnb = {
+			.mask = DM1105_LNB_MASK,
+			.off = DM1105_LNB_OFF,
+			.v13 = DM1105_LNB_13V,
+			.v18 = DM1105_LNB_18V,
+		},
+	},
+	[DM1105_BOARD_AXESS_DM05] = {
+		.name		= "Axess/EasyTv DM05",
+		.lnb = {
+			.mask = DM05_LNB_MASK,
+			.off = DM05_LNB_OFF,
+			.v13 = DM05_LNB_13V,
+			.v18 = DM05_LNB_18V,
+		},
+	},
+	[DM1105_BOARD_UNBRANDED_I2C_ON_GPIO] = {
+		.name		= "Unbranded DM1105 with i2c on GPIOs",
+		.lnb = {
+			.mask = UNBR_LNB_MASK,
+			.off = UNBR_LNB_OFF,
+			.v13 = UNBR_LNB_13V,
+			.v18 = UNBR_LNB_18V,
+		},
+		.gpio_scl	= GPIO14,
+		.gpio_sda	= GPIO13,
+	},
+};
+
+static const struct dm1105_subid dm1105_subids[] = {
+	{
+		.subvendor = 0x0000,
+		.subdevice = 0x2002,
+		.card      = DM1105_BOARD_DVBWORLD_2002,
+	}, {
+		.subvendor = 0x0001,
+		.subdevice = 0x2002,
+		.card      = DM1105_BOARD_DVBWORLD_2002,
+	}, {
+		.subvendor = 0x0000,
+		.subdevice = 0x2004,
+		.card      = DM1105_BOARD_DVBWORLD_2004,
+	}, {
+		.subvendor = 0x0001,
+		.subdevice = 0x2004,
+		.card      = DM1105_BOARD_DVBWORLD_2004,
+	}, {
+		.subvendor = 0x195d,
+		.subdevice = 0x1105,
+		.card      = DM1105_BOARD_AXESS_DM05,
+	},
+};
+
+static void dm1105_card_list(struct pci_dev *pci)
+{
+	int i;
+
+	if (0 == pci->subsystem_vendor &&
+			0 == pci->subsystem_device) {
+		printk(KERN_ERR
+			"dm1105: Your board has no valid PCI Subsystem ID\n"
+			"dm1105: and thus can't be autodetected\n"
+			"dm1105: Please pass card=<n> insmod option to\n"
+			"dm1105: workaround that.  Redirect complaints to\n"
+			"dm1105: the vendor of the TV card.  Best regards,\n"
+			"dm1105: -- tux\n");
+	} else {
+		printk(KERN_ERR
+			"dm1105: Your board isn't known (yet) to the driver.\n"
+			"dm1105: You can try to pick one of the existing\n"
+			"dm1105: card configs via card=<n> insmod option.\n"
+			"dm1105: Updating to the latest version might help\n"
+			"dm1105: as well.\n");
+	}
+	printk(KERN_ERR "Here is a list of valid choices for the card=<n> "
+		   "insmod option:\n");
+	for (i = 0; i < ARRAY_SIZE(dm1105_boards); i++)
+		printk(KERN_ERR "dm1105:    card=%d -> %s\n",
+				i, dm1105_boards[i].name);
+}
+
+/* infrared remote control */
+struct infrared {
+	struct rc_dev		*dev;
+	char			input_phys[32];
+	struct work_struct	work;
+	u32			ir_command;
+};
+
+struct dm1105_dev {
+	/* pci */
+	struct pci_dev *pdev;
+	u8 __iomem *io_mem;
+
+	/* ir */
+	struct infrared ir;
+
+	/* dvb */
+	struct dmx_frontend hw_frontend;
+	struct dmx_frontend mem_frontend;
+	struct dmxdev dmxdev;
+	struct dvb_adapter dvb_adapter;
+	struct dvb_demux demux;
+	struct dvb_frontend *fe;
+	struct dvb_net dvbnet;
+	unsigned int full_ts_users;
+	unsigned int boardnr;
+	int nr;
+
+	/* i2c */
+	struct i2c_adapter i2c_adap;
+	struct i2c_adapter i2c_bb_adap;
+	struct i2c_algo_bit_data i2c_bit;
+
+	/* irq */
+	struct work_struct work;
+	struct workqueue_struct *wq;
+	char wqn[16];
+
+	/* dma */
+	dma_addr_t dma_addr;
+	unsigned char *ts_buf;
+	u32 wrp;
+	u32 nextwrp;
+	u32 buffer_size;
+	unsigned int	PacketErrorCount;
+	unsigned int dmarst;
+	spinlock_t lock;
+};
+
+#define dm_io_mem(reg)	((unsigned long)(&dev->io_mem[reg]))
+
+#define dm_readb(reg)		inb(dm_io_mem(reg))
+#define dm_writeb(reg, value)	outb((value), (dm_io_mem(reg)))
+
+#define dm_readw(reg)		inw(dm_io_mem(reg))
+#define dm_writew(reg, value)	outw((value), (dm_io_mem(reg)))
+
+#define dm_readl(reg)		inl(dm_io_mem(reg))
+#define dm_writel(reg, value)	outl((value), (dm_io_mem(reg)))
+
+#define dm_andorl(reg, mask, value) \
+	outl((inl(dm_io_mem(reg)) & ~(mask)) |\
+		((value) & (mask)), (dm_io_mem(reg)))
+
+#define dm_setl(reg, bit)	dm_andorl((reg), (bit), (bit))
+#define dm_clearl(reg, bit)	dm_andorl((reg), (bit), 0)
+
+/* The chip has 18 GPIOs. In HOST mode GPIO's used as 15 bit address lines,
+ so we can use only 3 GPIO's from GPIO15 to GPIO17.
+ Here I don't check whether HOST is enebled as it is not implemented yet.
+ */
+static void dm1105_gpio_set(struct dm1105_dev *dev, u32 mask)
+{
+	if (mask & 0xfffc0000)
+		printk(KERN_ERR "%s: Only 18 GPIO's are allowed\n", __func__);
+
+	if (mask & 0x0003ffff)
+		dm_setl(DM1105_GPIOVAL, mask & 0x0003ffff);
+
+}
+
+static void dm1105_gpio_clear(struct dm1105_dev *dev, u32 mask)
+{
+	if (mask & 0xfffc0000)
+		printk(KERN_ERR "%s: Only 18 GPIO's are allowed\n", __func__);
+
+	if (mask & 0x0003ffff)
+		dm_clearl(DM1105_GPIOVAL, mask & 0x0003ffff);
+
+}
+
+static void dm1105_gpio_andor(struct dm1105_dev *dev, u32 mask, u32 val)
+{
+	if (mask & 0xfffc0000)
+		printk(KERN_ERR "%s: Only 18 GPIO's are allowed\n", __func__);
+
+	if (mask & 0x0003ffff)
+		dm_andorl(DM1105_GPIOVAL, mask & 0x0003ffff, val);
+
+}
+
+static u32 dm1105_gpio_get(struct dm1105_dev *dev, u32 mask)
+{
+	if (mask & 0xfffc0000)
+		printk(KERN_ERR "%s: Only 18 GPIO's are allowed\n", __func__);
+
+	if (mask & 0x0003ffff)
+		return dm_readl(DM1105_GPIOVAL) & mask & 0x0003ffff;
+
+	return 0;
+}
+
+static void dm1105_gpio_enable(struct dm1105_dev *dev, u32 mask, int asoutput)
+{
+	if (mask & 0xfffc0000)
+		printk(KERN_ERR "%s: Only 18 GPIO's are allowed\n", __func__);
+
+	if ((mask & 0x0003ffff) && asoutput)
+		dm_clearl(DM1105_GPIOCTR, mask & 0x0003ffff);
+	else if ((mask & 0x0003ffff) && !asoutput)
+		dm_setl(DM1105_GPIOCTR, mask & 0x0003ffff);
+
+}
+
+static void dm1105_setline(struct dm1105_dev *dev, u32 line, int state)
+{
+	if (state)
+		dm1105_gpio_enable(dev, line, 0);
+	else {
+		dm1105_gpio_enable(dev, line, 1);
+		dm1105_gpio_clear(dev, line);
+	}
+}
+
+static void dm1105_setsda(void *data, int state)
+{
+	struct dm1105_dev *dev = data;
+
+	dm1105_setline(dev, dm1105_boards[dev->boardnr].gpio_sda, state);
+}
+
+static void dm1105_setscl(void *data, int state)
+{
+	struct dm1105_dev *dev = data;
+
+	dm1105_setline(dev, dm1105_boards[dev->boardnr].gpio_scl, state);
+}
+
+static int dm1105_getsda(void *data)
+{
+	struct dm1105_dev *dev = data;
+
+	return dm1105_gpio_get(dev, dm1105_boards[dev->boardnr].gpio_sda)
+									? 1 : 0;
+}
+
+static int dm1105_getscl(void *data)
+{
+	struct dm1105_dev *dev = data;
+
+	return dm1105_gpio_get(dev, dm1105_boards[dev->boardnr].gpio_scl)
+									? 1 : 0;
+}
+
+static int dm1105_i2c_xfer(struct i2c_adapter *i2c_adap,
+			    struct i2c_msg *msgs, int num)
+{
+	struct dm1105_dev *dev ;
+
+	int addr, rc, i, j, k, len, byte, data;
+	u8 status;
+
+	dev = i2c_adap->algo_data;
+	for (i = 0; i < num; i++) {
+		dm_writeb(DM1105_I2CCTR, 0x00);
+		if (msgs[i].flags & I2C_M_RD) {
+			/* read bytes */
+			addr  = msgs[i].addr << 1;
+			addr |= 1;
+			dm_writeb(DM1105_I2CDAT, addr);
+			for (byte = 0; byte < msgs[i].len; byte++)
+				dm_writeb(DM1105_I2CDAT + byte + 1, 0);
+
+			dm_writeb(DM1105_I2CCTR, 0x81 + msgs[i].len);
+			for (j = 0; j < 55; j++) {
+				mdelay(10);
+				status = dm_readb(DM1105_I2CSTS);
+				if ((status & 0xc0) == 0x40)
+					break;
+			}
+			if (j >= 55)
+				return -1;
+
+			for (byte = 0; byte < msgs[i].len; byte++) {
+				rc = dm_readb(DM1105_I2CDAT + byte + 1);
+				if (rc < 0)
+					goto err;
+				msgs[i].buf[byte] = rc;
+			}
+		} else if ((msgs[i].buf[0] == 0xf7) && (msgs[i].addr == 0x55)) {
+			/* prepaired for cx24116 firmware */
+			/* Write in small blocks */
+			len = msgs[i].len - 1;
+			k = 1;
+			do {
+				dm_writeb(DM1105_I2CDAT, msgs[i].addr << 1);
+				dm_writeb(DM1105_I2CDAT + 1, 0xf7);
+				for (byte = 0; byte < (len > 48 ? 48 : len); byte++) {
+					data = msgs[i].buf[k + byte];
+					dm_writeb(DM1105_I2CDAT + byte + 2, data);
+				}
+				dm_writeb(DM1105_I2CCTR, 0x82 + (len > 48 ? 48 : len));
+				for (j = 0; j < 25; j++) {
+					mdelay(10);
+					status = dm_readb(DM1105_I2CSTS);
+					if ((status & 0xc0) == 0x40)
+						break;
+				}
+
+				if (j >= 25)
+					return -1;
+
+				k += 48;
+				len -= 48;
+			} while (len > 0);
+		} else {
+			/* write bytes */
+			dm_writeb(DM1105_I2CDAT, msgs[i].addr << 1);
+			for (byte = 0; byte < msgs[i].len; byte++) {
+				data = msgs[i].buf[byte];
+				dm_writeb(DM1105_I2CDAT + byte + 1, data);
+			}
+			dm_writeb(DM1105_I2CCTR, 0x81 + msgs[i].len);
+			for (j = 0; j < 25; j++) {
+				mdelay(10);
+				status = dm_readb(DM1105_I2CSTS);
+				if ((status & 0xc0) == 0x40)
+					break;
+			}
+
+			if (j >= 25)
+				return -1;
+		}
+	}
+	return num;
+ err:
+	return rc;
+}
+
+static u32 functionality(struct i2c_adapter *adap)
+{
+	return I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm dm1105_algo = {
+	.master_xfer   = dm1105_i2c_xfer,
+	.functionality = functionality,
+};
+
+static inline struct dm1105_dev *feed_to_dm1105_dev(struct dvb_demux_feed *feed)
+{
+	return container_of(feed->demux, struct dm1105_dev, demux);
+}
+
+static inline struct dm1105_dev *frontend_to_dm1105_dev(struct dvb_frontend *fe)
+{
+	return container_of(fe->dvb, struct dm1105_dev, dvb_adapter);
+}
+
+static int dm1105_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+{
+	struct dm1105_dev *dev = frontend_to_dm1105_dev(fe);
+
+	dm1105_gpio_enable(dev, dm1105_boards[dev->boardnr].lnb.mask, 1);
+	if (voltage == SEC_VOLTAGE_18)
+		dm1105_gpio_andor(dev,
+				dm1105_boards[dev->boardnr].lnb.mask,
+				dm1105_boards[dev->boardnr].lnb.v18);
+	else if (voltage == SEC_VOLTAGE_13)
+		dm1105_gpio_andor(dev,
+				dm1105_boards[dev->boardnr].lnb.mask,
+				dm1105_boards[dev->boardnr].lnb.v13);
+	else
+		dm1105_gpio_andor(dev,
+				dm1105_boards[dev->boardnr].lnb.mask,
+				dm1105_boards[dev->boardnr].lnb.off);
+
+	return 0;
+}
+
+static void dm1105_set_dma_addr(struct dm1105_dev *dev)
+{
+	dm_writel(DM1105_STADR, cpu_to_le32(dev->dma_addr));
+}
+
+static int __devinit dm1105_dma_map(struct dm1105_dev *dev)
+{
+	dev->ts_buf = pci_alloc_consistent(dev->pdev,
+					6 * DM1105_DMA_BYTES,
+					&dev->dma_addr);
+
+	return !dev->ts_buf;
+}
+
+static void dm1105_dma_unmap(struct dm1105_dev *dev)
+{
+	pci_free_consistent(dev->pdev,
+			6 * DM1105_DMA_BYTES,
+			dev->ts_buf,
+			dev->dma_addr);
+}
+
+static void dm1105_enable_irqs(struct dm1105_dev *dev)
+{
+	dm_writeb(DM1105_INTMAK, INTMAK_ALLMASK);
+	dm_writeb(DM1105_CR, 1);
+}
+
+static void dm1105_disable_irqs(struct dm1105_dev *dev)
+{
+	dm_writeb(DM1105_INTMAK, INTMAK_IRM);
+	dm_writeb(DM1105_CR, 0);
+}
+
+static int dm1105_start_feed(struct dvb_demux_feed *f)
+{
+	struct dm1105_dev *dev = feed_to_dm1105_dev(f);
+
+	if (dev->full_ts_users++ == 0)
+		dm1105_enable_irqs(dev);
+
+	return 0;
+}
+
+static int dm1105_stop_feed(struct dvb_demux_feed *f)
+{
+	struct dm1105_dev *dev = feed_to_dm1105_dev(f);
+
+	if (--dev->full_ts_users == 0)
+		dm1105_disable_irqs(dev);
+
+	return 0;
+}
+
+/* ir work handler */
+static void dm1105_emit_key(struct work_struct *work)
+{
+	struct infrared *ir = container_of(work, struct infrared, work);
+	u32 ircom = ir->ir_command;
+	u8 data;
+
+	if (ir_debug)
+		printk(KERN_INFO "%s: received byte 0x%04x\n", __func__, ircom);
+
+	data = (ircom >> 8) & 0x7f;
+
+	rc_keydown(ir->dev, data, 0);
+}
+
+/* work handler */
+static void dm1105_dmx_buffer(struct work_struct *work)
+{
+	struct dm1105_dev *dev = container_of(work, struct dm1105_dev, work);
+	unsigned int nbpackets;
+	u32 oldwrp = dev->wrp;
+	u32 nextwrp = dev->nextwrp;
+
+	if (!((dev->ts_buf[oldwrp] == 0x47) &&
+			(dev->ts_buf[oldwrp + 188] == 0x47) &&
+			(dev->ts_buf[oldwrp + 188 * 2] == 0x47))) {
+		dev->PacketErrorCount++;
+		/* bad packet found */
+		if ((dev->PacketErrorCount >= 2) &&
+				(dev->dmarst == 0)) {
+			dm_writeb(DM1105_RST, 1);
+			dev->wrp = 0;
+			dev->PacketErrorCount = 0;
+			dev->dmarst = 0;
+			return;
+		}
+	}
+
+	if (nextwrp < oldwrp) {
+		memcpy(dev->ts_buf + dev->buffer_size, dev->ts_buf, nextwrp);
+		nbpackets = ((dev->buffer_size - oldwrp) + nextwrp) / 188;
+	} else
+		nbpackets = (nextwrp - oldwrp) / 188;
+
+	dev->wrp = nextwrp;
+	dvb_dmx_swfilter_packets(&dev->demux, &dev->ts_buf[oldwrp], nbpackets);
+}
+
+static irqreturn_t dm1105_irq(int irq, void *dev_id)
+{
+	struct dm1105_dev *dev = dev_id;
+
+	/* Read-Write INSTS Ack's Interrupt for DM1105 chip 16.03.2008 */
+	unsigned int intsts = dm_readb(DM1105_INTSTS);
+	dm_writeb(DM1105_INTSTS, intsts);
+
+	switch (intsts) {
+	case INTSTS_TSIRQ:
+	case (INTSTS_TSIRQ | INTSTS_IR):
+		dev->nextwrp = dm_readl(DM1105_WRP) - dm_readl(DM1105_STADR);
+		queue_work(dev->wq, &dev->work);
+		break;
+	case INTSTS_IR:
+		dev->ir.ir_command = dm_readl(DM1105_IRCODE);
+		schedule_work(&dev->ir.work);
+		break;
+	}
+
+	return IRQ_HANDLED;
+}
+
+int __devinit dm1105_ir_init(struct dm1105_dev *dm1105)
+{
+	struct rc_dev *dev;
+	int err = -ENOMEM;
+
+	dev = rc_allocate_device();
+	if (!dev)
+		return -ENOMEM;
+
+	snprintf(dm1105->ir.input_phys, sizeof(dm1105->ir.input_phys),
+		"pci-%s/ir0", pci_name(dm1105->pdev));
+
+	dev->driver_name = MODULE_NAME;
+	dev->map_name = RC_MAP_DM1105_NEC;
+	dev->driver_type = RC_DRIVER_SCANCODE;
+	dev->input_name = "DVB on-card IR receiver";
+	dev->input_phys = dm1105->ir.input_phys;
+	dev->input_id.bustype = BUS_PCI;
+	dev->input_id.version = 1;
+	if (dm1105->pdev->subsystem_vendor) {
+		dev->input_id.vendor = dm1105->pdev->subsystem_vendor;
+		dev->input_id.product = dm1105->pdev->subsystem_device;
+	} else {
+		dev->input_id.vendor = dm1105->pdev->vendor;
+		dev->input_id.product = dm1105->pdev->device;
+	}
+	dev->dev.parent = &dm1105->pdev->dev;
+
+	INIT_WORK(&dm1105->ir.work, dm1105_emit_key);
+
+	err = rc_register_device(dev);
+	if (err < 0) {
+		rc_free_device(dev);
+		return err;
+	}
+
+	dm1105->ir.dev = dev;
+	return 0;
+}
+
+void __devexit dm1105_ir_exit(struct dm1105_dev *dm1105)
+{
+	rc_unregister_device(dm1105->ir.dev);
+}
+
+static int __devinit dm1105_hw_init(struct dm1105_dev *dev)
+{
+	dm1105_disable_irqs(dev);
+
+	dm_writeb(DM1105_HOST_CTR, 0);
+
+	/*DATALEN 188,*/
+	dm_writeb(DM1105_DTALENTH, 188);
+	/*TS_STRT TS_VALP MSBFIRST TS_MODE ALPAS TSPES*/
+	dm_writew(DM1105_TSCTR, 0xc10a);
+
+	/* map DMA and set address */
+	dm1105_dma_map(dev);
+	dm1105_set_dma_addr(dev);
+	/* big buffer */
+	dm_writel(DM1105_RLEN, 5 * DM1105_DMA_BYTES);
+	dm_writeb(DM1105_INTCNT, 47);
+
+	/* IR NEC mode enable */
+	dm_writeb(DM1105_IRCTR, (DM1105_IR_EN | DM1105_SYS_CHK));
+	dm_writeb(DM1105_IRMODE, 0);
+	dm_writew(DM1105_SYSTEMCODE, 0);
+
+	return 0;
+}
+
+static void dm1105_hw_exit(struct dm1105_dev *dev)
+{
+	dm1105_disable_irqs(dev);
+
+	/* IR disable */
+	dm_writeb(DM1105_IRCTR, 0);
+	dm_writeb(DM1105_INTMAK, INTMAK_NONEMASK);
+
+	dm1105_dma_unmap(dev);
+}
+
+static struct stv0299_config sharp_z0194a_config = {
+	.demod_address = 0x68,
+	.inittab = sharp_z0194a_inittab,
+	.mclk = 88000000UL,
+	.invert = 1,
+	.skip_reinit = 0,
+	.lock_output = STV0299_LOCKOUTPUT_1,
+	.volt13_op0_op1 = STV0299_VOLT13_OP1,
+	.min_delay_ms = 100,
+	.set_symbol_rate = sharp_z0194a_set_symbol_rate,
+};
+
+static struct stv0288_config earda_config = {
+	.demod_address = 0x68,
+	.min_delay_ms = 100,
+};
+
+static struct si21xx_config serit_config = {
+	.demod_address = 0x68,
+	.min_delay_ms = 100,
+
+};
+
+static struct cx24116_config serit_sp2633_config = {
+	.demod_address = 0x55,
+};
+
+static struct ds3000_config dvbworld_ds3000_config = {
+	.demod_address = 0x68,
+};
+
+static int __devinit frontend_init(struct dm1105_dev *dev)
+{
+	int ret;
+
+	switch (dev->boardnr) {
+	case DM1105_BOARD_UNBRANDED_I2C_ON_GPIO:
+		dm1105_gpio_enable(dev, GPIO15, 1);
+		dm1105_gpio_clear(dev, GPIO15);
+		msleep(100);
+		dm1105_gpio_set(dev, GPIO15);
+		msleep(200);
+		dev->fe = dvb_attach(
+			stv0299_attach, &sharp_z0194a_config,
+			&dev->i2c_bb_adap);
+		if (dev->fe) {
+			dev->fe->ops.set_voltage = dm1105_set_voltage;
+			dvb_attach(dvb_pll_attach, dev->fe, 0x60,
+					&dev->i2c_bb_adap, DVB_PLL_OPERA1);
+			break;
+		}
+
+		dev->fe = dvb_attach(
+			stv0288_attach, &earda_config,
+			&dev->i2c_bb_adap);
+		if (dev->fe) {
+			dev->fe->ops.set_voltage = dm1105_set_voltage;
+			dvb_attach(stb6000_attach, dev->fe, 0x61,
+					&dev->i2c_bb_adap);
+			break;
+		}
+
+		dev->fe = dvb_attach(
+			si21xx_attach, &serit_config,
+			&dev->i2c_bb_adap);
+		if (dev->fe)
+			dev->fe->ops.set_voltage = dm1105_set_voltage;
+		break;
+	case DM1105_BOARD_DVBWORLD_2004:
+		dev->fe = dvb_attach(
+			cx24116_attach, &serit_sp2633_config,
+			&dev->i2c_adap);
+		if (dev->fe) {
+			dev->fe->ops.set_voltage = dm1105_set_voltage;
+			break;
+		}
+
+		dev->fe = dvb_attach(
+			ds3000_attach, &dvbworld_ds3000_config,
+			&dev->i2c_adap);
+		if (dev->fe)
+			dev->fe->ops.set_voltage = dm1105_set_voltage;
+
+		break;
+	case DM1105_BOARD_DVBWORLD_2002:
+	case DM1105_BOARD_AXESS_DM05:
+	default:
+		dev->fe = dvb_attach(
+			stv0299_attach, &sharp_z0194a_config,
+			&dev->i2c_adap);
+		if (dev->fe) {
+			dev->fe->ops.set_voltage = dm1105_set_voltage;
+			dvb_attach(dvb_pll_attach, dev->fe, 0x60,
+					&dev->i2c_adap, DVB_PLL_OPERA1);
+			break;
+		}
+
+		dev->fe = dvb_attach(
+			stv0288_attach, &earda_config,
+			&dev->i2c_adap);
+		if (dev->fe) {
+			dev->fe->ops.set_voltage = dm1105_set_voltage;
+			dvb_attach(stb6000_attach, dev->fe, 0x61,
+					&dev->i2c_adap);
+			break;
+		}
+
+		dev->fe = dvb_attach(
+			si21xx_attach, &serit_config,
+			&dev->i2c_adap);
+		if (dev->fe)
+			dev->fe->ops.set_voltage = dm1105_set_voltage;
+
+	}
+
+	if (!dev->fe) {
+		dev_err(&dev->pdev->dev, "could not attach frontend\n");
+		return -ENODEV;
+	}
+
+	ret = dvb_register_frontend(&dev->dvb_adapter, dev->fe);
+	if (ret < 0) {
+		if (dev->fe->ops.release)
+			dev->fe->ops.release(dev->fe);
+		dev->fe = NULL;
+		return ret;
+	}
+
+	return 0;
+}
+
+static void __devinit dm1105_read_mac(struct dm1105_dev *dev, u8 *mac)
+{
+	static u8 command[1] = { 0x28 };
+
+	struct i2c_msg msg[] = {
+		{
+			.addr = IIC_24C01_addr >> 1,
+			.flags = 0,
+			.buf = command,
+			.len = 1
+		}, {
+			.addr = IIC_24C01_addr >> 1,
+			.flags = I2C_M_RD,
+			.buf = mac,
+			.len = 6
+		},
+	};
+
+	dm1105_i2c_xfer(&dev->i2c_adap, msg , 2);
+	dev_info(&dev->pdev->dev, "MAC %pM\n", mac);
+}
+
+static int __devinit dm1105_probe(struct pci_dev *pdev,
+				  const struct pci_device_id *ent)
+{
+	struct dm1105_dev *dev;
+	struct dvb_adapter *dvb_adapter;
+	struct dvb_demux *dvbdemux;
+	struct dmx_demux *dmx;
+	int ret = -ENOMEM;
+	int i;
+
+	dev = kzalloc(sizeof(struct dm1105_dev), GFP_KERNEL);
+	if (!dev)
+		return -ENOMEM;
+
+	/* board config */
+	dev->nr = dm1105_devcount;
+	dev->boardnr = UNSET;
+	if (card[dev->nr] < ARRAY_SIZE(dm1105_boards))
+		dev->boardnr = card[dev->nr];
+	for (i = 0; UNSET == dev->boardnr &&
+				i < ARRAY_SIZE(dm1105_subids); i++)
+		if (pdev->subsystem_vendor ==
+			dm1105_subids[i].subvendor &&
+				pdev->subsystem_device ==
+					dm1105_subids[i].subdevice)
+			dev->boardnr = dm1105_subids[i].card;
+
+	if (UNSET == dev->boardnr) {
+		dev->boardnr = DM1105_BOARD_UNKNOWN;
+		dm1105_card_list(pdev);
+	}
+
+	dm1105_devcount++;
+	dev->pdev = pdev;
+	dev->buffer_size = 5 * DM1105_DMA_BYTES;
+	dev->PacketErrorCount = 0;
+	dev->dmarst = 0;
+
+	ret = pci_enable_device(pdev);
+	if (ret < 0)
+		goto err_kfree;
+
+	ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+	if (ret < 0)
+		goto err_pci_disable_device;
+
+	pci_set_master(pdev);
+
+	ret = pci_request_regions(pdev, DRIVER_NAME);
+	if (ret < 0)
+		goto err_pci_disable_device;
+
+	dev->io_mem = pci_iomap(pdev, 0, pci_resource_len(pdev, 0));
+	if (!dev->io_mem) {
+		ret = -EIO;
+		goto err_pci_release_regions;
+	}
+
+	spin_lock_init(&dev->lock);
+	pci_set_drvdata(pdev, dev);
+
+	ret = dm1105_hw_init(dev);
+	if (ret < 0)
+		goto err_pci_iounmap;
+
+	/* i2c */
+	i2c_set_adapdata(&dev->i2c_adap, dev);
+	strcpy(dev->i2c_adap.name, DRIVER_NAME);
+	dev->i2c_adap.owner = THIS_MODULE;
+	dev->i2c_adap.dev.parent = &pdev->dev;
+	dev->i2c_adap.algo = &dm1105_algo;
+	dev->i2c_adap.algo_data = dev;
+	ret = i2c_add_adapter(&dev->i2c_adap);
+
+	if (ret < 0)
+		goto err_dm1105_hw_exit;
+
+	i2c_set_adapdata(&dev->i2c_bb_adap, dev);
+	strcpy(dev->i2c_bb_adap.name, DM1105_I2C_GPIO_NAME);
+	dev->i2c_bb_adap.owner = THIS_MODULE;
+	dev->i2c_bb_adap.dev.parent = &pdev->dev;
+	dev->i2c_bb_adap.algo_data = &dev->i2c_bit;
+	dev->i2c_bit.data = dev;
+	dev->i2c_bit.setsda = dm1105_setsda;
+	dev->i2c_bit.setscl = dm1105_setscl;
+	dev->i2c_bit.getsda = dm1105_getsda;
+	dev->i2c_bit.getscl = dm1105_getscl;
+	dev->i2c_bit.udelay = 10;
+	dev->i2c_bit.timeout = 10;
+
+	/* Raise SCL and SDA */
+	dm1105_setsda(dev, 1);
+	dm1105_setscl(dev, 1);
+
+	ret = i2c_bit_add_bus(&dev->i2c_bb_adap);
+	if (ret < 0)
+		goto err_i2c_del_adapter;
+
+	/* dvb */
+	ret = dvb_register_adapter(&dev->dvb_adapter, DRIVER_NAME,
+					THIS_MODULE, &pdev->dev, adapter_nr);
+	if (ret < 0)
+		goto err_i2c_del_adapters;
+
+	dvb_adapter = &dev->dvb_adapter;
+
+	dm1105_read_mac(dev, dvb_adapter->proposed_mac);
+
+	dvbdemux = &dev->demux;
+	dvbdemux->filternum = 256;
+	dvbdemux->feednum = 256;
+	dvbdemux->start_feed = dm1105_start_feed;
+	dvbdemux->stop_feed = dm1105_stop_feed;
+	dvbdemux->dmx.capabilities = (DMX_TS_FILTERING |
+			DMX_SECTION_FILTERING | DMX_MEMORY_BASED_FILTERING);
+	ret = dvb_dmx_init(dvbdemux);
+	if (ret < 0)
+		goto err_dvb_unregister_adapter;
+
+	dmx = &dvbdemux->dmx;
+	dev->dmxdev.filternum = 256;
+	dev->dmxdev.demux = dmx;
+	dev->dmxdev.capabilities = 0;
+
+	ret = dvb_dmxdev_init(&dev->dmxdev, dvb_adapter);
+	if (ret < 0)
+		goto err_dvb_dmx_release;
+
+	dev->hw_frontend.source = DMX_FRONTEND_0;
+
+	ret = dmx->add_frontend(dmx, &dev->hw_frontend);
+	if (ret < 0)
+		goto err_dvb_dmxdev_release;
+
+	dev->mem_frontend.source = DMX_MEMORY_FE;
+
+	ret = dmx->add_frontend(dmx, &dev->mem_frontend);
+	if (ret < 0)
+		goto err_remove_hw_frontend;
+
+	ret = dmx->connect_frontend(dmx, &dev->hw_frontend);
+	if (ret < 0)
+		goto err_remove_mem_frontend;
+
+	ret = dvb_net_init(dvb_adapter, &dev->dvbnet, dmx);
+	if (ret < 0)
+		goto err_disconnect_frontend;
+
+	ret = frontend_init(dev);
+	if (ret < 0)
+		goto err_dvb_net;
+
+	dm1105_ir_init(dev);
+
+	INIT_WORK(&dev->work, dm1105_dmx_buffer);
+	sprintf(dev->wqn, "%s/%d", dvb_adapter->name, dvb_adapter->num);
+	dev->wq = create_singlethread_workqueue(dev->wqn);
+	if (!dev->wq)
+		goto err_dvb_net;
+
+	ret = request_irq(pdev->irq, dm1105_irq, IRQF_SHARED,
+						DRIVER_NAME, dev);
+	if (ret < 0)
+		goto err_workqueue;
+
+	return 0;
+
+err_workqueue:
+	destroy_workqueue(dev->wq);
+err_dvb_net:
+	dvb_net_release(&dev->dvbnet);
+err_disconnect_frontend:
+	dmx->disconnect_frontend(dmx);
+err_remove_mem_frontend:
+	dmx->remove_frontend(dmx, &dev->mem_frontend);
+err_remove_hw_frontend:
+	dmx->remove_frontend(dmx, &dev->hw_frontend);
+err_dvb_dmxdev_release:
+	dvb_dmxdev_release(&dev->dmxdev);
+err_dvb_dmx_release:
+	dvb_dmx_release(dvbdemux);
+err_dvb_unregister_adapter:
+	dvb_unregister_adapter(dvb_adapter);
+err_i2c_del_adapters:
+	i2c_del_adapter(&dev->i2c_bb_adap);
+err_i2c_del_adapter:
+	i2c_del_adapter(&dev->i2c_adap);
+err_dm1105_hw_exit:
+	dm1105_hw_exit(dev);
+err_pci_iounmap:
+	pci_iounmap(pdev, dev->io_mem);
+err_pci_release_regions:
+	pci_release_regions(pdev);
+err_pci_disable_device:
+	pci_disable_device(pdev);
+err_kfree:
+	pci_set_drvdata(pdev, NULL);
+	kfree(dev);
+	return ret;
+}
+
+static void __devexit dm1105_remove(struct pci_dev *pdev)
+{
+	struct dm1105_dev *dev = pci_get_drvdata(pdev);
+	struct dvb_adapter *dvb_adapter = &dev->dvb_adapter;
+	struct dvb_demux *dvbdemux = &dev->demux;
+	struct dmx_demux *dmx = &dvbdemux->dmx;
+
+	dm1105_ir_exit(dev);
+	dmx->close(dmx);
+	dvb_net_release(&dev->dvbnet);
+	if (dev->fe)
+		dvb_unregister_frontend(dev->fe);
+
+	dmx->disconnect_frontend(dmx);
+	dmx->remove_frontend(dmx, &dev->mem_frontend);
+	dmx->remove_frontend(dmx, &dev->hw_frontend);
+	dvb_dmxdev_release(&dev->dmxdev);
+	dvb_dmx_release(dvbdemux);
+	dvb_unregister_adapter(dvb_adapter);
+	if (&dev->i2c_adap)
+		i2c_del_adapter(&dev->i2c_adap);
+
+	dm1105_hw_exit(dev);
+	synchronize_irq(pdev->irq);
+	free_irq(pdev->irq, dev);
+	pci_iounmap(pdev, dev->io_mem);
+	pci_release_regions(pdev);
+	pci_disable_device(pdev);
+	pci_set_drvdata(pdev, NULL);
+	dm1105_devcount--;
+	kfree(dev);
+}
+
+static struct pci_device_id dm1105_id_table[] __devinitdata = {
+	{
+		.vendor = PCI_VENDOR_ID_TRIGEM,
+		.device = PCI_DEVICE_ID_DM1105,
+		.subvendor = PCI_ANY_ID,
+		.subdevice = PCI_ANY_ID,
+	}, {
+		.vendor = PCI_VENDOR_ID_AXESS,
+		.device = PCI_DEVICE_ID_DM05,
+		.subvendor = PCI_ANY_ID,
+		.subdevice = PCI_ANY_ID,
+	}, {
+		/* empty */
+	},
+};
+
+MODULE_DEVICE_TABLE(pci, dm1105_id_table);
+
+static struct pci_driver dm1105_driver = {
+	.name = DRIVER_NAME,
+	.id_table = dm1105_id_table,
+	.probe = dm1105_probe,
+	.remove = __devexit_p(dm1105_remove),
+};
+
+static int __init dm1105_init(void)
+{
+	return pci_register_driver(&dm1105_driver);
+}
+
+static void __exit dm1105_exit(void)
+{
+	pci_unregister_driver(&dm1105_driver);
+}
+
+module_init(dm1105_init);
+module_exit(dm1105_exit);
+
+MODULE_AUTHOR("Igor M. Liplianin <liplianin@me.by>");
+MODULE_DESCRIPTION("SDMC DM1105 DVB driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/pci/ivtv/Kconfig b/drivers/media/pci/ivtv/Kconfig
new file mode 100644
index 0000000..dd6ee57
--- /dev/null
+++ b/drivers/media/pci/ivtv/Kconfig
@@ -0,0 +1,61 @@
+config VIDEO_IVTV
+	tristate "Conexant cx23416/cx23415 MPEG encoder/decoder support"
+	depends on VIDEO_V4L2 && PCI && I2C
+	select I2C_ALGOBIT
+	depends on RC_CORE
+	select VIDEO_TUNER
+	select VIDEO_TVEEPROM
+	select VIDEO_CX2341X
+	select VIDEO_CX25840
+	select VIDEO_MSP3400
+	select VIDEO_SAA711X
+	select VIDEO_SAA717X
+	select VIDEO_SAA7127
+	select VIDEO_CS53L32A
+	select VIDEO_M52790
+	select VIDEO_WM8775
+	select VIDEO_WM8739
+	select VIDEO_VP27SMPX
+	select VIDEO_UPD64031A
+	select VIDEO_UPD64083
+	---help---
+	  This is a video4linux driver for Conexant cx23416 or cx23415 based
+	  PCI personal video recorder devices.
+
+	  This is used in devices such as the Hauppauge PVR-150/250/350/500
+	  cards. There is a driver homepage at <http://www.ivtvdriver.org>.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ivtv.
+
+config VIDEO_IVTV_ALSA
+	tristate "Conexant cx23415/cx23416 ALSA interface for PCM audio capture"
+	depends on VIDEO_IVTV && SND
+	select SND_PCM
+	---help---
+	  This driver provides an ALSA interface as another method for user
+	  applications to obtain PCM audio data from Conexant cx23415/cx23416
+	  based PCI TV cards supported by the ivtv driver.
+
+	  The ALSA interface has much wider use in user applications performing
+	  PCM audio capture, than the V4L2 "/dev/video24" PCM audio interface
+	  provided by the main ivtv driver.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ivtv-alsa.
+
+config VIDEO_FB_IVTV
+	tristate "Conexant cx23415 framebuffer support"
+	depends on VIDEO_IVTV && FB
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	---help---
+	  This is a framebuffer driver for the Conexant cx23415 MPEG
+	  encoder/decoder.
+
+	  This is used in the Hauppauge PVR-350 card. There is a driver
+	  homepage at <http://www.ivtvdriver.org>.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ivtvfb.
diff --git a/drivers/media/pci/ivtv/Makefile b/drivers/media/pci/ivtv/Makefile
new file mode 100644
index 0000000..0eaa882
--- /dev/null
+++ b/drivers/media/pci/ivtv/Makefile
@@ -0,0 +1,16 @@
+ivtv-objs	:= ivtv-routing.o ivtv-cards.o ivtv-controls.o \
+		   ivtv-driver.o ivtv-fileops.o ivtv-firmware.o \
+		   ivtv-gpio.o ivtv-i2c.o ivtv-ioctl.o ivtv-irq.o \
+		   ivtv-mailbox.o ivtv-queue.o ivtv-streams.o ivtv-udma.o \
+		   ivtv-vbi.o ivtv-yuv.o
+ivtv-alsa-objs := ivtv-alsa-main.o ivtv-alsa-pcm.o
+
+obj-$(CONFIG_VIDEO_IVTV) += ivtv.o
+obj-$(CONFIG_VIDEO_IVTV_ALSA) += ivtv-alsa.o
+obj-$(CONFIG_VIDEO_FB_IVTV) += ivtvfb.o
+
+ccflags-y += -I$(srctree)/drivers/media/i2c
+ccflags-y += -I$(srctree)/drivers/media/tuners
+ccflags-y += -I$(srctree)/drivers/media/dvb-core
+ccflags-y += -I$(srctree)/drivers/media/dvb-frontends
+
diff --git a/drivers/media/pci/ivtv/ivtv-alsa-main.c b/drivers/media/pci/ivtv/ivtv-alsa-main.c
new file mode 100644
index 0000000..8deab16
--- /dev/null
+++ b/drivers/media/pci/ivtv/ivtv-alsa-main.c
@@ -0,0 +1,303 @@
+/*
+ *  ALSA interface to ivtv PCM capture streams
+ *
+ *  Copyright (C) 2009,2012  Andy Walls <awalls@md.metrocast.net>
+ *  Copyright (C) 2009  Devin Heitmueller <dheitmueller@kernellabs.com>
+ *
+ *  Portions of this work were sponsored by ONELAN Limited for the cx18 driver
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307  USA
+ */
+
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/spinlock.h>
+
+#include <media/v4l2-device.h>
+
+#include <sound/core.h>
+#include <sound/initval.h>
+
+#include "ivtv-driver.h"
+#include "ivtv-version.h"
+#include "ivtv-alsa.h"
+#include "ivtv-alsa-mixer.h"
+#include "ivtv-alsa-pcm.h"
+
+int ivtv_alsa_debug;
+
+#define IVTV_DEBUG_ALSA_INFO(fmt, arg...) \
+	do { \
+		if (ivtv_alsa_debug & 2) \
+			pr_info("%s: " fmt, "ivtv-alsa", ## arg); \
+	} while (0)
+
+module_param_named(debug, ivtv_alsa_debug, int, 0644);
+MODULE_PARM_DESC(debug,
+		 "Debug level (bitmask). Default: 0\n"
+		 "\t\t\t  1/0x0001: warning\n"
+		 "\t\t\t  2/0x0002: info\n");
+
+MODULE_AUTHOR("Andy Walls");
+MODULE_DESCRIPTION("CX23415/CX23416 ALSA Interface");
+MODULE_SUPPORTED_DEVICE("CX23415/CX23416 MPEG2 encoder");
+MODULE_LICENSE("GPL");
+
+MODULE_VERSION(IVTV_VERSION);
+
+static inline
+struct snd_ivtv_card *to_snd_ivtv_card(struct v4l2_device *v4l2_dev)
+{
+	return to_ivtv(v4l2_dev)->alsa;
+}
+
+static inline
+struct snd_ivtv_card *p_to_snd_ivtv_card(struct v4l2_device **v4l2_dev)
+{
+	return container_of(v4l2_dev, struct snd_ivtv_card, v4l2_dev);
+}
+
+static void snd_ivtv_card_free(struct snd_ivtv_card *itvsc)
+{
+	if (itvsc == NULL)
+		return;
+
+	if (itvsc->v4l2_dev != NULL)
+		to_ivtv(itvsc->v4l2_dev)->alsa = NULL;
+
+	/* FIXME - take any other stopping actions needed */
+
+	kfree(itvsc);
+}
+
+static void snd_ivtv_card_private_free(struct snd_card *sc)
+{
+	if (sc == NULL)
+		return;
+	snd_ivtv_card_free(sc->private_data);
+	sc->private_data = NULL;
+	sc->private_free = NULL;
+}
+
+static int snd_ivtv_card_create(struct v4l2_device *v4l2_dev,
+				       struct snd_card *sc,
+				       struct snd_ivtv_card **itvsc)
+{
+	*itvsc = kzalloc(sizeof(struct snd_ivtv_card), GFP_KERNEL);
+	if (*itvsc == NULL)
+		return -ENOMEM;
+
+	(*itvsc)->v4l2_dev = v4l2_dev;
+	(*itvsc)->sc = sc;
+
+	sc->private_data = *itvsc;
+	sc->private_free = snd_ivtv_card_private_free;
+
+	return 0;
+}
+
+static int snd_ivtv_card_set_names(struct snd_ivtv_card *itvsc)
+{
+	struct ivtv *itv = to_ivtv(itvsc->v4l2_dev);
+	struct snd_card *sc = itvsc->sc;
+
+	/* sc->driver is used by alsa-lib's configurator: simple, unique */
+	strlcpy(sc->driver, "CX2341[56]", sizeof(sc->driver));
+
+	/* sc->shortname is a symlink in /proc/asound: IVTV-M -> cardN */
+	snprintf(sc->shortname,  sizeof(sc->shortname), "IVTV-%d",
+		 itv->instance);
+
+	/* sc->longname is read from /proc/asound/cards */
+	snprintf(sc->longname, sizeof(sc->longname),
+		 "CX2341[56] #%d %s TV/FM Radio/Line-In Capture",
+		 itv->instance, itv->card_name);
+
+	return 0;
+}
+
+static int snd_ivtv_init(struct v4l2_device *v4l2_dev)
+{
+	struct ivtv *itv = to_ivtv(v4l2_dev);
+	struct snd_card *sc = NULL;
+	struct snd_ivtv_card *itvsc;
+	int ret;
+
+	/* Numbrs steps from "Writing an ALSA Driver" by Takashi Iwai */
+
+	/* (1) Check and increment the device index */
+	/* This is a no-op for us.  We'll use the itv->instance */
+
+	/* (2) Create a card instance */
+	ret = snd_card_create(SNDRV_DEFAULT_IDX1, /* use first available id */
+			      SNDRV_DEFAULT_STR1, /* xid from end of shortname*/
+			      THIS_MODULE, 0, &sc);
+	if (ret) {
+		IVTV_ALSA_ERR("%s: snd_card_create() failed with err %d\n",
+			      __func__, ret);
+		goto err_exit;
+	}
+
+	/* (3) Create a main component */
+	ret = snd_ivtv_card_create(v4l2_dev, sc, &itvsc);
+	if (ret) {
+		IVTV_ALSA_ERR("%s: snd_ivtv_card_create() failed with err %d\n",
+			      __func__, ret);
+		goto err_exit_free;
+	}
+
+	/* (4) Set the driver ID and name strings */
+	snd_ivtv_card_set_names(itvsc);
+
+	/* (5) Create other components: mixer, PCM, & proc files */
+#if 0
+	ret = snd_ivtv_mixer_create(itvsc);
+	if (ret) {
+		IVTV_ALSA_WARN("%s: snd_ivtv_mixer_create() failed with err %d:"
+			       " proceeding anyway\n", __func__, ret);
+	}
+#endif
+
+	ret = snd_ivtv_pcm_create(itvsc);
+	if (ret) {
+		IVTV_ALSA_ERR("%s: snd_ivtv_pcm_create() failed with err %d\n",
+			      __func__, ret);
+		goto err_exit_free;
+	}
+	/* FIXME - proc files */
+
+	/* (7) Set the driver data and return 0 */
+	/* We do this out of normal order for PCI drivers to avoid races */
+	itv->alsa = itvsc;
+
+	/* (6) Register the card instance */
+	ret = snd_card_register(sc);
+	if (ret) {
+		itv->alsa = NULL;
+		IVTV_ALSA_ERR("%s: snd_card_register() failed with err %d\n",
+			      __func__, ret);
+		goto err_exit_free;
+	}
+
+	return 0;
+
+err_exit_free:
+	if (sc != NULL)
+		snd_card_free(sc);
+	kfree(itvsc);
+err_exit:
+	return ret;
+}
+
+int ivtv_alsa_load(struct ivtv *itv)
+{
+	struct v4l2_device *v4l2_dev = &itv->v4l2_dev;
+	struct ivtv_stream *s;
+
+	if (v4l2_dev == NULL) {
+		pr_err("ivtv-alsa: %s: struct v4l2_device * is NULL\n",
+		       __func__);
+		return 0;
+	}
+
+	itv = to_ivtv(v4l2_dev);
+	if (itv == NULL) {
+		pr_err("ivtv-alsa itv is NULL\n");
+		return 0;
+	}
+
+	s = &itv->streams[IVTV_ENC_STREAM_TYPE_PCM];
+	if (s->vdev == NULL) {
+		IVTV_DEBUG_ALSA_INFO("%s: PCM stream for card is disabled - "
+				     "skipping\n", __func__);
+		return 0;
+	}
+
+	if (itv->alsa != NULL) {
+		IVTV_ALSA_ERR("%s: struct snd_ivtv_card * already exists\n",
+			      __func__);
+		return 0;
+	}
+
+	if (snd_ivtv_init(v4l2_dev)) {
+		IVTV_ALSA_ERR("%s: failed to create struct snd_ivtv_card\n",
+			      __func__);
+	} else {
+		IVTV_DEBUG_ALSA_INFO("%s: created ivtv ALSA interface instance "
+				     "\n", __func__);
+	}
+	return 0;
+}
+
+static int __init ivtv_alsa_init(void)
+{
+	pr_info("ivtv-alsa: module loading...\n");
+	ivtv_ext_init = &ivtv_alsa_load;
+	return 0;
+}
+
+static void __exit snd_ivtv_exit(struct snd_ivtv_card *itvsc)
+{
+	struct ivtv *itv = to_ivtv(itvsc->v4l2_dev);
+
+	/* FIXME - pointer checks & shutdown itvsc */
+
+	snd_card_free(itvsc->sc);
+	itv->alsa = NULL;
+}
+
+static int __exit ivtv_alsa_exit_callback(struct device *dev, void *data)
+{
+	struct v4l2_device *v4l2_dev = dev_get_drvdata(dev);
+	struct snd_ivtv_card *itvsc;
+
+	if (v4l2_dev == NULL) {
+		pr_err("ivtv-alsa: %s: struct v4l2_device * is NULL\n",
+		       __func__);
+		return 0;
+	}
+
+	itvsc = to_snd_ivtv_card(v4l2_dev);
+	if (itvsc == NULL) {
+		IVTV_ALSA_WARN("%s: struct snd_ivtv_card * is NULL\n",
+			       __func__);
+		return 0;
+	}
+
+	snd_ivtv_exit(itvsc);
+	return 0;
+}
+
+static void __exit ivtv_alsa_exit(void)
+{
+	struct device_driver *drv;
+	int ret;
+
+	pr_info("ivtv-alsa: module unloading...\n");
+
+	drv = driver_find("ivtv", &pci_bus_type);
+	ret = driver_for_each_device(drv, NULL, NULL, ivtv_alsa_exit_callback);
+	(void)ret;	/* suppress compiler warning */
+
+	ivtv_ext_init = NULL;
+	pr_info("ivtv-alsa: module unload complete\n");
+}
+
+module_init(ivtv_alsa_init);
+module_exit(ivtv_alsa_exit);
diff --git a/drivers/media/pci/ivtv/ivtv-alsa-mixer.c b/drivers/media/pci/ivtv/ivtv-alsa-mixer.c
new file mode 100644
index 0000000..33ec05b
--- /dev/null
+++ b/drivers/media/pci/ivtv/ivtv-alsa-mixer.c
@@ -0,0 +1,175 @@
+/*
+ *  ALSA mixer controls for the
+ *  ALSA interface to ivtv PCM capture streams
+ *
+ *  Copyright (C) 2009,2012  Andy Walls <awalls@md.metrocast.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 program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307  USA
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/spinlock.h>
+#include <linux/videodev2.h>
+
+#include <media/v4l2-device.h>
+
+#include <sound/core.h>
+#include <sound/control.h>
+#include <sound/tlv.h>
+
+#include "ivtv-alsa.h"
+#include "ivtv-driver.h"
+
+/*
+ * Note the cx25840-core volume scale is funny, due to the alignment of the
+ * scale with another chip's range:
+ *
+ * v4l2_control value	/512	indicated dB	actual dB	reg 0x8d4
+ * 0x0000 - 0x01ff	  0	-119		-96		228
+ * 0x0200 - 0x02ff	  1	-118		-96		228
+ * ...
+ * 0x2c00 - 0x2dff	 22	 -97		-96		228
+ * 0x2e00 - 0x2fff	 23	 -96		-96		228
+ * 0x3000 - 0x31ff	 24	 -95		-95		226
+ * ...
+ * 0xee00 - 0xefff	119	   0		  0		 36
+ * ...
+ * 0xfe00 - 0xffff	127	  +8		 +8		 20
+ */
+static inline int dB_to_cx25840_vol(int dB)
+{
+	if (dB < -96)
+		dB = -96;
+	else if (dB > 8)
+		dB = 8;
+	return (dB + 119) << 9;
+}
+
+static inline int cx25840_vol_to_dB(int v)
+{
+	if (v < (23 << 9))
+		v = (23 << 9);
+	else if (v > (127 << 9))
+		v = (127 << 9);
+	return (v >> 9) - 119;
+}
+
+static int snd_ivtv_mixer_tv_vol_info(struct snd_kcontrol *kcontrol,
+				      struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 1;
+	/* We're already translating values, just keep this control in dB */
+	uinfo->value.integer.min  = -96;
+	uinfo->value.integer.max  =   8;
+	uinfo->value.integer.step =   1;
+	return 0;
+}
+
+static int snd_ivtv_mixer_tv_vol_get(struct snd_kcontrol *kctl,
+				     struct snd_ctl_elem_value *uctl)
+{
+	struct snd_ivtv_card *itvsc = snd_kcontrol_chip(kctl);
+	struct ivtv *itv = to_ivtv(itvsc->v4l2_dev);
+	struct v4l2_control vctrl;
+	int ret;
+
+	vctrl.id = V4L2_CID_AUDIO_VOLUME;
+	vctrl.value = dB_to_cx25840_vol(uctl->value.integer.value[0]);
+
+	snd_ivtv_lock(itvsc);
+	ret = v4l2_subdev_call(itv->sd_audio, core, g_ctrl, &vctrl);
+	snd_ivtv_unlock(itvsc);
+
+	if (!ret)
+		uctl->value.integer.value[0] = cx25840_vol_to_dB(vctrl.value);
+	return ret;
+}
+
+static int snd_ivtv_mixer_tv_vol_put(struct snd_kcontrol *kctl,
+				     struct snd_ctl_elem_value *uctl)
+{
+	struct snd_ivtv_card *itvsc = snd_kcontrol_chip(kctl);
+	struct ivtv *itv = to_ivtv(itvsc->v4l2_dev);
+	struct v4l2_control vctrl;
+	int ret;
+
+	vctrl.id = V4L2_CID_AUDIO_VOLUME;
+	vctrl.value = dB_to_cx25840_vol(uctl->value.integer.value[0]);
+
+	snd_ivtv_lock(itvsc);
+
+	/* Fetch current state */
+	ret = v4l2_subdev_call(itv->sd_audio, core, g_ctrl, &vctrl);
+
+	if (ret ||
+	    (cx25840_vol_to_dB(vctrl.value) != uctl->value.integer.value[0])) {
+
+		/* Set, if needed */
+		vctrl.value = dB_to_cx25840_vol(uctl->value.integer.value[0]);
+		ret = v4l2_subdev_call(itv->sd_audio, core, s_ctrl, &vctrl);
+		if (!ret)
+			ret = 1; /* Indicate control was changed w/o error */
+	}
+	snd_ivtv_unlock(itvsc);
+
+	return ret;
+}
+
+
+/* This is a bit of overkill, the slider is already in dB internally */
+static DECLARE_TLV_DB_SCALE(snd_ivtv_mixer_tv_vol_db_scale, -9600, 100, 0);
+
+static struct snd_kcontrol_new snd_ivtv_mixer_tv_vol __initdata = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "Analog TV Capture Volume",
+	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
+		  SNDRV_CTL_ELEM_ACCESS_TLV_READ,
+	.info = snd_ivtv_mixer_tv_volume_info,
+	.get = snd_ivtv_mixer_tv_volume_get,
+	.put = snd_ivtv_mixer_tv_volume_put,
+	.tlv.p = snd_ivtv_mixer_tv_vol_db_scale
+};
+
+/* FIXME - add mute switch and balance, bass, treble sliders:
+	V4L2_CID_AUDIO_MUTE
+
+	V4L2_CID_AUDIO_BALANCE
+
+	V4L2_CID_AUDIO_BASS
+	V4L2_CID_AUDIO_TREBLE
+*/
+
+/* FIXME - add stereo, lang1, lang2, mono menu */
+/* FIXME - add I2S volume */
+
+int __init snd_ivtv_mixer_create(struct snd_ivtv_card *itvsc)
+{
+	struct v4l2_device *v4l2_dev = itvsc->v4l2_dev;
+	struct snd_card *sc = itvsc->sc;
+	int ret;
+
+	strlcpy(sc->mixername, "CX2341[56] Mixer", sizeof(sc->mixername));
+
+	ret = snd_ctl_add(sc, snd_ctl_new1(snd_ivtv_mixer_tv_vol, itvsc));
+	if (ret) {
+		IVTV_ALSA_WARN("%s: failed to add %s control, err %d\n",
+			       __func__, snd_ivtv_mixer_tv_vol.name, ret);
+	}
+	return ret;
+}
diff --git a/drivers/media/pci/ivtv/ivtv-alsa-mixer.h b/drivers/media/pci/ivtv/ivtv-alsa-mixer.h
new file mode 100644
index 0000000..cdde367
--- /dev/null
+++ b/drivers/media/pci/ivtv/ivtv-alsa-mixer.h
@@ -0,0 +1,23 @@
+/*
+ *  ALSA mixer controls for the
+ *  ALSA interface to ivtv PCM capture streams
+ *
+ *  Copyright (C) 2009,2012  Andy Walls <awalls@md.metrocast.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 program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307  USA
+ */
+
+int __init snd_ivtv_mixer_create(struct snd_ivtv_card *itvsc);
diff --git a/drivers/media/pci/ivtv/ivtv-alsa-pcm.c b/drivers/media/pci/ivtv/ivtv-alsa-pcm.c
new file mode 100644
index 0000000..82c708e
--- /dev/null
+++ b/drivers/media/pci/ivtv/ivtv-alsa-pcm.c
@@ -0,0 +1,357 @@
+/*
+ *  ALSA PCM device for the
+ *  ALSA interface to ivtv PCM capture streams
+ *
+ *  Copyright (C) 2009,2012  Andy Walls <awalls@md.metrocast.net>
+ *  Copyright (C) 2009  Devin Heitmueller <dheitmueller@kernellabs.com>
+ *
+ *  Portions of this work were sponsored by ONELAN Limited for the cx18 driver
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307  USA
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/vmalloc.h>
+#include <linux/printk.h>
+
+#include <media/v4l2-device.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+
+#include "ivtv-driver.h"
+#include "ivtv-queue.h"
+#include "ivtv-streams.h"
+#include "ivtv-fileops.h"
+#include "ivtv-alsa.h"
+
+static unsigned int pcm_debug;
+module_param(pcm_debug, int, 0644);
+MODULE_PARM_DESC(pcm_debug, "enable debug messages for pcm");
+
+#define dprintk(fmt, arg...) \
+	do { \
+		if (pcm_debug) \
+			pr_info("ivtv-alsa-pcm %s: " fmt, __func__, ##arg); \
+	} while (0)
+
+static struct snd_pcm_hardware snd_ivtv_hw_capture = {
+	.info = SNDRV_PCM_INFO_BLOCK_TRANSFER |
+		SNDRV_PCM_INFO_MMAP           |
+		SNDRV_PCM_INFO_INTERLEAVED    |
+		SNDRV_PCM_INFO_MMAP_VALID,
+
+	.formats = SNDRV_PCM_FMTBIT_S16_LE,
+
+	.rates = SNDRV_PCM_RATE_48000,
+
+	.rate_min = 48000,
+	.rate_max = 48000,
+	.channels_min = 2,
+	.channels_max = 2,
+	.buffer_bytes_max = 62720 * 8,	/* just about the value in usbaudio.c */
+	.period_bytes_min = 64,		/* 12544/2, */
+	.period_bytes_max = 12544,
+	.periods_min = 2,
+	.periods_max = 98,		/* 12544, */
+};
+
+void ivtv_alsa_announce_pcm_data(struct snd_ivtv_card *itvsc, u8 *pcm_data,
+				 size_t num_bytes)
+{
+	struct snd_pcm_substream *substream;
+	struct snd_pcm_runtime *runtime;
+	unsigned int oldptr;
+	unsigned int stride;
+	int period_elapsed = 0;
+	int length;
+
+	dprintk("ivtv alsa announce ptr=%p data=%p num_bytes=%zd\n", itvsc,
+		pcm_data, num_bytes);
+
+	substream = itvsc->capture_pcm_substream;
+	if (substream == NULL) {
+		dprintk("substream was NULL\n");
+		return;
+	}
+
+	runtime = substream->runtime;
+	if (runtime == NULL) {
+		dprintk("runtime was NULL\n");
+		return;
+	}
+
+	stride = runtime->frame_bits >> 3;
+	if (stride == 0) {
+		dprintk("stride is zero\n");
+		return;
+	}
+
+	length = num_bytes / stride;
+	if (length == 0) {
+		dprintk("%s: length was zero\n", __func__);
+		return;
+	}
+
+	if (runtime->dma_area == NULL) {
+		dprintk("dma area was NULL - ignoring\n");
+		return;
+	}
+
+	oldptr = itvsc->hwptr_done_capture;
+	if (oldptr + length >= runtime->buffer_size) {
+		unsigned int cnt =
+			runtime->buffer_size - oldptr;
+		memcpy(runtime->dma_area + oldptr * stride, pcm_data,
+		       cnt * stride);
+		memcpy(runtime->dma_area, pcm_data + cnt * stride,
+		       length * stride - cnt * stride);
+	} else {
+		memcpy(runtime->dma_area + oldptr * stride, pcm_data,
+		       length * stride);
+	}
+	snd_pcm_stream_lock(substream);
+
+	itvsc->hwptr_done_capture += length;
+	if (itvsc->hwptr_done_capture >=
+	    runtime->buffer_size)
+		itvsc->hwptr_done_capture -=
+			runtime->buffer_size;
+
+	itvsc->capture_transfer_done += length;
+	if (itvsc->capture_transfer_done >=
+	    runtime->period_size) {
+		itvsc->capture_transfer_done -=
+			runtime->period_size;
+		period_elapsed = 1;
+	}
+
+	snd_pcm_stream_unlock(substream);
+
+	if (period_elapsed)
+		snd_pcm_period_elapsed(substream);
+}
+
+static int snd_ivtv_pcm_capture_open(struct snd_pcm_substream *substream)
+{
+	struct snd_ivtv_card *itvsc = snd_pcm_substream_chip(substream);
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct v4l2_device *v4l2_dev = itvsc->v4l2_dev;
+	struct ivtv *itv = to_ivtv(v4l2_dev);
+	struct ivtv_stream *s;
+	struct ivtv_open_id item;
+	int ret;
+
+	/* Instruct the CX2341[56] to start sending packets */
+	snd_ivtv_lock(itvsc);
+	s = &itv->streams[IVTV_ENC_STREAM_TYPE_PCM];
+
+	v4l2_fh_init(&item.fh, s->vdev);
+	item.itv = itv;
+	item.type = s->type;
+
+	/* See if the stream is available */
+	if (ivtv_claim_stream(&item, item.type)) {
+		/* No, it's already in use */
+		snd_ivtv_unlock(itvsc);
+		return -EBUSY;
+	}
+
+	if (test_bit(IVTV_F_S_STREAMOFF, &s->s_flags) ||
+	    test_and_set_bit(IVTV_F_S_STREAMING, &s->s_flags)) {
+		/* We're already streaming.  No additional action required */
+		snd_ivtv_unlock(itvsc);
+		return 0;
+	}
+
+
+	runtime->hw = snd_ivtv_hw_capture;
+	snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
+	itvsc->capture_pcm_substream = substream;
+	runtime->private_data = itv;
+
+	itv->pcm_announce_callback = ivtv_alsa_announce_pcm_data;
+
+	/* Not currently streaming, so start it up */
+	set_bit(IVTV_F_S_STREAMING, &s->s_flags);
+	ret = ivtv_start_v4l2_encode_stream(s);
+	snd_ivtv_unlock(itvsc);
+
+	return ret;
+}
+
+static int snd_ivtv_pcm_capture_close(struct snd_pcm_substream *substream)
+{
+	struct snd_ivtv_card *itvsc = snd_pcm_substream_chip(substream);
+	struct v4l2_device *v4l2_dev = itvsc->v4l2_dev;
+	struct ivtv *itv = to_ivtv(v4l2_dev);
+	struct ivtv_stream *s;
+
+	/* Instruct the ivtv to stop sending packets */
+	snd_ivtv_lock(itvsc);
+	s = &itv->streams[IVTV_ENC_STREAM_TYPE_PCM];
+	ivtv_stop_v4l2_encode_stream(s, 0);
+	clear_bit(IVTV_F_S_STREAMING, &s->s_flags);
+
+	ivtv_release_stream(s);
+
+	itv->pcm_announce_callback = NULL;
+	snd_ivtv_unlock(itvsc);
+
+	return 0;
+}
+
+static int snd_ivtv_pcm_ioctl(struct snd_pcm_substream *substream,
+		     unsigned int cmd, void *arg)
+{
+	struct snd_ivtv_card *itvsc = snd_pcm_substream_chip(substream);
+	int ret;
+
+	snd_ivtv_lock(itvsc);
+	ret = snd_pcm_lib_ioctl(substream, cmd, arg);
+	snd_ivtv_unlock(itvsc);
+	return ret;
+}
+
+
+static int snd_pcm_alloc_vmalloc_buffer(struct snd_pcm_substream *subs,
+					size_t size)
+{
+	struct snd_pcm_runtime *runtime = subs->runtime;
+
+	dprintk("Allocating vbuffer\n");
+	if (runtime->dma_area) {
+		if (runtime->dma_bytes > size)
+			return 0;
+
+		vfree(runtime->dma_area);
+	}
+	runtime->dma_area = vmalloc(size);
+	if (!runtime->dma_area)
+		return -ENOMEM;
+
+	runtime->dma_bytes = size;
+
+	return 0;
+}
+
+static int snd_ivtv_pcm_hw_params(struct snd_pcm_substream *substream,
+			 struct snd_pcm_hw_params *params)
+{
+	dprintk("%s called\n", __func__);
+
+	return snd_pcm_alloc_vmalloc_buffer(substream,
+					   params_buffer_bytes(params));
+}
+
+static int snd_ivtv_pcm_hw_free(struct snd_pcm_substream *substream)
+{
+	struct snd_ivtv_card *itvsc = snd_pcm_substream_chip(substream);
+	unsigned long flags;
+
+	spin_lock_irqsave(&itvsc->slock, flags);
+	if (substream->runtime->dma_area) {
+		dprintk("freeing pcm capture region\n");
+		vfree(substream->runtime->dma_area);
+		substream->runtime->dma_area = NULL;
+	}
+	spin_unlock_irqrestore(&itvsc->slock, flags);
+
+	return 0;
+}
+
+static int snd_ivtv_pcm_prepare(struct snd_pcm_substream *substream)
+{
+	struct snd_ivtv_card *itvsc = snd_pcm_substream_chip(substream);
+
+	itvsc->hwptr_done_capture = 0;
+	itvsc->capture_transfer_done = 0;
+
+	return 0;
+}
+
+static int snd_ivtv_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+	return 0;
+}
+
+static
+snd_pcm_uframes_t snd_ivtv_pcm_pointer(struct snd_pcm_substream *substream)
+{
+	unsigned long flags;
+	snd_pcm_uframes_t hwptr_done;
+	struct snd_ivtv_card *itvsc = snd_pcm_substream_chip(substream);
+
+	spin_lock_irqsave(&itvsc->slock, flags);
+	hwptr_done = itvsc->hwptr_done_capture;
+	spin_unlock_irqrestore(&itvsc->slock, flags);
+
+	return hwptr_done;
+}
+
+static struct page *snd_pcm_get_vmalloc_page(struct snd_pcm_substream *subs,
+					     unsigned long offset)
+{
+	void *pageptr = subs->runtime->dma_area + offset;
+
+	return vmalloc_to_page(pageptr);
+}
+
+static struct snd_pcm_ops snd_ivtv_pcm_capture_ops = {
+	.open		= snd_ivtv_pcm_capture_open,
+	.close		= snd_ivtv_pcm_capture_close,
+	.ioctl		= snd_ivtv_pcm_ioctl,
+	.hw_params	= snd_ivtv_pcm_hw_params,
+	.hw_free	= snd_ivtv_pcm_hw_free,
+	.prepare	= snd_ivtv_pcm_prepare,
+	.trigger	= snd_ivtv_pcm_trigger,
+	.pointer	= snd_ivtv_pcm_pointer,
+	.page		= snd_pcm_get_vmalloc_page,
+};
+
+int snd_ivtv_pcm_create(struct snd_ivtv_card *itvsc)
+{
+	struct snd_pcm *sp;
+	struct snd_card *sc = itvsc->sc;
+	struct v4l2_device *v4l2_dev = itvsc->v4l2_dev;
+	struct ivtv *itv = to_ivtv(v4l2_dev);
+	int ret;
+
+	ret = snd_pcm_new(sc, "CX2341[56] PCM",
+			  0, /* PCM device 0, the only one for this card */
+			  0, /* 0 playback substreams */
+			  1, /* 1 capture substream */
+			  &sp);
+	if (ret) {
+		IVTV_ALSA_ERR("%s: snd_ivtv_pcm_create() failed with err %d\n",
+			      __func__, ret);
+		goto err_exit;
+	}
+
+	spin_lock_init(&itvsc->slock);
+
+	snd_pcm_set_ops(sp, SNDRV_PCM_STREAM_CAPTURE,
+			&snd_ivtv_pcm_capture_ops);
+	sp->info_flags = 0;
+	sp->private_data = itvsc;
+	strlcpy(sp->name, itv->card_name, sizeof(sp->name));
+
+	return 0;
+
+err_exit:
+	return ret;
+}
diff --git a/drivers/media/pci/ivtv/ivtv-alsa-pcm.h b/drivers/media/pci/ivtv/ivtv-alsa-pcm.h
new file mode 100644
index 0000000..5ab1831
--- /dev/null
+++ b/drivers/media/pci/ivtv/ivtv-alsa-pcm.h
@@ -0,0 +1,27 @@
+/*
+ *  ALSA PCM device for the
+ *  ALSA interface to ivtv PCM capture streams
+ *
+ *  Copyright (C) 2009,2012  Andy Walls <awalls@md.metrocast.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 program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307  USA
+ */
+
+int __init snd_ivtv_pcm_create(struct snd_ivtv_card *itvsc);
+
+/* Used by ivtv driver to announce the PCM data to the module */
+void ivtv_alsa_announce_pcm_data(struct snd_ivtv_card *card, u8 *pcm_data,
+				 size_t num_bytes);
diff --git a/drivers/media/pci/ivtv/ivtv-alsa.h b/drivers/media/pci/ivtv/ivtv-alsa.h
new file mode 100644
index 0000000..4a0d8f2
--- /dev/null
+++ b/drivers/media/pci/ivtv/ivtv-alsa.h
@@ -0,0 +1,75 @@
+/*
+ *  ALSA interface to ivtv PCM capture streams
+ *
+ *  Copyright (C) 2009,2012  Andy Walls <awalls@md.metrocast.net>
+ *  Copyright (C) 2009  Devin Heitmueller <dheitmueller@kernellabs.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
+ */
+
+struct snd_card;
+
+struct snd_ivtv_card {
+	struct v4l2_device *v4l2_dev;
+	struct snd_card *sc;
+	unsigned int capture_transfer_done;
+	unsigned int hwptr_done_capture;
+	struct snd_pcm_substream *capture_pcm_substream;
+	spinlock_t slock;
+};
+
+extern int ivtv_alsa_debug;
+
+/*
+ * File operations that manipulate the encoder or video or audio subdevices
+ * need to be serialized.  Use the same lock we use for v4l2 file ops.
+ */
+static inline void snd_ivtv_lock(struct snd_ivtv_card *itvsc)
+{
+	struct ivtv *itv = to_ivtv(itvsc->v4l2_dev);
+	mutex_lock(&itv->serialize_lock);
+}
+
+static inline void snd_ivtv_unlock(struct snd_ivtv_card *itvsc)
+{
+	struct ivtv *itv = to_ivtv(itvsc->v4l2_dev);
+	mutex_unlock(&itv->serialize_lock);
+}
+
+#define IVTV_ALSA_DBGFLG_WARN  (1 << 0)
+#define IVTV_ALSA_DBGFLG_INFO  (1 << 1)
+
+#define IVTV_ALSA_DEBUG(x, type, fmt, args...) \
+	do { \
+		if ((x) & ivtv_alsa_debug) \
+			pr_info("%s-alsa: " type ": " fmt, \
+				v4l2_dev->name , ## args); \
+	} while (0)
+
+#define IVTV_ALSA_DEBUG_WARN(fmt, args...) \
+	IVTV_ALSA_DEBUG(IVTV_ALSA_DBGFLG_WARN, "warning", fmt , ## args)
+
+#define IVTV_ALSA_DEBUG_INFO(fmt, args...) \
+	IVTV_ALSA_DEBUG(IVTV_ALSA_DBGFLG_INFO, "info", fmt , ## args)
+
+#define IVTV_ALSA_ERR(fmt, args...) \
+	pr_err("%s-alsa: " fmt, v4l2_dev->name , ## args)
+
+#define IVTV_ALSA_WARN(fmt, args...) \
+	pr_warn("%s-alsa: " fmt, v4l2_dev->name , ## args)
+
+#define IVTV_ALSA_INFO(fmt, args...) \
+	pr_info("%s-alsa: " fmt, v4l2_dev->name , ## args)
diff --git a/drivers/media/pci/ivtv/ivtv-cards.c b/drivers/media/pci/ivtv/ivtv-cards.c
new file mode 100644
index 0000000..145e474
--- /dev/null
+++ b/drivers/media/pci/ivtv/ivtv-cards.c
@@ -0,0 +1,1370 @@
+/*
+    Functions to query card hardware
+    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
+    Copyright (C) 2005-2007  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "ivtv-driver.h"
+#include "ivtv-cards.h"
+#include "ivtv-i2c.h"
+
+#include <media/msp3400.h>
+#include <media/m52790.h>
+#include <media/wm8775.h>
+#include <media/cs53l32a.h>
+#include <media/cx25840.h>
+#include <media/upd64031a.h>
+
+#define MSP_TUNER  MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER1, \
+				MSP_DSP_IN_TUNER, MSP_DSP_IN_TUNER)
+#define MSP_SCART1 MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER1, \
+				MSP_DSP_IN_SCART, MSP_DSP_IN_SCART)
+#define MSP_SCART2 MSP_INPUT(MSP_IN_SCART2, MSP_IN_TUNER1, \
+				MSP_DSP_IN_SCART, MSP_DSP_IN_SCART)
+#define MSP_SCART3 MSP_INPUT(MSP_IN_SCART3, MSP_IN_TUNER1, \
+				MSP_DSP_IN_SCART, MSP_DSP_IN_SCART)
+#define MSP_MONO   MSP_INPUT(MSP_IN_MONO, MSP_IN_TUNER1, \
+				MSP_DSP_IN_SCART, MSP_DSP_IN_SCART)
+
+#define V4L2_STD_PAL_SECAM (V4L2_STD_PAL|V4L2_STD_SECAM)
+
+/* usual i2c tuner addresses to probe */
+static struct ivtv_card_tuner_i2c ivtv_i2c_std = {
+	.radio = { I2C_CLIENT_END },
+	.demod = { 0x43, I2C_CLIENT_END },
+	.tv    = { 0x61, 0x60, I2C_CLIENT_END },
+};
+
+/* as above, but with possible radio tuner */
+static struct ivtv_card_tuner_i2c ivtv_i2c_radio = {
+	.radio = { 0x60, I2C_CLIENT_END },
+	.demod = { 0x43, I2C_CLIENT_END },
+	.tv    = { 0x61, I2C_CLIENT_END },
+};
+
+/* using the tda8290+75a combo */
+static struct ivtv_card_tuner_i2c ivtv_i2c_tda8290 = {
+	.radio = { I2C_CLIENT_END },
+	.demod = { I2C_CLIENT_END },
+	.tv    = { 0x4b, I2C_CLIENT_END },
+};
+
+/********************** card configuration *******************************/
+
+/* Please add new PCI IDs to: http://pci-ids.ucw.cz/ 
+   This keeps the PCI ID database up to date. Note that the entries
+   must be added under vendor 0x4444 (Conexant) as subsystem IDs.
+   New vendor IDs should still be added to the vendor ID list. */
+
+/* Hauppauge PVR-250 cards */
+
+/* Note: for Hauppauge cards the tveeprom information is used instead of PCI IDs */
+static const struct ivtv_card ivtv_card_pvr250 = {
+	.type = IVTV_CARD_PVR_250,
+	.name = "Hauppauge WinTV PVR-250",
+	.v4l2_capabilities = IVTV_CAP_ENCODER,
+	.hw_video = IVTV_HW_SAA7115,
+	.hw_audio = IVTV_HW_MSP34XX,
+	.hw_audio_ctrl = IVTV_HW_MSP34XX,
+	.hw_all = IVTV_HW_MSP34XX | IVTV_HW_SAA7115 |
+		  IVTV_HW_TVEEPROM | IVTV_HW_TUNER,
+	.video_inputs = {
+		{ IVTV_CARD_INPUT_VID_TUNER,  0, IVTV_SAA71XX_COMPOSITE4 },
+		{ IVTV_CARD_INPUT_SVIDEO1,    1, IVTV_SAA71XX_SVIDEO0    },
+		{ IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_COMPOSITE0 },
+		{ IVTV_CARD_INPUT_SVIDEO2,    2, IVTV_SAA71XX_SVIDEO1    },
+		{ IVTV_CARD_INPUT_COMPOSITE2, 2, IVTV_SAA71XX_COMPOSITE1 },
+		{ IVTV_CARD_INPUT_COMPOSITE3, 1, IVTV_SAA71XX_COMPOSITE5 },
+	},
+	.audio_inputs = {
+		{ IVTV_CARD_INPUT_AUD_TUNER,  MSP_TUNER  },
+		{ IVTV_CARD_INPUT_LINE_IN1,   MSP_SCART1 },
+		{ IVTV_CARD_INPUT_LINE_IN2,   MSP_SCART3 },
+	},
+	.radio_input = { IVTV_CARD_INPUT_AUD_TUNER, MSP_SCART2 },
+	.i2c = &ivtv_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* Hauppauge PVR-350 cards */
+
+/* Outputs for Hauppauge PVR350 cards */
+static struct ivtv_card_output ivtv_pvr350_outputs[] = {
+	{
+		.name = "S-Video + Composite",
+		.video_output = 0,
+	}, {
+		.name = "Composite",
+		.video_output = 1,
+	}, {
+		.name = "S-Video",
+		.video_output = 2,
+	}, {
+		.name = "RGB",
+		.video_output = 3,
+	}, {
+		.name = "YUV C",
+		.video_output = 4,
+	}, {
+		.name = "YUV V",
+		.video_output = 5,
+	}
+};
+
+static const struct ivtv_card ivtv_card_pvr350 = {
+	.type = IVTV_CARD_PVR_350,
+	.name = "Hauppauge WinTV PVR-350",
+	.v4l2_capabilities = IVTV_CAP_ENCODER | IVTV_CAP_DECODER,
+	.video_outputs = ivtv_pvr350_outputs,
+	.nof_outputs = ARRAY_SIZE(ivtv_pvr350_outputs),
+	.hw_video = IVTV_HW_SAA7115,
+	.hw_audio = IVTV_HW_MSP34XX,
+	.hw_audio_ctrl = IVTV_HW_MSP34XX,
+	.hw_all = IVTV_HW_MSP34XX | IVTV_HW_SAA7115 |
+		  IVTV_HW_SAA7127 | IVTV_HW_TVEEPROM | IVTV_HW_TUNER |
+		  IVTV_HW_I2C_IR_RX_HAUP_EXT | IVTV_HW_I2C_IR_RX_HAUP_INT,
+	.video_inputs = {
+		{ IVTV_CARD_INPUT_VID_TUNER,  0, IVTV_SAA71XX_COMPOSITE4 },
+		{ IVTV_CARD_INPUT_SVIDEO1,    1, IVTV_SAA71XX_SVIDEO0    },
+		{ IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_COMPOSITE0 },
+		{ IVTV_CARD_INPUT_SVIDEO2,    2, IVTV_SAA71XX_SVIDEO1    },
+		{ IVTV_CARD_INPUT_COMPOSITE2, 2, IVTV_SAA71XX_COMPOSITE1 },
+		{ IVTV_CARD_INPUT_COMPOSITE3, 1, IVTV_SAA71XX_COMPOSITE5 },
+	},
+	.audio_inputs = {
+		{ IVTV_CARD_INPUT_AUD_TUNER,  MSP_TUNER  },
+		{ IVTV_CARD_INPUT_LINE_IN1,   MSP_SCART1 },
+		{ IVTV_CARD_INPUT_LINE_IN2,   MSP_SCART3 },
+	},
+	.radio_input = { IVTV_CARD_INPUT_AUD_TUNER, MSP_SCART2 },
+	.i2c = &ivtv_i2c_std,
+};
+
+/* PVR-350 V1 boards have a different audio tuner input and use a
+   saa7114 instead of a saa7115.
+   Note that the info below comes from a pre-production model so it may
+   not be correct. Especially the audio behaves strangely (mono only it seems) */
+static const struct ivtv_card ivtv_card_pvr350_v1 = {
+	.type = IVTV_CARD_PVR_350_V1,
+	.name = "Hauppauge WinTV PVR-350 (V1)",
+	.v4l2_capabilities = IVTV_CAP_ENCODER | IVTV_CAP_DECODER,
+	.video_outputs = ivtv_pvr350_outputs,
+	.nof_outputs = ARRAY_SIZE(ivtv_pvr350_outputs),
+	.hw_video = IVTV_HW_SAA7114,
+	.hw_audio = IVTV_HW_MSP34XX,
+	.hw_audio_ctrl = IVTV_HW_MSP34XX,
+	.hw_all = IVTV_HW_MSP34XX | IVTV_HW_SAA7114 |
+		  IVTV_HW_SAA7127 | IVTV_HW_TVEEPROM | IVTV_HW_TUNER,
+	.video_inputs = {
+		{ IVTV_CARD_INPUT_VID_TUNER,  0, IVTV_SAA71XX_COMPOSITE4 },
+		{ IVTV_CARD_INPUT_SVIDEO1,    1, IVTV_SAA71XX_SVIDEO0    },
+		{ IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_COMPOSITE0 },
+		{ IVTV_CARD_INPUT_SVIDEO2,    2, IVTV_SAA71XX_SVIDEO1    },
+		{ IVTV_CARD_INPUT_COMPOSITE2, 2, IVTV_SAA71XX_COMPOSITE1 },
+		{ IVTV_CARD_INPUT_COMPOSITE3, 1, IVTV_SAA71XX_COMPOSITE5 },
+	},
+	.audio_inputs = {
+		{ IVTV_CARD_INPUT_AUD_TUNER,  MSP_MONO   },
+		{ IVTV_CARD_INPUT_LINE_IN1,   MSP_SCART1 },
+		{ IVTV_CARD_INPUT_LINE_IN2,   MSP_SCART3 },
+	},
+	.radio_input = { IVTV_CARD_INPUT_AUD_TUNER, MSP_SCART2 },
+	.i2c = &ivtv_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* Hauppauge PVR-150/PVR-500 cards */
+
+static const struct ivtv_card ivtv_card_pvr150 = {
+	.type = IVTV_CARD_PVR_150,
+	.name = "Hauppauge WinTV PVR-150",
+	.v4l2_capabilities = IVTV_CAP_ENCODER,
+	.hw_video = IVTV_HW_CX25840,
+	.hw_audio = IVTV_HW_CX25840,
+	.hw_audio_ctrl = IVTV_HW_CX25840,
+	.hw_muxer = IVTV_HW_WM8775,
+	.hw_all = IVTV_HW_WM8775 | IVTV_HW_CX25840 |
+		  IVTV_HW_TVEEPROM | IVTV_HW_TUNER |
+		  IVTV_HW_I2C_IR_RX_HAUP_EXT | IVTV_HW_I2C_IR_RX_HAUP_INT |
+		  IVTV_HW_Z8F0811_IR_HAUP,
+	.video_inputs = {
+		{ IVTV_CARD_INPUT_VID_TUNER,  0, CX25840_COMPOSITE7 },
+		{ IVTV_CARD_INPUT_SVIDEO1,    1, CX25840_SVIDEO1    },
+		{ IVTV_CARD_INPUT_COMPOSITE1, 1, CX25840_COMPOSITE3 },
+		{ IVTV_CARD_INPUT_SVIDEO2,    2, CX25840_SVIDEO2    },
+		{ IVTV_CARD_INPUT_COMPOSITE2, 2, CX25840_COMPOSITE4 },
+	},
+	.audio_inputs = {
+		{ IVTV_CARD_INPUT_AUD_TUNER,
+		  CX25840_AUDIO8, WM8775_AIN2 },
+		{ IVTV_CARD_INPUT_LINE_IN1,
+		  CX25840_AUDIO_SERIAL, WM8775_AIN2 },
+		{ IVTV_CARD_INPUT_LINE_IN2,
+		  CX25840_AUDIO_SERIAL, WM8775_AIN3 },
+	},
+	.radio_input = { IVTV_CARD_INPUT_AUD_TUNER,
+			 CX25840_AUDIO_SERIAL, WM8775_AIN4 },
+	/* apparently needed for the IR blaster */
+	.gpio_init = { .direction = 0x1f01, .initial_value = 0x26f3 },
+	.i2c = &ivtv_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* AVerMedia M179 cards */
+
+static const struct ivtv_card_pci_info ivtv_pci_m179[] = {
+	{ PCI_DEVICE_ID_IVTV15, IVTV_PCI_ID_AVERMEDIA, 0xa3cf },
+	{ PCI_DEVICE_ID_IVTV15, IVTV_PCI_ID_AVERMEDIA, 0xa3ce },
+	{ 0, 0, 0 }
+};
+
+static const struct ivtv_card ivtv_card_m179 = {
+	.type = IVTV_CARD_M179,
+	.name = "AVerMedia M179",
+	.v4l2_capabilities = IVTV_CAP_ENCODER,
+	.hw_video = IVTV_HW_SAA7114,
+	.hw_audio = IVTV_HW_GPIO,
+	.hw_audio_ctrl = IVTV_HW_GPIO,
+	.hw_all = IVTV_HW_GPIO | IVTV_HW_SAA7114 | IVTV_HW_TUNER,
+	.video_inputs = {
+		{ IVTV_CARD_INPUT_VID_TUNER,  0, IVTV_SAA71XX_COMPOSITE4 },
+		{ IVTV_CARD_INPUT_SVIDEO1,    1, IVTV_SAA71XX_SVIDEO0    },
+		{ IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_COMPOSITE3 },
+	},
+	.audio_inputs = {
+		{ IVTV_CARD_INPUT_AUD_TUNER,  IVTV_GPIO_TUNER   },
+		{ IVTV_CARD_INPUT_LINE_IN1,   IVTV_GPIO_LINE_IN },
+	},
+	.gpio_init = { .direction = 0xe380, .initial_value = 0x8290 },
+	.gpio_audio_input  = { .mask = 0x8040, .tuner  = 0x8000, .linein = 0x0000 },
+	.gpio_audio_mute   = { .mask = 0x2000, .mute   = 0x2000 },
+	.gpio_audio_mode   = { .mask = 0x4300, .mono   = 0x4000, .stereo = 0x0200,
+			      .lang1 = 0x0200, .lang2  = 0x0100, .both   = 0x0000 },
+	.gpio_audio_freq   = { .mask = 0x0018, .f32000 = 0x0000,
+			     .f44100 = 0x0008, .f48000 = 0x0010 },
+	.gpio_audio_detect = { .mask = 0x4000, .stereo = 0x0000 },
+	.tuners = {
+		/* As far as we know all M179 cards use this tuner */
+		{ .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_NTSC },
+	},
+	.pci_list = ivtv_pci_m179,
+	.i2c = &ivtv_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* Yuan MPG600/Kuroutoshikou ITVC16-STVLP cards */
+
+static const struct ivtv_card_pci_info ivtv_pci_mpg600[] = {
+	{ PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_YUAN1, 0xfff3 },
+	{ PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_YUAN1, 0xffff },
+	{ 0, 0, 0 }
+};
+
+static const struct ivtv_card ivtv_card_mpg600 = {
+	.type = IVTV_CARD_MPG600,
+	.name = "Yuan MPG600, Kuroutoshikou ITVC16-STVLP",
+	.v4l2_capabilities = IVTV_CAP_ENCODER,
+	.hw_video = IVTV_HW_SAA7115,
+	.hw_audio = IVTV_HW_GPIO,
+	.hw_audio_ctrl = IVTV_HW_GPIO,
+	.hw_all = IVTV_HW_GPIO | IVTV_HW_SAA7115 | IVTV_HW_TUNER,
+	.video_inputs = {
+		{ IVTV_CARD_INPUT_VID_TUNER,  0, IVTV_SAA71XX_COMPOSITE4 },
+		{ IVTV_CARD_INPUT_SVIDEO1,    1, IVTV_SAA71XX_SVIDEO0    },
+		{ IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_COMPOSITE3 },
+	},
+	.audio_inputs = {
+		{ IVTV_CARD_INPUT_AUD_TUNER,  IVTV_GPIO_TUNER   },
+		{ IVTV_CARD_INPUT_LINE_IN1,   IVTV_GPIO_LINE_IN },
+	},
+	.gpio_init = { .direction = 0x3080, .initial_value = 0x0004 },
+	.gpio_audio_input  = { .mask = 0x3000, .tuner  = 0x0000, .linein = 0x2000 },
+	.gpio_audio_mute   = { .mask = 0x0001, .mute   = 0x0001 },
+	.gpio_audio_mode   = { .mask = 0x000e, .mono   = 0x0006, .stereo = 0x0004,
+			      .lang1 = 0x0004, .lang2  = 0x0000, .both   = 0x0008 },
+	.gpio_audio_detect = { .mask = 0x0900, .stereo = 0x0100 },
+	.tuners = {
+		/* The PAL tuner is confirmed */
+		{ .std = V4L2_STD_PAL_SECAM, .tuner = TUNER_PHILIPS_FQ1216ME },
+		{ .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FQ1286 },
+	},
+	.pci_list = ivtv_pci_mpg600,
+	.i2c = &ivtv_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* Yuan MPG160/Kuroutoshikou ITVC15-STVLP cards */
+
+static const struct ivtv_card_pci_info ivtv_pci_mpg160[] = {
+	{ PCI_DEVICE_ID_IVTV15, IVTV_PCI_ID_YUAN1, 0 },
+	{ PCI_DEVICE_ID_IVTV15, IVTV_PCI_ID_IODATA, 0x40a0 },
+	{ 0, 0, 0 }
+};
+
+static const struct ivtv_card ivtv_card_mpg160 = {
+	.type = IVTV_CARD_MPG160,
+	.name = "YUAN MPG160, Kuroutoshikou ITVC15-STVLP, I/O Data GV-M2TV/PCI",
+	.v4l2_capabilities = IVTV_CAP_ENCODER,
+	.hw_video = IVTV_HW_SAA7114,
+	.hw_audio = IVTV_HW_GPIO,
+	.hw_audio_ctrl = IVTV_HW_GPIO,
+	.hw_all = IVTV_HW_GPIO | IVTV_HW_SAA7114 | IVTV_HW_TUNER,
+	.video_inputs = {
+		{ IVTV_CARD_INPUT_VID_TUNER,  0, IVTV_SAA71XX_COMPOSITE4 },
+		{ IVTV_CARD_INPUT_SVIDEO1,    1, IVTV_SAA71XX_SVIDEO0    },
+		{ IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_COMPOSITE3 },
+	},
+	.audio_inputs = {
+		{ IVTV_CARD_INPUT_AUD_TUNER,  IVTV_GPIO_TUNER   },
+		{ IVTV_CARD_INPUT_LINE_IN1,   IVTV_GPIO_LINE_IN },
+	},
+	.gpio_init = { .direction = 0x7080, .initial_value = 0x400c },
+	.gpio_audio_input  = { .mask = 0x3000, .tuner  = 0x0000, .linein = 0x2000 },
+	.gpio_audio_mute   = { .mask = 0x0001, .mute   = 0x0001 },
+	.gpio_audio_mode   = { .mask = 0x000e, .mono   = 0x0006, .stereo = 0x0004,
+			      .lang1 = 0x0004, .lang2  = 0x0000, .both   = 0x0008 },
+	.gpio_audio_detect = { .mask = 0x0900, .stereo = 0x0100 },
+	.tuners = {
+		{ .std = V4L2_STD_PAL_SECAM, .tuner = TUNER_PHILIPS_FQ1216ME },
+		{ .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FQ1286 },
+	},
+	.pci_list = ivtv_pci_mpg160,
+	.i2c = &ivtv_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* Yuan PG600/Diamond PVR-550 cards */
+
+static const struct ivtv_card_pci_info ivtv_pci_pg600[] = {
+	{ PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_DIAMONDMM, 0x0070 },
+	{ PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_YUAN3,     0x0600 },
+	{ 0, 0, 0 }
+};
+
+static const struct ivtv_card ivtv_card_pg600 = {
+	.type = IVTV_CARD_PG600,
+	.name = "Yuan PG600, Diamond PVR-550",
+	.v4l2_capabilities = IVTV_CAP_ENCODER,
+	.hw_video = IVTV_HW_CX25840,
+	.hw_audio = IVTV_HW_CX25840,
+	.hw_audio_ctrl = IVTV_HW_CX25840,
+	.hw_all = IVTV_HW_CX25840 | IVTV_HW_TUNER,
+	.video_inputs = {
+		{ IVTV_CARD_INPUT_VID_TUNER,  0, CX25840_COMPOSITE2 },
+		{ IVTV_CARD_INPUT_SVIDEO1,    1,
+		  CX25840_SVIDEO_LUMA3 | CX25840_SVIDEO_CHROMA4 },
+		{ IVTV_CARD_INPUT_COMPOSITE1, 1, CX25840_COMPOSITE1 },
+	},
+	.audio_inputs = {
+		{ IVTV_CARD_INPUT_AUD_TUNER,  CX25840_AUDIO5       },
+		{ IVTV_CARD_INPUT_LINE_IN1,   CX25840_AUDIO_SERIAL },
+	},
+	.tuners = {
+		{ .std = V4L2_STD_PAL_SECAM, .tuner = TUNER_PHILIPS_FQ1216ME },
+		{ .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FQ1286 },
+	},
+	.pci_list = ivtv_pci_pg600,
+	.i2c = &ivtv_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* Adaptec VideOh! AVC-2410 card */
+
+static const struct ivtv_card_pci_info ivtv_pci_avc2410[] = {
+	{ PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_ADAPTEC, 0x0093 },
+	{ 0, 0, 0 }
+};
+
+static const struct ivtv_card ivtv_card_avc2410 = {
+	.type = IVTV_CARD_AVC2410,
+	.name = "Adaptec VideOh! AVC-2410",
+	.v4l2_capabilities = IVTV_CAP_ENCODER,
+	.hw_video = IVTV_HW_SAA7115,
+	.hw_audio = IVTV_HW_MSP34XX,
+	.hw_audio_ctrl = IVTV_HW_MSP34XX,
+	.hw_muxer = IVTV_HW_CS53L32A,
+	.hw_all = IVTV_HW_MSP34XX | IVTV_HW_CS53L32A |
+		  IVTV_HW_SAA7115 | IVTV_HW_TUNER |
+		  IVTV_HW_I2C_IR_RX_ADAPTEC,
+	.video_inputs = {
+		{ IVTV_CARD_INPUT_VID_TUNER,  0, IVTV_SAA71XX_COMPOSITE4 },
+		{ IVTV_CARD_INPUT_SVIDEO1,    1, IVTV_SAA71XX_SVIDEO0    },
+		{ IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_COMPOSITE3 },
+	},
+	.audio_inputs = {
+		{ IVTV_CARD_INPUT_AUD_TUNER,
+		  MSP_TUNER, CS53L32A_IN0 },
+		{ IVTV_CARD_INPUT_LINE_IN1,
+		  MSP_SCART1, CS53L32A_IN2 },
+	},
+	/* This card has no eeprom and in fact the Windows driver relies
+	   on the country/region setting of the user to decide which tuner
+	   is available. */
+	.tuners = {
+		{ .std = V4L2_STD_PAL_SECAM, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
+		{ .std = V4L2_STD_ALL - V4L2_STD_NTSC_M_JP,
+			.tuner = TUNER_PHILIPS_FM1236_MK3 },
+		{ .std = V4L2_STD_NTSC_M_JP, .tuner = TUNER_PHILIPS_FQ1286 },
+	},
+	.pci_list = ivtv_pci_avc2410,
+	.i2c = &ivtv_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* Adaptec VideOh! AVC-2010 card */
+
+static const struct ivtv_card_pci_info ivtv_pci_avc2010[] = {
+	{ PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_ADAPTEC, 0x0092 },
+	{ 0, 0, 0 }
+};
+
+static const struct ivtv_card ivtv_card_avc2010 = {
+	.type = IVTV_CARD_AVC2010,
+	.name = "Adaptec VideOh! AVC-2010",
+	.v4l2_capabilities = IVTV_CAP_ENCODER,
+	.hw_video = IVTV_HW_SAA7115,
+	.hw_audio = IVTV_HW_CS53L32A,
+	.hw_audio_ctrl = IVTV_HW_CS53L32A,
+	.hw_all = IVTV_HW_CS53L32A | IVTV_HW_SAA7115,
+	.video_inputs = {
+		{ IVTV_CARD_INPUT_SVIDEO1,    0, IVTV_SAA71XX_SVIDEO0    },
+		{ IVTV_CARD_INPUT_COMPOSITE1, 0, IVTV_SAA71XX_COMPOSITE3 },
+	},
+	.audio_inputs = {
+		{ IVTV_CARD_INPUT_LINE_IN1,   CS53L32A_IN2 },
+	},
+	/* Does not have a tuner */
+	.pci_list = ivtv_pci_avc2010,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* Nagase Transgear 5000TV card */
+
+static const struct ivtv_card_pci_info ivtv_pci_tg5000tv[] = {
+	{ PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_AVERMEDIA, 0xbfff },
+	{ 0, 0, 0 }
+};
+
+static const struct ivtv_card ivtv_card_tg5000tv = {
+	.type = IVTV_CARD_TG5000TV,
+	.name = "Nagase Transgear 5000TV",
+	.v4l2_capabilities = IVTV_CAP_ENCODER,
+	.hw_video = IVTV_HW_SAA7114 | IVTV_HW_UPD64031A | IVTV_HW_UPD6408X |
+	IVTV_HW_GPIO,
+	.hw_audio = IVTV_HW_GPIO,
+	.hw_audio_ctrl = IVTV_HW_GPIO,
+	.hw_all = IVTV_HW_GPIO | IVTV_HW_SAA7114 | IVTV_HW_TUNER |
+		  IVTV_HW_UPD64031A | IVTV_HW_UPD6408X,
+	.video_inputs = {
+		{ IVTV_CARD_INPUT_VID_TUNER,  0, IVTV_SAA71XX_SVIDEO0 },
+		{ IVTV_CARD_INPUT_SVIDEO1,    1, IVTV_SAA71XX_SVIDEO2 },
+		{ IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_SVIDEO2 },
+	},
+	.audio_inputs = {
+		{ IVTV_CARD_INPUT_AUD_TUNER,  IVTV_GPIO_TUNER   },
+		{ IVTV_CARD_INPUT_LINE_IN1,   IVTV_GPIO_LINE_IN },
+	},
+	.gr_config = UPD64031A_VERTICAL_EXTERNAL,
+	.gpio_init = { .direction = 0xe080, .initial_value = 0x8000 },
+	.gpio_audio_input  = { .mask = 0x8080, .tuner  = 0x8000, .linein = 0x0080 },
+	.gpio_audio_mute   = { .mask = 0x6000, .mute   = 0x6000 },
+	.gpio_audio_mode   = { .mask = 0x4300, .mono   = 0x4000, .stereo = 0x0200,
+			      .lang1 = 0x0300, .lang2  = 0x0000, .both   = 0x0200 },
+	.gpio_video_input  = { .mask = 0x0030, .tuner  = 0x0000,
+			  .composite = 0x0010, .svideo = 0x0020 },
+	.tuners = {
+		{ .std = V4L2_STD_MN, .tuner = TUNER_PHILIPS_FQ1286 },
+	},
+	.pci_list = ivtv_pci_tg5000tv,
+	.i2c = &ivtv_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* AOpen VA2000MAX-SNT6 card */
+
+static const struct ivtv_card_pci_info ivtv_pci_va2000[] = {
+	{ PCI_DEVICE_ID_IVTV16, 0, 0xff5f },
+	{ 0, 0, 0 }
+};
+
+static const struct ivtv_card ivtv_card_va2000 = {
+	.type = IVTV_CARD_VA2000MAX_SNT6,
+	.name = "AOpen VA2000MAX-SNT6",
+	.v4l2_capabilities = IVTV_CAP_ENCODER,
+	.hw_video = IVTV_HW_SAA7115 | IVTV_HW_UPD6408X,
+	.hw_audio = IVTV_HW_MSP34XX,
+	.hw_audio_ctrl = IVTV_HW_MSP34XX,
+	.hw_all = IVTV_HW_MSP34XX | IVTV_HW_SAA7115 |
+		  IVTV_HW_UPD6408X | IVTV_HW_TUNER,
+	.video_inputs = {
+		{ IVTV_CARD_INPUT_VID_TUNER, 0, IVTV_SAA71XX_SVIDEO0 },
+	},
+	.audio_inputs = {
+		{ IVTV_CARD_INPUT_AUD_TUNER, MSP_TUNER },
+	},
+	.tuners = {
+		{ .std = V4L2_STD_MN, .tuner = TUNER_PHILIPS_FQ1286 },
+	},
+	.pci_list = ivtv_pci_va2000,
+	.i2c = &ivtv_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* Yuan MPG600GR/Kuroutoshikou CX23416GYC-STVLP cards */
+
+static const struct ivtv_card_pci_info ivtv_pci_cx23416gyc[] = {
+	{ PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_YUAN1, 0x0600 },
+	{ PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_YUAN4, 0x0600 },
+	{ PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_MELCO, 0x0523 },
+	{ 0, 0, 0 }
+};
+
+static const struct ivtv_card ivtv_card_cx23416gyc = {
+	.type = IVTV_CARD_CX23416GYC,
+	.name = "Yuan MPG600GR, Kuroutoshikou CX23416GYC-STVLP",
+	.v4l2_capabilities = IVTV_CAP_ENCODER,
+	.hw_video = IVTV_HW_SAA717X | IVTV_HW_GPIO |
+		IVTV_HW_UPD64031A | IVTV_HW_UPD6408X,
+	.hw_audio = IVTV_HW_SAA717X,
+	.hw_audio_ctrl = IVTV_HW_SAA717X,
+	.hw_all = IVTV_HW_GPIO | IVTV_HW_SAA717X | IVTV_HW_TUNER |
+		  IVTV_HW_UPD64031A | IVTV_HW_UPD6408X,
+	.video_inputs = {
+		{ IVTV_CARD_INPUT_VID_TUNER,  0, IVTV_SAA71XX_SVIDEO3 |
+						 IVTV_SAA717X_TUNER_FLAG },
+		{ IVTV_CARD_INPUT_SVIDEO1,    1, IVTV_SAA71XX_SVIDEO0 },
+		{ IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_SVIDEO3 },
+	},
+	.audio_inputs = {
+		{ IVTV_CARD_INPUT_AUD_TUNER,  IVTV_SAA717X_IN2 },
+		{ IVTV_CARD_INPUT_LINE_IN1,   IVTV_SAA717X_IN0 },
+	},
+	.gr_config = UPD64031A_VERTICAL_EXTERNAL,
+	.gpio_init = { .direction = 0xf880, .initial_value = 0x8800 },
+	.gpio_video_input  = { .mask = 0x0020, .tuner  = 0x0000,
+			       .composite = 0x0020, .svideo = 0x0020 },
+	.gpio_audio_freq   = { .mask = 0xc000, .f32000 = 0x0000,
+			     .f44100 = 0x4000, .f48000 = 0x8000 },
+	.tuners = {
+		{ .std = V4L2_STD_PAL_SECAM, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
+		{ .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FM1236_MK3 },
+	},
+	.pci_list = ivtv_pci_cx23416gyc,
+	.i2c = &ivtv_i2c_std,
+};
+
+static const struct ivtv_card ivtv_card_cx23416gyc_nogr = {
+	.type = IVTV_CARD_CX23416GYC_NOGR,
+	.name = "Yuan MPG600GR, Kuroutoshikou CX23416GYC-STVLP (no GR)",
+	.v4l2_capabilities = IVTV_CAP_ENCODER,
+	.hw_video = IVTV_HW_SAA717X | IVTV_HW_GPIO | IVTV_HW_UPD6408X,
+	.hw_audio = IVTV_HW_SAA717X,
+	.hw_audio_ctrl = IVTV_HW_SAA717X,
+	.hw_all = IVTV_HW_GPIO | IVTV_HW_SAA717X | IVTV_HW_TUNER |
+		  IVTV_HW_UPD6408X,
+	.video_inputs = {
+		{ IVTV_CARD_INPUT_VID_TUNER,  0, IVTV_SAA71XX_COMPOSITE4 |
+						 IVTV_SAA717X_TUNER_FLAG },
+		{ IVTV_CARD_INPUT_SVIDEO1,    1, IVTV_SAA71XX_SVIDEO0    },
+		{ IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_COMPOSITE0 },
+	},
+	.audio_inputs = {
+		{ IVTV_CARD_INPUT_AUD_TUNER,  IVTV_SAA717X_IN2 },
+		{ IVTV_CARD_INPUT_LINE_IN1,   IVTV_SAA717X_IN0 },
+	},
+	.gpio_init = { .direction = 0xf880, .initial_value = 0x8800 },
+	.gpio_video_input  = { .mask = 0x0020, .tuner  = 0x0000,
+			       .composite = 0x0020, .svideo = 0x0020 },
+	.gpio_audio_freq   = { .mask = 0xc000, .f32000 = 0x0000,
+			     .f44100 = 0x4000, .f48000 = 0x8000 },
+	.tuners = {
+		{ .std = V4L2_STD_PAL_SECAM, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
+		{ .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FM1236_MK3 },
+	},
+	.i2c = &ivtv_i2c_std,
+};
+
+static const struct ivtv_card ivtv_card_cx23416gyc_nogrycs = {
+	.type = IVTV_CARD_CX23416GYC_NOGRYCS,
+	.name = "Yuan MPG600GR, Kuroutoshikou CX23416GYC-STVLP (no GR/YCS)",
+	.v4l2_capabilities = IVTV_CAP_ENCODER,
+	.hw_video = IVTV_HW_SAA717X | IVTV_HW_GPIO,
+	.hw_audio = IVTV_HW_SAA717X,
+	.hw_audio_ctrl = IVTV_HW_SAA717X,
+	.hw_all = IVTV_HW_GPIO | IVTV_HW_SAA717X | IVTV_HW_TUNER,
+	.video_inputs = {
+		{ IVTV_CARD_INPUT_VID_TUNER,  0, IVTV_SAA71XX_COMPOSITE4 |
+						 IVTV_SAA717X_TUNER_FLAG },
+		{ IVTV_CARD_INPUT_SVIDEO1,    1, IVTV_SAA71XX_SVIDEO0    },
+		{ IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_COMPOSITE0 },
+	},
+	.audio_inputs = {
+		{ IVTV_CARD_INPUT_AUD_TUNER,  IVTV_SAA717X_IN2 },
+		{ IVTV_CARD_INPUT_LINE_IN1,   IVTV_SAA717X_IN0 },
+	},
+	.gpio_init = { .direction = 0xf880, .initial_value = 0x8800 },
+	.gpio_video_input  = { .mask = 0x0020, .tuner  = 0x0000,
+			       .composite = 0x0020, .svideo = 0x0020 },
+	.gpio_audio_freq   = { .mask = 0xc000, .f32000 = 0x0000,
+			     .f44100 = 0x4000, .f48000 = 0x8000 },
+	.tuners = {
+		{ .std = V4L2_STD_PAL_SECAM, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
+		{ .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_FM1236_MK3 },
+	},
+	.i2c = &ivtv_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* I/O Data GV-MVP/RX & GV-MVP/RX2W (dual tuner) cards */
+
+static const struct ivtv_card_pci_info ivtv_pci_gv_mvprx[] = {
+	{ PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_IODATA, 0xd01e },
+	{ PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_IODATA, 0xd038 }, /* 2W unit #1 */
+	{ PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_IODATA, 0xd039 }, /* 2W unit #2 */
+	{ 0, 0, 0 }
+};
+
+static const struct ivtv_card ivtv_card_gv_mvprx = {
+	.type = IVTV_CARD_GV_MVPRX,
+	.name = "I/O Data GV-MVP/RX, GV-MVP/RX2W (dual tuner)",
+	.v4l2_capabilities = IVTV_CAP_ENCODER,
+	.hw_video = IVTV_HW_SAA7115 | IVTV_HW_UPD64031A | IVTV_HW_UPD6408X,
+	.hw_audio = IVTV_HW_GPIO,
+	.hw_audio_ctrl = IVTV_HW_WM8739,
+	.hw_all = IVTV_HW_GPIO | IVTV_HW_SAA7115 | IVTV_HW_VP27SMPX |
+		  IVTV_HW_TUNER | IVTV_HW_WM8739 |
+		  IVTV_HW_UPD64031A | IVTV_HW_UPD6408X,
+	.video_inputs = {
+		{ IVTV_CARD_INPUT_VID_TUNER,  0, IVTV_SAA71XX_SVIDEO0    },
+		{ IVTV_CARD_INPUT_SVIDEO1,    1, IVTV_SAA71XX_SVIDEO1    },
+		{ IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_SVIDEO2    },
+	},
+	.audio_inputs = {
+		{ IVTV_CARD_INPUT_AUD_TUNER,  IVTV_GPIO_TUNER   },
+		{ IVTV_CARD_INPUT_LINE_IN1,   IVTV_GPIO_LINE_IN },
+	},
+	.gpio_init = { .direction = 0xc301, .initial_value = 0x0200 },
+	.gpio_audio_input  = { .mask = 0xffff, .tuner  = 0x0200, .linein = 0x0300 },
+	.tuners = {
+		/* This card has the Panasonic VP27 tuner */
+		{ .std = V4L2_STD_MN, .tuner = TUNER_PANASONIC_VP27 },
+	},
+	.pci_list = ivtv_pci_gv_mvprx,
+	.i2c = &ivtv_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* I/O Data GV-MVP/RX2E card */
+
+static const struct ivtv_card_pci_info ivtv_pci_gv_mvprx2e[] = {
+	{ PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_IODATA, 0xd025 },
+	{0, 0, 0}
+};
+
+static const struct ivtv_card ivtv_card_gv_mvprx2e = {
+	.type = IVTV_CARD_GV_MVPRX2E,
+	.name = "I/O Data GV-MVP/RX2E",
+	.v4l2_capabilities = IVTV_CAP_ENCODER,
+	.hw_video = IVTV_HW_SAA7115,
+	.hw_audio = IVTV_HW_GPIO,
+	.hw_audio_ctrl = IVTV_HW_WM8739,
+	.hw_all = IVTV_HW_GPIO | IVTV_HW_SAA7115 | IVTV_HW_TUNER |
+		  IVTV_HW_VP27SMPX | IVTV_HW_WM8739,
+	.video_inputs = {
+		{ IVTV_CARD_INPUT_VID_TUNER,  0, IVTV_SAA71XX_COMPOSITE4 },
+		{ IVTV_CARD_INPUT_SVIDEO1,    1, IVTV_SAA71XX_SVIDEO0    },
+		{ IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_COMPOSITE3 },
+	},
+	.audio_inputs = {
+		{ IVTV_CARD_INPUT_AUD_TUNER,  IVTV_GPIO_TUNER   },
+		{ IVTV_CARD_INPUT_LINE_IN1,   IVTV_GPIO_LINE_IN },
+	},
+	.gpio_init = { .direction = 0xc301, .initial_value = 0x0200 },
+	.gpio_audio_input  = { .mask = 0xffff, .tuner  = 0x0200, .linein = 0x0300 },
+	.tuners = {
+		/* This card has the Panasonic VP27 tuner */
+		{ .std = V4L2_STD_MN, .tuner = TUNER_PANASONIC_VP27 },
+	},
+	.pci_list = ivtv_pci_gv_mvprx2e,
+	.i2c = &ivtv_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* GotVIEW PCI DVD card */
+
+static const struct ivtv_card_pci_info ivtv_pci_gotview_pci_dvd[] = {
+	{ PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_YUAN1, 0x0600 },
+	{ 0, 0, 0 }
+};
+
+static const struct ivtv_card ivtv_card_gotview_pci_dvd = {
+	.type = IVTV_CARD_GOTVIEW_PCI_DVD,
+	.name = "GotView PCI DVD",
+	.v4l2_capabilities = IVTV_CAP_ENCODER,
+	.hw_video = IVTV_HW_SAA717X,
+	.hw_audio = IVTV_HW_SAA717X,
+	.hw_audio_ctrl = IVTV_HW_SAA717X,
+	.hw_all = IVTV_HW_SAA717X | IVTV_HW_TUNER,
+	.video_inputs = {
+		{ IVTV_CARD_INPUT_VID_TUNER,  0, IVTV_SAA71XX_COMPOSITE1 },  /* pin 116 */
+		{ IVTV_CARD_INPUT_SVIDEO1,    1, IVTV_SAA71XX_SVIDEO0 },     /* pin 114/109 */
+		{ IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_COMPOSITE3 },  /* pin 118 */
+	},
+	.audio_inputs = {
+		{ IVTV_CARD_INPUT_AUD_TUNER,  IVTV_SAA717X_IN0 },
+		{ IVTV_CARD_INPUT_LINE_IN1,   IVTV_SAA717X_IN2 },
+	},
+	.gpio_init = { .direction = 0xf000, .initial_value = 0xA000 },
+	.tuners = {
+		/* This card has a Philips FQ1216ME MK3 tuner */
+		{ .std = V4L2_STD_PAL_SECAM, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
+	},
+	.pci_list = ivtv_pci_gotview_pci_dvd,
+	.i2c = &ivtv_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* GotVIEW PCI DVD2 Deluxe card */
+
+static const struct ivtv_card_pci_info ivtv_pci_gotview_pci_dvd2[] = {
+	{ PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_GOTVIEW1, 0x0600 },
+	{ 0, 0, 0 }
+};
+
+static const struct ivtv_card ivtv_card_gotview_pci_dvd2 = {
+	.type = IVTV_CARD_GOTVIEW_PCI_DVD2,
+	.name = "GotView PCI DVD2 Deluxe",
+	.v4l2_capabilities = IVTV_CAP_ENCODER,
+	.hw_video = IVTV_HW_CX25840,
+	.hw_audio = IVTV_HW_CX25840,
+	.hw_audio_ctrl = IVTV_HW_CX25840,
+	.hw_muxer = IVTV_HW_GPIO,
+	.hw_all = IVTV_HW_CX25840 | IVTV_HW_TUNER,
+	.video_inputs = {
+		{ IVTV_CARD_INPUT_VID_TUNER,  0, CX25840_COMPOSITE2 },
+		{ IVTV_CARD_INPUT_SVIDEO1,    1,
+		  CX25840_SVIDEO_LUMA3 | CX25840_SVIDEO_CHROMA4 },
+		{ IVTV_CARD_INPUT_COMPOSITE1, 1, CX25840_COMPOSITE1 },
+	},
+	.audio_inputs = {
+		{ IVTV_CARD_INPUT_AUD_TUNER,  CX25840_AUDIO5,       0 },
+		{ IVTV_CARD_INPUT_LINE_IN1,   CX25840_AUDIO_SERIAL, 1 },
+	},
+	.radio_input = { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO_SERIAL, 2 },
+	.gpio_init = { .direction = 0x0800, .initial_value = 0 },
+	.gpio_audio_input  = { .mask = 0x0800, .tuner = 0, .linein = 0, .radio = 0x0800 },
+	.tuners = {
+		/* This card has a Philips FQ1216ME MK5 tuner */
+		{ .std = V4L2_STD_PAL_SECAM, .tuner = TUNER_PHILIPS_FM1216ME_MK3 },
+	},
+	.pci_list = ivtv_pci_gotview_pci_dvd2,
+	.i2c = &ivtv_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* Yuan MPC622 miniPCI card */
+
+static const struct ivtv_card_pci_info ivtv_pci_yuan_mpc622[] = {
+	{ PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_YUAN2, 0xd998 },
+	{ 0, 0, 0 }
+};
+
+static const struct ivtv_card ivtv_card_yuan_mpc622 = {
+	.type = IVTV_CARD_YUAN_MPC622,
+	.name = "Yuan MPC622",
+	.v4l2_capabilities = IVTV_CAP_ENCODER,
+	.hw_video = IVTV_HW_CX25840,
+	.hw_audio = IVTV_HW_CX25840,
+	.hw_audio_ctrl = IVTV_HW_CX25840,
+	.hw_all = IVTV_HW_CX25840 | IVTV_HW_TUNER,
+	.video_inputs = {
+		{ IVTV_CARD_INPUT_VID_TUNER,  0, CX25840_COMPOSITE2 },
+		{ IVTV_CARD_INPUT_SVIDEO1,    1,
+		  CX25840_SVIDEO_LUMA3 | CX25840_SVIDEO_CHROMA4 },
+		{ IVTV_CARD_INPUT_COMPOSITE1, 1, CX25840_COMPOSITE1 },
+	},
+	.audio_inputs = {
+		{ IVTV_CARD_INPUT_AUD_TUNER,  CX25840_AUDIO5       },
+		{ IVTV_CARD_INPUT_LINE_IN1,   CX25840_AUDIO_SERIAL },
+	},
+	.gpio_init = { .direction = 0x00ff, .initial_value = 0x0002 },
+	.tuners = {
+		/* This card has the TDA8290/TDA8275 tuner chips */
+		{ .std = V4L2_STD_ALL, .tuner = TUNER_PHILIPS_TDA8290 },
+	},
+	.pci_list = ivtv_pci_yuan_mpc622,
+	.i2c = &ivtv_i2c_tda8290,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* DIGITAL COWBOY DCT-MTVP1 card */
+
+static const struct ivtv_card_pci_info ivtv_pci_dctmvtvp1[] = {
+	{ PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_AVERMEDIA, 0xbfff },
+	{ 0, 0, 0 }
+};
+
+static const struct ivtv_card ivtv_card_dctmvtvp1 = {
+	.type = IVTV_CARD_DCTMTVP1,
+	.name = "Digital Cowboy DCT-MTVP1",
+	.v4l2_capabilities = IVTV_CAP_ENCODER,
+	.hw_video = IVTV_HW_SAA7115 | IVTV_HW_UPD64031A | IVTV_HW_UPD6408X |
+		IVTV_HW_GPIO,
+	.hw_audio = IVTV_HW_GPIO,
+	.hw_audio_ctrl = IVTV_HW_GPIO,
+	.hw_all = IVTV_HW_GPIO | IVTV_HW_SAA7115 | IVTV_HW_TUNER |
+		IVTV_HW_UPD64031A | IVTV_HW_UPD6408X,
+	.video_inputs = {
+		{ IVTV_CARD_INPUT_VID_TUNER,  0, IVTV_SAA71XX_SVIDEO0    },
+		{ IVTV_CARD_INPUT_SVIDEO1,    1, IVTV_SAA71XX_SVIDEO2    },
+		{ IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_SVIDEO2 },
+	},
+	.audio_inputs = {
+		{ IVTV_CARD_INPUT_AUD_TUNER,  IVTV_GPIO_TUNER   },
+		{ IVTV_CARD_INPUT_LINE_IN1,   IVTV_GPIO_LINE_IN },
+	},
+	.gpio_init = { .direction = 0xe080, .initial_value = 0x8000 },
+	.gpio_audio_input  = { .mask = 0x8080, .tuner  = 0x8000, .linein = 0x0080 },
+	.gpio_audio_mute   = { .mask = 0x6000, .mute   = 0x6000 },
+	.gpio_audio_mode   = { .mask = 0x4300, .mono   = 0x4000, .stereo = 0x0200,
+			      .lang1 = 0x0300, .lang2  = 0x0000, .both   = 0x0200 },
+	.gpio_video_input  = { .mask = 0x0030, .tuner  = 0x0000,
+			       .composite = 0x0010, .svideo = 0x0020},
+	.tuners = {
+		{ .std = V4L2_STD_MN, .tuner = TUNER_PHILIPS_FQ1286 },
+	},
+	.pci_list = ivtv_pci_dctmvtvp1,
+	.i2c = &ivtv_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* Yuan PG600-2/GotView PCI DVD Lite cards */
+
+static const struct ivtv_card_pci_info ivtv_pci_pg600v2[] = {
+	{ PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_YUAN3,     0x0600 },
+	{ PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_GOTVIEW2,  0x0600 },
+	{ 0, 0, 0 }
+};
+
+static const struct ivtv_card ivtv_card_pg600v2 = {
+	.type = IVTV_CARD_PG600V2,
+	.name = "Yuan PG600-2, GotView PCI DVD Lite",
+	.v4l2_capabilities = IVTV_CAP_ENCODER,
+	.hw_video = IVTV_HW_CX25840,
+	.hw_audio = IVTV_HW_CX25840,
+	.hw_audio_ctrl = IVTV_HW_CX25840,
+	.hw_all = IVTV_HW_CX25840 | IVTV_HW_TUNER,
+	/* XC2028 support apparently works for the Yuan, it's still
+	   uncertain whether it also works with the GotView. */
+	.video_inputs = {
+		{ IVTV_CARD_INPUT_VID_TUNER,  0, CX25840_COMPOSITE2 },
+		{ IVTV_CARD_INPUT_SVIDEO1,    1,
+		  CX25840_SVIDEO_LUMA3 | CX25840_SVIDEO_CHROMA4 },
+		{ IVTV_CARD_INPUT_COMPOSITE1, 1, CX25840_COMPOSITE1 },
+	},
+	.audio_inputs = {
+		{ IVTV_CARD_INPUT_AUD_TUNER,  CX25840_AUDIO5       },
+		{ IVTV_CARD_INPUT_LINE_IN1,   CX25840_AUDIO_SERIAL },
+	},
+	.radio_input = { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO5 },
+	.xceive_pin = 12,
+	.tuners = {
+		{ .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
+	},
+	.pci_list = ivtv_pci_pg600v2,
+	.i2c = &ivtv_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* Club3D ZAP-TV1x01 cards */
+
+static const struct ivtv_card_pci_info ivtv_pci_club3d[] = {
+	{ PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_YUAN3,     0x0600 },
+	{ 0, 0, 0 }
+};
+
+static const struct ivtv_card ivtv_card_club3d = {
+	.type = IVTV_CARD_CLUB3D,
+	.name = "Club3D ZAP-TV1x01",
+	.v4l2_capabilities = IVTV_CAP_ENCODER,
+	.hw_video = IVTV_HW_CX25840,
+	.hw_audio = IVTV_HW_CX25840,
+	.hw_audio_ctrl = IVTV_HW_CX25840,
+	.hw_all = IVTV_HW_CX25840 | IVTV_HW_TUNER,
+	.video_inputs = {
+		{ IVTV_CARD_INPUT_VID_TUNER,  0, CX25840_COMPOSITE2 },
+		{ IVTV_CARD_INPUT_SVIDEO1,    1,
+		  CX25840_SVIDEO_LUMA3 | CX25840_SVIDEO_CHROMA4 },
+		{ IVTV_CARD_INPUT_COMPOSITE1, 1, CX25840_COMPOSITE3 },
+	},
+	.audio_inputs = {
+		{ IVTV_CARD_INPUT_AUD_TUNER,  CX25840_AUDIO5       },
+		{ IVTV_CARD_INPUT_LINE_IN1,   CX25840_AUDIO_SERIAL },
+	},
+	.radio_input = { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO5 },
+	.xceive_pin = 12,
+	.tuners = {
+		{ .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
+	},
+	.pci_list = ivtv_pci_club3d,
+	.i2c = &ivtv_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* AVerTV MCE 116 Plus (M116) card */
+
+static const struct ivtv_card_pci_info ivtv_pci_avertv_mce116[] = {
+	{ PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_AVERMEDIA, 0xc439 },
+	{ 0, 0, 0 }
+};
+
+static const struct ivtv_card ivtv_card_avertv_mce116 = {
+	.type = IVTV_CARD_AVERTV_MCE116,
+	.name = "AVerTV MCE 116 Plus",
+	.v4l2_capabilities = IVTV_CAP_ENCODER,
+	.hw_video = IVTV_HW_CX25840,
+	.hw_audio = IVTV_HW_CX25840,
+	.hw_audio_ctrl = IVTV_HW_CX25840,
+	.hw_all = IVTV_HW_CX25840 | IVTV_HW_TUNER | IVTV_HW_WM8739 |
+		  IVTV_HW_I2C_IR_RX_AVER,
+	.video_inputs = {
+		{ IVTV_CARD_INPUT_VID_TUNER,  0, CX25840_COMPOSITE2 },
+		{ IVTV_CARD_INPUT_SVIDEO1,    1, CX25840_SVIDEO3    },
+		{ IVTV_CARD_INPUT_COMPOSITE1, 1, CX25840_COMPOSITE1 },
+	},
+	.audio_inputs = {
+		{ IVTV_CARD_INPUT_AUD_TUNER,  CX25840_AUDIO5       },
+		{ IVTV_CARD_INPUT_LINE_IN1,   CX25840_AUDIO_SERIAL, 1 },
+	},
+	.radio_input = { IVTV_CARD_INPUT_AUD_TUNER,  CX25840_AUDIO5 },
+	/* enable line-in */
+	.gpio_init = { .direction = 0xe000, .initial_value = 0x4000 },
+	.xceive_pin = 10,
+	.tuners = {
+		{ .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
+	},
+	.pci_list = ivtv_pci_avertv_mce116,
+	.i2c = &ivtv_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* AVerMedia PVR-150 Plus / AVerTV M113 cards with a Daewoo/Partsnic Tuner */
+
+static const struct ivtv_card_pci_info ivtv_pci_aver_pvr150[] = {
+	{ PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_AVERMEDIA, 0xc034 }, /* NTSC */
+	{ PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_AVERMEDIA, 0xc035 }, /* NTSC FM */
+	{ 0, 0, 0 }
+};
+
+static const struct ivtv_card ivtv_card_aver_pvr150 = {
+	.type = IVTV_CARD_AVER_PVR150PLUS,
+	.name = "AVerMedia PVR-150 Plus / AVerTV M113 Partsnic (Daewoo) Tuner",
+	.v4l2_capabilities = IVTV_CAP_ENCODER,
+	.hw_video = IVTV_HW_CX25840,
+	.hw_audio = IVTV_HW_CX25840,
+	.hw_audio_ctrl = IVTV_HW_CX25840,
+	.hw_muxer = IVTV_HW_GPIO,
+	.hw_all = IVTV_HW_CX25840 | IVTV_HW_TUNER |
+		  IVTV_HW_WM8739 | IVTV_HW_GPIO,
+	.video_inputs = {
+		{ IVTV_CARD_INPUT_VID_TUNER,  0, CX25840_COMPOSITE2 },
+		{ IVTV_CARD_INPUT_SVIDEO1,    1, CX25840_SVIDEO3    },
+		{ IVTV_CARD_INPUT_COMPOSITE1, 1, CX25840_COMPOSITE1 },
+	},
+	.audio_inputs = {
+		{ IVTV_CARD_INPUT_AUD_TUNER,  CX25840_AUDIO5,       0 },
+		{ IVTV_CARD_INPUT_LINE_IN1,   CX25840_AUDIO_SERIAL, 1 },
+	},
+	.radio_input = { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO_SERIAL, 2 },
+	/* The 74HC4052 Dual 4:1 multiplexer is controlled by 2 GPIO lines */
+	.gpio_init = { .direction = 0xc000, .initial_value = 0 },
+	.gpio_audio_input  = { .mask   = 0xc000,
+			       .tuner  = 0x0000,
+			       .linein = 0x4000,
+			       .radio  = 0x8000 },
+	.tuners = {
+		/* Subsystem ID's 0xc03[45] have a Partsnic PTI-5NF05 tuner */
+		{ .std = V4L2_STD_MN, .tuner = TUNER_PARTSNIC_PTI_5NF05 },
+	},
+	.pci_list = ivtv_pci_aver_pvr150,
+	/* Subsystem ID 0xc035 has a TEA5767(?) FM tuner, 0xc034 does not */
+	.i2c = &ivtv_i2c_radio,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* AVerMedia UltraTV 1500 MCE (newer non-cx88 version, M113 variant) card */
+
+static const struct ivtv_card_pci_info ivtv_pci_aver_ultra1500mce[] = {
+	{ PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_AVERMEDIA, 0xc019 }, /* NTSC */
+	{ PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_AVERMEDIA, 0xc01b }, /* PAL/SECAM */
+	{ 0, 0, 0 }
+};
+
+static const struct ivtv_card ivtv_card_aver_ultra1500mce = {
+	.type = IVTV_CARD_AVER_ULTRA1500MCE,
+	.name = "AVerMedia UltraTV 1500 MCE / AVerTV M113 Philips Tuner",
+	.comment = "For non-NTSC tuners, use the pal= or secam= module options",
+	.v4l2_capabilities = IVTV_CAP_ENCODER,
+	.hw_video = IVTV_HW_CX25840,
+	.hw_audio = IVTV_HW_CX25840,
+	.hw_audio_ctrl = IVTV_HW_CX25840,
+	.hw_muxer = IVTV_HW_GPIO,
+	.hw_all = IVTV_HW_CX25840 | IVTV_HW_TUNER |
+		  IVTV_HW_WM8739 | IVTV_HW_GPIO,
+	.video_inputs = {
+		{ IVTV_CARD_INPUT_VID_TUNER,  0, CX25840_COMPOSITE2 },
+		{ IVTV_CARD_INPUT_SVIDEO1,    1, CX25840_SVIDEO3    },
+		{ IVTV_CARD_INPUT_COMPOSITE1, 1, CX25840_COMPOSITE1 },
+	},
+	.audio_inputs = {
+		{ IVTV_CARD_INPUT_AUD_TUNER,  CX25840_AUDIO5,       0 },
+		{ IVTV_CARD_INPUT_LINE_IN1,   CX25840_AUDIO_SERIAL, 1 },
+	},
+	.radio_input = { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO_SERIAL, 2 },
+	/* The 74HC4052 Dual 4:1 multiplexer is controlled by 2 GPIO lines */
+	.gpio_init = { .direction = 0xc000, .initial_value = 0 },
+	.gpio_audio_input  = { .mask   = 0xc000,
+			       .tuner  = 0x0000,
+			       .linein = 0x4000,
+			       .radio  = 0x8000 },
+	.tuners = {
+		/* The UltraTV 1500 MCE has a Philips FM1236 MK5 TV/FM tuner */
+		{ .std = V4L2_STD_MN, .tuner = TUNER_PHILIPS_FM1236_MK3 },
+		{ .std = V4L2_STD_PAL_SECAM, .tuner = TUNER_PHILIPS_FM1216MK5 },
+	},
+	.pci_list = ivtv_pci_aver_ultra1500mce,
+	.i2c = &ivtv_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* AVerMedia EZMaker PCI Deluxe card */
+
+static const struct ivtv_card_pci_info ivtv_pci_aver_ezmaker[] = {
+	{ PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_AVERMEDIA, 0xc03f },
+	{ 0, 0, 0 }
+};
+
+static const struct ivtv_card ivtv_card_aver_ezmaker = {
+	.type = IVTV_CARD_AVER_EZMAKER,
+	.name = "AVerMedia EZMaker PCI Deluxe",
+	.v4l2_capabilities = IVTV_CAP_ENCODER,
+	.hw_video = IVTV_HW_CX25840,
+	.hw_audio = IVTV_HW_CX25840,
+	.hw_audio_ctrl = IVTV_HW_CX25840,
+	.hw_all = IVTV_HW_CX25840 | IVTV_HW_WM8739,
+	.video_inputs = {
+		{ IVTV_CARD_INPUT_SVIDEO1,    0, CX25840_SVIDEO3 },
+		{ IVTV_CARD_INPUT_COMPOSITE1, 0, CX25840_COMPOSITE1 },
+	},
+	.audio_inputs = {
+		{ IVTV_CARD_INPUT_LINE_IN1,   CX25840_AUDIO_SERIAL, 0 },
+	},
+	.gpio_init = { .direction = 0x4000, .initial_value = 0x4000 },
+	/* Does not have a tuner */
+	.pci_list = ivtv_pci_aver_ezmaker,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* ASUS Falcon2 */
+
+static const struct ivtv_card_pci_info ivtv_pci_asus_falcon2[] = {
+	{ PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_ASUSTEK, 0x4b66 },
+	{ PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_ASUSTEK, 0x462e },
+	{ PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_ASUSTEK, 0x4b2e },
+	{ 0, 0, 0 }
+};
+
+static const struct ivtv_card ivtv_card_asus_falcon2 = {
+	.type = IVTV_CARD_ASUS_FALCON2,
+	.name = "ASUS Falcon2",
+	.v4l2_capabilities = IVTV_CAP_ENCODER,
+	.hw_video = IVTV_HW_CX25840,
+	.hw_audio = IVTV_HW_CX25840,
+	.hw_audio_ctrl = IVTV_HW_CX25840,
+	.hw_muxer = IVTV_HW_M52790,
+	.hw_all = IVTV_HW_CX25840 | IVTV_HW_M52790 | IVTV_HW_TUNER,
+	.video_inputs = {
+		{ IVTV_CARD_INPUT_VID_TUNER,  0, CX25840_COMPOSITE2 },
+		{ IVTV_CARD_INPUT_SVIDEO1,    1, CX25840_SVIDEO3    },
+		{ IVTV_CARD_INPUT_COMPOSITE1, 2, CX25840_COMPOSITE2 },
+	},
+	.audio_inputs = {
+		{ IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO5, M52790_IN_TUNER },
+		{ IVTV_CARD_INPUT_LINE_IN1, CX25840_AUDIO_SERIAL,
+			M52790_IN_V2 | M52790_SW1_YCMIX | M52790_SW2_YCMIX },
+		{ IVTV_CARD_INPUT_LINE_IN1, CX25840_AUDIO_SERIAL, M52790_IN_V2 },
+	},
+	.radio_input = { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO_SERIAL, M52790_IN_TUNER },
+	.tuners = {
+		{ .std = V4L2_STD_MN, .tuner = TUNER_PHILIPS_FM1236_MK3 },
+	},
+	.pci_list = ivtv_pci_asus_falcon2,
+	.i2c = &ivtv_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* AVerMedia M104 miniPCI card */
+
+static const struct ivtv_card_pci_info ivtv_pci_aver_m104[] = {
+	{ PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_AVERMEDIA, 0xc136 },
+	{ 0, 0, 0 }
+};
+
+static const struct ivtv_card ivtv_card_aver_m104 = {
+	.type = IVTV_CARD_AVER_M104,
+	.name = "AVerMedia M104",
+	.comment = "Not yet supported!\n",
+	.v4l2_capabilities = 0, /*IVTV_CAP_ENCODER,*/
+	.hw_video = IVTV_HW_CX25840,
+	.hw_audio = IVTV_HW_CX25840,
+	.hw_audio_ctrl = IVTV_HW_CX25840,
+	.hw_all = IVTV_HW_CX25840 | IVTV_HW_TUNER | IVTV_HW_WM8739,
+	.video_inputs = {
+		{ IVTV_CARD_INPUT_SVIDEO1,    0, CX25840_SVIDEO3    },
+		{ IVTV_CARD_INPUT_COMPOSITE1, 0, CX25840_COMPOSITE1 },
+	},
+	.audio_inputs = {
+		{ IVTV_CARD_INPUT_LINE_IN1,   CX25840_AUDIO_SERIAL, 1 },
+	},
+	.radio_input = { IVTV_CARD_INPUT_AUD_TUNER, CX25840_AUDIO_SERIAL, 2 },
+	/* enable line-in + reset tuner */
+	.gpio_init = { .direction = 0xe000, .initial_value = 0x4000 },
+	.xceive_pin = 10,
+	.tuners = {
+		{ .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
+	},
+	.pci_list = ivtv_pci_aver_m104,
+	.i2c = &ivtv_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* Buffalo PC-MV5L/PCI cards */
+
+static const struct ivtv_card_pci_info ivtv_pci_buffalo[] = {
+	{ PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_MELCO, 0x052b },
+	{ 0, 0, 0 }
+};
+
+static const struct ivtv_card ivtv_card_buffalo = {
+	.type = IVTV_CARD_BUFFALO_MV5L,
+	.name = "Buffalo PC-MV5L/PCI",
+	.v4l2_capabilities = IVTV_CAP_ENCODER,
+	.hw_video = IVTV_HW_CX25840,
+	.hw_audio = IVTV_HW_CX25840,
+	.hw_audio_ctrl = IVTV_HW_CX25840,
+	.hw_all = IVTV_HW_CX25840 | IVTV_HW_TUNER,
+	.video_inputs = {
+		{ IVTV_CARD_INPUT_VID_TUNER,  0, CX25840_COMPOSITE2 },
+		{ IVTV_CARD_INPUT_SVIDEO1,    1,
+			CX25840_SVIDEO_LUMA3 | CX25840_SVIDEO_CHROMA4 },
+		{ IVTV_CARD_INPUT_COMPOSITE1, 1, CX25840_COMPOSITE1 },
+	},
+	.audio_inputs = {
+		{ IVTV_CARD_INPUT_AUD_TUNER,  CX25840_AUDIO5       },
+		{ IVTV_CARD_INPUT_LINE_IN1,   CX25840_AUDIO_SERIAL },
+	},
+	.xceive_pin = 12,
+	.tuners = {
+		{ .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 },
+	},
+	.pci_list = ivtv_pci_buffalo,
+	.i2c = &ivtv_i2c_std,
+};
+
+/* ------------------------------------------------------------------------- */
+/* Sony Kikyou */
+
+static const struct ivtv_card_pci_info ivtv_pci_kikyou[] = {
+	{ PCI_DEVICE_ID_IVTV16, IVTV_PCI_ID_SONY, 0x813d },
+	{ 0, 0, 0 }
+};
+
+static const struct ivtv_card ivtv_card_kikyou = {
+	.type = IVTV_CARD_KIKYOU,
+	.name = "Sony VAIO Giga Pocket (ENX Kikyou)",
+	.v4l2_capabilities = IVTV_CAP_ENCODER,
+	.hw_video = IVTV_HW_SAA7115,
+	.hw_audio = IVTV_HW_GPIO,
+	.hw_audio_ctrl = IVTV_HW_GPIO,
+	.hw_all = IVTV_HW_GPIO | IVTV_HW_SAA7115 | IVTV_HW_TUNER,
+	.video_inputs = {
+	{ IVTV_CARD_INPUT_VID_TUNER,  0, IVTV_SAA71XX_COMPOSITE1 },
+	{ IVTV_CARD_INPUT_COMPOSITE1, 1, IVTV_SAA71XX_COMPOSITE1 },
+	{ IVTV_CARD_INPUT_SVIDEO1,    1, IVTV_SAA71XX_SVIDEO1 },
+	},
+	.audio_inputs = {
+	     { IVTV_CARD_INPUT_AUD_TUNER,  IVTV_GPIO_TUNER },
+	     { IVTV_CARD_INPUT_LINE_IN1,   IVTV_GPIO_LINE_IN },
+	     { IVTV_CARD_INPUT_LINE_IN2,   IVTV_GPIO_LINE_IN },
+	},
+	.gpio_init = { .direction = 0x03e1, .initial_value = 0x0320 },
+	.gpio_audio_input = { .mask   = 0x0060,
+			      .tuner  = 0x0020,
+			      .linein = 0x0000,
+			      .radio  = 0x0060 },
+	.gpio_audio_mute  = { .mask = 0x0000,
+			      .mute = 0x0000 }, /* 0x200? Disable for now. */
+	.gpio_audio_mode  = { .mask   = 0x0080,
+			      .mono   = 0x0000,
+			      .stereo = 0x0000, /* SAP */
+			      .lang1  = 0x0080,
+			      .lang2  = 0x0000,
+			      .both   = 0x0080 },
+	.tuners = {
+	     { .std = V4L2_STD_ALL, .tuner = TUNER_SONY_BTF_PXN01Z },
+	},
+	.pci_list = ivtv_pci_kikyou,
+	.i2c = &ivtv_i2c_std,
+};
+
+
+static const struct ivtv_card *ivtv_card_list[] = {
+	&ivtv_card_pvr250,
+	&ivtv_card_pvr350,
+	&ivtv_card_pvr150,
+	&ivtv_card_m179,
+	&ivtv_card_mpg600,
+	&ivtv_card_mpg160,
+	&ivtv_card_pg600,
+	&ivtv_card_avc2410,
+	&ivtv_card_avc2010,
+	&ivtv_card_tg5000tv,
+	&ivtv_card_va2000,
+	&ivtv_card_cx23416gyc,
+	&ivtv_card_gv_mvprx,
+	&ivtv_card_gv_mvprx2e,
+	&ivtv_card_gotview_pci_dvd,
+	&ivtv_card_gotview_pci_dvd2,
+	&ivtv_card_yuan_mpc622,
+	&ivtv_card_dctmvtvp1,
+	&ivtv_card_pg600v2,
+	&ivtv_card_club3d,
+	&ivtv_card_avertv_mce116,
+	&ivtv_card_asus_falcon2,
+	&ivtv_card_aver_pvr150,
+	&ivtv_card_aver_ezmaker,
+	&ivtv_card_aver_m104,
+	&ivtv_card_buffalo,
+	&ivtv_card_aver_ultra1500mce,
+	&ivtv_card_kikyou,
+
+	/* Variations of standard cards but with the same PCI IDs.
+	   These cards must come last in this list. */
+	&ivtv_card_pvr350_v1,
+	&ivtv_card_cx23416gyc_nogr,
+	&ivtv_card_cx23416gyc_nogrycs,
+};
+
+const struct ivtv_card *ivtv_get_card(u16 index)
+{
+	if (index >= ARRAY_SIZE(ivtv_card_list))
+		return NULL;
+	return ivtv_card_list[index];
+}
+
+int ivtv_get_input(struct ivtv *itv, u16 index, struct v4l2_input *input)
+{
+	const struct ivtv_card_video_input *card_input = itv->card->video_inputs + index;
+	static const char * const input_strs[] = {
+		"Tuner 1",
+		"S-Video 1",
+		"S-Video 2",
+		"Composite 1",
+		"Composite 2",
+		"Composite 3"
+	};
+
+	if (index >= itv->nof_inputs)
+		return -EINVAL;
+	input->index = index;
+	strlcpy(input->name, input_strs[card_input->video_type - 1],
+			sizeof(input->name));
+	input->type = (card_input->video_type == IVTV_CARD_INPUT_VID_TUNER ?
+			V4L2_INPUT_TYPE_TUNER : V4L2_INPUT_TYPE_CAMERA);
+	input->audioset = (1 << itv->nof_audio_inputs) - 1;
+	input->std = (input->type == V4L2_INPUT_TYPE_TUNER) ?
+				itv->tuner_std : V4L2_STD_ALL;
+	return 0;
+}
+
+int ivtv_get_output(struct ivtv *itv, u16 index, struct v4l2_output *output)
+{
+	const struct ivtv_card_output *card_output = itv->card->video_outputs + index;
+
+	if (index >= itv->card->nof_outputs)
+		return -EINVAL;
+	output->index = index;
+	strlcpy(output->name, card_output->name, sizeof(output->name));
+	output->type = V4L2_OUTPUT_TYPE_ANALOG;
+	output->audioset = 1;
+	output->std = V4L2_STD_ALL;
+	return 0;
+}
+
+int ivtv_get_audio_input(struct ivtv *itv, u16 index, struct v4l2_audio *audio)
+{
+	const struct ivtv_card_audio_input *aud_input = itv->card->audio_inputs + index;
+	static const char * const input_strs[] = {
+		"Tuner 1",
+		"Line In 1",
+		"Line In 2"
+	};
+
+	memset(audio, 0, sizeof(*audio));
+	if (index >= itv->nof_audio_inputs)
+		return -EINVAL;
+	strlcpy(audio->name, input_strs[aud_input->audio_type - 1],
+			sizeof(audio->name));
+	audio->index = index;
+	audio->capability = V4L2_AUDCAP_STEREO;
+	return 0;
+}
+
+int ivtv_get_audio_output(struct ivtv *itv, u16 index, struct v4l2_audioout *aud_output)
+{
+	memset(aud_output, 0, sizeof(*aud_output));
+	if (itv->card->video_outputs == NULL || index != 0)
+		return -EINVAL;
+	strlcpy(aud_output->name, "A/V Audio Out", sizeof(aud_output->name));
+	return 0;
+}
diff --git a/drivers/media/pci/ivtv/ivtv-cards.h b/drivers/media/pci/ivtv/ivtv-cards.h
new file mode 100644
index 0000000..e6f5c02
--- /dev/null
+++ b/drivers/media/pci/ivtv/ivtv-cards.h
@@ -0,0 +1,309 @@
+/*
+    Functions to query card hardware
+    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
+    Copyright (C) 2005-2007  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef IVTV_CARDS_H
+#define IVTV_CARDS_H
+
+/* Supported cards */
+#define IVTV_CARD_PVR_250 	      0	/* WinTV PVR 250 */
+#define IVTV_CARD_PVR_350 	      1	/* encoder, decoder, tv-out */
+#define IVTV_CARD_PVR_150 	      2	/* WinTV PVR 150 and PVR 500 (really just two
+					   PVR150s on one PCI board) */
+#define IVTV_CARD_M179    	      3	/* AVerMedia M179 (encoder only) */
+#define IVTV_CARD_MPG600  	      4	/* Kuroutoshikou ITVC16-STVLP/YUAN MPG600, encoder only */
+#define IVTV_CARD_MPG160  	      5	/* Kuroutoshikou ITVC15-STVLP/YUAN MPG160
+					   cx23415 based, but does not have tv-out */
+#define IVTV_CARD_PG600 	      6	/* YUAN PG600/DIAMONDMM PVR-550 based on the CX Falcon 2 */
+#define IVTV_CARD_AVC2410 	      7	/* Adaptec AVC-2410 */
+#define IVTV_CARD_AVC2010 	      8	/* Adaptec AVD-2010 (No Tuner) */
+#define IVTV_CARD_TG5000TV   	      9 /* NAGASE TRANSGEAR 5000TV, encoder only */
+#define IVTV_CARD_VA2000MAX_SNT6     10 /* VA2000MAX-STN6 */
+#define IVTV_CARD_CX23416GYC 	     11 /* Kuroutoshikou CX23416GYC-STVLP (Yuan MPG600GR OEM) */
+#define IVTV_CARD_GV_MVPRX   	     12 /* I/O Data GV-MVP/RX, RX2, RX2W */
+#define IVTV_CARD_GV_MVPRX2E 	     13 /* I/O Data GV-MVP/RX2E */
+#define IVTV_CARD_GOTVIEW_PCI_DVD    14	/* GotView PCI DVD */
+#define IVTV_CARD_GOTVIEW_PCI_DVD2   15	/* GotView PCI DVD2 */
+#define IVTV_CARD_YUAN_MPC622        16	/* Yuan MPC622 miniPCI */
+#define IVTV_CARD_DCTMTVP1 	     17 /* DIGITAL COWBOY DCT-MTVP1 */
+#define IVTV_CARD_PG600V2	     18 /* Yuan PG600V2/GotView PCI DVD Lite */
+#define IVTV_CARD_CLUB3D	     19 /* Club3D ZAP-TV1x01 */
+#define IVTV_CARD_AVERTV_MCE116	     20 /* AVerTV MCE 116 Plus */
+#define IVTV_CARD_ASUS_FALCON2	     21 /* ASUS Falcon2 */
+#define IVTV_CARD_AVER_PVR150PLUS    22 /* AVerMedia PVR-150 Plus */
+#define IVTV_CARD_AVER_EZMAKER       23 /* AVerMedia EZMaker PCI Deluxe */
+#define IVTV_CARD_AVER_M104          24 /* AverMedia M104 miniPCI card */
+#define IVTV_CARD_BUFFALO_MV5L       25 /* Buffalo PC-MV5L/PCI card */
+#define IVTV_CARD_AVER_ULTRA1500MCE  26 /* AVerMedia UltraTV 1500 MCE */
+#define IVTV_CARD_KIKYOU             27 /* Sony VAIO Giga Pocket (ENX Kikyou) */
+#define IVTV_CARD_LAST 		     27
+
+/* Variants of existing cards but with the same PCI IDs. The driver
+   detects these based on other device information.
+   These cards must always come last.
+   New cards must be inserted above, and the indices of the cards below
+   must be adjusted accordingly. */
+
+/* PVR-350 V1 (uses saa7114) */
+#define IVTV_CARD_PVR_350_V1 	     (IVTV_CARD_LAST+1)
+/* 2 variants of Kuroutoshikou CX23416GYC-STVLP (Yuan MPG600GR OEM) */
+#define IVTV_CARD_CX23416GYC_NOGR    (IVTV_CARD_LAST+2)
+#define IVTV_CARD_CX23416GYC_NOGRYCS (IVTV_CARD_LAST+3)
+
+/* system vendor and device IDs */
+#define PCI_VENDOR_ID_ICOMP  0x4444
+#define PCI_DEVICE_ID_IVTV15 0x0803
+#define PCI_DEVICE_ID_IVTV16 0x0016
+
+/* subsystem vendor ID */
+#define IVTV_PCI_ID_HAUPPAUGE 		0x0070
+#define IVTV_PCI_ID_HAUPPAUGE_ALT1 	0x0270
+#define IVTV_PCI_ID_HAUPPAUGE_ALT2 	0x4070
+#define IVTV_PCI_ID_ADAPTEC 		0x9005
+#define IVTV_PCI_ID_ASUSTEK 		0x1043
+#define IVTV_PCI_ID_AVERMEDIA 		0x1461
+#define IVTV_PCI_ID_YUAN1		0x12ab
+#define IVTV_PCI_ID_YUAN2 		0xff01
+#define IVTV_PCI_ID_YUAN3 		0xffab
+#define IVTV_PCI_ID_YUAN4 		0xfbab
+#define IVTV_PCI_ID_DIAMONDMM 		0xff92
+#define IVTV_PCI_ID_IODATA 		0x10fc
+#define IVTV_PCI_ID_MELCO 		0x1154
+#define IVTV_PCI_ID_GOTVIEW1		0xffac
+#define IVTV_PCI_ID_GOTVIEW2 		0xffad
+#define IVTV_PCI_ID_SONY 		0x104d
+
+/* hardware flags, no gaps allowed */
+#define IVTV_HW_CX25840			(1 << 0)
+#define IVTV_HW_SAA7115			(1 << 1)
+#define IVTV_HW_SAA7127			(1 << 2)
+#define IVTV_HW_MSP34XX			(1 << 3)
+#define IVTV_HW_TUNER			(1 << 4)
+#define IVTV_HW_WM8775			(1 << 5)
+#define IVTV_HW_CS53L32A		(1 << 6)
+#define IVTV_HW_TVEEPROM		(1 << 7)
+#define IVTV_HW_SAA7114			(1 << 8)
+#define IVTV_HW_UPD64031A		(1 << 9)
+#define IVTV_HW_UPD6408X		(1 << 10)
+#define IVTV_HW_SAA717X			(1 << 11)
+#define IVTV_HW_WM8739			(1 << 12)
+#define IVTV_HW_VP27SMPX		(1 << 13)
+#define IVTV_HW_M52790			(1 << 14)
+#define IVTV_HW_GPIO			(1 << 15)
+#define IVTV_HW_I2C_IR_RX_AVER		(1 << 16)
+#define IVTV_HW_I2C_IR_RX_HAUP_EXT	(1 << 17) /* External before internal */
+#define IVTV_HW_I2C_IR_RX_HAUP_INT	(1 << 18)
+#define IVTV_HW_Z8F0811_IR_TX_HAUP	(1 << 19)
+#define IVTV_HW_Z8F0811_IR_RX_HAUP	(1 << 20)
+#define IVTV_HW_I2C_IR_RX_ADAPTEC	(1 << 21)
+
+#define IVTV_HW_Z8F0811_IR_HAUP	(IVTV_HW_Z8F0811_IR_RX_HAUP | \
+				 IVTV_HW_Z8F0811_IR_TX_HAUP)
+
+#define IVTV_HW_SAA711X   (IVTV_HW_SAA7115 | IVTV_HW_SAA7114)
+
+#define IVTV_HW_IR_RX_ANY (IVTV_HW_I2C_IR_RX_AVER | \
+			   IVTV_HW_I2C_IR_RX_HAUP_EXT | \
+			   IVTV_HW_I2C_IR_RX_HAUP_INT | \
+			   IVTV_HW_Z8F0811_IR_RX_HAUP | \
+			   IVTV_HW_I2C_IR_RX_ADAPTEC)
+
+#define IVTV_HW_IR_TX_ANY (IVTV_HW_Z8F0811_IR_TX_HAUP)
+
+#define IVTV_HW_IR_ANY	  (IVTV_HW_IR_RX_ANY | IVTV_HW_IR_TX_ANY)
+
+/* video inputs */
+#define	IVTV_CARD_INPUT_VID_TUNER	1
+#define	IVTV_CARD_INPUT_SVIDEO1 	2
+#define	IVTV_CARD_INPUT_SVIDEO2 	3
+#define	IVTV_CARD_INPUT_COMPOSITE1 	4
+#define	IVTV_CARD_INPUT_COMPOSITE2 	5
+#define	IVTV_CARD_INPUT_COMPOSITE3 	6
+
+/* audio inputs */
+#define	IVTV_CARD_INPUT_AUD_TUNER	1
+#define	IVTV_CARD_INPUT_LINE_IN1 	2
+#define	IVTV_CARD_INPUT_LINE_IN2 	3
+
+#define IVTV_CARD_MAX_VIDEO_INPUTS 6
+#define IVTV_CARD_MAX_AUDIO_INPUTS 3
+#define IVTV_CARD_MAX_TUNERS  	   3
+
+/* SAA71XX HW inputs */
+#define IVTV_SAA71XX_COMPOSITE0 0
+#define IVTV_SAA71XX_COMPOSITE1 1
+#define IVTV_SAA71XX_COMPOSITE2 2
+#define IVTV_SAA71XX_COMPOSITE3 3
+#define IVTV_SAA71XX_COMPOSITE4 4
+#define IVTV_SAA71XX_COMPOSITE5 5
+#define IVTV_SAA71XX_SVIDEO0    6
+#define IVTV_SAA71XX_SVIDEO1    7
+#define IVTV_SAA71XX_SVIDEO2    8
+#define IVTV_SAA71XX_SVIDEO3    9
+
+/* SAA717X needs to mark the tuner input by ORing with this flag */
+#define IVTV_SAA717X_TUNER_FLAG 0x80
+
+/* Dummy HW input */
+#define IVTV_DUMMY_AUDIO        0
+
+/* GPIO HW inputs */
+#define IVTV_GPIO_TUNER   0
+#define IVTV_GPIO_LINE_IN 1
+
+/* SAA717X HW inputs */
+#define IVTV_SAA717X_IN0 0
+#define IVTV_SAA717X_IN1 1
+#define IVTV_SAA717X_IN2 2
+
+/* V4L2 capability aliases */
+#define IVTV_CAP_ENCODER (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER | \
+			  V4L2_CAP_AUDIO | V4L2_CAP_READWRITE | V4L2_CAP_VBI_CAPTURE | \
+			  V4L2_CAP_SLICED_VBI_CAPTURE)
+#define IVTV_CAP_DECODER (V4L2_CAP_VIDEO_OUTPUT | \
+			  V4L2_CAP_SLICED_VBI_OUTPUT | V4L2_CAP_VIDEO_OUTPUT_OVERLAY)
+
+struct ivtv_card_video_input {
+	u8  video_type; 	/* video input type */
+	u8  audio_index;	/* index in ivtv_card_audio_input array */
+	u16 video_input;	/* hardware video input */
+};
+
+struct ivtv_card_audio_input {
+	u8  audio_type;		/* audio input type */
+	u32 audio_input;	/* hardware audio input */
+	u16 muxer_input;	/* hardware muxer input for boards with a
+				   multiplexer chip */
+};
+
+struct ivtv_card_output {
+	u8  name[32];
+	u16 video_output;  /* hardware video output */
+};
+
+struct ivtv_card_pci_info {
+	u16 device;
+	u16 subsystem_vendor;
+	u16 subsystem_device;
+};
+
+/* GPIO definitions */
+
+/* The mask is the set of bits used by the operation */
+
+struct ivtv_gpio_init { 	/* set initial GPIO DIR and OUT values */
+	u16 direction; 		/* DIR setting. Leave to 0 if no init is needed */
+	u16 initial_value;
+};
+
+struct ivtv_gpio_video_input { 	/* select tuner/line in input */
+	u16 mask; 		/* leave to 0 if not supported */
+	u16 tuner;
+	u16 composite;
+	u16 svideo;
+};
+
+struct ivtv_gpio_audio_input { 	/* select tuner/line in input */
+	u16 mask; 		/* leave to 0 if not supported */
+	u16 tuner;
+	u16 linein;
+	u16 radio;
+};
+
+struct ivtv_gpio_audio_mute {
+	u16 mask; 		/* leave to 0 if not supported */
+	u16 mute;		/* set this value to mute, 0 to unmute */
+};
+
+struct ivtv_gpio_audio_mode {
+	u16 mask; 		/* leave to 0 if not supported */
+	u16 mono; 		/* set audio to mono */
+	u16 stereo; 		/* set audio to stereo */
+	u16 lang1;		/* set audio to the first language */
+	u16 lang2;		/* set audio to the second language */
+	u16 both; 		/* both languages are output */
+};
+
+struct ivtv_gpio_audio_freq {
+	u16 mask; 		/* leave to 0 if not supported */
+	u16 f32000;
+	u16 f44100;
+	u16 f48000;
+};
+
+struct ivtv_gpio_audio_detect {
+	u16 mask; 		/* leave to 0 if not supported */
+	u16 stereo; 		/* if the input matches this value then
+				   stereo is detected */
+};
+
+struct ivtv_card_tuner {
+	v4l2_std_id std; 	/* standard for which the tuner is suitable */
+	int 	    tuner; 	/* tuner ID (from tuner.h) */
+};
+
+struct ivtv_card_tuner_i2c {
+	unsigned short radio[2];/* radio tuner i2c address to probe */
+	unsigned short demod[2];/* demodulator i2c address to probe */
+	unsigned short tv[4];	/* tv tuner i2c addresses to probe */
+};
+
+/* for card information/parameters */
+struct ivtv_card {
+	int type;
+	char *name;
+	char *comment;
+	u32 v4l2_capabilities;
+	u32 hw_video;		/* hardware used to process video */
+	u32 hw_audio;		/* hardware used to process audio */
+	u32 hw_audio_ctrl;	/* hardware used for the V4L2 controls (only 1 dev allowed) */
+	u32 hw_muxer;		/* hardware used to multiplex audio input */
+	u32 hw_all;		/* all hardware used by the board */
+	struct ivtv_card_video_input video_inputs[IVTV_CARD_MAX_VIDEO_INPUTS];
+	struct ivtv_card_audio_input audio_inputs[IVTV_CARD_MAX_AUDIO_INPUTS];
+	struct ivtv_card_audio_input radio_input;
+	int nof_outputs;
+	const struct ivtv_card_output *video_outputs;
+	u8 gr_config; 		/* config byte for the ghost reduction device */
+	u8 xceive_pin; 		/* XCeive tuner GPIO reset pin */
+
+	/* GPIO card-specific settings */
+	struct ivtv_gpio_init 		gpio_init;
+	struct ivtv_gpio_video_input	gpio_video_input;
+	struct ivtv_gpio_audio_input 	gpio_audio_input;
+	struct ivtv_gpio_audio_mute 	gpio_audio_mute;
+	struct ivtv_gpio_audio_mode 	gpio_audio_mode;
+	struct ivtv_gpio_audio_freq 	gpio_audio_freq;
+	struct ivtv_gpio_audio_detect 	gpio_audio_detect;
+
+	struct ivtv_card_tuner tuners[IVTV_CARD_MAX_TUNERS];
+	struct ivtv_card_tuner_i2c *i2c;
+
+	/* list of device and subsystem vendor/devices that
+	   correspond to this card type. */
+	const struct ivtv_card_pci_info *pci_list;
+};
+
+int ivtv_get_input(struct ivtv *itv, u16 index, struct v4l2_input *input);
+int ivtv_get_output(struct ivtv *itv, u16 index, struct v4l2_output *output);
+int ivtv_get_audio_input(struct ivtv *itv, u16 index, struct v4l2_audio *input);
+int ivtv_get_audio_output(struct ivtv *itv, u16 index, struct v4l2_audioout *output);
+const struct ivtv_card *ivtv_get_card(u16 index);
+
+#endif
diff --git a/drivers/media/pci/ivtv/ivtv-controls.c b/drivers/media/pci/ivtv/ivtv-controls.c
new file mode 100644
index 0000000..c604246
--- /dev/null
+++ b/drivers/media/pci/ivtv/ivtv-controls.c
@@ -0,0 +1,163 @@
+/*
+    ioctl control functions
+    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
+    Copyright (C) 2005-2007  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "ivtv-driver.h"
+#include "ivtv-ioctl.h"
+#include "ivtv-controls.h"
+#include "ivtv-mailbox.h"
+
+static int ivtv_s_stream_vbi_fmt(struct cx2341x_handler *cxhdl, u32 fmt)
+{
+	struct ivtv *itv = container_of(cxhdl, struct ivtv, cxhdl);
+
+	/* First try to allocate sliced VBI buffers if needed. */
+	if (fmt && itv->vbi.sliced_mpeg_data[0] == NULL) {
+		int i;
+
+		for (i = 0; i < IVTV_VBI_FRAMES; i++) {
+			/* Yuck, hardcoded. Needs to be a define */
+			itv->vbi.sliced_mpeg_data[i] = kmalloc(2049, GFP_KERNEL);
+			if (itv->vbi.sliced_mpeg_data[i] == NULL) {
+				while (--i >= 0) {
+					kfree(itv->vbi.sliced_mpeg_data[i]);
+					itv->vbi.sliced_mpeg_data[i] = NULL;
+				}
+				return -ENOMEM;
+			}
+		}
+	}
+
+	itv->vbi.insert_mpeg = fmt;
+
+	if (itv->vbi.insert_mpeg == 0) {
+		return 0;
+	}
+	/* Need sliced data for mpeg insertion */
+	if (ivtv_get_service_set(itv->vbi.sliced_in) == 0) {
+		if (itv->is_60hz)
+			itv->vbi.sliced_in->service_set = V4L2_SLICED_CAPTION_525;
+		else
+			itv->vbi.sliced_in->service_set = V4L2_SLICED_WSS_625;
+		ivtv_expand_service_set(itv->vbi.sliced_in, itv->is_50hz);
+	}
+	return 0;
+}
+
+static int ivtv_s_video_encoding(struct cx2341x_handler *cxhdl, u32 val)
+{
+	struct ivtv *itv = container_of(cxhdl, struct ivtv, cxhdl);
+	int is_mpeg1 = val == V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
+	struct v4l2_mbus_framefmt fmt;
+
+	/* fix videodecoder resolution */
+	fmt.width = cxhdl->width / (is_mpeg1 ? 2 : 1);
+	fmt.height = cxhdl->height;
+	fmt.code = V4L2_MBUS_FMT_FIXED;
+	v4l2_subdev_call(itv->sd_video, video, s_mbus_fmt, &fmt);
+	return 0;
+}
+
+static int ivtv_s_audio_sampling_freq(struct cx2341x_handler *cxhdl, u32 idx)
+{
+	static const u32 freqs[3] = { 44100, 48000, 32000 };
+	struct ivtv *itv = container_of(cxhdl, struct ivtv, cxhdl);
+
+	/* The audio clock of the digitizer must match the codec sample
+	   rate otherwise you get some very strange effects. */
+	if (idx < ARRAY_SIZE(freqs))
+		ivtv_call_all(itv, audio, s_clock_freq, freqs[idx]);
+	return 0;
+}
+
+static int ivtv_s_audio_mode(struct cx2341x_handler *cxhdl, u32 val)
+{
+	struct ivtv *itv = container_of(cxhdl, struct ivtv, cxhdl);
+
+	itv->dualwatch_stereo_mode = val;
+	return 0;
+}
+
+struct cx2341x_handler_ops ivtv_cxhdl_ops = {
+	.s_audio_mode = ivtv_s_audio_mode,
+	.s_audio_sampling_freq = ivtv_s_audio_sampling_freq,
+	.s_video_encoding = ivtv_s_video_encoding,
+	.s_stream_vbi_fmt = ivtv_s_stream_vbi_fmt,
+};
+
+int ivtv_g_pts_frame(struct ivtv *itv, s64 *pts, s64 *frame)
+{
+	u32 data[CX2341X_MBOX_MAX_DATA];
+
+	if (test_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags)) {
+		*pts = (s64)((u64)itv->last_dec_timing[2] << 32) |
+			(u64)itv->last_dec_timing[1];
+		*frame = itv->last_dec_timing[0];
+		return 0;
+	}
+	*pts = 0;
+	*frame = 0;
+	if (atomic_read(&itv->decoding)) {
+		if (ivtv_api(itv, CX2341X_DEC_GET_TIMING_INFO, 5, data)) {
+			IVTV_DEBUG_WARN("GET_TIMING: couldn't read clock\n");
+			return -EIO;
+		}
+		memcpy(itv->last_dec_timing, data, sizeof(itv->last_dec_timing));
+		set_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags);
+		*pts = (s64)((u64) data[2] << 32) | (u64) data[1];
+		*frame = data[0];
+		/*timing->scr = (u64) (((u64) data[4] << 32) | (u64) (data[3]));*/
+	}
+	return 0;
+}
+
+static int ivtv_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct ivtv *itv = container_of(ctrl->handler, struct ivtv, cxhdl.hdl);
+
+	switch (ctrl->id) {
+	/* V4L2_CID_MPEG_VIDEO_DEC_PTS and V4L2_CID_MPEG_VIDEO_DEC_FRAME
+	   control cluster */
+	case V4L2_CID_MPEG_VIDEO_DEC_PTS:
+		return ivtv_g_pts_frame(itv, &itv->ctrl_pts->val64,
+					     &itv->ctrl_frame->val64);
+	}
+	return 0;
+}
+
+static int ivtv_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct ivtv *itv = container_of(ctrl->handler, struct ivtv, cxhdl.hdl);
+
+	switch (ctrl->id) {
+	/* V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK and MULTILINGUAL_PLAYBACK
+	   control cluster */
+	case V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK:
+		itv->audio_stereo_mode = itv->ctrl_audio_playback->val - 1;
+		itv->audio_bilingual_mode = itv->ctrl_audio_multilingual_playback->val - 1;
+		ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode);
+		break;
+	}
+	return 0;
+}
+
+const struct v4l2_ctrl_ops ivtv_hdl_out_ops = {
+	.s_ctrl = ivtv_s_ctrl,
+	.g_volatile_ctrl = ivtv_g_volatile_ctrl,
+};
diff --git a/drivers/media/pci/ivtv/ivtv-controls.h b/drivers/media/pci/ivtv/ivtv-controls.h
new file mode 100644
index 0000000..3999e63
--- /dev/null
+++ b/drivers/media/pci/ivtv/ivtv-controls.h
@@ -0,0 +1,28 @@
+/*
+    ioctl control functions
+    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
+    Copyright (C) 2005-2007  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef IVTV_CONTROLS_H
+#define IVTV_CONTROLS_H
+
+extern struct cx2341x_handler_ops ivtv_cxhdl_ops;
+extern const struct v4l2_ctrl_ops ivtv_hdl_out_ops;
+int ivtv_g_pts_frame(struct ivtv *itv, s64 *pts, s64 *frame);
+
+#endif
diff --git a/drivers/media/pci/ivtv/ivtv-driver.c b/drivers/media/pci/ivtv/ivtv-driver.c
new file mode 100644
index 0000000..eed95a3
--- /dev/null
+++ b/drivers/media/pci/ivtv/ivtv-driver.c
@@ -0,0 +1,1535 @@
+/*
+    ivtv driver initialization and card probing
+    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
+    Copyright (C) 2004  Chris Kennedy <c@groovy.org>
+    Copyright (C) 2005-2007  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/* Main Driver file for the ivtv project:
+ * Driver for the Conexant CX23415/CX23416 chip.
+ * Author: Kevin Thayer (nufan_wfk at yahoo.com)
+ * License: GPL
+ * http://www.ivtvdriver.org
+ *
+ * -----
+ * MPG600/MPG160 support by  T.Adachi <tadachi@tadachi-net.com>
+ *                      and Takeru KOMORIYA<komoriya@paken.org>
+ *
+ * AVerMedia M179 GPIO info by Chris Pinkham <cpinkham@bc2va.org>
+ *                using information provided by Jiun-Kuei Jung @ AVerMedia.
+ *
+ * Kurouto Sikou CX23416GYC-STVLP tested by K.Ohta <alpha292@bremen.or.jp>
+ *                using information from T.Adachi,Takeru KOMORIYA and others :-)
+ *
+ * Nagase TRANSGEAR 5000TV, Aopen VA2000MAX-STN6 and I/O data GV-MVP/RX
+ *                version by T.Adachi. Special thanks  Mr.Suzuki
+ */
+
+#include "ivtv-driver.h"
+#include "ivtv-version.h"
+#include "ivtv-fileops.h"
+#include "ivtv-i2c.h"
+#include "ivtv-firmware.h"
+#include "ivtv-queue.h"
+#include "ivtv-udma.h"
+#include "ivtv-irq.h"
+#include "ivtv-mailbox.h"
+#include "ivtv-streams.h"
+#include "ivtv-ioctl.h"
+#include "ivtv-cards.h"
+#include "ivtv-vbi.h"
+#include "ivtv-routing.h"
+#include "ivtv-controls.h"
+#include "ivtv-gpio.h"
+#include <linux/dma-mapping.h>
+#include <media/tveeprom.h>
+#include <media/saa7115.h>
+#include <media/v4l2-chip-ident.h>
+#include "tuner-xc2028.h"
+
+/* 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 PVR-350 with. Normally this would give a
+   video1 device together with a radio0 device for the PVR. By
+   setting this to 1 you ensure that radio0 is now also radio1. */
+int ivtv_first_minor;
+
+/* Callback for registering extensions */
+int (*ivtv_ext_init)(struct ivtv *);
+EXPORT_SYMBOL(ivtv_ext_init);
+
+/* add your revision and whatnot here */
+static struct pci_device_id ivtv_pci_tbl[] __devinitdata = {
+	{PCI_VENDOR_ID_ICOMP, PCI_DEVICE_ID_IVTV15,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_ICOMP, PCI_DEVICE_ID_IVTV16,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{0,}
+};
+
+MODULE_DEVICE_TABLE(pci,ivtv_pci_tbl);
+
+/* ivtv instance counter */
+static atomic_t ivtv_instance = ATOMIC_INIT(0);
+
+/* Parameter declarations */
+static int cardtype[IVTV_MAX_CARDS];
+static int tuner[IVTV_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1,
+				     -1, -1, -1, -1, -1, -1, -1, -1,
+				     -1, -1, -1, -1, -1, -1, -1, -1,
+				     -1, -1, -1, -1, -1, -1, -1, -1 };
+static int radio[IVTV_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1,
+				     -1, -1, -1, -1, -1, -1, -1, -1,
+				     -1, -1, -1, -1, -1, -1, -1, -1,
+				     -1, -1, -1, -1, -1, -1, -1, -1 };
+static int i2c_clock_period[IVTV_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1,
+					       -1, -1, -1, -1, -1, -1, -1, -1,
+					       -1, -1, -1, -1, -1, -1, -1, -1,
+					       -1, -1, -1, -1, -1, -1, -1, -1 };
+
+static unsigned int cardtype_c = 1;
+static unsigned int tuner_c = 1;
+static int radio_c = 1;
+static unsigned int i2c_clock_period_c = 1;
+static char pal[] = "---";
+static char secam[] = "--";
+static char ntsc[] = "-";
+
+/* Buffers */
+
+/* DMA Buffers, Default size in MB allocated */
+#define IVTV_DEFAULT_ENC_MPG_BUFFERS 4
+#define IVTV_DEFAULT_ENC_YUV_BUFFERS 2
+#define IVTV_DEFAULT_ENC_VBI_BUFFERS 1
+/* Exception: size in kB for this stream (MB is overkill) */
+#define IVTV_DEFAULT_ENC_PCM_BUFFERS 320
+#define IVTV_DEFAULT_DEC_MPG_BUFFERS 1
+#define IVTV_DEFAULT_DEC_YUV_BUFFERS 1
+/* Exception: size in kB for this stream (MB is way overkill) */
+#define IVTV_DEFAULT_DEC_VBI_BUFFERS 64
+
+static int enc_mpg_buffers = IVTV_DEFAULT_ENC_MPG_BUFFERS;
+static int enc_yuv_buffers = IVTV_DEFAULT_ENC_YUV_BUFFERS;
+static int enc_vbi_buffers = IVTV_DEFAULT_ENC_VBI_BUFFERS;
+static int enc_pcm_buffers = IVTV_DEFAULT_ENC_PCM_BUFFERS;
+static int dec_mpg_buffers = IVTV_DEFAULT_DEC_MPG_BUFFERS;
+static int dec_yuv_buffers = IVTV_DEFAULT_DEC_YUV_BUFFERS;
+static int dec_vbi_buffers = IVTV_DEFAULT_DEC_VBI_BUFFERS;
+
+static int ivtv_yuv_mode;
+static int ivtv_yuv_threshold = -1;
+static int ivtv_pci_latency = 1;
+
+int ivtv_debug;
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+int ivtv_fw_debug;
+#endif
+
+static int tunertype = -1;
+static int newi2c = -1;
+
+module_param_array(tuner, int, &tuner_c, 0644);
+module_param_array(radio, int, &radio_c, 0644);
+module_param_array(cardtype, int, &cardtype_c, 0644);
+module_param_string(pal, pal, sizeof(pal), 0644);
+module_param_string(secam, secam, sizeof(secam), 0644);
+module_param_string(ntsc, ntsc, sizeof(ntsc), 0644);
+module_param_named(debug,ivtv_debug, int, 0644);
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+module_param_named(fw_debug, ivtv_fw_debug, int, 0644);
+#endif
+module_param(ivtv_pci_latency, int, 0644);
+module_param(ivtv_yuv_mode, int, 0644);
+module_param(ivtv_yuv_threshold, int, 0644);
+module_param(ivtv_first_minor, int, 0644);
+
+module_param(enc_mpg_buffers, int, 0644);
+module_param(enc_yuv_buffers, int, 0644);
+module_param(enc_vbi_buffers, int, 0644);
+module_param(enc_pcm_buffers, int, 0644);
+module_param(dec_mpg_buffers, int, 0644);
+module_param(dec_yuv_buffers, int, 0644);
+module_param(dec_vbi_buffers, int, 0644);
+
+module_param(tunertype, int, 0644);
+module_param(newi2c, int, 0644);
+module_param_array(i2c_clock_period, int, &i2c_clock_period_c, 0644);
+
+MODULE_PARM_DESC(tuner, "Tuner type selection,\n"
+			"\t\t\tsee tuner.h for values");
+MODULE_PARM_DESC(radio,
+		 "Enable or disable the radio. Use only if autodetection\n"
+		 "\t\t\tfails. 0 = disable, 1 = enable");
+MODULE_PARM_DESC(cardtype,
+		 "Only use this option if your card is not detected properly.\n"
+		 "\t\tSpecify card type:\n"
+		 "\t\t\t 1 = WinTV PVR 250\n"
+		 "\t\t\t 2 = WinTV PVR 350\n"
+		 "\t\t\t 3 = WinTV PVR-150 or PVR-500\n"
+		 "\t\t\t 4 = AVerMedia M179\n"
+		 "\t\t\t 5 = YUAN MPG600/Kuroutoshikou iTVC16-STVLP\n"
+		 "\t\t\t 6 = YUAN MPG160/Kuroutoshikou iTVC15-STVLP\n"
+		 "\t\t\t 7 = YUAN PG600/DIAMONDMM PVR-550 (CX Falcon 2)\n"
+		 "\t\t\t 8 = Adaptec AVC-2410\n"
+		 "\t\t\t 9 = Adaptec AVC-2010\n"
+		 "\t\t\t10 = NAGASE TRANSGEAR 5000TV\n"
+		 "\t\t\t11 = AOpen VA2000MAX-STN6\n"
+		 "\t\t\t12 = YUAN MPG600GR/Kuroutoshikou CX23416GYC-STVLP\n"
+		 "\t\t\t13 = I/O Data GV-MVP/RX\n"
+		 "\t\t\t14 = I/O Data GV-MVP/RX2E\n"
+		 "\t\t\t15 = GOTVIEW PCI DVD\n"
+		 "\t\t\t16 = GOTVIEW PCI DVD2 Deluxe\n"
+		 "\t\t\t17 = Yuan MPC622\n"
+		 "\t\t\t18 = Digital Cowboy DCT-MTVP1\n"
+		 "\t\t\t19 = Yuan PG600V2/GotView PCI DVD Lite\n"
+		 "\t\t\t20 = Club3D ZAP-TV1x01\n"
+		 "\t\t\t21 = AverTV MCE 116 Plus\n"
+		 "\t\t\t22 = ASUS Falcon2\n"
+		 "\t\t\t23 = AverMedia PVR-150 Plus\n"
+		 "\t\t\t24 = AverMedia EZMaker PCI Deluxe\n"
+		 "\t\t\t25 = AverMedia M104 (not yet working)\n"
+		 "\t\t\t26 = Buffalo PC-MV5L/PCI\n"
+		 "\t\t\t27 = AVerMedia UltraTV 1500 MCE\n"
+		 "\t\t\t28 = Sony VAIO Giga Pocket (ENX Kikyou)\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: BGH, DK, I, M, N, Nc, 60");
+MODULE_PARM_DESC(secam, "Set SECAM standard: BGH, DK, L, LC");
+MODULE_PARM_DESC(ntsc, "Set NTSC standard: M, J (Japan), K (South Korea)");
+MODULE_PARM_DESC(tunertype,
+		"Specify tuner type:\n"
+		"\t\t\t 0 = tuner for PAL-B/G/H/D/K/I, SECAM-B/G/H/D/K/L/Lc\n"
+		"\t\t\t 1 = tuner for NTSC-M/J/K, PAL-M/N/Nc\n"
+		"\t\t\t-1 = Autodetect (default)\n");
+MODULE_PARM_DESC(debug,
+		 "Debug level (bitmask). Default: 0\n"
+		 "\t\t\t   1/0x0001: warning\n"
+		 "\t\t\t   2/0x0002: info\n"
+		 "\t\t\t   4/0x0004: mailbox\n"
+		 "\t\t\t   8/0x0008: ioctl\n"
+		 "\t\t\t  16/0x0010: file\n"
+		 "\t\t\t  32/0x0020: dma\n"
+		 "\t\t\t  64/0x0040: irq\n"
+		 "\t\t\t 128/0x0080: decoder\n"
+		 "\t\t\t 256/0x0100: yuv\n"
+		 "\t\t\t 512/0x0200: i2c\n"
+		 "\t\t\t1024/0x0400: high volume\n");
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+MODULE_PARM_DESC(fw_debug,
+		 "Enable code for debugging firmware problems.  Default: 0\n");
+#endif
+MODULE_PARM_DESC(ivtv_pci_latency,
+		 "Change the PCI latency to 64 if lower: 0 = No, 1 = Yes,\n"
+		 "\t\t\tDefault: Yes");
+MODULE_PARM_DESC(ivtv_yuv_mode,
+		 "Specify the yuv playback mode:\n"
+		 "\t\t\t0 = interlaced\n\t\t\t1 = progressive\n\t\t\t2 = auto\n"
+		 "\t\t\tDefault: 0 (interlaced)");
+MODULE_PARM_DESC(ivtv_yuv_threshold,
+		 "If ivtv_yuv_mode is 2 (auto) then playback content as\n\t\tprogressive if src height <= ivtv_yuvthreshold\n"
+		 "\t\t\tDefault: 480");
+MODULE_PARM_DESC(enc_mpg_buffers,
+		 "Encoder MPG Buffers (in MB)\n"
+		 "\t\t\tDefault: " __stringify(IVTV_DEFAULT_ENC_MPG_BUFFERS));
+MODULE_PARM_DESC(enc_yuv_buffers,
+		 "Encoder YUV Buffers (in MB)\n"
+		 "\t\t\tDefault: " __stringify(IVTV_DEFAULT_ENC_YUV_BUFFERS));
+MODULE_PARM_DESC(enc_vbi_buffers,
+		 "Encoder VBI Buffers (in MB)\n"
+		 "\t\t\tDefault: " __stringify(IVTV_DEFAULT_ENC_VBI_BUFFERS));
+MODULE_PARM_DESC(enc_pcm_buffers,
+		 "Encoder PCM buffers (in kB)\n"
+		 "\t\t\tDefault: " __stringify(IVTV_DEFAULT_ENC_PCM_BUFFERS));
+MODULE_PARM_DESC(dec_mpg_buffers,
+		 "Decoder MPG buffers (in MB)\n"
+		 "\t\t\tDefault: " __stringify(IVTV_DEFAULT_DEC_MPG_BUFFERS));
+MODULE_PARM_DESC(dec_yuv_buffers,
+		 "Decoder YUV buffers (in MB)\n"
+		 "\t\t\tDefault: " __stringify(IVTV_DEFAULT_DEC_YUV_BUFFERS));
+MODULE_PARM_DESC(dec_vbi_buffers,
+		 "Decoder VBI buffers (in kB)\n"
+		 "\t\t\tDefault: " __stringify(IVTV_DEFAULT_DEC_VBI_BUFFERS));
+MODULE_PARM_DESC(newi2c,
+		 "Use new I2C implementation\n"
+		 "\t\t\t-1 is autodetect, 0 is off, 1 is on\n"
+		 "\t\t\tDefault is autodetect");
+MODULE_PARM_DESC(i2c_clock_period,
+		 "Period of SCL for the I2C bus controlled by the CX23415/6\n"
+		 "\t\t\tMin: 10 usec (100 kHz), Max: 4500 usec (222 Hz)\n"
+		 "\t\t\tDefault: " __stringify(IVTV_DEFAULT_I2C_CLOCK_PERIOD));
+
+MODULE_PARM_DESC(ivtv_first_minor, "Set device node number assigned to first card");
+
+MODULE_AUTHOR("Kevin Thayer, Chris Kennedy, Hans Verkuil");
+MODULE_DESCRIPTION("CX23415/CX23416 driver");
+MODULE_SUPPORTED_DEVICE
+    ("CX23415/CX23416 MPEG2 encoder (WinTV PVR-150/250/350/500,\n"
+		"\t\t\tYuan MPG series and similar)");
+MODULE_LICENSE("GPL");
+
+MODULE_VERSION(IVTV_VERSION);
+
+#if defined(CONFIG_MODULES) && defined(MODULE)
+static void request_module_async(struct work_struct *work)
+{
+	struct ivtv *dev = container_of(work, struct ivtv, request_module_wk);
+
+	/* Make sure ivtv-alsa module is loaded */
+	request_module("ivtv-alsa");
+
+	/* Initialize ivtv-alsa for this instance of the cx18 device */
+	if (ivtv_ext_init != NULL)
+		ivtv_ext_init(dev);
+}
+
+static void request_modules(struct ivtv *dev)
+{
+	INIT_WORK(&dev->request_module_wk, request_module_async);
+	schedule_work(&dev->request_module_wk);
+}
+
+static void flush_request_modules(struct ivtv *dev)
+{
+	flush_work_sync(&dev->request_module_wk);
+}
+#else
+#define request_modules(dev)
+#define flush_request_modules(dev)
+#endif /* CONFIG_MODULES */
+
+void ivtv_clear_irq_mask(struct ivtv *itv, u32 mask)
+{
+	itv->irqmask &= ~mask;
+	write_reg_sync(itv->irqmask, IVTV_REG_IRQMASK);
+}
+
+void ivtv_set_irq_mask(struct ivtv *itv, u32 mask)
+{
+	itv->irqmask |= mask;
+	write_reg_sync(itv->irqmask, IVTV_REG_IRQMASK);
+}
+
+int ivtv_set_output_mode(struct ivtv *itv, int mode)
+{
+    int old_mode;
+
+    spin_lock(&itv->lock);
+    old_mode = itv->output_mode;
+    if (old_mode == 0)
+	itv->output_mode = old_mode = mode;
+    spin_unlock(&itv->lock);
+    return old_mode;
+}
+
+struct ivtv_stream *ivtv_get_output_stream(struct ivtv *itv)
+{
+	switch (itv->output_mode) {
+	case OUT_MPG:
+		return &itv->streams[IVTV_DEC_STREAM_TYPE_MPG];
+	case OUT_YUV:
+		return &itv->streams[IVTV_DEC_STREAM_TYPE_YUV];
+	default:
+		return NULL;
+	}
+}
+
+int ivtv_waitq(wait_queue_head_t *waitq)
+{
+	DEFINE_WAIT(wait);
+
+	prepare_to_wait(waitq, &wait, TASK_INTERRUPTIBLE);
+	schedule();
+	finish_wait(waitq, &wait);
+	return signal_pending(current) ? -EINTR : 0;
+}
+
+/* Generic utility functions */
+int ivtv_msleep_timeout(unsigned int msecs, int intr)
+{
+	int timeout = msecs_to_jiffies(msecs);
+
+	do {
+		set_current_state(intr ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
+		timeout = schedule_timeout(timeout);
+		if (intr) {
+			int ret = signal_pending(current);
+
+			if (ret)
+				return ret;
+		}
+	} while (timeout);
+	return 0;
+}
+
+/* Release ioremapped memory */
+static void ivtv_iounmap(struct ivtv *itv)
+{
+	if (itv == NULL)
+		return;
+
+	/* Release registers memory */
+	if (itv->reg_mem != NULL) {
+		IVTV_DEBUG_INFO("releasing reg_mem\n");
+		iounmap(itv->reg_mem);
+		itv->reg_mem = NULL;
+	}
+	/* Release io memory */
+	if (itv->has_cx23415 && itv->dec_mem != NULL) {
+		IVTV_DEBUG_INFO("releasing dec_mem\n");
+		iounmap(itv->dec_mem);
+	}
+	itv->dec_mem = NULL;
+
+	/* Release io memory */
+	if (itv->enc_mem != NULL) {
+		IVTV_DEBUG_INFO("releasing enc_mem\n");
+		iounmap(itv->enc_mem);
+		itv->enc_mem = NULL;
+	}
+}
+
+/* Hauppauge card? get values from tveeprom */
+void ivtv_read_eeprom(struct ivtv *itv, struct tveeprom *tv)
+{
+	u8 eedata[256];
+
+	itv->i2c_client.addr = 0xA0 >> 1;
+	tveeprom_read(&itv->i2c_client, eedata, sizeof(eedata));
+	tveeprom_hauppauge_analog(&itv->i2c_client, tv, eedata);
+}
+
+static void ivtv_process_eeprom(struct ivtv *itv)
+{
+	struct tveeprom tv;
+	int pci_slot = PCI_SLOT(itv->pdev->devfn);
+
+	ivtv_read_eeprom(itv, &tv);
+
+	/* Many thanks to Steven Toth from Hauppauge for providing the
+	   model numbers */
+	switch (tv.model) {
+		/* In a few cases the PCI subsystem IDs do not correctly
+		   identify the card. A better method is to check the
+		   model number from the eeprom instead. */
+		case 30012 ... 30039:  /* Low profile PVR250 */
+		case 32000 ... 32999:
+		case 48000 ... 48099:  /* 48??? range are PVR250s with a cx23415 */
+		case 48400 ... 48599:
+			itv->card = ivtv_get_card(IVTV_CARD_PVR_250);
+			break;
+		case 48100 ... 48399:
+		case 48600 ... 48999:
+			itv->card = ivtv_get_card(IVTV_CARD_PVR_350);
+			break;
+		case 23000 ... 23999:  /* PVR500 */
+		case 25000 ... 25999:  /* Low profile PVR150 */
+		case 26000 ... 26999:  /* Regular PVR150 */
+			itv->card = ivtv_get_card(IVTV_CARD_PVR_150);
+			break;
+		case 0:
+			IVTV_ERR("Invalid EEPROM\n");
+			return;
+		default:
+			IVTV_ERR("Unknown model %d, defaulting to PVR-150\n", tv.model);
+			itv->card = ivtv_get_card(IVTV_CARD_PVR_150);
+			break;
+	}
+
+	switch (tv.model) {
+		/* Old style PVR350 (with an saa7114) uses this input for
+		   the tuner. */
+		case 48254:
+			itv->card = ivtv_get_card(IVTV_CARD_PVR_350_V1);
+			break;
+		default:
+			break;
+	}
+
+	itv->v4l2_cap = itv->card->v4l2_capabilities;
+	itv->card_name = itv->card->name;
+	itv->card_i2c = itv->card->i2c;
+
+	/* If this is a PVR500 then it should be possible to detect whether it is the
+	   first or second unit by looking at the subsystem device ID: is bit 4 is
+	   set, then it is the second unit (according to info from Hauppauge).
+
+	   However, while this works for most cards, I have seen a few PVR500 cards
+	   where both units have the same subsystem ID.
+
+	   So instead I look at the reported 'PCI slot' (which is the slot on the PVR500
+	   PCI bridge) and if it is 8, then it is assumed to be the first unit, otherwise
+	   it is the second unit. It is possible that it is a different slot when ivtv is
+	   used in Xen, in that case I ignore this card here. The worst that can happen
+	   is that the card presents itself with a non-working radio device.
+
+	   This detection is needed since the eeprom reports incorrectly that a radio is
+	   present on the second unit. */
+	if (tv.model / 1000 == 23) {
+		static const struct ivtv_card_tuner_i2c ivtv_i2c_radio = {
+			.radio = { 0x60, I2C_CLIENT_END },
+			.demod = { 0x43, I2C_CLIENT_END },
+			.tv = { 0x61, I2C_CLIENT_END },
+		};
+
+		itv->card_name = "WinTV PVR 500";
+		itv->card_i2c = &ivtv_i2c_radio;
+		if (pci_slot == 8 || pci_slot == 9) {
+			int is_first = (pci_slot & 1) == 0;
+
+			itv->card_name = is_first ? "WinTV PVR 500 (unit #1)" :
+						    "WinTV PVR 500 (unit #2)";
+			if (!is_first) {
+				IVTV_INFO("Correcting tveeprom data: no radio present on second unit\n");
+				tv.has_radio = 0;
+			}
+		}
+	}
+	IVTV_INFO("Autodetected %s\n", itv->card_name);
+
+	switch (tv.tuner_hauppauge_model) {
+		case 85:
+		case 99:
+		case 112:
+			itv->pvr150_workaround = 1;
+			break;
+		default:
+			break;
+	}
+	if (tv.tuner_type == TUNER_ABSENT)
+		IVTV_ERR("tveeprom cannot autodetect tuner!\n");
+
+	if (itv->options.tuner == -1)
+		itv->options.tuner = tv.tuner_type;
+	if (itv->options.radio == -1)
+		itv->options.radio = (tv.has_radio != 0);
+	/* only enable newi2c if an IR blaster is present */
+	if (itv->options.newi2c == -1 && tv.has_ir) {
+		itv->options.newi2c = (tv.has_ir & 4) ? 1 : 0;
+		if (itv->options.newi2c) {
+		    IVTV_INFO("Reopen i2c bus for IR-blaster support\n");
+		    exit_ivtv_i2c(itv);
+		    init_ivtv_i2c(itv);
+		}
+	}
+
+	if (itv->std != 0)
+		/* user specified tuner standard */
+		return;
+
+	/* autodetect tuner standard */
+	if (tv.tuner_formats & V4L2_STD_PAL) {
+		IVTV_DEBUG_INFO("PAL tuner detected\n");
+		itv->std |= V4L2_STD_PAL_BG | V4L2_STD_PAL_H;
+	} else if (tv.tuner_formats & V4L2_STD_NTSC) {
+		IVTV_DEBUG_INFO("NTSC tuner detected\n");
+		itv->std |= V4L2_STD_NTSC_M;
+	} else if (tv.tuner_formats & V4L2_STD_SECAM) {
+		IVTV_DEBUG_INFO("SECAM tuner detected\n");
+		itv->std |= V4L2_STD_SECAM_L;
+	} else {
+		IVTV_INFO("No tuner detected, default to NTSC-M\n");
+		itv->std |= V4L2_STD_NTSC_M;
+	}
+}
+
+static v4l2_std_id ivtv_parse_std(struct ivtv *itv)
+{
+	switch (pal[0]) {
+		case '6':
+			tunertype = 0;
+			return V4L2_STD_PAL_60;
+		case 'b':
+		case 'B':
+		case 'g':
+		case 'G':
+		case 'h':
+		case 'H':
+			tunertype = 0;
+			return V4L2_STD_PAL_BG | V4L2_STD_PAL_H;
+		case 'n':
+		case 'N':
+			tunertype = 1;
+			if (pal[1] == 'c' || pal[1] == 'C')
+				return V4L2_STD_PAL_Nc;
+			return V4L2_STD_PAL_N;
+		case 'i':
+		case 'I':
+			tunertype = 0;
+			return V4L2_STD_PAL_I;
+		case 'd':
+		case 'D':
+		case 'k':
+		case 'K':
+			tunertype = 0;
+			return V4L2_STD_PAL_DK;
+		case 'M':
+		case 'm':
+			tunertype = 1;
+			return V4L2_STD_PAL_M;
+		case '-':
+			break;
+		default:
+			IVTV_WARN("pal= argument not recognised\n");
+			return 0;
+	}
+
+	switch (secam[0]) {
+		case 'b':
+		case 'B':
+		case 'g':
+		case 'G':
+		case 'h':
+		case 'H':
+			tunertype = 0;
+			return V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H;
+		case 'd':
+		case 'D':
+		case 'k':
+		case 'K':
+			tunertype = 0;
+			return V4L2_STD_SECAM_DK;
+		case 'l':
+		case 'L':
+			tunertype = 0;
+			if (secam[1] == 'C' || secam[1] == 'c')
+				return V4L2_STD_SECAM_LC;
+			return V4L2_STD_SECAM_L;
+		case '-':
+			break;
+		default:
+			IVTV_WARN("secam= argument not recognised\n");
+			return 0;
+	}
+
+	switch (ntsc[0]) {
+		case 'm':
+		case 'M':
+			tunertype = 1;
+			return V4L2_STD_NTSC_M;
+		case 'j':
+		case 'J':
+			tunertype = 1;
+			return V4L2_STD_NTSC_M_JP;
+		case 'k':
+		case 'K':
+			tunertype = 1;
+			return V4L2_STD_NTSC_M_KR;
+		case '-':
+			break;
+		default:
+			IVTV_WARN("ntsc= argument not recognised\n");
+			return 0;
+	}
+
+	/* no match found */
+	return 0;
+}
+
+static void ivtv_process_options(struct ivtv *itv)
+{
+	const char *chipname;
+	int i, j;
+
+	itv->options.kilobytes[IVTV_ENC_STREAM_TYPE_MPG] = enc_mpg_buffers * 1024;
+	itv->options.kilobytes[IVTV_ENC_STREAM_TYPE_YUV] = enc_yuv_buffers * 1024;
+	itv->options.kilobytes[IVTV_ENC_STREAM_TYPE_VBI] = enc_vbi_buffers * 1024;
+	itv->options.kilobytes[IVTV_ENC_STREAM_TYPE_PCM] = enc_pcm_buffers;
+	itv->options.kilobytes[IVTV_DEC_STREAM_TYPE_MPG] = dec_mpg_buffers * 1024;
+	itv->options.kilobytes[IVTV_DEC_STREAM_TYPE_YUV] = dec_yuv_buffers * 1024;
+	itv->options.kilobytes[IVTV_DEC_STREAM_TYPE_VBI] = dec_vbi_buffers;
+	itv->options.cardtype = cardtype[itv->instance];
+	itv->options.tuner = tuner[itv->instance];
+	itv->options.radio = radio[itv->instance];
+
+	itv->options.i2c_clock_period = i2c_clock_period[itv->instance];
+	if (itv->options.i2c_clock_period == -1)
+		itv->options.i2c_clock_period = IVTV_DEFAULT_I2C_CLOCK_PERIOD;
+	else if (itv->options.i2c_clock_period < 10)
+		itv->options.i2c_clock_period = 10;
+	else if (itv->options.i2c_clock_period > 4500)
+		itv->options.i2c_clock_period = 4500;
+
+	itv->options.newi2c = newi2c;
+	if (tunertype < -1 || tunertype > 1) {
+		IVTV_WARN("Invalid tunertype argument, will autodetect instead\n");
+		tunertype = -1;
+	}
+	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->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);
+		return;
+	}
+	if ((itv->card = ivtv_get_card(itv->options.cardtype - 1))) {
+		IVTV_INFO("User specified %s card (detected %s based chip)\n",
+				itv->card->name, chipname);
+	} else if (itv->options.cardtype != 0) {
+		IVTV_ERR("Unknown user specified type, trying to autodetect card\n");
+	}
+	if (itv->card == NULL) {
+		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);
+		}
+	}
+	if (itv->card == NULL) {
+		for (i = 0; (itv->card = ivtv_get_card(i)); i++) {
+			if (itv->card->pci_list == NULL)
+				continue;
+			for (j = 0; itv->card->pci_list[j].device; j++) {
+				if (itv->pdev->device !=
+				    itv->card->pci_list[j].device)
+					continue;
+				if (itv->pdev->subsystem_vendor !=
+				    itv->card->pci_list[j].subsystem_vendor)
+					continue;
+				if (itv->pdev->subsystem_device !=
+				    itv->card->pci_list[j].subsystem_device)
+					continue;
+				IVTV_INFO("Autodetected %s card (%s based)\n",
+						itv->card->name, chipname);
+				goto done;
+			}
+		}
+	}
+done:
+
+	if (itv->card == NULL) {
+		itv->card = ivtv_get_card(IVTV_CARD_PVR_150);
+		IVTV_ERR("Unknown card: vendor/device: [%04x:%04x]\n",
+		     itv->pdev->vendor, itv->pdev->device);
+		IVTV_ERR("              subsystem vendor/device: [%04x:%04x]\n",
+		     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");
+		IVTV_ERR("card you have to the ivtv-devel mailinglist (www.ivtvdriver.org)\n");
+		IVTV_ERR("Prefix your subject line with [UNKNOWN IVTV CARD].\n");
+	}
+	itv->v4l2_cap = itv->card->v4l2_capabilities;
+	itv->card_name = itv->card->name;
+	itv->card_i2c = itv->card->i2c;
+}
+
+/* Precondition: the ivtv structure has been memset to 0. Only
+   the dev and num fields have been filled in.
+   No assumptions on the card type may be made here (see ivtv_init_struct2
+   for that).
+ */
+static int __devinit ivtv_init_struct1(struct ivtv *itv)
+{
+	struct sched_param param = { .sched_priority = 99 };
+
+	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) */
+
+	mutex_init(&itv->serialize_lock);
+	mutex_init(&itv->i2c_bus_lock);
+	mutex_init(&itv->udma.lock);
+
+	spin_lock_init(&itv->lock);
+	spin_lock_init(&itv->dma_reg_lock);
+
+	init_kthread_worker(&itv->irq_worker);
+	itv->irq_worker_task = kthread_run(kthread_worker_fn, &itv->irq_worker,
+					   itv->v4l2_dev.name);
+	if (IS_ERR(itv->irq_worker_task)) {
+		IVTV_ERR("Could not create ivtv task\n");
+		return -1;
+	}
+	/* must use the FIFO scheduler as it is realtime sensitive */
+	sched_setscheduler(itv->irq_worker_task, SCHED_FIFO, &param);
+
+	init_kthread_work(&itv->irq_work, ivtv_irq_work_handler);
+
+	/* Initial settings */
+	itv->cxhdl.port = CX2341X_PORT_MEMORY;
+	itv->cxhdl.capabilities = CX2341X_CAP_HAS_SLICED_VBI;
+	init_waitqueue_head(&itv->eos_waitq);
+	init_waitqueue_head(&itv->event_waitq);
+	init_waitqueue_head(&itv->vsync_waitq);
+	init_waitqueue_head(&itv->dma_waitq);
+	init_timer(&itv->dma_timer);
+	itv->dma_timer.function = ivtv_unfinished_dma;
+	itv->dma_timer.data = (unsigned long)itv;
+
+	itv->cur_dma_stream = -1;
+	itv->cur_pio_stream = -1;
+
+	/* Ctrls */
+	itv->speed = 1000;
+
+	/* VBI */
+	itv->vbi.in.type = V4L2_BUF_TYPE_VBI_CAPTURE;
+	itv->vbi.sliced_in = &itv->vbi.in.fmt.sliced;
+
+	/* Init the sg table for osd/yuv output */
+	sg_init_table(itv->udma.SGlist, IVTV_DMA_SG_OSD_ENT);
+
+	/* OSD */
+	itv->osd_global_alpha_state = 1;
+	itv->osd_global_alpha = 255;
+
+	/* YUV */
+	atomic_set(&itv->yuv_info.next_dma_frame, -1);
+	itv->yuv_info.lace_mode = ivtv_yuv_mode;
+	itv->yuv_info.lace_threshold = ivtv_yuv_threshold;
+	itv->yuv_info.max_frames_buffered = 3;
+	itv->yuv_info.track_osd = 1;
+	return 0;
+}
+
+/* Second initialization part. Here the card type has been
+   autodetected. */
+static void __devinit ivtv_init_struct2(struct ivtv *itv)
+{
+	int i;
+
+	for (i = 0; i < IVTV_CARD_MAX_VIDEO_INPUTS; i++)
+		if (itv->card->video_inputs[i].video_type == 0)
+			break;
+	itv->nof_inputs = i;
+	for (i = 0; i < IVTV_CARD_MAX_AUDIO_INPUTS; i++)
+		if (itv->card->audio_inputs[i].audio_type == 0)
+			break;
+	itv->nof_audio_inputs = i;
+
+	if (itv->card->hw_all & IVTV_HW_CX25840) {
+		itv->vbi.sliced_size = 288;  /* multiple of 16, real size = 284 */
+	} else {
+		itv->vbi.sliced_size = 64;   /* multiple of 16, real size = 52 */
+	}
+
+	/* Find tuner input */
+	for (i = 0; i < itv->nof_inputs; i++) {
+		if (itv->card->video_inputs[i].video_type ==
+				IVTV_CARD_INPUT_VID_TUNER)
+			break;
+	}
+	if (i == itv->nof_inputs)
+		i = 0;
+	itv->active_input = i;
+	itv->audio_input = itv->card->video_inputs[i].audio_index;
+}
+
+static int ivtv_setup_pci(struct ivtv *itv, struct pci_dev *pdev,
+			  const struct pci_device_id *pci_id)
+{
+	u16 cmd;
+	unsigned char pci_latency;
+
+	IVTV_DEBUG_INFO("Enabling pci device\n");
+
+	if (pci_enable_device(pdev)) {
+		IVTV_ERR("Can't enable device!\n");
+		return -EIO;
+	}
+	if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
+		IVTV_ERR("No suitable DMA available.\n");
+		return -EIO;
+	}
+	if (!request_mem_region(itv->base_addr, IVTV_ENCODER_SIZE, "ivtv encoder")) {
+		IVTV_ERR("Cannot request encoder memory region.\n");
+		return -EIO;
+	}
+
+	if (!request_mem_region(itv->base_addr + IVTV_REG_OFFSET,
+				IVTV_REG_SIZE, "ivtv registers")) {
+		IVTV_ERR("Cannot request register memory region.\n");
+		release_mem_region(itv->base_addr, IVTV_ENCODER_SIZE);
+		return -EIO;
+	}
+
+	if (itv->has_cx23415 &&
+	    !request_mem_region(itv->base_addr + IVTV_DECODER_OFFSET,
+				IVTV_DECODER_SIZE, "ivtv decoder")) {
+		IVTV_ERR("Cannot request decoder memory region.\n");
+		release_mem_region(itv->base_addr, IVTV_ENCODER_SIZE);
+		release_mem_region(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE);
+		return -EIO;
+	}
+
+	/* Check for bus mastering */
+	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(pdev);
+		pci_read_config_word(pdev, PCI_COMMAND, &cmd);
+		if (!(cmd & PCI_COMMAND_MASTER)) {
+			IVTV_ERR("Bus Mastering is not enabled\n");
+			return -ENXIO;
+		}
+	}
+	IVTV_DEBUG_INFO("Bus Mastering Enabled.\n");
+
+	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(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(pdev, 0x40, 0xffff);
+
+	IVTV_DEBUG_INFO("%d (rev %d) at %02x:%02x.%x, "
+		   "irq: %d, latency: %d, memory: 0x%llx\n",
+		   pdev->device, pdev->revision, pdev->bus->number,
+		   PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
+		   pdev->irq, pci_latency, (u64)itv->base_addr);
+
+	return 0;
+}
+
+static void ivtv_load_and_init_modules(struct ivtv *itv)
+{
+	u32 hw = itv->card->hw_all;
+	unsigned i;
+
+	/* check which i2c devices are actually found */
+	for (i = 0; i < 32; i++) {
+		u32 device = 1 << i;
+
+		if (!(device & hw))
+			continue;
+		if (device == IVTV_HW_GPIO || device == IVTV_HW_TVEEPROM) {
+			/* GPIO and TVEEPROM do not use i2c probing */
+			itv->hw_flags |= device;
+			continue;
+		}
+		if (ivtv_i2c_register(itv, i) == 0)
+			itv->hw_flags |= device;
+	}
+
+	/* probe for legacy IR controllers that aren't in card definitions */
+	if ((itv->hw_flags & IVTV_HW_IR_ANY) == 0)
+		ivtv_i2c_new_ir_legacy(itv);
+
+	if (itv->card->hw_all & IVTV_HW_CX25840)
+		itv->sd_video = ivtv_find_hw(itv, IVTV_HW_CX25840);
+	else if (itv->card->hw_all & IVTV_HW_SAA717X)
+		itv->sd_video = ivtv_find_hw(itv, IVTV_HW_SAA717X);
+	else if (itv->card->hw_all & IVTV_HW_SAA7114)
+		itv->sd_video = ivtv_find_hw(itv, IVTV_HW_SAA7114);
+	else
+		itv->sd_video = ivtv_find_hw(itv, IVTV_HW_SAA7115);
+	itv->sd_audio = ivtv_find_hw(itv, itv->card->hw_audio_ctrl);
+	itv->sd_muxer = ivtv_find_hw(itv, itv->card->hw_muxer);
+
+	hw = itv->hw_flags;
+
+	if (itv->card->type == IVTV_CARD_CX23416GYC) {
+		/* Several variations of this card exist, detect which card
+		   type should be used. */
+		if ((hw & (IVTV_HW_UPD64031A | IVTV_HW_UPD6408X)) == 0)
+			itv->card = ivtv_get_card(IVTV_CARD_CX23416GYC_NOGRYCS);
+		else if ((hw & IVTV_HW_UPD64031A) == 0)
+			itv->card = ivtv_get_card(IVTV_CARD_CX23416GYC_NOGR);
+	}
+	else if (itv->card->type == IVTV_CARD_GV_MVPRX ||
+		 itv->card->type == IVTV_CARD_GV_MVPRX2E) {
+		/* The crystal frequency of GVMVPRX is 24.576MHz */
+		v4l2_subdev_call(itv->sd_video, video, s_crystal_freq,
+			SAA7115_FREQ_24_576_MHZ, SAA7115_FREQ_FL_UCGC);
+	}
+
+	if (hw & IVTV_HW_CX25840) {
+		itv->vbi.raw_decoder_line_size = 1444;
+		itv->vbi.raw_decoder_sav_odd_field = 0x20;
+		itv->vbi.raw_decoder_sav_even_field = 0x60;
+		itv->vbi.sliced_decoder_line_size = 272;
+		itv->vbi.sliced_decoder_sav_odd_field = 0xB0;
+		itv->vbi.sliced_decoder_sav_even_field = 0xF0;
+	}
+
+	if (hw & IVTV_HW_SAA711X) {
+		struct v4l2_dbg_chip_ident v;
+
+		/* determine the exact saa711x model */
+		itv->hw_flags &= ~IVTV_HW_SAA711X;
+
+		v.match.type = V4L2_CHIP_MATCH_I2C_DRIVER;
+		strlcpy(v.match.name, "saa7115", sizeof(v.match.name));
+		ivtv_call_hw(itv, IVTV_HW_SAA711X, core, g_chip_ident, &v);
+		if (v.ident == V4L2_IDENT_SAA7114) {
+			itv->hw_flags |= IVTV_HW_SAA7114;
+			/* VBI is not yet supported by the saa7114 driver. */
+			itv->v4l2_cap &= ~(V4L2_CAP_SLICED_VBI_CAPTURE|V4L2_CAP_VBI_CAPTURE);
+		} else {
+			itv->hw_flags |= IVTV_HW_SAA7115;
+		}
+		itv->vbi.raw_decoder_line_size = 1443;
+		itv->vbi.raw_decoder_sav_odd_field = 0x25;
+		itv->vbi.raw_decoder_sav_even_field = 0x62;
+		itv->vbi.sliced_decoder_line_size = 51;
+		itv->vbi.sliced_decoder_sav_odd_field = 0xAB;
+		itv->vbi.sliced_decoder_sav_even_field = 0xEC;
+	}
+
+	if (hw & IVTV_HW_SAA717X) {
+		itv->vbi.raw_decoder_line_size = 1443;
+		itv->vbi.raw_decoder_sav_odd_field = 0x25;
+		itv->vbi.raw_decoder_sav_even_field = 0x62;
+		itv->vbi.sliced_decoder_line_size = 51;
+		itv->vbi.sliced_decoder_sav_odd_field = 0xAB;
+		itv->vbi.sliced_decoder_sav_even_field = 0xEC;
+	}
+}
+
+static int __devinit ivtv_probe(struct pci_dev *pdev,
+				const struct pci_device_id *pci_id)
+{
+	int retval = 0;
+	int vbi_buf_size;
+	struct ivtv *itv;
+
+	itv = kzalloc(sizeof(struct ivtv), GFP_ATOMIC);
+	if (itv == NULL)
+		return -ENOMEM;
+	itv->pdev = pdev;
+	itv->instance = v4l2_device_set_name(&itv->v4l2_dev, "ivtv",
+						&ivtv_instance);
+
+	retval = v4l2_device_register(&pdev->dev, &itv->v4l2_dev);
+	if (retval) {
+		kfree(itv);
+		return retval;
+	}
+	IVTV_INFO("Initializing card %d\n", itv->instance);
+
+	ivtv_process_options(itv);
+	if (itv->options.cardtype == -1) {
+		retval = -ENODEV;
+		goto err;
+	}
+	if (ivtv_init_struct1(itv)) {
+		retval = -ENOMEM;
+		goto err;
+	}
+	retval = cx2341x_handler_init(&itv->cxhdl, 50);
+	if (retval)
+		goto err;
+	itv->v4l2_dev.ctrl_handler = &itv->cxhdl.hdl;
+	itv->cxhdl.ops = &ivtv_cxhdl_ops;
+	itv->cxhdl.priv = itv;
+	itv->cxhdl.func = ivtv_api_func;
+
+	IVTV_DEBUG_INFO("base addr: 0x%llx\n", (u64)itv->base_addr);
+
+	/* PCI Device Setup */
+	retval = ivtv_setup_pci(itv, pdev, pci_id);
+	if (retval == -EIO)
+		goto free_worker;
+	if (retval == -ENXIO)
+		goto free_mem;
+
+	/* map io memory */
+	IVTV_DEBUG_INFO("attempting ioremap at 0x%llx len 0x%08x\n",
+		   (u64)itv->base_addr + IVTV_ENCODER_OFFSET, IVTV_ENCODER_SIZE);
+	itv->enc_mem = ioremap_nocache(itv->base_addr + IVTV_ENCODER_OFFSET,
+				       IVTV_ENCODER_SIZE);
+	if (!itv->enc_mem) {
+		IVTV_ERR("ioremap failed. Can't get a window into CX23415/6 "
+			 "encoder memory\n");
+		IVTV_ERR("Each capture card with a CX23415/6 needs 8 MB of "
+			 "vmalloc address space for this window\n");
+		IVTV_ERR("Check the output of 'grep Vmalloc /proc/meminfo'\n");
+		IVTV_ERR("Use the vmalloc= kernel command line option to set "
+			 "VmallocTotal to a larger value\n");
+		retval = -ENOMEM;
+		goto free_mem;
+	}
+
+	if (itv->has_cx23415) {
+		IVTV_DEBUG_INFO("attempting ioremap at 0x%llx len 0x%08x\n",
+				(u64)itv->base_addr + IVTV_DECODER_OFFSET, IVTV_DECODER_SIZE);
+		itv->dec_mem = ioremap_nocache(itv->base_addr + IVTV_DECODER_OFFSET,
+				IVTV_DECODER_SIZE);
+		if (!itv->dec_mem) {
+			IVTV_ERR("ioremap failed. Can't get a window into "
+				 "CX23415 decoder memory\n");
+			IVTV_ERR("Each capture card with a CX23415 needs 8 MB "
+				 "of vmalloc address space for this window\n");
+			IVTV_ERR("Check the output of 'grep Vmalloc "
+				 "/proc/meminfo'\n");
+			IVTV_ERR("Use the vmalloc= kernel command line option "
+				 "to set VmallocTotal to a larger value\n");
+			retval = -ENOMEM;
+			goto free_mem;
+		}
+	}
+	else {
+		itv->dec_mem = itv->enc_mem;
+	}
+
+	/* map registers memory */
+	IVTV_DEBUG_INFO("attempting ioremap at 0x%llx len 0x%08x\n",
+		   (u64)itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE);
+	itv->reg_mem =
+	    ioremap_nocache(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE);
+	if (!itv->reg_mem) {
+		IVTV_ERR("ioremap failed. Can't get a window into CX23415/6 "
+			 "register space\n");
+		IVTV_ERR("Each capture card with a CX23415/6 needs 64 kB of "
+			 "vmalloc address space for this window\n");
+		IVTV_ERR("Check the output of 'grep Vmalloc /proc/meminfo'\n");
+		IVTV_ERR("Use the vmalloc= kernel command line option to set "
+			 "VmallocTotal to a larger value\n");
+		retval = -ENOMEM;
+		goto free_io;
+	}
+
+	retval = ivtv_gpio_init(itv);
+	if (retval)
+		goto free_io;
+
+	/* active i2c  */
+	IVTV_DEBUG_INFO("activating i2c...\n");
+	if (init_ivtv_i2c(itv)) {
+		IVTV_ERR("Could not initialize i2c\n");
+		goto free_io;
+	}
+
+	if (itv->card->hw_all & IVTV_HW_TVEEPROM) {
+		/* Based on the model number the cardtype may be changed.
+		   The PCI IDs are not always reliable. */
+		ivtv_process_eeprom(itv);
+	}
+	if (itv->card->comment)
+		IVTV_INFO("%s", itv->card->comment);
+	if (itv->card->v4l2_capabilities == 0) {
+		/* card was detected but is not supported */
+		retval = -ENODEV;
+		goto free_i2c;
+	}
+
+	if (itv->std == 0) {
+		itv->std = V4L2_STD_NTSC_M;
+	}
+
+	if (itv->options.tuner == -1) {
+		int i;
+
+		for (i = 0; i < IVTV_CARD_MAX_TUNERS; i++) {
+			if ((itv->std & itv->card->tuners[i].std) == 0)
+				continue;
+			itv->options.tuner = itv->card->tuners[i].tuner;
+			break;
+		}
+	}
+	/* if no tuner was found, then pick the first tuner in the card list */
+	if (itv->options.tuner == -1 && itv->card->tuners[0].std) {
+		itv->std = itv->card->tuners[0].std;
+		if (itv->std & V4L2_STD_PAL)
+			itv->std = V4L2_STD_PAL_BG | V4L2_STD_PAL_H;
+		else if (itv->std & V4L2_STD_NTSC)
+			itv->std = V4L2_STD_NTSC_M;
+		else if (itv->std & V4L2_STD_SECAM)
+			itv->std = V4L2_STD_SECAM_L;
+		itv->options.tuner = itv->card->tuners[0].tuner;
+	}
+	if (itv->options.radio == -1)
+		itv->options.radio = (itv->card->radio_input.audio_type != 0);
+
+	/* The card is now fully identified, continue with card-specific
+	   initialization. */
+	ivtv_init_struct2(itv);
+
+	ivtv_load_and_init_modules(itv);
+
+	if (itv->std & V4L2_STD_525_60) {
+		itv->is_60hz = 1;
+		itv->is_out_60hz = 1;
+	} else {
+		itv->is_50hz = 1;
+		itv->is_out_50hz = 1;
+	}
+
+	itv->yuv_info.osd_full_w = 720;
+	itv->yuv_info.osd_full_h = itv->is_out_50hz ? 576 : 480;
+	itv->yuv_info.v4l2_src_w = itv->yuv_info.osd_full_w;
+	itv->yuv_info.v4l2_src_h = itv->yuv_info.osd_full_h;
+
+	cx2341x_handler_set_50hz(&itv->cxhdl, itv->is_50hz);
+
+	itv->stream_buf_size[IVTV_ENC_STREAM_TYPE_MPG] = 0x08000;
+	itv->stream_buf_size[IVTV_ENC_STREAM_TYPE_PCM] = 0x01200;
+	itv->stream_buf_size[IVTV_DEC_STREAM_TYPE_MPG] = 0x10000;
+	itv->stream_buf_size[IVTV_DEC_STREAM_TYPE_YUV] = 0x10000;
+	itv->stream_buf_size[IVTV_ENC_STREAM_TYPE_YUV] = 0x08000;
+
+	/* Setup VBI Raw Size. Should be big enough to hold PAL.
+	   It is possible to switch between PAL and NTSC, so we need to
+	   take the largest size here. */
+	/* 1456 is multiple of 16, real size = 1444 */
+	itv->vbi.raw_size = 1456;
+	/* We use a buffer size of 1/2 of the total size needed for a
+	   frame. This is actually very useful, since we now receive
+	   a field at a time and that makes 'compressing' the raw data
+	   down to size by stripping off the SAV codes a lot easier.
+	   Note: having two different buffer sizes prevents standard
+	   switching on the fly. We need to find a better solution... */
+	vbi_buf_size = itv->vbi.raw_size * (itv->is_60hz ? 24 : 36) / 2;
+	itv->stream_buf_size[IVTV_ENC_STREAM_TYPE_VBI] = vbi_buf_size;
+	itv->stream_buf_size[IVTV_DEC_STREAM_TYPE_VBI] = sizeof(struct v4l2_sliced_vbi_data) * 36;
+
+	if (itv->options.radio > 0)
+		itv->v4l2_cap |= V4L2_CAP_RADIO;
+
+	if (itv->options.tuner > -1) {
+		struct tuner_setup setup;
+
+		setup.addr = ADDR_UNSET;
+		setup.type = itv->options.tuner;
+		setup.mode_mask = T_ANALOG_TV;  /* matches TV tuners */
+		if (itv->options.radio > 0)
+			setup.mode_mask |= T_RADIO;
+		setup.tuner_callback = (setup.type == TUNER_XC2028) ?
+			ivtv_reset_tuner_gpio : NULL;
+		ivtv_call_all(itv, tuner, s_type_addr, &setup);
+		if (setup.type == TUNER_XC2028) {
+			static struct xc2028_ctrl ctrl = {
+				.fname = XC2028_DEFAULT_FIRMWARE,
+				.max_len = 64,
+			};
+			struct v4l2_priv_tun_config cfg = {
+				.tuner = itv->options.tuner,
+				.priv = &ctrl,
+			};
+			ivtv_call_all(itv, tuner, s_config, &cfg);
+		}
+	}
+
+	/* The tuner is fixed to the standard. The other inputs (e.g. S-Video)
+	   are not. */
+	itv->tuner_std = itv->std;
+
+	if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) {
+		struct v4l2_ctrl_handler *hdl = itv->v4l2_dev.ctrl_handler;
+
+		itv->ctrl_pts = v4l2_ctrl_new_std(hdl, &ivtv_hdl_out_ops,
+				V4L2_CID_MPEG_VIDEO_DEC_PTS, 0, 0, 0, 0);
+		itv->ctrl_frame = v4l2_ctrl_new_std(hdl, &ivtv_hdl_out_ops,
+				V4L2_CID_MPEG_VIDEO_DEC_FRAME, 0, 0, 0, 0);
+		/* Note: V4L2_MPEG_AUDIO_DEC_PLAYBACK_AUTO is not supported,
+		   mask that menu item. */
+		itv->ctrl_audio_playback =
+			v4l2_ctrl_new_std_menu(hdl, &ivtv_hdl_out_ops,
+				V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK,
+				V4L2_MPEG_AUDIO_DEC_PLAYBACK_SWAPPED_STEREO,
+				1 << V4L2_MPEG_AUDIO_DEC_PLAYBACK_AUTO,
+				V4L2_MPEG_AUDIO_DEC_PLAYBACK_STEREO);
+		itv->ctrl_audio_multilingual_playback =
+			v4l2_ctrl_new_std_menu(hdl, &ivtv_hdl_out_ops,
+				V4L2_CID_MPEG_AUDIO_DEC_MULTILINGUAL_PLAYBACK,
+				V4L2_MPEG_AUDIO_DEC_PLAYBACK_SWAPPED_STEREO,
+				1 << V4L2_MPEG_AUDIO_DEC_PLAYBACK_AUTO,
+				V4L2_MPEG_AUDIO_DEC_PLAYBACK_LEFT);
+		if (hdl->error) {
+			retval = hdl->error;
+			goto free_i2c;
+		}
+		v4l2_ctrl_cluster(2, &itv->ctrl_pts);
+		v4l2_ctrl_cluster(2, &itv->ctrl_audio_playback);
+		ivtv_call_all(itv, video, s_std_output, itv->std);
+		/* Turn off the output signal. The mpeg decoder is not yet
+		   active so without this you would get a green image until the
+		   mpeg decoder becomes active. */
+		ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 0);
+	}
+
+	/* clear interrupt mask, effectively disabling interrupts */
+	ivtv_set_irq_mask(itv, 0xffffffff);
+
+	/* Register IRQ */
+	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;
+	}
+
+	retval = ivtv_streams_setup(itv);
+	if (retval) {
+		IVTV_ERR("Error %d setting up streams\n", retval);
+		goto free_irq;
+	}
+	retval = ivtv_streams_register(itv);
+	if (retval) {
+		IVTV_ERR("Error %d registering devices\n", retval);
+		goto free_streams;
+	}
+	IVTV_INFO("Initialized card: %s\n", itv->card_name);
+
+	/* Load ivtv submodules (ivtv-alsa) */
+	request_modules(itv);
+	return 0;
+
+free_streams:
+	ivtv_streams_cleanup(itv, 1);
+free_irq:
+	free_irq(itv->pdev->irq, (void *)itv);
+free_i2c:
+	v4l2_ctrl_handler_free(&itv->cxhdl.hdl);
+	exit_ivtv_i2c(itv);
+free_io:
+	ivtv_iounmap(itv);
+free_mem:
+	release_mem_region(itv->base_addr, IVTV_ENCODER_SIZE);
+	release_mem_region(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE);
+	if (itv->has_cx23415)
+		release_mem_region(itv->base_addr + IVTV_DECODER_OFFSET, IVTV_DECODER_SIZE);
+free_worker:
+	kthread_stop(itv->irq_worker_task);
+err:
+	if (retval == 0)
+		retval = -ENODEV;
+	IVTV_ERR("Error %d on initialization\n", retval);
+
+	v4l2_device_unregister(&itv->v4l2_dev);
+	kfree(itv);
+	return retval;
+}
+
+int ivtv_init_on_first_open(struct ivtv *itv)
+{
+	struct v4l2_frequency vf;
+	/* Needed to call ioctls later */
+	struct ivtv_open_id fh;
+	int fw_retry_count = 3;
+	int video_input;
+
+	fh.itv = itv;
+
+	if (test_bit(IVTV_F_I_FAILED, &itv->i_flags))
+		return -ENXIO;
+
+	if (test_and_set_bit(IVTV_F_I_INITED, &itv->i_flags))
+		return 0;
+
+	while (--fw_retry_count > 0) {
+		/* load firmware */
+		if (ivtv_firmware_init(itv) == 0)
+			break;
+		if (fw_retry_count > 1)
+			IVTV_WARN("Retry loading firmware\n");
+	}
+
+	if (fw_retry_count == 0) {
+		set_bit(IVTV_F_I_FAILED, &itv->i_flags);
+		return -ENXIO;
+	}
+
+	/* Try and get firmware versions */
+	IVTV_DEBUG_INFO("Getting firmware version..\n");
+	ivtv_firmware_versions(itv);
+
+	if (itv->card->hw_all & IVTV_HW_CX25840)
+		v4l2_subdev_call(itv->sd_video, core, load_fw);
+
+	vf.tuner = 0;
+	vf.type = V4L2_TUNER_ANALOG_TV;
+	vf.frequency = 6400; /* the tuner 'baseline' frequency */
+
+	/* Set initial frequency. For PAL/SECAM broadcasts no
+	   'default' channel exists AFAIK. */
+	if (itv->std == V4L2_STD_NTSC_M_JP) {
+		vf.frequency = 1460;	/* ch. 1 91250*16/1000 */
+	}
+	else if (itv->std & V4L2_STD_NTSC_M) {
+		vf.frequency = 1076;	/* ch. 4 67250*16/1000 */
+	}
+
+	video_input = itv->active_input;
+	itv->active_input++;	/* Force update of input */
+	ivtv_s_input(NULL, &fh, video_input);
+
+	/* Let the VIDIOC_S_STD ioctl do all the work, keeps the code
+	   in one place. */
+	itv->std++;		/* Force full standard initialization */
+	itv->std_out = itv->std;
+	ivtv_s_frequency(NULL, &fh, &vf);
+
+	if (itv->card->v4l2_capabilities & V4L2_CAP_VIDEO_OUTPUT) {
+		/* Turn on the TV-out: ivtv_init_mpeg_decoder() initializes
+		   the mpeg decoder so now the saa7127 receives a proper
+		   signal. */
+		ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 1);
+		ivtv_init_mpeg_decoder(itv);
+	}
+
+	/* On a cx23416 this seems to be able to enable DMA to the chip? */
+	if (!itv->has_cx23415)
+		write_reg_sync(0x03, IVTV_REG_DMACONTROL);
+
+	ivtv_s_std_enc(itv, &itv->tuner_std);
+
+	/* Default interrupts enabled. For the PVR350 this includes the
+	   decoder VSYNC interrupt, which is always on. It is not only used
+	   during decoding but also by the OSD.
+	   Some old PVR250 cards had a cx23415, so testing for that is too
+	   general. Instead test if the card has video output capability. */
+	if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) {
+		ivtv_clear_irq_mask(itv, IVTV_IRQ_MASK_INIT | IVTV_IRQ_DEC_VSYNC);
+		ivtv_set_osd_alpha(itv);
+		ivtv_s_std_dec(itv, &itv->tuner_std);
+	} else {
+		ivtv_clear_irq_mask(itv, IVTV_IRQ_MASK_INIT);
+	}
+
+	/* Setup initial controls */
+	cx2341x_handler_setup(&itv->cxhdl);
+	return 0;
+}
+
+static void ivtv_remove(struct pci_dev *pdev)
+{
+	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");
+
+	flush_request_modules(itv);
+
+	if (test_bit(IVTV_F_I_INITED, &itv->i_flags)) {
+		/* Stop all captures */
+		IVTV_DEBUG_INFO("Stopping all streams\n");
+		if (atomic_read(&itv->capturing) > 0)
+			ivtv_stop_all_captures(itv);
+
+		/* Stop all decoding */
+		IVTV_DEBUG_INFO("Stopping decoding\n");
+
+		/* Turn off the TV-out */
+		if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)
+			ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 0);
+		if (atomic_read(&itv->decoding) > 0) {
+			int type;
+
+			if (test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags))
+				type = IVTV_DEC_STREAM_TYPE_YUV;
+			else
+				type = IVTV_DEC_STREAM_TYPE_MPG;
+			ivtv_stop_v4l2_decode_stream(&itv->streams[type],
+				V4L2_DEC_CMD_STOP_TO_BLACK | V4L2_DEC_CMD_STOP_IMMEDIATELY, 0);
+		}
+		ivtv_halt_firmware(itv);
+	}
+
+	/* Interrupts */
+	ivtv_set_irq_mask(itv, 0xffffffff);
+	del_timer_sync(&itv->dma_timer);
+
+	/* Kill irq worker */
+	flush_kthread_worker(&itv->irq_worker);
+	kthread_stop(itv->irq_worker_task);
+
+	ivtv_streams_cleanup(itv, 1);
+	ivtv_udma_free(itv);
+
+	v4l2_ctrl_handler_free(&itv->cxhdl.hdl);
+
+	exit_ivtv_i2c(itv);
+
+	free_irq(itv->pdev->irq, (void *)itv);
+	ivtv_iounmap(itv);
+
+	release_mem_region(itv->base_addr, IVTV_ENCODER_SIZE);
+	release_mem_region(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE);
+	if (itv->has_cx23415)
+		release_mem_region(itv->base_addr + IVTV_DECODER_OFFSET, IVTV_DECODER_SIZE);
+
+	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);
+}
+
+/* define a pci_driver for card detection */
+static struct pci_driver ivtv_pci_driver = {
+      .name =     "ivtv",
+      .id_table = ivtv_pci_tbl,
+      .probe =    ivtv_probe,
+      .remove =   ivtv_remove,
+};
+
+static int __init module_start(void)
+{
+	printk(KERN_INFO "ivtv: Start initialization, version %s\n", IVTV_VERSION);
+
+	/* Validate parameters */
+	if (ivtv_first_minor < 0 || ivtv_first_minor >= IVTV_MAX_CARDS) {
+		printk(KERN_ERR "ivtv: Exiting, ivtv_first_minor must be between 0 and %d\n",
+		     IVTV_MAX_CARDS - 1);
+		return -1;
+	}
+
+	if (ivtv_debug < 0 || ivtv_debug > 2047) {
+		ivtv_debug = 0;
+		printk(KERN_INFO "ivtv: Debug value must be >= 0 and <= 2047\n");
+	}
+
+	if (pci_register_driver(&ivtv_pci_driver)) {
+		printk(KERN_ERR "ivtv: Error detecting PCI card\n");
+		return -ENODEV;
+	}
+	printk(KERN_INFO "ivtv: End initialization\n");
+	return 0;
+}
+
+static void __exit module_cleanup(void)
+{
+	pci_unregister_driver(&ivtv_pci_driver);
+}
+
+/* Note: These symbols are exported because they are used by the ivtvfb
+   framebuffer module and an infrared module for the IR-blaster. */
+EXPORT_SYMBOL(ivtv_set_irq_mask);
+EXPORT_SYMBOL(ivtv_api);
+EXPORT_SYMBOL(ivtv_vapi);
+EXPORT_SYMBOL(ivtv_vapi_result);
+EXPORT_SYMBOL(ivtv_clear_irq_mask);
+EXPORT_SYMBOL(ivtv_debug);
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+EXPORT_SYMBOL(ivtv_fw_debug);
+#endif
+EXPORT_SYMBOL(ivtv_reset_ir_gpio);
+EXPORT_SYMBOL(ivtv_udma_setup);
+EXPORT_SYMBOL(ivtv_udma_unmap);
+EXPORT_SYMBOL(ivtv_udma_alloc);
+EXPORT_SYMBOL(ivtv_udma_prepare);
+EXPORT_SYMBOL(ivtv_init_on_first_open);
+EXPORT_SYMBOL(ivtv_firmware_check);
+
+module_init(module_start);
+module_exit(module_cleanup);
diff --git a/drivers/media/pci/ivtv/ivtv-driver.h b/drivers/media/pci/ivtv/ivtv-driver.h
new file mode 100644
index 0000000..bc309f4
--- /dev/null
+++ b/drivers/media/pci/ivtv/ivtv-driver.h
@@ -0,0 +1,850 @@
+/*
+    ivtv driver internal defines and structures
+    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
+    Copyright (C) 2004  Chris Kennedy <c@groovy.org>
+    Copyright (C) 2005-2007  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef IVTV_DRIVER_H
+#define IVTV_DRIVER_H
+
+/* Internal header for ivtv project:
+ * Driver for the cx23415/6 chip.
+ * Author: Kevin Thayer (nufan_wfk at yahoo.com)
+ * License: GPL
+ * http://www.ivtvdriver.org
+ *
+ * -----
+ * MPG600/MPG160 support by  T.Adachi <tadachi@tadachi-net.com>
+ *                      and Takeru KOMORIYA<komoriya@paken.org>
+ *
+ * AVerMedia M179 GPIO info by Chris Pinkham <cpinkham@bc2va.org>
+ *                using information provided by Jiun-Kuei Jung @ AVerMedia.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+#include <linux/list.h>
+#include <linux/unistd.h>
+#include <linux/pagemap.h>
+#include <linux/scatterlist.h>
+#include <linux/kthread.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <asm/uaccess.h>
+#include <asm/byteorder.h>
+
+#include <linux/dvb/video.h>
+#include <linux/dvb/audio.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-fh.h>
+#include <media/tuner.h>
+#include <media/cx2341x.h>
+#include <media/ir-kbd-i2c.h>
+
+#include <linux/ivtv.h>
+
+/* Memory layout */
+#define IVTV_ENCODER_OFFSET	0x00000000
+#define IVTV_ENCODER_SIZE	0x00800000	/* Total size is 0x01000000, but only first half is used */
+#define IVTV_DECODER_OFFSET	0x01000000
+#define IVTV_DECODER_SIZE	0x00800000	/* Total size is 0x01000000, but only first half is used */
+#define IVTV_REG_OFFSET 	0x02000000
+#define IVTV_REG_SIZE		0x00010000
+
+/* Maximum ivtv driver instances. Some people have a huge number of
+   capture cards, so set this to a high value. */
+#define IVTV_MAX_CARDS 32
+
+#define IVTV_ENC_STREAM_TYPE_MPG  0
+#define IVTV_ENC_STREAM_TYPE_YUV  1
+#define IVTV_ENC_STREAM_TYPE_VBI  2
+#define IVTV_ENC_STREAM_TYPE_PCM  3
+#define IVTV_ENC_STREAM_TYPE_RAD  4
+#define IVTV_DEC_STREAM_TYPE_MPG  5
+#define IVTV_DEC_STREAM_TYPE_VBI  6
+#define IVTV_DEC_STREAM_TYPE_VOUT 7
+#define IVTV_DEC_STREAM_TYPE_YUV  8
+#define IVTV_MAX_STREAMS	  9
+
+#define IVTV_DMA_SG_OSD_ENT	(2883584/PAGE_SIZE)	/* sg entities */
+
+/* DMA Registers */
+#define IVTV_REG_DMAXFER 	(0x0000)
+#define IVTV_REG_DMASTATUS 	(0x0004)
+#define IVTV_REG_DECDMAADDR 	(0x0008)
+#define IVTV_REG_ENCDMAADDR 	(0x000c)
+#define IVTV_REG_DMACONTROL 	(0x0010)
+#define IVTV_REG_IRQSTATUS 	(0x0040)
+#define IVTV_REG_IRQMASK 	(0x0048)
+
+/* Setup Registers */
+#define IVTV_REG_ENC_SDRAM_REFRESH 	(0x07F8)
+#define IVTV_REG_ENC_SDRAM_PRECHARGE 	(0x07FC)
+#define IVTV_REG_DEC_SDRAM_REFRESH 	(0x08F8)
+#define IVTV_REG_DEC_SDRAM_PRECHARGE 	(0x08FC)
+#define IVTV_REG_VDM 			(0x2800)
+#define IVTV_REG_AO 			(0x2D00)
+#define IVTV_REG_BYTEFLUSH 		(0x2D24)
+#define IVTV_REG_SPU 			(0x9050)
+#define IVTV_REG_HW_BLOCKS 		(0x9054)
+#define IVTV_REG_VPU 			(0x9058)
+#define IVTV_REG_APU 			(0xA064)
+
+/* Other registers */
+#define IVTV_REG_DEC_LINE_FIELD		(0x28C0)
+
+/* debugging */
+extern int ivtv_debug;
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+extern int ivtv_fw_debug;
+#endif
+
+#define IVTV_DBGFLG_WARN    (1 << 0)
+#define IVTV_DBGFLG_INFO    (1 << 1)
+#define IVTV_DBGFLG_MB      (1 << 2)
+#define IVTV_DBGFLG_IOCTL   (1 << 3)
+#define IVTV_DBGFLG_FILE    (1 << 4)
+#define IVTV_DBGFLG_DMA     (1 << 5)
+#define IVTV_DBGFLG_IRQ     (1 << 6)
+#define IVTV_DBGFLG_DEC     (1 << 7)
+#define IVTV_DBGFLG_YUV     (1 << 8)
+#define IVTV_DBGFLG_I2C     (1 << 9)
+/* Flag to turn on high volume debugging */
+#define IVTV_DBGFLG_HIGHVOL (1 << 10)
+
+#define IVTV_DEBUG(x, type, fmt, args...) \
+	do { \
+		if ((x) & ivtv_debug) \
+			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)
+#define IVTV_DEBUG_MB(fmt, args...)    IVTV_DEBUG(IVTV_DBGFLG_MB,    "mb",    fmt , ## args)
+#define IVTV_DEBUG_DMA(fmt, args...)   IVTV_DEBUG(IVTV_DBGFLG_DMA,   "dma",   fmt , ## args)
+#define IVTV_DEBUG_IOCTL(fmt, args...) IVTV_DEBUG(IVTV_DBGFLG_IOCTL, "ioctl", fmt , ## args)
+#define IVTV_DEBUG_FILE(fmt, args...)  IVTV_DEBUG(IVTV_DBGFLG_FILE,  "file",  fmt , ## args)
+#define IVTV_DEBUG_I2C(fmt, args...)   IVTV_DEBUG(IVTV_DBGFLG_I2C,   "i2c",   fmt , ## args)
+#define IVTV_DEBUG_IRQ(fmt, args...)   IVTV_DEBUG(IVTV_DBGFLG_IRQ,   "irq",   fmt , ## args)
+#define IVTV_DEBUG_DEC(fmt, args...)   IVTV_DEBUG(IVTV_DBGFLG_DEC,   "dec",   fmt , ## args)
+#define IVTV_DEBUG_YUV(fmt, args...)   IVTV_DEBUG(IVTV_DBGFLG_YUV,   "yuv",   fmt , ## args)
+
+#define IVTV_DEBUG_HIGH_VOL(x, type, fmt, args...) \
+	do { \
+		if (((x) & ivtv_debug) && (ivtv_debug & IVTV_DBGFLG_HIGHVOL)) 	\
+			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)
+#define IVTV_DEBUG_HI_MB(fmt, args...)    IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_MB,    "mb",    fmt , ## args)
+#define IVTV_DEBUG_HI_DMA(fmt, args...)   IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_DMA,   "dma",   fmt , ## args)
+#define IVTV_DEBUG_HI_IOCTL(fmt, args...) IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_IOCTL, "ioctl", fmt , ## args)
+#define IVTV_DEBUG_HI_FILE(fmt, args...)  IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_FILE,  "file",  fmt , ## args)
+#define IVTV_DEBUG_HI_I2C(fmt, args...)   IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_I2C,   "i2c",   fmt , ## args)
+#define IVTV_DEBUG_HI_IRQ(fmt, args...)   IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_IRQ,   "irq",   fmt , ## args)
+#define IVTV_DEBUG_HI_DEC(fmt, args...)   IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_DEC,   "dec",   fmt , ## args)
+#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->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
+#define OUT_MPG         1
+#define OUT_YUV         2
+#define OUT_UDMA_YUV    3
+#define OUT_PASSTHROUGH 4
+
+#define IVTV_MAX_PGM_INDEX (400)
+
+/* Default I2C SCL period in microseconds */
+#define IVTV_DEFAULT_I2C_CLOCK_PERIOD	20
+
+struct ivtv_options {
+	int kilobytes[IVTV_MAX_STREAMS];        /* size in kilobytes of each stream */
+	int cardtype;				/* force card type on load */
+	int tuner;				/* set tuner on load */
+	int radio;				/* enable/disable radio */
+	int newi2c;				/* new I2C algorithm */
+	int i2c_clock_period;			/* period of SCL for I2C bus */
+};
+
+/* ivtv-specific mailbox template */
+struct ivtv_mailbox {
+	u32 flags;
+	u32 cmd;
+	u32 retval;
+	u32 timeout;
+	u32 data[CX2341X_MBOX_MAX_DATA];
+};
+
+struct ivtv_api_cache {
+	unsigned long last_jiffies;		/* when last command was issued */
+	u32 data[CX2341X_MBOX_MAX_DATA];	/* last sent api data */
+};
+
+struct ivtv_mailbox_data {
+	volatile struct ivtv_mailbox __iomem *mbox;
+	/* Bits 0-2 are for the encoder mailboxes, 0-1 are for the decoder mailboxes.
+	   If the bit is set, then the corresponding mailbox is in use by the driver. */
+	unsigned long busy;
+	u8 max_mbox;
+};
+
+/* per-buffer bit flags */
+#define IVTV_F_B_NEED_BUF_SWAP  (1 << 0)	/* this buffer should be byte swapped */
+
+/* per-stream, s_flags */
+#define IVTV_F_S_DMA_PENDING	0	/* this stream has pending DMA */
+#define IVTV_F_S_DMA_HAS_VBI	1       /* the current DMA request also requests VBI data */
+#define IVTV_F_S_NEEDS_DATA	2 	/* this decoding stream needs more data */
+
+#define IVTV_F_S_CLAIMED 	3	/* this stream is claimed */
+#define IVTV_F_S_STREAMING      4	/* the fw is decoding/encoding this stream */
+#define IVTV_F_S_INTERNAL_USE	5	/* this stream is used internally (sliced VBI processing) */
+#define IVTV_F_S_PASSTHROUGH	6	/* this stream is in passthrough mode */
+#define IVTV_F_S_STREAMOFF	7	/* signal end of stream EOS */
+#define IVTV_F_S_APPL_IO        8	/* this stream is used read/written by an application */
+
+#define IVTV_F_S_PIO_PENDING	9	/* this stream has pending PIO */
+#define IVTV_F_S_PIO_HAS_VBI	1       /* the current PIO request also requests VBI data */
+
+/* per-ivtv, i_flags */
+#define IVTV_F_I_DMA		   0 	/* DMA in progress */
+#define IVTV_F_I_UDMA		   1 	/* UDMA in progress */
+#define IVTV_F_I_UDMA_PENDING	   2 	/* UDMA pending */
+#define IVTV_F_I_SPEED_CHANGE	   3 	/* a speed change is in progress */
+#define IVTV_F_I_EOS		   4 	/* end of encoder stream reached */
+#define IVTV_F_I_RADIO_USER	   5 	/* the radio tuner is selected */
+#define IVTV_F_I_DIG_RST	   6 	/* reset digitizer */
+#define IVTV_F_I_DEC_YUV	   7 	/* YUV instead of MPG is being decoded */
+#define IVTV_F_I_UPDATE_CC	   9  	/* CC should be updated */
+#define IVTV_F_I_UPDATE_WSS	   10 	/* WSS should be updated */
+#define IVTV_F_I_UPDATE_VPS	   11 	/* VPS should be updated */
+#define IVTV_F_I_DECODING_YUV	   12 	/* this stream is YUV frame decoding */
+#define IVTV_F_I_ENC_PAUSED	   13 	/* the encoder is paused */
+#define IVTV_F_I_VALID_DEC_TIMINGS 14 	/* last_dec_timing is valid */
+#define IVTV_F_I_HAVE_WORK  	   15	/* used in the interrupt handler: there is work to be done */
+#define IVTV_F_I_WORK_HANDLER_VBI  16	/* there is work to be done for VBI */
+#define IVTV_F_I_WORK_HANDLER_YUV  17	/* there is work to be done for YUV */
+#define IVTV_F_I_WORK_HANDLER_PIO  18	/* there is work to be done for PIO */
+#define IVTV_F_I_PIO		   19	/* PIO in progress */
+#define IVTV_F_I_DEC_PAUSED	   20 	/* the decoder is paused */
+#define IVTV_F_I_INITED		   21 	/* set after first open */
+#define IVTV_F_I_FAILED		   22 	/* set if first open failed */
+#define IVTV_F_I_WORK_HANDLER_PCM  23	/* there is work to be done for PCM */
+
+/* Event notifications */
+#define IVTV_F_I_EV_DEC_STOPPED	   28	/* decoder stopped event */
+#define IVTV_F_I_EV_VSYNC	   29 	/* VSYNC event */
+#define IVTV_F_I_EV_VSYNC_FIELD    30 	/* VSYNC event field (0 = first, 1 = second field) */
+#define IVTV_F_I_EV_VSYNC_ENABLED  31 	/* VSYNC event enabled */
+
+/* Scatter-Gather array element, used in DMA transfers */
+struct ivtv_sg_element {
+	__le32 src;
+	__le32 dst;
+	__le32 size;
+};
+
+struct ivtv_sg_host_element {
+	u32 src;
+	u32 dst;
+	u32 size;
+};
+
+struct ivtv_user_dma {
+	struct mutex lock;
+	int page_count;
+	struct page *map[IVTV_DMA_SG_OSD_ENT];
+	/* Needed when dealing with highmem userspace buffers */
+	struct page *bouncemap[IVTV_DMA_SG_OSD_ENT];
+
+	/* Base Dev SG Array for cx23415/6 */
+	struct ivtv_sg_element SGarray[IVTV_DMA_SG_OSD_ENT];
+	dma_addr_t SG_handle;
+	int SG_length;
+
+	/* SG List of Buffers */
+	struct scatterlist SGlist[IVTV_DMA_SG_OSD_ENT];
+};
+
+struct ivtv_dma_page_info {
+	unsigned long uaddr;
+	unsigned long first;
+	unsigned long last;
+	unsigned int offset;
+	unsigned int tail;
+	int page_count;
+};
+
+struct ivtv_buffer {
+	struct list_head list;
+	dma_addr_t dma_handle;
+	unsigned short b_flags;
+	unsigned short dma_xfer_cnt;
+	char *buf;
+	u32 bytesused;
+	u32 readpos;
+};
+
+struct ivtv_queue {
+	struct list_head list;          /* the list of buffers in this queue */
+	u32 buffers;                    /* number of buffers in this queue */
+	u32 length;                     /* total number of bytes of available buffer space */
+	u32 bytesused;                  /* total number of bytes used in this queue */
+};
+
+struct ivtv;				/* forward reference */
+
+struct ivtv_stream {
+	/* These first four fields are always set, even if the stream
+	   is not actually 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 */
+	u32 caps;			/* V4L2 capabilities */
+
+	struct v4l2_fh *fh;		/* pointer to the streaming filehandle */
+	spinlock_t qlock; 		/* locks access to the queues */
+	unsigned long s_flags;		/* status flags, see above */
+	int dma;			/* can be PCI_DMA_TODEVICE, PCI_DMA_FROMDEVICE or PCI_DMA_NONE */
+	u32 pending_offset;
+	u32 pending_backup;
+	u64 pending_pts;
+
+	u32 dma_offset;
+	u32 dma_backup;
+	u64 dma_pts;
+
+	int subtype;
+	wait_queue_head_t waitq;
+	u32 dma_last_offset;
+
+	/* Buffer Stats */
+	u32 buffers;
+	u32 buf_size;
+	u32 buffers_stolen;
+
+	/* Buffer Queues */
+	struct ivtv_queue q_free;	/* free buffers */
+	struct ivtv_queue q_full;	/* full buffers */
+	struct ivtv_queue q_io;		/* waiting for I/O */
+	struct ivtv_queue q_dma;	/* waiting for DMA */
+	struct ivtv_queue q_predma;	/* waiting for DMA */
+
+	/* DMA xfer counter, buffers belonging to the same DMA
+	   xfer will have the same dma_xfer_cnt. */
+	u16 dma_xfer_cnt;
+
+	/* Base Dev SG Array for cx23415/6 */
+	struct ivtv_sg_host_element *sg_pending;
+	struct ivtv_sg_host_element *sg_processing;
+	struct ivtv_sg_element *sg_dma;
+	dma_addr_t sg_handle;
+	int sg_pending_size;
+	int sg_processing_size;
+	int sg_processed;
+
+	/* SG List of Buffers */
+	struct scatterlist *SGlist;
+};
+
+struct ivtv_open_id {
+	struct v4l2_fh fh;
+	int type;                       /* stream type */
+	int yuv_frames;                 /* 1: started OUT_UDMA_YUV output mode */
+	struct ivtv *itv;
+};
+
+static inline struct ivtv_open_id *fh2id(struct v4l2_fh *fh)
+{
+	return container_of(fh, struct ivtv_open_id, fh);
+}
+
+struct yuv_frame_info
+{
+	u32 update;
+	s32 src_x;
+	s32 src_y;
+	u32 src_w;
+	u32 src_h;
+	s32 dst_x;
+	s32 dst_y;
+	u32 dst_w;
+	u32 dst_h;
+	s32 pan_x;
+	s32 pan_y;
+	u32 vis_w;
+	u32 vis_h;
+	u32 interlaced_y;
+	u32 interlaced_uv;
+	s32 tru_x;
+	u32 tru_w;
+	u32 tru_h;
+	u32 offset_y;
+	s32 lace_mode;
+	u32 sync_field;
+	u32 delay;
+	u32 interlaced;
+};
+
+#define IVTV_YUV_MODE_INTERLACED	0x00
+#define IVTV_YUV_MODE_PROGRESSIVE	0x01
+#define IVTV_YUV_MODE_AUTO		0x02
+#define IVTV_YUV_MODE_MASK		0x03
+
+#define IVTV_YUV_SYNC_EVEN		0x00
+#define IVTV_YUV_SYNC_ODD		0x04
+#define IVTV_YUV_SYNC_MASK		0x04
+
+#define IVTV_YUV_BUFFERS 8
+
+struct yuv_playback_info
+{
+	u32 reg_2834;
+	u32 reg_2838;
+	u32 reg_283c;
+	u32 reg_2840;
+	u32 reg_2844;
+	u32 reg_2848;
+	u32 reg_2854;
+	u32 reg_285c;
+	u32 reg_2864;
+
+	u32 reg_2870;
+	u32 reg_2874;
+	u32 reg_2890;
+	u32 reg_2898;
+	u32 reg_289c;
+
+	u32 reg_2918;
+	u32 reg_291c;
+	u32 reg_2920;
+	u32 reg_2924;
+	u32 reg_2928;
+	u32 reg_292c;
+	u32 reg_2930;
+
+	u32 reg_2934;
+
+	u32 reg_2938;
+	u32 reg_293c;
+	u32 reg_2940;
+	u32 reg_2944;
+	u32 reg_2948;
+	u32 reg_294c;
+	u32 reg_2950;
+	u32 reg_2954;
+	u32 reg_2958;
+	u32 reg_295c;
+	u32 reg_2960;
+	u32 reg_2964;
+	u32 reg_2968;
+	u32 reg_296c;
+
+	u32 reg_2970;
+
+	int v_filter_1;
+	int v_filter_2;
+	int h_filter;
+
+	u8 track_osd; /* Should yuv output track the OSD size & position */
+
+	u32 osd_x_offset;
+	u32 osd_y_offset;
+
+	u32 osd_x_pan;
+	u32 osd_y_pan;
+
+	u32 osd_vis_w;
+	u32 osd_vis_h;
+
+	u32 osd_full_w;
+	u32 osd_full_h;
+
+	int decode_height;
+
+	int lace_mode;
+	int lace_threshold;
+	int lace_sync_field;
+
+	atomic_t next_dma_frame;
+	atomic_t next_fill_frame;
+
+	u32 yuv_forced_update;
+	int update_frame;
+
+	u8 fields_lapsed;   /* Counter used when delaying a frame */
+
+	struct yuv_frame_info new_frame_info[IVTV_YUV_BUFFERS];
+	struct yuv_frame_info old_frame_info;
+	struct yuv_frame_info old_frame_info_args;
+
+	void *blanking_ptr;
+	dma_addr_t blanking_dmaptr;
+
+	int stream_size;
+
+	u8 draw_frame; /* PVR350 buffer to draw into */
+	u8 max_frames_buffered; /* Maximum number of frames to buffer */
+
+	struct v4l2_rect main_rect;
+	u32 v4l2_src_w;
+	u32 v4l2_src_h;
+
+	u8 running; /* Have any frames been displayed */
+};
+
+#define IVTV_VBI_FRAMES 32
+
+/* VBI data */
+struct vbi_cc {
+	u8 odd[2];	/* two-byte payload of odd field */
+	u8 even[2];	/* two-byte payload of even field */;
+};
+
+struct vbi_vps {
+	u8 data[5];	/* five-byte VPS payload */
+};
+
+struct vbi_info {
+	/* VBI general data, does not change during streaming */
+
+	u32 raw_decoder_line_size;              /* raw VBI line size from digitizer */
+	u8 raw_decoder_sav_odd_field;           /* raw VBI Start Active Video digitizer code of odd field */
+	u8 raw_decoder_sav_even_field;          /* raw VBI Start Active Video digitizer code of even field */
+	u32 sliced_decoder_line_size;           /* sliced VBI line size from digitizer */
+	u8 sliced_decoder_sav_odd_field;        /* sliced VBI Start Active Video digitizer code of odd field */
+	u8 sliced_decoder_sav_even_field;       /* sliced VBI Start Active Video digitizer code of even field */
+
+	u32 start[2];				/* start of first VBI line in the odd/even fields */
+	u32 count;				/* number of VBI lines per field */
+	u32 raw_size;				/* size of raw VBI line from the digitizer */
+	u32 sliced_size;			/* size of sliced VBI line from the digitizer */
+
+	u32 dec_start;				/* start in decoder memory of VBI re-insertion buffers */
+	u32 enc_start;				/* start in encoder memory of VBI capture buffers */
+	u32 enc_size;				/* size of VBI capture area */
+	int fpi;				/* number of VBI frames per interrupt */
+
+	struct v4l2_format in;			/* current VBI capture format */
+	struct v4l2_sliced_vbi_format *sliced_in; /* convenience pointer to sliced struct in vbi.in union */
+	int insert_mpeg;			/* if non-zero, then embed VBI data in MPEG stream */
+
+	/* Raw VBI compatibility hack */
+
+	u32 frame; 				/* frame counter hack needed for backwards compatibility
+						   of old VBI software */
+
+	/* Sliced VBI output data */
+
+	struct vbi_cc cc_payload[256];		/* sliced VBI CC payload array: it is an array to
+						   prevent dropping CC data if they couldn't be
+						   processed fast enough */
+	int cc_payload_idx;			/* index in cc_payload */
+	u8 cc_missing_cnt;			/* counts number of frames without CC for passthrough mode */
+	int wss_payload;			/* sliced VBI WSS payload */
+	u8 wss_missing_cnt;			/* counts number of frames without WSS for passthrough mode */
+	struct vbi_vps vps_payload;		/* sliced VBI VPS payload */
+
+	/* Sliced VBI capture data */
+
+	struct v4l2_sliced_vbi_data sliced_data[36];	/* sliced VBI storage for VBI encoder stream */
+	struct v4l2_sliced_vbi_data sliced_dec_data[36];/* sliced VBI storage for VBI decoder stream */
+
+	/* VBI Embedding data */
+
+	/* 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. */
+	u8 *sliced_mpeg_data[IVTV_VBI_FRAMES];
+	u32 sliced_mpeg_size[IVTV_VBI_FRAMES];
+	struct ivtv_buffer sliced_mpeg_buf;	/* temporary buffer holding data from sliced_mpeg_data */
+	u32 inserted_frame;			/* index in sliced_mpeg_size of next sliced data
+						   to be inserted in the MPEG stream */
+};
+
+/* forward declaration of struct defined in ivtv-cards.h */
+struct ivtv_card;
+
+/* Struct to hold info about ivtv cards */
+struct ivtv {
+	/* General fixed card data */
+	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 */
+	u8 has_cx23415;			/* 1 if it is a cx23415 based card, 0 for cx23416 */
+	u8 pvr150_workaround;           /* 1 if the cx25840 needs to workaround a PVR150 bug */
+	u8 nof_inputs;			/* number of video inputs */
+	u8 nof_audio_inputs;		/* number of audio inputs */
+	u32 v4l2_cap;			/* V4L2 capabilities of card */
+	u32 hw_flags; 			/* hardware description of the board */
+	v4l2_std_id tuner_std;		/* the norm of the card's tuner (fixed) */
+	struct v4l2_subdev *sd_video;	/* controlling video decoder subdev */
+	struct v4l2_subdev *sd_audio;	/* controlling audio subdev */
+	struct v4l2_subdev *sd_muxer;	/* controlling audio muxer subdev */
+	resource_size_t base_addr;      /* PCI resource base address */
+	volatile void __iomem *enc_mem; /* pointer to mapped encoder memory */
+	volatile void __iomem *dec_mem; /* pointer to mapped decoder memory */
+	volatile void __iomem *reg_mem; /* pointer to mapped registers */
+	struct ivtv_options options; 	/* user options */
+
+	struct v4l2_device v4l2_dev;
+	struct cx2341x_handler cxhdl;
+	struct {
+		/* PTS/Frame count control cluster */
+		struct v4l2_ctrl *ctrl_pts;
+		struct v4l2_ctrl *ctrl_frame;
+	};
+	struct {
+		/* Audio Playback control cluster */
+		struct v4l2_ctrl *ctrl_audio_playback;
+		struct v4l2_ctrl *ctrl_audio_multilingual_playback;
+	};
+	struct v4l2_ctrl_handler hdl_gpio;
+	struct v4l2_subdev sd_gpio;	/* GPIO sub-device */
+	u16 instance;
+
+	/* High-level state info */
+	unsigned long i_flags;          /* global ivtv flags */
+	u8 is_50hz;                     /* 1 if the current capture standard is 50 Hz */
+	u8 is_60hz                      /* 1 if the current capture standard is 60 Hz */;
+	u8 is_out_50hz                  /* 1 if the current TV output standard is 50 Hz */;
+	u8 is_out_60hz                  /* 1 if the current TV output standard is 60 Hz */;
+	int output_mode;                /* decoder output mode: NONE, MPG, YUV, UDMA YUV, passthrough */
+	u32 audio_input;                /* current audio input */
+	u32 active_input;               /* current video input */
+	u32 active_output;              /* current video output */
+	v4l2_std_id std;                /* current capture TV standard */
+	v4l2_std_id std_out;            /* current TV output standard */
+	u8 audio_stereo_mode;           /* decoder setting how to handle stereo MPEG audio */
+	u8 audio_bilingual_mode;        /* decoder setting how to handle bilingual MPEG audio */
+
+	/* Locking */
+	spinlock_t lock;                /* lock access to this struct */
+	struct mutex serialize_lock;    /* mutex used to serialize open/close/start/stop/ioctl operations */
+
+	/* Streams */
+	int stream_buf_size[IVTV_MAX_STREAMS];          /* stream buffer size */
+	struct ivtv_stream streams[IVTV_MAX_STREAMS]; 	/* stream data */
+	atomic_t capturing;		/* count number of active capture streams */
+	atomic_t decoding;		/* count number of active decoding streams */
+
+	/* ALSA interface for PCM capture stream */
+	struct snd_ivtv_card *alsa;
+	void (*pcm_announce_callback)(struct snd_ivtv_card *card, u8 *pcm_data,
+				      size_t num_bytes);
+
+	/* Used for ivtv-alsa module loading */
+	struct work_struct request_module_wk;
+
+	/* Interrupts & DMA */
+	u32 irqmask;                    /* active interrupts */
+	u32 irq_rr_idx;                 /* round-robin stream index */
+	struct kthread_worker irq_worker;		/* kthread worker for PIO/YUV/VBI actions */
+	struct task_struct *irq_worker_task;		/* task for irq_worker */
+	struct kthread_work irq_work;	/* kthread work entry */
+	spinlock_t dma_reg_lock;        /* lock access to DMA engine registers */
+	int cur_dma_stream;		/* index of current stream doing DMA (-1 if none) */
+	int cur_pio_stream;		/* index of current stream doing PIO (-1 if none) */
+	u32 dma_data_req_offset;        /* store offset in decoder memory of current DMA request */
+	u32 dma_data_req_size;          /* store size of current DMA request */
+	int dma_retries;                /* current DMA retry attempt */
+	struct ivtv_user_dma udma;      /* user based DMA for OSD */
+	struct timer_list dma_timer;    /* timer used to catch unfinished DMAs */
+	u32 last_vsync_field;           /* last seen vsync field */
+	wait_queue_head_t dma_waitq;    /* wake up when the current DMA is finished */
+	wait_queue_head_t eos_waitq;    /* wake up when EOS arrives */
+	wait_queue_head_t event_waitq;  /* wake up when the next decoder event arrives */
+	wait_queue_head_t vsync_waitq;  /* wake up when the next decoder vsync arrives */
+
+
+	/* Mailbox */
+	struct ivtv_mailbox_data enc_mbox;              /* encoder mailboxes */
+	struct ivtv_mailbox_data dec_mbox;              /* decoder mailboxes */
+	struct ivtv_api_cache api_cache[256]; 		/* cached API commands */
+
+
+	/* I2C */
+	struct i2c_adapter i2c_adap;
+	struct i2c_algo_bit_data i2c_algo;
+	struct i2c_client i2c_client;
+	int i2c_state;                  /* i2c bit state */
+	struct mutex i2c_bus_lock;      /* lock i2c bus */
+
+	struct IR_i2c_init_data ir_i2c_init_data;
+
+	/* Program Index information */
+	u32 pgm_info_offset;            /* start of pgm info in encoder memory */
+	u32 pgm_info_num;               /* number of elements in the pgm cyclic buffer in encoder memory */
+	u32 pgm_info_write_idx;         /* last index written by the card that was transferred to pgm_info[] */
+	u32 pgm_info_read_idx;          /* last index in pgm_info read by the application */
+	struct v4l2_enc_idx_entry pgm_info[IVTV_MAX_PGM_INDEX]; /* filled from the pgm cyclic buffer on the card */
+
+
+	/* Miscellaneous */
+	u32 open_id;			/* incremented each time an open occurs, is >= 1 */
+	int search_pack_header;         /* 1 if ivtv_copy_buf_to_user() is scanning for a pack header (0xba) */
+	int speed;                      /* current playback speed setting */
+	u8 speed_mute_audio;            /* 1 if audio should be muted when fast forward */
+	u64 mpg_data_received;          /* number of bytes received from the MPEG stream */
+	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 */
+	u32 dualwatch_stereo_mode;      /* current detected dualwatch stereo mode */
+
+
+	/* VBI state info */
+	struct vbi_info vbi;            /* VBI-specific data */
+
+
+	/* YUV playback */
+	struct yuv_playback_info yuv_info;              /* YUV playback data */
+
+
+	/* OSD support */
+	unsigned long osd_video_pbase;
+	int osd_global_alpha_state;     /* 1 = global alpha is on */
+	int osd_local_alpha_state;      /* 1 = local alpha is on */
+	int osd_chroma_key_state;       /* 1 = chroma-keying is on */
+	u8  osd_global_alpha;           /* current global alpha */
+	u32 osd_chroma_key;             /* current chroma key */
+	struct v4l2_rect osd_rect;      /* current OSD position and size */
+	struct v4l2_rect main_rect;     /* current Main window position and size */
+	struct osd_info *osd_info;      /* ivtvfb private OSD info */
+	void (*ivtvfb_restore)(struct ivtv *itv); /* Used for a warm start */
+};
+
+static inline struct ivtv *to_ivtv(struct v4l2_device *v4l2_dev)
+{
+	return container_of(v4l2_dev, struct ivtv, v4l2_dev);
+}
+
+/* ivtv extensions to be loaded */
+extern int (*ivtv_ext_init)(struct ivtv *);
+
+/* Globals */
+extern int ivtv_first_minor;
+
+/*==============Prototypes==================*/
+
+/* Hardware/IRQ */
+void ivtv_set_irq_mask(struct ivtv *itv, u32 mask);
+void ivtv_clear_irq_mask(struct ivtv *itv, u32 mask);
+
+/* try to set output mode, return current mode. */
+int ivtv_set_output_mode(struct ivtv *itv, int mode);
+
+/* return current output stream based on current mode */
+struct ivtv_stream *ivtv_get_output_stream(struct ivtv *itv);
+
+/* Return non-zero if a signal is pending */
+int ivtv_msleep_timeout(unsigned int msecs, int intr);
+
+/* Wait on queue, returns -EINTR if interrupted */
+int ivtv_waitq(wait_queue_head_t *waitq);
+
+/* Read Hauppauge eeprom */
+struct tveeprom; /* forward reference */
+void ivtv_read_eeprom(struct ivtv *itv, struct tveeprom *tv);
+
+/* First-open initialization: load firmware, init cx25840, etc. */
+int ivtv_init_on_first_open(struct ivtv *itv);
+
+/* Test if the current VBI mode is raw (1) or sliced (0) */
+static inline int ivtv_raw_vbi(const struct ivtv *itv)
+{
+	return itv->vbi.in.type == V4L2_BUF_TYPE_VBI_CAPTURE;
+}
+
+/* This is a PCI post thing, where if the pci register is not read, then
+   the write doesn't always take effect right away. By reading back the
+   register any pending PCI writes will be performed (in order), and so
+   you can be sure that the writes are guaranteed to be done.
+
+   Rarely needed, only in some timing sensitive cases.
+   Apparently if this is not done some motherboards seem
+   to kill the firmware and get into the broken state until computer is
+   rebooted. */
+#define write_sync(val, reg) \
+	do { writel(val, reg); readl(reg); } while (0)
+
+#define read_reg(reg) readl(itv->reg_mem + (reg))
+#define write_reg(val, reg) writel(val, itv->reg_mem + (reg))
+#define write_reg_sync(val, reg) \
+	do { write_reg(val, reg); read_reg(reg); } while (0)
+
+#define read_enc(addr) readl(itv->enc_mem + (u32)(addr))
+#define write_enc(val, addr) writel(val, itv->enc_mem + (u32)(addr))
+#define write_enc_sync(val, addr) \
+	do { write_enc(val, addr); read_enc(addr); } while (0)
+
+#define read_dec(addr) readl(itv->dec_mem + (u32)(addr))
+#define write_dec(val, addr) writel(val, itv->dec_mem + (u32)(addr))
+#define write_dec_sync(val, addr) \
+	do { write_dec(val, addr); read_dec(addr); } while (0)
+
+/* 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...) 				\
+	do {								\
+		struct v4l2_subdev *__sd;				\
+		__v4l2_device_call_subdevs_p(&(itv)->v4l2_dev, __sd,	\
+			!(hw) || (__sd->grp_id & (hw)), o, f , ##args);	\
+	} while (0)
+
+#define ivtv_call_all(itv, o, f, args...) ivtv_call_hw(itv, 0, o, f , ##args)
+
+/* Call the specified callback for all subdevs matching 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 ivtv_call_hw_err(itv, hw, o, f, args...)			\
+({									\
+	struct v4l2_subdev *__sd;					\
+	__v4l2_device_call_subdevs_until_err_p(&(itv)->v4l2_dev, __sd,	\
+		!(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)
+
+#endif
diff --git a/drivers/media/pci/ivtv/ivtv-fileops.c b/drivers/media/pci/ivtv/ivtv-fileops.c
new file mode 100644
index 0000000..7f2eb5f
--- /dev/null
+++ b/drivers/media/pci/ivtv/ivtv-fileops.c
@@ -0,0 +1,1072 @@
+/*
+    file operation functions
+    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
+    Copyright (C) 2004  Chris Kennedy <c@groovy.org>
+    Copyright (C) 2005-2007  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "ivtv-driver.h"
+#include "ivtv-fileops.h"
+#include "ivtv-i2c.h"
+#include "ivtv-queue.h"
+#include "ivtv-udma.h"
+#include "ivtv-irq.h"
+#include "ivtv-vbi.h"
+#include "ivtv-mailbox.h"
+#include "ivtv-routing.h"
+#include "ivtv-streams.h"
+#include "ivtv-yuv.h"
+#include "ivtv-ioctl.h"
+#include "ivtv-cards.h"
+#include "ivtv-firmware.h"
+#include <media/v4l2-event.h>
+#include <media/saa7115.h>
+
+/* This function tries to claim the stream for a specific file descriptor.
+   If no one else is using this stream then the stream is claimed and
+   associated VBI streams are also automatically claimed.
+   Possible error returns: -EBUSY if someone else has claimed
+   the stream or 0 on success. */
+int ivtv_claim_stream(struct ivtv_open_id *id, int type)
+{
+	struct ivtv *itv = id->itv;
+	struct ivtv_stream *s = &itv->streams[type];
+	struct ivtv_stream *s_vbi;
+	int vbi_type;
+
+	if (test_and_set_bit(IVTV_F_S_CLAIMED, &s->s_flags)) {
+		/* someone already claimed this stream */
+		if (s->fh == &id->fh) {
+			/* yes, this file descriptor did. So that's OK. */
+			return 0;
+		}
+		if (s->fh == NULL && (type == IVTV_DEC_STREAM_TYPE_VBI ||
+					 type == IVTV_ENC_STREAM_TYPE_VBI)) {
+			/* VBI is handled already internally, now also assign
+			   the file descriptor to this stream for external
+			   reading of the stream. */
+			s->fh = &id->fh;
+			IVTV_DEBUG_INFO("Start Read VBI\n");
+			return 0;
+		}
+		/* someone else is using this stream already */
+		IVTV_DEBUG_INFO("Stream %d is busy\n", type);
+		return -EBUSY;
+	}
+	s->fh = &id->fh;
+	if (type == IVTV_DEC_STREAM_TYPE_VBI) {
+		/* Enable reinsertion interrupt */
+		ivtv_clear_irq_mask(itv, IVTV_IRQ_DEC_VBI_RE_INSERT);
+	}
+
+	/* IVTV_DEC_STREAM_TYPE_MPG needs to claim IVTV_DEC_STREAM_TYPE_VBI,
+	   IVTV_ENC_STREAM_TYPE_MPG needs to claim IVTV_ENC_STREAM_TYPE_VBI
+	   (provided VBI insertion is on and sliced VBI is selected), for all
+	   other streams we're done */
+	if (type == IVTV_DEC_STREAM_TYPE_MPG) {
+		vbi_type = IVTV_DEC_STREAM_TYPE_VBI;
+	} else if (type == IVTV_ENC_STREAM_TYPE_MPG &&
+		   itv->vbi.insert_mpeg && !ivtv_raw_vbi(itv)) {
+		vbi_type = IVTV_ENC_STREAM_TYPE_VBI;
+	} else {
+		return 0;
+	}
+	s_vbi = &itv->streams[vbi_type];
+
+	if (!test_and_set_bit(IVTV_F_S_CLAIMED, &s_vbi->s_flags)) {
+		/* Enable reinsertion interrupt */
+		if (vbi_type == IVTV_DEC_STREAM_TYPE_VBI)
+			ivtv_clear_irq_mask(itv, IVTV_IRQ_DEC_VBI_RE_INSERT);
+	}
+	/* mark that it is used internally */
+	set_bit(IVTV_F_S_INTERNAL_USE, &s_vbi->s_flags);
+	return 0;
+}
+EXPORT_SYMBOL(ivtv_claim_stream);
+
+/* This function releases a previously claimed stream. It will take into
+   account associated VBI streams. */
+void ivtv_release_stream(struct ivtv_stream *s)
+{
+	struct ivtv *itv = s->itv;
+	struct ivtv_stream *s_vbi;
+
+	s->fh = NULL;
+	if ((s->type == IVTV_DEC_STREAM_TYPE_VBI || s->type == IVTV_ENC_STREAM_TYPE_VBI) &&
+		test_bit(IVTV_F_S_INTERNAL_USE, &s->s_flags)) {
+		/* this stream is still in use internally */
+		return;
+	}
+	if (!test_and_clear_bit(IVTV_F_S_CLAIMED, &s->s_flags)) {
+		IVTV_DEBUG_WARN("Release stream %s not in use!\n", s->name);
+		return;
+	}
+
+	ivtv_flush_queues(s);
+
+	/* disable reinsertion interrupt */
+	if (s->type == IVTV_DEC_STREAM_TYPE_VBI)
+		ivtv_set_irq_mask(itv, IVTV_IRQ_DEC_VBI_RE_INSERT);
+
+	/* IVTV_DEC_STREAM_TYPE_MPG needs to release IVTV_DEC_STREAM_TYPE_VBI,
+	   IVTV_ENC_STREAM_TYPE_MPG needs to release IVTV_ENC_STREAM_TYPE_VBI,
+	   for all other streams we're done */
+	if (s->type == IVTV_DEC_STREAM_TYPE_MPG)
+		s_vbi = &itv->streams[IVTV_DEC_STREAM_TYPE_VBI];
+	else if (s->type == IVTV_ENC_STREAM_TYPE_MPG)
+		s_vbi = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI];
+	else
+		return;
+
+	/* clear internal use flag */
+	if (!test_and_clear_bit(IVTV_F_S_INTERNAL_USE, &s_vbi->s_flags)) {
+		/* was already cleared */
+		return;
+	}
+	if (s_vbi->fh) {
+		/* VBI stream still claimed by a file descriptor */
+		return;
+	}
+	/* disable reinsertion interrupt */
+	if (s_vbi->type == IVTV_DEC_STREAM_TYPE_VBI)
+		ivtv_set_irq_mask(itv, IVTV_IRQ_DEC_VBI_RE_INSERT);
+	clear_bit(IVTV_F_S_CLAIMED, &s_vbi->s_flags);
+	ivtv_flush_queues(s_vbi);
+}
+EXPORT_SYMBOL(ivtv_release_stream);
+
+static void ivtv_dualwatch(struct ivtv *itv)
+{
+	struct v4l2_tuner vt;
+	u32 new_stereo_mode;
+	const u32 dual = 0x02;
+
+	new_stereo_mode = v4l2_ctrl_g_ctrl(itv->cxhdl.audio_mode);
+	memset(&vt, 0, sizeof(vt));
+	ivtv_call_all(itv, tuner, g_tuner, &vt);
+	if (vt.audmode == V4L2_TUNER_MODE_LANG1_LANG2 && (vt.rxsubchans & V4L2_TUNER_SUB_LANG2))
+		new_stereo_mode = dual;
+
+	if (new_stereo_mode == itv->dualwatch_stereo_mode)
+		return;
+
+	IVTV_DEBUG_INFO("dualwatch: change stereo flag from 0x%x to 0x%x.\n",
+			   itv->dualwatch_stereo_mode, new_stereo_mode);
+	if (v4l2_ctrl_s_ctrl(itv->cxhdl.audio_mode, new_stereo_mode))
+		IVTV_DEBUG_INFO("dualwatch: changing stereo flag failed\n");
+}
+
+static void ivtv_update_pgm_info(struct ivtv *itv)
+{
+	u32 wr_idx = (read_enc(itv->pgm_info_offset) - itv->pgm_info_offset - 4) / 24;
+	int cnt;
+	int i = 0;
+
+	if (wr_idx >= itv->pgm_info_num) {
+		IVTV_DEBUG_WARN("Invalid PGM index %d (>= %d)\n", wr_idx, itv->pgm_info_num);
+		return;
+	}
+	cnt = (wr_idx + itv->pgm_info_num - itv->pgm_info_write_idx) % itv->pgm_info_num;
+	while (i < cnt) {
+		int idx = (itv->pgm_info_write_idx + i) % itv->pgm_info_num;
+		struct v4l2_enc_idx_entry *e = itv->pgm_info + idx;
+		u32 addr = itv->pgm_info_offset + 4 + idx * 24;
+		const int mapping[8] = { -1, V4L2_ENC_IDX_FRAME_I, V4L2_ENC_IDX_FRAME_P, -1,
+			V4L2_ENC_IDX_FRAME_B, -1, -1, -1 };
+					// 1=I, 2=P, 4=B
+
+		e->offset = read_enc(addr + 4) + ((u64)read_enc(addr + 8) << 32);
+		if (e->offset > itv->mpg_data_received) {
+			break;
+		}
+		e->offset += itv->vbi_data_inserted;
+		e->length = read_enc(addr);
+		e->pts = read_enc(addr + 16) + ((u64)(read_enc(addr + 20) & 1) << 32);
+		e->flags = mapping[read_enc(addr + 12) & 7];
+		i++;
+	}
+	itv->pgm_info_write_idx = (itv->pgm_info_write_idx + i) % itv->pgm_info_num;
+}
+
+static struct ivtv_buffer *ivtv_get_buffer(struct ivtv_stream *s, int non_block, int *err)
+{
+	struct ivtv *itv = s->itv;
+	struct ivtv_stream *s_vbi = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI];
+	struct ivtv_buffer *buf;
+	DEFINE_WAIT(wait);
+
+	*err = 0;
+	while (1) {
+		if (s->type == IVTV_ENC_STREAM_TYPE_MPG) {
+			/* Process pending program info updates and pending VBI data */
+			ivtv_update_pgm_info(itv);
+
+			if (time_after(jiffies,
+				       itv->dualwatch_jiffies +
+				       msecs_to_jiffies(1000))) {
+				itv->dualwatch_jiffies = jiffies;
+				ivtv_dualwatch(itv);
+			}
+
+			if (test_bit(IVTV_F_S_INTERNAL_USE, &s_vbi->s_flags) &&
+			    !test_bit(IVTV_F_S_APPL_IO, &s_vbi->s_flags)) {
+				while ((buf = ivtv_dequeue(s_vbi, &s_vbi->q_full))) {
+					/* byteswap and process VBI data */
+					ivtv_process_vbi_data(itv, buf, s_vbi->dma_pts, s_vbi->type);
+					ivtv_enqueue(s_vbi, buf, &s_vbi->q_free);
+				}
+			}
+			buf = &itv->vbi.sliced_mpeg_buf;
+			if (buf->readpos != buf->bytesused) {
+				return buf;
+			}
+		}
+
+		/* do we have leftover data? */
+		buf = ivtv_dequeue(s, &s->q_io);
+		if (buf)
+			return buf;
+
+		/* do we have new data? */
+		buf = ivtv_dequeue(s, &s->q_full);
+		if (buf) {
+			if ((buf->b_flags & IVTV_F_B_NEED_BUF_SWAP) == 0)
+				return buf;
+			buf->b_flags &= ~IVTV_F_B_NEED_BUF_SWAP;
+			if (s->type == IVTV_ENC_STREAM_TYPE_MPG)
+				/* byteswap MPG data */
+				ivtv_buf_swap(buf);
+			else if (s->type != IVTV_DEC_STREAM_TYPE_VBI) {
+				/* byteswap and process VBI data */
+				ivtv_process_vbi_data(itv, buf, s->dma_pts, s->type);
+			}
+			return buf;
+		}
+
+		/* return if end of stream */
+		if (s->type != IVTV_DEC_STREAM_TYPE_VBI && !test_bit(IVTV_F_S_STREAMING, &s->s_flags)) {
+			IVTV_DEBUG_INFO("EOS %s\n", s->name);
+			return NULL;
+		}
+
+		/* return if file was opened with O_NONBLOCK */
+		if (non_block) {
+			*err = -EAGAIN;
+			return NULL;
+		}
+
+		/* wait for more data to arrive */
+		mutex_unlock(&itv->serialize_lock);
+		prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE);
+		/* New buffers might have become available before we were added to the waitqueue */
+		if (!s->q_full.buffers)
+			schedule();
+		finish_wait(&s->waitq, &wait);
+		mutex_lock(&itv->serialize_lock);
+		if (signal_pending(current)) {
+			/* return if a signal was received */
+			IVTV_DEBUG_INFO("User stopped %s\n", s->name);
+			*err = -EINTR;
+			return NULL;
+		}
+	}
+}
+
+static void ivtv_setup_sliced_vbi_buf(struct ivtv *itv)
+{
+	int idx = itv->vbi.inserted_frame % IVTV_VBI_FRAMES;
+
+	itv->vbi.sliced_mpeg_buf.buf = itv->vbi.sliced_mpeg_data[idx];
+	itv->vbi.sliced_mpeg_buf.bytesused = itv->vbi.sliced_mpeg_size[idx];
+	itv->vbi.sliced_mpeg_buf.readpos = 0;
+}
+
+static size_t ivtv_copy_buf_to_user(struct ivtv_stream *s, struct ivtv_buffer *buf,
+		char __user *ubuf, size_t ucount)
+{
+	struct ivtv *itv = s->itv;
+	size_t len = buf->bytesused - buf->readpos;
+
+	if (len > ucount) len = ucount;
+	if (itv->vbi.insert_mpeg && s->type == IVTV_ENC_STREAM_TYPE_MPG &&
+	    !ivtv_raw_vbi(itv) && buf != &itv->vbi.sliced_mpeg_buf) {
+		const char *start = buf->buf + buf->readpos;
+		const char *p = start + 1;
+		const u8 *q;
+		u8 ch = itv->search_pack_header ? 0xba : 0xe0;
+		int stuffing, i;
+
+		while (start + len > p && (q = memchr(p, 0, start + len - p))) {
+			p = q + 1;
+			if ((char *)q + 15 >= buf->buf + buf->bytesused ||
+			    q[1] != 0 || q[2] != 1 || q[3] != ch) {
+				continue;
+			}
+			if (!itv->search_pack_header) {
+				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;
+					itv->search_pack_header = 1;
+					p = q + 9;
+				}
+				continue;
+			}
+			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 && q[15 + stuffing] == 0 &&
+					q[16 + stuffing] == 1) {
+				itv->search_pack_header = 0;
+				len = (char *)q - start;
+				ivtv_setup_sliced_vbi_buf(itv);
+				break;
+			}
+		}
+	}
+	if (copy_to_user(ubuf, (u8 *)buf->buf + buf->readpos, len)) {
+		IVTV_DEBUG_WARN("copy %zd bytes to user failed for %s\n", len, s->name);
+		return -EFAULT;
+	}
+	/*IVTV_INFO("copied %lld %d %d %d %d %d vbi %d\n", itv->mpg_data_received, len, ucount,
+			buf->readpos, buf->bytesused, buf->bytesused - buf->readpos - len,
+			buf == &itv->vbi.sliced_mpeg_buf); */
+	buf->readpos += len;
+	if (s->type == IVTV_ENC_STREAM_TYPE_MPG && buf != &itv->vbi.sliced_mpeg_buf)
+		itv->mpg_data_received += len;
+	return len;
+}
+
+static ssize_t ivtv_read(struct ivtv_stream *s, char __user *ubuf, size_t tot_count, int non_block)
+{
+	struct ivtv *itv = s->itv;
+	size_t tot_written = 0;
+	int single_frame = 0;
+
+	if (atomic_read(&itv->capturing) == 0 && s->fh == NULL) {
+		/* shouldn't happen */
+		IVTV_DEBUG_WARN("Stream %s not initialized before read\n", s->name);
+		return -EIO;
+	}
+
+	/* Each VBI buffer is one frame, the v4l2 API says that for VBI the frames should
+	   arrive one-by-one, so make sure we never output more than one VBI frame at a time */
+	if (s->type == IVTV_DEC_STREAM_TYPE_VBI ||
+	    (s->type == IVTV_ENC_STREAM_TYPE_VBI && !ivtv_raw_vbi(itv)))
+		single_frame = 1;
+
+	for (;;) {
+		struct ivtv_buffer *buf;
+		int rc;
+
+		buf = ivtv_get_buffer(s, non_block, &rc);
+		/* if there is no data available... */
+		if (buf == NULL) {
+			/* if we got data, then return that regardless */
+			if (tot_written)
+				break;
+			/* EOS condition */
+			if (rc == 0) {
+				clear_bit(IVTV_F_S_STREAMOFF, &s->s_flags);
+				clear_bit(IVTV_F_S_APPL_IO, &s->s_flags);
+				ivtv_release_stream(s);
+			}
+			/* set errno */
+			return rc;
+		}
+		rc = ivtv_copy_buf_to_user(s, buf, ubuf + tot_written, tot_count - tot_written);
+		if (buf != &itv->vbi.sliced_mpeg_buf) {
+			ivtv_enqueue(s, buf, (buf->readpos == buf->bytesused) ? &s->q_free : &s->q_io);
+		}
+		else if (buf->readpos == buf->bytesused) {
+			int idx = itv->vbi.inserted_frame % IVTV_VBI_FRAMES;
+			itv->vbi.sliced_mpeg_size[idx] = 0;
+			itv->vbi.inserted_frame++;
+			itv->vbi_data_inserted += buf->bytesused;
+		}
+		if (rc < 0)
+			return rc;
+		tot_written += rc;
+
+		if (tot_written == tot_count || single_frame)
+			break;
+	}
+	return tot_written;
+}
+
+static ssize_t ivtv_read_pos(struct ivtv_stream *s, char __user *ubuf, size_t count,
+			loff_t *pos, int non_block)
+{
+	ssize_t rc = count ? ivtv_read(s, ubuf, count, non_block) : 0;
+	struct ivtv *itv = s->itv;
+
+	IVTV_DEBUG_HI_FILE("read %zd from %s, got %zd\n", count, s->name, rc);
+	if (rc > 0)
+		pos += rc;
+	return rc;
+}
+
+int ivtv_start_capture(struct ivtv_open_id *id)
+{
+	struct ivtv *itv = id->itv;
+	struct ivtv_stream *s = &itv->streams[id->type];
+	struct ivtv_stream *s_vbi;
+
+	if (s->type == IVTV_ENC_STREAM_TYPE_RAD ||
+	    s->type == IVTV_DEC_STREAM_TYPE_MPG ||
+	    s->type == IVTV_DEC_STREAM_TYPE_YUV ||
+	    s->type == IVTV_DEC_STREAM_TYPE_VOUT) {
+		/* you cannot read from these stream types. */
+		return -EPERM;
+	}
+
+	/* Try to claim this stream. */
+	if (ivtv_claim_stream(id, s->type))
+		return -EBUSY;
+
+	/* This stream does not need to start capturing */
+	if (s->type == IVTV_DEC_STREAM_TYPE_VBI) {
+		set_bit(IVTV_F_S_APPL_IO, &s->s_flags);
+		return 0;
+	}
+
+	/* If capture is already in progress, then we also have to
+	   do nothing extra. */
+	if (test_bit(IVTV_F_S_STREAMOFF, &s->s_flags) || test_and_set_bit(IVTV_F_S_STREAMING, &s->s_flags)) {
+		set_bit(IVTV_F_S_APPL_IO, &s->s_flags);
+		return 0;
+	}
+
+	/* Start VBI capture if required */
+	s_vbi = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI];
+	if (s->type == IVTV_ENC_STREAM_TYPE_MPG &&
+	    test_bit(IVTV_F_S_INTERNAL_USE, &s_vbi->s_flags) &&
+	    !test_and_set_bit(IVTV_F_S_STREAMING, &s_vbi->s_flags)) {
+		/* Note: the IVTV_ENC_STREAM_TYPE_VBI is claimed
+		   automatically when the MPG stream is claimed.
+		   We only need to start the VBI capturing. */
+		if (ivtv_start_v4l2_encode_stream(s_vbi)) {
+			IVTV_DEBUG_WARN("VBI capture start failed\n");
+
+			/* Failure, clean up and return an error */
+			clear_bit(IVTV_F_S_STREAMING, &s_vbi->s_flags);
+			clear_bit(IVTV_F_S_STREAMING, &s->s_flags);
+			/* also releases the associated VBI stream */
+			ivtv_release_stream(s);
+			return -EIO;
+		}
+		IVTV_DEBUG_INFO("VBI insertion started\n");
+	}
+
+	/* Tell the card to start capturing */
+	if (!ivtv_start_v4l2_encode_stream(s)) {
+		/* We're done */
+		set_bit(IVTV_F_S_APPL_IO, &s->s_flags);
+		/* Resume a possibly paused encoder */
+		if (test_and_clear_bit(IVTV_F_I_ENC_PAUSED, &itv->i_flags))
+			ivtv_vapi(itv, CX2341X_ENC_PAUSE_ENCODER, 1, 1);
+		return 0;
+	}
+
+	/* failure, clean up */
+	IVTV_DEBUG_WARN("Failed to start capturing for stream %s\n", s->name);
+
+	/* Note: the IVTV_ENC_STREAM_TYPE_VBI is released
+	   automatically when the MPG stream is released.
+	   We only need to stop the VBI capturing. */
+	if (s->type == IVTV_ENC_STREAM_TYPE_MPG &&
+	    test_bit(IVTV_F_S_STREAMING, &s_vbi->s_flags)) {
+		ivtv_stop_v4l2_encode_stream(s_vbi, 0);
+		clear_bit(IVTV_F_S_STREAMING, &s_vbi->s_flags);
+	}
+	clear_bit(IVTV_F_S_STREAMING, &s->s_flags);
+	ivtv_release_stream(s);
+	return -EIO;
+}
+
+ssize_t ivtv_v4l2_read(struct file * filp, char __user *buf, size_t count, loff_t * pos)
+{
+	struct ivtv_open_id *id = fh2id(filp->private_data);
+	struct ivtv *itv = id->itv;
+	struct ivtv_stream *s = &itv->streams[id->type];
+	ssize_t rc;
+
+	IVTV_DEBUG_HI_FILE("read %zd bytes from %s\n", count, s->name);
+
+	if (mutex_lock_interruptible(&itv->serialize_lock))
+		return -ERESTARTSYS;
+	rc = ivtv_start_capture(id);
+	if (!rc)
+		rc = ivtv_read_pos(s, buf, count, pos, filp->f_flags & O_NONBLOCK);
+	mutex_unlock(&itv->serialize_lock);
+	return rc;
+}
+
+int ivtv_start_decoding(struct ivtv_open_id *id, int speed)
+{
+	struct ivtv *itv = id->itv;
+	struct ivtv_stream *s = &itv->streams[id->type];
+	int rc;
+
+	if (atomic_read(&itv->decoding) == 0) {
+		if (ivtv_claim_stream(id, s->type)) {
+			/* someone else is using this stream already */
+			IVTV_DEBUG_WARN("start decode, stream already claimed\n");
+			return -EBUSY;
+		}
+		rc = ivtv_start_v4l2_decode_stream(s, 0);
+		if (rc < 0) {
+			if (rc == -EAGAIN)
+				rc = ivtv_start_v4l2_decode_stream(s, 0);
+			if (rc < 0)
+				return rc;
+		}
+	}
+	if (s->type == IVTV_DEC_STREAM_TYPE_MPG)
+		return ivtv_set_speed(itv, speed);
+	return 0;
+}
+
+static ssize_t ivtv_write(struct file *filp, const char __user *user_buf, size_t count, loff_t *pos)
+{
+	struct ivtv_open_id *id = fh2id(filp->private_data);
+	struct ivtv *itv = id->itv;
+	struct ivtv_stream *s = &itv->streams[id->type];
+	struct yuv_playback_info *yi = &itv->yuv_info;
+	struct ivtv_buffer *buf;
+	struct ivtv_queue q;
+	int bytes_written = 0;
+	int mode;
+	int rc;
+	DEFINE_WAIT(wait);
+
+	IVTV_DEBUG_HI_FILE("write %zd bytes to %s\n", count, s->name);
+
+	if (s->type != IVTV_DEC_STREAM_TYPE_MPG &&
+	    s->type != IVTV_DEC_STREAM_TYPE_YUV &&
+	    s->type != IVTV_DEC_STREAM_TYPE_VOUT)
+		/* not decoder streams */
+		return -EPERM;
+
+	/* Try to claim this stream */
+	if (ivtv_claim_stream(id, s->type))
+		return -EBUSY;
+
+	/* This stream does not need to start any decoding */
+	if (s->type == IVTV_DEC_STREAM_TYPE_VOUT) {
+		int elems = count / sizeof(struct v4l2_sliced_vbi_data);
+
+		set_bit(IVTV_F_S_APPL_IO, &s->s_flags);
+		return ivtv_write_vbi_from_user(itv,
+		   (const struct v4l2_sliced_vbi_data __user *)user_buf, elems);
+	}
+
+	mode = s->type == IVTV_DEC_STREAM_TYPE_MPG ? OUT_MPG : OUT_YUV;
+
+	if (ivtv_set_output_mode(itv, mode) != mode) {
+	    ivtv_release_stream(s);
+	    return -EBUSY;
+	}
+	ivtv_queue_init(&q);
+	set_bit(IVTV_F_S_APPL_IO, &s->s_flags);
+
+	/* Start decoder (returns 0 if already started) */
+	rc = ivtv_start_decoding(id, itv->speed);
+	if (rc) {
+		IVTV_DEBUG_WARN("Failed start decode stream %s\n", s->name);
+
+		/* failure, clean up */
+		clear_bit(IVTV_F_S_STREAMING, &s->s_flags);
+		clear_bit(IVTV_F_S_APPL_IO, &s->s_flags);
+		return rc;
+	}
+
+retry:
+	/* If possible, just DMA the entire frame - Check the data transfer size
+	since we may get here before the stream has been fully set-up */
+	if (mode == OUT_YUV && s->q_full.length == 0 && itv->dma_data_req_size) {
+		while (count >= itv->dma_data_req_size) {
+			rc = ivtv_yuv_udma_stream_frame(itv, (void __user *)user_buf);
+
+			if (rc < 0)
+				return rc;
+
+			bytes_written += itv->dma_data_req_size;
+			user_buf += itv->dma_data_req_size;
+			count -= itv->dma_data_req_size;
+		}
+		if (count == 0) {
+			IVTV_DEBUG_HI_FILE("Wrote %d bytes to %s (%d)\n", bytes_written, s->name, s->q_full.bytesused);
+			return bytes_written;
+		}
+	}
+
+	for (;;) {
+		/* Gather buffers */
+		while (q.length - q.bytesused < count && (buf = ivtv_dequeue(s, &s->q_io)))
+			ivtv_enqueue(s, buf, &q);
+		while (q.length - q.bytesused < count && (buf = ivtv_dequeue(s, &s->q_free))) {
+			ivtv_enqueue(s, buf, &q);
+		}
+		if (q.buffers)
+			break;
+		if (filp->f_flags & O_NONBLOCK)
+			return -EAGAIN;
+		mutex_unlock(&itv->serialize_lock);
+		prepare_to_wait(&s->waitq, &wait, TASK_INTERRUPTIBLE);
+		/* New buffers might have become free before we were added to the waitqueue */
+		if (!s->q_free.buffers)
+			schedule();
+		finish_wait(&s->waitq, &wait);
+		mutex_lock(&itv->serialize_lock);
+		if (signal_pending(current)) {
+			IVTV_DEBUG_INFO("User stopped %s\n", s->name);
+			return -EINTR;
+		}
+	}
+
+	/* copy user data into buffers */
+	while ((buf = ivtv_dequeue(s, &q))) {
+		/* yuv is a pain. Don't copy more data than needed for a single
+		   frame, otherwise we lose sync with the incoming stream */
+		if (s->type == IVTV_DEC_STREAM_TYPE_YUV &&
+		    yi->stream_size + count > itv->dma_data_req_size)
+			rc  = ivtv_buf_copy_from_user(s, buf, user_buf,
+				itv->dma_data_req_size - yi->stream_size);
+		else
+			rc = ivtv_buf_copy_from_user(s, buf, user_buf, count);
+
+		/* Make sure we really got all the user data */
+		if (rc < 0) {
+			ivtv_queue_move(s, &q, NULL, &s->q_free, 0);
+			return rc;
+		}
+		user_buf += rc;
+		count -= rc;
+		bytes_written += rc;
+
+		if (s->type == IVTV_DEC_STREAM_TYPE_YUV) {
+			yi->stream_size += rc;
+			/* If we have a complete yuv frame, break loop now */
+			if (yi->stream_size == itv->dma_data_req_size) {
+				ivtv_enqueue(s, buf, &s->q_full);
+				yi->stream_size = 0;
+				break;
+			}
+		}
+
+		if (buf->bytesused != s->buf_size) {
+			/* incomplete, leave in q_io for next time */
+			ivtv_enqueue(s, buf, &s->q_io);
+			break;
+		}
+		/* Byteswap MPEG buffer */
+		if (s->type == IVTV_DEC_STREAM_TYPE_MPG)
+			ivtv_buf_swap(buf);
+		ivtv_enqueue(s, buf, &s->q_full);
+	}
+
+	if (test_bit(IVTV_F_S_NEEDS_DATA, &s->s_flags)) {
+		if (s->q_full.length >= itv->dma_data_req_size) {
+			int got_sig;
+
+			if (mode == OUT_YUV)
+				ivtv_yuv_setup_stream_frame(itv);
+
+			mutex_unlock(&itv->serialize_lock);
+			prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE);
+			while (!(got_sig = signal_pending(current)) &&
+					test_bit(IVTV_F_S_DMA_PENDING, &s->s_flags)) {
+				schedule();
+			}
+			finish_wait(&itv->dma_waitq, &wait);
+			mutex_lock(&itv->serialize_lock);
+			if (got_sig) {
+				IVTV_DEBUG_INFO("User interrupted %s\n", s->name);
+				return -EINTR;
+			}
+
+			clear_bit(IVTV_F_S_NEEDS_DATA, &s->s_flags);
+			ivtv_queue_move(s, &s->q_full, NULL, &s->q_predma, itv->dma_data_req_size);
+			ivtv_dma_stream_dec_prepare(s, itv->dma_data_req_offset + IVTV_DECODER_OFFSET, 1);
+		}
+	}
+	/* more user data is available, wait until buffers become free
+	   to transfer the rest. */
+	if (count && !(filp->f_flags & O_NONBLOCK))
+		goto retry;
+	IVTV_DEBUG_HI_FILE("Wrote %d bytes to %s (%d)\n", bytes_written, s->name, s->q_full.bytesused);
+	return bytes_written;
+}
+
+ssize_t ivtv_v4l2_write(struct file *filp, const char __user *user_buf, size_t count, loff_t *pos)
+{
+	struct ivtv_open_id *id = fh2id(filp->private_data);
+	struct ivtv *itv = id->itv;
+	ssize_t res;
+
+	if (mutex_lock_interruptible(&itv->serialize_lock))
+		return -ERESTARTSYS;
+	res = ivtv_write(filp, user_buf, count, pos);
+	mutex_unlock(&itv->serialize_lock);
+	return res;
+}
+
+unsigned int ivtv_v4l2_dec_poll(struct file *filp, poll_table *wait)
+{
+	struct ivtv_open_id *id = fh2id(filp->private_data);
+	struct ivtv *itv = id->itv;
+	struct ivtv_stream *s = &itv->streams[id->type];
+	int res = 0;
+
+	/* add stream's waitq to the poll list */
+	IVTV_DEBUG_HI_FILE("Decoder poll\n");
+
+	/* If there are subscribed events, then only use the new event
+	   API instead of the old video.h based API. */
+	if (!list_empty(&id->fh.subscribed)) {
+		poll_wait(filp, &id->fh.wait, wait);
+		/* Turn off the old-style vsync events */
+		clear_bit(IVTV_F_I_EV_VSYNC_ENABLED, &itv->i_flags);
+		if (v4l2_event_pending(&id->fh))
+			res = POLLPRI;
+	} else {
+		/* This is the old-style API which is here only for backwards
+		   compatibility. */
+		poll_wait(filp, &s->waitq, wait);
+		set_bit(IVTV_F_I_EV_VSYNC_ENABLED, &itv->i_flags);
+		if (test_bit(IVTV_F_I_EV_VSYNC, &itv->i_flags) ||
+		    test_bit(IVTV_F_I_EV_DEC_STOPPED, &itv->i_flags))
+			res = POLLPRI;
+	}
+
+	/* Allow write if buffers are available for writing */
+	if (s->q_free.buffers)
+		res |= POLLOUT | POLLWRNORM;
+	return res;
+}
+
+unsigned int ivtv_v4l2_enc_poll(struct file *filp, poll_table *wait)
+{
+	unsigned long req_events = poll_requested_events(wait);
+	struct ivtv_open_id *id = fh2id(filp->private_data);
+	struct ivtv *itv = id->itv;
+	struct ivtv_stream *s = &itv->streams[id->type];
+	int eof = test_bit(IVTV_F_S_STREAMOFF, &s->s_flags);
+	unsigned res = 0;
+
+	/* Start a capture if there is none */
+	if (!eof && !test_bit(IVTV_F_S_STREAMING, &s->s_flags) &&
+			(req_events & (POLLIN | POLLRDNORM))) {
+		int rc;
+
+		mutex_lock(&itv->serialize_lock);
+		rc = ivtv_start_capture(id);
+		mutex_unlock(&itv->serialize_lock);
+		if (rc) {
+			IVTV_DEBUG_INFO("Could not start capture for %s (%d)\n",
+					s->name, rc);
+			return POLLERR;
+		}
+		IVTV_DEBUG_FILE("Encoder poll started capture\n");
+	}
+
+	/* add stream's waitq to the poll list */
+	IVTV_DEBUG_HI_FILE("Encoder poll\n");
+	poll_wait(filp, &s->waitq, wait);
+	if (v4l2_event_pending(&id->fh))
+		res |= POLLPRI;
+	else
+		poll_wait(filp, &id->fh.wait, wait);
+
+	if (s->q_full.length || s->q_io.length)
+		return res | POLLIN | POLLRDNORM;
+	if (eof)
+		return res | POLLHUP;
+	return res;
+}
+
+void ivtv_stop_capture(struct ivtv_open_id *id, int gop_end)
+{
+	struct ivtv *itv = id->itv;
+	struct ivtv_stream *s = &itv->streams[id->type];
+
+	IVTV_DEBUG_FILE("close() of %s\n", s->name);
+
+	/* 'Unclaim' this stream */
+
+	/* Stop capturing */
+	if (test_bit(IVTV_F_S_STREAMING, &s->s_flags)) {
+		struct ivtv_stream *s_vbi = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI];
+
+		IVTV_DEBUG_INFO("close stopping capture\n");
+		/* Special case: a running VBI capture for VBI insertion
+		   in the mpeg stream. Need to stop that too. */
+		if (id->type == IVTV_ENC_STREAM_TYPE_MPG &&
+		    test_bit(IVTV_F_S_STREAMING, &s_vbi->s_flags) &&
+		    !test_bit(IVTV_F_S_APPL_IO, &s_vbi->s_flags)) {
+			IVTV_DEBUG_INFO("close stopping embedded VBI capture\n");
+			ivtv_stop_v4l2_encode_stream(s_vbi, 0);
+		}
+		if ((id->type == IVTV_DEC_STREAM_TYPE_VBI ||
+		     id->type == IVTV_ENC_STREAM_TYPE_VBI) &&
+		    test_bit(IVTV_F_S_INTERNAL_USE, &s->s_flags)) {
+			/* Also used internally, don't stop capturing */
+			s->fh = NULL;
+		}
+		else {
+			ivtv_stop_v4l2_encode_stream(s, gop_end);
+		}
+	}
+	if (!gop_end) {
+		clear_bit(IVTV_F_S_APPL_IO, &s->s_flags);
+		clear_bit(IVTV_F_S_STREAMOFF, &s->s_flags);
+		ivtv_release_stream(s);
+	}
+}
+
+static void ivtv_stop_decoding(struct ivtv_open_id *id, int flags, u64 pts)
+{
+	struct ivtv *itv = id->itv;
+	struct ivtv_stream *s = &itv->streams[id->type];
+
+	IVTV_DEBUG_FILE("close() of %s\n", s->name);
+
+	if (id->type == IVTV_DEC_STREAM_TYPE_YUV &&
+		test_bit(IVTV_F_I_DECODING_YUV, &itv->i_flags)) {
+		/* Restore registers we've changed & clean up any mess */
+		ivtv_yuv_close(itv);
+	}
+
+	/* Stop decoding */
+	if (test_bit(IVTV_F_S_STREAMING, &s->s_flags)) {
+		IVTV_DEBUG_INFO("close stopping decode\n");
+
+		ivtv_stop_v4l2_decode_stream(s, flags, pts);
+		itv->output_mode = OUT_NONE;
+	}
+	clear_bit(IVTV_F_S_APPL_IO, &s->s_flags);
+	clear_bit(IVTV_F_S_STREAMOFF, &s->s_flags);
+
+	if (itv->output_mode == OUT_UDMA_YUV && id->yuv_frames)
+		itv->output_mode = OUT_NONE;
+
+	itv->speed = 0;
+	clear_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags);
+	ivtv_release_stream(s);
+}
+
+int ivtv_v4l2_close(struct file *filp)
+{
+	struct v4l2_fh *fh = filp->private_data;
+	struct ivtv_open_id *id = fh2id(fh);
+	struct ivtv *itv = id->itv;
+	struct ivtv_stream *s = &itv->streams[id->type];
+
+	IVTV_DEBUG_FILE("close %s\n", s->name);
+
+	mutex_lock(&itv->serialize_lock);
+
+	/* Stop radio */
+	if (id->type == IVTV_ENC_STREAM_TYPE_RAD &&
+			v4l2_fh_is_singular_file(filp)) {
+		/* Closing radio device, return to TV mode */
+		ivtv_mute(itv);
+		/* Mark that the radio is no longer in use */
+		clear_bit(IVTV_F_I_RADIO_USER, &itv->i_flags);
+		/* Switch tuner to TV */
+		ivtv_call_all(itv, core, s_std, itv->std);
+		/* Select correct audio input (i.e. TV tuner or Line in) */
+		ivtv_audio_set_io(itv);
+		if (itv->hw_flags & IVTV_HW_SAA711X) {
+			ivtv_call_hw(itv, IVTV_HW_SAA711X, video, s_crystal_freq,
+					SAA7115_FREQ_32_11_MHZ, 0);
+		}
+		if (atomic_read(&itv->capturing) > 0) {
+			/* Undo video mute */
+			ivtv_vapi(itv, CX2341X_ENC_MUTE_VIDEO, 1,
+					v4l2_ctrl_g_ctrl(itv->cxhdl.video_mute) |
+					(v4l2_ctrl_g_ctrl(itv->cxhdl.video_mute_yuv) << 8));
+		}
+		/* Done! Unmute and continue. */
+		ivtv_unmute(itv);
+	}
+
+	v4l2_fh_del(fh);
+	v4l2_fh_exit(fh);
+
+	/* Easy case first: this stream was never claimed by us */
+	if (s->fh != &id->fh)
+		goto close_done;
+
+	/* 'Unclaim' this stream */
+
+	if (s->type >= IVTV_DEC_STREAM_TYPE_MPG) {
+		struct ivtv_stream *s_vout = &itv->streams[IVTV_DEC_STREAM_TYPE_VOUT];
+
+		ivtv_stop_decoding(id, V4L2_DEC_CMD_STOP_TO_BLACK | V4L2_DEC_CMD_STOP_IMMEDIATELY, 0);
+
+		/* If all output streams are closed, and if the user doesn't have
+		   IVTV_DEC_STREAM_TYPE_VOUT open, then disable CC on TV-out. */
+		if (itv->output_mode == OUT_NONE && !test_bit(IVTV_F_S_APPL_IO, &s_vout->s_flags)) {
+			/* disable CC on TV-out */
+			ivtv_disable_cc(itv);
+		}
+	} else {
+		ivtv_stop_capture(id, 0);
+	}
+close_done:
+	kfree(id);
+	mutex_unlock(&itv->serialize_lock);
+	return 0;
+}
+
+static int ivtv_open(struct file *filp)
+{
+	struct video_device *vdev = video_devdata(filp);
+	struct ivtv_stream *s = video_get_drvdata(vdev);
+	struct ivtv *itv = s->itv;
+	struct ivtv_open_id *item;
+	int res = 0;
+
+	IVTV_DEBUG_FILE("open %s\n", s->name);
+
+	if (ivtv_init_on_first_open(itv)) {
+		IVTV_ERR("Failed to initialize on device %s\n",
+			 video_device_node_name(vdev));
+		return -ENXIO;
+	}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	/* Unless ivtv_fw_debug is set, error out if firmware dead. */
+	if (ivtv_fw_debug) {
+		IVTV_WARN("Opening %s with dead firmware lockout disabled\n",
+			  video_device_node_name(vdev));
+		IVTV_WARN("Selected firmware errors will be ignored\n");
+	} else {
+#else
+	if (1) {
+#endif
+		res = ivtv_firmware_check(itv, "ivtv_serialized_open");
+		if (res == -EAGAIN)
+			res = ivtv_firmware_check(itv, "ivtv_serialized_open");
+		if (res < 0)
+			return -EIO;
+	}
+
+	if (s->type == IVTV_DEC_STREAM_TYPE_MPG &&
+		test_bit(IVTV_F_S_CLAIMED, &itv->streams[IVTV_DEC_STREAM_TYPE_YUV].s_flags))
+		return -EBUSY;
+
+	if (s->type == IVTV_DEC_STREAM_TYPE_YUV &&
+		test_bit(IVTV_F_S_CLAIMED, &itv->streams[IVTV_DEC_STREAM_TYPE_MPG].s_flags))
+		return -EBUSY;
+
+	if (s->type == IVTV_DEC_STREAM_TYPE_YUV) {
+		if (read_reg(0x82c) == 0) {
+			IVTV_ERR("Tried to open YUV output device but need to send data to mpeg decoder before it can be used\n");
+			/* return -ENODEV; */
+		}
+		ivtv_udma_alloc(itv);
+	}
+
+	/* Allocate memory */
+	item = kzalloc(sizeof(struct ivtv_open_id), GFP_KERNEL);
+	if (NULL == item) {
+		IVTV_DEBUG_WARN("nomem on v4l2 open\n");
+		return -ENOMEM;
+	}
+	v4l2_fh_init(&item->fh, s->vdev);
+	item->itv = itv;
+	item->type = s->type;
+
+	filp->private_data = &item->fh;
+	v4l2_fh_add(&item->fh);
+
+	if (item->type == IVTV_ENC_STREAM_TYPE_RAD &&
+			v4l2_fh_is_singular_file(filp)) {
+		if (!test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags)) {
+			if (atomic_read(&itv->capturing) > 0) {
+				/* switching to radio while capture is
+				   in progress is not polite */
+				v4l2_fh_del(&item->fh);
+				v4l2_fh_exit(&item->fh);
+				kfree(item);
+				return -EBUSY;
+			}
+		}
+		/* Mark that the radio is being used. */
+		set_bit(IVTV_F_I_RADIO_USER, &itv->i_flags);
+		/* We have the radio */
+		ivtv_mute(itv);
+		/* Switch tuner to radio */
+		ivtv_call_all(itv, tuner, s_radio);
+		/* Select the correct audio input (i.e. radio tuner) */
+		ivtv_audio_set_io(itv);
+		if (itv->hw_flags & IVTV_HW_SAA711X) {
+			ivtv_call_hw(itv, IVTV_HW_SAA711X, video, s_crystal_freq,
+				SAA7115_FREQ_32_11_MHZ, SAA7115_FREQ_FL_APLL);
+		}
+		/* Done! Unmute and continue. */
+		ivtv_unmute(itv);
+	}
+
+	/* YUV or MPG Decoding Mode? */
+	if (s->type == IVTV_DEC_STREAM_TYPE_MPG) {
+		clear_bit(IVTV_F_I_DEC_YUV, &itv->i_flags);
+	} else if (s->type == IVTV_DEC_STREAM_TYPE_YUV) {
+		set_bit(IVTV_F_I_DEC_YUV, &itv->i_flags);
+		/* For yuv, we need to know the dma size before we start */
+		itv->dma_data_req_size =
+				1080 * ((itv->yuv_info.v4l2_src_h + 31) & ~31);
+		itv->yuv_info.stream_size = 0;
+	}
+	return 0;
+}
+
+int ivtv_v4l2_open(struct file *filp)
+{
+	struct video_device *vdev = video_devdata(filp);
+	int res;
+
+	if (mutex_lock_interruptible(vdev->lock))
+		return -ERESTARTSYS;
+	res = ivtv_open(filp);
+	mutex_unlock(vdev->lock);
+	return res;
+}
+
+void ivtv_mute(struct ivtv *itv)
+{
+	if (atomic_read(&itv->capturing))
+		ivtv_vapi(itv, CX2341X_ENC_MUTE_AUDIO, 1, 1);
+	IVTV_DEBUG_INFO("Mute\n");
+}
+
+void ivtv_unmute(struct ivtv *itv)
+{
+	if (atomic_read(&itv->capturing)) {
+		ivtv_msleep_timeout(100, 0);
+		ivtv_vapi(itv, CX2341X_ENC_MISC, 1, 12);
+		ivtv_vapi(itv, CX2341X_ENC_MUTE_AUDIO, 1, 0);
+	}
+	IVTV_DEBUG_INFO("Unmute\n");
+}
diff --git a/drivers/media/pci/ivtv/ivtv-fileops.h b/drivers/media/pci/ivtv/ivtv-fileops.h
new file mode 100644
index 0000000..5e08800
--- /dev/null
+++ b/drivers/media/pci/ivtv/ivtv-fileops.h
@@ -0,0 +1,44 @@
+/*
+    file operation functions
+    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
+    Copyright (C) 2005-2007  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef IVTV_FILEOPS_H
+#define IVTV_FILEOPS_H
+
+/* Testing/Debugging */
+int ivtv_v4l2_open(struct file *filp);
+ssize_t ivtv_v4l2_read(struct file *filp, char __user *buf, size_t count,
+		      loff_t * pos);
+ssize_t ivtv_v4l2_write(struct file *filp, const char __user *buf, size_t count,
+		       loff_t * pos);
+int ivtv_v4l2_close(struct file *filp);
+unsigned int ivtv_v4l2_enc_poll(struct file *filp, poll_table * wait);
+unsigned int ivtv_v4l2_dec_poll(struct file *filp, poll_table * wait);
+int ivtv_start_capture(struct ivtv_open_id *id);
+void ivtv_stop_capture(struct ivtv_open_id *id, int gop_end);
+int ivtv_start_decoding(struct ivtv_open_id *id, int speed);
+void ivtv_mute(struct ivtv *itv);
+void ivtv_unmute(struct ivtv *itv);
+
+/* Utilities */
+/* Shared with ivtv-alsa module */
+int ivtv_claim_stream(struct ivtv_open_id *id, int type);
+void ivtv_release_stream(struct ivtv_stream *s);
+
+#endif
diff --git a/drivers/media/pci/ivtv/ivtv-firmware.c b/drivers/media/pci/ivtv/ivtv-firmware.c
new file mode 100644
index 0000000..6ec7705
--- /dev/null
+++ b/drivers/media/pci/ivtv/ivtv-firmware.c
@@ -0,0 +1,402 @@
+/*
+    ivtv firmware functions.
+    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
+    Copyright (C) 2004  Chris Kennedy <c@groovy.org>
+    Copyright (C) 2005-2007  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "ivtv-driver.h"
+#include "ivtv-mailbox.h"
+#include "ivtv-firmware.h"
+#include "ivtv-yuv.h"
+#include "ivtv-ioctl.h"
+#include "ivtv-cards.h"
+#include <linux/firmware.h>
+#include <media/saa7127.h>
+
+#define IVTV_MASK_SPU_ENABLE 		0xFFFFFFFE
+#define IVTV_MASK_VPU_ENABLE15 		0xFFFFFFF6
+#define IVTV_MASK_VPU_ENABLE16 		0xFFFFFFFB
+#define IVTV_CMD_VDM_STOP 		0x00000000
+#define IVTV_CMD_AO_STOP 		0x00000005
+#define IVTV_CMD_APU_PING 		0x00000000
+#define IVTV_CMD_VPU_STOP15 		0xFFFFFFFE
+#define IVTV_CMD_VPU_STOP16 		0xFFFFFFEE
+#define IVTV_CMD_HW_BLOCKS_RST 		0xFFFFFFFF
+#define IVTV_CMD_SPU_STOP 		0x00000001
+#define IVTV_CMD_SDRAM_PRECHARGE_INIT 	0x0000001A
+#define IVTV_CMD_SDRAM_REFRESH_INIT 	0x80000640
+#define IVTV_SDRAM_SLEEPTIME 		600
+
+#define IVTV_DECODE_INIT_MPEG_FILENAME 	"v4l-cx2341x-init.mpg"
+#define IVTV_DECODE_INIT_MPEG_SIZE 	(152*1024)
+
+/* Encoder/decoder firmware sizes */
+#define IVTV_FW_ENC_SIZE 		(376836)
+#define IVTV_FW_DEC_SIZE 		(256*1024)
+
+static int load_fw_direct(const char *fn, volatile u8 __iomem *mem, struct ivtv *itv, long size)
+{
+	const struct firmware *fw = NULL;
+	int retries = 3;
+
+retry:
+	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;
+
+		if (fw->size != size) {
+			/* Due to race conditions in firmware loading (esp. with udev <0.95)
+			   the wrong file was sometimes loaded. So we check filesizes to
+			   see if at least the right-sized file was loaded. If not, then we
+			   retry. */
+			IVTV_INFO("Retry: file loaded was not %s (expected size %ld, got %zd)\n", fn, size, fw->size);
+			release_firmware(fw);
+			retries--;
+			goto retry;
+		}
+		for (i = 0; i < fw->size; i += 4) {
+			/* no need for endianness conversion on the ppc */
+			__raw_writel(*src, dst);
+			dst++;
+			src++;
+		}
+		IVTV_INFO("Loaded %s firmware (%zd bytes)\n", fn, fw->size);
+		release_firmware(fw);
+		return size;
+	}
+	IVTV_ERR("Unable to open firmware %s (must be %ld bytes)\n", fn, size);
+	IVTV_ERR("Did you put the firmware in the hotplug firmware directory?\n");
+	return -ENOMEM;
+}
+
+void ivtv_halt_firmware(struct ivtv *itv)
+{
+	IVTV_DEBUG_INFO("Preparing for firmware halt.\n");
+	if (itv->has_cx23415 && itv->dec_mbox.mbox)
+		ivtv_vapi(itv, CX2341X_DEC_HALT_FW, 0);
+	if (itv->enc_mbox.mbox)
+		ivtv_vapi(itv, CX2341X_ENC_HALT_FW, 0);
+
+	ivtv_msleep_timeout(10, 0);
+	itv->enc_mbox.mbox = itv->dec_mbox.mbox = NULL;
+
+	IVTV_DEBUG_INFO("Stopping VDM\n");
+	write_reg(IVTV_CMD_VDM_STOP, IVTV_REG_VDM);
+
+	IVTV_DEBUG_INFO("Stopping AO\n");
+	write_reg(IVTV_CMD_AO_STOP, IVTV_REG_AO);
+
+	IVTV_DEBUG_INFO("pinging (?) APU\n");
+	write_reg(IVTV_CMD_APU_PING, IVTV_REG_APU);
+
+	IVTV_DEBUG_INFO("Stopping VPU\n");
+	if (!itv->has_cx23415)
+		write_reg(IVTV_CMD_VPU_STOP16, IVTV_REG_VPU);
+	else
+		write_reg(IVTV_CMD_VPU_STOP15, IVTV_REG_VPU);
+
+	IVTV_DEBUG_INFO("Resetting Hw Blocks\n");
+	write_reg(IVTV_CMD_HW_BLOCKS_RST, IVTV_REG_HW_BLOCKS);
+
+	IVTV_DEBUG_INFO("Stopping SPU\n");
+	write_reg(IVTV_CMD_SPU_STOP, IVTV_REG_SPU);
+
+	ivtv_msleep_timeout(10, 0);
+
+	IVTV_DEBUG_INFO("init Encoder SDRAM pre-charge\n");
+	write_reg(IVTV_CMD_SDRAM_PRECHARGE_INIT, IVTV_REG_ENC_SDRAM_PRECHARGE);
+
+	IVTV_DEBUG_INFO("init Encoder SDRAM refresh to 1us\n");
+	write_reg(IVTV_CMD_SDRAM_REFRESH_INIT, IVTV_REG_ENC_SDRAM_REFRESH);
+
+	if (itv->has_cx23415) {
+		IVTV_DEBUG_INFO("init Decoder SDRAM pre-charge\n");
+		write_reg(IVTV_CMD_SDRAM_PRECHARGE_INIT, IVTV_REG_DEC_SDRAM_PRECHARGE);
+
+		IVTV_DEBUG_INFO("init Decoder SDRAM refresh to 1us\n");
+		write_reg(IVTV_CMD_SDRAM_REFRESH_INIT, IVTV_REG_DEC_SDRAM_REFRESH);
+	}
+
+	IVTV_DEBUG_INFO("Sleeping for %dms\n", IVTV_SDRAM_SLEEPTIME);
+	ivtv_msleep_timeout(IVTV_SDRAM_SLEEPTIME, 0);
+}
+
+void ivtv_firmware_versions(struct ivtv *itv)
+{
+	u32 data[CX2341X_MBOX_MAX_DATA];
+
+	/* Encoder */
+	ivtv_vapi_result(itv, data, CX2341X_ENC_GET_VERSION, 0);
+	IVTV_INFO("Encoder revision: 0x%08x\n", data[0]);
+
+	if (data[0] != 0x02060039)
+		IVTV_WARN("Recommended firmware version is 0x02060039.\n");
+
+	if (itv->has_cx23415) {
+		/* Decoder */
+		ivtv_vapi_result(itv, data, CX2341X_DEC_GET_VERSION, 0);
+		IVTV_INFO("Decoder revision: 0x%08x\n", data[0]);
+	}
+}
+
+static int ivtv_firmware_copy(struct ivtv *itv)
+{
+	IVTV_DEBUG_INFO("Loading encoder image\n");
+	if (load_fw_direct(CX2341X_FIRM_ENC_FILENAME,
+		   itv->enc_mem, itv, IVTV_FW_ENC_SIZE) != IVTV_FW_ENC_SIZE) {
+		IVTV_DEBUG_WARN("failed loading encoder firmware\n");
+		return -3;
+	}
+	if (!itv->has_cx23415)
+		return 0;
+
+	IVTV_DEBUG_INFO("Loading decoder image\n");
+	if (load_fw_direct(CX2341X_FIRM_DEC_FILENAME,
+		   itv->dec_mem, itv, IVTV_FW_DEC_SIZE) != IVTV_FW_DEC_SIZE) {
+		IVTV_DEBUG_WARN("failed loading decoder firmware\n");
+		return -1;
+	}
+	return 0;
+}
+
+static volatile struct ivtv_mailbox __iomem *ivtv_search_mailbox(const volatile u8 __iomem *mem, u32 size)
+{
+	int i;
+
+	/* mailbox is preceded by a 16 byte 'magic cookie' starting at a 256-byte
+	   address boundary */
+	for (i = 0; i < size; i += 0x100) {
+		if (readl(mem + i)      == 0x12345678 &&
+		    readl(mem + i + 4)  == 0x34567812 &&
+		    readl(mem + i + 8)  == 0x56781234 &&
+		    readl(mem + i + 12) == 0x78123456) {
+			return (volatile struct ivtv_mailbox __iomem *)(mem + i + 16);
+		}
+	}
+	return NULL;
+}
+
+int ivtv_firmware_init(struct ivtv *itv)
+{
+	int err;
+
+	ivtv_halt_firmware(itv);
+
+	/* load firmware */
+	err = ivtv_firmware_copy(itv);
+	if (err) {
+		IVTV_DEBUG_WARN("Error %d loading firmware\n", err);
+		return err;
+	}
+
+	/* start firmware */
+	write_reg(read_reg(IVTV_REG_SPU) & IVTV_MASK_SPU_ENABLE, IVTV_REG_SPU);
+	ivtv_msleep_timeout(100, 0);
+	if (itv->has_cx23415)
+		write_reg(read_reg(IVTV_REG_VPU) & IVTV_MASK_VPU_ENABLE15, IVTV_REG_VPU);
+	else
+		write_reg(read_reg(IVTV_REG_VPU) & IVTV_MASK_VPU_ENABLE16, IVTV_REG_VPU);
+	ivtv_msleep_timeout(100, 0);
+
+	/* find mailboxes and ping firmware */
+	itv->enc_mbox.mbox = ivtv_search_mailbox(itv->enc_mem, IVTV_ENCODER_SIZE);
+	if (itv->enc_mbox.mbox == NULL)
+		IVTV_ERR("Encoder mailbox not found\n");
+	else if (ivtv_vapi(itv, CX2341X_ENC_PING_FW, 0)) {
+		IVTV_ERR("Encoder firmware dead!\n");
+		itv->enc_mbox.mbox = NULL;
+	}
+	if (itv->enc_mbox.mbox == NULL)
+		return -ENODEV;
+
+	if (!itv->has_cx23415)
+		return 0;
+
+	itv->dec_mbox.mbox = ivtv_search_mailbox(itv->dec_mem, IVTV_DECODER_SIZE);
+	if (itv->dec_mbox.mbox == NULL) {
+		IVTV_ERR("Decoder mailbox not found\n");
+	} else if (itv->has_cx23415 && ivtv_vapi(itv, CX2341X_DEC_PING_FW, 0)) {
+		IVTV_ERR("Decoder firmware dead!\n");
+		itv->dec_mbox.mbox = NULL;
+	} else {
+		/* Firmware okay, so check yuv output filter table */
+		ivtv_yuv_filter_check(itv);
+	}
+	return itv->dec_mbox.mbox ? 0 : -ENODEV;
+}
+
+void ivtv_init_mpeg_decoder(struct ivtv *itv)
+{
+	u32 data[CX2341X_MBOX_MAX_DATA];
+	long readbytes;
+	volatile u8 __iomem *mem_offset;
+
+	data[0] = 0;
+	data[1] = itv->cxhdl.width;	/* YUV source width */
+	data[2] = itv->cxhdl.height;
+	data[3] = itv->cxhdl.audio_properties;	/* Audio settings to use,
+							   bitmap. see docs. */
+	if (ivtv_api(itv, CX2341X_DEC_SET_DECODER_SOURCE, 4, data)) {
+		IVTV_ERR("ivtv_init_mpeg_decoder failed to set decoder source\n");
+		return;
+	}
+
+	if (ivtv_vapi(itv, CX2341X_DEC_START_PLAYBACK, 2, 0, 1) != 0) {
+		IVTV_ERR("ivtv_init_mpeg_decoder failed to start playback\n");
+		return;
+	}
+	ivtv_api_get_data(&itv->dec_mbox, IVTV_MBOX_DMA, 2, data);
+	mem_offset = itv->dec_mem + data[1];
+
+	if ((readbytes = load_fw_direct(IVTV_DECODE_INIT_MPEG_FILENAME,
+		mem_offset, itv, IVTV_DECODE_INIT_MPEG_SIZE)) <= 0) {
+		IVTV_DEBUG_WARN("failed to read mpeg decoder initialisation file %s\n",
+				IVTV_DECODE_INIT_MPEG_FILENAME);
+	} else {
+		ivtv_vapi(itv, CX2341X_DEC_SCHED_DMA_FROM_HOST, 3, 0, readbytes, 0);
+		ivtv_msleep_timeout(100, 0);
+	}
+	ivtv_vapi(itv, CX2341X_DEC_STOP_PLAYBACK, 4, 0, 0, 0, 1);
+}
+
+/* Try to restart the card & restore previous settings */
+int ivtv_firmware_restart(struct ivtv *itv)
+{
+	int rc = 0;
+	v4l2_std_id std;
+
+	if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)
+		/* Display test image during restart */
+		ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_routing,
+		    SAA7127_INPUT_TYPE_TEST_IMAGE,
+		    itv->card->video_outputs[itv->active_output].video_output,
+		    0);
+
+	mutex_lock(&itv->udma.lock);
+
+	rc = ivtv_firmware_init(itv);
+	if (rc) {
+		mutex_unlock(&itv->udma.lock);
+		return rc;
+	}
+
+	/* Allow settings to reload */
+	ivtv_mailbox_cache_invalidate(itv);
+
+	/* Restore encoder video standard */
+	std = itv->std;
+	itv->std = 0;
+	ivtv_s_std_enc(itv, &std);
+
+	if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) {
+		ivtv_init_mpeg_decoder(itv);
+
+		/* Restore decoder video standard */
+		std = itv->std_out;
+		itv->std_out = 0;
+		ivtv_s_std_dec(itv, &std);
+
+		/* Restore framebuffer if active */
+		if (itv->ivtvfb_restore)
+			itv->ivtvfb_restore(itv);
+
+		/* Restore alpha settings */
+		ivtv_set_osd_alpha(itv);
+
+		/* Restore normal output */
+		ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_routing,
+		    SAA7127_INPUT_TYPE_NORMAL,
+		    itv->card->video_outputs[itv->active_output].video_output,
+		    0);
+	}
+
+	mutex_unlock(&itv->udma.lock);
+	return rc;
+}
+
+/* Check firmware running state. The checks fall through
+   allowing multiple failures to be logged. */
+int ivtv_firmware_check(struct ivtv *itv, char *where)
+{
+	int res = 0;
+
+	/* Check encoder is still running */
+	if (ivtv_vapi(itv, CX2341X_ENC_PING_FW, 0) < 0) {
+		IVTV_WARN("Encoder has died : %s\n", where);
+		res = -1;
+	}
+
+	/* Also check audio. Only check if not in use & encoder is okay */
+	if (!res && !atomic_read(&itv->capturing) &&
+	    (!atomic_read(&itv->decoding) ||
+	     (atomic_read(&itv->decoding) < 2 && test_bit(IVTV_F_I_DEC_YUV,
+							     &itv->i_flags)))) {
+
+		if (ivtv_vapi(itv, CX2341X_ENC_MISC, 1, 12) < 0) {
+			IVTV_WARN("Audio has died (Encoder OK) : %s\n", where);
+			res = -2;
+		}
+	}
+
+	if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) {
+		/* Second audio check. Skip if audio already failed */
+		if (res != -2 && read_dec(0x100) != read_dec(0x104)) {
+			/* Wait & try again to be certain. */
+			ivtv_msleep_timeout(14, 0);
+			if (read_dec(0x100) != read_dec(0x104)) {
+				IVTV_WARN("Audio has died (Decoder) : %s\n",
+					  where);
+				res = -1;
+			}
+		}
+
+		/* Check decoder is still running */
+		if (ivtv_vapi(itv, CX2341X_DEC_PING_FW, 0) < 0) {
+			IVTV_WARN("Decoder has died : %s\n", where);
+			res = -1;
+		}
+	}
+
+	/* If something failed & currently idle, try to reload */
+	if (res && !atomic_read(&itv->capturing) &&
+						!atomic_read(&itv->decoding)) {
+		IVTV_INFO("Detected in %s that firmware had failed - "
+			  "Reloading\n", where);
+		res = ivtv_firmware_restart(itv);
+		/*
+		 * Even if restarted ok, still signal a problem had occurred.
+		 * The caller can come through this function again to check
+		 * if things are really ok after the restart.
+		 */
+		if (!res) {
+			IVTV_INFO("Firmware restart okay\n");
+			res = -EAGAIN;
+		} else {
+			IVTV_INFO("Firmware restart failed\n");
+		}
+	} else if (res) {
+		res = -EIO;
+	}
+
+	return res;
+}
+
+MODULE_FIRMWARE(CX2341X_FIRM_ENC_FILENAME);
+MODULE_FIRMWARE(CX2341X_FIRM_DEC_FILENAME);
+MODULE_FIRMWARE(IVTV_DECODE_INIT_MPEG_FILENAME);
diff --git a/drivers/media/pci/ivtv/ivtv-firmware.h b/drivers/media/pci/ivtv/ivtv-firmware.h
new file mode 100644
index 0000000..52bb4e5
--- /dev/null
+++ b/drivers/media/pci/ivtv/ivtv-firmware.h
@@ -0,0 +1,31 @@
+/*
+    ivtv firmware functions.
+    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
+    Copyright (C) 2004  Chris Kennedy <c@groovy.org>
+    Copyright (C) 2005-2007  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef IVTV_FIRMWARE_H
+#define IVTV_FIRMWARE_H
+
+int ivtv_firmware_init(struct ivtv *itv);
+void ivtv_firmware_versions(struct ivtv *itv);
+void ivtv_halt_firmware(struct ivtv *itv);
+void ivtv_init_mpeg_decoder(struct ivtv *itv);
+int ivtv_firmware_check(struct ivtv *itv, char *where);
+
+#endif
diff --git a/drivers/media/pci/ivtv/ivtv-gpio.c b/drivers/media/pci/ivtv/ivtv-gpio.c
new file mode 100644
index 0000000..8f0d077
--- /dev/null
+++ b/drivers/media/pci/ivtv/ivtv-gpio.c
@@ -0,0 +1,374 @@
+/*
+    gpio functions.
+    Merging GPIO support into driver:
+    Copyright (C) 2004  Chris Kennedy <c@groovy.org>
+    Copyright (C) 2005-2007  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "ivtv-driver.h"
+#include "ivtv-cards.h"
+#include "ivtv-gpio.h"
+#include "tuner-xc2028.h"
+#include <media/tuner.h>
+#include <media/v4l2-ctrls.h>
+
+/*
+ * GPIO assignment of Yuan MPG600/MPG160
+ *
+ *    bit 15  14  13  12 |  11  10   9   8 |   7   6   5   4 |   3   2   1   0
+ * OUTPUT         IN1 IN0                                       AM3 AM2 AM1 AM0
+ *  INPUT                   DM1         DM0
+ *
+ *   IN* : Input selection
+ *          IN1 IN0
+ *           1   1  N/A
+ *           1   0  Line
+ *           0   1  N/A
+ *           0   0  Tuner
+ *
+ *   AM* : Audio Mode
+ *          AM3  0: Normal        1: Mixed(Sub+Main channel)
+ *          AM2  0: Subchannel    1: Main channel
+ *          AM1  0: Stereo        1: Mono
+ *          AM0  0: Normal        1: Mute
+ *
+ *   DM* : Detected tuner audio Mode
+ *          DM1  0: Stereo        1: Mono
+ *          DM0  0: Multiplex     1: Normal
+ *
+ * GPIO Initial Settings
+ *           MPG600   MPG160
+ *     DIR   0x3080   0x7080
+ *  OUTPUT   0x000C   0x400C
+ *
+ *  Special thanks to Makoto Iguchi <iguchi@tahoo.org> and Mr. Anonymous
+ *  for analyzing GPIO of MPG160.
+ *
+ *****************************************************************************
+ *
+ * GPIO assignment of Avermedia M179 (per information direct from AVerMedia)
+ *
+ *    bit 15  14  13  12 |  11  10   9   8 |   7   6   5   4 |   3   2   1   0
+ * OUTPUT IN0 AM0 IN1               AM1 AM2       IN2     BR0   BR1
+ *  INPUT
+ *
+ *   IN* : Input selection
+ *          IN0 IN1 IN2
+ *           *   1   *  Mute
+ *           0   0   0  Line-In
+ *           1   0   0  TV Tuner Audio
+ *           0   0   1  FM Audio
+ *           1   0   1  Mute
+ *
+ *   AM* : Audio Mode
+ *          AM0 AM1 AM2
+ *           0   0   0  TV Tuner Audio: L_OUT=(L+R)/2, R_OUT=SAP
+ *           0   0   1  TV Tuner Audio: L_OUT=R_OUT=SAP   (SAP)
+ *           0   1   0  TV Tuner Audio: L_OUT=L, R_OUT=R   (stereo)
+ *           0   1   1  TV Tuner Audio: mute
+ *           1   *   *  TV Tuner Audio: L_OUT=R_OUT=(L+R)/2   (mono)
+ *
+ *   BR* : Audio Sample Rate (BR stands for bitrate for some reason)
+ *          BR0 BR1
+ *           0   0   32 kHz
+ *           0   1   44.1 kHz
+ *           1   0   48 kHz
+ *
+ *   DM* : Detected tuner audio Mode
+ *         Unknown currently
+ *
+ * Special thanks to AVerMedia Technologies, Inc. and Jiun-Kuei Jung at
+ * AVerMedia for providing the GPIO information used to add support
+ * for the M179 cards.
+ */
+
+/********************* GPIO stuffs *********************/
+
+/* GPIO registers */
+#define IVTV_REG_GPIO_IN    0x9008
+#define IVTV_REG_GPIO_OUT   0x900c
+#define IVTV_REG_GPIO_DIR   0x9020
+
+void ivtv_reset_ir_gpio(struct ivtv *itv)
+{
+	int curdir, curout;
+
+	if (itv->card->type != IVTV_CARD_PVR_150)
+		return;
+	IVTV_DEBUG_INFO("Resetting PVR150 IR\n");
+	curout = read_reg(IVTV_REG_GPIO_OUT);
+	curdir = read_reg(IVTV_REG_GPIO_DIR);
+	curdir |= 0x80;
+	write_reg(curdir, IVTV_REG_GPIO_DIR);
+	curout = (curout & ~0xF) | 1;
+	write_reg(curout, IVTV_REG_GPIO_OUT);
+	/* We could use something else for smaller time */
+	schedule_timeout_interruptible(msecs_to_jiffies(1));
+	curout |= 2;
+	write_reg(curout, IVTV_REG_GPIO_OUT);
+	curdir &= ~0x80;
+	write_reg(curdir, IVTV_REG_GPIO_DIR);
+}
+
+/* Xceive tuner reset function */
+int ivtv_reset_tuner_gpio(void *dev, int component, int cmd, int value)
+{
+	struct i2c_algo_bit_data *algo = dev;
+	struct ivtv *itv = algo->data;
+	u32 curout;
+
+	if (cmd != XC2028_TUNER_RESET)
+		return 0;
+	IVTV_DEBUG_INFO("Resetting tuner\n");
+	curout = read_reg(IVTV_REG_GPIO_OUT);
+	curout &= ~(1 << itv->card->xceive_pin);
+	write_reg(curout, IVTV_REG_GPIO_OUT);
+	schedule_timeout_interruptible(msecs_to_jiffies(1));
+
+	curout |= 1 << itv->card->xceive_pin;
+	write_reg(curout, IVTV_REG_GPIO_OUT);
+	schedule_timeout_interruptible(msecs_to_jiffies(1));
+	return 0;
+}
+
+static inline struct ivtv *sd_to_ivtv(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct ivtv, sd_gpio);
+}
+
+static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
+{
+	return &container_of(ctrl->handler, struct ivtv, hdl_gpio)->sd_gpio;
+}
+
+static int subdev_s_clock_freq(struct v4l2_subdev *sd, u32 freq)
+{
+	struct ivtv *itv = sd_to_ivtv(sd);
+	u16 mask, data;
+
+	mask = itv->card->gpio_audio_freq.mask;
+	switch (freq) {
+	case 32000:
+		data = itv->card->gpio_audio_freq.f32000;
+		break;
+	case 44100:
+		data = itv->card->gpio_audio_freq.f44100;
+		break;
+	case 48000:
+	default:
+		data = itv->card->gpio_audio_freq.f48000;
+		break;
+	}
+	if (mask)
+		write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) | (data & mask), IVTV_REG_GPIO_OUT);
+	return 0;
+}
+
+static int subdev_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
+{
+	struct ivtv *itv = sd_to_ivtv(sd);
+	u16 mask;
+
+	mask = itv->card->gpio_audio_detect.mask;
+	if (mask == 0 || (read_reg(IVTV_REG_GPIO_IN) & mask))
+		vt->rxsubchans = V4L2_TUNER_SUB_STEREO |
+			V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
+	else
+		vt->rxsubchans = V4L2_TUNER_SUB_MONO;
+	return 0;
+}
+
+static int subdev_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
+{
+	struct ivtv *itv = sd_to_ivtv(sd);
+	u16 mask, data;
+
+	mask = itv->card->gpio_audio_mode.mask;
+	switch (vt->audmode) {
+	case V4L2_TUNER_MODE_LANG1:
+		data = itv->card->gpio_audio_mode.lang1;
+		break;
+	case V4L2_TUNER_MODE_LANG2:
+		data = itv->card->gpio_audio_mode.lang2;
+		break;
+	case V4L2_TUNER_MODE_MONO:
+		data = itv->card->gpio_audio_mode.mono;
+		break;
+	case V4L2_TUNER_MODE_STEREO:
+	case V4L2_TUNER_MODE_LANG1_LANG2:
+	default:
+		data = itv->card->gpio_audio_mode.stereo;
+		break;
+	}
+	if (mask)
+		write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) | (data & mask), IVTV_REG_GPIO_OUT);
+	return 0;
+}
+
+static int subdev_s_radio(struct v4l2_subdev *sd)
+{
+	struct ivtv *itv = sd_to_ivtv(sd);
+	u16 mask, data;
+
+	mask = itv->card->gpio_audio_input.mask;
+	data = itv->card->gpio_audio_input.radio;
+	if (mask)
+		write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) | (data & mask), IVTV_REG_GPIO_OUT);
+	return 0;
+}
+
+static int subdev_s_audio_routing(struct v4l2_subdev *sd,
+				  u32 input, u32 output, u32 config)
+{
+	struct ivtv *itv = sd_to_ivtv(sd);
+	u16 mask, data;
+
+	if (input > 2)
+		return -EINVAL;
+	mask = itv->card->gpio_audio_input.mask;
+	switch (input) {
+	case 0:
+		data = itv->card->gpio_audio_input.tuner;
+		break;
+	case 1:
+		data = itv->card->gpio_audio_input.linein;
+		break;
+	case 2:
+	default:
+		data = itv->card->gpio_audio_input.radio;
+		break;
+	}
+	if (mask)
+		write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) | (data & mask), IVTV_REG_GPIO_OUT);
+	return 0;
+}
+
+static int subdev_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct v4l2_subdev *sd = to_sd(ctrl);
+	struct ivtv *itv = sd_to_ivtv(sd);
+	u16 mask, data;
+
+	switch (ctrl->id) {
+	case V4L2_CID_AUDIO_MUTE:
+		mask = itv->card->gpio_audio_mute.mask;
+		data = ctrl->val ? itv->card->gpio_audio_mute.mute : 0;
+		if (mask)
+			write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) |
+					(data & mask), IVTV_REG_GPIO_OUT);
+		return 0;
+	}
+	return -EINVAL;
+}
+
+
+static int subdev_log_status(struct v4l2_subdev *sd)
+{
+	struct ivtv *itv = sd_to_ivtv(sd);
+
+	IVTV_INFO("GPIO status: DIR=0x%04x OUT=0x%04x IN=0x%04x\n",
+			read_reg(IVTV_REG_GPIO_DIR), read_reg(IVTV_REG_GPIO_OUT),
+			read_reg(IVTV_REG_GPIO_IN));
+	v4l2_ctrl_handler_log_status(&itv->hdl_gpio, sd->name);
+	return 0;
+}
+
+static int subdev_s_video_routing(struct v4l2_subdev *sd,
+				  u32 input, u32 output, u32 config)
+{
+	struct ivtv *itv = sd_to_ivtv(sd);
+	u16 mask, data;
+
+	if (input > 2) /* 0:Tuner 1:Composite 2:S-Video */
+		return -EINVAL;
+	mask = itv->card->gpio_video_input.mask;
+	if (input == 0)
+		data = itv->card->gpio_video_input.tuner;
+	else if (input == 1)
+		data = itv->card->gpio_video_input.composite;
+	else
+		data = itv->card->gpio_video_input.svideo;
+	if (mask)
+		write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) | (data & mask), IVTV_REG_GPIO_OUT);
+	return 0;
+}
+
+static const struct v4l2_ctrl_ops gpio_ctrl_ops = {
+	.s_ctrl = subdev_s_ctrl,
+};
+
+static const struct v4l2_subdev_core_ops subdev_core_ops = {
+	.log_status = subdev_log_status,
+	.g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
+	.try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
+	.s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
+	.g_ctrl = v4l2_subdev_g_ctrl,
+	.s_ctrl = v4l2_subdev_s_ctrl,
+	.queryctrl = v4l2_subdev_queryctrl,
+	.querymenu = v4l2_subdev_querymenu,
+};
+
+static const struct v4l2_subdev_tuner_ops subdev_tuner_ops = {
+	.s_radio = subdev_s_radio,
+	.g_tuner = subdev_g_tuner,
+	.s_tuner = subdev_s_tuner,
+};
+
+static const struct v4l2_subdev_audio_ops subdev_audio_ops = {
+	.s_clock_freq = subdev_s_clock_freq,
+	.s_routing = subdev_s_audio_routing,
+};
+
+static const struct v4l2_subdev_video_ops subdev_video_ops = {
+	.s_routing = subdev_s_video_routing,
+};
+
+static const struct v4l2_subdev_ops subdev_ops = {
+	.core = &subdev_core_ops,
+	.tuner = &subdev_tuner_ops,
+	.audio = &subdev_audio_ops,
+	.video = &subdev_video_ops,
+};
+
+int ivtv_gpio_init(struct ivtv *itv)
+{
+	u16 pin = 0;
+
+	if (itv->card->xceive_pin)
+		pin = 1 << itv->card->xceive_pin;
+
+	if ((itv->card->gpio_init.direction | pin) == 0)
+		return 0;
+
+	IVTV_DEBUG_INFO("GPIO initial dir: %08x out: %08x\n",
+		   read_reg(IVTV_REG_GPIO_DIR), read_reg(IVTV_REG_GPIO_OUT));
+
+	/* init output data then direction */
+	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->v4l2_dev.name);
+	itv->sd_gpio.grp_id = IVTV_HW_GPIO;
+	v4l2_ctrl_handler_init(&itv->hdl_gpio, 1);
+	v4l2_ctrl_new_std(&itv->hdl_gpio, &gpio_ctrl_ops,
+			V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0);
+	if (itv->hdl_gpio.error)
+		return itv->hdl_gpio.error;
+	itv->sd_gpio.ctrl_handler = &itv->hdl_gpio;
+	v4l2_ctrl_handler_setup(&itv->hdl_gpio);
+	return v4l2_device_register_subdev(&itv->v4l2_dev, &itv->sd_gpio);
+}
diff --git a/drivers/media/pci/ivtv/ivtv-gpio.h b/drivers/media/pci/ivtv/ivtv-gpio.h
new file mode 100644
index 0000000..0b5d19c
--- /dev/null
+++ b/drivers/media/pci/ivtv/ivtv-gpio.h
@@ -0,0 +1,29 @@
+/*
+    gpio functions.
+    Copyright (C) 2004  Chris Kennedy <c@groovy.org>
+    Copyright (C) 2005-2007  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef IVTV_GPIO_H
+#define IVTV_GPIO_H
+
+/* GPIO stuff */
+int ivtv_gpio_init(struct ivtv *itv);
+void ivtv_reset_ir_gpio(struct ivtv *itv);
+int ivtv_reset_tuner_gpio(void *dev, int component, int cmd, int value);
+
+#endif
diff --git a/drivers/media/pci/ivtv/ivtv-i2c.c b/drivers/media/pci/ivtv/ivtv-i2c.c
new file mode 100644
index 0000000..d47f41a
--- /dev/null
+++ b/drivers/media/pci/ivtv/ivtv-i2c.c
@@ -0,0 +1,760 @@
+/*
+    I2C functions
+    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
+    Copyright (C) 2005-2007  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+    This file includes an i2c implementation that was reverse engineered
+    from the Hauppauge windows driver.  Older ivtv versions used i2c-algo-bit,
+    which whilst fine under most circumstances, had trouble with the Zilog
+    CPU on the PVR-150 which handles IR functions (occasional inability to
+    communicate with the chip until it was reset) and also with the i2c
+    bus being completely unreachable when multiple PVR cards were present.
+
+    The implementation is very similar to i2c-algo-bit, but there are enough
+    subtle differences that the two are hard to merge.  The general strategy
+    employed by i2c-algo-bit is to use udelay() to implement the timing
+    when putting out bits on the scl/sda lines.  The general strategy taken
+    here is to poll the lines for state changes (see ivtv_waitscl and
+    ivtv_waitsda).  In addition there are small delays at various locations
+    which poll the SCL line 5 times (ivtv_scldelay).  I would guess that
+    since this is memory mapped I/O that the length of those delays is tied
+    to the PCI bus clock.  There is some extra code to do with recovery
+    and retries.  Since it is not known what causes the actual i2c problems
+    in the first place, the only goal if one was to attempt to use
+    i2c-algo-bit would be to try to make it follow the same code path.
+    This would be a lot of work, and I'm also not convinced that it would
+    provide a generic benefit to i2c-algo-bit.  Therefore consider this
+    an engineering solution -- not pretty, but it works.
+
+    Some more general comments about what we are doing:
+
+    The i2c bus is a 2 wire serial bus, with clock (SCL) and data (SDA)
+    lines.  To communicate on the bus (as a master, we don't act as a slave),
+    we first initiate a start condition (ivtv_start).  We then write the
+    address of the device that we want to communicate with, along with a flag
+    that indicates whether this is a read or a write.  The slave then issues
+    an ACK signal (ivtv_ack), which tells us that it is ready for reading /
+    writing.  We then proceed with reading or writing (ivtv_read/ivtv_write),
+    and finally issue a stop condition (ivtv_stop) to make the bus available
+    to other masters.
+
+    There is an additional form of transaction where a write may be
+    immediately followed by a read.  In this case, there is no intervening
+    stop condition.  (Only the msp3400 chip uses this method of data transfer).
+ */
+
+#include "ivtv-driver.h"
+#include "ivtv-cards.h"
+#include "ivtv-gpio.h"
+#include "ivtv-i2c.h"
+#include <media/cx25840.h>
+
+/* i2c implementation for cx23415/6 chip, ivtv project.
+ * Author: Kevin Thayer (nufan_wfk at yahoo.com)
+ */
+/* i2c stuff */
+#define IVTV_REG_I2C_SETSCL_OFFSET 0x7000
+#define IVTV_REG_I2C_SETSDA_OFFSET 0x7004
+#define IVTV_REG_I2C_GETSCL_OFFSET 0x7008
+#define IVTV_REG_I2C_GETSDA_OFFSET 0x700c
+
+#define IVTV_CS53L32A_I2C_ADDR		0x11
+#define IVTV_M52790_I2C_ADDR		0x48
+#define IVTV_CX25840_I2C_ADDR 		0x44
+#define IVTV_SAA7115_I2C_ADDR 		0x21
+#define IVTV_SAA7127_I2C_ADDR 		0x44
+#define IVTV_SAA717x_I2C_ADDR 		0x21
+#define IVTV_MSP3400_I2C_ADDR 		0x40
+#define IVTV_HAUPPAUGE_I2C_ADDR 	0x50
+#define IVTV_WM8739_I2C_ADDR 		0x1a
+#define IVTV_WM8775_I2C_ADDR		0x1b
+#define IVTV_TEA5767_I2C_ADDR		0x60
+#define IVTV_UPD64031A_I2C_ADDR 	0x12
+#define IVTV_UPD64083_I2C_ADDR 		0x5c
+#define IVTV_VP27SMPX_I2C_ADDR      	0x5b
+#define IVTV_M52790_I2C_ADDR      	0x48
+#define IVTV_AVERMEDIA_IR_RX_I2C_ADDR	0x40
+#define IVTV_HAUP_EXT_IR_RX_I2C_ADDR 	0x1a
+#define IVTV_HAUP_INT_IR_RX_I2C_ADDR 	0x18
+#define IVTV_Z8F0811_IR_TX_I2C_ADDR	0x70
+#define IVTV_Z8F0811_IR_RX_I2C_ADDR	0x71
+#define IVTV_ADAPTEC_IR_ADDR		0x6b
+
+/* This array should match the IVTV_HW_ defines */
+static const u8 hw_addrs[] = {
+	IVTV_CX25840_I2C_ADDR,
+	IVTV_SAA7115_I2C_ADDR,
+	IVTV_SAA7127_I2C_ADDR,
+	IVTV_MSP3400_I2C_ADDR,
+	0,
+	IVTV_WM8775_I2C_ADDR,
+	IVTV_CS53L32A_I2C_ADDR,
+	0,
+	IVTV_SAA7115_I2C_ADDR,
+	IVTV_UPD64031A_I2C_ADDR,
+	IVTV_UPD64083_I2C_ADDR,
+	IVTV_SAA717x_I2C_ADDR,
+	IVTV_WM8739_I2C_ADDR,
+	IVTV_VP27SMPX_I2C_ADDR,
+	IVTV_M52790_I2C_ADDR,
+	0,				/* IVTV_HW_GPIO dummy driver ID */
+	IVTV_AVERMEDIA_IR_RX_I2C_ADDR,	/* IVTV_HW_I2C_IR_RX_AVER */
+	IVTV_HAUP_EXT_IR_RX_I2C_ADDR,	/* IVTV_HW_I2C_IR_RX_HAUP_EXT */
+	IVTV_HAUP_INT_IR_RX_I2C_ADDR,	/* IVTV_HW_I2C_IR_RX_HAUP_INT */
+	IVTV_Z8F0811_IR_TX_I2C_ADDR,	/* IVTV_HW_Z8F0811_IR_TX_HAUP */
+	IVTV_Z8F0811_IR_RX_I2C_ADDR,	/* IVTV_HW_Z8F0811_IR_RX_HAUP */
+	IVTV_ADAPTEC_IR_ADDR,		/* IVTV_HW_I2C_IR_RX_ADAPTEC */
+};
+
+/* This array should match the IVTV_HW_ defines */
+static const char * const hw_devicenames[] = {
+	"cx25840",
+	"saa7115",
+	"saa7127_auto",	/* saa7127 or saa7129 */
+	"msp3400",
+	"tuner",
+	"wm8775",
+	"cs53l32a",
+	"tveeprom",
+	"saa7114",
+	"upd64031a",
+	"upd64083",
+	"saa717x",
+	"wm8739",
+	"vp27smpx",
+	"m52790",
+	"gpio",
+	"ir_video",		/* IVTV_HW_I2C_IR_RX_AVER */
+	"ir_video",		/* IVTV_HW_I2C_IR_RX_HAUP_EXT */
+	"ir_video",		/* IVTV_HW_I2C_IR_RX_HAUP_INT */
+	"ir_tx_z8f0811_haup",	/* IVTV_HW_Z8F0811_IR_TX_HAUP */
+	"ir_rx_z8f0811_haup",	/* IVTV_HW_Z8F0811_IR_RX_HAUP */
+	"ir_video",		/* IVTV_HW_I2C_IR_RX_ADAPTEC */
+};
+
+static int get_key_adaptec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+{
+	unsigned char keybuf[4];
+
+	keybuf[0] = 0x00;
+	i2c_master_send(ir->c, keybuf, 1);
+	/* poll IR chip */
+	if (i2c_master_recv(ir->c, keybuf, sizeof(keybuf)) != sizeof(keybuf)) {
+		return 0;
+	}
+
+	/* key pressed ? */
+	if (keybuf[2] == 0xff)
+		return 0;
+
+	/* remove repeat bit */
+	keybuf[2] &= 0x7f;
+	keybuf[3] |= 0x80;
+
+	*ir_key = keybuf[3] | keybuf[2] << 8 | keybuf[1] << 16 |keybuf[0] << 24;
+	*ir_raw = *ir_key;
+
+	return 1;
+}
+
+static int ivtv_i2c_new_ir(struct ivtv *itv, u32 hw, const char *type, u8 addr)
+{
+	struct i2c_board_info info;
+	struct i2c_adapter *adap = &itv->i2c_adap;
+	struct IR_i2c_init_data *init_data = &itv->ir_i2c_init_data;
+	unsigned short addr_list[2] = { addr, I2C_CLIENT_END };
+
+	/* Only allow one IR transmitter to be registered per board */
+	if (hw & IVTV_HW_IR_TX_ANY) {
+		if (itv->hw_flags & IVTV_HW_IR_TX_ANY)
+			return -1;
+		memset(&info, 0, sizeof(struct i2c_board_info));
+		strlcpy(info.type, type, I2C_NAME_SIZE);
+		return i2c_new_probed_device(adap, &info, addr_list, NULL)
+							   == NULL ? -1 : 0;
+	}
+
+	/* Only allow one IR receiver to be registered per board */
+	if (itv->hw_flags & IVTV_HW_IR_RX_ANY)
+		return -1;
+
+	/* Our default information for ir-kbd-i2c.c to use */
+	switch (hw) {
+	case IVTV_HW_I2C_IR_RX_AVER:
+		init_data->ir_codes = RC_MAP_AVERMEDIA_CARDBUS;
+		init_data->internal_get_key_func =
+					IR_KBD_GET_KEY_AVERMEDIA_CARDBUS;
+		init_data->type = RC_TYPE_OTHER;
+		init_data->name = "AVerMedia AVerTV card";
+		break;
+	case IVTV_HW_I2C_IR_RX_HAUP_EXT:
+	case IVTV_HW_I2C_IR_RX_HAUP_INT:
+		init_data->ir_codes = RC_MAP_HAUPPAUGE;
+		init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP;
+		init_data->type = RC_TYPE_RC5;
+		init_data->name = itv->card_name;
+		break;
+	case IVTV_HW_Z8F0811_IR_RX_HAUP:
+		/* Default to grey remote */
+		init_data->ir_codes = RC_MAP_HAUPPAUGE;
+		init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR;
+		init_data->type = RC_TYPE_RC5;
+		init_data->name = itv->card_name;
+		break;
+	case IVTV_HW_I2C_IR_RX_ADAPTEC:
+		init_data->get_key = get_key_adaptec;
+		init_data->name = itv->card_name;
+		/* FIXME: The protocol and RC_MAP needs to be corrected */
+		init_data->ir_codes = RC_MAP_EMPTY;
+		init_data->type = RC_TYPE_UNKNOWN;
+		break;
+	}
+
+	memset(&info, 0, sizeof(struct i2c_board_info));
+	info.platform_data = init_data;
+	strlcpy(info.type, type, I2C_NAME_SIZE);
+
+	return i2c_new_probed_device(adap, &info, addr_list, NULL) == NULL ?
+	       -1 : 0;
+}
+
+/* Instantiate the IR receiver device using probing -- undesirable */
+struct i2c_client *ivtv_i2c_new_ir_legacy(struct ivtv *itv)
+{
+	struct i2c_board_info info;
+	/*
+	 * The external IR receiver is at i2c address 0x34.
+	 * The internal IR receiver is at i2c address 0x30.
+	 *
+	 * In theory, both can be fitted, and Hauppauge suggests an external
+	 * overrides an internal.  That's why we probe 0x1a (~0x34) first. CB
+	 *
+	 * Some of these addresses we probe may collide with other i2c address
+	 * allocations, so this function must be called after all other i2c
+	 * devices we care about are registered.
+	 */
+	const unsigned short addr_list[] = {
+		0x1a,	/* Hauppauge IR external - collides with WM8739 */
+		0x18,	/* Hauppauge IR internal */
+		I2C_CLIENT_END
+	};
+
+	memset(&info, 0, sizeof(struct i2c_board_info));
+	strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
+	return i2c_new_probed_device(&itv->i2c_adap, &info, addr_list, NULL);
+}
+
+int ivtv_i2c_register(struct ivtv *itv, unsigned idx)
+{
+	struct v4l2_subdev *sd;
+	struct i2c_adapter *adap = &itv->i2c_adap;
+	const char *type = hw_devicenames[idx];
+	u32 hw = 1 << idx;
+
+	if (idx >= ARRAY_SIZE(hw_addrs))
+		return -1;
+	if (hw == IVTV_HW_TUNER) {
+		/* special tuner handling */
+		sd = v4l2_i2c_new_subdev(&itv->v4l2_dev, adap, type, 0,
+				itv->card_i2c->radio);
+		if (sd)
+			sd->grp_id = 1 << idx;
+		sd = v4l2_i2c_new_subdev(&itv->v4l2_dev, adap, type, 0,
+				itv->card_i2c->demod);
+		if (sd)
+			sd->grp_id = 1 << idx;
+		sd = v4l2_i2c_new_subdev(&itv->v4l2_dev, adap, type, 0,
+				itv->card_i2c->tv);
+		if (sd)
+			sd->grp_id = 1 << idx;
+		return sd ? 0 : -1;
+	}
+
+	if (hw & IVTV_HW_IR_ANY)
+		return ivtv_i2c_new_ir(itv, hw, type, hw_addrs[idx]);
+
+	/* Is it not an I2C device or one we do not wish to register? */
+	if (!hw_addrs[idx])
+		return -1;
+
+	/* It's an I2C device other than an analog tuner or IR chip */
+	if (hw == IVTV_HW_UPD64031A || hw == IVTV_HW_UPD6408X) {
+		sd = v4l2_i2c_new_subdev(&itv->v4l2_dev,
+				adap, type, 0, I2C_ADDRS(hw_addrs[idx]));
+	} else if (hw == IVTV_HW_CX25840) {
+		struct cx25840_platform_data pdata;
+		struct i2c_board_info cx25840_info = {
+			.type = "cx25840",
+			.addr = hw_addrs[idx],
+			.platform_data = &pdata,
+		};
+
+		pdata.pvr150_workaround = itv->pvr150_workaround;
+		sd = v4l2_i2c_new_subdev_board(&itv->v4l2_dev, adap,
+				&cx25840_info, NULL);
+	} else {
+		sd = v4l2_i2c_new_subdev(&itv->v4l2_dev,
+				adap, type, hw_addrs[idx], NULL);
+	}
+	if (sd)
+		sd->grp_id = 1 << idx;
+	return sd ? 0 : -1;
+}
+
+struct v4l2_subdev *ivtv_find_hw(struct ivtv *itv, u32 hw)
+{
+	struct v4l2_subdev *result = NULL;
+	struct v4l2_subdev *sd;
+
+	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->v4l2_dev.lock);
+	return result;
+}
+
+/* Set the serial clock line to the desired state */
+static void ivtv_setscl(struct ivtv *itv, int state)
+{
+	/* write them out */
+	/* write bits are inverted */
+	write_reg(~state, IVTV_REG_I2C_SETSCL_OFFSET);
+}
+
+/* Set the serial data line to the desired state */
+static void ivtv_setsda(struct ivtv *itv, int state)
+{
+	/* write them out */
+	/* write bits are inverted */
+	write_reg(~state & 1, IVTV_REG_I2C_SETSDA_OFFSET);
+}
+
+/* Read the serial clock line */
+static int ivtv_getscl(struct ivtv *itv)
+{
+	return read_reg(IVTV_REG_I2C_GETSCL_OFFSET) & 1;
+}
+
+/* Read the serial data line */
+static int ivtv_getsda(struct ivtv *itv)
+{
+	return read_reg(IVTV_REG_I2C_GETSDA_OFFSET) & 1;
+}
+
+/* Implement a short delay by polling the serial clock line */
+static void ivtv_scldelay(struct ivtv *itv)
+{
+	int i;
+
+	for (i = 0; i < 5; ++i)
+		ivtv_getscl(itv);
+}
+
+/* Wait for the serial clock line to become set to a specific value */
+static int ivtv_waitscl(struct ivtv *itv, int val)
+{
+	int i;
+
+	ivtv_scldelay(itv);
+	for (i = 0; i < 1000; ++i) {
+		if (ivtv_getscl(itv) == val)
+			return 1;
+	}
+	return 0;
+}
+
+/* Wait for the serial data line to become set to a specific value */
+static int ivtv_waitsda(struct ivtv *itv, int val)
+{
+	int i;
+
+	ivtv_scldelay(itv);
+	for (i = 0; i < 1000; ++i) {
+		if (ivtv_getsda(itv) == val)
+			return 1;
+	}
+	return 0;
+}
+
+/* Wait for the slave to issue an ACK */
+static int ivtv_ack(struct ivtv *itv)
+{
+	int ret = 0;
+
+	if (ivtv_getscl(itv) == 1) {
+		IVTV_DEBUG_HI_I2C("SCL was high starting an ack\n");
+		ivtv_setscl(itv, 0);
+		if (!ivtv_waitscl(itv, 0)) {
+			IVTV_DEBUG_I2C("Could not set SCL low starting an ack\n");
+			return -EREMOTEIO;
+		}
+	}
+	ivtv_setsda(itv, 1);
+	ivtv_scldelay(itv);
+	ivtv_setscl(itv, 1);
+	if (!ivtv_waitsda(itv, 0)) {
+		IVTV_DEBUG_I2C("Slave did not ack\n");
+		ret = -EREMOTEIO;
+	}
+	ivtv_setscl(itv, 0);
+	if (!ivtv_waitscl(itv, 0)) {
+		IVTV_DEBUG_I2C("Failed to set SCL low after ACK\n");
+		ret = -EREMOTEIO;
+	}
+	return ret;
+}
+
+/* Write a single byte to the i2c bus and wait for the slave to ACK */
+static int ivtv_sendbyte(struct ivtv *itv, unsigned char byte)
+{
+	int i, bit;
+
+	IVTV_DEBUG_HI_I2C("write %x\n",byte);
+	for (i = 0; i < 8; ++i, byte<<=1) {
+		ivtv_setscl(itv, 0);
+		if (!ivtv_waitscl(itv, 0)) {
+			IVTV_DEBUG_I2C("Error setting SCL low\n");
+			return -EREMOTEIO;
+		}
+		bit = (byte>>7)&1;
+		ivtv_setsda(itv, bit);
+		if (!ivtv_waitsda(itv, bit)) {
+			IVTV_DEBUG_I2C("Error setting SDA\n");
+			return -EREMOTEIO;
+		}
+		ivtv_setscl(itv, 1);
+		if (!ivtv_waitscl(itv, 1)) {
+			IVTV_DEBUG_I2C("Slave not ready for bit\n");
+			return -EREMOTEIO;
+		}
+	}
+	ivtv_setscl(itv, 0);
+	if (!ivtv_waitscl(itv, 0)) {
+		IVTV_DEBUG_I2C("Error setting SCL low\n");
+		return -EREMOTEIO;
+	}
+	return ivtv_ack(itv);
+}
+
+/* Read a byte from the i2c bus and send a NACK if applicable (i.e. for the
+   final byte) */
+static int ivtv_readbyte(struct ivtv *itv, unsigned char *byte, int nack)
+{
+	int i;
+
+	*byte = 0;
+
+	ivtv_setsda(itv, 1);
+	ivtv_scldelay(itv);
+	for (i = 0; i < 8; ++i) {
+		ivtv_setscl(itv, 0);
+		ivtv_scldelay(itv);
+		ivtv_setscl(itv, 1);
+		if (!ivtv_waitscl(itv, 1)) {
+			IVTV_DEBUG_I2C("Error setting SCL high\n");
+			return -EREMOTEIO;
+		}
+		*byte = ((*byte)<<1)|ivtv_getsda(itv);
+	}
+	ivtv_setscl(itv, 0);
+	ivtv_scldelay(itv);
+	ivtv_setsda(itv, nack);
+	ivtv_scldelay(itv);
+	ivtv_setscl(itv, 1);
+	ivtv_scldelay(itv);
+	ivtv_setscl(itv, 0);
+	ivtv_scldelay(itv);
+	IVTV_DEBUG_HI_I2C("read %x\n",*byte);
+	return 0;
+}
+
+/* Issue a start condition on the i2c bus to alert slaves to prepare for
+   an address write */
+static int ivtv_start(struct ivtv *itv)
+{
+	int sda;
+
+	sda = ivtv_getsda(itv);
+	if (sda != 1) {
+		IVTV_DEBUG_HI_I2C("SDA was low at start\n");
+		ivtv_setsda(itv, 1);
+		if (!ivtv_waitsda(itv, 1)) {
+			IVTV_DEBUG_I2C("SDA stuck low\n");
+			return -EREMOTEIO;
+		}
+	}
+	if (ivtv_getscl(itv) != 1) {
+		ivtv_setscl(itv, 1);
+		if (!ivtv_waitscl(itv, 1)) {
+			IVTV_DEBUG_I2C("SCL stuck low at start\n");
+			return -EREMOTEIO;
+		}
+	}
+	ivtv_setsda(itv, 0);
+	ivtv_scldelay(itv);
+	return 0;
+}
+
+/* Issue a stop condition on the i2c bus to release it */
+static int ivtv_stop(struct ivtv *itv)
+{
+	int i;
+
+	if (ivtv_getscl(itv) != 0) {
+		IVTV_DEBUG_HI_I2C("SCL not low when stopping\n");
+		ivtv_setscl(itv, 0);
+		if (!ivtv_waitscl(itv, 0)) {
+			IVTV_DEBUG_I2C("SCL could not be set low\n");
+		}
+	}
+	ivtv_setsda(itv, 0);
+	ivtv_scldelay(itv);
+	ivtv_setscl(itv, 1);
+	if (!ivtv_waitscl(itv, 1)) {
+		IVTV_DEBUG_I2C("SCL could not be set high\n");
+		return -EREMOTEIO;
+	}
+	ivtv_scldelay(itv);
+	ivtv_setsda(itv, 1);
+	if (!ivtv_waitsda(itv, 1)) {
+		IVTV_DEBUG_I2C("resetting I2C\n");
+		for (i = 0; i < 16; ++i) {
+			ivtv_setscl(itv, 0);
+			ivtv_scldelay(itv);
+			ivtv_setscl(itv, 1);
+			ivtv_scldelay(itv);
+			ivtv_setsda(itv, 1);
+		}
+		ivtv_waitsda(itv, 1);
+		return -EREMOTEIO;
+	}
+	return 0;
+}
+
+/* Write a message to the given i2c slave.  do_stop may be 0 to prevent
+   issuing the i2c stop condition (when following with a read) */
+static int ivtv_write(struct ivtv *itv, unsigned char addr, unsigned char *data, u32 len, int do_stop)
+{
+	int retry, ret = -EREMOTEIO;
+	u32 i;
+
+	for (retry = 0; ret != 0 && retry < 8; ++retry) {
+		ret = ivtv_start(itv);
+
+		if (ret == 0) {
+			ret = ivtv_sendbyte(itv, addr<<1);
+			for (i = 0; ret == 0 && i < len; ++i)
+				ret = ivtv_sendbyte(itv, data[i]);
+		}
+		if (ret != 0 || do_stop) {
+			ivtv_stop(itv);
+		}
+	}
+	if (ret)
+		IVTV_DEBUG_I2C("i2c write to %x failed\n", addr);
+	return ret;
+}
+
+/* Read data from the given i2c slave.  A stop condition is always issued. */
+static int ivtv_read(struct ivtv *itv, unsigned char addr, unsigned char *data, u32 len)
+{
+	int retry, ret = -EREMOTEIO;
+	u32 i;
+
+	for (retry = 0; ret != 0 && retry < 8; ++retry) {
+		ret = ivtv_start(itv);
+		if (ret == 0)
+			ret = ivtv_sendbyte(itv, (addr << 1) | 1);
+		for (i = 0; ret == 0 && i < len; ++i) {
+			ret = ivtv_readbyte(itv, &data[i], i == len - 1);
+		}
+		ivtv_stop(itv);
+	}
+	if (ret)
+		IVTV_DEBUG_I2C("i2c read from %x failed\n", addr);
+	return ret;
+}
+
+/* Kernel i2c transfer implementation.  Takes a number of messages to be read
+   or written.  If a read follows a write, this will occur without an
+   intervening stop condition */
+static int ivtv_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
+{
+	struct v4l2_device *v4l2_dev = i2c_get_adapdata(i2c_adap);
+	struct ivtv *itv = to_ivtv(v4l2_dev);
+	int retval;
+	int i;
+
+	mutex_lock(&itv->i2c_bus_lock);
+	for (i = retval = 0; retval == 0 && i < num; i++) {
+		if (msgs[i].flags & I2C_M_RD)
+			retval = ivtv_read(itv, msgs[i].addr, msgs[i].buf, msgs[i].len);
+		else {
+			/* if followed by a read, don't stop */
+			int stop = !(i + 1 < num && msgs[i + 1].flags == I2C_M_RD);
+
+			retval = ivtv_write(itv, msgs[i].addr, msgs[i].buf, msgs[i].len, stop);
+		}
+	}
+	mutex_unlock(&itv->i2c_bus_lock);
+	return retval ? retval : num;
+}
+
+/* Kernel i2c capabilities */
+static u32 ivtv_functionality(struct i2c_adapter *adap)
+{
+	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+static struct i2c_algorithm ivtv_algo = {
+	.master_xfer   = ivtv_xfer,
+	.functionality = ivtv_functionality,
+};
+
+/* template for our-bit banger */
+static struct i2c_adapter ivtv_i2c_adap_hw_template = {
+	.name = "ivtv i2c driver",
+	.algo = &ivtv_algo,
+	.algo_data = NULL,			/* filled from template */
+	.owner = THIS_MODULE,
+};
+
+static void ivtv_setscl_old(void *data, int state)
+{
+	struct ivtv *itv = (struct ivtv *)data;
+
+	if (state)
+		itv->i2c_state |= 0x01;
+	else
+		itv->i2c_state &= ~0x01;
+
+	/* write them out */
+	/* write bits are inverted */
+	write_reg(~itv->i2c_state, IVTV_REG_I2C_SETSCL_OFFSET);
+}
+
+static void ivtv_setsda_old(void *data, int state)
+{
+	struct ivtv *itv = (struct ivtv *)data;
+
+	if (state)
+		itv->i2c_state |= 0x01;
+	else
+		itv->i2c_state &= ~0x01;
+
+	/* write them out */
+	/* write bits are inverted */
+	write_reg(~itv->i2c_state, IVTV_REG_I2C_SETSDA_OFFSET);
+}
+
+static int ivtv_getscl_old(void *data)
+{
+	struct ivtv *itv = (struct ivtv *)data;
+
+	return read_reg(IVTV_REG_I2C_GETSCL_OFFSET) & 1;
+}
+
+static int ivtv_getsda_old(void *data)
+{
+	struct ivtv *itv = (struct ivtv *)data;
+
+	return read_reg(IVTV_REG_I2C_GETSDA_OFFSET) & 1;
+}
+
+/* template for i2c-bit-algo */
+static struct i2c_adapter ivtv_i2c_adap_template = {
+	.name = "ivtv i2c driver",
+	.algo = NULL,                   /* set by i2c-algo-bit */
+	.algo_data = NULL,              /* filled from template */
+	.owner = THIS_MODULE,
+};
+
+#define IVTV_ALGO_BIT_TIMEOUT	(2)	/* seconds */
+
+static const struct i2c_algo_bit_data ivtv_i2c_algo_template = {
+	.setsda		= ivtv_setsda_old,
+	.setscl		= ivtv_setscl_old,
+	.getsda		= ivtv_getsda_old,
+	.getscl		= ivtv_getscl_old,
+	.udelay		= IVTV_DEFAULT_I2C_CLOCK_PERIOD / 2,  /* microseconds */
+	.timeout	= IVTV_ALGO_BIT_TIMEOUT * HZ,         /* jiffies */
+};
+
+static struct i2c_client ivtv_i2c_client_template = {
+	.name = "ivtv internal",
+};
+
+/* init + register i2c adapter */
+int init_ivtv_i2c(struct ivtv *itv)
+{
+	int retval;
+
+	IVTV_DEBUG_I2C("i2c init\n");
+
+	/* Sanity checks for the I2C hardware arrays. They must be the
+	 * same size.
+	 */
+	if (ARRAY_SIZE(hw_devicenames) != ARRAY_SIZE(hw_addrs)) {
+		IVTV_ERR("Mismatched I2C hardware arrays\n");
+		return -ENODEV;
+	}
+	if (itv->options.newi2c > 0) {
+		memcpy(&itv->i2c_adap, &ivtv_i2c_adap_hw_template,
+		       sizeof(struct i2c_adapter));
+	} else {
+		memcpy(&itv->i2c_adap, &ivtv_i2c_adap_template,
+		       sizeof(struct i2c_adapter));
+		memcpy(&itv->i2c_algo, &ivtv_i2c_algo_template,
+		       sizeof(struct i2c_algo_bit_data));
+	}
+	itv->i2c_algo.udelay = itv->options.i2c_clock_period / 2;
+	itv->i2c_algo.data = itv;
+	itv->i2c_adap.algo_data = &itv->i2c_algo;
+
+	sprintf(itv->i2c_adap.name + strlen(itv->i2c_adap.name), " #%d",
+		itv->instance);
+	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->pdev->dev;
+
+	IVTV_DEBUG_I2C("setting scl and sda to 1\n");
+	ivtv_setscl(itv, 1);
+	ivtv_setsda(itv, 1);
+
+	if (itv->options.newi2c > 0)
+		retval = i2c_add_adapter(&itv->i2c_adap);
+	else
+		retval = i2c_bit_add_bus(&itv->i2c_adap);
+
+	return retval;
+}
+
+void exit_ivtv_i2c(struct ivtv *itv)
+{
+	IVTV_DEBUG_I2C("i2c exit\n");
+
+	i2c_del_adapter(&itv->i2c_adap);
+}
diff --git a/drivers/media/pci/ivtv/ivtv-i2c.h b/drivers/media/pci/ivtv/ivtv-i2c.h
new file mode 100644
index 0000000..7b9ec1c
--- /dev/null
+++ b/drivers/media/pci/ivtv/ivtv-i2c.h
@@ -0,0 +1,32 @@
+/*
+    I2C functions
+    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
+    Copyright (C) 2005-2007  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef IVTV_I2C_H
+#define IVTV_I2C_H
+
+struct i2c_client *ivtv_i2c_new_ir_legacy(struct ivtv *itv);
+int ivtv_i2c_register(struct ivtv *itv, unsigned idx);
+struct v4l2_subdev *ivtv_find_hw(struct ivtv *itv, u32 hw);
+
+/* init + register i2c adapter */
+int init_ivtv_i2c(struct ivtv *itv);
+void exit_ivtv_i2c(struct ivtv *itv);
+
+#endif
diff --git a/drivers/media/pci/ivtv/ivtv-ioctl.c b/drivers/media/pci/ivtv/ivtv-ioctl.c
new file mode 100644
index 0000000..32a5910
--- /dev/null
+++ b/drivers/media/pci/ivtv/ivtv-ioctl.c
@@ -0,0 +1,1899 @@
+/*
+    ioctl system call
+    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
+    Copyright (C) 2005-2007  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "ivtv-driver.h"
+#include "ivtv-version.h"
+#include "ivtv-mailbox.h"
+#include "ivtv-i2c.h"
+#include "ivtv-queue.h"
+#include "ivtv-fileops.h"
+#include "ivtv-vbi.h"
+#include "ivtv-routing.h"
+#include "ivtv-streams.h"
+#include "ivtv-yuv.h"
+#include "ivtv-ioctl.h"
+#include "ivtv-gpio.h"
+#include "ivtv-controls.h"
+#include "ivtv-cards.h"
+#include <media/saa7127.h>
+#include <media/tveeprom.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-event.h>
+#include <linux/dvb/audio.h>
+
+u16 ivtv_service2vbi(int type)
+{
+	switch (type) {
+		case V4L2_SLICED_TELETEXT_B:
+			return IVTV_SLICED_TYPE_TELETEXT_B;
+		case V4L2_SLICED_CAPTION_525:
+			return IVTV_SLICED_TYPE_CAPTION_525;
+		case V4L2_SLICED_WSS_625:
+			return IVTV_SLICED_TYPE_WSS_625;
+		case V4L2_SLICED_VPS:
+			return IVTV_SLICED_TYPE_VPS;
+		default:
+			return 0;
+	}
+}
+
+static int valid_service_line(int field, int line, int is_pal)
+{
+	return (is_pal && line >= 6 && (line != 23 || field == 0)) ||
+	       (!is_pal && line >= 10 && line < 22);
+}
+
+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);
+	int i;
+
+	set = set & valid_set;
+	if (set == 0 || !valid_service_line(field, line, is_pal)) {
+		return 0;
+	}
+	if (!is_pal) {
+		if (line == 21 && (set & V4L2_SLICED_CAPTION_525))
+			return V4L2_SLICED_CAPTION_525;
+	}
+	else {
+		if (line == 16 && field == 0 && (set & V4L2_SLICED_VPS))
+			return V4L2_SLICED_VPS;
+		if (line == 23 && field == 0 && (set & V4L2_SLICED_WSS_625))
+			return V4L2_SLICED_WSS_625;
+		if (line == 23)
+			return 0;
+	}
+	for (i = 0; i < 32; i++) {
+		if ((1 << i) & set)
+			return 1 << i;
+	}
+	return 0;
+}
+
+void ivtv_expand_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal)
+{
+	u16 set = fmt->service_set;
+	int f, l;
+
+	fmt->service_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, set, is_pal);
+		}
+	}
+}
+
+static void check_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal)
+{
+	int f, l;
+
+	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);
+		}
+	}
+}
+
+u16 ivtv_get_service_set(struct v4l2_sliced_vbi_format *fmt)
+{
+	int f, l;
+	u16 set = 0;
+
+	for (f = 0; f < 2; f++) {
+		for (l = 0; l < 24; l++) {
+			set |= fmt->service_lines[f][l];
+		}
+	}
+	return set;
+}
+
+void ivtv_set_osd_alpha(struct ivtv *itv)
+{
+	ivtv_vapi(itv, CX2341X_OSD_SET_GLOBAL_ALPHA, 3,
+		itv->osd_global_alpha_state, itv->osd_global_alpha, !itv->osd_local_alpha_state);
+	ivtv_vapi(itv, CX2341X_OSD_SET_CHROMA_KEY, 2, itv->osd_chroma_key_state, itv->osd_chroma_key);
+}
+
+int ivtv_set_speed(struct ivtv *itv, int speed)
+{
+	u32 data[CX2341X_MBOX_MAX_DATA];
+	int single_step = (speed == 1 || speed == -1);
+	DEFINE_WAIT(wait);
+
+	if (speed == 0) speed = 1000;
+
+	/* No change? */
+	if (speed == itv->speed && !single_step)
+		return 0;
+
+	if (single_step && (speed < 0) == (itv->speed < 0)) {
+		/* Single step video and no need to change direction */
+		ivtv_vapi(itv, CX2341X_DEC_STEP_VIDEO, 1, 0);
+		itv->speed = speed;
+		return 0;
+	}
+	if (single_step)
+		/* Need to change direction */
+		speed = speed < 0 ? -1000 : 1000;
+
+	data[0] = (speed > 1000 || speed < -1000) ? 0x80000000 : 0;
+	data[0] |= (speed > 1000 || speed < -1500) ? 0x40000000 : 0;
+	data[1] = (speed < 0);
+	data[2] = speed < 0 ? 3 : 7;
+	data[3] = v4l2_ctrl_g_ctrl(itv->cxhdl.video_b_frames);
+	data[4] = (speed == 1500 || speed == 500) ? itv->speed_mute_audio : 0;
+	data[5] = 0;
+	data[6] = 0;
+
+	if (speed == 1500 || speed == -1500) data[0] |= 1;
+	else if (speed == 2000 || speed == -2000) data[0] |= 2;
+	else if (speed > -1000 && speed < 0) data[0] |= (-1000 / speed);
+	else if (speed < 1000 && speed > 0) data[0] |= (1000 / speed);
+
+	/* If not decoding, just change speed setting */
+	if (atomic_read(&itv->decoding) > 0) {
+		int got_sig = 0;
+
+		/* Stop all DMA and decoding activity */
+		ivtv_vapi(itv, CX2341X_DEC_PAUSE_PLAYBACK, 1, 0);
+
+		/* Wait for any DMA to finish */
+		mutex_unlock(&itv->serialize_lock);
+		prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE);
+		while (test_bit(IVTV_F_I_DMA, &itv->i_flags)) {
+			got_sig = signal_pending(current);
+			if (got_sig)
+				break;
+			got_sig = 0;
+			schedule();
+		}
+		finish_wait(&itv->dma_waitq, &wait);
+		mutex_lock(&itv->serialize_lock);
+		if (got_sig)
+			return -EINTR;
+
+		/* Change Speed safely */
+		ivtv_api(itv, CX2341X_DEC_SET_PLAYBACK_SPEED, 7, data);
+		IVTV_DEBUG_INFO("Setting Speed to 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n",
+				data[0], data[1], data[2], data[3], data[4], data[5], data[6]);
+	}
+	if (single_step) {
+		speed = (speed < 0) ? -1 : 1;
+		ivtv_vapi(itv, CX2341X_DEC_STEP_VIDEO, 1, 0);
+	}
+	itv->speed = speed;
+	return 0;
+}
+
+static int ivtv_validate_speed(int cur_speed, int new_speed)
+{
+	int fact = new_speed < 0 ? -1 : 1;
+	int s;
+
+	if (cur_speed == 0)
+		cur_speed = 1000;
+	if (new_speed < 0)
+		new_speed = -new_speed;
+	if (cur_speed < 0)
+		cur_speed = -cur_speed;
+
+	if (cur_speed <= new_speed) {
+		if (new_speed > 1500)
+			return fact * 2000;
+		if (new_speed > 1000)
+			return fact * 1500;
+	}
+	else {
+		if (new_speed >= 2000)
+			return fact * 2000;
+		if (new_speed >= 1500)
+			return fact * 1500;
+		if (new_speed >= 1000)
+			return fact * 1000;
+	}
+	if (new_speed == 0)
+		return 1000;
+	if (new_speed == 1 || new_speed == 1000)
+		return fact * new_speed;
+
+	s = new_speed;
+	new_speed = 1000 / new_speed;
+	if (1000 / cur_speed == new_speed)
+		new_speed += (cur_speed < s) ? -1 : 1;
+	if (new_speed > 60) return 1000 / (fact * 60);
+	return 1000 / (fact * new_speed);
+}
+
+static int ivtv_video_command(struct ivtv *itv, struct ivtv_open_id *id,
+		struct v4l2_decoder_cmd *dc, int try)
+{
+	struct ivtv_stream *s = &itv->streams[IVTV_DEC_STREAM_TYPE_MPG];
+
+	if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
+		return -EINVAL;
+
+	switch (dc->cmd) {
+	case V4L2_DEC_CMD_START: {
+		dc->flags &= V4L2_DEC_CMD_START_MUTE_AUDIO;
+		dc->start.speed = ivtv_validate_speed(itv->speed, dc->start.speed);
+		if (dc->start.speed < 0)
+			dc->start.format = V4L2_DEC_START_FMT_GOP;
+		else
+			dc->start.format = V4L2_DEC_START_FMT_NONE;
+		if (dc->start.speed != 500 && dc->start.speed != 1500)
+			dc->flags = dc->start.speed == 1000 ? 0 :
+					V4L2_DEC_CMD_START_MUTE_AUDIO;
+		if (try) break;
+
+		itv->speed_mute_audio = dc->flags & V4L2_DEC_CMD_START_MUTE_AUDIO;
+		if (ivtv_set_output_mode(itv, OUT_MPG) != OUT_MPG)
+			return -EBUSY;
+		if (test_and_clear_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags)) {
+			/* forces ivtv_set_speed to be called */
+			itv->speed = 0;
+		}
+		return ivtv_start_decoding(id, dc->start.speed);
+	}
+
+	case V4L2_DEC_CMD_STOP:
+		dc->flags &= V4L2_DEC_CMD_STOP_IMMEDIATELY | V4L2_DEC_CMD_STOP_TO_BLACK;
+		if (dc->flags & V4L2_DEC_CMD_STOP_IMMEDIATELY)
+			dc->stop.pts = 0;
+		if (try) break;
+		if (atomic_read(&itv->decoding) == 0)
+			return 0;
+		if (itv->output_mode != OUT_MPG)
+			return -EBUSY;
+
+		itv->output_mode = OUT_NONE;
+		return ivtv_stop_v4l2_decode_stream(s, dc->flags, dc->stop.pts);
+
+	case V4L2_DEC_CMD_PAUSE:
+		dc->flags &= V4L2_DEC_CMD_PAUSE_TO_BLACK;
+		if (try) break;
+		if (itv->output_mode != OUT_MPG)
+			return -EBUSY;
+		if (atomic_read(&itv->decoding) > 0) {
+			ivtv_vapi(itv, CX2341X_DEC_PAUSE_PLAYBACK, 1,
+				(dc->flags & V4L2_DEC_CMD_PAUSE_TO_BLACK) ? 1 : 0);
+			set_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags);
+		}
+		break;
+
+	case V4L2_DEC_CMD_RESUME:
+		dc->flags = 0;
+		if (try) break;
+		if (itv->output_mode != OUT_MPG)
+			return -EBUSY;
+		if (test_and_clear_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags)) {
+			int speed = itv->speed;
+			itv->speed = 0;
+			return ivtv_start_decoding(id, speed);
+		}
+		break;
+
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int ivtv_g_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+	struct ivtv *itv = fh2id(fh)->itv;
+	struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
+
+	vbifmt->reserved[0] = 0;
+	vbifmt->reserved[1] = 0;
+	if (!(itv->v4l2_cap & V4L2_CAP_SLICED_VBI_OUTPUT))
+		return -EINVAL;
+	vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;
+	if (itv->is_60hz) {
+		vbifmt->service_lines[0][21] = V4L2_SLICED_CAPTION_525;
+		vbifmt->service_lines[1][21] = V4L2_SLICED_CAPTION_525;
+	} else {
+		vbifmt->service_lines[0][23] = V4L2_SLICED_WSS_625;
+		vbifmt->service_lines[0][16] = V4L2_SLICED_VPS;
+	}
+	vbifmt->service_set = ivtv_get_service_set(vbifmt);
+	return 0;
+}
+
+static int ivtv_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+	struct ivtv_open_id *id = fh2id(fh);
+	struct ivtv *itv = id->itv;
+	struct v4l2_pix_format *pixfmt = &fmt->fmt.pix;
+
+	pixfmt->width = itv->cxhdl.width;
+	pixfmt->height = itv->cxhdl.height;
+	pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
+	pixfmt->field = V4L2_FIELD_INTERLACED;
+	pixfmt->priv = 0;
+	if (id->type == IVTV_ENC_STREAM_TYPE_YUV) {
+		pixfmt->pixelformat = V4L2_PIX_FMT_HM12;
+		/* 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;
+		pixfmt->sizeimage = 128 * 1024;
+		pixfmt->bytesperline = 0;
+	}
+	return 0;
+}
+
+static int ivtv_g_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+	struct ivtv *itv = fh2id(fh)->itv;
+	struct v4l2_vbi_format *vbifmt = &fmt->fmt.vbi;
+
+	vbifmt->sampling_rate = 27000000;
+	vbifmt->offset = 248;
+	vbifmt->samples_per_line = itv->vbi.raw_decoder_line_size - 4;
+	vbifmt->sample_format = V4L2_PIX_FMT_GREY;
+	vbifmt->start[0] = itv->vbi.start[0];
+	vbifmt->start[1] = itv->vbi.start[1];
+	vbifmt->count[0] = vbifmt->count[1] = itv->vbi.count;
+	vbifmt->flags = 0;
+	vbifmt->reserved[0] = 0;
+	vbifmt->reserved[1] = 0;
+	return 0;
+}
+
+static int ivtv_g_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+	struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
+	struct ivtv_open_id *id = fh2id(fh);
+	struct ivtv *itv = id->itv;
+
+	vbifmt->reserved[0] = 0;
+	vbifmt->reserved[1] = 0;
+	vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;
+
+	if (id->type == IVTV_DEC_STREAM_TYPE_VBI) {
+		vbifmt->service_set = itv->is_50hz ? V4L2_SLICED_VBI_625 :
+			V4L2_SLICED_VBI_525;
+		ivtv_expand_service_set(vbifmt, itv->is_50hz);
+		return 0;
+	}
+
+	v4l2_subdev_call(itv->sd_video, vbi, g_sliced_fmt, vbifmt);
+	vbifmt->service_set = ivtv_get_service_set(vbifmt);
+	return 0;
+}
+
+static int ivtv_g_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+	struct ivtv_open_id *id = fh2id(fh);
+	struct ivtv *itv = id->itv;
+	struct v4l2_pix_format *pixfmt = &fmt->fmt.pix;
+
+	if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
+		return -EINVAL;
+	pixfmt->width = itv->main_rect.width;
+	pixfmt->height = itv->main_rect.height;
+	pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
+	pixfmt->field = V4L2_FIELD_INTERLACED;
+	pixfmt->priv = 0;
+	if (id->type == IVTV_DEC_STREAM_TYPE_YUV) {
+		switch (itv->yuv_info.lace_mode & IVTV_YUV_MODE_MASK) {
+		case IVTV_YUV_MODE_INTERLACED:
+			pixfmt->field = (itv->yuv_info.lace_mode & IVTV_YUV_SYNC_MASK) ?
+				V4L2_FIELD_INTERLACED_BT : V4L2_FIELD_INTERLACED_TB;
+			break;
+		case IVTV_YUV_MODE_PROGRESSIVE:
+			pixfmt->field = V4L2_FIELD_NONE;
+			break;
+		default:
+			pixfmt->field = V4L2_FIELD_ANY;
+			break;
+		}
+		pixfmt->pixelformat = V4L2_PIX_FMT_HM12;
+		pixfmt->bytesperline = 720;
+		pixfmt->width = itv->yuv_info.v4l2_src_w;
+		pixfmt->height = itv->yuv_info.v4l2_src_h;
+		/* YUV size is (Y=(h*w) + UV=(h*(w/2))) */
+		pixfmt->sizeimage =
+			1080 * ((pixfmt->height + 31) & ~31);
+	} else {
+		pixfmt->pixelformat = V4L2_PIX_FMT_MPEG;
+		pixfmt->sizeimage = 128 * 1024;
+		pixfmt->bytesperline = 0;
+	}
+	return 0;
+}
+
+static int ivtv_g_fmt_vid_out_overlay(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+	struct ivtv *itv = fh2id(fh)->itv;
+	struct v4l2_window *winfmt = &fmt->fmt.win;
+
+	if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
+		return -EINVAL;
+	winfmt->chromakey = itv->osd_chroma_key;
+	winfmt->global_alpha = itv->osd_global_alpha;
+	winfmt->field = V4L2_FIELD_INTERLACED;
+	winfmt->clips = NULL;
+	winfmt->clipcount = 0;
+	winfmt->bitmap = NULL;
+	winfmt->w.top = winfmt->w.left = 0;
+	winfmt->w.width = itv->osd_rect.width;
+	winfmt->w.height = itv->osd_rect.height;
+	return 0;
+}
+
+static int ivtv_try_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+	return ivtv_g_fmt_sliced_vbi_out(file, fh, fmt);
+}
+
+static int ivtv_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+	struct ivtv_open_id *id = fh2id(fh);
+	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, min_h);
+	ivtv_g_fmt_vid_cap(file, fh, fmt);
+	fmt->fmt.pix.width = w;
+	fmt->fmt.pix.height = h;
+	return 0;
+}
+
+static int ivtv_try_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+	return ivtv_g_fmt_vbi_cap(file, fh, fmt);
+}
+
+static int ivtv_try_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+	struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
+	struct ivtv_open_id *id = fh2id(fh);
+	struct ivtv *itv = id->itv;
+
+	if (id->type == IVTV_DEC_STREAM_TYPE_VBI)
+		return ivtv_g_fmt_sliced_vbi_cap(file, fh, fmt);
+
+	/* set sliced VBI capture format */
+	vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;
+	vbifmt->reserved[0] = 0;
+	vbifmt->reserved[1] = 0;
+
+	if (vbifmt->service_set)
+		ivtv_expand_service_set(vbifmt, itv->is_50hz);
+	check_service_set(vbifmt, itv->is_50hz);
+	vbifmt->service_set = ivtv_get_service_set(vbifmt);
+	return 0;
+}
+
+static int ivtv_try_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+	struct ivtv_open_id *id = fh2id(fh);
+	s32 w = fmt->fmt.pix.width;
+	s32 h = fmt->fmt.pix.height;
+	int field = fmt->fmt.pix.field;
+	int ret = ivtv_g_fmt_vid_out(file, fh, fmt);
+
+	w = min(w, 720);
+	w = max(w, 2);
+	/* Why can the height be 576 even when the output is NTSC?
+
+	   Internally the buffers of the PVR350 are always set to 720x576. The
+	   decoded video frame will always be placed in the top left corner of
+	   this buffer. For any video which is not 720x576, the buffer will
+	   then be cropped to remove the unused right and lower areas, with
+	   the remaining image being scaled by the hardware to fit the display
+	   area. The video can be scaled both up and down, so a 720x480 video
+	   can be displayed full-screen on PAL and a 720x576 video can be
+	   displayed without cropping on NTSC.
+
+	   Note that the scaling only occurs on the video stream, the osd
+	   resolution is locked to the broadcast standard and not scaled.
+
+	   Thanks to Ian Armstrong for this explanation. */
+	h = min(h, 576);
+	h = max(h, 2);
+	if (id->type == IVTV_DEC_STREAM_TYPE_YUV)
+		fmt->fmt.pix.field = field;
+	fmt->fmt.pix.width = w;
+	fmt->fmt.pix.height = h;
+	return ret;
+}
+
+static int ivtv_try_fmt_vid_out_overlay(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+	struct ivtv *itv = fh2id(fh)->itv;
+	u32 chromakey = fmt->fmt.win.chromakey;
+	u8 global_alpha = fmt->fmt.win.global_alpha;
+
+	if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
+		return -EINVAL;
+	ivtv_g_fmt_vid_out_overlay(file, fh, fmt);
+	fmt->fmt.win.chromakey = chromakey;
+	fmt->fmt.win.global_alpha = global_alpha;
+	return 0;
+}
+
+static int ivtv_s_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+	return ivtv_g_fmt_sliced_vbi_out(file, fh, fmt);
+}
+
+static int ivtv_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+	struct ivtv_open_id *id = fh2id(fh);
+	struct ivtv *itv = id->itv;
+	struct v4l2_mbus_framefmt mbus_fmt;
+	int ret = ivtv_try_fmt_vid_cap(file, fh, fmt);
+	int w = fmt->fmt.pix.width;
+	int h = fmt->fmt.pix.height;
+
+	if (ret)
+		return ret;
+
+	if (itv->cxhdl.width == w && itv->cxhdl.height == h)
+		return 0;
+
+	if (atomic_read(&itv->capturing) > 0)
+		return -EBUSY;
+
+	itv->cxhdl.width = w;
+	itv->cxhdl.height = h;
+	if (v4l2_ctrl_g_ctrl(itv->cxhdl.video_encoding) == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)
+		fmt->fmt.pix.width /= 2;
+	mbus_fmt.width = fmt->fmt.pix.width;
+	mbus_fmt.height = h;
+	mbus_fmt.code = V4L2_MBUS_FMT_FIXED;
+	v4l2_subdev_call(itv->sd_video, video, s_mbus_fmt, &mbus_fmt);
+	return ivtv_g_fmt_vid_cap(file, fh, fmt);
+}
+
+static int ivtv_s_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+	struct ivtv *itv = fh2id(fh)->itv;
+
+	if (!ivtv_raw_vbi(itv) && atomic_read(&itv->capturing) > 0)
+		return -EBUSY;
+	itv->vbi.sliced_in->service_set = 0;
+	itv->vbi.in.type = V4L2_BUF_TYPE_VBI_CAPTURE;
+	v4l2_subdev_call(itv->sd_video, vbi, s_raw_fmt, &fmt->fmt.vbi);
+	return ivtv_g_fmt_vbi_cap(file, fh, fmt);
+}
+
+static int ivtv_s_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+	struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
+	struct ivtv_open_id *id = fh2id(fh);
+	struct ivtv *itv = id->itv;
+	int ret = ivtv_try_fmt_sliced_vbi_cap(file, fh, fmt);
+
+	if (ret || id->type == IVTV_DEC_STREAM_TYPE_VBI)
+		return ret;
+
+	check_service_set(vbifmt, itv->is_50hz);
+	if (ivtv_raw_vbi(itv) && atomic_read(&itv->capturing) > 0)
+		return -EBUSY;
+	itv->vbi.in.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
+	v4l2_subdev_call(itv->sd_video, vbi, s_sliced_fmt, vbifmt);
+	memcpy(itv->vbi.sliced_in, vbifmt, sizeof(*itv->vbi.sliced_in));
+	return 0;
+}
+
+static int ivtv_s_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+	struct ivtv_open_id *id = fh2id(fh);
+	struct ivtv *itv = id->itv;
+	struct yuv_playback_info *yi = &itv->yuv_info;
+	int ret = ivtv_try_fmt_vid_out(file, fh, fmt);
+
+	if (ret)
+		return ret;
+
+	if (id->type != IVTV_DEC_STREAM_TYPE_YUV)
+		return 0;
+
+	/* Return now if we already have some frame data */
+	if (yi->stream_size)
+		return -EBUSY;
+
+	yi->v4l2_src_w = fmt->fmt.pix.width;
+	yi->v4l2_src_h = fmt->fmt.pix.height;
+
+	switch (fmt->fmt.pix.field) {
+	case V4L2_FIELD_NONE:
+		yi->lace_mode = IVTV_YUV_MODE_PROGRESSIVE;
+		break;
+	case V4L2_FIELD_ANY:
+		yi->lace_mode = IVTV_YUV_MODE_AUTO;
+		break;
+	case V4L2_FIELD_INTERLACED_BT:
+		yi->lace_mode =
+			IVTV_YUV_MODE_INTERLACED|IVTV_YUV_SYNC_ODD;
+		break;
+	case V4L2_FIELD_INTERLACED_TB:
+	default:
+		yi->lace_mode = IVTV_YUV_MODE_INTERLACED;
+		break;
+	}
+	yi->lace_sync_field = (yi->lace_mode & IVTV_YUV_SYNC_MASK) == IVTV_YUV_SYNC_EVEN ? 0 : 1;
+
+	if (test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags))
+		itv->dma_data_req_size =
+			1080 * ((yi->v4l2_src_h + 31) & ~31);
+
+	return 0;
+}
+
+static int ivtv_s_fmt_vid_out_overlay(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+	struct ivtv *itv = fh2id(fh)->itv;
+	int ret = ivtv_try_fmt_vid_out_overlay(file, fh, fmt);
+
+	if (ret == 0) {
+		itv->osd_chroma_key = fmt->fmt.win.chromakey;
+		itv->osd_global_alpha = fmt->fmt.win.global_alpha;
+		ivtv_set_osd_alpha(itv);
+	}
+	return ret;
+}
+
+static int ivtv_g_chip_ident(struct file *file, void *fh, struct v4l2_dbg_chip_ident *chip)
+{
+	struct ivtv *itv = fh2id(fh)->itv;
+
+	chip->ident = V4L2_IDENT_NONE;
+	chip->revision = 0;
+	if (chip->match.type == V4L2_CHIP_MATCH_HOST) {
+		if (v4l2_chip_match_host(&chip->match))
+			chip->ident = itv->has_cx23415 ? V4L2_IDENT_CX23415 : V4L2_IDENT_CX23416;
+		return 0;
+	}
+	if (chip->match.type != V4L2_CHIP_MATCH_I2C_DRIVER &&
+	    chip->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
+		return -EINVAL;
+	/* TODO: is this correct? */
+	return ivtv_call_all_err(itv, core, g_chip_ident, chip);
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int ivtv_itvc(struct ivtv *itv, unsigned int cmd, void *arg)
+{
+	struct v4l2_dbg_register *regs = arg;
+	volatile u8 __iomem *reg_start;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+	if (regs->reg >= IVTV_REG_OFFSET && regs->reg < IVTV_REG_OFFSET + IVTV_REG_SIZE)
+		reg_start = itv->reg_mem - IVTV_REG_OFFSET;
+	else if (itv->has_cx23415 && regs->reg >= IVTV_DECODER_OFFSET &&
+			regs->reg < IVTV_DECODER_OFFSET + IVTV_DECODER_SIZE)
+		reg_start = itv->dec_mem - IVTV_DECODER_OFFSET;
+	else if (regs->reg < IVTV_ENCODER_SIZE)
+		reg_start = itv->enc_mem;
+	else
+		return -EINVAL;
+
+	regs->size = 4;
+	if (cmd == VIDIOC_DBG_G_REGISTER)
+		regs->val = readl(regs->reg + reg_start);
+	else
+		writel(regs->val, regs->reg + reg_start);
+	return 0;
+}
+
+static int ivtv_g_register(struct file *file, void *fh, struct v4l2_dbg_register *reg)
+{
+	struct ivtv *itv = fh2id(fh)->itv;
+
+	if (v4l2_chip_match_host(&reg->match))
+		return ivtv_itvc(itv, VIDIOC_DBG_G_REGISTER, reg);
+	/* TODO: subdev errors should not be ignored, this should become a
+	   subdev helper function. */
+	ivtv_call_all(itv, core, g_register, reg);
+	return 0;
+}
+
+static int ivtv_s_register(struct file *file, void *fh, struct v4l2_dbg_register *reg)
+{
+	struct ivtv *itv = fh2id(fh)->itv;
+
+	if (v4l2_chip_match_host(&reg->match))
+		return ivtv_itvc(itv, VIDIOC_DBG_S_REGISTER, reg);
+	/* TODO: subdev errors should not be ignored, this should become a
+	   subdev helper function. */
+	ivtv_call_all(itv, core, s_register, reg);
+	return 0;
+}
+#endif
+
+static int ivtv_querycap(struct file *file, void *fh, struct v4l2_capability *vcap)
+{
+	struct ivtv_open_id *id = fh2id(file->private_data);
+	struct ivtv *itv = id->itv;
+	struct ivtv_stream *s = &itv->streams[id->type];
+
+	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->pdev));
+	vcap->capabilities = itv->v4l2_cap | V4L2_CAP_DEVICE_CAPS;
+	vcap->device_caps = s->caps;
+	return 0;
+}
+
+static int ivtv_enumaudio(struct file *file, void *fh, struct v4l2_audio *vin)
+{
+	struct ivtv *itv = fh2id(fh)->itv;
+
+	return ivtv_get_audio_input(itv, vin->index, vin);
+}
+
+static int ivtv_g_audio(struct file *file, void *fh, struct v4l2_audio *vin)
+{
+	struct ivtv *itv = fh2id(fh)->itv;
+
+	vin->index = itv->audio_input;
+	return ivtv_get_audio_input(itv, vin->index, vin);
+}
+
+static int ivtv_s_audio(struct file *file, void *fh, struct v4l2_audio *vout)
+{
+	struct ivtv *itv = fh2id(fh)->itv;
+
+	if (vout->index >= itv->nof_audio_inputs)
+		return -EINVAL;
+
+	itv->audio_input = vout->index;
+	ivtv_audio_set_io(itv);
+
+	return 0;
+}
+
+static int ivtv_enumaudout(struct file *file, void *fh, struct v4l2_audioout *vin)
+{
+	struct ivtv *itv = fh2id(fh)->itv;
+
+	/* set it to defaults from our table */
+	return ivtv_get_audio_output(itv, vin->index, vin);
+}
+
+static int ivtv_g_audout(struct file *file, void *fh, struct v4l2_audioout *vin)
+{
+	struct ivtv *itv = fh2id(fh)->itv;
+
+	vin->index = 0;
+	return ivtv_get_audio_output(itv, vin->index, vin);
+}
+
+static int ivtv_s_audout(struct file *file, void *fh, struct v4l2_audioout *vout)
+{
+	struct ivtv *itv = fh2id(fh)->itv;
+
+	return ivtv_get_audio_output(itv, vout->index, vout);
+}
+
+static int ivtv_enum_input(struct file *file, void *fh, struct v4l2_input *vin)
+{
+	struct ivtv *itv = fh2id(fh)->itv;
+
+	/* set it to defaults from our table */
+	return ivtv_get_input(itv, vin->index, vin);
+}
+
+static int ivtv_enum_output(struct file *file, void *fh, struct v4l2_output *vout)
+{
+	struct ivtv *itv = fh2id(fh)->itv;
+
+	return ivtv_get_output(itv, vout->index, vout);
+}
+
+static int ivtv_cropcap(struct file *file, void *fh, struct v4l2_cropcap *cropcap)
+{
+	struct ivtv_open_id *id = fh2id(fh);
+	struct ivtv *itv = id->itv;
+	struct yuv_playback_info *yi = &itv->yuv_info;
+	int streamtype;
+
+	streamtype = id->type;
+
+	if (cropcap->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
+		return -EINVAL;
+	cropcap->bounds.top = cropcap->bounds.left = 0;
+	cropcap->bounds.width = 720;
+	if (cropcap->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+		cropcap->bounds.height = itv->is_50hz ? 576 : 480;
+		cropcap->pixelaspect.numerator = itv->is_50hz ? 59 : 10;
+		cropcap->pixelaspect.denominator = itv->is_50hz ? 54 : 11;
+	} else if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
+		if (yi->track_osd) {
+			cropcap->bounds.width = yi->osd_full_w;
+			cropcap->bounds.height = yi->osd_full_h;
+		} else {
+			cropcap->bounds.width = 720;
+			cropcap->bounds.height =
+					itv->is_out_50hz ? 576 : 480;
+		}
+		cropcap->pixelaspect.numerator = itv->is_out_50hz ? 59 : 10;
+		cropcap->pixelaspect.denominator = itv->is_out_50hz ? 54 : 11;
+	} else {
+		cropcap->bounds.height = itv->is_out_50hz ? 576 : 480;
+		cropcap->pixelaspect.numerator = itv->is_out_50hz ? 59 : 10;
+		cropcap->pixelaspect.denominator = itv->is_out_50hz ? 54 : 11;
+	}
+	cropcap->defrect = cropcap->bounds;
+	return 0;
+}
+
+static int ivtv_s_crop(struct file *file, void *fh, struct v4l2_crop *crop)
+{
+	struct ivtv_open_id *id = fh2id(fh);
+	struct ivtv *itv = id->itv;
+	struct yuv_playback_info *yi = &itv->yuv_info;
+	int streamtype;
+
+	streamtype = id->type;
+
+	if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
+	    (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
+		if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
+			yi->main_rect = crop->c;
+			return 0;
+		} else {
+			if (!ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
+				crop->c.width, crop->c.height, crop->c.left, crop->c.top)) {
+				itv->main_rect = crop->c;
+				return 0;
+			}
+		}
+		return -EINVAL;
+	}
+	return -EINVAL;
+}
+
+static int ivtv_g_crop(struct file *file, void *fh, struct v4l2_crop *crop)
+{
+	struct ivtv_open_id *id = fh2id(fh);
+	struct ivtv *itv = id->itv;
+	struct yuv_playback_info *yi = &itv->yuv_info;
+	int streamtype;
+
+	streamtype = id->type;
+
+	if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
+	    (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
+		if (streamtype == IVTV_DEC_STREAM_TYPE_YUV)
+			crop->c = yi->main_rect;
+		else
+			crop->c = itv->main_rect;
+		return 0;
+	}
+	return -EINVAL;
+}
+
+static int ivtv_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt)
+{
+	static struct v4l2_fmtdesc formats[] = {
+		{ 0, 0, 0,
+		  "HM12 (YUV 4:2:0)", V4L2_PIX_FMT_HM12,
+		  { 0, 0, 0, 0 }
+		},
+		{ 1, 0, V4L2_FMT_FLAG_COMPRESSED,
+		  "MPEG", V4L2_PIX_FMT_MPEG,
+		  { 0, 0, 0, 0 }
+		}
+	};
+	enum v4l2_buf_type type = fmt->type;
+
+	if (fmt->index > 1)
+		return -EINVAL;
+
+	*fmt = formats[fmt->index];
+	fmt->type = type;
+	return 0;
+}
+
+static int ivtv_enum_fmt_vid_out(struct file *file, void *fh, struct v4l2_fmtdesc *fmt)
+{
+	struct ivtv *itv = fh2id(fh)->itv;
+
+	static struct v4l2_fmtdesc formats[] = {
+		{ 0, 0, 0,
+		  "HM12 (YUV 4:2:0)", V4L2_PIX_FMT_HM12,
+		  { 0, 0, 0, 0 }
+		},
+		{ 1, 0, V4L2_FMT_FLAG_COMPRESSED,
+		  "MPEG", V4L2_PIX_FMT_MPEG,
+		  { 0, 0, 0, 0 }
+		}
+	};
+	enum v4l2_buf_type type = fmt->type;
+
+	if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
+		return -EINVAL;
+
+	if (fmt->index > 1)
+		return -EINVAL;
+
+	*fmt = formats[fmt->index];
+	fmt->type = type;
+
+	return 0;
+}
+
+static int ivtv_g_input(struct file *file, void *fh, unsigned int *i)
+{
+	struct ivtv *itv = fh2id(fh)->itv;
+
+	*i = itv->active_input;
+
+	return 0;
+}
+
+int ivtv_s_input(struct file *file, void *fh, unsigned int inp)
+{
+	struct ivtv *itv = fh2id(fh)->itv;
+
+	if (inp < 0 || inp >= itv->nof_inputs)
+		return -EINVAL;
+
+	if (inp == itv->active_input) {
+		IVTV_DEBUG_INFO("Input unchanged\n");
+		return 0;
+	}
+
+	if (atomic_read(&itv->capturing) > 0) {
+		return -EBUSY;
+	}
+
+	IVTV_DEBUG_INFO("Changing input from %d to %d\n",
+			itv->active_input, inp);
+
+	itv->active_input = inp;
+	/* Set the audio input to whatever is appropriate for the
+	   input type. */
+	itv->audio_input = itv->card->video_inputs[inp].audio_index;
+
+	/* prevent others from messing with the streams until
+	   we're finished changing inputs. */
+	ivtv_mute(itv);
+	ivtv_video_set_io(itv);
+	ivtv_audio_set_io(itv);
+	ivtv_unmute(itv);
+
+	return 0;
+}
+
+static int ivtv_g_output(struct file *file, void *fh, unsigned int *i)
+{
+	struct ivtv *itv = fh2id(fh)->itv;
+
+	if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
+		return -EINVAL;
+
+	*i = itv->active_output;
+
+	return 0;
+}
+
+static int ivtv_s_output(struct file *file, void *fh, unsigned int outp)
+{
+	struct ivtv *itv = fh2id(fh)->itv;
+
+	if (outp >= itv->card->nof_outputs)
+		return -EINVAL;
+
+	if (outp == itv->active_output) {
+		IVTV_DEBUG_INFO("Output unchanged\n");
+		return 0;
+	}
+	IVTV_DEBUG_INFO("Changing output from %d to %d\n",
+		   itv->active_output, outp);
+
+	itv->active_output = outp;
+	ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_routing,
+			SAA7127_INPUT_TYPE_NORMAL,
+			itv->card->video_outputs[outp].video_output, 0);
+
+	return 0;
+}
+
+static int ivtv_g_frequency(struct file *file, void *fh, struct v4l2_frequency *vf)
+{
+	struct ivtv *itv = fh2id(fh)->itv;
+
+	if (vf->tuner != 0)
+		return -EINVAL;
+
+	ivtv_call_all(itv, tuner, g_frequency, vf);
+	return 0;
+}
+
+int ivtv_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf)
+{
+	struct ivtv *itv = fh2id(fh)->itv;
+
+	if (vf->tuner != 0)
+		return -EINVAL;
+
+	ivtv_mute(itv);
+	IVTV_DEBUG_INFO("v4l2 ioctl: set frequency %d\n", vf->frequency);
+	ivtv_call_all(itv, tuner, s_frequency, vf);
+	ivtv_unmute(itv);
+	return 0;
+}
+
+static int ivtv_g_std(struct file *file, void *fh, v4l2_std_id *std)
+{
+	struct ivtv *itv = fh2id(fh)->itv;
+
+	*std = itv->std;
+	return 0;
+}
+
+void ivtv_s_std_enc(struct ivtv *itv, v4l2_std_id *std)
+{
+	itv->std = *std;
+	itv->is_60hz = (*std & V4L2_STD_525_60) ? 1 : 0;
+	itv->is_50hz = !itv->is_60hz;
+	cx2341x_handler_set_50hz(&itv->cxhdl, itv->is_50hz);
+	itv->cxhdl.width = 720;
+	itv->cxhdl.height = itv->is_50hz ? 576 : 480;
+	itv->vbi.count = itv->is_50hz ? 18 : 12;
+	itv->vbi.start[0] = itv->is_50hz ? 6 : 10;
+	itv->vbi.start[1] = itv->is_50hz ? 318 : 273;
+
+	if (itv->hw_flags & IVTV_HW_CX25840)
+		itv->vbi.sliced_decoder_line_size = itv->is_60hz ? 272 : 284;
+
+	/* Tuner */
+	ivtv_call_all(itv, core, s_std, itv->std);
+}
+
+void ivtv_s_std_dec(struct ivtv *itv, v4l2_std_id *std)
+{
+	struct yuv_playback_info *yi = &itv->yuv_info;
+	DEFINE_WAIT(wait);
+	int f;
+
+	/* set display standard */
+	itv->std_out = *std;
+	itv->is_out_60hz = (*std & V4L2_STD_525_60) ? 1 : 0;
+	itv->is_out_50hz = !itv->is_out_60hz;
+	ivtv_call_all(itv, video, s_std_output, itv->std_out);
+
+	/*
+	 * The next firmware call is time sensitive. Time it to
+	 * avoid risk of a hard lock, by trying to ensure the call
+	 * happens within the first 100 lines of the top field.
+	 * Make 4 attempts to sync to the decoder before giving up.
+	 */
+	mutex_unlock(&itv->serialize_lock);
+	for (f = 0; f < 4; f++) {
+		prepare_to_wait(&itv->vsync_waitq, &wait,
+				TASK_UNINTERRUPTIBLE);
+		if ((read_reg(IVTV_REG_DEC_LINE_FIELD) >> 16) < 100)
+			break;
+		schedule_timeout(msecs_to_jiffies(25));
+	}
+	finish_wait(&itv->vsync_waitq, &wait);
+	mutex_lock(&itv->serialize_lock);
+
+	if (f == 4)
+		IVTV_WARN("Mode change failed to sync to decoder\n");
+
+	ivtv_vapi(itv, CX2341X_DEC_SET_STANDARD, 1, itv->is_out_50hz);
+	itv->main_rect.left = 0;
+	itv->main_rect.top = 0;
+	itv->main_rect.width = 720;
+	itv->main_rect.height = itv->is_out_50hz ? 576 : 480;
+	ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
+		720, itv->main_rect.height, 0, 0);
+	yi->main_rect = itv->main_rect;
+	if (!itv->osd_info) {
+		yi->osd_full_w = 720;
+		yi->osd_full_h = itv->is_out_50hz ? 576 : 480;
+	}
+}
+
+int ivtv_s_std(struct file *file, void *fh, v4l2_std_id *std)
+{
+	struct ivtv *itv = fh2id(fh)->itv;
+
+	if ((*std & V4L2_STD_ALL) == 0)
+		return -EINVAL;
+
+	if (*std == itv->std)
+		return 0;
+
+	if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ||
+	    atomic_read(&itv->capturing) > 0 ||
+	    atomic_read(&itv->decoding) > 0) {
+		/* Switching standard would mess with already running
+		   streams, prevent that by returning EBUSY. */
+		return -EBUSY;
+	}
+
+	IVTV_DEBUG_INFO("Switching standard to %llx.\n",
+		(unsigned long long)itv->std);
+
+	ivtv_s_std_enc(itv, std);
+	if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)
+		ivtv_s_std_dec(itv, std);
+
+	return 0;
+}
+
+static int ivtv_s_tuner(struct file *file, void *fh, struct v4l2_tuner *vt)
+{
+	struct ivtv_open_id *id = fh2id(fh);
+	struct ivtv *itv = id->itv;
+
+	if (vt->index != 0)
+		return -EINVAL;
+
+	ivtv_call_all(itv, tuner, s_tuner, vt);
+
+	return 0;
+}
+
+static int ivtv_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt)
+{
+	struct ivtv *itv = fh2id(fh)->itv;
+
+	if (vt->index != 0)
+		return -EINVAL;
+
+	ivtv_call_all(itv, tuner, g_tuner, vt);
+
+	if (vt->type == V4L2_TUNER_RADIO)
+		strlcpy(vt->name, "ivtv Radio Tuner", sizeof(vt->name));
+	else
+		strlcpy(vt->name, "ivtv TV Tuner", sizeof(vt->name));
+	return 0;
+}
+
+static int ivtv_g_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_sliced_vbi_cap *cap)
+{
+	struct ivtv *itv = fh2id(fh)->itv;
+	int set = itv->is_50hz ? V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525;
+	int f, l;
+
+	if (cap->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) {
+		for (f = 0; f < 2; f++) {
+			for (l = 0; l < 24; l++) {
+				if (valid_service_line(f, l, itv->is_50hz))
+					cap->service_lines[f][l] = set;
+			}
+		}
+	} else if (cap->type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT) {
+		if (!(itv->v4l2_cap & V4L2_CAP_SLICED_VBI_OUTPUT))
+			return -EINVAL;
+		if (itv->is_60hz) {
+			cap->service_lines[0][21] = V4L2_SLICED_CAPTION_525;
+			cap->service_lines[1][21] = V4L2_SLICED_CAPTION_525;
+		} else {
+			cap->service_lines[0][23] = V4L2_SLICED_WSS_625;
+			cap->service_lines[0][16] = V4L2_SLICED_VPS;
+		}
+	} else {
+		return -EINVAL;
+	}
+
+	set = 0;
+	for (f = 0; f < 2; f++)
+		for (l = 0; l < 24; l++)
+			set |= cap->service_lines[f][l];
+	cap->service_set = set;
+	return 0;
+}
+
+static int ivtv_g_enc_index(struct file *file, void *fh, struct v4l2_enc_idx *idx)
+{
+	struct ivtv *itv = fh2id(fh)->itv;
+	struct v4l2_enc_idx_entry *e = idx->entry;
+	int entries;
+	int i;
+
+	entries = (itv->pgm_info_write_idx + IVTV_MAX_PGM_INDEX - itv->pgm_info_read_idx) %
+				IVTV_MAX_PGM_INDEX;
+	if (entries > V4L2_ENC_IDX_ENTRIES)
+		entries = V4L2_ENC_IDX_ENTRIES;
+	idx->entries = 0;
+	for (i = 0; i < entries; i++) {
+		*e = itv->pgm_info[(itv->pgm_info_read_idx + i) % IVTV_MAX_PGM_INDEX];
+		if ((e->flags & V4L2_ENC_IDX_FRAME_MASK) <= V4L2_ENC_IDX_FRAME_B) {
+			idx->entries++;
+			e++;
+		}
+	}
+	itv->pgm_info_read_idx = (itv->pgm_info_read_idx + idx->entries) % IVTV_MAX_PGM_INDEX;
+	return 0;
+}
+
+static int ivtv_encoder_cmd(struct file *file, void *fh, struct v4l2_encoder_cmd *enc)
+{
+	struct ivtv_open_id *id = fh2id(fh);
+	struct ivtv *itv = id->itv;
+
+
+	switch (enc->cmd) {
+	case V4L2_ENC_CMD_START:
+		IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_START\n");
+		enc->flags = 0;
+		return ivtv_start_capture(id);
+
+	case V4L2_ENC_CMD_STOP:
+		IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_STOP\n");
+		enc->flags &= V4L2_ENC_CMD_STOP_AT_GOP_END;
+		ivtv_stop_capture(id, enc->flags & V4L2_ENC_CMD_STOP_AT_GOP_END);
+		return 0;
+
+	case V4L2_ENC_CMD_PAUSE:
+		IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_PAUSE\n");
+		enc->flags = 0;
+
+		if (!atomic_read(&itv->capturing))
+			return -EPERM;
+		if (test_and_set_bit(IVTV_F_I_ENC_PAUSED, &itv->i_flags))
+			return 0;
+
+		ivtv_mute(itv);
+		ivtv_vapi(itv, CX2341X_ENC_PAUSE_ENCODER, 1, 0);
+		break;
+
+	case V4L2_ENC_CMD_RESUME:
+		IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_RESUME\n");
+		enc->flags = 0;
+
+		if (!atomic_read(&itv->capturing))
+			return -EPERM;
+
+		if (!test_and_clear_bit(IVTV_F_I_ENC_PAUSED, &itv->i_flags))
+			return 0;
+
+		ivtv_vapi(itv, CX2341X_ENC_PAUSE_ENCODER, 1, 1);
+		ivtv_unmute(itv);
+		break;
+	default:
+		IVTV_DEBUG_IOCTL("Unknown cmd %d\n", enc->cmd);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int ivtv_try_encoder_cmd(struct file *file, void *fh, struct v4l2_encoder_cmd *enc)
+{
+	struct ivtv *itv = fh2id(fh)->itv;
+
+	switch (enc->cmd) {
+	case V4L2_ENC_CMD_START:
+		IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_START\n");
+		enc->flags = 0;
+		return 0;
+
+	case V4L2_ENC_CMD_STOP:
+		IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_STOP\n");
+		enc->flags &= V4L2_ENC_CMD_STOP_AT_GOP_END;
+		return 0;
+
+	case V4L2_ENC_CMD_PAUSE:
+		IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_PAUSE\n");
+		enc->flags = 0;
+		return 0;
+
+	case V4L2_ENC_CMD_RESUME:
+		IVTV_DEBUG_IOCTL("V4L2_ENC_CMD_RESUME\n");
+		enc->flags = 0;
+		return 0;
+	default:
+		IVTV_DEBUG_IOCTL("Unknown cmd %d\n", enc->cmd);
+		return -EINVAL;
+	}
+}
+
+static int ivtv_g_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb)
+{
+	struct ivtv *itv = fh2id(fh)->itv;
+	u32 data[CX2341X_MBOX_MAX_DATA];
+	struct yuv_playback_info *yi = &itv->yuv_info;
+
+	int pixfmt;
+	static u32 pixel_format[16] = {
+		V4L2_PIX_FMT_PAL8, /* Uses a 256-entry RGB colormap */
+		V4L2_PIX_FMT_RGB565,
+		V4L2_PIX_FMT_RGB555,
+		V4L2_PIX_FMT_RGB444,
+		V4L2_PIX_FMT_RGB32,
+		0,
+		0,
+		0,
+		V4L2_PIX_FMT_PAL8, /* Uses a 256-entry YUV colormap */
+		V4L2_PIX_FMT_YUV565,
+		V4L2_PIX_FMT_YUV555,
+		V4L2_PIX_FMT_YUV444,
+		V4L2_PIX_FMT_YUV32,
+		0,
+		0,
+		0,
+	};
+
+	if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
+		return -EINVAL;
+	if (!itv->osd_video_pbase)
+		return -EINVAL;
+
+	fb->capability = V4L2_FBUF_CAP_EXTERNOVERLAY | V4L2_FBUF_CAP_CHROMAKEY |
+		V4L2_FBUF_CAP_GLOBAL_ALPHA;
+
+	ivtv_vapi_result(itv, data, CX2341X_OSD_GET_STATE, 0);
+	data[0] |= (read_reg(0x2a00) >> 7) & 0x40;
+	pixfmt = (data[0] >> 3) & 0xf;
+
+	fb->fmt.pixelformat = pixel_format[pixfmt];
+	fb->fmt.width = itv->osd_rect.width;
+	fb->fmt.height = itv->osd_rect.height;
+	fb->fmt.field = V4L2_FIELD_INTERLACED;
+	fb->fmt.bytesperline = fb->fmt.width;
+	fb->fmt.colorspace = V4L2_COLORSPACE_SMPTE170M;
+	fb->fmt.field = V4L2_FIELD_INTERLACED;
+	fb->fmt.priv = 0;
+	if (fb->fmt.pixelformat != V4L2_PIX_FMT_PAL8)
+		fb->fmt.bytesperline *= 2;
+	if (fb->fmt.pixelformat == V4L2_PIX_FMT_RGB32 ||
+	    fb->fmt.pixelformat == V4L2_PIX_FMT_YUV32)
+		fb->fmt.bytesperline *= 2;
+	fb->fmt.sizeimage = fb->fmt.bytesperline * fb->fmt.height;
+	fb->base = (void *)itv->osd_video_pbase;
+	fb->flags = 0;
+
+	if (itv->osd_chroma_key_state)
+		fb->flags |= V4L2_FBUF_FLAG_CHROMAKEY;
+
+	if (itv->osd_global_alpha_state)
+		fb->flags |= V4L2_FBUF_FLAG_GLOBAL_ALPHA;
+
+	if (yi->track_osd)
+		fb->flags |= V4L2_FBUF_FLAG_OVERLAY;
+
+	pixfmt &= 7;
+
+	/* no local alpha for RGB565 or unknown formats */
+	if (pixfmt == 1 || pixfmt > 4)
+		return 0;
+
+	/* 16-bit formats have inverted local alpha */
+	if (pixfmt == 2 || pixfmt == 3)
+		fb->capability |= V4L2_FBUF_CAP_LOCAL_INV_ALPHA;
+	else
+		fb->capability |= V4L2_FBUF_CAP_LOCAL_ALPHA;
+
+	if (itv->osd_local_alpha_state) {
+		/* 16-bit formats have inverted local alpha */
+		if (pixfmt == 2 || pixfmt == 3)
+			fb->flags |= V4L2_FBUF_FLAG_LOCAL_INV_ALPHA;
+		else
+			fb->flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA;
+	}
+
+	return 0;
+}
+
+static int ivtv_s_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb)
+{
+	struct ivtv_open_id *id = fh2id(fh);
+	struct ivtv *itv = id->itv;
+	struct yuv_playback_info *yi = &itv->yuv_info;
+
+	if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
+		return -EINVAL;
+	if (!itv->osd_video_pbase)
+		return -EINVAL;
+
+	itv->osd_global_alpha_state = (fb->flags & V4L2_FBUF_FLAG_GLOBAL_ALPHA) != 0;
+	itv->osd_local_alpha_state =
+		(fb->flags & (V4L2_FBUF_FLAG_LOCAL_ALPHA|V4L2_FBUF_FLAG_LOCAL_INV_ALPHA)) != 0;
+	itv->osd_chroma_key_state = (fb->flags & V4L2_FBUF_FLAG_CHROMAKEY) != 0;
+	ivtv_set_osd_alpha(itv);
+	yi->track_osd = (fb->flags & V4L2_FBUF_FLAG_OVERLAY) != 0;
+	return ivtv_g_fbuf(file, fh, fb);
+}
+
+static int ivtv_overlay(struct file *file, void *fh, unsigned int on)
+{
+	struct ivtv_open_id *id = fh2id(fh);
+	struct ivtv *itv = id->itv;
+
+	if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
+		return -EINVAL;
+
+	ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, on != 0);
+
+	return 0;
+}
+
+static int ivtv_subscribe_event(struct v4l2_fh *fh, struct v4l2_event_subscription *sub)
+{
+	switch (sub->type) {
+	case V4L2_EVENT_VSYNC:
+	case V4L2_EVENT_EOS:
+		return v4l2_event_subscribe(fh, sub, 0, NULL);
+	case V4L2_EVENT_CTRL:
+		return v4l2_event_subscribe(fh, sub, 0, &v4l2_ctrl_sub_ev_ops);
+	default:
+		return -EINVAL;
+	}
+}
+
+static int ivtv_log_status(struct file *file, void *fh)
+{
+	struct ivtv *itv = fh2id(fh)->itv;
+	u32 data[CX2341X_MBOX_MAX_DATA];
+
+	int has_output = itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT;
+	struct v4l2_input vidin;
+	struct v4l2_audio audin;
+	int i;
+
+	IVTV_INFO("Version: %s Card: %s\n", IVTV_VERSION, itv->card_name);
+	if (itv->hw_flags & IVTV_HW_TVEEPROM) {
+		struct tveeprom tv;
+
+		ivtv_read_eeprom(itv, &tv);
+	}
+	ivtv_call_all(itv, core, log_status);
+	ivtv_get_input(itv, itv->active_input, &vidin);
+	ivtv_get_audio_input(itv, itv->audio_input, &audin);
+	IVTV_INFO("Video Input:  %s\n", vidin.name);
+	IVTV_INFO("Audio Input:  %s%s\n", audin.name,
+		(itv->dualwatch_stereo_mode & ~0x300) == 0x200 ? " (Bilingual)" : "");
+	if (has_output) {
+		struct v4l2_output vidout;
+		struct v4l2_audioout audout;
+		int mode = itv->output_mode;
+		static const char * const output_modes[5] = {
+			"None",
+			"MPEG Streaming",
+			"YUV Streaming",
+			"YUV Frames",
+			"Passthrough",
+		};
+		static const char * const alpha_mode[4] = {
+			"None",
+			"Global",
+			"Local",
+			"Global and Local"
+		};
+		static const char * const pixel_format[16] = {
+			"ARGB Indexed",
+			"RGB 5:6:5",
+			"ARGB 1:5:5:5",
+			"ARGB 1:4:4:4",
+			"ARGB 8:8:8:8",
+			"5",
+			"6",
+			"7",
+			"AYUV Indexed",
+			"YUV 5:6:5",
+			"AYUV 1:5:5:5",
+			"AYUV 1:4:4:4",
+			"AYUV 8:8:8:8",
+			"13",
+			"14",
+			"15",
+		};
+
+		ivtv_get_output(itv, itv->active_output, &vidout);
+		ivtv_get_audio_output(itv, 0, &audout);
+		IVTV_INFO("Video Output: %s\n", vidout.name);
+		if (mode < 0 || mode > OUT_PASSTHROUGH)
+			mode = OUT_NONE;
+		IVTV_INFO("Output Mode:  %s\n", output_modes[mode]);
+		ivtv_vapi_result(itv, data, CX2341X_OSD_GET_STATE, 0);
+		data[0] |= (read_reg(0x2a00) >> 7) & 0x40;
+		IVTV_INFO("Overlay:      %s, Alpha: %s, Pixel Format: %s\n",
+			data[0] & 1 ? "On" : "Off",
+			alpha_mode[(data[0] >> 1) & 0x3],
+			pixel_format[(data[0] >> 3) & 0xf]);
+	}
+	IVTV_INFO("Tuner:  %s\n",
+		test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ? "Radio" : "TV");
+	v4l2_ctrl_handler_log_status(&itv->cxhdl.hdl, 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->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,
+				(s->buffers * s->buf_size) / 1024, s->buffers);
+	}
+
+	IVTV_INFO("Read MPG/VBI: %lld/%lld bytes\n",
+			(long long)itv->mpg_data_received,
+			(long long)itv->vbi_data_inserted);
+	return 0;
+}
+
+static int ivtv_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *dec)
+{
+	struct ivtv_open_id *id = fh2id(file->private_data);
+	struct ivtv *itv = id->itv;
+
+	IVTV_DEBUG_IOCTL("VIDIOC_DECODER_CMD %d\n", dec->cmd);
+	return ivtv_video_command(itv, id, dec, false);
+}
+
+static int ivtv_try_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *dec)
+{
+	struct ivtv_open_id *id = fh2id(file->private_data);
+	struct ivtv *itv = id->itv;
+
+	IVTV_DEBUG_IOCTL("VIDIOC_TRY_DECODER_CMD %d\n", dec->cmd);
+	return ivtv_video_command(itv, id, dec, true);
+}
+
+static int ivtv_decoder_ioctls(struct file *filp, unsigned int cmd, void *arg)
+{
+	struct ivtv_open_id *id = fh2id(filp->private_data);
+	struct ivtv *itv = id->itv;
+	int nonblocking = filp->f_flags & O_NONBLOCK;
+	struct ivtv_stream *s = &itv->streams[id->type];
+	unsigned long iarg = (unsigned long)arg;
+
+	switch (cmd) {
+	case IVTV_IOC_DMA_FRAME: {
+		struct ivtv_dma_frame *args = arg;
+
+		IVTV_DEBUG_IOCTL("IVTV_IOC_DMA_FRAME\n");
+		if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
+			return -EINVAL;
+		if (args->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
+			return -EINVAL;
+		if (itv->output_mode == OUT_UDMA_YUV && args->y_source == NULL)
+			return 0;
+		if (ivtv_start_decoding(id, id->type)) {
+			return -EBUSY;
+		}
+		if (ivtv_set_output_mode(itv, OUT_UDMA_YUV) != OUT_UDMA_YUV) {
+			ivtv_release_stream(s);
+			return -EBUSY;
+		}
+		/* Mark that this file handle started the UDMA_YUV mode */
+		id->yuv_frames = 1;
+		if (args->y_source == NULL)
+			return 0;
+		return ivtv_yuv_prep_frame(itv, args);
+	}
+
+	case IVTV_IOC_PASSTHROUGH_MODE:
+		IVTV_DEBUG_IOCTL("IVTV_IOC_PASSTHROUGH_MODE\n");
+		if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
+			return -EINVAL;
+		return ivtv_passthrough_mode(itv, *(int *)arg != 0);
+
+	case VIDEO_GET_PTS: {
+		s64 *pts = arg;
+		s64 frame;
+
+		IVTV_DEBUG_IOCTL("VIDEO_GET_PTS\n");
+		if (s->type < IVTV_DEC_STREAM_TYPE_MPG) {
+			*pts = s->dma_pts;
+			break;
+		}
+		if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
+			return -EINVAL;
+		return ivtv_g_pts_frame(itv, pts, &frame);
+	}
+
+	case VIDEO_GET_FRAME_COUNT: {
+		s64 *frame = arg;
+		s64 pts;
+
+		IVTV_DEBUG_IOCTL("VIDEO_GET_FRAME_COUNT\n");
+		if (s->type < IVTV_DEC_STREAM_TYPE_MPG) {
+			*frame = 0;
+			break;
+		}
+		if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
+			return -EINVAL;
+		return ivtv_g_pts_frame(itv, &pts, frame);
+	}
+
+	case VIDEO_PLAY: {
+		struct v4l2_decoder_cmd dc;
+
+		IVTV_DEBUG_IOCTL("VIDEO_PLAY\n");
+		memset(&dc, 0, sizeof(dc));
+		dc.cmd = V4L2_DEC_CMD_START;
+		return ivtv_video_command(itv, id, &dc, 0);
+	}
+
+	case VIDEO_STOP: {
+		struct v4l2_decoder_cmd dc;
+
+		IVTV_DEBUG_IOCTL("VIDEO_STOP\n");
+		memset(&dc, 0, sizeof(dc));
+		dc.cmd = V4L2_DEC_CMD_STOP;
+		dc.flags = V4L2_DEC_CMD_STOP_TO_BLACK | V4L2_DEC_CMD_STOP_IMMEDIATELY;
+		return ivtv_video_command(itv, id, &dc, 0);
+	}
+
+	case VIDEO_FREEZE: {
+		struct v4l2_decoder_cmd dc;
+
+		IVTV_DEBUG_IOCTL("VIDEO_FREEZE\n");
+		memset(&dc, 0, sizeof(dc));
+		dc.cmd = V4L2_DEC_CMD_PAUSE;
+		return ivtv_video_command(itv, id, &dc, 0);
+	}
+
+	case VIDEO_CONTINUE: {
+		struct v4l2_decoder_cmd dc;
+
+		IVTV_DEBUG_IOCTL("VIDEO_CONTINUE\n");
+		memset(&dc, 0, sizeof(dc));
+		dc.cmd = V4L2_DEC_CMD_RESUME;
+		return ivtv_video_command(itv, id, &dc, 0);
+	}
+
+	case VIDEO_COMMAND:
+	case VIDEO_TRY_COMMAND: {
+		/* Note: struct v4l2_decoder_cmd has the same layout as
+		   struct video_command */
+		struct v4l2_decoder_cmd *dc = arg;
+		int try = (cmd == VIDEO_TRY_COMMAND);
+
+		if (try)
+			IVTV_DEBUG_IOCTL("VIDEO_TRY_COMMAND %d\n", dc->cmd);
+		else
+			IVTV_DEBUG_IOCTL("VIDEO_COMMAND %d\n", dc->cmd);
+		return ivtv_video_command(itv, id, dc, try);
+	}
+
+	case VIDEO_GET_EVENT: {
+		struct video_event *ev = arg;
+		DEFINE_WAIT(wait);
+
+		IVTV_DEBUG_IOCTL("VIDEO_GET_EVENT\n");
+		if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
+			return -EINVAL;
+		memset(ev, 0, sizeof(*ev));
+		set_bit(IVTV_F_I_EV_VSYNC_ENABLED, &itv->i_flags);
+
+		while (1) {
+			if (test_and_clear_bit(IVTV_F_I_EV_DEC_STOPPED, &itv->i_flags))
+				ev->type = VIDEO_EVENT_DECODER_STOPPED;
+			else if (test_and_clear_bit(IVTV_F_I_EV_VSYNC, &itv->i_flags)) {
+				ev->type = VIDEO_EVENT_VSYNC;
+				ev->u.vsync_field = test_bit(IVTV_F_I_EV_VSYNC_FIELD, &itv->i_flags) ?
+					VIDEO_VSYNC_FIELD_ODD : VIDEO_VSYNC_FIELD_EVEN;
+				if (itv->output_mode == OUT_UDMA_YUV &&
+					(itv->yuv_info.lace_mode & IVTV_YUV_MODE_MASK) ==
+								IVTV_YUV_MODE_PROGRESSIVE) {
+					ev->u.vsync_field = VIDEO_VSYNC_FIELD_PROGRESSIVE;
+				}
+			}
+			if (ev->type)
+				return 0;
+			if (nonblocking)
+				return -EAGAIN;
+			/* Wait for event. Note that serialize_lock is locked,
+			   so to allow other processes to access the driver while
+			   we are waiting unlock first and later lock again. */
+			mutex_unlock(&itv->serialize_lock);
+			prepare_to_wait(&itv->event_waitq, &wait, TASK_INTERRUPTIBLE);
+			if (!test_bit(IVTV_F_I_EV_DEC_STOPPED, &itv->i_flags) &&
+			    !test_bit(IVTV_F_I_EV_VSYNC, &itv->i_flags))
+				schedule();
+			finish_wait(&itv->event_waitq, &wait);
+			mutex_lock(&itv->serialize_lock);
+			if (signal_pending(current)) {
+				/* return if a signal was received */
+				IVTV_DEBUG_INFO("User stopped wait for event\n");
+				return -EINTR;
+			}
+		}
+		break;
+	}
+
+	case VIDEO_SELECT_SOURCE:
+		IVTV_DEBUG_IOCTL("VIDEO_SELECT_SOURCE\n");
+		if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
+			return -EINVAL;
+		return ivtv_passthrough_mode(itv, iarg == VIDEO_SOURCE_DEMUX);
+
+	case AUDIO_SET_MUTE:
+		IVTV_DEBUG_IOCTL("AUDIO_SET_MUTE\n");
+		itv->speed_mute_audio = iarg;
+		return 0;
+
+	case AUDIO_CHANNEL_SELECT:
+		IVTV_DEBUG_IOCTL("AUDIO_CHANNEL_SELECT\n");
+		if (iarg > AUDIO_STEREO_SWAPPED)
+			return -EINVAL;
+		return v4l2_ctrl_s_ctrl(itv->ctrl_audio_playback, iarg + 1);
+
+	case AUDIO_BILINGUAL_CHANNEL_SELECT:
+		IVTV_DEBUG_IOCTL("AUDIO_BILINGUAL_CHANNEL_SELECT\n");
+		if (iarg > AUDIO_STEREO_SWAPPED)
+			return -EINVAL;
+		return v4l2_ctrl_s_ctrl(itv->ctrl_audio_multilingual_playback, iarg + 1);
+
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static long ivtv_default(struct file *file, void *fh, bool valid_prio,
+			 int cmd, void *arg)
+{
+	struct ivtv *itv = fh2id(fh)->itv;
+
+	if (!valid_prio) {
+		switch (cmd) {
+		case IVTV_IOC_PASSTHROUGH_MODE:
+		case VIDEO_PLAY:
+		case VIDEO_STOP:
+		case VIDEO_FREEZE:
+		case VIDEO_CONTINUE:
+		case VIDEO_COMMAND:
+		case VIDEO_SELECT_SOURCE:
+		case AUDIO_SET_MUTE:
+		case AUDIO_CHANNEL_SELECT:
+		case AUDIO_BILINGUAL_CHANNEL_SELECT:
+			return -EBUSY;
+		}
+	}
+
+	switch (cmd) {
+	case VIDIOC_INT_RESET: {
+		u32 val = *(u32 *)arg;
+
+		if ((val == 0 && itv->options.newi2c) || (val & 0x01))
+			ivtv_reset_ir_gpio(itv);
+		if (val & 0x02)
+			v4l2_subdev_call(itv->sd_video, core, reset, 0);
+		break;
+	}
+
+	case IVTV_IOC_DMA_FRAME:
+	case IVTV_IOC_PASSTHROUGH_MODE:
+	case VIDEO_GET_PTS:
+	case VIDEO_GET_FRAME_COUNT:
+	case VIDEO_GET_EVENT:
+	case VIDEO_PLAY:
+	case VIDEO_STOP:
+	case VIDEO_FREEZE:
+	case VIDEO_CONTINUE:
+	case VIDEO_COMMAND:
+	case VIDEO_TRY_COMMAND:
+	case VIDEO_SELECT_SOURCE:
+	case AUDIO_SET_MUTE:
+	case AUDIO_CHANNEL_SELECT:
+	case AUDIO_BILINGUAL_CHANNEL_SELECT:
+		return ivtv_decoder_ioctls(file, cmd, (void *)arg);
+
+	default:
+		return -ENOTTY;
+	}
+	return 0;
+}
+
+static const struct v4l2_ioctl_ops ivtv_ioctl_ops = {
+	.vidioc_querycap    		    = ivtv_querycap,
+	.vidioc_s_audio     		    = ivtv_s_audio,
+	.vidioc_g_audio     		    = ivtv_g_audio,
+	.vidioc_enumaudio   		    = ivtv_enumaudio,
+	.vidioc_s_audout     		    = ivtv_s_audout,
+	.vidioc_g_audout     		    = ivtv_g_audout,
+	.vidioc_enum_input   		    = ivtv_enum_input,
+	.vidioc_enum_output   		    = ivtv_enum_output,
+	.vidioc_enumaudout   		    = ivtv_enumaudout,
+	.vidioc_cropcap       		    = ivtv_cropcap,
+	.vidioc_s_crop       		    = ivtv_s_crop,
+	.vidioc_g_crop       		    = ivtv_g_crop,
+	.vidioc_g_input      		    = ivtv_g_input,
+	.vidioc_s_input      		    = ivtv_s_input,
+	.vidioc_g_output     		    = ivtv_g_output,
+	.vidioc_s_output     		    = ivtv_s_output,
+	.vidioc_g_frequency 		    = ivtv_g_frequency,
+	.vidioc_s_frequency  		    = ivtv_s_frequency,
+	.vidioc_s_tuner      		    = ivtv_s_tuner,
+	.vidioc_g_tuner      		    = ivtv_g_tuner,
+	.vidioc_g_enc_index 		    = ivtv_g_enc_index,
+	.vidioc_g_fbuf			    = ivtv_g_fbuf,
+	.vidioc_s_fbuf			    = ivtv_s_fbuf,
+	.vidioc_g_std 			    = ivtv_g_std,
+	.vidioc_s_std 			    = ivtv_s_std,
+	.vidioc_overlay			    = ivtv_overlay,
+	.vidioc_log_status		    = ivtv_log_status,
+	.vidioc_enum_fmt_vid_cap 	    = ivtv_enum_fmt_vid_cap,
+	.vidioc_encoder_cmd  		    = ivtv_encoder_cmd,
+	.vidioc_try_encoder_cmd 	    = ivtv_try_encoder_cmd,
+	.vidioc_decoder_cmd		    = ivtv_decoder_cmd,
+	.vidioc_try_decoder_cmd		    = ivtv_try_decoder_cmd,
+	.vidioc_enum_fmt_vid_out 	    = ivtv_enum_fmt_vid_out,
+	.vidioc_g_fmt_vid_cap 		    = ivtv_g_fmt_vid_cap,
+	.vidioc_g_fmt_vbi_cap		    = ivtv_g_fmt_vbi_cap,
+	.vidioc_g_fmt_sliced_vbi_cap        = ivtv_g_fmt_sliced_vbi_cap,
+	.vidioc_g_fmt_vid_out               = ivtv_g_fmt_vid_out,
+	.vidioc_g_fmt_vid_out_overlay       = ivtv_g_fmt_vid_out_overlay,
+	.vidioc_g_fmt_sliced_vbi_out        = ivtv_g_fmt_sliced_vbi_out,
+	.vidioc_s_fmt_vid_cap  		    = ivtv_s_fmt_vid_cap,
+	.vidioc_s_fmt_vbi_cap 		    = ivtv_s_fmt_vbi_cap,
+	.vidioc_s_fmt_sliced_vbi_cap        = ivtv_s_fmt_sliced_vbi_cap,
+	.vidioc_s_fmt_vid_out               = ivtv_s_fmt_vid_out,
+	.vidioc_s_fmt_vid_out_overlay       = ivtv_s_fmt_vid_out_overlay,
+	.vidioc_s_fmt_sliced_vbi_out        = ivtv_s_fmt_sliced_vbi_out,
+	.vidioc_try_fmt_vid_cap  	    = ivtv_try_fmt_vid_cap,
+	.vidioc_try_fmt_vbi_cap		    = ivtv_try_fmt_vbi_cap,
+	.vidioc_try_fmt_sliced_vbi_cap      = ivtv_try_fmt_sliced_vbi_cap,
+	.vidioc_try_fmt_vid_out 	    = ivtv_try_fmt_vid_out,
+	.vidioc_try_fmt_vid_out_overlay     = ivtv_try_fmt_vid_out_overlay,
+	.vidioc_try_fmt_sliced_vbi_out 	    = ivtv_try_fmt_sliced_vbi_out,
+	.vidioc_g_sliced_vbi_cap 	    = ivtv_g_sliced_vbi_cap,
+	.vidioc_g_chip_ident 		    = ivtv_g_chip_ident,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.vidioc_g_register 		    = ivtv_g_register,
+	.vidioc_s_register 		    = ivtv_s_register,
+#endif
+	.vidioc_default 		    = ivtv_default,
+	.vidioc_subscribe_event 	    = ivtv_subscribe_event,
+	.vidioc_unsubscribe_event 	    = v4l2_event_unsubscribe,
+};
+
+void ivtv_set_funcs(struct video_device *vdev)
+{
+	vdev->ioctl_ops = &ivtv_ioctl_ops;
+}
diff --git a/drivers/media/pci/ivtv/ivtv-ioctl.h b/drivers/media/pci/ivtv/ivtv-ioctl.h
new file mode 100644
index 0000000..7c553d1
--- /dev/null
+++ b/drivers/media/pci/ivtv/ivtv-ioctl.h
@@ -0,0 +1,35 @@
+/*
+    ioctl system call
+    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
+    Copyright (C) 2005-2007  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef IVTV_IOCTL_H
+#define IVTV_IOCTL_H
+
+u16 ivtv_service2vbi(int type);
+void ivtv_expand_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal);
+u16 ivtv_get_service_set(struct v4l2_sliced_vbi_format *fmt);
+void ivtv_set_osd_alpha(struct ivtv *itv);
+int ivtv_set_speed(struct ivtv *itv, int speed);
+void ivtv_set_funcs(struct video_device *vdev);
+void ivtv_s_std_enc(struct ivtv *itv, v4l2_std_id *std);
+void ivtv_s_std_dec(struct ivtv *itv, v4l2_std_id *std);
+int ivtv_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf);
+int ivtv_s_input(struct file *file, void *fh, unsigned int inp);
+
+#endif
diff --git a/drivers/media/pci/ivtv/ivtv-irq.c b/drivers/media/pci/ivtv/ivtv-irq.c
new file mode 100644
index 0000000..19a7c9b
--- /dev/null
+++ b/drivers/media/pci/ivtv/ivtv-irq.c
@@ -0,0 +1,1088 @@
+/* interrupt handling
+    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
+    Copyright (C) 2004  Chris Kennedy <c@groovy.org>
+    Copyright (C) 2005-2007  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "ivtv-driver.h"
+#include "ivtv-queue.h"
+#include "ivtv-udma.h"
+#include "ivtv-irq.h"
+#include "ivtv-mailbox.h"
+#include "ivtv-vbi.h"
+#include "ivtv-yuv.h"
+#include <media/v4l2-event.h>
+
+#define DMA_MAGIC_COOKIE 0x000001fe
+
+static void ivtv_dma_dec_start(struct ivtv_stream *s);
+
+static const int ivtv_stream_map[] = {
+	IVTV_ENC_STREAM_TYPE_MPG,
+	IVTV_ENC_STREAM_TYPE_YUV,
+	IVTV_ENC_STREAM_TYPE_PCM,
+	IVTV_ENC_STREAM_TYPE_VBI,
+};
+
+static void ivtv_pcm_work_handler(struct ivtv *itv)
+{
+	struct ivtv_stream *s = &itv->streams[IVTV_ENC_STREAM_TYPE_PCM];
+	struct ivtv_buffer *buf;
+
+	/* Pass the PCM data to ivtv-alsa */
+
+	while (1) {
+		/*
+		 * Users should not be using both the ALSA and V4L2 PCM audio
+		 * capture interfaces at the same time.  If the user is doing
+		 * this, there maybe a buffer in q_io to grab, use, and put
+		 * back in rotation.
+		 */
+		buf = ivtv_dequeue(s, &s->q_io);
+		if (buf == NULL)
+			buf = ivtv_dequeue(s, &s->q_full);
+		if (buf == NULL)
+			break;
+
+		if (buf->readpos < buf->bytesused)
+			itv->pcm_announce_callback(itv->alsa,
+				(u8 *)(buf->buf + buf->readpos),
+				(size_t)(buf->bytesused - buf->readpos));
+
+		ivtv_enqueue(s, buf, &s->q_free);
+	}
+}
+
+static void ivtv_pio_work_handler(struct ivtv *itv)
+{
+	struct ivtv_stream *s = &itv->streams[itv->cur_pio_stream];
+	struct ivtv_buffer *buf;
+	int i = 0;
+
+	IVTV_DEBUG_HI_DMA("ivtv_pio_work_handler\n");
+	if (itv->cur_pio_stream < 0 || itv->cur_pio_stream >= IVTV_MAX_STREAMS ||
+			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);
+		return;
+	}
+	IVTV_DEBUG_HI_DMA("Process PIO %s\n", s->name);
+	list_for_each_entry(buf, &s->q_dma.list, list) {
+		u32 size = s->sg_processing[i].size & 0x3ffff;
+
+		/* Copy the data from the card to the buffer */
+		if (s->type == IVTV_DEC_STREAM_TYPE_VBI) {
+			memcpy_fromio(buf->buf, itv->dec_mem + s->sg_processing[i].src - IVTV_DECODER_OFFSET, size);
+		}
+		else {
+			memcpy_fromio(buf->buf, itv->enc_mem + s->sg_processing[i].src, size);
+		}
+		i++;
+		if (i == s->sg_processing_size)
+			break;
+	}
+	write_reg(IVTV_IRQ_ENC_PIO_COMPLETE, 0x44);
+}
+
+void ivtv_irq_work_handler(struct kthread_work *work)
+{
+	struct ivtv *itv = container_of(work, struct ivtv, irq_work);
+
+	if (test_and_clear_bit(IVTV_F_I_WORK_HANDLER_PIO, &itv->i_flags))
+		ivtv_pio_work_handler(itv);
+
+	if (test_and_clear_bit(IVTV_F_I_WORK_HANDLER_VBI, &itv->i_flags))
+		ivtv_vbi_work_handler(itv);
+
+	if (test_and_clear_bit(IVTV_F_I_WORK_HANDLER_YUV, &itv->i_flags))
+		ivtv_yuv_work_handler(itv);
+
+	if (test_and_clear_bit(IVTV_F_I_WORK_HANDLER_PCM, &itv->i_flags))
+		ivtv_pcm_work_handler(itv);
+}
+
+/* Determine the required DMA size, setup enough buffers in the predma queue and
+   actually copy the data from the card to the buffers in case a PIO transfer is
+   required for this stream.
+ */
+static int stream_enc_dma_append(struct ivtv_stream *s, u32 data[CX2341X_MBOX_MAX_DATA])
+{
+	struct ivtv *itv = s->itv;
+	struct ivtv_buffer *buf;
+	u32 bytes_needed = 0;
+	u32 offset, size;
+	u32 UVoffset = 0, UVsize = 0;
+	int skip_bufs = s->q_predma.buffers;
+	int idx = s->sg_pending_size;
+	int rc;
+
+	/* sanity checks */
+	if (s->vdev == NULL) {
+		IVTV_DEBUG_WARN("Stream %s not started\n", s->name);
+		return -1;
+	}
+	if (!test_bit(IVTV_F_S_CLAIMED, &s->s_flags)) {
+		IVTV_DEBUG_WARN("Stream %s not open\n", s->name);
+		return -1;
+	}
+
+	/* determine offset, size and PTS for the various streams */
+	switch (s->type) {
+		case IVTV_ENC_STREAM_TYPE_MPG:
+			offset = data[1];
+			size = data[2];
+			s->pending_pts = 0;
+			break;
+
+		case IVTV_ENC_STREAM_TYPE_YUV:
+			offset = data[1];
+			size = data[2];
+			UVoffset = data[3];
+			UVsize = data[4];
+			s->pending_pts = ((u64) data[5] << 32) | data[6];
+			break;
+
+		case IVTV_ENC_STREAM_TYPE_PCM:
+			offset = data[1] + 12;
+			size = data[2] - 12;
+			s->pending_pts = read_dec(offset - 8) |
+				((u64)(read_dec(offset - 12)) << 32);
+			if (itv->has_cx23415)
+				offset += IVTV_DECODER_OFFSET;
+			break;
+
+		case IVTV_ENC_STREAM_TYPE_VBI:
+			size = itv->vbi.enc_size * itv->vbi.fpi;
+			offset = read_enc(itv->vbi.enc_start - 4) + 12;
+			if (offset == 12) {
+				IVTV_DEBUG_INFO("VBI offset == 0\n");
+				return -1;
+			}
+			s->pending_pts = read_enc(offset - 4) | ((u64)read_enc(offset - 8) << 32);
+			break;
+
+		case IVTV_DEC_STREAM_TYPE_VBI:
+			size = read_dec(itv->vbi.dec_start + 4) + 8;
+			offset = read_dec(itv->vbi.dec_start) + itv->vbi.dec_start;
+			s->pending_pts = 0;
+			offset += IVTV_DECODER_OFFSET;
+			break;
+		default:
+			/* shouldn't happen */
+			return -1;
+	}
+
+	/* if this is the start of the DMA then fill in the magic cookie */
+	if (s->sg_pending_size == 0 && ivtv_use_dma(s)) {
+		if (itv->has_cx23415 && (s->type == IVTV_ENC_STREAM_TYPE_PCM ||
+		    s->type == IVTV_DEC_STREAM_TYPE_VBI)) {
+			s->pending_backup = read_dec(offset - IVTV_DECODER_OFFSET);
+			write_dec_sync(cpu_to_le32(DMA_MAGIC_COOKIE), offset - IVTV_DECODER_OFFSET);
+		}
+		else {
+			s->pending_backup = read_enc(offset);
+			write_enc_sync(cpu_to_le32(DMA_MAGIC_COOKIE), offset);
+		}
+		s->pending_offset = offset;
+	}
+
+	bytes_needed = size;
+	if (s->type == IVTV_ENC_STREAM_TYPE_YUV) {
+		/* The size for the Y samples needs to be rounded upwards to a
+		   multiple of the buf_size. The UV samples then start in the
+		   next buffer. */
+		bytes_needed = s->buf_size * ((bytes_needed + s->buf_size - 1) / s->buf_size);
+		bytes_needed += UVsize;
+	}
+
+	IVTV_DEBUG_HI_DMA("%s %s: 0x%08x bytes at 0x%08x\n",
+		ivtv_use_pio(s) ? "PIO" : "DMA", s->name, bytes_needed, offset);
+
+	rc = ivtv_queue_move(s, &s->q_free, &s->q_full, &s->q_predma, bytes_needed);
+	if (rc < 0) { /* Insufficient buffers */
+		IVTV_DEBUG_WARN("Cannot obtain %d bytes for %s data transfer\n",
+				bytes_needed, s->name);
+		return -1;
+	}
+	if (rc && !s->buffers_stolen && test_bit(IVTV_F_S_APPL_IO, &s->s_flags)) {
+		IVTV_WARN("All %s stream buffers are full. Dropping data.\n", s->name);
+		IVTV_WARN("Cause: the application is not reading fast enough.\n");
+	}
+	s->buffers_stolen = rc;
+
+	/* got the buffers, now fill in sg_pending */
+	buf = list_entry(s->q_predma.list.next, struct ivtv_buffer, list);
+	memset(buf->buf, 0, 128);
+	list_for_each_entry(buf, &s->q_predma.list, list) {
+		if (skip_bufs-- > 0)
+			continue;
+		s->sg_pending[idx].dst = buf->dma_handle;
+		s->sg_pending[idx].src = offset;
+		s->sg_pending[idx].size = s->buf_size;
+		buf->bytesused = min(size, s->buf_size);
+		buf->dma_xfer_cnt = s->dma_xfer_cnt;
+
+		s->q_predma.bytesused += buf->bytesused;
+		size -= buf->bytesused;
+		offset += s->buf_size;
+
+		/* Sync SG buffers */
+		ivtv_buf_sync_for_device(s, buf);
+
+		if (size == 0) {	/* YUV */
+			/* process the UV section */
+			offset = UVoffset;
+			size = UVsize;
+		}
+		idx++;
+	}
+	s->sg_pending_size = idx;
+	return 0;
+}
+
+static void dma_post(struct ivtv_stream *s)
+{
+	struct ivtv *itv = s->itv;
+	struct ivtv_buffer *buf = NULL;
+	struct list_head *p;
+	u32 offset;
+	__le32 *u32buf;
+	int x = 0;
+
+	IVTV_DEBUG_HI_DMA("%s %s completed (%x)\n", ivtv_use_pio(s) ? "PIO" : "DMA",
+			s->name, s->dma_offset);
+	list_for_each(p, &s->q_dma.list) {
+		buf = list_entry(p, struct ivtv_buffer, list);
+		u32buf = (__le32 *)buf->buf;
+
+		/* Sync Buffer */
+		ivtv_buf_sync_for_cpu(s, buf);
+
+		if (x == 0 && ivtv_use_dma(s)) {
+			offset = s->dma_last_offset;
+			if (u32buf[offset / 4] != DMA_MAGIC_COOKIE)
+			{
+				for (offset = 0; offset < 64; offset++) {
+					if (u32buf[offset] == DMA_MAGIC_COOKIE) {
+						break;
+					}
+				}
+				offset *= 4;
+				if (offset == 256) {
+					IVTV_DEBUG_WARN("%s: Couldn't find start of buffer within the first 256 bytes\n", s->name);
+					offset = s->dma_last_offset;
+				}
+				if (s->dma_last_offset != offset)
+					IVTV_DEBUG_WARN("%s: offset %d -> %d\n", s->name, s->dma_last_offset, offset);
+				s->dma_last_offset = offset;
+			}
+			if (itv->has_cx23415 && (s->type == IVTV_ENC_STREAM_TYPE_PCM ||
+						s->type == IVTV_DEC_STREAM_TYPE_VBI)) {
+				write_dec_sync(0, s->dma_offset - IVTV_DECODER_OFFSET);
+			}
+			else {
+				write_enc_sync(0, s->dma_offset);
+			}
+			if (offset) {
+				buf->bytesused -= offset;
+				memcpy(buf->buf, buf->buf + offset, buf->bytesused + offset);
+			}
+			*u32buf = cpu_to_le32(s->dma_backup);
+		}
+		x++;
+		/* flag byteswap ABCD -> DCBA for MPG & VBI data outside irq */
+		if (s->type == IVTV_ENC_STREAM_TYPE_MPG ||
+		    s->type == IVTV_ENC_STREAM_TYPE_VBI)
+			buf->b_flags |= IVTV_F_B_NEED_BUF_SWAP;
+	}
+	if (buf)
+		buf->bytesused += s->dma_last_offset;
+	if (buf && s->type == IVTV_DEC_STREAM_TYPE_VBI) {
+		list_for_each_entry(buf, &s->q_dma.list, list) {
+			/* Parse and Groom VBI Data */
+			s->q_dma.bytesused -= buf->bytesused;
+			ivtv_process_vbi_data(itv, buf, 0, s->type);
+			s->q_dma.bytesused += buf->bytesused;
+		}
+		if (s->fh == NULL) {
+			ivtv_queue_move(s, &s->q_dma, NULL, &s->q_free, 0);
+			return;
+		}
+	}
+
+	ivtv_queue_move(s, &s->q_dma, NULL, &s->q_full, s->q_dma.bytesused);
+
+	if (s->type == IVTV_ENC_STREAM_TYPE_PCM &&
+	    itv->pcm_announce_callback != NULL) {
+		/*
+		 * Set up the work handler to pass the data to ivtv-alsa.
+		 *
+		 * We just use q_full and let the work handler race with users
+		 * making ivtv-fileops.c calls on the PCM device node.
+		 *
+		 * Users should not be using both the ALSA and V4L2 PCM audio
+		 * capture interfaces at the same time.  If the user does this,
+		 * fragments of data will just go out each interface as they
+		 * race for PCM data.
+		 */
+		set_bit(IVTV_F_I_WORK_HANDLER_PCM, &itv->i_flags);
+		set_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags);
+	}
+
+	if (s->fh)
+		wake_up(&s->waitq);
+}
+
+void ivtv_dma_stream_dec_prepare(struct ivtv_stream *s, u32 offset, int lock)
+{
+	struct ivtv *itv = s->itv;
+	struct yuv_playback_info *yi = &itv->yuv_info;
+	u8 frame = yi->draw_frame;
+	struct yuv_frame_info *f = &yi->new_frame_info[frame];
+	struct ivtv_buffer *buf;
+	u32 y_size = 720 * ((f->src_h + 31) & ~31);
+	u32 uv_offset = offset + IVTV_YUV_BUFFER_UV_OFFSET;
+	int y_done = 0;
+	int bytes_written = 0;
+	unsigned long flags = 0;
+	int idx = 0;
+
+	IVTV_DEBUG_HI_DMA("DEC PREPARE DMA %s: %08x %08x\n", s->name, s->q_predma.bytesused, offset);
+
+	/* Insert buffer block for YUV if needed */
+	if (s->type == IVTV_DEC_STREAM_TYPE_YUV && f->offset_y) {
+		if (yi->blanking_dmaptr) {
+			s->sg_pending[idx].src = yi->blanking_dmaptr;
+			s->sg_pending[idx].dst = offset;
+			s->sg_pending[idx].size = 720 * 16;
+		}
+		offset += 720 * 16;
+		idx++;
+	}
+
+	list_for_each_entry(buf, &s->q_predma.list, list) {
+		/* YUV UV Offset from Y Buffer */
+		if (s->type == IVTV_DEC_STREAM_TYPE_YUV && !y_done &&
+				(bytes_written + buf->bytesused) >= y_size) {
+			s->sg_pending[idx].src = buf->dma_handle;
+			s->sg_pending[idx].dst = offset;
+			s->sg_pending[idx].size = y_size - bytes_written;
+			offset = uv_offset;
+			if (s->sg_pending[idx].size != buf->bytesused) {
+				idx++;
+				s->sg_pending[idx].src =
+				  buf->dma_handle + s->sg_pending[idx - 1].size;
+				s->sg_pending[idx].dst = offset;
+				s->sg_pending[idx].size =
+				   buf->bytesused - s->sg_pending[idx - 1].size;
+				offset += s->sg_pending[idx].size;
+			}
+			y_done = 1;
+		} else {
+			s->sg_pending[idx].src = buf->dma_handle;
+			s->sg_pending[idx].dst = offset;
+			s->sg_pending[idx].size = buf->bytesused;
+			offset += buf->bytesused;
+		}
+		bytes_written += buf->bytesused;
+
+		/* Sync SG buffers */
+		ivtv_buf_sync_for_device(s, buf);
+		idx++;
+	}
+	s->sg_pending_size = idx;
+
+	/* Sync Hardware SG List of buffers */
+	ivtv_stream_sync_for_device(s);
+	if (lock)
+		spin_lock_irqsave(&itv->dma_reg_lock, flags);
+	if (!test_bit(IVTV_F_I_DMA, &itv->i_flags)) {
+		ivtv_dma_dec_start(s);
+	}
+	else {
+		set_bit(IVTV_F_S_DMA_PENDING, &s->s_flags);
+	}
+	if (lock)
+		spin_unlock_irqrestore(&itv->dma_reg_lock, flags);
+}
+
+static void ivtv_dma_enc_start_xfer(struct ivtv_stream *s)
+{
+	struct ivtv *itv = s->itv;
+
+	s->sg_dma->src = cpu_to_le32(s->sg_processing[s->sg_processed].src);
+	s->sg_dma->dst = cpu_to_le32(s->sg_processing[s->sg_processed].dst);
+	s->sg_dma->size = cpu_to_le32(s->sg_processing[s->sg_processed].size | 0x80000000);
+	s->sg_processed++;
+	/* Sync Hardware SG List of buffers */
+	ivtv_stream_sync_for_device(s);
+	write_reg(s->sg_handle, IVTV_REG_ENCDMAADDR);
+	write_reg_sync(read_reg(IVTV_REG_DMAXFER) | 0x02, IVTV_REG_DMAXFER);
+	itv->dma_timer.expires = jiffies + msecs_to_jiffies(300);
+	add_timer(&itv->dma_timer);
+}
+
+static void ivtv_dma_dec_start_xfer(struct ivtv_stream *s)
+{
+	struct ivtv *itv = s->itv;
+
+	s->sg_dma->src = cpu_to_le32(s->sg_processing[s->sg_processed].src);
+	s->sg_dma->dst = cpu_to_le32(s->sg_processing[s->sg_processed].dst);
+	s->sg_dma->size = cpu_to_le32(s->sg_processing[s->sg_processed].size | 0x80000000);
+	s->sg_processed++;
+	/* Sync Hardware SG List of buffers */
+	ivtv_stream_sync_for_device(s);
+	write_reg(s->sg_handle, IVTV_REG_DECDMAADDR);
+	write_reg_sync(read_reg(IVTV_REG_DMAXFER) | 0x01, IVTV_REG_DMAXFER);
+	itv->dma_timer.expires = jiffies + msecs_to_jiffies(300);
+	add_timer(&itv->dma_timer);
+}
+
+/* start the encoder DMA */
+static void ivtv_dma_enc_start(struct ivtv_stream *s)
+{
+	struct ivtv *itv = s->itv;
+	struct ivtv_stream *s_vbi = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI];
+	int i;
+
+	IVTV_DEBUG_HI_DMA("start %s for %s\n", ivtv_use_dma(s) ? "DMA" : "PIO", s->name);
+
+	if (s->q_predma.bytesused)
+		ivtv_queue_move(s, &s->q_predma, NULL, &s->q_dma, s->q_predma.bytesused);
+
+	if (ivtv_use_dma(s))
+		s->sg_pending[s->sg_pending_size - 1].size += 256;
+
+	/* If this is an MPEG stream, and VBI data is also pending, then append the
+	   VBI DMA to the MPEG DMA and transfer both sets of data at once.
+
+	   VBI DMA is a second class citizen compared to MPEG and mixing them together
+	   will confuse the firmware (the end of a VBI DMA is seen as the end of a
+	   MPEG DMA, thus effectively dropping an MPEG frame). So instead we make
+	   sure we only use the MPEG DMA to transfer the VBI DMA if both are in
+	   use. This way no conflicts occur. */
+	clear_bit(IVTV_F_S_DMA_HAS_VBI, &s->s_flags);
+	if (s->type == IVTV_ENC_STREAM_TYPE_MPG && s_vbi->sg_pending_size &&
+			s->sg_pending_size + s_vbi->sg_pending_size <= s->buffers) {
+		ivtv_queue_move(s_vbi, &s_vbi->q_predma, NULL, &s_vbi->q_dma, s_vbi->q_predma.bytesused);
+		if (ivtv_use_dma(s_vbi))
+			s_vbi->sg_pending[s_vbi->sg_pending_size - 1].size += 256;
+		for (i = 0; i < s_vbi->sg_pending_size; i++) {
+			s->sg_pending[s->sg_pending_size++] = s_vbi->sg_pending[i];
+		}
+		s_vbi->dma_offset = s_vbi->pending_offset;
+		s_vbi->sg_pending_size = 0;
+		s_vbi->dma_xfer_cnt++;
+		set_bit(IVTV_F_S_DMA_HAS_VBI, &s->s_flags);
+		IVTV_DEBUG_HI_DMA("include DMA for %s\n", s_vbi->name);
+	}
+
+	s->dma_xfer_cnt++;
+	memcpy(s->sg_processing, s->sg_pending, sizeof(struct ivtv_sg_host_element) * s->sg_pending_size);
+	s->sg_processing_size = s->sg_pending_size;
+	s->sg_pending_size = 0;
+	s->sg_processed = 0;
+	s->dma_offset = s->pending_offset;
+	s->dma_backup = s->pending_backup;
+	s->dma_pts = s->pending_pts;
+
+	if (ivtv_use_pio(s)) {
+		set_bit(IVTV_F_I_WORK_HANDLER_PIO, &itv->i_flags);
+		set_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags);
+		set_bit(IVTV_F_I_PIO, &itv->i_flags);
+		itv->cur_pio_stream = s->type;
+	}
+	else {
+		itv->dma_retries = 0;
+		ivtv_dma_enc_start_xfer(s);
+		set_bit(IVTV_F_I_DMA, &itv->i_flags);
+		itv->cur_dma_stream = s->type;
+	}
+}
+
+static void ivtv_dma_dec_start(struct ivtv_stream *s)
+{
+	struct ivtv *itv = s->itv;
+
+	if (s->q_predma.bytesused)
+		ivtv_queue_move(s, &s->q_predma, NULL, &s->q_dma, s->q_predma.bytesused);
+	s->dma_xfer_cnt++;
+	memcpy(s->sg_processing, s->sg_pending, sizeof(struct ivtv_sg_host_element) * s->sg_pending_size);
+	s->sg_processing_size = s->sg_pending_size;
+	s->sg_pending_size = 0;
+	s->sg_processed = 0;
+
+	IVTV_DEBUG_HI_DMA("start DMA for %s\n", s->name);
+	itv->dma_retries = 0;
+	ivtv_dma_dec_start_xfer(s);
+	set_bit(IVTV_F_I_DMA, &itv->i_flags);
+	itv->cur_dma_stream = s->type;
+}
+
+static void ivtv_irq_dma_read(struct ivtv *itv)
+{
+	struct ivtv_stream *s = NULL;
+	struct ivtv_buffer *buf;
+	int hw_stream_type = 0;
+
+	IVTV_DEBUG_HI_IRQ("DEC DMA READ\n");
+
+	del_timer(&itv->dma_timer);
+
+	if (!test_bit(IVTV_F_I_UDMA, &itv->i_flags) && itv->cur_dma_stream < 0)
+		return;
+
+	if (!test_bit(IVTV_F_I_UDMA, &itv->i_flags)) {
+		s = &itv->streams[itv->cur_dma_stream];
+		ivtv_stream_sync_for_cpu(s);
+
+		if (read_reg(IVTV_REG_DMASTATUS) & 0x14) {
+			IVTV_DEBUG_WARN("DEC DMA ERROR %x (xfer %d of %d, retry %d)\n",
+					read_reg(IVTV_REG_DMASTATUS),
+					s->sg_processed, s->sg_processing_size, itv->dma_retries);
+			write_reg(read_reg(IVTV_REG_DMASTATUS) & 3, IVTV_REG_DMASTATUS);
+			if (itv->dma_retries == 3) {
+				/* Too many retries, give up on this frame */
+				itv->dma_retries = 0;
+				s->sg_processed = s->sg_processing_size;
+			}
+			else {
+				/* Retry, starting with the first xfer segment.
+				   Just retrying the current segment is not sufficient. */
+				s->sg_processed = 0;
+				itv->dma_retries++;
+			}
+		}
+		if (s->sg_processed < s->sg_processing_size) {
+			/* DMA next buffer */
+			ivtv_dma_dec_start_xfer(s);
+			return;
+		}
+		if (s->type == IVTV_DEC_STREAM_TYPE_YUV)
+			hw_stream_type = 2;
+		IVTV_DEBUG_HI_DMA("DEC DATA READ %s: %d\n", s->name, s->q_dma.bytesused);
+
+		/* For some reason must kick the firmware, like PIO mode,
+		   I think this tells the firmware we are done and the size
+		   of the xfer so it can calculate what we need next.
+		   I think we can do this part ourselves but would have to
+		   fully calculate xfer info ourselves and not use interrupts
+		 */
+		ivtv_vapi(itv, CX2341X_DEC_SCHED_DMA_FROM_HOST, 3, 0, s->q_dma.bytesused,
+				hw_stream_type);
+
+		/* Free last DMA call */
+		while ((buf = ivtv_dequeue(s, &s->q_dma)) != NULL) {
+			ivtv_buf_sync_for_cpu(s, buf);
+			ivtv_enqueue(s, buf, &s->q_free);
+		}
+		wake_up(&s->waitq);
+	}
+	clear_bit(IVTV_F_I_UDMA, &itv->i_flags);
+	clear_bit(IVTV_F_I_DMA, &itv->i_flags);
+	itv->cur_dma_stream = -1;
+	wake_up(&itv->dma_waitq);
+}
+
+static void ivtv_irq_enc_dma_complete(struct ivtv *itv)
+{
+	u32 data[CX2341X_MBOX_MAX_DATA];
+	struct ivtv_stream *s;
+
+	ivtv_api_get_data(&itv->enc_mbox, IVTV_MBOX_DMA_END, 2, data);
+	IVTV_DEBUG_HI_IRQ("ENC DMA COMPLETE %x %d (%d)\n", data[0], data[1], itv->cur_dma_stream);
+
+	del_timer(&itv->dma_timer);
+
+	if (itv->cur_dma_stream < 0)
+		return;
+
+	s = &itv->streams[itv->cur_dma_stream];
+	ivtv_stream_sync_for_cpu(s);
+
+	if (data[0] & 0x18) {
+		IVTV_DEBUG_WARN("ENC DMA ERROR %x (offset %08x, xfer %d of %d, retry %d)\n", data[0],
+			s->dma_offset, s->sg_processed, s->sg_processing_size, itv->dma_retries);
+		write_reg(read_reg(IVTV_REG_DMASTATUS) & 3, IVTV_REG_DMASTATUS);
+		if (itv->dma_retries == 3) {
+			/* Too many retries, give up on this frame */
+			itv->dma_retries = 0;
+			s->sg_processed = s->sg_processing_size;
+		}
+		else {
+			/* Retry, starting with the first xfer segment.
+			   Just retrying the current segment is not sufficient. */
+			s->sg_processed = 0;
+			itv->dma_retries++;
+		}
+	}
+	if (s->sg_processed < s->sg_processing_size) {
+		/* DMA next buffer */
+		ivtv_dma_enc_start_xfer(s);
+		return;
+	}
+	clear_bit(IVTV_F_I_DMA, &itv->i_flags);
+	itv->cur_dma_stream = -1;
+	dma_post(s);
+	if (test_and_clear_bit(IVTV_F_S_DMA_HAS_VBI, &s->s_flags)) {
+		s = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI];
+		dma_post(s);
+	}
+	s->sg_processing_size = 0;
+	s->sg_processed = 0;
+	wake_up(&itv->dma_waitq);
+}
+
+static void ivtv_irq_enc_pio_complete(struct ivtv *itv)
+{
+	struct ivtv_stream *s;
+
+	if (itv->cur_pio_stream < 0 || itv->cur_pio_stream >= IVTV_MAX_STREAMS) {
+		itv->cur_pio_stream = -1;
+		return;
+	}
+	s = &itv->streams[itv->cur_pio_stream];
+	IVTV_DEBUG_HI_IRQ("ENC PIO COMPLETE %s\n", s->name);
+	clear_bit(IVTV_F_I_PIO, &itv->i_flags);
+	itv->cur_pio_stream = -1;
+	dma_post(s);
+	if (s->type == IVTV_ENC_STREAM_TYPE_MPG)
+		ivtv_vapi(itv, CX2341X_ENC_SCHED_DMA_TO_HOST, 3, 0, 0, 0);
+	else if (s->type == IVTV_ENC_STREAM_TYPE_YUV)
+		ivtv_vapi(itv, CX2341X_ENC_SCHED_DMA_TO_HOST, 3, 0, 0, 1);
+	else if (s->type == IVTV_ENC_STREAM_TYPE_PCM)
+		ivtv_vapi(itv, CX2341X_ENC_SCHED_DMA_TO_HOST, 3, 0, 0, 2);
+	clear_bit(IVTV_F_I_PIO, &itv->i_flags);
+	if (test_and_clear_bit(IVTV_F_S_DMA_HAS_VBI, &s->s_flags)) {
+		s = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI];
+		dma_post(s);
+	}
+	wake_up(&itv->dma_waitq);
+}
+
+static void ivtv_irq_dma_err(struct ivtv *itv)
+{
+	u32 data[CX2341X_MBOX_MAX_DATA];
+	u32 status;
+
+	del_timer(&itv->dma_timer);
+
+	ivtv_api_get_data(&itv->enc_mbox, IVTV_MBOX_DMA_END, 2, data);
+	status = read_reg(IVTV_REG_DMASTATUS);
+	IVTV_DEBUG_WARN("DMA ERROR %08x %08x %08x %d\n", data[0], data[1],
+				status, itv->cur_dma_stream);
+	/*
+	 * We do *not* write back to the IVTV_REG_DMASTATUS register to
+	 * clear the error status, if either the encoder write (0x02) or
+	 * decoder read (0x01) bus master DMA operation do not indicate
+	 * completed.  We can race with the DMA engine, which may have
+	 * transitioned to completed status *after* we read the register.
+	 * Setting a IVTV_REG_DMASTATUS flag back to "busy" status, after the
+	 * DMA engine has completed, will cause the DMA engine to stop working.
+	 */
+	status &= 0x3;
+	if (status == 0x3)
+		write_reg(status, IVTV_REG_DMASTATUS);
+
+	if (!test_bit(IVTV_F_I_UDMA, &itv->i_flags) &&
+	    itv->cur_dma_stream >= 0 && itv->cur_dma_stream < IVTV_MAX_STREAMS) {
+		struct ivtv_stream *s = &itv->streams[itv->cur_dma_stream];
+
+		if (s->type >= IVTV_DEC_STREAM_TYPE_MPG) {
+			/* retry */
+			/*
+			 * FIXME - handle cases of DMA error similar to
+			 * encoder below, except conditioned on status & 0x1
+			 */
+			ivtv_dma_dec_start(s);
+			return;
+		} else {
+			if ((status & 0x2) == 0) {
+				/*
+				 * CX2341x Bus Master DMA write is ongoing.
+				 * Reset the timer and let it complete.
+				 */
+				itv->dma_timer.expires =
+						jiffies + msecs_to_jiffies(600);
+				add_timer(&itv->dma_timer);
+				return;
+			}
+
+			if (itv->dma_retries < 3) {
+				/*
+				 * CX2341x Bus Master DMA write has ended.
+				 * Retry the write, starting with the first
+				 * xfer segment. Just retrying the current
+				 * segment is not sufficient.
+				 */
+				s->sg_processed = 0;
+				itv->dma_retries++;
+				ivtv_dma_enc_start_xfer(s);
+				return;
+			}
+			/* Too many retries, give up on this one */
+		}
+
+	}
+	if (test_bit(IVTV_F_I_UDMA, &itv->i_flags)) {
+		ivtv_udma_start(itv);
+		return;
+	}
+	clear_bit(IVTV_F_I_UDMA, &itv->i_flags);
+	clear_bit(IVTV_F_I_DMA, &itv->i_flags);
+	itv->cur_dma_stream = -1;
+	wake_up(&itv->dma_waitq);
+}
+
+static void ivtv_irq_enc_start_cap(struct ivtv *itv)
+{
+	u32 data[CX2341X_MBOX_MAX_DATA];
+	struct ivtv_stream *s;
+
+	/* Get DMA destination and size arguments from card */
+	ivtv_api_get_data(&itv->enc_mbox, IVTV_MBOX_DMA, 7, data);
+	IVTV_DEBUG_HI_IRQ("ENC START CAP %d: %08x %08x\n", data[0], data[1], data[2]);
+
+	if (data[0] > 2 || data[1] == 0 || data[2] == 0) {
+		IVTV_DEBUG_WARN("Unknown input: %08x %08x %08x\n",
+				data[0], data[1], data[2]);
+		return;
+	}
+	s = &itv->streams[ivtv_stream_map[data[0]]];
+	if (!stream_enc_dma_append(s, data)) {
+		set_bit(ivtv_use_pio(s) ? IVTV_F_S_PIO_PENDING : IVTV_F_S_DMA_PENDING, &s->s_flags);
+	}
+}
+
+static void ivtv_irq_enc_vbi_cap(struct ivtv *itv)
+{
+	u32 data[CX2341X_MBOX_MAX_DATA];
+	struct ivtv_stream *s;
+
+	IVTV_DEBUG_HI_IRQ("ENC START VBI CAP\n");
+	s = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI];
+
+	if (!stream_enc_dma_append(s, data))
+		set_bit(ivtv_use_pio(s) ? IVTV_F_S_PIO_PENDING : IVTV_F_S_DMA_PENDING, &s->s_flags);
+}
+
+static void ivtv_irq_dec_vbi_reinsert(struct ivtv *itv)
+{
+	u32 data[CX2341X_MBOX_MAX_DATA];
+	struct ivtv_stream *s = &itv->streams[IVTV_DEC_STREAM_TYPE_VBI];
+
+	IVTV_DEBUG_HI_IRQ("DEC VBI REINSERT\n");
+	if (test_bit(IVTV_F_S_CLAIMED, &s->s_flags) &&
+			!stream_enc_dma_append(s, data)) {
+		set_bit(IVTV_F_S_PIO_PENDING, &s->s_flags);
+	}
+}
+
+static void ivtv_irq_dec_data_req(struct ivtv *itv)
+{
+	u32 data[CX2341X_MBOX_MAX_DATA];
+	struct ivtv_stream *s;
+
+	/* YUV or MPG */
+
+	if (test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags)) {
+		ivtv_api_get_data(&itv->dec_mbox, IVTV_MBOX_DMA, 2, data);
+		itv->dma_data_req_size =
+				 1080 * ((itv->yuv_info.v4l2_src_h + 31) & ~31);
+		itv->dma_data_req_offset = data[1];
+		if (atomic_read(&itv->yuv_info.next_dma_frame) >= 0)
+			ivtv_yuv_frame_complete(itv);
+		s = &itv->streams[IVTV_DEC_STREAM_TYPE_YUV];
+	}
+	else {
+		ivtv_api_get_data(&itv->dec_mbox, IVTV_MBOX_DMA, 3, data);
+		itv->dma_data_req_size = min_t(u32, data[2], 0x10000);
+		itv->dma_data_req_offset = data[1];
+		s = &itv->streams[IVTV_DEC_STREAM_TYPE_MPG];
+	}
+	IVTV_DEBUG_HI_IRQ("DEC DATA REQ %s: %d %08x %u\n", s->name, s->q_full.bytesused,
+		       itv->dma_data_req_offset, itv->dma_data_req_size);
+	if (itv->dma_data_req_size == 0 || s->q_full.bytesused < itv->dma_data_req_size) {
+		set_bit(IVTV_F_S_NEEDS_DATA, &s->s_flags);
+	}
+	else {
+		if (test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags))
+			ivtv_yuv_setup_stream_frame(itv);
+		clear_bit(IVTV_F_S_NEEDS_DATA, &s->s_flags);
+		ivtv_queue_move(s, &s->q_full, NULL, &s->q_predma, itv->dma_data_req_size);
+		ivtv_dma_stream_dec_prepare(s, itv->dma_data_req_offset + IVTV_DECODER_OFFSET, 0);
+	}
+}
+
+static void ivtv_irq_vsync(struct ivtv *itv)
+{
+	/* The vsync interrupt is unusual in that it won't clear until
+	 * the end of the first line for the current field, at which
+	 * point it clears itself. This can result in repeated vsync
+	 * interrupts, or a missed vsync. Read some of the registers
+	 * to determine the line being displayed and ensure we handle
+	 * one vsync per frame.
+	 */
+	unsigned int frame = read_reg(IVTV_REG_DEC_LINE_FIELD) & 1;
+	struct yuv_playback_info *yi = &itv->yuv_info;
+	int last_dma_frame = atomic_read(&yi->next_dma_frame);
+	struct yuv_frame_info *f = &yi->new_frame_info[last_dma_frame];
+
+	if (0) IVTV_DEBUG_IRQ("DEC VSYNC\n");
+
+	if (((frame ^ f->sync_field) == 0 &&
+		((itv->last_vsync_field & 1) ^ f->sync_field)) ||
+			(frame != (itv->last_vsync_field & 1) && !f->interlaced)) {
+		int next_dma_frame = last_dma_frame;
+
+		if (!(f->interlaced && f->delay && yi->fields_lapsed < 1)) {
+			if (next_dma_frame >= 0 && next_dma_frame != atomic_read(&yi->next_fill_frame)) {
+				write_reg(yuv_offset[next_dma_frame] >> 4, 0x82c);
+				write_reg((yuv_offset[next_dma_frame] + IVTV_YUV_BUFFER_UV_OFFSET) >> 4, 0x830);
+				write_reg(yuv_offset[next_dma_frame] >> 4, 0x834);
+				write_reg((yuv_offset[next_dma_frame] + IVTV_YUV_BUFFER_UV_OFFSET) >> 4, 0x838);
+				next_dma_frame = (next_dma_frame + 1) % IVTV_YUV_BUFFERS;
+				atomic_set(&yi->next_dma_frame, next_dma_frame);
+				yi->fields_lapsed = -1;
+				yi->running = 1;
+			}
+		}
+	}
+	if (frame != (itv->last_vsync_field & 1)) {
+		static const struct v4l2_event evtop = {
+			.type = V4L2_EVENT_VSYNC,
+			.u.vsync.field = V4L2_FIELD_TOP,
+		};
+		static const struct v4l2_event evbottom = {
+			.type = V4L2_EVENT_VSYNC,
+			.u.vsync.field = V4L2_FIELD_BOTTOM,
+		};
+		struct ivtv_stream *s = ivtv_get_output_stream(itv);
+
+		itv->last_vsync_field += 1;
+		if (frame == 0) {
+			clear_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags);
+			clear_bit(IVTV_F_I_EV_VSYNC_FIELD, &itv->i_flags);
+		}
+		else {
+			set_bit(IVTV_F_I_EV_VSYNC_FIELD, &itv->i_flags);
+		}
+		if (test_bit(IVTV_F_I_EV_VSYNC_ENABLED, &itv->i_flags)) {
+			set_bit(IVTV_F_I_EV_VSYNC, &itv->i_flags);
+			wake_up(&itv->event_waitq);
+			if (s)
+				wake_up(&s->waitq);
+		}
+		if (s && s->vdev)
+			v4l2_event_queue(s->vdev, frame ? &evtop : &evbottom);
+		wake_up(&itv->vsync_waitq);
+
+		/* Send VBI to saa7127 */
+		if (frame && (itv->output_mode == OUT_PASSTHROUGH ||
+			test_bit(IVTV_F_I_UPDATE_WSS, &itv->i_flags) ||
+			test_bit(IVTV_F_I_UPDATE_VPS, &itv->i_flags) ||
+			test_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags))) {
+			set_bit(IVTV_F_I_WORK_HANDLER_VBI, &itv->i_flags);
+			set_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags);
+		}
+
+		/* Check if we need to update the yuv registers */
+		if (yi->running && (yi->yuv_forced_update || f->update)) {
+			if (!f->update) {
+				last_dma_frame =
+					(u8)(atomic_read(&yi->next_dma_frame) -
+						 1) % IVTV_YUV_BUFFERS;
+				f = &yi->new_frame_info[last_dma_frame];
+			}
+
+			if (f->src_w) {
+				yi->update_frame = last_dma_frame;
+				f->update = 0;
+				yi->yuv_forced_update = 0;
+				set_bit(IVTV_F_I_WORK_HANDLER_YUV, &itv->i_flags);
+				set_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags);
+			}
+		}
+
+		yi->fields_lapsed++;
+	}
+}
+
+#define IVTV_IRQ_DMA (IVTV_IRQ_DMA_READ | IVTV_IRQ_ENC_DMA_COMPLETE | IVTV_IRQ_DMA_ERR | IVTV_IRQ_ENC_START_CAP | IVTV_IRQ_ENC_VBI_CAP | IVTV_IRQ_DEC_DATA_REQ | IVTV_IRQ_DEC_VBI_RE_INSERT)
+
+irqreturn_t ivtv_irq_handler(int irq, void *dev_id)
+{
+	struct ivtv *itv = (struct ivtv *)dev_id;
+	u32 combo;
+	u32 stat;
+	int i;
+	u8 vsync_force = 0;
+
+	spin_lock(&itv->dma_reg_lock);
+	/* get contents of irq status register */
+	stat = read_reg(IVTV_REG_IRQSTATUS);
+
+	combo = ~itv->irqmask & stat;
+
+	/* Clear out IRQ */
+	if (combo) write_reg(combo, IVTV_REG_IRQSTATUS);
+
+	if (0 == combo) {
+		/* The vsync interrupt is unusual and clears itself. If we
+		 * took too long, we may have missed it. Do some checks
+		 */
+		if (~itv->irqmask & IVTV_IRQ_DEC_VSYNC) {
+			/* vsync is enabled, see if we're in a new field */
+			if ((itv->last_vsync_field & 1) !=
+			    (read_reg(IVTV_REG_DEC_LINE_FIELD) & 1)) {
+				/* New field, looks like we missed it */
+				IVTV_DEBUG_YUV("VSync interrupt missed %d\n",
+				       read_reg(IVTV_REG_DEC_LINE_FIELD) >> 16);
+				vsync_force = 1;
+			}
+		}
+
+		if (!vsync_force) {
+			/* No Vsync expected, wasn't for us */
+			spin_unlock(&itv->dma_reg_lock);
+			return IRQ_NONE;
+		}
+	}
+
+	/* Exclude interrupts noted below from the output, otherwise the log is flooded with
+	   these messages */
+	if (combo & ~0xff6d0400)
+		IVTV_DEBUG_HI_IRQ("======= valid IRQ bits: 0x%08x ======\n", combo);
+
+	if (combo & IVTV_IRQ_DEC_DMA_COMPLETE) {
+		IVTV_DEBUG_HI_IRQ("DEC DMA COMPLETE\n");
+	}
+
+	if (combo & IVTV_IRQ_DMA_READ) {
+		ivtv_irq_dma_read(itv);
+	}
+
+	if (combo & IVTV_IRQ_ENC_DMA_COMPLETE) {
+		ivtv_irq_enc_dma_complete(itv);
+	}
+
+	if (combo & IVTV_IRQ_ENC_PIO_COMPLETE) {
+		ivtv_irq_enc_pio_complete(itv);
+	}
+
+	if (combo & IVTV_IRQ_DMA_ERR) {
+		ivtv_irq_dma_err(itv);
+	}
+
+	if (combo & IVTV_IRQ_ENC_START_CAP) {
+		ivtv_irq_enc_start_cap(itv);
+	}
+
+	if (combo & IVTV_IRQ_ENC_VBI_CAP) {
+		ivtv_irq_enc_vbi_cap(itv);
+	}
+
+	if (combo & IVTV_IRQ_DEC_VBI_RE_INSERT) {
+		ivtv_irq_dec_vbi_reinsert(itv);
+	}
+
+	if (combo & IVTV_IRQ_ENC_EOS) {
+		IVTV_DEBUG_IRQ("ENC EOS\n");
+		set_bit(IVTV_F_I_EOS, &itv->i_flags);
+		wake_up(&itv->eos_waitq);
+	}
+
+	if (combo & IVTV_IRQ_DEC_DATA_REQ) {
+		ivtv_irq_dec_data_req(itv);
+	}
+
+	/* Decoder Vertical Sync - We can't rely on 'combo', so check if vsync enabled */
+	if (~itv->irqmask & IVTV_IRQ_DEC_VSYNC) {
+		ivtv_irq_vsync(itv);
+	}
+
+	if (combo & IVTV_IRQ_ENC_VIM_RST) {
+		IVTV_DEBUG_IRQ("VIM RST\n");
+		/*ivtv_vapi(itv, CX2341X_ENC_REFRESH_INPUT, 0); */
+	}
+
+	if (combo & IVTV_IRQ_DEC_AUD_MODE_CHG) {
+		IVTV_DEBUG_INFO("Stereo mode changed\n");
+	}
+
+	if ((combo & IVTV_IRQ_DMA) && !test_bit(IVTV_F_I_DMA, &itv->i_flags)) {
+		itv->irq_rr_idx++;
+		for (i = 0; i < IVTV_MAX_STREAMS; i++) {
+			int idx = (i + itv->irq_rr_idx) % IVTV_MAX_STREAMS;
+			struct ivtv_stream *s = &itv->streams[idx];
+
+			if (!test_and_clear_bit(IVTV_F_S_DMA_PENDING, &s->s_flags))
+				continue;
+			if (s->type >= IVTV_DEC_STREAM_TYPE_MPG)
+				ivtv_dma_dec_start(s);
+			else
+				ivtv_dma_enc_start(s);
+			break;
+		}
+
+		if (i == IVTV_MAX_STREAMS &&
+		    test_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags))
+			ivtv_udma_start(itv);
+	}
+
+	if ((combo & IVTV_IRQ_DMA) && !test_bit(IVTV_F_I_PIO, &itv->i_flags)) {
+		itv->irq_rr_idx++;
+		for (i = 0; i < IVTV_MAX_STREAMS; i++) {
+			int idx = (i + itv->irq_rr_idx) % IVTV_MAX_STREAMS;
+			struct ivtv_stream *s = &itv->streams[idx];
+
+			if (!test_and_clear_bit(IVTV_F_S_PIO_PENDING, &s->s_flags))
+				continue;
+			if (s->type == IVTV_DEC_STREAM_TYPE_VBI || s->type < IVTV_DEC_STREAM_TYPE_MPG)
+				ivtv_dma_enc_start(s);
+			break;
+		}
+	}
+
+	if (test_and_clear_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags)) {
+		queue_kthread_work(&itv->irq_worker, &itv->irq_work);
+	}
+
+	spin_unlock(&itv->dma_reg_lock);
+
+	/* If we've just handled a 'forced' vsync, it's safest to say it
+	 * wasn't ours. Another device may have triggered it at just
+	 * the right time.
+	 */
+	return vsync_force ? IRQ_NONE : IRQ_HANDLED;
+}
+
+void ivtv_unfinished_dma(unsigned long arg)
+{
+	struct ivtv *itv = (struct ivtv *)arg;
+
+	if (!test_bit(IVTV_F_I_DMA, &itv->i_flags))
+		return;
+	IVTV_ERR("DMA TIMEOUT %08x %d\n", read_reg(IVTV_REG_DMASTATUS), itv->cur_dma_stream);
+
+	write_reg(read_reg(IVTV_REG_DMASTATUS) & 3, IVTV_REG_DMASTATUS);
+	clear_bit(IVTV_F_I_UDMA, &itv->i_flags);
+	clear_bit(IVTV_F_I_DMA, &itv->i_flags);
+	itv->cur_dma_stream = -1;
+	wake_up(&itv->dma_waitq);
+}
diff --git a/drivers/media/pci/ivtv/ivtv-irq.h b/drivers/media/pci/ivtv/ivtv-irq.h
new file mode 100644
index 0000000..1e84433
--- /dev/null
+++ b/drivers/media/pci/ivtv/ivtv-irq.h
@@ -0,0 +1,53 @@
+/*
+    interrupt handling
+    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
+    Copyright (C) 2004  Chris Kennedy <c@groovy.org>
+    Copyright (C) 2005-2007  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef IVTV_IRQ_H
+#define IVTV_IRQ_H
+
+#define IVTV_IRQ_ENC_START_CAP		(0x1 << 31)
+#define IVTV_IRQ_ENC_EOS		(0x1 << 30)
+#define IVTV_IRQ_ENC_VBI_CAP		(0x1 << 29)
+#define IVTV_IRQ_ENC_VIM_RST		(0x1 << 28)
+#define IVTV_IRQ_ENC_DMA_COMPLETE	(0x1 << 27)
+#define IVTV_IRQ_ENC_PIO_COMPLETE	(0x1 << 25)
+#define IVTV_IRQ_DEC_AUD_MODE_CHG	(0x1 << 24)
+#define IVTV_IRQ_DEC_DATA_REQ		(0x1 << 22)
+#define IVTV_IRQ_DEC_DMA_COMPLETE	(0x1 << 20)
+#define IVTV_IRQ_DEC_VBI_RE_INSERT	(0x1 << 19)
+#define IVTV_IRQ_DMA_ERR		(0x1 << 18)
+#define IVTV_IRQ_DMA_WRITE		(0x1 << 17)
+#define IVTV_IRQ_DMA_READ		(0x1 << 16)
+#define IVTV_IRQ_DEC_VSYNC		(0x1 << 10)
+
+/* IRQ Masks */
+#define IVTV_IRQ_MASK_INIT (IVTV_IRQ_DMA_ERR|IVTV_IRQ_ENC_DMA_COMPLETE|\
+		IVTV_IRQ_DMA_READ|IVTV_IRQ_ENC_PIO_COMPLETE)
+
+#define IVTV_IRQ_MASK_CAPTURE (IVTV_IRQ_ENC_START_CAP | IVTV_IRQ_ENC_EOS)
+#define IVTV_IRQ_MASK_DECODE  (IVTV_IRQ_DEC_DATA_REQ|IVTV_IRQ_DEC_AUD_MODE_CHG)
+
+irqreturn_t ivtv_irq_handler(int irq, void *dev_id);
+
+void ivtv_irq_work_handler(struct kthread_work *work);
+void ivtv_dma_stream_dec_prepare(struct ivtv_stream *s, u32 offset, int lock);
+void ivtv_unfinished_dma(unsigned long arg);
+
+#endif
diff --git a/drivers/media/pci/ivtv/ivtv-mailbox.c b/drivers/media/pci/ivtv/ivtv-mailbox.c
new file mode 100644
index 0000000..e3ce967
--- /dev/null
+++ b/drivers/media/pci/ivtv/ivtv-mailbox.c
@@ -0,0 +1,387 @@
+/*
+    mailbox functions
+    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
+    Copyright (C) 2004  Chris Kennedy <c@groovy.org>
+    Copyright (C) 2005-2007  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <stdarg.h>
+
+#include "ivtv-driver.h"
+#include "ivtv-mailbox.h"
+
+/* Firmware mailbox flags*/
+#define IVTV_MBOX_FIRMWARE_DONE 0x00000004
+#define IVTV_MBOX_DRIVER_DONE   0x00000002
+#define IVTV_MBOX_DRIVER_BUSY   0x00000001
+#define IVTV_MBOX_FREE 		0x00000000
+
+/* Firmware mailbox standard timeout */
+#define IVTV_API_STD_TIMEOUT 	0x02000000
+
+#define API_CACHE 	 (1 << 0) 	/* Allow the command to be stored in the cache */
+#define API_RESULT	 (1 << 1) 	/* Allow 1 second for this cmd to end */
+#define API_FAST_RESULT	 (3 << 1)	/* Allow 0.1 second for this cmd to end */
+#define API_DMA 	 (1 << 3)	/* DMA mailbox, has special handling */
+#define API_HIGH_VOL 	 (1 << 5)	/* High volume command (i.e. called during encoding or decoding) */
+#define API_NO_WAIT_MB 	 (1 << 4)	/* Command may not wait for a free mailbox */
+#define API_NO_WAIT_RES	 (1 << 5)	/* Command may not wait for the result */
+#define API_NO_POLL	 (1 << 6)	/* Avoid pointless polling */
+
+struct ivtv_api_info {
+	int flags;		/* Flags, see above */
+	const char *name; 	/* The name of the command */
+};
+
+#define API_ENTRY(x, f) [x] = { (f), #x }
+
+static const struct ivtv_api_info api_info[256] = {
+	/* MPEG encoder API */
+	API_ENTRY(CX2341X_ENC_PING_FW, 			API_FAST_RESULT),
+	API_ENTRY(CX2341X_ENC_START_CAPTURE, 		API_RESULT | API_NO_POLL),
+	API_ENTRY(CX2341X_ENC_STOP_CAPTURE, 		API_RESULT),
+	API_ENTRY(CX2341X_ENC_SET_AUDIO_ID, 		API_CACHE),
+	API_ENTRY(CX2341X_ENC_SET_VIDEO_ID, 		API_CACHE),
+	API_ENTRY(CX2341X_ENC_SET_PCR_ID, 		API_CACHE),
+	API_ENTRY(CX2341X_ENC_SET_FRAME_RATE, 		API_CACHE),
+	API_ENTRY(CX2341X_ENC_SET_FRAME_SIZE, 		API_CACHE),
+	API_ENTRY(CX2341X_ENC_SET_BIT_RATE, 		API_CACHE),
+	API_ENTRY(CX2341X_ENC_SET_GOP_PROPERTIES, 	API_CACHE),
+	API_ENTRY(CX2341X_ENC_SET_ASPECT_RATIO, 	API_CACHE),
+	API_ENTRY(CX2341X_ENC_SET_DNR_FILTER_MODE, 	API_CACHE),
+	API_ENTRY(CX2341X_ENC_SET_DNR_FILTER_PROPS, 	API_CACHE),
+	API_ENTRY(CX2341X_ENC_SET_CORING_LEVELS, 	API_CACHE),
+	API_ENTRY(CX2341X_ENC_SET_SPATIAL_FILTER_TYPE, 	API_CACHE),
+	API_ENTRY(CX2341X_ENC_SET_VBI_LINE, 		API_RESULT),
+	API_ENTRY(CX2341X_ENC_SET_STREAM_TYPE, 		API_CACHE),
+	API_ENTRY(CX2341X_ENC_SET_OUTPUT_PORT, 		API_CACHE),
+	API_ENTRY(CX2341X_ENC_SET_AUDIO_PROPERTIES, 	API_CACHE),
+	API_ENTRY(CX2341X_ENC_HALT_FW, 			API_FAST_RESULT),
+	API_ENTRY(CX2341X_ENC_GET_VERSION, 		API_FAST_RESULT),
+	API_ENTRY(CX2341X_ENC_SET_GOP_CLOSURE, 		API_CACHE),
+	API_ENTRY(CX2341X_ENC_GET_SEQ_END, 		API_RESULT),
+	API_ENTRY(CX2341X_ENC_SET_PGM_INDEX_INFO, 	API_FAST_RESULT),
+	API_ENTRY(CX2341X_ENC_SET_VBI_CONFIG, 		API_RESULT),
+	API_ENTRY(CX2341X_ENC_SET_DMA_BLOCK_SIZE, 	API_CACHE),
+	API_ENTRY(CX2341X_ENC_GET_PREV_DMA_INFO_MB_10, 	API_FAST_RESULT),
+	API_ENTRY(CX2341X_ENC_GET_PREV_DMA_INFO_MB_9, 	API_FAST_RESULT),
+	API_ENTRY(CX2341X_ENC_SCHED_DMA_TO_HOST, 	API_DMA | API_HIGH_VOL),
+	API_ENTRY(CX2341X_ENC_INITIALIZE_INPUT, 	API_RESULT),
+	API_ENTRY(CX2341X_ENC_SET_FRAME_DROP_RATE, 	API_CACHE),
+	API_ENTRY(CX2341X_ENC_PAUSE_ENCODER, 		API_RESULT),
+	API_ENTRY(CX2341X_ENC_REFRESH_INPUT, 		API_NO_WAIT_MB | API_HIGH_VOL),
+	API_ENTRY(CX2341X_ENC_SET_COPYRIGHT, 		API_CACHE),
+	API_ENTRY(CX2341X_ENC_SET_EVENT_NOTIFICATION, 	API_RESULT),
+	API_ENTRY(CX2341X_ENC_SET_NUM_VSYNC_LINES, 	API_CACHE),
+	API_ENTRY(CX2341X_ENC_SET_PLACEHOLDER, 		API_CACHE),
+	API_ENTRY(CX2341X_ENC_MUTE_VIDEO, 		API_RESULT),
+	API_ENTRY(CX2341X_ENC_MUTE_AUDIO, 		API_RESULT),
+	API_ENTRY(CX2341X_ENC_SET_VERT_CROP_LINE,	API_FAST_RESULT),
+	API_ENTRY(CX2341X_ENC_MISC, 			API_FAST_RESULT),
+	/* Obsolete PULLDOWN API command */
+	API_ENTRY(0xb1, 				API_CACHE),
+
+	/* MPEG decoder API */
+	API_ENTRY(CX2341X_DEC_PING_FW, 			API_FAST_RESULT),
+	API_ENTRY(CX2341X_DEC_START_PLAYBACK, 		API_RESULT | API_NO_POLL),
+	API_ENTRY(CX2341X_DEC_STOP_PLAYBACK, 		API_RESULT),
+	API_ENTRY(CX2341X_DEC_SET_PLAYBACK_SPEED, 	API_RESULT),
+	API_ENTRY(CX2341X_DEC_STEP_VIDEO, 		API_RESULT),
+	API_ENTRY(CX2341X_DEC_SET_DMA_BLOCK_SIZE, 	API_CACHE),
+	API_ENTRY(CX2341X_DEC_GET_XFER_INFO, 		API_FAST_RESULT),
+	API_ENTRY(CX2341X_DEC_GET_DMA_STATUS, 		API_FAST_RESULT),
+	API_ENTRY(CX2341X_DEC_SCHED_DMA_FROM_HOST, 	API_DMA | API_HIGH_VOL),
+	API_ENTRY(CX2341X_DEC_PAUSE_PLAYBACK, 		API_RESULT),
+	API_ENTRY(CX2341X_DEC_HALT_FW, 			API_FAST_RESULT),
+	API_ENTRY(CX2341X_DEC_SET_STANDARD, 		API_CACHE),
+	API_ENTRY(CX2341X_DEC_GET_VERSION, 		API_FAST_RESULT),
+	API_ENTRY(CX2341X_DEC_SET_STREAM_INPUT, 	API_CACHE),
+	API_ENTRY(CX2341X_DEC_GET_TIMING_INFO, 		API_RESULT /*| API_NO_WAIT_RES*/),
+	API_ENTRY(CX2341X_DEC_SET_AUDIO_MODE, 		API_CACHE),
+	API_ENTRY(CX2341X_DEC_SET_EVENT_NOTIFICATION, 	API_RESULT),
+	API_ENTRY(CX2341X_DEC_SET_DISPLAY_BUFFERS, 	API_CACHE),
+	API_ENTRY(CX2341X_DEC_EXTRACT_VBI, 		API_RESULT),
+	API_ENTRY(CX2341X_DEC_SET_DECODER_SOURCE, 	API_FAST_RESULT),
+	API_ENTRY(CX2341X_DEC_SET_PREBUFFERING, 	API_CACHE),
+
+	/* OSD API */
+	API_ENTRY(CX2341X_OSD_GET_FRAMEBUFFER, 		API_FAST_RESULT),
+	API_ENTRY(CX2341X_OSD_GET_PIXEL_FORMAT, 	API_FAST_RESULT),
+	API_ENTRY(CX2341X_OSD_SET_PIXEL_FORMAT, 	API_CACHE),
+	API_ENTRY(CX2341X_OSD_GET_STATE, 		API_FAST_RESULT),
+	API_ENTRY(CX2341X_OSD_SET_STATE, 		API_CACHE),
+	API_ENTRY(CX2341X_OSD_GET_OSD_COORDS, 		API_FAST_RESULT),
+	API_ENTRY(CX2341X_OSD_SET_OSD_COORDS, 		API_CACHE),
+	API_ENTRY(CX2341X_OSD_GET_SCREEN_COORDS, 	API_FAST_RESULT),
+	API_ENTRY(CX2341X_OSD_SET_SCREEN_COORDS, 	API_CACHE),
+	API_ENTRY(CX2341X_OSD_GET_GLOBAL_ALPHA, 	API_FAST_RESULT),
+	API_ENTRY(CX2341X_OSD_SET_GLOBAL_ALPHA, 	API_CACHE),
+	API_ENTRY(CX2341X_OSD_SET_BLEND_COORDS, 	API_CACHE),
+	API_ENTRY(CX2341X_OSD_GET_FLICKER_STATE, 	API_FAST_RESULT),
+	API_ENTRY(CX2341X_OSD_SET_FLICKER_STATE, 	API_CACHE),
+	API_ENTRY(CX2341X_OSD_BLT_COPY, 		API_RESULT),
+	API_ENTRY(CX2341X_OSD_BLT_FILL, 		API_RESULT),
+	API_ENTRY(CX2341X_OSD_BLT_TEXT, 		API_RESULT),
+	API_ENTRY(CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 	API_CACHE),
+	API_ENTRY(CX2341X_OSD_SET_CHROMA_KEY, 		API_CACHE),
+	API_ENTRY(CX2341X_OSD_GET_ALPHA_CONTENT_INDEX, 	API_FAST_RESULT),
+	API_ENTRY(CX2341X_OSD_SET_ALPHA_CONTENT_INDEX, 	API_CACHE)
+};
+
+static int try_mailbox(struct ivtv *itv, struct ivtv_mailbox_data *mbdata, int mb)
+{
+	u32 flags = readl(&mbdata->mbox[mb].flags);
+	int is_free = flags == IVTV_MBOX_FREE || (flags & IVTV_MBOX_FIRMWARE_DONE);
+
+	/* if the mailbox is free, then try to claim it */
+	if (is_free && !test_and_set_bit(mb, &mbdata->busy)) {
+		write_sync(IVTV_MBOX_DRIVER_BUSY, &mbdata->mbox[mb].flags);
+		return 1;
+	}
+	return 0;
+}
+
+/* Try to find a free mailbox. Note mailbox 0 is reserved for DMA and so is not
+   attempted here. */
+static int get_mailbox(struct ivtv *itv, struct ivtv_mailbox_data *mbdata, int flags)
+{
+	unsigned long then = jiffies;
+	int i, mb;
+	int max_mbox = mbdata->max_mbox;
+	int retries = 100;
+
+	/* All slow commands use the same mailbox, serializing them and also
+	   leaving the other mailbox free for simple fast commands. */
+	if ((flags & API_FAST_RESULT) == API_RESULT)
+		max_mbox = 1;
+
+	/* find free non-DMA mailbox */
+	for (i = 0; i < retries; i++) {
+		for (mb = 1; mb <= max_mbox; mb++)
+			if (try_mailbox(itv, mbdata, mb))
+				return mb;
+
+		/* Sleep before a retry, if not atomic */
+		if (!(flags & API_NO_WAIT_MB)) {
+			if (time_after(jiffies,
+				       then + msecs_to_jiffies(10*retries)))
+			       break;
+			ivtv_msleep_timeout(10, 0);
+		}
+	}
+	return -ENODEV;
+}
+
+static void write_mailbox(volatile struct ivtv_mailbox __iomem *mbox, int cmd, int args, u32 data[])
+{
+	int i;
+
+	write_sync(cmd, &mbox->cmd);
+	write_sync(IVTV_API_STD_TIMEOUT, &mbox->timeout);
+
+	for (i = 0; i < CX2341X_MBOX_MAX_DATA; i++)
+		write_sync(data[i], &mbox->data[i]);
+
+	write_sync(IVTV_MBOX_DRIVER_DONE | IVTV_MBOX_DRIVER_BUSY, &mbox->flags);
+}
+
+static void clear_all_mailboxes(struct ivtv *itv, struct ivtv_mailbox_data *mbdata)
+{
+	int i;
+
+	for (i = 0; i <= mbdata->max_mbox; i++) {
+		IVTV_DEBUG_WARN("Clearing mailbox %d: cmd 0x%08x flags 0x%08x\n",
+			i, readl(&mbdata->mbox[i].cmd), readl(&mbdata->mbox[i].flags));
+		write_sync(0, &mbdata->mbox[i].flags);
+		clear_bit(i, &mbdata->busy);
+	}
+}
+
+static int ivtv_api_call(struct ivtv *itv, int cmd, int args, u32 data[])
+{
+	struct ivtv_mailbox_data *mbdata = (cmd >= 128) ? &itv->enc_mbox : &itv->dec_mbox;
+	volatile struct ivtv_mailbox __iomem *mbox;
+	int api_timeout = msecs_to_jiffies(1000);
+	int flags, mb, i;
+	unsigned long then;
+
+	/* sanity checks */
+	if (NULL == mbdata) {
+		IVTV_ERR("No mailbox allocated\n");
+		return -ENODEV;
+	}
+	if (args < 0 || args > CX2341X_MBOX_MAX_DATA ||
+	    cmd < 0 || cmd > 255 || api_info[cmd].name == NULL) {
+		IVTV_ERR("Invalid MB call: cmd = 0x%02x, args = %d\n", cmd, args);
+		return -EINVAL;
+	}
+
+	if (api_info[cmd].flags & API_HIGH_VOL) {
+	    IVTV_DEBUG_HI_MB("MB Call: %s\n", api_info[cmd].name);
+	}
+	else {
+	    IVTV_DEBUG_MB("MB Call: %s\n", api_info[cmd].name);
+	}
+
+	/* clear possibly uninitialized part of data array */
+	for (i = args; i < CX2341X_MBOX_MAX_DATA; i++)
+		data[i] = 0;
+
+	/* If this command was issued within the last 30 minutes and with identical
+	   data, then just return 0 as there is no need to issue this command again.
+	   Just an optimization to prevent unnecessary use of mailboxes. */
+	if (itv->api_cache[cmd].last_jiffies &&
+	    time_before(jiffies,
+			itv->api_cache[cmd].last_jiffies +
+			msecs_to_jiffies(1800000)) &&
+	    !memcmp(data, itv->api_cache[cmd].data, sizeof(itv->api_cache[cmd].data))) {
+		itv->api_cache[cmd].last_jiffies = jiffies;
+		return 0;
+	}
+
+	flags = api_info[cmd].flags;
+
+	if (flags & API_DMA) {
+		for (i = 0; i < 100; i++) {
+			mb = i % (mbdata->max_mbox + 1);
+			if (try_mailbox(itv, mbdata, mb)) {
+				write_mailbox(&mbdata->mbox[mb], cmd, args, data);
+				clear_bit(mb, &mbdata->busy);
+				return 0;
+			}
+			IVTV_DEBUG_WARN("%s: mailbox %d not free %08x\n",
+					api_info[cmd].name, mb, readl(&mbdata->mbox[mb].flags));
+		}
+		IVTV_WARN("Could not find free DMA mailbox for %s\n", api_info[cmd].name);
+		clear_all_mailboxes(itv, mbdata);
+		return -EBUSY;
+	}
+
+	if ((flags & API_FAST_RESULT) == API_FAST_RESULT)
+		api_timeout = msecs_to_jiffies(100);
+
+	mb = get_mailbox(itv, mbdata, flags);
+	if (mb < 0) {
+		IVTV_DEBUG_WARN("No free mailbox found (%s)\n", api_info[cmd].name);
+		clear_all_mailboxes(itv, mbdata);
+		return -EBUSY;
+	}
+	mbox = &mbdata->mbox[mb];
+	write_mailbox(mbox, cmd, args, data);
+	if (flags & API_CACHE) {
+		memcpy(itv->api_cache[cmd].data, data, sizeof(itv->api_cache[cmd].data));
+		itv->api_cache[cmd].last_jiffies = jiffies;
+	}
+	if ((flags & API_RESULT) == 0) {
+		clear_bit(mb, &mbdata->busy);
+		return 0;
+	}
+
+	/* Get results */
+	then = jiffies;
+
+	if (!(flags & API_NO_POLL)) {
+		/* First try to poll, then switch to delays */
+		for (i = 0; i < 100; i++) {
+			if (readl(&mbox->flags) & IVTV_MBOX_FIRMWARE_DONE)
+				break;
+		}
+	}
+	while (!(readl(&mbox->flags) & IVTV_MBOX_FIRMWARE_DONE)) {
+		if (time_after(jiffies, then + api_timeout)) {
+			IVTV_DEBUG_WARN("Could not get result (%s)\n", api_info[cmd].name);
+			/* reset the mailbox, but it is likely too late already */
+			write_sync(0, &mbox->flags);
+			clear_bit(mb, &mbdata->busy);
+			return -EIO;
+		}
+		if (flags & API_NO_WAIT_RES)
+			mdelay(1);
+		else
+			ivtv_msleep_timeout(1, 0);
+	}
+	if (time_after(jiffies, then + msecs_to_jiffies(100)))
+		IVTV_DEBUG_WARN("%s took %u jiffies\n",
+				api_info[cmd].name,
+				jiffies_to_msecs(jiffies - then));
+
+	for (i = 0; i < CX2341X_MBOX_MAX_DATA; i++)
+		data[i] = readl(&mbox->data[i]);
+	write_sync(0, &mbox->flags);
+	clear_bit(mb, &mbdata->busy);
+	return 0;
+}
+
+int ivtv_api(struct ivtv *itv, int cmd, int args, u32 data[])
+{
+	int res = ivtv_api_call(itv, cmd, args, data);
+
+	/* Allow a single retry, probably already too late though.
+	   If there is no free mailbox then that is usually an indication
+	   of a more serious problem. */
+	return (res == -EBUSY) ? ivtv_api_call(itv, cmd, args, data) : res;
+}
+
+int ivtv_api_func(void *priv, u32 cmd, int in, int out, u32 data[CX2341X_MBOX_MAX_DATA])
+{
+	return ivtv_api(priv, cmd, in, data);
+}
+
+int ivtv_vapi_result(struct ivtv *itv, u32 data[CX2341X_MBOX_MAX_DATA], int cmd, int args, ...)
+{
+	va_list ap;
+	int i;
+
+	va_start(ap, args);
+	for (i = 0; i < args; i++) {
+		data[i] = va_arg(ap, u32);
+	}
+	va_end(ap);
+	return ivtv_api(itv, cmd, args, data);
+}
+
+int ivtv_vapi(struct ivtv *itv, int cmd, int args, ...)
+{
+	u32 data[CX2341X_MBOX_MAX_DATA];
+	va_list ap;
+	int i;
+
+	va_start(ap, args);
+	for (i = 0; i < args; i++) {
+		data[i] = va_arg(ap, u32);
+	}
+	va_end(ap);
+	return ivtv_api(itv, cmd, args, data);
+}
+
+/* This one is for stuff that can't sleep.. irq handlers, etc.. */
+void ivtv_api_get_data(struct ivtv_mailbox_data *mbdata, int mb,
+		       int argc, u32 data[])
+{
+	volatile u32 __iomem *p = mbdata->mbox[mb].data;
+	int i;
+	for (i = 0; i < argc; i++, p++)
+		data[i] = readl(p);
+}
+
+/* Wipe api cache */
+void ivtv_mailbox_cache_invalidate(struct ivtv *itv)
+{
+	int i;
+	for (i = 0; i < 256; i++)
+		itv->api_cache[i].last_jiffies = 0;
+}
diff --git a/drivers/media/pci/ivtv/ivtv-mailbox.h b/drivers/media/pci/ivtv/ivtv-mailbox.h
new file mode 100644
index 0000000..2c834d2
--- /dev/null
+++ b/drivers/media/pci/ivtv/ivtv-mailbox.h
@@ -0,0 +1,35 @@
+/*
+    mailbox functions
+    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
+    Copyright (C) 2005-2007  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef IVTV_MAILBOX_H
+#define IVTV_MAILBOX_H
+
+#define IVTV_MBOX_DMA_END         8
+#define IVTV_MBOX_DMA             9
+
+void ivtv_api_get_data(struct ivtv_mailbox_data *mbdata, int mb,
+		       int argc, u32 data[]);
+int ivtv_api(struct ivtv *itv, int cmd, int args, u32 data[]);
+int ivtv_vapi_result(struct ivtv *itv, u32 data[CX2341X_MBOX_MAX_DATA], int cmd, int args, ...);
+int ivtv_vapi(struct ivtv *itv, int cmd, int args, ...);
+int ivtv_api_func(void *priv, u32 cmd, int in, int out, u32 data[CX2341X_MBOX_MAX_DATA]);
+void ivtv_mailbox_cache_invalidate(struct ivtv *itv);
+
+#endif
diff --git a/drivers/media/pci/ivtv/ivtv-queue.c b/drivers/media/pci/ivtv/ivtv-queue.c
new file mode 100644
index 0000000..7fde36e
--- /dev/null
+++ b/drivers/media/pci/ivtv/ivtv-queue.c
@@ -0,0 +1,297 @@
+/*
+    buffer queues.
+    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
+    Copyright (C) 2004  Chris Kennedy <c@groovy.org>
+    Copyright (C) 2005-2007  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "ivtv-driver.h"
+#include "ivtv-queue.h"
+
+int ivtv_buf_copy_from_user(struct ivtv_stream *s, struct ivtv_buffer *buf, const char __user *src, int copybytes)
+{
+	if (s->buf_size - buf->bytesused < copybytes)
+		copybytes = s->buf_size - buf->bytesused;
+	if (copy_from_user(buf->buf + buf->bytesused, src, copybytes)) {
+		return -EFAULT;
+	}
+	buf->bytesused += copybytes;
+	return copybytes;
+}
+
+void ivtv_buf_swap(struct ivtv_buffer *buf)
+{
+	int i;
+
+	for (i = 0; i < buf->bytesused; i += 4)
+		swab32s((u32 *)(buf->buf + i));
+}
+
+void ivtv_queue_init(struct ivtv_queue *q)
+{
+	INIT_LIST_HEAD(&q->list);
+	q->buffers = 0;
+	q->length = 0;
+	q->bytesused = 0;
+}
+
+void ivtv_enqueue(struct ivtv_stream *s, struct ivtv_buffer *buf, struct ivtv_queue *q)
+{
+	unsigned long flags;
+
+	/* clear the buffer if it is going to be enqueued to the free queue */
+	if (q == &s->q_free) {
+		buf->bytesused = 0;
+		buf->readpos = 0;
+		buf->b_flags = 0;
+		buf->dma_xfer_cnt = 0;
+	}
+	spin_lock_irqsave(&s->qlock, flags);
+	list_add_tail(&buf->list, &q->list);
+	q->buffers++;
+	q->length += s->buf_size;
+	q->bytesused += buf->bytesused - buf->readpos;
+	spin_unlock_irqrestore(&s->qlock, flags);
+}
+
+struct ivtv_buffer *ivtv_dequeue(struct ivtv_stream *s, struct ivtv_queue *q)
+{
+	struct ivtv_buffer *buf = NULL;
+	unsigned long flags;
+
+	spin_lock_irqsave(&s->qlock, flags);
+	if (!list_empty(&q->list)) {
+		buf = list_entry(q->list.next, struct ivtv_buffer, list);
+		list_del_init(q->list.next);
+		q->buffers--;
+		q->length -= s->buf_size;
+		q->bytesused -= buf->bytesused - buf->readpos;
+	}
+	spin_unlock_irqrestore(&s->qlock, flags);
+	return buf;
+}
+
+static void ivtv_queue_move_buf(struct ivtv_stream *s, struct ivtv_queue *from,
+		struct ivtv_queue *to, int clear)
+{
+	struct ivtv_buffer *buf = list_entry(from->list.next, struct ivtv_buffer, list);
+
+	list_move_tail(from->list.next, &to->list);
+	from->buffers--;
+	from->length -= s->buf_size;
+	from->bytesused -= buf->bytesused - buf->readpos;
+	/* special handling for q_free */
+	if (clear)
+		buf->bytesused = buf->readpos = buf->b_flags = buf->dma_xfer_cnt = 0;
+	to->buffers++;
+	to->length += s->buf_size;
+	to->bytesused += buf->bytesused - buf->readpos;
+}
+
+/* Move 'needed_bytes' worth of buffers from queue 'from' into queue 'to'.
+   If 'needed_bytes' == 0, then move all buffers from 'from' into 'to'.
+   If 'steal' != NULL, then buffers may also taken from that queue if
+   needed, but only if 'from' is the free queue.
+
+   The buffer is automatically cleared if it goes to the free queue. It is
+   also cleared if buffers need to be taken from the 'steal' queue and
+   the 'from' queue is the free queue.
+
+   When 'from' is q_free, then needed_bytes is compared to the total
+   available buffer length, otherwise needed_bytes is compared to the
+   bytesused value. For the 'steal' queue the total available buffer
+   length is always used.
+
+   -ENOMEM is returned if the buffers could not be obtained, 0 if all
+   buffers where obtained from the 'from' list and if non-zero then
+   the number of stolen buffers is returned. */
+int ivtv_queue_move(struct ivtv_stream *s, struct ivtv_queue *from, struct ivtv_queue *steal,
+		    struct ivtv_queue *to, int needed_bytes)
+{
+	unsigned long flags;
+	int rc = 0;
+	int from_free = from == &s->q_free;
+	int to_free = to == &s->q_free;
+	int bytes_available, bytes_steal;
+
+	spin_lock_irqsave(&s->qlock, flags);
+	if (needed_bytes == 0) {
+		from_free = 1;
+		needed_bytes = from->length;
+	}
+
+	bytes_available = from_free ? from->length : from->bytesused;
+	bytes_steal = (from_free && steal) ? steal->length : 0;
+
+	if (bytes_available + bytes_steal < needed_bytes) {
+		spin_unlock_irqrestore(&s->qlock, flags);
+		return -ENOMEM;
+	}
+	while (bytes_available < needed_bytes) {
+		struct ivtv_buffer *buf = list_entry(steal->list.prev, struct ivtv_buffer, list);
+		u16 dma_xfer_cnt = buf->dma_xfer_cnt;
+
+		/* move buffers from the tail of the 'steal' queue to the tail of the
+		   'from' queue. Always copy all the buffers with the same dma_xfer_cnt
+		   value, this ensures that you do not end up with partial frame data
+		   if one frame is stored in multiple buffers. */
+		while (dma_xfer_cnt == buf->dma_xfer_cnt) {
+			list_move_tail(steal->list.prev, &from->list);
+			rc++;
+			steal->buffers--;
+			steal->length -= s->buf_size;
+			steal->bytesused -= buf->bytesused - buf->readpos;
+			buf->bytesused = buf->readpos = buf->b_flags = buf->dma_xfer_cnt = 0;
+			from->buffers++;
+			from->length += s->buf_size;
+			bytes_available += s->buf_size;
+			if (list_empty(&steal->list))
+				break;
+			buf = list_entry(steal->list.prev, struct ivtv_buffer, list);
+		}
+	}
+	if (from_free) {
+		u32 old_length = to->length;
+
+		while (to->length - old_length < needed_bytes) {
+			ivtv_queue_move_buf(s, from, to, 1);
+		}
+	}
+	else {
+		u32 old_bytesused = to->bytesused;
+
+		while (to->bytesused - old_bytesused < needed_bytes) {
+			ivtv_queue_move_buf(s, from, to, to_free);
+		}
+	}
+	spin_unlock_irqrestore(&s->qlock, flags);
+	return rc;
+}
+
+void ivtv_flush_queues(struct ivtv_stream *s)
+{
+	ivtv_queue_move(s, &s->q_io, NULL, &s->q_free, 0);
+	ivtv_queue_move(s, &s->q_full, NULL, &s->q_free, 0);
+	ivtv_queue_move(s, &s->q_dma, NULL, &s->q_free, 0);
+	ivtv_queue_move(s, &s->q_predma, NULL, &s->q_free, 0);
+}
+
+int ivtv_stream_alloc(struct ivtv_stream *s)
+{
+	struct ivtv *itv = s->itv;
+	int SGsize = sizeof(struct ivtv_sg_host_element) * s->buffers;
+	int i;
+
+	if (s->buffers == 0)
+		return 0;
+
+	IVTV_DEBUG_INFO("Allocate %s%s stream: %d x %d buffers (%dkB total)\n",
+		s->dma != PCI_DMA_NONE ? "DMA " : "",
+		s->name, s->buffers, s->buf_size, s->buffers * s->buf_size / 1024);
+
+	s->sg_pending = kzalloc(SGsize, GFP_KERNEL|__GFP_NOWARN);
+	if (s->sg_pending == NULL) {
+		IVTV_ERR("Could not allocate sg_pending for %s stream\n", s->name);
+		return -ENOMEM;
+	}
+	s->sg_pending_size = 0;
+
+	s->sg_processing = kzalloc(SGsize, GFP_KERNEL|__GFP_NOWARN);
+	if (s->sg_processing == NULL) {
+		IVTV_ERR("Could not allocate sg_processing for %s stream\n", s->name);
+		kfree(s->sg_pending);
+		s->sg_pending = NULL;
+		return -ENOMEM;
+	}
+	s->sg_processing_size = 0;
+
+	s->sg_dma = kzalloc(sizeof(struct ivtv_sg_element),
+					GFP_KERNEL|__GFP_NOWARN);
+	if (s->sg_dma == NULL) {
+		IVTV_ERR("Could not allocate sg_dma for %s stream\n", s->name);
+		kfree(s->sg_pending);
+		s->sg_pending = NULL;
+		kfree(s->sg_processing);
+		s->sg_processing = NULL;
+		return -ENOMEM;
+	}
+	if (ivtv_might_use_dma(s)) {
+		s->sg_handle = pci_map_single(itv->pdev, s->sg_dma,
+				sizeof(struct ivtv_sg_element), PCI_DMA_TODEVICE);
+		ivtv_stream_sync_for_cpu(s);
+	}
+
+	/* allocate stream buffers. Initially all buffers are in q_free. */
+	for (i = 0; i < s->buffers; i++) {
+		struct ivtv_buffer *buf = kzalloc(sizeof(struct ivtv_buffer),
+						GFP_KERNEL|__GFP_NOWARN);
+
+		if (buf == NULL)
+			break;
+		buf->buf = kmalloc(s->buf_size + 256, GFP_KERNEL|__GFP_NOWARN);
+		if (buf->buf == NULL) {
+			kfree(buf);
+			break;
+		}
+		INIT_LIST_HEAD(&buf->list);
+		if (ivtv_might_use_dma(s)) {
+			buf->dma_handle = pci_map_single(s->itv->pdev,
+				buf->buf, s->buf_size + 256, s->dma);
+			ivtv_buf_sync_for_cpu(s, buf);
+		}
+		ivtv_enqueue(s, buf, &s->q_free);
+	}
+	if (i == s->buffers)
+		return 0;
+	IVTV_ERR("Couldn't allocate buffers for %s stream\n", s->name);
+	ivtv_stream_free(s);
+	return -ENOMEM;
+}
+
+void ivtv_stream_free(struct ivtv_stream *s)
+{
+	struct ivtv_buffer *buf;
+
+	/* move all buffers to q_free */
+	ivtv_flush_queues(s);
+
+	/* empty q_free */
+	while ((buf = ivtv_dequeue(s, &s->q_free))) {
+		if (ivtv_might_use_dma(s))
+			pci_unmap_single(s->itv->pdev, buf->dma_handle,
+				s->buf_size + 256, s->dma);
+		kfree(buf->buf);
+		kfree(buf);
+	}
+
+	/* Free SG Array/Lists */
+	if (s->sg_dma != NULL) {
+		if (s->sg_handle != IVTV_DMA_UNMAPPED) {
+			pci_unmap_single(s->itv->pdev, s->sg_handle,
+				 sizeof(struct ivtv_sg_element), PCI_DMA_TODEVICE);
+			s->sg_handle = IVTV_DMA_UNMAPPED;
+		}
+		kfree(s->sg_pending);
+		kfree(s->sg_processing);
+		kfree(s->sg_dma);
+		s->sg_pending = NULL;
+		s->sg_processing = NULL;
+		s->sg_dma = NULL;
+		s->sg_pending_size = 0;
+		s->sg_processing_size = 0;
+	}
+}
diff --git a/drivers/media/pci/ivtv/ivtv-queue.h b/drivers/media/pci/ivtv/ivtv-queue.h
new file mode 100644
index 0000000..9123383
--- /dev/null
+++ b/drivers/media/pci/ivtv/ivtv-queue.h
@@ -0,0 +1,96 @@
+/*
+    buffer queues.
+    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
+    Copyright (C) 2004  Chris Kennedy <c@groovy.org>
+    Copyright (C) 2005-2007  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef IVTV_QUEUE_H
+#define IVTV_QUEUE_H
+
+#define IVTV_DMA_UNMAPPED	((u32) -1)
+#define SLICED_VBI_PIO 0
+
+/* ivtv_buffer utility functions */
+
+static inline int ivtv_might_use_pio(struct ivtv_stream *s)
+{
+	return s->dma == PCI_DMA_NONE || (SLICED_VBI_PIO && s->type == IVTV_ENC_STREAM_TYPE_VBI);
+}
+
+static inline int ivtv_use_pio(struct ivtv_stream *s)
+{
+	struct ivtv *itv = s->itv;
+
+	return s->dma == PCI_DMA_NONE ||
+	    (SLICED_VBI_PIO && s->type == IVTV_ENC_STREAM_TYPE_VBI && itv->vbi.sliced_in->service_set);
+}
+
+static inline int ivtv_might_use_dma(struct ivtv_stream *s)
+{
+	return s->dma != PCI_DMA_NONE;
+}
+
+static inline int ivtv_use_dma(struct ivtv_stream *s)
+{
+	return !ivtv_use_pio(s);
+}
+
+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->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->pdev, buf->dma_handle,
+				s->buf_size + 256, s->dma);
+}
+
+int ivtv_buf_copy_from_user(struct ivtv_stream *s, struct ivtv_buffer *buf, const char __user *src, int copybytes);
+void ivtv_buf_swap(struct ivtv_buffer *buf);
+
+/* ivtv_queue utility functions */
+void ivtv_queue_init(struct ivtv_queue *q);
+void ivtv_enqueue(struct ivtv_stream *s, struct ivtv_buffer *buf, struct ivtv_queue *q);
+struct ivtv_buffer *ivtv_dequeue(struct ivtv_stream *s, struct ivtv_queue *q);
+int ivtv_queue_move(struct ivtv_stream *s, struct ivtv_queue *from, struct ivtv_queue *steal,
+		    struct ivtv_queue *to, int needed_bytes);
+void ivtv_flush_queues(struct ivtv_stream *s);
+
+/* ivtv_stream utility functions */
+int ivtv_stream_alloc(struct ivtv_stream *s);
+void ivtv_stream_free(struct ivtv_stream *s);
+
+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->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->pdev, s->sg_handle,
+			sizeof(struct ivtv_sg_element), PCI_DMA_TODEVICE);
+}
+
+#endif
diff --git a/drivers/media/pci/ivtv/ivtv-routing.c b/drivers/media/pci/ivtv/ivtv-routing.c
new file mode 100644
index 0000000..8898c56
--- /dev/null
+++ b/drivers/media/pci/ivtv/ivtv-routing.c
@@ -0,0 +1,119 @@
+/*
+    Audio/video-routing-related ivtv functions.
+    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
+    Copyright (C) 2005-2007  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "ivtv-driver.h"
+#include "ivtv-i2c.h"
+#include "ivtv-cards.h"
+#include "ivtv-gpio.h"
+#include "ivtv-routing.h"
+
+#include <media/msp3400.h>
+#include <media/m52790.h>
+#include <media/upd64031a.h>
+#include <media/upd64083.h>
+
+/* Selects the audio input and output according to the current
+   settings. */
+void ivtv_audio_set_io(struct ivtv *itv)
+{
+	const struct ivtv_card_audio_input *in;
+	u32 input, output = 0;
+
+	/* Determine which input to use */
+	if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags))
+		in = &itv->card->radio_input;
+	else
+		in = &itv->card->audio_inputs[itv->audio_input];
+
+	/* handle muxer chips */
+	input = in->muxer_input;
+	if (itv->card->hw_muxer & IVTV_HW_M52790)
+		output = M52790_OUT_STEREO;
+	v4l2_subdev_call(itv->sd_muxer, audio, s_routing,
+			input, output, 0);
+
+	input = in->audio_input;
+	output = 0;
+	if (itv->card->hw_audio & IVTV_HW_MSP34XX)
+		output = MSP_OUTPUT(MSP_SC_IN_DSP_SCART1);
+	ivtv_call_hw(itv, itv->card->hw_audio, audio, s_routing,
+			input, output, 0);
+}
+
+/* Selects the video input and output according to the current
+   settings. */
+void ivtv_video_set_io(struct ivtv *itv)
+{
+	int inp = itv->active_input;
+	u32 input;
+	u32 type;
+
+	v4l2_subdev_call(itv->sd_video, video, s_routing,
+		itv->card->video_inputs[inp].video_input, 0, 0);
+
+	type = itv->card->video_inputs[inp].video_type;
+
+	if (type == IVTV_CARD_INPUT_VID_TUNER) {
+		input = 0;  /* Tuner */
+	} else if (type < IVTV_CARD_INPUT_COMPOSITE1) {
+		input = 2;  /* S-Video */
+	} else {
+		input = 1;  /* Composite */
+	}
+
+	if (itv->card->hw_video & IVTV_HW_GPIO)
+		ivtv_call_hw(itv, IVTV_HW_GPIO, video, s_routing,
+				input, 0, 0);
+
+	if (itv->card->hw_video & IVTV_HW_UPD64031A) {
+		if (type == IVTV_CARD_INPUT_VID_TUNER ||
+		    type >= IVTV_CARD_INPUT_COMPOSITE1) {
+			/* Composite: GR on, connect to 3DYCS */
+			input = UPD64031A_GR_ON | UPD64031A_3DYCS_COMPOSITE;
+		} else {
+			/* S-Video: GR bypassed, turn it off */
+			input = UPD64031A_GR_OFF | UPD64031A_3DYCS_DISABLE;
+		}
+		input |= itv->card->gr_config;
+
+		ivtv_call_hw(itv, IVTV_HW_UPD64031A, video, s_routing,
+				input, 0, 0);
+	}
+
+	if (itv->card->hw_video & IVTV_HW_UPD6408X) {
+		input = UPD64083_YCS_MODE;
+		if (type > IVTV_CARD_INPUT_VID_TUNER &&
+		    type < IVTV_CARD_INPUT_COMPOSITE1) {
+			/* S-Video uses YCNR mode and internal Y-ADC, the
+			   upd64031a is not used. */
+			input |= UPD64083_YCNR_MODE;
+		}
+		else if (itv->card->hw_video & IVTV_HW_UPD64031A) {
+			/* Use upd64031a output for tuner and
+			   composite(CX23416GYC only) inputs */
+			if (type == IVTV_CARD_INPUT_VID_TUNER ||
+			    itv->card->type == IVTV_CARD_CX23416GYC) {
+				input |= UPD64083_EXT_Y_ADC;
+			}
+		}
+		ivtv_call_hw(itv, IVTV_HW_UPD6408X, video, s_routing,
+				input, 0, 0);
+	}
+}
diff --git a/drivers/media/pci/ivtv/ivtv-routing.h b/drivers/media/pci/ivtv/ivtv-routing.h
new file mode 100644
index 0000000..c72a973
--- /dev/null
+++ b/drivers/media/pci/ivtv/ivtv-routing.h
@@ -0,0 +1,27 @@
+/*
+    Audio/video-routing-related ivtv functions.
+    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
+    Copyright (C) 2005-2007  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef IVTV_ROUTING_H
+#define IVTV_ROUTING_H
+
+void ivtv_audio_set_io(struct ivtv *itv);
+void ivtv_video_set_io(struct ivtv *itv);
+
+#endif
diff --git a/drivers/media/pci/ivtv/ivtv-streams.c b/drivers/media/pci/ivtv/ivtv-streams.c
new file mode 100644
index 0000000..ea61352
--- /dev/null
+++ b/drivers/media/pci/ivtv/ivtv-streams.c
@@ -0,0 +1,1016 @@
+/*
+    init/start/stop/exit stream functions
+    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
+    Copyright (C) 2004  Chris Kennedy <c@groovy.org>
+    Copyright (C) 2005-2007  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/* License: GPL
+ * Author: Kevin Thayer <nufan_wfk at yahoo dot com>
+ *
+ * This file will hold API related functions, both internal (firmware api)
+ * and external (v4l2, etc)
+ *
+ * -----
+ * MPG600/MPG160 support by  T.Adachi <tadachi@tadachi-net.com>
+ *                      and Takeru KOMORIYA<komoriya@paken.org>
+ *
+ * AVerMedia M179 GPIO info by Chris Pinkham <cpinkham@bc2va.org>
+ *                using information provided by Jiun-Kuei Jung @ AVerMedia.
+ */
+
+#include "ivtv-driver.h"
+#include "ivtv-fileops.h"
+#include "ivtv-queue.h"
+#include "ivtv-mailbox.h"
+#include "ivtv-ioctl.h"
+#include "ivtv-irq.h"
+#include "ivtv-yuv.h"
+#include "ivtv-cards.h"
+#include "ivtv-streams.h"
+#include "ivtv-firmware.h"
+#include <media/v4l2-event.h>
+
+static const struct v4l2_file_operations ivtv_v4l2_enc_fops = {
+	.owner = THIS_MODULE,
+	.read = ivtv_v4l2_read,
+	.write = ivtv_v4l2_write,
+	.open = ivtv_v4l2_open,
+	.unlocked_ioctl = video_ioctl2,
+	.release = ivtv_v4l2_close,
+	.poll = ivtv_v4l2_enc_poll,
+};
+
+static const struct v4l2_file_operations ivtv_v4l2_dec_fops = {
+	.owner = THIS_MODULE,
+	.read = ivtv_v4l2_read,
+	.write = ivtv_v4l2_write,
+	.open = ivtv_v4l2_open,
+	.unlocked_ioctl = video_ioctl2,
+	.release = ivtv_v4l2_close,
+	.poll = ivtv_v4l2_dec_poll,
+};
+
+#define IVTV_V4L2_DEC_MPG_OFFSET  16	/* offset from 0 to register decoder mpg v4l2 minors on */
+#define IVTV_V4L2_ENC_PCM_OFFSET  24	/* offset from 0 to register pcm v4l2 minors on */
+#define IVTV_V4L2_ENC_YUV_OFFSET  32	/* offset from 0 to register yuv v4l2 minors on */
+#define IVTV_V4L2_DEC_YUV_OFFSET  48	/* offset from 0 to register decoder yuv v4l2 minors on */
+#define IVTV_V4L2_DEC_VBI_OFFSET   8	/* offset from 0 to register decoder vbi input v4l2 minors on */
+#define IVTV_V4L2_DEC_VOUT_OFFSET 16	/* offset from 0 to register vbi output v4l2 minors on */
+
+static struct {
+	const char *name;
+	int vfl_type;
+	int num_offset;
+	int dma, pio;
+	enum v4l2_buf_type buf_type;
+	u32 v4l2_caps;
+	const struct v4l2_file_operations *fops;
+} ivtv_stream_info[] = {
+	{	/* IVTV_ENC_STREAM_TYPE_MPG */
+		"encoder MPG",
+		VFL_TYPE_GRABBER, 0,
+		PCI_DMA_FROMDEVICE, 0, V4L2_BUF_TYPE_VIDEO_CAPTURE,
+		V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER |
+			V4L2_CAP_AUDIO | V4L2_CAP_READWRITE,
+		&ivtv_v4l2_enc_fops
+	},
+	{	/* IVTV_ENC_STREAM_TYPE_YUV */
+		"encoder YUV",
+		VFL_TYPE_GRABBER, IVTV_V4L2_ENC_YUV_OFFSET,
+		PCI_DMA_FROMDEVICE, 0, V4L2_BUF_TYPE_VIDEO_CAPTURE,
+		V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER |
+			V4L2_CAP_AUDIO | V4L2_CAP_READWRITE,
+		&ivtv_v4l2_enc_fops
+	},
+	{	/* IVTV_ENC_STREAM_TYPE_VBI */
+		"encoder VBI",
+		VFL_TYPE_VBI, 0,
+		PCI_DMA_FROMDEVICE, 0, V4L2_BUF_TYPE_VBI_CAPTURE,
+		V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_CAPTURE | V4L2_CAP_TUNER |
+			V4L2_CAP_AUDIO | V4L2_CAP_READWRITE,
+		&ivtv_v4l2_enc_fops
+	},
+	{	/* IVTV_ENC_STREAM_TYPE_PCM */
+		"encoder PCM",
+		VFL_TYPE_GRABBER, IVTV_V4L2_ENC_PCM_OFFSET,
+		PCI_DMA_FROMDEVICE, 0, V4L2_BUF_TYPE_PRIVATE,
+		V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE,
+		&ivtv_v4l2_enc_fops
+	},
+	{	/* IVTV_ENC_STREAM_TYPE_RAD */
+		"encoder radio",
+		VFL_TYPE_RADIO, 0,
+		PCI_DMA_NONE, 1, V4L2_BUF_TYPE_PRIVATE,
+		V4L2_CAP_RADIO | V4L2_CAP_TUNER,
+		&ivtv_v4l2_enc_fops
+	},
+	{	/* IVTV_DEC_STREAM_TYPE_MPG */
+		"decoder MPG",
+		VFL_TYPE_GRABBER, IVTV_V4L2_DEC_MPG_OFFSET,
+		PCI_DMA_TODEVICE, 0, V4L2_BUF_TYPE_VIDEO_OUTPUT,
+		V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE,
+		&ivtv_v4l2_dec_fops
+	},
+	{	/* IVTV_DEC_STREAM_TYPE_VBI */
+		"decoder VBI",
+		VFL_TYPE_VBI, IVTV_V4L2_DEC_VBI_OFFSET,
+		PCI_DMA_NONE, 1, V4L2_BUF_TYPE_VBI_CAPTURE,
+		V4L2_CAP_SLICED_VBI_CAPTURE | V4L2_CAP_READWRITE,
+		&ivtv_v4l2_enc_fops
+	},
+	{	/* IVTV_DEC_STREAM_TYPE_VOUT */
+		"decoder VOUT",
+		VFL_TYPE_VBI, IVTV_V4L2_DEC_VOUT_OFFSET,
+		PCI_DMA_NONE, 1, V4L2_BUF_TYPE_VBI_OUTPUT,
+		V4L2_CAP_SLICED_VBI_OUTPUT | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE,
+		&ivtv_v4l2_dec_fops
+	},
+	{	/* IVTV_DEC_STREAM_TYPE_YUV */
+		"decoder YUV",
+		VFL_TYPE_GRABBER, IVTV_V4L2_DEC_YUV_OFFSET,
+		PCI_DMA_TODEVICE, 0, V4L2_BUF_TYPE_VIDEO_OUTPUT,
+		V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE,
+		&ivtv_v4l2_dec_fops
+	}
+};
+
+static void ivtv_stream_init(struct ivtv *itv, int type)
+{
+	struct ivtv_stream *s = &itv->streams[type];
+	struct video_device *vdev = s->vdev;
+
+	/* we need to keep vdev, so restore it afterwards */
+	memset(s, 0, sizeof(*s));
+	s->vdev = vdev;
+
+	/* initialize ivtv_stream fields */
+	s->itv = itv;
+	s->type = type;
+	s->name = ivtv_stream_info[type].name;
+	s->caps = ivtv_stream_info[type].v4l2_caps;
+
+	if (ivtv_stream_info[type].pio)
+		s->dma = PCI_DMA_NONE;
+	else
+		s->dma = ivtv_stream_info[type].dma;
+	s->buf_size = itv->stream_buf_size[type];
+	if (s->buf_size)
+		s->buffers = (itv->options.kilobytes[type] * 1024 + s->buf_size - 1) / s->buf_size;
+	spin_lock_init(&s->qlock);
+	init_waitqueue_head(&s->waitq);
+	s->sg_handle = IVTV_DMA_UNMAPPED;
+	ivtv_queue_init(&s->q_free);
+	ivtv_queue_init(&s->q_full);
+	ivtv_queue_init(&s->q_dma);
+	ivtv_queue_init(&s->q_predma);
+	ivtv_queue_init(&s->q_io);
+}
+
+static int ivtv_prep_dev(struct ivtv *itv, int type)
+{
+	struct ivtv_stream *s = &itv->streams[type];
+	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 vdev == NULL, then
+	   this stream is not in use. In that case no other fields but these
+	   four can be used. */
+	s->vdev = NULL;
+	s->itv = itv;
+	s->type = type;
+	s->name = ivtv_stream_info[type].name;
+
+	/* Check whether the radio is supported */
+	if (type == IVTV_ENC_STREAM_TYPE_RAD && !(itv->v4l2_cap & V4L2_CAP_RADIO))
+		return 0;
+	if (type >= IVTV_DEC_STREAM_TYPE_MPG && !(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
+		return 0;
+
+	/* User explicitly selected 0 buffers for these streams, so don't
+	   create them. */
+	if (ivtv_stream_info[type].dma != PCI_DMA_NONE &&
+	    itv->options.kilobytes[type] == 0) {
+		IVTV_INFO("Disabled %s device\n", ivtv_stream_info[type].name);
+		return 0;
+	}
+
+	ivtv_stream_init(itv, type);
+
+	/* allocate and initialize the v4l2 video device structure */
+	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->vdev->name, sizeof(s->vdev->name), "%s %s",
+			itv->v4l2_dev.name, s->name);
+
+	s->vdev->num = num;
+	s->vdev->v4l2_dev = &itv->v4l2_dev;
+	s->vdev->fops = ivtv_stream_info[type].fops;
+	s->vdev->ctrl_handler = itv->v4l2_dev.ctrl_handler;
+	s->vdev->release = video_device_release;
+	s->vdev->tvnorms = V4L2_STD_ALL;
+	s->vdev->lock = &itv->serialize_lock;
+	set_bit(V4L2_FL_USE_FH_PRIO, &s->vdev->flags);
+	ivtv_set_funcs(s->vdev);
+	return 0;
+}
+
+/* Initialize v4l2 variables and prepare v4l2 devices */
+int ivtv_streams_setup(struct ivtv *itv)
+{
+	int type;
+
+	/* Setup V4L2 Devices */
+	for (type = 0; type < IVTV_MAX_STREAMS; type++) {
+		/* Prepare device */
+		if (ivtv_prep_dev(itv, type))
+			break;
+
+		if (itv->streams[type].vdev == NULL)
+			continue;
+
+		/* Allocate Stream */
+		if (ivtv_stream_alloc(&itv->streams[type]))
+			break;
+	}
+	if (type == IVTV_MAX_STREAMS)
+		return 0;
+
+	/* One or more streams could not be initialized. Clean 'em all up. */
+	ivtv_streams_cleanup(itv, 0);
+	return -ENOMEM;
+}
+
+static int ivtv_reg_dev(struct ivtv *itv, int type)
+{
+	struct ivtv_stream *s = &itv->streams[type];
+	int vfl_type = ivtv_stream_info[type].vfl_type;
+	const char *name;
+	int num;
+
+	if (s->vdev == NULL)
+		return 0;
+
+	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->vdev)
+			num = s_mpg->vdev->num + ivtv_stream_info[type].num_offset;
+	}
+	video_set_drvdata(s->vdev, s);
+
+	/* Register device. First try the desired minor, then any free one. */
+	if (video_register_device_no_warn(s->vdev, vfl_type, num)) {
+		IVTV_ERR("Couldn't register v4l2 device for %s (device node number %d)\n",
+				s->name, num);
+		video_device_release(s->vdev);
+		s->vdev = NULL;
+		return -ENOMEM;
+	}
+	name = video_device_node_name(s->vdev);
+
+	switch (vfl_type) {
+	case VFL_TYPE_GRABBER:
+		IVTV_INFO("Registered device %s for %s (%d kB)\n",
+			name, s->name, itv->options.kilobytes[type]);
+		break;
+	case VFL_TYPE_RADIO:
+		IVTV_INFO("Registered device %s for %s\n",
+			name, s->name);
+		break;
+	case VFL_TYPE_VBI:
+		if (itv->options.kilobytes[type])
+			IVTV_INFO("Registered device %s for %s (%d kB)\n",
+				name, s->name, itv->options.kilobytes[type]);
+		else
+			IVTV_INFO("Registered device %s for %s\n",
+				name, s->name);
+		break;
+	}
+	return 0;
+}
+
+/* Register v4l2 devices */
+int ivtv_streams_register(struct ivtv *itv)
+{
+	int type;
+	int err = 0;
+
+	/* Register V4L2 devices */
+	for (type = 0; type < IVTV_MAX_STREAMS; type++)
+		err |= ivtv_reg_dev(itv, type);
+
+	if (err == 0)
+		return 0;
+
+	/* One or more streams could not be initialized. Clean 'em all up. */
+	ivtv_streams_cleanup(itv, 1);
+	return -ENOMEM;
+}
+
+/* Unregister v4l2 devices */
+void ivtv_streams_cleanup(struct ivtv *itv, int unregister)
+{
+	int type;
+
+	/* Teardown all streams */
+	for (type = 0; type < IVTV_MAX_STREAMS; type++) {
+		struct video_device *vdev = itv->streams[type].vdev;
+
+		itv->streams[type].vdev = NULL;
+		if (vdev == NULL)
+			continue;
+
+		ivtv_stream_free(&itv->streams[type]);
+		/* Unregister or release device */
+		if (unregister)
+			video_unregister_device(vdev);
+		else
+			video_device_release(vdev);
+	}
+}
+
+static void ivtv_vbi_setup(struct ivtv *itv)
+{
+	int raw = ivtv_raw_vbi(itv);
+	u32 data[CX2341X_MBOX_MAX_DATA];
+	int lines;
+	int i;
+
+	/* Reset VBI */
+	ivtv_vapi(itv, CX2341X_ENC_SET_VBI_LINE, 5, 0xffff , 0, 0, 0, 0);
+
+	/* setup VBI registers */
+	if (raw)
+		v4l2_subdev_call(itv->sd_video, vbi, s_raw_fmt, &itv->vbi.in.fmt.vbi);
+	else
+		v4l2_subdev_call(itv->sd_video, vbi, s_sliced_fmt, &itv->vbi.in.fmt.sliced);
+
+	/* determine number of lines and total number of VBI bytes.
+	   A raw line takes 1443 bytes: 2 * 720 + 4 byte frame header - 1
+	   The '- 1' byte is probably an unused U or V byte. Or something...
+	   A sliced line takes 51 bytes: 4 byte frame header, 4 byte internal
+	   header, 42 data bytes + checksum (to be confirmed) */
+	if (raw) {
+		lines = itv->vbi.count * 2;
+	} else {
+		lines = itv->is_60hz ? 24 : 38;
+		if (itv->is_60hz && (itv->hw_flags & IVTV_HW_CX25840))
+			lines += 2;
+	}
+
+	itv->vbi.enc_size = lines * (raw ? itv->vbi.raw_size : itv->vbi.sliced_size);
+
+	/* Note: sliced vs raw flag doesn't seem to have any effect
+	   TODO: check mode (0x02) value with older ivtv versions. */
+	data[0] = raw | 0x02 | (0xbd << 8);
+
+	/* Every X number of frames a VBI interrupt arrives (frames as in 25 or 30 fps) */
+	data[1] = 1;
+	/* The VBI frames are stored in a ringbuffer with this size (with a VBI frame as unit) */
+	data[2] = raw ? 4 : 4 * (itv->vbi.raw_size / itv->vbi.enc_size);
+	/* The start/stop codes determine which VBI lines end up in the raw VBI data area.
+	   The codes are from table 24 in the saa7115 datasheet. Each raw/sliced/video line
+	   is framed with codes FF0000XX where XX is the SAV/EAV (Start/End of Active Video)
+	   code. These values for raw VBI are obtained from a driver disassembly. The sliced
+	   start/stop codes was deduced from this, but they do not appear in the driver.
+	   Other code pairs that I found are: 0x250E6249/0x13545454 and 0x25256262/0x38137F54.
+	   However, I have no idea what these values are for. */
+	if (itv->hw_flags & IVTV_HW_CX25840) {
+		/* Setup VBI for the cx25840 digitizer */
+		if (raw) {
+			data[3] = 0x20602060;
+			data[4] = 0x30703070;
+		} else {
+			data[3] = 0xB0F0B0F0;
+			data[4] = 0xA0E0A0E0;
+		}
+		/* Lines per frame */
+		data[5] = lines;
+		/* bytes per line */
+		data[6] = (raw ? itv->vbi.raw_size : itv->vbi.sliced_size);
+	} else {
+		/* Setup VBI for the saa7115 digitizer */
+		if (raw) {
+			data[3] = 0x25256262;
+			data[4] = 0x387F7F7F;
+		} else {
+			data[3] = 0xABABECEC;
+			data[4] = 0xB6F1F1F1;
+		}
+		/* Lines per frame */
+		data[5] = lines;
+		/* bytes per line */
+		data[6] = itv->vbi.enc_size / lines;
+	}
+
+	IVTV_DEBUG_INFO(
+		"Setup VBI API header 0x%08x pkts %d buffs %d ln %d sz %d\n",
+			data[0], data[1], data[2], data[5], data[6]);
+
+	ivtv_api(itv, CX2341X_ENC_SET_VBI_CONFIG, 7, data);
+
+	/* returns the VBI encoder memory area. */
+	itv->vbi.enc_start = data[2];
+	itv->vbi.fpi = data[0];
+	if (!itv->vbi.fpi)
+		itv->vbi.fpi = 1;
+
+	IVTV_DEBUG_INFO("Setup VBI start 0x%08x frames %d fpi %d\n",
+		itv->vbi.enc_start, data[1], itv->vbi.fpi);
+
+	/* select VBI lines.
+	   Note that the sliced argument seems to have no effect. */
+	for (i = 2; i <= 24; i++) {
+		int valid;
+
+		if (itv->is_60hz) {
+			valid = i >= 10 && i < 22;
+		} else {
+			valid = i >= 6 && i < 24;
+		}
+		ivtv_vapi(itv, CX2341X_ENC_SET_VBI_LINE, 5, i - 1,
+				valid, 0 , 0, 0);
+		ivtv_vapi(itv, CX2341X_ENC_SET_VBI_LINE, 5, (i - 1) | 0x80000000,
+				valid, 0, 0, 0);
+	}
+
+	/* Remaining VBI questions:
+	   - Is it possible to select particular VBI lines only for inclusion in the MPEG
+	   stream? Currently you can only get the first X lines.
+	   - Is mixed raw and sliced VBI possible?
+	   - What's the meaning of the raw/sliced flag?
+	   - What's the meaning of params 2, 3 & 4 of the Select VBI command? */
+}
+
+int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s)
+{
+	u32 data[CX2341X_MBOX_MAX_DATA];
+	struct ivtv *itv = s->itv;
+	int captype = 0, subtype = 0;
+	int enable_passthrough = 0;
+
+	if (s->vdev == NULL)
+		return -EINVAL;
+
+	IVTV_DEBUG_INFO("Start encoder stream %s\n", s->name);
+
+	switch (s->type) {
+	case IVTV_ENC_STREAM_TYPE_MPG:
+		captype = 0;
+		subtype = 3;
+
+		/* Stop Passthrough */
+		if (itv->output_mode == OUT_PASSTHROUGH) {
+			ivtv_passthrough_mode(itv, 0);
+			enable_passthrough = 1;
+		}
+		itv->mpg_data_received = itv->vbi_data_inserted = 0;
+		itv->dualwatch_jiffies = jiffies;
+		itv->dualwatch_stereo_mode = v4l2_ctrl_g_ctrl(itv->cxhdl.audio_mode);
+		itv->search_pack_header = 0;
+		break;
+
+	case IVTV_ENC_STREAM_TYPE_YUV:
+		if (itv->output_mode == OUT_PASSTHROUGH) {
+			captype = 2;
+			subtype = 11;	/* video+audio+decoder */
+			break;
+		}
+		captype = 1;
+		subtype = 1;
+		break;
+	case IVTV_ENC_STREAM_TYPE_PCM:
+		captype = 1;
+		subtype = 2;
+		break;
+	case IVTV_ENC_STREAM_TYPE_VBI:
+		captype = 1;
+		subtype = 4;
+
+		itv->vbi.frame = 0;
+		itv->vbi.inserted_frame = 0;
+		memset(itv->vbi.sliced_mpeg_size,
+			0, sizeof(itv->vbi.sliced_mpeg_size));
+		break;
+	default:
+		return -EINVAL;
+	}
+	s->subtype = subtype;
+	s->buffers_stolen = 0;
+
+	/* Clear Streamoff flags in case left from last capture */
+	clear_bit(IVTV_F_S_STREAMOFF, &s->s_flags);
+
+	if (atomic_read(&itv->capturing) == 0) {
+		int digitizer;
+
+		/* Always use frame based mode. Experiments have demonstrated that byte
+		   stream based mode results in dropped frames and corruption. Not often,
+		   but occasionally. Many thanks go to Leonard Orb who spent a lot of
+		   effort and time trying to trace the cause of the drop outs. */
+		/* 1 frame per DMA */
+		/*ivtv_vapi(itv, CX2341X_ENC_SET_DMA_BLOCK_SIZE, 2, 128, 0); */
+		ivtv_vapi(itv, CX2341X_ENC_SET_DMA_BLOCK_SIZE, 2, 1, 1);
+
+		/* Stuff from Windows, we don't know what it is */
+		ivtv_vapi(itv, CX2341X_ENC_SET_VERT_CROP_LINE, 1, 0);
+		/* According to the docs, this should be correct. However, this is
+		   untested. I don't dare enable this without having tested it.
+		   Only very few old cards actually have this hardware combination.
+		ivtv_vapi(itv, CX2341X_ENC_SET_VERT_CROP_LINE, 1,
+			((itv->hw_flags & IVTV_HW_SAA7114) && itv->is_60hz) ? 10001 : 0);
+		*/
+		ivtv_vapi(itv, CX2341X_ENC_MISC, 2, 3, !itv->has_cx23415);
+		ivtv_vapi(itv, CX2341X_ENC_MISC, 2, 8, 0);
+		ivtv_vapi(itv, CX2341X_ENC_MISC, 2, 4, 1);
+		ivtv_vapi(itv, CX2341X_ENC_MISC, 1, 12);
+
+		/* assign placeholder */
+		ivtv_vapi(itv, CX2341X_ENC_SET_PLACEHOLDER, 12,
+			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+
+		if (itv->card->hw_all & (IVTV_HW_SAA7115 | IVTV_HW_SAA717X))
+		    digitizer = 0xF1;
+		else if (itv->card->hw_all & IVTV_HW_SAA7114)
+		    digitizer = 0xEF;
+		else /* cx25840 */
+		    digitizer = 0x140;
+
+		ivtv_vapi(itv, CX2341X_ENC_SET_NUM_VSYNC_LINES, 2, digitizer, digitizer);
+
+		/* Setup VBI */
+		if (itv->v4l2_cap & V4L2_CAP_VBI_CAPTURE) {
+			ivtv_vbi_setup(itv);
+		}
+
+		/* assign program index info. Mask 7: select I/P/B, Num_req: 400 max */
+		ivtv_vapi_result(itv, data, CX2341X_ENC_SET_PGM_INDEX_INFO, 2, 7, 400);
+		itv->pgm_info_offset = data[0];
+		itv->pgm_info_num = data[1];
+		itv->pgm_info_write_idx = 0;
+		itv->pgm_info_read_idx = 0;
+
+		IVTV_DEBUG_INFO("PGM Index at 0x%08x with %d elements\n",
+				itv->pgm_info_offset, itv->pgm_info_num);
+
+		/* Setup API for Stream */
+		cx2341x_handler_setup(&itv->cxhdl);
+
+		/* mute if capturing radio */
+		if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags))
+			ivtv_vapi(itv, CX2341X_ENC_MUTE_VIDEO, 1,
+				1 | (v4l2_ctrl_g_ctrl(itv->cxhdl.video_mute_yuv) << 8));
+	}
+
+	/* Vsync Setup */
+	if (itv->has_cx23415 && !test_and_set_bit(IVTV_F_I_DIG_RST, &itv->i_flags)) {
+		/* event notification (on) */
+		ivtv_vapi(itv, CX2341X_ENC_SET_EVENT_NOTIFICATION, 4, 0, 1, IVTV_IRQ_ENC_VIM_RST, -1);
+		ivtv_clear_irq_mask(itv, IVTV_IRQ_ENC_VIM_RST);
+	}
+
+	if (atomic_read(&itv->capturing) == 0) {
+		/* Clear all Pending Interrupts */
+		ivtv_set_irq_mask(itv, IVTV_IRQ_MASK_CAPTURE);
+
+		clear_bit(IVTV_F_I_EOS, &itv->i_flags);
+
+		cx2341x_handler_set_busy(&itv->cxhdl, 1);
+
+		/* Initialize Digitizer for Capture */
+		/* Avoid tinny audio problem - ensure audio clocks are going */
+		v4l2_subdev_call(itv->sd_audio, audio, s_stream, 1);
+		/* Avoid unpredictable PCI bus hang - disable video clocks */
+		v4l2_subdev_call(itv->sd_video, video, s_stream, 0);
+		ivtv_msleep_timeout(300, 0);
+		ivtv_vapi(itv, CX2341X_ENC_INITIALIZE_INPUT, 0);
+		v4l2_subdev_call(itv->sd_video, video, s_stream, 1);
+	}
+
+	/* begin_capture */
+	if (ivtv_vapi(itv, CX2341X_ENC_START_CAPTURE, 2, captype, subtype))
+	{
+		IVTV_DEBUG_WARN( "Error starting capture!\n");
+		return -EINVAL;
+	}
+
+	/* Start Passthrough */
+	if (enable_passthrough) {
+		ivtv_passthrough_mode(itv, 1);
+	}
+
+	if (s->type == IVTV_ENC_STREAM_TYPE_VBI)
+		ivtv_clear_irq_mask(itv, IVTV_IRQ_ENC_VBI_CAP);
+	else
+		ivtv_clear_irq_mask(itv, IVTV_IRQ_MASK_CAPTURE);
+
+	/* you're live! sit back and await interrupts :) */
+	atomic_inc(&itv->capturing);
+	return 0;
+}
+EXPORT_SYMBOL(ivtv_start_v4l2_encode_stream);
+
+static int ivtv_setup_v4l2_decode_stream(struct ivtv_stream *s)
+{
+	u32 data[CX2341X_MBOX_MAX_DATA];
+	struct ivtv *itv = s->itv;
+	int datatype;
+	u16 width;
+	u16 height;
+
+	if (s->vdev == NULL)
+		return -EINVAL;
+
+	IVTV_DEBUG_INFO("Setting some initial decoder settings\n");
+
+	width = itv->cxhdl.width;
+	height = itv->cxhdl.height;
+
+	/* set audio mode to left/stereo  for dual/stereo mode. */
+	ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode);
+
+	/* set number of internal decoder buffers */
+	ivtv_vapi(itv, CX2341X_DEC_SET_DISPLAY_BUFFERS, 1, 0);
+
+	/* prebuffering */
+	ivtv_vapi(itv, CX2341X_DEC_SET_PREBUFFERING, 1, 1);
+
+	/* extract from user packets */
+	ivtv_vapi_result(itv, data, CX2341X_DEC_EXTRACT_VBI, 1, 1);
+	itv->vbi.dec_start = data[0];
+
+	IVTV_DEBUG_INFO("Decoder VBI RE-Insert start 0x%08x size 0x%08x\n",
+		itv->vbi.dec_start, data[1]);
+
+	/* set decoder source settings */
+	/* Data type: 0 = mpeg from host,
+	   1 = yuv from encoder,
+	   2 = yuv_from_host */
+	switch (s->type) {
+	case IVTV_DEC_STREAM_TYPE_YUV:
+		if (itv->output_mode == OUT_PASSTHROUGH) {
+			datatype = 1;
+		} else {
+			/* Fake size to avoid switching video standard */
+			datatype = 2;
+			width = 720;
+			height = itv->is_out_50hz ? 576 : 480;
+		}
+		IVTV_DEBUG_INFO("Setup DEC YUV Stream data[0] = %d\n", datatype);
+		break;
+	case IVTV_DEC_STREAM_TYPE_MPG:
+	default:
+		datatype = 0;
+		break;
+	}
+	if (ivtv_vapi(itv, CX2341X_DEC_SET_DECODER_SOURCE, 4, datatype,
+			width, height, itv->cxhdl.audio_properties)) {
+		IVTV_DEBUG_WARN("Couldn't initialize decoder source\n");
+	}
+
+	/* Decoder sometimes dies here, so wait a moment */
+	ivtv_msleep_timeout(10, 0);
+
+	/* Known failure point for firmware, so check */
+	return ivtv_firmware_check(itv, "ivtv_setup_v4l2_decode_stream");
+}
+
+int ivtv_start_v4l2_decode_stream(struct ivtv_stream *s, int gop_offset)
+{
+	struct ivtv *itv = s->itv;
+	int rc;
+
+	if (s->vdev == NULL)
+		return -EINVAL;
+
+	if (test_and_set_bit(IVTV_F_S_STREAMING, &s->s_flags))
+		return 0;	/* already started */
+
+	IVTV_DEBUG_INFO("Starting decode stream %s (gop_offset %d)\n", s->name, gop_offset);
+
+	rc = ivtv_setup_v4l2_decode_stream(s);
+	if (rc < 0) {
+		clear_bit(IVTV_F_S_STREAMING, &s->s_flags);
+		return rc;
+	}
+
+	/* set dma size to 65536 bytes */
+	ivtv_vapi(itv, CX2341X_DEC_SET_DMA_BLOCK_SIZE, 1, 65536);
+
+	/* Clear Streamoff */
+	clear_bit(IVTV_F_S_STREAMOFF, &s->s_flags);
+
+	/* Zero out decoder counters */
+	writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_DMA_END].data[0]);
+	writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_DMA_END].data[1]);
+	writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_DMA_END].data[2]);
+	writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_DMA_END].data[3]);
+	writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_DMA].data[0]);
+	writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_DMA].data[1]);
+	writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_DMA].data[2]);
+	writel(0, &itv->dec_mbox.mbox[IVTV_MBOX_DMA].data[3]);
+
+	/* turn on notification of dual/stereo mode change */
+	ivtv_vapi(itv, CX2341X_DEC_SET_EVENT_NOTIFICATION, 4, 0, 1, IVTV_IRQ_DEC_AUD_MODE_CHG, -1);
+
+	/* start playback */
+	ivtv_vapi(itv, CX2341X_DEC_START_PLAYBACK, 2, gop_offset, 0);
+
+	/* Let things settle before we actually start */
+	ivtv_msleep_timeout(10, 0);
+
+	/* Clear the following Interrupt mask bits for decoding */
+	ivtv_clear_irq_mask(itv, IVTV_IRQ_MASK_DECODE);
+	IVTV_DEBUG_IRQ("IRQ Mask is now: 0x%08x\n", itv->irqmask);
+
+	/* you're live! sit back and await interrupts :) */
+	atomic_inc(&itv->decoding);
+	return 0;
+}
+
+void ivtv_stop_all_captures(struct ivtv *itv)
+{
+	int i;
+
+	for (i = IVTV_MAX_STREAMS - 1; i >= 0; i--) {
+		struct ivtv_stream *s = &itv->streams[i];
+
+		if (s->vdev == NULL)
+			continue;
+		if (test_bit(IVTV_F_S_STREAMING, &s->s_flags)) {
+			ivtv_stop_v4l2_encode_stream(s, 0);
+		}
+	}
+}
+
+int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end)
+{
+	struct ivtv *itv = s->itv;
+	DECLARE_WAITQUEUE(wait, current);
+	int cap_type;
+	int stopmode;
+
+	if (s->vdev == NULL)
+		return -EINVAL;
+
+	/* This function assumes that you are allowed to stop the capture
+	   and that we are actually capturing */
+
+	IVTV_DEBUG_INFO("Stop Capture\n");
+
+	if (s->type == IVTV_DEC_STREAM_TYPE_VOUT)
+		return 0;
+	if (atomic_read(&itv->capturing) == 0)
+		return 0;
+
+	switch (s->type) {
+	case IVTV_ENC_STREAM_TYPE_YUV:
+		cap_type = 1;
+		break;
+	case IVTV_ENC_STREAM_TYPE_PCM:
+		cap_type = 1;
+		break;
+	case IVTV_ENC_STREAM_TYPE_VBI:
+		cap_type = 1;
+		break;
+	case IVTV_ENC_STREAM_TYPE_MPG:
+	default:
+		cap_type = 0;
+		break;
+	}
+
+	/* Stop Capture Mode */
+	if (s->type == IVTV_ENC_STREAM_TYPE_MPG && gop_end) {
+		stopmode = 0;
+	} else {
+		stopmode = 1;
+	}
+
+	/* end_capture */
+	/* when: 0 =  end of GOP  1 = NOW!, type: 0 = mpeg, subtype: 3 = video+audio */
+	ivtv_vapi(itv, CX2341X_ENC_STOP_CAPTURE, 3, stopmode, cap_type, s->subtype);
+
+	if (!test_bit(IVTV_F_S_PASSTHROUGH, &s->s_flags)) {
+		if (s->type == IVTV_ENC_STREAM_TYPE_MPG && gop_end) {
+			/* only run these if we're shutting down the last cap */
+			unsigned long duration;
+			unsigned long then = jiffies;
+
+			add_wait_queue(&itv->eos_waitq, &wait);
+
+			set_current_state(TASK_INTERRUPTIBLE);
+
+			/* wait 2s for EOS interrupt */
+			while (!test_bit(IVTV_F_I_EOS, &itv->i_flags) &&
+				time_before(jiffies,
+					    then + msecs_to_jiffies(2000))) {
+				schedule_timeout(msecs_to_jiffies(10));
+			}
+
+			/* To convert jiffies to ms, we must multiply by 1000
+			 * and divide by HZ.  To avoid runtime division, we
+			 * convert this to multiplication by 1000/HZ.
+			 * Since integer division truncates, we get the best
+			 * accuracy if we do a rounding calculation of the constant.
+			 * Think of the case where HZ is 1024.
+			 */
+			duration = ((1000 + HZ / 2) / HZ) * (jiffies - then);
+
+			if (!test_bit(IVTV_F_I_EOS, &itv->i_flags)) {
+				IVTV_DEBUG_WARN("%s: EOS interrupt not received! stopping anyway.\n", s->name);
+				IVTV_DEBUG_WARN("%s: waited %lu ms.\n", s->name, duration);
+			} else {
+				IVTV_DEBUG_INFO("%s: EOS took %lu ms to occur.\n", s->name, duration);
+			}
+			set_current_state(TASK_RUNNING);
+			remove_wait_queue(&itv->eos_waitq, &wait);
+			set_bit(IVTV_F_S_STREAMOFF, &s->s_flags);
+		}
+
+		/* Handle any pending interrupts */
+		ivtv_msleep_timeout(100, 0);
+	}
+
+	atomic_dec(&itv->capturing);
+
+	/* Clear capture and no-read bits */
+	clear_bit(IVTV_F_S_STREAMING, &s->s_flags);
+
+	if (s->type == IVTV_ENC_STREAM_TYPE_VBI)
+		ivtv_set_irq_mask(itv, IVTV_IRQ_ENC_VBI_CAP);
+
+	if (atomic_read(&itv->capturing) > 0) {
+		return 0;
+	}
+
+	cx2341x_handler_set_busy(&itv->cxhdl, 0);
+
+	/* Set the following Interrupt mask bits for capture */
+	ivtv_set_irq_mask(itv, IVTV_IRQ_MASK_CAPTURE);
+	del_timer(&itv->dma_timer);
+
+	/* event notification (off) */
+	if (test_and_clear_bit(IVTV_F_I_DIG_RST, &itv->i_flags)) {
+		/* type: 0 = refresh */
+		/* on/off: 0 = off, intr: 0x10000000, mbox_id: -1: none */
+		ivtv_vapi(itv, CX2341X_ENC_SET_EVENT_NOTIFICATION, 4, 0, 0, IVTV_IRQ_ENC_VIM_RST, -1);
+		ivtv_set_irq_mask(itv, IVTV_IRQ_ENC_VIM_RST);
+	}
+
+	/* Raw-passthrough is implied on start. Make sure it's stopped so
+	   the encoder will re-initialize when next started */
+	ivtv_vapi(itv, CX2341X_ENC_STOP_CAPTURE, 3, 1, 2, 7);
+
+	wake_up(&s->waitq);
+
+	return 0;
+}
+EXPORT_SYMBOL(ivtv_stop_v4l2_encode_stream);
+
+int ivtv_stop_v4l2_decode_stream(struct ivtv_stream *s, int flags, u64 pts)
+{
+	static const struct v4l2_event ev = {
+		.type = V4L2_EVENT_EOS,
+	};
+	struct ivtv *itv = s->itv;
+
+	if (s->vdev == NULL)
+		return -EINVAL;
+
+	if (s->type != IVTV_DEC_STREAM_TYPE_YUV && s->type != IVTV_DEC_STREAM_TYPE_MPG)
+		return -EINVAL;
+
+	if (!test_bit(IVTV_F_S_STREAMING, &s->s_flags))
+		return 0;
+
+	IVTV_DEBUG_INFO("Stop Decode at %llu, flags: %x\n", (unsigned long long)pts, flags);
+
+	/* Stop Decoder */
+	if (!(flags & V4L2_DEC_CMD_STOP_IMMEDIATELY) || pts) {
+		u32 tmp = 0;
+
+		/* Wait until the decoder is no longer running */
+		if (pts) {
+			ivtv_vapi(itv, CX2341X_DEC_STOP_PLAYBACK, 3,
+				0, (u32)(pts & 0xffffffff), (u32)(pts >> 32));
+		}
+		while (1) {
+			u32 data[CX2341X_MBOX_MAX_DATA];
+			ivtv_vapi_result(itv, data, CX2341X_DEC_GET_XFER_INFO, 0);
+			if (s->q_full.buffers + s->q_dma.buffers == 0) {
+				if (tmp == data[3])
+					break;
+				tmp = data[3];
+			}
+			if (ivtv_msleep_timeout(100, 1))
+				break;
+		}
+	}
+	ivtv_vapi(itv, CX2341X_DEC_STOP_PLAYBACK, 3, flags & V4L2_DEC_CMD_STOP_TO_BLACK, 0, 0);
+
+	/* turn off notification of dual/stereo mode change */
+	ivtv_vapi(itv, CX2341X_DEC_SET_EVENT_NOTIFICATION, 4, 0, 0, IVTV_IRQ_DEC_AUD_MODE_CHG, -1);
+
+	ivtv_set_irq_mask(itv, IVTV_IRQ_MASK_DECODE);
+	del_timer(&itv->dma_timer);
+
+	clear_bit(IVTV_F_S_NEEDS_DATA, &s->s_flags);
+	clear_bit(IVTV_F_S_STREAMING, &s->s_flags);
+	ivtv_flush_queues(s);
+
+	/* decoder needs time to settle */
+	ivtv_msleep_timeout(40, 0);
+
+	/* decrement decoding */
+	atomic_dec(&itv->decoding);
+
+	set_bit(IVTV_F_I_EV_DEC_STOPPED, &itv->i_flags);
+	wake_up(&itv->event_waitq);
+	v4l2_event_queue(s->vdev, &ev);
+
+	/* wake up wait queues */
+	wake_up(&s->waitq);
+
+	return 0;
+}
+
+int ivtv_passthrough_mode(struct ivtv *itv, int enable)
+{
+	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->vdev == NULL || dec_stream->vdev == NULL)
+		return -EINVAL;
+
+	IVTV_DEBUG_INFO("ivtv ioctl: Select passthrough mode\n");
+
+	/* Prevent others from starting/stopping streams while we
+	   initiate/terminate passthrough mode */
+	if (enable) {
+		if (itv->output_mode == OUT_PASSTHROUGH) {
+			return 0;
+		}
+		if (ivtv_set_output_mode(itv, OUT_PASSTHROUGH) != OUT_PASSTHROUGH)
+			return -EBUSY;
+
+		/* Fully initialize stream, and then unflag init */
+		set_bit(IVTV_F_S_PASSTHROUGH, &dec_stream->s_flags);
+		set_bit(IVTV_F_S_STREAMING, &dec_stream->s_flags);
+
+		/* Setup YUV Decoder */
+		ivtv_setup_v4l2_decode_stream(dec_stream);
+
+		/* Start Decoder */
+		ivtv_vapi(itv, CX2341X_DEC_START_PLAYBACK, 2, 0, 1);
+		atomic_inc(&itv->decoding);
+
+		/* Setup capture if not already done */
+		if (atomic_read(&itv->capturing) == 0) {
+			cx2341x_handler_setup(&itv->cxhdl);
+			cx2341x_handler_set_busy(&itv->cxhdl, 1);
+		}
+
+		/* Start Passthrough Mode */
+		ivtv_vapi(itv, CX2341X_ENC_START_CAPTURE, 2, 2, 11);
+		atomic_inc(&itv->capturing);
+		return 0;
+	}
+
+	if (itv->output_mode != OUT_PASSTHROUGH)
+		return 0;
+
+	/* Stop Passthrough Mode */
+	ivtv_vapi(itv, CX2341X_ENC_STOP_CAPTURE, 3, 1, 2, 11);
+	ivtv_vapi(itv, CX2341X_DEC_STOP_PLAYBACK, 3, 1, 0, 0);
+
+	atomic_dec(&itv->capturing);
+	atomic_dec(&itv->decoding);
+	clear_bit(IVTV_F_S_PASSTHROUGH, &dec_stream->s_flags);
+	clear_bit(IVTV_F_S_STREAMING, &dec_stream->s_flags);
+	itv->output_mode = OUT_NONE;
+	if (atomic_read(&itv->capturing) == 0)
+		cx2341x_handler_set_busy(&itv->cxhdl, 0);
+
+	return 0;
+}
diff --git a/drivers/media/pci/ivtv/ivtv-streams.h b/drivers/media/pci/ivtv/ivtv-streams.h
new file mode 100644
index 0000000..a653a51
--- /dev/null
+++ b/drivers/media/pci/ivtv/ivtv-streams.h
@@ -0,0 +1,37 @@
+/*
+    init/start/stop/exit stream functions
+    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
+    Copyright (C) 2005-2007  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef IVTV_STREAMS_H
+#define IVTV_STREAMS_H
+
+int ivtv_streams_setup(struct ivtv *itv);
+int ivtv_streams_register(struct ivtv *itv);
+void ivtv_streams_cleanup(struct ivtv *itv, int unregister);
+
+/* Capture related */
+int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s);
+int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end);
+int ivtv_start_v4l2_decode_stream(struct ivtv_stream *s, int gop_offset);
+int ivtv_stop_v4l2_decode_stream(struct ivtv_stream *s, int flags, u64 pts);
+
+void ivtv_stop_all_captures(struct ivtv *itv);
+int ivtv_passthrough_mode(struct ivtv *itv, int enable);
+
+#endif
diff --git a/drivers/media/pci/ivtv/ivtv-udma.c b/drivers/media/pci/ivtv/ivtv-udma.c
new file mode 100644
index 0000000..7338cb2
--- /dev/null
+++ b/drivers/media/pci/ivtv/ivtv-udma.c
@@ -0,0 +1,234 @@
+/*
+    User DMA
+
+    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
+    Copyright (C) 2004  Chris Kennedy <c@groovy.org>
+    Copyright (C) 2005-2007  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "ivtv-driver.h"
+#include "ivtv-udma.h"
+
+void ivtv_udma_get_page_info(struct ivtv_dma_page_info *dma_page, unsigned long first, unsigned long size)
+{
+	dma_page->uaddr = first & PAGE_MASK;
+	dma_page->offset = first & ~PAGE_MASK;
+	dma_page->tail = 1 + ((first+size-1) & ~PAGE_MASK);
+	dma_page->first = (first & PAGE_MASK) >> PAGE_SHIFT;
+	dma_page->last = ((first+size-1) & PAGE_MASK) >> PAGE_SHIFT;
+	dma_page->page_count = dma_page->last - dma_page->first + 1;
+	if (dma_page->page_count == 1) dma_page->tail -= dma_page->offset;
+}
+
+int ivtv_udma_fill_sg_list (struct ivtv_user_dma *dma, struct ivtv_dma_page_info *dma_page, int map_offset)
+{
+	int i, offset;
+	unsigned long flags;
+
+	if (map_offset < 0)
+		return map_offset;
+
+	offset = dma_page->offset;
+
+	/* Fill SG Array with new values */
+	for (i = 0; i < dma_page->page_count; i++) {
+		unsigned int len = (i == dma_page->page_count - 1) ?
+			dma_page->tail : PAGE_SIZE - offset;
+
+		if (PageHighMem(dma->map[map_offset])) {
+			void *src;
+
+			if (dma->bouncemap[map_offset] == NULL)
+				dma->bouncemap[map_offset] = alloc_page(GFP_KERNEL);
+			if (dma->bouncemap[map_offset] == NULL)
+				return -1;
+			local_irq_save(flags);
+			src = kmap_atomic(dma->map[map_offset]) + offset;
+			memcpy(page_address(dma->bouncemap[map_offset]) + offset, src, len);
+			kunmap_atomic(src);
+			local_irq_restore(flags);
+			sg_set_page(&dma->SGlist[map_offset], dma->bouncemap[map_offset], len, offset);
+		}
+		else {
+			sg_set_page(&dma->SGlist[map_offset], dma->map[map_offset], len, offset);
+		}
+		offset = 0;
+		map_offset++;
+	}
+	return map_offset;
+}
+
+void ivtv_udma_fill_sg_array (struct ivtv_user_dma *dma, u32 buffer_offset, u32 buffer_offset_2, u32 split) {
+	int i;
+	struct scatterlist *sg;
+
+	for (i = 0, sg = dma->SGlist; i < dma->SG_length; i++, sg++) {
+		dma->SGarray[i].size = cpu_to_le32(sg_dma_len(sg));
+		dma->SGarray[i].src = cpu_to_le32(sg_dma_address(sg));
+		dma->SGarray[i].dst = cpu_to_le32(buffer_offset);
+		buffer_offset += sg_dma_len(sg);
+
+		split -= sg_dma_len(sg);
+		if (split == 0)
+			buffer_offset = buffer_offset_2;
+	}
+}
+
+/* User DMA Buffers */
+void ivtv_udma_alloc(struct ivtv *itv)
+{
+	if (itv->udma.SG_handle == 0) {
+		/* Map DMA Page Array Buffer */
+		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);
+	}
+}
+
+int ivtv_udma_setup(struct ivtv *itv, unsigned long ivtv_dest_addr,
+		       void __user *userbuf, int size_in_bytes)
+{
+	struct ivtv_dma_page_info user_dma;
+	struct ivtv_user_dma *dma = &itv->udma;
+	int i, err;
+
+	IVTV_DEBUG_DMA("ivtv_udma_setup, dst: 0x%08x\n", (unsigned int)ivtv_dest_addr);
+
+	/* Still in USE */
+	if (dma->SG_length || dma->page_count) {
+		IVTV_DEBUG_WARN("ivtv_udma_setup: SG_length %d page_count %d still full?\n",
+			   dma->SG_length, dma->page_count);
+		return -EBUSY;
+	}
+
+	ivtv_udma_get_page_info(&user_dma, (unsigned long)userbuf, size_in_bytes);
+
+	if (user_dma.page_count <= 0) {
+		IVTV_DEBUG_WARN("ivtv_udma_setup: Error %d page_count from %d bytes %d offset\n",
+			   user_dma.page_count, size_in_bytes, user_dma.offset);
+		return -EINVAL;
+	}
+
+	/* Get user pages for DMA Xfer */
+	down_read(&current->mm->mmap_sem);
+	err = get_user_pages(current, current->mm,
+			user_dma.uaddr, user_dma.page_count, 0, 1, dma->map, NULL);
+	up_read(&current->mm->mmap_sem);
+
+	if (user_dma.page_count != err) {
+		IVTV_DEBUG_WARN("failed to map user pages, returned %d instead of %d\n",
+			   err, user_dma.page_count);
+		if (err >= 0) {
+			for (i = 0; i < err; i++)
+				put_page(dma->map[i]);
+			return -EINVAL;
+		}
+		return err;
+	}
+
+	dma->page_count = user_dma.page_count;
+
+	/* Fill SG List with new values */
+	if (ivtv_udma_fill_sg_list(dma, &user_dma, 0) < 0) {
+		for (i = 0; i < dma->page_count; i++) {
+			put_page(dma->map[i]);
+		}
+		dma->page_count = 0;
+		return -ENOMEM;
+	}
+
+	/* Map SG List */
+	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);
+
+	/* Tag SG Array with Interrupt Bit */
+	dma->SGarray[dma->SG_length - 1].size |= cpu_to_le32(0x80000000);
+
+	ivtv_udma_sync_for_device(itv);
+	return dma->page_count;
+}
+
+void ivtv_udma_unmap(struct ivtv *itv)
+{
+	struct ivtv_user_dma *dma = &itv->udma;
+	int i;
+
+	IVTV_DEBUG_INFO("ivtv_unmap_user_dma\n");
+
+	/* Nothing to free */
+	if (dma->page_count == 0)
+		return;
+
+	/* Unmap Scatterlist */
+	if (dma->SG_length) {
+		pci_unmap_sg(itv->pdev, dma->SGlist, dma->page_count, PCI_DMA_TODEVICE);
+		dma->SG_length = 0;
+	}
+	/* sync DMA */
+	ivtv_udma_sync_for_cpu(itv);
+
+	/* Release User Pages */
+	for (i = 0; i < dma->page_count; i++) {
+		put_page(dma->map[i]);
+	}
+	dma->page_count = 0;
+}
+
+void ivtv_udma_free(struct ivtv *itv)
+{
+	int i;
+
+	/* Unmap SG Array */
+	if (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->pdev, itv->udma.SGlist, itv->udma.page_count, PCI_DMA_TODEVICE);
+	}
+
+	for (i = 0; i < IVTV_DMA_SG_OSD_ENT; i++) {
+		if (itv->udma.bouncemap[i])
+			__free_page(itv->udma.bouncemap[i]);
+	}
+}
+
+void ivtv_udma_start(struct ivtv *itv)
+{
+	IVTV_DEBUG_DMA("start UDMA\n");
+	write_reg(itv->udma.SG_handle, IVTV_REG_DECDMAADDR);
+	write_reg_sync(read_reg(IVTV_REG_DMAXFER) | 0x01, IVTV_REG_DMAXFER);
+	set_bit(IVTV_F_I_DMA, &itv->i_flags);
+	set_bit(IVTV_F_I_UDMA, &itv->i_flags);
+	clear_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags);
+}
+
+void ivtv_udma_prepare(struct ivtv *itv)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&itv->dma_reg_lock, flags);
+	if (!test_bit(IVTV_F_I_DMA, &itv->i_flags))
+		ivtv_udma_start(itv);
+	else
+		set_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags);
+	spin_unlock_irqrestore(&itv->dma_reg_lock, flags);
+}
diff --git a/drivers/media/pci/ivtv/ivtv-udma.h b/drivers/media/pci/ivtv/ivtv-udma.h
new file mode 100644
index 0000000..ee3c9ef
--- /dev/null
+++ b/drivers/media/pci/ivtv/ivtv-udma.h
@@ -0,0 +1,48 @@
+/*
+    Copyright (C) 2003-2004  Kevin Thayer <nufan_wfk at yahoo.com>
+    Copyright (C) 2004  Chris Kennedy <c@groovy.org>
+    Copyright (C) 2006-2007  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef IVTV_UDMA_H
+#define IVTV_UDMA_H
+
+/* User DMA functions */
+void ivtv_udma_get_page_info(struct ivtv_dma_page_info *dma_page, unsigned long first, unsigned long size);
+int ivtv_udma_fill_sg_list(struct ivtv_user_dma *dma, struct ivtv_dma_page_info *dma_page, int map_offset);
+void ivtv_udma_fill_sg_array(struct ivtv_user_dma *dma, u32 buffer_offset, u32 buffer_offset_2, u32 split);
+int ivtv_udma_setup(struct ivtv *itv, unsigned long ivtv_dest_addr,
+		       void __user *userbuf, int size_in_bytes);
+void ivtv_udma_unmap(struct ivtv *itv);
+void ivtv_udma_free(struct ivtv *itv);
+void ivtv_udma_alloc(struct ivtv *itv);
+void ivtv_udma_prepare(struct ivtv *itv);
+void ivtv_udma_start(struct ivtv *itv);
+
+static inline void ivtv_udma_sync_for_device(struct ivtv *itv)
+{
+	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(itv->pdev, itv->udma.SG_handle,
+		sizeof(itv->udma.SGarray), PCI_DMA_TODEVICE);
+}
+
+#endif
diff --git a/drivers/media/pci/ivtv/ivtv-vbi.c b/drivers/media/pci/ivtv/ivtv-vbi.c
new file mode 100644
index 0000000..293db80
--- /dev/null
+++ b/drivers/media/pci/ivtv/ivtv-vbi.c
@@ -0,0 +1,549 @@
+/*
+    Vertical Blank Interval support functions
+    Copyright (C) 2004-2007  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "ivtv-driver.h"
+#include "ivtv-i2c.h"
+#include "ivtv-ioctl.h"
+#include "ivtv-queue.h"
+#include "ivtv-cards.h"
+#include "ivtv-vbi.h"
+
+static void ivtv_set_vps(struct ivtv *itv, int enabled)
+{
+	struct v4l2_sliced_vbi_data data;
+
+	if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
+		return;
+	data.id = V4L2_SLICED_VPS;
+	data.field = 0;
+	data.line = enabled ? 16 : 0;
+	data.data[2] = itv->vbi.vps_payload.data[0];
+	data.data[8] = itv->vbi.vps_payload.data[1];
+	data.data[9] = itv->vbi.vps_payload.data[2];
+	data.data[10] = itv->vbi.vps_payload.data[3];
+	data.data[11] = itv->vbi.vps_payload.data[4];
+	ivtv_call_hw(itv, IVTV_HW_SAA7127, vbi, s_vbi_data, &data);
+}
+
+static void ivtv_set_cc(struct ivtv *itv, int mode, const struct vbi_cc *cc)
+{
+	struct v4l2_sliced_vbi_data data;
+
+	if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
+		return;
+	data.id = V4L2_SLICED_CAPTION_525;
+	data.field = 0;
+	data.line = (mode & 1) ? 21 : 0;
+	data.data[0] = cc->odd[0];
+	data.data[1] = cc->odd[1];
+	ivtv_call_hw(itv, IVTV_HW_SAA7127, vbi, s_vbi_data, &data);
+	data.field = 1;
+	data.line = (mode & 2) ? 21 : 0;
+	data.data[0] = cc->even[0];
+	data.data[1] = cc->even[1];
+	ivtv_call_hw(itv, IVTV_HW_SAA7127, vbi, s_vbi_data, &data);
+}
+
+static void ivtv_set_wss(struct ivtv *itv, int enabled, int mode)
+{
+	struct v4l2_sliced_vbi_data data;
+
+	if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
+		return;
+	/* When using a 50 Hz system, always turn on the
+	   wide screen signal with 4x3 ratio as the default.
+	   Turning this signal on and off can confuse certain
+	   TVs. As far as I can tell there is no reason not to
+	   transmit this signal. */
+	if ((itv->std_out & V4L2_STD_625_50) && !enabled) {
+		enabled = 1;
+		mode = 0x08;  /* 4x3 full format */
+	}
+	data.id = V4L2_SLICED_WSS_625;
+	data.field = 0;
+	data.line = enabled ? 23 : 0;
+	data.data[0] = mode & 0xff;
+	data.data[1] = (mode >> 8) & 0xff;
+	ivtv_call_hw(itv, IVTV_HW_SAA7127, vbi, s_vbi_data, &data);
+}
+
+static int odd_parity(u8 c)
+{
+	c ^= (c >> 4);
+	c ^= (c >> 2);
+	c ^= (c >> 1);
+
+	return c & 1;
+}
+
+static void ivtv_write_vbi_line(struct ivtv *itv,
+				const struct v4l2_sliced_vbi_data *d,
+				struct vbi_cc *cc, int *found_cc)
+{
+	struct vbi_info *vi = &itv->vbi;
+
+	if (d->id == V4L2_SLICED_CAPTION_525 && d->line == 21) {
+		if (d->field) {
+			cc->even[0] = d->data[0];
+			cc->even[1] = d->data[1];
+		} else {
+			cc->odd[0] = d->data[0];
+			cc->odd[1] = d->data[1];
+		}
+		*found_cc = 1;
+	} else if (d->id == V4L2_SLICED_VPS && d->line == 16 && d->field == 0) {
+		struct vbi_vps vps;
+
+		vps.data[0] = d->data[2];
+		vps.data[1] = d->data[8];
+		vps.data[2] = d->data[9];
+		vps.data[3] = d->data[10];
+		vps.data[4] = d->data[11];
+		if (memcmp(&vps, &vi->vps_payload, sizeof(vps))) {
+			vi->vps_payload = vps;
+			set_bit(IVTV_F_I_UPDATE_VPS, &itv->i_flags);
+		}
+	} else if (d->id == V4L2_SLICED_WSS_625 &&
+		   d->line == 23 && d->field == 0) {
+		int wss = d->data[0] | d->data[1] << 8;
+
+		if (vi->wss_payload != wss) {
+			vi->wss_payload = wss;
+			set_bit(IVTV_F_I_UPDATE_WSS, &itv->i_flags);
+		}
+	}
+}
+
+static void ivtv_write_vbi_cc_lines(struct ivtv *itv, const struct vbi_cc *cc)
+{
+	struct vbi_info *vi = &itv->vbi;
+
+	if (vi->cc_payload_idx < ARRAY_SIZE(vi->cc_payload)) {
+		memcpy(&vi->cc_payload[vi->cc_payload_idx], cc,
+		       sizeof(struct vbi_cc));
+		vi->cc_payload_idx++;
+		set_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags);
+	}
+}
+
+static void ivtv_write_vbi(struct ivtv *itv,
+			   const struct v4l2_sliced_vbi_data *sliced,
+			   size_t cnt)
+{
+	struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } };
+	int found_cc = 0;
+	size_t i;
+
+	for (i = 0; i < cnt; i++)
+		ivtv_write_vbi_line(itv, sliced + i, &cc, &found_cc);
+
+	if (found_cc)
+		ivtv_write_vbi_cc_lines(itv, &cc);
+}
+
+ssize_t
+ivtv_write_vbi_from_user(struct ivtv *itv,
+			 const struct v4l2_sliced_vbi_data __user *sliced,
+			 size_t cnt)
+{
+	struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } };
+	int found_cc = 0;
+	size_t i;
+	struct v4l2_sliced_vbi_data d;
+	ssize_t ret = cnt * sizeof(struct v4l2_sliced_vbi_data);
+
+	for (i = 0; i < cnt; i++) {
+		if (copy_from_user(&d, sliced + i,
+				   sizeof(struct v4l2_sliced_vbi_data))) {
+			ret = -EFAULT;
+			break;
+		}
+		ivtv_write_vbi_line(itv, &d, &cc, &found_cc);
+	}
+
+	if (found_cc)
+		ivtv_write_vbi_cc_lines(itv, &cc);
+
+	return ret;
+}
+
+static void copy_vbi_data(struct ivtv *itv, int lines, u32 pts_stamp)
+{
+	int line = 0;
+	int i;
+	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
+	};
+	const int sd = sizeof(mpeg_hdr_data);	/* start of vbi data */
+	int idx = itv->vbi.frame % IVTV_VBI_FRAMES;
+	u8 *dst = &itv->vbi.sliced_mpeg_data[idx][0];
+
+	for (i = 0; i < lines; i++) {
+		int f, l;
+
+		if (itv->vbi.sliced_data[i].id == 0)
+			continue;
+
+		l = itv->vbi.sliced_data[i].line - 6;
+		f = itv->vbi.sliced_data[i].field;
+		if (f)
+			l += 18;
+		if (l < 32)
+			linemask[0] |= (1 << l);
+		else
+			linemask[1] |= (1 << (l - 32));
+		dst[sd + 12 + line * 43] =
+			ivtv_service2vbi(itv->vbi.sliced_data[i].id);
+		memcpy(dst + sd + 12 + line * 43 + 1, itv->vbi.sliced_data[i].data, 42);
+		line++;
+	}
+	memcpy(dst, mpeg_hdr_data, sizeof(mpeg_hdr_data));
+	if (line == 36) {
+		/* All lines are used, so there is no space for the linemask
+		   (the max size of the VBI data is 36 * 43 + 4 bytes).
+		   So in this case we use the magic number 'ITV0'. */
+		memcpy(dst + sd, "ITV0", 4);
+		memcpy(dst + sd + 4, dst + sd + 12, line * 43);
+		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);
+	}
+	dst[4+16] = (size + 10) >> 8;
+	dst[5+16] = (size + 10) & 0xff;
+	dst[9+16] = 0x21 | ((pts_stamp >> 29) & 0x6);
+	dst[10+16] = (pts_stamp >> 22) & 0xff;
+	dst[11+16] = 1 | ((pts_stamp >> 14) & 0xff);
+	dst[12+16] = (pts_stamp >> 7) & 0xff;
+	dst[13+16] = 1 | ((pts_stamp & 0x7f) << 1);
+	itv->vbi.sliced_mpeg_size[idx] = sd + size;
+}
+
+static int ivtv_convert_ivtv_vbi(struct ivtv *itv, u8 *p)
+{
+	u32 linemask[2];
+	int i, l, id2;
+	int line = 0;
+
+	if (!memcmp(p, "itv0", 4)) {
+		memcpy(linemask, p + 4, 8);
+		p += 12;
+	} else if (!memcmp(p, "ITV0", 4)) {
+		linemask[0] = 0xffffffff;
+		linemask[1] = 0xf;
+		p += 4;
+	} else {
+		/* unknown VBI data, convert to empty VBI frame */
+		linemask[0] = linemask[1] = 0;
+	}
+	for (i = 0; i < 36; i++) {
+		int err = 0;
+
+		if (i < 32 && !(linemask[0] & (1 << i)))
+			continue;
+		if (i >= 32 && !(linemask[1] & (1 << (i - 32))))
+			continue;
+		id2 = *p & 0xf;
+		switch (id2) {
+		case IVTV_SLICED_TYPE_TELETEXT_B:
+			id2 = V4L2_SLICED_TELETEXT_B;
+			break;
+		case IVTV_SLICED_TYPE_CAPTION_525:
+			id2 = V4L2_SLICED_CAPTION_525;
+			err = !odd_parity(p[1]) || !odd_parity(p[2]);
+			break;
+		case IVTV_SLICED_TYPE_VPS:
+			id2 = V4L2_SLICED_VPS;
+			break;
+		case IVTV_SLICED_TYPE_WSS_625:
+			id2 = V4L2_SLICED_WSS_625;
+			break;
+		default:
+			id2 = 0;
+			break;
+		}
+		if (err == 0) {
+			l = (i < 18) ? i + 6 : i - 18 + 6;
+			itv->vbi.sliced_dec_data[line].line = l;
+			itv->vbi.sliced_dec_data[line].field = i >= 18;
+			itv->vbi.sliced_dec_data[line].id = id2;
+			memcpy(itv->vbi.sliced_dec_data[line].data, p + 1, 42);
+			line++;
+		}
+		p += 43;
+	}
+	while (line < 36) {
+		itv->vbi.sliced_dec_data[line].id = 0;
+		itv->vbi.sliced_dec_data[line].line = 0;
+		itv->vbi.sliced_dec_data[line].field = 0;
+		line++;
+	}
+	return line * sizeof(itv->vbi.sliced_dec_data[0]);
+}
+
+/* Compress raw VBI format, removes leading SAV codes and surplus space after the
+   field.
+   Returns new compressed size. */
+static u32 compress_raw_buf(struct ivtv *itv, u8 *buf, u32 size)
+{
+	u32 line_size = itv->vbi.raw_decoder_line_size;
+	u32 lines = itv->vbi.count;
+	u8 sav1 = itv->vbi.raw_decoder_sav_odd_field;
+	u8 sav2 = itv->vbi.raw_decoder_sav_even_field;
+	u8 *q = buf;
+	u8 *p;
+	int i;
+
+	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)) {
+			break;
+		}
+		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 ivtv *itv, u32 line, u8 *buf, u32 size, u8 sav)
+{
+	u32 line_size = itv->vbi.sliced_decoder_line_size;
+	struct v4l2_decode_vbi_line vbi;
+	int i;
+	unsigned lines = 0;
+
+	/* find the first valid line */
+	for (i = 0; i < size; i++, buf++) {
+		if (buf[0] == 0xff && !buf[1] && !buf[2] && buf[3] == sav)
+			break;
+	}
+
+	size -= i;
+	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) {
+			continue;
+		}
+		vbi.p = p + 4;
+		v4l2_subdev_call(itv->sd_video, vbi, decode_vbi_line, &vbi);
+		if (vbi.type && !(lines & (1 << vbi.line))) {
+			lines |= 1 << vbi.line;
+			itv->vbi.sliced_data[line].id = vbi.type;
+			itv->vbi.sliced_data[line].field = vbi.is_second_field;
+			itv->vbi.sliced_data[line].line = vbi.line;
+			memcpy(itv->vbi.sliced_data[line].data, vbi.p, 42);
+			line++;
+		}
+	}
+	return line;
+}
+
+void ivtv_process_vbi_data(struct ivtv *itv, struct ivtv_buffer *buf,
+			   u64 pts_stamp, int streamtype)
+{
+	u8 *p = (u8 *) buf->buf;
+	u32 size = buf->bytesused;
+	int y;
+
+	/* Raw VBI data */
+	if (streamtype == IVTV_ENC_STREAM_TYPE_VBI && ivtv_raw_vbi(itv)) {
+		u8 type;
+
+		ivtv_buf_swap(buf);
+
+		type = p[3];
+
+		size = buf->bytesused = compress_raw_buf(itv, p, size);
+
+		/* second field of the frame? */
+		if (type == itv->vbi.raw_decoder_sav_even_field) {
+			/* Dirty hack needed for backwards
+			   compatibility of old VBI software. */
+			p += size - 4;
+			memcpy(p, &itv->vbi.frame, 4);
+			itv->vbi.frame++;
+		}
+		return;
+	}
+
+	/* Sliced VBI data with data insertion */
+	if (streamtype == IVTV_ENC_STREAM_TYPE_VBI) {
+		int lines;
+
+		ivtv_buf_swap(buf);
+
+		/* first field */
+		lines = compress_sliced_buf(itv, 0, p, size / 2,
+			itv->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(itv, lines, p + size / 2 - 32, size / 2 + 32,
+			itv->vbi.sliced_decoder_sav_even_field);
+		/* always return at least one empty line */
+		if (lines == 0) {
+			itv->vbi.sliced_data[0].id = 0;
+			itv->vbi.sliced_data[0].line = 0;
+			itv->vbi.sliced_data[0].field = 0;
+			lines = 1;
+		}
+		buf->bytesused = size = lines * sizeof(itv->vbi.sliced_data[0]);
+		memcpy(p, &itv->vbi.sliced_data[0], size);
+
+		if (itv->vbi.insert_mpeg) {
+			copy_vbi_data(itv, lines, pts_stamp);
+		}
+		itv->vbi.frame++;
+		return;
+	}
+
+	/* Sliced VBI re-inserted from an MPEG stream */
+	if (streamtype == IVTV_DEC_STREAM_TYPE_VBI) {
+		/* If the size is not 4-byte aligned, then the starting address
+		   for the swapping is also shifted. After swapping the data the
+		   real start address of the VBI data is exactly 4 bytes after the
+		   original start. It's a bit fiddly but it works like a charm.
+		   Non-4-byte alignment happens when an lseek is done on the input
+		   mpeg file to a non-4-byte aligned position. So on arrival here
+		   the VBI data is also non-4-byte aligned. */
+		int offset = size & 3;
+		int cnt;
+
+		if (offset) {
+			p += 4 - offset;
+		}
+		/* Swap Buffer */
+		for (y = 0; y < size; y += 4) {
+		       swab32s((u32 *)(p + y));
+		}
+
+		cnt = ivtv_convert_ivtv_vbi(itv, p + offset);
+		memcpy(buf->buf, itv->vbi.sliced_dec_data, cnt);
+		buf->bytesused = cnt;
+
+		ivtv_write_vbi(itv, itv->vbi.sliced_dec_data,
+			       cnt / sizeof(itv->vbi.sliced_dec_data[0]));
+		return;
+	}
+}
+
+void ivtv_disable_cc(struct ivtv *itv)
+{
+	struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } };
+
+	clear_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags);
+	ivtv_set_cc(itv, 0, &cc);
+	itv->vbi.cc_payload_idx = 0;
+}
+
+
+void ivtv_vbi_work_handler(struct ivtv *itv)
+{
+	struct vbi_info *vi = &itv->vbi;
+	struct v4l2_sliced_vbi_data data;
+	struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } };
+
+	/* Lock */
+	if (itv->output_mode == OUT_PASSTHROUGH) {
+		if (itv->is_50hz) {
+			data.id = V4L2_SLICED_WSS_625;
+			data.field = 0;
+
+			if (v4l2_subdev_call(itv->sd_video, vbi, g_vbi_data, &data) == 0) {
+				ivtv_set_wss(itv, 1, data.data[0] & 0xf);
+				vi->wss_missing_cnt = 0;
+			} else if (vi->wss_missing_cnt == 4) {
+				ivtv_set_wss(itv, 1, 0x8);  /* 4x3 full format */
+			} else {
+				vi->wss_missing_cnt++;
+			}
+		}
+		else {
+			int mode = 0;
+
+			data.id = V4L2_SLICED_CAPTION_525;
+			data.field = 0;
+			if (v4l2_subdev_call(itv->sd_video, vbi, g_vbi_data, &data) == 0) {
+				mode |= 1;
+				cc.odd[0] = data.data[0];
+				cc.odd[1] = data.data[1];
+			}
+			data.field = 1;
+			if (v4l2_subdev_call(itv->sd_video, vbi, g_vbi_data, &data) == 0) {
+				mode |= 2;
+				cc.even[0] = data.data[0];
+				cc.even[1] = data.data[1];
+			}
+			if (mode) {
+				vi->cc_missing_cnt = 0;
+				ivtv_set_cc(itv, mode, &cc);
+			} else if (vi->cc_missing_cnt == 4) {
+				ivtv_set_cc(itv, 0, &cc);
+			} else {
+				vi->cc_missing_cnt++;
+			}
+		}
+		return;
+	}
+
+	if (test_and_clear_bit(IVTV_F_I_UPDATE_WSS, &itv->i_flags)) {
+		ivtv_set_wss(itv, 1, vi->wss_payload & 0xf);
+	}
+
+	if (test_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags)) {
+		if (vi->cc_payload_idx == 0) {
+			clear_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags);
+			ivtv_set_cc(itv, 3, &cc);
+		}
+		while (vi->cc_payload_idx) {
+			cc = vi->cc_payload[0];
+
+			memcpy(vi->cc_payload, vi->cc_payload + 1,
+					sizeof(vi->cc_payload) - sizeof(vi->cc_payload[0]));
+			vi->cc_payload_idx--;
+			if (vi->cc_payload_idx && cc.odd[0] == 0x80 && cc.odd[1] == 0x80)
+				continue;
+
+			ivtv_set_cc(itv, 3, &cc);
+			break;
+		}
+	}
+
+	if (test_and_clear_bit(IVTV_F_I_UPDATE_VPS, &itv->i_flags)) {
+		ivtv_set_vps(itv, 1);
+	}
+}
diff --git a/drivers/media/pci/ivtv/ivtv-vbi.h b/drivers/media/pci/ivtv/ivtv-vbi.h
new file mode 100644
index 0000000..166dd0b
--- /dev/null
+++ b/drivers/media/pci/ivtv/ivtv-vbi.h
@@ -0,0 +1,34 @@
+/*
+    Vertical Blank Interval support functions
+    Copyright (C) 2004-2007  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef IVTV_VBI_H
+#define IVTV_VBI_H
+
+ssize_t
+ivtv_write_vbi_from_user(struct ivtv *itv,
+			 const struct v4l2_sliced_vbi_data __user *sliced,
+			 size_t count);
+void ivtv_process_vbi_data(struct ivtv *itv, struct ivtv_buffer *buf,
+			   u64 pts_stamp, int streamtype);
+int ivtv_used_line(struct ivtv *itv, int line, int field);
+void ivtv_disable_cc(struct ivtv *itv);
+void ivtv_set_vbi(unsigned long arg);
+void ivtv_vbi_work_handler(struct ivtv *itv);
+
+#endif
diff --git a/drivers/media/pci/ivtv/ivtv-version.h b/drivers/media/pci/ivtv/ivtv-version.h
new file mode 100644
index 0000000..a20f346
--- /dev/null
+++ b/drivers/media/pci/ivtv/ivtv-version.h
@@ -0,0 +1,26 @@
+/*
+    ivtv driver version information
+    Copyright (C) 2005-2007  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef IVTV_VERSION_H
+#define IVTV_VERSION_H
+
+#define IVTV_DRIVER_NAME "ivtv"
+#define IVTV_VERSION "1.4.3"
+
+#endif
diff --git a/drivers/media/pci/ivtv/ivtv-yuv.c b/drivers/media/pci/ivtv/ivtv-yuv.c
new file mode 100644
index 0000000..2ad65eb
--- /dev/null
+++ b/drivers/media/pci/ivtv/ivtv-yuv.c
@@ -0,0 +1,1296 @@
+/*
+    yuv support
+
+    Copyright (C) 2007  Ian Armstrong <ian@iarmst.demon.co.uk>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public 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 "ivtv-driver.h"
+#include "ivtv-udma.h"
+#include "ivtv-yuv.h"
+
+/* YUV buffer offsets */
+const u32 yuv_offset[IVTV_YUV_BUFFERS] = {
+	0x001a8600,
+	0x00240400,
+	0x002d8200,
+	0x00370000,
+	0x00029000,
+	0x000C0E00,
+	0x006B0400,
+	0x00748200
+};
+
+static int ivtv_yuv_prep_user_dma(struct ivtv *itv, struct ivtv_user_dma *dma,
+				  struct ivtv_dma_frame *args)
+{
+	struct ivtv_dma_page_info y_dma;
+	struct ivtv_dma_page_info uv_dma;
+	struct yuv_playback_info *yi = &itv->yuv_info;
+	u8 frame = yi->draw_frame;
+	struct yuv_frame_info *f = &yi->new_frame_info[frame];
+	int i;
+	int y_pages, uv_pages;
+	unsigned long y_buffer_offset, uv_buffer_offset;
+	int y_decode_height, uv_decode_height, y_size;
+
+	y_buffer_offset = IVTV_DECODER_OFFSET + yuv_offset[frame];
+	uv_buffer_offset = y_buffer_offset + IVTV_YUV_BUFFER_UV_OFFSET;
+
+	y_decode_height = uv_decode_height = f->src_h + f->src_y;
+
+	if (f->offset_y)
+		y_buffer_offset += 720 * 16;
+
+	if (y_decode_height & 15)
+		y_decode_height = (y_decode_height + 16) & ~15;
+
+	if (uv_decode_height & 31)
+		uv_decode_height = (uv_decode_height + 32) & ~31;
+
+	y_size = 720 * y_decode_height;
+
+	/* Still in USE */
+	if (dma->SG_length || dma->page_count) {
+		IVTV_DEBUG_WARN
+		    ("prep_user_dma: SG_length %d page_count %d still full?\n",
+		     dma->SG_length, dma->page_count);
+		return -EBUSY;
+	}
+
+	ivtv_udma_get_page_info (&y_dma, (unsigned long)args->y_source, 720 * y_decode_height);
+	ivtv_udma_get_page_info (&uv_dma, (unsigned long)args->uv_source, 360 * uv_decode_height);
+
+	/* Get user pages for DMA Xfer */
+	down_read(&current->mm->mmap_sem);
+	y_pages = get_user_pages(current, current->mm, y_dma.uaddr, y_dma.page_count, 0, 1, &dma->map[0], NULL);
+	uv_pages = 0; /* silence gcc. value is set and consumed only if: */
+	if (y_pages == y_dma.page_count) {
+		uv_pages = get_user_pages(current, current->mm,
+					  uv_dma.uaddr, uv_dma.page_count, 0, 1,
+					  &dma->map[y_pages], NULL);
+	}
+	up_read(&current->mm->mmap_sem);
+
+	if (y_pages != y_dma.page_count || uv_pages != uv_dma.page_count) {
+		int rc = -EFAULT;
+
+		if (y_pages == y_dma.page_count) {
+			IVTV_DEBUG_WARN
+				("failed to map uv user pages, returned %d "
+				 "expecting %d\n", uv_pages, uv_dma.page_count);
+
+			if (uv_pages >= 0) {
+				for (i = 0; i < uv_pages; i++)
+					put_page(dma->map[y_pages + i]);
+				rc = -EFAULT;
+			} else {
+				rc = uv_pages;
+			}
+		} else {
+			IVTV_DEBUG_WARN
+				("failed to map y user pages, returned %d "
+				 "expecting %d\n", y_pages, y_dma.page_count);
+		}
+		if (y_pages >= 0) {
+			for (i = 0; i < y_pages; i++)
+				put_page(dma->map[i]);
+			/*
+			 * Inherit the -EFAULT from rc's
+			 * initialization, but allow it to be
+			 * overriden by uv_pages above if it was an
+			 * actual errno.
+			 */
+		} else {
+			rc = y_pages;
+		}
+		return rc;
+	}
+
+	dma->page_count = y_pages + uv_pages;
+
+	/* Fill & map SG List */
+	if (ivtv_udma_fill_sg_list (dma, &uv_dma, ivtv_udma_fill_sg_list (dma, &y_dma, 0)) < 0) {
+		IVTV_DEBUG_WARN("could not allocate bounce buffers for highmem userspace buffers\n");
+		for (i = 0; i < dma->page_count; i++) {
+			put_page(dma->map[i]);
+		}
+		dma->page_count = 0;
+		return -ENOMEM;
+	}
+	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);
+
+	/* If we've offset the y plane, ensure top area is blanked */
+	if (f->offset_y && yi->blanking_dmaptr) {
+		dma->SGarray[dma->SG_length].size = cpu_to_le32(720*16);
+		dma->SGarray[dma->SG_length].src = cpu_to_le32(yi->blanking_dmaptr);
+		dma->SGarray[dma->SG_length].dst = cpu_to_le32(IVTV_DECODER_OFFSET + yuv_offset[frame]);
+		dma->SG_length++;
+	}
+
+	/* Tag SG Array with Interrupt Bit */
+	dma->SGarray[dma->SG_length - 1].size |= cpu_to_le32(0x80000000);
+
+	ivtv_udma_sync_for_device(itv);
+	return 0;
+}
+
+/* We rely on a table held in the firmware - Quick check. */
+int ivtv_yuv_filter_check(struct ivtv *itv)
+{
+	int i, y, uv;
+
+	for (i = 0, y = 16, uv = 4; i < 16; i++, y += 24, uv += 12) {
+		if ((read_dec(IVTV_YUV_HORIZONTAL_FILTER_OFFSET + y) != i << 16) ||
+		    (read_dec(IVTV_YUV_VERTICAL_FILTER_OFFSET + uv) != i << 16)) {
+			IVTV_WARN ("YUV filter table not found in firmware.\n");
+			return -1;
+		}
+	}
+	return 0;
+}
+
+static void ivtv_yuv_filter(struct ivtv *itv, int h_filter, int v_filter_1, int v_filter_2)
+{
+	u32 i, line;
+
+	/* If any filter is -1, then don't update it */
+	if (h_filter > -1) {
+		if (h_filter > 4)
+			h_filter = 4;
+		i = IVTV_YUV_HORIZONTAL_FILTER_OFFSET + (h_filter * 384);
+		for (line = 0; line < 16; line++) {
+			write_reg(read_dec(i), 0x02804);
+			write_reg(read_dec(i), 0x0281c);
+			i += 4;
+			write_reg(read_dec(i), 0x02808);
+			write_reg(read_dec(i), 0x02820);
+			i += 4;
+			write_reg(read_dec(i), 0x0280c);
+			write_reg(read_dec(i), 0x02824);
+			i += 4;
+			write_reg(read_dec(i), 0x02810);
+			write_reg(read_dec(i), 0x02828);
+			i += 4;
+			write_reg(read_dec(i), 0x02814);
+			write_reg(read_dec(i), 0x0282c);
+			i += 8;
+			write_reg(0, 0x02818);
+			write_reg(0, 0x02830);
+		}
+		IVTV_DEBUG_YUV("h_filter -> %d\n", h_filter);
+	}
+
+	if (v_filter_1 > -1) {
+		if (v_filter_1 > 4)
+			v_filter_1 = 4;
+		i = IVTV_YUV_VERTICAL_FILTER_OFFSET + (v_filter_1 * 192);
+		for (line = 0; line < 16; line++) {
+			write_reg(read_dec(i), 0x02900);
+			i += 4;
+			write_reg(read_dec(i), 0x02904);
+			i += 8;
+			write_reg(0, 0x02908);
+		}
+		IVTV_DEBUG_YUV("v_filter_1 -> %d\n", v_filter_1);
+	}
+
+	if (v_filter_2 > -1) {
+		if (v_filter_2 > 4)
+			v_filter_2 = 4;
+		i = IVTV_YUV_VERTICAL_FILTER_OFFSET + (v_filter_2 * 192);
+		for (line = 0; line < 16; line++) {
+			write_reg(read_dec(i), 0x0290c);
+			i += 4;
+			write_reg(read_dec(i), 0x02910);
+			i += 8;
+			write_reg(0, 0x02914);
+		}
+		IVTV_DEBUG_YUV("v_filter_2 -> %d\n", v_filter_2);
+	}
+}
+
+static void ivtv_yuv_handle_horizontal(struct ivtv *itv, struct yuv_frame_info *f)
+{
+	struct yuv_playback_info *yi = &itv->yuv_info;
+	u32 reg_2834, reg_2838, reg_283c;
+	u32 reg_2844, reg_2854, reg_285c;
+	u32 reg_2864, reg_2874, reg_2890;
+	u32 reg_2870, reg_2870_base, reg_2870_offset;
+	int x_cutoff;
+	int h_filter;
+	u32 master_width;
+
+	IVTV_DEBUG_WARN
+	    ("Adjust to width %d src_w %d dst_w %d src_x %d dst_x %d\n",
+	     f->tru_w, f->src_w, f->dst_w, f->src_x, f->dst_x);
+
+	/* How wide is the src image */
+	x_cutoff = f->src_w + f->src_x;
+
+	/* Set the display width */
+	reg_2834 = f->dst_w;
+	reg_2838 = reg_2834;
+
+	/* Set the display position */
+	reg_2890 = f->dst_x;
+
+	/* Index into the image horizontally */
+	reg_2870 = 0;
+
+	/* 2870 is normally fudged to align video coords with osd coords.
+	   If running full screen, it causes an unwanted left shift
+	   Remove the fudge if we almost fill the screen.
+	   Gradually adjust the offset to avoid the video 'snapping'
+	   left/right if it gets dragged through this region.
+	   Only do this if osd is full width. */
+	if (f->vis_w == 720) {
+		if ((f->tru_x - f->pan_x > -1) && (f->tru_x - f->pan_x <= 40) && (f->dst_w >= 680))
+			reg_2870 = 10 - (f->tru_x - f->pan_x) / 4;
+		else if ((f->tru_x - f->pan_x < 0) && (f->tru_x - f->pan_x >= -20) && (f->dst_w >= 660))
+			reg_2870 = (10 + (f->tru_x - f->pan_x) / 2);
+
+		if (f->dst_w >= f->src_w)
+			reg_2870 = reg_2870 << 16 | reg_2870;
+		else
+			reg_2870 = ((reg_2870 & ~1) << 15) | (reg_2870 & ~1);
+	}
+
+	if (f->dst_w < f->src_w)
+		reg_2870 = 0x000d000e - reg_2870;
+	else
+		reg_2870 = 0x0012000e - reg_2870;
+
+	/* We're also using 2870 to shift the image left (src_x & negative dst_x) */
+	reg_2870_offset = (f->src_x * ((f->dst_w << 21) / f->src_w)) >> 19;
+
+	if (f->dst_w >= f->src_w) {
+		x_cutoff &= ~1;
+		master_width = (f->src_w * 0x00200000) / (f->dst_w);
+		if (master_width * f->dst_w != f->src_w * 0x00200000)
+			master_width++;
+		reg_2834 = (reg_2834 << 16) | x_cutoff;
+		reg_2838 = (reg_2838 << 16) | x_cutoff;
+		reg_283c = master_width >> 2;
+		reg_2844 = master_width >> 2;
+		reg_2854 = master_width;
+		reg_285c = master_width >> 1;
+		reg_2864 = master_width >> 1;
+
+		/* We also need to factor in the scaling
+		   (src_w - dst_w) / (src_w / 4) */
+		if (f->dst_w > f->src_w)
+			reg_2870_base = ((f->dst_w - f->src_w)<<16) / (f->src_w <<14);
+		else
+			reg_2870_base = 0;
+
+		reg_2870 += (((reg_2870_offset << 14) & 0xFFFF0000) | reg_2870_offset >> 2) + (reg_2870_base << 17 | reg_2870_base);
+		reg_2874 = 0;
+	} else if (f->dst_w < f->src_w / 2) {
+		master_width = (f->src_w * 0x00080000) / f->dst_w;
+		if (master_width * f->dst_w != f->src_w * 0x00080000)
+			master_width++;
+		reg_2834 = (reg_2834 << 16) | x_cutoff;
+		reg_2838 = (reg_2838 << 16) | x_cutoff;
+		reg_283c = master_width >> 2;
+		reg_2844 = master_width >> 1;
+		reg_2854 = master_width;
+		reg_285c = master_width >> 1;
+		reg_2864 = master_width >> 1;
+		reg_2870 += ((reg_2870_offset << 15) & 0xFFFF0000) | reg_2870_offset;
+		reg_2870 += (5 - (((f->src_w + f->src_w / 2) - 1) / f->dst_w)) << 16;
+		reg_2874 = 0x00000012;
+	} else {
+		master_width = (f->src_w * 0x00100000) / f->dst_w;
+		if (master_width * f->dst_w != f->src_w * 0x00100000)
+			master_width++;
+		reg_2834 = (reg_2834 << 16) | x_cutoff;
+		reg_2838 = (reg_2838 << 16) | x_cutoff;
+		reg_283c = master_width >> 2;
+		reg_2844 = master_width >> 1;
+		reg_2854 = master_width;
+		reg_285c = master_width >> 1;
+		reg_2864 = master_width >> 1;
+		reg_2870 += ((reg_2870_offset << 14) & 0xFFFF0000) | reg_2870_offset >> 1;
+		reg_2870 += (5 - (((f->src_w * 3) - 1) / f->dst_w)) << 16;
+		reg_2874 = 0x00000001;
+	}
+
+	/* Select the horizontal filter */
+	if (f->src_w == f->dst_w) {
+		/* An exact size match uses filter 0 */
+		h_filter = 0;
+	} else {
+		/* Figure out which filter to use */
+		h_filter = ((f->src_w << 16) / f->dst_w) >> 15;
+		h_filter = (h_filter >> 1) + (h_filter & 1);
+		/* Only an exact size match can use filter 0 */
+		h_filter += !h_filter;
+	}
+
+	write_reg(reg_2834, 0x02834);
+	write_reg(reg_2838, 0x02838);
+	IVTV_DEBUG_YUV("Update reg 0x2834 %08x->%08x 0x2838 %08x->%08x\n",
+		       yi->reg_2834, reg_2834, yi->reg_2838, reg_2838);
+
+	write_reg(reg_283c, 0x0283c);
+	write_reg(reg_2844, 0x02844);
+
+	IVTV_DEBUG_YUV("Update reg 0x283c %08x->%08x 0x2844 %08x->%08x\n",
+		       yi->reg_283c, reg_283c, yi->reg_2844, reg_2844);
+
+	write_reg(0x00080514, 0x02840);
+	write_reg(0x00100514, 0x02848);
+	IVTV_DEBUG_YUV("Update reg 0x2840 %08x->%08x 0x2848 %08x->%08x\n",
+		       yi->reg_2840, 0x00080514, yi->reg_2848, 0x00100514);
+
+	write_reg(reg_2854, 0x02854);
+	IVTV_DEBUG_YUV("Update reg 0x2854 %08x->%08x \n",
+		       yi->reg_2854, reg_2854);
+
+	write_reg(reg_285c, 0x0285c);
+	write_reg(reg_2864, 0x02864);
+	IVTV_DEBUG_YUV("Update reg 0x285c %08x->%08x 0x2864 %08x->%08x\n",
+		       yi->reg_285c, reg_285c, yi->reg_2864, reg_2864);
+
+	write_reg(reg_2874, 0x02874);
+	IVTV_DEBUG_YUV("Update reg 0x2874 %08x->%08x\n",
+		       yi->reg_2874, reg_2874);
+
+	write_reg(reg_2870, 0x02870);
+	IVTV_DEBUG_YUV("Update reg 0x2870 %08x->%08x\n",
+		       yi->reg_2870, reg_2870);
+
+	write_reg(reg_2890, 0x02890);
+	IVTV_DEBUG_YUV("Update reg 0x2890 %08x->%08x\n",
+		       yi->reg_2890, reg_2890);
+
+	/* Only update the filter if we really need to */
+	if (h_filter != yi->h_filter) {
+		ivtv_yuv_filter(itv, h_filter, -1, -1);
+		yi->h_filter = h_filter;
+	}
+}
+
+static void ivtv_yuv_handle_vertical(struct ivtv *itv, struct yuv_frame_info *f)
+{
+	struct yuv_playback_info *yi = &itv->yuv_info;
+	u32 master_height;
+	u32 reg_2918, reg_291c, reg_2920, reg_2928;
+	u32 reg_2930, reg_2934, reg_293c;
+	u32 reg_2940, reg_2944, reg_294c;
+	u32 reg_2950, reg_2954, reg_2958, reg_295c;
+	u32 reg_2960, reg_2964, reg_2968, reg_296c;
+	u32 reg_289c;
+	u32 src_major_y, src_minor_y;
+	u32 src_major_uv, src_minor_uv;
+	u32 reg_2964_base, reg_2968_base;
+	int v_filter_1, v_filter_2;
+
+	IVTV_DEBUG_WARN
+	    ("Adjust to height %d src_h %d dst_h %d src_y %d dst_y %d\n",
+	     f->tru_h, f->src_h, f->dst_h, f->src_y, f->dst_y);
+
+	/* What scaling mode is being used... */
+	IVTV_DEBUG_YUV("Scaling mode Y: %s\n",
+		       f->interlaced_y ? "Interlaced" : "Progressive");
+
+	IVTV_DEBUG_YUV("Scaling mode UV: %s\n",
+		       f->interlaced_uv ? "Interlaced" : "Progressive");
+
+	/* What is the source video being treated as... */
+	IVTV_DEBUG_WARN("Source video: %s\n",
+			f->interlaced ? "Interlaced" : "Progressive");
+
+	/* We offset into the image using two different index methods, so split
+	   the y source coord into two parts. */
+	if (f->src_y < 8) {
+		src_minor_uv = f->src_y;
+		src_major_uv = 0;
+	} else {
+		src_minor_uv = 8;
+		src_major_uv = f->src_y - 8;
+	}
+
+	src_minor_y = src_minor_uv;
+	src_major_y = src_major_uv;
+
+	if (f->offset_y)
+		src_minor_y += 16;
+
+	if (f->interlaced_y)
+		reg_2918 = (f->dst_h << 16) | (f->src_h + src_minor_y);
+	else
+		reg_2918 = (f->dst_h << 16) | ((f->src_h + src_minor_y) << 1);
+
+	if (f->interlaced_uv)
+		reg_291c = (f->dst_h << 16) | ((f->src_h + src_minor_uv) >> 1);
+	else
+		reg_291c = (f->dst_h << 16) | (f->src_h + src_minor_uv);
+
+	reg_2964_base = (src_minor_y * ((f->dst_h << 16) / f->src_h)) >> 14;
+	reg_2968_base = (src_minor_uv * ((f->dst_h << 16) / f->src_h)) >> 14;
+
+	if (f->dst_h / 2 >= f->src_h && !f->interlaced_y) {
+		master_height = (f->src_h * 0x00400000) / f->dst_h;
+		if ((f->src_h * 0x00400000) - (master_height * f->dst_h) >= f->dst_h / 2)
+			master_height++;
+		reg_2920 = master_height >> 2;
+		reg_2928 = master_height >> 3;
+		reg_2930 = master_height;
+		reg_2940 = master_height >> 1;
+		reg_2964_base >>= 3;
+		reg_2968_base >>= 3;
+		reg_296c = 0x00000000;
+	} else if (f->dst_h >= f->src_h) {
+		master_height = (f->src_h * 0x00400000) / f->dst_h;
+		master_height = (master_height >> 1) + (master_height & 1);
+		reg_2920 = master_height >> 2;
+		reg_2928 = master_height >> 2;
+		reg_2930 = master_height;
+		reg_2940 = master_height >> 1;
+		reg_296c = 0x00000000;
+		if (f->interlaced_y) {
+			reg_2964_base >>= 3;
+		} else {
+			reg_296c++;
+			reg_2964_base >>= 2;
+		}
+		if (f->interlaced_uv)
+			reg_2928 >>= 1;
+		reg_2968_base >>= 3;
+	} else if (f->dst_h >= f->src_h / 2) {
+		master_height = (f->src_h * 0x00200000) / f->dst_h;
+		master_height = (master_height >> 1) + (master_height & 1);
+		reg_2920 = master_height >> 2;
+		reg_2928 = master_height >> 2;
+		reg_2930 = master_height;
+		reg_2940 = master_height;
+		reg_296c = 0x00000101;
+		if (f->interlaced_y) {
+			reg_2964_base >>= 2;
+		} else {
+			reg_296c++;
+			reg_2964_base >>= 1;
+		}
+		if (f->interlaced_uv)
+			reg_2928 >>= 1;
+		reg_2968_base >>= 2;
+	} else {
+		master_height = (f->src_h * 0x00100000) / f->dst_h;
+		master_height = (master_height >> 1) + (master_height & 1);
+		reg_2920 = master_height >> 2;
+		reg_2928 = master_height >> 2;
+		reg_2930 = master_height;
+		reg_2940 = master_height;
+		reg_2964_base >>= 1;
+		reg_2968_base >>= 2;
+		reg_296c = 0x00000102;
+	}
+
+	/* FIXME These registers change depending on scaled / unscaled output
+	   We really need to work out what they should be */
+	if (f->src_h == f->dst_h) {
+		reg_2934 = 0x00020000;
+		reg_293c = 0x00100000;
+		reg_2944 = 0x00040000;
+		reg_294c = 0x000b0000;
+	} else {
+		reg_2934 = 0x00000FF0;
+		reg_293c = 0x00000FF0;
+		reg_2944 = 0x00000FF0;
+		reg_294c = 0x00000FF0;
+	}
+
+	/* The first line to be displayed */
+	reg_2950 = 0x00010000 + src_major_y;
+	if (f->interlaced_y)
+		reg_2950 += 0x00010000;
+	reg_2954 = reg_2950 + 1;
+
+	reg_2958 = 0x00010000 + (src_major_y >> 1);
+	if (f->interlaced_uv)
+		reg_2958 += 0x00010000;
+	reg_295c = reg_2958 + 1;
+
+	if (yi->decode_height == 480)
+		reg_289c = 0x011e0017;
+	else
+		reg_289c = 0x01500017;
+
+	if (f->dst_y < 0)
+		reg_289c = (reg_289c - ((f->dst_y & ~1)<<15))-(f->dst_y >>1);
+	else
+		reg_289c = (reg_289c + ((f->dst_y & ~1)<<15))+(f->dst_y >>1);
+
+	/* How much of the source to decode.
+	   Take into account the source offset */
+	reg_2960 = ((src_minor_y + f->src_h + src_major_y) - 1) |
+		(((src_minor_uv + f->src_h + src_major_uv - 1) & ~1) << 15);
+
+	/* Calculate correct value for register 2964 */
+	if (f->src_h == f->dst_h) {
+		reg_2964 = 1;
+	} else {
+		reg_2964 = 2 + ((f->dst_h << 1) / f->src_h);
+		reg_2964 = (reg_2964 >> 1) + (reg_2964 & 1);
+	}
+	reg_2968 = (reg_2964 << 16) + reg_2964 + (reg_2964 >> 1);
+	reg_2964 = (reg_2964 << 16) + reg_2964 + (reg_2964 * 46 / 94);
+
+	/* Okay, we've wasted time working out the correct value,
+	   but if we use it, it fouls the the window alignment.
+	   Fudge it to what we want... */
+	reg_2964 = 0x00010001 + ((reg_2964 & 0x0000FFFF) - (reg_2964 >> 16));
+	reg_2968 = 0x00010001 + ((reg_2968 & 0x0000FFFF) - (reg_2968 >> 16));
+
+	/* Deviate further from what it should be. I find the flicker headache
+	   inducing so try to reduce it slightly. Leave 2968 as-is otherwise
+	   colours foul. */
+	if ((reg_2964 != 0x00010001) && (f->dst_h / 2 <= f->src_h))
+		reg_2964 = (reg_2964 & 0xFFFF0000) + ((reg_2964 & 0x0000FFFF) / 2);
+
+	if (!f->interlaced_y)
+		reg_2964 -= 0x00010001;
+	if (!f->interlaced_uv)
+		reg_2968 -= 0x00010001;
+
+	reg_2964 += ((reg_2964_base << 16) | reg_2964_base);
+	reg_2968 += ((reg_2968_base << 16) | reg_2968_base);
+
+	/* Select the vertical filter */
+	if (f->src_h == f->dst_h) {
+		/* An exact size match uses filter 0/1 */
+		v_filter_1 = 0;
+		v_filter_2 = 1;
+	} else {
+		/* Figure out which filter to use */
+		v_filter_1 = ((f->src_h << 16) / f->dst_h) >> 15;
+		v_filter_1 = (v_filter_1 >> 1) + (v_filter_1 & 1);
+		/* Only an exact size match can use filter 0 */
+		v_filter_1 += !v_filter_1;
+		v_filter_2 = v_filter_1;
+	}
+
+	write_reg(reg_2934, 0x02934);
+	write_reg(reg_293c, 0x0293c);
+	IVTV_DEBUG_YUV("Update reg 0x2934 %08x->%08x 0x293c %08x->%08x\n",
+		       yi->reg_2934, reg_2934, yi->reg_293c, reg_293c);
+	write_reg(reg_2944, 0x02944);
+	write_reg(reg_294c, 0x0294c);
+	IVTV_DEBUG_YUV("Update reg 0x2944 %08x->%08x 0x294c %08x->%08x\n",
+		       yi->reg_2944, reg_2944, yi->reg_294c, reg_294c);
+
+	/* Ensure 2970 is 0 (does it ever change ?) */
+/*	write_reg(0,0x02970); */
+/*	IVTV_DEBUG_YUV("Update reg 0x2970 %08x->%08x\n", yi->reg_2970, 0); */
+
+	write_reg(reg_2930, 0x02938);
+	write_reg(reg_2930, 0x02930);
+	IVTV_DEBUG_YUV("Update reg 0x2930 %08x->%08x 0x2938 %08x->%08x\n",
+		       yi->reg_2930, reg_2930, yi->reg_2938, reg_2930);
+
+	write_reg(reg_2928, 0x02928);
+	write_reg(reg_2928 + 0x514, 0x0292C);
+	IVTV_DEBUG_YUV("Update reg 0x2928 %08x->%08x 0x292c %08x->%08x\n",
+		       yi->reg_2928, reg_2928, yi->reg_292c, reg_2928 + 0x514);
+
+	write_reg(reg_2920, 0x02920);
+	write_reg(reg_2920 + 0x514, 0x02924);
+	IVTV_DEBUG_YUV("Update reg 0x2920 %08x->%08x 0x2924 %08x->%08x\n",
+		       yi->reg_2920, reg_2920, yi->reg_2924, reg_2920 + 0x514);
+
+	write_reg(reg_2918, 0x02918);
+	write_reg(reg_291c, 0x0291C);
+	IVTV_DEBUG_YUV("Update reg 0x2918 %08x->%08x 0x291C %08x->%08x\n",
+		       yi->reg_2918, reg_2918, yi->reg_291c, reg_291c);
+
+	write_reg(reg_296c, 0x0296c);
+	IVTV_DEBUG_YUV("Update reg 0x296c %08x->%08x\n",
+		       yi->reg_296c, reg_296c);
+
+	write_reg(reg_2940, 0x02948);
+	write_reg(reg_2940, 0x02940);
+	IVTV_DEBUG_YUV("Update reg 0x2940 %08x->%08x 0x2948 %08x->%08x\n",
+		       yi->reg_2940, reg_2940, yi->reg_2948, reg_2940);
+
+	write_reg(reg_2950, 0x02950);
+	write_reg(reg_2954, 0x02954);
+	IVTV_DEBUG_YUV("Update reg 0x2950 %08x->%08x 0x2954 %08x->%08x\n",
+		       yi->reg_2950, reg_2950, yi->reg_2954, reg_2954);
+
+	write_reg(reg_2958, 0x02958);
+	write_reg(reg_295c, 0x0295C);
+	IVTV_DEBUG_YUV("Update reg 0x2958 %08x->%08x 0x295C %08x->%08x\n",
+		       yi->reg_2958, reg_2958, yi->reg_295c, reg_295c);
+
+	write_reg(reg_2960, 0x02960);
+	IVTV_DEBUG_YUV("Update reg 0x2960 %08x->%08x \n",
+		       yi->reg_2960, reg_2960);
+
+	write_reg(reg_2964, 0x02964);
+	write_reg(reg_2968, 0x02968);
+	IVTV_DEBUG_YUV("Update reg 0x2964 %08x->%08x 0x2968 %08x->%08x\n",
+		       yi->reg_2964, reg_2964, yi->reg_2968, reg_2968);
+
+	write_reg(reg_289c, 0x0289c);
+	IVTV_DEBUG_YUV("Update reg 0x289c %08x->%08x\n",
+		       yi->reg_289c, reg_289c);
+
+	/* Only update filter 1 if we really need to */
+	if (v_filter_1 != yi->v_filter_1) {
+		ivtv_yuv_filter(itv, -1, v_filter_1, -1);
+		yi->v_filter_1 = v_filter_1;
+	}
+
+	/* Only update filter 2 if we really need to */
+	if (v_filter_2 != yi->v_filter_2) {
+		ivtv_yuv_filter(itv, -1, -1, v_filter_2);
+		yi->v_filter_2 = v_filter_2;
+	}
+}
+
+/* Modify the supplied coordinate information to fit the visible osd area */
+static u32 ivtv_yuv_window_setup(struct ivtv *itv, struct yuv_frame_info *f)
+{
+	struct yuv_frame_info *of = &itv->yuv_info.old_frame_info;
+	int osd_crop;
+	u32 osd_scale;
+	u32 yuv_update = 0;
+
+	/* Sorry, but no negative coords for src */
+	if (f->src_x < 0)
+		f->src_x = 0;
+	if (f->src_y < 0)
+		f->src_y = 0;
+
+	/* Can only reduce width down to 1/4 original size */
+	if ((osd_crop = f->src_w - 4 * f->dst_w) > 0) {
+		f->src_x += osd_crop / 2;
+		f->src_w = (f->src_w - osd_crop) & ~3;
+		f->dst_w = f->src_w / 4;
+		f->dst_w += f->dst_w & 1;
+	}
+
+	/* Can only reduce height down to 1/4 original size */
+	if (f->src_h / f->dst_h >= 2) {
+		/* Overflow may be because we're running progressive,
+		   so force mode switch */
+		f->interlaced_y = 1;
+		/* Make sure we're still within limits for interlace */
+		if ((osd_crop = f->src_h - 4 * f->dst_h) > 0) {
+			/* If we reach here we'll have to force the height. */
+			f->src_y += osd_crop / 2;
+			f->src_h = (f->src_h - osd_crop) & ~3;
+			f->dst_h = f->src_h / 4;
+			f->dst_h += f->dst_h & 1;
+		}
+	}
+
+	/* If there's nothing to safe to display, we may as well stop now */
+	if ((int)f->dst_w <= 2 || (int)f->dst_h <= 2 ||
+	    (int)f->src_w <= 2 || (int)f->src_h <= 2) {
+		return IVTV_YUV_UPDATE_INVALID;
+	}
+
+	/* Ensure video remains inside OSD area */
+	osd_scale = (f->src_h << 16) / f->dst_h;
+
+	if ((osd_crop = f->pan_y - f->dst_y) > 0) {
+		/* Falls off the upper edge - crop */
+		f->src_y += (osd_scale * osd_crop) >> 16;
+		f->src_h -= (osd_scale * osd_crop) >> 16;
+		f->dst_h -= osd_crop;
+		f->dst_y = 0;
+	} else {
+		f->dst_y -= f->pan_y;
+	}
+
+	if ((osd_crop = f->dst_h + f->dst_y - f->vis_h) > 0) {
+		/* Falls off the lower edge - crop */
+		f->dst_h -= osd_crop;
+		f->src_h -= (osd_scale * osd_crop) >> 16;
+	}
+
+	osd_scale = (f->src_w << 16) / f->dst_w;
+
+	if ((osd_crop = f->pan_x - f->dst_x) > 0) {
+		/* Fall off the left edge - crop */
+		f->src_x += (osd_scale * osd_crop) >> 16;
+		f->src_w -= (osd_scale * osd_crop) >> 16;
+		f->dst_w -= osd_crop;
+		f->dst_x = 0;
+	} else {
+		f->dst_x -= f->pan_x;
+	}
+
+	if ((osd_crop = f->dst_w + f->dst_x - f->vis_w) > 0) {
+		/* Falls off the right edge - crop */
+		f->dst_w -= osd_crop;
+		f->src_w -= (osd_scale * osd_crop) >> 16;
+	}
+
+	if (itv->yuv_info.track_osd) {
+		/* The OSD can be moved. Track to it */
+		f->dst_x += itv->yuv_info.osd_x_offset;
+		f->dst_y += itv->yuv_info.osd_y_offset;
+	}
+
+	/* Width & height for both src & dst must be even.
+	   Same for coordinates. */
+	f->dst_w &= ~1;
+	f->dst_x &= ~1;
+
+	f->src_w += f->src_x & 1;
+	f->src_x &= ~1;
+
+	f->src_w &= ~1;
+	f->dst_w &= ~1;
+
+	f->dst_h &= ~1;
+	f->dst_y &= ~1;
+
+	f->src_h += f->src_y & 1;
+	f->src_y &= ~1;
+
+	f->src_h &= ~1;
+	f->dst_h &= ~1;
+
+	/* Due to rounding, we may have reduced the output size to <1/4 of
+	   the source. Check again, but this time just resize. Don't change
+	   source coordinates */
+	if (f->dst_w < f->src_w / 4) {
+		f->src_w &= ~3;
+		f->dst_w = f->src_w / 4;
+		f->dst_w += f->dst_w & 1;
+	}
+	if (f->dst_h < f->src_h / 4) {
+		f->src_h &= ~3;
+		f->dst_h = f->src_h / 4;
+		f->dst_h += f->dst_h & 1;
+	}
+
+	/* Check again. If there's nothing to safe to display, stop now */
+	if ((int)f->dst_w <= 2 || (int)f->dst_h <= 2 ||
+	    (int)f->src_w <= 2 || (int)f->src_h <= 2) {
+		return IVTV_YUV_UPDATE_INVALID;
+	}
+
+	/* Both x offset & width are linked, so they have to be done together */
+	if ((of->dst_w != f->dst_w) || (of->src_w != f->src_w) ||
+	    (of->dst_x != f->dst_x) || (of->src_x != f->src_x) ||
+	    (of->pan_x != f->pan_x) || (of->vis_w != f->vis_w)) {
+		yuv_update |= IVTV_YUV_UPDATE_HORIZONTAL;
+	}
+
+	if ((of->src_h != f->src_h) || (of->dst_h != f->dst_h) ||
+	    (of->dst_y != f->dst_y) || (of->src_y != f->src_y) ||
+	    (of->pan_y != f->pan_y) || (of->vis_h != f->vis_h) ||
+	    (of->lace_mode != f->lace_mode) ||
+	    (of->interlaced_y != f->interlaced_y) ||
+	    (of->interlaced_uv != f->interlaced_uv)) {
+		yuv_update |= IVTV_YUV_UPDATE_VERTICAL;
+	}
+
+	return yuv_update;
+}
+
+/* Update the scaling register to the requested value */
+void ivtv_yuv_work_handler(struct ivtv *itv)
+{
+	struct yuv_playback_info *yi = &itv->yuv_info;
+	struct yuv_frame_info f;
+	int frame = yi->update_frame;
+	u32 yuv_update;
+
+	IVTV_DEBUG_YUV("Update yuv registers for frame %d\n", frame);
+	f = yi->new_frame_info[frame];
+
+	if (yi->track_osd) {
+		/* Snapshot the osd pan info */
+		f.pan_x = yi->osd_x_pan;
+		f.pan_y = yi->osd_y_pan;
+		f.vis_w = yi->osd_vis_w;
+		f.vis_h = yi->osd_vis_h;
+	} else {
+		/* Not tracking the osd, so assume full screen */
+		f.pan_x = 0;
+		f.pan_y = 0;
+		f.vis_w = 720;
+		f.vis_h = yi->decode_height;
+	}
+
+	/* Calculate the display window coordinates. Exit if nothing left */
+	if (!(yuv_update = ivtv_yuv_window_setup(itv, &f)))
+		return;
+
+	if (yuv_update & IVTV_YUV_UPDATE_INVALID) {
+		write_reg(0x01008080, 0x2898);
+	} else if (yuv_update) {
+		write_reg(0x00108080, 0x2898);
+
+		if (yuv_update & IVTV_YUV_UPDATE_HORIZONTAL)
+			ivtv_yuv_handle_horizontal(itv, &f);
+
+		if (yuv_update & IVTV_YUV_UPDATE_VERTICAL)
+			ivtv_yuv_handle_vertical(itv, &f);
+	}
+	yi->old_frame_info = f;
+}
+
+static void ivtv_yuv_init(struct ivtv *itv)
+{
+	struct yuv_playback_info *yi = &itv->yuv_info;
+
+	IVTV_DEBUG_YUV("ivtv_yuv_init\n");
+
+	/* Take a snapshot of the current register settings */
+	yi->reg_2834 = read_reg(0x02834);
+	yi->reg_2838 = read_reg(0x02838);
+	yi->reg_283c = read_reg(0x0283c);
+	yi->reg_2840 = read_reg(0x02840);
+	yi->reg_2844 = read_reg(0x02844);
+	yi->reg_2848 = read_reg(0x02848);
+	yi->reg_2854 = read_reg(0x02854);
+	yi->reg_285c = read_reg(0x0285c);
+	yi->reg_2864 = read_reg(0x02864);
+	yi->reg_2870 = read_reg(0x02870);
+	yi->reg_2874 = read_reg(0x02874);
+	yi->reg_2898 = read_reg(0x02898);
+	yi->reg_2890 = read_reg(0x02890);
+
+	yi->reg_289c = read_reg(0x0289c);
+	yi->reg_2918 = read_reg(0x02918);
+	yi->reg_291c = read_reg(0x0291c);
+	yi->reg_2920 = read_reg(0x02920);
+	yi->reg_2924 = read_reg(0x02924);
+	yi->reg_2928 = read_reg(0x02928);
+	yi->reg_292c = read_reg(0x0292c);
+	yi->reg_2930 = read_reg(0x02930);
+	yi->reg_2934 = read_reg(0x02934);
+	yi->reg_2938 = read_reg(0x02938);
+	yi->reg_293c = read_reg(0x0293c);
+	yi->reg_2940 = read_reg(0x02940);
+	yi->reg_2944 = read_reg(0x02944);
+	yi->reg_2948 = read_reg(0x02948);
+	yi->reg_294c = read_reg(0x0294c);
+	yi->reg_2950 = read_reg(0x02950);
+	yi->reg_2954 = read_reg(0x02954);
+	yi->reg_2958 = read_reg(0x02958);
+	yi->reg_295c = read_reg(0x0295c);
+	yi->reg_2960 = read_reg(0x02960);
+	yi->reg_2964 = read_reg(0x02964);
+	yi->reg_2968 = read_reg(0x02968);
+	yi->reg_296c = read_reg(0x0296c);
+	yi->reg_2970 = read_reg(0x02970);
+
+	yi->v_filter_1 = -1;
+	yi->v_filter_2 = -1;
+	yi->h_filter = -1;
+
+	/* Set some valid size info */
+	yi->osd_x_offset = read_reg(0x02a04) & 0x00000FFF;
+	yi->osd_y_offset = (read_reg(0x02a04) >> 16) & 0x00000FFF;
+
+	/* Bit 2 of reg 2878 indicates current decoder output format
+	   0 : NTSC    1 : PAL */
+	if (read_reg(0x2878) & 4)
+		yi->decode_height = 576;
+	else
+		yi->decode_height = 480;
+
+	if (!itv->osd_info) {
+		yi->osd_vis_w = 720 - yi->osd_x_offset;
+		yi->osd_vis_h = yi->decode_height - yi->osd_y_offset;
+	} else {
+		/* If no visible size set, assume full size */
+		if (!yi->osd_vis_w)
+			yi->osd_vis_w = 720 - yi->osd_x_offset;
+
+		if (!yi->osd_vis_h) {
+			yi->osd_vis_h = yi->decode_height - yi->osd_y_offset;
+		} else if (yi->osd_vis_h + yi->osd_y_offset > yi->decode_height) {
+			/* If output video standard has changed, requested height may
+			   not be legal */
+			IVTV_DEBUG_WARN("Clipping yuv output - fb size (%d) exceeds video standard limit (%d)\n",
+					yi->osd_vis_h + yi->osd_y_offset,
+					yi->decode_height);
+			yi->osd_vis_h = yi->decode_height - yi->osd_y_offset;
+		}
+	}
+
+	/* 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->pdev, yi->blanking_ptr, 720*16, PCI_DMA_TODEVICE);
+	} else {
+		yi->blanking_dmaptr = 0;
+		IVTV_DEBUG_WARN("Failed to allocate yuv blanking buffer\n");
+	}
+
+	/* Enable YUV decoder output */
+	write_reg_sync(0x01, IVTV_REG_VDM);
+
+	set_bit(IVTV_F_I_DECODING_YUV, &itv->i_flags);
+	atomic_set(&yi->next_dma_frame, 0);
+}
+
+/* Get next available yuv buffer on PVR350 */
+static void ivtv_yuv_next_free(struct ivtv *itv)
+{
+	int draw, display;
+	struct yuv_playback_info *yi = &itv->yuv_info;
+
+	if (atomic_read(&yi->next_dma_frame) == -1)
+		ivtv_yuv_init(itv);
+
+	draw = atomic_read(&yi->next_fill_frame);
+	display = atomic_read(&yi->next_dma_frame);
+
+	if (display > draw)
+		display -= IVTV_YUV_BUFFERS;
+
+	if (draw - display >= yi->max_frames_buffered)
+		draw = (u8)(draw - 1) % IVTV_YUV_BUFFERS;
+	else
+		yi->new_frame_info[draw].update = 0;
+
+	yi->draw_frame = draw;
+}
+
+/* Set up frame according to ivtv_dma_frame parameters */
+static void ivtv_yuv_setup_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
+{
+	struct yuv_playback_info *yi = &itv->yuv_info;
+	u8 frame = yi->draw_frame;
+	u8 last_frame = (u8)(frame - 1) % IVTV_YUV_BUFFERS;
+	struct yuv_frame_info *nf = &yi->new_frame_info[frame];
+	struct yuv_frame_info *of = &yi->new_frame_info[last_frame];
+	int lace_threshold = yi->lace_threshold;
+
+	/* Preserve old update flag in case we're overwriting a queued frame */
+	int update = nf->update;
+
+	/* Take a snapshot of the yuv coordinate information */
+	nf->src_x = args->src.left;
+	nf->src_y = args->src.top;
+	nf->src_w = args->src.width;
+	nf->src_h = args->src.height;
+	nf->dst_x = args->dst.left;
+	nf->dst_y = args->dst.top;
+	nf->dst_w = args->dst.width;
+	nf->dst_h = args->dst.height;
+	nf->tru_x = args->dst.left;
+	nf->tru_w = args->src_width;
+	nf->tru_h = args->src_height;
+
+	/* Are we going to offset the Y plane */
+	nf->offset_y = (nf->tru_h + nf->src_x < 512 - 16) ? 1 : 0;
+
+	nf->update = 0;
+	nf->interlaced_y = 0;
+	nf->interlaced_uv = 0;
+	nf->delay = 0;
+	nf->sync_field = 0;
+	nf->lace_mode = yi->lace_mode & IVTV_YUV_MODE_MASK;
+
+	if (lace_threshold < 0)
+		lace_threshold = yi->decode_height - 1;
+
+	/* Work out the lace settings */
+	switch (nf->lace_mode) {
+	case IVTV_YUV_MODE_PROGRESSIVE: /* Progressive mode */
+		nf->interlaced = 0;
+		if (nf->tru_h < 512 || (nf->tru_h > 576 && nf->tru_h < 1021))
+			nf->interlaced_y = 0;
+		else
+			nf->interlaced_y = 1;
+
+		if (nf->tru_h < 1021 && (nf->dst_h >= nf->src_h / 2))
+			nf->interlaced_uv = 0;
+		else
+			nf->interlaced_uv = 1;
+		break;
+
+	case IVTV_YUV_MODE_AUTO:
+		if (nf->tru_h <= lace_threshold || nf->tru_h > 576 || nf->tru_w > 720) {
+			nf->interlaced = 0;
+			if ((nf->tru_h < 512) ||
+			    (nf->tru_h > 576 && nf->tru_h < 1021) ||
+			    (nf->tru_w > 720 && nf->tru_h < 1021))
+				nf->interlaced_y = 0;
+			else
+				nf->interlaced_y = 1;
+			if (nf->tru_h < 1021 && (nf->dst_h >= nf->src_h / 2))
+				nf->interlaced_uv = 0;
+			else
+				nf->interlaced_uv = 1;
+		} else {
+			nf->interlaced = 1;
+			nf->interlaced_y = 1;
+			nf->interlaced_uv = 1;
+		}
+		break;
+
+	case IVTV_YUV_MODE_INTERLACED: /* Interlace mode */
+	default:
+		nf->interlaced = 1;
+		nf->interlaced_y = 1;
+		nf->interlaced_uv = 1;
+		break;
+	}
+
+	if (memcmp(&yi->old_frame_info_args, nf, sizeof(*nf))) {
+		yi->old_frame_info_args = *nf;
+		nf->update = 1;
+		IVTV_DEBUG_YUV("Requesting reg update for frame %d\n", frame);
+	}
+
+	nf->update |= update;
+	nf->sync_field = yi->lace_sync_field;
+	nf->delay = nf->sync_field != of->sync_field;
+}
+
+/* Frame is complete & ready for display */
+void ivtv_yuv_frame_complete(struct ivtv *itv)
+{
+	atomic_set(&itv->yuv_info.next_fill_frame,
+			(itv->yuv_info.draw_frame + 1) % IVTV_YUV_BUFFERS);
+}
+
+static int ivtv_yuv_udma_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
+{
+	DEFINE_WAIT(wait);
+	int rc = 0;
+	int got_sig = 0;
+	/* DMA the frame */
+	mutex_lock(&itv->udma.lock);
+
+	if ((rc = ivtv_yuv_prep_user_dma(itv, &itv->udma, args)) != 0) {
+		mutex_unlock(&itv->udma.lock);
+		return rc;
+	}
+
+	ivtv_udma_prepare(itv);
+	prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE);
+	/* if no UDMA is pending and no UDMA is in progress, then the DMA
+	   is finished */
+	while (test_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags) ||
+	       test_bit(IVTV_F_I_UDMA, &itv->i_flags)) {
+		/* don't interrupt if the DMA is in progress but break off
+		   a still pending DMA. */
+		got_sig = signal_pending(current);
+		if (got_sig && test_and_clear_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags))
+			break;
+		got_sig = 0;
+		schedule();
+	}
+	finish_wait(&itv->dma_waitq, &wait);
+
+	/* Unmap Last DMA Xfer */
+	ivtv_udma_unmap(itv);
+
+	if (got_sig) {
+		IVTV_DEBUG_INFO("User stopped YUV UDMA\n");
+		mutex_unlock(&itv->udma.lock);
+		return -EINTR;
+	}
+
+	ivtv_yuv_frame_complete(itv);
+
+	mutex_unlock(&itv->udma.lock);
+	return rc;
+}
+
+/* Setup frame according to V4L2 parameters */
+void ivtv_yuv_setup_stream_frame(struct ivtv *itv)
+{
+	struct yuv_playback_info *yi = &itv->yuv_info;
+	struct ivtv_dma_frame dma_args;
+
+	ivtv_yuv_next_free(itv);
+
+	/* Copy V4L2 parameters to an ivtv_dma_frame struct... */
+	dma_args.y_source = NULL;
+	dma_args.uv_source = NULL;
+	dma_args.src.left = 0;
+	dma_args.src.top = 0;
+	dma_args.src.width = yi->v4l2_src_w;
+	dma_args.src.height = yi->v4l2_src_h;
+	dma_args.dst = yi->main_rect;
+	dma_args.src_width = yi->v4l2_src_w;
+	dma_args.src_height = yi->v4l2_src_h;
+
+	/* ... and use the same setup routine as ivtv_yuv_prep_frame */
+	ivtv_yuv_setup_frame(itv, &dma_args);
+
+	if (!itv->dma_data_req_offset)
+		itv->dma_data_req_offset = yuv_offset[yi->draw_frame];
+}
+
+/* Attempt to dma a frame from a user buffer */
+int ivtv_yuv_udma_stream_frame(struct ivtv *itv, void __user *src)
+{
+	struct yuv_playback_info *yi = &itv->yuv_info;
+	struct ivtv_dma_frame dma_args;
+	int res;
+
+	ivtv_yuv_setup_stream_frame(itv);
+
+	/* We only need to supply source addresses for this */
+	dma_args.y_source = src;
+	dma_args.uv_source = src + 720 * ((yi->v4l2_src_h + 31) & ~31);
+	/* Wait for frame DMA. Note that serialize_lock is locked,
+	   so to allow other processes to access the driver while
+	   we are waiting unlock first and later lock again. */
+	mutex_unlock(&itv->serialize_lock);
+	res = ivtv_yuv_udma_frame(itv, &dma_args);
+	mutex_lock(&itv->serialize_lock);
+	return res;
+}
+
+/* IVTV_IOC_DMA_FRAME ioctl handler */
+int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args)
+{
+	int res;
+
+/*	IVTV_DEBUG_INFO("yuv_prep_frame\n"); */
+	ivtv_yuv_next_free(itv);
+	ivtv_yuv_setup_frame(itv, args);
+	/* Wait for frame DMA. Note that serialize_lock is locked,
+	   so to allow other processes to access the driver while
+	   we are waiting unlock first and later lock again. */
+	mutex_unlock(&itv->serialize_lock);
+	res = ivtv_yuv_udma_frame(itv, args);
+	mutex_lock(&itv->serialize_lock);
+	return res;
+}
+
+void ivtv_yuv_close(struct ivtv *itv)
+{
+	struct yuv_playback_info *yi = &itv->yuv_info;
+	int h_filter, v_filter_1, v_filter_2;
+
+	IVTV_DEBUG_YUV("ivtv_yuv_close\n");
+	mutex_unlock(&itv->serialize_lock);
+	ivtv_waitq(&itv->vsync_waitq);
+	mutex_lock(&itv->serialize_lock);
+
+	yi->running = 0;
+	atomic_set(&yi->next_dma_frame, -1);
+	atomic_set(&yi->next_fill_frame, 0);
+
+	/* Reset registers we have changed so mpeg playback works */
+
+	/* If we fully restore this register, the display may remain active.
+	   Restore, but set one bit to blank the video. Firmware will always
+	   clear this bit when needed, so not a problem. */
+	write_reg(yi->reg_2898 | 0x01000000, 0x2898);
+
+	write_reg(yi->reg_2834, 0x02834);
+	write_reg(yi->reg_2838, 0x02838);
+	write_reg(yi->reg_283c, 0x0283c);
+	write_reg(yi->reg_2840, 0x02840);
+	write_reg(yi->reg_2844, 0x02844);
+	write_reg(yi->reg_2848, 0x02848);
+	write_reg(yi->reg_2854, 0x02854);
+	write_reg(yi->reg_285c, 0x0285c);
+	write_reg(yi->reg_2864, 0x02864);
+	write_reg(yi->reg_2870, 0x02870);
+	write_reg(yi->reg_2874, 0x02874);
+	write_reg(yi->reg_2890, 0x02890);
+	write_reg(yi->reg_289c, 0x0289c);
+
+	write_reg(yi->reg_2918, 0x02918);
+	write_reg(yi->reg_291c, 0x0291c);
+	write_reg(yi->reg_2920, 0x02920);
+	write_reg(yi->reg_2924, 0x02924);
+	write_reg(yi->reg_2928, 0x02928);
+	write_reg(yi->reg_292c, 0x0292c);
+	write_reg(yi->reg_2930, 0x02930);
+	write_reg(yi->reg_2934, 0x02934);
+	write_reg(yi->reg_2938, 0x02938);
+	write_reg(yi->reg_293c, 0x0293c);
+	write_reg(yi->reg_2940, 0x02940);
+	write_reg(yi->reg_2944, 0x02944);
+	write_reg(yi->reg_2948, 0x02948);
+	write_reg(yi->reg_294c, 0x0294c);
+	write_reg(yi->reg_2950, 0x02950);
+	write_reg(yi->reg_2954, 0x02954);
+	write_reg(yi->reg_2958, 0x02958);
+	write_reg(yi->reg_295c, 0x0295c);
+	write_reg(yi->reg_2960, 0x02960);
+	write_reg(yi->reg_2964, 0x02964);
+	write_reg(yi->reg_2968, 0x02968);
+	write_reg(yi->reg_296c, 0x0296c);
+	write_reg(yi->reg_2970, 0x02970);
+
+	/* Prepare to restore filters */
+
+	/* First the horizontal filter */
+	if ((yi->reg_2834 & 0x0000FFFF) == (yi->reg_2834 >> 16)) {
+		/* An exact size match uses filter 0 */
+		h_filter = 0;
+	} else {
+		/* Figure out which filter to use */
+		h_filter = ((yi->reg_2834 << 16) / (yi->reg_2834 >> 16)) >> 15;
+		h_filter = (h_filter >> 1) + (h_filter & 1);
+		/* Only an exact size match can use filter 0. */
+		h_filter += !h_filter;
+	}
+
+	/* Now the vertical filter */
+	if ((yi->reg_2918 & 0x0000FFFF) == (yi->reg_2918 >> 16)) {
+		/* An exact size match uses filter 0/1 */
+		v_filter_1 = 0;
+		v_filter_2 = 1;
+	} else {
+		/* Figure out which filter to use */
+		v_filter_1 = ((yi->reg_2918 << 16) / (yi->reg_2918 >> 16)) >> 15;
+		v_filter_1 = (v_filter_1 >> 1) + (v_filter_1 & 1);
+		/* Only an exact size match can use filter 0 */
+		v_filter_1 += !v_filter_1;
+		v_filter_2 = v_filter_1;
+	}
+
+	/* Now restore the filters */
+	ivtv_yuv_filter(itv, h_filter, v_filter_1, v_filter_2);
+
+	/* and clear a few registers */
+	write_reg(0, 0x02814);
+	write_reg(0, 0x0282c);
+	write_reg(0, 0x02904);
+	write_reg(0, 0x02910);
+
+	/* Release the blanking buffer */
+	if (yi->blanking_ptr) {
+		kfree(yi->blanking_ptr);
+		yi->blanking_ptr = NULL;
+		pci_unmap_single(itv->pdev, yi->blanking_dmaptr, 720*16, PCI_DMA_TODEVICE);
+	}
+
+	/* Invalidate the old dimension information */
+	yi->old_frame_info.src_w = 0;
+	yi->old_frame_info.src_h = 0;
+	yi->old_frame_info_args.src_w = 0;
+	yi->old_frame_info_args.src_h = 0;
+
+	/* All done. */
+	clear_bit(IVTV_F_I_DECODING_YUV, &itv->i_flags);
+}
diff --git a/drivers/media/pci/ivtv/ivtv-yuv.h b/drivers/media/pci/ivtv/ivtv-yuv.h
new file mode 100644
index 0000000..ca5173f
--- /dev/null
+++ b/drivers/media/pci/ivtv/ivtv-yuv.h
@@ -0,0 +1,44 @@
+/*
+    yuv support
+
+    Copyright (C) 2007  Ian Armstrong <ian@iarmst.demon.co.uk>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public 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 IVTV_YUV_H
+#define IVTV_YUV_H
+
+#define IVTV_YUV_BUFFER_UV_OFFSET 0x65400	/* Offset to UV Buffer */
+
+/* Offset to filter table in firmware */
+#define IVTV_YUV_HORIZONTAL_FILTER_OFFSET 0x025d8
+#define IVTV_YUV_VERTICAL_FILTER_OFFSET 0x03358
+
+#define IVTV_YUV_UPDATE_HORIZONTAL  0x01
+#define IVTV_YUV_UPDATE_VERTICAL    0x02
+#define IVTV_YUV_UPDATE_INVALID     0x04
+
+extern const u32 yuv_offset[IVTV_YUV_BUFFERS];
+
+int ivtv_yuv_filter_check(struct ivtv *itv);
+void ivtv_yuv_setup_stream_frame(struct ivtv *itv);
+int ivtv_yuv_udma_stream_frame(struct ivtv *itv, void __user *src);
+void ivtv_yuv_frame_complete(struct ivtv *itv);
+int ivtv_yuv_prep_frame(struct ivtv *itv, struct ivtv_dma_frame *args);
+void ivtv_yuv_close(struct ivtv *itv);
+void ivtv_yuv_work_handler(struct ivtv *itv);
+
+#endif
diff --git a/drivers/media/pci/ivtv/ivtvfb.c b/drivers/media/pci/ivtv/ivtvfb.c
new file mode 100644
index 0000000..05b94aa
--- /dev/null
+++ b/drivers/media/pci/ivtv/ivtvfb.c
@@ -0,0 +1,1317 @@
+/*
+    On Screen Display cx23415 Framebuffer driver
+
+    This module presents the cx23415 OSD (onscreen display) framebuffer memory
+    as a standard Linux /dev/fb style framebuffer device. The framebuffer has
+    support for 8, 16 & 32 bpp packed pixel formats with alpha channel. In 16bpp
+    mode, there is a choice of a three color depths (12, 15 or 16 bits), but no
+    local alpha. The colorspace is selectable between rgb & yuv.
+    Depending on the TV standard configured in the ivtv module at load time,
+    the initial resolution is either 640x400 (NTSC) or 640x480 (PAL) at 8bpp.
+    Video timings are locked to ensure a vertical refresh rate of 50Hz (PAL)
+    or 59.94 (NTSC)
+
+    Copyright (c) 2003 Matt T. Yourst <yourst@yourst.com>
+
+    Derived from drivers/video/vesafb.c
+    Portions (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de>
+
+    2.6 kernel port:
+    Copyright (C) 2004 Matthias Badaire
+
+    Copyright (C) 2004  Chris Kennedy <c@groovy.org>
+
+    Copyright (C) 2006  Ian Armstrong <ian@iarmst.demon.co.uk>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/fb.h>
+#include <linux/ivtvfb.h>
+#include <linux/slab.h>
+
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif
+
+#include "ivtv-driver.h"
+#include "ivtv-cards.h"
+#include "ivtv-i2c.h"
+#include "ivtv-udma.h"
+#include "ivtv-mailbox.h"
+#include "ivtv-firmware.h"
+
+/* card parameters */
+static int ivtvfb_card_id = -1;
+static int ivtvfb_debug = 0;
+static bool osd_laced;
+static int osd_depth;
+static int osd_upper;
+static int osd_left;
+static int osd_yres;
+static int osd_xres;
+
+module_param(ivtvfb_card_id, int, 0444);
+module_param_named(debug,ivtvfb_debug, int, 0644);
+module_param(osd_laced, bool, 0444);
+module_param(osd_depth, int, 0444);
+module_param(osd_upper, int, 0444);
+module_param(osd_left, int, 0444);
+module_param(osd_yres, int, 0444);
+module_param(osd_xres, int, 0444);
+
+MODULE_PARM_DESC(ivtvfb_card_id,
+		 "Only use framebuffer of the specified ivtv card (0-31)\n"
+		 "\t\t\tdefault -1: initialize all available framebuffers");
+
+MODULE_PARM_DESC(debug,
+		 "Debug level (bitmask). Default: errors only\n"
+		 "\t\t\t(debug = 3 gives full debugging)");
+
+/* Why upper, left, xres, yres, depth, laced ? To match terminology used
+   by fbset.
+   Why start at 1 for left & upper coordinate ? Because X doesn't allow 0 */
+
+MODULE_PARM_DESC(osd_laced,
+		 "Interlaced mode\n"
+		 "\t\t\t0=off\n"
+		 "\t\t\t1=on\n"
+		 "\t\t\tdefault off");
+
+MODULE_PARM_DESC(osd_depth,
+		 "Bits per pixel - 8, 16, 32\n"
+		 "\t\t\tdefault 8");
+
+MODULE_PARM_DESC(osd_upper,
+		 "Vertical start position\n"
+		 "\t\t\tdefault 0 (Centered)");
+
+MODULE_PARM_DESC(osd_left,
+		 "Horizontal start position\n"
+		 "\t\t\tdefault 0 (Centered)");
+
+MODULE_PARM_DESC(osd_yres,
+		 "Display height\n"
+		 "\t\t\tdefault 480 (PAL)\n"
+		 "\t\t\t        400 (NTSC)");
+
+MODULE_PARM_DESC(osd_xres,
+		 "Display width\n"
+		 "\t\t\tdefault 640");
+
+MODULE_AUTHOR("Kevin Thayer, Chris Kennedy, Hans Verkuil, John Harvey, Ian Armstrong");
+MODULE_LICENSE("GPL");
+
+/* --------------------------------------------------------------------- */
+
+#define IVTVFB_DBGFLG_WARN  (1 << 0)
+#define IVTVFB_DBGFLG_INFO  (1 << 1)
+
+#define IVTVFB_DEBUG(x, type, fmt, args...) \
+	do { \
+		if ((x) & ivtvfb_debug) \
+			printk(KERN_INFO "ivtvfb%d " type ": " fmt, itv->instance , ## args); \
+	} while (0)
+#define IVTVFB_DEBUG_WARN(fmt, args...)  IVTVFB_DEBUG(IVTVFB_DBGFLG_WARN, "warning", fmt , ## args)
+#define IVTVFB_DEBUG_INFO(fmt, args...)  IVTVFB_DEBUG(IVTVFB_DBGFLG_INFO, "info", fmt , ## args)
+
+/* Standard kernel messages */
+#define IVTVFB_ERR(fmt, args...)   printk(KERN_ERR  "ivtvfb%d: " fmt, itv->instance , ## args)
+#define IVTVFB_WARN(fmt, args...)  printk(KERN_WARNING  "ivtvfb%d: " fmt, itv->instance , ## args)
+#define IVTVFB_INFO(fmt, args...)  printk(KERN_INFO "ivtvfb%d: " fmt, itv->instance , ## args)
+
+/* --------------------------------------------------------------------- */
+
+#define IVTV_OSD_MAX_WIDTH  720
+#define IVTV_OSD_MAX_HEIGHT 576
+
+#define IVTV_OSD_BPP_8      0x00
+#define IVTV_OSD_BPP_16_444 0x03
+#define IVTV_OSD_BPP_16_555 0x02
+#define IVTV_OSD_BPP_16_565 0x01
+#define IVTV_OSD_BPP_32     0x04
+
+struct osd_info {
+	/* Physical base address */
+	unsigned long video_pbase;
+	/* Relative base address (relative to start of decoder memory) */
+	u32 video_rbase;
+	/* Mapped base address */
+	volatile char __iomem *video_vbase;
+	/* Buffer size */
+	u32 video_buffer_size;
+
+#ifdef CONFIG_MTRR
+	/* video_base rounded down as required by hardware MTRRs */
+	unsigned long fb_start_aligned_physaddr;
+	/* video_base rounded up as required by hardware MTRRs */
+	unsigned long fb_end_aligned_physaddr;
+#endif
+
+	/* Store the buffer offset */
+	int set_osd_coords_x;
+	int set_osd_coords_y;
+
+	/* Current dimensions (NOT VISIBLE SIZE!) */
+	int display_width;
+	int display_height;
+	int display_byte_stride;
+
+	/* Current bits per pixel */
+	int bits_per_pixel;
+	int bytes_per_pixel;
+
+	/* Frame buffer stuff */
+	struct fb_info ivtvfb_info;
+	struct fb_var_screeninfo ivtvfb_defined;
+	struct fb_fix_screeninfo ivtvfb_fix;
+
+	/* Used for a warm start */
+	struct fb_var_screeninfo fbvar_cur;
+	int blank_cur;
+	u32 palette_cur[256];
+	u32 pan_cur;
+};
+
+struct ivtv_osd_coords {
+	unsigned long offset;
+	unsigned long max_offset;
+	int pixel_stride;
+	int lines;
+	int x;
+	int y;
+};
+
+/* --------------------------------------------------------------------- */
+
+/* ivtv API calls for framebuffer related support */
+
+static int ivtvfb_get_framebuffer(struct ivtv *itv, u32 *fbbase,
+				       u32 *fblength)
+{
+	u32 data[CX2341X_MBOX_MAX_DATA];
+	int rc;
+
+	ivtv_firmware_check(itv, "ivtvfb_get_framebuffer");
+	rc = ivtv_vapi_result(itv, data, CX2341X_OSD_GET_FRAMEBUFFER, 0);
+	*fbbase = data[0];
+	*fblength = data[1];
+	return rc;
+}
+
+static int ivtvfb_get_osd_coords(struct ivtv *itv,
+				      struct ivtv_osd_coords *osd)
+{
+	struct osd_info *oi = itv->osd_info;
+	u32 data[CX2341X_MBOX_MAX_DATA];
+
+	ivtv_vapi_result(itv, data, CX2341X_OSD_GET_OSD_COORDS, 0);
+
+	osd->offset = data[0] - oi->video_rbase;
+	osd->max_offset = oi->display_width * oi->display_height * 4;
+	osd->pixel_stride = data[1];
+	osd->lines = data[2];
+	osd->x = data[3];
+	osd->y = data[4];
+	return 0;
+}
+
+static int ivtvfb_set_osd_coords(struct ivtv *itv, const struct ivtv_osd_coords *osd)
+{
+	struct osd_info *oi = itv->osd_info;
+
+	oi->display_width = osd->pixel_stride;
+	oi->display_byte_stride = osd->pixel_stride * oi->bytes_per_pixel;
+	oi->set_osd_coords_x += osd->x;
+	oi->set_osd_coords_y = osd->y;
+
+	return ivtv_vapi(itv, CX2341X_OSD_SET_OSD_COORDS, 5,
+			osd->offset + oi->video_rbase,
+			osd->pixel_stride,
+			osd->lines, osd->x, osd->y);
+}
+
+static int ivtvfb_set_display_window(struct ivtv *itv, struct v4l2_rect *ivtv_window)
+{
+	int osd_height_limit = itv->is_out_50hz ? 576 : 480;
+
+	/* Only fail if resolution too high, otherwise fudge the start coords. */
+	if ((ivtv_window->height > osd_height_limit) || (ivtv_window->width > IVTV_OSD_MAX_WIDTH))
+		return -EINVAL;
+
+	/* Ensure we don't exceed display limits */
+	if (ivtv_window->top + ivtv_window->height > osd_height_limit) {
+		IVTVFB_DEBUG_WARN("ivtv_ioctl_fb_set_display_window - Invalid height setting (%d, %d)\n",
+			ivtv_window->top, ivtv_window->height);
+		ivtv_window->top = osd_height_limit - ivtv_window->height;
+	}
+
+	if (ivtv_window->left + ivtv_window->width > IVTV_OSD_MAX_WIDTH) {
+		IVTVFB_DEBUG_WARN("ivtv_ioctl_fb_set_display_window - Invalid width setting (%d, %d)\n",
+			ivtv_window->left, ivtv_window->width);
+		ivtv_window->left = IVTV_OSD_MAX_WIDTH - ivtv_window->width;
+	}
+
+	/* Set the OSD origin */
+	write_reg((ivtv_window->top << 16) | ivtv_window->left, 0x02a04);
+
+	/* How much to display */
+	write_reg(((ivtv_window->top+ivtv_window->height) << 16) | (ivtv_window->left+ivtv_window->width), 0x02a08);
+
+	/* Pass this info back the yuv handler */
+	itv->yuv_info.osd_vis_w = ivtv_window->width;
+	itv->yuv_info.osd_vis_h = ivtv_window->height;
+	itv->yuv_info.osd_x_offset = ivtv_window->left;
+	itv->yuv_info.osd_y_offset = ivtv_window->top;
+
+	return 0;
+}
+
+static int ivtvfb_prep_dec_dma_to_device(struct ivtv *itv,
+				  unsigned long ivtv_dest_addr, void __user *userbuf,
+				  int size_in_bytes)
+{
+	DEFINE_WAIT(wait);
+	int got_sig = 0;
+
+	mutex_lock(&itv->udma.lock);
+	/* Map User DMA */
+	if (ivtv_udma_setup(itv, ivtv_dest_addr, userbuf, size_in_bytes) <= 0) {
+		mutex_unlock(&itv->udma.lock);
+		IVTVFB_WARN("ivtvfb_prep_dec_dma_to_device, "
+			       "Error with get_user_pages: %d bytes, %d pages returned\n",
+			       size_in_bytes, itv->udma.page_count);
+
+		/* get_user_pages must have failed completely */
+		return -EIO;
+	}
+
+	IVTVFB_DEBUG_INFO("ivtvfb_prep_dec_dma_to_device, %d bytes, %d pages\n",
+		       size_in_bytes, itv->udma.page_count);
+
+	ivtv_udma_prepare(itv);
+	prepare_to_wait(&itv->dma_waitq, &wait, TASK_INTERRUPTIBLE);
+	/* if no UDMA is pending and no UDMA is in progress, then the DMA
+	   is finished */
+	while (test_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags) ||
+	       test_bit(IVTV_F_I_UDMA, &itv->i_flags)) {
+		/* don't interrupt if the DMA is in progress but break off
+		   a still pending DMA. */
+		got_sig = signal_pending(current);
+		if (got_sig && test_and_clear_bit(IVTV_F_I_UDMA_PENDING, &itv->i_flags))
+			break;
+		got_sig = 0;
+		schedule();
+	}
+	finish_wait(&itv->dma_waitq, &wait);
+
+	/* Unmap Last DMA Xfer */
+	ivtv_udma_unmap(itv);
+	mutex_unlock(&itv->udma.lock);
+	if (got_sig) {
+		IVTV_DEBUG_INFO("User stopped OSD\n");
+		return -EINTR;
+	}
+
+	return 0;
+}
+
+static int ivtvfb_prep_frame(struct ivtv *itv, int cmd, void __user *source,
+			      unsigned long dest_offset, int count)
+{
+	DEFINE_WAIT(wait);
+	struct osd_info *oi = itv->osd_info;
+
+	/* Nothing to do */
+	if (count == 0) {
+		IVTVFB_DEBUG_WARN("ivtvfb_prep_frame: Nothing to do. count = 0\n");
+		return -EINVAL;
+	}
+
+	/* Check Total FB Size */
+	if ((dest_offset + count) > oi->video_buffer_size) {
+		IVTVFB_WARN("ivtvfb_prep_frame: Overflowing the framebuffer %ld, only %d available\n",
+			dest_offset + count, oi->video_buffer_size);
+		return -E2BIG;
+	}
+
+	/* Not fatal, but will have undesirable results */
+	if ((unsigned long)source & 3)
+		IVTVFB_WARN("ivtvfb_prep_frame: Source address not 32 bit aligned (0x%08lx)\n",
+			(unsigned long)source);
+
+	if (dest_offset & 3)
+		IVTVFB_WARN("ivtvfb_prep_frame: Dest offset not 32 bit aligned (%ld)\n", dest_offset);
+
+	if (count & 3)
+		IVTVFB_WARN("ivtvfb_prep_frame: Count not a multiple of 4 (%d)\n", count);
+
+	/* Check Source */
+	if (!access_ok(VERIFY_READ, source + dest_offset, count)) {
+		IVTVFB_WARN("Invalid userspace pointer 0x%08lx\n",
+			(unsigned long)source);
+
+		IVTVFB_DEBUG_WARN("access_ok() failed for offset 0x%08lx source 0x%08lx count %d\n",
+			dest_offset, (unsigned long)source,
+			count);
+		return -EINVAL;
+	}
+
+	/* OSD Address to send DMA to */
+	dest_offset += IVTV_DECODER_OFFSET + oi->video_rbase;
+
+	/* Fill Buffers */
+	return ivtvfb_prep_dec_dma_to_device(itv, dest_offset, source, count);
+}
+
+static ssize_t ivtvfb_write(struct fb_info *info, const char __user *buf,
+						size_t count, loff_t *ppos)
+{
+	unsigned long p = *ppos;
+	void *dst;
+	int err = 0;
+	int dma_err;
+	unsigned long total_size;
+	struct ivtv *itv = (struct ivtv *) info->par;
+	unsigned long dma_offset =
+			IVTV_DECODER_OFFSET + itv->osd_info->video_rbase;
+	unsigned long dma_size;
+	u16 lead = 0, tail = 0;
+
+	if (info->state != FBINFO_STATE_RUNNING)
+		return -EPERM;
+
+	total_size = info->screen_size;
+
+	if (total_size == 0)
+		total_size = info->fix.smem_len;
+
+	if (p > total_size)
+		return -EFBIG;
+
+	if (count > total_size) {
+		err = -EFBIG;
+		count = total_size;
+	}
+
+	if (count + p > total_size) {
+		if (!err)
+			err = -ENOSPC;
+		count = total_size - p;
+	}
+
+	dst = (void __force *) (info->screen_base + p);
+
+	if (info->fbops->fb_sync)
+		info->fbops->fb_sync(info);
+
+	/* If transfer size > threshold and both src/dst
+	addresses are aligned, use DMA */
+	if (count >= 4096 &&
+	    ((unsigned long)buf & 3) == ((unsigned long)dst & 3)) {
+		/* Odd address = can't DMA. Align */
+		if ((unsigned long)dst & 3) {
+			lead = 4 - ((unsigned long)dst & 3);
+			if (copy_from_user(dst, buf, lead))
+				return -EFAULT;
+			buf += lead;
+			dst += lead;
+		}
+		/* DMA resolution is 32 bits */
+		if ((count - lead) & 3)
+			tail = (count - lead) & 3;
+		/* DMA the data */
+		dma_size = count - lead - tail;
+		dma_err = ivtvfb_prep_dec_dma_to_device(itv,
+		       p + lead + dma_offset, (void __user *)buf, dma_size);
+		if (dma_err)
+			return dma_err;
+		dst += dma_size;
+		buf += dma_size;
+		/* Copy any leftover data */
+		if (tail && copy_from_user(dst, buf, tail))
+			return -EFAULT;
+	} else if (copy_from_user(dst, buf, count)) {
+		return -EFAULT;
+	}
+
+	if  (!err)
+		*ppos += count;
+
+	return (err) ? err : count;
+}
+
+static int ivtvfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
+{
+	DEFINE_WAIT(wait);
+	struct ivtv *itv = (struct ivtv *)info->par;
+	int rc = 0;
+
+	switch (cmd) {
+		case FBIOGET_VBLANK: {
+			struct fb_vblank vblank;
+			u32 trace;
+
+			memset(&vblank, 0, sizeof(struct fb_vblank));
+
+			vblank.flags = FB_VBLANK_HAVE_COUNT |FB_VBLANK_HAVE_VCOUNT |
+					FB_VBLANK_HAVE_VSYNC;
+			trace = read_reg(IVTV_REG_DEC_LINE_FIELD) >> 16;
+			if (itv->is_out_50hz && trace > 312)
+				trace -= 312;
+			else if (itv->is_out_60hz && trace > 262)
+				trace -= 262;
+			if (trace == 1)
+				vblank.flags |= FB_VBLANK_VSYNCING;
+			vblank.count = itv->last_vsync_field;
+			vblank.vcount = trace;
+			vblank.hcount = 0;
+			if (copy_to_user((void __user *)arg, &vblank, sizeof(vblank)))
+				return -EFAULT;
+			return 0;
+		}
+
+		case FBIO_WAITFORVSYNC:
+			prepare_to_wait(&itv->vsync_waitq, &wait, TASK_INTERRUPTIBLE);
+			if (!schedule_timeout(msecs_to_jiffies(50)))
+				rc = -ETIMEDOUT;
+			finish_wait(&itv->vsync_waitq, &wait);
+			return rc;
+
+		case IVTVFB_IOC_DMA_FRAME: {
+			struct ivtvfb_dma_frame args;
+
+			IVTVFB_DEBUG_INFO("IVTVFB_IOC_DMA_FRAME\n");
+			if (copy_from_user(&args, (void __user *)arg, sizeof(args)))
+				return -EFAULT;
+
+			return ivtvfb_prep_frame(itv, cmd, args.source, args.dest_offset, args.count);
+		}
+
+		default:
+			IVTVFB_DEBUG_INFO("Unknown ioctl %08x\n", cmd);
+			return -EINVAL;
+	}
+	return 0;
+}
+
+/* Framebuffer device handling */
+
+static int ivtvfb_set_var(struct ivtv *itv, struct fb_var_screeninfo *var)
+{
+	struct osd_info *oi = itv->osd_info;
+	struct ivtv_osd_coords ivtv_osd;
+	struct v4l2_rect ivtv_window;
+	int osd_mode = -1;
+
+	IVTVFB_DEBUG_INFO("ivtvfb_set_var\n");
+
+	/* Select color space */
+	if (var->nonstd) /* YUV */
+		write_reg(read_reg(0x02a00) | 0x0002000, 0x02a00);
+	else /* RGB  */
+		write_reg(read_reg(0x02a00) & ~0x0002000, 0x02a00);
+
+	/* Set the color mode */
+	switch (var->bits_per_pixel) {
+		case 8:
+			osd_mode = IVTV_OSD_BPP_8;
+			break;
+		case 32:
+			osd_mode = IVTV_OSD_BPP_32;
+			break;
+		case 16:
+			switch (var->green.length) {
+			case 4:
+				osd_mode = IVTV_OSD_BPP_16_444;
+				break;
+			case 5:
+				osd_mode = IVTV_OSD_BPP_16_555;
+				break;
+			case 6:
+				osd_mode = IVTV_OSD_BPP_16_565;
+				break;
+			default:
+				IVTVFB_DEBUG_WARN("ivtvfb_set_var - Invalid bpp\n");
+			}
+			break;
+		default:
+			IVTVFB_DEBUG_WARN("ivtvfb_set_var - Invalid bpp\n");
+	}
+
+	/* Set video mode. Although rare, the display can become scrambled even
+	   if we don't change mode. Always 'bounce' to osd_mode via mode 0 */
+	if (osd_mode != -1) {
+		ivtv_vapi(itv, CX2341X_OSD_SET_PIXEL_FORMAT, 1, 0);
+		ivtv_vapi(itv, CX2341X_OSD_SET_PIXEL_FORMAT, 1, osd_mode);
+	}
+
+	oi->bits_per_pixel = var->bits_per_pixel;
+	oi->bytes_per_pixel = var->bits_per_pixel / 8;
+
+	/* Set the flicker filter */
+	switch (var->vmode & FB_VMODE_MASK) {
+		case FB_VMODE_NONINTERLACED: /* Filter on */
+			ivtv_vapi(itv, CX2341X_OSD_SET_FLICKER_STATE, 1, 1);
+			break;
+		case FB_VMODE_INTERLACED: /* Filter off */
+			ivtv_vapi(itv, CX2341X_OSD_SET_FLICKER_STATE, 1, 0);
+			break;
+		default:
+			IVTVFB_DEBUG_WARN("ivtvfb_set_var - Invalid video mode\n");
+	}
+
+	/* Read the current osd info */
+	ivtvfb_get_osd_coords(itv, &ivtv_osd);
+
+	/* Now set the OSD to the size we want */
+	ivtv_osd.pixel_stride = var->xres_virtual;
+	ivtv_osd.lines = var->yres_virtual;
+	ivtv_osd.x = 0;
+	ivtv_osd.y = 0;
+	ivtvfb_set_osd_coords(itv, &ivtv_osd);
+
+	/* Can't seem to find the right API combo for this.
+	   Use another function which does what we need through direct register access. */
+	ivtv_window.width = var->xres;
+	ivtv_window.height = var->yres;
+
+	/* Minimum margin cannot be 0, as X won't allow such a mode */
+	if (!var->upper_margin)
+		var->upper_margin++;
+	if (!var->left_margin)
+		var->left_margin++;
+	ivtv_window.top = var->upper_margin - 1;
+	ivtv_window.left = var->left_margin - 1;
+
+	ivtvfb_set_display_window(itv, &ivtv_window);
+
+	/* Pass screen size back to yuv handler */
+	itv->yuv_info.osd_full_w = ivtv_osd.pixel_stride;
+	itv->yuv_info.osd_full_h = ivtv_osd.lines;
+
+	/* Force update of yuv registers */
+	itv->yuv_info.yuv_forced_update = 1;
+
+	/* Keep a copy of these settings */
+	memcpy(&oi->fbvar_cur, var, sizeof(oi->fbvar_cur));
+
+	IVTVFB_DEBUG_INFO("Display size: %dx%d (virtual %dx%d) @ %dbpp\n",
+		      var->xres, var->yres,
+		      var->xres_virtual, var->yres_virtual,
+		      var->bits_per_pixel);
+
+	IVTVFB_DEBUG_INFO("Display position: %d, %d\n",
+		      var->left_margin, var->upper_margin);
+
+	IVTVFB_DEBUG_INFO("Display filter: %s\n",
+			(var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED ? "on" : "off");
+	IVTVFB_DEBUG_INFO("Color space: %s\n", var->nonstd ? "YUV" : "RGB");
+
+	return 0;
+}
+
+static int ivtvfb_get_fix(struct ivtv *itv, struct fb_fix_screeninfo *fix)
+{
+	struct osd_info *oi = itv->osd_info;
+
+	IVTVFB_DEBUG_INFO("ivtvfb_get_fix\n");
+	memset(fix, 0, sizeof(struct fb_fix_screeninfo));
+	strlcpy(fix->id, "cx23415 TV out", sizeof(fix->id));
+	fix->smem_start = oi->video_pbase;
+	fix->smem_len = oi->video_buffer_size;
+	fix->type = FB_TYPE_PACKED_PIXELS;
+	fix->visual = (oi->bits_per_pixel == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
+	fix->xpanstep = 1;
+	fix->ypanstep = 1;
+	fix->ywrapstep = 0;
+	fix->line_length = oi->display_byte_stride;
+	fix->accel = FB_ACCEL_NONE;
+	return 0;
+}
+
+/* Check the requested display mode, returning -EINVAL if we can't
+   handle it. */
+
+static int _ivtvfb_check_var(struct fb_var_screeninfo *var, struct ivtv *itv)
+{
+	struct osd_info *oi = itv->osd_info;
+	int osd_height_limit;
+	u32 pixclock, hlimit, vlimit;
+
+	IVTVFB_DEBUG_INFO("ivtvfb_check_var\n");
+
+	/* Set base references for mode calcs. */
+	if (itv->is_out_50hz) {
+		pixclock = 84316;
+		hlimit = 776;
+		vlimit = 591;
+		osd_height_limit = 576;
+	}
+	else {
+		pixclock = 83926;
+		hlimit = 776;
+		vlimit = 495;
+		osd_height_limit = 480;
+	}
+
+	if (var->bits_per_pixel == 8 || var->bits_per_pixel == 32) {
+		var->transp.offset = 24;
+		var->transp.length = 8;
+		var->red.offset = 16;
+		var->red.length = 8;
+		var->green.offset = 8;
+		var->green.length = 8;
+		var->blue.offset = 0;
+		var->blue.length = 8;
+	}
+	else if (var->bits_per_pixel == 16) {
+		/* To find out the true mode, check green length */
+		switch (var->green.length) {
+			case 4:
+				var->red.offset = 8;
+				var->red.length = 4;
+				var->green.offset = 4;
+				var->green.length = 4;
+				var->blue.offset = 0;
+				var->blue.length = 4;
+				var->transp.offset = 12;
+				var->transp.length = 1;
+				break;
+			case 5:
+				var->red.offset = 10;
+				var->red.length = 5;
+				var->green.offset = 5;
+				var->green.length = 5;
+				var->blue.offset = 0;
+				var->blue.length = 5;
+				var->transp.offset = 15;
+				var->transp.length = 1;
+				break;
+			default:
+				var->red.offset = 11;
+				var->red.length = 5;
+				var->green.offset = 5;
+				var->green.length = 6;
+				var->blue.offset = 0;
+				var->blue.length = 5;
+				var->transp.offset = 0;
+				var->transp.length = 0;
+				break;
+		}
+	}
+	else {
+		IVTVFB_DEBUG_WARN("Invalid colour mode: %d\n", var->bits_per_pixel);
+		return -EINVAL;
+	}
+
+	/* Check the resolution */
+	if (var->xres > IVTV_OSD_MAX_WIDTH || var->yres > osd_height_limit) {
+		IVTVFB_DEBUG_WARN("Invalid resolution: %dx%d\n",
+				var->xres, var->yres);
+		return -EINVAL;
+	}
+
+	/* Max horizontal size is 1023 @ 32bpp, 2046 & 16bpp, 4092 @ 8bpp */
+	if (var->xres_virtual > 4095 / (var->bits_per_pixel / 8) ||
+	    var->xres_virtual * var->yres_virtual * (var->bits_per_pixel / 8) > oi->video_buffer_size ||
+	    var->xres_virtual < var->xres ||
+	    var->yres_virtual < var->yres) {
+		IVTVFB_DEBUG_WARN("Invalid virtual resolution: %dx%d\n",
+			var->xres_virtual, var->yres_virtual);
+		return -EINVAL;
+	}
+
+	/* Some extra checks if in 8 bit mode */
+	if (var->bits_per_pixel == 8) {
+		/* Width must be a multiple of 4 */
+		if (var->xres & 3) {
+			IVTVFB_DEBUG_WARN("Invalid resolution for 8bpp: %d\n", var->xres);
+			return -EINVAL;
+		}
+		if (var->xres_virtual & 3) {
+			IVTVFB_DEBUG_WARN("Invalid virtual resolution for 8bpp: %d)\n", var->xres_virtual);
+			return -EINVAL;
+		}
+	}
+	else if (var->bits_per_pixel == 16) {
+		/* Width must be a multiple of 2 */
+		if (var->xres & 1) {
+			IVTVFB_DEBUG_WARN("Invalid resolution for 16bpp: %d\n", var->xres);
+			return -EINVAL;
+		}
+		if (var->xres_virtual & 1) {
+			IVTVFB_DEBUG_WARN("Invalid virtual resolution for 16bpp: %d)\n", var->xres_virtual);
+			return -EINVAL;
+		}
+	}
+
+	/* Now check the offsets */
+	if (var->xoffset >= var->xres_virtual || var->yoffset >= var->yres_virtual) {
+		IVTVFB_DEBUG_WARN("Invalid offset: %d (%d) %d (%d)\n",
+			var->xoffset, var->xres_virtual, var->yoffset, var->yres_virtual);
+		return -EINVAL;
+	}
+
+	/* Check pixel format */
+	if (var->nonstd > 1) {
+		IVTVFB_DEBUG_WARN("Invalid nonstd % d\n", var->nonstd);
+		return -EINVAL;
+	}
+
+	/* Check video mode */
+	if (((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED) &&
+		((var->vmode & FB_VMODE_MASK) != FB_VMODE_INTERLACED)) {
+		IVTVFB_DEBUG_WARN("Invalid video mode: %d\n", var->vmode & FB_VMODE_MASK);
+		return -EINVAL;
+	}
+
+	/* Check the left & upper margins
+	   If the margins are too large, just center the screen
+	   (enforcing margins causes too many problems) */
+
+	if (var->left_margin + var->xres > IVTV_OSD_MAX_WIDTH + 1)
+		var->left_margin = 1 + ((IVTV_OSD_MAX_WIDTH - var->xres) / 2);
+
+	if (var->upper_margin + var->yres > (itv->is_out_50hz ? 577 : 481))
+		var->upper_margin = 1 + (((itv->is_out_50hz ? 576 : 480) -
+			var->yres) / 2);
+
+	/* Maintain overall 'size' for a constant refresh rate */
+	var->right_margin = hlimit - var->left_margin - var->xres;
+	var->lower_margin = vlimit - var->upper_margin - var->yres;
+
+	/* Fixed sync times */
+	var->hsync_len = 24;
+	var->vsync_len = 2;
+
+	/* Non-interlaced / interlaced mode is used to switch the OSD filter
+	   on or off. Adjust the clock timings to maintain a constant
+	   vertical refresh rate. */
+	if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED)
+		var->pixclock = pixclock / 2;
+	else
+		var->pixclock = pixclock;
+
+	itv->osd_rect.width = var->xres;
+	itv->osd_rect.height = var->yres;
+
+	IVTVFB_DEBUG_INFO("Display size: %dx%d (virtual %dx%d) @ %dbpp\n",
+		      var->xres, var->yres,
+		      var->xres_virtual, var->yres_virtual,
+		      var->bits_per_pixel);
+
+	IVTVFB_DEBUG_INFO("Display position: %d, %d\n",
+		      var->left_margin, var->upper_margin);
+
+	IVTVFB_DEBUG_INFO("Display filter: %s\n",
+			(var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED ? "on" : "off");
+	IVTVFB_DEBUG_INFO("Color space: %s\n", var->nonstd ? "YUV" : "RGB");
+	return 0;
+}
+
+static int ivtvfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	struct ivtv *itv = (struct ivtv *) info->par;
+	IVTVFB_DEBUG_INFO("ivtvfb_check_var\n");
+	return _ivtvfb_check_var(var, itv);
+}
+
+static int ivtvfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	u32 osd_pan_index;
+	struct ivtv *itv = (struct ivtv *) info->par;
+
+	if (var->yoffset + info->var.yres > info->var.yres_virtual ||
+	    var->xoffset + info->var.xres > info->var.xres_virtual)
+		return -EINVAL;
+
+	osd_pan_index = var->yoffset * info->fix.line_length
+		      + var->xoffset * info->var.bits_per_pixel / 8;
+	write_reg(osd_pan_index, 0x02A0C);
+
+	/* Pass this info back the yuv handler */
+	itv->yuv_info.osd_x_pan = var->xoffset;
+	itv->yuv_info.osd_y_pan = var->yoffset;
+	/* Force update of yuv registers */
+	itv->yuv_info.yuv_forced_update = 1;
+	/* Remember this value */
+	itv->osd_info->pan_cur = osd_pan_index;
+	return 0;
+}
+
+static int ivtvfb_set_par(struct fb_info *info)
+{
+	int rc = 0;
+	struct ivtv *itv = (struct ivtv *) info->par;
+
+	IVTVFB_DEBUG_INFO("ivtvfb_set_par\n");
+
+	rc = ivtvfb_set_var(itv, &info->var);
+	ivtvfb_pan_display(&info->var, info);
+	ivtvfb_get_fix(itv, &info->fix);
+	ivtv_firmware_check(itv, "ivtvfb_set_par");
+	return rc;
+}
+
+static int ivtvfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+				unsigned blue, unsigned transp,
+				struct fb_info *info)
+{
+	u32 color, *palette;
+	struct ivtv *itv = (struct ivtv *)info->par;
+
+	if (regno >= info->cmap.len)
+		return -EINVAL;
+
+	color = ((transp & 0xFF00) << 16) |((red & 0xFF00) << 8) | (green & 0xFF00) | ((blue & 0xFF00) >> 8);
+	if (info->var.bits_per_pixel <= 8) {
+		write_reg(regno, 0x02a30);
+		write_reg(color, 0x02a34);
+		itv->osd_info->palette_cur[regno] = color;
+		return 0;
+	}
+	if (regno >= 16)
+		return -EINVAL;
+
+	palette = info->pseudo_palette;
+	if (info->var.bits_per_pixel == 16) {
+		switch (info->var.green.length) {
+			case 4:
+				color = ((red & 0xf000) >> 4) |
+					((green & 0xf000) >> 8) |
+					((blue & 0xf000) >> 12);
+				break;
+			case 5:
+				color = ((red & 0xf800) >> 1) |
+					((green & 0xf800) >> 6) |
+					((blue & 0xf800) >> 11);
+				break;
+			case 6:
+				color = (red & 0xf800 ) |
+					((green & 0xfc00) >> 5) |
+					((blue & 0xf800) >> 11);
+				break;
+		}
+	}
+	palette[regno] = color;
+	return 0;
+}
+
+/* We don't really support blanking. All this does is enable or
+   disable the OSD. */
+static int ivtvfb_blank(int blank_mode, struct fb_info *info)
+{
+	struct ivtv *itv = (struct ivtv *)info->par;
+
+	IVTVFB_DEBUG_INFO("Set blanking mode : %d\n", blank_mode);
+	switch (blank_mode) {
+	case FB_BLANK_UNBLANK:
+		ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 1);
+		ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 1);
+		break;
+	case FB_BLANK_NORMAL:
+	case FB_BLANK_HSYNC_SUSPEND:
+	case FB_BLANK_VSYNC_SUSPEND:
+		ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 0);
+		ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 1);
+		break;
+	case FB_BLANK_POWERDOWN:
+		ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 0);
+		ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 0);
+		break;
+	}
+	itv->osd_info->blank_cur = blank_mode;
+	return 0;
+}
+
+static struct fb_ops ivtvfb_ops = {
+	.owner = THIS_MODULE,
+	.fb_write       = ivtvfb_write,
+	.fb_check_var   = ivtvfb_check_var,
+	.fb_set_par     = ivtvfb_set_par,
+	.fb_setcolreg   = ivtvfb_setcolreg,
+	.fb_fillrect    = cfb_fillrect,
+	.fb_copyarea    = cfb_copyarea,
+	.fb_imageblit   = cfb_imageblit,
+	.fb_cursor      = NULL,
+	.fb_ioctl       = ivtvfb_ioctl,
+	.fb_pan_display = ivtvfb_pan_display,
+	.fb_blank       = ivtvfb_blank,
+};
+
+/* Restore hardware after firmware restart */
+static void ivtvfb_restore(struct ivtv *itv)
+{
+	struct osd_info *oi = itv->osd_info;
+	int i;
+
+	ivtvfb_set_var(itv, &oi->fbvar_cur);
+	ivtvfb_blank(oi->blank_cur, &oi->ivtvfb_info);
+	for (i = 0; i < 256; i++) {
+		write_reg(i, 0x02a30);
+		write_reg(oi->palette_cur[i], 0x02a34);
+	}
+	write_reg(oi->pan_cur, 0x02a0c);
+}
+
+/* Initialization */
+
+
+/* Setup our initial video mode */
+static int ivtvfb_init_vidmode(struct ivtv *itv)
+{
+	struct osd_info *oi = itv->osd_info;
+	struct v4l2_rect start_window;
+	int max_height;
+
+	/* Color mode */
+
+	if (osd_depth != 8 && osd_depth != 16 && osd_depth != 32)
+		osd_depth = 8;
+	oi->bits_per_pixel = osd_depth;
+	oi->bytes_per_pixel = oi->bits_per_pixel / 8;
+
+	/* Horizontal size & position */
+
+	if (osd_xres > 720)
+		osd_xres = 720;
+
+	/* Must be a multiple of 4 for 8bpp & 2 for 16bpp */
+	if (osd_depth == 8)
+		osd_xres &= ~3;
+	else if (osd_depth == 16)
+		osd_xres &= ~1;
+
+	start_window.width = osd_xres ? osd_xres : 640;
+
+	/* Check horizontal start (osd_left). */
+	if (osd_left && osd_left + start_window.width > 721) {
+		IVTVFB_ERR("Invalid osd_left - assuming default\n");
+		osd_left = 0;
+	}
+
+	/* Hardware coords start at 0, user coords start at 1. */
+	osd_left--;
+
+	start_window.left = osd_left >= 0 ?
+		 osd_left : ((IVTV_OSD_MAX_WIDTH - start_window.width) / 2);
+
+	oi->display_byte_stride =
+			start_window.width * oi->bytes_per_pixel;
+
+	/* Vertical size & position */
+
+	max_height = itv->is_out_50hz ? 576 : 480;
+
+	if (osd_yres > max_height)
+		osd_yres = max_height;
+
+	start_window.height = osd_yres ?
+		osd_yres : itv->is_out_50hz ? 480 : 400;
+
+	/* Check vertical start (osd_upper). */
+	if (osd_upper + start_window.height > max_height + 1) {
+		IVTVFB_ERR("Invalid osd_upper - assuming default\n");
+		osd_upper = 0;
+	}
+
+	/* Hardware coords start at 0, user coords start at 1. */
+	osd_upper--;
+
+	start_window.top = osd_upper >= 0 ? osd_upper : ((max_height - start_window.height) / 2);
+
+	oi->display_width = start_window.width;
+	oi->display_height = start_window.height;
+
+	/* Generate a valid fb_var_screeninfo */
+
+	oi->ivtvfb_defined.xres = oi->display_width;
+	oi->ivtvfb_defined.yres = oi->display_height;
+	oi->ivtvfb_defined.xres_virtual = oi->display_width;
+	oi->ivtvfb_defined.yres_virtual = oi->display_height;
+	oi->ivtvfb_defined.bits_per_pixel = oi->bits_per_pixel;
+	oi->ivtvfb_defined.vmode = (osd_laced ? FB_VMODE_INTERLACED : FB_VMODE_NONINTERLACED);
+	oi->ivtvfb_defined.left_margin = start_window.left + 1;
+	oi->ivtvfb_defined.upper_margin = start_window.top + 1;
+	oi->ivtvfb_defined.accel_flags = FB_ACCEL_NONE;
+	oi->ivtvfb_defined.nonstd = 0;
+
+	/* We've filled in the most data, let the usual mode check
+	   routine fill in the rest. */
+	_ivtvfb_check_var(&oi->ivtvfb_defined, itv);
+
+	/* Generate valid fb_fix_screeninfo */
+
+	ivtvfb_get_fix(itv, &oi->ivtvfb_fix);
+
+	/* Generate valid fb_info */
+
+	oi->ivtvfb_info.node = -1;
+	oi->ivtvfb_info.flags = FBINFO_FLAG_DEFAULT;
+	oi->ivtvfb_info.fbops = &ivtvfb_ops;
+	oi->ivtvfb_info.par = itv;
+	oi->ivtvfb_info.var = oi->ivtvfb_defined;
+	oi->ivtvfb_info.fix = oi->ivtvfb_fix;
+	oi->ivtvfb_info.screen_base = (u8 __iomem *)oi->video_vbase;
+	oi->ivtvfb_info.fbops = &ivtvfb_ops;
+
+	/* Supply some monitor specs. Bogus values will do for now */
+	oi->ivtvfb_info.monspecs.hfmin = 8000;
+	oi->ivtvfb_info.monspecs.hfmax = 70000;
+	oi->ivtvfb_info.monspecs.vfmin = 10;
+	oi->ivtvfb_info.monspecs.vfmax = 100;
+
+	/* Allocate color map */
+	if (fb_alloc_cmap(&oi->ivtvfb_info.cmap, 256, 1)) {
+		IVTVFB_ERR("abort, unable to alloc cmap\n");
+		return -ENOMEM;
+	}
+
+	/* Allocate the pseudo palette */
+	oi->ivtvfb_info.pseudo_palette =
+		kmalloc(sizeof(u32) * 16, GFP_KERNEL|__GFP_NOWARN);
+
+	if (!oi->ivtvfb_info.pseudo_palette) {
+		IVTVFB_ERR("abort, unable to alloc pseudo palette\n");
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+/* Find OSD buffer base & size. Add to mtrr. Zero osd buffer. */
+
+static int ivtvfb_init_io(struct ivtv *itv)
+{
+	struct osd_info *oi = itv->osd_info;
+
+	mutex_lock(&itv->serialize_lock);
+	if (ivtv_init_on_first_open(itv)) {
+		mutex_unlock(&itv->serialize_lock);
+		IVTVFB_ERR("Failed to initialize ivtv\n");
+		return -ENXIO;
+	}
+	mutex_unlock(&itv->serialize_lock);
+
+	if (ivtvfb_get_framebuffer(itv, &oi->video_rbase,
+					&oi->video_buffer_size) < 0) {
+		IVTVFB_ERR("Firmware failed to respond\n");
+		return -EIO;
+	}
+
+	/* The osd buffer size depends on the number of video buffers allocated
+	   on the PVR350 itself. For now we'll hardcode the smallest osd buffer
+	   size to prevent any overlap. */
+	oi->video_buffer_size = 1704960;
+
+	oi->video_pbase = itv->base_addr + IVTV_DECODER_OFFSET + oi->video_rbase;
+	oi->video_vbase = itv->dec_mem + oi->video_rbase;
+
+	if (!oi->video_vbase) {
+		IVTVFB_ERR("abort, video memory 0x%x @ 0x%lx isn't mapped!\n",
+		     oi->video_buffer_size, oi->video_pbase);
+		return -EIO;
+	}
+
+	IVTVFB_INFO("Framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",
+			oi->video_pbase, oi->video_vbase,
+			oi->video_buffer_size / 1024);
+
+#ifdef CONFIG_MTRR
+	{
+		/* Find the largest power of two that maps the whole buffer */
+		int size_shift = 31;
+
+		while (!(oi->video_buffer_size & (1 << size_shift))) {
+			size_shift--;
+		}
+		size_shift++;
+		oi->fb_start_aligned_physaddr = oi->video_pbase & ~((1 << size_shift) - 1);
+		oi->fb_end_aligned_physaddr = oi->video_pbase + oi->video_buffer_size;
+		oi->fb_end_aligned_physaddr += (1 << size_shift) - 1;
+		oi->fb_end_aligned_physaddr &= ~((1 << size_shift) - 1);
+		if (mtrr_add(oi->fb_start_aligned_physaddr,
+			oi->fb_end_aligned_physaddr - oi->fb_start_aligned_physaddr,
+			     MTRR_TYPE_WRCOMB, 1) < 0) {
+			IVTVFB_INFO("disabled mttr\n");
+			oi->fb_start_aligned_physaddr = 0;
+			oi->fb_end_aligned_physaddr = 0;
+		}
+	}
+#endif
+
+	/* Blank the entire osd. */
+	memset_io(oi->video_vbase, 0, oi->video_buffer_size);
+
+	return 0;
+}
+
+/* Release any memory we've grabbed & remove mtrr entry */
+static void ivtvfb_release_buffers (struct ivtv *itv)
+{
+	struct osd_info *oi = itv->osd_info;
+
+	/* Release cmap */
+	if (oi->ivtvfb_info.cmap.len)
+		fb_dealloc_cmap(&oi->ivtvfb_info.cmap);
+
+	/* Release pseudo palette */
+	if (oi->ivtvfb_info.pseudo_palette)
+		kfree(oi->ivtvfb_info.pseudo_palette);
+
+#ifdef CONFIG_MTRR
+	if (oi->fb_end_aligned_physaddr) {
+		mtrr_del(-1, oi->fb_start_aligned_physaddr,
+			oi->fb_end_aligned_physaddr - oi->fb_start_aligned_physaddr);
+	}
+#endif
+
+	kfree(oi);
+	itv->osd_info = NULL;
+}
+
+/* Initialize the specified card */
+
+static int ivtvfb_init_card(struct ivtv *itv)
+{
+	int rc;
+
+	if (itv->osd_info) {
+		IVTVFB_ERR("Card %d already initialised\n", ivtvfb_card_id);
+		return -EBUSY;
+	}
+
+	itv->osd_info = kzalloc(sizeof(struct osd_info),
+					GFP_ATOMIC|__GFP_NOWARN);
+	if (itv->osd_info == NULL) {
+		IVTVFB_ERR("Failed to allocate memory for osd_info\n");
+		return -ENOMEM;
+	}
+
+	/* Find & setup the OSD buffer */
+	rc = ivtvfb_init_io(itv);
+	if (rc) {
+		ivtvfb_release_buffers(itv);
+		return rc;
+	}
+
+	/* Set the startup video mode information */
+	if ((rc = ivtvfb_init_vidmode(itv))) {
+		ivtvfb_release_buffers(itv);
+		return rc;
+	}
+
+	/* Register the framebuffer */
+	if (register_framebuffer(&itv->osd_info->ivtvfb_info) < 0) {
+		ivtvfb_release_buffers(itv);
+		return -EINVAL;
+	}
+
+	itv->osd_video_pbase = itv->osd_info->video_pbase;
+
+	/* Set the card to the requested mode */
+	ivtvfb_set_par(&itv->osd_info->ivtvfb_info);
+
+	/* Set color 0 to black */
+	write_reg(0, 0x02a30);
+	write_reg(0, 0x02a34);
+
+	/* Enable the osd */
+	ivtvfb_blank(FB_BLANK_UNBLANK, &itv->osd_info->ivtvfb_info);
+
+	/* Enable restart */
+	itv->ivtvfb_restore = ivtvfb_restore;
+
+	/* Allocate DMA */
+	ivtv_udma_alloc(itv);
+	return 0;
+
+}
+
+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, v4l2_dev);
+
+	if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) {
+		if (ivtvfb_init_card(itv) == 0) {
+			IVTVFB_INFO("Framebuffer registered on %s\n",
+					itv->v4l2_dev.name);
+			(*(int *)p)++;
+		}
+	}
+	return 0;
+}
+
+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, v4l2_dev);
+	struct osd_info *oi = itv->osd_info;
+
+	if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) {
+		if (unregister_framebuffer(&itv->osd_info->ivtvfb_info)) {
+			IVTVFB_WARN("Framebuffer %d is in use, cannot unload\n",
+				       itv->instance);
+			return 0;
+		}
+		IVTVFB_INFO("Unregister framebuffer %d\n", itv->instance);
+		itv->ivtvfb_restore = NULL;
+		ivtvfb_blank(FB_BLANK_VSYNC_SUSPEND, &oi->ivtvfb_info);
+		ivtvfb_release_buffers(itv);
+		itv->osd_video_pbase = 0;
+	}
+	return 0;
+}
+
+static int __init ivtvfb_init(void)
+{
+	struct device_driver *drv;
+	int registered = 0;
+	int err;
+
+	if (ivtvfb_card_id < -1 || ivtvfb_card_id >= IVTV_MAX_CARDS) {
+		printk(KERN_ERR "ivtvfb:  ivtvfb_card_id parameter is out of range (valid range: -1 - %d)\n",
+		     IVTV_MAX_CARDS - 1);
+		return -EINVAL;
+	}
+
+	drv = driver_find("ivtv", &pci_bus_type);
+	err = driver_for_each_device(drv, NULL, &registered, ivtvfb_callback_init);
+	(void)err;	/* suppress compiler warning */
+	if (!registered) {
+		printk(KERN_ERR "ivtvfb:  no cards found\n");
+		return -ENODEV;
+	}
+	return 0;
+}
+
+static void ivtvfb_cleanup(void)
+{
+	struct device_driver *drv;
+	int err;
+
+	printk(KERN_INFO "ivtvfb:  Unloading framebuffer module\n");
+
+	drv = driver_find("ivtv", &pci_bus_type);
+	err = driver_for_each_device(drv, NULL, NULL, ivtvfb_callback_cleanup);
+	(void)err;	/* suppress compiler warning */
+}
+
+module_init(ivtvfb_init);
+module_exit(ivtvfb_cleanup);
diff --git a/drivers/media/pci/mantis/Kconfig b/drivers/media/pci/mantis/Kconfig
new file mode 100644
index 0000000..d3cc216
--- /dev/null
+++ b/drivers/media/pci/mantis/Kconfig
@@ -0,0 +1,38 @@
+config MANTIS_CORE
+	tristate "Mantis/Hopper PCI bridge based devices"
+	depends on PCI && I2C && INPUT && RC_CORE
+
+	help
+	  Support for PCI cards based on the Mantis and Hopper PCi bridge.
+
+	  Say Y if you own such a device and want to use it.
+
+config DVB_MANTIS
+	tristate "MANTIS based cards"
+	depends on MANTIS_CORE && DVB_CORE && PCI && I2C
+	select DVB_MB86A16 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_ZL10353 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_STV0299 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_LNBP21 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_STB0899 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_STB6100 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_TDA665x if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_TDA10021 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_TDA10023 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_PLL
+	help
+	  Support for PCI cards based on the Mantis PCI bridge.
+	  Say Y when you have a Mantis based DVB card and want to use it.
+
+	  If unsure say N.
+
+config DVB_HOPPER
+	tristate "HOPPER based cards"
+	depends on MANTIS_CORE && DVB_CORE && PCI && I2C
+	select DVB_ZL10353 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_PLL
+	help
+	  Support for PCI cards based on the Hopper  PCI bridge.
+	  Say Y when you have a Hopper based DVB card and want to use it.
+
+	  If unsure say N
diff --git a/drivers/media/pci/mantis/Makefile b/drivers/media/pci/mantis/Makefile
new file mode 100644
index 0000000..f715051
--- /dev/null
+++ b/drivers/media/pci/mantis/Makefile
@@ -0,0 +1,28 @@
+mantis_core-objs :=	mantis_ioc.o	\
+			mantis_uart.o	\
+			mantis_dma.o	\
+			mantis_pci.o	\
+			mantis_i2c.o	\
+			mantis_dvb.o	\
+			mantis_evm.o	\
+			mantis_hif.o	\
+			mantis_ca.o	\
+			mantis_pcmcia.o	\
+			mantis_input.o
+
+mantis-objs	:=	mantis_cards.o	\
+			mantis_vp1033.o	\
+			mantis_vp1034.o	\
+			mantis_vp1041.o	\
+			mantis_vp2033.o	\
+			mantis_vp2040.o	\
+			mantis_vp3030.o
+
+hopper-objs	:=	hopper_cards.o	\
+			hopper_vp3028.o
+
+obj-$(CONFIG_MANTIS_CORE)	+= mantis_core.o
+obj-$(CONFIG_DVB_MANTIS)	+= mantis.o
+obj-$(CONFIG_DVB_HOPPER)	+= hopper.o
+
+ccflags-y += -Idrivers/media/dvb-core/ -Idrivers/media/dvb-frontends/
diff --git a/drivers/media/pci/mantis/hopper_cards.c b/drivers/media/pci/mantis/hopper_cards.c
new file mode 100644
index 0000000..cc0251e
--- /dev/null
+++ b/drivers/media/pci/mantis/hopper_cards.c
@@ -0,0 +1,277 @@
+/*
+	Hopper PCI bridge driver
+
+	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <asm/irq.h>
+#include <linux/interrupt.h>
+
+#include "dmxdev.h"
+#include "dvbdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dvb_net.h"
+
+#include "mantis_common.h"
+#include "hopper_vp3028.h"
+#include "mantis_dma.h"
+#include "mantis_dvb.h"
+#include "mantis_uart.h"
+#include "mantis_ioc.h"
+#include "mantis_pci.h"
+#include "mantis_i2c.h"
+#include "mantis_reg.h"
+
+static unsigned int verbose;
+module_param(verbose, int, 0644);
+MODULE_PARM_DESC(verbose, "verbose startup messages, default is 0 (no)");
+
+#define DRIVER_NAME	"Hopper"
+
+static char *label[10] = {
+	"DMA",
+	"IRQ-0",
+	"IRQ-1",
+	"OCERR",
+	"PABRT",
+	"RIPRR",
+	"PPERR",
+	"FTRGT",
+	"RISCI",
+	"RACK"
+};
+
+static int devs;
+
+static irqreturn_t hopper_irq_handler(int irq, void *dev_id)
+{
+	u32 stat = 0, mask = 0;
+	u32 rst_stat = 0, rst_mask = 0;
+
+	struct mantis_pci *mantis;
+	struct mantis_ca *ca;
+
+	mantis = (struct mantis_pci *) dev_id;
+	if (unlikely(mantis == NULL)) {
+		dprintk(MANTIS_ERROR, 1, "Mantis == NULL");
+		return IRQ_NONE;
+	}
+	ca = mantis->mantis_ca;
+
+	stat = mmread(MANTIS_INT_STAT);
+	mask = mmread(MANTIS_INT_MASK);
+	if (!(stat & mask))
+		return IRQ_NONE;
+
+	rst_mask  = MANTIS_GPIF_WRACK  |
+		    MANTIS_GPIF_OTHERR |
+		    MANTIS_SBUF_WSTO   |
+		    MANTIS_GPIF_EXTIRQ;
+
+	rst_stat  = mmread(MANTIS_GPIF_STATUS);
+	rst_stat &= rst_mask;
+	mmwrite(rst_stat, MANTIS_GPIF_STATUS);
+
+	mantis->mantis_int_stat = stat;
+	mantis->mantis_int_mask = mask;
+	dprintk(MANTIS_DEBUG, 0, "\n-- Stat=<%02x> Mask=<%02x> --", stat, mask);
+	if (stat & MANTIS_INT_RISCEN) {
+		dprintk(MANTIS_DEBUG, 0, "<%s>", label[0]);
+	}
+	if (stat & MANTIS_INT_IRQ0) {
+		dprintk(MANTIS_DEBUG, 0, "<%s>", label[1]);
+		mantis->gpif_status = rst_stat;
+		wake_up(&ca->hif_write_wq);
+		schedule_work(&ca->hif_evm_work);
+	}
+	if (stat & MANTIS_INT_IRQ1) {
+		dprintk(MANTIS_DEBUG, 0, "<%s>", label[2]);
+		schedule_work(&mantis->uart_work);
+	}
+	if (stat & MANTIS_INT_OCERR) {
+		dprintk(MANTIS_DEBUG, 0, "<%s>", label[3]);
+	}
+	if (stat & MANTIS_INT_PABORT) {
+		dprintk(MANTIS_DEBUG, 0, "<%s>", label[4]);
+	}
+	if (stat & MANTIS_INT_RIPERR) {
+		dprintk(MANTIS_DEBUG, 0, "<%s>", label[5]);
+	}
+	if (stat & MANTIS_INT_PPERR) {
+		dprintk(MANTIS_DEBUG, 0, "<%s>", label[6]);
+	}
+	if (stat & MANTIS_INT_FTRGT) {
+		dprintk(MANTIS_DEBUG, 0, "<%s>", label[7]);
+	}
+	if (stat & MANTIS_INT_RISCI) {
+		dprintk(MANTIS_DEBUG, 0, "<%s>", label[8]);
+		mantis->busy_block = (stat & MANTIS_INT_RISCSTAT) >> 28;
+		tasklet_schedule(&mantis->tasklet);
+	}
+	if (stat & MANTIS_INT_I2CDONE) {
+		dprintk(MANTIS_DEBUG, 0, "<%s>", label[9]);
+		wake_up(&mantis->i2c_wq);
+	}
+	mmwrite(stat, MANTIS_INT_STAT);
+	stat &= ~(MANTIS_INT_RISCEN   | MANTIS_INT_I2CDONE |
+		  MANTIS_INT_I2CRACK  | MANTIS_INT_PCMCIA7 |
+		  MANTIS_INT_PCMCIA6  | MANTIS_INT_PCMCIA5 |
+		  MANTIS_INT_PCMCIA4  | MANTIS_INT_PCMCIA3 |
+		  MANTIS_INT_PCMCIA2  | MANTIS_INT_PCMCIA1 |
+		  MANTIS_INT_PCMCIA0  | MANTIS_INT_IRQ1	   |
+		  MANTIS_INT_IRQ0     | MANTIS_INT_OCERR   |
+		  MANTIS_INT_PABORT   | MANTIS_INT_RIPERR  |
+		  MANTIS_INT_PPERR    | MANTIS_INT_FTRGT   |
+		  MANTIS_INT_RISCI);
+
+	if (stat)
+		dprintk(MANTIS_DEBUG, 0, "<Unknown> Stat=<%02x> Mask=<%02x>", stat, mask);
+
+	dprintk(MANTIS_DEBUG, 0, "\n");
+	return IRQ_HANDLED;
+}
+
+static int __devinit hopper_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
+{
+	struct mantis_pci *mantis;
+	struct mantis_hwconfig *config;
+	int err = 0;
+
+	mantis = kzalloc(sizeof(struct mantis_pci), GFP_KERNEL);
+	if (mantis == NULL) {
+		printk(KERN_ERR "%s ERROR: Out of memory\n", __func__);
+		err = -ENOMEM;
+		goto fail0;
+	}
+
+	mantis->num		= devs;
+	mantis->verbose		= verbose;
+	mantis->pdev		= pdev;
+	config			= (struct mantis_hwconfig *) pci_id->driver_data;
+	config->irq_handler	= &hopper_irq_handler;
+	mantis->hwconfig	= config;
+
+	err = mantis_pci_init(mantis);
+	if (err) {
+		dprintk(MANTIS_ERROR, 1, "ERROR: Mantis PCI initialization failed <%d>", err);
+		goto fail1;
+	}
+
+	err = mantis_stream_control(mantis, STREAM_TO_HIF);
+	if (err < 0) {
+		dprintk(MANTIS_ERROR, 1, "ERROR: Mantis stream control failed <%d>", err);
+		goto fail1;
+	}
+
+	err = mantis_i2c_init(mantis);
+	if (err < 0) {
+		dprintk(MANTIS_ERROR, 1, "ERROR: Mantis I2C initialization failed <%d>", err);
+		goto fail2;
+	}
+
+	err = mantis_get_mac(mantis);
+	if (err < 0) {
+		dprintk(MANTIS_ERROR, 1, "ERROR: Mantis MAC address read failed <%d>", err);
+		goto fail2;
+	}
+
+	err = mantis_dma_init(mantis);
+	if (err < 0) {
+		dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DMA initialization failed <%d>", err);
+		goto fail3;
+	}
+
+	err = mantis_dvb_init(mantis);
+	if (err < 0) {
+		dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DVB initialization failed <%d>", err);
+		goto fail4;
+	}
+	devs++;
+
+	return err;
+
+fail4:
+	dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DMA exit! <%d>", err);
+	mantis_dma_exit(mantis);
+
+fail3:
+	dprintk(MANTIS_ERROR, 1, "ERROR: Mantis I2C exit! <%d>", err);
+	mantis_i2c_exit(mantis);
+
+fail2:
+	dprintk(MANTIS_ERROR, 1, "ERROR: Mantis PCI exit! <%d>", err);
+	mantis_pci_exit(mantis);
+
+fail1:
+	dprintk(MANTIS_ERROR, 1, "ERROR: Mantis free! <%d>", err);
+	kfree(mantis);
+
+fail0:
+	return err;
+}
+
+static void __devexit hopper_pci_remove(struct pci_dev *pdev)
+{
+	struct mantis_pci *mantis = pci_get_drvdata(pdev);
+
+	if (mantis) {
+		mantis_dvb_exit(mantis);
+		mantis_dma_exit(mantis);
+		mantis_i2c_exit(mantis);
+		mantis_pci_exit(mantis);
+		kfree(mantis);
+	}
+	return;
+
+}
+
+static struct pci_device_id hopper_pci_table[] = {
+	MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_3028_DVB_T, &vp3028_config),
+	{ }
+};
+
+MODULE_DEVICE_TABLE(pci, hopper_pci_table);
+
+static struct pci_driver hopper_pci_driver = {
+	.name		= DRIVER_NAME,
+	.id_table	= hopper_pci_table,
+	.probe		= hopper_pci_probe,
+	.remove		= hopper_pci_remove,
+};
+
+static int __devinit hopper_init(void)
+{
+	return pci_register_driver(&hopper_pci_driver);
+}
+
+static void __devexit hopper_exit(void)
+{
+	return pci_unregister_driver(&hopper_pci_driver);
+}
+
+module_init(hopper_init);
+module_exit(hopper_exit);
+
+MODULE_DESCRIPTION("HOPPER driver");
+MODULE_AUTHOR("Manu Abraham");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/pci/mantis/hopper_vp3028.c b/drivers/media/pci/mantis/hopper_vp3028.c
new file mode 100644
index 0000000..68a29f8
--- /dev/null
+++ b/drivers/media/pci/mantis/hopper_vp3028.c
@@ -0,0 +1,88 @@
+/*
+	Hopper VP-3028 driver
+
+	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+
+#include "dmxdev.h"
+#include "dvbdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dvb_net.h"
+
+#include "zl10353.h"
+#include "mantis_common.h"
+#include "mantis_ioc.h"
+#include "mantis_dvb.h"
+#include "hopper_vp3028.h"
+
+struct zl10353_config hopper_vp3028_config = {
+	.demod_address	= 0x0f,
+};
+
+#define MANTIS_MODEL_NAME	"VP-3028"
+#define MANTIS_DEV_TYPE		"DVB-T"
+
+static int vp3028_frontend_init(struct mantis_pci *mantis, struct dvb_frontend *fe)
+{
+	struct i2c_adapter *adapter	= &mantis->adapter;
+	struct mantis_hwconfig *config	= mantis->hwconfig;
+	int err = 0;
+
+	mantis_gpio_set_bits(mantis, config->reset, 0);
+	msleep(100);
+	err = mantis_frontend_power(mantis, POWER_ON);
+	msleep(100);
+	mantis_gpio_set_bits(mantis, config->reset, 1);
+
+	err = mantis_frontend_power(mantis, POWER_ON);
+	if (err == 0) {
+		msleep(250);
+		dprintk(MANTIS_ERROR, 1, "Probing for 10353 (DVB-T)");
+		fe = dvb_attach(zl10353_attach, &hopper_vp3028_config, adapter);
+
+		if (!fe)
+			return -1;
+	} else {
+		dprintk(MANTIS_ERROR, 1, "Frontend on <%s> POWER ON failed! <%d>",
+			adapter->name,
+			err);
+
+		return -EIO;
+	}
+	dprintk(MANTIS_ERROR, 1, "Done!");
+
+	return 0;
+}
+
+struct mantis_hwconfig vp3028_config = {
+	.model_name	= MANTIS_MODEL_NAME,
+	.dev_type	= MANTIS_DEV_TYPE,
+	.ts_size	= MANTIS_TS_188,
+
+	.baud_rate	= MANTIS_BAUD_9600,
+	.parity		= MANTIS_PARITY_NONE,
+	.bytes		= 0,
+
+	.frontend_init	= vp3028_frontend_init,
+	.power		= GPIF_A00,
+	.reset		= GPIF_A03,
+};
diff --git a/drivers/media/pci/mantis/hopper_vp3028.h b/drivers/media/pci/mantis/hopper_vp3028.h
new file mode 100644
index 0000000..5723949
--- /dev/null
+++ b/drivers/media/pci/mantis/hopper_vp3028.h
@@ -0,0 +1,30 @@
+/*
+	Hopper VP-3028 driver
+
+	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __MANTIS_VP3028_H
+#define __MANTIS_VP3028_H
+
+#include "mantis_common.h"
+
+#define MANTIS_VP_3028_DVB_T	0x0028
+
+extern struct mantis_hwconfig vp3028_config;
+
+#endif /* __MANTIS_VP3028_H */
diff --git a/drivers/media/pci/mantis/mantis_ca.c b/drivers/media/pci/mantis/mantis_ca.c
new file mode 100644
index 0000000..3d70469
--- /dev/null
+++ b/drivers/media/pci/mantis/mantis_ca.c
@@ -0,0 +1,209 @@
+/*
+	Mantis PCI bridge driver
+
+	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/signal.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <asm/io.h>
+
+#include "dmxdev.h"
+#include "dvbdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dvb_net.h"
+
+#include "mantis_common.h"
+#include "mantis_link.h"
+#include "mantis_hif.h"
+#include "mantis_reg.h"
+
+#include "mantis_ca.h"
+
+static int mantis_ca_read_attr_mem(struct dvb_ca_en50221 *en50221, int slot, int addr)
+{
+	struct mantis_ca *ca = en50221->data;
+	struct mantis_pci *mantis = ca->ca_priv;
+
+	dprintk(MANTIS_DEBUG, 1, "Slot(%d): Request Attribute Mem Read", slot);
+
+	if (slot != 0)
+		return -EINVAL;
+
+	return mantis_hif_read_mem(ca, addr);
+}
+
+static int mantis_ca_write_attr_mem(struct dvb_ca_en50221 *en50221, int slot, int addr, u8 data)
+{
+	struct mantis_ca *ca = en50221->data;
+	struct mantis_pci *mantis = ca->ca_priv;
+
+	dprintk(MANTIS_DEBUG, 1, "Slot(%d): Request Attribute Mem Write", slot);
+
+	if (slot != 0)
+		return -EINVAL;
+
+	return mantis_hif_write_mem(ca, addr, data);
+}
+
+static int mantis_ca_read_cam_ctl(struct dvb_ca_en50221 *en50221, int slot, u8 addr)
+{
+	struct mantis_ca *ca = en50221->data;
+	struct mantis_pci *mantis = ca->ca_priv;
+
+	dprintk(MANTIS_DEBUG, 1, "Slot(%d): Request CAM control Read", slot);
+
+	if (slot != 0)
+		return -EINVAL;
+
+	return mantis_hif_read_iom(ca, addr);
+}
+
+static int mantis_ca_write_cam_ctl(struct dvb_ca_en50221 *en50221, int slot, u8 addr, u8 data)
+{
+	struct mantis_ca *ca = en50221->data;
+	struct mantis_pci *mantis = ca->ca_priv;
+
+	dprintk(MANTIS_DEBUG, 1, "Slot(%d): Request CAM control Write", slot);
+
+	if (slot != 0)
+		return -EINVAL;
+
+	return mantis_hif_write_iom(ca, addr, data);
+}
+
+static int mantis_ca_slot_reset(struct dvb_ca_en50221 *en50221, int slot)
+{
+	struct mantis_ca *ca = en50221->data;
+	struct mantis_pci *mantis = ca->ca_priv;
+
+	dprintk(MANTIS_DEBUG, 1, "Slot(%d): Slot RESET", slot);
+	udelay(500); /* Wait.. */
+	mmwrite(0xda, MANTIS_PCMCIA_RESET); /* Leading edge assert */
+	udelay(500);
+	mmwrite(0x00, MANTIS_PCMCIA_RESET); /* Trailing edge deassert */
+	msleep(1000);
+	dvb_ca_en50221_camready_irq(&ca->en50221, 0);
+
+	return 0;
+}
+
+static int mantis_ca_slot_shutdown(struct dvb_ca_en50221 *en50221, int slot)
+{
+	struct mantis_ca *ca = en50221->data;
+	struct mantis_pci *mantis = ca->ca_priv;
+
+	dprintk(MANTIS_DEBUG, 1, "Slot(%d): Slot shutdown", slot);
+
+	return 0;
+}
+
+static int mantis_ts_control(struct dvb_ca_en50221 *en50221, int slot)
+{
+	struct mantis_ca *ca = en50221->data;
+	struct mantis_pci *mantis = ca->ca_priv;
+
+	dprintk(MANTIS_DEBUG, 1, "Slot(%d): TS control", slot);
+/*	mantis_set_direction(mantis, 1); */ /* Enable TS through CAM */
+
+	return 0;
+}
+
+static int mantis_slot_status(struct dvb_ca_en50221 *en50221, int slot, int open)
+{
+	struct mantis_ca *ca = en50221->data;
+	struct mantis_pci *mantis = ca->ca_priv;
+
+	dprintk(MANTIS_DEBUG, 1, "Slot(%d): Poll Slot status", slot);
+
+	if (ca->slot_state == MODULE_INSERTED) {
+		dprintk(MANTIS_DEBUG, 1, "CA Module present and ready");
+		return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY;
+	} else {
+		dprintk(MANTIS_DEBUG, 1, "CA Module not present or not ready");
+	}
+
+	return 0;
+}
+
+int mantis_ca_init(struct mantis_pci *mantis)
+{
+	struct dvb_adapter *dvb_adapter	= &mantis->dvb_adapter;
+	struct mantis_ca *ca;
+	int ca_flags = 0, result;
+
+	dprintk(MANTIS_DEBUG, 1, "Initializing Mantis CA");
+	ca = kzalloc(sizeof(struct mantis_ca), GFP_KERNEL);
+	if (!ca) {
+		dprintk(MANTIS_ERROR, 1, "Out of memory!, exiting ..");
+		result = -ENOMEM;
+		goto err;
+	}
+
+	ca->ca_priv		= mantis;
+	mantis->mantis_ca	= ca;
+	ca_flags		= DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE;
+	/* register CA interface */
+	ca->en50221.owner		= THIS_MODULE;
+	ca->en50221.read_attribute_mem	= mantis_ca_read_attr_mem;
+	ca->en50221.write_attribute_mem	= mantis_ca_write_attr_mem;
+	ca->en50221.read_cam_control	= mantis_ca_read_cam_ctl;
+	ca->en50221.write_cam_control	= mantis_ca_write_cam_ctl;
+	ca->en50221.slot_reset		= mantis_ca_slot_reset;
+	ca->en50221.slot_shutdown	= mantis_ca_slot_shutdown;
+	ca->en50221.slot_ts_enable	= mantis_ts_control;
+	ca->en50221.poll_slot_status	= mantis_slot_status;
+	ca->en50221.data		= ca;
+
+	mutex_init(&ca->ca_lock);
+
+	init_waitqueue_head(&ca->hif_data_wq);
+	init_waitqueue_head(&ca->hif_opdone_wq);
+	init_waitqueue_head(&ca->hif_write_wq);
+
+	dprintk(MANTIS_ERROR, 1, "Registering EN50221 device");
+	result = dvb_ca_en50221_init(dvb_adapter, &ca->en50221, ca_flags, 1);
+	if (result != 0) {
+		dprintk(MANTIS_ERROR, 1, "EN50221: Initialization failed <%d>", result);
+		goto err;
+	}
+	dprintk(MANTIS_ERROR, 1, "Registered EN50221 device");
+	mantis_evmgr_init(ca);
+	return 0;
+err:
+	kfree(ca);
+	return result;
+}
+EXPORT_SYMBOL_GPL(mantis_ca_init);
+
+void mantis_ca_exit(struct mantis_pci *mantis)
+{
+	struct mantis_ca *ca = mantis->mantis_ca;
+
+	dprintk(MANTIS_DEBUG, 1, "Mantis CA exit");
+
+	mantis_evmgr_exit(ca);
+	dprintk(MANTIS_ERROR, 1, "Unregistering EN50221 device");
+	if (ca)
+		dvb_ca_en50221_release(&ca->en50221);
+
+	kfree(ca);
+}
+EXPORT_SYMBOL_GPL(mantis_ca_exit);
diff --git a/drivers/media/pci/mantis/mantis_ca.h b/drivers/media/pci/mantis/mantis_ca.h
new file mode 100644
index 0000000..dc63e55
--- /dev/null
+++ b/drivers/media/pci/mantis/mantis_ca.h
@@ -0,0 +1,27 @@
+/*
+	Mantis PCI bridge driver
+
+	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __MANTIS_CA_H
+#define __MANTIS_CA_H
+
+extern int mantis_ca_init(struct mantis_pci *mantis);
+extern void mantis_ca_exit(struct mantis_pci *mantis);
+
+#endif /* __MANTIS_CA_H */
diff --git a/drivers/media/pci/mantis/mantis_cards.c b/drivers/media/pci/mantis/mantis_cards.c
new file mode 100644
index 0000000..0207d1f
--- /dev/null
+++ b/drivers/media/pci/mantis/mantis_cards.c
@@ -0,0 +1,307 @@
+/*
+	Mantis PCI bridge driver
+
+	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <asm/irq.h>
+#include <linux/interrupt.h>
+
+#include "dmxdev.h"
+#include "dvbdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dvb_net.h"
+
+#include "mantis_common.h"
+
+#include "mantis_vp1033.h"
+#include "mantis_vp1034.h"
+#include "mantis_vp1041.h"
+#include "mantis_vp2033.h"
+#include "mantis_vp2040.h"
+#include "mantis_vp3030.h"
+
+#include "mantis_dma.h"
+#include "mantis_ca.h"
+#include "mantis_dvb.h"
+#include "mantis_uart.h"
+#include "mantis_ioc.h"
+#include "mantis_pci.h"
+#include "mantis_i2c.h"
+#include "mantis_reg.h"
+
+static unsigned int verbose;
+module_param(verbose, int, 0644);
+MODULE_PARM_DESC(verbose, "verbose startup messages, default is 0 (no)");
+
+static int devs;
+
+#define DRIVER_NAME	"Mantis"
+
+static char *label[10] = {
+	"DMA",
+	"IRQ-0",
+	"IRQ-1",
+	"OCERR",
+	"PABRT",
+	"RIPRR",
+	"PPERR",
+	"FTRGT",
+	"RISCI",
+	"RACK"
+};
+
+static irqreturn_t mantis_irq_handler(int irq, void *dev_id)
+{
+	u32 stat = 0, mask = 0;
+	u32 rst_stat = 0, rst_mask = 0;
+
+	struct mantis_pci *mantis;
+	struct mantis_ca *ca;
+
+	mantis = (struct mantis_pci *) dev_id;
+	if (unlikely(mantis == NULL)) {
+		dprintk(MANTIS_ERROR, 1, "Mantis == NULL");
+		return IRQ_NONE;
+	}
+	ca = mantis->mantis_ca;
+
+	stat = mmread(MANTIS_INT_STAT);
+	mask = mmread(MANTIS_INT_MASK);
+	if (!(stat & mask))
+		return IRQ_NONE;
+
+	rst_mask  = MANTIS_GPIF_WRACK  |
+		    MANTIS_GPIF_OTHERR |
+		    MANTIS_SBUF_WSTO   |
+		    MANTIS_GPIF_EXTIRQ;
+
+	rst_stat  = mmread(MANTIS_GPIF_STATUS);
+	rst_stat &= rst_mask;
+	mmwrite(rst_stat, MANTIS_GPIF_STATUS);
+
+	mantis->mantis_int_stat = stat;
+	mantis->mantis_int_mask = mask;
+	dprintk(MANTIS_DEBUG, 0, "\n-- Stat=<%02x> Mask=<%02x> --", stat, mask);
+	if (stat & MANTIS_INT_RISCEN) {
+		dprintk(MANTIS_DEBUG, 0, "<%s>", label[0]);
+	}
+	if (stat & MANTIS_INT_IRQ0) {
+		dprintk(MANTIS_DEBUG, 0, "<%s>", label[1]);
+		mantis->gpif_status = rst_stat;
+		wake_up(&ca->hif_write_wq);
+		schedule_work(&ca->hif_evm_work);
+	}
+	if (stat & MANTIS_INT_IRQ1) {
+		dprintk(MANTIS_DEBUG, 0, "<%s>", label[2]);
+		schedule_work(&mantis->uart_work);
+	}
+	if (stat & MANTIS_INT_OCERR) {
+		dprintk(MANTIS_DEBUG, 0, "<%s>", label[3]);
+	}
+	if (stat & MANTIS_INT_PABORT) {
+		dprintk(MANTIS_DEBUG, 0, "<%s>", label[4]);
+	}
+	if (stat & MANTIS_INT_RIPERR) {
+		dprintk(MANTIS_DEBUG, 0, "<%s>", label[5]);
+	}
+	if (stat & MANTIS_INT_PPERR) {
+		dprintk(MANTIS_DEBUG, 0, "<%s>", label[6]);
+	}
+	if (stat & MANTIS_INT_FTRGT) {
+		dprintk(MANTIS_DEBUG, 0, "<%s>", label[7]);
+	}
+	if (stat & MANTIS_INT_RISCI) {
+		dprintk(MANTIS_DEBUG, 0, "<%s>", label[8]);
+		mantis->busy_block = (stat & MANTIS_INT_RISCSTAT) >> 28;
+		tasklet_schedule(&mantis->tasklet);
+	}
+	if (stat & MANTIS_INT_I2CDONE) {
+		dprintk(MANTIS_DEBUG, 0, "<%s>", label[9]);
+		wake_up(&mantis->i2c_wq);
+	}
+	mmwrite(stat, MANTIS_INT_STAT);
+	stat &= ~(MANTIS_INT_RISCEN   | MANTIS_INT_I2CDONE |
+		  MANTIS_INT_I2CRACK  | MANTIS_INT_PCMCIA7 |
+		  MANTIS_INT_PCMCIA6  | MANTIS_INT_PCMCIA5 |
+		  MANTIS_INT_PCMCIA4  | MANTIS_INT_PCMCIA3 |
+		  MANTIS_INT_PCMCIA2  | MANTIS_INT_PCMCIA1 |
+		  MANTIS_INT_PCMCIA0  | MANTIS_INT_IRQ1	   |
+		  MANTIS_INT_IRQ0     | MANTIS_INT_OCERR   |
+		  MANTIS_INT_PABORT   | MANTIS_INT_RIPERR  |
+		  MANTIS_INT_PPERR    | MANTIS_INT_FTRGT   |
+		  MANTIS_INT_RISCI);
+
+	if (stat)
+		dprintk(MANTIS_DEBUG, 0, "<Unknown> Stat=<%02x> Mask=<%02x>", stat, mask);
+
+	dprintk(MANTIS_DEBUG, 0, "\n");
+	return IRQ_HANDLED;
+}
+
+static int __devinit mantis_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
+{
+	struct mantis_pci *mantis;
+	struct mantis_hwconfig *config;
+	int err = 0;
+
+	mantis = kzalloc(sizeof(struct mantis_pci), GFP_KERNEL);
+	if (mantis == NULL) {
+		printk(KERN_ERR "%s ERROR: Out of memory\n", __func__);
+		err = -ENOMEM;
+		goto fail0;
+	}
+
+	mantis->num		= devs;
+	mantis->verbose		= verbose;
+	mantis->pdev		= pdev;
+	config			= (struct mantis_hwconfig *) pci_id->driver_data;
+	config->irq_handler	= &mantis_irq_handler;
+	mantis->hwconfig	= config;
+
+	err = mantis_pci_init(mantis);
+	if (err) {
+		dprintk(MANTIS_ERROR, 1, "ERROR: Mantis PCI initialization failed <%d>", err);
+		goto fail1;
+	}
+
+	err = mantis_stream_control(mantis, STREAM_TO_HIF);
+	if (err < 0) {
+		dprintk(MANTIS_ERROR, 1, "ERROR: Mantis stream control failed <%d>", err);
+		goto fail1;
+	}
+
+	err = mantis_i2c_init(mantis);
+	if (err < 0) {
+		dprintk(MANTIS_ERROR, 1, "ERROR: Mantis I2C initialization failed <%d>", err);
+		goto fail2;
+	}
+
+	err = mantis_get_mac(mantis);
+	if (err < 0) {
+		dprintk(MANTIS_ERROR, 1, "ERROR: Mantis MAC address read failed <%d>", err);
+		goto fail2;
+	}
+
+	err = mantis_dma_init(mantis);
+	if (err < 0) {
+		dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DMA initialization failed <%d>", err);
+		goto fail3;
+	}
+
+	err = mantis_dvb_init(mantis);
+	if (err < 0) {
+		dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DVB initialization failed <%d>", err);
+		goto fail4;
+	}
+	err = mantis_uart_init(mantis);
+	if (err < 0) {
+		dprintk(MANTIS_ERROR, 1, "ERROR: Mantis UART initialization failed <%d>", err);
+		goto fail6;
+	}
+
+	devs++;
+
+	return err;
+
+
+	dprintk(MANTIS_ERROR, 1, "ERROR: Mantis UART exit! <%d>", err);
+	mantis_uart_exit(mantis);
+
+fail6:
+fail4:
+	dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DMA exit! <%d>", err);
+	mantis_dma_exit(mantis);
+
+fail3:
+	dprintk(MANTIS_ERROR, 1, "ERROR: Mantis I2C exit! <%d>", err);
+	mantis_i2c_exit(mantis);
+
+fail2:
+	dprintk(MANTIS_ERROR, 1, "ERROR: Mantis PCI exit! <%d>", err);
+	mantis_pci_exit(mantis);
+
+fail1:
+	dprintk(MANTIS_ERROR, 1, "ERROR: Mantis free! <%d>", err);
+	kfree(mantis);
+
+fail0:
+	return err;
+}
+
+static void __devexit mantis_pci_remove(struct pci_dev *pdev)
+{
+	struct mantis_pci *mantis = pci_get_drvdata(pdev);
+
+	if (mantis) {
+
+		mantis_uart_exit(mantis);
+		mantis_dvb_exit(mantis);
+		mantis_dma_exit(mantis);
+		mantis_i2c_exit(mantis);
+		mantis_pci_exit(mantis);
+		kfree(mantis);
+	}
+	return;
+}
+
+static struct pci_device_id mantis_pci_table[] = {
+	MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_1033_DVB_S, &vp1033_config),
+	MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_1034_DVB_S, &vp1034_config),
+	MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_1041_DVB_S2, &vp1041_config),
+	MAKE_ENTRY(TECHNISAT, SKYSTAR_HD2_10, &vp1041_config),
+	MAKE_ENTRY(TECHNISAT, SKYSTAR_HD2_20, &vp1041_config),
+	MAKE_ENTRY(TERRATEC, CINERGY_S2_PCI_HD, &vp1041_config),
+	MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_2033_DVB_C, &vp2033_config),
+	MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_2040_DVB_C, &vp2040_config),
+	MAKE_ENTRY(TECHNISAT, CABLESTAR_HD2, &vp2040_config),
+	MAKE_ENTRY(TERRATEC, CINERGY_C, &vp2040_config),
+	MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_3030_DVB_T, &vp3030_config),
+	{ }
+};
+
+MODULE_DEVICE_TABLE(pci, mantis_pci_table);
+
+static struct pci_driver mantis_pci_driver = {
+	.name		= DRIVER_NAME,
+	.id_table	= mantis_pci_table,
+	.probe		= mantis_pci_probe,
+	.remove		= mantis_pci_remove,
+};
+
+static int __devinit mantis_init(void)
+{
+	return pci_register_driver(&mantis_pci_driver);
+}
+
+static void __devexit mantis_exit(void)
+{
+	return pci_unregister_driver(&mantis_pci_driver);
+}
+
+module_init(mantis_init);
+module_exit(mantis_exit);
+
+MODULE_DESCRIPTION("MANTIS driver");
+MODULE_AUTHOR("Manu Abraham");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/pci/mantis/mantis_common.h b/drivers/media/pci/mantis/mantis_common.h
new file mode 100644
index 0000000..f2410cf
--- /dev/null
+++ b/drivers/media/pci/mantis/mantis_common.h
@@ -0,0 +1,179 @@
+/*
+	Mantis PCI bridge driver
+
+	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __MANTIS_COMMON_H
+#define __MANTIS_COMMON_H
+
+#include <linux/interrupt.h>
+#include <linux/mutex.h>
+#include <linux/workqueue.h>
+
+#include "mantis_uart.h"
+
+#include "mantis_link.h"
+
+#define MANTIS_ERROR		0
+#define MANTIS_NOTICE		1
+#define MANTIS_INFO		2
+#define MANTIS_DEBUG		3
+#define MANTIS_TMG		9
+
+#define dprintk(y, z, format, arg...) do {								\
+	if (z) {											\
+		if	((mantis->verbose > MANTIS_ERROR) && (mantis->verbose > y))			\
+			printk(KERN_ERR "%s (%d): " format "\n" , __func__ , mantis->num , ##arg);	\
+		else if	((mantis->verbose > MANTIS_NOTICE) && (mantis->verbose > y))			\
+			printk(KERN_NOTICE "%s (%d): " format "\n" , __func__ , mantis->num , ##arg);	\
+		else if ((mantis->verbose > MANTIS_INFO) && (mantis->verbose > y))			\
+			printk(KERN_INFO "%s (%d): " format "\n" , __func__ , mantis->num , ##arg);	\
+		else if ((mantis->verbose > MANTIS_DEBUG) && (mantis->verbose > y))			\
+			printk(KERN_DEBUG "%s (%d): " format "\n" , __func__ , mantis->num , ##arg);	\
+		else if ((mantis->verbose > MANTIS_TMG) && (mantis->verbose > y))			\
+			printk(KERN_DEBUG "%s (%d): " format "\n" , __func__ , mantis->num , ##arg);	\
+	} else {											\
+		if (mantis->verbose > y)								\
+			printk(format , ##arg);								\
+	}												\
+} while(0)
+
+#define mwrite(dat, addr)	writel((dat), addr)
+#define mread(addr)		readl(addr)
+
+#define mmwrite(dat, addr)	mwrite((dat), (mantis->mmio + (addr)))
+#define mmread(addr)		mread(mantis->mmio + (addr))
+
+#define MANTIS_TS_188		0
+#define MANTIS_TS_204		1
+
+#define TWINHAN_TECHNOLOGIES	0x1822
+#define MANTIS			0x4e35
+
+#define TECHNISAT		0x1ae4
+#define TERRATEC		0x153b
+
+#define MAKE_ENTRY(__subven, __subdev, __configptr) {			\
+		.vendor		= TWINHAN_TECHNOLOGIES,			\
+		.device		= MANTIS,				\
+		.subvendor	= (__subven),				\
+		.subdevice	= (__subdev),				\
+		.driver_data	= (unsigned long) (__configptr)		\
+}
+
+enum mantis_i2c_mode {
+	MANTIS_PAGE_MODE = 0,
+	MANTIS_BYTE_MODE,
+};
+
+struct mantis_pci;
+
+struct mantis_hwconfig {
+	char			*model_name;
+	char			*dev_type;
+	u32			ts_size;
+
+	enum mantis_baud	baud_rate;
+	enum mantis_parity	parity;
+	u32			bytes;
+
+	irqreturn_t (*irq_handler)(int irq, void *dev_id);
+	int (*frontend_init)(struct mantis_pci *mantis, struct dvb_frontend *fe);
+
+	u8			power;
+	u8			reset;
+
+	enum mantis_i2c_mode	i2c_mode;
+};
+
+struct mantis_pci {
+	unsigned int		verbose;
+
+	/*	PCI stuff		*/
+	u16			vendor_id;
+	u16			device_id;
+	u16			subsystem_vendor;
+	u16			subsystem_device;
+
+	u8			latency;
+
+	struct pci_dev		*pdev;
+
+	unsigned long		mantis_addr;
+	void __iomem		*mmio;
+
+	u8			irq;
+	u8			revision;
+
+	unsigned int		num;
+
+	/*	RISC Core		*/
+	u32			busy_block;
+	u32			last_block;
+	u8			*buf_cpu;
+	dma_addr_t		buf_dma;
+	u32			*risc_cpu;
+	dma_addr_t		risc_dma;
+
+	struct tasklet_struct	tasklet;
+
+	struct i2c_adapter	adapter;
+	int			i2c_rc;
+	wait_queue_head_t	i2c_wq;
+	struct mutex		i2c_lock;
+
+	/*	DVB stuff		*/
+	struct dvb_adapter	dvb_adapter;
+	struct dvb_frontend	*fe;
+	struct dvb_demux	demux;
+	struct dmxdev		dmxdev;
+	struct dmx_frontend	fe_hw;
+	struct dmx_frontend	fe_mem;
+	struct dvb_net		dvbnet;
+
+	u8			feeds;
+
+	struct mantis_hwconfig	*hwconfig;
+
+	u32			mantis_int_stat;
+	u32			mantis_int_mask;
+
+	/*	board specific		*/
+	u8			mac_address[8];
+	u32			sub_vendor_id;
+	u32			sub_device_id;
+
+	 /*	A12 A13 A14		*/
+	u32			gpio_status;
+
+	u32			gpif_status;
+
+	struct mantis_ca	*mantis_ca;
+
+	wait_queue_head_t	uart_wq;
+	struct work_struct	uart_work;
+	spinlock_t		uart_lock;
+
+	struct rc_dev		*rc;
+	char			input_name[80];
+	char			input_phys[80];
+};
+
+#define MANTIS_HIF_STATUS	(mantis->gpio_status)
+
+#endif /* __MANTIS_COMMON_H */
diff --git a/drivers/media/pci/mantis/mantis_core.c b/drivers/media/pci/mantis/mantis_core.c
new file mode 100644
index 0000000..684d906
--- /dev/null
+++ b/drivers/media/pci/mantis/mantis_core.c
@@ -0,0 +1,235 @@
+/*
+	Mantis PCI bridge driver
+
+	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "mantis_common.h"
+#include "mantis_core.h"
+#include "mantis_vp1033.h"
+#include "mantis_vp1034.h"
+#include "mantis_vp1041.h"
+#include "mantis_vp2033.h"
+#include "mantis_vp2040.h"
+#include "mantis_vp3030.h"
+
+static int read_eeprom_byte(struct mantis_pci *mantis, u8 *data, u8 length)
+{
+	int err;
+	struct i2c_msg msg[] = {
+		{
+			.addr = 0x50,
+			.flags = 0,
+			.buf = data,
+			.len = 1
+		}, {
+			.addr = 0x50,
+			.flags = I2C_M_RD,
+			.buf = data,
+			.len = length
+		},
+	};
+
+	err = i2c_transfer(&mantis->adapter, msg, 2);
+	if (err < 0) {
+		dprintk(verbose, MANTIS_ERROR, 1,
+			"ERROR: i2c read: < err=%i d0=0x%02x d1=0x%02x >",
+			err, data[0], data[1]);
+
+		return err;
+	}
+
+	return 0;
+}
+
+static int write_eeprom_byte(struct mantis_pci *mantis, u8 *data, u8 length)
+{
+	int err;
+
+	struct i2c_msg msg = {
+		.addr = 0x50,
+		.flags = 0,
+		.buf = data,
+		.len = length
+	};
+
+	err = i2c_transfer(&mantis->adapter, &msg, 1);
+	if (err < 0) {
+		dprintk(verbose, MANTIS_ERROR, 1,
+			"ERROR: i2c write: < err=%i length=0x%02x d0=0x%02x, d1=0x%02x >",
+			err, length, data[0], data[1]);
+
+		return err;
+	}
+
+	return 0;
+}
+
+static int get_mac_address(struct mantis_pci *mantis)
+{
+	int err;
+
+	mantis->mac_address[0] = 0x08;
+	err = read_eeprom_byte(mantis, &mantis->mac_address[0], 6);
+	if (err < 0) {
+		dprintk(verbose, MANTIS_ERROR, 1, "Mantis EEPROM read error");
+
+		return err;
+	}
+	dprintk(verbose, MANTIS_ERROR, 0,
+		"    MAC Address=[%pM]\n", mantis->mac_address);
+
+	return 0;
+}
+
+#define MANTIS_MODEL_UNKNOWN	"UNKNOWN"
+#define MANTIS_DEV_UNKNOWN	"UNKNOWN"
+
+struct mantis_hwconfig unknown_device = {
+	.model_name	= MANTIS_MODEL_UNKNOWN,
+	.dev_type	= MANTIS_DEV_UNKNOWN,
+};
+
+static void mantis_load_config(struct mantis_pci *mantis)
+{
+	switch (mantis->subsystem_device) {
+	case MANTIS_VP_1033_DVB_S:	/* VP-1033 */
+		mantis->hwconfig = &vp1033_mantis_config;
+		break;
+	case MANTIS_VP_1034_DVB_S:	/* VP-1034 */
+		mantis->hwconfig = &vp1034_mantis_config;
+		break;
+	case MANTIS_VP_1041_DVB_S2:	/* VP-1041 */
+	case TECHNISAT_SKYSTAR_HD2:
+		mantis->hwconfig = &vp1041_mantis_config;
+		break;
+	case MANTIS_VP_2033_DVB_C:	/* VP-2033 */
+		mantis->hwconfig = &vp2033_mantis_config;
+		break;
+	case MANTIS_VP_2040_DVB_C:	/* VP-2040 */
+	case CINERGY_C:	/* VP-2040 clone */
+	case TECHNISAT_CABLESTAR_HD2:
+		mantis->hwconfig = &vp2040_mantis_config;
+		break;
+	case MANTIS_VP_3030_DVB_T:	/* VP-3030 */
+		mantis->hwconfig = &vp3030_mantis_config;
+		break;
+	default:
+		mantis->hwconfig = &unknown_device;
+		break;
+	}
+}
+
+int mantis_core_init(struct mantis_pci *mantis)
+{
+	int err = 0;
+
+	mantis_load_config(mantis);
+	dprintk(verbose, MANTIS_ERROR, 0, "found a %s PCI %s device on (%02x:%02x.%x),\n",
+		mantis->hwconfig->model_name, mantis->hwconfig->dev_type,
+		mantis->pdev->bus->number, PCI_SLOT(mantis->pdev->devfn), PCI_FUNC(mantis->pdev->devfn));
+	dprintk(verbose, MANTIS_ERROR, 0, "    Mantis Rev %d [%04x:%04x], ",
+		mantis->revision,
+		mantis->subsystem_vendor, mantis->subsystem_device);
+	dprintk(verbose, MANTIS_ERROR, 0,
+		"irq: %d, latency: %d\n    memory: 0x%lx, mmio: 0x%p\n",
+		mantis->pdev->irq, mantis->latency,
+		mantis->mantis_addr, mantis->mantis_mmio);
+
+	err = mantis_i2c_init(mantis);
+	if (err < 0) {
+		dprintk(verbose, MANTIS_ERROR, 1, "Mantis I2C init failed");
+		return err;
+	}
+	err = get_mac_address(mantis);
+	if (err < 0) {
+		dprintk(verbose, MANTIS_ERROR, 1, "get MAC address failed");
+		return err;
+	}
+	err = mantis_dma_init(mantis);
+	if (err < 0) {
+		dprintk(verbose, MANTIS_ERROR, 1, "Mantis DMA init failed");
+		return err;
+	}
+	err = mantis_dvb_init(mantis);
+	if (err < 0) {
+		dprintk(verbose, MANTIS_DEBUG, 1, "Mantis DVB init failed");
+		return err;
+	}
+	err = mantis_uart_init(mantis);
+	if (err < 0) {
+		dprintk(verbose, MANTIS_DEBUG, 1, "Mantis UART init failed");
+		return err;
+	}
+
+	return 0;
+}
+
+int mantis_core_exit(struct mantis_pci *mantis)
+{
+	mantis_dma_stop(mantis);
+	dprintk(verbose, MANTIS_ERROR, 1, "DMA engine stopping");
+
+	mantis_uart_exit(mantis);
+	dprintk(verbose, MANTIS_ERROR, 1, "UART exit failed");
+
+	if (mantis_dma_exit(mantis) < 0)
+		dprintk(verbose, MANTIS_ERROR, 1, "DMA exit failed");
+	if (mantis_dvb_exit(mantis) < 0)
+		dprintk(verbose, MANTIS_ERROR, 1, "DVB exit failed");
+	if (mantis_i2c_exit(mantis) < 0)
+		dprintk(verbose, MANTIS_ERROR, 1, "I2C adapter delete.. failed");
+
+	return 0;
+}
+
+/* Turn the given bit on or off. */
+void gpio_set_bits(struct mantis_pci *mantis, u32 bitpos, u8 value)
+{
+	u32 cur;
+
+	cur = mmread(MANTIS_GPIF_ADDR);
+	if (value)
+		mantis->gpio_status = cur | (1 << bitpos);
+	else
+		mantis->gpio_status = cur & (~(1 << bitpos));
+
+	mmwrite(mantis->gpio_status, MANTIS_GPIF_ADDR);
+	mmwrite(0x00, MANTIS_GPIF_DOUT);
+	udelay(100);
+}
+
+/* direction = 0 , no CI passthrough ; 1 , CI passthrough */
+void mantis_set_direction(struct mantis_pci *mantis, int direction)
+{
+	u32 reg;
+
+	reg = mmread(0x28);
+	dprintk(verbose, MANTIS_DEBUG, 1, "TS direction setup");
+	if (direction == 0x01) {
+		/* to CI */
+		reg |= 0x04;
+		mmwrite(reg, 0x28);
+		reg &= 0xff - 0x04;
+		mmwrite(reg, 0x28);
+	} else {
+		reg &= 0xff - 0x04;
+		mmwrite(reg, 0x28);
+		reg |= 0x04;
+		mmwrite(reg, 0x28);
+	}
+}
diff --git a/drivers/media/pci/mantis/mantis_core.h b/drivers/media/pci/mantis/mantis_core.h
new file mode 100644
index 0000000..833ee42
--- /dev/null
+++ b/drivers/media/pci/mantis/mantis_core.h
@@ -0,0 +1,57 @@
+/*
+	Mantis PCI bridge driver
+
+	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __MANTIS_CORE_H
+#define __MANTIS_CORE_H
+
+#include "mantis_common.h"
+
+
+#define FE_TYPE_SAT	0
+#define FE_TYPE_CAB	1
+#define FE_TYPE_TER	2
+
+#define FE_TYPE_TS204	0
+#define FE_TYPE_TS188	1
+
+
+struct vendorname {
+	u8  *sub_vendor_name;
+	u32 sub_vendor_id;
+};
+
+struct devicetype {
+	u8  *sub_device_name;
+	u32 sub_device_id;
+	u8  device_type;
+	u32 type_flags;
+};
+
+
+extern int mantis_dma_init(struct mantis_pci *mantis);
+extern int mantis_dma_exit(struct mantis_pci *mantis);
+extern void mantis_dma_start(struct mantis_pci *mantis);
+extern void mantis_dma_stop(struct mantis_pci *mantis);
+extern int mantis_i2c_init(struct mantis_pci *mantis);
+extern int mantis_i2c_exit(struct mantis_pci *mantis);
+extern int mantis_core_init(struct mantis_pci *mantis);
+extern int mantis_core_exit(struct mantis_pci *mantis);
+
+#endif /* __MANTIS_CORE_H */
diff --git a/drivers/media/pci/mantis/mantis_dma.c b/drivers/media/pci/mantis/mantis_dma.c
new file mode 100644
index 0000000..566c407
--- /dev/null
+++ b/drivers/media/pci/mantis/mantis_dma.c
@@ -0,0 +1,230 @@
+/*
+	Mantis PCI bridge driver
+
+	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/kernel.h>
+#include <asm/page.h>
+#include <linux/vmalloc.h>
+#include <linux/pci.h>
+
+#include <asm/irq.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+
+#include "dmxdev.h"
+#include "dvbdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dvb_net.h"
+
+#include "mantis_common.h"
+#include "mantis_reg.h"
+#include "mantis_dma.h"
+
+#define RISC_WRITE		(0x01 << 28)
+#define RISC_JUMP		(0x07 << 28)
+#define RISC_IRQ		(0x01 << 24)
+
+#define RISC_STATUS(status)	((((~status) & 0x0f) << 20) | ((status & 0x0f) << 16))
+#define RISC_FLUSH(risc_pos)		(risc_pos = 0)
+#define RISC_INSTR(risc_pos, opcode)	(mantis->risc_cpu[risc_pos++] = cpu_to_le32(opcode))
+
+#define MANTIS_BUF_SIZE		(64 * 1024)
+#define MANTIS_BLOCK_BYTES      (MANTIS_BUF_SIZE / 4)
+#define MANTIS_DMA_TR_BYTES     (2 * 1024) /* upper limit: 4095 bytes. */
+#define MANTIS_BLOCK_COUNT	(MANTIS_BUF_SIZE / MANTIS_BLOCK_BYTES)
+
+#define MANTIS_DMA_TR_UNITS     (MANTIS_BLOCK_BYTES / MANTIS_DMA_TR_BYTES)
+/* MANTIS_BUF_SIZE / MANTIS_DMA_TR_UNITS must not exceed MANTIS_RISC_SIZE (4k RISC cmd buffer) */
+#define MANTIS_RISC_SIZE	PAGE_SIZE /* RISC program must fit here. */
+
+int mantis_dma_exit(struct mantis_pci *mantis)
+{
+	if (mantis->buf_cpu) {
+		dprintk(MANTIS_ERROR, 1,
+			"DMA=0x%lx cpu=0x%p size=%d",
+			(unsigned long) mantis->buf_dma,
+			 mantis->buf_cpu,
+			 MANTIS_BUF_SIZE);
+
+		pci_free_consistent(mantis->pdev, MANTIS_BUF_SIZE,
+				    mantis->buf_cpu, mantis->buf_dma);
+
+		mantis->buf_cpu = NULL;
+	}
+	if (mantis->risc_cpu) {
+		dprintk(MANTIS_ERROR, 1,
+			"RISC=0x%lx cpu=0x%p size=%lx",
+			(unsigned long) mantis->risc_dma,
+			mantis->risc_cpu,
+			MANTIS_RISC_SIZE);
+
+		pci_free_consistent(mantis->pdev, MANTIS_RISC_SIZE,
+				    mantis->risc_cpu, mantis->risc_dma);
+
+		mantis->risc_cpu = NULL;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(mantis_dma_exit);
+
+static inline int mantis_alloc_buffers(struct mantis_pci *mantis)
+{
+	if (!mantis->buf_cpu) {
+		mantis->buf_cpu = pci_alloc_consistent(mantis->pdev,
+						       MANTIS_BUF_SIZE,
+						       &mantis->buf_dma);
+		if (!mantis->buf_cpu) {
+			dprintk(MANTIS_ERROR, 1,
+				"DMA buffer allocation failed");
+
+			goto err;
+		}
+		dprintk(MANTIS_ERROR, 1,
+			"DMA=0x%lx cpu=0x%p size=%d",
+			(unsigned long) mantis->buf_dma,
+			mantis->buf_cpu, MANTIS_BUF_SIZE);
+	}
+	if (!mantis->risc_cpu) {
+		mantis->risc_cpu = pci_alloc_consistent(mantis->pdev,
+							MANTIS_RISC_SIZE,
+							&mantis->risc_dma);
+
+		if (!mantis->risc_cpu) {
+			dprintk(MANTIS_ERROR, 1,
+				"RISC program allocation failed");
+
+			mantis_dma_exit(mantis);
+
+			goto err;
+		}
+		dprintk(MANTIS_ERROR, 1,
+			"RISC=0x%lx cpu=0x%p size=%lx",
+			(unsigned long) mantis->risc_dma,
+			mantis->risc_cpu, MANTIS_RISC_SIZE);
+	}
+
+	return 0;
+err:
+	dprintk(MANTIS_ERROR, 1, "Out of memory (?) .....");
+	return -ENOMEM;
+}
+
+int mantis_dma_init(struct mantis_pci *mantis)
+{
+	int err = 0;
+
+	dprintk(MANTIS_DEBUG, 1, "Mantis DMA init");
+	if (mantis_alloc_buffers(mantis) < 0) {
+		dprintk(MANTIS_ERROR, 1, "Error allocating DMA buffer");
+
+		/* Stop RISC Engine */
+		mmwrite(0, MANTIS_DMA_CTL);
+
+		goto err;
+	}
+
+	return 0;
+err:
+	return err;
+}
+EXPORT_SYMBOL_GPL(mantis_dma_init);
+
+static inline void mantis_risc_program(struct mantis_pci *mantis)
+{
+	u32 buf_pos = 0;
+	u32 line, step;
+	u32 risc_pos;
+
+	dprintk(MANTIS_DEBUG, 1, "Mantis create RISC program");
+	RISC_FLUSH(risc_pos);
+
+	dprintk(MANTIS_DEBUG, 1, "risc len lines %u, bytes per line %u, bytes per DMA tr %u",
+		MANTIS_BLOCK_COUNT, MANTIS_BLOCK_BYTES, MANTIS_DMA_TR_BYTES);
+
+	for (line = 0; line < MANTIS_BLOCK_COUNT; line++) {
+		for (step = 0; step < MANTIS_DMA_TR_UNITS; step++) {
+			dprintk(MANTIS_DEBUG, 1, "RISC PROG line=[%d], step=[%d]", line, step);
+			if (step == 0) {
+				RISC_INSTR(risc_pos, RISC_WRITE	|
+					   RISC_IRQ	|
+					   RISC_STATUS(line) |
+					   MANTIS_DMA_TR_BYTES);
+			} else {
+				RISC_INSTR(risc_pos, RISC_WRITE | MANTIS_DMA_TR_BYTES);
+			}
+			RISC_INSTR(risc_pos, mantis->buf_dma + buf_pos);
+			buf_pos += MANTIS_DMA_TR_BYTES;
+		  }
+	}
+	RISC_INSTR(risc_pos, RISC_JUMP);
+	RISC_INSTR(risc_pos, mantis->risc_dma);
+}
+
+void mantis_dma_start(struct mantis_pci *mantis)
+{
+	dprintk(MANTIS_DEBUG, 1, "Mantis Start DMA engine");
+
+	mantis_risc_program(mantis);
+	mmwrite(mantis->risc_dma, MANTIS_RISC_START);
+	mmwrite(mmread(MANTIS_GPIF_ADDR) | MANTIS_GPIF_HIFRDWRN, MANTIS_GPIF_ADDR);
+
+	mmwrite(0, MANTIS_DMA_CTL);
+	mantis->last_block = mantis->busy_block = 0;
+
+	mmwrite(mmread(MANTIS_INT_MASK) | MANTIS_INT_RISCI, MANTIS_INT_MASK);
+
+	mmwrite(MANTIS_FIFO_EN | MANTIS_DCAP_EN
+			       | MANTIS_RISC_EN, MANTIS_DMA_CTL);
+
+}
+
+void mantis_dma_stop(struct mantis_pci *mantis)
+{
+	dprintk(MANTIS_DEBUG, 1, "Mantis Stop DMA engine");
+
+	mmwrite((mmread(MANTIS_GPIF_ADDR) & (~(MANTIS_GPIF_HIFRDWRN))), MANTIS_GPIF_ADDR);
+
+	mmwrite((mmread(MANTIS_DMA_CTL) & ~(MANTIS_FIFO_EN |
+					    MANTIS_DCAP_EN |
+					    MANTIS_RISC_EN)), MANTIS_DMA_CTL);
+
+	mmwrite(mmread(MANTIS_INT_STAT), MANTIS_INT_STAT);
+
+	mmwrite(mmread(MANTIS_INT_MASK) & ~(MANTIS_INT_RISCI |
+					    MANTIS_INT_RISCEN), MANTIS_INT_MASK);
+}
+
+
+void mantis_dma_xfer(unsigned long data)
+{
+	struct mantis_pci *mantis = (struct mantis_pci *) data;
+	struct mantis_hwconfig *config = mantis->hwconfig;
+
+	while (mantis->last_block != mantis->busy_block) {
+		dprintk(MANTIS_DEBUG, 1, "last block=[%d] finished block=[%d]",
+			mantis->last_block, mantis->busy_block);
+
+		(config->ts_size ? dvb_dmx_swfilter_204 : dvb_dmx_swfilter)
+		(&mantis->demux, &mantis->buf_cpu[mantis->last_block * MANTIS_BLOCK_BYTES], MANTIS_BLOCK_BYTES);
+		mantis->last_block = (mantis->last_block + 1) % MANTIS_BLOCK_COUNT;
+	}
+}
diff --git a/drivers/media/pci/mantis/mantis_dma.h b/drivers/media/pci/mantis/mantis_dma.h
new file mode 100644
index 0000000..6be00fa
--- /dev/null
+++ b/drivers/media/pci/mantis/mantis_dma.h
@@ -0,0 +1,30 @@
+/*
+	Mantis PCI bridge driver
+
+	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __MANTIS_DMA_H
+#define __MANTIS_DMA_H
+
+extern int mantis_dma_init(struct mantis_pci *mantis);
+extern int mantis_dma_exit(struct mantis_pci *mantis);
+extern void mantis_dma_start(struct mantis_pci *mantis);
+extern void mantis_dma_stop(struct mantis_pci *mantis);
+extern void mantis_dma_xfer(unsigned long data);
+
+#endif /* __MANTIS_DMA_H */
diff --git a/drivers/media/pci/mantis/mantis_dvb.c b/drivers/media/pci/mantis/mantis_dvb.c
new file mode 100644
index 0000000..5d15c6b
--- /dev/null
+++ b/drivers/media/pci/mantis/mantis_dvb.c
@@ -0,0 +1,301 @@
+/*
+	Mantis PCI bridge driver
+	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/kernel.h>
+#include <linux/bitops.h>
+
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/i2c.h>
+
+#include "dmxdev.h"
+#include "dvbdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dvb_net.h"
+
+#include "mantis_common.h"
+#include "mantis_dma.h"
+#include "mantis_ca.h"
+#include "mantis_ioc.h"
+#include "mantis_dvb.h"
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+int mantis_frontend_power(struct mantis_pci *mantis, enum mantis_power power)
+{
+	struct mantis_hwconfig *config = mantis->hwconfig;
+
+	switch (power) {
+	case POWER_ON:
+		dprintk(MANTIS_DEBUG, 1, "Power ON");
+		mantis_gpio_set_bits(mantis, config->power, POWER_ON);
+		msleep(100);
+		mantis_gpio_set_bits(mantis, config->power, POWER_ON);
+		msleep(100);
+		break;
+
+	case POWER_OFF:
+		dprintk(MANTIS_DEBUG, 1, "Power OFF");
+		mantis_gpio_set_bits(mantis, config->power, POWER_OFF);
+		msleep(100);
+		break;
+
+	default:
+		dprintk(MANTIS_DEBUG, 1, "Unknown state <%02x>", power);
+		return -1;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(mantis_frontend_power);
+
+void mantis_frontend_soft_reset(struct mantis_pci *mantis)
+{
+	struct mantis_hwconfig *config = mantis->hwconfig;
+
+	dprintk(MANTIS_DEBUG, 1, "Frontend RESET");
+	mantis_gpio_set_bits(mantis, config->reset, 0);
+	msleep(100);
+	mantis_gpio_set_bits(mantis, config->reset, 0);
+	msleep(100);
+	mantis_gpio_set_bits(mantis, config->reset, 1);
+	msleep(100);
+	mantis_gpio_set_bits(mantis, config->reset, 1);
+	msleep(100);
+
+	return;
+}
+EXPORT_SYMBOL_GPL(mantis_frontend_soft_reset);
+
+static int mantis_frontend_shutdown(struct mantis_pci *mantis)
+{
+	int err;
+
+	mantis_frontend_soft_reset(mantis);
+	err = mantis_frontend_power(mantis, POWER_OFF);
+	if (err != 0) {
+		dprintk(MANTIS_ERROR, 1, "Frontend POWER OFF failed! <%d>", err);
+		return 1;
+	}
+
+	return 0;
+}
+
+static int mantis_dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed)
+{
+	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
+	struct mantis_pci *mantis = dvbdmx->priv;
+
+	dprintk(MANTIS_DEBUG, 1, "Mantis DVB Start feed");
+	if (!dvbdmx->dmx.frontend) {
+		dprintk(MANTIS_DEBUG, 1, "no frontend ?");
+		return -EINVAL;
+	}
+
+	mantis->feeds++;
+	dprintk(MANTIS_DEBUG, 1, "mantis start feed, feeds=%d",	mantis->feeds);
+
+	if (mantis->feeds == 1)	 {
+		dprintk(MANTIS_DEBUG, 1, "mantis start feed & dma");
+		mantis_dma_start(mantis);
+		tasklet_enable(&mantis->tasklet);
+	}
+
+	return mantis->feeds;
+}
+
+static int mantis_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
+{
+	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
+	struct mantis_pci *mantis = dvbdmx->priv;
+
+	dprintk(MANTIS_DEBUG, 1, "Mantis DVB Stop feed");
+	if (!dvbdmx->dmx.frontend) {
+		dprintk(MANTIS_DEBUG, 1, "no frontend ?");
+		return -EINVAL;
+	}
+
+	mantis->feeds--;
+	if (mantis->feeds == 0) {
+		dprintk(MANTIS_DEBUG, 1, "mantis stop feed and dma");
+		tasklet_disable(&mantis->tasklet);
+		mantis_dma_stop(mantis);
+	}
+
+	return 0;
+}
+
+int __devinit mantis_dvb_init(struct mantis_pci *mantis)
+{
+	struct mantis_hwconfig *config = mantis->hwconfig;
+	int result = -1;
+
+	dprintk(MANTIS_DEBUG, 1, "dvb_register_adapter");
+
+	result = dvb_register_adapter(&mantis->dvb_adapter,
+				      "Mantis DVB adapter",
+				      THIS_MODULE,
+				      &mantis->pdev->dev,
+				      adapter_nr);
+
+	if (result < 0) {
+
+		dprintk(MANTIS_ERROR, 1, "Error registering adapter");
+		return -ENODEV;
+	}
+
+	mantis->dvb_adapter.priv	= mantis;
+	mantis->demux.dmx.capabilities	= DMX_TS_FILTERING	|
+					 DMX_SECTION_FILTERING	|
+					 DMX_MEMORY_BASED_FILTERING;
+
+	mantis->demux.priv		= mantis;
+	mantis->demux.filternum		= 256;
+	mantis->demux.feednum		= 256;
+	mantis->demux.start_feed	= mantis_dvb_start_feed;
+	mantis->demux.stop_feed		= mantis_dvb_stop_feed;
+	mantis->demux.write_to_decoder	= NULL;
+
+	dprintk(MANTIS_DEBUG, 1, "dvb_dmx_init");
+	result = dvb_dmx_init(&mantis->demux);
+	if (result < 0) {
+		dprintk(MANTIS_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result);
+
+		goto err0;
+	}
+
+	mantis->dmxdev.filternum	= 256;
+	mantis->dmxdev.demux		= &mantis->demux.dmx;
+	mantis->dmxdev.capabilities	= 0;
+	dprintk(MANTIS_DEBUG, 1, "dvb_dmxdev_init");
+
+	result = dvb_dmxdev_init(&mantis->dmxdev, &mantis->dvb_adapter);
+	if (result < 0) {
+
+		dprintk(MANTIS_ERROR, 1, "dvb_dmxdev_init failed, ERROR=%d", result);
+		goto err1;
+	}
+
+	mantis->fe_hw.source		= DMX_FRONTEND_0;
+	result = mantis->demux.dmx.add_frontend(&mantis->demux.dmx, &mantis->fe_hw);
+	if (result < 0) {
+
+		dprintk(MANTIS_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result);
+		goto err2;
+	}
+
+	mantis->fe_mem.source		= DMX_MEMORY_FE;
+	result = mantis->demux.dmx.add_frontend(&mantis->demux.dmx, &mantis->fe_mem);
+	if (result < 0) {
+		dprintk(MANTIS_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result);
+		goto err3;
+	}
+
+	result = mantis->demux.dmx.connect_frontend(&mantis->demux.dmx, &mantis->fe_hw);
+	if (result < 0) {
+		dprintk(MANTIS_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result);
+		goto err4;
+	}
+
+	dvb_net_init(&mantis->dvb_adapter, &mantis->dvbnet, &mantis->demux.dmx);
+	tasklet_init(&mantis->tasklet, mantis_dma_xfer, (unsigned long) mantis);
+	tasklet_disable(&mantis->tasklet);
+	if (mantis->hwconfig) {
+		result = config->frontend_init(mantis, mantis->fe);
+		if (result < 0) {
+			dprintk(MANTIS_ERROR, 1, "!!! NO Frontends found !!!");
+			goto err5;
+		} else {
+			if (mantis->fe == NULL) {
+				dprintk(MANTIS_ERROR, 1, "FE <NULL>");
+				goto err5;
+			}
+
+			if (dvb_register_frontend(&mantis->dvb_adapter, mantis->fe)) {
+				dprintk(MANTIS_ERROR, 1, "ERROR: Frontend registration failed");
+
+				if (mantis->fe->ops.release)
+					mantis->fe->ops.release(mantis->fe);
+
+				mantis->fe = NULL;
+				goto err5;
+			}
+		}
+	}
+
+	return 0;
+
+	/* Error conditions ..	*/
+err5:
+	tasklet_kill(&mantis->tasklet);
+	dvb_net_release(&mantis->dvbnet);
+	if (mantis->fe) {
+		dvb_unregister_frontend(mantis->fe);
+		dvb_frontend_detach(mantis->fe);
+	}
+err4:
+	mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_mem);
+
+err3:
+	mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_hw);
+
+err2:
+	dvb_dmxdev_release(&mantis->dmxdev);
+
+err1:
+	dvb_dmx_release(&mantis->demux);
+
+err0:
+	dvb_unregister_adapter(&mantis->dvb_adapter);
+
+	return result;
+}
+EXPORT_SYMBOL_GPL(mantis_dvb_init);
+
+int __devexit mantis_dvb_exit(struct mantis_pci *mantis)
+{
+	int err;
+
+	if (mantis->fe) {
+		/* mantis_ca_exit(mantis); */
+		err = mantis_frontend_shutdown(mantis);
+		if (err != 0)
+			dprintk(MANTIS_ERROR, 1, "Frontend exit while POWER ON! <%d>", err);
+		dvb_unregister_frontend(mantis->fe);
+		dvb_frontend_detach(mantis->fe);
+	}
+
+	tasklet_kill(&mantis->tasklet);
+	dvb_net_release(&mantis->dvbnet);
+
+	mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_mem);
+	mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_hw);
+
+	dvb_dmxdev_release(&mantis->dmxdev);
+	dvb_dmx_release(&mantis->demux);
+
+	dprintk(MANTIS_DEBUG, 1, "dvb_unregister_adapter");
+	dvb_unregister_adapter(&mantis->dvb_adapter);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(mantis_dvb_exit);
diff --git a/drivers/media/pci/mantis/mantis_dvb.h b/drivers/media/pci/mantis/mantis_dvb.h
new file mode 100644
index 0000000..464199d
--- /dev/null
+++ b/drivers/media/pci/mantis/mantis_dvb.h
@@ -0,0 +1,35 @@
+/*
+	Mantis PCI bridge driver
+
+	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __MANTIS_DVB_H
+#define __MANTIS_DVB_H
+
+enum mantis_power {
+	POWER_OFF	= 0,
+	POWER_ON	= 1
+};
+
+extern int mantis_frontend_power(struct mantis_pci *mantis, enum mantis_power power);
+extern void mantis_frontend_soft_reset(struct mantis_pci *mantis);
+
+extern int mantis_dvb_init(struct mantis_pci *mantis);
+extern int mantis_dvb_exit(struct mantis_pci *mantis);
+
+#endif /* __MANTIS_DVB_H */
diff --git a/drivers/media/pci/mantis/mantis_evm.c b/drivers/media/pci/mantis/mantis_evm.c
new file mode 100644
index 0000000..909ff54
--- /dev/null
+++ b/drivers/media/pci/mantis/mantis_evm.c
@@ -0,0 +1,117 @@
+/*
+	Mantis PCI bridge driver
+
+	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/kernel.h>
+
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <asm/io.h>
+
+#include "dmxdev.h"
+#include "dvbdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dvb_net.h"
+
+#include "mantis_common.h"
+#include "mantis_link.h"
+#include "mantis_hif.h"
+#include "mantis_reg.h"
+
+static void mantis_hifevm_work(struct work_struct *work)
+{
+	struct mantis_ca *ca = container_of(work, struct mantis_ca, hif_evm_work);
+	struct mantis_pci *mantis = ca->ca_priv;
+
+	u32 gpif_stat;
+
+	gpif_stat = mmread(MANTIS_GPIF_STATUS);
+
+	if (gpif_stat & MANTIS_GPIF_DETSTAT) {
+		if (gpif_stat & MANTIS_CARD_PLUGIN) {
+			dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): CAM Plugin", mantis->num);
+			mmwrite(0xdada0000, MANTIS_CARD_RESET);
+			mantis_event_cam_plugin(ca);
+			dvb_ca_en50221_camchange_irq(&ca->en50221,
+						     0,
+						     DVB_CA_EN50221_CAMCHANGE_INSERTED);
+		}
+	} else {
+		if (gpif_stat & MANTIS_CARD_PLUGOUT) {
+			dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): CAM Unplug", mantis->num);
+			mmwrite(0xdada0000, MANTIS_CARD_RESET);
+			mantis_event_cam_unplug(ca);
+			dvb_ca_en50221_camchange_irq(&ca->en50221,
+						     0,
+						     DVB_CA_EN50221_CAMCHANGE_REMOVED);
+		}
+	}
+
+	if (mantis->gpif_status & MANTIS_GPIF_EXTIRQ)
+		dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Ext IRQ", mantis->num);
+
+	if (mantis->gpif_status & MANTIS_SBUF_WSTO)
+		dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Timeout", mantis->num);
+
+	if (mantis->gpif_status & MANTIS_GPIF_OTHERR)
+		dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Alignment Error", mantis->num);
+
+	if (gpif_stat & MANTIS_SBUF_OVFLW)
+		dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Overflow", mantis->num);
+
+	if (gpif_stat & MANTIS_GPIF_BRRDY)
+		dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Read Ready", mantis->num);
+
+	if (gpif_stat & MANTIS_GPIF_INTSTAT)
+		dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): GPIF IRQ", mantis->num);
+
+	if (gpif_stat & MANTIS_SBUF_EMPTY)
+		dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Empty", mantis->num);
+
+	if (gpif_stat & MANTIS_SBUF_OPDONE) {
+		dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer operation complete", mantis->num);
+		ca->sbuf_status = MANTIS_SBUF_DATA_AVAIL;
+		ca->hif_event = MANTIS_SBUF_OPDONE;
+		wake_up(&ca->hif_opdone_wq);
+	}
+}
+
+int mantis_evmgr_init(struct mantis_ca *ca)
+{
+	struct mantis_pci *mantis = ca->ca_priv;
+
+	dprintk(MANTIS_DEBUG, 1, "Initializing Mantis Host I/F Event manager");
+	INIT_WORK(&ca->hif_evm_work, mantis_hifevm_work);
+	mantis_pcmcia_init(ca);
+	schedule_work(&ca->hif_evm_work);
+	mantis_hif_init(ca);
+	return 0;
+}
+
+void mantis_evmgr_exit(struct mantis_ca *ca)
+{
+	struct mantis_pci *mantis = ca->ca_priv;
+
+	dprintk(MANTIS_DEBUG, 1, "Mantis Host I/F Event manager exiting");
+	flush_work(&ca->hif_evm_work);
+	mantis_hif_exit(ca);
+	mantis_pcmcia_exit(ca);
+}
diff --git a/drivers/media/pci/mantis/mantis_hif.c b/drivers/media/pci/mantis/mantis_hif.c
new file mode 100644
index 0000000..10c68df
--- /dev/null
+++ b/drivers/media/pci/mantis/mantis_hif.c
@@ -0,0 +1,239 @@
+/*
+	Mantis PCI bridge driver
+
+	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+
+#include <linux/interrupt.h>
+#include <asm/io.h>
+
+#include "dmxdev.h"
+#include "dvbdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dvb_net.h"
+
+#include "mantis_common.h"
+
+#include "mantis_hif.h"
+#include "mantis_link.h" /* temporary due to physical layer stuff */
+
+#include "mantis_reg.h"
+
+
+static int mantis_hif_sbuf_opdone_wait(struct mantis_ca *ca)
+{
+	struct mantis_pci *mantis = ca->ca_priv;
+	int rc = 0;
+
+	if (wait_event_timeout(ca->hif_opdone_wq,
+			       ca->hif_event & MANTIS_SBUF_OPDONE,
+			       msecs_to_jiffies(500)) == -ERESTARTSYS) {
+
+		dprintk(MANTIS_ERROR, 1, "Adapter(%d) Slot(0): Smart buffer operation timeout !", mantis->num);
+		rc = -EREMOTEIO;
+	}
+	dprintk(MANTIS_DEBUG, 1, "Smart Buffer Operation complete");
+	ca->hif_event &= ~MANTIS_SBUF_OPDONE;
+	return rc;
+}
+
+static int mantis_hif_write_wait(struct mantis_ca *ca)
+{
+	struct mantis_pci *mantis = ca->ca_priv;
+	u32 opdone = 0, timeout = 0;
+	int rc = 0;
+
+	if (wait_event_timeout(ca->hif_write_wq,
+			       mantis->gpif_status & MANTIS_GPIF_WRACK,
+			       msecs_to_jiffies(500)) == -ERESTARTSYS) {
+
+		dprintk(MANTIS_ERROR, 1, "Adapter(%d) Slot(0): Write ACK timed out !", mantis->num);
+		rc = -EREMOTEIO;
+	}
+	dprintk(MANTIS_DEBUG, 1, "Write Acknowledged");
+	mantis->gpif_status &= ~MANTIS_GPIF_WRACK;
+	while (!opdone) {
+		opdone = (mmread(MANTIS_GPIF_STATUS) & MANTIS_SBUF_OPDONE);
+		udelay(500);
+		timeout++;
+		if (timeout > 100) {
+			dprintk(MANTIS_ERROR, 1, "Adapter(%d) Slot(0): Write operation timed out!", mantis->num);
+			rc = -ETIMEDOUT;
+			break;
+		}
+	}
+	dprintk(MANTIS_DEBUG, 1, "HIF Write success");
+	return rc;
+}
+
+
+int mantis_hif_read_mem(struct mantis_ca *ca, u32 addr)
+{
+	struct mantis_pci *mantis = ca->ca_priv;
+	u32 hif_addr = 0, data, count = 4;
+
+	dprintk(MANTIS_DEBUG, 1, "Adapter(%d) Slot(0): Request HIF Mem Read", mantis->num);
+	mutex_lock(&ca->ca_lock);
+	hif_addr &= ~MANTIS_GPIF_PCMCIAREG;
+	hif_addr &= ~MANTIS_GPIF_PCMCIAIOM;
+	hif_addr |=  MANTIS_HIF_STATUS;
+	hif_addr |=  addr;
+
+	mmwrite(hif_addr, MANTIS_GPIF_BRADDR);
+	mmwrite(count, MANTIS_GPIF_BRBYTES);
+	udelay(20);
+	mmwrite(hif_addr | MANTIS_GPIF_HIFRDWRN, MANTIS_GPIF_ADDR);
+
+	if (mantis_hif_sbuf_opdone_wait(ca) != 0) {
+		dprintk(MANTIS_ERROR, 1, "Adapter(%d) Slot(0): GPIF Smart Buffer operation failed", mantis->num);
+		mutex_unlock(&ca->ca_lock);
+		return -EREMOTEIO;
+	}
+	data = mmread(MANTIS_GPIF_DIN);
+	mutex_unlock(&ca->ca_lock);
+	dprintk(MANTIS_DEBUG, 1, "Mem Read: 0x%02x", data);
+	return (data >> 24) & 0xff;
+}
+
+int mantis_hif_write_mem(struct mantis_ca *ca, u32 addr, u8 data)
+{
+	struct mantis_slot *slot = ca->slot;
+	struct mantis_pci *mantis = ca->ca_priv;
+	u32 hif_addr = 0;
+
+	dprintk(MANTIS_DEBUG, 1, "Adapter(%d) Slot(0): Request HIF Mem Write", mantis->num);
+	mutex_lock(&ca->ca_lock);
+	hif_addr &= ~MANTIS_GPIF_HIFRDWRN;
+	hif_addr &= ~MANTIS_GPIF_PCMCIAREG;
+	hif_addr &= ~MANTIS_GPIF_PCMCIAIOM;
+	hif_addr |=  MANTIS_HIF_STATUS;
+	hif_addr |=  addr;
+
+	mmwrite(slot->slave_cfg, MANTIS_GPIF_CFGSLA); /* Slot0 alone for now */
+	mmwrite(hif_addr, MANTIS_GPIF_ADDR);
+	mmwrite(data, MANTIS_GPIF_DOUT);
+
+	if (mantis_hif_write_wait(ca) != 0) {
+		dprintk(MANTIS_ERROR, 1, "Adapter(%d) Slot(0): HIF Smart Buffer operation failed", mantis->num);
+		mutex_unlock(&ca->ca_lock);
+		return -EREMOTEIO;
+	}
+	dprintk(MANTIS_DEBUG, 1, "Mem Write: (0x%02x to 0x%02x)", data, addr);
+	mutex_unlock(&ca->ca_lock);
+
+	return 0;
+}
+
+int mantis_hif_read_iom(struct mantis_ca *ca, u32 addr)
+{
+	struct mantis_pci *mantis = ca->ca_priv;
+	u32 data, hif_addr = 0;
+
+	dprintk(MANTIS_DEBUG, 1, "Adapter(%d) Slot(0): Request HIF I/O Read", mantis->num);
+	mutex_lock(&ca->ca_lock);
+	hif_addr &= ~MANTIS_GPIF_PCMCIAREG;
+	hif_addr |=  MANTIS_GPIF_PCMCIAIOM;
+	hif_addr |=  MANTIS_HIF_STATUS;
+	hif_addr |=  addr;
+
+	mmwrite(hif_addr, MANTIS_GPIF_BRADDR);
+	mmwrite(1, MANTIS_GPIF_BRBYTES);
+	udelay(20);
+	mmwrite(hif_addr | MANTIS_GPIF_HIFRDWRN, MANTIS_GPIF_ADDR);
+
+	if (mantis_hif_sbuf_opdone_wait(ca) != 0) {
+		dprintk(MANTIS_ERROR, 1, "Adapter(%d) Slot(0): HIF Smart Buffer operation failed", mantis->num);
+		mutex_unlock(&ca->ca_lock);
+		return -EREMOTEIO;
+	}
+	data = mmread(MANTIS_GPIF_DIN);
+	dprintk(MANTIS_DEBUG, 1, "I/O Read: 0x%02x", data);
+	udelay(50);
+	mutex_unlock(&ca->ca_lock);
+
+	return (u8) data;
+}
+
+int mantis_hif_write_iom(struct mantis_ca *ca, u32 addr, u8 data)
+{
+	struct mantis_pci *mantis = ca->ca_priv;
+	u32 hif_addr = 0;
+
+	dprintk(MANTIS_DEBUG, 1, "Adapter(%d) Slot(0): Request HIF I/O Write", mantis->num);
+	mutex_lock(&ca->ca_lock);
+	hif_addr &= ~MANTIS_GPIF_PCMCIAREG;
+	hif_addr &= ~MANTIS_GPIF_HIFRDWRN;
+	hif_addr |=  MANTIS_GPIF_PCMCIAIOM;
+	hif_addr |=  MANTIS_HIF_STATUS;
+	hif_addr |=  addr;
+
+	mmwrite(hif_addr, MANTIS_GPIF_ADDR);
+	mmwrite(data, MANTIS_GPIF_DOUT);
+
+	if (mantis_hif_write_wait(ca) != 0) {
+		dprintk(MANTIS_ERROR, 1, "Adapter(%d) Slot(0): HIF Smart Buffer operation failed", mantis->num);
+		mutex_unlock(&ca->ca_lock);
+		return -EREMOTEIO;
+	}
+	dprintk(MANTIS_DEBUG, 1, "I/O Write: (0x%02x to 0x%02x)", data, addr);
+	mutex_unlock(&ca->ca_lock);
+	udelay(50);
+
+	return 0;
+}
+
+int mantis_hif_init(struct mantis_ca *ca)
+{
+	struct mantis_slot *slot = ca->slot;
+	struct mantis_pci *mantis = ca->ca_priv;
+	u32 irqcfg;
+
+	slot[0].slave_cfg = 0x70773028;
+	dprintk(MANTIS_ERROR, 1, "Adapter(%d) Initializing Mantis Host Interface", mantis->num);
+
+	mutex_lock(&ca->ca_lock);
+	irqcfg = mmread(MANTIS_GPIF_IRQCFG);
+	irqcfg = MANTIS_MASK_BRRDY	|
+		 MANTIS_MASK_WRACK	|
+		 MANTIS_MASK_EXTIRQ	|
+		 MANTIS_MASK_WSTO	|
+		 MANTIS_MASK_OTHERR	|
+		 MANTIS_MASK_OVFLW;
+
+	mmwrite(irqcfg, MANTIS_GPIF_IRQCFG);
+	mutex_unlock(&ca->ca_lock);
+
+	return 0;
+}
+
+void mantis_hif_exit(struct mantis_ca *ca)
+{
+	struct mantis_pci *mantis = ca->ca_priv;
+	u32 irqcfg;
+
+	dprintk(MANTIS_ERROR, 1, "Adapter(%d) Exiting Mantis Host Interface", mantis->num);
+	mutex_lock(&ca->ca_lock);
+	irqcfg = mmread(MANTIS_GPIF_IRQCFG);
+	irqcfg &= ~MANTIS_MASK_BRRDY;
+	mmwrite(irqcfg, MANTIS_GPIF_IRQCFG);
+	mutex_unlock(&ca->ca_lock);
+}
diff --git a/drivers/media/pci/mantis/mantis_hif.h b/drivers/media/pci/mantis/mantis_hif.h
new file mode 100644
index 0000000..9094f9e
--- /dev/null
+++ b/drivers/media/pci/mantis/mantis_hif.h
@@ -0,0 +1,29 @@
+/*
+	Mantis PCI bridge driver
+
+	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __MANTIS_HIF_H
+#define __MANTIS_HIF_H
+
+#define MANTIS_HIF_MEMRD		1
+#define MANTIS_HIF_MEMWR		2
+#define MANTIS_HIF_IOMRD		3
+#define MANTIS_HIF_IOMWR		4
+
+#endif /* __MANTIS_HIF_H */
diff --git a/drivers/media/pci/mantis/mantis_i2c.c b/drivers/media/pci/mantis/mantis_i2c.c
new file mode 100644
index 0000000..e779451
--- /dev/null
+++ b/drivers/media/pci/mantis/mantis_i2c.c
@@ -0,0 +1,266 @@
+/*
+	Mantis PCI bridge driver
+
+	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <asm/io.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <linux/i2c.h>
+
+#include "dmxdev.h"
+#include "dvbdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dvb_net.h"
+
+#include "mantis_common.h"
+#include "mantis_reg.h"
+#include "mantis_i2c.h"
+
+#define TRIALS			10000
+
+static int mantis_i2c_read(struct mantis_pci *mantis, const struct i2c_msg *msg)
+{
+	u32 rxd, i, stat, trials;
+
+	dprintk(MANTIS_INFO, 0, "        %s:  Address=[0x%02x] <R>[ ",
+		__func__, msg->addr);
+
+	for (i = 0; i < msg->len; i++) {
+		rxd = (msg->addr << 25) | (1 << 24)
+					| MANTIS_I2C_RATE_3
+					| MANTIS_I2C_STOP
+					| MANTIS_I2C_PGMODE;
+
+		if (i == (msg->len - 1))
+			rxd &= ~MANTIS_I2C_STOP;
+
+		mmwrite(MANTIS_INT_I2CDONE, MANTIS_INT_STAT);
+		mmwrite(rxd, MANTIS_I2CDATA_CTL);
+
+		/* wait for xfer completion */
+		for (trials = 0; trials < TRIALS; trials++) {
+			stat = mmread(MANTIS_INT_STAT);
+			if (stat & MANTIS_INT_I2CDONE)
+				break;
+		}
+
+		dprintk(MANTIS_TMG, 0, "I2CDONE: trials=%d\n", trials);
+
+		/* wait for xfer completion */
+		for (trials = 0; trials < TRIALS; trials++) {
+			stat = mmread(MANTIS_INT_STAT);
+			if (stat & MANTIS_INT_I2CRACK)
+				break;
+		}
+
+		dprintk(MANTIS_TMG, 0, "I2CRACK: trials=%d\n", trials);
+
+		rxd = mmread(MANTIS_I2CDATA_CTL);
+		msg->buf[i] = (u8)((rxd >> 8) & 0xFF);
+		dprintk(MANTIS_INFO, 0, "%02x ", msg->buf[i]);
+	}
+	dprintk(MANTIS_INFO, 0, "]\n");
+
+	return 0;
+}
+
+static int mantis_i2c_write(struct mantis_pci *mantis, const struct i2c_msg *msg)
+{
+	int i;
+	u32 txd = 0, stat, trials;
+
+	dprintk(MANTIS_INFO, 0, "        %s: Address=[0x%02x] <W>[ ",
+		__func__, msg->addr);
+
+	for (i = 0; i < msg->len; i++) {
+		dprintk(MANTIS_INFO, 0, "%02x ", msg->buf[i]);
+		txd = (msg->addr << 25) | (msg->buf[i] << 8)
+					| MANTIS_I2C_RATE_3
+					| MANTIS_I2C_STOP
+					| MANTIS_I2C_PGMODE;
+
+		if (i == (msg->len - 1))
+			txd &= ~MANTIS_I2C_STOP;
+
+		mmwrite(MANTIS_INT_I2CDONE, MANTIS_INT_STAT);
+		mmwrite(txd, MANTIS_I2CDATA_CTL);
+
+		/* wait for xfer completion */
+		for (trials = 0; trials < TRIALS; trials++) {
+			stat = mmread(MANTIS_INT_STAT);
+			if (stat & MANTIS_INT_I2CDONE)
+				break;
+		}
+
+		dprintk(MANTIS_TMG, 0, "I2CDONE: trials=%d\n", trials);
+
+		/* wait for xfer completion */
+		for (trials = 0; trials < TRIALS; trials++) {
+			stat = mmread(MANTIS_INT_STAT);
+			if (stat & MANTIS_INT_I2CRACK)
+				break;
+		}
+
+		dprintk(MANTIS_TMG, 0, "I2CRACK: trials=%d\n", trials);
+	}
+	dprintk(MANTIS_INFO, 0, "]\n");
+
+	return 0;
+}
+
+static int mantis_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num)
+{
+	int ret = 0, i = 0, trials;
+	u32 stat, data, txd;
+	struct mantis_pci *mantis;
+	struct mantis_hwconfig *config;
+
+	mantis = i2c_get_adapdata(adapter);
+	BUG_ON(!mantis);
+	config = mantis->hwconfig;
+	BUG_ON(!config);
+
+	dprintk(MANTIS_DEBUG, 1, "Messages:%d", num);
+	mutex_lock(&mantis->i2c_lock);
+
+	while (i < num) {
+		/* Byte MODE */
+		if ((config->i2c_mode & MANTIS_BYTE_MODE) &&
+		    ((i + 1) < num)			&&
+		    (msgs[i].len < 2)			&&
+		    (msgs[i + 1].len < 2)		&&
+		    (msgs[i + 1].flags & I2C_M_RD)) {
+
+			dprintk(MANTIS_DEBUG, 0, "        Byte MODE:\n");
+
+			/* Read operation */
+			txd = msgs[i].addr << 25 | (0x1 << 24)
+						 | (msgs[i].buf[0] << 16)
+						 | MANTIS_I2C_RATE_3;
+
+			mmwrite(txd, MANTIS_I2CDATA_CTL);
+			/* wait for xfer completion */
+			for (trials = 0; trials < TRIALS; trials++) {
+				stat = mmread(MANTIS_INT_STAT);
+				if (stat & MANTIS_INT_I2CDONE)
+					break;
+			}
+
+			/* check for xfer completion */
+			if (stat & MANTIS_INT_I2CDONE) {
+				/* check xfer was acknowledged */
+				if (stat & MANTIS_INT_I2CRACK) {
+					data = mmread(MANTIS_I2CDATA_CTL);
+					msgs[i + 1].buf[0] = (data >> 8) & 0xff;
+					dprintk(MANTIS_DEBUG, 0, "        Byte <%d> RXD=0x%02x  [%02x]\n", 0x0, data, msgs[i + 1].buf[0]);
+				} else {
+					/* I/O error */
+					dprintk(MANTIS_ERROR, 1, "        I/O error, LINE:%d", __LINE__);
+					ret = -EIO;
+					break;
+				}
+			} else {
+				/* I/O error */
+				dprintk(MANTIS_ERROR, 1, "        I/O error, LINE:%d", __LINE__);
+				ret = -EIO;
+				break;
+			}
+			i += 2; /* Write/Read operation in one go */
+		}
+
+		if (i < num) {
+			if (msgs[i].flags & I2C_M_RD)
+				ret = mantis_i2c_read(mantis, &msgs[i]);
+			else
+				ret = mantis_i2c_write(mantis, &msgs[i]);
+
+			i++;
+			if (ret < 0)
+				goto bail_out;
+		}
+
+	}
+
+	mutex_unlock(&mantis->i2c_lock);
+
+	return num;
+
+bail_out:
+	mutex_unlock(&mantis->i2c_lock);
+	return ret;
+}
+
+static u32 mantis_i2c_func(struct i2c_adapter *adapter)
+{
+	return I2C_FUNC_SMBUS_EMUL;
+}
+
+static struct i2c_algorithm mantis_algo = {
+	.master_xfer		= mantis_i2c_xfer,
+	.functionality		= mantis_i2c_func,
+};
+
+int __devinit mantis_i2c_init(struct mantis_pci *mantis)
+{
+	u32 intstat, intmask;
+	struct i2c_adapter *i2c_adapter = &mantis->adapter;
+	struct pci_dev *pdev		= mantis->pdev;
+
+	init_waitqueue_head(&mantis->i2c_wq);
+	mutex_init(&mantis->i2c_lock);
+	strncpy(i2c_adapter->name, "Mantis I2C", sizeof(i2c_adapter->name));
+	i2c_set_adapdata(i2c_adapter, mantis);
+
+	i2c_adapter->owner	= THIS_MODULE;
+	i2c_adapter->algo	= &mantis_algo;
+	i2c_adapter->algo_data	= NULL;
+	i2c_adapter->timeout	= 500;
+	i2c_adapter->retries	= 3;
+	i2c_adapter->dev.parent	= &pdev->dev;
+
+	mantis->i2c_rc		= i2c_add_adapter(i2c_adapter);
+	if (mantis->i2c_rc < 0)
+		return mantis->i2c_rc;
+
+	dprintk(MANTIS_DEBUG, 1, "Initializing I2C ..");
+
+	intstat = mmread(MANTIS_INT_STAT);
+	intmask = mmread(MANTIS_INT_MASK);
+	mmwrite(intstat, MANTIS_INT_STAT);
+	dprintk(MANTIS_DEBUG, 1, "Disabling I2C interrupt");
+	intmask = mmread(MANTIS_INT_MASK);
+	mmwrite((intmask & ~MANTIS_INT_I2CDONE), MANTIS_INT_MASK);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(mantis_i2c_init);
+
+int mantis_i2c_exit(struct mantis_pci *mantis)
+{
+	u32 intmask;
+
+	dprintk(MANTIS_DEBUG, 1, "Disabling I2C interrupt");
+	intmask = mmread(MANTIS_INT_MASK);
+	mmwrite((intmask & ~MANTIS_INT_I2CDONE), MANTIS_INT_MASK);
+
+	dprintk(MANTIS_DEBUG, 1, "Removing I2C adapter");
+	return i2c_del_adapter(&mantis->adapter);
+}
+EXPORT_SYMBOL_GPL(mantis_i2c_exit);
diff --git a/drivers/media/pci/mantis/mantis_i2c.h b/drivers/media/pci/mantis/mantis_i2c.h
new file mode 100644
index 0000000..1342df2
--- /dev/null
+++ b/drivers/media/pci/mantis/mantis_i2c.h
@@ -0,0 +1,30 @@
+/*
+	Mantis PCI bridge driver
+
+	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __MANTIS_I2C_H
+#define __MANTIS_I2C_H
+
+#define I2C_STOP		(1 <<  0)
+#define I2C_READ		(1 <<  1)
+
+extern int mantis_i2c_init(struct mantis_pci *mantis);
+extern int mantis_i2c_exit(struct mantis_pci *mantis);
+
+#endif /* __MANTIS_I2C_H */
diff --git a/drivers/media/pci/mantis/mantis_input.c b/drivers/media/pci/mantis/mantis_input.c
new file mode 100644
index 0000000..db6d54d
--- /dev/null
+++ b/drivers/media/pci/mantis/mantis_input.c
@@ -0,0 +1,159 @@
+/*
+	Mantis PCI bridge driver
+
+	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <media/rc-core.h>
+#include <linux/pci.h>
+
+#include "dmxdev.h"
+#include "dvbdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dvb_net.h"
+
+#include "mantis_common.h"
+#include "mantis_reg.h"
+#include "mantis_uart.h"
+
+#define MODULE_NAME "mantis_core"
+#define RC_MAP_MANTIS "rc-mantis"
+
+static struct rc_map_table mantis_ir_table[] = {
+	{ 0x29, KEY_POWER	},
+	{ 0x28, KEY_FAVORITES	},
+	{ 0x30, KEY_TEXT	},
+	{ 0x17, KEY_INFO	}, /* Preview */
+	{ 0x23, KEY_EPG		},
+	{ 0x3b, KEY_F22		}, /* Record List */
+	{ 0x3c, KEY_1		},
+	{ 0x3e, KEY_2		},
+	{ 0x39, KEY_3		},
+	{ 0x36, KEY_4		},
+	{ 0x22, KEY_5		},
+	{ 0x20, KEY_6		},
+	{ 0x32, KEY_7		},
+	{ 0x26, KEY_8		},
+	{ 0x24, KEY_9		},
+	{ 0x2a, KEY_0		},
+
+	{ 0x33, KEY_CANCEL	},
+	{ 0x2c, KEY_BACK	},
+	{ 0x15, KEY_CLEAR	},
+	{ 0x3f, KEY_TAB		},
+	{ 0x10, KEY_ENTER	},
+	{ 0x14, KEY_UP		},
+	{ 0x0d, KEY_RIGHT	},
+	{ 0x0e, KEY_DOWN	},
+	{ 0x11, KEY_LEFT	},
+
+	{ 0x21, KEY_VOLUMEUP	},
+	{ 0x35, KEY_VOLUMEDOWN	},
+	{ 0x3d, KEY_CHANNELDOWN	},
+	{ 0x3a, KEY_CHANNELUP	},
+	{ 0x2e, KEY_RECORD	},
+	{ 0x2b, KEY_PLAY	},
+	{ 0x13, KEY_PAUSE	},
+	{ 0x25, KEY_STOP	},
+
+	{ 0x1f, KEY_REWIND	},
+	{ 0x2d, KEY_FASTFORWARD	},
+	{ 0x1e, KEY_PREVIOUS	}, /* Replay |< */
+	{ 0x1d, KEY_NEXT	}, /* Skip   >| */
+
+	{ 0x0b, KEY_CAMERA	}, /* Capture */
+	{ 0x0f, KEY_LANGUAGE	}, /* SAP */
+	{ 0x18, KEY_MODE	}, /* PIP */
+	{ 0x12, KEY_ZOOM	}, /* Full screen */
+	{ 0x1c, KEY_SUBTITLE	},
+	{ 0x2f, KEY_MUTE	},
+	{ 0x16, KEY_F20		}, /* L/R */
+	{ 0x38, KEY_F21		}, /* Hibernate */
+
+	{ 0x37, KEY_SWITCHVIDEOMODE }, /* A/V */
+	{ 0x31, KEY_AGAIN	}, /* Recall */
+	{ 0x1a, KEY_KPPLUS	}, /* Zoom+ */
+	{ 0x19, KEY_KPMINUS	}, /* Zoom- */
+	{ 0x27, KEY_RED		},
+	{ 0x0C, KEY_GREEN	},
+	{ 0x01, KEY_YELLOW	},
+	{ 0x00, KEY_BLUE	},
+};
+
+static struct rc_map_list ir_mantis_map = {
+	.map = {
+		.scan = mantis_ir_table,
+		.size = ARRAY_SIZE(mantis_ir_table),
+		.rc_type = RC_TYPE_UNKNOWN,
+		.name = RC_MAP_MANTIS,
+	}
+};
+
+int mantis_input_init(struct mantis_pci *mantis)
+{
+	struct rc_dev *dev;
+	int err;
+
+	err = rc_map_register(&ir_mantis_map);
+	if (err)
+		goto out;
+
+	dev = rc_allocate_device();
+	if (!dev) {
+		dprintk(MANTIS_ERROR, 1, "Remote device allocation failed");
+		err = -ENOMEM;
+		goto out_map;
+	}
+
+	sprintf(mantis->input_name, "Mantis %s IR receiver", mantis->hwconfig->model_name);
+	sprintf(mantis->input_phys, "pci-%s/ir0", pci_name(mantis->pdev));
+
+	dev->input_name         = mantis->input_name;
+	dev->input_phys         = mantis->input_phys;
+	dev->input_id.bustype   = BUS_PCI;
+	dev->input_id.vendor    = mantis->vendor_id;
+	dev->input_id.product   = mantis->device_id;
+	dev->input_id.version   = 1;
+	dev->driver_name        = MODULE_NAME;
+	dev->map_name           = RC_MAP_MANTIS;
+	dev->dev.parent         = &mantis->pdev->dev;
+
+	err = rc_register_device(dev);
+	if (err) {
+		dprintk(MANTIS_ERROR, 1, "IR device registration failed, ret = %d", err);
+		goto out_dev;
+	}
+
+	mantis->rc = dev;
+	return 0;
+
+out_dev:
+	rc_free_device(dev);
+out_map:
+	rc_map_unregister(&ir_mantis_map);
+out:
+	return err;
+}
+
+int mantis_exit(struct mantis_pci *mantis)
+{
+	rc_unregister_device(mantis->rc);
+	rc_map_unregister(&ir_mantis_map);
+	return 0;
+}
+
diff --git a/drivers/media/pci/mantis/mantis_ioc.c b/drivers/media/pci/mantis/mantis_ioc.c
new file mode 100644
index 0000000..24fcdc6
--- /dev/null
+++ b/drivers/media/pci/mantis/mantis_ioc.c
@@ -0,0 +1,124 @@
+/*
+	Mantis PCI bridge driver
+
+	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <asm/io.h>
+
+#include "dmxdev.h"
+#include "dvbdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dvb_net.h"
+
+#include "mantis_common.h"
+#include "mantis_reg.h"
+#include "mantis_ioc.h"
+
+static int read_eeprom_bytes(struct mantis_pci *mantis, u8 reg, u8 *data, u8 length)
+{
+	struct i2c_adapter *adapter = &mantis->adapter;
+	int err;
+	u8 buf = reg;
+
+	struct i2c_msg msg[] = {
+		{ .addr = 0x50, .flags = 0, .buf = &buf, .len = 1 },
+		{ .addr = 0x50, .flags = I2C_M_RD, .buf = data, .len = length },
+	};
+
+	err = i2c_transfer(adapter, msg, 2);
+	if (err < 0) {
+		dprintk(MANTIS_ERROR, 1, "ERROR: i2c read: < err=%i d0=0x%02x d1=0x%02x >",
+			err, data[0], data[1]);
+
+		return err;
+	}
+
+	return 0;
+}
+int mantis_get_mac(struct mantis_pci *mantis)
+{
+	int err;
+	u8 mac_addr[6] = {0};
+
+	err = read_eeprom_bytes(mantis, 0x08, mac_addr, 6);
+	if (err < 0) {
+		dprintk(MANTIS_ERROR, 1, "ERROR: Mantis EEPROM read error <%d>", err);
+
+		return err;
+	}
+
+	dprintk(MANTIS_ERROR, 0, "    MAC Address=[%pM]\n", mac_addr);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(mantis_get_mac);
+
+/* Turn the given bit on or off. */
+void mantis_gpio_set_bits(struct mantis_pci *mantis, u32 bitpos, u8 value)
+{
+	u32 cur;
+
+	dprintk(MANTIS_DEBUG, 1, "Set Bit <%d> to <%d>", bitpos, value);
+	cur = mmread(MANTIS_GPIF_ADDR);
+	if (value)
+		mantis->gpio_status = cur | (1 << bitpos);
+	else
+		mantis->gpio_status = cur & (~(1 << bitpos));
+
+	dprintk(MANTIS_DEBUG, 1, "GPIO Value <%02x>", mantis->gpio_status);
+	mmwrite(mantis->gpio_status, MANTIS_GPIF_ADDR);
+	mmwrite(0x00, MANTIS_GPIF_DOUT);
+}
+EXPORT_SYMBOL_GPL(mantis_gpio_set_bits);
+
+int mantis_stream_control(struct mantis_pci *mantis, enum mantis_stream_control stream_ctl)
+{
+	u32 reg;
+
+	reg = mmread(MANTIS_CONTROL);
+	switch (stream_ctl) {
+	case STREAM_TO_HIF:
+		dprintk(MANTIS_DEBUG, 1, "Set stream to HIF");
+		reg &= 0xff - MANTIS_BYPASS;
+		mmwrite(reg, MANTIS_CONTROL);
+		reg |= MANTIS_BYPASS;
+		mmwrite(reg, MANTIS_CONTROL);
+		break;
+
+	case STREAM_TO_CAM:
+		dprintk(MANTIS_DEBUG, 1, "Set stream to CAM");
+		reg |= MANTIS_BYPASS;
+		mmwrite(reg, MANTIS_CONTROL);
+		reg &= 0xff - MANTIS_BYPASS;
+		mmwrite(reg, MANTIS_CONTROL);
+		break;
+	default:
+		dprintk(MANTIS_ERROR, 1, "Unknown MODE <%02x>", stream_ctl);
+		return -1;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(mantis_stream_control);
diff --git a/drivers/media/pci/mantis/mantis_ioc.h b/drivers/media/pci/mantis/mantis_ioc.h
new file mode 100644
index 0000000..d56e002
--- /dev/null
+++ b/drivers/media/pci/mantis/mantis_ioc.h
@@ -0,0 +1,51 @@
+/*
+	Mantis PCI bridge driver
+
+	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __MANTIS_IOC_H
+#define __MANTIS_IOC_H
+
+#define GPIF_A00		0x00
+#define GPIF_A01		0x01
+#define GPIF_A02		0x02
+#define GPIF_A03		0x03
+#define GPIF_A04		0x04
+#define GPIF_A05		0x05
+#define GPIF_A06		0x06
+#define GPIF_A07		0x07
+#define GPIF_A08		0x08
+#define GPIF_A09		0x09
+#define GPIF_A10		0x0a
+#define GPIF_A11		0x0b
+
+#define GPIF_A12		0x0c
+#define GPIF_A13		0x0d
+#define GPIF_A14		0x0e
+
+enum mantis_stream_control {
+	STREAM_TO_HIF = 0,
+	STREAM_TO_CAM
+};
+
+extern int mantis_get_mac(struct mantis_pci *mantis);
+extern void mantis_gpio_set_bits(struct mantis_pci *mantis, u32 bitpos, u8 value);
+
+extern int mantis_stream_control(struct mantis_pci *mantis, enum mantis_stream_control stream_ctl);
+
+#endif /* __MANTIS_IOC_H */
diff --git a/drivers/media/pci/mantis/mantis_link.h b/drivers/media/pci/mantis/mantis_link.h
new file mode 100644
index 0000000..2a81477
--- /dev/null
+++ b/drivers/media/pci/mantis/mantis_link.h
@@ -0,0 +1,83 @@
+/*
+	Mantis PCI bridge driver
+
+	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __MANTIS_LINK_H
+#define __MANTIS_LINK_H
+
+#include <linux/mutex.h>
+#include <linux/workqueue.h>
+#include "dvb_ca_en50221.h"
+
+enum mantis_sbuf_status {
+	MANTIS_SBUF_DATA_AVAIL		= 1,
+	MANTIS_SBUF_DATA_EMPTY		= 2,
+	MANTIS_SBUF_DATA_OVFLW		= 3
+};
+
+struct mantis_slot {
+	u32				timeout;
+	u32				slave_cfg;
+	u32				bar;
+};
+
+/* Physical layer */
+enum mantis_slot_state {
+	MODULE_INSERTED			= 3,
+	MODULE_XTRACTED			= 4
+};
+
+struct mantis_ca {
+	struct mantis_slot		slot[4];
+
+	struct work_struct		hif_evm_work;
+
+	u32				hif_event;
+	wait_queue_head_t		hif_opdone_wq;
+	wait_queue_head_t		hif_brrdyw_wq;
+	wait_queue_head_t		hif_data_wq;
+	wait_queue_head_t		hif_write_wq; /* HIF Write op */
+
+	enum mantis_sbuf_status		sbuf_status;
+
+	enum mantis_slot_state		slot_state;
+
+	void				*ca_priv;
+
+	struct dvb_ca_en50221		en50221;
+	struct mutex			ca_lock;
+};
+
+/* CA */
+extern void mantis_event_cam_plugin(struct mantis_ca *ca);
+extern void mantis_event_cam_unplug(struct mantis_ca *ca);
+extern int mantis_pcmcia_init(struct mantis_ca *ca);
+extern void mantis_pcmcia_exit(struct mantis_ca *ca);
+extern int mantis_evmgr_init(struct mantis_ca *ca);
+extern void mantis_evmgr_exit(struct mantis_ca *ca);
+
+/* HIF */
+extern int mantis_hif_init(struct mantis_ca *ca);
+extern void mantis_hif_exit(struct mantis_ca *ca);
+extern int mantis_hif_read_mem(struct mantis_ca *ca, u32 addr);
+extern int mantis_hif_write_mem(struct mantis_ca *ca, u32 addr, u8 data);
+extern int mantis_hif_read_iom(struct mantis_ca *ca, u32 addr);
+extern int mantis_hif_write_iom(struct mantis_ca *ca, u32 addr, u8 data);
+
+#endif /* __MANTIS_LINK_H */
diff --git a/drivers/media/pci/mantis/mantis_pci.c b/drivers/media/pci/mantis/mantis_pci.c
new file mode 100644
index 0000000..371558a
--- /dev/null
+++ b/drivers/media/pci/mantis/mantis_pci.c
@@ -0,0 +1,170 @@
+/*
+	Mantis PCI bridge driver
+
+	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <asm/io.h>
+#include <asm/page.h>
+#include <linux/kmod.h>
+#include <linux/vmalloc.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/pci.h>
+
+#include <asm/irq.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+
+#include "dmxdev.h"
+#include "dvbdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dvb_net.h"
+
+#include "mantis_common.h"
+#include "mantis_reg.h"
+#include "mantis_pci.h"
+
+#define DRIVER_NAME		"Mantis Core"
+
+int __devinit mantis_pci_init(struct mantis_pci *mantis)
+{
+	u8 latency;
+	struct mantis_hwconfig *config	= mantis->hwconfig;
+	struct pci_dev *pdev		= mantis->pdev;
+	int err, ret = 0;
+
+	dprintk(MANTIS_ERROR, 0, "found a %s PCI %s device on (%02x:%02x.%x),\n",
+		config->model_name,
+		config->dev_type,
+		mantis->pdev->bus->number,
+		PCI_SLOT(mantis->pdev->devfn),
+		PCI_FUNC(mantis->pdev->devfn));
+
+	err = pci_enable_device(pdev);
+	if (err != 0) {
+		ret = -ENODEV;
+		dprintk(MANTIS_ERROR, 1, "ERROR: PCI enable failed <%i>", err);
+		goto fail0;
+	}
+
+	err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
+	if (err != 0) {
+		dprintk(MANTIS_ERROR, 1, "ERROR: Unable to obtain 32 bit DMA <%i>", err);
+		ret = -ENOMEM;
+		goto fail1;
+	}
+
+	pci_set_master(pdev);
+
+	if (!request_mem_region(pci_resource_start(pdev, 0),
+				pci_resource_len(pdev, 0),
+				DRIVER_NAME)) {
+
+		dprintk(MANTIS_ERROR, 1, "ERROR: BAR0 Request failed !");
+		ret = -ENODEV;
+		goto fail1;
+	}
+
+	mantis->mmio = ioremap(pci_resource_start(pdev, 0),
+			       pci_resource_len(pdev, 0));
+
+	if (!mantis->mmio) {
+		dprintk(MANTIS_ERROR, 1, "ERROR: BAR0 remap failed !");
+		ret = -ENODEV;
+		goto fail2;
+	}
+
+	pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &latency);
+	mantis->latency = latency;
+	mantis->revision = pdev->revision;
+
+	dprintk(MANTIS_ERROR, 0, "    Mantis Rev %d [%04x:%04x], ",
+		mantis->revision,
+		mantis->pdev->subsystem_vendor,
+		mantis->pdev->subsystem_device);
+
+	dprintk(MANTIS_ERROR, 0,
+		"irq: %d, latency: %d\n    memory: 0x%lx, mmio: 0x%p\n",
+		mantis->pdev->irq,
+		mantis->latency,
+		mantis->mantis_addr,
+		mantis->mmio);
+
+	err = request_irq(pdev->irq,
+			  config->irq_handler,
+			  IRQF_SHARED,
+			  DRIVER_NAME,
+			  mantis);
+
+	if (err != 0) {
+
+		dprintk(MANTIS_ERROR, 1, "ERROR: IRQ registration failed ! <%d>", err);
+		ret = -ENODEV;
+		goto fail3;
+	}
+
+	pci_set_drvdata(pdev, mantis);
+	return ret;
+
+	/* Error conditions */
+fail3:
+	dprintk(MANTIS_ERROR, 1, "ERROR: <%d> I/O unmap", ret);
+	if (mantis->mmio)
+		iounmap(mantis->mmio);
+
+fail2:
+	dprintk(MANTIS_ERROR, 1, "ERROR: <%d> releasing regions", ret);
+	release_mem_region(pci_resource_start(pdev, 0),
+			   pci_resource_len(pdev, 0));
+
+fail1:
+	dprintk(MANTIS_ERROR, 1, "ERROR: <%d> disabling device", ret);
+	pci_disable_device(pdev);
+
+fail0:
+	dprintk(MANTIS_ERROR, 1, "ERROR: <%d> exiting", ret);
+	pci_set_drvdata(pdev, NULL);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(mantis_pci_init);
+
+void mantis_pci_exit(struct mantis_pci *mantis)
+{
+	struct pci_dev *pdev = mantis->pdev;
+
+	dprintk(MANTIS_NOTICE, 1, " mem: 0x%p", mantis->mmio);
+	free_irq(pdev->irq, mantis);
+	if (mantis->mmio) {
+		iounmap(mantis->mmio);
+		release_mem_region(pci_resource_start(pdev, 0),
+				   pci_resource_len(pdev, 0));
+	}
+
+	pci_disable_device(pdev);
+	pci_set_drvdata(pdev, NULL);
+}
+EXPORT_SYMBOL_GPL(mantis_pci_exit);
+
+MODULE_DESCRIPTION("Mantis PCI DTV bridge driver");
+MODULE_AUTHOR("Manu Abraham");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/pci/mantis/mantis_pci.h b/drivers/media/pci/mantis/mantis_pci.h
new file mode 100644
index 0000000..65f0045
--- /dev/null
+++ b/drivers/media/pci/mantis/mantis_pci.h
@@ -0,0 +1,27 @@
+/*
+	Mantis PCI bridge driver
+
+	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __MANTIS_PCI_H
+#define __MANTIS_PCI_H
+
+extern int mantis_pci_init(struct mantis_pci *mantis);
+extern void mantis_pci_exit(struct mantis_pci *mantis);
+
+#endif /* __MANTIS_PCI_H */
diff --git a/drivers/media/pci/mantis/mantis_pcmcia.c b/drivers/media/pci/mantis/mantis_pcmcia.c
new file mode 100644
index 0000000..2f188c0
--- /dev/null
+++ b/drivers/media/pci/mantis/mantis_pcmcia.c
@@ -0,0 +1,121 @@
+/*
+	Mantis PCI bridge driver
+
+	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/kernel.h>
+
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <asm/io.h>
+
+#include "dmxdev.h"
+#include "dvbdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dvb_net.h"
+
+#include "mantis_common.h"
+#include "mantis_link.h" /* temporary due to physical layer stuff */
+#include "mantis_reg.h"
+
+/*
+ * If Slot state is already PLUG_IN event and we are called
+ * again, definitely it is jitter alone
+ */
+void mantis_event_cam_plugin(struct mantis_ca *ca)
+{
+	struct mantis_pci *mantis = ca->ca_priv;
+
+	u32 gpif_irqcfg;
+
+	if (ca->slot_state == MODULE_XTRACTED) {
+		dprintk(MANTIS_DEBUG, 1, "Event: CAM Plugged IN: Adapter(%d) Slot(0)", mantis->num);
+		udelay(50);
+		mmwrite(0xda000000, MANTIS_CARD_RESET);
+		gpif_irqcfg  = mmread(MANTIS_GPIF_IRQCFG);
+		gpif_irqcfg |= MANTIS_MASK_PLUGOUT;
+		gpif_irqcfg &= ~MANTIS_MASK_PLUGIN;
+		mmwrite(gpif_irqcfg, MANTIS_GPIF_IRQCFG);
+		udelay(500);
+		ca->slot_state = MODULE_INSERTED;
+	}
+	udelay(100);
+}
+
+/*
+ * If Slot state is already UN_PLUG event and we are called
+ * again, definitely it is jitter alone
+ */
+void mantis_event_cam_unplug(struct mantis_ca *ca)
+{
+	struct mantis_pci *mantis = ca->ca_priv;
+
+	u32 gpif_irqcfg;
+
+	if (ca->slot_state == MODULE_INSERTED) {
+		dprintk(MANTIS_DEBUG, 1, "Event: CAM Unplugged: Adapter(%d) Slot(0)", mantis->num);
+		udelay(50);
+		mmwrite(0x00da0000, MANTIS_CARD_RESET);
+		gpif_irqcfg  = mmread(MANTIS_GPIF_IRQCFG);
+		gpif_irqcfg |= MANTIS_MASK_PLUGIN;
+		gpif_irqcfg &= ~MANTIS_MASK_PLUGOUT;
+		mmwrite(gpif_irqcfg, MANTIS_GPIF_IRQCFG);
+		udelay(500);
+		ca->slot_state = MODULE_XTRACTED;
+	}
+	udelay(100);
+}
+
+int mantis_pcmcia_init(struct mantis_ca *ca)
+{
+	struct mantis_pci *mantis = ca->ca_priv;
+
+	u32 gpif_stat, card_stat;
+
+	mmwrite(mmread(MANTIS_INT_MASK) | MANTIS_INT_IRQ0, MANTIS_INT_MASK);
+	gpif_stat = mmread(MANTIS_GPIF_STATUS);
+	card_stat = mmread(MANTIS_GPIF_IRQCFG);
+
+	if (gpif_stat & MANTIS_GPIF_DETSTAT) {
+		dprintk(MANTIS_DEBUG, 1, "CAM found on Adapter(%d) Slot(0)", mantis->num);
+		mmwrite(card_stat | MANTIS_MASK_PLUGOUT, MANTIS_GPIF_IRQCFG);
+		ca->slot_state = MODULE_INSERTED;
+		dvb_ca_en50221_camchange_irq(&ca->en50221,
+					     0,
+					     DVB_CA_EN50221_CAMCHANGE_INSERTED);
+	} else {
+		dprintk(MANTIS_DEBUG, 1, "Empty Slot on Adapter(%d) Slot(0)", mantis->num);
+		mmwrite(card_stat | MANTIS_MASK_PLUGIN, MANTIS_GPIF_IRQCFG);
+		ca->slot_state = MODULE_XTRACTED;
+		dvb_ca_en50221_camchange_irq(&ca->en50221,
+					     0,
+					     DVB_CA_EN50221_CAMCHANGE_REMOVED);
+	}
+
+	return 0;
+}
+
+void mantis_pcmcia_exit(struct mantis_ca *ca)
+{
+	struct mantis_pci *mantis = ca->ca_priv;
+
+	mmwrite(mmread(MANTIS_GPIF_STATUS) & (~MANTIS_CARD_PLUGOUT | ~MANTIS_CARD_PLUGIN), MANTIS_GPIF_STATUS);
+	mmwrite(mmread(MANTIS_INT_MASK) & ~MANTIS_INT_IRQ0, MANTIS_INT_MASK);
+}
diff --git a/drivers/media/pci/mantis/mantis_reg.h b/drivers/media/pci/mantis/mantis_reg.h
new file mode 100644
index 0000000..7761f9d
--- /dev/null
+++ b/drivers/media/pci/mantis/mantis_reg.h
@@ -0,0 +1,197 @@
+/*
+	Mantis PCI bridge driver
+
+	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __MANTIS_REG_H
+#define __MANTIS_REG_H
+
+/* Interrupts */
+#define MANTIS_INT_STAT			0x00
+#define MANTIS_INT_MASK			0x04
+
+#define MANTIS_INT_RISCSTAT		(0x0f << 28)
+#define MANTIS_INT_RISCEN		(0x01 << 27)
+#define MANTIS_INT_I2CRACK		(0x01 << 26)
+
+/* #define MANTIS_INT_GPIF			(0xff << 12) */
+
+#define MANTIS_INT_PCMCIA7		(0x01 << 19)
+#define MANTIS_INT_PCMCIA6		(0x01 << 18)
+#define MANTIS_INT_PCMCIA5		(0x01 << 17)
+#define MANTIS_INT_PCMCIA4		(0x01 << 16)
+#define MANTIS_INT_PCMCIA3		(0x01 << 15)
+#define MANTIS_INT_PCMCIA2		(0x01 << 14)
+#define MANTIS_INT_PCMCIA1		(0x01 << 13)
+#define MANTIS_INT_PCMCIA0		(0x01 << 12)
+#define MANTIS_INT_IRQ1			(0x01 << 11)
+#define MANTIS_INT_IRQ0			(0x01 << 10)
+#define MANTIS_INT_OCERR		(0x01 <<  8)
+#define MANTIS_INT_PABORT		(0x01 <<  7)
+#define MANTIS_INT_RIPERR		(0x01 <<  6)
+#define MANTIS_INT_PPERR		(0x01 <<  5)
+#define MANTIS_INT_FTRGT		(0x01 <<  3)
+#define MANTIS_INT_RISCI		(0x01 <<  1)
+#define MANTIS_INT_I2CDONE		(0x01 <<  0)
+
+/* DMA */
+#define MANTIS_DMA_CTL			0x08
+#define MANTIS_GPIF_RD			(0xff << 24)
+#define MANTIS_GPIF_WR			(0xff << 16)
+#define MANTIS_CPU_DO			(0x01 << 10)
+#define MANTIS_DRV_DO			(0x01 <<  9)
+#define	MANTIS_I2C_RD			(0x01 <<  7)
+#define MANTIS_I2C_WR			(0x01 <<  6)
+#define MANTIS_DCAP_MODE		(0x01 <<  5)
+#define MANTIS_FIFO_TP_4		(0x00 <<  3)
+#define MANTIS_FIFO_TP_8		(0x01 <<  3)
+#define MANTIS_FIFO_TP_16		(0x02 <<  3)
+#define MANTIS_FIFO_EN			(0x01 <<  2)
+#define MANTIS_DCAP_EN			(0x01 <<  1)
+#define MANTIS_RISC_EN			(0x01 <<  0)
+
+/* DEBUG */
+#define MANTIS_DEBUGREG			0x0c
+#define MANTIS_DATINV			(0x0e <<  7)
+#define MANTIS_TOP_DEBUGSEL		(0x07 <<  4)
+#define MANTIS_PCMCIA_DEBUGSEL		(0x0f <<  0)
+
+#define MANTIS_RISC_START		0x10
+#define MANTIS_RISC_PC			0x14
+
+/* I2C */
+#define MANTIS_I2CDATA_CTL		0x18
+#define MANTIS_I2C_RATE_1		(0x00 <<  6)
+#define MANTIS_I2C_RATE_2		(0x01 <<  6)
+#define MANTIS_I2C_RATE_3		(0x02 <<  6)
+#define MANTIS_I2C_RATE_4		(0x03 <<  6)
+#define MANTIS_I2C_STOP			(0x01 <<  5)
+#define MANTIS_I2C_PGMODE		(0x01 <<  3)
+
+/* DATA */
+#define MANTIS_CMD_DATA_R1		0x20
+#define MANTIS_CMD_DATA_3		(0xff << 24)
+#define MANTIS_CMD_DATA_2		(0xff << 16)
+#define MANTIS_CMD_DATA_1		(0xff <<  8)
+#define MANTIS_CMD_DATA_0		(0xff <<  0)
+
+#define MANTIS_CMD_DATA_R2		0x24
+#define MANTIS_CMD_DATA_7		(0xff << 24)
+#define MANTIS_CMD_DATA_6		(0xff << 16)
+#define MANTIS_CMD_DATA_5		(0xff <<  8)
+#define MANTIS_CMD_DATA_4		(0xff <<  0)
+
+#define MANTIS_CONTROL			0x28
+#define MANTIS_DET			(0x01 <<  7)
+#define MANTIS_DAT_CF_EN		(0x01 <<  6)
+#define MANTIS_ACS			(0x03 <<  4)
+#define MANTIS_VCCEN			(0x01 <<  3)
+#define MANTIS_BYPASS			(0x01 <<  2)
+#define MANTIS_MRST			(0x01 <<  1)
+#define MANTIS_CRST_INT			(0x01 <<  0)
+
+#define MANTIS_GPIF_CFGSLA		0x84
+#define MANTIS_GPIF_WAITSMPL		(0x07 << 28)
+#define MANTIS_GPIF_BYTEADDRSUB		(0x01 << 25)
+#define MANTIS_GPIF_WAITPOL		(0x01 << 24)
+#define MANTIS_GPIF_NCDELAY		(0x07 << 20)
+#define MANTIS_GPIF_RW2CSDELAY		(0x07 << 16)
+#define MANTIS_GPIF_SLFTIMEDMODE	(0x01 << 15)
+#define MANTIS_GPIF_SLFTIMEDDELY	(0x7f <<  8)
+#define MANTIS_GPIF_DEVTYPE		(0x07 <<  4)
+#define MANTIS_GPIF_BIGENDIAN		(0x01 <<  3)
+#define MANTIS_GPIF_FETCHCMD		(0x03 <<  1)
+#define MANTIS_GPIF_HWORDDEV		(0x01 <<  0)
+
+#define MANTIS_GPIF_WSTOPER		0x90
+#define MANTIS_GPIF_WSTOPERWREN3	(0x01 << 31)
+#define MANTIS_GPIF_PARBOOTN		(0x01 << 29)
+#define MANTIS_GPIF_WSTOPERSLID3	(0x1f << 24)
+#define MANTIS_GPIF_WSTOPERWREN2	(0x01 << 23)
+#define MANTIS_GPIF_WSTOPERSLID2	(0x1f << 16)
+#define MANTIS_GPIF_WSTOPERWREN1	(0x01 << 15)
+#define MANTIS_GPIF_WSTOPERSLID1	(0x1f <<  8)
+#define MANTIS_GPIF_WSTOPERWREN0	(0x01 <<  7)
+#define MANTIS_GPIF_WSTOPERSLID0	(0x1f <<  0)
+
+#define MANTIS_GPIF_CS2RW		0x94
+#define MANTIS_GPIF_CS2RWWREN3		(0x01 << 31)
+#define MANTIS_GPIF_CS2RWDELY3		(0x3f << 24)
+#define MANTIS_GPIF_CS2RWWREN2		(0x01 << 23)
+#define MANTIS_GPIF_CS2RWDELY2		(0x3f << 16)
+#define MANTIS_GPIF_CS2RWWREN1		(0x01 << 15)
+#define MANTIS_GPIF_CS2RWDELY1		(0x3f <<  8)
+#define MANTIS_GPIF_CS2RWWREN0		(0x01 <<  7)
+#define MANTIS_GPIF_CS2RWDELY0		(0x3f <<  0)
+
+#define MANTIS_GPIF_IRQCFG		0x98
+#define MANTIS_GPIF_IRQPOL		(0x01 <<  8)
+#define MANTIS_MASK_WRACK		(0x01 <<  7)
+#define MANTIS_MASK_BRRDY		(0x01 <<  6)
+#define MANTIS_MASK_OVFLW		(0x01 <<  5)
+#define MANTIS_MASK_OTHERR		(0x01 <<  4)
+#define MANTIS_MASK_WSTO		(0x01 <<  3)
+#define MANTIS_MASK_EXTIRQ		(0x01 <<  2)
+#define MANTIS_MASK_PLUGIN		(0x01 <<  1)
+#define MANTIS_MASK_PLUGOUT		(0x01 <<  0)
+
+#define MANTIS_GPIF_STATUS		0x9c
+#define MANTIS_SBUF_KILLOP		(0x01 << 15)
+#define MANTIS_SBUF_OPDONE		(0x01 << 14)
+#define MANTIS_SBUF_EMPTY		(0x01 << 13)
+#define MANTIS_GPIF_DETSTAT		(0x01 <<  9)
+#define MANTIS_GPIF_INTSTAT		(0x01 <<  8)
+#define MANTIS_GPIF_WRACK		(0x01 <<  7)
+#define MANTIS_GPIF_BRRDY		(0x01 <<  6)
+#define MANTIS_SBUF_OVFLW		(0x01 <<  5)
+#define MANTIS_GPIF_OTHERR		(0x01 <<  4)
+#define MANTIS_SBUF_WSTO		(0x01 <<  3)
+#define MANTIS_GPIF_EXTIRQ		(0x01 <<  2)
+#define MANTIS_CARD_PLUGIN		(0x01 <<  1)
+#define MANTIS_CARD_PLUGOUT		(0x01 <<  0)
+
+#define MANTIS_GPIF_BRADDR		0xa0
+#define MANTIS_GPIF_PCMCIAREG		(0x01 		<< 27)
+#define MANTIS_GPIF_PCMCIAIOM		(0x01 		<< 26)
+#define MANTIS_GPIF_BR_ADDR		(0xfffffff	<<  0)
+
+#define MANTIS_GPIF_BRBYTES		0xa4
+#define MANTIS_GPIF_BRCNT		(0xfff 		<<  0)
+
+#define MANTIS_PCMCIA_RESET		0xa8
+#define MANTIS_PCMCIA_RSTVAL		(0xff << 0)
+
+#define MANTIS_CARD_RESET		0xac
+
+#define MANTIS_GPIF_ADDR		0xb0
+#define MANTIS_GPIF_HIFRDWRN		(0x01		<< 31)
+#define MANTIS_GPIF_PCMCIAREG		(0x01		<< 27)
+#define MANTIS_GPIF_PCMCIAIOM		(0x01		<< 26)
+#define MANTIS_GPIF_HIFADDR		(0xfffffff	<<  0)
+
+#define MANTIS_GPIF_DOUT		0xb4
+#define MANTIS_GPIF_HIFDOUT		(0xfffffff	<<  0)
+
+#define MANTIS_GPIF_DIN			0xb8
+#define MANTIS_GPIF_HIFDIN		(0xfffffff	<<  0)
+
+#define MANTIS_GPIF_SPARE		0xbc
+#define MANTIS_GPIF_LOGICRD		(0xffff		<< 16)
+#define MANTIS_GPIF_LOGICRW		(0xffff		<<  0)
+
+#endif /* __MANTIS_REG_H */
diff --git a/drivers/media/pci/mantis/mantis_uart.c b/drivers/media/pci/mantis/mantis_uart.c
new file mode 100644
index 0000000..85e9778
--- /dev/null
+++ b/drivers/media/pci/mantis/mantis_uart.c
@@ -0,0 +1,188 @@
+/*
+	Mantis PCI bridge driver
+
+	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <asm/io.h>
+
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+
+#include "dmxdev.h"
+#include "dvbdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dvb_net.h"
+
+#include "mantis_common.h"
+#include "mantis_reg.h"
+#include "mantis_uart.h"
+
+struct mantis_uart_params {
+	enum mantis_baud	baud_rate;
+	enum mantis_parity	parity;
+};
+
+static struct {
+	char string[7];
+} rates[5] = {
+	{ "9600" },
+	{ "19200" },
+	{ "38400" },
+	{ "57600" },
+	{ "115200" }
+};
+
+static struct {
+	char string[5];
+} parity[3] = {
+	{ "NONE" },
+	{ "ODD" },
+	{ "EVEN" }
+};
+
+#define UART_MAX_BUF			16
+
+int mantis_uart_read(struct mantis_pci *mantis, u8 *data)
+{
+	struct mantis_hwconfig *config = mantis->hwconfig;
+	u32 stat = 0, i;
+
+	/* get data */
+	for (i = 0; i < (config->bytes + 1); i++) {
+
+		stat = mmread(MANTIS_UART_STAT);
+
+		if (stat & MANTIS_UART_RXFIFO_FULL) {
+			dprintk(MANTIS_ERROR, 1, "RX Fifo FULL");
+		}
+		data[i] = mmread(MANTIS_UART_RXD) & 0x3f;
+
+		dprintk(MANTIS_DEBUG, 1, "Reading ... <%02x>", data[i] & 0x3f);
+
+		if (data[i] & (1 << 7)) {
+			dprintk(MANTIS_ERROR, 1, "UART framing error");
+			return -EINVAL;
+		}
+		if (data[i] & (1 << 6)) {
+			dprintk(MANTIS_ERROR, 1, "UART parity error");
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
+static void mantis_uart_work(struct work_struct *work)
+{
+	struct mantis_pci *mantis = container_of(work, struct mantis_pci, uart_work);
+	struct mantis_hwconfig *config = mantis->hwconfig;
+	u8 buf[16];
+	int i;
+
+	mantis_uart_read(mantis, buf);
+
+	for (i = 0; i < (config->bytes + 1); i++)
+		dprintk(MANTIS_INFO, 1, "UART BUF:%d <%02x> ", i, buf[i]);
+
+	dprintk(MANTIS_DEBUG, 0, "\n");
+}
+
+static int mantis_uart_setup(struct mantis_pci *mantis,
+			     struct mantis_uart_params *params)
+{
+	u32 reg;
+
+	mmwrite((mmread(MANTIS_UART_CTL) | (params->parity & 0x3)), MANTIS_UART_CTL);
+
+	reg = mmread(MANTIS_UART_BAUD);
+
+	switch (params->baud_rate) {
+	case MANTIS_BAUD_9600:
+		reg |= 0xd8;
+		break;
+	case MANTIS_BAUD_19200:
+		reg |= 0x6c;
+		break;
+	case MANTIS_BAUD_38400:
+		reg |= 0x36;
+		break;
+	case MANTIS_BAUD_57600:
+		reg |= 0x23;
+		break;
+	case MANTIS_BAUD_115200:
+		reg |= 0x11;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	mmwrite(reg, MANTIS_UART_BAUD);
+
+	return 0;
+}
+
+int mantis_uart_init(struct mantis_pci *mantis)
+{
+	struct mantis_hwconfig *config = mantis->hwconfig;
+	struct mantis_uart_params params;
+
+	/* default parity: */
+	params.baud_rate = config->baud_rate;
+	params.parity = config->parity;
+	dprintk(MANTIS_INFO, 1, "Initializing UART @ %sbps parity:%s",
+		rates[params.baud_rate].string,
+		parity[params.parity].string);
+
+	init_waitqueue_head(&mantis->uart_wq);
+	spin_lock_init(&mantis->uart_lock);
+
+	INIT_WORK(&mantis->uart_work, mantis_uart_work);
+
+	/* disable interrupt */
+	mmwrite(mmread(MANTIS_UART_CTL) & 0xffef, MANTIS_UART_CTL);
+
+	mantis_uart_setup(mantis, &params);
+
+	/* default 1 byte */
+	mmwrite((mmread(MANTIS_UART_BAUD) | (config->bytes << 8)), MANTIS_UART_BAUD);
+
+	/* flush buffer */
+	mmwrite((mmread(MANTIS_UART_CTL) | MANTIS_UART_RXFLUSH), MANTIS_UART_CTL);
+
+	/* enable interrupt */
+	mmwrite(mmread(MANTIS_INT_MASK) | 0x800, MANTIS_INT_MASK);
+	mmwrite(mmread(MANTIS_UART_CTL) | MANTIS_UART_RXINT, MANTIS_UART_CTL);
+
+	schedule_work(&mantis->uart_work);
+	dprintk(MANTIS_DEBUG, 1, "UART successfully initialized");
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(mantis_uart_init);
+
+void mantis_uart_exit(struct mantis_pci *mantis)
+{
+	/* disable interrupt */
+	mmwrite(mmread(MANTIS_UART_CTL) & 0xffef, MANTIS_UART_CTL);
+	flush_work(&mantis->uart_work);
+}
+EXPORT_SYMBOL_GPL(mantis_uart_exit);
diff --git a/drivers/media/pci/mantis/mantis_uart.h b/drivers/media/pci/mantis/mantis_uart.h
new file mode 100644
index 0000000..ffb62a0
--- /dev/null
+++ b/drivers/media/pci/mantis/mantis_uart.h
@@ -0,0 +1,58 @@
+/*
+	Mantis PCI bridge driver
+
+	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __MANTIS_UART_H
+#define __MANTIS_UART_H
+
+#define MANTIS_UART_CTL			0xe0
+#define MANTIS_UART_RXINT		(1 << 4)
+#define MANTIS_UART_RXFLUSH		(1 << 2)
+
+#define MANTIS_UART_RXD			0xe8
+#define MANTIS_UART_BAUD		0xec
+
+#define MANTIS_UART_STAT		0xf0
+#define MANTIS_UART_RXFIFO_DATA		(1 << 7)
+#define MANTIS_UART_RXFIFO_EMPTY	(1 << 6)
+#define MANTIS_UART_RXFIFO_FULL		(1 << 3)
+#define MANTIS_UART_FRAME_ERR		(1 << 2)
+#define MANTIS_UART_PARITY_ERR		(1 << 1)
+#define MANTIS_UART_RXTHRESH_INT	(1 << 0)
+
+enum mantis_baud {
+	MANTIS_BAUD_9600	= 0,
+	MANTIS_BAUD_19200,
+	MANTIS_BAUD_38400,
+	MANTIS_BAUD_57600,
+	MANTIS_BAUD_115200
+};
+
+enum mantis_parity {
+	MANTIS_PARITY_NONE	= 0,
+	MANTIS_PARITY_EVEN,
+	MANTIS_PARITY_ODD,
+};
+
+struct mantis_pci;
+
+extern int mantis_uart_init(struct mantis_pci *mantis);
+extern void mantis_uart_exit(struct mantis_pci *mantis);
+
+#endif /* __MANTIS_UART_H */
diff --git a/drivers/media/pci/mantis/mantis_vp1033.c b/drivers/media/pci/mantis/mantis_vp1033.c
new file mode 100644
index 0000000..ad013e9
--- /dev/null
+++ b/drivers/media/pci/mantis/mantis_vp1033.c
@@ -0,0 +1,212 @@
+/*
+	Mantis VP-1033 driver
+
+	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+
+#include "dmxdev.h"
+#include "dvbdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dvb_net.h"
+
+#include "stv0299.h"
+#include "mantis_common.h"
+#include "mantis_ioc.h"
+#include "mantis_dvb.h"
+#include "mantis_vp1033.h"
+#include "mantis_reg.h"
+
+u8 lgtdqcs001f_inittab[] = {
+	0x01, 0x15,
+	0x02, 0x30,
+	0x03, 0x00,
+	0x04, 0x2a,
+	0x05, 0x85,
+	0x06, 0x02,
+	0x07, 0x00,
+	0x08, 0x00,
+	0x0c, 0x01,
+	0x0d, 0x81,
+	0x0e, 0x44,
+	0x0f, 0x94,
+	0x10, 0x3c,
+	0x11, 0x84,
+	0x12, 0xb9,
+	0x13, 0xb5,
+	0x14, 0x4f,
+	0x15, 0xc9,
+	0x16, 0x80,
+	0x17, 0x36,
+	0x18, 0xfb,
+	0x19, 0xcf,
+	0x1a, 0xbc,
+	0x1c, 0x2b,
+	0x1d, 0x27,
+	0x1e, 0x00,
+	0x1f, 0x0b,
+	0x20, 0xa1,
+	0x21, 0x60,
+	0x22, 0x00,
+	0x23, 0x00,
+	0x28, 0x00,
+	0x29, 0x28,
+	0x2a, 0x14,
+	0x2b, 0x0f,
+	0x2c, 0x09,
+	0x2d, 0x05,
+	0x31, 0x1f,
+	0x32, 0x19,
+	0x33, 0xfc,
+	0x34, 0x13,
+	0xff, 0xff,
+};
+
+#define MANTIS_MODEL_NAME	"VP-1033"
+#define MANTIS_DEV_TYPE		"DVB-S/DSS"
+
+int lgtdqcs001f_tuner_set(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct mantis_pci *mantis	= fe->dvb->priv;
+	struct i2c_adapter *adapter	= &mantis->adapter;
+
+	u8 buf[4];
+	u32 div;
+
+
+	struct i2c_msg msg = {.addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf)};
+
+	div = p->frequency / 250;
+
+	buf[0] = (div >> 8) & 0x7f;
+	buf[1] =  div & 0xff;
+	buf[2] =  0x83;
+	buf[3] =  0xc0;
+
+	if (p->frequency < 1531000)
+		buf[3] |= 0x04;
+	else
+		buf[3] &= ~0x04;
+	if (i2c_transfer(adapter, &msg, 1) < 0) {
+		dprintk(MANTIS_ERROR, 1, "Write: I2C Transfer failed");
+		return -EIO;
+	}
+	msleep_interruptible(100);
+
+	return 0;
+}
+
+int lgtdqcs001f_set_symbol_rate(struct dvb_frontend *fe,
+				u32 srate, u32 ratio)
+{
+	u8 aclk = 0;
+	u8 bclk = 0;
+
+	if (srate < 1500000) {
+		aclk = 0xb7;
+		bclk = 0x47;
+	} else if (srate < 3000000) {
+		aclk = 0xb7;
+		bclk = 0x4b;
+	} else if (srate < 7000000) {
+		aclk = 0xb7;
+		bclk = 0x4f;
+	} else if (srate < 14000000) {
+		aclk = 0xb7;
+		bclk = 0x53;
+	} else if (srate < 30000000) {
+		aclk = 0xb6;
+		bclk = 0x53;
+	} else if (srate < 45000000) {
+		aclk = 0xb4;
+		bclk = 0x51;
+	}
+	stv0299_writereg(fe, 0x13, aclk);
+	stv0299_writereg(fe, 0x14, bclk);
+
+	stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
+	stv0299_writereg(fe, 0x20, (ratio >>  8) & 0xff);
+	stv0299_writereg(fe, 0x21,  ratio & 0xf0);
+
+	return 0;
+}
+
+struct stv0299_config lgtdqcs001f_config = {
+	.demod_address		= 0x68,
+	.inittab		= lgtdqcs001f_inittab,
+	.mclk			= 88000000UL,
+	.invert			= 0,
+	.skip_reinit		= 0,
+	.volt13_op0_op1		= STV0299_VOLT13_OP0,
+	.min_delay_ms		= 100,
+	.set_symbol_rate	= lgtdqcs001f_set_symbol_rate,
+};
+
+static int vp1033_frontend_init(struct mantis_pci *mantis, struct dvb_frontend *fe)
+{
+	struct i2c_adapter *adapter	= &mantis->adapter;
+
+	int err = 0;
+
+	err = mantis_frontend_power(mantis, POWER_ON);
+	if (err == 0) {
+		mantis_frontend_soft_reset(mantis);
+		msleep(250);
+
+		dprintk(MANTIS_ERROR, 1, "Probing for STV0299 (DVB-S)");
+		fe = dvb_attach(stv0299_attach, &lgtdqcs001f_config, adapter);
+
+		if (fe) {
+			fe->ops.tuner_ops.set_params = lgtdqcs001f_tuner_set;
+			dprintk(MANTIS_ERROR, 1, "found STV0299 DVB-S frontend @ 0x%02x",
+				lgtdqcs001f_config.demod_address);
+
+			dprintk(MANTIS_ERROR, 1, "Mantis DVB-S STV0299 frontend attach success");
+		} else {
+			return -1;
+		}
+	} else {
+		dprintk(MANTIS_ERROR, 1, "Frontend on <%s> POWER ON failed! <%d>",
+			adapter->name,
+			err);
+
+		return -EIO;
+	}
+	mantis->fe = fe;
+	dprintk(MANTIS_ERROR, 1, "Done!");
+
+	return 0;
+}
+
+struct mantis_hwconfig vp1033_config = {
+	.model_name		= MANTIS_MODEL_NAME,
+	.dev_type		= MANTIS_DEV_TYPE,
+	.ts_size		= MANTIS_TS_204,
+
+	.baud_rate		= MANTIS_BAUD_9600,
+	.parity			= MANTIS_PARITY_NONE,
+	.bytes			= 0,
+
+	.frontend_init		= vp1033_frontend_init,
+	.power			= GPIF_A12,
+	.reset			= GPIF_A13,
+};
diff --git a/drivers/media/pci/mantis/mantis_vp1033.h b/drivers/media/pci/mantis/mantis_vp1033.h
new file mode 100644
index 0000000..7daaa1b
--- /dev/null
+++ b/drivers/media/pci/mantis/mantis_vp1033.h
@@ -0,0 +1,30 @@
+/*
+	Mantis VP-1033 driver
+
+	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __MANTIS_VP1033_H
+#define __MANTIS_VP1033_H
+
+#include "mantis_common.h"
+
+#define MANTIS_VP_1033_DVB_S	0x0016
+
+extern struct mantis_hwconfig vp1033_config;
+
+#endif /* __MANTIS_VP1033_H */
diff --git a/drivers/media/pci/mantis/mantis_vp1034.c b/drivers/media/pci/mantis/mantis_vp1034.c
new file mode 100644
index 0000000..430ae84
--- /dev/null
+++ b/drivers/media/pci/mantis/mantis_vp1034.c
@@ -0,0 +1,120 @@
+/*
+	Mantis VP-1034 driver
+
+	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <asm/io.h>
+
+#include "dmxdev.h"
+#include "dvbdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dvb_net.h"
+
+#include "mb86a16.h"
+#include "mantis_common.h"
+#include "mantis_ioc.h"
+#include "mantis_dvb.h"
+#include "mantis_vp1034.h"
+#include "mantis_reg.h"
+
+struct mb86a16_config vp1034_mb86a16_config = {
+	.demod_address	= 0x08,
+	.set_voltage	= vp1034_set_voltage,
+};
+
+#define MANTIS_MODEL_NAME	"VP-1034"
+#define MANTIS_DEV_TYPE		"DVB-S/DSS"
+
+int vp1034_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+{
+	struct mantis_pci *mantis = fe->dvb->priv;
+
+	switch (voltage) {
+	case SEC_VOLTAGE_13:
+		dprintk(MANTIS_ERROR, 1, "Polarization=[13V]");
+		mantis_gpio_set_bits(mantis, 13, 1);
+		mantis_gpio_set_bits(mantis, 14, 0);
+		break;
+	case SEC_VOLTAGE_18:
+		dprintk(MANTIS_ERROR, 1, "Polarization=[18V]");
+		mantis_gpio_set_bits(mantis, 13, 1);
+		mantis_gpio_set_bits(mantis, 14, 1);
+		break;
+	case SEC_VOLTAGE_OFF:
+		dprintk(MANTIS_ERROR, 1, "Frontend (dummy) POWERDOWN");
+		break;
+	default:
+		dprintk(MANTIS_ERROR, 1, "Invalid = (%d)", (u32) voltage);
+		return -EINVAL;
+	}
+	mmwrite(0x00, MANTIS_GPIF_DOUT);
+
+	return 0;
+}
+
+static int vp1034_frontend_init(struct mantis_pci *mantis, struct dvb_frontend *fe)
+{
+	struct i2c_adapter *adapter	= &mantis->adapter;
+
+	int err = 0;
+
+	err = mantis_frontend_power(mantis, POWER_ON);
+	if (err == 0) {
+		mantis_frontend_soft_reset(mantis);
+		msleep(250);
+
+		dprintk(MANTIS_ERROR, 1, "Probing for MB86A16 (DVB-S/DSS)");
+		fe = dvb_attach(mb86a16_attach, &vp1034_mb86a16_config, adapter);
+		if (fe) {
+			dprintk(MANTIS_ERROR, 1,
+			"found MB86A16 DVB-S/DSS frontend @0x%02x",
+			vp1034_mb86a16_config.demod_address);
+
+		} else {
+			return -1;
+		}
+	} else {
+		dprintk(MANTIS_ERROR, 1, "Frontend on <%s> POWER ON failed! <%d>",
+			adapter->name,
+			err);
+
+		return -EIO;
+	}
+	mantis->fe = fe;
+	dprintk(MANTIS_ERROR, 1, "Done!");
+
+	return 0;
+}
+
+struct mantis_hwconfig vp1034_config = {
+	.model_name	= MANTIS_MODEL_NAME,
+	.dev_type	= MANTIS_DEV_TYPE,
+	.ts_size	= MANTIS_TS_204,
+
+	.baud_rate	= MANTIS_BAUD_9600,
+	.parity		= MANTIS_PARITY_NONE,
+	.bytes		= 0,
+
+	.frontend_init	= vp1034_frontend_init,
+	.power		= GPIF_A12,
+	.reset		= GPIF_A13,
+};
diff --git a/drivers/media/pci/mantis/mantis_vp1034.h b/drivers/media/pci/mantis/mantis_vp1034.h
new file mode 100644
index 0000000..323f38e
--- /dev/null
+++ b/drivers/media/pci/mantis/mantis_vp1034.h
@@ -0,0 +1,33 @@
+/*
+	Mantis VP-1034 driver
+
+	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __MANTIS_VP1034_H
+#define __MANTIS_VP1034_H
+
+#include "dvb_frontend.h"
+#include "mantis_common.h"
+
+
+#define MANTIS_VP_1034_DVB_S	0x0014
+
+extern struct mantis_hwconfig vp1034_config;
+extern int vp1034_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage);
+
+#endif /* __MANTIS_VP1034_H */
diff --git a/drivers/media/pci/mantis/mantis_vp1041.c b/drivers/media/pci/mantis/mantis_vp1041.c
new file mode 100644
index 0000000..07aa887
--- /dev/null
+++ b/drivers/media/pci/mantis/mantis_vp1041.c
@@ -0,0 +1,357 @@
+/*
+	Mantis VP-1041 driver
+
+	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+
+#include "dmxdev.h"
+#include "dvbdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dvb_net.h"
+
+#include "mantis_common.h"
+#include "mantis_ioc.h"
+#include "mantis_dvb.h"
+#include "mantis_vp1041.h"
+#include "stb0899_reg.h"
+#include "stb0899_drv.h"
+#include "stb0899_cfg.h"
+#include "stb6100_cfg.h"
+#include "stb6100.h"
+#include "lnbp21.h"
+
+#define MANTIS_MODEL_NAME	"VP-1041"
+#define MANTIS_DEV_TYPE		"DSS/DVB-S/DVB-S2"
+
+static const struct stb0899_s1_reg vp1041_stb0899_s1_init_1[] = {
+
+	/* 0x0000000b, *//* SYSREG */
+	{ STB0899_DEV_ID		, 0x30 },
+	{ STB0899_DISCNTRL1		, 0x32 },
+	{ STB0899_DISCNTRL2     	, 0x80 },
+	{ STB0899_DISRX_ST0     	, 0x04 },
+	{ STB0899_DISRX_ST1     	, 0x00 },
+	{ STB0899_DISPARITY     	, 0x00 },
+	{ STB0899_DISSTATUS		, 0x20 },
+	{ STB0899_DISF22        	, 0x99 },
+	{ STB0899_DISF22RX      	, 0xa8 },
+	/* SYSREG ? */
+	{ STB0899_ACRPRESC      	, 0x11 },
+	{ STB0899_ACRDIV1       	, 0x0a },
+	{ STB0899_ACRDIV2       	, 0x05 },
+	{ STB0899_DACR1         	, 0x00 },
+	{ STB0899_DACR2         	, 0x00 },
+	{ STB0899_OUTCFG        	, 0x00 },
+	{ STB0899_MODECFG       	, 0x00 },
+	{ STB0899_IRQSTATUS_3		, 0xfe },
+	{ STB0899_IRQSTATUS_2		, 0x03 },
+	{ STB0899_IRQSTATUS_1		, 0x7c },
+	{ STB0899_IRQSTATUS_0		, 0xf4 },
+	{ STB0899_IRQMSK_3      	, 0xf3 },
+	{ STB0899_IRQMSK_2      	, 0xfc },
+	{ STB0899_IRQMSK_1      	, 0xff },
+	{ STB0899_IRQMSK_0		, 0xff },
+	{ STB0899_IRQCFG		, 0x00 },
+	{ STB0899_I2CCFG        	, 0x88 },
+	{ STB0899_I2CRPT        	, 0x58 },
+	{ STB0899_IOPVALUE5		, 0x00 },
+	{ STB0899_IOPVALUE4		, 0x33 },
+	{ STB0899_IOPVALUE3		, 0x6d },
+	{ STB0899_IOPVALUE2		, 0x90 },
+	{ STB0899_IOPVALUE1		, 0x60 },
+	{ STB0899_IOPVALUE0		, 0x00 },
+	{ STB0899_GPIO00CFG     	, 0x82 },
+	{ STB0899_GPIO01CFG     	, 0x82 },
+	{ STB0899_GPIO02CFG     	, 0x82 },
+	{ STB0899_GPIO03CFG     	, 0x82 },
+	{ STB0899_GPIO04CFG     	, 0x82 },
+	{ STB0899_GPIO05CFG     	, 0x82 },
+	{ STB0899_GPIO06CFG     	, 0x82 },
+	{ STB0899_GPIO07CFG     	, 0x82 },
+	{ STB0899_GPIO08CFG     	, 0x82 },
+	{ STB0899_GPIO09CFG     	, 0x82 },
+	{ STB0899_GPIO10CFG     	, 0x82 },
+	{ STB0899_GPIO11CFG     	, 0x82 },
+	{ STB0899_GPIO12CFG     	, 0x82 },
+	{ STB0899_GPIO13CFG     	, 0x82 },
+	{ STB0899_GPIO14CFG     	, 0x82 },
+	{ STB0899_GPIO15CFG     	, 0x82 },
+	{ STB0899_GPIO16CFG     	, 0x82 },
+	{ STB0899_GPIO17CFG     	, 0x82 },
+	{ STB0899_GPIO18CFG     	, 0x82 },
+	{ STB0899_GPIO19CFG     	, 0x82 },
+	{ STB0899_GPIO20CFG     	, 0x82 },
+	{ STB0899_SDATCFG       	, 0xb8 },
+	{ STB0899_SCLTCFG       	, 0xba },
+	{ STB0899_AGCRFCFG      	, 0x1c }, /* 0x11 */
+	{ STB0899_GPIO22        	, 0x82 }, /* AGCBB2CFG */
+	{ STB0899_GPIO21        	, 0x91 }, /* AGCBB1CFG */
+	{ STB0899_DIRCLKCFG     	, 0x82 },
+	{ STB0899_CLKOUT27CFG   	, 0x7e },
+	{ STB0899_STDBYCFG      	, 0x82 },
+	{ STB0899_CS0CFG        	, 0x82 },
+	{ STB0899_CS1CFG        	, 0x82 },
+	{ STB0899_DISEQCOCFG    	, 0x20 },
+	{ STB0899_GPIO32CFG		, 0x82 },
+	{ STB0899_GPIO33CFG		, 0x82 },
+	{ STB0899_GPIO34CFG		, 0x82 },
+	{ STB0899_GPIO35CFG		, 0x82 },
+	{ STB0899_GPIO36CFG		, 0x82 },
+	{ STB0899_GPIO37CFG		, 0x82 },
+	{ STB0899_GPIO38CFG		, 0x82 },
+	{ STB0899_GPIO39CFG		, 0x82 },
+	{ STB0899_NCOARSE       	, 0x17 }, /* 0x15 = 27 Mhz Clock, F/3 = 198MHz, F/6 = 99MHz */
+	{ STB0899_SYNTCTRL      	, 0x02 }, /* 0x00 = CLK from CLKI, 0x02 = CLK from XTALI */
+	{ STB0899_FILTCTRL      	, 0x00 },
+	{ STB0899_SYSCTRL       	, 0x01 },
+	{ STB0899_STOPCLK1      	, 0x20 },
+	{ STB0899_STOPCLK2      	, 0x00 },
+	{ STB0899_INTBUFSTATUS		, 0x00 },
+	{ STB0899_INTBUFCTRL    	, 0x0a },
+	{ 0xffff			, 0xff },
+};
+
+static const struct stb0899_s1_reg vp1041_stb0899_s1_init_3[] = {
+	{ STB0899_DEMOD         	, 0x00 },
+	{ STB0899_RCOMPC        	, 0xc9 },
+	{ STB0899_AGC1CN        	, 0x01 },
+	{ STB0899_AGC1REF       	, 0x10 },
+	{ STB0899_RTC			, 0x23 },
+	{ STB0899_TMGCFG        	, 0x4e },
+	{ STB0899_AGC2REF       	, 0x34 },
+	{ STB0899_TLSR          	, 0x84 },
+	{ STB0899_CFD           	, 0xf7 },
+	{ STB0899_ACLC			, 0x87 },
+	{ STB0899_BCLC          	, 0x94 },
+	{ STB0899_EQON          	, 0x41 },
+	{ STB0899_LDT           	, 0xf1 },
+	{ STB0899_LDT2          	, 0xe3 },
+	{ STB0899_EQUALREF      	, 0xb4 },
+	{ STB0899_TMGRAMP       	, 0x10 },
+	{ STB0899_TMGTHD        	, 0x30 },
+	{ STB0899_IDCCOMP		, 0xfd },
+	{ STB0899_QDCCOMP		, 0xff },
+	{ STB0899_POWERI		, 0x0c },
+	{ STB0899_POWERQ		, 0x0f },
+	{ STB0899_RCOMP			, 0x6c },
+	{ STB0899_AGCIQIN		, 0x80 },
+	{ STB0899_AGC2I1		, 0x06 },
+	{ STB0899_AGC2I2		, 0x00 },
+	{ STB0899_TLIR			, 0x30 },
+	{ STB0899_RTF			, 0x7f },
+	{ STB0899_DSTATUS		, 0x00 },
+	{ STB0899_LDI			, 0xbc },
+	{ STB0899_CFRM			, 0xea },
+	{ STB0899_CFRL			, 0x31 },
+	{ STB0899_NIRM			, 0x2b },
+	{ STB0899_NIRL			, 0x80 },
+	{ STB0899_ISYMB			, 0x1d },
+	{ STB0899_QSYMB			, 0xa6 },
+	{ STB0899_SFRH          	, 0x2f },
+	{ STB0899_SFRM          	, 0x68 },
+	{ STB0899_SFRL          	, 0x40 },
+	{ STB0899_SFRUPH        	, 0x2f },
+	{ STB0899_SFRUPM        	, 0x68 },
+	{ STB0899_SFRUPL        	, 0x40 },
+	{ STB0899_EQUAI1		, 0x02 },
+	{ STB0899_EQUAQ1		, 0xff },
+	{ STB0899_EQUAI2		, 0x04 },
+	{ STB0899_EQUAQ2		, 0x05 },
+	{ STB0899_EQUAI3		, 0x02 },
+	{ STB0899_EQUAQ3		, 0xfd },
+	{ STB0899_EQUAI4		, 0x03 },
+	{ STB0899_EQUAQ4		, 0x07 },
+	{ STB0899_EQUAI5		, 0x08 },
+	{ STB0899_EQUAQ5		, 0xf5 },
+	{ STB0899_DSTATUS2		, 0x00 },
+	{ STB0899_VSTATUS       	, 0x00 },
+	{ STB0899_VERROR		, 0x86 },
+	{ STB0899_IQSWAP		, 0x2a },
+	{ STB0899_ECNT1M		, 0x00 },
+	{ STB0899_ECNT1L		, 0x00 },
+	{ STB0899_ECNT2M		, 0x00 },
+	{ STB0899_ECNT2L		, 0x00 },
+	{ STB0899_ECNT3M		, 0x0a },
+	{ STB0899_ECNT3L		, 0xad },
+	{ STB0899_FECAUTO1      	, 0x06 },
+	{ STB0899_FECM			, 0x01 },
+	{ STB0899_VTH12         	, 0xb0 },
+	{ STB0899_VTH23         	, 0x7a },
+	{ STB0899_VTH34			, 0x58 },
+	{ STB0899_VTH56         	, 0x38 },
+	{ STB0899_VTH67         	, 0x34 },
+	{ STB0899_VTH78         	, 0x24 },
+	{ STB0899_PRVIT         	, 0xff },
+	{ STB0899_VITSYNC       	, 0x19 },
+	{ STB0899_RSULC         	, 0xb1 }, /* DVB = 0xb1, DSS = 0xa1 */
+	{ STB0899_TSULC         	, 0x42 },
+	{ STB0899_RSLLC         	, 0x41 },
+	{ STB0899_TSLPL			, 0x12 },
+	{ STB0899_TSCFGH        	, 0x0c },
+	{ STB0899_TSCFGM        	, 0x00 },
+	{ STB0899_TSCFGL        	, 0x00 },
+	{ STB0899_TSOUT			, 0x69 }, /* 0x0d for CAM */
+	{ STB0899_RSSYNCDEL     	, 0x00 },
+	{ STB0899_TSINHDELH     	, 0x02 },
+	{ STB0899_TSINHDELM		, 0x00 },
+	{ STB0899_TSINHDELL		, 0x00 },
+	{ STB0899_TSLLSTKM		, 0x1b },
+	{ STB0899_TSLLSTKL		, 0xb3 },
+	{ STB0899_TSULSTKM		, 0x00 },
+	{ STB0899_TSULSTKL		, 0x00 },
+	{ STB0899_PCKLENUL		, 0xbc },
+	{ STB0899_PCKLENLL		, 0xcc },
+	{ STB0899_RSPCKLEN		, 0xbd },
+	{ STB0899_TSSTATUS		, 0x90 },
+	{ STB0899_ERRCTRL1      	, 0xb6 },
+	{ STB0899_ERRCTRL2      	, 0x95 },
+	{ STB0899_ERRCTRL3      	, 0x8d },
+	{ STB0899_DMONMSK1		, 0x27 },
+	{ STB0899_DMONMSK0		, 0x03 },
+	{ STB0899_DEMAPVIT      	, 0x5c },
+	{ STB0899_PLPARM		, 0x19 },
+	{ STB0899_PDELCTRL      	, 0x48 },
+	{ STB0899_PDELCTRL2     	, 0x00 },
+	{ STB0899_BBHCTRL1      	, 0x00 },
+	{ STB0899_BBHCTRL2      	, 0x00 },
+	{ STB0899_HYSTTHRESH    	, 0x77 },
+	{ STB0899_MATCSTM		, 0x00 },
+	{ STB0899_MATCSTL		, 0x00 },
+	{ STB0899_UPLCSTM		, 0x00 },
+	{ STB0899_UPLCSTL		, 0x00 },
+	{ STB0899_DFLCSTM		, 0x00 },
+	{ STB0899_DFLCSTL		, 0x00 },
+	{ STB0899_SYNCCST		, 0x00 },
+	{ STB0899_SYNCDCSTM		, 0x00 },
+	{ STB0899_SYNCDCSTL		, 0x00 },
+	{ STB0899_ISI_ENTRY		, 0x00 },
+	{ STB0899_ISI_BIT_EN		, 0x00 },
+	{ STB0899_MATSTRM		, 0xf0 },
+	{ STB0899_MATSTRL		, 0x02 },
+	{ STB0899_UPLSTRM		, 0x45 },
+	{ STB0899_UPLSTRL		, 0x60 },
+	{ STB0899_DFLSTRM		, 0xe3 },
+	{ STB0899_DFLSTRL		, 0x00 },
+	{ STB0899_SYNCSTR		, 0x47 },
+	{ STB0899_SYNCDSTRM		, 0x05 },
+	{ STB0899_SYNCDSTRL		, 0x18 },
+	{ STB0899_CFGPDELSTATUS1	, 0x19 },
+	{ STB0899_CFGPDELSTATUS2	, 0x2b },
+	{ STB0899_BBFERRORM		, 0x00 },
+	{ STB0899_BBFERRORL		, 0x01 },
+	{ STB0899_UPKTERRORM		, 0x00 },
+	{ STB0899_UPKTERRORL		, 0x00 },
+	{ 0xffff			, 0xff },
+};
+
+struct stb0899_config vp1041_stb0899_config = {
+	.init_dev		= vp1041_stb0899_s1_init_1,
+	.init_s2_demod		= stb0899_s2_init_2,
+	.init_s1_demod		= vp1041_stb0899_s1_init_3,
+	.init_s2_fec		= stb0899_s2_init_4,
+	.init_tst		= stb0899_s1_init_5,
+
+	.demod_address 		= 0x68, /*  0xd0 >> 1 */
+
+	.xtal_freq		= 27000000,
+	.inversion		= IQ_SWAP_ON, /* 1 */
+
+	.lo_clk			= 76500000,
+	.hi_clk			= 99000000,
+
+	.esno_ave		= STB0899_DVBS2_ESNO_AVE,
+	.esno_quant		= STB0899_DVBS2_ESNO_QUANT,
+	.avframes_coarse	= STB0899_DVBS2_AVFRAMES_COARSE,
+	.avframes_fine		= STB0899_DVBS2_AVFRAMES_FINE,
+	.miss_threshold		= STB0899_DVBS2_MISS_THRESHOLD,
+	.uwp_threshold_acq	= STB0899_DVBS2_UWP_THRESHOLD_ACQ,
+	.uwp_threshold_track	= STB0899_DVBS2_UWP_THRESHOLD_TRACK,
+	.uwp_threshold_sof	= STB0899_DVBS2_UWP_THRESHOLD_SOF,
+	.sof_search_timeout	= STB0899_DVBS2_SOF_SEARCH_TIMEOUT,
+
+	.btr_nco_bits		= STB0899_DVBS2_BTR_NCO_BITS,
+	.btr_gain_shift_offset	= STB0899_DVBS2_BTR_GAIN_SHIFT_OFFSET,
+	.crl_nco_bits		= STB0899_DVBS2_CRL_NCO_BITS,
+	.ldpc_max_iter		= STB0899_DVBS2_LDPC_MAX_ITER,
+
+	.tuner_get_frequency	= stb6100_get_frequency,
+	.tuner_set_frequency	= stb6100_set_frequency,
+	.tuner_set_bandwidth	= stb6100_set_bandwidth,
+	.tuner_get_bandwidth	= stb6100_get_bandwidth,
+	.tuner_set_rfsiggain	= NULL,
+};
+
+struct stb6100_config vp1041_stb6100_config = {
+	.tuner_address	= 0x60,
+	.refclock	= 27000000,
+};
+
+static int vp1041_frontend_init(struct mantis_pci *mantis, struct dvb_frontend *fe)
+{
+	struct i2c_adapter *adapter	= &mantis->adapter;
+
+	int err = 0;
+
+	err = mantis_frontend_power(mantis, POWER_ON);
+	if (err == 0) {
+		mantis_frontend_soft_reset(mantis);
+		msleep(250);
+		mantis->fe = dvb_attach(stb0899_attach, &vp1041_stb0899_config, adapter);
+		if (mantis->fe) {
+			dprintk(MANTIS_ERROR, 1,
+				"found STB0899 DVB-S/DVB-S2 frontend @0x%02x",
+				vp1041_stb0899_config.demod_address);
+
+			if (dvb_attach(stb6100_attach, mantis->fe, &vp1041_stb6100_config, adapter)) {
+				if (!dvb_attach(lnbp21_attach, mantis->fe, adapter, 0, 0))
+					dprintk(MANTIS_ERROR, 1, "No LNBP21 found!");
+			}
+		} else {
+			return -EREMOTEIO;
+		}
+	} else {
+		dprintk(MANTIS_ERROR, 1, "Frontend on <%s> POWER ON failed! <%d>",
+			adapter->name,
+			err);
+
+		return -EIO;
+	}
+
+
+	dprintk(MANTIS_ERROR, 1, "Done!");
+
+	return 0;
+}
+
+struct mantis_hwconfig vp1041_config = {
+	.model_name	= MANTIS_MODEL_NAME,
+	.dev_type	= MANTIS_DEV_TYPE,
+	.ts_size	= MANTIS_TS_188,
+
+	.baud_rate	= MANTIS_BAUD_9600,
+	.parity		= MANTIS_PARITY_NONE,
+	.bytes		= 0,
+
+	.frontend_init	= vp1041_frontend_init,
+	.power		= GPIF_A12,
+	.reset		= GPIF_A13,
+};
diff --git a/drivers/media/pci/mantis/mantis_vp1041.h b/drivers/media/pci/mantis/mantis_vp1041.h
new file mode 100644
index 0000000..1ae5b3d
--- /dev/null
+++ b/drivers/media/pci/mantis/mantis_vp1041.h
@@ -0,0 +1,33 @@
+/*
+	Mantis VP-1041 driver
+
+	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __MANTIS_VP1041_H
+#define __MANTIS_VP1041_H
+
+#include "mantis_common.h"
+
+#define MANTIS_VP_1041_DVB_S2	0x0031
+#define SKYSTAR_HD2_10		0x0001
+#define SKYSTAR_HD2_20		0x0003
+#define CINERGY_S2_PCI_HD	0x1179
+
+extern struct mantis_hwconfig vp1041_config;
+
+#endif /* __MANTIS_VP1041_H */
diff --git a/drivers/media/pci/mantis/mantis_vp2033.c b/drivers/media/pci/mantis/mantis_vp2033.c
new file mode 100644
index 0000000..1ca6837
--- /dev/null
+++ b/drivers/media/pci/mantis/mantis_vp2033.c
@@ -0,0 +1,188 @@
+/*
+	Mantis VP-2033 driver
+
+	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+
+#include "dmxdev.h"
+#include "dvbdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dvb_net.h"
+
+#include "tda1002x.h"
+#include "mantis_common.h"
+#include "mantis_ioc.h"
+#include "mantis_dvb.h"
+#include "mantis_vp2033.h"
+
+#define MANTIS_MODEL_NAME	"VP-2033"
+#define MANTIS_DEV_TYPE		"DVB-C"
+
+struct tda1002x_config vp2033_tda1002x_cu1216_config = {
+	.demod_address = 0x18 >> 1,
+	.invert = 1,
+};
+
+struct tda10023_config vp2033_tda10023_cu1216_config = {
+	.demod_address = 0x18 >> 1,
+	.invert = 1,
+};
+
+static u8 read_pwm(struct mantis_pci *mantis)
+{
+	struct i2c_adapter *adapter = &mantis->adapter;
+
+	u8 b = 0xff;
+	u8 pwm;
+	struct i2c_msg msg[] = {
+		{.addr = 0x50, .flags = 0, .buf = &b, .len = 1},
+		{.addr = 0x50, .flags = I2C_M_RD, .buf = &pwm, .len = 1}
+	};
+
+	if ((i2c_transfer(adapter, msg, 2) != 2)
+	    || (pwm == 0xff))
+		pwm = 0x48;
+
+	return pwm;
+}
+
+static int tda1002x_cu1216_tuner_set(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct mantis_pci *mantis = fe->dvb->priv;
+	struct i2c_adapter *adapter = &mantis->adapter;
+
+	u8 buf[6];
+	struct i2c_msg msg = {.addr = 0x60, .flags = 0, .buf = buf, .len = sizeof(buf)};
+	int i;
+
+#define CU1216_IF 36125000
+#define TUNER_MUL 62500
+
+	u32 div = (p->frequency + CU1216_IF + TUNER_MUL / 2) / TUNER_MUL;
+
+	buf[0] = (div >> 8) & 0x7f;
+	buf[1] = div & 0xff;
+	buf[2] = 0xce;
+	buf[3] = (p->frequency < 150000000 ? 0x01 :
+		  p->frequency < 445000000 ? 0x02 : 0x04);
+	buf[4] = 0xde;
+	buf[5] = 0x20;
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+
+	if (i2c_transfer(adapter, &msg, 1) != 1)
+		return -EIO;
+
+	/* wait for the pll lock */
+	msg.flags = I2C_M_RD;
+	msg.len = 1;
+	for (i = 0; i < 20; i++) {
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 1);
+
+		if (i2c_transfer(adapter, &msg, 1) == 1 && (buf[0] & 0x40))
+			break;
+
+		msleep(10);
+	}
+
+	/* switch the charge pump to the lower current */
+	msg.flags = 0;
+	msg.len = 2;
+	msg.buf = &buf[2];
+	buf[2] &= ~0x40;
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+
+	if (i2c_transfer(adapter, &msg, 1) != 1)
+		return -EIO;
+
+	return 0;
+}
+
+static int vp2033_frontend_init(struct mantis_pci *mantis, struct dvb_frontend *fe)
+{
+	struct i2c_adapter *adapter = &mantis->adapter;
+
+	int err = 0;
+
+	err = mantis_frontend_power(mantis, POWER_ON);
+	if (err == 0) {
+		mantis_frontend_soft_reset(mantis);
+		msleep(250);
+
+		dprintk(MANTIS_ERROR, 1, "Probing for CU1216 (DVB-C)");
+		fe = dvb_attach(tda10021_attach, &vp2033_tda1002x_cu1216_config,
+				     adapter,
+				     read_pwm(mantis));
+
+		if (fe) {
+			dprintk(MANTIS_ERROR, 1,
+				"found Philips CU1216 DVB-C frontend (TDA10021) @ 0x%02x",
+				vp2033_tda1002x_cu1216_config.demod_address);
+		} else {
+			fe = dvb_attach(tda10023_attach, &vp2033_tda10023_cu1216_config,
+					     adapter,
+					     read_pwm(mantis));
+
+			if (fe) {
+				dprintk(MANTIS_ERROR, 1,
+					"found Philips CU1216 DVB-C frontend (TDA10023) @ 0x%02x",
+					vp2033_tda1002x_cu1216_config.demod_address);
+			}
+		}
+
+		if (fe) {
+			fe->ops.tuner_ops.set_params = tda1002x_cu1216_tuner_set;
+			dprintk(MANTIS_ERROR, 1, "Mantis DVB-C Philips CU1216 frontend attach success");
+		} else {
+			return -1;
+		}
+	} else {
+		dprintk(MANTIS_ERROR, 1, "Frontend on <%s> POWER ON failed! <%d>",
+			adapter->name,
+			err);
+
+		return -EIO;
+	}
+
+	mantis->fe = fe;
+	dprintk(MANTIS_DEBUG, 1, "Done!");
+
+	return 0;
+}
+
+struct mantis_hwconfig vp2033_config = {
+	.model_name	= MANTIS_MODEL_NAME,
+	.dev_type	= MANTIS_DEV_TYPE,
+	.ts_size	= MANTIS_TS_204,
+
+	.baud_rate	= MANTIS_BAUD_9600,
+	.parity		= MANTIS_PARITY_NONE,
+	.bytes		= 0,
+
+	.frontend_init	= vp2033_frontend_init,
+	.power		= GPIF_A12,
+	.reset		= GPIF_A13,
+};
diff --git a/drivers/media/pci/mantis/mantis_vp2033.h b/drivers/media/pci/mantis/mantis_vp2033.h
new file mode 100644
index 0000000..c55242b
--- /dev/null
+++ b/drivers/media/pci/mantis/mantis_vp2033.h
@@ -0,0 +1,30 @@
+/*
+	Mantis VP-2033 driver
+
+	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __MANTIS_VP2033_H
+#define __MANTIS_VP2033_H
+
+#include "mantis_common.h"
+
+#define MANTIS_VP_2033_DVB_C	0x0008
+
+extern struct mantis_hwconfig vp2033_config;
+
+#endif /* __MANTIS_VP2033_H */
diff --git a/drivers/media/pci/mantis/mantis_vp2040.c b/drivers/media/pci/mantis/mantis_vp2040.c
new file mode 100644
index 0000000..d480741
--- /dev/null
+++ b/drivers/media/pci/mantis/mantis_vp2040.c
@@ -0,0 +1,187 @@
+/*
+	Mantis VP-2040 driver
+
+	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+
+#include "dmxdev.h"
+#include "dvbdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dvb_net.h"
+
+#include "tda1002x.h"
+#include "mantis_common.h"
+#include "mantis_ioc.h"
+#include "mantis_dvb.h"
+#include "mantis_vp2040.h"
+
+#define MANTIS_MODEL_NAME	"VP-2040"
+#define MANTIS_DEV_TYPE		"DVB-C"
+
+struct tda1002x_config vp2040_tda1002x_cu1216_config = {
+	.demod_address	= 0x18 >> 1,
+	.invert		= 1,
+};
+
+struct tda10023_config vp2040_tda10023_cu1216_config = {
+	.demod_address	= 0x18 >> 1,
+	.invert		= 1,
+};
+
+static int tda1002x_cu1216_tuner_set(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct mantis_pci *mantis	= fe->dvb->priv;
+	struct i2c_adapter *adapter	= &mantis->adapter;
+
+	u8 buf[6];
+	struct i2c_msg msg = {.addr = 0x60, .flags = 0, .buf = buf, .len = sizeof(buf)};
+	int i;
+
+#define CU1216_IF 36125000
+#define TUNER_MUL 62500
+
+	u32 div = (p->frequency + CU1216_IF + TUNER_MUL / 2) / TUNER_MUL;
+
+	buf[0] = (div >> 8) & 0x7f;
+	buf[1] = div & 0xff;
+	buf[2] = 0xce;
+	buf[3] = (p->frequency < 150000000 ? 0x01 :
+		  p->frequency < 445000000 ? 0x02 : 0x04);
+	buf[4] = 0xde;
+	buf[5] = 0x20;
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+
+	if (i2c_transfer(adapter, &msg, 1) != 1)
+		return -EIO;
+
+	/* wait for the pll lock */
+	msg.flags = I2C_M_RD;
+	msg.len = 1;
+	for (i = 0; i < 20; i++) {
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 1);
+
+		if (i2c_transfer(adapter, &msg, 1) == 1 && (buf[0] & 0x40))
+			break;
+
+		msleep(10);
+	}
+
+	/* switch the charge pump to the lower current */
+	msg.flags = 0;
+	msg.len = 2;
+	msg.buf = &buf[2];
+	buf[2] &= ~0x40;
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+
+	if (i2c_transfer(adapter, &msg, 1) != 1)
+		return -EIO;
+
+	return 0;
+}
+
+static u8 read_pwm(struct mantis_pci *mantis)
+{
+	struct i2c_adapter *adapter = &mantis->adapter;
+
+	u8 b = 0xff;
+	u8 pwm;
+	struct i2c_msg msg[] = {
+		{.addr = 0x50, .flags = 0, .buf = &b, .len = 1},
+		{.addr = 0x50, .flags = I2C_M_RD, .buf = &pwm, .len = 1}
+	};
+
+	if ((i2c_transfer(adapter, msg, 2) != 2)
+	    || (pwm == 0xff))
+		pwm = 0x48;
+
+	return pwm;
+}
+
+static int vp2040_frontend_init(struct mantis_pci *mantis, struct dvb_frontend *fe)
+{
+	struct i2c_adapter *adapter = &mantis->adapter;
+
+	int err = 0;
+
+	err = mantis_frontend_power(mantis, POWER_ON);
+	if (err == 0) {
+		mantis_frontend_soft_reset(mantis);
+		msleep(250);
+
+		dprintk(MANTIS_ERROR, 1, "Probing for CU1216 (DVB-C)");
+		fe = dvb_attach(tda10021_attach, &vp2040_tda1002x_cu1216_config,
+				     adapter,
+				     read_pwm(mantis));
+
+		if (fe) {
+			dprintk(MANTIS_ERROR, 1,
+				"found Philips CU1216 DVB-C frontend (TDA10021) @ 0x%02x",
+				vp2040_tda1002x_cu1216_config.demod_address);
+		} else {
+			fe = dvb_attach(tda10023_attach, &vp2040_tda10023_cu1216_config,
+					     adapter,
+					     read_pwm(mantis));
+
+			if (fe) {
+				dprintk(MANTIS_ERROR, 1,
+					"found Philips CU1216 DVB-C frontend (TDA10023) @ 0x%02x",
+					vp2040_tda1002x_cu1216_config.demod_address);
+			}
+		}
+
+		if (fe) {
+			fe->ops.tuner_ops.set_params = tda1002x_cu1216_tuner_set;
+			dprintk(MANTIS_ERROR, 1, "Mantis DVB-C Philips CU1216 frontend attach success");
+		} else {
+			return -1;
+		}
+	} else {
+		dprintk(MANTIS_ERROR, 1, "Frontend on <%s> POWER ON failed! <%d>",
+			adapter->name,
+			err);
+
+		return -EIO;
+	}
+	mantis->fe = fe;
+	dprintk(MANTIS_DEBUG, 1, "Done!");
+
+	return 0;
+}
+
+struct mantis_hwconfig vp2040_config = {
+	.model_name	= MANTIS_MODEL_NAME,
+	.dev_type	= MANTIS_DEV_TYPE,
+	.ts_size	= MANTIS_TS_204,
+
+	.baud_rate	= MANTIS_BAUD_9600,
+	.parity		= MANTIS_PARITY_NONE,
+	.bytes		= 0,
+
+	.frontend_init	= vp2040_frontend_init,
+	.power		= GPIF_A12,
+	.reset		= GPIF_A13,
+};
diff --git a/drivers/media/pci/mantis/mantis_vp2040.h b/drivers/media/pci/mantis/mantis_vp2040.h
new file mode 100644
index 0000000..d125e21
--- /dev/null
+++ b/drivers/media/pci/mantis/mantis_vp2040.h
@@ -0,0 +1,32 @@
+/*
+	Mantis VP-2040 driver
+
+	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __MANTIS_VP2040_H
+#define __MANTIS_VP2040_H
+
+#include "mantis_common.h"
+
+#define MANTIS_VP_2040_DVB_C	0x0043
+#define CINERGY_C		0x1178
+#define CABLESTAR_HD2		0x0002
+
+extern struct mantis_hwconfig vp2040_config;
+
+#endif /* __MANTIS_VP2040_H */
diff --git a/drivers/media/pci/mantis/mantis_vp3028.c b/drivers/media/pci/mantis/mantis_vp3028.c
new file mode 100644
index 0000000..4155c83
--- /dev/null
+++ b/drivers/media/pci/mantis/mantis_vp3028.c
@@ -0,0 +1,38 @@
+/*
+	Mantis VP-3028 driver
+
+	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "mantis_common.h"
+#include "mantis_vp3028.h"
+
+struct zl10353_config mantis_vp3028_config = {
+	.demod_address	= 0x0f,
+};
+
+#define MANTIS_MODEL_NAME	"VP-3028"
+#define MANTIS_DEV_TYPE		"DVB-T"
+
+struct mantis_hwconfig vp3028_mantis_config = {
+	.model_name	= MANTIS_MODEL_NAME,
+	.dev_type	= MANTIS_DEV_TYPE,
+	.ts_size	= MANTIS_TS_188,
+	.baud_rate	= MANTIS_BAUD_9600,
+	.parity		= MANTIS_PARITY_NONE,
+	.bytes		= 0,
+};
diff --git a/drivers/media/pci/mantis/mantis_vp3028.h b/drivers/media/pci/mantis/mantis_vp3028.h
new file mode 100644
index 0000000..b07be6a
--- /dev/null
+++ b/drivers/media/pci/mantis/mantis_vp3028.h
@@ -0,0 +1,33 @@
+/*
+	Mantis VP-3028 driver
+
+	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __MANTIS_VP3028_H
+#define __MANTIS_VP3028_H
+
+#include "dvb_frontend.h"
+#include "mantis_common.h"
+#include "zl10353.h"
+
+#define MANTIS_VP_3028_DVB_T	0x0028
+
+extern struct zl10353_config mantis_vp3028_config;
+extern struct mantis_hwconfig vp3028_mantis_config;
+
+#endif /* __MANTIS_VP3028_H */
diff --git a/drivers/media/pci/mantis/mantis_vp3030.c b/drivers/media/pci/mantis/mantis_vp3030.c
new file mode 100644
index 0000000..c09308cd
--- /dev/null
+++ b/drivers/media/pci/mantis/mantis_vp3030.c
@@ -0,0 +1,105 @@
+/*
+	Mantis VP-3030 driver
+
+	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+
+#include "dmxdev.h"
+#include "dvbdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dvb_net.h"
+
+#include "zl10353.h"
+#include "tda665x.h"
+#include "mantis_common.h"
+#include "mantis_ioc.h"
+#include "mantis_dvb.h"
+#include "mantis_vp3030.h"
+
+struct zl10353_config mantis_vp3030_config = {
+	.demod_address		= 0x0f,
+};
+
+struct tda665x_config env57h12d5_config = {
+	.name			= "ENV57H12D5 (ET-50DT)",
+	.addr			= 0x60,
+	.frequency_min		=  47000000,
+	.frequency_max		= 862000000,
+	.frequency_offst	=   3616667,
+	.ref_multiplier		= 6, /* 1/6 MHz */
+	.ref_divider		= 100000, /* 1/6 MHz */
+};
+
+#define MANTIS_MODEL_NAME	"VP-3030"
+#define MANTIS_DEV_TYPE		"DVB-T"
+
+
+static int vp3030_frontend_init(struct mantis_pci *mantis, struct dvb_frontend *fe)
+{
+	struct i2c_adapter *adapter	= &mantis->adapter;
+	struct mantis_hwconfig *config	= mantis->hwconfig;
+	int err = 0;
+
+	mantis_gpio_set_bits(mantis, config->reset, 0);
+	msleep(100);
+	err = mantis_frontend_power(mantis, POWER_ON);
+	msleep(100);
+	mantis_gpio_set_bits(mantis, config->reset, 1);
+
+	if (err == 0) {
+		msleep(250);
+		dprintk(MANTIS_ERROR, 1, "Probing for 10353 (DVB-T)");
+		fe = dvb_attach(zl10353_attach, &mantis_vp3030_config, adapter);
+
+		if (!fe)
+			return -1;
+
+		dvb_attach(tda665x_attach, fe, &env57h12d5_config, adapter);
+	} else {
+		dprintk(MANTIS_ERROR, 1, "Frontend on <%s> POWER ON failed! <%d>",
+			adapter->name,
+			err);
+
+		return -EIO;
+
+	}
+	mantis->fe = fe;
+	dprintk(MANTIS_ERROR, 1, "Done!");
+
+	return 0;
+}
+
+struct mantis_hwconfig vp3030_config = {
+	.model_name	= MANTIS_MODEL_NAME,
+	.dev_type	= MANTIS_DEV_TYPE,
+	.ts_size	= MANTIS_TS_188,
+
+	.baud_rate	= MANTIS_BAUD_9600,
+	.parity		= MANTIS_PARITY_NONE,
+	.bytes		= 0,
+
+	.frontend_init	= vp3030_frontend_init,
+	.power		= GPIF_A12,
+	.reset		= GPIF_A13,
+
+	.i2c_mode	= MANTIS_BYTE_MODE
+};
diff --git a/drivers/media/pci/mantis/mantis_vp3030.h b/drivers/media/pci/mantis/mantis_vp3030.h
new file mode 100644
index 0000000..5f12c42
--- /dev/null
+++ b/drivers/media/pci/mantis/mantis_vp3030.h
@@ -0,0 +1,30 @@
+/*
+	Mantis VP-3030 driver
+
+	Copyright (C) Manu Abraham (abraham.manu@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __MANTIS_VP3030_H
+#define __MANTIS_VP3030_H
+
+#include "mantis_common.h"
+
+#define MANTIS_VP_3030_DVB_T	0x0024
+
+extern struct mantis_hwconfig vp3030_config;
+
+#endif /* __MANTIS_VP3030_H */
diff --git a/drivers/media/pci/meye/Kconfig b/drivers/media/pci/meye/Kconfig
new file mode 100644
index 0000000..b4bf848
--- /dev/null
+++ b/drivers/media/pci/meye/Kconfig
@@ -0,0 +1,13 @@
+config VIDEO_MEYE
+	tristate "Sony Vaio Picturebook Motion Eye Video For Linux"
+	depends on PCI && SONY_LAPTOP && VIDEO_V4L2
+	---help---
+	  This is the video4linux driver for the Motion Eye camera found
+	  in the Vaio Picturebook laptops. Please read the material in
+	  <file:Documentation/video4linux/meye.txt> for more information.
+
+	  If you say Y or M here, you need to say Y or M to "Sony Laptop
+	  Extras" in the misc device section.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called meye.
diff --git a/drivers/media/pci/meye/Makefile b/drivers/media/pci/meye/Makefile
new file mode 100644
index 0000000..4938851
--- /dev/null
+++ b/drivers/media/pci/meye/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_VIDEO_MEYE) += meye.o
diff --git a/drivers/media/pci/meye/meye.c b/drivers/media/pci/meye/meye.c
new file mode 100644
index 0000000..e5a76da
--- /dev/null
+++ b/drivers/media/pci/meye/meye.c
@@ -0,0 +1,1964 @@
+/*
+ * Motion Eye video4linux driver for Sony Vaio PictureBook
+ *
+ * Copyright (C) 2001-2004 Stelian Pop <stelian@popies.net>
+ *
+ * Copyright (C) 2001-2002 Alcôve <www.alcove.com>
+ *
+ * Copyright (C) 2000 Andrew Tridgell <tridge@valinux.com>
+ *
+ * Earlier work by Werner Almesberger, Paul `Rusty' Russell and Paul Mackerras.
+ *
+ * Some parts borrowed from various video4linux drivers, especially
+ * bttv-driver.c and zoran.c, see original files for credits.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/pci.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/gfp.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/vmalloc.h>
+#include <linux/dma-mapping.h>
+
+#include "meye.h"
+#include <linux/meye.h>
+
+MODULE_AUTHOR("Stelian Pop <stelian@popies.net>");
+MODULE_DESCRIPTION("v4l2 driver for the MotionEye camera");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(MEYE_DRIVER_VERSION);
+
+/* number of grab buffers */
+static unsigned int gbuffers = 2;
+module_param(gbuffers, int, 0444);
+MODULE_PARM_DESC(gbuffers, "number of capture buffers, default is 2 (32 max)");
+
+/* size of a grab buffer */
+static unsigned int gbufsize = MEYE_MAX_BUFSIZE;
+module_param(gbufsize, int, 0444);
+MODULE_PARM_DESC(gbufsize, "size of the capture buffers, default is 614400"
+		 " (will be rounded up to a page multiple)");
+
+/* /dev/videoX registration number */
+static int video_nr = -1;
+module_param(video_nr, int, 0444);
+MODULE_PARM_DESC(video_nr, "video device to register (0=/dev/video0, etc)");
+
+/* driver structure - only one possible */
+static struct meye meye;
+
+/****************************************************************************/
+/* Memory allocation routines (stolen from bttv-driver.c)                   */
+/****************************************************************************/
+static void *rvmalloc(unsigned long size)
+{
+	void *mem;
+	unsigned long adr;
+
+	size = PAGE_ALIGN(size);
+	mem = vmalloc_32(size);
+	if (mem) {
+		memset(mem, 0, size);
+		adr = (unsigned long) mem;
+		while (size > 0) {
+			SetPageReserved(vmalloc_to_page((void *)adr));
+			adr += PAGE_SIZE;
+			size -= PAGE_SIZE;
+		}
+	}
+	return mem;
+}
+
+static void rvfree(void * mem, unsigned long size)
+{
+	unsigned long adr;
+
+	if (mem) {
+		adr = (unsigned long) mem;
+		while ((long) size > 0) {
+			ClearPageReserved(vmalloc_to_page((void *)adr));
+			adr += PAGE_SIZE;
+			size -= PAGE_SIZE;
+		}
+		vfree(mem);
+	}
+}
+
+/*
+ * return a page table pointing to N pages of locked memory
+ *
+ * NOTE: The meye device expects DMA addresses on 32 bits, we build
+ * a table of 1024 entries = 4 bytes * 1024 = 4096 bytes.
+ */
+static int ptable_alloc(void)
+{
+	u32 *pt;
+	int i;
+
+	memset(meye.mchip_ptable, 0, sizeof(meye.mchip_ptable));
+
+	/* give only 32 bit DMA addresses */
+	if (dma_set_mask(&meye.mchip_dev->dev, DMA_BIT_MASK(32)))
+		return -1;
+
+	meye.mchip_ptable_toc = dma_alloc_coherent(&meye.mchip_dev->dev,
+						   PAGE_SIZE,
+						   &meye.mchip_dmahandle,
+						   GFP_KERNEL);
+	if (!meye.mchip_ptable_toc) {
+		meye.mchip_dmahandle = 0;
+		return -1;
+	}
+
+	pt = meye.mchip_ptable_toc;
+	for (i = 0; i < MCHIP_NB_PAGES; i++) {
+		dma_addr_t dma;
+		meye.mchip_ptable[i] = dma_alloc_coherent(&meye.mchip_dev->dev,
+							  PAGE_SIZE,
+							  &dma,
+							  GFP_KERNEL);
+		if (!meye.mchip_ptable[i]) {
+			int j;
+			pt = meye.mchip_ptable_toc;
+			for (j = 0; j < i; ++j) {
+				dma = (dma_addr_t) *pt;
+				dma_free_coherent(&meye.mchip_dev->dev,
+						  PAGE_SIZE,
+						  meye.mchip_ptable[j], dma);
+				pt++;
+			}
+			dma_free_coherent(&meye.mchip_dev->dev,
+					  PAGE_SIZE,
+					  meye.mchip_ptable_toc,
+					  meye.mchip_dmahandle);
+			meye.mchip_ptable_toc = NULL;
+			meye.mchip_dmahandle = 0;
+			return -1;
+		}
+		*pt = (u32) dma;
+		pt++;
+	}
+	return 0;
+}
+
+static void ptable_free(void)
+{
+	u32 *pt;
+	int i;
+
+	pt = meye.mchip_ptable_toc;
+	for (i = 0; i < MCHIP_NB_PAGES; i++) {
+		dma_addr_t dma = (dma_addr_t) *pt;
+		if (meye.mchip_ptable[i])
+			dma_free_coherent(&meye.mchip_dev->dev,
+					  PAGE_SIZE,
+					  meye.mchip_ptable[i], dma);
+		pt++;
+	}
+
+	if (meye.mchip_ptable_toc)
+		dma_free_coherent(&meye.mchip_dev->dev,
+				  PAGE_SIZE,
+				  meye.mchip_ptable_toc,
+				  meye.mchip_dmahandle);
+
+	memset(meye.mchip_ptable, 0, sizeof(meye.mchip_ptable));
+	meye.mchip_ptable_toc = NULL;
+	meye.mchip_dmahandle = 0;
+}
+
+/* copy data from ptable into buf */
+static void ptable_copy(u8 *buf, int start, int size, int pt_pages)
+{
+	int i;
+
+	for (i = 0; i < (size / PAGE_SIZE) * PAGE_SIZE; i += PAGE_SIZE) {
+		memcpy(buf + i, meye.mchip_ptable[start++], PAGE_SIZE);
+		if (start >= pt_pages)
+			start = 0;
+	}
+	memcpy(buf + i, meye.mchip_ptable[start], size % PAGE_SIZE);
+}
+
+/****************************************************************************/
+/* JPEG tables at different qualities to load into the VRJ chip             */
+/****************************************************************************/
+
+/* return a set of quantisation tables based on a quality from 1 to 10 */
+static u16 *jpeg_quantisation_tables(int *length, int quality)
+{
+	static u16 jpeg_tables[][70] = { {
+		0xdbff, 0x4300, 0xff00, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+		0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+		0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+		0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+		0xffff, 0xffff, 0xffff,
+		0xdbff, 0x4300, 0xff01, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+		0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+		0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+		0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+		0xffff, 0xffff, 0xffff,
+	},
+	{
+		0xdbff, 0x4300, 0x5000, 0x3c37, 0x3c46, 0x5032, 0x4146, 0x5a46,
+		0x5055, 0x785f, 0x82c8, 0x6e78, 0x786e, 0xaff5, 0x91b9, 0xffc8,
+		0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+		0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+		0xffff, 0xffff, 0xffff,
+		0xdbff, 0x4300, 0x5501, 0x5a5a, 0x6978, 0xeb78, 0x8282, 0xffeb,
+		0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+		0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+		0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+		0xffff, 0xffff, 0xffff,
+	},
+	{
+		0xdbff, 0x4300, 0x2800, 0x1e1c, 0x1e23, 0x2819, 0x2123, 0x2d23,
+		0x282b, 0x3c30, 0x4164, 0x373c, 0x3c37, 0x587b, 0x495d, 0x9164,
+		0x9980, 0x8f96, 0x8c80, 0xa08a, 0xe6b4, 0xa0c3, 0xdaaa, 0x8aad,
+		0xc88c, 0xcbff, 0xeeda, 0xfff5, 0xffff, 0xc19b, 0xffff, 0xfaff,
+		0xe6ff, 0xfffd, 0xfff8,
+		0xdbff, 0x4300, 0x2b01, 0x2d2d, 0x353c, 0x763c, 0x4141, 0xf876,
+		0x8ca5, 0xf8a5, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8,
+		0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8,
+		0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8,
+		0xf8f8, 0xf8f8, 0xfff8,
+	},
+	{
+		0xdbff, 0x4300, 0x1b00, 0x1412, 0x1417, 0x1b11, 0x1617, 0x1e17,
+		0x1b1c, 0x2820, 0x2b42, 0x2528, 0x2825, 0x3a51, 0x303d, 0x6042,
+		0x6555, 0x5f64, 0x5d55, 0x6a5b, 0x9978, 0x6a81, 0x9071, 0x5b73,
+		0x855d, 0x86b5, 0x9e90, 0xaba3, 0xabad, 0x8067, 0xc9bc, 0xa6ba,
+		0x99c7, 0xaba8, 0xffa4,
+		0xdbff, 0x4300, 0x1c01, 0x1e1e, 0x2328, 0x4e28, 0x2b2b, 0xa44e,
+		0x5d6e, 0xa46e, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
+		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
+		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
+		0xa4a4, 0xa4a4, 0xffa4,
+	},
+	{
+		0xdbff, 0x4300, 0x1400, 0x0f0e, 0x0f12, 0x140d, 0x1012, 0x1712,
+		0x1415, 0x1e18, 0x2132, 0x1c1e, 0x1e1c, 0x2c3d, 0x242e, 0x4932,
+		0x4c40, 0x474b, 0x4640, 0x5045, 0x735a, 0x5062, 0x6d55, 0x4556,
+		0x6446, 0x6588, 0x776d, 0x817b, 0x8182, 0x604e, 0x978d, 0x7d8c,
+		0x7396, 0x817e, 0xff7c,
+		0xdbff, 0x4300, 0x1501, 0x1717, 0x1a1e, 0x3b1e, 0x2121, 0x7c3b,
+		0x4653, 0x7c53, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c,
+		0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c,
+		0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c, 0x7c7c,
+		0x7c7c, 0x7c7c, 0xff7c,
+	},
+	{
+		0xdbff, 0x4300, 0x1000, 0x0c0b, 0x0c0e, 0x100a, 0x0d0e, 0x120e,
+		0x1011, 0x1813, 0x1a28, 0x1618, 0x1816, 0x2331, 0x1d25, 0x3a28,
+		0x3d33, 0x393c, 0x3833, 0x4037, 0x5c48, 0x404e, 0x5744, 0x3745,
+		0x5038, 0x516d, 0x5f57, 0x6762, 0x6768, 0x4d3e, 0x7971, 0x6470,
+		0x5c78, 0x6765, 0xff63,
+		0xdbff, 0x4300, 0x1101, 0x1212, 0x1518, 0x2f18, 0x1a1a, 0x632f,
+		0x3842, 0x6342, 0x6363, 0x6363, 0x6363, 0x6363, 0x6363, 0x6363,
+		0x6363, 0x6363, 0x6363, 0x6363, 0x6363, 0x6363, 0x6363, 0x6363,
+		0x6363, 0x6363, 0x6363, 0x6363, 0x6363, 0x6363, 0x6363, 0x6363,
+		0x6363, 0x6363, 0xff63,
+	},
+	{
+		0xdbff, 0x4300, 0x0d00, 0x0a09, 0x0a0b, 0x0d08, 0x0a0b, 0x0e0b,
+		0x0d0e, 0x130f, 0x1520, 0x1213, 0x1312, 0x1c27, 0x171e, 0x2e20,
+		0x3129, 0x2e30, 0x2d29, 0x332c, 0x4a3a, 0x333e, 0x4636, 0x2c37,
+		0x402d, 0x4157, 0x4c46, 0x524e, 0x5253, 0x3e32, 0x615a, 0x505a,
+		0x4a60, 0x5251, 0xff4f,
+		0xdbff, 0x4300, 0x0e01, 0x0e0e, 0x1113, 0x2613, 0x1515, 0x4f26,
+		0x2d35, 0x4f35, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f,
+		0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f,
+		0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f, 0x4f4f,
+		0x4f4f, 0x4f4f, 0xff4f,
+	},
+	{
+		0xdbff, 0x4300, 0x0a00, 0x0707, 0x0708, 0x0a06, 0x0808, 0x0b08,
+		0x0a0a, 0x0e0b, 0x1018, 0x0d0e, 0x0e0d, 0x151d, 0x1116, 0x2318,
+		0x251f, 0x2224, 0x221f, 0x2621, 0x372b, 0x262f, 0x3429, 0x2129,
+		0x3022, 0x3141, 0x3934, 0x3e3b, 0x3e3e, 0x2e25, 0x4944, 0x3c43,
+		0x3748, 0x3e3d, 0xff3b,
+		0xdbff, 0x4300, 0x0a01, 0x0b0b, 0x0d0e, 0x1c0e, 0x1010, 0x3b1c,
+		0x2228, 0x3b28, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b,
+		0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b,
+		0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b,
+		0x3b3b, 0x3b3b, 0xff3b,
+	},
+	{
+		0xdbff, 0x4300, 0x0600, 0x0504, 0x0506, 0x0604, 0x0506, 0x0706,
+		0x0607, 0x0a08, 0x0a10, 0x090a, 0x0a09, 0x0e14, 0x0c0f, 0x1710,
+		0x1814, 0x1718, 0x1614, 0x1a16, 0x251d, 0x1a1f, 0x231b, 0x161c,
+		0x2016, 0x202c, 0x2623, 0x2927, 0x292a, 0x1f19, 0x302d, 0x282d,
+		0x2530, 0x2928, 0xff28,
+		0xdbff, 0x4300, 0x0701, 0x0707, 0x080a, 0x130a, 0x0a0a, 0x2813,
+		0x161a, 0x281a, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828,
+		0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828,
+		0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828,
+		0x2828, 0x2828, 0xff28,
+	},
+	{
+		0xdbff, 0x4300, 0x0300, 0x0202, 0x0203, 0x0302, 0x0303, 0x0403,
+		0x0303, 0x0504, 0x0508, 0x0405, 0x0504, 0x070a, 0x0607, 0x0c08,
+		0x0c0a, 0x0b0c, 0x0b0a, 0x0d0b, 0x120e, 0x0d10, 0x110e, 0x0b0e,
+		0x100b, 0x1016, 0x1311, 0x1514, 0x1515, 0x0f0c, 0x1817, 0x1416,
+		0x1218, 0x1514, 0xff14,
+		0xdbff, 0x4300, 0x0301, 0x0404, 0x0405, 0x0905, 0x0505, 0x1409,
+		0x0b0d, 0x140d, 0x1414, 0x1414, 0x1414, 0x1414, 0x1414, 0x1414,
+		0x1414, 0x1414, 0x1414, 0x1414, 0x1414, 0x1414, 0x1414, 0x1414,
+		0x1414, 0x1414, 0x1414, 0x1414, 0x1414, 0x1414, 0x1414, 0x1414,
+		0x1414, 0x1414, 0xff14,
+	},
+	{
+		0xdbff, 0x4300, 0x0100, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101,
+		0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101,
+		0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101,
+		0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101,
+		0x0101, 0x0101, 0xff01,
+		0xdbff, 0x4300, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101,
+		0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101,
+		0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101,
+		0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101,
+		0x0101, 0x0101, 0xff01,
+	} };
+
+	if (quality < 0 || quality > 10) {
+		printk(KERN_WARNING
+		       "meye: invalid quality level %d - using 8\n", quality);
+		quality = 8;
+	}
+
+	*length = ARRAY_SIZE(jpeg_tables[quality]);
+	return jpeg_tables[quality];
+}
+
+/* return a generic set of huffman tables */
+static u16 *jpeg_huffman_tables(int *length)
+{
+	static u16 tables[] = {
+		0xC4FF, 0xB500, 0x0010, 0x0102, 0x0303, 0x0402, 0x0503, 0x0405,
+		0x0004, 0x0100, 0x017D, 0x0302, 0x0400, 0x0511, 0x2112, 0x4131,
+		0x1306, 0x6151, 0x2207, 0x1471, 0x8132, 0xA191, 0x2308, 0xB142,
+		0x15C1, 0xD152, 0x24F0, 0x6233, 0x8272, 0x0A09, 0x1716, 0x1918,
+		0x251A, 0x2726, 0x2928, 0x342A, 0x3635, 0x3837, 0x3A39, 0x4443,
+		0x4645, 0x4847, 0x4A49, 0x5453, 0x5655, 0x5857, 0x5A59, 0x6463,
+		0x6665, 0x6867, 0x6A69, 0x7473, 0x7675, 0x7877, 0x7A79, 0x8483,
+		0x8685, 0x8887, 0x8A89, 0x9392, 0x9594, 0x9796, 0x9998, 0xA29A,
+		0xA4A3, 0xA6A5, 0xA8A7, 0xAAA9, 0xB3B2, 0xB5B4, 0xB7B6, 0xB9B8,
+		0xC2BA, 0xC4C3, 0xC6C5, 0xC8C7, 0xCAC9, 0xD3D2, 0xD5D4, 0xD7D6,
+		0xD9D8, 0xE1DA, 0xE3E2, 0xE5E4, 0xE7E6, 0xE9E8, 0xF1EA, 0xF3F2,
+		0xF5F4, 0xF7F6, 0xF9F8, 0xFFFA,
+		0xC4FF, 0xB500, 0x0011, 0x0102, 0x0402, 0x0304, 0x0704, 0x0405,
+		0x0004, 0x0201, 0x0077, 0x0201, 0x1103, 0x0504, 0x3121, 0x1206,
+		0x5141, 0x6107, 0x1371, 0x3222, 0x0881, 0x4214, 0xA191, 0xC1B1,
+		0x2309, 0x5233, 0x15F0, 0x7262, 0x0AD1, 0x2416, 0xE134, 0xF125,
+		0x1817, 0x1A19, 0x2726, 0x2928, 0x352A, 0x3736, 0x3938, 0x433A,
+		0x4544, 0x4746, 0x4948, 0x534A, 0x5554, 0x5756, 0x5958, 0x635A,
+		0x6564, 0x6766, 0x6968, 0x736A, 0x7574, 0x7776, 0x7978, 0x827A,
+		0x8483, 0x8685, 0x8887, 0x8A89, 0x9392, 0x9594, 0x9796, 0x9998,
+		0xA29A, 0xA4A3, 0xA6A5, 0xA8A7, 0xAAA9, 0xB3B2, 0xB5B4, 0xB7B6,
+		0xB9B8, 0xC2BA, 0xC4C3, 0xC6C5, 0xC8C7, 0xCAC9, 0xD3D2, 0xD5D4,
+		0xD7D6, 0xD9D8, 0xE2DA, 0xE4E3, 0xE6E5, 0xE8E7, 0xEAE9, 0xF3F2,
+		0xF5F4, 0xF7F6, 0xF9F8, 0xFFFA,
+		0xC4FF, 0x1F00, 0x0000, 0x0501, 0x0101, 0x0101, 0x0101, 0x0000,
+		0x0000, 0x0000, 0x0000, 0x0201, 0x0403, 0x0605, 0x0807, 0x0A09,
+		0xFF0B,
+		0xC4FF, 0x1F00, 0x0001, 0x0103, 0x0101, 0x0101, 0x0101, 0x0101,
+		0x0000, 0x0000, 0x0000, 0x0201, 0x0403, 0x0605, 0x0807, 0x0A09,
+		0xFF0B
+	};
+
+	*length = ARRAY_SIZE(tables);
+	return tables;
+}
+
+/****************************************************************************/
+/* MCHIP low-level functions                                                */
+/****************************************************************************/
+
+/* returns the horizontal capture size */
+static inline int mchip_hsize(void)
+{
+	return meye.params.subsample ? 320 : 640;
+}
+
+/* returns the vertical capture size */
+static inline int mchip_vsize(void)
+{
+	return meye.params.subsample ? 240 : 480;
+}
+
+/* waits for a register to be available */
+static void mchip_sync(int reg)
+{
+	u32 status;
+	int i;
+
+	if (reg == MCHIP_MM_FIFO_DATA) {
+		for (i = 0; i < MCHIP_REG_TIMEOUT; i++) {
+			status = readl(meye.mchip_mmregs +
+				       MCHIP_MM_FIFO_STATUS);
+			if (!(status & MCHIP_MM_FIFO_WAIT)) {
+				printk(KERN_WARNING "meye: fifo not ready\n");
+				return;
+			}
+			if (status & MCHIP_MM_FIFO_READY)
+				return;
+			udelay(1);
+		}
+	} else if (reg > 0x80) {
+		u32 mask = (reg < 0x100) ? MCHIP_HIC_STATUS_MCC_RDY
+					 : MCHIP_HIC_STATUS_VRJ_RDY;
+		for (i = 0; i < MCHIP_REG_TIMEOUT; i++) {
+			status = readl(meye.mchip_mmregs + MCHIP_HIC_STATUS);
+			if (status & mask)
+				return;
+			udelay(1);
+		}
+	} else
+		return;
+	printk(KERN_WARNING
+	       "meye: mchip_sync() timeout on reg 0x%x status=0x%x\n",
+	       reg, status);
+}
+
+/* sets a value into the register */
+static inline void mchip_set(int reg, u32 v)
+{
+	mchip_sync(reg);
+	writel(v, meye.mchip_mmregs + reg);
+}
+
+/* get the register value */
+static inline u32 mchip_read(int reg)
+{
+	mchip_sync(reg);
+	return readl(meye.mchip_mmregs + reg);
+}
+
+/* wait for a register to become a particular value */
+static inline int mchip_delay(u32 reg, u32 v)
+{
+	int n = 10;
+	while (--n && mchip_read(reg) != v)
+		udelay(1);
+	return n;
+}
+
+/* setup subsampling */
+static void mchip_subsample(void)
+{
+	mchip_set(MCHIP_MCC_R_SAMPLING, meye.params.subsample);
+	mchip_set(MCHIP_MCC_R_XRANGE, mchip_hsize());
+	mchip_set(MCHIP_MCC_R_YRANGE, mchip_vsize());
+	mchip_set(MCHIP_MCC_B_XRANGE, mchip_hsize());
+	mchip_set(MCHIP_MCC_B_YRANGE, mchip_vsize());
+	mchip_delay(MCHIP_HIC_STATUS, MCHIP_HIC_STATUS_IDLE);
+}
+
+/* set the framerate into the mchip */
+static void mchip_set_framerate(void)
+{
+	mchip_set(MCHIP_HIC_S_RATE, meye.params.framerate);
+}
+
+/* load some huffman and quantisation tables into the VRJ chip ready
+   for JPEG compression */
+static void mchip_load_tables(void)
+{
+	int i;
+	int length;
+	u16 *tables;
+
+	tables = jpeg_huffman_tables(&length);
+	for (i = 0; i < length; i++)
+		writel(tables[i], meye.mchip_mmregs + MCHIP_VRJ_TABLE_DATA);
+
+	tables = jpeg_quantisation_tables(&length, meye.params.quality);
+	for (i = 0; i < length; i++)
+		writel(tables[i], meye.mchip_mmregs + MCHIP_VRJ_TABLE_DATA);
+}
+
+/* setup the VRJ parameters in the chip */
+static void mchip_vrj_setup(u8 mode)
+{
+	mchip_set(MCHIP_VRJ_BUS_MODE, 5);
+	mchip_set(MCHIP_VRJ_SIGNAL_ACTIVE_LEVEL, 0x1f);
+	mchip_set(MCHIP_VRJ_PDAT_USE, 1);
+	mchip_set(MCHIP_VRJ_IRQ_FLAG, 0xa0);
+	mchip_set(MCHIP_VRJ_MODE_SPECIFY, mode);
+	mchip_set(MCHIP_VRJ_NUM_LINES, mchip_vsize());
+	mchip_set(MCHIP_VRJ_NUM_PIXELS, mchip_hsize());
+	mchip_set(MCHIP_VRJ_NUM_COMPONENTS, 0x1b);
+	mchip_set(MCHIP_VRJ_LIMIT_COMPRESSED_LO, 0xFFFF);
+	mchip_set(MCHIP_VRJ_LIMIT_COMPRESSED_HI, 0xFFFF);
+	mchip_set(MCHIP_VRJ_COMP_DATA_FORMAT, 0xC);
+	mchip_set(MCHIP_VRJ_RESTART_INTERVAL, 0);
+	mchip_set(MCHIP_VRJ_SOF1, 0x601);
+	mchip_set(MCHIP_VRJ_SOF2, 0x1502);
+	mchip_set(MCHIP_VRJ_SOF3, 0x1503);
+	mchip_set(MCHIP_VRJ_SOF4, 0x1596);
+	mchip_set(MCHIP_VRJ_SOS, 0x0ed0);
+
+	mchip_load_tables();
+}
+
+/* sets the DMA parameters into the chip */
+static void mchip_dma_setup(dma_addr_t dma_addr)
+{
+	int i;
+
+	mchip_set(MCHIP_MM_PT_ADDR, (u32)dma_addr);
+	for (i = 0; i < 4; i++)
+		mchip_set(MCHIP_MM_FIR(i), 0);
+	meye.mchip_fnum = 0;
+}
+
+/* setup for DMA transfers - also zeros the framebuffer */
+static int mchip_dma_alloc(void)
+{
+	if (!meye.mchip_dmahandle)
+		if (ptable_alloc())
+			return -1;
+	return 0;
+}
+
+/* frees the DMA buffer */
+static void mchip_dma_free(void)
+{
+	if (meye.mchip_dmahandle) {
+		mchip_dma_setup(0);
+		ptable_free();
+	}
+}
+
+/* stop any existing HIC action and wait for any dma to complete then
+   reset the dma engine */
+static void mchip_hic_stop(void)
+{
+	int i, j;
+
+	meye.mchip_mode = MCHIP_HIC_MODE_NOOP;
+	if (!(mchip_read(MCHIP_HIC_STATUS) & MCHIP_HIC_STATUS_BUSY))
+		return;
+	for (i = 0; i < 20; ++i) {
+		mchip_set(MCHIP_HIC_CMD, MCHIP_HIC_CMD_STOP);
+		mchip_delay(MCHIP_HIC_CMD, 0);
+		for (j = 0; j < 100; ++j) {
+			if (mchip_delay(MCHIP_HIC_STATUS,
+					MCHIP_HIC_STATUS_IDLE))
+				return;
+			msleep(1);
+		}
+		printk(KERN_ERR "meye: need to reset HIC!\n");
+
+		mchip_set(MCHIP_HIC_CTL, MCHIP_HIC_CTL_SOFT_RESET);
+		msleep(250);
+	}
+	printk(KERN_ERR "meye: resetting HIC hanged!\n");
+}
+
+/****************************************************************************/
+/* MCHIP frame processing functions                                         */
+/****************************************************************************/
+
+/* get the next ready frame from the dma engine */
+static u32 mchip_get_frame(void)
+{
+	u32 v;
+
+	v = mchip_read(MCHIP_MM_FIR(meye.mchip_fnum));
+	return v;
+}
+
+/* frees the current frame from the dma engine */
+static void mchip_free_frame(void)
+{
+	mchip_set(MCHIP_MM_FIR(meye.mchip_fnum), 0);
+	meye.mchip_fnum++;
+	meye.mchip_fnum %= 4;
+}
+
+/* read one frame from the framebuffer assuming it was captured using
+   a uncompressed transfer */
+static void mchip_cont_read_frame(u32 v, u8 *buf, int size)
+{
+	int pt_id;
+
+	pt_id = (v >> 17) & 0x3FF;
+
+	ptable_copy(buf, pt_id, size, MCHIP_NB_PAGES);
+}
+
+/* read a compressed frame from the framebuffer */
+static int mchip_comp_read_frame(u32 v, u8 *buf, int size)
+{
+	int pt_start, pt_end, trailer;
+	int fsize;
+	int i;
+
+	pt_start = (v >> 19) & 0xFF;
+	pt_end = (v >> 11) & 0xFF;
+	trailer = (v >> 1) & 0x3FF;
+
+	if (pt_end < pt_start)
+		fsize = (MCHIP_NB_PAGES_MJPEG - pt_start) * PAGE_SIZE +
+			pt_end * PAGE_SIZE + trailer * 4;
+	else
+		fsize = (pt_end - pt_start) * PAGE_SIZE + trailer * 4;
+
+	if (fsize > size) {
+		printk(KERN_WARNING "meye: oversized compressed frame %d\n",
+		       fsize);
+		return -1;
+	}
+
+	ptable_copy(buf, pt_start, fsize, MCHIP_NB_PAGES_MJPEG);
+
+#ifdef MEYE_JPEG_CORRECTION
+
+	/* Some mchip generated jpeg frames are incorrect. In most
+	 * (all ?) of those cases, the final EOI (0xff 0xd9) marker
+	 * is not present at the end of the frame.
+	 *
+	 * Since adding the final marker is not enough to restore
+	 * the jpeg integrity, we drop the frame.
+	 */
+
+	for (i = fsize - 1; i > 0 && buf[i] == 0xff; i--) ;
+
+	if (i < 2 || buf[i - 1] != 0xff || buf[i] != 0xd9)
+		return -1;
+
+#endif
+
+	return fsize;
+}
+
+/* take a picture into SDRAM */
+static void mchip_take_picture(void)
+{
+	int i;
+
+	mchip_hic_stop();
+	mchip_subsample();
+	mchip_dma_setup(meye.mchip_dmahandle);
+
+	mchip_set(MCHIP_HIC_MODE, MCHIP_HIC_MODE_STILL_CAP);
+	mchip_set(MCHIP_HIC_CMD, MCHIP_HIC_CMD_START);
+
+	mchip_delay(MCHIP_HIC_CMD, 0);
+
+	for (i = 0; i < 100; ++i) {
+		if (mchip_delay(MCHIP_HIC_STATUS, MCHIP_HIC_STATUS_IDLE))
+			break;
+		msleep(1);
+	}
+}
+
+/* dma a previously taken picture into a buffer */
+static void mchip_get_picture(u8 *buf, int bufsize)
+{
+	u32 v;
+	int i;
+
+	mchip_set(MCHIP_HIC_MODE, MCHIP_HIC_MODE_STILL_OUT);
+	mchip_set(MCHIP_HIC_CMD, MCHIP_HIC_CMD_START);
+
+	mchip_delay(MCHIP_HIC_CMD, 0);
+	for (i = 0; i < 100; ++i) {
+		if (mchip_delay(MCHIP_HIC_STATUS, MCHIP_HIC_STATUS_IDLE))
+			break;
+		msleep(1);
+	}
+	for (i = 0; i < 4; ++i) {
+		v = mchip_get_frame();
+		if (v & MCHIP_MM_FIR_RDY) {
+			mchip_cont_read_frame(v, buf, bufsize);
+			break;
+		}
+		mchip_free_frame();
+	}
+}
+
+/* start continuous dma capture */
+static void mchip_continuous_start(void)
+{
+	mchip_hic_stop();
+	mchip_subsample();
+	mchip_set_framerate();
+	mchip_dma_setup(meye.mchip_dmahandle);
+
+	meye.mchip_mode = MCHIP_HIC_MODE_CONT_OUT;
+
+	mchip_set(MCHIP_HIC_MODE, MCHIP_HIC_MODE_CONT_OUT);
+	mchip_set(MCHIP_HIC_CMD, MCHIP_HIC_CMD_START);
+
+	mchip_delay(MCHIP_HIC_CMD, 0);
+}
+
+/* compress one frame into a buffer */
+static int mchip_compress_frame(u8 *buf, int bufsize)
+{
+	u32 v;
+	int len = -1, i;
+
+	mchip_vrj_setup(0x3f);
+	udelay(50);
+
+	mchip_set(MCHIP_HIC_MODE, MCHIP_HIC_MODE_STILL_COMP);
+	mchip_set(MCHIP_HIC_CMD, MCHIP_HIC_CMD_START);
+
+	mchip_delay(MCHIP_HIC_CMD, 0);
+	for (i = 0; i < 100; ++i) {
+		if (mchip_delay(MCHIP_HIC_STATUS, MCHIP_HIC_STATUS_IDLE))
+			break;
+		msleep(1);
+	}
+
+	for (i = 0; i < 4; ++i) {
+		v = mchip_get_frame();
+		if (v & MCHIP_MM_FIR_RDY) {
+			len = mchip_comp_read_frame(v, buf, bufsize);
+			break;
+		}
+		mchip_free_frame();
+	}
+	return len;
+}
+
+#if 0
+/* uncompress one image into a buffer */
+static int mchip_uncompress_frame(u8 *img, int imgsize, u8 *buf, int bufsize)
+{
+	mchip_vrj_setup(0x3f);
+	udelay(50);
+
+	mchip_set(MCHIP_HIC_MODE, MCHIP_HIC_MODE_STILL_DECOMP);
+	mchip_set(MCHIP_HIC_CMD, MCHIP_HIC_CMD_START);
+
+	mchip_delay(MCHIP_HIC_CMD, 0);
+
+	return mchip_comp_read_frame(buf, bufsize);
+}
+#endif
+
+/* start continuous compressed capture */
+static void mchip_cont_compression_start(void)
+{
+	mchip_hic_stop();
+	mchip_vrj_setup(0x3f);
+	mchip_subsample();
+	mchip_set_framerate();
+	mchip_dma_setup(meye.mchip_dmahandle);
+
+	meye.mchip_mode = MCHIP_HIC_MODE_CONT_COMP;
+
+	mchip_set(MCHIP_HIC_MODE, MCHIP_HIC_MODE_CONT_COMP);
+	mchip_set(MCHIP_HIC_CMD, MCHIP_HIC_CMD_START);
+
+	mchip_delay(MCHIP_HIC_CMD, 0);
+}
+
+/****************************************************************************/
+/* Interrupt handling                                                       */
+/****************************************************************************/
+
+static irqreturn_t meye_irq(int irq, void *dev_id)
+{
+	u32 v;
+	int reqnr;
+	static int sequence;
+
+	v = mchip_read(MCHIP_MM_INTA);
+
+	if (meye.mchip_mode != MCHIP_HIC_MODE_CONT_OUT &&
+	    meye.mchip_mode != MCHIP_HIC_MODE_CONT_COMP)
+		return IRQ_NONE;
+
+again:
+	v = mchip_get_frame();
+	if (!(v & MCHIP_MM_FIR_RDY))
+		return IRQ_HANDLED;
+
+	if (meye.mchip_mode == MCHIP_HIC_MODE_CONT_OUT) {
+		if (kfifo_out_locked(&meye.grabq, (unsigned char *)&reqnr,
+			      sizeof(int), &meye.grabq_lock) != sizeof(int)) {
+			mchip_free_frame();
+			return IRQ_HANDLED;
+		}
+		mchip_cont_read_frame(v, meye.grab_fbuffer + gbufsize * reqnr,
+				      mchip_hsize() * mchip_vsize() * 2);
+		meye.grab_buffer[reqnr].size = mchip_hsize() * mchip_vsize() * 2;
+		meye.grab_buffer[reqnr].state = MEYE_BUF_DONE;
+		do_gettimeofday(&meye.grab_buffer[reqnr].timestamp);
+		meye.grab_buffer[reqnr].sequence = sequence++;
+		kfifo_in_locked(&meye.doneq, (unsigned char *)&reqnr,
+				sizeof(int), &meye.doneq_lock);
+		wake_up_interruptible(&meye.proc_list);
+	} else {
+		int size;
+		size = mchip_comp_read_frame(v, meye.grab_temp, gbufsize);
+		if (size == -1) {
+			mchip_free_frame();
+			goto again;
+		}
+		if (kfifo_out_locked(&meye.grabq, (unsigned char *)&reqnr,
+			      sizeof(int), &meye.grabq_lock) != sizeof(int)) {
+			mchip_free_frame();
+			goto again;
+		}
+		memcpy(meye.grab_fbuffer + gbufsize * reqnr, meye.grab_temp,
+		       size);
+		meye.grab_buffer[reqnr].size = size;
+		meye.grab_buffer[reqnr].state = MEYE_BUF_DONE;
+		do_gettimeofday(&meye.grab_buffer[reqnr].timestamp);
+		meye.grab_buffer[reqnr].sequence = sequence++;
+		kfifo_in_locked(&meye.doneq, (unsigned char *)&reqnr,
+				sizeof(int), &meye.doneq_lock);
+		wake_up_interruptible(&meye.proc_list);
+	}
+	mchip_free_frame();
+	goto again;
+}
+
+/****************************************************************************/
+/* video4linux integration                                                  */
+/****************************************************************************/
+
+static int meye_open(struct file *file)
+{
+	int i;
+
+	if (test_and_set_bit(0, &meye.in_use))
+		return -EBUSY;
+
+	mchip_hic_stop();
+
+	if (mchip_dma_alloc()) {
+		printk(KERN_ERR "meye: mchip framebuffer allocation failed\n");
+		clear_bit(0, &meye.in_use);
+		return -ENOBUFS;
+	}
+
+	for (i = 0; i < MEYE_MAX_BUFNBRS; i++)
+		meye.grab_buffer[i].state = MEYE_BUF_UNUSED;
+	kfifo_reset(&meye.grabq);
+	kfifo_reset(&meye.doneq);
+	return 0;
+}
+
+static int meye_release(struct file *file)
+{
+	mchip_hic_stop();
+	mchip_dma_free();
+	clear_bit(0, &meye.in_use);
+	return 0;
+}
+
+static int meyeioc_g_params(struct meye_params *p)
+{
+	*p = meye.params;
+	return 0;
+}
+
+static int meyeioc_s_params(struct meye_params *jp)
+{
+	if (jp->subsample > 1)
+		return -EINVAL;
+
+	if (jp->quality > 10)
+		return -EINVAL;
+
+	if (jp->sharpness > 63 || jp->agc > 63 || jp->picture > 63)
+		return -EINVAL;
+
+	if (jp->framerate > 31)
+		return -EINVAL;
+
+	mutex_lock(&meye.lock);
+
+	if (meye.params.subsample != jp->subsample ||
+	    meye.params.quality != jp->quality)
+		mchip_hic_stop();	/* need restart */
+
+	meye.params = *jp;
+	sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERASHARPNESS,
+			      meye.params.sharpness);
+	sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAAGC,
+			      meye.params.agc);
+	sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAPICTURE,
+			      meye.params.picture);
+	mutex_unlock(&meye.lock);
+
+	return 0;
+}
+
+static int meyeioc_qbuf_capt(int *nb)
+{
+	if (!meye.grab_fbuffer)
+		return -EINVAL;
+
+	if (*nb >= gbuffers)
+		return -EINVAL;
+
+	if (*nb < 0) {
+		/* stop capture */
+		mchip_hic_stop();
+		return 0;
+	}
+
+	if (meye.grab_buffer[*nb].state != MEYE_BUF_UNUSED)
+		return -EBUSY;
+
+	mutex_lock(&meye.lock);
+
+	if (meye.mchip_mode != MCHIP_HIC_MODE_CONT_COMP)
+		mchip_cont_compression_start();
+
+	meye.grab_buffer[*nb].state = MEYE_BUF_USING;
+	kfifo_in_locked(&meye.grabq, (unsigned char *)nb, sizeof(int),
+			 &meye.grabq_lock);
+	mutex_unlock(&meye.lock);
+
+	return 0;
+}
+
+static int meyeioc_sync(struct file *file, void *fh, int *i)
+{
+	int unused;
+
+	if (*i < 0 || *i >= gbuffers)
+		return -EINVAL;
+
+	mutex_lock(&meye.lock);
+	switch (meye.grab_buffer[*i].state) {
+
+	case MEYE_BUF_UNUSED:
+		mutex_unlock(&meye.lock);
+		return -EINVAL;
+	case MEYE_BUF_USING:
+		if (file->f_flags & O_NONBLOCK) {
+			mutex_unlock(&meye.lock);
+			return -EAGAIN;
+		}
+		if (wait_event_interruptible(meye.proc_list,
+			(meye.grab_buffer[*i].state != MEYE_BUF_USING))) {
+			mutex_unlock(&meye.lock);
+			return -EINTR;
+		}
+		/* fall through */
+	case MEYE_BUF_DONE:
+		meye.grab_buffer[*i].state = MEYE_BUF_UNUSED;
+		if (kfifo_out_locked(&meye.doneq, (unsigned char *)&unused,
+				sizeof(int), &meye.doneq_lock) != sizeof(int))
+					break;
+	}
+	*i = meye.grab_buffer[*i].size;
+	mutex_unlock(&meye.lock);
+	return 0;
+}
+
+static int meyeioc_stillcapt(void)
+{
+	if (!meye.grab_fbuffer)
+		return -EINVAL;
+
+	if (meye.grab_buffer[0].state != MEYE_BUF_UNUSED)
+		return -EBUSY;
+
+	mutex_lock(&meye.lock);
+	meye.grab_buffer[0].state = MEYE_BUF_USING;
+	mchip_take_picture();
+
+	mchip_get_picture(meye.grab_fbuffer,
+			mchip_hsize() * mchip_vsize() * 2);
+
+	meye.grab_buffer[0].state = MEYE_BUF_DONE;
+	mutex_unlock(&meye.lock);
+
+	return 0;
+}
+
+static int meyeioc_stilljcapt(int *len)
+{
+	if (!meye.grab_fbuffer)
+		return -EINVAL;
+
+	if (meye.grab_buffer[0].state != MEYE_BUF_UNUSED)
+		return -EBUSY;
+
+	mutex_lock(&meye.lock);
+	meye.grab_buffer[0].state = MEYE_BUF_USING;
+	*len = -1;
+
+	while (*len == -1) {
+		mchip_take_picture();
+		*len = mchip_compress_frame(meye.grab_fbuffer, gbufsize);
+	}
+
+	meye.grab_buffer[0].state = MEYE_BUF_DONE;
+	mutex_unlock(&meye.lock);
+	return 0;
+}
+
+static int vidioc_querycap(struct file *file, void *fh,
+				struct v4l2_capability *cap)
+{
+	strcpy(cap->driver, "meye");
+	strcpy(cap->card, "meye");
+	sprintf(cap->bus_info, "PCI:%s", pci_name(meye.mchip_dev));
+
+	cap->version = (MEYE_DRIVER_MAJORVERSION << 8) +
+		       MEYE_DRIVER_MINORVERSION;
+
+	cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
+			    V4L2_CAP_STREAMING;
+
+	return 0;
+}
+
+static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
+{
+	if (i->index != 0)
+		return -EINVAL;
+
+	strcpy(i->name, "Camera");
+	i->type = V4L2_INPUT_TYPE_CAMERA;
+
+	return 0;
+}
+
+static int vidioc_g_input(struct file *file, void *fh, unsigned int *i)
+{
+	*i = 0;
+	return 0;
+}
+
+static int vidioc_s_input(struct file *file, void *fh, unsigned int i)
+{
+	if (i != 0)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int vidioc_queryctrl(struct file *file, void *fh,
+				struct v4l2_queryctrl *c)
+{
+	switch (c->id) {
+
+	case V4L2_CID_BRIGHTNESS:
+		c->type = V4L2_CTRL_TYPE_INTEGER;
+		strcpy(c->name, "Brightness");
+		c->minimum = 0;
+		c->maximum = 63;
+		c->step = 1;
+		c->default_value = 32;
+		c->flags = 0;
+		break;
+	case V4L2_CID_HUE:
+		c->type = V4L2_CTRL_TYPE_INTEGER;
+		strcpy(c->name, "Hue");
+		c->minimum = 0;
+		c->maximum = 63;
+		c->step = 1;
+		c->default_value = 32;
+		c->flags = 0;
+		break;
+	case V4L2_CID_CONTRAST:
+		c->type = V4L2_CTRL_TYPE_INTEGER;
+		strcpy(c->name, "Contrast");
+		c->minimum = 0;
+		c->maximum = 63;
+		c->step = 1;
+		c->default_value = 32;
+		c->flags = 0;
+		break;
+	case V4L2_CID_SATURATION:
+		c->type = V4L2_CTRL_TYPE_INTEGER;
+		strcpy(c->name, "Saturation");
+		c->minimum = 0;
+		c->maximum = 63;
+		c->step = 1;
+		c->default_value = 32;
+		c->flags = 0;
+		break;
+	case V4L2_CID_AGC:
+		c->type = V4L2_CTRL_TYPE_INTEGER;
+		strcpy(c->name, "Agc");
+		c->minimum = 0;
+		c->maximum = 63;
+		c->step = 1;
+		c->default_value = 48;
+		c->flags = 0;
+		break;
+	case V4L2_CID_MEYE_SHARPNESS:
+	case V4L2_CID_SHARPNESS:
+		c->type = V4L2_CTRL_TYPE_INTEGER;
+		strcpy(c->name, "Sharpness");
+		c->minimum = 0;
+		c->maximum = 63;
+		c->step = 1;
+		c->default_value = 32;
+
+		/* Continue to report legacy private SHARPNESS ctrl but
+		 * say it is disabled in preference to ctrl in the spec
+		 */
+		c->flags = (c->id == V4L2_CID_SHARPNESS) ? 0 :
+						V4L2_CTRL_FLAG_DISABLED;
+		break;
+	case V4L2_CID_PICTURE:
+		c->type = V4L2_CTRL_TYPE_INTEGER;
+		strcpy(c->name, "Picture");
+		c->minimum = 0;
+		c->maximum = 63;
+		c->step = 1;
+		c->default_value = 0;
+		c->flags = 0;
+		break;
+	case V4L2_CID_JPEGQUAL:
+		c->type = V4L2_CTRL_TYPE_INTEGER;
+		strcpy(c->name, "JPEG quality");
+		c->minimum = 0;
+		c->maximum = 10;
+		c->step = 1;
+		c->default_value = 8;
+		c->flags = 0;
+		break;
+	case V4L2_CID_FRAMERATE:
+		c->type = V4L2_CTRL_TYPE_INTEGER;
+		strcpy(c->name, "Framerate");
+		c->minimum = 0;
+		c->maximum = 31;
+		c->step = 1;
+		c->default_value = 0;
+		c->flags = 0;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *c)
+{
+	mutex_lock(&meye.lock);
+	switch (c->id) {
+	case V4L2_CID_BRIGHTNESS:
+		sony_pic_camera_command(
+			SONY_PIC_COMMAND_SETCAMERABRIGHTNESS, c->value);
+		meye.brightness = c->value << 10;
+		break;
+	case V4L2_CID_HUE:
+		sony_pic_camera_command(
+			SONY_PIC_COMMAND_SETCAMERAHUE, c->value);
+		meye.hue = c->value << 10;
+		break;
+	case V4L2_CID_CONTRAST:
+		sony_pic_camera_command(
+			SONY_PIC_COMMAND_SETCAMERACONTRAST, c->value);
+		meye.contrast = c->value << 10;
+		break;
+	case V4L2_CID_SATURATION:
+		sony_pic_camera_command(
+			SONY_PIC_COMMAND_SETCAMERACOLOR, c->value);
+		meye.colour = c->value << 10;
+		break;
+	case V4L2_CID_AGC:
+		sony_pic_camera_command(
+			SONY_PIC_COMMAND_SETCAMERAAGC, c->value);
+		meye.params.agc = c->value;
+		break;
+	case V4L2_CID_SHARPNESS:
+	case V4L2_CID_MEYE_SHARPNESS:
+		sony_pic_camera_command(
+			SONY_PIC_COMMAND_SETCAMERASHARPNESS, c->value);
+		meye.params.sharpness = c->value;
+		break;
+	case V4L2_CID_PICTURE:
+		sony_pic_camera_command(
+			SONY_PIC_COMMAND_SETCAMERAPICTURE, c->value);
+		meye.params.picture = c->value;
+		break;
+	case V4L2_CID_JPEGQUAL:
+		meye.params.quality = c->value;
+		break;
+	case V4L2_CID_FRAMERATE:
+		meye.params.framerate = c->value;
+		break;
+	default:
+		mutex_unlock(&meye.lock);
+		return -EINVAL;
+	}
+	mutex_unlock(&meye.lock);
+
+	return 0;
+}
+
+static int vidioc_g_ctrl(struct file *file, void *fh, struct v4l2_control *c)
+{
+	mutex_lock(&meye.lock);
+	switch (c->id) {
+	case V4L2_CID_BRIGHTNESS:
+		c->value = meye.brightness >> 10;
+		break;
+	case V4L2_CID_HUE:
+		c->value = meye.hue >> 10;
+		break;
+	case V4L2_CID_CONTRAST:
+		c->value = meye.contrast >> 10;
+		break;
+	case V4L2_CID_SATURATION:
+		c->value = meye.colour >> 10;
+		break;
+	case V4L2_CID_AGC:
+		c->value = meye.params.agc;
+		break;
+	case V4L2_CID_SHARPNESS:
+	case V4L2_CID_MEYE_SHARPNESS:
+		c->value = meye.params.sharpness;
+		break;
+	case V4L2_CID_PICTURE:
+		c->value = meye.params.picture;
+		break;
+	case V4L2_CID_JPEGQUAL:
+		c->value = meye.params.quality;
+		break;
+	case V4L2_CID_FRAMERATE:
+		c->value = meye.params.framerate;
+		break;
+	default:
+		mutex_unlock(&meye.lock);
+		return -EINVAL;
+	}
+	mutex_unlock(&meye.lock);
+
+	return 0;
+}
+
+static int vidioc_enum_fmt_vid_cap(struct file *file, void *fh,
+				struct v4l2_fmtdesc *f)
+{
+	if (f->index > 1)
+		return -EINVAL;
+
+	if (f->index == 0) {
+		/* standard YUV 422 capture */
+		f->flags = 0;
+		strcpy(f->description, "YUV422");
+		f->pixelformat = V4L2_PIX_FMT_YUYV;
+	} else {
+		/* compressed MJPEG capture */
+		f->flags = V4L2_FMT_FLAG_COMPRESSED;
+		strcpy(f->description, "MJPEG");
+		f->pixelformat = V4L2_PIX_FMT_MJPEG;
+	}
+
+	return 0;
+}
+
+static int vidioc_try_fmt_vid_cap(struct file *file, void *fh,
+				struct v4l2_format *f)
+{
+	if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_YUYV &&
+	    f->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG)
+		return -EINVAL;
+
+	if (f->fmt.pix.field != V4L2_FIELD_ANY &&
+	    f->fmt.pix.field != V4L2_FIELD_NONE)
+		return -EINVAL;
+
+	f->fmt.pix.field = V4L2_FIELD_NONE;
+
+	if (f->fmt.pix.width <= 320) {
+		f->fmt.pix.width = 320;
+		f->fmt.pix.height = 240;
+	} else {
+		f->fmt.pix.width = 640;
+		f->fmt.pix.height = 480;
+	}
+
+	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;
+}
+
+static int vidioc_g_fmt_vid_cap(struct file *file, void *fh,
+				    struct v4l2_format *f)
+{
+	switch (meye.mchip_mode) {
+	case MCHIP_HIC_MODE_CONT_OUT:
+	default:
+		f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
+		break;
+	case MCHIP_HIC_MODE_CONT_COMP:
+		f->fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;
+		break;
+	}
+
+	f->fmt.pix.field = V4L2_FIELD_NONE;
+	f->fmt.pix.width = mchip_hsize();
+	f->fmt.pix.height = mchip_vsize();
+	f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
+	f->fmt.pix.sizeimage = f->fmt.pix.height *
+			       f->fmt.pix.bytesperline;
+
+	return 0;
+}
+
+static int vidioc_s_fmt_vid_cap(struct file *file, void *fh,
+				    struct v4l2_format *f)
+{
+	if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_YUYV &&
+	    f->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG)
+		return -EINVAL;
+
+	if (f->fmt.pix.field != V4L2_FIELD_ANY &&
+	    f->fmt.pix.field != V4L2_FIELD_NONE)
+		return -EINVAL;
+
+	f->fmt.pix.field = V4L2_FIELD_NONE;
+	mutex_lock(&meye.lock);
+
+	if (f->fmt.pix.width <= 320) {
+		f->fmt.pix.width = 320;
+		f->fmt.pix.height = 240;
+		meye.params.subsample = 1;
+	} else {
+		f->fmt.pix.width = 640;
+		f->fmt.pix.height = 480;
+		meye.params.subsample = 0;
+	}
+
+	switch (f->fmt.pix.pixelformat) {
+	case V4L2_PIX_FMT_YUYV:
+		meye.mchip_mode = MCHIP_HIC_MODE_CONT_OUT;
+		break;
+	case V4L2_PIX_FMT_MJPEG:
+		meye.mchip_mode = MCHIP_HIC_MODE_CONT_COMP;
+		break;
+	}
+
+	mutex_unlock(&meye.lock);
+	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;
+}
+
+static int vidioc_reqbufs(struct file *file, void *fh,
+				struct v4l2_requestbuffers *req)
+{
+	int i;
+
+	if (req->memory != V4L2_MEMORY_MMAP)
+		return -EINVAL;
+
+	if (meye.grab_fbuffer && req->count == gbuffers) {
+		/* already allocated, no modifications */
+		return 0;
+	}
+
+	mutex_lock(&meye.lock);
+	if (meye.grab_fbuffer) {
+		for (i = 0; i < gbuffers; i++)
+			if (meye.vma_use_count[i]) {
+				mutex_unlock(&meye.lock);
+				return -EINVAL;
+			}
+		rvfree(meye.grab_fbuffer, gbuffers * gbufsize);
+		meye.grab_fbuffer = NULL;
+	}
+
+	gbuffers = max(2, min((int)req->count, MEYE_MAX_BUFNBRS));
+	req->count = gbuffers;
+	meye.grab_fbuffer = rvmalloc(gbuffers * gbufsize);
+
+	if (!meye.grab_fbuffer) {
+		printk(KERN_ERR "meye: v4l framebuffer allocation"
+				" failed\n");
+		mutex_unlock(&meye.lock);
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < gbuffers; i++)
+		meye.vma_use_count[i] = 0;
+
+	mutex_unlock(&meye.lock);
+
+	return 0;
+}
+
+static int vidioc_querybuf(struct file *file, void *fh, struct v4l2_buffer *buf)
+{
+	unsigned int index = buf->index;
+
+	if (index >= gbuffers)
+		return -EINVAL;
+
+	buf->bytesused = meye.grab_buffer[index].size;
+	buf->flags = V4L2_BUF_FLAG_MAPPED;
+
+	if (meye.grab_buffer[index].state == MEYE_BUF_USING)
+		buf->flags |= V4L2_BUF_FLAG_QUEUED;
+
+	if (meye.grab_buffer[index].state == MEYE_BUF_DONE)
+		buf->flags |= V4L2_BUF_FLAG_DONE;
+
+	buf->field = V4L2_FIELD_NONE;
+	buf->timestamp = meye.grab_buffer[index].timestamp;
+	buf->sequence = meye.grab_buffer[index].sequence;
+	buf->memory = V4L2_MEMORY_MMAP;
+	buf->m.offset = index * gbufsize;
+	buf->length = gbufsize;
+
+	return 0;
+}
+
+static int vidioc_qbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
+{
+	if (buf->memory != V4L2_MEMORY_MMAP)
+		return -EINVAL;
+
+	if (buf->index >= gbuffers)
+		return -EINVAL;
+
+	if (meye.grab_buffer[buf->index].state != MEYE_BUF_UNUSED)
+		return -EINVAL;
+
+	mutex_lock(&meye.lock);
+	buf->flags |= V4L2_BUF_FLAG_QUEUED;
+	buf->flags &= ~V4L2_BUF_FLAG_DONE;
+	meye.grab_buffer[buf->index].state = MEYE_BUF_USING;
+	kfifo_in_locked(&meye.grabq, (unsigned char *)&buf->index,
+			sizeof(int), &meye.grabq_lock);
+	mutex_unlock(&meye.lock);
+
+	return 0;
+}
+
+static int vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
+{
+	int reqnr;
+
+	if (buf->memory != V4L2_MEMORY_MMAP)
+		return -EINVAL;
+
+	mutex_lock(&meye.lock);
+
+	if (kfifo_len(&meye.doneq) == 0 && file->f_flags & O_NONBLOCK) {
+		mutex_unlock(&meye.lock);
+		return -EAGAIN;
+	}
+
+	if (wait_event_interruptible(meye.proc_list,
+				     kfifo_len(&meye.doneq) != 0) < 0) {
+		mutex_unlock(&meye.lock);
+		return -EINTR;
+	}
+
+	if (!kfifo_out_locked(&meye.doneq, (unsigned char *)&reqnr,
+		       sizeof(int), &meye.doneq_lock)) {
+		mutex_unlock(&meye.lock);
+		return -EBUSY;
+	}
+
+	if (meye.grab_buffer[reqnr].state != MEYE_BUF_DONE) {
+		mutex_unlock(&meye.lock);
+		return -EINVAL;
+	}
+
+	buf->index = reqnr;
+	buf->bytesused = meye.grab_buffer[reqnr].size;
+	buf->flags = V4L2_BUF_FLAG_MAPPED;
+	buf->field = V4L2_FIELD_NONE;
+	buf->timestamp = meye.grab_buffer[reqnr].timestamp;
+	buf->sequence = meye.grab_buffer[reqnr].sequence;
+	buf->memory = V4L2_MEMORY_MMAP;
+	buf->m.offset = reqnr * gbufsize;
+	buf->length = gbufsize;
+	meye.grab_buffer[reqnr].state = MEYE_BUF_UNUSED;
+	mutex_unlock(&meye.lock);
+
+	return 0;
+}
+
+static int vidioc_streamon(struct file *file, void *fh, enum v4l2_buf_type i)
+{
+	mutex_lock(&meye.lock);
+
+	switch (meye.mchip_mode) {
+	case MCHIP_HIC_MODE_CONT_OUT:
+		mchip_continuous_start();
+		break;
+	case MCHIP_HIC_MODE_CONT_COMP:
+		mchip_cont_compression_start();
+		break;
+	default:
+		mutex_unlock(&meye.lock);
+		return -EINVAL;
+	}
+
+	mutex_unlock(&meye.lock);
+
+	return 0;
+}
+
+static int vidioc_streamoff(struct file *file, void *fh, enum v4l2_buf_type i)
+{
+	mutex_lock(&meye.lock);
+	mchip_hic_stop();
+	kfifo_reset(&meye.grabq);
+	kfifo_reset(&meye.doneq);
+
+	for (i = 0; i < MEYE_MAX_BUFNBRS; i++)
+		meye.grab_buffer[i].state = MEYE_BUF_UNUSED;
+
+	mutex_unlock(&meye.lock);
+	return 0;
+}
+
+static long vidioc_default(struct file *file, void *fh, bool valid_prio,
+						int cmd, void *arg)
+{
+	switch (cmd) {
+	case MEYEIOC_G_PARAMS:
+		return meyeioc_g_params((struct meye_params *) arg);
+
+	case MEYEIOC_S_PARAMS:
+		return meyeioc_s_params((struct meye_params *) arg);
+
+	case MEYEIOC_QBUF_CAPT:
+		return meyeioc_qbuf_capt((int *) arg);
+
+	case MEYEIOC_SYNC:
+		return meyeioc_sync(file, fh, (int *) arg);
+
+	case MEYEIOC_STILLCAPT:
+		return meyeioc_stillcapt();
+
+	case MEYEIOC_STILLJCAPT:
+		return meyeioc_stilljcapt((int *) arg);
+
+	default:
+		return -ENOTTY;
+	}
+
+}
+
+static unsigned int meye_poll(struct file *file, poll_table *wait)
+{
+	unsigned int res = 0;
+
+	mutex_lock(&meye.lock);
+	poll_wait(file, &meye.proc_list, wait);
+	if (kfifo_len(&meye.doneq))
+		res = POLLIN | POLLRDNORM;
+	mutex_unlock(&meye.lock);
+	return res;
+}
+
+static void meye_vm_open(struct vm_area_struct *vma)
+{
+	long idx = (long)vma->vm_private_data;
+	meye.vma_use_count[idx]++;
+}
+
+static void meye_vm_close(struct vm_area_struct *vma)
+{
+	long idx = (long)vma->vm_private_data;
+	meye.vma_use_count[idx]--;
+}
+
+static const struct vm_operations_struct meye_vm_ops = {
+	.open		= meye_vm_open,
+	.close		= meye_vm_close,
+};
+
+static int meye_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	unsigned long start = vma->vm_start;
+	unsigned long size = vma->vm_end - vma->vm_start;
+	unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+	unsigned long page, pos;
+
+	mutex_lock(&meye.lock);
+	if (size > gbuffers * gbufsize) {
+		mutex_unlock(&meye.lock);
+		return -EINVAL;
+	}
+	if (!meye.grab_fbuffer) {
+		int i;
+
+		/* lazy allocation */
+		meye.grab_fbuffer = rvmalloc(gbuffers*gbufsize);
+		if (!meye.grab_fbuffer) {
+			printk(KERN_ERR "meye: v4l framebuffer allocation failed\n");
+			mutex_unlock(&meye.lock);
+			return -ENOMEM;
+		}
+		for (i = 0; i < gbuffers; i++)
+			meye.vma_use_count[i] = 0;
+	}
+	pos = (unsigned long)meye.grab_fbuffer + offset;
+
+	while (size > 0) {
+		page = vmalloc_to_pfn((void *)pos);
+		if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) {
+			mutex_unlock(&meye.lock);
+			return -EAGAIN;
+		}
+		start += PAGE_SIZE;
+		pos += PAGE_SIZE;
+		if (size > PAGE_SIZE)
+			size -= PAGE_SIZE;
+		else
+			size = 0;
+	}
+
+	vma->vm_ops = &meye_vm_ops;
+	vma->vm_flags &= ~VM_IO;	/* not I/O memory */
+	vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
+	vma->vm_private_data = (void *) (offset / gbufsize);
+	meye_vm_open(vma);
+
+	mutex_unlock(&meye.lock);
+	return 0;
+}
+
+static const struct v4l2_file_operations meye_fops = {
+	.owner		= THIS_MODULE,
+	.open		= meye_open,
+	.release	= meye_release,
+	.mmap		= meye_mmap,
+	.unlocked_ioctl	= video_ioctl2,
+	.poll		= meye_poll,
+};
+
+static const struct v4l2_ioctl_ops meye_ioctl_ops = {
+	.vidioc_querycap	= vidioc_querycap,
+	.vidioc_enum_input	= vidioc_enum_input,
+	.vidioc_g_input		= vidioc_g_input,
+	.vidioc_s_input		= vidioc_s_input,
+	.vidioc_queryctrl	= vidioc_queryctrl,
+	.vidioc_s_ctrl		= vidioc_s_ctrl,
+	.vidioc_g_ctrl		= vidioc_g_ctrl,
+	.vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
+	.vidioc_try_fmt_vid_cap	= vidioc_try_fmt_vid_cap,
+	.vidioc_g_fmt_vid_cap	= vidioc_g_fmt_vid_cap,
+	.vidioc_s_fmt_vid_cap	= vidioc_s_fmt_vid_cap,
+	.vidioc_reqbufs		= vidioc_reqbufs,
+	.vidioc_querybuf	= vidioc_querybuf,
+	.vidioc_qbuf		= vidioc_qbuf,
+	.vidioc_dqbuf		= vidioc_dqbuf,
+	.vidioc_streamon	= vidioc_streamon,
+	.vidioc_streamoff	= vidioc_streamoff,
+	.vidioc_default		= vidioc_default,
+};
+
+static struct video_device meye_template = {
+	.name		= "meye",
+	.fops		= &meye_fops,
+	.ioctl_ops 	= &meye_ioctl_ops,
+	.release	= video_device_release,
+};
+
+#ifdef CONFIG_PM
+static int meye_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	pci_save_state(pdev);
+	meye.pm_mchip_mode = meye.mchip_mode;
+	mchip_hic_stop();
+	mchip_set(MCHIP_MM_INTA, 0x0);
+	return 0;
+}
+
+static int meye_resume(struct pci_dev *pdev)
+{
+	pci_restore_state(pdev);
+	pci_write_config_word(meye.mchip_dev, MCHIP_PCI_SOFTRESET_SET, 1);
+
+	mchip_delay(MCHIP_HIC_CMD, 0);
+	mchip_delay(MCHIP_HIC_STATUS, MCHIP_HIC_STATUS_IDLE);
+	msleep(1);
+	mchip_set(MCHIP_VRJ_SOFT_RESET, 1);
+	msleep(1);
+	mchip_set(MCHIP_MM_PCI_MODE, 5);
+	msleep(1);
+	mchip_set(MCHIP_MM_INTA, MCHIP_MM_INTA_HIC_1_MASK);
+
+	switch (meye.pm_mchip_mode) {
+	case MCHIP_HIC_MODE_CONT_OUT:
+		mchip_continuous_start();
+		break;
+	case MCHIP_HIC_MODE_CONT_COMP:
+		mchip_cont_compression_start();
+		break;
+	}
+	return 0;
+}
+#endif
+
+static int __devinit meye_probe(struct pci_dev *pcidev,
+				const struct pci_device_id *ent)
+{
+	struct v4l2_device *v4l2_dev = &meye.v4l2_dev;
+	int ret = -EBUSY;
+	unsigned long mchip_adr;
+
+	if (meye.mchip_dev != NULL) {
+		printk(KERN_ERR "meye: only one device allowed!\n");
+		goto outnotdev;
+	}
+
+	ret = v4l2_device_register(&pcidev->dev, v4l2_dev);
+	if (ret < 0) {
+		v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
+		return ret;
+	}
+	ret = -ENOMEM;
+	meye.mchip_dev = pcidev;
+	meye.vdev = video_device_alloc();
+	if (!meye.vdev) {
+		v4l2_err(v4l2_dev, "video_device_alloc() failed!\n");
+		goto outnotdev;
+	}
+
+	meye.grab_temp = vmalloc(MCHIP_NB_PAGES_MJPEG * PAGE_SIZE);
+	if (!meye.grab_temp) {
+		v4l2_err(v4l2_dev, "grab buffer allocation failed\n");
+		goto outvmalloc;
+	}
+
+	spin_lock_init(&meye.grabq_lock);
+	if (kfifo_alloc(&meye.grabq, sizeof(int) * MEYE_MAX_BUFNBRS,
+				GFP_KERNEL)) {
+		v4l2_err(v4l2_dev, "fifo allocation failed\n");
+		goto outkfifoalloc1;
+	}
+	spin_lock_init(&meye.doneq_lock);
+	if (kfifo_alloc(&meye.doneq, sizeof(int) * MEYE_MAX_BUFNBRS,
+				GFP_KERNEL)) {
+		v4l2_err(v4l2_dev, "fifo allocation failed\n");
+		goto outkfifoalloc2;
+	}
+
+	memcpy(meye.vdev, &meye_template, sizeof(meye_template));
+	meye.vdev->v4l2_dev = &meye.v4l2_dev;
+
+	ret = -EIO;
+	if ((ret = sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERA, 1))) {
+		v4l2_err(v4l2_dev, "meye: unable to power on the camera\n");
+		v4l2_err(v4l2_dev, "meye: did you enable the camera in "
+				"sonypi using the module options ?\n");
+		goto outsonypienable;
+	}
+
+	if ((ret = pci_enable_device(meye.mchip_dev))) {
+		v4l2_err(v4l2_dev, "meye: pci_enable_device failed\n");
+		goto outenabledev;
+	}
+
+	mchip_adr = pci_resource_start(meye.mchip_dev,0);
+	if (!mchip_adr) {
+		v4l2_err(v4l2_dev, "meye: mchip has no device base address\n");
+		goto outregions;
+	}
+	if (!request_mem_region(pci_resource_start(meye.mchip_dev, 0),
+				pci_resource_len(meye.mchip_dev, 0),
+				"meye")) {
+		v4l2_err(v4l2_dev, "meye: request_mem_region failed\n");
+		goto outregions;
+	}
+	meye.mchip_mmregs = ioremap(mchip_adr, MCHIP_MM_REGS);
+	if (!meye.mchip_mmregs) {
+		v4l2_err(v4l2_dev, "meye: ioremap failed\n");
+		goto outremap;
+	}
+
+	meye.mchip_irq = pcidev->irq;
+	if (request_irq(meye.mchip_irq, meye_irq,
+			IRQF_DISABLED | IRQF_SHARED, "meye", meye_irq)) {
+		v4l2_err(v4l2_dev, "request_irq failed\n");
+		goto outreqirq;
+	}
+
+	pci_write_config_byte(meye.mchip_dev, PCI_CACHE_LINE_SIZE, 8);
+	pci_write_config_byte(meye.mchip_dev, PCI_LATENCY_TIMER, 64);
+
+	pci_set_master(meye.mchip_dev);
+
+	/* Ask the camera to perform a soft reset. */
+	pci_write_config_word(meye.mchip_dev, MCHIP_PCI_SOFTRESET_SET, 1);
+
+	mchip_delay(MCHIP_HIC_CMD, 0);
+	mchip_delay(MCHIP_HIC_STATUS, MCHIP_HIC_STATUS_IDLE);
+
+	msleep(1);
+	mchip_set(MCHIP_VRJ_SOFT_RESET, 1);
+
+	msleep(1);
+	mchip_set(MCHIP_MM_PCI_MODE, 5);
+
+	msleep(1);
+	mchip_set(MCHIP_MM_INTA, MCHIP_MM_INTA_HIC_1_MASK);
+
+	mutex_init(&meye.lock);
+	init_waitqueue_head(&meye.proc_list);
+	meye.brightness = 32 << 10;
+	meye.hue = 32 << 10;
+	meye.colour = 32 << 10;
+	meye.contrast = 32 << 10;
+	meye.params.subsample = 0;
+	meye.params.quality = 8;
+	meye.params.sharpness = 32;
+	meye.params.agc = 48;
+	meye.params.picture = 0;
+	meye.params.framerate = 0;
+
+	sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERABRIGHTNESS, 32);
+	sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAHUE, 32);
+	sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERACOLOR, 32);
+	sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERACONTRAST, 32);
+	sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERASHARPNESS, 32);
+	sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAPICTURE, 0);
+	sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAAGC, 48);
+
+	if (video_register_device(meye.vdev, VFL_TYPE_GRABBER,
+				  video_nr) < 0) {
+		v4l2_err(v4l2_dev, "video_register_device failed\n");
+		goto outvideoreg;
+	}
+
+	v4l2_info(v4l2_dev, "Motion Eye Camera Driver v%s.\n",
+	       MEYE_DRIVER_VERSION);
+	v4l2_info(v4l2_dev, "mchip KL5A72002 rev. %d, base %lx, irq %d\n",
+	       meye.mchip_dev->revision, mchip_adr, meye.mchip_irq);
+
+	return 0;
+
+outvideoreg:
+	free_irq(meye.mchip_irq, meye_irq);
+outreqirq:
+	iounmap(meye.mchip_mmregs);
+outremap:
+	release_mem_region(pci_resource_start(meye.mchip_dev, 0),
+			   pci_resource_len(meye.mchip_dev, 0));
+outregions:
+	pci_disable_device(meye.mchip_dev);
+outenabledev:
+	sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERA, 0);
+outsonypienable:
+	kfifo_free(&meye.doneq);
+outkfifoalloc2:
+	kfifo_free(&meye.grabq);
+outkfifoalloc1:
+	vfree(meye.grab_temp);
+outvmalloc:
+	video_device_release(meye.vdev);
+outnotdev:
+	return ret;
+}
+
+static void __devexit meye_remove(struct pci_dev *pcidev)
+{
+	video_unregister_device(meye.vdev);
+
+	mchip_hic_stop();
+
+	mchip_dma_free();
+
+	/* disable interrupts */
+	mchip_set(MCHIP_MM_INTA, 0x0);
+
+	free_irq(meye.mchip_irq, meye_irq);
+
+	iounmap(meye.mchip_mmregs);
+
+	release_mem_region(pci_resource_start(meye.mchip_dev, 0),
+			   pci_resource_len(meye.mchip_dev, 0));
+
+	pci_disable_device(meye.mchip_dev);
+
+	sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERA, 0);
+
+	kfifo_free(&meye.doneq);
+	kfifo_free(&meye.grabq);
+
+	vfree(meye.grab_temp);
+
+	if (meye.grab_fbuffer) {
+		rvfree(meye.grab_fbuffer, gbuffers*gbufsize);
+		meye.grab_fbuffer = NULL;
+	}
+
+	printk(KERN_INFO "meye: removed\n");
+}
+
+static struct pci_device_id meye_pci_tbl[] = {
+	{ PCI_VDEVICE(KAWASAKI, PCI_DEVICE_ID_MCHIP_KL5A72002), 0 },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(pci, meye_pci_tbl);
+
+static struct pci_driver meye_driver = {
+	.name		= "meye",
+	.id_table	= meye_pci_tbl,
+	.probe		= meye_probe,
+	.remove		= __devexit_p(meye_remove),
+#ifdef CONFIG_PM
+	.suspend	= meye_suspend,
+	.resume		= meye_resume,
+#endif
+};
+
+static int __init meye_init(void)
+{
+	gbuffers = max(2, min((int)gbuffers, MEYE_MAX_BUFNBRS));
+	if (gbufsize < 0 || gbufsize > MEYE_MAX_BUFSIZE)
+		gbufsize = MEYE_MAX_BUFSIZE;
+	gbufsize = PAGE_ALIGN(gbufsize);
+	printk(KERN_INFO "meye: using %d buffers with %dk (%dk total) "
+			 "for capture\n",
+			 gbuffers,
+			 gbufsize / 1024, gbuffers * gbufsize / 1024);
+	return pci_register_driver(&meye_driver);
+}
+
+static void __exit meye_exit(void)
+{
+	pci_unregister_driver(&meye_driver);
+}
+
+module_init(meye_init);
+module_exit(meye_exit);
diff --git a/drivers/media/pci/meye/meye.h b/drivers/media/pci/meye/meye.h
new file mode 100644
index 0000000..4bdeb03
--- /dev/null
+++ b/drivers/media/pci/meye/meye.h
@@ -0,0 +1,324 @@
+/*
+ * Motion Eye video4linux driver for Sony Vaio PictureBook
+ *
+ * Copyright (C) 2001-2004 Stelian Pop <stelian@popies.net>
+ *
+ * Copyright (C) 2001-2002 Alcôve <www.alcove.com>
+ *
+ * Copyright (C) 2000 Andrew Tridgell <tridge@valinux.com>
+ *
+ * Earlier work by Werner Almesberger, Paul `Rusty' Russell and Paul Mackerras.
+ *
+ * Some parts borrowed from various video4linux drivers, especially
+ * bttv-driver.c and zoran.c, see original files for credits.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 _MEYE_PRIV_H_
+#define _MEYE_PRIV_H_
+
+#define MEYE_DRIVER_MAJORVERSION	 1
+#define MEYE_DRIVER_MINORVERSION	14
+
+#define MEYE_DRIVER_VERSION __stringify(MEYE_DRIVER_MAJORVERSION) "." \
+			    __stringify(MEYE_DRIVER_MINORVERSION)
+
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kfifo.h>
+
+/****************************************************************************/
+/* Motion JPEG chip registers                                               */
+/****************************************************************************/
+
+/* Motion JPEG chip PCI configuration registers */
+#define MCHIP_PCI_POWER_CSR		0x54
+#define MCHIP_PCI_MCORE_STATUS		0x60		/* see HIC_STATUS   */
+#define MCHIP_PCI_HOSTUSEREQ_SET	0x64
+#define MCHIP_PCI_HOSTUSEREQ_CLR	0x68
+#define MCHIP_PCI_LOWPOWER_SET		0x6c
+#define MCHIP_PCI_LOWPOWER_CLR		0x70
+#define MCHIP_PCI_SOFTRESET_SET		0x74
+
+/* Motion JPEG chip memory mapped registers */
+#define MCHIP_MM_REGS			0x200		/* 512 bytes        */
+#define MCHIP_REG_TIMEOUT		1000		/* reg access, ~us  */
+#define MCHIP_MCC_VRJ_TIMEOUT		1000		/* MCC & VRJ access */
+
+#define MCHIP_MM_PCI_MODE		0x00		/* PCI access mode */
+#define MCHIP_MM_PCI_MODE_RETRY		0x00000001	/* retry mode */
+#define MCHIP_MM_PCI_MODE_MASTER	0x00000002	/* master access */
+#define MCHIP_MM_PCI_MODE_READ_LINE	0x00000004	/* read line */
+
+#define MCHIP_MM_INTA			0x04		/* Int status/mask */
+#define MCHIP_MM_INTA_MCC		0x00000001	/* MCC interrupt */
+#define MCHIP_MM_INTA_VRJ		0x00000002	/* VRJ interrupt */
+#define MCHIP_MM_INTA_HIC_1		0x00000004	/* one frame done */
+#define MCHIP_MM_INTA_HIC_1_MASK	0x00000400	/* 1: enable */
+#define MCHIP_MM_INTA_HIC_END		0x00000008	/* all frames done */
+#define MCHIP_MM_INTA_HIC_END_MASK	0x00000800
+#define MCHIP_MM_INTA_JPEG		0x00000010	/* decompress. error */
+#define MCHIP_MM_INTA_JPEG_MASK		0x00001000
+#define MCHIP_MM_INTA_CAPTURE		0x00000020	/* capture end */
+#define MCHIP_MM_INTA_PCI_ERR		0x00000040	/* PCI error */
+#define MCHIP_MM_INTA_PCI_ERR_MASK	0x00004000
+
+#define MCHIP_MM_PT_ADDR		0x08		/* page table address*/
+							/* n*4kB */
+#define MCHIP_NB_PAGES			1024		/* pages for display */
+#define MCHIP_NB_PAGES_MJPEG		256		/* pages for mjpeg */
+
+#define MCHIP_MM_FIR(n)			(0x0c+(n)*4)	/* Frame info 0-3 */
+#define MCHIP_MM_FIR_RDY		0x00000001	/* frame ready */
+#define MCHIP_MM_FIR_FAILFR_MASK	0xf8000000	/* # of failed frames */
+#define MCHIP_MM_FIR_FAILFR_SHIFT	27
+
+	/* continuous comp/decomp mode */
+#define MCHIP_MM_FIR_C_ENDL_MASK	0x000007fe	/* end DW [10] */
+#define MCHIP_MM_FIR_C_ENDL_SHIFT	1
+#define MCHIP_MM_FIR_C_ENDP_MASK	0x0007f800	/* end page [8] */
+#define MCHIP_MM_FIR_C_ENDP_SHIFT	11
+#define MCHIP_MM_FIR_C_STARTP_MASK	0x07f80000	/* start page [8] */
+#define MCHIP_MM_FIR_C_STARTP_SHIFT	19
+
+	/* continuous picture output mode */
+#define MCHIP_MM_FIR_O_STARTP_MASK	0x7ffe0000	/* start page [10] */
+#define MCHIP_MM_FIR_O_STARTP_SHIFT	17
+
+#define MCHIP_MM_FIFO_DATA		0x1c		/* PCI TGT FIFO data */
+#define MCHIP_MM_FIFO_STATUS		0x20		/* PCI TGT FIFO stat */
+#define MCHIP_MM_FIFO_MASK		0x00000003
+#define MCHIP_MM_FIFO_WAIT_OR_READY	0x00000002      /* Bits common to WAIT & READY*/
+#define MCHIP_MM_FIFO_IDLE		0x0		/* HIC idle */
+#define MCHIP_MM_FIFO_IDLE1		0x1		/* idem ??? */
+#define	MCHIP_MM_FIFO_WAIT		0x2		/* wait request */
+#define MCHIP_MM_FIFO_READY		0x3		/* data ready */
+
+#define MCHIP_HIC_HOST_USEREQ		0x40		/* host uses MCORE */
+
+#define MCHIP_HIC_TP_BUSY		0x44		/* taking picture */
+
+#define MCHIP_HIC_PIC_SAVED		0x48		/* pic in SDRAM */
+
+#define MCHIP_HIC_LOWPOWER		0x4c		/* clock stopped */
+
+#define MCHIP_HIC_CTL			0x50		/* HIC control */
+#define MCHIP_HIC_CTL_SOFT_RESET	0x00000001	/* MCORE reset */
+#define MCHIP_HIC_CTL_MCORE_RDY		0x00000002	/* MCORE ready */
+
+#define MCHIP_HIC_CMD			0x54		/* HIC command */
+#define MCHIP_HIC_CMD_BITS		0x00000003      /* cmd width=[1:0]*/
+#define MCHIP_HIC_CMD_NOOP		0x0
+#define MCHIP_HIC_CMD_START		0x1
+#define MCHIP_HIC_CMD_STOP		0x2
+
+#define MCHIP_HIC_MODE			0x58
+#define MCHIP_HIC_MODE_NOOP		0x0
+#define MCHIP_HIC_MODE_STILL_CAP	0x1		/* still pic capt */
+#define MCHIP_HIC_MODE_DISPLAY		0x2		/* display */
+#define MCHIP_HIC_MODE_STILL_COMP	0x3		/* still pic comp. */
+#define MCHIP_HIC_MODE_STILL_DECOMP	0x4		/* still pic decomp. */
+#define MCHIP_HIC_MODE_CONT_COMP	0x5		/* cont capt+comp */
+#define MCHIP_HIC_MODE_CONT_DECOMP	0x6		/* cont decomp+disp */
+#define MCHIP_HIC_MODE_STILL_OUT	0x7		/* still pic output */
+#define MCHIP_HIC_MODE_CONT_OUT		0x8		/* cont output */
+
+#define MCHIP_HIC_STATUS		0x5c
+#define MCHIP_HIC_STATUS_MCC_RDY	0x00000001	/* MCC reg acc ok */
+#define MCHIP_HIC_STATUS_VRJ_RDY	0x00000002	/* VRJ reg acc ok */
+#define MCHIP_HIC_STATUS_IDLE           0x00000003
+#define MCHIP_HIC_STATUS_CAPDIS		0x00000004	/* cap/disp in prog */
+#define MCHIP_HIC_STATUS_COMPDEC	0x00000008	/* (de)comp in prog */
+#define MCHIP_HIC_STATUS_BUSY		0x00000010	/* HIC busy */
+
+#define MCHIP_HIC_S_RATE		0x60		/* MJPEG # frames */
+
+#define MCHIP_HIC_PCI_VFMT		0x64		/* video format */
+#define MCHIP_HIC_PCI_VFMT_YVYU		0x00000001	/* 0: V Y' U Y */
+							/* 1: Y' V Y U */
+
+#define MCHIP_MCC_CMD			0x80		/* MCC commands */
+#define MCHIP_MCC_CMD_INITIAL		0x0		/* idle ? */
+#define MCHIP_MCC_CMD_IIC_START_SET	0x1
+#define MCHIP_MCC_CMD_IIC_END_SET	0x2
+#define MCHIP_MCC_CMD_FM_WRITE		0x3		/* frame memory */
+#define MCHIP_MCC_CMD_FM_READ		0x4
+#define MCHIP_MCC_CMD_FM_STOP		0x5
+#define MCHIP_MCC_CMD_CAPTURE		0x6
+#define MCHIP_MCC_CMD_DISPLAY		0x7
+#define MCHIP_MCC_CMD_END_DISP		0x8
+#define MCHIP_MCC_CMD_STILL_COMP	0x9
+#define MCHIP_MCC_CMD_STILL_DECOMP	0xa
+#define MCHIP_MCC_CMD_STILL_OUTPUT	0xb
+#define MCHIP_MCC_CMD_CONT_OUTPUT	0xc
+#define MCHIP_MCC_CMD_CONT_COMP		0xd
+#define MCHIP_MCC_CMD_CONT_DECOMP	0xe
+#define MCHIP_MCC_CMD_RESET		0xf		/* MCC reset */
+
+#define MCHIP_MCC_IIC_WR		0x84
+
+#define MCHIP_MCC_MCC_WR		0x88
+
+#define MCHIP_MCC_MCC_RD		0x8c
+
+#define MCHIP_MCC_STATUS		0x90
+#define MCHIP_MCC_STATUS_CAPT		0x00000001	/* capturing */
+#define MCHIP_MCC_STATUS_DISP		0x00000002	/* displaying */
+#define MCHIP_MCC_STATUS_COMP		0x00000004	/* compressing */
+#define MCHIP_MCC_STATUS_DECOMP		0x00000008	/* decompressing */
+#define MCHIP_MCC_STATUS_MCC_WR		0x00000010	/* register ready */
+#define MCHIP_MCC_STATUS_MCC_RD		0x00000020	/* register ready */
+#define MCHIP_MCC_STATUS_IIC_WR		0x00000040	/* register ready */
+#define MCHIP_MCC_STATUS_OUTPUT		0x00000080	/* output in prog */
+
+#define MCHIP_MCC_SIG_POLARITY		0x94
+#define MCHIP_MCC_SIG_POL_VS_H		0x00000001	/* VS active-high */
+#define MCHIP_MCC_SIG_POL_HS_H		0x00000002	/* HS active-high */
+#define MCHIP_MCC_SIG_POL_DOE_H		0x00000004	/* DOE active-high */
+
+#define MCHIP_MCC_IRQ			0x98
+#define MCHIP_MCC_IRQ_CAPDIS_STRT	0x00000001	/* cap/disp started */
+#define MCHIP_MCC_IRQ_CAPDIS_STRT_MASK	0x00000010
+#define MCHIP_MCC_IRQ_CAPDIS_END	0x00000002	/* cap/disp ended */
+#define MCHIP_MCC_IRQ_CAPDIS_END_MASK	0x00000020
+#define MCHIP_MCC_IRQ_COMPDEC_STRT	0x00000004	/* (de)comp started */
+#define MCHIP_MCC_IRQ_COMPDEC_STRT_MASK	0x00000040
+#define MCHIP_MCC_IRQ_COMPDEC_END	0x00000008	/* (de)comp ended */
+#define MCHIP_MCC_IRQ_COMPDEC_END_MASK	0x00000080
+
+#define MCHIP_MCC_HSTART		0x9c		/* video in */
+#define MCHIP_MCC_VSTART		0xa0
+#define MCHIP_MCC_HCOUNT		0xa4
+#define MCHIP_MCC_VCOUNT		0xa8
+#define MCHIP_MCC_R_XBASE		0xac		/* capt/disp */
+#define MCHIP_MCC_R_YBASE		0xb0
+#define MCHIP_MCC_R_XRANGE		0xb4
+#define MCHIP_MCC_R_YRANGE		0xb8
+#define MCHIP_MCC_B_XBASE		0xbc		/* comp/decomp */
+#define MCHIP_MCC_B_YBASE		0xc0
+#define MCHIP_MCC_B_XRANGE		0xc4
+#define MCHIP_MCC_B_YRANGE		0xc8
+
+#define MCHIP_MCC_R_SAMPLING		0xcc		/* 1: 1:4 */
+
+#define MCHIP_VRJ_CMD			0x100		/* VRJ commands */
+
+/* VRJ registers (see table 12.2.4) */
+#define MCHIP_VRJ_COMPRESSED_DATA	0x1b0
+#define MCHIP_VRJ_PIXEL_DATA		0x1b8
+
+#define MCHIP_VRJ_BUS_MODE		0x100
+#define MCHIP_VRJ_SIGNAL_ACTIVE_LEVEL	0x108
+#define MCHIP_VRJ_PDAT_USE		0x110
+#define MCHIP_VRJ_MODE_SPECIFY		0x118
+#define MCHIP_VRJ_LIMIT_COMPRESSED_LO	0x120
+#define MCHIP_VRJ_LIMIT_COMPRESSED_HI	0x124
+#define MCHIP_VRJ_COMP_DATA_FORMAT	0x128
+#define MCHIP_VRJ_TABLE_DATA		0x140
+#define MCHIP_VRJ_RESTART_INTERVAL	0x148
+#define MCHIP_VRJ_NUM_LINES		0x150
+#define MCHIP_VRJ_NUM_PIXELS		0x158
+#define MCHIP_VRJ_NUM_COMPONENTS	0x160
+#define MCHIP_VRJ_SOF1			0x168
+#define MCHIP_VRJ_SOF2			0x170
+#define MCHIP_VRJ_SOF3			0x178
+#define MCHIP_VRJ_SOF4			0x180
+#define MCHIP_VRJ_SOS			0x188
+#define MCHIP_VRJ_SOFT_RESET		0x190
+
+#define MCHIP_VRJ_STATUS		0x1c0
+#define MCHIP_VRJ_STATUS_BUSY		0x00001
+#define MCHIP_VRJ_STATUS_COMP_ACCESS	0x00002
+#define MCHIP_VRJ_STATUS_PIXEL_ACCESS	0x00004
+#define MCHIP_VRJ_STATUS_ERROR		0x00008
+
+#define MCHIP_VRJ_IRQ_FLAG		0x1c8
+#define MCHIP_VRJ_ERROR_REPORT		0x1d8
+
+#define MCHIP_VRJ_START_COMMAND		0x1a0
+
+/****************************************************************************/
+/* Driver definitions.                                                      */
+/****************************************************************************/
+
+/* Sony Programmable I/O Controller for accessing the camera commands */
+#include <linux/sony-laptop.h>
+
+/* private API definitions */
+#include <linux/meye.h>
+#include <linux/mutex.h>
+
+
+/* Enable jpg software correction */
+#define MEYE_JPEG_CORRECTION	1
+
+/* Maximum size of a buffer */
+#define MEYE_MAX_BUFSIZE	614400	/* 640 * 480 * 2 */
+
+/* Maximum number of buffers */
+#define MEYE_MAX_BUFNBRS	32
+
+/* State of a buffer */
+#define MEYE_BUF_UNUSED	0	/* not used */
+#define MEYE_BUF_USING	1	/* currently grabbing / playing */
+#define MEYE_BUF_DONE	2	/* done */
+
+/* grab buffer */
+struct meye_grab_buffer {
+	int state;			/* state of buffer */
+	unsigned long size;		/* size of jpg frame */
+	struct timeval timestamp;	/* timestamp */
+	unsigned long sequence;		/* sequence number */
+};
+
+/* size of kfifos containings buffer indices */
+#define MEYE_QUEUE_SIZE	MEYE_MAX_BUFNBRS
+
+/* Motion Eye device structure */
+struct meye {
+	struct v4l2_device v4l2_dev;	/* Main v4l2_device struct */
+	struct pci_dev *mchip_dev;	/* pci device */
+	u8 mchip_irq;			/* irq */
+	u8 mchip_mode;			/* actual mchip mode: HIC_MODE... */
+	u8 mchip_fnum;			/* current mchip frame number */
+	unsigned char __iomem *mchip_mmregs;/* mchip: memory mapped registers */
+	u8 *mchip_ptable[MCHIP_NB_PAGES];/* mchip: ptable */
+	void *mchip_ptable_toc;		/* mchip: ptable toc */
+	dma_addr_t mchip_dmahandle;	/* mchip: dma handle to ptable toc */
+	unsigned char *grab_fbuffer;	/* capture framebuffer */
+	unsigned char *grab_temp;	/* temporary buffer */
+					/* list of buffers */
+	struct meye_grab_buffer grab_buffer[MEYE_MAX_BUFNBRS];
+	int vma_use_count[MEYE_MAX_BUFNBRS]; /* mmap count */
+	struct mutex lock;		/* mutex for open/mmap... */
+	struct kfifo grabq;		/* queue for buffers to be grabbed */
+	spinlock_t grabq_lock;		/* lock protecting the queue */
+	struct kfifo doneq;		/* queue for grabbed buffers */
+	spinlock_t doneq_lock;		/* lock protecting the queue */
+	wait_queue_head_t proc_list;	/* wait queue */
+	struct video_device *vdev;	/* video device parameters */
+	u16 brightness;
+	u16 hue;
+	u16 contrast;
+	u16 colour;
+	struct meye_params params;	/* additional parameters */
+	unsigned long in_use;		/* set to 1 if the device is in use */
+#ifdef CONFIG_PM
+	u8 pm_mchip_mode;		/* old mchip mode */
+#endif
+};
+
+#endif
diff --git a/drivers/media/pci/ngene/Kconfig b/drivers/media/pci/ngene/Kconfig
new file mode 100644
index 0000000..637d506
--- /dev/null
+++ b/drivers/media/pci/ngene/Kconfig
@@ -0,0 +1,13 @@
+config DVB_NGENE
+	tristate "Micronas nGene support"
+	depends on DVB_CORE && PCI && I2C
+	select DVB_LNBP21 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_STV6110x if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_STV090x if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_LGDT330X if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_DRXK if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_TDA18271C2DD if MEDIA_SUBDRV_AUTOSELECT
+	select MEDIA_TUNER_MT2131 if MEDIA_SUBDRV_AUTOSELECT
+	---help---
+	  Support for Micronas PCI express cards with nGene bridge.
+
diff --git a/drivers/media/pci/ngene/Makefile b/drivers/media/pci/ngene/Makefile
new file mode 100644
index 0000000..5c0b5d6
--- /dev/null
+++ b/drivers/media/pci/ngene/Makefile
@@ -0,0 +1,14 @@
+#
+# Makefile for the nGene device driver
+#
+
+ngene-objs := ngene-core.o ngene-i2c.o ngene-cards.o ngene-dvb.o
+
+obj-$(CONFIG_DVB_NGENE) += ngene.o
+
+ccflags-y += -Idrivers/media/dvb-core/
+ccflags-y += -Idrivers/media/dvb-frontends/
+ccflags-y += -Idrivers/media/tuners/
+
+# For the staging CI driver cxd2099
+ccflags-y += -Idrivers/staging/media/cxd2099/
diff --git a/drivers/media/pci/ngene/ngene-cards.c b/drivers/media/pci/ngene/ngene-cards.c
new file mode 100644
index 0000000..96a13ed
--- /dev/null
+++ b/drivers/media/pci/ngene/ngene-cards.c
@@ -0,0 +1,823 @@
+/*
+ * ngene-cards.c: nGene PCIe bridge driver - card specific info
+ *
+ * Copyright (C) 2005-2007 Micronas
+ *
+ * Copyright (C) 2008-2009 Ralph Metzler <rjkm@metzlerbros.de>
+ *                         Modifications for new nGene firmware,
+ *                         support for EEPROM-copying,
+ *                         support for new dual DVB-S2 card prototype
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 only, as published by the Free Software Foundation.
+ *
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+
+#include "ngene.h"
+
+/* demods/tuners */
+#include "stv6110x.h"
+#include "stv090x.h"
+#include "lnbh24.h"
+#include "lgdt330x.h"
+#include "mt2131.h"
+#include "tda18271c2dd.h"
+#include "drxk.h"
+#include "drxd.h"
+#include "dvb-pll.h"
+
+
+/****************************************************************************/
+/* Demod/tuner attachment ***************************************************/
+/****************************************************************************/
+
+static int tuner_attach_stv6110(struct ngene_channel *chan)
+{
+	struct i2c_adapter *i2c;
+	struct stv090x_config *feconf = (struct stv090x_config *)
+		chan->dev->card_info->fe_config[chan->number];
+	struct stv6110x_config *tunerconf = (struct stv6110x_config *)
+		chan->dev->card_info->tuner_config[chan->number];
+	struct stv6110x_devctl *ctl;
+
+	/* tuner 1+2: i2c adapter #0, tuner 3+4: i2c adapter #1 */
+	if (chan->number < 2)
+		i2c = &chan->dev->channel[0].i2c_adapter;
+	else
+		i2c = &chan->dev->channel[1].i2c_adapter;
+
+	ctl = dvb_attach(stv6110x_attach, chan->fe, tunerconf, i2c);
+	if (ctl == NULL) {
+		printk(KERN_ERR	DEVICE_NAME ": No STV6110X found!\n");
+		return -ENODEV;
+	}
+
+	feconf->tuner_init          = ctl->tuner_init;
+	feconf->tuner_sleep         = ctl->tuner_sleep;
+	feconf->tuner_set_mode      = ctl->tuner_set_mode;
+	feconf->tuner_set_frequency = ctl->tuner_set_frequency;
+	feconf->tuner_get_frequency = ctl->tuner_get_frequency;
+	feconf->tuner_set_bandwidth = ctl->tuner_set_bandwidth;
+	feconf->tuner_get_bandwidth = ctl->tuner_get_bandwidth;
+	feconf->tuner_set_bbgain    = ctl->tuner_set_bbgain;
+	feconf->tuner_get_bbgain    = ctl->tuner_get_bbgain;
+	feconf->tuner_set_refclk    = ctl->tuner_set_refclk;
+	feconf->tuner_get_status    = ctl->tuner_get_status;
+
+	return 0;
+}
+
+
+static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+	struct ngene_channel *chan = fe->sec_priv;
+	int status;
+
+	if (enable) {
+		down(&chan->dev->pll_mutex);
+		status = chan->gate_ctrl(fe, 1);
+	} else {
+		status = chan->gate_ctrl(fe, 0);
+		up(&chan->dev->pll_mutex);
+	}
+	return status;
+}
+
+static int tuner_attach_tda18271(struct ngene_channel *chan)
+{
+	struct i2c_adapter *i2c;
+	struct dvb_frontend *fe;
+
+	i2c = &chan->dev->channel[0].i2c_adapter;
+	if (chan->fe->ops.i2c_gate_ctrl)
+		chan->fe->ops.i2c_gate_ctrl(chan->fe, 1);
+	fe = dvb_attach(tda18271c2dd_attach, chan->fe, i2c, 0x60);
+	if (chan->fe->ops.i2c_gate_ctrl)
+		chan->fe->ops.i2c_gate_ctrl(chan->fe, 0);
+	if (!fe) {
+		printk(KERN_ERR "No TDA18271 found!\n");
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static int tuner_attach_probe(struct ngene_channel *chan)
+{
+	if (chan->demod_type == 0)
+		return tuner_attach_stv6110(chan);
+	if (chan->demod_type == 1)
+		return tuner_attach_tda18271(chan);
+	return -EINVAL;
+}
+
+static int demod_attach_stv0900(struct ngene_channel *chan)
+{
+	struct i2c_adapter *i2c;
+	struct stv090x_config *feconf = (struct stv090x_config *)
+		chan->dev->card_info->fe_config[chan->number];
+
+	/* tuner 1+2: i2c adapter #0, tuner 3+4: i2c adapter #1 */
+	/* Note: Both adapters share the same i2c bus, but the demod     */
+	/*       driver requires that each demod has its own i2c adapter */
+	if (chan->number < 2)
+		i2c = &chan->dev->channel[0].i2c_adapter;
+	else
+		i2c = &chan->dev->channel[1].i2c_adapter;
+
+	chan->fe = dvb_attach(stv090x_attach, feconf, i2c,
+			(chan->number & 1) == 0 ? STV090x_DEMODULATOR_0
+						: STV090x_DEMODULATOR_1);
+	if (chan->fe == NULL) {
+		printk(KERN_ERR	DEVICE_NAME ": No STV0900 found!\n");
+		return -ENODEV;
+	}
+
+	/* store channel info */
+	if (feconf->tuner_i2c_lock)
+		chan->fe->analog_demod_priv = chan;
+
+	if (!dvb_attach(lnbh24_attach, chan->fe, i2c, 0,
+			0, chan->dev->card_info->lnb[chan->number])) {
+		printk(KERN_ERR DEVICE_NAME ": No LNBH24 found!\n");
+		dvb_frontend_detach(chan->fe);
+		chan->fe = NULL;
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static void cineS2_tuner_i2c_lock(struct dvb_frontend *fe, int lock)
+{
+	struct ngene_channel *chan = fe->analog_demod_priv;
+
+	if (lock)
+		down(&chan->dev->pll_mutex);
+	else
+		up(&chan->dev->pll_mutex);
+}
+
+static int i2c_read(struct i2c_adapter *adapter, u8 adr, u8 *val)
+{
+	struct i2c_msg msgs[1] = {{.addr = adr,  .flags = I2C_M_RD,
+				   .buf  = val,  .len   = 1 } };
+	return (i2c_transfer(adapter, msgs, 1) == 1) ? 0 : -1;
+}
+
+static int i2c_read_reg16(struct i2c_adapter *adapter, u8 adr,
+			  u16 reg, u8 *val)
+{
+	u8 msg[2] = {reg>>8, reg&0xff};
+	struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0,
+				   .buf  = msg, .len   = 2},
+				  {.addr = adr, .flags = I2C_M_RD,
+				   .buf  = val, .len   = 1} };
+	return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1;
+}
+
+static int port_has_stv0900(struct i2c_adapter *i2c, int port)
+{
+	u8 val;
+	if (i2c_read_reg16(i2c, 0x68+port/2, 0xf100, &val) < 0)
+		return 0;
+	return 1;
+}
+
+static int port_has_drxk(struct i2c_adapter *i2c, int port)
+{
+	u8 val;
+
+	if (i2c_read(i2c, 0x29+port, &val) < 0)
+		return 0;
+	return 1;
+}
+
+static int demod_attach_drxk(struct ngene_channel *chan,
+			     struct i2c_adapter *i2c)
+{
+	struct drxk_config config;
+
+	memset(&config, 0, sizeof(config));
+	config.microcode_name = "drxk_a3.mc";
+	config.qam_demod_parameter_count = 4;
+	config.adr = 0x29 + (chan->number ^ 2);
+
+	chan->fe = dvb_attach(drxk_attach, &config, i2c);
+	if (!chan->fe) {
+		printk(KERN_ERR "No DRXK found!\n");
+		return -ENODEV;
+	}
+	chan->fe->sec_priv = chan;
+	chan->gate_ctrl = chan->fe->ops.i2c_gate_ctrl;
+	chan->fe->ops.i2c_gate_ctrl = drxk_gate_ctrl;
+	return 0;
+}
+
+static int cineS2_probe(struct ngene_channel *chan)
+{
+	struct i2c_adapter *i2c;
+	struct stv090x_config *fe_conf;
+	u8 buf[3];
+	struct i2c_msg i2c_msg = { .flags = 0, .buf = buf };
+	int rc;
+
+	/* tuner 1+2: i2c adapter #0, tuner 3+4: i2c adapter #1 */
+	if (chan->number < 2)
+		i2c = &chan->dev->channel[0].i2c_adapter;
+	else
+		i2c = &chan->dev->channel[1].i2c_adapter;
+
+	if (port_has_stv0900(i2c, chan->number)) {
+		chan->demod_type = 0;
+		fe_conf = chan->dev->card_info->fe_config[chan->number];
+		/* demod found, attach it */
+		rc = demod_attach_stv0900(chan);
+		if (rc < 0 || chan->number < 2)
+			return rc;
+
+		/* demod #2: reprogram outputs DPN1 & DPN2 */
+		i2c_msg.addr = fe_conf->address;
+		i2c_msg.len = 3;
+		buf[0] = 0xf1;
+		switch (chan->number) {
+		case 2:
+			buf[1] = 0x5c;
+			buf[2] = 0xc2;
+			break;
+		case 3:
+			buf[1] = 0x61;
+			buf[2] = 0xcc;
+			break;
+		default:
+			return -ENODEV;
+		}
+		rc = i2c_transfer(i2c, &i2c_msg, 1);
+		if (rc != 1) {
+			printk(KERN_ERR DEVICE_NAME ": could not setup DPNx\n");
+			return -EIO;
+		}
+	} else if (port_has_drxk(i2c, chan->number^2)) {
+		chan->demod_type = 1;
+		demod_attach_drxk(chan, i2c);
+	} else {
+		printk(KERN_ERR "No demod found on chan %d\n", chan->number);
+		return -ENODEV;
+	}
+	return 0;
+}
+
+
+static struct lgdt330x_config aver_m780 = {
+	.demod_address = 0xb2 >> 1,
+	.demod_chip    = LGDT3303,
+	.serial_mpeg   = 0x00, /* PARALLEL */
+	.clock_polarity_flip = 1,
+};
+
+static struct mt2131_config m780_tunerconfig = {
+	0xc0 >> 1
+};
+
+/* A single func to attach the demo and tuner, rather than
+ * use two sep funcs like the current design mandates.
+ */
+static int demod_attach_lg330x(struct ngene_channel *chan)
+{
+	chan->fe = dvb_attach(lgdt330x_attach, &aver_m780, &chan->i2c_adapter);
+	if (chan->fe == NULL) {
+		printk(KERN_ERR	DEVICE_NAME ": No LGDT330x found!\n");
+		return -ENODEV;
+	}
+
+	dvb_attach(mt2131_attach, chan->fe, &chan->i2c_adapter,
+		   &m780_tunerconfig, 0);
+
+	return (chan->fe) ? 0 : -ENODEV;
+}
+
+static int demod_attach_drxd(struct ngene_channel *chan)
+{
+	struct drxd_config *feconf;
+
+	feconf = chan->dev->card_info->fe_config[chan->number];
+
+	chan->fe = dvb_attach(drxd_attach, feconf, chan,
+			&chan->i2c_adapter, &chan->dev->pci_dev->dev);
+	if (!chan->fe) {
+		pr_err("No DRXD found!\n");
+		return -ENODEV;
+	}
+
+	if (!dvb_attach(dvb_pll_attach, chan->fe, feconf->pll_address,
+			&chan->i2c_adapter,
+			feconf->pll_type)) {
+		pr_err("No pll(%d) found!\n", feconf->pll_type);
+		return -ENODEV;
+	}
+	return 0;
+}
+
+/****************************************************************************/
+/* EEPROM TAGS **************************************************************/
+/****************************************************************************/
+
+#define MICNG_EE_START      0x0100
+#define MICNG_EE_END        0x0FF0
+
+#define MICNG_EETAG_END0    0x0000
+#define MICNG_EETAG_END1    0xFFFF
+
+/* 0x0001 - 0x000F reserved for housekeeping */
+/* 0xFFFF - 0xFFFE reserved for housekeeping */
+
+/* Micronas assigned tags
+   EEProm tags for hardware support */
+
+#define MICNG_EETAG_DRXD1_OSCDEVIATION  0x1000  /* 2 Bytes data */
+#define MICNG_EETAG_DRXD2_OSCDEVIATION  0x1001  /* 2 Bytes data */
+
+#define MICNG_EETAG_MT2060_1_1STIF      0x1100  /* 2 Bytes data */
+#define MICNG_EETAG_MT2060_2_1STIF      0x1101  /* 2 Bytes data */
+
+/* Tag range for OEMs */
+
+#define MICNG_EETAG_OEM_FIRST  0xC000
+#define MICNG_EETAG_OEM_LAST   0xFFEF
+
+static int i2c_write_eeprom(struct i2c_adapter *adapter,
+			    u8 adr, u16 reg, u8 data)
+{
+	u8 m[3] = {(reg >> 8), (reg & 0xff), data};
+	struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = m,
+			      .len = sizeof(m)};
+
+	if (i2c_transfer(adapter, &msg, 1) != 1) {
+		pr_err(DEVICE_NAME ": Error writing EEPROM!\n");
+		return -EIO;
+	}
+	return 0;
+}
+
+static int i2c_read_eeprom(struct i2c_adapter *adapter,
+			   u8 adr, u16 reg, u8 *data, int len)
+{
+	u8 msg[2] = {(reg >> 8), (reg & 0xff)};
+	struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0,
+				   .buf = msg, .len = 2 },
+				  {.addr = adr, .flags = I2C_M_RD,
+				   .buf = data, .len = len} };
+
+	if (i2c_transfer(adapter, msgs, 2) != 2) {
+		pr_err(DEVICE_NAME ": Error reading EEPROM\n");
+		return -EIO;
+	}
+	return 0;
+}
+
+static int ReadEEProm(struct i2c_adapter *adapter,
+		      u16 Tag, u32 MaxLen, u8 *data, u32 *pLength)
+{
+	int status = 0;
+	u16 Addr = MICNG_EE_START, Length, tag = 0;
+	u8  EETag[3];
+
+	while (Addr + sizeof(u16) + 1 < MICNG_EE_END) {
+		if (i2c_read_eeprom(adapter, 0x50, Addr, EETag, sizeof(EETag)))
+			return -1;
+		tag = (EETag[0] << 8) | EETag[1];
+		if (tag == MICNG_EETAG_END0 || tag == MICNG_EETAG_END1)
+			return -1;
+		if (tag == Tag)
+			break;
+		Addr += sizeof(u16) + 1 + EETag[2];
+	}
+	if (Addr + sizeof(u16) + 1 + EETag[2] > MICNG_EE_END) {
+		pr_err(DEVICE_NAME
+		       ": Reached EOEE @ Tag = %04x Length = %3d\n",
+		       tag, EETag[2]);
+		return -1;
+	}
+	Length = EETag[2];
+	if (Length > MaxLen)
+		Length = (u16) MaxLen;
+	if (Length > 0) {
+		Addr += sizeof(u16) + 1;
+		status = i2c_read_eeprom(adapter, 0x50, Addr, data, Length);
+		if (!status) {
+			*pLength = EETag[2];
+			if (Length < EETag[2])
+				; /*status=STATUS_BUFFER_OVERFLOW; */
+		}
+	}
+	return status;
+}
+
+static int WriteEEProm(struct i2c_adapter *adapter,
+		       u16 Tag, u32 Length, u8 *data)
+{
+	int status = 0;
+	u16 Addr = MICNG_EE_START;
+	u8 EETag[3];
+	u16 tag = 0;
+	int retry, i;
+
+	while (Addr + sizeof(u16) + 1 < MICNG_EE_END) {
+		if (i2c_read_eeprom(adapter, 0x50, Addr, EETag, sizeof(EETag)))
+			return -1;
+		tag = (EETag[0] << 8) | EETag[1];
+		if (tag == MICNG_EETAG_END0 || tag == MICNG_EETAG_END1)
+			return -1;
+		if (tag == Tag)
+			break;
+		Addr += sizeof(u16) + 1 + EETag[2];
+	}
+	if (Addr + sizeof(u16) + 1 + EETag[2] > MICNG_EE_END) {
+		pr_err(DEVICE_NAME
+		       ": Reached EOEE @ Tag = %04x Length = %3d\n",
+		       tag, EETag[2]);
+		return -1;
+	}
+
+	if (Length > EETag[2])
+		return -EINVAL;
+	/* Note: We write the data one byte at a time to avoid
+	   issues with page sizes. (which are different for
+	   each manufacture and eeprom size)
+	 */
+	Addr += sizeof(u16) + 1;
+	for (i = 0; i < Length; i++, Addr++) {
+		status = i2c_write_eeprom(adapter, 0x50, Addr, data[i]);
+
+		if (status)
+			break;
+
+		/* Poll for finishing write cycle */
+		retry = 10;
+		while (retry) {
+			u8 Tmp;
+
+			msleep(50);
+			status = i2c_read_eeprom(adapter, 0x50, Addr, &Tmp, 1);
+			if (status)
+				break;
+			if (Tmp != data[i])
+				pr_err(DEVICE_NAME
+				       "eeprom write error\n");
+			retry -= 1;
+		}
+		if (status) {
+			pr_err(DEVICE_NAME
+			       ": Timeout polling eeprom\n");
+			break;
+		}
+	}
+	return status;
+}
+
+static int eeprom_read_ushort(struct i2c_adapter *adapter, u16 tag, u16 *data)
+{
+	int stat;
+	u8 buf[2];
+	u32 len = 0;
+
+	stat = ReadEEProm(adapter, tag, 2, buf, &len);
+	if (stat)
+		return stat;
+	if (len != 2)
+		return -EINVAL;
+
+	*data = (buf[0] << 8) | buf[1];
+	return 0;
+}
+
+static int eeprom_write_ushort(struct i2c_adapter *adapter, u16 tag, u16 data)
+{
+	int stat;
+	u8 buf[2];
+
+	buf[0] = data >> 8;
+	buf[1] = data & 0xff;
+	stat = WriteEEProm(adapter, tag, 2, buf);
+	if (stat)
+		return stat;
+	return 0;
+}
+
+static s16 osc_deviation(void *priv, s16 deviation, int flag)
+{
+	struct ngene_channel *chan = priv;
+	struct i2c_adapter *adap = &chan->i2c_adapter;
+	u16 data = 0;
+
+	if (flag) {
+		data = (u16) deviation;
+		pr_info(DEVICE_NAME ": write deviation %d\n",
+		       deviation);
+		eeprom_write_ushort(adap, 0x1000 + chan->number, data);
+	} else {
+		if (eeprom_read_ushort(adap, 0x1000 + chan->number, &data))
+			data = 0;
+		pr_info(DEVICE_NAME ": read deviation %d\n",
+		       (s16) data);
+	}
+
+	return (s16) data;
+}
+
+/****************************************************************************/
+/* Switch control (I2C gates, etc.) *****************************************/
+/****************************************************************************/
+
+
+static struct stv090x_config fe_cineS2 = {
+	.device         = STV0900,
+	.demod_mode     = STV090x_DUAL,
+	.clk_mode       = STV090x_CLK_EXT,
+
+	.xtal           = 27000000,
+	.address        = 0x68,
+
+	.ts1_mode       = STV090x_TSMODE_SERIAL_PUNCTURED,
+	.ts2_mode       = STV090x_TSMODE_SERIAL_PUNCTURED,
+
+	.repeater_level = STV090x_RPTLEVEL_16,
+
+	.adc1_range	= STV090x_ADC_1Vpp,
+	.adc2_range	= STV090x_ADC_1Vpp,
+
+	.diseqc_envelope_mode = true,
+
+	.tuner_i2c_lock = cineS2_tuner_i2c_lock,
+};
+
+static struct stv090x_config fe_cineS2_2 = {
+	.device         = STV0900,
+	.demod_mode     = STV090x_DUAL,
+	.clk_mode       = STV090x_CLK_EXT,
+
+	.xtal           = 27000000,
+	.address        = 0x69,
+
+	.ts1_mode       = STV090x_TSMODE_SERIAL_PUNCTURED,
+	.ts2_mode       = STV090x_TSMODE_SERIAL_PUNCTURED,
+
+	.repeater_level = STV090x_RPTLEVEL_16,
+
+	.adc1_range	= STV090x_ADC_1Vpp,
+	.adc2_range	= STV090x_ADC_1Vpp,
+
+	.diseqc_envelope_mode = true,
+
+	.tuner_i2c_lock = cineS2_tuner_i2c_lock,
+};
+
+static struct stv6110x_config tuner_cineS2_0 = {
+	.addr	= 0x60,
+	.refclk	= 27000000,
+	.clk_div = 1,
+};
+
+static struct stv6110x_config tuner_cineS2_1 = {
+	.addr	= 0x63,
+	.refclk	= 27000000,
+	.clk_div = 1,
+};
+
+static struct ngene_info ngene_info_cineS2 = {
+	.type		= NGENE_SIDEWINDER,
+	.name		= "Linux4Media cineS2 DVB-S2 Twin Tuner",
+	.io_type	= {NGENE_IO_TSIN, NGENE_IO_TSIN},
+	.demod_attach	= {demod_attach_stv0900, demod_attach_stv0900},
+	.tuner_attach	= {tuner_attach_stv6110, tuner_attach_stv6110},
+	.fe_config	= {&fe_cineS2, &fe_cineS2},
+	.tuner_config	= {&tuner_cineS2_0, &tuner_cineS2_1},
+	.lnb		= {0x0b, 0x08},
+	.tsf		= {3, 3},
+	.fw_version	= 18,
+	.msi_supported	= true,
+};
+
+static struct ngene_info ngene_info_satixS2 = {
+	.type		= NGENE_SIDEWINDER,
+	.name		= "Mystique SaTiX-S2 Dual",
+	.io_type	= {NGENE_IO_TSIN, NGENE_IO_TSIN},
+	.demod_attach	= {demod_attach_stv0900, demod_attach_stv0900},
+	.tuner_attach	= {tuner_attach_stv6110, tuner_attach_stv6110},
+	.fe_config	= {&fe_cineS2, &fe_cineS2},
+	.tuner_config	= {&tuner_cineS2_0, &tuner_cineS2_1},
+	.lnb		= {0x0b, 0x08},
+	.tsf		= {3, 3},
+	.fw_version	= 18,
+	.msi_supported	= true,
+};
+
+static struct ngene_info ngene_info_satixS2v2 = {
+	.type		= NGENE_SIDEWINDER,
+	.name		= "Mystique SaTiX-S2 Dual (v2)",
+	.io_type	= {NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN,
+			   NGENE_IO_TSOUT},
+	.demod_attach	= {demod_attach_stv0900, demod_attach_stv0900, cineS2_probe, cineS2_probe},
+	.tuner_attach	= {tuner_attach_stv6110, tuner_attach_stv6110, tuner_attach_probe, tuner_attach_probe},
+	.fe_config	= {&fe_cineS2, &fe_cineS2, &fe_cineS2_2, &fe_cineS2_2},
+	.tuner_config	= {&tuner_cineS2_0, &tuner_cineS2_1, &tuner_cineS2_0, &tuner_cineS2_1},
+	.lnb		= {0x0a, 0x08, 0x0b, 0x09},
+	.tsf		= {3, 3},
+	.fw_version	= 18,
+	.msi_supported	= true,
+};
+
+static struct ngene_info ngene_info_cineS2v5 = {
+	.type		= NGENE_SIDEWINDER,
+	.name		= "Linux4Media cineS2 DVB-S2 Twin Tuner (v5)",
+	.io_type	= {NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN,
+			   NGENE_IO_TSOUT},
+	.demod_attach	= {demod_attach_stv0900, demod_attach_stv0900, cineS2_probe, cineS2_probe},
+	.tuner_attach	= {tuner_attach_stv6110, tuner_attach_stv6110, tuner_attach_probe, tuner_attach_probe},
+	.fe_config	= {&fe_cineS2, &fe_cineS2, &fe_cineS2_2, &fe_cineS2_2},
+	.tuner_config	= {&tuner_cineS2_0, &tuner_cineS2_1, &tuner_cineS2_0, &tuner_cineS2_1},
+	.lnb		= {0x0a, 0x08, 0x0b, 0x09},
+	.tsf		= {3, 3},
+	.fw_version	= 18,
+	.msi_supported	= true,
+};
+
+
+static struct ngene_info ngene_info_duoFlex = {
+	.type           = NGENE_SIDEWINDER,
+	.name           = "Digital Devices DuoFlex PCIe or miniPCIe",
+	.io_type        = {NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN,
+			   NGENE_IO_TSOUT},
+	.demod_attach   = {cineS2_probe, cineS2_probe, cineS2_probe, cineS2_probe},
+	.tuner_attach   = {tuner_attach_probe, tuner_attach_probe, tuner_attach_probe, tuner_attach_probe},
+	.fe_config      = {&fe_cineS2, &fe_cineS2, &fe_cineS2_2, &fe_cineS2_2},
+	.tuner_config   = {&tuner_cineS2_0, &tuner_cineS2_1, &tuner_cineS2_0, &tuner_cineS2_1},
+	.lnb            = {0x0a, 0x08, 0x0b, 0x09},
+	.tsf            = {3, 3},
+	.fw_version     = 18,
+	.msi_supported	= true,
+};
+
+static struct ngene_info ngene_info_m780 = {
+	.type           = NGENE_APP,
+	.name           = "Aver M780 ATSC/QAM-B",
+
+	/* Channel 0 is analog, which is currently unsupported */
+	.io_type        = { NGENE_IO_NONE, NGENE_IO_TSIN },
+	.demod_attach   = { NULL, demod_attach_lg330x },
+
+	/* Ensure these are NULL else the frame will call them (as funcs) */
+	.tuner_attach   = { 0, 0, 0, 0 },
+	.fe_config      = { NULL, &aver_m780 },
+	.avf            = { 0 },
+
+	/* A custom electrical interface config for the demod to bridge */
+	.tsf		= { 4, 4 },
+	.fw_version	= 15,
+};
+
+static struct drxd_config fe_terratec_dvbt_0 = {
+	.index          = 0,
+	.demod_address  = 0x70,
+	.demod_revision = 0xa2,
+	.demoda_address = 0x00,
+	.pll_address    = 0x60,
+	.pll_type       = DVB_PLL_THOMSON_DTT7520X,
+	.clock          = 20000,
+	.osc_deviation  = osc_deviation,
+};
+
+static struct drxd_config fe_terratec_dvbt_1 = {
+	.index          = 1,
+	.demod_address  = 0x71,
+	.demod_revision = 0xa2,
+	.demoda_address = 0x00,
+	.pll_address    = 0x60,
+	.pll_type       = DVB_PLL_THOMSON_DTT7520X,
+	.clock          = 20000,
+	.osc_deviation  = osc_deviation,
+};
+
+static struct ngene_info ngene_info_terratec = {
+	.type           = NGENE_TERRATEC,
+	.name           = "Terratec Integra/Cinergy2400i Dual DVB-T",
+	.io_type        = {NGENE_IO_TSIN, NGENE_IO_TSIN},
+	.demod_attach   = {demod_attach_drxd, demod_attach_drxd},
+	.fe_config      = {&fe_terratec_dvbt_0, &fe_terratec_dvbt_1},
+	.i2c_access     = 1,
+};
+
+/****************************************************************************/
+
+
+
+/****************************************************************************/
+/* PCI Subsystem ID *********************************************************/
+/****************************************************************************/
+
+#define NGENE_ID(_subvend, _subdev, _driverdata) { \
+	.vendor = NGENE_VID, .device = NGENE_PID, \
+	.subvendor = _subvend, .subdevice = _subdev, \
+	.driver_data = (unsigned long) &_driverdata }
+
+/****************************************************************************/
+
+static const struct pci_device_id ngene_id_tbl[] __devinitdata = {
+	NGENE_ID(0x18c3, 0xabc3, ngene_info_cineS2),
+	NGENE_ID(0x18c3, 0xabc4, ngene_info_cineS2),
+	NGENE_ID(0x18c3, 0xdb01, ngene_info_satixS2),
+	NGENE_ID(0x18c3, 0xdb02, ngene_info_satixS2v2),
+	NGENE_ID(0x18c3, 0xdd00, ngene_info_cineS2v5),
+	NGENE_ID(0x18c3, 0xdd10, ngene_info_duoFlex),
+	NGENE_ID(0x18c3, 0xdd20, ngene_info_duoFlex),
+	NGENE_ID(0x1461, 0x062e, ngene_info_m780),
+	NGENE_ID(0x153b, 0x1167, ngene_info_terratec),
+	{0}
+};
+MODULE_DEVICE_TABLE(pci, ngene_id_tbl);
+
+/****************************************************************************/
+/* Init/Exit ****************************************************************/
+/****************************************************************************/
+
+static pci_ers_result_t ngene_error_detected(struct pci_dev *dev,
+					     enum pci_channel_state state)
+{
+	printk(KERN_ERR DEVICE_NAME ": PCI error\n");
+	if (state == pci_channel_io_perm_failure)
+		return PCI_ERS_RESULT_DISCONNECT;
+	if (state == pci_channel_io_frozen)
+		return PCI_ERS_RESULT_NEED_RESET;
+	return PCI_ERS_RESULT_CAN_RECOVER;
+}
+
+static pci_ers_result_t ngene_link_reset(struct pci_dev *dev)
+{
+	printk(KERN_INFO DEVICE_NAME ": link reset\n");
+	return 0;
+}
+
+static pci_ers_result_t ngene_slot_reset(struct pci_dev *dev)
+{
+	printk(KERN_INFO DEVICE_NAME ": slot reset\n");
+	return 0;
+}
+
+static void ngene_resume(struct pci_dev *dev)
+{
+	printk(KERN_INFO DEVICE_NAME ": resume\n");
+}
+
+static const struct pci_error_handlers ngene_errors = {
+	.error_detected = ngene_error_detected,
+	.link_reset = ngene_link_reset,
+	.slot_reset = ngene_slot_reset,
+	.resume = ngene_resume,
+};
+
+static struct pci_driver ngene_pci_driver = {
+	.name        = "ngene",
+	.id_table    = ngene_id_tbl,
+	.probe       = ngene_probe,
+	.remove      = __devexit_p(ngene_remove),
+	.err_handler = &ngene_errors,
+	.shutdown    = ngene_shutdown,
+};
+
+static __init int module_init_ngene(void)
+{
+	printk(KERN_INFO
+	       "nGene PCIE bridge driver, Copyright (C) 2005-2007 Micronas\n");
+	return pci_register_driver(&ngene_pci_driver);
+}
+
+static __exit void module_exit_ngene(void)
+{
+	pci_unregister_driver(&ngene_pci_driver);
+}
+
+module_init(module_init_ngene);
+module_exit(module_exit_ngene);
+
+MODULE_DESCRIPTION("nGene");
+MODULE_AUTHOR("Micronas, Ralph Metzler, Manfred Voelkel");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/pci/ngene/ngene-core.c b/drivers/media/pci/ngene/ngene-core.c
new file mode 100644
index 0000000..c8e0d5b
--- /dev/null
+++ b/drivers/media/pci/ngene/ngene-core.c
@@ -0,0 +1,1707 @@
+/*
+ * ngene.c: nGene PCIe bridge driver
+ *
+ * Copyright (C) 2005-2007 Micronas
+ *
+ * Copyright (C) 2008-2009 Ralph Metzler <rjkm@metzlerbros.de>
+ *                         Modifications for new nGene firmware,
+ *                         support for EEPROM-copying,
+ *                         support for new dual DVB-S2 card prototype
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 only, as published by the Free Software Foundation.
+ *
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/poll.h>
+#include <linux/io.h>
+#include <asm/div64.h>
+#include <linux/pci.h>
+#include <linux/timer.h>
+#include <linux/byteorder/generic.h>
+#include <linux/firmware.h>
+#include <linux/vmalloc.h>
+
+#include "ngene.h"
+
+static int one_adapter;
+module_param(one_adapter, int, 0444);
+MODULE_PARM_DESC(one_adapter, "Use only one adapter.");
+
+static int shutdown_workaround;
+module_param(shutdown_workaround, int, 0644);
+MODULE_PARM_DESC(shutdown_workaround, "Activate workaround for shutdown problem with some chipsets.");
+
+static int debug;
+module_param(debug, int, 0444);
+MODULE_PARM_DESC(debug, "Print debugging information.");
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+#define dprintk	if (debug) printk
+
+#define ngwriteb(dat, adr)         writeb((dat), (char *)(dev->iomem + (adr)))
+#define ngwritel(dat, adr)         writel((dat), (char *)(dev->iomem + (adr)))
+#define ngwriteb(dat, adr)         writeb((dat), (char *)(dev->iomem + (adr)))
+#define ngreadl(adr)               readl(dev->iomem + (adr))
+#define ngreadb(adr)               readb(dev->iomem + (adr))
+#define ngcpyto(adr, src, count)   memcpy_toio((char *) \
+				   (dev->iomem + (adr)), (src), (count))
+#define ngcpyfrom(dst, adr, count) memcpy_fromio((dst), (char *) \
+				   (dev->iomem + (adr)), (count))
+
+/****************************************************************************/
+/* nGene interrupt handler **************************************************/
+/****************************************************************************/
+
+static void event_tasklet(unsigned long data)
+{
+	struct ngene *dev = (struct ngene *)data;
+
+	while (dev->EventQueueReadIndex != dev->EventQueueWriteIndex) {
+		struct EVENT_BUFFER Event =
+			dev->EventQueue[dev->EventQueueReadIndex];
+		dev->EventQueueReadIndex =
+			(dev->EventQueueReadIndex + 1) & (EVENT_QUEUE_SIZE - 1);
+
+		if ((Event.UARTStatus & 0x01) && (dev->TxEventNotify))
+			dev->TxEventNotify(dev, Event.TimeStamp);
+		if ((Event.UARTStatus & 0x02) && (dev->RxEventNotify))
+			dev->RxEventNotify(dev, Event.TimeStamp,
+					   Event.RXCharacter);
+	}
+}
+
+static void demux_tasklet(unsigned long data)
+{
+	struct ngene_channel *chan = (struct ngene_channel *)data;
+	struct SBufferHeader *Cur = chan->nextBuffer;
+
+	spin_lock_irq(&chan->state_lock);
+
+	while (Cur->ngeneBuffer.SR.Flags & 0x80) {
+		if (chan->mode & NGENE_IO_TSOUT) {
+			u32 Flags = chan->DataFormatFlags;
+			if (Cur->ngeneBuffer.SR.Flags & 0x20)
+				Flags |= BEF_OVERFLOW;
+			if (chan->pBufferExchange) {
+				if (!chan->pBufferExchange(chan,
+							   Cur->Buffer1,
+							   chan->Capture1Length,
+							   Cur->ngeneBuffer.SR.
+							   Clock, Flags)) {
+					/*
+					   We didn't get data
+					   Clear in service flag to make sure we
+					   get called on next interrupt again.
+					   leave fill/empty (0x80) flag alone
+					   to avoid hardware running out of
+					   buffers during startup, we hold only
+					   in run state ( the source may be late
+					   delivering data )
+					*/
+
+					if (chan->HWState == HWSTATE_RUN) {
+						Cur->ngeneBuffer.SR.Flags &=
+							~0x40;
+						break;
+						/* Stop processing stream */
+					}
+				} else {
+					/* We got a valid buffer,
+					   so switch to run state */
+					chan->HWState = HWSTATE_RUN;
+				}
+			} else {
+				printk(KERN_ERR DEVICE_NAME ": OOPS\n");
+				if (chan->HWState == HWSTATE_RUN) {
+					Cur->ngeneBuffer.SR.Flags &= ~0x40;
+					break;	/* Stop processing stream */
+				}
+			}
+			if (chan->AudioDTOUpdated) {
+				printk(KERN_INFO DEVICE_NAME
+				       ": Update AudioDTO = %d\n",
+				       chan->AudioDTOValue);
+				Cur->ngeneBuffer.SR.DTOUpdate =
+					chan->AudioDTOValue;
+				chan->AudioDTOUpdated = 0;
+			}
+		} else {
+			if (chan->HWState == HWSTATE_RUN) {
+				u32 Flags = chan->DataFormatFlags;
+				IBufferExchange *exch1 = chan->pBufferExchange;
+				IBufferExchange *exch2 = chan->pBufferExchange2;
+				if (Cur->ngeneBuffer.SR.Flags & 0x01)
+					Flags |= BEF_EVEN_FIELD;
+				if (Cur->ngeneBuffer.SR.Flags & 0x20)
+					Flags |= BEF_OVERFLOW;
+				spin_unlock_irq(&chan->state_lock);
+				if (exch1)
+					exch1(chan, Cur->Buffer1,
+						chan->Capture1Length,
+						Cur->ngeneBuffer.SR.Clock,
+						Flags);
+				if (exch2)
+					exch2(chan, Cur->Buffer2,
+						chan->Capture2Length,
+						Cur->ngeneBuffer.SR.Clock,
+						Flags);
+				spin_lock_irq(&chan->state_lock);
+			} else if (chan->HWState != HWSTATE_STOP)
+				chan->HWState = HWSTATE_RUN;
+		}
+		Cur->ngeneBuffer.SR.Flags = 0x00;
+		Cur = Cur->Next;
+	}
+	chan->nextBuffer = Cur;
+
+	spin_unlock_irq(&chan->state_lock);
+}
+
+static irqreturn_t irq_handler(int irq, void *dev_id)
+{
+	struct ngene *dev = (struct ngene *)dev_id;
+	u32 icounts = 0;
+	irqreturn_t rc = IRQ_NONE;
+	u32 i = MAX_STREAM;
+	u8 *tmpCmdDoneByte;
+
+	if (dev->BootFirmware) {
+		icounts = ngreadl(NGENE_INT_COUNTS);
+		if (icounts != dev->icounts) {
+			ngwritel(0, FORCE_NMI);
+			dev->cmd_done = 1;
+			wake_up(&dev->cmd_wq);
+			dev->icounts = icounts;
+			rc = IRQ_HANDLED;
+		}
+		return rc;
+	}
+
+	ngwritel(0, FORCE_NMI);
+
+	spin_lock(&dev->cmd_lock);
+	tmpCmdDoneByte = dev->CmdDoneByte;
+	if (tmpCmdDoneByte &&
+	    (*tmpCmdDoneByte ||
+	    (dev->ngenetohost[0] == 1 && dev->ngenetohost[1] != 0))) {
+		dev->CmdDoneByte = NULL;
+		dev->cmd_done = 1;
+		wake_up(&dev->cmd_wq);
+		rc = IRQ_HANDLED;
+	}
+	spin_unlock(&dev->cmd_lock);
+
+	if (dev->EventBuffer->EventStatus & 0x80) {
+		u8 nextWriteIndex =
+			(dev->EventQueueWriteIndex + 1) &
+			(EVENT_QUEUE_SIZE - 1);
+		if (nextWriteIndex != dev->EventQueueReadIndex) {
+			dev->EventQueue[dev->EventQueueWriteIndex] =
+				*(dev->EventBuffer);
+			dev->EventQueueWriteIndex = nextWriteIndex;
+		} else {
+			printk(KERN_ERR DEVICE_NAME ": event overflow\n");
+			dev->EventQueueOverflowCount += 1;
+			dev->EventQueueOverflowFlag = 1;
+		}
+		dev->EventBuffer->EventStatus &= ~0x80;
+		tasklet_schedule(&dev->event_tasklet);
+		rc = IRQ_HANDLED;
+	}
+
+	while (i > 0) {
+		i--;
+		spin_lock(&dev->channel[i].state_lock);
+		/* if (dev->channel[i].State>=KSSTATE_RUN) { */
+		if (dev->channel[i].nextBuffer) {
+			if ((dev->channel[i].nextBuffer->
+			     ngeneBuffer.SR.Flags & 0xC0) == 0x80) {
+				dev->channel[i].nextBuffer->
+					ngeneBuffer.SR.Flags |= 0x40;
+				tasklet_schedule(
+					&dev->channel[i].demux_tasklet);
+				rc = IRQ_HANDLED;
+			}
+		}
+		spin_unlock(&dev->channel[i].state_lock);
+	}
+
+	/* Request might have been processed by a previous call. */
+	return IRQ_HANDLED;
+}
+
+/****************************************************************************/
+/* nGene command interface **************************************************/
+/****************************************************************************/
+
+static void dump_command_io(struct ngene *dev)
+{
+	u8 buf[8], *b;
+
+	ngcpyfrom(buf, HOST_TO_NGENE, 8);
+	printk(KERN_ERR "host_to_ngene (%04x): %*ph\n", HOST_TO_NGENE, 8, buf);
+
+	ngcpyfrom(buf, NGENE_TO_HOST, 8);
+	printk(KERN_ERR "ngene_to_host (%04x): %*ph\n", NGENE_TO_HOST, 8, buf);
+
+	b = dev->hosttongene;
+	printk(KERN_ERR "dev->hosttongene (%p): %*ph\n", b, 8, b);
+
+	b = dev->ngenetohost;
+	printk(KERN_ERR "dev->ngenetohost (%p): %*ph\n", b, 8, b);
+}
+
+static int ngene_command_mutex(struct ngene *dev, struct ngene_command *com)
+{
+	int ret;
+	u8 *tmpCmdDoneByte;
+
+	dev->cmd_done = 0;
+
+	if (com->cmd.hdr.Opcode == CMD_FWLOAD_PREPARE) {
+		dev->BootFirmware = 1;
+		dev->icounts = ngreadl(NGENE_INT_COUNTS);
+		ngwritel(0, NGENE_COMMAND);
+		ngwritel(0, NGENE_COMMAND_HI);
+		ngwritel(0, NGENE_STATUS);
+		ngwritel(0, NGENE_STATUS_HI);
+		ngwritel(0, NGENE_EVENT);
+		ngwritel(0, NGENE_EVENT_HI);
+	} else if (com->cmd.hdr.Opcode == CMD_FWLOAD_FINISH) {
+		u64 fwio = dev->PAFWInterfaceBuffer;
+
+		ngwritel(fwio & 0xffffffff, NGENE_COMMAND);
+		ngwritel(fwio >> 32, NGENE_COMMAND_HI);
+		ngwritel((fwio + 256) & 0xffffffff, NGENE_STATUS);
+		ngwritel((fwio + 256) >> 32, NGENE_STATUS_HI);
+		ngwritel((fwio + 512) & 0xffffffff, NGENE_EVENT);
+		ngwritel((fwio + 512) >> 32, NGENE_EVENT_HI);
+	}
+
+	memcpy(dev->FWInterfaceBuffer, com->cmd.raw8, com->in_len + 2);
+
+	if (dev->BootFirmware)
+		ngcpyto(HOST_TO_NGENE, com->cmd.raw8, com->in_len + 2);
+
+	spin_lock_irq(&dev->cmd_lock);
+	tmpCmdDoneByte = dev->ngenetohost + com->out_len;
+	if (!com->out_len)
+		tmpCmdDoneByte++;
+	*tmpCmdDoneByte = 0;
+	dev->ngenetohost[0] = 0;
+	dev->ngenetohost[1] = 0;
+	dev->CmdDoneByte = tmpCmdDoneByte;
+	spin_unlock_irq(&dev->cmd_lock);
+
+	/* Notify 8051. */
+	ngwritel(1, FORCE_INT);
+
+	ret = wait_event_timeout(dev->cmd_wq, dev->cmd_done == 1, 2 * HZ);
+	if (!ret) {
+		/*ngwritel(0, FORCE_NMI);*/
+
+		printk(KERN_ERR DEVICE_NAME
+		       ": Command timeout cmd=%02x prev=%02x\n",
+		       com->cmd.hdr.Opcode, dev->prev_cmd);
+		dump_command_io(dev);
+		return -1;
+	}
+	if (com->cmd.hdr.Opcode == CMD_FWLOAD_FINISH)
+		dev->BootFirmware = 0;
+
+	dev->prev_cmd = com->cmd.hdr.Opcode;
+
+	if (!com->out_len)
+		return 0;
+
+	memcpy(com->cmd.raw8, dev->ngenetohost, com->out_len);
+
+	return 0;
+}
+
+int ngene_command(struct ngene *dev, struct ngene_command *com)
+{
+	int result;
+
+	down(&dev->cmd_mutex);
+	result = ngene_command_mutex(dev, com);
+	up(&dev->cmd_mutex);
+	return result;
+}
+
+
+static int ngene_command_load_firmware(struct ngene *dev,
+				       u8 *ngene_fw, u32 size)
+{
+#define FIRSTCHUNK (1024)
+	u32 cleft;
+	struct ngene_command com;
+
+	com.cmd.hdr.Opcode = CMD_FWLOAD_PREPARE;
+	com.cmd.hdr.Length = 0;
+	com.in_len = 0;
+	com.out_len = 0;
+
+	ngene_command(dev, &com);
+
+	cleft = (size + 3) & ~3;
+	if (cleft > FIRSTCHUNK) {
+		ngcpyto(PROGRAM_SRAM + FIRSTCHUNK, ngene_fw + FIRSTCHUNK,
+			cleft - FIRSTCHUNK);
+		cleft = FIRSTCHUNK;
+	}
+	ngcpyto(DATA_FIFO_AREA, ngene_fw, cleft);
+
+	memset(&com, 0, sizeof(struct ngene_command));
+	com.cmd.hdr.Opcode = CMD_FWLOAD_FINISH;
+	com.cmd.hdr.Length = 4;
+	com.cmd.FWLoadFinish.Address = DATA_FIFO_AREA;
+	com.cmd.FWLoadFinish.Length = (unsigned short)cleft;
+	com.in_len = 4;
+	com.out_len = 0;
+
+	return ngene_command(dev, &com);
+}
+
+
+static int ngene_command_config_buf(struct ngene *dev, u8 config)
+{
+	struct ngene_command com;
+
+	com.cmd.hdr.Opcode = CMD_CONFIGURE_BUFFER;
+	com.cmd.hdr.Length = 1;
+	com.cmd.ConfigureBuffers.config = config;
+	com.in_len = 1;
+	com.out_len = 0;
+
+	if (ngene_command(dev, &com) < 0)
+		return -EIO;
+	return 0;
+}
+
+static int ngene_command_config_free_buf(struct ngene *dev, u8 *config)
+{
+	struct ngene_command com;
+
+	com.cmd.hdr.Opcode = CMD_CONFIGURE_FREE_BUFFER;
+	com.cmd.hdr.Length = 6;
+	memcpy(&com.cmd.ConfigureBuffers.config, config, 6);
+	com.in_len = 6;
+	com.out_len = 0;
+
+	if (ngene_command(dev, &com) < 0)
+		return -EIO;
+
+	return 0;
+}
+
+int ngene_command_gpio_set(struct ngene *dev, u8 select, u8 level)
+{
+	struct ngene_command com;
+
+	com.cmd.hdr.Opcode = CMD_SET_GPIO_PIN;
+	com.cmd.hdr.Length = 1;
+	com.cmd.SetGpioPin.select = select | (level << 7);
+	com.in_len = 1;
+	com.out_len = 0;
+
+	return ngene_command(dev, &com);
+}
+
+
+/*
+ 02000640 is sample on rising edge.
+ 02000740 is sample on falling edge.
+ 02000040 is ignore "valid" signal
+
+ 0: FD_CTL1 Bit 7,6 must be 0,1
+    7   disable(fw controlled)
+    6   0-AUX,1-TS
+    5   0-par,1-ser
+    4   0-lsb/1-msb
+    3,2 reserved
+    1,0 0-no sync, 1-use ext. start, 2-use 0x47, 3-both
+ 1: FD_CTL2 has 3-valid must be hi, 2-use valid, 1-edge
+ 2: FD_STA is read-only. 0-sync
+ 3: FD_INSYNC is number of 47s to trigger "in sync".
+ 4: FD_OUTSYNC is number of 47s to trigger "out of sync".
+ 5: FD_MAXBYTE1 is low-order of bytes per packet.
+ 6: FD_MAXBYTE2 is high-order of bytes per packet.
+ 7: Top byte is unused.
+*/
+
+/****************************************************************************/
+
+static u8 TSFeatureDecoderSetup[8 * 5] = {
+	0x42, 0x00, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00,
+	0x40, 0x06, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00,	/* DRXH */
+	0x71, 0x07, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00,	/* DRXHser */
+	0x72, 0x00, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00,	/* S2ser */
+	0x40, 0x07, 0x00, 0x02, 0x02, 0xbc, 0x00, 0x00, /* LGDT3303 */
+};
+
+/* Set NGENE I2S Config to 16 bit packed */
+static u8 I2SConfiguration[] = {
+	0x00, 0x10, 0x00, 0x00,
+	0x80, 0x10, 0x00, 0x00,
+};
+
+static u8 SPDIFConfiguration[10] = {
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+/* Set NGENE I2S Config to transport stream compatible mode */
+
+static u8 TS_I2SConfiguration[4] = { 0x3E, 0x18, 0x00, 0x00 };
+
+static u8 TS_I2SOutConfiguration[4] = { 0x80, 0x04, 0x00, 0x00 };
+
+static u8 ITUDecoderSetup[4][16] = {
+	{0x1c, 0x13, 0x01, 0x68, 0x3d, 0x90, 0x14, 0x20,  /* SDTV */
+	 0x00, 0x00, 0x01, 0xb0, 0x9c, 0x00, 0x00, 0x00},
+	{0x9c, 0x03, 0x23, 0xC0, 0x60, 0x0E, 0x13, 0x00,
+	 0x00, 0x00, 0x00, 0x01, 0xB0, 0x00, 0x00, 0x00},
+	{0x9f, 0x00, 0x23, 0xC0, 0x60, 0x0F, 0x13, 0x00,  /* HDTV 1080i50 */
+	 0x00, 0x00, 0x00, 0x01, 0xB0, 0x00, 0x00, 0x00},
+	{0x9c, 0x01, 0x23, 0xC0, 0x60, 0x0E, 0x13, 0x00,  /* HDTV 1080i60 */
+	 0x00, 0x00, 0x00, 0x01, 0xB0, 0x00, 0x00, 0x00},
+};
+
+/*
+ * 50 48 60 gleich
+ * 27p50 9f 00 22 80 42 69 18 ...
+ * 27p60 93 00 22 80 82 69 1c ...
+ */
+
+/* Maxbyte to 1144 (for raw data) */
+static u8 ITUFeatureDecoderSetup[8] = {
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x04, 0x00
+};
+
+void FillTSBuffer(void *Buffer, int Length, u32 Flags)
+{
+	u32 *ptr = Buffer;
+
+	memset(Buffer, TS_FILLER, Length);
+	while (Length > 0) {
+		if (Flags & DF_SWAP32)
+			*ptr = 0x471FFF10;
+		else
+			*ptr = 0x10FF1F47;
+		ptr += (188 / 4);
+		Length -= 188;
+	}
+}
+
+
+static void flush_buffers(struct ngene_channel *chan)
+{
+	u8 val;
+
+	do {
+		msleep(1);
+		spin_lock_irq(&chan->state_lock);
+		val = chan->nextBuffer->ngeneBuffer.SR.Flags & 0x80;
+		spin_unlock_irq(&chan->state_lock);
+	} while (val);
+}
+
+static void clear_buffers(struct ngene_channel *chan)
+{
+	struct SBufferHeader *Cur = chan->nextBuffer;
+
+	do {
+		memset(&Cur->ngeneBuffer.SR, 0, sizeof(Cur->ngeneBuffer.SR));
+		if (chan->mode & NGENE_IO_TSOUT)
+			FillTSBuffer(Cur->Buffer1,
+				     chan->Capture1Length,
+				     chan->DataFormatFlags);
+		Cur = Cur->Next;
+	} while (Cur != chan->nextBuffer);
+
+	if (chan->mode & NGENE_IO_TSOUT) {
+		chan->nextBuffer->ngeneBuffer.SR.DTOUpdate =
+			chan->AudioDTOValue;
+		chan->AudioDTOUpdated = 0;
+
+		Cur = chan->TSIdleBuffer.Head;
+
+		do {
+			memset(&Cur->ngeneBuffer.SR, 0,
+			       sizeof(Cur->ngeneBuffer.SR));
+			FillTSBuffer(Cur->Buffer1,
+				     chan->Capture1Length,
+				     chan->DataFormatFlags);
+			Cur = Cur->Next;
+		} while (Cur != chan->TSIdleBuffer.Head);
+	}
+}
+
+static int ngene_command_stream_control(struct ngene *dev, u8 stream,
+					u8 control, u8 mode, u8 flags)
+{
+	struct ngene_channel *chan = &dev->channel[stream];
+	struct ngene_command com;
+	u16 BsUVI = ((stream & 1) ? 0x9400 : 0x9300);
+	u16 BsSDI = ((stream & 1) ? 0x9600 : 0x9500);
+	u16 BsSPI = ((stream & 1) ? 0x9800 : 0x9700);
+	u16 BsSDO = 0x9B00;
+
+	down(&dev->stream_mutex);
+	memset(&com, 0, sizeof(com));
+	com.cmd.hdr.Opcode = CMD_CONTROL;
+	com.cmd.hdr.Length = sizeof(struct FW_STREAM_CONTROL) - 2;
+	com.cmd.StreamControl.Stream = stream | (control ? 8 : 0);
+	if (chan->mode & NGENE_IO_TSOUT)
+		com.cmd.StreamControl.Stream |= 0x07;
+	com.cmd.StreamControl.Control = control |
+		(flags & SFLAG_ORDER_LUMA_CHROMA);
+	com.cmd.StreamControl.Mode = mode;
+	com.in_len = sizeof(struct FW_STREAM_CONTROL);
+	com.out_len = 0;
+
+	dprintk(KERN_INFO DEVICE_NAME
+		": Stream=%02x, Control=%02x, Mode=%02x\n",
+		com.cmd.StreamControl.Stream, com.cmd.StreamControl.Control,
+		com.cmd.StreamControl.Mode);
+
+	chan->Mode = mode;
+
+	if (!(control & 0x80)) {
+		spin_lock_irq(&chan->state_lock);
+		if (chan->State == KSSTATE_RUN) {
+			chan->State = KSSTATE_ACQUIRE;
+			chan->HWState = HWSTATE_STOP;
+			spin_unlock_irq(&chan->state_lock);
+			if (ngene_command(dev, &com) < 0) {
+				up(&dev->stream_mutex);
+				return -1;
+			}
+			/* clear_buffers(chan); */
+			flush_buffers(chan);
+			up(&dev->stream_mutex);
+			return 0;
+		}
+		spin_unlock_irq(&chan->state_lock);
+		up(&dev->stream_mutex);
+		return 0;
+	}
+
+	if (mode & SMODE_AUDIO_CAPTURE) {
+		com.cmd.StreamControl.CaptureBlockCount =
+			chan->Capture1Length / AUDIO_BLOCK_SIZE;
+		com.cmd.StreamControl.Buffer_Address = chan->RingBuffer.PAHead;
+	} else if (mode & SMODE_TRANSPORT_STREAM) {
+		com.cmd.StreamControl.CaptureBlockCount =
+			chan->Capture1Length / TS_BLOCK_SIZE;
+		com.cmd.StreamControl.MaxLinesPerField =
+			chan->Capture1Length / TS_BLOCK_SIZE;
+		com.cmd.StreamControl.Buffer_Address =
+			chan->TSRingBuffer.PAHead;
+		if (chan->mode & NGENE_IO_TSOUT) {
+			com.cmd.StreamControl.BytesPerVBILine =
+				chan->Capture1Length / TS_BLOCK_SIZE;
+			com.cmd.StreamControl.Stream |= 0x07;
+		}
+	} else {
+		com.cmd.StreamControl.BytesPerVideoLine = chan->nBytesPerLine;
+		com.cmd.StreamControl.MaxLinesPerField = chan->nLines;
+		com.cmd.StreamControl.MinLinesPerField = 100;
+		com.cmd.StreamControl.Buffer_Address = chan->RingBuffer.PAHead;
+
+		if (mode & SMODE_VBI_CAPTURE) {
+			com.cmd.StreamControl.MaxVBILinesPerField =
+				chan->nVBILines;
+			com.cmd.StreamControl.MinVBILinesPerField = 0;
+			com.cmd.StreamControl.BytesPerVBILine =
+				chan->nBytesPerVBILine;
+		}
+		if (flags & SFLAG_COLORBAR)
+			com.cmd.StreamControl.Stream |= 0x04;
+	}
+
+	spin_lock_irq(&chan->state_lock);
+	if (mode & SMODE_AUDIO_CAPTURE) {
+		chan->nextBuffer = chan->RingBuffer.Head;
+		if (mode & SMODE_AUDIO_SPDIF) {
+			com.cmd.StreamControl.SetupDataLen =
+				sizeof(SPDIFConfiguration);
+			com.cmd.StreamControl.SetupDataAddr = BsSPI;
+			memcpy(com.cmd.StreamControl.SetupData,
+			       SPDIFConfiguration, sizeof(SPDIFConfiguration));
+		} else {
+			com.cmd.StreamControl.SetupDataLen = 4;
+			com.cmd.StreamControl.SetupDataAddr = BsSDI;
+			memcpy(com.cmd.StreamControl.SetupData,
+			       I2SConfiguration +
+			       4 * dev->card_info->i2s[stream], 4);
+		}
+	} else if (mode & SMODE_TRANSPORT_STREAM) {
+		chan->nextBuffer = chan->TSRingBuffer.Head;
+		if (stream >= STREAM_AUDIOIN1) {
+			if (chan->mode & NGENE_IO_TSOUT) {
+				com.cmd.StreamControl.SetupDataLen =
+					sizeof(TS_I2SOutConfiguration);
+				com.cmd.StreamControl.SetupDataAddr = BsSDO;
+				memcpy(com.cmd.StreamControl.SetupData,
+				       TS_I2SOutConfiguration,
+				       sizeof(TS_I2SOutConfiguration));
+			} else {
+				com.cmd.StreamControl.SetupDataLen =
+					sizeof(TS_I2SConfiguration);
+				com.cmd.StreamControl.SetupDataAddr = BsSDI;
+				memcpy(com.cmd.StreamControl.SetupData,
+				       TS_I2SConfiguration,
+				       sizeof(TS_I2SConfiguration));
+			}
+		} else {
+			com.cmd.StreamControl.SetupDataLen = 8;
+			com.cmd.StreamControl.SetupDataAddr = BsUVI + 0x10;
+			memcpy(com.cmd.StreamControl.SetupData,
+			       TSFeatureDecoderSetup +
+			       8 * dev->card_info->tsf[stream], 8);
+		}
+	} else {
+		chan->nextBuffer = chan->RingBuffer.Head;
+		com.cmd.StreamControl.SetupDataLen =
+			16 + sizeof(ITUFeatureDecoderSetup);
+		com.cmd.StreamControl.SetupDataAddr = BsUVI;
+		memcpy(com.cmd.StreamControl.SetupData,
+		       ITUDecoderSetup[chan->itumode], 16);
+		memcpy(com.cmd.StreamControl.SetupData + 16,
+		       ITUFeatureDecoderSetup, sizeof(ITUFeatureDecoderSetup));
+	}
+	clear_buffers(chan);
+	chan->State = KSSTATE_RUN;
+	if (mode & SMODE_TRANSPORT_STREAM)
+		chan->HWState = HWSTATE_RUN;
+	else
+		chan->HWState = HWSTATE_STARTUP;
+	spin_unlock_irq(&chan->state_lock);
+
+	if (ngene_command(dev, &com) < 0) {
+		up(&dev->stream_mutex);
+		return -1;
+	}
+	up(&dev->stream_mutex);
+	return 0;
+}
+
+void set_transfer(struct ngene_channel *chan, int state)
+{
+	u8 control = 0, mode = 0, flags = 0;
+	struct ngene *dev = chan->dev;
+	int ret;
+
+	/*
+	printk(KERN_INFO DEVICE_NAME ": st %d\n", state);
+	msleep(100);
+	*/
+
+	if (state) {
+		if (chan->running) {
+			printk(KERN_INFO DEVICE_NAME ": already running\n");
+			return;
+		}
+	} else {
+		if (!chan->running) {
+			printk(KERN_INFO DEVICE_NAME ": already stopped\n");
+			return;
+		}
+	}
+
+	if (dev->card_info->switch_ctrl)
+		dev->card_info->switch_ctrl(chan, 1, state ^ 1);
+
+	if (state) {
+		spin_lock_irq(&chan->state_lock);
+
+		/* printk(KERN_INFO DEVICE_NAME ": lock=%08x\n",
+			  ngreadl(0x9310)); */
+		dvb_ringbuffer_flush(&dev->tsout_rbuf);
+		control = 0x80;
+		if (chan->mode & (NGENE_IO_TSIN | NGENE_IO_TSOUT)) {
+			chan->Capture1Length = 512 * 188;
+			mode = SMODE_TRANSPORT_STREAM;
+		}
+		if (chan->mode & NGENE_IO_TSOUT) {
+			chan->pBufferExchange = tsout_exchange;
+			/* 0x66666666 = 50MHz *2^33 /250MHz */
+			chan->AudioDTOValue = 0x80000000;
+			chan->AudioDTOUpdated = 1;
+		}
+		if (chan->mode & NGENE_IO_TSIN)
+			chan->pBufferExchange = tsin_exchange;
+		spin_unlock_irq(&chan->state_lock);
+	} else
+		;/* printk(KERN_INFO DEVICE_NAME ": lock=%08x\n",
+			   ngreadl(0x9310)); */
+
+	ret = ngene_command_stream_control(dev, chan->number,
+					   control, mode, flags);
+	if (!ret)
+		chan->running = state;
+	else
+		printk(KERN_ERR DEVICE_NAME ": set_transfer %d failed\n",
+		       state);
+	if (!state) {
+		spin_lock_irq(&chan->state_lock);
+		chan->pBufferExchange = NULL;
+		dvb_ringbuffer_flush(&dev->tsout_rbuf);
+		spin_unlock_irq(&chan->state_lock);
+	}
+}
+
+
+/****************************************************************************/
+/* nGene hardware init and release functions ********************************/
+/****************************************************************************/
+
+static void free_ringbuffer(struct ngene *dev, struct SRingBufferDescriptor *rb)
+{
+	struct SBufferHeader *Cur = rb->Head;
+	u32 j;
+
+	if (!Cur)
+		return;
+
+	for (j = 0; j < rb->NumBuffers; j++, Cur = Cur->Next) {
+		if (Cur->Buffer1)
+			pci_free_consistent(dev->pci_dev,
+					    rb->Buffer1Length,
+					    Cur->Buffer1,
+					    Cur->scList1->Address);
+
+		if (Cur->Buffer2)
+			pci_free_consistent(dev->pci_dev,
+					    rb->Buffer2Length,
+					    Cur->Buffer2,
+					    Cur->scList2->Address);
+	}
+
+	if (rb->SCListMem)
+		pci_free_consistent(dev->pci_dev, rb->SCListMemSize,
+				    rb->SCListMem, rb->PASCListMem);
+
+	pci_free_consistent(dev->pci_dev, rb->MemSize, rb->Head, rb->PAHead);
+}
+
+static void free_idlebuffer(struct ngene *dev,
+		     struct SRingBufferDescriptor *rb,
+		     struct SRingBufferDescriptor *tb)
+{
+	int j;
+	struct SBufferHeader *Cur = tb->Head;
+
+	if (!rb->Head)
+		return;
+	free_ringbuffer(dev, rb);
+	for (j = 0; j < tb->NumBuffers; j++, Cur = Cur->Next) {
+		Cur->Buffer2 = NULL;
+		Cur->scList2 = NULL;
+		Cur->ngeneBuffer.Address_of_first_entry_2 = 0;
+		Cur->ngeneBuffer.Number_of_entries_2 = 0;
+	}
+}
+
+static void free_common_buffers(struct ngene *dev)
+{
+	u32 i;
+	struct ngene_channel *chan;
+
+	for (i = STREAM_VIDEOIN1; i < MAX_STREAM; i++) {
+		chan = &dev->channel[i];
+		free_idlebuffer(dev, &chan->TSIdleBuffer, &chan->TSRingBuffer);
+		free_ringbuffer(dev, &chan->RingBuffer);
+		free_ringbuffer(dev, &chan->TSRingBuffer);
+	}
+
+	if (dev->OverflowBuffer)
+		pci_free_consistent(dev->pci_dev,
+				    OVERFLOW_BUFFER_SIZE,
+				    dev->OverflowBuffer, dev->PAOverflowBuffer);
+
+	if (dev->FWInterfaceBuffer)
+		pci_free_consistent(dev->pci_dev,
+				    4096,
+				    dev->FWInterfaceBuffer,
+				    dev->PAFWInterfaceBuffer);
+}
+
+/****************************************************************************/
+/* Ring buffer handling *****************************************************/
+/****************************************************************************/
+
+static int create_ring_buffer(struct pci_dev *pci_dev,
+		       struct SRingBufferDescriptor *descr, u32 NumBuffers)
+{
+	dma_addr_t tmp;
+	struct SBufferHeader *Head;
+	u32 i;
+	u32 MemSize = SIZEOF_SBufferHeader * NumBuffers;
+	u64 PARingBufferHead;
+	u64 PARingBufferCur;
+	u64 PARingBufferNext;
+	struct SBufferHeader *Cur, *Next;
+
+	descr->Head = NULL;
+	descr->MemSize = 0;
+	descr->PAHead = 0;
+	descr->NumBuffers = 0;
+
+	if (MemSize < 4096)
+		MemSize = 4096;
+
+	Head = pci_alloc_consistent(pci_dev, MemSize, &tmp);
+	PARingBufferHead = tmp;
+
+	if (!Head)
+		return -ENOMEM;
+
+	memset(Head, 0, MemSize);
+
+	PARingBufferCur = PARingBufferHead;
+	Cur = Head;
+
+	for (i = 0; i < NumBuffers - 1; i++) {
+		Next = (struct SBufferHeader *)
+			(((u8 *) Cur) + SIZEOF_SBufferHeader);
+		PARingBufferNext = PARingBufferCur + SIZEOF_SBufferHeader;
+		Cur->Next = Next;
+		Cur->ngeneBuffer.Next = PARingBufferNext;
+		Cur = Next;
+		PARingBufferCur = PARingBufferNext;
+	}
+	/* Last Buffer points back to first one */
+	Cur->Next = Head;
+	Cur->ngeneBuffer.Next = PARingBufferHead;
+
+	descr->Head       = Head;
+	descr->MemSize    = MemSize;
+	descr->PAHead     = PARingBufferHead;
+	descr->NumBuffers = NumBuffers;
+
+	return 0;
+}
+
+static int AllocateRingBuffers(struct pci_dev *pci_dev,
+			       dma_addr_t of,
+			       struct SRingBufferDescriptor *pRingBuffer,
+			       u32 Buffer1Length, u32 Buffer2Length)
+{
+	dma_addr_t tmp;
+	u32 i, j;
+	int status = 0;
+	u32 SCListMemSize = pRingBuffer->NumBuffers
+		* ((Buffer2Length != 0) ? (NUM_SCATTER_GATHER_ENTRIES * 2) :
+		    NUM_SCATTER_GATHER_ENTRIES)
+		* sizeof(struct HW_SCATTER_GATHER_ELEMENT);
+
+	u64 PASCListMem;
+	struct HW_SCATTER_GATHER_ELEMENT *SCListEntry;
+	u64 PASCListEntry;
+	struct SBufferHeader *Cur;
+	void *SCListMem;
+
+	if (SCListMemSize < 4096)
+		SCListMemSize = 4096;
+
+	SCListMem = pci_alloc_consistent(pci_dev, SCListMemSize, &tmp);
+
+	PASCListMem = tmp;
+	if (SCListMem == NULL)
+		return -ENOMEM;
+
+	memset(SCListMem, 0, SCListMemSize);
+
+	pRingBuffer->SCListMem = SCListMem;
+	pRingBuffer->PASCListMem = PASCListMem;
+	pRingBuffer->SCListMemSize = SCListMemSize;
+	pRingBuffer->Buffer1Length = Buffer1Length;
+	pRingBuffer->Buffer2Length = Buffer2Length;
+
+	SCListEntry = SCListMem;
+	PASCListEntry = PASCListMem;
+	Cur = pRingBuffer->Head;
+
+	for (i = 0; i < pRingBuffer->NumBuffers; i += 1, Cur = Cur->Next) {
+		u64 PABuffer;
+
+		void *Buffer = pci_alloc_consistent(pci_dev, Buffer1Length,
+						    &tmp);
+		PABuffer = tmp;
+
+		if (Buffer == NULL)
+			return -ENOMEM;
+
+		Cur->Buffer1 = Buffer;
+
+		SCListEntry->Address = PABuffer;
+		SCListEntry->Length  = Buffer1Length;
+
+		Cur->scList1 = SCListEntry;
+		Cur->ngeneBuffer.Address_of_first_entry_1 = PASCListEntry;
+		Cur->ngeneBuffer.Number_of_entries_1 =
+			NUM_SCATTER_GATHER_ENTRIES;
+
+		SCListEntry += 1;
+		PASCListEntry += sizeof(struct HW_SCATTER_GATHER_ELEMENT);
+
+#if NUM_SCATTER_GATHER_ENTRIES > 1
+		for (j = 0; j < NUM_SCATTER_GATHER_ENTRIES - 1; j += 1) {
+			SCListEntry->Address = of;
+			SCListEntry->Length = OVERFLOW_BUFFER_SIZE;
+			SCListEntry += 1;
+			PASCListEntry +=
+				sizeof(struct HW_SCATTER_GATHER_ELEMENT);
+		}
+#endif
+
+		if (!Buffer2Length)
+			continue;
+
+		Buffer = pci_alloc_consistent(pci_dev, Buffer2Length, &tmp);
+		PABuffer = tmp;
+
+		if (Buffer == NULL)
+			return -ENOMEM;
+
+		Cur->Buffer2 = Buffer;
+
+		SCListEntry->Address = PABuffer;
+		SCListEntry->Length  = Buffer2Length;
+
+		Cur->scList2 = SCListEntry;
+		Cur->ngeneBuffer.Address_of_first_entry_2 = PASCListEntry;
+		Cur->ngeneBuffer.Number_of_entries_2 =
+			NUM_SCATTER_GATHER_ENTRIES;
+
+		SCListEntry   += 1;
+		PASCListEntry += sizeof(struct HW_SCATTER_GATHER_ELEMENT);
+
+#if NUM_SCATTER_GATHER_ENTRIES > 1
+		for (j = 0; j < NUM_SCATTER_GATHER_ENTRIES - 1; j++) {
+			SCListEntry->Address = of;
+			SCListEntry->Length = OVERFLOW_BUFFER_SIZE;
+			SCListEntry += 1;
+			PASCListEntry +=
+				sizeof(struct HW_SCATTER_GATHER_ELEMENT);
+		}
+#endif
+
+	}
+
+	return status;
+}
+
+static int FillTSIdleBuffer(struct SRingBufferDescriptor *pIdleBuffer,
+			    struct SRingBufferDescriptor *pRingBuffer)
+{
+	int status = 0;
+
+	/* Copy pointer to scatter gather list in TSRingbuffer
+	   structure for buffer 2
+	   Load number of buffer
+	*/
+	u32 n = pRingBuffer->NumBuffers;
+
+	/* Point to first buffer entry */
+	struct SBufferHeader *Cur = pRingBuffer->Head;
+	int i;
+	/* Loop thru all buffer and set Buffer 2 pointers to TSIdlebuffer */
+	for (i = 0; i < n; i++) {
+		Cur->Buffer2 = pIdleBuffer->Head->Buffer1;
+		Cur->scList2 = pIdleBuffer->Head->scList1;
+		Cur->ngeneBuffer.Address_of_first_entry_2 =
+			pIdleBuffer->Head->ngeneBuffer.
+			Address_of_first_entry_1;
+		Cur->ngeneBuffer.Number_of_entries_2 =
+			pIdleBuffer->Head->ngeneBuffer.Number_of_entries_1;
+		Cur = Cur->Next;
+	}
+	return status;
+}
+
+static u32 RingBufferSizes[MAX_STREAM] = {
+	RING_SIZE_VIDEO,
+	RING_SIZE_VIDEO,
+	RING_SIZE_AUDIO,
+	RING_SIZE_AUDIO,
+	RING_SIZE_AUDIO,
+};
+
+static u32 Buffer1Sizes[MAX_STREAM] = {
+	MAX_VIDEO_BUFFER_SIZE,
+	MAX_VIDEO_BUFFER_SIZE,
+	MAX_AUDIO_BUFFER_SIZE,
+	MAX_AUDIO_BUFFER_SIZE,
+	MAX_AUDIO_BUFFER_SIZE
+};
+
+static u32 Buffer2Sizes[MAX_STREAM] = {
+	MAX_VBI_BUFFER_SIZE,
+	MAX_VBI_BUFFER_SIZE,
+	0,
+	0,
+	0
+};
+
+
+static int AllocCommonBuffers(struct ngene *dev)
+{
+	int status = 0, i;
+
+	dev->FWInterfaceBuffer = pci_alloc_consistent(dev->pci_dev, 4096,
+						     &dev->PAFWInterfaceBuffer);
+	if (!dev->FWInterfaceBuffer)
+		return -ENOMEM;
+	dev->hosttongene = dev->FWInterfaceBuffer;
+	dev->ngenetohost = dev->FWInterfaceBuffer + 256;
+	dev->EventBuffer = dev->FWInterfaceBuffer + 512;
+
+	dev->OverflowBuffer = pci_alloc_consistent(dev->pci_dev,
+						   OVERFLOW_BUFFER_SIZE,
+						   &dev->PAOverflowBuffer);
+	if (!dev->OverflowBuffer)
+		return -ENOMEM;
+	memset(dev->OverflowBuffer, 0, OVERFLOW_BUFFER_SIZE);
+
+	for (i = STREAM_VIDEOIN1; i < MAX_STREAM; i++) {
+		int type = dev->card_info->io_type[i];
+
+		dev->channel[i].State = KSSTATE_STOP;
+
+		if (type & (NGENE_IO_TV | NGENE_IO_HDTV | NGENE_IO_AIN)) {
+			status = create_ring_buffer(dev->pci_dev,
+						    &dev->channel[i].RingBuffer,
+						    RingBufferSizes[i]);
+			if (status < 0)
+				break;
+
+			if (type & (NGENE_IO_TV | NGENE_IO_AIN)) {
+				status = AllocateRingBuffers(dev->pci_dev,
+							     dev->
+							     PAOverflowBuffer,
+							     &dev->channel[i].
+							     RingBuffer,
+							     Buffer1Sizes[i],
+							     Buffer2Sizes[i]);
+				if (status < 0)
+					break;
+			} else if (type & NGENE_IO_HDTV) {
+				status = AllocateRingBuffers(dev->pci_dev,
+							     dev->
+							     PAOverflowBuffer,
+							     &dev->channel[i].
+							     RingBuffer,
+							   MAX_HDTV_BUFFER_SIZE,
+							     0);
+				if (status < 0)
+					break;
+			}
+		}
+
+		if (type & (NGENE_IO_TSIN | NGENE_IO_TSOUT)) {
+
+			status = create_ring_buffer(dev->pci_dev,
+						    &dev->channel[i].
+						    TSRingBuffer, RING_SIZE_TS);
+			if (status < 0)
+				break;
+
+			status = AllocateRingBuffers(dev->pci_dev,
+						     dev->PAOverflowBuffer,
+						     &dev->channel[i].
+						     TSRingBuffer,
+						     MAX_TS_BUFFER_SIZE, 0);
+			if (status)
+				break;
+		}
+
+		if (type & NGENE_IO_TSOUT) {
+			status = create_ring_buffer(dev->pci_dev,
+						    &dev->channel[i].
+						    TSIdleBuffer, 1);
+			if (status < 0)
+				break;
+			status = AllocateRingBuffers(dev->pci_dev,
+						     dev->PAOverflowBuffer,
+						     &dev->channel[i].
+						     TSIdleBuffer,
+						     MAX_TS_BUFFER_SIZE, 0);
+			if (status)
+				break;
+			FillTSIdleBuffer(&dev->channel[i].TSIdleBuffer,
+					 &dev->channel[i].TSRingBuffer);
+		}
+	}
+	return status;
+}
+
+static void ngene_release_buffers(struct ngene *dev)
+{
+	if (dev->iomem)
+		iounmap(dev->iomem);
+	free_common_buffers(dev);
+	vfree(dev->tsout_buf);
+	vfree(dev->tsin_buf);
+	vfree(dev->ain_buf);
+	vfree(dev->vin_buf);
+	vfree(dev);
+}
+
+static int ngene_get_buffers(struct ngene *dev)
+{
+	if (AllocCommonBuffers(dev))
+		return -ENOMEM;
+	if (dev->card_info->io_type[4] & NGENE_IO_TSOUT) {
+		dev->tsout_buf = vmalloc(TSOUT_BUF_SIZE);
+		if (!dev->tsout_buf)
+			return -ENOMEM;
+		dvb_ringbuffer_init(&dev->tsout_rbuf,
+				    dev->tsout_buf, TSOUT_BUF_SIZE);
+	}
+	if (dev->card_info->io_type[2]&NGENE_IO_TSIN) {
+		dev->tsin_buf = vmalloc(TSIN_BUF_SIZE);
+		if (!dev->tsin_buf)
+			return -ENOMEM;
+		dvb_ringbuffer_init(&dev->tsin_rbuf,
+				    dev->tsin_buf, TSIN_BUF_SIZE);
+	}
+	if (dev->card_info->io_type[2] & NGENE_IO_AIN) {
+		dev->ain_buf = vmalloc(AIN_BUF_SIZE);
+		if (!dev->ain_buf)
+			return -ENOMEM;
+		dvb_ringbuffer_init(&dev->ain_rbuf, dev->ain_buf, AIN_BUF_SIZE);
+	}
+	if (dev->card_info->io_type[0] & NGENE_IO_HDTV) {
+		dev->vin_buf = vmalloc(VIN_BUF_SIZE);
+		if (!dev->vin_buf)
+			return -ENOMEM;
+		dvb_ringbuffer_init(&dev->vin_rbuf, dev->vin_buf, VIN_BUF_SIZE);
+	}
+	dev->iomem = ioremap(pci_resource_start(dev->pci_dev, 0),
+			     pci_resource_len(dev->pci_dev, 0));
+	if (!dev->iomem)
+		return -ENOMEM;
+
+	return 0;
+}
+
+static void ngene_init(struct ngene *dev)
+{
+	int i;
+
+	tasklet_init(&dev->event_tasklet, event_tasklet, (unsigned long)dev);
+
+	memset_io(dev->iomem + 0xc000, 0x00, 0x220);
+	memset_io(dev->iomem + 0xc400, 0x00, 0x100);
+
+	for (i = 0; i < MAX_STREAM; i++) {
+		dev->channel[i].dev = dev;
+		dev->channel[i].number = i;
+	}
+
+	dev->fw_interface_version = 0;
+
+	ngwritel(0, NGENE_INT_ENABLE);
+
+	dev->icounts = ngreadl(NGENE_INT_COUNTS);
+
+	dev->device_version = ngreadl(DEV_VER) & 0x0f;
+	printk(KERN_INFO DEVICE_NAME ": Device version %d\n",
+	       dev->device_version);
+}
+
+static int ngene_load_firm(struct ngene *dev)
+{
+	u32 size;
+	const struct firmware *fw = NULL;
+	u8 *ngene_fw;
+	char *fw_name;
+	int err, version;
+
+	version = dev->card_info->fw_version;
+
+	switch (version) {
+	default:
+	case 15:
+		version = 15;
+		size = 23466;
+		fw_name = "ngene_15.fw";
+		dev->cmd_timeout_workaround = true;
+		break;
+	case 16:
+		size = 23498;
+		fw_name = "ngene_16.fw";
+		dev->cmd_timeout_workaround = true;
+		break;
+	case 17:
+		size = 24446;
+		fw_name = "ngene_17.fw";
+		dev->cmd_timeout_workaround = true;
+		break;
+	case 18:
+		size = 0;
+		fw_name = "ngene_18.fw";
+		break;
+	}
+
+	if (request_firmware(&fw, fw_name, &dev->pci_dev->dev) < 0) {
+		printk(KERN_ERR DEVICE_NAME
+			": Could not load firmware file %s.\n", fw_name);
+		printk(KERN_INFO DEVICE_NAME
+			": Copy %s to your hotplug directory!\n", fw_name);
+		return -1;
+	}
+	if (size == 0)
+		size = fw->size;
+	if (size != fw->size) {
+		printk(KERN_ERR DEVICE_NAME
+			": Firmware %s has invalid size!", fw_name);
+		err = -1;
+	} else {
+		printk(KERN_INFO DEVICE_NAME
+			": Loading firmware file %s.\n", fw_name);
+		ngene_fw = (u8 *) fw->data;
+		err = ngene_command_load_firmware(dev, ngene_fw, size);
+	}
+
+	release_firmware(fw);
+
+	return err;
+}
+
+static void ngene_stop(struct ngene *dev)
+{
+	down(&dev->cmd_mutex);
+	i2c_del_adapter(&(dev->channel[0].i2c_adapter));
+	i2c_del_adapter(&(dev->channel[1].i2c_adapter));
+	ngwritel(0, NGENE_INT_ENABLE);
+	ngwritel(0, NGENE_COMMAND);
+	ngwritel(0, NGENE_COMMAND_HI);
+	ngwritel(0, NGENE_STATUS);
+	ngwritel(0, NGENE_STATUS_HI);
+	ngwritel(0, NGENE_EVENT);
+	ngwritel(0, NGENE_EVENT_HI);
+	free_irq(dev->pci_dev->irq, dev);
+#ifdef CONFIG_PCI_MSI
+	if (dev->msi_enabled)
+		pci_disable_msi(dev->pci_dev);
+#endif
+}
+
+static int ngene_buffer_config(struct ngene *dev)
+{
+	int stat;
+
+	if (dev->card_info->fw_version >= 17) {
+		u8 tsin12_config[6]   = { 0x60, 0x60, 0x00, 0x00, 0x00, 0x00 };
+		u8 tsin1234_config[6] = { 0x30, 0x30, 0x00, 0x30, 0x30, 0x00 };
+		u8 tsio1235_config[6] = { 0x30, 0x30, 0x00, 0x28, 0x00, 0x38 };
+		u8 *bconf = tsin12_config;
+
+		if (dev->card_info->io_type[2]&NGENE_IO_TSIN &&
+		    dev->card_info->io_type[3]&NGENE_IO_TSIN) {
+			bconf = tsin1234_config;
+			if (dev->card_info->io_type[4]&NGENE_IO_TSOUT &&
+			    dev->ci.en)
+				bconf = tsio1235_config;
+		}
+		stat = ngene_command_config_free_buf(dev, bconf);
+	} else {
+		int bconf = BUFFER_CONFIG_4422;
+
+		if (dev->card_info->io_type[3] == NGENE_IO_TSIN)
+			bconf = BUFFER_CONFIG_3333;
+		stat = ngene_command_config_buf(dev, bconf);
+	}
+	return stat;
+}
+
+
+static int ngene_start(struct ngene *dev)
+{
+	int stat;
+	int i;
+
+	pci_set_master(dev->pci_dev);
+	ngene_init(dev);
+
+	stat = request_irq(dev->pci_dev->irq, irq_handler,
+			   IRQF_SHARED, "nGene",
+			   (void *)dev);
+	if (stat < 0)
+		return stat;
+
+	init_waitqueue_head(&dev->cmd_wq);
+	init_waitqueue_head(&dev->tx_wq);
+	init_waitqueue_head(&dev->rx_wq);
+	sema_init(&dev->cmd_mutex, 1);
+	sema_init(&dev->stream_mutex, 1);
+	sema_init(&dev->pll_mutex, 1);
+	sema_init(&dev->i2c_switch_mutex, 1);
+	spin_lock_init(&dev->cmd_lock);
+	for (i = 0; i < MAX_STREAM; i++)
+		spin_lock_init(&dev->channel[i].state_lock);
+	ngwritel(1, TIMESTAMPS);
+
+	ngwritel(1, NGENE_INT_ENABLE);
+
+	stat = ngene_load_firm(dev);
+	if (stat < 0)
+		goto fail;
+
+#ifdef CONFIG_PCI_MSI
+	/* enable MSI if kernel and card support it */
+	if (pci_msi_enabled() && dev->card_info->msi_supported) {
+		unsigned long flags;
+
+		ngwritel(0, NGENE_INT_ENABLE);
+		free_irq(dev->pci_dev->irq, dev);
+		stat = pci_enable_msi(dev->pci_dev);
+		if (stat) {
+			printk(KERN_INFO DEVICE_NAME
+				": MSI not available\n");
+			flags = IRQF_SHARED;
+		} else {
+			flags = 0;
+			dev->msi_enabled = true;
+		}
+		stat = request_irq(dev->pci_dev->irq, irq_handler,
+					flags, "nGene", dev);
+		if (stat < 0)
+			goto fail2;
+		ngwritel(1, NGENE_INT_ENABLE);
+	}
+#endif
+
+	stat = ngene_i2c_init(dev, 0);
+	if (stat < 0)
+		goto fail;
+
+	stat = ngene_i2c_init(dev, 1);
+	if (stat < 0)
+		goto fail;
+
+	return 0;
+
+fail:
+	ngwritel(0, NGENE_INT_ENABLE);
+	free_irq(dev->pci_dev->irq, dev);
+#ifdef CONFIG_PCI_MSI
+fail2:
+	if (dev->msi_enabled)
+		pci_disable_msi(dev->pci_dev);
+#endif
+	return stat;
+}
+
+/****************************************************************************/
+/****************************************************************************/
+/****************************************************************************/
+
+static void release_channel(struct ngene_channel *chan)
+{
+	struct dvb_demux *dvbdemux = &chan->demux;
+	struct ngene *dev = chan->dev;
+
+	if (chan->running)
+		set_transfer(chan, 0);
+
+	tasklet_kill(&chan->demux_tasklet);
+
+	if (chan->ci_dev) {
+		dvb_unregister_device(chan->ci_dev);
+		chan->ci_dev = NULL;
+	}
+
+	if (chan->fe2)
+		dvb_unregister_frontend(chan->fe2);
+
+	if (chan->fe) {
+		dvb_unregister_frontend(chan->fe);
+		dvb_frontend_detach(chan->fe);
+		chan->fe = NULL;
+	}
+
+	if (chan->has_demux) {
+		dvb_net_release(&chan->dvbnet);
+		dvbdemux->dmx.close(&dvbdemux->dmx);
+		dvbdemux->dmx.remove_frontend(&dvbdemux->dmx,
+					      &chan->hw_frontend);
+		dvbdemux->dmx.remove_frontend(&dvbdemux->dmx,
+					      &chan->mem_frontend);
+		dvb_dmxdev_release(&chan->dmxdev);
+		dvb_dmx_release(&chan->demux);
+		chan->has_demux = false;
+	}
+
+	if (chan->has_adapter) {
+		dvb_unregister_adapter(&dev->adapter[chan->number]);
+		chan->has_adapter = false;
+	}
+}
+
+static int init_channel(struct ngene_channel *chan)
+{
+	int ret = 0, nr = chan->number;
+	struct dvb_adapter *adapter = NULL;
+	struct dvb_demux *dvbdemux = &chan->demux;
+	struct ngene *dev = chan->dev;
+	struct ngene_info *ni = dev->card_info;
+	int io = ni->io_type[nr];
+
+	tasklet_init(&chan->demux_tasklet, demux_tasklet, (unsigned long)chan);
+	chan->users = 0;
+	chan->type = io;
+	chan->mode = chan->type;	/* for now only one mode */
+
+	if (io & NGENE_IO_TSIN) {
+		chan->fe = NULL;
+		if (ni->demod_attach[nr]) {
+			ret = ni->demod_attach[nr](chan);
+			if (ret < 0)
+				goto err;
+		}
+		if (chan->fe && ni->tuner_attach[nr]) {
+			ret = ni->tuner_attach[nr](chan);
+			if (ret < 0)
+				goto err;
+		}
+	}
+
+	if (!dev->ci.en && (io & NGENE_IO_TSOUT))
+		return 0;
+
+	if (io & (NGENE_IO_TSIN | NGENE_IO_TSOUT)) {
+		if (nr >= STREAM_AUDIOIN1)
+			chan->DataFormatFlags = DF_SWAP32;
+
+		if (nr == 0 || !one_adapter || dev->first_adapter == NULL) {
+			adapter = &dev->adapter[nr];
+			ret = dvb_register_adapter(adapter, "nGene",
+						   THIS_MODULE,
+						   &chan->dev->pci_dev->dev,
+						   adapter_nr);
+			if (ret < 0)
+				goto err;
+			if (dev->first_adapter == NULL)
+				dev->first_adapter = adapter;
+			chan->has_adapter = true;
+		} else
+			adapter = dev->first_adapter;
+	}
+
+	if (dev->ci.en && (io & NGENE_IO_TSOUT)) {
+		dvb_ca_en50221_init(adapter, dev->ci.en, 0, 1);
+		set_transfer(chan, 1);
+		chan->dev->channel[2].DataFormatFlags = DF_SWAP32;
+		set_transfer(&chan->dev->channel[2], 1);
+		dvb_register_device(adapter, &chan->ci_dev,
+				    &ngene_dvbdev_ci, (void *) chan,
+				    DVB_DEVICE_SEC);
+		if (!chan->ci_dev)
+			goto err;
+	}
+
+	if (chan->fe) {
+		if (dvb_register_frontend(adapter, chan->fe) < 0)
+			goto err;
+		chan->has_demux = true;
+	}
+	if (chan->fe2) {
+		if (dvb_register_frontend(adapter, chan->fe2) < 0)
+			goto err;
+		chan->fe2->tuner_priv = chan->fe->tuner_priv;
+		memcpy(&chan->fe2->ops.tuner_ops,
+		       &chan->fe->ops.tuner_ops,
+		       sizeof(struct dvb_tuner_ops));
+	}
+
+	if (chan->has_demux) {
+		ret = my_dvb_dmx_ts_card_init(dvbdemux, "SW demux",
+					      ngene_start_feed,
+					      ngene_stop_feed, chan);
+		ret = my_dvb_dmxdev_ts_card_init(&chan->dmxdev, &chan->demux,
+						 &chan->hw_frontend,
+						 &chan->mem_frontend, adapter);
+		ret = dvb_net_init(adapter, &chan->dvbnet, &chan->demux.dmx);
+	}
+
+	return ret;
+
+err:
+	if (chan->fe) {
+		dvb_frontend_detach(chan->fe);
+		chan->fe = NULL;
+	}
+	release_channel(chan);
+	return 0;
+}
+
+static int init_channels(struct ngene *dev)
+{
+	int i, j;
+
+	for (i = 0; i < MAX_STREAM; i++) {
+		dev->channel[i].number = i;
+		if (init_channel(&dev->channel[i]) < 0) {
+			for (j = i - 1; j >= 0; j--)
+				release_channel(&dev->channel[j]);
+			return -1;
+		}
+	}
+	return 0;
+}
+
+static struct cxd2099_cfg cxd_cfg = {
+	.bitrate = 62000,
+	.adr = 0x40,
+	.polarity = 0,
+	.clock_mode = 0,
+};
+
+static void cxd_attach(struct ngene *dev)
+{
+	struct ngene_ci *ci = &dev->ci;
+
+	ci->en = cxd2099_attach(&cxd_cfg, dev, &dev->channel[0].i2c_adapter);
+	ci->dev = dev;
+	return;
+}
+
+static void cxd_detach(struct ngene *dev)
+{
+	struct ngene_ci *ci = &dev->ci;
+
+	dvb_ca_en50221_release(ci->en);
+	kfree(ci->en);
+	ci->en = 0;
+}
+
+/***********************************/
+/* workaround for shutdown failure */
+/***********************************/
+
+static void ngene_unlink(struct ngene *dev)
+{
+	struct ngene_command com;
+
+	com.cmd.hdr.Opcode = CMD_MEM_WRITE;
+	com.cmd.hdr.Length = 3;
+	com.cmd.MemoryWrite.address = 0x910c;
+	com.cmd.MemoryWrite.data = 0xff;
+	com.in_len = 3;
+	com.out_len = 1;
+
+	down(&dev->cmd_mutex);
+	ngwritel(0, NGENE_INT_ENABLE);
+	ngene_command_mutex(dev, &com);
+	up(&dev->cmd_mutex);
+}
+
+void ngene_shutdown(struct pci_dev *pdev)
+{
+	struct ngene *dev = (struct ngene *)pci_get_drvdata(pdev);
+
+	if (!dev || !shutdown_workaround)
+		return;
+
+	printk(KERN_INFO DEVICE_NAME ": shutdown workaround...\n");
+	ngene_unlink(dev);
+	pci_disable_device(pdev);
+}
+
+/****************************************************************************/
+/* device probe/remove calls ************************************************/
+/****************************************************************************/
+
+void __devexit ngene_remove(struct pci_dev *pdev)
+{
+	struct ngene *dev = pci_get_drvdata(pdev);
+	int i;
+
+	tasklet_kill(&dev->event_tasklet);
+	for (i = MAX_STREAM - 1; i >= 0; i--)
+		release_channel(&dev->channel[i]);
+	if (dev->ci.en)
+		cxd_detach(dev);
+	ngene_stop(dev);
+	ngene_release_buffers(dev);
+	pci_set_drvdata(pdev, NULL);
+	pci_disable_device(pdev);
+}
+
+int __devinit ngene_probe(struct pci_dev *pci_dev,
+			  const struct pci_device_id *id)
+{
+	struct ngene *dev;
+	int stat = 0;
+
+	if (pci_enable_device(pci_dev) < 0)
+		return -ENODEV;
+
+	dev = vzalloc(sizeof(struct ngene));
+	if (dev == NULL) {
+		stat = -ENOMEM;
+		goto fail0;
+	}
+
+	dev->pci_dev = pci_dev;
+	dev->card_info = (struct ngene_info *)id->driver_data;
+	printk(KERN_INFO DEVICE_NAME ": Found %s\n", dev->card_info->name);
+
+	pci_set_drvdata(pci_dev, dev);
+
+	/* Alloc buffers and start nGene */
+	stat = ngene_get_buffers(dev);
+	if (stat < 0)
+		goto fail1;
+	stat = ngene_start(dev);
+	if (stat < 0)
+		goto fail1;
+
+	cxd_attach(dev);
+
+	stat = ngene_buffer_config(dev);
+	if (stat < 0)
+		goto fail1;
+
+
+	dev->i2c_current_bus = -1;
+
+	/* Register DVB adapters and devices for both channels */
+	if (init_channels(dev) < 0)
+		goto fail2;
+
+	return 0;
+
+fail2:
+	ngene_stop(dev);
+fail1:
+	ngene_release_buffers(dev);
+fail0:
+	pci_disable_device(pci_dev);
+	pci_set_drvdata(pci_dev, NULL);
+	return stat;
+}
diff --git a/drivers/media/pci/ngene/ngene-dvb.c b/drivers/media/pci/ngene/ngene-dvb.c
new file mode 100644
index 0000000..fcb16a6
--- /dev/null
+++ b/drivers/media/pci/ngene/ngene-dvb.c
@@ -0,0 +1,261 @@
+/*
+ * ngene-dvb.c: nGene PCIe bridge driver - DVB functions
+ *
+ * Copyright (C) 2005-2007 Micronas
+ *
+ * Copyright (C) 2008-2009 Ralph Metzler <rjkm@metzlerbros.de>
+ *                         Modifications for new nGene firmware,
+ *                         support for EEPROM-copying,
+ *                         support for new dual DVB-S2 card prototype
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 only, as published by the Free Software Foundation.
+ *
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/poll.h>
+#include <linux/io.h>
+#include <asm/div64.h>
+#include <linux/pci.h>
+#include <linux/timer.h>
+#include <linux/byteorder/generic.h>
+#include <linux/firmware.h>
+#include <linux/vmalloc.h>
+
+#include "ngene.h"
+
+
+/****************************************************************************/
+/* COMMAND API interface ****************************************************/
+/****************************************************************************/
+
+static ssize_t ts_write(struct file *file, const char *buf,
+			size_t count, loff_t *ppos)
+{
+	struct dvb_device *dvbdev = file->private_data;
+	struct ngene_channel *chan = dvbdev->priv;
+	struct ngene *dev = chan->dev;
+
+	if (wait_event_interruptible(dev->tsout_rbuf.queue,
+				     dvb_ringbuffer_free
+				     (&dev->tsout_rbuf) >= count) < 0)
+		return 0;
+
+	dvb_ringbuffer_write(&dev->tsout_rbuf, buf, count);
+
+	return count;
+}
+
+static ssize_t ts_read(struct file *file, char *buf,
+		       size_t count, loff_t *ppos)
+{
+	struct dvb_device *dvbdev = file->private_data;
+	struct ngene_channel *chan = dvbdev->priv;
+	struct ngene *dev = chan->dev;
+	int left, avail;
+
+	left = count;
+	while (left) {
+		if (wait_event_interruptible(
+			    dev->tsin_rbuf.queue,
+			    dvb_ringbuffer_avail(&dev->tsin_rbuf) > 0) < 0)
+			return -EAGAIN;
+		avail = dvb_ringbuffer_avail(&dev->tsin_rbuf);
+		if (avail > left)
+			avail = left;
+		dvb_ringbuffer_read_user(&dev->tsin_rbuf, buf, avail);
+		left -= avail;
+		buf += avail;
+	}
+	return count;
+}
+
+static const struct file_operations ci_fops = {
+	.owner   = THIS_MODULE,
+	.read    = ts_read,
+	.write   = ts_write,
+	.open    = dvb_generic_open,
+	.release = dvb_generic_release,
+};
+
+struct dvb_device ngene_dvbdev_ci = {
+	.priv    = 0,
+	.readers = -1,
+	.writers = -1,
+	.users   = -1,
+	.fops    = &ci_fops,
+};
+
+
+/****************************************************************************/
+/* DVB functions and API interface ******************************************/
+/****************************************************************************/
+
+static void swap_buffer(u32 *p, u32 len)
+{
+	while (len) {
+		*p = swab32(*p);
+		p++;
+		len -= 4;
+	}
+}
+
+/* start of filler packet */
+static u8 fill_ts[] = { 0x47, 0x1f, 0xff, 0x10, TS_FILLER };
+
+/* #define DEBUG_CI_XFER */
+#ifdef DEBUG_CI_XFER
+static u32 ok;
+static u32 overflow;
+static u32 stripped;
+#endif
+
+void *tsin_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags)
+{
+	struct ngene_channel *chan = priv;
+	struct ngene *dev = chan->dev;
+
+
+	if (flags & DF_SWAP32)
+		swap_buffer(buf, len);
+
+	if (dev->ci.en && chan->number == 2) {
+		while (len >= 188) {
+			if (memcmp(buf, fill_ts, sizeof fill_ts) != 0) {
+				if (dvb_ringbuffer_free(&dev->tsin_rbuf) >= 188) {
+					dvb_ringbuffer_write(&dev->tsin_rbuf, buf, 188);
+					wake_up(&dev->tsin_rbuf.queue);
+#ifdef DEBUG_CI_XFER
+					ok++;
+#endif
+				}
+#ifdef DEBUG_CI_XFER
+				else
+					overflow++;
+#endif
+			}
+#ifdef DEBUG_CI_XFER
+			else
+				stripped++;
+
+			if (ok % 100 == 0 && overflow)
+				printk(KERN_WARNING "%s: ok %u overflow %u dropped %u\n", __func__, ok, overflow, stripped);
+#endif
+			buf += 188;
+			len -= 188;
+		}
+		return NULL;
+	}
+
+	if (chan->users > 0)
+		dvb_dmx_swfilter(&chan->demux, buf, len);
+
+	return NULL;
+}
+
+void *tsout_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags)
+{
+	struct ngene_channel *chan = priv;
+	struct ngene *dev = chan->dev;
+	u32 alen;
+
+	alen = dvb_ringbuffer_avail(&dev->tsout_rbuf);
+	alen -= alen % 188;
+
+	if (alen < len)
+		FillTSBuffer(buf + alen, len - alen, flags);
+	else
+		alen = len;
+	dvb_ringbuffer_read(&dev->tsout_rbuf, buf, alen);
+	if (flags & DF_SWAP32)
+		swap_buffer((u32 *)buf, alen);
+	wake_up_interruptible(&dev->tsout_rbuf.queue);
+	return buf;
+}
+
+
+
+int ngene_start_feed(struct dvb_demux_feed *dvbdmxfeed)
+{
+	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
+	struct ngene_channel *chan = dvbdmx->priv;
+
+	if (chan->users == 0) {
+		if (!chan->dev->cmd_timeout_workaround || !chan->running)
+			set_transfer(chan, 1);
+	}
+
+	return ++chan->users;
+}
+
+int ngene_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
+{
+	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
+	struct ngene_channel *chan = dvbdmx->priv;
+
+	if (--chan->users)
+		return chan->users;
+
+	if (!chan->dev->cmd_timeout_workaround)
+		set_transfer(chan, 0);
+
+	return 0;
+}
+
+int my_dvb_dmx_ts_card_init(struct dvb_demux *dvbdemux, char *id,
+			    int (*start_feed)(struct dvb_demux_feed *),
+			    int (*stop_feed)(struct dvb_demux_feed *),
+			    void *priv)
+{
+	dvbdemux->priv = priv;
+
+	dvbdemux->filternum = 256;
+	dvbdemux->feednum = 256;
+	dvbdemux->start_feed = start_feed;
+	dvbdemux->stop_feed = stop_feed;
+	dvbdemux->write_to_decoder = NULL;
+	dvbdemux->dmx.capabilities = (DMX_TS_FILTERING |
+				      DMX_SECTION_FILTERING |
+				      DMX_MEMORY_BASED_FILTERING);
+	return dvb_dmx_init(dvbdemux);
+}
+
+int my_dvb_dmxdev_ts_card_init(struct dmxdev *dmxdev,
+			       struct dvb_demux *dvbdemux,
+			       struct dmx_frontend *hw_frontend,
+			       struct dmx_frontend *mem_frontend,
+			       struct dvb_adapter *dvb_adapter)
+{
+	int ret;
+
+	dmxdev->filternum = 256;
+	dmxdev->demux = &dvbdemux->dmx;
+	dmxdev->capabilities = 0;
+	ret = dvb_dmxdev_init(dmxdev, dvb_adapter);
+	if (ret < 0)
+		return ret;
+
+	hw_frontend->source = DMX_FRONTEND_0;
+	dvbdemux->dmx.add_frontend(&dvbdemux->dmx, hw_frontend);
+	mem_frontend->source = DMX_MEMORY_FE;
+	dvbdemux->dmx.add_frontend(&dvbdemux->dmx, mem_frontend);
+	return dvbdemux->dmx.connect_frontend(&dvbdemux->dmx, hw_frontend);
+}
diff --git a/drivers/media/pci/ngene/ngene-i2c.c b/drivers/media/pci/ngene/ngene-i2c.c
new file mode 100644
index 0000000..d28554f
--- /dev/null
+++ b/drivers/media/pci/ngene/ngene-i2c.c
@@ -0,0 +1,176 @@
+/*
+ * ngene-i2c.c: nGene PCIe bridge driver i2c functions
+ *
+ * Copyright (C) 2005-2007 Micronas
+ *
+ * Copyright (C) 2008-2009 Ralph Metzler <rjkm@metzlerbros.de>
+ *                         Modifications for new nGene firmware,
+ *                         support for EEPROM-copying,
+ *                         support for new dual DVB-S2 card prototype
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 only, as published by the Free Software Foundation.
+ *
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ */
+
+/* FIXME - some of these can probably be removed */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/poll.h>
+#include <linux/io.h>
+#include <asm/div64.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/timer.h>
+#include <linux/byteorder/generic.h>
+#include <linux/firmware.h>
+#include <linux/vmalloc.h>
+
+#include "ngene.h"
+
+/* Firmware command for i2c operations */
+static int ngene_command_i2c_read(struct ngene *dev, u8 adr,
+			   u8 *out, u8 outlen, u8 *in, u8 inlen, int flag)
+{
+	struct ngene_command com;
+
+	com.cmd.hdr.Opcode = CMD_I2C_READ;
+	com.cmd.hdr.Length = outlen + 3;
+	com.cmd.I2CRead.Device = adr << 1;
+	memcpy(com.cmd.I2CRead.Data, out, outlen);
+	com.cmd.I2CRead.Data[outlen] = inlen;
+	com.cmd.I2CRead.Data[outlen + 1] = 0;
+	com.in_len = outlen + 3;
+	com.out_len = inlen + 1;
+
+	if (ngene_command(dev, &com) < 0)
+		return -EIO;
+
+	if ((com.cmd.raw8[0] >> 1) != adr)
+		return -EIO;
+
+	if (flag)
+		memcpy(in, com.cmd.raw8, inlen + 1);
+	else
+		memcpy(in, com.cmd.raw8 + 1, inlen);
+	return 0;
+}
+
+static int ngene_command_i2c_write(struct ngene *dev, u8 adr,
+				   u8 *out, u8 outlen)
+{
+	struct ngene_command com;
+
+
+	com.cmd.hdr.Opcode = CMD_I2C_WRITE;
+	com.cmd.hdr.Length = outlen + 1;
+	com.cmd.I2CRead.Device = adr << 1;
+	memcpy(com.cmd.I2CRead.Data, out, outlen);
+	com.in_len = outlen + 1;
+	com.out_len = 1;
+
+	if (ngene_command(dev, &com) < 0)
+		return -EIO;
+
+	if (com.cmd.raw8[0] == 1)
+		return -EIO;
+
+	return 0;
+}
+
+static void ngene_i2c_set_bus(struct ngene *dev, int bus)
+{
+	if (!(dev->card_info->i2c_access & 2))
+		return;
+	if (dev->i2c_current_bus == bus)
+		return;
+
+	switch (bus) {
+	case 0:
+		ngene_command_gpio_set(dev, 3, 0);
+		ngene_command_gpio_set(dev, 2, 1);
+		break;
+
+	case 1:
+		ngene_command_gpio_set(dev, 2, 0);
+		ngene_command_gpio_set(dev, 3, 1);
+		break;
+	}
+	dev->i2c_current_bus = bus;
+}
+
+static int ngene_i2c_master_xfer(struct i2c_adapter *adapter,
+				 struct i2c_msg msg[], int num)
+{
+	struct ngene_channel *chan =
+		(struct ngene_channel *)i2c_get_adapdata(adapter);
+	struct ngene *dev = chan->dev;
+
+	down(&dev->i2c_switch_mutex);
+	ngene_i2c_set_bus(dev, chan->number);
+
+	if (num == 2 && msg[1].flags & I2C_M_RD && !(msg[0].flags & I2C_M_RD))
+		if (!ngene_command_i2c_read(dev, msg[0].addr,
+					    msg[0].buf, msg[0].len,
+					    msg[1].buf, msg[1].len, 0))
+			goto done;
+
+	if (num == 1 && !(msg[0].flags & I2C_M_RD))
+		if (!ngene_command_i2c_write(dev, msg[0].addr,
+					     msg[0].buf, msg[0].len))
+			goto done;
+	if (num == 1 && (msg[0].flags & I2C_M_RD))
+		if (!ngene_command_i2c_read(dev, msg[0].addr, NULL, 0,
+					    msg[0].buf, msg[0].len, 0))
+			goto done;
+
+	up(&dev->i2c_switch_mutex);
+	return -EIO;
+
+done:
+	up(&dev->i2c_switch_mutex);
+	return num;
+}
+
+
+static u32 ngene_i2c_functionality(struct i2c_adapter *adap)
+{
+	return I2C_FUNC_SMBUS_EMUL;
+}
+
+static struct i2c_algorithm ngene_i2c_algo = {
+	.master_xfer = ngene_i2c_master_xfer,
+	.functionality = ngene_i2c_functionality,
+};
+
+int ngene_i2c_init(struct ngene *dev, int dev_nr)
+{
+	struct i2c_adapter *adap = &(dev->channel[dev_nr].i2c_adapter);
+
+	i2c_set_adapdata(adap, &(dev->channel[dev_nr]));
+
+	strcpy(adap->name, "nGene");
+
+	adap->algo = &ngene_i2c_algo;
+	adap->algo_data = (void *)&(dev->channel[dev_nr]);
+	adap->dev.parent = &dev->pci_dev->dev;
+
+	return i2c_add_adapter(adap);
+}
+
diff --git a/drivers/media/pci/ngene/ngene.h b/drivers/media/pci/ngene/ngene.h
new file mode 100644
index 0000000..5443dc0
--- /dev/null
+++ b/drivers/media/pci/ngene/ngene.h
@@ -0,0 +1,921 @@
+/*
+ * ngene.h: nGene PCIe bridge driver
+ *
+ * Copyright (C) 2005-2007 Micronas
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 only, as published by the Free Software Foundation.
+ *
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ */
+
+#ifndef _NGENE_H_
+#define _NGENE_H_
+
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <asm/dma.h>
+#include <linux/scatterlist.h>
+
+#include <linux/dvb/frontend.h>
+
+#include "dmxdev.h"
+#include "dvbdev.h"
+#include "dvb_demux.h"
+#include "dvb_ca_en50221.h"
+#include "dvb_frontend.h"
+#include "dvb_ringbuffer.h"
+#include "dvb_net.h"
+#include "cxd2099.h"
+
+#define DEVICE_NAME "ngene"
+
+#define NGENE_VID       0x18c3
+#define NGENE_PID       0x0720
+
+#ifndef VIDEO_CAP_VC1
+#define VIDEO_CAP_AVC   128
+#define VIDEO_CAP_H264  128
+#define VIDEO_CAP_VC1   256
+#define VIDEO_CAP_WMV9  256
+#define VIDEO_CAP_MPEG4 512
+#endif
+
+enum STREAM {
+	STREAM_VIDEOIN1 = 0,        /* ITU656 or TS Input */
+	STREAM_VIDEOIN2,
+	STREAM_AUDIOIN1,            /* I2S or SPI Input */
+	STREAM_AUDIOIN2,
+	STREAM_AUDIOOUT,
+	MAX_STREAM
+};
+
+enum SMODE_BITS {
+	SMODE_AUDIO_SPDIF = 0x20,
+	SMODE_AVSYNC = 0x10,
+	SMODE_TRANSPORT_STREAM = 0x08,
+	SMODE_AUDIO_CAPTURE = 0x04,
+	SMODE_VBI_CAPTURE = 0x02,
+	SMODE_VIDEO_CAPTURE = 0x01
+};
+
+enum STREAM_FLAG_BITS {
+	SFLAG_CHROMA_FORMAT_2COMP  = 0x01, /* Chroma Format : 2's complement */
+	SFLAG_CHROMA_FORMAT_OFFSET = 0x00, /* Chroma Format : Binary offset */
+	SFLAG_ORDER_LUMA_CHROMA    = 0x02, /* Byte order: Y,Cb,Y,Cr */
+	SFLAG_ORDER_CHROMA_LUMA    = 0x00, /* Byte order: Cb,Y,Cr,Y */
+	SFLAG_COLORBAR             = 0x04, /* Select colorbar */
+};
+
+#define PROGRAM_ROM     0x0000
+#define PROGRAM_SRAM    0x1000
+#define PERIPHERALS0    0x8000
+#define PERIPHERALS1    0x9000
+#define SHARED_BUFFER   0xC000
+
+#define HOST_TO_NGENE    (SHARED_BUFFER+0x0000)
+#define NGENE_TO_HOST    (SHARED_BUFFER+0x0100)
+#define NGENE_COMMAND    (SHARED_BUFFER+0x0200)
+#define NGENE_COMMAND_HI (SHARED_BUFFER+0x0204)
+#define NGENE_STATUS     (SHARED_BUFFER+0x0208)
+#define NGENE_STATUS_HI  (SHARED_BUFFER+0x020C)
+#define NGENE_EVENT      (SHARED_BUFFER+0x0210)
+#define NGENE_EVENT_HI   (SHARED_BUFFER+0x0214)
+#define VARIABLES        (SHARED_BUFFER+0x0210)
+
+#define NGENE_INT_COUNTS       (SHARED_BUFFER+0x0260)
+#define NGENE_INT_ENABLE       (SHARED_BUFFER+0x0264)
+#define NGENE_VBI_LINE_COUNT   (SHARED_BUFFER+0x0268)
+
+#define BUFFER_GP_XMIT  (SHARED_BUFFER+0x0800)
+#define BUFFER_GP_RECV  (SHARED_BUFFER+0x0900)
+#define EEPROM_AREA     (SHARED_BUFFER+0x0A00)
+
+#define SG_V_IN_1       (SHARED_BUFFER+0x0A80)
+#define SG_VBI_1        (SHARED_BUFFER+0x0B00)
+#define SG_A_IN_1       (SHARED_BUFFER+0x0B80)
+#define SG_V_IN_2       (SHARED_BUFFER+0x0C00)
+#define SG_VBI_2        (SHARED_BUFFER+0x0C80)
+#define SG_A_IN_2       (SHARED_BUFFER+0x0D00)
+#define SG_V_OUT        (SHARED_BUFFER+0x0D80)
+#define SG_A_OUT2       (SHARED_BUFFER+0x0E00)
+
+#define DATA_A_IN_1     (SHARED_BUFFER+0x0E80)
+#define DATA_A_IN_2     (SHARED_BUFFER+0x0F00)
+#define DATA_A_OUT      (SHARED_BUFFER+0x0F80)
+#define DATA_V_IN_1     (SHARED_BUFFER+0x1000)
+#define DATA_V_IN_2     (SHARED_BUFFER+0x2000)
+#define DATA_V_OUT      (SHARED_BUFFER+0x3000)
+
+#define DATA_FIFO_AREA  (SHARED_BUFFER+0x1000)
+
+#define TIMESTAMPS      0xA000
+#define SCRATCHPAD      0xA080
+#define FORCE_INT       0xA088
+#define FORCE_NMI       0xA090
+#define INT_STATUS      0xA0A0
+
+#define DEV_VER         0x9004
+
+#define FW_DEBUG_DEFAULT (PROGRAM_SRAM+0x00FF)
+
+struct SG_ADDR {
+	u64 start;
+	u64 curr;
+	u16 curr_ptr;
+	u16 elements;
+	u32 pad[3];
+} __attribute__ ((__packed__));
+
+struct SHARED_MEMORY {
+	/* C000 */
+	u32 HostToNgene[64];
+
+	/* C100 */
+	u32 NgeneToHost[64];
+
+	/* C200 */
+	u64 NgeneCommand;
+	u64 NgeneStatus;
+	u64 NgeneEvent;
+
+	/* C210 */
+	u8 pad1[0xc260 - 0xc218];
+
+	/* C260 */
+	u32 IntCounts;
+	u32 IntEnable;
+
+	/* C268 */
+	u8 pad2[0xd000 - 0xc268];
+
+} __attribute__ ((__packed__));
+
+struct BUFFER_STREAM_RESULTS {
+	u32 Clock;           /* Stream time in 100ns units */
+	u16 RemainingLines;  /* Remaining lines in this field.
+				0 for complete field */
+	u8  FieldCount;      /* Video field number */
+	u8  Flags;           /* Bit 7 = Done, Bit 6 = seen, Bit 5 = overflow,
+				Bit 0 = FieldID */
+	u16 BlockCount;      /* Audio block count (unused) */
+	u8  Reserved[2];
+	u32 DTOUpdate;
+} __attribute__ ((__packed__));
+
+struct HW_SCATTER_GATHER_ELEMENT {
+	u64 Address;
+	u32 Length;
+	u32 Reserved;
+} __attribute__ ((__packed__));
+
+struct BUFFER_HEADER {
+	u64    Next;
+	struct BUFFER_STREAM_RESULTS SR;
+
+	u32    Number_of_entries_1;
+	u32    Reserved5;
+	u64    Address_of_first_entry_1;
+
+	u32    Number_of_entries_2;
+	u32    Reserved7;
+	u64    Address_of_first_entry_2;
+} __attribute__ ((__packed__));
+
+struct EVENT_BUFFER {
+	u32    TimeStamp;
+	u8     GPIOStatus;
+	u8     UARTStatus;
+	u8     RXCharacter;
+	u8     EventStatus;
+	u32    Reserved[2];
+} __attribute__ ((__packed__));
+
+/* Firmware commands. */
+
+enum OPCODES {
+	CMD_NOP = 0,
+	CMD_FWLOAD_PREPARE  = 0x01,
+	CMD_FWLOAD_FINISH   = 0x02,
+	CMD_I2C_READ        = 0x03,
+	CMD_I2C_WRITE       = 0x04,
+
+	CMD_I2C_WRITE_NOSTOP = 0x05,
+	CMD_I2C_CONTINUE_WRITE = 0x06,
+	CMD_I2C_CONTINUE_WRITE_NOSTOP = 0x07,
+
+	CMD_DEBUG_OUTPUT    = 0x09,
+
+	CMD_CONTROL         = 0x10,
+	CMD_CONFIGURE_BUFFER = 0x11,
+	CMD_CONFIGURE_FREE_BUFFER = 0x12,
+
+	CMD_SPI_READ        = 0x13,
+	CMD_SPI_WRITE       = 0x14,
+
+	CMD_MEM_READ        = 0x20,
+	CMD_MEM_WRITE	    = 0x21,
+	CMD_SFR_READ	    = 0x22,
+	CMD_SFR_WRITE	    = 0x23,
+	CMD_IRAM_READ	    = 0x24,
+	CMD_IRAM_WRITE	    = 0x25,
+	CMD_SET_GPIO_PIN    = 0x26,
+	CMD_SET_GPIO_INT    = 0x27,
+	CMD_CONFIGURE_UART  = 0x28,
+	CMD_WRITE_UART      = 0x29,
+	MAX_CMD
+};
+
+enum RESPONSES {
+	OK = 0,
+	ERROR = 1
+};
+
+struct FW_HEADER {
+	u8 Opcode;
+	u8 Length;
+} __attribute__ ((__packed__));
+
+struct FW_I2C_WRITE {
+	struct FW_HEADER hdr;
+	u8 Device;
+	u8 Data[250];
+} __attribute__ ((__packed__));
+
+struct FW_I2C_CONTINUE_WRITE {
+	struct FW_HEADER hdr;
+	u8 Data[250];
+} __attribute__ ((__packed__));
+
+struct FW_I2C_READ {
+	struct FW_HEADER hdr;
+	u8 Device;
+	u8 Data[252];    /* followed by two bytes of read data count */
+} __attribute__ ((__packed__));
+
+struct FW_SPI_WRITE {
+	struct FW_HEADER hdr;
+	u8 ModeSelect;
+	u8 Data[250];
+} __attribute__ ((__packed__));
+
+struct FW_SPI_READ {
+	struct FW_HEADER hdr;
+	u8 ModeSelect;
+	u8 Data[252];    /* followed by two bytes of read data count */
+} __attribute__ ((__packed__));
+
+struct FW_FWLOAD_PREPARE {
+	struct FW_HEADER hdr;
+} __attribute__ ((__packed__));
+
+struct FW_FWLOAD_FINISH {
+	struct FW_HEADER hdr;
+	u16 Address;     /* address of final block */
+	u16 Length;
+} __attribute__ ((__packed__));
+
+/*
+ * Meaning of FW_STREAM_CONTROL::Mode bits:
+ *  Bit 7: Loopback PEXin to PEXout using TVOut channel
+ *  Bit 6: AVLOOP
+ *  Bit 5: Audio select; 0=I2S, 1=SPDIF
+ *  Bit 4: AVSYNC
+ *  Bit 3: Enable transport stream
+ *  Bit 2: Enable audio capture
+ *  Bit 1: Enable ITU-Video VBI capture
+ *  Bit 0: Enable ITU-Video capture
+ *
+ * Meaning of FW_STREAM_CONTROL::Control bits (see UVI1_CTL)
+ *  Bit 7: continuous capture
+ *  Bit 6: capture one field
+ *  Bit 5: capture one frame
+ *  Bit 4: unused
+ *  Bit 3: starting field; 0=odd, 1=even
+ *  Bit 2: sample size; 0=8-bit, 1=10-bit
+ *  Bit 1: data format; 0=UYVY, 1=YUY2
+ *  Bit 0: resets buffer pointers
+*/
+
+enum FSC_MODE_BITS {
+	SMODE_LOOPBACK          = 0x80,
+	SMODE_AVLOOP            = 0x40,
+	_SMODE_AUDIO_SPDIF      = 0x20,
+	_SMODE_AVSYNC           = 0x10,
+	_SMODE_TRANSPORT_STREAM = 0x08,
+	_SMODE_AUDIO_CAPTURE    = 0x04,
+	_SMODE_VBI_CAPTURE      = 0x02,
+	_SMODE_VIDEO_CAPTURE    = 0x01
+};
+
+
+/* Meaning of FW_STREAM_CONTROL::Stream bits:
+ * Bit 3: Audio sample count:  0 = relative, 1 = absolute
+ * Bit 2: color bar select; 1=color bars, 0=CV3 decoder
+ * Bits 1-0: stream select, UVI1, UVI2, TVOUT
+ */
+
+struct FW_STREAM_CONTROL {
+	struct FW_HEADER hdr;
+	u8     Stream;             /* Stream number (UVI1, UVI2, TVOUT) */
+	u8     Control;            /* Value written to UVI1_CTL */
+	u8     Mode;               /* Controls clock source */
+	u8     SetupDataLen;	   /* Length of setup data, MSB=1 write
+				      backwards */
+	u16    CaptureBlockCount;  /* Blocks (a 256 Bytes) to capture per buffer
+				      for TS and Audio */
+	u64    Buffer_Address;	   /* Address of first buffer header */
+	u16    BytesPerVideoLine;
+	u16    MaxLinesPerField;
+	u16    MinLinesPerField;
+	u16    Reserved_1;
+	u16    BytesPerVBILine;
+	u16    MaxVBILinesPerField;
+	u16    MinVBILinesPerField;
+	u16    SetupDataAddr;      /* ngene relative address of setup data */
+	u8     SetupData[32];      /* setup data */
+} __attribute__((__packed__));
+
+#define AUDIO_BLOCK_SIZE    256
+#define TS_BLOCK_SIZE       256
+
+struct FW_MEM_READ {
+	struct FW_HEADER hdr;
+	u16   address;
+} __attribute__ ((__packed__));
+
+struct FW_MEM_WRITE {
+	struct FW_HEADER hdr;
+	u16   address;
+	u8    data;
+} __attribute__ ((__packed__));
+
+struct FW_SFR_IRAM_READ {
+	struct FW_HEADER hdr;
+	u8    address;
+} __attribute__ ((__packed__));
+
+struct FW_SFR_IRAM_WRITE {
+	struct FW_HEADER hdr;
+	u8    address;
+	u8    data;
+} __attribute__ ((__packed__));
+
+struct FW_SET_GPIO_PIN {
+	struct FW_HEADER hdr;
+	u8    select;
+} __attribute__ ((__packed__));
+
+struct FW_SET_GPIO_INT {
+	struct FW_HEADER hdr;
+	u8    select;
+} __attribute__ ((__packed__));
+
+struct FW_SET_DEBUGMODE {
+	struct FW_HEADER hdr;
+	u8   debug_flags;
+} __attribute__ ((__packed__));
+
+struct FW_CONFIGURE_BUFFERS {
+	struct FW_HEADER hdr;
+	u8   config;
+} __attribute__ ((__packed__));
+
+enum _BUFFER_CONFIGS {
+	/* 4k UVI1, 4k UVI2, 2k AUD1, 2k AUD2  (standard usage) */
+	BUFFER_CONFIG_4422 = 0,
+	/* 3k UVI1, 3k UVI2, 3k AUD1, 3k AUD2  (4x TS input usage) */
+	BUFFER_CONFIG_3333 = 1,
+	/* 8k UVI1, 0k UVI2, 2k AUD1, 2k I2SOut  (HDTV decoder usage) */
+	BUFFER_CONFIG_8022 = 2,
+	BUFFER_CONFIG_FW17 = 255, /* Use new FW 17 command */
+};
+
+struct FW_CONFIGURE_FREE_BUFFERS {
+	struct FW_HEADER hdr;
+	u8   UVI1_BufferLength;
+	u8   UVI2_BufferLength;
+	u8   TVO_BufferLength;
+	u8   AUD1_BufferLength;
+	u8   AUD2_BufferLength;
+	u8   TVA_BufferLength;
+} __attribute__ ((__packed__));
+
+struct FW_CONFIGURE_UART {
+	struct FW_HEADER hdr;
+	u8 UartControl;
+} __attribute__ ((__packed__));
+
+enum _UART_CONFIG {
+	_UART_BAUDRATE_19200 = 0,
+	_UART_BAUDRATE_9600  = 1,
+	_UART_BAUDRATE_4800  = 2,
+	_UART_BAUDRATE_2400  = 3,
+	_UART_RX_ENABLE      = 0x40,
+	_UART_TX_ENABLE      = 0x80,
+};
+
+struct FW_WRITE_UART {
+	struct FW_HEADER hdr;
+	u8 Data[252];
+} __attribute__ ((__packed__));
+
+
+struct ngene_command {
+	u32 in_len;
+	u32 out_len;
+	union {
+		u32                              raw[64];
+		u8                               raw8[256];
+		struct FW_HEADER                 hdr;
+		struct FW_I2C_WRITE              I2CWrite;
+		struct FW_I2C_CONTINUE_WRITE     I2CContinueWrite;
+		struct FW_I2C_READ               I2CRead;
+		struct FW_STREAM_CONTROL         StreamControl;
+		struct FW_FWLOAD_PREPARE         FWLoadPrepare;
+		struct FW_FWLOAD_FINISH          FWLoadFinish;
+		struct FW_MEM_READ		 MemoryRead;
+		struct FW_MEM_WRITE		 MemoryWrite;
+		struct FW_SFR_IRAM_READ		 SfrIramRead;
+		struct FW_SFR_IRAM_WRITE         SfrIramWrite;
+		struct FW_SPI_WRITE              SPIWrite;
+		struct FW_SPI_READ               SPIRead;
+		struct FW_SET_GPIO_PIN           SetGpioPin;
+		struct FW_SET_GPIO_INT           SetGpioInt;
+		struct FW_SET_DEBUGMODE          SetDebugMode;
+		struct FW_CONFIGURE_BUFFERS      ConfigureBuffers;
+		struct FW_CONFIGURE_FREE_BUFFERS ConfigureFreeBuffers;
+		struct FW_CONFIGURE_UART         ConfigureUart;
+		struct FW_WRITE_UART             WriteUart;
+	} cmd;
+} __attribute__ ((__packed__));
+
+#define NGENE_INTERFACE_VERSION 0x103
+#define MAX_VIDEO_BUFFER_SIZE   (417792) /* 288*1440 rounded up to next page */
+#define MAX_AUDIO_BUFFER_SIZE     (8192) /* Gives room for about 23msec@48KHz */
+#define MAX_VBI_BUFFER_SIZE      (28672) /* 1144*18 rounded up to next page */
+#define MAX_TS_BUFFER_SIZE       (98304) /* 512*188 rounded up to next page */
+#define MAX_HDTV_BUFFER_SIZE   (2080768) /* 541*1920*2 rounded up to next page
+					    Max: (1920x1080i60) */
+
+#define OVERFLOW_BUFFER_SIZE    (8192)
+
+#define RING_SIZE_VIDEO     4
+#define RING_SIZE_AUDIO     8
+#define RING_SIZE_TS        8
+
+#define NUM_SCATTER_GATHER_ENTRIES  8
+
+#define MAX_DMA_LENGTH (((MAX_VIDEO_BUFFER_SIZE + MAX_VBI_BUFFER_SIZE) * \
+			RING_SIZE_VIDEO * 2) + \
+			(MAX_AUDIO_BUFFER_SIZE * RING_SIZE_AUDIO * 2) + \
+			(MAX_TS_BUFFER_SIZE * RING_SIZE_TS * 4) + \
+			(RING_SIZE_VIDEO * PAGE_SIZE * 2) + \
+			(RING_SIZE_AUDIO * PAGE_SIZE * 2) + \
+			(RING_SIZE_TS    * PAGE_SIZE * 4) + \
+			 8 * PAGE_SIZE + OVERFLOW_BUFFER_SIZE + PAGE_SIZE)
+
+#define EVENT_QUEUE_SIZE    16
+
+/* Gathers the current state of a single channel. */
+
+struct SBufferHeader {
+	struct BUFFER_HEADER   ngeneBuffer; /* Physical descriptor */
+	struct SBufferHeader  *Next;
+	void                  *Buffer1;
+	struct HW_SCATTER_GATHER_ELEMENT *scList1;
+	void                  *Buffer2;
+	struct HW_SCATTER_GATHER_ELEMENT *scList2;
+};
+
+/* Sizeof SBufferHeader aligned to next 64 Bit boundary (hw restriction) */
+#define SIZEOF_SBufferHeader ((sizeof(struct SBufferHeader) + 63) & ~63)
+
+enum HWSTATE {
+	HWSTATE_STOP,
+	HWSTATE_STARTUP,
+	HWSTATE_RUN,
+	HWSTATE_PAUSE,
+};
+
+enum KSSTATE {
+	KSSTATE_STOP,
+	KSSTATE_ACQUIRE,
+	KSSTATE_PAUSE,
+	KSSTATE_RUN,
+};
+
+struct SRingBufferDescriptor {
+	struct SBufferHeader *Head; /* Points to first buffer in ring buffer
+				       structure*/
+	u64   PAHead;         /* Physical address of first buffer */
+	u32   MemSize;        /* Memory size of allocated ring buffers
+				 (needed for freeing) */
+	u32   NumBuffers;     /* Number of buffers in the ring */
+	u32   Buffer1Length;  /* Allocated length of Buffer 1 */
+	u32   Buffer2Length;  /* Allocated length of Buffer 2 */
+	void *SCListMem;      /* Memory to hold scatter gather lists for this
+				 ring */
+	u64   PASCListMem;    /* Physical address  .. */
+	u32   SCListMemSize;  /* Size of this memory */
+};
+
+enum STREAMMODEFLAGS {
+	StreamMode_NONE   = 0, /* Stream not used */
+	StreamMode_ANALOG = 1, /* Analog: Stream 0,1 = Video, 2,3 = Audio */
+	StreamMode_TSIN   = 2, /* Transport stream input (all) */
+	StreamMode_HDTV   = 4, /* HDTV: Maximum 1920x1080p30,1920x1080i60
+				  (only stream 0) */
+	StreamMode_TSOUT  = 8, /* Transport stream output (only stream 3) */
+};
+
+
+enum BufferExchangeFlags {
+	BEF_EVEN_FIELD   = 0x00000001,
+	BEF_CONTINUATION = 0x00000002,
+	BEF_MORE_DATA    = 0x00000004,
+	BEF_OVERFLOW     = 0x00000008,
+	DF_SWAP32        = 0x00010000,
+};
+
+typedef void *(IBufferExchange)(void *, void *, u32, u32, u32);
+
+struct MICI_STREAMINFO {
+	IBufferExchange    *pExchange;
+	IBufferExchange    *pExchangeVBI;     /* Secondary (VBI, ancillary) */
+	u8  Stream;
+	u8  Flags;
+	u8  Mode;
+	u8  Reserved;
+	u16 nLinesVideo;
+	u16 nBytesPerLineVideo;
+	u16 nLinesVBI;
+	u16 nBytesPerLineVBI;
+	u32 CaptureLength;    /* Used for audio and transport stream */
+};
+
+/****************************************************************************/
+/* STRUCTS ******************************************************************/
+/****************************************************************************/
+
+/* sound hardware definition */
+#define MIXER_ADDR_TVTUNER      0
+#define MIXER_ADDR_LAST         0
+
+struct ngene_channel;
+
+/*struct sound chip*/
+
+struct mychip {
+	struct ngene_channel *chan;
+	struct snd_card *card;
+	struct pci_dev *pci;
+	struct snd_pcm_substream *substream;
+	struct snd_pcm *pcm;
+	unsigned long port;
+	int irq;
+	spinlock_t mixer_lock;
+	spinlock_t lock;
+	int mixer_volume[MIXER_ADDR_LAST + 1][2];
+	int capture_source[MIXER_ADDR_LAST + 1][2];
+};
+
+#ifdef NGENE_V4L
+struct ngene_overlay {
+	int                    tvnorm;
+	struct v4l2_rect       w;
+	enum v4l2_field        field;
+	struct v4l2_clip       *clips;
+	int                    nclips;
+	int                    setup_ok;
+};
+
+struct ngene_tvnorm {
+	int   v4l2_id;
+	char  *name;
+	u16   swidth, sheight; /* scaled standard width, height */
+	int   tuner_norm;
+	int   soundstd;
+};
+
+struct ngene_vopen {
+	struct ngene_channel      *ch;
+	enum v4l2_priority         prio;
+	int                        width;
+	int                        height;
+	int                        depth;
+	struct videobuf_queue      vbuf_q;
+	struct videobuf_queue      vbi;
+	int                        fourcc;
+	int                        picxcount;
+	int                        resources;
+	enum v4l2_buf_type         type;
+	const struct ngene_format *fmt;
+
+	const struct ngene_format *ovfmt;
+	struct ngene_overlay       ov;
+};
+#endif
+
+struct ngene_channel {
+	struct device         device;
+	struct i2c_adapter    i2c_adapter;
+
+	struct ngene         *dev;
+	int                   number;
+	int                   type;
+	int                   mode;
+	bool                  has_adapter;
+	bool                  has_demux;
+	int                   demod_type;
+	int (*gate_ctrl)(struct dvb_frontend *, int);
+
+	struct dvb_frontend  *fe;
+	struct dvb_frontend  *fe2;
+	struct dmxdev         dmxdev;
+	struct dvb_demux      demux;
+	struct dvb_net        dvbnet;
+	struct dmx_frontend   hw_frontend;
+	struct dmx_frontend   mem_frontend;
+	int                   users;
+	struct video_device  *v4l_dev;
+	struct dvb_device    *ci_dev;
+	struct tasklet_struct demux_tasklet;
+
+	struct SBufferHeader *nextBuffer;
+	enum KSSTATE          State;
+	enum HWSTATE          HWState;
+	u8                    Stream;
+	u8                    Flags;
+	u8                    Mode;
+	IBufferExchange      *pBufferExchange;
+	IBufferExchange      *pBufferExchange2;
+
+	spinlock_t            state_lock;
+	u16                   nLines;
+	u16                   nBytesPerLine;
+	u16                   nVBILines;
+	u16                   nBytesPerVBILine;
+	u16                   itumode;
+	u32                   Capture1Length;
+	u32                   Capture2Length;
+	struct SRingBufferDescriptor RingBuffer;
+	struct SRingBufferDescriptor TSRingBuffer;
+	struct SRingBufferDescriptor TSIdleBuffer;
+
+	u32                   DataFormatFlags;
+
+	int                   AudioDTOUpdated;
+	u32                   AudioDTOValue;
+
+	int (*set_tone)(struct dvb_frontend *, fe_sec_tone_mode_t);
+	u8 lnbh;
+
+	/* stuff from analog driver */
+
+	int minor;
+	struct mychip        *mychip;
+	struct snd_card      *soundcard;
+	u8                   *evenbuffer;
+	u8                    dma_on;
+	int                   soundstreamon;
+	int                   audiomute;
+	int                   soundbuffisallocated;
+	int                   sndbuffflag;
+	int                   tun_rdy;
+	int                   dec_rdy;
+	int                   tun_dec_rdy;
+	int                   lastbufferflag;
+
+	struct ngene_tvnorm  *tvnorms;
+	int                   tvnorm_num;
+	int                   tvnorm;
+
+#ifdef NGENE_V4L
+	int                   videousers;
+	struct v4l2_prio_state prio;
+	struct ngene_vopen    init;
+	int                   resources;
+	struct v4l2_framebuffer fbuf;
+	struct ngene_buffer  *screen;     /* overlay             */
+	struct list_head      capture;    /* video capture queue */
+	spinlock_t s_lock;
+	struct semaphore reslock;
+#endif
+
+	int running;
+};
+
+
+struct ngene_ci {
+	struct device         device;
+	struct i2c_adapter    i2c_adapter;
+
+	struct ngene         *dev;
+	struct dvb_ca_en50221 *en;
+};
+
+struct ngene;
+
+typedef void (rx_cb_t)(struct ngene *, u32, u8);
+typedef void (tx_cb_t)(struct ngene *, u32);
+
+struct ngene {
+	int                   nr;
+	struct pci_dev       *pci_dev;
+	unsigned char        *iomem;
+
+	/*struct i2c_adapter  i2c_adapter;*/
+
+	u32                   device_version;
+	u32                   fw_interface_version;
+	u32                   icounts;
+	bool                  msi_enabled;
+	bool                  cmd_timeout_workaround;
+
+	u8                   *CmdDoneByte;
+	int                   BootFirmware;
+	void                 *OverflowBuffer;
+	dma_addr_t            PAOverflowBuffer;
+	void                 *FWInterfaceBuffer;
+	dma_addr_t            PAFWInterfaceBuffer;
+	u8                   *ngenetohost;
+	u8                   *hosttongene;
+
+	struct EVENT_BUFFER   EventQueue[EVENT_QUEUE_SIZE];
+	int                   EventQueueOverflowCount;
+	int                   EventQueueOverflowFlag;
+	struct tasklet_struct event_tasklet;
+	struct EVENT_BUFFER  *EventBuffer;
+	int                   EventQueueWriteIndex;
+	int                   EventQueueReadIndex;
+
+	wait_queue_head_t     cmd_wq;
+	int                   cmd_done;
+	struct semaphore      cmd_mutex;
+	struct semaphore      stream_mutex;
+	struct semaphore      pll_mutex;
+	struct semaphore      i2c_switch_mutex;
+	int                   i2c_current_channel;
+	int                   i2c_current_bus;
+	spinlock_t            cmd_lock;
+
+	struct dvb_adapter    adapter[MAX_STREAM];
+	struct dvb_adapter    *first_adapter; /* "one_adapter" modprobe opt */
+	struct ngene_channel  channel[MAX_STREAM];
+
+	struct ngene_info    *card_info;
+
+	tx_cb_t              *TxEventNotify;
+	rx_cb_t              *RxEventNotify;
+	int                   tx_busy;
+	wait_queue_head_t     tx_wq;
+	wait_queue_head_t     rx_wq;
+#define UART_RBUF_LEN 4096
+	u8                    uart_rbuf[UART_RBUF_LEN];
+	int                   uart_rp, uart_wp;
+
+#define TS_FILLER  0x6f
+
+	u8                   *tsout_buf;
+#define TSOUT_BUF_SIZE (512*188*8)
+	struct dvb_ringbuffer tsout_rbuf;
+
+	u8                   *tsin_buf;
+#define TSIN_BUF_SIZE (512*188*8)
+	struct dvb_ringbuffer tsin_rbuf;
+
+	u8                   *ain_buf;
+#define AIN_BUF_SIZE (128*1024)
+	struct dvb_ringbuffer ain_rbuf;
+
+
+	u8                   *vin_buf;
+#define VIN_BUF_SIZE (4*1920*1080)
+	struct dvb_ringbuffer vin_rbuf;
+
+	unsigned long         exp_val;
+	int prev_cmd;
+
+	struct ngene_ci       ci;
+};
+
+struct ngene_info {
+	int   type;
+#define NGENE_APP        0
+#define NGENE_TERRATEC   1
+#define NGENE_SIDEWINDER 2
+#define NGENE_RACER      3
+#define NGENE_VIPER      4
+#define NGENE_PYTHON     5
+#define NGENE_VBOX_V1	 6
+#define NGENE_VBOX_V2	 7
+
+	int   fw_version;
+	bool  msi_supported;
+	char *name;
+
+	int   io_type[MAX_STREAM];
+#define NGENE_IO_NONE    0
+#define NGENE_IO_TV      1
+#define NGENE_IO_HDTV    2
+#define NGENE_IO_TSIN    4
+#define NGENE_IO_TSOUT   8
+#define NGENE_IO_AIN     16
+
+	void *fe_config[4];
+	void *tuner_config[4];
+
+	int (*demod_attach[4])(struct ngene_channel *);
+	int (*tuner_attach[4])(struct ngene_channel *);
+
+	u8    avf[4];
+	u8    msp[4];
+	u8    demoda[4];
+	u8    lnb[4];
+	int   i2c_access;
+	u8    ntsc;
+	u8    tsf[4];
+	u8    i2s[4];
+
+	int (*gate_ctrl)(struct dvb_frontend *, int);
+	int (*switch_ctrl)(struct ngene_channel *, int, int);
+};
+
+#ifdef NGENE_V4L
+struct ngene_format {
+	char *name;
+	int   fourcc;          /* video4linux 2      */
+	int   btformat;        /* BT848_COLOR_FMT_*  */
+	int   format;
+	int   btswap;          /* BT848_COLOR_CTL_*  */
+	int   depth;           /* bit/pixel          */
+	int   flags;
+	int   hshift, vshift;  /* for planar modes   */
+	int   palette;
+};
+
+#define RESOURCE_OVERLAY       1
+#define RESOURCE_VIDEO         2
+#define RESOURCE_VBI           4
+
+struct ngene_buffer {
+	/* common v4l buffer stuff -- must be first */
+	struct videobuf_buffer     vb;
+
+	/* ngene specific */
+	const struct ngene_format *fmt;
+	int                        tvnorm;
+	int                        btformat;
+	int                        btswap;
+};
+#endif
+
+
+/* Provided by ngene-core.c */
+int __devinit ngene_probe(struct pci_dev *pci_dev,
+			  const struct pci_device_id *id);
+void __devexit ngene_remove(struct pci_dev *pdev);
+void ngene_shutdown(struct pci_dev *pdev);
+int ngene_command(struct ngene *dev, struct ngene_command *com);
+int ngene_command_gpio_set(struct ngene *dev, u8 select, u8 level);
+void set_transfer(struct ngene_channel *chan, int state);
+void FillTSBuffer(void *Buffer, int Length, u32 Flags);
+
+/* Provided by ngene-i2c.c */
+int ngene_i2c_init(struct ngene *dev, int dev_nr);
+
+/* Provided by ngene-dvb.c */
+extern struct dvb_device ngene_dvbdev_ci;
+void *tsout_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags);
+void *tsin_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags);
+int ngene_start_feed(struct dvb_demux_feed *dvbdmxfeed);
+int ngene_stop_feed(struct dvb_demux_feed *dvbdmxfeed);
+int my_dvb_dmx_ts_card_init(struct dvb_demux *dvbdemux, char *id,
+			    int (*start_feed)(struct dvb_demux_feed *),
+			    int (*stop_feed)(struct dvb_demux_feed *),
+			    void *priv);
+int my_dvb_dmxdev_ts_card_init(struct dmxdev *dmxdev,
+			       struct dvb_demux *dvbdemux,
+			       struct dmx_frontend *hw_frontend,
+			       struct dmx_frontend *mem_frontend,
+			       struct dvb_adapter *dvb_adapter);
+
+#endif
+
+/*  LocalWords:  Endif
+ */
diff --git a/drivers/media/pci/pluto2/Kconfig b/drivers/media/pci/pluto2/Kconfig
new file mode 100644
index 0000000..7d8e6e8
--- /dev/null
+++ b/drivers/media/pci/pluto2/Kconfig
@@ -0,0 +1,15 @@
+config DVB_PLUTO2
+	tristate "Pluto2 cards"
+	depends on DVB_CORE && PCI && I2C
+	select I2C_ALGOBIT
+	select DVB_TDA1004X
+	help
+	  Support for PCI cards based on the Pluto2 FPGA like the Satelco
+	  Easywatch Mobile Terrestrial DVB-T Receiver.
+
+	  Since these cards have no MPEG decoder onboard, they transmit
+	  only compressed MPEG data over the PCI bus, so you need
+	  an external software decoder to watch TV on your computer.
+
+	  Say Y or M if you own such a device and want to use it.
+
diff --git a/drivers/media/pci/pluto2/Makefile b/drivers/media/pci/pluto2/Makefile
new file mode 100644
index 0000000..524bf84
--- /dev/null
+++ b/drivers/media/pci/pluto2/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_DVB_PLUTO2) += pluto2.o
+
+ccflags-y += -Idrivers/media/dvb-core/ -Idrivers/media/dvb-frontends/
diff --git a/drivers/media/pci/pluto2/pluto2.c b/drivers/media/pci/pluto2/pluto2.c
new file mode 100644
index 0000000..f148b19
--- /dev/null
+++ b/drivers/media/pci/pluto2/pluto2.c
@@ -0,0 +1,815 @@
+/*
+ * pluto2.c - Satelco Easywatch Mobile Terrestrial Receiver [DVB-T]
+ *
+ * Copyright (C) 2005 Andreas Oberritter <obi@linuxtv.org>
+ *
+ * based on pluto2.c 1.10 - http://instinct-wp8.no-ip.org/pluto/
+ * 	by Dany Salman <salmandany@yahoo.fr>
+ *	Copyright (c) 2004 TDF
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/i2c.h>
+#include <linux/i2c-algo-bit.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+
+#include "demux.h"
+#include "dmxdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dvb_net.h"
+#include "dvbdev.h"
+#include "tda1004x.h"
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+#define DRIVER_NAME		"pluto2"
+
+#define REG_PIDn(n)		((n) << 2)	/* PID n pattern registers */
+#define REG_PCAR		0x0020		/* PC address register */
+#define REG_TSCR		0x0024		/* TS ctrl & status */
+#define REG_MISC		0x0028		/* miscellaneous */
+#define REG_MMAC		0x002c		/* MSB MAC address */
+#define REG_IMAC		0x0030		/* ISB MAC address */
+#define REG_LMAC		0x0034		/* LSB MAC address */
+#define REG_SPID		0x0038		/* SPI data */
+#define REG_SLCS		0x003c		/* serial links ctrl/status */
+
+#define PID0_NOFIL		(0x0001 << 16)
+#define PIDn_ENP		(0x0001 << 15)
+#define PID0_END		(0x0001 << 14)
+#define PID0_AFIL		(0x0001 << 13)
+#define PIDn_PID		(0x1fff <<  0)
+
+#define TSCR_NBPACKETS		(0x00ff << 24)
+#define TSCR_DEM		(0x0001 << 17)
+#define TSCR_DE			(0x0001 << 16)
+#define TSCR_RSTN		(0x0001 << 15)
+#define TSCR_MSKO		(0x0001 << 14)
+#define TSCR_MSKA		(0x0001 << 13)
+#define TSCR_MSKL		(0x0001 << 12)
+#define TSCR_OVR		(0x0001 << 11)
+#define TSCR_AFUL		(0x0001 << 10)
+#define TSCR_LOCK		(0x0001 <<  9)
+#define TSCR_IACK		(0x0001 <<  8)
+#define TSCR_ADEF		(0x007f <<  0)
+
+#define MISC_DVR		(0x0fff <<  4)
+#define MISC_ALED		(0x0001 <<  3)
+#define MISC_FRST		(0x0001 <<  2)
+#define MISC_LED1		(0x0001 <<  1)
+#define MISC_LED0		(0x0001 <<  0)
+
+#define SPID_SPIDR		(0x00ff <<  0)
+
+#define SLCS_SCL		(0x0001 <<  7)
+#define SLCS_SDA		(0x0001 <<  6)
+#define SLCS_CSN		(0x0001 <<  2)
+#define SLCS_OVR		(0x0001 <<  1)
+#define SLCS_SWC		(0x0001 <<  0)
+
+#define TS_DMA_PACKETS		(8)
+#define TS_DMA_BYTES		(188 * TS_DMA_PACKETS)
+
+#define I2C_ADDR_TDA10046	0x10
+#define I2C_ADDR_TUA6034	0xc2
+#define NHWFILTERS		8
+
+struct pluto {
+	/* pci */
+	struct pci_dev *pdev;
+	u8 __iomem *io_mem;
+
+	/* dvb */
+	struct dmx_frontend hw_frontend;
+	struct dmx_frontend mem_frontend;
+	struct dmxdev dmxdev;
+	struct dvb_adapter dvb_adapter;
+	struct dvb_demux demux;
+	struct dvb_frontend *fe;
+	struct dvb_net dvbnet;
+	unsigned int full_ts_users;
+	unsigned int users;
+
+	/* i2c */
+	struct i2c_algo_bit_data i2c_bit;
+	struct i2c_adapter i2c_adap;
+	unsigned int i2cbug;
+
+	/* irq */
+	unsigned int overflow;
+	unsigned int dead;
+
+	/* dma */
+	dma_addr_t dma_addr;
+	u8 dma_buf[TS_DMA_BYTES];
+	u8 dummy[4096];
+};
+
+static inline struct pluto *feed_to_pluto(struct dvb_demux_feed *feed)
+{
+	return container_of(feed->demux, struct pluto, demux);
+}
+
+static inline struct pluto *frontend_to_pluto(struct dvb_frontend *fe)
+{
+	return container_of(fe->dvb, struct pluto, dvb_adapter);
+}
+
+static inline u32 pluto_readreg(struct pluto *pluto, u32 reg)
+{
+	return readl(&pluto->io_mem[reg]);
+}
+
+static inline void pluto_writereg(struct pluto *pluto, u32 reg, u32 val)
+{
+	writel(val, &pluto->io_mem[reg]);
+}
+
+static inline void pluto_rw(struct pluto *pluto, u32 reg, u32 mask, u32 bits)
+{
+	u32 val = readl(&pluto->io_mem[reg]);
+	val &= ~mask;
+	val |= bits;
+	writel(val, &pluto->io_mem[reg]);
+}
+
+static void pluto_write_tscr(struct pluto *pluto, u32 val)
+{
+	/* set the number of packets */
+	val &= ~TSCR_ADEF;
+	val |= TS_DMA_PACKETS / 2;
+
+	pluto_writereg(pluto, REG_TSCR, val);
+}
+
+static void pluto_setsda(void *data, int state)
+{
+	struct pluto *pluto = data;
+
+	if (state)
+		pluto_rw(pluto, REG_SLCS, SLCS_SDA, SLCS_SDA);
+	else
+		pluto_rw(pluto, REG_SLCS, SLCS_SDA, 0);
+}
+
+static void pluto_setscl(void *data, int state)
+{
+	struct pluto *pluto = data;
+
+	if (state)
+		pluto_rw(pluto, REG_SLCS, SLCS_SCL, SLCS_SCL);
+	else
+		pluto_rw(pluto, REG_SLCS, SLCS_SCL, 0);
+
+	/* try to detect i2c_inb() to workaround hardware bug:
+	 * reset SDA to high after SCL has been set to low */
+	if ((state) && (pluto->i2cbug == 0)) {
+		pluto->i2cbug = 1;
+	} else {
+		if ((!state) && (pluto->i2cbug == 1))
+			pluto_setsda(pluto, 1);
+		pluto->i2cbug = 0;
+	}
+}
+
+static int pluto_getsda(void *data)
+{
+	struct pluto *pluto = data;
+
+	return pluto_readreg(pluto, REG_SLCS) & SLCS_SDA;
+}
+
+static int pluto_getscl(void *data)
+{
+	struct pluto *pluto = data;
+
+	return pluto_readreg(pluto, REG_SLCS) & SLCS_SCL;
+}
+
+static void pluto_reset_frontend(struct pluto *pluto, int reenable)
+{
+	u32 val = pluto_readreg(pluto, REG_MISC);
+
+	if (val & MISC_FRST) {
+		val &= ~MISC_FRST;
+		pluto_writereg(pluto, REG_MISC, val);
+	}
+	if (reenable) {
+		val |= MISC_FRST;
+		pluto_writereg(pluto, REG_MISC, val);
+	}
+}
+
+static void pluto_reset_ts(struct pluto *pluto, int reenable)
+{
+	u32 val = pluto_readreg(pluto, REG_TSCR);
+
+	if (val & TSCR_RSTN) {
+		val &= ~TSCR_RSTN;
+		pluto_write_tscr(pluto, val);
+	}
+	if (reenable) {
+		val |= TSCR_RSTN;
+		pluto_write_tscr(pluto, val);
+	}
+}
+
+static void pluto_set_dma_addr(struct pluto *pluto)
+{
+	pluto_writereg(pluto, REG_PCAR, pluto->dma_addr);
+}
+
+static int __devinit pluto_dma_map(struct pluto *pluto)
+{
+	pluto->dma_addr = pci_map_single(pluto->pdev, pluto->dma_buf,
+			TS_DMA_BYTES, PCI_DMA_FROMDEVICE);
+
+	return pci_dma_mapping_error(pluto->pdev, pluto->dma_addr);
+}
+
+static void pluto_dma_unmap(struct pluto *pluto)
+{
+	pci_unmap_single(pluto->pdev, pluto->dma_addr,
+			TS_DMA_BYTES, PCI_DMA_FROMDEVICE);
+}
+
+static int pluto_start_feed(struct dvb_demux_feed *f)
+{
+	struct pluto *pluto = feed_to_pluto(f);
+
+	/* enable PID filtering */
+	if (pluto->users++ == 0)
+		pluto_rw(pluto, REG_PIDn(0), PID0_AFIL | PID0_NOFIL, 0);
+
+	if ((f->pid < 0x2000) && (f->index < NHWFILTERS))
+		pluto_rw(pluto, REG_PIDn(f->index), PIDn_ENP | PIDn_PID, PIDn_ENP | f->pid);
+	else if (pluto->full_ts_users++ == 0)
+		pluto_rw(pluto, REG_PIDn(0), PID0_NOFIL, PID0_NOFIL);
+
+	return 0;
+}
+
+static int pluto_stop_feed(struct dvb_demux_feed *f)
+{
+	struct pluto *pluto = feed_to_pluto(f);
+
+	/* disable PID filtering */
+	if (--pluto->users == 0)
+		pluto_rw(pluto, REG_PIDn(0), PID0_AFIL, PID0_AFIL);
+
+	if ((f->pid < 0x2000) && (f->index < NHWFILTERS))
+		pluto_rw(pluto, REG_PIDn(f->index), PIDn_ENP | PIDn_PID, 0x1fff);
+	else if (--pluto->full_ts_users == 0)
+		pluto_rw(pluto, REG_PIDn(0), PID0_NOFIL, 0);
+
+	return 0;
+}
+
+static void pluto_dma_end(struct pluto *pluto, unsigned int nbpackets)
+{
+	/* synchronize the DMA transfer with the CPU
+	 * first so that we see updated contents. */
+	pci_dma_sync_single_for_cpu(pluto->pdev, pluto->dma_addr,
+			TS_DMA_BYTES, PCI_DMA_FROMDEVICE);
+
+	/* Workaround for broken hardware:
+	 * [1] On startup NBPACKETS seems to contain an uninitialized value,
+	 *     but no packets have been transferred.
+	 * [2] Sometimes (actually very often) NBPACKETS stays at zero
+	 *     although one packet has been transferred.
+	 * [3] Sometimes (actually rarely), the card gets into an erroneous
+	 *     mode where it continuously generates interrupts, claiming it
+	 *     has received nbpackets>TS_DMA_PACKETS packets, but no packet
+	 *     has been transferred. Only a reset seems to solve this
+	 */
+	if ((nbpackets == 0) || (nbpackets > TS_DMA_PACKETS)) {
+		unsigned int i = 0;
+		while (pluto->dma_buf[i] == 0x47)
+			i += 188;
+		nbpackets = i / 188;
+		if (i == 0) {
+			pluto_reset_ts(pluto, 1);
+			dev_printk(KERN_DEBUG, &pluto->pdev->dev, "resetting TS because of invalid packet counter\n");
+		}
+	}
+
+	dvb_dmx_swfilter_packets(&pluto->demux, pluto->dma_buf, nbpackets);
+
+	/* clear the dma buffer. this is needed to be able to identify
+	 * new valid ts packets above */
+	memset(pluto->dma_buf, 0, nbpackets * 188);
+
+	/* reset the dma address */
+	pluto_set_dma_addr(pluto);
+
+	/* sync the buffer and give it back to the card */
+	pci_dma_sync_single_for_device(pluto->pdev, pluto->dma_addr,
+			TS_DMA_BYTES, PCI_DMA_FROMDEVICE);
+}
+
+static irqreturn_t pluto_irq(int irq, void *dev_id)
+{
+	struct pluto *pluto = dev_id;
+	u32 tscr;
+
+	/* check whether an interrupt occurred on this device */
+	tscr = pluto_readreg(pluto, REG_TSCR);
+	if (!(tscr & (TSCR_DE | TSCR_OVR)))
+		return IRQ_NONE;
+
+	if (tscr == 0xffffffff) {
+		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;
+	}
+
+	/* dma end interrupt */
+	if (tscr & TSCR_DE) {
+		pluto_dma_end(pluto, (tscr & TSCR_NBPACKETS) >> 24);
+		/* overflow interrupt */
+		if (tscr & TSCR_OVR)
+			pluto->overflow++;
+		if (pluto->overflow) {
+			dev_err(&pluto->pdev->dev, "overflow irq (%d)\n",
+					pluto->overflow);
+			pluto_reset_ts(pluto, 1);
+			pluto->overflow = 0;
+		}
+	} else if (tscr & TSCR_OVR) {
+		pluto->overflow++;
+	}
+
+	/* ACK the interrupt */
+	pluto_write_tscr(pluto, tscr | TSCR_IACK);
+
+	return IRQ_HANDLED;
+}
+
+static void __devinit pluto_enable_irqs(struct pluto *pluto)
+{
+	u32 val = pluto_readreg(pluto, REG_TSCR);
+
+	/* disable AFUL and LOCK interrupts */
+	val |= (TSCR_MSKA | TSCR_MSKL);
+	/* enable DMA and OVERFLOW interrupts */
+	val &= ~(TSCR_DEM | TSCR_MSKO);
+	/* clear pending interrupts */
+	val |= TSCR_IACK;
+
+	pluto_write_tscr(pluto, val);
+}
+
+static void pluto_disable_irqs(struct pluto *pluto)
+{
+	u32 val = pluto_readreg(pluto, REG_TSCR);
+
+	/* disable all interrupts */
+	val |= (TSCR_DEM | TSCR_MSKO | TSCR_MSKA | TSCR_MSKL);
+	/* clear pending interrupts */
+	val |= TSCR_IACK;
+
+	pluto_write_tscr(pluto, val);
+}
+
+static int __devinit pluto_hw_init(struct pluto *pluto)
+{
+	pluto_reset_frontend(pluto, 1);
+
+	/* set automatic LED control by FPGA */
+	pluto_rw(pluto, REG_MISC, MISC_ALED, MISC_ALED);
+
+	/* set data endianess */
+#ifdef __LITTLE_ENDIAN
+	pluto_rw(pluto, REG_PIDn(0), PID0_END, PID0_END);
+#else
+	pluto_rw(pluto, REG_PIDn(0), PID0_END, 0);
+#endif
+	/* map DMA and set address */
+	pluto_dma_map(pluto);
+	pluto_set_dma_addr(pluto);
+
+	/* enable interrupts */
+	pluto_enable_irqs(pluto);
+
+	/* reset TS logic */
+	pluto_reset_ts(pluto, 1);
+
+	return 0;
+}
+
+static void pluto_hw_exit(struct pluto *pluto)
+{
+	/* disable interrupts */
+	pluto_disable_irqs(pluto);
+
+	pluto_reset_ts(pluto, 0);
+
+	/* LED: disable automatic control, enable yellow, disable green */
+	pluto_rw(pluto, REG_MISC, MISC_ALED | MISC_LED1 | MISC_LED0, MISC_LED1);
+
+	/* unmap DMA */
+	pluto_dma_unmap(pluto);
+
+	pluto_reset_frontend(pluto, 0);
+}
+
+static inline u32 divide(u32 numerator, u32 denominator)
+{
+	if (denominator == 0)
+		return ~0;
+
+	return DIV_ROUND_CLOSEST(numerator, denominator);
+}
+
+/* LG Innotek TDTE-E001P (Infineon TUA6034) */
+static int lg_tdtpe001p_tuner_set_params(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct pluto *pluto = frontend_to_pluto(fe);
+	struct i2c_msg msg;
+	int ret;
+	u8 buf[4];
+	u32 div;
+
+	// Fref = 166.667 Hz
+	// Fref * 3 = 500.000 Hz
+	// IF = 36166667
+	// IF / Fref = 217
+	//div = divide(p->frequency + 36166667, 166667);
+	div = divide(p->frequency * 3, 500000) + 217;
+	buf[0] = (div >> 8) & 0x7f;
+	buf[1] = (div >> 0) & 0xff;
+
+	if (p->frequency < 611000000)
+		buf[2] = 0xb4;
+	else if (p->frequency < 811000000)
+		buf[2] = 0xbc;
+	else
+		buf[2] = 0xf4;
+
+	// VHF: 174-230 MHz
+	// center: 350 MHz
+	// UHF: 470-862 MHz
+	if (p->frequency < 350000000)
+		buf[3] = 0x02;
+	else
+		buf[3] = 0x04;
+
+	if (p->bandwidth_hz == 8000000)
+		buf[3] |= 0x08;
+
+	msg.addr = I2C_ADDR_TUA6034 >> 1;
+	msg.flags = 0;
+	msg.buf = buf;
+	msg.len = sizeof(buf);
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+	ret = i2c_transfer(&pluto->i2c_adap, &msg, 1);
+	if (ret < 0)
+		return ret;
+	else if (ret == 0)
+		return -EREMOTEIO;
+
+	return 0;
+}
+
+static int pluto2_request_firmware(struct dvb_frontend *fe,
+				   const struct firmware **fw, char *name)
+{
+	struct pluto *pluto = frontend_to_pluto(fe);
+
+	return request_firmware(fw, name, &pluto->pdev->dev);
+}
+
+static struct tda1004x_config pluto2_fe_config __devinitdata = {
+	.demod_address = I2C_ADDR_TDA10046 >> 1,
+	.invert = 1,
+	.invert_oclk = 0,
+	.xtal_freq = TDA10046_XTAL_16M,
+	.agc_config = TDA10046_AGC_DEFAULT,
+	.if_freq = TDA10046_FREQ_3617,
+	.request_firmware = pluto2_request_firmware,
+};
+
+static int __devinit frontend_init(struct pluto *pluto)
+{
+	int ret;
+
+	pluto->fe = tda10046_attach(&pluto2_fe_config, &pluto->i2c_adap);
+	if (!pluto->fe) {
+		dev_err(&pluto->pdev->dev, "could not attach frontend\n");
+		return -ENODEV;
+	}
+	pluto->fe->ops.tuner_ops.set_params = lg_tdtpe001p_tuner_set_params;
+
+	ret = dvb_register_frontend(&pluto->dvb_adapter, pluto->fe);
+	if (ret < 0) {
+		if (pluto->fe->ops.release)
+			pluto->fe->ops.release(pluto->fe);
+		return ret;
+	}
+
+	return 0;
+}
+
+static void __devinit pluto_read_rev(struct pluto *pluto)
+{
+	u32 val = pluto_readreg(pluto, REG_MISC) & MISC_DVR;
+	dev_info(&pluto->pdev->dev, "board revision %d.%d\n",
+			(val >> 12) & 0x0f, (val >> 4) & 0xff);
+}
+
+static void __devinit pluto_read_mac(struct pluto *pluto, u8 *mac)
+{
+	u32 val = pluto_readreg(pluto, REG_MMAC);
+	mac[0] = (val >> 8) & 0xff;
+	mac[1] = (val >> 0) & 0xff;
+
+	val = pluto_readreg(pluto, REG_IMAC);
+	mac[2] = (val >> 8) & 0xff;
+	mac[3] = (val >> 0) & 0xff;
+
+	val = pluto_readreg(pluto, REG_LMAC);
+	mac[4] = (val >> 8) & 0xff;
+	mac[5] = (val >> 0) & 0xff;
+
+	dev_info(&pluto->pdev->dev, "MAC %pM\n", mac);
+}
+
+static int __devinit pluto_read_serial(struct pluto *pluto)
+{
+	struct pci_dev *pdev = pluto->pdev;
+	unsigned int i, j;
+	u8 __iomem *cis;
+
+	cis = pci_iomap(pdev, 1, 0);
+	if (!cis)
+		return -EIO;
+
+	dev_info(&pdev->dev, "S/N ");
+
+	for (i = 0xe0; i < 0x100; i += 4) {
+		u32 val = readl(&cis[i]);
+		for (j = 0; j < 32; j += 8) {
+			if ((val & 0xff) == 0xff)
+				goto out;
+			printk("%c", val & 0xff);
+			val >>= 8;
+		}
+	}
+out:
+	printk("\n");
+	pci_iounmap(pdev, cis);
+
+	return 0;
+}
+
+static int __devinit pluto2_probe(struct pci_dev *pdev,
+				  const struct pci_device_id *ent)
+{
+	struct pluto *pluto;
+	struct dvb_adapter *dvb_adapter;
+	struct dvb_demux *dvbdemux;
+	struct dmx_demux *dmx;
+	int ret = -ENOMEM;
+
+	pluto = kzalloc(sizeof(struct pluto), GFP_KERNEL);
+	if (!pluto)
+		goto out;
+
+	pluto->pdev = pdev;
+
+	ret = pci_enable_device(pdev);
+	if (ret < 0)
+		goto err_kfree;
+
+	/* enable interrupts */
+	pci_write_config_dword(pdev, 0x6c, 0x8000);
+
+	ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+	if (ret < 0)
+		goto err_pci_disable_device;
+
+	pci_set_master(pdev);
+
+	ret = pci_request_regions(pdev, DRIVER_NAME);
+	if (ret < 0)
+		goto err_pci_disable_device;
+
+	pluto->io_mem = pci_iomap(pdev, 0, 0x40);
+	if (!pluto->io_mem) {
+		ret = -EIO;
+		goto err_pci_release_regions;
+	}
+
+	pci_set_drvdata(pdev, pluto);
+
+	ret = request_irq(pdev->irq, pluto_irq, IRQF_SHARED, DRIVER_NAME, pluto);
+	if (ret < 0)
+		goto err_pci_iounmap;
+
+	ret = pluto_hw_init(pluto);
+	if (ret < 0)
+		goto err_free_irq;
+
+	/* i2c */
+	i2c_set_adapdata(&pluto->i2c_adap, pluto);
+	strcpy(pluto->i2c_adap.name, DRIVER_NAME);
+	pluto->i2c_adap.owner = THIS_MODULE;
+	pluto->i2c_adap.dev.parent = &pdev->dev;
+	pluto->i2c_adap.algo_data = &pluto->i2c_bit;
+	pluto->i2c_bit.data = pluto;
+	pluto->i2c_bit.setsda = pluto_setsda;
+	pluto->i2c_bit.setscl = pluto_setscl;
+	pluto->i2c_bit.getsda = pluto_getsda;
+	pluto->i2c_bit.getscl = pluto_getscl;
+	pluto->i2c_bit.udelay = 10;
+	pluto->i2c_bit.timeout = 10;
+
+	/* Raise SCL and SDA */
+	pluto_setsda(pluto, 1);
+	pluto_setscl(pluto, 1);
+
+	ret = i2c_bit_add_bus(&pluto->i2c_adap);
+	if (ret < 0)
+		goto err_pluto_hw_exit;
+
+	/* dvb */
+	ret = dvb_register_adapter(&pluto->dvb_adapter, DRIVER_NAME,
+				   THIS_MODULE, &pdev->dev, adapter_nr);
+	if (ret < 0)
+		goto err_i2c_del_adapter;
+
+	dvb_adapter = &pluto->dvb_adapter;
+
+	pluto_read_rev(pluto);
+	pluto_read_serial(pluto);
+	pluto_read_mac(pluto, dvb_adapter->proposed_mac);
+
+	dvbdemux = &pluto->demux;
+	dvbdemux->filternum = 256;
+	dvbdemux->feednum = 256;
+	dvbdemux->start_feed = pluto_start_feed;
+	dvbdemux->stop_feed = pluto_stop_feed;
+	dvbdemux->dmx.capabilities = (DMX_TS_FILTERING |
+			DMX_SECTION_FILTERING | DMX_MEMORY_BASED_FILTERING);
+	ret = dvb_dmx_init(dvbdemux);
+	if (ret < 0)
+		goto err_dvb_unregister_adapter;
+
+	dmx = &dvbdemux->dmx;
+
+	pluto->hw_frontend.source = DMX_FRONTEND_0;
+	pluto->mem_frontend.source = DMX_MEMORY_FE;
+	pluto->dmxdev.filternum = NHWFILTERS;
+	pluto->dmxdev.demux = dmx;
+
+	ret = dvb_dmxdev_init(&pluto->dmxdev, dvb_adapter);
+	if (ret < 0)
+		goto err_dvb_dmx_release;
+
+	ret = dmx->add_frontend(dmx, &pluto->hw_frontend);
+	if (ret < 0)
+		goto err_dvb_dmxdev_release;
+
+	ret = dmx->add_frontend(dmx, &pluto->mem_frontend);
+	if (ret < 0)
+		goto err_remove_hw_frontend;
+
+	ret = dmx->connect_frontend(dmx, &pluto->hw_frontend);
+	if (ret < 0)
+		goto err_remove_mem_frontend;
+
+	ret = frontend_init(pluto);
+	if (ret < 0)
+		goto err_disconnect_frontend;
+
+	dvb_net_init(dvb_adapter, &pluto->dvbnet, dmx);
+out:
+	return ret;
+
+err_disconnect_frontend:
+	dmx->disconnect_frontend(dmx);
+err_remove_mem_frontend:
+	dmx->remove_frontend(dmx, &pluto->mem_frontend);
+err_remove_hw_frontend:
+	dmx->remove_frontend(dmx, &pluto->hw_frontend);
+err_dvb_dmxdev_release:
+	dvb_dmxdev_release(&pluto->dmxdev);
+err_dvb_dmx_release:
+	dvb_dmx_release(dvbdemux);
+err_dvb_unregister_adapter:
+	dvb_unregister_adapter(dvb_adapter);
+err_i2c_del_adapter:
+	i2c_del_adapter(&pluto->i2c_adap);
+err_pluto_hw_exit:
+	pluto_hw_exit(pluto);
+err_free_irq:
+	free_irq(pdev->irq, pluto);
+err_pci_iounmap:
+	pci_iounmap(pdev, pluto->io_mem);
+err_pci_release_regions:
+	pci_release_regions(pdev);
+err_pci_disable_device:
+	pci_disable_device(pdev);
+err_kfree:
+	pci_set_drvdata(pdev, NULL);
+	kfree(pluto);
+	goto out;
+}
+
+static void __devexit pluto2_remove(struct pci_dev *pdev)
+{
+	struct pluto *pluto = pci_get_drvdata(pdev);
+	struct dvb_adapter *dvb_adapter = &pluto->dvb_adapter;
+	struct dvb_demux *dvbdemux = &pluto->demux;
+	struct dmx_demux *dmx = &dvbdemux->dmx;
+
+	dmx->close(dmx);
+	dvb_net_release(&pluto->dvbnet);
+	if (pluto->fe)
+		dvb_unregister_frontend(pluto->fe);
+
+	dmx->disconnect_frontend(dmx);
+	dmx->remove_frontend(dmx, &pluto->mem_frontend);
+	dmx->remove_frontend(dmx, &pluto->hw_frontend);
+	dvb_dmxdev_release(&pluto->dmxdev);
+	dvb_dmx_release(dvbdemux);
+	dvb_unregister_adapter(dvb_adapter);
+	i2c_del_adapter(&pluto->i2c_adap);
+	pluto_hw_exit(pluto);
+	free_irq(pdev->irq, pluto);
+	pci_iounmap(pdev, pluto->io_mem);
+	pci_release_regions(pdev);
+	pci_disable_device(pdev);
+	pci_set_drvdata(pdev, NULL);
+	kfree(pluto);
+}
+
+#ifndef PCI_VENDOR_ID_SCM
+#define PCI_VENDOR_ID_SCM	0x0432
+#endif
+#ifndef PCI_DEVICE_ID_PLUTO2
+#define PCI_DEVICE_ID_PLUTO2	0x0001
+#endif
+
+static struct pci_device_id pluto2_id_table[] __devinitdata = {
+	{
+		.vendor = PCI_VENDOR_ID_SCM,
+		.device = PCI_DEVICE_ID_PLUTO2,
+		.subvendor = PCI_ANY_ID,
+		.subdevice = PCI_ANY_ID,
+	}, {
+		/* empty */
+	},
+};
+
+MODULE_DEVICE_TABLE(pci, pluto2_id_table);
+
+static struct pci_driver pluto2_driver = {
+	.name = DRIVER_NAME,
+	.id_table = pluto2_id_table,
+	.probe = pluto2_probe,
+	.remove = __devexit_p(pluto2_remove),
+};
+
+static int __init pluto2_init(void)
+{
+	return pci_register_driver(&pluto2_driver);
+}
+
+static void __exit pluto2_exit(void)
+{
+	pci_unregister_driver(&pluto2_driver);
+}
+
+module_init(pluto2_init);
+module_exit(pluto2_exit);
+
+MODULE_AUTHOR("Andreas Oberritter <obi@linuxtv.org>");
+MODULE_DESCRIPTION("Pluto2 driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/pci/pt1/Kconfig b/drivers/media/pci/pt1/Kconfig
new file mode 100644
index 0000000..24501d5
--- /dev/null
+++ b/drivers/media/pci/pt1/Kconfig
@@ -0,0 +1,12 @@
+config DVB_PT1
+	tristate "PT1 cards"
+	depends on DVB_CORE && PCI && I2C
+	help
+	  Support for Earthsoft PT1 PCI cards.
+
+	  Since these cards have no MPEG decoder onboard, they transmit
+	  only compressed MPEG data over the PCI bus, so you need
+	  an external software decoder to watch TV on your computer.
+
+	  Say Y or M if you own such a device and want to use it.
+
diff --git a/drivers/media/pci/pt1/Makefile b/drivers/media/pci/pt1/Makefile
new file mode 100644
index 0000000..98e3912
--- /dev/null
+++ b/drivers/media/pci/pt1/Makefile
@@ -0,0 +1,5 @@
+earth-pt1-objs := pt1.o va1j5jf8007s.o va1j5jf8007t.o
+
+obj-$(CONFIG_DVB_PT1) += earth-pt1.o
+
+ccflags-y += -Idrivers/media/dvb-core -Idrivers/media/dvb-frontends
diff --git a/drivers/media/pci/pt1/pt1.c b/drivers/media/pci/pt1/pt1.c
new file mode 100644
index 0000000..15b35c4
--- /dev/null
+++ b/drivers/media/pci/pt1/pt1.c
@@ -0,0 +1,1246 @@
+/*
+ * driver for Earthsoft PT1/PT2
+ *
+ * Copyright (C) 2009 HIRANO Takahito <hiranotaka@zng.info>
+ *
+ * based on pt1dvr - http://pt1dvr.sourceforge.jp/
+ * 	by Tomoaki Ishikawa <tomy@users.sourceforge.jp>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/pci.h>
+#include <linux/kthread.h>
+#include <linux/freezer.h>
+#include <linux/ratelimit.h>
+
+#include "dvbdev.h"
+#include "dvb_demux.h"
+#include "dmxdev.h"
+#include "dvb_net.h"
+#include "dvb_frontend.h"
+
+#include "va1j5jf8007t.h"
+#include "va1j5jf8007s.h"
+
+#define DRIVER_NAME "earth-pt1"
+
+#define PT1_PAGE_SHIFT 12
+#define PT1_PAGE_SIZE (1 << PT1_PAGE_SHIFT)
+#define PT1_NR_UPACKETS 1024
+#define PT1_NR_BUFS 511
+
+struct pt1_buffer_page {
+	__le32 upackets[PT1_NR_UPACKETS];
+};
+
+struct pt1_table_page {
+	__le32 next_pfn;
+	__le32 buf_pfns[PT1_NR_BUFS];
+};
+
+struct pt1_buffer {
+	struct pt1_buffer_page *page;
+	dma_addr_t addr;
+};
+
+struct pt1_table {
+	struct pt1_table_page *page;
+	dma_addr_t addr;
+	struct pt1_buffer bufs[PT1_NR_BUFS];
+};
+
+#define PT1_NR_ADAPS 4
+
+struct pt1_adapter;
+
+struct pt1 {
+	struct pci_dev *pdev;
+	void __iomem *regs;
+	struct i2c_adapter i2c_adap;
+	int i2c_running;
+	struct pt1_adapter *adaps[PT1_NR_ADAPS];
+	struct pt1_table *tables;
+	struct task_struct *kthread;
+	int table_index;
+	int buf_index;
+
+	struct mutex lock;
+	int power;
+	int reset;
+};
+
+struct pt1_adapter {
+	struct pt1 *pt1;
+	int index;
+
+	u8 *buf;
+	int upacket_count;
+	int packet_count;
+	int st_count;
+
+	struct dvb_adapter adap;
+	struct dvb_demux demux;
+	int users;
+	struct dmxdev dmxdev;
+	struct dvb_frontend *fe;
+	int (*orig_set_voltage)(struct dvb_frontend *fe,
+				fe_sec_voltage_t voltage);
+	int (*orig_sleep)(struct dvb_frontend *fe);
+	int (*orig_init)(struct dvb_frontend *fe);
+
+	fe_sec_voltage_t voltage;
+	int sleep;
+};
+
+#define pt1_printk(level, pt1, format, arg...)	\
+	dev_printk(level, &(pt1)->pdev->dev, format, ##arg)
+
+static void pt1_write_reg(struct pt1 *pt1, int reg, u32 data)
+{
+	writel(data, pt1->regs + reg * 4);
+}
+
+static u32 pt1_read_reg(struct pt1 *pt1, int reg)
+{
+	return readl(pt1->regs + reg * 4);
+}
+
+static int pt1_nr_tables = 8;
+module_param_named(nr_tables, pt1_nr_tables, int, 0);
+
+static void pt1_increment_table_count(struct pt1 *pt1)
+{
+	pt1_write_reg(pt1, 0, 0x00000020);
+}
+
+static void pt1_init_table_count(struct pt1 *pt1)
+{
+	pt1_write_reg(pt1, 0, 0x00000010);
+}
+
+static void pt1_register_tables(struct pt1 *pt1, u32 first_pfn)
+{
+	pt1_write_reg(pt1, 5, first_pfn);
+	pt1_write_reg(pt1, 0, 0x0c000040);
+}
+
+static void pt1_unregister_tables(struct pt1 *pt1)
+{
+	pt1_write_reg(pt1, 0, 0x08080000);
+}
+
+static int pt1_sync(struct pt1 *pt1)
+{
+	int i;
+	for (i = 0; i < 57; i++) {
+		if (pt1_read_reg(pt1, 0) & 0x20000000)
+			return 0;
+		pt1_write_reg(pt1, 0, 0x00000008);
+	}
+	pt1_printk(KERN_ERR, pt1, "could not sync\n");
+	return -EIO;
+}
+
+static u64 pt1_identify(struct pt1 *pt1)
+{
+	int i;
+	u64 id;
+	id = 0;
+	for (i = 0; i < 57; i++) {
+		id |= (u64)(pt1_read_reg(pt1, 0) >> 30 & 1) << i;
+		pt1_write_reg(pt1, 0, 0x00000008);
+	}
+	return id;
+}
+
+static int pt1_unlock(struct pt1 *pt1)
+{
+	int i;
+	pt1_write_reg(pt1, 0, 0x00000008);
+	for (i = 0; i < 3; i++) {
+		if (pt1_read_reg(pt1, 0) & 0x80000000)
+			return 0;
+		schedule_timeout_uninterruptible((HZ + 999) / 1000);
+	}
+	pt1_printk(KERN_ERR, pt1, "could not unlock\n");
+	return -EIO;
+}
+
+static int pt1_reset_pci(struct pt1 *pt1)
+{
+	int i;
+	pt1_write_reg(pt1, 0, 0x01010000);
+	pt1_write_reg(pt1, 0, 0x01000000);
+	for (i = 0; i < 10; i++) {
+		if (pt1_read_reg(pt1, 0) & 0x00000001)
+			return 0;
+		schedule_timeout_uninterruptible((HZ + 999) / 1000);
+	}
+	pt1_printk(KERN_ERR, pt1, "could not reset PCI\n");
+	return -EIO;
+}
+
+static int pt1_reset_ram(struct pt1 *pt1)
+{
+	int i;
+	pt1_write_reg(pt1, 0, 0x02020000);
+	pt1_write_reg(pt1, 0, 0x02000000);
+	for (i = 0; i < 10; i++) {
+		if (pt1_read_reg(pt1, 0) & 0x00000002)
+			return 0;
+		schedule_timeout_uninterruptible((HZ + 999) / 1000);
+	}
+	pt1_printk(KERN_ERR, pt1, "could not reset RAM\n");
+	return -EIO;
+}
+
+static int pt1_do_enable_ram(struct pt1 *pt1)
+{
+	int i, j;
+	u32 status;
+	status = pt1_read_reg(pt1, 0) & 0x00000004;
+	pt1_write_reg(pt1, 0, 0x00000002);
+	for (i = 0; i < 10; i++) {
+		for (j = 0; j < 1024; j++) {
+			if ((pt1_read_reg(pt1, 0) & 0x00000004) != status)
+				return 0;
+		}
+		schedule_timeout_uninterruptible((HZ + 999) / 1000);
+	}
+	pt1_printk(KERN_ERR, pt1, "could not enable RAM\n");
+	return -EIO;
+}
+
+static int pt1_enable_ram(struct pt1 *pt1)
+{
+	int i, ret;
+	int phase;
+	schedule_timeout_uninterruptible((HZ + 999) / 1000);
+	phase = pt1->pdev->device == 0x211a ? 128 : 166;
+	for (i = 0; i < phase; i++) {
+		ret = pt1_do_enable_ram(pt1);
+		if (ret < 0)
+			return ret;
+	}
+	return 0;
+}
+
+static void pt1_disable_ram(struct pt1 *pt1)
+{
+	pt1_write_reg(pt1, 0, 0x0b0b0000);
+}
+
+static void pt1_set_stream(struct pt1 *pt1, int index, int enabled)
+{
+	pt1_write_reg(pt1, 2, 1 << (index + 8) | enabled << index);
+}
+
+static void pt1_init_streams(struct pt1 *pt1)
+{
+	int i;
+	for (i = 0; i < PT1_NR_ADAPS; i++)
+		pt1_set_stream(pt1, i, 0);
+}
+
+static int pt1_filter(struct pt1 *pt1, struct pt1_buffer_page *page)
+{
+	u32 upacket;
+	int i;
+	int index;
+	struct pt1_adapter *adap;
+	int offset;
+	u8 *buf;
+	int sc;
+
+	if (!page->upackets[PT1_NR_UPACKETS - 1])
+		return 0;
+
+	for (i = 0; i < PT1_NR_UPACKETS; i++) {
+		upacket = le32_to_cpu(page->upackets[i]);
+		index = (upacket >> 29) - 1;
+		if (index < 0 || index >=  PT1_NR_ADAPS)
+			continue;
+
+		adap = pt1->adaps[index];
+		if (upacket >> 25 & 1)
+			adap->upacket_count = 0;
+		else if (!adap->upacket_count)
+			continue;
+
+		if (upacket >> 24 & 1)
+			printk_ratelimited(KERN_INFO "earth-pt1: device "
+				"buffer overflowing. table[%d] buf[%d]\n",
+				pt1->table_index, pt1->buf_index);
+		sc = upacket >> 26 & 0x7;
+		if (adap->st_count != -1 && sc != ((adap->st_count + 1) & 0x7))
+			printk_ratelimited(KERN_INFO "earth-pt1: data loss"
+				" in streamID(adapter)[%d]\n", index);
+		adap->st_count = sc;
+
+		buf = adap->buf;
+		offset = adap->packet_count * 188 + adap->upacket_count * 3;
+		buf[offset] = upacket >> 16;
+		buf[offset + 1] = upacket >> 8;
+		if (adap->upacket_count != 62)
+			buf[offset + 2] = upacket;
+
+		if (++adap->upacket_count >= 63) {
+			adap->upacket_count = 0;
+			if (++adap->packet_count >= 21) {
+				dvb_dmx_swfilter_packets(&adap->demux, buf, 21);
+				adap->packet_count = 0;
+			}
+		}
+	}
+
+	page->upackets[PT1_NR_UPACKETS - 1] = 0;
+	return 1;
+}
+
+static int pt1_thread(void *data)
+{
+	struct pt1 *pt1;
+	struct pt1_buffer_page *page;
+
+	pt1 = data;
+	set_freezable();
+
+	while (!kthread_should_stop()) {
+		try_to_freeze();
+
+		page = pt1->tables[pt1->table_index].bufs[pt1->buf_index].page;
+		if (!pt1_filter(pt1, page)) {
+			schedule_timeout_interruptible((HZ + 999) / 1000);
+			continue;
+		}
+
+		if (++pt1->buf_index >= PT1_NR_BUFS) {
+			pt1_increment_table_count(pt1);
+			pt1->buf_index = 0;
+			if (++pt1->table_index >= pt1_nr_tables)
+				pt1->table_index = 0;
+		}
+	}
+
+	return 0;
+}
+
+static void pt1_free_page(struct pt1 *pt1, void *page, dma_addr_t addr)
+{
+	dma_free_coherent(&pt1->pdev->dev, PT1_PAGE_SIZE, page, addr);
+}
+
+static void *pt1_alloc_page(struct pt1 *pt1, dma_addr_t *addrp, u32 *pfnp)
+{
+	void *page;
+	dma_addr_t addr;
+
+	page = dma_alloc_coherent(&pt1->pdev->dev, PT1_PAGE_SIZE, &addr,
+				  GFP_KERNEL);
+	if (page == NULL)
+		return NULL;
+
+	BUG_ON(addr & (PT1_PAGE_SIZE - 1));
+	BUG_ON(addr >> PT1_PAGE_SHIFT >> 31 >> 1);
+
+	*addrp = addr;
+	*pfnp = addr >> PT1_PAGE_SHIFT;
+	return page;
+}
+
+static void pt1_cleanup_buffer(struct pt1 *pt1, struct pt1_buffer *buf)
+{
+	pt1_free_page(pt1, buf->page, buf->addr);
+}
+
+static int
+pt1_init_buffer(struct pt1 *pt1, struct pt1_buffer *buf,  u32 *pfnp)
+{
+	struct pt1_buffer_page *page;
+	dma_addr_t addr;
+
+	page = pt1_alloc_page(pt1, &addr, pfnp);
+	if (page == NULL)
+		return -ENOMEM;
+
+	page->upackets[PT1_NR_UPACKETS - 1] = 0;
+
+	buf->page = page;
+	buf->addr = addr;
+	return 0;
+}
+
+static void pt1_cleanup_table(struct pt1 *pt1, struct pt1_table *table)
+{
+	int i;
+
+	for (i = 0; i < PT1_NR_BUFS; i++)
+		pt1_cleanup_buffer(pt1, &table->bufs[i]);
+
+	pt1_free_page(pt1, table->page, table->addr);
+}
+
+static int
+pt1_init_table(struct pt1 *pt1, struct pt1_table *table, u32 *pfnp)
+{
+	struct pt1_table_page *page;
+	dma_addr_t addr;
+	int i, ret;
+	u32 buf_pfn;
+
+	page = pt1_alloc_page(pt1, &addr, pfnp);
+	if (page == NULL)
+		return -ENOMEM;
+
+	for (i = 0; i < PT1_NR_BUFS; i++) {
+		ret = pt1_init_buffer(pt1, &table->bufs[i], &buf_pfn);
+		if (ret < 0)
+			goto err;
+
+		page->buf_pfns[i] = cpu_to_le32(buf_pfn);
+	}
+
+	pt1_increment_table_count(pt1);
+	table->page = page;
+	table->addr = addr;
+	return 0;
+
+err:
+	while (i--)
+		pt1_cleanup_buffer(pt1, &table->bufs[i]);
+
+	pt1_free_page(pt1, page, addr);
+	return ret;
+}
+
+static void pt1_cleanup_tables(struct pt1 *pt1)
+{
+	struct pt1_table *tables;
+	int i;
+
+	tables = pt1->tables;
+	pt1_unregister_tables(pt1);
+
+	for (i = 0; i < pt1_nr_tables; i++)
+		pt1_cleanup_table(pt1, &tables[i]);
+
+	vfree(tables);
+}
+
+static int pt1_init_tables(struct pt1 *pt1)
+{
+	struct pt1_table *tables;
+	int i, ret;
+	u32 first_pfn, pfn;
+
+	tables = vmalloc(sizeof(struct pt1_table) * pt1_nr_tables);
+	if (tables == NULL)
+		return -ENOMEM;
+
+	pt1_init_table_count(pt1);
+
+	i = 0;
+	if (pt1_nr_tables) {
+		ret = pt1_init_table(pt1, &tables[0], &first_pfn);
+		if (ret)
+			goto err;
+		i++;
+	}
+
+	while (i < pt1_nr_tables) {
+		ret = pt1_init_table(pt1, &tables[i], &pfn);
+		if (ret)
+			goto err;
+		tables[i - 1].page->next_pfn = cpu_to_le32(pfn);
+		i++;
+	}
+
+	tables[pt1_nr_tables - 1].page->next_pfn = cpu_to_le32(first_pfn);
+
+	pt1_register_tables(pt1, first_pfn);
+	pt1->tables = tables;
+	return 0;
+
+err:
+	while (i--)
+		pt1_cleanup_table(pt1, &tables[i]);
+
+	vfree(tables);
+	return ret;
+}
+
+static int pt1_start_polling(struct pt1 *pt1)
+{
+	int ret = 0;
+
+	mutex_lock(&pt1->lock);
+	if (!pt1->kthread) {
+		pt1->kthread = kthread_run(pt1_thread, pt1, "earth-pt1");
+		if (IS_ERR(pt1->kthread)) {
+			ret = PTR_ERR(pt1->kthread);
+			pt1->kthread = NULL;
+		}
+	}
+	mutex_unlock(&pt1->lock);
+	return ret;
+}
+
+static int pt1_start_feed(struct dvb_demux_feed *feed)
+{
+	struct pt1_adapter *adap;
+	adap = container_of(feed->demux, struct pt1_adapter, demux);
+	if (!adap->users++) {
+		int ret;
+
+		ret = pt1_start_polling(adap->pt1);
+		if (ret)
+			return ret;
+		pt1_set_stream(adap->pt1, adap->index, 1);
+	}
+	return 0;
+}
+
+static void pt1_stop_polling(struct pt1 *pt1)
+{
+	int i, count;
+
+	mutex_lock(&pt1->lock);
+	for (i = 0, count = 0; i < PT1_NR_ADAPS; i++)
+		count += pt1->adaps[i]->users;
+
+	if (count == 0 && pt1->kthread) {
+		kthread_stop(pt1->kthread);
+		pt1->kthread = NULL;
+	}
+	mutex_unlock(&pt1->lock);
+}
+
+static int pt1_stop_feed(struct dvb_demux_feed *feed)
+{
+	struct pt1_adapter *adap;
+	adap = container_of(feed->demux, struct pt1_adapter, demux);
+	if (!--adap->users) {
+		pt1_set_stream(adap->pt1, adap->index, 0);
+		pt1_stop_polling(adap->pt1);
+	}
+	return 0;
+}
+
+static void
+pt1_update_power(struct pt1 *pt1)
+{
+	int bits;
+	int i;
+	struct pt1_adapter *adap;
+	static const int sleep_bits[] = {
+		1 << 4,
+		1 << 6 | 1 << 7,
+		1 << 5,
+		1 << 6 | 1 << 8,
+	};
+
+	bits = pt1->power | !pt1->reset << 3;
+	mutex_lock(&pt1->lock);
+	for (i = 0; i < PT1_NR_ADAPS; i++) {
+		adap = pt1->adaps[i];
+		switch (adap->voltage) {
+		case SEC_VOLTAGE_13: /* actually 11V */
+			bits |= 1 << 1;
+			break;
+		case SEC_VOLTAGE_18: /* actually 15V */
+			bits |= 1 << 1 | 1 << 2;
+			break;
+		default:
+			break;
+		}
+
+		/* XXX: The bits should be changed depending on adap->sleep. */
+		bits |= sleep_bits[i];
+	}
+	pt1_write_reg(pt1, 1, bits);
+	mutex_unlock(&pt1->lock);
+}
+
+static int pt1_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+{
+	struct pt1_adapter *adap;
+
+	adap = container_of(fe->dvb, struct pt1_adapter, adap);
+	adap->voltage = voltage;
+	pt1_update_power(adap->pt1);
+
+	if (adap->orig_set_voltage)
+		return adap->orig_set_voltage(fe, voltage);
+	else
+		return 0;
+}
+
+static int pt1_sleep(struct dvb_frontend *fe)
+{
+	struct pt1_adapter *adap;
+
+	adap = container_of(fe->dvb, struct pt1_adapter, adap);
+	adap->sleep = 1;
+	pt1_update_power(adap->pt1);
+
+	if (adap->orig_sleep)
+		return adap->orig_sleep(fe);
+	else
+		return 0;
+}
+
+static int pt1_wakeup(struct dvb_frontend *fe)
+{
+	struct pt1_adapter *adap;
+
+	adap = container_of(fe->dvb, struct pt1_adapter, adap);
+	adap->sleep = 0;
+	pt1_update_power(adap->pt1);
+	schedule_timeout_uninterruptible((HZ + 999) / 1000);
+
+	if (adap->orig_init)
+		return adap->orig_init(fe);
+	else
+		return 0;
+}
+
+static void pt1_free_adapter(struct pt1_adapter *adap)
+{
+	adap->demux.dmx.close(&adap->demux.dmx);
+	dvb_dmxdev_release(&adap->dmxdev);
+	dvb_dmx_release(&adap->demux);
+	dvb_unregister_adapter(&adap->adap);
+	free_page((unsigned long)adap->buf);
+	kfree(adap);
+}
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+static struct pt1_adapter *
+pt1_alloc_adapter(struct pt1 *pt1)
+{
+	struct pt1_adapter *adap;
+	void *buf;
+	struct dvb_adapter *dvb_adap;
+	struct dvb_demux *demux;
+	struct dmxdev *dmxdev;
+	int ret;
+
+	adap = kzalloc(sizeof(struct pt1_adapter), GFP_KERNEL);
+	if (!adap) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	adap->pt1 = pt1;
+
+	adap->voltage = SEC_VOLTAGE_OFF;
+	adap->sleep = 1;
+
+	buf = (u8 *)__get_free_page(GFP_KERNEL);
+	if (!buf) {
+		ret = -ENOMEM;
+		goto err_kfree;
+	}
+
+	adap->buf = buf;
+	adap->upacket_count = 0;
+	adap->packet_count = 0;
+	adap->st_count = -1;
+
+	dvb_adap = &adap->adap;
+	dvb_adap->priv = adap;
+	ret = dvb_register_adapter(dvb_adap, DRIVER_NAME, THIS_MODULE,
+				   &pt1->pdev->dev, adapter_nr);
+	if (ret < 0)
+		goto err_free_page;
+
+	demux = &adap->demux;
+	demux->dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING;
+	demux->priv = adap;
+	demux->feednum = 256;
+	demux->filternum = 256;
+	demux->start_feed = pt1_start_feed;
+	demux->stop_feed = pt1_stop_feed;
+	demux->write_to_decoder = NULL;
+	ret = dvb_dmx_init(demux);
+	if (ret < 0)
+		goto err_unregister_adapter;
+
+	dmxdev = &adap->dmxdev;
+	dmxdev->filternum = 256;
+	dmxdev->demux = &demux->dmx;
+	dmxdev->capabilities = 0;
+	ret = dvb_dmxdev_init(dmxdev, dvb_adap);
+	if (ret < 0)
+		goto err_dmx_release;
+
+	return adap;
+
+err_dmx_release:
+	dvb_dmx_release(demux);
+err_unregister_adapter:
+	dvb_unregister_adapter(dvb_adap);
+err_free_page:
+	free_page((unsigned long)buf);
+err_kfree:
+	kfree(adap);
+err:
+	return ERR_PTR(ret);
+}
+
+static void pt1_cleanup_adapters(struct pt1 *pt1)
+{
+	int i;
+	for (i = 0; i < PT1_NR_ADAPS; i++)
+		pt1_free_adapter(pt1->adaps[i]);
+}
+
+static int pt1_init_adapters(struct pt1 *pt1)
+{
+	int i;
+	struct pt1_adapter *adap;
+	int ret;
+
+	for (i = 0; i < PT1_NR_ADAPS; i++) {
+		adap = pt1_alloc_adapter(pt1);
+		if (IS_ERR(adap)) {
+			ret = PTR_ERR(adap);
+			goto err;
+		}
+
+		adap->index = i;
+		pt1->adaps[i] = adap;
+	}
+	return 0;
+
+err:
+	while (i--)
+		pt1_free_adapter(pt1->adaps[i]);
+
+	return ret;
+}
+
+static void pt1_cleanup_frontend(struct pt1_adapter *adap)
+{
+	dvb_unregister_frontend(adap->fe);
+}
+
+static int pt1_init_frontend(struct pt1_adapter *adap, struct dvb_frontend *fe)
+{
+	int ret;
+
+	adap->orig_set_voltage = fe->ops.set_voltage;
+	adap->orig_sleep = fe->ops.sleep;
+	adap->orig_init = fe->ops.init;
+	fe->ops.set_voltage = pt1_set_voltage;
+	fe->ops.sleep = pt1_sleep;
+	fe->ops.init = pt1_wakeup;
+
+	ret = dvb_register_frontend(&adap->adap, fe);
+	if (ret < 0)
+		return ret;
+
+	adap->fe = fe;
+	return 0;
+}
+
+static void pt1_cleanup_frontends(struct pt1 *pt1)
+{
+	int i;
+	for (i = 0; i < PT1_NR_ADAPS; i++)
+		pt1_cleanup_frontend(pt1->adaps[i]);
+}
+
+struct pt1_config {
+	struct va1j5jf8007s_config va1j5jf8007s_config;
+	struct va1j5jf8007t_config va1j5jf8007t_config;
+};
+
+static const struct pt1_config pt1_configs[2] = {
+	{
+		{
+			.demod_address = 0x1b,
+			.frequency = VA1J5JF8007S_20MHZ,
+		},
+		{
+			.demod_address = 0x1a,
+			.frequency = VA1J5JF8007T_20MHZ,
+		},
+	}, {
+		{
+			.demod_address = 0x19,
+			.frequency = VA1J5JF8007S_20MHZ,
+		},
+		{
+			.demod_address = 0x18,
+			.frequency = VA1J5JF8007T_20MHZ,
+		},
+	},
+};
+
+static const struct pt1_config pt2_configs[2] = {
+	{
+		{
+			.demod_address = 0x1b,
+			.frequency = VA1J5JF8007S_25MHZ,
+		},
+		{
+			.demod_address = 0x1a,
+			.frequency = VA1J5JF8007T_25MHZ,
+		},
+	}, {
+		{
+			.demod_address = 0x19,
+			.frequency = VA1J5JF8007S_25MHZ,
+		},
+		{
+			.demod_address = 0x18,
+			.frequency = VA1J5JF8007T_25MHZ,
+		},
+	},
+};
+
+static int pt1_init_frontends(struct pt1 *pt1)
+{
+	int i, j;
+	struct i2c_adapter *i2c_adap;
+	const struct pt1_config *configs, *config;
+	struct dvb_frontend *fe[4];
+	int ret;
+
+	i = 0;
+	j = 0;
+
+	i2c_adap = &pt1->i2c_adap;
+	configs = pt1->pdev->device == 0x211a ? pt1_configs : pt2_configs;
+	do {
+		config = &configs[i / 2];
+
+		fe[i] = va1j5jf8007s_attach(&config->va1j5jf8007s_config,
+					    i2c_adap);
+		if (!fe[i]) {
+			ret = -ENODEV; /* This does not sound nice... */
+			goto err;
+		}
+		i++;
+
+		fe[i] = va1j5jf8007t_attach(&config->va1j5jf8007t_config,
+					    i2c_adap);
+		if (!fe[i]) {
+			ret = -ENODEV;
+			goto err;
+		}
+		i++;
+
+		ret = va1j5jf8007s_prepare(fe[i - 2]);
+		if (ret < 0)
+			goto err;
+
+		ret = va1j5jf8007t_prepare(fe[i - 1]);
+		if (ret < 0)
+			goto err;
+
+	} while (i < 4);
+
+	do {
+		ret = pt1_init_frontend(pt1->adaps[j], fe[j]);
+		if (ret < 0)
+			goto err;
+	} while (++j < 4);
+
+	return 0;
+
+err:
+	while (i-- > j)
+		fe[i]->ops.release(fe[i]);
+
+	while (j--)
+		dvb_unregister_frontend(fe[j]);
+
+	return ret;
+}
+
+static void pt1_i2c_emit(struct pt1 *pt1, int addr, int busy, int read_enable,
+			 int clock, int data, int next_addr)
+{
+	pt1_write_reg(pt1, 4, addr << 18 | busy << 13 | read_enable << 12 |
+		      !clock << 11 | !data << 10 | next_addr);
+}
+
+static void pt1_i2c_write_bit(struct pt1 *pt1, int addr, int *addrp, int data)
+{
+	pt1_i2c_emit(pt1, addr,     1, 0, 0, data, addr + 1);
+	pt1_i2c_emit(pt1, addr + 1, 1, 0, 1, data, addr + 2);
+	pt1_i2c_emit(pt1, addr + 2, 1, 0, 0, data, addr + 3);
+	*addrp = addr + 3;
+}
+
+static void pt1_i2c_read_bit(struct pt1 *pt1, int addr, int *addrp)
+{
+	pt1_i2c_emit(pt1, addr,     1, 0, 0, 1, addr + 1);
+	pt1_i2c_emit(pt1, addr + 1, 1, 0, 1, 1, addr + 2);
+	pt1_i2c_emit(pt1, addr + 2, 1, 1, 1, 1, addr + 3);
+	pt1_i2c_emit(pt1, addr + 3, 1, 0, 0, 1, addr + 4);
+	*addrp = addr + 4;
+}
+
+static void pt1_i2c_write_byte(struct pt1 *pt1, int addr, int *addrp, int data)
+{
+	int i;
+	for (i = 0; i < 8; i++)
+		pt1_i2c_write_bit(pt1, addr, &addr, data >> (7 - i) & 1);
+	pt1_i2c_write_bit(pt1, addr, &addr, 1);
+	*addrp = addr;
+}
+
+static void pt1_i2c_read_byte(struct pt1 *pt1, int addr, int *addrp, int last)
+{
+	int i;
+	for (i = 0; i < 8; i++)
+		pt1_i2c_read_bit(pt1, addr, &addr);
+	pt1_i2c_write_bit(pt1, addr, &addr, last);
+	*addrp = addr;
+}
+
+static void pt1_i2c_prepare(struct pt1 *pt1, int addr, int *addrp)
+{
+	pt1_i2c_emit(pt1, addr,     1, 0, 1, 1, addr + 1);
+	pt1_i2c_emit(pt1, addr + 1, 1, 0, 1, 0, addr + 2);
+	pt1_i2c_emit(pt1, addr + 2, 1, 0, 0, 0, addr + 3);
+	*addrp = addr + 3;
+}
+
+static void
+pt1_i2c_write_msg(struct pt1 *pt1, int addr, int *addrp, struct i2c_msg *msg)
+{
+	int i;
+	pt1_i2c_prepare(pt1, addr, &addr);
+	pt1_i2c_write_byte(pt1, addr, &addr, msg->addr << 1);
+	for (i = 0; i < msg->len; i++)
+		pt1_i2c_write_byte(pt1, addr, &addr, msg->buf[i]);
+	*addrp = addr;
+}
+
+static void
+pt1_i2c_read_msg(struct pt1 *pt1, int addr, int *addrp, struct i2c_msg *msg)
+{
+	int i;
+	pt1_i2c_prepare(pt1, addr, &addr);
+	pt1_i2c_write_byte(pt1, addr, &addr, msg->addr << 1 | 1);
+	for (i = 0; i < msg->len; i++)
+		pt1_i2c_read_byte(pt1, addr, &addr, i == msg->len - 1);
+	*addrp = addr;
+}
+
+static int pt1_i2c_end(struct pt1 *pt1, int addr)
+{
+	pt1_i2c_emit(pt1, addr,     1, 0, 0, 0, addr + 1);
+	pt1_i2c_emit(pt1, addr + 1, 1, 0, 1, 0, addr + 2);
+	pt1_i2c_emit(pt1, addr + 2, 1, 0, 1, 1, 0);
+
+	pt1_write_reg(pt1, 0, 0x00000004);
+	do {
+		if (signal_pending(current))
+			return -EINTR;
+		schedule_timeout_interruptible((HZ + 999) / 1000);
+	} while (pt1_read_reg(pt1, 0) & 0x00000080);
+	return 0;
+}
+
+static void pt1_i2c_begin(struct pt1 *pt1, int *addrp)
+{
+	int addr;
+	addr = 0;
+
+	pt1_i2c_emit(pt1, addr,     0, 0, 1, 1, addr /* itself */);
+	addr = addr + 1;
+
+	if (!pt1->i2c_running) {
+		pt1_i2c_emit(pt1, addr,     1, 0, 1, 1, addr + 1);
+		pt1_i2c_emit(pt1, addr + 1, 1, 0, 1, 0, addr + 2);
+		addr = addr + 2;
+		pt1->i2c_running = 1;
+	}
+	*addrp = addr;
+}
+
+static int pt1_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
+{
+	struct pt1 *pt1;
+	int i;
+	struct i2c_msg *msg, *next_msg;
+	int addr, ret;
+	u16 len;
+	u32 word;
+
+	pt1 = i2c_get_adapdata(adap);
+
+	for (i = 0; i < num; i++) {
+		msg = &msgs[i];
+		if (msg->flags & I2C_M_RD)
+			return -ENOTSUPP;
+
+		if (i + 1 < num)
+			next_msg = &msgs[i + 1];
+		else
+			next_msg = NULL;
+
+		if (next_msg && next_msg->flags & I2C_M_RD) {
+			i++;
+
+			len = next_msg->len;
+			if (len > 4)
+				return -ENOTSUPP;
+
+			pt1_i2c_begin(pt1, &addr);
+			pt1_i2c_write_msg(pt1, addr, &addr, msg);
+			pt1_i2c_read_msg(pt1, addr, &addr, next_msg);
+			ret = pt1_i2c_end(pt1, addr);
+			if (ret < 0)
+				return ret;
+
+			word = pt1_read_reg(pt1, 2);
+			while (len--) {
+				next_msg->buf[len] = word;
+				word >>= 8;
+			}
+		} else {
+			pt1_i2c_begin(pt1, &addr);
+			pt1_i2c_write_msg(pt1, addr, &addr, msg);
+			ret = pt1_i2c_end(pt1, addr);
+			if (ret < 0)
+				return ret;
+		}
+	}
+
+	return num;
+}
+
+static u32 pt1_i2c_func(struct i2c_adapter *adap)
+{
+	return I2C_FUNC_I2C;
+}
+
+static const struct i2c_algorithm pt1_i2c_algo = {
+	.master_xfer = pt1_i2c_xfer,
+	.functionality = pt1_i2c_func,
+};
+
+static void pt1_i2c_wait(struct pt1 *pt1)
+{
+	int i;
+	for (i = 0; i < 128; i++)
+		pt1_i2c_emit(pt1, 0, 0, 0, 1, 1, 0);
+}
+
+static void pt1_i2c_init(struct pt1 *pt1)
+{
+	int i;
+	for (i = 0; i < 1024; i++)
+		pt1_i2c_emit(pt1, i, 0, 0, 1, 1, 0);
+}
+
+static void __devexit pt1_remove(struct pci_dev *pdev)
+{
+	struct pt1 *pt1;
+	void __iomem *regs;
+
+	pt1 = pci_get_drvdata(pdev);
+	regs = pt1->regs;
+
+	if (pt1->kthread)
+		kthread_stop(pt1->kthread);
+	pt1_cleanup_tables(pt1);
+	pt1_cleanup_frontends(pt1);
+	pt1_disable_ram(pt1);
+	pt1->power = 0;
+	pt1->reset = 1;
+	pt1_update_power(pt1);
+	pt1_cleanup_adapters(pt1);
+	i2c_del_adapter(&pt1->i2c_adap);
+	pci_set_drvdata(pdev, NULL);
+	kfree(pt1);
+	pci_iounmap(pdev, regs);
+	pci_release_regions(pdev);
+	pci_disable_device(pdev);
+}
+
+static int __devinit
+pt1_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	int ret;
+	void __iomem *regs;
+	struct pt1 *pt1;
+	struct i2c_adapter *i2c_adap;
+
+	ret = pci_enable_device(pdev);
+	if (ret < 0)
+		goto err;
+
+	ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+	if (ret < 0)
+		goto err_pci_disable_device;
+
+	pci_set_master(pdev);
+
+	ret = pci_request_regions(pdev, DRIVER_NAME);
+	if (ret < 0)
+		goto err_pci_disable_device;
+
+	regs = pci_iomap(pdev, 0, 0);
+	if (!regs) {
+		ret = -EIO;
+		goto err_pci_release_regions;
+	}
+
+	pt1 = kzalloc(sizeof(struct pt1), GFP_KERNEL);
+	if (!pt1) {
+		ret = -ENOMEM;
+		goto err_pci_iounmap;
+	}
+
+	mutex_init(&pt1->lock);
+	pt1->pdev = pdev;
+	pt1->regs = regs;
+	pci_set_drvdata(pdev, pt1);
+
+	ret = pt1_init_adapters(pt1);
+	if (ret < 0)
+		goto err_kfree;
+
+	mutex_init(&pt1->lock);
+
+	pt1->power = 0;
+	pt1->reset = 1;
+	pt1_update_power(pt1);
+
+	i2c_adap = &pt1->i2c_adap;
+	i2c_adap->algo = &pt1_i2c_algo;
+	i2c_adap->algo_data = NULL;
+	i2c_adap->dev.parent = &pdev->dev;
+	strcpy(i2c_adap->name, DRIVER_NAME);
+	i2c_set_adapdata(i2c_adap, pt1);
+	ret = i2c_add_adapter(i2c_adap);
+	if (ret < 0)
+		goto err_pt1_cleanup_adapters;
+
+	pt1_i2c_init(pt1);
+	pt1_i2c_wait(pt1);
+
+	ret = pt1_sync(pt1);
+	if (ret < 0)
+		goto err_i2c_del_adapter;
+
+	pt1_identify(pt1);
+
+	ret = pt1_unlock(pt1);
+	if (ret < 0)
+		goto err_i2c_del_adapter;
+
+	ret = pt1_reset_pci(pt1);
+	if (ret < 0)
+		goto err_i2c_del_adapter;
+
+	ret = pt1_reset_ram(pt1);
+	if (ret < 0)
+		goto err_i2c_del_adapter;
+
+	ret = pt1_enable_ram(pt1);
+	if (ret < 0)
+		goto err_i2c_del_adapter;
+
+	pt1_init_streams(pt1);
+
+	pt1->power = 1;
+	pt1_update_power(pt1);
+	schedule_timeout_uninterruptible((HZ + 49) / 50);
+
+	pt1->reset = 0;
+	pt1_update_power(pt1);
+	schedule_timeout_uninterruptible((HZ + 999) / 1000);
+
+	ret = pt1_init_frontends(pt1);
+	if (ret < 0)
+		goto err_pt1_disable_ram;
+
+	ret = pt1_init_tables(pt1);
+	if (ret < 0)
+		goto err_pt1_cleanup_frontends;
+
+	return 0;
+
+err_pt1_cleanup_frontends:
+	pt1_cleanup_frontends(pt1);
+err_pt1_disable_ram:
+	pt1_disable_ram(pt1);
+	pt1->power = 0;
+	pt1->reset = 1;
+	pt1_update_power(pt1);
+err_i2c_del_adapter:
+	i2c_del_adapter(i2c_adap);
+err_pt1_cleanup_adapters:
+	pt1_cleanup_adapters(pt1);
+err_kfree:
+	pci_set_drvdata(pdev, NULL);
+	kfree(pt1);
+err_pci_iounmap:
+	pci_iounmap(pdev, regs);
+err_pci_release_regions:
+	pci_release_regions(pdev);
+err_pci_disable_device:
+	pci_disable_device(pdev);
+err:
+	return ret;
+
+}
+
+static struct pci_device_id pt1_id_table[] = {
+	{ PCI_DEVICE(0x10ee, 0x211a) },
+	{ PCI_DEVICE(0x10ee, 0x222a) },
+	{ },
+};
+MODULE_DEVICE_TABLE(pci, pt1_id_table);
+
+static struct pci_driver pt1_driver = {
+	.name		= DRIVER_NAME,
+	.probe		= pt1_probe,
+	.remove		= __devexit_p(pt1_remove),
+	.id_table	= pt1_id_table,
+};
+
+
+static int __init pt1_init(void)
+{
+	return pci_register_driver(&pt1_driver);
+}
+
+
+static void __exit pt1_cleanup(void)
+{
+	pci_unregister_driver(&pt1_driver);
+}
+
+module_init(pt1_init);
+module_exit(pt1_cleanup);
+
+MODULE_AUTHOR("Takahito HIRANO <hiranotaka@zng.info>");
+MODULE_DESCRIPTION("Earthsoft PT1/PT2 Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/pci/pt1/va1j5jf8007s.c b/drivers/media/pci/pt1/va1j5jf8007s.c
new file mode 100644
index 0000000..1b637b7
--- /dev/null
+++ b/drivers/media/pci/pt1/va1j5jf8007s.c
@@ -0,0 +1,736 @@
+/*
+ * ISDB-S driver for VA1J5JF8007/VA1J5JF8011
+ *
+ * Copyright (C) 2009 HIRANO Takahito <hiranotaka@zng.info>
+ *
+ * based on pt1dvr - http://pt1dvr.sourceforge.jp/
+ * 	by Tomoaki Ishikawa <tomy@users.sourceforge.jp>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/slab.h>
+#include <linux/i2c.h>
+#include "dvb_frontend.h"
+#include "va1j5jf8007s.h"
+
+enum va1j5jf8007s_tune_state {
+	VA1J5JF8007S_IDLE,
+	VA1J5JF8007S_SET_FREQUENCY_1,
+	VA1J5JF8007S_SET_FREQUENCY_2,
+	VA1J5JF8007S_SET_FREQUENCY_3,
+	VA1J5JF8007S_CHECK_FREQUENCY,
+	VA1J5JF8007S_SET_MODULATION,
+	VA1J5JF8007S_CHECK_MODULATION,
+	VA1J5JF8007S_SET_TS_ID,
+	VA1J5JF8007S_CHECK_TS_ID,
+	VA1J5JF8007S_TRACK,
+};
+
+struct va1j5jf8007s_state {
+	const struct va1j5jf8007s_config *config;
+	struct i2c_adapter *adap;
+	struct dvb_frontend fe;
+	enum va1j5jf8007s_tune_state tune_state;
+};
+
+static int va1j5jf8007s_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+	struct va1j5jf8007s_state *state;
+	u8 addr;
+	int i;
+	u8 write_buf[1], read_buf[1];
+	struct i2c_msg msgs[2];
+	s32 word, x1, x2, x3, x4, x5, y;
+
+	state = fe->demodulator_priv;
+	addr = state->config->demod_address;
+
+	word = 0;
+	for (i = 0; i < 2; i++) {
+		write_buf[0] = 0xbc + i;
+
+		msgs[0].addr = addr;
+		msgs[0].flags = 0;
+		msgs[0].len = sizeof(write_buf);
+		msgs[0].buf = write_buf;
+
+		msgs[1].addr = addr;
+		msgs[1].flags = I2C_M_RD;
+		msgs[1].len = sizeof(read_buf);
+		msgs[1].buf = read_buf;
+
+		if (i2c_transfer(state->adap, msgs, 2) != 2)
+			return -EREMOTEIO;
+
+		word <<= 8;
+		word |= read_buf[0];
+	}
+
+	word -= 3000;
+	if (word < 0)
+		word = 0;
+
+	x1 = int_sqrt(word << 16) * ((15625ll << 21) / 1000000);
+	x2 = (s64)x1 * x1 >> 31;
+	x3 = (s64)x2 * x1 >> 31;
+	x4 = (s64)x2 * x2 >> 31;
+	x5 = (s64)x4 * x1 >> 31;
+
+	y = (58857ll << 23) / 1000;
+	y -= (s64)x1 * ((89565ll << 24) / 1000) >> 30;
+	y += (s64)x2 * ((88977ll << 24) / 1000) >> 28;
+	y -= (s64)x3 * ((50259ll << 25) / 1000) >> 27;
+	y += (s64)x4 * ((14341ll << 27) / 1000) >> 27;
+	y -= (s64)x5 * ((16346ll << 30) / 10000) >> 28;
+
+	*snr = y < 0 ? 0 : y >> 15;
+	return 0;
+}
+
+static int va1j5jf8007s_get_frontend_algo(struct dvb_frontend *fe)
+{
+	return DVBFE_ALGO_HW;
+}
+
+static int
+va1j5jf8007s_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+	struct va1j5jf8007s_state *state;
+
+	state = fe->demodulator_priv;
+
+	switch (state->tune_state) {
+	case VA1J5JF8007S_IDLE:
+	case VA1J5JF8007S_SET_FREQUENCY_1:
+	case VA1J5JF8007S_SET_FREQUENCY_2:
+	case VA1J5JF8007S_SET_FREQUENCY_3:
+	case VA1J5JF8007S_CHECK_FREQUENCY:
+		*status = 0;
+		return 0;
+
+
+	case VA1J5JF8007S_SET_MODULATION:
+	case VA1J5JF8007S_CHECK_MODULATION:
+		*status |= FE_HAS_SIGNAL;
+		return 0;
+
+	case VA1J5JF8007S_SET_TS_ID:
+	case VA1J5JF8007S_CHECK_TS_ID:
+		*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER;
+		return 0;
+
+	case VA1J5JF8007S_TRACK:
+		*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_LOCK;
+		return 0;
+	}
+
+	BUG();
+}
+
+struct va1j5jf8007s_cb_map {
+	u32 frequency;
+	u8 cb;
+};
+
+static const struct va1j5jf8007s_cb_map va1j5jf8007s_cb_maps[] = {
+	{  986000, 0xb2 },
+	{ 1072000, 0xd2 },
+	{ 1154000, 0xe2 },
+	{ 1291000, 0x20 },
+	{ 1447000, 0x40 },
+	{ 1615000, 0x60 },
+	{ 1791000, 0x80 },
+	{ 1972000, 0xa0 },
+};
+
+static u8 va1j5jf8007s_lookup_cb(u32 frequency)
+{
+	int i;
+	const struct va1j5jf8007s_cb_map *map;
+
+	for (i = 0; i < ARRAY_SIZE(va1j5jf8007s_cb_maps); i++) {
+		map = &va1j5jf8007s_cb_maps[i];
+		if (frequency < map->frequency)
+			return map->cb;
+	}
+	return 0xc0;
+}
+
+static int va1j5jf8007s_set_frequency_1(struct va1j5jf8007s_state *state)
+{
+	u32 frequency;
+	u16 word;
+	u8 buf[6];
+	struct i2c_msg msg;
+
+	frequency = state->fe.dtv_property_cache.frequency;
+
+	word = (frequency + 500) / 1000;
+	if (frequency < 1072000)
+		word = (word << 1 & ~0x1f) | (word & 0x0f);
+
+	buf[0] = 0xfe;
+	buf[1] = 0xc0;
+	buf[2] = 0x40 | word >> 8;
+	buf[3] = word;
+	buf[4] = 0xe0;
+	buf[5] = va1j5jf8007s_lookup_cb(frequency);
+
+	msg.addr = state->config->demod_address;
+	msg.flags = 0;
+	msg.len = sizeof(buf);
+	msg.buf = buf;
+
+	if (i2c_transfer(state->adap, &msg, 1) != 1)
+		return -EREMOTEIO;
+
+	return 0;
+}
+
+static int va1j5jf8007s_set_frequency_2(struct va1j5jf8007s_state *state)
+{
+	u8 buf[3];
+	struct i2c_msg msg;
+
+	buf[0] = 0xfe;
+	buf[1] = 0xc0;
+	buf[2] = 0xe4;
+
+	msg.addr = state->config->demod_address;
+	msg.flags = 0;
+	msg.len = sizeof(buf);
+	msg.buf = buf;
+
+	if (i2c_transfer(state->adap, &msg, 1) != 1)
+		return -EREMOTEIO;
+
+	return 0;
+}
+
+static int va1j5jf8007s_set_frequency_3(struct va1j5jf8007s_state *state)
+{
+	u32 frequency;
+	u8 buf[4];
+	struct i2c_msg msg;
+
+	frequency = state->fe.dtv_property_cache.frequency;
+
+	buf[0] = 0xfe;
+	buf[1] = 0xc0;
+	buf[2] = 0xf4;
+	buf[3] = va1j5jf8007s_lookup_cb(frequency) | 0x4;
+
+	msg.addr = state->config->demod_address;
+	msg.flags = 0;
+	msg.len = sizeof(buf);
+	msg.buf = buf;
+
+	if (i2c_transfer(state->adap, &msg, 1) != 1)
+		return -EREMOTEIO;
+
+	return 0;
+}
+
+static int
+va1j5jf8007s_check_frequency(struct va1j5jf8007s_state *state, int *lock)
+{
+	u8 addr;
+	u8 write_buf[2], read_buf[1];
+	struct i2c_msg msgs[2];
+
+	addr = state->config->demod_address;
+
+	write_buf[0] = 0xfe;
+	write_buf[1] = 0xc1;
+
+	msgs[0].addr = addr;
+	msgs[0].flags = 0;
+	msgs[0].len = sizeof(write_buf);
+	msgs[0].buf = write_buf;
+
+	msgs[1].addr = addr;
+	msgs[1].flags = I2C_M_RD;
+	msgs[1].len = sizeof(read_buf);
+	msgs[1].buf = read_buf;
+
+	if (i2c_transfer(state->adap, msgs, 2) != 2)
+		return -EREMOTEIO;
+
+	*lock = read_buf[0] & 0x40;
+	return 0;
+}
+
+static int va1j5jf8007s_set_modulation(struct va1j5jf8007s_state *state)
+{
+	u8 buf[2];
+	struct i2c_msg msg;
+
+	buf[0] = 0x03;
+	buf[1] = 0x01;
+
+	msg.addr = state->config->demod_address;
+	msg.flags = 0;
+	msg.len = sizeof(buf);
+	msg.buf = buf;
+
+	if (i2c_transfer(state->adap, &msg, 1) != 1)
+		return -EREMOTEIO;
+
+	return 0;
+}
+
+static int
+va1j5jf8007s_check_modulation(struct va1j5jf8007s_state *state, int *lock)
+{
+	u8 addr;
+	u8 write_buf[1], read_buf[1];
+	struct i2c_msg msgs[2];
+
+	addr = state->config->demod_address;
+
+	write_buf[0] = 0xc3;
+
+	msgs[0].addr = addr;
+	msgs[0].flags = 0;
+	msgs[0].len = sizeof(write_buf);
+	msgs[0].buf = write_buf;
+
+	msgs[1].addr = addr;
+	msgs[1].flags = I2C_M_RD;
+	msgs[1].len = sizeof(read_buf);
+	msgs[1].buf = read_buf;
+
+	if (i2c_transfer(state->adap, msgs, 2) != 2)
+		return -EREMOTEIO;
+
+	*lock = !(read_buf[0] & 0x10);
+	return 0;
+}
+
+static int
+va1j5jf8007s_set_ts_id(struct va1j5jf8007s_state *state)
+{
+	u32 ts_id;
+	u8 buf[3];
+	struct i2c_msg msg;
+
+	ts_id = state->fe.dtv_property_cache.stream_id;
+	if (!ts_id || ts_id == NO_STREAM_ID_FILTER)
+		return 0;
+
+	buf[0] = 0x8f;
+	buf[1] = ts_id >> 8;
+	buf[2] = ts_id;
+
+	msg.addr = state->config->demod_address;
+	msg.flags = 0;
+	msg.len = sizeof(buf);
+	msg.buf = buf;
+
+	if (i2c_transfer(state->adap, &msg, 1) != 1)
+		return -EREMOTEIO;
+
+	return 0;
+}
+
+static int
+va1j5jf8007s_check_ts_id(struct va1j5jf8007s_state *state, int *lock)
+{
+	u8 addr;
+	u8 write_buf[1], read_buf[2];
+	struct i2c_msg msgs[2];
+	u32 ts_id;
+
+	ts_id = state->fe.dtv_property_cache.stream_id;
+	if (!ts_id || ts_id == NO_STREAM_ID_FILTER) {
+		*lock = 1;
+		return 0;
+	}
+
+	addr = state->config->demod_address;
+
+	write_buf[0] = 0xe6;
+
+	msgs[0].addr = addr;
+	msgs[0].flags = 0;
+	msgs[0].len = sizeof(write_buf);
+	msgs[0].buf = write_buf;
+
+	msgs[1].addr = addr;
+	msgs[1].flags = I2C_M_RD;
+	msgs[1].len = sizeof(read_buf);
+	msgs[1].buf = read_buf;
+
+	if (i2c_transfer(state->adap, msgs, 2) != 2)
+		return -EREMOTEIO;
+
+	*lock = (read_buf[0] << 8 | read_buf[1]) == ts_id;
+	return 0;
+}
+
+static int
+va1j5jf8007s_tune(struct dvb_frontend *fe,
+		  bool re_tune,
+		  unsigned int mode_flags,  unsigned int *delay,
+		  fe_status_t *status)
+{
+	struct va1j5jf8007s_state *state;
+	int ret;
+	int lock = 0;
+
+	state = fe->demodulator_priv;
+
+	if (re_tune)
+		state->tune_state = VA1J5JF8007S_SET_FREQUENCY_1;
+
+	switch (state->tune_state) {
+	case VA1J5JF8007S_IDLE:
+		*delay = 3 * HZ;
+		*status = 0;
+		return 0;
+
+	case VA1J5JF8007S_SET_FREQUENCY_1:
+		ret = va1j5jf8007s_set_frequency_1(state);
+		if (ret < 0)
+			return ret;
+
+		state->tune_state = VA1J5JF8007S_SET_FREQUENCY_2;
+		*delay = 0;
+		*status = 0;
+		return 0;
+
+	case VA1J5JF8007S_SET_FREQUENCY_2:
+		ret = va1j5jf8007s_set_frequency_2(state);
+		if (ret < 0)
+			return ret;
+
+		state->tune_state = VA1J5JF8007S_SET_FREQUENCY_3;
+		*delay = (HZ + 99) / 100;
+		*status = 0;
+		return 0;
+
+	case VA1J5JF8007S_SET_FREQUENCY_3:
+		ret = va1j5jf8007s_set_frequency_3(state);
+		if (ret < 0)
+			return ret;
+
+		state->tune_state = VA1J5JF8007S_CHECK_FREQUENCY;
+		*delay = 0;
+		*status = 0;
+		return 0;
+
+	case VA1J5JF8007S_CHECK_FREQUENCY:
+		ret = va1j5jf8007s_check_frequency(state, &lock);
+		if (ret < 0)
+			return ret;
+
+		if (!lock)  {
+			*delay = (HZ + 999) / 1000;
+			*status = 0;
+			return 0;
+		}
+
+		state->tune_state = VA1J5JF8007S_SET_MODULATION;
+		*delay = 0;
+		*status = FE_HAS_SIGNAL;
+		return 0;
+
+	case VA1J5JF8007S_SET_MODULATION:
+		ret = va1j5jf8007s_set_modulation(state);
+		if (ret < 0)
+			return ret;
+
+		state->tune_state = VA1J5JF8007S_CHECK_MODULATION;
+		*delay = 0;
+		*status = FE_HAS_SIGNAL;
+		return 0;
+
+	case VA1J5JF8007S_CHECK_MODULATION:
+		ret = va1j5jf8007s_check_modulation(state, &lock);
+		if (ret < 0)
+			return ret;
+
+		if (!lock)  {
+			*delay = (HZ + 49) / 50;
+			*status = FE_HAS_SIGNAL;
+			return 0;
+		}
+
+		state->tune_state = VA1J5JF8007S_SET_TS_ID;
+		*delay = 0;
+		*status = FE_HAS_SIGNAL | FE_HAS_CARRIER;
+		return 0;
+
+	case VA1J5JF8007S_SET_TS_ID:
+		ret = va1j5jf8007s_set_ts_id(state);
+		if (ret < 0)
+			return ret;
+
+		state->tune_state = VA1J5JF8007S_CHECK_TS_ID;
+		return 0;
+
+	case VA1J5JF8007S_CHECK_TS_ID:
+		ret = va1j5jf8007s_check_ts_id(state, &lock);
+		if (ret < 0)
+			return ret;
+
+		if (!lock)  {
+			*delay = (HZ + 99) / 100;
+			*status = FE_HAS_SIGNAL | FE_HAS_CARRIER;
+			return 0;
+		}
+
+		state->tune_state = VA1J5JF8007S_TRACK;
+		/* fall through */
+
+	case VA1J5JF8007S_TRACK:
+		*delay = 3 * HZ;
+		*status = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_LOCK;
+		return 0;
+	}
+
+	BUG();
+}
+
+static int va1j5jf8007s_init_frequency(struct va1j5jf8007s_state *state)
+{
+	u8 buf[4];
+	struct i2c_msg msg;
+
+	buf[0] = 0xfe;
+	buf[1] = 0xc0;
+	buf[2] = 0xf0;
+	buf[3] = 0x04;
+
+	msg.addr = state->config->demod_address;
+	msg.flags = 0;
+	msg.len = sizeof(buf);
+	msg.buf = buf;
+
+	if (i2c_transfer(state->adap, &msg, 1) != 1)
+		return -EREMOTEIO;
+
+	return 0;
+}
+
+static int va1j5jf8007s_set_sleep(struct va1j5jf8007s_state *state, int sleep)
+{
+	u8 buf[2];
+	struct i2c_msg msg;
+
+	buf[0] = 0x17;
+	buf[1] = sleep ? 0x01 : 0x00;
+
+	msg.addr = state->config->demod_address;
+	msg.flags = 0;
+	msg.len = sizeof(buf);
+	msg.buf = buf;
+
+	if (i2c_transfer(state->adap, &msg, 1) != 1)
+		return -EREMOTEIO;
+
+	return 0;
+}
+
+static int va1j5jf8007s_sleep(struct dvb_frontend *fe)
+{
+	struct va1j5jf8007s_state *state;
+	int ret;
+
+	state = fe->demodulator_priv;
+
+	ret = va1j5jf8007s_init_frequency(state);
+	if (ret < 0)
+		return ret;
+
+	return va1j5jf8007s_set_sleep(state, 1);
+}
+
+static int va1j5jf8007s_init(struct dvb_frontend *fe)
+{
+	struct va1j5jf8007s_state *state;
+
+	state = fe->demodulator_priv;
+	state->tune_state = VA1J5JF8007S_IDLE;
+
+	return va1j5jf8007s_set_sleep(state, 0);
+}
+
+static void va1j5jf8007s_release(struct dvb_frontend *fe)
+{
+	struct va1j5jf8007s_state *state;
+	state = fe->demodulator_priv;
+	kfree(state);
+}
+
+static struct dvb_frontend_ops va1j5jf8007s_ops = {
+	.delsys = { SYS_ISDBS },
+	.info = {
+		.name = "VA1J5JF8007/VA1J5JF8011 ISDB-S",
+		.frequency_min = 950000,
+		.frequency_max = 2150000,
+		.frequency_stepsize = 1000,
+		.caps = FE_CAN_INVERSION_AUTO | FE_CAN_FEC_AUTO |
+			FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO |
+			FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO |
+			FE_CAN_MULTISTREAM,
+	},
+
+	.read_snr = va1j5jf8007s_read_snr,
+	.get_frontend_algo = va1j5jf8007s_get_frontend_algo,
+	.read_status = va1j5jf8007s_read_status,
+	.tune = va1j5jf8007s_tune,
+	.sleep = va1j5jf8007s_sleep,
+	.init = va1j5jf8007s_init,
+	.release = va1j5jf8007s_release,
+};
+
+static int va1j5jf8007s_prepare_1(struct va1j5jf8007s_state *state)
+{
+	u8 addr;
+	u8 write_buf[1], read_buf[1];
+	struct i2c_msg msgs[2];
+
+	addr = state->config->demod_address;
+
+	write_buf[0] = 0x07;
+
+	msgs[0].addr = addr;
+	msgs[0].flags = 0;
+	msgs[0].len = sizeof(write_buf);
+	msgs[0].buf = write_buf;
+
+	msgs[1].addr = addr;
+	msgs[1].flags = I2C_M_RD;
+	msgs[1].len = sizeof(read_buf);
+	msgs[1].buf = read_buf;
+
+	if (i2c_transfer(state->adap, msgs, 2) != 2)
+		return -EREMOTEIO;
+
+	if (read_buf[0] != 0x41)
+		return -EIO;
+
+	return 0;
+}
+
+static const u8 va1j5jf8007s_20mhz_prepare_bufs[][2] = {
+	{0x04, 0x02}, {0x0d, 0x55}, {0x11, 0x40}, {0x13, 0x80}, {0x17, 0x01},
+	{0x1c, 0x0a}, {0x1d, 0xaa}, {0x1e, 0x20}, {0x1f, 0x88}, {0x51, 0xb0},
+	{0x52, 0x89}, {0x53, 0xb3}, {0x5a, 0x2d}, {0x5b, 0xd3}, {0x85, 0x69},
+	{0x87, 0x04}, {0x8e, 0x02}, {0xa3, 0xf7}, {0xa5, 0xc0},
+};
+
+static const u8 va1j5jf8007s_25mhz_prepare_bufs[][2] = {
+	{0x04, 0x02}, {0x11, 0x40}, {0x13, 0x80}, {0x17, 0x01}, {0x1c, 0x0a},
+	{0x1d, 0xaa}, {0x1e, 0x20}, {0x1f, 0x88}, {0x51, 0xb0}, {0x52, 0x89},
+	{0x53, 0xb3}, {0x5a, 0x2d}, {0x5b, 0xd3}, {0x85, 0x69}, {0x87, 0x04},
+	{0x8e, 0x26}, {0xa3, 0xf7}, {0xa5, 0xc0},
+};
+
+static int va1j5jf8007s_prepare_2(struct va1j5jf8007s_state *state)
+{
+	const u8 (*bufs)[2];
+	int size;
+	u8 addr;
+	u8 buf[2];
+	struct i2c_msg msg;
+	int i;
+
+	switch (state->config->frequency) {
+	case VA1J5JF8007S_20MHZ:
+		bufs = va1j5jf8007s_20mhz_prepare_bufs;
+		size = ARRAY_SIZE(va1j5jf8007s_20mhz_prepare_bufs);
+		break;
+	case VA1J5JF8007S_25MHZ:
+		bufs = va1j5jf8007s_25mhz_prepare_bufs;
+		size = ARRAY_SIZE(va1j5jf8007s_25mhz_prepare_bufs);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	addr = state->config->demod_address;
+
+	msg.addr = addr;
+	msg.flags = 0;
+	msg.len = 2;
+	msg.buf = buf;
+	for (i = 0; i < size; i++) {
+		memcpy(buf, bufs[i], sizeof(buf));
+		if (i2c_transfer(state->adap, &msg, 1) != 1)
+			return -EREMOTEIO;
+	}
+
+	return 0;
+}
+
+/* must be called after va1j5jf8007t_attach */
+int va1j5jf8007s_prepare(struct dvb_frontend *fe)
+{
+	struct va1j5jf8007s_state *state;
+	int ret;
+
+	state = fe->demodulator_priv;
+
+	ret = va1j5jf8007s_prepare_1(state);
+	if (ret < 0)
+		return ret;
+
+	ret = va1j5jf8007s_prepare_2(state);
+	if (ret < 0)
+		return ret;
+
+	return va1j5jf8007s_init_frequency(state);
+}
+
+struct dvb_frontend *
+va1j5jf8007s_attach(const struct va1j5jf8007s_config *config,
+		    struct i2c_adapter *adap)
+{
+	struct va1j5jf8007s_state *state;
+	struct dvb_frontend *fe;
+	u8 buf[2];
+	struct i2c_msg msg;
+
+	state = kzalloc(sizeof(struct va1j5jf8007s_state), GFP_KERNEL);
+	if (!state)
+		return NULL;
+
+	state->config = config;
+	state->adap = adap;
+
+	fe = &state->fe;
+	memcpy(&fe->ops, &va1j5jf8007s_ops, sizeof(struct dvb_frontend_ops));
+	fe->demodulator_priv = state;
+
+	buf[0] = 0x01;
+	buf[1] = 0x80;
+
+	msg.addr = state->config->demod_address;
+	msg.flags = 0;
+	msg.len = sizeof(buf);
+	msg.buf = buf;
+
+	if (i2c_transfer(state->adap, &msg, 1) != 1) {
+		kfree(state);
+		return NULL;
+	}
+
+	return fe;
+}
diff --git a/drivers/media/pci/pt1/va1j5jf8007s.h b/drivers/media/pci/pt1/va1j5jf8007s.h
new file mode 100644
index 0000000..b7d6f05
--- /dev/null
+++ b/drivers/media/pci/pt1/va1j5jf8007s.h
@@ -0,0 +1,46 @@
+/*
+ * ISDB-S driver for VA1J5JF8007/VA1J5JF8011
+ *
+ * Copyright (C) 2009 HIRANO Takahito <hiranotaka@zng.info>
+ *
+ * based on pt1dvr - http://pt1dvr.sourceforge.jp/
+ * 	by Tomoaki Ishikawa <tomy@users.sourceforge.jp>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 VA1J5JF8007S_H
+#define VA1J5JF8007S_H
+
+enum va1j5jf8007s_frequency {
+	VA1J5JF8007S_20MHZ,
+	VA1J5JF8007S_25MHZ,
+};
+
+struct va1j5jf8007s_config {
+	u8 demod_address;
+	enum va1j5jf8007s_frequency frequency;
+};
+
+struct i2c_adapter;
+
+struct dvb_frontend *
+va1j5jf8007s_attach(const struct va1j5jf8007s_config *config,
+		    struct i2c_adapter *adap);
+
+/* must be called after va1j5jf8007t_attach */
+int va1j5jf8007s_prepare(struct dvb_frontend *fe);
+
+#endif
diff --git a/drivers/media/pci/pt1/va1j5jf8007t.c b/drivers/media/pci/pt1/va1j5jf8007t.c
new file mode 100644
index 0000000..2db15159
--- /dev/null
+++ b/drivers/media/pci/pt1/va1j5jf8007t.c
@@ -0,0 +1,536 @@
+/*
+ * ISDB-T driver for VA1J5JF8007/VA1J5JF8011
+ *
+ * Copyright (C) 2009 HIRANO Takahito <hiranotaka@zng.info>
+ *
+ * based on pt1dvr - http://pt1dvr.sourceforge.jp/
+ * 	by Tomoaki Ishikawa <tomy@users.sourceforge.jp>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/slab.h>
+#include <linux/i2c.h>
+#include "dvb_frontend.h"
+#include "dvb_math.h"
+#include "va1j5jf8007t.h"
+
+enum va1j5jf8007t_tune_state {
+	VA1J5JF8007T_IDLE,
+	VA1J5JF8007T_SET_FREQUENCY,
+	VA1J5JF8007T_CHECK_FREQUENCY,
+	VA1J5JF8007T_SET_MODULATION,
+	VA1J5JF8007T_CHECK_MODULATION,
+	VA1J5JF8007T_TRACK,
+	VA1J5JF8007T_ABORT,
+};
+
+struct va1j5jf8007t_state {
+	const struct va1j5jf8007t_config *config;
+	struct i2c_adapter *adap;
+	struct dvb_frontend fe;
+	enum va1j5jf8007t_tune_state tune_state;
+};
+
+static int va1j5jf8007t_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+	struct va1j5jf8007t_state *state;
+	u8 addr;
+	int i;
+	u8 write_buf[1], read_buf[1];
+	struct i2c_msg msgs[2];
+	s32 word, x, y;
+
+	state = fe->demodulator_priv;
+	addr = state->config->demod_address;
+
+	word = 0;
+	for (i = 0; i < 3; i++) {
+		write_buf[0] = 0x8b + i;
+
+		msgs[0].addr = addr;
+		msgs[0].flags = 0;
+		msgs[0].len = sizeof(write_buf);
+		msgs[0].buf = write_buf;
+
+		msgs[1].addr = addr;
+		msgs[1].flags = I2C_M_RD;
+		msgs[1].len = sizeof(read_buf);
+		msgs[1].buf = read_buf;
+
+		if (i2c_transfer(state->adap, msgs, 2) != 2)
+			return -EREMOTEIO;
+
+		word <<= 8;
+		word |= read_buf[0];
+	}
+
+	if (!word)
+		return -EIO;
+
+	x = 10 * (intlog10(0x540000 * 100 / word) - (2 << 24));
+	y = (24ll << 46) / 1000000;
+	y = ((s64)y * x >> 30) - (16ll << 40) / 10000;
+	y = ((s64)y * x >> 29) + (398ll << 35) / 10000;
+	y = ((s64)y * x >> 30) + (5491ll << 29) / 10000;
+	y = ((s64)y * x >> 30) + (30965ll << 23) / 10000;
+	*snr = y >> 15;
+	return 0;
+}
+
+static int va1j5jf8007t_get_frontend_algo(struct dvb_frontend *fe)
+{
+	return DVBFE_ALGO_HW;
+}
+
+static int
+va1j5jf8007t_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+	struct va1j5jf8007t_state *state;
+
+	state = fe->demodulator_priv;
+
+	switch (state->tune_state) {
+	case VA1J5JF8007T_IDLE:
+	case VA1J5JF8007T_SET_FREQUENCY:
+	case VA1J5JF8007T_CHECK_FREQUENCY:
+		*status = 0;
+		return 0;
+
+
+	case VA1J5JF8007T_SET_MODULATION:
+	case VA1J5JF8007T_CHECK_MODULATION:
+	case VA1J5JF8007T_ABORT:
+		*status |= FE_HAS_SIGNAL;
+		return 0;
+
+	case VA1J5JF8007T_TRACK:
+		*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_LOCK;
+		return 0;
+	}
+
+	BUG();
+}
+
+struct va1j5jf8007t_cb_map {
+	u32 frequency;
+	u8 cb;
+};
+
+static const struct va1j5jf8007t_cb_map va1j5jf8007t_cb_maps[] = {
+	{  90000000, 0x80 },
+	{ 140000000, 0x81 },
+	{ 170000000, 0xa1 },
+	{ 220000000, 0x62 },
+	{ 330000000, 0xa2 },
+	{ 402000000, 0xe2 },
+	{ 450000000, 0x64 },
+	{ 550000000, 0x84 },
+	{ 600000000, 0xa4 },
+	{ 700000000, 0xc4 },
+};
+
+static u8 va1j5jf8007t_lookup_cb(u32 frequency)
+{
+	int i;
+	const struct va1j5jf8007t_cb_map *map;
+
+	for (i = 0; i < ARRAY_SIZE(va1j5jf8007t_cb_maps); i++) {
+		map = &va1j5jf8007t_cb_maps[i];
+		if (frequency < map->frequency)
+			return map->cb;
+	}
+	return 0xe4;
+}
+
+static int va1j5jf8007t_set_frequency(struct va1j5jf8007t_state *state)
+{
+	u32 frequency;
+	u16 word;
+	u8 buf[6];
+	struct i2c_msg msg;
+
+	frequency = state->fe.dtv_property_cache.frequency;
+
+	word = (frequency + 71428) / 142857 + 399;
+	buf[0] = 0xfe;
+	buf[1] = 0xc2;
+	buf[2] = word >> 8;
+	buf[3] = word;
+	buf[4] = 0x80;
+	buf[5] = va1j5jf8007t_lookup_cb(frequency);
+
+	msg.addr = state->config->demod_address;
+	msg.flags = 0;
+	msg.len = sizeof(buf);
+	msg.buf = buf;
+
+	if (i2c_transfer(state->adap, &msg, 1) != 1)
+		return -EREMOTEIO;
+
+	return 0;
+}
+
+static int
+va1j5jf8007t_check_frequency(struct va1j5jf8007t_state *state, int *lock)
+{
+	u8 addr;
+	u8 write_buf[2], read_buf[1];
+	struct i2c_msg msgs[2];
+
+	addr = state->config->demod_address;
+
+	write_buf[0] = 0xfe;
+	write_buf[1] = 0xc3;
+
+	msgs[0].addr = addr;
+	msgs[0].flags = 0;
+	msgs[0].len = sizeof(write_buf);
+	msgs[0].buf = write_buf;
+
+	msgs[1].addr = addr;
+	msgs[1].flags = I2C_M_RD;
+	msgs[1].len = sizeof(read_buf);
+	msgs[1].buf = read_buf;
+
+	if (i2c_transfer(state->adap, msgs, 2) != 2)
+		return -EREMOTEIO;
+
+	*lock = read_buf[0] & 0x40;
+	return 0;
+}
+
+static int va1j5jf8007t_set_modulation(struct va1j5jf8007t_state *state)
+{
+	u8 buf[2];
+	struct i2c_msg msg;
+
+	buf[0] = 0x01;
+	buf[1] = 0x40;
+
+	msg.addr = state->config->demod_address;
+	msg.flags = 0;
+	msg.len = sizeof(buf);
+	msg.buf = buf;
+
+	if (i2c_transfer(state->adap, &msg, 1) != 1)
+		return -EREMOTEIO;
+
+	return 0;
+}
+
+static int va1j5jf8007t_check_modulation(struct va1j5jf8007t_state *state,
+					 int *lock, int *retry)
+{
+	u8 addr;
+	u8 write_buf[1], read_buf[1];
+	struct i2c_msg msgs[2];
+
+	addr = state->config->demod_address;
+
+	write_buf[0] = 0x80;
+
+	msgs[0].addr = addr;
+	msgs[0].flags = 0;
+	msgs[0].len = sizeof(write_buf);
+	msgs[0].buf = write_buf;
+
+	msgs[1].addr = addr;
+	msgs[1].flags = I2C_M_RD;
+	msgs[1].len = sizeof(read_buf);
+	msgs[1].buf = read_buf;
+
+	if (i2c_transfer(state->adap, msgs, 2) != 2)
+		return -EREMOTEIO;
+
+	*lock = !(read_buf[0] & 0x10);
+	*retry = read_buf[0] & 0x80;
+	return 0;
+}
+
+static int
+va1j5jf8007t_tune(struct dvb_frontend *fe,
+		  bool re_tune,
+		  unsigned int mode_flags,  unsigned int *delay,
+		  fe_status_t *status)
+{
+	struct va1j5jf8007t_state *state;
+	int ret;
+	int lock = 0, retry = 0;
+
+	state = fe->demodulator_priv;
+
+	if (re_tune)
+		state->tune_state = VA1J5JF8007T_SET_FREQUENCY;
+
+	switch (state->tune_state) {
+	case VA1J5JF8007T_IDLE:
+		*delay = 3 * HZ;
+		*status = 0;
+		return 0;
+
+	case VA1J5JF8007T_SET_FREQUENCY:
+		ret = va1j5jf8007t_set_frequency(state);
+		if (ret < 0)
+			return ret;
+
+		state->tune_state = VA1J5JF8007T_CHECK_FREQUENCY;
+		*delay = 0;
+		*status = 0;
+		return 0;
+
+	case VA1J5JF8007T_CHECK_FREQUENCY:
+		ret = va1j5jf8007t_check_frequency(state, &lock);
+		if (ret < 0)
+			return ret;
+
+		if (!lock)  {
+			*delay = (HZ + 999) / 1000;
+			*status = 0;
+			return 0;
+		}
+
+		state->tune_state = VA1J5JF8007T_SET_MODULATION;
+		*delay = 0;
+		*status = FE_HAS_SIGNAL;
+		return 0;
+
+	case VA1J5JF8007T_SET_MODULATION:
+		ret = va1j5jf8007t_set_modulation(state);
+		if (ret < 0)
+			return ret;
+
+		state->tune_state = VA1J5JF8007T_CHECK_MODULATION;
+		*delay = 0;
+		*status = FE_HAS_SIGNAL;
+		return 0;
+
+	case VA1J5JF8007T_CHECK_MODULATION:
+		ret = va1j5jf8007t_check_modulation(state, &lock, &retry);
+		if (ret < 0)
+			return ret;
+
+		if (!lock)  {
+			if (!retry)  {
+				state->tune_state = VA1J5JF8007T_ABORT;
+				*delay = 3 * HZ;
+				*status = FE_HAS_SIGNAL;
+				return 0;
+			}
+			*delay = (HZ + 999) / 1000;
+			*status = FE_HAS_SIGNAL;
+			return 0;
+		}
+
+		state->tune_state = VA1J5JF8007T_TRACK;
+		/* fall through */
+
+	case VA1J5JF8007T_TRACK:
+		*delay = 3 * HZ;
+		*status = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_LOCK;
+		return 0;
+
+	case VA1J5JF8007T_ABORT:
+		*delay = 3 * HZ;
+		*status = FE_HAS_SIGNAL;
+		return 0;
+	}
+
+	BUG();
+}
+
+static int va1j5jf8007t_init_frequency(struct va1j5jf8007t_state *state)
+{
+	u8 buf[7];
+	struct i2c_msg msg;
+
+	buf[0] = 0xfe;
+	buf[1] = 0xc2;
+	buf[2] = 0x01;
+	buf[3] = 0x8f;
+	buf[4] = 0xc1;
+	buf[5] = 0x80;
+	buf[6] = 0x80;
+
+	msg.addr = state->config->demod_address;
+	msg.flags = 0;
+	msg.len = sizeof(buf);
+	msg.buf = buf;
+
+	if (i2c_transfer(state->adap, &msg, 1) != 1)
+		return -EREMOTEIO;
+
+	return 0;
+}
+
+static int va1j5jf8007t_set_sleep(struct va1j5jf8007t_state *state, int sleep)
+{
+	u8 buf[2];
+	struct i2c_msg msg;
+
+	buf[0] = 0x03;
+	buf[1] = sleep ? 0x90 : 0x80;
+
+	msg.addr = state->config->demod_address;
+	msg.flags = 0;
+	msg.len = sizeof(buf);
+	msg.buf = buf;
+
+	if (i2c_transfer(state->adap, &msg, 1) != 1)
+		return -EREMOTEIO;
+
+	return 0;
+}
+
+static int va1j5jf8007t_sleep(struct dvb_frontend *fe)
+{
+	struct va1j5jf8007t_state *state;
+	int ret;
+
+	state = fe->demodulator_priv;
+
+	ret = va1j5jf8007t_init_frequency(state);
+	if (ret < 0)
+		return ret;
+
+	return va1j5jf8007t_set_sleep(state, 1);
+}
+
+static int va1j5jf8007t_init(struct dvb_frontend *fe)
+{
+	struct va1j5jf8007t_state *state;
+
+	state = fe->demodulator_priv;
+	state->tune_state = VA1J5JF8007T_IDLE;
+
+	return va1j5jf8007t_set_sleep(state, 0);
+}
+
+static void va1j5jf8007t_release(struct dvb_frontend *fe)
+{
+	struct va1j5jf8007t_state *state;
+	state = fe->demodulator_priv;
+	kfree(state);
+}
+
+static struct dvb_frontend_ops va1j5jf8007t_ops = {
+	.delsys = { SYS_ISDBT },
+	.info = {
+		.name = "VA1J5JF8007/VA1J5JF8011 ISDB-T",
+		.frequency_min = 90000000,
+		.frequency_max = 770000000,
+		.frequency_stepsize = 142857,
+		.caps = FE_CAN_INVERSION_AUTO | FE_CAN_FEC_AUTO |
+			FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO |
+			FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO,
+	},
+
+	.read_snr = va1j5jf8007t_read_snr,
+	.get_frontend_algo = va1j5jf8007t_get_frontend_algo,
+	.read_status = va1j5jf8007t_read_status,
+	.tune = va1j5jf8007t_tune,
+	.sleep = va1j5jf8007t_sleep,
+	.init = va1j5jf8007t_init,
+	.release = va1j5jf8007t_release,
+};
+
+static const u8 va1j5jf8007t_20mhz_prepare_bufs[][2] = {
+	{0x03, 0x90}, {0x14, 0x8f}, {0x1c, 0x2a}, {0x1d, 0xa8}, {0x1e, 0xa2},
+	{0x22, 0x83}, {0x31, 0x0d}, {0x32, 0xe0}, {0x39, 0xd3}, {0x3a, 0x00},
+	{0x5c, 0x40}, {0x5f, 0x80}, {0x75, 0x02}, {0x76, 0x4e}, {0x77, 0x03},
+	{0xef, 0x01}
+};
+
+static const u8 va1j5jf8007t_25mhz_prepare_bufs[][2] = {
+	{0x03, 0x90}, {0x1c, 0x2a}, {0x1d, 0xa8}, {0x1e, 0xa2}, {0x22, 0x83},
+	{0x3a, 0x00}, {0x5c, 0x40}, {0x5f, 0x80}, {0x75, 0x0a}, {0x76, 0x4c},
+	{0x77, 0x03}, {0xef, 0x01}
+};
+
+int va1j5jf8007t_prepare(struct dvb_frontend *fe)
+{
+	struct va1j5jf8007t_state *state;
+	const u8 (*bufs)[2];
+	int size;
+	u8 buf[2];
+	struct i2c_msg msg;
+	int i;
+
+	state = fe->demodulator_priv;
+
+	switch (state->config->frequency) {
+	case VA1J5JF8007T_20MHZ:
+		bufs = va1j5jf8007t_20mhz_prepare_bufs;
+		size = ARRAY_SIZE(va1j5jf8007t_20mhz_prepare_bufs);
+		break;
+	case VA1J5JF8007T_25MHZ:
+		bufs = va1j5jf8007t_25mhz_prepare_bufs;
+		size = ARRAY_SIZE(va1j5jf8007t_25mhz_prepare_bufs);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	msg.addr = state->config->demod_address;
+	msg.flags = 0;
+	msg.len = sizeof(buf);
+	msg.buf = buf;
+
+	for (i = 0; i < size; i++) {
+		memcpy(buf, bufs[i], sizeof(buf));
+		if (i2c_transfer(state->adap, &msg, 1) != 1)
+			return -EREMOTEIO;
+	}
+
+	return va1j5jf8007t_init_frequency(state);
+}
+
+struct dvb_frontend *
+va1j5jf8007t_attach(const struct va1j5jf8007t_config *config,
+		    struct i2c_adapter *adap)
+{
+	struct va1j5jf8007t_state *state;
+	struct dvb_frontend *fe;
+	u8 buf[2];
+	struct i2c_msg msg;
+
+	state = kzalloc(sizeof(struct va1j5jf8007t_state), GFP_KERNEL);
+	if (!state)
+		return NULL;
+
+	state->config = config;
+	state->adap = adap;
+
+	fe = &state->fe;
+	memcpy(&fe->ops, &va1j5jf8007t_ops, sizeof(struct dvb_frontend_ops));
+	fe->demodulator_priv = state;
+
+	buf[0] = 0x01;
+	buf[1] = 0x80;
+
+	msg.addr = state->config->demod_address;
+	msg.flags = 0;
+	msg.len = sizeof(buf);
+	msg.buf = buf;
+
+	if (i2c_transfer(state->adap, &msg, 1) != 1) {
+		kfree(state);
+		return NULL;
+	}
+
+	return fe;
+}
diff --git a/drivers/media/pci/pt1/va1j5jf8007t.h b/drivers/media/pci/pt1/va1j5jf8007t.h
new file mode 100644
index 0000000..2903be5
--- /dev/null
+++ b/drivers/media/pci/pt1/va1j5jf8007t.h
@@ -0,0 +1,46 @@
+/*
+ * ISDB-T driver for VA1J5JF8007/VA1J5JF8011
+ *
+ * Copyright (C) 2009 HIRANO Takahito <hiranotaka@zng.info>
+ *
+ * based on pt1dvr - http://pt1dvr.sourceforge.jp/
+ * 	by Tomoaki Ishikawa <tomy@users.sourceforge.jp>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 VA1J5JF8007T_H
+#define VA1J5JF8007T_H
+
+enum va1j5jf8007t_frequency {
+	VA1J5JF8007T_20MHZ,
+	VA1J5JF8007T_25MHZ,
+};
+
+struct va1j5jf8007t_config {
+	u8 demod_address;
+	enum va1j5jf8007t_frequency frequency;
+};
+
+struct i2c_adapter;
+
+struct dvb_frontend *
+va1j5jf8007t_attach(const struct va1j5jf8007t_config *config,
+		    struct i2c_adapter *adap);
+
+/* must be called after va1j5jf8007s_attach */
+int va1j5jf8007t_prepare(struct dvb_frontend *fe);
+
+#endif
diff --git a/drivers/media/pci/saa7134/Kconfig b/drivers/media/pci/saa7134/Kconfig
new file mode 100644
index 0000000..15b90d6
--- /dev/null
+++ b/drivers/media/pci/saa7134/Kconfig
@@ -0,0 +1,64 @@
+config VIDEO_SAA7134
+	tristate "Philips SAA7134 support"
+	depends on VIDEO_DEV && PCI && I2C
+	select VIDEOBUF_DMA_SG
+	select VIDEO_TUNER
+	select VIDEO_TVEEPROM
+	select CRC32
+	select VIDEO_SAA6588 if MEDIA_SUBDRV_AUTOSELECT
+	---help---
+	  This is a video4linux driver for Philips SAA713x based
+	  TV cards.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called saa7134.
+
+config VIDEO_SAA7134_ALSA
+	tristate "Philips SAA7134 DMA audio support"
+	depends on VIDEO_SAA7134 && SND
+	select SND_PCM
+	---help---
+	  This is a video4linux driver for direct (DMA) audio in
+	  Philips SAA713x based TV cards using ALSA
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called saa7134-alsa.
+
+config VIDEO_SAA7134_RC
+	bool "Philips SAA7134 Remote Controller support"
+	depends on RC_CORE
+	depends on VIDEO_SAA7134
+	depends on !(RC_CORE=m && VIDEO_SAA7134=y)
+	default y
+	---help---
+	  Enables Remote Controller support on saa7134 driver.
+
+config VIDEO_SAA7134_DVB
+	tristate "DVB/ATSC Support for saa7134 based TV cards"
+	depends on VIDEO_SAA7134 && DVB_CORE
+	select VIDEOBUF_DVB
+	select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_MT352 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_TDA1004X if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_NXT200X if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_TDA10086 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_TDA826X if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_ISL6421 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_ISL6405 if MEDIA_SUBDRV_AUTOSELECT
+	select MEDIA_TUNER_TDA827X if MEDIA_SUBDRV_AUTOSELECT
+	select MEDIA_TUNER_SIMPLE if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_ZL10036 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_MT312 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_LNBP21 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_ZL10353 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_LGDT3305 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_TDA10048 if MEDIA_SUBDRV_AUTOSELECT
+	select MEDIA_TUNER_TDA18271 if MEDIA_SUBDRV_AUTOSELECT
+	select MEDIA_TUNER_TDA8290 if MEDIA_SUBDRV_AUTOSELECT
+	select DVB_ZL10039 if MEDIA_SUBDRV_AUTOSELECT
+	---help---
+	  This adds support for DVB cards based on the
+	  Philips saa7134 chip.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called saa7134-dvb.
diff --git a/drivers/media/pci/saa7134/Makefile b/drivers/media/pci/saa7134/Makefile
new file mode 100644
index 0000000..3537548
--- /dev/null
+++ b/drivers/media/pci/saa7134/Makefile
@@ -0,0 +1,16 @@
+
+saa7134-y +=	saa7134-cards.o saa7134-core.o saa7134-i2c.o
+saa7134-y +=	saa7134-ts.o saa7134-tvaudio.o saa7134-vbi.o
+saa7134-y +=	saa7134-video.o
+saa7134-$(CONFIG_VIDEO_SAA7134_RC) += saa7134-input.o
+
+obj-$(CONFIG_VIDEO_SAA7134) +=  saa6752hs.o saa7134.o saa7134-empress.o
+
+obj-$(CONFIG_VIDEO_SAA7134_ALSA) += saa7134-alsa.o
+
+obj-$(CONFIG_VIDEO_SAA7134_DVB) += saa7134-dvb.o
+
+ccflags-y += -I$(srctree)/drivers/media/i2c
+ccflags-y += -I$(srctree)/drivers/media/tuners
+ccflags-y += -I$(srctree)/drivers/media/dvb-core
+ccflags-y += -I$(srctree)/drivers/media/dvb-frontends
diff --git a/drivers/media/pci/saa7134/saa6752hs.c b/drivers/media/pci/saa7134/saa6752hs.c
new file mode 100644
index 0000000..f147b05
--- /dev/null
+++ b/drivers/media/pci/saa7134/saa6752hs.c
@@ -0,0 +1,1012 @@
+ /*
+    saa6752hs - i2c-driver for the saa6752hs by Philips
+
+    Copyright (C) 2004 Andrew de Quincey
+
+    AC-3 support:
+
+    Copyright (C) 2008 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 vs 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 Mvss Ave, Cambridge, MA 02139, USA.
+  */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/poll.h>
+#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 <linux/init.h>
+#include <linux/crc32.h>
+
+#define MPEG_VIDEO_TARGET_BITRATE_MAX  27000
+#define MPEG_VIDEO_MAX_BITRATE_MAX     27000
+#define MPEG_TOTAL_TARGET_BITRATE_MAX  27000
+#define MPEG_PID_MAX ((1 << 14) - 1)
+
+
+MODULE_DESCRIPTION("device driver for saa6752hs MPEG2 encoder");
+MODULE_AUTHOR("Andrew de Quincey");
+MODULE_LICENSE("GPL");
+
+enum saa6752hs_videoformat {
+	SAA6752HS_VF_D1 = 0,    /* standard D1 video format: 720x576 */
+	SAA6752HS_VF_2_3_D1 = 1,/* 2/3D1 video format: 480x576 */
+	SAA6752HS_VF_1_2_D1 = 2,/* 1/2D1 video format: 352x576 */
+	SAA6752HS_VF_SIF = 3,   /* SIF video format: 352x288 */
+	SAA6752HS_VF_UNKNOWN,
+};
+
+struct saa6752hs_mpeg_params {
+	/* transport streams */
+	__u16				ts_pid_pmt;
+	__u16				ts_pid_audio;
+	__u16				ts_pid_video;
+	__u16				ts_pid_pcr;
+
+	/* audio */
+	enum v4l2_mpeg_audio_encoding    au_encoding;
+	enum v4l2_mpeg_audio_l2_bitrate  au_l2_bitrate;
+	enum v4l2_mpeg_audio_ac3_bitrate au_ac3_bitrate;
+
+	/* video */
+	enum v4l2_mpeg_video_aspect	vi_aspect;
+	enum v4l2_mpeg_video_bitrate_mode vi_bitrate_mode;
+	__u32 				vi_bitrate;
+	__u32 				vi_bitrate_peak;
+};
+
+static const struct v4l2_format v4l2_format_table[] =
+{
+	[SAA6752HS_VF_D1] =
+		{ .fmt = { .pix = { .width = 720, .height = 576 }}},
+	[SAA6752HS_VF_2_3_D1] =
+		{ .fmt = { .pix = { .width = 480, .height = 576 }}},
+	[SAA6752HS_VF_1_2_D1] =
+		{ .fmt = { .pix = { .width = 352, .height = 576 }}},
+	[SAA6752HS_VF_SIF] =
+		{ .fmt = { .pix = { .width = 352, .height = 288 }}},
+	[SAA6752HS_VF_UNKNOWN] =
+		{ .fmt = { .pix = { .width = 0, .height = 0}}},
+};
+
+struct saa6752hs_state {
+	struct v4l2_subdev            sd;
+	int 			      chip;
+	u32 			      revision;
+	int 			      has_ac3;
+	struct saa6752hs_mpeg_params  params;
+	enum saa6752hs_videoformat    video_format;
+	v4l2_std_id                   standard;
+};
+
+enum saa6752hs_command {
+	SAA6752HS_COMMAND_RESET = 0,
+	SAA6752HS_COMMAND_STOP = 1,
+	SAA6752HS_COMMAND_START = 2,
+	SAA6752HS_COMMAND_PAUSE = 3,
+	SAA6752HS_COMMAND_RECONFIGURE = 4,
+	SAA6752HS_COMMAND_SLEEP = 5,
+	SAA6752HS_COMMAND_RECONFIGURE_FORCE = 6,
+
+	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[] = {
+	0xc2, /* i2c register */
+	0x00, /* table number for encoder */
+
+	0x47, /* sync */
+	0x40, 0x00, /* transport_error_indicator(0), payload_unit_start(1), transport_priority(0), pid(0) */
+	0x10, /* transport_scrambling_control(00), adaptation_field_control(01), continuity_counter(0) */
+
+	0x00, /* PSI pointer to start of table */
+
+	0x00, /* tid(0) */
+	0xb0, 0x0d, /* section_syntax_indicator(1), section_length(13) */
+
+	0x00, 0x01, /* transport_stream_id(1) */
+
+	0xc1, /* version_number(0), current_next_indicator(1) */
+
+	0x00, 0x00, /* section_number(0), last_section_number(0) */
+
+	0x00, 0x01, /* program_number(1) */
+
+	0xe0, 0x00, /* PMT PID */
+
+	0x00, 0x00, 0x00, 0x00 /* CRC32 */
+};
+
+static u8 PMT[] = {
+	0xc2, /* i2c register */
+	0x01, /* table number for encoder */
+
+	0x47, /* sync */
+	0x40, 0x00, /* transport_error_indicator(0), payload_unit_start(1), transport_priority(0), pid */
+	0x10, /* transport_scrambling_control(00), adaptation_field_control(01), continuity_counter(0) */
+
+	0x00, /* PSI pointer to start of table */
+
+	0x02, /* tid(2) */
+	0xb0, 0x17, /* section_syntax_indicator(1), section_length(23) */
+
+	0x00, 0x01, /* program_number(1) */
+
+	0xc1, /* version_number(0), current_next_indicator(1) */
+
+	0x00, 0x00, /* section_number(0), last_section_number(0) */
+
+	0xe0, 0x00, /* PCR_PID */
+
+	0xf0, 0x00, /* program_info_length(0) */
+
+	0x02, 0xe0, 0x00, 0xf0, 0x00, /* video stream type(2), pid */
+	0x04, 0xe0, 0x00, 0xf0, 0x00, /* audio stream type(4), pid */
+
+	0x00, 0x00, 0x00, 0x00 /* CRC32 */
+};
+
+static u8 PMT_AC3[] = {
+	0xc2, /* i2c register */
+	0x01, /* table number for encoder(1) */
+	0x47, /* sync */
+
+	0x40, /* transport_error_indicator(0), payload_unit_start(1), transport_priority(0) */
+	0x10, /* PMT PID (0x0010) */
+	0x10, /* transport_scrambling_control(00), adaptation_field_control(01), continuity_counter(0) */
+
+	0x00, /* PSI pointer to start of table */
+
+	0x02, /* TID (2) */
+	0xb0, 0x1a, /* section_syntax_indicator(1), section_length(26) */
+
+	0x00, 0x01, /* program_number(1) */
+
+	0xc1, /* version_number(0), current_next_indicator(1) */
+
+	0x00, 0x00, /* section_number(0), last_section_number(0) */
+
+	0xe1, 0x04, /* PCR_PID (0x0104) */
+
+	0xf0, 0x00, /* program_info_length(0) */
+
+	0x02, 0xe1, 0x00, 0xf0, 0x00, /* video stream type(2), pid */
+	0x06, 0xe1, 0x03, 0xf0, 0x03, /* audio stream type(6), pid */
+	0x6a, /* AC3 */
+	0x01, /* Descriptor_length(1) */
+	0x00, /* component_type_flag(0), bsid_flag(0), mainid_flag(0), asvc_flag(0), reserved flags(0) */
+
+	0xED, 0xDE, 0x2D, 0xF3 /* CRC32 BE */
+};
+
+static struct saa6752hs_mpeg_params param_defaults =
+{
+	.ts_pid_pmt      = 16,
+	.ts_pid_video    = 260,
+	.ts_pid_audio    = 256,
+	.ts_pid_pcr      = 259,
+
+	.vi_aspect       = V4L2_MPEG_VIDEO_ASPECT_4x3,
+	.vi_bitrate      = 4000,
+	.vi_bitrate_peak = 6000,
+	.vi_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
+
+	.au_encoding     = V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
+	.au_l2_bitrate   = V4L2_MPEG_AUDIO_L2_BITRATE_256K,
+	.au_ac3_bitrate  = V4L2_MPEG_AUDIO_AC3_BITRATE_256K,
+};
+
+/* ---------------------------------------------------------------------- */
+
+static int saa6752hs_chip_command(struct i2c_client *client,
+				  enum saa6752hs_command command)
+{
+	unsigned char buf[3];
+	unsigned long timeout;
+	int status = 0;
+
+	/* execute the command */
+	switch(command) {
+	case SAA6752HS_COMMAND_RESET:
+		buf[0] = 0x00;
+		break;
+
+	case SAA6752HS_COMMAND_STOP:
+		buf[0] = 0x03;
+		break;
+
+	case SAA6752HS_COMMAND_START:
+		buf[0] = 0x02;
+		break;
+
+	case SAA6752HS_COMMAND_PAUSE:
+		buf[0] = 0x04;
+		break;
+
+	case SAA6752HS_COMMAND_RECONFIGURE:
+		buf[0] = 0x05;
+		break;
+
+	case SAA6752HS_COMMAND_SLEEP:
+		buf[0] = 0x06;
+		break;
+
+	case SAA6752HS_COMMAND_RECONFIGURE_FORCE:
+		buf[0] = 0x07;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	/* set it and wait for it to be so */
+	i2c_master_send(client, buf, 1);
+	timeout = jiffies + HZ * 3;
+	for (;;) {
+		/* get the current status */
+		buf[0] = 0x10;
+		i2c_master_send(client, buf, 1);
+		i2c_master_recv(client, buf, 1);
+
+		if (!(buf[0] & 0x20))
+			break;
+		if (time_after(jiffies,timeout)) {
+			status = -ETIMEDOUT;
+			break;
+		}
+
+		msleep(10);
+	}
+
+	/* delay a bit to let encoder settle */
+	msleep(50);
+
+	return status;
+}
+
+
+static inline void set_reg8(struct i2c_client *client, uint8_t reg, uint8_t val)
+{
+	u8 buf[2];
+
+	buf[0] = reg;
+	buf[1] = val;
+	i2c_master_send(client, buf, 2);
+}
+
+static inline void set_reg16(struct i2c_client *client, uint8_t reg, uint16_t val)
+{
+	u8 buf[3];
+
+	buf[0] = reg;
+	buf[1] = val >> 8;
+	buf[2] = val & 0xff;
+	i2c_master_send(client, buf, 3);
+}
+
+static int saa6752hs_set_bitrate(struct i2c_client *client,
+				 struct saa6752hs_state *h)
+{
+	struct saa6752hs_mpeg_params *params = &h->params;
+	int tot_bitrate;
+	int is_384k;
+
+	/* set the bitrate mode */
+	set_reg8(client, 0x71,
+		params->vi_bitrate_mode != V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
+
+	/* set the video bitrate */
+	if (params->vi_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) {
+		/* set the target bitrate */
+		set_reg16(client, 0x80, params->vi_bitrate);
+
+		/* set the max bitrate */
+		set_reg16(client, 0x81, params->vi_bitrate_peak);
+		tot_bitrate = params->vi_bitrate_peak;
+	} else {
+		/* set the target bitrate (no max bitrate for CBR) */
+		set_reg16(client, 0x81, params->vi_bitrate);
+		tot_bitrate = params->vi_bitrate;
+	}
+
+	/* set the audio encoding */
+	set_reg8(client, 0x93,
+			params->au_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3);
+
+	/* set the audio bitrate */
+	if (params->au_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3)
+		is_384k = V4L2_MPEG_AUDIO_AC3_BITRATE_384K == params->au_ac3_bitrate;
+	else
+		is_384k = V4L2_MPEG_AUDIO_L2_BITRATE_384K == params->au_l2_bitrate;
+	set_reg8(client, 0x94, is_384k);
+	tot_bitrate += is_384k ? 384 : 256;
+
+	/* Note: the total max bitrate is determined by adding the video and audio
+	   bitrates together and also adding an extra 768kbit/s to stay on the
+	   safe side. If more control should be required, then an extra MPEG control
+	   should be added. */
+	tot_bitrate += 768;
+	if (tot_bitrate > MPEG_TOTAL_TARGET_BITRATE_MAX)
+		tot_bitrate = MPEG_TOTAL_TARGET_BITRATE_MAX;
+
+	/* set the total bitrate */
+	set_reg16(client, 0xb1, tot_bitrate);
+	return 0;
+}
+
+
+static int get_ctrl(int has_ac3, struct saa6752hs_mpeg_params *params,
+		struct v4l2_ext_control *ctrl)
+{
+	switch (ctrl->id) {
+	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;
+	}
+	return 0;
+}
+
+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;
+		params->au_encoding = new;
+		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;
+
+	switch (qctrl->id) {
+	case V4L2_CID_MPEG_AUDIO_ENCODING:
+		return v4l2_ctrl_query_fill(qctrl,
+				V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
+				h->has_ac3 ? V4L2_MPEG_AUDIO_ENCODING_AC3 :
+					V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
+				1, V4L2_MPEG_AUDIO_ENCODING_LAYER_2);
+
+	case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
+		return v4l2_ctrl_query_fill(qctrl,
+				V4L2_MPEG_AUDIO_L2_BITRATE_256K,
+				V4L2_MPEG_AUDIO_L2_BITRATE_384K, 1,
+				V4L2_MPEG_AUDIO_L2_BITRATE_256K);
+
+	case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:
+		if (!h->has_ac3)
+			return -EINVAL;
+		return v4l2_ctrl_query_fill(qctrl,
+				V4L2_MPEG_AUDIO_AC3_BITRATE_256K,
+				V4L2_MPEG_AUDIO_AC3_BITRATE_384K, 1,
+				V4L2_MPEG_AUDIO_AC3_BITRATE_256K);
+
+	case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
+		return v4l2_ctrl_query_fill(qctrl,
+				V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000,
+				V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000, 1,
+				V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000);
+
+	case V4L2_CID_MPEG_VIDEO_ENCODING:
+		return v4l2_ctrl_query_fill(qctrl,
+				V4L2_MPEG_VIDEO_ENCODING_MPEG_2,
+				V4L2_MPEG_VIDEO_ENCODING_MPEG_2, 1,
+				V4L2_MPEG_VIDEO_ENCODING_MPEG_2);
+
+	case V4L2_CID_MPEG_VIDEO_ASPECT:
+		return v4l2_ctrl_query_fill(qctrl,
+				V4L2_MPEG_VIDEO_ASPECT_4x3,
+				V4L2_MPEG_VIDEO_ASPECT_16x9, 1,
+				V4L2_MPEG_VIDEO_ASPECT_4x3);
+
+	case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
+		err = v4l2_ctrl_query_fill(qctrl, 0, 27000000, 1, 8000000);
+		if (err == 0 &&
+		    params->vi_bitrate_mode ==
+				V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
+			qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
+		return err;
+
+	case V4L2_CID_MPEG_STREAM_TYPE:
+		return v4l2_ctrl_query_fill(qctrl,
+				V4L2_MPEG_STREAM_TYPE_MPEG2_TS,
+				V4L2_MPEG_STREAM_TYPE_MPEG2_TS, 1,
+				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(qctrl, 0, (1 << 14) - 1, 1, 259);
+
+	default:
+		break;
+	}
+	return -EINVAL;
+}
+
+static int saa6752hs_querymenu(struct v4l2_subdev *sd, struct v4l2_querymenu *qmenu)
+{
+	static const u32 mpeg_audio_encoding[] = {
+		V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
+		V4L2_CTRL_MENU_IDS_END
+	};
+	static const u32 mpeg_audio_ac3_encoding[] = {
+		V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
+		V4L2_MPEG_AUDIO_ENCODING_AC3,
+		V4L2_CTRL_MENU_IDS_END
+	};
+	static u32 mpeg_audio_l2_bitrate[] = {
+		V4L2_MPEG_AUDIO_L2_BITRATE_256K,
+		V4L2_MPEG_AUDIO_L2_BITRATE_384K,
+		V4L2_CTRL_MENU_IDS_END
+	};
+	static u32 mpeg_audio_ac3_bitrate[] = {
+		V4L2_MPEG_AUDIO_AC3_BITRATE_256K,
+		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_queryctrl(sd, &qctrl);
+	if (err)
+		return err;
+	switch (qmenu->id) {
+	case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
+		return v4l2_ctrl_query_menu_valid_items(qmenu,
+				mpeg_audio_l2_bitrate);
+	case V4L2_CID_MPEG_AUDIO_AC3_BITRATE:
+		if (!h->has_ac3)
+			return -EINVAL;
+		return v4l2_ctrl_query_menu_valid_items(qmenu,
+				mpeg_audio_ac3_bitrate);
+	case V4L2_CID_MPEG_AUDIO_ENCODING:
+		return v4l2_ctrl_query_menu_valid_items(qmenu,
+			h->has_ac3 ? mpeg_audio_ac3_encoding :
+				mpeg_audio_encoding);
+	}
+	return v4l2_ctrl_query_menu(qmenu, &qctrl, NULL);
+}
+
+static int saa6752hs_init(struct v4l2_subdev *sd, u32 leading_null_bytes)
+{
+	unsigned char buf[9], buf2[4];
+	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];
+
+	/* Set video format - must be done first as it resets other settings */
+	set_reg8(client, 0x41, h->video_format);
+
+	/* Set number of lines in input signal */
+	set_reg8(client, 0x40, (h->standard & V4L2_STD_525_60) ? 1 : 0);
+
+	/* set bitrate */
+	saa6752hs_set_bitrate(client, h);
+
+	/* Set GOP structure {3, 13} */
+	set_reg16(client, 0x72, 0x030d);
+
+	/* Set minimum Q-scale {4} */
+	set_reg8(client, 0x82, 0x04);
+
+	/* Set maximum Q-scale {12} */
+	set_reg8(client, 0x83, 0x0c);
+
+	/* Set Output Protocol */
+	set_reg8(client, 0xd0, 0x81);
+
+	/* Set video output stream format {TS} */
+	set_reg8(client, 0xb0, 0x05);
+
+	/* Set leading null byte for TS */
+	set_reg16(client, 0xf6, leading_null_bytes);
+
+	/* compute PAT */
+	memcpy(localPAT, PAT, sizeof(PAT));
+	localPAT[17] = 0xe0 | ((h->params.ts_pid_pmt >> 8) & 0x0f);
+	localPAT[18] = h->params.ts_pid_pmt & 0xff;
+	crc = crc32_be(~0, &localPAT[7], sizeof(PAT) - 7 - 4);
+	localPAT[sizeof(PAT) - 4] = (crc >> 24) & 0xFF;
+	localPAT[sizeof(PAT) - 3] = (crc >> 16) & 0xFF;
+	localPAT[sizeof(PAT) - 2] = (crc >> 8) & 0xFF;
+	localPAT[sizeof(PAT) - 1] = crc & 0xFF;
+
+	/* compute PMT */
+	if (h->params.au_encoding == V4L2_MPEG_AUDIO_ENCODING_AC3) {
+		size = sizeof(PMT_AC3);
+		memcpy(localPMT, PMT_AC3, size);
+	} else {
+		size = sizeof(PMT);
+		memcpy(localPMT, PMT, size);
+	}
+	localPMT[3] = 0x40 | ((h->params.ts_pid_pmt >> 8) & 0x0f);
+	localPMT[4] = h->params.ts_pid_pmt & 0xff;
+	localPMT[15] = 0xE0 | ((h->params.ts_pid_pcr >> 8) & 0x0F);
+	localPMT[16] = h->params.ts_pid_pcr & 0xFF;
+	localPMT[20] = 0xE0 | ((h->params.ts_pid_video >> 8) & 0x0F);
+	localPMT[21] = h->params.ts_pid_video & 0xFF;
+	localPMT[25] = 0xE0 | ((h->params.ts_pid_audio >> 8) & 0x0F);
+	localPMT[26] = h->params.ts_pid_audio & 0xFF;
+	crc = crc32_be(~0, &localPMT[7], size - 7 - 4);
+	localPMT[size - 4] = (crc >> 24) & 0xFF;
+	localPMT[size - 3] = (crc >> 16) & 0xFF;
+	localPMT[size - 2] = (crc >> 8) & 0xFF;
+	localPMT[size - 1] = crc & 0xFF;
+
+	/* Set Audio PID */
+	set_reg16(client, 0xc1, h->params.ts_pid_audio);
+
+	/* Set Video PID */
+	set_reg16(client, 0xc0, h->params.ts_pid_video);
+
+	/* Set PCR PID */
+	set_reg16(client, 0xc4, h->params.ts_pid_pcr);
+
+	/* Send SI tables */
+	i2c_master_send(client, localPAT, sizeof(PAT));
+	i2c_master_send(client, localPMT, size);
+
+	/* mute then unmute audio. This removes buzzing artefacts */
+	set_reg8(client, 0xa4, 1);
+	set_reg8(client, 0xa4, 0);
+
+	/* start it going */
+	saa6752hs_chip_command(client, SAA6752HS_COMMAND_START);
+
+	/* readout current state */
+	buf[0] = 0xE1;
+	buf[1] = 0xA7;
+	buf[2] = 0xFE;
+	buf[3] = 0x82;
+	buf[4] = 0xB0;
+	i2c_master_send(client, buf, 5);
+	i2c_master_recv(client, buf2, 4);
+
+	/* change aspect ratio */
+	buf[0] = 0xE0;
+	buf[1] = 0xA7;
+	buf[2] = 0xFE;
+	buf[3] = 0x82;
+	buf[4] = 0xB0;
+	buf[5] = buf2[0];
+	switch (h->params.vi_aspect) {
+	case V4L2_MPEG_VIDEO_ASPECT_16x9:
+		buf[6] = buf2[1] | 0x40;
+		break;
+	case V4L2_MPEG_VIDEO_ASPECT_4x3:
+	default:
+		buf[6] = buf2[1] & 0xBF;
+		break;
+	}
+	buf[7] = buf2[2];
+	buf[8] = buf2[3];
+	i2c_master_send(client, buf, 9);
+
+	return 0;
+}
+
+static int saa6752hs_do_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ctrls, int set)
+{
+	struct saa6752hs_state *h = to_state(sd);
+	struct saa6752hs_mpeg_params params;
+	int i;
+
+	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;
+	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_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *f)
+{
+	struct saa6752hs_state *h = to_state(sd);
+
+	if (h->video_format == SAA6752HS_VF_UNKNOWN)
+		h->video_format = SAA6752HS_VF_D1;
+	f->width = v4l2_format_table[h->video_format].fmt.pix.width;
+	f->height = v4l2_format_table[h->video_format].fmt.pix.height;
+	f->code = V4L2_MBUS_FMT_FIXED;
+	f->field = V4L2_FIELD_INTERLACED;
+	f->colorspace = V4L2_COLORSPACE_SMPTE170M;
+	return 0;
+}
+
+static int saa6752hs_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *f)
+{
+	struct saa6752hs_state *h = to_state(sd);
+	int dist_352, dist_480, dist_720;
+
+	if (f->code != V4L2_MBUS_FMT_FIXED)
+		return -EINVAL;
+
+	/*
+	  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->width - 352);
+	dist_480 = abs(f->width - 480);
+	dist_720 = abs(f->width - 720);
+	if (dist_720 < dist_480) {
+		f->width = 720;
+		f->height = 576;
+		h->video_format = SAA6752HS_VF_D1;
+	} else if (dist_480 < dist_352) {
+		f->width = 480;
+		f->height = 576;
+		h->video_format = SAA6752HS_VF_2_3_D1;
+	} else {
+		f->width = 352;
+		if (abs(f->height - 576) <
+		    abs(f->height - 288)) {
+			f->height = 576;
+			h->video_format = SAA6752HS_VF_1_2_D1;
+		} else {
+			f->height = 288;
+			h->video_format = SAA6752HS_VF_SIF;
+		}
+	}
+	f->field = V4L2_FIELD_INTERLACED;
+	f->colorspace = V4L2_COLORSPACE_SMPTE170M;
+	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,
+	.s_std = saa6752hs_s_std,
+};
+
+static const struct v4l2_subdev_video_ops saa6752hs_video_ops = {
+	.s_mbus_fmt = saa6752hs_s_mbus_fmt,
+	.g_mbus_fmt = saa6752hs_g_mbus_fmt,
+};
+
+static const struct v4l2_subdev_ops saa6752hs_ops = {
+	.core = &saa6752hs_core_ops,
+	.video = &saa6752hs_video_ops,
+};
+
+static int saa6752hs_probe(struct i2c_client *client,
+		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];
+
+	v4l_info(client, "chip found @ 0x%x (%s)\n",
+			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));
+	h->chip = V4L2_IDENT_SAA6752HS;
+	h->revision = (data[8] << 8) | data[9];
+	h->has_ac3 = 0;
+	if (h->revision == 0x0206) {
+		h->chip = V4L2_IDENT_SAA6752HS_AC3;
+		h->has_ac3 = 1;
+		v4l_info(client, "support AC-3\n");
+	}
+	h->params = param_defaults;
+	h->standard = 0; /* Assume 625 input lines */
+	return 0;
+}
+
+static int saa6752hs_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+
+	v4l2_device_unregister_subdev(sd);
+	kfree(to_state(sd));
+	return 0;
+}
+
+static const struct i2c_device_id saa6752hs_id[] = {
+	{ "saa6752hs", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, saa6752hs_id);
+
+static struct i2c_driver saa6752hs_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "saa6752hs",
+	},
+	.probe		= saa6752hs_probe,
+	.remove		= saa6752hs_remove,
+	.id_table	= saa6752hs_id,
+};
+
+module_i2c_driver(saa6752hs_driver);
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/pci/saa7134/saa7134-alsa.c b/drivers/media/pci/saa7134/saa7134-alsa.c
new file mode 100644
index 0000000..10460fd
--- /dev/null
+++ b/drivers/media/pci/saa7134/saa7134-alsa.c
@@ -0,0 +1,1209 @@
+/*
+ *   SAA713x ALSA support for V4L
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, version 2
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/time.h>
+#include <linux/wait.h>
+#include <linux/module.h>
+#include <sound/core.h>
+#include <sound/control.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/initval.h>
+#include <linux/interrupt.h>
+
+#include "saa7134.h"
+#include "saa7134-reg.h"
+
+static unsigned int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug,"enable debug messages [alsa]");
+
+/*
+ * Configuration macros
+ */
+
+/* defaults */
+#define MIXER_ADDR_UNSELECTED	-1
+#define MIXER_ADDR_TVTUNER	0
+#define MIXER_ADDR_LINE1	1
+#define MIXER_ADDR_LINE2	2
+#define MIXER_ADDR_LAST		2
+
+
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
+static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
+static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 1};
+
+module_param_array(index, int, NULL, 0444);
+module_param_array(enable, int, NULL, 0444);
+MODULE_PARM_DESC(index, "Index value for SAA7134 capture interface(s).");
+MODULE_PARM_DESC(enable, "Enable (or not) the SAA7134 capture interface(s).");
+
+#define dprintk(fmt, arg...)    if (debug) \
+	printk(KERN_DEBUG "%s/alsa: " fmt, dev->name , ##arg)
+
+
+
+/*
+ * Main chip structure
+ */
+
+typedef struct snd_card_saa7134 {
+	struct snd_card *card;
+	spinlock_t mixer_lock;
+	int mixer_volume[MIXER_ADDR_LAST+1][2];
+	int capture_source_addr;
+	int capture_source[2];
+	struct snd_kcontrol *capture_ctl[MIXER_ADDR_LAST+1];
+	struct pci_dev *pci;
+	struct saa7134_dev *dev;
+
+	unsigned long iobase;
+	s16 irq;
+	u16 mute_was_on;
+
+	spinlock_t lock;
+} snd_card_saa7134_t;
+
+
+/*
+ * PCM structure
+ */
+
+typedef struct snd_card_saa7134_pcm {
+	struct saa7134_dev *dev;
+
+	spinlock_t lock;
+
+	struct snd_pcm_substream *substream;
+} snd_card_saa7134_pcm_t;
+
+static struct snd_card *snd_saa7134_cards[SNDRV_CARDS];
+
+
+/*
+ * saa7134 DMA audio stop
+ *
+ *   Called when the capture device is released or the buffer overflows
+ *
+ *   - Copied verbatim from saa7134-oss's dsp_dma_stop.
+ *
+ */
+
+static void saa7134_dma_stop(struct saa7134_dev *dev)
+{
+	dev->dmasound.dma_blk     = -1;
+	dev->dmasound.dma_running = 0;
+	saa7134_set_dmabits(dev);
+}
+
+/*
+ * saa7134 DMA audio start
+ *
+ *   Called when preparing the capture device for use
+ *
+ *   - Copied verbatim from saa7134-oss's dsp_dma_start.
+ *
+ */
+
+static void saa7134_dma_start(struct saa7134_dev *dev)
+{
+	dev->dmasound.dma_blk     = 0;
+	dev->dmasound.dma_running = 1;
+	saa7134_set_dmabits(dev);
+}
+
+/*
+ * saa7134 audio DMA IRQ handler
+ *
+ *   Called whenever we get an SAA7134_IRQ_REPORT_DONE_RA3 interrupt
+ *   Handles shifting between the 2 buffers, manages the read counters,
+ *  and notifies ALSA when periods elapse
+ *
+ *   - Mostly copied from saa7134-oss's saa7134_irq_oss_done.
+ *
+ */
+
+static void saa7134_irq_alsa_done(struct saa7134_dev *dev,
+				  unsigned long status)
+{
+	int next_blk, reg = 0;
+
+	spin_lock(&dev->slock);
+	if (UNSET == dev->dmasound.dma_blk) {
+		dprintk("irq: recording stopped\n");
+		goto done;
+	}
+	if (0 != (status & 0x0f000000))
+		dprintk("irq: lost %ld\n", (status >> 24) & 0x0f);
+	if (0 == (status & 0x10000000)) {
+		/* odd */
+		if (0 == (dev->dmasound.dma_blk & 0x01))
+			reg = SAA7134_RS_BA1(6);
+	} else {
+		/* even */
+		if (1 == (dev->dmasound.dma_blk & 0x01))
+			reg = SAA7134_RS_BA2(6);
+	}
+	if (0 == reg) {
+		dprintk("irq: field oops [%s]\n",
+			(status & 0x10000000) ? "even" : "odd");
+		goto done;
+	}
+
+	if (dev->dmasound.read_count >= dev->dmasound.blksize * (dev->dmasound.blocks-2)) {
+		dprintk("irq: overrun [full=%d/%d] - Blocks in %d\n",dev->dmasound.read_count,
+			dev->dmasound.bufsize, dev->dmasound.blocks);
+		spin_unlock(&dev->slock);
+		snd_pcm_stop(dev->dmasound.substream,SNDRV_PCM_STATE_XRUN);
+		return;
+	}
+
+	/* next block addr */
+	next_blk = (dev->dmasound.dma_blk + 2) % dev->dmasound.blocks;
+	saa_writel(reg,next_blk * dev->dmasound.blksize);
+	if (debug > 2)
+		dprintk("irq: ok, %s, next_blk=%d, addr=%x, blocks=%u, size=%u, read=%u\n",
+			(status & 0x10000000) ? "even" : "odd ", next_blk,
+			next_blk * dev->dmasound.blksize, dev->dmasound.blocks, dev->dmasound.blksize, dev->dmasound.read_count);
+
+	/* update status & wake waiting readers */
+	dev->dmasound.dma_blk = (dev->dmasound.dma_blk + 1) % dev->dmasound.blocks;
+	dev->dmasound.read_count += dev->dmasound.blksize;
+
+	dev->dmasound.recording_on = reg;
+
+	if (dev->dmasound.read_count >= snd_pcm_lib_period_bytes(dev->dmasound.substream)) {
+		spin_unlock(&dev->slock);
+		snd_pcm_period_elapsed(dev->dmasound.substream);
+		spin_lock(&dev->slock);
+	}
+
+ done:
+	spin_unlock(&dev->slock);
+
+}
+
+/*
+ * IRQ request handler
+ *
+ *   Runs along with saa7134's IRQ handler, discards anything that isn't
+ *   DMA sound
+ *
+ */
+
+static irqreturn_t saa7134_alsa_irq(int irq, void *dev_id)
+{
+	struct saa7134_dmasound *dmasound = dev_id;
+	struct saa7134_dev *dev = dmasound->priv_data;
+
+	unsigned long report, status;
+	int loop, handled = 0;
+
+	for (loop = 0; loop < 10; loop++) {
+		report = saa_readl(SAA7134_IRQ_REPORT);
+		status = saa_readl(SAA7134_IRQ_STATUS);
+
+		if (report & SAA7134_IRQ_REPORT_DONE_RA3) {
+			handled = 1;
+			saa_writel(SAA7134_IRQ_REPORT,
+				   SAA7134_IRQ_REPORT_DONE_RA3);
+			saa7134_irq_alsa_done(dev, status);
+		} else {
+			goto out;
+		}
+	}
+
+	if (loop == 10) {
+		dprintk("error! looping IRQ!");
+	}
+
+out:
+	return IRQ_RETVAL(handled);
+}
+
+/*
+ * ALSA capture trigger
+ *
+ *   - One of the ALSA capture callbacks.
+ *
+ *   Called whenever a capture is started or stopped. Must be defined,
+ *   but there's nothing we want to do here
+ *
+ */
+
+static int snd_card_saa7134_capture_trigger(struct snd_pcm_substream * substream,
+					  int cmd)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	snd_card_saa7134_pcm_t *pcm = runtime->private_data;
+	struct saa7134_dev *dev=pcm->dev;
+	int err = 0;
+
+	spin_lock(&dev->slock);
+	if (cmd == SNDRV_PCM_TRIGGER_START) {
+		/* start dma */
+		saa7134_dma_start(dev);
+	} else if (cmd == SNDRV_PCM_TRIGGER_STOP) {
+		/* stop dma */
+		saa7134_dma_stop(dev);
+	} else {
+		err = -EINVAL;
+	}
+	spin_unlock(&dev->slock);
+
+	return err;
+}
+
+/*
+ * DMA buffer initialization
+ *
+ *   Uses V4L functions to initialize the DMA. Shouldn't be necessary in
+ *  ALSA, but I was unable to use ALSA's own DMA, and had to force the
+ *  usage of V4L's
+ *
+ *   - Copied verbatim from saa7134-oss.
+ *
+ */
+
+static int dsp_buffer_init(struct saa7134_dev *dev)
+{
+	int err;
+
+	BUG_ON(!dev->dmasound.bufsize);
+
+	videobuf_dma_init(&dev->dmasound.dma);
+	err = videobuf_dma_init_kernel(&dev->dmasound.dma, PCI_DMA_FROMDEVICE,
+				       (dev->dmasound.bufsize + PAGE_SIZE) >> PAGE_SHIFT);
+	if (0 != err)
+		return err;
+	return 0;
+}
+
+/*
+ * DMA buffer release
+ *
+ *   Called after closing the device, during snd_card_saa7134_capture_close
+ *
+ */
+
+static int dsp_buffer_free(struct saa7134_dev *dev)
+{
+	BUG_ON(!dev->dmasound.blksize);
+
+	videobuf_dma_free(&dev->dmasound.dma);
+
+	dev->dmasound.blocks  = 0;
+	dev->dmasound.blksize = 0;
+	dev->dmasound.bufsize = 0;
+
+	return 0;
+}
+
+/*
+ * Setting the capture source and updating the ALSA controls
+ */
+static int snd_saa7134_capsrc_set(struct snd_kcontrol *kcontrol,
+				  int left, int right, bool force_notify)
+{
+	snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol);
+	int change = 0, addr = kcontrol->private_value;
+	int active, old_addr;
+	u32 anabar, xbarin;
+	int analog_io, rate;
+	struct saa7134_dev *dev;
+
+	dev = chip->dev;
+
+	spin_lock_irq(&chip->mixer_lock);
+
+	active = left != 0 || right != 0;
+	old_addr = chip->capture_source_addr;
+
+	/* The active capture source cannot be deactivated */
+	if (active) {
+		change = old_addr != addr ||
+			 chip->capture_source[0] != left ||
+			 chip->capture_source[1] != right;
+
+		chip->capture_source[0] = left;
+		chip->capture_source[1] = right;
+		chip->capture_source_addr = addr;
+		dev->dmasound.input = addr;
+	}
+	spin_unlock_irq(&chip->mixer_lock);
+
+	if (change) {
+		switch (dev->pci->device) {
+
+		case PCI_DEVICE_ID_PHILIPS_SAA7134:
+			switch (addr) {
+			case MIXER_ADDR_TVTUNER:
+				saa_andorb(SAA7134_AUDIO_FORMAT_CTRL,
+					   0xc0, 0xc0);
+				saa_andorb(SAA7134_SIF_SAMPLE_FREQ,
+					   0x03, 0x00);
+				break;
+			case MIXER_ADDR_LINE1:
+			case MIXER_ADDR_LINE2:
+				analog_io = (MIXER_ADDR_LINE1 == addr) ?
+					     0x00 : 0x08;
+				rate = (32000 == dev->dmasound.rate) ?
+					0x01 : 0x03;
+				saa_andorb(SAA7134_ANALOG_IO_SELECT,
+					   0x08, analog_io);
+				saa_andorb(SAA7134_AUDIO_FORMAT_CTRL,
+					   0xc0, 0x80);
+				saa_andorb(SAA7134_SIF_SAMPLE_FREQ,
+					   0x03, rate);
+				break;
+			}
+
+			break;
+		case PCI_DEVICE_ID_PHILIPS_SAA7133:
+		case PCI_DEVICE_ID_PHILIPS_SAA7135:
+			xbarin = 0x03; /* adc */
+			anabar = 0;
+			switch (addr) {
+			case MIXER_ADDR_TVTUNER:
+				xbarin = 0; /* Demodulator */
+				anabar = 2; /* DACs */
+				break;
+			case MIXER_ADDR_LINE1:
+				anabar = 0;  /* aux1, aux1 */
+				break;
+			case MIXER_ADDR_LINE2:
+				anabar = 9;  /* aux2, aux2 */
+				break;
+			}
+
+			/* output xbar always main channel */
+			saa_dsp_writel(dev, SAA7133_DIGITAL_OUTPUT_SEL1,
+				       0xbbbb10);
+
+			if (left || right) {
+				/* We've got data, turn the input on */
+				saa_dsp_writel(dev, SAA7133_DIGITAL_INPUT_XBAR1,
+					       xbarin);
+				saa_writel(SAA7133_ANALOG_IO_SELECT, anabar);
+			} else {
+				saa_dsp_writel(dev, SAA7133_DIGITAL_INPUT_XBAR1,
+					       0);
+				saa_writel(SAA7133_ANALOG_IO_SELECT, 0);
+			}
+			break;
+		}
+	}
+
+	if (change) {
+		if (force_notify)
+			snd_ctl_notify(chip->card,
+				       SNDRV_CTL_EVENT_MASK_VALUE,
+				       &chip->capture_ctl[addr]->id);
+
+		if (old_addr != MIXER_ADDR_UNSELECTED && old_addr != addr)
+			snd_ctl_notify(chip->card,
+				       SNDRV_CTL_EVENT_MASK_VALUE,
+				       &chip->capture_ctl[old_addr]->id);
+	}
+
+	return change;
+}
+
+/*
+ * ALSA PCM preparation
+ *
+ *   - One of the ALSA capture callbacks.
+ *
+ *   Called right after the capture device is opened, this function configures
+ *  the buffer using the previously defined functions, allocates the memory,
+ *  sets up the hardware registers, and then starts the DMA. When this function
+ *  returns, the audio should be flowing.
+ *
+ */
+
+static int snd_card_saa7134_capture_prepare(struct snd_pcm_substream * substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	int bswap, sign;
+	u32 fmt, control;
+	snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream);
+	struct saa7134_dev *dev;
+	snd_card_saa7134_pcm_t *pcm = runtime->private_data;
+
+	pcm->dev->dmasound.substream = substream;
+
+	dev = saa7134->dev;
+
+	if (snd_pcm_format_width(runtime->format) == 8)
+		fmt = 0x00;
+	else
+		fmt = 0x01;
+
+	if (snd_pcm_format_signed(runtime->format))
+		sign = 1;
+	else
+		sign = 0;
+
+	if (snd_pcm_format_big_endian(runtime->format))
+		bswap = 1;
+	else
+		bswap = 0;
+
+	switch (dev->pci->device) {
+	  case PCI_DEVICE_ID_PHILIPS_SAA7134:
+		if (1 == runtime->channels)
+			fmt |= (1 << 3);
+		if (2 == runtime->channels)
+			fmt |= (3 << 3);
+		if (sign)
+			fmt |= 0x04;
+
+		fmt |= (MIXER_ADDR_TVTUNER == dev->dmasound.input) ? 0xc0 : 0x80;
+		saa_writeb(SAA7134_NUM_SAMPLES0, ((dev->dmasound.blksize - 1) & 0x0000ff));
+		saa_writeb(SAA7134_NUM_SAMPLES1, ((dev->dmasound.blksize - 1) & 0x00ff00) >>  8);
+		saa_writeb(SAA7134_NUM_SAMPLES2, ((dev->dmasound.blksize - 1) & 0xff0000) >> 16);
+		saa_writeb(SAA7134_AUDIO_FORMAT_CTRL, fmt);
+
+		break;
+	  case PCI_DEVICE_ID_PHILIPS_SAA7133:
+	  case PCI_DEVICE_ID_PHILIPS_SAA7135:
+		if (1 == runtime->channels)
+			fmt |= (1 << 4);
+		if (2 == runtime->channels)
+			fmt |= (2 << 4);
+		if (!sign)
+			fmt |= 0x04;
+		saa_writel(SAA7133_NUM_SAMPLES, dev->dmasound.blksize -1);
+		saa_writel(SAA7133_AUDIO_CHANNEL, 0x543210 | (fmt << 24));
+		break;
+	}
+
+	dprintk("rec_start: afmt=%d ch=%d  =>  fmt=0x%x swap=%c\n",
+		runtime->format, runtime->channels, fmt,
+		bswap ? 'b' : '-');
+	/* dma: setup channel 6 (= AUDIO) */
+	control = SAA7134_RS_CONTROL_BURST_16 |
+		SAA7134_RS_CONTROL_ME |
+		(dev->dmasound.pt.dma >> 12);
+	if (bswap)
+		control |= SAA7134_RS_CONTROL_BSWAP;
+
+	saa_writel(SAA7134_RS_BA1(6),0);
+	saa_writel(SAA7134_RS_BA2(6),dev->dmasound.blksize);
+	saa_writel(SAA7134_RS_PITCH(6),0);
+	saa_writel(SAA7134_RS_CONTROL(6),control);
+
+	dev->dmasound.rate = runtime->rate;
+
+	/* Setup and update the card/ALSA controls */
+	snd_saa7134_capsrc_set(saa7134->capture_ctl[dev->dmasound.input], 1, 1,
+			       true);
+
+	return 0;
+
+}
+
+/*
+ * ALSA pointer fetching
+ *
+ *   - One of the ALSA capture callbacks.
+ *
+ *   Called whenever a period elapses, it must return the current hardware
+ *  position of the buffer.
+ *   Also resets the read counter used to prevent overruns
+ *
+ */
+
+static snd_pcm_uframes_t
+snd_card_saa7134_capture_pointer(struct snd_pcm_substream * substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	snd_card_saa7134_pcm_t *pcm = runtime->private_data;
+	struct saa7134_dev *dev=pcm->dev;
+
+	if (dev->dmasound.read_count) {
+		dev->dmasound.read_count  -= snd_pcm_lib_period_bytes(substream);
+		dev->dmasound.read_offset += snd_pcm_lib_period_bytes(substream);
+		if (dev->dmasound.read_offset == dev->dmasound.bufsize)
+			dev->dmasound.read_offset = 0;
+	}
+
+	return bytes_to_frames(runtime, dev->dmasound.read_offset);
+}
+
+/*
+ * ALSA hardware capabilities definition
+ *
+ *  Report only 32kHz for ALSA:
+ *
+ *  - SAA7133/35 uses DDEP (DemDec Easy Programming mode), which works in 32kHz
+ *    only
+ *  - SAA7134 for TV mode uses DemDec mode (32kHz)
+ *  - Radio works in 32kHz only
+ *  - When recording 48kHz from Line1/Line2, switching of capture source to TV
+ *    means
+ *    switching to 32kHz without any frequency translation
+ */
+
+static struct snd_pcm_hardware snd_card_saa7134_capture =
+{
+	.info =                 (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
+				 SNDRV_PCM_INFO_BLOCK_TRANSFER |
+				 SNDRV_PCM_INFO_MMAP_VALID),
+	.formats =		SNDRV_PCM_FMTBIT_S16_LE | \
+				SNDRV_PCM_FMTBIT_S16_BE | \
+				SNDRV_PCM_FMTBIT_S8 | \
+				SNDRV_PCM_FMTBIT_U8 | \
+				SNDRV_PCM_FMTBIT_U16_LE | \
+				SNDRV_PCM_FMTBIT_U16_BE,
+	.rates =		SNDRV_PCM_RATE_32000,
+	.rate_min =		32000,
+	.rate_max =		32000,
+	.channels_min =		1,
+	.channels_max =		2,
+	.buffer_bytes_max =	(256*1024),
+	.period_bytes_min =	64,
+	.period_bytes_max =	(256*1024),
+	.periods_min =		4,
+	.periods_max =		1024,
+};
+
+static void snd_card_saa7134_runtime_free(struct snd_pcm_runtime *runtime)
+{
+	snd_card_saa7134_pcm_t *pcm = runtime->private_data;
+
+	kfree(pcm);
+}
+
+
+/*
+ * ALSA hardware params
+ *
+ *   - One of the ALSA capture callbacks.
+ *
+ *   Called on initialization, right before the PCM preparation
+ *
+ */
+
+static int snd_card_saa7134_hw_params(struct snd_pcm_substream * substream,
+				      struct snd_pcm_hw_params * hw_params)
+{
+	snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream);
+	struct saa7134_dev *dev;
+	unsigned int period_size, periods;
+	int err;
+
+	period_size = params_period_bytes(hw_params);
+	periods = params_periods(hw_params);
+
+	if (period_size < 0x100 || period_size > 0x10000)
+		return -EINVAL;
+	if (periods < 4)
+		return -EINVAL;
+	if (period_size * periods > 1024 * 1024)
+		return -EINVAL;
+
+	dev = saa7134->dev;
+
+	if (dev->dmasound.blocks == periods &&
+	    dev->dmasound.blksize == period_size)
+		return 0;
+
+	/* release the old buffer */
+	if (substream->runtime->dma_area) {
+		saa7134_pgtable_free(dev->pci, &dev->dmasound.pt);
+		videobuf_dma_unmap(&dev->pci->dev, &dev->dmasound.dma);
+		dsp_buffer_free(dev);
+		substream->runtime->dma_area = NULL;
+	}
+	dev->dmasound.blocks  = periods;
+	dev->dmasound.blksize = period_size;
+	dev->dmasound.bufsize = period_size * periods;
+
+	err = dsp_buffer_init(dev);
+	if (0 != err) {
+		dev->dmasound.blocks  = 0;
+		dev->dmasound.blksize = 0;
+		dev->dmasound.bufsize = 0;
+		return err;
+	}
+
+	if (0 != (err = videobuf_dma_map(&dev->pci->dev, &dev->dmasound.dma))) {
+		dsp_buffer_free(dev);
+		return err;
+	}
+	if (0 != (err = saa7134_pgtable_alloc(dev->pci,&dev->dmasound.pt))) {
+		videobuf_dma_unmap(&dev->pci->dev, &dev->dmasound.dma);
+		dsp_buffer_free(dev);
+		return err;
+	}
+	if (0 != (err = saa7134_pgtable_build(dev->pci,&dev->dmasound.pt,
+						dev->dmasound.dma.sglist,
+						dev->dmasound.dma.sglen,
+						0))) {
+		saa7134_pgtable_free(dev->pci, &dev->dmasound.pt);
+		videobuf_dma_unmap(&dev->pci->dev, &dev->dmasound.dma);
+		dsp_buffer_free(dev);
+		return err;
+	}
+
+	/* I should be able to use runtime->dma_addr in the control
+	   byte, but it doesn't work. So I allocate the DMA using the
+	   V4L functions, and force ALSA to use that as the DMA area */
+
+	substream->runtime->dma_area = dev->dmasound.dma.vaddr;
+	substream->runtime->dma_bytes = dev->dmasound.bufsize;
+	substream->runtime->dma_addr = 0;
+
+	return 0;
+
+}
+
+/*
+ * ALSA hardware release
+ *
+ *   - One of the ALSA capture callbacks.
+ *
+ *   Called after closing the device, but before snd_card_saa7134_capture_close
+ *   It stops the DMA audio and releases the buffers.
+ *
+ */
+
+static int snd_card_saa7134_hw_free(struct snd_pcm_substream * substream)
+{
+	snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream);
+	struct saa7134_dev *dev;
+
+	dev = saa7134->dev;
+
+	if (substream->runtime->dma_area) {
+		saa7134_pgtable_free(dev->pci, &dev->dmasound.pt);
+		videobuf_dma_unmap(&dev->pci->dev, &dev->dmasound.dma);
+		dsp_buffer_free(dev);
+		substream->runtime->dma_area = NULL;
+	}
+
+	return 0;
+}
+
+/*
+ * ALSA capture finish
+ *
+ *   - One of the ALSA capture callbacks.
+ *
+ *   Called after closing the device.
+ *
+ */
+
+static int snd_card_saa7134_capture_close(struct snd_pcm_substream * substream)
+{
+	snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream);
+	struct saa7134_dev *dev = saa7134->dev;
+
+	if (saa7134->mute_was_on) {
+		dev->ctl_mute = 1;
+		saa7134_tvaudio_setmute(dev);
+	}
+	return 0;
+}
+
+/*
+ * ALSA capture start
+ *
+ *   - One of the ALSA capture callbacks.
+ *
+ *   Called when opening the device. It creates and populates the PCM
+ *  structure
+ *
+ */
+
+static int snd_card_saa7134_capture_open(struct snd_pcm_substream * substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	snd_card_saa7134_pcm_t *pcm;
+	snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream);
+	struct saa7134_dev *dev;
+	int amux, err;
+
+	if (!saa7134) {
+		printk(KERN_ERR "BUG: saa7134 can't find device struct."
+				" Can't proceed with open\n");
+		return -ENODEV;
+	}
+	dev = saa7134->dev;
+	mutex_lock(&dev->dmasound.lock);
+
+	dev->dmasound.read_count  = 0;
+	dev->dmasound.read_offset = 0;
+
+	amux = dev->input->amux;
+	if ((amux < 1) || (amux > 3))
+		amux = 1;
+	dev->dmasound.input  =  amux - 1;
+
+	mutex_unlock(&dev->dmasound.lock);
+
+	pcm = kzalloc(sizeof(*pcm), GFP_KERNEL);
+	if (pcm == NULL)
+		return -ENOMEM;
+
+	pcm->dev=saa7134->dev;
+
+	spin_lock_init(&pcm->lock);
+
+	pcm->substream = substream;
+	runtime->private_data = pcm;
+	runtime->private_free = snd_card_saa7134_runtime_free;
+	runtime->hw = snd_card_saa7134_capture;
+
+	if (dev->ctl_mute != 0) {
+		saa7134->mute_was_on = 1;
+		dev->ctl_mute = 0;
+		saa7134_tvaudio_setmute(dev);
+	}
+
+	err = snd_pcm_hw_constraint_integer(runtime,
+						SNDRV_PCM_HW_PARAM_PERIODS);
+	if (err < 0)
+		return err;
+
+	err = snd_pcm_hw_constraint_step(runtime, 0,
+						SNDRV_PCM_HW_PARAM_PERIODS, 2);
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
+/*
+ * page callback (needed for mmap)
+ */
+
+static struct page *snd_card_saa7134_page(struct snd_pcm_substream *substream,
+					unsigned long offset)
+{
+	void *pageptr = substream->runtime->dma_area + offset;
+	return vmalloc_to_page(pageptr);
+}
+
+/*
+ * ALSA capture callbacks definition
+ */
+
+static struct snd_pcm_ops snd_card_saa7134_capture_ops = {
+	.open =			snd_card_saa7134_capture_open,
+	.close =		snd_card_saa7134_capture_close,
+	.ioctl =		snd_pcm_lib_ioctl,
+	.hw_params =		snd_card_saa7134_hw_params,
+	.hw_free =		snd_card_saa7134_hw_free,
+	.prepare =		snd_card_saa7134_capture_prepare,
+	.trigger =		snd_card_saa7134_capture_trigger,
+	.pointer =		snd_card_saa7134_capture_pointer,
+	.page =			snd_card_saa7134_page,
+};
+
+/*
+ * ALSA PCM setup
+ *
+ *   Called when initializing the board. Sets up the name and hooks up
+ *  the callbacks
+ *
+ */
+
+static int snd_card_saa7134_pcm(snd_card_saa7134_t *saa7134, int device)
+{
+	struct snd_pcm *pcm;
+	int err;
+
+	if ((err = snd_pcm_new(saa7134->card, "SAA7134 PCM", device, 0, 1, &pcm)) < 0)
+		return err;
+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_card_saa7134_capture_ops);
+	pcm->private_data = saa7134;
+	pcm->info_flags = 0;
+	strcpy(pcm->name, "SAA7134 PCM");
+	return 0;
+}
+
+#define SAA713x_VOLUME(xname, xindex, addr) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
+  .info = snd_saa7134_volume_info, \
+  .get = snd_saa7134_volume_get, .put = snd_saa7134_volume_put, \
+  .private_value = addr }
+
+static int snd_saa7134_volume_info(struct snd_kcontrol * kcontrol,
+				   struct snd_ctl_elem_info * uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 2;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 20;
+	return 0;
+}
+
+static int snd_saa7134_volume_get(struct snd_kcontrol * kcontrol,
+				  struct snd_ctl_elem_value * ucontrol)
+{
+	snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol);
+	int addr = kcontrol->private_value;
+
+	ucontrol->value.integer.value[0] = chip->mixer_volume[addr][0];
+	ucontrol->value.integer.value[1] = chip->mixer_volume[addr][1];
+	return 0;
+}
+
+static int snd_saa7134_volume_put(struct snd_kcontrol * kcontrol,
+				  struct snd_ctl_elem_value * ucontrol)
+{
+	snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol);
+	struct saa7134_dev *dev = chip->dev;
+
+	int change, addr = kcontrol->private_value;
+	int left, right;
+
+	left = ucontrol->value.integer.value[0];
+	if (left < 0)
+		left = 0;
+	if (left > 20)
+		left = 20;
+	right = ucontrol->value.integer.value[1];
+	if (right < 0)
+		right = 0;
+	if (right > 20)
+		right = 20;
+	spin_lock_irq(&chip->mixer_lock);
+	change = 0;
+	if (chip->mixer_volume[addr][0] != left) {
+		change = 1;
+		right = left;
+	}
+	if (chip->mixer_volume[addr][1] != right) {
+		change = 1;
+		left = right;
+	}
+	if (change) {
+		switch (dev->pci->device) {
+			case PCI_DEVICE_ID_PHILIPS_SAA7134:
+				switch (addr) {
+					case MIXER_ADDR_TVTUNER:
+						left = 20;
+						break;
+					case MIXER_ADDR_LINE1:
+						saa_andorb(SAA7134_ANALOG_IO_SELECT,  0x10,
+							   (left > 10) ? 0x00 : 0x10);
+						break;
+					case MIXER_ADDR_LINE2:
+						saa_andorb(SAA7134_ANALOG_IO_SELECT,  0x20,
+							   (left > 10) ? 0x00 : 0x20);
+						break;
+				}
+				break;
+			case PCI_DEVICE_ID_PHILIPS_SAA7133:
+			case PCI_DEVICE_ID_PHILIPS_SAA7135:
+				switch (addr) {
+					case MIXER_ADDR_TVTUNER:
+						left = 20;
+						break;
+					case MIXER_ADDR_LINE1:
+						saa_andorb(0x0594,  0x10,
+							   (left > 10) ? 0x00 : 0x10);
+						break;
+					case MIXER_ADDR_LINE2:
+						saa_andorb(0x0594,  0x20,
+							   (left > 10) ? 0x00 : 0x20);
+						break;
+				}
+				break;
+		}
+		chip->mixer_volume[addr][0] = left;
+		chip->mixer_volume[addr][1] = right;
+	}
+	spin_unlock_irq(&chip->mixer_lock);
+	return change;
+}
+
+#define SAA713x_CAPSRC(xname, xindex, addr) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
+  .info = snd_saa7134_capsrc_info, \
+  .get = snd_saa7134_capsrc_get, .put = snd_saa7134_capsrc_put, \
+  .private_value = addr }
+
+static int snd_saa7134_capsrc_info(struct snd_kcontrol * kcontrol,
+				   struct snd_ctl_elem_info * uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+	uinfo->count = 2;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 1;
+	return 0;
+}
+
+static int snd_saa7134_capsrc_get(struct snd_kcontrol * kcontrol,
+				  struct snd_ctl_elem_value * ucontrol)
+{
+	snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol);
+	int addr = kcontrol->private_value;
+
+	spin_lock_irq(&chip->mixer_lock);
+	if (chip->capture_source_addr == addr) {
+		ucontrol->value.integer.value[0] = chip->capture_source[0];
+		ucontrol->value.integer.value[1] = chip->capture_source[1];
+	} else {
+		ucontrol->value.integer.value[0] = 0;
+		ucontrol->value.integer.value[1] = 0;
+	}
+	spin_unlock_irq(&chip->mixer_lock);
+
+	return 0;
+}
+
+static int snd_saa7134_capsrc_put(struct snd_kcontrol * kcontrol,
+				  struct snd_ctl_elem_value * ucontrol)
+{
+	int left, right;
+	left = ucontrol->value.integer.value[0] & 1;
+	right = ucontrol->value.integer.value[1] & 1;
+
+	return snd_saa7134_capsrc_set(kcontrol, left, right, false);
+}
+
+static struct snd_kcontrol_new snd_saa7134_volume_controls[] = {
+SAA713x_VOLUME("Video Volume", 0, MIXER_ADDR_TVTUNER),
+SAA713x_VOLUME("Line Volume", 1, MIXER_ADDR_LINE1),
+SAA713x_VOLUME("Line Volume", 2, MIXER_ADDR_LINE2),
+};
+
+static struct snd_kcontrol_new snd_saa7134_capture_controls[] = {
+SAA713x_CAPSRC("Video Capture Switch", 0, MIXER_ADDR_TVTUNER),
+SAA713x_CAPSRC("Line Capture Switch", 1, MIXER_ADDR_LINE1),
+SAA713x_CAPSRC("Line Capture Switch", 2, MIXER_ADDR_LINE2),
+};
+
+/*
+ * ALSA mixer setup
+ *
+ *   Called when initializing the board. Sets up the name and hooks up
+ *  the callbacks
+ *
+ */
+
+static int snd_card_saa7134_new_mixer(snd_card_saa7134_t * chip)
+{
+	struct snd_card *card = chip->card;
+	struct snd_kcontrol *kcontrol;
+	unsigned int idx;
+	int err, addr;
+
+	strcpy(card->mixername, "SAA7134 Mixer");
+
+	for (idx = 0; idx < ARRAY_SIZE(snd_saa7134_volume_controls); idx++) {
+		kcontrol = snd_ctl_new1(&snd_saa7134_volume_controls[idx],
+					chip);
+		err = snd_ctl_add(card, kcontrol);
+		if (err < 0)
+			return err;
+	}
+
+	for (idx = 0; idx < ARRAY_SIZE(snd_saa7134_capture_controls); idx++) {
+		kcontrol = snd_ctl_new1(&snd_saa7134_capture_controls[idx],
+					chip);
+		addr = snd_saa7134_capture_controls[idx].private_value;
+		chip->capture_ctl[addr] = kcontrol;
+		err = snd_ctl_add(card, kcontrol);
+		if (err < 0)
+			return err;
+	}
+
+	chip->capture_source_addr = MIXER_ADDR_UNSELECTED;
+	return 0;
+}
+
+static void snd_saa7134_free(struct snd_card * card)
+{
+	snd_card_saa7134_t *chip = card->private_data;
+
+	if (chip->dev->dmasound.priv_data == NULL)
+		return;
+
+	if (chip->irq >= 0)
+		free_irq(chip->irq, &chip->dev->dmasound);
+
+	chip->dev->dmasound.priv_data = NULL;
+
+}
+
+/*
+ * ALSA initialization
+ *
+ *   Called by the init routine, once for each saa7134 device present,
+ *  it creates the basic structures and registers the ALSA devices
+ *
+ */
+
+static int alsa_card_saa7134_create(struct saa7134_dev *dev, int devnum)
+{
+
+	struct snd_card *card;
+	snd_card_saa7134_t *chip;
+	int err;
+
+
+	if (devnum >= SNDRV_CARDS)
+		return -ENODEV;
+	if (!enable[devnum])
+		return -ENODEV;
+
+	err = snd_card_create(index[devnum], id[devnum], THIS_MODULE,
+			      sizeof(snd_card_saa7134_t), &card);
+	if (err < 0)
+		return err;
+
+	strcpy(card->driver, "SAA7134");
+
+	/* Card "creation" */
+
+	card->private_free = snd_saa7134_free;
+	chip = card->private_data;
+
+	spin_lock_init(&chip->lock);
+	spin_lock_init(&chip->mixer_lock);
+
+	chip->dev = dev;
+
+	chip->card = card;
+
+	chip->pci = dev->pci;
+	chip->iobase = pci_resource_start(dev->pci, 0);
+
+
+	err = request_irq(dev->pci->irq, saa7134_alsa_irq,
+				IRQF_SHARED | IRQF_DISABLED, dev->name,
+				(void*) &dev->dmasound);
+
+	if (err < 0) {
+		printk(KERN_ERR "%s: can't get IRQ %d for ALSA\n",
+			dev->name, dev->pci->irq);
+		goto __nodev;
+	}
+
+	chip->irq = dev->pci->irq;
+
+	mutex_init(&dev->dmasound.lock);
+
+	if ((err = snd_card_saa7134_new_mixer(chip)) < 0)
+		goto __nodev;
+
+	if ((err = snd_card_saa7134_pcm(chip, 0)) < 0)
+		goto __nodev;
+
+	snd_card_set_dev(card, &chip->pci->dev);
+
+	/* End of "creation" */
+
+	strcpy(card->shortname, "SAA7134");
+	sprintf(card->longname, "%s at 0x%lx irq %d",
+		chip->dev->name, chip->iobase, chip->irq);
+
+	printk(KERN_INFO "%s/alsa: %s registered as card %d\n",dev->name,card->longname,index[devnum]);
+
+	if ((err = snd_card_register(card)) == 0) {
+		snd_saa7134_cards[devnum] = card;
+		return 0;
+	}
+
+__nodev:
+	snd_card_free(card);
+	return err;
+}
+
+
+static int alsa_device_init(struct saa7134_dev *dev)
+{
+	dev->dmasound.priv_data = dev;
+	alsa_card_saa7134_create(dev,dev->nr);
+	return 1;
+}
+
+static int alsa_device_exit(struct saa7134_dev *dev)
+{
+
+	snd_card_free(snd_saa7134_cards[dev->nr]);
+	snd_saa7134_cards[dev->nr] = NULL;
+	return 1;
+}
+
+/*
+ * Module initializer
+ *
+ * Loops through present saa7134 cards, and assigns an ALSA device
+ * to each one
+ *
+ */
+
+static int saa7134_alsa_init(void)
+{
+	struct saa7134_dev *dev = NULL;
+	struct list_head *list;
+
+	saa7134_dmasound_init = alsa_device_init;
+	saa7134_dmasound_exit = alsa_device_exit;
+
+	printk(KERN_INFO "saa7134 ALSA driver for DMA sound loaded\n");
+
+	list_for_each(list,&saa7134_devlist) {
+		dev = list_entry(list, struct saa7134_dev, devlist);
+		if (dev->pci->device == PCI_DEVICE_ID_PHILIPS_SAA7130)
+			printk(KERN_INFO "%s/alsa: %s doesn't support digital audio\n",
+				dev->name, saa7134_boards[dev->board].name);
+		else
+			alsa_device_init(dev);
+	}
+
+	if (dev == NULL)
+		printk(KERN_INFO "saa7134 ALSA: no saa7134 cards found\n");
+
+	return 0;
+
+}
+
+/*
+ * Module destructor
+ */
+
+static void saa7134_alsa_exit(void)
+{
+	int idx;
+
+	for (idx = 0; idx < SNDRV_CARDS; idx++) {
+		snd_card_free(snd_saa7134_cards[idx]);
+	}
+
+	saa7134_dmasound_init = NULL;
+	saa7134_dmasound_exit = NULL;
+	printk(KERN_INFO "saa7134 ALSA driver for DMA sound unloaded\n");
+
+	return;
+}
+
+/* We initialize this late, to make sure the sound system is up and running */
+late_initcall(saa7134_alsa_init);
+module_exit(saa7134_alsa_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Ricardo Cerqueira");
diff --git a/drivers/media/pci/saa7134/saa7134-cards.c b/drivers/media/pci/saa7134/saa7134-cards.c
new file mode 100644
index 0000000..bc08f1d
--- /dev/null
+++ b/drivers/media/pci/saa7134/saa7134-cards.c
@@ -0,0 +1,8026 @@
+/*
+ *
+ * device driver for philips saa7134 based TV cards
+ * card-specific stuff.
+ *
+ * (c) 2001-04 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the 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/init.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+
+#include "saa7134-reg.h"
+#include "saa7134.h"
+#include "tuner-xc2028.h"
+#include <media/v4l2-common.h>
+#include <media/tveeprom.h>
+#include "tea5767.h"
+#include "tda18271.h"
+#include "xc5000.h"
+#include "s5h1411.h"
+
+/* commly used strings */
+static char name_mute[]    = "mute";
+static char name_radio[]   = "Radio";
+static char name_tv[]      = "Television";
+static char name_tv_mono[] = "TV (mono only)";
+static char name_comp[]    = "Composite";
+static char name_comp1[]   = "Composite1";
+static char name_comp2[]   = "Composite2";
+static char name_comp3[]   = "Composite3";
+static char name_comp4[]   = "Composite4";
+static char name_svideo[]  = "S-Video";
+
+/* ------------------------------------------------------------------ */
+/* board config info                                                  */
+
+/* If radio_type !=UNSET, radio_addr should be specified
+ */
+
+struct saa7134_board saa7134_boards[] = {
+	[SAA7134_BOARD_UNKNOWN] = {
+		.name		= "UNKNOWN/GENERIC",
+		.audio_clock	= 0x00187de7,
+		.tuner_type	= TUNER_ABSENT,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+
+		.inputs         = {{
+			.name = "default",
+			.vmux = 0,
+			.amux = LINE1,
+		}},
+	},
+	[SAA7134_BOARD_PROTEUS_PRO] = {
+		/* /me */
+		.name		= "Proteus Pro [philips reference design]",
+		.audio_clock	= 0x00187de7,
+		.tuner_type	= TUNER_PHILIPS_PAL,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+
+		.inputs         = {{
+			.name = name_comp1,
+			.vmux = 0,
+			.amux = LINE1,
+		},{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.tv   = 1,
+		},{
+			.name = name_tv_mono,
+			.vmux = 1,
+			.amux = LINE2,
+			.tv   = 1,
+		}},
+		.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+		},
+	},
+	[SAA7134_BOARD_FLYVIDEO3000] = {
+		/* "Marco d'Itri" <md@Linux.IT> */
+		.name		= "LifeView FlyVIDEO3000",
+		.audio_clock	= 0x00200000,
+		.tuner_type	= TUNER_PHILIPS_PAL,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+
+		.gpiomask       = 0xe000,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.gpio = 0x8000,
+			.tv   = 1,
+		},{
+			.name = name_tv_mono,
+			.vmux = 1,
+			.amux = LINE2,
+			.gpio = 0x0000,
+			.tv   = 1,
+		},{
+			.name = name_comp1,
+			.vmux = 0,
+			.amux = LINE2,
+			.gpio = 0x4000,
+		},{
+			.name = name_comp2,
+			.vmux = 3,
+			.amux = LINE2,
+			.gpio = 0x4000,
+		},{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE2,
+			.gpio = 0x4000,
+		}},
+		.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+			.gpio = 0x2000,
+		},
+		.mute = {
+			.name = name_mute,
+			.amux = TV,
+			.gpio = 0x8000,
+		},
+	},
+	[SAA7134_BOARD_FLYVIDEO2000] = {
+		/* "TC Wan" <tcwan@cs.usm.my> */
+		.name           = "LifeView/Typhoon FlyVIDEO2000",
+		.audio_clock    = 0x00200000,
+		.tuner_type     = TUNER_LG_PAL_NEW_TAPC,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+
+		.gpiomask       = 0xe000,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = LINE2,
+			.gpio = 0x0000,
+			.tv   = 1,
+		},{
+			.name = name_comp1,
+			.vmux = 0,
+			.amux = LINE2,
+			.gpio = 0x4000,
+		},{
+			.name = name_comp2,
+			.vmux = 3,
+			.amux = LINE2,
+			.gpio = 0x4000,
+		},{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE2,
+			.gpio = 0x4000,
+		}},
+		.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+			.gpio = 0x2000,
+		},
+		.mute = {
+			.name = name_mute,
+			.amux = LINE2,
+			.gpio = 0x8000,
+		},
+	},
+	[SAA7134_BOARD_FLYTVPLATINUM_MINI] = {
+		/* "Arnaud Quette" <aquette@free.fr> */
+		.name           = "LifeView FlyTV Platinum Mini",
+		.audio_clock    = 0x00200000,
+		.tuner_type     = TUNER_PHILIPS_TDA8290,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.tv   = 1,
+		},{
+			.name = name_comp1,     /* Composite signal on S-Video input */
+			.vmux = 0,
+			.amux = LINE2,
+		},{
+			.name = name_comp2,	/* Composite input */
+			.vmux = 3,
+			.amux = LINE2,
+		},{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE2,
+		}},
+	},
+	[SAA7134_BOARD_FLYTVPLATINUM_FM] = {
+		/* LifeView FlyTV Platinum FM (LR214WF) */
+		/* "Peter Missel <peter.missel@onlinehome.de> */
+		.name           = "LifeView FlyTV Platinum FM / Gold",
+		.audio_clock    = 0x00200000,
+		.tuner_type     = TUNER_PHILIPS_TDA8290,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+
+		.gpiomask       = 0x1E000,	/* Set GP16 and unused 15,14,13 to Output */
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.gpio = 0x10000,	/* GP16=1 selects TV input */
+			.tv   = 1,
+		},{
+/*			.name = name_tv_mono,
+			.vmux = 1,
+			.amux = LINE2,
+			.gpio = 0x0000,
+			.tv   = 1,
+		},{
+*/			.name = name_comp1,	/* Composite signal on S-Video input */
+			.vmux = 0,
+			.amux = LINE2,
+/*			.gpio = 0x4000,         */
+		},{
+			.name = name_comp2,	/* Composite input */
+			.vmux = 3,
+			.amux = LINE2,
+/*			.gpio = 0x4000,         */
+		},{
+			.name = name_svideo,	/* S-Video signal on S-Video input */
+			.vmux = 8,
+			.amux = LINE2,
+/*			.gpio = 0x4000,         */
+		}},
+		.radio = {
+			.name = name_radio,
+			.amux = TV,
+			.gpio = 0x00000,	/* GP16=0 selects FM radio antenna */
+		},
+		.mute = {
+			.name = name_mute,
+			.amux = TV,
+			.gpio = 0x10000,
+		},
+	},
+	[SAA7134_BOARD_ROVERMEDIA_LINK_PRO_FM] = {
+		/* RoverMedia TV Link Pro FM (LR138 REV:I) */
+		/* Eugene Yudin <Eugene.Yudin@gmail.com> */
+		.name		= "RoverMedia TV Link Pro FM",
+		.audio_clock	= 0x00200000,
+		.tuner_type	= TUNER_PHILIPS_FM1216ME_MK3, /* TCL MFPE05 2 */
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.gpiomask       = 0xe000,
+		.inputs         = { {
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.gpio = 0x8000,
+			.tv   = 1,
+		}, {
+			.name = name_tv_mono,
+			.vmux = 1,
+			.amux = LINE2,
+			.gpio = 0x0000,
+			.tv   = 1,
+		}, {
+			.name = name_comp1,
+			.vmux = 0,
+			.amux = LINE2,
+			.gpio = 0x4000,
+		}, {
+			.name = name_comp2,
+			.vmux = 3,
+			.amux = LINE2,
+			.gpio = 0x4000,
+		}, {
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE2,
+			.gpio = 0x4000,
+		} },
+		.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+			.gpio = 0x2000,
+		},
+		.mute = {
+			.name = name_mute,
+			.amux = TV,
+			.gpio = 0x8000,
+		},
+	},
+	[SAA7134_BOARD_EMPRESS] = {
+		/* "Gert Vervoort" <gert.vervoort@philips.com> */
+		.name		= "EMPRESS",
+		.audio_clock	= 0x00187de7,
+		.tuner_type	= TUNER_PHILIPS_PAL,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.empress_addr 	= 0x20,
+
+		.inputs         = {{
+			.name = name_comp1,
+			.vmux = 0,
+			.amux = LINE1,
+		},{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		},{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = LINE2,
+			.tv   = 1,
+		}},
+		.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+		},
+		.mpeg      = SAA7134_MPEG_EMPRESS,
+		.video_out = CCIR656,
+	},
+	[SAA7134_BOARD_MONSTERTV] = {
+		/* "K.Ohta" <alpha292@bremen.or.jp> */
+		.name           = "SKNet Monster TV",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_NTSC_M,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.tv   = 1,
+		},{
+			.name = name_comp1,
+			.vmux = 0,
+			.amux = LINE1,
+		},{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		}},
+		.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+		},
+	},
+	[SAA7134_BOARD_MD9717] = {
+		.name		= "Tevion MD 9717",
+		.audio_clock	= 0x00200000,
+		.tuner_type	= TUNER_PHILIPS_PAL,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.tv   = 1,
+		},{
+			/* workaround for problems with normal TV sound */
+			.name = name_tv_mono,
+			.vmux = 1,
+			.amux = LINE2,
+			.tv   = 1,
+		},{
+			.name = name_comp1,
+			.vmux = 0,
+			.amux = LINE1,
+		},{
+			.name = name_comp2,
+			.vmux = 3,
+			.amux = LINE1,
+		},{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		}},
+		.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+		},
+	       .mute = {
+		       .name = name_mute,
+		       .amux = TV,
+	       },
+	},
+	[SAA7134_BOARD_TVSTATION_RDS] = {
+		/* Typhoon TV Tuner RDS: Art.Nr. 50694 */
+		.name		= "KNC One TV-Station RDS / Typhoon TV Tuner RDS",
+		.audio_clock	= 0x00200000,
+		.tuner_type	= TUNER_PHILIPS_FM1216ME_MK3,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.tv   = 1,
+		},{
+			.name = name_tv_mono,
+			.vmux = 1,
+			.amux   = LINE2,
+			.tv   = 1,
+		},{
+
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		},{
+			.name = name_comp1,
+			.vmux = 3,
+			.amux = LINE1,
+		},{
+
+			.name = "CVid over SVid",
+			.vmux = 0,
+			.amux = LINE1,
+		}},
+		.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+		},
+	},
+	[SAA7134_BOARD_TVSTATION_DVR] = {
+		.name		= "KNC One TV-Station DVR",
+		.audio_clock	= 0x00200000,
+		.tuner_type	= TUNER_PHILIPS_FM1216ME_MK3,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.empress_addr 	= 0x20,
+		.tda9887_conf	= TDA9887_PRESENT,
+		.gpiomask	= 0x820000,
+		.inputs		= {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.tv   = 1,
+			.gpio = 0x20000,
+		},{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+			.gpio = 0x20000,
+		},{
+			.name = name_comp1,
+			.vmux = 3,
+			.amux = LINE1,
+			.gpio = 0x20000,
+		}},
+		.radio		= {
+			.name = name_radio,
+			.amux = LINE2,
+			.gpio = 0x20000,
+		},
+		.mpeg           = SAA7134_MPEG_EMPRESS,
+		.video_out	= CCIR656,
+	},
+	[SAA7134_BOARD_CINERGY400] = {
+		.name           = "Terratec Cinergy 400 TV",
+		.audio_clock    = 0x00200000,
+		.tuner_type     = TUNER_PHILIPS_PAL,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.tv   = 1,
+		},{
+			.name = name_comp1,
+			.vmux = 4,
+			.amux = LINE1,
+		},{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		},{
+			.name = name_comp2, /* CVideo over SVideo Connector */
+			.vmux = 0,
+			.amux = LINE1,
+		}}
+	},
+	[SAA7134_BOARD_MD5044] = {
+		.name           = "Medion 5044",
+		.audio_clock    = 0x00187de7, /* was: 0x00200000, */
+		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.tv   = 1,
+		},{
+			/* workaround for problems with normal TV sound */
+			.name = name_tv_mono,
+			.vmux = 1,
+			.amux = LINE2,
+			.tv   = 1,
+		},{
+			.name = name_comp1,
+			.vmux = 0,
+			.amux = LINE2,
+		},{
+			.name = name_comp2,
+			.vmux = 3,
+			.amux = LINE2,
+		},{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE2,
+		}},
+		.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+		},
+	},
+	[SAA7134_BOARD_KWORLD] = {
+		.name           = "Kworld/KuroutoShikou SAA7130-TVPCI",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_NTSC_M,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.inputs         = {{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		},{
+			.name = name_comp1,
+			.vmux = 3,
+			.amux = LINE1,
+		},{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = LINE2,
+			.tv   = 1,
+		}},
+	},
+	[SAA7134_BOARD_CINERGY600] = {
+		.name           = "Terratec Cinergy 600 TV",
+		.audio_clock    = 0x00200000,
+		.tuner_type     = TUNER_PHILIPS_PAL,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.tv   = 1,
+		},{
+			.name = name_comp1,
+			.vmux = 4,
+			.amux = LINE1,
+		},{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		},{
+			.name = name_comp2, /* CVideo over SVideo Connector */
+			.vmux = 0,
+			.amux = LINE1,
+		}},
+		.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+		},
+	},
+	[SAA7134_BOARD_MD7134] = {
+		.name           = "Medion 7134",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_FMD1216ME_MK3,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.mpeg           = SAA7134_MPEG_DVB,
+		.inputs = {{
+			.name   = name_tv,
+			.vmux   = 1,
+			.amux   = TV,
+			.tv     = 1,
+		},{
+			.name   = name_comp1,
+			.vmux   = 0,
+			.amux   = LINE1,
+		},{
+			.name   = name_svideo,
+			.vmux   = 8,
+			.amux   = LINE1,
+		}},
+		.radio = {
+			.name   = name_radio,
+			.amux   = LINE2,
+	       },
+	       .mute = {
+		       .name = name_mute,
+		       .amux = TV,
+		},
+	},
+	[SAA7134_BOARD_TYPHOON_90031] = {
+		/* aka Typhoon "TV+Radio", Art.Nr 90031 */
+		/* Tom Zoerner <tomzo at users sourceforge net> */
+		.name           = "Typhoon TV+Radio 90031",
+		.audio_clock    = 0x00200000,
+		.tuner_type     = TUNER_PHILIPS_PAL,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.inputs         = {{
+			.name   = name_tv,
+			.vmux   = 1,
+			.amux   = TV,
+			.tv     = 1,
+		},{
+			.name   = name_comp1,
+			.vmux   = 3,
+			.amux   = LINE1,
+		},{
+			.name   = name_svideo,
+			.vmux   = 8,
+			.amux   = LINE1,
+		}},
+		.radio = {
+			.name   = name_radio,
+			.amux   = LINE2,
+		},
+	},
+	[SAA7134_BOARD_ELSA] = {
+		.name           = "ELSA EX-VISION 300TV",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_HITACHI_NTSC,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.inputs         = {{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		},{
+			.name   = name_comp1,
+			.vmux   = 0,
+			.amux   = LINE1,
+		},{
+			.name = name_tv,
+			.vmux = 4,
+			.amux = LINE2,
+			.tv   = 1,
+		}},
+	},
+	[SAA7134_BOARD_ELSA_500TV] = {
+		.name           = "ELSA EX-VISION 500TV",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_HITACHI_NTSC,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.inputs         = {{
+			.name = name_svideo,
+			.vmux = 7,
+			.amux = LINE1,
+		},{
+			.name = name_tv,
+			.vmux = 8,
+			.amux = TV,
+			.tv   = 1,
+		},{
+			.name = name_tv_mono,
+			.vmux = 8,
+			.amux = LINE2,
+			.tv   = 1,
+		}},
+	},
+	[SAA7134_BOARD_ELSA_700TV] = {
+		.name           = "ELSA EX-VISION 700TV",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_HITACHI_NTSC,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 4,
+			.amux = LINE2,
+			.tv   = 1,
+		},{
+			.name = name_comp1,
+			.vmux = 6,
+			.amux = LINE1,
+		},{
+			.name = name_svideo,
+			.vmux = 7,
+			.amux = LINE1,
+		}},
+		.mute           = {
+			.name = name_mute,
+			.amux = TV,
+		},
+	},
+	[SAA7134_BOARD_ASUSTeK_TVFM7134] = {
+		.name           = "ASUS TV-FM 7134",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.tv   = 1,
+		},{
+			.name = name_comp1,
+			.vmux = 4,
+			.amux = LINE2,
+		},{
+			.name = name_svideo,
+			.vmux = 6,
+			.amux = LINE2,
+		}},
+		.radio = {
+			.name = name_radio,
+			.amux = LINE1,
+		},
+	},
+	[SAA7134_BOARD_ASUSTeK_TVFM7135] = {
+		.name           = "ASUS TV-FM 7135",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_TDA8290,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.gpiomask       = 0x200000,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.gpio = 0x0000,
+			.tv   = 1,
+		},{
+			.name = name_comp1,
+			.vmux = 4,
+			.amux = LINE2,
+			.gpio = 0x0000,
+		},{
+			.name = name_svideo,
+			.vmux = 6,
+			.amux = LINE2,
+			.gpio = 0x0000,
+		}},
+		.radio = {
+			.name = name_radio,
+			.amux = TV,
+			.gpio = 0x200000,
+		},
+		.mute  = {
+			.name = name_mute,
+			.gpio = 0x0000,
+		},
+
+	},
+	[SAA7134_BOARD_VA1000POWER] = {
+		.name           = "AOPEN VA1000 POWER",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_NTSC,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.inputs         = {{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		},{
+			.name = name_comp1,
+			.vmux = 3,
+			.amux = LINE1,
+		},{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = LINE2,
+			.tv   = 1,
+		}},
+	},
+	[SAA7134_BOARD_10MOONSTVMASTER] = {
+		/* "lilicheng" <llc@linuxfans.org> */
+		.name           = "10MOONS PCI TV CAPTURE CARD",
+		.audio_clock    = 0x00200000,
+		.tuner_type     = TUNER_LG_PAL_NEW_TAPC,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.gpiomask       = 0xe000,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = LINE2,
+			.gpio = 0x0000,
+			.tv   = 1,
+		},{
+			.name = name_comp1,
+			.vmux = 0,
+			.amux = LINE2,
+			.gpio = 0x4000,
+		},{
+			.name = name_comp2,
+			.vmux = 3,
+			.amux = LINE2,
+			.gpio = 0x4000,
+		},{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE2,
+			.gpio = 0x4000,
+		}},
+		.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+			.gpio = 0x2000,
+		},
+		.mute = {
+			.name = name_mute,
+			.amux = LINE2,
+			.gpio = 0x8000,
+		},
+	},
+	[SAA7134_BOARD_BMK_MPEX_NOTUNER] = {
+		/* "Andrew de Quincey" <adq@lidskialf.net> */
+		.name		= "BMK MPEX No Tuner",
+		.audio_clock	= 0x200000,
+		.tuner_type	= TUNER_ABSENT,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.empress_addr 	= 0x20,
+		.inputs         = {{
+			.name = name_comp1,
+			.vmux = 4,
+			.amux = LINE1,
+		},{
+			.name = name_comp2,
+			.vmux = 3,
+			.amux = LINE1,
+		},{
+			.name = name_comp3,
+			.vmux = 0,
+			.amux = LINE1,
+		},{
+			.name = name_comp4,
+			.vmux = 1,
+			.amux = LINE1,
+		},{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		}},
+		.mpeg      = SAA7134_MPEG_EMPRESS,
+		.video_out = CCIR656,
+	},
+	[SAA7134_BOARD_VIDEOMATE_TV] = {
+		.name           = "Compro VideoMate TV",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_NTSC_M,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.inputs         = {{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		},{
+			.name = name_comp1,
+			.vmux = 3,
+			.amux = LINE1,
+		},{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = LINE2,
+			.tv   = 1,
+		}},
+	},
+	[SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUS] = {
+		.name           = "Compro VideoMate TV Gold+",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_NTSC_M,
+		.gpiomask       = 0x800c0000,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.inputs         = {{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+			.gpio = 0x06c00012,
+		},{
+			.name = name_comp1,
+			.vmux = 3,
+			.amux = LINE1,
+			.gpio = 0x0ac20012,
+		},{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = LINE2,
+			.gpio = 0x08c20012,
+			.tv   = 1,
+		}},				/* radio and probably mute is missing */
+	},
+	[SAA7134_BOARD_CRONOS_PLUS] = {
+		/*
+		gpio pins:
+			0  .. 3   BASE_ID
+			4  .. 7   PROTECT_ID
+			8  .. 11  USER_OUT
+			12 .. 13  USER_IN
+			14 .. 15  VIDIN_SEL
+		*/
+		.name           = "Matrox CronosPlus",
+		.tuner_type     = TUNER_ABSENT,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.gpiomask       = 0xcf00,
+		.inputs         = {{
+			.name = name_comp1,
+			.vmux = 0,
+			.gpio = 2 << 14,
+		},{
+			.name = name_comp2,
+			.vmux = 0,
+			.gpio = 1 << 14,
+		},{
+			.name = name_comp3,
+			.vmux = 0,
+			.gpio = 0 << 14,
+		},{
+			.name = name_comp4,
+			.vmux = 0,
+			.gpio = 3 << 14,
+		},{
+			.name = name_svideo,
+			.vmux = 8,
+			.gpio = 2 << 14,
+		}},
+	},
+	[SAA7134_BOARD_MD2819] = {
+		.name           = "AverMedia M156 / Medion 2819",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.gpiomask	= 0x03,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.tv   = 1,
+			.gpio = 0x00,
+		}, {
+			.name = name_comp1,
+			.vmux = 3,
+			.amux = LINE1,
+			.gpio = 0x02,
+		}, {
+			.name = name_comp2,
+			.vmux = 0,
+			.amux = LINE1,
+			.gpio = 0x02,
+		}, {
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+			.gpio = 0x02,
+		} },
+		.radio = {
+			.name = name_radio,
+			.amux = LINE1,
+			.gpio = 0x01,
+		},
+		.mute  = {
+			.name = name_mute,
+			.amux = TV,
+			.gpio = 0x00,
+		},
+	},
+	[SAA7134_BOARD_BMK_MPEX_TUNER] = {
+		/* "Greg Wickham <greg.wickham@grangenet.net> */
+		.name           = "BMK MPEX Tuner",
+		.audio_clock    = 0x200000,
+		.tuner_type     = TUNER_PHILIPS_PAL,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.empress_addr 	= 0x20,
+		.inputs         = {{
+			.name = name_comp1,
+			.vmux = 1,
+			.amux = LINE1,
+		},{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		},{
+			.name = name_tv,
+			.vmux = 3,
+			.amux = TV,
+			.tv   = 1,
+		}},
+		.mpeg      = SAA7134_MPEG_EMPRESS,
+		.video_out = CCIR656,
+	},
+	[SAA7134_BOARD_ASUSTEK_TVFM7133] = {
+		.name           = "ASUS TV-FM 7133",
+		.audio_clock    = 0x00187de7,
+		/* probably wrong, the 7133 one is the NTSC version ...
+		* .tuner_type  = TUNER_PHILIPS_FM1236_MK3 */
+		.tuner_type     = TUNER_LG_NTSC_NEW_TAPC,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.tv   = 1,
+
+		},{
+			.name = name_comp1,
+			.vmux = 4,
+			.amux = LINE2,
+		},{
+			.name = name_svideo,
+			.vmux = 6,
+			.amux = LINE2,
+		}},
+		.radio = {
+			.name = name_radio,
+			.amux = LINE1,
+		},
+	},
+	[SAA7134_BOARD_PINNACLE_PCTV_STEREO] = {
+		.name           = "Pinnacle PCTV Stereo (saa7134)",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_MT2032,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT | TDA9887_INTERCARRIER | TDA9887_PORT2_INACTIVE,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 3,
+			.amux = TV,
+			.tv   = 1,
+		},{
+			.name = name_comp1,
+			.vmux = 0,
+			.amux = LINE2,
+		},{
+			.name = name_comp2,
+			.vmux = 1,
+			.amux = LINE2,
+		},{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE2,
+		}},
+	},
+	[SAA7134_BOARD_MANLI_MTV002] = {
+		/* Ognjen Nastic <ognjen@logosoft.ba> */
+		.name           = "Manli MuchTV M-TV002",
+		.audio_clock    = 0x00200000,
+		.tuner_type     = TUNER_PHILIPS_PAL,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.inputs         = {{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		},{
+			.name   = name_comp1,
+			.vmux   = 1,
+			.amux   = LINE1,
+		},{
+			.name = name_tv,
+			.vmux = 3,
+			.amux = LINE2,
+			.tv   = 1,
+		}},
+		.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+		},
+	},
+	[SAA7134_BOARD_MANLI_MTV001] = {
+		/* Ognjen Nastic <ognjen@logosoft.ba> UNTESTED */
+		.name           = "Manli MuchTV M-TV001",
+		.audio_clock    = 0x00200000,
+		.tuner_type     = TUNER_PHILIPS_PAL,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.inputs         = {{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		},{
+			.name = name_comp1,
+			.vmux = 1,
+			.amux = LINE1,
+		},{
+			.name = name_tv,
+			.vmux = 3,
+			.amux = LINE2,
+			.tv   = 1,
+		}},
+		.mute = {
+			.name = name_mute,
+			.amux = LINE1,
+		},
+	},
+	[SAA7134_BOARD_TG3000TV] = {
+		/* TransGear 3000TV */
+		.name           = "Nagase Sangyo TransGear 3000TV",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_NTSC_M,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = LINE2,
+			.tv   = 1,
+		},{
+			.name = name_comp1,
+			.vmux = 3,
+			.amux = LINE2,
+		},{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE2,
+		}},
+	},
+	[SAA7134_BOARD_ECS_TVP3XP] = {
+		.name           = "Elitegroup ECS TVP3XP FM1216 Tuner Card(PAL-BG,FM) ",
+		.audio_clock    = 0x187de7,  /* xtal 32.1 MHz */
+		.tuner_type     = TUNER_PHILIPS_PAL,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.inputs         = {{
+			.name   = name_tv,
+			.vmux   = 1,
+			.amux   = TV,
+			.tv     = 1,
+		},{
+			.name   = name_tv_mono,
+			.vmux   = 1,
+			.amux   = LINE2,
+			.tv     = 1,
+		},{
+			.name   = name_comp1,
+			.vmux   = 3,
+			.amux   = LINE1,
+		},{
+			.name   = name_svideo,
+			.vmux   = 8,
+			.amux   = LINE1,
+		},{
+			.name   = "CVid over SVid",
+			.vmux   = 0,
+			.amux   = LINE1,
+		}},
+		.radio = {
+			.name   = name_radio,
+			.amux   = LINE2,
+		},
+	},
+	[SAA7134_BOARD_ECS_TVP3XP_4CB5] = {
+		.name           = "Elitegroup ECS TVP3XP FM1236 Tuner Card (NTSC,FM)",
+		.audio_clock    = 0x187de7,
+		.tuner_type     = TUNER_PHILIPS_NTSC,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.inputs         = {{
+			.name   = name_tv,
+			.vmux   = 1,
+			.amux   = TV,
+			.tv     = 1,
+		},{
+			.name   = name_tv_mono,
+			.vmux   = 1,
+			.amux   = LINE2,
+			.tv     = 1,
+		},{
+			.name   = name_comp1,
+			.vmux   = 3,
+			.amux   = LINE1,
+		},{
+			.name   = name_svideo,
+			.vmux   = 8,
+			.amux   = LINE1,
+		},{
+			.name   = "CVid over SVid",
+			.vmux   = 0,
+			.amux   = LINE1,
+		}},
+		.radio = {
+			.name   = name_radio,
+			.amux   = LINE2,
+		},
+	},
+    [SAA7134_BOARD_ECS_TVP3XP_4CB6] = {
+		/* Barry Scott <barry.scott@onelan.co.uk> */
+		.name		= "Elitegroup ECS TVP3XP FM1246 Tuner Card (PAL,FM)",
+		.audio_clock    = 0x187de7,
+		.tuner_type     = TUNER_PHILIPS_PAL_I,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.inputs         = {{
+			.name   = name_tv,
+			.vmux   = 1,
+			.amux   = TV,
+			.tv     = 1,
+		},{
+			.name   = name_tv_mono,
+			.vmux   = 1,
+			.amux   = LINE2,
+			.tv     = 1,
+		},{
+			.name   = name_comp1,
+			.vmux   = 3,
+			.amux   = LINE1,
+		},{
+			.name   = name_svideo,
+			.vmux   = 8,
+			.amux   = LINE1,
+		},{
+			.name   = "CVid over SVid",
+			.vmux   = 0,
+			.amux   = LINE1,
+		}},
+		.radio = {
+			.name   = name_radio,
+			.amux   = LINE2,
+		},
+	},
+	[SAA7134_BOARD_AVACSSMARTTV] = {
+		/* Roman Pszonczenko <romka@kolos.math.uni.lodz.pl> */
+		.name           = "AVACS SmartTV",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_PAL,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.tv   = 1,
+		},{
+			.name = name_tv_mono,
+			.vmux = 1,
+			.amux = LINE2,
+			.tv   = 1,
+		},{
+			.name = name_comp1,
+			.vmux = 0,
+			.amux = LINE2,
+		},{
+			.name = name_comp2,
+			.vmux = 3,
+			.amux = LINE2,
+		},{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE2,
+		}},
+		.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+			.gpio = 0x200000,
+		},
+	},
+	[SAA7134_BOARD_AVERMEDIA_DVD_EZMAKER] = {
+		/* Michael Smith <msmith@cbnco.com> */
+		.name           = "AVerMedia DVD EZMaker",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_ABSENT,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.inputs         = {{
+			.name = name_comp1,
+			.vmux = 3,
+		},{
+			.name = name_svideo,
+			.vmux = 8,
+		}},
+	},
+	[SAA7134_BOARD_AVERMEDIA_M103] = {
+		/* Massimo Piccioni <dafastidio@libero.it> */
+		.name           = "AVerMedia MiniPCI DVB-T Hybrid M103",
+		.audio_clock    = 0x187de7,
+		.tuner_type     = TUNER_XC2028,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		 .mpeg           = SAA7134_MPEG_DVB,
+		 .inputs         = {{
+			 .name = name_tv,
+			 .vmux = 1,
+			 .amux = TV,
+			 .tv   = 1,
+		 } },
+	},
+	[SAA7134_BOARD_NOVAC_PRIMETV7133] = {
+		/* toshii@netbsd.org */
+		.name           = "Noval Prime TV 7133",
+		.audio_clock    = 0x00200000,
+		.tuner_type     = TUNER_ALPS_TSBH1_NTSC,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.inputs         = {{
+			.name = name_comp1,
+			.vmux = 3,
+		},{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.tv   = 1,
+		},{
+			.name = name_svideo,
+			.vmux = 8,
+		}},
+	},
+	[SAA7134_BOARD_AVERMEDIA_STUDIO_305] = {
+		.name           = "AverMedia AverTV Studio 305",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_FM1256_IH3,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = LINE2,
+			.tv   = 1,
+		},{
+			.name = name_comp1,
+			.vmux = 0,
+			.amux = LINE2,
+		},{
+			.name = name_comp2,
+			.vmux = 3,
+			.amux = LINE2,
+		},{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE2,
+		}},
+		.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+		},
+		.mute = {
+			.name = name_mute,
+			.amux = LINE1,
+		},
+	},
+	[SAA7134_BOARD_AVERMEDIA_STUDIO_505] = {
+		/* Vasiliy Temnikov <vaka@newmail.ru> */
+		.name           = "AverMedia AverTV Studio 505",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.inputs         = { {
+			.name = name_tv,
+			.vmux = 1,
+			.amux = LINE2,
+			.tv   = 1,
+		}, {
+			.name = name_comp1,
+			.vmux = 0,
+			.amux = LINE2,
+		}, {
+			.name = name_comp2,
+			.vmux = 3,
+			.amux = LINE2,
+		},{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE2,
+		} },
+		.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+		},
+		.mute = {
+			.name = name_mute,
+			.amux = LINE1,
+		},
+	},
+	[SAA7134_BOARD_UPMOST_PURPLE_TV] = {
+		.name           = "UPMOST PURPLE TV",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_FM1236_MK3,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 7,
+			.amux = TV,
+			.tv   = 1,
+		},{
+			.name = name_svideo,
+			.vmux = 7,
+			.amux = LINE1,
+		}},
+	},
+	[SAA7134_BOARD_ITEMS_MTV005] = {
+		/* Norman Jonas <normanjonas@arcor.de> */
+		.name           = "Items MuchTV Plus / IT-005",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_PAL,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 3,
+			.amux = TV,
+			.tv   = 1,
+		},{
+			.name   = name_comp1,
+			.vmux   = 1,
+			.amux   = LINE1,
+		},{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		}},
+		.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+		},
+	},
+	[SAA7134_BOARD_CINERGY200] = {
+		.name           = "Terratec Cinergy 200 TV",
+		.audio_clock    = 0x00200000,
+		.tuner_type     = TUNER_PHILIPS_PAL,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = LINE2,
+			.tv   = 1,
+		},{
+			.name = name_comp1,
+			.vmux = 4,
+			.amux = LINE1,
+		},{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		},{
+			.name = name_comp2, /* CVideo over SVideo Connector */
+			.vmux = 0,
+			.amux = LINE1,
+		}},
+		.mute = {
+			.name = name_mute,
+			.amux = LINE2,
+		},
+	},
+	[SAA7134_BOARD_VIDEOMATE_TV_PVR] = {
+		/* Alain St-Denis <alain@topaze.homeip.net> */
+		.name           = "Compro VideoMate TV PVR/FM",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_NTSC_M,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.gpiomask	= 0x808c0080,
+		.inputs         = {{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+			.gpio = 0x00080,
+		},{
+			.name = name_comp1,
+			.vmux = 3,
+			.amux = LINE1,
+			.gpio = 0x00080,
+		},{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = LINE2_LEFT,
+			.tv   = 1,
+			.gpio = 0x00080,
+		}},
+		.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+			.gpio = 0x80000,
+		},
+		.mute = {
+			.name = name_mute,
+			.amux = LINE2,
+			.gpio = 0x40000,
+		},
+	},
+	[SAA7134_BOARD_SABRENT_SBTTVFM] = {
+		/* Michael Rodriguez-Torrent <mrtorrent@asu.edu> */
+		.name           = "Sabrent SBT-TVFM (saa7130)",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_NTSC_M,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.inputs         = {{
+			.name = name_comp1,
+			.vmux = 1,
+			.amux = LINE1,
+		},{
+			.name = name_tv,
+			.vmux = 3,
+			.amux = LINE2,
+			.tv   = 1,
+		},{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		}},
+		.radio = {
+			.name   = name_radio,
+			.amux   = LINE2,
+		},
+	},
+	[SAA7134_BOARD_ZOLID_XPERT_TV7134] = {
+		/* Helge Jensen <helge.jensen@slog.dk> */
+		.name           = ":Zolid Xpert TV7134",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_NTSC,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.inputs         = {{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		},{
+			.name = name_comp1,
+			.vmux = 3,
+			.amux = LINE1,
+		},{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = LINE2,
+			.tv   = 1,
+		}},
+	},
+	[SAA7134_BOARD_EMPIRE_PCI_TV_RADIO_LE] = {
+		/* "Matteo Az" <matte.az@nospam.libero.it> ;-) */
+		.name           = "Empire PCI TV-Radio LE",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_PAL,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.gpiomask       = 0x4000,
+		.inputs         = {{
+			.name = name_tv_mono,
+			.vmux = 1,
+			.amux = LINE2,
+			.gpio = 0x8000,
+			.tv   = 1,
+		},{
+			.name = name_comp1,
+			.vmux = 3,
+			.amux = LINE1,
+			.gpio = 0x8000,
+		},{
+			.name = name_svideo,
+			.vmux = 6,
+			.amux = LINE1,
+			.gpio = 0x8000,
+		}},
+		.radio = {
+			.name = name_radio,
+			.amux = LINE1,
+			.gpio = 0x8000,
+		},
+		.mute = {
+			.name = name_mute,
+			.amux = TV,
+			.gpio =0x8000,
+		}
+	},
+	[SAA7134_BOARD_AVERMEDIA_STUDIO_307] = {
+		/*
+		Nickolay V. Shmyrev <nshmyrev@yandex.ru>
+		Lots of thanks to Andrey Zolotarev <zolotarev_andrey@mail.ru>
+		*/
+		.name           = "Avermedia AVerTV Studio 307",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_FM1256_IH3,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.gpiomask       = 0x03,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.tv   = 1,
+			.gpio = 0x00,
+		},{
+			.name = name_comp,
+			.vmux = 3,
+			.amux = LINE1,
+			.gpio = 0x02,
+		},{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+			.gpio = 0x02,
+		}},
+		.radio = {
+			.name = name_radio,
+			.amux = LINE1,
+			.gpio = 0x01,
+		},
+		.mute  = {
+			.name = name_mute,
+			.amux = LINE1,
+			.gpio = 0x00,
+		},
+	},
+	[SAA7134_BOARD_AVERMEDIA_GO_007_FM] = {
+		.name           = "Avermedia AVerTV GO 007 FM",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_TDA8290,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.gpiomask       = 0x00300003,
+		/* .gpiomask       = 0x8c240003, */
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.tv   = 1,
+			.gpio = 0x01,
+		},{
+			.name = name_comp1,
+			.vmux = 0,
+			.amux = LINE1,
+			.gpio = 0x02,
+		},{
+			.name = name_svideo,
+			.vmux = 6,
+			.amux = LINE1,
+			.gpio = 0x02,
+		}},
+		.radio = {
+			.name = name_radio,
+			.amux = TV,
+			.gpio = 0x00300001,
+		},
+		.mute = {
+			.name = name_mute,
+			.amux = TV,
+			.gpio = 0x01,
+		},
+	},
+	[SAA7134_BOARD_AVERMEDIA_CARDBUS] = {
+		/* Kees.Blom@cwi.nl */
+		.name           = "AVerMedia Cardbus TV/Radio (E500)",
+		.audio_clock    = 0x187de7,
+		.tuner_type     = TUNER_PHILIPS_TDA8290,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.tv   = 1,
+		},{
+			.name = name_comp1,
+			.vmux = 3,
+			.amux = LINE2,
+		},{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		}},
+		.radio = {
+			.name = name_radio,
+			.amux = LINE1,
+		},
+	},
+	[SAA7134_BOARD_AVERMEDIA_CARDBUS_501] = {
+		/* Oldrich Jedlicka <oldium.pro@seznam.cz> */
+		.name           = "AVerMedia Cardbus TV/Radio (E501R)",
+		.audio_clock    = 0x187de7,
+		.tuner_type     = TUNER_ALPS_TSBE5_PAL,
+		.radio_type     = TUNER_TEA5767,
+		.tuner_addr	= 0x61,
+		.radio_addr	= 0x60,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.gpiomask       = 0x08000000,
+		.inputs         = { {
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.tv   = 1,
+			.gpio = 0x08000000,
+		}, {
+			.name = name_comp1,
+			.vmux = 3,
+			.amux = LINE1,
+			.gpio = 0x08000000,
+		}, {
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+			.gpio = 0x08000000,
+		} },
+		.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+			.gpio = 0x00000000,
+		},
+	},
+	[SAA7134_BOARD_CINERGY400_CARDBUS] = {
+		.name           = "Terratec Cinergy 400 mobile",
+		.audio_clock    = 0x187de7,
+		.tuner_type     = TUNER_ALPS_TSBE5_PAL,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.tv   = 1,
+		},{
+			.name = name_tv_mono,
+			.vmux = 1,
+			.amux = LINE2,
+			.tv   = 1,
+		},{
+			.name = name_comp1,
+			.vmux = 3,
+			.amux = LINE1,
+		},{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		}},
+	},
+	[SAA7134_BOARD_CINERGY600_MK3] = {
+		.name           = "Terratec Cinergy 600 TV MK3",
+		.audio_clock    = 0x00200000,
+		.tuner_type	= TUNER_PHILIPS_FM1216ME_MK3,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.rds_addr 	= 0x10,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.tv   = 1,
+		},{
+			.name = name_comp1,
+			.vmux = 4,
+			.amux = LINE1,
+		},{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		},{
+			.name = name_comp2, /* CVideo over SVideo Connector */
+			.vmux = 0,
+			.amux = LINE1,
+		}},
+		.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+		},
+	},
+	[SAA7134_BOARD_VIDEOMATE_GOLD_PLUS] = {
+		/* Dylan Walkden <dylan_walkden@hotmail.com> */
+		.name		= "Compro VideoMate Gold+ Pal",
+		.audio_clock	= 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_PAL,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.gpiomask	= 0x1ce780,
+		.inputs		= {{
+			.name = name_svideo,
+			.vmux = 0,		/* CVideo over SVideo Connector - ok? */
+			.amux = LINE1,
+			.gpio = 0x008080,
+		},{
+			.name = name_comp1,
+			.vmux = 3,
+			.amux = LINE1,
+			.gpio = 0x008080,
+		},{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.tv   = 1,
+			.gpio = 0x008080,
+		}},
+		.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+			.gpio = 0x80000,
+		},
+		.mute = {
+			.name = name_mute,
+			.amux = LINE2,
+			.gpio = 0x0c8000,
+		},
+	},
+	[SAA7134_BOARD_PINNACLE_300I_DVBT_PAL] = {
+		.name           = "Pinnacle PCTV 300i DVB-T + PAL",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_MT2032,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT | TDA9887_INTERCARRIER | TDA9887_PORT2_INACTIVE,
+		.mpeg           = SAA7134_MPEG_DVB,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 3,
+			.amux = TV,
+			.tv   = 1,
+		},{
+			.name = name_comp1,
+			.vmux = 0,
+			.amux = LINE2,
+		},{
+			.name = name_comp2,
+			.vmux = 1,
+			.amux = LINE2,
+		},{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE2,
+		}},
+	},
+	[SAA7134_BOARD_PROVIDEO_PV952] = {
+		/* andreas.kretschmer@web.de */
+		.name		= "ProVideo PV952",
+		.audio_clock	= 0x00187de7,
+		.tuner_type	= TUNER_PHILIPS_FM1216ME_MK3,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.inputs         = {{
+			.name = name_comp1,
+			.vmux = 0,
+			.amux = LINE1,
+		},{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.tv   = 1,
+		},{
+			.name = name_tv_mono,
+			.vmux = 1,
+			.amux = LINE2,
+			.tv   = 1,
+		}},
+		.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+		},
+	},
+	[SAA7134_BOARD_AVERMEDIA_305] = {
+		/* much like the "studio" version but without radio
+		* and another tuner (sirspiritus@yandex.ru) */
+		.name           = "AverMedia AverTV/305",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_FQ1216ME,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = LINE2,
+			.tv   = 1,
+		},{
+			.name = name_comp1,
+			.vmux = 0,
+			.amux = LINE2,
+		},{
+			.name = name_comp2,
+			.vmux = 3,
+			.amux = LINE2,
+		},{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE2,
+		}},
+		.mute = {
+			.name = name_mute,
+			.amux = LINE1,
+		},
+	},
+	[SAA7134_BOARD_FLYDVBTDUO] = {
+		/* LifeView FlyDVB-T DUO */
+		/* "Nico Sabbi <nsabbi@tiscali.it>  Hartmut Hackmann hartmut.hackmann@t-online.de*/
+		.name           = "LifeView FlyDVB-T DUO / MSI TV@nywhere Duo",
+		.audio_clock    = 0x00200000,
+		.tuner_type     = TUNER_PHILIPS_TDA8290,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.gpiomask	= 0x00200000,
+		.mpeg           = SAA7134_MPEG_DVB,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.gpio = 0x200000,	/* GPIO21=High for TV input */
+			.tv   = 1,
+		},{
+			.name = name_comp1,	/* Composite signal on S-Video input */
+			.vmux = 0,
+			.amux = LINE2,
+		},{
+			.name = name_comp2,	/* Composite input */
+			.vmux = 3,
+			.amux = LINE2,
+		},{
+			.name = name_svideo,	/* S-Video signal on S-Video input */
+			.vmux = 8,
+			.amux = LINE2,
+		}},
+		.radio = {
+			.name = name_radio,
+			.amux = TV,
+			.gpio = 0x000000,	/* GPIO21=Low for FM radio antenna */
+		},
+	},
+	[SAA7134_BOARD_PHILIPS_TOUGH] = {
+		.name           = "Philips TOUGH DVB-T reference design",
+		.tuner_type	= TUNER_ABSENT,
+		.audio_clock    = 0x00187de7,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.mpeg           = SAA7134_MPEG_DVB,
+		.inputs = {{
+			.name   = name_comp1,
+			.vmux   = 0,
+			.amux   = LINE1,
+		},{
+			.name   = name_svideo,
+			.vmux   = 8,
+			.amux   = LINE1,
+		}},
+	},
+	[SAA7134_BOARD_AVERMEDIA_307] = {
+		/*
+		Davydov Vladimir <vladimir@iqmedia.com>
+		*/
+		.name           = "Avermedia AVerTV 307",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_FQ1216ME,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.tv   = 1,
+		},{
+			.name = name_comp1,
+			.vmux = 0,
+			.amux = LINE1,
+		},{
+			.name = name_comp2,
+			.vmux = 3,
+			.amux = LINE1,
+		},{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		}},
+	},
+	[SAA7134_BOARD_ADS_INSTANT_TV] = {
+		.name           = "ADS Tech Instant TV (saa7135)",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_TDA8290,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.tv   = 1,
+		},{
+			.name = name_comp1,
+			.vmux = 3,
+			.amux = LINE2,
+		},{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE2,
+		}},
+	},
+	[SAA7134_BOARD_KWORLD_VSTREAM_XPERT] = {
+		.name           = "Kworld/Tevion V-Stream Xpert TV PVR7134",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_PAL_I,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.gpiomask	= 0x0700,
+		.inputs = {{
+			.name   = name_tv,
+			.vmux   = 1,
+			.amux   = TV,
+			.tv     = 1,
+			.gpio   = 0x000,
+		},{
+			.name   = name_comp1,
+			.vmux   = 3,
+			.amux   = LINE1,
+			.gpio   = 0x200,		/* gpio by DScaler */
+		},{
+			.name   = name_svideo,
+			.vmux   = 0,
+			.amux   = LINE1,
+			.gpio   = 0x200,
+		}},
+		.radio = {
+			.name   = name_radio,
+			.amux   = LINE1,
+			.gpio   = 0x100,
+		},
+		.mute  = {
+			.name = name_mute,
+			.amux = TV,
+			.gpio = 0x000,
+		},
+	},
+	[SAA7134_BOARD_FLYDVBT_DUO_CARDBUS] = {
+		.name		= "LifeView/Typhoon/Genius FlyDVB-T Duo Cardbus",
+		.audio_clock    = 0x00200000,
+		.tuner_type     = TUNER_PHILIPS_TDA8290,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.mpeg           = SAA7134_MPEG_DVB,
+		.gpiomask	= 0x00200000,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.gpio = 0x200000,	/* GPIO21=High for TV input */
+			.tv   = 1,
+		},{
+			.name = name_svideo,	/* S-Video signal on S-Video input */
+			.vmux = 8,
+			.amux = LINE2,
+		},{
+			.name = name_comp1,	/* Composite signal on S-Video input */
+			.vmux = 0,
+			.amux = LINE2,
+		},{
+			.name = name_comp2,	/* Composite input */
+			.vmux = 3,
+			.amux = LINE2,
+		}},
+		.radio = {
+			.name = name_radio,
+			.amux = TV,
+			.gpio = 0x000000,	/* GPIO21=Low for FM radio antenna */
+		},
+	},
+	[SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII] = {
+		.name           = "Compro VideoMate TV Gold+II",
+		.audio_clock    = 0x002187de7,
+		.tuner_type     = TUNER_LG_PAL_NEW_TAPC,
+		.radio_type     = TUNER_TEA5767,
+		.tuner_addr     = 0x63,
+		.radio_addr     = 0x60,
+		.gpiomask       = 0x8c1880,
+		.inputs         = {{
+			.name = name_svideo,
+			.vmux = 0,
+			.amux = LINE1,
+			.gpio = 0x800800,
+		},{
+			.name = name_comp1,
+			.vmux = 3,
+			.amux = LINE1,
+			.gpio = 0x801000,
+		},{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.tv   = 1,
+			.gpio = 0x800000,
+		}},
+		.radio = {
+			.name = name_radio,
+			.amux = TV,
+			.gpio = 0x880000,
+		},
+		.mute = {
+			.name = name_mute,
+			.amux = LINE2,
+			.gpio = 0x840000,
+		},
+	},
+	[SAA7134_BOARD_KWORLD_XPERT] = {
+		/*
+		FIXME:
+		- Remote control doesn't initialize properly.
+		- Audio volume starts muted,
+		then gradually increases after channel change.
+		- Overlay scaling problems (application error?)
+		- Composite S-Video untested.
+		From: Konrad Rzepecki <hannibal@megapolis.pl>
+		*/
+		.name           = "Kworld Xpert TV PVR7134",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_TENA_9533_DI,
+		.radio_type     = TUNER_TEA5767,
+		.tuner_addr	= 0x61,
+		.radio_addr	= 0x60,
+		.gpiomask	= 0x0700,
+		.inputs = {{
+			.name   = name_tv,
+			.vmux   = 1,
+			.amux   = TV,
+			.tv     = 1,
+			.gpio   = 0x000,
+		},{
+			.name   = name_comp1,
+			.vmux   = 3,
+			.amux   = LINE1,
+			.gpio   = 0x200,		/* gpio by DScaler */
+		},{
+			.name   = name_svideo,
+			.vmux   = 0,
+			.amux   = LINE1,
+			.gpio   = 0x200,
+		}},
+		.radio = {
+			.name   = name_radio,
+			.amux   = LINE1,
+			.gpio   = 0x100,
+		},
+		.mute = {
+			.name = name_mute,
+			.amux = TV,
+			.gpio = 0x000,
+		},
+	},
+	[SAA7134_BOARD_FLYTV_DIGIMATRIX] = {
+		.name		= "FlyTV mini Asus Digimatrix",
+		.audio_clock	= 0x00200000,
+		.tuner_type	= TUNER_LG_TALN,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.tv   = 1,
+		},{
+			.name = name_tv_mono,
+			.vmux = 1,
+			.amux = LINE2,
+			.tv   = 1,
+		},{
+			.name = name_comp1,
+			.vmux = 0,
+			.amux = LINE2,
+		},{
+			.name = name_comp2,
+			.vmux = 3,
+			.amux = LINE2,
+		},{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE2,
+		}},
+		.radio = {
+			.name = name_radio,		/* radio unconfirmed */
+			.amux = LINE2,
+		},
+	},
+	[SAA7134_BOARD_KWORLD_TERMINATOR] = {
+		/* Kworld V-Stream Studio TV Terminator */
+		/* "James Webb <jrwebb@qwest.net> */
+		.name           = "V-Stream Studio TV Terminator",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_TDA8290,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.gpiomask       = 1 << 21,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.gpio = 0x0000000,
+			.tv   = 1,
+		},{
+			.name = name_comp1,     /* Composite input */
+			.vmux = 3,
+			.amux = LINE2,
+			.gpio = 0x0000000,
+		},{
+			.name = name_svideo,    /* S-Video input */
+			.vmux = 8,
+			.amux = LINE2,
+			.gpio = 0x0000000,
+		}},
+		.radio = {
+			.name = name_radio,
+			.amux = TV,
+			.gpio = 0x0200000,
+		},
+	},
+	[SAA7134_BOARD_YUAN_TUN900] = {
+		/* FIXME:
+		 * S-Video and composite sources untested.
+		 * Radio not working.
+		 * Remote control not yet implemented.
+		 * From : codemaster@webgeeks.be */
+		.name           = "Yuan TUN-900 (saa7135)",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_TDA8290,
+		.radio_type     = UNSET,
+		.tuner_addr= ADDR_UNSET,
+		.radio_addr= ADDR_UNSET,
+		.gpiomask       = 0x00010003,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.tv   = 1,
+			.gpio = 0x01,
+		},{
+			.name = name_comp1,
+			.vmux = 0,
+			.amux = LINE2,
+			.gpio = 0x02,
+		},{
+			.name = name_svideo,
+			.vmux = 6,
+			.amux = LINE2,
+			.gpio = 0x02,
+		}},
+		.radio = {
+			.name = name_radio,
+			.amux = LINE1,
+			.gpio = 0x00010003,
+		},
+		.mute = {
+			.name = name_mute,
+			.amux = TV,
+			.gpio = 0x01,
+		},
+	},
+	[SAA7134_BOARD_BEHOLD_409FM] = {
+		/* <http://tuner.beholder.ru>, Sergey <skiv@orel.ru> */
+		/*       Beholder Intl. Ltd. 2008      */
+		/*Dmitry Belimov <d.belimov@gmail.com> */
+		.name           = "Beholder BeholdTV 409 FM",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.gpiomask       = 0x00008000,
+		.inputs         = {{
+			  .name = name_tv,
+			  .vmux = 3,
+			  .amux = TV,
+			  .tv   = 1,
+		},{
+			  .name = name_comp1,
+			  .vmux = 1,
+			  .amux = LINE1,
+		},{
+			  .name = name_svideo,
+			  .vmux = 8,
+			  .amux = LINE1,
+		}},
+		.radio = {
+			  .name = name_radio,
+			  .amux = LINE2,
+		},
+	},
+	[SAA7134_BOARD_GOTVIEW_7135] = {
+		/* Mike Baikov <mike@baikov.com> */
+		/* Andrey Cvetcov <ays14@yandex.ru> */
+		.name            = "GoTView 7135 PCI",
+		.audio_clock     = 0x00187de7,
+		.tuner_type      = TUNER_PHILIPS_FM1216ME_MK3,
+		.radio_type      = UNSET,
+		.tuner_addr      = ADDR_UNSET,
+		.radio_addr      = ADDR_UNSET,
+		.tda9887_conf    = TDA9887_PRESENT,
+		.gpiomask        = 0x00200003,
+		.inputs          = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.tv   = 1,
+			.gpio = 0x00200003,
+		},{
+			.name = name_tv_mono,
+			.vmux = 1,
+			.amux = LINE2,
+			.gpio = 0x00200003,
+		},{
+			.name = name_comp1,
+			.vmux = 3,
+			.amux = LINE1,
+			.gpio = 0x00200003,
+		},{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+			.gpio = 0x00200003,
+		}},
+		.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+			.gpio = 0x00200003,
+		},
+		.mute = {
+			.name = name_mute,
+			.amux = TV,
+			.gpio = 0x00200003,
+		},
+	},
+	[SAA7134_BOARD_PHILIPS_EUROPA] = {
+		.name           = "Philips EUROPA V3 reference design",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_TD1316,
+		.radio_type     = UNSET,
+		.tuner_addr	= 0x61,
+		.radio_addr	= ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE,
+		.mpeg           = SAA7134_MPEG_DVB,
+		.inputs = {{
+			.name   = name_tv,
+			.vmux   = 3,
+			.amux   = TV,
+			.tv     = 1,
+		},{
+			.name   = name_comp1,
+			.vmux   = 0,
+			.amux   = LINE2,
+		},{
+			.name   = name_svideo,
+			.vmux   = 8,
+			.amux   = LINE2,
+		}},
+	},
+	[SAA7134_BOARD_VIDEOMATE_DVBT_300] = {
+		.name           = "Compro Videomate DVB-T300",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_TD1316,
+		.radio_type     = UNSET,
+		.tuner_addr	= 0x61,
+		.radio_addr	= ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE,
+		.mpeg           = SAA7134_MPEG_DVB,
+		.inputs = {{
+			.name   = name_tv,
+			.vmux   = 3,
+			.amux   = TV,
+			.tv     = 1,
+		},{
+			.name   = name_comp1,
+			.vmux   = 1,
+			.amux   = LINE2,
+		},{
+			.name   = name_svideo,
+			.vmux   = 8,
+			.amux   = LINE2,
+		}},
+	},
+	[SAA7134_BOARD_VIDEOMATE_DVBT_200] = {
+		.name           = "Compro Videomate DVB-T200",
+		.tuner_type	= TUNER_ABSENT,
+		.audio_clock    = 0x00187de7,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.mpeg           = SAA7134_MPEG_DVB,
+		.inputs = {{
+			.name   = name_comp1,
+			.vmux   = 0,
+			.amux   = LINE1,
+		},{
+			.name   = name_svideo,
+			.vmux   = 8,
+			.amux   = LINE1,
+		}},
+	},
+	[SAA7134_BOARD_RTD_VFG7350] = {
+		.name		= "RTD Embedded Technologies VFG7350",
+		.audio_clock	= 0x00200000,
+		.tuner_type	= TUNER_ABSENT,
+		.radio_type	= UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.empress_addr 	= 0x21,
+		.inputs		= {{
+			.name   = "Composite 0",
+			.vmux   = 0,
+			.amux   = LINE1,
+		},{
+			.name   = "Composite 1",
+			.vmux   = 1,
+			.amux   = LINE2,
+		},{
+			.name   = "Composite 2",
+			.vmux   = 2,
+			.amux   = LINE1,
+		},{
+			.name   = "Composite 3",
+			.vmux   = 3,
+			.amux   = LINE2,
+		},{
+			.name   = "S-Video 0",
+			.vmux   = 8,
+			.amux   = LINE1,
+		},{
+			.name   = "S-Video 1",
+			.vmux   = 9,
+			.amux   = LINE2,
+		}},
+		.mpeg           = SAA7134_MPEG_EMPRESS,
+		.video_out      = CCIR656,
+		.vid_port_opts  = ( SET_T_CODE_POLARITY_NON_INVERTED |
+				    SET_CLOCK_NOT_DELAYED |
+				    SET_CLOCK_INVERTED |
+				    SET_VSYNC_OFF ),
+	},
+	[SAA7134_BOARD_RTD_VFG7330] = {
+		.name		= "RTD Embedded Technologies VFG7330",
+		.audio_clock	= 0x00200000,
+		.tuner_type	= TUNER_ABSENT,
+		.radio_type	= UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.inputs		= {{
+			.name   = "Composite 0",
+			.vmux   = 0,
+			.amux   = LINE1,
+		},{
+			.name   = "Composite 1",
+			.vmux   = 1,
+			.amux   = LINE2,
+		},{
+			.name   = "Composite 2",
+			.vmux   = 2,
+			.amux   = LINE1,
+		},{
+			.name   = "Composite 3",
+			.vmux   = 3,
+			.amux   = LINE2,
+		},{
+			.name   = "S-Video 0",
+			.vmux   = 8,
+			.amux   = LINE1,
+		},{
+			.name   = "S-Video 1",
+			.vmux   = 9,
+			.amux   = LINE2,
+		}},
+	},
+	[SAA7134_BOARD_FLYTVPLATINUM_MINI2] = {
+		.name           = "LifeView FlyTV Platinum Mini2",
+		.audio_clock    = 0x00200000,
+		.tuner_type     = TUNER_PHILIPS_TDA8290,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.tv   = 1,
+		},{
+			.name = name_comp1,     /* Composite signal on S-Video input */
+			.vmux = 0,
+			.amux = LINE2,
+		},{
+			.name = name_comp2,	/* Composite input */
+			.vmux = 3,
+			.amux = LINE2,
+		},{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE2,
+		}},
+	},
+	[SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180] = {
+		/* Michael Krufky <mkrufky@m1k.net>
+		 * Uses Alps Electric TDHU2, containing NXT2004 ATSC Decoder
+		 * AFAIK, there is no analog demod, thus,
+		 * no support for analog television.
+		 */
+		.name           = "AVerMedia AVerTVHD MCE A180",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_ABSENT,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.mpeg           = SAA7134_MPEG_DVB,
+		.inputs         = {{
+			.name = name_comp1,
+			.vmux = 3,
+			.amux = LINE2,
+		},{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE2,
+		}},
+	},
+	[SAA7134_BOARD_MONSTERTV_MOBILE] = {
+		.name           = "SKNet MonsterTV Mobile",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_TDA8290,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+
+		.inputs         = {{
+			  .name = name_tv,
+			  .vmux = 1,
+			  .amux = TV,
+			  .tv   = 1,
+		},{
+			  .name = name_comp1,
+			  .vmux = 3,
+			  .amux = LINE1,
+		},{
+			  .name = name_svideo,
+			  .vmux = 6,
+			  .amux = LINE1,
+		}},
+	},
+	[SAA7134_BOARD_PINNACLE_PCTV_110i] = {
+	       .name           = "Pinnacle PCTV 40i/50i/110i (saa7133)",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_TDA8290,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.gpiomask       = 0x080200000,
+		.inputs         = { {
+			.name = name_tv,
+			.vmux = 4,
+			.amux = TV,
+			.tv   = 1,
+		}, {
+			.name = name_comp1,
+			.vmux = 1,
+			.amux = LINE2,
+		}, {
+			.name = name_comp2,
+			.vmux = 0,
+			.amux = LINE2,
+		}, {
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE2,
+		} },
+		.radio = {
+			.name = name_radio,
+			.amux = TV,
+			.gpio = 0x0200000,
+		},
+	},
+	[SAA7134_BOARD_ASUSTeK_P7131_DUAL] = {
+		.name           = "ASUSTeK P7131 Dual",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_TDA8290,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.gpiomask	= 1 << 21,
+		.mpeg           = SAA7134_MPEG_DVB,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.tv   = 1,
+			.gpio = 0x0000000,
+		},{
+			.name = name_comp1,
+			.vmux = 3,
+			.amux = LINE2,
+			.gpio = 0x0200000,
+		},{
+			.name = name_comp2,
+			.vmux = 0,
+			.amux = LINE2,
+			.gpio = 0x0200000,
+		},{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE2,
+			.gpio = 0x0200000,
+		}},
+		.radio = {
+			.name = name_radio,
+			.amux = TV,
+			.gpio = 0x0200000,
+		},
+	},
+	[SAA7134_BOARD_SEDNA_PC_TV_CARDBUS] = {
+		/* Paul Tom Zalac <pzalac@gmail.com> */
+		/* Pavel Mihaylov <bin@bash.info> */
+		.name           = "Sedna/MuchTV PC TV Cardbus TV/Radio (ITO25 Rev:2B)",
+				/* Sedna/MuchTV (OEM) Cardbus TV Tuner */
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_TDA8290,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.gpiomask       = 0xe880c0,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 3,
+			.amux = TV,
+			.tv   = 1,
+		},{
+			.name = name_comp1,
+			.vmux = 1,
+			.amux = LINE1,
+		},{
+			.name = name_svideo,
+			.vmux = 6,
+			.amux = LINE1,
+		}},
+		.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+		},
+	},
+	[SAA7134_BOARD_ASUSTEK_DIGIMATRIX_TV] = {
+		/* "Cyril Lacoux (Yack)" <clacoux@ifeelgood.org> */
+		.name           = "ASUS Digimatrix TV",
+		.audio_clock    = 0x00200000,
+		.tuner_type     = TUNER_PHILIPS_FQ1216ME,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.tv   = 1,
+		},{
+			.name = name_comp1,
+			.vmux = 3,
+			.amux = LINE1,
+		},{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		}},
+	},
+	[SAA7134_BOARD_PHILIPS_TIGER] = {
+		.name           = "Philips Tiger reference design",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_TDA8290,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.tuner_config   = 0,
+		.mpeg           = SAA7134_MPEG_DVB,
+		.gpiomask       = 0x0200000,
+		.inputs = {{
+			.name   = name_tv,
+			.vmux   = 1,
+			.amux   = TV,
+			.tv     = 1,
+		},{
+			.name   = name_comp1,
+			.vmux   = 3,
+			.amux   = LINE1,
+		},{
+			.name   = name_svideo,
+			.vmux   = 8,
+			.amux   = LINE1,
+		}},
+		.radio = {
+			.name   = name_radio,
+			.amux   = TV,
+			.gpio   = 0x0200000,
+		},
+	},
+	[SAA7134_BOARD_MSI_TVATANYWHERE_PLUS] = {
+		.name           = "MSI TV@Anywhere plus",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_TDA8290,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.gpiomask       = 1 << 21,
+		.inputs = {{
+			.name   = name_tv,
+			.vmux   = 1,
+			.amux   = TV,
+			.tv     = 1,
+		},{
+			.name   = name_comp1,
+			.vmux   = 3,
+			.amux   = LINE2,	/* unconfirmed, taken from Philips driver */
+		},{
+			.name   = name_comp2,
+			.vmux   = 0,		/* untested, Composite over S-Video */
+			.amux   = LINE2,
+		},{
+			.name   = name_svideo,
+			.vmux   = 8,
+			.amux   = LINE2,
+		}},
+		.radio = {
+			.name   = name_radio,
+			.amux   = TV,
+			.gpio   = 0x0200000,
+		},
+	},
+	[SAA7134_BOARD_CINERGY250PCI] = {
+		/* remote-control does not work. The signal about a
+		   key press comes in via gpio, but the key code
+		   doesn't. Neither does it have an i2c remote control
+		   interface. */
+		.name           = "Terratec Cinergy 250 PCI TV",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_TDA8290,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.gpiomask       = 0x80200000,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.tv   = 1,
+		},{
+			.name = name_svideo,  /* NOT tested */
+			.vmux = 8,
+			.amux = LINE1,
+		}},
+		.radio = {
+			.name   = name_radio,
+			.amux   = TV,
+			.gpio   = 0x0200000,
+		},
+	},
+	[SAA7134_BOARD_FLYDVB_TRIO] = {
+		/* LifeView LR319 FlyDVB Trio */
+		/* Peter Missel <peter.missel@onlinehome.de> */
+		.name           = "LifeView FlyDVB Trio",
+		.audio_clock    = 0x00200000,
+		.tuner_type     = TUNER_PHILIPS_TDA8290,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.gpiomask	= 0x00200000,
+		.mpeg           = SAA7134_MPEG_DVB,
+		.inputs         = {{
+			.name = name_tv,	/* Analog broadcast/cable TV */
+			.vmux = 1,
+			.amux = TV,
+			.gpio = 0x200000,	/* GPIO21=High for TV input */
+			.tv   = 1,
+		},{
+			.name = name_svideo,	/* S-Video signal on S-Video input */
+			.vmux = 8,
+			.amux = LINE2,
+		},{
+			.name = name_comp1,	/* Composite signal on S-Video input */
+			.vmux = 0,
+			.amux = LINE2,
+		},{
+			.name = name_comp2,	/* Composite input */
+			.vmux = 3,
+			.amux = LINE2,
+		}},
+		.radio = {
+			.name = name_radio,
+			.amux = TV,
+			.gpio = 0x000000,	/* GPIO21=Low for FM radio antenna */
+		},
+	},
+	[SAA7134_BOARD_AVERMEDIA_777] = {
+		.name           = "AverTV DVB-T 777",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_ABSENT,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.mpeg           = SAA7134_MPEG_DVB,
+		.inputs = {{
+			.name   = name_comp1,
+			.vmux   = 1,
+			.amux   = LINE1,
+		},{
+			.name   = name_svideo,
+			.vmux   = 8,
+			.amux   = LINE1,
+		}},
+	},
+	[SAA7134_BOARD_FLYDVBT_LR301] = {
+		/* LifeView FlyDVB-T */
+		/* Giampiero Giancipoli <gianci@libero.it> */
+		.name           = "LifeView FlyDVB-T / Genius VideoWonder DVB-T",
+		.audio_clock    = 0x00200000,
+		.tuner_type     = TUNER_ABSENT,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.mpeg           = SAA7134_MPEG_DVB,
+		.inputs         = {{
+			.name = name_comp1,	/* Composite input */
+			.vmux = 3,
+			.amux = LINE2,
+		},{
+			.name = name_svideo,	/* S-Video signal on S-Video input */
+			.vmux = 8,
+			.amux = LINE2,
+		}},
+	},
+	[SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331] = {
+		.name           = "ADS Instant TV Duo Cardbus PTV331",
+		.audio_clock    = 0x00200000,
+		.tuner_type     = TUNER_PHILIPS_TDA8290,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.mpeg           = SAA7134_MPEG_DVB,
+		.gpiomask       = 0x00600000, /* Bit 21 0=Radio, Bit 22 0=TV */
+		.inputs = {{
+			.name   = name_tv,
+			.vmux   = 1,
+			.amux   = TV,
+			.tv     = 1,
+			.gpio   = 0x00200000,
+		}},
+	},
+	[SAA7134_BOARD_TEVION_DVBT_220RF] = {
+		.name           = "Tevion/KWorld DVB-T 220RF",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_TDA8290,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.mpeg           = SAA7134_MPEG_DVB,
+		.gpiomask       = 1 << 21,
+		.inputs = {{
+			.name   = name_tv,
+			.vmux   = 1,
+			.amux   = TV,
+			.tv     = 1,
+		},{
+			.name   = name_comp1,
+			.vmux   = 3,
+			.amux   = LINE1,
+		},{
+			.name   = name_comp2,
+			.vmux   = 0,
+			.amux   = LINE1,
+		},{
+			.name   = name_svideo,
+			.vmux   = 8,
+			.amux   = LINE1,
+		}},
+		.radio = {
+			.name   = name_radio,
+			.amux   = TV,
+			.gpio   = 0x0200000,
+		},
+	},
+	[SAA7134_BOARD_KWORLD_DVBT_210] = {
+		.name           = "KWorld DVB-T 210",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_TDA8290,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.mpeg           = SAA7134_MPEG_DVB,
+		.gpiomask       = 1 << 21,
+		.inputs = {{
+			.name   = name_tv,
+			.vmux   = 1,
+			.amux   = TV,
+			.tv     = 1,
+		},{
+			.name   = name_comp1,
+			.vmux   = 3,
+			.amux   = LINE1,
+		},{
+			.name   = name_svideo,
+			.vmux   = 8,
+			.amux   = LINE1,
+		}},
+		.radio = {
+			.name   = name_radio,
+			.amux   = TV,
+			.gpio   = 0x0200000,
+		},
+	},
+	[SAA7134_BOARD_KWORLD_ATSC110] = {
+		.name           = "Kworld ATSC110/115",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_TUV1236D,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.mpeg           = SAA7134_MPEG_DVB,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.tv   = 1,
+		},{
+			.name = name_comp1,
+			.vmux = 3,
+			.amux = LINE2,
+		},{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE2,
+		}},
+	},
+	[SAA7134_BOARD_AVERMEDIA_A169_B] = {
+		/* AVerMedia A169  */
+		/* Rickard Osser <ricky@osser.se>  */
+		/* This card has two saa7134 chips on it,
+		   but only one of them is currently working. */
+		.name		= "AVerMedia A169 B",
+		.audio_clock    = 0x02187de7,
+		.tuner_type	= TUNER_LG_TALN,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.gpiomask       = 0x0a60000,
+	},
+	[SAA7134_BOARD_AVERMEDIA_A169_B1] = {
+		/* AVerMedia A169 */
+		/* Rickard Osser <ricky@osser.se> */
+		.name		= "AVerMedia A169 B1",
+		.audio_clock    = 0x02187de7,
+		.tuner_type	= TUNER_LG_TALN,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.gpiomask       = 0xca60000,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 4,
+			.amux = TV,
+			.tv   = 1,
+			.gpio = 0x04a61000,
+		},{
+			.name = name_comp2,  /*  Composite SVIDEO (B/W if signal is carried with SVIDEO) */
+			.vmux = 1,
+			.amux = LINE2,
+		},{
+			.name = name_svideo,
+			.vmux = 9,           /* 9 is correct as S-VIDEO1 according to a169.inf! */
+			.amux = LINE1,
+		}},
+	},
+	[SAA7134_BOARD_MD7134_BRIDGE_2] = {
+		/* The second saa7134 on this card only serves as DVB-S host bridge */
+		.name           = "Medion 7134 Bridge #2",
+		.audio_clock    = 0x00187de7,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.mpeg           = SAA7134_MPEG_DVB,
+	},
+	[SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS] = {
+		.name		= "LifeView FlyDVB-T Hybrid Cardbus/MSI TV @nywhere A/D NB",
+		.audio_clock    = 0x00200000,
+		.tuner_type     = TUNER_PHILIPS_TDA8290,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.mpeg           = SAA7134_MPEG_DVB,
+		.gpiomask       = 0x00600000, /* Bit 21 0=Radio, Bit 22 0=TV */
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.gpio = 0x200000,	/* GPIO21=High for TV input */
+			.tv   = 1,
+		},{
+			.name = name_svideo,	/* S-Video signal on S-Video input */
+			.vmux = 8,
+			.amux = LINE2,
+		},{
+			.name = name_comp1,	/* Composite signal on S-Video input */
+			.vmux = 0,
+			.amux = LINE2,
+		},{
+			.name = name_comp2,	/* Composite input */
+			.vmux = 3,
+			.amux = LINE2,
+		}},
+		.radio = {
+			.name = name_radio,
+			.amux = TV,
+			.gpio = 0x000000,	/* GPIO21=Low for FM radio antenna */
+		},
+	},
+	[SAA7134_BOARD_FLYVIDEO3000_NTSC] = {
+		/* "Zac Bowling" <zac@zacbowling.com> */
+		.name           = "LifeView FlyVIDEO3000 (NTSC)",
+		.audio_clock    = 0x00200000,
+		.tuner_type     = TUNER_PHILIPS_NTSC,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+
+		.gpiomask       = 0xe000,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.gpio = 0x8000,
+			.tv   = 1,
+		},{
+			.name = name_tv_mono,
+			.vmux = 1,
+			.amux = LINE2,
+			.gpio = 0x0000,
+			.tv   = 1,
+		},{
+			.name = name_comp1,
+			.vmux = 0,
+			.amux = LINE2,
+			.gpio = 0x4000,
+		},{
+			.name = name_comp2,
+			.vmux = 3,
+			.amux = LINE2,
+			.gpio = 0x4000,
+		},{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE2,
+			.gpio = 0x4000,
+		}},
+		.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+			.gpio = 0x2000,
+		},
+			.mute = {
+			.name = name_mute,
+			.amux = TV,
+			.gpio = 0x8000,
+		},
+	},
+	[SAA7134_BOARD_MEDION_MD8800_QUADRO] = {
+		.name           = "Medion Md8800 Quadro",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_TDA8290,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.mpeg           = SAA7134_MPEG_DVB,
+		.inputs = {{
+			.name   = name_tv,
+			.vmux   = 1,
+			.amux   = TV,
+			.tv     = 1,
+		},{
+			.name   = name_comp1,
+			.vmux   = 0,
+			.amux   = LINE1,
+		},{
+			.name   = name_svideo,
+			.vmux   = 8,
+			.amux   = LINE1,
+		}},
+	},
+	[SAA7134_BOARD_FLYDVBS_LR300] = {
+		/* LifeView FlyDVB-s */
+		/* Igor M. Liplianin <liplianin@tut.by> */
+		.name           = "LifeView FlyDVB-S /Acorp TV134DS",
+		.audio_clock    = 0x00200000,
+		.tuner_type     = TUNER_ABSENT,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.mpeg           = SAA7134_MPEG_DVB,
+		.inputs         = {{
+			.name = name_comp1,	/* Composite input */
+			.vmux = 3,
+			.amux = LINE1,
+		},{
+			.name = name_svideo,	/* S-Video signal on S-Video input */
+			.vmux = 8,
+			.amux = LINE1,
+		}},
+	},
+	[SAA7134_BOARD_PROTEUS_2309] = {
+		.name           = "Proteus Pro 2309",
+		.audio_clock    = 0x00187de7,
+		.tuner_type	= TUNER_PHILIPS_FM1216ME_MK3,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = LINE2,
+			.tv   = 1,
+		},{
+			.name = name_comp1,
+			.vmux = 0,
+			.amux = LINE2,
+		},{
+			.name = name_comp2,
+			.vmux = 3,
+			.amux = LINE2,
+		},{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE2,
+		}},
+		.mute = {
+			.name = name_mute,
+			.amux = LINE1,
+		},
+	},
+	[SAA7134_BOARD_AVERMEDIA_A16AR] = {
+		/* Petr Baudis <pasky@ucw.cz> */
+		.name           = "AVerMedia TV Hybrid A16AR",
+		.audio_clock    = 0x187de7,
+		.tuner_type     = TUNER_PHILIPS_TD1316, /* untested */
+		.radio_type     = TUNER_TEA5767, /* untested */
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = 0x60,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.mpeg           = SAA7134_MPEG_DVB,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.tv   = 1,
+		},{
+			.name = name_comp1,
+			.vmux = 3,
+			.amux = LINE2,
+		},{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		}},
+		.radio = {
+			.name = name_radio,
+			.amux = LINE1,
+		},
+	},
+	[SAA7134_BOARD_ASUS_EUROPA2_HYBRID] = {
+		.name           = "Asus Europa2 OEM",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_FMD1216ME_MK3,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT| TDA9887_PORT1_ACTIVE | TDA9887_PORT2_ACTIVE,
+		.mpeg           = SAA7134_MPEG_DVB,
+		.inputs = {{
+			.name   = name_tv,
+			.vmux   = 3,
+			.amux   = TV,
+			.tv     = 1,
+		},{
+			.name   = name_comp1,
+			.vmux   = 4,
+			.amux   = LINE2,
+		},{
+			.name   = name_svideo,
+			.vmux   = 8,
+			.amux   = LINE2,
+		}},
+		.radio = {
+			.name   = name_radio,
+			.amux   = LINE1,
+		},
+	},
+	[SAA7134_BOARD_PINNACLE_PCTV_310i] = {
+		.name           = "Pinnacle PCTV 310i",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_TDA8290,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.tuner_config   = 1,
+		.mpeg           = SAA7134_MPEG_DVB,
+		.gpiomask       = 0x000200000,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 4,
+			.amux = TV,
+			.tv   = 1,
+		},{
+			.name = name_comp1,
+			.vmux = 1,
+			.amux = LINE2,
+		},{
+			.name = name_comp2,
+			.vmux = 0,
+			.amux = LINE2,
+		},{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE2,
+		}},
+		.radio = {
+			.name = name_radio,
+			.amux   = TV,
+			.gpio   = 0x0200000,
+		},
+	},
+	[SAA7134_BOARD_AVERMEDIA_STUDIO_507] = {
+		/* Mikhail Fedotov <mo_fedotov@mail.ru> */
+		.name           = "Avermedia AVerTV Studio 507",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_FM1256_IH3,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.gpiomask       = 0x03,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.tv   = 1,
+			.gpio = 0x00,
+		},{
+			.name = name_comp1,
+			.vmux = 0,
+			.amux = LINE2,
+			.gpio = 0x00,
+		},{
+			.name = name_comp2,
+			.vmux = 3,
+			.amux = LINE2,
+			.gpio = 0x00,
+		},{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE2,
+			.gpio = 0x00,
+		}},
+		.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+			.gpio = 0x01,
+		},
+		.mute  = {
+			.name = name_mute,
+			.amux = LINE1,
+			.gpio = 0x00,
+		},
+	},
+	[SAA7134_BOARD_VIDEOMATE_DVBT_200A] = {
+		/* Francis Barber <fedora@barber-family.id.au> */
+		.name           = "Compro Videomate DVB-T200A",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_ABSENT,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE,
+		.mpeg           = SAA7134_MPEG_DVB,
+		.inputs = {{
+			.name   = name_tv,
+			.vmux   = 3,
+			.amux   = TV,
+			.tv     = 1,
+		},{
+			.name   = name_comp1,
+			.vmux   = 1,
+			.amux   = LINE2,
+		},{
+			.name   = name_svideo,
+			.vmux   = 8,
+			.amux   = LINE2,
+		}},
+	},
+	[SAA7134_BOARD_HAUPPAUGE_HVR1110] = {
+		/* Thomas Genty <tomlohave@gmail.com> */
+		/* David Bentham <db260179@hotmail.com> */
+		.name           = "Hauppauge WinTV-HVR1110 DVB-T/Hybrid",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_TDA8290,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.tuner_config   = 1,
+		.mpeg           = SAA7134_MPEG_DVB,
+		.gpiomask       = 0x0200100,
+		.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 = 0x0200100,
+		},
+	},
+	[SAA7134_BOARD_HAUPPAUGE_HVR1150] = {
+		.name           = "Hauppauge WinTV-HVR1150 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,
+		.ts_force_val   = 1,
+		.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_HVR1120] = {
+		.name           = "Hauppauge WinTV-HVR1120 DVB-T/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_CINERGY_HT_PCMCIA] = {
+		.name           = "Terratec Cinergy HT PCMCIA",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_TDA8290,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.mpeg           = SAA7134_MPEG_DVB,
+		.inputs = {{
+			.name   = name_tv,
+			.vmux   = 1,
+			.amux   = TV,
+			.tv     = 1,
+		},{
+			.name   = name_comp1,
+			.vmux   = 0,
+			.amux   = LINE1,
+		},{
+			.name   = name_svideo,
+			.vmux   = 6,
+			.amux   = LINE1,
+		}},
+	},
+	[SAA7134_BOARD_ENCORE_ENLTV] = {
+	/* Steven Walter <stevenrwalter@gmail.com>
+	   Juan Pablo Sormani <sorman@gmail.com> */
+		.name           = "Encore ENLTV",
+		.audio_clock    = 0x00200000,
+		.tuner_type     = TUNER_TNF_5335MF,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = 3,
+			.tv   = 1,
+		},{
+			.name = name_tv_mono,
+			.vmux = 7,
+			.amux = 4,
+			.tv   = 1,
+		},{
+			.name = name_comp1,
+			.vmux = 3,
+			.amux = 2,
+		},{
+			.name = name_svideo,
+			.vmux = 0,
+			.amux = 2,
+		}},
+		.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+/*			.gpio = 0x00300001,*/
+			.gpio = 0x20000,
+
+		},
+		.mute = {
+			.name = name_mute,
+			.amux = 0,
+		},
+	},
+	[SAA7134_BOARD_ENCORE_ENLTV_FM] = {
+  /*	Juan Pablo Sormani <sorman@gmail.com> */
+		.name           = "Encore ENLTV-FM",
+		.audio_clock    = 0x00200000,
+		.tuner_type     = TUNER_PHILIPS_FCV1236D,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = 3,
+			.tv   = 1,
+		},{
+			.name = name_tv_mono,
+			.vmux = 7,
+			.amux = 4,
+			.tv   = 1,
+		},{
+			.name = name_comp1,
+			.vmux = 3,
+			.amux = 2,
+		},{
+			.name = name_svideo,
+			.vmux = 0,
+			.amux = 2,
+		}},
+		.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+			.gpio = 0x20000,
+
+		},
+		.mute = {
+			.name = name_mute,
+			.amux = 0,
+		},
+	},
+	[SAA7134_BOARD_ENCORE_ENLTV_FM53] = {
+		.name           = "Encore ENLTV-FM v5.3",
+		.audio_clock    = 0x00200000,
+		.tuner_type     = TUNER_TNF_5335MF,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.gpiomask	= 0x7000,
+		.inputs         = { {
+			.name = name_tv,
+			.vmux = 1,
+			.amux = 1,
+			.tv   = 1,
+			.gpio = 0x50000,
+		}, {
+			.name = name_comp1,
+			.vmux = 3,
+			.amux = 2,
+			.gpio = 0x2000,
+		}, {
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = 2,
+			.gpio = 0x2000,
+		} },
+		.radio = {
+			.name = name_radio,
+			.vmux = 1,
+			.amux = 1,
+		},
+		.mute = {
+			.name = name_mute,
+			.gpio = 0xf000,
+			.amux = 0,
+		},
+	},
+	[SAA7134_BOARD_ENCORE_ENLTV_FM3] = {
+		.name           = "Encore ENLTV-FM 3",
+		.audio_clock    = 0x02187de7,
+		.tuner_type     = TUNER_TENA_TNF_5337,
+		.radio_type     = TUNER_TEA5767,
+		.tuner_addr	= 0x61,
+		.radio_addr	= 0x60,
+		.inputs         = { {
+			.name = name_tv,
+			.vmux = 1,
+			.amux = LINE2,
+			.tv   = 1,
+		}, {
+			.name = name_comp1,
+			.vmux = 3,
+			.amux = LINE1,
+		}, {
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		} },
+		.radio = {
+			.name = name_radio,
+			.vmux = 1,
+			.amux = LINE1,
+		},
+		.mute = {
+			.name = name_mute,
+			.amux = LINE1,
+			.gpio = 0x43000,
+		},
+	},
+	[SAA7134_BOARD_CINERGY_HT_PCI] = {
+		.name           = "Terratec Cinergy HT PCI",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_TDA8290,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.mpeg           = SAA7134_MPEG_DVB,
+		.inputs = {{
+			.name   = name_tv,
+			.vmux   = 1,
+			.amux   = TV,
+			.tv     = 1,
+		},{
+			.name   = name_comp1,
+			.vmux   = 0,
+			.amux   = LINE1,
+		},{
+			.name   = name_svideo,
+			.vmux   = 6,
+			.amux   = LINE1,
+		}},
+	},
+	[SAA7134_BOARD_PHILIPS_TIGER_S] = {
+		.name           = "Philips Tiger - S Reference design",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_TDA8290,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.tuner_config   = 2,
+		.mpeg           = SAA7134_MPEG_DVB,
+		.gpiomask       = 0x0200000,
+		.inputs = {{
+			.name   = name_tv,
+			.vmux   = 1,
+			.amux   = TV,
+			.tv     = 1,
+		},{
+			.name   = name_comp1,
+			.vmux   = 3,
+			.amux   = LINE1,
+		},{
+			.name   = name_svideo,
+			.vmux   = 8,
+			.amux   = LINE1,
+		}},
+		.radio = {
+			.name   = name_radio,
+			.amux   = TV,
+			.gpio   = 0x0200000,
+		},
+	},
+	[SAA7134_BOARD_AVERMEDIA_M102] = {
+		.name           = "Avermedia M102",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_TDA8290,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.gpiomask       = 1<<21,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.tv   = 1,
+		},{
+			.name = name_comp1,
+			.vmux = 0,
+			.amux = LINE2,
+		},{
+			.name = name_svideo,
+			.vmux = 6,
+			.amux = LINE2,
+		}},
+	},
+	[SAA7134_BOARD_ASUS_P7131_4871] = {
+		.name           = "ASUS P7131 4871",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_TDA8290,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.tuner_config   = 2,
+		.mpeg           = SAA7134_MPEG_DVB,
+		.gpiomask       = 0x0200000,
+		.inputs = {{
+			.name   = name_tv,
+			.vmux   = 1,
+			.amux   = TV,
+			.tv     = 1,
+			.gpio   = 0x0200000,
+		}},
+	},
+	[SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA] = {
+		.name           = "ASUSTeK P7131 Hybrid",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_TDA8290,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.tuner_config   = 2,
+		.gpiomask	= 1 << 21,
+		.mpeg           = SAA7134_MPEG_DVB,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.tv   = 1,
+			.gpio = 0x0000000,
+		},{
+			.name = name_comp1,
+			.vmux = 3,
+			.amux = LINE2,
+			.gpio = 0x0200000,
+		},{
+			.name = name_comp2,
+			.vmux = 0,
+			.amux = LINE2,
+			.gpio = 0x0200000,
+		},{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE2,
+			.gpio = 0x0200000,
+		}},
+		.radio = {
+			.name = name_radio,
+			.amux = TV,
+			.gpio = 0x0200000,
+		},
+	},
+	[SAA7134_BOARD_ASUSTeK_P7131_ANALOG] = {
+	       .name           = "ASUSTeK P7131 Analog",
+	       .audio_clock    = 0x00187de7,
+	       .tuner_type     = TUNER_PHILIPS_TDA8290,
+	       .radio_type     = UNSET,
+	       .tuner_addr     = ADDR_UNSET,
+	       .radio_addr     = ADDR_UNSET,
+	       .gpiomask       = 1 << 21,
+	       .inputs         = {{
+		       .name = name_tv,
+		       .vmux = 1,
+		       .amux = TV,
+		       .tv   = 1,
+		       .gpio = 0x0000000,
+	       }, {
+		       .name = name_comp1,
+		       .vmux = 3,
+		       .amux = LINE2,
+	       }, {
+		       .name = name_comp2,
+		       .vmux = 0,
+		       .amux = LINE2,
+	       }, {
+		       .name = name_svideo,
+		       .vmux = 8,
+		       .amux = LINE2,
+	       } },
+	       .radio = {
+		       .name = name_radio,
+		       .amux = TV,
+		       .gpio = 0x0200000,
+	       },
+	},
+	[SAA7134_BOARD_SABRENT_TV_PCB05] = {
+		.name           = "Sabrent PCMCIA TV-PCB05",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_TDA8290,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.tv   = 1,
+		},{
+			.name = name_comp1,
+			.vmux = 3,
+			.amux = LINE1,
+		},{
+			.name = name_comp2,
+			.vmux = 0,
+			.amux = LINE1,
+		},{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		}},
+		.mute = {
+			.name = name_mute,
+			.amux = TV,
+		},
+	},
+	[SAA7134_BOARD_10MOONSTVMASTER3] = {
+		/* Tony Wan <aloha_cn@hotmail.com> */
+		.name           = "10MOONS TM300 TV Card",
+		.audio_clock    = 0x00200000,
+		.tuner_type     = TUNER_LG_PAL_NEW_TAPC,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.gpiomask       = 0x7000,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = LINE2,
+			.gpio = 0x0000,
+			.tv   = 1,
+		},{
+			.name = name_comp1,
+			.vmux = 3,
+			.amux = LINE1,
+			.gpio = 0x2000,
+		},{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+			.gpio = 0x2000,
+		}},
+		.mute = {
+			.name = name_mute,
+			.amux = LINE2,
+			.gpio = 0x3000,
+		},
+	},
+	[SAA7134_BOARD_AVERMEDIA_SUPER_007] = {
+		.name           = "Avermedia Super 007",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_TDA8290,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.tuner_config   = 0,
+		.mpeg           = SAA7134_MPEG_DVB,
+		.inputs = {{
+			.name   = name_tv, /* FIXME: analog tv untested */
+			.vmux   = 1,
+			.amux   = TV,
+			.tv     = 1,
+		}},
+	},
+	[SAA7134_BOARD_AVERMEDIA_M135A] = {
+		.name           = "Avermedia PCI pure analog (M135A)",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_TDA8290,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.tuner_config   = 2,
+		.gpiomask       = 0x020200000,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.tv   = 1,
+		}, {
+			.name = name_comp1,
+			.vmux = 3,
+			.amux = LINE1,
+		}, {
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		} },
+		.radio = {
+			.name = name_radio,
+			.amux = TV,
+			.gpio = 0x00200000,
+		},
+		.mute = {
+			.name = name_mute,
+			.amux = TV,
+			.gpio = 0x01,
+		},
+	},
+	[SAA7134_BOARD_AVERMEDIA_M733A] = {
+		.name		= "Avermedia PCI M733A",
+		.audio_clock	= 0x00187de7,
+		.tuner_type	= TUNER_PHILIPS_TDA8290,
+		.radio_type	= UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.tuner_config	= 0,
+		.gpiomask	= 0x020200000,
+		.inputs		= {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.tv   = 1,
+		}, {
+			.name = name_comp1,
+			.vmux = 3,
+			.amux = LINE1,
+		}, {
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		} },
+		.radio = {
+			.name = name_radio,
+			.amux = TV,
+			.gpio = 0x00200000,
+		},
+		.mute = {
+			.name = name_mute,
+			.amux = TV,
+			.gpio = 0x01,
+		},
+	},
+	[SAA7134_BOARD_BEHOLD_401] = {
+		/*       Beholder Intl. Ltd. 2008      */
+		/*Dmitry Belimov <d.belimov@gmail.com> */
+		.name           = "Beholder BeholdTV 401",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_FQ1216ME,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.gpiomask       = 0x00008000,
+		.inputs         = {{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		},{
+			.name = name_comp1,
+			.vmux = 1,
+			.amux = LINE1,
+		},{
+			.name = name_tv,
+			.vmux = 3,
+			.amux = LINE2,
+			.tv   = 1,
+		}},
+		.mute = {
+			.name = name_mute,
+			.amux = LINE1,
+		},
+	},
+	[SAA7134_BOARD_BEHOLD_403] = {
+		/*       Beholder Intl. Ltd. 2008      */
+		/*Dmitry Belimov <d.belimov@gmail.com> */
+		.name           = "Beholder BeholdTV 403",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_FQ1216ME,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.gpiomask       = 0x00008000,
+		.inputs         = {{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		},{
+			.name   = name_comp1,
+			.vmux   = 1,
+			.amux   = LINE1,
+		},{
+			.name = name_tv,
+			.vmux = 3,
+			.amux = LINE2,
+			.tv   = 1,
+		}},
+	},
+	[SAA7134_BOARD_BEHOLD_403FM] = {
+		/*       Beholder Intl. Ltd. 2008      */
+		/*Dmitry Belimov <d.belimov@gmail.com> */
+		.name           = "Beholder BeholdTV 403 FM",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_FQ1216ME,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.gpiomask       = 0x00008000,
+		.inputs         = {{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		},{
+			.name   = name_comp1,
+			.vmux   = 1,
+			.amux   = LINE1,
+		},{
+			.name = name_tv,
+			.vmux = 3,
+			.amux = LINE2,
+			.tv   = 1,
+		}},
+		.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+		},
+	},
+	[SAA7134_BOARD_BEHOLD_405] = {
+		/*       Beholder Intl. Ltd. 2008      */
+		/*Dmitry Belimov <d.belimov@gmail.com> */
+		.name           = "Beholder BeholdTV 405",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.gpiomask       = 0x00008000,
+		.inputs         = {{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		},{
+			.name = name_comp1,
+			.vmux = 3,
+			.amux = LINE1,
+		},{
+			.name = name_tv,
+			.vmux = 3,
+			.amux = LINE2,
+			.tv   = 1,
+		}},
+	},
+	[SAA7134_BOARD_BEHOLD_405FM] = {
+		/* Sergey <skiv@orel.ru> */
+		/*       Beholder Intl. Ltd. 2008      */
+		/*Dmitry Belimov <d.belimov@gmail.com> */
+		.name           = "Beholder BeholdTV 405 FM",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.gpiomask       = 0x00008000,
+		.inputs         = {{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		},{
+			.name = name_comp1,
+			.vmux = 3,
+			.amux = LINE1,
+		},{
+			.name = name_tv,
+			.vmux = 3,
+			.amux = LINE2,
+			.tv   = 1,
+		}},
+		.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+		},
+	},
+	[SAA7134_BOARD_BEHOLD_407] = {
+		/*       Beholder Intl. Ltd. 2008      */
+		/*Dmitry Belimov <d.belimov@gmail.com> */
+		.name 		= "Beholder BeholdTV 407",
+		.audio_clock 	= 0x00187de7,
+		.tuner_type 	= TUNER_PHILIPS_FM1216ME_MK3,
+		.radio_type 	= UNSET,
+		.tuner_addr 	= ADDR_UNSET,
+		.radio_addr 	= ADDR_UNSET,
+		.tda9887_conf 	= TDA9887_PRESENT,
+		.gpiomask       = 0x00008000,
+		.inputs = {{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+			.gpio = 0xc0c000,
+		},{
+			.name = name_comp1,
+			.vmux = 1,
+			.amux = LINE1,
+			.gpio = 0xc0c000,
+		},{
+			.name = name_tv,
+			.vmux = 3,
+			.amux = TV,
+			.tv = 1,
+			.gpio = 0xc0c000,
+		}},
+	},
+	[SAA7134_BOARD_BEHOLD_407FM] = {
+		/*       Beholder Intl. Ltd. 2008      */
+		/*Dmitry Belimov <d.belimov@gmail.com> */
+		.name 		= "Beholder BeholdTV 407 FM",
+		.audio_clock 	= 0x00187de7,
+		.tuner_type 	= TUNER_PHILIPS_FM1216ME_MK3,
+		.radio_type 	= UNSET,
+		.tuner_addr 	= ADDR_UNSET,
+		.radio_addr 	= ADDR_UNSET,
+		.tda9887_conf 	= TDA9887_PRESENT,
+		.gpiomask       = 0x00008000,
+		.inputs = {{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+			.gpio = 0xc0c000,
+		},{
+			.name = name_comp1,
+			.vmux = 1,
+			.amux = LINE1,
+			.gpio = 0xc0c000,
+		},{
+			.name = name_tv,
+			.vmux = 3,
+			.amux = TV,
+			.tv = 1,
+			.gpio = 0xc0c000,
+		}},
+		.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+			.gpio = 0xc0c000,
+		},
+	},
+	[SAA7134_BOARD_BEHOLD_409] = {
+		/*       Beholder Intl. Ltd. 2008      */
+		/*Dmitry Belimov <d.belimov@gmail.com> */
+		.name           = "Beholder BeholdTV 409",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.gpiomask       = 0x00008000,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 3,
+			.amux = TV,
+			.tv   = 1,
+		},{
+			.name = name_comp1,
+			.vmux = 1,
+			.amux = LINE1,
+		},{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		}},
+	},
+	[SAA7134_BOARD_BEHOLD_505FM] = {
+		/*       Beholder Intl. Ltd. 2008      */
+		/*Dmitry Belimov <d.belimov@gmail.com> */
+		.name           = "Beholder BeholdTV 505 FM",
+		.audio_clock    = 0x00200000,
+		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.gpiomask       = 0x00008000,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 3,
+			.amux = LINE2,
+			.tv   = 1,
+		}, {
+			.name = name_comp1,
+			.vmux = 1,
+			.amux = LINE1,
+		}, {
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		} },
+		.mute = {
+			.name = name_mute,
+			.amux = LINE1,
+		},
+		.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+		},
+	},
+	[SAA7134_BOARD_BEHOLD_505RDS_MK5] = {
+		/*       Beholder Intl. Ltd. 2008      */
+		/*Dmitry Belimov <d.belimov@gmail.com> */
+		.name           = "Beholder BeholdTV 505 RDS",
+		.audio_clock    = 0x00200000,
+		.tuner_type     = TUNER_PHILIPS_FM1216MK5,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.rds_addr 	= 0x10,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.gpiomask       = 0x00008000,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 3,
+			.amux = LINE2,
+			.tv   = 1,
+		},{
+			.name = name_comp1,
+			.vmux = 1,
+			.amux = LINE1,
+		},{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		}},
+		.mute = {
+			.name = name_mute,
+			.amux = LINE1,
+		},
+		.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+		},
+	},
+	[SAA7134_BOARD_BEHOLD_507_9FM] = {
+		/*       Beholder Intl. Ltd. 2008      */
+		/*Dmitry Belimov <d.belimov@gmail.com> */
+		.name           = "Beholder BeholdTV 507 FM / BeholdTV 509 FM",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.gpiomask       = 0x00008000,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 3,
+			.amux = TV,
+			.tv   = 1,
+		},{
+			.name = name_comp1,
+			.vmux = 1,
+			.amux = LINE1,
+		},{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		}},
+			.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+		},
+	},
+	[SAA7134_BOARD_BEHOLD_507RDS_MK5] = {
+		/*       Beholder Intl. Ltd. 2008      */
+		/*Dmitry Belimov <d.belimov@gmail.com> */
+		.name           = "Beholder BeholdTV 507 RDS",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_FM1216MK5,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.rds_addr 	= 0x10,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.gpiomask       = 0x00008000,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 3,
+			.amux = TV,
+			.tv   = 1,
+		}, {
+			.name = name_comp1,
+			.vmux = 1,
+			.amux = LINE1,
+		}, {
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		} },
+			.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+		},
+	},
+	[SAA7134_BOARD_BEHOLD_507RDS_MK3] = {
+		/*       Beholder Intl. Ltd. 2008      */
+		/*Dmitry Belimov <d.belimov@gmail.com> */
+		.name           = "Beholder BeholdTV 507 RDS",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.rds_addr 	= 0x10,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.gpiomask       = 0x00008000,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 3,
+			.amux = TV,
+			.tv   = 1,
+		}, {
+			.name = name_comp1,
+			.vmux = 1,
+			.amux = LINE1,
+		}, {
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		} },
+			.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+		},
+	},
+	[SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM] = {
+		/*       Beholder Intl. Ltd. 2008      */
+		/* Dmitry Belimov <d.belimov@gmail.com> */
+		.name           = "Beholder BeholdTV Columbus TV/FM",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_ALPS_TSBE5_PAL,
+		.radio_type     = TUNER_TEA5767,
+		.tuner_addr     = 0xc2 >> 1,
+		.radio_addr     = 0xc0 >> 1,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.gpiomask       = 0x000A8004,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 3,
+			.amux = TV,
+			.tv   = 1,
+			.gpio = 0x000A8004,
+		}, {
+			.name = name_comp1,
+			.vmux = 1,
+			.amux = LINE1,
+			.gpio = 0x000A8000,
+		}, {
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+			.gpio = 0x000A8000,
+		} },
+		.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+			.gpio = 0x000A8000,
+		},
+	},
+	[SAA7134_BOARD_BEHOLD_607FM_MK3] = {
+		/* Andrey Melnikoff <temnota@kmv.ru> */
+		.name           = "Beholder BeholdTV 607 FM",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 3,
+			.amux = TV,
+			.tv   = 1,
+		}, {
+			.name = name_comp1,
+			.vmux = 1,
+			.amux = LINE1,
+		}, {
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		} },
+		.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+		},
+	},
+	[SAA7134_BOARD_BEHOLD_609FM_MK3] = {
+		/* Andrey Melnikoff <temnota@kmv.ru> */
+		.name           = "Beholder BeholdTV 609 FM",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 3,
+			.amux = TV,
+			.tv   = 1,
+		}, {
+			.name = name_comp1,
+			.vmux = 1,
+			.amux = LINE1,
+		}, {
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		} },
+		.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+		},
+	},
+	[SAA7134_BOARD_BEHOLD_607FM_MK5] = {
+		/* Andrey Melnikoff <temnota@kmv.ru> */
+		.name           = "Beholder BeholdTV 607 FM",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_FM1216MK5,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 3,
+			.amux = TV,
+			.tv   = 1,
+		}, {
+			.name = name_comp1,
+			.vmux = 1,
+			.amux = LINE1,
+		}, {
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		} },
+		.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+		},
+	},
+	[SAA7134_BOARD_BEHOLD_609FM_MK5] = {
+		/* Andrey Melnikoff <temnota@kmv.ru> */
+		.name           = "Beholder BeholdTV 609 FM",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_FM1216MK5,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 3,
+			.amux = TV,
+			.tv   = 1,
+		}, {
+			.name = name_comp1,
+			.vmux = 1,
+			.amux = LINE1,
+		}, {
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		} },
+		.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+		},
+	},
+	[SAA7134_BOARD_BEHOLD_607RDS_MK3] = {
+		/* Andrey Melnikoff <temnota@kmv.ru> */
+		.name           = "Beholder BeholdTV 607 RDS",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.rds_addr 	= 0x10,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 3,
+			.amux = TV,
+			.tv   = 1,
+		}, {
+			.name = name_comp1,
+			.vmux = 1,
+			.amux = LINE1,
+		}, {
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		} },
+		.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+		},
+	},
+	[SAA7134_BOARD_BEHOLD_609RDS_MK3] = {
+		/* Andrey Melnikoff <temnota@kmv.ru> */
+		.name           = "Beholder BeholdTV 609 RDS",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.rds_addr 	= 0x10,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 3,
+			.amux = TV,
+			.tv   = 1,
+		}, {
+			.name = name_comp1,
+			.vmux = 1,
+			.amux = LINE1,
+		}, {
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		} },
+		.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+		},
+	},
+	[SAA7134_BOARD_BEHOLD_607RDS_MK5] = {
+		/* Andrey Melnikoff <temnota@kmv.ru> */
+		.name           = "Beholder BeholdTV 607 RDS",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_FM1216MK5,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.rds_addr 	= 0x10,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 3,
+			.amux = TV,
+			.tv   = 1,
+		}, {
+			.name = name_comp1,
+			.vmux = 1,
+			.amux = LINE1,
+		}, {
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		} },
+		.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+		},
+	},
+	[SAA7134_BOARD_BEHOLD_609RDS_MK5] = {
+		/* Andrey Melnikoff <temnota@kmv.ru> */
+		.name           = "Beholder BeholdTV 609 RDS",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_FM1216MK5,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.rds_addr 	= 0x10,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 3,
+			.amux = TV,
+			.tv   = 1,
+		},{
+			.name = name_comp1,
+			.vmux = 1,
+			.amux = LINE1,
+		},{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		}},
+		.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+		},
+	},
+	[SAA7134_BOARD_BEHOLD_M6] = {
+		/* Igor Kuznetsov <igk@igk.ru> */
+		/* Andrey Melnikoff <temnota@kmv.ru> */
+		/* Beholder Intl. Ltd. Dmitry Belimov <d.belimov@gmail.com> */
+		/* Alexey Osipov <lion-simba@pridelands.ru> */
+		.name           = "Beholder BeholdTV M6",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.empress_addr 	= 0x20,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.inputs         = { {
+			.name = name_tv,
+			.vmux = 3,
+			.amux = TV,
+			.tv   = 1,
+		}, {
+			.name = name_comp1,
+			.vmux = 1,
+			.amux = LINE1,
+		}, {
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		} },
+		.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+		},
+		.mpeg  = SAA7134_MPEG_EMPRESS,
+		.video_out = CCIR656,
+		.vid_port_opts  = (SET_T_CODE_POLARITY_NON_INVERTED |
+					SET_CLOCK_NOT_DELAYED |
+					SET_CLOCK_INVERTED |
+					SET_VSYNC_OFF),
+	},
+	[SAA7134_BOARD_BEHOLD_M63] = {
+		/* Igor Kuznetsov <igk@igk.ru> */
+		/* Andrey Melnikoff <temnota@kmv.ru> */
+		/* Beholder Intl. Ltd. Dmitry Belimov <d.belimov@gmail.com> */
+		.name           = "Beholder BeholdTV M63",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.empress_addr 	= 0x20,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.inputs         = { {
+			.name = name_tv,
+			.vmux = 3,
+			.amux = TV,
+			.tv   = 1,
+		}, {
+			.name = name_comp1,
+			.vmux = 1,
+			.amux = LINE1,
+		}, {
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		} },
+		.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+		},
+		.mpeg  = SAA7134_MPEG_EMPRESS,
+		.video_out = CCIR656,
+		.vid_port_opts  = (SET_T_CODE_POLARITY_NON_INVERTED |
+					SET_CLOCK_NOT_DELAYED |
+					SET_CLOCK_INVERTED |
+					SET_VSYNC_OFF),
+	},
+	[SAA7134_BOARD_BEHOLD_M6_EXTRA] = {
+		/* Igor Kuznetsov <igk@igk.ru> */
+		/* Andrey Melnikoff <temnota@kmv.ru> */
+		/* Beholder Intl. Ltd. Dmitry Belimov <d.belimov@gmail.com> */
+		/* Alexey Osipov <lion-simba@pridelands.ru> */
+		.name           = "Beholder BeholdTV M6 Extra",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_FM1216MK5,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.rds_addr 	= 0x10,
+		.empress_addr 	= 0x20,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.inputs         = { {
+			.name = name_tv,
+			.vmux = 3,
+			.amux = TV,
+			.tv   = 1,
+		}, {
+			.name = name_comp1,
+			.vmux = 1,
+			.amux = LINE1,
+		}, {
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		} },
+		.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+		},
+		.mpeg  = SAA7134_MPEG_EMPRESS,
+		.video_out = CCIR656,
+		.vid_port_opts  = (SET_T_CODE_POLARITY_NON_INVERTED |
+					SET_CLOCK_NOT_DELAYED |
+					SET_CLOCK_INVERTED |
+					SET_VSYNC_OFF),
+	},
+	[SAA7134_BOARD_TWINHAN_DTV_DVB_3056] = {
+		.name           = "Twinhan Hybrid DTV-DVB 3056 PCI",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_TDA8290,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.tuner_config   = 2,
+		.mpeg           = SAA7134_MPEG_DVB,
+		.gpiomask       = 0x0200000,
+		.inputs = {{
+			.name   = name_tv,
+			.vmux   = 1,
+			.amux   = TV,
+			.tv     = 1,
+		}, {
+			.name   = name_comp1,
+			.vmux   = 3,
+			.amux   = LINE1,
+		}, {
+			.name   = name_svideo,
+			.vmux   = 8,		/* untested */
+			.amux   = LINE1,
+		} },
+		.radio = {
+			.name   = name_radio,
+			.amux   = TV,
+			.gpio   = 0x0200000,
+		},
+	},
+	[SAA7134_BOARD_GENIUS_TVGO_A11MCE] = {
+		/* Adrian Pardini <pardo.bsso@gmail.com> */
+		.name		= "Genius TVGO AM11MCE",
+		.audio_clock	= 0x00200000,
+		.tuner_type	= TUNER_TNF_5335MF,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.gpiomask       = 0xf000,
+		.inputs         = {{
+			.name = name_tv_mono,
+			.vmux = 1,
+			.amux = LINE2,
+			.gpio = 0x0000,
+			.tv   = 1,
+		}, {
+			.name = name_comp1,
+			.vmux = 3,
+			.amux = LINE1,
+			.gpio = 0x2000,
+			.tv = 1
+		}, {
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+			.gpio = 0x2000,
+	} },
+		.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+			.gpio = 0x1000,
+		},
+		.mute = {
+			.name = name_mute,
+			.amux = LINE2,
+			.gpio = 0x6000,
+		},
+	},
+	[SAA7134_BOARD_PHILIPS_SNAKE] = {
+		.name           = "NXP Snake DVB-S reference design",
+		.audio_clock    = 0x00200000,
+		.tuner_type     = TUNER_ABSENT,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.mpeg           = SAA7134_MPEG_DVB,
+		.inputs = {{
+			.name   = name_comp1,
+			.vmux   = 3,
+			.amux   = LINE1,
+		}, {
+			.name   = name_svideo,
+			.vmux   = 8,
+			.amux   = LINE1,
+		} },
+	},
+	[SAA7134_BOARD_CREATIX_CTX953] = {
+		.name         = "Medion/Creatix CTX953 Hybrid",
+		.audio_clock  = 0x00187de7,
+		.tuner_type   = TUNER_PHILIPS_TDA8290,
+		.radio_type   = UNSET,
+		.tuner_addr   = ADDR_UNSET,
+		.radio_addr   = ADDR_UNSET,
+		.tuner_config = 0,
+		.mpeg         = SAA7134_MPEG_DVB,
+		.inputs       = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.tv   = 1,
+		}, {
+			.name = name_comp1,
+			.vmux = 0,
+			.amux = LINE1,
+		}, {
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		} },
+	},
+	[SAA7134_BOARD_MSI_TVANYWHERE_AD11] = {
+		.name           = "MSI TV@nywhere A/D v1.1",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_TDA8290,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.tuner_config   = 2,
+		.mpeg           = SAA7134_MPEG_DVB,
+		.gpiomask       = 0x0200000,
+		.inputs = { {
+			.name   = name_tv,
+			.vmux   = 1,
+			.amux   = TV,
+			.tv     = 1,
+		}, {
+			.name   = name_comp1,
+			.vmux   = 3,
+			.amux   = LINE1,
+		}, {
+			.name   = name_svideo,
+			.vmux   = 8,
+			.amux   = LINE1,
+		} },
+		.radio = {
+			.name   = name_radio,
+			.amux   = TV,
+			.gpio   = 0x0200000,
+		},
+	},
+	[SAA7134_BOARD_AVERMEDIA_CARDBUS_506] = {
+		.name           = "AVerMedia Cardbus TV/Radio (E506R)",
+		.audio_clock    = 0x187de7,
+		.tuner_type     = TUNER_XC2028,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		 .mpeg           = SAA7134_MPEG_DVB,
+		 .inputs         = {{
+			 .name = name_tv,
+			 .vmux = 1,
+			 .amux = TV,
+			 .tv   = 1,
+		 }, {
+			 .name = name_comp1,
+			 .vmux = 3,
+			 .amux = LINE1,
+		 }, {
+			 .name = name_svideo,
+			 .vmux = 8,
+			 .amux = LINE2,
+		 } },
+		 .radio = {
+			 .name = name_radio,
+			 .amux = TV,
+		 },
+	},
+	[SAA7134_BOARD_AVERMEDIA_A16D] = {
+		.name           = "AVerMedia Hybrid TV/Radio (A16D)",
+		.audio_clock    = 0x187de7,
+		.tuner_type     = TUNER_XC2028,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.mpeg           = SAA7134_MPEG_DVB,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.tv   = 1,
+		}, {
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		}, {
+			.name = name_comp,
+			.vmux = 0,
+			.amux = LINE1,
+		} },
+		.radio = {
+			.name = name_radio,
+			.amux = TV,
+		},
+	},
+	[SAA7134_BOARD_AVERMEDIA_M115] = {
+		.name           = "Avermedia M115",
+		.audio_clock    = 0x187de7,
+		.tuner_type     = TUNER_XC2028,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.tv   = 1,
+		}, {
+			.name = name_comp1,
+			.vmux = 3,
+			.amux = LINE1,
+		}, {
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE2,
+		} },
+	},
+	[SAA7134_BOARD_VIDEOMATE_T750] = {
+		/* John Newbigin <jn@it.swin.edu.au> */
+		.name           = "Compro VideoMate T750",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_XC2028,
+		.radio_type     = UNSET,
+		.tuner_addr	= 0x61,
+		.radio_addr	= ADDR_UNSET,
+		.mpeg           = SAA7134_MPEG_DVB,
+		.inputs = {{
+			.name   = name_tv,
+			.vmux   = 3,
+			.amux   = TV,
+			.tv     = 1,
+		}, {
+			.name   = name_comp1,
+			.vmux   = 1,
+			.amux   = LINE2,
+		}, {
+			.name   = name_svideo,
+			.vmux   = 8,
+			.amux   = LINE2,
+		} },
+		.radio = {
+			.name = name_radio,
+			.amux = TV,
+		}
+	},
+	[SAA7134_BOARD_AVERMEDIA_A700_PRO] = {
+		/* Matthias Schwarzott <zzam@gentoo.org> */
+		.name           = "Avermedia DVB-S Pro A700",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_ABSENT,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.mpeg           = SAA7134_MPEG_DVB,
+		.inputs         = { {
+			.name = name_comp,
+			.vmux = 1,
+			.amux = LINE1,
+		}, {
+			.name = name_svideo,
+			.vmux = 6,
+			.amux = LINE1,
+		} },
+	},
+	[SAA7134_BOARD_AVERMEDIA_A700_HYBRID] = {
+		/* Matthias Schwarzott <zzam@gentoo.org> */
+		.name           = "Avermedia DVB-S Hybrid+FM A700",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_XC2028,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.mpeg           = SAA7134_MPEG_DVB,
+		.inputs         = { {
+			.name   = name_tv,
+			.vmux   = 4,
+			.amux   = TV,
+			.tv     = 1,
+		}, {
+			.name = name_comp,
+			.vmux = 1,
+			.amux = LINE1,
+		}, {
+			.name = name_svideo,
+			.vmux = 6,
+			.amux = LINE1,
+		} },
+		.radio = {
+			.name = name_radio,
+			.amux = TV,
+		},
+	},
+	[SAA7134_BOARD_BEHOLD_H6] = {
+		/* Igor Kuznetsov <igk@igk.ru> */
+		.name           = "Beholder BeholdTV H6",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_FMD1216MEX_MK3,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.mpeg           = SAA7134_MPEG_DVB,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 3,
+			.amux = TV,
+			.tv   = 1,
+		}, {
+			.name = name_comp1,
+			.vmux = 1,
+			.amux = LINE1,
+		}, {
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		} },
+		.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+		},
+	},
+	[SAA7134_BOARD_ASUSTeK_TIGER_3IN1] = {
+		.name           = "Asus Tiger 3in1",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_TDA8290,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.tuner_config   = 2,
+		.gpiomask       = 1 << 21,
+		.mpeg           = SAA7134_MPEG_DVB,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.tv   = 1,
+		}, {
+			.name = name_comp,
+			.vmux = 0,
+			.amux = LINE2,
+		}, {
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE2,
+		} },
+		.radio = {
+			.name = name_radio,
+			.amux = TV,
+			.gpio = 0x0200000,
+		},
+	},
+	[SAA7134_BOARD_ASUSTeK_PS3_100] = {
+		.name           = "Asus My Cinema PS3-100",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_TDA8290,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.tuner_config   = 2,
+		.gpiomask       = 1 << 21,
+		.mpeg           = SAA7134_MPEG_DVB,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.tv   = 1,
+		}, {
+			.name = name_comp,
+			.vmux = 0,
+			.amux = LINE2,
+		}, {
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE2,
+		} },
+		.radio = {
+			.name = name_radio,
+			.amux = TV,
+			.gpio = 0x0200000,
+		},
+	},
+	[SAA7134_BOARD_REAL_ANGEL_220] = {
+		.name           = "Zogis Real Angel 220",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_TNF_5335MF,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.gpiomask       = 0x801a8087,
+		.inputs = { {
+			.name   = name_tv,
+			.vmux   = 3,
+			.amux   = LINE2,
+			.tv     = 1,
+			.gpio   = 0x624000,
+		}, {
+			.name   = name_comp1,
+			.vmux   = 1,
+			.amux   = LINE1,
+			.gpio   = 0x624000,
+		}, {
+			.name   = name_svideo,
+			.vmux   = 1,
+			.amux   = LINE1,
+			.gpio   = 0x624000,
+		} },
+		.radio = {
+			.name   = name_radio,
+			.amux   = LINE2,
+			.gpio   = 0x624001,
+		},
+		.mute = {
+			.name = name_mute,
+			.amux = TV,
+		},
+	},
+	[SAA7134_BOARD_ADS_INSTANT_HDTV_PCI] = {
+		.name           = "ADS Tech Instant HDTV",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_TUV1236D,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.mpeg           = SAA7134_MPEG_DVB,
+		.inputs         = { {
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.tv   = 1,
+		}, {
+			.name = name_comp,
+			.vmux = 4,
+			.amux = LINE1,
+		}, {
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		} },
+	},
+	[SAA7134_BOARD_ASUSTeK_TIGER] = {
+		.name           = "Asus Tiger Rev:1.00",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_TDA8290,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.tuner_config   = 0,
+		.mpeg           = SAA7134_MPEG_DVB,
+		.gpiomask       = 0x0200000,
+		.inputs = { {
+			.name   = name_tv,
+			.vmux   = 1,
+			.amux   = TV,
+			.tv     = 1,
+		}, {
+			.name   = name_comp1,
+			.vmux   = 3,
+			.amux   = LINE2,
+		}, {
+			.name   = name_comp2,
+			.vmux   = 0,
+			.amux   = LINE2,
+		}, {
+			.name   = name_svideo,
+			.vmux   = 8,
+			.amux   = LINE2,
+		} },
+		.radio = {
+			.name   = name_radio,
+			.amux   = TV,
+			.gpio   = 0x0200000,
+		},
+	},
+	[SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG] = {
+		.name           = "Kworld Plus TV Analog Lite PCI",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_YMEC_TVF_5533MF,
+		.radio_type     = TUNER_TEA5767,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = 0x60,
+		.gpiomask       = 0x80000700,
+		.inputs = { {
+			.name   = name_tv,
+			.vmux   = 1,
+			.amux   = LINE2,
+			.tv     = 1,
+			.gpio   = 0x100,
+		}, {
+			.name   = name_comp1,
+			.vmux   = 3,
+			.amux   = LINE1,
+			.gpio   = 0x200,
+		}, {
+			.name   = name_svideo,
+			.vmux   = 8,
+			.amux   = LINE1,
+			.gpio   = 0x200,
+		} },
+		.radio = {
+			.name   = name_radio,
+			.vmux   = 1,
+			.amux   = LINE1,
+			.gpio   = 0x100,
+		},
+		.mute = {
+			.name = name_mute,
+			.vmux = 8,
+			.amux = 2,
+		},
+	},
+	[SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG] = {
+		.name           = "Kworld PCI SBTVD/ISDB-T Full-Seg Hybrid",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_TDA8290,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_type     = UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.gpiomask       = 0x8e054000,
+		.mpeg           = SAA7134_MPEG_DVB,
+		.ts_type	= SAA7134_MPEG_TS_PARALLEL,
+		.inputs = { {
+			.name   = name_tv,
+			.vmux   = 1,
+			.amux   = TV,
+			.tv     = 1,
+#if 0	/* FIXME */
+		}, {
+			.name   = name_comp1,
+			.vmux   = 3,
+			.amux   = LINE1,
+			.gpio   = 0x200,
+		}, {
+			.name   = name_svideo,
+			.vmux   = 8,
+			.amux   = LINE1,
+			.gpio   = 0x200,
+#endif
+		} },
+#if 0
+		.radio = {
+			.name   = name_radio,
+			.vmux   = 1,
+			.amux   = LINE1,
+			.gpio   = 0x100,
+		},
+#endif
+		.mute = {
+			.name = name_mute,
+			.vmux = 0,
+			.amux = TV,
+		},
+	},
+	[SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS] = {
+		.name           = "Avermedia AVerTV GO 007 FM Plus",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_TDA8290,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.gpiomask       = 0x00300003,
+		/* .gpiomask       = 0x8c240003, */
+		.inputs         = { {
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.tv   = 1,
+			.gpio = 0x01,
+		}, {
+			.name = name_svideo,
+			.vmux = 6,
+			.amux = LINE1,
+			.gpio = 0x02,
+		} },
+		.radio = {
+			.name = name_radio,
+			.amux = TV,
+			.gpio = 0x00300001,
+		},
+		.mute = {
+			.name = name_mute,
+			.amux = TV,
+			.gpio = 0x01,
+		},
+	},
+	[SAA7134_BOARD_AVERMEDIA_STUDIO_507UA] = {
+		/* Andy Shevchenko <andy@smile.org.ua> */
+		.name           = "Avermedia AVerTV Studio 507UA",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3, /* Should be MK5 */
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.gpiomask       = 0x03,
+		.inputs         = { {
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.tv   = 1,
+			.gpio = 0x00,
+		}, {
+			.name = name_comp1,
+			.vmux = 3,
+			.amux = LINE1,
+			.gpio = 0x00,
+		}, {
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+			.gpio = 0x00,
+		} },
+		.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+			.gpio = 0x01,
+		},
+		.mute  = {
+			.name = name_mute,
+			.amux = LINE1,
+			.gpio = 0x00,
+		},
+	},
+	[SAA7134_BOARD_VIDEOMATE_S350] = {
+		/* Jan D. Louw <jd.louw@mweb.co.za */
+		.name		= "Compro VideoMate S350/S300",
+		.audio_clock	= 0x00187de7,
+		.tuner_type	= TUNER_ABSENT,
+		.radio_type	= UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.mpeg		= SAA7134_MPEG_DVB,
+		.inputs = { {
+			.name	= name_comp1,
+			.vmux	= 0,
+			.amux	= LINE1,
+		}, {
+			.name	= name_svideo,
+			.vmux	= 8, /* Not tested */
+			.amux	= LINE1
+		} },
+	},
+	[SAA7134_BOARD_BEHOLD_X7] = {
+		/* Beholder Intl. Ltd. Dmitry Belimov <d.belimov@gmail.com> */
+		.name           = "Beholder BeholdTV X7",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_XC5000,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.mpeg           = SAA7134_MPEG_DVB,
+		.inputs         = { {
+			.name = name_tv,
+			.vmux = 2,
+			.amux = TV,
+			.tv   = 1,
+		}, {
+			.name = name_comp1,
+			.vmux = 0,
+			.amux = LINE1,
+		}, {
+			.name = name_svideo,
+			.vmux = 9,
+			.amux = LINE1,
+		} },
+		.radio = {
+			.name = name_radio,
+			.amux = TV,
+		},
+	},
+	[SAA7134_BOARD_ZOLID_HYBRID_PCI] = {
+		.name           = "Zolid Hybrid TV Tuner PCI",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_TDA8290,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.tuner_config   = 0,
+		.mpeg           = SAA7134_MPEG_DVB,
+		.ts_type	= SAA7134_MPEG_TS_PARALLEL,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.tv   = 1,
+		} },
+		.radio = {	/* untested */
+			.name = name_radio,
+			.amux = TV,
+		},
+	},
+	[SAA7134_BOARD_ASUS_EUROPA_HYBRID] = {
+		.name           = "Asus Europa Hybrid OEM",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_TD1316,
+		.radio_type     = UNSET,
+		.tuner_addr	= 0x61,
+		.radio_addr	= ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE,
+		.mpeg           = SAA7134_MPEG_DVB,
+		.inputs = { {
+			.name   = name_tv,
+			.vmux   = 3,
+			.amux   = TV,
+			.tv     = 1,
+		}, {
+			.name   = name_comp1,
+			.vmux   = 4,
+			.amux   = LINE2,
+		}, {
+			.name   = name_svideo,
+			.vmux   = 8,
+			.amux   = LINE2,
+		} },
+	},
+	[SAA7134_BOARD_LEADTEK_WINFAST_DTV1000S] = {
+		.name           = "Leadtek Winfast DTV1000S",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_TDA8290,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.mpeg           = SAA7134_MPEG_DVB,
+		.inputs         = { {
+			.name = name_comp1,
+			.vmux = 3,
+		}, {
+			.name = name_svideo,
+			.vmux = 8,
+		} },
+	},
+	[SAA7134_BOARD_BEHOLD_505RDS_MK3] = {
+		/*       Beholder Intl. Ltd. 2008      */
+		/*Dmitry Belimov <d.belimov@gmail.com> */
+		.name           = "Beholder BeholdTV 505 RDS",
+		.audio_clock    = 0x00200000,
+		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.rds_addr 	= 0x10,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.gpiomask       = 0x00008000,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 3,
+			.amux = LINE2,
+			.tv   = 1,
+		}, {
+			.name = name_comp1,
+			.vmux = 1,
+			.amux = LINE1,
+		}, {
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		} },
+		.mute = {
+			.name = name_mute,
+			.amux = LINE1,
+		},
+		.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+		},
+	},
+	[SAA7134_BOARD_HAWELL_HW_404M7] = {
+		/* Hawell HW-404M7 & Hawell HW-808M7  */
+		/* Bogoslovskiy Viktor <bogovic@bk.ru> */
+		.name         = "Hawell HW-404M7",
+		.audio_clock   = 0x00200000,
+		.tuner_type    = UNSET,
+		.radio_type    = UNSET,
+		.tuner_addr   = ADDR_UNSET,
+		.radio_addr   = ADDR_UNSET,
+		.gpiomask      = 0x389c00,
+		.inputs       = {{
+			.name = name_comp1,
+			.vmux = 3,
+			.amux = LINE1,
+			.gpio = 0x01fc00,
+		} },
+	},
+	[SAA7134_BOARD_BEHOLD_H7] = {
+		/* Beholder Intl. Ltd. Dmitry Belimov <d.belimov@gmail.com> */
+		.name           = "Beholder BeholdTV H7",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_XC5000,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.mpeg           = SAA7134_MPEG_DVB,
+		.ts_type	= SAA7134_MPEG_TS_PARALLEL,
+		.inputs         = { {
+			.name = name_tv,
+			.vmux = 2,
+			.amux = TV,
+			.tv   = 1,
+		}, {
+			.name = name_comp1,
+			.vmux = 0,
+			.amux = LINE1,
+		}, {
+			.name = name_svideo,
+			.vmux = 9,
+			.amux = LINE1,
+		} },
+		.radio = {
+			.name = name_radio,
+			.amux = TV,
+		},
+	},
+	[SAA7134_BOARD_BEHOLD_A7] = {
+		/* Beholder Intl. Ltd. Dmitry Belimov <d.belimov@gmail.com> */
+		.name           = "Beholder BeholdTV A7",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_XC5000,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.inputs         = { {
+			.name = name_tv,
+			.vmux = 2,
+			.amux = TV,
+			.tv   = 1,
+		}, {
+			.name = name_comp1,
+			.vmux = 0,
+			.amux = LINE1,
+		}, {
+			.name = name_svideo,
+			.vmux = 9,
+			.amux = LINE1,
+		} },
+		.radio = {
+			.name = name_radio,
+			.amux = TV,
+		},
+	},
+	[SAA7134_BOARD_TECHNOTREND_BUDGET_T3000] = {
+		.name           = "TechoTrend TT-budget T-3000",
+		.tuner_type     = TUNER_PHILIPS_TD1316,
+		.audio_clock    = 0x00187de7,
+		.radio_type     = UNSET,
+		.tuner_addr     = 0x63,
+		.radio_addr     = ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE,
+		.mpeg           = SAA7134_MPEG_DVB,
+		.inputs = {{
+			.name   = name_tv,
+			.vmux   = 3,
+			.amux   = TV,
+			.tv     = 1,
+		}, {
+			.name   = name_comp1,
+			.vmux   = 0,
+			.amux   = LINE2,
+		}, {
+			.name   = name_svideo,
+			.vmux   = 8,
+			.amux   = LINE2,
+		} },
+	},
+	[SAA7134_BOARD_VIDEOMATE_M1F] = {
+		/* Pavel Osnova <pvosnova@gmail.com> */
+		.name           = "Compro VideoMate Vista M1F",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_LG_PAL_NEW_TAPC,
+		.radio_type     = TUNER_TEA5767,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = 0x60,
+		.inputs         = { {
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.tv   = 1,
+		}, {
+			.name = name_comp1,
+			.vmux = 3,
+			.amux = LINE2,
+		}, {
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE2,
+		} },
+		.radio = {
+			.name = name_radio,
+			.amux = LINE1,
+		},
+		.mute = {
+			.name = name_mute,
+			.amux = TV,
+		},
+	},
+	[SAA7134_BOARD_MAGICPRO_PROHDTV_PRO2] = {
+		/* Timothy Lee <timothy.lee@siriushk.com> */
+		.name		= "MagicPro ProHDTV Pro2 DMB-TH/Hybrid",
+		.audio_clock	= 0x00187de7,
+		.tuner_type	= TUNER_PHILIPS_TDA8290,
+		.radio_type	= UNSET,
+		.tuner_config	= 3,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.gpiomask	= 0x02050000,
+		.mpeg		= SAA7134_MPEG_DVB,
+		.ts_type	= SAA7134_MPEG_TS_PARALLEL,
+		.inputs		= { {
+			.name   = name_tv,
+			.vmux   = 1,
+			.amux   = TV,
+			.tv     = 1,
+			.gpio   = 0x00050000,
+		}, {
+			.name   = name_comp1,
+			.vmux   = 3,
+			.amux   = LINE1,
+			.gpio   = 0x00050000,
+		}, {
+			.name   = name_svideo,
+			.vmux   = 8,
+			.amux   = LINE1,
+			.gpio   = 0x00050000,
+		} },
+		.radio = {
+			.name   = name_radio,
+			.amux   = TV,
+			.gpio   = 0x00050000,
+		},
+		.mute = {
+			.name   = name_mute,
+			.vmux   = 0,
+			.amux   = TV,
+			.gpio   = 0x00050000,
+		},
+	},
+	[SAA7134_BOARD_BEHOLD_501] = {
+		/*       Beholder Intl. Ltd. 2010       */
+		/* Dmitry Belimov <d.belimov@gmail.com> */
+		.name           = "Beholder BeholdTV 501",
+		.audio_clock    = 0x00200000,
+		.tuner_type     = TUNER_ABSENT,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.gpiomask       = 0x00008000,
+		.inputs         = { {
+			.name = name_tv,
+			.vmux = 3,
+			.amux = LINE2,
+			.tv   = 1,
+		}, {
+			.name = name_comp1,
+			.vmux = 1,
+			.amux = LINE1,
+		}, {
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		} },
+		.mute = {
+			.name = name_mute,
+			.amux = LINE1,
+		},
+	},
+	[SAA7134_BOARD_BEHOLD_503FM] = {
+		/*       Beholder Intl. Ltd. 2010       */
+		/* Dmitry Belimov <d.belimov@gmail.com> */
+		.name           = "Beholder BeholdTV 503 FM",
+		.audio_clock    = 0x00200000,
+		.tuner_type     = TUNER_ABSENT,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.gpiomask       = 0x00008000,
+		.inputs         = { {
+			.name = name_tv,
+			.vmux = 3,
+			.amux = LINE2,
+			.tv   = 1,
+		}, {
+			.name = name_comp1,
+			.vmux = 1,
+			.amux = LINE1,
+		}, {
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		} },
+		.mute = {
+			.name = name_mute,
+			.amux = LINE1,
+		},
+	},
+	[SAA7134_BOARD_SENSORAY811_911] = {
+		.name		= "Sensoray 811/911",
+		.audio_clock	= 0x00200000,
+		.tuner_type	= TUNER_ABSENT,
+		.radio_type	= UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.inputs		= {{
+			.name   = name_comp1,
+			.vmux   = 0,
+			.amux   = LINE1,
+		}, {
+			.name   = name_comp3,
+			.vmux   = 2,
+			.amux   = LINE1,
+		}, {
+			.name   = name_svideo,
+			.vmux   = 8,
+			.amux   = LINE1,
+		} },
+	},
+	[SAA7134_BOARD_KWORLD_PC150U] = {
+		.name           = "Kworld PC150-U",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_TDA8290,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.mpeg           = SAA7134_MPEG_DVB,
+		.gpiomask       = 1 << 21,
+		.ts_type	= SAA7134_MPEG_TS_PARALLEL,
+		.inputs = { {
+			.name   = name_tv,
+			.vmux   = 1,
+			.amux   = TV,
+			.tv     = 1,
+		}, {
+			.name   = name_comp,
+			.vmux   = 3,
+			.amux   = LINE1,
+		}, {
+			.name   = name_svideo,
+			.vmux   = 8,
+			.amux   = LINE2,
+		} },
+		.radio = {
+			.name   = name_radio,
+			.amux   = TV,
+			.gpio	= 0x0000000,
+		},
+	},
+
+};
+
+const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards);
+
+/* ------------------------------------------------------------------ */
+/* PCI ids + subsystem IDs                                            */
+
+struct pci_device_id saa7134_pci_tbl[] = {
+	{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = PCI_VENDOR_ID_PHILIPS,
+		.subdevice    = 0x2001,
+		.driver_data  = SAA7134_BOARD_PROTEUS_PRO,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = PCI_VENDOR_ID_PHILIPS,
+		.subdevice    = 0x2001,
+		.driver_data  = SAA7134_BOARD_PROTEUS_PRO,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = PCI_VENDOR_ID_PHILIPS,
+		.subdevice    = 0x6752,
+		.driver_data  = SAA7134_BOARD_EMPRESS,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = 0x1131,
+		.subdevice    = 0x4e85,
+		.driver_data  = SAA7134_BOARD_MONSTERTV,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = 0x153b,
+		.subdevice    = 0x1142,
+		.driver_data  = SAA7134_BOARD_CINERGY400,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = 0x153b,
+		.subdevice    = 0x1143,
+		.driver_data  = SAA7134_BOARD_CINERGY600,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = 0x153b,
+		.subdevice    = 0x1158,
+		.driver_data  = SAA7134_BOARD_CINERGY600_MK3,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x153b,
+		.subdevice    = 0x1162,
+		.driver_data  = SAA7134_BOARD_CINERGY400_CARDBUS,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = 0x5169,
+		.subdevice    = 0x0138,
+		.driver_data  = SAA7134_BOARD_FLYVIDEO3000_NTSC,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = 0x5168,
+		.subdevice    = 0x0138,
+		.driver_data  = SAA7134_BOARD_FLYVIDEO3000,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = 0x4e42,				/* "Typhoon PCI Capture TV Card" Art.No. 50673 */
+		.subdevice    = 0x0138,
+		.driver_data  = SAA7134_BOARD_FLYVIDEO3000,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+		.subvendor    = 0x5168,
+		.subdevice    = 0x0138,
+		.driver_data  = SAA7134_BOARD_FLYVIDEO2000,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+		.subvendor    = 0x4e42,		/* Typhoon */
+		.subdevice    = 0x0138,		/* LifeView FlyTV Prime30 OEM */
+		.driver_data  = SAA7134_BOARD_FLYVIDEO2000,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x5168,
+		.subdevice    = 0x0212, /* minipci, LR212 */
+		.driver_data  = SAA7134_BOARD_FLYTVPLATINUM_MINI,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x14c0,
+		.subdevice    = 0x1212, /* minipci, LR1212 */
+		.driver_data  = SAA7134_BOARD_FLYTVPLATINUM_MINI2,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x4e42,
+		.subdevice    = 0x0212, /* OEM minipci, LR212 */
+		.driver_data  = SAA7134_BOARD_FLYTVPLATINUM_MINI,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x5168,	/* Animation Technologies (LifeView) */
+		.subdevice    = 0x0214, /* Standard PCI, LR214 Rev E and earlier (SAA7135) */
+		.driver_data  = SAA7134_BOARD_FLYTVPLATINUM_FM,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x5168,	/* Animation Technologies (LifeView) */
+		.subdevice    = 0x5214, /* Standard PCI, LR214 Rev F onwards (SAA7131) */
+		.driver_data  = SAA7134_BOARD_FLYTVPLATINUM_FM,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x1489, /* KYE */
+		.subdevice    = 0x0214, /* Genius VideoWonder ProTV */
+		.driver_data  = SAA7134_BOARD_FLYTVPLATINUM_FM, /* is an LR214WF actually */
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = 0x16be,
+		.subdevice    = 0x0003,
+		.driver_data  = SAA7134_BOARD_MD7134,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = 0x16be, /* CTX946 analog TV, HW mpeg, DVB-T */
+		.subdevice    = 0x5000, /* only analog TV and DVB-T for now */
+		.driver_data  = SAA7134_BOARD_MD7134,
+	}, {
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+		.subvendor    = 0x1048,
+		.subdevice    = 0x226b,
+		.driver_data  = SAA7134_BOARD_ELSA,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+		.subvendor    = 0x1048,
+		.subdevice    = 0x226a,
+		.driver_data  = SAA7134_BOARD_ELSA_500TV,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+		.subvendor    = 0x1048,
+		.subdevice    = 0x226c,
+		.driver_data  = SAA7134_BOARD_ELSA_700TV,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = PCI_VENDOR_ID_ASUSTEK,
+		.subdevice    = 0x4842,
+		.driver_data  = SAA7134_BOARD_ASUSTeK_TVFM7134,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = PCI_VENDOR_ID_ASUSTEK,
+		.subdevice    = 0x4845,
+		.driver_data  = SAA7134_BOARD_ASUSTeK_TVFM7135,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = PCI_VENDOR_ID_ASUSTEK,
+		.subdevice    = 0x4830,
+		.driver_data  = SAA7134_BOARD_ASUSTeK_TVFM7134,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = PCI_VENDOR_ID_ASUSTEK,
+		.subdevice    = 0x4843,
+		.driver_data  = SAA7134_BOARD_ASUSTEK_TVFM7133,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = PCI_VENDOR_ID_ASUSTEK,
+		.subdevice    = 0x4840,
+		.driver_data  = SAA7134_BOARD_ASUSTeK_TVFM7134,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = PCI_VENDOR_ID_PHILIPS,
+		.subdevice    = 0xfe01,
+		.driver_data  = SAA7134_BOARD_TVSTATION_RDS,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = 0x1894,
+		.subdevice    = 0xfe01,
+		.driver_data  = SAA7134_BOARD_TVSTATION_RDS,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = 0x1894,
+		.subdevice    = 0xa006,
+		.driver_data  = SAA7134_BOARD_TVSTATION_DVR,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = 0x1131,
+		.subdevice    = 0x7133,
+		.driver_data  = SAA7134_BOARD_VA1000POWER,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+		.subvendor    = PCI_VENDOR_ID_PHILIPS,
+		.subdevice    = 0x2001,
+		.driver_data  = SAA7134_BOARD_10MOONSTVMASTER,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x185b,
+		.subdevice    = 0xc100,
+		.driver_data  = SAA7134_BOARD_VIDEOMATE_TV,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x185b,
+		.subdevice    = 0xc100,
+		.driver_data  = SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUS,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+		.subvendor    = PCI_VENDOR_ID_MATROX,
+		.subdevice    = 0x48d0,
+		.driver_data  = SAA7134_BOARD_CRONOS_PLUS,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = 0x1461, /* Avermedia Technologies Inc */
+		.subdevice    = 0xa70b,
+		.driver_data  = SAA7134_BOARD_MD2819,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x1461, /* Avermedia Technologies Inc */
+		.subdevice    = 0xa7a1,
+		.driver_data  = SAA7134_BOARD_AVERMEDIA_A700_PRO,
+	}, {
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x1461, /* Avermedia Technologies Inc */
+		.subdevice    = 0xa7a2,
+		.driver_data  = SAA7134_BOARD_AVERMEDIA_A700_HYBRID,
+	}, {
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+		.subvendor    = 0x1461, /* Avermedia Technologies Inc */
+		.subdevice    = 0x2115,
+		.driver_data  = SAA7134_BOARD_AVERMEDIA_STUDIO_305,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+		.subvendor    = 0x1461, /* Avermedia Technologies Inc */
+		.subdevice    = 0xa115,
+		.driver_data  = SAA7134_BOARD_AVERMEDIA_STUDIO_505,
+	}, {
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+		.subvendor    = 0x1461, /* Avermedia Technologies Inc */
+		.subdevice    = 0x2108,
+		.driver_data  = SAA7134_BOARD_AVERMEDIA_305,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+		.subvendor    = 0x1461, /* Avermedia Technologies Inc */
+		.subdevice    = 0x10ff,
+		.driver_data  = SAA7134_BOARD_AVERMEDIA_DVD_EZMAKER,
+	},{
+		/* AVerMedia CardBus */
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = 0x1461, /* Avermedia Technologies Inc */
+		.subdevice    = 0xd6ee,
+		.driver_data  = SAA7134_BOARD_AVERMEDIA_CARDBUS,
+	},{
+		/* AVerMedia CardBus */
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = 0x1461, /* Avermedia Technologies Inc */
+		.subdevice    = 0xb7e9,
+		.driver_data  = SAA7134_BOARD_AVERMEDIA_CARDBUS_501,
+	}, {
+		/* TransGear 3000TV */
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+		.subvendor    = 0x1461, /* Avermedia Technologies Inc */
+		.subdevice    = 0x050c,
+		.driver_data  = SAA7134_BOARD_TG3000TV,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = 0x11bd,
+		.subdevice    = 0x002b,
+		.driver_data  = SAA7134_BOARD_PINNACLE_PCTV_STEREO,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = 0x11bd,
+		.subdevice    = 0x002d,
+		.driver_data  = SAA7134_BOARD_PINNACLE_300I_DVBT_PAL,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = 0x1019,
+		.subdevice    = 0x4cb4,
+		.driver_data  = SAA7134_BOARD_ECS_TVP3XP,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x1019,
+		.subdevice    = 0x4cb5,
+		.driver_data  = SAA7134_BOARD_ECS_TVP3XP_4CB5,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = 0x1019,
+		.subdevice    = 0x4cb6,
+		.driver_data  = SAA7134_BOARD_ECS_TVP3XP_4CB6,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x12ab,
+		.subdevice    = 0x0800,
+		.driver_data  = SAA7134_BOARD_UPMOST_PURPLE_TV,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+		.subvendor    = 0x153b,
+		.subdevice    = 0x1152,
+		.driver_data  = SAA7134_BOARD_CINERGY200,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+		.subvendor    = 0x185b,
+		.subdevice    = 0xc100,
+		.driver_data  = SAA7134_BOARD_VIDEOMATE_TV_PVR,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = 0x1461, /* Avermedia Technologies Inc */
+		.subdevice    = 0x9715,
+		.driver_data  = SAA7134_BOARD_AVERMEDIA_STUDIO_307,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = 0x1461, /* Avermedia Technologies Inc */
+		.subdevice    = 0xa70a,
+		.driver_data  = SAA7134_BOARD_AVERMEDIA_307,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = 0x185b,
+		.subdevice    = 0xc200,
+		.driver_data  = SAA7134_BOARD_VIDEOMATE_GOLD_PLUS,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = 0x1540,
+		.subdevice    = 0x9524,
+		.driver_data  = SAA7134_BOARD_PROVIDEO_PV952,
+
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x5168,
+		.subdevice    = 0x0502,                /* Cardbus version */
+		.driver_data  = SAA7134_BOARD_FLYDVBT_DUO_CARDBUS,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x5168,
+		.subdevice    = 0x0306,                /* PCI version */
+		.driver_data  = SAA7134_BOARD_FLYDVBTDUO,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x1461, /* Avermedia Technologies Inc */
+		.subdevice    = 0xf31f,
+		.driver_data  = SAA7134_BOARD_AVERMEDIA_GO_007_FM,
+
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x1461, /* Avermedia Technologies Inc */
+		.subdevice    = 0xf11d,
+		.driver_data  = SAA7134_BOARD_AVERMEDIA_M135A,
+	}, {
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x1461, /* Avermedia Technologies Inc */
+		.subdevice    = 0x4155,
+		.driver_data  = SAA7134_BOARD_AVERMEDIA_M733A,
+	}, {
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x1461, /* Avermedia Technologies Inc */
+		.subdevice    = 0x4255,
+		.driver_data  = SAA7134_BOARD_AVERMEDIA_M733A,
+	}, {
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+		.subvendor    = PCI_VENDOR_ID_PHILIPS,
+		.subdevice    = 0x2004,
+		.driver_data  = SAA7134_BOARD_PHILIPS_TOUGH,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x1421,
+		.subdevice    = 0x0350,		/* PCI version */
+		.driver_data  = SAA7134_BOARD_ADS_INSTANT_TV,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x1421,
+		.subdevice    = 0x0351,		/* PCI version, new revision */
+		.driver_data  = SAA7134_BOARD_ADS_INSTANT_TV,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x1421,
+		.subdevice    = 0x0370,		/* cardbus version */
+		.driver_data  = SAA7134_BOARD_ADS_INSTANT_TV,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x1421,
+		.subdevice    = 0x1370,        /* cardbus version */
+		.driver_data  = SAA7134_BOARD_ADS_INSTANT_TV,
+
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x4e42,		/* Typhoon */
+		.subdevice    = 0x0502,		/* LifeView LR502 OEM */
+		.driver_data  = SAA7134_BOARD_FLYDVBT_DUO_CARDBUS,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x1043,
+		.subdevice    = 0x0210,		/* mini pci NTSC version */
+		.driver_data  = SAA7134_BOARD_FLYTV_DIGIMATRIX,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = 0x1043,
+		.subdevice    = 0x0210,		/* mini pci PAL/SECAM version */
+		.driver_data  = SAA7134_BOARD_ASUSTEK_DIGIMATRIX_TV,
+
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x0000, /* It shouldn't break anything, since subdevice id seems unique */
+		.subdevice    = 0x4091,
+		.driver_data  = SAA7134_BOARD_BEHOLD_409FM,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x5456, /* GoTView */
+		.subdevice    = 0x7135,
+		.driver_data  = SAA7134_BOARD_GOTVIEW_7135,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = PCI_VENDOR_ID_PHILIPS,
+		.subdevice    = 0x2004,
+		.driver_data  = SAA7134_BOARD_PHILIPS_EUROPA,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = 0x185b,
+		.subdevice    = 0xc900,
+		.driver_data  = SAA7134_BOARD_VIDEOMATE_DVBT_300,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+		.subvendor    = 0x185b,
+		.subdevice    = 0xc901,
+		.driver_data  = SAA7134_BOARD_VIDEOMATE_DVBT_200,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x1435,
+		.subdevice    = 0x7350,
+		.driver_data  = SAA7134_BOARD_RTD_VFG7350,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x1435,
+		.subdevice    = 0x7330,
+		.driver_data  = SAA7134_BOARD_RTD_VFG7330,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x1461,
+		.subdevice    = 0x1044,
+		.driver_data  = SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x1131,
+		.subdevice    = 0x4ee9,
+		.driver_data  = SAA7134_BOARD_MONSTERTV_MOBILE,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x11bd,
+		.subdevice    = 0x002e,
+		.driver_data  = SAA7134_BOARD_PINNACLE_PCTV_110i,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x1043,
+		.subdevice    = 0x4862,
+		.driver_data  = SAA7134_BOARD_ASUSTeK_P7131_DUAL,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = PCI_VENDOR_ID_PHILIPS,
+		.subdevice    = 0x2018,
+		.driver_data  = SAA7134_BOARD_PHILIPS_TIGER,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x1462,
+		.subdevice    = 0x6231, /* tda8275a, ks003 IR */
+		.driver_data  = SAA7134_BOARD_MSI_TVATANYWHERE_PLUS,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x1462,
+		.subdevice    = 0x8624, /* tda8275, ks003 IR */
+		.driver_data  = SAA7134_BOARD_MSI_TVATANYWHERE_PLUS,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x153b,
+		.subdevice    = 0x1160,
+		.driver_data  = SAA7134_BOARD_CINERGY250PCI,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,	/* SAA 7131E */
+		.subvendor    = 0x5168,
+		.subdevice    = 0x0319,
+		.driver_data  = SAA7134_BOARD_FLYDVB_TRIO,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = 0x1461,
+		.subdevice    = 0x2c05,
+		.driver_data  = SAA7134_BOARD_AVERMEDIA_777,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = 0x5168,
+		.subdevice    = 0x0301,
+		.driver_data  = SAA7134_BOARD_FLYDVBT_LR301,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x0331,
+		.subdevice    = 0x1421,
+		.driver_data  = SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x17de,
+		.subdevice    = 0x7201,
+		.driver_data  = SAA7134_BOARD_TEVION_DVBT_220RF,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x17de,
+		.subdevice    = 0x7250,
+		.driver_data  = SAA7134_BOARD_KWORLD_DVBT_210,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133, /* SAA7135HL */
+		.subvendor    = 0x17de,
+		.subdevice    = 0x7350,
+		.driver_data  = SAA7134_BOARD_KWORLD_ATSC110,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133, /* SAA7135HL */
+		.subvendor    = 0x17de,
+		.subdevice    = 0x7352,
+		.driver_data  = SAA7134_BOARD_KWORLD_ATSC110, /* ATSC 115 */
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133, /* SAA7135HL */
+		.subvendor    = 0x17de,
+		.subdevice    = 0xa134,
+		.driver_data  = SAA7134_BOARD_KWORLD_PC150U,
+	}, {
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = 0x1461,
+		.subdevice    = 0x7360,
+		.driver_data  = SAA7134_BOARD_AVERMEDIA_A169_B,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = 0x1461,
+		.subdevice    = 0x6360,
+		.driver_data  = SAA7134_BOARD_AVERMEDIA_A169_B1,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = 0x16be,
+		.subdevice    = 0x0005,
+		.driver_data  = SAA7134_BOARD_MD7134_BRIDGE_2,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = 0x5168,
+		.subdevice    = 0x0300,
+		.driver_data  = SAA7134_BOARD_FLYDVBS_LR300,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = 0x4e42,
+		.subdevice    = 0x0300,/* LR300 */
+		.driver_data  = SAA7134_BOARD_FLYDVBS_LR300,
+	},{
+		.vendor = PCI_VENDOR_ID_PHILIPS,
+		.device = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor = 0x1489,
+		.subdevice = 0x0301,
+		.driver_data = SAA7134_BOARD_FLYDVBT_LR301,
+	},{
+		.vendor = PCI_VENDOR_ID_PHILIPS,
+		.device = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor = 0x5168, /* Animation Technologies (LifeView) */
+		.subdevice = 0x0304,
+		.driver_data = SAA7134_BOARD_FLYTVPLATINUM_FM,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x5168,
+		.subdevice    = 0x3306,
+		.driver_data  = SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x5168,
+		.subdevice    = 0x3502,  /* whats the difference to 0x3306 ?*/
+		.driver_data  = SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x5168,
+		.subdevice    = 0x3307, /* FlyDVB-T Hybrid Mini PCI */
+		.driver_data  = SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS,
+	}, {
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x16be,
+		.subdevice    = 0x0007,
+		.driver_data  = SAA7134_BOARD_MEDION_MD8800_QUADRO,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x16be,
+		.subdevice    = 0x0008,
+		.driver_data  = SAA7134_BOARD_MEDION_MD8800_QUADRO,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x16be,
+		.subdevice    = 0x000d, /* triple CTX948_V1.1.1 */
+		.driver_data  = SAA7134_BOARD_MEDION_MD8800_QUADRO,
+	}, {
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x1461,
+		.subdevice    = 0x2c05,
+		.driver_data  = SAA7134_BOARD_AVERMEDIA_777,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x1489,
+		.subdevice    = 0x0502,                /* Cardbus version */
+		.driver_data  = SAA7134_BOARD_FLYDVBT_DUO_CARDBUS,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+		.subvendor    = 0x0919, /* Philips Proteus PRO 2309 */
+		.subdevice    = 0x2003,
+		.driver_data  = SAA7134_BOARD_PROTEUS_2309,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = 0x1461,
+		.subdevice    = 0x2c00,
+		.driver_data  = SAA7134_BOARD_AVERMEDIA_A16AR,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = 0x1043,
+		.subdevice    = 0x4860,
+		.driver_data  = SAA7134_BOARD_ASUS_EUROPA2_HYBRID,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x11bd,
+		.subdevice    = 0x002f,
+		.driver_data  = SAA7134_BOARD_PINNACLE_PCTV_310i,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x1461, /* Avermedia Technologies Inc */
+		.subdevice    = 0x9715,
+		.driver_data  = SAA7134_BOARD_AVERMEDIA_STUDIO_507,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = 0x1461, /* Avermedia Technologies Inc */
+		.subdevice    = 0xa11b,
+		.driver_data  = SAA7134_BOARD_AVERMEDIA_STUDIO_507UA,
+	}, {
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x1043,
+		.subdevice    = 0x4876,
+		.driver_data  = SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x0070,
+		.subdevice    = 0x6700,
+		.driver_data  = SAA7134_BOARD_HAUPPAUGE_HVR1110,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x0070,
+		.subdevice    = 0x6701,
+		.driver_data  = SAA7134_BOARD_HAUPPAUGE_HVR1110,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x0070,
+		.subdevice    = 0x6702,
+		.driver_data  = SAA7134_BOARD_HAUPPAUGE_HVR1110,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x0070,
+		.subdevice    = 0x6703,
+		.driver_data  = SAA7134_BOARD_HAUPPAUGE_HVR1110,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x0070,
+		.subdevice    = 0x6704,
+		.driver_data  = SAA7134_BOARD_HAUPPAUGE_HVR1110,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x0070,
+		.subdevice    = 0x6705,
+		.driver_data  = SAA7134_BOARD_HAUPPAUGE_HVR1110,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x0070,
+		.subdevice    = 0x6706,
+		.driver_data  = SAA7134_BOARD_HAUPPAUGE_HVR1150,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x0070,
+		.subdevice    = 0x6707,
+		.driver_data  = SAA7134_BOARD_HAUPPAUGE_HVR1120,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x0070,
+		.subdevice    = 0x6708,
+		.driver_data  = SAA7134_BOARD_HAUPPAUGE_HVR1150,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x0070,
+		.subdevice    = 0x6709,
+		.driver_data  = SAA7134_BOARD_HAUPPAUGE_HVR1120,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x0070,
+		.subdevice    = 0x670a,
+		.driver_data  = SAA7134_BOARD_HAUPPAUGE_HVR1120,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x153b,
+		.subdevice    = 0x1172,
+		.driver_data  = SAA7134_BOARD_CINERGY_HT_PCMCIA,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+		.subvendor    = PCI_VENDOR_ID_PHILIPS,
+		.subdevice    = 0x2342,
+		.driver_data  = SAA7134_BOARD_ENCORE_ENLTV,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+		.subvendor    = 0x1131,
+		.subdevice    = 0x2341,
+		.driver_data  = SAA7134_BOARD_ENCORE_ENLTV,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+		.subvendor    = 0x3016,
+		.subdevice    = 0x2344,
+		.driver_data  = SAA7134_BOARD_ENCORE_ENLTV,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+		.subvendor    = 0x1131,
+		.subdevice    = 0x230f,
+		.driver_data  = SAA7134_BOARD_ENCORE_ENLTV_FM,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+		.subvendor    = 0x1a7f,
+		.subdevice    = 0x2008,
+		.driver_data  = SAA7134_BOARD_ENCORE_ENLTV_FM53,
+	}, {
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = 0x1a7f,
+		.subdevice    = 0x2108,
+		.driver_data  = SAA7134_BOARD_ENCORE_ENLTV_FM3,
+	}, {
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x153b,
+		.subdevice    = 0x1175,
+		.driver_data  = SAA7134_BOARD_CINERGY_HT_PCI,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x1461, /* Avermedia Technologies Inc */
+		.subdevice    = 0xf31e,
+		.driver_data  = SAA7134_BOARD_AVERMEDIA_M102,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x4E42,         /* MSI */
+		.subdevice    = 0x0306,         /* TV@nywhere DUO */
+		.driver_data  = SAA7134_BOARD_FLYDVBTDUO,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x1043,
+		.subdevice    = 0x4871,
+		.driver_data  = SAA7134_BOARD_ASUS_P7131_4871,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x1043,
+		.subdevice    = 0x4857,		/* REV:1.00 */
+		.driver_data  = SAA7134_BOARD_ASUSTeK_TIGER,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = 0x0919, /* SinoVideo PCI 2309 Proteus (7134) */
+		.subdevice    = 0x2003, /* OEM cardbus */
+		.driver_data  = SAA7134_BOARD_SABRENT_TV_PCB05,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+		.subvendor    = PCI_VENDOR_ID_PHILIPS,
+		.subdevice    = 0x2304,
+		.driver_data  = SAA7134_BOARD_10MOONSTVMASTER3,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x1461, /* Avermedia Technologies Inc */
+		.subdevice    = 0xf01d, /* AVerTV DVB-T Super 007 */
+		.driver_data  = SAA7134_BOARD_AVERMEDIA_SUPER_007,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+		.subvendor    = 0x0000,
+		.subdevice    = 0x4016,
+		.driver_data  = SAA7134_BOARD_BEHOLD_401,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = 0x0000,
+		.subdevice    = 0x4036,
+		.driver_data  = SAA7134_BOARD_BEHOLD_403,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = 0x0000,
+		.subdevice    = 0x4037,
+		.driver_data  = SAA7134_BOARD_BEHOLD_403FM,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+		.subvendor    = 0x0000,
+		.subdevice    = 0x4050,
+		.driver_data  = SAA7134_BOARD_BEHOLD_405,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+		.subvendor    = 0x0000,
+		.subdevice    = 0x4051,
+		.driver_data  = SAA7134_BOARD_BEHOLD_405FM,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = 0x0000,
+		.subdevice    = 0x4070,
+		.driver_data  = SAA7134_BOARD_BEHOLD_407,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = 0x0000,
+		.subdevice    = 0x4071,
+		.driver_data  = SAA7134_BOARD_BEHOLD_407FM,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x0000,
+		.subdevice    = 0x4090,
+		.driver_data  = SAA7134_BOARD_BEHOLD_409,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+		.subvendor    = 0x0000,
+		.subdevice    = 0x505B,
+		.driver_data  = SAA7134_BOARD_BEHOLD_505RDS_MK5,
+	}, {
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+		.subvendor    = 0x0000,
+		.subdevice    = 0x5051,
+		.driver_data  = SAA7134_BOARD_BEHOLD_505RDS_MK3,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+		.subvendor    = 0x5ace,
+		.subdevice    = 0x5050,
+		.driver_data  = SAA7134_BOARD_BEHOLD_505FM,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x0000,
+		.subdevice    = 0x5071,
+		.driver_data  = SAA7134_BOARD_BEHOLD_507RDS_MK3,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x0000,
+		.subdevice    = 0x507B,
+		.driver_data  = SAA7134_BOARD_BEHOLD_507RDS_MK5,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = 0x5ace,
+		.subdevice    = 0x5070,
+		.driver_data  = SAA7134_BOARD_BEHOLD_507_9FM,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x5ace,
+		.subdevice    = 0x5090,
+		.driver_data  = SAA7134_BOARD_BEHOLD_507_9FM,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x0000,
+		.subdevice    = 0x5201,
+		.driver_data  = SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = 0x5ace,
+		.subdevice    = 0x6070,
+		.driver_data  = SAA7134_BOARD_BEHOLD_607FM_MK3,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = 0x5ace,
+		.subdevice    = 0x6071,
+		.driver_data  = SAA7134_BOARD_BEHOLD_607FM_MK5,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = 0x5ace,
+		.subdevice    = 0x6072,
+		.driver_data  = SAA7134_BOARD_BEHOLD_607RDS_MK3,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = 0x5ace,
+		.subdevice    = 0x6073,
+		.driver_data  = SAA7134_BOARD_BEHOLD_607RDS_MK5,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x5ace,
+		.subdevice    = 0x6090,
+		.driver_data  = SAA7134_BOARD_BEHOLD_609FM_MK3,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x5ace,
+		.subdevice    = 0x6091,
+		.driver_data  = SAA7134_BOARD_BEHOLD_609FM_MK5,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x5ace,
+		.subdevice    = 0x6092,
+		.driver_data  = SAA7134_BOARD_BEHOLD_609RDS_MK3,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x5ace,
+		.subdevice    = 0x6093,
+		.driver_data  = SAA7134_BOARD_BEHOLD_609RDS_MK5,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x5ace,
+		.subdevice    = 0x6190,
+		.driver_data  = SAA7134_BOARD_BEHOLD_M6,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x5ace,
+		.subdevice    = 0x6193,
+		.driver_data  = SAA7134_BOARD_BEHOLD_M6_EXTRA,
+	}, {
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x5ace,
+		.subdevice    = 0x6191,
+		.driver_data  = SAA7134_BOARD_BEHOLD_M63,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x4e42,
+		.subdevice    = 0x3502,
+		.driver_data  = SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS,
+	}, {
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x1822, /*Twinhan Technology Co. Ltd*/
+		.subdevice    = 0x0022,
+		.driver_data  = SAA7134_BOARD_TWINHAN_DTV_DVB_3056,
+	}, {
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x16be,
+		.subdevice    = 0x0010, /* Medion version CTX953_V.1.4.3 */
+		.driver_data  = SAA7134_BOARD_CREATIX_CTX953,
+	}, {
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x1462, /* MSI */
+		.subdevice    = 0x8625, /* TV@nywhere A/D v1.1 */
+		.driver_data  = SAA7134_BOARD_MSI_TVANYWHERE_AD11,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x1461, /* Avermedia Technologies Inc */
+		.subdevice    = 0xf436,
+		.driver_data  = SAA7134_BOARD_AVERMEDIA_CARDBUS_506,
+	}, {
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x1461, /* Avermedia Technologies Inc */
+		.subdevice    = 0xf936,
+		.driver_data  = SAA7134_BOARD_AVERMEDIA_A16D,
+	}, {
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x1461, /* Avermedia Technologies Inc */
+		.subdevice    = 0xa836,
+		.driver_data  = SAA7134_BOARD_AVERMEDIA_M115,
+	}, {
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x185b,
+		.subdevice    = 0xc900,
+		.driver_data  = SAA7134_BOARD_VIDEOMATE_T750,
+	}, {
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133, /* SAA7135HL */
+		.subvendor    = 0x1421,
+		.subdevice    = 0x0380,
+		.driver_data  = SAA7134_BOARD_ADS_INSTANT_HDTV_PCI,
+	}, {
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x5169,
+		.subdevice    = 0x1502,
+		.driver_data  = SAA7134_BOARD_FLYTVPLATINUM_MINI,
+	}, {
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x5ace,
+		.subdevice    = 0x6290,
+		.driver_data  = SAA7134_BOARD_BEHOLD_H6,
+	}, {
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x1461, /* Avermedia Technologies Inc */
+		.subdevice    = 0xf636,
+		.driver_data  = SAA7134_BOARD_AVERMEDIA_M103,
+	}, {
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x1461, /* Avermedia Technologies Inc */
+		.subdevice    = 0xf736,
+		.driver_data  = SAA7134_BOARD_AVERMEDIA_M103,
+	}, {
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x1043,
+		.subdevice    = 0x4878, /* REV:1.02G */
+		.driver_data  = SAA7134_BOARD_ASUSTeK_TIGER_3IN1,
+	}, {
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x1043,
+		.subdevice    = 0x48cd,
+		.driver_data  = SAA7134_BOARD_ASUSTeK_PS3_100,
+	}, {
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = 0x17de,
+		.subdevice    = 0x7128,
+		.driver_data  = SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG,
+	}, {
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x17de,
+		.subdevice    = 0xb136,
+		.driver_data  = SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG,
+	}, {
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x1461, /* Avermedia Technologies Inc */
+		.subdevice    = 0xf31d,
+		.driver_data  = SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS,
+	}, {
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+		.subvendor    = 0x185b,
+		.subdevice    = 0xc900,
+		.driver_data  = SAA7134_BOARD_VIDEOMATE_S350,
+	}, {
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x5ace, /* Beholder Intl. Ltd. */
+		.subdevice    = 0x7595,
+		.driver_data  = SAA7134_BOARD_BEHOLD_X7,
+	}, {
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = 0x19d1, /* RoverMedia */
+		.subdevice    = 0x0138, /* LifeView FlyTV Prime30 OEM */
+		.driver_data  = SAA7134_BOARD_ROVERMEDIA_LINK_PRO_FM,
+	}, {
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = PCI_VENDOR_ID_PHILIPS,
+		.subdevice    = 0x2004,
+		.driver_data  = SAA7134_BOARD_ZOLID_HYBRID_PCI,
+	}, {
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = 0x1043,
+		.subdevice    = 0x4847,
+		.driver_data  = SAA7134_BOARD_ASUS_EUROPA_HYBRID,
+	}, {
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+		.subvendor    = 0x107d,
+		.subdevice    = 0x6655,
+		.driver_data  = SAA7134_BOARD_LEADTEK_WINFAST_DTV1000S,
+	}, {
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x13c2,
+		.subdevice    = 0x2804,
+		.driver_data  = SAA7134_BOARD_TECHNOTREND_BUDGET_T3000,
+	}, {
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x5ace, /* Beholder Intl. Ltd. */
+		.subdevice    = 0x7190,
+		.driver_data  = SAA7134_BOARD_BEHOLD_H7,
+	}, {
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x5ace, /* Beholder Intl. Ltd. */
+		.subdevice    = 0x7090,
+		.driver_data  = SAA7134_BOARD_BEHOLD_A7,
+	}, {
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7135,
+		.subvendor    = 0x185b,
+		.subdevice    = 0xc900,
+		.driver_data  = SAA7134_BOARD_VIDEOMATE_M1F,
+	}, {
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x5ace,
+		.subdevice    = 0x5030,
+		.driver_data  = SAA7134_BOARD_BEHOLD_503FM,
+	}, {
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+		.subvendor    = 0x5ace,
+		.subdevice    = 0x5010,
+		.driver_data  = SAA7134_BOARD_BEHOLD_501,
+	}, {
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = 0x17de,
+		.subdevice    = 0xd136,
+		.driver_data  = SAA7134_BOARD_MAGICPRO_PROHDTV_PRO2,
+	}, {
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x6000,
+		.subdevice    = 0x0811,
+		.driver_data  = SAA7134_BOARD_SENSORAY811_911,
+	}, {
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x6000,
+		.subdevice    = 0x0911,
+		.driver_data  = SAA7134_BOARD_SENSORAY811_911,
+	}, {
+		/* --- boards without eeprom + subsystem ID --- */
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = PCI_VENDOR_ID_PHILIPS,
+		.subdevice    = 0,
+		.driver_data  = SAA7134_BOARD_NOAUTO,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+		.subvendor    = PCI_VENDOR_ID_PHILIPS,
+		.subdevice    = 0,
+		.driver_data  = SAA7134_BOARD_NOAUTO,
+	},{
+		/* --- default catch --- */
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7130,
+		.subvendor    = PCI_ANY_ID,
+		.subdevice    = PCI_ANY_ID,
+		.driver_data  = SAA7134_BOARD_UNKNOWN,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = PCI_ANY_ID,
+		.subdevice    = PCI_ANY_ID,
+		.driver_data  = SAA7134_BOARD_UNKNOWN,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = PCI_ANY_ID,
+		.subdevice    = PCI_ANY_ID,
+		.driver_data  = SAA7134_BOARD_UNKNOWN,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7135,
+		.subvendor    = PCI_ANY_ID,
+		.subdevice    = PCI_ANY_ID,
+		.driver_data  = SAA7134_BOARD_UNKNOWN,
+	},{
+		/* --- end of list --- */
+	}
+};
+MODULE_DEVICE_TABLE(pci, saa7134_pci_tbl);
+
+/* ----------------------------------------------------------- */
+/* flyvideo tweaks                                             */
+
+
+static void board_flyvideo(struct saa7134_dev *dev)
+{
+	printk("%s: there are different flyvideo cards with different tuners\n"
+	       "%s: out there, you might have to use the tuner=<nr> insmod\n"
+	       "%s: option to override the default value.\n",
+	       dev->name, dev->name, dev->name);
+}
+
+static int saa7134_xc2028_callback(struct saa7134_dev *dev,
+				   int command, int arg)
+{
+	switch (command) {
+	case XC2028_TUNER_RESET:
+		saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x00008000, 0x00000000);
+		saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x00008000, 0x00008000);
+		switch (dev->board) {
+		case SAA7134_BOARD_AVERMEDIA_CARDBUS_506:
+		case SAA7134_BOARD_AVERMEDIA_M103:
+			saa7134_set_gpio(dev, 23, 0);
+			msleep(10);
+			saa7134_set_gpio(dev, 23, 1);
+		break;
+		case SAA7134_BOARD_AVERMEDIA_A16D:
+			saa7134_set_gpio(dev, 21, 0);
+			msleep(10);
+			saa7134_set_gpio(dev, 21, 1);
+		break;
+		case SAA7134_BOARD_AVERMEDIA_A700_HYBRID:
+			saa7134_set_gpio(dev, 18, 0);
+			msleep(10);
+			saa7134_set_gpio(dev, 18, 1);
+		break;
+		case SAA7134_BOARD_VIDEOMATE_T750:
+			saa7134_set_gpio(dev, 20, 0);
+			msleep(10);
+			saa7134_set_gpio(dev, 20, 1);
+		break;
+		}
+	return 0;
+	}
+	return -EINVAL;
+}
+
+static int saa7134_xc5000_callback(struct saa7134_dev *dev,
+				   int command, int arg)
+{
+	switch (dev->board) {
+	case SAA7134_BOARD_BEHOLD_X7:
+	case SAA7134_BOARD_BEHOLD_H7:
+	case SAA7134_BOARD_BEHOLD_A7:
+		if (command == XC5000_TUNER_RESET) {
+		/* Down and UP pheripherial RESET pin for reset all chips */
+			saa_writeb(SAA7134_SPECIAL_MODE, 0x00);
+			msleep(10);
+			saa_writeb(SAA7134_SPECIAL_MODE, 0x01);
+			msleep(10);
+		}
+		break;
+	default:
+		saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x06e20000, 0x06e20000);
+		saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x06a20000, 0x06a20000);
+		saa_andorl(SAA7133_ANALOG_IO_SELECT >> 2, 0x02, 0x02);
+		saa_andorl(SAA7134_ANALOG_IN_CTRL1 >> 2, 0x81, 0x81);
+		saa_andorl(SAA7134_AUDIO_CLOCK0 >> 2, 0x03187de7, 0x03187de7);
+		saa_andorl(SAA7134_AUDIO_PLL_CTRL >> 2, 0x03, 0x03);
+		saa_andorl(SAA7134_AUDIO_CLOCKS_PER_FIELD0 >> 2,
+			   0x0001e000, 0x0001e000);
+		break;
+	}
+	return 0;
+}
+
+static int saa7134_tda8290_827x_callback(struct saa7134_dev *dev,
+					 int command, int arg)
+{
+	u8 sync_control;
+
+	switch (command) {
+	case 0: /* switch LNA gain through GPIO 22*/
+		saa7134_set_gpio(dev, 22, arg) ;
+		break;
+	case 1: /* vsync output at GPIO22. 50 / 60Hz */
+		saa_andorb(SAA7134_VIDEO_PORT_CTRL3, 0x80, 0x80);
+		saa_andorb(SAA7134_VIDEO_PORT_CTRL6, 0x0f, 0x03);
+		if (arg == 1)
+			sync_control = 11;
+		else
+			sync_control = 17;
+		saa_writeb(SAA7134_VGATE_START, sync_control);
+		saa_writeb(SAA7134_VGATE_STOP, sync_control + 1);
+		saa_andorb(SAA7134_MISC_VGATE_MSB, 0x03, 0x00);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	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 inline int saa7134_kworld_sbtvd_toggle_agc(struct saa7134_dev *dev,
+						  enum tda18271_mode mode)
+{
+	/* toggle AGC switch through GPIO 27 */
+	switch (mode) {
+	case TDA18271_ANALOG:
+		saa_writel(SAA7134_GPIO_GPMODE0 >> 2, 0x4000);
+		saa_writel(SAA7134_GPIO_GPSTATUS0 >> 2, 0x4000);
+		msleep(20);
+		break;
+	case TDA18271_DIGITAL:
+		saa_writel(SAA7134_GPIO_GPMODE0 >> 2, 0x14000);
+		saa_writel(SAA7134_GPIO_GPSTATUS0 >> 2, 0x14000);
+		msleep(20);
+		saa_writel(SAA7134_GPIO_GPMODE0 >> 2, 0x54000);
+		saa_writel(SAA7134_GPIO_GPSTATUS0 >> 2, 0x54000);
+		msleep(30);
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int saa7134_kworld_pc150u_toggle_agc(struct saa7134_dev *dev,
+					    enum tda18271_mode mode)
+{
+	switch (mode) {
+	case TDA18271_ANALOG:
+		saa7134_set_gpio(dev, 18, 0);
+		break;
+	case TDA18271_DIGITAL:
+		saa7134_set_gpio(dev, 18, 1);
+		msleep(30);
+		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_HVR1150:
+		case SAA7134_BOARD_HAUPPAUGE_HVR1120:
+		case SAA7134_BOARD_MAGICPRO_PROHDTV_PRO2:
+			ret = saa7134_tda18271_hvr11x0_toggle_agc(dev, arg);
+			break;
+		case SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG:
+			ret = saa7134_kworld_sbtvd_toggle_agc(dev, arg);
+			break;
+		case SAA7134_BOARD_KWORLD_PC150U:
+			ret = saa7134_kworld_pc150u_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_HVR1150:
+	case SAA7134_BOARD_HAUPPAUGE_HVR1120:
+	case SAA7134_BOARD_AVERMEDIA_M733A:
+	case SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG:
+	case SAA7134_BOARD_KWORLD_PC150U:
+	case SAA7134_BOARD_MAGICPRO_PROHDTV_PRO2:
+		/* 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;
+
+	if (dev != NULL) {
+		switch (dev->tuner_type) {
+		case TUNER_PHILIPS_TDA8290:
+			return saa7134_tda8290_callback(dev, command, arg);
+		case TUNER_XC2028:
+			return saa7134_xc2028_callback(dev, command, arg);
+		case TUNER_XC5000:
+			return saa7134_xc5000_callback(dev, command, arg);
+		}
+	} else {
+		printk(KERN_ERR "saa7134: Error - device struct undefined.\n");
+		return -EINVAL;
+	}
+	return -EINVAL;
+}
+EXPORT_SYMBOL(saa7134_tuner_callback);
+
+/* ----------------------------------------------------------- */
+
+static void hauppauge_eeprom(struct saa7134_dev *dev, u8 *eeprom_data)
+{
+	struct tveeprom tv;
+
+	tveeprom_hauppauge_analog(&dev->i2c_client, &tv, eeprom_data);
+
+	/* Make sure we support the board model */
+	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-HVR1150 (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-HVR1150 (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: "
+		       "unknown hauppauge model #%d\n", dev->name, tv.model);
+		break;
+	}
+
+	printk(KERN_INFO "%s: hauppauge eeprom: model=%d\n",
+	       dev->name, tv.model);
+}
+
+/* ----------------------------------------------------------- */
+
+int saa7134_board_init1(struct saa7134_dev *dev)
+{
+	/* Always print gpio, often manufacturers encode tuner type and other info. */
+	saa_writel(SAA7134_GPIO_GPMODE0 >> 2, 0);
+	dev->gpio_value = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2);
+	printk(KERN_INFO "%s: board init: gpio is %x\n", dev->name, dev->gpio_value);
+
+	switch (dev->board) {
+	case SAA7134_BOARD_FLYVIDEO2000:
+	case SAA7134_BOARD_FLYVIDEO3000:
+	case SAA7134_BOARD_FLYVIDEO3000_NTSC:
+		dev->has_remote = SAA7134_REMOTE_GPIO;
+		board_flyvideo(dev);
+		break;
+	case SAA7134_BOARD_FLYTVPLATINUM_MINI2:
+	case SAA7134_BOARD_FLYTVPLATINUM_FM:
+	case SAA7134_BOARD_CINERGY400:
+	case SAA7134_BOARD_CINERGY600:
+	case SAA7134_BOARD_CINERGY600_MK3:
+	case SAA7134_BOARD_ECS_TVP3XP:
+	case SAA7134_BOARD_ECS_TVP3XP_4CB5:
+	case SAA7134_BOARD_ECS_TVP3XP_4CB6:
+	case SAA7134_BOARD_MD2819:
+	case SAA7134_BOARD_KWORLD_VSTREAM_XPERT:
+	case SAA7134_BOARD_KWORLD_XPERT:
+	case SAA7134_BOARD_AVERMEDIA_STUDIO_305:
+	case SAA7134_BOARD_AVERMEDIA_STUDIO_505:
+	case SAA7134_BOARD_AVERMEDIA_305:
+	case SAA7134_BOARD_AVERMEDIA_STUDIO_307:
+	case SAA7134_BOARD_AVERMEDIA_307:
+	case SAA7134_BOARD_AVERMEDIA_STUDIO_507:
+	case SAA7134_BOARD_AVERMEDIA_GO_007_FM:
+	case SAA7134_BOARD_AVERMEDIA_777:
+	case SAA7134_BOARD_AVERMEDIA_M135A:
+/*      case SAA7134_BOARD_SABRENT_SBTTVFM:  */ /* not finished yet */
+	case SAA7134_BOARD_VIDEOMATE_TV_PVR:
+	case SAA7134_BOARD_VIDEOMATE_GOLD_PLUS:
+	case SAA7134_BOARD_VIDEOMATE_TV_GOLD_PLUSII:
+	case SAA7134_BOARD_VIDEOMATE_M1F:
+	case SAA7134_BOARD_VIDEOMATE_DVBT_300:
+	case SAA7134_BOARD_VIDEOMATE_DVBT_200:
+	case SAA7134_BOARD_VIDEOMATE_DVBT_200A:
+	case SAA7134_BOARD_MANLI_MTV001:
+	case SAA7134_BOARD_MANLI_MTV002:
+	case SAA7134_BOARD_BEHOLD_409FM:
+	case SAA7134_BOARD_AVACSSMARTTV:
+	case SAA7134_BOARD_GOTVIEW_7135:
+	case SAA7134_BOARD_KWORLD_TERMINATOR:
+	case SAA7134_BOARD_SEDNA_PC_TV_CARDBUS:
+	case SAA7134_BOARD_FLYDVBT_LR301:
+	case SAA7134_BOARD_ASUSTeK_PS3_100:
+	case SAA7134_BOARD_ASUSTeK_P7131_DUAL:
+	case SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA:
+	case SAA7134_BOARD_ASUSTeK_P7131_ANALOG:
+	case SAA7134_BOARD_FLYDVBTDUO:
+	case SAA7134_BOARD_PROTEUS_2309:
+	case SAA7134_BOARD_AVERMEDIA_A16AR:
+	case SAA7134_BOARD_ENCORE_ENLTV:
+	case SAA7134_BOARD_ENCORE_ENLTV_FM:
+	case SAA7134_BOARD_ENCORE_ENLTV_FM53:
+	case SAA7134_BOARD_ENCORE_ENLTV_FM3:
+	case SAA7134_BOARD_10MOONSTVMASTER3:
+	case SAA7134_BOARD_BEHOLD_401:
+	case SAA7134_BOARD_BEHOLD_403:
+	case SAA7134_BOARD_BEHOLD_403FM:
+	case SAA7134_BOARD_BEHOLD_405:
+	case SAA7134_BOARD_BEHOLD_405FM:
+	case SAA7134_BOARD_BEHOLD_407:
+	case SAA7134_BOARD_BEHOLD_407FM:
+	case SAA7134_BOARD_BEHOLD_409:
+	case SAA7134_BOARD_BEHOLD_505FM:
+	case SAA7134_BOARD_BEHOLD_505RDS_MK5:
+	case SAA7134_BOARD_BEHOLD_505RDS_MK3:
+	case SAA7134_BOARD_BEHOLD_507_9FM:
+	case SAA7134_BOARD_BEHOLD_507RDS_MK3:
+	case SAA7134_BOARD_BEHOLD_507RDS_MK5:
+	case SAA7134_BOARD_GENIUS_TVGO_A11MCE:
+	case SAA7134_BOARD_REAL_ANGEL_220:
+	case SAA7134_BOARD_KWORLD_PLUS_TV_ANALOG:
+	case SAA7134_BOARD_AVERMEDIA_GO_007_FM_PLUS:
+	case SAA7134_BOARD_ROVERMEDIA_LINK_PRO_FM:
+	case SAA7134_BOARD_LEADTEK_WINFAST_DTV1000S:
+		dev->has_remote = SAA7134_REMOTE_GPIO;
+		break;
+	case SAA7134_BOARD_FLYDVBS_LR300:
+		saa_writeb(SAA7134_GPIO_GPMODE3, 0x80);
+		saa_writeb(SAA7134_GPIO_GPSTATUS2, 0x40);
+		dev->has_remote = SAA7134_REMOTE_GPIO;
+		break;
+	case SAA7134_BOARD_MD5044:
+		printk("%s: seems there are two different versions of the MD5044\n"
+		       "%s: (with the same ID) out there.  If sound doesn't work for\n"
+		       "%s: you try the audio_clock_override=0x200000 insmod option.\n",
+		       dev->name,dev->name,dev->name);
+		break;
+	case SAA7134_BOARD_CINERGY400_CARDBUS:
+		/* power-up tuner chip */
+		saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0x00040000, 0x00040000);
+		saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x00040000, 0x00000000);
+		break;
+	case SAA7134_BOARD_PINNACLE_300I_DVBT_PAL:
+		/* this turns the remote control chip off to work around a bug in it */
+		saa_writeb(SAA7134_GPIO_GPMODE1, 0x80);
+		saa_writeb(SAA7134_GPIO_GPSTATUS1, 0x80);
+		break;
+	case SAA7134_BOARD_MONSTERTV_MOBILE:
+		/* power-up tuner chip */
+		saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0x00040000, 0x00040000);
+		saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x00040000, 0x00000004);
+		break;
+	case SAA7134_BOARD_FLYDVBT_DUO_CARDBUS:
+		/* turn the fan on */
+		saa_writeb(SAA7134_GPIO_GPMODE3, 0x08);
+		saa_writeb(SAA7134_GPIO_GPSTATUS3, 0x06);
+		break;
+	case SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331:
+	case SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS:
+		saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x08000000, 0x08000000);
+		saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x08000000, 0x00000000);
+		break;
+	case SAA7134_BOARD_AVERMEDIA_CARDBUS:
+	case SAA7134_BOARD_AVERMEDIA_M115:
+		/* power-down tuner chip */
+		saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0xffffffff, 0);
+		saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0xffffffff, 0);
+		msleep(10);
+		/* power-up tuner chip */
+		saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0xffffffff, 0xffffffff);
+		saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0xffffffff, 0xffffffff);
+		msleep(10);
+		break;
+	case SAA7134_BOARD_AVERMEDIA_CARDBUS_501:
+		/* power-down tuner chip */
+		saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0x08400000, 0x08400000);
+		saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x08400000, 0);
+		msleep(10);
+		saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0x08400000, 0x08400000);
+		saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x08400000, 0x08400000);
+		msleep(10);
+		dev->has_remote = SAA7134_REMOTE_I2C;
+		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);
+		saa7134_set_gpio(dev, 23, 1);
+		break;
+	case SAA7134_BOARD_AVERMEDIA_A16D:
+		saa7134_set_gpio(dev, 21, 0);
+		msleep(10);
+		saa7134_set_gpio(dev, 21, 1);
+		msleep(1);
+		dev->has_remote = SAA7134_REMOTE_GPIO;
+		break;
+	case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM:
+		/* power-down tuner chip */
+		saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0x000A8004, 0x000A8004);
+		saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x000A8004, 0);
+		msleep(10);
+		/* power-up tuner chip */
+		saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0x000A8004, 0x000A8004);
+		saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x000A8004, 0x000A8004);
+		msleep(10);
+		/* remote via GPIO */
+		dev->has_remote = SAA7134_REMOTE_GPIO;
+		break;
+	case SAA7134_BOARD_RTD_VFG7350:
+
+		/*
+		 * Make sure Production Test Register at offset 0x1D1 is cleared
+		 * to take chip out of test mode.  Clearing bit 4 (TST_EN_AOUT)
+		 * prevents pin 105 from remaining low; keeping pin 105 low
+		 * continually resets the SAA6752 chip.
+		 */
+
+		saa_writeb (SAA7134_PRODUCTION_TEST_MODE, 0x00);
+		break;
+	case SAA7134_BOARD_HAUPPAUGE_HVR1150:
+	case SAA7134_BOARD_HAUPPAUGE_HVR1120:
+		dev->has_remote = SAA7134_REMOTE_GPIO;
+		/* 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:
+	case SAA7134_BOARD_UPMOST_PURPLE_TV:
+	case SAA7134_BOARD_MSI_TVATANYWHERE_PLUS:
+	case SAA7134_BOARD_HAUPPAUGE_HVR1110:
+	case SAA7134_BOARD_BEHOLD_607FM_MK3:
+	case SAA7134_BOARD_BEHOLD_607FM_MK5:
+	case SAA7134_BOARD_BEHOLD_609FM_MK3:
+	case SAA7134_BOARD_BEHOLD_609FM_MK5:
+	case SAA7134_BOARD_BEHOLD_607RDS_MK3:
+	case SAA7134_BOARD_BEHOLD_607RDS_MK5:
+	case SAA7134_BOARD_BEHOLD_609RDS_MK3:
+	case SAA7134_BOARD_BEHOLD_609RDS_MK5:
+	case SAA7134_BOARD_BEHOLD_M6:
+	case SAA7134_BOARD_BEHOLD_M63:
+	case SAA7134_BOARD_BEHOLD_M6_EXTRA:
+	case SAA7134_BOARD_BEHOLD_H6:
+	case SAA7134_BOARD_BEHOLD_X7:
+	case SAA7134_BOARD_BEHOLD_H7:
+	case SAA7134_BOARD_BEHOLD_A7:
+	case SAA7134_BOARD_KWORLD_PC150U:
+		dev->has_remote = SAA7134_REMOTE_I2C;
+		break;
+	case SAA7134_BOARD_AVERMEDIA_A169_B:
+		printk("%s: %s: dual saa713x broadcast decoders\n"
+		       "%s: Sorry, none of the inputs to this chip are supported yet.\n"
+		       "%s: Dual decoder functionality is disabled for now, use the other chip.\n",
+		       dev->name,card(dev).name,dev->name,dev->name);
+		break;
+	case SAA7134_BOARD_AVERMEDIA_M102:
+		/* enable tuner */
+	       dev->has_remote = SAA7134_REMOTE_GPIO;
+		saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0x8c040007, 0x8c040007);
+		saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x0c0007cd, 0x0c0007cd);
+		break;
+	case SAA7134_BOARD_AVERMEDIA_A700_HYBRID:
+	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);
+		break;
+	case SAA7134_BOARD_VIDEOMATE_S350:
+		dev->has_remote = SAA7134_REMOTE_GPIO;
+		saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0x0000C000, 0x0000C000);
+		saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x0000C000, 0x0000C000);
+		break;
+	case SAA7134_BOARD_AVERMEDIA_M733A:
+		saa7134_set_gpio(dev, 1, 1);
+		msleep(10);
+		saa7134_set_gpio(dev, 1, 0);
+		msleep(10);
+		saa7134_set_gpio(dev, 1, 1);
+		dev->has_remote = SAA7134_REMOTE_GPIO;
+		break;
+	case SAA7134_BOARD_MAGICPRO_PROHDTV_PRO2:
+		/* enable LGS-8G75 */
+		saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0x0e050000, 0x0c050000);
+		saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x0e050000, 0x0c050000);
+		break;
+	case SAA7134_BOARD_VIDEOMATE_T750:
+		/* enable the analog tuner */
+		saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0x00008000, 0x00008000);
+		saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x00008000, 0x00008000);
+		break;
+	}
+	return 0;
+}
+
+static void saa7134_tuner_setup(struct saa7134_dev *dev)
+{
+	struct tuner_setup tun_setup;
+	unsigned int mode_mask = T_RADIO | T_ANALOG_TV;
+
+	memset(&tun_setup, 0, sizeof(tun_setup));
+	tun_setup.tuner_callback = saa7134_tuner_callback;
+
+	if (saa7134_boards[dev->board].radio_type != UNSET) {
+		tun_setup.type = saa7134_boards[dev->board].radio_type;
+		tun_setup.addr = saa7134_boards[dev->board].radio_addr;
+
+		tun_setup.mode_mask = T_RADIO;
+
+		saa_call_all(dev, tuner, s_type_addr, &tun_setup);
+		mode_mask &= ~T_RADIO;
+	}
+
+	if ((dev->tuner_type != TUNER_ABSENT) && (dev->tuner_type != UNSET)) {
+		tun_setup.type = dev->tuner_type;
+		tun_setup.addr = dev->tuner_addr;
+		tun_setup.config = saa7134_boards[dev->board].tuner_config;
+		tun_setup.tuner_callback = saa7134_tuner_callback;
+
+		tun_setup.mode_mask = mode_mask;
+
+		saa_call_all(dev, tuner, s_type_addr, &tun_setup);
+	}
+
+	if (dev->tda9887_conf) {
+		struct v4l2_priv_tun_config tda9887_cfg;
+
+		tda9887_cfg.tuner = TUNER_TDA9887;
+		tda9887_cfg.priv = &dev->tda9887_conf;
+
+		saa_call_all(dev, tuner, s_config, &tda9887_cfg);
+	}
+
+	if (dev->tuner_type == TUNER_XC2028) {
+		struct v4l2_priv_tun_config  xc2028_cfg;
+		struct xc2028_ctrl           ctl;
+
+		memset(&xc2028_cfg, 0, sizeof(xc2028_cfg));
+		memset(&ctl, 0, sizeof(ctl));
+
+		ctl.fname   = XC2028_DEFAULT_FIRMWARE;
+		ctl.max_len = 64;
+
+		switch (dev->board) {
+		case SAA7134_BOARD_AVERMEDIA_A16D:
+		case SAA7134_BOARD_AVERMEDIA_CARDBUS_506:
+		case SAA7134_BOARD_AVERMEDIA_M103:
+		case SAA7134_BOARD_AVERMEDIA_A700_HYBRID:
+			ctl.demod = XC3028_FE_ZARLINK456;
+			break;
+		default:
+			ctl.demod = XC3028_FE_OREN538;
+			ctl.mts = 1;
+		}
+
+		xc2028_cfg.tuner = TUNER_XC2028;
+		xc2028_cfg.priv  = &ctl;
+
+		saa_call_all(dev, tuner, s_config, &xc2028_cfg);
+	}
+}
+
+/* stuff which needs working i2c */
+int saa7134_board_init2(struct saa7134_dev *dev)
+{
+	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
+			: SAA7134_BOARD_BMK_MPEX_TUNER;
+		if (board == dev->board)
+			break;
+		dev->board = board;
+		printk("%s: board type fixup: %s\n", dev->name,
+		saa7134_boards[dev->board].name);
+		dev->tuner_type = saa7134_boards[dev->board].tuner_type;
+
+		break;
+	case SAA7134_BOARD_MD7134:
+	{
+		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");
+		} else if ((data[0] != 0) && (data[0] != 0xff)) {
+			/* old config structure */
+			subaddr = data[0] + 2;
+			msg[1].len = 2;
+			i2c_transfer(&dev->i2c_adap, msg, 2);
+			tuner_t = (data[0] << 8) + data[1];
+			switch (tuner_t){
+			case 0x0103:
+				dev->tuner_type = TUNER_PHILIPS_PAL;
+				break;
+			case 0x010C:
+				dev->tuner_type = TUNER_PHILIPS_FM1216ME_MK3;
+				break;
+			default:
+				printk(KERN_ERR "%s Can't determine tuner type %x from EEPROM\n", dev->name, tuner_t);
+			}
+		} else if ((data[1] != 0) && (data[1] != 0xff)) {
+			/* new config structure */
+			subaddr = data[1] + 1;
+			msg[1].len = 1;
+			i2c_transfer(&dev->i2c_adap, msg, 2);
+			subaddr = data[0] + 1;
+			msg[1].len = 2;
+			i2c_transfer(&dev->i2c_adap, msg, 2);
+			tuner_t = (data[1] << 8) + data[0];
+			switch (tuner_t) {
+			case 0x0005:
+				dev->tuner_type = TUNER_PHILIPS_FM1216ME_MK3;
+				break;
+			case 0x001d:
+				dev->tuner_type = TUNER_PHILIPS_FMD1216ME_MK3;
+					printk(KERN_INFO "%s Board has DVB-T\n", dev->name);
+				break;
+			default:
+				printk(KERN_ERR "%s Can't determine tuner type %x from EEPROM\n", dev->name, tuner_t);
+			}
+		} else {
+			printk(KERN_ERR "%s unexpected config structure\n", dev->name);
+		}
+
+		printk(KERN_INFO "%s Tuner type is %d\n", dev->name, dev->tuner_type);
+		break;
+	}
+	case SAA7134_BOARD_PHILIPS_EUROPA:
+		if (dev->autodetected && (dev->eedata[0x41] == 0x1c)) {
+			/* Reconfigure board as Snake reference design */
+			dev->board = SAA7134_BOARD_PHILIPS_SNAKE;
+			dev->tuner_type = saa7134_boards[dev->board].tuner_type;
+			printk(KERN_INFO "%s: Reconfigured board as %s\n",
+				dev->name, saa7134_boards[dev->board].name);
+			break;
+		}
+		/* break intentionally omitted */
+	case SAA7134_BOARD_VIDEOMATE_DVBT_300:
+	case SAA7134_BOARD_ASUS_EUROPA2_HYBRID:
+	case SAA7134_BOARD_ASUS_EUROPA_HYBRID:
+	case SAA7134_BOARD_TECHNOTREND_BUDGET_T3000:
+	{
+
+		/* 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)};
+		i2c_transfer(&dev->i2c_adap, &msg, 1);
+
+		break;
+	}
+	case SAA7134_BOARD_PHILIPS_TIGER:
+	case SAA7134_BOARD_PHILIPS_TIGER_S:
+	{
+		u8 data[] = { 0x3c, 0x33, 0x60};
+		struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)};
+		if (dev->autodetected && (dev->eedata[0x49] == 0x50)) {
+			dev->board = SAA7134_BOARD_PHILIPS_TIGER_S;
+			printk(KERN_INFO "%s: Reconfigured board as %s\n",
+				dev->name, saa7134_boards[dev->board].name);
+		}
+		if (dev->board == SAA7134_BOARD_PHILIPS_TIGER_S) {
+			dev->tuner_type = TUNER_PHILIPS_TDA8290;
+
+			data[2] = 0x68;
+			i2c_transfer(&dev->i2c_adap, &msg, 1);
+			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 */
+	       if (dev->autodetected && (dev->eedata[0x27] == 0x03)) {
+		       dev->board = SAA7134_BOARD_ASUSTeK_P7131_ANALOG;
+		       printk(KERN_INFO "%s: P7131 analog only, using "
+						       "entry of %s\n",
+		       dev->name, saa7134_boards[dev->board].name);
+
+			/* IR init has already happened for other cards, so
+			 * we have to catch up. */
+			dev->has_remote = SAA7134_REMOTE_GPIO;
+			saa7134_input_init1(dev);
+	       }
+	       break;
+	case SAA7134_BOARD_HAUPPAUGE_HVR1150:
+	case SAA7134_BOARD_HAUPPAUGE_HVR1120:
+		hauppauge_eeprom(dev, dev->eedata+0x80);
+		break;
+	case SAA7134_BOARD_HAUPPAUGE_HVR1110:
+		hauppauge_eeprom(dev, dev->eedata+0x80);
+		/* break intentionally omitted */
+	case SAA7134_BOARD_PINNACLE_PCTV_310i:
+	case SAA7134_BOARD_KWORLD_DVBT_210:
+	case SAA7134_BOARD_TEVION_DVBT_220RF:
+	case SAA7134_BOARD_ASUSTeK_TIGER:
+	case SAA7134_BOARD_ASUSTeK_P7131_DUAL:
+	case SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA:
+	case SAA7134_BOARD_MEDION_MD8800_QUADRO:
+	case SAA7134_BOARD_AVERMEDIA_SUPER_007:
+	case SAA7134_BOARD_TWINHAN_DTV_DVB_3056:
+	case SAA7134_BOARD_CREATIX_CTX953:
+	{
+		/* this is a hybrid board, initialize to analog mode
+		 * and configure firmware eeprom address
+		 */
+		u8 data[] = { 0x3c, 0x33, 0x60};
+		struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)};
+		i2c_transfer(&dev->i2c_adap, &msg, 1);
+		break;
+	}
+	case SAA7134_BOARD_ASUSTeK_TIGER_3IN1:
+	{
+		u8 data[] = { 0x3c, 0x33, 0x60};
+		struct i2c_msg msg = {.addr = 0x0b, .flags = 0, .buf = data,
+							.len = sizeof(data)};
+		i2c_transfer(&dev->i2c_adap, &msg, 1);
+		break;
+	}
+	case SAA7134_BOARD_ASUSTeK_PS3_100:
+	{
+		u8 data[] = { 0x3c, 0x33, 0x60};
+		struct i2c_msg msg = {.addr = 0x0b, .flags = 0, .buf = data,
+						       .len = sizeof(data)};
+		i2c_transfer(&dev->i2c_adap, &msg, 1);
+		break;
+	}
+	case SAA7134_BOARD_FLYDVB_TRIO:
+	{
+		u8 temp = 0;
+		int rc;
+		u8 data[] = { 0x3c, 0x33, 0x62};
+		struct i2c_msg msg = {.addr=0x09, .flags=0, .buf=data, .len = sizeof(data)};
+		i2c_transfer(&dev->i2c_adap, &msg, 1);
+
+		/*
+		 * send weak up message to pic16C505 chip
+		 * @ LifeView FlyDVB Trio
+		 */
+		msg.buf = &temp;
+		msg.addr = 0x0b;
+		msg.len = 1;
+		if (1 != i2c_transfer(&dev->i2c_adap, &msg, 1)) {
+			printk(KERN_WARNING "%s: send wake up byte to pic16C505"
+					"(IR chip) failed\n", dev->name);
+		} else {
+			msg.flags = I2C_M_RD;
+			rc = i2c_transfer(&dev->i2c_adap, &msg, 1);
+			printk(KERN_INFO "%s: probe IR chip @ i2c 0x%02x: %s\n",
+				   dev->name, msg.addr,
+				   (1 == rc) ? "yes" : "no");
+			if (rc == 1)
+				dev->has_remote = SAA7134_REMOTE_I2C;
+		}
+		break;
+	}
+	case SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331:
+	case SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS:
+	{
+		/* initialize analog mode  */
+		u8 data[] = { 0x3c, 0x33, 0x6a};
+		struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)};
+		i2c_transfer(&dev->i2c_adap, &msg, 1);
+		break;
+	}
+	case SAA7134_BOARD_CINERGY_HT_PCMCIA:
+	case SAA7134_BOARD_CINERGY_HT_PCI:
+	{
+		/* initialize analog mode */
+		u8 data[] = { 0x3c, 0x33, 0x68};
+		struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)};
+		i2c_transfer(&dev->i2c_adap, &msg, 1);
+		break;
+	}
+	case SAA7134_BOARD_VIDEOMATE_DVBT_200:
+	case SAA7134_BOARD_VIDEOMATE_DVBT_200A:
+		/* The T200 and the T200A share the same pci id.  Consequently,
+		 * we are going to query eeprom to try to find out which one we
+		 * are actually looking at. */
+
+		/* 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))
+			break;
+		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;
+			dev->tda9887_conf = saa7134_boards[dev->board].tda9887_conf;
+			printk(KERN_INFO "%s: Reconfigured board as %s\n",
+				dev->name, saa7134_boards[dev->board].name);
+		} else {
+			printk(KERN_WARNING "%s: Unexpected tuner type info: %x in eeprom\n",
+				dev->name, dev->eedata[0x41]);
+			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;
+	}
+	case SAA7134_BOARD_BEHOLD_H6:
+	{
+		u8 data[] = { 0x09, 0x9f, 0x86, 0x11};
+		struct i2c_msg msg = {.addr = 0x61, .flags = 0, .buf = data,
+							.len = sizeof(data)};
+
+		/* The tuner TUNER_PHILIPS_FMD1216MEX_MK3 after hardware    */
+		/* start has disabled IF and enabled DVB-T. When saa7134    */
+		/* scan I2C devices it not detect IF tda9887 and can`t      */
+		/* watch TV without software reboot. For solve this problem */
+		/* switch the tuner to analog TV mode manually.             */
+		if (i2c_transfer(&dev->i2c_adap, &msg, 1) != 1)
+				printk(KERN_WARNING
+				      "%s: Unable to enable IF of the tuner.\n",
+				       dev->name);
+		break;
+	}
+	case SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG:
+		saa_writel(SAA7134_GPIO_GPMODE0 >> 2, 0x4000);
+		saa_writel(SAA7134_GPIO_GPSTATUS0 >> 2, 0x4000);
+
+		saa7134_set_gpio(dev, 27, 0);
+		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->v4l2_dev,
+				&dev->i2c_adap, "tuner",
+				dev->radio_addr, NULL);
+		if (has_demod)
+			v4l2_i2c_new_subdev(&dev->v4l2_dev,
+				&dev->i2c_adap, "tuner",
+				0, 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_subdev(&dev->v4l2_dev,
+				&dev->i2c_adap, "tuner",
+				0, v4l2_i2c_tuner_addrs(type));
+		} else {
+			v4l2_i2c_new_subdev(&dev->v4l2_dev,
+				&dev->i2c_adap, "tuner",
+				dev->tuner_addr, NULL);
+		}
+	}
+
+	saa7134_tuner_setup(dev);
+
+	switch (dev->board) {
+	case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM:
+	case SAA7134_BOARD_AVERMEDIA_CARDBUS_501:
+	{
+		struct v4l2_priv_tun_config tea5767_cfg;
+		struct tea5767_ctrl ctl;
+
+		dev->i2c_client.addr = 0xC0;
+		/* set TEA5767(analog FM) defines */
+		memset(&ctl, 0, sizeof(ctl));
+		ctl.xtal_freq = TEA5767_HIGH_LO_13MHz;
+		tea5767_cfg.tuner = TUNER_TEA5767;
+		tea5767_cfg.priv  = &ctl;
+		saa_call_all(dev, tuner, s_config, &tea5767_cfg);
+		break;
+	}
+	} /* switch() */
+
+	return 0;
+}
diff --git a/drivers/media/pci/saa7134/saa7134-core.c b/drivers/media/pci/saa7134/saa7134-core.c
new file mode 100644
index 0000000..f2b37e0
--- /dev/null
+++ b/drivers/media/pci/saa7134/saa7134-core.c
@@ -0,0 +1,1368 @@
+/*
+ *
+ * device driver for philips saa7134 based TV cards
+ * driver core
+ *
+ * (c) 2001-03 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the 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/init.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/kmod.h>
+#include <linux/sound.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/mutex.h>
+#include <linux/dma-mapping.h>
+#include <linux/pm.h>
+
+#include "saa7134-reg.h"
+#include "saa7134.h"
+
+MODULE_DESCRIPTION("v4l2 driver module for saa7130/34 based TV cards");
+MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(SAA7134_VERSION);
+
+
+/* ------------------------------------------------------------------ */
+
+static unsigned int irq_debug;
+module_param(irq_debug, int, 0644);
+MODULE_PARM_DESC(irq_debug,"enable debug messages [IRQ handler]");
+
+static unsigned int core_debug;
+module_param(core_debug, int, 0644);
+MODULE_PARM_DESC(core_debug,"enable debug messages [core]");
+
+static unsigned int gpio_tracking;
+module_param(gpio_tracking, int, 0644);
+MODULE_PARM_DESC(gpio_tracking,"enable debug messages [gpio]");
+
+static unsigned int alsa = 1;
+module_param(alsa, int, 0644);
+MODULE_PARM_DESC(alsa,"enable/disable ALSA DMA sound [dmasound]");
+
+static unsigned int latency = UNSET;
+module_param(latency, int, 0444);
+MODULE_PARM_DESC(latency,"pci latency timer");
+
+int saa7134_no_overlay=-1;
+module_param_named(no_overlay, saa7134_no_overlay, int, 0444);
+MODULE_PARM_DESC(no_overlay,"allow override overlay default (0 disables, 1 enables)"
+		" [some VIA/SIS chipsets are known to have problem with overlay]");
+
+static unsigned int video_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
+static unsigned int vbi_nr[]   = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
+static unsigned int radio_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
+static unsigned int tuner[]    = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
+static unsigned int card[]     = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
+
+
+module_param_array(video_nr, int, NULL, 0444);
+module_param_array(vbi_nr,   int, NULL, 0444);
+module_param_array(radio_nr, int, NULL, 0444);
+module_param_array(tuner,    int, NULL, 0444);
+module_param_array(card,     int, NULL, 0444);
+
+MODULE_PARM_DESC(video_nr, "video device number");
+MODULE_PARM_DESC(vbi_nr,   "vbi device number");
+MODULE_PARM_DESC(radio_nr, "radio device number");
+MODULE_PARM_DESC(tuner,    "tuner type");
+MODULE_PARM_DESC(card,     "card type");
+
+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;
+
+int (*saa7134_dmasound_init)(struct saa7134_dev *dev);
+int (*saa7134_dmasound_exit)(struct saa7134_dev *dev);
+
+#define dprintk(fmt, arg...)	if (core_debug) \
+	printk(KERN_DEBUG "%s/core: " fmt, dev->name , ## arg)
+
+void saa7134_track_gpio(struct saa7134_dev *dev, char *msg)
+{
+	unsigned long mode,status;
+
+	if (!gpio_tracking)
+		return;
+	/* rising SAA7134_GPIO_GPRESCAN reads the status */
+	saa_andorb(SAA7134_GPIO_GPMODE3,SAA7134_GPIO_GPRESCAN,0);
+	saa_andorb(SAA7134_GPIO_GPMODE3,SAA7134_GPIO_GPRESCAN,SAA7134_GPIO_GPRESCAN);
+	mode   = saa_readl(SAA7134_GPIO_GPMODE0   >> 2) & 0xfffffff;
+	status = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2) & 0xfffffff;
+	printk(KERN_DEBUG
+	       "%s: gpio: mode=0x%07lx in=0x%07lx out=0x%07lx [%s]\n",
+	       dev->name, mode, (~mode) & status, mode & status, msg);
+}
+
+void saa7134_set_gpio(struct saa7134_dev *dev, int bit_no, int value)
+{
+	u32 index, bitval;
+
+	index = 1 << bit_no;
+	switch (value) {
+	case 0: /* static value */
+	case 1:	dprintk("setting GPIO%d to static %d\n", bit_no, value);
+		/* turn sync mode off if necessary */
+		if (index & 0x00c00000)
+			saa_andorb(SAA7134_VIDEO_PORT_CTRL6, 0x0f, 0x00);
+		if (value)
+			bitval = index;
+		else
+			bitval = 0;
+		saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, index, index);
+		saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, index, bitval);
+		break;
+	case 3:	/* tristate */
+		dprintk("setting GPIO%d to tristate\n", bit_no);
+		saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, index, 0);
+		break;
+	}
+}
+
+/* ------------------------------------------------------------------ */
+
+
+/* ----------------------------------------------------------- */
+/* delayed request_module                                      */
+
+#if defined(CONFIG_MODULES) && defined(MODULE)
+
+static void request_module_async(struct work_struct *work){
+	struct saa7134_dev* dev = container_of(work, struct saa7134_dev, request_module_wk);
+	if (card_is_empress(dev))
+		request_module("saa7134-empress");
+	if (card_is_dvb(dev))
+		request_module("saa7134-dvb");
+	if (alsa) {
+		if (dev->pci->device != PCI_DEVICE_ID_PHILIPS_SAA7130)
+			request_module("saa7134-alsa");
+	}
+}
+
+static void request_submodules(struct saa7134_dev *dev)
+{
+	INIT_WORK(&dev->request_module_wk, request_module_async);
+	schedule_work(&dev->request_module_wk);
+}
+
+static void flush_request_submodules(struct saa7134_dev *dev)
+{
+	flush_work(&dev->request_module_wk);
+}
+
+#else
+#define request_submodules(dev)
+#define flush_request_submodules(dev)
+#endif /* CONFIG_MODULES */
+
+/* ------------------------------------------------------------------ */
+
+/* nr of (saa7134-)pages for the given buffer size */
+static int saa7134_buffer_pages(int size)
+{
+	size  = PAGE_ALIGN(size);
+	size += PAGE_SIZE; /* for non-page-aligned buffers */
+	size /= 4096;
+	return size;
+}
+
+/* calc max # of buffers from size (must not exceed the 4MB virtual
+ * address space per DMA channel) */
+int saa7134_buffer_count(unsigned int size, unsigned int count)
+{
+	unsigned int maxcount;
+
+	maxcount = 1024 / saa7134_buffer_pages(size);
+	if (count > maxcount)
+		count = maxcount;
+	return count;
+}
+
+int saa7134_buffer_startpage(struct saa7134_buf *buf)
+{
+	return saa7134_buffer_pages(buf->vb.bsize) * buf->vb.i;
+}
+
+unsigned long saa7134_buffer_base(struct saa7134_buf *buf)
+{
+	unsigned long base;
+	struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
+
+	base  = saa7134_buffer_startpage(buf) * 4096;
+	base += dma->sglist[0].offset;
+	return base;
+}
+
+/* ------------------------------------------------------------------ */
+
+int saa7134_pgtable_alloc(struct pci_dev *pci, struct saa7134_pgtable *pt)
+{
+	__le32       *cpu;
+	dma_addr_t   dma_addr = 0;
+
+	cpu = pci_alloc_consistent(pci, SAA7134_PGTABLE_SIZE, &dma_addr);
+	if (NULL == cpu)
+		return -ENOMEM;
+	pt->size = SAA7134_PGTABLE_SIZE;
+	pt->cpu  = cpu;
+	pt->dma  = dma_addr;
+	return 0;
+}
+
+int saa7134_pgtable_build(struct pci_dev *pci, struct saa7134_pgtable *pt,
+			  struct scatterlist *list, unsigned int length,
+			  unsigned int startpage)
+{
+	__le32        *ptr;
+	unsigned int  i,p;
+
+	BUG_ON(NULL == pt || NULL == pt->cpu);
+
+	ptr = pt->cpu + startpage;
+	for (i = 0; i < length; i++, list++)
+		for (p = 0; p * 4096 < list->length; p++, ptr++)
+			*ptr = cpu_to_le32(sg_dma_address(list) - list->offset);
+	return 0;
+}
+
+void saa7134_pgtable_free(struct pci_dev *pci, struct saa7134_pgtable *pt)
+{
+	if (NULL == pt->cpu)
+		return;
+	pci_free_consistent(pci, pt->size, pt->cpu, pt->dma);
+	pt->cpu = NULL;
+}
+
+/* ------------------------------------------------------------------ */
+
+void saa7134_dma_free(struct videobuf_queue *q,struct saa7134_buf *buf)
+{
+	struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
+	BUG_ON(in_interrupt());
+
+	videobuf_waiton(q, &buf->vb, 0, 0);
+	videobuf_dma_unmap(q->dev, dma);
+	videobuf_dma_free(dma);
+	buf->vb.state = VIDEOBUF_NEEDS_INIT;
+}
+
+/* ------------------------------------------------------------------ */
+
+int saa7134_buffer_queue(struct saa7134_dev *dev,
+			 struct saa7134_dmaqueue *q,
+			 struct saa7134_buf *buf)
+{
+	struct saa7134_buf *next = NULL;
+
+	assert_spin_locked(&dev->slock);
+	dprintk("buffer_queue %p\n",buf);
+	if (NULL == q->curr) {
+		if (!q->need_two) {
+			q->curr = buf;
+			buf->activate(dev,buf,NULL);
+		} else if (list_empty(&q->queue)) {
+			list_add_tail(&buf->vb.queue,&q->queue);
+			buf->vb.state = VIDEOBUF_QUEUED;
+		} else {
+			next = list_entry(q->queue.next,struct saa7134_buf,
+					  vb.queue);
+			q->curr = buf;
+			buf->activate(dev,buf,next);
+		}
+	} else {
+		list_add_tail(&buf->vb.queue,&q->queue);
+		buf->vb.state = VIDEOBUF_QUEUED;
+	}
+	return 0;
+}
+
+void saa7134_buffer_finish(struct saa7134_dev *dev,
+			   struct saa7134_dmaqueue *q,
+			   unsigned int state)
+{
+	assert_spin_locked(&dev->slock);
+	dprintk("buffer_finish %p\n",q->curr);
+
+	/* finish current buffer */
+	q->curr->vb.state = state;
+	do_gettimeofday(&q->curr->vb.ts);
+	wake_up(&q->curr->vb.done);
+	q->curr = NULL;
+}
+
+void saa7134_buffer_next(struct saa7134_dev *dev,
+			 struct saa7134_dmaqueue *q)
+{
+	struct saa7134_buf *buf,*next = NULL;
+
+	assert_spin_locked(&dev->slock);
+	BUG_ON(NULL != q->curr);
+
+	if (!list_empty(&q->queue)) {
+		/* activate next one from queue */
+		buf = list_entry(q->queue.next,struct saa7134_buf,vb.queue);
+		dprintk("buffer_next %p [prev=%p/next=%p]\n",
+			buf,q->queue.prev,q->queue.next);
+		list_del(&buf->vb.queue);
+		if (!list_empty(&q->queue))
+			next = list_entry(q->queue.next,struct saa7134_buf,
+					  vb.queue);
+		q->curr = buf;
+		buf->activate(dev,buf,next);
+		dprintk("buffer_next #2 prev=%p/next=%p\n",
+			q->queue.prev,q->queue.next);
+	} else {
+		/* nothing to do -- just stop DMA */
+		dprintk("buffer_next %p\n",NULL);
+		saa7134_set_dmabits(dev);
+		del_timer(&q->timeout);
+
+		if (card_has_mpeg(dev))
+			if (dev->ts_started)
+				saa7134_ts_stop(dev);
+	}
+}
+
+void saa7134_buffer_timeout(unsigned long data)
+{
+	struct saa7134_dmaqueue *q = (struct saa7134_dmaqueue*)data;
+	struct saa7134_dev *dev = q->dev;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->slock,flags);
+
+	/* try to reset the hardware (SWRST) */
+	saa_writeb(SAA7134_REGION_ENABLE, 0x00);
+	saa_writeb(SAA7134_REGION_ENABLE, 0x80);
+	saa_writeb(SAA7134_REGION_ENABLE, 0x00);
+
+	/* flag current buffer as failed,
+	   try to start over with the next one. */
+	if (q->curr) {
+		dprintk("timeout on %p\n",q->curr);
+		saa7134_buffer_finish(dev,q,VIDEOBUF_ERROR);
+	}
+	saa7134_buffer_next(dev,q);
+	spin_unlock_irqrestore(&dev->slock,flags);
+}
+
+/* ------------------------------------------------------------------ */
+
+int saa7134_set_dmabits(struct saa7134_dev *dev)
+{
+	u32 split, task=0, ctrl=0, irq=0;
+	enum v4l2_field cap = V4L2_FIELD_ANY;
+	enum v4l2_field ov  = V4L2_FIELD_ANY;
+
+	assert_spin_locked(&dev->slock);
+
+	if (dev->insuspend)
+		return 0;
+
+	/* video capture -- dma 0 + video task A */
+	if (dev->video_q.curr) {
+		task |= 0x01;
+		ctrl |= SAA7134_MAIN_CTRL_TE0;
+		irq  |= SAA7134_IRQ1_INTE_RA0_1 |
+			SAA7134_IRQ1_INTE_RA0_0;
+		cap = dev->video_q.curr->vb.field;
+	}
+
+	/* video capture -- dma 1+2 (planar modes) */
+	if (dev->video_q.curr &&
+	    dev->video_q.curr->fmt->planar) {
+		ctrl |= SAA7134_MAIN_CTRL_TE4 |
+			SAA7134_MAIN_CTRL_TE5;
+	}
+
+	/* screen overlay -- dma 0 + video task B */
+	if (dev->ovenable) {
+		task |= 0x10;
+		ctrl |= SAA7134_MAIN_CTRL_TE1;
+		ov = dev->ovfield;
+	}
+
+	/* vbi capture -- dma 0 + vbi task A+B */
+	if (dev->vbi_q.curr) {
+		task |= 0x22;
+		ctrl |= SAA7134_MAIN_CTRL_TE2 |
+			SAA7134_MAIN_CTRL_TE3;
+		irq  |= SAA7134_IRQ1_INTE_RA0_7 |
+			SAA7134_IRQ1_INTE_RA0_6 |
+			SAA7134_IRQ1_INTE_RA0_5 |
+			SAA7134_IRQ1_INTE_RA0_4;
+	}
+
+	/* audio capture -- dma 3 */
+	if (dev->dmasound.dma_running) {
+		ctrl |= SAA7134_MAIN_CTRL_TE6;
+		irq  |= SAA7134_IRQ1_INTE_RA3_1 |
+			SAA7134_IRQ1_INTE_RA3_0;
+	}
+
+	/* TS capture -- dma 5 */
+	if (dev->ts_q.curr) {
+		ctrl |= SAA7134_MAIN_CTRL_TE5;
+		irq  |= SAA7134_IRQ1_INTE_RA2_1 |
+			SAA7134_IRQ1_INTE_RA2_0;
+	}
+
+	/* set task conditions + field handling */
+	if (V4L2_FIELD_HAS_BOTH(cap) || V4L2_FIELD_HAS_BOTH(ov) || cap == ov) {
+		/* default config -- use full frames */
+		saa_writeb(SAA7134_TASK_CONDITIONS(TASK_A), 0x0d);
+		saa_writeb(SAA7134_TASK_CONDITIONS(TASK_B), 0x0d);
+		saa_writeb(SAA7134_FIELD_HANDLING(TASK_A),  0x02);
+		saa_writeb(SAA7134_FIELD_HANDLING(TASK_B),  0x02);
+		split = 0;
+	} else {
+		/* split fields between tasks */
+		if (V4L2_FIELD_TOP == cap) {
+			/* odd A, even B, repeat */
+			saa_writeb(SAA7134_TASK_CONDITIONS(TASK_A), 0x0d);
+			saa_writeb(SAA7134_TASK_CONDITIONS(TASK_B), 0x0e);
+		} else {
+			/* odd B, even A, repeat */
+			saa_writeb(SAA7134_TASK_CONDITIONS(TASK_A), 0x0e);
+			saa_writeb(SAA7134_TASK_CONDITIONS(TASK_B), 0x0d);
+		}
+		saa_writeb(SAA7134_FIELD_HANDLING(TASK_A),  0x01);
+		saa_writeb(SAA7134_FIELD_HANDLING(TASK_B),  0x01);
+		split = 1;
+	}
+
+	/* irqs */
+	saa_writeb(SAA7134_REGION_ENABLE, task);
+	saa_writel(SAA7134_IRQ1,          irq);
+	saa_andorl(SAA7134_MAIN_CTRL,
+		   SAA7134_MAIN_CTRL_TE0 |
+		   SAA7134_MAIN_CTRL_TE1 |
+		   SAA7134_MAIN_CTRL_TE2 |
+		   SAA7134_MAIN_CTRL_TE3 |
+		   SAA7134_MAIN_CTRL_TE4 |
+		   SAA7134_MAIN_CTRL_TE5 |
+		   SAA7134_MAIN_CTRL_TE6,
+		   ctrl);
+	dprintk("dmabits: task=0x%02x ctrl=0x%02x irq=0x%x split=%s\n",
+		task, ctrl, irq, split ? "no" : "yes");
+
+	return 0;
+}
+
+/* ------------------------------------------------------------------ */
+/* IRQ handler + helpers                                              */
+
+static char *irqbits[] = {
+	"DONE_RA0", "DONE_RA1", "DONE_RA2", "DONE_RA3",
+	"AR", "PE", "PWR_ON", "RDCAP", "INTL", "FIDT", "MMC",
+	"TRIG_ERR", "CONF_ERR", "LOAD_ERR",
+	"GPIO16", "GPIO18", "GPIO22", "GPIO23"
+};
+#define IRQBITS ARRAY_SIZE(irqbits)
+
+static void print_irqstatus(struct saa7134_dev *dev, int loop,
+			    unsigned long report, unsigned long status)
+{
+	unsigned int i;
+
+	printk(KERN_DEBUG "%s/irq[%d,%ld]: r=0x%lx s=0x%02lx",
+	       dev->name,loop,jiffies,report,status);
+	for (i = 0; i < IRQBITS; i++) {
+		if (!(report & (1 << i)))
+			continue;
+		printk(" %s",irqbits[i]);
+	}
+	if (report & SAA7134_IRQ_REPORT_DONE_RA0) {
+		printk(" | RA0=%s,%s,%s,%ld",
+		       (status & 0x40) ? "vbi"  : "video",
+		       (status & 0x20) ? "b"    : "a",
+		       (status & 0x10) ? "odd"  : "even",
+		       (status & 0x0f));
+	}
+	printk("\n");
+}
+
+static irqreturn_t saa7134_irq(int irq, void *dev_id)
+{
+	struct saa7134_dev *dev = (struct saa7134_dev*) dev_id;
+	unsigned long report,status;
+	int loop, handled = 0;
+
+	if (dev->insuspend)
+		goto out;
+
+	for (loop = 0; loop < 10; loop++) {
+		report = saa_readl(SAA7134_IRQ_REPORT);
+		status = saa_readl(SAA7134_IRQ_STATUS);
+
+		/* If dmasound support is active and we get a sound report,
+		 * mask out the report and let the saa7134-alsa module deal
+		 * with it */
+		if ((report & SAA7134_IRQ_REPORT_DONE_RA3) &&
+			(dev->dmasound.priv_data != NULL) )
+		{
+			if (irq_debug > 1)
+				printk(KERN_DEBUG "%s/irq: preserving DMA sound interrupt\n",
+				       dev->name);
+			report &= ~SAA7134_IRQ_REPORT_DONE_RA3;
+		}
+
+		if (0 == report) {
+			if (irq_debug > 1)
+				printk(KERN_DEBUG "%s/irq: no (more) work\n",
+				       dev->name);
+			goto out;
+		}
+
+		handled = 1;
+		saa_writel(SAA7134_IRQ_REPORT,report);
+		if (irq_debug)
+			print_irqstatus(dev,loop,report,status);
+
+
+		if ((report & SAA7134_IRQ_REPORT_RDCAP) ||
+			(report & SAA7134_IRQ_REPORT_INTL))
+				saa7134_irq_video_signalchange(dev);
+
+
+		if ((report & SAA7134_IRQ_REPORT_DONE_RA0) &&
+		    (status & 0x60) == 0)
+			saa7134_irq_video_done(dev,status);
+
+		if ((report & SAA7134_IRQ_REPORT_DONE_RA0) &&
+		    (status & 0x40) == 0x40)
+			saa7134_irq_vbi_done(dev,status);
+
+		if ((report & SAA7134_IRQ_REPORT_DONE_RA2) &&
+		    card_has_mpeg(dev))
+			saa7134_irq_ts_done(dev,status);
+
+		if (report & SAA7134_IRQ_REPORT_GPIO16) {
+			switch (dev->has_remote) {
+				case SAA7134_REMOTE_GPIO:
+					if (!dev->remote)
+						break;
+					if  (dev->remote->mask_keydown & 0x10000) {
+						saa7134_input_irq(dev);
+					}
+					